From 186d55017f2d9abbdbd9ce3b8806b30dc5b887c9 Mon Sep 17 00:00:00 2001 From: Jakub Klena Date: Thu, 16 Oct 2025 02:23:00 +0200 Subject: [PATCH 01/30] Backup senica-RVO2 on 16.10.2025 --- RVO2/addSwitch.py | 36 + RVO2/cloud_topic.py | 76 + RVO2/config | 12 + RVO2/createNode.py | 43 + RVO2/databases/accelerometer_db.js | 3055 ++++++++++++++++ RVO2/databases/modbus_config.js | 114 + RVO2/databases/nodes.table | 28 + .../nodes_original/.nodes_original.table.swp | Bin 0 -> 12288 bytes .../nodes_original/nodes_original.table | 1 + RVO2/databases/notifications.table | 41 + RVO2/databases/pins.table | 14 + RVO2/databases/relays.table | 5 + RVO2/databases/settings.table | 2 + RVO2/databases/status.table | 2 + RVO2/databases/tbdata.nosql | 4 + RVO2/databases/tbdatacloud.nosql | 3 + RVO2/databases/total_energy.js | 38 + RVO2/debug.js | 16 + RVO2/err.txt | 33 + RVO2/flow/cloudmqttconnect.js | 357 ++ RVO2/flow/cmd_manager.js | 3071 ++++++++++++++++ RVO2/flow/code.js | 90 + RVO2/flow/comment.js | 11 + RVO2/flow/count.js | 60 + RVO2/flow/db_connector.js | 286 ++ RVO2/flow/db_init.js | 113 + RVO2/flow/debug.js | 100 + RVO2/flow/designer.json | 3102 +++++++++++++++++ RVO2/flow/dido_controller.js | 1486 ++++++++ RVO2/flow/helper/DataToTbHandler.js | 187 + RVO2/flow/helper/ErrorToServiceHandler.js | 91 + RVO2/flow/helper/db_helper.js | 44 + RVO2/flow/helper/logger.js | 30 + RVO2/flow/helper/md5.js | 5 + RVO2/flow/helper/notification_reporter.js | 121 + RVO2/flow/helper/register.js | 144 + RVO2/flow/helper/serialport_helper.js | 99 + RVO2/flow/helper/suncalc.js | 317 ++ RVO2/flow/helper/utils.js | 161 + RVO2/flow/httprequest.js | 137 + RVO2/flow/httpresponse.js | 76 + RVO2/flow/httproute.js | 326 ++ RVO2/flow/infosender.js | 81 + RVO2/flow/modbus_reader.js | 346 ++ RVO2/flow/monitorconsumption.js | 156 + RVO2/flow/monitordisk.js | 96 + RVO2/flow/monitormemory.js | 87 + RVO2/flow/nodesdb_changecheck.js | 77 + RVO2/flow/show_dbdata.js | 243 ++ RVO2/flow/slack_filter.js | 188 + RVO2/flow/thermometer.js | 99 + RVO2/flow/trigger.js | 79 + RVO2/flow/variables.txt | 0 RVO2/flow/virtualwirein.js | 43 + RVO2/flow/virtualwireout.js | 41 + RVO2/flow/wsmqttpublish.js | 448 +++ RVO2/flow_22_01_25/audit_test_panel.csv | 48 + RVO2/flow_22_01_25/cloudmqttconnect.js | 374 ++ RVO2/flow_22_01_25/cmd_manager.js | 2988 ++++++++++++++++ RVO2/flow_22_01_25/code.js | 90 + RVO2/flow_22_01_25/comment.js | 11 + RVO2/flow_22_01_25/csv_import.js | 175 + RVO2/flow_22_01_25/db_connector.js | 286 ++ RVO2/flow_22_01_25/db_init.js | 106 + RVO2/flow_22_01_25/debug.js | 100 + RVO2/flow_22_01_25/designer.json | 2846 +++++++++++++++ RVO2/flow_22_01_25/dido_controller.js | 1524 ++++++++ RVO2/flow_22_01_25/helper/DataToTbHandler.js | 133 + .../helper/ErrorToServiceHandler.js | 126 + RVO2/flow_22_01_25/helper/db_helper.js | 44 + RVO2/flow_22_01_25/helper/logger.js | 30 + RVO2/flow_22_01_25/helper/md5.js | 5 + .../helper/notification_reporter.js | 131 + RVO2/flow_22_01_25/helper/register.js | 144 + .../flow_22_01_25/helper/serialport_helper.js | 100 + RVO2/flow_22_01_25/helper/suncalc.js | 317 ++ RVO2/flow_22_01_25/helper/utils.js | 124 + RVO2/flow_22_01_25/httprequest.js | 137 + RVO2/flow_22_01_25/httpresponse.js | 76 + RVO2/flow_22_01_25/httproute.js | 326 ++ RVO2/flow_22_01_25/infosender.js | 101 + RVO2/flow_22_01_25/modbus_reader.js | 363 ++ RVO2/flow_22_01_25/monitorconsumption.js | 156 + RVO2/flow_22_01_25/monitordisk.js | 96 + RVO2/flow_22_01_25/monitormemory.js | 87 + RVO2/flow_22_01_25/nodesdb_changecheck.js | 70 + RVO2/flow_22_01_25/notifikacie.csv | 31 + RVO2/flow_22_01_25/show_dbdata.js | 241 ++ RVO2/flow_22_01_25/slack_filter.js | 187 + RVO2/flow_22_01_25/thermometer.js | 98 + RVO2/flow_22_01_25/trigger.js | 79 + RVO2/flow_22_01_25/variables.txt | 0 RVO2/flow_22_01_25/virtualwirein.js | 43 + RVO2/flow_22_01_25/virtualwireout.js | 41 + RVO2/flow_22_01_25/wsmqttpublish.js | 477 +++ RVO2/monitor.txt | 306 ++ RVO2/package-lock.json | 2139 ++++++++++++ RVO2/package.json | 30 + RVO2/release.js | 15 + RVO2/release.js.json | 34 + RVO2/report_data.log | 196 ++ 101 files changed, 30952 insertions(+) create mode 100755 RVO2/addSwitch.py create mode 100755 RVO2/cloud_topic.py create mode 100755 RVO2/config create mode 100755 RVO2/createNode.py create mode 100755 RVO2/databases/accelerometer_db.js create mode 100755 RVO2/databases/modbus_config.js create mode 100755 RVO2/databases/nodes.table create mode 100755 RVO2/databases/nodes_original/.nodes_original.table.swp create mode 100755 RVO2/databases/nodes_original/nodes_original.table create mode 100755 RVO2/databases/notifications.table create mode 100755 RVO2/databases/pins.table create mode 100755 RVO2/databases/relays.table create mode 100755 RVO2/databases/settings.table create mode 100755 RVO2/databases/status.table create mode 100755 RVO2/databases/tbdata.nosql create mode 100755 RVO2/databases/tbdatacloud.nosql create mode 100755 RVO2/databases/total_energy.js create mode 100755 RVO2/debug.js create mode 100755 RVO2/err.txt create mode 100755 RVO2/flow/cloudmqttconnect.js create mode 100755 RVO2/flow/cmd_manager.js create mode 100755 RVO2/flow/code.js create mode 100755 RVO2/flow/comment.js create mode 100755 RVO2/flow/count.js create mode 100755 RVO2/flow/db_connector.js create mode 100755 RVO2/flow/db_init.js create mode 100755 RVO2/flow/debug.js create mode 100755 RVO2/flow/designer.json create mode 100755 RVO2/flow/dido_controller.js create mode 100755 RVO2/flow/helper/DataToTbHandler.js create mode 100755 RVO2/flow/helper/ErrorToServiceHandler.js create mode 100755 RVO2/flow/helper/db_helper.js create mode 100755 RVO2/flow/helper/logger.js create mode 100755 RVO2/flow/helper/md5.js create mode 100755 RVO2/flow/helper/notification_reporter.js create mode 100755 RVO2/flow/helper/register.js create mode 100755 RVO2/flow/helper/serialport_helper.js create mode 100755 RVO2/flow/helper/suncalc.js create mode 100755 RVO2/flow/helper/utils.js create mode 100755 RVO2/flow/httprequest.js create mode 100755 RVO2/flow/httpresponse.js create mode 100755 RVO2/flow/httproute.js create mode 100755 RVO2/flow/infosender.js create mode 100755 RVO2/flow/modbus_reader.js create mode 100755 RVO2/flow/monitorconsumption.js create mode 100755 RVO2/flow/monitordisk.js create mode 100755 RVO2/flow/monitormemory.js create mode 100755 RVO2/flow/nodesdb_changecheck.js create mode 100755 RVO2/flow/show_dbdata.js create mode 100755 RVO2/flow/slack_filter.js create mode 100755 RVO2/flow/thermometer.js create mode 100755 RVO2/flow/trigger.js create mode 100755 RVO2/flow/variables.txt create mode 100755 RVO2/flow/virtualwirein.js create mode 100755 RVO2/flow/virtualwireout.js create mode 100755 RVO2/flow/wsmqttpublish.js create mode 100755 RVO2/flow_22_01_25/audit_test_panel.csv create mode 100755 RVO2/flow_22_01_25/cloudmqttconnect.js create mode 100755 RVO2/flow_22_01_25/cmd_manager.js create mode 100755 RVO2/flow_22_01_25/code.js create mode 100755 RVO2/flow_22_01_25/comment.js create mode 100755 RVO2/flow_22_01_25/csv_import.js create mode 100755 RVO2/flow_22_01_25/db_connector.js create mode 100755 RVO2/flow_22_01_25/db_init.js create mode 100755 RVO2/flow_22_01_25/debug.js create mode 100755 RVO2/flow_22_01_25/designer.json create mode 100755 RVO2/flow_22_01_25/dido_controller.js create mode 100755 RVO2/flow_22_01_25/helper/DataToTbHandler.js create mode 100755 RVO2/flow_22_01_25/helper/ErrorToServiceHandler.js create mode 100755 RVO2/flow_22_01_25/helper/db_helper.js create mode 100755 RVO2/flow_22_01_25/helper/logger.js create mode 100755 RVO2/flow_22_01_25/helper/md5.js create mode 100755 RVO2/flow_22_01_25/helper/notification_reporter.js create mode 100755 RVO2/flow_22_01_25/helper/register.js create mode 100755 RVO2/flow_22_01_25/helper/serialport_helper.js create mode 100755 RVO2/flow_22_01_25/helper/suncalc.js create mode 100755 RVO2/flow_22_01_25/helper/utils.js create mode 100755 RVO2/flow_22_01_25/httprequest.js create mode 100755 RVO2/flow_22_01_25/httpresponse.js create mode 100755 RVO2/flow_22_01_25/httproute.js create mode 100755 RVO2/flow_22_01_25/infosender.js create mode 100755 RVO2/flow_22_01_25/modbus_reader.js create mode 100755 RVO2/flow_22_01_25/monitorconsumption.js create mode 100755 RVO2/flow_22_01_25/monitordisk.js create mode 100755 RVO2/flow_22_01_25/monitormemory.js create mode 100755 RVO2/flow_22_01_25/nodesdb_changecheck.js create mode 100755 RVO2/flow_22_01_25/notifikacie.csv create mode 100755 RVO2/flow_22_01_25/show_dbdata.js create mode 100755 RVO2/flow_22_01_25/slack_filter.js create mode 100755 RVO2/flow_22_01_25/thermometer.js create mode 100755 RVO2/flow_22_01_25/trigger.js create mode 100755 RVO2/flow_22_01_25/variables.txt create mode 100755 RVO2/flow_22_01_25/virtualwirein.js create mode 100755 RVO2/flow_22_01_25/virtualwireout.js create mode 100755 RVO2/flow_22_01_25/wsmqttpublish.js create mode 100755 RVO2/monitor.txt create mode 100755 RVO2/package-lock.json create mode 100755 RVO2/package.json create mode 100755 RVO2/release.js create mode 100755 RVO2/release.js.json create mode 100755 RVO2/report_data.log diff --git a/RVO2/addSwitch.py b/RVO2/addSwitch.py new file mode 100755 index 0000000..c35e96b --- /dev/null +++ b/RVO2/addSwitch.py @@ -0,0 +1,36 @@ +import os + +def process_set_file(): + """ + Checks if /root/flowserver exists, reads set.txt, and modifies the second line. + """ + default_folder = "/root/flowserver" if os.path.exists("/root/flowserver") else "/home/unipi/flowserver" + flag = 1 if default_folder == "/root/flowserver" else 0 + + try: + with open("/home/unipi/flowserver/databases/settings.table", "r") as f: + lines = f.readlines() + + if len(lines) >= 2: + lines[0] = lines[0].rstrip('\n') + "|main_switch:boolean\n" + second_line = lines[1].strip() # remove trailing newline + last_pipe_index = second_line.rfind("|") + + if last_pipe_index != -1: + modified_line = second_line[:last_pipe_index + 1] + str(flag) + "|" + second_line[last_pipe_index + 1:] + lines[1] = modified_line + else: + print("Warning: No '|' character found in the second line of set.txt") + + with open("/home/unipi/flowserver/databases/settings.table", "w") as f: + f.writelines(lines) + else: + print("Warning: settings.table has less than two lines.") + + except FileNotFoundError: + print("Error: settings.table not found.") + except Exception as e: + print(e) + +# if __name__ == "__main__": +process_set_file() diff --git a/RVO2/cloud_topic.py b/RVO2/cloud_topic.py new file mode 100755 index 0000000..77c31f1 --- /dev/null +++ b/RVO2/cloud_topic.py @@ -0,0 +1,76 @@ +# import os +# +# def modify_file(file_path): +# """ +# Modifies the given file by: +# 1. Appending "|cloud_topic" to the first line. +# 2. Inserting the text from the third "." to the first "|" on the second line after the last "|" character. +# +# Args: +# file_path (str): The path to the file to be modified. +# """ +# +# with open(file_path, 'r+') as f: +# lines = f.readlines() +# +# # Modify the first line +# lines[0] += "|cloud_topic:string" +# +# # Modify the second line +# second_line = lines[1].strip() # Remove leading/trailing whitespace +# first_pipe_index = second_line.find('|') +# third_dot_index = second_line.find('.', second_line.find('.', second_line.find('.') + 1) + 1) +# text_to_insert = second_line[third_dot_index:first_pipe_index] +# +# last_pipe_index = second_line.rfind('|') +# lines[1] = second_line[:last_pipe_index + 1] + text_to_insert + "|" + second_line[last_pipe_index + 1:] +# +# print(first_pipe_index, third_dot_index, text_to_insert, last_pipe_index) +# # Write the modified lines back to the file +# # f.seek(0) +# # f.writelines(lines) +# # f.truncate() +# +# # Example usage: +# file_path = "settings.table" # Replace with the actual file path +# modify_file(file_path) +# + + +def modify_file(file_path): + """ + Modifies the given file by: + 1. Appending "|cloud_topic" to the first line. + 2. Inserting the text between the third "." and the second "|" on the second line after the last "|" character. + + Args: + file_path (str): The path to the file to be modified. + """ + + with open(file_path, 'r+') as f: + lines = f.readlines() + + first_line = lines[0].strip() + first_line += "|cloud_topic:string\n" + # Modify the first line + lines[0] = first_line + + # Modify the second line + second_line = lines[1].strip() # Remove leading/trailing whitespace + first_pipe_index = second_line.find('|') + second_pipe_index = second_line.find('|', first_pipe_index + 1) + third_dot_index = second_line.find('.', second_line.find('.', second_line.find('.') + 1) + 1) + text_to_insert = "u" + second_line[third_dot_index+1:second_pipe_index] + + last_pipe_index = second_line.rfind('|') + lines[1] = second_line[:last_pipe_index + 1] + text_to_insert + "|" + second_line[last_pipe_index + 1:] + + print(first_pipe_index, third_dot_index, text_to_insert, last_pipe_index) + # Write the modified lines back to the file + f.seek(0) + f.writelines(lines) + f.truncate() + +# Example usage: +file_path = "/home/unipi/flowserver/databases/settings.table" # Replace with the actual file path +modify_file(file_path) diff --git a/RVO2/config b/RVO2/config new file mode 100755 index 0000000..cd0a8a9 --- /dev/null +++ b/RVO2/config @@ -0,0 +1,12 @@ +name : Total.js Flow +default_timezone : Europe/Bratislava + +// Packages settings +package#flow (Object) : { url: '/' } + + +table.relays : line:number|tbname:string|contactor:number|profile:string +table.nodes : node:number|pole_number:string|node_type:string|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|project_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|cloud_topic:string|has_main_switch:boolean|daily_report:boolean|send_changed_node_numbers:boolean +table.pins : pin:string|type:string|line:number +table.notifications : key:string|weight:string|sk:string|en:string diff --git a/RVO2/createNode.py b/RVO2/createNode.py new file mode 100755 index 0000000..a8cea91 --- /dev/null +++ b/RVO2/createNode.py @@ -0,0 +1,43 @@ +print("zaciname") +import re, json + +search_str = '|' +final = [] +counter = 1 +with open("/home/unipi/flowserver/databases/nodes.table", 'r') as file: +# with open("/home/rasta5man/dev/oms/flowserver/databases/nodes.table", 'r') as file: + # Read each line in the file + for line in file: + # Print each line + line = line.strip() + print(line) + if counter != 1: + i = [m.start() for m in re.finditer(re.escape(search_str), line)] + node = line[ i[0] + 1 : i[1] ] + tbname = line[ i[3] + 1 : i[4] ] + final.append({node:tbname}) + counter += 1 +print(json.dumps(final)) +f = open("/home/unipi/flowserver/databases/nodes_original/nodes_original.table", "w") +f.write(json.dumps(final)) +f.close() + + +# +# # ``d`` has to be replaced with a different character +# old_character = "'" +# +# # ``t`` will replace ``d` +# new_character = '"' +# resultant_string = 0; +# with open("/home/unipi/flowserver/databases/nodes_original/nodes_original.table", 'r') as file: +# for line in file: +# resultant_string = re.sub("'", '"', line) +# +# resultant_string = re.sub(" ", "", resultant_string) +# print(resultant_string) +# +# f = open("/home/unipi/flowserver/databases/nodes_original/nodes_original.table", "w") +# f.write(str(resultant_string)) +# f.close() +# diff --git a/RVO2/databases/accelerometer_db.js b/RVO2/databases/accelerometer_db.js new file mode 100755 index 0000000..fdfc7fd --- /dev/null +++ b/RVO2/databases/accelerometer_db.js @@ -0,0 +1,3055 @@ +let naklony = { + "3993": { "label": "1/3A", "naklon": 0 }, + "3989": { "label": "1/3B", "naklon": 15 }, + "3976": { "label": "1/1", "naklon": 0 }, + "4181": { "label": "1/2", "naklon": 0 }, + "4376": { "label": "1/4", "naklon": 15 }, + "3868": { "label": "1/5", "naklon": 15 }, + "3728": { "label": "1/6", "naklon": 15 }, + "3730": { "label": "1/7", "naklon": 0 }, + "4374": { "label": "1/8", "naklon": 0 }, + "3718": { "label": "1/9", "naklon": 15 }, + "4375": { "label": "1/10", "naklon": 15 }, + "4172": { "label": "1/11", "naklon": 15 }, + "4176": { "label": "1/12", "naklon": 15 }, + "3800": { "label": "2/1", "naklon": 5 }, + "3823": { "label": "2/2", "naklon": 5 }, + "3905": { "label": "2/3", "naklon": 5 }, + "3803": { "label": "2/4", "naklon": 5 }, + "3817": { "label": "2/5", "naklon": 5 }, + "3818": { "label": "2/6", "naklon": 5 }, + "3811": { "label": "2/7", "naklon": 5 }, + "3915": { "label": "2/8", "naklon": 5 }, + "3843": { "label": "2/9", "naklon": 10 }, + "3827": { "label": "2/10", "naklon": 10 }, + "4220": { "label": "2/11", "naklon": 10 }, + "3826": { "label": "2/12", "naklon": 10 }, + "3834": { "label": "2/13", "naklon": 10 }, + "3838": { "label": "2/14", "naklon": 10 }, + "2823": { "label": "2/15", "naklon": 10 }, + "3750": { "label": "2/16", "naklon": 10 }, + "3378": { "label": "2/17", "naklon": 0 }, + "3376": { "label": "2/18", "naklon": 0 }, + "3379": { "label": "2/19", "naklon": 0 }, + "3285": { "label": "2/20", "naklon": 0 }, + "3382": { "label": "2/21", "naklon": 0 }, + "3383": { "label": "2/22", "naklon": 0 }, + "3375": { "label": "2/24", "naklon": 0 }, + "3381": { "label": "2/25", "naklon": 0 }, + "3380": { "label": "2/26", "naklon": 0 }, + "3828": { "label": "2/27", "naklon": 10 }, + "3377": { "label": "2/28", "naklon": 0 }, + "3591": { "label": "7/1", "naklon": 0 }, + "3587": { "label": "7/2", "naklon": 0 }, + "3468": { "label": "7/3", "naklon": 0 }, + "3466": { "label": "7/4", "naklon": 0 }, + "3474": { "label": "7/5", "naklon": 0 }, + "3481": { "label": "7/6", "naklon": 0 }, + "3589": { "label": "7/7", "naklon": 0 }, + "3472": { "label": "7/8", "naklon": 0 }, + "3473": { "label": "7/9", "naklon": 0 }, + "3584": { "label": "7/10", "naklon": 0 }, + "3571": { "label": "7/11", "naklon": 0 }, + "3476": { "label": "7/12", "naklon": 0 }, + "3590": { "label": "7/13", "naklon": 0 }, + "3478": { "label": "7/14", "naklon": 0 }, + "3471": { "label": "7/15", "naklon": 0 }, + "3467": { "label": "7/16", "naklon": 0 }, + "3479": { "label": "7/17", "naklon": 0 }, + "3480": { "label": "7/18", "naklon": 0 }, + "3477": { "label": "7/19", "naklon": 0 }, + "3362": { "label": "12/1", "naklon": 0 }, + "3355": { "label": "12/2", "naklon": 0 }, + "3356": { "label": "12/3", "naklon": 0 }, + "3349": { "label": "12/4", "naklon": 0 }, + "3357": { "label": "12/5", "naklon": 0 }, + "3350": { "label": "12/6", "naklon": 0 }, + "3353": { "label": "12/7", "naklon": 0 }, + "3539": { "label": "12/8", "naklon": 0 }, + "3050": { "label": "12/9", "naklon": 0 }, + "3361": { "label": "12/10", "naklon": 0 }, + "3360": { "label": "12/11", "naklon": 0 }, + "3358": { "label": "12/12", "naklon": 0 }, + "3541": { "label": "12/13", "naklon": 0 }, + "3551": { "label": "12/14", "naklon": 0 }, + "3514": { "label": "12/15", "naklon": 0 }, + "3547": { "label": "12/16", "naklon": 0 }, + "3562": { "label": "12/17", "naklon": 0 }, + "3525": { "label": "12/18", "naklon": 0 }, + "3558": { "label": "12/19", "naklon": 0 }, + "3511": { "label": "12/20", "naklon": 0 }, + "3058": { "label": "12/21", "naklon": 0 }, + "3062": { "label": "12/22", "naklon": 0 }, + "3070": { "label": "12/23", "naklon": 0 }, + "3447": { "label": "12/24", "naklon": 0 }, + "3056": { "label": "12/25", "naklon": 0 }, + "3057": { "label": "12/26", "naklon": 0 }, + "3071": { "label": "12/27", "naklon": 0 }, + "3061": { "label": "12/28", "naklon": 0 }, + "3069": { "label": "12/29", "naklon": 0 }, + "3077": { "label": "12/30", "naklon": 0 }, + "3080": { "label": "12/31", "naklon": 0 }, + "3081": { "label": "12/32", "naklon": 0 }, + "3078": { "label": "12/33", "naklon": 0 }, + "4037": { "label": "12/34", "naklon": 0 }, + "3067": { "label": "12/35", "naklon": 0 }, + "3051": { "label": "12/36", "naklon": 0 }, + "2924": { "label": "12/37", "naklon": 0 }, + "3060": { "label": "12/38", "naklon": 0 }, + "3073": { "label": "12/39", "naklon": 0 }, + "3469": { "label": "12/40", "naklon": 0 }, + "2923": { "label": "12/41", "naklon": 0 }, + "2925": { "label": "12/42", "naklon": 0 }, + "3359": { "label": "12/43", "naklon": 0 }, + "3055": { "label": "12/44", "naklon": 0 }, + "2922": { "label": "12/45", "naklon": 0 }, + "3084": { "label": "12/46", "naklon": 0 }, + "3064": { "label": "12/47", "naklon": 0 }, + "3066": { "label": "12/48", "naklon": 0 }, + "3072": { "label": "12/49", "naklon": 0 }, + "3415": { "label": "13/13A", "naklon": 0 }, + "3409": { "label": "13/13B", "naklon": 0 }, + "3399": { "label": "13/13C", "naklon": 0 }, + "3410": { "label": "13/29A", "naklon": 0 }, + "3407": { "label": "13/29B", "naklon": 0 }, + "3405": { "label": "13/34A", "naklon": 0 }, + "3404": { "label": "13/34B", "naklon": 0 }, + "3392": { "label": "13/45A", "naklon": 0 }, + "3386": { "label": "13/45B", "naklon": 0 }, + "3303": { "label": "13/60A", "naklon": 3 }, + "3302": { "label": "13/60B", "naklon": 3 }, + "3319": { "label": "13/70A", "naklon": 6 }, + "3317": { "label": "13/70B", "naklon": 6 }, + "3326": { "label": "13/70C", "naklon": 6 }, + "3351": { "label": "13/73A", "naklon": 6 }, + "3313": { "label": "13/73B", "naklon": 6 }, + "3316": { "label": "13/83A", "naklon": 0 }, + "3320": { "label": "13/83B", "naklon": 0 }, + "3336": { "label": "13/95A", "naklon": 0 }, + "3323": { "label": "13/95B", "naklon": 0 }, + "3339": { "label": "13/98A", "naklon": 0 }, + "3333": { "label": "13/98B", "naklon": 0 }, + "3425": { "label": "13/1", "naklon": 0 }, + "3419": { "label": "13/2", "naklon": 0 }, + "3416": { "label": "13/3", "naklon": 0 }, + "3332": { "label": "13/4", "naklon": 0 }, + "3422": { "label": "13/5", "naklon": 0 }, + "3417": { "label": "13/6", "naklon": 0 }, + "3418": { "label": "13/7", "naklon": 0 }, + "3424": { "label": "13/8", "naklon": 0 }, + "3334": { "label": "13/9", "naklon": 0 }, + "4363": { "label": "13/10", "naklon": 0 }, + "3423": { "label": "13/11", "naklon": 0 }, + "3406": { "label": "13/12", "naklon": 0 }, + "3411": { "label": "13/14", "naklon": 0 }, + "3412": { "label": "13/15", "naklon": 0 }, + "3413": { "label": "13/16", "naklon": 0 }, + "3414": { "label": "13/17", "naklon": 0 }, + "3391": { "label": "13/18", "naklon": 0 }, + "3370": { "label": "13/19", "naklon": 0 }, + "3369": { "label": "13/20", "naklon": 0 }, + "3408": { "label": "13/21", "naklon": 0 }, + "3393": { "label": "13/22", "naklon": 0 }, + "3128": { "label": "13/23", "naklon": 0 }, + "3197": { "label": "13/24", "naklon": 0 }, + "4364": { "label": "13/25", "naklon": 0 }, + "3155": { "label": "13/26", "naklon": 0 }, + "3196": { "label": "13/27", "naklon": 0 }, + "3144": { "label": "13/28", "naklon": 0 }, + "3150": { "label": "13/30", "naklon": 0 }, + "3390": { "label": "13/31", "naklon": 0 }, + "3401": { "label": "13/32", "naklon": 0 }, + "3275": { "label": "13/33", "naklon": 0 }, + "3371": { "label": "13/35", "naklon": 0 }, + "3389": { "label": "13/36", "naklon": 0 }, + "3388": { "label": "13/37", "naklon": 0 }, + "3365": { "label": "13/38", "naklon": 0 }, + "3363": { "label": "13/39", "naklon": 0 }, + "3397": { "label": "13/40", "naklon": 0 }, + "3567": { "label": "13/40/1", "naklon": 0 }, + "3387": { "label": "13/41", "naklon": 0 }, + "3403": { "label": "13/42", "naklon": 0 }, + "3147": { "label": "13/43", "naklon": 0 }, + "3141": { "label": "13/44", "naklon": 0 }, + "3364": { "label": "13/46", "naklon": 0 }, + "3367": { "label": "13/47", "naklon": 0 }, + "3368": { "label": "13/48", "naklon": 0 }, + "3402": { "label": "13/49", "naklon": 0 }, + "3366": { "label": "13/50", "naklon": 0 }, + "3395": { "label": "13/51", "naklon": 0 }, + "3372": { "label": "13/52", "naklon": 0 }, + "3394": { "label": "13/53", "naklon": 0 }, + "3308": { "label": "13/54", "naklon": 0 }, + "3847": { "label": "13/54/1", "naklon": 0 }, + "3312": { "label": "13/55", "naklon": 3 }, + "3309": { "label": "13/56", "naklon": 3 }, + "3311": { "label": "13/57", "naklon": 3 }, + "3310": { "label": "13/58", "naklon": 3 }, + "4365": { "label": "13/59", "naklon": 3 }, + "4093": { "label": "13/60/1", "naklon": 3 }, + "3304": { "label": "13/61", "naklon": 3 }, + "3307": { "label": "13/62", "naklon": 3 }, + "3271": { "label": "13/63", "naklon": 3 }, + "3301": { "label": "13/64", "naklon": 3 }, + "4366": { "label": "13/65", "naklon": 3 }, + "3300": { "label": "13/66", "naklon": 3 }, + "3185": { "label": "13/67", "naklon": 0 }, + "3184": { "label": "13/68", "naklon": 0 }, + "3188": { "label": "13/69", "naklon": 0 }, + "3343": { "label": "13/71", "naklon": 6 }, + "3819": { "label": "13/71/1", "naklon": 6 }, + "3880": { "label": "13/71/2", "naklon": 6 }, + "3348": { "label": "13/72", "naklon": 6 }, + "3344": { "label": "13/74", "naklon": 6 }, + "3346": { "label": "13/75", "naklon": 6 }, + "3597": { "label": "13/75/1", "naklon": 6 }, + "3345": { "label": "13/76", "naklon": 6 }, + "3322": { "label": "13/77", "naklon": 0 }, + "3325": { "label": "13/78", "naklon": 0 }, + "4310": { "label": "13/78/1", "naklon": 0 }, + "3315": { "label": "13/79", "naklon": 0 }, + "3328": { "label": "13/80", "naklon": 0 }, + "3321": { "label": "13/81", "naklon": 0 }, + "3324": { "label": "13/82", "naklon": 0 }, + "3140": { "label": "13/84", "naklon": 0 }, + "3153": { "label": "13/85", "naklon": 0 }, + "3145": { "label": "13/86", "naklon": 0 }, + "3134": { "label": "13/87", "naklon": 0 }, + "3151": { "label": "13/88", "naklon": 0 }, + "3143": { "label": "13/89", "naklon": 0 }, + "3318": { "label": "13/90", "naklon": 0 }, + "3347": { "label": "13/91", "naklon": 0 }, + "3314": { "label": "13/94", "naklon": 0 }, + "3331": { "label": "13/96", "naklon": 0 }, + "3327": { "label": "13/97", "naklon": 0 }, + "3329": { "label": "13/99", "naklon": 0 }, + "3337": { "label": "13/100", "naklon": 0 }, + "3330": { "label": "13/101", "naklon": 0 }, + "3335": { "label": "13/102", "naklon": 0 }, + "3420": { "label": "13/103", "naklon": 0 }, + "3421": { "label": "13/104", "naklon": 0 }, + "4361": { "label": "13/105", "naklon": 0 }, + "4362": { "label": "13/106", "naklon": 0 }, + "3526": { "label": "13/107", "naklon": 0 }, + "4424": { "label": "13/108", "naklon": null }, + "3561": { "label": "13/109", "naklon": null }, + "3527": { "label": "13/110", "naklon": null }, + "3521": { "label": "13/111", "naklon": null }, + "3552": { "label": "13/112", "naklon": null }, + "3544": { "label": "13/113", "naklon": null }, + "3534": { "label": "13/114", "naklon": null }, + "3516": { "label": "13/115", "naklon": null }, + "3513": { "label": "13/116", "naklon": null }, + "3565": { "label": "13/117", "naklon": null }, + "3866": { "label": "13/118", "naklon": null }, + "3136": { "label": "14/1", "naklon": 0 }, + "3137": { "label": "14/2", "naklon": 0 }, + "3135": { "label": "14/3", "naklon": 0 }, + "3149": { "label": "14/4", "naklon": 0 }, + "3142": { "label": "14/5", "naklon": 0 }, + "3342": { "label": "14/6", "naklon": 0 }, + "3340": { "label": "14/7", "naklon": 0 }, + "3152": { "label": "14/8", "naklon": 0 }, + "3886": { "label": "14/9", "naklon": 0 }, + "3341": { "label": "14/10", "naklon": null }, + "3352": { "label": "14/11", "naklon": null }, + "3396": { "label": "15/1", "naklon": 5 }, + "2784": { "label": "15/2", "naklon": 5 }, + "2788": { "label": "15/3", "naklon": 5 }, + "2801": { "label": "15/4", "naklon": 5 }, + "2815": { "label": "15/5", "naklon": 5 }, + "2829": { "label": "15/6", "naklon": 5 }, + "2796": { "label": "15/7", "naklon": 5 }, + "2803": { "label": "15/8", "naklon": 5 }, + "4304": { "label": "15/8/1", "naklon": 5 }, + "4311": { "label": "15/8/2", "naklon": 5 }, + "2821": { "label": "15/9", "naklon": 5 }, + "3400": { "label": "15/10", "naklon": 5 }, + "2799": { "label": "15/11", "naklon": 5 }, + "2804": { "label": "15/12", "naklon": 5 }, + "4303": { "label": "15/12/1", "naklon": 5 }, + "4309": { "label": "15/12/2", "naklon": 5 }, + "2806": { "label": "15/13", "naklon": 5 }, + "2787": { "label": "15/14", "naklon": 5 }, + "2809": { "label": "15/15", "naklon": 5 }, + "2814": { "label": "15/16", "naklon": 0 }, + "3934": { "label": "15/17", "naklon": 0 }, + "3192": { "label": "15/18", "naklon": 0 }, + "2812": { "label": "15/19", "naklon": 0 }, + "4070": { "label": "15/20", "naklon": 0 }, + "2826": { "label": "15/21", "naklon": 0 }, + "2808": { "label": "15/22", "naklon": 3 }, + "2795": { "label": "15/23", "naklon": 3 }, + "2807": { "label": "15/24", "naklon": 3 }, + "2831": { "label": "15/25", "naklon": 0 }, + "2862": { "label": "15/26", "naklon": null }, + "2861": { "label": "15/27", "naklon": 0 }, + "2866": { "label": "15/28", "naklon": 0 }, + "3546": { "label": "15/28/1", "naklon": 0 }, + "4146": { "label": "15/29", "naklon": 0 }, + "3001": { "label": "15/29/1", "naklon": 0 }, + "2835": { "label": "15/30", "naklon": 0 }, + "2874": { "label": "15/31", "naklon": 0 }, + "2852": { "label": "15/32", "naklon": 0 }, + "2851": { "label": "15/33", "naklon": 0 }, + "3560": { "label": "15/33/1", "naklon": 0 }, + "2858": { "label": "15/34", "naklon": 0 }, + "4306": { "label": "15/34/1", "naklon": 0 }, + "2856": { "label": "15/35", "naklon": 0 }, + "2847": { "label": "15/36", "naklon": 0 }, + "3556": { "label": "15/36/1", "naklon": 0 }, + "3950": { "label": "15/37", "naklon": 0 }, + "2848": { "label": "15/38", "naklon": 0 }, + "2863": { "label": "15/39", "naklon": 0 }, + "4313": { "label": "15/39/1", "naklon": 0 }, + "2873": { "label": "15/40", "naklon": 0 }, + "2984": { "label": "15/40/1", "naklon": 0 }, + "2854": { "label": "15/41", "naklon": 0 }, + "2859": { "label": "15/42", "naklon": 0 }, + "2872": { "label": "15/43", "naklon": 0 }, + "2849": { "label": "15/44", "naklon": 0 }, + "2864": { "label": "15/45", "naklon": 0 }, + "3553": { "label": "15/46", "naklon": null }, + "3021": { "label": "15/47", "naklon": null }, + "3008": { "label": "15/47/1", "naklon": null }, + "3017": { "label": "15/48", "naklon": null }, + "3014": { "label": "15/49", "naklon": null }, + "2981": { "label": "15/50", "naklon": null }, + "3020": { "label": "15/51", "naklon": null }, + "3027": { "label": "15/52", "naklon": null }, + "3006": { "label": "15/53", "naklon": null }, + "3012": { "label": "15/54", "naklon": null }, + "2738": { "label": "15/55", "naklon": 0 }, + "2725": { "label": "15/56", "naklon": 0 }, + "3016": { "label": "15/57", "naklon": null }, + "3005": { "label": "15/58", "naklon": null }, + "3009": { "label": "15/58/1", "naklon": null }, + "3010": { "label": "15/59", "naklon": 0 }, + "3538": { "label": "15/59/1", "naklon": 0 }, + "4145": { "label": "15/59/2", "naklon": 0 }, + "2713": { "label": "15/60", "naklon": 0 }, + "2789": { "label": "15/61", "naklon": 0 }, + "2736": { "label": "15/62", "naklon": 0 }, + "2739": { "label": "15/63", "naklon": 0 }, + "4346": { "label": "15/64", "naklon": 0 }, + "2731": { "label": "15/65", "naklon": 0 }, + "2818": { "label": "15/66", "naklon": 0 }, + "3557": { "label": "15/66/1", "naklon": 0 }, + "2822": { "label": "15/67", "naklon": 0 }, + "2833": { "label": "15/68", "naklon": 0 }, + "2834": { "label": "15/69", "naklon": 0 }, + "3097": { "label": "15/70", "naklon": 0 }, + "2824": { "label": "15/71", "naklon": 0 }, + "2828": { "label": "15/72", "naklon": 0 }, + "2600": { "label": "15/73", "naklon": 0 }, + "4314": { "label": "15/73/1", "naklon": 0 }, + "2832": { "label": "15/74", "naklon": 0 }, + "4360": { "label": "15/75", "naklon": 0 }, + "2846": { "label": "15/76", "naklon": 0 }, + "2584": { "label": "15/77", "naklon": 0 }, + "2843": { "label": "15/78", "naklon": 0 }, + "4308": { "label": "15/78/1", "naklon": 0 }, + "4144": { "label": "15/79", "naklon": null }, + "2844": { "label": "15/80", "naklon": 0 }, + "2842": { "label": "15/81", "naklon": 0 }, + "2838": { "label": "15/82", "naklon": 0 }, + "2837": { "label": "15/83", "naklon": null }, + "3555": { "label": "15/83/1", "naklon": null }, + "2839": { "label": "15/84", "naklon": 0 }, + "2830": { "label": "15/85", "naklon": 0 }, + "4066": { "label": "15/86", "naklon": 0 }, + "2836": { "label": "15/87", "naklon": 0 }, + "2911": { "label": "15/88", "naklon": 0 }, + "2825": { "label": "15/89", "naklon": 0 }, + "2811": { "label": "15/90", "naklon": 0 }, + "3740": { "label": "15/94", "naklon": 15 }, + "2734": { "label": "15/95", "naklon": 15 }, + "3105": { "label": "15/96", "naklon": 15 }, + "2732": { "label": "15/97", "naklon": 15 }, + "2727": { "label": "15/98", "naklon": 15 }, + "2735": { "label": "15/99", "naklon": 15 }, + "3926": { "label": "15/100", "naklon": 15 }, + "2918": { "label": "15/101", "naklon": 0 }, + "2705": { "label": "15/102", "naklon": 10 }, + "2708": { "label": "15/103", "naklon": 10 }, + "2721": { "label": "15/104", "naklon": 10 }, + "2719": { "label": "15/105", "naklon": 10 }, + "2919": { "label": "15/106", "naklon": 10 }, + "3101": { "label": "15/107", "naklon": 10 }, + "2853": { "label": "15/108", "naklon": 10 }, + "2715": { "label": "15/109", "naklon": 10 }, + "2712": { "label": "15/110", "naklon": 0 }, + "2711": { "label": "15/111", "naklon": 0 }, + "2709": { "label": "15/112", "naklon": 0 }, + "2710": { "label": "15/113", "naklon": 0 }, + "2907": { "label": "15/114", "naklon": 0 }, + "2906": { "label": "15/115", "naklon": 0 }, + "2908": { "label": "15/116", "naklon": 0 }, + "2901": { "label": "15/117", "naklon": 0 }, + "2913": { "label": "15/118", "naklon": 0 }, + "3656": { "label": "15/119", "naklon": 0 }, + "2781": { "label": "15/120", "naklon": 0 }, + "2802": { "label": "15/121", "naklon": 0 }, + "2791": { "label": "15/122", "naklon": 0 }, + "2783": { "label": "15/123", "naklon": 0 }, + "2794": { "label": "15/124", "naklon": 0 }, + "3139": { "label": "15/125", "naklon": 0 }, + "3229": { "label": "15/126", "naklon": 5 }, + "3239": { "label": "15/127", "naklon": 5 }, + "3230": { "label": "15/128", "naklon": 5 }, + "4016": { "label": "15/129", "naklon": null }, + "3608": { "label": "16/16A", "naklon": 0 }, + "4151": { "label": "16/16B", "naklon": 0 }, + "3710": { "label": "16/1", "naklon": 0 }, + "3726": { "label": "16/2", "naklon": 0 }, + "3743": { "label": "16/3", "naklon": 0 }, + "3724": { "label": "16/4", "naklon": 0 }, + "3712": { "label": "16/5", "naklon": 0 }, + "3739": { "label": "16/6", "naklon": 0 }, + "3742": { "label": "16/7", "naklon": 0 }, + "3731": { "label": "16/8", "naklon": 0 }, + "3727": { "label": "16/9", "naklon": 0 }, + "3729": { "label": "16/10", "naklon": 0 }, + "3736": { "label": "16/11", "naklon": 0 }, + "3713": { "label": "16/12", "naklon": 0 }, + "3715": { "label": "16/13", "naklon": 0 }, + "3733": { "label": "16/14", "naklon": 0 }, + "3732": { "label": "16/15", "naklon": 0 }, + "3634": { "label": "16/17", "naklon": 0 }, + "3610": { "label": "16/18", "naklon": 0 }, + "3626": { "label": "16/19", "naklon": 0 }, + "3618": { "label": "16/20", "naklon": 0 }, + "3619": { "label": "16/21", "naklon": 0 }, + "3628": { "label": "16/22", "naklon": 0 }, + "3615": { "label": "16/23", "naklon": 0 }, + "3609": { "label": "16/24", "naklon": 0 }, + "3606": { "label": "16/25", "naklon": 0 }, + "3624": { "label": "16/26", "naklon": 0 }, + "3627": { "label": "16/27", "naklon": 0 }, + "3607": { "label": "16/28", "naklon": 0 }, + "4370": { "label": "16/29", "naklon": 0 }, + "3692": { "label": "16/30", "naklon": 0 }, + "3614": { "label": "16/31", "naklon": 0 }, + "3623": { "label": "16/32", "naklon": 0 }, + "4373": { "label": "16/33", "naklon": 0 }, + "3620": { "label": "16/34", "naklon": 0 }, + "3685": { "label": "16/35", "naklon": 0 }, + "3616": { "label": "16/36", "naklon": 0 }, + "3686": { "label": "16/37", "naklon": 0 }, + "3688": { "label": "16/38", "naklon": 0 }, + "3684": { "label": "16/39", "naklon": 0 }, + "3825": { "label": "16/40", "naklon": 0 }, + "3865": { "label": "16/41", "naklon": 0 }, + "3824": { "label": "16/42", "naklon": 0 }, + "3871": { "label": "16/43", "naklon": 0 }, + "3801": { "label": "16/44", "naklon": 0 }, + "3862": { "label": "16/45", "naklon": 0 }, + "3876": { "label": "16/46", "naklon": 0 }, + "3861": { "label": "16/47", "naklon": 0 }, + "4215": { "label": "16/48", "naklon": 0 }, + "3605": { "label": "16/49", "naklon": 10 }, + "3603": { "label": "16/50", "naklon": 10 }, + "3592": { "label": "16/51", "naklon": 10 }, + "3598": { "label": "16/52", "naklon": 10 }, + "3594": { "label": "16/53", "naklon": 10 }, + "3593": { "label": "16/54", "naklon": 10 }, + "3630": { "label": "16/55", "naklon": 10 }, + "3763": { "label": "16/56", "naklon": 10 }, + "3746": { "label": "16/57", "naklon": 10 }, + "3699": { "label": "16/58", "naklon": 0 }, + "3698": { "label": "16/59", "naklon": 0 }, + "3709": { "label": "16/60", "naklon": null }, + "3708": { "label": "16/61", "naklon": 0 }, + "3703": { "label": "16/62", "naklon": null }, + "3700": { "label": "16/63", "naklon": 0 }, + "3701": { "label": "16/64", "naklon": null }, + "3704": { "label": "16/65", "naklon": 0 }, + "3707": { "label": "16/66", "naklon": null }, + "3810": { "label": "16/67", "naklon": 0 }, + "4208": { "label": "16/68", "naklon": null }, + "3867": { "label": "16/69", "naklon": 0 }, + "4372": { "label": "16/70", "naklon": null }, + "3881": { "label": "16/71", "naklon": 0 }, + "4204": { "label": "16/72", "naklon": null }, + "3869": { "label": "16/73", "naklon": 0 }, + "4202": { "label": "16/74", "naklon": null }, + "3830": { "label": "16/75", "naklon": 0 }, + "3870": { "label": "16/76", "naklon": null }, + "3964": { "label": "16/77", "naklon": 0 }, + "3849": { "label": "16/78", "naklon": 0 }, + "3694": { "label": "16/79", "naklon": null }, + "3717": { "label": "16/80", "naklon": 0 }, + "3877": { "label": "16/81", "naklon": null }, + "3755": { "label": "16/82", "naklon": 0 }, + "3725": { "label": "16/83", "naklon": null }, + "3716": { "label": "16/84", "naklon": 0 }, + "3696": { "label": "16/85", "naklon": null }, + "3702": { "label": "16/86", "naklon": 0 }, + "3706": { "label": "16/87", "naklon": null }, + "3850": { "label": "16/88", "naklon": 0 }, + "3848": { "label": "16/89", "naklon": null }, + "3737": { "label": "16/90", "naklon": null }, + "3705": { "label": "16/91", "naklon": 0 }, + "3723": { "label": "16/92", "naklon": null }, + "3842": { "label": "16/93", "naklon": 0 }, + "3735": { "label": "16/94", "naklon": null }, + "3719": { "label": "16/95", "naklon": 0 }, + "3697": { "label": "16/96", "naklon": 0 }, + "3711": { "label": "16/97", "naklon": 0 }, + "4107": { "label": "16/98", "naklon": null }, + "4112": { "label": "16/99", "naklon": 5 }, + "4106": { "label": "16/100", "naklon": 5 }, + "4111": { "label": "16/101", "naklon": 5 }, + "4091": { "label": "16/102", "naklon": null }, + "4104": { "label": "16/103", "naklon": 5 }, + "4094": { "label": "16/104", "naklon": null }, + "4089": { "label": "16/105", "naklon": 5 }, + "4095": { "label": "16/106", "naklon": null }, + "4102": { "label": "16/107", "naklon": 5 }, + "4105": { "label": "16/108", "naklon": null }, + "3859": { "label": "16/109", "naklon": null }, + "4090": { "label": "16/110", "naklon": 5 }, + "4110": { "label": "16/111", "naklon": null }, + "4097": { "label": "16/112", "naklon": 5 }, + "4099": { "label": "16/113", "naklon": null }, + "4096": { "label": "16/114", "naklon": null }, + "4101": { "label": "16/115", "naklon": 5 }, + "4109": { "label": "16/116", "naklon": null }, + "4092": { "label": "16/117", "naklon": 5 }, + "3631": { "label": "16/118", "naklon": null }, + "3632": { "label": "16/119", "naklon": 0 }, + "3641": { "label": "16/120", "naklon": null }, + "3638": { "label": "16/121", "naklon": 0 }, + "3637": { "label": "16/122", "naklon": null }, + "4142": { "label": "16/123", "naklon": null }, + "4147": { "label": "16/124", "naklon": 5 }, + "4139": { "label": "16/125", "naklon": 5 }, + "3172": { "label": "20/30A", "naklon": 2 }, + "3164": { "label": "20/30B", "naklon": 2 }, + "3247": { "label": "20/1", "naklon": 10 }, + "3296": { "label": "20/2", "naklon": 10 }, + "3246": { "label": "20/3", "naklon": 10 }, + "3270": { "label": "20/4", "naklon": 10 }, + "3294": { "label": "20/5", "naklon": 10 }, + "3298": { "label": "20/6", "naklon": 10 }, + "3297": { "label": "20/7", "naklon": 10 }, + "3293": { "label": "20/8", "naklon": 10 }, + "3299": { "label": "20/9", "naklon": 10 }, + "3295": { "label": "20/10", "naklon": 10 }, + "3244": { "label": "20/11", "naklon": 10 }, + "3249": { "label": "20/12", "naklon": 10 }, + "3268": { "label": "20/13", "naklon": 10 }, + "3245": { "label": "20/14", "naklon": 10 }, + "3278": { "label": "20/15", "naklon": 10 }, + "3280": { "label": "20/16", "naklon": 10 }, + "3292": { "label": "20/17", "naklon": 10 }, + "3287": { "label": "20/18", "naklon": 10 }, + "3282": { "label": "20/19", "naklon": 10 }, + "3273": { "label": "20/20", "naklon": 0 }, + "3157": { "label": "20/21", "naklon": 0 }, + "3283": { "label": "20/22", "naklon": 0 }, + "3159": { "label": "20/23", "naklon": 0 }, + "3289": { "label": "20/24", "naklon": 0 }, + "3163": { "label": "20/25", "naklon": 0 }, + "3126": { "label": "20/26", "naklon": 0 }, + "3171": { "label": "20/27", "naklon": 0 }, + "3162": { "label": "20/28", "naklon": 0 }, + "3279": { "label": "20/29", "naklon": 10 }, + "3173": { "label": "20/31", "naklon": 0 }, + "3127": { "label": "20/32", "naklon": 0 }, + "3131": { "label": "20/33", "naklon": 0 }, + "3129": { "label": "20/34", "naklon": 0 }, + "3276": { "label": "20/35", "naklon": 2 }, + "3290": { "label": "20/36", "naklon": 2 }, + "3132": { "label": "20/37", "naklon": 0 }, + "3138": { "label": "20/38", "naklon": 0 }, + "3272": { "label": "20/39", "naklon": 0 }, + "3291": { "label": "20/40", "naklon": 0 }, + "3277": { "label": "20/41", "naklon": 10 }, + "3286": { "label": "20/42", "naklon": 10 }, + "3281": { "label": "20/43", "naklon": 10 }, + "3288": { "label": "20/44", "naklon": 10 }, + "3284": { "label": "20/45", "naklon": 10 }, + "3167": { "label": "20/46", "naklon": 10 }, + "3872": { "label": "20/47", "naklon": 0 }, + "3124": { "label": "20/48", "naklon": 0 }, + "3133": { "label": "20/49", "naklon": 0 }, + "3158": { "label": "20/50", "naklon": 0 }, + "3169": { "label": "20/51", "naklon": 0 }, + "3146": { "label": "20/52", "naklon": 0 }, + "3160": { "label": "20/53", "naklon": 0 }, + "3248": { "label": "20/54", "naklon": 0 }, + "3156": { "label": "20/55", "naklon": 0 }, + "3161": { "label": "20/56", "naklon": 0 }, + "3170": { "label": "20/57", "naklon": 0 }, + "3168": { "label": "20/58", "naklon": 0 }, + "3125": { "label": "20/59", "naklon": 0 }, + "3166": { "label": "20/60", "naklon": 0 }, + "3130": { "label": "20/61", "naklon": 0 }, + "3563": { "label": "20/62", "naklon": 0 }, + "3550": { "label": "20/63", "naklon": null }, + "3269": { "label": "20/67", "naklon": 0 }, + "2921": { "label": "21/1", "naklon": 0 }, + "2707": { "label": "21/2", "naklon": 0 }, + "2723": { "label": "21/3", "naklon": 0 }, + "2716": { "label": "21/4", "naklon": 0 }, + "2717": { "label": "21/5", "naklon": 0 }, + "2720": { "label": "21/6", "naklon": 0 }, + "2722": { "label": "21/7", "naklon": 0 }, + "2718": { "label": "21/8", "naklon": 0 }, + "2724": { "label": "21/9", "naklon": 0 }, + "2742": { "label": "21/10", "naklon": 0 }, + "2743": { "label": "21/11", "naklon": 0 }, + "2733": { "label": "21/12", "naklon": 0 }, + "2903": { "label": "21/14", "naklon": 0 }, + "2917": { "label": "21/15", "naklon": 0 }, + "2897": { "label": "21/16", "naklon": 0 }, + "2914": { "label": "21/17", "naklon": 0 }, + "2898": { "label": "21/18", "naklon": 0 }, + "2773": { "label": "21/19", "naklon": 0 }, + "2895": { "label": "21/20", "naklon": 0 }, + "2896": { "label": "21/21", "naklon": 0 }, + "2771": { "label": "21/22", "naklon": 0 }, + "2772": { "label": "21/23", "naklon": 0 }, + "2793": { "label": "21/24", "naklon": 0 }, + "2902": { "label": "21/25", "naklon": 0 }, + "2910": { "label": "21/26", "naklon": 0 }, + "2909": { "label": "21/27", "naklon": 0 }, + "2920": { "label": "21/28", "naklon": 0 }, + "2916": { "label": "21/29", "naklon": 0 }, + "2904": { "label": "21/30", "naklon": 0 }, + "2915": { "label": "21/31", "naklon": 0 }, + "2905": { "label": "21/32", "naklon": 0 }, + "2900": { "label": "21/33", "naklon": 0 }, + "2899": { "label": "21/34", "naklon": 0 }, + "2741": { "label": "21/36", "naklon": 0 }, + "2714": { "label": "21/37", "naklon": 0 }, + "2701": { "label": "21/38", "naklon": 0 }, + "2703": { "label": "21/39", "naklon": 0 }, + "2704": { "label": "21/40", "naklon": 0 }, + "2702": { "label": "21/41", "naklon": 0 }, + "2706": { "label": "21/42", "naklon": 0 }, + "2776": { "label": "21/43", "naklon": 0 }, + "2770": { "label": "21/44", "naklon": 0 }, + "2786": { "label": "21/45", "naklon": 0 }, + "2779": { "label": "21/46", "naklon": 0 }, + "2782": { "label": "21/47", "naklon": 0 }, + "2785": { "label": "21/48", "naklon": 0 }, + "2769": { "label": "21/49", "naklon": 0 }, + "3354": { "label": "21/50", "naklon": 0 }, + "2778": { "label": "21/51", "naklon": 0 }, + "2775": { "label": "21/52", "naklon": 0 }, + "2780": { "label": "21/53", "naklon": 0 }, + "2790": { "label": "21/54", "naklon": 0 }, + "2792": { "label": "21/55", "naklon": 0 }, + "2774": { "label": "21/56", "naklon": 0 }, + "2630": { "label": "22/1", "naklon": 0 }, + "2631": { "label": "22/2", "naklon": 0 }, + "2632": { "label": "22/3", "naklon": 0 }, + "2633": { "label": "22/4", "naklon": 0 }, + "2634": { "label": "22/5", "naklon": 0 }, + "2636": { "label": "22/6", "naklon": 0 }, + "4367": { "label": "22/7", "naklon": 0 }, + "2637": { "label": "22/8", "naklon": 0 }, + "2638": { "label": "22/9", "naklon": 0 }, + "2639": { "label": "22/10", "naklon": 0 }, + "2640": { "label": "22/11", "naklon": 0 }, + "2641": { "label": "22/12", "naklon": 0 }, + "2642": { "label": "22/13", "naklon": 0 }, + "2643": { "label": "22/14", "naklon": 0 }, + "2644": { "label": "22/15", "naklon": 0 }, + "2645": { "label": "22/16", "naklon": 0 }, + "2646": { "label": "22/17", "naklon": 0 }, + "2647": { "label": "22/18", "naklon": 0 }, + "2648": { "label": "22/19", "naklon": 0 }, + "2649": { "label": "22/20", "naklon": 0 }, + "2650": { "label": "22/21", "naklon": 0 }, + "2651": { "label": "22/22", "naklon": 0 }, + "4103": { "label": "22/23", "naklon": 0 }, + "2653": { "label": "22/24", "naklon": 0 }, + "2654": { "label": "22/25", "naklon": 0 }, + "2655": { "label": "22/26", "naklon": 0 }, + "2656": { "label": "22/27", "naklon": 0 }, + "2657": { "label": "22/28", "naklon": 0 }, + "2658": { "label": "22/29", "naklon": 0 }, + "2659": { "label": "22/30", "naklon": 0 }, + "2660": { "label": "22/31", "naklon": 0 }, + "2661": { "label": "22/32", "naklon": 0 }, + "3015": { "label": "22/32/1", "naklon": 0 }, + "2662": { "label": "22/33", "naklon": 0 }, + "2663": { "label": "22/34", "naklon": 0 }, + "2664": { "label": "22/35", "naklon": 0 }, + "2665": { "label": "22/36", "naklon": 0 }, + "2666": { "label": "22/37", "naklon": 0 }, + "2667": { "label": "22/38", "naklon": 0 }, + "2668": { "label": "22/39", "naklon": 0 }, + "2669": { "label": "22/40", "naklon": null }, + "2670": { "label": "22/41", "naklon": null }, + "2671": { "label": "22/42", "naklon": null }, + "3087": { "label": "23/9A", "naklon": 10 }, + "3090": { "label": "23/9B", "naklon": 10 }, + "3075": { "label": "23/1", "naklon": 0 }, + "3089": { "label": "23/2", "naklon": 0 }, + "3088": { "label": "23/3", "naklon": 0 }, + "3228": { "label": "23/4", "naklon": 10 }, + "2751": { "label": "23/5", "naklon": 10 }, + "3243": { "label": "23/6", "naklon": 10 }, + "4349": { "label": "23/7", "naklon": 10 }, + "3102": { "label": "23/8", "naklon": 10 }, + "3099": { "label": "23/10", "naklon": 10 }, + "3103": { "label": "23/11", "naklon": 10 }, + "3093": { "label": "23/12", "naklon": 10 }, + "3098": { "label": "23/13", "naklon": 10 }, + "3092": { "label": "23/14", "naklon": 10 }, + "3233": { "label": "23/15", "naklon": 0 }, + "3095": { "label": "23/16", "naklon": 0 }, + "4074": { "label": "23/17", "naklon": 0 }, + "2729": { "label": "23/18", "naklon": 0 }, + "3234": { "label": "23/19", "naklon": 0 }, + "3094": { "label": "23/20", "naklon": 0 }, + "2817": { "label": "23/21", "naklon": 0 }, + "3226": { "label": "23/22", "naklon": 0 }, + "3225": { "label": "23/23", "naklon": 0 }, + "3237": { "label": "23/24", "naklon": 0 }, + "4250": { "label": "23/25", "naklon": 0 }, + "3059": { "label": "23/26", "naklon": 10 }, + "3238": { "label": "23/27", "naklon": 10 }, + "3242": { "label": "23/28", "naklon": 10 }, + "3236": { "label": "23/29", "naklon": 10 }, + "3112": { "label": "23/30", "naklon": 10 }, + "3224": { "label": "23/31", "naklon": 0 }, + "4298": { "label": "23/32", "naklon": 10 }, + "4150": { "label": "23/33", "naklon": 10 }, + "3091": { "label": "23/34", "naklon": 10 }, + "3771": { "label": "25/1", "naklon": 5 }, + "3777": { "label": "25/2", "naklon": 5 }, + "3749": { "label": "25/3", "naklon": 5 }, + "3769": { "label": "25/4", "naklon": 5 }, + "3765": { "label": "25/5", "naklon": 5 }, + "3785": { "label": "25/6", "naklon": 5 }, + "3761": { "label": "25/7", "naklon": 5 }, + "3758": { "label": "25/8", "naklon": 5 }, + "3766": { "label": "25/9", "naklon": 5 }, + "3779": { "label": "25/10", "naklon": 5 }, + "3899": { "label": "25/11", "naklon": 10 }, + "3922": { "label": "25/12", "naklon": 10 }, + "3912": { "label": "25/13", "naklon": 10 }, + "3933": { "label": "25/14", "naklon": 10 }, + "3921": { "label": "25/15", "naklon": 10 }, + "4300": { "label": "25/16", "naklon": 10 }, + "3927": { "label": "25/17", "naklon": 10 }, + "3212": { "label": "25/18", "naklon": 10 }, + "3208": { "label": "25/19", "naklon": 10 }, + "3207": { "label": "25/20", "naklon": 10 }, + "4294": { "label": "25/21", "naklon": 10 }, + "3209": { "label": "25/22", "naklon": 10 }, + "3745": { "label": "25/23", "naklon": 10 }, + "3762": { "label": "25/24", "naklon": 10 }, + "3215": { "label": "25/25", "naklon": 10 }, + "3210": { "label": "25/26", "naklon": 10 }, + "3211": { "label": "25/27", "naklon": 10 }, + "3206": { "label": "25/28", "naklon": 10 }, + "3918": { "label": "25/29", "naklon": 5 }, + "3928": { "label": "25/30", "naklon": 5 }, + "3917": { "label": "25/31", "naklon": 5 }, + "4029": { "label": "25/32", "naklon": 0 }, + "4038": { "label": "25/33", "naklon": 0 }, + "4022": { "label": "25/34", "naklon": 0 }, + "3937": { "label": "25/35", "naklon": 0 }, + "3190": { "label": "25/36", "naklon": 0 }, + "3835": { "label": "25/37", "naklon": 0 }, + "3201": { "label": "25/38", "naklon": 0 }, + "3193": { "label": "25/39", "naklon": 0 }, + "3191": { "label": "25/40", "naklon": 0 }, + "3203": { "label": "25/41", "naklon": 0 }, + "4301": { "label": "25/42", "naklon": 0 }, + "3223": { "label": "25/43", "naklon": 0 }, + "3202": { "label": "25/44", "naklon": 0 }, + "3205": { "label": "25/45", "naklon": 0 }, + "3194": { "label": "25/46", "naklon": 0 }, + "3198": { "label": "25/47", "naklon": 0 }, + "3204": { "label": "25/48", "naklon": 0 }, + "3200": { "label": "25/49", "naklon": 0 }, + "3216": { "label": "25/50", "naklon": 0 }, + "3932": { "label": "25/51", "naklon": 5 }, + "3923": { "label": "25/52", "naklon": 5 }, + "3913": { "label": "25/53", "naklon": 5 }, + "3900": { "label": "25/54", "naklon": 5 }, + "4189": { "label": "25/55", "naklon": 10 }, + "4191": { "label": "25/56", "naklon": 10 }, + "3790": { "label": "25/57", "naklon": 10 }, + "4190": { "label": "25/58", "naklon": 10 }, + "4302": { "label": "25/59", "naklon": 0 }, + "4351": { "label": "25/60", "naklon": 0 }, + "4075": { "label": "25/61", "naklon": 0 }, + "4071": { "label": "25/62", "naklon": 0 }, + "3784": { "label": "25/63", "naklon": 0 }, + "4065": { "label": "25/64", "naklon": 0 }, + "4297": { "label": "25/65", "naklon": 0 }, + "4295": { "label": "25/66", "naklon": 0 }, + "4299": { "label": "25/67", "naklon": 0 }, + "3772": { "label": "25/68", "naklon": 0 }, + "3941": { "label": "25/69", "naklon": 0 }, + "3782": { "label": "25/70", "naklon": 0 }, + "4068": { "label": "25/71", "naklon": 0 }, + "4073": { "label": "25/72", "naklon": 0 }, + "3901": { "label": "25/73", "naklon": 5 }, + "4296": { "label": "25/74", "naklon": 5 }, + "3910": { "label": "25/75", "naklon": 5 }, + "4293": { "label": "25/76", "naklon": 5 }, + "3919": { "label": "25/77", "naklon": 5 }, + "3924": { "label": "25/78", "naklon": 5 }, + "3909": { "label": "25/79", "naklon": 5 }, + "3896": { "label": "25/80", "naklon": 5 }, + "3911": { "label": "25/81", "naklon": 5 }, + "2819": { "label": "25/82", "naklon": 15 }, + "3776": { "label": "25/83", "naklon": 15 }, + "3752": { "label": "25/84", "naklon": 15 }, + "4353": { "label": "25/85", "naklon": 15 }, + "3791": { "label": "25/86", "naklon": 0 }, + "3770": { "label": "25/87", "naklon": 0 }, + "3760": { "label": "25/88", "naklon": 0 }, + "3115": { "label": "25/89", "naklon": 0 }, + "3738": { "label": "25/90", "naklon": 0 }, + "3748": { "label": "25/91", "naklon": 0 }, + "3753": { "label": "25/92", "naklon": 0 }, + "3775": { "label": "25/93", "naklon": 0 }, + "3778": { "label": "25/94", "naklon": 5 }, + "4078": { "label": "25/95", "naklon": 5 }, + "4088": { "label": "25/96", "naklon": 5 }, + "3856": { "label": "25/97", "naklon": 5 }, + "4084": { "label": "25/98", "naklon": 5 }, + "4069": { "label": "25/99", "naklon": 5 }, + "4188": { "label": "25/100", "naklon": 5 }, + "4064": { "label": "25/101", "naklon": 5 }, + "3792": { "label": "25/102", "naklon": 5 }, + "3780": { "label": "25/103", "naklon": 5 }, + "4034": { "label": "25/104", "naklon": 5 }, + "4072": { "label": "25/105", "naklon": 5 }, + "3884": { "label": "25/106", "naklon": 5 }, + "3793": { "label": "25/107", "naklon": 5 }, + "3863": { "label": "25/108", "naklon": 5 }, + "3855": { "label": "25/109", "naklon": 5 }, + "3846": { "label": "33/1", "naklon": 0 }, + "3943": { "label": "33/2", "naklon": 0 }, + "3903": { "label": "33/3", "naklon": 0 }, + "3982": { "label": "33/4", "naklon": 0 }, + "3879": { "label": "33/5", "naklon": 0 }, + "3887": { "label": "33/6", "naklon": 0 }, + "3920": { "label": "33/7", "naklon": 5 }, + "3942": { "label": "33/8", "naklon": 5 }, + "3829": { "label": "33/9", "naklon": null }, + "3452": { "label": "34/79A", "naklon": 6 }, + "3460": { "label": "34/79B", "naklon": 6 }, + "3443": { "label": "34/90A", "naklon": 6 }, + "3445": { "label": "34/90B", "naklon": 6 }, + "3457": { "label": "34/90C", "naklon": 6 }, + "3461": { "label": "34/97A", "naklon": 6 }, + "3463": { "label": "34/97B", "naklon": 6 }, + "3426": { "label": "34/98A", "naklon": 6 }, + "3444": { "label": "34/98B", "naklon": 6 }, + "3453": { "label": "34/99A", "naklon": 6 }, + "3455": { "label": "34/99B", "naklon": 6 }, + "4009": { "label": "34/1", "naklon": 0 }, + "3602": { "label": "34/2", "naklon": 0 }, + "3441": { "label": "34/3", "naklon": 0 }, + "3464": { "label": "34/4", "naklon": 0 }, + "3883": { "label": "34/5", "naklon": 0 }, + "4098": { "label": "34/6", "naklon": 0 }, + "4003": { "label": "34/7", "naklon": 0 }, + "4004": { "label": "34/8", "naklon": 0 }, + "3888": { "label": "34/9", "naklon": 0 }, + "3997": { "label": "34/10", "naklon": 0 }, + "4006": { "label": "34/11", "naklon": 0 }, + "4000": { "label": "34/12", "naklon": 0 }, + "4011": { "label": "34/13", "naklon": 0 }, + "3999": { "label": "34/14", "naklon": 0 }, + "3981": { "label": "34/15", "naklon": 0 }, + "3988": { "label": "34/16", "naklon": 0 }, + "3986": { "label": "34/17", "naklon": 0 }, + "3998": { "label": "34/18", "naklon": 0 }, + "3983": { "label": "34/19", "naklon": 0 }, + "4005": { "label": "34/20", "naklon": 0 }, + "4001": { "label": "34/21", "naklon": 0 }, + "4008": { "label": "34/22", "naklon": 0 }, + "4002": { "label": "34/23", "naklon": 0 }, + "3996": { "label": "34/24", "naklon": 0 }, + "4007": { "label": "34/25", "naklon": 0 }, + "4113": { "label": "34/26", "naklon": 15 }, + "3595": { "label": "34/27", "naklon": 5 }, + "3599": { "label": "34/28", "naklon": 5 }, + "3601": { "label": "34/29", "naklon": 5 }, + "4205": { "label": "34/30", "naklon": 0 }, + "3987": { "label": "34/31", "naklon": null }, + "4214": { "label": "34/32", "naklon": 0 }, + "4226": { "label": "34/33", "naklon": 0 }, + "4209": { "label": "34/34", "naklon": 0 }, + "4201": { "label": "34/35", "naklon": 0 }, + "3440": { "label": "34/36", "naklon": 0 }, + "3465": { "label": "34/37", "naklon": 0 }, + "3446": { "label": "34/38", "naklon": 0 }, + "4039": { "label": "34/39", "naklon": 5 }, + "4057": { "label": "34/40", "naklon": 5 }, + "3985": { "label": "34/41", "naklon": 0 }, + "3882": { "label": "34/42", "naklon": 0 }, + "4040": { "label": "34/43", "naklon": 5 }, + "3231": { "label": "34/44", "naklon": 0 }, + "3227": { "label": "34/45", "naklon": 0 }, + "3431": { "label": "34/46", "naklon": 0 }, + "4013": { "label": "34/47", "naklon": 0 }, + "4045": { "label": "34/48", "naklon": 0 }, + "3949": { "label": "34/49", "naklon": 0 }, + "3953": { "label": "34/50", "naklon": 0 }, + "3952": { "label": "34/51", "naklon": 0 }, + "3995": { "label": "34/52", "naklon": 0 }, + "3992": { "label": "34/53", "naklon": 0 }, + "4198": { "label": "34/54", "naklon": 0 }, + "3935": { "label": "34/55", "naklon": 0 }, + "4050": { "label": "34/56", "naklon": 0 }, + "4049": { "label": "34/57", "naklon": 0 }, + "4054": { "label": "34/58", "naklon": 0 }, + "3663": { "label": "34/59", "naklon": 6 }, + "3661": { "label": "34/60", "naklon": 6 }, + "3664": { "label": "34/61", "naklon": 6 }, + "3660": { "label": "34/62", "naklon": 6 }, + "3662": { "label": "34/63", "naklon": 6 }, + "3665": { "label": "34/65", "naklon": 6 }, + "3667": { "label": "34/66", "naklon": 6 }, + "3675": { "label": "34/67", "naklon": 6 }, + "3666": { "label": "34/68", "naklon": 6 }, + "3652": { "label": "34/69", "naklon": 6 }, + "3458": { "label": "34/70", "naklon": 6 }, + "4425": { "label": "34/70/1", "naklon": 6 }, + "3459": { "label": "34/71", "naklon": 6 }, + "3435": { "label": "34/72", "naklon": 6 }, + "3448": { "label": "34/73", "naklon": 6 }, + "3451": { "label": "34/74", "naklon": 6 }, + "3442": { "label": "34/75", "naklon": 6 }, + "3449": { "label": "34/76", "naklon": 6 }, + "3450": { "label": "34/77", "naklon": 6 }, + "3433": { "label": "34/78", "naklon": 6 }, + "3432": { "label": "34/80", "naklon": 12 }, + "3470": { "label": "34/81", "naklon": 12 }, + "3438": { "label": "34/82", "naklon": 12 }, + "3439": { "label": "34/83", "naklon": 12 }, + "4028": { "label": "34/84", "naklon": 5 }, + "3596": { "label": "34/85", "naklon": 5 }, + "4021": { "label": "34/86", "naklon": 5 }, + "3437": { "label": "34/87", "naklon": 12 }, + "3428": { "label": "34/88", "naklon": 12 }, + "3430": { "label": "34/89", "naklon": 12 }, + "3454": { "label": "34/91", "naklon": 6 }, + "3492": { "label": "34/92", "naklon": 6 }, + "3462": { "label": "34/93", "naklon": 6 }, + "3427": { "label": "34/94", "naklon": 6 }, + "3434": { "label": "34/95", "naklon": 6 }, + "3456": { "label": "34/96", "naklon": 6 }, + "4307": { "label": "34/98/1", "naklon": 6 }, + "3968": { "label": "35/1", "naklon": 0 }, + "3969": { "label": "35/2", "naklon": 0 }, + "3947": { "label": "35/3", "naklon": 0 }, + "3979": { "label": "35/4", "naklon": 0 }, + "3959": { "label": "35/5", "naklon": 0 }, + "3948": { "label": "35/6", "naklon": 0 }, + "3961": { "label": "35/7", "naklon": 0 }, + "3956": { "label": "35/8", "naklon": 0 }, + "3604": { "label": "35/9", "naklon": 0 }, + "3944": { "label": "35/10", "naklon": 0 }, + "3960": { "label": "35/11", "naklon": 0 }, + "3958": { "label": "35/12", "naklon": 0 }, + "4036": { "label": "35/13", "naklon": 5 }, + "3893": { "label": "35/18", "naklon": 5 }, + "4108": { "label": "35/19", "naklon": 5 }, + "4017": { "label": "35/20", "naklon": 5 }, + "3963": { "label": "35/21", "naklon": 0 }, + "3658": { "label": "35/22", "naklon": 0 }, + "3975": { "label": "35/23", "naklon": 0 }, + "3980": { "label": "35/24", "naklon": 0 }, + "4012": { "label": "35/25", "naklon": 0 }, + "3655": { "label": "35/26", "naklon": 0 }, + "3962": { "label": "35/27", "naklon": 0 }, + "3945": { "label": "35/28", "naklon": 0 }, + "3569": { "label": "35/29", "naklon": 0 }, + "3429": { "label": "35/30", "naklon": 0 }, + "3657": { "label": "35/31", "naklon": 0 }, + "3646": { "label": "35/32", "naklon": 0 }, + "3622": { "label": "35/33", "naklon": 0 }, + "3612": { "label": "35/34", "naklon": 0 }, + "3955": { "label": "35/35", "naklon": 0 }, + "3878": { "label": "35/37", "naklon": 0 }, + "3965": { "label": "35/38", "naklon": 0 }, + "3970": { "label": "35/39", "naklon": 0 }, + "3611": { "label": "35/40", "naklon": 0 }, + "2635": { "label": "35/41", "naklon": 0 }, + "3978": { "label": "35/42", "naklon": 0 }, + "4213": { "label": "35/43", "naklon": 0 }, + "3984": { "label": "35/44", "naklon": 0 }, + "4218": { "label": "35/45", "naklon": 0 }, + "3973": { "label": "35/46", "naklon": 0 }, + "3974": { "label": "35/47", "naklon": 0 }, + "3759": { "label": "35/48", "naklon": 0 }, + "3844": { "label": "35/49", "naklon": 0 }, + "3804": { "label": "35/50", "naklon": 0 }, + "3831": { "label": "35/51", "naklon": 0 }, + "3643": { "label": "35/52", "naklon": 0 }, + "3966": { "label": "35/53", "naklon": 0 }, + "3971": { "label": "35/54", "naklon": 0 }, + "3650": { "label": "35/55", "naklon": 6 }, + "3651": { "label": "35/56", "naklon": 6 }, + "3669": { "label": "35/57", "naklon": 6 }, + "3648": { "label": "35/58", "naklon": 6 }, + "3645": { "label": "35/59", "naklon": 6 }, + "3659": { "label": "35/60", "naklon": 6 }, + "3647": { "label": "35/61", "naklon": 6 }, + "3644": { "label": "35/62", "naklon": 6 }, + "3671": { "label": "35/63", "naklon": 6 }, + "3682": { "label": "35/64", "naklon": 6 }, + "3672": { "label": "35/65", "naklon": 6 }, + "3683": { "label": "35/66", "naklon": 6 }, + "3673": { "label": "35/67", "naklon": 6 }, + "3674": { "label": "35/68", "naklon": 6 }, + "3679": { "label": "35/69", "naklon": 6 }, + "3649": { "label": "35/70", "naklon": 6 }, + "3687": { "label": "35/71", "naklon": 6 }, + "3677": { "label": "35/72", "naklon": 6 }, + "3690": { "label": "35/73", "naklon": 6 }, + "3691": { "label": "35/74", "naklon": 6 }, + "3676": { "label": "35/75", "naklon": 6 }, + "3680": { "label": "35/76", "naklon": 6 }, + "3668": { "label": "35/77", "naklon": 6 }, + "3681": { "label": "35/78", "naklon": 6 }, + "3670": { "label": "35/79", "naklon": 6 }, + "3689": { "label": "35/80", "naklon": 6 }, + "3678": { "label": "35/81", "naklon": 6 }, + "3693": { "label": "35/82", "naklon": 6 }, + "3654": { "label": "35/83", "naklon": null }, + "4086": { "label": "36/1", "naklon": 0 }, + "4085": { "label": "36/2", "naklon": 0 }, + "4083": { "label": "36/3", "naklon": 0 }, + "4087": { "label": "36/4", "naklon": 0 }, + "4077": { "label": "36/5", "naklon": 0 }, + "4082": { "label": "36/6", "naklon": 0 }, + "4186": { "label": "36/7", "naklon": 0 }, + "4206": { "label": "36/8", "naklon": 0 }, + "4080": { "label": "36/9", "naklon": 0 }, + "4081": { "label": "36/10", "naklon": 0 }, + "4210": { "label": "36/11", "naklon": 0 }, + "4079": { "label": "36/12", "naklon": 0 }, + "4076": { "label": "36/13", "naklon": 0 }, + "3852": { "label": "36/14", "naklon": 0 }, + "2813": { "label": "36/15", "naklon": 0 }, + "4219": { "label": "36/16", "naklon": 0 }, + "3104": { "label": "37/1A", "naklon": 15 }, + "3121": { "label": "37/1B", "naklon": 15 }, + "3113": { "label": "37/2", "naklon": 10 }, + "3118": { "label": "37/3", "naklon": 10 }, + "3111": { "label": "37/4", "naklon": 10 }, + "4020": { "label": "37/5", "naklon": 10 }, + "3119": { "label": "37/6", "naklon": 10 }, + "3110": { "label": "37/7", "naklon": 10 }, + "3108": { "label": "37/8", "naklon": 10 }, + "3107": { "label": "37/12", "naklon": 0 }, + "3199": { "label": "37/13", "naklon": 0 }, + "3120": { "label": "37/14", "naklon": 0 }, + "3122": { "label": "37/15", "naklon": 0 }, + "3908": { "label": "37/16", "naklon": 0 }, + "3114": { "label": "37/17", "naklon": 0 }, + "3105": { "label": "37/18", "naklon": 0 }, + "3116": { "label": "37/19", "naklon": 0 }, + "3106": { "label": "37/20", "naklon": 0 }, + "2887": { "label": "37/21", "naklon": 5 }, + "2888": { "label": "37/22", "naklon": 5 }, + "2877": { "label": "37/23", "naklon": 5 }, + "2891": { "label": "37/24", "naklon": 5 }, + "2886": { "label": "37/25", "naklon": 5 }, + "2892": { "label": "37/26", "naklon": 5 }, + "2882": { "label": "37/27", "naklon": 5 }, + "2883": { "label": "37/28", "naklon": 5 }, + "2876": { "label": "37/29", "naklon": 5 }, + "3109": { "label": "37/30", "naklon": 5 }, + "4152": { "label": "37/31", "naklon": 5 }, + "3117": { "label": "37/32", "naklon": 5 }, + "2870": { "label": "37/33", "naklon": 5 }, + "2867": { "label": "37/34", "naklon": 0 }, + "2865": { "label": "37/35", "naklon": 0 }, + "3096": { "label": "37/36", "naklon": 0 }, + "2871": { "label": "37/37", "naklon": 0 }, + "2884": { "label": "37/38", "naklon": 0 }, + "2855": { "label": "37/39", "naklon": 0 }, + "2878": { "label": "37/40", "naklon": 0 }, + "2889": { "label": "37/41", "naklon": 0 }, + "2879": { "label": "37/42", "naklon": 0 }, + "2850": { "label": "37/43", "naklon": 0 }, + "2894": { "label": "37/44", "naklon": 0 }, + "2880": { "label": "37/45", "naklon": 0 }, + "2893": { "label": "37/46", "naklon": 0 }, + "2890": { "label": "37/47", "naklon": 0 }, + "4355": { "label": "37/48", "naklon": 0 }, + "2885": { "label": "37/49", "naklon": 0 }, + "2875": { "label": "37/50", "naklon": 0 }, + "3486": { "label": "38/30A", "naklon": 5 }, + "3714": { "label": "38/30B", "naklon": 0 }, + "3483": { "label": "38/32A", "naklon": 5 }, + "3496": { "label": "38/32B", "naklon": 0 }, + "3487": { "label": "38/35A", "naklon": 5 }, + "3498": { "label": "38/35B", "naklon": 5 }, + "3578": { "label": "38/38A", "naklon": 5 }, + "3508": { "label": "38/38B", "naklon": 5 }, + "3787": { "label": "38/59A", "naklon": 5 }, + "3491": { "label": "38/59B", "naklon": 5 }, + "3568": { "label": "38/1", "naklon": null }, + "3502": { "label": "38/2", "naklon": 0 }, + "3836": { "label": "38/3", "naklon": 0 }, + "3588": { "label": "38/4", "naklon": 0 }, + "3493": { "label": "38/5", "naklon": 0 }, + "3580": { "label": "38/6", "naklon": 0 }, + "3572": { "label": "38/7", "naklon": 0 }, + "3506": { "label": "38/8", "naklon": 0 }, + "3503": { "label": "38/9", "naklon": 0 }, + "3579": { "label": "38/10", "naklon": 0 }, + "3586": { "label": "38/11", "naklon": 0 }, + "3495": { "label": "38/12", "naklon": 5 }, + "3492": { "label": "38/13", "naklon": 5 }, + "3532": { "label": "38/14", "naklon": 5 }, + "3574": { "label": "38/15", "naklon": 5 }, + "4140": { "label": "38/16", "naklon": 5 }, + "3795": { "label": "38/17", "naklon": 5 }, + "3788": { "label": "38/18", "naklon": 5 }, + "3796": { "label": "38/19", "naklon": 5 }, + "3797": { "label": "38/20", "naklon": 5 }, + "3798": { "label": "38/21", "naklon": 5 }, + "3786": { "label": "38/22", "naklon": 5 }, + "4067": { "label": "38/23", "naklon": 5 }, + "3773": { "label": "38/24", "naklon": 5 }, + "3774": { "label": "38/25", "naklon": 5 }, + "3789": { "label": "38/26", "naklon": 5 }, + "3520": { "label": "38/27", "naklon": null }, + "3577": { "label": "38/29", "naklon": 5 }, + "3530": { "label": "38/31", "naklon": null }, + "3488": { "label": "38/33", "naklon": 5 }, + "3505": { "label": "38/34", "naklon": 5 }, + "3497": { "label": "38/36", "naklon": 5 }, + "3490": { "label": "38/37", "naklon": 5 }, + "3585": { "label": "38/39", "naklon": 5 }, + "3582": { "label": "38/40", "naklon": 5 }, + "3507": { "label": "38/41", "naklon": 5 }, + "3484": { "label": "38/42", "naklon": 5 }, + "3501": { "label": "38/43", "naklon": 5 }, + "3581": { "label": "38/44", "naklon": 5 }, + "4192": { "label": "38/45", "naklon": 5 }, + "3576": { "label": "38/46", "naklon": 5 }, + "3489": { "label": "38/47", "naklon": 5 }, + "3573": { "label": "38/48", "naklon": 5 }, + "3504": { "label": "38/49", "naklon": 5 }, + "3794": { "label": "38/50", "naklon": 5 }, + "3485": { "label": "38/51", "naklon": 5 }, + "3482": { "label": "38/52", "naklon": 5 }, + "3575": { "label": "38/53", "naklon": 5 }, + "3499": { "label": "38/54", "naklon": 5 }, + "3494": { "label": "38/55", "naklon": 5 }, + "3583": { "label": "38/56", "naklon": 5 }, + "3570": { "label": "38/57", "naklon": 5 }, + "3500": { "label": "38/58", "naklon": 0 }, + "3510": { "label": "38/63", "naklon": null }, + "3512": { "label": "38/64", "naklon": null }, + "3535": { "label": "38/67", "naklon": null }, + "3531": { "label": "38/68", "naklon": null }, + "3537": { "label": "38/69", "naklon": null }, + "3522": { "label": "39/1", "naklon": 10 }, + "4018": { "label": "39/2", "naklon": 10 }, + "4019": { "label": "39/3", "naklon": 10 }, + "4154": { "label": "39/4", "naklon": 5 }, + "3907": { "label": "39/5", "naklon": 5 }, + "4148": { "label": "39/6", "naklon": 0 }, + "4153": { "label": "39/7", "naklon": 0 }, + "3938": { "label": "39/8", "naklon": 0 }, + "3802": { "label": "39/9", "naklon": 0 }, + "4015": { "label": "39/10", "naklon": 0 }, + "3929": { "label": "39/11", "naklon": 0 }, + "3946": { "label": "39/12", "naklon": 0 }, + "4014": { "label": "39/13", "naklon": 0 }, + "4155": { "label": "39/14", "naklon": 0 }, + "4149": { "label": "39/15", "naklon": 0 }, + "3642": { "label": "39/16", "naklon": 0 }, + "3636": { "label": "39/17", "naklon": 5 }, + "3991": { "label": "39/18", "naklon": 0 }, + "3994": { "label": "39/19", "naklon": 0 }, + "3990": { "label": "39/20", "naklon": 0 }, + "3967": { "label": "39/21", "naklon": 0 }, + "3977": { "label": "39/22", "naklon": 0 }, + "3757": { "label": "39/23", "naklon": 15 }, + "3633": { "label": "39/24", "naklon": 15 }, + "3744": { "label": "39/25", "naklon": 15 }, + "4023": { "label": "39/26", "naklon": 5 }, + "3720": { "label": "39/27", "naklon": 5 }, + "3734": { "label": "39/28", "naklon": 5 }, + "3741": { "label": "39/29", "naklon": 5 }, + "3721": { "label": "39/30", "naklon": 5 }, + "3845": { "label": "39/31", "naklon": 0 }, + "3840": { "label": "39/32", "naklon": 0 }, + "3837": { "label": "39/33", "naklon": null }, + "3839": { "label": "39/34", "naklon": 0 }, + "3542": { "label": "41/1", "naklon": null }, + "3566": { "label": "41/2", "naklon": null }, + "3548": { "label": "41/3", "naklon": null }, + "3515": { "label": "41/4", "naklon": null }, + "3559": { "label": "41/5", "naklon": null }, + "3509": { "label": "41/6", "naklon": null }, + "3524": { "label": "41/7", "naklon": null }, + "3518": { "label": "41/8", "naklon": null }, + "3182": { "label": "41/9", "naklon": null }, + "3187": { "label": "41/10", "naklon": null }, + "3195": { "label": "41/11", "naklon": 0 }, + "3857": { "label": "41/12", "naklon": 0 }, + "3183": { "label": "41/13", "naklon": 0 }, + "3177": { "label": "41/14", "naklon": 0 }, + "3189": { "label": "41/15", "naklon": 0 }, + "3186": { "label": "41/16", "naklon": 0 }, + "3178": { "label": "42/1", "naklon": 0 }, + "3219": { "label": "42/2", "naklon": 0 }, + "3475": { "label": "42/3", "naklon": 0 }, + "3175": { "label": "42/4", "naklon": 0 }, + "3222": { "label": "42/5", "naklon": 0 }, + "3221": { "label": "42/6", "naklon": 0 }, + "3181": { "label": "42/7", "naklon": 0 }, + "3180": { "label": "42/8", "naklon": 0 }, + "3218": { "label": "42/9", "naklon": 0 }, + "3176": { "label": "42/10", "naklon": 0 }, + "3174": { "label": "42/11", "naklon": 0 }, + "3220": { "label": "42/12", "naklon": 0 }, + "3533": { "label": "42/13", "naklon": null }, + "3543": { "label": "42/14", "naklon": null }, + "3554": { "label": "42/15", "naklon": null }, + "3549": { "label": "42/16", "naklon": null }, + "2857": { "label": "43/1", "naklon": 5 }, + "2752": { "label": "43/2", "naklon": 5 }, + "2753": { "label": "43/3", "naklon": 5 }, + "3024": { "label": "43/4", "naklon": 5 }, + "2754": { "label": "43/5", "naklon": 5 }, + "4423": { "label": "43/6", "naklon": 5 }, + "4368": { "label": "43/7", "naklon": 5 }, + "2978": { "label": "43/8", "naklon": 5 }, + "2868": { "label": "43/9", "naklon": 5 }, + "4377": { "label": "43/10", "naklon": 5 }, + "2757": { "label": "43/11", "naklon": 5 }, + "2970": { "label": "43/12", "naklon": 5 }, + "2758": { "label": "43/13", "naklon": 5 }, + "4378": { "label": "43/14", "naklon": 5 }, + "2759": { "label": "43/15", "naklon": 5 }, + "4342": { "label": "43/16", "naklon": 5 }, + "3026": { "label": "43/17", "naklon": null }, + "2986": { "label": "43/18", "naklon": null }, + "4343": { "label": "43/19", "naklon": null }, + "2760": { "label": "43/20", "naklon": null }, + "4379": { "label": "43/21", "naklon": null }, + "2971": { "label": "43/22", "naklon": null }, + "2761": { "label": "43/23", "naklon": null }, + "2762": { "label": "43/24", "naklon": null }, + "4339": { "label": "43/25", "naklon": null }, + "4380": { "label": "43/26", "naklon": null }, + "2975": { "label": "43/27", "naklon": null }, + "3003": { "label": "43/28", "naklon": null }, + "4338": { "label": "43/29", "naklon": null }, + "3002": { "label": "43/30", "naklon": null }, + "4345": { "label": "43/31", "naklon": null }, + "2979": { "label": "43/32", "naklon": null }, + "2989": { "label": "43/33", "naklon": null }, + "2996": { "label": "43/34", "naklon": null }, + "2972": { "label": "43/35", "naklon": null }, + "2988": { "label": "43/36", "naklon": null }, + "4344": { "label": "43/37", "naklon": null }, + "3022": { "label": "43/38", "naklon": null }, + "4341": { "label": "43/39", "naklon": null }, + "2983": { "label": "43/40", "naklon": null }, + "2995": { "label": "43/41", "naklon": null }, + "2763": { "label": "43/42", "naklon": null }, + "2764": { "label": "43/43", "naklon": null }, + "2765": { "label": "43/44", "naklon": null }, + "2766": { "label": "43/45", "naklon": null }, + "2767": { "label": "43/46", "naklon": null }, + "2768": { "label": "43/47", "naklon": null }, + "3018": { "label": "43/48", "naklon": null }, + "2982": { "label": "43/49", "naklon": null }, + "3019": { "label": "43/50", "naklon": 0 }, + "3013": { "label": "43/51", "naklon": null }, + "3007": { "label": "43/52", "naklon": null }, + "2980": { "label": "43/53", "naklon": null }, + "3011": { "label": "43/54", "naklon": null }, + "2672": { "label": "43/55", "naklon": null }, + "2673": { "label": "43/56", "naklon": null }, + "2674": { "label": "43/57", "naklon": null }, + "2675": { "label": "43/58", "naklon": null }, + "2676": { "label": "43/59", "naklon": null }, + "2677": { "label": "43/60", "naklon": null }, + "2678": { "label": "43/61", "naklon": null }, + "2679": { "label": "43/62", "naklon": null }, + "2680": { "label": "43/63", "naklon": null }, + "2840": { "label": "43/64", "naklon": null }, + "2682": { "label": "43/65", "naklon": null }, + "2683": { "label": "43/66", "naklon": null }, + "2684": { "label": "43/67", "naklon": 0 }, + "2685": { "label": "43/68", "naklon": null }, + "2686": { "label": "43/69", "naklon": null }, + "2687": { "label": "43/70", "naklon": null }, + "2688": { "label": "43/71", "naklon": null }, + "2689": { "label": "43/72", "naklon": null }, + "2690": { "label": "43/73", "naklon": null }, + "2691": { "label": "43/74", "naklon": null }, + "2692": { "label": "43/75", "naklon": null }, + "2693": { "label": "43/76", "naklon": 0 }, + "2694": { "label": "43/77", "naklon": null }, + "2695": { "label": "43/78", "naklon": null }, + "2696": { "label": "43/79", "naklon": 0 }, + "2697": { "label": "43/80", "naklon": null }, + "2698": { "label": "43/81", "naklon": 0 }, + "2699": { "label": "43/82", "naklon": null }, + "2700": { "label": "43/83", "naklon": 0 }, + "2744": { "label": "43/84", "naklon": null }, + "2745": { "label": "43/85", "naklon": 0 }, + "2746": { "label": "43/86", "naklon": null }, + "2747": { "label": "43/87", "naklon": 0 }, + "2748": { "label": "43/88", "naklon": null }, + "2749": { "label": "43/89", "naklon": 0 }, + "2841": { "label": "43/90", "naklon": null }, + "4237": { "label": "45/1", "naklon": 5 }, + "4226": { "label": "45/2", "naklon": 5 }, + "4242": { "label": "45/3", "naklon": 5 }, + "4179": { "label": "45/4", "naklon": 5 }, + "4247": { "label": "45/5", "naklon": 5 }, + "4245": { "label": "45/6", "naklon": 5 }, + "3872": { "label": "45/7", "naklon": 5 }, + "4175": { "label": "45/8", "naklon": 5 }, + "4236": { "label": "45/9", "naklon": 5 }, + "4170": { "label": "45/10", "naklon": 5 }, + "4238": { "label": "45/11", "naklon": 5 }, + "4246": { "label": "45/12", "naklon": 5 }, + "4166": { "label": "45/13", "naklon": 5 }, + "4227": { "label": "45/14", "naklon": 5 }, + "4171": { "label": "45/15", "naklon": 5 }, + "4180": { "label": "45/16", "naklon": 5 }, + "4244": { "label": "45/17", "naklon": 5 }, + "4199": { "label": "45/18", "naklon": 5 }, + "4239": { "label": "45/19", "naklon": 5 }, + "4207": { "label": "45/20", "naklon": 5 }, + "4223": { "label": "45/21", "naklon": 5 }, + "4230": { "label": "45/22", "naklon": 5 }, + "4233": { "label": "45/23", "naklon": 5 }, + "4222": { "label": "45/24", "naklon": 5 }, + "4217": { "label": "45/25", "naklon": 5 }, + "4243": { "label": "45/26", "naklon": 5 }, + "4200": { "label": "45/27", "naklon": 5 }, + "4228": { "label": "45/28", "naklon": 5 }, + "4211": { "label": "45/29", "naklon": 5 }, + "4234": { "label": "45/30", "naklon": 5 }, + "4235": { "label": "45/31", "naklon": 5 }, + "4203": { "label": "45/32", "naklon": 5 }, + "4240": { "label": "45/33", "naklon": 5 }, + "4224": { "label": "45/34", "naklon": 5 }, + "4232": { "label": "45/35", "naklon": 5 }, + "4231": { "label": "45/36", "naklon": 5 }, + "4161": { "label": "45/37", "naklon": 5 }, + "4225": { "label": "45/38", "naklon": 5 }, + "4241": { "label": "45/39", "naklon": 5 }, + "4229": { "label": "45/40", "naklon": 5 }, + "4221": { "label": "45/41", "naklon": 5 }, + "4212": { "label": "45/42", "naklon": 5 }, + "4216": { "label": "45/43", "naklon": 5 }, + "3864": { "label": "45/44", "naklon": null }, + "3806": { "label": "46/1", "naklon": 5 }, + "3813": { "label": "46/2", "naklon": 5 }, + "3815": { "label": "46/3", "naklon": 5 }, + "3807": { "label": "46/4", "naklon": 5 }, + "3895": { "label": "46/5", "naklon": 5 }, + "3809": { "label": "46/6", "naklon": 5 }, + "3820": { "label": "46/7", "naklon": 5 }, + "3805": { "label": "46/8", "naklon": 5 }, + "3894": { "label": "46/9", "naklon": 0 }, + "4055": { "label": "46/10", "naklon": 0 }, + "3812": { "label": "46/11", "naklon": 5 }, + "3822": { "label": "46/12", "naklon": 5 }, + "3821": { "label": "46/13", "naklon": 5 }, + "3808": { "label": "46/14", "naklon": 5 }, + "3799": { "label": "46/15", "naklon": 5 }, + "3816": { "label": "46/16", "naklon": 5 }, + "3751": { "label": "46/17", "naklon": 5 }, + "3814": { "label": "46/18", "naklon": 5 }, + "4044": { "label": "46/19", "naklon": 0 }, + "3931": { "label": "46/20", "naklon": 0 }, + "3902": { "label": "46/21", "naklon": 5 }, + "3916": { "label": "46/22", "naklon": 5 }, + "3892": { "label": "46/23", "naklon": 5 }, + "3914": { "label": "46/24", "naklon": 5 }, + "3898": { "label": "46/25", "naklon": 5 }, + "3897": { "label": "46/26", "naklon": 5 }, + "3885": { "label": "46/27", "naklon": 5 }, + "3906": { "label": "46/28", "naklon": 5 }, + "3930": { "label": "46/29", "naklon": 0 }, + "3936": { "label": "46/30", "naklon": 0 }, + "3860": { "label": "46/31", "naklon": 5 }, + "3841": { "label": "46/32", "naklon": 5 }, + "3873": { "label": "46/33", "naklon": 5 }, + "3854": { "label": "46/34", "naklon": 5 }, + "3939": { "label": "46/35", "naklon": 5 }, + "3858": { "label": "46/36", "naklon": 5 }, + "3940": { "label": "46/37", "naklon": 5 }, + "4035": { "label": "46/38", "naklon": 5 }, + "3373": { "label": "47/1", "naklon": 0 }, + "3374": { "label": "47/2", "naklon": 0 }, + "3384": { "label": "47/3", "naklon": 0 }, + "3385": { "label": "47/4", "naklon": 0 }, + "4051": { "label": "48/1", "naklon": 5 }, + "4041": { "label": "48/2", "naklon": 5 }, + "4056": { "label": "48/3", "naklon": 5 }, + "3875": { "label": "48/4", "naklon": 5 }, + "4061": { "label": "48/5", "naklon": 5 }, + "4047": { "label": "48/6", "naklon": 5 }, + "4060": { "label": "48/7", "naklon": 5 }, + "4059": { "label": "48/8", "naklon": 5 }, + "4058": { "label": "48/9", "naklon": 5 }, + "3635": { "label": "48/10", "naklon": 5 }, + "3640": { "label": "48/11", "naklon": 5 }, + "3747": { "label": "48/12", "naklon": 5 }, + "3629": { "label": "48/13", "naklon": 5 }, + "4048": { "label": "48/14", "naklon": 5 }, + "4063": { "label": "48/15", "naklon": 5 }, + "4062": { "label": "48/16", "naklon": 5 }, + "4043": { "label": "48/17", "naklon": 5 }, + "4052": { "label": "48/18", "naklon": 5 }, + "4042": { "label": "48/19", "naklon": 5 }, + "4053": { "label": "48/20", "naklon": 5 }, + "4167": { "label": "50/15A", "naklon": null }, + "4159": { "label": "50/15B", "naklon": null }, + "4183": { "label": "50/1", "naklon": 0 }, + "4157": { "label": "50/2", "naklon": 0 }, + "4160": { "label": "50/3", "naklon": 0 }, + "4173": { "label": "50/4", "naklon": 0 }, + "4177": { "label": "50/5", "naklon": 0 }, + "4174": { "label": "50/6", "naklon": 0 }, + "4178": { "label": "50/7", "naklon": 0 }, + "4195": { "label": "50/8", "naklon": 0 }, + "4169": { "label": "50/9", "naklon": 0 }, + "4162": { "label": "50/10", "naklon": 0 }, + "4158": { "label": "50/11", "naklon": 0 }, + "4182": { "label": "50/12", "naklon": 0 }, + "4194": { "label": "50/13", "naklon": 0 }, + "4184": { "label": "50/14", "naklon": 0 }, + "4197": { "label": "50/16", "naklon": null }, + "4164": { "label": "50/17", "naklon": null }, + "3306": { "label": "50/18", "naklon": null }, + "4168": { "label": "50/19", "naklon": null }, + "4193": { "label": "50/20", "naklon": null }, + "4187": { "label": "50/21", "naklon": null }, + "4163": { "label": "50/22", "naklon": null }, + "4165": { "label": "50/23", "naklon": null }, + "4185": { "label": "50/24", "naklon": null }, + "3904": { "label": "50/25", "naklon": null }, + "2619": { "label": "53/1", "naklon": 0 }, + "2623": { "label": "53/2", "naklon": 0 }, + "2617": { "label": "53/3", "naklon": 0 }, + "2622": { "label": "53/4", "naklon": 0 }, + "2618": { "label": "53/5", "naklon": 0 }, + "2626": { "label": "53/6", "naklon": 0 }, + "2869": { "label": "53/7", "naklon": 0 }, + "2613": { "label": "53/8", "naklon": 0 }, + "2608": { "label": "53/9", "naklon": 0 }, + "2611": { "label": "53/10", "naklon": 0 }, + "2598": { "label": "53/11", "naklon": 0 }, + "3528": { "label": "53/12", "naklon": 0 }, + "3545": { "label": "53/13", "naklon": 0 }, + "2620": { "label": "53/14", "naklon": 0 }, + "2612": { "label": "53/15", "naklon": 0 }, + "2615": { "label": "53/16", "naklon": 0 }, + "3722": { "label": "53/17", "naklon": 0 }, + "2624": { "label": "53/18", "naklon": 0 }, + "2609": { "label": "53/19", "naklon": 0 }, + "2625": { "label": "53/20", "naklon": 0 }, + "2602": { "label": "53/21", "naklon": 0 }, + "2610": { "label": "53/22", "naklon": 0 }, + "2599": { "label": "53/23", "naklon": 0 }, + "2605": { "label": "53/24", "naklon": 0 }, + "2593": { "label": "53/25", "naklon": 0 }, + "3074": { "label": "53/26", "naklon": 0 }, + "2740": { "label": "53/27", "naklon": 0 }, + "2614": { "label": "53/28", "naklon": 0 }, + "2601": { "label": "53/29", "naklon": 0 }, + "4196": { "label": "53/30", "naklon": 0 }, + "2607": { "label": "53/31", "naklon": 0 }, + "2582": { "label": "53/32", "naklon": 0 }, + "2594": { "label": "53/33", "naklon": 0 }, + "2589": { "label": "53/34", "naklon": 0 }, + "2596": { "label": "53/35", "naklon": 0 }, + "2603": { "label": "53/36", "naklon": 0 }, + "2597": { "label": "53/37", "naklon": 0 }, + "2590": { "label": "53/38", "naklon": 0 }, + "2581": { "label": "53/39", "naklon": 0 }, + "2583": { "label": "53/40", "naklon": 0 }, + "2580": { "label": "53/41", "naklon": 0 }, + "2579": { "label": "53/42", "naklon": 0 }, + "2797": { "label": "53/43", "naklon": 0 }, + "2577": { "label": "53/44", "naklon": 0 }, + "2586": { "label": "53/45", "naklon": 0 }, + "2588": { "label": "53/46", "naklon": 0 }, + "2591": { "label": "53/47", "naklon": 0 }, + "2592": { "label": "53/48", "naklon": 0 }, + "2573": { "label": "53/49", "naklon": 0 }, + "2595": { "label": "53/50", "naklon": 0 }, + "2587": { "label": "53/51", "naklon": 0 }, + "2578": { "label": "53/52", "naklon": 0 }, + "2574": { "label": "53/53", "naklon": 0 }, + "2571": { "label": "53/54", "naklon": 0 }, + "2570": { "label": "53/55", "naklon": 0 }, + "2576": { "label": "53/56", "naklon": 0 }, + "2881": { "label": "53/57", "naklon": 0 }, + "2575": { "label": "53/58", "naklon": 0 }, + "2572": { "label": "53/59", "naklon": 0 }, + "2569": { "label": "53/60", "naklon": 0 }, + "4324": { "label": "55/1", "naklon": 0 }, + "4319": { "label": "55/2", "naklon": 0 }, + "4327": { "label": "55/3", "naklon": 0 }, + "4333": { "label": "55/4", "naklon": 0 }, + "4332": { "label": "55/5", "naklon": 0 }, + "4320": { "label": "55/6", "naklon": 0 }, + "4317": { "label": "55/7", "naklon": 0 }, + "4318": { "label": "55/8", "naklon": 0 }, + "4328": { "label": "55/9", "naklon": 0 }, + "4323": { "label": "55/10", "naklon": 0 }, + "4325": { "label": "55/11", "naklon": 0 }, + "4326": { "label": "55/12", "naklon": 0 }, + "4316": { "label": "55/13", "naklon": 0 }, + "4322": { "label": "55/14", "naklon": 0 }, + "4331": { "label": "55/15", "naklon": 0 }, + "4321": { "label": "55/16", "naklon": 0 }, + "4315": { "label": "55/17", "naklon": 0 }, + "4329": { "label": "55/18", "naklon": 0 }, + "4334": { "label": "55/19", "naklon": 0 }, + "4330": { "label": "55/20", "naklon": 0 } +}; + + +let svetlaSorted = [{ "label": "1/3A", "node": 3993, "naklon": 0 }, +{ "label": "1/3B", "node": 3989, "naklon": 15 }, +{ "label": "1/1", "node": 3976, "naklon": 0 }, +{ "label": "1/2", "node": 4181, "naklon": 0 }, +{ "label": "1/4", "node": 4376, "naklon": 15 }, +{ "label": "1/5", "node": 3868, "naklon": 15 }, +{ "label": "1/6", "node": 3728, "naklon": 15 }, +{ "label": "1/7", "node": 3730, "naklon": 0 }, +{ "label": "1/8", "node": 4374, "naklon": 0 }, +{ "label": "1/9", "node": 3718, "naklon": 15 }, +{ "label": "1/10", "node": 4375, "naklon": 15 }, +{ "label": "1/11", "node": 4172, "naklon": 15 }, +{ "label": "1/12", "node": 4176, "naklon": 15 }, +{ "label": "2/1", "node": 3800, "naklon": 5 }, +{ "label": "2/2", "node": 3823, "naklon": 5 }, +{ "label": "2/3", "node": 3905, "naklon": 5 }, +{ "label": "2/4", "node": 3803, "naklon": 5 }, +{ "label": "2/5", "node": 3817, "naklon": 5 }, +{ "label": "2/6", "node": 3818, "naklon": 5 }, +{ "label": "2/7", "node": 3811, "naklon": 5 }, +{ "label": "2/8", "node": 3915, "naklon": 5 }, +{ "label": "2/9", "node": 3843, "naklon": 10 }, +{ "label": "2/10", "node": 3827, "naklon": 10 }, +{ "label": "2/11", "node": 4220, "naklon": 10 }, +{ "label": "2/12", "node": 3826, "naklon": 10 }, +{ "label": "2/13", "node": 3834, "naklon": 10 }, +{ "label": "2/14", "node": 3838, "naklon": 10 }, +{ "label": "2/15", "node": 2823, "naklon": 10 }, +{ "label": "2/16", "node": 3750, "naklon": 10 }, +{ "label": "2/17", "node": 3378, "naklon": 0 }, +{ "label": "2/18", "node": 3376, "naklon": 0 }, +{ "label": "2/19", "node": 3379, "naklon": 0 }, +{ "label": "2/20", "node": 3285, "naklon": 0 }, +{ "label": "2/21", "node": 3382, "naklon": 0 }, +{ "label": "2/22", "node": 3383, "naklon": 0 }, +{ "label": "2/24", "node": 3375, "naklon": 0 }, +{ "label": "2/25", "node": 3381, "naklon": 0 }, +{ "label": "2/26", "node": 3380, "naklon": 0 }, +{ "label": "2/27", "node": 3828, "naklon": 10 }, +{ "label": "2/28", "node": 3377, "naklon": 0 }, +{ "label": "7/1", "node": 3591, "naklon": 0 }, +{ "label": "7/2", "node": 3587, "naklon": 0 }, +{ "label": "7/3", "node": 3468, "naklon": 0 }, +{ "label": "7/4", "node": 3466, "naklon": 0 }, +{ "label": "7/5", "node": 3474, "naklon": 0 }, +{ "label": "7/6", "node": 3481, "naklon": 0 }, +{ "label": "7/7", "node": 3589, "naklon": 0 }, +{ "label": "7/8", "node": 3472, "naklon": 0 }, +{ "label": "7/9", "node": 3473, "naklon": 0 }, +{ "label": "7/10", "node": 3584, "naklon": 0 }, +{ "label": "7/11", "node": 3571, "naklon": 0 }, +{ "label": "7/12", "node": 3476, "naklon": 0 }, +{ "label": "7/13", "node": 3590, "naklon": 0 }, +{ "label": "7/14", "node": 3478, "naklon": 0 }, +{ "label": "7/15", "node": 3471, "naklon": 0 }, +{ "label": "7/16", "node": 3467, "naklon": 0 }, +{ "label": "7/17", "node": 3479, "naklon": 0 }, +{ "label": "7/18", "node": 3480, "naklon": 0 }, +{ "label": "7/19", "node": 3477, "naklon": 0 }, +{ "label": "12/1", "node": 3362, "naklon": 0 }, +{ "label": "12/2", "node": 3355, "naklon": 0 }, +{ "label": "12/3", "node": 3356, "naklon": 0 }, +{ "label": "12/4", "node": 3349, "naklon": 0 }, +{ "label": "12/5", "node": 3357, "naklon": 0 }, +{ "label": "12/6", "node": 3350, "naklon": 0 }, +{ "label": "12/7", "node": 3353, "naklon": 0 }, +{ "label": "12/8", "node": 3539, "naklon": 0 }, +{ "label": "12/9", "node": 3050, "naklon": 0 }, +{ "label": "12/10", "node": 3361, "naklon": 0 }, +{ "label": "12/11", "node": 3360, "naklon": 0 }, +{ "label": "12/12", "node": 3358, "naklon": 0 }, +{ "label": "12/13", "node": 3541, "naklon": 0 }, +{ "label": "12/14", "node": 3551, "naklon": 0 }, +{ "label": "12/15", "node": 3514, "naklon": 0 }, +{ "label": "12/16", "node": 3547, "naklon": 0 }, +{ "label": "12/17", "node": 3562, "naklon": 0 }, +{ "label": "12/18", "node": 3525, "naklon": 0 }, +{ "label": "12/19", "node": 3558, "naklon": 0 }, +{ "label": "12/20", "node": 3511, "naklon": 0 }, +{ "label": "12/21", "node": 3058, "naklon": 0 }, +{ "label": "12/22", "node": 3062, "naklon": 0 }, +{ "label": "12/23", "node": 3070, "naklon": 0 }, +{ "label": "12/24", "node": 3447, "naklon": 0 }, +{ "label": "12/25", "node": 3056, "naklon": 0 }, +{ "label": "12/26", "node": 3057, "naklon": 0 }, +{ "label": "12/27", "node": 3071, "naklon": 0 }, +{ "label": "12/28", "node": 3061, "naklon": 0 }, +{ "label": "12/29", "node": 3069, "naklon": 0 }, +{ "label": "12/30", "node": 3077, "naklon": 0 }, +{ "label": "12/31", "node": 3080, "naklon": 0 }, +{ "label": "12/32", "node": 3081, "naklon": 0 }, +{ "label": "12/33", "node": 3078, "naklon": 0 }, +{ "label": "12/34", "node": 4037, "naklon": 0 }, +{ "label": "12/35", "node": 3067, "naklon": 0 }, +{ "label": "12/36", "node": 3051, "naklon": 0 }, +{ "label": "12/37", "node": 2924, "naklon": 0 }, +{ "label": "12/38", "node": 3060, "naklon": 0 }, +{ "label": "12/39", "node": 3073, "naklon": 0 }, +{ "label": "12/40", "node": 3469, "naklon": 0 }, +{ "label": "12/41", "node": 2923, "naklon": 0 }, +{ "label": "12/42", "node": 2925, "naklon": 0 }, +{ "label": "12/43", "node": 3359, "naklon": 0 }, +{ "label": "12/44", "node": 3055, "naklon": 0 }, +{ "label": "12/45", "node": 2922, "naklon": 0 }, +{ "label": "12/46", "node": 3084, "naklon": 0 }, +{ "label": "12/47", "node": 3064, "naklon": 0 }, +{ "label": "12/48", "node": 3066, "naklon": 0 }, +{ "label": "12/49", "node": 3072, "naklon": 0 }, +{ "label": "13/13A", "node": 3415, "naklon": 0 }, +{ "label": "13/13B", "node": 3409, "naklon": 0 }, +{ "label": "13/13C", "node": 3399, "naklon": 0 }, +{ "label": "13/29A", "node": 3410, "naklon": 0 }, +{ "label": "13/29B", "node": 3407, "naklon": 0 }, +{ "label": "13/34A", "node": 3405, "naklon": 0 }, +{ "label": "13/34B", "node": 3404, "naklon": 0 }, +{ "label": "13/45A", "node": 3392, "naklon": 0 }, +{ "label": "13/45B", "node": 3386, "naklon": 0 }, +{ "label": "13/60A", "node": 3303, "naklon": 3 }, +{ "label": "13/60B", "node": 3302, "naklon": 3 }, +{ "label": "13/70A", "node": 3319, "naklon": 6 }, +{ "label": "13/70B", "node": 3317, "naklon": 6 }, +{ "label": "13/70C", "node": 3326, "naklon": 6 }, +{ "label": "13/73A", "node": 3351, "naklon": 6 }, +{ "label": "13/73B", "node": 3313, "naklon": 6 }, +{ "label": "13/83A", "node": 3316, "naklon": 0 }, +{ "label": "13/83B", "node": 3320, "naklon": 0 }, +{ "label": "13/95A", "node": 3336, "naklon": 0 }, +{ "label": "13/95B", "node": 3323, "naklon": 0 }, +{ "label": "13/98A", "node": 3339, "naklon": 0 }, +{ "label": "13/98B", "node": 3333, "naklon": 0 }, +{ "label": "13/1", "node": 3425, "naklon": 0 }, +{ "label": "13/2", "node": 3419, "naklon": 0 }, +{ "label": "13/3", "node": 3416, "naklon": 0 }, +{ "label": "13/4", "node": 3332, "naklon": 0 }, +{ "label": "13/5", "node": 3422, "naklon": 0 }, +{ "label": "13/6", "node": 3417, "naklon": 0 }, +{ "label": "13/7", "node": 3418, "naklon": 0 }, +{ "label": "13/8", "node": 3424, "naklon": 0 }, +{ "label": "13/9", "node": 3334, "naklon": 0 }, +{ "label": "13/10", "node": 4363, "naklon": 0 }, +{ "label": "13/11", "node": 3423, "naklon": 0 }, +{ "label": "13/12", "node": 3406, "naklon": 0 }, +{ "label": "13/14", "node": 3411, "naklon": 0 }, +{ "label": "13/15", "node": 3412, "naklon": 0 }, +{ "label": "13/16", "node": 3413, "naklon": 0 }, +{ "label": "13/17", "node": 3414, "naklon": 0 }, +{ "label": "13/18", "node": 3391, "naklon": 0 }, +{ "label": "13/19", "node": 3370, "naklon": 0 }, +{ "label": "13/20", "node": 3369, "naklon": 0 }, +{ "label": "13/21", "node": 3408, "naklon": 0 }, +{ "label": "13/22", "node": 3393, "naklon": 0 }, +{ "label": "13/23", "node": 3128, "naklon": 0 }, +{ "label": "13/24", "node": 3197, "naklon": 0 }, +{ "label": "13/25", "node": 4364, "naklon": 0 }, +{ "label": "13/26", "node": 3155, "naklon": 0 }, +{ "label": "13/27", "node": 3196, "naklon": 0 }, +{ "label": "13/28", "node": 3144, "naklon": 0 }, +{ "label": "13/30", "node": 3150, "naklon": 0 }, +{ "label": "13/31", "node": 3390, "naklon": 0 }, +{ "label": "13/32", "node": 3401, "naklon": 0 }, +{ "label": "13/33", "node": 3275, "naklon": 0 }, +{ "label": "13/35", "node": 3371, "naklon": 0 }, +{ "label": "13/36", "node": 3389, "naklon": 0 }, +{ "label": "13/37", "node": 3388, "naklon": 0 }, +{ "label": "13/38", "node": 3365, "naklon": 0 }, +{ "label": "13/39", "node": 3363, "naklon": 0 }, +{ "label": "13/40", "node": 3397, "naklon": 0 }, +{ "label": "13/40/1", "node": 3567, "naklon": 0 }, +{ "label": "13/41", "node": 3387, "naklon": 0 }, +{ "label": "13/42", "node": 3403, "naklon": 0 }, +{ "label": "13/43", "node": 3147, "naklon": 0 }, +{ "label": "13/44", "node": 3141, "naklon": 0 }, +{ "label": "13/46", "node": 3364, "naklon": 0 }, +{ "label": "13/47", "node": 3367, "naklon": 0 }, +{ "label": "13/48", "node": 3368, "naklon": 0 }, +{ "label": "13/49", "node": 3402, "naklon": 0 }, +{ "label": "13/50", "node": 3366, "naklon": 0 }, +{ "label": "13/51", "node": 3395, "naklon": 0 }, +{ "label": "13/52", "node": 3372, "naklon": 0 }, +{ "label": "13/53", "node": 3394, "naklon": 0 }, +{ "label": "13/54", "node": 3308, "naklon": 0 }, +{ "label": "13/54/1", "node": 3847, "naklon": 0 }, +{ "label": "13/55", "node": 3312, "naklon": 3 }, +{ "label": "13/56", "node": 3309, "naklon": 3 }, +{ "label": "13/57", "node": 3311, "naklon": 3 }, +{ "label": "13/58", "node": 3310, "naklon": 3 }, +{ "label": "13/59", "node": 4365, "naklon": 3 }, +{ "label": "13/60/1", "node": 4093, "naklon": 3 }, +{ "label": "13/61", "node": 3304, "naklon": 3 }, +{ "label": "13/62", "node": 3307, "naklon": 3 }, +{ "label": "13/63", "node": 3271, "naklon": 3 }, +{ "label": "13/64", "node": 3301, "naklon": 3 }, +{ "label": "13/65", "node": 4366, "naklon": 3 }, +{ "label": "13/66", "node": 3300, "naklon": 3 }, +{ "label": "13/67", "node": 3185, "naklon": 0 }, +{ "label": "13/68", "node": 3184, "naklon": 0 }, +{ "label": "13/69", "node": 3188, "naklon": 0 }, +{ "label": "13/71", "node": 3343, "naklon": 6 }, +{ "label": "13/71/1", "node": 3819, "naklon": 6 }, +{ "label": "13/71/2", "node": 3880, "naklon": 6 }, +{ "label": "13/72", "node": 3348, "naklon": 6 }, +{ "label": "13/74", "node": 3344, "naklon": 6 }, +{ "label": "13/75", "node": 3346, "naklon": 6 }, +{ "label": "13/75/1", "node": 3597, "naklon": 6 }, +{ "label": "13/76", "node": 3345, "naklon": 6 }, +{ "label": "13/77", "node": 3322, "naklon": 0 }, +{ "label": "13/78", "node": 3325, "naklon": 0 }, +{ "label": "13/78/1", "node": 4310, "naklon": 0 }, +{ "label": "13/79", "node": 3315, "naklon": 0 }, +{ "label": "13/80", "node": 3328, "naklon": 0 }, +{ "label": "13/81", "node": 3321, "naklon": 0 }, +{ "label": "13/82", "node": 3324, "naklon": 0 }, +{ "label": "13/84", "node": 3140, "naklon": 0 }, +{ "label": "13/85", "node": 3153, "naklon": 0 }, +{ "label": "13/86", "node": 3145, "naklon": 0 }, +{ "label": "13/87", "node": 3134, "naklon": 0 }, +{ "label": "13/88", "node": 3151, "naklon": 0 }, +{ "label": "13/89", "node": 3143, "naklon": 0 }, +{ "label": "13/90", "node": 3318, "naklon": 0 }, +{ "label": "13/91", "node": 3347, "naklon": 0 }, +{ "label": "13/94", "node": 3314, "naklon": 0 }, +{ "label": "13/96", "node": 3331, "naklon": 0 }, +{ "label": "13/97", "node": 3327, "naklon": 0 }, +{ "label": "13/99", "node": 3329, "naklon": 0 }, +{ "label": "13/100", "node": 3337, "naklon": 0 }, +{ "label": "13/101", "node": 3330, "naklon": 0 }, +{ "label": "13/102", "node": 3335, "naklon": 0 }, +{ "label": "13/103", "node": 3420, "naklon": 0 }, +{ "label": "13/104", "node": 3421, "naklon": 0 }, +{ "label": "13/105", "node": 4361, "naklon": 0 }, +{ "label": "13/106", "node": 4362, "naklon": 0 }, +{ "label": "13/107", "node": 3526, "naklon": 0 }, +{ "label": "13/108", "node": 4424, "naklon": null }, +{ "label": "13/109", "node": 3561, "naklon": null }, +{ "label": "13/110", "node": 3527, "naklon": null }, +{ "label": "13/111", "node": 3521, "naklon": null }, +{ "label": "13/112", "node": 3552, "naklon": null }, +{ "label": "13/113", "node": 3544, "naklon": null }, +{ "label": "13/114", "node": 3534, "naklon": null }, +{ "label": "13/115", "node": 3516, "naklon": null }, +{ "label": "13/116", "node": 3513, "naklon": null }, +{ "label": "13/117", "node": 3565, "naklon": null }, +{ "label": "13/118", "node": 3866, "naklon": null }, +{ "label": "14/1", "node": 3136, "naklon": 0 }, +{ "label": "14/2", "node": 3137, "naklon": 0 }, +{ "label": "14/3", "node": 3135, "naklon": 0 }, +{ "label": "14/4", "node": 3149, "naklon": 0 }, +{ "label": "14/5", "node": 3142, "naklon": 0 }, +{ "label": "14/6", "node": 3342, "naklon": 0 }, +{ "label": "14/7", "node": 3340, "naklon": 0 }, +{ "label": "14/8", "node": 3152, "naklon": 0 }, +{ "label": "14/9", "node": 3886, "naklon": 0 }, +{ "label": "14/10", "node": 3341, "naklon": null }, +{ "label": "14/11", "node": 3352, "naklon": null }, +{ "label": "15/1", "node": 3396, "naklon": 5 }, +{ "label": "15/2", "node": 2784, "naklon": 5 }, +{ "label": "15/3", "node": 2788, "naklon": 5 }, +{ "label": "15/4", "node": 2801, "naklon": 5 }, +{ "label": "15/5", "node": 2815, "naklon": 5 }, +{ "label": "15/6", "node": 2829, "naklon": 5 }, +{ "label": "15/7", "node": 2796, "naklon": 5 }, +{ "label": "15/8", "node": 2803, "naklon": 5 }, +{ "label": "15/8/1", "node": 4304, "naklon": 5 }, +{ "label": "15/8/2", "node": 4311, "naklon": 5 }, +{ "label": "15/9", "node": 2821, "naklon": 5 }, +{ "label": "15/10", "node": 3400, "naklon": 5 }, +{ "label": "15/11", "node": 2799, "naklon": 5 }, +{ "label": "15/12", "node": 2804, "naklon": 5 }, +{ "label": "15/12/1", "node": 4303, "naklon": 5 }, +{ "label": "15/12/2", "node": 4309, "naklon": 5 }, +{ "label": "15/13", "node": 2806, "naklon": 5 }, +{ "label": "15/14", "node": 2787, "naklon": 5 }, +{ "label": "15/15", "node": 2809, "naklon": 5 }, +{ "label": "15/16", "node": 2814, "naklon": 0 }, +{ "label": "15/17", "node": 3934, "naklon": 0 }, +{ "label": "15/18", "node": 3192, "naklon": 0 }, +{ "label": "15/19", "node": 2812, "naklon": 0 }, +{ "label": "15/20", "node": 4070, "naklon": 0 }, +{ "label": "15/21", "node": 2826, "naklon": 0 }, +{ "label": "15/22", "node": 2808, "naklon": 3 }, +{ "label": "15/23", "node": 2795, "naklon": 3 }, +{ "label": "15/24", "node": 2807, "naklon": 3 }, +{ "label": "15/25", "node": 2831, "naklon": 0 }, +{ "label": "15/26", "node": 2862, "naklon": null }, +{ "label": "15/27", "node": 2861, "naklon": 0 }, +{ "label": "15/28", "node": 2866, "naklon": 0 }, +{ "label": "15/28/1", "node": 3546, "naklon": 0 }, +{ "label": "15/29", "node": 4146, "naklon": 0 }, +{ "label": "15/29/1", "node": 3001, "naklon": 0 }, +{ "label": "15/30", "node": 2835, "naklon": 0 }, +{ "label": "15/31", "node": 2874, "naklon": 0 }, +{ "label": "15/32", "node": 2852, "naklon": 0 }, +{ "label": "15/33", "node": 2851, "naklon": 0 }, +{ "label": "15/33/1", "node": 3560, "naklon": 0 }, +{ "label": "15/34", "node": 2858, "naklon": 0 }, +{ "label": "15/34/1", "node": 4306, "naklon": 0 }, +{ "label": "15/35", "node": 2856, "naklon": 0 }, +{ "label": "15/36", "node": 2847, "naklon": 0 }, +{ "label": "15/36/1", "node": 3556, "naklon": 0 }, +{ "label": "15/37", "node": 3950, "naklon": 0 }, +{ "label": "15/38", "node": 2848, "naklon": 0 }, +{ "label": "15/39", "node": 2863, "naklon": 0 }, +{ "label": "15/39/1", "node": 4313, "naklon": 0 }, +{ "label": "15/40", "node": 2873, "naklon": 0 }, +{ "label": "15/40/1", "node": 2984, "naklon": 0 }, +{ "label": "15/41", "node": 2854, "naklon": 0 }, +{ "label": "15/42", "node": 2859, "naklon": 0 }, +{ "label": "15/43", "node": 2872, "naklon": 0 }, +{ "label": "15/44", "node": 2849, "naklon": 0 }, +{ "label": "15/45", "node": 2864, "naklon": 0 }, +{ "label": "15/46", "node": 3553, "naklon": null }, +{ "label": "15/47", "node": 3021, "naklon": null }, +{ "label": "15/47/1", "node": 3008, "naklon": null }, +{ "label": "15/48", "node": 3017, "naklon": null }, +{ "label": "15/49", "node": 3014, "naklon": null }, +{ "label": "15/50", "node": 2981, "naklon": null }, +{ "label": "15/51", "node": 3020, "naklon": null }, +{ "label": "15/52", "node": 3027, "naklon": null }, +{ "label": "15/53", "node": 3006, "naklon": null }, +{ "label": "15/54", "node": 3012, "naklon": null }, +{ "label": "15/55", "node": 2738, "naklon": 0 }, +{ "label": "15/56", "node": 2725, "naklon": 0 }, +{ "label": "15/57", "node": 3016, "naklon": null }, +{ "label": "15/58", "node": 3005, "naklon": null }, +{ "label": "15/58/1", "node": 3009, "naklon": null }, +{ "label": "15/59", "node": 3010, "naklon": 0 }, +{ "label": "15/59/1", "node": 3538, "naklon": 0 }, +{ "label": "15/59/2", "node": 4145, "naklon": 0 }, +{ "label": "15/60", "node": 2713, "naklon": 0 }, +{ "label": "15/61", "node": 2789, "naklon": 0 }, +{ "label": "15/62", "node": 2736, "naklon": 0 }, +{ "label": "15/63", "node": 2739, "naklon": 0 }, +{ "label": "15/64", "node": 4346, "naklon": 0 }, +{ "label": "15/65", "node": 2731, "naklon": 0 }, +{ "label": "15/66", "node": 2818, "naklon": 0 }, +{ "label": "15/66/1", "node": 3557, "naklon": 0 }, +{ "label": "15/67", "node": 2822, "naklon": 0 }, +{ "label": "15/68", "node": 2833, "naklon": 0 }, +{ "label": "15/69", "node": 2834, "naklon": 0 }, +{ "label": "15/70", "node": 3097, "naklon": 0 }, +{ "label": "15/71", "node": 2824, "naklon": 0 }, +{ "label": "15/72", "node": 2828, "naklon": 0 }, +{ "label": "15/73", "node": 2600, "naklon": 0 }, +{ "label": "15/73/1", "node": 4314, "naklon": 0 }, +{ "label": "15/74", "node": 2832, "naklon": 0 }, +{ "label": "15/75", "node": 4360, "naklon": 0 }, +{ "label": "15/76", "node": 2846, "naklon": 0 }, +{ "label": "15/77", "node": 2584, "naklon": 0 }, +{ "label": "15/78", "node": 2843, "naklon": 0 }, +{ "label": "15/78/1", "node": 4308, "naklon": 0 }, +{ "label": "15/79", "node": 4144, "naklon": null }, +{ "label": "15/80", "node": 2844, "naklon": 0 }, +{ "label": "15/81", "node": 2842, "naklon": 0 }, +{ "label": "15/82", "node": 2838, "naklon": 0 }, +{ "label": "15/83", "node": 2837, "naklon": null }, +{ "label": "15/83/1", "node": 3555, "naklon": null }, +{ "label": "15/84", "node": 2839, "naklon": 0 }, +{ "label": "15/85", "node": 2830, "naklon": 0 }, +{ "label": "15/86", "node": 4066, "naklon": 0 }, +{ "label": "15/87", "node": 2836, "naklon": 0 }, +{ "label": "15/88", "node": 2911, "naklon": 0 }, +{ "label": "15/89", "node": 2825, "naklon": 0 }, +{ "label": "15/90", "node": 2811, "naklon": 0 }, +{ "label": "15/94", "node": 3740, "naklon": 15 }, +{ "label": "15/95", "node": 2734, "naklon": 15 }, +{ "label": "15/96", "node": 3105, "naklon": 15 }, +{ "label": "15/97", "node": 2732, "naklon": 15 }, +{ "label": "15/98", "node": 2727, "naklon": 15 }, +{ "label": "15/99", "node": 2735, "naklon": 15 }, +{ "label": "15/100", "node": 3926, "naklon": 15 }, +{ "label": "15/101", "node": 2918, "naklon": 0 }, +{ "label": "15/102", "node": 2705, "naklon": 10 }, +{ "label": "15/103", "node": 2708, "naklon": 10 }, +{ "label": "15/104", "node": 2721, "naklon": 10 }, +{ "label": "15/105", "node": 2719, "naklon": 10 }, +{ "label": "15/106", "node": 2919, "naklon": 10 }, +{ "label": "15/107", "node": 3101, "naklon": 10 }, +{ "label": "15/108", "node": 2853, "naklon": 10 }, +{ "label": "15/109", "node": 2715, "naklon": 10 }, +{ "label": "15/110", "node": 2712, "naklon": 0 }, +{ "label": "15/111", "node": 2711, "naklon": 0 }, +{ "label": "15/112", "node": 2709, "naklon": 0 }, +{ "label": "15/113", "node": 2710, "naklon": 0 }, +{ "label": "15/114", "node": 2907, "naklon": 0 }, +{ "label": "15/115", "node": 2906, "naklon": 0 }, +{ "label": "15/116", "node": 2908, "naklon": 0 }, +{ "label": "15/117", "node": 2901, "naklon": 0 }, +{ "label": "15/118", "node": 2913, "naklon": 0 }, +{ "label": "15/119", "node": 3656, "naklon": 0 }, +{ "label": "15/120", "node": 2781, "naklon": 0 }, +{ "label": "15/121", "node": 2802, "naklon": 0 }, +{ "label": "15/122", "node": 2791, "naklon": 0 }, +{ "label": "15/123", "node": 2783, "naklon": 0 }, +{ "label": "15/124", "node": 2794, "naklon": 0 }, +{ "label": "15/125", "node": 3139, "naklon": 0 }, +{ "label": "15/126", "node": 3229, "naklon": 5 }, +{ "label": "15/127", "node": 3239, "naklon": 5 }, +{ "label": "15/128", "node": 3230, "naklon": 5 }, +{ "label": "15/129", "node": 4016, "naklon": null }, +{ "label": "16/16A", "node": 3608, "naklon": 0 }, +{ "label": "16/16B", "node": 4151, "naklon": 0 }, +{ "label": "16/1", "node": 3710, "naklon": 0 }, +{ "label": "16/2", "node": 3726, "naklon": 0 }, +{ "label": "16/3", "node": 3743, "naklon": 0 }, +{ "label": "16/4", "node": 3724, "naklon": 0 }, +{ "label": "16/5", "node": 3712, "naklon": 0 }, +{ "label": "16/6", "node": 3739, "naklon": 0 }, +{ "label": "16/7", "node": 3742, "naklon": 0 }, +{ "label": "16/8", "node": 3731, "naklon": 0 }, +{ "label": "16/9", "node": 3727, "naklon": 0 }, +{ "label": "16/10", "node": 3729, "naklon": 0 }, +{ "label": "16/11", "node": 3736, "naklon": 0 }, +{ "label": "16/12", "node": 3713, "naklon": 0 }, +{ "label": "16/13", "node": 3715, "naklon": 0 }, +{ "label": "16/14", "node": 3733, "naklon": 0 }, +{ "label": "16/15", "node": 3732, "naklon": 0 }, +{ "label": "16/17", "node": 3634, "naklon": 0 }, +{ "label": "16/18", "node": 3610, "naklon": 0 }, +{ "label": "16/19", "node": 3626, "naklon": 0 }, +{ "label": "16/20", "node": 3618, "naklon": 0 }, +{ "label": "16/21", "node": 3619, "naklon": 0 }, +{ "label": "16/22", "node": 3628, "naklon": 0 }, +{ "label": "16/23", "node": 3615, "naklon": 0 }, +{ "label": "16/24", "node": 3609, "naklon": 0 }, +{ "label": "16/25", "node": 3606, "naklon": 0 }, +{ "label": "16/26", "node": 3624, "naklon": 0 }, +{ "label": "16/27", "node": 3627, "naklon": 0 }, +{ "label": "16/28", "node": 3607, "naklon": 0 }, +{ "label": "16/29", "node": 4370, "naklon": 0 }, +{ "label": "16/30", "node": 3692, "naklon": 0 }, +{ "label": "16/31", "node": 3614, "naklon": 0 }, +{ "label": "16/32", "node": 3623, "naklon": 0 }, +{ "label": "16/33", "node": 4373, "naklon": 0 }, +{ "label": "16/34", "node": 3620, "naklon": 0 }, +{ "label": "16/35", "node": 3685, "naklon": 0 }, +{ "label": "16/36", "node": 3616, "naklon": 0 }, +{ "label": "16/37", "node": 3686, "naklon": 0 }, +{ "label": "16/38", "node": 3688, "naklon": 0 }, +{ "label": "16/39", "node": 3684, "naklon": 0 }, +{ "label": "16/40", "node": 3825, "naklon": 0 }, +{ "label": "16/41", "node": 3865, "naklon": 0 }, +{ "label": "16/42", "node": 3824, "naklon": 0 }, +{ "label": "16/43", "node": 3871, "naklon": 0 }, +{ "label": "16/44", "node": 3801, "naklon": 0 }, +{ "label": "16/45", "node": 3862, "naklon": 0 }, +{ "label": "16/46", "node": 3876, "naklon": 0 }, +{ "label": "16/47", "node": 3861, "naklon": 0 }, +{ "label": "16/48", "node": 4215, "naklon": 0 }, +{ "label": "16/49", "node": 3605, "naklon": 10 }, +{ "label": "16/50", "node": 3603, "naklon": 10 }, +{ "label": "16/51", "node": 3592, "naklon": 10 }, +{ "label": "16/52", "node": 3598, "naklon": 10 }, +{ "label": "16/53", "node": 3594, "naklon": 10 }, +{ "label": "16/54", "node": 3593, "naklon": 10 }, +{ "label": "16/55", "node": 3630, "naklon": 10 }, +{ "label": "16/56", "node": 3763, "naklon": 10 }, +{ "label": "16/57", "node": 3746, "naklon": 10 }, +{ "label": "16/58", "node": 3699, "naklon": 0 }, +{ "label": "16/59", "node": 3698, "naklon": 0 }, +{ "label": "16/60", "node": 3709, "naklon": null }, +{ "label": "16/61", "node": 3708, "naklon": 0 }, +{ "label": "16/62", "node": 3703, "naklon": null }, +{ "label": "16/63", "node": 3700, "naklon": 0 }, +{ "label": "16/64", "node": 3701, "naklon": null }, +{ "label": "16/65", "node": 3704, "naklon": 0 }, +{ "label": "16/66", "node": 3707, "naklon": null }, +{ "label": "16/67", "node": 3810, "naklon": 0 }, +{ "label": "16/68", "node": 4208, "naklon": null }, +{ "label": "16/69", "node": 3867, "naklon": 0 }, +{ "label": "16/70", "node": 4372, "naklon": null }, +{ "label": "16/71", "node": 3881, "naklon": 0 }, +{ "label": "16/72", "node": 4204, "naklon": null }, +{ "label": "16/73", "node": 3869, "naklon": 0 }, +{ "label": "16/74", "node": 4202, "naklon": null }, +{ "label": "16/75", "node": 3830, "naklon": 0 }, +{ "label": "16/76", "node": 3870, "naklon": null }, +{ "label": "16/77", "node": 3964, "naklon": 0 }, +{ "label": "16/78", "node": 3849, "naklon": 0 }, +{ "label": "16/79", "node": 3694, "naklon": null }, +{ "label": "16/80", "node": 3717, "naklon": 0 }, +{ "label": "16/81", "node": 3877, "naklon": null }, +{ "label": "16/82", "node": 3755, "naklon": 0 }, +{ "label": "16/83", "node": 3725, "naklon": null }, +{ "label": "16/84", "node": 3716, "naklon": 0 }, +{ "label": "16/85", "node": 3696, "naklon": null }, +{ "label": "16/86", "node": 3702, "naklon": 0 }, +{ "label": "16/87", "node": 3706, "naklon": null }, +{ "label": "16/88", "node": 3850, "naklon": 0 }, +{ "label": "16/89", "node": 3848, "naklon": null }, +{ "label": "16/90", "node": 3737, "naklon": null }, +{ "label": "16/91", "node": 3705, "naklon": 0 }, +{ "label": "16/92", "node": 3723, "naklon": null }, +{ "label": "16/93", "node": 3842, "naklon": 0 }, +{ "label": "16/94", "node": 3735, "naklon": null }, +{ "label": "16/95", "node": 3719, "naklon": 0 }, +{ "label": "16/96", "node": 3697, "naklon": 0 }, +{ "label": "16/97", "node": 3711, "naklon": 0 }, +{ "label": "16/98", "node": 4107, "naklon": null }, +{ "label": "16/99", "node": 4112, "naklon": 5 }, +{ "label": "16/100", "node": 4106, "naklon": 5 }, +{ "label": "16/101", "node": 4111, "naklon": 5 }, +{ "label": "16/102", "node": 4091, "naklon": null }, +{ "label": "16/103", "node": 4104, "naklon": 5 }, +{ "label": "16/104", "node": 4094, "naklon": null }, +{ "label": "16/105", "node": 4089, "naklon": 5 }, +{ "label": "16/106", "node": 4095, "naklon": null }, +{ "label": "16/107", "node": 4102, "naklon": 5 }, +{ "label": "16/108", "node": 4105, "naklon": null }, +{ "label": "16/109", "node": 3859, "naklon": null }, +{ "label": "16/110", "node": 4090, "naklon": 5 }, +{ "label": "16/111", "node": 4110, "naklon": null }, +{ "label": "16/112", "node": 4097, "naklon": 5 }, +{ "label": "16/113", "node": 4099, "naklon": null }, +{ "label": "16/114", "node": 4096, "naklon": null }, +{ "label": "16/115", "node": 4101, "naklon": 5 }, +{ "label": "16/116", "node": 4109, "naklon": null }, +{ "label": "16/117", "node": 4092, "naklon": 5 }, +{ "label": "16/118", "node": 3631, "naklon": null }, +{ "label": "16/119", "node": 3632, "naklon": 0 }, +{ "label": "16/120", "node": 3641, "naklon": null }, +{ "label": "16/121", "node": 3638, "naklon": 0 }, +{ "label": "16/122", "node": 3637, "naklon": null }, +{ "label": "16/123", "node": 4142, "naklon": null }, +{ "label": "16/124", "node": 4147, "naklon": 5 }, +{ "label": "16/125", "node": 4139, "naklon": 5 }, +{ "label": "20/30A", "node": 3172, "naklon": 2 }, +{ "label": "20/30B", "node": 3164, "naklon": 2 }, +{ "label": "20/1", "node": 3247, "naklon": 10 }, +{ "label": "20/2", "node": 3296, "naklon": 10 }, +{ "label": "20/3", "node": 3246, "naklon": 10 }, +{ "label": "20/4", "node": 3270, "naklon": 10 }, +{ "label": "20/5", "node": 3294, "naklon": 10 }, +{ "label": "20/6", "node": 3298, "naklon": 10 }, +{ "label": "20/7", "node": 3297, "naklon": 10 }, +{ "label": "20/8", "node": 3293, "naklon": 10 }, +{ "label": "20/9", "node": 3299, "naklon": 10 }, +{ "label": "20/10", "node": 3295, "naklon": 10 }, +{ "label": "20/11", "node": 3244, "naklon": 10 }, +{ "label": "20/12", "node": 3249, "naklon": 10 }, +{ "label": "20/13", "node": 3268, "naklon": 10 }, +{ "label": "20/14", "node": 3245, "naklon": 10 }, +{ "label": "20/15", "node": 3278, "naklon": 10 }, +{ "label": "20/16", "node": 3280, "naklon": 10 }, +{ "label": "20/17", "node": 3292, "naklon": 10 }, +{ "label": "20/18", "node": 3287, "naklon": 10 }, +{ "label": "20/19", "node": 3282, "naklon": 10 }, +{ "label": "20/20", "node": 3273, "naklon": 0 }, +{ "label": "20/21", "node": 3157, "naklon": 0 }, +{ "label": "20/22", "node": 3283, "naklon": 0 }, +{ "label": "20/23", "node": 3159, "naklon": 0 }, +{ "label": "20/24", "node": 3289, "naklon": 0 }, +{ "label": "20/25", "node": 3163, "naklon": 0 }, +{ "label": "20/26", "node": 3126, "naklon": 0 }, +{ "label": "20/27", "node": 3171, "naklon": 0 }, +{ "label": "20/28", "node": 3162, "naklon": 0 }, +{ "label": "20/29", "node": 3279, "naklon": 10 }, +{ "label": "20/31", "node": 3173, "naklon": 0 }, +{ "label": "20/32", "node": 3127, "naklon": 0 }, +{ "label": "20/33", "node": 3131, "naklon": 0 }, +{ "label": "20/34", "node": 3129, "naklon": 0 }, +{ "label": "20/35", "node": 3276, "naklon": 2 }, +{ "label": "20/36", "node": 3290, "naklon": 2 }, +{ "label": "20/37", "node": 3132, "naklon": 0 }, +{ "label": "20/38", "node": 3138, "naklon": 0 }, +{ "label": "20/39", "node": 3272, "naklon": 0 }, +{ "label": "20/40", "node": 3291, "naklon": 0 }, +{ "label": "20/41", "node": 3277, "naklon": 10 }, +{ "label": "20/42", "node": 3286, "naklon": 10 }, +{ "label": "20/43", "node": 3281, "naklon": 10 }, +{ "label": "20/44", "node": 3288, "naklon": 10 }, +{ "label": "20/45", "node": 3284, "naklon": 10 }, +{ "label": "20/46", "node": 3167, "naklon": 10 }, +{ "label": "20/47", "node": 3872, "naklon": 0 }, +{ "label": "20/48", "node": 3124, "naklon": 0 }, +{ "label": "20/49", "node": 3133, "naklon": 0 }, +{ "label": "20/50", "node": 3158, "naklon": 0 }, +{ "label": "20/51", "node": 3169, "naklon": 0 }, +{ "label": "20/52", "node": 3146, "naklon": 0 }, +{ "label": "20/53", "node": 3160, "naklon": 0 }, +{ "label": "20/54", "node": 3248, "naklon": 0 }, +{ "label": "20/55", "node": 3156, "naklon": 0 }, +{ "label": "20/56", "node": 3161, "naklon": 0 }, +{ "label": "20/57", "node": 3170, "naklon": 0 }, +{ "label": "20/58", "node": 3168, "naklon": 0 }, +{ "label": "20/59", "node": 3125, "naklon": 0 }, +{ "label": "20/60", "node": 3166, "naklon": 0 }, +{ "label": "20/61", "node": 3130, "naklon": 0 }, +{ "label": "20/62", "node": 3563, "naklon": 0 }, +{ "label": "20/63", "node": 3550, "naklon": null }, +{ "label": "20/67", "node": 3269, "naklon": 0 }, +{ "label": "21/1", "node": 2921, "naklon": 0 }, +{ "label": "21/2", "node": 2707, "naklon": 0 }, +{ "label": "21/3", "node": 2723, "naklon": 0 }, +{ "label": "21/4", "node": 2716, "naklon": 0 }, +{ "label": "21/5", "node": 2717, "naklon": 0 }, +{ "label": "21/6", "node": 2720, "naklon": 0 }, +{ "label": "21/7", "node": 2722, "naklon": 0 }, +{ "label": "21/8", "node": 2718, "naklon": 0 }, +{ "label": "21/9", "node": 2724, "naklon": 0 }, +{ "label": "21/10", "node": 2742, "naklon": 0 }, +{ "label": "21/11", "node": 2743, "naklon": 0 }, +{ "label": "21/12", "node": 2733, "naklon": 0 }, +{ "label": "21/14", "node": 2903, "naklon": 0 }, +{ "label": "21/15", "node": 2917, "naklon": 0 }, +{ "label": "21/16", "node": 2897, "naklon": 0 }, +{ "label": "21/17", "node": 2914, "naklon": 0 }, +{ "label": "21/18", "node": 2898, "naklon": 0 }, +{ "label": "21/19", "node": 2773, "naklon": 0 }, +{ "label": "21/20", "node": 2895, "naklon": 0 }, +{ "label": "21/21", "node": 2896, "naklon": 0 }, +{ "label": "21/22", "node": 2771, "naklon": 0 }, +{ "label": "21/23", "node": 2772, "naklon": 0 }, +{ "label": "21/24", "node": 2793, "naklon": 0 }, +{ "label": "21/25", "node": 2902, "naklon": 0 }, +{ "label": "21/26", "node": 2910, "naklon": 0 }, +{ "label": "21/27", "node": 2909, "naklon": 0 }, +{ "label": "21/28", "node": 2920, "naklon": 0 }, +{ "label": "21/29", "node": 2916, "naklon": 0 }, +{ "label": "21/30", "node": 2904, "naklon": 0 }, +{ "label": "21/31", "node": 2915, "naklon": 0 }, +{ "label": "21/32", "node": 2905, "naklon": 0 }, +{ "label": "21/33", "node": 2900, "naklon": 0 }, +{ "label": "21/34", "node": 2899, "naklon": 0 }, +{ "label": "21/36", "node": 2741, "naklon": 0 }, +{ "label": "21/37", "node": 2714, "naklon": 0 }, +{ "label": "21/38", "node": 2701, "naklon": 0 }, +{ "label": "21/39", "node": 2703, "naklon": 0 }, +{ "label": "21/40", "node": 2704, "naklon": 0 }, +{ "label": "21/41", "node": 2702, "naklon": 0 }, +{ "label": "21/42", "node": 2706, "naklon": 0 }, +{ "label": "21/43", "node": 2776, "naklon": 0 }, +{ "label": "21/44", "node": 2770, "naklon": 0 }, +{ "label": "21/45", "node": 2786, "naklon": 0 }, +{ "label": "21/46", "node": 2779, "naklon": 0 }, +{ "label": "21/47", "node": 2782, "naklon": 0 }, +{ "label": "21/48", "node": 2785, "naklon": 0 }, +{ "label": "21/49", "node": 2769, "naklon": 0 }, +{ "label": "21/50", "node": 3354, "naklon": 0 }, +{ "label": "21/51", "node": 2778, "naklon": 0 }, +{ "label": "21/52", "node": 2775, "naklon": 0 }, +{ "label": "21/53", "node": 2780, "naklon": 0 }, +{ "label": "21/54", "node": 2790, "naklon": 0 }, +{ "label": "21/55", "node": 2792, "naklon": 0 }, +{ "label": "21/56", "node": 2774, "naklon": 0 }, +{ "label": "22/1", "node": 2630, "naklon": 0 }, +{ "label": "22/2", "node": 2631, "naklon": 0 }, +{ "label": "22/3", "node": 2632, "naklon": 0 }, +{ "label": "22/4", "node": 2633, "naklon": 0 }, +{ "label": "22/5", "node": 2634, "naklon": 0 }, +{ "label": "22/6", "node": 2636, "naklon": 0 }, +{ "label": "22/7", "node": 4367, "naklon": 0 }, +{ "label": "22/8", "node": 2637, "naklon": 0 }, +{ "label": "22/9", "node": 2638, "naklon": 0 }, +{ "label": "22/10", "node": 2639, "naklon": 0 }, +{ "label": "22/11", "node": 2640, "naklon": 0 }, +{ "label": "22/12", "node": 2641, "naklon": 0 }, +{ "label": "22/13", "node": 2642, "naklon": 0 }, +{ "label": "22/14", "node": 2643, "naklon": 0 }, +{ "label": "22/15", "node": 2644, "naklon": 0 }, +{ "label": "22/16", "node": 2645, "naklon": 0 }, +{ "label": "22/17", "node": 2646, "naklon": 0 }, +{ "label": "22/18", "node": 2647, "naklon": 0 }, +{ "label": "22/19", "node": 2648, "naklon": 0 }, +{ "label": "22/20", "node": 2649, "naklon": 0 }, +{ "label": "22/21", "node": 2650, "naklon": 0 }, +{ "label": "22/22", "node": 2651, "naklon": 0 }, +{ "label": "22/23", "node": 4103, "naklon": 0 }, +{ "label": "22/24", "node": 2653, "naklon": 0 }, +{ "label": "22/25", "node": 2654, "naklon": 0 }, +{ "label": "22/26", "node": 2655, "naklon": 0 }, +{ "label": "22/27", "node": 2656, "naklon": 0 }, +{ "label": "22/28", "node": 2657, "naklon": 0 }, +{ "label": "22/29", "node": 2658, "naklon": 0 }, +{ "label": "22/30", "node": 2659, "naklon": 0 }, +{ "label": "22/31", "node": 2660, "naklon": 0 }, +{ "label": "22/32", "node": 2661, "naklon": 0 }, +{ "label": "22/32/1", "node": 3015, "naklon": 0 }, +{ "label": "22/33", "node": 2662, "naklon": 0 }, +{ "label": "22/34", "node": 2663, "naklon": 0 }, +{ "label": "22/35", "node": 2664, "naklon": 0 }, +{ "label": "22/36", "node": 2665, "naklon": 0 }, +{ "label": "22/37", "node": 2666, "naklon": 0 }, +{ "label": "22/38", "node": 2667, "naklon": 0 }, +{ "label": "22/39", "node": 2668, "naklon": 0 }, +{ "label": "22/40", "node": 2669, "naklon": null }, +{ "label": "22/41", "node": 2670, "naklon": null }, +{ "label": "22/42", "node": 2671, "naklon": null }, +{ "label": "23/9A", "node": 3087, "naklon": 10 }, +{ "label": "23/9B", "node": 3090, "naklon": 10 }, +{ "label": "23/1", "node": 3075, "naklon": 0 }, +{ "label": "23/2", "node": 3089, "naklon": 0 }, +{ "label": "23/3", "node": 3088, "naklon": 0 }, +{ "label": "23/4", "node": 3228, "naklon": 10 }, +{ "label": "23/5", "node": 2751, "naklon": 10 }, +{ "label": "23/6", "node": 3243, "naklon": 10 }, +{ "label": "23/7", "node": 4349, "naklon": 10 }, +{ "label": "23/8", "node": 3102, "naklon": 10 }, +{ "label": "23/10", "node": 3099, "naklon": 10 }, +{ "label": "23/11", "node": 3103, "naklon": 10 }, +{ "label": "23/12", "node": 3093, "naklon": 10 }, +{ "label": "23/13", "node": 3098, "naklon": 10 }, +{ "label": "23/14", "node": 3092, "naklon": 10 }, +{ "label": "23/15", "node": 3233, "naklon": 0 }, +{ "label": "23/16", "node": 3095, "naklon": 0 }, +{ "label": "23/17", "node": 4074, "naklon": 0 }, +{ "label": "23/18", "node": 2729, "naklon": 0 }, +{ "label": "23/19", "node": 3234, "naklon": 0 }, +{ "label": "23/20", "node": 3094, "naklon": 0 }, +{ "label": "23/21", "node": 2817, "naklon": 0 }, +{ "label": "23/22", "node": 3226, "naklon": 0 }, +{ "label": "23/23", "node": 3225, "naklon": 0 }, +{ "label": "23/24", "node": 3237, "naklon": 0 }, +{ "label": "23/25", "node": 4250, "naklon": 0 }, +{ "label": "23/26", "node": 3059, "naklon": 10 }, +{ "label": "23/27", "node": 3238, "naklon": 10 }, +{ "label": "23/28", "node": 3242, "naklon": 10 }, +{ "label": "23/29", "node": 3236, "naklon": 10 }, +{ "label": "23/30", "node": 3112, "naklon": 10 }, +{ "label": "23/31", "node": 3224, "naklon": 0 }, +{ "label": "23/32", "node": 4298, "naklon": 10 }, +{ "label": "23/33", "node": 4150, "naklon": 10 }, +{ "label": "23/34", "node": 3091, "naklon": 10 }, +{ "label": "25/1", "node": 3771, "naklon": 5 }, +{ "label": "25/2", "node": 3777, "naklon": 5 }, +{ "label": "25/3", "node": 3749, "naklon": 5 }, +{ "label": "25/4", "node": 3769, "naklon": 5 }, +{ "label": "25/5", "node": 3765, "naklon": 5 }, +{ "label": "25/6", "node": 3785, "naklon": 5 }, +{ "label": "25/7", "node": 3761, "naklon": 5 }, +{ "label": "25/8", "node": 3758, "naklon": 5 }, +{ "label": "25/9", "node": 3766, "naklon": 5 }, +{ "label": "25/10", "node": 3779, "naklon": 5 }, +{ "label": "25/11", "node": 3899, "naklon": 10 }, +{ "label": "25/12", "node": 3922, "naklon": 10 }, +{ "label": "25/13", "node": 3912, "naklon": 10 }, +{ "label": "25/14", "node": 3933, "naklon": 10 }, +{ "label": "25/15", "node": 3921, "naklon": 10 }, +{ "label": "25/16", "node": 4300, "naklon": 10 }, +{ "label": "25/17", "node": 3927, "naklon": 10 }, +{ "label": "25/18", "node": 3212, "naklon": 10 }, +{ "label": "25/19", "node": 3208, "naklon": 10 }, +{ "label": "25/20", "node": 3207, "naklon": 10 }, +{ "label": "25/21", "node": 4294, "naklon": 10 }, +{ "label": "25/22", "node": 3209, "naklon": 10 }, +{ "label": "25/23", "node": 3745, "naklon": 10 }, +{ "label": "25/24", "node": 3762, "naklon": 10 }, +{ "label": "25/25", "node": 3215, "naklon": 10 }, +{ "label": "25/26", "node": 3210, "naklon": 10 }, +{ "label": "25/27", "node": 3211, "naklon": 10 }, +{ "label": "25/28", "node": 3206, "naklon": 10 }, +{ "label": "25/29", "node": 3918, "naklon": 5 }, +{ "label": "25/30", "node": 3928, "naklon": 5 }, +{ "label": "25/31", "node": 3917, "naklon": 5 }, +{ "label": "25/32", "node": 4029, "naklon": 0 }, +{ "label": "25/33", "node": 4038, "naklon": 0 }, +{ "label": "25/34", "node": 4022, "naklon": 0 }, +{ "label": "25/35", "node": 3937, "naklon": 0 }, +{ "label": "25/36", "node": 3190, "naklon": 0 }, +{ "label": "25/37", "node": 3835, "naklon": 0 }, +{ "label": "25/38", "node": 3201, "naklon": 0 }, +{ "label": "25/39", "node": 3193, "naklon": 0 }, +{ "label": "25/40", "node": 3191, "naklon": 0 }, +{ "label": "25/41", "node": 3203, "naklon": 0 }, +{ "label": "25/42", "node": 4301, "naklon": 0 }, +{ "label": "25/43", "node": 3223, "naklon": 0 }, +{ "label": "25/44", "node": 3202, "naklon": 0 }, +{ "label": "25/45", "node": 3205, "naklon": 0 }, +{ "label": "25/46", "node": 3194, "naklon": 0 }, +{ "label": "25/47", "node": 3198, "naklon": 0 }, +{ "label": "25/48", "node": 3204, "naklon": 0 }, +{ "label": "25/49", "node": 3200, "naklon": 0 }, +{ "label": "25/50", "node": 3216, "naklon": 0 }, +{ "label": "25/51", "node": 3932, "naklon": 5 }, +{ "label": "25/52", "node": 3923, "naklon": 5 }, +{ "label": "25/53", "node": 3913, "naklon": 5 }, +{ "label": "25/54", "node": 3900, "naklon": 5 }, +{ "label": "25/55", "node": 4189, "naklon": 10 }, +{ "label": "25/56", "node": 4191, "naklon": 10 }, +{ "label": "25/57", "node": 3790, "naklon": 10 }, +{ "label": "25/58", "node": 4190, "naklon": 10 }, +{ "label": "25/59", "node": 4302, "naklon": 0 }, +{ "label": "25/60", "node": 4351, "naklon": 0 }, +{ "label": "25/61", "node": 4075, "naklon": 0 }, +{ "label": "25/62", "node": 4071, "naklon": 0 }, +{ "label": "25/63", "node": 3784, "naklon": 0 }, +{ "label": "25/64", "node": 4065, "naklon": 0 }, +{ "label": "25/65", "node": 4297, "naklon": 0 }, +{ "label": "25/66", "node": 4295, "naklon": 0 }, +{ "label": "25/67", "node": 4299, "naklon": 0 }, +{ "label": "25/68", "node": 3772, "naklon": 0 }, +{ "label": "25/69", "node": 3941, "naklon": 0 }, +{ "label": "25/70", "node": 3782, "naklon": 0 }, +{ "label": "25/71", "node": 4068, "naklon": 0 }, +{ "label": "25/72", "node": 4073, "naklon": 0 }, +{ "label": "25/73", "node": 3901, "naklon": 5 }, +{ "label": "25/74", "node": 4296, "naklon": 5 }, +{ "label": "25/75", "node": 3910, "naklon": 5 }, +{ "label": "25/76", "node": 4293, "naklon": 5 }, +{ "label": "25/77", "node": 3919, "naklon": 5 }, +{ "label": "25/78", "node": 3924, "naklon": 5 }, +{ "label": "25/79", "node": 3909, "naklon": 5 }, +{ "label": "25/80", "node": 3896, "naklon": 5 }, +{ "label": "25/81", "node": 3911, "naklon": 5 }, +{ "label": "25/82", "node": 2819, "naklon": 15 }, +{ "label": "25/83", "node": 3776, "naklon": 15 }, +{ "label": "25/84", "node": 3752, "naklon": 15 }, +{ "label": "25/85", "node": 4353, "naklon": 15 }, +{ "label": "25/86", "node": 3791, "naklon": 0 }, +{ "label": "25/87", "node": 3770, "naklon": 0 }, +{ "label": "25/88", "node": 3760, "naklon": 0 }, +{ "label": "25/89", "node": 3115, "naklon": 0 }, +{ "label": "25/90", "node": 3738, "naklon": 0 }, +{ "label": "25/91", "node": 3748, "naklon": 0 }, +{ "label": "25/92", "node": 3753, "naklon": 0 }, +{ "label": "25/93", "node": 3775, "naklon": 0 }, +{ "label": "25/94", "node": 3778, "naklon": 5 }, +{ "label": "25/95", "node": 4078, "naklon": 5 }, +{ "label": "25/96", "node": 4088, "naklon": 5 }, +{ "label": "25/97", "node": 3856, "naklon": 5 }, +{ "label": "25/98", "node": 4084, "naklon": 5 }, +{ "label": "25/99", "node": 4069, "naklon": 5 }, +{ "label": "25/100", "node": 4188, "naklon": 5 }, +{ "label": "25/101", "node": 4064, "naklon": 5 }, +{ "label": "25/102", "node": 3792, "naklon": 5 }, +{ "label": "25/103", "node": 3780, "naklon": 5 }, +{ "label": "25/104", "node": 4034, "naklon": 5 }, +{ "label": "25/105", "node": 4072, "naklon": 5 }, +{ "label": "25/106", "node": 3884, "naklon": 5 }, +{ "label": "25/107", "node": 3793, "naklon": 5 }, +{ "label": "25/108", "node": 3863, "naklon": 5 }, +{ "label": "25/109", "node": 3855, "naklon": 5 }, +{ "label": "33/1", "node": 3846, "naklon": 0 }, +{ "label": "33/2", "node": 3943, "naklon": 0 }, +{ "label": "33/3", "node": 3903, "naklon": 0 }, +{ "label": "33/4", "node": 3982, "naklon": 0 }, +{ "label": "33/5", "node": 3879, "naklon": 0 }, +{ "label": "33/6", "node": 3887, "naklon": 0 }, +{ "label": "33/7", "node": 3920, "naklon": 5 }, +{ "label": "33/8", "node": 3942, "naklon": 5 }, +{ "label": "33/9", "node": 3829, "naklon": null }, +{ "label": "34/79A", "node": 3452, "naklon": 6 }, +{ "label": "34/79B", "node": 3460, "naklon": 6 }, +{ "label": "34/90A", "node": 3443, "naklon": 6 }, +{ "label": "34/90B", "node": 3445, "naklon": 6 }, +{ "label": "34/90C", "node": 3457, "naklon": 6 }, +{ "label": "34/97A", "node": 3461, "naklon": 6 }, +{ "label": "34/97B", "node": 3463, "naklon": 6 }, +{ "label": "34/98A", "node": 3426, "naklon": 6 }, +{ "label": "34/98B", "node": 3444, "naklon": 6 }, +{ "label": "34/99A", "node": 3453, "naklon": 6 }, +{ "label": "34/99B", "node": 3455, "naklon": 6 }, +{ "label": "34/1", "node": 4009, "naklon": 0 }, +{ "label": "34/2", "node": 3602, "naklon": 0 }, +{ "label": "34/3", "node": 3441, "naklon": 0 }, +{ "label": "34/4", "node": 3464, "naklon": 0 }, +{ "label": "34/5", "node": 3883, "naklon": 0 }, +{ "label": "34/6", "node": 4098, "naklon": 0 }, +{ "label": "34/7", "node": 4003, "naklon": 0 }, +{ "label": "34/8", "node": 4004, "naklon": 0 }, +{ "label": "34/9", "node": 3888, "naklon": 0 }, +{ "label": "34/10", "node": 3997, "naklon": 0 }, +{ "label": "34/11", "node": 4006, "naklon": 0 }, +{ "label": "34/12", "node": 4000, "naklon": 0 }, +{ "label": "34/13", "node": 4011, "naklon": 0 }, +{ "label": "34/14", "node": 3999, "naklon": 0 }, +{ "label": "34/15", "node": 3981, "naklon": 0 }, +{ "label": "34/16", "node": 3988, "naklon": 0 }, +{ "label": "34/17", "node": 3986, "naklon": 0 }, +{ "label": "34/18", "node": 3998, "naklon": 0 }, +{ "label": "34/19", "node": 3983, "naklon": 0 }, +{ "label": "34/20", "node": 4005, "naklon": 0 }, +{ "label": "34/21", "node": 4001, "naklon": 0 }, +{ "label": "34/22", "node": 4008, "naklon": 0 }, +{ "label": "34/23", "node": 4002, "naklon": 0 }, +{ "label": "34/24", "node": 3996, "naklon": 0 }, +{ "label": "34/25", "node": 4007, "naklon": 0 }, +{ "label": "34/26", "node": 4113, "naklon": 15 }, +{ "label": "34/27", "node": 3595, "naklon": 5 }, +{ "label": "34/28", "node": 3599, "naklon": 5 }, +{ "label": "34/29", "node": 3601, "naklon": 5 }, +{ "label": "34/30", "node": 4205, "naklon": 0 }, +{ "label": "34/31", "node": 3987, "naklon": null }, +{ "label": "34/32", "node": 4214, "naklon": 0 }, +{ "label": "34/33", "node": 4226, "naklon": 0 }, +{ "label": "34/34", "node": 4209, "naklon": 0 }, +{ "label": "34/35", "node": 4201, "naklon": 0 }, +{ "label": "34/36", "node": 3440, "naklon": 0 }, +{ "label": "34/37", "node": 3465, "naklon": 0 }, +{ "label": "34/38", "node": 3446, "naklon": 0 }, +{ "label": "34/39", "node": 4039, "naklon": 5 }, +{ "label": "34/40", "node": 4057, "naklon": 5 }, +{ "label": "34/41", "node": 3985, "naklon": 0 }, +{ "label": "34/42", "node": 3882, "naklon": 0 }, +{ "label": "34/43", "node": 4040, "naklon": 5 }, +{ "label": "34/44", "node": 3231, "naklon": 0 }, +{ "label": "34/45", "node": 3227, "naklon": 0 }, +{ "label": "34/46", "node": 3431, "naklon": 0 }, +{ "label": "34/47", "node": 4013, "naklon": 0 }, +{ "label": "34/48", "node": 4045, "naklon": 0 }, +{ "label": "34/49", "node": 3949, "naklon": 0 }, +{ "label": "34/50", "node": 3953, "naklon": 0 }, +{ "label": "34/51", "node": 3952, "naklon": 0 }, +{ "label": "34/52", "node": 3995, "naklon": 0 }, +{ "label": "34/53", "node": 3992, "naklon": 0 }, +{ "label": "34/54", "node": 4198, "naklon": 0 }, +{ "label": "34/55", "node": 3935, "naklon": 0 }, +{ "label": "34/56", "node": 4050, "naklon": 0 }, +{ "label": "34/57", "node": 4049, "naklon": 0 }, +{ "label": "34/58", "node": 4054, "naklon": 0 }, +{ "label": "34/59", "node": 3663, "naklon": 6 }, +{ "label": "34/60", "node": 3661, "naklon": 6 }, +{ "label": "34/61", "node": 3664, "naklon": 6 }, +{ "label": "34/62", "node": 3660, "naklon": 6 }, +{ "label": "34/63", "node": 3662, "naklon": 6 }, +{ "label": "34/65", "node": 3665, "naklon": 6 }, +{ "label": "34/66", "node": 3667, "naklon": 6 }, +{ "label": "34/67", "node": 3675, "naklon": 6 }, +{ "label": "34/68", "node": 3666, "naklon": 6 }, +{ "label": "34/69", "node": 3652, "naklon": 6 }, +{ "label": "34/70", "node": 3458, "naklon": 6 }, +{ "label": "34/70/1", "node": 4425, "naklon": 6 }, +{ "label": "34/71", "node": 3459, "naklon": 6 }, +{ "label": "34/72", "node": 3435, "naklon": 6 }, +{ "label": "34/73", "node": 3448, "naklon": 6 }, +{ "label": "34/74", "node": 3451, "naklon": 6 }, +{ "label": "34/75", "node": 3442, "naklon": 6 }, +{ "label": "34/76", "node": 3449, "naklon": 6 }, +{ "label": "34/77", "node": 3450, "naklon": 6 }, +{ "label": "34/78", "node": 3433, "naklon": 6 }, +{ "label": "34/80", "node": 3432, "naklon": 12 }, +{ "label": "34/81", "node": 3470, "naklon": 12 }, +{ "label": "34/82", "node": 3438, "naklon": 12 }, +{ "label": "34/83", "node": 3439, "naklon": 12 }, +{ "label": "34/84", "node": 4028, "naklon": 5 }, +{ "label": "34/85", "node": 3596, "naklon": 5 }, +{ "label": "34/86", "node": 4021, "naklon": 5 }, +{ "label": "34/87", "node": 3437, "naklon": 12 }, +{ "label": "34/88", "node": 3428, "naklon": 12 }, +{ "label": "34/89", "node": 3430, "naklon": 12 }, +{ "label": "34/91", "node": 3454, "naklon": 6 }, +{ "label": "34/92", "node": 3492, "naklon": 6 }, +{ "label": "34/93", "node": 3462, "naklon": 6 }, +{ "label": "34/94", "node": 3427, "naklon": 6 }, +{ "label": "34/95", "node": 3434, "naklon": 6 }, +{ "label": "34/96", "node": 3456, "naklon": 6 }, +{ "label": "34/98/1", "node": 4307, "naklon": 6 }, +{ "label": "35/1", "node": 3968, "naklon": 0 }, +{ "label": "35/2", "node": 3969, "naklon": 0 }, +{ "label": "35/3", "node": 3947, "naklon": 0 }, +{ "label": "35/4", "node": 3979, "naklon": 0 }, +{ "label": "35/5", "node": 3959, "naklon": 0 }, +{ "label": "35/6", "node": 3948, "naklon": 0 }, +{ "label": "35/7", "node": 3961, "naklon": 0 }, +{ "label": "35/8", "node": 3956, "naklon": 0 }, +{ "label": "35/9", "node": 3604, "naklon": 0 }, +{ "label": "35/10", "node": 3944, "naklon": 0 }, +{ "label": "35/11", "node": 3960, "naklon": 0 }, +{ "label": "35/12", "node": 3958, "naklon": 0 }, +{ "label": "35/13", "node": 4036, "naklon": 5 }, +{ "label": "35/18", "node": 3893, "naklon": 5 }, +{ "label": "35/19", "node": 4108, "naklon": 5 }, +{ "label": "35/20", "node": 4017, "naklon": 5 }, +{ "label": "35/21", "node": 3963, "naklon": 0 }, +{ "label": "35/22", "node": 3658, "naklon": 0 }, +{ "label": "35/23", "node": 3975, "naklon": 0 }, +{ "label": "35/24", "node": 3980, "naklon": 0 }, +{ "label": "35/25", "node": 4012, "naklon": 0 }, +{ "label": "35/26", "node": 3655, "naklon": 0 }, +{ "label": "35/27", "node": 3962, "naklon": 0 }, +{ "label": "35/28", "node": 3945, "naklon": 0 }, +{ "label": "35/29", "node": 3569, "naklon": 0 }, +{ "label": "35/30", "node": 3429, "naklon": 0 }, +{ "label": "35/31", "node": 3657, "naklon": 0 }, +{ "label": "35/32", "node": 3646, "naklon": 0 }, +{ "label": "35/33", "node": 3622, "naklon": 0 }, +{ "label": "35/34", "node": 3612, "naklon": 0 }, +{ "label": "35/35", "node": 3955, "naklon": 0 }, +{ "label": "35/37", "node": 3878, "naklon": 0 }, +{ "label": "35/38", "node": 3965, "naklon": 0 }, +{ "label": "35/39", "node": 3970, "naklon": 0 }, +{ "label": "35/40", "node": 3611, "naklon": 0 }, +{ "label": "35/41", "node": 2635, "naklon": 0 }, +{ "label": "35/42", "node": 3978, "naklon": 0 }, +{ "label": "35/43", "node": 4213, "naklon": 0 }, +{ "label": "35/44", "node": 3984, "naklon": 0 }, +{ "label": "35/45", "node": 4218, "naklon": 0 }, +{ "label": "35/46", "node": 3973, "naklon": 0 }, +{ "label": "35/47", "node": 3974, "naklon": 0 }, +{ "label": "35/48", "node": 3759, "naklon": 0 }, +{ "label": "35/49", "node": 3844, "naklon": 0 }, +{ "label": "35/50", "node": 3804, "naklon": 0 }, +{ "label": "35/51", "node": 3831, "naklon": 0 }, +{ "label": "35/52", "node": 3643, "naklon": 0 }, +{ "label": "35/53", "node": 3966, "naklon": 0 }, +{ "label": "35/54", "node": 3971, "naklon": 0 }, +{ "label": "35/55", "node": 3650, "naklon": 6 }, +{ "label": "35/56", "node": 3651, "naklon": 6 }, +{ "label": "35/57", "node": 3669, "naklon": 6 }, +{ "label": "35/58", "node": 3648, "naklon": 6 }, +{ "label": "35/59", "node": 3645, "naklon": 6 }, +{ "label": "35/60", "node": 3659, "naklon": 6 }, +{ "label": "35/61", "node": 3647, "naklon": 6 }, +{ "label": "35/62", "node": 3644, "naklon": 6 }, +{ "label": "35/63", "node": 3671, "naklon": 6 }, +{ "label": "35/64", "node": 3682, "naklon": 6 }, +{ "label": "35/65", "node": 3672, "naklon": 6 }, +{ "label": "35/66", "node": 3683, "naklon": 6 }, +{ "label": "35/67", "node": 3673, "naklon": 6 }, +{ "label": "35/68", "node": 3674, "naklon": 6 }, +{ "label": "35/69", "node": 3679, "naklon": 6 }, +{ "label": "35/70", "node": 3649, "naklon": 6 }, +{ "label": "35/71", "node": 3687, "naklon": 6 }, +{ "label": "35/72", "node": 3677, "naklon": 6 }, +{ "label": "35/73", "node": 3690, "naklon": 6 }, +{ "label": "35/74", "node": 3691, "naklon": 6 }, +{ "label": "35/75", "node": 3676, "naklon": 6 }, +{ "label": "35/76", "node": 3680, "naklon": 6 }, +{ "label": "35/77", "node": 3668, "naklon": 6 }, +{ "label": "35/78", "node": 3681, "naklon": 6 }, +{ "label": "35/79", "node": 3670, "naklon": 6 }, +{ "label": "35/80", "node": 3689, "naklon": 6 }, +{ "label": "35/81", "node": 3678, "naklon": 6 }, +{ "label": "35/82", "node": 3693, "naklon": 6 }, +{ "label": "35/83", "node": 3654, "naklon": null }, +{ "label": "36/1", "node": 4086, "naklon": 0 }, +{ "label": "36/2", "node": 4085, "naklon": 0 }, +{ "label": "36/3", "node": 4083, "naklon": 0 }, +{ "label": "36/4", "node": 4087, "naklon": 0 }, +{ "label": "36/5", "node": 4077, "naklon": 0 }, +{ "label": "36/6", "node": 4082, "naklon": 0 }, +{ "label": "36/7", "node": 4186, "naklon": 0 }, +{ "label": "36/8", "node": 4206, "naklon": 0 }, +{ "label": "36/9", "node": 4080, "naklon": 0 }, +{ "label": "36/10", "node": 4081, "naklon": 0 }, +{ "label": "36/11", "node": 4210, "naklon": 0 }, +{ "label": "36/12", "node": 4079, "naklon": 0 }, +{ "label": "36/13", "node": 4076, "naklon": 0 }, +{ "label": "36/14", "node": 3852, "naklon": 0 }, +{ "label": "36/15", "node": 2813, "naklon": 0 }, +{ "label": "36/16", "node": 4219, "naklon": 0 }, +{ "label": "37/1A", "node": 3104, "naklon": 15 }, +{ "label": "37/1B", "node": 3121, "naklon": 15 }, +{ "label": "37/2", "node": 3113, "naklon": 10 }, +{ "label": "37/3", "node": 3118, "naklon": 10 }, +{ "label": "37/4", "node": 3111, "naklon": 10 }, +{ "label": "37/5", "node": 4020, "naklon": 10 }, +{ "label": "37/6", "node": 3119, "naklon": 10 }, +{ "label": "37/7", "node": 3110, "naklon": 10 }, +{ "label": "37/8", "node": 3108, "naklon": 10 }, +{ "label": "37/12", "node": 3107, "naklon": 0 }, +{ "label": "37/13", "node": 3199, "naklon": 0 }, +{ "label": "37/14", "node": 3120, "naklon": 0 }, +{ "label": "37/15", "node": 3122, "naklon": 0 }, +{ "label": "37/16", "node": 3908, "naklon": 0 }, +{ "label": "37/17", "node": 3114, "naklon": 0 }, +{ "label": "37/18", "node": 3105, "naklon": 0 }, +{ "label": "37/19", "node": 3116, "naklon": 0 }, +{ "label": "37/20", "node": 3106, "naklon": 0 }, +{ "label": "37/21", "node": 2887, "naklon": 5 }, +{ "label": "37/22", "node": 2888, "naklon": 5 }, +{ "label": "37/23", "node": 2877, "naklon": 5 }, +{ "label": "37/24", "node": 2891, "naklon": 5 }, +{ "label": "37/25", "node": 2886, "naklon": 5 }, +{ "label": "37/26", "node": 2892, "naklon": 5 }, +{ "label": "37/27", "node": 2882, "naklon": 5 }, +{ "label": "37/28", "node": 2883, "naklon": 5 }, +{ "label": "37/29", "node": 2876, "naklon": 5 }, +{ "label": "37/30", "node": 3109, "naklon": 5 }, +{ "label": "37/31", "node": 4152, "naklon": 5 }, +{ "label": "37/32", "node": 3117, "naklon": 5 }, +{ "label": "37/33", "node": 2870, "naklon": 5 }, +{ "label": "37/34", "node": 2867, "naklon": 0 }, +{ "label": "37/35", "node": 2865, "naklon": 0 }, +{ "label": "37/36", "node": 3096, "naklon": 0 }, +{ "label": "37/37", "node": 2871, "naklon": 0 }, +{ "label": "37/38", "node": 2884, "naklon": 0 }, +{ "label": "37/39", "node": 2855, "naklon": 0 }, +{ "label": "37/40", "node": 2878, "naklon": 0 }, +{ "label": "37/41", "node": 2889, "naklon": 0 }, +{ "label": "37/42", "node": 2879, "naklon": 0 }, +{ "label": "37/43", "node": 2850, "naklon": 0 }, +{ "label": "37/44", "node": 2894, "naklon": 0 }, +{ "label": "37/45", "node": 2880, "naklon": 0 }, +{ "label": "37/46", "node": 2893, "naklon": 0 }, +{ "label": "37/47", "node": 2890, "naklon": 0 }, +{ "label": "37/48", "node": 4355, "naklon": 0 }, +{ "label": "37/49", "node": 2885, "naklon": 0 }, +{ "label": "37/50", "node": 2875, "naklon": 0 }, +{ "label": "38/30A", "node": 3486, "naklon": 5 }, +{ "label": "38/30B", "node": 3714, "naklon": 0 }, +{ "label": "38/32A", "node": 3483, "naklon": 5 }, +{ "label": "38/32B", "node": 3496, "naklon": 0 }, +{ "label": "38/35A", "node": 3487, "naklon": 5 }, +{ "label": "38/35B", "node": 3498, "naklon": 5 }, +{ "label": "38/38A", "node": 3578, "naklon": 5 }, +{ "label": "38/38B", "node": 3508, "naklon": 5 }, +{ "label": "38/59A", "node": 3787, "naklon": 5 }, +{ "label": "38/59B", "node": 3491, "naklon": 5 }, +{ "label": "38/1", "node": 3568, "naklon": null }, +{ "label": "38/2", "node": 3502, "naklon": 0 }, +{ "label": "38/3", "node": 3836, "naklon": 0 }, +{ "label": "38/4", "node": 3588, "naklon": 0 }, +{ "label": "38/5", "node": 3493, "naklon": 0 }, +{ "label": "38/6", "node": 3580, "naklon": 0 }, +{ "label": "38/7", "node": 3572, "naklon": 0 }, +{ "label": "38/8", "node": 3506, "naklon": 0 }, +{ "label": "38/9", "node": 3503, "naklon": 0 }, +{ "label": "38/10", "node": 3579, "naklon": 0 }, +{ "label": "38/11", "node": 3586, "naklon": 0 }, +{ "label": "38/12", "node": 3495, "naklon": 5 }, +{ "label": "38/13", "node": 3492, "naklon": 5 }, +{ "label": "38/14", "node": 3532, "naklon": 5 }, +{ "label": "38/15", "node": 3574, "naklon": 5 }, +{ "label": "38/16", "node": 4140, "naklon": 5 }, +{ "label": "38/17", "node": 3795, "naklon": 5 }, +{ "label": "38/18", "node": 3788, "naklon": 5 }, +{ "label": "38/19", "node": 3796, "naklon": 5 }, +{ "label": "38/20", "node": 3797, "naklon": 5 }, +{ "label": "38/21", "node": 3798, "naklon": 5 }, +{ "label": "38/22", "node": 3786, "naklon": 5 }, +{ "label": "38/23", "node": 4067, "naklon": 5 }, +{ "label": "38/24", "node": 3773, "naklon": 5 }, +{ "label": "38/25", "node": 3774, "naklon": 5 }, +{ "label": "38/26", "node": 3789, "naklon": 5 }, +{ "label": "38/27", "node": 3520, "naklon": null }, +{ "label": "38/29", "node": 3577, "naklon": 5 }, +{ "label": "38/31", "node": 3530, "naklon": null }, +{ "label": "38/33", "node": 3488, "naklon": 5 }, +{ "label": "38/34", "node": 3505, "naklon": 5 }, +{ "label": "38/36", "node": 3497, "naklon": 5 }, +{ "label": "38/37", "node": 3490, "naklon": 5 }, +{ "label": "38/39", "node": 3585, "naklon": 5 }, +{ "label": "38/40", "node": 3582, "naklon": 5 }, +{ "label": "38/41", "node": 3507, "naklon": 5 }, +{ "label": "38/42", "node": 3484, "naklon": 5 }, +{ "label": "38/43", "node": 3501, "naklon": 5 }, +{ "label": "38/44", "node": 3581, "naklon": 5 }, +{ "label": "38/45", "node": 4192, "naklon": 5 }, +{ "label": "38/46", "node": 3576, "naklon": 5 }, +{ "label": "38/47", "node": 3489, "naklon": 5 }, +{ "label": "38/48", "node": 3573, "naklon": 5 }, +{ "label": "38/49", "node": 3504, "naklon": 5 }, +{ "label": "38/50", "node": 3794, "naklon": 5 }, +{ "label": "38/51", "node": 3485, "naklon": 5 }, +{ "label": "38/52", "node": 3482, "naklon": 5 }, +{ "label": "38/53", "node": 3575, "naklon": 5 }, +{ "label": "38/54", "node": 3499, "naklon": 5 }, +{ "label": "38/55", "node": 3494, "naklon": 5 }, +{ "label": "38/56", "node": 3583, "naklon": 5 }, +{ "label": "38/57", "node": 3570, "naklon": 5 }, +{ "label": "38/58", "node": 3500, "naklon": 0 }, +{ "label": "38/63", "node": 3510, "naklon": null }, +{ "label": "38/64", "node": 3512, "naklon": null }, +{ "label": "38/67", "node": 3535, "naklon": null }, +{ "label": "38/68", "node": 3531, "naklon": null }, +{ "label": "38/69", "node": 3537, "naklon": null }, +{ "label": "39/1", "node": 3522, "naklon": 10 }, +{ "label": "39/2", "node": 4018, "naklon": 10 }, +{ "label": "39/3", "node": 4019, "naklon": 10 }, +{ "label": "39/4", "node": 4154, "naklon": 5 }, +{ "label": "39/5", "node": 3907, "naklon": 5 }, +{ "label": "39/6", "node": 4148, "naklon": 0 }, +{ "label": "39/7", "node": 4153, "naklon": 0 }, +{ "label": "39/8", "node": 3938, "naklon": 0 }, +{ "label": "39/9", "node": 3802, "naklon": 0 }, +{ "label": "39/10", "node": 4015, "naklon": 0 }, +{ "label": "39/11", "node": 3929, "naklon": 0 }, +{ "label": "39/12", "node": 3946, "naklon": 0 }, +{ "label": "39/13", "node": 4014, "naklon": 0 }, +{ "label": "39/14", "node": 4155, "naklon": 0 }, +{ "label": "39/15", "node": 4149, "naklon": 0 }, +{ "label": "39/16", "node": 3642, "naklon": 0 }, +{ "label": "39/17", "node": 3636, "naklon": 5 }, +{ "label": "39/18", "node": 3991, "naklon": 0 }, +{ "label": "39/19", "node": 3994, "naklon": 0 }, +{ "label": "39/20", "node": 3990, "naklon": 0 }, +{ "label": "39/21", "node": 3967, "naklon": 0 }, +{ "label": "39/22", "node": 3977, "naklon": 0 }, +{ "label": "39/23", "node": 3757, "naklon": 15 }, +{ "label": "39/24", "node": 3633, "naklon": 15 }, +{ "label": "39/25", "node": 3744, "naklon": 15 }, +{ "label": "39/26", "node": 4023, "naklon": 5 }, +{ "label": "39/27", "node": 3720, "naklon": 5 }, +{ "label": "39/28", "node": 3734, "naklon": 5 }, +{ "label": "39/29", "node": 3741, "naklon": 5 }, +{ "label": "39/30", "node": 3721, "naklon": 5 }, +{ "label": "39/31", "node": 3845, "naklon": 0 }, +{ "label": "39/32", "node": 3840, "naklon": 0 }, +{ "label": "39/33", "node": 3837, "naklon": null }, +{ "label": "39/34", "node": 3839, "naklon": 0 }, +{ "label": "41/1", "node": 3542, "naklon": null }, +{ "label": "41/2", "node": 3566, "naklon": null }, +{ "label": "41/3", "node": 3548, "naklon": null }, +{ "label": "41/4", "node": 3515, "naklon": null }, +{ "label": "41/5", "node": 3559, "naklon": null }, +{ "label": "41/6", "node": 3509, "naklon": null }, +{ "label": "41/7", "node": 3524, "naklon": null }, +{ "label": "41/8", "node": 3518, "naklon": null }, +{ "label": "41/9", "node": 3182, "naklon": null }, +{ "label": "41/10", "node": 3187, "naklon": null }, +{ "label": "41/11", "node": 3195, "naklon": 0 }, +{ "label": "41/12", "node": 3857, "naklon": 0 }, +{ "label": "41/13", "node": 3183, "naklon": 0 }, +{ "label": "41/14", "node": 3177, "naklon": 0 }, +{ "label": "41/15", "node": 3189, "naklon": 0 }, +{ "label": "41/16", "node": 3186, "naklon": 0 }, +{ "label": "42/1", "node": 3178, "naklon": 0 }, +{ "label": "42/2", "node": 3219, "naklon": 0 }, +{ "label": "42/3", "node": 3475, "naklon": 0 }, +{ "label": "42/4", "node": 3175, "naklon": 0 }, +{ "label": "42/5", "node": 3222, "naklon": 0 }, +{ "label": "42/6", "node": 3221, "naklon": 0 }, +{ "label": "42/7", "node": 3181, "naklon": 0 }, +{ "label": "42/8", "node": 3180, "naklon": 0 }, +{ "label": "42/9", "node": 3218, "naklon": 0 }, +{ "label": "42/10", "node": 3176, "naklon": 0 }, +{ "label": "42/11", "node": 3174, "naklon": 0 }, +{ "label": "42/12", "node": 3220, "naklon": 0 }, +{ "label": "42/13", "node": 3533, "naklon": null }, +{ "label": "42/14", "node": 3543, "naklon": null }, +{ "label": "42/15", "node": 3554, "naklon": null }, +{ "label": "42/16", "node": 3549, "naklon": null }, +{ "label": "43/1", "node": 2857, "naklon": 5 }, +{ "label": "43/2", "node": 2752, "naklon": 5 }, +{ "label": "43/3", "node": 2753, "naklon": 5 }, +{ "label": "43/4", "node": 3024, "naklon": 5 }, +{ "label": "43/5", "node": 2754, "naklon": 5 }, +{ "label": "43/6", "node": 4423, "naklon": 5 }, +{ "label": "43/7", "node": 4368, "naklon": 5 }, +{ "label": "43/8", "node": 2978, "naklon": 5 }, +{ "label": "43/9", "node": 2868, "naklon": 5 }, +{ "label": "43/10", "node": 4377, "naklon": 5 }, +{ "label": "43/11", "node": 2757, "naklon": 5 }, +{ "label": "43/12", "node": 2970, "naklon": 5 }, +{ "label": "43/13", "node": 2758, "naklon": 5 }, +{ "label": "43/14", "node": 4378, "naklon": 5 }, +{ "label": "43/15", "node": 2759, "naklon": 5 }, +{ "label": "43/16", "node": 4342, "naklon": 5 }, +{ "label": "43/17", "node": 3026, "naklon": null }, +{ "label": "43/18", "node": 2986, "naklon": null }, +{ "label": "43/19", "node": 4343, "naklon": null }, +{ "label": "43/20", "node": 2760, "naklon": null }, +{ "label": "43/21", "node": 4379, "naklon": null }, +{ "label": "43/22", "node": 2971, "naklon": null }, +{ "label": "43/23", "node": 2761, "naklon": null }, +{ "label": "43/24", "node": 2762, "naklon": null }, +{ "label": "43/25", "node": 4339, "naklon": null }, +{ "label": "43/26", "node": 4380, "naklon": null }, +{ "label": "43/27", "node": 2975, "naklon": null }, +{ "label": "43/28", "node": 3003, "naklon": null }, +{ "label": "43/29", "node": 4338, "naklon": null }, +{ "label": "43/30", "node": 3002, "naklon": null }, +{ "label": "43/31", "node": 4345, "naklon": null }, +{ "label": "43/32", "node": 2979, "naklon": null }, +{ "label": "43/33", "node": 2989, "naklon": null }, +{ "label": "43/34", "node": 2996, "naklon": null }, +{ "label": "43/35", "node": 2972, "naklon": null }, +{ "label": "43/36", "node": 2988, "naklon": null }, +{ "label": "43/37", "node": 4344, "naklon": null }, +{ "label": "43/38", "node": 3022, "naklon": null }, +{ "label": "43/39", "node": 4341, "naklon": null }, +{ "label": "43/40", "node": 2983, "naklon": null }, +{ "label": "43/41", "node": 2995, "naklon": null }, +{ "label": "43/42", "node": 2763, "naklon": null }, +{ "label": "43/43", "node": 2764, "naklon": null }, +{ "label": "43/44", "node": 2765, "naklon": null }, +{ "label": "43/45", "node": 2766, "naklon": null }, +{ "label": "43/46", "node": 2767, "naklon": null }, +{ "label": "43/47", "node": 2768, "naklon": null }, +{ "label": "43/48", "node": 3018, "naklon": null }, +{ "label": "43/49", "node": 2982, "naklon": null }, +{ "label": "43/50", "node": 3019, "naklon": 0 }, +{ "label": "43/51", "node": 3013, "naklon": null }, +{ "label": "43/52", "node": 3007, "naklon": null }, +{ "label": "43/53", "node": 2980, "naklon": null }, +{ "label": "43/54", "node": 3011, "naklon": null }, +{ "label": "43/55", "node": 2672, "naklon": null }, +{ "label": "43/56", "node": 2673, "naklon": null }, +{ "label": "43/57", "node": 2674, "naklon": null }, +{ "label": "43/58", "node": 2675, "naklon": null }, +{ "label": "43/59", "node": 2676, "naklon": null }, +{ "label": "43/60", "node": 2677, "naklon": null }, +{ "label": "43/61", "node": 2678, "naklon": null }, +{ "label": "43/62", "node": 2679, "naklon": null }, +{ "label": "43/63", "node": 2680, "naklon": null }, +{ "label": "43/64", "node": 2840, "naklon": null }, +{ "label": "43/65", "node": 2682, "naklon": null }, +{ "label": "43/66", "node": 2683, "naklon": null }, +{ "label": "43/67", "node": 2684, "naklon": 0 }, +{ "label": "43/68", "node": 2685, "naklon": null }, +{ "label": "43/69", "node": 2686, "naklon": null }, +{ "label": "43/70", "node": 2687, "naklon": null }, +{ "label": "43/71", "node": 2688, "naklon": null }, +{ "label": "43/72", "node": 2689, "naklon": null }, +{ "label": "43/73", "node": 2690, "naklon": null }, +{ "label": "43/74", "node": 2691, "naklon": null }, +{ "label": "43/75", "node": 2692, "naklon": null }, +{ "label": "43/76", "node": 2693, "naklon": 0 }, +{ "label": "43/77", "node": 2694, "naklon": null }, +{ "label": "43/78", "node": 2695, "naklon": null }, +{ "label": "43/79", "node": 2696, "naklon": 0 }, +{ "label": "43/80", "node": 2697, "naklon": null }, +{ "label": "43/81", "node": 2698, "naklon": 0 }, +{ "label": "43/82", "node": 2699, "naklon": null }, +{ "label": "43/83", "node": 2700, "naklon": 0 }, +{ "label": "43/84", "node": 2744, "naklon": null }, +{ "label": "43/85", "node": 2745, "naklon": 0 }, +{ "label": "43/86", "node": 2746, "naklon": null }, +{ "label": "43/87", "node": 2747, "naklon": 0 }, +{ "label": "43/88", "node": 2748, "naklon": null }, +{ "label": "43/89", "node": 2749, "naklon": 0 }, +{ "label": "43/90", "node": 2841, "naklon": null }, +{ "label": "45/1", "node": 4237, "naklon": 5 }, +{ "label": "45/2", "node": 4226, "naklon": 5 }, +{ "label": "45/3", "node": 4242, "naklon": 5 }, +{ "label": "45/4", "node": 4179, "naklon": 5 }, +{ "label": "45/5", "node": 4247, "naklon": 5 }, +{ "label": "45/6", "node": 4245, "naklon": 5 }, +{ "label": "45/7", "node": 3872, "naklon": 5 }, +{ "label": "45/8", "node": 4175, "naklon": 5 }, +{ "label": "45/9", "node": 4236, "naklon": 5 }, +{ "label": "45/10", "node": 4170, "naklon": 5 }, +{ "label": "45/11", "node": 4238, "naklon": 5 }, +{ "label": "45/12", "node": 4246, "naklon": 5 }, +{ "label": "45/13", "node": 4166, "naklon": 5 }, +{ "label": "45/14", "node": 4227, "naklon": 5 }, +{ "label": "45/15", "node": 4171, "naklon": 5 }, +{ "label": "45/16", "node": 4180, "naklon": 5 }, +{ "label": "45/17", "node": 4244, "naklon": 5 }, +{ "label": "45/18", "node": 4199, "naklon": 5 }, +{ "label": "45/19", "node": 4239, "naklon": 5 }, +{ "label": "45/20", "node": 4207, "naklon": 5 }, +{ "label": "45/21", "node": 4223, "naklon": 5 }, +{ "label": "45/22", "node": 4230, "naklon": 5 }, +{ "label": "45/23", "node": 4233, "naklon": 5 }, +{ "label": "45/24", "node": 4222, "naklon": 5 }, +{ "label": "45/25", "node": 4217, "naklon": 5 }, +{ "label": "45/26", "node": 4243, "naklon": 5 }, +{ "label": "45/27", "node": 4200, "naklon": 5 }, +{ "label": "45/28", "node": 4228, "naklon": 5 }, +{ "label": "45/29", "node": 4211, "naklon": 5 }, +{ "label": "45/30", "node": 4234, "naklon": 5 }, +{ "label": "45/31", "node": 4235, "naklon": 5 }, +{ "label": "45/32", "node": 4203, "naklon": 5 }, +{ "label": "45/33", "node": 4240, "naklon": 5 }, +{ "label": "45/34", "node": 4224, "naklon": 5 }, +{ "label": "45/35", "node": 4232, "naklon": 5 }, +{ "label": "45/36", "node": 4231, "naklon": 5 }, +{ "label": "45/37", "node": 4161, "naklon": 5 }, +{ "label": "45/38", "node": 4225, "naklon": 5 }, +{ "label": "45/39", "node": 4241, "naklon": 5 }, +{ "label": "45/40", "node": 4229, "naklon": 5 }, +{ "label": "45/41", "node": 4221, "naklon": 5 }, +{ "label": "45/42", "node": 4212, "naklon": 5 }, +{ "label": "45/43", "node": 4216, "naklon": 5 }, +{ "label": "45/44", "node": 3864, "naklon": null }, +{ "label": "46/1", "node": 3806, "naklon": 5 }, +{ "label": "46/2", "node": 3813, "naklon": 5 }, +{ "label": "46/3", "node": 3815, "naklon": 5 }, +{ "label": "46/4", "node": 3807, "naklon": 5 }, +{ "label": "46/5", "node": 3895, "naklon": 5 }, +{ "label": "46/6", "node": 3809, "naklon": 5 }, +{ "label": "46/7", "node": 3820, "naklon": 5 }, +{ "label": "46/8", "node": 3805, "naklon": 5 }, +{ "label": "46/9", "node": 3894, "naklon": 0 }, +{ "label": "46/10", "node": 4055, "naklon": 0 }, +{ "label": "46/11", "node": 3812, "naklon": 5 }, +{ "label": "46/12", "node": 3822, "naklon": 5 }, +{ "label": "46/13", "node": 3821, "naklon": 5 }, +{ "label": "46/14", "node": 3808, "naklon": 5 }, +{ "label": "46/15", "node": 3799, "naklon": 5 }, +{ "label": "46/16", "node": 3816, "naklon": 5 }, +{ "label": "46/17", "node": 3751, "naklon": 5 }, +{ "label": "46/18", "node": 3814, "naklon": 5 }, +{ "label": "46/19", "node": 4044, "naklon": 0 }, +{ "label": "46/20", "node": 3931, "naklon": 0 }, +{ "label": "46/21", "node": 3902, "naklon": 5 }, +{ "label": "46/22", "node": 3916, "naklon": 5 }, +{ "label": "46/23", "node": 3892, "naklon": 5 }, +{ "label": "46/24", "node": 3914, "naklon": 5 }, +{ "label": "46/25", "node": 3898, "naklon": 5 }, +{ "label": "46/26", "node": 3897, "naklon": 5 }, +{ "label": "46/27", "node": 3885, "naklon": 5 }, +{ "label": "46/28", "node": 3906, "naklon": 5 }, +{ "label": "46/29", "node": 3930, "naklon": 0 }, +{ "label": "46/30", "node": 3936, "naklon": 0 }, +{ "label": "46/31", "node": 3860, "naklon": 5 }, +{ "label": "46/32", "node": 3841, "naklon": 5 }, +{ "label": "46/33", "node": 3873, "naklon": 5 }, +{ "label": "46/34", "node": 3854, "naklon": 5 }, +{ "label": "46/35", "node": 3939, "naklon": 5 }, +{ "label": "46/36", "node": 3858, "naklon": 5 }, +{ "label": "46/37", "node": 3940, "naklon": 5 }, +{ "label": "46/38", "node": 4035, "naklon": 5 }, +{ "label": "47/1", "node": 3373, "naklon": 0 }, +{ "label": "47/2", "node": 3374, "naklon": 0 }, +{ "label": "47/3", "node": 3384, "naklon": 0 }, +{ "label": "47/4", "node": 3385, "naklon": 0 }, +{ "label": "48/1", "node": 4051, "naklon": 5 }, +{ "label": "48/2", "node": 4041, "naklon": 5 }, +{ "label": "48/3", "node": 4056, "naklon": 5 }, +{ "label": "48/4", "node": 3875, "naklon": 5 }, +{ "label": "48/5", "node": 4061, "naklon": 5 }, +{ "label": "48/6", "node": 4047, "naklon": 5 }, +{ "label": "48/7", "node": 4060, "naklon": 5 }, +{ "label": "48/8", "node": 4059, "naklon": 5 }, +{ "label": "48/9", "node": 4058, "naklon": 5 }, +{ "label": "48/10", "node": 3635, "naklon": 5 }, +{ "label": "48/11", "node": 3640, "naklon": 5 }, +{ "label": "48/12", "node": 3747, "naklon": 5 }, +{ "label": "48/13", "node": 3629, "naklon": 5 }, +{ "label": "48/14", "node": 4048, "naklon": 5 }, +{ "label": "48/15", "node": 4063, "naklon": 5 }, +{ "label": "48/16", "node": 4062, "naklon": 5 }, +{ "label": "48/17", "node": 4043, "naklon": 5 }, +{ "label": "48/18", "node": 4052, "naklon": 5 }, +{ "label": "48/19", "node": 4042, "naklon": 5 }, +{ "label": "48/20", "node": 4053, "naklon": 5 }, +{ "label": "50/15A", "node": 4167, "naklon": null }, +{ "label": "50/15B", "node": 4159, "naklon": null }, +{ "label": "50/1", "node": 4183, "naklon": 0 }, +{ "label": "50/2", "node": 4157, "naklon": 0 }, +{ "label": "50/3", "node": 4160, "naklon": 0 }, +{ "label": "50/4", "node": 4173, "naklon": 0 }, +{ "label": "50/5", "node": 4177, "naklon": 0 }, +{ "label": "50/6", "node": 4174, "naklon": 0 }, +{ "label": "50/7", "node": 4178, "naklon": 0 }, +{ "label": "50/8", "node": 4195, "naklon": 0 }, +{ "label": "50/9", "node": 4169, "naklon": 0 }, +{ "label": "50/10", "node": 4162, "naklon": 0 }, +{ "label": "50/11", "node": 4158, "naklon": 0 }, +{ "label": "50/12", "node": 4182, "naklon": 0 }, +{ "label": "50/13", "node": 4194, "naklon": 0 }, +{ "label": "50/14", "node": 4184, "naklon": 0 }, +{ "label": "50/16", "node": 4197, "naklon": null }, +{ "label": "50/17", "node": 4164, "naklon": null }, +{ "label": "50/18", "node": 3306, "naklon": null }, +{ "label": "50/19", "node": 4168, "naklon": null }, +{ "label": "50/20", "node": 4193, "naklon": null }, +{ "label": "50/21", "node": 4187, "naklon": null }, +{ "label": "50/22", "node": 4163, "naklon": null }, +{ "label": "50/23", "node": 4165, "naklon": null }, +{ "label": "50/24", "node": 4185, "naklon": null }, +{ "label": "50/25", "node": 3904, "naklon": null }, +{ "label": "53/1", "node": 2619, "naklon": 0 }, +{ "label": "53/2", "node": 2623, "naklon": 0 }, +{ "label": "53/3", "node": 2617, "naklon": 0 }, +{ "label": "53/4", "node": 2622, "naklon": 0 }, +{ "label": "53/5", "node": 2618, "naklon": 0 }, +{ "label": "53/6", "node": 2626, "naklon": 0 }, +{ "label": "53/7", "node": 2869, "naklon": 0 }, +{ "label": "53/8", "node": 2613, "naklon": 0 }, +{ "label": "53/9", "node": 2608, "naklon": 0 }, +{ "label": "53/10", "node": 2611, "naklon": 0 }, +{ "label": "53/11", "node": 2598, "naklon": 0 }, +{ "label": "53/12", "node": 3528, "naklon": 0 }, +{ "label": "53/13", "node": 3545, "naklon": 0 }, +{ "label": "53/14", "node": 2620, "naklon": 0 }, +{ "label": "53/15", "node": 2612, "naklon": 0 }, +{ "label": "53/16", "node": 2615, "naklon": 0 }, +{ "label": "53/17", "node": 3722, "naklon": 0 }, +{ "label": "53/18", "node": 2624, "naklon": 0 }, +{ "label": "53/19", "node": 2609, "naklon": 0 }, +{ "label": "53/20", "node": 2625, "naklon": 0 }, +{ "label": "53/21", "node": 2602, "naklon": 0 }, +{ "label": "53/22", "node": 2610, "naklon": 0 }, +{ "label": "53/23", "node": 2599, "naklon": 0 }, +{ "label": "53/24", "node": 2605, "naklon": 0 }, +{ "label": "53/25", "node": 2593, "naklon": 0 }, +{ "label": "53/26", "node": 3074, "naklon": 0 }, +{ "label": "53/27", "node": 2740, "naklon": 0 }, +{ "label": "53/28", "node": 2614, "naklon": 0 }, +{ "label": "53/29", "node": 2601, "naklon": 0 }, +{ "label": "53/30", "node": 4196, "naklon": 0 }, +{ "label": "53/31", "node": 2607, "naklon": 0 }, +{ "label": "53/32", "node": 2582, "naklon": 0 }, +{ "label": "53/33", "node": 2594, "naklon": 0 }, +{ "label": "53/34", "node": 2589, "naklon": 0 }, +{ "label": "53/35", "node": 2596, "naklon": 0 }, +{ "label": "53/36", "node": 2603, "naklon": 0 }, +{ "label": "53/37", "node": 2597, "naklon": 0 }, +{ "label": "53/38", "node": 2590, "naklon": 0 }, +{ "label": "53/39", "node": 2581, "naklon": 0 }, +{ "label": "53/40", "node": 2583, "naklon": 0 }, +{ "label": "53/41", "node": 2580, "naklon": 0 }, +{ "label": "53/42", "node": 2579, "naklon": 0 }, +{ "label": "53/43", "node": 2797, "naklon": 0 }, +{ "label": "53/44", "node": 2577, "naklon": 0 }, +{ "label": "53/45", "node": 2586, "naklon": 0 }, +{ "label": "53/46", "node": 2588, "naklon": 0 }, +{ "label": "53/47", "node": 2591, "naklon": 0 }, +{ "label": "53/48", "node": 2592, "naklon": 0 }, +{ "label": "53/49", "node": 2573, "naklon": 0 }, +{ "label": "53/50", "node": 2595, "naklon": 0 }, +{ "label": "53/51", "node": 2587, "naklon": 0 }, +{ "label": "53/52", "node": 2578, "naklon": 0 }, +{ "label": "53/53", "node": 2574, "naklon": 0 }, +{ "label": "53/54", "node": 2571, "naklon": 0 }, +{ "label": "53/55", "node": 2570, "naklon": 0 }, +{ "label": "53/56", "node": 2576, "naklon": 0 }, +{ "label": "53/57", "node": 2881, "naklon": 0 }, +{ "label": "53/58", "node": 2575, "naklon": 0 }, +{ "label": "53/59", "node": 2572, "naklon": 0 }, +{ "label": "53/60", "node": 2569, "naklon": 0 }, +{ "label": "55/1", "node": 4324, "naklon": 0 }, +{ "label": "55/2", "node": 4319, "naklon": 0 }, +{ "label": "55/3", "node": 4327, "naklon": 0 }, +{ "label": "55/4", "node": 4333, "naklon": 0 }, +{ "label": "55/5", "node": 4332, "naklon": 0 }, +{ "label": "55/6", "node": 4320, "naklon": 0 }, +{ "label": "55/7", "node": 4317, "naklon": 0 }, +{ "label": "55/8", "node": 4318, "naklon": 0 }, +{ "label": "55/9", "node": 4328, "naklon": 0 }, +{ "label": "55/10", "node": 4323, "naklon": 0 }, +{ "label": "55/11", "node": 4325, "naklon": 0 }, +{ "label": "55/12", "node": 4326, "naklon": 0 }, +{ "label": "55/13", "node": 4316, "naklon": 0 }, +{ "label": "55/14", "node": 4322, "naklon": 0 }, +{ "label": "55/15", "node": 4331, "naklon": 0 }, +{ "label": "55/16", "node": 4321, "naklon": 0 }, +{ "label": "55/17", "node": 4315, "naklon": 0 }, +{ "label": "55/18", "node": 4329, "naklon": 0 }, +{ "label": "55/19", "node": 4334, "naklon": 0 }, +{ "label": "55/20", "node": 4330, "naklon": 0 } +]; + +module.exports = { naklony }; diff --git a/RVO2/databases/modbus_config.js b/RVO2/databases/modbus_config.js new file mode 100755 index 0000000..b73116a --- /dev/null +++ b/RVO2/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/RVO2/databases/nodes.table b/RVO2/databases/nodes.table new file mode 100755 index 0000000..0dd827b --- /dev/null +++ b/RVO2/databases/nodes.table @@ -0,0 +1,28 @@ +node:number|pole_number:string|node_type:string|tbname:string|line:number|profile:string|processed:boolean|status:boolean|time_of_last_communication:number ++|3375|24|NEMA|nJL5lPMwBx23YpqRe0rlDV7damXvWVbOrD4gNzy8|1||1|1|1760573771961|............. ++|3240|18|NEMA|PLBJzmK1r3Gynd6OW0gGbM0e5wV4vx9bDEqNgYR8|1||1|1|1760573768542|............. ++|3380|26|NEMA|gYbDLqlyZVoRerQpB72rPj7WJnwM5z24POKa8Exj|1||1|1|1760573775700|............. ++|2823|15|NEMA|EjgWGnXaLy9opPOz20n6K4086BlYM3w1deVQvbKr|1||1|1|1760573771753|............. ++|3381|25|NEMA|XMBbew5z4ELrZa2mRAd5wO08vPN6gy3DdVYlpKjq|1||1|1|1760573775892|............. ++|3382|21|NEMA|E6Kg9oDnLWyzPRMva7vrpa7Jxp4VG58qO2w1lZYe|1||1|1|1760573776563|............. ++|3756|16|NEMA|wvKJdZML6mXP4DzWBAXW9W7jxNloa5g23Ve9Y1ry|1||1|1|1760573814497|............. ++|3803|4|NEMA|PjLblDgRBO6WQqnxmkJ1Zr0Jv3ewZN4p5a89yKdY|1||1|1|1760573782923|............. ++|3754|7|NEMA|gRoJEyXVx4qD9er287L45v7wBzGldaPjLWQKm3Mv|1||1|1|1760573779951|............. ++|3818|6|NEMA|d5xjWYMwEJon6rLlK7yEWm7qgV4DaOeNB9ZX3Gzb|1||1|1|1760573786246|............. ++|3823|2|NEMA|Z5KyJe9nEg1QNbWlX0w45BkoDjBLdqzR83VGv624|1||1|1|1760573786694|............. ++|3826|12|NEMA|ZmRwd93QL4gaezxEbAxW9971prn2XjlPvGyqJ6BO|1||1|1|1760573789921|............. ++|3827|10|NEMA|B5EoxeMVp4zwr8nqW0GB2pARjvD1PNamOGbLg63Z|1||1|1|1760573790752|............. ++|3834|13|NEMA|eod9aRWLVl34Gx1Dn7VoJaA2rz6qjgmpEXwQJN5Z|1||1|1|1760573792846|............. ++|3838|14|NEMA|3a5oqJN1bgnx4Ol9dk86bBAByE6jQ8mKDWMpGrLV|1||1|1|1760573794076|............. ++|3905|3|NEMA|1JMYvnx2RzKEo4aWQ7DGq5kL8yZV3m9NBePXbrdj|1||1|1|1760573797911|............. ++|3915|8|NEMA|K94XLav1glVRnyQ6r01PdzAme3YJwBxM5oOzdP2j|1||1|1|1760573798310|............. ++|4220|11|NEMA|aw4eELG2DlPMdn1JW0BMnnAqQXOZRN3xB5yp8VKr|1||1|1|1760573798518|............. ++|3828|27|NEMA|ZmRwd93QL4gaezxEbAxWqw71prn2XjlPvGyqJ6BO|1||1|1|1760573792622|............. ++|3377|28|NEMA|eod9aRWLVl34Gx1Dn7VoODA2rz6qjgmpEXwQJN5Z|1||1|1|1760573772457|............. ++|3800|1|NEMA|3JjOWdylwgNLzxVab7NaWnkZ2vG64rq8PEB5QmDo|1||1|1|1760573782156|............. ++|3843|9|NEMA|d9x2V5LGYBzXp4mMRAOmzjkPloaqJwnQj6DgrNe3|1||1|1|1760573795178|............. ++|3378|17|NEMA|Nzp2OoJlqn6r1ZgvdA3GndAabBwP5G4eE3RQmyxD|1||1|1|1760573775525|............. ++|3639|19|NEMA|52dD6ZlV1QaOpRBmbAqKwgkKnGzWMLj4eJq38Pgo|1||1|1|1760573779759|............. ++|3383|22|NEMA|roKgWqY95V3mXMRzyAjmMD7bLjexpJPvaGDBw826|1||1|1|1760573809751|............. ++|3817|5|NEMA|dz4ojlpP85JMgDLZWkQJNG7aKYqQexEr62GXRV1y|1||1|1|1760573790545|............. ++|3232|20|NEMA|rDbQ84xzwgdqEoPm3kbJZ3k9anOZY1RXyBv2LVM6|1||1|1|1760573766928|............. diff --git a/RVO2/databases/nodes_original/.nodes_original.table.swp b/RVO2/databases/nodes_original/.nodes_original.table.swp new file mode 100755 index 0000000000000000000000000000000000000000..7707a1a4d75c4cb9a7f443f61b0fc0110cb0c45d GIT binary patch literal 12288 zcmeI2%Z{Z)9L5VVhx+PY-;b)Va&k^e2j5y(=qW>O#|ISk&!<}P=x>U8@-apI z(%f`6`{%DXz5}%I)osHA_T>$KKRSH&bJb3_`7q|gvkX7SDZb5bpEYfk-~QANH^ohZ zs~2vcZmp{P<(-qKga9G%3IdP6hk&8?MxS4QcJ;JrKMB;v+NV#bdac?4!)@z=k7xvL<8hpIJ- zu#ZJ9fOTZ~>mrr4r3k56=5wdJBi0moLf~E{9JLzV;0S_DkTsyTt{OV zq|TtQg}pB5QcK|XTCOSUYi%$C)RrdWoscfH)S`243fOTLQ$_9VBKFbs-T3HTQ^cua z_SKREt)CBGCktS3OCi*o$>LVPx{iU7I+u5q00M_AwJbudiLkkdZRa{Gpc~#`X~fG_ zY{7}i^1vHYW4MeDF?+4ZlGA+RR#r8K1cTa_GH!BcG`colEKtdUxay3uzgK}>rSe80 zwn}4$%j){ph=pJkMr+bd!|03?_!Hwu%yYE_1}K10u_p*7yC(C#VY<}!?}N!8niAI!=S7B#Gez6e+a zJGm{3Nd&buy{PV}C!De9x!9-$4)nFx}9AsI1&kTY84>2exMmQTctXOvA!)fi))=VbHQ1~0&vVGJh8cI zYCzeRWY#cxNXu5!NWB+1iEqPM=9Ufx`)uDA7J7KLexwd#4{jE2Nqso`zo~JT@UMAp z9L^wmXeobrXAf^zzBq$|xMwK`GKEj7fbp=?`Es2~y)hLhqtVvTGD|ksdx+ek-Exuo zVb2} +
+
+
Hostname or IP address (if not empty - setting will override db setting)
+
+
+
Port
+
+
+
+
+
@(Client id)
+
+
+
topic
+
+
+ `; + + + +const { promisifyBuilder } = require('./helper/db_helper'); +const fs = require('fs'); +const mqtt = require('mqtt'); +const nosql = NOSQL('tbdatacloud'); + +const SEND_TO = { + debug: 0, + rpcCall: 1, +} + +//CONFIG +let saveTelemetryOnError = true;//backup_on_failure overrides this value +//------------------------ + +const noSqlFileSizeLimit = 4194304;//use 5MB - 4194304 +let insertNoSqlCounter = 0; +let insertBackupNoSqlCounter = 0; +let processingData = false; + +let backup_on_failure = true;//== saveTelemetryOnError - create backup client send failure +let restore_from_backup = 50; //how many rows process at once? +let restore_backup_wait = 3;//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; + + +exports.install = function(instance) { + + var client; + var opts; + var clientReady = false; + + let o = {}; //options + + function main() { + loadSettings(); + } + + //set opts according to db settings + function loadSettings() { + + o = instance.options; + if (!o.topic) o.topic = FLOW.GLOBALS.settings.cloud_topic; + + opts = { + host: o.host, + port: o.port, + clientId: o.clientid, + username: o.username, + rejectUnauthorized: false, + resubscribe: false + }; + + console.log("wsmqttpublich -> loadSettings from instance.options", o); + + if (!o.topic) { + instance.status("Not configured", "white"); + console.log("Cloud mqtt connect: no topic selected"); + return; + } + + connectToTbServer(); + } + + function connectToTbServer() { + var url = "mqtt://" + opts.host + ":" + opts.port; + console.log("MQTT URL: ", url); + + client = mqtt.connect(url, opts); + + client.on('connect', function() { + client.subscribe(`${o.topic}_backward`, (err) => { + if (!err) { + console.log("MQTT subscribed"); + } + }); + instance.status("Connected", "green"); + clientReady = true; + sendClientError = true; + }); + + client.on('reconnect', function() { + instance.status("Reconnecting", "yellow"); + clientReady = false; + }); + + client.on('message', function(topic, message) { + // message is type of buffer + message = message.toString(); + if (message[0] === '{') { + TRY(function() { + + message = JSON.parse(message); + if (message.hasOwnProperty("device") && message.hasOwnProperty("data") && message.data.hasOwnProperty("id")) { + client.publish(`${o.topic}_forward`, `{"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 } }); + } + + }, () => instance.debug('MQTT: Error parsing data', message)); + } + + instance.send(SEND_TO.rpcCall, { "topic": o.topic, "content": message }); + }); + + client.on('close', function() { + clientReady = false; + + instance.status("Disconnected", "red"); + instance.send(SEND_TO.debug, { "message": "Client CLOSE signal received !" }); + }); + + client.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) { + console.log('MQTT client error', err); + sendClientError = false; + } + clientReady = false; + }); + + } + + + instance.on('0', function(data) { + + if (clientReady) { + //do we have some data in backup file? if any, process data from database + if (saveTelemetryOnError) { + //read telemetry data and send back to server + if (!processingData) processDataFromDatabase(); + } + + let stringifiedJson = JSON.stringify(data.data) + client.publish(`${o.topic}_forward`, stringifiedJson, { qos: 1 }); + } + 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 (saveTelemetryOnError && o.topic) { + //create new file from tbdata.nosql, if file size exceeds given limit, and clear tbdata.nosql + makeBackupFromDbFile(); + + //write to tb + data.data.id = UID(); + nosql.insert(data.data); + } + } + }); + + instance.on("1", _ => { + main(); + }) + + instance.close = function(done) { + if (clientReady) { + client.end(); + } + }; + + + function getDbBackupFileCounter(type) { + var files = fs.readdirSync(__dirname + "/../databases"); + + let counter = 0; + for (var i = 0; i < files.length; i++) { + + if (files[i] == "tbdatacloud.nosql") continue; + + if (files[i].endsWith(".nosql")) { + + let pos = files[i].indexOf("."); + if (pos > -1) { + + let fileCounter = counter; + let firstDigit = files[i].slice(0, pos); + + fileCounter = parseInt(firstDigit); + if (isNaN(fileCounter)) fileCounter = 0; + //console.log("getDbBackupFileCounter digit:", files[i], firstDigit, fileCounter, isNaN(fileCounter), type); + + if (type == "max") { + if (fileCounter > counter) { + counter = fileCounter; + } + } + else if (type == "min") { + if (counter == 0) counter = fileCounter; + + if (fileCounter < counter) { + counter = fileCounter; + } + } + } + } + + } + + if (type == "max") counter++; + + return counter; + } + + const makeBackupFromDbFile = async () => { + + if (!saveTelemetryOnError) return; + + //to avoid large file: tbdata.nosql + + //init value is 0! + if (insertNoSqlCounter > 0) { + --insertNoSqlCounter; + return; + } + + insertNoSqlCounter = 100; + + let source = __dirname + "/../databases/tbdatacloud.nosql"; + + var stats = fs.statSync(source); + var fileSizeInBytes = stats.size; + + if (fileSizeInBytes > noSqlFileSizeLimit) { + + let counter = 1; + counter = getDbBackupFileCounter("max"); + + let destination = __dirname + "/../databases/" + counter + "." + "tbdatacloud.nosql"; + + //make backup file + fs.copyFileSync(source, destination); + //fs.renameSync(p, p + "." + counter); + + //clear tbdata.nosql + fs.writeFileSync(source, ""); + fs.truncateSync(source, 0); + + } + } + + const processDataFromDatabase = async () => { + + if (restore_from_backup <= 0) return; + + //calculate diff + const now = new Date(); + let currentTime = now.getTime(); + let diff = currentTime - lastRestoreTime; + + if ((diff / 1000) < restore_backup_wait) { + //console.log("*********restore_backup_wait", diff, restore_backup_wait); + return; + } + + processingData = true; + + //get filename to process + let counter = getDbBackupFileCounter("min"); + + //we have some backup files + let dataBase = 'tbdata'; + + var nosql; + if (counter == 0) dataBase = 'tbdatacloud'; + else dataBase = counter + "." + 'tbdatacloud'; + + nosql = NOSQL(dataBase); + + //select all data - use limit restore_from_backup + let records = await promisifyBuilder(nosql.find().take(restore_from_backup)); + + for (let i = 0; i < records.length; i++) { + if (clientReady) { + + let item = records[i]; + let id = item.id; + + if (id !== undefined) { + //console.log("------------processDataFromDatabase - remove", id, dataBase, i); + + try { + + let message = JSON.parse(JSON.stringify(item)); + delete message.id; + client.publish(`${o.topic}_forward`, JSON.stringify(message), { qos: 1 }); + + //remove from database + await promisifyBuilder(nosql.remove().where("id", id)); + + } catch (error) { + //process error + console.log("processDataFromDatabase", error); + } + + } + + } + else { + processingData = false; + return; + } + } + + if (records.length > 0) { + //clean backup file + if (counter > 0) nosql.clean(); + } + + //no data in db, remove + if (records.length == 0) { + if (counter > 0) nosql.drop(); + } + + const d = new Date(); + lastRestoreTime = d.getTime(); + + processingData = false; + + } + + instance.on('options', main); + +}; diff --git a/RVO2/flow/cmd_manager.js b/RVO2/flow/cmd_manager.js new file mode 100755 index 0000000..25912df --- /dev/null +++ b/RVO2/flow/cmd_manager.js @@ -0,0 +1,3071 @@ +exports.id = 'cmd_manager'; +exports.title = 'CMD Manager'; +exports.group = 'Worksys'; +exports.color = '#5D9CEC'; +exports.version = '0.0.3'; +exports.output = ['red', 'blue', 'yellow', 'blue', 'white', 'green']; +exports.input = 3; +exports.icon = 'cloud-upload'; + +exports.html = ` +
+
+
+
RPC - run RPC calls

+
+
+
@(User)
+
+
+
@(Password)
+
+
+
@(My edge)
+
+
+
+`; +exports.readme = `Manager for CMD calls`; + + +exports.install = function(instance) { + + 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, isEmptyObject, emptyJsObject, writeToFile, addToArrayIfUnique } = require('./helper/utils'); + const bitwise = require('bitwise'); + + var SunCalc = require('./helper/suncalc'); + const DataToTbHandler = require('./helper/DataToTbHandler'); + const errorHandler = require('./helper/ErrorToServiceHandler'); + const { sendNotification } = require('./helper/notification_reporter'); + const process = require('process'); + const { errLogger, logger, monitor } = require('./helper/logger'); + + //for accelerometer purposes + const { naklony } = require("../databases/accelerometer_db"); + + const dbNodes = TABLE("nodes"); + const dbRelays = TABLE("relays"); + + let GLOBALS; + let SETTINGS; + let rsPort; + let tbHandler; + + // runTasks intervals + const SHORT_INTERVAL = 30; + const LONG_INTERVAL = 300; + + //send data to following instances: + const SEND_TO = { + debug: 0, + tb: 1, + http_response: 2, + dido_controller: 3, + infoSender: 4, + dailyReport: 5 + } + + 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 + } + + 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 sendNodeReadout = null; // interval for sending agregate data from node + + 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["1"] = minutes; // dimming + priorities["76"] = minutes; // power + + minutes = 5; + priorities["75"] = minutes; // current + priorities["79"] = minutes; // energy + priorities["87"] = minutes; // aktualny cas + //priorities["84"] = minutes; //accelerometer + + minutes = 10; + priorities["74"] = minutes; // voltage + priorities["77"] = minutes; // power factor + priorities["78"] = minutes; // frequency + + minutes = 60; + priorities["0"] = minutes; // statecode + priorities["6"] = minutes; // dusk + priorities["7"] = minutes; // dawn + priorities["8"] = minutes; // profile + + minutes = 60 * 24; + priorities["89"] = minutes; // verzia fw + priorities["80"] = minutes; // lifetime + + //prikazy kt sa budu spustat na dany node - see config.js in terminal-oms.app. (1 - dimming) + let listOfCommands = [0, 1, 6, 7, 8, 74, 75, 76, 77, 78, 79, 80, 87, 89]; + + 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; + + // holds dusk, dawn (and more) values + let sunCalcResult; + + //helper container for counting resolved group of commands (commands related to set profile) + let cmdCounter = {};//key is node, value is counter + + //TODO: is this set working?? According to previous checks, sets do not work + //if sending of profile to node fails, we send notification and push node into set, so we do not send notification twice + const nodeProfileSendFail = new Set(); + + //we expect to get current temperature in Senica from senica-prod01 + let temperatureInSenica = null; + let accelerometerInterval = null; + + //NOTE: daily reports senica: + //rvo_is_on status, we monitor all nodes - if true, power and dimming should be not 0, if false, 24/7 nodes should be 0, other rvo should not respond + let rvo_is_on; + let previous_rvo_is_on_value; + let handleDailyReport; //setInterval for dailyReportHandler function + let dailyReport = {}; //data needed for daily report + let reportToSend = {}; //final report which we send to cloud + let breakerCounter = null; // status of breakers after flow starts is not in report + let rvoPeriod; // interval of checking dusk dawn and if rvo_is_on + let initialReportStatus = false; + + const DAILY_REPORT_HANDLER_TIME = 3_600_000; + const SET_SUNCALC_RESULT_TIME = 3_600_000; + const SET_RVO_PERIOD_TIME = 300_000; + const ADD_NODE_TO_REPORT_TIME = 3_600_000; + + //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); + + let now = new Date(); + console.log("Cmd-mngr installed", now.toLocaleString("sk-SK")); + + sunCalcResult = calculateDuskDawn(); + + handleRsPort(); + + customTasksInterval = setInterval(reportEdgeDateTimeAndNumberOfLuminaires, 120_000); + setTimeout(reportEdgeDateTimeAndNumberOfLuminaires, 4000); + + //dailyReport related + emptyReportToSend(); + breakerCounter = Object.keys(relaysData).length - 1; // we get number of lines (breakers) except of line 0 + rvoPeriod = setInterval(setRvoPeriod, SET_RVO_PERIOD_TIME); + setTimeout(setRvoPeriod, 3000); + setInterval(setSunCalcResult, SET_SUNCALC_RESULT_TIME); + handleDailyReport = setInterval(dailyReportHandler, DAILY_REPORT_HANDLER_TIME); + + + setCorrectTime = setInterval(setCorrectPlcTimeOnceADay, 60000 * 60); // 1 hour + setCorrectPlcTimeOnceADay(); + + sendNodeReadout = setInterval(sendNodesData, 150_000); + accelerometerInterval = setInterval(accelerometerData, 60000 * 30); //30 min + } + + + 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" + //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 + // if node regular readout does not respond, we repeat request + params.repeatCounter = 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-mngr: 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.byte4 = 96; + params.recipient = 1; + params.register = 8; + params.rw = 1;//write + params.timestamp = timestamp; + 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.byte4 = 96; + params.recipient = 1; + params.register = 8; + params.rw = 1;//write + params.timestamp = timestamp; + 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). + */ + + 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.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.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 + { + + logger.debug("processNodeProfile: Threshold lux level for DUSK/DAWN", node); + + let params = getParams(); + params.type = "set_node_profile"; + params.address = node; + params.register = 96; + params.recipient = 1; + params.rw = 1;//write + params.timestamp = timestamp; + 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(); + params.type = "set_node_profile"; + params.address = node; + params.register = 97; + params.recipient = 1; + params.rw = 1;//write + params.timestamp = timestamp; + 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.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); + + 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); + + console.log("proces profile finished *********************") + } + + + 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; + }); + } + + + 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) { + for (let k in nodesData) { + 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`); + } + } + } + + + function loadRelaysData(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 (value.contactor == 1) processAllNodeProfilesOnLine(value.line); + } + } + + + function reportOnlineNodeStatus(line) { + //Po zapnutí línie broadcastovo aktualizovať predtým čas a o 3 sek neskor - status, brightness + + logger.debug("Cmd-mngr: ----->reportOnlineNodeStatus for line", line); + + const d = new Date(); + + // broadcast actual time + let params = getParams(); + params.address = 0xffffffff;//Broadcast + params.byte1 = d.getHours(); + params.byte2 = d.getMinutes(); + params.recipient = 2;//2 broadcast, address = 0 + params.register = 87;//Actual time + params.rw = 1;//write + params.type = "node-onetime-write"; + params.timestamp = d.getTime() + 30000; + params.info = "run broadcast: Actual time"; + //params.debug = true; + + tasks.push(params); + + let sec = 3; + setTimeout(function() { + //Po zapnutí línie - spraviť hromadný refresh stavu práve zapnutých svietidiel + + let time = Date.now(); + + for (let k in nodesData) { + + //potrebujem nody k danej linii + 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].node_status_before_offline === true || nodesData[k].status === true) { + status = "OK"; + nodesData[k].time_of_last_communication = time; + } + + nodesData[k].readout.status = status; + + updateNodeStatus(k, status === "OK" ? true : false); + if (nodesData[k].hasOwnProperty("node_status_before_offline")) delete nodesData[k].node_status_before_offline; + sendTelemetry({ status: status }, tbname, time); + + //vyreportovanie dimming, current, input power pre liniu pre vsetky nody + //Prud + { + let params = getParams(); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 75;//prud + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = time + 4000; + params.info = 'read current'; + //params.debug = true; + tasks.push(params); + } + + //vykon + { + let params = getParams(); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 76;//výkon + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = time + 4100; + params.info = 'read power'; + //params.debug = true; + + tasks.push(params); + } + //dimming + { + let params = getParams(); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 1;//dimming + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = time + 4200; + params.info = 'read dimming'; + //params.debug = true; + + tasks.push(params); + } + + } + } + + }, sec * 1000); + } + + + function reportOfflineNodeStatus(line) { + + logger.info("Cmd-mngr: ------>reportOffLineNodeStatus for line ", line); + + values = {}; + values["dimming"] = 0;//brightness + values["power"] = 0;//výkon + values["current"] = 0;//prúd + values["status"] = "OFFLINE"; + + const date = Date.now(); + + Object.keys(nodesData).forEach(node => { + + //potrebujem nody k danej linii + if (line == nodesData[node].line || line == undefined) { + + let tbname = nodesData[node].tbname; + let nodeStatus = nodesData[node].status; + + //in case we have reported offline node status, we return (continue with next node) + if (nodeStatus === "OFFLINE") return; + + nodesData[node].node_status_before_offline = nodeStatus; + nodesData[node].status = "OFFLINE"; + nodesData[node].readout = {}; + + sendTelemetry({ ...values }, tbname, date); + } + }); + + } + + + function turnLine(onOrOff, line, info) { + let obj = { + line: line, + command: onOrOff, + info: info + }; + + //to assure, handleDailyReportFunction do not run before rvo_is_on variable changes. So after every line switch we reset the timer + clearInterval(handleDailyReport); + handleDailyReport = setInterval(dailyReportHandler, DAILY_REPORT_HANDLER_TIME); + + //logger.debug("linia", line, obj); + instance.send(SEND_TO.dido_controller, obj); + } + + + 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"; + 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]) { + //CRC_ERROR + message = "NOK"; + error = "CRC_ERROR c1"; + instance.send(SEND_TO.debug, "CRC_ERROR c1"); + } + + 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") { + instance.send(SEND_TO.debug, bytes); + instance.send(SEND_TO.debug, "RESPONSE " + type + " - " + bytes[4]); + + //logger.debug(SEND_TO.debug, "RESPONSE " + type + " - " + bytes[4], bytes); + + error = "type is: " + type; + + message = "NOK"; + } + + return { message, type, error }; + } + + + //BUILD TASKS// + function buildTasks(params) { + + //return; + console.log("buidTAaasks start ****************", params); + monitor.info("buildTasks - params", params); + + let processLine; //defined line + let init = false; + let processLineProfiles = true; + let processBroadcast = true; + let processNodes = true; + + if (params == undefined) { + init = true; + tasks = []; + logger.debug("-->buildTasks clear tasks"); + } + else { + processLineProfiles = params.processLineProfiles; + processBroadcast = false; + processNodes = false; + + processLine = params.line; + } + + let now = new Date(); + + //process line profiles + if (processLineProfiles) { + + let keys = Object.keys(relaysData); + + for (let i = 0; i < keys.length; i++) { + + let line = parseInt(keys[i]); + let profilestr = relaysData[line].profile; + + if (processLine != undefined) { + if (processLine != line) continue; + } + + try { + + /** + * we process line profiles: timepoints, astro clock, lux_sensor, offsets ... + */ + if (profilestr === "") throw ("Profile is not defined"); + let profile = JSON.parse(profilestr); + 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; + + // add name to regular profile timepoint and delete unused end_time key: + time_points.forEach(point => { + point.name = "profileTimepoint" + delete point.end_time; + }); + + //monitor.info("buildTasks: time_points", time_points); + + + /** + * 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 astro clock true, we remove all regular profile points + time_points = []; + + //TODO: when astro clock == true, is offset calculated ??? + //let duskAstroClockOffset = profile.dusk_astro_clock_offset; + //let dawnAstroClockOffset = profile.dawn_astro_clock_offset; + //console.log("line astro clock offsets dusk a dawn: ", duskAstroClockOffset, dawnAstroClockOffset); + // maybe add dusk dawn offset to calculateDuskDawn ?? what dusk dawn will be if dawn_lux_sensor == true?? + //let sunCalcResult = calculateDuskDawn(new Date(), line, duskAstroClockOffset, dawnAstroClockOffset); + + 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 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); + + 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); + + 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(':'); + + let ad = new Date(); + ad.setHours(parseInt(ahours), parseInt(aminutes), 0); + + let bd = new Date(); + bd.setHours(parseInt(bhours), parseInt(bminutes), 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++) { + + let start_time = new Date(); + let [hours, minutes] = time_points[t].start_time.split(':'); + start_time.setHours(parseInt(hours), parseInt(minutes), 0); + + //task is in 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(); + params.type = "relay"; + params.line = parseInt(line); + params.value = time_points[t].value; + params.tbname = relaysData[line].tbname; + params.timestamp = start_time.getTime(); + + // 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; + + //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)) { + 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; + + params.debug = true; + + //turn on/off line + tasks.push(params); + monitor.info("TimePoint params: ", params.info, start_time); + } + + monitor.info("-->time_points final", line, time_points); + + //ensure to turn on/off according to calculated currentValue + let params = getParams(); + params.type = "relay"; + params.line = parseInt(line); + params.tbname = relaysData[line].tbname; + params.value = currentValue; + params.timestamp = i; + params.debug = true; + + //logger.debug(now.toLocaleString("sk-SK")); + 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; + + tasks.push(params); + + } catch (error) { + if (profilestr !== "") { + //errLogger.error(profilestr, error); + console.log(`Cmd_mngr: Unable to process line profile ${line}. Error: `, error); + errorHandler.sendMessageToService(profilestr + "-" + error, 0, "js_error"); + } else { + turnLine("off", line, "No line profile. Switching it off on startup"); + } + } + + } + //logger.debug("tasks:"); + //logger.debug(tasks); + } + + + //NOTE: PROCESS DEFAULT BROADCASTS - Time of dusk, Time of dawn, Actual Time + if (processBroadcast) { + + let d = new Date(); + let time = d.getTime(); + //let sunCalcResult = calculateDuskDawn(); + + { + let params = getParams(); + + params.address = 0xffffffff;//broadcast + params.byte1 = sunCalcResult["dusk_hours"]; + params.byte2 = sunCalcResult["dusk_minutes"]; + params.recipient = 2;//2 broadcast, + params.register = 6;//Time of dusk + params.rw = 1;//write + params.type = "node-regular-write"; + params.timestamp = time + 60000; + params.addMinutesToTimestamp = 60 * 3; //kazde 3 hodiny zisti novy dusk + params.info = "Broadcast-duskTime"; + + tasks.push(params); + } + + { + let params = getParams(); + + params.address = 0xffffffff;//broadcast + params.byte1 = sunCalcResult["dawn_hours"]; + params.byte2 = sunCalcResult["dawn_minutes"]; + params.recipient = 2; //2 broadcast + params.register = 7;//Time of dawn + params.rw = 1;//write + params.type = "node-regular-write"; + params.timestamp = time + 60001; + params.addMinutesToTimestamp = 60 * 3; //kazde 3 hodiny zisti novy dawn + params.info = "Broadcast-dawnTime"; + + tasks.push(params); + } + + { + let params = getParams(); + + params.address = 0xffffffff;//broadcast + params.byte1 = d.getHours(); + params.byte2 = d.getMinutes(); + params.recipient = 2; //2 broadcast + params.register = 87;//Actual time + params.rw = 1;//write + params.type = "node-regular-write"; + params.timestamp = time + 60002; + params.addMinutesToTimestamp = 5; + params.info = "run broadcast: Actual time"; + + tasks.push(params); + } + + } + + //process nodes & tasks - read node's data + if (processNodes) { + + let time = Date.now(); + + for (let k in nodesData) { + let address = parseInt(k); + let tbname = nodesData[k].tbname; + let register = 0; + + for (let i = 0; i < listOfCommands.length; i++) { + + register = listOfCommands[i]; + let addMinutesToTimestamp = priorities[register]; + + let params = getParams(); + + params.address = address; + params.recipient = 1; + params.register = register; + params.type = register == 1 ? "node-dimming-read" : "node-regular-read"; + params.tbname = tbname; + params.timestamp = time + 5000 + i * 500 + addMinutesToTimestamp * 1000; //to make slight time difference + params.addMinutesToTimestamp = addMinutesToTimestamp; + params.info = "Node regular read command"; + + tasks.push(params); + } + + } + } + + + //niektore ulohy sa vygeneruju iba 1x pri starte!!! + if (!init) return; + + + //Master node FW version - modifies SETTINGS.masterNodeIsResponding + { + let params = getParams(); + params.type = "cmd-master"; + params.register = 4; + params.address = 0; + params.timestamp = 0; + params.addMinutesToTimestamp = 5; + params.tbname = SETTINGS.rvoTbName; + params.info = "Master node FW verzia"; + //params.debug = true; + + tasks.push(params); + } + + //kazdu hodinu skontrolovat nastavenie profilov + { + let params = getParams(); + params.type = "process_profiles"; + params.timestamp = Date.now() + 60001; + params.addMinutesToTimestamp = 60;//60 = every hour + params.info = "detekcia nespracovaných profilov linie a nodov"; + //params.debug = true; + + tasks.push(params); + } + + monitor.info("tasks created:", tasks.length); + } + + + /** + * We process line profile, where "astro_clock": true + * example profile: + * + "dawn_lux_sensor": true, + "dusk_lux_sensor": true, + "dawn_lux_sensor_value": 5, + "dusk_lux_sensor_value": 5, + "dawn_astro_clock_offset": 0, + "dusk_astro_clock_offset": 10, + "dawn_lux_sensor_time_window": 30, + "dusk_lux_sensor_time_window": 30, + "dawn_astro_clock_time_window": 60, + "dusk_astro_clock_time_window": 60 + + * if dawn: if currentTimestamp is in timewindow "dawnTime + and - dawn_lux_sensor_time_window" and lux value >= lux_sensor_value, we switch off the line. + * if dusk: we do oposite + * + * dawn: usvit - lux je nad hranicou - vypnem + * dusk: sumrak - lux je pod hranicou - zapnem + */ + 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++) { + + let line = keys[i]; //line is turned off by default + let profilestr = relaysData[line].profile; + const contactor = relaysData[line].contactor; + + try { + + let profile = JSON.parse(profilestr); + if (Object.keys(profile).length === 0) throw ("turnOnOffLinesAccordingToLuxSensor - profile is not defined"); + + 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 (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"); + } + } + } + + //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 (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"); + } + } + } + + } + + } catch (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) { + //MASTER + if (node == 0) return; + + let nodeObj = nodesData[node]; + if (nodeObj == undefined) return; + + let nodeCurrentStatus = nodeObj.status; + const now = Date.now(); + + let data = null; + + if (nodeCurrentStatus === "OFFLINE") { + data = { status: newStatus }; + nodeDbStatusModify(node, data); + return; + } + else 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; + } + + } + + + 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 }; + } + }); + }); + } + + + function processDailyReport() { + + const now = Date.now(); + + for (const [key, value] of Object.entries(dailyReport)) { + + if (["name", "time", "dusk_and_dawn"].includes(key)) continue; + + let poleNumber = nodesData[key]["pole_number"]; + let line = dailyReport[key].line; + let nodeType = nodesData[key]["node_type"]; + let fullNodeName = key // key == nodeNumber + + if (poleNumber && nodeType) { + fullNodeName = SETTINGS.rvo_number + "/" + poleNumber + "_" + line + "L_" + key + "_" + nodeType; + } else { + fullNodeName = key; + } + + if (rvo_is_on) { + + if (value.initialTs) { + if (value.initialTs + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["night_no_data"], fullNodeName); + console.log('report nedostava ziadne data uz hodinu', fullNodeName); + value.initialTs = now; + } + } + if (value.dimmingIsZeroTime) { + if (value.dimmingIsZeroTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["night_dimming=0"], fullNodeName); + console.log("report node dimming je 0 ale ma svietit", fullNodeName); + value.dimmingIsZeroTime = now; + } + } + if (value.powerIsZeroTime) { + if (value.powerIsZeroTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["night_power=0"], fullNodeName); + console.log("report node power je 0 ale ma svietit", fullNodeName); + value.powerIsZeroTime = now; + } + } + + } else { + + let contactorStatus = relaysData[line].contactor; + if (contactorStatus === 1) { + + if (value.initialTs) { + if (value.initialTs + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["day_24/7_no_data"], fullNodeName); + console.log('node je na 24/7 ale nedostava ziadne data uz hodinu', fullNodeName); + value.initialTs = now; + } + } + if (value.dimmingIsOnButShouldBeOffTime) { + if (value.dimmingIsOnButShouldBeOffTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["day_24/7_dimming>0"], fullNodeName); + console.log("report dimming je > 0 ale nema svietit", fullNodeName); + value.dimmingIsOnButShouldBeOffTime = now; + } + } + if (value.powerIsOnButShouldBeOffTime) { + if (value.powerIsOnButShouldBeOffTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["day_24/7_power>0"], fullNodeName); + console.log("report power je > 0 ale nema svietit", fullNodeName); + value.powerIsOnButShouldBeOffTime = now; + } + } + + } + + } + + } + + let report = {}; + report["name"] = SETTINGS.rvo_name; + report["time"] = new Date(); + report["report"] = reportToSend; + + writeToFile(F.path.root("report_data.log"), report, true); + instance.send(SEND_TO.dailyReport, report); + } + + + function dailyReportHandler() { + + if (!SETTINGS.daily_report) return; + + // after dawn we empty reportToSend and start to get data for a new day + const date = new Date(); + const hour = date.getHours(); + const minute = date.getMinutes(); + + console.log("now: ", hour, minute, "suncalc: ", sunCalcResult.dawn_hours, sunCalcResult.dawn_minutes); + + if (hour === sunCalcResult.dawn_hours) { + + //NOTE: ak je este pred usvitom, spracujeme report a posleme na cloud, ak uz je po usvite, resetujeme report plnime data noveho dna + if (minute >= sunCalcResult.dawn_minutes - 2) { + emptyReportToSend(); + emptyDailyReport(); + console.log("Podmienka 1 v dailyReport handler"); + } else { + processDailyReport(); + emptyReportToSend(); + emptyDailyReport(); + console.log("Podmienka 2 v dailyReport handler"); + } + + initialReportStatus = true; + + // ak sa funkcia spusti o hodinu alebo 2 neskor, ako je usvit (moze sa to stat, kedze kazde zapnutie/vypnutie linii odznova spusti casovac. + } else if (hour === sunCalcResult.dawn_hours + 1 || hour === sunCalcResult.dawn_hours + 2) { + if (!initialReportStatus) { + emptyReportToSend(); + emptyDailyReport(); + initialReportStatus = true; + console.log("Podmienka 3 v dailyReport handler"); + } else { + processDailyReport(); + initialReportStatus = true; + console.log("Podmienka 4 v dailyReport handler"); + } + } else { + processDailyReport(); + initialReportStatus = false; + console.log("Podmienka 5 v dailyReport handler"); + } + + console.log("initialReportStatus: ", initialReportStatus); + + } + + function emptyReportToSend() { + emptyJsObject(reportToSend); + reportToSend["contactor"] = { off: [], on: [] }; + reportToSend["night_no_data"] = []; + reportToSend["night_dimming=0"] = []; + reportToSend["night_power=0"] = []; + reportToSend["day_24/7_no_data"] = []; + reportToSend["day_24/7_dimming>0"] = []; + reportToSend["day_24/7_power>0"] = []; + console.log(`resetuje sa reportToSend`); + } + + + //NOTE: ked je initialTs stale rovnaky a zistime ze linie su vypnute (relaysData.line.contactor) - zistim, ci je node na tej linii. Vieme, ze ak je linia vypnuta je to v poriadku lebo nie je na 24/7 linii + //ak je na 24/7 linii, reportujeme, ze neprijima data + function emptyDailyReport() { + const ts = Date.now(); + emptyJsObject(dailyReport); + + //NOTE: do dailyReport dame vsetky nody a pravidelne kontrolujeme ci maju data + //ked nastane sumrak/usvit a svetla maju zacat/prestat svietit, dailyReport spravime nanovo: + for (const [key, value] of Object.entries(nodesData)) { + dailyReport[value.node] = { line: value.line, initialTs: ts }; + } + + console.log("dailyReport: ", dailyReport); + } + + + async function runTasks() { + + clearInterval(interval); + + let currentTimestamp = Date.now(); + + //sort tasks based on timestamp + 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) { + instance.send(SEND_TO.debug, "no tasks created"); + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + if (!rsPort.isOpen) { + instance.send(SEND_TO.debug, "!rsPort.isOpen"); + //await rsPort.open(); + //console.log("Cmd-mngr: !rsPort.isOpen"); + } + + let currentTask = tasks[0]; + + if (currentTask.debug) { + //logger.debug("--->task to process", currentTask); + } + + if (currentTask.timestamp <= currentTimestamp) { + let params = { ...tasks[0] }; + + //allow terminal commands + if (SETTINGS.maintenance_mode && params.type !== "cmd-terminal") { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + let type = params.type; + let tbname = params.tbname; + let node = params.address; + let register = params.register; + let line = null; + let itIsNodeCommand; + + if (nodesData[node] !== undefined) { + line = nodesData[node].line; + itIsNodeCommand = true; + } + + if (params.line !== undefined) line = params.line; + + if (params.addMinutesToTimestamp > 0 || params.timePointName) { + tasks[0].timestamp = currentTimestamp + tasks[0].addMinutesToTimestamp * 60000; + } else { + tasks.shift(); + } + + //kontrola nespracovanych profilov nodov + //TODO: co ked niektore nody neprijimaju profily? kazdu hodinu zahltuju "tasks" array + if (type == "process_profiles") { + //na vsetky zapnutych liniach sa spracuju nespracovane profily nodov + loadRelaysData(); + interval = setInterval(runTasks, SHORT_INTERVAL); + return; + } + + //relay + if (type == "relay") { + + const timePointName = params.timePointName; + const value = params.value; + + let date = new Date(); + date.setDate(date.getDate() + 1);//next day + + let sunCalcResult; + if (timePointName) sunCalcResult = calculateDuskDawn(date, params.line); + + + if (timePointName == "dawn") { + tasks[0].timestamp = sunCalcResult.dawn_time; + } + else if (timePointName == "dusk") { + tasks[0].timestamp = sunCalcResult.dusk_time; + } + else if (timePointName == "luxOn") { + tasks[0].timestamp = sunCalcResult.dusk_time + params.dusk_lux_sensor_time_window * 60000; + } + else if (timePointName == "luxOff") { + tasks[0].timestamp = sunCalcResult.dawn_time + params.dawn_lux_sensor_time_window * 60000; + } + else if (timePointName == "profileTimepoint") { + tasks[0].timestamp = currentTimestamp + tasks[0].addMinutesToTimestamp * 60000; + } + + let info = "aplikovany bod profilu"; + let onOrOff = ""; + value == 1 ? onOrOff = "on" : onOrOff = "off"; + + turnLine(onOrOff, params.line, info); + + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + if (!SETTINGS.masterNodeIsResponding) { + //ak neodpoveda, nebudeme vykonavat ziadne commands, okrem cmd-terminal cmd-master + errorHandler.sendMessageToService("Master node is not responding"); + + let stop = true; + + if (type === "cmd-terminal" || type === "cmd-master") stop = false; + if (stop) { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + } + + let contactorStatus = 1; + if (relaysData[line] != undefined) contactorStatus = relaysData[line].contactor; + + if (line === 0 || contactorStatus === 0 || FLOW.deviceStatus.state_of_breaker[line] === "Off") { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + // TODO: -> status offline for rvo if rotary_switch_state is OFF, this is source of errors + // check if rotary_switch_state == "Off" + // state_of_braker: disconnected = true? + + if (!rsPort.isOpen) { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + //RE-CALCULATE VALUES + //set actual time for broadcast + if (register == 87 && params.recipient === 2) { + var d = new Date(); + params.byte1 = d.getHours();//h + params.byte2 = d.getMinutes();//m + } + + //SET DUSK/DAWN FOR BROADCAST + //Time of dusk + if (register == 6 && params.recipient === 2) { + + if (type != "cmd-terminal") { + params.byte1 = sunCalcResult["dusk_hours"];//h + params.byte2 = sunCalcResult["dusk_minutes"];//m + } + } + + //Time of dawn + if (register == 7 && params.recipient === 2) { + if (type != "cmd-terminal") { + params.byte1 = sunCalcResult["dawn_hours"];//h + params.byte2 = sunCalcResult["dawn_minutes"];//m + } + } + //----------------------- + + instance.send(SEND_TO.debug, "address: " + node + " register:" + register + "type: " + type); + + var startTime, endTime; + startTime = new Date(); + + let saveToTb = true; + if (!tbname) saveToTb = false; + + let resp = com_generic(node, params.recipient, params.rw, register, params.name, params.byte1, params.byte2, params.byte3, params.byte4); + let readBytes = 11; + let timeout = 4000; + + + // await keyword is important, otherwise incorrect data is returned! + await writeData(rsPort, resp, readBytes, timeout).then(function(data) { + + //sometimes happens, that status of node changes to OK, NOK even if line was turned off and should be status OFFLINE. To prevent this, we return if line contactor is 0: + if (itIsNodeCommand && line && relaysData[line].contactor !== 1) return; + + 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); + + //ak sa odpoved zacina 0 - je to v poriadku, inak je NOK + let message = result.message; // OK, NOK + let message_type = result.type; + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + console.log("detected response:", result); + logger.debug("Cmd-mngr: writeData done " + message_type + " duration: " + timeDiff + " type: " + params.debug, params, result); + } + } + + let values = {}; + + //CMD FINISHED + if (message == "OK") { + + updateNodeStatus(node, true); + + //write + if (type == "set_node_profile") { + let result = cmdCounterResolve(node); + if (result == 0) { + dbNodes.modify({ processed: true }).where("node", node).make(function(builder) { + builder.callback(function(err, response) { + + sendNotification("Cmd-mngr: process cmd", SETTINGS.rvoTbName, "dimming_profile_was_successfully_received_by_node", { node: node }, "", SEND_TO.tb, instance); + + logger.debug("--> profil úspešne odoslaný na node č. " + node); + nodesData[node].processed = true; + nodeProfileSendFail.delete(node); + }); + }); + } + } + + //parse read response + if (params.rw == 0) { + values = processResponse(register, dataBytes); //read + } + + if (itIsNodeCommand) { + values.comm_status = "OK"; + values.status = "OK"; + nodesData[node].readout = { ...nodesData[node].readout, ...values }; + + + if (SETTINGS.daily_report) { + //TODO: co ak nedostavame odpovede z nodu ? Musime vyreportovat!! + //v dailyReport teda musi byt kompletny zoznam nodov a neustale kontrolovat, ci maju data, ak nie report node - neodpoveda + if (register === 1) { + + let now = Date.now(); + + if (rvo_is_on === true) { + + if ("dimmingIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].dimmingIsOnButShouldBeOffTime; + + if (values.dimming > 0) { + if ("dimmingIsZeroTime" in dailyReport[node]) delete dailyReport[node].dimmingIsZeroTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if (!("dimmingIsZeroTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], dimmingIsZeroTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } else { + + if ("dimmingIsZeroTime" in dailyReport[node]) delete dailyReport[node].dimmingIsZeroTime; + + if (values.dimming > 0) { + if (!("dimmingIsOnButShouldBeOffTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], dimmingIsOnButShouldBeOffTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if ("dimmingIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].dimmingIsOnButShouldBeOffTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } + } + + if (register === 76) { + + let now = Date.now(); + + if (rvo_is_on === true) { + + if ("powerIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].powerIsOnButShouldBeOffTime; + + if (values.power > 1) { + if ("powerIsZeroTime" in dailyReport[node]) delete dailyReport[node].powerIsZeroTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if (!("powerIsZeroTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], powerIsZeroTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } else { + + if ("powerIsZeroTime" in dailyReport[node]) delete dailyReport[node].powerIsZeroTime; + + if (values.power > 1) { + if (!("powerIsOnButShouldBeOffTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], powerIsOnButShouldBeOffTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if ("powerIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].powerIsOnButShouldBeOffTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } + } + } + + } + + //master node + if (node == 0) { + sendNotification("Cmd-mngr: 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; + } + + if (params.debug) { + //logger.debug("saveToTb", saveToTb, tbname, values); + } + + if (saveToTb && type != "node-regular-read") { + sendTelemetry(values, tbname); + } + else { + if (type == "cmd-terminal") { + terminalCommandResponse(params, "SUCCESS", data); + } + } + + } + else { + terminalCommandResponse(params, "ERROR", data); + handleNokResponseOnRsPort("handleNOK else block", params, itIsNodeCommand, saveToTb); + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + //logger.debug("writeData err: ", error, result, params); + logger.debug("writeData err: ", tbname, node, register, values); + } + } + + //logger.debug(error, result, params); + } + }).catch(function(reason) { + + //console.log("writeData catch exception", reason); + instance.send(SEND_TO.debug, reason); + + terminalCommandResponse(params, "FAILURE", null, reason); + handleNokResponseOnRsPort("handleNOK catch block", params, itIsNodeCommand, saveToTb); + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + logger.debug("-->WRITE FAILED: " + reason, params.debug, params); + } + } + + }); + + } + 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); + } + + + // if node does not respond to request, we repeat request 3 times: + function repeatCommand(params) { + params.repeatCounter++; + if (params.repeatCounter < 4) { + params.timestamp = 0; + params.addMinutesToTimestamp = 0; + tasks.push(params); + } + } + + function handleNokResponseOnRsPort(message, params, itIsNodeCommand, saveToTb) { + + let node = params.address; + let register = params.register; + let type = params.type; + let tbName = params.tbname; + if (!tbName) return; + + let values = {}; + + let updateStatus = updateNodeStatus(node, false); + + if (itIsNodeCommand) { + values.comm_status = "NOK"; + nodesData[node].readout.comm_status = "NOK"; + repeatCommand(params); + } + + if (updateStatus) { + values.status = "NOK"; + nodesData[node].readout.status = "NOK"; + } + + if (type === "node-regular-read") return; + + //master node + if (node == 0) { + sendNotification("Cmd-mngr: 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; + + if (register == 4) values["master_node_version"] = "NOK"; + } + + if (type == "set_node_profile") { + delete cmdCounter[node]; + logger.debug("profil nebol úspešne odoslaný na node č. ", params); + + if (!nodeProfileSendFail.has(node)) { + sendNotification("Cmd-mngr: process cmd", tbName, "configuration_of_dimming_profile_to_node_failed", { node: node }, "", SEND_TO.tb, instance); + nodeProfileSendFail.add(node); + } + } + + // console.log("------",node, register, type, itIsNodeCommand, updateStatus, saveToTb, values); + if (saveToTb) { + sendTelemetry(values, tbName); + } + + } + + + function sendNodesData() { + Object.keys(nodesData).forEach(node => { + if (nodesData[node]["status"] !== "OFFLINE") { + sendTelemetry(nodesData[node].readout, nodesData[node].tbname); + nodesData[node].readout = {}; + } + }) + } + + + /** + * 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; + } + + 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); + + //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 === "OFFLINE") { + nodeObj.node_status_before_offline === true ? number_of_ok_luminaires++ : number_of_nok_luminaires++; + } + else if (nodeObj.status == true) 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 - ts % 60000 //round to full minute + }; + + sendTelemetry(values, SETTINGS.rvoTbName, ts); + } + + + function setSunCalcResult() { + //if next day, we get new dusk and dawn. To make sure, in local timezone 2:00 means 00:00 in utc (it means next day) + if (new Date().getHours() === 2) { + sunCalcResult = calculateDuskDawn(); + console.log("Novy suncalc: ", sunCalcResult); + } + } + + + function setRvoPeriod() { + + if (!SETTINGS.daily_report) return; + + const ts = Date.now(); + + previous_rvo_is_on_value = rvo_is_on; + + if (ts < sunCalcResult.dawn_time - 1_800_000) { // nodes should be on (00:00 -> 06:00 ( - pol hodina, lebo rvo vypina skor) + rvo_is_on = true; + } else if (sunCalcResult.dawn_time - 1_800_000 < ts && ts < sunCalcResult.dusk_time + 1_800_000) { // nodes should be off 06:00 -> 21:00 + rvo_is_on = false; + } else if (sunCalcResult.dusk_time + 1_800_000 < ts) { // nodes should be on 21:00 -> 00:00 + rvo_is_on = true; + } + + if (previous_rvo_is_on_value !== rvo_is_on) { + emptyDailyReport(); + console.log("rvo_is: ", rvo_is_on, previous_rvo_is_on_value); + } + } + + + function handleRsPort() { + + if (rsPort) { + rsPort.removeAllListeners(); + rsPort = null; + } + + //! 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-mngr: rsPort opened success"); + + 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); + + }).catch(function(reason) { + instance.send(SEND_TO.debug, "Cmd-mngr: RPC runSyncExec - promise rejected:" + reason); + }); + }); + + rsPort.on('error', function(err) { + errorHandler.sendMessageToService([exports.title, "unable to open port", SETTINGS.serial_port, err.message], 0); + monitor.info("Cmd-mngr: Error on rsPort", err.message); + }); + + rsPort.on("close", () => { + monitor.info("Cmd-mngr: rsPort closed, reconnecting..."); + setTimeout(handleRsPort, 1000); + }); + + rsPort.open(); + } + + + instance.on("close", () => { + clearInterval(interval); + clearInterval(customTasksInterval); + clearInterval(setCorrectTime); + clearInterval(sendNodeReadout); + clearInterval(accelerometerInterval); + rsPort.close(); + }); + + instance.on("0", _ => { + main(); + }) + + + instance.on("2", _ => { + console.log("dailyReport, reportToSend, rvo_is_on", dailyReport, reportToSend, rvo_is_on, previous_rvo_is_on_value); + }) + + instance.on("1", 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(); + return; + } + else if (flowdata.data == "close") { + rsPort.close(); + return; + } + else if (flowdata.data == "clean") { + tasks = []; + return; + } + else if (flowdata.data == "buildtasks") { + //build & run + return; + } + else if (flowdata.data == "run") { + //durations = []; + + if (tasks.length == 0) { + + buildTasks(); + + if (rsPort.isOpen) { + interval = setInterval(runTasks, 100); + } + else { + instance.send(SEND_TO.debug, "port is not opened!!!"); + } + } + } + else { + //terminal data - object + //logger.debug("flowdata", flowdata.data); + + if (typeof flowdata.data === 'object') { + //logger.debug("dido", flowdata.data); + if (flowdata.data.hasOwnProperty("sender")) { + //data from dido_controller + if (flowdata.data.sender == "dido_controller") { + + if (flowdata.data.hasOwnProperty("cmd")) { + let cmd = flowdata.data.cmd; + + if (cmd == "buildTasks") { + clearInterval(interval); + + logger.debug("-->Cmd-mngr: BUILD TASKS"); + buildTasks(); + + //logger.debug("tasks:"); + //logger.debug(tasks); + + logger.debug("-->Cmd-mngr: RUN TASKS"); + interval = setInterval(runTasks, 5000); + } + else if (cmd == "reload_relays") { + loadRelaysData(flowdata.data.line); + + if (flowdata.data.dataChanged) { + if (!flowdata.data.value) { + reportOfflineNodeStatus(flowdata.data.line); + } + else { + reportOnlineNodeStatus(flowdata.data.line); + } + } + + } + else if (cmd == "rotary_switch_state") { + let value = flowdata.data.value; + + //state was changed + if (rotary_switch_state != value) { + if (value == "Off") { + //vyreportovat vsetky svietdla + reportOfflineNodeStatus(); + } + + rotary_switch_state = value; + } + } + 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) { + + // we send lux_sensor value to all nodes: + let params = getParams(PRIORITY_TYPES.node_broadcast); + + params.recipient = 2;//2 broadcast, address = 0 + params.address = 0xffffffff;//Broadcast + + let ba = longToByteArray(lux_sensor); + + params.byte3 = ba[1];//msb + params.byte4 = ba[0]; + params.timestamp = PRIORITY_TYPES.node_broadcast; + params.info = "run broadcast: Actual Lux level from cabinet"; + params.register = 95;//Actual Lux level from cabinet + params.rw = 1;//write + + tasks.push(params); + + //process profiles + turnOnOffLinesAccordingToLuxSensor(lux_sensor); + } + } + else if (cmd == "state_of_breaker") { + //istic linie + + breakerCounter--; + + let value = flowdata.data.value; + let line = parseInt(flowdata.data.line); + + let dataChanged = false; + if (state_of_breaker[line] != value) dataChanged = true; + + state_of_breaker[line] = value; + + let status = "OK"; + if (value == "Off") status = "NOK"; + + if (dataChanged) { + + if (relaysData.hasOwnProperty(line)) { + let tbname = relaysData[line].tbname; + + if (value == "Off") { + sendNotification("Cmd-mngr: onData", tbname, "circuit_breaker_was_turned_off_line", { line: line }, "", SEND_TO.tb, instance, "circuit_breaker"); + if (breakerCounter < 0) reportToSend["contactor"]["off"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + else { + sendNotification("Cmd-mngr: onData", tbname, "circuit_breaker_was_turned_on_line", { line: line }, "", SEND_TO.tb, instance, "circuit_breaker"); + if (breakerCounter < 0) reportToSend["contactor"]["on"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + + //report status liniu + sendTelemetry({ status: status }, tbname) + + //current value + if (value == "Off") reportOfflineNodeStatus(line); //vyreportovat vsetky svietidla na linii + } + + } + } + else { + logger.debug("undefined cmd", cmd); + } + } + } + + return; + } + + //data from worksys + if (flowdata.data.hasOwnProperty("topic")) { + + let data = getNested(flowdata.data, "content", "data"); + + //if we get temperature in senica from senica-prod01 + let temperature = getNested(flowdata.data, "content", "senica_temperature"); + + if (temperature !== undefined) { + temperatureInSenica = temperature; + return; + } + + if (data === undefined) { + console.log("Invalid rpc command came from platform"); + return; + } + + let command = data.params.command; + let method = data.method; + let profile = data.params.payload; + if (profile == undefined) profile = ""; + let entity = data.params.entities[0]; + let entity_type = entity.entity_type; + let tbname = entity.tb_name; + + instance.send(SEND_TO.debug, flowdata.data); + 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") { + + //let command = data.params.command; + let value = data.params.payload.value; + + if (command == "dimming") { + + let nodeWasFound = false; + let keys = Object.keys(nodesData); + + //logger.debug("-----", keys); + + 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); + + value = parseInt(value); + if (value > 0) value = value + 128; + + params.type = "node-onetime-write"; + params.tbname = tbname; + params.address = node; + params.register = 1; + params.recipient = 1; + params.byte4 = value; + params.rw = 1; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'set dimming from platform'; + //params.debug = true; + + //debug(params); + logger.debug("dimming", params); + + tasks.push(params); + + 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); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 1; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read dimming (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + //pridame aj vyreportovanie - vykon + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 76; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read Input Power (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + //pridame aj vyreportovanie - prud svietidla + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 75; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read Input Current (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + //pridame aj vyreportovanie - power faktor - ucinnik + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 77; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read power factor (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + }, 4000); + + nodeWasFound = true; + break; + } + } + + if (!nodeWasFound) { + logger.debug("set dimming from platform", "unable to find tbname", tbname); + } + } + else { + instance.send(SEND_TO.debug, "undefined command " + command); + logger.debug("undefined command", command); + } + + return; + } + 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++) { + let node = keys[i]; + if (tbname == nodesData[node].tbname) { + + 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"); + + //profil úspešne prijatý pre node č. xx + sendNotification("Cmd-mngr", tbname, "dimming_profile_was_processed_for_node", { node: node }, profile, SEND_TO.tb, instance); + + nodesData[node].processed = false; + nodesData[node].profile = profile; + + processNodeProfile(node); + }); + }); + } + } + } + else { + + instance.send(SEND_TO.debug, "unknown method " + method); + logger.debug("unknown method", method); + + return; + } + } + + //nastav profil linie z platformy + 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") { + + 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++) { + let line = keys[i]; + if (tbname == relaysData[line].tbname) { + //zmazeme tasky + 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) { + + //update profile + logger.debug("worksys - update relay profile done:", profile); + instance.send(SEND_TO.debug, "worksys - update relay profile done"); + + relaysData[line].profile = profile; + + loadRelaysData(line) + logger.debug("loadRelaysData DONE for line", line); + + buildTasks({ processLineProfiles: true, line: line }); + + sendNotification("Cmd-mngr: set profile from worksys", tbname, "switching_profile_was_processed_for_line", { line: line }, profile, SEND_TO.tb, instance); + }); + }); + break; + } + } + } + else if (method == "set_command") { + let value = data.params.payload.value; + + 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; + + 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"); + if (line != 0) reportToSend["contactor"]["off"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + else { + turnLine("on", line, "command received from platform"); + if (line != 0) reportToSend["contactor"]["on"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + } + } + else { + instance.send(SEND_TO.debug, "undefined method " + method); + logger.debug("undefined method", method); + } + + return; + } + else { + instance.send(SEND_TO.debug, "UNKNOW entity_type " + entity_type); + logger.debug("UNKNOW entity_type", entity_type); + } + return; + } + + //terminal + if (!rsPort.isOpen) await rsPort.open(); + + let params = flowdata.data.body; + if (params == undefined) { + //logger.debug("Cmd-mngr: flowdata.data.body is undefined"); + return; + } + + params.priority = PRIORITY_TYPES.terminal; + params.type = "cmd-terminal"; + params.tbname = ""; + params.timestamp = PRIORITY_TYPES.terminal; + params.addMinutesToTimestamp = 0;// do not repeat task!!! + params.debug = true; + + let timestamp = Date.now(); + params.refFlowdataKey = timestamp; + //params.refFlowdata = flowdata; + //refFlowdata = flowdata; + + //console.log("flowdata", flowdata); + + cleanUpRefFlowdataObj(); + + refFlowdataObj[timestamp] = flowdata; + + //fix + //params.address = params.adress; + logger.debug("received from terminal", params); + logger.debug("date/time:", new Date()); + logger.debug("tasks length:", tasks.length); + + //tasks = []; + + //add to tasks + tasks.push(params); + + } + } + }) + + + //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) + } + + + /** + * 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; + + RESTBuilder.make(function(builder) { + + if (!builder) return; + + builder.method('GET'); + builder.url('http://192.168.252.2:8004/gettime?projects_id=1'); + + builder.callback(function(err, response, output) { + + 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); + } + + }); + } + + } 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); + + } else { + //console.log("Read-only", stdout); + + 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]: [ + { + "ts": date, + "values": values + } + ] + } + + tbHandler.sendToTb(dataToTb, instance); + } + + + function calculateDuskDawn(date, line, duskOffset = 0, dawnOffset = 0) { + + if (date === undefined) date = new Date(); + + 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); + } + + //if(profile.dawn_lux_sensor == false) + { + if (profile.hasOwnProperty("dawn_astro_clock_offset")) dawn_astro_clock_offset = parseInt(profile.dawn_astro_clock_offset); + } + + } + + } catch (error) { + if (profilestr != "") { + logger.debug(profilestr); + logger.debug(error); + } + } + + 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; + } + + //Dimming, CCT + else if (register == 1) { + let brightness = 0; + let dimming = byte0; + if (dimming > 128) { + //dimming = -128; + brightness = dimming - 128; + } + + //cct + //Ak Byte3 == 1: CCT = (Byte2*256)+Byte1 + let cct; + if (byte3 == 1) cct = byte2 * 256 + byte1; + else cct = bytesToInt(bytes.slice(0, 3)); + + //cct podla auditu + + values["dimming"] = brightness; + return values; + } + + // + else if (register == 4) { + values["master_node_version"] = bytes[1] + "." + bytes[2]; + //logger.debug("FW Version", register, bytes); + } + + //Napätie + else if (register == 74) { + let voltage = (bytesToInt(bytes) * 0.1).toFixed(1); + values["voltage"] = Number(voltage); + } + + //Prúd + else if (register == 75) { + let current = bytesToInt(bytes); + values["current"] = current; + } + + //výkon + else if (register == 76) { + let power = (bytesToInt(bytes) * 0.1).toFixed(2); + values["power"] = Number(power); + } + + //účinník + else if (register == 77) { + let power_factor = Math.cos(bytesToInt(bytes) * 0.1 * (Math.PI / 180)).toFixed(2); + values["power_factor"] = Number(power_factor); + } + + //frekvencia + else if (register == 78) { + let frequency = (bytesToInt(bytes) * 0.1).toFixed(2); + values["frequency"] = Number(frequency); + } + + //energia + else if (register == 79) { + let energy = bytesToInt(bytes); + values["energy"] = energy / 1000; //energia v kWh -> delit 1000 + } + + //doba života + else if (register == 80) { + let lifetime = (bytesToInt(bytes) / 60).toFixed(2); + values["lifetime"] = Number(lifetime); + } + + //nastavenie profilu + else if (register == 8) { + let time_schedule_settings = bytesToInt(bytes); + values["time_schedule_settings"] = time_schedule_settings; + } + + //naklon - nateraz sa z nodu nevycitava! kvoli problemom s accelerometrom a vracanymi hodnotami, posielame temp a x y z vo funkcii accelerometerData() + else if (register == 84) { + values["temperature"] = byte3 >= 128 ? (byte3 - 128) * (-1) : byte3; + values["inclination_x"] = byte2 >= 128 ? (byte2 - 128) * (-1) : byte2; + values["inclination_y"] = byte1 >= 128 ? (byte1 - 128) * (-1) : byte1; + values["inclination_z"] = byte0 >= 128 ? (byte0 - 128) * (-1) : byte0; + } + + //FW verzia nodu + else if (register == 89) { + //formát: "Byte3: Byte2.Byte1 (Byte0)" + values["fw_version"] = byte3 + ":" + byte2 + "." + byte1 + "(" + byte0 + ")"; + } + + else if (register == 87 || register == 6 || register == 7) { + var d = new Date(); + d.setHours(byte3, byte2, 0, 0); + let timestamp = d.getTime(); + + //aktuálny čas + if (register == 87) values["actual_time"] = timestamp; + //čas súmraku + else if (register == 6) values["dusk_time"] = timestamp; + //čas úsvitu + else if (register == 7) values["dawn_time"] = timestamp; + } + + 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; + + } + + + function getObjectByTbValue(object, tbname) { + return object[Object.keys(object).find(key => object[key].tbname === tbname)]; + } + + + function isObject(item) { + return (typeof item === "object" && !Array.isArray(item) && item !== null); + } + + + // we fake data, that should be received from accelerometer, as they are a bit unreliable. (temperature, x,y,z) + function accelerometerData() { + + if (temperatureInSenica === null) return; + + //clone nodesData and relaysData objects + let nodesData_clone = JSON.parse(JSON.stringify(nodesData)); + let relaysData_clone = JSON.parse(JSON.stringify(relaysData)); + + for (const key in relaysData_clone) { + + const lineData = relaysData_clone[key]; + const lineNumber = lineData.line; + const contactor = lineData.contactor; + + if (lineNumber === 0) continue; + + if (contactor === 1) { + + let date = Date.now(); + + Object.keys(nodesData_clone).forEach((node, index) => { + + setTimeout(function() { + + if (nodesData_clone[node].line === lineNumber) { + + // NOTE: if status of luminaire is NOK or OFFLINE, we do not send data; + let status = nodesData_clone[node].status; + if (status === "OFFLINE" || !status) return; + + let x = null; + if (naklony.hasOwnProperty(node)) x = naklony[node].naklon; + if (x === null) x = 0; + + sendTelemetry({ temperature: Math.round(temperatureInSenica + 10 + Math.floor(Math.random() * 3)), inclination_x: x, inclination_y: 0, inclination_z: 0 }, nodesData_clone[node].tbname, date); + } + + }, (index + 1) * 500); + }) + + } + } + } + + +} // end of instance.export + diff --git a/RVO2/flow/code.js b/RVO2/flow/code.js new file mode 100755 index 0000000..63b31bf --- /dev/null +++ b/RVO2/flow/code.js @@ -0,0 +1,90 @@ +exports.id = 'code'; +exports.title = 'Code'; +exports.group = 'Common'; +exports.color = '#656D78'; +exports.input = true; +exports.output = 1; +exports.author = 'Peter Širka'; +exports.icon = 'code'; +exports.version = '1.2.0'; +exports.options = { outputs: 1, code: 'send(0, value);', keepmessage: true }; + +exports.html = `
+
+
+
@(Number of outputs)
+
@(Minimum is 1)
+
+
+
@(Code)
+
@(Keep message instance)
+
+`; + +exports.readme = `# Code + +This component executes custom JavaScript code as it is and it doesn't contain any secure scope. + +\`\`\`javascript +// value {Object} contains received data +// send(outputIndex, newValue) sends a new value +// error(value) sends an error +// instance {Object} a current component instance +// flowdata {Object} a current flowdata +// repository {Object} a current repository of flowdata +// Example: + +// send() can be execute multiple times +send(0, value); +\`\`\``; + +exports.install = function(instance) { + + var fn; + + instance.on('data', function(response) { + if (fn) { + try { + fn(response.data, instance, response, instance.options, response.repository, require); + } catch (e) { + response.data = e; + instance.throw(response); + } + } + }); + + instance.reconfigure = function() { + try { + if (instance.options.code) { + instance.status(''); + var code = 'var send = function(index, value) { if (options.keepmessage) { flowdata.data = value; instance.send2(index, flowdata); } else instance.send2(index, value);}; var error = function(err) { instance.throw(err); }; ' + instance.options.code; + fn = new Function('value', 'instance', 'flowdata', 'options', 'repository', 'require', code); + } else { + instance.status('Not configured', 'red'); + fn = null; + } + } catch (e) { + fn = null; + instance.error('Code: ' + e.message); + } + }; + + instance.on('options', instance.reconfigure); + instance.reconfigure(); +}; \ No newline at end of file diff --git a/RVO2/flow/comment.js b/RVO2/flow/comment.js new file mode 100755 index 0000000..1e0cd13 --- /dev/null +++ b/RVO2/flow/comment.js @@ -0,0 +1,11 @@ +exports.id = 'comment'; +exports.title = 'Comment'; +exports.group = 'Common'; +exports.color = '#704cff'; +exports.author = 'Martin Smola'; +exports.icon = 'comment'; +exports.traffic = false; +exports.version = '1.0.0'; +exports.readme = '# Comment'; + +exports.install = function() {}; diff --git a/RVO2/flow/count.js b/RVO2/flow/count.js new file mode 100755 index 0000000..fa92ee9 --- /dev/null +++ b/RVO2/flow/count.js @@ -0,0 +1,60 @@ +exports.id = 'count'; +exports.title = 'Count'; +exports.version = '1.0.1'; +exports.author = 'John Graves'; +exports.color = '#656D78'; +exports.icon = 'plus-square'; +exports.input = 2; +exports.output = 1; +exports.options = { increment: 1, initialvalue: 1 }; +exports.readme = `# Counter + +Counter Number of times called.`; + +exports.html = `
+
@(Initial Value)
+
@(Increment)
+

Example Video

+
`; + +exports.readme = `# Count + +This component counts the number of messages received. + +__Response:__ + +Integer value based on the initial value and increment settings. + +__Arguments:__ +- Initial Value: What number should be output on the receipt of the first message. +- Increment: What should the increment be for each following message received.`; + +exports.install = function(instance) { + + var count = 0; + var initialCall = true; + + instance.on('data', function(flowdata) { + var index = flowdata.index; + if (index) { + instance.debug('Reset Count.'); + count = instance.options.initialvalue; + initialCall = true; + } else { + // If this is the first time, set the value to 'initial value' + if(initialCall) { + initialCall = false; + count = instance.options.initialvalue; + } else + count = count+instance.options.increment; + instance.status('Count:' + count); + instance.send2(count); + } + }); + + instance.on('options', function() { + count = instance.options.initialvalue; + initialCall = true; + }); + +}; diff --git a/RVO2/flow/db_connector.js b/RVO2/flow/db_connector.js new file mode 100755 index 0000000..65ee94b --- /dev/null +++ b/RVO2/flow/db_connector.js @@ -0,0 +1,286 @@ +exports.id = 'db_connector'; +exports.title = 'DbConnector'; +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.html = `
+
+
+
DbConnector
+
+
+
`; + +exports.readme = `# read/write data to tables`; + +const instanceSendTo = { + debug: 0, + http_response: 1, +} + +const { promisifyBuilder, makeMapFromDbResult } = require('./helper/db_helper.js'); + +function extractWhereParams(params) +{ + let name = params[0]; + let operator = '='; + let value = params[1]; + + if(params.length == 3) + { + operator = params[1]; + value = params[2]; + } + + return {name: name, operator: operator, value: value}; +} + +exports.install = function(instance) { + + let refFlowdata = null;//holds reference to httprequest flowdata + + instance.on("close", () => { + + }) + + + instance.on("data", async function(flowdata) { + + let params = flowdata.data.body; + console.log("DbConnector", params); + + refFlowdata = flowdata; + + if(refFlowdata != undefined) + { + //make http response + let responseObj = {}; + responseObj["type"] = "SUCESS"; + + try{ + + let table = params.table; + let action = params.action; + + + if(params.data != undefined) + { + let className = params.data.className; + + if(className == "SqlQueryBuilder") + { + let type = params.data.type; + + console.log("SqlQueryBuilder---->", params.data); + + if(type == "SELECT") + { + let table = params.data.queryData.tables[0].table; + + const db = TABLE(table); + var builder = db.find(); + + let result = await promisifyBuilder(builder); + + let response = {}; + response["result"] = result; + response["success"] = true; + + responseObj["data"] = response; + + //console.log(responseObj); + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + } + + return; + } + } + + + console.log("db_connector---->", table, action); + + //actions: read, replace, insert, delete, update... + + if(action == "read") + { + const db = TABLE(params.table); + + //where builder.where('age', '<', 15); + //builder.where('id', 3403); + + var builder = db.find(); + + //https://docs.totaljs.com/latest/en.html#api~DatabaseBuilder~builder.where + if(params.hasOwnProperty("where")) + { + //optionalCan contain "=", "<=", "<", ">=", ">". + //Default value: '=' + + //1.["production_line", 1] + //2. ["or", ["production_line", 1], ["production_line", 2], "end"] + + if (Array.isArray(params.where)) { + + let multipleConditions = false; + + if(params.where[0] == "or") multipleConditions = true; + if (Array.isArray(params.where[0])) multipleConditions = true; + + if(multipleConditions) + { + + for(var i = 0; i < params.where.length; i++) + { + const item = params.where[i]; + + if(item === "or") builder.or(); + + if (Array.isArray(item)) + { + const { name, operator, value } = extractWhereParams(item); + builder.where(name, operator, value); + } + + if(item === "end") builder.end(); + + } + + } + else + { + const { name, operator, value } = extractWhereParams(params.where); + builder.where(name, operator, value); + } + + } + + /* + if(params.where.length >=2 ) + { + let name = params.where[0]; + let operator = '='; + let value = params.where[1]; + + if(params.where.length == 3) + { + operator = params.where[1]; + value = params.where[2]; + } + + builder.where(name, operator, value); + } + */ + } + + if(params.hasOwnProperty("between")) + { + builder.between(params.between[0], params.between[1], params.between[2]); + } + + let response = await promisifyBuilder(builder); + responseObj["data"] = response; + + //console.log(responseObj); + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + + return; + } + + if(action == "delete") + { + + } + + + if(action == "update") + { + //! data receiving from terminal (params) + // { + // hostname: 'localhost', + // table: 'settings', + // action: 'update', + // body: { + // rvo_name: 'terrrr', + // lang: 'en', + // temperature_adress: '28.427B45920702', + // latitude: 48.70826502, + // longitude: 17.28455203, + // mqtt_host: '192.168.252.4', + // mqtt_clientid: 'showroom_test_panel_led', + // mqtt_username: 'xmRd6RJxW53WZe4vMFLU', + // mqtt_port: 1883, + // maintanace_mode: false + // } + // } + const tableToModify = TABLE(params.table); + const newValues = params.body; + + tableToModify.modify(newValues).make(function(builder) { + + builder.callback(function(err, response) { + + if(!err) + { + responseObj["data"] = response; + responseObj["tableUpdated"] = true; + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + } + }); + }); + + } + + if(action == "replace") + { + //truncate table + const db = TABLE(params.table); + var builder = db.remove(); + db.clean(); + + //insert data + let data = params.data; + + for(let i = 0; i < data.length; i++) + { + //console.log(data[i]); + db.insert(data[i]); + } + + console.log("insert done"); + + let responseObj = {}; + responseObj["type"] = "SUCESS"; + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + + + } + + + + } catch (error) { + //console.log(error); + responseObj["type"] = "ERROR"; + responseObj["message"] = error; + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + } + } + }) +} + + diff --git a/RVO2/flow/db_init.js b/RVO2/flow/db_init.js new file mode 100755 index 0000000..b399878 --- /dev/null +++ b/RVO2/flow/db_init.js @@ -0,0 +1,113 @@ +exports.id = 'db_init'; +exports.title = 'DB Initialization'; +exports.group = 'Worksys'; +exports.color = '#888600'; +exports.version = '1.0.2'; +exports.icon = 'sign-out'; +exports.output = 2; + +exports.readme = ` + # DB initialization +`; + +const { promisifyBuilder, makeMapFromDbResult } = require('./helper/db_helper.js'); +const { initNotification } = require('./helper/notification_reporter'); +const errorHandler = require('./helper/ErrorToServiceHandler'); +const total_energy = require('../databases/total_energy'); + +const SEND_TO = { + db_init: 0, + infoSender: 1 +}; + + +exports.install = async function(instance) { + const dbNodes = TABLE("nodes"); + const dbRelays = TABLE("relays"); + const dbSettings = TABLE("settings"); + 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 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.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"]; + Object.keys(dbs.nodesData).forEach(node => dbs.nodesData[node].readout = {}) + + let rvo_number = responseSettings[0]["rvo_name"].match(/\D+(\d{1,2})_/)[1]; + + dbs.settings = { + edge_fw_version: "2025-10-08", //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"], + phases: responseSettings[0]["phases"], + cloud_topic: responseSettings[0]["cloud_topic"], + has_main_switch: responseSettings[0]["has_main_switch"], + daily_report: responseSettings[0]["daily_report"], + send_changed_node_numbers: responseSettings[0]["send_changed_node_numbers"], + rvo_number: rvo_number, + + //dynamic values + masterNodeIsResponding: true, //cmd_manager + maintenance_mode: false, + } + + + dbs.settings.energy_to_switch_lamps = total_energy[rvo_number]; + if (dbs.settings.energy_to_switch_lamps === undefined) console.log('=============== db_init.js: energy_to_switch_lamps is undefined'); + + FLOW.dbLoaded = true; + errorHandler.setProjectId(dbs.settings.project_id); + initNotification(); + + //APP START - send to data services + const toService = { + id: dbs.settings.project_id, + name: dbs.settings.rvo_name, + fw_version: dbs.settings.edge_fw_version, + startdate: new Date().toISOString().slice(0, 19).replace('T', ' '), + js_error: "", + error_message: "" + }; + + instance.send(SEND_TO.infoSender, toService); + console.log("----------------> START - message send to service", toService); + + setTimeout(() => { + console.log("DB_INIT - data loaded"); + instance.send(SEND_TO.db_init, "_") + }, 5000) + +}; + diff --git a/RVO2/flow/debug.js b/RVO2/flow/debug.js new file mode 100755 index 0000000..00cb259 --- /dev/null +++ b/RVO2/flow/debug.js @@ -0,0 +1,100 @@ +exports.id = 'debug'; +exports.title = 'Debug'; +exports.author = 'Peter Širka'; +exports.color = '#967ADC'; +exports.click = true; +exports.input = true; +exports.icon = 'bug'; +exports.version = '2.0.4'; +exports.options = { enabled: true, repository: false, type: 'data' }; +exports.readme = `# Debug + +Prints data to the debug tab.`; + +exports.html = `
+
+
+
@(Output type)
+
@(Path to the property (leave empty to show the whole data object))
+
@(A group name)
+
@(Enabled)
+
+
+
`; + +exports.install = function(instance) { + + instance.on('data', function(response) { + if (instance.options.enabled) { + + var opt = instance.options; + var rep = response.repository; + var val = response.data; + var id = response.id; + + switch (instance.options.type){ + case 'both': + var data = {}; + data.repository = rep; + data.data = val instanceof Error ? { error: val.message, stack: val.stack } : val; + instance.debug(safeparse(opt.property ? U.get(data, opt.property) : data), undefined, opt.group, id); + break; + case 'repository': + instance.debug(safeparse(opt.property ? U.get(rep, opt.property) : rep), undefined, opt.group, id); + break; + case 'data': + default: + if (val instanceof Error) + instance.debug({ error: val.message, stack: val.stack }, undefined, opt.group, id); + else + instance.debug(safeparse(opt.property ? U.get(val, opt.property) : val), undefined, opt.group, id); + break; + } + } + }); + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + instance.save(); + }); + + instance.on('options', function() { + instance.custom.status(); + }); + + instance.custom.status = function() { + instance.status(instance.options.enabled ? 'Enabled' : 'Disabled'); + }; + + instance.custom.status(); + + function safeparse(o) { + + if (o instanceof Buffer) + return o; + + if (o === undefined) + return 'undefined'; + + if (o === null) + return 'null'; + + var cache = []; + var str = JSON.stringify(o, function(key, value) { + if (typeof value === 'object' && value !== null) { + if (cache.indexOf(value) !== -1) { + try { + return JSON.parse(JSON.stringify(value)); + } catch (error) { + return; + } + } + cache.push(value); + } + return value; + }); + cache = null; + return JSON.parse(str); + } +}; diff --git a/RVO2/flow/designer.json b/RVO2/flow/designer.json new file mode 100755 index 0000000..580f5a3 --- /dev/null +++ b/RVO2/flow/designer.json @@ -0,0 +1,3102 @@ +{ + "tabs": [ + { + "name": "MAIN PUSH", + "linker": "main-push", + "id": "1612772287426", + "index": 0 + }, + { + "name": "CMD manager", + "linker": "cmd-manager", + "id": "1615551125555", + "index": 1 + }, + { + "name": "Devices", + "linker": "devices", + "id": "1611921777196", + "index": 2 + } + ], + "components": [ + { + "id": "1611951142547", + "component": "debug", + "tab": "1611921777196", + "name": "ERROR", + "x": 598, + "y": 60, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#DA4453", + "notes": "" + }, + { + "id": "1612776786008", + "component": "wsmqttpublish", + "tab": "1612772287426", + "name": "WS MQTT publish", + "x": 281.75, + "y": 174, + "connections": { + "0": [ + { + "index": "0", + "id": "1615551060773" + } + ], + "1": [ + { + "index": "0", + "id": "1618300858252" + }, + { + "index": "0", + "id": "1618558465485" + } + ], + "2": [ + { + "index": "0", + "id": "1634303685503" + } + ], + "3": [ + { + "index": "0", + "id": "1731068754606" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Connected", + "color": "green" + }, + "options": { + "username": "", + "clientid": "", + "port": "1883", + "host": "" + }, + "color": "#888600", + "notes": "" + }, + { + "id": "1612778461252", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "tb-push", + "x": 72.75, + "y": 328, + "connections": { + "0": [ + { + "index": "0", + "id": "1612783322136" + }, + { + "index": "1", + "id": "1612776786008" + }, + { + "index": "0", + "id": "1731068754606" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1612783322136", + "component": "debug", + "tab": "1612772287426", + "name": "to TB", + "x": 283.75, + "y": 324, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615551060773", + "component": "debug", + "tab": "1612772287426", + "name": "errors from MQTT Broker", + "x": 594, + "y": 57, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#DA4453", + "notes": "" + }, + { + "id": "1615563373927", + "component": "debug", + "tab": "1615551125555", + "name": "Debug", + "x": 755, + "y": 155, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#DA4453", + "notes": "" + }, + { + "id": "1615566865233", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "tb-push", + "x": 755, + "y": 248, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1615798582262", + "component": "debug", + "tab": "1615551125555", + "name": "CMD_debug", + "x": 755, + "y": 346, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615802995322", + "component": "debug", + "tab": "1611921777196", + "name": "Debug", + "x": 596.8833312988281, + "y": 566.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Disabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": false + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615809128443", + "component": "debug", + "tab": "1611921777196", + "name": "tempToTb", + "x": 595.8833312988281, + "y": 658.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615809595184", + "component": "virtualwireout", + "tab": "1611921777196", + "name": "tb-push", + "x": 597.8833312988281, + "y": 377.25, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1616165795916", + "component": "httproute", + "tab": "1615551125555", + "name": "POST /terminal", + "x": 135, + "y": 547, + "connections": { + "0": [ + { + "index": "0", + "id": "1684060205000" + }, + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Listening", + "color": "green" + }, + "options": { + "timeout": 10, + "cachepolicy": 0, + "cacheexpire": "5 minutes", + "size": 5, + "url": "/terminal", + "method": "POST", + "name": "", + "flags": [ + "id:1616165795916", + "post", + 10000 + ], + "emptyresponse": false + }, + "color": "#5D9CEC", + "notes": "### Configuration\n\n- __POST /terminal__\n- flags: \n- maximum request data length: __5 kB__\n- empty response: __false__\n- cache policy: __no cache__\n- cache expire: __5 minutes__", + "cloning": false + }, + { + "id": "1616165824813", + "component": "httpresponse", + "tab": "1615551125555", + "name": "HTTP Response", + "x": 753, + "y": 423, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "json" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1617104731852", + "component": "debug", + "tab": "1615551125555", + "name": "DIDO_Debug", + "x": 669, + "y": 1040, + "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": "turnOff line", + "x": 133, + "y": 1161, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "object", + "data": "{line: 3, command: \"turnOff\", force: true}" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1617115013095", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "tb-push", + "x": 669, + "y": 1150, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1617284749681", + "component": "trigger", + "tab": "1615551125555", + "name": "update profile / node", + "x": 112, + "y": 208, + "connections": { + "0": [ + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "data": "profile_nodes", + "datatype": "string" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1618235171399", + "component": "trigger", + "tab": "1615551125555", + "name": "tun tasks", + "x": 184, + "y": 279, + "connections": { + "0": [ + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "data": "run" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1618300858252", + "component": "debug", + "tab": "1612772287426", + "name": "wsmqtt-exit1", + "x": 597.8833312988281, + "y": 149, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1618393583970", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "to-cmd-manager", + "x": 668.8833312988281, + "y": 1269, + "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": 132.88333129882812, + "y": 367, + "connections": { + "0": [ + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "platform-rpc-call", + "color": "gray" + }, + "options": { + "wirename": "platform-rpc-call" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1618393759854", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "cmd_to_dido", + "x": 119.88333129882812, + "y": 1007, + "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": 752.8833312988281, + "y": 527, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "cmd_to_dido", + "color": "gray" + }, + "options": { + "wirename": "cmd_to_dido" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1618558465485", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "platform-rpc-call", + "x": 597.8833312988281, + "y": 247, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "platform-rpc-call", + "color": "gray" + }, + "options": { + "wirename": "platform-rpc-call" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1618572059773", + "component": "trigger", + "tab": "1615551125555", + "name": "turnOn line", + "x": 132, + "y": 1085, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "data": "{line: 1, command: \"turnOn\", force: true}", + "datatype": "object" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1619515097737", + "component": "cmd_manager", + "tab": "1615551125555", + "name": "CMD Manager", + "x": 452.1091003417969, + "y": 341.05455017089844, + "connections": { + "0": [ + { + "index": "0", + "id": "1615563373927" + } + ], + "1": [ + { + "index": "0", + "id": "1615566865233" + }, + { + "index": "0", + "id": "1615798582262" + } + ], + "2": [ + { + "index": "0", + "id": "1616165824813" + } + ], + "3": [ + { + "index": "0", + "id": "1618393827655" + } + ], + "4": [ + { + "index": "0", + "id": "1635936391935" + } + ], + "5": [ + { + "index": "0", + "id": "1757006030239" + }, + { + "index": "0", + "id": "1757006060377" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1619605019281", + "component": "httproute", + "tab": "1615551125555", + "name": "GET db", + "x": 173, + "y": 653, + "connections": { + "0": [ + { + "index": "0", + "id": "1684060205000" + }, + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Listening", + "color": "green" + }, + "options": { + "timeout": 5, + "cachepolicy": 0, + "cacheexpire": "5 minutes", + "size": 5, + "url": "/db", + "method": "GET", + "name": "", + "flags": [ + "id:1619605019281", + "get", + 5000 + ] + }, + "color": "#5D9CEC", + "notes": "### Configuration\n\n- __GET /db__\n- flags: undefined\n- maximum request data length: __5 kB__\n- empty response: __undefined__\n- cache policy: __no cache__\n- cache expire: __5 minutes__", + "cloning": false + }, + { + "id": "1619784672383", + "component": "trigger", + "tab": "1615551125555", + "name": "turnOnAlarm", + "x": 120, + "y": 1234, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "object", + "data": "{command: \"turnOnAlarm\"}" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1619784812964", + "component": "trigger", + "tab": "1615551125555", + "name": "turnOffAlarm", + "x": 118, + "y": 1307, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "object", + "data": "{command: \"turnOffAlarm\"}" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1621340721628", + "component": "virtualwireout", + "tab": "1611921777196", + "name": "modbus_to_dido", + "x": 599, + "y": 471, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "modbus_to_dido", + "color": "gray" + }, + "options": { + "wirename": "modbus_to_dido" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1622640022885", + "component": "httproute", + "tab": "1615551125555", + "name": "POST /db_connector", + "x": 98, + "y": 1586, + "connections": { + "0": [ + { + "index": "0", + "id": "1622640073521" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Listening", + "color": "green" + }, + "options": { + "timeout": 5, + "cachepolicy": 0, + "cacheexpire": "5 minutes", + "size": 5, + "url": "/db_connector", + "method": "POST", + "flags": [ + "id:1622640022885", + "post", + 5000 + ] + }, + "color": "#5D9CEC", + "notes": "### Configuration\n\n- __POST /db_connector__\n- flags: \n- maximum request data length: __5 kB__\n- empty response: __undefined__\n- cache policy: __no cache__\n- cache expire: __5 minutes__", + "cloning": false + }, + { + "id": "1622640073521", + "component": "db_connector", + "tab": "1615551125555", + "name": "DbConnector", + "x": 372, + "y": 1572, + "connections": { + "1": [ + { + "index": "0", + "id": "1622641420685" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "edge": "undefined" + }, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1622641420685", + "component": "httpresponse", + "tab": "1615551125555", + "name": "HTTP Response", + "x": 596, + "y": 1586, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1634303504177", + "component": "monitormemory", + "tab": "1612772287426", + "name": "RAM", + "x": 69.88333129882812, + "y": 888.5, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465281992" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "858.88 MB / 985.68 MB", + "color": "gray" + }, + "options": { + "enabled": true, + "interval": 30000 + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1634303533779", + "component": "monitordisk", + "tab": "1612772287426", + "name": "disk", + "x": 70.88333129882812, + "y": 982.5, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465821120" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "5.78 GB / 7.26 GB", + "color": "gray" + }, + "options": { + "enabled": true, + "path": "/", + "interval": 30000 + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1634303595494", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "send-to-services", + "x": 51.883331298828125, + "y": 1400.5, + "connections": { + "0": [ + { + "index": "0", + "id": "1634463186563" + }, + { + "index": "1", + "id": "1634488120710" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1634303602169", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "send-to-services", + "x": 426.8833312988281, + "y": 878.5, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1634303685503", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "send-to-services", + "x": 600.8833312988281, + "y": 341.5, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1634303743260", + "component": "httprequest", + "tab": "1612772287426", + "name": "192.168.252.2:8004/sentmessage", + "reference": "", + "x": 506.8833312988281, + "y": 1331.7333374023438, + "connections": { + "0": [ + { + "index": "0", + "id": "1635327431236" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "url": "http://192.168.252.2:8004/sentmessage", + "method": "POST", + "stringify": "json" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1634463186563", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 305.75, + "y": 1442, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634464580289", + "component": "code", + "tab": "1612772287426", + "name": "Code", + "x": 245, + "y": 787, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465243324" + }, + { + "index": "0", + "id": "1634303602169" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "keepmessage": true, + "code": "let response = {};\nresponse.cpu = value.cpu;\nresponse.uptime = value.uptime;\n\nsend(0, response);", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1634465243324", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 428, + "y": 784, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634465281992", + "component": "code", + "tab": "1612772287426", + "name": "Code", + "x": 245, + "y": 884, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465338103" + }, + { + "index": "0", + "id": "1634303602169" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "keepmessage": true, + "code": "value.sender = \"ram\";\n\nlet response = {};\n\nresponse.memory_total = Math.round(value.total / (1024 ** 2));\nresponse.memory_free = Math.round(value.free / (1024 ** 2));\nresponse.memory_used = Math.round(value.used / (1024 ** 2));\n\nsend(0, response);", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1634465338103", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 429, + "y": 976, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634465821120", + "component": "code", + "tab": "1612772287426", + "name": "Code", + "x": 245, + "y": 978, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465892500" + }, + { + "index": "0", + "id": "1634303602169" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "keepmessage": true, + "code": "value.sender = \"hdd\";\n\nlet response = {};\n\nresponse.hdd_total = Math.round(value.total / (1024 ** 2));\nresponse.hdd_free = Math.round(value.free / (1024 ** 2));\nresponse.hdd_used = Math.round(value.used / (1024 ** 2));\n\nsend(0, response);", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1634465892500", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 432, + "y": 1068, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634484067516", + "component": "debug", + "tab": "1612772287426", + "name": "Send info", + "x": 513, + "y": 1441, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634488120710", + "component": "infosender", + "tab": "1612772287426", + "name": "Info sender", + "x": 301, + "y": 1336, + "connections": { + "0": [ + { + "index": "0", + "id": "1634484067516" + }, + { + "index": "0", + "id": "1634303743260" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "edge": "undefined" + }, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1635327431236", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 837.8833312988281, + "y": 1325.5, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1635936391935", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "send-to-services", + "x": 753, + "y": 623, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1637069803394", + "component": "monitorconsumption", + "tab": "1612772287426", + "name": "CPU", + "x": 69, + "y": 791, + "connections": { + "0": [ + { + "index": "0", + "id": "1634464580289" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "49.2% / 69.91 MB", + "color": "gray" + }, + "options": { + "monitorfiles": true, + "monitorconnections": true, + "monitorsize": true, + "monitorconsumption": true, + "enabled": true, + "interval": 30000 + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1683664161036", + "component": "debug", + "tab": "1615551125555", + "name": "CMDtoDIDO", + "x": 392, + "y": 1012, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1683981346282", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "from-dido-controller", + "x": 112, + "y": 459, + "connections": { + "0": [ + { + "index": "0", + "id": "1684055037116" + }, + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "from-dido-controller", + "color": "gray" + }, + "options": { + "wirename": "from-dido-controller" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1684055037116", + "component": "debug", + "tab": "1615551125555", + "name": "from dido to cmd", + "x": 451, + "y": 532, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1684060205000", + "component": "debug", + "tab": "1615551125555", + "name": "HTTP routes", + "x": 450, + "y": 639, + "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": "MDBToDido", + "x": 598, + "y": 147, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1699963668903", + "component": "dido_controller", + "tab": "1615551125555", + "name": "DIDO_Controller", + "x": 397, + "y": 1131, + "connections": { + "0": [ + { + "index": "0", + "id": "1617104731852" + } + ], + "1": [ + { + "index": "0", + "id": "1617104731852" + }, + { + "index": "0", + "id": "1617115013095" + } + ], + "2": [ + { + "index": "0", + "id": "1618393583970" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "edge": "undefined" + }, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1699964678894", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "modbus_to_dido", + "x": 96, + "y": 924, + "connections": { + "0": [ + { + "index": "0", + "id": "1699963668903" + }, + { + "index": "0", + "id": "1699964793925" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "modbus_to_dido", + "color": "gray" + }, + "options": { + "wirename": "modbus_to_dido" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1699964793925", + "component": "debug", + "tab": "1615551125555", + "name": "modbusToDido", + "x": 388, + "y": 920, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1699965957410", + "component": "modbus_reader", + "tab": "1611921777196", + "name": "Modbus reader", + "x": 232, + "y": 175, + "connections": { + "0": [ + { + "index": "0", + "id": "1611951142547" + } + ], + "1": [ + { + "index": "0", + "id": "1621340721628" + }, + { + "index": "0", + "id": "1684179110403" + }, + { + "index": "0", + "id": "1717441414646" + } + ], + "2": [ + { + "index": "0", + "id": "1615809595184" + }, + { + "index": "0", + "id": "1714752862828" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1700411878636", + "component": "thermometer", + "tab": "1611921777196", + "name": "Thermometer", + "x": 234.75, + "y": 444, + "connections": { + "0": [ + { + "index": "0", + "id": "1615802995322" + } + ], + "1": [ + { + "index": "0", + "id": "1615809595184" + }, + { + "index": "0", + "id": "1615809128443" + } + ], + "2": [ + { + "index": "0", + "id": "1621340721628" + }, + { + "index": "0", + "id": "1732889185927" + }, + { + "index": "0", + "id": "1717441414646" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#5CB36D", + "notes": "" + }, + { + "id": "1714752862828", + "component": "debug", + "tab": "1611921777196", + "name": "MDBToTb", + "x": 766, + "y": 324, + "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": 764.0833282470703, + "y": 222, + "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\telse if(value.status === \"NOK-thermometer\")\n\t{\n\t\tsend(0, {\"thermometer\": \"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\telse if(value.values.hasOwnProperty(\"temperature\"))\n\t{\n\t\tsend(0, {\"thermometer\": \"OK\"});\n\t}\n}", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1717442627834", + "component": "debug", + "tab": "1611921777196", + "name": "modbus service", + "x": 966.0833282470703, + "y": 165, + "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": 968.0833282470703, + "y": 268, + "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": 88.75, + "y": 1685, + "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": 296, + "y": 1671, + "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\", \"Flow has been restarted\", \"Node db has changed\"]", + "types": "[\"emergency\", \"critical\", \"error\", \"alert\"]", + "name": "" + }, + "color": "#30E193", + "notes": "" + }, + { + "id": "1718016073501", + "component": "httprequest", + "tab": "1612772287426", + "name": "http://192.168.252.2:8004/slack", + "x": 495, + "y": 1753, + "connections": { + "0": [ + { + "index": "0", + "id": "1718016086212" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "url": "http://192.168.252.2:8004/slack", + "method": "POST", + "stringify": "json" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1718016086212", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 832, + "y": 1664, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "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": 87, + "y": 1591, + "connections": { + "0": [ + { + "index": "0", + "id": "1718016052341" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "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\": \"\" } } } ] }", + "datatype": "object" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1729855334955", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "platform-rpc-call", + "x": 599.9333343505859, + "y": 541.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "platform-rpc-call", + "color": "gray" + }, + "options": { + "wirename": "platform-rpc-call" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1729855371093", + "component": "debug", + "tab": "1612772287426", + "name": "rpc cloud", + "x": 601.9333343505859, + "y": 440.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1731068658334", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 75.75, + "y": 184, + "connections": { + "0": [ + { + "index": "0", + "id": "1612776786008" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731068754606", + "component": "cloudmqttconnect", + "tab": "1612772287426", + "name": "MQTT to senica-prod01", + "x": 284.75, + "y": 452, + "connections": { + "1": [ + { + "index": "0", + "id": "1729855371093" + }, + { + "index": "0", + "id": "1729855334955" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Connected", + "color": "green" + }, + "options": { + "username": "", + "clientid": "", + "port": "2764", + "host": "192.168.252.2", + "topic": "" + }, + "color": "#888600", + "notes": "" + }, + { + "id": "1731069001548", + "component": "db_init", + "tab": "1612772287426", + "name": "DB Initialization", + "x": 1003.75, + "y": 240.25, + "connections": { + "0": [ + { + "index": "0", + "id": "1731069033416" + } + ], + "1": [ + { + "index": "0", + "id": "1747561603739" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#888600", + "notes": "" + }, + { + "id": "1731069033416", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "db-init", + "x": 1244.75, + "y": 233.25, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069059135", + "component": "showdb", + "tab": "1612772287426", + "name": "Show db data", + "x": 1186.75, + "y": 821.25, + "connections": { + "0": [ + { + "index": "0", + "id": "1731069079243" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#888600", + "notes": "" + }, + { + "id": "1731069079243", + "component": "debug", + "tab": "1612772287426", + "name": "dbData", + "x": 1390.75, + "y": 870.25, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1731069116691", + "component": "trigger", + "tab": "1612772287426", + "name": "settings", + "x": 934.75, + "y": 669.75, + "connections": { + "0": [ + { + "index": "0", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069131637", + "component": "trigger", + "tab": "1612772287426", + "name": "relaysData", + "x": 876.75, + "y": 733.75, + "connections": { + "0": [ + { + "index": "1", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069137374", + "component": "trigger", + "tab": "1612772287426", + "name": "nodesData", + "x": 852.75, + "y": 794.75, + "connections": { + "0": [ + { + "index": "2", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069179846", + "component": "trigger", + "tab": "1612772287426", + "name": "pinsData", + "x": 850.75, + "y": 861.75, + "connections": { + "0": [ + { + "index": "3", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069192937", + "component": "trigger", + "tab": "1612772287426", + "name": "sample data", + "x": 857.75, + "y": 928.75, + "connections": { + "0": [ + { + "index": "4", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069264443", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 63.75, + "y": 1279, + "connections": { + "0": [ + { + "index": "0", + "id": "1634488120710" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069334626", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "db-init", + "x": 172.88333129882812, + "y": 129, + "connections": { + "0": [ + { + "index": "0", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069548145", + "component": "virtualwirein", + "tab": "1611921777196", + "name": "db-init", + "x": 46.75, + "y": 192, + "connections": { + "0": [ + { + "index": "0", + "id": "1699965957410" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069567152", + "component": "virtualwirein", + "tab": "1611921777196", + "name": "db-init", + "x": 44.75, + "y": 465, + "connections": { + "0": [ + { + "index": "0", + "id": "1700411878636" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731070156936", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "db-init", + "x": 126.88333129882812, + "y": 1377, + "connections": { + "0": [ + { + "index": "2", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731234189516", + "component": "trigger", + "tab": "1612772287426", + "name": "monitor.txt", + "x": 882.75, + "y": 991.75, + "connections": { + "0": [ + { + "index": "5", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731234189551", + "component": "trigger", + "tab": "1612772287426", + "name": "err.txt", + "x": 904.75, + "y": 1053.75, + "connections": { + "0": [ + { + "index": "6", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1732700042559", + "component": "nodesdb_change_check", + "tab": "1612772287426", + "name": "Nodes DB change check", + "x": 266.8833312988281, + "y": 1980.2333984375, + "connections": { + "0": [ + { + "index": "0", + "id": "1732700071298" + }, + { + "index": "0", + "id": "1732700642917" + } + ], + "1": [ + { + "index": "0", + "id": "1759958914348" + }, + { + "index": "0", + "id": "1759959003114" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#888600", + "notes": "" + }, + { + "id": "1732700057052", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 76.75, + "y": 1988, + "connections": { + "0": [ + { + "index": "0", + "id": "1732700042559" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1732700071298", + "component": "debug", + "tab": "1612772287426", + "name": "nodesChange", + "x": 571.8833312988281, + "y": 2018.2333984375, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1732700642917", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "tb-push", + "x": 567.8833312988281, + "y": 1933, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1732889185927", + "component": "debug", + "tab": "1611921777196", + "name": "tempToDido", + "x": 594.8833312988281, + "y": 753, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1733574412965", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 72.75, + "y": 474, + "connections": { + "0": [ + { + "index": "1", + "id": "1731068754606" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1747561603739", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "send-to-services", + "x": 1243.8833312988281, + "y": 334.5, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1747562867845", + "component": "comment", + "tab": "1612772287426", + "name": "FLOW STARTING POINT", + "x": 1003.5666656494141, + "y": 178, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#704cff", + "notes": "" + }, + { + "id": "1749211698385", + "component": "trigger", + "tab": "1612772287426", + "name": "deviceStatus", + "x": 911.75, + "y": 1116.75, + "connections": { + "0": [ + { + "index": "7", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1757006030239", + "component": "httprequest", + "tab": "1615551125555", + "name": "192.168.252.2:8015/daily_report", + "x": 756.5666656494141, + "y": 715.4499969482422, + "connections": { + "0": [ + { + "index": "0", + "id": "1757006045804" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "stringify": "json", + "method": "POST", + "url": "http://192.168.252.2:8015/daily_report" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1757006045804", + "component": "debug", + "tab": "1615551125555", + "name": "ddd", + "x": 1091.566665649414, + "y": 711.4499969482422, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1757006060377", + "component": "debug", + "tab": "1615551125555", + "name": "reportDebug", + "x": 749.5666656494141, + "y": 799.4499969482422, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1759958914348", + "component": "httprequest", + "tab": "1612772287426", + "name": "http://192.168.252.2:8015/node_numbers", + "x": 571, + "y": 2111, + "connections": { + "0": [ + { + "index": "0", + "id": "1759958927094" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "stringify": "json", + "method": "POST", + "url": "http://192.168.252.2:8015/node_numbers" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1759958927094", + "component": "debug", + "tab": "1612772287426", + "name": "nodesChangeCloud", + "x": 951.8833312988281, + "y": 2109.2333984375, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1759959003114", + "component": "debug", + "tab": "1612772287426", + "name": "nodeChangeCloud1", + "x": 574, + "y": 2218, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1760020290879", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 84.75, + "y": 1787, + "connections": { + "0": [ + { + "index": "1", + "id": "1718016052341" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + } + ], + "version": 615 +} diff --git a/RVO2/flow/dido_controller.js b/RVO2/flow/dido_controller.js new file mode 100755 index 0000000..d16fb19 --- /dev/null +++ b/RVO2/flow/dido_controller.js @@ -0,0 +1,1486 @@ +exports.id = 'dido_controller'; +exports.title = 'DIDO_Controller'; +exports.version = '2.0.0'; +exports.group = 'Worksys'; +exports.color = '#2134B0'; +exports.input = 3; +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 + +state_of_main_switch - reportovat stav hlaveho istica : 0-> off 1-> on +rotary_switch_state - sem by sa mal reportovat stav vstupov manual a auto pola nasledovnej logiky: Manual = 1 a Auto = 0 -> Manu +Manual = 0 a Auto = 0 -> Off, Manual = 0 a Auto = 1 -> Automatic + +door_condition - pin 6, dverový kontakt -> 1 -> vyreportuje Closed, 0 -> vyreportuje Ope +twilight_sensor - hodnotu, ktoru vracia ten analogovy vstup (17) treba poslat sem ako float number. Zrejme tu potom pridame nejaky koeficient prevodu na luxy + +Na kazdu liniu +state_of_breaker - podla indexu istica sa reportuje jeho stav, teda istic na liniu 1: 0-> off, 1-> on +state_of_contactor - podla indexu stkaca sa reportuje jeho stav, teda stykac 1 na liniu 1: 0-> off, 1-> on +*/ + +const { errLogger, logger, monitor } = require('./helper/logger'); +const SerialPort = require('serialport'); +const WebSocket = require('ws'); +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 errorHandler = require('./helper/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 hasMainSwitch; + +let alarmStatus = "OFF"; + +const SEND_TO = { + debug: 0, + tb: 1, + cmd_manager: 2 +} + + +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 = {}; + let rsPortReceivedData = []; + + //to be able to get proper twilight values + let twilight_sensor_interval = 5;//minutes + let twilight_sensor = []; + const twilight_sensor_array = []; + let twilightError = false; + + monitor.info("DIDO_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-we make it global to see it from outside + FLOW.deviceStatus = { //key is device name: temperature,.... + "state_of_main_switch": "Off", //Hlavny istic (alebo druhy dverovy kontakt) + "rotary_switch_state": "Off", //Prevadzkovy + "door_condition": "closed", //Dverový kontakt + "em": "OK", //elektromer rvo + "temperature": "OK", //templomer + "battery": "OK", //Bateria + "power_supply": "OK", //Zdroj + "master_node": "OK", //MN - GLOBALS.settings.masterNodeIsResponding + "no_voltage": "OK", //GLOBALS.settings.no_voltage - vypadok napatia na faze + "state_of_breaker": {}, //"Off",//Istic + "state_of_contactor": {}, //"Off",//Stykac + "twilight_sensor": "OK" //lux sensor + }; + let deviceStatus = FLOW.deviceStatus; + + + function main() { + + GLOBALS = FLOW.GLOBALS; + SETTINGS = FLOW.GLOBALS.settings; + rvoTbName = SETTINGS.rvoTbName; + pinsData = GLOBALS.pinsData; + relaysData = GLOBALS.relaysData; + + tbHandler = new DataToTbHandler(SEND_TO.tb); + tbHandler.setSender(exports.title); + + controller_type = SETTINGS.controller_type; //"lm" or "unipi" + hasMainSwitch = SETTINGS.has_main_switch; + + if (controller_type == "") controller_type = "lm"; + + 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, "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; + } + } + + //report RVO version relaysData[0].tbname; + let values = {}; + values["edge_fw_version"] = SETTINGS.edge_fw_version; + values["maintenance_mode"] = SETTINGS.maintenance_mode; + + sendTelemetry(values, rvoTbName); + + 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); + } + + + function handleRsPort() { + + if (rsPort) { + rsPort.removeAllListeners(); + rsPort = null; + } + + //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('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) { + if (!err) { + monitor.info(exports.title + "--->Digital in_out has been set (runSyncExec was sucessfull)"); + + turnAlarm("off"); + 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('error', err => { + let message = "Dido: rsPort error: " + err.message; + logger.debug(message); + monitor.info(message); + errorHandler.sendMessageToService(message); + }) + + rsPort.on("close", () => { + let message = "Dido: rsPort closed - reconnecting ..."; + logger.debug(message); + monitor.info(message); + setTimeout(handleRsPort, 1000); + }) + + rsPort.open(); + } + + + function handleWebSocket() { + + if (ws) { + ws.removeAllListeners(); + ws = null; + } + + //to keep websocket opened, we send request every 150 seconds + let startRequests = null; + + console.log("handleWebSocket function called"); + ws = new WebSocket('ws:/0.0.0.0:1234/ws'); + + ws.onopen = function open() { + + instance.send(0, exports.title + " running"); + turnAlarm("off"); + + initialSetting(); + + setTimeout(function() { ws.send(JSON.stringify({ cmd: "all" })) }, 5000); + // we request dev info about neuron device from evok to keep websocket connection alive + // for some reason this request returns no data, but connection keeps alive + startRequests = setInterval(() => { + ws.send(JSON.stringify({ "cmd": "filter", "dev": ["neuron"] })); + }, 150000) + }; + + + // 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 = async 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; + + 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 => { + logger.debug('Dido: websocket error', err); + }) + + ws.onclose = function() { + logger.debug('Dido: websocket onclose, reconnecting...') + clearInterval(startRequests); + setTimeout(handleWebSocket, 1000); + } + } + + 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 turnAlarm(onOrOff) { + let value = 0; + if (onOrOff == "on") value = 1; + + if (value == 1 && SETTINGS.maintenance_mode) return; + + alarmStatus = "OFF"; + if (value == 1) alarmStatus = "ON"; + + if (rsPort) { + let arr = [0x55]; + arr.push(13); + arr.push(0); + arr.push(value); + + rsPort.write(Buffer.from(arr), function(err) { + logger.debug(`sirena - ${onOrOff}`); + }); + } + else if (ws) { + let cmd = { "cmd": "set", "dev": "relay", "circuit": "1_01", "value": value }; + ws.send(JSON.stringify(cmd)); + logger.debug(`sirena - ${onOrOff}`); + } + } + + + 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") { + bits.push(0); + } + else bits.push(1); + + if (deviceStatus["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); + } + + + // turn line on or off + function turnLine(onOrOff, line, pin, force, info) { + //onOrOff => "on" or "off" + let value = 0; + if (onOrOff == "on") value = 1; + + if (force == undefined) force = false; + + if (line == 0) { + if (value == 1 && alarmStatus == "ON") turnAlarm("off"); + SETTINGS.maintenance_mode = value ? true : false; + + 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); + return; + } + + if (pin === undefined) pin = getPin(line); + + if (pin === undefined) { + errLogger.error("pin is undefined!", line); + return; + } + + if (!force) { + if (relaysData[line].contactor == value) { + instance.send(SEND_TO.debug, `line is already ${onOrOff} ` + line); + logger.debug(`Dido: turnLine: line is already ${onOrOff} `, line); + return; + } + } + + // if(!rsPort.isOpen && !ws) + if (!rsPort && !ws) { + errLogger.error("Dido - port or websocket is not opened"); + return; + } + + if (rsPort) { + let arr = [0x55]; + arr.push(pin); + arr.push(0); + arr.push(value); + + rsPort.write(Buffer.from(arr), function(err) { + if (err === undefined) { + monitor.info(`Dido: turnLine ${onOrOff} zapisal do rsPort-u`, line, pin, arr, info); + switchLogic(arr); + } + else { + monitor.info(`Dido: turnLine ${onOrOff} WRITE error`, err); + } + }); + + } + else if (ws) { + //pin = "relay1_03" or "input1_01" ... we must make just "1_01" with slice method + monitor.info(`Dido: turnLine ${onOrOff} - (line, pin, force)`, line, pin, force, info); + let cmd = { "cmd": "set", "dev": "relay", "circuit": pin.slice(5), "value": value }; + ws.send(JSON.stringify(cmd)); + } + + //if rvo is 24/7, it has just one switching profile point at 13:00. we do not want to send notification as it repeats every day. + //const d = new Date(); + //if(d.getHours() != 13) sendNotification("Dido_controller: ", SETTINGS.rvoTbName, "switching_profile_point_applied_to_line", { line: line, value: onOrOff }, "", SEND_TO.tb, instance); + } + + + // 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; + + // 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) { + const status = flowdata.data.status; + if (status == "NOK-twilight_sensor") { + deviceStatus["twilight_sensor"] = "NOK"; + } + else if (status == "NOK-em340" || status == "NOK-em111") { + deviceStatus["em"] = "NOK"; + } + else if (status == "NOK-thermometer") { + deviceStatus["temperature"] = "NOK"; + } + } + else if ("values" in flowdata.data) { + 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" + } + else if (values.hasOwnProperty("temperature")) { + deviceStatus["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"; + } + + sendTelemetry(values, rvoTbName); + } + + sendRvoStatus(); + }) + + + + + // we expect array as flowdata.data + instance.on("1", flowdata => { + + //console.log(flowdata.data); + + if (!flowdata.data instanceof Object) return; + + let obj = flowdata.data; + let line = obj.line; + 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"); + }) + + + function calculateStateCode() { + + let bits = []; + + //Hlavny istic - state_of_main_switch => v rvo senica je to druhy door pre silovu cast (EM) + if (deviceStatus["state_of_main_switch"] === "closed" || deviceStatus["state_of_main_switch"] === "Off") { + bits.push(0); + } + else { + bits.push(1); + } + + //Prevadzkovy mod - Manual, Off, Automatic, maintenance_mode = true/false // DAVA 2 BITY + if (!SETTINGS.maintenance_mode) { + if (deviceStatus["rotary_switch_state"] === "Manual") { + bits.push(0); + bits.push(1); + } + + if (deviceStatus["rotary_switch_state"] === "Automatic") { + bits.push(0); + bits.push(0); + } + + if (deviceStatus["rotary_switch_state"] === "Off") { + bits.push(1); + bits.push(0); + } + } + else { + bits.push(1); + bits.push(1); + } + + //Dverovy kontakt + if (deviceStatus["door_condition"] === "closed") { + bits.push(0); + } + else { + bits.push(1); + } + + //EM + if (deviceStatus["em"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //Teplomer + if (deviceStatus["temperature"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //Batéria + if (deviceStatus["battery"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //Zdroj + if (deviceStatus["power_supply"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //MN + if (deviceStatus["master_node"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //výpadok napätia na fáze + if (deviceStatus["no_voltage"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + if (deviceStatus["twilight_sensor"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + // doplnime do 16 bitov (2 byty) + for (let i = bits.length; i < 16; i++) { + bits.push(0); + } + + // console.log("calculateStateCode - deviceStatus", deviceStatus); + // 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; + } + + + async function sendRvoStatus() { + + if (SETTINGS === undefined) return; + SETTINGS.masterNodeIsResponding ? deviceStatus["master_node"] = "OK" : deviceStatus["master_node"] = "NOK"; + + 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 pinsForRvoStatus(controllerType, hasMainSwitch) { + + let pins = []; + + if (controllerType === "lm") { + pins = [1, 4, 6]; + if (hasMainSwitch === 1) { + pins = [4, 6]; + } + } else if (controllerType === "unipi") { + pins = ["input1_01", "input1_04", "input1_05"]; + if (hasMainSwitch === 1) { + pins = ["input1_01", "input1_04"]; + } + } + + return pins; + } + + + function checkRvoStatus() { + + // 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 + //set RVO state + let status = "OK"; + + for (const [key, value] of Object.entries(deviceStatus)) { + if (["em", "twilight_sensor", "temperature", "master_node"].includes(key) && value === "NOK") status = "NOK"; + } + + if (status === "OK") { + + let pinIndexes = pinsForRvoStatus(controller_type, hasMainSwitch); + + for (const pinIndex of pinIndexes) { + if (previousValues[pinIndex] === 0) { + if ((pinIndex === 6 || pinIndex === 'input1_01' || pinIndex === 'input1_05') && SETTINGS.maintenance_mode) continue; + status = "NOK"; + break; + } + } + } + + // battery status. If value is 1 - battery is NOK + if (previousValues[5] === 1) status = "NOK"; + if (SETTINGS.no_voltage.size > 0) status = "NOK"; + + // console.log("rvo status",status) + return status; + } + + + // we pass array to function in case of rsPort ==> switchLogic([55,3,0,1]) ==> [[55,3,0,1]] + // we pass two values in case of websocket ==> switchLogic("relay1_03",1) ==> ["relay1_03",1] + const switchLogic = (...args) => { + + let values = {}; + let pinIndex, newPinValue, twilight; + + //data from rsPort + if (args.length == 1) { + pinIndex = args[0][1] + 1; + if (pinIndex === 17) pinIndex--; + newPinValue = args[0][3]; + twilight = args[0][2]; + } + //data from websocket + else { + pinIndex = args[0]; + newPinValue = args[1]; + } + + 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; + + //default value + let value = "On"; + if (newPinValue === 0) value = "Off"; + + //Hlavny istic + if (type === "state_of_main_switch" && hasMainSwitch) { + if (newPinValue === 0 && newPinValue !== previousValues[pinIndex]) { + sendNotification("switchLogic", rvoTbName, "main_switch_has_been_turned_off", {}, "", SEND_TO.tb, instance, "state_of_main_switch"); + 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"); + deviceStatus["state_of_main_switch"] = "On"; + } + } + + //Prevadzkovy mod + 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"; + + deviceStatus["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, "power_supply_has_disconnected_input", {}, "", SEND_TO.tb, instance, "power_supply"); + + deviceStatus["power_supply"] = "NOK"; + } + else if (newPinValue === 1 && newPinValue !== previousValues[pinIndex]) { + sendNotification("switchLogic", rvoTbName, "power_supply_works_correctly", {}, "", SEND_TO.tb, instance, "power_supply"); + + deviceStatus["power_supply"] = "OK"; + } + } + + //Bateria - 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"); + + deviceStatus["battery"] = "NOK"; + } + else if (newPinValue === 0 && newPinValue !== previousValues[pinIndex]) { + sendNotification("switchLogic", rvoTbName, "battery_level_is_ok", {}, "", SEND_TO.tb, instance, "battery_level"); + + deviceStatus["battery"] = "OK"; + } + } + + //Dverovy kontakt - pin 6 + //! Ak je rvo s dvoma dverovymi kontaktami, ked pride z evoku signal z input1_05, co bol predytm "state_of_main switch" handlujeme ho teraz ako 'door_condition' + else if (type == "door_condition" || type === "state_of_main_switch") { + newPinValue === 0 ? value = "open" : value = "closed"; + + let door = "door_main"; + if (type === "state_of_main_switch") door = "door_em"; + + if (value === "open") { + if (SETTINGS.maintenance_mode) { + sendNotification("switchLogic", rvoTbName, door + "_open", {}, "", SEND_TO.tb, instance, door); + } else { + sendNotification("switchLogic", rvoTbName, door + "_open_without_permission", {}, "", SEND_TO.tb, instance, door); + + // 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 (value === "closed") { + if (alarmStatus == "ON") turnAlarm("off"); + sendNotification("switchLogic", rvoTbName, door + "_close", {}, "", SEND_TO.tb, instance, door); + } + + deviceStatus[type] = value; + } + + //lux sensor + else if (type == "twilight_sensor") { + //! TODO - to show nok status, if lux value is not changing more then 10 times. + //Daylight is far more than 1000. So most of the day, when it is sunshine comes just value 1000. But lux sensor is not NOK. + //This is not the case in LM. If value from LM is the same 10x, there is 99% possibility, that sensor is NOK. + value = newPinValue; + + if (controller_type === 'lm') { + value = parseFloat(newPinValue + (256 * twilight)); + + 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 && !twilightError) { + twilightError = true; + let value = twilight_sensor_array.shift(); + + newPinValue = 0; + } + else if (set.size !== 1 && twilightError) { + //sendNotification("switchLogic", rvoTbName, 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) { + 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); + } + } + + 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); + } + + deviceStatus["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 (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 }); + + //mame iba 3 istice. vyreportujeme a ohandlujeme liniu na tom istom istici ako paralelna linia (napr linia 1, paralelna s nou je linia 4, key je string "4") + // ak je 7 linii, na 1 istici je linia 1,4,7 + + if (line == 1) { + + const lineOnSameBraker = [4, 7]; + + for (var i = 0; i < lineOnSameBraker.length; i++) { + if (!relaysData.hasOwnProperty(lineOnSameBraker[i])) continue; + + 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; + reportLineStatus(lineOnSameBraker[i]); + + values[type] = value; + const tbname = relaysData[lineOnSameBraker[i]].tbname; + sendTelemetry(values, tbname); + + delete values[type]; + } + + } + else { + const lineOnSameBraker = line + 3 + ""; + + if (relaysData.hasOwnProperty(lineOnSameBraker)) { + 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; + reportLineStatus(line + 3); + + values[type] = value; + const tbname = relaysData[lineOnSameBraker].tbname; + sendTelemetry(values, tbname); + + delete values[type]; + } + } + + } + + if (value == "Off") values["status"] = "NOK"; + deviceStatus["state_of_breaker"][line] = value; + + reportLineStatus(line); + } + else return; + + values[type] = value; + + if (type == "rotary_switch_state") { + if (SETTINGS.maintenance_mode) value = "maintenance"; + value = value.toLowerCase(); + values["power_mode"] = value; + } + + if (newPinValue != previousValues[pinIndex]) previousValues[pinIndex] = newPinValue; + if (Object.keys(values).length > 0 && tbname) sendTelemetry(values, tbname); + } + + + function sendTelemetry(values, tbname, date = Date.now()) { + let dataToTb = { + [tbname]: [ + { + "ts": date, + "values": values + } + ] + }; + + tbHandler.sendToTb(dataToTb, instance); + } + + + function isObject(item) { + return (typeof item === "object" && !Array.isArray(item) && item !== null); + } + +} //end of 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 +// *|input1_01|state_of_main_switch|0|........... +// *|input1_02|rotary_switch_state|0|........... +// *|input1_03|rotary_switch_state|0|........... +// *|intut1_04|power_supply|0|........... +// *|input1_05|door_condition|0|........... +// *|input1_06|state_of_breaker|1|........... +// *|input1_07|state_of_breaker|2|........... +// *|input1_08|state_of_breaker|3|........... +// *|relay1_02|state_of_contactor|1|........... +// *|relay1_03|state_of_contactor|2|........... +// *|relay1_04|state_of_contactor|3|........... +// *|287D8776E0013CE9|temperature|0|........... + + +//! pins_data --> from UNIPI +// { +// 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 } +// } + +//! relays_data +// { +// '0': { +// line: 0, +// tbname: 'KjbN4q7JPZmexgdnz2yKQ98YAWwO0Q3BMX6ERLoV', +// contactor: 1, +// profile: '' +// }, +// '1': { +// line: 1, +// tbname: 'RMgnK93rkoAazbqdQ4yBG95Z1YXGx6pmwBeVEP2O', +// contactor: 0, +// profile: '{"intervals":[{"value":0,"end_time":"20:00","start_time":"13:00"},{"value":1,"end_time":"10:00","start_time":"20:00"},{"value":0,"end_time":"10:20","start_time":"10:00"},{"value":1,"end_time":"10:40","start_time":"10:20"},{"value":0,"end_time":"11:00","start_time":"10:40"},{"value":1,"end_time":"11:30","start_time":"11:00"},{"value":0,"end_time":"11:50","start_time":"11:30"},{"value":1,"end_time":"13:00","start_time":"11:50"}],"astro_clock":false,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' +// }, +// '2': { +// line: 2, +// tbname: 'dlE1VQjYrNx9gZRmb38gG08oLBO4qaAk2M6JPnG7', +// contactor: 0, +// profile: '{"intervals":[{"value":0,"end_time":"20:00","start_time":"13:00"},{"value":1,"end_time":"10:00","start_time":"20:00"},{"value":0,"end_time":"10:20","start_time":"10:00"},{"value":1,"end_time":"10:40","start_time":"10:20"},{"value":0,"end_time":"11:00","start_time":"10:40"},{"value":1,"end_time":"11:30","start_time":"11:00"},{"value":0,"end_time":"11:50","start_time":"11:30"},{"value":1,"end_time":"13:00","start_time":"11:50"}],"astro_clock":false,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' +// }, +// '3': { +// line: 3, +// tbname: 'vnmG4kJxaXWNBgMQq0D7Aj5e9oZzOAlr6LdR3w2V', +// contactor: 0, +// profile: '{"intervals":[{"value":0,"end_time":"20:30","start_time":"13:00"},{"value":1,"end_time":"00:10","start_time":"20:30"},{"value":0,"end_time":"13:00","start_time":"05:40"},{"value":1,"end_time":"05:40","start_time":"00:10"}],"astro_clock":true,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' +// } +// } + + + + + +// { +// "jbN4q7JPZmexgdnz2yKbWGDYAWwO0Q3BMX6ERLoV": [ +// { +// "ts": 1700409326353, +// "values": { +// "_event": { +// "type": "notice", +// "status": "new", +// "source": { +// "func": "rsPort.open()", +// "component": "1700343402190", +// "component_name": "DIDO_Controller", +// "edge": "jbN4q7JPZmexgdnz2yKbWGDYAWwO0Q3BMX6ERLoV" +// }, +// "message": "al_shariff_10.0.0.38: FLOW has been started ", +// "message_data": "" +// } +// } +// } +// ] +// } diff --git a/RVO2/flow/helper/DataToTbHandler.js b/RVO2/flow/helper/DataToTbHandler.js new file mode 100755 index 0000000..716ef7b --- /dev/null +++ b/RVO2/flow/helper/DataToTbHandler.js @@ -0,0 +1,187 @@ +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; + this.itIsNodeReadout = false; + this.sender = ""; + + // if attribute change difference is less than limit value, we do not send to tb. + this.attributeChangeLimit = { + temperature: 0.5, + Phase_1_voltage: 2, + Phase_2_voltage: 2, + Phase_3_voltage: 2, + Phase_1_current: 0.1, + Phase_2_current: 0.1, + Phase_3_current: 0.1, + Phase_1_power: 2, + Phase_2_power: 2, + Phase_3_power: 2, + total_power: 2, + total_energy: 1, + Phase_1_pow_factor: 0.1, + Phase_2_pow_factor: 0.1, + Phase_3_pow_factor: 0.1, + power_factor: 0.1, + lifetime: 2, + voltage: 2, + power: 2, + frequency: 3, + energy: 0.1, + current: 2, + inclination_x: 10, + inclination_y: 10, + inclination_z: 10 + }; + + } + + dump() { + console.log("----------------------------"); + console.log("previousValues", this.previousValues); + console.log("----------------------------"); + } + + setSender(sender) { + this.sender = sender; + } + + isEmptyObject(obj) { + for (var _ in obj) { + return false; + } + return true; + } + + + sendToTb(data, instance) { + + //not to modify data object, we do deep copy: + let dataCopy = JSON.parse(JSON.stringify(data)); + + let keys = Object.keys(dataCopy); + + if (keys.length == 0) { + if (this.debug) console.log("sendToTb received empty object", dataCopy); + return; + } + + let tbname = keys[0]; + let ts; + + let arrayOfValues = dataCopy[tbname]; + let arrayOfValuesToSend = []; + + for (let i = 0; i < arrayOfValues.length; i++) { + + ts = arrayOfValues[i].ts; + let values = this.prepareValuesForTb(tbname, ts, arrayOfValues[i].values); + + if (!this.isEmptyObject(values)) { + arrayOfValuesToSend.push({ ts: ts, values: values }); + } + + } + + if (arrayOfValuesToSend.length == 0) { + //if(this.debug) console.log("data not sent - empty array"); + return; + } + + this.messageCounter++; + + let dataToTbModified = { + [tbname]: arrayOfValuesToSend + } + + //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); + instance.send(this.index, dataToTbModified); + } + + + getDiffTimestamp(key) { + //TODO set different value for given key!!! + //if(key == "status") this.timeToHoldTbValue = 2*60*60;//2h + return this.timeToHoldTbValue * 1000; + } + + + prepareValuesForTb(tbname, timestamp, values) { + + let keys = Object.keys(values); + + if (keys.includes("lifetime")) this.itIsNodeReadout = true; + + if (!this.previousValues.hasOwnProperty(tbname)) { + this.previousValues[tbname] = {}; + } + + //if(this.debug) console.log("prepareValuesForTb", tbname, timestamp, values); + + for (let i = 0; i < keys.length; i++) { + + let key = keys[i]; + let value = values[key]; + + if (!this.previousValues[tbname].hasOwnProperty(key)) { + this.previousValues[tbname][key] = { ts: timestamp, value: value }; + continue; + } + + // attributeData ==> {voltage: {ts:333333, value:5}} + let attributeData = this.previousValues[tbname][key]; + let attributeToChange = false; + if (key in this.attributeChangeLimit) attributeToChange = true; + let limit = this.attributeChangeLimit[key]; + let timestampDiffToRemoveKey; + + //this will ensure "node statecode" will be sent just once an hour + if (this.itIsNodeReadout && key === "statecode") { + attributeData.value = value; + this.itIsNodeReadout = false; + timestampDiffToRemoveKey = 1 * 60 * 60 * 1000; // 1 hour + } + + if (key === "twilight_sensor" && value > 100) { + attributeData.value = value; + } + + //if edge, master or node version do not change, send just once a day: + if (["edge_fw_version", "master_node_version", "fw_version"].includes(key)) { + timestampDiffToRemoveKey = 24 * 60 * 60 * 1000; + } + + if (attributeData.value === value || attributeToChange && Math.abs(attributeData.value - value) < limit) { + + let diff = timestamp - attributeData.ts; + if (!timestampDiffToRemoveKey) timestampDiffToRemoveKey = this.getDiffTimestamp(key); + + if (diff > timestampDiffToRemoveKey) { + attributeData.ts = Date.now(); + //if(this.debug) console.log(this.sender + ": update ts for key", key, "diff is", diff, "messageCounter", this.messageCounter); + } + else { + delete values[key]; + //if(this.debug) console.log(this.sender + ": delete key", key, "diff is", diff, "messageCounter", this.messageCounter, timestampDiffToRemoveKey); + } + } + else { + attributeData.value = value; + attributeData.ts = timestamp; + } + + } + + return values; + } +} + +module.exports = DataToTbHandler; + diff --git a/RVO2/flow/helper/ErrorToServiceHandler.js b/RVO2/flow/helper/ErrorToServiceHandler.js new file mode 100755 index 0000000..2b27c32 --- /dev/null +++ b/RVO2/flow/helper/ErrorToServiceHandler.js @@ -0,0 +1,91 @@ +const { MD5 } = require('./md5.js'); +const { networkInterfaces } = require('os'); + +class ErrorToServiceHandler { + constructor() { + this.previousValues = {}; + + this.project_id = undefined; + + const nets = networkInterfaces(); + this.ipAddresses = {}; + + for (const name of Object.keys(nets)) { + for (const net of nets[name]) { + // Skip over non-IPv4 and internal (i.e. 127.0.0.1) addresses + if (net.family === 'IPv4' && !net.internal) { + if (!this.ipAddresses[name]) { + this.ipAddresses[name] = []; + } + this.ipAddresses[name].push(net.address); + } + } + } + } + + setProjectId(project_id) { + this.project_id = project_id; + } + + processMessage(message, seconds) { + if (Array.isArray(message)) message = message.join(', '); + + let key = MD5(message); + let ts = Date.now(); + + //keep in memory - default value is 1h + if (seconds === undefined) seconds = 60 * 60; + + if (!this.previousValues.hasOwnProperty(key)) { + this.previousValues[key] = { ts: ts, duration: seconds }; + } + + let diff = (ts - this.previousValues[key].ts); + if (diff < this.previousValues[key].duration * 1000) return false; + + this.previousValues[key].ts = ts; + + return message; + } + + sendMessageToService(message, seconds, message_type) { + + // if error occures too early FLOW.GLOBALS.settings.project_id is still undefined + if (this.project_id === undefined) { + console.log("ErrorToServiceHandler.js: no project_id"); + return; + } + + let f = this.processMessage(message, seconds); + if (f === false) return; + + if (message_type === undefined) message_type = "error_message"; + + let toService = { + id: this.project_id, + ipAddresses: this.ipAddresses + }; + + //js_error || error_message + toService[message_type] = message; + + console.log("ErrorToServiceHandler------------------------>send to service", toService); + + RESTBuilder.make(function(builder) { + builder.method('POST'); + builder.post(toService); + builder.url('http://192.168.252.2:8004/sentmessage'); + + builder.callback(function(err, response, output) { + console.log("process.on error send", err, response, output, toService); + }); + }); + + } +} + +const errorHandler = new ErrorToServiceHandler(); + + +module.exports = errorHandler; +//module.exports = ErrorToServiceHandler; diff --git a/RVO2/flow/helper/db_helper.js b/RVO2/flow/helper/db_helper.js new file mode 100755 index 0000000..40e796c --- /dev/null +++ b/RVO2/flow/helper/db_helper.js @@ -0,0 +1,44 @@ +function promisifyBuilder(builder) +{ + return new Promise((resolve, reject) => { + + try{ + + builder.callback(function(err, response) { + + if(err != null) reject(err); + resolve(response); + }); + + } catch (error) { + reject(error); + } + }) +} + +function makeMapFromDbResult(response, ...keys) +{ + let s = "-"; + let data = {}; + + for(let i = 0; i < response.length; i++) + { + let record = response[i]; + + let k = []; + for(let j = 0; j < keys.length; j++) + { + k.push( record[keys[j]] ); + } + + let key = k.join(s); + data[ key ] = record; + } + + return data; +} + +module.exports = { + promisifyBuilder, + makeMapFromDbResult + } \ No newline at end of file diff --git a/RVO2/flow/helper/logger.js b/RVO2/flow/helper/logger.js new file mode 100755 index 0000000..2585639 --- /dev/null +++ b/RVO2/flow/helper/logger.js @@ -0,0 +1,30 @@ +//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/RVO2/flow/helper/md5.js b/RVO2/flow/helper/md5.js new file mode 100755 index 0000000..d3b0480 --- /dev/null +++ b/RVO2/flow/helper/md5.js @@ -0,0 +1,5 @@ +function MD5(d){var r = M(V(Y(X(d),8*d.length)));return r.toLowerCase()};function M(d){for(var _,m="0123456789ABCDEF",f="",r=0;r>>4&15)+m.charAt(15&_);return f}function X(d){for(var _=Array(d.length>>2),m=0;m<_.length;m++)_[m]=0;for(m=0;m<8*d.length;m+=8)_[m>>5]|=(255&d.charCodeAt(m/8))<>5]>>>m%32&255);return _}function Y(d,_){d[_>>5]|=128<<_%32,d[14+(_+64>>>9<<4)]=_;for(var m=1732584193,f=-271733879,r=-1732584194,i=271733878,n=0;n>16)+(_>>16)+(m>>16)<<16|65535&m}function bit_rol(d,_){return d<<_|d>>>32-_} + +module.exports = { + MD5 +} \ No newline at end of file diff --git a/RVO2/flow/helper/notification_reporter.js b/RVO2/flow/helper/notification_reporter.js new file mode 100755 index 0000000..839c12c --- /dev/null +++ b/RVO2/flow/helper/notification_reporter.js @@ -0,0 +1,121 @@ +//key is device, value = message {} +let sentValues = {}; +let notificationsData = null; +let rvoName; + +//sendNotification("CMD Manager: process cmd", SETTINGS.rvoTbName, "dimming_profile_was_successfully_received_by_node", { node: node }, "", SEND_TO.tb, instance); + +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 +}; + +function getKey(map, val) { + return Object.keys(map).findItem(key => map[key] === val); +} + +//https://stackoverflow.com/questions/41117799/string-interpolation-on-variable +var template = (tpl, args) => tpl.replace(/\${(\w+)}/g, (_, v) => args[v]); + + +function initNotification() { + notificationsData = FLOW.GLOBALS.notificationsData; + rvoName = FLOW.GLOBALS.settings.rvo_name; +} + + +function sendNotification(func, device, key, params, extra, tb_output, instance, saveKey) { + + let storeToSendValues = true; + if (saveKey == undefined) storeToSendValues = false; + + let weight = ""; + let message = {}; + + let notification = notificationsData[key]; + + if (notification) { + weight = notification.weight.toLowerCase(); + + Object.keys(notification).forEach(item => { + if (["en", "sk", "de", "cz", "it", "es"].includes(item)) { + message[item] = rvoName + ": " + template(notification[item], params); + } + }) + } + else { + //console.error("sendNotification: Notifications: undefined key", key, func, notificationsData); + console.error("sendNotification: Notifications: undefined key", key, func); + return false; + } + + //detect invalid err weight + if (getKey(ERRWEIGHT, weight) == undefined) { + console.error("sendNotification: Notifications: undefined weight", weight, key, func); + return false; + } + + if (sentValues.hasOwnProperty(saveKey)) { + if (JSON.stringify(sentValues[saveKey]) == JSON.stringify(message)) { + return false; + } + } + + if (sentValues[saveKey] == undefined) { + if (storeToSendValues) { + //do not send - flow is was started + sentValues[saveKey] = message; + return false; + } + } + + if (storeToSendValues) sentValues[saveKey] = message; + + let content = { + "type": weight, + "status": "new", + "source": { + "func": func, + "component": instance.id, + "component_name": instance.name, + "edge": device + }, + "message": message, + "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 + + return true; + +} + +module.exports = { + sendNotification, + ERRWEIGHT, + initNotification +} + diff --git a/RVO2/flow/helper/register.js b/RVO2/flow/helper/register.js new file mode 100755 index 0000000..fc1d008 --- /dev/null +++ b/RVO2/flow/helper/register.js @@ -0,0 +1,144 @@ +/* +0 - cislo registra / prikaz +1 - recepient - 0 = master, 1 = slave (slave je automaticky group a broadcast) +2 - r/rw - read/write +3- register name - nazov registra / prikazu (len pre info - zobrazenie v aplikacii) + +4,5,6,7, - jednotlive byte-y - nazov byte-u +4-7 - RES. a prazdny string "" sa nezobrazia!!! +*/ + +//124 zaznamov +const registers = [ + ["0","1","R","Status","","",""], + ["1","1","RW","Dimming","R-Channel ","G-Channel","B-Channel ","W - Channel"], + ["2","1","R","Device types","","",".",""], + ["3","1","RW","Group addresses 1-4","Groups Add. 4","Groups Add. 3","Groups Add. 2","Groups Add. 1"], + ["4","1","RW","Group addresses 5-8","Groups Add. 8","Groups Add. 7","Groups Add. 6","Groups Add. 5"], + ["5","1","RW","Serial number (MAC)","","","",""], + ["6","1","RW","Time of dusk","HH","MM","SS","EXTRA"], + ["7","1","RW","Time of dawn","HH","MM","SS","EXTRA"], + ["8","1","RW","Time Schedule settings","TBD","TBD","Movement sensor","Time Schedule"], + ["9","1","RW","TS1 Time point 1","HH","MM","SS","Ext. Device"], + ["10","1","RW","TS1 Time point 1 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["11","1","RW","TS1 Time point 2","HH","MM","SS","Ext. Device"], + ["12","1","RW","TS1 Time point 2 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["13","1","RW","TS1 Time point 3","HH","MM","SS","Ext. Device"], + ["14","1","RW","TS1 Time point 3 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["15","1","RW","TS1 Time point 4","HH","MM","SS","Ext. Device"], + ["16","1","RW","TS1 Time point 4 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["17","1","RW","TS1 Time point 5","HH","MM","SS","Ext. Device"], + ["18","1","RW","TS1 Time point 5 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["19","1","RW","TS1 Time point 6","HH","MM","SS","Ext. Device"], + ["20","1","RW","TS1 Time point 6 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["21","1","RW","TS1 Time point 7","HH","MM","SS","Ext. Device"], + ["22","1","RW","TS1 Time point 7 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["23","1","RW","TS1 Time point 8","HH","MM","SS","Ext. Device"], + ["24","1","RW","TS1 Time point 8 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["25","1","RW","TS1 Time point 9","HH","MM","SS","Ext. Device"], + ["26","1","RW","TS1 Time point 9 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["27","1","RW","TS1 Time point 10","HH","MM","SS","Ext. Device"], + ["28","1","RW","TS1 Time point 10 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["29","1","RW","TS1 Time point 11","HH","MM","SS","Ext. Device"], + ["30","1","RW","TS1 Time point 11 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["31","1","RW","TS1 Time point 12","HH","MM","SS","Ext. Device"], + ["32","1","RW","TS1 Time point 12 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["33","1","RW","TS1 Time point 13","HH","MM","SS","Ext. Device"], + ["34","1","RW","TS1 Time point 13 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["35","1","RW","TS1 Time point 14","HH","MM","SS","Ext. Device"], + ["36","1","RW","TS1 Time point 14 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["37","1","RW","TS1 Time point 15","HH","MM","SS","Ext. Device"], + ["38","1","RW","TS1 Time point 15 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["39","1","RW","TS1 Time point 16","HH","MM","SS","Ext. Device"], + ["40","1","RW","TS1 Time point 16 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["41","1","RW","TS2 Time point 1","HH","MM","SS","Ext. Device"], + ["42","1","RW","TS2 Time point 1 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["43","1","RW","TS2 Time point 2","HH","MM","SS","Ext. Device"], + ["44","1","RW","TS2 Time point 2 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["45","1","RW","TS2 Time point 3","HH","MM","SS","Ext. Device"], + ["46","1","RW","TS2 Time point 3 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["47","1","RW","TS2 Time point 4","HH","MM","SS","Ext. Device"], + ["48","1","RW","TS2 Time point 4 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["49","1","RW","TS2 Time point 5","HH","MM","SS","Ext. Device"], + ["50","1","RW","TS2 Time point 5 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["51","1","RW","TS2 Time point 6","HH","MM","SS","Ext. Device"], + ["52","1","RW","TS2 Time point 6 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["53","1","RW","TS2 Time point 7","HH","MM","SS","Ext. Device"], + ["54","1","RW","TS2 Time point 7 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["55","1","RW","TS2 Time point 8","HH","MM","SS","Ext. Device"], + ["56","1","RW","TS2 Time point 8 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["57","1","RW","TS2 Time point 9","HH","MM","SS","Ext. Device"], + ["58","1","RW","TS2 Time point 9 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["59","1","RW","TS2 Time point 10","HH","MM","SS","Ext. Device"], + ["60","1","RW","TS2 Time point 10 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["61","1","RW","TS2 Time point 11","HH","MM","SS","Ext. Device"], + ["62","1","RW","TS2 Time point 11 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["63","1","RW","TS2 Time point 12","HH","MM","SS","Ext. Device"], + ["64","1","RW","TS2 Time point 12 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["65","1","RW","TS2 Time point 13","HH","MM","SS","Ext. Device"], + ["66","1","RW","TS2 Time point 13 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["67","1","RW","TS2 Time point 14","HH","MM","SS","Ext. Device"], + ["68","1","RW","TS2 Time point 14 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["69","1","RW","TS2 Time point 15","HH","MM","SS","Ext. Device"], + ["70","1","RW","TS2 Time point 15 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["71","1","RW","TS2 Time point 16","HH","MM","SS","Ext. Device"], + ["72","1","RW","TS2 Time point 16 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["73","1","RW","Power meter status","TBD","","",""], + ["74","1","R","Input Voltage","","","",""], + ["75","1","R","Input Current","","","",""], + ["76","1","R","Input Power","","","",""], + ["77","1","R","Cos phi","","","",""], + ["78","1","R","Frequency","","","",""], + ["79","1","RW","Energy","","","",""], + ["80","1","RW","Lifetime","","","",""], + ["81","1","RW","Power on cycles (input)","","","",""], + ["82","1","RW","Power on cycles (relay)","","","",""], + ["83","1","R","Time since last power on","","","",""], + ["84","1","R","Accelerometer data","","","",""], + ["85","1","RW","GPS latitude","pos/neg","deg","min ","sec"], + ["86","1","RW","GPS longitude","pos/neg","deg","min ","sec"], + ["87","1","RW","Actual time","HH","MM","SS","RES."], + ["88","1","RW","Actual date","Day of week","Day","Month","Year"], + ["89","1","R","Production data 1","","","",""], + ["90","1","R","Production data 2","","","",""], + ["91","1","RW","Network ID","NID3","NID2","NID1","NID0"], + ["95","1","RW","Actual Lux level from cabinet","RES.","RES.","HB","LB"], + ["96","1","RW","Threshold lux level","Dusk HB","Dusk LB","Dawn HB","Dawn LB"], + ["97","1","RW","Adjust period","Dusk HB","Dusk LB","Dawn HB","Dawn LB"], + ["98","1","RW","Offset","RES.","RES.","Dusk","Dawn"], + ["99","1","RW","CCT min/max range","max-H","max-L","min-H","min-L"], + ["100","1","RW","DALI interface","Cmd ID","Add","Cmd","Resp"], + ["101","1","RW","Module FW ver","v1","v2","v3","v4"], + ["102","1","RW","Module MAC-H","unused","unused","M1","M2"], + ["103","1","RW","Module MAC-L","M3","M4","M5","M6"], + ["122","1","R","FW update status/control register","Byte3","Byte2","Byte1","Byte0"], + ["123","1","R","FW update - data index","Byte3","Byte2","Byte1","Byte0"], + ["124","1","R","FW update - data","Byte3","Byte2","Byte1","Byte0"], + ["0","0","R","Status","","","",""], + ["1","0","RW","Control register","RES.","RES.","RES.","init mode enable"], + ["2","0","R","Device types","","","",""], + ["3","0","R","Serial number (MAC)","","","",""], + ["4","0","R","Production data 1","","","",""], + ["5","0","R","Production data 2","","","",""], + ["6","0","RW","Network ID","NID3","NID2","NID1","NID0"], + ["7","0","RW","RS232 settings","param.","param.","Baudrate H","Baudrate L"], + ["8","0","R","Accelerometer data","","","",""], + ["9","0","RW","Module FW ver","v1","v2","v3","v4"], + ["10","0","RW","Module MAC-H","unused","unused","M1","M2"], + ["11","0","RW","Module MAC-L","M3","M4","M5","M6"], + ["32","0","RW","FW update status/control register","Byte3","Byte2","Byte1","Byte0"], + ["33","0","RW","FW update - data index","Byte3","Byte2","Byte1","Byte0"], + ["34","0","RW","FW update - data","Byte3","Byte2","Byte1","Byte0"], + ["125","0","RW","Debug Register","Byte3","Byte2","Byte1","Byte0"], + ["126","0","RW","Network Control Register","Byte3","Byte2","Byte1","Byte0"], + ["127","0","R","Network Status Register","Byte3","Byte2","Byte1","Byte0"], + ["128","0","RW","Node XX Serial Number Register","SER3","SER2","SER1","SER0"], + ["256","0","R","Node XX Network Status Register","","","",""] +]; + +let register = {}; + +module.exports = { + registers, + register +} \ No newline at end of file diff --git a/RVO2/flow/helper/serialport_helper.js b/RVO2/flow/helper/serialport_helper.js new file mode 100755 index 0000000..7f5920d --- /dev/null +++ b/RVO2/flow/helper/serialport_helper.js @@ -0,0 +1,99 @@ +const { exec } = require('child_process'); + +function openPort(port) { + return new Promise((resolve, reject) => { + + var callbackError = function(err) { + port.removeListener('error', callbackError); + port.removeListener('open', callbackError); + + reject(err.message); + }; + + var callbackOpen = function(data) { + port.removeListener('error', callbackError); + port.removeListener('open', callbackOpen); + + resolve("port open: ok"); + }; + + port.on('error', callbackError); + port.on('open', callbackOpen); + + port.open(); + + }) +} + +function runSyncExec(command) { + return new Promise((resolve, reject) => { + + exec(command, (error, stdout, stderr) => { + if (error == null) resolve(stdout); + reject(error); + }); + + }) +} + +async function writeData(port, data, readbytes, timeout) { + return new Promise((resolve, reject) => { + + // 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) { + + port.write(Buffer.from(data), function(err) { + if (err) { + reject(err.message); + } + }); + + 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 +} diff --git a/RVO2/flow/helper/suncalc.js b/RVO2/flow/helper/suncalc.js new file mode 100755 index 0000000..c9ca56d --- /dev/null +++ b/RVO2/flow/helper/suncalc.js @@ -0,0 +1,317 @@ +/* + (c) 2011-2015, Vladimir Agafonkin + SunCalc is a JavaScript library for calculating sun/moon position and light phases. + https://github.com/mourner/suncalc +*/ + +(function () { 'use strict'; + +// shortcuts for easier to read formulas + +var PI = Math.PI, + sin = Math.sin, + cos = Math.cos, + tan = Math.tan, + asin = Math.asin, + atan = Math.atan2, + acos = Math.acos, + rad = PI / 180; + +// sun calculations are based on http://aa.quae.nl/en/reken/zonpositie.html formulas + + +// date/time constants and conversions + +var dayMs = 1000 * 60 * 60 * 24, + J1970 = 2440588, + J2000 = 2451545; + +function toJulian(date) { return date.valueOf() / dayMs - 0.5 + J1970; } +function fromJulian(j) { return new Date((j + 0.5 - J1970) * dayMs); } +function toDays(date) { return toJulian(date) - J2000; } + + +// general calculations for position + +var e = rad * 23.4397; // obliquity of the Earth + +function rightAscension(l, b) { return atan(sin(l) * cos(e) - tan(b) * sin(e), cos(l)); } +function declination(l, b) { return asin(sin(b) * cos(e) + cos(b) * sin(e) * sin(l)); } + +function azimuth(H, phi, dec) { return atan(sin(H), cos(H) * sin(phi) - tan(dec) * cos(phi)); } +function altitude(H, phi, dec) { return asin(sin(phi) * sin(dec) + cos(phi) * cos(dec) * cos(H)); } + +function siderealTime(d, lw) { return rad * (280.16 + 360.9856235 * d) - lw; } + +function astroRefraction(h) { + if (h < 0) // the following formula works for positive altitudes only. + h = 0; // if h = -0.08901179 a div/0 would occur. + + // formula 16.4 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + // 1.02 / tan(h + 10.26 / (h + 5.10)) h in degrees, result in arc minutes -> converted to rad: + return 0.0002967 / Math.tan(h + 0.00312536 / (h + 0.08901179)); +} + +// general sun calculations + +function solarMeanAnomaly(d) { return rad * (357.5291 + 0.98560028 * d); } + +function eclipticLongitude(M) { + + var C = rad * (1.9148 * sin(M) + 0.02 * sin(2 * M) + 0.0003 * sin(3 * M)), // equation of center + P = rad * 102.9372; // perihelion of the Earth + + return M + C + P + PI; +} + +function sunCoords(d) { + + var M = solarMeanAnomaly(d), + L = eclipticLongitude(M); + + return { + dec: declination(L, 0), + ra: rightAscension(L, 0) + }; +} + + +var SunCalc = {}; + + +// calculates sun position for a given date and latitude/longitude + +SunCalc.getPosition = function (date, lat, lng) { + + var lw = rad * -lng, + phi = rad * lat, + d = toDays(date), + + c = sunCoords(d), + H = siderealTime(d, lw) - c.ra; + + return { + azimuth: azimuth(H, phi, c.dec), + altitude: altitude(H, phi, c.dec) + }; +}; + + +// sun times configuration (angle, morning name, evening name) + +var times = SunCalc.times = [ + [-0.833, 'sunrise', 'sunset' ], + [ -0.3, 'sunriseEnd', 'sunsetStart' ], + [ -6, 'dawn', 'dusk' ], + [ -12, 'nauticalDawn', 'nauticalDusk'], + [ -18, 'nightEnd', 'night' ], + [ 6, 'goldenHourEnd', 'goldenHour' ] +]; + +// adds a custom time to the times config + +SunCalc.addTime = function (angle, riseName, setName) { + times.push([angle, riseName, setName]); +}; + + +// calculations for sun times + +var J0 = 0.0009; + +function julianCycle(d, lw) { return Math.round(d - J0 - lw / (2 * PI)); } + +function approxTransit(Ht, lw, n) { return J0 + (Ht + lw) / (2 * PI) + n; } +function solarTransitJ(ds, M, L) { return J2000 + ds + 0.0053 * sin(M) - 0.0069 * sin(2 * L); } + +function hourAngle(h, phi, d) { return acos((sin(h) - sin(phi) * sin(d)) / (cos(phi) * cos(d))); } +function observerAngle(height) { return -2.076 * Math.sqrt(height) / 60; } + +// returns set time for the given sun altitude +function getSetJ(h, lw, phi, dec, n, M, L) { + + var w = hourAngle(h, phi, dec), + a = approxTransit(w, lw, n); + return solarTransitJ(a, M, L); +} + + +// calculates sun times for a given date, latitude/longitude, and, optionally, +// the observer height (in meters) relative to the horizon + +SunCalc.getTimes = function (date, lat, lng, height) { + + height = height || 0; + + var lw = rad * -lng, + phi = rad * lat, + + dh = observerAngle(height), + + d = toDays(date), + n = julianCycle(d, lw), + ds = approxTransit(0, lw, n), + + M = solarMeanAnomaly(ds), + L = eclipticLongitude(M), + dec = declination(L, 0), + + Jnoon = solarTransitJ(ds, M, L), + + i, len, time, h0, Jset, Jrise; + + + var result = { + solarNoon: fromJulian(Jnoon), + nadir: fromJulian(Jnoon - 0.5) + }; + + for (i = 0, len = times.length; i < len; i += 1) { + time = times[i]; + h0 = (time[0] + dh) * rad; + + Jset = getSetJ(h0, lw, phi, dec, n, M, L); + Jrise = Jnoon - (Jset - Jnoon); + + result[time[1]] = fromJulian(Jrise); + result[time[2]] = fromJulian(Jset); + } + + return result; +}; + + +// moon calculations, based on http://aa.quae.nl/en/reken/hemelpositie.html formulas + +function moonCoords(d) { // geocentric ecliptic coordinates of the moon + + var L = rad * (218.316 + 13.176396 * d), // ecliptic longitude + M = rad * (134.963 + 13.064993 * d), // mean anomaly + F = rad * (93.272 + 13.229350 * d), // mean distance + + l = L + rad * 6.289 * sin(M), // longitude + b = rad * 5.128 * sin(F), // latitude + dt = 385001 - 20905 * cos(M); // distance to the moon in km + + return { + ra: rightAscension(l, b), + dec: declination(l, b), + dist: dt + }; +} + +SunCalc.getMoonPosition = function (date, lat, lng) { + + var lw = rad * -lng, + phi = rad * lat, + d = toDays(date), + + c = moonCoords(d), + H = siderealTime(d, lw) - c.ra, + h = altitude(H, phi, c.dec), + // formula 14.1 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + pa = atan(sin(H), tan(phi) * cos(c.dec) - sin(c.dec) * cos(H)); + + h = h + astroRefraction(h); // altitude correction for refraction + + return { + azimuth: azimuth(H, phi, c.dec), + altitude: h, + distance: c.dist, + parallacticAngle: pa + }; +}; + + +// calculations for illumination parameters of the moon, +// based on http://idlastro.gsfc.nasa.gov/ftp/pro/astro/mphase.pro formulas and +// Chapter 48 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + +SunCalc.getMoonIllumination = function (date) { + + var d = toDays(date || new Date()), + s = sunCoords(d), + m = moonCoords(d), + + sdist = 149598000, // distance from Earth to Sun in km + + phi = acos(sin(s.dec) * sin(m.dec) + cos(s.dec) * cos(m.dec) * cos(s.ra - m.ra)), + inc = atan(sdist * sin(phi), m.dist - sdist * cos(phi)), + angle = atan(cos(s.dec) * sin(s.ra - m.ra), sin(s.dec) * cos(m.dec) - + cos(s.dec) * sin(m.dec) * cos(s.ra - m.ra)); + + return { + fraction: (1 + cos(inc)) / 2, + phase: 0.5 + 0.5 * inc * (angle < 0 ? -1 : 1) / Math.PI, + angle: angle + }; +}; + + +function hoursLater(date, h) { + return new Date(date.valueOf() + h * dayMs / 24); +} + +// calculations for moon rise/set times are based on http://www.stargazing.net/kepler/moonrise.html article + +SunCalc.getMoonTimes = function (date, lat, lng, inUTC) { + var t = new Date(date); + if (inUTC) t.setUTCHours(0, 0, 0, 0); + else t.setHours(0, 0, 0, 0); + + var hc = 0.133 * rad, + h0 = SunCalc.getMoonPosition(t, lat, lng).altitude - hc, + h1, h2, rise, set, a, b, xe, ye, d, roots, x1, x2, dx; + + // go in 2-hour chunks, each time seeing if a 3-point quadratic curve crosses zero (which means rise or set) + for (var i = 1; i <= 24; i += 2) { + h1 = SunCalc.getMoonPosition(hoursLater(t, i), lat, lng).altitude - hc; + h2 = SunCalc.getMoonPosition(hoursLater(t, i + 1), lat, lng).altitude - hc; + + a = (h0 + h2) / 2 - h1; + b = (h2 - h0) / 2; + xe = -b / (2 * a); + ye = (a * xe + b) * xe + h1; + d = b * b - 4 * a * h1; + roots = 0; + + if (d >= 0) { + dx = Math.sqrt(d) / (Math.abs(a) * 2); + x1 = xe - dx; + x2 = xe + dx; + if (Math.abs(x1) <= 1) roots++; + if (Math.abs(x2) <= 1) roots++; + if (x1 < -1) x1 = x2; + } + + if (roots === 1) { + if (h0 < 0) rise = i + x1; + else set = i + x1; + + } else if (roots === 2) { + rise = i + (ye < 0 ? x2 : x1); + set = i + (ye < 0 ? x1 : x2); + } + + if (rise && set) break; + + h0 = h2; + } + + var result = {}; + + if (rise) result.rise = hoursLater(t, rise); + if (set) result.set = hoursLater(t, set); + + if (!rise && !set) result[ye > 0 ? 'alwaysUp' : 'alwaysDown'] = true; + + return result; +}; + + +// export as Node module / AMD module / browser variable +if (typeof exports === 'object' && typeof module !== 'undefined') module.exports = SunCalc; +else if (typeof define === 'function' && define.amd) define(SunCalc); +else window.SunCalc = SunCalc; + +}()); diff --git a/RVO2/flow/helper/utils.js b/RVO2/flow/helper/utils.js new file mode 100755 index 0000000..dbffe45 --- /dev/null +++ b/RVO2/flow/helper/utils.js @@ -0,0 +1,161 @@ +const fs = require('fs').promises; + +function bytesToInt(bytes, numberOfBytes) { + let buffer = []; + if (Array.isArray(bytes)) { + buffer = bytes.slice(0); + if (numberOfBytes != undefined) { + buffer = bytes.slice(bytes.length - numberOfBytes); + } + } + else buffer.push(bytes); + + let result = 0; + for (let i = 0; i < buffer.length; i++) { + result = (result << 8) | buffer[i]; + } + + return result >>> 0; //ensure it's an unsigned 32-bit number +} + +function resizeArray(arr, newSize, defaultValue) { + while (newSize > arr.length) + arr.push(defaultValue); + arr.length = newSize; +} + +longToByteArray = function(/*long*/long) { + // we want to represent the input as a 8-bytes array + var byteArray = [0, 0, 0, 0, 0, 0, 0, 0]; + + for (var index = 0; index < byteArray.length; index++) { + var byte = long & 0xff; + byteArray[index] = byte; + long = (long - byte) / 256; + } + + return byteArray; +}; + +function addDays(date, days) { + var result = new Date(date); + result.setDate(result.getDate() + days); + return result; +} + +/* +sleep(2000).then(() => { + // Do something after the sleep! + + +}); +*/ + +function sleep(time) { + return new Promise((resolve) => setTimeout(resolve, time)); +} + +function isEmptyObject(obj) { + for (var name in obj) { + return false; + } + return true; +} + +function emptyJsObject(jsObject) { + Object.keys(jsObject).forEach(key => delete jsObject[key]); +} + +function convertUTCDateToLocalDate(date) { + var newDate = new Date(date); + newDate.setMinutes(date.getMinutes() + date.getTimezoneOffset()); + return newDate; +} + +function addZeroBefore(n) { + return (n < 10 ? '0' : '') + n; +} + + +/** + * Asynchronously writes data to a file. + * + * @param {string} filePath The path to the file. + * @param {string} data The data to write to the file. + * @param {boolean} [append=false] If true, appends the data to the file. If false, it overwrites the file. + */ +async function writeToFile(filePath, data, append = false) { + if (typeof data !== 'string') data = JSON.stringify(data, null, 2); + try { + if (append) { + // Append the data to the end of the file. This is the simplest way to append. + await fs.appendFile(filePath, data, 'utf8'); + console.log(`Successfully appended data to ${filePath} using fs.appendFile.`); + } else { + // Overwrite the file with the new data. + await fs.writeFile(filePath, data, 'utf8'); + console.log(`Successfully wrote (overwrote) data to ${filePath} using fs.writeFile.`); + } + } catch (error) { + console.error(`Error writing to file ${filePath}:`, error); + } +} + + + /** + * Checks if an item is present in an array and adds it if it's not. + * * @param {Array} arr The array to check. + * @param {*} item The item to add. + * @returns {Array} The modified array. + */ +const addToArrayIfUnique = (arr, item) => { + if (!arr.includes(item)) { + arr.push(item); + } + return arr; +}; + + +var convertBase = function() { + + function convertBase(baseFrom, baseTo) { + return function(num) { + return parseInt(num, baseFrom).toString(baseTo); + + }; + } + + // binary to decimal + convertBase.bin2dec = convertBase(2, 10); + + // binary to hexadecimal + convertBase.bin2hex = convertBase(2, 16); + + // decimal to binary + convertBase.dec2bin = convertBase(10, 2); + + // decimal to hexadecimal + convertBase.dec2hex = convertBase(10, 16); + + // hexadecimal to binary + convertBase.hex2bin = convertBase(16, 2); + + // hexadecimal to decimal + convertBase.hex2dec = convertBase(16, 10); + + return convertBase; +}(); + +module.exports = { + bytesToInt, + longToByteArray, + addDays, + addZeroBefore, + resizeArray, + isEmptyObject, + emptyJsObject, + sleep, + convertUTCDateToLocalDate, + writeToFile, + addToArrayIfUnique +} diff --git a/RVO2/flow/httprequest.js b/RVO2/flow/httprequest.js new file mode 100755 index 0000000..469c8cb --- /dev/null +++ b/RVO2/flow/httprequest.js @@ -0,0 +1,137 @@ +exports.id = 'httprequest'; +exports.title = 'HTTP Request'; +exports.group = 'HTTP'; +exports.color = '#5D9CEC'; +exports.input = true; +exports.version = '2.0.1'; +exports.output = 1; +exports.author = 'Peter Širka'; +exports.icon = 'cloud-upload'; + +exports.html = `
+
@(URL address)
+
+
+
@(HTTP method)
+
+
+
@(Serialization)
+
+
+
@(Download the content in chunks)
+
@(Keep persistent cookies)
+
@(Disable DNS cache)
+
@(Keep alive connection)
+
+
+
+
@(Custom headers)
+
@(Cookies)
+
+
+
+ +
+
+
+
@(User)
+
+
+
@(Password)
+
+
+
+
+
`; + +exports.readme = `# Request + +This component creates a request with received data. + +__Response:__ +\`\`\`javascript +{ + data: String, + headers: Object, + status: Number, + host: String +} +\`\`\` + +__Dynamic arguments__: +Are performed via FlowData repository and can be used for URL address or for custom headers/cookies/auth. Use \`repository\` component for creating of dynamic arguments. Dynamic values are replaced in the form \`{key}\`: + +- url address e.g. \`https://.../{key}/\` +- headers values e.g. \`{token}\` +- cookies values e.g. \`{token}\``; + +exports.install = function(instance) { + + var can = false; + var flags = null; + var cookies2 = null; + + instance.on('data', function(response) { + can && instance.custom.send(response); + }); + + instance.custom.send = function(response) { + var options = instance.options; + + var headers = null; + var cookies = null; + + options.headers && Object.keys(options.headers).forEach(function(key) { + !headers && (headers = {}); + headers[key] = response.arg(options.headers[key]); + }); + + if (options.username && options.userpassword) { + !headers && (headers = {}); + headers['Authorization'] = 'Basic ' + U.createBuffer(response.arg(options.username + ':' + options.userpassword)).toString('base64'); + } + + options.cookies && Object.keys(options.cookies).forEach(function(key) { + !cookies && (cookies = {}); + cookies[key] = response.arg(options.cookies[key]); + }); + + if (options.chunks) { + U.download(response.arg(options.url), flags, options.stringify === 'none' ? null : response.data, function(err, response) { + response.on('data', (chunks) => instance.send2(chunks)); + }, cookies || cookies2, headers); + } else { + U.request(response.arg(options.url), flags, options.stringify === 'none' ? null : response.data, 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) + instance.error(err, response); + }, cookies || cookies2, headers); + } + }; + + instance.reconfigure = function() { + var options = instance.options; + can = options.url && options.url && options.method && options.stringify ? true : false; + instance.status(can ? '' : 'Not configured', can ? undefined : 'red'); + + if (!can) + return; + + flags = []; + flags.push(options.method.toLowerCase()); + options.stringify === 'json' && flags.push('json'); + options.stringify === 'raw' && flags.push('raw'); + options.keepalive && flags.push('keepalive'); + !options.nodns && flags.push('dnscache'); + if (options.persistentcookies) { + flags.push('cookies'); + cookies2 = {}; + } else + cookies2 = null; + }; + + instance.on('options', instance.reconfigure); + instance.reconfigure(); +}; \ No newline at end of file diff --git a/RVO2/flow/httpresponse.js b/RVO2/flow/httpresponse.js new file mode 100755 index 0000000..160a3bb --- /dev/null +++ b/RVO2/flow/httpresponse.js @@ -0,0 +1,76 @@ +exports.id = 'httpresponse'; +exports.title = 'HTTP Response'; +exports.group = 'HTTP'; +exports.color = '#5D9CEC'; +exports.icon = 'arrow-right'; +exports.input = true; +exports.output = ['#666D76']; +exports.version = '2.0.0'; +exports.author = 'Martin Smola'; +exports.readme = `# HTTP response + +HTTP response will respond with data recieved using data-type set in Settings form or plain text if not set. Output is the message duration \`Number\` in seconds.`; + +exports.html = `
+
@(Response data-type)
+
JSON is by default.
+
`; + +exports.install = function(instance) { + + var dursum = 0; + var durcount = 0; + + instance.on('data', function(flowdata) { + + var ctrl = flowdata.repository.controller; + var data = flowdata.data; + + if (!ctrl) { + instance.throw('No controller to use for response!'); + return; + } + + durcount++; + dursum += ((new Date() - flowdata.begin) / 1000).floor(2); + setTimeout2(instance.id, instance.custom.duration, 500, 10); + + ctrl.$flowdata = flowdata; + + var datatype = instance.options.datatype || 'json'; + if (datatype === 'emptyresponse') + return ctrl.plain(''); + + if (datatype !== 'json' && typeof(data) !== 'string') { + instance.throw('Incorect type of data, expected string, got ' + typeof(data)); + ctrl.plain(data == null ? '' : data.toString()); + return; + } + + switch(datatype) { + case 'html': + ctrl.content(data, 'text/html'); + break; + case 'plain': + ctrl.plain(data); + break; + case 'xml': + ctrl.content(data, 'text/xml'); + break; + default: + ctrl.json(data); + break; + } + }); + + instance.on('service', function() { + dursum = 0; + durcount = 0; + }); + + instance.custom.duration = function() { + var avg = (dursum / durcount).floor(2); + instance.status(avg + ' sec.'); + instance.send2(0, avg); + }; +}; diff --git a/RVO2/flow/httproute.js b/RVO2/flow/httproute.js new file mode 100755 index 0000000..583a19d --- /dev/null +++ b/RVO2/flow/httproute.js @@ -0,0 +1,326 @@ +exports.id = 'httproute'; +exports.title = 'HTTP Route'; +exports.group = 'HTTP'; +exports.color = '#5D9CEC'; +exports.icon = 'globe'; +exports.input = false; +exports.output = ['#6CAC5A', '#37BC9B']; +exports.version = '1.2.3'; +exports.author = 'Martin Smola'; +exports.cloning = false; +exports.options = { method: 'GET', url: '', size: 5, cacheexpire: '5 minutes', cachepolicy: 0, timeout: 5 }; +exports.dateupdated = '2021-01-21 18:30d'; +exports.readme = `# HTTP route + +__Outputs__: +- first output: raw data (cache is empty or is disabled) +- second output: cached data + +If one of the outputs is disabled then automatic responce with code "503 service unavailable" is sent. + +When a request comes in bellow object is available at \`flowdata.data\`: + +\`\`\`javascript +{ + params: { id: '1' }, // params for dynamic routes, e.g. /test/{id} + query: { msg: 'Hello' }, // parsed query string, e.g. /test/1?msg=Hello + body: { test: 'OK' }, // object if json requests otherwise string + headers: {}, // headers data + session: {}, // session data + user: {}, // user data + files: [], // uploaded files + url: '/users/', // a relative URL address + referrer: '/', // referrer + mobile: false, // determines mobile device + robot: false, // determines search robots/crawlsers + language: 'en' // determines language +} +\`\`\` + +See [documentation for flags](https://docs.totaljs.com/latest/en.html#api~HttpRouteOptionsFlags~unauthorize). These method flags are set automatically e.g. \`get, post, put, patch or delete\` + +--- + +\`id:ROUTE_ID\` flag cannot be used since it's already used by this component internally`; + +exports.html = `
+
+ +
+ +
+
+
@(HTTP method)
+
+
+
@(URL address)
+
+
+
+
+
@(Additional flags)
+
@(Separate flags by comma e.g. json, authorize)
+
+
+
@(Max. request size)
+
@(In kB kilobytes)
+
+
+
@(Timeout)
+
@(In seconds.)
+
+
+
+
+
+
@(Automatically respond with 200 OK?)
+
@(If not checked you need to use HTTP response component to respond to the request.)
+
+
@(Custom headers)
+
@(Cookies)
+
+
+
+
+
+
@(Cache policy)
+
@(User instance must contain id property.)
+
+
+
@(Expiration)
+
@(E.g. 5 minutes)
+
+
+
+`; + +exports.install = function(instance) { + + var route; + + var uninstall = function(id) { + if (F.is4) { + route && route.remove(); + route = null; + } else + UNINSTALL('route', id); + }; + + instance.custom.emptyresponse = function(self) { + self.plain(); + }; + + instance.reconfigure = function() { + + var options = instance.options; + + if (!options.url) { + instance.status('Not configured', 'red'); + return; + } + + if (typeof(options.flags) === 'string') + options.flags = options.flags.split(',').trim(); + + uninstall('id:' + instance.id); + + var flags = options.flags || []; + + flags.push('id:' + instance.id); + + if (!F.is4) + flags.push(options.method.toLowerCase()); + + options.timeout && flags.push(options.timeout * 1000); + + // Make unique values + flags = flags.filter(function(v, i, a) { + if(F.is4 && v.toString().toLowerCase() === options.method.toLowerCase()) + return false; // remove method + return a.indexOf(v) === i; + }); + + options.flags = flags; + var handler = function() { + + if (instance.paused || (instance.isDisabled && (instance.isDisabled('output', 0) || instance.isDisabled('output', 1)))) { + instance.status('503 Service Unavailable'); + this.status = 503; + this.json(); + return; + } + + var key; + var self = this; + + if (instance.options.emptyresponse) { + instance.status('200 OK'); + setTimeout(instance.custom.emptyresponse, 100, self); + + if (instance.hasConnection(0)) { + var data = instance.make({ + query: self.query, + body: self.body, + session: self.session, + user: self.user, + files: self.files, + headers: self.req.headers, + url: self.url, + params: self.params + }); + instance.send2(0, data); + } + + return; + } + + switch (instance.options.cachepolicy) { + case 1: // URL + key = 'rro' + instance.id + self.url.hash(); + break; + case 2: // URL + query + case 3: // URL + query + user + key = self.url; + var keys = Object.keys(self.query); + keys.sort(); + for (var i = 0, length = keys.length; i < length; i++) + key += keys[i] + self.query[keys[i]] + '&'; + if (instance.options.cachepolicy === 3 && self.user) + key += 'iduser' + self.user.id; + key = 'rro' + instance.id + key.hash(); + break; + } + + if (key && F.cache.get2(key)) { + var data = instance.make(F.cache.get2(key)); + data.repository.controller = self; + instance.send2(1, data); + } else { + + var data = instance.make({ + query: self.query, + body: self.body, + session: self.session, + user: self.user, + files: self.files, + headers: self.req.headers, + url: self.url, + params: self.params, + mobile: self.mobile, + robot: self.robot, + referrer: self.referrer, + language: self.language + }); + + data.repository.controller = self; + instance.send2(0, data); + key && FINISHED(self.res, () => F.cache.set(key, self.$flowdata.data, instance.options.cacheexpire)); + } + }; + + if (F.is4) + route = ROUTE(options.method.toUpperCase() + ' ' + options.url, handler, flags, options.size || 5); + else + F.route(options.url, handler, flags, options.size || 5); + + instance.status('Listening', 'green'); + }; + + instance.reconfigure(); + instance.on('options', instance.reconfigure); + instance.on('close', function(){ + uninstall('id:' + instance.id); + }); +}; + +// check url exists +FLOW.trigger('httproutecheckurl', function(next, data) { + var url = data.url; + var method = data.method; + if (url[url.length - 1] !== '/') + url += '/'; + var exists = F.routes.web.findItem(r => r.urlraw === url && r.method === method); + next(exists != null); +}); + +exports.uninstall = function() { + FLOW.trigger('httproutecheckurl', null); +}; diff --git a/RVO2/flow/infosender.js b/RVO2/flow/infosender.js new file mode 100755 index 0000000..587724f --- /dev/null +++ b/RVO2/flow/infosender.js @@ -0,0 +1,81 @@ +exports.id = 'infosender'; +exports.title = 'Info sender'; +exports.version = '1.0.0'; +exports.group = 'Worksys'; +exports.color = '#2134B0'; +exports.input = 2; +exports.output = 1 +exports.icon = 'bolt'; + +const { networkInterfaces } = require('os'); + +exports.html = `
+
+
+
CSV Import
+
+
+
`; + +exports.readme = `# send all data to projects.worksys.io, required to monitor status of controller(unipi)`; + +exports.install = function(instance) { + + let id; + let allValues = {}; + let sendAllValuesInterval; + let configured = false; + + let now = new Date(); + console.log(exports.title, "INSTALLED", now.toLocaleString("sk-SK")); + + const nets = networkInterfaces(); + let ipAddresses = Object.create(null); // Or just '{}', an empty object + + for (const name of Object.keys(nets)) { + for (const net of nets[name]) { + // Skip over non-IPv4 and internal (i.e. 127.0.0.1) addresses + if (net.family === 'IPv4' && !net.internal) { + if (!ipAddresses[name]) { + ipAddresses[name] = []; + } + ipAddresses[name].push(net.address); + } + } + } + + function sendValues() { + if (!configured) return; + + if (Object.keys(allValues).length > 0) { + let dataToSend = { ...allValues }; + dataToSend.id = id; + dataToSend.ipAddresses = ipAddresses; + + instance.send(0, dataToSend); + + allValues = {}; + } + } + + instance.on("close", () => { + clearInterval(sendAllValuesInterval); + }) + + instance.on("0", _ => { + id = FLOW.GLOBALS.settings.project_id; + if (id) configured = true; + else console.log(exports.title, "InfoSender: Unable to send data, no id"); + }) + + instance.on("1", flowdata => { + allValues = { ...allValues, ...flowdata.data }; + //console.log("DATA RECEIVED", flowdata.data); + }) + + sendAllValuesInterval = setInterval(() => { + sendValues(); + }, 60000 * 3); + +} + diff --git a/RVO2/flow/modbus_reader.js b/RVO2/flow/modbus_reader.js new file mode 100755 index 0000000..d6d9dad --- /dev/null +++ b/RVO2/flow/modbus_reader.js @@ -0,0 +1,346 @@ +exports.id = 'modbus_reader'; +exports.title = 'Modbus reader'; +exports.version = '2.0.0'; +exports.group = 'Worksys'; +exports.color = '#2134B0'; +exports.input = 1; +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; +//number of phases inRVO +let phases; +//phases where voltage is 0 (set) +let noVoltage; +let energyToSwitchLamps; + +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.phases = this.buildPhases(); + + this.startSocket(); + } + + buildPhases = () => { + let a = []; + for (let i = 1; i <= phases; i++) { + a.push(`Phase_${i}_voltage`) + } + return a; + } + + startSocket = () => { + + let obj = this; + + if (this.socket) { + this.socket.removeAllListeners(); + this.socket = null; + } + + 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('Modbus_reader: Socket connection error', e); //'ECONNREFUSED' or 'ECONNRESET' ?? + }); + + this.socket.on('close', function() { + console.log('Modbus_reader: Socket connection closed - Waiting 10 seconds before connecting 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 we just start to loop devices from the beginning, or there is just 1 device in config, we wait whole timeoutInterval + if (this.indexInDeviceConfig == 0 || deviceConfig.length === 1) 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 (this.phases.includes(singleValue)) { + let l = singleValue.split("_"); + let phase = parseInt(l[1]); + + // console.log(values[singleValue], tbName); + + if (values[singleValue] == 0) { + noVoltage.add(phase); + sendNotification("modbus_reader: checkNullVoltage", tbName, "no_voltage_on_phase", { phase: phase }, "", SEND_TO.tb, instance, "voltage" + phase); + // console.log('no voltage') + } + else { + noVoltage.delete(phase); + // console.log('voltage detected') + sendNotification("modbus_reader: checkNullVoltage", tbName, "voltage_on_phase_restored", { phase: phase }, "", SEND_TO.tb, instance, "voltage" + phase); + } + } + }) + } + + /** + * function sends notification to slack and to tb, if EM total_power value changes more than numberOfNodes*15. This should show, that RVO lamps has been switched on or off + */ + lampSwitchNotification = (values) => { + + if (!values.hasOwnProperty("total_power")) return; + + const actualTotalPower = values.total_power; + + if (actualTotalPower > energyToSwitchLamps && 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 <= energyToSwitchLamps && 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; + } + + function main() { + + phases = FLOW.GLOBALS.settings.phases; + tbName = FLOW.GLOBALS.settings.rvoTbName; + noVoltage = FLOW.GLOBALS.settings.no_voltage; + energyToSwitchLamps = FLOW.GLOBALS.settings.energy_to_switch_lamps / 2.5; //half value is enought to show if lamps are turned on or off + if (deviceConfig.length) mainSocket = new SocketWithClients(); + else console.log("Modbus_reader: no modbus device in configuration"); + + // this notification is to show, that flow (unipi) has been restarted + sendNotification("modbus_reader", tbName, "flow_restart", {}, "", SEND_TO.slack, instance); + } + + instance.on("0", function(_) { + main(); + }) + +} + diff --git a/RVO2/flow/monitorconsumption.js b/RVO2/flow/monitorconsumption.js new file mode 100755 index 0000000..64cc58e --- /dev/null +++ b/RVO2/flow/monitorconsumption.js @@ -0,0 +1,156 @@ +exports.id = 'monitorconsumption'; +exports.title = 'Consumption'; +exports.version = '1.0.0'; +exports.author = 'Peter Širka'; +exports.group = 'Monitoring'; +exports.color = '#967ADC'; +exports.input = 0; +exports.output = 1; +exports.icon = 'bug'; +exports.options = { interval: 5000, enabled: true, monitorconsumption: true, monitorsize: true, monitorconnections: true, monitorfiles: true }; +exports.click = true; +exports.readme = `# Consumption monitoring + +This component measure CPU and memory consumption, open files and open connections of this application. It uses these Linux commands: \`ps\`, \`lsof\`, \`netstat\` and \`df\`. + +__Data Example__: + +\`\`\`javascript +{ + cpu: 0, // percentage + memory: 4096, // in bytes + size: 34303, // directory size in bytes + files: 34, // count of open files + connections: 343, // count of connections + uptime: '1-12:34:00' +} +\`\`\``; + +exports.html = `
+
+
+
@(Interval in milliseconds)
+
+
+
+
Monitor: Consumption + uptime
+
Monitor: Count of open files
+
Monitor: Count of open connections
+
Monitor: Directory size
+
`; + +exports.install = function(instance) { + + var current = { cpu: 0, memory: 0, files: 0, connections: 0, size: 0, uptime: '', counter: 0 }; + var tproc = null; + var Exec = require('child_process').exec; + var reg_empty = /\s{2,}/g; + var reg_appdisksize = /^[\d.,]+/; + + instance.custom.run = function() { + + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + + var arr = []; + + // Get CPU and Memory consumption + instance.options.monitorconsumption && arr.push(function(next) { + Exec('ps -p {0} -o %cpu,rss,etime'.format(process.pid), function(err, response) { + + if (err) { + instance.throw(err); + } else { + var line = response.split('\n')[1]; + line = line.trim().replace(reg_empty, ' ').split(' '); + var cpu = line[0].parseFloat(); + current.cpu = cpu.floor(1); + current.memory = line[1].parseInt2() * 1024; // kB to bytes + current.uptime = line[2]; + } + + next(); + }); + }); + + // Get count of open files + instance.options.monitorfiles && arr.push(function(next) { + Exec('lsof -a -p {0} | wc -l'.format(process.pid), function(err, response) { + if (err) + instance.throw(err); + else + current.files = response.trim().parseInt2(); + next(); + }); + }); + + // Get count of opened network connections + instance.options.monitorconnections && arr.push(function(next) { + Exec('netstat -an | grep :{0} | wc -l'.format(F.port), function(err, response) { + if (err) { + instance.throw(err); + } else { + current.connections = response.trim().parseInt2() - 1; + if (current.connections < 0) + current.connections = 0; + } + next(); + }); + }); + + // Get directory size + instance.options.monitorsize && current.counter % 5 !== 0 && arr.push(function(next) { + Exec('du -hsb ' + process.cwd(), function(err, response) { + if (err) { + instance.throw(err); + } else { + var match = response.trim().match(reg_appdisksize); + match && (current.size = match.toString().trim().parseInt2()); + } + next(); + }); + }); + + arr.async(function() { + + tproc && clearTimeout(tproc); + + if (instance.options.enabled) { + tproc = setTimeout(instance.custom.run, instance.options.interval); + instance.send2(current); + } + + instance.custom.status(); + current.counter++; + }); + }; + + instance.custom.status = function() { + if (instance.options.enabled) + instance.status('{0}% / {1}'.format(current.cpu, current.memory.filesize())); + else + instance.status('Disabled', 'red'); + }; + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + + if (instance.options.enabled) { + current.counter = 0; + instance.custom.run(); + } + + }); + + instance.on('close', function() { + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + }); + + setTimeout(instance.custom.run, 1000); +}; \ No newline at end of file diff --git a/RVO2/flow/monitordisk.js b/RVO2/flow/monitordisk.js new file mode 100755 index 0000000..f4fdaa0 --- /dev/null +++ b/RVO2/flow/monitordisk.js @@ -0,0 +1,96 @@ +exports.id = 'monitordisk'; +exports.title = 'Disk'; +exports.version = '1.0.0'; +exports.author = 'Peter Širka'; +exports.group = 'Monitoring'; +exports.color = '#F6BB42'; +exports.output = 1; +exports.icon = 'hdd-o'; +exports.click = true; +exports.options = { interval: 8000, path: '/', enabled: true }; +exports.readme = `# Disk monitoring + +This component monitors disk \`bytes\` consumption in Linux systems. It uses \`df\` command. + +__Data Example__: + +\`\`\`javascript +{ + total: 474549649408, + used: 39125245952, + free: 411294994432 +} +\`\`\``; + +exports.html = `
+
+
+
@(Interval in milliseconds)
+
+
+
@(Path)
+
+
+
`; + +exports.install = function(instance) { + + var current = { total: 0, used: 0, free: 0, path: '', type: '', percentUsed: 0 }; + var tproc = null; + + instance.custom.run = function() { + + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + + if (!instance.options.enabled) + return; + + require('child_process').exec('df -hTB1 ' + instance.options.path, function(err, response) { + + tproc = setTimeout(instance.custom.run, instance.options.interval); + + if (err) { + instance.error(err); + return; + } + + response.parseTerminal(function(line) { + if (line[0][0] !== '/') + return; + current.total = line[2].parseInt(); + current.free = line[4].parseInt(); + current.used = line[3].parseInt(); + current.path = instance.options.path || '/'; + current.type = line[1]; + current.percentUsed = line[5]; + instance.custom.status(); + instance.send2(current); + }); + }); + }; + + instance.custom.status = function() { + if (instance.options.enabled) + instance.status(current.free.filesize() + ' / ' + current.total.filesize()); + else + instance.status('Disabled', 'red'); + }; + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + instance.options.enabled && instance.custom.run(); + }); + + instance.on('close', function() { + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + }); + + setTimeout(instance.custom.run, 1000); +}; \ No newline at end of file diff --git a/RVO2/flow/monitormemory.js b/RVO2/flow/monitormemory.js new file mode 100755 index 0000000..2decbc4 --- /dev/null +++ b/RVO2/flow/monitormemory.js @@ -0,0 +1,87 @@ +exports.id = 'monitormemory'; +exports.title = 'Memory'; +exports.version = '1.0.0'; +exports.author = 'Peter Širka'; +exports.group = 'Monitoring'; +exports.color = '#F6BB42'; +exports.output = 1; +exports.click = true; +exports.icon = 'microchip'; +exports.options = { interval: 8000, enabled: true }; +exports.readme = `# Memory monitoring + +This component monitors memory \`bytes\` consumption in Linux systems. It uses \`free\` command. + +__Data Example__: + +\`\`\`javascript +{ + total: 33558769664, + used: 1998868480, + free: 2653708288 +} +\`\`\``; + +exports.html = `
+
+
+
@(Interval in milliseconds)
+
+
+
`; + +exports.install = function(instance) { + + var current = { total: 0, used: 0, free: 0 }; + var tproc = null; + + instance.custom.run = function() { + + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + + if (!instance.options.enabled) + return; + + require('child_process').exec('free -b -t', function(err, response) { + + tproc = setTimeout(instance.custom.run, instance.options.interval); + + if (err) { + instance.error(err); + return; + } + + var memory = response.split('\n')[1].match(/\d+/g); + current.total = memory[0].parseInt(); + current.used = memory[1].parseInt() - memory[3].parseInt(); + current.free = current.total - current.used; + instance.custom.status(); + instance.send2(current); + }); + }; + + instance.custom.status = function() { + if (instance.options.enabled) + instance.status(current.free.filesize() + ' / ' + current.total.filesize()); + else + instance.status('Disabled', 'red'); + }; + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + instance.options.enabled && instance.custom.run(); + }); + + instance.on('close', function() { + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + }); + + setTimeout(instance.custom.run, 1000); +}; \ No newline at end of file diff --git a/RVO2/flow/nodesdb_changecheck.js b/RVO2/flow/nodesdb_changecheck.js new file mode 100755 index 0000000..9adab62 --- /dev/null +++ b/RVO2/flow/nodesdb_changecheck.js @@ -0,0 +1,77 @@ +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 = 2; +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); + } + } + + //kedze do slacku posielame stringy, na cloud musime previest vsetky stringy spat na objekty: + // Funkcia na parsovanie všetkých reťazcov v poli + const parseArray = (arr) => { + return arr.map(jsonString => JSON.parse(jsonString)); + }; + + 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); + if (FLOW.GLOBALS.settings.send_changed_node_numbers) instance.send(1, { aktualneNody: parseArray(zmenene), originalne: parseArray(Array.from(set2)) }); + } + 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/RVO2/flow/show_dbdata.js b/RVO2/flow/show_dbdata.js new file mode 100755 index 0000000..1e23ff7 --- /dev/null +++ b/RVO2/flow/show_dbdata.js @@ -0,0 +1,243 @@ +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 = 8; +exports.output = 1; + +const { exec } = require('child_process'); + +exports.install = 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 }) + }) + instance.on("5", _ => { + exec("sudo tail -n 25 monitor.txt", (err, stdout, stderr) => { + if (err || stderr) instance.send(0, { err, stderr }); + else instance.send(0, stdout); + }) + }) + instance.on("6", _ => { + exec("sudo tail -n 25 err.txt", (err, stdout, stderr) => { + if (err || stderr) instance.send(0, { err, stderr }); + else instance.send(0, stdout); + }) + }) + instance.on("7", _ => { + instance.send(0, FLOW.deviceStatus); + }) +}; + + +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/RVO2/flow/slack_filter.js b/RVO2/flow/slack_filter.js new file mode 100755 index 0000000..6618523 --- /dev/null +++ b/RVO2/flow/slack_filter.js @@ -0,0 +1,188 @@ +exports.id = 'slack_filter'; +exports.title = 'Slack Filter'; +exports.group = 'Citysys'; +exports.color = '#30E193'; +exports.input = 2; +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 = `
+
+
+
@(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('0', 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']['en']; + 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"] = []; + } + + instance.options.name = FLOW.GLOBALS.settings.rvo_name; + if (instance.options.name) { + instance.status('Running'); + running = true; + } else { + instance.status('Please run options again', 'red'); + running = false; + } + } catch (e) { + instance.error('Citysys connector: ' + e.message); + } + }; + + instance.on('options', instance.reconfigure); + + instance.on("1", _ => { + instance.reconfigure(); + }) +}; diff --git a/RVO2/flow/thermometer.js b/RVO2/flow/thermometer.js new file mode 100755 index 0000000..fc7074d --- /dev/null +++ b/RVO2/flow/thermometer.js @@ -0,0 +1,99 @@ +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 = 5;//minutes +let NUMBER_OF_FAILURES_TO_SEND_ERROR = 13; + +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) => { + + 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); + setTimeout(main, 20000); + }) +}; diff --git a/RVO2/flow/trigger.js b/RVO2/flow/trigger.js new file mode 100755 index 0000000..27545a8 --- /dev/null +++ b/RVO2/flow/trigger.js @@ -0,0 +1,79 @@ +exports.id = 'trigger'; +exports.title = 'Trigger'; +exports.group = 'Inputs'; +exports.color = '#F6BB42'; +exports.click = true; +exports.output = 1; +exports.version = '1.1.0'; +exports.author = 'Martin Smola'; +exports.icon = 'play'; + +exports.html = `
+
@(Data type (String by default))
+
@(Data)
+
Trigger 5s after initialization.
+
@(Useful when there's a need to run certain flow when the app restarts, etc.)
+
`; + +exports.readme = `# Trigger + +- Clicking on the component starts the chain +- Settings allows to set a data-type and a value`; + +exports.install = function(instance) { + + var value; + + instance.on('click', () => instance.send2(value)); + + instance.reconfigure = function() { + var options = instance.options; + value = null; + switch (options.datatype) { + case 'integer': + value = options.data.parseInt2('error'); + value = value === 'error' ? NaN : value; + break; + case 'float': + value = options.data.parseFloat2('error'); + value = value === 'error' ? NaN : value; + break; + case 'date': + options.data = options.data.toString(); + var num = options.data.parseInt('error'); + num === 'error' && (num = options.data.parseDate('error')); + num === 'error' && (num = null); + value = num ? new Date(num).toUTCString() : num; + break; + case 'object': + try { + value = (new Function('return ' + options.data))(); + } catch (e) { + instance.error(e); + } + break; + case 'boolean': + value = options.data.parseBoolean(); + break; + case 'buffer': + try { + value = U.createBuffer(options.data); + } catch (e) { + instance.error(e); + } + break; + case 'string': + default: + value = '' + (options.data || ''); + break; + } + }; + + instance.on('options', instance.reconfigure); + instance.reconfigure(); + + if (instance.options.restart) + setTimeout(function(){ + instance.send2(value); + }, 5000); +}; diff --git a/RVO2/flow/variables.txt b/RVO2/flow/variables.txt new file mode 100755 index 0000000..e69de29 diff --git a/RVO2/flow/virtualwirein.js b/RVO2/flow/virtualwirein.js new file mode 100755 index 0000000..38a4e42 --- /dev/null +++ b/RVO2/flow/virtualwirein.js @@ -0,0 +1,43 @@ +exports.id = 'virtualwirein'; +exports.title = 'Virtual wire in'; +exports.version = '1.0.0'; +exports.author = 'Martin Smola'; +exports.color = '#303E4D'; +exports.icon = 'sign-in'; +exports.input = false; +exports.output = 1; +exports.options = {}; +exports.readme = `# Virtual wire in + +When the wires between the components are mess it's time to use Virtual wire.`; + +exports.html = `
+
@(Wire name)
+
+`; + +exports.install = function(instance) { + + instance.custom.reconfigure = function(options){ + if (instance.options.wirename) { + instance.status(instance.options.wirename); + } else + instance.status('Not configured', 'red'); + }; + + ON('virtualwire', function(wirename, flowdata){ + if (instance.options.wirename && instance.options.wirename === wirename) + instance.send(flowdata); + }); + + instance.on('options', instance.custom.reconfigure); + instance.custom.reconfigure(); +}; diff --git a/RVO2/flow/virtualwireout.js b/RVO2/flow/virtualwireout.js new file mode 100755 index 0000000..94a1e4f --- /dev/null +++ b/RVO2/flow/virtualwireout.js @@ -0,0 +1,41 @@ +exports.id = 'virtualwireout'; +exports.title = 'Virtual wire out'; +exports.version = '1.0.0'; +exports.author = 'Martin Smola'; +exports.color = '#303E4D'; +exports.icon = 'sign-out'; +exports.input = true; +exports.options = {}; +exports.readme = `# Virtual wire out + +When the wires between the components are mess it's time to use Virtual wire.`; + +exports.html = `
+
@(Wire name)
+
+`; + +exports.install = function(instance) { + + instance.custom.reconfigure = function(){ + if (instance.options.wirename) { + instance.status(instance.options.wirename); + } else + instance.status('Not configured', 'red'); + }; + + instance.on('data', function(flowdata) { + EMIT('virtualwire', instance.options.wirename, flowdata); + }); + + instance.on('options', instance.custom.reconfigure); + instance.custom.reconfigure(); +}; diff --git a/RVO2/flow/wsmqttpublish.js b/RVO2/flow/wsmqttpublish.js new file mode 100755 index 0000000..0eba804 --- /dev/null +++ b/RVO2/flow/wsmqttpublish.js @@ -0,0 +1,448 @@ +exports.id = 'wsmqttpublish'; +exports.title = 'WS MQTT publish'; +exports.group = 'MQTT'; +exports.color = '#888600'; +exports.version = '1.0.2'; +exports.icon = 'sign-out'; +exports.input = 2; +exports.output = 3; +exports.options = { host: 'tb-stage.worksys.io', port: 1883, clientid: "", username: "" }; + +exports.html = `
+
+
+
Hostname or IP address (if not empty - setting will override db setting)
+
+
+
Port
+
+
+
+
+
@(Client id)
+
+
+
@(Username)
+
+
+
`; + + +exports.readme = ` +# WS MQTT Publish + +Version 1.0.3. + +Added: +- database collections, +- 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 = { + debug: 0, + rpcCall: 1, + services: 2 +} + +//CONFIG +let createTelemetryBackup = true; +let saveTelemetryOnError = true;//backup_on_failure overrides this value +//------------------------ + +let rollers; +if (createTelemetryBackup) rollers = require('streamroller'); + +const noSqlFileSizeLimit = 4194304;//use 5MB - 4194304 +let insertNoSqlCounter = 0; +let insertBackupNoSqlCounter = 0; +let processingData = false; + +let backup_on_failure = false;//== saveTelemetryOnError - create backup client 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; + +process.on('uncaughtException', function(err) { + + errLogger.error('uncaughtException:', err.message) + errLogger.error(err.stack); + + //TODO + //send to service + + //process.exit(1); +}) + +const nosql = NOSQL('tbdata'); +const nosqlBackup = NOSQL('/backup/tbdata'); + + +exports.install = function(instance) { + + var client; + var opts; + var clientReady = false; + + // wsmqtt status for notification purposes on projects.worksys.io database + let wsmqttName = null; + let sendWsStatusVar = null; + let wsmqtt_status = 'disconnected'; + + 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'; + } + + function sendWsStatus() { + instance.send(SEND_TO.services, { [wsmqttName]: wsmqtt_status }); + } + + + function main() { + if (!FLOW.dbLoaded) return; + + loadSettings(); + clearInterval(sendWsStatus); + sendWsStatusVar = setInterval(sendWsStatus, 180000); + } + + //set opts according to db settings + function loadSettings() { + + if (instance.options.host !== "") { + //override settings from database + var o = instance.options; + opts = { + host: o.host, + port: o.port, + clientId: o.clientid, + username: o.username, + rejectUnauthorized: false, + resubscribe: false + }; + + wsmqttName = getWsmqttName(o.host); + + console.log("wsmqttpublich -> loadSettings from instance.options", instance.options); + } + else { + + const SETTINGS = FLOW.GLOBALS.settings; + backup_on_failure = SETTINGS.backup_on_failure; + saveTelemetryOnError = backup_on_failure; + + restore_from_backup = SETTINGS.restore_from_backup; + restore_backup_wait = SETTINGS.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; + + opts = { + host: mqtt_host, + port: mqtt_port, + keepalive: 10, + clientId: mqtt_clientid, + username: mqtt_username, + rejectUnauthorized: false, + resubscribe: false + }; + + wsmqttName = getWsmqttName(mqtt_host); + } + + connectToTbServer(); + } + + function connectToTbServer() { + 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"); + //monitor.info("MQTT client connected"); + + sendClientError = true; + clientReady = true; + wsmqtt_status = 'connected'; + }); + + client.on('reconnect', function() { + instance.status("Reconnecting", "yellow"); + clientReady = false; + }); + + client.on('message', function(topic, message) { + // message is type of buffer + message = message.toString(); + if (message[0] === '{') { + TRY(function() { + + message = JSON.parse(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 } }); + } + + }, () => instance.debug('MQTT: Error parsing data', message)); + } + + instance.send(SEND_TO.rpcCall, { "topic": topic, "content": message }); + }); + + client.on('close', function() { + clientReady = false; + wsmqtt_status = 'disconnected'; + + instance.status("Disconnected", "red"); + instance.send(SEND_TO.debug, { "message": "Client CLOSE signal received !" }); + }); + + client.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; + wsmqtt_status = 'disconnected'; + }); + + } + + + instance.on("0", _ => { + main(); + }) + + + instance.on('1', function(data) { + + if (clientReady) { + //do we have some data in backup file? if any, process data from database + if (saveTelemetryOnError) { + //read telemetry data and send back to server + if (!processingData) processDataFromDatabase(); + } + + let stringifiedJson = JSON.stringify(data.data); + client.publish("v1/gateway/telemetry", stringifiedJson, { qos: 1 }); + + //backup telemetry + if (createTelemetryBackup) { + data.data.id = UID(); + nosqlBackup.insert(data.data); + + insertBackupNoSqlCounter++; + if (insertBackupNoSqlCounter > 150) { + let options = { compress: true }; + let path = __dirname + "/../databases/backup/tbdata.nosql"; + var stream = new rollers.RollingFileStream(path, noSqlFileSizeLimit, 150, options); + stream.write(""); + stream.end(); + + insertBackupNoSqlCounter = 0; + } + } + + } + 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 (saveTelemetryOnError) { + //create new file from tbdata.nosql, if file size exceeds given limit, and clear tbdata.nosql + makeBackupFromDbFile(); + + //write to tb + data.data.id = UID(); + nosql.insert(data.data); + } + } + }); + + + instance.close = function(done) { + if (clientReady) { + client.end(); + clearInterval(sendWsStatusVar); + } + }; + + + function getDbBackupFileCounter(type) { + var files = fs.readdirSync(__dirname + "/../databases"); + + let counter = 0; + for (var i = 0; i < files.length; i++) { + + if (files[i] == "tbdata.nosql") continue; + + if (files[i].endsWith(".nosql")) { + + let pos = files[i].indexOf("."); + if (pos > -1) { + + let fileCounter = counter; + let firstDigit = files[i].slice(0, pos); + + fileCounter = parseInt(firstDigit); + if (isNaN(fileCounter)) fileCounter = 0; + //console.log("getDbBackupFileCounter digit:", files[i], firstDigit, fileCounter, isNaN(fileCounter), type); + + if (type == "max") { + if (fileCounter > counter) { + counter = fileCounter; + } + } + else if (type == "min") { + if (counter == 0) counter = fileCounter; + + if (fileCounter < counter) { + counter = fileCounter; + } + } + } + } + + } + + if (type == "max") counter++; + + return counter; + } + + const makeBackupFromDbFile = async () => { + + if (!saveTelemetryOnError) return; + + //to avoid large file: tbdata.nosql + + //init value is 0! + if (insertNoSqlCounter > 0) { + --insertNoSqlCounter; + return; + } + + insertNoSqlCounter = 100; + + let source = __dirname + "/../databases/tbdata.nosql"; + + var stats = fs.statSync(source); + var fileSizeInBytes = stats.size; + + if (fileSizeInBytes > noSqlFileSizeLimit) { + + let counter = 1; + counter = getDbBackupFileCounter("max"); + + let destination = __dirname + "/../databases/" + counter + "." + "tbdata.nosql"; + + //make backup file + fs.copyFileSync(source, destination); + //fs.renameSync(p, p + "." + counter); + + //clear tbdata.nosql + fs.writeFileSync(source, ""); + fs.truncateSync(source, 0); + + } + } + + const processDataFromDatabase = async () => { + + if (restore_from_backup <= 0) return; + + //calculate diff + const now = new Date(); + let currentTime = now.getTime(); + let diff = currentTime - lastRestoreTime; + + if ((diff / 1000) < restore_backup_wait) { + //console.log("*********restore_backup_wait", diff, restore_backup_wait); + return; + } + + processingData = true; + + //get filename to process + let counter = getDbBackupFileCounter("min"); + + //we have some backup files + let dataBase = 'tbdata'; + + var nosql; + if (counter == 0) dataBase = 'tbdata'; + else dataBase = counter + "." + 'tbdata'; + + nosql = NOSQL(dataBase); + + //select all data - use limit restore_from_backup + let records = await promisifyBuilder(nosql.find().take(restore_from_backup)); + + for (let i = 0; i < records.length; i++) { + if (clientReady) { + + let item = records[i]; + let id = item.id; + + if (id !== undefined) { + //console.log("------------processDataFromDatabase - remove", id, dataBase, i); + + try { + + let message = JSON.parse(JSON.stringify(item)); + delete message.id; + + client.publish("v1/gateway/telemetry", JSON.stringify(message), { qos: 1 }); + + //remove from database + await promisifyBuilder(nosql.remove().where("id", id)); + + } catch (error) { + //process error + console.log("processDataFromDatabase", error); + } + + } + + } + else { + processingData = false; + return; + } + } + + if (records.length > 0) { + //clean backup file + if (counter > 0) nosql.clean(); + } + + //no data in db, remove + if (records.length == 0) { + if (counter > 0) nosql.drop(); + } + + const d = new Date(); + lastRestoreTime = d.getTime(); + + processingData = false; + + } + + instance.on('options', main); + //instance.reconfigure(); +}; diff --git a/RVO2/flow_22_01_25/audit_test_panel.csv b/RVO2/flow_22_01_25/audit_test_panel.csv new file mode 100755 index 0000000..907a6a9 --- /dev/null +++ b/RVO2/flow_22_01_25/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/RVO2/flow_22_01_25/cloudmqttconnect.js b/RVO2/flow_22_01_25/cloudmqttconnect.js new file mode 100755 index 0000000..d619784 --- /dev/null +++ b/RVO2/flow_22_01_25/cloudmqttconnect.js @@ -0,0 +1,374 @@ +exports.id = 'cloudmqttconnect'; +exports.title = 'Cloud connect mqtt'; +exports.group = 'MQTT'; +exports.color = '#888600'; +exports.version = '1.0.2'; +exports.icon = 'sign-out'; +exports.input = 2; +exports.output = 2; +exports.options = { host: 'tb-stage.worksys.io', port: 1883, clientid: "", username: "" }; + +exports.html = `
+
+
+
Hostname or IP address (if not empty - setting will override db setting)
+
+
+
Port
+
+
+
+
+
@(Client id)
+
+
+
topic
+
+
+
`; + + + +const { promisifyBuilder } = require('./helper/db_helper'); +const fs = require('fs'); +const mqtt = require('mqtt'); +const nosql = NOSQL('tbdatacloud'); + +const SEND_TO = { + debug: 0, + rpcCall: 1, +} + +//CONFIG +let saveTelemetryOnError = true;//backup_on_failure overrides this value +//------------------------ + +const noSqlFileSizeLimit = 4194304;//use 5MB - 4194304 +let insertNoSqlCounter = 0; +let insertBackupNoSqlCounter = 0; +let processingData = false; + +let backup_on_failure = true;//== saveTelemetryOnError - create backup client send failure +let restore_from_backup = 50; //how many rows process at once? +let restore_backup_wait = 3;//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; + + +exports.install = function(instance) { + + var client; + var opts; + var clientReady = false; + + let o = null; //options + + function main() + { + loadSettings(); + } + + //set opts according to db settings + function loadSettings() + { + + o = instance.options; + if(!o.topic) o.topic = FLOW.GLOBALS.settings.cloud_topic; + + opts = { + host: o.host, + port: o.port, + clientId: o.clientid, + username: o.username, + rejectUnauthorized: false, + resubscribe: false + }; + + console.log("wsmqttpublich -> loadSettings from instance.options",o); + + connectToTbServer(); + } + + function connectToTbServer() + { + var url = "mqtt://" + opts.host + ":" + opts.port; + console.log("MQTT URL: ", url); + + client = mqtt.connect(url, opts); + + client.on('connect', function() { + client.subscribe(`${o.topic}_backward`, (err) => { + if (!err) { + console.log("MQTT subscribed"); + } + }); + instance.status("Connected", "green"); + clientReady = true; + sendClientError = true; + }); + + client.on('reconnect', function() { + instance.status("Reconnecting", "yellow"); + clientReady = false; + }); + + client.on('message', function(topic, message) { + // message is type of buffer + message = message.toString(); + if (message[0] === '{') { + TRY(function() { + + message = JSON.parse(message); + if (message.hasOwnProperty("device") && message.hasOwnProperty("data") && message.data.hasOwnProperty("id")) { + client.publish(`${o.topic}_forward`, `{"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}}); + } + + }, () => instance.debug('MQTT: Error parsing data', message)); + } + + instance.send(SEND_TO.rpcCall, {"topic":o.topic, "content":message }); + }); + + client.on('close', function() { + clientReady = false; + + instance.status("Disconnected", "red"); + instance.send(SEND_TO.debug, {"message":"Client CLOSE signal received !"}); + }); + + client.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) { + console.log('MQTT client error', err); + sendClientError = false; + } + clientReady = false; + }); + + } + + + instance.on('0', function(data) { + + if(clientReady) + { + //do we have some data in backup file? if any, process data from database + if(saveTelemetryOnError) + { + //read telemetry data and send back to server + if(!processingData) processDataFromDatabase(); + } + + let stringifiedJson = JSON.stringify(data.data) + client.publish(`${o.topic}_forward`, stringifiedJson, {qos: 1}); + } + 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(saveTelemetryOnError) + { + //create new file from tbdata.nosql, if file size exceeds given limit, and clear tbdata.nosql + makeBackupFromDbFile(); + + //write to tb + data.data.id = UID(); + nosql.insert(data.data); + } + } + }); + + instance.on("1", _ => { + main(); + }) + + instance.close = function(done) { + if(clientReady){ + client.end(); + } + }; + + + function getDbBackupFileCounter(type) + { + var files = fs.readdirSync(__dirname + "/../databases"); + + let counter = 0; + for(var i = 0; i < files.length; i++) + { + + if(files[i] == "tbdatacloud.nosql") continue; + + if(files[i].endsWith(".nosql")) + { + + let pos = files[i].indexOf("."); + if(pos > -1) + { + + let fileCounter = counter; + let firstDigit = files[i].slice(0, pos); + + fileCounter = parseInt(firstDigit); + if(isNaN(fileCounter)) fileCounter = 0; + //console.log("getDbBackupFileCounter digit:", files[i], firstDigit, fileCounter, isNaN(fileCounter), type); + + if(type == "max") + { + if(fileCounter > counter) + { + counter = fileCounter; + } + } + else if(type == "min") + { + if(counter == 0) counter = fileCounter; + + if(fileCounter < counter) + { + counter = fileCounter; + } + } + } + } + + } + + if(type == "max") counter++; + + return counter; + } + + const makeBackupFromDbFile = async () => { + + if(!saveTelemetryOnError) return; + + //to avoid large file: tbdata.nosql + + //init value is 0! + if(insertNoSqlCounter > 0) + { + --insertNoSqlCounter; + return; + } + + insertNoSqlCounter = 100; + + let source = __dirname + "/../databases/tbdatacloud.nosql"; + + var stats = fs.statSync(source); + var fileSizeInBytes = stats.size; + + if(fileSizeInBytes > noSqlFileSizeLimit) + { + + let counter = 1; + counter = getDbBackupFileCounter("max"); + + let destination = __dirname + "/../databases/" + counter + "." + "tbdatacloud.nosql"; + + //make backup file + fs.copyFileSync(source, destination); + //fs.renameSync(p, p + "." + counter); + + //clear tbdata.nosql + fs.writeFileSync(source, ""); + fs.truncateSync(source, 0); + + } + } + + const processDataFromDatabase = async () => { + + if(restore_from_backup <= 0) return; + + //calculate diff + const now = new Date(); + let currentTime = now.getTime(); + let diff = currentTime - lastRestoreTime; + + if( (diff / 1000) < restore_backup_wait) + { + //console.log("*********restore_backup_wait", diff, restore_backup_wait); + return; + } + + processingData = true; + + //get filename to process + let counter = getDbBackupFileCounter("min"); + + //we have some backup files + let dataBase = 'tbdata'; + + var nosql; + if(counter == 0) dataBase = 'tbdatacloud'; + else dataBase = counter + "." + 'tbdatacloud'; + + nosql = NOSQL(dataBase); + + //select all data - use limit restore_from_backup + let records = await promisifyBuilder(nosql.find().take(restore_from_backup)); + + for(let i = 0; i < records.length; i++) + { + if(clientReady) { + + let item = records[i]; + let id = item.id; + + if(id !== undefined) + { + //console.log("------------processDataFromDatabase - remove", id, dataBase, i); + + try { + + let message = JSON.parse(JSON.stringify(item)); + delete message.id; + client.publish(`${o.topic}_forward`, JSON.stringify(message), {qos:1}); + + //remove from database + await promisifyBuilder(nosql.remove().where("id", id)); + + } catch(error) { + //process error + console.log("processDataFromDatabase", error); + } + + } + + } + else + { + processingData = false; + return; + } + } + + if(records.length > 0) + { + //clean backup file + if(counter > 0) nosql.clean(); + } + + //no data in db, remove + if(records.length == 0) + { + if(counter > 0) nosql.drop(); + } + + const d = new Date(); + lastRestoreTime = d.getTime(); + + processingData = false; + + } + + instance.on('options', main); + +}; diff --git a/RVO2/flow_22_01_25/cmd_manager.js b/RVO2/flow_22_01_25/cmd_manager.js new file mode 100755 index 0000000..a960aaa --- /dev/null +++ b/RVO2/flow_22_01_25/cmd_manager.js @@ -0,0 +1,2988 @@ +exports.id = 'cmd_manager'; +exports.title = 'CMD Manager'; +exports.group = 'Worksys'; +exports.color = '#5D9CEC'; +exports.version = '0.0.3'; +exports.output = ['red', 'blue', 'yellow', 'blue', 'white']; +exports.input = 3; +exports.icon = 'cloud-upload'; + +exports.html = ` +
+
+
+
RPC - run RPC calls

+
+
+
@(User)
+
+
+
@(Password)
+
+
+
@(My edge)
+
+
+
+`; +exports.readme = `Manager for CMD calls`; + + +exports.install = function(instance) { + + 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'); + + 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'); + + const dbNodes = TABLE("nodes"); + const dbRelays = TABLE("relays"); + + let GLOBALS; + let SETTINGS; + let rsPort; + let tbHandler; + + // runTasks intervals + const SHORT_INTERVAL = 30; + const LONG_INTERVAL = 300; + + //send data to following instances: + const SEND_TO = { + debug: 0, + tb: 1, + http_response: 2, + dido_controller: 3, + infoSender: 4 + } + + 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 + } + + 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 + + //if sending of profile to node fails, we send notification and push node into set, so we do not send notification twice + const nodeProfileSendFail = new Set(); + + //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(); + } + + + 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" + //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); + + 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); + + console.log("proces profile finished *********************") + } + + + 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; + }); + } + + + 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) { + for (let k in nodesData) { + 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`); + } + } + } + + + function loadRelaysData(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 (value.contactor == 1) processAllNodeProfilesOnLine(value.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 = {}; + + 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.byte1 = hours;//h + params.byte2 = minutes;//m + params.byte3 = seconds;//s + params.byte4 = 0; + params.recipient = 2;//2 broadcast, address = 0 + params.register = 87;//Actual time + params.rw = 1;//write + + //other values + params.type = "cmd"; + params.timestamp = Date.now() + 60000; + params.addMinutesToTimestamp = addMinutesToTimestamp; + params.info = "run broadcast: Actual time"; + + tasks.push(params); + + let sec = 3; + 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) { + 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); + + 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'; + //params.debug = true; + + tasks.push(params); + } + + //Prúd + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "cmd"; + params.tbname = tbname; + params.address = node; + params.register = 75;//prud + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read current'; + //params.debug = true; + + tasks.push(params); + } + + //výkon + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "cmd"; + params.tbname = tbname; + params.address = node; + params.register = 76;//výkon + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read power'; + //params.debug = true; + + tasks.push(params); + } + } + } + }, sec * 1000); + } + + + 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"; + + const date = Date.now(); + + // 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); + }) + + } + + + function turnLine(onOrOff, line, info) { + let obj = { + line: line, + command: onOrOff, + info: info + }; + + logger.debug("linia", line, obj); + instance.send(SEND_TO.dido_controller, obj); + } + + + + 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"; + 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]) { + //CRC_ERROR + message = "NOK"; + error = "CRC_ERROR c1"; + instance.send(SEND_TO.debug, "CRC_ERROR c1"); + } + + 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") { + instance.send(SEND_TO.debug, bytes); + instance.send(SEND_TO.debug, "RESPONSE " + type + " - " + bytes[4]); + + //logger.debug(SEND_TO.debug, "RESPONSE " + type + " - " + bytes[4], bytes); + + error = "type is: " + type; + + message = "NOK"; + } + + return { message, type, error }; + } + + + //BUILD TASKS// + function buildTasks(params) { + //report SETTINGS.edge_fw_version as fw_version + //report date as startdate + + //return; + console.log("buidTAaasks start ****************", params); + + monitor.info("buildTasks - params", params); + + let processLine; //defined line + let init = false; + let processLineProfiles = true; + let processBroadcast = true; + let processNodes = true; + + if (params == undefined) { + init = true; + tasks = []; + logger.debug("-->buildTasks clear tasks"); + } + else { + processLineProfiles = false; + processBroadcast = false; + processNodes = false; + + processLineProfiles = params.processLineProfiles; + processLine = params.line; + } + + //load profiles pre vsetky linie: + let now = new Date(); + + if (processLineProfiles) { + //process line profiles + let keys = Object.keys(relaysData); + 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; + } + + try { + + /** + * we process line profiles: timepoints, astro clock, lux_sensor, offsets ... + */ + if (profilestr === "") throw ("Profile is not defined"); + let profile = JSON.parse(profilestr); + 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; + + // add name to regular profile timepoint and delete unused end_time key: + time_points.forEach(point => { + point.name = "profileTimepoint" + delete point.end_time; + }); + + //monitor.info("buildTasks: time_points", time_points); + + + /** + * 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 astro clock true, we remove all regular profile points + time_points = []; + + 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 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); + + 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); + + 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(':'); + + let ad = new Date(); + ad.setHours(parseInt(ahours), parseInt(aminutes), 0); + + let bd = new Date(); + bd.setHours(parseInt(bhours), parseInt(bminutes), 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++) { + + let start_time = new Date(); + let [hours, minutes] = time_points[t].start_time.split(':'); + start_time.setHours(parseInt(hours), parseInt(minutes), 0); + + //task is in 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); + params.value = time_points[t].value; + params.tbname = relaysData[line].tbname; + params.timestamp = start_time.getTime(); + + 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; + + //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)) { + 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; + + params.debug = true; + + //turn on/off line + tasks.push(params); + monitor.info("TimePoint params: ", params.info, start_time); + } + + monitor.info("-->time_points final", line, time_points); + + //ensure to turn on/off according to calculated currentValue + let params = getParams(PRIORITY_TYPES.terminal); + params.type = "relay"; + params.line = parseInt(line); + params.tbname = relaysData[line].tbname; + params.value = currentValue; + + params.timestamp = PRIORITY_TYPES.terminal; + params.addMinutesToTimestamp = 0; + params.debug = true; + + //logger.debug(now.toLocaleString("sk-SK")); + 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; + + tasks.push(params); + + } catch (error) { + if (profilestr !== "") { + //errLogger.error(profilestr, error); + errorHandler.sendMessageToService(profilestr + "-" + error, 0, "js_error"); + } + } + + } + + //logger.debug("tasks:"); + //logger.debug(tasks); + } + + + //PROCESS DEFAULT BROADCASTS + //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.register = 6;//Time of dusk - Reg 6 + params.rw = 1;//write + + //other values + params.type = "cmd"; + params.timestamp = Date.now() + 60000; + params.addMinutesToTimestamp = addMinutesToTimestamp; + params.info = "Broadcast-duskTime"; + + tasks.push(params); + } + + { + + //run broadcast Time of dawn + 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 + params.byte3 = 0;//s + params.byte4 = 0; + params.recipient = 2; //2 broadcast + params.register = 7;//Time of dawn - Reg 6 + params.rw = 1;//write + + //other values + params.type = "cmd"; + params.timestamp = Date.now() + 60000; + params.addMinutesToTimestamp = addMinutesToTimestamp; + params.info = "Broadcast-dawnTime"; + + tasks.push(params); + } + + { + //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 + params.byte3 = seconds;//s + params.byte4 = 0; + params.recipient = 2; //2 broadcast + params.register = 87;//Actual time + params.rw = 1;//write + + //other values + params.type = "cmd"; + params.timestamp = Date.now() + 60000; + params.addMinutesToTimestamp = addMinutesToTimestamp; + params.info = "run broadcast: Actual time"; + + tasks.push(params); + } + + } + + //process nodes & tasks + //reportovanie pre platformu + 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++) { + register = listOfCommands[i]; + + let params = getParams(PRIORITY_TYPES.node_cmd); + + //core rpc values + params.address = address; + params.byte1 = 0; + params.byte2 = 0; + params.byte3 = 0; + params.byte4 = 0; + 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) { + timestampStart = timestampStart + addMinutesToTimestamp * 60000; + } + + //other values + params.type = "cmd"; + params.tbname = tbname; + params.timestamp = timestampStart; + params.addMinutesToTimestamp = addMinutesToTimestamp; + params.info = "generated cmd - buildTasks (node)"; + + tasks.push(params); + + } + } + } + + + //niektore ulohy sa vygeneruju iba 1x pri starte!!! + if (!init) return; + + + //Priebežne (raz za cca 5 minút) je potrebné vyčítať z Master nodu verziu jeho FW. + //Jedná sa o register 10. Rovnaká interpretácia ako pri FW verzii nodu. + //Adresa mastera je 0. V prípade že kedykoľvek nastane situácia že Master Node neodpovedá (napríklad pri vyčítaní telemetrie z nodu nevráti žiadne dáta), + //tak treba vyreportovať string "NOK". + { + let params = getParams(PRIORITY_TYPES.fw_detection); + params.type = "cmd-master"; + params.register = 4; + params.address = 0; + params.timestamp = Date.now() + 60000; + params.addMinutesToTimestamp = 5; + params.tbname = SETTINGS.rvoTbName; + params.info = "Master node FW verzia"; + //params.debug = true; + + //this will set SETTINGS.masterNodeIsResponding + + tasks.push(params); + } + + //kazdu hodinu skontrolovat nastavenie profilov + { + let params = getParams(PRIORITY_TYPES.fw_detection); + params.type = "process_profiles"; + params.timestamp = Date.now() + 60000; + params.addMinutesToTimestamp = 60;//60 = every hour + params.info = "detekcia nespracovaných profilov linie a nodov"; + //params.debug = true; + + tasks.push(params); + } + + monitor.info("tasks created:", tasks.length); + } + + + /** + * We process line profile, where "astro_clock": true + * example profile: + * + "dawn_lux_sensor": true, + "dusk_lux_sensor": true, + "dawn_lux_sensor_value": 5, + "dusk_lux_sensor_value": 5, + "dawn_astro_clock_offset": 0, + "dusk_astro_clock_offset": 10, + "dawn_lux_sensor_time_window": 30, + "dusk_lux_sensor_time_window": 30, + "dawn_astro_clock_time_window": 60, + "dusk_astro_clock_time_window": 60 + + * if dawn: if currentTimestamp is in timewindow "dawnTime + and - dawn_lux_sensor_time_window" and lux value >= lux_sensor_value, we switch off the line. + * if dusk: we do oposite + * + * dawn: usvit - lux je nad hranicou - vypnem + * dusk: sumrak - lux je pod hranicou - zapnem + */ + 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++) { + + let line = keys[i]; //line is turned off by default + let profilestr = relaysData[line].profile; + const contactor = relaysData[line].contactor; + + try { + + let profile = JSON.parse(profilestr); + if (Object.keys(profile).length === 0) throw ("turnOnOffLinesAccordingToLuxSensor - profile is not defined"); + + 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 (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"); + } + } + } + + //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 (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"); + } + } + } + + } + + } catch (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) { + //MASTER + if (node == 0) return; + + let nodeObj = nodesData[node]; + 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; + } + + } + + + 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 }; + } + }); + }); + } + + + async function runTasks() { + + clearInterval(interval); + + let currentTimestamp = Date.now(); + + //report dusk, dawn--------------------------------- + if (reportDuskDawn.dusk_time < currentTimestamp) { + //vyreportuj iba ak nie je velky rozdiel napr. 60 sekund + 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); + reportDuskDawn.dusk_time_reported = sunCalcResult.dusk_time; + } + } + + var nextDay = new Date(); + nextDay.setDate(nextDay.getDate() + 1); + + sunCalcResult = calculateDuskDawn(nextDay); + reportDuskDawn.dusk_time = sunCalcResult.dusk_time; + } + + if (reportDuskDawn.dawn_time < currentTimestamp) { + //vyreportuj iba ak nie je velky rozdiel napr. 60 sekund + 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); + reportDuskDawn.dawn_time_reported = sunCalcResult.dawn_time; + } + } + + var nextDay = new Date(); + nextDay.setDate(nextDay.getDate() + 1); + + sunCalcResult = calculateDuskDawn(nextDay); + reportDuskDawn.dawn_time = sunCalcResult.dawn_time; + + } + //-------------------------------------------------------- + + //sort tasks based on timestamp + 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) { + instance.send(SEND_TO.debug, "no tasks created"); + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + 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) { + //logger.debug("--->task to process", currentTask); + } + + if (currentTask.timestamp <= currentTimestamp) { + let params = { ...tasks[0] }; + + //allow terminal commands + if (SETTINGS.maintenance_mode && params.type !== "cmd-terminal") { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + let type = params.type; + let tbname = params.tbname; + let node = params.address; + + let line = null; + + //rpc related + if (nodesData[node] !== undefined) line = nodesData[node].line; + if (params.line !== undefined) line = params.line; + + let repeatTask = false; + if (params.addMinutesToTimestamp > 0 || params.timePointName) repeatTask = true; + + if (repeatTask) { + if (type === "cmd" || type === "cmd-master") { + //set next start time automatically + tasks[0].timestamp = currentTimestamp + tasks[0].addMinutesToTimestamp * 60000; + } + } + else { + tasks.shift(); + } + + //kontrola nespracovanych profilov nodov + if (type == "process_profiles") { + tasks[0].timestamp = currentTimestamp + tasks[0].addMinutesToTimestamp * 60000; + + //vsetky linie kt. su zapnute, a spracuju sa nespracovane profily nodov + loadRelaysData(); + + interval = setInterval(runTasks, SHORT_INTERVAL); + return; + } + + //relay + if (type == "relay") { + + const timePointName = params.timePointName; + const value = params.value; + + let date = new Date(); + date.setDate(date.getDate() + 1);//next day + + let sunCalcResult; + if (timePointName) sunCalcResult = calculateDuskDawn(date, params.line); + + if (timePointName == "dawn") { + tasks[0].timestamp = sunCalcResult.dawn_time; + } + else if (timePointName == "dusk") { + tasks[0].timestamp = sunCalcResult.dusk_time; + } + else if (timePointName == "luxOn") { + tasks[0].timestamp = sunCalcResult.dusk_time + params.dusk_lux_sensor_time_window * 60000; + } + else if (timePointName == "luxOff") { + tasks[0].timestamp = sunCalcResult.dawn_time + params.dawn_lux_sensor_time_window * 60000; + } + else if (timePointName == "profileTimepoint") { + tasks[0].timestamp = currentTimestamp + tasks[0].addMinutesToTimestamp * 60000; + } + + let info = "aplikovany bod profilu"; + let onOrOff = ""; + value == 1 ? onOrOff = "on" : onOrOff = "off"; + + turnLine(onOrOff, params.line, info); + + interval = setInterval(runTasks, SHORT_INTERVAL); + return; + } + + //zhodeny hlavny istic + let disconnected = false; + //if(rotary_switch_state == "Off") disconnected = true; + + //state_of_breaker[line] - alebo istic linie + 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" }; + + 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; + + if (!disconnectedReport[tbname]) { + sendTelemetry(values, tbname) + } + + interval = setInterval(runTasks, SHORT_INTERVAL); + + return; + } + + disconnectedReport[tbname] = false; + + const register = params.register; + + //high_priority + if (!SETTINGS.masterNodeIsResponding) { + //ak neodpoveda, nebudeme vykonavat ziadne commands, okrem cmd-terminal, a fw version + errorHandler.sendMessageToService("Master node is not responding"); + + let stop = true; + + //fw version - register == 4 + if (type == "cmd-terminal" || register == 4) stop = false; + if (stop) { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + } + + let contactorStatus = 1; + if (relaysData[line] != undefined) contactorStatus = relaysData[line].contactor; + + if (line == 0 || contactorStatus == 0) { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + // TODO: -> status offline for rvo if rotary_switch_state is OFF, this is source of errors + // + // let relayStatus = 1; + // if (relaysData[line] != undefined) { + // relayStatus = relaysData[line].contactor; + // } + + // if (line == 0) relayStatus = 0; + // if (type == "cmd-terminal") relayStatus = 1; + + // //check if rotary_switch_state == "Off" + // if (relayStatus == 0) { + // console.log("------------------------------------relayStatus", relayStatus, line); + // let values = { "status": "OFFLINE" }; + + // if(tbname) sendTelemetry(values, tbname) + + // interval = setInterval(runTasks, SHORT_INTERVAL); + // return; + // } + + if (!rsPort.isOpen) { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + //RE-CALCULATE VALUES + //set actual time for broadcast + if (register == 87 && params.recipient === 2) { + var d = new Date(); + params.byte1 = d.getHours();//h + params.byte2 = d.getMinutes();//m + params.byte3 = 0;//s + params.byte4 = 0; + } + + //SET DUSK/DAWN FOR BROADCAST + //Time of dusk + if (register == 6 && params.recipient === 2) { + + if (type != "cmd-terminal") { + let sunCalcResult = calculateDuskDawn(); + params.byte1 = sunCalcResult["dusk_hours"];//h + params.byte2 = sunCalcResult["dusk_minutes"];//m + params.byte3 = 0;//s + params.byte4 = 0; + + //TODO astrohodiny + let dusk = "Time of dusk: " + sunCalcResult["dusk"]; + } + } + + //Time of dawn + if (register == 7 && params.recipient === 2) { + if (type != "cmd-terminal") { + let sunCalcResult = calculateDuskDawn(); + params.byte1 = sunCalcResult["dawn_hours"];//h + params.byte2 = sunCalcResult["dawn_minutes"];//m + params.byte3 = 0;//s + params.byte4 = 0; + + //TODO astrohodiny + let dawn = "Time of dawn: " + sunCalcResult["dawn"]; + } + + } + //----------------------- + + instance.send(SEND_TO.debug, "address: " + node + " register:" + register + "type: " + 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(node, params.recipient, params.rw, register, params.name, params.byte1, params.byte2, params.byte3, params.byte4); + let readBytes = 11; + let timeout = 4000; + + // await keyword is important, otherwise incorrect data is returned! + 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); + + //ak sa odpoved zacina 0 - je to v poriadku, inak je NOK + let message = result.message; // OK, NOK + let message_type = result.type; + let error = result.error; + + if (params.debug != "generated cmd") { + //debug("writeData: done " + message_type + " duration: " + timeDiff + " message_type: " + params.debug, params); + } + + // 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); + // } + // } + + //debug("writeData: done " + message_type + " duration: " + timeDiff + " message_type: " + params.debug); + //debug("writeData done", message_type, "duration", timeDiff, "message_type", params.debug, result); + + let values = {}; + + //CMD FINISHED + if (message == "OK") { + + updateNodeStatus(node, true); + + //write + if (type == "set_node_profile") { + let result = cmdCounterResolve(node); + if (result == 0) { + dbNodes.modify({ processed: true }).where("node", node).make(function(builder) { + builder.callback(function(err, response) { + + sendNotification("CMD Manager: process cmd", SETTINGS.rvoTbName, "dimming_profile_was_successfully_received_by_node", { node: node }, "", SEND_TO.tb, instance); + + logger.debug("--> profil úspešne odoslaný na node č. " + node); + nodesData[node].processed = true; + nodeProfileSendFail.delete(node); + }); + }); + } + } + + //parse read response + if (params.rw == 0) { + values = processResponse(register, dataBytes); //read + } + + if (itIsNodeCommand) { + values.comm_status = "OK"; + values.status = "OK"; + } + + //master node + if (node == 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; + } + + //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.debug) { + //logger.debug("saveToTb", saveToTb, tbname, values); + } + + if (saveToTb) { + sendTelemetry(values, tbname) + } + else { + if (type == "cmd-terminal") { + terminalCommandResponse(params, "SUCCESS", data); + } + } + + } + else { + + terminalCommandResponse(params, "ERROR", data) + handleNokResponseOnRsPort("handleNOK else block", params, itIsNodeCommand, saveToTb); + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + //logger.debug("writeData err: ", error, result, params); + logger.debug("writeData err: ", tbname, node, register, values); + } + } + + //logger.debug(error, result, params); + } + }).catch(function(reason) { + + console.log("writeData catch exception", reason); + instance.send(SEND_TO.debug, reason); + + terminalCommandResponse(params, "FAILURE", null, reason); + handleNokResponseOnRsPort("handleNOK catch block", params, itIsNodeCommand, saveToTb); + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + logger.debug("-->WRITE FAILED: " + reason, params.debug, params); + } + } + + }); + + } + 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); + } + + + function handleNokResponseOnRsPort(message, params, itIsNodeCommand, saveToTb) { + + let node = params.address; + let register = params.register; + let type = params.type; + let tbName = params.tbname; + if (!tbName) return; + + let values = {}; + + // console.log(message); + let updateStatus = updateNodeStatus(node, false); + + //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; + + if (register == 4) values["master_node_version"] = "NOK"; + } + + if (type == "set_node_profile") { + delete cmdCounter[node]; + logger.debug("profil nebol úspešne odoslaný na node č. ", params); + + if (!nodeProfileSendFail.has(node)) { + sendNotification("CMD Manager: process cmd", tbName, "configuration_of_dimming_profile_to_node_failed", { node: node }, "", SEND_TO.tb, instance); + nodeProfileSendFail.add(node); + } + } + + if (itIsNodeCommand) { + values.comm_status = "NOK"; + } + + 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); + }); + }); + + 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); + + instance.send(SEND_TO.debug, err.message); + }); + + rsPort.on("close", () => { + setTimeout(() => rsPort.open(), 1000); + }); + + 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.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(); + return; + } + else if (flowdata.data == "close") { + rsPort.close(); + return; + } + else if (flowdata.data == "clean") { + tasks = []; + return; + } + else if (flowdata.data == "buildtasks") { + //build & run + return; + } + else if (flowdata.data == "run") { + //durations = []; + + if (tasks.length == 0) { + + buildTasks(); + + if (rsPort.isOpen) { + interval = setInterval(runTasks, 100); + } + else { + instance.send(SEND_TO.debug, "port is not opened!!!"); + } + } + } + else { + //terminal data - object + //logger.debug("flowdata", flowdata.data); + + if (typeof flowdata.data === 'object') { + //logger.debug("dido", flowdata.data); + if (flowdata.data.hasOwnProperty("sender")) { + //data from dido_controller + if (flowdata.data.sender == "dido_controller") { + + if (flowdata.data.hasOwnProperty("cmd")) { + let cmd = flowdata.data.cmd; + + if (cmd == "buildTasks") { + clearInterval(interval); + + logger.debug("-->CMD MANAGER - BUILD TASKS"); + buildTasks(); + + //logger.debug("tasks:"); + //logger.debug(tasks); + + logger.debug("-->CMD MANAGER - RUN TASKS"); + interval = setInterval(runTasks, LONG_INTERVAL); + } + else if (cmd == "reload_relays") { + loadRelaysData(flowdata.data.line); + + if (flowdata.data.dataChanged) { + if (!flowdata.data.value) { + reportOfflineNodeStatus(flowdata.data.line); + } + else { + reportOnlineNodeStatus(flowdata.data.line); + } + } + + } + else if (cmd == "rotary_switch_state") { + let value = flowdata.data.value; + + //state was changed + if (rotary_switch_state != value) { + if (value == "Off") { + //vyreportovat vsetky svietdla + reportOfflineNodeStatus(); + } + + rotary_switch_state = value; + } + } + 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) { + + // we send lux_sensor value to all nodes: + let params = getParams(PRIORITY_TYPES.node_broadcast); + + params.recipient = 2;//2 broadcast, address = 0 + params.address = 0xffffffff;//Broadcast + + let ba = longToByteArray(lux_sensor); + + params.byte3 = ba[1];//msb + params.byte4 = ba[0]; + params.timestamp = PRIORITY_TYPES.node_broadcast; + params.info = "run broadcast: Actual Lux level from cabinet"; + params.register = 95;//Actual Lux level from cabinet + params.rw = 1;//write + + tasks.push(params); + + //process profiles + turnOnOffLinesAccordingToLuxSensor(lux_sensor); + } + } + else if (cmd == "state_of_breaker") { + //istic linie + let value = flowdata.data.value; + let line = parseInt(flowdata.data.line); + + let dataChanged = false; + if (state_of_breaker[line] != value) dataChanged = true; + + state_of_breaker[line] = value; + + let status = "OK"; + if (value == "Off") status = "NOK"; + + if (dataChanged) { + + 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"); + + //report status liniu + sendTelemetry({ status: status }, tbname) + + //current value + if (value == "Off") reportOfflineNodeStatus(line); //vyreportovat vsetky svietidla na linii + } + + } + } + else { + logger.debug("undefined cmd", cmd); + } + } + } + + return; + } + + //data from worksys + 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 command = data.params.command; + let method = data.method; + let profile = data.params.payload; + if (profile == undefined) profile = ""; + let entity = data.params.entities[0]; + let entity_type = entity.entity_type; + let tbname = entity.tb_name; + + instance.send(SEND_TO.debug, flowdata.data); + 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") { + + //let command = data.params.command; + let value = data.params.payload.value; + + if (command == "dimming") { + + let nodeWasFound = false; + let keys = Object.keys(nodesData); + + //logger.debug("-----", keys); + + 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); + + 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; + + //ak linia je + + //debug(params); + logger.debug("dimming", params); + + tasks.push(params); + + 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); + + 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); + } + + //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; + + tasks.push(params); + } + + //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; + + tasks.push(params); + } + + //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; + + tasks.push(params); + } + + }, 4000); + + + nodeWasFound = true; + + break; + } + } + + if (!nodeWasFound) { + logger.debug("set dimming from platform", "unable to find tbname", tbname); + } + } + else { + instance.send(SEND_TO.debug, "undefined command " + command); + logger.debug("undefined command", command); + } + + return; + } + 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++) { + let node = keys[i]; + if (tbname == nodesData[node].tbname) { + + 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"); + + //profil úspešne prijatý pre node č. xx + 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; + + processNodeProfile(node); + }); + }); + } + } + } + else { + + instance.send(SEND_TO.debug, "unknown method " + method); + logger.debug("unknown method", method); + + return; + } + } + + //nastav profil linie z platformy + 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") { + + 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++) { + let line = keys[i]; + if (tbname == relaysData[line].tbname) { + //zmazeme tasky + 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) { + + //update profile + 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); + + }); + }); + break; + } + } + } + else if (method == "set_command") { + let value = data.params.payload.value; + + 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; + + 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"); + } + } + else { + instance.send(SEND_TO.debug, "undefined method " + method); + logger.debug("undefined method", method); + } + + return; + } + else { + instance.send(SEND_TO.debug, "UNKNOW entity_type " + entity_type); + logger.debug("UNKNOW entity_type", entity_type); + } + return; + } + + //terminal + if (!rsPort.isOpen) await rsPort.open(); + + let params = flowdata.data.body; + if (params == undefined) { + //logger.debug("CMD manager flowdata.data.body is undefined"); + return; + } + + params.priority = PRIORITY_TYPES.terminal; + params.type = "cmd-terminal"; + params.tbname = ""; + params.timestamp = PRIORITY_TYPES.terminal; + params.addMinutesToTimestamp = 0;// do not repeat task!!! + params.debug = true; + + let timestamp = Date.now(); + params.refFlowdataKey = timestamp; + //params.refFlowdata = flowdata; + //refFlowdata = flowdata; + + //console.log("flowdata", flowdata); + + cleanUpRefFlowdataObj(); + + refFlowdataObj[timestamp] = flowdata; + + //fix + //params.address = params.adress; + logger.debug("received from terminal", params); + logger.debug("date/time:", new Date()); + logger.debug("tasks length:", tasks.length); + + //tasks = []; + + //add to tasks + tasks.push(params); + + } + } + }) + + + //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) + } + + + /** + * 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; + + RESTBuilder.make(function(builder) { + + if (!builder) return; + + builder.method('GET'); + builder.url('http://192.168.252.2:8004/gettime?projects_id=1'); + + builder.callback(function(err, response, output) { + + 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); + } + + }); + } + + } 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); + + } else { + //console.log("Read-only", stdout); + + 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]: [ + { + "ts": date, + "values": values + } + ] + } + + 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); + } + + //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); + } + } + + 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; + } + + //Dimming, CCT + if (register == 1) { + let brightness = 0; + let dimming = byte0; + if (dimming > 128) { + //dimming = -128; + brightness = dimming - 128; + } + + //cct + //Ak Byte3 == 1: CCT = (Byte2*256)+Byte1 + let cct; + if (byte3 == 1) cct = byte2 * 256 + byte1; + else cct = bytesToInt(bytes.slice(0, 3)); + + //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; + } + + 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, 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 + ")"; + } + + 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; + + } + + function getObjectByTbValue(object, tbname) { + return object[Object.keys(object).find(key => object[key].tbname === tbname)]; + } + + function isObject(item) { + return (typeof item === "object" && !Array.isArray(item) && item !== null); + } + +} // end of instance.export + diff --git a/RVO2/flow_22_01_25/code.js b/RVO2/flow_22_01_25/code.js new file mode 100755 index 0000000..63b31bf --- /dev/null +++ b/RVO2/flow_22_01_25/code.js @@ -0,0 +1,90 @@ +exports.id = 'code'; +exports.title = 'Code'; +exports.group = 'Common'; +exports.color = '#656D78'; +exports.input = true; +exports.output = 1; +exports.author = 'Peter Širka'; +exports.icon = 'code'; +exports.version = '1.2.0'; +exports.options = { outputs: 1, code: 'send(0, value);', keepmessage: true }; + +exports.html = `
+
+
+
@(Number of outputs)
+
@(Minimum is 1)
+
+
+
@(Code)
+
@(Keep message instance)
+
+`; + +exports.readme = `# Code + +This component executes custom JavaScript code as it is and it doesn't contain any secure scope. + +\`\`\`javascript +// value {Object} contains received data +// send(outputIndex, newValue) sends a new value +// error(value) sends an error +// instance {Object} a current component instance +// flowdata {Object} a current flowdata +// repository {Object} a current repository of flowdata +// Example: + +// send() can be execute multiple times +send(0, value); +\`\`\``; + +exports.install = function(instance) { + + var fn; + + instance.on('data', function(response) { + if (fn) { + try { + fn(response.data, instance, response, instance.options, response.repository, require); + } catch (e) { + response.data = e; + instance.throw(response); + } + } + }); + + instance.reconfigure = function() { + try { + if (instance.options.code) { + instance.status(''); + var code = 'var send = function(index, value) { if (options.keepmessage) { flowdata.data = value; instance.send2(index, flowdata); } else instance.send2(index, value);}; var error = function(err) { instance.throw(err); }; ' + instance.options.code; + fn = new Function('value', 'instance', 'flowdata', 'options', 'repository', 'require', code); + } else { + instance.status('Not configured', 'red'); + fn = null; + } + } catch (e) { + fn = null; + instance.error('Code: ' + e.message); + } + }; + + instance.on('options', instance.reconfigure); + instance.reconfigure(); +}; \ No newline at end of file diff --git a/RVO2/flow_22_01_25/comment.js b/RVO2/flow_22_01_25/comment.js new file mode 100755 index 0000000..1e0cd13 --- /dev/null +++ b/RVO2/flow_22_01_25/comment.js @@ -0,0 +1,11 @@ +exports.id = 'comment'; +exports.title = 'Comment'; +exports.group = 'Common'; +exports.color = '#704cff'; +exports.author = 'Martin Smola'; +exports.icon = 'comment'; +exports.traffic = false; +exports.version = '1.0.0'; +exports.readme = '# Comment'; + +exports.install = function() {}; diff --git a/RVO2/flow_22_01_25/csv_import.js b/RVO2/flow_22_01_25/csv_import.js new file mode 100755 index 0000000..5ae1e68 --- /dev/null +++ b/RVO2/flow_22_01_25/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/RVO2/flow_22_01_25/db_connector.js b/RVO2/flow_22_01_25/db_connector.js new file mode 100755 index 0000000..65ee94b --- /dev/null +++ b/RVO2/flow_22_01_25/db_connector.js @@ -0,0 +1,286 @@ +exports.id = 'db_connector'; +exports.title = 'DbConnector'; +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.html = `
+
+
+
DbConnector
+
+
+
`; + +exports.readme = `# read/write data to tables`; + +const instanceSendTo = { + debug: 0, + http_response: 1, +} + +const { promisifyBuilder, makeMapFromDbResult } = require('./helper/db_helper.js'); + +function extractWhereParams(params) +{ + let name = params[0]; + let operator = '='; + let value = params[1]; + + if(params.length == 3) + { + operator = params[1]; + value = params[2]; + } + + return {name: name, operator: operator, value: value}; +} + +exports.install = function(instance) { + + let refFlowdata = null;//holds reference to httprequest flowdata + + instance.on("close", () => { + + }) + + + instance.on("data", async function(flowdata) { + + let params = flowdata.data.body; + console.log("DbConnector", params); + + refFlowdata = flowdata; + + if(refFlowdata != undefined) + { + //make http response + let responseObj = {}; + responseObj["type"] = "SUCESS"; + + try{ + + let table = params.table; + let action = params.action; + + + if(params.data != undefined) + { + let className = params.data.className; + + if(className == "SqlQueryBuilder") + { + let type = params.data.type; + + console.log("SqlQueryBuilder---->", params.data); + + if(type == "SELECT") + { + let table = params.data.queryData.tables[0].table; + + const db = TABLE(table); + var builder = db.find(); + + let result = await promisifyBuilder(builder); + + let response = {}; + response["result"] = result; + response["success"] = true; + + responseObj["data"] = response; + + //console.log(responseObj); + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + } + + return; + } + } + + + console.log("db_connector---->", table, action); + + //actions: read, replace, insert, delete, update... + + if(action == "read") + { + const db = TABLE(params.table); + + //where builder.where('age', '<', 15); + //builder.where('id', 3403); + + var builder = db.find(); + + //https://docs.totaljs.com/latest/en.html#api~DatabaseBuilder~builder.where + if(params.hasOwnProperty("where")) + { + //optionalCan contain "=", "<=", "<", ">=", ">". + //Default value: '=' + + //1.["production_line", 1] + //2. ["or", ["production_line", 1], ["production_line", 2], "end"] + + if (Array.isArray(params.where)) { + + let multipleConditions = false; + + if(params.where[0] == "or") multipleConditions = true; + if (Array.isArray(params.where[0])) multipleConditions = true; + + if(multipleConditions) + { + + for(var i = 0; i < params.where.length; i++) + { + const item = params.where[i]; + + if(item === "or") builder.or(); + + if (Array.isArray(item)) + { + const { name, operator, value } = extractWhereParams(item); + builder.where(name, operator, value); + } + + if(item === "end") builder.end(); + + } + + } + else + { + const { name, operator, value } = extractWhereParams(params.where); + builder.where(name, operator, value); + } + + } + + /* + if(params.where.length >=2 ) + { + let name = params.where[0]; + let operator = '='; + let value = params.where[1]; + + if(params.where.length == 3) + { + operator = params.where[1]; + value = params.where[2]; + } + + builder.where(name, operator, value); + } + */ + } + + if(params.hasOwnProperty("between")) + { + builder.between(params.between[0], params.between[1], params.between[2]); + } + + let response = await promisifyBuilder(builder); + responseObj["data"] = response; + + //console.log(responseObj); + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + + return; + } + + if(action == "delete") + { + + } + + + if(action == "update") + { + //! data receiving from terminal (params) + // { + // hostname: 'localhost', + // table: 'settings', + // action: 'update', + // body: { + // rvo_name: 'terrrr', + // lang: 'en', + // temperature_adress: '28.427B45920702', + // latitude: 48.70826502, + // longitude: 17.28455203, + // mqtt_host: '192.168.252.4', + // mqtt_clientid: 'showroom_test_panel_led', + // mqtt_username: 'xmRd6RJxW53WZe4vMFLU', + // mqtt_port: 1883, + // maintanace_mode: false + // } + // } + const tableToModify = TABLE(params.table); + const newValues = params.body; + + tableToModify.modify(newValues).make(function(builder) { + + builder.callback(function(err, response) { + + if(!err) + { + responseObj["data"] = response; + responseObj["tableUpdated"] = true; + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + } + }); + }); + + } + + if(action == "replace") + { + //truncate table + const db = TABLE(params.table); + var builder = db.remove(); + db.clean(); + + //insert data + let data = params.data; + + for(let i = 0; i < data.length; i++) + { + //console.log(data[i]); + db.insert(data[i]); + } + + console.log("insert done"); + + let responseObj = {}; + responseObj["type"] = "SUCESS"; + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + + + } + + + + } catch (error) { + //console.log(error); + responseObj["type"] = "ERROR"; + responseObj["message"] = error; + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + } + } + }) +} + + diff --git a/RVO2/flow_22_01_25/db_init.js b/RVO2/flow_22_01_25/db_init.js new file mode 100755 index 0000000..ddd0aa0 --- /dev/null +++ b/RVO2/flow_22_01_25/db_init.js @@ -0,0 +1,106 @@ +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 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 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.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 : "2025-01-09", //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"], + phases: responseSettings[0]["phases"], + cloud_topic: responseSettings[0]["cloud_topic"], + + //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/RVO2/flow_22_01_25/debug.js b/RVO2/flow_22_01_25/debug.js new file mode 100755 index 0000000..00cb259 --- /dev/null +++ b/RVO2/flow_22_01_25/debug.js @@ -0,0 +1,100 @@ +exports.id = 'debug'; +exports.title = 'Debug'; +exports.author = 'Peter Širka'; +exports.color = '#967ADC'; +exports.click = true; +exports.input = true; +exports.icon = 'bug'; +exports.version = '2.0.4'; +exports.options = { enabled: true, repository: false, type: 'data' }; +exports.readme = `# Debug + +Prints data to the debug tab.`; + +exports.html = `
+
+
+
@(Output type)
+
@(Path to the property (leave empty to show the whole data object))
+
@(A group name)
+
@(Enabled)
+
+
+
`; + +exports.install = function(instance) { + + instance.on('data', function(response) { + if (instance.options.enabled) { + + var opt = instance.options; + var rep = response.repository; + var val = response.data; + var id = response.id; + + switch (instance.options.type){ + case 'both': + var data = {}; + data.repository = rep; + data.data = val instanceof Error ? { error: val.message, stack: val.stack } : val; + instance.debug(safeparse(opt.property ? U.get(data, opt.property) : data), undefined, opt.group, id); + break; + case 'repository': + instance.debug(safeparse(opt.property ? U.get(rep, opt.property) : rep), undefined, opt.group, id); + break; + case 'data': + default: + if (val instanceof Error) + instance.debug({ error: val.message, stack: val.stack }, undefined, opt.group, id); + else + instance.debug(safeparse(opt.property ? U.get(val, opt.property) : val), undefined, opt.group, id); + break; + } + } + }); + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + instance.save(); + }); + + instance.on('options', function() { + instance.custom.status(); + }); + + instance.custom.status = function() { + instance.status(instance.options.enabled ? 'Enabled' : 'Disabled'); + }; + + instance.custom.status(); + + function safeparse(o) { + + if (o instanceof Buffer) + return o; + + if (o === undefined) + return 'undefined'; + + if (o === null) + return 'null'; + + var cache = []; + var str = JSON.stringify(o, function(key, value) { + if (typeof value === 'object' && value !== null) { + if (cache.indexOf(value) !== -1) { + try { + return JSON.parse(JSON.stringify(value)); + } catch (error) { + return; + } + } + cache.push(value); + } + return value; + }); + cache = null; + return JSON.parse(str); + } +}; diff --git a/RVO2/flow_22_01_25/designer.json b/RVO2/flow_22_01_25/designer.json new file mode 100755 index 0000000..f88b174 --- /dev/null +++ b/RVO2/flow_22_01_25/designer.json @@ -0,0 +1,2846 @@ +{ + "tabs": [ + { + "name": "MAIN PUSH", + "linker": "main-push", + "id": "1612772287426", + "index": 0 + }, + { + "name": "CMD manager", + "linker": "cmd-manager", + "id": "1615551125555", + "index": 1 + }, + { + "name": "Devices", + "linker": "devices", + "id": "1611921777196", + "index": 2 + } + ], + "components": [ + { + "id": "1611951142547", + "component": "debug", + "tab": "1611921777196", + "name": "ERROR", + "x": 598, + "y": 60, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#DA4453", + "notes": "" + }, + { + "id": "1612776786008", + "component": "wsmqttpublish", + "tab": "1612772287426", + "name": "WS MQTT publish", + "x": 304.75, + "y": 237, + "connections": { + "0": [ + { + "index": "0", + "id": "1615551060773" + } + ], + "1": [ + { + "index": "0", + "id": "1618300858252" + }, + { + "index": "0", + "id": "1618558465485" + } + ], + "2": [ + { + "index": "0", + "id": "1618300863816" + }, + { + "index": "0", + "id": "1634303685503" + } + ], + "3": [ + { + "index": "0", + "id": "1731068754606" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Connected", + "color": "green" + }, + "options": { + "username": "", + "clientid": "", + "port": "1883", + "host": "" + }, + "color": "#888600", + "notes": "" + }, + { + "id": "1612778461252", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "tb-push", + "x": 86.75, + "y": 375, + "connections": { + "0": [ + { + "index": "0", + "id": "1612783322136" + }, + { + "index": "1", + "id": "1612776786008" + }, + { + "index": "0", + "id": "1731068754606" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1612783322136", + "component": "debug", + "tab": "1612772287426", + "name": "to TB", + "x": 306.75, + "y": 371, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615551060773", + "component": "debug", + "tab": "1612772287426", + "name": "errors from MQTT Broker", + "x": 650, + "y": 76, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#DA4453", + "notes": "" + }, + { + "id": "1615563373927", + "component": "debug", + "tab": "1615551125555", + "name": "Debug", + "x": 753, + "y": 150, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#DA4453", + "notes": "" + }, + { + "id": "1615566865233", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "tb-push", + "x": 761, + "y": 251, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1615798582262", + "component": "debug", + "tab": "1615551125555", + "name": "CMD_debug", + "x": 765, + "y": 350, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615802995322", + "component": "debug", + "tab": "1611921777196", + "name": "Debug", + "x": 595.8833312988281, + "y": 557.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Disabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": false + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615809128443", + "component": "debug", + "tab": "1611921777196", + "name": "tempToTb", + "x": 598.8833312988281, + "y": 654.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615809595184", + "component": "virtualwireout", + "tab": "1611921777196", + "name": "tb-push", + "x": 594.8833312988281, + "y": 350.25, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1616165795916", + "component": "httproute", + "tab": "1615551125555", + "name": "POST /terminal", + "x": 114, + "y": 546, + "connections": { + "0": [ + { + "index": "0", + "id": "1684060205000" + }, + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Listening", + "color": "green" + }, + "options": { + "timeout": 10, + "cachepolicy": 0, + "cacheexpire": "5 minutes", + "size": 5, + "url": "/terminal", + "method": "POST", + "name": "", + "flags": [ + "id:1616165795916", + "post", + 10000 + ], + "emptyresponse": false + }, + "color": "#5D9CEC", + "notes": "### Configuration\n\n- __POST /terminal__\n- flags: \n- maximum request data length: __5 kB__\n- empty response: __false__\n- cache policy: __no cache__\n- cache expire: __5 minutes__", + "cloning": false + }, + { + "id": "1616165824813", + "component": "httpresponse", + "tab": "1615551125555", + "name": "HTTP Response", + "x": 772, + "y": 443, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "json" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1617104731852", + "component": "debug", + "tab": "1615551125555", + "name": "DIDO_Debug", + "x": 669, + "y": 1040, + "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": "turnOff line", + "x": 88, + "y": 1158, + "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": 669, + "y": 1150, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1617284749681", + "component": "trigger", + "tab": "1615551125555", + "name": "update profile / node", + "x": 112, + "y": 215, + "connections": { + "0": [ + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "string", + "data": "profile_nodes" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1618235171399", + "component": "trigger", + "tab": "1615551125555", + "name": "tun tasks", + "x": 119, + "y": 280, + "connections": { + "0": [ + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "data": "run" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1618300858252", + "component": "debug", + "tab": "1612772287426", + "name": "wsmqtt-exit1", + "x": 650.8833312988281, + "y": 160, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1618300863816", + "component": "debug", + "tab": "1612772287426", + "name": "wsmqtt-exit2", + "x": 845.8833312988281, + "y": 320, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1618393583970", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "to-cmd-manager", + "x": 668.8833312988281, + "y": 1269, + "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": 119.88333129882812, + "y": 369, + "connections": { + "0": [ + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "platform-rpc-call", + "color": "gray" + }, + "options": { + "wirename": "platform-rpc-call" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1618393759854", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "cmd_to_dido", + "x": 93.88333129882812, + "y": 1007, + "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": 779.8833312988281, + "y": 552, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "cmd_to_dido", + "color": "gray" + }, + "options": { + "wirename": "cmd_to_dido" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1618558465485", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "platform-rpc-call", + "x": 649.8833312988281, + "y": 246, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "platform-rpc-call", + "color": "gray" + }, + "options": { + "wirename": "platform-rpc-call" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1618572059773", + "component": "trigger", + "tab": "1615551125555", + "name": "turnOn line", + "x": 89, + "y": 1085, + "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": 452.1091003417969, + "y": 341.05455017089844, + "connections": { + "0": [ + { + "index": "0", + "id": "1615563373927" + } + ], + "1": [ + { + "index": "0", + "id": "1615566865233" + }, + { + "index": "0", + "id": "1615798582262" + } + ], + "2": [ + { + "index": "0", + "id": "1616165824813" + } + ], + "3": [ + { + "index": "0", + "id": "1618393827655" + } + ], + "4": [ + { + "index": "0", + "id": "1635936391935" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1619605019281", + "component": "httproute", + "tab": "1615551125555", + "name": "GET db", + "x": 115, + "y": 651, + "connections": { + "0": [ + { + "index": "0", + "id": "1684060205000" + }, + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Listening", + "color": "green" + }, + "options": { + "timeout": 5, + "cachepolicy": 0, + "cacheexpire": "5 minutes", + "size": 5, + "url": "/db", + "method": "GET", + "name": "", + "flags": [ + "id:1619605019281", + "get", + 5000 + ] + }, + "color": "#5D9CEC", + "notes": "### Configuration\n\n- __GET /db__\n- flags: undefined\n- maximum request data length: __5 kB__\n- empty response: __undefined__\n- cache policy: __no cache__\n- cache expire: __5 minutes__", + "cloning": false + }, + { + "id": "1619784672383", + "component": "trigger", + "tab": "1615551125555", + "name": "turnOnAlarm", + "x": 85, + "y": 1231, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "data": "{command: \"turnOnAlarm\"}", + "datatype": "object" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1619784812964", + "component": "trigger", + "tab": "1615551125555", + "name": "turnOffAlarm", + "x": 84, + "y": 1304, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "data": "{command: \"turnOffAlarm\"}", + "datatype": "object" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1621340721628", + "component": "virtualwireout", + "tab": "1611921777196", + "name": "modbus_to_dido", + "x": 596, + "y": 462, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "modbus_to_dido", + "color": "gray" + }, + "options": { + "wirename": "modbus_to_dido" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1622640022885", + "component": "httproute", + "tab": "1615551125555", + "name": "POST /db_connector", + "x": 98, + "y": 1586, + "connections": { + "0": [ + { + "index": "0", + "id": "1622640073521" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Listening", + "color": "green" + }, + "options": { + "timeout": 5, + "cachepolicy": 0, + "cacheexpire": "5 minutes", + "size": 5, + "url": "/db_connector", + "method": "POST", + "flags": [ + "id:1622640022885", + "post", + 5000 + ] + }, + "color": "#5D9CEC", + "notes": "### Configuration\n\n- __POST /db_connector__\n- flags: \n- maximum request data length: __5 kB__\n- empty response: __undefined__\n- cache policy: __no cache__\n- cache expire: __5 minutes__", + "cloning": false + }, + { + "id": "1622640073521", + "component": "db_connector", + "tab": "1615551125555", + "name": "DbConnector", + "x": 372, + "y": 1572, + "connections": { + "1": [ + { + "index": "0", + "id": "1622641420685" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "edge": "undefined" + }, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1622641420685", + "component": "httpresponse", + "tab": "1615551125555", + "name": "HTTP Response", + "x": 596, + "y": 1586, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1634303504177", + "component": "monitormemory", + "tab": "1612772287426", + "name": "RAM", + "x": 69.88333129882812, + "y": 885.5, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465281992" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "840.70 MB / 985.68 MB", + "color": "gray" + }, + "options": { + "enabled": true, + "interval": 30000 + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1634303533779", + "component": "monitordisk", + "tab": "1612772287426", + "name": "disk", + "x": 70.88333129882812, + "y": 982.5, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465821120" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "5.77 GB / 7.26 GB", + "color": "gray" + }, + "options": { + "enabled": true, + "path": "/", + "interval": 30000 + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1634303595494", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "send-to-services", + "x": 51.883331298828125, + "y": 1400.5, + "connections": { + "0": [ + { + "index": "0", + "id": "1634463186563" + }, + { + "index": "1", + "id": "1634488120710" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1634303602169", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "send-to-services", + "x": 426.8833312988281, + "y": 878.5, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1634303685503", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "send-to-services", + "x": 650.8833312988281, + "y": 355.5, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1634303743260", + "component": "httprequest", + "tab": "1612772287426", + "name": "192.168.252.2:8004/sentmessage", + "reference": "", + "x": 480.8833312988281, + "y": 1334.7333374023438, + "connections": { + "0": [ + { + "index": "0", + "id": "1635327431236" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "stringify": "json", + "method": "POST", + "url": "http://192.168.252.2:8004/sentmessage" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1634463186563", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 280.75, + "y": 1446, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634464580289", + "component": "code", + "tab": "1612772287426", + "name": "Code", + "x": 253, + "y": 788, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465243324" + }, + { + "index": "0", + "id": "1634303602169" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "keepmessage": true, + "code": "let response = {};\nresponse.cpu = value.cpu;\nresponse.uptime = value.uptime;\n\nsend(0, response);", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1634465243324", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 428, + "y": 784, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634465281992", + "component": "code", + "tab": "1612772287426", + "name": "Code", + "x": 242, + "y": 884, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465338103" + }, + { + "index": "0", + "id": "1634303602169" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "keepmessage": true, + "code": "value.sender = \"ram\";\n//let total = value.total/1024/1024;\n//let free = value.free/1024/1024;\n//let used = value.used/1024/1024;\nlet response = {};\n//value.memory_total = (total).toFixed(0) + ' MB';\n//value.memory_free = (free).toFixed(0) + ' MB';\n//value.memory_used = (used).toFixed(0) + ' MB';\n\nresponse.memory_total = value.total;\nresponse.memory_free = value.free;\nresponse.memory_used = value.used;\n\nsend(0, response);", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1634465338103", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 429, + "y": 976, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634465821120", + "component": "code", + "tab": "1612772287426", + "name": "Code", + "x": 245, + "y": 978, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465892500" + }, + { + "index": "0", + "id": "1634303602169" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "keepmessage": true, + "code": "value.sender = \"hdd\";\n//let total = value.total/1024/1024;\n//let free = value.free/1024/1024;\n//let used = value.used/1024/1024;\nlet response = {};\n//value.hdd_total = (total).toFixed(0) + ' MB';\n//value.hdd_free = (free).toFixed(0) + ' MB';\n//value.used = (used).toFixed(0) + ' MB';\n\nresponse.hdd_total = value.total;\nresponse.hdd_free = value.free;\nresponse.hdd_used = value.used;\n\nsend(0, response);", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1634465892500", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 432, + "y": 1068, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634484067516", + "component": "debug", + "tab": "1612772287426", + "name": "Send info", + "x": 480, + "y": 1441, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634488120710", + "component": "infosender", + "tab": "1612772287426", + "name": "Info sender", + "x": 285, + "y": 1338, + "connections": { + "0": [ + { + "index": "0", + "id": "1634484067516" + }, + { + "index": "0", + "id": "1634303743260" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "edge": "undefined" + }, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1635327431236", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 795.8833312988281, + "y": 1329.5, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1635936391935", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "send-to-services", + "x": 778, + "y": 656, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1637069803394", + "component": "monitorconsumption", + "tab": "1612772287426", + "name": "CPU", + "x": 69, + "y": 791, + "connections": { + "0": [ + { + "index": "0", + "id": "1634464580289" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "0.5% / 101.13 MB", + "color": "gray" + }, + "options": { + "monitorfiles": true, + "monitorconnections": true, + "monitorsize": true, + "monitorconsumption": true, + "enabled": true, + "interval": 30000 + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1683664161036", + "component": "debug", + "tab": "1615551125555", + "name": "CMDtoDIDO", + "x": 392, + "y": 1012, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1683981346282", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "from-dido-controller", + "x": 113, + "y": 456, + "connections": { + "0": [ + { + "index": "0", + "id": "1684055037116" + }, + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "from-dido-controller", + "color": "gray" + }, + "options": { + "wirename": "from-dido-controller" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1684055037116", + "component": "debug", + "tab": "1615551125555", + "name": "from dido to cmd", + "x": 448, + "y": 519, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1684060205000", + "component": "debug", + "tab": "1615551125555", + "name": "HTTP routes", + "x": 447, + "y": 620, + "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": "MDBToDido", + "x": 598, + "y": 147, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1699963668903", + "component": "dido_controller", + "tab": "1615551125555", + "name": "DIDO_Controller", + "x": 397, + "y": 1131, + "connections": { + "0": [ + { + "index": "0", + "id": "1617104731852" + } + ], + "1": [ + { + "index": "0", + "id": "1617104731852" + }, + { + "index": "0", + "id": "1617115013095" + } + ], + "2": [ + { + "index": "0", + "id": "1618393583970" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "edge": "undefined" + }, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1699964678894", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "modbus_to_dido", + "x": 96, + "y": 924, + "connections": { + "0": [ + { + "index": "0", + "id": "1699963668903" + }, + { + "index": "0", + "id": "1699964793925" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "modbus_to_dido", + "color": "gray" + }, + "options": { + "wirename": "modbus_to_dido" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1699964793925", + "component": "debug", + "tab": "1615551125555", + "name": "modbusToDido", + "x": 388, + "y": 920, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1699965957410", + "component": "modbus_reader", + "tab": "1611921777196", + "name": "Modbus reader", + "x": 232, + "y": 175, + "connections": { + "0": [ + { + "index": "0", + "id": "1611951142547" + } + ], + "1": [ + { + "index": "0", + "id": "1621340721628" + }, + { + "index": "0", + "id": "1684179110403" + }, + { + "index": "0", + "id": "1717441414646" + } + ], + "2": [ + { + "index": "0", + "id": "1615809595184" + }, + { + "index": "0", + "id": "1714752862828" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1700411878636", + "component": "thermometer", + "tab": "1611921777196", + "name": "Thermometer", + "x": 234.75, + "y": 444, + "connections": { + "0": [ + { + "index": "0", + "id": "1615802995322" + } + ], + "1": [ + { + "index": "0", + "id": "1615809595184" + }, + { + "index": "0", + "id": "1615809128443" + } + ], + "2": [ + { + "index": "0", + "id": "1621340721628" + }, + { + "index": "0", + "id": "1732889185927" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#5CB36D", + "notes": "" + }, + { + "id": "1714752862828", + "component": "debug", + "tab": "1611921777196", + "name": "MDBToTb", + "x": 599, + "y": 257, + "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": 755.0833282470703, + "y": 209, + "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": 966.0833282470703, + "y": 152, + "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": 968.0833282470703, + "y": 268, + "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": 77.75, + "y": 1630, + "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": 296, + "y": 1671, + "connections": { + "0": [ + { + "index": "0", + "id": "1718016086212" + }, + { + "index": "0", + "id": "1718016073501" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Running", + "color": "gray" + }, + "options": { + "name": "rvo_senica_2_10.0.0.130", + "types": "[\"emergency\", \"critical\", \"error\", \"alert\"]", + "message_includes": "[\"is responding again\", \"Flow has been restarted\", \"Node db has changed\"]", + "tag_on_include": "[{\"user_id\":\"U072JE5JUQG\", \"includes\":[\"Electrometer\", \"Twilight sensor\"]}]", + "slack_channel": "C071KN2Q8SK" + }, + "color": "#30E193", + "notes": "" + }, + { + "id": "1718016073501", + "component": "httprequest", + "tab": "1612772287426", + "name": "http://192.168.252.2:8004/slack", + "x": 495, + "y": 1753, + "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": 832, + "y": 1664, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "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": 79, + "y": 1723, + "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": "" + }, + { + "id": "1729855334955", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "platform-rpc-call", + "x": 649.9333343505859, + "y": 541.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "platform-rpc-call", + "color": "gray" + }, + "options": { + "wirename": "platform-rpc-call" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1729855371093", + "component": "debug", + "tab": "1612772287426", + "name": "rpc cloud", + "x": 650.9333343505859, + "y": 451.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1731068658334", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 90.75, + "y": 250, + "connections": { + "0": [ + { + "index": "0", + "id": "1612776786008" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731068754606", + "component": "cloudmqttconnect", + "tab": "1612772287426", + "name": "MQTT client - to senica-prod01", + "x": 304.75, + "y": 474, + "connections": { + "1": [ + { + "index": "0", + "id": "1729855371093" + }, + { + "index": "0", + "id": "1729855334955" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Connected", + "color": "green" + }, + "options": { + "username": "", + "clientid": "", + "port": "2764", + "host": "192.168.252.2", + "topic": "u130" + }, + "color": "#888600", + "notes": "" + }, + { + "id": "1731069001548", + "component": "db_init", + "tab": "1612772287426", + "name": "DB Initialization", + "x": 91.75, + "y": 55.25, + "connections": { + "0": [ + { + "index": "0", + "id": "1731069033416" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#888600", + "notes": "" + }, + { + "id": "1731069033416", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "db-init", + "x": 343.75, + "y": 50.25, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069059135", + "component": "showdb", + "tab": "1612772287426", + "name": "Show db data", + "x": 1121.75, + "y": 814.25, + "connections": { + "0": [ + { + "index": "0", + "id": "1731069079243" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#888600", + "notes": "" + }, + { + "id": "1731069079243", + "component": "debug", + "tab": "1612772287426", + "name": "dbData", + "x": 1315.75, + "y": 853.25, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1731069116691", + "component": "trigger", + "tab": "1612772287426", + "name": "settings", + "x": 911.75, + "y": 710.75, + "connections": { + "0": [ + { + "index": "0", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069131637", + "component": "trigger", + "tab": "1612772287426", + "name": "relaysData", + "x": 832.75, + "y": 775.75, + "connections": { + "0": [ + { + "index": "1", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069137374", + "component": "trigger", + "tab": "1612772287426", + "name": "nodesData", + "x": 747.75, + "y": 840.75, + "connections": { + "0": [ + { + "index": "2", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069179846", + "component": "trigger", + "tab": "1612772287426", + "name": "pinsData", + "x": 803.75, + "y": 899.75, + "connections": { + "0": [ + { + "index": "3", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069192937", + "component": "trigger", + "tab": "1612772287426", + "name": "sample data", + "x": 858.75, + "y": 959.75, + "connections": { + "0": [ + { + "index": "4", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069264443", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 63.75, + "y": 1279, + "connections": { + "0": [ + { + "index": "0", + "id": "1634488120710" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069334626", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "db-init", + "x": 151.88333129882812, + "y": 148, + "connections": { + "0": [ + { + "index": "0", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069548145", + "component": "virtualwirein", + "tab": "1611921777196", + "name": "db-init", + "x": 46.75, + "y": 192, + "connections": { + "0": [ + { + "index": "0", + "id": "1699965957410" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069567152", + "component": "virtualwirein", + "tab": "1611921777196", + "name": "db-init", + "x": 44.75, + "y": 465, + "connections": { + "0": [ + { + "index": "0", + "id": "1700411878636" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731070156936", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "db-init", + "x": 89.88333129882812, + "y": 1381, + "connections": { + "0": [ + { + "index": "2", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731234189516", + "component": "trigger", + "tab": "1612772287426", + "name": "monitor.txt", + "x": 915.75, + "y": 1017.75, + "connections": { + "0": [ + { + "index": "5", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731234189551", + "component": "trigger", + "tab": "1612772287426", + "name": "err.txt", + "x": 966.75, + "y": 1080.75, + "connections": { + "0": [ + { + "index": "6", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1732700042559", + "component": "nodesdb_change_check", + "tab": "1612772287426", + "name": "Nodes DB change check", + "x": 263.8833312988281, + "y": 1993.2333984375, + "connections": { + "0": [ + { + "index": "0", + "id": "1732700071298" + }, + { + "index": "0", + "id": "1732700642917" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#888600", + "notes": "" + }, + { + "id": "1732700057052", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 84.75, + "y": 1994, + "connections": { + "0": [ + { + "index": "0", + "id": "1732700042559" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1732700071298", + "component": "debug", + "tab": "1612772287426", + "name": "nodesChange", + "x": 561.8833312988281, + "y": 2055.2333984375, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1732700642917", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "tb-push", + "x": 557.8833312988281, + "y": 1949, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1732889185927", + "component": "debug", + "tab": "1611921777196", + "name": "tempToDido", + "x": 594.8833312988281, + "y": 745, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1733574412965", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 86.75, + "y": 495, + "connections": { + "0": [ + { + "index": "1", + "id": "1731068754606" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + } + ], + "version": 615 +} \ No newline at end of file diff --git a/RVO2/flow_22_01_25/dido_controller.js b/RVO2/flow_22_01_25/dido_controller.js new file mode 100755 index 0000000..8415921 --- /dev/null +++ b/RVO2/flow_22_01_25/dido_controller.js @@ -0,0 +1,1524 @@ +exports.id = 'dido_controller'; +exports.title = 'DIDO_Controller'; +exports.version = '2.0.0'; +exports.group = 'Worksys'; +exports.color = '#2134B0'; +exports.input = 3; +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 { 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 +} + + +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 = {}; + 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"); + + //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 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 + }; + + + function main() { + + GLOBALS = FLOW.GLOBALS; + SETTINGS = FLOW.GLOBALS.settings; + rvoTbName = SETTINGS.rvoTbName; + pinsData = GLOBALS.pinsData; + relaysData = GLOBALS.relaysData; + + 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"; + + 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, "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; + turnLine("off", 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; + + sendTelemetry(values, rvoTbName); + + 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) { + if (!err) { + monitor.info(exports.title + "--->Digital in_out has been set (runSyncExec was sucessfull)"); + + turnAlarm("off"); + 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() { + + //to keep websocket opened, we send request every 150 seconds + let startRequests = null; + + console.log("handleWebSocket function called"); + ws = new WebSocket('ws:/0.0.0.0:1234/ws'); + + ws.onopen = function open() { + + instance.send(0, exports.title + " running"); + turnAlarm("off"); + + // useTurnOffCounter = true; + // turnOffCounter = relaysData.length - 1; + initialSetting(); + ws.send(JSON.stringify({ "cmd": "all" })); + + // we request dev info about neuron device from evok to keep websocket connection alive + // for some reason this request returns no data, but connection keeps alive + // https://evok.api-docs.io/1.0/mpqzDwPwirsoq7i5A/websocket + startRequests = setInterval(() => { + // console.log(" *** data from evok requested"); + ws.send(JSON.stringify({ "cmd": "filter", "dev": ["neuron"] })); + }, 150000) + }; + + + // 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 = async 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; + + 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) => { + monitor.info('websocket error, reconnect') + instance.send(SEND_TO.debug, err.message); + clearInterval(startRequests); + ws = null; + setTimeout(handleWebSocket, 1000); + }) + + + ws.onclose = function() { + // connection closed, discard old websocket and create a new one in 5s + // stopRequests(); + monitor.info('websocket onclose, reconnect') + clearInterval(startRequests); + ws = null; + console.log("ws is null now, reconnecting..."); + setTimeout(handleWebSocket, 1000); + } + } + + 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 turnAlarm(onOrOff) { + let value = 0; + if (onOrOff == "on") value = 1; + + if (value == 1 && SETTINGS.maintenance_mode) return; + + alarmStatus = "OFF"; + if (value == 1) alarmStatus = "ON"; + + if (rsPort) { + let arr = [0x55]; + arr.push(13); + arr.push(0); + arr.push(value); + + rsPort.write(Buffer.from(arr), function(err) { + logger.debug(`sirena - ${onOrOff}`); + }); + } + else if (ws) { + let cmd = { "cmd": "set", "dev": "relay", "circuit": "1_01", "value": value }; + ws.send(JSON.stringify(cmd)); + logger.debug(`sirena - ${onOrOff}`); + } + } + + + 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") { + bits.push(0); + } + else bits.push(1); + + if (deviceStatus["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); + } + + + // turn line on or off + function turnLine(onOrOff, line, pin, force, info) { + //onOrOff => "on" or "off" + let value = 0; + if (onOrOff == "on") value = 1; + + if (force == undefined) force = false; + + if (line == 0) { + if (value == 1 && alarmStatus == "ON") turnAlarm("off"); + SETTINGS.maintenance_mode = value ? true : false; + + 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); + return; + } + + if (pin === undefined) pin = getPin(line); + + if (pin === undefined) { + errLogger.error("pin is undefined!", line); + return; + } + + if (!force) { + if (relaysData[line].contactor == value) { + instance.send(SEND_TO.debug, `line is already ${onOrOff} ` + line); + logger.debug(`turnLine: line is already ${onOrOff} `, 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(value); + + rsPort.write(Buffer.from(arr), function(err) { + if (err === undefined) { + monitor.info(`turnLine ${onOrOff} zapisal do rsPort-u`, line, pin, arr, info); + switchLogic(arr); + } + else { + monitor.info(`turnLine ${onOrOff} 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 }; + ws.send(JSON.stringify(cmd)); + switchLogic(pin, value) + } + + //if rvo is 24/7, it has just one switching profile point at 13:00. we do not want to send notification as it repeats every day. + //const d = new Date(); + //if(d.getHours() != 13) sendNotification("Dido_controller: ", SETTINGS.rvoTbName, "switching_profile_point_applied_to_line", { line: line, value: onOrOff }, "", SEND_TO.tb, instance); + } + + + // 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; + + // 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) { + const status = flowdata.data.status; + if (status == "NOK-twilight_sensor") { + deviceStatus["twilight_sensor"] = "NOK"; + } + else if (status == "NOK-em340" || status == "NOK-em111") { + deviceStatus["em"] = "NOK"; + } + else if (status == "NOK-thermometer") { + deviceStatus["temperature"] = "NOK"; + } + } + else if ("values" in flowdata.data) { + 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" + } + else if (values.hasOwnProperty("temperature")) { + deviceStatus["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"; + } + + sendTelemetry(values, rvoTbName); + } + + sendRvoStatus(); + }) + + + // we expect array as flowdata.data + instance.on("1", flowdata => { + + console.log(flowdata.data); + + if (!flowdata.data instanceof Object) return; + + let obj = flowdata.data; + let line = obj.line; + 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"); + + //! ake data prichadzaju z cmd_manager.js ??? + //TODO transform to websocket + if (Array.isArray(obj)) { + + rsPort.write(Buffer.from(obj), function(err) { + switchLogic(obj); + + instance.send(SEND_TO.debug, { "WRITE": obj }); + }); + } + }) + + + function calculateStateCode() { + + 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") { + bits.push(0); + } + else { + bits.push(1); + } + + //Prevádzkový mód - Manual, Off, Automatic, maintenance_mode = true/false // DAVA 2 BITY + if (!SETTINGS.maintenance_mode) { + if (deviceStatus["rotary_switch_state"] == "Manual") { + bits.push(0); + bits.push(1); + } + + if (deviceStatus["rotary_switch_state"] == "Automatic") { + bits.push(0); + bits.push(0); + } + + if (deviceStatus["rotary_switch_state"] == "Off") { + bits.push(1); + bits.push(0); + } + } + else { + bits.push(1); + bits.push(1); + } + + //Dverový kontakt + if (deviceStatus["door_condition"] == "closed") { + bits.push(0); + } + else { + bits.push(1); + } + + //EM + if (deviceStatus["em"] == "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //Teplomer + if (deviceStatus["temperature"] == "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //Batéria + if (deviceStatus["battery"] == "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //Zdroj + if (deviceStatus["power_supply"] == "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //MN + if (deviceStatus["master_node"] == "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //výpadok napätia na fáze + if (deviceStatus["no_voltage"] == "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + if (deviceStatus["twilight_sensor"] == "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + // doplnime do 16 bitov (2 byty) + for (let i = bits.length; i < 16; i++) { + bits.push(0); + } + + // console.log("calculateStateCode - deviceStatus", deviceStatus); + // 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; + } + + + async function sendRvoStatus() { + + if (SETTINGS === undefined) return; + SETTINGS.masterNodeIsResponding ? deviceStatus["master_node"] = "OK" : deviceStatus["master_node"] = "NOK"; + + 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() { + + // 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 + //set RVO state + let status = "OK"; + + for (const [key, value] of Object.entries(deviceStatus)) { + if (["em", "twilight_sensor", "temperature", "master_node"].includes(key) && value == "NOK") status = "NOK"; + } + + if (status == "OK") { + let pinIndexes = [1, 4, 6]; + if (controller_type == 'unipi') pinIndexes = ['input1_01', 'input1_04', 'input1_05']; + + for (const pinIndex of pinIndexes) { + if (previousValues[pinIndex] === 0) { + if ((pinIndex === 6 || pinIndex === 'input1_01' || pinIndex === 'input1_05') && SETTINGS.maintenance_mode) continue; + status = "NOK"; + break; + } + } + } + + // battery status. If value is 1 - battery is NOK + if (previousValues[5] === 1) status = "NOK"; + if (SETTINGS.no_voltage.size > 0) status = "NOK"; + + // console.log("rvo status",status) + return status; + } + + + // we pass array to function in case of rsPort ==> switchLogic([55,3,0,1]) ==> [[55,3,0,1]] + // we pass two values in case of websocket ==> switchLogic("relay1_03",1) ==> ["relay1_03",1] + const switchLogic = (...args) => { + + let values = {}; + let pinIndex, newPinValue, twilight; + + //data from rsPort + if (args.length == 1) { + pinIndex = args[0][1] + 1; + if (pinIndex === 17) pinIndex--; + newPinValue = args[0][3]; + twilight = args[0][2]; + } + //data from websocket + else { + pinIndex = args[0]; + newPinValue = args[1]; + } + + 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; + + //default value + let value = "On"; + if (newPinValue === 0) value = "Off"; + + //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"; + + // 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"); + + // deviceStatus["state_of_main_switch"] = "On"; + // } + // } + + //Prevádzkový mód + 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"; + + deviceStatus["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, "power_supply_has_disconnected_input", {}, "", SEND_TO.tb, instance, "power_supply"); + + deviceStatus["power_supply"] = "NOK"; + } + else if (newPinValue === 1 && newPinValue !== previousValues[pinIndex]) { + sendNotification("switchLogic", rvoTbName, "power_supply_works_correctly", {}, "", SEND_TO.tb, instance, "power_supply"); + + deviceStatus["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"); + + deviceStatus["battery"] = "NOK"; + } + else if (newPinValue === 0 && newPinValue !== previousValues[pinIndex]) { + sendNotification("switchLogic", rvoTbName, "battery_level_is_ok", {}, "", SEND_TO.tb, instance, "battery_level"); + + deviceStatus["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' + else if (type == "door_condition" || type === "state_of_main_switch") { + newPinValue === 0 ? value = "open" : value = "closed"; + + 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, "door_opened_without_permission", {}, "", SEND_TO.tb, instance, "rvo_door"); + + // 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 (value === "closed") { + if (alarmStatus == "ON") turnAlarm("off"); + sendNotification("switchLogic", rvoTbName, "door_closed", {}, "", SEND_TO.tb, instance, "rvo_door"); + } + + deviceStatus[type] = value; + } + + //lux sensor + else if (type == "twilight_sensor") { + //! TODO - to show nok status, if lux value is not changing more then 10 times. + //Daylight is far more than 1000. So most of the day, when it is sunshine comes just value 1000. But lux sensor is not NOK. + //This is not the case in LM. If value from LM is the same 10x, there is 99% possibility, that sensor is NOK. + value = newPinValue; + + if (controller_type === 'lm') { + value = parseFloat(newPinValue + (256 * twilight)); + + 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 && !twilightError) { + twilightError = true; + let value = twilight_sensor_array.shift(); + + newPinValue = 0; + } + else if (set.size !== 1 && twilightError) { + //sendNotification("switchLogic", rvoTbName, 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) { + 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); + } + } + + 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); + } + + deviceStatus["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) + // { + // let time = 0; + // if(value) time = 1000 * 10;//10 sekund + + // let dataChanged = false; + // if(relaysData[line].contactor != newPinValue) dataChanged = true; + // relaysData[line].contactor = newPinValue; // 0,1 + + // //ak bola predchadzajuci stav off a novy stav je on, budu sa nastavovat nespracovane node profiles + // //a budu sa odosielat commandy, tie vsak mozu zlyhat, a preto potrebujeme ich spusti trochu neskor + // setTimeout(function(){ + // instance.send(SEND_TO.cmd_manager, {sender: "dido_controller", cmd: "reload_relays", line: line, time: time, value: value, dataChanged: dataChanged}); + // }, time); + + // reportLineStatus(line); + // } + // else + // { + // errLogger.error("modify table relays failed", err); + // } + + // }); + // }); + } + + 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 }); + + //mame iba 3 istice. vyreportujeme a ohandlujeme liniu na tom istom istici ako paralelna linia (napr linia 1, paralelna s nou je linia 4, key je string "4") + // ak je 7 linii, na 1 istici je linia 1,4,7 + + if (line == 1) { + + const lineOnSameBraker = [4, 7]; + + for (var i = 0; i < lineOnSameBraker.length; i++) { + if (!relaysData.hasOwnProperty(lineOnSameBraker[i])) continue; + + 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; + reportLineStatus(lineOnSameBraker[i]); + + values[type] = value; + const tbname = relaysData[lineOnSameBraker[i]].tbname; + sendTelemetry(values, tbname); + + delete values[type]; + } + + } + else { + const lineOnSameBraker = line + 3 + ""; + + if (relaysData.hasOwnProperty(lineOnSameBraker)) { + 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; + reportLineStatus(line + 3); + + values[type] = value; + const tbname = relaysData[lineOnSameBraker].tbname; + sendTelemetry(values, tbname); + + delete values[type]; + } + } + + } + + if (value == "Off") values["status"] = "NOK"; + deviceStatus["state_of_breaker"][line] = value; + + reportLineStatus(line); + } + else return; + + values[type] = value; + + if (type == "rotary_switch_state") { + if (SETTINGS.maintenance_mode) value = "maintenance"; + value = value.toLowerCase(); + values["power_mode"] = value; + } + + if (newPinValue != previousValues[pinIndex]) previousValues[pinIndex] = newPinValue; + if (Object.keys(values).length > 0 && tbname) sendTelemetry(values, tbname); + } + + + function sendTelemetry(values, tbname, date = Date.now()) { + let dataToTb = { + [tbname]: [ + { + "ts": date, + "values": values + } + ] + }; + + tbHandler.sendToTb(dataToTb, instance); + } + + + function isObject(item) { + return (typeof item === "object" && !Array.isArray(item) && item !== null); + } + +} //end of 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 +// *|input1_01|state_of_main_switch|0|........... +// *|input1_02|rotary_switch_state|0|........... +// *|input1_03|rotary_switch_state|0|........... +// *|intut1_04|power_supply|0|........... +// *|input1_05|door_condition|0|........... +// *|input1_06|state_of_breaker|1|........... +// *|input1_07|state_of_breaker|2|........... +// *|input1_08|state_of_breaker|3|........... +// *|relay1_02|state_of_contactor|1|........... +// *|relay1_03|state_of_contactor|2|........... +// *|relay1_04|state_of_contactor|3|........... +// *|287D8776E0013CE9|temperature|0|........... + + +//! pins_data --> from UNIPI +// { +// 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 } +// } + +//! relays_data +// { +// '0': { +// line: 0, +// tbname: 'KjbN4q7JPZmexgdnz2yKQ98YAWwO0Q3BMX6ERLoV', +// contactor: 1, +// profile: '' +// }, +// '1': { +// line: 1, +// tbname: 'RMgnK93rkoAazbqdQ4yBG95Z1YXGx6pmwBeVEP2O', +// contactor: 0, +// profile: '{"intervals":[{"value":0,"end_time":"20:00","start_time":"13:00"},{"value":1,"end_time":"10:00","start_time":"20:00"},{"value":0,"end_time":"10:20","start_time":"10:00"},{"value":1,"end_time":"10:40","start_time":"10:20"},{"value":0,"end_time":"11:00","start_time":"10:40"},{"value":1,"end_time":"11:30","start_time":"11:00"},{"value":0,"end_time":"11:50","start_time":"11:30"},{"value":1,"end_time":"13:00","start_time":"11:50"}],"astro_clock":false,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' +// }, +// '2': { +// line: 2, +// tbname: 'dlE1VQjYrNx9gZRmb38gG08oLBO4qaAk2M6JPnG7', +// contactor: 0, +// profile: '{"intervals":[{"value":0,"end_time":"20:00","start_time":"13:00"},{"value":1,"end_time":"10:00","start_time":"20:00"},{"value":0,"end_time":"10:20","start_time":"10:00"},{"value":1,"end_time":"10:40","start_time":"10:20"},{"value":0,"end_time":"11:00","start_time":"10:40"},{"value":1,"end_time":"11:30","start_time":"11:00"},{"value":0,"end_time":"11:50","start_time":"11:30"},{"value":1,"end_time":"13:00","start_time":"11:50"}],"astro_clock":false,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' +// }, +// '3': { +// line: 3, +// tbname: 'vnmG4kJxaXWNBgMQq0D7Aj5e9oZzOAlr6LdR3w2V', +// contactor: 0, +// profile: '{"intervals":[{"value":0,"end_time":"20:30","start_time":"13:00"},{"value":1,"end_time":"00:10","start_time":"20:30"},{"value":0,"end_time":"13:00","start_time":"05:40"},{"value":1,"end_time":"05:40","start_time":"00:10"}],"astro_clock":true,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' +// } +// } + + + + + +// { +// "jbN4q7JPZmexgdnz2yKbWGDYAWwO0Q3BMX6ERLoV": [ +// { +// "ts": 1700409326353, +// "values": { +// "_event": { +// "type": "notice", +// "status": "new", +// "source": { +// "func": "rsPort.open()", +// "component": "1700343402190", +// "component_name": "DIDO_Controller", +// "edge": "jbN4q7JPZmexgdnz2yKbWGDYAWwO0Q3BMX6ERLoV" +// }, +// "message": "al_shariff_10.0.0.38: FLOW has been started ", +// "message_data": "" +// } +// } +// } +// ] +// } diff --git a/RVO2/flow_22_01_25/helper/DataToTbHandler.js b/RVO2/flow_22_01_25/helper/DataToTbHandler.js new file mode 100755 index 0000000..a89b75b --- /dev/null +++ b/RVO2/flow_22_01_25/helper/DataToTbHandler.js @@ -0,0 +1,133 @@ +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; + + this.sender = ""; + } + + dump() { + console.log("----------------------------"); + console.log("previousValues", this.previousValues); + console.log("----------------------------"); + } + + setSender(sender) { + this.sender = sender; + } + + isEmptyObject(obj) { + for (var name in obj) { + return false; + } + return true; + } + + sendToTb(dataToTb, instance) { + + let keys = Object.keys(dataToTb); + + if(keys.length == 0) + { + if(this.debug) console.log("sendToTb received empty object", dataToTb); + return; + } + + let tbname = keys[0]; + let ts; + + let arrayOfValues = dataToTb[tbname]; + let arrayOfValuesToSend = []; + + for(let i = 0; i < arrayOfValues.length; i++) + { + ts = arrayOfValues[i].ts; + let values = this.prepareValuesForTb(tbname, ts, arrayOfValues[i].values); + + if(!this.isEmptyObject(values)) + { + arrayOfValuesToSend.push({ts: ts, values: values}); + } + } + + if(arrayOfValuesToSend.length == 0) + { + //if(this.debug) console.log("data not sent - empty array"); + return; + } + + this.messageCounter++; + + let dataToTbModified = { + [tbname]: arrayOfValuesToSend + } + + //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); + instance.send(this.index, dataToTbModified); + } + + getDiffTimestamp(key) { + //TODO set different value for given key!!! + //if(key == "status") this.timeToHoldTbValue = 2*60*60;//2h + return this.timeToHoldTbValue * 1000; + } + + prepareValuesForTb(tbname, timestamp, values) { + + let keys = Object.keys(values); + if(!this.previousValues.hasOwnProperty(tbname)) + { + this.previousValues[tbname] = {}; + } + + //if(this.debug) console.log("prepareValuesForTb", tbname, timestamp, values); + + for(let i = 0; i < keys.length; i++) + { + let key = keys[i]; + let value = values[key]; + + if(!this.previousValues[tbname].hasOwnProperty(key)) + { + this.previousValues[tbname][key] = {ts: timestamp, value: value}; + continue; + } + + if(this.previousValues[tbname][key].value === value) + { + let diff = timestamp - this.previousValues[tbname][key].ts; + + let timestampDiffToRemoveKey = this.getDiffTimestamp(key); + if(diff > timestampDiffToRemoveKey) + { + this.previousValues[tbname][key].ts = Date.now(); + //if(this.debug) console.log(this.sender + ": update ts for key", key, "diff is", diff, "messageCounter", this.messageCounter); + + } + else + { + delete values[key]; + //if(this.debug) console.log(this.sender + ": delete key", key, "diff is", diff, "messageCounter", this.messageCounter, timestampDiffToRemoveKey); + } + } + else + { + this.previousValues[tbname][key].value = value; + this.previousValues[tbname][key].ts = timestamp; + } + + } + + return values; + } +} + +module.exports = DataToTbHandler; diff --git a/RVO2/flow_22_01_25/helper/ErrorToServiceHandler.js b/RVO2/flow_22_01_25/helper/ErrorToServiceHandler.js new file mode 100755 index 0000000..110ea8b --- /dev/null +++ b/RVO2/flow_22_01_25/helper/ErrorToServiceHandler.js @@ -0,0 +1,126 @@ +const { MD5 } = require('./md5.js'); +const { networkInterfaces } = require('os'); + +class ErrorToServiceHandler +{ + constructor() { + this.previousValues = {}; + + this.projects_id = undefined; + + const nets = networkInterfaces(); + this.ipAddresses = Object.create(null); // Or just '{}', an empty object + + for (const name of Object.keys(nets)) { + for (const net of nets[name]) { + // Skip over non-IPv4 and internal (i.e. 127.0.0.1) addresses + if (net.family === 'IPv4' && !net.internal) { + if (!this.ipAddresses[name]) { + this.ipAddresses[name] = []; + } + this.ipAddresses[name].push(net.address); + } + } + } + + //console.log(this.ipAddresses); + + } + + setProjectsId(projects_id) + { + this.projects_id = projects_id; + } + + processMessage(message, seconds, message_type) + { + if(message_type == undefined) message_type = "error_message"; + if(Array.isArray(message)) message = message.join(', '); + + let key = MD5(message); + let timestamp = new Date().getTime(); + + //keep in memory - default value is 1h + if (seconds === undefined) seconds = 60*60; + + if(!this.previousValues.hasOwnProperty(key)) + { + this.previousValues[key] = {ts: timestamp, duration: seconds}; + } + + let diff = (timestamp - this.previousValues[key].ts); + if(diff < this.previousValues[key].duration*1000) return false; + + this.previousValues[key].ts = timestamp; + + return true; + } + + sendMessageToService(message, seconds, message_type) + { + + let f = this.processMessage(message, seconds, message_type); + if(!f) return; + + /* + //------------- + if(message_type == undefined) message_type = "error_message"; + if(Array.isArray(message)) message = message.join(', '); + + let key = MD5(message); + let timestamp = new Date().getTime(); + + //keep in memory + if (seconds === undefined) seconds = 60*60; + + if(!this.previousValues.hasOwnProperty(key)) + { + this.previousValues[key] = {ts: timestamp, duration: seconds}; + } + + let diff = (timestamp - this.previousValues[key].ts); + if(diff < this.previousValues[key].duration*1000) return; + + this.previousValues[key].ts = timestamp; + */ + + //------------------------- + + //send to service + + let dataToInfoSender = {id: this.projects_id}; + + //js_error || error_message + dataToInfoSender[message_type] = message; + dataToInfoSender.ipAddresses = this.ipAddresses; + + 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) + { + console.log("this.projects_id is undefined"); + return; + } + */ + + RESTBuilder.make(function(builder) { + builder.method('POST'); + builder.post(dataToInfoSender); + builder.url('http://192.168.252.2:8004/sentmessage'); + + builder.callback(function(err, response, output) { + console.log("process.on error send", err, response, output, dataToInfoSender); + }); + }); + + + } +} + +module.exports = ErrorToServiceHandler; \ No newline at end of file diff --git a/RVO2/flow_22_01_25/helper/db_helper.js b/RVO2/flow_22_01_25/helper/db_helper.js new file mode 100755 index 0000000..40e796c --- /dev/null +++ b/RVO2/flow_22_01_25/helper/db_helper.js @@ -0,0 +1,44 @@ +function promisifyBuilder(builder) +{ + return new Promise((resolve, reject) => { + + try{ + + builder.callback(function(err, response) { + + if(err != null) reject(err); + resolve(response); + }); + + } catch (error) { + reject(error); + } + }) +} + +function makeMapFromDbResult(response, ...keys) +{ + let s = "-"; + let data = {}; + + for(let i = 0; i < response.length; i++) + { + let record = response[i]; + + let k = []; + for(let j = 0; j < keys.length; j++) + { + k.push( record[keys[j]] ); + } + + let key = k.join(s); + data[ key ] = record; + } + + return data; +} + +module.exports = { + promisifyBuilder, + makeMapFromDbResult + } \ No newline at end of file diff --git a/RVO2/flow_22_01_25/helper/logger.js b/RVO2/flow_22_01_25/helper/logger.js new file mode 100755 index 0000000..2585639 --- /dev/null +++ b/RVO2/flow_22_01_25/helper/logger.js @@ -0,0 +1,30 @@ +//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/RVO2/flow_22_01_25/helper/md5.js b/RVO2/flow_22_01_25/helper/md5.js new file mode 100755 index 0000000..d3b0480 --- /dev/null +++ b/RVO2/flow_22_01_25/helper/md5.js @@ -0,0 +1,5 @@ +function MD5(d){var r = M(V(Y(X(d),8*d.length)));return r.toLowerCase()};function M(d){for(var _,m="0123456789ABCDEF",f="",r=0;r>>4&15)+m.charAt(15&_);return f}function X(d){for(var _=Array(d.length>>2),m=0;m<_.length;m++)_[m]=0;for(m=0;m<8*d.length;m+=8)_[m>>5]|=(255&d.charCodeAt(m/8))<>5]>>>m%32&255);return _}function Y(d,_){d[_>>5]|=128<<_%32,d[14+(_+64>>>9<<4)]=_;for(var m=1732584193,f=-271733879,r=-1732584194,i=271733878,n=0;n>16)+(_>>16)+(m>>16)<<16|65535&m}function bit_rol(d,_){return d<<_|d>>>32-_} + +module.exports = { + MD5 +} \ No newline at end of file diff --git a/RVO2/flow_22_01_25/helper/notification_reporter.js b/RVO2/flow_22_01_25/helper/notification_reporter.js new file mode 100755 index 0000000..61c0aef --- /dev/null +++ b/RVO2/flow_22_01_25/helper/notification_reporter.js @@ -0,0 +1,131 @@ +//key is device, value = str +let sentValues= {}; +let notificationsData = null; + +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 +}; + +function getKey(map, val) { + return Object.keys(map).findItem(key => map[key] === val); +} + +//https://stackoverflow.com/questions/41117799/string-interpolation-on-variable +var template = (tpl, args) => tpl.replace(/\${(\w+)}/g, (_, v) => args[v]); + + +function initNotification() { + notificationsData = FLOW.GLOBALS.notificationsData; +} + +function sendNotification(func, device, key, params, extra, tb_output, instance, saveKey) { + + // return; + + let storeToSendValues = true; + if(saveKey == undefined) storeToSendValues = false; + + let lang = FLOW.GLOBALS.settings.language; + if(lang != "en" || lang != "sk") lang = "en"; + + let tpl = key; + let weight = ""; + + if(notificationsData[key]) + { + weight = notificationsData[key].weight; + weight = weight.toLowerCase(); + + tpl = notificationsData[key][lang]; + tpl = template(tpl, params); + } + else + { + //console.error("sendNotification: Notifications: undefined key", key, func, notificationsData); + console.error("sendNotification: Notifications: undefined key", key, func ); + return false; + } + + //detect invalid err weight + if(getKey(ERRWEIGHT, weight) == undefined) + { + console.error("sendNotification: Notifications: undefined weight", weight, key, func); + return false; + } + + if(sentValues.hasOwnProperty(saveKey)) + { + if(sentValues[saveKey] == tpl) + { + return false; + } + } + + if(sentValues[saveKey] == undefined) + { + if(storeToSendValues) + { + //do not send - flow is was started + sentValues[saveKey] = tpl; + return false; + } + } + + if(saveKey == "rvo_door") + { + //console.log("******", saveKey, sentValues[saveKey], tpl); + } + + if(storeToSendValues) sentValues[saveKey] = tpl; + + let str = FLOW.GLOBALS.settings.rvo_name; + if(str != "") str = str + ": "; + str = str + tpl; + + 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 + + return true; + +} + +module.exports = { + sendNotification, + ERRWEIGHT, + initNotification +} diff --git a/RVO2/flow_22_01_25/helper/register.js b/RVO2/flow_22_01_25/helper/register.js new file mode 100755 index 0000000..fc1d008 --- /dev/null +++ b/RVO2/flow_22_01_25/helper/register.js @@ -0,0 +1,144 @@ +/* +0 - cislo registra / prikaz +1 - recepient - 0 = master, 1 = slave (slave je automaticky group a broadcast) +2 - r/rw - read/write +3- register name - nazov registra / prikazu (len pre info - zobrazenie v aplikacii) + +4,5,6,7, - jednotlive byte-y - nazov byte-u +4-7 - RES. a prazdny string "" sa nezobrazia!!! +*/ + +//124 zaznamov +const registers = [ + ["0","1","R","Status","","",""], + ["1","1","RW","Dimming","R-Channel ","G-Channel","B-Channel ","W - Channel"], + ["2","1","R","Device types","","",".",""], + ["3","1","RW","Group addresses 1-4","Groups Add. 4","Groups Add. 3","Groups Add. 2","Groups Add. 1"], + ["4","1","RW","Group addresses 5-8","Groups Add. 8","Groups Add. 7","Groups Add. 6","Groups Add. 5"], + ["5","1","RW","Serial number (MAC)","","","",""], + ["6","1","RW","Time of dusk","HH","MM","SS","EXTRA"], + ["7","1","RW","Time of dawn","HH","MM","SS","EXTRA"], + ["8","1","RW","Time Schedule settings","TBD","TBD","Movement sensor","Time Schedule"], + ["9","1","RW","TS1 Time point 1","HH","MM","SS","Ext. Device"], + ["10","1","RW","TS1 Time point 1 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["11","1","RW","TS1 Time point 2","HH","MM","SS","Ext. Device"], + ["12","1","RW","TS1 Time point 2 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["13","1","RW","TS1 Time point 3","HH","MM","SS","Ext. Device"], + ["14","1","RW","TS1 Time point 3 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["15","1","RW","TS1 Time point 4","HH","MM","SS","Ext. Device"], + ["16","1","RW","TS1 Time point 4 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["17","1","RW","TS1 Time point 5","HH","MM","SS","Ext. Device"], + ["18","1","RW","TS1 Time point 5 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["19","1","RW","TS1 Time point 6","HH","MM","SS","Ext. Device"], + ["20","1","RW","TS1 Time point 6 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["21","1","RW","TS1 Time point 7","HH","MM","SS","Ext. Device"], + ["22","1","RW","TS1 Time point 7 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["23","1","RW","TS1 Time point 8","HH","MM","SS","Ext. Device"], + ["24","1","RW","TS1 Time point 8 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["25","1","RW","TS1 Time point 9","HH","MM","SS","Ext. Device"], + ["26","1","RW","TS1 Time point 9 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["27","1","RW","TS1 Time point 10","HH","MM","SS","Ext. Device"], + ["28","1","RW","TS1 Time point 10 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["29","1","RW","TS1 Time point 11","HH","MM","SS","Ext. Device"], + ["30","1","RW","TS1 Time point 11 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["31","1","RW","TS1 Time point 12","HH","MM","SS","Ext. Device"], + ["32","1","RW","TS1 Time point 12 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["33","1","RW","TS1 Time point 13","HH","MM","SS","Ext. Device"], + ["34","1","RW","TS1 Time point 13 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["35","1","RW","TS1 Time point 14","HH","MM","SS","Ext. Device"], + ["36","1","RW","TS1 Time point 14 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["37","1","RW","TS1 Time point 15","HH","MM","SS","Ext. Device"], + ["38","1","RW","TS1 Time point 15 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["39","1","RW","TS1 Time point 16","HH","MM","SS","Ext. Device"], + ["40","1","RW","TS1 Time point 16 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["41","1","RW","TS2 Time point 1","HH","MM","SS","Ext. Device"], + ["42","1","RW","TS2 Time point 1 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["43","1","RW","TS2 Time point 2","HH","MM","SS","Ext. Device"], + ["44","1","RW","TS2 Time point 2 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["45","1","RW","TS2 Time point 3","HH","MM","SS","Ext. Device"], + ["46","1","RW","TS2 Time point 3 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["47","1","RW","TS2 Time point 4","HH","MM","SS","Ext. Device"], + ["48","1","RW","TS2 Time point 4 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["49","1","RW","TS2 Time point 5","HH","MM","SS","Ext. Device"], + ["50","1","RW","TS2 Time point 5 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["51","1","RW","TS2 Time point 6","HH","MM","SS","Ext. Device"], + ["52","1","RW","TS2 Time point 6 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["53","1","RW","TS2 Time point 7","HH","MM","SS","Ext. Device"], + ["54","1","RW","TS2 Time point 7 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["55","1","RW","TS2 Time point 8","HH","MM","SS","Ext. Device"], + ["56","1","RW","TS2 Time point 8 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["57","1","RW","TS2 Time point 9","HH","MM","SS","Ext. Device"], + ["58","1","RW","TS2 Time point 9 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["59","1","RW","TS2 Time point 10","HH","MM","SS","Ext. Device"], + ["60","1","RW","TS2 Time point 10 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["61","1","RW","TS2 Time point 11","HH","MM","SS","Ext. Device"], + ["62","1","RW","TS2 Time point 11 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["63","1","RW","TS2 Time point 12","HH","MM","SS","Ext. Device"], + ["64","1","RW","TS2 Time point 12 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["65","1","RW","TS2 Time point 13","HH","MM","SS","Ext. Device"], + ["66","1","RW","TS2 Time point 13 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["67","1","RW","TS2 Time point 14","HH","MM","SS","Ext. Device"], + ["68","1","RW","TS2 Time point 14 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["69","1","RW","TS2 Time point 15","HH","MM","SS","Ext. Device"], + ["70","1","RW","TS2 Time point 15 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["71","1","RW","TS2 Time point 16","HH","MM","SS","Ext. Device"], + ["72","1","RW","TS2 Time point 16 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["73","1","RW","Power meter status","TBD","","",""], + ["74","1","R","Input Voltage","","","",""], + ["75","1","R","Input Current","","","",""], + ["76","1","R","Input Power","","","",""], + ["77","1","R","Cos phi","","","",""], + ["78","1","R","Frequency","","","",""], + ["79","1","RW","Energy","","","",""], + ["80","1","RW","Lifetime","","","",""], + ["81","1","RW","Power on cycles (input)","","","",""], + ["82","1","RW","Power on cycles (relay)","","","",""], + ["83","1","R","Time since last power on","","","",""], + ["84","1","R","Accelerometer data","","","",""], + ["85","1","RW","GPS latitude","pos/neg","deg","min ","sec"], + ["86","1","RW","GPS longitude","pos/neg","deg","min ","sec"], + ["87","1","RW","Actual time","HH","MM","SS","RES."], + ["88","1","RW","Actual date","Day of week","Day","Month","Year"], + ["89","1","R","Production data 1","","","",""], + ["90","1","R","Production data 2","","","",""], + ["91","1","RW","Network ID","NID3","NID2","NID1","NID0"], + ["95","1","RW","Actual Lux level from cabinet","RES.","RES.","HB","LB"], + ["96","1","RW","Threshold lux level","Dusk HB","Dusk LB","Dawn HB","Dawn LB"], + ["97","1","RW","Adjust period","Dusk HB","Dusk LB","Dawn HB","Dawn LB"], + ["98","1","RW","Offset","RES.","RES.","Dusk","Dawn"], + ["99","1","RW","CCT min/max range","max-H","max-L","min-H","min-L"], + ["100","1","RW","DALI interface","Cmd ID","Add","Cmd","Resp"], + ["101","1","RW","Module FW ver","v1","v2","v3","v4"], + ["102","1","RW","Module MAC-H","unused","unused","M1","M2"], + ["103","1","RW","Module MAC-L","M3","M4","M5","M6"], + ["122","1","R","FW update status/control register","Byte3","Byte2","Byte1","Byte0"], + ["123","1","R","FW update - data index","Byte3","Byte2","Byte1","Byte0"], + ["124","1","R","FW update - data","Byte3","Byte2","Byte1","Byte0"], + ["0","0","R","Status","","","",""], + ["1","0","RW","Control register","RES.","RES.","RES.","init mode enable"], + ["2","0","R","Device types","","","",""], + ["3","0","R","Serial number (MAC)","","","",""], + ["4","0","R","Production data 1","","","",""], + ["5","0","R","Production data 2","","","",""], + ["6","0","RW","Network ID","NID3","NID2","NID1","NID0"], + ["7","0","RW","RS232 settings","param.","param.","Baudrate H","Baudrate L"], + ["8","0","R","Accelerometer data","","","",""], + ["9","0","RW","Module FW ver","v1","v2","v3","v4"], + ["10","0","RW","Module MAC-H","unused","unused","M1","M2"], + ["11","0","RW","Module MAC-L","M3","M4","M5","M6"], + ["32","0","RW","FW update status/control register","Byte3","Byte2","Byte1","Byte0"], + ["33","0","RW","FW update - data index","Byte3","Byte2","Byte1","Byte0"], + ["34","0","RW","FW update - data","Byte3","Byte2","Byte1","Byte0"], + ["125","0","RW","Debug Register","Byte3","Byte2","Byte1","Byte0"], + ["126","0","RW","Network Control Register","Byte3","Byte2","Byte1","Byte0"], + ["127","0","R","Network Status Register","Byte3","Byte2","Byte1","Byte0"], + ["128","0","RW","Node XX Serial Number Register","SER3","SER2","SER1","SER0"], + ["256","0","R","Node XX Network Status Register","","","",""] +]; + +let register = {}; + +module.exports = { + registers, + register +} \ No newline at end of file diff --git a/RVO2/flow_22_01_25/helper/serialport_helper.js b/RVO2/flow_22_01_25/helper/serialport_helper.js new file mode 100755 index 0000000..8efa6af --- /dev/null +++ b/RVO2/flow_22_01_25/helper/serialport_helper.js @@ -0,0 +1,100 @@ +const { exec } = require('child_process'); + +function openPort(port){ + return new Promise((resolve, reject) => { + + var callbackError = function(err) { + port.removeListener('error', callbackError); + port.removeListener('open', callbackError); + + reject(err.message); + }; + + var callbackOpen = function(data) { + port.removeListener('error', callbackError); + port.removeListener('open', callbackOpen); + + resolve("port open: ok"); + }; + + port.on('error', callbackError); + port.on('open', callbackOpen); + + port.open(); + + }) +} + +function runSyncExec(command){ + return new Promise((resolve, reject) => { + + exec(command, (error, stdout, stderr) => { + if(error == null) resolve(stdout); + reject(error); + }); + + }) +} + +async function writeData(port, data, readbytes, timeout){ + return new Promise((resolve, reject) => { + + // 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) { + + port.write(Buffer.from(data), function(err) { + if (err) { + reject(err.message); + } + }); + + 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 +} diff --git a/RVO2/flow_22_01_25/helper/suncalc.js b/RVO2/flow_22_01_25/helper/suncalc.js new file mode 100755 index 0000000..c9ca56d --- /dev/null +++ b/RVO2/flow_22_01_25/helper/suncalc.js @@ -0,0 +1,317 @@ +/* + (c) 2011-2015, Vladimir Agafonkin + SunCalc is a JavaScript library for calculating sun/moon position and light phases. + https://github.com/mourner/suncalc +*/ + +(function () { 'use strict'; + +// shortcuts for easier to read formulas + +var PI = Math.PI, + sin = Math.sin, + cos = Math.cos, + tan = Math.tan, + asin = Math.asin, + atan = Math.atan2, + acos = Math.acos, + rad = PI / 180; + +// sun calculations are based on http://aa.quae.nl/en/reken/zonpositie.html formulas + + +// date/time constants and conversions + +var dayMs = 1000 * 60 * 60 * 24, + J1970 = 2440588, + J2000 = 2451545; + +function toJulian(date) { return date.valueOf() / dayMs - 0.5 + J1970; } +function fromJulian(j) { return new Date((j + 0.5 - J1970) * dayMs); } +function toDays(date) { return toJulian(date) - J2000; } + + +// general calculations for position + +var e = rad * 23.4397; // obliquity of the Earth + +function rightAscension(l, b) { return atan(sin(l) * cos(e) - tan(b) * sin(e), cos(l)); } +function declination(l, b) { return asin(sin(b) * cos(e) + cos(b) * sin(e) * sin(l)); } + +function azimuth(H, phi, dec) { return atan(sin(H), cos(H) * sin(phi) - tan(dec) * cos(phi)); } +function altitude(H, phi, dec) { return asin(sin(phi) * sin(dec) + cos(phi) * cos(dec) * cos(H)); } + +function siderealTime(d, lw) { return rad * (280.16 + 360.9856235 * d) - lw; } + +function astroRefraction(h) { + if (h < 0) // the following formula works for positive altitudes only. + h = 0; // if h = -0.08901179 a div/0 would occur. + + // formula 16.4 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + // 1.02 / tan(h + 10.26 / (h + 5.10)) h in degrees, result in arc minutes -> converted to rad: + return 0.0002967 / Math.tan(h + 0.00312536 / (h + 0.08901179)); +} + +// general sun calculations + +function solarMeanAnomaly(d) { return rad * (357.5291 + 0.98560028 * d); } + +function eclipticLongitude(M) { + + var C = rad * (1.9148 * sin(M) + 0.02 * sin(2 * M) + 0.0003 * sin(3 * M)), // equation of center + P = rad * 102.9372; // perihelion of the Earth + + return M + C + P + PI; +} + +function sunCoords(d) { + + var M = solarMeanAnomaly(d), + L = eclipticLongitude(M); + + return { + dec: declination(L, 0), + ra: rightAscension(L, 0) + }; +} + + +var SunCalc = {}; + + +// calculates sun position for a given date and latitude/longitude + +SunCalc.getPosition = function (date, lat, lng) { + + var lw = rad * -lng, + phi = rad * lat, + d = toDays(date), + + c = sunCoords(d), + H = siderealTime(d, lw) - c.ra; + + return { + azimuth: azimuth(H, phi, c.dec), + altitude: altitude(H, phi, c.dec) + }; +}; + + +// sun times configuration (angle, morning name, evening name) + +var times = SunCalc.times = [ + [-0.833, 'sunrise', 'sunset' ], + [ -0.3, 'sunriseEnd', 'sunsetStart' ], + [ -6, 'dawn', 'dusk' ], + [ -12, 'nauticalDawn', 'nauticalDusk'], + [ -18, 'nightEnd', 'night' ], + [ 6, 'goldenHourEnd', 'goldenHour' ] +]; + +// adds a custom time to the times config + +SunCalc.addTime = function (angle, riseName, setName) { + times.push([angle, riseName, setName]); +}; + + +// calculations for sun times + +var J0 = 0.0009; + +function julianCycle(d, lw) { return Math.round(d - J0 - lw / (2 * PI)); } + +function approxTransit(Ht, lw, n) { return J0 + (Ht + lw) / (2 * PI) + n; } +function solarTransitJ(ds, M, L) { return J2000 + ds + 0.0053 * sin(M) - 0.0069 * sin(2 * L); } + +function hourAngle(h, phi, d) { return acos((sin(h) - sin(phi) * sin(d)) / (cos(phi) * cos(d))); } +function observerAngle(height) { return -2.076 * Math.sqrt(height) / 60; } + +// returns set time for the given sun altitude +function getSetJ(h, lw, phi, dec, n, M, L) { + + var w = hourAngle(h, phi, dec), + a = approxTransit(w, lw, n); + return solarTransitJ(a, M, L); +} + + +// calculates sun times for a given date, latitude/longitude, and, optionally, +// the observer height (in meters) relative to the horizon + +SunCalc.getTimes = function (date, lat, lng, height) { + + height = height || 0; + + var lw = rad * -lng, + phi = rad * lat, + + dh = observerAngle(height), + + d = toDays(date), + n = julianCycle(d, lw), + ds = approxTransit(0, lw, n), + + M = solarMeanAnomaly(ds), + L = eclipticLongitude(M), + dec = declination(L, 0), + + Jnoon = solarTransitJ(ds, M, L), + + i, len, time, h0, Jset, Jrise; + + + var result = { + solarNoon: fromJulian(Jnoon), + nadir: fromJulian(Jnoon - 0.5) + }; + + for (i = 0, len = times.length; i < len; i += 1) { + time = times[i]; + h0 = (time[0] + dh) * rad; + + Jset = getSetJ(h0, lw, phi, dec, n, M, L); + Jrise = Jnoon - (Jset - Jnoon); + + result[time[1]] = fromJulian(Jrise); + result[time[2]] = fromJulian(Jset); + } + + return result; +}; + + +// moon calculations, based on http://aa.quae.nl/en/reken/hemelpositie.html formulas + +function moonCoords(d) { // geocentric ecliptic coordinates of the moon + + var L = rad * (218.316 + 13.176396 * d), // ecliptic longitude + M = rad * (134.963 + 13.064993 * d), // mean anomaly + F = rad * (93.272 + 13.229350 * d), // mean distance + + l = L + rad * 6.289 * sin(M), // longitude + b = rad * 5.128 * sin(F), // latitude + dt = 385001 - 20905 * cos(M); // distance to the moon in km + + return { + ra: rightAscension(l, b), + dec: declination(l, b), + dist: dt + }; +} + +SunCalc.getMoonPosition = function (date, lat, lng) { + + var lw = rad * -lng, + phi = rad * lat, + d = toDays(date), + + c = moonCoords(d), + H = siderealTime(d, lw) - c.ra, + h = altitude(H, phi, c.dec), + // formula 14.1 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + pa = atan(sin(H), tan(phi) * cos(c.dec) - sin(c.dec) * cos(H)); + + h = h + astroRefraction(h); // altitude correction for refraction + + return { + azimuth: azimuth(H, phi, c.dec), + altitude: h, + distance: c.dist, + parallacticAngle: pa + }; +}; + + +// calculations for illumination parameters of the moon, +// based on http://idlastro.gsfc.nasa.gov/ftp/pro/astro/mphase.pro formulas and +// Chapter 48 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + +SunCalc.getMoonIllumination = function (date) { + + var d = toDays(date || new Date()), + s = sunCoords(d), + m = moonCoords(d), + + sdist = 149598000, // distance from Earth to Sun in km + + phi = acos(sin(s.dec) * sin(m.dec) + cos(s.dec) * cos(m.dec) * cos(s.ra - m.ra)), + inc = atan(sdist * sin(phi), m.dist - sdist * cos(phi)), + angle = atan(cos(s.dec) * sin(s.ra - m.ra), sin(s.dec) * cos(m.dec) - + cos(s.dec) * sin(m.dec) * cos(s.ra - m.ra)); + + return { + fraction: (1 + cos(inc)) / 2, + phase: 0.5 + 0.5 * inc * (angle < 0 ? -1 : 1) / Math.PI, + angle: angle + }; +}; + + +function hoursLater(date, h) { + return new Date(date.valueOf() + h * dayMs / 24); +} + +// calculations for moon rise/set times are based on http://www.stargazing.net/kepler/moonrise.html article + +SunCalc.getMoonTimes = function (date, lat, lng, inUTC) { + var t = new Date(date); + if (inUTC) t.setUTCHours(0, 0, 0, 0); + else t.setHours(0, 0, 0, 0); + + var hc = 0.133 * rad, + h0 = SunCalc.getMoonPosition(t, lat, lng).altitude - hc, + h1, h2, rise, set, a, b, xe, ye, d, roots, x1, x2, dx; + + // go in 2-hour chunks, each time seeing if a 3-point quadratic curve crosses zero (which means rise or set) + for (var i = 1; i <= 24; i += 2) { + h1 = SunCalc.getMoonPosition(hoursLater(t, i), lat, lng).altitude - hc; + h2 = SunCalc.getMoonPosition(hoursLater(t, i + 1), lat, lng).altitude - hc; + + a = (h0 + h2) / 2 - h1; + b = (h2 - h0) / 2; + xe = -b / (2 * a); + ye = (a * xe + b) * xe + h1; + d = b * b - 4 * a * h1; + roots = 0; + + if (d >= 0) { + dx = Math.sqrt(d) / (Math.abs(a) * 2); + x1 = xe - dx; + x2 = xe + dx; + if (Math.abs(x1) <= 1) roots++; + if (Math.abs(x2) <= 1) roots++; + if (x1 < -1) x1 = x2; + } + + if (roots === 1) { + if (h0 < 0) rise = i + x1; + else set = i + x1; + + } else if (roots === 2) { + rise = i + (ye < 0 ? x2 : x1); + set = i + (ye < 0 ? x1 : x2); + } + + if (rise && set) break; + + h0 = h2; + } + + var result = {}; + + if (rise) result.rise = hoursLater(t, rise); + if (set) result.set = hoursLater(t, set); + + if (!rise && !set) result[ye > 0 ? 'alwaysUp' : 'alwaysDown'] = true; + + return result; +}; + + +// export as Node module / AMD module / browser variable +if (typeof exports === 'object' && typeof module !== 'undefined') module.exports = SunCalc; +else if (typeof define === 'function' && define.amd) define(SunCalc); +else window.SunCalc = SunCalc; + +}()); diff --git a/RVO2/flow_22_01_25/helper/utils.js b/RVO2/flow_22_01_25/helper/utils.js new file mode 100755 index 0000000..a16210c --- /dev/null +++ b/RVO2/flow_22_01_25/helper/utils.js @@ -0,0 +1,124 @@ +function bytesToInt(bytes, numberOfBytes) +{ + let buffer = []; + if(Array.isArray(bytes)) + { + buffer = bytes.slice(0); + if(numberOfBytes != undefined) + { + buffer = bytes.slice(bytes.length - numberOfBytes); + } + } + else buffer.push(bytes); + + //var decimal = (buffer[0] << 24) + (buffer[1] << 16) + (buffer[2] << 8) + buffer[3]; + let l = (buffer.length - 1) * 8; + + let decimal = 0; + for(let i = 0; i < buffer.length; i++) + { + var s = buffer[i] << l; + if(l < 8) s = buffer[i] + decimal = decimal + s; + + l = l - 8; + + } + + return decimal; +} + +function resizeArray(arr, newSize, defaultValue) { + while(newSize > arr.length) + arr.push(defaultValue); + arr.length = newSize; +} + +longToByteArray = function(/*long*/long) { + // we want to represent the input as a 8-bytes array + var byteArray = [0, 0, 0, 0, 0, 0, 0, 0]; + + for ( var index = 0; index < byteArray.length; index ++ ) { + var byte = long & 0xff; + byteArray [ index ] = byte; + long = (long - byte) / 256 ; + } + + return byteArray; + }; + +function addDays(date, days) { + var result = new Date(date); + result.setDate(result.getDate() + days); + return result; +} + +/* +sleep(2000).then(() => { + // Do something after the sleep! + + +}); +*/ + +function sleep (time) { + return new Promise((resolve) => setTimeout(resolve, time)); +} + +function isEmptyObject( obj ) { + for ( var name in obj ) { + return false; + } + return true; +} + +function convertUTCDateToLocalDate(date) { + var newDate = new Date(date); + newDate.setMinutes(date.getMinutes() + date.getTimezoneOffset()); + return newDate; +} + +function addZeroBefore(n) { + return (n < 10 ? '0' : '') + n; +} + +var convertBase = function () { + + function convertBase(baseFrom, baseTo) { + return function (num) { + return parseInt(num, baseFrom).toString(baseTo); + + }; + } + + // binary to decimal + convertBase.bin2dec = convertBase(2, 10); + + // binary to hexadecimal + convertBase.bin2hex = convertBase(2, 16); + + // decimal to binary + convertBase.dec2bin = convertBase(10, 2); + + // decimal to hexadecimal + convertBase.dec2hex = convertBase(10, 16); + + // hexadecimal to binary + convertBase.hex2bin = convertBase(16, 2); + + // hexadecimal to decimal + convertBase.hex2dec = convertBase(16, 10); + + return convertBase; + }(); + +module.exports = { + bytesToInt, + longToByteArray, + addDays, + addZeroBefore, + resizeArray, + isEmptyObject, + sleep, + convertUTCDateToLocalDate +} \ No newline at end of file diff --git a/RVO2/flow_22_01_25/httprequest.js b/RVO2/flow_22_01_25/httprequest.js new file mode 100755 index 0000000..469c8cb --- /dev/null +++ b/RVO2/flow_22_01_25/httprequest.js @@ -0,0 +1,137 @@ +exports.id = 'httprequest'; +exports.title = 'HTTP Request'; +exports.group = 'HTTP'; +exports.color = '#5D9CEC'; +exports.input = true; +exports.version = '2.0.1'; +exports.output = 1; +exports.author = 'Peter Širka'; +exports.icon = 'cloud-upload'; + +exports.html = `
+
@(URL address)
+
+
+
@(HTTP method)
+
+
+
@(Serialization)
+
+
+
@(Download the content in chunks)
+
@(Keep persistent cookies)
+
@(Disable DNS cache)
+
@(Keep alive connection)
+
+
+
+
@(Custom headers)
+
@(Cookies)
+
+
+
+ +
+
+
+
@(User)
+
+
+
@(Password)
+
+
+
+
+
`; + +exports.readme = `# Request + +This component creates a request with received data. + +__Response:__ +\`\`\`javascript +{ + data: String, + headers: Object, + status: Number, + host: String +} +\`\`\` + +__Dynamic arguments__: +Are performed via FlowData repository and can be used for URL address or for custom headers/cookies/auth. Use \`repository\` component for creating of dynamic arguments. Dynamic values are replaced in the form \`{key}\`: + +- url address e.g. \`https://.../{key}/\` +- headers values e.g. \`{token}\` +- cookies values e.g. \`{token}\``; + +exports.install = function(instance) { + + var can = false; + var flags = null; + var cookies2 = null; + + instance.on('data', function(response) { + can && instance.custom.send(response); + }); + + instance.custom.send = function(response) { + var options = instance.options; + + var headers = null; + var cookies = null; + + options.headers && Object.keys(options.headers).forEach(function(key) { + !headers && (headers = {}); + headers[key] = response.arg(options.headers[key]); + }); + + if (options.username && options.userpassword) { + !headers && (headers = {}); + headers['Authorization'] = 'Basic ' + U.createBuffer(response.arg(options.username + ':' + options.userpassword)).toString('base64'); + } + + options.cookies && Object.keys(options.cookies).forEach(function(key) { + !cookies && (cookies = {}); + cookies[key] = response.arg(options.cookies[key]); + }); + + if (options.chunks) { + U.download(response.arg(options.url), flags, options.stringify === 'none' ? null : response.data, function(err, response) { + response.on('data', (chunks) => instance.send2(chunks)); + }, cookies || cookies2, headers); + } else { + U.request(response.arg(options.url), flags, options.stringify === 'none' ? null : response.data, 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) + instance.error(err, response); + }, cookies || cookies2, headers); + } + }; + + instance.reconfigure = function() { + var options = instance.options; + can = options.url && options.url && options.method && options.stringify ? true : false; + instance.status(can ? '' : 'Not configured', can ? undefined : 'red'); + + if (!can) + return; + + flags = []; + flags.push(options.method.toLowerCase()); + options.stringify === 'json' && flags.push('json'); + options.stringify === 'raw' && flags.push('raw'); + options.keepalive && flags.push('keepalive'); + !options.nodns && flags.push('dnscache'); + if (options.persistentcookies) { + flags.push('cookies'); + cookies2 = {}; + } else + cookies2 = null; + }; + + instance.on('options', instance.reconfigure); + instance.reconfigure(); +}; \ No newline at end of file diff --git a/RVO2/flow_22_01_25/httpresponse.js b/RVO2/flow_22_01_25/httpresponse.js new file mode 100755 index 0000000..160a3bb --- /dev/null +++ b/RVO2/flow_22_01_25/httpresponse.js @@ -0,0 +1,76 @@ +exports.id = 'httpresponse'; +exports.title = 'HTTP Response'; +exports.group = 'HTTP'; +exports.color = '#5D9CEC'; +exports.icon = 'arrow-right'; +exports.input = true; +exports.output = ['#666D76']; +exports.version = '2.0.0'; +exports.author = 'Martin Smola'; +exports.readme = `# HTTP response + +HTTP response will respond with data recieved using data-type set in Settings form or plain text if not set. Output is the message duration \`Number\` in seconds.`; + +exports.html = `
+
@(Response data-type)
+
JSON is by default.
+
`; + +exports.install = function(instance) { + + var dursum = 0; + var durcount = 0; + + instance.on('data', function(flowdata) { + + var ctrl = flowdata.repository.controller; + var data = flowdata.data; + + if (!ctrl) { + instance.throw('No controller to use for response!'); + return; + } + + durcount++; + dursum += ((new Date() - flowdata.begin) / 1000).floor(2); + setTimeout2(instance.id, instance.custom.duration, 500, 10); + + ctrl.$flowdata = flowdata; + + var datatype = instance.options.datatype || 'json'; + if (datatype === 'emptyresponse') + return ctrl.plain(''); + + if (datatype !== 'json' && typeof(data) !== 'string') { + instance.throw('Incorect type of data, expected string, got ' + typeof(data)); + ctrl.plain(data == null ? '' : data.toString()); + return; + } + + switch(datatype) { + case 'html': + ctrl.content(data, 'text/html'); + break; + case 'plain': + ctrl.plain(data); + break; + case 'xml': + ctrl.content(data, 'text/xml'); + break; + default: + ctrl.json(data); + break; + } + }); + + instance.on('service', function() { + dursum = 0; + durcount = 0; + }); + + instance.custom.duration = function() { + var avg = (dursum / durcount).floor(2); + instance.status(avg + ' sec.'); + instance.send2(0, avg); + }; +}; diff --git a/RVO2/flow_22_01_25/httproute.js b/RVO2/flow_22_01_25/httproute.js new file mode 100755 index 0000000..583a19d --- /dev/null +++ b/RVO2/flow_22_01_25/httproute.js @@ -0,0 +1,326 @@ +exports.id = 'httproute'; +exports.title = 'HTTP Route'; +exports.group = 'HTTP'; +exports.color = '#5D9CEC'; +exports.icon = 'globe'; +exports.input = false; +exports.output = ['#6CAC5A', '#37BC9B']; +exports.version = '1.2.3'; +exports.author = 'Martin Smola'; +exports.cloning = false; +exports.options = { method: 'GET', url: '', size: 5, cacheexpire: '5 minutes', cachepolicy: 0, timeout: 5 }; +exports.dateupdated = '2021-01-21 18:30d'; +exports.readme = `# HTTP route + +__Outputs__: +- first output: raw data (cache is empty or is disabled) +- second output: cached data + +If one of the outputs is disabled then automatic responce with code "503 service unavailable" is sent. + +When a request comes in bellow object is available at \`flowdata.data\`: + +\`\`\`javascript +{ + params: { id: '1' }, // params for dynamic routes, e.g. /test/{id} + query: { msg: 'Hello' }, // parsed query string, e.g. /test/1?msg=Hello + body: { test: 'OK' }, // object if json requests otherwise string + headers: {}, // headers data + session: {}, // session data + user: {}, // user data + files: [], // uploaded files + url: '/users/', // a relative URL address + referrer: '/', // referrer + mobile: false, // determines mobile device + robot: false, // determines search robots/crawlsers + language: 'en' // determines language +} +\`\`\` + +See [documentation for flags](https://docs.totaljs.com/latest/en.html#api~HttpRouteOptionsFlags~unauthorize). These method flags are set automatically e.g. \`get, post, put, patch or delete\` + +--- + +\`id:ROUTE_ID\` flag cannot be used since it's already used by this component internally`; + +exports.html = `
+
+ +
+ +
+
+
@(HTTP method)
+
+
+
@(URL address)
+
+
+
+
+
@(Additional flags)
+
@(Separate flags by comma e.g. json, authorize)
+
+
+
@(Max. request size)
+
@(In kB kilobytes)
+
+
+
@(Timeout)
+
@(In seconds.)
+
+
+
+
+
+
@(Automatically respond with 200 OK?)
+
@(If not checked you need to use HTTP response component to respond to the request.)
+
+
@(Custom headers)
+
@(Cookies)
+
+
+
+
+
+
@(Cache policy)
+
@(User instance must contain id property.)
+
+
+
@(Expiration)
+
@(E.g. 5 minutes)
+
+
+
+`; + +exports.install = function(instance) { + + var route; + + var uninstall = function(id) { + if (F.is4) { + route && route.remove(); + route = null; + } else + UNINSTALL('route', id); + }; + + instance.custom.emptyresponse = function(self) { + self.plain(); + }; + + instance.reconfigure = function() { + + var options = instance.options; + + if (!options.url) { + instance.status('Not configured', 'red'); + return; + } + + if (typeof(options.flags) === 'string') + options.flags = options.flags.split(',').trim(); + + uninstall('id:' + instance.id); + + var flags = options.flags || []; + + flags.push('id:' + instance.id); + + if (!F.is4) + flags.push(options.method.toLowerCase()); + + options.timeout && flags.push(options.timeout * 1000); + + // Make unique values + flags = flags.filter(function(v, i, a) { + if(F.is4 && v.toString().toLowerCase() === options.method.toLowerCase()) + return false; // remove method + return a.indexOf(v) === i; + }); + + options.flags = flags; + var handler = function() { + + if (instance.paused || (instance.isDisabled && (instance.isDisabled('output', 0) || instance.isDisabled('output', 1)))) { + instance.status('503 Service Unavailable'); + this.status = 503; + this.json(); + return; + } + + var key; + var self = this; + + if (instance.options.emptyresponse) { + instance.status('200 OK'); + setTimeout(instance.custom.emptyresponse, 100, self); + + if (instance.hasConnection(0)) { + var data = instance.make({ + query: self.query, + body: self.body, + session: self.session, + user: self.user, + files: self.files, + headers: self.req.headers, + url: self.url, + params: self.params + }); + instance.send2(0, data); + } + + return; + } + + switch (instance.options.cachepolicy) { + case 1: // URL + key = 'rro' + instance.id + self.url.hash(); + break; + case 2: // URL + query + case 3: // URL + query + user + key = self.url; + var keys = Object.keys(self.query); + keys.sort(); + for (var i = 0, length = keys.length; i < length; i++) + key += keys[i] + self.query[keys[i]] + '&'; + if (instance.options.cachepolicy === 3 && self.user) + key += 'iduser' + self.user.id; + key = 'rro' + instance.id + key.hash(); + break; + } + + if (key && F.cache.get2(key)) { + var data = instance.make(F.cache.get2(key)); + data.repository.controller = self; + instance.send2(1, data); + } else { + + var data = instance.make({ + query: self.query, + body: self.body, + session: self.session, + user: self.user, + files: self.files, + headers: self.req.headers, + url: self.url, + params: self.params, + mobile: self.mobile, + robot: self.robot, + referrer: self.referrer, + language: self.language + }); + + data.repository.controller = self; + instance.send2(0, data); + key && FINISHED(self.res, () => F.cache.set(key, self.$flowdata.data, instance.options.cacheexpire)); + } + }; + + if (F.is4) + route = ROUTE(options.method.toUpperCase() + ' ' + options.url, handler, flags, options.size || 5); + else + F.route(options.url, handler, flags, options.size || 5); + + instance.status('Listening', 'green'); + }; + + instance.reconfigure(); + instance.on('options', instance.reconfigure); + instance.on('close', function(){ + uninstall('id:' + instance.id); + }); +}; + +// check url exists +FLOW.trigger('httproutecheckurl', function(next, data) { + var url = data.url; + var method = data.method; + if (url[url.length - 1] !== '/') + url += '/'; + var exists = F.routes.web.findItem(r => r.urlraw === url && r.method === method); + next(exists != null); +}); + +exports.uninstall = function() { + FLOW.trigger('httproutecheckurl', null); +}; diff --git a/RVO2/flow_22_01_25/infosender.js b/RVO2/flow_22_01_25/infosender.js new file mode 100755 index 0000000..c7afd83 --- /dev/null +++ b/RVO2/flow_22_01_25/infosender.js @@ -0,0 +1,101 @@ +exports.id = 'infosender'; +exports.title = 'Info sender'; +exports.version = '1.0.0'; +exports.group = 'Worksys'; +exports.color = '#2134B0'; +exports.input = 2; +exports.output = 1 +exports.icon = 'bolt'; + +const { networkInterfaces } = require('os'); + +exports.html = `
+
+
+
CSV Import
+
+
+
`; + +exports.readme = `# send all data to projects.worksys.io, required to monitor status of controller(unipi)`; + +exports.install = function(instance) { + + let id; + let allValues = {}; + let sendAllValuesInterval; + let configured = false; + + let now = new Date(); + console.log(exports.title, "INSTALLED", now.toLocaleString("sk-SK")); + + const nets = networkInterfaces(); + let ipAddresses = Object.create(null); // Or just '{}', an empty object + + for (const name of Object.keys(nets)) { + for (const net of nets[name]) { + // Skip over non-IPv4 and internal (i.e. 127.0.0.1) addresses + if (net.family === 'IPv4' && !net.internal) { + if (!ipAddresses[name]) { + ipAddresses[name] = []; + } + ipAddresses[name].push(net.address); + } + } + } + + function sendValues() + { + if(!configured) return; + + if(Object.keys(allValues).length > 0) + { + if(id) + { + delete allValues.__force__; + let dataToSend = {...allValues}; + dataToSend.id = id; + dataToSend.ipAddresses = ipAddresses; + + instance.send(0, dataToSend); + + allValues = {}; + } + else + { + console.log(exports.title, "unable to send data, no id"); + } + + } + } + + instance.on("close", () => { + clearInterval(sendAllValuesInterval); + }) + + instance.on("0", _ => { + id = FLOW.GLOBALS.settings.project_id; + configured = true; + }) + + instance.on("1", flowdata => { + + allValues = { ...allValues, ...flowdata.data}; + //console.log("DATA RECEIVED", flowdata.data); + + //__force__ + if(flowdata.data.hasOwnProperty("__force__")) + { + if(flowdata.data.__force__) + { + sendValues(); + } + } + }) + + sendAllValuesInterval = setInterval(() => { + sendValues(); + }, 60000*3); + +} + diff --git a/RVO2/flow_22_01_25/modbus_reader.js b/RVO2/flow_22_01_25/modbus_reader.js new file mode 100755 index 0000000..b0908ae --- /dev/null +++ b/RVO2/flow_22_01_25/modbus_reader.js @@ -0,0 +1,363 @@ +exports.id = 'modbus_reader'; +exports.title = 'Modbus reader'; +exports.version = '2.0.0'; +exports.group = 'Worksys'; +exports.color = '#2134B0'; +exports.input = 1; +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; +//number of phases inRVO +let phases; +//phases where voltage is 0 (set) +let noVoltage; + +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.phases = this.buildPhases(); + + this.startSocket(); + } + + buildPhases = () => { + let a = []; + for (let i = 1; i<= phases; i++) { + a.push(`Phase_${i}_voltage`) + } + return a; + } + + 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 (this.phases.includes(singleValue)) + { + let l = singleValue.split("_"); + let phase = parseInt(l[1]); + + // console.log(values[singleValue], tbName); + + if(values[singleValue] == 0) + { + noVoltage.add(phase); + sendNotification("modbus_reader: checkNullVoltage", tbName, "no_voltage_on_phase", {phase: phase}, "", SEND_TO.tb, instance, "voltage" + phase ); + // console.log('no voltage') + } + else + { + noVoltage.delete(phase); + // console.log('voltage detected') + sendNotification("modbus_reader: checkNullVoltage", tbName, "voltage_on_phase_restored", {phase: phase}, "", SEND_TO.tb, instance, "voltage" + phase); + } + } + }) + } + + /** + * 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; + } + + function main() { + + phases = FLOW.GLOBALS.settings.phases; + tbName = FLOW.GLOBALS.settings.rvoTbName; + noVoltage = FLOW.GLOBALS.settings.no_voltage; + mainSocket = new SocketWithClients(); + + // this notification is to show, that flow (unipi) has been restarted + sendNotification("modbus_reader", tbName, "flow_restart", {}, "", SEND_TO.slack, instance); + } + + instance.on("0", function(_) { + main(); + }) + +} + diff --git a/RVO2/flow_22_01_25/monitorconsumption.js b/RVO2/flow_22_01_25/monitorconsumption.js new file mode 100755 index 0000000..64cc58e --- /dev/null +++ b/RVO2/flow_22_01_25/monitorconsumption.js @@ -0,0 +1,156 @@ +exports.id = 'monitorconsumption'; +exports.title = 'Consumption'; +exports.version = '1.0.0'; +exports.author = 'Peter Širka'; +exports.group = 'Monitoring'; +exports.color = '#967ADC'; +exports.input = 0; +exports.output = 1; +exports.icon = 'bug'; +exports.options = { interval: 5000, enabled: true, monitorconsumption: true, monitorsize: true, monitorconnections: true, monitorfiles: true }; +exports.click = true; +exports.readme = `# Consumption monitoring + +This component measure CPU and memory consumption, open files and open connections of this application. It uses these Linux commands: \`ps\`, \`lsof\`, \`netstat\` and \`df\`. + +__Data Example__: + +\`\`\`javascript +{ + cpu: 0, // percentage + memory: 4096, // in bytes + size: 34303, // directory size in bytes + files: 34, // count of open files + connections: 343, // count of connections + uptime: '1-12:34:00' +} +\`\`\``; + +exports.html = `
+
+
+
@(Interval in milliseconds)
+
+
+
+
Monitor: Consumption + uptime
+
Monitor: Count of open files
+
Monitor: Count of open connections
+
Monitor: Directory size
+
`; + +exports.install = function(instance) { + + var current = { cpu: 0, memory: 0, files: 0, connections: 0, size: 0, uptime: '', counter: 0 }; + var tproc = null; + var Exec = require('child_process').exec; + var reg_empty = /\s{2,}/g; + var reg_appdisksize = /^[\d.,]+/; + + instance.custom.run = function() { + + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + + var arr = []; + + // Get CPU and Memory consumption + instance.options.monitorconsumption && arr.push(function(next) { + Exec('ps -p {0} -o %cpu,rss,etime'.format(process.pid), function(err, response) { + + if (err) { + instance.throw(err); + } else { + var line = response.split('\n')[1]; + line = line.trim().replace(reg_empty, ' ').split(' '); + var cpu = line[0].parseFloat(); + current.cpu = cpu.floor(1); + current.memory = line[1].parseInt2() * 1024; // kB to bytes + current.uptime = line[2]; + } + + next(); + }); + }); + + // Get count of open files + instance.options.monitorfiles && arr.push(function(next) { + Exec('lsof -a -p {0} | wc -l'.format(process.pid), function(err, response) { + if (err) + instance.throw(err); + else + current.files = response.trim().parseInt2(); + next(); + }); + }); + + // Get count of opened network connections + instance.options.monitorconnections && arr.push(function(next) { + Exec('netstat -an | grep :{0} | wc -l'.format(F.port), function(err, response) { + if (err) { + instance.throw(err); + } else { + current.connections = response.trim().parseInt2() - 1; + if (current.connections < 0) + current.connections = 0; + } + next(); + }); + }); + + // Get directory size + instance.options.monitorsize && current.counter % 5 !== 0 && arr.push(function(next) { + Exec('du -hsb ' + process.cwd(), function(err, response) { + if (err) { + instance.throw(err); + } else { + var match = response.trim().match(reg_appdisksize); + match && (current.size = match.toString().trim().parseInt2()); + } + next(); + }); + }); + + arr.async(function() { + + tproc && clearTimeout(tproc); + + if (instance.options.enabled) { + tproc = setTimeout(instance.custom.run, instance.options.interval); + instance.send2(current); + } + + instance.custom.status(); + current.counter++; + }); + }; + + instance.custom.status = function() { + if (instance.options.enabled) + instance.status('{0}% / {1}'.format(current.cpu, current.memory.filesize())); + else + instance.status('Disabled', 'red'); + }; + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + + if (instance.options.enabled) { + current.counter = 0; + instance.custom.run(); + } + + }); + + instance.on('close', function() { + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + }); + + setTimeout(instance.custom.run, 1000); +}; \ No newline at end of file diff --git a/RVO2/flow_22_01_25/monitordisk.js b/RVO2/flow_22_01_25/monitordisk.js new file mode 100755 index 0000000..f4fdaa0 --- /dev/null +++ b/RVO2/flow_22_01_25/monitordisk.js @@ -0,0 +1,96 @@ +exports.id = 'monitordisk'; +exports.title = 'Disk'; +exports.version = '1.0.0'; +exports.author = 'Peter Širka'; +exports.group = 'Monitoring'; +exports.color = '#F6BB42'; +exports.output = 1; +exports.icon = 'hdd-o'; +exports.click = true; +exports.options = { interval: 8000, path: '/', enabled: true }; +exports.readme = `# Disk monitoring + +This component monitors disk \`bytes\` consumption in Linux systems. It uses \`df\` command. + +__Data Example__: + +\`\`\`javascript +{ + total: 474549649408, + used: 39125245952, + free: 411294994432 +} +\`\`\``; + +exports.html = `
+
+
+
@(Interval in milliseconds)
+
+
+
@(Path)
+
+
+
`; + +exports.install = function(instance) { + + var current = { total: 0, used: 0, free: 0, path: '', type: '', percentUsed: 0 }; + var tproc = null; + + instance.custom.run = function() { + + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + + if (!instance.options.enabled) + return; + + require('child_process').exec('df -hTB1 ' + instance.options.path, function(err, response) { + + tproc = setTimeout(instance.custom.run, instance.options.interval); + + if (err) { + instance.error(err); + return; + } + + response.parseTerminal(function(line) { + if (line[0][0] !== '/') + return; + current.total = line[2].parseInt(); + current.free = line[4].parseInt(); + current.used = line[3].parseInt(); + current.path = instance.options.path || '/'; + current.type = line[1]; + current.percentUsed = line[5]; + instance.custom.status(); + instance.send2(current); + }); + }); + }; + + instance.custom.status = function() { + if (instance.options.enabled) + instance.status(current.free.filesize() + ' / ' + current.total.filesize()); + else + instance.status('Disabled', 'red'); + }; + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + instance.options.enabled && instance.custom.run(); + }); + + instance.on('close', function() { + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + }); + + setTimeout(instance.custom.run, 1000); +}; \ No newline at end of file diff --git a/RVO2/flow_22_01_25/monitormemory.js b/RVO2/flow_22_01_25/monitormemory.js new file mode 100755 index 0000000..2decbc4 --- /dev/null +++ b/RVO2/flow_22_01_25/monitormemory.js @@ -0,0 +1,87 @@ +exports.id = 'monitormemory'; +exports.title = 'Memory'; +exports.version = '1.0.0'; +exports.author = 'Peter Širka'; +exports.group = 'Monitoring'; +exports.color = '#F6BB42'; +exports.output = 1; +exports.click = true; +exports.icon = 'microchip'; +exports.options = { interval: 8000, enabled: true }; +exports.readme = `# Memory monitoring + +This component monitors memory \`bytes\` consumption in Linux systems. It uses \`free\` command. + +__Data Example__: + +\`\`\`javascript +{ + total: 33558769664, + used: 1998868480, + free: 2653708288 +} +\`\`\``; + +exports.html = `
+
+
+
@(Interval in milliseconds)
+
+
+
`; + +exports.install = function(instance) { + + var current = { total: 0, used: 0, free: 0 }; + var tproc = null; + + instance.custom.run = function() { + + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + + if (!instance.options.enabled) + return; + + require('child_process').exec('free -b -t', function(err, response) { + + tproc = setTimeout(instance.custom.run, instance.options.interval); + + if (err) { + instance.error(err); + return; + } + + var memory = response.split('\n')[1].match(/\d+/g); + current.total = memory[0].parseInt(); + current.used = memory[1].parseInt() - memory[3].parseInt(); + current.free = current.total - current.used; + instance.custom.status(); + instance.send2(current); + }); + }; + + instance.custom.status = function() { + if (instance.options.enabled) + instance.status(current.free.filesize() + ' / ' + current.total.filesize()); + else + instance.status('Disabled', 'red'); + }; + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + instance.options.enabled && instance.custom.run(); + }); + + instance.on('close', function() { + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + }); + + setTimeout(instance.custom.run, 1000); +}; \ No newline at end of file diff --git a/RVO2/flow_22_01_25/nodesdb_changecheck.js b/RVO2/flow_22_01_25/nodesdb_changecheck.js new file mode 100755 index 0000000..be1e700 --- /dev/null +++ b/RVO2/flow_22_01_25/nodesdb_changecheck.js @@ -0,0 +1,70 @@ +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/RVO2/flow_22_01_25/notifikacie.csv b/RVO2/flow_22_01_25/notifikacie.csv new file mode 100755 index 0000000..520c997 --- /dev/null +++ b/RVO2/flow_22_01_25/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/RVO2/flow_22_01_25/show_dbdata.js b/RVO2/flow_22_01_25/show_dbdata.js new file mode 100755 index 0000000..d01eecd --- /dev/null +++ b/RVO2/flow_22_01_25/show_dbdata.js @@ -0,0 +1,241 @@ +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 = 7; +exports.output = 1; + +const { exec } = require('child_process'); + +exports.install = 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}) + }) + instance.on("5", _ => { + exec("sudo tail -n 25 monitor.txt" , (err, stdout, stderr) => { + if (err || stderr) instance.send(0,{err, stderr}); + else instance.send(0,stdout); + }) + }) + instance.on("6", _ => { + exec("sudo tail -n 25 err.txt" , (err, stdout, stderr) => { + if (err || stderr) instance.send(0,{err, stderr}); + else instance.send(0,stdout); + }) + }) +}; + + + +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/RVO2/flow_22_01_25/slack_filter.js b/RVO2/flow_22_01_25/slack_filter.js new file mode 100755 index 0000000..753c24a --- /dev/null +++ b/RVO2/flow_22_01_25/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 = `
+
+
+
@(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"] = []; + } + + instance.options.name = FLOW.GLOBALS.settings.rvo_name; + if (instance.options.name) { + instance.status('Running'); + running = true; + } else { + instance.status('Please run options again', 'red'); + running = false; + } + } catch (e) { + instance.error('Citysys connector: ' + e.message); + } + }; + + instance.on('options', instance.reconfigure); + setTimeout(instance.reconfigure, 10000); + + +}; diff --git a/RVO2/flow_22_01_25/thermometer.js b/RVO2/flow_22_01_25/thermometer.js new file mode 100755 index 0000000..fa015c6 --- /dev/null +++ b/RVO2/flow_22_01_25/thermometer.js @@ -0,0 +1,98 @@ +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 = 5;//minutes +let NUMBER_OF_FAILURES_TO_SEND_ERROR = 13; + +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) => { + + 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); + setTimeout(main, 20000); + }) +}; diff --git a/RVO2/flow_22_01_25/trigger.js b/RVO2/flow_22_01_25/trigger.js new file mode 100755 index 0000000..27545a8 --- /dev/null +++ b/RVO2/flow_22_01_25/trigger.js @@ -0,0 +1,79 @@ +exports.id = 'trigger'; +exports.title = 'Trigger'; +exports.group = 'Inputs'; +exports.color = '#F6BB42'; +exports.click = true; +exports.output = 1; +exports.version = '1.1.0'; +exports.author = 'Martin Smola'; +exports.icon = 'play'; + +exports.html = `
+
@(Data type (String by default))
+
@(Data)
+
Trigger 5s after initialization.
+
@(Useful when there's a need to run certain flow when the app restarts, etc.)
+
`; + +exports.readme = `# Trigger + +- Clicking on the component starts the chain +- Settings allows to set a data-type and a value`; + +exports.install = function(instance) { + + var value; + + instance.on('click', () => instance.send2(value)); + + instance.reconfigure = function() { + var options = instance.options; + value = null; + switch (options.datatype) { + case 'integer': + value = options.data.parseInt2('error'); + value = value === 'error' ? NaN : value; + break; + case 'float': + value = options.data.parseFloat2('error'); + value = value === 'error' ? NaN : value; + break; + case 'date': + options.data = options.data.toString(); + var num = options.data.parseInt('error'); + num === 'error' && (num = options.data.parseDate('error')); + num === 'error' && (num = null); + value = num ? new Date(num).toUTCString() : num; + break; + case 'object': + try { + value = (new Function('return ' + options.data))(); + } catch (e) { + instance.error(e); + } + break; + case 'boolean': + value = options.data.parseBoolean(); + break; + case 'buffer': + try { + value = U.createBuffer(options.data); + } catch (e) { + instance.error(e); + } + break; + case 'string': + default: + value = '' + (options.data || ''); + break; + } + }; + + instance.on('options', instance.reconfigure); + instance.reconfigure(); + + if (instance.options.restart) + setTimeout(function(){ + instance.send2(value); + }, 5000); +}; diff --git a/RVO2/flow_22_01_25/variables.txt b/RVO2/flow_22_01_25/variables.txt new file mode 100755 index 0000000..e69de29 diff --git a/RVO2/flow_22_01_25/virtualwirein.js b/RVO2/flow_22_01_25/virtualwirein.js new file mode 100755 index 0000000..38a4e42 --- /dev/null +++ b/RVO2/flow_22_01_25/virtualwirein.js @@ -0,0 +1,43 @@ +exports.id = 'virtualwirein'; +exports.title = 'Virtual wire in'; +exports.version = '1.0.0'; +exports.author = 'Martin Smola'; +exports.color = '#303E4D'; +exports.icon = 'sign-in'; +exports.input = false; +exports.output = 1; +exports.options = {}; +exports.readme = `# Virtual wire in + +When the wires between the components are mess it's time to use Virtual wire.`; + +exports.html = `
+
@(Wire name)
+
+`; + +exports.install = function(instance) { + + instance.custom.reconfigure = function(options){ + if (instance.options.wirename) { + instance.status(instance.options.wirename); + } else + instance.status('Not configured', 'red'); + }; + + ON('virtualwire', function(wirename, flowdata){ + if (instance.options.wirename && instance.options.wirename === wirename) + instance.send(flowdata); + }); + + instance.on('options', instance.custom.reconfigure); + instance.custom.reconfigure(); +}; diff --git a/RVO2/flow_22_01_25/virtualwireout.js b/RVO2/flow_22_01_25/virtualwireout.js new file mode 100755 index 0000000..94a1e4f --- /dev/null +++ b/RVO2/flow_22_01_25/virtualwireout.js @@ -0,0 +1,41 @@ +exports.id = 'virtualwireout'; +exports.title = 'Virtual wire out'; +exports.version = '1.0.0'; +exports.author = 'Martin Smola'; +exports.color = '#303E4D'; +exports.icon = 'sign-out'; +exports.input = true; +exports.options = {}; +exports.readme = `# Virtual wire out + +When the wires between the components are mess it's time to use Virtual wire.`; + +exports.html = `
+
@(Wire name)
+
+`; + +exports.install = function(instance) { + + instance.custom.reconfigure = function(){ + if (instance.options.wirename) { + instance.status(instance.options.wirename); + } else + instance.status('Not configured', 'red'); + }; + + instance.on('data', function(flowdata) { + EMIT('virtualwire', instance.options.wirename, flowdata); + }); + + instance.on('options', instance.custom.reconfigure); + instance.custom.reconfigure(); +}; diff --git a/RVO2/flow_22_01_25/wsmqttpublish.js b/RVO2/flow_22_01_25/wsmqttpublish.js new file mode 100755 index 0000000..b2a218d --- /dev/null +++ b/RVO2/flow_22_01_25/wsmqttpublish.js @@ -0,0 +1,477 @@ +exports.id = 'wsmqttpublish'; +exports.title = 'WS MQTT publish'; +exports.group = 'MQTT'; +exports.color = '#888600'; +exports.version = '1.0.2'; +exports.icon = 'sign-out'; +exports.input = 2; +exports.output = 3; +exports.options = { host: 'tb-stage.worksys.io', port: 1883, clientid: "", username: "" }; + +exports.html = `
+
+
+
Hostname or IP address (if not empty - setting will override db setting)
+
+
+
Port
+
+
+
+
+
@(Client id)
+
+
+
@(Username)
+
+
+
`; + + +exports.readme = ` +# WS MQTT Publish + +Version 1.0.3. + +Added: +- database collections, +- 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 = { + debug: 0, + rpcCall: 1, + services: 2 +} + +//CONFIG +let createTelemetryBackup = true; +let saveTelemetryOnError = true;//backup_on_failure overrides this value +//------------------------ + +let rollers; +if(createTelemetryBackup) rollers = require('streamroller'); + +const noSqlFileSizeLimit = 4194304;//use 5MB - 4194304 +let insertNoSqlCounter = 0; +let insertBackupNoSqlCounter = 0; +let processingData = false; + +let backup_on_failure = false;//== saveTelemetryOnError - create backup client 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; + +process.on('uncaughtException', function (err) { + + errLogger.error('uncaughtException:', err.message) + errLogger.error(err.stack); + + //TODO + //send to service + + //process.exit(1); +}) + +const nosql = NOSQL('tbdata'); +const nosqlBackup = NOSQL('/backup/tbdata'); + + +exports.install = function(instance) { + + var client; + var opts; + var clientReady = false; + + // wsmqtt status for notification purposes on projects.worksys.io database + let wsmqttName = null; + let sendWsStatusVar = null; + let wsmqtt_status = 'disconnected'; + + 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'; + } + + function sendWsStatus() + { + instance.send(SEND_TO.services, {[wsmqttName]: wsmqtt_status}); + } + + + function main() + { + if(!FLOW.dbLoaded) return; + + loadSettings(); + clearInterval(sendWsStatus); + sendWsStatusVar = setInterval(sendWsStatus, 180000); + } + + //set opts according to db settings + function loadSettings() + { + + if(instance.options.host !== "") + { + //override settings from database + var o = instance.options; + opts = { + host: o.host, + port: o.port, + clientId: o.clientid, + username: o.username, + rejectUnauthorized: false, + resubscribe: false + }; + + wsmqttName = getWsmqttName(o.host); + + console.log("wsmqttpublich -> loadSettings from instance.options", instance.options); + } + else + { + + const SETTINGS = FLOW.GLOBALS.settings; + backup_on_failure = SETTINGS.backup_on_failure; + saveTelemetryOnError = backup_on_failure; + + restore_from_backup = SETTINGS.restore_from_backup; + restore_backup_wait = SETTINGS.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; + + opts = { + host: mqtt_host, + port: mqtt_port, + keepalive: 10, + clientId: mqtt_clientid, + username: mqtt_username, + rejectUnauthorized: false, + resubscribe: false + }; + + wsmqttName = getWsmqttName(mqtt_host); + } + + connectToTbServer(); + } + + function connectToTbServer() + { + 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"); + monitor.info("MQTT client connected"); + + sendClientError = true; + clientReady = true; + wsmqtt_status = 'connected'; + }); + + client.on('reconnect', function() { + instance.status("Reconnecting", "yellow"); + clientReady = false; + }); + + client.on('message', function(topic, message) { + // message is type of buffer + message = message.toString(); + if (message[0] === '{') { + TRY(function() { + + message = JSON.parse(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}}); + } + + }, () => instance.debug('MQTT: Error parsing data', message)); + } + + instance.send(SEND_TO.rpcCall, {"topic":topic, "content":message }); + }); + + client.on('close', function() { + clientReady = false; + wsmqtt_status = 'disconnected'; + + instance.status("Disconnected", "red"); + instance.send(SEND_TO.debug, {"message":"Client CLOSE signal received !"}); + }); + + client.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; + wsmqtt_status = 'disconnected'; + }); + + } + + + instance.on("0", _ => { + main(); + }) + + + instance.on('1', function(data) { + + if(clientReady) + { + //do we have some data in backup file? if any, process data from database + if(saveTelemetryOnError) + { + //read telemetry data and send back to server + if(!processingData) processDataFromDatabase(); + } + + let stringifiedJson = JSON.stringify(data.data); + client.publish("v1/gateway/telemetry", stringifiedJson, {qos: 1}); + + //backup telemetry + if(createTelemetryBackup) + { + data.data.id = UID(); + nosqlBackup.insert(data.data); + + insertBackupNoSqlCounter++; + if(insertBackupNoSqlCounter > 150) + { + let options = {compress: true}; + let path = __dirname + "/../databases/backup/tbdata.nosql"; + var stream = new rollers.RollingFileStream(path, noSqlFileSizeLimit, 150, options); + stream.write(""); + stream.end(); + + insertBackupNoSqlCounter = 0; + } + } + + } + 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(saveTelemetryOnError) + { + //create new file from tbdata.nosql, if file size exceeds given limit, and clear tbdata.nosql + makeBackupFromDbFile(); + + //write to tb + data.data.id = UID(); + nosql.insert(data.data); + } + } + }); + + + instance.close = function(done) { + if(clientReady){ + client.end(); + clearInterval(sendWsStatusVar); + } + }; + + + function getDbBackupFileCounter(type) + { + var files = fs.readdirSync(__dirname + "/../databases"); + + let counter = 0; + for(var i = 0; i < files.length; i++) + { + + if(files[i] == "tbdata.nosql") continue; + + if(files[i].endsWith(".nosql")) + { + + let pos = files[i].indexOf("."); + if(pos > -1) + { + + let fileCounter = counter; + let firstDigit = files[i].slice(0, pos); + + fileCounter = parseInt(firstDigit); + if(isNaN(fileCounter)) fileCounter = 0; + //console.log("getDbBackupFileCounter digit:", files[i], firstDigit, fileCounter, isNaN(fileCounter), type); + + if(type == "max") + { + if(fileCounter > counter) + { + counter = fileCounter; + } + } + else if(type == "min") + { + if(counter == 0) counter = fileCounter; + + if(fileCounter < counter) + { + counter = fileCounter; + } + } + } + } + + } + + if(type == "max") counter++; + + return counter; + } + + const makeBackupFromDbFile = async () => { + + if(!saveTelemetryOnError) return; + + //to avoid large file: tbdata.nosql + + //init value is 0! + if(insertNoSqlCounter > 0) + { + --insertNoSqlCounter; + return; + } + + insertNoSqlCounter = 100; + + let source = __dirname + "/../databases/tbdata.nosql"; + + var stats = fs.statSync(source); + var fileSizeInBytes = stats.size; + + if(fileSizeInBytes > noSqlFileSizeLimit) + { + + let counter = 1; + counter = getDbBackupFileCounter("max"); + + let destination = __dirname + "/../databases/" + counter + "." + "tbdata.nosql"; + + //make backup file + fs.copyFileSync(source, destination); + //fs.renameSync(p, p + "." + counter); + + //clear tbdata.nosql + fs.writeFileSync(source, ""); + fs.truncateSync(source, 0); + + } + } + + const processDataFromDatabase = async () => { + + if(restore_from_backup <= 0) return; + + //calculate diff + const now = new Date(); + let currentTime = now.getTime(); + let diff = currentTime - lastRestoreTime; + + if( (diff / 1000) < restore_backup_wait) + { + //console.log("*********restore_backup_wait", diff, restore_backup_wait); + return; + } + + processingData = true; + + //get filename to process + let counter = getDbBackupFileCounter("min"); + + //we have some backup files + let dataBase = 'tbdata'; + + var nosql; + if(counter == 0) dataBase = 'tbdata'; + else dataBase = counter + "." + 'tbdata'; + + nosql = NOSQL(dataBase); + + //select all data - use limit restore_from_backup + let records = await promisifyBuilder(nosql.find().take(restore_from_backup)); + + for(let i = 0; i < records.length; i++) + { + if(clientReady) { + + let item = records[i]; + let id = item.id; + + if(id !== undefined) + { + //console.log("------------processDataFromDatabase - remove", id, dataBase, i); + + try { + + let message = JSON.parse(JSON.stringify(item)); + delete message.id; + + client.publish("v1/gateway/telemetry", JSON.stringify(message), {qos:1}); + + //remove from database + await promisifyBuilder(nosql.remove().where("id", id)); + + } catch(error) { + //process error + console.log("processDataFromDatabase", error); + } + + } + + } + else + { + processingData = false; + return; + } + } + + if(records.length > 0) + { + //clean backup file + if(counter > 0) nosql.clean(); + } + + //no data in db, remove + if(records.length == 0) + { + if(counter > 0) nosql.drop(); + } + + const d = new Date(); + lastRestoreTime = d.getTime(); + + processingData = false; + + } + + instance.on('options', main); + //instance.reconfigure(); +}; diff --git a/RVO2/monitor.txt b/RVO2/monitor.txt new file mode 100755 index 0000000..3f0c318 --- /dev/null +++ b/RVO2/monitor.txt @@ -0,0 +1,306 @@ +[2025-10-09T16:59:24.604] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-09T16:59:29.943] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-09T16:59:29.948] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-09T16:59:29.949] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-09T16:59:29.950] [INFO] monitorLogs - profile: { + 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: 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 +} +[2025-10-09T16:59:29.954] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T16:59:29.956] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 1 2025-10-10T04:42:00.955Z +[2025-10-09T16:59:29.957] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 1 2025-10-09T16:35:00.957Z +[2025-10-09T16:59:29.958] [INFO] monitorLogs - -->time_points final 1 [ + { start_time: '06:42', value: 0, name: 'dawn' }, + { start_time: '18:35', value: 1, name: 'dusk' } +] +[2025-10-09T16:59:29.959] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-10-09T16:59:29.960] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-09T16:59:29.960] [INFO] monitorLogs - profile: { + 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: 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 +} +[2025-10-09T16:59:29.963] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T16:59:29.964] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 2 2025-10-10T04:42:00.963Z +[2025-10-09T16:59:29.965] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 2 2025-10-09T16:35:00.965Z +[2025-10-09T16:59:29.965] [INFO] monitorLogs - -->time_points final 2 [ + { start_time: '06:42', value: 0, name: 'dawn' }, + { start_time: '18:35', value: 1, name: 'dusk' } +] +[2025-10-09T16:59:29.966] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-10-09T16:59:29.967] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-09T16:59:29.968] [INFO] monitorLogs - profile: { + 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: 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 +} +[2025-10-09T16:59:29.970] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T16:59:29.971] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 3 2025-10-10T04:42:00.970Z +[2025-10-09T16:59:29.971] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 3 2025-10-09T16:35:00.971Z +[2025-10-09T16:59:29.972] [INFO] monitorLogs - -->time_points final 3 [ + { start_time: '06:42', value: 0, name: 'dawn' }, + { start_time: '18:35', value: 1, name: 'dusk' } +] +[2025-10-09T16:59:29.973] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-10-09T16:59:29.976] [INFO] monitorLogs - tasks created: 392 +[2025-10-09T16:59:29.978] [INFO] monitorLogs - -->FLOW bol spustený PjLblDgRBO6WQqnxmkJ1M60Jv3ewZN4p5a89yKdY 2025-08-08 +[2025-10-09T16:59:34.984] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-09T18:35:01.268] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-09T18:35:01.571] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-10-09T18:35:01.874] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-10-09T19:12:22.983] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-09T19:12:28.317] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-09T19:12:28.322] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-09T19:12:28.323] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-09T19:12:28.324] [INFO] monitorLogs - profile: { + 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: 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 +} +[2025-10-09T19:12:28.328] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T19:12:28.329] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 1 2025-10-10T04:42:00.328Z +[2025-10-09T19:12:28.330] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 1 2025-10-10T16:35:00.330Z +[2025-10-09T19:12:28.331] [INFO] monitorLogs - -->time_points final 1 [ + { start_time: '06:42', value: 0, name: 'dawn' }, + { start_time: '18:35', value: 1, name: 'dusk' } +] +[2025-10-09T19:12:28.332] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-10-09T19:12:28.333] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-09T19:12:28.334] [INFO] monitorLogs - profile: { + 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: 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 +} +[2025-10-09T19:12:28.336] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T19:12:28.337] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 2 2025-10-10T04:42:00.337Z +[2025-10-09T19:12:28.338] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 2 2025-10-10T16:35:00.338Z +[2025-10-09T19:12:28.338] [INFO] monitorLogs - -->time_points final 2 [ + { start_time: '06:42', value: 0, name: 'dawn' }, + { start_time: '18:35', value: 1, name: 'dusk' } +] +[2025-10-09T19:12:28.339] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-10-09T19:12:28.340] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-09T19:12:28.341] [INFO] monitorLogs - profile: { + 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: 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 +} +[2025-10-09T19:12:28.343] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T19:12:28.344] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 3 2025-10-10T04:42:00.344Z +[2025-10-09T19:12:28.345] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 3 2025-10-10T16:35:00.344Z +[2025-10-09T19:12:28.345] [INFO] monitorLogs - -->time_points final 3 [ + { start_time: '06:42', value: 0, name: 'dawn' }, + { start_time: '18:35', value: 1, name: 'dusk' } +] +[2025-10-09T19:12:28.346] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-10-09T19:12:28.349] [INFO] monitorLogs - tasks created: 392 +[2025-10-09T19:12:28.351] [INFO] monitorLogs - -->FLOW bol spustený PjLblDgRBO6WQqnxmkJ1M60Jv3ewZN4p5a89yKdY 2025-08-08 +[2025-10-09T19:12:33.360] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-10T03:12:29.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-10 03:12:29 +[2025-10-10T06:42:00.422] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-10T06:42:00.727] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-10-10T06:42:01.031] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-10-10T18:35:00.659] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-10T18:35:00.962] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-10-10T18:35:01.265] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-10-11T03:12:30.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-11 03:12:30 +[2025-10-11T06:45:58.468] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-10-11T06:45:58.772] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-10-11T06:45:59.076] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-11T18:31:33.932] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-10-11T18:31:34.235] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-10-11T18:31:34.538] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-12T03:12:31.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-12 03:12:31 +[2025-10-12T06:47:26.658] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-12T06:47:26.962] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-10-12T06:47:27.267] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-10-12T18:29:33.794] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-12T18:29:34.097] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-10-12T18:29:34.400] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-10-13T03:12:31.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-13 03:12:31 +[2025-10-13T06:48:56.656] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-10-13T06:48:56.960] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-10-13T06:48:57.262] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-13T18:27:33.795] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-10-13T18:27:34.103] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-10-13T18:27:34.405] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-14T03:12:32.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-14 03:12:32 +[2025-10-14T06:50:27.321] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-14T06:50:27.625] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-10-14T06:50:27.928] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-10-14T18:25:35.130] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-14T18:25:35.436] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-10-14T18:25:35.739] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-10-15T03:12:33.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-15 03:12:33 +[2025-10-15T06:51:58.876] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-10-15T06:51:59.180] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-10-15T06:51:59.483] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-15T12:09:48.171] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-15T12:09:53.514] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-15T12:09:53.519] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-15T12:09:53.520] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-15T12:09:53.521] [INFO] monitorLogs - profile: { + 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: 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 +} +[2025-10-15T12:09:53.525] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-15T12:09:53.526] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 1 2025-10-16T04:51:00.525Z +[2025-10-15T12:09:53.527] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 1 2025-10-15T16:23:00.527Z +[2025-10-15T12:09:53.528] [INFO] monitorLogs - -->time_points final 1 [ + { start_time: '06:51', value: 0, name: 'dawn' }, + { start_time: '18:23', value: 1, name: 'dusk' } +] +[2025-10-15T12:09:53.529] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-10-15T12:09:53.530] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-15T12:09:53.531] [INFO] monitorLogs - profile: { + 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: 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 +} +[2025-10-15T12:09:53.533] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-15T12:09:53.534] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 2 2025-10-16T04:51:00.534Z +[2025-10-15T12:09:53.535] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 2 2025-10-15T16:23:00.535Z +[2025-10-15T12:09:53.535] [INFO] monitorLogs - -->time_points final 2 [ + { start_time: '06:51', value: 0, name: 'dawn' }, + { start_time: '18:23', value: 1, name: 'dusk' } +] +[2025-10-15T12:09:53.536] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-10-15T12:09:53.537] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-15T12:09:53.538] [INFO] monitorLogs - profile: { + 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: 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 +} +[2025-10-15T12:09:53.540] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-15T12:09:53.541] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 3 2025-10-16T04:51:00.540Z +[2025-10-15T12:09:53.541] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 3 2025-10-15T16:23:00.541Z +[2025-10-15T12:09:53.542] [INFO] monitorLogs - -->time_points final 3 [ + { start_time: '06:51', value: 0, name: 'dawn' }, + { start_time: '18:23', value: 1, name: 'dusk' } +] +[2025-10-15T12:09:53.543] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-10-15T12:09:53.546] [INFO] monitorLogs - tasks created: 392 +[2025-10-15T12:09:53.548] [INFO] monitorLogs - -->FLOW bol spustený PjLblDgRBO6WQqnxmkJ1M60Jv3ewZN4p5a89yKdY 2025-10-08 +[2025-10-15T12:09:58.571] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-15T18:23:00.660] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-15T18:23:00.971] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-10-15T18:23:01.274] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu diff --git a/RVO2/package-lock.json b/RVO2/package-lock.json new file mode 100755 index 0000000..3c5c1ba --- /dev/null +++ b/RVO2/package-lock.json @@ -0,0 +1,2139 @@ +{ + "name": "emptyproject", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "emptyproject", + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "bitwise": "^2.1.0", + "easy-crc": "0.0.2", + "jsmodbus": "^4.0.6", + "log4js": "^6.3.0", + "moment": "^2.30.1", + "mqtt": "^4.2.6", + "nodemailer": "^6.9.7", + "serialport": "^9.2.8", + "total.js": "^3.4.13" + } + }, + "node_modules/@serialport/binding-abstract": { + "version": "9.2.3", + "resolved": "https://registry.npmjs.org/@serialport/binding-abstract/-/binding-abstract-9.2.3.tgz", + "integrity": "sha512-cQs9tbIlG3P0IrOWyVirqlhWuJ7Ms2Zh9m2108z6Y5UW/iVj6wEOiW8EmK9QX9jmJXYllE7wgGgvVozP5oCj3w==", + "dependencies": { + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/binding-mock": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/binding-mock/-/binding-mock-9.2.4.tgz", + "integrity": "sha512-dpEhACCs44oQhh6ajJfJdvQdK38Vq0N4W6iD/gdplglDCK7qXRQCMUjJIeKdS/HSEiWkC3bwumUhUufdsOyT4g==", + "dependencies": { + "@serialport/binding-abstract": "9.2.3", + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/bindings": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/@serialport/bindings/-/bindings-9.2.8.tgz", + "integrity": "sha512-hSLxTe0tADZ3LMMGwvEJWOC/TaFQTyPeFalUCsJ1lSQ0k6bPF04JwrtB/C81GetmDBTNRY0GlD0SNtKCc7Dr5g==", + "hasInstallScript": true, + "dependencies": { + "@serialport/binding-abstract": "9.2.3", + "@serialport/parser-readline": "9.2.4", + "bindings": "^1.5.0", + "debug": "^4.3.2", + "nan": "^2.15.0", + "prebuild-install": "^7.0.0" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-byte-length": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-byte-length/-/parser-byte-length-9.2.4.tgz", + "integrity": "sha512-sQD/iw4ZMU3xW9PLi0/GlvU6Y623jGeWecbMkO7izUo/6P7gtfv1c9ikd5h0kwL8AoAOpQA1lxdHIKox+umBUg==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-cctalk": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-cctalk/-/parser-cctalk-9.2.4.tgz", + "integrity": "sha512-T4TU5vQMwmo9AB3gQLFDWbfJXlW5jd9guEsB/nqKjFHTv0FXPdZ7DQ2TpSp8RnHWxU3GX6kYTaDO20BKzc8GPQ==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-delimiter": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-delimiter/-/parser-delimiter-9.2.4.tgz", + "integrity": "sha512-4nvTAoYAgkxFiXrkI+3CA49Yd43CODjeszh89EK+I9c8wOZ+etZduRCzINYPiy26g7zO+GRAb9FoPCsY+sYcbQ==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-inter-byte-timeout": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-inter-byte-timeout/-/parser-inter-byte-timeout-9.2.4.tgz", + "integrity": "sha512-SOAdvr0oBQIOCXX198hiTlxs4JTKg9j5piapw5tNq52fwDOWdbYrFneT/wN04UTMKaDrJuEvXq6T4rv4j7nJ5A==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-readline": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-readline/-/parser-readline-9.2.4.tgz", + "integrity": "sha512-Z1/qrZTQUVhNSJP1hd9YfDvq0o7d87rNwAjjRKbVpa7Qi51tG5BnKt43IV3NFMyBlVcRe0rnIb3tJu57E0SOwg==", + "dependencies": { + "@serialport/parser-delimiter": "9.2.4" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-ready": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-ready/-/parser-ready-9.2.4.tgz", + "integrity": "sha512-Pyi94Itjl6qAURwIZr/gmZpMAyTmKXThm6vL5DoAWGQjcRHWB0gwv2TY2v7N+mQLJYUKU3cMnvnATXxHm7xjxw==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-regex": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-regex/-/parser-regex-9.2.4.tgz", + "integrity": "sha512-sI/cVvPOYz+Dbv4ZdnW16qAwvXiFf/1pGASQdbveRTlgJDdz7sRNlCBifzfTN2xljwvCTZYqiudKvDdC1TepRQ==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/stream": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/stream/-/stream-9.2.4.tgz", + "integrity": "sha512-bLye8Ub4vUFQGmkh8qEqehr7SE7EJs2yDs0h9jzuL5oKi+F34CFmWkEErO8GAOQ8YNn7p6b3GxUgs+0BrHHDZQ==", + "dependencies": { + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "node_modules/are-we-there-yet": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", + "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/base64-js": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", + "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==" + }, + "node_modules/bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "dependencies": { + "file-uri-to-path": "1.0.0" + } + }, + "node_modules/bitwise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/bitwise/-/bitwise-2.1.0.tgz", + "integrity": "sha512-XKgAhMXCh4H/3oNwAHAsAO0iC89s9cOiumgYwSHjSobGWxYjv62YhkL9QEdvGP151xypCtMlAfKK79GEcd2eRQ==" + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/bl/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/buffer": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz", + "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==", + "dependencies": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + }, + "node_modules/buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" + }, + "node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, + "node_modules/code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/commist": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/commist/-/commist-1.1.0.tgz", + "integrity": "sha512-rraC8NXWOEjhADbZe9QBNzLAN5Q3fsTPQtBV+fEVj6xKIgDgNiEVE6ZNfHpZOqfQ21YUzfVNUXLOEZquYvQPPg==", + "dependencies": { + "leven": "^2.1.0", + "minimist": "^1.1.0" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "node_modules/concat-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", + "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", + "engines": [ + "node >= 6.0" + ], + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.0.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/concat-stream/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" + }, + "node_modules/core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "node_modules/crc": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/crc/-/crc-3.4.0.tgz", + "integrity": "sha512-ycVC2+4/DLgXXq7QweYi2znhqDuZz6P5TQXnkQo8v15XY/5p/IWeZwsSE31Ifo8w15b8TWLsqhXOjXyilHuQxw==" + }, + "node_modules/date-format": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.11.tgz", + "integrity": "sha512-VS20KRyorrbMCQmpdl2hg5KaOUsda1RbnsJg461FfrcyCUg+pkd0b40BSW4niQyTheww4DBXQnS7HwSrKkipLw==", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" + }, + "node_modules/detect-libc": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz", + "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==", + "engines": { + "node": ">=8" + } + }, + "node_modules/duplexify": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.2.tgz", + "integrity": "sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw==", + "dependencies": { + "end-of-stream": "^1.4.1", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1", + "stream-shift": "^1.0.0" + } + }, + "node_modules/duplexify/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/easy-crc": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/easy-crc/-/easy-crc-0.0.2.tgz", + "integrity": "sha512-h6eqIdhJRe0p271/xZJbM/0klCi13mW5IB7ZEzEGH11yV4QXWAkD4yPErz0fXdhFrd6sZ4Q1k5Iky2kMsMNePw==" + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" + }, + "node_modules/flatted": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", + "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==" + }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, + "node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "node_modules/gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha512-14x4kjc6lkD3ltw589k0NrPD6cCNTD6CWoVUNpB85+DrtONoZn+Rug6xZU5RvSC4+TZPxA5AnBibQYAvZn41Hg==", + "dependencies": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "node_modules/github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==" + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" + }, + "node_modules/has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" + }, + "node_modules/help-me": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/help-me/-/help-me-3.0.0.tgz", + "integrity": "sha512-hx73jClhyk910sidBB7ERlnhMlFsJJIBqSVMFDwPN8o2v9nmp5KgLq1Xz1Bf1fCMMZ6mPrX159iG0VLy/fPMtQ==", + "dependencies": { + "glob": "^7.1.6", + "readable-stream": "^3.6.0" + } + }, + "node_modules/help-me/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, + "node_modules/is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==", + "dependencies": { + "number-is-nan": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "node_modules/js-sdsl": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz", + "integrity": "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/js-sdsl" + } + }, + "node_modules/jsmodbus": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/jsmodbus/-/jsmodbus-4.0.6.tgz", + "integrity": "sha512-gCmjoaERErK5Rn9Lu/BN07fY13MoWV7JKgGzrnkPlQPdPxYcwDhLtYcmpFFpZ4J9NPZZBSezi1UkLZO/DnNppA==", + "dependencies": { + "crc": "3.4.0", + "debug": "^3.1.0" + }, + "bin": { + "jsmodbus": "bin/jsmodbus.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/jsmodbus/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/leven": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", + "integrity": "sha1-wuep93IJTe6dNCAq6KzORoeHVYA=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/log4js": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.5.2.tgz", + "integrity": "sha512-DXtpNtt+KDOMT7RHUDIur/WsSA3rntlUh9Zg4XCdV42wUuMmbFkl38+LZ92Z5QvQA7mD5kAVkLiBSEH/tvUB8A==", + "dependencies": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "flatted": "^3.2.5", + "rfdc": "^1.3.0", + "streamroller": "^3.1.1" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" + }, + "node_modules/moment": { + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", + "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==", + "engines": { + "node": "*" + } + }, + "node_modules/mqtt": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/mqtt/-/mqtt-4.3.7.tgz", + "integrity": "sha512-ew3qwG/TJRorTz47eW46vZ5oBw5MEYbQZVaEji44j5lAUSQSqIEoul7Kua/BatBW0H0kKQcC9kwUHa1qzaWHSw==", + "dependencies": { + "commist": "^1.0.0", + "concat-stream": "^2.0.0", + "debug": "^4.1.1", + "duplexify": "^4.1.1", + "help-me": "^3.0.0", + "inherits": "^2.0.3", + "lru-cache": "^6.0.0", + "minimist": "^1.2.5", + "mqtt-packet": "^6.8.0", + "number-allocator": "^1.0.9", + "pump": "^3.0.0", + "readable-stream": "^3.6.0", + "reinterval": "^1.1.0", + "rfdc": "^1.3.0", + "split2": "^3.1.0", + "ws": "^7.5.5", + "xtend": "^4.0.2" + }, + "bin": { + "mqtt": "bin/mqtt.js", + "mqtt_pub": "bin/pub.js", + "mqtt_sub": "bin/sub.js" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/mqtt-packet": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/mqtt-packet/-/mqtt-packet-6.10.0.tgz", + "integrity": "sha512-ja8+mFKIHdB1Tpl6vac+sktqy3gA8t9Mduom1BA75cI+R9AHnZOiaBQwpGiWnaVJLDGRdNhQmFaAqd7tkKSMGA==", + "dependencies": { + "bl": "^4.0.2", + "debug": "^4.1.1", + "process-nextick-args": "^2.0.1" + } + }, + "node_modules/mqtt/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/nan": { + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.16.0.tgz", + "integrity": "sha512-UdAqHyFngu7TfQKsCBgAA6pWDkT8MAO7d0jyOecVhN5354xbLqdn8mV9Tat9gepAupm0bt2DbeaSC8vS52MuFA==" + }, + "node_modules/napi-build-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", + "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==" + }, + "node_modules/node-abi": { + "version": "3.22.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.22.0.tgz", + "integrity": "sha512-u4uAs/4Zzmp/jjsD9cyFYDXeISfUWaAVWshPmDZOFOv4Xl4SbzTXm53I04C2uRueYJ+0t5PEtLH/owbn2Npf/w==", + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/nodemailer": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.7.tgz", + "integrity": "sha512-rUtR77ksqex/eZRLmQ21LKVH5nAAsVicAtAYudK7JgwenEDZ0UIQ1adUGqErz7sMkWYxWTTU1aeP2Jga6WQyJw==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "dependencies": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "node_modules/number-allocator": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/number-allocator/-/number-allocator-1.0.14.tgz", + "integrity": "sha512-OrL44UTVAvkKdOdRQZIJpLkAdjXGTRda052sN4sO77bKEzYYqWKMBjQvrJFzqygI99gL6Z4u2xctPW1tB8ErvA==", + "dependencies": { + "debug": "^4.3.1", + "js-sdsl": "4.3.0" + } + }, + "node_modules/number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/prebuild-install": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.0.tgz", + "integrity": "sha512-CNcMgI1xBypOyGqjp3wOc8AAo1nMhZS3Cwd3iHIxOdAUbb+YxdNuM4Z5iIrZ8RLvOsf3F3bl7b7xGq6DjQoNYA==", + "dependencies": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^1.0.1", + "node-abi": "^3.3.0", + "npmlog": "^4.0.1", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + }, + "bin": { + "prebuild-install": "bin.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/reinterval": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reinterval/-/reinterval-1.1.0.tgz", + "integrity": "sha1-M2Hs+jymwYKDOA3Qu5VG85D17Oc=" + }, + "node_modules/rfdc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==" + }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/serialport": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/serialport/-/serialport-9.2.8.tgz", + "integrity": "sha512-FsWpMQgSJxi93JgWl5xM1f9/Z8IjRJuaUEoHqLf8FPBLw7gMhInuHOBhI2onQufWIYPGTz3H3oGcu1nCaK1EfA==", + "dependencies": { + "@serialport/binding-mock": "9.2.4", + "@serialport/bindings": "9.2.8", + "@serialport/parser-byte-length": "9.2.4", + "@serialport/parser-cctalk": "9.2.4", + "@serialport/parser-delimiter": "9.2.4", + "@serialport/parser-inter-byte-timeout": "9.2.4", + "@serialport/parser-readline": "9.2.4", + "@serialport/parser-ready": "9.2.4", + "@serialport/parser-regex": "9.2.4", + "@serialport/stream": "9.2.4", + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "node_modules/split2": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", + "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", + "dependencies": { + "readable-stream": "^3.0.0" + } + }, + "node_modules/split2/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==" + }, + "node_modules/streamroller": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.1.1.tgz", + "integrity": "sha512-iPhtd9unZ6zKdWgMeYGfSBuqCngyJy1B/GPi/lTpwGpa3bajuX30GjUVd0/Tn/Xhg0mr4DOSENozz9Y06qyonQ==", + "dependencies": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "fs-extra": "^10.1.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dependencies": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/tar-fs": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "dependencies": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tar-stream/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/total.js": { + "version": "3.4.13", + "resolved": "https://registry.npmjs.org/total.js/-/total.js-3.4.13.tgz", + "integrity": "sha512-lAH4gEixlPFbrE3xfKADAcHfO79IFq2wKa9GTsrgRzIR5MTg3mNH7+4IxvX1pK8faoYb/0oYSJ1YTsAa5hIFFQ==", + "bin": { + "total": "bin/totaljs", + "total.js": "bin/totaljs", + "totaljs": "bin/totaljs", + "totalpackage": "bin/tpm", + "tpm": "bin/tpm" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, + "node_modules/universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "node_modules/wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "node_modules/ws": { + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } + }, + "dependencies": { + "@serialport/binding-abstract": { + "version": "9.2.3", + "resolved": "https://registry.npmjs.org/@serialport/binding-abstract/-/binding-abstract-9.2.3.tgz", + "integrity": "sha512-cQs9tbIlG3P0IrOWyVirqlhWuJ7Ms2Zh9m2108z6Y5UW/iVj6wEOiW8EmK9QX9jmJXYllE7wgGgvVozP5oCj3w==", + "requires": { + "debug": "^4.3.2" + } + }, + "@serialport/binding-mock": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/binding-mock/-/binding-mock-9.2.4.tgz", + "integrity": "sha512-dpEhACCs44oQhh6ajJfJdvQdK38Vq0N4W6iD/gdplglDCK7qXRQCMUjJIeKdS/HSEiWkC3bwumUhUufdsOyT4g==", + "requires": { + "@serialport/binding-abstract": "9.2.3", + "debug": "^4.3.2" + } + }, + "@serialport/bindings": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/@serialport/bindings/-/bindings-9.2.8.tgz", + "integrity": "sha512-hSLxTe0tADZ3LMMGwvEJWOC/TaFQTyPeFalUCsJ1lSQ0k6bPF04JwrtB/C81GetmDBTNRY0GlD0SNtKCc7Dr5g==", + "requires": { + "@serialport/binding-abstract": "9.2.3", + "@serialport/parser-readline": "9.2.4", + "bindings": "^1.5.0", + "debug": "^4.3.2", + "nan": "^2.15.0", + "prebuild-install": "^7.0.0" + } + }, + "@serialport/parser-byte-length": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-byte-length/-/parser-byte-length-9.2.4.tgz", + "integrity": "sha512-sQD/iw4ZMU3xW9PLi0/GlvU6Y623jGeWecbMkO7izUo/6P7gtfv1c9ikd5h0kwL8AoAOpQA1lxdHIKox+umBUg==" + }, + "@serialport/parser-cctalk": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-cctalk/-/parser-cctalk-9.2.4.tgz", + "integrity": "sha512-T4TU5vQMwmo9AB3gQLFDWbfJXlW5jd9guEsB/nqKjFHTv0FXPdZ7DQ2TpSp8RnHWxU3GX6kYTaDO20BKzc8GPQ==" + }, + "@serialport/parser-delimiter": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-delimiter/-/parser-delimiter-9.2.4.tgz", + "integrity": "sha512-4nvTAoYAgkxFiXrkI+3CA49Yd43CODjeszh89EK+I9c8wOZ+etZduRCzINYPiy26g7zO+GRAb9FoPCsY+sYcbQ==" + }, + "@serialport/parser-inter-byte-timeout": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-inter-byte-timeout/-/parser-inter-byte-timeout-9.2.4.tgz", + "integrity": "sha512-SOAdvr0oBQIOCXX198hiTlxs4JTKg9j5piapw5tNq52fwDOWdbYrFneT/wN04UTMKaDrJuEvXq6T4rv4j7nJ5A==" + }, + "@serialport/parser-readline": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-readline/-/parser-readline-9.2.4.tgz", + "integrity": "sha512-Z1/qrZTQUVhNSJP1hd9YfDvq0o7d87rNwAjjRKbVpa7Qi51tG5BnKt43IV3NFMyBlVcRe0rnIb3tJu57E0SOwg==", + "requires": { + "@serialport/parser-delimiter": "9.2.4" + } + }, + "@serialport/parser-ready": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-ready/-/parser-ready-9.2.4.tgz", + "integrity": "sha512-Pyi94Itjl6qAURwIZr/gmZpMAyTmKXThm6vL5DoAWGQjcRHWB0gwv2TY2v7N+mQLJYUKU3cMnvnATXxHm7xjxw==" + }, + "@serialport/parser-regex": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-regex/-/parser-regex-9.2.4.tgz", + "integrity": "sha512-sI/cVvPOYz+Dbv4ZdnW16qAwvXiFf/1pGASQdbveRTlgJDdz7sRNlCBifzfTN2xljwvCTZYqiudKvDdC1TepRQ==" + }, + "@serialport/stream": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/stream/-/stream-9.2.4.tgz", + "integrity": "sha512-bLye8Ub4vUFQGmkh8qEqehr7SE7EJs2yDs0h9jzuL5oKi+F34CFmWkEErO8GAOQ8YNn7p6b3GxUgs+0BrHHDZQ==", + "requires": { + "debug": "^4.3.2" + } + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==" + }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "are-we-there-yet": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", + "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "base64-js": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", + "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==" + }, + "bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "requires": { + "file-uri-to-path": "1.0.0" + } + }, + "bitwise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/bitwise/-/bitwise-2.1.0.tgz", + "integrity": "sha512-XKgAhMXCh4H/3oNwAHAsAO0iC89s9cOiumgYwSHjSobGWxYjv62YhkL9QEdvGP151xypCtMlAfKK79GEcd2eRQ==" + }, + "bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "requires": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "buffer": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz", + "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==", + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" + }, + "chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==" + }, + "commist": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/commist/-/commist-1.1.0.tgz", + "integrity": "sha512-rraC8NXWOEjhADbZe9QBNzLAN5Q3fsTPQtBV+fEVj6xKIgDgNiEVE6ZNfHpZOqfQ21YUzfVNUXLOEZquYvQPPg==", + "requires": { + "leven": "^2.1.0", + "minimist": "^1.1.0" + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "concat-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", + "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.0.2", + "typedarray": "^0.0.6" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "crc": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/crc/-/crc-3.4.0.tgz", + "integrity": "sha512-ycVC2+4/DLgXXq7QweYi2znhqDuZz6P5TQXnkQo8v15XY/5p/IWeZwsSE31Ifo8w15b8TWLsqhXOjXyilHuQxw==" + }, + "date-format": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.11.tgz", + "integrity": "sha512-VS20KRyorrbMCQmpdl2hg5KaOUsda1RbnsJg461FfrcyCUg+pkd0b40BSW4niQyTheww4DBXQnS7HwSrKkipLw==" + }, + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "requires": { + "ms": "2.1.2" + } + }, + "decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "requires": { + "mimic-response": "^3.1.0" + } + }, + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==" + }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" + }, + "detect-libc": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz", + "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==" + }, + "duplexify": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.2.tgz", + "integrity": "sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw==", + "requires": { + "end-of-stream": "^1.4.1", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1", + "stream-shift": "^1.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "easy-crc": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/easy-crc/-/easy-crc-0.0.2.tgz", + "integrity": "sha512-h6eqIdhJRe0p271/xZJbM/0klCi13mW5IB7ZEzEGH11yV4QXWAkD4yPErz0fXdhFrd6sZ4Q1k5Iky2kMsMNePw==" + }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "requires": { + "once": "^1.4.0" + } + }, + "expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==" + }, + "file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" + }, + "flatted": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", + "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==" + }, + "fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, + "fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha512-14x4kjc6lkD3ltw589k0NrPD6cCNTD6CWoVUNpB85+DrtONoZn+Rug6xZU5RvSC4+TZPxA5AnBibQYAvZn41Hg==", + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==" + }, + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" + }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" + }, + "help-me": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/help-me/-/help-me-3.0.0.tgz", + "integrity": "sha512-hx73jClhyk910sidBB7ERlnhMlFsJJIBqSVMFDwPN8o2v9nmp5KgLq1Xz1Bf1fCMMZ6mPrX159iG0VLy/fPMtQ==", + "requires": { + "glob": "^7.1.6", + "readable-stream": "^3.6.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==", + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "js-sdsl": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz", + "integrity": "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==" + }, + "jsmodbus": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/jsmodbus/-/jsmodbus-4.0.6.tgz", + "integrity": "sha512-gCmjoaERErK5Rn9Lu/BN07fY13MoWV7JKgGzrnkPlQPdPxYcwDhLtYcmpFFpZ4J9NPZZBSezi1UkLZO/DnNppA==", + "requires": { + "crc": "3.4.0", + "debug": "^3.1.0" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "requires": { + "ms": "^2.1.1" + } + } + } + }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, + "leven": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", + "integrity": "sha1-wuep93IJTe6dNCAq6KzORoeHVYA=" + }, + "log4js": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.5.2.tgz", + "integrity": "sha512-DXtpNtt+KDOMT7RHUDIur/WsSA3rntlUh9Zg4XCdV42wUuMmbFkl38+LZ92Z5QvQA7mD5kAVkLiBSEH/tvUB8A==", + "requires": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "flatted": "^3.2.5", + "rfdc": "^1.3.0", + "streamroller": "^3.1.1" + } + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "requires": { + "yallist": "^4.0.0" + } + }, + "mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==" + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==" + }, + "mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" + }, + "moment": { + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", + "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==" + }, + "mqtt": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/mqtt/-/mqtt-4.3.7.tgz", + "integrity": "sha512-ew3qwG/TJRorTz47eW46vZ5oBw5MEYbQZVaEji44j5lAUSQSqIEoul7Kua/BatBW0H0kKQcC9kwUHa1qzaWHSw==", + "requires": { + "commist": "^1.0.0", + "concat-stream": "^2.0.0", + "debug": "^4.1.1", + "duplexify": "^4.1.1", + "help-me": "^3.0.0", + "inherits": "^2.0.3", + "lru-cache": "^6.0.0", + "minimist": "^1.2.5", + "mqtt-packet": "^6.8.0", + "number-allocator": "^1.0.9", + "pump": "^3.0.0", + "readable-stream": "^3.6.0", + "reinterval": "^1.1.0", + "rfdc": "^1.3.0", + "split2": "^3.1.0", + "ws": "^7.5.5", + "xtend": "^4.0.2" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "mqtt-packet": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/mqtt-packet/-/mqtt-packet-6.10.0.tgz", + "integrity": "sha512-ja8+mFKIHdB1Tpl6vac+sktqy3gA8t9Mduom1BA75cI+R9AHnZOiaBQwpGiWnaVJLDGRdNhQmFaAqd7tkKSMGA==", + "requires": { + "bl": "^4.0.2", + "debug": "^4.1.1", + "process-nextick-args": "^2.0.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "nan": { + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.16.0.tgz", + "integrity": "sha512-UdAqHyFngu7TfQKsCBgAA6pWDkT8MAO7d0jyOecVhN5354xbLqdn8mV9Tat9gepAupm0bt2DbeaSC8vS52MuFA==" + }, + "napi-build-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", + "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==" + }, + "node-abi": { + "version": "3.22.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.22.0.tgz", + "integrity": "sha512-u4uAs/4Zzmp/jjsD9cyFYDXeISfUWaAVWshPmDZOFOv4Xl4SbzTXm53I04C2uRueYJ+0t5PEtLH/owbn2Npf/w==", + "requires": { + "semver": "^7.3.5" + } + }, + "nodemailer": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.7.tgz", + "integrity": "sha512-rUtR77ksqex/eZRLmQ21LKVH5nAAsVicAtAYudK7JgwenEDZ0UIQ1adUGqErz7sMkWYxWTTU1aeP2Jga6WQyJw==" + }, + "npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "number-allocator": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/number-allocator/-/number-allocator-1.0.14.tgz", + "integrity": "sha512-OrL44UTVAvkKdOdRQZIJpLkAdjXGTRda052sN4sO77bKEzYYqWKMBjQvrJFzqygI99gL6Z4u2xctPW1tB8ErvA==", + "requires": { + "debug": "^4.3.1", + "js-sdsl": "4.3.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==" + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==" + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==" + }, + "prebuild-install": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.0.tgz", + "integrity": "sha512-CNcMgI1xBypOyGqjp3wOc8AAo1nMhZS3Cwd3iHIxOdAUbb+YxdNuM4Z5iIrZ8RLvOsf3F3bl7b7xGq6DjQoNYA==", + "requires": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^1.0.1", + "node-abi": "^3.3.0", + "npmlog": "^4.0.1", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + } + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + } + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "reinterval": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reinterval/-/reinterval-1.1.0.tgz", + "integrity": "sha1-M2Hs+jymwYKDOA3Qu5VG85D17Oc=" + }, + "rfdc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==" + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "requires": { + "lru-cache": "^6.0.0" + } + }, + "serialport": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/serialport/-/serialport-9.2.8.tgz", + "integrity": "sha512-FsWpMQgSJxi93JgWl5xM1f9/Z8IjRJuaUEoHqLf8FPBLw7gMhInuHOBhI2onQufWIYPGTz3H3oGcu1nCaK1EfA==", + "requires": { + "@serialport/binding-mock": "9.2.4", + "@serialport/bindings": "9.2.8", + "@serialport/parser-byte-length": "9.2.4", + "@serialport/parser-cctalk": "9.2.4", + "@serialport/parser-delimiter": "9.2.4", + "@serialport/parser-inter-byte-timeout": "9.2.4", + "@serialport/parser-readline": "9.2.4", + "@serialport/parser-ready": "9.2.4", + "@serialport/parser-regex": "9.2.4", + "@serialport/stream": "9.2.4", + "debug": "^4.3.2" + } + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==" + }, + "simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "requires": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "split2": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", + "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", + "requires": { + "readable-stream": "^3.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==" + }, + "streamroller": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.1.1.tgz", + "integrity": "sha512-iPhtd9unZ6zKdWgMeYGfSBuqCngyJy1B/GPi/lTpwGpa3bajuX30GjUVd0/Tn/Xhg0mr4DOSENozz9Y06qyonQ==", + "requires": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "fs-extra": "^10.1.0" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" + }, + "tar-fs": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "requires": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "requires": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "total.js": { + "version": "3.4.13", + "resolved": "https://registry.npmjs.org/total.js/-/total.js-3.4.13.tgz", + "integrity": "sha512-lAH4gEixlPFbrE3xfKADAcHfO79IFq2wKa9GTsrgRzIR5MTg3mNH7+4IxvX1pK8faoYb/0oYSJ1YTsAa5hIFFQ==" + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, + "universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==" + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "requires": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "ws": { + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "requires": {} + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } + } +} diff --git a/RVO2/package.json b/RVO2/package.json new file mode 100755 index 0000000..7f7c795 --- /dev/null +++ b/RVO2/package.json @@ -0,0 +1,30 @@ +{ + "name": "emptyproject", + "description": "Total.js empty project.", + "version": "1.0.0", + "main": "debug.js", + "dependencies": { + "bitwise": "^2.1.0", + "easy-crc": "0.0.2", + "jsmodbus": "^4.0.6", + "log4js": "^6.3.0", + "moment": "^2.30.1", + "mqtt": "^4.2.6", + "nodemailer": "^6.9.7", + "serialport": "^9.2.8", + "total.js": "^3.4.13" + }, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "https://github.com/totaljs/emptyproject-flow" + }, + "keywords": [ + "empty", + "project" + ], + "author": "Peter Širka", + "license": "MIT" +} diff --git a/RVO2/release.js b/RVO2/release.js new file mode 100755 index 0000000..02d52ff --- /dev/null +++ b/RVO2/release.js @@ -0,0 +1,15 @@ +// =================================================== +// FOR PRODUCTION +// Total.js - framework for Node.js platform +// https://www.totaljs.com +// =================================================== + +const options = {'ip':'0.0.0.0', 'port':12345}; + +// options.ip = '127.0.0.1'; +// options.port = parseInt(process.argv[2]); +// options.config = { name: 'Total.js' }; +// options.sleep = 3000; + +require('total.js').http('release', options); +// require('total.js').cluster.http(5, 'release', options); diff --git a/RVO2/release.js.json b/RVO2/release.js.json new file mode 100755 index 0000000..baeca2b --- /dev/null +++ b/RVO2/release.js.json @@ -0,0 +1,34 @@ +{ + "pid": 389, + "stats": [ + { + "id": null, + "version": { + "node": "v14.18.1", + "total": "3.4.13", + "app": "1.0.0" + }, + "pid": 389, + "thread": "", + "mode": "release", + "overload": 0, + "date": "2025-10-16T00:22:44.269Z", + "memory": 25.94, + "rm": 0, + "fm": 0, + "wm": 0, + "mm": 0, + "om": 6, + "em": 1, + "dbrm": 0, + "dbwm": 0, + "usage": 0, + "requests": 7, + "pending": 0, + "errors": 0, + "timeouts": 0, + "uptime": 854, + "online": 0 + } + ] +} \ No newline at end of file diff --git a/RVO2/report_data.log b/RVO2/report_data.log new file mode 100755 index 0000000..2b65e3b --- /dev/null +++ b/RVO2/report_data.log @@ -0,0 +1,196 @@ +{ + "name": "rvo_senica_2_10.0.0.130", + "time": "2025-10-15T11:09:59.182Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_2_10.0.0.130", + "time": "2025-10-15T12:09:59.177Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_2_10.0.0.130", + "time": "2025-10-15T13:09:59.177Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_2_10.0.0.130", + "time": "2025-10-15T14:09:59.177Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_2_10.0.0.130", + "time": "2025-10-15T15:09:59.177Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_2_10.0.0.130", + "time": "2025-10-15T16:09:59.178Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_2_10.0.0.130", + "time": "2025-10-15T17:23:01.275Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_2_10.0.0.130", + "time": "2025-10-15T18:23:01.275Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_2_10.0.0.130", + "time": "2025-10-15T19:23:01.275Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_2_10.0.0.130", + "time": "2025-10-15T20:23:01.276Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_2_10.0.0.130", + "time": "2025-10-15T21:23:01.276Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_2_10.0.0.130", + "time": "2025-10-15T22:23:01.276Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_2_10.0.0.130", + "time": "2025-10-15T23:23:01.277Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +} \ No newline at end of file From ad6a1663adfc4686488b37b138864235d550a82c Mon Sep 17 00:00:00 2001 From: Jakub Klena Date: Thu, 16 Oct 2025 02:23:14 +0200 Subject: [PATCH 02/30] Backup senica-RVO3 on 16.10.2025 --- RVO3/addSwitch.py | 36 + RVO3/cloud_topic.py | 76 + RVO3/config | 12 + RVO3/createNode.py | 43 + RVO3/databases/accelerometer_db.js | 3055 +++++++ RVO3/databases/modbus_config.js | 114 + RVO3/databases/nodes.table | 1 + .../nodes_original/nodes_original.table | 1 + RVO3/databases/notifications.table | 41 + RVO3/databases/pins.table | 14 + RVO3/databases/relays.table | 5 + RVO3/databases/settings.table | 2 + RVO3/databases/tbdata.nosql | 4 + RVO3/databases/tbdatacloud.nosql | 3 + RVO3/databases/total_energy.js | 38 + RVO3/debug.js | 16 + RVO3/err.txt | 33 + RVO3/flow/cloudmqttconnect.js | 357 + RVO3/flow/cmd_manager.js | 3071 +++++++ RVO3/flow/code.js | 90 + RVO3/flow/comment.js | 11 + RVO3/flow/count.js | 60 + RVO3/flow/db_connector.js | 286 + RVO3/flow/db_init.js | 113 + RVO3/flow/debug.js | 100 + RVO3/flow/designer.json | 3102 +++++++ RVO3/flow/dido_controller.js | 1486 +++ RVO3/flow/helper/DataToTbHandler.js | 187 + RVO3/flow/helper/ErrorToServiceHandler.js | 91 + RVO3/flow/helper/db_helper.js | 44 + RVO3/flow/helper/logger.js | 30 + RVO3/flow/helper/md5.js | 5 + RVO3/flow/helper/notification_reporter.js | 121 + RVO3/flow/helper/register.js | 144 + RVO3/flow/helper/serialport_helper.js | 99 + RVO3/flow/helper/suncalc.js | 317 + RVO3/flow/helper/utils.js | 161 + RVO3/flow/httprequest.js | 137 + RVO3/flow/httpresponse.js | 76 + RVO3/flow/httproute.js | 326 + RVO3/flow/infosender.js | 81 + RVO3/flow/modbus_reader.js | 346 + RVO3/flow/monitorconsumption.js | 156 + RVO3/flow/monitordisk.js | 96 + RVO3/flow/monitormemory.js | 87 + RVO3/flow/nodesdb_changecheck.js | 77 + RVO3/flow/show_dbdata.js | 243 + RVO3/flow/slack_filter.js | 188 + RVO3/flow/thermometer.js | 99 + RVO3/flow/trigger.js | 79 + RVO3/flow/variables.txt | 0 RVO3/flow/virtualwirein.js | 43 + RVO3/flow/virtualwireout.js | 41 + RVO3/flow/wsmqttpublish.js | 448 + RVO3/flow_20_01_25/cloudmqttconnect.js | 374 + RVO3/flow_20_01_25/cmd_manager.js | 2988 ++++++ RVO3/flow_20_01_25/code.js | 90 + RVO3/flow_20_01_25/comment.js | 11 + RVO3/flow_20_01_25/db_connector.js | 286 + RVO3/flow_20_01_25/db_init.js | 106 + RVO3/flow_20_01_25/debug.js | 100 + RVO3/flow_20_01_25/designer.json | 2846 ++++++ RVO3/flow_20_01_25/dido_controller.js | 1524 ++++ RVO3/flow_20_01_25/helper/DataToTbHandler.js | 166 + .../helper/ErrorToServiceHandler.js | 126 + RVO3/flow_20_01_25/helper/db_helper.js | 44 + RVO3/flow_20_01_25/helper/logger.js | 30 + RVO3/flow_20_01_25/helper/md5.js | 5 + .../helper/notification_reporter.js | 131 + RVO3/flow_20_01_25/helper/register.js | 144 + .../flow_20_01_25/helper/serialport_helper.js | 100 + RVO3/flow_20_01_25/helper/suncalc.js | 317 + RVO3/flow_20_01_25/helper/utils.js | 124 + RVO3/flow_20_01_25/httprequest.js | 137 + RVO3/flow_20_01_25/httpresponse.js | 76 + RVO3/flow_20_01_25/httproute.js | 326 + RVO3/flow_20_01_25/infosender.js | 101 + RVO3/flow_20_01_25/modbus_reader.js | 367 + RVO3/flow_20_01_25/monitorconsumption.js | 156 + RVO3/flow_20_01_25/monitordisk.js | 96 + RVO3/flow_20_01_25/monitormemory.js | 87 + RVO3/flow_20_01_25/nodesdb_changecheck.js | 70 + RVO3/flow_20_01_25/show_dbdata.js | 241 + RVO3/flow_20_01_25/slack_filter.js | 187 + RVO3/flow_20_01_25/thermometer.js | 98 + RVO3/flow_20_01_25/trigger.js | 79 + RVO3/flow_20_01_25/variables.txt | 0 RVO3/flow_20_01_25/virtualwirein.js | 43 + RVO3/flow_20_01_25/virtualwireout.js | 41 + RVO3/flow_20_01_25/wsmqttpublish.js | 477 + RVO3/monitor.txt | 8002 +++++++++++++++++ RVO3/package-lock.json | 2139 +++++ RVO3/package.json | 30 + RVO3/release.js | 15 + RVO3/release.js.json | 34 + RVO3/report_data.log | 211 + 96 files changed, 38417 insertions(+) create mode 100755 RVO3/addSwitch.py create mode 100755 RVO3/cloud_topic.py create mode 100755 RVO3/config create mode 100755 RVO3/createNode.py create mode 100755 RVO3/databases/accelerometer_db.js create mode 100755 RVO3/databases/modbus_config.js create mode 100755 RVO3/databases/nodes.table create mode 100755 RVO3/databases/nodes_original/nodes_original.table create mode 100755 RVO3/databases/notifications.table create mode 100755 RVO3/databases/pins.table create mode 100755 RVO3/databases/relays.table create mode 100755 RVO3/databases/settings.table create mode 100755 RVO3/databases/tbdata.nosql create mode 100755 RVO3/databases/tbdatacloud.nosql create mode 100755 RVO3/databases/total_energy.js create mode 100755 RVO3/debug.js create mode 100755 RVO3/err.txt create mode 100755 RVO3/flow/cloudmqttconnect.js create mode 100755 RVO3/flow/cmd_manager.js create mode 100755 RVO3/flow/code.js create mode 100755 RVO3/flow/comment.js create mode 100755 RVO3/flow/count.js create mode 100755 RVO3/flow/db_connector.js create mode 100755 RVO3/flow/db_init.js create mode 100755 RVO3/flow/debug.js create mode 100755 RVO3/flow/designer.json create mode 100755 RVO3/flow/dido_controller.js create mode 100755 RVO3/flow/helper/DataToTbHandler.js create mode 100755 RVO3/flow/helper/ErrorToServiceHandler.js create mode 100755 RVO3/flow/helper/db_helper.js create mode 100755 RVO3/flow/helper/logger.js create mode 100755 RVO3/flow/helper/md5.js create mode 100755 RVO3/flow/helper/notification_reporter.js create mode 100755 RVO3/flow/helper/register.js create mode 100755 RVO3/flow/helper/serialport_helper.js create mode 100755 RVO3/flow/helper/suncalc.js create mode 100755 RVO3/flow/helper/utils.js create mode 100755 RVO3/flow/httprequest.js create mode 100755 RVO3/flow/httpresponse.js create mode 100755 RVO3/flow/httproute.js create mode 100755 RVO3/flow/infosender.js create mode 100755 RVO3/flow/modbus_reader.js create mode 100755 RVO3/flow/monitorconsumption.js create mode 100755 RVO3/flow/monitordisk.js create mode 100755 RVO3/flow/monitormemory.js create mode 100755 RVO3/flow/nodesdb_changecheck.js create mode 100755 RVO3/flow/show_dbdata.js create mode 100755 RVO3/flow/slack_filter.js create mode 100755 RVO3/flow/thermometer.js create mode 100755 RVO3/flow/trigger.js create mode 100755 RVO3/flow/variables.txt create mode 100755 RVO3/flow/virtualwirein.js create mode 100755 RVO3/flow/virtualwireout.js create mode 100755 RVO3/flow/wsmqttpublish.js create mode 100755 RVO3/flow_20_01_25/cloudmqttconnect.js create mode 100755 RVO3/flow_20_01_25/cmd_manager.js create mode 100755 RVO3/flow_20_01_25/code.js create mode 100755 RVO3/flow_20_01_25/comment.js create mode 100755 RVO3/flow_20_01_25/db_connector.js create mode 100755 RVO3/flow_20_01_25/db_init.js create mode 100755 RVO3/flow_20_01_25/debug.js create mode 100755 RVO3/flow_20_01_25/designer.json create mode 100755 RVO3/flow_20_01_25/dido_controller.js create mode 100755 RVO3/flow_20_01_25/helper/DataToTbHandler.js create mode 100755 RVO3/flow_20_01_25/helper/ErrorToServiceHandler.js create mode 100755 RVO3/flow_20_01_25/helper/db_helper.js create mode 100755 RVO3/flow_20_01_25/helper/logger.js create mode 100755 RVO3/flow_20_01_25/helper/md5.js create mode 100755 RVO3/flow_20_01_25/helper/notification_reporter.js create mode 100755 RVO3/flow_20_01_25/helper/register.js create mode 100755 RVO3/flow_20_01_25/helper/serialport_helper.js create mode 100755 RVO3/flow_20_01_25/helper/suncalc.js create mode 100755 RVO3/flow_20_01_25/helper/utils.js create mode 100755 RVO3/flow_20_01_25/httprequest.js create mode 100755 RVO3/flow_20_01_25/httpresponse.js create mode 100755 RVO3/flow_20_01_25/httproute.js create mode 100755 RVO3/flow_20_01_25/infosender.js create mode 100755 RVO3/flow_20_01_25/modbus_reader.js create mode 100755 RVO3/flow_20_01_25/monitorconsumption.js create mode 100755 RVO3/flow_20_01_25/monitordisk.js create mode 100755 RVO3/flow_20_01_25/monitormemory.js create mode 100755 RVO3/flow_20_01_25/nodesdb_changecheck.js create mode 100755 RVO3/flow_20_01_25/show_dbdata.js create mode 100755 RVO3/flow_20_01_25/slack_filter.js create mode 100755 RVO3/flow_20_01_25/thermometer.js create mode 100755 RVO3/flow_20_01_25/trigger.js create mode 100755 RVO3/flow_20_01_25/variables.txt create mode 100755 RVO3/flow_20_01_25/virtualwirein.js create mode 100755 RVO3/flow_20_01_25/virtualwireout.js create mode 100755 RVO3/flow_20_01_25/wsmqttpublish.js create mode 100755 RVO3/monitor.txt create mode 100755 RVO3/package-lock.json create mode 100755 RVO3/package.json create mode 100755 RVO3/release.js create mode 100755 RVO3/release.js.json create mode 100755 RVO3/report_data.log diff --git a/RVO3/addSwitch.py b/RVO3/addSwitch.py new file mode 100755 index 0000000..c35e96b --- /dev/null +++ b/RVO3/addSwitch.py @@ -0,0 +1,36 @@ +import os + +def process_set_file(): + """ + Checks if /root/flowserver exists, reads set.txt, and modifies the second line. + """ + default_folder = "/root/flowserver" if os.path.exists("/root/flowserver") else "/home/unipi/flowserver" + flag = 1 if default_folder == "/root/flowserver" else 0 + + try: + with open("/home/unipi/flowserver/databases/settings.table", "r") as f: + lines = f.readlines() + + if len(lines) >= 2: + lines[0] = lines[0].rstrip('\n') + "|main_switch:boolean\n" + second_line = lines[1].strip() # remove trailing newline + last_pipe_index = second_line.rfind("|") + + if last_pipe_index != -1: + modified_line = second_line[:last_pipe_index + 1] + str(flag) + "|" + second_line[last_pipe_index + 1:] + lines[1] = modified_line + else: + print("Warning: No '|' character found in the second line of set.txt") + + with open("/home/unipi/flowserver/databases/settings.table", "w") as f: + f.writelines(lines) + else: + print("Warning: settings.table has less than two lines.") + + except FileNotFoundError: + print("Error: settings.table not found.") + except Exception as e: + print(e) + +# if __name__ == "__main__": +process_set_file() diff --git a/RVO3/cloud_topic.py b/RVO3/cloud_topic.py new file mode 100755 index 0000000..77c31f1 --- /dev/null +++ b/RVO3/cloud_topic.py @@ -0,0 +1,76 @@ +# import os +# +# def modify_file(file_path): +# """ +# Modifies the given file by: +# 1. Appending "|cloud_topic" to the first line. +# 2. Inserting the text from the third "." to the first "|" on the second line after the last "|" character. +# +# Args: +# file_path (str): The path to the file to be modified. +# """ +# +# with open(file_path, 'r+') as f: +# lines = f.readlines() +# +# # Modify the first line +# lines[0] += "|cloud_topic:string" +# +# # Modify the second line +# second_line = lines[1].strip() # Remove leading/trailing whitespace +# first_pipe_index = second_line.find('|') +# third_dot_index = second_line.find('.', second_line.find('.', second_line.find('.') + 1) + 1) +# text_to_insert = second_line[third_dot_index:first_pipe_index] +# +# last_pipe_index = second_line.rfind('|') +# lines[1] = second_line[:last_pipe_index + 1] + text_to_insert + "|" + second_line[last_pipe_index + 1:] +# +# print(first_pipe_index, third_dot_index, text_to_insert, last_pipe_index) +# # Write the modified lines back to the file +# # f.seek(0) +# # f.writelines(lines) +# # f.truncate() +# +# # Example usage: +# file_path = "settings.table" # Replace with the actual file path +# modify_file(file_path) +# + + +def modify_file(file_path): + """ + Modifies the given file by: + 1. Appending "|cloud_topic" to the first line. + 2. Inserting the text between the third "." and the second "|" on the second line after the last "|" character. + + Args: + file_path (str): The path to the file to be modified. + """ + + with open(file_path, 'r+') as f: + lines = f.readlines() + + first_line = lines[0].strip() + first_line += "|cloud_topic:string\n" + # Modify the first line + lines[0] = first_line + + # Modify the second line + second_line = lines[1].strip() # Remove leading/trailing whitespace + first_pipe_index = second_line.find('|') + second_pipe_index = second_line.find('|', first_pipe_index + 1) + third_dot_index = second_line.find('.', second_line.find('.', second_line.find('.') + 1) + 1) + text_to_insert = "u" + second_line[third_dot_index+1:second_pipe_index] + + last_pipe_index = second_line.rfind('|') + lines[1] = second_line[:last_pipe_index + 1] + text_to_insert + "|" + second_line[last_pipe_index + 1:] + + print(first_pipe_index, third_dot_index, text_to_insert, last_pipe_index) + # Write the modified lines back to the file + f.seek(0) + f.writelines(lines) + f.truncate() + +# Example usage: +file_path = "/home/unipi/flowserver/databases/settings.table" # Replace with the actual file path +modify_file(file_path) diff --git a/RVO3/config b/RVO3/config new file mode 100755 index 0000000..cd0a8a9 --- /dev/null +++ b/RVO3/config @@ -0,0 +1,12 @@ +name : Total.js Flow +default_timezone : Europe/Bratislava + +// Packages settings +package#flow (Object) : { url: '/' } + + +table.relays : line:number|tbname:string|contactor:number|profile:string +table.nodes : node:number|pole_number:string|node_type:string|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|project_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|cloud_topic:string|has_main_switch:boolean|daily_report:boolean|send_changed_node_numbers:boolean +table.pins : pin:string|type:string|line:number +table.notifications : key:string|weight:string|sk:string|en:string diff --git a/RVO3/createNode.py b/RVO3/createNode.py new file mode 100755 index 0000000..a8cea91 --- /dev/null +++ b/RVO3/createNode.py @@ -0,0 +1,43 @@ +print("zaciname") +import re, json + +search_str = '|' +final = [] +counter = 1 +with open("/home/unipi/flowserver/databases/nodes.table", 'r') as file: +# with open("/home/rasta5man/dev/oms/flowserver/databases/nodes.table", 'r') as file: + # Read each line in the file + for line in file: + # Print each line + line = line.strip() + print(line) + if counter != 1: + i = [m.start() for m in re.finditer(re.escape(search_str), line)] + node = line[ i[0] + 1 : i[1] ] + tbname = line[ i[3] + 1 : i[4] ] + final.append({node:tbname}) + counter += 1 +print(json.dumps(final)) +f = open("/home/unipi/flowserver/databases/nodes_original/nodes_original.table", "w") +f.write(json.dumps(final)) +f.close() + + +# +# # ``d`` has to be replaced with a different character +# old_character = "'" +# +# # ``t`` will replace ``d` +# new_character = '"' +# resultant_string = 0; +# with open("/home/unipi/flowserver/databases/nodes_original/nodes_original.table", 'r') as file: +# for line in file: +# resultant_string = re.sub("'", '"', line) +# +# resultant_string = re.sub(" ", "", resultant_string) +# print(resultant_string) +# +# f = open("/home/unipi/flowserver/databases/nodes_original/nodes_original.table", "w") +# f.write(str(resultant_string)) +# f.close() +# diff --git a/RVO3/databases/accelerometer_db.js b/RVO3/databases/accelerometer_db.js new file mode 100755 index 0000000..fdfc7fd --- /dev/null +++ b/RVO3/databases/accelerometer_db.js @@ -0,0 +1,3055 @@ +let naklony = { + "3993": { "label": "1/3A", "naklon": 0 }, + "3989": { "label": "1/3B", "naklon": 15 }, + "3976": { "label": "1/1", "naklon": 0 }, + "4181": { "label": "1/2", "naklon": 0 }, + "4376": { "label": "1/4", "naklon": 15 }, + "3868": { "label": "1/5", "naklon": 15 }, + "3728": { "label": "1/6", "naklon": 15 }, + "3730": { "label": "1/7", "naklon": 0 }, + "4374": { "label": "1/8", "naklon": 0 }, + "3718": { "label": "1/9", "naklon": 15 }, + "4375": { "label": "1/10", "naklon": 15 }, + "4172": { "label": "1/11", "naklon": 15 }, + "4176": { "label": "1/12", "naklon": 15 }, + "3800": { "label": "2/1", "naklon": 5 }, + "3823": { "label": "2/2", "naklon": 5 }, + "3905": { "label": "2/3", "naklon": 5 }, + "3803": { "label": "2/4", "naklon": 5 }, + "3817": { "label": "2/5", "naklon": 5 }, + "3818": { "label": "2/6", "naklon": 5 }, + "3811": { "label": "2/7", "naklon": 5 }, + "3915": { "label": "2/8", "naklon": 5 }, + "3843": { "label": "2/9", "naklon": 10 }, + "3827": { "label": "2/10", "naklon": 10 }, + "4220": { "label": "2/11", "naklon": 10 }, + "3826": { "label": "2/12", "naklon": 10 }, + "3834": { "label": "2/13", "naklon": 10 }, + "3838": { "label": "2/14", "naklon": 10 }, + "2823": { "label": "2/15", "naklon": 10 }, + "3750": { "label": "2/16", "naklon": 10 }, + "3378": { "label": "2/17", "naklon": 0 }, + "3376": { "label": "2/18", "naklon": 0 }, + "3379": { "label": "2/19", "naklon": 0 }, + "3285": { "label": "2/20", "naklon": 0 }, + "3382": { "label": "2/21", "naklon": 0 }, + "3383": { "label": "2/22", "naklon": 0 }, + "3375": { "label": "2/24", "naklon": 0 }, + "3381": { "label": "2/25", "naklon": 0 }, + "3380": { "label": "2/26", "naklon": 0 }, + "3828": { "label": "2/27", "naklon": 10 }, + "3377": { "label": "2/28", "naklon": 0 }, + "3591": { "label": "7/1", "naklon": 0 }, + "3587": { "label": "7/2", "naklon": 0 }, + "3468": { "label": "7/3", "naklon": 0 }, + "3466": { "label": "7/4", "naklon": 0 }, + "3474": { "label": "7/5", "naklon": 0 }, + "3481": { "label": "7/6", "naklon": 0 }, + "3589": { "label": "7/7", "naklon": 0 }, + "3472": { "label": "7/8", "naklon": 0 }, + "3473": { "label": "7/9", "naklon": 0 }, + "3584": { "label": "7/10", "naklon": 0 }, + "3571": { "label": "7/11", "naklon": 0 }, + "3476": { "label": "7/12", "naklon": 0 }, + "3590": { "label": "7/13", "naklon": 0 }, + "3478": { "label": "7/14", "naklon": 0 }, + "3471": { "label": "7/15", "naklon": 0 }, + "3467": { "label": "7/16", "naklon": 0 }, + "3479": { "label": "7/17", "naklon": 0 }, + "3480": { "label": "7/18", "naklon": 0 }, + "3477": { "label": "7/19", "naklon": 0 }, + "3362": { "label": "12/1", "naklon": 0 }, + "3355": { "label": "12/2", "naklon": 0 }, + "3356": { "label": "12/3", "naklon": 0 }, + "3349": { "label": "12/4", "naklon": 0 }, + "3357": { "label": "12/5", "naklon": 0 }, + "3350": { "label": "12/6", "naklon": 0 }, + "3353": { "label": "12/7", "naklon": 0 }, + "3539": { "label": "12/8", "naklon": 0 }, + "3050": { "label": "12/9", "naklon": 0 }, + "3361": { "label": "12/10", "naklon": 0 }, + "3360": { "label": "12/11", "naklon": 0 }, + "3358": { "label": "12/12", "naklon": 0 }, + "3541": { "label": "12/13", "naklon": 0 }, + "3551": { "label": "12/14", "naklon": 0 }, + "3514": { "label": "12/15", "naklon": 0 }, + "3547": { "label": "12/16", "naklon": 0 }, + "3562": { "label": "12/17", "naklon": 0 }, + "3525": { "label": "12/18", "naklon": 0 }, + "3558": { "label": "12/19", "naklon": 0 }, + "3511": { "label": "12/20", "naklon": 0 }, + "3058": { "label": "12/21", "naklon": 0 }, + "3062": { "label": "12/22", "naklon": 0 }, + "3070": { "label": "12/23", "naklon": 0 }, + "3447": { "label": "12/24", "naklon": 0 }, + "3056": { "label": "12/25", "naklon": 0 }, + "3057": { "label": "12/26", "naklon": 0 }, + "3071": { "label": "12/27", "naklon": 0 }, + "3061": { "label": "12/28", "naklon": 0 }, + "3069": { "label": "12/29", "naklon": 0 }, + "3077": { "label": "12/30", "naklon": 0 }, + "3080": { "label": "12/31", "naklon": 0 }, + "3081": { "label": "12/32", "naklon": 0 }, + "3078": { "label": "12/33", "naklon": 0 }, + "4037": { "label": "12/34", "naklon": 0 }, + "3067": { "label": "12/35", "naklon": 0 }, + "3051": { "label": "12/36", "naklon": 0 }, + "2924": { "label": "12/37", "naklon": 0 }, + "3060": { "label": "12/38", "naklon": 0 }, + "3073": { "label": "12/39", "naklon": 0 }, + "3469": { "label": "12/40", "naklon": 0 }, + "2923": { "label": "12/41", "naklon": 0 }, + "2925": { "label": "12/42", "naklon": 0 }, + "3359": { "label": "12/43", "naklon": 0 }, + "3055": { "label": "12/44", "naklon": 0 }, + "2922": { "label": "12/45", "naklon": 0 }, + "3084": { "label": "12/46", "naklon": 0 }, + "3064": { "label": "12/47", "naklon": 0 }, + "3066": { "label": "12/48", "naklon": 0 }, + "3072": { "label": "12/49", "naklon": 0 }, + "3415": { "label": "13/13A", "naklon": 0 }, + "3409": { "label": "13/13B", "naklon": 0 }, + "3399": { "label": "13/13C", "naklon": 0 }, + "3410": { "label": "13/29A", "naklon": 0 }, + "3407": { "label": "13/29B", "naklon": 0 }, + "3405": { "label": "13/34A", "naklon": 0 }, + "3404": { "label": "13/34B", "naklon": 0 }, + "3392": { "label": "13/45A", "naklon": 0 }, + "3386": { "label": "13/45B", "naklon": 0 }, + "3303": { "label": "13/60A", "naklon": 3 }, + "3302": { "label": "13/60B", "naklon": 3 }, + "3319": { "label": "13/70A", "naklon": 6 }, + "3317": { "label": "13/70B", "naklon": 6 }, + "3326": { "label": "13/70C", "naklon": 6 }, + "3351": { "label": "13/73A", "naklon": 6 }, + "3313": { "label": "13/73B", "naklon": 6 }, + "3316": { "label": "13/83A", "naklon": 0 }, + "3320": { "label": "13/83B", "naklon": 0 }, + "3336": { "label": "13/95A", "naklon": 0 }, + "3323": { "label": "13/95B", "naklon": 0 }, + "3339": { "label": "13/98A", "naklon": 0 }, + "3333": { "label": "13/98B", "naklon": 0 }, + "3425": { "label": "13/1", "naklon": 0 }, + "3419": { "label": "13/2", "naklon": 0 }, + "3416": { "label": "13/3", "naklon": 0 }, + "3332": { "label": "13/4", "naklon": 0 }, + "3422": { "label": "13/5", "naklon": 0 }, + "3417": { "label": "13/6", "naklon": 0 }, + "3418": { "label": "13/7", "naklon": 0 }, + "3424": { "label": "13/8", "naklon": 0 }, + "3334": { "label": "13/9", "naklon": 0 }, + "4363": { "label": "13/10", "naklon": 0 }, + "3423": { "label": "13/11", "naklon": 0 }, + "3406": { "label": "13/12", "naklon": 0 }, + "3411": { "label": "13/14", "naklon": 0 }, + "3412": { "label": "13/15", "naklon": 0 }, + "3413": { "label": "13/16", "naklon": 0 }, + "3414": { "label": "13/17", "naklon": 0 }, + "3391": { "label": "13/18", "naklon": 0 }, + "3370": { "label": "13/19", "naklon": 0 }, + "3369": { "label": "13/20", "naklon": 0 }, + "3408": { "label": "13/21", "naklon": 0 }, + "3393": { "label": "13/22", "naklon": 0 }, + "3128": { "label": "13/23", "naklon": 0 }, + "3197": { "label": "13/24", "naklon": 0 }, + "4364": { "label": "13/25", "naklon": 0 }, + "3155": { "label": "13/26", "naklon": 0 }, + "3196": { "label": "13/27", "naklon": 0 }, + "3144": { "label": "13/28", "naklon": 0 }, + "3150": { "label": "13/30", "naklon": 0 }, + "3390": { "label": "13/31", "naklon": 0 }, + "3401": { "label": "13/32", "naklon": 0 }, + "3275": { "label": "13/33", "naklon": 0 }, + "3371": { "label": "13/35", "naklon": 0 }, + "3389": { "label": "13/36", "naklon": 0 }, + "3388": { "label": "13/37", "naklon": 0 }, + "3365": { "label": "13/38", "naklon": 0 }, + "3363": { "label": "13/39", "naklon": 0 }, + "3397": { "label": "13/40", "naklon": 0 }, + "3567": { "label": "13/40/1", "naklon": 0 }, + "3387": { "label": "13/41", "naklon": 0 }, + "3403": { "label": "13/42", "naklon": 0 }, + "3147": { "label": "13/43", "naklon": 0 }, + "3141": { "label": "13/44", "naklon": 0 }, + "3364": { "label": "13/46", "naklon": 0 }, + "3367": { "label": "13/47", "naklon": 0 }, + "3368": { "label": "13/48", "naklon": 0 }, + "3402": { "label": "13/49", "naklon": 0 }, + "3366": { "label": "13/50", "naklon": 0 }, + "3395": { "label": "13/51", "naklon": 0 }, + "3372": { "label": "13/52", "naklon": 0 }, + "3394": { "label": "13/53", "naklon": 0 }, + "3308": { "label": "13/54", "naklon": 0 }, + "3847": { "label": "13/54/1", "naklon": 0 }, + "3312": { "label": "13/55", "naklon": 3 }, + "3309": { "label": "13/56", "naklon": 3 }, + "3311": { "label": "13/57", "naklon": 3 }, + "3310": { "label": "13/58", "naklon": 3 }, + "4365": { "label": "13/59", "naklon": 3 }, + "4093": { "label": "13/60/1", "naklon": 3 }, + "3304": { "label": "13/61", "naklon": 3 }, + "3307": { "label": "13/62", "naklon": 3 }, + "3271": { "label": "13/63", "naklon": 3 }, + "3301": { "label": "13/64", "naklon": 3 }, + "4366": { "label": "13/65", "naklon": 3 }, + "3300": { "label": "13/66", "naklon": 3 }, + "3185": { "label": "13/67", "naklon": 0 }, + "3184": { "label": "13/68", "naklon": 0 }, + "3188": { "label": "13/69", "naklon": 0 }, + "3343": { "label": "13/71", "naklon": 6 }, + "3819": { "label": "13/71/1", "naklon": 6 }, + "3880": { "label": "13/71/2", "naklon": 6 }, + "3348": { "label": "13/72", "naklon": 6 }, + "3344": { "label": "13/74", "naklon": 6 }, + "3346": { "label": "13/75", "naklon": 6 }, + "3597": { "label": "13/75/1", "naklon": 6 }, + "3345": { "label": "13/76", "naklon": 6 }, + "3322": { "label": "13/77", "naklon": 0 }, + "3325": { "label": "13/78", "naklon": 0 }, + "4310": { "label": "13/78/1", "naklon": 0 }, + "3315": { "label": "13/79", "naklon": 0 }, + "3328": { "label": "13/80", "naklon": 0 }, + "3321": { "label": "13/81", "naklon": 0 }, + "3324": { "label": "13/82", "naklon": 0 }, + "3140": { "label": "13/84", "naklon": 0 }, + "3153": { "label": "13/85", "naklon": 0 }, + "3145": { "label": "13/86", "naklon": 0 }, + "3134": { "label": "13/87", "naklon": 0 }, + "3151": { "label": "13/88", "naklon": 0 }, + "3143": { "label": "13/89", "naklon": 0 }, + "3318": { "label": "13/90", "naklon": 0 }, + "3347": { "label": "13/91", "naklon": 0 }, + "3314": { "label": "13/94", "naklon": 0 }, + "3331": { "label": "13/96", "naklon": 0 }, + "3327": { "label": "13/97", "naklon": 0 }, + "3329": { "label": "13/99", "naklon": 0 }, + "3337": { "label": "13/100", "naklon": 0 }, + "3330": { "label": "13/101", "naklon": 0 }, + "3335": { "label": "13/102", "naklon": 0 }, + "3420": { "label": "13/103", "naklon": 0 }, + "3421": { "label": "13/104", "naklon": 0 }, + "4361": { "label": "13/105", "naklon": 0 }, + "4362": { "label": "13/106", "naklon": 0 }, + "3526": { "label": "13/107", "naklon": 0 }, + "4424": { "label": "13/108", "naklon": null }, + "3561": { "label": "13/109", "naklon": null }, + "3527": { "label": "13/110", "naklon": null }, + "3521": { "label": "13/111", "naklon": null }, + "3552": { "label": "13/112", "naklon": null }, + "3544": { "label": "13/113", "naklon": null }, + "3534": { "label": "13/114", "naklon": null }, + "3516": { "label": "13/115", "naklon": null }, + "3513": { "label": "13/116", "naklon": null }, + "3565": { "label": "13/117", "naklon": null }, + "3866": { "label": "13/118", "naklon": null }, + "3136": { "label": "14/1", "naklon": 0 }, + "3137": { "label": "14/2", "naklon": 0 }, + "3135": { "label": "14/3", "naklon": 0 }, + "3149": { "label": "14/4", "naklon": 0 }, + "3142": { "label": "14/5", "naklon": 0 }, + "3342": { "label": "14/6", "naklon": 0 }, + "3340": { "label": "14/7", "naklon": 0 }, + "3152": { "label": "14/8", "naklon": 0 }, + "3886": { "label": "14/9", "naklon": 0 }, + "3341": { "label": "14/10", "naklon": null }, + "3352": { "label": "14/11", "naklon": null }, + "3396": { "label": "15/1", "naklon": 5 }, + "2784": { "label": "15/2", "naklon": 5 }, + "2788": { "label": "15/3", "naklon": 5 }, + "2801": { "label": "15/4", "naklon": 5 }, + "2815": { "label": "15/5", "naklon": 5 }, + "2829": { "label": "15/6", "naklon": 5 }, + "2796": { "label": "15/7", "naklon": 5 }, + "2803": { "label": "15/8", "naklon": 5 }, + "4304": { "label": "15/8/1", "naklon": 5 }, + "4311": { "label": "15/8/2", "naklon": 5 }, + "2821": { "label": "15/9", "naklon": 5 }, + "3400": { "label": "15/10", "naklon": 5 }, + "2799": { "label": "15/11", "naklon": 5 }, + "2804": { "label": "15/12", "naklon": 5 }, + "4303": { "label": "15/12/1", "naklon": 5 }, + "4309": { "label": "15/12/2", "naklon": 5 }, + "2806": { "label": "15/13", "naklon": 5 }, + "2787": { "label": "15/14", "naklon": 5 }, + "2809": { "label": "15/15", "naklon": 5 }, + "2814": { "label": "15/16", "naklon": 0 }, + "3934": { "label": "15/17", "naklon": 0 }, + "3192": { "label": "15/18", "naklon": 0 }, + "2812": { "label": "15/19", "naklon": 0 }, + "4070": { "label": "15/20", "naklon": 0 }, + "2826": { "label": "15/21", "naklon": 0 }, + "2808": { "label": "15/22", "naklon": 3 }, + "2795": { "label": "15/23", "naklon": 3 }, + "2807": { "label": "15/24", "naklon": 3 }, + "2831": { "label": "15/25", "naklon": 0 }, + "2862": { "label": "15/26", "naklon": null }, + "2861": { "label": "15/27", "naklon": 0 }, + "2866": { "label": "15/28", "naklon": 0 }, + "3546": { "label": "15/28/1", "naklon": 0 }, + "4146": { "label": "15/29", "naklon": 0 }, + "3001": { "label": "15/29/1", "naklon": 0 }, + "2835": { "label": "15/30", "naklon": 0 }, + "2874": { "label": "15/31", "naklon": 0 }, + "2852": { "label": "15/32", "naklon": 0 }, + "2851": { "label": "15/33", "naklon": 0 }, + "3560": { "label": "15/33/1", "naklon": 0 }, + "2858": { "label": "15/34", "naklon": 0 }, + "4306": { "label": "15/34/1", "naklon": 0 }, + "2856": { "label": "15/35", "naklon": 0 }, + "2847": { "label": "15/36", "naklon": 0 }, + "3556": { "label": "15/36/1", "naklon": 0 }, + "3950": { "label": "15/37", "naklon": 0 }, + "2848": { "label": "15/38", "naklon": 0 }, + "2863": { "label": "15/39", "naklon": 0 }, + "4313": { "label": "15/39/1", "naklon": 0 }, + "2873": { "label": "15/40", "naklon": 0 }, + "2984": { "label": "15/40/1", "naklon": 0 }, + "2854": { "label": "15/41", "naklon": 0 }, + "2859": { "label": "15/42", "naklon": 0 }, + "2872": { "label": "15/43", "naklon": 0 }, + "2849": { "label": "15/44", "naklon": 0 }, + "2864": { "label": "15/45", "naklon": 0 }, + "3553": { "label": "15/46", "naklon": null }, + "3021": { "label": "15/47", "naklon": null }, + "3008": { "label": "15/47/1", "naklon": null }, + "3017": { "label": "15/48", "naklon": null }, + "3014": { "label": "15/49", "naklon": null }, + "2981": { "label": "15/50", "naklon": null }, + "3020": { "label": "15/51", "naklon": null }, + "3027": { "label": "15/52", "naklon": null }, + "3006": { "label": "15/53", "naklon": null }, + "3012": { "label": "15/54", "naklon": null }, + "2738": { "label": "15/55", "naklon": 0 }, + "2725": { "label": "15/56", "naklon": 0 }, + "3016": { "label": "15/57", "naklon": null }, + "3005": { "label": "15/58", "naklon": null }, + "3009": { "label": "15/58/1", "naklon": null }, + "3010": { "label": "15/59", "naklon": 0 }, + "3538": { "label": "15/59/1", "naklon": 0 }, + "4145": { "label": "15/59/2", "naklon": 0 }, + "2713": { "label": "15/60", "naklon": 0 }, + "2789": { "label": "15/61", "naklon": 0 }, + "2736": { "label": "15/62", "naklon": 0 }, + "2739": { "label": "15/63", "naklon": 0 }, + "4346": { "label": "15/64", "naklon": 0 }, + "2731": { "label": "15/65", "naklon": 0 }, + "2818": { "label": "15/66", "naklon": 0 }, + "3557": { "label": "15/66/1", "naklon": 0 }, + "2822": { "label": "15/67", "naklon": 0 }, + "2833": { "label": "15/68", "naklon": 0 }, + "2834": { "label": "15/69", "naklon": 0 }, + "3097": { "label": "15/70", "naklon": 0 }, + "2824": { "label": "15/71", "naklon": 0 }, + "2828": { "label": "15/72", "naklon": 0 }, + "2600": { "label": "15/73", "naklon": 0 }, + "4314": { "label": "15/73/1", "naklon": 0 }, + "2832": { "label": "15/74", "naklon": 0 }, + "4360": { "label": "15/75", "naklon": 0 }, + "2846": { "label": "15/76", "naklon": 0 }, + "2584": { "label": "15/77", "naklon": 0 }, + "2843": { "label": "15/78", "naklon": 0 }, + "4308": { "label": "15/78/1", "naklon": 0 }, + "4144": { "label": "15/79", "naklon": null }, + "2844": { "label": "15/80", "naklon": 0 }, + "2842": { "label": "15/81", "naklon": 0 }, + "2838": { "label": "15/82", "naklon": 0 }, + "2837": { "label": "15/83", "naklon": null }, + "3555": { "label": "15/83/1", "naklon": null }, + "2839": { "label": "15/84", "naklon": 0 }, + "2830": { "label": "15/85", "naklon": 0 }, + "4066": { "label": "15/86", "naklon": 0 }, + "2836": { "label": "15/87", "naklon": 0 }, + "2911": { "label": "15/88", "naklon": 0 }, + "2825": { "label": "15/89", "naklon": 0 }, + "2811": { "label": "15/90", "naklon": 0 }, + "3740": { "label": "15/94", "naklon": 15 }, + "2734": { "label": "15/95", "naklon": 15 }, + "3105": { "label": "15/96", "naklon": 15 }, + "2732": { "label": "15/97", "naklon": 15 }, + "2727": { "label": "15/98", "naklon": 15 }, + "2735": { "label": "15/99", "naklon": 15 }, + "3926": { "label": "15/100", "naklon": 15 }, + "2918": { "label": "15/101", "naklon": 0 }, + "2705": { "label": "15/102", "naklon": 10 }, + "2708": { "label": "15/103", "naklon": 10 }, + "2721": { "label": "15/104", "naklon": 10 }, + "2719": { "label": "15/105", "naklon": 10 }, + "2919": { "label": "15/106", "naklon": 10 }, + "3101": { "label": "15/107", "naklon": 10 }, + "2853": { "label": "15/108", "naklon": 10 }, + "2715": { "label": "15/109", "naklon": 10 }, + "2712": { "label": "15/110", "naklon": 0 }, + "2711": { "label": "15/111", "naklon": 0 }, + "2709": { "label": "15/112", "naklon": 0 }, + "2710": { "label": "15/113", "naklon": 0 }, + "2907": { "label": "15/114", "naklon": 0 }, + "2906": { "label": "15/115", "naklon": 0 }, + "2908": { "label": "15/116", "naklon": 0 }, + "2901": { "label": "15/117", "naklon": 0 }, + "2913": { "label": "15/118", "naklon": 0 }, + "3656": { "label": "15/119", "naklon": 0 }, + "2781": { "label": "15/120", "naklon": 0 }, + "2802": { "label": "15/121", "naklon": 0 }, + "2791": { "label": "15/122", "naklon": 0 }, + "2783": { "label": "15/123", "naklon": 0 }, + "2794": { "label": "15/124", "naklon": 0 }, + "3139": { "label": "15/125", "naklon": 0 }, + "3229": { "label": "15/126", "naklon": 5 }, + "3239": { "label": "15/127", "naklon": 5 }, + "3230": { "label": "15/128", "naklon": 5 }, + "4016": { "label": "15/129", "naklon": null }, + "3608": { "label": "16/16A", "naklon": 0 }, + "4151": { "label": "16/16B", "naklon": 0 }, + "3710": { "label": "16/1", "naklon": 0 }, + "3726": { "label": "16/2", "naklon": 0 }, + "3743": { "label": "16/3", "naklon": 0 }, + "3724": { "label": "16/4", "naklon": 0 }, + "3712": { "label": "16/5", "naklon": 0 }, + "3739": { "label": "16/6", "naklon": 0 }, + "3742": { "label": "16/7", "naklon": 0 }, + "3731": { "label": "16/8", "naklon": 0 }, + "3727": { "label": "16/9", "naklon": 0 }, + "3729": { "label": "16/10", "naklon": 0 }, + "3736": { "label": "16/11", "naklon": 0 }, + "3713": { "label": "16/12", "naklon": 0 }, + "3715": { "label": "16/13", "naklon": 0 }, + "3733": { "label": "16/14", "naklon": 0 }, + "3732": { "label": "16/15", "naklon": 0 }, + "3634": { "label": "16/17", "naklon": 0 }, + "3610": { "label": "16/18", "naklon": 0 }, + "3626": { "label": "16/19", "naklon": 0 }, + "3618": { "label": "16/20", "naklon": 0 }, + "3619": { "label": "16/21", "naklon": 0 }, + "3628": { "label": "16/22", "naklon": 0 }, + "3615": { "label": "16/23", "naklon": 0 }, + "3609": { "label": "16/24", "naklon": 0 }, + "3606": { "label": "16/25", "naklon": 0 }, + "3624": { "label": "16/26", "naklon": 0 }, + "3627": { "label": "16/27", "naklon": 0 }, + "3607": { "label": "16/28", "naklon": 0 }, + "4370": { "label": "16/29", "naklon": 0 }, + "3692": { "label": "16/30", "naklon": 0 }, + "3614": { "label": "16/31", "naklon": 0 }, + "3623": { "label": "16/32", "naklon": 0 }, + "4373": { "label": "16/33", "naklon": 0 }, + "3620": { "label": "16/34", "naklon": 0 }, + "3685": { "label": "16/35", "naklon": 0 }, + "3616": { "label": "16/36", "naklon": 0 }, + "3686": { "label": "16/37", "naklon": 0 }, + "3688": { "label": "16/38", "naklon": 0 }, + "3684": { "label": "16/39", "naklon": 0 }, + "3825": { "label": "16/40", "naklon": 0 }, + "3865": { "label": "16/41", "naklon": 0 }, + "3824": { "label": "16/42", "naklon": 0 }, + "3871": { "label": "16/43", "naklon": 0 }, + "3801": { "label": "16/44", "naklon": 0 }, + "3862": { "label": "16/45", "naklon": 0 }, + "3876": { "label": "16/46", "naklon": 0 }, + "3861": { "label": "16/47", "naklon": 0 }, + "4215": { "label": "16/48", "naklon": 0 }, + "3605": { "label": "16/49", "naklon": 10 }, + "3603": { "label": "16/50", "naklon": 10 }, + "3592": { "label": "16/51", "naklon": 10 }, + "3598": { "label": "16/52", "naklon": 10 }, + "3594": { "label": "16/53", "naklon": 10 }, + "3593": { "label": "16/54", "naklon": 10 }, + "3630": { "label": "16/55", "naklon": 10 }, + "3763": { "label": "16/56", "naklon": 10 }, + "3746": { "label": "16/57", "naklon": 10 }, + "3699": { "label": "16/58", "naklon": 0 }, + "3698": { "label": "16/59", "naklon": 0 }, + "3709": { "label": "16/60", "naklon": null }, + "3708": { "label": "16/61", "naklon": 0 }, + "3703": { "label": "16/62", "naklon": null }, + "3700": { "label": "16/63", "naklon": 0 }, + "3701": { "label": "16/64", "naklon": null }, + "3704": { "label": "16/65", "naklon": 0 }, + "3707": { "label": "16/66", "naklon": null }, + "3810": { "label": "16/67", "naklon": 0 }, + "4208": { "label": "16/68", "naklon": null }, + "3867": { "label": "16/69", "naklon": 0 }, + "4372": { "label": "16/70", "naklon": null }, + "3881": { "label": "16/71", "naklon": 0 }, + "4204": { "label": "16/72", "naklon": null }, + "3869": { "label": "16/73", "naklon": 0 }, + "4202": { "label": "16/74", "naklon": null }, + "3830": { "label": "16/75", "naklon": 0 }, + "3870": { "label": "16/76", "naklon": null }, + "3964": { "label": "16/77", "naklon": 0 }, + "3849": { "label": "16/78", "naklon": 0 }, + "3694": { "label": "16/79", "naklon": null }, + "3717": { "label": "16/80", "naklon": 0 }, + "3877": { "label": "16/81", "naklon": null }, + "3755": { "label": "16/82", "naklon": 0 }, + "3725": { "label": "16/83", "naklon": null }, + "3716": { "label": "16/84", "naklon": 0 }, + "3696": { "label": "16/85", "naklon": null }, + "3702": { "label": "16/86", "naklon": 0 }, + "3706": { "label": "16/87", "naklon": null }, + "3850": { "label": "16/88", "naklon": 0 }, + "3848": { "label": "16/89", "naklon": null }, + "3737": { "label": "16/90", "naklon": null }, + "3705": { "label": "16/91", "naklon": 0 }, + "3723": { "label": "16/92", "naklon": null }, + "3842": { "label": "16/93", "naklon": 0 }, + "3735": { "label": "16/94", "naklon": null }, + "3719": { "label": "16/95", "naklon": 0 }, + "3697": { "label": "16/96", "naklon": 0 }, + "3711": { "label": "16/97", "naklon": 0 }, + "4107": { "label": "16/98", "naklon": null }, + "4112": { "label": "16/99", "naklon": 5 }, + "4106": { "label": "16/100", "naklon": 5 }, + "4111": { "label": "16/101", "naklon": 5 }, + "4091": { "label": "16/102", "naklon": null }, + "4104": { "label": "16/103", "naklon": 5 }, + "4094": { "label": "16/104", "naklon": null }, + "4089": { "label": "16/105", "naklon": 5 }, + "4095": { "label": "16/106", "naklon": null }, + "4102": { "label": "16/107", "naklon": 5 }, + "4105": { "label": "16/108", "naklon": null }, + "3859": { "label": "16/109", "naklon": null }, + "4090": { "label": "16/110", "naklon": 5 }, + "4110": { "label": "16/111", "naklon": null }, + "4097": { "label": "16/112", "naklon": 5 }, + "4099": { "label": "16/113", "naklon": null }, + "4096": { "label": "16/114", "naklon": null }, + "4101": { "label": "16/115", "naklon": 5 }, + "4109": { "label": "16/116", "naklon": null }, + "4092": { "label": "16/117", "naklon": 5 }, + "3631": { "label": "16/118", "naklon": null }, + "3632": { "label": "16/119", "naklon": 0 }, + "3641": { "label": "16/120", "naklon": null }, + "3638": { "label": "16/121", "naklon": 0 }, + "3637": { "label": "16/122", "naklon": null }, + "4142": { "label": "16/123", "naklon": null }, + "4147": { "label": "16/124", "naklon": 5 }, + "4139": { "label": "16/125", "naklon": 5 }, + "3172": { "label": "20/30A", "naklon": 2 }, + "3164": { "label": "20/30B", "naklon": 2 }, + "3247": { "label": "20/1", "naklon": 10 }, + "3296": { "label": "20/2", "naklon": 10 }, + "3246": { "label": "20/3", "naklon": 10 }, + "3270": { "label": "20/4", "naklon": 10 }, + "3294": { "label": "20/5", "naklon": 10 }, + "3298": { "label": "20/6", "naklon": 10 }, + "3297": { "label": "20/7", "naklon": 10 }, + "3293": { "label": "20/8", "naklon": 10 }, + "3299": { "label": "20/9", "naklon": 10 }, + "3295": { "label": "20/10", "naklon": 10 }, + "3244": { "label": "20/11", "naklon": 10 }, + "3249": { "label": "20/12", "naklon": 10 }, + "3268": { "label": "20/13", "naklon": 10 }, + "3245": { "label": "20/14", "naklon": 10 }, + "3278": { "label": "20/15", "naklon": 10 }, + "3280": { "label": "20/16", "naklon": 10 }, + "3292": { "label": "20/17", "naklon": 10 }, + "3287": { "label": "20/18", "naklon": 10 }, + "3282": { "label": "20/19", "naklon": 10 }, + "3273": { "label": "20/20", "naklon": 0 }, + "3157": { "label": "20/21", "naklon": 0 }, + "3283": { "label": "20/22", "naklon": 0 }, + "3159": { "label": "20/23", "naklon": 0 }, + "3289": { "label": "20/24", "naklon": 0 }, + "3163": { "label": "20/25", "naklon": 0 }, + "3126": { "label": "20/26", "naklon": 0 }, + "3171": { "label": "20/27", "naklon": 0 }, + "3162": { "label": "20/28", "naklon": 0 }, + "3279": { "label": "20/29", "naklon": 10 }, + "3173": { "label": "20/31", "naklon": 0 }, + "3127": { "label": "20/32", "naklon": 0 }, + "3131": { "label": "20/33", "naklon": 0 }, + "3129": { "label": "20/34", "naklon": 0 }, + "3276": { "label": "20/35", "naklon": 2 }, + "3290": { "label": "20/36", "naklon": 2 }, + "3132": { "label": "20/37", "naklon": 0 }, + "3138": { "label": "20/38", "naklon": 0 }, + "3272": { "label": "20/39", "naklon": 0 }, + "3291": { "label": "20/40", "naklon": 0 }, + "3277": { "label": "20/41", "naklon": 10 }, + "3286": { "label": "20/42", "naklon": 10 }, + "3281": { "label": "20/43", "naklon": 10 }, + "3288": { "label": "20/44", "naklon": 10 }, + "3284": { "label": "20/45", "naklon": 10 }, + "3167": { "label": "20/46", "naklon": 10 }, + "3872": { "label": "20/47", "naklon": 0 }, + "3124": { "label": "20/48", "naklon": 0 }, + "3133": { "label": "20/49", "naklon": 0 }, + "3158": { "label": "20/50", "naklon": 0 }, + "3169": { "label": "20/51", "naklon": 0 }, + "3146": { "label": "20/52", "naklon": 0 }, + "3160": { "label": "20/53", "naklon": 0 }, + "3248": { "label": "20/54", "naklon": 0 }, + "3156": { "label": "20/55", "naklon": 0 }, + "3161": { "label": "20/56", "naklon": 0 }, + "3170": { "label": "20/57", "naklon": 0 }, + "3168": { "label": "20/58", "naklon": 0 }, + "3125": { "label": "20/59", "naklon": 0 }, + "3166": { "label": "20/60", "naklon": 0 }, + "3130": { "label": "20/61", "naklon": 0 }, + "3563": { "label": "20/62", "naklon": 0 }, + "3550": { "label": "20/63", "naklon": null }, + "3269": { "label": "20/67", "naklon": 0 }, + "2921": { "label": "21/1", "naklon": 0 }, + "2707": { "label": "21/2", "naklon": 0 }, + "2723": { "label": "21/3", "naklon": 0 }, + "2716": { "label": "21/4", "naklon": 0 }, + "2717": { "label": "21/5", "naklon": 0 }, + "2720": { "label": "21/6", "naklon": 0 }, + "2722": { "label": "21/7", "naklon": 0 }, + "2718": { "label": "21/8", "naklon": 0 }, + "2724": { "label": "21/9", "naklon": 0 }, + "2742": { "label": "21/10", "naklon": 0 }, + "2743": { "label": "21/11", "naklon": 0 }, + "2733": { "label": "21/12", "naklon": 0 }, + "2903": { "label": "21/14", "naklon": 0 }, + "2917": { "label": "21/15", "naklon": 0 }, + "2897": { "label": "21/16", "naklon": 0 }, + "2914": { "label": "21/17", "naklon": 0 }, + "2898": { "label": "21/18", "naklon": 0 }, + "2773": { "label": "21/19", "naklon": 0 }, + "2895": { "label": "21/20", "naklon": 0 }, + "2896": { "label": "21/21", "naklon": 0 }, + "2771": { "label": "21/22", "naklon": 0 }, + "2772": { "label": "21/23", "naklon": 0 }, + "2793": { "label": "21/24", "naklon": 0 }, + "2902": { "label": "21/25", "naklon": 0 }, + "2910": { "label": "21/26", "naklon": 0 }, + "2909": { "label": "21/27", "naklon": 0 }, + "2920": { "label": "21/28", "naklon": 0 }, + "2916": { "label": "21/29", "naklon": 0 }, + "2904": { "label": "21/30", "naklon": 0 }, + "2915": { "label": "21/31", "naklon": 0 }, + "2905": { "label": "21/32", "naklon": 0 }, + "2900": { "label": "21/33", "naklon": 0 }, + "2899": { "label": "21/34", "naklon": 0 }, + "2741": { "label": "21/36", "naklon": 0 }, + "2714": { "label": "21/37", "naklon": 0 }, + "2701": { "label": "21/38", "naklon": 0 }, + "2703": { "label": "21/39", "naklon": 0 }, + "2704": { "label": "21/40", "naklon": 0 }, + "2702": { "label": "21/41", "naklon": 0 }, + "2706": { "label": "21/42", "naklon": 0 }, + "2776": { "label": "21/43", "naklon": 0 }, + "2770": { "label": "21/44", "naklon": 0 }, + "2786": { "label": "21/45", "naklon": 0 }, + "2779": { "label": "21/46", "naklon": 0 }, + "2782": { "label": "21/47", "naklon": 0 }, + "2785": { "label": "21/48", "naklon": 0 }, + "2769": { "label": "21/49", "naklon": 0 }, + "3354": { "label": "21/50", "naklon": 0 }, + "2778": { "label": "21/51", "naklon": 0 }, + "2775": { "label": "21/52", "naklon": 0 }, + "2780": { "label": "21/53", "naklon": 0 }, + "2790": { "label": "21/54", "naklon": 0 }, + "2792": { "label": "21/55", "naklon": 0 }, + "2774": { "label": "21/56", "naklon": 0 }, + "2630": { "label": "22/1", "naklon": 0 }, + "2631": { "label": "22/2", "naklon": 0 }, + "2632": { "label": "22/3", "naklon": 0 }, + "2633": { "label": "22/4", "naklon": 0 }, + "2634": { "label": "22/5", "naklon": 0 }, + "2636": { "label": "22/6", "naklon": 0 }, + "4367": { "label": "22/7", "naklon": 0 }, + "2637": { "label": "22/8", "naklon": 0 }, + "2638": { "label": "22/9", "naklon": 0 }, + "2639": { "label": "22/10", "naklon": 0 }, + "2640": { "label": "22/11", "naklon": 0 }, + "2641": { "label": "22/12", "naklon": 0 }, + "2642": { "label": "22/13", "naklon": 0 }, + "2643": { "label": "22/14", "naklon": 0 }, + "2644": { "label": "22/15", "naklon": 0 }, + "2645": { "label": "22/16", "naklon": 0 }, + "2646": { "label": "22/17", "naklon": 0 }, + "2647": { "label": "22/18", "naklon": 0 }, + "2648": { "label": "22/19", "naklon": 0 }, + "2649": { "label": "22/20", "naklon": 0 }, + "2650": { "label": "22/21", "naklon": 0 }, + "2651": { "label": "22/22", "naklon": 0 }, + "4103": { "label": "22/23", "naklon": 0 }, + "2653": { "label": "22/24", "naklon": 0 }, + "2654": { "label": "22/25", "naklon": 0 }, + "2655": { "label": "22/26", "naklon": 0 }, + "2656": { "label": "22/27", "naklon": 0 }, + "2657": { "label": "22/28", "naklon": 0 }, + "2658": { "label": "22/29", "naklon": 0 }, + "2659": { "label": "22/30", "naklon": 0 }, + "2660": { "label": "22/31", "naklon": 0 }, + "2661": { "label": "22/32", "naklon": 0 }, + "3015": { "label": "22/32/1", "naklon": 0 }, + "2662": { "label": "22/33", "naklon": 0 }, + "2663": { "label": "22/34", "naklon": 0 }, + "2664": { "label": "22/35", "naklon": 0 }, + "2665": { "label": "22/36", "naklon": 0 }, + "2666": { "label": "22/37", "naklon": 0 }, + "2667": { "label": "22/38", "naklon": 0 }, + "2668": { "label": "22/39", "naklon": 0 }, + "2669": { "label": "22/40", "naklon": null }, + "2670": { "label": "22/41", "naklon": null }, + "2671": { "label": "22/42", "naklon": null }, + "3087": { "label": "23/9A", "naklon": 10 }, + "3090": { "label": "23/9B", "naklon": 10 }, + "3075": { "label": "23/1", "naklon": 0 }, + "3089": { "label": "23/2", "naklon": 0 }, + "3088": { "label": "23/3", "naklon": 0 }, + "3228": { "label": "23/4", "naklon": 10 }, + "2751": { "label": "23/5", "naklon": 10 }, + "3243": { "label": "23/6", "naklon": 10 }, + "4349": { "label": "23/7", "naklon": 10 }, + "3102": { "label": "23/8", "naklon": 10 }, + "3099": { "label": "23/10", "naklon": 10 }, + "3103": { "label": "23/11", "naklon": 10 }, + "3093": { "label": "23/12", "naklon": 10 }, + "3098": { "label": "23/13", "naklon": 10 }, + "3092": { "label": "23/14", "naklon": 10 }, + "3233": { "label": "23/15", "naklon": 0 }, + "3095": { "label": "23/16", "naklon": 0 }, + "4074": { "label": "23/17", "naklon": 0 }, + "2729": { "label": "23/18", "naklon": 0 }, + "3234": { "label": "23/19", "naklon": 0 }, + "3094": { "label": "23/20", "naklon": 0 }, + "2817": { "label": "23/21", "naklon": 0 }, + "3226": { "label": "23/22", "naklon": 0 }, + "3225": { "label": "23/23", "naklon": 0 }, + "3237": { "label": "23/24", "naklon": 0 }, + "4250": { "label": "23/25", "naklon": 0 }, + "3059": { "label": "23/26", "naklon": 10 }, + "3238": { "label": "23/27", "naklon": 10 }, + "3242": { "label": "23/28", "naklon": 10 }, + "3236": { "label": "23/29", "naklon": 10 }, + "3112": { "label": "23/30", "naklon": 10 }, + "3224": { "label": "23/31", "naklon": 0 }, + "4298": { "label": "23/32", "naklon": 10 }, + "4150": { "label": "23/33", "naklon": 10 }, + "3091": { "label": "23/34", "naklon": 10 }, + "3771": { "label": "25/1", "naklon": 5 }, + "3777": { "label": "25/2", "naklon": 5 }, + "3749": { "label": "25/3", "naklon": 5 }, + "3769": { "label": "25/4", "naklon": 5 }, + "3765": { "label": "25/5", "naklon": 5 }, + "3785": { "label": "25/6", "naklon": 5 }, + "3761": { "label": "25/7", "naklon": 5 }, + "3758": { "label": "25/8", "naklon": 5 }, + "3766": { "label": "25/9", "naklon": 5 }, + "3779": { "label": "25/10", "naklon": 5 }, + "3899": { "label": "25/11", "naklon": 10 }, + "3922": { "label": "25/12", "naklon": 10 }, + "3912": { "label": "25/13", "naklon": 10 }, + "3933": { "label": "25/14", "naklon": 10 }, + "3921": { "label": "25/15", "naklon": 10 }, + "4300": { "label": "25/16", "naklon": 10 }, + "3927": { "label": "25/17", "naklon": 10 }, + "3212": { "label": "25/18", "naklon": 10 }, + "3208": { "label": "25/19", "naklon": 10 }, + "3207": { "label": "25/20", "naklon": 10 }, + "4294": { "label": "25/21", "naklon": 10 }, + "3209": { "label": "25/22", "naklon": 10 }, + "3745": { "label": "25/23", "naklon": 10 }, + "3762": { "label": "25/24", "naklon": 10 }, + "3215": { "label": "25/25", "naklon": 10 }, + "3210": { "label": "25/26", "naklon": 10 }, + "3211": { "label": "25/27", "naklon": 10 }, + "3206": { "label": "25/28", "naklon": 10 }, + "3918": { "label": "25/29", "naklon": 5 }, + "3928": { "label": "25/30", "naklon": 5 }, + "3917": { "label": "25/31", "naklon": 5 }, + "4029": { "label": "25/32", "naklon": 0 }, + "4038": { "label": "25/33", "naklon": 0 }, + "4022": { "label": "25/34", "naklon": 0 }, + "3937": { "label": "25/35", "naklon": 0 }, + "3190": { "label": "25/36", "naklon": 0 }, + "3835": { "label": "25/37", "naklon": 0 }, + "3201": { "label": "25/38", "naklon": 0 }, + "3193": { "label": "25/39", "naklon": 0 }, + "3191": { "label": "25/40", "naklon": 0 }, + "3203": { "label": "25/41", "naklon": 0 }, + "4301": { "label": "25/42", "naklon": 0 }, + "3223": { "label": "25/43", "naklon": 0 }, + "3202": { "label": "25/44", "naklon": 0 }, + "3205": { "label": "25/45", "naklon": 0 }, + "3194": { "label": "25/46", "naklon": 0 }, + "3198": { "label": "25/47", "naklon": 0 }, + "3204": { "label": "25/48", "naklon": 0 }, + "3200": { "label": "25/49", "naklon": 0 }, + "3216": { "label": "25/50", "naklon": 0 }, + "3932": { "label": "25/51", "naklon": 5 }, + "3923": { "label": "25/52", "naklon": 5 }, + "3913": { "label": "25/53", "naklon": 5 }, + "3900": { "label": "25/54", "naklon": 5 }, + "4189": { "label": "25/55", "naklon": 10 }, + "4191": { "label": "25/56", "naklon": 10 }, + "3790": { "label": "25/57", "naklon": 10 }, + "4190": { "label": "25/58", "naklon": 10 }, + "4302": { "label": "25/59", "naklon": 0 }, + "4351": { "label": "25/60", "naklon": 0 }, + "4075": { "label": "25/61", "naklon": 0 }, + "4071": { "label": "25/62", "naklon": 0 }, + "3784": { "label": "25/63", "naklon": 0 }, + "4065": { "label": "25/64", "naklon": 0 }, + "4297": { "label": "25/65", "naklon": 0 }, + "4295": { "label": "25/66", "naklon": 0 }, + "4299": { "label": "25/67", "naklon": 0 }, + "3772": { "label": "25/68", "naklon": 0 }, + "3941": { "label": "25/69", "naklon": 0 }, + "3782": { "label": "25/70", "naklon": 0 }, + "4068": { "label": "25/71", "naklon": 0 }, + "4073": { "label": "25/72", "naklon": 0 }, + "3901": { "label": "25/73", "naklon": 5 }, + "4296": { "label": "25/74", "naklon": 5 }, + "3910": { "label": "25/75", "naklon": 5 }, + "4293": { "label": "25/76", "naklon": 5 }, + "3919": { "label": "25/77", "naklon": 5 }, + "3924": { "label": "25/78", "naklon": 5 }, + "3909": { "label": "25/79", "naklon": 5 }, + "3896": { "label": "25/80", "naklon": 5 }, + "3911": { "label": "25/81", "naklon": 5 }, + "2819": { "label": "25/82", "naklon": 15 }, + "3776": { "label": "25/83", "naklon": 15 }, + "3752": { "label": "25/84", "naklon": 15 }, + "4353": { "label": "25/85", "naklon": 15 }, + "3791": { "label": "25/86", "naklon": 0 }, + "3770": { "label": "25/87", "naklon": 0 }, + "3760": { "label": "25/88", "naklon": 0 }, + "3115": { "label": "25/89", "naklon": 0 }, + "3738": { "label": "25/90", "naklon": 0 }, + "3748": { "label": "25/91", "naklon": 0 }, + "3753": { "label": "25/92", "naklon": 0 }, + "3775": { "label": "25/93", "naklon": 0 }, + "3778": { "label": "25/94", "naklon": 5 }, + "4078": { "label": "25/95", "naklon": 5 }, + "4088": { "label": "25/96", "naklon": 5 }, + "3856": { "label": "25/97", "naklon": 5 }, + "4084": { "label": "25/98", "naklon": 5 }, + "4069": { "label": "25/99", "naklon": 5 }, + "4188": { "label": "25/100", "naklon": 5 }, + "4064": { "label": "25/101", "naklon": 5 }, + "3792": { "label": "25/102", "naklon": 5 }, + "3780": { "label": "25/103", "naklon": 5 }, + "4034": { "label": "25/104", "naklon": 5 }, + "4072": { "label": "25/105", "naklon": 5 }, + "3884": { "label": "25/106", "naklon": 5 }, + "3793": { "label": "25/107", "naklon": 5 }, + "3863": { "label": "25/108", "naklon": 5 }, + "3855": { "label": "25/109", "naklon": 5 }, + "3846": { "label": "33/1", "naklon": 0 }, + "3943": { "label": "33/2", "naklon": 0 }, + "3903": { "label": "33/3", "naklon": 0 }, + "3982": { "label": "33/4", "naklon": 0 }, + "3879": { "label": "33/5", "naklon": 0 }, + "3887": { "label": "33/6", "naklon": 0 }, + "3920": { "label": "33/7", "naklon": 5 }, + "3942": { "label": "33/8", "naklon": 5 }, + "3829": { "label": "33/9", "naklon": null }, + "3452": { "label": "34/79A", "naklon": 6 }, + "3460": { "label": "34/79B", "naklon": 6 }, + "3443": { "label": "34/90A", "naklon": 6 }, + "3445": { "label": "34/90B", "naklon": 6 }, + "3457": { "label": "34/90C", "naklon": 6 }, + "3461": { "label": "34/97A", "naklon": 6 }, + "3463": { "label": "34/97B", "naklon": 6 }, + "3426": { "label": "34/98A", "naklon": 6 }, + "3444": { "label": "34/98B", "naklon": 6 }, + "3453": { "label": "34/99A", "naklon": 6 }, + "3455": { "label": "34/99B", "naklon": 6 }, + "4009": { "label": "34/1", "naklon": 0 }, + "3602": { "label": "34/2", "naklon": 0 }, + "3441": { "label": "34/3", "naklon": 0 }, + "3464": { "label": "34/4", "naklon": 0 }, + "3883": { "label": "34/5", "naklon": 0 }, + "4098": { "label": "34/6", "naklon": 0 }, + "4003": { "label": "34/7", "naklon": 0 }, + "4004": { "label": "34/8", "naklon": 0 }, + "3888": { "label": "34/9", "naklon": 0 }, + "3997": { "label": "34/10", "naklon": 0 }, + "4006": { "label": "34/11", "naklon": 0 }, + "4000": { "label": "34/12", "naklon": 0 }, + "4011": { "label": "34/13", "naklon": 0 }, + "3999": { "label": "34/14", "naklon": 0 }, + "3981": { "label": "34/15", "naklon": 0 }, + "3988": { "label": "34/16", "naklon": 0 }, + "3986": { "label": "34/17", "naklon": 0 }, + "3998": { "label": "34/18", "naklon": 0 }, + "3983": { "label": "34/19", "naklon": 0 }, + "4005": { "label": "34/20", "naklon": 0 }, + "4001": { "label": "34/21", "naklon": 0 }, + "4008": { "label": "34/22", "naklon": 0 }, + "4002": { "label": "34/23", "naklon": 0 }, + "3996": { "label": "34/24", "naklon": 0 }, + "4007": { "label": "34/25", "naklon": 0 }, + "4113": { "label": "34/26", "naklon": 15 }, + "3595": { "label": "34/27", "naklon": 5 }, + "3599": { "label": "34/28", "naklon": 5 }, + "3601": { "label": "34/29", "naklon": 5 }, + "4205": { "label": "34/30", "naklon": 0 }, + "3987": { "label": "34/31", "naklon": null }, + "4214": { "label": "34/32", "naklon": 0 }, + "4226": { "label": "34/33", "naklon": 0 }, + "4209": { "label": "34/34", "naklon": 0 }, + "4201": { "label": "34/35", "naklon": 0 }, + "3440": { "label": "34/36", "naklon": 0 }, + "3465": { "label": "34/37", "naklon": 0 }, + "3446": { "label": "34/38", "naklon": 0 }, + "4039": { "label": "34/39", "naklon": 5 }, + "4057": { "label": "34/40", "naklon": 5 }, + "3985": { "label": "34/41", "naklon": 0 }, + "3882": { "label": "34/42", "naklon": 0 }, + "4040": { "label": "34/43", "naklon": 5 }, + "3231": { "label": "34/44", "naklon": 0 }, + "3227": { "label": "34/45", "naklon": 0 }, + "3431": { "label": "34/46", "naklon": 0 }, + "4013": { "label": "34/47", "naklon": 0 }, + "4045": { "label": "34/48", "naklon": 0 }, + "3949": { "label": "34/49", "naklon": 0 }, + "3953": { "label": "34/50", "naklon": 0 }, + "3952": { "label": "34/51", "naklon": 0 }, + "3995": { "label": "34/52", "naklon": 0 }, + "3992": { "label": "34/53", "naklon": 0 }, + "4198": { "label": "34/54", "naklon": 0 }, + "3935": { "label": "34/55", "naklon": 0 }, + "4050": { "label": "34/56", "naklon": 0 }, + "4049": { "label": "34/57", "naklon": 0 }, + "4054": { "label": "34/58", "naklon": 0 }, + "3663": { "label": "34/59", "naklon": 6 }, + "3661": { "label": "34/60", "naklon": 6 }, + "3664": { "label": "34/61", "naklon": 6 }, + "3660": { "label": "34/62", "naklon": 6 }, + "3662": { "label": "34/63", "naklon": 6 }, + "3665": { "label": "34/65", "naklon": 6 }, + "3667": { "label": "34/66", "naklon": 6 }, + "3675": { "label": "34/67", "naklon": 6 }, + "3666": { "label": "34/68", "naklon": 6 }, + "3652": { "label": "34/69", "naklon": 6 }, + "3458": { "label": "34/70", "naklon": 6 }, + "4425": { "label": "34/70/1", "naklon": 6 }, + "3459": { "label": "34/71", "naklon": 6 }, + "3435": { "label": "34/72", "naklon": 6 }, + "3448": { "label": "34/73", "naklon": 6 }, + "3451": { "label": "34/74", "naklon": 6 }, + "3442": { "label": "34/75", "naklon": 6 }, + "3449": { "label": "34/76", "naklon": 6 }, + "3450": { "label": "34/77", "naklon": 6 }, + "3433": { "label": "34/78", "naklon": 6 }, + "3432": { "label": "34/80", "naklon": 12 }, + "3470": { "label": "34/81", "naklon": 12 }, + "3438": { "label": "34/82", "naklon": 12 }, + "3439": { "label": "34/83", "naklon": 12 }, + "4028": { "label": "34/84", "naklon": 5 }, + "3596": { "label": "34/85", "naklon": 5 }, + "4021": { "label": "34/86", "naklon": 5 }, + "3437": { "label": "34/87", "naklon": 12 }, + "3428": { "label": "34/88", "naklon": 12 }, + "3430": { "label": "34/89", "naklon": 12 }, + "3454": { "label": "34/91", "naklon": 6 }, + "3492": { "label": "34/92", "naklon": 6 }, + "3462": { "label": "34/93", "naklon": 6 }, + "3427": { "label": "34/94", "naklon": 6 }, + "3434": { "label": "34/95", "naklon": 6 }, + "3456": { "label": "34/96", "naklon": 6 }, + "4307": { "label": "34/98/1", "naklon": 6 }, + "3968": { "label": "35/1", "naklon": 0 }, + "3969": { "label": "35/2", "naklon": 0 }, + "3947": { "label": "35/3", "naklon": 0 }, + "3979": { "label": "35/4", "naklon": 0 }, + "3959": { "label": "35/5", "naklon": 0 }, + "3948": { "label": "35/6", "naklon": 0 }, + "3961": { "label": "35/7", "naklon": 0 }, + "3956": { "label": "35/8", "naklon": 0 }, + "3604": { "label": "35/9", "naklon": 0 }, + "3944": { "label": "35/10", "naklon": 0 }, + "3960": { "label": "35/11", "naklon": 0 }, + "3958": { "label": "35/12", "naklon": 0 }, + "4036": { "label": "35/13", "naklon": 5 }, + "3893": { "label": "35/18", "naklon": 5 }, + "4108": { "label": "35/19", "naklon": 5 }, + "4017": { "label": "35/20", "naklon": 5 }, + "3963": { "label": "35/21", "naklon": 0 }, + "3658": { "label": "35/22", "naklon": 0 }, + "3975": { "label": "35/23", "naklon": 0 }, + "3980": { "label": "35/24", "naklon": 0 }, + "4012": { "label": "35/25", "naklon": 0 }, + "3655": { "label": "35/26", "naklon": 0 }, + "3962": { "label": "35/27", "naklon": 0 }, + "3945": { "label": "35/28", "naklon": 0 }, + "3569": { "label": "35/29", "naklon": 0 }, + "3429": { "label": "35/30", "naklon": 0 }, + "3657": { "label": "35/31", "naklon": 0 }, + "3646": { "label": "35/32", "naklon": 0 }, + "3622": { "label": "35/33", "naklon": 0 }, + "3612": { "label": "35/34", "naklon": 0 }, + "3955": { "label": "35/35", "naklon": 0 }, + "3878": { "label": "35/37", "naklon": 0 }, + "3965": { "label": "35/38", "naklon": 0 }, + "3970": { "label": "35/39", "naklon": 0 }, + "3611": { "label": "35/40", "naklon": 0 }, + "2635": { "label": "35/41", "naklon": 0 }, + "3978": { "label": "35/42", "naklon": 0 }, + "4213": { "label": "35/43", "naklon": 0 }, + "3984": { "label": "35/44", "naklon": 0 }, + "4218": { "label": "35/45", "naklon": 0 }, + "3973": { "label": "35/46", "naklon": 0 }, + "3974": { "label": "35/47", "naklon": 0 }, + "3759": { "label": "35/48", "naklon": 0 }, + "3844": { "label": "35/49", "naklon": 0 }, + "3804": { "label": "35/50", "naklon": 0 }, + "3831": { "label": "35/51", "naklon": 0 }, + "3643": { "label": "35/52", "naklon": 0 }, + "3966": { "label": "35/53", "naklon": 0 }, + "3971": { "label": "35/54", "naklon": 0 }, + "3650": { "label": "35/55", "naklon": 6 }, + "3651": { "label": "35/56", "naklon": 6 }, + "3669": { "label": "35/57", "naklon": 6 }, + "3648": { "label": "35/58", "naklon": 6 }, + "3645": { "label": "35/59", "naklon": 6 }, + "3659": { "label": "35/60", "naklon": 6 }, + "3647": { "label": "35/61", "naklon": 6 }, + "3644": { "label": "35/62", "naklon": 6 }, + "3671": { "label": "35/63", "naklon": 6 }, + "3682": { "label": "35/64", "naklon": 6 }, + "3672": { "label": "35/65", "naklon": 6 }, + "3683": { "label": "35/66", "naklon": 6 }, + "3673": { "label": "35/67", "naklon": 6 }, + "3674": { "label": "35/68", "naklon": 6 }, + "3679": { "label": "35/69", "naklon": 6 }, + "3649": { "label": "35/70", "naklon": 6 }, + "3687": { "label": "35/71", "naklon": 6 }, + "3677": { "label": "35/72", "naklon": 6 }, + "3690": { "label": "35/73", "naklon": 6 }, + "3691": { "label": "35/74", "naklon": 6 }, + "3676": { "label": "35/75", "naklon": 6 }, + "3680": { "label": "35/76", "naklon": 6 }, + "3668": { "label": "35/77", "naklon": 6 }, + "3681": { "label": "35/78", "naklon": 6 }, + "3670": { "label": "35/79", "naklon": 6 }, + "3689": { "label": "35/80", "naklon": 6 }, + "3678": { "label": "35/81", "naklon": 6 }, + "3693": { "label": "35/82", "naklon": 6 }, + "3654": { "label": "35/83", "naklon": null }, + "4086": { "label": "36/1", "naklon": 0 }, + "4085": { "label": "36/2", "naklon": 0 }, + "4083": { "label": "36/3", "naklon": 0 }, + "4087": { "label": "36/4", "naklon": 0 }, + "4077": { "label": "36/5", "naklon": 0 }, + "4082": { "label": "36/6", "naklon": 0 }, + "4186": { "label": "36/7", "naklon": 0 }, + "4206": { "label": "36/8", "naklon": 0 }, + "4080": { "label": "36/9", "naklon": 0 }, + "4081": { "label": "36/10", "naklon": 0 }, + "4210": { "label": "36/11", "naklon": 0 }, + "4079": { "label": "36/12", "naklon": 0 }, + "4076": { "label": "36/13", "naklon": 0 }, + "3852": { "label": "36/14", "naklon": 0 }, + "2813": { "label": "36/15", "naklon": 0 }, + "4219": { "label": "36/16", "naklon": 0 }, + "3104": { "label": "37/1A", "naklon": 15 }, + "3121": { "label": "37/1B", "naklon": 15 }, + "3113": { "label": "37/2", "naklon": 10 }, + "3118": { "label": "37/3", "naklon": 10 }, + "3111": { "label": "37/4", "naklon": 10 }, + "4020": { "label": "37/5", "naklon": 10 }, + "3119": { "label": "37/6", "naklon": 10 }, + "3110": { "label": "37/7", "naklon": 10 }, + "3108": { "label": "37/8", "naklon": 10 }, + "3107": { "label": "37/12", "naklon": 0 }, + "3199": { "label": "37/13", "naklon": 0 }, + "3120": { "label": "37/14", "naklon": 0 }, + "3122": { "label": "37/15", "naklon": 0 }, + "3908": { "label": "37/16", "naklon": 0 }, + "3114": { "label": "37/17", "naklon": 0 }, + "3105": { "label": "37/18", "naklon": 0 }, + "3116": { "label": "37/19", "naklon": 0 }, + "3106": { "label": "37/20", "naklon": 0 }, + "2887": { "label": "37/21", "naklon": 5 }, + "2888": { "label": "37/22", "naklon": 5 }, + "2877": { "label": "37/23", "naklon": 5 }, + "2891": { "label": "37/24", "naklon": 5 }, + "2886": { "label": "37/25", "naklon": 5 }, + "2892": { "label": "37/26", "naklon": 5 }, + "2882": { "label": "37/27", "naklon": 5 }, + "2883": { "label": "37/28", "naklon": 5 }, + "2876": { "label": "37/29", "naklon": 5 }, + "3109": { "label": "37/30", "naklon": 5 }, + "4152": { "label": "37/31", "naklon": 5 }, + "3117": { "label": "37/32", "naklon": 5 }, + "2870": { "label": "37/33", "naklon": 5 }, + "2867": { "label": "37/34", "naklon": 0 }, + "2865": { "label": "37/35", "naklon": 0 }, + "3096": { "label": "37/36", "naklon": 0 }, + "2871": { "label": "37/37", "naklon": 0 }, + "2884": { "label": "37/38", "naklon": 0 }, + "2855": { "label": "37/39", "naklon": 0 }, + "2878": { "label": "37/40", "naklon": 0 }, + "2889": { "label": "37/41", "naklon": 0 }, + "2879": { "label": "37/42", "naklon": 0 }, + "2850": { "label": "37/43", "naklon": 0 }, + "2894": { "label": "37/44", "naklon": 0 }, + "2880": { "label": "37/45", "naklon": 0 }, + "2893": { "label": "37/46", "naklon": 0 }, + "2890": { "label": "37/47", "naklon": 0 }, + "4355": { "label": "37/48", "naklon": 0 }, + "2885": { "label": "37/49", "naklon": 0 }, + "2875": { "label": "37/50", "naklon": 0 }, + "3486": { "label": "38/30A", "naklon": 5 }, + "3714": { "label": "38/30B", "naklon": 0 }, + "3483": { "label": "38/32A", "naklon": 5 }, + "3496": { "label": "38/32B", "naklon": 0 }, + "3487": { "label": "38/35A", "naklon": 5 }, + "3498": { "label": "38/35B", "naklon": 5 }, + "3578": { "label": "38/38A", "naklon": 5 }, + "3508": { "label": "38/38B", "naklon": 5 }, + "3787": { "label": "38/59A", "naklon": 5 }, + "3491": { "label": "38/59B", "naklon": 5 }, + "3568": { "label": "38/1", "naklon": null }, + "3502": { "label": "38/2", "naklon": 0 }, + "3836": { "label": "38/3", "naklon": 0 }, + "3588": { "label": "38/4", "naklon": 0 }, + "3493": { "label": "38/5", "naklon": 0 }, + "3580": { "label": "38/6", "naklon": 0 }, + "3572": { "label": "38/7", "naklon": 0 }, + "3506": { "label": "38/8", "naklon": 0 }, + "3503": { "label": "38/9", "naklon": 0 }, + "3579": { "label": "38/10", "naklon": 0 }, + "3586": { "label": "38/11", "naklon": 0 }, + "3495": { "label": "38/12", "naklon": 5 }, + "3492": { "label": "38/13", "naklon": 5 }, + "3532": { "label": "38/14", "naklon": 5 }, + "3574": { "label": "38/15", "naklon": 5 }, + "4140": { "label": "38/16", "naklon": 5 }, + "3795": { "label": "38/17", "naklon": 5 }, + "3788": { "label": "38/18", "naklon": 5 }, + "3796": { "label": "38/19", "naklon": 5 }, + "3797": { "label": "38/20", "naklon": 5 }, + "3798": { "label": "38/21", "naklon": 5 }, + "3786": { "label": "38/22", "naklon": 5 }, + "4067": { "label": "38/23", "naklon": 5 }, + "3773": { "label": "38/24", "naklon": 5 }, + "3774": { "label": "38/25", "naklon": 5 }, + "3789": { "label": "38/26", "naklon": 5 }, + "3520": { "label": "38/27", "naklon": null }, + "3577": { "label": "38/29", "naklon": 5 }, + "3530": { "label": "38/31", "naklon": null }, + "3488": { "label": "38/33", "naklon": 5 }, + "3505": { "label": "38/34", "naklon": 5 }, + "3497": { "label": "38/36", "naklon": 5 }, + "3490": { "label": "38/37", "naklon": 5 }, + "3585": { "label": "38/39", "naklon": 5 }, + "3582": { "label": "38/40", "naklon": 5 }, + "3507": { "label": "38/41", "naklon": 5 }, + "3484": { "label": "38/42", "naklon": 5 }, + "3501": { "label": "38/43", "naklon": 5 }, + "3581": { "label": "38/44", "naklon": 5 }, + "4192": { "label": "38/45", "naklon": 5 }, + "3576": { "label": "38/46", "naklon": 5 }, + "3489": { "label": "38/47", "naklon": 5 }, + "3573": { "label": "38/48", "naklon": 5 }, + "3504": { "label": "38/49", "naklon": 5 }, + "3794": { "label": "38/50", "naklon": 5 }, + "3485": { "label": "38/51", "naklon": 5 }, + "3482": { "label": "38/52", "naklon": 5 }, + "3575": { "label": "38/53", "naklon": 5 }, + "3499": { "label": "38/54", "naklon": 5 }, + "3494": { "label": "38/55", "naklon": 5 }, + "3583": { "label": "38/56", "naklon": 5 }, + "3570": { "label": "38/57", "naklon": 5 }, + "3500": { "label": "38/58", "naklon": 0 }, + "3510": { "label": "38/63", "naklon": null }, + "3512": { "label": "38/64", "naklon": null }, + "3535": { "label": "38/67", "naklon": null }, + "3531": { "label": "38/68", "naklon": null }, + "3537": { "label": "38/69", "naklon": null }, + "3522": { "label": "39/1", "naklon": 10 }, + "4018": { "label": "39/2", "naklon": 10 }, + "4019": { "label": "39/3", "naklon": 10 }, + "4154": { "label": "39/4", "naklon": 5 }, + "3907": { "label": "39/5", "naklon": 5 }, + "4148": { "label": "39/6", "naklon": 0 }, + "4153": { "label": "39/7", "naklon": 0 }, + "3938": { "label": "39/8", "naklon": 0 }, + "3802": { "label": "39/9", "naklon": 0 }, + "4015": { "label": "39/10", "naklon": 0 }, + "3929": { "label": "39/11", "naklon": 0 }, + "3946": { "label": "39/12", "naklon": 0 }, + "4014": { "label": "39/13", "naklon": 0 }, + "4155": { "label": "39/14", "naklon": 0 }, + "4149": { "label": "39/15", "naklon": 0 }, + "3642": { "label": "39/16", "naklon": 0 }, + "3636": { "label": "39/17", "naklon": 5 }, + "3991": { "label": "39/18", "naklon": 0 }, + "3994": { "label": "39/19", "naklon": 0 }, + "3990": { "label": "39/20", "naklon": 0 }, + "3967": { "label": "39/21", "naklon": 0 }, + "3977": { "label": "39/22", "naklon": 0 }, + "3757": { "label": "39/23", "naklon": 15 }, + "3633": { "label": "39/24", "naklon": 15 }, + "3744": { "label": "39/25", "naklon": 15 }, + "4023": { "label": "39/26", "naklon": 5 }, + "3720": { "label": "39/27", "naklon": 5 }, + "3734": { "label": "39/28", "naklon": 5 }, + "3741": { "label": "39/29", "naklon": 5 }, + "3721": { "label": "39/30", "naklon": 5 }, + "3845": { "label": "39/31", "naklon": 0 }, + "3840": { "label": "39/32", "naklon": 0 }, + "3837": { "label": "39/33", "naklon": null }, + "3839": { "label": "39/34", "naklon": 0 }, + "3542": { "label": "41/1", "naklon": null }, + "3566": { "label": "41/2", "naklon": null }, + "3548": { "label": "41/3", "naklon": null }, + "3515": { "label": "41/4", "naklon": null }, + "3559": { "label": "41/5", "naklon": null }, + "3509": { "label": "41/6", "naklon": null }, + "3524": { "label": "41/7", "naklon": null }, + "3518": { "label": "41/8", "naklon": null }, + "3182": { "label": "41/9", "naklon": null }, + "3187": { "label": "41/10", "naklon": null }, + "3195": { "label": "41/11", "naklon": 0 }, + "3857": { "label": "41/12", "naklon": 0 }, + "3183": { "label": "41/13", "naklon": 0 }, + "3177": { "label": "41/14", "naklon": 0 }, + "3189": { "label": "41/15", "naklon": 0 }, + "3186": { "label": "41/16", "naklon": 0 }, + "3178": { "label": "42/1", "naklon": 0 }, + "3219": { "label": "42/2", "naklon": 0 }, + "3475": { "label": "42/3", "naklon": 0 }, + "3175": { "label": "42/4", "naklon": 0 }, + "3222": { "label": "42/5", "naklon": 0 }, + "3221": { "label": "42/6", "naklon": 0 }, + "3181": { "label": "42/7", "naklon": 0 }, + "3180": { "label": "42/8", "naklon": 0 }, + "3218": { "label": "42/9", "naklon": 0 }, + "3176": { "label": "42/10", "naklon": 0 }, + "3174": { "label": "42/11", "naklon": 0 }, + "3220": { "label": "42/12", "naklon": 0 }, + "3533": { "label": "42/13", "naklon": null }, + "3543": { "label": "42/14", "naklon": null }, + "3554": { "label": "42/15", "naklon": null }, + "3549": { "label": "42/16", "naklon": null }, + "2857": { "label": "43/1", "naklon": 5 }, + "2752": { "label": "43/2", "naklon": 5 }, + "2753": { "label": "43/3", "naklon": 5 }, + "3024": { "label": "43/4", "naklon": 5 }, + "2754": { "label": "43/5", "naklon": 5 }, + "4423": { "label": "43/6", "naklon": 5 }, + "4368": { "label": "43/7", "naklon": 5 }, + "2978": { "label": "43/8", "naklon": 5 }, + "2868": { "label": "43/9", "naklon": 5 }, + "4377": { "label": "43/10", "naklon": 5 }, + "2757": { "label": "43/11", "naklon": 5 }, + "2970": { "label": "43/12", "naklon": 5 }, + "2758": { "label": "43/13", "naklon": 5 }, + "4378": { "label": "43/14", "naklon": 5 }, + "2759": { "label": "43/15", "naklon": 5 }, + "4342": { "label": "43/16", "naklon": 5 }, + "3026": { "label": "43/17", "naklon": null }, + "2986": { "label": "43/18", "naklon": null }, + "4343": { "label": "43/19", "naklon": null }, + "2760": { "label": "43/20", "naklon": null }, + "4379": { "label": "43/21", "naklon": null }, + "2971": { "label": "43/22", "naklon": null }, + "2761": { "label": "43/23", "naklon": null }, + "2762": { "label": "43/24", "naklon": null }, + "4339": { "label": "43/25", "naklon": null }, + "4380": { "label": "43/26", "naklon": null }, + "2975": { "label": "43/27", "naklon": null }, + "3003": { "label": "43/28", "naklon": null }, + "4338": { "label": "43/29", "naklon": null }, + "3002": { "label": "43/30", "naklon": null }, + "4345": { "label": "43/31", "naklon": null }, + "2979": { "label": "43/32", "naklon": null }, + "2989": { "label": "43/33", "naklon": null }, + "2996": { "label": "43/34", "naklon": null }, + "2972": { "label": "43/35", "naklon": null }, + "2988": { "label": "43/36", "naklon": null }, + "4344": { "label": "43/37", "naklon": null }, + "3022": { "label": "43/38", "naklon": null }, + "4341": { "label": "43/39", "naklon": null }, + "2983": { "label": "43/40", "naklon": null }, + "2995": { "label": "43/41", "naklon": null }, + "2763": { "label": "43/42", "naklon": null }, + "2764": { "label": "43/43", "naklon": null }, + "2765": { "label": "43/44", "naklon": null }, + "2766": { "label": "43/45", "naklon": null }, + "2767": { "label": "43/46", "naklon": null }, + "2768": { "label": "43/47", "naklon": null }, + "3018": { "label": "43/48", "naklon": null }, + "2982": { "label": "43/49", "naklon": null }, + "3019": { "label": "43/50", "naklon": 0 }, + "3013": { "label": "43/51", "naklon": null }, + "3007": { "label": "43/52", "naklon": null }, + "2980": { "label": "43/53", "naklon": null }, + "3011": { "label": "43/54", "naklon": null }, + "2672": { "label": "43/55", "naklon": null }, + "2673": { "label": "43/56", "naklon": null }, + "2674": { "label": "43/57", "naklon": null }, + "2675": { "label": "43/58", "naklon": null }, + "2676": { "label": "43/59", "naklon": null }, + "2677": { "label": "43/60", "naklon": null }, + "2678": { "label": "43/61", "naklon": null }, + "2679": { "label": "43/62", "naklon": null }, + "2680": { "label": "43/63", "naklon": null }, + "2840": { "label": "43/64", "naklon": null }, + "2682": { "label": "43/65", "naklon": null }, + "2683": { "label": "43/66", "naklon": null }, + "2684": { "label": "43/67", "naklon": 0 }, + "2685": { "label": "43/68", "naklon": null }, + "2686": { "label": "43/69", "naklon": null }, + "2687": { "label": "43/70", "naklon": null }, + "2688": { "label": "43/71", "naklon": null }, + "2689": { "label": "43/72", "naklon": null }, + "2690": { "label": "43/73", "naklon": null }, + "2691": { "label": "43/74", "naklon": null }, + "2692": { "label": "43/75", "naklon": null }, + "2693": { "label": "43/76", "naklon": 0 }, + "2694": { "label": "43/77", "naklon": null }, + "2695": { "label": "43/78", "naklon": null }, + "2696": { "label": "43/79", "naklon": 0 }, + "2697": { "label": "43/80", "naklon": null }, + "2698": { "label": "43/81", "naklon": 0 }, + "2699": { "label": "43/82", "naklon": null }, + "2700": { "label": "43/83", "naklon": 0 }, + "2744": { "label": "43/84", "naklon": null }, + "2745": { "label": "43/85", "naklon": 0 }, + "2746": { "label": "43/86", "naklon": null }, + "2747": { "label": "43/87", "naklon": 0 }, + "2748": { "label": "43/88", "naklon": null }, + "2749": { "label": "43/89", "naklon": 0 }, + "2841": { "label": "43/90", "naklon": null }, + "4237": { "label": "45/1", "naklon": 5 }, + "4226": { "label": "45/2", "naklon": 5 }, + "4242": { "label": "45/3", "naklon": 5 }, + "4179": { "label": "45/4", "naklon": 5 }, + "4247": { "label": "45/5", "naklon": 5 }, + "4245": { "label": "45/6", "naklon": 5 }, + "3872": { "label": "45/7", "naklon": 5 }, + "4175": { "label": "45/8", "naklon": 5 }, + "4236": { "label": "45/9", "naklon": 5 }, + "4170": { "label": "45/10", "naklon": 5 }, + "4238": { "label": "45/11", "naklon": 5 }, + "4246": { "label": "45/12", "naklon": 5 }, + "4166": { "label": "45/13", "naklon": 5 }, + "4227": { "label": "45/14", "naklon": 5 }, + "4171": { "label": "45/15", "naklon": 5 }, + "4180": { "label": "45/16", "naklon": 5 }, + "4244": { "label": "45/17", "naklon": 5 }, + "4199": { "label": "45/18", "naklon": 5 }, + "4239": { "label": "45/19", "naklon": 5 }, + "4207": { "label": "45/20", "naklon": 5 }, + "4223": { "label": "45/21", "naklon": 5 }, + "4230": { "label": "45/22", "naklon": 5 }, + "4233": { "label": "45/23", "naklon": 5 }, + "4222": { "label": "45/24", "naklon": 5 }, + "4217": { "label": "45/25", "naklon": 5 }, + "4243": { "label": "45/26", "naklon": 5 }, + "4200": { "label": "45/27", "naklon": 5 }, + "4228": { "label": "45/28", "naklon": 5 }, + "4211": { "label": "45/29", "naklon": 5 }, + "4234": { "label": "45/30", "naklon": 5 }, + "4235": { "label": "45/31", "naklon": 5 }, + "4203": { "label": "45/32", "naklon": 5 }, + "4240": { "label": "45/33", "naklon": 5 }, + "4224": { "label": "45/34", "naklon": 5 }, + "4232": { "label": "45/35", "naklon": 5 }, + "4231": { "label": "45/36", "naklon": 5 }, + "4161": { "label": "45/37", "naklon": 5 }, + "4225": { "label": "45/38", "naklon": 5 }, + "4241": { "label": "45/39", "naklon": 5 }, + "4229": { "label": "45/40", "naklon": 5 }, + "4221": { "label": "45/41", "naklon": 5 }, + "4212": { "label": "45/42", "naklon": 5 }, + "4216": { "label": "45/43", "naklon": 5 }, + "3864": { "label": "45/44", "naklon": null }, + "3806": { "label": "46/1", "naklon": 5 }, + "3813": { "label": "46/2", "naklon": 5 }, + "3815": { "label": "46/3", "naklon": 5 }, + "3807": { "label": "46/4", "naklon": 5 }, + "3895": { "label": "46/5", "naklon": 5 }, + "3809": { "label": "46/6", "naklon": 5 }, + "3820": { "label": "46/7", "naklon": 5 }, + "3805": { "label": "46/8", "naklon": 5 }, + "3894": { "label": "46/9", "naklon": 0 }, + "4055": { "label": "46/10", "naklon": 0 }, + "3812": { "label": "46/11", "naklon": 5 }, + "3822": { "label": "46/12", "naklon": 5 }, + "3821": { "label": "46/13", "naklon": 5 }, + "3808": { "label": "46/14", "naklon": 5 }, + "3799": { "label": "46/15", "naklon": 5 }, + "3816": { "label": "46/16", "naklon": 5 }, + "3751": { "label": "46/17", "naklon": 5 }, + "3814": { "label": "46/18", "naklon": 5 }, + "4044": { "label": "46/19", "naklon": 0 }, + "3931": { "label": "46/20", "naklon": 0 }, + "3902": { "label": "46/21", "naklon": 5 }, + "3916": { "label": "46/22", "naklon": 5 }, + "3892": { "label": "46/23", "naklon": 5 }, + "3914": { "label": "46/24", "naklon": 5 }, + "3898": { "label": "46/25", "naklon": 5 }, + "3897": { "label": "46/26", "naklon": 5 }, + "3885": { "label": "46/27", "naklon": 5 }, + "3906": { "label": "46/28", "naklon": 5 }, + "3930": { "label": "46/29", "naklon": 0 }, + "3936": { "label": "46/30", "naklon": 0 }, + "3860": { "label": "46/31", "naklon": 5 }, + "3841": { "label": "46/32", "naklon": 5 }, + "3873": { "label": "46/33", "naklon": 5 }, + "3854": { "label": "46/34", "naklon": 5 }, + "3939": { "label": "46/35", "naklon": 5 }, + "3858": { "label": "46/36", "naklon": 5 }, + "3940": { "label": "46/37", "naklon": 5 }, + "4035": { "label": "46/38", "naklon": 5 }, + "3373": { "label": "47/1", "naklon": 0 }, + "3374": { "label": "47/2", "naklon": 0 }, + "3384": { "label": "47/3", "naklon": 0 }, + "3385": { "label": "47/4", "naklon": 0 }, + "4051": { "label": "48/1", "naklon": 5 }, + "4041": { "label": "48/2", "naklon": 5 }, + "4056": { "label": "48/3", "naklon": 5 }, + "3875": { "label": "48/4", "naklon": 5 }, + "4061": { "label": "48/5", "naklon": 5 }, + "4047": { "label": "48/6", "naklon": 5 }, + "4060": { "label": "48/7", "naklon": 5 }, + "4059": { "label": "48/8", "naklon": 5 }, + "4058": { "label": "48/9", "naklon": 5 }, + "3635": { "label": "48/10", "naklon": 5 }, + "3640": { "label": "48/11", "naklon": 5 }, + "3747": { "label": "48/12", "naklon": 5 }, + "3629": { "label": "48/13", "naklon": 5 }, + "4048": { "label": "48/14", "naklon": 5 }, + "4063": { "label": "48/15", "naklon": 5 }, + "4062": { "label": "48/16", "naklon": 5 }, + "4043": { "label": "48/17", "naklon": 5 }, + "4052": { "label": "48/18", "naklon": 5 }, + "4042": { "label": "48/19", "naklon": 5 }, + "4053": { "label": "48/20", "naklon": 5 }, + "4167": { "label": "50/15A", "naklon": null }, + "4159": { "label": "50/15B", "naklon": null }, + "4183": { "label": "50/1", "naklon": 0 }, + "4157": { "label": "50/2", "naklon": 0 }, + "4160": { "label": "50/3", "naklon": 0 }, + "4173": { "label": "50/4", "naklon": 0 }, + "4177": { "label": "50/5", "naklon": 0 }, + "4174": { "label": "50/6", "naklon": 0 }, + "4178": { "label": "50/7", "naklon": 0 }, + "4195": { "label": "50/8", "naklon": 0 }, + "4169": { "label": "50/9", "naklon": 0 }, + "4162": { "label": "50/10", "naklon": 0 }, + "4158": { "label": "50/11", "naklon": 0 }, + "4182": { "label": "50/12", "naklon": 0 }, + "4194": { "label": "50/13", "naklon": 0 }, + "4184": { "label": "50/14", "naklon": 0 }, + "4197": { "label": "50/16", "naklon": null }, + "4164": { "label": "50/17", "naklon": null }, + "3306": { "label": "50/18", "naklon": null }, + "4168": { "label": "50/19", "naklon": null }, + "4193": { "label": "50/20", "naklon": null }, + "4187": { "label": "50/21", "naklon": null }, + "4163": { "label": "50/22", "naklon": null }, + "4165": { "label": "50/23", "naklon": null }, + "4185": { "label": "50/24", "naklon": null }, + "3904": { "label": "50/25", "naklon": null }, + "2619": { "label": "53/1", "naklon": 0 }, + "2623": { "label": "53/2", "naklon": 0 }, + "2617": { "label": "53/3", "naklon": 0 }, + "2622": { "label": "53/4", "naklon": 0 }, + "2618": { "label": "53/5", "naklon": 0 }, + "2626": { "label": "53/6", "naklon": 0 }, + "2869": { "label": "53/7", "naklon": 0 }, + "2613": { "label": "53/8", "naklon": 0 }, + "2608": { "label": "53/9", "naklon": 0 }, + "2611": { "label": "53/10", "naklon": 0 }, + "2598": { "label": "53/11", "naklon": 0 }, + "3528": { "label": "53/12", "naklon": 0 }, + "3545": { "label": "53/13", "naklon": 0 }, + "2620": { "label": "53/14", "naklon": 0 }, + "2612": { "label": "53/15", "naklon": 0 }, + "2615": { "label": "53/16", "naklon": 0 }, + "3722": { "label": "53/17", "naklon": 0 }, + "2624": { "label": "53/18", "naklon": 0 }, + "2609": { "label": "53/19", "naklon": 0 }, + "2625": { "label": "53/20", "naklon": 0 }, + "2602": { "label": "53/21", "naklon": 0 }, + "2610": { "label": "53/22", "naklon": 0 }, + "2599": { "label": "53/23", "naklon": 0 }, + "2605": { "label": "53/24", "naklon": 0 }, + "2593": { "label": "53/25", "naklon": 0 }, + "3074": { "label": "53/26", "naklon": 0 }, + "2740": { "label": "53/27", "naklon": 0 }, + "2614": { "label": "53/28", "naklon": 0 }, + "2601": { "label": "53/29", "naklon": 0 }, + "4196": { "label": "53/30", "naklon": 0 }, + "2607": { "label": "53/31", "naklon": 0 }, + "2582": { "label": "53/32", "naklon": 0 }, + "2594": { "label": "53/33", "naklon": 0 }, + "2589": { "label": "53/34", "naklon": 0 }, + "2596": { "label": "53/35", "naklon": 0 }, + "2603": { "label": "53/36", "naklon": 0 }, + "2597": { "label": "53/37", "naklon": 0 }, + "2590": { "label": "53/38", "naklon": 0 }, + "2581": { "label": "53/39", "naklon": 0 }, + "2583": { "label": "53/40", "naklon": 0 }, + "2580": { "label": "53/41", "naklon": 0 }, + "2579": { "label": "53/42", "naklon": 0 }, + "2797": { "label": "53/43", "naklon": 0 }, + "2577": { "label": "53/44", "naklon": 0 }, + "2586": { "label": "53/45", "naklon": 0 }, + "2588": { "label": "53/46", "naklon": 0 }, + "2591": { "label": "53/47", "naklon": 0 }, + "2592": { "label": "53/48", "naklon": 0 }, + "2573": { "label": "53/49", "naklon": 0 }, + "2595": { "label": "53/50", "naklon": 0 }, + "2587": { "label": "53/51", "naklon": 0 }, + "2578": { "label": "53/52", "naklon": 0 }, + "2574": { "label": "53/53", "naklon": 0 }, + "2571": { "label": "53/54", "naklon": 0 }, + "2570": { "label": "53/55", "naklon": 0 }, + "2576": { "label": "53/56", "naklon": 0 }, + "2881": { "label": "53/57", "naklon": 0 }, + "2575": { "label": "53/58", "naklon": 0 }, + "2572": { "label": "53/59", "naklon": 0 }, + "2569": { "label": "53/60", "naklon": 0 }, + "4324": { "label": "55/1", "naklon": 0 }, + "4319": { "label": "55/2", "naklon": 0 }, + "4327": { "label": "55/3", "naklon": 0 }, + "4333": { "label": "55/4", "naklon": 0 }, + "4332": { "label": "55/5", "naklon": 0 }, + "4320": { "label": "55/6", "naklon": 0 }, + "4317": { "label": "55/7", "naklon": 0 }, + "4318": { "label": "55/8", "naklon": 0 }, + "4328": { "label": "55/9", "naklon": 0 }, + "4323": { "label": "55/10", "naklon": 0 }, + "4325": { "label": "55/11", "naklon": 0 }, + "4326": { "label": "55/12", "naklon": 0 }, + "4316": { "label": "55/13", "naklon": 0 }, + "4322": { "label": "55/14", "naklon": 0 }, + "4331": { "label": "55/15", "naklon": 0 }, + "4321": { "label": "55/16", "naklon": 0 }, + "4315": { "label": "55/17", "naklon": 0 }, + "4329": { "label": "55/18", "naklon": 0 }, + "4334": { "label": "55/19", "naklon": 0 }, + "4330": { "label": "55/20", "naklon": 0 } +}; + + +let svetlaSorted = [{ "label": "1/3A", "node": 3993, "naklon": 0 }, +{ "label": "1/3B", "node": 3989, "naklon": 15 }, +{ "label": "1/1", "node": 3976, "naklon": 0 }, +{ "label": "1/2", "node": 4181, "naklon": 0 }, +{ "label": "1/4", "node": 4376, "naklon": 15 }, +{ "label": "1/5", "node": 3868, "naklon": 15 }, +{ "label": "1/6", "node": 3728, "naklon": 15 }, +{ "label": "1/7", "node": 3730, "naklon": 0 }, +{ "label": "1/8", "node": 4374, "naklon": 0 }, +{ "label": "1/9", "node": 3718, "naklon": 15 }, +{ "label": "1/10", "node": 4375, "naklon": 15 }, +{ "label": "1/11", "node": 4172, "naklon": 15 }, +{ "label": "1/12", "node": 4176, "naklon": 15 }, +{ "label": "2/1", "node": 3800, "naklon": 5 }, +{ "label": "2/2", "node": 3823, "naklon": 5 }, +{ "label": "2/3", "node": 3905, "naklon": 5 }, +{ "label": "2/4", "node": 3803, "naklon": 5 }, +{ "label": "2/5", "node": 3817, "naklon": 5 }, +{ "label": "2/6", "node": 3818, "naklon": 5 }, +{ "label": "2/7", "node": 3811, "naklon": 5 }, +{ "label": "2/8", "node": 3915, "naklon": 5 }, +{ "label": "2/9", "node": 3843, "naklon": 10 }, +{ "label": "2/10", "node": 3827, "naklon": 10 }, +{ "label": "2/11", "node": 4220, "naklon": 10 }, +{ "label": "2/12", "node": 3826, "naklon": 10 }, +{ "label": "2/13", "node": 3834, "naklon": 10 }, +{ "label": "2/14", "node": 3838, "naklon": 10 }, +{ "label": "2/15", "node": 2823, "naklon": 10 }, +{ "label": "2/16", "node": 3750, "naklon": 10 }, +{ "label": "2/17", "node": 3378, "naklon": 0 }, +{ "label": "2/18", "node": 3376, "naklon": 0 }, +{ "label": "2/19", "node": 3379, "naklon": 0 }, +{ "label": "2/20", "node": 3285, "naklon": 0 }, +{ "label": "2/21", "node": 3382, "naklon": 0 }, +{ "label": "2/22", "node": 3383, "naklon": 0 }, +{ "label": "2/24", "node": 3375, "naklon": 0 }, +{ "label": "2/25", "node": 3381, "naklon": 0 }, +{ "label": "2/26", "node": 3380, "naklon": 0 }, +{ "label": "2/27", "node": 3828, "naklon": 10 }, +{ "label": "2/28", "node": 3377, "naklon": 0 }, +{ "label": "7/1", "node": 3591, "naklon": 0 }, +{ "label": "7/2", "node": 3587, "naklon": 0 }, +{ "label": "7/3", "node": 3468, "naklon": 0 }, +{ "label": "7/4", "node": 3466, "naklon": 0 }, +{ "label": "7/5", "node": 3474, "naklon": 0 }, +{ "label": "7/6", "node": 3481, "naklon": 0 }, +{ "label": "7/7", "node": 3589, "naklon": 0 }, +{ "label": "7/8", "node": 3472, "naklon": 0 }, +{ "label": "7/9", "node": 3473, "naklon": 0 }, +{ "label": "7/10", "node": 3584, "naklon": 0 }, +{ "label": "7/11", "node": 3571, "naklon": 0 }, +{ "label": "7/12", "node": 3476, "naklon": 0 }, +{ "label": "7/13", "node": 3590, "naklon": 0 }, +{ "label": "7/14", "node": 3478, "naklon": 0 }, +{ "label": "7/15", "node": 3471, "naklon": 0 }, +{ "label": "7/16", "node": 3467, "naklon": 0 }, +{ "label": "7/17", "node": 3479, "naklon": 0 }, +{ "label": "7/18", "node": 3480, "naklon": 0 }, +{ "label": "7/19", "node": 3477, "naklon": 0 }, +{ "label": "12/1", "node": 3362, "naklon": 0 }, +{ "label": "12/2", "node": 3355, "naklon": 0 }, +{ "label": "12/3", "node": 3356, "naklon": 0 }, +{ "label": "12/4", "node": 3349, "naklon": 0 }, +{ "label": "12/5", "node": 3357, "naklon": 0 }, +{ "label": "12/6", "node": 3350, "naklon": 0 }, +{ "label": "12/7", "node": 3353, "naklon": 0 }, +{ "label": "12/8", "node": 3539, "naklon": 0 }, +{ "label": "12/9", "node": 3050, "naklon": 0 }, +{ "label": "12/10", "node": 3361, "naklon": 0 }, +{ "label": "12/11", "node": 3360, "naklon": 0 }, +{ "label": "12/12", "node": 3358, "naklon": 0 }, +{ "label": "12/13", "node": 3541, "naklon": 0 }, +{ "label": "12/14", "node": 3551, "naklon": 0 }, +{ "label": "12/15", "node": 3514, "naklon": 0 }, +{ "label": "12/16", "node": 3547, "naklon": 0 }, +{ "label": "12/17", "node": 3562, "naklon": 0 }, +{ "label": "12/18", "node": 3525, "naklon": 0 }, +{ "label": "12/19", "node": 3558, "naklon": 0 }, +{ "label": "12/20", "node": 3511, "naklon": 0 }, +{ "label": "12/21", "node": 3058, "naklon": 0 }, +{ "label": "12/22", "node": 3062, "naklon": 0 }, +{ "label": "12/23", "node": 3070, "naklon": 0 }, +{ "label": "12/24", "node": 3447, "naklon": 0 }, +{ "label": "12/25", "node": 3056, "naklon": 0 }, +{ "label": "12/26", "node": 3057, "naklon": 0 }, +{ "label": "12/27", "node": 3071, "naklon": 0 }, +{ "label": "12/28", "node": 3061, "naklon": 0 }, +{ "label": "12/29", "node": 3069, "naklon": 0 }, +{ "label": "12/30", "node": 3077, "naklon": 0 }, +{ "label": "12/31", "node": 3080, "naklon": 0 }, +{ "label": "12/32", "node": 3081, "naklon": 0 }, +{ "label": "12/33", "node": 3078, "naklon": 0 }, +{ "label": "12/34", "node": 4037, "naklon": 0 }, +{ "label": "12/35", "node": 3067, "naklon": 0 }, +{ "label": "12/36", "node": 3051, "naklon": 0 }, +{ "label": "12/37", "node": 2924, "naklon": 0 }, +{ "label": "12/38", "node": 3060, "naklon": 0 }, +{ "label": "12/39", "node": 3073, "naklon": 0 }, +{ "label": "12/40", "node": 3469, "naklon": 0 }, +{ "label": "12/41", "node": 2923, "naklon": 0 }, +{ "label": "12/42", "node": 2925, "naklon": 0 }, +{ "label": "12/43", "node": 3359, "naklon": 0 }, +{ "label": "12/44", "node": 3055, "naklon": 0 }, +{ "label": "12/45", "node": 2922, "naklon": 0 }, +{ "label": "12/46", "node": 3084, "naklon": 0 }, +{ "label": "12/47", "node": 3064, "naklon": 0 }, +{ "label": "12/48", "node": 3066, "naklon": 0 }, +{ "label": "12/49", "node": 3072, "naklon": 0 }, +{ "label": "13/13A", "node": 3415, "naklon": 0 }, +{ "label": "13/13B", "node": 3409, "naklon": 0 }, +{ "label": "13/13C", "node": 3399, "naklon": 0 }, +{ "label": "13/29A", "node": 3410, "naklon": 0 }, +{ "label": "13/29B", "node": 3407, "naklon": 0 }, +{ "label": "13/34A", "node": 3405, "naklon": 0 }, +{ "label": "13/34B", "node": 3404, "naklon": 0 }, +{ "label": "13/45A", "node": 3392, "naklon": 0 }, +{ "label": "13/45B", "node": 3386, "naklon": 0 }, +{ "label": "13/60A", "node": 3303, "naklon": 3 }, +{ "label": "13/60B", "node": 3302, "naklon": 3 }, +{ "label": "13/70A", "node": 3319, "naklon": 6 }, +{ "label": "13/70B", "node": 3317, "naklon": 6 }, +{ "label": "13/70C", "node": 3326, "naklon": 6 }, +{ "label": "13/73A", "node": 3351, "naklon": 6 }, +{ "label": "13/73B", "node": 3313, "naklon": 6 }, +{ "label": "13/83A", "node": 3316, "naklon": 0 }, +{ "label": "13/83B", "node": 3320, "naklon": 0 }, +{ "label": "13/95A", "node": 3336, "naklon": 0 }, +{ "label": "13/95B", "node": 3323, "naklon": 0 }, +{ "label": "13/98A", "node": 3339, "naklon": 0 }, +{ "label": "13/98B", "node": 3333, "naklon": 0 }, +{ "label": "13/1", "node": 3425, "naklon": 0 }, +{ "label": "13/2", "node": 3419, "naklon": 0 }, +{ "label": "13/3", "node": 3416, "naklon": 0 }, +{ "label": "13/4", "node": 3332, "naklon": 0 }, +{ "label": "13/5", "node": 3422, "naklon": 0 }, +{ "label": "13/6", "node": 3417, "naklon": 0 }, +{ "label": "13/7", "node": 3418, "naklon": 0 }, +{ "label": "13/8", "node": 3424, "naklon": 0 }, +{ "label": "13/9", "node": 3334, "naklon": 0 }, +{ "label": "13/10", "node": 4363, "naklon": 0 }, +{ "label": "13/11", "node": 3423, "naklon": 0 }, +{ "label": "13/12", "node": 3406, "naklon": 0 }, +{ "label": "13/14", "node": 3411, "naklon": 0 }, +{ "label": "13/15", "node": 3412, "naklon": 0 }, +{ "label": "13/16", "node": 3413, "naklon": 0 }, +{ "label": "13/17", "node": 3414, "naklon": 0 }, +{ "label": "13/18", "node": 3391, "naklon": 0 }, +{ "label": "13/19", "node": 3370, "naklon": 0 }, +{ "label": "13/20", "node": 3369, "naklon": 0 }, +{ "label": "13/21", "node": 3408, "naklon": 0 }, +{ "label": "13/22", "node": 3393, "naklon": 0 }, +{ "label": "13/23", "node": 3128, "naklon": 0 }, +{ "label": "13/24", "node": 3197, "naklon": 0 }, +{ "label": "13/25", "node": 4364, "naklon": 0 }, +{ "label": "13/26", "node": 3155, "naklon": 0 }, +{ "label": "13/27", "node": 3196, "naklon": 0 }, +{ "label": "13/28", "node": 3144, "naklon": 0 }, +{ "label": "13/30", "node": 3150, "naklon": 0 }, +{ "label": "13/31", "node": 3390, "naklon": 0 }, +{ "label": "13/32", "node": 3401, "naklon": 0 }, +{ "label": "13/33", "node": 3275, "naklon": 0 }, +{ "label": "13/35", "node": 3371, "naklon": 0 }, +{ "label": "13/36", "node": 3389, "naklon": 0 }, +{ "label": "13/37", "node": 3388, "naklon": 0 }, +{ "label": "13/38", "node": 3365, "naklon": 0 }, +{ "label": "13/39", "node": 3363, "naklon": 0 }, +{ "label": "13/40", "node": 3397, "naklon": 0 }, +{ "label": "13/40/1", "node": 3567, "naklon": 0 }, +{ "label": "13/41", "node": 3387, "naklon": 0 }, +{ "label": "13/42", "node": 3403, "naklon": 0 }, +{ "label": "13/43", "node": 3147, "naklon": 0 }, +{ "label": "13/44", "node": 3141, "naklon": 0 }, +{ "label": "13/46", "node": 3364, "naklon": 0 }, +{ "label": "13/47", "node": 3367, "naklon": 0 }, +{ "label": "13/48", "node": 3368, "naklon": 0 }, +{ "label": "13/49", "node": 3402, "naklon": 0 }, +{ "label": "13/50", "node": 3366, "naklon": 0 }, +{ "label": "13/51", "node": 3395, "naklon": 0 }, +{ "label": "13/52", "node": 3372, "naklon": 0 }, +{ "label": "13/53", "node": 3394, "naklon": 0 }, +{ "label": "13/54", "node": 3308, "naklon": 0 }, +{ "label": "13/54/1", "node": 3847, "naklon": 0 }, +{ "label": "13/55", "node": 3312, "naklon": 3 }, +{ "label": "13/56", "node": 3309, "naklon": 3 }, +{ "label": "13/57", "node": 3311, "naklon": 3 }, +{ "label": "13/58", "node": 3310, "naklon": 3 }, +{ "label": "13/59", "node": 4365, "naklon": 3 }, +{ "label": "13/60/1", "node": 4093, "naklon": 3 }, +{ "label": "13/61", "node": 3304, "naklon": 3 }, +{ "label": "13/62", "node": 3307, "naklon": 3 }, +{ "label": "13/63", "node": 3271, "naklon": 3 }, +{ "label": "13/64", "node": 3301, "naklon": 3 }, +{ "label": "13/65", "node": 4366, "naklon": 3 }, +{ "label": "13/66", "node": 3300, "naklon": 3 }, +{ "label": "13/67", "node": 3185, "naklon": 0 }, +{ "label": "13/68", "node": 3184, "naklon": 0 }, +{ "label": "13/69", "node": 3188, "naklon": 0 }, +{ "label": "13/71", "node": 3343, "naklon": 6 }, +{ "label": "13/71/1", "node": 3819, "naklon": 6 }, +{ "label": "13/71/2", "node": 3880, "naklon": 6 }, +{ "label": "13/72", "node": 3348, "naklon": 6 }, +{ "label": "13/74", "node": 3344, "naklon": 6 }, +{ "label": "13/75", "node": 3346, "naklon": 6 }, +{ "label": "13/75/1", "node": 3597, "naklon": 6 }, +{ "label": "13/76", "node": 3345, "naklon": 6 }, +{ "label": "13/77", "node": 3322, "naklon": 0 }, +{ "label": "13/78", "node": 3325, "naklon": 0 }, +{ "label": "13/78/1", "node": 4310, "naklon": 0 }, +{ "label": "13/79", "node": 3315, "naklon": 0 }, +{ "label": "13/80", "node": 3328, "naklon": 0 }, +{ "label": "13/81", "node": 3321, "naklon": 0 }, +{ "label": "13/82", "node": 3324, "naklon": 0 }, +{ "label": "13/84", "node": 3140, "naklon": 0 }, +{ "label": "13/85", "node": 3153, "naklon": 0 }, +{ "label": "13/86", "node": 3145, "naklon": 0 }, +{ "label": "13/87", "node": 3134, "naklon": 0 }, +{ "label": "13/88", "node": 3151, "naklon": 0 }, +{ "label": "13/89", "node": 3143, "naklon": 0 }, +{ "label": "13/90", "node": 3318, "naklon": 0 }, +{ "label": "13/91", "node": 3347, "naklon": 0 }, +{ "label": "13/94", "node": 3314, "naklon": 0 }, +{ "label": "13/96", "node": 3331, "naklon": 0 }, +{ "label": "13/97", "node": 3327, "naklon": 0 }, +{ "label": "13/99", "node": 3329, "naklon": 0 }, +{ "label": "13/100", "node": 3337, "naklon": 0 }, +{ "label": "13/101", "node": 3330, "naklon": 0 }, +{ "label": "13/102", "node": 3335, "naklon": 0 }, +{ "label": "13/103", "node": 3420, "naklon": 0 }, +{ "label": "13/104", "node": 3421, "naklon": 0 }, +{ "label": "13/105", "node": 4361, "naklon": 0 }, +{ "label": "13/106", "node": 4362, "naklon": 0 }, +{ "label": "13/107", "node": 3526, "naklon": 0 }, +{ "label": "13/108", "node": 4424, "naklon": null }, +{ "label": "13/109", "node": 3561, "naklon": null }, +{ "label": "13/110", "node": 3527, "naklon": null }, +{ "label": "13/111", "node": 3521, "naklon": null }, +{ "label": "13/112", "node": 3552, "naklon": null }, +{ "label": "13/113", "node": 3544, "naklon": null }, +{ "label": "13/114", "node": 3534, "naklon": null }, +{ "label": "13/115", "node": 3516, "naklon": null }, +{ "label": "13/116", "node": 3513, "naklon": null }, +{ "label": "13/117", "node": 3565, "naklon": null }, +{ "label": "13/118", "node": 3866, "naklon": null }, +{ "label": "14/1", "node": 3136, "naklon": 0 }, +{ "label": "14/2", "node": 3137, "naklon": 0 }, +{ "label": "14/3", "node": 3135, "naklon": 0 }, +{ "label": "14/4", "node": 3149, "naklon": 0 }, +{ "label": "14/5", "node": 3142, "naklon": 0 }, +{ "label": "14/6", "node": 3342, "naklon": 0 }, +{ "label": "14/7", "node": 3340, "naklon": 0 }, +{ "label": "14/8", "node": 3152, "naklon": 0 }, +{ "label": "14/9", "node": 3886, "naklon": 0 }, +{ "label": "14/10", "node": 3341, "naklon": null }, +{ "label": "14/11", "node": 3352, "naklon": null }, +{ "label": "15/1", "node": 3396, "naklon": 5 }, +{ "label": "15/2", "node": 2784, "naklon": 5 }, +{ "label": "15/3", "node": 2788, "naklon": 5 }, +{ "label": "15/4", "node": 2801, "naklon": 5 }, +{ "label": "15/5", "node": 2815, "naklon": 5 }, +{ "label": "15/6", "node": 2829, "naklon": 5 }, +{ "label": "15/7", "node": 2796, "naklon": 5 }, +{ "label": "15/8", "node": 2803, "naklon": 5 }, +{ "label": "15/8/1", "node": 4304, "naklon": 5 }, +{ "label": "15/8/2", "node": 4311, "naklon": 5 }, +{ "label": "15/9", "node": 2821, "naklon": 5 }, +{ "label": "15/10", "node": 3400, "naklon": 5 }, +{ "label": "15/11", "node": 2799, "naklon": 5 }, +{ "label": "15/12", "node": 2804, "naklon": 5 }, +{ "label": "15/12/1", "node": 4303, "naklon": 5 }, +{ "label": "15/12/2", "node": 4309, "naklon": 5 }, +{ "label": "15/13", "node": 2806, "naklon": 5 }, +{ "label": "15/14", "node": 2787, "naklon": 5 }, +{ "label": "15/15", "node": 2809, "naklon": 5 }, +{ "label": "15/16", "node": 2814, "naklon": 0 }, +{ "label": "15/17", "node": 3934, "naklon": 0 }, +{ "label": "15/18", "node": 3192, "naklon": 0 }, +{ "label": "15/19", "node": 2812, "naklon": 0 }, +{ "label": "15/20", "node": 4070, "naklon": 0 }, +{ "label": "15/21", "node": 2826, "naklon": 0 }, +{ "label": "15/22", "node": 2808, "naklon": 3 }, +{ "label": "15/23", "node": 2795, "naklon": 3 }, +{ "label": "15/24", "node": 2807, "naklon": 3 }, +{ "label": "15/25", "node": 2831, "naklon": 0 }, +{ "label": "15/26", "node": 2862, "naklon": null }, +{ "label": "15/27", "node": 2861, "naklon": 0 }, +{ "label": "15/28", "node": 2866, "naklon": 0 }, +{ "label": "15/28/1", "node": 3546, "naklon": 0 }, +{ "label": "15/29", "node": 4146, "naklon": 0 }, +{ "label": "15/29/1", "node": 3001, "naklon": 0 }, +{ "label": "15/30", "node": 2835, "naklon": 0 }, +{ "label": "15/31", "node": 2874, "naklon": 0 }, +{ "label": "15/32", "node": 2852, "naklon": 0 }, +{ "label": "15/33", "node": 2851, "naklon": 0 }, +{ "label": "15/33/1", "node": 3560, "naklon": 0 }, +{ "label": "15/34", "node": 2858, "naklon": 0 }, +{ "label": "15/34/1", "node": 4306, "naklon": 0 }, +{ "label": "15/35", "node": 2856, "naklon": 0 }, +{ "label": "15/36", "node": 2847, "naklon": 0 }, +{ "label": "15/36/1", "node": 3556, "naklon": 0 }, +{ "label": "15/37", "node": 3950, "naklon": 0 }, +{ "label": "15/38", "node": 2848, "naklon": 0 }, +{ "label": "15/39", "node": 2863, "naklon": 0 }, +{ "label": "15/39/1", "node": 4313, "naklon": 0 }, +{ "label": "15/40", "node": 2873, "naklon": 0 }, +{ "label": "15/40/1", "node": 2984, "naklon": 0 }, +{ "label": "15/41", "node": 2854, "naklon": 0 }, +{ "label": "15/42", "node": 2859, "naklon": 0 }, +{ "label": "15/43", "node": 2872, "naklon": 0 }, +{ "label": "15/44", "node": 2849, "naklon": 0 }, +{ "label": "15/45", "node": 2864, "naklon": 0 }, +{ "label": "15/46", "node": 3553, "naklon": null }, +{ "label": "15/47", "node": 3021, "naklon": null }, +{ "label": "15/47/1", "node": 3008, "naklon": null }, +{ "label": "15/48", "node": 3017, "naklon": null }, +{ "label": "15/49", "node": 3014, "naklon": null }, +{ "label": "15/50", "node": 2981, "naklon": null }, +{ "label": "15/51", "node": 3020, "naklon": null }, +{ "label": "15/52", "node": 3027, "naklon": null }, +{ "label": "15/53", "node": 3006, "naklon": null }, +{ "label": "15/54", "node": 3012, "naklon": null }, +{ "label": "15/55", "node": 2738, "naklon": 0 }, +{ "label": "15/56", "node": 2725, "naklon": 0 }, +{ "label": "15/57", "node": 3016, "naklon": null }, +{ "label": "15/58", "node": 3005, "naklon": null }, +{ "label": "15/58/1", "node": 3009, "naklon": null }, +{ "label": "15/59", "node": 3010, "naklon": 0 }, +{ "label": "15/59/1", "node": 3538, "naklon": 0 }, +{ "label": "15/59/2", "node": 4145, "naklon": 0 }, +{ "label": "15/60", "node": 2713, "naklon": 0 }, +{ "label": "15/61", "node": 2789, "naklon": 0 }, +{ "label": "15/62", "node": 2736, "naklon": 0 }, +{ "label": "15/63", "node": 2739, "naklon": 0 }, +{ "label": "15/64", "node": 4346, "naklon": 0 }, +{ "label": "15/65", "node": 2731, "naklon": 0 }, +{ "label": "15/66", "node": 2818, "naklon": 0 }, +{ "label": "15/66/1", "node": 3557, "naklon": 0 }, +{ "label": "15/67", "node": 2822, "naklon": 0 }, +{ "label": "15/68", "node": 2833, "naklon": 0 }, +{ "label": "15/69", "node": 2834, "naklon": 0 }, +{ "label": "15/70", "node": 3097, "naklon": 0 }, +{ "label": "15/71", "node": 2824, "naklon": 0 }, +{ "label": "15/72", "node": 2828, "naklon": 0 }, +{ "label": "15/73", "node": 2600, "naklon": 0 }, +{ "label": "15/73/1", "node": 4314, "naklon": 0 }, +{ "label": "15/74", "node": 2832, "naklon": 0 }, +{ "label": "15/75", "node": 4360, "naklon": 0 }, +{ "label": "15/76", "node": 2846, "naklon": 0 }, +{ "label": "15/77", "node": 2584, "naklon": 0 }, +{ "label": "15/78", "node": 2843, "naklon": 0 }, +{ "label": "15/78/1", "node": 4308, "naklon": 0 }, +{ "label": "15/79", "node": 4144, "naklon": null }, +{ "label": "15/80", "node": 2844, "naklon": 0 }, +{ "label": "15/81", "node": 2842, "naklon": 0 }, +{ "label": "15/82", "node": 2838, "naklon": 0 }, +{ "label": "15/83", "node": 2837, "naklon": null }, +{ "label": "15/83/1", "node": 3555, "naklon": null }, +{ "label": "15/84", "node": 2839, "naklon": 0 }, +{ "label": "15/85", "node": 2830, "naklon": 0 }, +{ "label": "15/86", "node": 4066, "naklon": 0 }, +{ "label": "15/87", "node": 2836, "naklon": 0 }, +{ "label": "15/88", "node": 2911, "naklon": 0 }, +{ "label": "15/89", "node": 2825, "naklon": 0 }, +{ "label": "15/90", "node": 2811, "naklon": 0 }, +{ "label": "15/94", "node": 3740, "naklon": 15 }, +{ "label": "15/95", "node": 2734, "naklon": 15 }, +{ "label": "15/96", "node": 3105, "naklon": 15 }, +{ "label": "15/97", "node": 2732, "naklon": 15 }, +{ "label": "15/98", "node": 2727, "naklon": 15 }, +{ "label": "15/99", "node": 2735, "naklon": 15 }, +{ "label": "15/100", "node": 3926, "naklon": 15 }, +{ "label": "15/101", "node": 2918, "naklon": 0 }, +{ "label": "15/102", "node": 2705, "naklon": 10 }, +{ "label": "15/103", "node": 2708, "naklon": 10 }, +{ "label": "15/104", "node": 2721, "naklon": 10 }, +{ "label": "15/105", "node": 2719, "naklon": 10 }, +{ "label": "15/106", "node": 2919, "naklon": 10 }, +{ "label": "15/107", "node": 3101, "naklon": 10 }, +{ "label": "15/108", "node": 2853, "naklon": 10 }, +{ "label": "15/109", "node": 2715, "naklon": 10 }, +{ "label": "15/110", "node": 2712, "naklon": 0 }, +{ "label": "15/111", "node": 2711, "naklon": 0 }, +{ "label": "15/112", "node": 2709, "naklon": 0 }, +{ "label": "15/113", "node": 2710, "naklon": 0 }, +{ "label": "15/114", "node": 2907, "naklon": 0 }, +{ "label": "15/115", "node": 2906, "naklon": 0 }, +{ "label": "15/116", "node": 2908, "naklon": 0 }, +{ "label": "15/117", "node": 2901, "naklon": 0 }, +{ "label": "15/118", "node": 2913, "naklon": 0 }, +{ "label": "15/119", "node": 3656, "naklon": 0 }, +{ "label": "15/120", "node": 2781, "naklon": 0 }, +{ "label": "15/121", "node": 2802, "naklon": 0 }, +{ "label": "15/122", "node": 2791, "naklon": 0 }, +{ "label": "15/123", "node": 2783, "naklon": 0 }, +{ "label": "15/124", "node": 2794, "naklon": 0 }, +{ "label": "15/125", "node": 3139, "naklon": 0 }, +{ "label": "15/126", "node": 3229, "naklon": 5 }, +{ "label": "15/127", "node": 3239, "naklon": 5 }, +{ "label": "15/128", "node": 3230, "naklon": 5 }, +{ "label": "15/129", "node": 4016, "naklon": null }, +{ "label": "16/16A", "node": 3608, "naklon": 0 }, +{ "label": "16/16B", "node": 4151, "naklon": 0 }, +{ "label": "16/1", "node": 3710, "naklon": 0 }, +{ "label": "16/2", "node": 3726, "naklon": 0 }, +{ "label": "16/3", "node": 3743, "naklon": 0 }, +{ "label": "16/4", "node": 3724, "naklon": 0 }, +{ "label": "16/5", "node": 3712, "naklon": 0 }, +{ "label": "16/6", "node": 3739, "naklon": 0 }, +{ "label": "16/7", "node": 3742, "naklon": 0 }, +{ "label": "16/8", "node": 3731, "naklon": 0 }, +{ "label": "16/9", "node": 3727, "naklon": 0 }, +{ "label": "16/10", "node": 3729, "naklon": 0 }, +{ "label": "16/11", "node": 3736, "naklon": 0 }, +{ "label": "16/12", "node": 3713, "naklon": 0 }, +{ "label": "16/13", "node": 3715, "naklon": 0 }, +{ "label": "16/14", "node": 3733, "naklon": 0 }, +{ "label": "16/15", "node": 3732, "naklon": 0 }, +{ "label": "16/17", "node": 3634, "naklon": 0 }, +{ "label": "16/18", "node": 3610, "naklon": 0 }, +{ "label": "16/19", "node": 3626, "naklon": 0 }, +{ "label": "16/20", "node": 3618, "naklon": 0 }, +{ "label": "16/21", "node": 3619, "naklon": 0 }, +{ "label": "16/22", "node": 3628, "naklon": 0 }, +{ "label": "16/23", "node": 3615, "naklon": 0 }, +{ "label": "16/24", "node": 3609, "naklon": 0 }, +{ "label": "16/25", "node": 3606, "naklon": 0 }, +{ "label": "16/26", "node": 3624, "naklon": 0 }, +{ "label": "16/27", "node": 3627, "naklon": 0 }, +{ "label": "16/28", "node": 3607, "naklon": 0 }, +{ "label": "16/29", "node": 4370, "naklon": 0 }, +{ "label": "16/30", "node": 3692, "naklon": 0 }, +{ "label": "16/31", "node": 3614, "naklon": 0 }, +{ "label": "16/32", "node": 3623, "naklon": 0 }, +{ "label": "16/33", "node": 4373, "naklon": 0 }, +{ "label": "16/34", "node": 3620, "naklon": 0 }, +{ "label": "16/35", "node": 3685, "naklon": 0 }, +{ "label": "16/36", "node": 3616, "naklon": 0 }, +{ "label": "16/37", "node": 3686, "naklon": 0 }, +{ "label": "16/38", "node": 3688, "naklon": 0 }, +{ "label": "16/39", "node": 3684, "naklon": 0 }, +{ "label": "16/40", "node": 3825, "naklon": 0 }, +{ "label": "16/41", "node": 3865, "naklon": 0 }, +{ "label": "16/42", "node": 3824, "naklon": 0 }, +{ "label": "16/43", "node": 3871, "naklon": 0 }, +{ "label": "16/44", "node": 3801, "naklon": 0 }, +{ "label": "16/45", "node": 3862, "naklon": 0 }, +{ "label": "16/46", "node": 3876, "naklon": 0 }, +{ "label": "16/47", "node": 3861, "naklon": 0 }, +{ "label": "16/48", "node": 4215, "naklon": 0 }, +{ "label": "16/49", "node": 3605, "naklon": 10 }, +{ "label": "16/50", "node": 3603, "naklon": 10 }, +{ "label": "16/51", "node": 3592, "naklon": 10 }, +{ "label": "16/52", "node": 3598, "naklon": 10 }, +{ "label": "16/53", "node": 3594, "naklon": 10 }, +{ "label": "16/54", "node": 3593, "naklon": 10 }, +{ "label": "16/55", "node": 3630, "naklon": 10 }, +{ "label": "16/56", "node": 3763, "naklon": 10 }, +{ "label": "16/57", "node": 3746, "naklon": 10 }, +{ "label": "16/58", "node": 3699, "naklon": 0 }, +{ "label": "16/59", "node": 3698, "naklon": 0 }, +{ "label": "16/60", "node": 3709, "naklon": null }, +{ "label": "16/61", "node": 3708, "naklon": 0 }, +{ "label": "16/62", "node": 3703, "naklon": null }, +{ "label": "16/63", "node": 3700, "naklon": 0 }, +{ "label": "16/64", "node": 3701, "naklon": null }, +{ "label": "16/65", "node": 3704, "naklon": 0 }, +{ "label": "16/66", "node": 3707, "naklon": null }, +{ "label": "16/67", "node": 3810, "naklon": 0 }, +{ "label": "16/68", "node": 4208, "naklon": null }, +{ "label": "16/69", "node": 3867, "naklon": 0 }, +{ "label": "16/70", "node": 4372, "naklon": null }, +{ "label": "16/71", "node": 3881, "naklon": 0 }, +{ "label": "16/72", "node": 4204, "naklon": null }, +{ "label": "16/73", "node": 3869, "naklon": 0 }, +{ "label": "16/74", "node": 4202, "naklon": null }, +{ "label": "16/75", "node": 3830, "naklon": 0 }, +{ "label": "16/76", "node": 3870, "naklon": null }, +{ "label": "16/77", "node": 3964, "naklon": 0 }, +{ "label": "16/78", "node": 3849, "naklon": 0 }, +{ "label": "16/79", "node": 3694, "naklon": null }, +{ "label": "16/80", "node": 3717, "naklon": 0 }, +{ "label": "16/81", "node": 3877, "naklon": null }, +{ "label": "16/82", "node": 3755, "naklon": 0 }, +{ "label": "16/83", "node": 3725, "naklon": null }, +{ "label": "16/84", "node": 3716, "naklon": 0 }, +{ "label": "16/85", "node": 3696, "naklon": null }, +{ "label": "16/86", "node": 3702, "naklon": 0 }, +{ "label": "16/87", "node": 3706, "naklon": null }, +{ "label": "16/88", "node": 3850, "naklon": 0 }, +{ "label": "16/89", "node": 3848, "naklon": null }, +{ "label": "16/90", "node": 3737, "naklon": null }, +{ "label": "16/91", "node": 3705, "naklon": 0 }, +{ "label": "16/92", "node": 3723, "naklon": null }, +{ "label": "16/93", "node": 3842, "naklon": 0 }, +{ "label": "16/94", "node": 3735, "naklon": null }, +{ "label": "16/95", "node": 3719, "naklon": 0 }, +{ "label": "16/96", "node": 3697, "naklon": 0 }, +{ "label": "16/97", "node": 3711, "naklon": 0 }, +{ "label": "16/98", "node": 4107, "naklon": null }, +{ "label": "16/99", "node": 4112, "naklon": 5 }, +{ "label": "16/100", "node": 4106, "naklon": 5 }, +{ "label": "16/101", "node": 4111, "naklon": 5 }, +{ "label": "16/102", "node": 4091, "naklon": null }, +{ "label": "16/103", "node": 4104, "naklon": 5 }, +{ "label": "16/104", "node": 4094, "naklon": null }, +{ "label": "16/105", "node": 4089, "naklon": 5 }, +{ "label": "16/106", "node": 4095, "naklon": null }, +{ "label": "16/107", "node": 4102, "naklon": 5 }, +{ "label": "16/108", "node": 4105, "naklon": null }, +{ "label": "16/109", "node": 3859, "naklon": null }, +{ "label": "16/110", "node": 4090, "naklon": 5 }, +{ "label": "16/111", "node": 4110, "naklon": null }, +{ "label": "16/112", "node": 4097, "naklon": 5 }, +{ "label": "16/113", "node": 4099, "naklon": null }, +{ "label": "16/114", "node": 4096, "naklon": null }, +{ "label": "16/115", "node": 4101, "naklon": 5 }, +{ "label": "16/116", "node": 4109, "naklon": null }, +{ "label": "16/117", "node": 4092, "naklon": 5 }, +{ "label": "16/118", "node": 3631, "naklon": null }, +{ "label": "16/119", "node": 3632, "naklon": 0 }, +{ "label": "16/120", "node": 3641, "naklon": null }, +{ "label": "16/121", "node": 3638, "naklon": 0 }, +{ "label": "16/122", "node": 3637, "naklon": null }, +{ "label": "16/123", "node": 4142, "naklon": null }, +{ "label": "16/124", "node": 4147, "naklon": 5 }, +{ "label": "16/125", "node": 4139, "naklon": 5 }, +{ "label": "20/30A", "node": 3172, "naklon": 2 }, +{ "label": "20/30B", "node": 3164, "naklon": 2 }, +{ "label": "20/1", "node": 3247, "naklon": 10 }, +{ "label": "20/2", "node": 3296, "naklon": 10 }, +{ "label": "20/3", "node": 3246, "naklon": 10 }, +{ "label": "20/4", "node": 3270, "naklon": 10 }, +{ "label": "20/5", "node": 3294, "naklon": 10 }, +{ "label": "20/6", "node": 3298, "naklon": 10 }, +{ "label": "20/7", "node": 3297, "naklon": 10 }, +{ "label": "20/8", "node": 3293, "naklon": 10 }, +{ "label": "20/9", "node": 3299, "naklon": 10 }, +{ "label": "20/10", "node": 3295, "naklon": 10 }, +{ "label": "20/11", "node": 3244, "naklon": 10 }, +{ "label": "20/12", "node": 3249, "naklon": 10 }, +{ "label": "20/13", "node": 3268, "naklon": 10 }, +{ "label": "20/14", "node": 3245, "naklon": 10 }, +{ "label": "20/15", "node": 3278, "naklon": 10 }, +{ "label": "20/16", "node": 3280, "naklon": 10 }, +{ "label": "20/17", "node": 3292, "naklon": 10 }, +{ "label": "20/18", "node": 3287, "naklon": 10 }, +{ "label": "20/19", "node": 3282, "naklon": 10 }, +{ "label": "20/20", "node": 3273, "naklon": 0 }, +{ "label": "20/21", "node": 3157, "naklon": 0 }, +{ "label": "20/22", "node": 3283, "naklon": 0 }, +{ "label": "20/23", "node": 3159, "naklon": 0 }, +{ "label": "20/24", "node": 3289, "naklon": 0 }, +{ "label": "20/25", "node": 3163, "naklon": 0 }, +{ "label": "20/26", "node": 3126, "naklon": 0 }, +{ "label": "20/27", "node": 3171, "naklon": 0 }, +{ "label": "20/28", "node": 3162, "naklon": 0 }, +{ "label": "20/29", "node": 3279, "naklon": 10 }, +{ "label": "20/31", "node": 3173, "naklon": 0 }, +{ "label": "20/32", "node": 3127, "naklon": 0 }, +{ "label": "20/33", "node": 3131, "naklon": 0 }, +{ "label": "20/34", "node": 3129, "naklon": 0 }, +{ "label": "20/35", "node": 3276, "naklon": 2 }, +{ "label": "20/36", "node": 3290, "naklon": 2 }, +{ "label": "20/37", "node": 3132, "naklon": 0 }, +{ "label": "20/38", "node": 3138, "naklon": 0 }, +{ "label": "20/39", "node": 3272, "naklon": 0 }, +{ "label": "20/40", "node": 3291, "naklon": 0 }, +{ "label": "20/41", "node": 3277, "naklon": 10 }, +{ "label": "20/42", "node": 3286, "naklon": 10 }, +{ "label": "20/43", "node": 3281, "naklon": 10 }, +{ "label": "20/44", "node": 3288, "naklon": 10 }, +{ "label": "20/45", "node": 3284, "naklon": 10 }, +{ "label": "20/46", "node": 3167, "naklon": 10 }, +{ "label": "20/47", "node": 3872, "naklon": 0 }, +{ "label": "20/48", "node": 3124, "naklon": 0 }, +{ "label": "20/49", "node": 3133, "naklon": 0 }, +{ "label": "20/50", "node": 3158, "naklon": 0 }, +{ "label": "20/51", "node": 3169, "naklon": 0 }, +{ "label": "20/52", "node": 3146, "naklon": 0 }, +{ "label": "20/53", "node": 3160, "naklon": 0 }, +{ "label": "20/54", "node": 3248, "naklon": 0 }, +{ "label": "20/55", "node": 3156, "naklon": 0 }, +{ "label": "20/56", "node": 3161, "naklon": 0 }, +{ "label": "20/57", "node": 3170, "naklon": 0 }, +{ "label": "20/58", "node": 3168, "naklon": 0 }, +{ "label": "20/59", "node": 3125, "naklon": 0 }, +{ "label": "20/60", "node": 3166, "naklon": 0 }, +{ "label": "20/61", "node": 3130, "naklon": 0 }, +{ "label": "20/62", "node": 3563, "naklon": 0 }, +{ "label": "20/63", "node": 3550, "naklon": null }, +{ "label": "20/67", "node": 3269, "naklon": 0 }, +{ "label": "21/1", "node": 2921, "naklon": 0 }, +{ "label": "21/2", "node": 2707, "naklon": 0 }, +{ "label": "21/3", "node": 2723, "naklon": 0 }, +{ "label": "21/4", "node": 2716, "naklon": 0 }, +{ "label": "21/5", "node": 2717, "naklon": 0 }, +{ "label": "21/6", "node": 2720, "naklon": 0 }, +{ "label": "21/7", "node": 2722, "naklon": 0 }, +{ "label": "21/8", "node": 2718, "naklon": 0 }, +{ "label": "21/9", "node": 2724, "naklon": 0 }, +{ "label": "21/10", "node": 2742, "naklon": 0 }, +{ "label": "21/11", "node": 2743, "naklon": 0 }, +{ "label": "21/12", "node": 2733, "naklon": 0 }, +{ "label": "21/14", "node": 2903, "naklon": 0 }, +{ "label": "21/15", "node": 2917, "naklon": 0 }, +{ "label": "21/16", "node": 2897, "naklon": 0 }, +{ "label": "21/17", "node": 2914, "naklon": 0 }, +{ "label": "21/18", "node": 2898, "naklon": 0 }, +{ "label": "21/19", "node": 2773, "naklon": 0 }, +{ "label": "21/20", "node": 2895, "naklon": 0 }, +{ "label": "21/21", "node": 2896, "naklon": 0 }, +{ "label": "21/22", "node": 2771, "naklon": 0 }, +{ "label": "21/23", "node": 2772, "naklon": 0 }, +{ "label": "21/24", "node": 2793, "naklon": 0 }, +{ "label": "21/25", "node": 2902, "naklon": 0 }, +{ "label": "21/26", "node": 2910, "naklon": 0 }, +{ "label": "21/27", "node": 2909, "naklon": 0 }, +{ "label": "21/28", "node": 2920, "naklon": 0 }, +{ "label": "21/29", "node": 2916, "naklon": 0 }, +{ "label": "21/30", "node": 2904, "naklon": 0 }, +{ "label": "21/31", "node": 2915, "naklon": 0 }, +{ "label": "21/32", "node": 2905, "naklon": 0 }, +{ "label": "21/33", "node": 2900, "naklon": 0 }, +{ "label": "21/34", "node": 2899, "naklon": 0 }, +{ "label": "21/36", "node": 2741, "naklon": 0 }, +{ "label": "21/37", "node": 2714, "naklon": 0 }, +{ "label": "21/38", "node": 2701, "naklon": 0 }, +{ "label": "21/39", "node": 2703, "naklon": 0 }, +{ "label": "21/40", "node": 2704, "naklon": 0 }, +{ "label": "21/41", "node": 2702, "naklon": 0 }, +{ "label": "21/42", "node": 2706, "naklon": 0 }, +{ "label": "21/43", "node": 2776, "naklon": 0 }, +{ "label": "21/44", "node": 2770, "naklon": 0 }, +{ "label": "21/45", "node": 2786, "naklon": 0 }, +{ "label": "21/46", "node": 2779, "naklon": 0 }, +{ "label": "21/47", "node": 2782, "naklon": 0 }, +{ "label": "21/48", "node": 2785, "naklon": 0 }, +{ "label": "21/49", "node": 2769, "naklon": 0 }, +{ "label": "21/50", "node": 3354, "naklon": 0 }, +{ "label": "21/51", "node": 2778, "naklon": 0 }, +{ "label": "21/52", "node": 2775, "naklon": 0 }, +{ "label": "21/53", "node": 2780, "naklon": 0 }, +{ "label": "21/54", "node": 2790, "naklon": 0 }, +{ "label": "21/55", "node": 2792, "naklon": 0 }, +{ "label": "21/56", "node": 2774, "naklon": 0 }, +{ "label": "22/1", "node": 2630, "naklon": 0 }, +{ "label": "22/2", "node": 2631, "naklon": 0 }, +{ "label": "22/3", "node": 2632, "naklon": 0 }, +{ "label": "22/4", "node": 2633, "naklon": 0 }, +{ "label": "22/5", "node": 2634, "naklon": 0 }, +{ "label": "22/6", "node": 2636, "naklon": 0 }, +{ "label": "22/7", "node": 4367, "naklon": 0 }, +{ "label": "22/8", "node": 2637, "naklon": 0 }, +{ "label": "22/9", "node": 2638, "naklon": 0 }, +{ "label": "22/10", "node": 2639, "naklon": 0 }, +{ "label": "22/11", "node": 2640, "naklon": 0 }, +{ "label": "22/12", "node": 2641, "naklon": 0 }, +{ "label": "22/13", "node": 2642, "naklon": 0 }, +{ "label": "22/14", "node": 2643, "naklon": 0 }, +{ "label": "22/15", "node": 2644, "naklon": 0 }, +{ "label": "22/16", "node": 2645, "naklon": 0 }, +{ "label": "22/17", "node": 2646, "naklon": 0 }, +{ "label": "22/18", "node": 2647, "naklon": 0 }, +{ "label": "22/19", "node": 2648, "naklon": 0 }, +{ "label": "22/20", "node": 2649, "naklon": 0 }, +{ "label": "22/21", "node": 2650, "naklon": 0 }, +{ "label": "22/22", "node": 2651, "naklon": 0 }, +{ "label": "22/23", "node": 4103, "naklon": 0 }, +{ "label": "22/24", "node": 2653, "naklon": 0 }, +{ "label": "22/25", "node": 2654, "naklon": 0 }, +{ "label": "22/26", "node": 2655, "naklon": 0 }, +{ "label": "22/27", "node": 2656, "naklon": 0 }, +{ "label": "22/28", "node": 2657, "naklon": 0 }, +{ "label": "22/29", "node": 2658, "naklon": 0 }, +{ "label": "22/30", "node": 2659, "naklon": 0 }, +{ "label": "22/31", "node": 2660, "naklon": 0 }, +{ "label": "22/32", "node": 2661, "naklon": 0 }, +{ "label": "22/32/1", "node": 3015, "naklon": 0 }, +{ "label": "22/33", "node": 2662, "naklon": 0 }, +{ "label": "22/34", "node": 2663, "naklon": 0 }, +{ "label": "22/35", "node": 2664, "naklon": 0 }, +{ "label": "22/36", "node": 2665, "naklon": 0 }, +{ "label": "22/37", "node": 2666, "naklon": 0 }, +{ "label": "22/38", "node": 2667, "naklon": 0 }, +{ "label": "22/39", "node": 2668, "naklon": 0 }, +{ "label": "22/40", "node": 2669, "naklon": null }, +{ "label": "22/41", "node": 2670, "naklon": null }, +{ "label": "22/42", "node": 2671, "naklon": null }, +{ "label": "23/9A", "node": 3087, "naklon": 10 }, +{ "label": "23/9B", "node": 3090, "naklon": 10 }, +{ "label": "23/1", "node": 3075, "naklon": 0 }, +{ "label": "23/2", "node": 3089, "naklon": 0 }, +{ "label": "23/3", "node": 3088, "naklon": 0 }, +{ "label": "23/4", "node": 3228, "naklon": 10 }, +{ "label": "23/5", "node": 2751, "naklon": 10 }, +{ "label": "23/6", "node": 3243, "naklon": 10 }, +{ "label": "23/7", "node": 4349, "naklon": 10 }, +{ "label": "23/8", "node": 3102, "naklon": 10 }, +{ "label": "23/10", "node": 3099, "naklon": 10 }, +{ "label": "23/11", "node": 3103, "naklon": 10 }, +{ "label": "23/12", "node": 3093, "naklon": 10 }, +{ "label": "23/13", "node": 3098, "naklon": 10 }, +{ "label": "23/14", "node": 3092, "naklon": 10 }, +{ "label": "23/15", "node": 3233, "naklon": 0 }, +{ "label": "23/16", "node": 3095, "naklon": 0 }, +{ "label": "23/17", "node": 4074, "naklon": 0 }, +{ "label": "23/18", "node": 2729, "naklon": 0 }, +{ "label": "23/19", "node": 3234, "naklon": 0 }, +{ "label": "23/20", "node": 3094, "naklon": 0 }, +{ "label": "23/21", "node": 2817, "naklon": 0 }, +{ "label": "23/22", "node": 3226, "naklon": 0 }, +{ "label": "23/23", "node": 3225, "naklon": 0 }, +{ "label": "23/24", "node": 3237, "naklon": 0 }, +{ "label": "23/25", "node": 4250, "naklon": 0 }, +{ "label": "23/26", "node": 3059, "naklon": 10 }, +{ "label": "23/27", "node": 3238, "naklon": 10 }, +{ "label": "23/28", "node": 3242, "naklon": 10 }, +{ "label": "23/29", "node": 3236, "naklon": 10 }, +{ "label": "23/30", "node": 3112, "naklon": 10 }, +{ "label": "23/31", "node": 3224, "naklon": 0 }, +{ "label": "23/32", "node": 4298, "naklon": 10 }, +{ "label": "23/33", "node": 4150, "naklon": 10 }, +{ "label": "23/34", "node": 3091, "naklon": 10 }, +{ "label": "25/1", "node": 3771, "naklon": 5 }, +{ "label": "25/2", "node": 3777, "naklon": 5 }, +{ "label": "25/3", "node": 3749, "naklon": 5 }, +{ "label": "25/4", "node": 3769, "naklon": 5 }, +{ "label": "25/5", "node": 3765, "naklon": 5 }, +{ "label": "25/6", "node": 3785, "naklon": 5 }, +{ "label": "25/7", "node": 3761, "naklon": 5 }, +{ "label": "25/8", "node": 3758, "naklon": 5 }, +{ "label": "25/9", "node": 3766, "naklon": 5 }, +{ "label": "25/10", "node": 3779, "naklon": 5 }, +{ "label": "25/11", "node": 3899, "naklon": 10 }, +{ "label": "25/12", "node": 3922, "naklon": 10 }, +{ "label": "25/13", "node": 3912, "naklon": 10 }, +{ "label": "25/14", "node": 3933, "naklon": 10 }, +{ "label": "25/15", "node": 3921, "naklon": 10 }, +{ "label": "25/16", "node": 4300, "naklon": 10 }, +{ "label": "25/17", "node": 3927, "naklon": 10 }, +{ "label": "25/18", "node": 3212, "naklon": 10 }, +{ "label": "25/19", "node": 3208, "naklon": 10 }, +{ "label": "25/20", "node": 3207, "naklon": 10 }, +{ "label": "25/21", "node": 4294, "naklon": 10 }, +{ "label": "25/22", "node": 3209, "naklon": 10 }, +{ "label": "25/23", "node": 3745, "naklon": 10 }, +{ "label": "25/24", "node": 3762, "naklon": 10 }, +{ "label": "25/25", "node": 3215, "naklon": 10 }, +{ "label": "25/26", "node": 3210, "naklon": 10 }, +{ "label": "25/27", "node": 3211, "naklon": 10 }, +{ "label": "25/28", "node": 3206, "naklon": 10 }, +{ "label": "25/29", "node": 3918, "naklon": 5 }, +{ "label": "25/30", "node": 3928, "naklon": 5 }, +{ "label": "25/31", "node": 3917, "naklon": 5 }, +{ "label": "25/32", "node": 4029, "naklon": 0 }, +{ "label": "25/33", "node": 4038, "naklon": 0 }, +{ "label": "25/34", "node": 4022, "naklon": 0 }, +{ "label": "25/35", "node": 3937, "naklon": 0 }, +{ "label": "25/36", "node": 3190, "naklon": 0 }, +{ "label": "25/37", "node": 3835, "naklon": 0 }, +{ "label": "25/38", "node": 3201, "naklon": 0 }, +{ "label": "25/39", "node": 3193, "naklon": 0 }, +{ "label": "25/40", "node": 3191, "naklon": 0 }, +{ "label": "25/41", "node": 3203, "naklon": 0 }, +{ "label": "25/42", "node": 4301, "naklon": 0 }, +{ "label": "25/43", "node": 3223, "naklon": 0 }, +{ "label": "25/44", "node": 3202, "naklon": 0 }, +{ "label": "25/45", "node": 3205, "naklon": 0 }, +{ "label": "25/46", "node": 3194, "naklon": 0 }, +{ "label": "25/47", "node": 3198, "naklon": 0 }, +{ "label": "25/48", "node": 3204, "naklon": 0 }, +{ "label": "25/49", "node": 3200, "naklon": 0 }, +{ "label": "25/50", "node": 3216, "naklon": 0 }, +{ "label": "25/51", "node": 3932, "naklon": 5 }, +{ "label": "25/52", "node": 3923, "naklon": 5 }, +{ "label": "25/53", "node": 3913, "naklon": 5 }, +{ "label": "25/54", "node": 3900, "naklon": 5 }, +{ "label": "25/55", "node": 4189, "naklon": 10 }, +{ "label": "25/56", "node": 4191, "naklon": 10 }, +{ "label": "25/57", "node": 3790, "naklon": 10 }, +{ "label": "25/58", "node": 4190, "naklon": 10 }, +{ "label": "25/59", "node": 4302, "naklon": 0 }, +{ "label": "25/60", "node": 4351, "naklon": 0 }, +{ "label": "25/61", "node": 4075, "naklon": 0 }, +{ "label": "25/62", "node": 4071, "naklon": 0 }, +{ "label": "25/63", "node": 3784, "naklon": 0 }, +{ "label": "25/64", "node": 4065, "naklon": 0 }, +{ "label": "25/65", "node": 4297, "naklon": 0 }, +{ "label": "25/66", "node": 4295, "naklon": 0 }, +{ "label": "25/67", "node": 4299, "naklon": 0 }, +{ "label": "25/68", "node": 3772, "naklon": 0 }, +{ "label": "25/69", "node": 3941, "naklon": 0 }, +{ "label": "25/70", "node": 3782, "naklon": 0 }, +{ "label": "25/71", "node": 4068, "naklon": 0 }, +{ "label": "25/72", "node": 4073, "naklon": 0 }, +{ "label": "25/73", "node": 3901, "naklon": 5 }, +{ "label": "25/74", "node": 4296, "naklon": 5 }, +{ "label": "25/75", "node": 3910, "naklon": 5 }, +{ "label": "25/76", "node": 4293, "naklon": 5 }, +{ "label": "25/77", "node": 3919, "naklon": 5 }, +{ "label": "25/78", "node": 3924, "naklon": 5 }, +{ "label": "25/79", "node": 3909, "naklon": 5 }, +{ "label": "25/80", "node": 3896, "naklon": 5 }, +{ "label": "25/81", "node": 3911, "naklon": 5 }, +{ "label": "25/82", "node": 2819, "naklon": 15 }, +{ "label": "25/83", "node": 3776, "naklon": 15 }, +{ "label": "25/84", "node": 3752, "naklon": 15 }, +{ "label": "25/85", "node": 4353, "naklon": 15 }, +{ "label": "25/86", "node": 3791, "naklon": 0 }, +{ "label": "25/87", "node": 3770, "naklon": 0 }, +{ "label": "25/88", "node": 3760, "naklon": 0 }, +{ "label": "25/89", "node": 3115, "naklon": 0 }, +{ "label": "25/90", "node": 3738, "naklon": 0 }, +{ "label": "25/91", "node": 3748, "naklon": 0 }, +{ "label": "25/92", "node": 3753, "naklon": 0 }, +{ "label": "25/93", "node": 3775, "naklon": 0 }, +{ "label": "25/94", "node": 3778, "naklon": 5 }, +{ "label": "25/95", "node": 4078, "naklon": 5 }, +{ "label": "25/96", "node": 4088, "naklon": 5 }, +{ "label": "25/97", "node": 3856, "naklon": 5 }, +{ "label": "25/98", "node": 4084, "naklon": 5 }, +{ "label": "25/99", "node": 4069, "naklon": 5 }, +{ "label": "25/100", "node": 4188, "naklon": 5 }, +{ "label": "25/101", "node": 4064, "naklon": 5 }, +{ "label": "25/102", "node": 3792, "naklon": 5 }, +{ "label": "25/103", "node": 3780, "naklon": 5 }, +{ "label": "25/104", "node": 4034, "naklon": 5 }, +{ "label": "25/105", "node": 4072, "naklon": 5 }, +{ "label": "25/106", "node": 3884, "naklon": 5 }, +{ "label": "25/107", "node": 3793, "naklon": 5 }, +{ "label": "25/108", "node": 3863, "naklon": 5 }, +{ "label": "25/109", "node": 3855, "naklon": 5 }, +{ "label": "33/1", "node": 3846, "naklon": 0 }, +{ "label": "33/2", "node": 3943, "naklon": 0 }, +{ "label": "33/3", "node": 3903, "naklon": 0 }, +{ "label": "33/4", "node": 3982, "naklon": 0 }, +{ "label": "33/5", "node": 3879, "naklon": 0 }, +{ "label": "33/6", "node": 3887, "naklon": 0 }, +{ "label": "33/7", "node": 3920, "naklon": 5 }, +{ "label": "33/8", "node": 3942, "naklon": 5 }, +{ "label": "33/9", "node": 3829, "naklon": null }, +{ "label": "34/79A", "node": 3452, "naklon": 6 }, +{ "label": "34/79B", "node": 3460, "naklon": 6 }, +{ "label": "34/90A", "node": 3443, "naklon": 6 }, +{ "label": "34/90B", "node": 3445, "naklon": 6 }, +{ "label": "34/90C", "node": 3457, "naklon": 6 }, +{ "label": "34/97A", "node": 3461, "naklon": 6 }, +{ "label": "34/97B", "node": 3463, "naklon": 6 }, +{ "label": "34/98A", "node": 3426, "naklon": 6 }, +{ "label": "34/98B", "node": 3444, "naklon": 6 }, +{ "label": "34/99A", "node": 3453, "naklon": 6 }, +{ "label": "34/99B", "node": 3455, "naklon": 6 }, +{ "label": "34/1", "node": 4009, "naklon": 0 }, +{ "label": "34/2", "node": 3602, "naklon": 0 }, +{ "label": "34/3", "node": 3441, "naklon": 0 }, +{ "label": "34/4", "node": 3464, "naklon": 0 }, +{ "label": "34/5", "node": 3883, "naklon": 0 }, +{ "label": "34/6", "node": 4098, "naklon": 0 }, +{ "label": "34/7", "node": 4003, "naklon": 0 }, +{ "label": "34/8", "node": 4004, "naklon": 0 }, +{ "label": "34/9", "node": 3888, "naklon": 0 }, +{ "label": "34/10", "node": 3997, "naklon": 0 }, +{ "label": "34/11", "node": 4006, "naklon": 0 }, +{ "label": "34/12", "node": 4000, "naklon": 0 }, +{ "label": "34/13", "node": 4011, "naklon": 0 }, +{ "label": "34/14", "node": 3999, "naklon": 0 }, +{ "label": "34/15", "node": 3981, "naklon": 0 }, +{ "label": "34/16", "node": 3988, "naklon": 0 }, +{ "label": "34/17", "node": 3986, "naklon": 0 }, +{ "label": "34/18", "node": 3998, "naklon": 0 }, +{ "label": "34/19", "node": 3983, "naklon": 0 }, +{ "label": "34/20", "node": 4005, "naklon": 0 }, +{ "label": "34/21", "node": 4001, "naklon": 0 }, +{ "label": "34/22", "node": 4008, "naklon": 0 }, +{ "label": "34/23", "node": 4002, "naklon": 0 }, +{ "label": "34/24", "node": 3996, "naklon": 0 }, +{ "label": "34/25", "node": 4007, "naklon": 0 }, +{ "label": "34/26", "node": 4113, "naklon": 15 }, +{ "label": "34/27", "node": 3595, "naklon": 5 }, +{ "label": "34/28", "node": 3599, "naklon": 5 }, +{ "label": "34/29", "node": 3601, "naklon": 5 }, +{ "label": "34/30", "node": 4205, "naklon": 0 }, +{ "label": "34/31", "node": 3987, "naklon": null }, +{ "label": "34/32", "node": 4214, "naklon": 0 }, +{ "label": "34/33", "node": 4226, "naklon": 0 }, +{ "label": "34/34", "node": 4209, "naklon": 0 }, +{ "label": "34/35", "node": 4201, "naklon": 0 }, +{ "label": "34/36", "node": 3440, "naklon": 0 }, +{ "label": "34/37", "node": 3465, "naklon": 0 }, +{ "label": "34/38", "node": 3446, "naklon": 0 }, +{ "label": "34/39", "node": 4039, "naklon": 5 }, +{ "label": "34/40", "node": 4057, "naklon": 5 }, +{ "label": "34/41", "node": 3985, "naklon": 0 }, +{ "label": "34/42", "node": 3882, "naklon": 0 }, +{ "label": "34/43", "node": 4040, "naklon": 5 }, +{ "label": "34/44", "node": 3231, "naklon": 0 }, +{ "label": "34/45", "node": 3227, "naklon": 0 }, +{ "label": "34/46", "node": 3431, "naklon": 0 }, +{ "label": "34/47", "node": 4013, "naklon": 0 }, +{ "label": "34/48", "node": 4045, "naklon": 0 }, +{ "label": "34/49", "node": 3949, "naklon": 0 }, +{ "label": "34/50", "node": 3953, "naklon": 0 }, +{ "label": "34/51", "node": 3952, "naklon": 0 }, +{ "label": "34/52", "node": 3995, "naklon": 0 }, +{ "label": "34/53", "node": 3992, "naklon": 0 }, +{ "label": "34/54", "node": 4198, "naklon": 0 }, +{ "label": "34/55", "node": 3935, "naklon": 0 }, +{ "label": "34/56", "node": 4050, "naklon": 0 }, +{ "label": "34/57", "node": 4049, "naklon": 0 }, +{ "label": "34/58", "node": 4054, "naklon": 0 }, +{ "label": "34/59", "node": 3663, "naklon": 6 }, +{ "label": "34/60", "node": 3661, "naklon": 6 }, +{ "label": "34/61", "node": 3664, "naklon": 6 }, +{ "label": "34/62", "node": 3660, "naklon": 6 }, +{ "label": "34/63", "node": 3662, "naklon": 6 }, +{ "label": "34/65", "node": 3665, "naklon": 6 }, +{ "label": "34/66", "node": 3667, "naklon": 6 }, +{ "label": "34/67", "node": 3675, "naklon": 6 }, +{ "label": "34/68", "node": 3666, "naklon": 6 }, +{ "label": "34/69", "node": 3652, "naklon": 6 }, +{ "label": "34/70", "node": 3458, "naklon": 6 }, +{ "label": "34/70/1", "node": 4425, "naklon": 6 }, +{ "label": "34/71", "node": 3459, "naklon": 6 }, +{ "label": "34/72", "node": 3435, "naklon": 6 }, +{ "label": "34/73", "node": 3448, "naklon": 6 }, +{ "label": "34/74", "node": 3451, "naklon": 6 }, +{ "label": "34/75", "node": 3442, "naklon": 6 }, +{ "label": "34/76", "node": 3449, "naklon": 6 }, +{ "label": "34/77", "node": 3450, "naklon": 6 }, +{ "label": "34/78", "node": 3433, "naklon": 6 }, +{ "label": "34/80", "node": 3432, "naklon": 12 }, +{ "label": "34/81", "node": 3470, "naklon": 12 }, +{ "label": "34/82", "node": 3438, "naklon": 12 }, +{ "label": "34/83", "node": 3439, "naklon": 12 }, +{ "label": "34/84", "node": 4028, "naklon": 5 }, +{ "label": "34/85", "node": 3596, "naklon": 5 }, +{ "label": "34/86", "node": 4021, "naklon": 5 }, +{ "label": "34/87", "node": 3437, "naklon": 12 }, +{ "label": "34/88", "node": 3428, "naklon": 12 }, +{ "label": "34/89", "node": 3430, "naklon": 12 }, +{ "label": "34/91", "node": 3454, "naklon": 6 }, +{ "label": "34/92", "node": 3492, "naklon": 6 }, +{ "label": "34/93", "node": 3462, "naklon": 6 }, +{ "label": "34/94", "node": 3427, "naklon": 6 }, +{ "label": "34/95", "node": 3434, "naklon": 6 }, +{ "label": "34/96", "node": 3456, "naklon": 6 }, +{ "label": "34/98/1", "node": 4307, "naklon": 6 }, +{ "label": "35/1", "node": 3968, "naklon": 0 }, +{ "label": "35/2", "node": 3969, "naklon": 0 }, +{ "label": "35/3", "node": 3947, "naklon": 0 }, +{ "label": "35/4", "node": 3979, "naklon": 0 }, +{ "label": "35/5", "node": 3959, "naklon": 0 }, +{ "label": "35/6", "node": 3948, "naklon": 0 }, +{ "label": "35/7", "node": 3961, "naklon": 0 }, +{ "label": "35/8", "node": 3956, "naklon": 0 }, +{ "label": "35/9", "node": 3604, "naklon": 0 }, +{ "label": "35/10", "node": 3944, "naklon": 0 }, +{ "label": "35/11", "node": 3960, "naklon": 0 }, +{ "label": "35/12", "node": 3958, "naklon": 0 }, +{ "label": "35/13", "node": 4036, "naklon": 5 }, +{ "label": "35/18", "node": 3893, "naklon": 5 }, +{ "label": "35/19", "node": 4108, "naklon": 5 }, +{ "label": "35/20", "node": 4017, "naklon": 5 }, +{ "label": "35/21", "node": 3963, "naklon": 0 }, +{ "label": "35/22", "node": 3658, "naklon": 0 }, +{ "label": "35/23", "node": 3975, "naklon": 0 }, +{ "label": "35/24", "node": 3980, "naklon": 0 }, +{ "label": "35/25", "node": 4012, "naklon": 0 }, +{ "label": "35/26", "node": 3655, "naklon": 0 }, +{ "label": "35/27", "node": 3962, "naklon": 0 }, +{ "label": "35/28", "node": 3945, "naklon": 0 }, +{ "label": "35/29", "node": 3569, "naklon": 0 }, +{ "label": "35/30", "node": 3429, "naklon": 0 }, +{ "label": "35/31", "node": 3657, "naklon": 0 }, +{ "label": "35/32", "node": 3646, "naklon": 0 }, +{ "label": "35/33", "node": 3622, "naklon": 0 }, +{ "label": "35/34", "node": 3612, "naklon": 0 }, +{ "label": "35/35", "node": 3955, "naklon": 0 }, +{ "label": "35/37", "node": 3878, "naklon": 0 }, +{ "label": "35/38", "node": 3965, "naklon": 0 }, +{ "label": "35/39", "node": 3970, "naklon": 0 }, +{ "label": "35/40", "node": 3611, "naklon": 0 }, +{ "label": "35/41", "node": 2635, "naklon": 0 }, +{ "label": "35/42", "node": 3978, "naklon": 0 }, +{ "label": "35/43", "node": 4213, "naklon": 0 }, +{ "label": "35/44", "node": 3984, "naklon": 0 }, +{ "label": "35/45", "node": 4218, "naklon": 0 }, +{ "label": "35/46", "node": 3973, "naklon": 0 }, +{ "label": "35/47", "node": 3974, "naklon": 0 }, +{ "label": "35/48", "node": 3759, "naklon": 0 }, +{ "label": "35/49", "node": 3844, "naklon": 0 }, +{ "label": "35/50", "node": 3804, "naklon": 0 }, +{ "label": "35/51", "node": 3831, "naklon": 0 }, +{ "label": "35/52", "node": 3643, "naklon": 0 }, +{ "label": "35/53", "node": 3966, "naklon": 0 }, +{ "label": "35/54", "node": 3971, "naklon": 0 }, +{ "label": "35/55", "node": 3650, "naklon": 6 }, +{ "label": "35/56", "node": 3651, "naklon": 6 }, +{ "label": "35/57", "node": 3669, "naklon": 6 }, +{ "label": "35/58", "node": 3648, "naklon": 6 }, +{ "label": "35/59", "node": 3645, "naklon": 6 }, +{ "label": "35/60", "node": 3659, "naklon": 6 }, +{ "label": "35/61", "node": 3647, "naklon": 6 }, +{ "label": "35/62", "node": 3644, "naklon": 6 }, +{ "label": "35/63", "node": 3671, "naklon": 6 }, +{ "label": "35/64", "node": 3682, "naklon": 6 }, +{ "label": "35/65", "node": 3672, "naklon": 6 }, +{ "label": "35/66", "node": 3683, "naklon": 6 }, +{ "label": "35/67", "node": 3673, "naklon": 6 }, +{ "label": "35/68", "node": 3674, "naklon": 6 }, +{ "label": "35/69", "node": 3679, "naklon": 6 }, +{ "label": "35/70", "node": 3649, "naklon": 6 }, +{ "label": "35/71", "node": 3687, "naklon": 6 }, +{ "label": "35/72", "node": 3677, "naklon": 6 }, +{ "label": "35/73", "node": 3690, "naklon": 6 }, +{ "label": "35/74", "node": 3691, "naklon": 6 }, +{ "label": "35/75", "node": 3676, "naklon": 6 }, +{ "label": "35/76", "node": 3680, "naklon": 6 }, +{ "label": "35/77", "node": 3668, "naklon": 6 }, +{ "label": "35/78", "node": 3681, "naklon": 6 }, +{ "label": "35/79", "node": 3670, "naklon": 6 }, +{ "label": "35/80", "node": 3689, "naklon": 6 }, +{ "label": "35/81", "node": 3678, "naklon": 6 }, +{ "label": "35/82", "node": 3693, "naklon": 6 }, +{ "label": "35/83", "node": 3654, "naklon": null }, +{ "label": "36/1", "node": 4086, "naklon": 0 }, +{ "label": "36/2", "node": 4085, "naklon": 0 }, +{ "label": "36/3", "node": 4083, "naklon": 0 }, +{ "label": "36/4", "node": 4087, "naklon": 0 }, +{ "label": "36/5", "node": 4077, "naklon": 0 }, +{ "label": "36/6", "node": 4082, "naklon": 0 }, +{ "label": "36/7", "node": 4186, "naklon": 0 }, +{ "label": "36/8", "node": 4206, "naklon": 0 }, +{ "label": "36/9", "node": 4080, "naklon": 0 }, +{ "label": "36/10", "node": 4081, "naklon": 0 }, +{ "label": "36/11", "node": 4210, "naklon": 0 }, +{ "label": "36/12", "node": 4079, "naklon": 0 }, +{ "label": "36/13", "node": 4076, "naklon": 0 }, +{ "label": "36/14", "node": 3852, "naklon": 0 }, +{ "label": "36/15", "node": 2813, "naklon": 0 }, +{ "label": "36/16", "node": 4219, "naklon": 0 }, +{ "label": "37/1A", "node": 3104, "naklon": 15 }, +{ "label": "37/1B", "node": 3121, "naklon": 15 }, +{ "label": "37/2", "node": 3113, "naklon": 10 }, +{ "label": "37/3", "node": 3118, "naklon": 10 }, +{ "label": "37/4", "node": 3111, "naklon": 10 }, +{ "label": "37/5", "node": 4020, "naklon": 10 }, +{ "label": "37/6", "node": 3119, "naklon": 10 }, +{ "label": "37/7", "node": 3110, "naklon": 10 }, +{ "label": "37/8", "node": 3108, "naklon": 10 }, +{ "label": "37/12", "node": 3107, "naklon": 0 }, +{ "label": "37/13", "node": 3199, "naklon": 0 }, +{ "label": "37/14", "node": 3120, "naklon": 0 }, +{ "label": "37/15", "node": 3122, "naklon": 0 }, +{ "label": "37/16", "node": 3908, "naklon": 0 }, +{ "label": "37/17", "node": 3114, "naklon": 0 }, +{ "label": "37/18", "node": 3105, "naklon": 0 }, +{ "label": "37/19", "node": 3116, "naklon": 0 }, +{ "label": "37/20", "node": 3106, "naklon": 0 }, +{ "label": "37/21", "node": 2887, "naklon": 5 }, +{ "label": "37/22", "node": 2888, "naklon": 5 }, +{ "label": "37/23", "node": 2877, "naklon": 5 }, +{ "label": "37/24", "node": 2891, "naklon": 5 }, +{ "label": "37/25", "node": 2886, "naklon": 5 }, +{ "label": "37/26", "node": 2892, "naklon": 5 }, +{ "label": "37/27", "node": 2882, "naklon": 5 }, +{ "label": "37/28", "node": 2883, "naklon": 5 }, +{ "label": "37/29", "node": 2876, "naklon": 5 }, +{ "label": "37/30", "node": 3109, "naklon": 5 }, +{ "label": "37/31", "node": 4152, "naklon": 5 }, +{ "label": "37/32", "node": 3117, "naklon": 5 }, +{ "label": "37/33", "node": 2870, "naklon": 5 }, +{ "label": "37/34", "node": 2867, "naklon": 0 }, +{ "label": "37/35", "node": 2865, "naklon": 0 }, +{ "label": "37/36", "node": 3096, "naklon": 0 }, +{ "label": "37/37", "node": 2871, "naklon": 0 }, +{ "label": "37/38", "node": 2884, "naklon": 0 }, +{ "label": "37/39", "node": 2855, "naklon": 0 }, +{ "label": "37/40", "node": 2878, "naklon": 0 }, +{ "label": "37/41", "node": 2889, "naklon": 0 }, +{ "label": "37/42", "node": 2879, "naklon": 0 }, +{ "label": "37/43", "node": 2850, "naklon": 0 }, +{ "label": "37/44", "node": 2894, "naklon": 0 }, +{ "label": "37/45", "node": 2880, "naklon": 0 }, +{ "label": "37/46", "node": 2893, "naklon": 0 }, +{ "label": "37/47", "node": 2890, "naklon": 0 }, +{ "label": "37/48", "node": 4355, "naklon": 0 }, +{ "label": "37/49", "node": 2885, "naklon": 0 }, +{ "label": "37/50", "node": 2875, "naklon": 0 }, +{ "label": "38/30A", "node": 3486, "naklon": 5 }, +{ "label": "38/30B", "node": 3714, "naklon": 0 }, +{ "label": "38/32A", "node": 3483, "naklon": 5 }, +{ "label": "38/32B", "node": 3496, "naklon": 0 }, +{ "label": "38/35A", "node": 3487, "naklon": 5 }, +{ "label": "38/35B", "node": 3498, "naklon": 5 }, +{ "label": "38/38A", "node": 3578, "naklon": 5 }, +{ "label": "38/38B", "node": 3508, "naklon": 5 }, +{ "label": "38/59A", "node": 3787, "naklon": 5 }, +{ "label": "38/59B", "node": 3491, "naklon": 5 }, +{ "label": "38/1", "node": 3568, "naklon": null }, +{ "label": "38/2", "node": 3502, "naklon": 0 }, +{ "label": "38/3", "node": 3836, "naklon": 0 }, +{ "label": "38/4", "node": 3588, "naklon": 0 }, +{ "label": "38/5", "node": 3493, "naklon": 0 }, +{ "label": "38/6", "node": 3580, "naklon": 0 }, +{ "label": "38/7", "node": 3572, "naklon": 0 }, +{ "label": "38/8", "node": 3506, "naklon": 0 }, +{ "label": "38/9", "node": 3503, "naklon": 0 }, +{ "label": "38/10", "node": 3579, "naklon": 0 }, +{ "label": "38/11", "node": 3586, "naklon": 0 }, +{ "label": "38/12", "node": 3495, "naklon": 5 }, +{ "label": "38/13", "node": 3492, "naklon": 5 }, +{ "label": "38/14", "node": 3532, "naklon": 5 }, +{ "label": "38/15", "node": 3574, "naklon": 5 }, +{ "label": "38/16", "node": 4140, "naklon": 5 }, +{ "label": "38/17", "node": 3795, "naklon": 5 }, +{ "label": "38/18", "node": 3788, "naklon": 5 }, +{ "label": "38/19", "node": 3796, "naklon": 5 }, +{ "label": "38/20", "node": 3797, "naklon": 5 }, +{ "label": "38/21", "node": 3798, "naklon": 5 }, +{ "label": "38/22", "node": 3786, "naklon": 5 }, +{ "label": "38/23", "node": 4067, "naklon": 5 }, +{ "label": "38/24", "node": 3773, "naklon": 5 }, +{ "label": "38/25", "node": 3774, "naklon": 5 }, +{ "label": "38/26", "node": 3789, "naklon": 5 }, +{ "label": "38/27", "node": 3520, "naklon": null }, +{ "label": "38/29", "node": 3577, "naklon": 5 }, +{ "label": "38/31", "node": 3530, "naklon": null }, +{ "label": "38/33", "node": 3488, "naklon": 5 }, +{ "label": "38/34", "node": 3505, "naklon": 5 }, +{ "label": "38/36", "node": 3497, "naklon": 5 }, +{ "label": "38/37", "node": 3490, "naklon": 5 }, +{ "label": "38/39", "node": 3585, "naklon": 5 }, +{ "label": "38/40", "node": 3582, "naklon": 5 }, +{ "label": "38/41", "node": 3507, "naklon": 5 }, +{ "label": "38/42", "node": 3484, "naklon": 5 }, +{ "label": "38/43", "node": 3501, "naklon": 5 }, +{ "label": "38/44", "node": 3581, "naklon": 5 }, +{ "label": "38/45", "node": 4192, "naklon": 5 }, +{ "label": "38/46", "node": 3576, "naklon": 5 }, +{ "label": "38/47", "node": 3489, "naklon": 5 }, +{ "label": "38/48", "node": 3573, "naklon": 5 }, +{ "label": "38/49", "node": 3504, "naklon": 5 }, +{ "label": "38/50", "node": 3794, "naklon": 5 }, +{ "label": "38/51", "node": 3485, "naklon": 5 }, +{ "label": "38/52", "node": 3482, "naklon": 5 }, +{ "label": "38/53", "node": 3575, "naklon": 5 }, +{ "label": "38/54", "node": 3499, "naklon": 5 }, +{ "label": "38/55", "node": 3494, "naklon": 5 }, +{ "label": "38/56", "node": 3583, "naklon": 5 }, +{ "label": "38/57", "node": 3570, "naklon": 5 }, +{ "label": "38/58", "node": 3500, "naklon": 0 }, +{ "label": "38/63", "node": 3510, "naklon": null }, +{ "label": "38/64", "node": 3512, "naklon": null }, +{ "label": "38/67", "node": 3535, "naklon": null }, +{ "label": "38/68", "node": 3531, "naklon": null }, +{ "label": "38/69", "node": 3537, "naklon": null }, +{ "label": "39/1", "node": 3522, "naklon": 10 }, +{ "label": "39/2", "node": 4018, "naklon": 10 }, +{ "label": "39/3", "node": 4019, "naklon": 10 }, +{ "label": "39/4", "node": 4154, "naklon": 5 }, +{ "label": "39/5", "node": 3907, "naklon": 5 }, +{ "label": "39/6", "node": 4148, "naklon": 0 }, +{ "label": "39/7", "node": 4153, "naklon": 0 }, +{ "label": "39/8", "node": 3938, "naklon": 0 }, +{ "label": "39/9", "node": 3802, "naklon": 0 }, +{ "label": "39/10", "node": 4015, "naklon": 0 }, +{ "label": "39/11", "node": 3929, "naklon": 0 }, +{ "label": "39/12", "node": 3946, "naklon": 0 }, +{ "label": "39/13", "node": 4014, "naklon": 0 }, +{ "label": "39/14", "node": 4155, "naklon": 0 }, +{ "label": "39/15", "node": 4149, "naklon": 0 }, +{ "label": "39/16", "node": 3642, "naklon": 0 }, +{ "label": "39/17", "node": 3636, "naklon": 5 }, +{ "label": "39/18", "node": 3991, "naklon": 0 }, +{ "label": "39/19", "node": 3994, "naklon": 0 }, +{ "label": "39/20", "node": 3990, "naklon": 0 }, +{ "label": "39/21", "node": 3967, "naklon": 0 }, +{ "label": "39/22", "node": 3977, "naklon": 0 }, +{ "label": "39/23", "node": 3757, "naklon": 15 }, +{ "label": "39/24", "node": 3633, "naklon": 15 }, +{ "label": "39/25", "node": 3744, "naklon": 15 }, +{ "label": "39/26", "node": 4023, "naklon": 5 }, +{ "label": "39/27", "node": 3720, "naklon": 5 }, +{ "label": "39/28", "node": 3734, "naklon": 5 }, +{ "label": "39/29", "node": 3741, "naklon": 5 }, +{ "label": "39/30", "node": 3721, "naklon": 5 }, +{ "label": "39/31", "node": 3845, "naklon": 0 }, +{ "label": "39/32", "node": 3840, "naklon": 0 }, +{ "label": "39/33", "node": 3837, "naklon": null }, +{ "label": "39/34", "node": 3839, "naklon": 0 }, +{ "label": "41/1", "node": 3542, "naklon": null }, +{ "label": "41/2", "node": 3566, "naklon": null }, +{ "label": "41/3", "node": 3548, "naklon": null }, +{ "label": "41/4", "node": 3515, "naklon": null }, +{ "label": "41/5", "node": 3559, "naklon": null }, +{ "label": "41/6", "node": 3509, "naklon": null }, +{ "label": "41/7", "node": 3524, "naklon": null }, +{ "label": "41/8", "node": 3518, "naklon": null }, +{ "label": "41/9", "node": 3182, "naklon": null }, +{ "label": "41/10", "node": 3187, "naklon": null }, +{ "label": "41/11", "node": 3195, "naklon": 0 }, +{ "label": "41/12", "node": 3857, "naklon": 0 }, +{ "label": "41/13", "node": 3183, "naklon": 0 }, +{ "label": "41/14", "node": 3177, "naklon": 0 }, +{ "label": "41/15", "node": 3189, "naklon": 0 }, +{ "label": "41/16", "node": 3186, "naklon": 0 }, +{ "label": "42/1", "node": 3178, "naklon": 0 }, +{ "label": "42/2", "node": 3219, "naklon": 0 }, +{ "label": "42/3", "node": 3475, "naklon": 0 }, +{ "label": "42/4", "node": 3175, "naklon": 0 }, +{ "label": "42/5", "node": 3222, "naklon": 0 }, +{ "label": "42/6", "node": 3221, "naklon": 0 }, +{ "label": "42/7", "node": 3181, "naklon": 0 }, +{ "label": "42/8", "node": 3180, "naklon": 0 }, +{ "label": "42/9", "node": 3218, "naklon": 0 }, +{ "label": "42/10", "node": 3176, "naklon": 0 }, +{ "label": "42/11", "node": 3174, "naklon": 0 }, +{ "label": "42/12", "node": 3220, "naklon": 0 }, +{ "label": "42/13", "node": 3533, "naklon": null }, +{ "label": "42/14", "node": 3543, "naklon": null }, +{ "label": "42/15", "node": 3554, "naklon": null }, +{ "label": "42/16", "node": 3549, "naklon": null }, +{ "label": "43/1", "node": 2857, "naklon": 5 }, +{ "label": "43/2", "node": 2752, "naklon": 5 }, +{ "label": "43/3", "node": 2753, "naklon": 5 }, +{ "label": "43/4", "node": 3024, "naklon": 5 }, +{ "label": "43/5", "node": 2754, "naklon": 5 }, +{ "label": "43/6", "node": 4423, "naklon": 5 }, +{ "label": "43/7", "node": 4368, "naklon": 5 }, +{ "label": "43/8", "node": 2978, "naklon": 5 }, +{ "label": "43/9", "node": 2868, "naklon": 5 }, +{ "label": "43/10", "node": 4377, "naklon": 5 }, +{ "label": "43/11", "node": 2757, "naklon": 5 }, +{ "label": "43/12", "node": 2970, "naklon": 5 }, +{ "label": "43/13", "node": 2758, "naklon": 5 }, +{ "label": "43/14", "node": 4378, "naklon": 5 }, +{ "label": "43/15", "node": 2759, "naklon": 5 }, +{ "label": "43/16", "node": 4342, "naklon": 5 }, +{ "label": "43/17", "node": 3026, "naklon": null }, +{ "label": "43/18", "node": 2986, "naklon": null }, +{ "label": "43/19", "node": 4343, "naklon": null }, +{ "label": "43/20", "node": 2760, "naklon": null }, +{ "label": "43/21", "node": 4379, "naklon": null }, +{ "label": "43/22", "node": 2971, "naklon": null }, +{ "label": "43/23", "node": 2761, "naklon": null }, +{ "label": "43/24", "node": 2762, "naklon": null }, +{ "label": "43/25", "node": 4339, "naklon": null }, +{ "label": "43/26", "node": 4380, "naklon": null }, +{ "label": "43/27", "node": 2975, "naklon": null }, +{ "label": "43/28", "node": 3003, "naklon": null }, +{ "label": "43/29", "node": 4338, "naklon": null }, +{ "label": "43/30", "node": 3002, "naklon": null }, +{ "label": "43/31", "node": 4345, "naklon": null }, +{ "label": "43/32", "node": 2979, "naklon": null }, +{ "label": "43/33", "node": 2989, "naklon": null }, +{ "label": "43/34", "node": 2996, "naklon": null }, +{ "label": "43/35", "node": 2972, "naklon": null }, +{ "label": "43/36", "node": 2988, "naklon": null }, +{ "label": "43/37", "node": 4344, "naklon": null }, +{ "label": "43/38", "node": 3022, "naklon": null }, +{ "label": "43/39", "node": 4341, "naklon": null }, +{ "label": "43/40", "node": 2983, "naklon": null }, +{ "label": "43/41", "node": 2995, "naklon": null }, +{ "label": "43/42", "node": 2763, "naklon": null }, +{ "label": "43/43", "node": 2764, "naklon": null }, +{ "label": "43/44", "node": 2765, "naklon": null }, +{ "label": "43/45", "node": 2766, "naklon": null }, +{ "label": "43/46", "node": 2767, "naklon": null }, +{ "label": "43/47", "node": 2768, "naklon": null }, +{ "label": "43/48", "node": 3018, "naklon": null }, +{ "label": "43/49", "node": 2982, "naklon": null }, +{ "label": "43/50", "node": 3019, "naklon": 0 }, +{ "label": "43/51", "node": 3013, "naklon": null }, +{ "label": "43/52", "node": 3007, "naklon": null }, +{ "label": "43/53", "node": 2980, "naklon": null }, +{ "label": "43/54", "node": 3011, "naklon": null }, +{ "label": "43/55", "node": 2672, "naklon": null }, +{ "label": "43/56", "node": 2673, "naklon": null }, +{ "label": "43/57", "node": 2674, "naklon": null }, +{ "label": "43/58", "node": 2675, "naklon": null }, +{ "label": "43/59", "node": 2676, "naklon": null }, +{ "label": "43/60", "node": 2677, "naklon": null }, +{ "label": "43/61", "node": 2678, "naklon": null }, +{ "label": "43/62", "node": 2679, "naklon": null }, +{ "label": "43/63", "node": 2680, "naklon": null }, +{ "label": "43/64", "node": 2840, "naklon": null }, +{ "label": "43/65", "node": 2682, "naklon": null }, +{ "label": "43/66", "node": 2683, "naklon": null }, +{ "label": "43/67", "node": 2684, "naklon": 0 }, +{ "label": "43/68", "node": 2685, "naklon": null }, +{ "label": "43/69", "node": 2686, "naklon": null }, +{ "label": "43/70", "node": 2687, "naklon": null }, +{ "label": "43/71", "node": 2688, "naklon": null }, +{ "label": "43/72", "node": 2689, "naklon": null }, +{ "label": "43/73", "node": 2690, "naklon": null }, +{ "label": "43/74", "node": 2691, "naklon": null }, +{ "label": "43/75", "node": 2692, "naklon": null }, +{ "label": "43/76", "node": 2693, "naklon": 0 }, +{ "label": "43/77", "node": 2694, "naklon": null }, +{ "label": "43/78", "node": 2695, "naklon": null }, +{ "label": "43/79", "node": 2696, "naklon": 0 }, +{ "label": "43/80", "node": 2697, "naklon": null }, +{ "label": "43/81", "node": 2698, "naklon": 0 }, +{ "label": "43/82", "node": 2699, "naklon": null }, +{ "label": "43/83", "node": 2700, "naklon": 0 }, +{ "label": "43/84", "node": 2744, "naklon": null }, +{ "label": "43/85", "node": 2745, "naklon": 0 }, +{ "label": "43/86", "node": 2746, "naklon": null }, +{ "label": "43/87", "node": 2747, "naklon": 0 }, +{ "label": "43/88", "node": 2748, "naklon": null }, +{ "label": "43/89", "node": 2749, "naklon": 0 }, +{ "label": "43/90", "node": 2841, "naklon": null }, +{ "label": "45/1", "node": 4237, "naklon": 5 }, +{ "label": "45/2", "node": 4226, "naklon": 5 }, +{ "label": "45/3", "node": 4242, "naklon": 5 }, +{ "label": "45/4", "node": 4179, "naklon": 5 }, +{ "label": "45/5", "node": 4247, "naklon": 5 }, +{ "label": "45/6", "node": 4245, "naklon": 5 }, +{ "label": "45/7", "node": 3872, "naklon": 5 }, +{ "label": "45/8", "node": 4175, "naklon": 5 }, +{ "label": "45/9", "node": 4236, "naklon": 5 }, +{ "label": "45/10", "node": 4170, "naklon": 5 }, +{ "label": "45/11", "node": 4238, "naklon": 5 }, +{ "label": "45/12", "node": 4246, "naklon": 5 }, +{ "label": "45/13", "node": 4166, "naklon": 5 }, +{ "label": "45/14", "node": 4227, "naklon": 5 }, +{ "label": "45/15", "node": 4171, "naklon": 5 }, +{ "label": "45/16", "node": 4180, "naklon": 5 }, +{ "label": "45/17", "node": 4244, "naklon": 5 }, +{ "label": "45/18", "node": 4199, "naklon": 5 }, +{ "label": "45/19", "node": 4239, "naklon": 5 }, +{ "label": "45/20", "node": 4207, "naklon": 5 }, +{ "label": "45/21", "node": 4223, "naklon": 5 }, +{ "label": "45/22", "node": 4230, "naklon": 5 }, +{ "label": "45/23", "node": 4233, "naklon": 5 }, +{ "label": "45/24", "node": 4222, "naklon": 5 }, +{ "label": "45/25", "node": 4217, "naklon": 5 }, +{ "label": "45/26", "node": 4243, "naklon": 5 }, +{ "label": "45/27", "node": 4200, "naklon": 5 }, +{ "label": "45/28", "node": 4228, "naklon": 5 }, +{ "label": "45/29", "node": 4211, "naklon": 5 }, +{ "label": "45/30", "node": 4234, "naklon": 5 }, +{ "label": "45/31", "node": 4235, "naklon": 5 }, +{ "label": "45/32", "node": 4203, "naklon": 5 }, +{ "label": "45/33", "node": 4240, "naklon": 5 }, +{ "label": "45/34", "node": 4224, "naklon": 5 }, +{ "label": "45/35", "node": 4232, "naklon": 5 }, +{ "label": "45/36", "node": 4231, "naklon": 5 }, +{ "label": "45/37", "node": 4161, "naklon": 5 }, +{ "label": "45/38", "node": 4225, "naklon": 5 }, +{ "label": "45/39", "node": 4241, "naklon": 5 }, +{ "label": "45/40", "node": 4229, "naklon": 5 }, +{ "label": "45/41", "node": 4221, "naklon": 5 }, +{ "label": "45/42", "node": 4212, "naklon": 5 }, +{ "label": "45/43", "node": 4216, "naklon": 5 }, +{ "label": "45/44", "node": 3864, "naklon": null }, +{ "label": "46/1", "node": 3806, "naklon": 5 }, +{ "label": "46/2", "node": 3813, "naklon": 5 }, +{ "label": "46/3", "node": 3815, "naklon": 5 }, +{ "label": "46/4", "node": 3807, "naklon": 5 }, +{ "label": "46/5", "node": 3895, "naklon": 5 }, +{ "label": "46/6", "node": 3809, "naklon": 5 }, +{ "label": "46/7", "node": 3820, "naklon": 5 }, +{ "label": "46/8", "node": 3805, "naklon": 5 }, +{ "label": "46/9", "node": 3894, "naklon": 0 }, +{ "label": "46/10", "node": 4055, "naklon": 0 }, +{ "label": "46/11", "node": 3812, "naklon": 5 }, +{ "label": "46/12", "node": 3822, "naklon": 5 }, +{ "label": "46/13", "node": 3821, "naklon": 5 }, +{ "label": "46/14", "node": 3808, "naklon": 5 }, +{ "label": "46/15", "node": 3799, "naklon": 5 }, +{ "label": "46/16", "node": 3816, "naklon": 5 }, +{ "label": "46/17", "node": 3751, "naklon": 5 }, +{ "label": "46/18", "node": 3814, "naklon": 5 }, +{ "label": "46/19", "node": 4044, "naklon": 0 }, +{ "label": "46/20", "node": 3931, "naklon": 0 }, +{ "label": "46/21", "node": 3902, "naklon": 5 }, +{ "label": "46/22", "node": 3916, "naklon": 5 }, +{ "label": "46/23", "node": 3892, "naklon": 5 }, +{ "label": "46/24", "node": 3914, "naklon": 5 }, +{ "label": "46/25", "node": 3898, "naklon": 5 }, +{ "label": "46/26", "node": 3897, "naklon": 5 }, +{ "label": "46/27", "node": 3885, "naklon": 5 }, +{ "label": "46/28", "node": 3906, "naklon": 5 }, +{ "label": "46/29", "node": 3930, "naklon": 0 }, +{ "label": "46/30", "node": 3936, "naklon": 0 }, +{ "label": "46/31", "node": 3860, "naklon": 5 }, +{ "label": "46/32", "node": 3841, "naklon": 5 }, +{ "label": "46/33", "node": 3873, "naklon": 5 }, +{ "label": "46/34", "node": 3854, "naklon": 5 }, +{ "label": "46/35", "node": 3939, "naklon": 5 }, +{ "label": "46/36", "node": 3858, "naklon": 5 }, +{ "label": "46/37", "node": 3940, "naklon": 5 }, +{ "label": "46/38", "node": 4035, "naklon": 5 }, +{ "label": "47/1", "node": 3373, "naklon": 0 }, +{ "label": "47/2", "node": 3374, "naklon": 0 }, +{ "label": "47/3", "node": 3384, "naklon": 0 }, +{ "label": "47/4", "node": 3385, "naklon": 0 }, +{ "label": "48/1", "node": 4051, "naklon": 5 }, +{ "label": "48/2", "node": 4041, "naklon": 5 }, +{ "label": "48/3", "node": 4056, "naklon": 5 }, +{ "label": "48/4", "node": 3875, "naklon": 5 }, +{ "label": "48/5", "node": 4061, "naklon": 5 }, +{ "label": "48/6", "node": 4047, "naklon": 5 }, +{ "label": "48/7", "node": 4060, "naklon": 5 }, +{ "label": "48/8", "node": 4059, "naklon": 5 }, +{ "label": "48/9", "node": 4058, "naklon": 5 }, +{ "label": "48/10", "node": 3635, "naklon": 5 }, +{ "label": "48/11", "node": 3640, "naklon": 5 }, +{ "label": "48/12", "node": 3747, "naklon": 5 }, +{ "label": "48/13", "node": 3629, "naklon": 5 }, +{ "label": "48/14", "node": 4048, "naklon": 5 }, +{ "label": "48/15", "node": 4063, "naklon": 5 }, +{ "label": "48/16", "node": 4062, "naklon": 5 }, +{ "label": "48/17", "node": 4043, "naklon": 5 }, +{ "label": "48/18", "node": 4052, "naklon": 5 }, +{ "label": "48/19", "node": 4042, "naklon": 5 }, +{ "label": "48/20", "node": 4053, "naklon": 5 }, +{ "label": "50/15A", "node": 4167, "naklon": null }, +{ "label": "50/15B", "node": 4159, "naklon": null }, +{ "label": "50/1", "node": 4183, "naklon": 0 }, +{ "label": "50/2", "node": 4157, "naklon": 0 }, +{ "label": "50/3", "node": 4160, "naklon": 0 }, +{ "label": "50/4", "node": 4173, "naklon": 0 }, +{ "label": "50/5", "node": 4177, "naklon": 0 }, +{ "label": "50/6", "node": 4174, "naklon": 0 }, +{ "label": "50/7", "node": 4178, "naklon": 0 }, +{ "label": "50/8", "node": 4195, "naklon": 0 }, +{ "label": "50/9", "node": 4169, "naklon": 0 }, +{ "label": "50/10", "node": 4162, "naklon": 0 }, +{ "label": "50/11", "node": 4158, "naklon": 0 }, +{ "label": "50/12", "node": 4182, "naklon": 0 }, +{ "label": "50/13", "node": 4194, "naklon": 0 }, +{ "label": "50/14", "node": 4184, "naklon": 0 }, +{ "label": "50/16", "node": 4197, "naklon": null }, +{ "label": "50/17", "node": 4164, "naklon": null }, +{ "label": "50/18", "node": 3306, "naklon": null }, +{ "label": "50/19", "node": 4168, "naklon": null }, +{ "label": "50/20", "node": 4193, "naklon": null }, +{ "label": "50/21", "node": 4187, "naklon": null }, +{ "label": "50/22", "node": 4163, "naklon": null }, +{ "label": "50/23", "node": 4165, "naklon": null }, +{ "label": "50/24", "node": 4185, "naklon": null }, +{ "label": "50/25", "node": 3904, "naklon": null }, +{ "label": "53/1", "node": 2619, "naklon": 0 }, +{ "label": "53/2", "node": 2623, "naklon": 0 }, +{ "label": "53/3", "node": 2617, "naklon": 0 }, +{ "label": "53/4", "node": 2622, "naklon": 0 }, +{ "label": "53/5", "node": 2618, "naklon": 0 }, +{ "label": "53/6", "node": 2626, "naklon": 0 }, +{ "label": "53/7", "node": 2869, "naklon": 0 }, +{ "label": "53/8", "node": 2613, "naklon": 0 }, +{ "label": "53/9", "node": 2608, "naklon": 0 }, +{ "label": "53/10", "node": 2611, "naklon": 0 }, +{ "label": "53/11", "node": 2598, "naklon": 0 }, +{ "label": "53/12", "node": 3528, "naklon": 0 }, +{ "label": "53/13", "node": 3545, "naklon": 0 }, +{ "label": "53/14", "node": 2620, "naklon": 0 }, +{ "label": "53/15", "node": 2612, "naklon": 0 }, +{ "label": "53/16", "node": 2615, "naklon": 0 }, +{ "label": "53/17", "node": 3722, "naklon": 0 }, +{ "label": "53/18", "node": 2624, "naklon": 0 }, +{ "label": "53/19", "node": 2609, "naklon": 0 }, +{ "label": "53/20", "node": 2625, "naklon": 0 }, +{ "label": "53/21", "node": 2602, "naklon": 0 }, +{ "label": "53/22", "node": 2610, "naklon": 0 }, +{ "label": "53/23", "node": 2599, "naklon": 0 }, +{ "label": "53/24", "node": 2605, "naklon": 0 }, +{ "label": "53/25", "node": 2593, "naklon": 0 }, +{ "label": "53/26", "node": 3074, "naklon": 0 }, +{ "label": "53/27", "node": 2740, "naklon": 0 }, +{ "label": "53/28", "node": 2614, "naklon": 0 }, +{ "label": "53/29", "node": 2601, "naklon": 0 }, +{ "label": "53/30", "node": 4196, "naklon": 0 }, +{ "label": "53/31", "node": 2607, "naklon": 0 }, +{ "label": "53/32", "node": 2582, "naklon": 0 }, +{ "label": "53/33", "node": 2594, "naklon": 0 }, +{ "label": "53/34", "node": 2589, "naklon": 0 }, +{ "label": "53/35", "node": 2596, "naklon": 0 }, +{ "label": "53/36", "node": 2603, "naklon": 0 }, +{ "label": "53/37", "node": 2597, "naklon": 0 }, +{ "label": "53/38", "node": 2590, "naklon": 0 }, +{ "label": "53/39", "node": 2581, "naklon": 0 }, +{ "label": "53/40", "node": 2583, "naklon": 0 }, +{ "label": "53/41", "node": 2580, "naklon": 0 }, +{ "label": "53/42", "node": 2579, "naklon": 0 }, +{ "label": "53/43", "node": 2797, "naklon": 0 }, +{ "label": "53/44", "node": 2577, "naklon": 0 }, +{ "label": "53/45", "node": 2586, "naklon": 0 }, +{ "label": "53/46", "node": 2588, "naklon": 0 }, +{ "label": "53/47", "node": 2591, "naklon": 0 }, +{ "label": "53/48", "node": 2592, "naklon": 0 }, +{ "label": "53/49", "node": 2573, "naklon": 0 }, +{ "label": "53/50", "node": 2595, "naklon": 0 }, +{ "label": "53/51", "node": 2587, "naklon": 0 }, +{ "label": "53/52", "node": 2578, "naklon": 0 }, +{ "label": "53/53", "node": 2574, "naklon": 0 }, +{ "label": "53/54", "node": 2571, "naklon": 0 }, +{ "label": "53/55", "node": 2570, "naklon": 0 }, +{ "label": "53/56", "node": 2576, "naklon": 0 }, +{ "label": "53/57", "node": 2881, "naklon": 0 }, +{ "label": "53/58", "node": 2575, "naklon": 0 }, +{ "label": "53/59", "node": 2572, "naklon": 0 }, +{ "label": "53/60", "node": 2569, "naklon": 0 }, +{ "label": "55/1", "node": 4324, "naklon": 0 }, +{ "label": "55/2", "node": 4319, "naklon": 0 }, +{ "label": "55/3", "node": 4327, "naklon": 0 }, +{ "label": "55/4", "node": 4333, "naklon": 0 }, +{ "label": "55/5", "node": 4332, "naklon": 0 }, +{ "label": "55/6", "node": 4320, "naklon": 0 }, +{ "label": "55/7", "node": 4317, "naklon": 0 }, +{ "label": "55/8", "node": 4318, "naklon": 0 }, +{ "label": "55/9", "node": 4328, "naklon": 0 }, +{ "label": "55/10", "node": 4323, "naklon": 0 }, +{ "label": "55/11", "node": 4325, "naklon": 0 }, +{ "label": "55/12", "node": 4326, "naklon": 0 }, +{ "label": "55/13", "node": 4316, "naklon": 0 }, +{ "label": "55/14", "node": 4322, "naklon": 0 }, +{ "label": "55/15", "node": 4331, "naklon": 0 }, +{ "label": "55/16", "node": 4321, "naklon": 0 }, +{ "label": "55/17", "node": 4315, "naklon": 0 }, +{ "label": "55/18", "node": 4329, "naklon": 0 }, +{ "label": "55/19", "node": 4334, "naklon": 0 }, +{ "label": "55/20", "node": 4330, "naklon": 0 } +]; + +module.exports = { naklony }; diff --git a/RVO3/databases/modbus_config.js b/RVO3/databases/modbus_config.js new file mode 100755 index 0000000..b73116a --- /dev/null +++ b/RVO3/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/RVO3/databases/nodes.table b/RVO3/databases/nodes.table new file mode 100755 index 0000000..0f4ee51 --- /dev/null +++ b/RVO3/databases/nodes.table @@ -0,0 +1 @@ +node:number|pole_number:string|node_type:string|tbname:string|line:number|profile:string|processed:boolean|status:boolean|time_of_last_communication:number \ No newline at end of file diff --git a/RVO3/databases/nodes_original/nodes_original.table b/RVO3/databases/nodes_original/nodes_original.table new file mode 100755 index 0000000..0637a08 --- /dev/null +++ b/RVO3/databases/nodes_original/nodes_original.table @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/RVO3/databases/notifications.table b/RVO3/databases/notifications.table new file mode 100755 index 0000000..f7c96cb --- /dev/null +++ b/RVO3/databases/notifications.table @@ -0,0 +1,41 @@ +key:string|weight:string|sk:string|en:string ++|switching_profile_point_applied_to_line|INFORMATIONAL|Aplikovaný bod spínacieho profilu na línií č. ${line} : ${value}|Switching profile point applied to line no. ${line} : ${value}|............... ++|dusk_has_occured|INFORMATIONAL|Nastal súmrak: ${value}|Dusk has occured: ${value}|............... ++|dawn_has_occured|INFORMATIONAL|Nastal úsvit: ${value}|Dawn has occured: ${value}|............... ++|dimming_profile_was_successfully_received_by_node|NOTICE|Stmievací profil bol úspešne prijatý nodom č. ${node}|Dimming profile was successfully received by node no. ${node}|............... ++|master_node_is_responding_again|NOTICE|Master node začal znovu odpovedať|Master node is responding again|............... ++|command_was_sent_from_terminal_interface|DEBUG|Z terminálu bol odoslaný príkaz|A command was sent from terminal interface|............... ++|master_node_is_not_responding|ALERT|Master node neodpovedá|Master node is not responding|............... ++|configuration_of_dimming_profile_to_node_failed|ALERT|Konfigurácia stmievacieho profilu pre node č. ${node} zlyhala|Configuration of dimming profile to node no. ${node} has failed|............... ++|circuit_breaker_was_turned_on_line|NOTICE|Zapnutie ističa na línii č. ${line}|Circuit breaker was turned on - line no. ${line}|............... ++|circuit_breaker_was_turned_off_line|ERROR|Vypnutie ističa na línií č. ${line}|Circuit breaker was turned off - line no. ${line}|............... ++|dimming_profile_was_processed_for_node|INFORMATIONAL|Stmievací profil bol spracovaný pre node č. ${node}|Dimming profile was processed for node no. ${node}|............... ++|switching_profile_was_processed_for_line|INFORMATIONAL|Spínací profil bol spracovaný pre líniu č. ${line}|Switching profile was processed for line no. ${line}|............... ++|thermometer_is_not_responding|WARNING|Teplomer neodpovedá|Thermometer is not responding|............... ++|thermometer_is_responding_again|NOTICE|Teplomer znovu odpovedá|Thermometer is responding again|............... ++|thermometer_sends_invalid_data|WARNING|Teplomer posiela neplatné hodnoty|Thermometer sends invalid data|............... ++|main_switch_has_been_turned_off|CRITICAL|Hlavný vypínač bol vypnutý|Main switch has been turned off|............... ++|main_switch_has_been_turned_on|NOTICE|Hlavný vypínač bol zapnutý|Main switch has been turned on|............... ++|power_supply_has_disconnected_input|ALERT|Napájací zdroj nemá napätie na vstupe|Power supply has disconnected input|............... ++|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_main_open|NOTICE|Hlavné dvere boli otvorené|Main door has been opened|............... ++|door_em_open|NOTICE|Dvere silovej časti boli otvorené|Power door has been opened|............... ++|door_main_open_without_permission|WARNING|Hlavné dvere boli otvorené bez povolenia - zapnutá siréna|Main door has been opened without permission - alarm is on|............... ++|door_em_open_without_permission|WARNING|Dvere silovej časti boli otvorené bez povolenia|Power door has been opened without permission|............... ++|door_main_close|NOTICE|Hlavné dvere boli zatvorené|Main door has been closed|............... ++|door_em_close|NOTICE|Dvere silovej časti boli zatvorené|Power door has been closed|............... ++|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|............... ++|electrometer_ok|NOTICE|Elektromer znovu odpovedá|Electrometer is responding again|............... ++|no_voltage_on_phase|CRITICAL|Na fáze č. ${phase} nie je napätie|No voltage detected on phase no. ${phase}|............... ++|voltage_on_phase_restored|NOTICE|Napätie na fáze č. ${phase} bolo obnovené|Voltage on phase no. ${phase} has been restored|............... ++|flow_start|NOTICE|FLOW bol spustený|FLOW has been started |............... ++|twilight_sensor_nok|ERROR|Sensor súmraku neodpovedá|Twilight sensor is not responding|............... ++|twilight_sensor_ok|NOTICE|Sensor súmraku znovu odpovedá|Twilight sensor is responding again|............... ++|lamps_have_turned_on|NOTICE|Lampy sa zapli|Lamps have turned on|............... ++|lamps_have_turned_off|NOTICE|Lampy sa vypli|Lamps have turned off|............... ++|flow_restart|NOTICE|FLOW bol reštartovaný|FLOW has been restarted|............... ++|nodes_db_changed|NOTICE|Zmena v node databáze|Node db has changed|............... diff --git a/RVO3/databases/pins.table b/RVO3/databases/pins.table new file mode 100755 index 0000000..e464faf --- /dev/null +++ b/RVO3/databases/pins.table @@ -0,0 +1,14 @@ +pin:string|type:string|line:number +*|input1_01|door_condition|0|........... +*|input1_02|rotary_switch_state|0|........... +*|input1_03|rotary_switch_state|0|........... +*|input1_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|........... +*|28E7369D0E000022|temperature|0|........... +*|twilight_sensor|twilight_sensor|0|........... diff --git a/RVO3/databases/relays.table b/RVO3/databases/relays.table new file mode 100755 index 0000000..d9fee4e --- /dev/null +++ b/RVO3/databases/relays.table @@ -0,0 +1,5 @@ +line:number|tbname:string|contactor:number|profile:string ++|0|dz4ojlpP85JMgDLZWkQJ4D7aKYqQexEr62GXRV1y|1||........... ++|1|2O14VBzl8aDmWdNw3A51omAGyZ5qLJoEMpj6R9ng|9|{"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":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":15,"dusk_lux_sensor_value":15,"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}|........... ++|2|pE5X8NQPaow6vlOZxk6gG87q42ezGBMyWgDVjR3L|9|{"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":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":15,"dusk_lux_sensor_value":15,"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}|........... ++|3|6lQGaY9RDywdVzObj0P1NDkPg4NBn3exEK51LWZq|9|{"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":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":15,"dusk_lux_sensor_value":15,"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}|........... diff --git a/RVO3/databases/settings.table b/RVO3/databases/settings.table new file mode 100755 index 0000000..7887606 --- /dev/null +++ b/RVO3/databases/settings.table @@ -0,0 +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|project_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|cloud_topic:string|has_main_switch:boolean|daily_report:boolean|send_changed_node_numbers:boolean ++|rvo_senica_3_ip119|en|28.E7369D0E0000|48.70826502|17.28455203|192.168.252.1|rvo_senica_3_ip119|IVg2m3KmpqIJgE0VXmjw|1883|0|73|unipi|ttyUSB0|1|20|5|6|3|u119|0|1|1|................................................... diff --git a/RVO3/databases/tbdata.nosql b/RVO3/databases/tbdata.nosql new file mode 100755 index 0000000..c926fc1 --- /dev/null +++ b/RVO3/databases/tbdata.nosql @@ -0,0 +1,4 @@ +-"dz4ojlpP85JMgDLZWkQJ4D7aKYqQexEr62GXRV1y":[{"ts":1760520843384,"values":{"_event":{"type":"notice","status":"new","source":{"func":"modbus_reader","component":"1699965957410","component_name":"Modbus reader","edge":"dz4ojlpP85JMgDLZWkQJ4D7aKYqQexEr62GXRV1y"},"message":{"sk":"rvo_senica_3_ip119: FLOW bol reštartovaný","en":"rvo_senica_3_ip119: FLOW has been restarted"},"message_data":""}}}],"id":"3000154001gw71b"} +-"dz4ojlpP85JMgDLZWkQJ4D7aKYqQexEr62GXRV1y":[{"ts":1760520843457,"values":{"edge_fw_version":"2025-10-08","maintenance_mode":false}}],"id":"3000154002gw70b"} +-"dz4ojlpP85JMgDLZWkQJ4D7aKYqQexEr62GXRV1y":[{"ts":1760520843471,"values":{"statecode":2,"power_mode":"Automatic"}}],"id":"3000154004gw70b"} +-"dz4ojlpP85JMgDLZWkQJ4D7aKYqQexEr62GXRV1y":[{"ts":1760520843499,"values":{"_event":{"type":"notice","status":"new","source":{"func":"rsPort.open()","component":"1699963668903","component_name":"DIDO_Controller","edge":"dz4ojlpP85JMgDLZWkQJ4D7aKYqQexEr62GXRV1y"},"message":{"sk":"rvo_senica_3_ip119: FLOW bol spustený","en":"rvo_senica_3_ip119: FLOW has been started "},"message_data":""}}}],"id":"3000154006gw70b"} diff --git a/RVO3/databases/tbdatacloud.nosql b/RVO3/databases/tbdatacloud.nosql new file mode 100755 index 0000000..d5992ce --- /dev/null +++ b/RVO3/databases/tbdatacloud.nosql @@ -0,0 +1,3 @@ +-"dz4ojlpP85JMgDLZWkQJ4D7aKYqQexEr62GXRV1y":[{"ts":1760520843457,"values":{"edge_fw_version":"2025-10-08","maintenance_mode":false}}],"id":"3000154003gw71b"} +-"dz4ojlpP85JMgDLZWkQJ4D7aKYqQexEr62GXRV1y":[{"ts":1760520843471,"values":{"statecode":2,"power_mode":"Automatic"}}],"id":"3000154005gw71b"} +-"dz4ojlpP85JMgDLZWkQJ4D7aKYqQexEr62GXRV1y":[{"ts":1760520843499,"values":{"_event":{"type":"notice","status":"new","source":{"func":"rsPort.open()","component":"1699963668903","component_name":"DIDO_Controller","edge":"dz4ojlpP85JMgDLZWkQJ4D7aKYqQexEr62GXRV1y"},"message":{"sk":"rvo_senica_3_ip119: FLOW bol spustený","en":"rvo_senica_3_ip119: FLOW has been started "},"message_data":""}}}],"id":"3000154007gw71b"} diff --git a/RVO3/databases/total_energy.js b/RVO3/databases/total_energy.js new file mode 100755 index 0000000..dde340e --- /dev/null +++ b/RVO3/databases/total_energy.js @@ -0,0 +1,38 @@ +//key is rvo_number, value is max energy when lamps are on +const total_energy = { + 1: 580, + 2: 1100, + 3: 3700, + 4: 4100, + 7: 360, + 12: 1700, + 13: 5400, + 14: 440, + 15: 6100, + 16: 4800, + 20: 1600, + 21: 1000, + 22: 2600, + 23: 1000, + 25: 2600, + 33: 240, + 34: 4000, + 35: 2700, + 36: 820, + 37: 1400, + 35: 3500, + 39: 1170, + 41: 740, + 42: 660, + 43: 4900, + 45: 930, + 46: 700, + 47: 1100, + 48: 1500, + 50: 3200, + 53: 1250, + 55: 1000, + 56: 5500 +} + +module.exports = total_energy; diff --git a/RVO3/debug.js b/RVO3/debug.js new file mode 100755 index 0000000..9818194 --- /dev/null +++ b/RVO3/debug.js @@ -0,0 +1,16 @@ +// =================================================== +// FOR DEVELOPMENT +// Total.js - framework for Node.js platform +// https://www.totaljs.com +// =================================================== + +const options = {}; + +// options.ip = '127.0.0.1'; +// options.port = parseInt(process.argv[2]); +// options.config = { name: 'Total.js' }; +// options.sleep = 3000; +// options.inspector = 9229; +// options.watch = ['private']; + +require('total.js/debug')(options); \ No newline at end of file diff --git a/RVO3/err.txt b/RVO3/err.txt new file mode 100755 index 0000000..e890231 --- /dev/null +++ b/RVO3/err.txt @@ -0,0 +1,33 @@ +[2025-09-23T14:05:47.424] [ERROR] errLogs - uncaughtException: Cannot read property 'getHours' of undefined +[2025-09-23T14:05:47.425] [ERROR] errLogs - TypeError: Cannot read property 'getHours' of undefined + at Timeout.emptyReportToSend [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:05:47.426] [ERROR] errLogs - uncaughtException: Cannot read property 'getHours' of undefined +[2025-09-23T14:05:47.427] [ERROR] errLogs - TypeError: Cannot read property 'getHours' of undefined + at Timeout.emptyReportToSend [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:05:47.436] [ERROR] errLogs - uncaughtException: Cannot read property 'getHours' of undefined +[2025-09-23T14:05:47.436] [ERROR] errLogs - TypeError: Cannot read property 'getHours' of undefined + at Timeout.emptyReportToSend [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:05:53.147] [ERROR] errLogs - uncaughtException: date.getHours is not a function +[2025-09-23T14:05:53.148] [ERROR] errLogs - TypeError: date.getHours is not a function + at emptyReportToSend (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at Timeout.dailyReportCheck [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1351:5) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:05:53.148] [ERROR] errLogs - uncaughtException: date.getHours is not a function +[2025-09-23T14:05:53.149] [ERROR] errLogs - TypeError: date.getHours is not a function + at emptyReportToSend (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at Timeout.dailyReportCheck [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1351:5) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:05:53.153] [ERROR] errLogs - uncaughtException: date.getHours is not a function +[2025-09-23T14:05:53.154] [ERROR] errLogs - TypeError: date.getHours is not a function + at emptyReportToSend (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at Timeout.dailyReportCheck [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1351:5) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) diff --git a/RVO3/flow/cloudmqttconnect.js b/RVO3/flow/cloudmqttconnect.js new file mode 100755 index 0000000..b03491f --- /dev/null +++ b/RVO3/flow/cloudmqttconnect.js @@ -0,0 +1,357 @@ +exports.id = 'cloudmqttconnect'; +exports.title = 'Cloud connect mqtt'; +exports.group = 'MQTT'; +exports.color = '#888600'; +exports.version = '1.0.2'; +exports.icon = 'sign-out'; +exports.input = 2; +exports.output = 2; +exports.options = { host: 'tb-stage.worksys.io', port: 1883, clientid: "", username: "" }; + +exports.html = `
+
+
+
Hostname or IP address (if not empty - setting will override db setting)
+
+
+
Port
+
+
+
+
+
@(Client id)
+
+
+
topic
+
+
+
`; + + + +const { promisifyBuilder } = require('./helper/db_helper'); +const fs = require('fs'); +const mqtt = require('mqtt'); +const nosql = NOSQL('tbdatacloud'); + +const SEND_TO = { + debug: 0, + rpcCall: 1, +} + +//CONFIG +let saveTelemetryOnError = true;//backup_on_failure overrides this value +//------------------------ + +const noSqlFileSizeLimit = 4194304;//use 5MB - 4194304 +let insertNoSqlCounter = 0; +let insertBackupNoSqlCounter = 0; +let processingData = false; + +let backup_on_failure = true;//== saveTelemetryOnError - create backup client send failure +let restore_from_backup = 50; //how many rows process at once? +let restore_backup_wait = 3;//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; + + +exports.install = function(instance) { + + var client; + var opts; + var clientReady = false; + + let o = {}; //options + + function main() { + loadSettings(); + } + + //set opts according to db settings + function loadSettings() { + + o = instance.options; + if (!o.topic) o.topic = FLOW.GLOBALS.settings.cloud_topic; + + opts = { + host: o.host, + port: o.port, + clientId: o.clientid, + username: o.username, + rejectUnauthorized: false, + resubscribe: false + }; + + console.log("wsmqttpublich -> loadSettings from instance.options", o); + + if (!o.topic) { + instance.status("Not configured", "white"); + console.log("Cloud mqtt connect: no topic selected"); + return; + } + + connectToTbServer(); + } + + function connectToTbServer() { + var url = "mqtt://" + opts.host + ":" + opts.port; + console.log("MQTT URL: ", url); + + client = mqtt.connect(url, opts); + + client.on('connect', function() { + client.subscribe(`${o.topic}_backward`, (err) => { + if (!err) { + console.log("MQTT subscribed"); + } + }); + instance.status("Connected", "green"); + clientReady = true; + sendClientError = true; + }); + + client.on('reconnect', function() { + instance.status("Reconnecting", "yellow"); + clientReady = false; + }); + + client.on('message', function(topic, message) { + // message is type of buffer + message = message.toString(); + if (message[0] === '{') { + TRY(function() { + + message = JSON.parse(message); + if (message.hasOwnProperty("device") && message.hasOwnProperty("data") && message.data.hasOwnProperty("id")) { + client.publish(`${o.topic}_forward`, `{"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 } }); + } + + }, () => instance.debug('MQTT: Error parsing data', message)); + } + + instance.send(SEND_TO.rpcCall, { "topic": o.topic, "content": message }); + }); + + client.on('close', function() { + clientReady = false; + + instance.status("Disconnected", "red"); + instance.send(SEND_TO.debug, { "message": "Client CLOSE signal received !" }); + }); + + client.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) { + console.log('MQTT client error', err); + sendClientError = false; + } + clientReady = false; + }); + + } + + + instance.on('0', function(data) { + + if (clientReady) { + //do we have some data in backup file? if any, process data from database + if (saveTelemetryOnError) { + //read telemetry data and send back to server + if (!processingData) processDataFromDatabase(); + } + + let stringifiedJson = JSON.stringify(data.data) + client.publish(`${o.topic}_forward`, stringifiedJson, { qos: 1 }); + } + 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 (saveTelemetryOnError && o.topic) { + //create new file from tbdata.nosql, if file size exceeds given limit, and clear tbdata.nosql + makeBackupFromDbFile(); + + //write to tb + data.data.id = UID(); + nosql.insert(data.data); + } + } + }); + + instance.on("1", _ => { + main(); + }) + + instance.close = function(done) { + if (clientReady) { + client.end(); + } + }; + + + function getDbBackupFileCounter(type) { + var files = fs.readdirSync(__dirname + "/../databases"); + + let counter = 0; + for (var i = 0; i < files.length; i++) { + + if (files[i] == "tbdatacloud.nosql") continue; + + if (files[i].endsWith(".nosql")) { + + let pos = files[i].indexOf("."); + if (pos > -1) { + + let fileCounter = counter; + let firstDigit = files[i].slice(0, pos); + + fileCounter = parseInt(firstDigit); + if (isNaN(fileCounter)) fileCounter = 0; + //console.log("getDbBackupFileCounter digit:", files[i], firstDigit, fileCounter, isNaN(fileCounter), type); + + if (type == "max") { + if (fileCounter > counter) { + counter = fileCounter; + } + } + else if (type == "min") { + if (counter == 0) counter = fileCounter; + + if (fileCounter < counter) { + counter = fileCounter; + } + } + } + } + + } + + if (type == "max") counter++; + + return counter; + } + + const makeBackupFromDbFile = async () => { + + if (!saveTelemetryOnError) return; + + //to avoid large file: tbdata.nosql + + //init value is 0! + if (insertNoSqlCounter > 0) { + --insertNoSqlCounter; + return; + } + + insertNoSqlCounter = 100; + + let source = __dirname + "/../databases/tbdatacloud.nosql"; + + var stats = fs.statSync(source); + var fileSizeInBytes = stats.size; + + if (fileSizeInBytes > noSqlFileSizeLimit) { + + let counter = 1; + counter = getDbBackupFileCounter("max"); + + let destination = __dirname + "/../databases/" + counter + "." + "tbdatacloud.nosql"; + + //make backup file + fs.copyFileSync(source, destination); + //fs.renameSync(p, p + "." + counter); + + //clear tbdata.nosql + fs.writeFileSync(source, ""); + fs.truncateSync(source, 0); + + } + } + + const processDataFromDatabase = async () => { + + if (restore_from_backup <= 0) return; + + //calculate diff + const now = new Date(); + let currentTime = now.getTime(); + let diff = currentTime - lastRestoreTime; + + if ((diff / 1000) < restore_backup_wait) { + //console.log("*********restore_backup_wait", diff, restore_backup_wait); + return; + } + + processingData = true; + + //get filename to process + let counter = getDbBackupFileCounter("min"); + + //we have some backup files + let dataBase = 'tbdata'; + + var nosql; + if (counter == 0) dataBase = 'tbdatacloud'; + else dataBase = counter + "." + 'tbdatacloud'; + + nosql = NOSQL(dataBase); + + //select all data - use limit restore_from_backup + let records = await promisifyBuilder(nosql.find().take(restore_from_backup)); + + for (let i = 0; i < records.length; i++) { + if (clientReady) { + + let item = records[i]; + let id = item.id; + + if (id !== undefined) { + //console.log("------------processDataFromDatabase - remove", id, dataBase, i); + + try { + + let message = JSON.parse(JSON.stringify(item)); + delete message.id; + client.publish(`${o.topic}_forward`, JSON.stringify(message), { qos: 1 }); + + //remove from database + await promisifyBuilder(nosql.remove().where("id", id)); + + } catch (error) { + //process error + console.log("processDataFromDatabase", error); + } + + } + + } + else { + processingData = false; + return; + } + } + + if (records.length > 0) { + //clean backup file + if (counter > 0) nosql.clean(); + } + + //no data in db, remove + if (records.length == 0) { + if (counter > 0) nosql.drop(); + } + + const d = new Date(); + lastRestoreTime = d.getTime(); + + processingData = false; + + } + + instance.on('options', main); + +}; diff --git a/RVO3/flow/cmd_manager.js b/RVO3/flow/cmd_manager.js new file mode 100755 index 0000000..25912df --- /dev/null +++ b/RVO3/flow/cmd_manager.js @@ -0,0 +1,3071 @@ +exports.id = 'cmd_manager'; +exports.title = 'CMD Manager'; +exports.group = 'Worksys'; +exports.color = '#5D9CEC'; +exports.version = '0.0.3'; +exports.output = ['red', 'blue', 'yellow', 'blue', 'white', 'green']; +exports.input = 3; +exports.icon = 'cloud-upload'; + +exports.html = ` +
+
+
+
RPC - run RPC calls

+
+
+
@(User)
+
+
+
@(Password)
+
+
+
@(My edge)
+
+
+
+`; +exports.readme = `Manager for CMD calls`; + + +exports.install = function(instance) { + + 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, isEmptyObject, emptyJsObject, writeToFile, addToArrayIfUnique } = require('./helper/utils'); + const bitwise = require('bitwise'); + + var SunCalc = require('./helper/suncalc'); + const DataToTbHandler = require('./helper/DataToTbHandler'); + const errorHandler = require('./helper/ErrorToServiceHandler'); + const { sendNotification } = require('./helper/notification_reporter'); + const process = require('process'); + const { errLogger, logger, monitor } = require('./helper/logger'); + + //for accelerometer purposes + const { naklony } = require("../databases/accelerometer_db"); + + const dbNodes = TABLE("nodes"); + const dbRelays = TABLE("relays"); + + let GLOBALS; + let SETTINGS; + let rsPort; + let tbHandler; + + // runTasks intervals + const SHORT_INTERVAL = 30; + const LONG_INTERVAL = 300; + + //send data to following instances: + const SEND_TO = { + debug: 0, + tb: 1, + http_response: 2, + dido_controller: 3, + infoSender: 4, + dailyReport: 5 + } + + 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 + } + + 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 sendNodeReadout = null; // interval for sending agregate data from node + + 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["1"] = minutes; // dimming + priorities["76"] = minutes; // power + + minutes = 5; + priorities["75"] = minutes; // current + priorities["79"] = minutes; // energy + priorities["87"] = minutes; // aktualny cas + //priorities["84"] = minutes; //accelerometer + + minutes = 10; + priorities["74"] = minutes; // voltage + priorities["77"] = minutes; // power factor + priorities["78"] = minutes; // frequency + + minutes = 60; + priorities["0"] = minutes; // statecode + priorities["6"] = minutes; // dusk + priorities["7"] = minutes; // dawn + priorities["8"] = minutes; // profile + + minutes = 60 * 24; + priorities["89"] = minutes; // verzia fw + priorities["80"] = minutes; // lifetime + + //prikazy kt sa budu spustat na dany node - see config.js in terminal-oms.app. (1 - dimming) + let listOfCommands = [0, 1, 6, 7, 8, 74, 75, 76, 77, 78, 79, 80, 87, 89]; + + 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; + + // holds dusk, dawn (and more) values + let sunCalcResult; + + //helper container for counting resolved group of commands (commands related to set profile) + let cmdCounter = {};//key is node, value is counter + + //TODO: is this set working?? According to previous checks, sets do not work + //if sending of profile to node fails, we send notification and push node into set, so we do not send notification twice + const nodeProfileSendFail = new Set(); + + //we expect to get current temperature in Senica from senica-prod01 + let temperatureInSenica = null; + let accelerometerInterval = null; + + //NOTE: daily reports senica: + //rvo_is_on status, we monitor all nodes - if true, power and dimming should be not 0, if false, 24/7 nodes should be 0, other rvo should not respond + let rvo_is_on; + let previous_rvo_is_on_value; + let handleDailyReport; //setInterval for dailyReportHandler function + let dailyReport = {}; //data needed for daily report + let reportToSend = {}; //final report which we send to cloud + let breakerCounter = null; // status of breakers after flow starts is not in report + let rvoPeriod; // interval of checking dusk dawn and if rvo_is_on + let initialReportStatus = false; + + const DAILY_REPORT_HANDLER_TIME = 3_600_000; + const SET_SUNCALC_RESULT_TIME = 3_600_000; + const SET_RVO_PERIOD_TIME = 300_000; + const ADD_NODE_TO_REPORT_TIME = 3_600_000; + + //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); + + let now = new Date(); + console.log("Cmd-mngr installed", now.toLocaleString("sk-SK")); + + sunCalcResult = calculateDuskDawn(); + + handleRsPort(); + + customTasksInterval = setInterval(reportEdgeDateTimeAndNumberOfLuminaires, 120_000); + setTimeout(reportEdgeDateTimeAndNumberOfLuminaires, 4000); + + //dailyReport related + emptyReportToSend(); + breakerCounter = Object.keys(relaysData).length - 1; // we get number of lines (breakers) except of line 0 + rvoPeriod = setInterval(setRvoPeriod, SET_RVO_PERIOD_TIME); + setTimeout(setRvoPeriod, 3000); + setInterval(setSunCalcResult, SET_SUNCALC_RESULT_TIME); + handleDailyReport = setInterval(dailyReportHandler, DAILY_REPORT_HANDLER_TIME); + + + setCorrectTime = setInterval(setCorrectPlcTimeOnceADay, 60000 * 60); // 1 hour + setCorrectPlcTimeOnceADay(); + + sendNodeReadout = setInterval(sendNodesData, 150_000); + accelerometerInterval = setInterval(accelerometerData, 60000 * 30); //30 min + } + + + 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" + //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 + // if node regular readout does not respond, we repeat request + params.repeatCounter = 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-mngr: 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.byte4 = 96; + params.recipient = 1; + params.register = 8; + params.rw = 1;//write + params.timestamp = timestamp; + 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.byte4 = 96; + params.recipient = 1; + params.register = 8; + params.rw = 1;//write + params.timestamp = timestamp; + 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). + */ + + 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.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.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 + { + + logger.debug("processNodeProfile: Threshold lux level for DUSK/DAWN", node); + + let params = getParams(); + params.type = "set_node_profile"; + params.address = node; + params.register = 96; + params.recipient = 1; + params.rw = 1;//write + params.timestamp = timestamp; + 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(); + params.type = "set_node_profile"; + params.address = node; + params.register = 97; + params.recipient = 1; + params.rw = 1;//write + params.timestamp = timestamp; + 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.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); + + 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); + + console.log("proces profile finished *********************") + } + + + 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; + }); + } + + + 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) { + for (let k in nodesData) { + 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`); + } + } + } + + + function loadRelaysData(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 (value.contactor == 1) processAllNodeProfilesOnLine(value.line); + } + } + + + function reportOnlineNodeStatus(line) { + //Po zapnutí línie broadcastovo aktualizovať predtým čas a o 3 sek neskor - status, brightness + + logger.debug("Cmd-mngr: ----->reportOnlineNodeStatus for line", line); + + const d = new Date(); + + // broadcast actual time + let params = getParams(); + params.address = 0xffffffff;//Broadcast + params.byte1 = d.getHours(); + params.byte2 = d.getMinutes(); + params.recipient = 2;//2 broadcast, address = 0 + params.register = 87;//Actual time + params.rw = 1;//write + params.type = "node-onetime-write"; + params.timestamp = d.getTime() + 30000; + params.info = "run broadcast: Actual time"; + //params.debug = true; + + tasks.push(params); + + let sec = 3; + setTimeout(function() { + //Po zapnutí línie - spraviť hromadný refresh stavu práve zapnutých svietidiel + + let time = Date.now(); + + for (let k in nodesData) { + + //potrebujem nody k danej linii + 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].node_status_before_offline === true || nodesData[k].status === true) { + status = "OK"; + nodesData[k].time_of_last_communication = time; + } + + nodesData[k].readout.status = status; + + updateNodeStatus(k, status === "OK" ? true : false); + if (nodesData[k].hasOwnProperty("node_status_before_offline")) delete nodesData[k].node_status_before_offline; + sendTelemetry({ status: status }, tbname, time); + + //vyreportovanie dimming, current, input power pre liniu pre vsetky nody + //Prud + { + let params = getParams(); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 75;//prud + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = time + 4000; + params.info = 'read current'; + //params.debug = true; + tasks.push(params); + } + + //vykon + { + let params = getParams(); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 76;//výkon + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = time + 4100; + params.info = 'read power'; + //params.debug = true; + + tasks.push(params); + } + //dimming + { + let params = getParams(); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 1;//dimming + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = time + 4200; + params.info = 'read dimming'; + //params.debug = true; + + tasks.push(params); + } + + } + } + + }, sec * 1000); + } + + + function reportOfflineNodeStatus(line) { + + logger.info("Cmd-mngr: ------>reportOffLineNodeStatus for line ", line); + + values = {}; + values["dimming"] = 0;//brightness + values["power"] = 0;//výkon + values["current"] = 0;//prúd + values["status"] = "OFFLINE"; + + const date = Date.now(); + + Object.keys(nodesData).forEach(node => { + + //potrebujem nody k danej linii + if (line == nodesData[node].line || line == undefined) { + + let tbname = nodesData[node].tbname; + let nodeStatus = nodesData[node].status; + + //in case we have reported offline node status, we return (continue with next node) + if (nodeStatus === "OFFLINE") return; + + nodesData[node].node_status_before_offline = nodeStatus; + nodesData[node].status = "OFFLINE"; + nodesData[node].readout = {}; + + sendTelemetry({ ...values }, tbname, date); + } + }); + + } + + + function turnLine(onOrOff, line, info) { + let obj = { + line: line, + command: onOrOff, + info: info + }; + + //to assure, handleDailyReportFunction do not run before rvo_is_on variable changes. So after every line switch we reset the timer + clearInterval(handleDailyReport); + handleDailyReport = setInterval(dailyReportHandler, DAILY_REPORT_HANDLER_TIME); + + //logger.debug("linia", line, obj); + instance.send(SEND_TO.dido_controller, obj); + } + + + 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"; + 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]) { + //CRC_ERROR + message = "NOK"; + error = "CRC_ERROR c1"; + instance.send(SEND_TO.debug, "CRC_ERROR c1"); + } + + 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") { + instance.send(SEND_TO.debug, bytes); + instance.send(SEND_TO.debug, "RESPONSE " + type + " - " + bytes[4]); + + //logger.debug(SEND_TO.debug, "RESPONSE " + type + " - " + bytes[4], bytes); + + error = "type is: " + type; + + message = "NOK"; + } + + return { message, type, error }; + } + + + //BUILD TASKS// + function buildTasks(params) { + + //return; + console.log("buidTAaasks start ****************", params); + monitor.info("buildTasks - params", params); + + let processLine; //defined line + let init = false; + let processLineProfiles = true; + let processBroadcast = true; + let processNodes = true; + + if (params == undefined) { + init = true; + tasks = []; + logger.debug("-->buildTasks clear tasks"); + } + else { + processLineProfiles = params.processLineProfiles; + processBroadcast = false; + processNodes = false; + + processLine = params.line; + } + + let now = new Date(); + + //process line profiles + if (processLineProfiles) { + + let keys = Object.keys(relaysData); + + for (let i = 0; i < keys.length; i++) { + + let line = parseInt(keys[i]); + let profilestr = relaysData[line].profile; + + if (processLine != undefined) { + if (processLine != line) continue; + } + + try { + + /** + * we process line profiles: timepoints, astro clock, lux_sensor, offsets ... + */ + if (profilestr === "") throw ("Profile is not defined"); + let profile = JSON.parse(profilestr); + 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; + + // add name to regular profile timepoint and delete unused end_time key: + time_points.forEach(point => { + point.name = "profileTimepoint" + delete point.end_time; + }); + + //monitor.info("buildTasks: time_points", time_points); + + + /** + * 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 astro clock true, we remove all regular profile points + time_points = []; + + //TODO: when astro clock == true, is offset calculated ??? + //let duskAstroClockOffset = profile.dusk_astro_clock_offset; + //let dawnAstroClockOffset = profile.dawn_astro_clock_offset; + //console.log("line astro clock offsets dusk a dawn: ", duskAstroClockOffset, dawnAstroClockOffset); + // maybe add dusk dawn offset to calculateDuskDawn ?? what dusk dawn will be if dawn_lux_sensor == true?? + //let sunCalcResult = calculateDuskDawn(new Date(), line, duskAstroClockOffset, dawnAstroClockOffset); + + 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 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); + + 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); + + 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(':'); + + let ad = new Date(); + ad.setHours(parseInt(ahours), parseInt(aminutes), 0); + + let bd = new Date(); + bd.setHours(parseInt(bhours), parseInt(bminutes), 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++) { + + let start_time = new Date(); + let [hours, minutes] = time_points[t].start_time.split(':'); + start_time.setHours(parseInt(hours), parseInt(minutes), 0); + + //task is in 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(); + params.type = "relay"; + params.line = parseInt(line); + params.value = time_points[t].value; + params.tbname = relaysData[line].tbname; + params.timestamp = start_time.getTime(); + + // 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; + + //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)) { + 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; + + params.debug = true; + + //turn on/off line + tasks.push(params); + monitor.info("TimePoint params: ", params.info, start_time); + } + + monitor.info("-->time_points final", line, time_points); + + //ensure to turn on/off according to calculated currentValue + let params = getParams(); + params.type = "relay"; + params.line = parseInt(line); + params.tbname = relaysData[line].tbname; + params.value = currentValue; + params.timestamp = i; + params.debug = true; + + //logger.debug(now.toLocaleString("sk-SK")); + 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; + + tasks.push(params); + + } catch (error) { + if (profilestr !== "") { + //errLogger.error(profilestr, error); + console.log(`Cmd_mngr: Unable to process line profile ${line}. Error: `, error); + errorHandler.sendMessageToService(profilestr + "-" + error, 0, "js_error"); + } else { + turnLine("off", line, "No line profile. Switching it off on startup"); + } + } + + } + //logger.debug("tasks:"); + //logger.debug(tasks); + } + + + //NOTE: PROCESS DEFAULT BROADCASTS - Time of dusk, Time of dawn, Actual Time + if (processBroadcast) { + + let d = new Date(); + let time = d.getTime(); + //let sunCalcResult = calculateDuskDawn(); + + { + let params = getParams(); + + params.address = 0xffffffff;//broadcast + params.byte1 = sunCalcResult["dusk_hours"]; + params.byte2 = sunCalcResult["dusk_minutes"]; + params.recipient = 2;//2 broadcast, + params.register = 6;//Time of dusk + params.rw = 1;//write + params.type = "node-regular-write"; + params.timestamp = time + 60000; + params.addMinutesToTimestamp = 60 * 3; //kazde 3 hodiny zisti novy dusk + params.info = "Broadcast-duskTime"; + + tasks.push(params); + } + + { + let params = getParams(); + + params.address = 0xffffffff;//broadcast + params.byte1 = sunCalcResult["dawn_hours"]; + params.byte2 = sunCalcResult["dawn_minutes"]; + params.recipient = 2; //2 broadcast + params.register = 7;//Time of dawn + params.rw = 1;//write + params.type = "node-regular-write"; + params.timestamp = time + 60001; + params.addMinutesToTimestamp = 60 * 3; //kazde 3 hodiny zisti novy dawn + params.info = "Broadcast-dawnTime"; + + tasks.push(params); + } + + { + let params = getParams(); + + params.address = 0xffffffff;//broadcast + params.byte1 = d.getHours(); + params.byte2 = d.getMinutes(); + params.recipient = 2; //2 broadcast + params.register = 87;//Actual time + params.rw = 1;//write + params.type = "node-regular-write"; + params.timestamp = time + 60002; + params.addMinutesToTimestamp = 5; + params.info = "run broadcast: Actual time"; + + tasks.push(params); + } + + } + + //process nodes & tasks - read node's data + if (processNodes) { + + let time = Date.now(); + + for (let k in nodesData) { + let address = parseInt(k); + let tbname = nodesData[k].tbname; + let register = 0; + + for (let i = 0; i < listOfCommands.length; i++) { + + register = listOfCommands[i]; + let addMinutesToTimestamp = priorities[register]; + + let params = getParams(); + + params.address = address; + params.recipient = 1; + params.register = register; + params.type = register == 1 ? "node-dimming-read" : "node-regular-read"; + params.tbname = tbname; + params.timestamp = time + 5000 + i * 500 + addMinutesToTimestamp * 1000; //to make slight time difference + params.addMinutesToTimestamp = addMinutesToTimestamp; + params.info = "Node regular read command"; + + tasks.push(params); + } + + } + } + + + //niektore ulohy sa vygeneruju iba 1x pri starte!!! + if (!init) return; + + + //Master node FW version - modifies SETTINGS.masterNodeIsResponding + { + let params = getParams(); + params.type = "cmd-master"; + params.register = 4; + params.address = 0; + params.timestamp = 0; + params.addMinutesToTimestamp = 5; + params.tbname = SETTINGS.rvoTbName; + params.info = "Master node FW verzia"; + //params.debug = true; + + tasks.push(params); + } + + //kazdu hodinu skontrolovat nastavenie profilov + { + let params = getParams(); + params.type = "process_profiles"; + params.timestamp = Date.now() + 60001; + params.addMinutesToTimestamp = 60;//60 = every hour + params.info = "detekcia nespracovaných profilov linie a nodov"; + //params.debug = true; + + tasks.push(params); + } + + monitor.info("tasks created:", tasks.length); + } + + + /** + * We process line profile, where "astro_clock": true + * example profile: + * + "dawn_lux_sensor": true, + "dusk_lux_sensor": true, + "dawn_lux_sensor_value": 5, + "dusk_lux_sensor_value": 5, + "dawn_astro_clock_offset": 0, + "dusk_astro_clock_offset": 10, + "dawn_lux_sensor_time_window": 30, + "dusk_lux_sensor_time_window": 30, + "dawn_astro_clock_time_window": 60, + "dusk_astro_clock_time_window": 60 + + * if dawn: if currentTimestamp is in timewindow "dawnTime + and - dawn_lux_sensor_time_window" and lux value >= lux_sensor_value, we switch off the line. + * if dusk: we do oposite + * + * dawn: usvit - lux je nad hranicou - vypnem + * dusk: sumrak - lux je pod hranicou - zapnem + */ + 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++) { + + let line = keys[i]; //line is turned off by default + let profilestr = relaysData[line].profile; + const contactor = relaysData[line].contactor; + + try { + + let profile = JSON.parse(profilestr); + if (Object.keys(profile).length === 0) throw ("turnOnOffLinesAccordingToLuxSensor - profile is not defined"); + + 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 (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"); + } + } + } + + //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 (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"); + } + } + } + + } + + } catch (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) { + //MASTER + if (node == 0) return; + + let nodeObj = nodesData[node]; + if (nodeObj == undefined) return; + + let nodeCurrentStatus = nodeObj.status; + const now = Date.now(); + + let data = null; + + if (nodeCurrentStatus === "OFFLINE") { + data = { status: newStatus }; + nodeDbStatusModify(node, data); + return; + } + else 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; + } + + } + + + 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 }; + } + }); + }); + } + + + function processDailyReport() { + + const now = Date.now(); + + for (const [key, value] of Object.entries(dailyReport)) { + + if (["name", "time", "dusk_and_dawn"].includes(key)) continue; + + let poleNumber = nodesData[key]["pole_number"]; + let line = dailyReport[key].line; + let nodeType = nodesData[key]["node_type"]; + let fullNodeName = key // key == nodeNumber + + if (poleNumber && nodeType) { + fullNodeName = SETTINGS.rvo_number + "/" + poleNumber + "_" + line + "L_" + key + "_" + nodeType; + } else { + fullNodeName = key; + } + + if (rvo_is_on) { + + if (value.initialTs) { + if (value.initialTs + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["night_no_data"], fullNodeName); + console.log('report nedostava ziadne data uz hodinu', fullNodeName); + value.initialTs = now; + } + } + if (value.dimmingIsZeroTime) { + if (value.dimmingIsZeroTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["night_dimming=0"], fullNodeName); + console.log("report node dimming je 0 ale ma svietit", fullNodeName); + value.dimmingIsZeroTime = now; + } + } + if (value.powerIsZeroTime) { + if (value.powerIsZeroTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["night_power=0"], fullNodeName); + console.log("report node power je 0 ale ma svietit", fullNodeName); + value.powerIsZeroTime = now; + } + } + + } else { + + let contactorStatus = relaysData[line].contactor; + if (contactorStatus === 1) { + + if (value.initialTs) { + if (value.initialTs + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["day_24/7_no_data"], fullNodeName); + console.log('node je na 24/7 ale nedostava ziadne data uz hodinu', fullNodeName); + value.initialTs = now; + } + } + if (value.dimmingIsOnButShouldBeOffTime) { + if (value.dimmingIsOnButShouldBeOffTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["day_24/7_dimming>0"], fullNodeName); + console.log("report dimming je > 0 ale nema svietit", fullNodeName); + value.dimmingIsOnButShouldBeOffTime = now; + } + } + if (value.powerIsOnButShouldBeOffTime) { + if (value.powerIsOnButShouldBeOffTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["day_24/7_power>0"], fullNodeName); + console.log("report power je > 0 ale nema svietit", fullNodeName); + value.powerIsOnButShouldBeOffTime = now; + } + } + + } + + } + + } + + let report = {}; + report["name"] = SETTINGS.rvo_name; + report["time"] = new Date(); + report["report"] = reportToSend; + + writeToFile(F.path.root("report_data.log"), report, true); + instance.send(SEND_TO.dailyReport, report); + } + + + function dailyReportHandler() { + + if (!SETTINGS.daily_report) return; + + // after dawn we empty reportToSend and start to get data for a new day + const date = new Date(); + const hour = date.getHours(); + const minute = date.getMinutes(); + + console.log("now: ", hour, minute, "suncalc: ", sunCalcResult.dawn_hours, sunCalcResult.dawn_minutes); + + if (hour === sunCalcResult.dawn_hours) { + + //NOTE: ak je este pred usvitom, spracujeme report a posleme na cloud, ak uz je po usvite, resetujeme report plnime data noveho dna + if (minute >= sunCalcResult.dawn_minutes - 2) { + emptyReportToSend(); + emptyDailyReport(); + console.log("Podmienka 1 v dailyReport handler"); + } else { + processDailyReport(); + emptyReportToSend(); + emptyDailyReport(); + console.log("Podmienka 2 v dailyReport handler"); + } + + initialReportStatus = true; + + // ak sa funkcia spusti o hodinu alebo 2 neskor, ako je usvit (moze sa to stat, kedze kazde zapnutie/vypnutie linii odznova spusti casovac. + } else if (hour === sunCalcResult.dawn_hours + 1 || hour === sunCalcResult.dawn_hours + 2) { + if (!initialReportStatus) { + emptyReportToSend(); + emptyDailyReport(); + initialReportStatus = true; + console.log("Podmienka 3 v dailyReport handler"); + } else { + processDailyReport(); + initialReportStatus = true; + console.log("Podmienka 4 v dailyReport handler"); + } + } else { + processDailyReport(); + initialReportStatus = false; + console.log("Podmienka 5 v dailyReport handler"); + } + + console.log("initialReportStatus: ", initialReportStatus); + + } + + function emptyReportToSend() { + emptyJsObject(reportToSend); + reportToSend["contactor"] = { off: [], on: [] }; + reportToSend["night_no_data"] = []; + reportToSend["night_dimming=0"] = []; + reportToSend["night_power=0"] = []; + reportToSend["day_24/7_no_data"] = []; + reportToSend["day_24/7_dimming>0"] = []; + reportToSend["day_24/7_power>0"] = []; + console.log(`resetuje sa reportToSend`); + } + + + //NOTE: ked je initialTs stale rovnaky a zistime ze linie su vypnute (relaysData.line.contactor) - zistim, ci je node na tej linii. Vieme, ze ak je linia vypnuta je to v poriadku lebo nie je na 24/7 linii + //ak je na 24/7 linii, reportujeme, ze neprijima data + function emptyDailyReport() { + const ts = Date.now(); + emptyJsObject(dailyReport); + + //NOTE: do dailyReport dame vsetky nody a pravidelne kontrolujeme ci maju data + //ked nastane sumrak/usvit a svetla maju zacat/prestat svietit, dailyReport spravime nanovo: + for (const [key, value] of Object.entries(nodesData)) { + dailyReport[value.node] = { line: value.line, initialTs: ts }; + } + + console.log("dailyReport: ", dailyReport); + } + + + async function runTasks() { + + clearInterval(interval); + + let currentTimestamp = Date.now(); + + //sort tasks based on timestamp + 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) { + instance.send(SEND_TO.debug, "no tasks created"); + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + if (!rsPort.isOpen) { + instance.send(SEND_TO.debug, "!rsPort.isOpen"); + //await rsPort.open(); + //console.log("Cmd-mngr: !rsPort.isOpen"); + } + + let currentTask = tasks[0]; + + if (currentTask.debug) { + //logger.debug("--->task to process", currentTask); + } + + if (currentTask.timestamp <= currentTimestamp) { + let params = { ...tasks[0] }; + + //allow terminal commands + if (SETTINGS.maintenance_mode && params.type !== "cmd-terminal") { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + let type = params.type; + let tbname = params.tbname; + let node = params.address; + let register = params.register; + let line = null; + let itIsNodeCommand; + + if (nodesData[node] !== undefined) { + line = nodesData[node].line; + itIsNodeCommand = true; + } + + if (params.line !== undefined) line = params.line; + + if (params.addMinutesToTimestamp > 0 || params.timePointName) { + tasks[0].timestamp = currentTimestamp + tasks[0].addMinutesToTimestamp * 60000; + } else { + tasks.shift(); + } + + //kontrola nespracovanych profilov nodov + //TODO: co ked niektore nody neprijimaju profily? kazdu hodinu zahltuju "tasks" array + if (type == "process_profiles") { + //na vsetky zapnutych liniach sa spracuju nespracovane profily nodov + loadRelaysData(); + interval = setInterval(runTasks, SHORT_INTERVAL); + return; + } + + //relay + if (type == "relay") { + + const timePointName = params.timePointName; + const value = params.value; + + let date = new Date(); + date.setDate(date.getDate() + 1);//next day + + let sunCalcResult; + if (timePointName) sunCalcResult = calculateDuskDawn(date, params.line); + + + if (timePointName == "dawn") { + tasks[0].timestamp = sunCalcResult.dawn_time; + } + else if (timePointName == "dusk") { + tasks[0].timestamp = sunCalcResult.dusk_time; + } + else if (timePointName == "luxOn") { + tasks[0].timestamp = sunCalcResult.dusk_time + params.dusk_lux_sensor_time_window * 60000; + } + else if (timePointName == "luxOff") { + tasks[0].timestamp = sunCalcResult.dawn_time + params.dawn_lux_sensor_time_window * 60000; + } + else if (timePointName == "profileTimepoint") { + tasks[0].timestamp = currentTimestamp + tasks[0].addMinutesToTimestamp * 60000; + } + + let info = "aplikovany bod profilu"; + let onOrOff = ""; + value == 1 ? onOrOff = "on" : onOrOff = "off"; + + turnLine(onOrOff, params.line, info); + + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + if (!SETTINGS.masterNodeIsResponding) { + //ak neodpoveda, nebudeme vykonavat ziadne commands, okrem cmd-terminal cmd-master + errorHandler.sendMessageToService("Master node is not responding"); + + let stop = true; + + if (type === "cmd-terminal" || type === "cmd-master") stop = false; + if (stop) { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + } + + let contactorStatus = 1; + if (relaysData[line] != undefined) contactorStatus = relaysData[line].contactor; + + if (line === 0 || contactorStatus === 0 || FLOW.deviceStatus.state_of_breaker[line] === "Off") { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + // TODO: -> status offline for rvo if rotary_switch_state is OFF, this is source of errors + // check if rotary_switch_state == "Off" + // state_of_braker: disconnected = true? + + if (!rsPort.isOpen) { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + //RE-CALCULATE VALUES + //set actual time for broadcast + if (register == 87 && params.recipient === 2) { + var d = new Date(); + params.byte1 = d.getHours();//h + params.byte2 = d.getMinutes();//m + } + + //SET DUSK/DAWN FOR BROADCAST + //Time of dusk + if (register == 6 && params.recipient === 2) { + + if (type != "cmd-terminal") { + params.byte1 = sunCalcResult["dusk_hours"];//h + params.byte2 = sunCalcResult["dusk_minutes"];//m + } + } + + //Time of dawn + if (register == 7 && params.recipient === 2) { + if (type != "cmd-terminal") { + params.byte1 = sunCalcResult["dawn_hours"];//h + params.byte2 = sunCalcResult["dawn_minutes"];//m + } + } + //----------------------- + + instance.send(SEND_TO.debug, "address: " + node + " register:" + register + "type: " + type); + + var startTime, endTime; + startTime = new Date(); + + let saveToTb = true; + if (!tbname) saveToTb = false; + + let resp = com_generic(node, params.recipient, params.rw, register, params.name, params.byte1, params.byte2, params.byte3, params.byte4); + let readBytes = 11; + let timeout = 4000; + + + // await keyword is important, otherwise incorrect data is returned! + await writeData(rsPort, resp, readBytes, timeout).then(function(data) { + + //sometimes happens, that status of node changes to OK, NOK even if line was turned off and should be status OFFLINE. To prevent this, we return if line contactor is 0: + if (itIsNodeCommand && line && relaysData[line].contactor !== 1) return; + + 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); + + //ak sa odpoved zacina 0 - je to v poriadku, inak je NOK + let message = result.message; // OK, NOK + let message_type = result.type; + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + console.log("detected response:", result); + logger.debug("Cmd-mngr: writeData done " + message_type + " duration: " + timeDiff + " type: " + params.debug, params, result); + } + } + + let values = {}; + + //CMD FINISHED + if (message == "OK") { + + updateNodeStatus(node, true); + + //write + if (type == "set_node_profile") { + let result = cmdCounterResolve(node); + if (result == 0) { + dbNodes.modify({ processed: true }).where("node", node).make(function(builder) { + builder.callback(function(err, response) { + + sendNotification("Cmd-mngr: process cmd", SETTINGS.rvoTbName, "dimming_profile_was_successfully_received_by_node", { node: node }, "", SEND_TO.tb, instance); + + logger.debug("--> profil úspešne odoslaný na node č. " + node); + nodesData[node].processed = true; + nodeProfileSendFail.delete(node); + }); + }); + } + } + + //parse read response + if (params.rw == 0) { + values = processResponse(register, dataBytes); //read + } + + if (itIsNodeCommand) { + values.comm_status = "OK"; + values.status = "OK"; + nodesData[node].readout = { ...nodesData[node].readout, ...values }; + + + if (SETTINGS.daily_report) { + //TODO: co ak nedostavame odpovede z nodu ? Musime vyreportovat!! + //v dailyReport teda musi byt kompletny zoznam nodov a neustale kontrolovat, ci maju data, ak nie report node - neodpoveda + if (register === 1) { + + let now = Date.now(); + + if (rvo_is_on === true) { + + if ("dimmingIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].dimmingIsOnButShouldBeOffTime; + + if (values.dimming > 0) { + if ("dimmingIsZeroTime" in dailyReport[node]) delete dailyReport[node].dimmingIsZeroTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if (!("dimmingIsZeroTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], dimmingIsZeroTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } else { + + if ("dimmingIsZeroTime" in dailyReport[node]) delete dailyReport[node].dimmingIsZeroTime; + + if (values.dimming > 0) { + if (!("dimmingIsOnButShouldBeOffTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], dimmingIsOnButShouldBeOffTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if ("dimmingIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].dimmingIsOnButShouldBeOffTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } + } + + if (register === 76) { + + let now = Date.now(); + + if (rvo_is_on === true) { + + if ("powerIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].powerIsOnButShouldBeOffTime; + + if (values.power > 1) { + if ("powerIsZeroTime" in dailyReport[node]) delete dailyReport[node].powerIsZeroTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if (!("powerIsZeroTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], powerIsZeroTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } else { + + if ("powerIsZeroTime" in dailyReport[node]) delete dailyReport[node].powerIsZeroTime; + + if (values.power > 1) { + if (!("powerIsOnButShouldBeOffTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], powerIsOnButShouldBeOffTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if ("powerIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].powerIsOnButShouldBeOffTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } + } + } + + } + + //master node + if (node == 0) { + sendNotification("Cmd-mngr: 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; + } + + if (params.debug) { + //logger.debug("saveToTb", saveToTb, tbname, values); + } + + if (saveToTb && type != "node-regular-read") { + sendTelemetry(values, tbname); + } + else { + if (type == "cmd-terminal") { + terminalCommandResponse(params, "SUCCESS", data); + } + } + + } + else { + terminalCommandResponse(params, "ERROR", data); + handleNokResponseOnRsPort("handleNOK else block", params, itIsNodeCommand, saveToTb); + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + //logger.debug("writeData err: ", error, result, params); + logger.debug("writeData err: ", tbname, node, register, values); + } + } + + //logger.debug(error, result, params); + } + }).catch(function(reason) { + + //console.log("writeData catch exception", reason); + instance.send(SEND_TO.debug, reason); + + terminalCommandResponse(params, "FAILURE", null, reason); + handleNokResponseOnRsPort("handleNOK catch block", params, itIsNodeCommand, saveToTb); + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + logger.debug("-->WRITE FAILED: " + reason, params.debug, params); + } + } + + }); + + } + 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); + } + + + // if node does not respond to request, we repeat request 3 times: + function repeatCommand(params) { + params.repeatCounter++; + if (params.repeatCounter < 4) { + params.timestamp = 0; + params.addMinutesToTimestamp = 0; + tasks.push(params); + } + } + + function handleNokResponseOnRsPort(message, params, itIsNodeCommand, saveToTb) { + + let node = params.address; + let register = params.register; + let type = params.type; + let tbName = params.tbname; + if (!tbName) return; + + let values = {}; + + let updateStatus = updateNodeStatus(node, false); + + if (itIsNodeCommand) { + values.comm_status = "NOK"; + nodesData[node].readout.comm_status = "NOK"; + repeatCommand(params); + } + + if (updateStatus) { + values.status = "NOK"; + nodesData[node].readout.status = "NOK"; + } + + if (type === "node-regular-read") return; + + //master node + if (node == 0) { + sendNotification("Cmd-mngr: 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; + + if (register == 4) values["master_node_version"] = "NOK"; + } + + if (type == "set_node_profile") { + delete cmdCounter[node]; + logger.debug("profil nebol úspešne odoslaný na node č. ", params); + + if (!nodeProfileSendFail.has(node)) { + sendNotification("Cmd-mngr: process cmd", tbName, "configuration_of_dimming_profile_to_node_failed", { node: node }, "", SEND_TO.tb, instance); + nodeProfileSendFail.add(node); + } + } + + // console.log("------",node, register, type, itIsNodeCommand, updateStatus, saveToTb, values); + if (saveToTb) { + sendTelemetry(values, tbName); + } + + } + + + function sendNodesData() { + Object.keys(nodesData).forEach(node => { + if (nodesData[node]["status"] !== "OFFLINE") { + sendTelemetry(nodesData[node].readout, nodesData[node].tbname); + nodesData[node].readout = {}; + } + }) + } + + + /** + * 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; + } + + 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); + + //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 === "OFFLINE") { + nodeObj.node_status_before_offline === true ? number_of_ok_luminaires++ : number_of_nok_luminaires++; + } + else if (nodeObj.status == true) 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 - ts % 60000 //round to full minute + }; + + sendTelemetry(values, SETTINGS.rvoTbName, ts); + } + + + function setSunCalcResult() { + //if next day, we get new dusk and dawn. To make sure, in local timezone 2:00 means 00:00 in utc (it means next day) + if (new Date().getHours() === 2) { + sunCalcResult = calculateDuskDawn(); + console.log("Novy suncalc: ", sunCalcResult); + } + } + + + function setRvoPeriod() { + + if (!SETTINGS.daily_report) return; + + const ts = Date.now(); + + previous_rvo_is_on_value = rvo_is_on; + + if (ts < sunCalcResult.dawn_time - 1_800_000) { // nodes should be on (00:00 -> 06:00 ( - pol hodina, lebo rvo vypina skor) + rvo_is_on = true; + } else if (sunCalcResult.dawn_time - 1_800_000 < ts && ts < sunCalcResult.dusk_time + 1_800_000) { // nodes should be off 06:00 -> 21:00 + rvo_is_on = false; + } else if (sunCalcResult.dusk_time + 1_800_000 < ts) { // nodes should be on 21:00 -> 00:00 + rvo_is_on = true; + } + + if (previous_rvo_is_on_value !== rvo_is_on) { + emptyDailyReport(); + console.log("rvo_is: ", rvo_is_on, previous_rvo_is_on_value); + } + } + + + function handleRsPort() { + + if (rsPort) { + rsPort.removeAllListeners(); + rsPort = null; + } + + //! 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-mngr: rsPort opened success"); + + 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); + + }).catch(function(reason) { + instance.send(SEND_TO.debug, "Cmd-mngr: RPC runSyncExec - promise rejected:" + reason); + }); + }); + + rsPort.on('error', function(err) { + errorHandler.sendMessageToService([exports.title, "unable to open port", SETTINGS.serial_port, err.message], 0); + monitor.info("Cmd-mngr: Error on rsPort", err.message); + }); + + rsPort.on("close", () => { + monitor.info("Cmd-mngr: rsPort closed, reconnecting..."); + setTimeout(handleRsPort, 1000); + }); + + rsPort.open(); + } + + + instance.on("close", () => { + clearInterval(interval); + clearInterval(customTasksInterval); + clearInterval(setCorrectTime); + clearInterval(sendNodeReadout); + clearInterval(accelerometerInterval); + rsPort.close(); + }); + + instance.on("0", _ => { + main(); + }) + + + instance.on("2", _ => { + console.log("dailyReport, reportToSend, rvo_is_on", dailyReport, reportToSend, rvo_is_on, previous_rvo_is_on_value); + }) + + instance.on("1", 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(); + return; + } + else if (flowdata.data == "close") { + rsPort.close(); + return; + } + else if (flowdata.data == "clean") { + tasks = []; + return; + } + else if (flowdata.data == "buildtasks") { + //build & run + return; + } + else if (flowdata.data == "run") { + //durations = []; + + if (tasks.length == 0) { + + buildTasks(); + + if (rsPort.isOpen) { + interval = setInterval(runTasks, 100); + } + else { + instance.send(SEND_TO.debug, "port is not opened!!!"); + } + } + } + else { + //terminal data - object + //logger.debug("flowdata", flowdata.data); + + if (typeof flowdata.data === 'object') { + //logger.debug("dido", flowdata.data); + if (flowdata.data.hasOwnProperty("sender")) { + //data from dido_controller + if (flowdata.data.sender == "dido_controller") { + + if (flowdata.data.hasOwnProperty("cmd")) { + let cmd = flowdata.data.cmd; + + if (cmd == "buildTasks") { + clearInterval(interval); + + logger.debug("-->Cmd-mngr: BUILD TASKS"); + buildTasks(); + + //logger.debug("tasks:"); + //logger.debug(tasks); + + logger.debug("-->Cmd-mngr: RUN TASKS"); + interval = setInterval(runTasks, 5000); + } + else if (cmd == "reload_relays") { + loadRelaysData(flowdata.data.line); + + if (flowdata.data.dataChanged) { + if (!flowdata.data.value) { + reportOfflineNodeStatus(flowdata.data.line); + } + else { + reportOnlineNodeStatus(flowdata.data.line); + } + } + + } + else if (cmd == "rotary_switch_state") { + let value = flowdata.data.value; + + //state was changed + if (rotary_switch_state != value) { + if (value == "Off") { + //vyreportovat vsetky svietdla + reportOfflineNodeStatus(); + } + + rotary_switch_state = value; + } + } + 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) { + + // we send lux_sensor value to all nodes: + let params = getParams(PRIORITY_TYPES.node_broadcast); + + params.recipient = 2;//2 broadcast, address = 0 + params.address = 0xffffffff;//Broadcast + + let ba = longToByteArray(lux_sensor); + + params.byte3 = ba[1];//msb + params.byte4 = ba[0]; + params.timestamp = PRIORITY_TYPES.node_broadcast; + params.info = "run broadcast: Actual Lux level from cabinet"; + params.register = 95;//Actual Lux level from cabinet + params.rw = 1;//write + + tasks.push(params); + + //process profiles + turnOnOffLinesAccordingToLuxSensor(lux_sensor); + } + } + else if (cmd == "state_of_breaker") { + //istic linie + + breakerCounter--; + + let value = flowdata.data.value; + let line = parseInt(flowdata.data.line); + + let dataChanged = false; + if (state_of_breaker[line] != value) dataChanged = true; + + state_of_breaker[line] = value; + + let status = "OK"; + if (value == "Off") status = "NOK"; + + if (dataChanged) { + + if (relaysData.hasOwnProperty(line)) { + let tbname = relaysData[line].tbname; + + if (value == "Off") { + sendNotification("Cmd-mngr: onData", tbname, "circuit_breaker_was_turned_off_line", { line: line }, "", SEND_TO.tb, instance, "circuit_breaker"); + if (breakerCounter < 0) reportToSend["contactor"]["off"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + else { + sendNotification("Cmd-mngr: onData", tbname, "circuit_breaker_was_turned_on_line", { line: line }, "", SEND_TO.tb, instance, "circuit_breaker"); + if (breakerCounter < 0) reportToSend["contactor"]["on"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + + //report status liniu + sendTelemetry({ status: status }, tbname) + + //current value + if (value == "Off") reportOfflineNodeStatus(line); //vyreportovat vsetky svietidla na linii + } + + } + } + else { + logger.debug("undefined cmd", cmd); + } + } + } + + return; + } + + //data from worksys + if (flowdata.data.hasOwnProperty("topic")) { + + let data = getNested(flowdata.data, "content", "data"); + + //if we get temperature in senica from senica-prod01 + let temperature = getNested(flowdata.data, "content", "senica_temperature"); + + if (temperature !== undefined) { + temperatureInSenica = temperature; + return; + } + + if (data === undefined) { + console.log("Invalid rpc command came from platform"); + return; + } + + let command = data.params.command; + let method = data.method; + let profile = data.params.payload; + if (profile == undefined) profile = ""; + let entity = data.params.entities[0]; + let entity_type = entity.entity_type; + let tbname = entity.tb_name; + + instance.send(SEND_TO.debug, flowdata.data); + 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") { + + //let command = data.params.command; + let value = data.params.payload.value; + + if (command == "dimming") { + + let nodeWasFound = false; + let keys = Object.keys(nodesData); + + //logger.debug("-----", keys); + + 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); + + value = parseInt(value); + if (value > 0) value = value + 128; + + params.type = "node-onetime-write"; + params.tbname = tbname; + params.address = node; + params.register = 1; + params.recipient = 1; + params.byte4 = value; + params.rw = 1; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'set dimming from platform'; + //params.debug = true; + + //debug(params); + logger.debug("dimming", params); + + tasks.push(params); + + 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); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 1; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read dimming (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + //pridame aj vyreportovanie - vykon + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 76; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read Input Power (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + //pridame aj vyreportovanie - prud svietidla + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 75; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read Input Current (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + //pridame aj vyreportovanie - power faktor - ucinnik + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 77; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read power factor (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + }, 4000); + + nodeWasFound = true; + break; + } + } + + if (!nodeWasFound) { + logger.debug("set dimming from platform", "unable to find tbname", tbname); + } + } + else { + instance.send(SEND_TO.debug, "undefined command " + command); + logger.debug("undefined command", command); + } + + return; + } + 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++) { + let node = keys[i]; + if (tbname == nodesData[node].tbname) { + + 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"); + + //profil úspešne prijatý pre node č. xx + sendNotification("Cmd-mngr", tbname, "dimming_profile_was_processed_for_node", { node: node }, profile, SEND_TO.tb, instance); + + nodesData[node].processed = false; + nodesData[node].profile = profile; + + processNodeProfile(node); + }); + }); + } + } + } + else { + + instance.send(SEND_TO.debug, "unknown method " + method); + logger.debug("unknown method", method); + + return; + } + } + + //nastav profil linie z platformy + 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") { + + 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++) { + let line = keys[i]; + if (tbname == relaysData[line].tbname) { + //zmazeme tasky + 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) { + + //update profile + logger.debug("worksys - update relay profile done:", profile); + instance.send(SEND_TO.debug, "worksys - update relay profile done"); + + relaysData[line].profile = profile; + + loadRelaysData(line) + logger.debug("loadRelaysData DONE for line", line); + + buildTasks({ processLineProfiles: true, line: line }); + + sendNotification("Cmd-mngr: set profile from worksys", tbname, "switching_profile_was_processed_for_line", { line: line }, profile, SEND_TO.tb, instance); + }); + }); + break; + } + } + } + else if (method == "set_command") { + let value = data.params.payload.value; + + 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; + + 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"); + if (line != 0) reportToSend["contactor"]["off"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + else { + turnLine("on", line, "command received from platform"); + if (line != 0) reportToSend["contactor"]["on"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + } + } + else { + instance.send(SEND_TO.debug, "undefined method " + method); + logger.debug("undefined method", method); + } + + return; + } + else { + instance.send(SEND_TO.debug, "UNKNOW entity_type " + entity_type); + logger.debug("UNKNOW entity_type", entity_type); + } + return; + } + + //terminal + if (!rsPort.isOpen) await rsPort.open(); + + let params = flowdata.data.body; + if (params == undefined) { + //logger.debug("Cmd-mngr: flowdata.data.body is undefined"); + return; + } + + params.priority = PRIORITY_TYPES.terminal; + params.type = "cmd-terminal"; + params.tbname = ""; + params.timestamp = PRIORITY_TYPES.terminal; + params.addMinutesToTimestamp = 0;// do not repeat task!!! + params.debug = true; + + let timestamp = Date.now(); + params.refFlowdataKey = timestamp; + //params.refFlowdata = flowdata; + //refFlowdata = flowdata; + + //console.log("flowdata", flowdata); + + cleanUpRefFlowdataObj(); + + refFlowdataObj[timestamp] = flowdata; + + //fix + //params.address = params.adress; + logger.debug("received from terminal", params); + logger.debug("date/time:", new Date()); + logger.debug("tasks length:", tasks.length); + + //tasks = []; + + //add to tasks + tasks.push(params); + + } + } + }) + + + //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) + } + + + /** + * 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; + + RESTBuilder.make(function(builder) { + + if (!builder) return; + + builder.method('GET'); + builder.url('http://192.168.252.2:8004/gettime?projects_id=1'); + + builder.callback(function(err, response, output) { + + 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); + } + + }); + } + + } 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); + + } else { + //console.log("Read-only", stdout); + + 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]: [ + { + "ts": date, + "values": values + } + ] + } + + tbHandler.sendToTb(dataToTb, instance); + } + + + function calculateDuskDawn(date, line, duskOffset = 0, dawnOffset = 0) { + + if (date === undefined) date = new Date(); + + 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); + } + + //if(profile.dawn_lux_sensor == false) + { + if (profile.hasOwnProperty("dawn_astro_clock_offset")) dawn_astro_clock_offset = parseInt(profile.dawn_astro_clock_offset); + } + + } + + } catch (error) { + if (profilestr != "") { + logger.debug(profilestr); + logger.debug(error); + } + } + + 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; + } + + //Dimming, CCT + else if (register == 1) { + let brightness = 0; + let dimming = byte0; + if (dimming > 128) { + //dimming = -128; + brightness = dimming - 128; + } + + //cct + //Ak Byte3 == 1: CCT = (Byte2*256)+Byte1 + let cct; + if (byte3 == 1) cct = byte2 * 256 + byte1; + else cct = bytesToInt(bytes.slice(0, 3)); + + //cct podla auditu + + values["dimming"] = brightness; + return values; + } + + // + else if (register == 4) { + values["master_node_version"] = bytes[1] + "." + bytes[2]; + //logger.debug("FW Version", register, bytes); + } + + //Napätie + else if (register == 74) { + let voltage = (bytesToInt(bytes) * 0.1).toFixed(1); + values["voltage"] = Number(voltage); + } + + //Prúd + else if (register == 75) { + let current = bytesToInt(bytes); + values["current"] = current; + } + + //výkon + else if (register == 76) { + let power = (bytesToInt(bytes) * 0.1).toFixed(2); + values["power"] = Number(power); + } + + //účinník + else if (register == 77) { + let power_factor = Math.cos(bytesToInt(bytes) * 0.1 * (Math.PI / 180)).toFixed(2); + values["power_factor"] = Number(power_factor); + } + + //frekvencia + else if (register == 78) { + let frequency = (bytesToInt(bytes) * 0.1).toFixed(2); + values["frequency"] = Number(frequency); + } + + //energia + else if (register == 79) { + let energy = bytesToInt(bytes); + values["energy"] = energy / 1000; //energia v kWh -> delit 1000 + } + + //doba života + else if (register == 80) { + let lifetime = (bytesToInt(bytes) / 60).toFixed(2); + values["lifetime"] = Number(lifetime); + } + + //nastavenie profilu + else if (register == 8) { + let time_schedule_settings = bytesToInt(bytes); + values["time_schedule_settings"] = time_schedule_settings; + } + + //naklon - nateraz sa z nodu nevycitava! kvoli problemom s accelerometrom a vracanymi hodnotami, posielame temp a x y z vo funkcii accelerometerData() + else if (register == 84) { + values["temperature"] = byte3 >= 128 ? (byte3 - 128) * (-1) : byte3; + values["inclination_x"] = byte2 >= 128 ? (byte2 - 128) * (-1) : byte2; + values["inclination_y"] = byte1 >= 128 ? (byte1 - 128) * (-1) : byte1; + values["inclination_z"] = byte0 >= 128 ? (byte0 - 128) * (-1) : byte0; + } + + //FW verzia nodu + else if (register == 89) { + //formát: "Byte3: Byte2.Byte1 (Byte0)" + values["fw_version"] = byte3 + ":" + byte2 + "." + byte1 + "(" + byte0 + ")"; + } + + else if (register == 87 || register == 6 || register == 7) { + var d = new Date(); + d.setHours(byte3, byte2, 0, 0); + let timestamp = d.getTime(); + + //aktuálny čas + if (register == 87) values["actual_time"] = timestamp; + //čas súmraku + else if (register == 6) values["dusk_time"] = timestamp; + //čas úsvitu + else if (register == 7) values["dawn_time"] = timestamp; + } + + 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; + + } + + + function getObjectByTbValue(object, tbname) { + return object[Object.keys(object).find(key => object[key].tbname === tbname)]; + } + + + function isObject(item) { + return (typeof item === "object" && !Array.isArray(item) && item !== null); + } + + + // we fake data, that should be received from accelerometer, as they are a bit unreliable. (temperature, x,y,z) + function accelerometerData() { + + if (temperatureInSenica === null) return; + + //clone nodesData and relaysData objects + let nodesData_clone = JSON.parse(JSON.stringify(nodesData)); + let relaysData_clone = JSON.parse(JSON.stringify(relaysData)); + + for (const key in relaysData_clone) { + + const lineData = relaysData_clone[key]; + const lineNumber = lineData.line; + const contactor = lineData.contactor; + + if (lineNumber === 0) continue; + + if (contactor === 1) { + + let date = Date.now(); + + Object.keys(nodesData_clone).forEach((node, index) => { + + setTimeout(function() { + + if (nodesData_clone[node].line === lineNumber) { + + // NOTE: if status of luminaire is NOK or OFFLINE, we do not send data; + let status = nodesData_clone[node].status; + if (status === "OFFLINE" || !status) return; + + let x = null; + if (naklony.hasOwnProperty(node)) x = naklony[node].naklon; + if (x === null) x = 0; + + sendTelemetry({ temperature: Math.round(temperatureInSenica + 10 + Math.floor(Math.random() * 3)), inclination_x: x, inclination_y: 0, inclination_z: 0 }, nodesData_clone[node].tbname, date); + } + + }, (index + 1) * 500); + }) + + } + } + } + + +} // end of instance.export + diff --git a/RVO3/flow/code.js b/RVO3/flow/code.js new file mode 100755 index 0000000..63b31bf --- /dev/null +++ b/RVO3/flow/code.js @@ -0,0 +1,90 @@ +exports.id = 'code'; +exports.title = 'Code'; +exports.group = 'Common'; +exports.color = '#656D78'; +exports.input = true; +exports.output = 1; +exports.author = 'Peter Širka'; +exports.icon = 'code'; +exports.version = '1.2.0'; +exports.options = { outputs: 1, code: 'send(0, value);', keepmessage: true }; + +exports.html = `
+
+
+
@(Number of outputs)
+
@(Minimum is 1)
+
+
+
@(Code)
+
@(Keep message instance)
+
+`; + +exports.readme = `# Code + +This component executes custom JavaScript code as it is and it doesn't contain any secure scope. + +\`\`\`javascript +// value {Object} contains received data +// send(outputIndex, newValue) sends a new value +// error(value) sends an error +// instance {Object} a current component instance +// flowdata {Object} a current flowdata +// repository {Object} a current repository of flowdata +// Example: + +// send() can be execute multiple times +send(0, value); +\`\`\``; + +exports.install = function(instance) { + + var fn; + + instance.on('data', function(response) { + if (fn) { + try { + fn(response.data, instance, response, instance.options, response.repository, require); + } catch (e) { + response.data = e; + instance.throw(response); + } + } + }); + + instance.reconfigure = function() { + try { + if (instance.options.code) { + instance.status(''); + var code = 'var send = function(index, value) { if (options.keepmessage) { flowdata.data = value; instance.send2(index, flowdata); } else instance.send2(index, value);}; var error = function(err) { instance.throw(err); }; ' + instance.options.code; + fn = new Function('value', 'instance', 'flowdata', 'options', 'repository', 'require', code); + } else { + instance.status('Not configured', 'red'); + fn = null; + } + } catch (e) { + fn = null; + instance.error('Code: ' + e.message); + } + }; + + instance.on('options', instance.reconfigure); + instance.reconfigure(); +}; \ No newline at end of file diff --git a/RVO3/flow/comment.js b/RVO3/flow/comment.js new file mode 100755 index 0000000..1e0cd13 --- /dev/null +++ b/RVO3/flow/comment.js @@ -0,0 +1,11 @@ +exports.id = 'comment'; +exports.title = 'Comment'; +exports.group = 'Common'; +exports.color = '#704cff'; +exports.author = 'Martin Smola'; +exports.icon = 'comment'; +exports.traffic = false; +exports.version = '1.0.0'; +exports.readme = '# Comment'; + +exports.install = function() {}; diff --git a/RVO3/flow/count.js b/RVO3/flow/count.js new file mode 100755 index 0000000..fa92ee9 --- /dev/null +++ b/RVO3/flow/count.js @@ -0,0 +1,60 @@ +exports.id = 'count'; +exports.title = 'Count'; +exports.version = '1.0.1'; +exports.author = 'John Graves'; +exports.color = '#656D78'; +exports.icon = 'plus-square'; +exports.input = 2; +exports.output = 1; +exports.options = { increment: 1, initialvalue: 1 }; +exports.readme = `# Counter + +Counter Number of times called.`; + +exports.html = `
+
@(Initial Value)
+
@(Increment)
+

Example Video

+
`; + +exports.readme = `# Count + +This component counts the number of messages received. + +__Response:__ + +Integer value based on the initial value and increment settings. + +__Arguments:__ +- Initial Value: What number should be output on the receipt of the first message. +- Increment: What should the increment be for each following message received.`; + +exports.install = function(instance) { + + var count = 0; + var initialCall = true; + + instance.on('data', function(flowdata) { + var index = flowdata.index; + if (index) { + instance.debug('Reset Count.'); + count = instance.options.initialvalue; + initialCall = true; + } else { + // If this is the first time, set the value to 'initial value' + if(initialCall) { + initialCall = false; + count = instance.options.initialvalue; + } else + count = count+instance.options.increment; + instance.status('Count:' + count); + instance.send2(count); + } + }); + + instance.on('options', function() { + count = instance.options.initialvalue; + initialCall = true; + }); + +}; diff --git a/RVO3/flow/db_connector.js b/RVO3/flow/db_connector.js new file mode 100755 index 0000000..65ee94b --- /dev/null +++ b/RVO3/flow/db_connector.js @@ -0,0 +1,286 @@ +exports.id = 'db_connector'; +exports.title = 'DbConnector'; +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.html = `
+
+
+
DbConnector
+
+
+
`; + +exports.readme = `# read/write data to tables`; + +const instanceSendTo = { + debug: 0, + http_response: 1, +} + +const { promisifyBuilder, makeMapFromDbResult } = require('./helper/db_helper.js'); + +function extractWhereParams(params) +{ + let name = params[0]; + let operator = '='; + let value = params[1]; + + if(params.length == 3) + { + operator = params[1]; + value = params[2]; + } + + return {name: name, operator: operator, value: value}; +} + +exports.install = function(instance) { + + let refFlowdata = null;//holds reference to httprequest flowdata + + instance.on("close", () => { + + }) + + + instance.on("data", async function(flowdata) { + + let params = flowdata.data.body; + console.log("DbConnector", params); + + refFlowdata = flowdata; + + if(refFlowdata != undefined) + { + //make http response + let responseObj = {}; + responseObj["type"] = "SUCESS"; + + try{ + + let table = params.table; + let action = params.action; + + + if(params.data != undefined) + { + let className = params.data.className; + + if(className == "SqlQueryBuilder") + { + let type = params.data.type; + + console.log("SqlQueryBuilder---->", params.data); + + if(type == "SELECT") + { + let table = params.data.queryData.tables[0].table; + + const db = TABLE(table); + var builder = db.find(); + + let result = await promisifyBuilder(builder); + + let response = {}; + response["result"] = result; + response["success"] = true; + + responseObj["data"] = response; + + //console.log(responseObj); + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + } + + return; + } + } + + + console.log("db_connector---->", table, action); + + //actions: read, replace, insert, delete, update... + + if(action == "read") + { + const db = TABLE(params.table); + + //where builder.where('age', '<', 15); + //builder.where('id', 3403); + + var builder = db.find(); + + //https://docs.totaljs.com/latest/en.html#api~DatabaseBuilder~builder.where + if(params.hasOwnProperty("where")) + { + //optionalCan contain "=", "<=", "<", ">=", ">". + //Default value: '=' + + //1.["production_line", 1] + //2. ["or", ["production_line", 1], ["production_line", 2], "end"] + + if (Array.isArray(params.where)) { + + let multipleConditions = false; + + if(params.where[0] == "or") multipleConditions = true; + if (Array.isArray(params.where[0])) multipleConditions = true; + + if(multipleConditions) + { + + for(var i = 0; i < params.where.length; i++) + { + const item = params.where[i]; + + if(item === "or") builder.or(); + + if (Array.isArray(item)) + { + const { name, operator, value } = extractWhereParams(item); + builder.where(name, operator, value); + } + + if(item === "end") builder.end(); + + } + + } + else + { + const { name, operator, value } = extractWhereParams(params.where); + builder.where(name, operator, value); + } + + } + + /* + if(params.where.length >=2 ) + { + let name = params.where[0]; + let operator = '='; + let value = params.where[1]; + + if(params.where.length == 3) + { + operator = params.where[1]; + value = params.where[2]; + } + + builder.where(name, operator, value); + } + */ + } + + if(params.hasOwnProperty("between")) + { + builder.between(params.between[0], params.between[1], params.between[2]); + } + + let response = await promisifyBuilder(builder); + responseObj["data"] = response; + + //console.log(responseObj); + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + + return; + } + + if(action == "delete") + { + + } + + + if(action == "update") + { + //! data receiving from terminal (params) + // { + // hostname: 'localhost', + // table: 'settings', + // action: 'update', + // body: { + // rvo_name: 'terrrr', + // lang: 'en', + // temperature_adress: '28.427B45920702', + // latitude: 48.70826502, + // longitude: 17.28455203, + // mqtt_host: '192.168.252.4', + // mqtt_clientid: 'showroom_test_panel_led', + // mqtt_username: 'xmRd6RJxW53WZe4vMFLU', + // mqtt_port: 1883, + // maintanace_mode: false + // } + // } + const tableToModify = TABLE(params.table); + const newValues = params.body; + + tableToModify.modify(newValues).make(function(builder) { + + builder.callback(function(err, response) { + + if(!err) + { + responseObj["data"] = response; + responseObj["tableUpdated"] = true; + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + } + }); + }); + + } + + if(action == "replace") + { + //truncate table + const db = TABLE(params.table); + var builder = db.remove(); + db.clean(); + + //insert data + let data = params.data; + + for(let i = 0; i < data.length; i++) + { + //console.log(data[i]); + db.insert(data[i]); + } + + console.log("insert done"); + + let responseObj = {}; + responseObj["type"] = "SUCESS"; + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + + + } + + + + } catch (error) { + //console.log(error); + responseObj["type"] = "ERROR"; + responseObj["message"] = error; + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + } + } + }) +} + + diff --git a/RVO3/flow/db_init.js b/RVO3/flow/db_init.js new file mode 100755 index 0000000..b399878 --- /dev/null +++ b/RVO3/flow/db_init.js @@ -0,0 +1,113 @@ +exports.id = 'db_init'; +exports.title = 'DB Initialization'; +exports.group = 'Worksys'; +exports.color = '#888600'; +exports.version = '1.0.2'; +exports.icon = 'sign-out'; +exports.output = 2; + +exports.readme = ` + # DB initialization +`; + +const { promisifyBuilder, makeMapFromDbResult } = require('./helper/db_helper.js'); +const { initNotification } = require('./helper/notification_reporter'); +const errorHandler = require('./helper/ErrorToServiceHandler'); +const total_energy = require('../databases/total_energy'); + +const SEND_TO = { + db_init: 0, + infoSender: 1 +}; + + +exports.install = async function(instance) { + const dbNodes = TABLE("nodes"); + const dbRelays = TABLE("relays"); + const dbSettings = TABLE("settings"); + 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 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.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"]; + Object.keys(dbs.nodesData).forEach(node => dbs.nodesData[node].readout = {}) + + let rvo_number = responseSettings[0]["rvo_name"].match(/\D+(\d{1,2})_/)[1]; + + dbs.settings = { + edge_fw_version: "2025-10-08", //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"], + phases: responseSettings[0]["phases"], + cloud_topic: responseSettings[0]["cloud_topic"], + has_main_switch: responseSettings[0]["has_main_switch"], + daily_report: responseSettings[0]["daily_report"], + send_changed_node_numbers: responseSettings[0]["send_changed_node_numbers"], + rvo_number: rvo_number, + + //dynamic values + masterNodeIsResponding: true, //cmd_manager + maintenance_mode: false, + } + + + dbs.settings.energy_to_switch_lamps = total_energy[rvo_number]; + if (dbs.settings.energy_to_switch_lamps === undefined) console.log('=============== db_init.js: energy_to_switch_lamps is undefined'); + + FLOW.dbLoaded = true; + errorHandler.setProjectId(dbs.settings.project_id); + initNotification(); + + //APP START - send to data services + const toService = { + id: dbs.settings.project_id, + name: dbs.settings.rvo_name, + fw_version: dbs.settings.edge_fw_version, + startdate: new Date().toISOString().slice(0, 19).replace('T', ' '), + js_error: "", + error_message: "" + }; + + instance.send(SEND_TO.infoSender, toService); + console.log("----------------> START - message send to service", toService); + + setTimeout(() => { + console.log("DB_INIT - data loaded"); + instance.send(SEND_TO.db_init, "_") + }, 5000) + +}; + diff --git a/RVO3/flow/debug.js b/RVO3/flow/debug.js new file mode 100755 index 0000000..00cb259 --- /dev/null +++ b/RVO3/flow/debug.js @@ -0,0 +1,100 @@ +exports.id = 'debug'; +exports.title = 'Debug'; +exports.author = 'Peter Širka'; +exports.color = '#967ADC'; +exports.click = true; +exports.input = true; +exports.icon = 'bug'; +exports.version = '2.0.4'; +exports.options = { enabled: true, repository: false, type: 'data' }; +exports.readme = `# Debug + +Prints data to the debug tab.`; + +exports.html = `
+
+
+
@(Output type)
+
@(Path to the property (leave empty to show the whole data object))
+
@(A group name)
+
@(Enabled)
+
+
+
`; + +exports.install = function(instance) { + + instance.on('data', function(response) { + if (instance.options.enabled) { + + var opt = instance.options; + var rep = response.repository; + var val = response.data; + var id = response.id; + + switch (instance.options.type){ + case 'both': + var data = {}; + data.repository = rep; + data.data = val instanceof Error ? { error: val.message, stack: val.stack } : val; + instance.debug(safeparse(opt.property ? U.get(data, opt.property) : data), undefined, opt.group, id); + break; + case 'repository': + instance.debug(safeparse(opt.property ? U.get(rep, opt.property) : rep), undefined, opt.group, id); + break; + case 'data': + default: + if (val instanceof Error) + instance.debug({ error: val.message, stack: val.stack }, undefined, opt.group, id); + else + instance.debug(safeparse(opt.property ? U.get(val, opt.property) : val), undefined, opt.group, id); + break; + } + } + }); + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + instance.save(); + }); + + instance.on('options', function() { + instance.custom.status(); + }); + + instance.custom.status = function() { + instance.status(instance.options.enabled ? 'Enabled' : 'Disabled'); + }; + + instance.custom.status(); + + function safeparse(o) { + + if (o instanceof Buffer) + return o; + + if (o === undefined) + return 'undefined'; + + if (o === null) + return 'null'; + + var cache = []; + var str = JSON.stringify(o, function(key, value) { + if (typeof value === 'object' && value !== null) { + if (cache.indexOf(value) !== -1) { + try { + return JSON.parse(JSON.stringify(value)); + } catch (error) { + return; + } + } + cache.push(value); + } + return value; + }); + cache = null; + return JSON.parse(str); + } +}; diff --git a/RVO3/flow/designer.json b/RVO3/flow/designer.json new file mode 100755 index 0000000..580f5a3 --- /dev/null +++ b/RVO3/flow/designer.json @@ -0,0 +1,3102 @@ +{ + "tabs": [ + { + "name": "MAIN PUSH", + "linker": "main-push", + "id": "1612772287426", + "index": 0 + }, + { + "name": "CMD manager", + "linker": "cmd-manager", + "id": "1615551125555", + "index": 1 + }, + { + "name": "Devices", + "linker": "devices", + "id": "1611921777196", + "index": 2 + } + ], + "components": [ + { + "id": "1611951142547", + "component": "debug", + "tab": "1611921777196", + "name": "ERROR", + "x": 598, + "y": 60, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#DA4453", + "notes": "" + }, + { + "id": "1612776786008", + "component": "wsmqttpublish", + "tab": "1612772287426", + "name": "WS MQTT publish", + "x": 281.75, + "y": 174, + "connections": { + "0": [ + { + "index": "0", + "id": "1615551060773" + } + ], + "1": [ + { + "index": "0", + "id": "1618300858252" + }, + { + "index": "0", + "id": "1618558465485" + } + ], + "2": [ + { + "index": "0", + "id": "1634303685503" + } + ], + "3": [ + { + "index": "0", + "id": "1731068754606" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Connected", + "color": "green" + }, + "options": { + "username": "", + "clientid": "", + "port": "1883", + "host": "" + }, + "color": "#888600", + "notes": "" + }, + { + "id": "1612778461252", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "tb-push", + "x": 72.75, + "y": 328, + "connections": { + "0": [ + { + "index": "0", + "id": "1612783322136" + }, + { + "index": "1", + "id": "1612776786008" + }, + { + "index": "0", + "id": "1731068754606" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1612783322136", + "component": "debug", + "tab": "1612772287426", + "name": "to TB", + "x": 283.75, + "y": 324, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615551060773", + "component": "debug", + "tab": "1612772287426", + "name": "errors from MQTT Broker", + "x": 594, + "y": 57, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#DA4453", + "notes": "" + }, + { + "id": "1615563373927", + "component": "debug", + "tab": "1615551125555", + "name": "Debug", + "x": 755, + "y": 155, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#DA4453", + "notes": "" + }, + { + "id": "1615566865233", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "tb-push", + "x": 755, + "y": 248, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1615798582262", + "component": "debug", + "tab": "1615551125555", + "name": "CMD_debug", + "x": 755, + "y": 346, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615802995322", + "component": "debug", + "tab": "1611921777196", + "name": "Debug", + "x": 596.8833312988281, + "y": 566.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Disabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": false + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615809128443", + "component": "debug", + "tab": "1611921777196", + "name": "tempToTb", + "x": 595.8833312988281, + "y": 658.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615809595184", + "component": "virtualwireout", + "tab": "1611921777196", + "name": "tb-push", + "x": 597.8833312988281, + "y": 377.25, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1616165795916", + "component": "httproute", + "tab": "1615551125555", + "name": "POST /terminal", + "x": 135, + "y": 547, + "connections": { + "0": [ + { + "index": "0", + "id": "1684060205000" + }, + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Listening", + "color": "green" + }, + "options": { + "timeout": 10, + "cachepolicy": 0, + "cacheexpire": "5 minutes", + "size": 5, + "url": "/terminal", + "method": "POST", + "name": "", + "flags": [ + "id:1616165795916", + "post", + 10000 + ], + "emptyresponse": false + }, + "color": "#5D9CEC", + "notes": "### Configuration\n\n- __POST /terminal__\n- flags: \n- maximum request data length: __5 kB__\n- empty response: __false__\n- cache policy: __no cache__\n- cache expire: __5 minutes__", + "cloning": false + }, + { + "id": "1616165824813", + "component": "httpresponse", + "tab": "1615551125555", + "name": "HTTP Response", + "x": 753, + "y": 423, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "json" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1617104731852", + "component": "debug", + "tab": "1615551125555", + "name": "DIDO_Debug", + "x": 669, + "y": 1040, + "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": "turnOff line", + "x": 133, + "y": 1161, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "object", + "data": "{line: 3, command: \"turnOff\", force: true}" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1617115013095", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "tb-push", + "x": 669, + "y": 1150, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1617284749681", + "component": "trigger", + "tab": "1615551125555", + "name": "update profile / node", + "x": 112, + "y": 208, + "connections": { + "0": [ + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "data": "profile_nodes", + "datatype": "string" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1618235171399", + "component": "trigger", + "tab": "1615551125555", + "name": "tun tasks", + "x": 184, + "y": 279, + "connections": { + "0": [ + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "data": "run" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1618300858252", + "component": "debug", + "tab": "1612772287426", + "name": "wsmqtt-exit1", + "x": 597.8833312988281, + "y": 149, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1618393583970", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "to-cmd-manager", + "x": 668.8833312988281, + "y": 1269, + "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": 132.88333129882812, + "y": 367, + "connections": { + "0": [ + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "platform-rpc-call", + "color": "gray" + }, + "options": { + "wirename": "platform-rpc-call" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1618393759854", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "cmd_to_dido", + "x": 119.88333129882812, + "y": 1007, + "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": 752.8833312988281, + "y": 527, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "cmd_to_dido", + "color": "gray" + }, + "options": { + "wirename": "cmd_to_dido" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1618558465485", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "platform-rpc-call", + "x": 597.8833312988281, + "y": 247, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "platform-rpc-call", + "color": "gray" + }, + "options": { + "wirename": "platform-rpc-call" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1618572059773", + "component": "trigger", + "tab": "1615551125555", + "name": "turnOn line", + "x": 132, + "y": 1085, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "data": "{line: 1, command: \"turnOn\", force: true}", + "datatype": "object" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1619515097737", + "component": "cmd_manager", + "tab": "1615551125555", + "name": "CMD Manager", + "x": 452.1091003417969, + "y": 341.05455017089844, + "connections": { + "0": [ + { + "index": "0", + "id": "1615563373927" + } + ], + "1": [ + { + "index": "0", + "id": "1615566865233" + }, + { + "index": "0", + "id": "1615798582262" + } + ], + "2": [ + { + "index": "0", + "id": "1616165824813" + } + ], + "3": [ + { + "index": "0", + "id": "1618393827655" + } + ], + "4": [ + { + "index": "0", + "id": "1635936391935" + } + ], + "5": [ + { + "index": "0", + "id": "1757006030239" + }, + { + "index": "0", + "id": "1757006060377" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1619605019281", + "component": "httproute", + "tab": "1615551125555", + "name": "GET db", + "x": 173, + "y": 653, + "connections": { + "0": [ + { + "index": "0", + "id": "1684060205000" + }, + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Listening", + "color": "green" + }, + "options": { + "timeout": 5, + "cachepolicy": 0, + "cacheexpire": "5 minutes", + "size": 5, + "url": "/db", + "method": "GET", + "name": "", + "flags": [ + "id:1619605019281", + "get", + 5000 + ] + }, + "color": "#5D9CEC", + "notes": "### Configuration\n\n- __GET /db__\n- flags: undefined\n- maximum request data length: __5 kB__\n- empty response: __undefined__\n- cache policy: __no cache__\n- cache expire: __5 minutes__", + "cloning": false + }, + { + "id": "1619784672383", + "component": "trigger", + "tab": "1615551125555", + "name": "turnOnAlarm", + "x": 120, + "y": 1234, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "object", + "data": "{command: \"turnOnAlarm\"}" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1619784812964", + "component": "trigger", + "tab": "1615551125555", + "name": "turnOffAlarm", + "x": 118, + "y": 1307, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "object", + "data": "{command: \"turnOffAlarm\"}" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1621340721628", + "component": "virtualwireout", + "tab": "1611921777196", + "name": "modbus_to_dido", + "x": 599, + "y": 471, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "modbus_to_dido", + "color": "gray" + }, + "options": { + "wirename": "modbus_to_dido" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1622640022885", + "component": "httproute", + "tab": "1615551125555", + "name": "POST /db_connector", + "x": 98, + "y": 1586, + "connections": { + "0": [ + { + "index": "0", + "id": "1622640073521" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Listening", + "color": "green" + }, + "options": { + "timeout": 5, + "cachepolicy": 0, + "cacheexpire": "5 minutes", + "size": 5, + "url": "/db_connector", + "method": "POST", + "flags": [ + "id:1622640022885", + "post", + 5000 + ] + }, + "color": "#5D9CEC", + "notes": "### Configuration\n\n- __POST /db_connector__\n- flags: \n- maximum request data length: __5 kB__\n- empty response: __undefined__\n- cache policy: __no cache__\n- cache expire: __5 minutes__", + "cloning": false + }, + { + "id": "1622640073521", + "component": "db_connector", + "tab": "1615551125555", + "name": "DbConnector", + "x": 372, + "y": 1572, + "connections": { + "1": [ + { + "index": "0", + "id": "1622641420685" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "edge": "undefined" + }, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1622641420685", + "component": "httpresponse", + "tab": "1615551125555", + "name": "HTTP Response", + "x": 596, + "y": 1586, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1634303504177", + "component": "monitormemory", + "tab": "1612772287426", + "name": "RAM", + "x": 69.88333129882812, + "y": 888.5, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465281992" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "858.88 MB / 985.68 MB", + "color": "gray" + }, + "options": { + "enabled": true, + "interval": 30000 + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1634303533779", + "component": "monitordisk", + "tab": "1612772287426", + "name": "disk", + "x": 70.88333129882812, + "y": 982.5, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465821120" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "5.78 GB / 7.26 GB", + "color": "gray" + }, + "options": { + "enabled": true, + "path": "/", + "interval": 30000 + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1634303595494", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "send-to-services", + "x": 51.883331298828125, + "y": 1400.5, + "connections": { + "0": [ + { + "index": "0", + "id": "1634463186563" + }, + { + "index": "1", + "id": "1634488120710" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1634303602169", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "send-to-services", + "x": 426.8833312988281, + "y": 878.5, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1634303685503", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "send-to-services", + "x": 600.8833312988281, + "y": 341.5, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1634303743260", + "component": "httprequest", + "tab": "1612772287426", + "name": "192.168.252.2:8004/sentmessage", + "reference": "", + "x": 506.8833312988281, + "y": 1331.7333374023438, + "connections": { + "0": [ + { + "index": "0", + "id": "1635327431236" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "url": "http://192.168.252.2:8004/sentmessage", + "method": "POST", + "stringify": "json" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1634463186563", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 305.75, + "y": 1442, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634464580289", + "component": "code", + "tab": "1612772287426", + "name": "Code", + "x": 245, + "y": 787, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465243324" + }, + { + "index": "0", + "id": "1634303602169" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "keepmessage": true, + "code": "let response = {};\nresponse.cpu = value.cpu;\nresponse.uptime = value.uptime;\n\nsend(0, response);", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1634465243324", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 428, + "y": 784, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634465281992", + "component": "code", + "tab": "1612772287426", + "name": "Code", + "x": 245, + "y": 884, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465338103" + }, + { + "index": "0", + "id": "1634303602169" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "keepmessage": true, + "code": "value.sender = \"ram\";\n\nlet response = {};\n\nresponse.memory_total = Math.round(value.total / (1024 ** 2));\nresponse.memory_free = Math.round(value.free / (1024 ** 2));\nresponse.memory_used = Math.round(value.used / (1024 ** 2));\n\nsend(0, response);", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1634465338103", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 429, + "y": 976, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634465821120", + "component": "code", + "tab": "1612772287426", + "name": "Code", + "x": 245, + "y": 978, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465892500" + }, + { + "index": "0", + "id": "1634303602169" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "keepmessage": true, + "code": "value.sender = \"hdd\";\n\nlet response = {};\n\nresponse.hdd_total = Math.round(value.total / (1024 ** 2));\nresponse.hdd_free = Math.round(value.free / (1024 ** 2));\nresponse.hdd_used = Math.round(value.used / (1024 ** 2));\n\nsend(0, response);", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1634465892500", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 432, + "y": 1068, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634484067516", + "component": "debug", + "tab": "1612772287426", + "name": "Send info", + "x": 513, + "y": 1441, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634488120710", + "component": "infosender", + "tab": "1612772287426", + "name": "Info sender", + "x": 301, + "y": 1336, + "connections": { + "0": [ + { + "index": "0", + "id": "1634484067516" + }, + { + "index": "0", + "id": "1634303743260" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "edge": "undefined" + }, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1635327431236", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 837.8833312988281, + "y": 1325.5, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1635936391935", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "send-to-services", + "x": 753, + "y": 623, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1637069803394", + "component": "monitorconsumption", + "tab": "1612772287426", + "name": "CPU", + "x": 69, + "y": 791, + "connections": { + "0": [ + { + "index": "0", + "id": "1634464580289" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "49.2% / 69.91 MB", + "color": "gray" + }, + "options": { + "monitorfiles": true, + "monitorconnections": true, + "monitorsize": true, + "monitorconsumption": true, + "enabled": true, + "interval": 30000 + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1683664161036", + "component": "debug", + "tab": "1615551125555", + "name": "CMDtoDIDO", + "x": 392, + "y": 1012, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1683981346282", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "from-dido-controller", + "x": 112, + "y": 459, + "connections": { + "0": [ + { + "index": "0", + "id": "1684055037116" + }, + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "from-dido-controller", + "color": "gray" + }, + "options": { + "wirename": "from-dido-controller" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1684055037116", + "component": "debug", + "tab": "1615551125555", + "name": "from dido to cmd", + "x": 451, + "y": 532, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1684060205000", + "component": "debug", + "tab": "1615551125555", + "name": "HTTP routes", + "x": 450, + "y": 639, + "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": "MDBToDido", + "x": 598, + "y": 147, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1699963668903", + "component": "dido_controller", + "tab": "1615551125555", + "name": "DIDO_Controller", + "x": 397, + "y": 1131, + "connections": { + "0": [ + { + "index": "0", + "id": "1617104731852" + } + ], + "1": [ + { + "index": "0", + "id": "1617104731852" + }, + { + "index": "0", + "id": "1617115013095" + } + ], + "2": [ + { + "index": "0", + "id": "1618393583970" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "edge": "undefined" + }, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1699964678894", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "modbus_to_dido", + "x": 96, + "y": 924, + "connections": { + "0": [ + { + "index": "0", + "id": "1699963668903" + }, + { + "index": "0", + "id": "1699964793925" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "modbus_to_dido", + "color": "gray" + }, + "options": { + "wirename": "modbus_to_dido" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1699964793925", + "component": "debug", + "tab": "1615551125555", + "name": "modbusToDido", + "x": 388, + "y": 920, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1699965957410", + "component": "modbus_reader", + "tab": "1611921777196", + "name": "Modbus reader", + "x": 232, + "y": 175, + "connections": { + "0": [ + { + "index": "0", + "id": "1611951142547" + } + ], + "1": [ + { + "index": "0", + "id": "1621340721628" + }, + { + "index": "0", + "id": "1684179110403" + }, + { + "index": "0", + "id": "1717441414646" + } + ], + "2": [ + { + "index": "0", + "id": "1615809595184" + }, + { + "index": "0", + "id": "1714752862828" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1700411878636", + "component": "thermometer", + "tab": "1611921777196", + "name": "Thermometer", + "x": 234.75, + "y": 444, + "connections": { + "0": [ + { + "index": "0", + "id": "1615802995322" + } + ], + "1": [ + { + "index": "0", + "id": "1615809595184" + }, + { + "index": "0", + "id": "1615809128443" + } + ], + "2": [ + { + "index": "0", + "id": "1621340721628" + }, + { + "index": "0", + "id": "1732889185927" + }, + { + "index": "0", + "id": "1717441414646" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#5CB36D", + "notes": "" + }, + { + "id": "1714752862828", + "component": "debug", + "tab": "1611921777196", + "name": "MDBToTb", + "x": 766, + "y": 324, + "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": 764.0833282470703, + "y": 222, + "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\telse if(value.status === \"NOK-thermometer\")\n\t{\n\t\tsend(0, {\"thermometer\": \"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\telse if(value.values.hasOwnProperty(\"temperature\"))\n\t{\n\t\tsend(0, {\"thermometer\": \"OK\"});\n\t}\n}", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1717442627834", + "component": "debug", + "tab": "1611921777196", + "name": "modbus service", + "x": 966.0833282470703, + "y": 165, + "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": 968.0833282470703, + "y": 268, + "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": 88.75, + "y": 1685, + "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": 296, + "y": 1671, + "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\", \"Flow has been restarted\", \"Node db has changed\"]", + "types": "[\"emergency\", \"critical\", \"error\", \"alert\"]", + "name": "" + }, + "color": "#30E193", + "notes": "" + }, + { + "id": "1718016073501", + "component": "httprequest", + "tab": "1612772287426", + "name": "http://192.168.252.2:8004/slack", + "x": 495, + "y": 1753, + "connections": { + "0": [ + { + "index": "0", + "id": "1718016086212" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "url": "http://192.168.252.2:8004/slack", + "method": "POST", + "stringify": "json" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1718016086212", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 832, + "y": 1664, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "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": 87, + "y": 1591, + "connections": { + "0": [ + { + "index": "0", + "id": "1718016052341" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "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\": \"\" } } } ] }", + "datatype": "object" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1729855334955", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "platform-rpc-call", + "x": 599.9333343505859, + "y": 541.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "platform-rpc-call", + "color": "gray" + }, + "options": { + "wirename": "platform-rpc-call" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1729855371093", + "component": "debug", + "tab": "1612772287426", + "name": "rpc cloud", + "x": 601.9333343505859, + "y": 440.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1731068658334", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 75.75, + "y": 184, + "connections": { + "0": [ + { + "index": "0", + "id": "1612776786008" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731068754606", + "component": "cloudmqttconnect", + "tab": "1612772287426", + "name": "MQTT to senica-prod01", + "x": 284.75, + "y": 452, + "connections": { + "1": [ + { + "index": "0", + "id": "1729855371093" + }, + { + "index": "0", + "id": "1729855334955" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Connected", + "color": "green" + }, + "options": { + "username": "", + "clientid": "", + "port": "2764", + "host": "192.168.252.2", + "topic": "" + }, + "color": "#888600", + "notes": "" + }, + { + "id": "1731069001548", + "component": "db_init", + "tab": "1612772287426", + "name": "DB Initialization", + "x": 1003.75, + "y": 240.25, + "connections": { + "0": [ + { + "index": "0", + "id": "1731069033416" + } + ], + "1": [ + { + "index": "0", + "id": "1747561603739" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#888600", + "notes": "" + }, + { + "id": "1731069033416", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "db-init", + "x": 1244.75, + "y": 233.25, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069059135", + "component": "showdb", + "tab": "1612772287426", + "name": "Show db data", + "x": 1186.75, + "y": 821.25, + "connections": { + "0": [ + { + "index": "0", + "id": "1731069079243" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#888600", + "notes": "" + }, + { + "id": "1731069079243", + "component": "debug", + "tab": "1612772287426", + "name": "dbData", + "x": 1390.75, + "y": 870.25, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1731069116691", + "component": "trigger", + "tab": "1612772287426", + "name": "settings", + "x": 934.75, + "y": 669.75, + "connections": { + "0": [ + { + "index": "0", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069131637", + "component": "trigger", + "tab": "1612772287426", + "name": "relaysData", + "x": 876.75, + "y": 733.75, + "connections": { + "0": [ + { + "index": "1", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069137374", + "component": "trigger", + "tab": "1612772287426", + "name": "nodesData", + "x": 852.75, + "y": 794.75, + "connections": { + "0": [ + { + "index": "2", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069179846", + "component": "trigger", + "tab": "1612772287426", + "name": "pinsData", + "x": 850.75, + "y": 861.75, + "connections": { + "0": [ + { + "index": "3", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069192937", + "component": "trigger", + "tab": "1612772287426", + "name": "sample data", + "x": 857.75, + "y": 928.75, + "connections": { + "0": [ + { + "index": "4", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069264443", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 63.75, + "y": 1279, + "connections": { + "0": [ + { + "index": "0", + "id": "1634488120710" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069334626", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "db-init", + "x": 172.88333129882812, + "y": 129, + "connections": { + "0": [ + { + "index": "0", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069548145", + "component": "virtualwirein", + "tab": "1611921777196", + "name": "db-init", + "x": 46.75, + "y": 192, + "connections": { + "0": [ + { + "index": "0", + "id": "1699965957410" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069567152", + "component": "virtualwirein", + "tab": "1611921777196", + "name": "db-init", + "x": 44.75, + "y": 465, + "connections": { + "0": [ + { + "index": "0", + "id": "1700411878636" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731070156936", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "db-init", + "x": 126.88333129882812, + "y": 1377, + "connections": { + "0": [ + { + "index": "2", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731234189516", + "component": "trigger", + "tab": "1612772287426", + "name": "monitor.txt", + "x": 882.75, + "y": 991.75, + "connections": { + "0": [ + { + "index": "5", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731234189551", + "component": "trigger", + "tab": "1612772287426", + "name": "err.txt", + "x": 904.75, + "y": 1053.75, + "connections": { + "0": [ + { + "index": "6", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1732700042559", + "component": "nodesdb_change_check", + "tab": "1612772287426", + "name": "Nodes DB change check", + "x": 266.8833312988281, + "y": 1980.2333984375, + "connections": { + "0": [ + { + "index": "0", + "id": "1732700071298" + }, + { + "index": "0", + "id": "1732700642917" + } + ], + "1": [ + { + "index": "0", + "id": "1759958914348" + }, + { + "index": "0", + "id": "1759959003114" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#888600", + "notes": "" + }, + { + "id": "1732700057052", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 76.75, + "y": 1988, + "connections": { + "0": [ + { + "index": "0", + "id": "1732700042559" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1732700071298", + "component": "debug", + "tab": "1612772287426", + "name": "nodesChange", + "x": 571.8833312988281, + "y": 2018.2333984375, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1732700642917", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "tb-push", + "x": 567.8833312988281, + "y": 1933, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1732889185927", + "component": "debug", + "tab": "1611921777196", + "name": "tempToDido", + "x": 594.8833312988281, + "y": 753, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1733574412965", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 72.75, + "y": 474, + "connections": { + "0": [ + { + "index": "1", + "id": "1731068754606" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1747561603739", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "send-to-services", + "x": 1243.8833312988281, + "y": 334.5, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1747562867845", + "component": "comment", + "tab": "1612772287426", + "name": "FLOW STARTING POINT", + "x": 1003.5666656494141, + "y": 178, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#704cff", + "notes": "" + }, + { + "id": "1749211698385", + "component": "trigger", + "tab": "1612772287426", + "name": "deviceStatus", + "x": 911.75, + "y": 1116.75, + "connections": { + "0": [ + { + "index": "7", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1757006030239", + "component": "httprequest", + "tab": "1615551125555", + "name": "192.168.252.2:8015/daily_report", + "x": 756.5666656494141, + "y": 715.4499969482422, + "connections": { + "0": [ + { + "index": "0", + "id": "1757006045804" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "stringify": "json", + "method": "POST", + "url": "http://192.168.252.2:8015/daily_report" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1757006045804", + "component": "debug", + "tab": "1615551125555", + "name": "ddd", + "x": 1091.566665649414, + "y": 711.4499969482422, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1757006060377", + "component": "debug", + "tab": "1615551125555", + "name": "reportDebug", + "x": 749.5666656494141, + "y": 799.4499969482422, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1759958914348", + "component": "httprequest", + "tab": "1612772287426", + "name": "http://192.168.252.2:8015/node_numbers", + "x": 571, + "y": 2111, + "connections": { + "0": [ + { + "index": "0", + "id": "1759958927094" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "stringify": "json", + "method": "POST", + "url": "http://192.168.252.2:8015/node_numbers" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1759958927094", + "component": "debug", + "tab": "1612772287426", + "name": "nodesChangeCloud", + "x": 951.8833312988281, + "y": 2109.2333984375, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1759959003114", + "component": "debug", + "tab": "1612772287426", + "name": "nodeChangeCloud1", + "x": 574, + "y": 2218, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1760020290879", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 84.75, + "y": 1787, + "connections": { + "0": [ + { + "index": "1", + "id": "1718016052341" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + } + ], + "version": 615 +} diff --git a/RVO3/flow/dido_controller.js b/RVO3/flow/dido_controller.js new file mode 100755 index 0000000..d16fb19 --- /dev/null +++ b/RVO3/flow/dido_controller.js @@ -0,0 +1,1486 @@ +exports.id = 'dido_controller'; +exports.title = 'DIDO_Controller'; +exports.version = '2.0.0'; +exports.group = 'Worksys'; +exports.color = '#2134B0'; +exports.input = 3; +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 + +state_of_main_switch - reportovat stav hlaveho istica : 0-> off 1-> on +rotary_switch_state - sem by sa mal reportovat stav vstupov manual a auto pola nasledovnej logiky: Manual = 1 a Auto = 0 -> Manu +Manual = 0 a Auto = 0 -> Off, Manual = 0 a Auto = 1 -> Automatic + +door_condition - pin 6, dverový kontakt -> 1 -> vyreportuje Closed, 0 -> vyreportuje Ope +twilight_sensor - hodnotu, ktoru vracia ten analogovy vstup (17) treba poslat sem ako float number. Zrejme tu potom pridame nejaky koeficient prevodu na luxy + +Na kazdu liniu +state_of_breaker - podla indexu istica sa reportuje jeho stav, teda istic na liniu 1: 0-> off, 1-> on +state_of_contactor - podla indexu stkaca sa reportuje jeho stav, teda stykac 1 na liniu 1: 0-> off, 1-> on +*/ + +const { errLogger, logger, monitor } = require('./helper/logger'); +const SerialPort = require('serialport'); +const WebSocket = require('ws'); +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 errorHandler = require('./helper/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 hasMainSwitch; + +let alarmStatus = "OFF"; + +const SEND_TO = { + debug: 0, + tb: 1, + cmd_manager: 2 +} + + +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 = {}; + let rsPortReceivedData = []; + + //to be able to get proper twilight values + let twilight_sensor_interval = 5;//minutes + let twilight_sensor = []; + const twilight_sensor_array = []; + let twilightError = false; + + monitor.info("DIDO_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-we make it global to see it from outside + FLOW.deviceStatus = { //key is device name: temperature,.... + "state_of_main_switch": "Off", //Hlavny istic (alebo druhy dverovy kontakt) + "rotary_switch_state": "Off", //Prevadzkovy + "door_condition": "closed", //Dverový kontakt + "em": "OK", //elektromer rvo + "temperature": "OK", //templomer + "battery": "OK", //Bateria + "power_supply": "OK", //Zdroj + "master_node": "OK", //MN - GLOBALS.settings.masterNodeIsResponding + "no_voltage": "OK", //GLOBALS.settings.no_voltage - vypadok napatia na faze + "state_of_breaker": {}, //"Off",//Istic + "state_of_contactor": {}, //"Off",//Stykac + "twilight_sensor": "OK" //lux sensor + }; + let deviceStatus = FLOW.deviceStatus; + + + function main() { + + GLOBALS = FLOW.GLOBALS; + SETTINGS = FLOW.GLOBALS.settings; + rvoTbName = SETTINGS.rvoTbName; + pinsData = GLOBALS.pinsData; + relaysData = GLOBALS.relaysData; + + tbHandler = new DataToTbHandler(SEND_TO.tb); + tbHandler.setSender(exports.title); + + controller_type = SETTINGS.controller_type; //"lm" or "unipi" + hasMainSwitch = SETTINGS.has_main_switch; + + if (controller_type == "") controller_type = "lm"; + + 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, "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; + } + } + + //report RVO version relaysData[0].tbname; + let values = {}; + values["edge_fw_version"] = SETTINGS.edge_fw_version; + values["maintenance_mode"] = SETTINGS.maintenance_mode; + + sendTelemetry(values, rvoTbName); + + 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); + } + + + function handleRsPort() { + + if (rsPort) { + rsPort.removeAllListeners(); + rsPort = null; + } + + //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('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) { + if (!err) { + monitor.info(exports.title + "--->Digital in_out has been set (runSyncExec was sucessfull)"); + + turnAlarm("off"); + 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('error', err => { + let message = "Dido: rsPort error: " + err.message; + logger.debug(message); + monitor.info(message); + errorHandler.sendMessageToService(message); + }) + + rsPort.on("close", () => { + let message = "Dido: rsPort closed - reconnecting ..."; + logger.debug(message); + monitor.info(message); + setTimeout(handleRsPort, 1000); + }) + + rsPort.open(); + } + + + function handleWebSocket() { + + if (ws) { + ws.removeAllListeners(); + ws = null; + } + + //to keep websocket opened, we send request every 150 seconds + let startRequests = null; + + console.log("handleWebSocket function called"); + ws = new WebSocket('ws:/0.0.0.0:1234/ws'); + + ws.onopen = function open() { + + instance.send(0, exports.title + " running"); + turnAlarm("off"); + + initialSetting(); + + setTimeout(function() { ws.send(JSON.stringify({ cmd: "all" })) }, 5000); + // we request dev info about neuron device from evok to keep websocket connection alive + // for some reason this request returns no data, but connection keeps alive + startRequests = setInterval(() => { + ws.send(JSON.stringify({ "cmd": "filter", "dev": ["neuron"] })); + }, 150000) + }; + + + // 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 = async 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; + + 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 => { + logger.debug('Dido: websocket error', err); + }) + + ws.onclose = function() { + logger.debug('Dido: websocket onclose, reconnecting...') + clearInterval(startRequests); + setTimeout(handleWebSocket, 1000); + } + } + + 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 turnAlarm(onOrOff) { + let value = 0; + if (onOrOff == "on") value = 1; + + if (value == 1 && SETTINGS.maintenance_mode) return; + + alarmStatus = "OFF"; + if (value == 1) alarmStatus = "ON"; + + if (rsPort) { + let arr = [0x55]; + arr.push(13); + arr.push(0); + arr.push(value); + + rsPort.write(Buffer.from(arr), function(err) { + logger.debug(`sirena - ${onOrOff}`); + }); + } + else if (ws) { + let cmd = { "cmd": "set", "dev": "relay", "circuit": "1_01", "value": value }; + ws.send(JSON.stringify(cmd)); + logger.debug(`sirena - ${onOrOff}`); + } + } + + + 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") { + bits.push(0); + } + else bits.push(1); + + if (deviceStatus["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); + } + + + // turn line on or off + function turnLine(onOrOff, line, pin, force, info) { + //onOrOff => "on" or "off" + let value = 0; + if (onOrOff == "on") value = 1; + + if (force == undefined) force = false; + + if (line == 0) { + if (value == 1 && alarmStatus == "ON") turnAlarm("off"); + SETTINGS.maintenance_mode = value ? true : false; + + 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); + return; + } + + if (pin === undefined) pin = getPin(line); + + if (pin === undefined) { + errLogger.error("pin is undefined!", line); + return; + } + + if (!force) { + if (relaysData[line].contactor == value) { + instance.send(SEND_TO.debug, `line is already ${onOrOff} ` + line); + logger.debug(`Dido: turnLine: line is already ${onOrOff} `, line); + return; + } + } + + // if(!rsPort.isOpen && !ws) + if (!rsPort && !ws) { + errLogger.error("Dido - port or websocket is not opened"); + return; + } + + if (rsPort) { + let arr = [0x55]; + arr.push(pin); + arr.push(0); + arr.push(value); + + rsPort.write(Buffer.from(arr), function(err) { + if (err === undefined) { + monitor.info(`Dido: turnLine ${onOrOff} zapisal do rsPort-u`, line, pin, arr, info); + switchLogic(arr); + } + else { + monitor.info(`Dido: turnLine ${onOrOff} WRITE error`, err); + } + }); + + } + else if (ws) { + //pin = "relay1_03" or "input1_01" ... we must make just "1_01" with slice method + monitor.info(`Dido: turnLine ${onOrOff} - (line, pin, force)`, line, pin, force, info); + let cmd = { "cmd": "set", "dev": "relay", "circuit": pin.slice(5), "value": value }; + ws.send(JSON.stringify(cmd)); + } + + //if rvo is 24/7, it has just one switching profile point at 13:00. we do not want to send notification as it repeats every day. + //const d = new Date(); + //if(d.getHours() != 13) sendNotification("Dido_controller: ", SETTINGS.rvoTbName, "switching_profile_point_applied_to_line", { line: line, value: onOrOff }, "", SEND_TO.tb, instance); + } + + + // 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; + + // 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) { + const status = flowdata.data.status; + if (status == "NOK-twilight_sensor") { + deviceStatus["twilight_sensor"] = "NOK"; + } + else if (status == "NOK-em340" || status == "NOK-em111") { + deviceStatus["em"] = "NOK"; + } + else if (status == "NOK-thermometer") { + deviceStatus["temperature"] = "NOK"; + } + } + else if ("values" in flowdata.data) { + 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" + } + else if (values.hasOwnProperty("temperature")) { + deviceStatus["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"; + } + + sendTelemetry(values, rvoTbName); + } + + sendRvoStatus(); + }) + + + + + // we expect array as flowdata.data + instance.on("1", flowdata => { + + //console.log(flowdata.data); + + if (!flowdata.data instanceof Object) return; + + let obj = flowdata.data; + let line = obj.line; + 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"); + }) + + + function calculateStateCode() { + + let bits = []; + + //Hlavny istic - state_of_main_switch => v rvo senica je to druhy door pre silovu cast (EM) + if (deviceStatus["state_of_main_switch"] === "closed" || deviceStatus["state_of_main_switch"] === "Off") { + bits.push(0); + } + else { + bits.push(1); + } + + //Prevadzkovy mod - Manual, Off, Automatic, maintenance_mode = true/false // DAVA 2 BITY + if (!SETTINGS.maintenance_mode) { + if (deviceStatus["rotary_switch_state"] === "Manual") { + bits.push(0); + bits.push(1); + } + + if (deviceStatus["rotary_switch_state"] === "Automatic") { + bits.push(0); + bits.push(0); + } + + if (deviceStatus["rotary_switch_state"] === "Off") { + bits.push(1); + bits.push(0); + } + } + else { + bits.push(1); + bits.push(1); + } + + //Dverovy kontakt + if (deviceStatus["door_condition"] === "closed") { + bits.push(0); + } + else { + bits.push(1); + } + + //EM + if (deviceStatus["em"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //Teplomer + if (deviceStatus["temperature"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //Batéria + if (deviceStatus["battery"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //Zdroj + if (deviceStatus["power_supply"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //MN + if (deviceStatus["master_node"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //výpadok napätia na fáze + if (deviceStatus["no_voltage"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + if (deviceStatus["twilight_sensor"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + // doplnime do 16 bitov (2 byty) + for (let i = bits.length; i < 16; i++) { + bits.push(0); + } + + // console.log("calculateStateCode - deviceStatus", deviceStatus); + // 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; + } + + + async function sendRvoStatus() { + + if (SETTINGS === undefined) return; + SETTINGS.masterNodeIsResponding ? deviceStatus["master_node"] = "OK" : deviceStatus["master_node"] = "NOK"; + + 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 pinsForRvoStatus(controllerType, hasMainSwitch) { + + let pins = []; + + if (controllerType === "lm") { + pins = [1, 4, 6]; + if (hasMainSwitch === 1) { + pins = [4, 6]; + } + } else if (controllerType === "unipi") { + pins = ["input1_01", "input1_04", "input1_05"]; + if (hasMainSwitch === 1) { + pins = ["input1_01", "input1_04"]; + } + } + + return pins; + } + + + function checkRvoStatus() { + + // 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 + //set RVO state + let status = "OK"; + + for (const [key, value] of Object.entries(deviceStatus)) { + if (["em", "twilight_sensor", "temperature", "master_node"].includes(key) && value === "NOK") status = "NOK"; + } + + if (status === "OK") { + + let pinIndexes = pinsForRvoStatus(controller_type, hasMainSwitch); + + for (const pinIndex of pinIndexes) { + if (previousValues[pinIndex] === 0) { + if ((pinIndex === 6 || pinIndex === 'input1_01' || pinIndex === 'input1_05') && SETTINGS.maintenance_mode) continue; + status = "NOK"; + break; + } + } + } + + // battery status. If value is 1 - battery is NOK + if (previousValues[5] === 1) status = "NOK"; + if (SETTINGS.no_voltage.size > 0) status = "NOK"; + + // console.log("rvo status",status) + return status; + } + + + // we pass array to function in case of rsPort ==> switchLogic([55,3,0,1]) ==> [[55,3,0,1]] + // we pass two values in case of websocket ==> switchLogic("relay1_03",1) ==> ["relay1_03",1] + const switchLogic = (...args) => { + + let values = {}; + let pinIndex, newPinValue, twilight; + + //data from rsPort + if (args.length == 1) { + pinIndex = args[0][1] + 1; + if (pinIndex === 17) pinIndex--; + newPinValue = args[0][3]; + twilight = args[0][2]; + } + //data from websocket + else { + pinIndex = args[0]; + newPinValue = args[1]; + } + + 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; + + //default value + let value = "On"; + if (newPinValue === 0) value = "Off"; + + //Hlavny istic + if (type === "state_of_main_switch" && hasMainSwitch) { + if (newPinValue === 0 && newPinValue !== previousValues[pinIndex]) { + sendNotification("switchLogic", rvoTbName, "main_switch_has_been_turned_off", {}, "", SEND_TO.tb, instance, "state_of_main_switch"); + 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"); + deviceStatus["state_of_main_switch"] = "On"; + } + } + + //Prevadzkovy mod + 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"; + + deviceStatus["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, "power_supply_has_disconnected_input", {}, "", SEND_TO.tb, instance, "power_supply"); + + deviceStatus["power_supply"] = "NOK"; + } + else if (newPinValue === 1 && newPinValue !== previousValues[pinIndex]) { + sendNotification("switchLogic", rvoTbName, "power_supply_works_correctly", {}, "", SEND_TO.tb, instance, "power_supply"); + + deviceStatus["power_supply"] = "OK"; + } + } + + //Bateria - 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"); + + deviceStatus["battery"] = "NOK"; + } + else if (newPinValue === 0 && newPinValue !== previousValues[pinIndex]) { + sendNotification("switchLogic", rvoTbName, "battery_level_is_ok", {}, "", SEND_TO.tb, instance, "battery_level"); + + deviceStatus["battery"] = "OK"; + } + } + + //Dverovy kontakt - pin 6 + //! Ak je rvo s dvoma dverovymi kontaktami, ked pride z evoku signal z input1_05, co bol predytm "state_of_main switch" handlujeme ho teraz ako 'door_condition' + else if (type == "door_condition" || type === "state_of_main_switch") { + newPinValue === 0 ? value = "open" : value = "closed"; + + let door = "door_main"; + if (type === "state_of_main_switch") door = "door_em"; + + if (value === "open") { + if (SETTINGS.maintenance_mode) { + sendNotification("switchLogic", rvoTbName, door + "_open", {}, "", SEND_TO.tb, instance, door); + } else { + sendNotification("switchLogic", rvoTbName, door + "_open_without_permission", {}, "", SEND_TO.tb, instance, door); + + // 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 (value === "closed") { + if (alarmStatus == "ON") turnAlarm("off"); + sendNotification("switchLogic", rvoTbName, door + "_close", {}, "", SEND_TO.tb, instance, door); + } + + deviceStatus[type] = value; + } + + //lux sensor + else if (type == "twilight_sensor") { + //! TODO - to show nok status, if lux value is not changing more then 10 times. + //Daylight is far more than 1000. So most of the day, when it is sunshine comes just value 1000. But lux sensor is not NOK. + //This is not the case in LM. If value from LM is the same 10x, there is 99% possibility, that sensor is NOK. + value = newPinValue; + + if (controller_type === 'lm') { + value = parseFloat(newPinValue + (256 * twilight)); + + 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 && !twilightError) { + twilightError = true; + let value = twilight_sensor_array.shift(); + + newPinValue = 0; + } + else if (set.size !== 1 && twilightError) { + //sendNotification("switchLogic", rvoTbName, 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) { + 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); + } + } + + 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); + } + + deviceStatus["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 (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 }); + + //mame iba 3 istice. vyreportujeme a ohandlujeme liniu na tom istom istici ako paralelna linia (napr linia 1, paralelna s nou je linia 4, key je string "4") + // ak je 7 linii, na 1 istici je linia 1,4,7 + + if (line == 1) { + + const lineOnSameBraker = [4, 7]; + + for (var i = 0; i < lineOnSameBraker.length; i++) { + if (!relaysData.hasOwnProperty(lineOnSameBraker[i])) continue; + + 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; + reportLineStatus(lineOnSameBraker[i]); + + values[type] = value; + const tbname = relaysData[lineOnSameBraker[i]].tbname; + sendTelemetry(values, tbname); + + delete values[type]; + } + + } + else { + const lineOnSameBraker = line + 3 + ""; + + if (relaysData.hasOwnProperty(lineOnSameBraker)) { + 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; + reportLineStatus(line + 3); + + values[type] = value; + const tbname = relaysData[lineOnSameBraker].tbname; + sendTelemetry(values, tbname); + + delete values[type]; + } + } + + } + + if (value == "Off") values["status"] = "NOK"; + deviceStatus["state_of_breaker"][line] = value; + + reportLineStatus(line); + } + else return; + + values[type] = value; + + if (type == "rotary_switch_state") { + if (SETTINGS.maintenance_mode) value = "maintenance"; + value = value.toLowerCase(); + values["power_mode"] = value; + } + + if (newPinValue != previousValues[pinIndex]) previousValues[pinIndex] = newPinValue; + if (Object.keys(values).length > 0 && tbname) sendTelemetry(values, tbname); + } + + + function sendTelemetry(values, tbname, date = Date.now()) { + let dataToTb = { + [tbname]: [ + { + "ts": date, + "values": values + } + ] + }; + + tbHandler.sendToTb(dataToTb, instance); + } + + + function isObject(item) { + return (typeof item === "object" && !Array.isArray(item) && item !== null); + } + +} //end of 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 +// *|input1_01|state_of_main_switch|0|........... +// *|input1_02|rotary_switch_state|0|........... +// *|input1_03|rotary_switch_state|0|........... +// *|intut1_04|power_supply|0|........... +// *|input1_05|door_condition|0|........... +// *|input1_06|state_of_breaker|1|........... +// *|input1_07|state_of_breaker|2|........... +// *|input1_08|state_of_breaker|3|........... +// *|relay1_02|state_of_contactor|1|........... +// *|relay1_03|state_of_contactor|2|........... +// *|relay1_04|state_of_contactor|3|........... +// *|287D8776E0013CE9|temperature|0|........... + + +//! pins_data --> from UNIPI +// { +// 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 } +// } + +//! relays_data +// { +// '0': { +// line: 0, +// tbname: 'KjbN4q7JPZmexgdnz2yKQ98YAWwO0Q3BMX6ERLoV', +// contactor: 1, +// profile: '' +// }, +// '1': { +// line: 1, +// tbname: 'RMgnK93rkoAazbqdQ4yBG95Z1YXGx6pmwBeVEP2O', +// contactor: 0, +// profile: '{"intervals":[{"value":0,"end_time":"20:00","start_time":"13:00"},{"value":1,"end_time":"10:00","start_time":"20:00"},{"value":0,"end_time":"10:20","start_time":"10:00"},{"value":1,"end_time":"10:40","start_time":"10:20"},{"value":0,"end_time":"11:00","start_time":"10:40"},{"value":1,"end_time":"11:30","start_time":"11:00"},{"value":0,"end_time":"11:50","start_time":"11:30"},{"value":1,"end_time":"13:00","start_time":"11:50"}],"astro_clock":false,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' +// }, +// '2': { +// line: 2, +// tbname: 'dlE1VQjYrNx9gZRmb38gG08oLBO4qaAk2M6JPnG7', +// contactor: 0, +// profile: '{"intervals":[{"value":0,"end_time":"20:00","start_time":"13:00"},{"value":1,"end_time":"10:00","start_time":"20:00"},{"value":0,"end_time":"10:20","start_time":"10:00"},{"value":1,"end_time":"10:40","start_time":"10:20"},{"value":0,"end_time":"11:00","start_time":"10:40"},{"value":1,"end_time":"11:30","start_time":"11:00"},{"value":0,"end_time":"11:50","start_time":"11:30"},{"value":1,"end_time":"13:00","start_time":"11:50"}],"astro_clock":false,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' +// }, +// '3': { +// line: 3, +// tbname: 'vnmG4kJxaXWNBgMQq0D7Aj5e9oZzOAlr6LdR3w2V', +// contactor: 0, +// profile: '{"intervals":[{"value":0,"end_time":"20:30","start_time":"13:00"},{"value":1,"end_time":"00:10","start_time":"20:30"},{"value":0,"end_time":"13:00","start_time":"05:40"},{"value":1,"end_time":"05:40","start_time":"00:10"}],"astro_clock":true,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' +// } +// } + + + + + +// { +// "jbN4q7JPZmexgdnz2yKbWGDYAWwO0Q3BMX6ERLoV": [ +// { +// "ts": 1700409326353, +// "values": { +// "_event": { +// "type": "notice", +// "status": "new", +// "source": { +// "func": "rsPort.open()", +// "component": "1700343402190", +// "component_name": "DIDO_Controller", +// "edge": "jbN4q7JPZmexgdnz2yKbWGDYAWwO0Q3BMX6ERLoV" +// }, +// "message": "al_shariff_10.0.0.38: FLOW has been started ", +// "message_data": "" +// } +// } +// } +// ] +// } diff --git a/RVO3/flow/helper/DataToTbHandler.js b/RVO3/flow/helper/DataToTbHandler.js new file mode 100755 index 0000000..716ef7b --- /dev/null +++ b/RVO3/flow/helper/DataToTbHandler.js @@ -0,0 +1,187 @@ +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; + this.itIsNodeReadout = false; + this.sender = ""; + + // if attribute change difference is less than limit value, we do not send to tb. + this.attributeChangeLimit = { + temperature: 0.5, + Phase_1_voltage: 2, + Phase_2_voltage: 2, + Phase_3_voltage: 2, + Phase_1_current: 0.1, + Phase_2_current: 0.1, + Phase_3_current: 0.1, + Phase_1_power: 2, + Phase_2_power: 2, + Phase_3_power: 2, + total_power: 2, + total_energy: 1, + Phase_1_pow_factor: 0.1, + Phase_2_pow_factor: 0.1, + Phase_3_pow_factor: 0.1, + power_factor: 0.1, + lifetime: 2, + voltage: 2, + power: 2, + frequency: 3, + energy: 0.1, + current: 2, + inclination_x: 10, + inclination_y: 10, + inclination_z: 10 + }; + + } + + dump() { + console.log("----------------------------"); + console.log("previousValues", this.previousValues); + console.log("----------------------------"); + } + + setSender(sender) { + this.sender = sender; + } + + isEmptyObject(obj) { + for (var _ in obj) { + return false; + } + return true; + } + + + sendToTb(data, instance) { + + //not to modify data object, we do deep copy: + let dataCopy = JSON.parse(JSON.stringify(data)); + + let keys = Object.keys(dataCopy); + + if (keys.length == 0) { + if (this.debug) console.log("sendToTb received empty object", dataCopy); + return; + } + + let tbname = keys[0]; + let ts; + + let arrayOfValues = dataCopy[tbname]; + let arrayOfValuesToSend = []; + + for (let i = 0; i < arrayOfValues.length; i++) { + + ts = arrayOfValues[i].ts; + let values = this.prepareValuesForTb(tbname, ts, arrayOfValues[i].values); + + if (!this.isEmptyObject(values)) { + arrayOfValuesToSend.push({ ts: ts, values: values }); + } + + } + + if (arrayOfValuesToSend.length == 0) { + //if(this.debug) console.log("data not sent - empty array"); + return; + } + + this.messageCounter++; + + let dataToTbModified = { + [tbname]: arrayOfValuesToSend + } + + //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); + instance.send(this.index, dataToTbModified); + } + + + getDiffTimestamp(key) { + //TODO set different value for given key!!! + //if(key == "status") this.timeToHoldTbValue = 2*60*60;//2h + return this.timeToHoldTbValue * 1000; + } + + + prepareValuesForTb(tbname, timestamp, values) { + + let keys = Object.keys(values); + + if (keys.includes("lifetime")) this.itIsNodeReadout = true; + + if (!this.previousValues.hasOwnProperty(tbname)) { + this.previousValues[tbname] = {}; + } + + //if(this.debug) console.log("prepareValuesForTb", tbname, timestamp, values); + + for (let i = 0; i < keys.length; i++) { + + let key = keys[i]; + let value = values[key]; + + if (!this.previousValues[tbname].hasOwnProperty(key)) { + this.previousValues[tbname][key] = { ts: timestamp, value: value }; + continue; + } + + // attributeData ==> {voltage: {ts:333333, value:5}} + let attributeData = this.previousValues[tbname][key]; + let attributeToChange = false; + if (key in this.attributeChangeLimit) attributeToChange = true; + let limit = this.attributeChangeLimit[key]; + let timestampDiffToRemoveKey; + + //this will ensure "node statecode" will be sent just once an hour + if (this.itIsNodeReadout && key === "statecode") { + attributeData.value = value; + this.itIsNodeReadout = false; + timestampDiffToRemoveKey = 1 * 60 * 60 * 1000; // 1 hour + } + + if (key === "twilight_sensor" && value > 100) { + attributeData.value = value; + } + + //if edge, master or node version do not change, send just once a day: + if (["edge_fw_version", "master_node_version", "fw_version"].includes(key)) { + timestampDiffToRemoveKey = 24 * 60 * 60 * 1000; + } + + if (attributeData.value === value || attributeToChange && Math.abs(attributeData.value - value) < limit) { + + let diff = timestamp - attributeData.ts; + if (!timestampDiffToRemoveKey) timestampDiffToRemoveKey = this.getDiffTimestamp(key); + + if (diff > timestampDiffToRemoveKey) { + attributeData.ts = Date.now(); + //if(this.debug) console.log(this.sender + ": update ts for key", key, "diff is", diff, "messageCounter", this.messageCounter); + } + else { + delete values[key]; + //if(this.debug) console.log(this.sender + ": delete key", key, "diff is", diff, "messageCounter", this.messageCounter, timestampDiffToRemoveKey); + } + } + else { + attributeData.value = value; + attributeData.ts = timestamp; + } + + } + + return values; + } +} + +module.exports = DataToTbHandler; + diff --git a/RVO3/flow/helper/ErrorToServiceHandler.js b/RVO3/flow/helper/ErrorToServiceHandler.js new file mode 100755 index 0000000..2b27c32 --- /dev/null +++ b/RVO3/flow/helper/ErrorToServiceHandler.js @@ -0,0 +1,91 @@ +const { MD5 } = require('./md5.js'); +const { networkInterfaces } = require('os'); + +class ErrorToServiceHandler { + constructor() { + this.previousValues = {}; + + this.project_id = undefined; + + const nets = networkInterfaces(); + this.ipAddresses = {}; + + for (const name of Object.keys(nets)) { + for (const net of nets[name]) { + // Skip over non-IPv4 and internal (i.e. 127.0.0.1) addresses + if (net.family === 'IPv4' && !net.internal) { + if (!this.ipAddresses[name]) { + this.ipAddresses[name] = []; + } + this.ipAddresses[name].push(net.address); + } + } + } + } + + setProjectId(project_id) { + this.project_id = project_id; + } + + processMessage(message, seconds) { + if (Array.isArray(message)) message = message.join(', '); + + let key = MD5(message); + let ts = Date.now(); + + //keep in memory - default value is 1h + if (seconds === undefined) seconds = 60 * 60; + + if (!this.previousValues.hasOwnProperty(key)) { + this.previousValues[key] = { ts: ts, duration: seconds }; + } + + let diff = (ts - this.previousValues[key].ts); + if (diff < this.previousValues[key].duration * 1000) return false; + + this.previousValues[key].ts = ts; + + return message; + } + + sendMessageToService(message, seconds, message_type) { + + // if error occures too early FLOW.GLOBALS.settings.project_id is still undefined + if (this.project_id === undefined) { + console.log("ErrorToServiceHandler.js: no project_id"); + return; + } + + let f = this.processMessage(message, seconds); + if (f === false) return; + + if (message_type === undefined) message_type = "error_message"; + + let toService = { + id: this.project_id, + ipAddresses: this.ipAddresses + }; + + //js_error || error_message + toService[message_type] = message; + + console.log("ErrorToServiceHandler------------------------>send to service", toService); + + RESTBuilder.make(function(builder) { + builder.method('POST'); + builder.post(toService); + builder.url('http://192.168.252.2:8004/sentmessage'); + + builder.callback(function(err, response, output) { + console.log("process.on error send", err, response, output, toService); + }); + }); + + } +} + +const errorHandler = new ErrorToServiceHandler(); + + +module.exports = errorHandler; +//module.exports = ErrorToServiceHandler; diff --git a/RVO3/flow/helper/db_helper.js b/RVO3/flow/helper/db_helper.js new file mode 100755 index 0000000..40e796c --- /dev/null +++ b/RVO3/flow/helper/db_helper.js @@ -0,0 +1,44 @@ +function promisifyBuilder(builder) +{ + return new Promise((resolve, reject) => { + + try{ + + builder.callback(function(err, response) { + + if(err != null) reject(err); + resolve(response); + }); + + } catch (error) { + reject(error); + } + }) +} + +function makeMapFromDbResult(response, ...keys) +{ + let s = "-"; + let data = {}; + + for(let i = 0; i < response.length; i++) + { + let record = response[i]; + + let k = []; + for(let j = 0; j < keys.length; j++) + { + k.push( record[keys[j]] ); + } + + let key = k.join(s); + data[ key ] = record; + } + + return data; +} + +module.exports = { + promisifyBuilder, + makeMapFromDbResult + } \ No newline at end of file diff --git a/RVO3/flow/helper/logger.js b/RVO3/flow/helper/logger.js new file mode 100755 index 0000000..2585639 --- /dev/null +++ b/RVO3/flow/helper/logger.js @@ -0,0 +1,30 @@ +//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/RVO3/flow/helper/md5.js b/RVO3/flow/helper/md5.js new file mode 100755 index 0000000..d3b0480 --- /dev/null +++ b/RVO3/flow/helper/md5.js @@ -0,0 +1,5 @@ +function MD5(d){var r = M(V(Y(X(d),8*d.length)));return r.toLowerCase()};function M(d){for(var _,m="0123456789ABCDEF",f="",r=0;r>>4&15)+m.charAt(15&_);return f}function X(d){for(var _=Array(d.length>>2),m=0;m<_.length;m++)_[m]=0;for(m=0;m<8*d.length;m+=8)_[m>>5]|=(255&d.charCodeAt(m/8))<>5]>>>m%32&255);return _}function Y(d,_){d[_>>5]|=128<<_%32,d[14+(_+64>>>9<<4)]=_;for(var m=1732584193,f=-271733879,r=-1732584194,i=271733878,n=0;n>16)+(_>>16)+(m>>16)<<16|65535&m}function bit_rol(d,_){return d<<_|d>>>32-_} + +module.exports = { + MD5 +} \ No newline at end of file diff --git a/RVO3/flow/helper/notification_reporter.js b/RVO3/flow/helper/notification_reporter.js new file mode 100755 index 0000000..839c12c --- /dev/null +++ b/RVO3/flow/helper/notification_reporter.js @@ -0,0 +1,121 @@ +//key is device, value = message {} +let sentValues = {}; +let notificationsData = null; +let rvoName; + +//sendNotification("CMD Manager: process cmd", SETTINGS.rvoTbName, "dimming_profile_was_successfully_received_by_node", { node: node }, "", SEND_TO.tb, instance); + +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 +}; + +function getKey(map, val) { + return Object.keys(map).findItem(key => map[key] === val); +} + +//https://stackoverflow.com/questions/41117799/string-interpolation-on-variable +var template = (tpl, args) => tpl.replace(/\${(\w+)}/g, (_, v) => args[v]); + + +function initNotification() { + notificationsData = FLOW.GLOBALS.notificationsData; + rvoName = FLOW.GLOBALS.settings.rvo_name; +} + + +function sendNotification(func, device, key, params, extra, tb_output, instance, saveKey) { + + let storeToSendValues = true; + if (saveKey == undefined) storeToSendValues = false; + + let weight = ""; + let message = {}; + + let notification = notificationsData[key]; + + if (notification) { + weight = notification.weight.toLowerCase(); + + Object.keys(notification).forEach(item => { + if (["en", "sk", "de", "cz", "it", "es"].includes(item)) { + message[item] = rvoName + ": " + template(notification[item], params); + } + }) + } + else { + //console.error("sendNotification: Notifications: undefined key", key, func, notificationsData); + console.error("sendNotification: Notifications: undefined key", key, func); + return false; + } + + //detect invalid err weight + if (getKey(ERRWEIGHT, weight) == undefined) { + console.error("sendNotification: Notifications: undefined weight", weight, key, func); + return false; + } + + if (sentValues.hasOwnProperty(saveKey)) { + if (JSON.stringify(sentValues[saveKey]) == JSON.stringify(message)) { + return false; + } + } + + if (sentValues[saveKey] == undefined) { + if (storeToSendValues) { + //do not send - flow is was started + sentValues[saveKey] = message; + return false; + } + } + + if (storeToSendValues) sentValues[saveKey] = message; + + let content = { + "type": weight, + "status": "new", + "source": { + "func": func, + "component": instance.id, + "component_name": instance.name, + "edge": device + }, + "message": message, + "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 + + return true; + +} + +module.exports = { + sendNotification, + ERRWEIGHT, + initNotification +} + diff --git a/RVO3/flow/helper/register.js b/RVO3/flow/helper/register.js new file mode 100755 index 0000000..fc1d008 --- /dev/null +++ b/RVO3/flow/helper/register.js @@ -0,0 +1,144 @@ +/* +0 - cislo registra / prikaz +1 - recepient - 0 = master, 1 = slave (slave je automaticky group a broadcast) +2 - r/rw - read/write +3- register name - nazov registra / prikazu (len pre info - zobrazenie v aplikacii) + +4,5,6,7, - jednotlive byte-y - nazov byte-u +4-7 - RES. a prazdny string "" sa nezobrazia!!! +*/ + +//124 zaznamov +const registers = [ + ["0","1","R","Status","","",""], + ["1","1","RW","Dimming","R-Channel ","G-Channel","B-Channel ","W - Channel"], + ["2","1","R","Device types","","",".",""], + ["3","1","RW","Group addresses 1-4","Groups Add. 4","Groups Add. 3","Groups Add. 2","Groups Add. 1"], + ["4","1","RW","Group addresses 5-8","Groups Add. 8","Groups Add. 7","Groups Add. 6","Groups Add. 5"], + ["5","1","RW","Serial number (MAC)","","","",""], + ["6","1","RW","Time of dusk","HH","MM","SS","EXTRA"], + ["7","1","RW","Time of dawn","HH","MM","SS","EXTRA"], + ["8","1","RW","Time Schedule settings","TBD","TBD","Movement sensor","Time Schedule"], + ["9","1","RW","TS1 Time point 1","HH","MM","SS","Ext. Device"], + ["10","1","RW","TS1 Time point 1 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["11","1","RW","TS1 Time point 2","HH","MM","SS","Ext. Device"], + ["12","1","RW","TS1 Time point 2 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["13","1","RW","TS1 Time point 3","HH","MM","SS","Ext. Device"], + ["14","1","RW","TS1 Time point 3 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["15","1","RW","TS1 Time point 4","HH","MM","SS","Ext. Device"], + ["16","1","RW","TS1 Time point 4 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["17","1","RW","TS1 Time point 5","HH","MM","SS","Ext. Device"], + ["18","1","RW","TS1 Time point 5 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["19","1","RW","TS1 Time point 6","HH","MM","SS","Ext. Device"], + ["20","1","RW","TS1 Time point 6 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["21","1","RW","TS1 Time point 7","HH","MM","SS","Ext. Device"], + ["22","1","RW","TS1 Time point 7 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["23","1","RW","TS1 Time point 8","HH","MM","SS","Ext. Device"], + ["24","1","RW","TS1 Time point 8 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["25","1","RW","TS1 Time point 9","HH","MM","SS","Ext. Device"], + ["26","1","RW","TS1 Time point 9 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["27","1","RW","TS1 Time point 10","HH","MM","SS","Ext. Device"], + ["28","1","RW","TS1 Time point 10 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["29","1","RW","TS1 Time point 11","HH","MM","SS","Ext. Device"], + ["30","1","RW","TS1 Time point 11 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["31","1","RW","TS1 Time point 12","HH","MM","SS","Ext. Device"], + ["32","1","RW","TS1 Time point 12 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["33","1","RW","TS1 Time point 13","HH","MM","SS","Ext. Device"], + ["34","1","RW","TS1 Time point 13 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["35","1","RW","TS1 Time point 14","HH","MM","SS","Ext. Device"], + ["36","1","RW","TS1 Time point 14 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["37","1","RW","TS1 Time point 15","HH","MM","SS","Ext. Device"], + ["38","1","RW","TS1 Time point 15 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["39","1","RW","TS1 Time point 16","HH","MM","SS","Ext. Device"], + ["40","1","RW","TS1 Time point 16 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["41","1","RW","TS2 Time point 1","HH","MM","SS","Ext. Device"], + ["42","1","RW","TS2 Time point 1 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["43","1","RW","TS2 Time point 2","HH","MM","SS","Ext. Device"], + ["44","1","RW","TS2 Time point 2 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["45","1","RW","TS2 Time point 3","HH","MM","SS","Ext. Device"], + ["46","1","RW","TS2 Time point 3 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["47","1","RW","TS2 Time point 4","HH","MM","SS","Ext. Device"], + ["48","1","RW","TS2 Time point 4 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["49","1","RW","TS2 Time point 5","HH","MM","SS","Ext. Device"], + ["50","1","RW","TS2 Time point 5 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["51","1","RW","TS2 Time point 6","HH","MM","SS","Ext. Device"], + ["52","1","RW","TS2 Time point 6 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["53","1","RW","TS2 Time point 7","HH","MM","SS","Ext. Device"], + ["54","1","RW","TS2 Time point 7 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["55","1","RW","TS2 Time point 8","HH","MM","SS","Ext. Device"], + ["56","1","RW","TS2 Time point 8 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["57","1","RW","TS2 Time point 9","HH","MM","SS","Ext. Device"], + ["58","1","RW","TS2 Time point 9 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["59","1","RW","TS2 Time point 10","HH","MM","SS","Ext. Device"], + ["60","1","RW","TS2 Time point 10 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["61","1","RW","TS2 Time point 11","HH","MM","SS","Ext. Device"], + ["62","1","RW","TS2 Time point 11 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["63","1","RW","TS2 Time point 12","HH","MM","SS","Ext. Device"], + ["64","1","RW","TS2 Time point 12 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["65","1","RW","TS2 Time point 13","HH","MM","SS","Ext. Device"], + ["66","1","RW","TS2 Time point 13 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["67","1","RW","TS2 Time point 14","HH","MM","SS","Ext. Device"], + ["68","1","RW","TS2 Time point 14 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["69","1","RW","TS2 Time point 15","HH","MM","SS","Ext. Device"], + ["70","1","RW","TS2 Time point 15 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["71","1","RW","TS2 Time point 16","HH","MM","SS","Ext. Device"], + ["72","1","RW","TS2 Time point 16 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["73","1","RW","Power meter status","TBD","","",""], + ["74","1","R","Input Voltage","","","",""], + ["75","1","R","Input Current","","","",""], + ["76","1","R","Input Power","","","",""], + ["77","1","R","Cos phi","","","",""], + ["78","1","R","Frequency","","","",""], + ["79","1","RW","Energy","","","",""], + ["80","1","RW","Lifetime","","","",""], + ["81","1","RW","Power on cycles (input)","","","",""], + ["82","1","RW","Power on cycles (relay)","","","",""], + ["83","1","R","Time since last power on","","","",""], + ["84","1","R","Accelerometer data","","","",""], + ["85","1","RW","GPS latitude","pos/neg","deg","min ","sec"], + ["86","1","RW","GPS longitude","pos/neg","deg","min ","sec"], + ["87","1","RW","Actual time","HH","MM","SS","RES."], + ["88","1","RW","Actual date","Day of week","Day","Month","Year"], + ["89","1","R","Production data 1","","","",""], + ["90","1","R","Production data 2","","","",""], + ["91","1","RW","Network ID","NID3","NID2","NID1","NID0"], + ["95","1","RW","Actual Lux level from cabinet","RES.","RES.","HB","LB"], + ["96","1","RW","Threshold lux level","Dusk HB","Dusk LB","Dawn HB","Dawn LB"], + ["97","1","RW","Adjust period","Dusk HB","Dusk LB","Dawn HB","Dawn LB"], + ["98","1","RW","Offset","RES.","RES.","Dusk","Dawn"], + ["99","1","RW","CCT min/max range","max-H","max-L","min-H","min-L"], + ["100","1","RW","DALI interface","Cmd ID","Add","Cmd","Resp"], + ["101","1","RW","Module FW ver","v1","v2","v3","v4"], + ["102","1","RW","Module MAC-H","unused","unused","M1","M2"], + ["103","1","RW","Module MAC-L","M3","M4","M5","M6"], + ["122","1","R","FW update status/control register","Byte3","Byte2","Byte1","Byte0"], + ["123","1","R","FW update - data index","Byte3","Byte2","Byte1","Byte0"], + ["124","1","R","FW update - data","Byte3","Byte2","Byte1","Byte0"], + ["0","0","R","Status","","","",""], + ["1","0","RW","Control register","RES.","RES.","RES.","init mode enable"], + ["2","0","R","Device types","","","",""], + ["3","0","R","Serial number (MAC)","","","",""], + ["4","0","R","Production data 1","","","",""], + ["5","0","R","Production data 2","","","",""], + ["6","0","RW","Network ID","NID3","NID2","NID1","NID0"], + ["7","0","RW","RS232 settings","param.","param.","Baudrate H","Baudrate L"], + ["8","0","R","Accelerometer data","","","",""], + ["9","0","RW","Module FW ver","v1","v2","v3","v4"], + ["10","0","RW","Module MAC-H","unused","unused","M1","M2"], + ["11","0","RW","Module MAC-L","M3","M4","M5","M6"], + ["32","0","RW","FW update status/control register","Byte3","Byte2","Byte1","Byte0"], + ["33","0","RW","FW update - data index","Byte3","Byte2","Byte1","Byte0"], + ["34","0","RW","FW update - data","Byte3","Byte2","Byte1","Byte0"], + ["125","0","RW","Debug Register","Byte3","Byte2","Byte1","Byte0"], + ["126","0","RW","Network Control Register","Byte3","Byte2","Byte1","Byte0"], + ["127","0","R","Network Status Register","Byte3","Byte2","Byte1","Byte0"], + ["128","0","RW","Node XX Serial Number Register","SER3","SER2","SER1","SER0"], + ["256","0","R","Node XX Network Status Register","","","",""] +]; + +let register = {}; + +module.exports = { + registers, + register +} \ No newline at end of file diff --git a/RVO3/flow/helper/serialport_helper.js b/RVO3/flow/helper/serialport_helper.js new file mode 100755 index 0000000..7f5920d --- /dev/null +++ b/RVO3/flow/helper/serialport_helper.js @@ -0,0 +1,99 @@ +const { exec } = require('child_process'); + +function openPort(port) { + return new Promise((resolve, reject) => { + + var callbackError = function(err) { + port.removeListener('error', callbackError); + port.removeListener('open', callbackError); + + reject(err.message); + }; + + var callbackOpen = function(data) { + port.removeListener('error', callbackError); + port.removeListener('open', callbackOpen); + + resolve("port open: ok"); + }; + + port.on('error', callbackError); + port.on('open', callbackOpen); + + port.open(); + + }) +} + +function runSyncExec(command) { + return new Promise((resolve, reject) => { + + exec(command, (error, stdout, stderr) => { + if (error == null) resolve(stdout); + reject(error); + }); + + }) +} + +async function writeData(port, data, readbytes, timeout) { + return new Promise((resolve, reject) => { + + // 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) { + + port.write(Buffer.from(data), function(err) { + if (err) { + reject(err.message); + } + }); + + 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 +} diff --git a/RVO3/flow/helper/suncalc.js b/RVO3/flow/helper/suncalc.js new file mode 100755 index 0000000..c9ca56d --- /dev/null +++ b/RVO3/flow/helper/suncalc.js @@ -0,0 +1,317 @@ +/* + (c) 2011-2015, Vladimir Agafonkin + SunCalc is a JavaScript library for calculating sun/moon position and light phases. + https://github.com/mourner/suncalc +*/ + +(function () { 'use strict'; + +// shortcuts for easier to read formulas + +var PI = Math.PI, + sin = Math.sin, + cos = Math.cos, + tan = Math.tan, + asin = Math.asin, + atan = Math.atan2, + acos = Math.acos, + rad = PI / 180; + +// sun calculations are based on http://aa.quae.nl/en/reken/zonpositie.html formulas + + +// date/time constants and conversions + +var dayMs = 1000 * 60 * 60 * 24, + J1970 = 2440588, + J2000 = 2451545; + +function toJulian(date) { return date.valueOf() / dayMs - 0.5 + J1970; } +function fromJulian(j) { return new Date((j + 0.5 - J1970) * dayMs); } +function toDays(date) { return toJulian(date) - J2000; } + + +// general calculations for position + +var e = rad * 23.4397; // obliquity of the Earth + +function rightAscension(l, b) { return atan(sin(l) * cos(e) - tan(b) * sin(e), cos(l)); } +function declination(l, b) { return asin(sin(b) * cos(e) + cos(b) * sin(e) * sin(l)); } + +function azimuth(H, phi, dec) { return atan(sin(H), cos(H) * sin(phi) - tan(dec) * cos(phi)); } +function altitude(H, phi, dec) { return asin(sin(phi) * sin(dec) + cos(phi) * cos(dec) * cos(H)); } + +function siderealTime(d, lw) { return rad * (280.16 + 360.9856235 * d) - lw; } + +function astroRefraction(h) { + if (h < 0) // the following formula works for positive altitudes only. + h = 0; // if h = -0.08901179 a div/0 would occur. + + // formula 16.4 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + // 1.02 / tan(h + 10.26 / (h + 5.10)) h in degrees, result in arc minutes -> converted to rad: + return 0.0002967 / Math.tan(h + 0.00312536 / (h + 0.08901179)); +} + +// general sun calculations + +function solarMeanAnomaly(d) { return rad * (357.5291 + 0.98560028 * d); } + +function eclipticLongitude(M) { + + var C = rad * (1.9148 * sin(M) + 0.02 * sin(2 * M) + 0.0003 * sin(3 * M)), // equation of center + P = rad * 102.9372; // perihelion of the Earth + + return M + C + P + PI; +} + +function sunCoords(d) { + + var M = solarMeanAnomaly(d), + L = eclipticLongitude(M); + + return { + dec: declination(L, 0), + ra: rightAscension(L, 0) + }; +} + + +var SunCalc = {}; + + +// calculates sun position for a given date and latitude/longitude + +SunCalc.getPosition = function (date, lat, lng) { + + var lw = rad * -lng, + phi = rad * lat, + d = toDays(date), + + c = sunCoords(d), + H = siderealTime(d, lw) - c.ra; + + return { + azimuth: azimuth(H, phi, c.dec), + altitude: altitude(H, phi, c.dec) + }; +}; + + +// sun times configuration (angle, morning name, evening name) + +var times = SunCalc.times = [ + [-0.833, 'sunrise', 'sunset' ], + [ -0.3, 'sunriseEnd', 'sunsetStart' ], + [ -6, 'dawn', 'dusk' ], + [ -12, 'nauticalDawn', 'nauticalDusk'], + [ -18, 'nightEnd', 'night' ], + [ 6, 'goldenHourEnd', 'goldenHour' ] +]; + +// adds a custom time to the times config + +SunCalc.addTime = function (angle, riseName, setName) { + times.push([angle, riseName, setName]); +}; + + +// calculations for sun times + +var J0 = 0.0009; + +function julianCycle(d, lw) { return Math.round(d - J0 - lw / (2 * PI)); } + +function approxTransit(Ht, lw, n) { return J0 + (Ht + lw) / (2 * PI) + n; } +function solarTransitJ(ds, M, L) { return J2000 + ds + 0.0053 * sin(M) - 0.0069 * sin(2 * L); } + +function hourAngle(h, phi, d) { return acos((sin(h) - sin(phi) * sin(d)) / (cos(phi) * cos(d))); } +function observerAngle(height) { return -2.076 * Math.sqrt(height) / 60; } + +// returns set time for the given sun altitude +function getSetJ(h, lw, phi, dec, n, M, L) { + + var w = hourAngle(h, phi, dec), + a = approxTransit(w, lw, n); + return solarTransitJ(a, M, L); +} + + +// calculates sun times for a given date, latitude/longitude, and, optionally, +// the observer height (in meters) relative to the horizon + +SunCalc.getTimes = function (date, lat, lng, height) { + + height = height || 0; + + var lw = rad * -lng, + phi = rad * lat, + + dh = observerAngle(height), + + d = toDays(date), + n = julianCycle(d, lw), + ds = approxTransit(0, lw, n), + + M = solarMeanAnomaly(ds), + L = eclipticLongitude(M), + dec = declination(L, 0), + + Jnoon = solarTransitJ(ds, M, L), + + i, len, time, h0, Jset, Jrise; + + + var result = { + solarNoon: fromJulian(Jnoon), + nadir: fromJulian(Jnoon - 0.5) + }; + + for (i = 0, len = times.length; i < len; i += 1) { + time = times[i]; + h0 = (time[0] + dh) * rad; + + Jset = getSetJ(h0, lw, phi, dec, n, M, L); + Jrise = Jnoon - (Jset - Jnoon); + + result[time[1]] = fromJulian(Jrise); + result[time[2]] = fromJulian(Jset); + } + + return result; +}; + + +// moon calculations, based on http://aa.quae.nl/en/reken/hemelpositie.html formulas + +function moonCoords(d) { // geocentric ecliptic coordinates of the moon + + var L = rad * (218.316 + 13.176396 * d), // ecliptic longitude + M = rad * (134.963 + 13.064993 * d), // mean anomaly + F = rad * (93.272 + 13.229350 * d), // mean distance + + l = L + rad * 6.289 * sin(M), // longitude + b = rad * 5.128 * sin(F), // latitude + dt = 385001 - 20905 * cos(M); // distance to the moon in km + + return { + ra: rightAscension(l, b), + dec: declination(l, b), + dist: dt + }; +} + +SunCalc.getMoonPosition = function (date, lat, lng) { + + var lw = rad * -lng, + phi = rad * lat, + d = toDays(date), + + c = moonCoords(d), + H = siderealTime(d, lw) - c.ra, + h = altitude(H, phi, c.dec), + // formula 14.1 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + pa = atan(sin(H), tan(phi) * cos(c.dec) - sin(c.dec) * cos(H)); + + h = h + astroRefraction(h); // altitude correction for refraction + + return { + azimuth: azimuth(H, phi, c.dec), + altitude: h, + distance: c.dist, + parallacticAngle: pa + }; +}; + + +// calculations for illumination parameters of the moon, +// based on http://idlastro.gsfc.nasa.gov/ftp/pro/astro/mphase.pro formulas and +// Chapter 48 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + +SunCalc.getMoonIllumination = function (date) { + + var d = toDays(date || new Date()), + s = sunCoords(d), + m = moonCoords(d), + + sdist = 149598000, // distance from Earth to Sun in km + + phi = acos(sin(s.dec) * sin(m.dec) + cos(s.dec) * cos(m.dec) * cos(s.ra - m.ra)), + inc = atan(sdist * sin(phi), m.dist - sdist * cos(phi)), + angle = atan(cos(s.dec) * sin(s.ra - m.ra), sin(s.dec) * cos(m.dec) - + cos(s.dec) * sin(m.dec) * cos(s.ra - m.ra)); + + return { + fraction: (1 + cos(inc)) / 2, + phase: 0.5 + 0.5 * inc * (angle < 0 ? -1 : 1) / Math.PI, + angle: angle + }; +}; + + +function hoursLater(date, h) { + return new Date(date.valueOf() + h * dayMs / 24); +} + +// calculations for moon rise/set times are based on http://www.stargazing.net/kepler/moonrise.html article + +SunCalc.getMoonTimes = function (date, lat, lng, inUTC) { + var t = new Date(date); + if (inUTC) t.setUTCHours(0, 0, 0, 0); + else t.setHours(0, 0, 0, 0); + + var hc = 0.133 * rad, + h0 = SunCalc.getMoonPosition(t, lat, lng).altitude - hc, + h1, h2, rise, set, a, b, xe, ye, d, roots, x1, x2, dx; + + // go in 2-hour chunks, each time seeing if a 3-point quadratic curve crosses zero (which means rise or set) + for (var i = 1; i <= 24; i += 2) { + h1 = SunCalc.getMoonPosition(hoursLater(t, i), lat, lng).altitude - hc; + h2 = SunCalc.getMoonPosition(hoursLater(t, i + 1), lat, lng).altitude - hc; + + a = (h0 + h2) / 2 - h1; + b = (h2 - h0) / 2; + xe = -b / (2 * a); + ye = (a * xe + b) * xe + h1; + d = b * b - 4 * a * h1; + roots = 0; + + if (d >= 0) { + dx = Math.sqrt(d) / (Math.abs(a) * 2); + x1 = xe - dx; + x2 = xe + dx; + if (Math.abs(x1) <= 1) roots++; + if (Math.abs(x2) <= 1) roots++; + if (x1 < -1) x1 = x2; + } + + if (roots === 1) { + if (h0 < 0) rise = i + x1; + else set = i + x1; + + } else if (roots === 2) { + rise = i + (ye < 0 ? x2 : x1); + set = i + (ye < 0 ? x1 : x2); + } + + if (rise && set) break; + + h0 = h2; + } + + var result = {}; + + if (rise) result.rise = hoursLater(t, rise); + if (set) result.set = hoursLater(t, set); + + if (!rise && !set) result[ye > 0 ? 'alwaysUp' : 'alwaysDown'] = true; + + return result; +}; + + +// export as Node module / AMD module / browser variable +if (typeof exports === 'object' && typeof module !== 'undefined') module.exports = SunCalc; +else if (typeof define === 'function' && define.amd) define(SunCalc); +else window.SunCalc = SunCalc; + +}()); diff --git a/RVO3/flow/helper/utils.js b/RVO3/flow/helper/utils.js new file mode 100755 index 0000000..dbffe45 --- /dev/null +++ b/RVO3/flow/helper/utils.js @@ -0,0 +1,161 @@ +const fs = require('fs').promises; + +function bytesToInt(bytes, numberOfBytes) { + let buffer = []; + if (Array.isArray(bytes)) { + buffer = bytes.slice(0); + if (numberOfBytes != undefined) { + buffer = bytes.slice(bytes.length - numberOfBytes); + } + } + else buffer.push(bytes); + + let result = 0; + for (let i = 0; i < buffer.length; i++) { + result = (result << 8) | buffer[i]; + } + + return result >>> 0; //ensure it's an unsigned 32-bit number +} + +function resizeArray(arr, newSize, defaultValue) { + while (newSize > arr.length) + arr.push(defaultValue); + arr.length = newSize; +} + +longToByteArray = function(/*long*/long) { + // we want to represent the input as a 8-bytes array + var byteArray = [0, 0, 0, 0, 0, 0, 0, 0]; + + for (var index = 0; index < byteArray.length; index++) { + var byte = long & 0xff; + byteArray[index] = byte; + long = (long - byte) / 256; + } + + return byteArray; +}; + +function addDays(date, days) { + var result = new Date(date); + result.setDate(result.getDate() + days); + return result; +} + +/* +sleep(2000).then(() => { + // Do something after the sleep! + + +}); +*/ + +function sleep(time) { + return new Promise((resolve) => setTimeout(resolve, time)); +} + +function isEmptyObject(obj) { + for (var name in obj) { + return false; + } + return true; +} + +function emptyJsObject(jsObject) { + Object.keys(jsObject).forEach(key => delete jsObject[key]); +} + +function convertUTCDateToLocalDate(date) { + var newDate = new Date(date); + newDate.setMinutes(date.getMinutes() + date.getTimezoneOffset()); + return newDate; +} + +function addZeroBefore(n) { + return (n < 10 ? '0' : '') + n; +} + + +/** + * Asynchronously writes data to a file. + * + * @param {string} filePath The path to the file. + * @param {string} data The data to write to the file. + * @param {boolean} [append=false] If true, appends the data to the file. If false, it overwrites the file. + */ +async function writeToFile(filePath, data, append = false) { + if (typeof data !== 'string') data = JSON.stringify(data, null, 2); + try { + if (append) { + // Append the data to the end of the file. This is the simplest way to append. + await fs.appendFile(filePath, data, 'utf8'); + console.log(`Successfully appended data to ${filePath} using fs.appendFile.`); + } else { + // Overwrite the file with the new data. + await fs.writeFile(filePath, data, 'utf8'); + console.log(`Successfully wrote (overwrote) data to ${filePath} using fs.writeFile.`); + } + } catch (error) { + console.error(`Error writing to file ${filePath}:`, error); + } +} + + + /** + * Checks if an item is present in an array and adds it if it's not. + * * @param {Array} arr The array to check. + * @param {*} item The item to add. + * @returns {Array} The modified array. + */ +const addToArrayIfUnique = (arr, item) => { + if (!arr.includes(item)) { + arr.push(item); + } + return arr; +}; + + +var convertBase = function() { + + function convertBase(baseFrom, baseTo) { + return function(num) { + return parseInt(num, baseFrom).toString(baseTo); + + }; + } + + // binary to decimal + convertBase.bin2dec = convertBase(2, 10); + + // binary to hexadecimal + convertBase.bin2hex = convertBase(2, 16); + + // decimal to binary + convertBase.dec2bin = convertBase(10, 2); + + // decimal to hexadecimal + convertBase.dec2hex = convertBase(10, 16); + + // hexadecimal to binary + convertBase.hex2bin = convertBase(16, 2); + + // hexadecimal to decimal + convertBase.hex2dec = convertBase(16, 10); + + return convertBase; +}(); + +module.exports = { + bytesToInt, + longToByteArray, + addDays, + addZeroBefore, + resizeArray, + isEmptyObject, + emptyJsObject, + sleep, + convertUTCDateToLocalDate, + writeToFile, + addToArrayIfUnique +} diff --git a/RVO3/flow/httprequest.js b/RVO3/flow/httprequest.js new file mode 100755 index 0000000..469c8cb --- /dev/null +++ b/RVO3/flow/httprequest.js @@ -0,0 +1,137 @@ +exports.id = 'httprequest'; +exports.title = 'HTTP Request'; +exports.group = 'HTTP'; +exports.color = '#5D9CEC'; +exports.input = true; +exports.version = '2.0.1'; +exports.output = 1; +exports.author = 'Peter Širka'; +exports.icon = 'cloud-upload'; + +exports.html = `
+
@(URL address)
+
+
+
@(HTTP method)
+
+
+
@(Serialization)
+
+
+
@(Download the content in chunks)
+
@(Keep persistent cookies)
+
@(Disable DNS cache)
+
@(Keep alive connection)
+
+
+
+
@(Custom headers)
+
@(Cookies)
+
+
+
+ +
+
+
+
@(User)
+
+
+
@(Password)
+
+
+
+
+
`; + +exports.readme = `# Request + +This component creates a request with received data. + +__Response:__ +\`\`\`javascript +{ + data: String, + headers: Object, + status: Number, + host: String +} +\`\`\` + +__Dynamic arguments__: +Are performed via FlowData repository and can be used for URL address or for custom headers/cookies/auth. Use \`repository\` component for creating of dynamic arguments. Dynamic values are replaced in the form \`{key}\`: + +- url address e.g. \`https://.../{key}/\` +- headers values e.g. \`{token}\` +- cookies values e.g. \`{token}\``; + +exports.install = function(instance) { + + var can = false; + var flags = null; + var cookies2 = null; + + instance.on('data', function(response) { + can && instance.custom.send(response); + }); + + instance.custom.send = function(response) { + var options = instance.options; + + var headers = null; + var cookies = null; + + options.headers && Object.keys(options.headers).forEach(function(key) { + !headers && (headers = {}); + headers[key] = response.arg(options.headers[key]); + }); + + if (options.username && options.userpassword) { + !headers && (headers = {}); + headers['Authorization'] = 'Basic ' + U.createBuffer(response.arg(options.username + ':' + options.userpassword)).toString('base64'); + } + + options.cookies && Object.keys(options.cookies).forEach(function(key) { + !cookies && (cookies = {}); + cookies[key] = response.arg(options.cookies[key]); + }); + + if (options.chunks) { + U.download(response.arg(options.url), flags, options.stringify === 'none' ? null : response.data, function(err, response) { + response.on('data', (chunks) => instance.send2(chunks)); + }, cookies || cookies2, headers); + } else { + U.request(response.arg(options.url), flags, options.stringify === 'none' ? null : response.data, 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) + instance.error(err, response); + }, cookies || cookies2, headers); + } + }; + + instance.reconfigure = function() { + var options = instance.options; + can = options.url && options.url && options.method && options.stringify ? true : false; + instance.status(can ? '' : 'Not configured', can ? undefined : 'red'); + + if (!can) + return; + + flags = []; + flags.push(options.method.toLowerCase()); + options.stringify === 'json' && flags.push('json'); + options.stringify === 'raw' && flags.push('raw'); + options.keepalive && flags.push('keepalive'); + !options.nodns && flags.push('dnscache'); + if (options.persistentcookies) { + flags.push('cookies'); + cookies2 = {}; + } else + cookies2 = null; + }; + + instance.on('options', instance.reconfigure); + instance.reconfigure(); +}; \ No newline at end of file diff --git a/RVO3/flow/httpresponse.js b/RVO3/flow/httpresponse.js new file mode 100755 index 0000000..160a3bb --- /dev/null +++ b/RVO3/flow/httpresponse.js @@ -0,0 +1,76 @@ +exports.id = 'httpresponse'; +exports.title = 'HTTP Response'; +exports.group = 'HTTP'; +exports.color = '#5D9CEC'; +exports.icon = 'arrow-right'; +exports.input = true; +exports.output = ['#666D76']; +exports.version = '2.0.0'; +exports.author = 'Martin Smola'; +exports.readme = `# HTTP response + +HTTP response will respond with data recieved using data-type set in Settings form or plain text if not set. Output is the message duration \`Number\` in seconds.`; + +exports.html = `
+
@(Response data-type)
+
JSON is by default.
+
`; + +exports.install = function(instance) { + + var dursum = 0; + var durcount = 0; + + instance.on('data', function(flowdata) { + + var ctrl = flowdata.repository.controller; + var data = flowdata.data; + + if (!ctrl) { + instance.throw('No controller to use for response!'); + return; + } + + durcount++; + dursum += ((new Date() - flowdata.begin) / 1000).floor(2); + setTimeout2(instance.id, instance.custom.duration, 500, 10); + + ctrl.$flowdata = flowdata; + + var datatype = instance.options.datatype || 'json'; + if (datatype === 'emptyresponse') + return ctrl.plain(''); + + if (datatype !== 'json' && typeof(data) !== 'string') { + instance.throw('Incorect type of data, expected string, got ' + typeof(data)); + ctrl.plain(data == null ? '' : data.toString()); + return; + } + + switch(datatype) { + case 'html': + ctrl.content(data, 'text/html'); + break; + case 'plain': + ctrl.plain(data); + break; + case 'xml': + ctrl.content(data, 'text/xml'); + break; + default: + ctrl.json(data); + break; + } + }); + + instance.on('service', function() { + dursum = 0; + durcount = 0; + }); + + instance.custom.duration = function() { + var avg = (dursum / durcount).floor(2); + instance.status(avg + ' sec.'); + instance.send2(0, avg); + }; +}; diff --git a/RVO3/flow/httproute.js b/RVO3/flow/httproute.js new file mode 100755 index 0000000..583a19d --- /dev/null +++ b/RVO3/flow/httproute.js @@ -0,0 +1,326 @@ +exports.id = 'httproute'; +exports.title = 'HTTP Route'; +exports.group = 'HTTP'; +exports.color = '#5D9CEC'; +exports.icon = 'globe'; +exports.input = false; +exports.output = ['#6CAC5A', '#37BC9B']; +exports.version = '1.2.3'; +exports.author = 'Martin Smola'; +exports.cloning = false; +exports.options = { method: 'GET', url: '', size: 5, cacheexpire: '5 minutes', cachepolicy: 0, timeout: 5 }; +exports.dateupdated = '2021-01-21 18:30d'; +exports.readme = `# HTTP route + +__Outputs__: +- first output: raw data (cache is empty or is disabled) +- second output: cached data + +If one of the outputs is disabled then automatic responce with code "503 service unavailable" is sent. + +When a request comes in bellow object is available at \`flowdata.data\`: + +\`\`\`javascript +{ + params: { id: '1' }, // params for dynamic routes, e.g. /test/{id} + query: { msg: 'Hello' }, // parsed query string, e.g. /test/1?msg=Hello + body: { test: 'OK' }, // object if json requests otherwise string + headers: {}, // headers data + session: {}, // session data + user: {}, // user data + files: [], // uploaded files + url: '/users/', // a relative URL address + referrer: '/', // referrer + mobile: false, // determines mobile device + robot: false, // determines search robots/crawlsers + language: 'en' // determines language +} +\`\`\` + +See [documentation for flags](https://docs.totaljs.com/latest/en.html#api~HttpRouteOptionsFlags~unauthorize). These method flags are set automatically e.g. \`get, post, put, patch or delete\` + +--- + +\`id:ROUTE_ID\` flag cannot be used since it's already used by this component internally`; + +exports.html = `
+
+ +
+ +
+
+
@(HTTP method)
+
+
+
@(URL address)
+
+
+
+
+
@(Additional flags)
+
@(Separate flags by comma e.g. json, authorize)
+
+
+
@(Max. request size)
+
@(In kB kilobytes)
+
+
+
@(Timeout)
+
@(In seconds.)
+
+
+
+
+
+
@(Automatically respond with 200 OK?)
+
@(If not checked you need to use HTTP response component to respond to the request.)
+
+
@(Custom headers)
+
@(Cookies)
+
+
+
+
+
+
@(Cache policy)
+
@(User instance must contain id property.)
+
+
+
@(Expiration)
+
@(E.g. 5 minutes)
+
+
+
+`; + +exports.install = function(instance) { + + var route; + + var uninstall = function(id) { + if (F.is4) { + route && route.remove(); + route = null; + } else + UNINSTALL('route', id); + }; + + instance.custom.emptyresponse = function(self) { + self.plain(); + }; + + instance.reconfigure = function() { + + var options = instance.options; + + if (!options.url) { + instance.status('Not configured', 'red'); + return; + } + + if (typeof(options.flags) === 'string') + options.flags = options.flags.split(',').trim(); + + uninstall('id:' + instance.id); + + var flags = options.flags || []; + + flags.push('id:' + instance.id); + + if (!F.is4) + flags.push(options.method.toLowerCase()); + + options.timeout && flags.push(options.timeout * 1000); + + // Make unique values + flags = flags.filter(function(v, i, a) { + if(F.is4 && v.toString().toLowerCase() === options.method.toLowerCase()) + return false; // remove method + return a.indexOf(v) === i; + }); + + options.flags = flags; + var handler = function() { + + if (instance.paused || (instance.isDisabled && (instance.isDisabled('output', 0) || instance.isDisabled('output', 1)))) { + instance.status('503 Service Unavailable'); + this.status = 503; + this.json(); + return; + } + + var key; + var self = this; + + if (instance.options.emptyresponse) { + instance.status('200 OK'); + setTimeout(instance.custom.emptyresponse, 100, self); + + if (instance.hasConnection(0)) { + var data = instance.make({ + query: self.query, + body: self.body, + session: self.session, + user: self.user, + files: self.files, + headers: self.req.headers, + url: self.url, + params: self.params + }); + instance.send2(0, data); + } + + return; + } + + switch (instance.options.cachepolicy) { + case 1: // URL + key = 'rro' + instance.id + self.url.hash(); + break; + case 2: // URL + query + case 3: // URL + query + user + key = self.url; + var keys = Object.keys(self.query); + keys.sort(); + for (var i = 0, length = keys.length; i < length; i++) + key += keys[i] + self.query[keys[i]] + '&'; + if (instance.options.cachepolicy === 3 && self.user) + key += 'iduser' + self.user.id; + key = 'rro' + instance.id + key.hash(); + break; + } + + if (key && F.cache.get2(key)) { + var data = instance.make(F.cache.get2(key)); + data.repository.controller = self; + instance.send2(1, data); + } else { + + var data = instance.make({ + query: self.query, + body: self.body, + session: self.session, + user: self.user, + files: self.files, + headers: self.req.headers, + url: self.url, + params: self.params, + mobile: self.mobile, + robot: self.robot, + referrer: self.referrer, + language: self.language + }); + + data.repository.controller = self; + instance.send2(0, data); + key && FINISHED(self.res, () => F.cache.set(key, self.$flowdata.data, instance.options.cacheexpire)); + } + }; + + if (F.is4) + route = ROUTE(options.method.toUpperCase() + ' ' + options.url, handler, flags, options.size || 5); + else + F.route(options.url, handler, flags, options.size || 5); + + instance.status('Listening', 'green'); + }; + + instance.reconfigure(); + instance.on('options', instance.reconfigure); + instance.on('close', function(){ + uninstall('id:' + instance.id); + }); +}; + +// check url exists +FLOW.trigger('httproutecheckurl', function(next, data) { + var url = data.url; + var method = data.method; + if (url[url.length - 1] !== '/') + url += '/'; + var exists = F.routes.web.findItem(r => r.urlraw === url && r.method === method); + next(exists != null); +}); + +exports.uninstall = function() { + FLOW.trigger('httproutecheckurl', null); +}; diff --git a/RVO3/flow/infosender.js b/RVO3/flow/infosender.js new file mode 100755 index 0000000..587724f --- /dev/null +++ b/RVO3/flow/infosender.js @@ -0,0 +1,81 @@ +exports.id = 'infosender'; +exports.title = 'Info sender'; +exports.version = '1.0.0'; +exports.group = 'Worksys'; +exports.color = '#2134B0'; +exports.input = 2; +exports.output = 1 +exports.icon = 'bolt'; + +const { networkInterfaces } = require('os'); + +exports.html = `
+
+
+
CSV Import
+
+
+
`; + +exports.readme = `# send all data to projects.worksys.io, required to monitor status of controller(unipi)`; + +exports.install = function(instance) { + + let id; + let allValues = {}; + let sendAllValuesInterval; + let configured = false; + + let now = new Date(); + console.log(exports.title, "INSTALLED", now.toLocaleString("sk-SK")); + + const nets = networkInterfaces(); + let ipAddresses = Object.create(null); // Or just '{}', an empty object + + for (const name of Object.keys(nets)) { + for (const net of nets[name]) { + // Skip over non-IPv4 and internal (i.e. 127.0.0.1) addresses + if (net.family === 'IPv4' && !net.internal) { + if (!ipAddresses[name]) { + ipAddresses[name] = []; + } + ipAddresses[name].push(net.address); + } + } + } + + function sendValues() { + if (!configured) return; + + if (Object.keys(allValues).length > 0) { + let dataToSend = { ...allValues }; + dataToSend.id = id; + dataToSend.ipAddresses = ipAddresses; + + instance.send(0, dataToSend); + + allValues = {}; + } + } + + instance.on("close", () => { + clearInterval(sendAllValuesInterval); + }) + + instance.on("0", _ => { + id = FLOW.GLOBALS.settings.project_id; + if (id) configured = true; + else console.log(exports.title, "InfoSender: Unable to send data, no id"); + }) + + instance.on("1", flowdata => { + allValues = { ...allValues, ...flowdata.data }; + //console.log("DATA RECEIVED", flowdata.data); + }) + + sendAllValuesInterval = setInterval(() => { + sendValues(); + }, 60000 * 3); + +} + diff --git a/RVO3/flow/modbus_reader.js b/RVO3/flow/modbus_reader.js new file mode 100755 index 0000000..d6d9dad --- /dev/null +++ b/RVO3/flow/modbus_reader.js @@ -0,0 +1,346 @@ +exports.id = 'modbus_reader'; +exports.title = 'Modbus reader'; +exports.version = '2.0.0'; +exports.group = 'Worksys'; +exports.color = '#2134B0'; +exports.input = 1; +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; +//number of phases inRVO +let phases; +//phases where voltage is 0 (set) +let noVoltage; +let energyToSwitchLamps; + +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.phases = this.buildPhases(); + + this.startSocket(); + } + + buildPhases = () => { + let a = []; + for (let i = 1; i <= phases; i++) { + a.push(`Phase_${i}_voltage`) + } + return a; + } + + startSocket = () => { + + let obj = this; + + if (this.socket) { + this.socket.removeAllListeners(); + this.socket = null; + } + + 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('Modbus_reader: Socket connection error', e); //'ECONNREFUSED' or 'ECONNRESET' ?? + }); + + this.socket.on('close', function() { + console.log('Modbus_reader: Socket connection closed - Waiting 10 seconds before connecting 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 we just start to loop devices from the beginning, or there is just 1 device in config, we wait whole timeoutInterval + if (this.indexInDeviceConfig == 0 || deviceConfig.length === 1) 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 (this.phases.includes(singleValue)) { + let l = singleValue.split("_"); + let phase = parseInt(l[1]); + + // console.log(values[singleValue], tbName); + + if (values[singleValue] == 0) { + noVoltage.add(phase); + sendNotification("modbus_reader: checkNullVoltage", tbName, "no_voltage_on_phase", { phase: phase }, "", SEND_TO.tb, instance, "voltage" + phase); + // console.log('no voltage') + } + else { + noVoltage.delete(phase); + // console.log('voltage detected') + sendNotification("modbus_reader: checkNullVoltage", tbName, "voltage_on_phase_restored", { phase: phase }, "", SEND_TO.tb, instance, "voltage" + phase); + } + } + }) + } + + /** + * function sends notification to slack and to tb, if EM total_power value changes more than numberOfNodes*15. This should show, that RVO lamps has been switched on or off + */ + lampSwitchNotification = (values) => { + + if (!values.hasOwnProperty("total_power")) return; + + const actualTotalPower = values.total_power; + + if (actualTotalPower > energyToSwitchLamps && 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 <= energyToSwitchLamps && 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; + } + + function main() { + + phases = FLOW.GLOBALS.settings.phases; + tbName = FLOW.GLOBALS.settings.rvoTbName; + noVoltage = FLOW.GLOBALS.settings.no_voltage; + energyToSwitchLamps = FLOW.GLOBALS.settings.energy_to_switch_lamps / 2.5; //half value is enought to show if lamps are turned on or off + if (deviceConfig.length) mainSocket = new SocketWithClients(); + else console.log("Modbus_reader: no modbus device in configuration"); + + // this notification is to show, that flow (unipi) has been restarted + sendNotification("modbus_reader", tbName, "flow_restart", {}, "", SEND_TO.slack, instance); + } + + instance.on("0", function(_) { + main(); + }) + +} + diff --git a/RVO3/flow/monitorconsumption.js b/RVO3/flow/monitorconsumption.js new file mode 100755 index 0000000..64cc58e --- /dev/null +++ b/RVO3/flow/monitorconsumption.js @@ -0,0 +1,156 @@ +exports.id = 'monitorconsumption'; +exports.title = 'Consumption'; +exports.version = '1.0.0'; +exports.author = 'Peter Širka'; +exports.group = 'Monitoring'; +exports.color = '#967ADC'; +exports.input = 0; +exports.output = 1; +exports.icon = 'bug'; +exports.options = { interval: 5000, enabled: true, monitorconsumption: true, monitorsize: true, monitorconnections: true, monitorfiles: true }; +exports.click = true; +exports.readme = `# Consumption monitoring + +This component measure CPU and memory consumption, open files and open connections of this application. It uses these Linux commands: \`ps\`, \`lsof\`, \`netstat\` and \`df\`. + +__Data Example__: + +\`\`\`javascript +{ + cpu: 0, // percentage + memory: 4096, // in bytes + size: 34303, // directory size in bytes + files: 34, // count of open files + connections: 343, // count of connections + uptime: '1-12:34:00' +} +\`\`\``; + +exports.html = `
+
+
+
@(Interval in milliseconds)
+
+
+
+
Monitor: Consumption + uptime
+
Monitor: Count of open files
+
Monitor: Count of open connections
+
Monitor: Directory size
+
`; + +exports.install = function(instance) { + + var current = { cpu: 0, memory: 0, files: 0, connections: 0, size: 0, uptime: '', counter: 0 }; + var tproc = null; + var Exec = require('child_process').exec; + var reg_empty = /\s{2,}/g; + var reg_appdisksize = /^[\d.,]+/; + + instance.custom.run = function() { + + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + + var arr = []; + + // Get CPU and Memory consumption + instance.options.monitorconsumption && arr.push(function(next) { + Exec('ps -p {0} -o %cpu,rss,etime'.format(process.pid), function(err, response) { + + if (err) { + instance.throw(err); + } else { + var line = response.split('\n')[1]; + line = line.trim().replace(reg_empty, ' ').split(' '); + var cpu = line[0].parseFloat(); + current.cpu = cpu.floor(1); + current.memory = line[1].parseInt2() * 1024; // kB to bytes + current.uptime = line[2]; + } + + next(); + }); + }); + + // Get count of open files + instance.options.monitorfiles && arr.push(function(next) { + Exec('lsof -a -p {0} | wc -l'.format(process.pid), function(err, response) { + if (err) + instance.throw(err); + else + current.files = response.trim().parseInt2(); + next(); + }); + }); + + // Get count of opened network connections + instance.options.monitorconnections && arr.push(function(next) { + Exec('netstat -an | grep :{0} | wc -l'.format(F.port), function(err, response) { + if (err) { + instance.throw(err); + } else { + current.connections = response.trim().parseInt2() - 1; + if (current.connections < 0) + current.connections = 0; + } + next(); + }); + }); + + // Get directory size + instance.options.monitorsize && current.counter % 5 !== 0 && arr.push(function(next) { + Exec('du -hsb ' + process.cwd(), function(err, response) { + if (err) { + instance.throw(err); + } else { + var match = response.trim().match(reg_appdisksize); + match && (current.size = match.toString().trim().parseInt2()); + } + next(); + }); + }); + + arr.async(function() { + + tproc && clearTimeout(tproc); + + if (instance.options.enabled) { + tproc = setTimeout(instance.custom.run, instance.options.interval); + instance.send2(current); + } + + instance.custom.status(); + current.counter++; + }); + }; + + instance.custom.status = function() { + if (instance.options.enabled) + instance.status('{0}% / {1}'.format(current.cpu, current.memory.filesize())); + else + instance.status('Disabled', 'red'); + }; + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + + if (instance.options.enabled) { + current.counter = 0; + instance.custom.run(); + } + + }); + + instance.on('close', function() { + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + }); + + setTimeout(instance.custom.run, 1000); +}; \ No newline at end of file diff --git a/RVO3/flow/monitordisk.js b/RVO3/flow/monitordisk.js new file mode 100755 index 0000000..f4fdaa0 --- /dev/null +++ b/RVO3/flow/monitordisk.js @@ -0,0 +1,96 @@ +exports.id = 'monitordisk'; +exports.title = 'Disk'; +exports.version = '1.0.0'; +exports.author = 'Peter Širka'; +exports.group = 'Monitoring'; +exports.color = '#F6BB42'; +exports.output = 1; +exports.icon = 'hdd-o'; +exports.click = true; +exports.options = { interval: 8000, path: '/', enabled: true }; +exports.readme = `# Disk monitoring + +This component monitors disk \`bytes\` consumption in Linux systems. It uses \`df\` command. + +__Data Example__: + +\`\`\`javascript +{ + total: 474549649408, + used: 39125245952, + free: 411294994432 +} +\`\`\``; + +exports.html = `
+
+
+
@(Interval in milliseconds)
+
+
+
@(Path)
+
+
+
`; + +exports.install = function(instance) { + + var current = { total: 0, used: 0, free: 0, path: '', type: '', percentUsed: 0 }; + var tproc = null; + + instance.custom.run = function() { + + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + + if (!instance.options.enabled) + return; + + require('child_process').exec('df -hTB1 ' + instance.options.path, function(err, response) { + + tproc = setTimeout(instance.custom.run, instance.options.interval); + + if (err) { + instance.error(err); + return; + } + + response.parseTerminal(function(line) { + if (line[0][0] !== '/') + return; + current.total = line[2].parseInt(); + current.free = line[4].parseInt(); + current.used = line[3].parseInt(); + current.path = instance.options.path || '/'; + current.type = line[1]; + current.percentUsed = line[5]; + instance.custom.status(); + instance.send2(current); + }); + }); + }; + + instance.custom.status = function() { + if (instance.options.enabled) + instance.status(current.free.filesize() + ' / ' + current.total.filesize()); + else + instance.status('Disabled', 'red'); + }; + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + instance.options.enabled && instance.custom.run(); + }); + + instance.on('close', function() { + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + }); + + setTimeout(instance.custom.run, 1000); +}; \ No newline at end of file diff --git a/RVO3/flow/monitormemory.js b/RVO3/flow/monitormemory.js new file mode 100755 index 0000000..2decbc4 --- /dev/null +++ b/RVO3/flow/monitormemory.js @@ -0,0 +1,87 @@ +exports.id = 'monitormemory'; +exports.title = 'Memory'; +exports.version = '1.0.0'; +exports.author = 'Peter Širka'; +exports.group = 'Monitoring'; +exports.color = '#F6BB42'; +exports.output = 1; +exports.click = true; +exports.icon = 'microchip'; +exports.options = { interval: 8000, enabled: true }; +exports.readme = `# Memory monitoring + +This component monitors memory \`bytes\` consumption in Linux systems. It uses \`free\` command. + +__Data Example__: + +\`\`\`javascript +{ + total: 33558769664, + used: 1998868480, + free: 2653708288 +} +\`\`\``; + +exports.html = `
+
+
+
@(Interval in milliseconds)
+
+
+
`; + +exports.install = function(instance) { + + var current = { total: 0, used: 0, free: 0 }; + var tproc = null; + + instance.custom.run = function() { + + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + + if (!instance.options.enabled) + return; + + require('child_process').exec('free -b -t', function(err, response) { + + tproc = setTimeout(instance.custom.run, instance.options.interval); + + if (err) { + instance.error(err); + return; + } + + var memory = response.split('\n')[1].match(/\d+/g); + current.total = memory[0].parseInt(); + current.used = memory[1].parseInt() - memory[3].parseInt(); + current.free = current.total - current.used; + instance.custom.status(); + instance.send2(current); + }); + }; + + instance.custom.status = function() { + if (instance.options.enabled) + instance.status(current.free.filesize() + ' / ' + current.total.filesize()); + else + instance.status('Disabled', 'red'); + }; + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + instance.options.enabled && instance.custom.run(); + }); + + instance.on('close', function() { + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + }); + + setTimeout(instance.custom.run, 1000); +}; \ No newline at end of file diff --git a/RVO3/flow/nodesdb_changecheck.js b/RVO3/flow/nodesdb_changecheck.js new file mode 100755 index 0000000..9adab62 --- /dev/null +++ b/RVO3/flow/nodesdb_changecheck.js @@ -0,0 +1,77 @@ +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 = 2; +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); + } + } + + //kedze do slacku posielame stringy, na cloud musime previest vsetky stringy spat na objekty: + // Funkcia na parsovanie všetkých reťazcov v poli + const parseArray = (arr) => { + return arr.map(jsonString => JSON.parse(jsonString)); + }; + + 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); + if (FLOW.GLOBALS.settings.send_changed_node_numbers) instance.send(1, { aktualneNody: parseArray(zmenene), originalne: parseArray(Array.from(set2)) }); + } + 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/RVO3/flow/show_dbdata.js b/RVO3/flow/show_dbdata.js new file mode 100755 index 0000000..1e23ff7 --- /dev/null +++ b/RVO3/flow/show_dbdata.js @@ -0,0 +1,243 @@ +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 = 8; +exports.output = 1; + +const { exec } = require('child_process'); + +exports.install = 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 }) + }) + instance.on("5", _ => { + exec("sudo tail -n 25 monitor.txt", (err, stdout, stderr) => { + if (err || stderr) instance.send(0, { err, stderr }); + else instance.send(0, stdout); + }) + }) + instance.on("6", _ => { + exec("sudo tail -n 25 err.txt", (err, stdout, stderr) => { + if (err || stderr) instance.send(0, { err, stderr }); + else instance.send(0, stdout); + }) + }) + instance.on("7", _ => { + instance.send(0, FLOW.deviceStatus); + }) +}; + + +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/RVO3/flow/slack_filter.js b/RVO3/flow/slack_filter.js new file mode 100755 index 0000000..6618523 --- /dev/null +++ b/RVO3/flow/slack_filter.js @@ -0,0 +1,188 @@ +exports.id = 'slack_filter'; +exports.title = 'Slack Filter'; +exports.group = 'Citysys'; +exports.color = '#30E193'; +exports.input = 2; +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 = `
+
+
+
@(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('0', 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']['en']; + 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"] = []; + } + + instance.options.name = FLOW.GLOBALS.settings.rvo_name; + if (instance.options.name) { + instance.status('Running'); + running = true; + } else { + instance.status('Please run options again', 'red'); + running = false; + } + } catch (e) { + instance.error('Citysys connector: ' + e.message); + } + }; + + instance.on('options', instance.reconfigure); + + instance.on("1", _ => { + instance.reconfigure(); + }) +}; diff --git a/RVO3/flow/thermometer.js b/RVO3/flow/thermometer.js new file mode 100755 index 0000000..fc7074d --- /dev/null +++ b/RVO3/flow/thermometer.js @@ -0,0 +1,99 @@ +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 = 5;//minutes +let NUMBER_OF_FAILURES_TO_SEND_ERROR = 13; + +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) => { + + 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); + setTimeout(main, 20000); + }) +}; diff --git a/RVO3/flow/trigger.js b/RVO3/flow/trigger.js new file mode 100755 index 0000000..27545a8 --- /dev/null +++ b/RVO3/flow/trigger.js @@ -0,0 +1,79 @@ +exports.id = 'trigger'; +exports.title = 'Trigger'; +exports.group = 'Inputs'; +exports.color = '#F6BB42'; +exports.click = true; +exports.output = 1; +exports.version = '1.1.0'; +exports.author = 'Martin Smola'; +exports.icon = 'play'; + +exports.html = `
+
@(Data type (String by default))
+
@(Data)
+
Trigger 5s after initialization.
+
@(Useful when there's a need to run certain flow when the app restarts, etc.)
+
`; + +exports.readme = `# Trigger + +- Clicking on the component starts the chain +- Settings allows to set a data-type and a value`; + +exports.install = function(instance) { + + var value; + + instance.on('click', () => instance.send2(value)); + + instance.reconfigure = function() { + var options = instance.options; + value = null; + switch (options.datatype) { + case 'integer': + value = options.data.parseInt2('error'); + value = value === 'error' ? NaN : value; + break; + case 'float': + value = options.data.parseFloat2('error'); + value = value === 'error' ? NaN : value; + break; + case 'date': + options.data = options.data.toString(); + var num = options.data.parseInt('error'); + num === 'error' && (num = options.data.parseDate('error')); + num === 'error' && (num = null); + value = num ? new Date(num).toUTCString() : num; + break; + case 'object': + try { + value = (new Function('return ' + options.data))(); + } catch (e) { + instance.error(e); + } + break; + case 'boolean': + value = options.data.parseBoolean(); + break; + case 'buffer': + try { + value = U.createBuffer(options.data); + } catch (e) { + instance.error(e); + } + break; + case 'string': + default: + value = '' + (options.data || ''); + break; + } + }; + + instance.on('options', instance.reconfigure); + instance.reconfigure(); + + if (instance.options.restart) + setTimeout(function(){ + instance.send2(value); + }, 5000); +}; diff --git a/RVO3/flow/variables.txt b/RVO3/flow/variables.txt new file mode 100755 index 0000000..e69de29 diff --git a/RVO3/flow/virtualwirein.js b/RVO3/flow/virtualwirein.js new file mode 100755 index 0000000..38a4e42 --- /dev/null +++ b/RVO3/flow/virtualwirein.js @@ -0,0 +1,43 @@ +exports.id = 'virtualwirein'; +exports.title = 'Virtual wire in'; +exports.version = '1.0.0'; +exports.author = 'Martin Smola'; +exports.color = '#303E4D'; +exports.icon = 'sign-in'; +exports.input = false; +exports.output = 1; +exports.options = {}; +exports.readme = `# Virtual wire in + +When the wires between the components are mess it's time to use Virtual wire.`; + +exports.html = `
+
@(Wire name)
+
+`; + +exports.install = function(instance) { + + instance.custom.reconfigure = function(options){ + if (instance.options.wirename) { + instance.status(instance.options.wirename); + } else + instance.status('Not configured', 'red'); + }; + + ON('virtualwire', function(wirename, flowdata){ + if (instance.options.wirename && instance.options.wirename === wirename) + instance.send(flowdata); + }); + + instance.on('options', instance.custom.reconfigure); + instance.custom.reconfigure(); +}; diff --git a/RVO3/flow/virtualwireout.js b/RVO3/flow/virtualwireout.js new file mode 100755 index 0000000..94a1e4f --- /dev/null +++ b/RVO3/flow/virtualwireout.js @@ -0,0 +1,41 @@ +exports.id = 'virtualwireout'; +exports.title = 'Virtual wire out'; +exports.version = '1.0.0'; +exports.author = 'Martin Smola'; +exports.color = '#303E4D'; +exports.icon = 'sign-out'; +exports.input = true; +exports.options = {}; +exports.readme = `# Virtual wire out + +When the wires between the components are mess it's time to use Virtual wire.`; + +exports.html = `
+
@(Wire name)
+
+`; + +exports.install = function(instance) { + + instance.custom.reconfigure = function(){ + if (instance.options.wirename) { + instance.status(instance.options.wirename); + } else + instance.status('Not configured', 'red'); + }; + + instance.on('data', function(flowdata) { + EMIT('virtualwire', instance.options.wirename, flowdata); + }); + + instance.on('options', instance.custom.reconfigure); + instance.custom.reconfigure(); +}; diff --git a/RVO3/flow/wsmqttpublish.js b/RVO3/flow/wsmqttpublish.js new file mode 100755 index 0000000..0eba804 --- /dev/null +++ b/RVO3/flow/wsmqttpublish.js @@ -0,0 +1,448 @@ +exports.id = 'wsmqttpublish'; +exports.title = 'WS MQTT publish'; +exports.group = 'MQTT'; +exports.color = '#888600'; +exports.version = '1.0.2'; +exports.icon = 'sign-out'; +exports.input = 2; +exports.output = 3; +exports.options = { host: 'tb-stage.worksys.io', port: 1883, clientid: "", username: "" }; + +exports.html = `
+
+
+
Hostname or IP address (if not empty - setting will override db setting)
+
+
+
Port
+
+
+
+
+
@(Client id)
+
+
+
@(Username)
+
+
+
`; + + +exports.readme = ` +# WS MQTT Publish + +Version 1.0.3. + +Added: +- database collections, +- 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 = { + debug: 0, + rpcCall: 1, + services: 2 +} + +//CONFIG +let createTelemetryBackup = true; +let saveTelemetryOnError = true;//backup_on_failure overrides this value +//------------------------ + +let rollers; +if (createTelemetryBackup) rollers = require('streamroller'); + +const noSqlFileSizeLimit = 4194304;//use 5MB - 4194304 +let insertNoSqlCounter = 0; +let insertBackupNoSqlCounter = 0; +let processingData = false; + +let backup_on_failure = false;//== saveTelemetryOnError - create backup client 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; + +process.on('uncaughtException', function(err) { + + errLogger.error('uncaughtException:', err.message) + errLogger.error(err.stack); + + //TODO + //send to service + + //process.exit(1); +}) + +const nosql = NOSQL('tbdata'); +const nosqlBackup = NOSQL('/backup/tbdata'); + + +exports.install = function(instance) { + + var client; + var opts; + var clientReady = false; + + // wsmqtt status for notification purposes on projects.worksys.io database + let wsmqttName = null; + let sendWsStatusVar = null; + let wsmqtt_status = 'disconnected'; + + 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'; + } + + function sendWsStatus() { + instance.send(SEND_TO.services, { [wsmqttName]: wsmqtt_status }); + } + + + function main() { + if (!FLOW.dbLoaded) return; + + loadSettings(); + clearInterval(sendWsStatus); + sendWsStatusVar = setInterval(sendWsStatus, 180000); + } + + //set opts according to db settings + function loadSettings() { + + if (instance.options.host !== "") { + //override settings from database + var o = instance.options; + opts = { + host: o.host, + port: o.port, + clientId: o.clientid, + username: o.username, + rejectUnauthorized: false, + resubscribe: false + }; + + wsmqttName = getWsmqttName(o.host); + + console.log("wsmqttpublich -> loadSettings from instance.options", instance.options); + } + else { + + const SETTINGS = FLOW.GLOBALS.settings; + backup_on_failure = SETTINGS.backup_on_failure; + saveTelemetryOnError = backup_on_failure; + + restore_from_backup = SETTINGS.restore_from_backup; + restore_backup_wait = SETTINGS.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; + + opts = { + host: mqtt_host, + port: mqtt_port, + keepalive: 10, + clientId: mqtt_clientid, + username: mqtt_username, + rejectUnauthorized: false, + resubscribe: false + }; + + wsmqttName = getWsmqttName(mqtt_host); + } + + connectToTbServer(); + } + + function connectToTbServer() { + 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"); + //monitor.info("MQTT client connected"); + + sendClientError = true; + clientReady = true; + wsmqtt_status = 'connected'; + }); + + client.on('reconnect', function() { + instance.status("Reconnecting", "yellow"); + clientReady = false; + }); + + client.on('message', function(topic, message) { + // message is type of buffer + message = message.toString(); + if (message[0] === '{') { + TRY(function() { + + message = JSON.parse(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 } }); + } + + }, () => instance.debug('MQTT: Error parsing data', message)); + } + + instance.send(SEND_TO.rpcCall, { "topic": topic, "content": message }); + }); + + client.on('close', function() { + clientReady = false; + wsmqtt_status = 'disconnected'; + + instance.status("Disconnected", "red"); + instance.send(SEND_TO.debug, { "message": "Client CLOSE signal received !" }); + }); + + client.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; + wsmqtt_status = 'disconnected'; + }); + + } + + + instance.on("0", _ => { + main(); + }) + + + instance.on('1', function(data) { + + if (clientReady) { + //do we have some data in backup file? if any, process data from database + if (saveTelemetryOnError) { + //read telemetry data and send back to server + if (!processingData) processDataFromDatabase(); + } + + let stringifiedJson = JSON.stringify(data.data); + client.publish("v1/gateway/telemetry", stringifiedJson, { qos: 1 }); + + //backup telemetry + if (createTelemetryBackup) { + data.data.id = UID(); + nosqlBackup.insert(data.data); + + insertBackupNoSqlCounter++; + if (insertBackupNoSqlCounter > 150) { + let options = { compress: true }; + let path = __dirname + "/../databases/backup/tbdata.nosql"; + var stream = new rollers.RollingFileStream(path, noSqlFileSizeLimit, 150, options); + stream.write(""); + stream.end(); + + insertBackupNoSqlCounter = 0; + } + } + + } + 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 (saveTelemetryOnError) { + //create new file from tbdata.nosql, if file size exceeds given limit, and clear tbdata.nosql + makeBackupFromDbFile(); + + //write to tb + data.data.id = UID(); + nosql.insert(data.data); + } + } + }); + + + instance.close = function(done) { + if (clientReady) { + client.end(); + clearInterval(sendWsStatusVar); + } + }; + + + function getDbBackupFileCounter(type) { + var files = fs.readdirSync(__dirname + "/../databases"); + + let counter = 0; + for (var i = 0; i < files.length; i++) { + + if (files[i] == "tbdata.nosql") continue; + + if (files[i].endsWith(".nosql")) { + + let pos = files[i].indexOf("."); + if (pos > -1) { + + let fileCounter = counter; + let firstDigit = files[i].slice(0, pos); + + fileCounter = parseInt(firstDigit); + if (isNaN(fileCounter)) fileCounter = 0; + //console.log("getDbBackupFileCounter digit:", files[i], firstDigit, fileCounter, isNaN(fileCounter), type); + + if (type == "max") { + if (fileCounter > counter) { + counter = fileCounter; + } + } + else if (type == "min") { + if (counter == 0) counter = fileCounter; + + if (fileCounter < counter) { + counter = fileCounter; + } + } + } + } + + } + + if (type == "max") counter++; + + return counter; + } + + const makeBackupFromDbFile = async () => { + + if (!saveTelemetryOnError) return; + + //to avoid large file: tbdata.nosql + + //init value is 0! + if (insertNoSqlCounter > 0) { + --insertNoSqlCounter; + return; + } + + insertNoSqlCounter = 100; + + let source = __dirname + "/../databases/tbdata.nosql"; + + var stats = fs.statSync(source); + var fileSizeInBytes = stats.size; + + if (fileSizeInBytes > noSqlFileSizeLimit) { + + let counter = 1; + counter = getDbBackupFileCounter("max"); + + let destination = __dirname + "/../databases/" + counter + "." + "tbdata.nosql"; + + //make backup file + fs.copyFileSync(source, destination); + //fs.renameSync(p, p + "." + counter); + + //clear tbdata.nosql + fs.writeFileSync(source, ""); + fs.truncateSync(source, 0); + + } + } + + const processDataFromDatabase = async () => { + + if (restore_from_backup <= 0) return; + + //calculate diff + const now = new Date(); + let currentTime = now.getTime(); + let diff = currentTime - lastRestoreTime; + + if ((diff / 1000) < restore_backup_wait) { + //console.log("*********restore_backup_wait", diff, restore_backup_wait); + return; + } + + processingData = true; + + //get filename to process + let counter = getDbBackupFileCounter("min"); + + //we have some backup files + let dataBase = 'tbdata'; + + var nosql; + if (counter == 0) dataBase = 'tbdata'; + else dataBase = counter + "." + 'tbdata'; + + nosql = NOSQL(dataBase); + + //select all data - use limit restore_from_backup + let records = await promisifyBuilder(nosql.find().take(restore_from_backup)); + + for (let i = 0; i < records.length; i++) { + if (clientReady) { + + let item = records[i]; + let id = item.id; + + if (id !== undefined) { + //console.log("------------processDataFromDatabase - remove", id, dataBase, i); + + try { + + let message = JSON.parse(JSON.stringify(item)); + delete message.id; + + client.publish("v1/gateway/telemetry", JSON.stringify(message), { qos: 1 }); + + //remove from database + await promisifyBuilder(nosql.remove().where("id", id)); + + } catch (error) { + //process error + console.log("processDataFromDatabase", error); + } + + } + + } + else { + processingData = false; + return; + } + } + + if (records.length > 0) { + //clean backup file + if (counter > 0) nosql.clean(); + } + + //no data in db, remove + if (records.length == 0) { + if (counter > 0) nosql.drop(); + } + + const d = new Date(); + lastRestoreTime = d.getTime(); + + processingData = false; + + } + + instance.on('options', main); + //instance.reconfigure(); +}; diff --git a/RVO3/flow_20_01_25/cloudmqttconnect.js b/RVO3/flow_20_01_25/cloudmqttconnect.js new file mode 100755 index 0000000..d619784 --- /dev/null +++ b/RVO3/flow_20_01_25/cloudmqttconnect.js @@ -0,0 +1,374 @@ +exports.id = 'cloudmqttconnect'; +exports.title = 'Cloud connect mqtt'; +exports.group = 'MQTT'; +exports.color = '#888600'; +exports.version = '1.0.2'; +exports.icon = 'sign-out'; +exports.input = 2; +exports.output = 2; +exports.options = { host: 'tb-stage.worksys.io', port: 1883, clientid: "", username: "" }; + +exports.html = `
+
+
+
Hostname or IP address (if not empty - setting will override db setting)
+
+
+
Port
+
+
+
+
+
@(Client id)
+
+
+
topic
+
+
+
`; + + + +const { promisifyBuilder } = require('./helper/db_helper'); +const fs = require('fs'); +const mqtt = require('mqtt'); +const nosql = NOSQL('tbdatacloud'); + +const SEND_TO = { + debug: 0, + rpcCall: 1, +} + +//CONFIG +let saveTelemetryOnError = true;//backup_on_failure overrides this value +//------------------------ + +const noSqlFileSizeLimit = 4194304;//use 5MB - 4194304 +let insertNoSqlCounter = 0; +let insertBackupNoSqlCounter = 0; +let processingData = false; + +let backup_on_failure = true;//== saveTelemetryOnError - create backup client send failure +let restore_from_backup = 50; //how many rows process at once? +let restore_backup_wait = 3;//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; + + +exports.install = function(instance) { + + var client; + var opts; + var clientReady = false; + + let o = null; //options + + function main() + { + loadSettings(); + } + + //set opts according to db settings + function loadSettings() + { + + o = instance.options; + if(!o.topic) o.topic = FLOW.GLOBALS.settings.cloud_topic; + + opts = { + host: o.host, + port: o.port, + clientId: o.clientid, + username: o.username, + rejectUnauthorized: false, + resubscribe: false + }; + + console.log("wsmqttpublich -> loadSettings from instance.options",o); + + connectToTbServer(); + } + + function connectToTbServer() + { + var url = "mqtt://" + opts.host + ":" + opts.port; + console.log("MQTT URL: ", url); + + client = mqtt.connect(url, opts); + + client.on('connect', function() { + client.subscribe(`${o.topic}_backward`, (err) => { + if (!err) { + console.log("MQTT subscribed"); + } + }); + instance.status("Connected", "green"); + clientReady = true; + sendClientError = true; + }); + + client.on('reconnect', function() { + instance.status("Reconnecting", "yellow"); + clientReady = false; + }); + + client.on('message', function(topic, message) { + // message is type of buffer + message = message.toString(); + if (message[0] === '{') { + TRY(function() { + + message = JSON.parse(message); + if (message.hasOwnProperty("device") && message.hasOwnProperty("data") && message.data.hasOwnProperty("id")) { + client.publish(`${o.topic}_forward`, `{"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}}); + } + + }, () => instance.debug('MQTT: Error parsing data', message)); + } + + instance.send(SEND_TO.rpcCall, {"topic":o.topic, "content":message }); + }); + + client.on('close', function() { + clientReady = false; + + instance.status("Disconnected", "red"); + instance.send(SEND_TO.debug, {"message":"Client CLOSE signal received !"}); + }); + + client.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) { + console.log('MQTT client error', err); + sendClientError = false; + } + clientReady = false; + }); + + } + + + instance.on('0', function(data) { + + if(clientReady) + { + //do we have some data in backup file? if any, process data from database + if(saveTelemetryOnError) + { + //read telemetry data and send back to server + if(!processingData) processDataFromDatabase(); + } + + let stringifiedJson = JSON.stringify(data.data) + client.publish(`${o.topic}_forward`, stringifiedJson, {qos: 1}); + } + 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(saveTelemetryOnError) + { + //create new file from tbdata.nosql, if file size exceeds given limit, and clear tbdata.nosql + makeBackupFromDbFile(); + + //write to tb + data.data.id = UID(); + nosql.insert(data.data); + } + } + }); + + instance.on("1", _ => { + main(); + }) + + instance.close = function(done) { + if(clientReady){ + client.end(); + } + }; + + + function getDbBackupFileCounter(type) + { + var files = fs.readdirSync(__dirname + "/../databases"); + + let counter = 0; + for(var i = 0; i < files.length; i++) + { + + if(files[i] == "tbdatacloud.nosql") continue; + + if(files[i].endsWith(".nosql")) + { + + let pos = files[i].indexOf("."); + if(pos > -1) + { + + let fileCounter = counter; + let firstDigit = files[i].slice(0, pos); + + fileCounter = parseInt(firstDigit); + if(isNaN(fileCounter)) fileCounter = 0; + //console.log("getDbBackupFileCounter digit:", files[i], firstDigit, fileCounter, isNaN(fileCounter), type); + + if(type == "max") + { + if(fileCounter > counter) + { + counter = fileCounter; + } + } + else if(type == "min") + { + if(counter == 0) counter = fileCounter; + + if(fileCounter < counter) + { + counter = fileCounter; + } + } + } + } + + } + + if(type == "max") counter++; + + return counter; + } + + const makeBackupFromDbFile = async () => { + + if(!saveTelemetryOnError) return; + + //to avoid large file: tbdata.nosql + + //init value is 0! + if(insertNoSqlCounter > 0) + { + --insertNoSqlCounter; + return; + } + + insertNoSqlCounter = 100; + + let source = __dirname + "/../databases/tbdatacloud.nosql"; + + var stats = fs.statSync(source); + var fileSizeInBytes = stats.size; + + if(fileSizeInBytes > noSqlFileSizeLimit) + { + + let counter = 1; + counter = getDbBackupFileCounter("max"); + + let destination = __dirname + "/../databases/" + counter + "." + "tbdatacloud.nosql"; + + //make backup file + fs.copyFileSync(source, destination); + //fs.renameSync(p, p + "." + counter); + + //clear tbdata.nosql + fs.writeFileSync(source, ""); + fs.truncateSync(source, 0); + + } + } + + const processDataFromDatabase = async () => { + + if(restore_from_backup <= 0) return; + + //calculate diff + const now = new Date(); + let currentTime = now.getTime(); + let diff = currentTime - lastRestoreTime; + + if( (diff / 1000) < restore_backup_wait) + { + //console.log("*********restore_backup_wait", diff, restore_backup_wait); + return; + } + + processingData = true; + + //get filename to process + let counter = getDbBackupFileCounter("min"); + + //we have some backup files + let dataBase = 'tbdata'; + + var nosql; + if(counter == 0) dataBase = 'tbdatacloud'; + else dataBase = counter + "." + 'tbdatacloud'; + + nosql = NOSQL(dataBase); + + //select all data - use limit restore_from_backup + let records = await promisifyBuilder(nosql.find().take(restore_from_backup)); + + for(let i = 0; i < records.length; i++) + { + if(clientReady) { + + let item = records[i]; + let id = item.id; + + if(id !== undefined) + { + //console.log("------------processDataFromDatabase - remove", id, dataBase, i); + + try { + + let message = JSON.parse(JSON.stringify(item)); + delete message.id; + client.publish(`${o.topic}_forward`, JSON.stringify(message), {qos:1}); + + //remove from database + await promisifyBuilder(nosql.remove().where("id", id)); + + } catch(error) { + //process error + console.log("processDataFromDatabase", error); + } + + } + + } + else + { + processingData = false; + return; + } + } + + if(records.length > 0) + { + //clean backup file + if(counter > 0) nosql.clean(); + } + + //no data in db, remove + if(records.length == 0) + { + if(counter > 0) nosql.drop(); + } + + const d = new Date(); + lastRestoreTime = d.getTime(); + + processingData = false; + + } + + instance.on('options', main); + +}; diff --git a/RVO3/flow_20_01_25/cmd_manager.js b/RVO3/flow_20_01_25/cmd_manager.js new file mode 100755 index 0000000..a960aaa --- /dev/null +++ b/RVO3/flow_20_01_25/cmd_manager.js @@ -0,0 +1,2988 @@ +exports.id = 'cmd_manager'; +exports.title = 'CMD Manager'; +exports.group = 'Worksys'; +exports.color = '#5D9CEC'; +exports.version = '0.0.3'; +exports.output = ['red', 'blue', 'yellow', 'blue', 'white']; +exports.input = 3; +exports.icon = 'cloud-upload'; + +exports.html = ` +
+
+
+
RPC - run RPC calls

+
+
+
@(User)
+
+
+
@(Password)
+
+
+
@(My edge)
+
+
+
+`; +exports.readme = `Manager for CMD calls`; + + +exports.install = function(instance) { + + 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'); + + 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'); + + const dbNodes = TABLE("nodes"); + const dbRelays = TABLE("relays"); + + let GLOBALS; + let SETTINGS; + let rsPort; + let tbHandler; + + // runTasks intervals + const SHORT_INTERVAL = 30; + const LONG_INTERVAL = 300; + + //send data to following instances: + const SEND_TO = { + debug: 0, + tb: 1, + http_response: 2, + dido_controller: 3, + infoSender: 4 + } + + 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 + } + + 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 + + //if sending of profile to node fails, we send notification and push node into set, so we do not send notification twice + const nodeProfileSendFail = new Set(); + + //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(); + } + + + 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" + //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); + + 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); + + console.log("proces profile finished *********************") + } + + + 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; + }); + } + + + 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) { + for (let k in nodesData) { + 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`); + } + } + } + + + function loadRelaysData(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 (value.contactor == 1) processAllNodeProfilesOnLine(value.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 = {}; + + 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.byte1 = hours;//h + params.byte2 = minutes;//m + params.byte3 = seconds;//s + params.byte4 = 0; + params.recipient = 2;//2 broadcast, address = 0 + params.register = 87;//Actual time + params.rw = 1;//write + + //other values + params.type = "cmd"; + params.timestamp = Date.now() + 60000; + params.addMinutesToTimestamp = addMinutesToTimestamp; + params.info = "run broadcast: Actual time"; + + tasks.push(params); + + let sec = 3; + 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) { + 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); + + 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'; + //params.debug = true; + + tasks.push(params); + } + + //Prúd + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "cmd"; + params.tbname = tbname; + params.address = node; + params.register = 75;//prud + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read current'; + //params.debug = true; + + tasks.push(params); + } + + //výkon + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "cmd"; + params.tbname = tbname; + params.address = node; + params.register = 76;//výkon + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read power'; + //params.debug = true; + + tasks.push(params); + } + } + } + }, sec * 1000); + } + + + 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"; + + const date = Date.now(); + + // 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); + }) + + } + + + function turnLine(onOrOff, line, info) { + let obj = { + line: line, + command: onOrOff, + info: info + }; + + logger.debug("linia", line, obj); + instance.send(SEND_TO.dido_controller, obj); + } + + + + 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"; + 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]) { + //CRC_ERROR + message = "NOK"; + error = "CRC_ERROR c1"; + instance.send(SEND_TO.debug, "CRC_ERROR c1"); + } + + 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") { + instance.send(SEND_TO.debug, bytes); + instance.send(SEND_TO.debug, "RESPONSE " + type + " - " + bytes[4]); + + //logger.debug(SEND_TO.debug, "RESPONSE " + type + " - " + bytes[4], bytes); + + error = "type is: " + type; + + message = "NOK"; + } + + return { message, type, error }; + } + + + //BUILD TASKS// + function buildTasks(params) { + //report SETTINGS.edge_fw_version as fw_version + //report date as startdate + + //return; + console.log("buidTAaasks start ****************", params); + + monitor.info("buildTasks - params", params); + + let processLine; //defined line + let init = false; + let processLineProfiles = true; + let processBroadcast = true; + let processNodes = true; + + if (params == undefined) { + init = true; + tasks = []; + logger.debug("-->buildTasks clear tasks"); + } + else { + processLineProfiles = false; + processBroadcast = false; + processNodes = false; + + processLineProfiles = params.processLineProfiles; + processLine = params.line; + } + + //load profiles pre vsetky linie: + let now = new Date(); + + if (processLineProfiles) { + //process line profiles + let keys = Object.keys(relaysData); + 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; + } + + try { + + /** + * we process line profiles: timepoints, astro clock, lux_sensor, offsets ... + */ + if (profilestr === "") throw ("Profile is not defined"); + let profile = JSON.parse(profilestr); + 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; + + // add name to regular profile timepoint and delete unused end_time key: + time_points.forEach(point => { + point.name = "profileTimepoint" + delete point.end_time; + }); + + //monitor.info("buildTasks: time_points", time_points); + + + /** + * 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 astro clock true, we remove all regular profile points + time_points = []; + + 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 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); + + 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); + + 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(':'); + + let ad = new Date(); + ad.setHours(parseInt(ahours), parseInt(aminutes), 0); + + let bd = new Date(); + bd.setHours(parseInt(bhours), parseInt(bminutes), 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++) { + + let start_time = new Date(); + let [hours, minutes] = time_points[t].start_time.split(':'); + start_time.setHours(parseInt(hours), parseInt(minutes), 0); + + //task is in 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); + params.value = time_points[t].value; + params.tbname = relaysData[line].tbname; + params.timestamp = start_time.getTime(); + + 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; + + //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)) { + 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; + + params.debug = true; + + //turn on/off line + tasks.push(params); + monitor.info("TimePoint params: ", params.info, start_time); + } + + monitor.info("-->time_points final", line, time_points); + + //ensure to turn on/off according to calculated currentValue + let params = getParams(PRIORITY_TYPES.terminal); + params.type = "relay"; + params.line = parseInt(line); + params.tbname = relaysData[line].tbname; + params.value = currentValue; + + params.timestamp = PRIORITY_TYPES.terminal; + params.addMinutesToTimestamp = 0; + params.debug = true; + + //logger.debug(now.toLocaleString("sk-SK")); + 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; + + tasks.push(params); + + } catch (error) { + if (profilestr !== "") { + //errLogger.error(profilestr, error); + errorHandler.sendMessageToService(profilestr + "-" + error, 0, "js_error"); + } + } + + } + + //logger.debug("tasks:"); + //logger.debug(tasks); + } + + + //PROCESS DEFAULT BROADCASTS + //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.register = 6;//Time of dusk - Reg 6 + params.rw = 1;//write + + //other values + params.type = "cmd"; + params.timestamp = Date.now() + 60000; + params.addMinutesToTimestamp = addMinutesToTimestamp; + params.info = "Broadcast-duskTime"; + + tasks.push(params); + } + + { + + //run broadcast Time of dawn + 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 + params.byte3 = 0;//s + params.byte4 = 0; + params.recipient = 2; //2 broadcast + params.register = 7;//Time of dawn - Reg 6 + params.rw = 1;//write + + //other values + params.type = "cmd"; + params.timestamp = Date.now() + 60000; + params.addMinutesToTimestamp = addMinutesToTimestamp; + params.info = "Broadcast-dawnTime"; + + tasks.push(params); + } + + { + //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 + params.byte3 = seconds;//s + params.byte4 = 0; + params.recipient = 2; //2 broadcast + params.register = 87;//Actual time + params.rw = 1;//write + + //other values + params.type = "cmd"; + params.timestamp = Date.now() + 60000; + params.addMinutesToTimestamp = addMinutesToTimestamp; + params.info = "run broadcast: Actual time"; + + tasks.push(params); + } + + } + + //process nodes & tasks + //reportovanie pre platformu + 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++) { + register = listOfCommands[i]; + + let params = getParams(PRIORITY_TYPES.node_cmd); + + //core rpc values + params.address = address; + params.byte1 = 0; + params.byte2 = 0; + params.byte3 = 0; + params.byte4 = 0; + 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) { + timestampStart = timestampStart + addMinutesToTimestamp * 60000; + } + + //other values + params.type = "cmd"; + params.tbname = tbname; + params.timestamp = timestampStart; + params.addMinutesToTimestamp = addMinutesToTimestamp; + params.info = "generated cmd - buildTasks (node)"; + + tasks.push(params); + + } + } + } + + + //niektore ulohy sa vygeneruju iba 1x pri starte!!! + if (!init) return; + + + //Priebežne (raz za cca 5 minút) je potrebné vyčítať z Master nodu verziu jeho FW. + //Jedná sa o register 10. Rovnaká interpretácia ako pri FW verzii nodu. + //Adresa mastera je 0. V prípade že kedykoľvek nastane situácia že Master Node neodpovedá (napríklad pri vyčítaní telemetrie z nodu nevráti žiadne dáta), + //tak treba vyreportovať string "NOK". + { + let params = getParams(PRIORITY_TYPES.fw_detection); + params.type = "cmd-master"; + params.register = 4; + params.address = 0; + params.timestamp = Date.now() + 60000; + params.addMinutesToTimestamp = 5; + params.tbname = SETTINGS.rvoTbName; + params.info = "Master node FW verzia"; + //params.debug = true; + + //this will set SETTINGS.masterNodeIsResponding + + tasks.push(params); + } + + //kazdu hodinu skontrolovat nastavenie profilov + { + let params = getParams(PRIORITY_TYPES.fw_detection); + params.type = "process_profiles"; + params.timestamp = Date.now() + 60000; + params.addMinutesToTimestamp = 60;//60 = every hour + params.info = "detekcia nespracovaných profilov linie a nodov"; + //params.debug = true; + + tasks.push(params); + } + + monitor.info("tasks created:", tasks.length); + } + + + /** + * We process line profile, where "astro_clock": true + * example profile: + * + "dawn_lux_sensor": true, + "dusk_lux_sensor": true, + "dawn_lux_sensor_value": 5, + "dusk_lux_sensor_value": 5, + "dawn_astro_clock_offset": 0, + "dusk_astro_clock_offset": 10, + "dawn_lux_sensor_time_window": 30, + "dusk_lux_sensor_time_window": 30, + "dawn_astro_clock_time_window": 60, + "dusk_astro_clock_time_window": 60 + + * if dawn: if currentTimestamp is in timewindow "dawnTime + and - dawn_lux_sensor_time_window" and lux value >= lux_sensor_value, we switch off the line. + * if dusk: we do oposite + * + * dawn: usvit - lux je nad hranicou - vypnem + * dusk: sumrak - lux je pod hranicou - zapnem + */ + 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++) { + + let line = keys[i]; //line is turned off by default + let profilestr = relaysData[line].profile; + const contactor = relaysData[line].contactor; + + try { + + let profile = JSON.parse(profilestr); + if (Object.keys(profile).length === 0) throw ("turnOnOffLinesAccordingToLuxSensor - profile is not defined"); + + 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 (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"); + } + } + } + + //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 (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"); + } + } + } + + } + + } catch (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) { + //MASTER + if (node == 0) return; + + let nodeObj = nodesData[node]; + 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; + } + + } + + + 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 }; + } + }); + }); + } + + + async function runTasks() { + + clearInterval(interval); + + let currentTimestamp = Date.now(); + + //report dusk, dawn--------------------------------- + if (reportDuskDawn.dusk_time < currentTimestamp) { + //vyreportuj iba ak nie je velky rozdiel napr. 60 sekund + 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); + reportDuskDawn.dusk_time_reported = sunCalcResult.dusk_time; + } + } + + var nextDay = new Date(); + nextDay.setDate(nextDay.getDate() + 1); + + sunCalcResult = calculateDuskDawn(nextDay); + reportDuskDawn.dusk_time = sunCalcResult.dusk_time; + } + + if (reportDuskDawn.dawn_time < currentTimestamp) { + //vyreportuj iba ak nie je velky rozdiel napr. 60 sekund + 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); + reportDuskDawn.dawn_time_reported = sunCalcResult.dawn_time; + } + } + + var nextDay = new Date(); + nextDay.setDate(nextDay.getDate() + 1); + + sunCalcResult = calculateDuskDawn(nextDay); + reportDuskDawn.dawn_time = sunCalcResult.dawn_time; + + } + //-------------------------------------------------------- + + //sort tasks based on timestamp + 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) { + instance.send(SEND_TO.debug, "no tasks created"); + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + 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) { + //logger.debug("--->task to process", currentTask); + } + + if (currentTask.timestamp <= currentTimestamp) { + let params = { ...tasks[0] }; + + //allow terminal commands + if (SETTINGS.maintenance_mode && params.type !== "cmd-terminal") { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + let type = params.type; + let tbname = params.tbname; + let node = params.address; + + let line = null; + + //rpc related + if (nodesData[node] !== undefined) line = nodesData[node].line; + if (params.line !== undefined) line = params.line; + + let repeatTask = false; + if (params.addMinutesToTimestamp > 0 || params.timePointName) repeatTask = true; + + if (repeatTask) { + if (type === "cmd" || type === "cmd-master") { + //set next start time automatically + tasks[0].timestamp = currentTimestamp + tasks[0].addMinutesToTimestamp * 60000; + } + } + else { + tasks.shift(); + } + + //kontrola nespracovanych profilov nodov + if (type == "process_profiles") { + tasks[0].timestamp = currentTimestamp + tasks[0].addMinutesToTimestamp * 60000; + + //vsetky linie kt. su zapnute, a spracuju sa nespracovane profily nodov + loadRelaysData(); + + interval = setInterval(runTasks, SHORT_INTERVAL); + return; + } + + //relay + if (type == "relay") { + + const timePointName = params.timePointName; + const value = params.value; + + let date = new Date(); + date.setDate(date.getDate() + 1);//next day + + let sunCalcResult; + if (timePointName) sunCalcResult = calculateDuskDawn(date, params.line); + + if (timePointName == "dawn") { + tasks[0].timestamp = sunCalcResult.dawn_time; + } + else if (timePointName == "dusk") { + tasks[0].timestamp = sunCalcResult.dusk_time; + } + else if (timePointName == "luxOn") { + tasks[0].timestamp = sunCalcResult.dusk_time + params.dusk_lux_sensor_time_window * 60000; + } + else if (timePointName == "luxOff") { + tasks[0].timestamp = sunCalcResult.dawn_time + params.dawn_lux_sensor_time_window * 60000; + } + else if (timePointName == "profileTimepoint") { + tasks[0].timestamp = currentTimestamp + tasks[0].addMinutesToTimestamp * 60000; + } + + let info = "aplikovany bod profilu"; + let onOrOff = ""; + value == 1 ? onOrOff = "on" : onOrOff = "off"; + + turnLine(onOrOff, params.line, info); + + interval = setInterval(runTasks, SHORT_INTERVAL); + return; + } + + //zhodeny hlavny istic + let disconnected = false; + //if(rotary_switch_state == "Off") disconnected = true; + + //state_of_breaker[line] - alebo istic linie + 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" }; + + 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; + + if (!disconnectedReport[tbname]) { + sendTelemetry(values, tbname) + } + + interval = setInterval(runTasks, SHORT_INTERVAL); + + return; + } + + disconnectedReport[tbname] = false; + + const register = params.register; + + //high_priority + if (!SETTINGS.masterNodeIsResponding) { + //ak neodpoveda, nebudeme vykonavat ziadne commands, okrem cmd-terminal, a fw version + errorHandler.sendMessageToService("Master node is not responding"); + + let stop = true; + + //fw version - register == 4 + if (type == "cmd-terminal" || register == 4) stop = false; + if (stop) { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + } + + let contactorStatus = 1; + if (relaysData[line] != undefined) contactorStatus = relaysData[line].contactor; + + if (line == 0 || contactorStatus == 0) { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + // TODO: -> status offline for rvo if rotary_switch_state is OFF, this is source of errors + // + // let relayStatus = 1; + // if (relaysData[line] != undefined) { + // relayStatus = relaysData[line].contactor; + // } + + // if (line == 0) relayStatus = 0; + // if (type == "cmd-terminal") relayStatus = 1; + + // //check if rotary_switch_state == "Off" + // if (relayStatus == 0) { + // console.log("------------------------------------relayStatus", relayStatus, line); + // let values = { "status": "OFFLINE" }; + + // if(tbname) sendTelemetry(values, tbname) + + // interval = setInterval(runTasks, SHORT_INTERVAL); + // return; + // } + + if (!rsPort.isOpen) { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + //RE-CALCULATE VALUES + //set actual time for broadcast + if (register == 87 && params.recipient === 2) { + var d = new Date(); + params.byte1 = d.getHours();//h + params.byte2 = d.getMinutes();//m + params.byte3 = 0;//s + params.byte4 = 0; + } + + //SET DUSK/DAWN FOR BROADCAST + //Time of dusk + if (register == 6 && params.recipient === 2) { + + if (type != "cmd-terminal") { + let sunCalcResult = calculateDuskDawn(); + params.byte1 = sunCalcResult["dusk_hours"];//h + params.byte2 = sunCalcResult["dusk_minutes"];//m + params.byte3 = 0;//s + params.byte4 = 0; + + //TODO astrohodiny + let dusk = "Time of dusk: " + sunCalcResult["dusk"]; + } + } + + //Time of dawn + if (register == 7 && params.recipient === 2) { + if (type != "cmd-terminal") { + let sunCalcResult = calculateDuskDawn(); + params.byte1 = sunCalcResult["dawn_hours"];//h + params.byte2 = sunCalcResult["dawn_minutes"];//m + params.byte3 = 0;//s + params.byte4 = 0; + + //TODO astrohodiny + let dawn = "Time of dawn: " + sunCalcResult["dawn"]; + } + + } + //----------------------- + + instance.send(SEND_TO.debug, "address: " + node + " register:" + register + "type: " + 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(node, params.recipient, params.rw, register, params.name, params.byte1, params.byte2, params.byte3, params.byte4); + let readBytes = 11; + let timeout = 4000; + + // await keyword is important, otherwise incorrect data is returned! + 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); + + //ak sa odpoved zacina 0 - je to v poriadku, inak je NOK + let message = result.message; // OK, NOK + let message_type = result.type; + let error = result.error; + + if (params.debug != "generated cmd") { + //debug("writeData: done " + message_type + " duration: " + timeDiff + " message_type: " + params.debug, params); + } + + // 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); + // } + // } + + //debug("writeData: done " + message_type + " duration: " + timeDiff + " message_type: " + params.debug); + //debug("writeData done", message_type, "duration", timeDiff, "message_type", params.debug, result); + + let values = {}; + + //CMD FINISHED + if (message == "OK") { + + updateNodeStatus(node, true); + + //write + if (type == "set_node_profile") { + let result = cmdCounterResolve(node); + if (result == 0) { + dbNodes.modify({ processed: true }).where("node", node).make(function(builder) { + builder.callback(function(err, response) { + + sendNotification("CMD Manager: process cmd", SETTINGS.rvoTbName, "dimming_profile_was_successfully_received_by_node", { node: node }, "", SEND_TO.tb, instance); + + logger.debug("--> profil úspešne odoslaný na node č. " + node); + nodesData[node].processed = true; + nodeProfileSendFail.delete(node); + }); + }); + } + } + + //parse read response + if (params.rw == 0) { + values = processResponse(register, dataBytes); //read + } + + if (itIsNodeCommand) { + values.comm_status = "OK"; + values.status = "OK"; + } + + //master node + if (node == 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; + } + + //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.debug) { + //logger.debug("saveToTb", saveToTb, tbname, values); + } + + if (saveToTb) { + sendTelemetry(values, tbname) + } + else { + if (type == "cmd-terminal") { + terminalCommandResponse(params, "SUCCESS", data); + } + } + + } + else { + + terminalCommandResponse(params, "ERROR", data) + handleNokResponseOnRsPort("handleNOK else block", params, itIsNodeCommand, saveToTb); + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + //logger.debug("writeData err: ", error, result, params); + logger.debug("writeData err: ", tbname, node, register, values); + } + } + + //logger.debug(error, result, params); + } + }).catch(function(reason) { + + console.log("writeData catch exception", reason); + instance.send(SEND_TO.debug, reason); + + terminalCommandResponse(params, "FAILURE", null, reason); + handleNokResponseOnRsPort("handleNOK catch block", params, itIsNodeCommand, saveToTb); + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + logger.debug("-->WRITE FAILED: " + reason, params.debug, params); + } + } + + }); + + } + 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); + } + + + function handleNokResponseOnRsPort(message, params, itIsNodeCommand, saveToTb) { + + let node = params.address; + let register = params.register; + let type = params.type; + let tbName = params.tbname; + if (!tbName) return; + + let values = {}; + + // console.log(message); + let updateStatus = updateNodeStatus(node, false); + + //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; + + if (register == 4) values["master_node_version"] = "NOK"; + } + + if (type == "set_node_profile") { + delete cmdCounter[node]; + logger.debug("profil nebol úspešne odoslaný na node č. ", params); + + if (!nodeProfileSendFail.has(node)) { + sendNotification("CMD Manager: process cmd", tbName, "configuration_of_dimming_profile_to_node_failed", { node: node }, "", SEND_TO.tb, instance); + nodeProfileSendFail.add(node); + } + } + + if (itIsNodeCommand) { + values.comm_status = "NOK"; + } + + 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); + }); + }); + + 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); + + instance.send(SEND_TO.debug, err.message); + }); + + rsPort.on("close", () => { + setTimeout(() => rsPort.open(), 1000); + }); + + 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.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(); + return; + } + else if (flowdata.data == "close") { + rsPort.close(); + return; + } + else if (flowdata.data == "clean") { + tasks = []; + return; + } + else if (flowdata.data == "buildtasks") { + //build & run + return; + } + else if (flowdata.data == "run") { + //durations = []; + + if (tasks.length == 0) { + + buildTasks(); + + if (rsPort.isOpen) { + interval = setInterval(runTasks, 100); + } + else { + instance.send(SEND_TO.debug, "port is not opened!!!"); + } + } + } + else { + //terminal data - object + //logger.debug("flowdata", flowdata.data); + + if (typeof flowdata.data === 'object') { + //logger.debug("dido", flowdata.data); + if (flowdata.data.hasOwnProperty("sender")) { + //data from dido_controller + if (flowdata.data.sender == "dido_controller") { + + if (flowdata.data.hasOwnProperty("cmd")) { + let cmd = flowdata.data.cmd; + + if (cmd == "buildTasks") { + clearInterval(interval); + + logger.debug("-->CMD MANAGER - BUILD TASKS"); + buildTasks(); + + //logger.debug("tasks:"); + //logger.debug(tasks); + + logger.debug("-->CMD MANAGER - RUN TASKS"); + interval = setInterval(runTasks, LONG_INTERVAL); + } + else if (cmd == "reload_relays") { + loadRelaysData(flowdata.data.line); + + if (flowdata.data.dataChanged) { + if (!flowdata.data.value) { + reportOfflineNodeStatus(flowdata.data.line); + } + else { + reportOnlineNodeStatus(flowdata.data.line); + } + } + + } + else if (cmd == "rotary_switch_state") { + let value = flowdata.data.value; + + //state was changed + if (rotary_switch_state != value) { + if (value == "Off") { + //vyreportovat vsetky svietdla + reportOfflineNodeStatus(); + } + + rotary_switch_state = value; + } + } + 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) { + + // we send lux_sensor value to all nodes: + let params = getParams(PRIORITY_TYPES.node_broadcast); + + params.recipient = 2;//2 broadcast, address = 0 + params.address = 0xffffffff;//Broadcast + + let ba = longToByteArray(lux_sensor); + + params.byte3 = ba[1];//msb + params.byte4 = ba[0]; + params.timestamp = PRIORITY_TYPES.node_broadcast; + params.info = "run broadcast: Actual Lux level from cabinet"; + params.register = 95;//Actual Lux level from cabinet + params.rw = 1;//write + + tasks.push(params); + + //process profiles + turnOnOffLinesAccordingToLuxSensor(lux_sensor); + } + } + else if (cmd == "state_of_breaker") { + //istic linie + let value = flowdata.data.value; + let line = parseInt(flowdata.data.line); + + let dataChanged = false; + if (state_of_breaker[line] != value) dataChanged = true; + + state_of_breaker[line] = value; + + let status = "OK"; + if (value == "Off") status = "NOK"; + + if (dataChanged) { + + 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"); + + //report status liniu + sendTelemetry({ status: status }, tbname) + + //current value + if (value == "Off") reportOfflineNodeStatus(line); //vyreportovat vsetky svietidla na linii + } + + } + } + else { + logger.debug("undefined cmd", cmd); + } + } + } + + return; + } + + //data from worksys + 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 command = data.params.command; + let method = data.method; + let profile = data.params.payload; + if (profile == undefined) profile = ""; + let entity = data.params.entities[0]; + let entity_type = entity.entity_type; + let tbname = entity.tb_name; + + instance.send(SEND_TO.debug, flowdata.data); + 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") { + + //let command = data.params.command; + let value = data.params.payload.value; + + if (command == "dimming") { + + let nodeWasFound = false; + let keys = Object.keys(nodesData); + + //logger.debug("-----", keys); + + 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); + + 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; + + //ak linia je + + //debug(params); + logger.debug("dimming", params); + + tasks.push(params); + + 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); + + 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); + } + + //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; + + tasks.push(params); + } + + //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; + + tasks.push(params); + } + + //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; + + tasks.push(params); + } + + }, 4000); + + + nodeWasFound = true; + + break; + } + } + + if (!nodeWasFound) { + logger.debug("set dimming from platform", "unable to find tbname", tbname); + } + } + else { + instance.send(SEND_TO.debug, "undefined command " + command); + logger.debug("undefined command", command); + } + + return; + } + 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++) { + let node = keys[i]; + if (tbname == nodesData[node].tbname) { + + 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"); + + //profil úspešne prijatý pre node č. xx + 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; + + processNodeProfile(node); + }); + }); + } + } + } + else { + + instance.send(SEND_TO.debug, "unknown method " + method); + logger.debug("unknown method", method); + + return; + } + } + + //nastav profil linie z platformy + 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") { + + 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++) { + let line = keys[i]; + if (tbname == relaysData[line].tbname) { + //zmazeme tasky + 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) { + + //update profile + 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); + + }); + }); + break; + } + } + } + else if (method == "set_command") { + let value = data.params.payload.value; + + 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; + + 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"); + } + } + else { + instance.send(SEND_TO.debug, "undefined method " + method); + logger.debug("undefined method", method); + } + + return; + } + else { + instance.send(SEND_TO.debug, "UNKNOW entity_type " + entity_type); + logger.debug("UNKNOW entity_type", entity_type); + } + return; + } + + //terminal + if (!rsPort.isOpen) await rsPort.open(); + + let params = flowdata.data.body; + if (params == undefined) { + //logger.debug("CMD manager flowdata.data.body is undefined"); + return; + } + + params.priority = PRIORITY_TYPES.terminal; + params.type = "cmd-terminal"; + params.tbname = ""; + params.timestamp = PRIORITY_TYPES.terminal; + params.addMinutesToTimestamp = 0;// do not repeat task!!! + params.debug = true; + + let timestamp = Date.now(); + params.refFlowdataKey = timestamp; + //params.refFlowdata = flowdata; + //refFlowdata = flowdata; + + //console.log("flowdata", flowdata); + + cleanUpRefFlowdataObj(); + + refFlowdataObj[timestamp] = flowdata; + + //fix + //params.address = params.adress; + logger.debug("received from terminal", params); + logger.debug("date/time:", new Date()); + logger.debug("tasks length:", tasks.length); + + //tasks = []; + + //add to tasks + tasks.push(params); + + } + } + }) + + + //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) + } + + + /** + * 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; + + RESTBuilder.make(function(builder) { + + if (!builder) return; + + builder.method('GET'); + builder.url('http://192.168.252.2:8004/gettime?projects_id=1'); + + builder.callback(function(err, response, output) { + + 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); + } + + }); + } + + } 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); + + } else { + //console.log("Read-only", stdout); + + 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]: [ + { + "ts": date, + "values": values + } + ] + } + + 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); + } + + //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); + } + } + + 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; + } + + //Dimming, CCT + if (register == 1) { + let brightness = 0; + let dimming = byte0; + if (dimming > 128) { + //dimming = -128; + brightness = dimming - 128; + } + + //cct + //Ak Byte3 == 1: CCT = (Byte2*256)+Byte1 + let cct; + if (byte3 == 1) cct = byte2 * 256 + byte1; + else cct = bytesToInt(bytes.slice(0, 3)); + + //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; + } + + 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, 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 + ")"; + } + + 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; + + } + + function getObjectByTbValue(object, tbname) { + return object[Object.keys(object).find(key => object[key].tbname === tbname)]; + } + + function isObject(item) { + return (typeof item === "object" && !Array.isArray(item) && item !== null); + } + +} // end of instance.export + diff --git a/RVO3/flow_20_01_25/code.js b/RVO3/flow_20_01_25/code.js new file mode 100755 index 0000000..63b31bf --- /dev/null +++ b/RVO3/flow_20_01_25/code.js @@ -0,0 +1,90 @@ +exports.id = 'code'; +exports.title = 'Code'; +exports.group = 'Common'; +exports.color = '#656D78'; +exports.input = true; +exports.output = 1; +exports.author = 'Peter Širka'; +exports.icon = 'code'; +exports.version = '1.2.0'; +exports.options = { outputs: 1, code: 'send(0, value);', keepmessage: true }; + +exports.html = `
+
+
+
@(Number of outputs)
+
@(Minimum is 1)
+
+
+
@(Code)
+
@(Keep message instance)
+
+`; + +exports.readme = `# Code + +This component executes custom JavaScript code as it is and it doesn't contain any secure scope. + +\`\`\`javascript +// value {Object} contains received data +// send(outputIndex, newValue) sends a new value +// error(value) sends an error +// instance {Object} a current component instance +// flowdata {Object} a current flowdata +// repository {Object} a current repository of flowdata +// Example: + +// send() can be execute multiple times +send(0, value); +\`\`\``; + +exports.install = function(instance) { + + var fn; + + instance.on('data', function(response) { + if (fn) { + try { + fn(response.data, instance, response, instance.options, response.repository, require); + } catch (e) { + response.data = e; + instance.throw(response); + } + } + }); + + instance.reconfigure = function() { + try { + if (instance.options.code) { + instance.status(''); + var code = 'var send = function(index, value) { if (options.keepmessage) { flowdata.data = value; instance.send2(index, flowdata); } else instance.send2(index, value);}; var error = function(err) { instance.throw(err); }; ' + instance.options.code; + fn = new Function('value', 'instance', 'flowdata', 'options', 'repository', 'require', code); + } else { + instance.status('Not configured', 'red'); + fn = null; + } + } catch (e) { + fn = null; + instance.error('Code: ' + e.message); + } + }; + + instance.on('options', instance.reconfigure); + instance.reconfigure(); +}; \ No newline at end of file diff --git a/RVO3/flow_20_01_25/comment.js b/RVO3/flow_20_01_25/comment.js new file mode 100755 index 0000000..1e0cd13 --- /dev/null +++ b/RVO3/flow_20_01_25/comment.js @@ -0,0 +1,11 @@ +exports.id = 'comment'; +exports.title = 'Comment'; +exports.group = 'Common'; +exports.color = '#704cff'; +exports.author = 'Martin Smola'; +exports.icon = 'comment'; +exports.traffic = false; +exports.version = '1.0.0'; +exports.readme = '# Comment'; + +exports.install = function() {}; diff --git a/RVO3/flow_20_01_25/db_connector.js b/RVO3/flow_20_01_25/db_connector.js new file mode 100755 index 0000000..65ee94b --- /dev/null +++ b/RVO3/flow_20_01_25/db_connector.js @@ -0,0 +1,286 @@ +exports.id = 'db_connector'; +exports.title = 'DbConnector'; +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.html = `
+
+
+
DbConnector
+
+
+
`; + +exports.readme = `# read/write data to tables`; + +const instanceSendTo = { + debug: 0, + http_response: 1, +} + +const { promisifyBuilder, makeMapFromDbResult } = require('./helper/db_helper.js'); + +function extractWhereParams(params) +{ + let name = params[0]; + let operator = '='; + let value = params[1]; + + if(params.length == 3) + { + operator = params[1]; + value = params[2]; + } + + return {name: name, operator: operator, value: value}; +} + +exports.install = function(instance) { + + let refFlowdata = null;//holds reference to httprequest flowdata + + instance.on("close", () => { + + }) + + + instance.on("data", async function(flowdata) { + + let params = flowdata.data.body; + console.log("DbConnector", params); + + refFlowdata = flowdata; + + if(refFlowdata != undefined) + { + //make http response + let responseObj = {}; + responseObj["type"] = "SUCESS"; + + try{ + + let table = params.table; + let action = params.action; + + + if(params.data != undefined) + { + let className = params.data.className; + + if(className == "SqlQueryBuilder") + { + let type = params.data.type; + + console.log("SqlQueryBuilder---->", params.data); + + if(type == "SELECT") + { + let table = params.data.queryData.tables[0].table; + + const db = TABLE(table); + var builder = db.find(); + + let result = await promisifyBuilder(builder); + + let response = {}; + response["result"] = result; + response["success"] = true; + + responseObj["data"] = response; + + //console.log(responseObj); + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + } + + return; + } + } + + + console.log("db_connector---->", table, action); + + //actions: read, replace, insert, delete, update... + + if(action == "read") + { + const db = TABLE(params.table); + + //where builder.where('age', '<', 15); + //builder.where('id', 3403); + + var builder = db.find(); + + //https://docs.totaljs.com/latest/en.html#api~DatabaseBuilder~builder.where + if(params.hasOwnProperty("where")) + { + //optionalCan contain "=", "<=", "<", ">=", ">". + //Default value: '=' + + //1.["production_line", 1] + //2. ["or", ["production_line", 1], ["production_line", 2], "end"] + + if (Array.isArray(params.where)) { + + let multipleConditions = false; + + if(params.where[0] == "or") multipleConditions = true; + if (Array.isArray(params.where[0])) multipleConditions = true; + + if(multipleConditions) + { + + for(var i = 0; i < params.where.length; i++) + { + const item = params.where[i]; + + if(item === "or") builder.or(); + + if (Array.isArray(item)) + { + const { name, operator, value } = extractWhereParams(item); + builder.where(name, operator, value); + } + + if(item === "end") builder.end(); + + } + + } + else + { + const { name, operator, value } = extractWhereParams(params.where); + builder.where(name, operator, value); + } + + } + + /* + if(params.where.length >=2 ) + { + let name = params.where[0]; + let operator = '='; + let value = params.where[1]; + + if(params.where.length == 3) + { + operator = params.where[1]; + value = params.where[2]; + } + + builder.where(name, operator, value); + } + */ + } + + if(params.hasOwnProperty("between")) + { + builder.between(params.between[0], params.between[1], params.between[2]); + } + + let response = await promisifyBuilder(builder); + responseObj["data"] = response; + + //console.log(responseObj); + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + + return; + } + + if(action == "delete") + { + + } + + + if(action == "update") + { + //! data receiving from terminal (params) + // { + // hostname: 'localhost', + // table: 'settings', + // action: 'update', + // body: { + // rvo_name: 'terrrr', + // lang: 'en', + // temperature_adress: '28.427B45920702', + // latitude: 48.70826502, + // longitude: 17.28455203, + // mqtt_host: '192.168.252.4', + // mqtt_clientid: 'showroom_test_panel_led', + // mqtt_username: 'xmRd6RJxW53WZe4vMFLU', + // mqtt_port: 1883, + // maintanace_mode: false + // } + // } + const tableToModify = TABLE(params.table); + const newValues = params.body; + + tableToModify.modify(newValues).make(function(builder) { + + builder.callback(function(err, response) { + + if(!err) + { + responseObj["data"] = response; + responseObj["tableUpdated"] = true; + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + } + }); + }); + + } + + if(action == "replace") + { + //truncate table + const db = TABLE(params.table); + var builder = db.remove(); + db.clean(); + + //insert data + let data = params.data; + + for(let i = 0; i < data.length; i++) + { + //console.log(data[i]); + db.insert(data[i]); + } + + console.log("insert done"); + + let responseObj = {}; + responseObj["type"] = "SUCESS"; + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + + + } + + + + } catch (error) { + //console.log(error); + responseObj["type"] = "ERROR"; + responseObj["message"] = error; + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + } + } + }) +} + + diff --git a/RVO3/flow_20_01_25/db_init.js b/RVO3/flow_20_01_25/db_init.js new file mode 100755 index 0000000..ddd0aa0 --- /dev/null +++ b/RVO3/flow_20_01_25/db_init.js @@ -0,0 +1,106 @@ +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 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 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.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 : "2025-01-09", //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"], + phases: responseSettings[0]["phases"], + cloud_topic: responseSettings[0]["cloud_topic"], + + //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/RVO3/flow_20_01_25/debug.js b/RVO3/flow_20_01_25/debug.js new file mode 100755 index 0000000..00cb259 --- /dev/null +++ b/RVO3/flow_20_01_25/debug.js @@ -0,0 +1,100 @@ +exports.id = 'debug'; +exports.title = 'Debug'; +exports.author = 'Peter Širka'; +exports.color = '#967ADC'; +exports.click = true; +exports.input = true; +exports.icon = 'bug'; +exports.version = '2.0.4'; +exports.options = { enabled: true, repository: false, type: 'data' }; +exports.readme = `# Debug + +Prints data to the debug tab.`; + +exports.html = `
+
+
+
@(Output type)
+
@(Path to the property (leave empty to show the whole data object))
+
@(A group name)
+
@(Enabled)
+
+
+
`; + +exports.install = function(instance) { + + instance.on('data', function(response) { + if (instance.options.enabled) { + + var opt = instance.options; + var rep = response.repository; + var val = response.data; + var id = response.id; + + switch (instance.options.type){ + case 'both': + var data = {}; + data.repository = rep; + data.data = val instanceof Error ? { error: val.message, stack: val.stack } : val; + instance.debug(safeparse(opt.property ? U.get(data, opt.property) : data), undefined, opt.group, id); + break; + case 'repository': + instance.debug(safeparse(opt.property ? U.get(rep, opt.property) : rep), undefined, opt.group, id); + break; + case 'data': + default: + if (val instanceof Error) + instance.debug({ error: val.message, stack: val.stack }, undefined, opt.group, id); + else + instance.debug(safeparse(opt.property ? U.get(val, opt.property) : val), undefined, opt.group, id); + break; + } + } + }); + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + instance.save(); + }); + + instance.on('options', function() { + instance.custom.status(); + }); + + instance.custom.status = function() { + instance.status(instance.options.enabled ? 'Enabled' : 'Disabled'); + }; + + instance.custom.status(); + + function safeparse(o) { + + if (o instanceof Buffer) + return o; + + if (o === undefined) + return 'undefined'; + + if (o === null) + return 'null'; + + var cache = []; + var str = JSON.stringify(o, function(key, value) { + if (typeof value === 'object' && value !== null) { + if (cache.indexOf(value) !== -1) { + try { + return JSON.parse(JSON.stringify(value)); + } catch (error) { + return; + } + } + cache.push(value); + } + return value; + }); + cache = null; + return JSON.parse(str); + } +}; diff --git a/RVO3/flow_20_01_25/designer.json b/RVO3/flow_20_01_25/designer.json new file mode 100755 index 0000000..6bb31a2 --- /dev/null +++ b/RVO3/flow_20_01_25/designer.json @@ -0,0 +1,2846 @@ +{ + "tabs": [ + { + "name": "MAIN PUSH", + "linker": "main-push", + "id": "1612772287426", + "index": 0 + }, + { + "name": "CMD manager", + "linker": "cmd-manager", + "id": "1615551125555", + "index": 1 + }, + { + "name": "Devices", + "linker": "devices", + "id": "1611921777196", + "index": 2 + } + ], + "components": [ + { + "id": "1611951142547", + "component": "debug", + "tab": "1611921777196", + "name": "ERROR", + "x": 598, + "y": 60, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#DA4453", + "notes": "" + }, + { + "id": "1612776786008", + "component": "wsmqttpublish", + "tab": "1612772287426", + "name": "WS MQTT publish", + "x": 304.75, + "y": 237, + "connections": { + "0": [ + { + "index": "0", + "id": "1615551060773" + } + ], + "1": [ + { + "index": "0", + "id": "1618300858252" + }, + { + "index": "0", + "id": "1618558465485" + } + ], + "2": [ + { + "index": "0", + "id": "1618300863816" + }, + { + "index": "0", + "id": "1634303685503" + } + ], + "3": [ + { + "index": "0", + "id": "1731068754606" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Connected", + "color": "green" + }, + "options": { + "username": "", + "clientid": "", + "port": "1883", + "host": "" + }, + "color": "#888600", + "notes": "" + }, + { + "id": "1612778461252", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "tb-push", + "x": 86.75, + "y": 375, + "connections": { + "0": [ + { + "index": "0", + "id": "1612783322136" + }, + { + "index": "1", + "id": "1612776786008" + }, + { + "index": "0", + "id": "1731068754606" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1612783322136", + "component": "debug", + "tab": "1612772287426", + "name": "to TB", + "x": 306.75, + "y": 371, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615551060773", + "component": "debug", + "tab": "1612772287426", + "name": "errors from MQTT Broker", + "x": 650, + "y": 76, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#DA4453", + "notes": "" + }, + { + "id": "1615563373927", + "component": "debug", + "tab": "1615551125555", + "name": "Debug", + "x": 753, + "y": 150, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#DA4453", + "notes": "" + }, + { + "id": "1615566865233", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "tb-push", + "x": 761, + "y": 251, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1615798582262", + "component": "debug", + "tab": "1615551125555", + "name": "CMD_debug", + "x": 765, + "y": 350, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615802995322", + "component": "debug", + "tab": "1611921777196", + "name": "Debug", + "x": 595.8833312988281, + "y": 557.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Disabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": false + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615809128443", + "component": "debug", + "tab": "1611921777196", + "name": "tempToTb", + "x": 598.8833312988281, + "y": 654.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615809595184", + "component": "virtualwireout", + "tab": "1611921777196", + "name": "tb-push", + "x": 594.8833312988281, + "y": 350.25, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1616165795916", + "component": "httproute", + "tab": "1615551125555", + "name": "POST /terminal", + "x": 114, + "y": 546, + "connections": { + "0": [ + { + "index": "0", + "id": "1684060205000" + }, + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Listening", + "color": "green" + }, + "options": { + "timeout": 10, + "cachepolicy": 0, + "cacheexpire": "5 minutes", + "size": 5, + "url": "/terminal", + "method": "POST", + "name": "", + "flags": [ + "id:1616165795916", + "post", + 10000 + ], + "emptyresponse": false + }, + "color": "#5D9CEC", + "notes": "### Configuration\n\n- __POST /terminal__\n- flags: \n- maximum request data length: __5 kB__\n- empty response: __false__\n- cache policy: __no cache__\n- cache expire: __5 minutes__", + "cloning": false + }, + { + "id": "1616165824813", + "component": "httpresponse", + "tab": "1615551125555", + "name": "HTTP Response", + "x": 772, + "y": 443, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "json" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1617104731852", + "component": "debug", + "tab": "1615551125555", + "name": "DIDO_Debug", + "x": 669, + "y": 1040, + "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": "turnOff line", + "x": 88, + "y": 1158, + "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": 669, + "y": 1150, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1617284749681", + "component": "trigger", + "tab": "1615551125555", + "name": "update profile / node", + "x": 112, + "y": 215, + "connections": { + "0": [ + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "string", + "data": "profile_nodes" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1618235171399", + "component": "trigger", + "tab": "1615551125555", + "name": "tun tasks", + "x": 119, + "y": 280, + "connections": { + "0": [ + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "data": "run" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1618300858252", + "component": "debug", + "tab": "1612772287426", + "name": "wsmqtt-exit1", + "x": 650.8833312988281, + "y": 160, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1618300863816", + "component": "debug", + "tab": "1612772287426", + "name": "wsmqtt-exit2", + "x": 845.8833312988281, + "y": 320, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1618393583970", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "to-cmd-manager", + "x": 668.8833312988281, + "y": 1269, + "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": 119.88333129882812, + "y": 369, + "connections": { + "0": [ + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "platform-rpc-call", + "color": "gray" + }, + "options": { + "wirename": "platform-rpc-call" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1618393759854", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "cmd_to_dido", + "x": 93.88333129882812, + "y": 1007, + "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": 779.8833312988281, + "y": 552, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "cmd_to_dido", + "color": "gray" + }, + "options": { + "wirename": "cmd_to_dido" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1618558465485", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "platform-rpc-call", + "x": 649.8833312988281, + "y": 246, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "platform-rpc-call", + "color": "gray" + }, + "options": { + "wirename": "platform-rpc-call" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1618572059773", + "component": "trigger", + "tab": "1615551125555", + "name": "turnOn line", + "x": 89, + "y": 1085, + "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": 452.1091003417969, + "y": 341.05455017089844, + "connections": { + "0": [ + { + "index": "0", + "id": "1615563373927" + } + ], + "1": [ + { + "index": "0", + "id": "1615566865233" + }, + { + "index": "0", + "id": "1615798582262" + } + ], + "2": [ + { + "index": "0", + "id": "1616165824813" + } + ], + "3": [ + { + "index": "0", + "id": "1618393827655" + } + ], + "4": [ + { + "index": "0", + "id": "1635936391935" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1619605019281", + "component": "httproute", + "tab": "1615551125555", + "name": "GET db", + "x": 115, + "y": 651, + "connections": { + "0": [ + { + "index": "0", + "id": "1684060205000" + }, + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Listening", + "color": "green" + }, + "options": { + "timeout": 5, + "cachepolicy": 0, + "cacheexpire": "5 minutes", + "size": 5, + "url": "/db", + "method": "GET", + "name": "", + "flags": [ + "id:1619605019281", + "get", + 5000 + ] + }, + "color": "#5D9CEC", + "notes": "### Configuration\n\n- __GET /db__\n- flags: undefined\n- maximum request data length: __5 kB__\n- empty response: __undefined__\n- cache policy: __no cache__\n- cache expire: __5 minutes__", + "cloning": false + }, + { + "id": "1619784672383", + "component": "trigger", + "tab": "1615551125555", + "name": "turnOnAlarm", + "x": 85, + "y": 1231, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "data": "{command: \"turnOnAlarm\"}", + "datatype": "object" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1619784812964", + "component": "trigger", + "tab": "1615551125555", + "name": "turnOffAlarm", + "x": 84, + "y": 1304, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "data": "{command: \"turnOffAlarm\"}", + "datatype": "object" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1621340721628", + "component": "virtualwireout", + "tab": "1611921777196", + "name": "modbus_to_dido", + "x": 596, + "y": 462, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "modbus_to_dido", + "color": "gray" + }, + "options": { + "wirename": "modbus_to_dido" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1622640022885", + "component": "httproute", + "tab": "1615551125555", + "name": "POST /db_connector", + "x": 98, + "y": 1586, + "connections": { + "0": [ + { + "index": "0", + "id": "1622640073521" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Listening", + "color": "green" + }, + "options": { + "timeout": 5, + "cachepolicy": 0, + "cacheexpire": "5 minutes", + "size": 5, + "url": "/db_connector", + "method": "POST", + "flags": [ + "id:1622640022885", + "post", + 5000 + ] + }, + "color": "#5D9CEC", + "notes": "### Configuration\n\n- __POST /db_connector__\n- flags: \n- maximum request data length: __5 kB__\n- empty response: __undefined__\n- cache policy: __no cache__\n- cache expire: __5 minutes__", + "cloning": false + }, + { + "id": "1622640073521", + "component": "db_connector", + "tab": "1615551125555", + "name": "DbConnector", + "x": 372, + "y": 1572, + "connections": { + "1": [ + { + "index": "0", + "id": "1622641420685" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "edge": "undefined" + }, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1622641420685", + "component": "httpresponse", + "tab": "1615551125555", + "name": "HTTP Response", + "x": 596, + "y": 1586, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1634303504177", + "component": "monitormemory", + "tab": "1612772287426", + "name": "RAM", + "x": 69.88333129882812, + "y": 885.5, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465281992" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "838.19 MB / 985.68 MB", + "color": "gray" + }, + "options": { + "enabled": true, + "interval": 30000 + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1634303533779", + "component": "monitordisk", + "tab": "1612772287426", + "name": "disk", + "x": 70.88333129882812, + "y": 982.5, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465821120" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "5.83 GB / 7.26 GB", + "color": "gray" + }, + "options": { + "enabled": true, + "path": "/", + "interval": 30000 + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1634303595494", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "send-to-services", + "x": 51.883331298828125, + "y": 1400.5, + "connections": { + "0": [ + { + "index": "0", + "id": "1634463186563" + }, + { + "index": "1", + "id": "1634488120710" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1634303602169", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "send-to-services", + "x": 426.8833312988281, + "y": 878.5, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1634303685503", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "send-to-services", + "x": 650.8833312988281, + "y": 355.5, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1634303743260", + "component": "httprequest", + "tab": "1612772287426", + "name": "192.168.252.2:8004/sentmessage", + "reference": "", + "x": 480.8833312988281, + "y": 1334.7333374023438, + "connections": { + "0": [ + { + "index": "0", + "id": "1635327431236" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "stringify": "json", + "method": "POST", + "url": "http://192.168.252.2:8004/sentmessage" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1634463186563", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 280.75, + "y": 1446, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634464580289", + "component": "code", + "tab": "1612772287426", + "name": "Code", + "x": 253, + "y": 788, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465243324" + }, + { + "index": "0", + "id": "1634303602169" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "keepmessage": true, + "code": "let response = {};\nresponse.cpu = value.cpu;\nresponse.uptime = value.uptime;\n\nsend(0, response);", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1634465243324", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 428, + "y": 784, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634465281992", + "component": "code", + "tab": "1612772287426", + "name": "Code", + "x": 242, + "y": 884, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465338103" + }, + { + "index": "0", + "id": "1634303602169" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "keepmessage": true, + "code": "value.sender = \"ram\";\n//let total = value.total/1024/1024;\n//let free = value.free/1024/1024;\n//let used = value.used/1024/1024;\nlet response = {};\n//value.memory_total = (total).toFixed(0) + ' MB';\n//value.memory_free = (free).toFixed(0) + ' MB';\n//value.memory_used = (used).toFixed(0) + ' MB';\n\nresponse.memory_total = value.total;\nresponse.memory_free = value.free;\nresponse.memory_used = value.used;\n\nsend(0, response);", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1634465338103", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 429, + "y": 976, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634465821120", + "component": "code", + "tab": "1612772287426", + "name": "Code", + "x": 245, + "y": 978, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465892500" + }, + { + "index": "0", + "id": "1634303602169" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "keepmessage": true, + "code": "value.sender = \"hdd\";\n//let total = value.total/1024/1024;\n//let free = value.free/1024/1024;\n//let used = value.used/1024/1024;\nlet response = {};\n//value.hdd_total = (total).toFixed(0) + ' MB';\n//value.hdd_free = (free).toFixed(0) + ' MB';\n//value.used = (used).toFixed(0) + ' MB';\n\nresponse.hdd_total = value.total;\nresponse.hdd_free = value.free;\nresponse.hdd_used = value.used;\n\nsend(0, response);", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1634465892500", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 432, + "y": 1068, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634484067516", + "component": "debug", + "tab": "1612772287426", + "name": "Send info", + "x": 480, + "y": 1441, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634488120710", + "component": "infosender", + "tab": "1612772287426", + "name": "Info sender", + "x": 285, + "y": 1338, + "connections": { + "0": [ + { + "index": "0", + "id": "1634484067516" + }, + { + "index": "0", + "id": "1634303743260" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "edge": "undefined" + }, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1635327431236", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 795.8833312988281, + "y": 1329.5, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1635936391935", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "send-to-services", + "x": 778, + "y": 656, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1637069803394", + "component": "monitorconsumption", + "tab": "1612772287426", + "name": "CPU", + "x": 69, + "y": 791, + "connections": { + "0": [ + { + "index": "0", + "id": "1634464580289" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "0.2% / 85.33 MB", + "color": "gray" + }, + "options": { + "monitorfiles": true, + "monitorconnections": true, + "monitorsize": true, + "monitorconsumption": true, + "enabled": true, + "interval": 30000 + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1683664161036", + "component": "debug", + "tab": "1615551125555", + "name": "CMDtoDIDO", + "x": 392, + "y": 1012, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1683981346282", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "from-dido-controller", + "x": 113, + "y": 456, + "connections": { + "0": [ + { + "index": "0", + "id": "1684055037116" + }, + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "from-dido-controller", + "color": "gray" + }, + "options": { + "wirename": "from-dido-controller" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1684055037116", + "component": "debug", + "tab": "1615551125555", + "name": "from dido to cmd", + "x": 448, + "y": 519, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1684060205000", + "component": "debug", + "tab": "1615551125555", + "name": "HTTP routes", + "x": 447, + "y": 620, + "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": "MDBToDido", + "x": 598, + "y": 147, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1699963668903", + "component": "dido_controller", + "tab": "1615551125555", + "name": "DIDO_Controller", + "x": 397, + "y": 1131, + "connections": { + "0": [ + { + "index": "0", + "id": "1617104731852" + } + ], + "1": [ + { + "index": "0", + "id": "1617104731852" + }, + { + "index": "0", + "id": "1617115013095" + } + ], + "2": [ + { + "index": "0", + "id": "1618393583970" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "edge": "undefined" + }, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1699964678894", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "modbus_to_dido", + "x": 96, + "y": 924, + "connections": { + "0": [ + { + "index": "0", + "id": "1699963668903" + }, + { + "index": "0", + "id": "1699964793925" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "modbus_to_dido", + "color": "gray" + }, + "options": { + "wirename": "modbus_to_dido" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1699964793925", + "component": "debug", + "tab": "1615551125555", + "name": "modbusToDido", + "x": 388, + "y": 920, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1699965957410", + "component": "modbus_reader", + "tab": "1611921777196", + "name": "Modbus reader", + "x": 232, + "y": 175, + "connections": { + "0": [ + { + "index": "0", + "id": "1611951142547" + } + ], + "1": [ + { + "index": "0", + "id": "1621340721628" + }, + { + "index": "0", + "id": "1684179110403" + }, + { + "index": "0", + "id": "1717441414646" + } + ], + "2": [ + { + "index": "0", + "id": "1615809595184" + }, + { + "index": "0", + "id": "1714752862828" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1700411878636", + "component": "thermometer", + "tab": "1611921777196", + "name": "Thermometer", + "x": 234.75, + "y": 444, + "connections": { + "0": [ + { + "index": "0", + "id": "1615802995322" + } + ], + "1": [ + { + "index": "0", + "id": "1615809595184" + }, + { + "index": "0", + "id": "1615809128443" + } + ], + "2": [ + { + "index": "0", + "id": "1621340721628" + }, + { + "index": "0", + "id": "1732889185927" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#5CB36D", + "notes": "" + }, + { + "id": "1714752862828", + "component": "debug", + "tab": "1611921777196", + "name": "MDBToTb", + "x": 599, + "y": 257, + "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": 755.0833282470703, + "y": 209, + "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": 966.0833282470703, + "y": 152, + "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": 968.0833282470703, + "y": 268, + "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": 77.75, + "y": 1630, + "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": 296, + "y": 1671, + "connections": { + "0": [ + { + "index": "0", + "id": "1718016086212" + }, + { + "index": "0", + "id": "1718016073501" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Running", + "color": "gray" + }, + "options": { + "name": "rvo_senica_3_10.0.0.119", + "types": "[\"emergency\", \"critical\", \"error\", \"alert\"]", + "message_includes": "[\"is responding again\", \"Flow has been restarted\", \"Node db has changed\"]", + "tag_on_include": "[{\"user_id\":\"U072JE5JUQG\", \"includes\":[\"Electrometer\", \"Twilight sensor\"]}]", + "slack_channel": "C071KN2Q8SK" + }, + "color": "#30E193", + "notes": "" + }, + { + "id": "1718016073501", + "component": "httprequest", + "tab": "1612772287426", + "name": "http://192.168.252.2:8004/slack", + "x": 495, + "y": 1753, + "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": 832, + "y": 1664, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "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": 79, + "y": 1723, + "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": "" + }, + { + "id": "1729855334955", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "platform-rpc-call", + "x": 649.9333343505859, + "y": 541.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "platform-rpc-call", + "color": "gray" + }, + "options": { + "wirename": "platform-rpc-call" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1729855371093", + "component": "debug", + "tab": "1612772287426", + "name": "rpc cloud", + "x": 650.9333343505859, + "y": 451.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1731068658334", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 90.75, + "y": 250, + "connections": { + "0": [ + { + "index": "0", + "id": "1612776786008" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731068754606", + "component": "cloudmqttconnect", + "tab": "1612772287426", + "name": "MQTT client - to senica-prod01", + "x": 304.75, + "y": 474, + "connections": { + "1": [ + { + "index": "0", + "id": "1729855371093" + }, + { + "index": "0", + "id": "1729855334955" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Connected", + "color": "green" + }, + "options": { + "username": "", + "clientid": "", + "port": "2764", + "host": "192.168.252.2", + "topic": "u119" + }, + "color": "#888600", + "notes": "" + }, + { + "id": "1731069001548", + "component": "db_init", + "tab": "1612772287426", + "name": "DB Initialization", + "x": 91.75, + "y": 55.25, + "connections": { + "0": [ + { + "index": "0", + "id": "1731069033416" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#888600", + "notes": "" + }, + { + "id": "1731069033416", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "db-init", + "x": 343.75, + "y": 50.25, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069059135", + "component": "showdb", + "tab": "1612772287426", + "name": "Show db data", + "x": 1121.75, + "y": 814.25, + "connections": { + "0": [ + { + "index": "0", + "id": "1731069079243" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#888600", + "notes": "" + }, + { + "id": "1731069079243", + "component": "debug", + "tab": "1612772287426", + "name": "dbData", + "x": 1315.75, + "y": 853.25, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1731069116691", + "component": "trigger", + "tab": "1612772287426", + "name": "settings", + "x": 911.75, + "y": 710.75, + "connections": { + "0": [ + { + "index": "0", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069131637", + "component": "trigger", + "tab": "1612772287426", + "name": "relaysData", + "x": 832.75, + "y": 775.75, + "connections": { + "0": [ + { + "index": "1", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069137374", + "component": "trigger", + "tab": "1612772287426", + "name": "nodesData", + "x": 747.75, + "y": 840.75, + "connections": { + "0": [ + { + "index": "2", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069179846", + "component": "trigger", + "tab": "1612772287426", + "name": "pinsData", + "x": 803.75, + "y": 899.75, + "connections": { + "0": [ + { + "index": "3", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069192937", + "component": "trigger", + "tab": "1612772287426", + "name": "sample data", + "x": 858.75, + "y": 959.75, + "connections": { + "0": [ + { + "index": "4", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069264443", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 63.75, + "y": 1279, + "connections": { + "0": [ + { + "index": "0", + "id": "1634488120710" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069334626", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "db-init", + "x": 151.88333129882812, + "y": 148, + "connections": { + "0": [ + { + "index": "0", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069548145", + "component": "virtualwirein", + "tab": "1611921777196", + "name": "db-init", + "x": 46.75, + "y": 192, + "connections": { + "0": [ + { + "index": "0", + "id": "1699965957410" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069567152", + "component": "virtualwirein", + "tab": "1611921777196", + "name": "db-init", + "x": 44.75, + "y": 465, + "connections": { + "0": [ + { + "index": "0", + "id": "1700411878636" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731070156936", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "db-init", + "x": 89.88333129882812, + "y": 1381, + "connections": { + "0": [ + { + "index": "2", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731234189516", + "component": "trigger", + "tab": "1612772287426", + "name": "monitor.txt", + "x": 915.75, + "y": 1017.75, + "connections": { + "0": [ + { + "index": "5", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731234189551", + "component": "trigger", + "tab": "1612772287426", + "name": "err.txt", + "x": 966.75, + "y": 1080.75, + "connections": { + "0": [ + { + "index": "6", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1732700042559", + "component": "nodesdb_change_check", + "tab": "1612772287426", + "name": "Nodes DB change check", + "x": 263.8833312988281, + "y": 1993.2333984375, + "connections": { + "0": [ + { + "index": "0", + "id": "1732700071298" + }, + { + "index": "0", + "id": "1732700642917" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#888600", + "notes": "" + }, + { + "id": "1732700057052", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 84.75, + "y": 1994, + "connections": { + "0": [ + { + "index": "0", + "id": "1732700042559" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1732700071298", + "component": "debug", + "tab": "1612772287426", + "name": "nodesChange", + "x": 561.8833312988281, + "y": 2055.2333984375, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1732700642917", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "tb-push", + "x": 557.8833312988281, + "y": 1949, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1732889185927", + "component": "debug", + "tab": "1611921777196", + "name": "tempToDido", + "x": 594.8833312988281, + "y": 745, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1733574412965", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 86.75, + "y": 495, + "connections": { + "0": [ + { + "index": "1", + "id": "1731068754606" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + } + ], + "version": 615 +} \ No newline at end of file diff --git a/RVO3/flow_20_01_25/dido_controller.js b/RVO3/flow_20_01_25/dido_controller.js new file mode 100755 index 0000000..8415921 --- /dev/null +++ b/RVO3/flow_20_01_25/dido_controller.js @@ -0,0 +1,1524 @@ +exports.id = 'dido_controller'; +exports.title = 'DIDO_Controller'; +exports.version = '2.0.0'; +exports.group = 'Worksys'; +exports.color = '#2134B0'; +exports.input = 3; +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 { 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 +} + + +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 = {}; + 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"); + + //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 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 + }; + + + function main() { + + GLOBALS = FLOW.GLOBALS; + SETTINGS = FLOW.GLOBALS.settings; + rvoTbName = SETTINGS.rvoTbName; + pinsData = GLOBALS.pinsData; + relaysData = GLOBALS.relaysData; + + 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"; + + 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, "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; + turnLine("off", 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; + + sendTelemetry(values, rvoTbName); + + 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) { + if (!err) { + monitor.info(exports.title + "--->Digital in_out has been set (runSyncExec was sucessfull)"); + + turnAlarm("off"); + 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() { + + //to keep websocket opened, we send request every 150 seconds + let startRequests = null; + + console.log("handleWebSocket function called"); + ws = new WebSocket('ws:/0.0.0.0:1234/ws'); + + ws.onopen = function open() { + + instance.send(0, exports.title + " running"); + turnAlarm("off"); + + // useTurnOffCounter = true; + // turnOffCounter = relaysData.length - 1; + initialSetting(); + ws.send(JSON.stringify({ "cmd": "all" })); + + // we request dev info about neuron device from evok to keep websocket connection alive + // for some reason this request returns no data, but connection keeps alive + // https://evok.api-docs.io/1.0/mpqzDwPwirsoq7i5A/websocket + startRequests = setInterval(() => { + // console.log(" *** data from evok requested"); + ws.send(JSON.stringify({ "cmd": "filter", "dev": ["neuron"] })); + }, 150000) + }; + + + // 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 = async 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; + + 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) => { + monitor.info('websocket error, reconnect') + instance.send(SEND_TO.debug, err.message); + clearInterval(startRequests); + ws = null; + setTimeout(handleWebSocket, 1000); + }) + + + ws.onclose = function() { + // connection closed, discard old websocket and create a new one in 5s + // stopRequests(); + monitor.info('websocket onclose, reconnect') + clearInterval(startRequests); + ws = null; + console.log("ws is null now, reconnecting..."); + setTimeout(handleWebSocket, 1000); + } + } + + 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 turnAlarm(onOrOff) { + let value = 0; + if (onOrOff == "on") value = 1; + + if (value == 1 && SETTINGS.maintenance_mode) return; + + alarmStatus = "OFF"; + if (value == 1) alarmStatus = "ON"; + + if (rsPort) { + let arr = [0x55]; + arr.push(13); + arr.push(0); + arr.push(value); + + rsPort.write(Buffer.from(arr), function(err) { + logger.debug(`sirena - ${onOrOff}`); + }); + } + else if (ws) { + let cmd = { "cmd": "set", "dev": "relay", "circuit": "1_01", "value": value }; + ws.send(JSON.stringify(cmd)); + logger.debug(`sirena - ${onOrOff}`); + } + } + + + 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") { + bits.push(0); + } + else bits.push(1); + + if (deviceStatus["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); + } + + + // turn line on or off + function turnLine(onOrOff, line, pin, force, info) { + //onOrOff => "on" or "off" + let value = 0; + if (onOrOff == "on") value = 1; + + if (force == undefined) force = false; + + if (line == 0) { + if (value == 1 && alarmStatus == "ON") turnAlarm("off"); + SETTINGS.maintenance_mode = value ? true : false; + + 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); + return; + } + + if (pin === undefined) pin = getPin(line); + + if (pin === undefined) { + errLogger.error("pin is undefined!", line); + return; + } + + if (!force) { + if (relaysData[line].contactor == value) { + instance.send(SEND_TO.debug, `line is already ${onOrOff} ` + line); + logger.debug(`turnLine: line is already ${onOrOff} `, 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(value); + + rsPort.write(Buffer.from(arr), function(err) { + if (err === undefined) { + monitor.info(`turnLine ${onOrOff} zapisal do rsPort-u`, line, pin, arr, info); + switchLogic(arr); + } + else { + monitor.info(`turnLine ${onOrOff} 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 }; + ws.send(JSON.stringify(cmd)); + switchLogic(pin, value) + } + + //if rvo is 24/7, it has just one switching profile point at 13:00. we do not want to send notification as it repeats every day. + //const d = new Date(); + //if(d.getHours() != 13) sendNotification("Dido_controller: ", SETTINGS.rvoTbName, "switching_profile_point_applied_to_line", { line: line, value: onOrOff }, "", SEND_TO.tb, instance); + } + + + // 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; + + // 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) { + const status = flowdata.data.status; + if (status == "NOK-twilight_sensor") { + deviceStatus["twilight_sensor"] = "NOK"; + } + else if (status == "NOK-em340" || status == "NOK-em111") { + deviceStatus["em"] = "NOK"; + } + else if (status == "NOK-thermometer") { + deviceStatus["temperature"] = "NOK"; + } + } + else if ("values" in flowdata.data) { + 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" + } + else if (values.hasOwnProperty("temperature")) { + deviceStatus["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"; + } + + sendTelemetry(values, rvoTbName); + } + + sendRvoStatus(); + }) + + + // we expect array as flowdata.data + instance.on("1", flowdata => { + + console.log(flowdata.data); + + if (!flowdata.data instanceof Object) return; + + let obj = flowdata.data; + let line = obj.line; + 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"); + + //! ake data prichadzaju z cmd_manager.js ??? + //TODO transform to websocket + if (Array.isArray(obj)) { + + rsPort.write(Buffer.from(obj), function(err) { + switchLogic(obj); + + instance.send(SEND_TO.debug, { "WRITE": obj }); + }); + } + }) + + + function calculateStateCode() { + + 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") { + bits.push(0); + } + else { + bits.push(1); + } + + //Prevádzkový mód - Manual, Off, Automatic, maintenance_mode = true/false // DAVA 2 BITY + if (!SETTINGS.maintenance_mode) { + if (deviceStatus["rotary_switch_state"] == "Manual") { + bits.push(0); + bits.push(1); + } + + if (deviceStatus["rotary_switch_state"] == "Automatic") { + bits.push(0); + bits.push(0); + } + + if (deviceStatus["rotary_switch_state"] == "Off") { + bits.push(1); + bits.push(0); + } + } + else { + bits.push(1); + bits.push(1); + } + + //Dverový kontakt + if (deviceStatus["door_condition"] == "closed") { + bits.push(0); + } + else { + bits.push(1); + } + + //EM + if (deviceStatus["em"] == "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //Teplomer + if (deviceStatus["temperature"] == "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //Batéria + if (deviceStatus["battery"] == "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //Zdroj + if (deviceStatus["power_supply"] == "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //MN + if (deviceStatus["master_node"] == "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //výpadok napätia na fáze + if (deviceStatus["no_voltage"] == "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + if (deviceStatus["twilight_sensor"] == "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + // doplnime do 16 bitov (2 byty) + for (let i = bits.length; i < 16; i++) { + bits.push(0); + } + + // console.log("calculateStateCode - deviceStatus", deviceStatus); + // 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; + } + + + async function sendRvoStatus() { + + if (SETTINGS === undefined) return; + SETTINGS.masterNodeIsResponding ? deviceStatus["master_node"] = "OK" : deviceStatus["master_node"] = "NOK"; + + 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() { + + // 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 + //set RVO state + let status = "OK"; + + for (const [key, value] of Object.entries(deviceStatus)) { + if (["em", "twilight_sensor", "temperature", "master_node"].includes(key) && value == "NOK") status = "NOK"; + } + + if (status == "OK") { + let pinIndexes = [1, 4, 6]; + if (controller_type == 'unipi') pinIndexes = ['input1_01', 'input1_04', 'input1_05']; + + for (const pinIndex of pinIndexes) { + if (previousValues[pinIndex] === 0) { + if ((pinIndex === 6 || pinIndex === 'input1_01' || pinIndex === 'input1_05') && SETTINGS.maintenance_mode) continue; + status = "NOK"; + break; + } + } + } + + // battery status. If value is 1 - battery is NOK + if (previousValues[5] === 1) status = "NOK"; + if (SETTINGS.no_voltage.size > 0) status = "NOK"; + + // console.log("rvo status",status) + return status; + } + + + // we pass array to function in case of rsPort ==> switchLogic([55,3,0,1]) ==> [[55,3,0,1]] + // we pass two values in case of websocket ==> switchLogic("relay1_03",1) ==> ["relay1_03",1] + const switchLogic = (...args) => { + + let values = {}; + let pinIndex, newPinValue, twilight; + + //data from rsPort + if (args.length == 1) { + pinIndex = args[0][1] + 1; + if (pinIndex === 17) pinIndex--; + newPinValue = args[0][3]; + twilight = args[0][2]; + } + //data from websocket + else { + pinIndex = args[0]; + newPinValue = args[1]; + } + + 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; + + //default value + let value = "On"; + if (newPinValue === 0) value = "Off"; + + //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"; + + // 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"); + + // deviceStatus["state_of_main_switch"] = "On"; + // } + // } + + //Prevádzkový mód + 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"; + + deviceStatus["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, "power_supply_has_disconnected_input", {}, "", SEND_TO.tb, instance, "power_supply"); + + deviceStatus["power_supply"] = "NOK"; + } + else if (newPinValue === 1 && newPinValue !== previousValues[pinIndex]) { + sendNotification("switchLogic", rvoTbName, "power_supply_works_correctly", {}, "", SEND_TO.tb, instance, "power_supply"); + + deviceStatus["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"); + + deviceStatus["battery"] = "NOK"; + } + else if (newPinValue === 0 && newPinValue !== previousValues[pinIndex]) { + sendNotification("switchLogic", rvoTbName, "battery_level_is_ok", {}, "", SEND_TO.tb, instance, "battery_level"); + + deviceStatus["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' + else if (type == "door_condition" || type === "state_of_main_switch") { + newPinValue === 0 ? value = "open" : value = "closed"; + + 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, "door_opened_without_permission", {}, "", SEND_TO.tb, instance, "rvo_door"); + + // 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 (value === "closed") { + if (alarmStatus == "ON") turnAlarm("off"); + sendNotification("switchLogic", rvoTbName, "door_closed", {}, "", SEND_TO.tb, instance, "rvo_door"); + } + + deviceStatus[type] = value; + } + + //lux sensor + else if (type == "twilight_sensor") { + //! TODO - to show nok status, if lux value is not changing more then 10 times. + //Daylight is far more than 1000. So most of the day, when it is sunshine comes just value 1000. But lux sensor is not NOK. + //This is not the case in LM. If value from LM is the same 10x, there is 99% possibility, that sensor is NOK. + value = newPinValue; + + if (controller_type === 'lm') { + value = parseFloat(newPinValue + (256 * twilight)); + + 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 && !twilightError) { + twilightError = true; + let value = twilight_sensor_array.shift(); + + newPinValue = 0; + } + else if (set.size !== 1 && twilightError) { + //sendNotification("switchLogic", rvoTbName, 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) { + 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); + } + } + + 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); + } + + deviceStatus["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) + // { + // let time = 0; + // if(value) time = 1000 * 10;//10 sekund + + // let dataChanged = false; + // if(relaysData[line].contactor != newPinValue) dataChanged = true; + // relaysData[line].contactor = newPinValue; // 0,1 + + // //ak bola predchadzajuci stav off a novy stav je on, budu sa nastavovat nespracovane node profiles + // //a budu sa odosielat commandy, tie vsak mozu zlyhat, a preto potrebujeme ich spusti trochu neskor + // setTimeout(function(){ + // instance.send(SEND_TO.cmd_manager, {sender: "dido_controller", cmd: "reload_relays", line: line, time: time, value: value, dataChanged: dataChanged}); + // }, time); + + // reportLineStatus(line); + // } + // else + // { + // errLogger.error("modify table relays failed", err); + // } + + // }); + // }); + } + + 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 }); + + //mame iba 3 istice. vyreportujeme a ohandlujeme liniu na tom istom istici ako paralelna linia (napr linia 1, paralelna s nou je linia 4, key je string "4") + // ak je 7 linii, na 1 istici je linia 1,4,7 + + if (line == 1) { + + const lineOnSameBraker = [4, 7]; + + for (var i = 0; i < lineOnSameBraker.length; i++) { + if (!relaysData.hasOwnProperty(lineOnSameBraker[i])) continue; + + 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; + reportLineStatus(lineOnSameBraker[i]); + + values[type] = value; + const tbname = relaysData[lineOnSameBraker[i]].tbname; + sendTelemetry(values, tbname); + + delete values[type]; + } + + } + else { + const lineOnSameBraker = line + 3 + ""; + + if (relaysData.hasOwnProperty(lineOnSameBraker)) { + 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; + reportLineStatus(line + 3); + + values[type] = value; + const tbname = relaysData[lineOnSameBraker].tbname; + sendTelemetry(values, tbname); + + delete values[type]; + } + } + + } + + if (value == "Off") values["status"] = "NOK"; + deviceStatus["state_of_breaker"][line] = value; + + reportLineStatus(line); + } + else return; + + values[type] = value; + + if (type == "rotary_switch_state") { + if (SETTINGS.maintenance_mode) value = "maintenance"; + value = value.toLowerCase(); + values["power_mode"] = value; + } + + if (newPinValue != previousValues[pinIndex]) previousValues[pinIndex] = newPinValue; + if (Object.keys(values).length > 0 && tbname) sendTelemetry(values, tbname); + } + + + function sendTelemetry(values, tbname, date = Date.now()) { + let dataToTb = { + [tbname]: [ + { + "ts": date, + "values": values + } + ] + }; + + tbHandler.sendToTb(dataToTb, instance); + } + + + function isObject(item) { + return (typeof item === "object" && !Array.isArray(item) && item !== null); + } + +} //end of 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 +// *|input1_01|state_of_main_switch|0|........... +// *|input1_02|rotary_switch_state|0|........... +// *|input1_03|rotary_switch_state|0|........... +// *|intut1_04|power_supply|0|........... +// *|input1_05|door_condition|0|........... +// *|input1_06|state_of_breaker|1|........... +// *|input1_07|state_of_breaker|2|........... +// *|input1_08|state_of_breaker|3|........... +// *|relay1_02|state_of_contactor|1|........... +// *|relay1_03|state_of_contactor|2|........... +// *|relay1_04|state_of_contactor|3|........... +// *|287D8776E0013CE9|temperature|0|........... + + +//! pins_data --> from UNIPI +// { +// 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 } +// } + +//! relays_data +// { +// '0': { +// line: 0, +// tbname: 'KjbN4q7JPZmexgdnz2yKQ98YAWwO0Q3BMX6ERLoV', +// contactor: 1, +// profile: '' +// }, +// '1': { +// line: 1, +// tbname: 'RMgnK93rkoAazbqdQ4yBG95Z1YXGx6pmwBeVEP2O', +// contactor: 0, +// profile: '{"intervals":[{"value":0,"end_time":"20:00","start_time":"13:00"},{"value":1,"end_time":"10:00","start_time":"20:00"},{"value":0,"end_time":"10:20","start_time":"10:00"},{"value":1,"end_time":"10:40","start_time":"10:20"},{"value":0,"end_time":"11:00","start_time":"10:40"},{"value":1,"end_time":"11:30","start_time":"11:00"},{"value":0,"end_time":"11:50","start_time":"11:30"},{"value":1,"end_time":"13:00","start_time":"11:50"}],"astro_clock":false,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' +// }, +// '2': { +// line: 2, +// tbname: 'dlE1VQjYrNx9gZRmb38gG08oLBO4qaAk2M6JPnG7', +// contactor: 0, +// profile: '{"intervals":[{"value":0,"end_time":"20:00","start_time":"13:00"},{"value":1,"end_time":"10:00","start_time":"20:00"},{"value":0,"end_time":"10:20","start_time":"10:00"},{"value":1,"end_time":"10:40","start_time":"10:20"},{"value":0,"end_time":"11:00","start_time":"10:40"},{"value":1,"end_time":"11:30","start_time":"11:00"},{"value":0,"end_time":"11:50","start_time":"11:30"},{"value":1,"end_time":"13:00","start_time":"11:50"}],"astro_clock":false,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' +// }, +// '3': { +// line: 3, +// tbname: 'vnmG4kJxaXWNBgMQq0D7Aj5e9oZzOAlr6LdR3w2V', +// contactor: 0, +// profile: '{"intervals":[{"value":0,"end_time":"20:30","start_time":"13:00"},{"value":1,"end_time":"00:10","start_time":"20:30"},{"value":0,"end_time":"13:00","start_time":"05:40"},{"value":1,"end_time":"05:40","start_time":"00:10"}],"astro_clock":true,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' +// } +// } + + + + + +// { +// "jbN4q7JPZmexgdnz2yKbWGDYAWwO0Q3BMX6ERLoV": [ +// { +// "ts": 1700409326353, +// "values": { +// "_event": { +// "type": "notice", +// "status": "new", +// "source": { +// "func": "rsPort.open()", +// "component": "1700343402190", +// "component_name": "DIDO_Controller", +// "edge": "jbN4q7JPZmexgdnz2yKbWGDYAWwO0Q3BMX6ERLoV" +// }, +// "message": "al_shariff_10.0.0.38: FLOW has been started ", +// "message_data": "" +// } +// } +// } +// ] +// } diff --git a/RVO3/flow_20_01_25/helper/DataToTbHandler.js b/RVO3/flow_20_01_25/helper/DataToTbHandler.js new file mode 100755 index 0000000..65e4ec3 --- /dev/null +++ b/RVO3/flow_20_01_25/helper/DataToTbHandler.js @@ -0,0 +1,166 @@ +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; + + this.sender = ""; + + // if attribute difference is less than limit value, we do not send to tb. + this.attributeChangeLimit = { + temperature: 0.5, + Phase_1_voltage: 2, + Phase_2_voltage: 2, + Phase_3_voltage: 2, + Phase_1_current: 0.1, + Phase_2_current: 0.1, + Phase_3_current: 0.1, + Phase_1_power: 2, + Phase_2_power: 2, + Phase_3_power: 2, + total_power: 2, + Phase_1_pow_factor: 0.1, + Phase_2_pow_factor: 0.1, + Phase_3_pow_factor: 0.1, + power_factor: 0.1, + lifetime: 0.5, + voltage: 2, + power: 2, + frequency: 3, + energy: 0.1, + current: 2, + inclination_x: 10, + inclination_y: 10, + inclination_z: 10 + }; + } + + dump() { + console.log("----------------------------"); + console.log("previousValues", this.previousValues); + console.log("----------------------------"); + } + + setSender(sender) { + this.sender = sender; + } + + isEmptyObject(obj) { + for (var name in obj) { + return false; + } + return true; + } + + sendToTb(dataToTb, instance) { + + let keys = Object.keys(dataToTb); + + if(keys.length == 0) + { + if(this.debug) console.log("sendToTb received empty object", dataToTb); + return; + } + + let tbname = keys[0]; + let ts; + + let arrayOfValues = dataToTb[tbname]; + let arrayOfValuesToSend = []; + + for(let i = 0; i < arrayOfValues.length; i++) + { + ts = arrayOfValues[i].ts; + let values = this.prepareValuesForTb(tbname, ts, arrayOfValues[i].values); + + if(!this.isEmptyObject(values)) + { + arrayOfValuesToSend.push({ts: ts, values: values}); + } + } + + if(arrayOfValuesToSend.length == 0) + { + //if(this.debug) console.log("data not sent - empty array"); + return; + } + + this.messageCounter++; + + let dataToTbModified = { + [tbname]: arrayOfValuesToSend + } + + //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); + instance.send(this.index, dataToTbModified); + } + + getDiffTimestamp(key) { + //TODO set different value for given key!!! + //if(key == "status") this.timeToHoldTbValue = 2*60*60;//2h + return this.timeToHoldTbValue * 1000; + } + + prepareValuesForTb(tbname, timestamp, values) { + + let keys = Object.keys(values); + if(!this.previousValues.hasOwnProperty(tbname)) + { + this.previousValues[tbname] = {}; + } + + //if(this.debug) console.log("prepareValuesForTb", tbname, timestamp, values); + + for(let i = 0; i < keys.length; i++) + { + let key = keys[i]; + let value = values[key]; + + if(!this.previousValues[tbname].hasOwnProperty(key)) + { + this.previousValues[tbname][key] = {ts: timestamp, value: value}; + continue; + } + + // attributeData ==> voltage: {ts:333333, value:5} + let attributeData = this.previousValues[tbname][key]; + let attributeToChange = false; + if(key in this.attributeChangeLimit) attributeToChange = true; + let limit = this.attributeChangeLimit[key]; + + if(attributeData.value === value || attributeToChange && Math.abs(attributeData.value - value) < limit) + { + let diff = timestamp - attributeData.ts; + let timestampDiffToRemoveKey = this.getDiffTimestamp(key); + if(diff > timestampDiffToRemoveKey) + { + attributeData.ts = Date.now(); + //if(this.debug) console.log(this.sender + ": update ts for key", key, "diff is", diff, "messageCounter", this.messageCounter); + } + else + { + delete values[key]; + //if(this.debug) console.log(this.sender + ": delete key", key, "diff is", diff, "messageCounter", this.messageCounter, timestampDiffToRemoveKey); + } + } + else + { + attributeData.value = value; + attributeData.ts = timestamp; + } + + } + + return values; + } +} + +module.exports = DataToTbHandler; + diff --git a/RVO3/flow_20_01_25/helper/ErrorToServiceHandler.js b/RVO3/flow_20_01_25/helper/ErrorToServiceHandler.js new file mode 100755 index 0000000..110ea8b --- /dev/null +++ b/RVO3/flow_20_01_25/helper/ErrorToServiceHandler.js @@ -0,0 +1,126 @@ +const { MD5 } = require('./md5.js'); +const { networkInterfaces } = require('os'); + +class ErrorToServiceHandler +{ + constructor() { + this.previousValues = {}; + + this.projects_id = undefined; + + const nets = networkInterfaces(); + this.ipAddresses = Object.create(null); // Or just '{}', an empty object + + for (const name of Object.keys(nets)) { + for (const net of nets[name]) { + // Skip over non-IPv4 and internal (i.e. 127.0.0.1) addresses + if (net.family === 'IPv4' && !net.internal) { + if (!this.ipAddresses[name]) { + this.ipAddresses[name] = []; + } + this.ipAddresses[name].push(net.address); + } + } + } + + //console.log(this.ipAddresses); + + } + + setProjectsId(projects_id) + { + this.projects_id = projects_id; + } + + processMessage(message, seconds, message_type) + { + if(message_type == undefined) message_type = "error_message"; + if(Array.isArray(message)) message = message.join(', '); + + let key = MD5(message); + let timestamp = new Date().getTime(); + + //keep in memory - default value is 1h + if (seconds === undefined) seconds = 60*60; + + if(!this.previousValues.hasOwnProperty(key)) + { + this.previousValues[key] = {ts: timestamp, duration: seconds}; + } + + let diff = (timestamp - this.previousValues[key].ts); + if(diff < this.previousValues[key].duration*1000) return false; + + this.previousValues[key].ts = timestamp; + + return true; + } + + sendMessageToService(message, seconds, message_type) + { + + let f = this.processMessage(message, seconds, message_type); + if(!f) return; + + /* + //------------- + if(message_type == undefined) message_type = "error_message"; + if(Array.isArray(message)) message = message.join(', '); + + let key = MD5(message); + let timestamp = new Date().getTime(); + + //keep in memory + if (seconds === undefined) seconds = 60*60; + + if(!this.previousValues.hasOwnProperty(key)) + { + this.previousValues[key] = {ts: timestamp, duration: seconds}; + } + + let diff = (timestamp - this.previousValues[key].ts); + if(diff < this.previousValues[key].duration*1000) return; + + this.previousValues[key].ts = timestamp; + */ + + //------------------------- + + //send to service + + let dataToInfoSender = {id: this.projects_id}; + + //js_error || error_message + dataToInfoSender[message_type] = message; + dataToInfoSender.ipAddresses = this.ipAddresses; + + 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) + { + console.log("this.projects_id is undefined"); + return; + } + */ + + RESTBuilder.make(function(builder) { + builder.method('POST'); + builder.post(dataToInfoSender); + builder.url('http://192.168.252.2:8004/sentmessage'); + + builder.callback(function(err, response, output) { + console.log("process.on error send", err, response, output, dataToInfoSender); + }); + }); + + + } +} + +module.exports = ErrorToServiceHandler; \ No newline at end of file diff --git a/RVO3/flow_20_01_25/helper/db_helper.js b/RVO3/flow_20_01_25/helper/db_helper.js new file mode 100755 index 0000000..40e796c --- /dev/null +++ b/RVO3/flow_20_01_25/helper/db_helper.js @@ -0,0 +1,44 @@ +function promisifyBuilder(builder) +{ + return new Promise((resolve, reject) => { + + try{ + + builder.callback(function(err, response) { + + if(err != null) reject(err); + resolve(response); + }); + + } catch (error) { + reject(error); + } + }) +} + +function makeMapFromDbResult(response, ...keys) +{ + let s = "-"; + let data = {}; + + for(let i = 0; i < response.length; i++) + { + let record = response[i]; + + let k = []; + for(let j = 0; j < keys.length; j++) + { + k.push( record[keys[j]] ); + } + + let key = k.join(s); + data[ key ] = record; + } + + return data; +} + +module.exports = { + promisifyBuilder, + makeMapFromDbResult + } \ No newline at end of file diff --git a/RVO3/flow_20_01_25/helper/logger.js b/RVO3/flow_20_01_25/helper/logger.js new file mode 100755 index 0000000..2585639 --- /dev/null +++ b/RVO3/flow_20_01_25/helper/logger.js @@ -0,0 +1,30 @@ +//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/RVO3/flow_20_01_25/helper/md5.js b/RVO3/flow_20_01_25/helper/md5.js new file mode 100755 index 0000000..d3b0480 --- /dev/null +++ b/RVO3/flow_20_01_25/helper/md5.js @@ -0,0 +1,5 @@ +function MD5(d){var r = M(V(Y(X(d),8*d.length)));return r.toLowerCase()};function M(d){for(var _,m="0123456789ABCDEF",f="",r=0;r>>4&15)+m.charAt(15&_);return f}function X(d){for(var _=Array(d.length>>2),m=0;m<_.length;m++)_[m]=0;for(m=0;m<8*d.length;m+=8)_[m>>5]|=(255&d.charCodeAt(m/8))<>5]>>>m%32&255);return _}function Y(d,_){d[_>>5]|=128<<_%32,d[14+(_+64>>>9<<4)]=_;for(var m=1732584193,f=-271733879,r=-1732584194,i=271733878,n=0;n>16)+(_>>16)+(m>>16)<<16|65535&m}function bit_rol(d,_){return d<<_|d>>>32-_} + +module.exports = { + MD5 +} \ No newline at end of file diff --git a/RVO3/flow_20_01_25/helper/notification_reporter.js b/RVO3/flow_20_01_25/helper/notification_reporter.js new file mode 100755 index 0000000..61c0aef --- /dev/null +++ b/RVO3/flow_20_01_25/helper/notification_reporter.js @@ -0,0 +1,131 @@ +//key is device, value = str +let sentValues= {}; +let notificationsData = null; + +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 +}; + +function getKey(map, val) { + return Object.keys(map).findItem(key => map[key] === val); +} + +//https://stackoverflow.com/questions/41117799/string-interpolation-on-variable +var template = (tpl, args) => tpl.replace(/\${(\w+)}/g, (_, v) => args[v]); + + +function initNotification() { + notificationsData = FLOW.GLOBALS.notificationsData; +} + +function sendNotification(func, device, key, params, extra, tb_output, instance, saveKey) { + + // return; + + let storeToSendValues = true; + if(saveKey == undefined) storeToSendValues = false; + + let lang = FLOW.GLOBALS.settings.language; + if(lang != "en" || lang != "sk") lang = "en"; + + let tpl = key; + let weight = ""; + + if(notificationsData[key]) + { + weight = notificationsData[key].weight; + weight = weight.toLowerCase(); + + tpl = notificationsData[key][lang]; + tpl = template(tpl, params); + } + else + { + //console.error("sendNotification: Notifications: undefined key", key, func, notificationsData); + console.error("sendNotification: Notifications: undefined key", key, func ); + return false; + } + + //detect invalid err weight + if(getKey(ERRWEIGHT, weight) == undefined) + { + console.error("sendNotification: Notifications: undefined weight", weight, key, func); + return false; + } + + if(sentValues.hasOwnProperty(saveKey)) + { + if(sentValues[saveKey] == tpl) + { + return false; + } + } + + if(sentValues[saveKey] == undefined) + { + if(storeToSendValues) + { + //do not send - flow is was started + sentValues[saveKey] = tpl; + return false; + } + } + + if(saveKey == "rvo_door") + { + //console.log("******", saveKey, sentValues[saveKey], tpl); + } + + if(storeToSendValues) sentValues[saveKey] = tpl; + + let str = FLOW.GLOBALS.settings.rvo_name; + if(str != "") str = str + ": "; + str = str + tpl; + + 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 + + return true; + +} + +module.exports = { + sendNotification, + ERRWEIGHT, + initNotification +} diff --git a/RVO3/flow_20_01_25/helper/register.js b/RVO3/flow_20_01_25/helper/register.js new file mode 100755 index 0000000..fc1d008 --- /dev/null +++ b/RVO3/flow_20_01_25/helper/register.js @@ -0,0 +1,144 @@ +/* +0 - cislo registra / prikaz +1 - recepient - 0 = master, 1 = slave (slave je automaticky group a broadcast) +2 - r/rw - read/write +3- register name - nazov registra / prikazu (len pre info - zobrazenie v aplikacii) + +4,5,6,7, - jednotlive byte-y - nazov byte-u +4-7 - RES. a prazdny string "" sa nezobrazia!!! +*/ + +//124 zaznamov +const registers = [ + ["0","1","R","Status","","",""], + ["1","1","RW","Dimming","R-Channel ","G-Channel","B-Channel ","W - Channel"], + ["2","1","R","Device types","","",".",""], + ["3","1","RW","Group addresses 1-4","Groups Add. 4","Groups Add. 3","Groups Add. 2","Groups Add. 1"], + ["4","1","RW","Group addresses 5-8","Groups Add. 8","Groups Add. 7","Groups Add. 6","Groups Add. 5"], + ["5","1","RW","Serial number (MAC)","","","",""], + ["6","1","RW","Time of dusk","HH","MM","SS","EXTRA"], + ["7","1","RW","Time of dawn","HH","MM","SS","EXTRA"], + ["8","1","RW","Time Schedule settings","TBD","TBD","Movement sensor","Time Schedule"], + ["9","1","RW","TS1 Time point 1","HH","MM","SS","Ext. Device"], + ["10","1","RW","TS1 Time point 1 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["11","1","RW","TS1 Time point 2","HH","MM","SS","Ext. Device"], + ["12","1","RW","TS1 Time point 2 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["13","1","RW","TS1 Time point 3","HH","MM","SS","Ext. Device"], + ["14","1","RW","TS1 Time point 3 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["15","1","RW","TS1 Time point 4","HH","MM","SS","Ext. Device"], + ["16","1","RW","TS1 Time point 4 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["17","1","RW","TS1 Time point 5","HH","MM","SS","Ext. Device"], + ["18","1","RW","TS1 Time point 5 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["19","1","RW","TS1 Time point 6","HH","MM","SS","Ext. Device"], + ["20","1","RW","TS1 Time point 6 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["21","1","RW","TS1 Time point 7","HH","MM","SS","Ext. Device"], + ["22","1","RW","TS1 Time point 7 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["23","1","RW","TS1 Time point 8","HH","MM","SS","Ext. Device"], + ["24","1","RW","TS1 Time point 8 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["25","1","RW","TS1 Time point 9","HH","MM","SS","Ext. Device"], + ["26","1","RW","TS1 Time point 9 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["27","1","RW","TS1 Time point 10","HH","MM","SS","Ext. Device"], + ["28","1","RW","TS1 Time point 10 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["29","1","RW","TS1 Time point 11","HH","MM","SS","Ext. Device"], + ["30","1","RW","TS1 Time point 11 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["31","1","RW","TS1 Time point 12","HH","MM","SS","Ext. Device"], + ["32","1","RW","TS1 Time point 12 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["33","1","RW","TS1 Time point 13","HH","MM","SS","Ext. Device"], + ["34","1","RW","TS1 Time point 13 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["35","1","RW","TS1 Time point 14","HH","MM","SS","Ext. Device"], + ["36","1","RW","TS1 Time point 14 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["37","1","RW","TS1 Time point 15","HH","MM","SS","Ext. Device"], + ["38","1","RW","TS1 Time point 15 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["39","1","RW","TS1 Time point 16","HH","MM","SS","Ext. Device"], + ["40","1","RW","TS1 Time point 16 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["41","1","RW","TS2 Time point 1","HH","MM","SS","Ext. Device"], + ["42","1","RW","TS2 Time point 1 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["43","1","RW","TS2 Time point 2","HH","MM","SS","Ext. Device"], + ["44","1","RW","TS2 Time point 2 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["45","1","RW","TS2 Time point 3","HH","MM","SS","Ext. Device"], + ["46","1","RW","TS2 Time point 3 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["47","1","RW","TS2 Time point 4","HH","MM","SS","Ext. Device"], + ["48","1","RW","TS2 Time point 4 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["49","1","RW","TS2 Time point 5","HH","MM","SS","Ext. Device"], + ["50","1","RW","TS2 Time point 5 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["51","1","RW","TS2 Time point 6","HH","MM","SS","Ext. Device"], + ["52","1","RW","TS2 Time point 6 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["53","1","RW","TS2 Time point 7","HH","MM","SS","Ext. Device"], + ["54","1","RW","TS2 Time point 7 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["55","1","RW","TS2 Time point 8","HH","MM","SS","Ext. Device"], + ["56","1","RW","TS2 Time point 8 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["57","1","RW","TS2 Time point 9","HH","MM","SS","Ext. Device"], + ["58","1","RW","TS2 Time point 9 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["59","1","RW","TS2 Time point 10","HH","MM","SS","Ext. Device"], + ["60","1","RW","TS2 Time point 10 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["61","1","RW","TS2 Time point 11","HH","MM","SS","Ext. Device"], + ["62","1","RW","TS2 Time point 11 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["63","1","RW","TS2 Time point 12","HH","MM","SS","Ext. Device"], + ["64","1","RW","TS2 Time point 12 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["65","1","RW","TS2 Time point 13","HH","MM","SS","Ext. Device"], + ["66","1","RW","TS2 Time point 13 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["67","1","RW","TS2 Time point 14","HH","MM","SS","Ext. Device"], + ["68","1","RW","TS2 Time point 14 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["69","1","RW","TS2 Time point 15","HH","MM","SS","Ext. Device"], + ["70","1","RW","TS2 Time point 15 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["71","1","RW","TS2 Time point 16","HH","MM","SS","Ext. Device"], + ["72","1","RW","TS2 Time point 16 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["73","1","RW","Power meter status","TBD","","",""], + ["74","1","R","Input Voltage","","","",""], + ["75","1","R","Input Current","","","",""], + ["76","1","R","Input Power","","","",""], + ["77","1","R","Cos phi","","","",""], + ["78","1","R","Frequency","","","",""], + ["79","1","RW","Energy","","","",""], + ["80","1","RW","Lifetime","","","",""], + ["81","1","RW","Power on cycles (input)","","","",""], + ["82","1","RW","Power on cycles (relay)","","","",""], + ["83","1","R","Time since last power on","","","",""], + ["84","1","R","Accelerometer data","","","",""], + ["85","1","RW","GPS latitude","pos/neg","deg","min ","sec"], + ["86","1","RW","GPS longitude","pos/neg","deg","min ","sec"], + ["87","1","RW","Actual time","HH","MM","SS","RES."], + ["88","1","RW","Actual date","Day of week","Day","Month","Year"], + ["89","1","R","Production data 1","","","",""], + ["90","1","R","Production data 2","","","",""], + ["91","1","RW","Network ID","NID3","NID2","NID1","NID0"], + ["95","1","RW","Actual Lux level from cabinet","RES.","RES.","HB","LB"], + ["96","1","RW","Threshold lux level","Dusk HB","Dusk LB","Dawn HB","Dawn LB"], + ["97","1","RW","Adjust period","Dusk HB","Dusk LB","Dawn HB","Dawn LB"], + ["98","1","RW","Offset","RES.","RES.","Dusk","Dawn"], + ["99","1","RW","CCT min/max range","max-H","max-L","min-H","min-L"], + ["100","1","RW","DALI interface","Cmd ID","Add","Cmd","Resp"], + ["101","1","RW","Module FW ver","v1","v2","v3","v4"], + ["102","1","RW","Module MAC-H","unused","unused","M1","M2"], + ["103","1","RW","Module MAC-L","M3","M4","M5","M6"], + ["122","1","R","FW update status/control register","Byte3","Byte2","Byte1","Byte0"], + ["123","1","R","FW update - data index","Byte3","Byte2","Byte1","Byte0"], + ["124","1","R","FW update - data","Byte3","Byte2","Byte1","Byte0"], + ["0","0","R","Status","","","",""], + ["1","0","RW","Control register","RES.","RES.","RES.","init mode enable"], + ["2","0","R","Device types","","","",""], + ["3","0","R","Serial number (MAC)","","","",""], + ["4","0","R","Production data 1","","","",""], + ["5","0","R","Production data 2","","","",""], + ["6","0","RW","Network ID","NID3","NID2","NID1","NID0"], + ["7","0","RW","RS232 settings","param.","param.","Baudrate H","Baudrate L"], + ["8","0","R","Accelerometer data","","","",""], + ["9","0","RW","Module FW ver","v1","v2","v3","v4"], + ["10","0","RW","Module MAC-H","unused","unused","M1","M2"], + ["11","0","RW","Module MAC-L","M3","M4","M5","M6"], + ["32","0","RW","FW update status/control register","Byte3","Byte2","Byte1","Byte0"], + ["33","0","RW","FW update - data index","Byte3","Byte2","Byte1","Byte0"], + ["34","0","RW","FW update - data","Byte3","Byte2","Byte1","Byte0"], + ["125","0","RW","Debug Register","Byte3","Byte2","Byte1","Byte0"], + ["126","0","RW","Network Control Register","Byte3","Byte2","Byte1","Byte0"], + ["127","0","R","Network Status Register","Byte3","Byte2","Byte1","Byte0"], + ["128","0","RW","Node XX Serial Number Register","SER3","SER2","SER1","SER0"], + ["256","0","R","Node XX Network Status Register","","","",""] +]; + +let register = {}; + +module.exports = { + registers, + register +} \ No newline at end of file diff --git a/RVO3/flow_20_01_25/helper/serialport_helper.js b/RVO3/flow_20_01_25/helper/serialport_helper.js new file mode 100755 index 0000000..8efa6af --- /dev/null +++ b/RVO3/flow_20_01_25/helper/serialport_helper.js @@ -0,0 +1,100 @@ +const { exec } = require('child_process'); + +function openPort(port){ + return new Promise((resolve, reject) => { + + var callbackError = function(err) { + port.removeListener('error', callbackError); + port.removeListener('open', callbackError); + + reject(err.message); + }; + + var callbackOpen = function(data) { + port.removeListener('error', callbackError); + port.removeListener('open', callbackOpen); + + resolve("port open: ok"); + }; + + port.on('error', callbackError); + port.on('open', callbackOpen); + + port.open(); + + }) +} + +function runSyncExec(command){ + return new Promise((resolve, reject) => { + + exec(command, (error, stdout, stderr) => { + if(error == null) resolve(stdout); + reject(error); + }); + + }) +} + +async function writeData(port, data, readbytes, timeout){ + return new Promise((resolve, reject) => { + + // 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) { + + port.write(Buffer.from(data), function(err) { + if (err) { + reject(err.message); + } + }); + + 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 +} diff --git a/RVO3/flow_20_01_25/helper/suncalc.js b/RVO3/flow_20_01_25/helper/suncalc.js new file mode 100755 index 0000000..c9ca56d --- /dev/null +++ b/RVO3/flow_20_01_25/helper/suncalc.js @@ -0,0 +1,317 @@ +/* + (c) 2011-2015, Vladimir Agafonkin + SunCalc is a JavaScript library for calculating sun/moon position and light phases. + https://github.com/mourner/suncalc +*/ + +(function () { 'use strict'; + +// shortcuts for easier to read formulas + +var PI = Math.PI, + sin = Math.sin, + cos = Math.cos, + tan = Math.tan, + asin = Math.asin, + atan = Math.atan2, + acos = Math.acos, + rad = PI / 180; + +// sun calculations are based on http://aa.quae.nl/en/reken/zonpositie.html formulas + + +// date/time constants and conversions + +var dayMs = 1000 * 60 * 60 * 24, + J1970 = 2440588, + J2000 = 2451545; + +function toJulian(date) { return date.valueOf() / dayMs - 0.5 + J1970; } +function fromJulian(j) { return new Date((j + 0.5 - J1970) * dayMs); } +function toDays(date) { return toJulian(date) - J2000; } + + +// general calculations for position + +var e = rad * 23.4397; // obliquity of the Earth + +function rightAscension(l, b) { return atan(sin(l) * cos(e) - tan(b) * sin(e), cos(l)); } +function declination(l, b) { return asin(sin(b) * cos(e) + cos(b) * sin(e) * sin(l)); } + +function azimuth(H, phi, dec) { return atan(sin(H), cos(H) * sin(phi) - tan(dec) * cos(phi)); } +function altitude(H, phi, dec) { return asin(sin(phi) * sin(dec) + cos(phi) * cos(dec) * cos(H)); } + +function siderealTime(d, lw) { return rad * (280.16 + 360.9856235 * d) - lw; } + +function astroRefraction(h) { + if (h < 0) // the following formula works for positive altitudes only. + h = 0; // if h = -0.08901179 a div/0 would occur. + + // formula 16.4 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + // 1.02 / tan(h + 10.26 / (h + 5.10)) h in degrees, result in arc minutes -> converted to rad: + return 0.0002967 / Math.tan(h + 0.00312536 / (h + 0.08901179)); +} + +// general sun calculations + +function solarMeanAnomaly(d) { return rad * (357.5291 + 0.98560028 * d); } + +function eclipticLongitude(M) { + + var C = rad * (1.9148 * sin(M) + 0.02 * sin(2 * M) + 0.0003 * sin(3 * M)), // equation of center + P = rad * 102.9372; // perihelion of the Earth + + return M + C + P + PI; +} + +function sunCoords(d) { + + var M = solarMeanAnomaly(d), + L = eclipticLongitude(M); + + return { + dec: declination(L, 0), + ra: rightAscension(L, 0) + }; +} + + +var SunCalc = {}; + + +// calculates sun position for a given date and latitude/longitude + +SunCalc.getPosition = function (date, lat, lng) { + + var lw = rad * -lng, + phi = rad * lat, + d = toDays(date), + + c = sunCoords(d), + H = siderealTime(d, lw) - c.ra; + + return { + azimuth: azimuth(H, phi, c.dec), + altitude: altitude(H, phi, c.dec) + }; +}; + + +// sun times configuration (angle, morning name, evening name) + +var times = SunCalc.times = [ + [-0.833, 'sunrise', 'sunset' ], + [ -0.3, 'sunriseEnd', 'sunsetStart' ], + [ -6, 'dawn', 'dusk' ], + [ -12, 'nauticalDawn', 'nauticalDusk'], + [ -18, 'nightEnd', 'night' ], + [ 6, 'goldenHourEnd', 'goldenHour' ] +]; + +// adds a custom time to the times config + +SunCalc.addTime = function (angle, riseName, setName) { + times.push([angle, riseName, setName]); +}; + + +// calculations for sun times + +var J0 = 0.0009; + +function julianCycle(d, lw) { return Math.round(d - J0 - lw / (2 * PI)); } + +function approxTransit(Ht, lw, n) { return J0 + (Ht + lw) / (2 * PI) + n; } +function solarTransitJ(ds, M, L) { return J2000 + ds + 0.0053 * sin(M) - 0.0069 * sin(2 * L); } + +function hourAngle(h, phi, d) { return acos((sin(h) - sin(phi) * sin(d)) / (cos(phi) * cos(d))); } +function observerAngle(height) { return -2.076 * Math.sqrt(height) / 60; } + +// returns set time for the given sun altitude +function getSetJ(h, lw, phi, dec, n, M, L) { + + var w = hourAngle(h, phi, dec), + a = approxTransit(w, lw, n); + return solarTransitJ(a, M, L); +} + + +// calculates sun times for a given date, latitude/longitude, and, optionally, +// the observer height (in meters) relative to the horizon + +SunCalc.getTimes = function (date, lat, lng, height) { + + height = height || 0; + + var lw = rad * -lng, + phi = rad * lat, + + dh = observerAngle(height), + + d = toDays(date), + n = julianCycle(d, lw), + ds = approxTransit(0, lw, n), + + M = solarMeanAnomaly(ds), + L = eclipticLongitude(M), + dec = declination(L, 0), + + Jnoon = solarTransitJ(ds, M, L), + + i, len, time, h0, Jset, Jrise; + + + var result = { + solarNoon: fromJulian(Jnoon), + nadir: fromJulian(Jnoon - 0.5) + }; + + for (i = 0, len = times.length; i < len; i += 1) { + time = times[i]; + h0 = (time[0] + dh) * rad; + + Jset = getSetJ(h0, lw, phi, dec, n, M, L); + Jrise = Jnoon - (Jset - Jnoon); + + result[time[1]] = fromJulian(Jrise); + result[time[2]] = fromJulian(Jset); + } + + return result; +}; + + +// moon calculations, based on http://aa.quae.nl/en/reken/hemelpositie.html formulas + +function moonCoords(d) { // geocentric ecliptic coordinates of the moon + + var L = rad * (218.316 + 13.176396 * d), // ecliptic longitude + M = rad * (134.963 + 13.064993 * d), // mean anomaly + F = rad * (93.272 + 13.229350 * d), // mean distance + + l = L + rad * 6.289 * sin(M), // longitude + b = rad * 5.128 * sin(F), // latitude + dt = 385001 - 20905 * cos(M); // distance to the moon in km + + return { + ra: rightAscension(l, b), + dec: declination(l, b), + dist: dt + }; +} + +SunCalc.getMoonPosition = function (date, lat, lng) { + + var lw = rad * -lng, + phi = rad * lat, + d = toDays(date), + + c = moonCoords(d), + H = siderealTime(d, lw) - c.ra, + h = altitude(H, phi, c.dec), + // formula 14.1 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + pa = atan(sin(H), tan(phi) * cos(c.dec) - sin(c.dec) * cos(H)); + + h = h + astroRefraction(h); // altitude correction for refraction + + return { + azimuth: azimuth(H, phi, c.dec), + altitude: h, + distance: c.dist, + parallacticAngle: pa + }; +}; + + +// calculations for illumination parameters of the moon, +// based on http://idlastro.gsfc.nasa.gov/ftp/pro/astro/mphase.pro formulas and +// Chapter 48 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + +SunCalc.getMoonIllumination = function (date) { + + var d = toDays(date || new Date()), + s = sunCoords(d), + m = moonCoords(d), + + sdist = 149598000, // distance from Earth to Sun in km + + phi = acos(sin(s.dec) * sin(m.dec) + cos(s.dec) * cos(m.dec) * cos(s.ra - m.ra)), + inc = atan(sdist * sin(phi), m.dist - sdist * cos(phi)), + angle = atan(cos(s.dec) * sin(s.ra - m.ra), sin(s.dec) * cos(m.dec) - + cos(s.dec) * sin(m.dec) * cos(s.ra - m.ra)); + + return { + fraction: (1 + cos(inc)) / 2, + phase: 0.5 + 0.5 * inc * (angle < 0 ? -1 : 1) / Math.PI, + angle: angle + }; +}; + + +function hoursLater(date, h) { + return new Date(date.valueOf() + h * dayMs / 24); +} + +// calculations for moon rise/set times are based on http://www.stargazing.net/kepler/moonrise.html article + +SunCalc.getMoonTimes = function (date, lat, lng, inUTC) { + var t = new Date(date); + if (inUTC) t.setUTCHours(0, 0, 0, 0); + else t.setHours(0, 0, 0, 0); + + var hc = 0.133 * rad, + h0 = SunCalc.getMoonPosition(t, lat, lng).altitude - hc, + h1, h2, rise, set, a, b, xe, ye, d, roots, x1, x2, dx; + + // go in 2-hour chunks, each time seeing if a 3-point quadratic curve crosses zero (which means rise or set) + for (var i = 1; i <= 24; i += 2) { + h1 = SunCalc.getMoonPosition(hoursLater(t, i), lat, lng).altitude - hc; + h2 = SunCalc.getMoonPosition(hoursLater(t, i + 1), lat, lng).altitude - hc; + + a = (h0 + h2) / 2 - h1; + b = (h2 - h0) / 2; + xe = -b / (2 * a); + ye = (a * xe + b) * xe + h1; + d = b * b - 4 * a * h1; + roots = 0; + + if (d >= 0) { + dx = Math.sqrt(d) / (Math.abs(a) * 2); + x1 = xe - dx; + x2 = xe + dx; + if (Math.abs(x1) <= 1) roots++; + if (Math.abs(x2) <= 1) roots++; + if (x1 < -1) x1 = x2; + } + + if (roots === 1) { + if (h0 < 0) rise = i + x1; + else set = i + x1; + + } else if (roots === 2) { + rise = i + (ye < 0 ? x2 : x1); + set = i + (ye < 0 ? x1 : x2); + } + + if (rise && set) break; + + h0 = h2; + } + + var result = {}; + + if (rise) result.rise = hoursLater(t, rise); + if (set) result.set = hoursLater(t, set); + + if (!rise && !set) result[ye > 0 ? 'alwaysUp' : 'alwaysDown'] = true; + + return result; +}; + + +// export as Node module / AMD module / browser variable +if (typeof exports === 'object' && typeof module !== 'undefined') module.exports = SunCalc; +else if (typeof define === 'function' && define.amd) define(SunCalc); +else window.SunCalc = SunCalc; + +}()); diff --git a/RVO3/flow_20_01_25/helper/utils.js b/RVO3/flow_20_01_25/helper/utils.js new file mode 100755 index 0000000..a16210c --- /dev/null +++ b/RVO3/flow_20_01_25/helper/utils.js @@ -0,0 +1,124 @@ +function bytesToInt(bytes, numberOfBytes) +{ + let buffer = []; + if(Array.isArray(bytes)) + { + buffer = bytes.slice(0); + if(numberOfBytes != undefined) + { + buffer = bytes.slice(bytes.length - numberOfBytes); + } + } + else buffer.push(bytes); + + //var decimal = (buffer[0] << 24) + (buffer[1] << 16) + (buffer[2] << 8) + buffer[3]; + let l = (buffer.length - 1) * 8; + + let decimal = 0; + for(let i = 0; i < buffer.length; i++) + { + var s = buffer[i] << l; + if(l < 8) s = buffer[i] + decimal = decimal + s; + + l = l - 8; + + } + + return decimal; +} + +function resizeArray(arr, newSize, defaultValue) { + while(newSize > arr.length) + arr.push(defaultValue); + arr.length = newSize; +} + +longToByteArray = function(/*long*/long) { + // we want to represent the input as a 8-bytes array + var byteArray = [0, 0, 0, 0, 0, 0, 0, 0]; + + for ( var index = 0; index < byteArray.length; index ++ ) { + var byte = long & 0xff; + byteArray [ index ] = byte; + long = (long - byte) / 256 ; + } + + return byteArray; + }; + +function addDays(date, days) { + var result = new Date(date); + result.setDate(result.getDate() + days); + return result; +} + +/* +sleep(2000).then(() => { + // Do something after the sleep! + + +}); +*/ + +function sleep (time) { + return new Promise((resolve) => setTimeout(resolve, time)); +} + +function isEmptyObject( obj ) { + for ( var name in obj ) { + return false; + } + return true; +} + +function convertUTCDateToLocalDate(date) { + var newDate = new Date(date); + newDate.setMinutes(date.getMinutes() + date.getTimezoneOffset()); + return newDate; +} + +function addZeroBefore(n) { + return (n < 10 ? '0' : '') + n; +} + +var convertBase = function () { + + function convertBase(baseFrom, baseTo) { + return function (num) { + return parseInt(num, baseFrom).toString(baseTo); + + }; + } + + // binary to decimal + convertBase.bin2dec = convertBase(2, 10); + + // binary to hexadecimal + convertBase.bin2hex = convertBase(2, 16); + + // decimal to binary + convertBase.dec2bin = convertBase(10, 2); + + // decimal to hexadecimal + convertBase.dec2hex = convertBase(10, 16); + + // hexadecimal to binary + convertBase.hex2bin = convertBase(16, 2); + + // hexadecimal to decimal + convertBase.hex2dec = convertBase(16, 10); + + return convertBase; + }(); + +module.exports = { + bytesToInt, + longToByteArray, + addDays, + addZeroBefore, + resizeArray, + isEmptyObject, + sleep, + convertUTCDateToLocalDate +} \ No newline at end of file diff --git a/RVO3/flow_20_01_25/httprequest.js b/RVO3/flow_20_01_25/httprequest.js new file mode 100755 index 0000000..469c8cb --- /dev/null +++ b/RVO3/flow_20_01_25/httprequest.js @@ -0,0 +1,137 @@ +exports.id = 'httprequest'; +exports.title = 'HTTP Request'; +exports.group = 'HTTP'; +exports.color = '#5D9CEC'; +exports.input = true; +exports.version = '2.0.1'; +exports.output = 1; +exports.author = 'Peter Širka'; +exports.icon = 'cloud-upload'; + +exports.html = `
+
@(URL address)
+
+
+
@(HTTP method)
+
+
+
@(Serialization)
+
+
+
@(Download the content in chunks)
+
@(Keep persistent cookies)
+
@(Disable DNS cache)
+
@(Keep alive connection)
+
+
+
+
@(Custom headers)
+
@(Cookies)
+
+
+
+ +
+
+
+
@(User)
+
+
+
@(Password)
+
+
+
+
+
`; + +exports.readme = `# Request + +This component creates a request with received data. + +__Response:__ +\`\`\`javascript +{ + data: String, + headers: Object, + status: Number, + host: String +} +\`\`\` + +__Dynamic arguments__: +Are performed via FlowData repository and can be used for URL address or for custom headers/cookies/auth. Use \`repository\` component for creating of dynamic arguments. Dynamic values are replaced in the form \`{key}\`: + +- url address e.g. \`https://.../{key}/\` +- headers values e.g. \`{token}\` +- cookies values e.g. \`{token}\``; + +exports.install = function(instance) { + + var can = false; + var flags = null; + var cookies2 = null; + + instance.on('data', function(response) { + can && instance.custom.send(response); + }); + + instance.custom.send = function(response) { + var options = instance.options; + + var headers = null; + var cookies = null; + + options.headers && Object.keys(options.headers).forEach(function(key) { + !headers && (headers = {}); + headers[key] = response.arg(options.headers[key]); + }); + + if (options.username && options.userpassword) { + !headers && (headers = {}); + headers['Authorization'] = 'Basic ' + U.createBuffer(response.arg(options.username + ':' + options.userpassword)).toString('base64'); + } + + options.cookies && Object.keys(options.cookies).forEach(function(key) { + !cookies && (cookies = {}); + cookies[key] = response.arg(options.cookies[key]); + }); + + if (options.chunks) { + U.download(response.arg(options.url), flags, options.stringify === 'none' ? null : response.data, function(err, response) { + response.on('data', (chunks) => instance.send2(chunks)); + }, cookies || cookies2, headers); + } else { + U.request(response.arg(options.url), flags, options.stringify === 'none' ? null : response.data, 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) + instance.error(err, response); + }, cookies || cookies2, headers); + } + }; + + instance.reconfigure = function() { + var options = instance.options; + can = options.url && options.url && options.method && options.stringify ? true : false; + instance.status(can ? '' : 'Not configured', can ? undefined : 'red'); + + if (!can) + return; + + flags = []; + flags.push(options.method.toLowerCase()); + options.stringify === 'json' && flags.push('json'); + options.stringify === 'raw' && flags.push('raw'); + options.keepalive && flags.push('keepalive'); + !options.nodns && flags.push('dnscache'); + if (options.persistentcookies) { + flags.push('cookies'); + cookies2 = {}; + } else + cookies2 = null; + }; + + instance.on('options', instance.reconfigure); + instance.reconfigure(); +}; \ No newline at end of file diff --git a/RVO3/flow_20_01_25/httpresponse.js b/RVO3/flow_20_01_25/httpresponse.js new file mode 100755 index 0000000..160a3bb --- /dev/null +++ b/RVO3/flow_20_01_25/httpresponse.js @@ -0,0 +1,76 @@ +exports.id = 'httpresponse'; +exports.title = 'HTTP Response'; +exports.group = 'HTTP'; +exports.color = '#5D9CEC'; +exports.icon = 'arrow-right'; +exports.input = true; +exports.output = ['#666D76']; +exports.version = '2.0.0'; +exports.author = 'Martin Smola'; +exports.readme = `# HTTP response + +HTTP response will respond with data recieved using data-type set in Settings form or plain text if not set. Output is the message duration \`Number\` in seconds.`; + +exports.html = `
+
@(Response data-type)
+
JSON is by default.
+
`; + +exports.install = function(instance) { + + var dursum = 0; + var durcount = 0; + + instance.on('data', function(flowdata) { + + var ctrl = flowdata.repository.controller; + var data = flowdata.data; + + if (!ctrl) { + instance.throw('No controller to use for response!'); + return; + } + + durcount++; + dursum += ((new Date() - flowdata.begin) / 1000).floor(2); + setTimeout2(instance.id, instance.custom.duration, 500, 10); + + ctrl.$flowdata = flowdata; + + var datatype = instance.options.datatype || 'json'; + if (datatype === 'emptyresponse') + return ctrl.plain(''); + + if (datatype !== 'json' && typeof(data) !== 'string') { + instance.throw('Incorect type of data, expected string, got ' + typeof(data)); + ctrl.plain(data == null ? '' : data.toString()); + return; + } + + switch(datatype) { + case 'html': + ctrl.content(data, 'text/html'); + break; + case 'plain': + ctrl.plain(data); + break; + case 'xml': + ctrl.content(data, 'text/xml'); + break; + default: + ctrl.json(data); + break; + } + }); + + instance.on('service', function() { + dursum = 0; + durcount = 0; + }); + + instance.custom.duration = function() { + var avg = (dursum / durcount).floor(2); + instance.status(avg + ' sec.'); + instance.send2(0, avg); + }; +}; diff --git a/RVO3/flow_20_01_25/httproute.js b/RVO3/flow_20_01_25/httproute.js new file mode 100755 index 0000000..583a19d --- /dev/null +++ b/RVO3/flow_20_01_25/httproute.js @@ -0,0 +1,326 @@ +exports.id = 'httproute'; +exports.title = 'HTTP Route'; +exports.group = 'HTTP'; +exports.color = '#5D9CEC'; +exports.icon = 'globe'; +exports.input = false; +exports.output = ['#6CAC5A', '#37BC9B']; +exports.version = '1.2.3'; +exports.author = 'Martin Smola'; +exports.cloning = false; +exports.options = { method: 'GET', url: '', size: 5, cacheexpire: '5 minutes', cachepolicy: 0, timeout: 5 }; +exports.dateupdated = '2021-01-21 18:30d'; +exports.readme = `# HTTP route + +__Outputs__: +- first output: raw data (cache is empty or is disabled) +- second output: cached data + +If one of the outputs is disabled then automatic responce with code "503 service unavailable" is sent. + +When a request comes in bellow object is available at \`flowdata.data\`: + +\`\`\`javascript +{ + params: { id: '1' }, // params for dynamic routes, e.g. /test/{id} + query: { msg: 'Hello' }, // parsed query string, e.g. /test/1?msg=Hello + body: { test: 'OK' }, // object if json requests otherwise string + headers: {}, // headers data + session: {}, // session data + user: {}, // user data + files: [], // uploaded files + url: '/users/', // a relative URL address + referrer: '/', // referrer + mobile: false, // determines mobile device + robot: false, // determines search robots/crawlsers + language: 'en' // determines language +} +\`\`\` + +See [documentation for flags](https://docs.totaljs.com/latest/en.html#api~HttpRouteOptionsFlags~unauthorize). These method flags are set automatically e.g. \`get, post, put, patch or delete\` + +--- + +\`id:ROUTE_ID\` flag cannot be used since it's already used by this component internally`; + +exports.html = `
+
+ +
+ +
+
+
@(HTTP method)
+
+
+
@(URL address)
+
+
+
+
+
@(Additional flags)
+
@(Separate flags by comma e.g. json, authorize)
+
+
+
@(Max. request size)
+
@(In kB kilobytes)
+
+
+
@(Timeout)
+
@(In seconds.)
+
+
+
+
+
+
@(Automatically respond with 200 OK?)
+
@(If not checked you need to use HTTP response component to respond to the request.)
+
+
@(Custom headers)
+
@(Cookies)
+
+
+
+
+
+
@(Cache policy)
+
@(User instance must contain id property.)
+
+
+
@(Expiration)
+
@(E.g. 5 minutes)
+
+
+
+`; + +exports.install = function(instance) { + + var route; + + var uninstall = function(id) { + if (F.is4) { + route && route.remove(); + route = null; + } else + UNINSTALL('route', id); + }; + + instance.custom.emptyresponse = function(self) { + self.plain(); + }; + + instance.reconfigure = function() { + + var options = instance.options; + + if (!options.url) { + instance.status('Not configured', 'red'); + return; + } + + if (typeof(options.flags) === 'string') + options.flags = options.flags.split(',').trim(); + + uninstall('id:' + instance.id); + + var flags = options.flags || []; + + flags.push('id:' + instance.id); + + if (!F.is4) + flags.push(options.method.toLowerCase()); + + options.timeout && flags.push(options.timeout * 1000); + + // Make unique values + flags = flags.filter(function(v, i, a) { + if(F.is4 && v.toString().toLowerCase() === options.method.toLowerCase()) + return false; // remove method + return a.indexOf(v) === i; + }); + + options.flags = flags; + var handler = function() { + + if (instance.paused || (instance.isDisabled && (instance.isDisabled('output', 0) || instance.isDisabled('output', 1)))) { + instance.status('503 Service Unavailable'); + this.status = 503; + this.json(); + return; + } + + var key; + var self = this; + + if (instance.options.emptyresponse) { + instance.status('200 OK'); + setTimeout(instance.custom.emptyresponse, 100, self); + + if (instance.hasConnection(0)) { + var data = instance.make({ + query: self.query, + body: self.body, + session: self.session, + user: self.user, + files: self.files, + headers: self.req.headers, + url: self.url, + params: self.params + }); + instance.send2(0, data); + } + + return; + } + + switch (instance.options.cachepolicy) { + case 1: // URL + key = 'rro' + instance.id + self.url.hash(); + break; + case 2: // URL + query + case 3: // URL + query + user + key = self.url; + var keys = Object.keys(self.query); + keys.sort(); + for (var i = 0, length = keys.length; i < length; i++) + key += keys[i] + self.query[keys[i]] + '&'; + if (instance.options.cachepolicy === 3 && self.user) + key += 'iduser' + self.user.id; + key = 'rro' + instance.id + key.hash(); + break; + } + + if (key && F.cache.get2(key)) { + var data = instance.make(F.cache.get2(key)); + data.repository.controller = self; + instance.send2(1, data); + } else { + + var data = instance.make({ + query: self.query, + body: self.body, + session: self.session, + user: self.user, + files: self.files, + headers: self.req.headers, + url: self.url, + params: self.params, + mobile: self.mobile, + robot: self.robot, + referrer: self.referrer, + language: self.language + }); + + data.repository.controller = self; + instance.send2(0, data); + key && FINISHED(self.res, () => F.cache.set(key, self.$flowdata.data, instance.options.cacheexpire)); + } + }; + + if (F.is4) + route = ROUTE(options.method.toUpperCase() + ' ' + options.url, handler, flags, options.size || 5); + else + F.route(options.url, handler, flags, options.size || 5); + + instance.status('Listening', 'green'); + }; + + instance.reconfigure(); + instance.on('options', instance.reconfigure); + instance.on('close', function(){ + uninstall('id:' + instance.id); + }); +}; + +// check url exists +FLOW.trigger('httproutecheckurl', function(next, data) { + var url = data.url; + var method = data.method; + if (url[url.length - 1] !== '/') + url += '/'; + var exists = F.routes.web.findItem(r => r.urlraw === url && r.method === method); + next(exists != null); +}); + +exports.uninstall = function() { + FLOW.trigger('httproutecheckurl', null); +}; diff --git a/RVO3/flow_20_01_25/infosender.js b/RVO3/flow_20_01_25/infosender.js new file mode 100755 index 0000000..c7afd83 --- /dev/null +++ b/RVO3/flow_20_01_25/infosender.js @@ -0,0 +1,101 @@ +exports.id = 'infosender'; +exports.title = 'Info sender'; +exports.version = '1.0.0'; +exports.group = 'Worksys'; +exports.color = '#2134B0'; +exports.input = 2; +exports.output = 1 +exports.icon = 'bolt'; + +const { networkInterfaces } = require('os'); + +exports.html = `
+
+
+
CSV Import
+
+
+
`; + +exports.readme = `# send all data to projects.worksys.io, required to monitor status of controller(unipi)`; + +exports.install = function(instance) { + + let id; + let allValues = {}; + let sendAllValuesInterval; + let configured = false; + + let now = new Date(); + console.log(exports.title, "INSTALLED", now.toLocaleString("sk-SK")); + + const nets = networkInterfaces(); + let ipAddresses = Object.create(null); // Or just '{}', an empty object + + for (const name of Object.keys(nets)) { + for (const net of nets[name]) { + // Skip over non-IPv4 and internal (i.e. 127.0.0.1) addresses + if (net.family === 'IPv4' && !net.internal) { + if (!ipAddresses[name]) { + ipAddresses[name] = []; + } + ipAddresses[name].push(net.address); + } + } + } + + function sendValues() + { + if(!configured) return; + + if(Object.keys(allValues).length > 0) + { + if(id) + { + delete allValues.__force__; + let dataToSend = {...allValues}; + dataToSend.id = id; + dataToSend.ipAddresses = ipAddresses; + + instance.send(0, dataToSend); + + allValues = {}; + } + else + { + console.log(exports.title, "unable to send data, no id"); + } + + } + } + + instance.on("close", () => { + clearInterval(sendAllValuesInterval); + }) + + instance.on("0", _ => { + id = FLOW.GLOBALS.settings.project_id; + configured = true; + }) + + instance.on("1", flowdata => { + + allValues = { ...allValues, ...flowdata.data}; + //console.log("DATA RECEIVED", flowdata.data); + + //__force__ + if(flowdata.data.hasOwnProperty("__force__")) + { + if(flowdata.data.__force__) + { + sendValues(); + } + } + }) + + sendAllValuesInterval = setInterval(() => { + sendValues(); + }, 60000*3); + +} + diff --git a/RVO3/flow_20_01_25/modbus_reader.js b/RVO3/flow_20_01_25/modbus_reader.js new file mode 100755 index 0000000..b907148 --- /dev/null +++ b/RVO3/flow_20_01_25/modbus_reader.js @@ -0,0 +1,367 @@ +exports.id = 'modbus_reader'; +exports.title = 'Modbus reader'; +exports.version = '2.0.0'; +exports.group = 'Worksys'; +exports.color = '#2134B0'; +exports.input = 1; +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; +//number of phases inRVO +let phases; +//phases where voltage is 0 (set) +let noVoltage; + +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.phases = this.buildPhases(); + + this.startSocket(); + } + + buildPhases = () => { + let a = []; + for (let i = 1; i<= phases; i++) { + a.push(`Phase_${i}_voltage`) + } + return a; + } + + 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 (this.phases.includes(singleValue)) + { + let l = singleValue.split("_"); + let phase = parseInt(l[1]); + + // console.log(values[singleValue], tbName); + + if(values[singleValue] == 0) + { + noVoltage.add(phase); + sendNotification("modbus_reader: checkNullVoltage", tbName, "no_voltage_on_phase", {phase: phase}, "", SEND_TO.tb, instance, "voltage" + phase ); + // console.log('no voltage') + } + else + { + noVoltage.delete(phase); + // console.log('voltage detected') + sendNotification("modbus_reader: checkNullVoltage", tbName, "voltage_on_phase_restored", {phase: phase}, "", SEND_TO.tb, instance, "voltage" + phase); + } + } + }) + } + + /** + * function sends notification to slack and to tb, if EM total_power value changes more than numberOfNodes*15. This should show, that RVO lamps has been switched on or off + */ + lampSwitchNotification = (values) => { + + if(!values.hasOwnProperty("total_power")) return; + + const actualTotalPower = values.total_power; + + const numberOfNodes = Object.keys(FLOW.GLOBALS.nodesData).length; + if(numberOfNodes == 0) numberOfNodes = 20; // to make sure, we send notification if totalPower is more than 300 + + if(actualTotalPower > numberOfNodes * 15 && this.onNotificationSent == false) + { + sendNotification("modbus_reader: lampSwitchNotification", tbName, "lamps_have_turned_on", {}, "", SEND_TO.tb, instance); + this.onNotificationSent = true; + this.offNotificationSent = false; + } + else if(actualTotalPower <= numberOfNodes * 15 && this.offNotificationSent == false) + { + 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; + } + + function main() { + + phases = FLOW.GLOBALS.settings.phases; + tbName = FLOW.GLOBALS.settings.rvoTbName; + noVoltage = FLOW.GLOBALS.settings.no_voltage; + mainSocket = new SocketWithClients(); + + // this notification is to show, that flow (unipi) has been restarted + sendNotification("modbus_reader", tbName, "flow_restart", {}, "", SEND_TO.slack, instance); + } + + instance.on("0", function(_) { + main(); + }) + +} + diff --git a/RVO3/flow_20_01_25/monitorconsumption.js b/RVO3/flow_20_01_25/monitorconsumption.js new file mode 100755 index 0000000..64cc58e --- /dev/null +++ b/RVO3/flow_20_01_25/monitorconsumption.js @@ -0,0 +1,156 @@ +exports.id = 'monitorconsumption'; +exports.title = 'Consumption'; +exports.version = '1.0.0'; +exports.author = 'Peter Širka'; +exports.group = 'Monitoring'; +exports.color = '#967ADC'; +exports.input = 0; +exports.output = 1; +exports.icon = 'bug'; +exports.options = { interval: 5000, enabled: true, monitorconsumption: true, monitorsize: true, monitorconnections: true, monitorfiles: true }; +exports.click = true; +exports.readme = `# Consumption monitoring + +This component measure CPU and memory consumption, open files and open connections of this application. It uses these Linux commands: \`ps\`, \`lsof\`, \`netstat\` and \`df\`. + +__Data Example__: + +\`\`\`javascript +{ + cpu: 0, // percentage + memory: 4096, // in bytes + size: 34303, // directory size in bytes + files: 34, // count of open files + connections: 343, // count of connections + uptime: '1-12:34:00' +} +\`\`\``; + +exports.html = `
+
+
+
@(Interval in milliseconds)
+
+
+
+
Monitor: Consumption + uptime
+
Monitor: Count of open files
+
Monitor: Count of open connections
+
Monitor: Directory size
+
`; + +exports.install = function(instance) { + + var current = { cpu: 0, memory: 0, files: 0, connections: 0, size: 0, uptime: '', counter: 0 }; + var tproc = null; + var Exec = require('child_process').exec; + var reg_empty = /\s{2,}/g; + var reg_appdisksize = /^[\d.,]+/; + + instance.custom.run = function() { + + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + + var arr = []; + + // Get CPU and Memory consumption + instance.options.monitorconsumption && arr.push(function(next) { + Exec('ps -p {0} -o %cpu,rss,etime'.format(process.pid), function(err, response) { + + if (err) { + instance.throw(err); + } else { + var line = response.split('\n')[1]; + line = line.trim().replace(reg_empty, ' ').split(' '); + var cpu = line[0].parseFloat(); + current.cpu = cpu.floor(1); + current.memory = line[1].parseInt2() * 1024; // kB to bytes + current.uptime = line[2]; + } + + next(); + }); + }); + + // Get count of open files + instance.options.monitorfiles && arr.push(function(next) { + Exec('lsof -a -p {0} | wc -l'.format(process.pid), function(err, response) { + if (err) + instance.throw(err); + else + current.files = response.trim().parseInt2(); + next(); + }); + }); + + // Get count of opened network connections + instance.options.monitorconnections && arr.push(function(next) { + Exec('netstat -an | grep :{0} | wc -l'.format(F.port), function(err, response) { + if (err) { + instance.throw(err); + } else { + current.connections = response.trim().parseInt2() - 1; + if (current.connections < 0) + current.connections = 0; + } + next(); + }); + }); + + // Get directory size + instance.options.monitorsize && current.counter % 5 !== 0 && arr.push(function(next) { + Exec('du -hsb ' + process.cwd(), function(err, response) { + if (err) { + instance.throw(err); + } else { + var match = response.trim().match(reg_appdisksize); + match && (current.size = match.toString().trim().parseInt2()); + } + next(); + }); + }); + + arr.async(function() { + + tproc && clearTimeout(tproc); + + if (instance.options.enabled) { + tproc = setTimeout(instance.custom.run, instance.options.interval); + instance.send2(current); + } + + instance.custom.status(); + current.counter++; + }); + }; + + instance.custom.status = function() { + if (instance.options.enabled) + instance.status('{0}% / {1}'.format(current.cpu, current.memory.filesize())); + else + instance.status('Disabled', 'red'); + }; + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + + if (instance.options.enabled) { + current.counter = 0; + instance.custom.run(); + } + + }); + + instance.on('close', function() { + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + }); + + setTimeout(instance.custom.run, 1000); +}; \ No newline at end of file diff --git a/RVO3/flow_20_01_25/monitordisk.js b/RVO3/flow_20_01_25/monitordisk.js new file mode 100755 index 0000000..f4fdaa0 --- /dev/null +++ b/RVO3/flow_20_01_25/monitordisk.js @@ -0,0 +1,96 @@ +exports.id = 'monitordisk'; +exports.title = 'Disk'; +exports.version = '1.0.0'; +exports.author = 'Peter Širka'; +exports.group = 'Monitoring'; +exports.color = '#F6BB42'; +exports.output = 1; +exports.icon = 'hdd-o'; +exports.click = true; +exports.options = { interval: 8000, path: '/', enabled: true }; +exports.readme = `# Disk monitoring + +This component monitors disk \`bytes\` consumption in Linux systems. It uses \`df\` command. + +__Data Example__: + +\`\`\`javascript +{ + total: 474549649408, + used: 39125245952, + free: 411294994432 +} +\`\`\``; + +exports.html = `
+
+
+
@(Interval in milliseconds)
+
+
+
@(Path)
+
+
+
`; + +exports.install = function(instance) { + + var current = { total: 0, used: 0, free: 0, path: '', type: '', percentUsed: 0 }; + var tproc = null; + + instance.custom.run = function() { + + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + + if (!instance.options.enabled) + return; + + require('child_process').exec('df -hTB1 ' + instance.options.path, function(err, response) { + + tproc = setTimeout(instance.custom.run, instance.options.interval); + + if (err) { + instance.error(err); + return; + } + + response.parseTerminal(function(line) { + if (line[0][0] !== '/') + return; + current.total = line[2].parseInt(); + current.free = line[4].parseInt(); + current.used = line[3].parseInt(); + current.path = instance.options.path || '/'; + current.type = line[1]; + current.percentUsed = line[5]; + instance.custom.status(); + instance.send2(current); + }); + }); + }; + + instance.custom.status = function() { + if (instance.options.enabled) + instance.status(current.free.filesize() + ' / ' + current.total.filesize()); + else + instance.status('Disabled', 'red'); + }; + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + instance.options.enabled && instance.custom.run(); + }); + + instance.on('close', function() { + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + }); + + setTimeout(instance.custom.run, 1000); +}; \ No newline at end of file diff --git a/RVO3/flow_20_01_25/monitormemory.js b/RVO3/flow_20_01_25/monitormemory.js new file mode 100755 index 0000000..2decbc4 --- /dev/null +++ b/RVO3/flow_20_01_25/monitormemory.js @@ -0,0 +1,87 @@ +exports.id = 'monitormemory'; +exports.title = 'Memory'; +exports.version = '1.0.0'; +exports.author = 'Peter Širka'; +exports.group = 'Monitoring'; +exports.color = '#F6BB42'; +exports.output = 1; +exports.click = true; +exports.icon = 'microchip'; +exports.options = { interval: 8000, enabled: true }; +exports.readme = `# Memory monitoring + +This component monitors memory \`bytes\` consumption in Linux systems. It uses \`free\` command. + +__Data Example__: + +\`\`\`javascript +{ + total: 33558769664, + used: 1998868480, + free: 2653708288 +} +\`\`\``; + +exports.html = `
+
+
+
@(Interval in milliseconds)
+
+
+
`; + +exports.install = function(instance) { + + var current = { total: 0, used: 0, free: 0 }; + var tproc = null; + + instance.custom.run = function() { + + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + + if (!instance.options.enabled) + return; + + require('child_process').exec('free -b -t', function(err, response) { + + tproc = setTimeout(instance.custom.run, instance.options.interval); + + if (err) { + instance.error(err); + return; + } + + var memory = response.split('\n')[1].match(/\d+/g); + current.total = memory[0].parseInt(); + current.used = memory[1].parseInt() - memory[3].parseInt(); + current.free = current.total - current.used; + instance.custom.status(); + instance.send2(current); + }); + }; + + instance.custom.status = function() { + if (instance.options.enabled) + instance.status(current.free.filesize() + ' / ' + current.total.filesize()); + else + instance.status('Disabled', 'red'); + }; + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + instance.options.enabled && instance.custom.run(); + }); + + instance.on('close', function() { + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + }); + + setTimeout(instance.custom.run, 1000); +}; \ No newline at end of file diff --git a/RVO3/flow_20_01_25/nodesdb_changecheck.js b/RVO3/flow_20_01_25/nodesdb_changecheck.js new file mode 100755 index 0000000..be1e700 --- /dev/null +++ b/RVO3/flow_20_01_25/nodesdb_changecheck.js @@ -0,0 +1,70 @@ +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/RVO3/flow_20_01_25/show_dbdata.js b/RVO3/flow_20_01_25/show_dbdata.js new file mode 100755 index 0000000..d01eecd --- /dev/null +++ b/RVO3/flow_20_01_25/show_dbdata.js @@ -0,0 +1,241 @@ +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 = 7; +exports.output = 1; + +const { exec } = require('child_process'); + +exports.install = 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}) + }) + instance.on("5", _ => { + exec("sudo tail -n 25 monitor.txt" , (err, stdout, stderr) => { + if (err || stderr) instance.send(0,{err, stderr}); + else instance.send(0,stdout); + }) + }) + instance.on("6", _ => { + exec("sudo tail -n 25 err.txt" , (err, stdout, stderr) => { + if (err || stderr) instance.send(0,{err, stderr}); + else instance.send(0,stdout); + }) + }) +}; + + + +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/RVO3/flow_20_01_25/slack_filter.js b/RVO3/flow_20_01_25/slack_filter.js new file mode 100755 index 0000000..753c24a --- /dev/null +++ b/RVO3/flow_20_01_25/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 = `
+
+
+
@(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"] = []; + } + + instance.options.name = FLOW.GLOBALS.settings.rvo_name; + if (instance.options.name) { + instance.status('Running'); + running = true; + } else { + instance.status('Please run options again', 'red'); + running = false; + } + } catch (e) { + instance.error('Citysys connector: ' + e.message); + } + }; + + instance.on('options', instance.reconfigure); + setTimeout(instance.reconfigure, 10000); + + +}; diff --git a/RVO3/flow_20_01_25/thermometer.js b/RVO3/flow_20_01_25/thermometer.js new file mode 100755 index 0000000..fa015c6 --- /dev/null +++ b/RVO3/flow_20_01_25/thermometer.js @@ -0,0 +1,98 @@ +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 = 5;//minutes +let NUMBER_OF_FAILURES_TO_SEND_ERROR = 13; + +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) => { + + 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); + setTimeout(main, 20000); + }) +}; diff --git a/RVO3/flow_20_01_25/trigger.js b/RVO3/flow_20_01_25/trigger.js new file mode 100755 index 0000000..27545a8 --- /dev/null +++ b/RVO3/flow_20_01_25/trigger.js @@ -0,0 +1,79 @@ +exports.id = 'trigger'; +exports.title = 'Trigger'; +exports.group = 'Inputs'; +exports.color = '#F6BB42'; +exports.click = true; +exports.output = 1; +exports.version = '1.1.0'; +exports.author = 'Martin Smola'; +exports.icon = 'play'; + +exports.html = `
+
@(Data type (String by default))
+
@(Data)
+
Trigger 5s after initialization.
+
@(Useful when there's a need to run certain flow when the app restarts, etc.)
+
`; + +exports.readme = `# Trigger + +- Clicking on the component starts the chain +- Settings allows to set a data-type and a value`; + +exports.install = function(instance) { + + var value; + + instance.on('click', () => instance.send2(value)); + + instance.reconfigure = function() { + var options = instance.options; + value = null; + switch (options.datatype) { + case 'integer': + value = options.data.parseInt2('error'); + value = value === 'error' ? NaN : value; + break; + case 'float': + value = options.data.parseFloat2('error'); + value = value === 'error' ? NaN : value; + break; + case 'date': + options.data = options.data.toString(); + var num = options.data.parseInt('error'); + num === 'error' && (num = options.data.parseDate('error')); + num === 'error' && (num = null); + value = num ? new Date(num).toUTCString() : num; + break; + case 'object': + try { + value = (new Function('return ' + options.data))(); + } catch (e) { + instance.error(e); + } + break; + case 'boolean': + value = options.data.parseBoolean(); + break; + case 'buffer': + try { + value = U.createBuffer(options.data); + } catch (e) { + instance.error(e); + } + break; + case 'string': + default: + value = '' + (options.data || ''); + break; + } + }; + + instance.on('options', instance.reconfigure); + instance.reconfigure(); + + if (instance.options.restart) + setTimeout(function(){ + instance.send2(value); + }, 5000); +}; diff --git a/RVO3/flow_20_01_25/variables.txt b/RVO3/flow_20_01_25/variables.txt new file mode 100755 index 0000000..e69de29 diff --git a/RVO3/flow_20_01_25/virtualwirein.js b/RVO3/flow_20_01_25/virtualwirein.js new file mode 100755 index 0000000..38a4e42 --- /dev/null +++ b/RVO3/flow_20_01_25/virtualwirein.js @@ -0,0 +1,43 @@ +exports.id = 'virtualwirein'; +exports.title = 'Virtual wire in'; +exports.version = '1.0.0'; +exports.author = 'Martin Smola'; +exports.color = '#303E4D'; +exports.icon = 'sign-in'; +exports.input = false; +exports.output = 1; +exports.options = {}; +exports.readme = `# Virtual wire in + +When the wires between the components are mess it's time to use Virtual wire.`; + +exports.html = `
+
@(Wire name)
+
+`; + +exports.install = function(instance) { + + instance.custom.reconfigure = function(options){ + if (instance.options.wirename) { + instance.status(instance.options.wirename); + } else + instance.status('Not configured', 'red'); + }; + + ON('virtualwire', function(wirename, flowdata){ + if (instance.options.wirename && instance.options.wirename === wirename) + instance.send(flowdata); + }); + + instance.on('options', instance.custom.reconfigure); + instance.custom.reconfigure(); +}; diff --git a/RVO3/flow_20_01_25/virtualwireout.js b/RVO3/flow_20_01_25/virtualwireout.js new file mode 100755 index 0000000..94a1e4f --- /dev/null +++ b/RVO3/flow_20_01_25/virtualwireout.js @@ -0,0 +1,41 @@ +exports.id = 'virtualwireout'; +exports.title = 'Virtual wire out'; +exports.version = '1.0.0'; +exports.author = 'Martin Smola'; +exports.color = '#303E4D'; +exports.icon = 'sign-out'; +exports.input = true; +exports.options = {}; +exports.readme = `# Virtual wire out + +When the wires between the components are mess it's time to use Virtual wire.`; + +exports.html = `
+
@(Wire name)
+
+`; + +exports.install = function(instance) { + + instance.custom.reconfigure = function(){ + if (instance.options.wirename) { + instance.status(instance.options.wirename); + } else + instance.status('Not configured', 'red'); + }; + + instance.on('data', function(flowdata) { + EMIT('virtualwire', instance.options.wirename, flowdata); + }); + + instance.on('options', instance.custom.reconfigure); + instance.custom.reconfigure(); +}; diff --git a/RVO3/flow_20_01_25/wsmqttpublish.js b/RVO3/flow_20_01_25/wsmqttpublish.js new file mode 100755 index 0000000..b2a218d --- /dev/null +++ b/RVO3/flow_20_01_25/wsmqttpublish.js @@ -0,0 +1,477 @@ +exports.id = 'wsmqttpublish'; +exports.title = 'WS MQTT publish'; +exports.group = 'MQTT'; +exports.color = '#888600'; +exports.version = '1.0.2'; +exports.icon = 'sign-out'; +exports.input = 2; +exports.output = 3; +exports.options = { host: 'tb-stage.worksys.io', port: 1883, clientid: "", username: "" }; + +exports.html = `
+
+
+
Hostname or IP address (if not empty - setting will override db setting)
+
+
+
Port
+
+
+
+
+
@(Client id)
+
+
+
@(Username)
+
+
+
`; + + +exports.readme = ` +# WS MQTT Publish + +Version 1.0.3. + +Added: +- database collections, +- 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 = { + debug: 0, + rpcCall: 1, + services: 2 +} + +//CONFIG +let createTelemetryBackup = true; +let saveTelemetryOnError = true;//backup_on_failure overrides this value +//------------------------ + +let rollers; +if(createTelemetryBackup) rollers = require('streamroller'); + +const noSqlFileSizeLimit = 4194304;//use 5MB - 4194304 +let insertNoSqlCounter = 0; +let insertBackupNoSqlCounter = 0; +let processingData = false; + +let backup_on_failure = false;//== saveTelemetryOnError - create backup client 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; + +process.on('uncaughtException', function (err) { + + errLogger.error('uncaughtException:', err.message) + errLogger.error(err.stack); + + //TODO + //send to service + + //process.exit(1); +}) + +const nosql = NOSQL('tbdata'); +const nosqlBackup = NOSQL('/backup/tbdata'); + + +exports.install = function(instance) { + + var client; + var opts; + var clientReady = false; + + // wsmqtt status for notification purposes on projects.worksys.io database + let wsmqttName = null; + let sendWsStatusVar = null; + let wsmqtt_status = 'disconnected'; + + 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'; + } + + function sendWsStatus() + { + instance.send(SEND_TO.services, {[wsmqttName]: wsmqtt_status}); + } + + + function main() + { + if(!FLOW.dbLoaded) return; + + loadSettings(); + clearInterval(sendWsStatus); + sendWsStatusVar = setInterval(sendWsStatus, 180000); + } + + //set opts according to db settings + function loadSettings() + { + + if(instance.options.host !== "") + { + //override settings from database + var o = instance.options; + opts = { + host: o.host, + port: o.port, + clientId: o.clientid, + username: o.username, + rejectUnauthorized: false, + resubscribe: false + }; + + wsmqttName = getWsmqttName(o.host); + + console.log("wsmqttpublich -> loadSettings from instance.options", instance.options); + } + else + { + + const SETTINGS = FLOW.GLOBALS.settings; + backup_on_failure = SETTINGS.backup_on_failure; + saveTelemetryOnError = backup_on_failure; + + restore_from_backup = SETTINGS.restore_from_backup; + restore_backup_wait = SETTINGS.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; + + opts = { + host: mqtt_host, + port: mqtt_port, + keepalive: 10, + clientId: mqtt_clientid, + username: mqtt_username, + rejectUnauthorized: false, + resubscribe: false + }; + + wsmqttName = getWsmqttName(mqtt_host); + } + + connectToTbServer(); + } + + function connectToTbServer() + { + 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"); + monitor.info("MQTT client connected"); + + sendClientError = true; + clientReady = true; + wsmqtt_status = 'connected'; + }); + + client.on('reconnect', function() { + instance.status("Reconnecting", "yellow"); + clientReady = false; + }); + + client.on('message', function(topic, message) { + // message is type of buffer + message = message.toString(); + if (message[0] === '{') { + TRY(function() { + + message = JSON.parse(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}}); + } + + }, () => instance.debug('MQTT: Error parsing data', message)); + } + + instance.send(SEND_TO.rpcCall, {"topic":topic, "content":message }); + }); + + client.on('close', function() { + clientReady = false; + wsmqtt_status = 'disconnected'; + + instance.status("Disconnected", "red"); + instance.send(SEND_TO.debug, {"message":"Client CLOSE signal received !"}); + }); + + client.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; + wsmqtt_status = 'disconnected'; + }); + + } + + + instance.on("0", _ => { + main(); + }) + + + instance.on('1', function(data) { + + if(clientReady) + { + //do we have some data in backup file? if any, process data from database + if(saveTelemetryOnError) + { + //read telemetry data and send back to server + if(!processingData) processDataFromDatabase(); + } + + let stringifiedJson = JSON.stringify(data.data); + client.publish("v1/gateway/telemetry", stringifiedJson, {qos: 1}); + + //backup telemetry + if(createTelemetryBackup) + { + data.data.id = UID(); + nosqlBackup.insert(data.data); + + insertBackupNoSqlCounter++; + if(insertBackupNoSqlCounter > 150) + { + let options = {compress: true}; + let path = __dirname + "/../databases/backup/tbdata.nosql"; + var stream = new rollers.RollingFileStream(path, noSqlFileSizeLimit, 150, options); + stream.write(""); + stream.end(); + + insertBackupNoSqlCounter = 0; + } + } + + } + 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(saveTelemetryOnError) + { + //create new file from tbdata.nosql, if file size exceeds given limit, and clear tbdata.nosql + makeBackupFromDbFile(); + + //write to tb + data.data.id = UID(); + nosql.insert(data.data); + } + } + }); + + + instance.close = function(done) { + if(clientReady){ + client.end(); + clearInterval(sendWsStatusVar); + } + }; + + + function getDbBackupFileCounter(type) + { + var files = fs.readdirSync(__dirname + "/../databases"); + + let counter = 0; + for(var i = 0; i < files.length; i++) + { + + if(files[i] == "tbdata.nosql") continue; + + if(files[i].endsWith(".nosql")) + { + + let pos = files[i].indexOf("."); + if(pos > -1) + { + + let fileCounter = counter; + let firstDigit = files[i].slice(0, pos); + + fileCounter = parseInt(firstDigit); + if(isNaN(fileCounter)) fileCounter = 0; + //console.log("getDbBackupFileCounter digit:", files[i], firstDigit, fileCounter, isNaN(fileCounter), type); + + if(type == "max") + { + if(fileCounter > counter) + { + counter = fileCounter; + } + } + else if(type == "min") + { + if(counter == 0) counter = fileCounter; + + if(fileCounter < counter) + { + counter = fileCounter; + } + } + } + } + + } + + if(type == "max") counter++; + + return counter; + } + + const makeBackupFromDbFile = async () => { + + if(!saveTelemetryOnError) return; + + //to avoid large file: tbdata.nosql + + //init value is 0! + if(insertNoSqlCounter > 0) + { + --insertNoSqlCounter; + return; + } + + insertNoSqlCounter = 100; + + let source = __dirname + "/../databases/tbdata.nosql"; + + var stats = fs.statSync(source); + var fileSizeInBytes = stats.size; + + if(fileSizeInBytes > noSqlFileSizeLimit) + { + + let counter = 1; + counter = getDbBackupFileCounter("max"); + + let destination = __dirname + "/../databases/" + counter + "." + "tbdata.nosql"; + + //make backup file + fs.copyFileSync(source, destination); + //fs.renameSync(p, p + "." + counter); + + //clear tbdata.nosql + fs.writeFileSync(source, ""); + fs.truncateSync(source, 0); + + } + } + + const processDataFromDatabase = async () => { + + if(restore_from_backup <= 0) return; + + //calculate diff + const now = new Date(); + let currentTime = now.getTime(); + let diff = currentTime - lastRestoreTime; + + if( (diff / 1000) < restore_backup_wait) + { + //console.log("*********restore_backup_wait", diff, restore_backup_wait); + return; + } + + processingData = true; + + //get filename to process + let counter = getDbBackupFileCounter("min"); + + //we have some backup files + let dataBase = 'tbdata'; + + var nosql; + if(counter == 0) dataBase = 'tbdata'; + else dataBase = counter + "." + 'tbdata'; + + nosql = NOSQL(dataBase); + + //select all data - use limit restore_from_backup + let records = await promisifyBuilder(nosql.find().take(restore_from_backup)); + + for(let i = 0; i < records.length; i++) + { + if(clientReady) { + + let item = records[i]; + let id = item.id; + + if(id !== undefined) + { + //console.log("------------processDataFromDatabase - remove", id, dataBase, i); + + try { + + let message = JSON.parse(JSON.stringify(item)); + delete message.id; + + client.publish("v1/gateway/telemetry", JSON.stringify(message), {qos:1}); + + //remove from database + await promisifyBuilder(nosql.remove().where("id", id)); + + } catch(error) { + //process error + console.log("processDataFromDatabase", error); + } + + } + + } + else + { + processingData = false; + return; + } + } + + if(records.length > 0) + { + //clean backup file + if(counter > 0) nosql.clean(); + } + + //no data in db, remove + if(records.length == 0) + { + if(counter > 0) nosql.drop(); + } + + const d = new Date(); + lastRestoreTime = d.getTime(); + + processingData = false; + + } + + instance.on('options', main); + //instance.reconfigure(); +}; diff --git a/RVO3/monitor.txt b/RVO3/monitor.txt new file mode 100755 index 0000000..01571cc --- /dev/null +++ b/RVO3/monitor.txt @@ -0,0 +1,8002 @@ +[2024-11-12T15:51:15.084] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2024-11-12T15:51:20.407] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 true turn off on startup +[2024-11-12T15:51:20.419] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 true turn off on startup +[2024-11-12T15:51:20.425] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 true turn off on startup +[2024-11-12T15:51:20.521] [INFO] monitorLogs - MQTT client connected +[2024-11-12T15:51:25.436] [INFO] monitorLogs - buildTasks - params undefined +[2024-11-12T15:51:25.437] [INFO] monitorLogs - buildTasks: profile for line 1 +[2024-11-12T15:51:25.438] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2024-11-12T15:51:25.444] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-12T15:51:25.445] [INFO] monitorLogs - dawn: turn off line: 1 2024-11-13T05:36:00.444Z +[2024-11-12T15:51:25.447] [INFO] monitorLogs - dusk: turn on line: 1 2024-11-12T15:36:00.446Z +[2024-11-12T15:51:25.447] [INFO] monitorLogs - -->time_points final 1 [ + { start_time: '06:36', value: 0, name: 'dawn' }, + { start_time: '16:36', value: 1, name: 'dusk' } +] +[2024-11-12T15:51:25.448] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2024-11-12T15:51:25.449] [INFO] monitorLogs - buildTasks: profile for line 2 +[2024-11-12T15:51:25.450] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2024-11-12T15:51:25.452] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-12T15:51:25.453] [INFO] monitorLogs - dawn: turn off line: 2 2024-11-13T05:36:00.453Z +[2024-11-12T15:51:25.454] [INFO] monitorLogs - dusk: turn on line: 2 2024-11-12T15:36:00.453Z +[2024-11-12T15:51:25.454] [INFO] monitorLogs - -->time_points final 2 [ + { start_time: '06:36', value: 0, name: 'dawn' }, + { start_time: '16:36', value: 1, name: 'dusk' } +] +[2024-11-12T15:51:25.455] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2024-11-12T15:51:25.456] [INFO] monitorLogs - buildTasks: profile for line 3 +[2024-11-12T15:51:25.456] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2024-11-12T15:51:25.458] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-12T15:51:25.459] [INFO] monitorLogs - dawn: turn off line: 3 2024-11-13T05:36:00.459Z +[2024-11-12T15:51:25.460] [INFO] monitorLogs - dusk: turn on line: 3 2024-11-12T15:36:00.460Z +[2024-11-12T15:51:25.460] [INFO] monitorLogs - -->time_points final 3 [ + { start_time: '06:36', value: 0, name: 'dawn' }, + { start_time: '16:36', value: 1, name: 'dusk' } +] +[2024-11-12T15:51:25.461] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2024-11-12T15:51:25.463] [INFO] monitorLogs - tasks created: 14 +[2024-11-12T15:51:25.471] [INFO] monitorLogs - -->FLOW bol spustený dz4ojlpP85JMgDLZWkQJ4D7aKYqQexEr62GXRV1y 2024-11-04 +[2024-11-12T15:53:34.999] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2024-11-12T15:53:40.392] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 true turn off on startup +[2024-11-12T15:53:40.405] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 true turn off on startup +[2024-11-12T15:53:40.410] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 true turn off on startup +[2024-11-12T15:53:40.513] [INFO] monitorLogs - MQTT client connected +[2024-11-12T15:53:45.421] [INFO] monitorLogs - buildTasks - params undefined +[2024-11-12T15:53:45.422] [INFO] monitorLogs - buildTasks: profile for line 1 +[2024-11-12T15:53:45.423] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2024-11-12T15:53:45.428] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-12T15:53:45.429] [INFO] monitorLogs - dawn: turn off line: 1 2024-11-13T05:36:00.428Z +[2024-11-12T15:53:45.430] [INFO] monitorLogs - dusk: turn on line: 1 2024-11-12T15:36:00.430Z +[2024-11-12T15:53:45.431] [INFO] monitorLogs - -->time_points final 1 [ + { start_time: '06:36', value: 0, name: 'dawn' }, + { start_time: '16:36', value: 1, name: 'dusk' } +] +[2024-11-12T15:53:45.433] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2024-11-12T15:53:45.433] [INFO] monitorLogs - buildTasks: profile for line 2 +[2024-11-12T15:53:45.434] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2024-11-12T15:53:45.437] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-12T15:53:45.437] [INFO] monitorLogs - dawn: turn off line: 2 2024-11-13T05:36:00.437Z +[2024-11-12T15:53:45.438] [INFO] monitorLogs - dusk: turn on line: 2 2024-11-12T15:36:00.438Z +[2024-11-12T15:53:45.439] [INFO] monitorLogs - -->time_points final 2 [ + { start_time: '06:36', value: 0, name: 'dawn' }, + { start_time: '16:36', value: 1, name: 'dusk' } +] +[2024-11-12T15:53:45.440] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2024-11-12T15:53:45.440] [INFO] monitorLogs - buildTasks: profile for line 3 +[2024-11-12T15:53:45.441] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2024-11-12T15:53:45.443] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-12T15:53:45.444] [INFO] monitorLogs - dawn: turn off line: 3 2024-11-13T05:36:00.443Z +[2024-11-12T15:53:45.445] [INFO] monitorLogs - dusk: turn on line: 3 2024-11-12T15:36:00.445Z +[2024-11-12T15:53:45.445] [INFO] monitorLogs - -->time_points final 3 [ + { start_time: '06:36', value: 0, name: 'dawn' }, + { start_time: '16:36', value: 1, name: 'dusk' } +] +[2024-11-12T15:53:45.446] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2024-11-12T15:53:45.448] [INFO] monitorLogs - tasks created: 14 +[2024-11-12T15:53:45.451] [INFO] monitorLogs - -->FLOW bol spustený dz4ojlpP85JMgDLZWkQJ4D7aKYqQexEr62GXRV1y 2024-11-04 +[2024-11-12T16:36:00.595] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-12T16:36:00.639] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-12T16:36:00.687] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-13T03:53:40.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-13 03:53:40 +[2024-11-13T06:36:00.632] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-13T06:36:00.674] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-13T06:36:00.714] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-13T10:21:01.011] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2024-11-13T10:21:06.330] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 true turn off on startup +[2024-11-13T10:21:06.343] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 true turn off on startup +[2024-11-13T10:21:06.348] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 true turn off on startup +[2024-11-13T10:21:06.462] [INFO] monitorLogs - MQTT client connected +[2024-11-13T10:21:11.359] [INFO] monitorLogs - buildTasks - params undefined +[2024-11-13T10:21:11.360] [INFO] monitorLogs - buildTasks: profile for line 1 +[2024-11-13T10:21:11.361] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2024-11-13T10:21:11.365] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-13T10:21:11.367] [INFO] monitorLogs - dawn: turn off line: 1 2024-11-14T05:37:00.366Z +[2024-11-13T10:21:11.368] [INFO] monitorLogs - dusk: turn on line: 1 2024-11-13T15:35:00.368Z +[2024-11-13T10:21:11.369] [INFO] monitorLogs - -->time_points final 1 [ + { start_time: '06:37', value: 0, name: 'dawn' }, + { start_time: '16:35', value: 1, name: 'dusk' } +] +[2024-11-13T10:21:11.370] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2024-11-13T10:21:11.371] [INFO] monitorLogs - buildTasks: profile for line 2 +[2024-11-13T10:21:11.372] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2024-11-13T10:21:11.374] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-13T10:21:11.375] [INFO] monitorLogs - dawn: turn off line: 2 2024-11-14T05:37:00.375Z +[2024-11-13T10:21:11.376] [INFO] monitorLogs - dusk: turn on line: 2 2024-11-13T15:35:00.376Z +[2024-11-13T10:21:11.376] [INFO] monitorLogs - -->time_points final 2 [ + { start_time: '06:37', value: 0, name: 'dawn' }, + { start_time: '16:35', value: 1, name: 'dusk' } +] +[2024-11-13T10:21:11.377] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2024-11-13T10:21:11.378] [INFO] monitorLogs - buildTasks: profile for line 3 +[2024-11-13T10:21:11.379] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2024-11-13T10:21:11.381] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-13T10:21:11.382] [INFO] monitorLogs - dawn: turn off line: 3 2024-11-14T05:37:00.381Z +[2024-11-13T10:21:11.382] [INFO] monitorLogs - dusk: turn on line: 3 2024-11-13T15:35:00.382Z +[2024-11-13T10:21:11.383] [INFO] monitorLogs - -->time_points final 3 [ + { start_time: '06:37', value: 0, name: 'dawn' }, + { start_time: '16:35', value: 1, name: 'dusk' } +] +[2024-11-13T10:21:11.384] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2024-11-13T10:21:11.386] [INFO] monitorLogs - tasks created: 14 +[2024-11-13T10:21:11.394] [INFO] monitorLogs - -->FLOW bol spustený dz4ojlpP85JMgDLZWkQJ4D7aKYqQexEr62GXRV1y 2024-11-04 +[2024-11-13T16:35:00.528] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-13T16:35:00.574] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-13T16:35:00.613] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-14T03:21:07.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-14 03:21:07 +[2024-11-14T06:37:00.471] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-14T06:37:00.513] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-14T06:37:00.552] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-14T16:33:56.993] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-14T16:33:57.033] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-14T16:33:57.071] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-15T03:21:08.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-15 03:21:08 +[2024-11-15T06:41:05.680] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-15T06:41:05.719] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-15T06:41:05.758] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-15T16:32:45.019] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-15T16:32:45.057] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-15T16:32:45.095] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-16T03:21:09.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-16 03:21:09 +[2024-11-16T06:42:38.424] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-16T06:42:38.465] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-16T06:42:38.503] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-16T16:31:35.229] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-16T16:31:35.268] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-16T16:31:35.306] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-17T03:21:09.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-17 03:21:09 +[2024-11-17T06:44:10.880] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-17T06:44:10.922] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-17T06:44:10.962] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-17T16:30:27.582] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-17T16:30:27.628] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-17T16:30:27.667] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-18T03:21:10.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-18 03:21:10 +[2024-11-18T06:45:42.444] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-18T06:45:42.485] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-18T06:45:42.524] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-18T08:17:23.808] [INFO] monitorLogs - MQTT client connected +[2024-11-18T16:29:22.119] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-18T16:29:22.159] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-18T16:29:22.197] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-19T03:21:16.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-19 03:21:16 +[2024-11-19T06:47:13.367] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-19T06:47:13.409] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-19T06:47:13.448] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-19T16:28:18.740] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-19T16:28:18.779] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-19T16:28:18.818] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-20T03:21:11.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-20 03:21:11 +[2024-11-20T06:48:43.728] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-20T06:48:43.769] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-20T06:48:43.808] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-20T16:27:18.064] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-20T16:27:18.103] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-20T16:27:18.141] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-21T03:21:12.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-21 03:21:12 +[2024-11-21T06:50:13.061] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-21T06:50:13.102] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-21T06:50:13.141] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-21T16:26:19.565] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-21T16:26:19.606] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-21T16:26:19.644] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-22T03:21:12.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-22 03:21:12 +[2024-11-22T06:51:41.504] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-22T06:51:41.557] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-22T06:51:41.597] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-22T09:05:31.813] [INFO] monitorLogs - MQTT client connected +[2024-11-22T16:25:23.527] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-22T16:25:23.566] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-22T16:25:23.604] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-23T03:21:13.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-23 03:21:13 +[2024-11-23T06:53:08.874] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-23T06:53:08.915] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-23T06:53:08.953] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-23T13:31:21.591] [INFO] monitorLogs - MQTT client connected +[2024-11-23T13:58:23.486] [INFO] monitorLogs - MQTT client connected +[2024-11-23T14:12:55.793] [INFO] monitorLogs - MQTT client connected +[2024-11-23T14:18:00.855] [INFO] monitorLogs - MQTT client connected +[2024-11-23T14:36:22.862] [INFO] monitorLogs - MQTT client connected +[2024-11-23T16:24:30.024] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-23T16:24:30.064] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-23T16:24:30.100] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-24T06:54:35.274] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-24T06:54:35.314] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-24T06:54:35.351] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-24T16:08:20.943] [INFO] monitorLogs - MQTT client connected +[2024-11-24T16:23:38.983] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-24T16:23:39.030] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-24T16:23:39.069] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-24T23:11:37.376] [INFO] monitorLogs - MQTT client connected +[2024-11-25T01:27:48.552] [INFO] monitorLogs - MQTT client error Error: Connection refused: Server unavailable + at MqttClient._handleConnack (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:1388:17) + at MqttClient._handlePacket (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:549:12) + at work (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:438:12) + at Writable.writable._write (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:452:5) + at doWrite (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:409:139) + at writeOrBuffer (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:398:5) + at Writable.write (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:307:11) + at Socket.ondata (internal/streams/readable.js:731:22) + at Socket.emit (events.js:400:28) + at addChunk (internal/streams/readable.js:293:12) { + code: 3 +} +[2024-11-25T01:27:49.832] [INFO] monitorLogs - MQTT client connected +[2024-11-25T01:28:24.071] [INFO] monitorLogs - MQTT client error Error: Connection refused: Server unavailable + at MqttClient._handleConnack (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:1388:17) + at MqttClient._handlePacket (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:549:12) + at work (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:438:12) + at Writable.writable._write (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:452:5) + at doWrite (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:409:139) + at writeOrBuffer (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:398:5) + at Writable.write (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:307:11) + at Socket.ondata (internal/streams/readable.js:731:22) + at Socket.emit (events.js:400:28) + at addChunk (internal/streams/readable.js:293:12) { + code: 3 +} +[2024-11-25T01:28:25.991] [INFO] monitorLogs - MQTT client connected +[2024-11-25T02:12:05.176] [INFO] monitorLogs - MQTT client connected +[2024-11-25T02:14:06.454] [INFO] monitorLogs - MQTT client connected +[2024-11-25T03:21:14.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-25 03:21:14 +[2024-11-25T05:11:02.569] [INFO] monitorLogs - MQTT client error Error: Connection refused: Server unavailable + at MqttClient._handleConnack (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:1388:17) + at MqttClient._handlePacket (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:549:12) + at work (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:438:12) + at Writable.writable._write (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:452:5) + at doWrite (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:409:139) + at writeOrBuffer (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:398:5) + at Writable.write (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:307:11) + at Socket.ondata (internal/streams/readable.js:731:22) + at Socket.emit (events.js:400:28) + at addChunk (internal/streams/readable.js:293:12) { + code: 3 +} +[2024-11-25T05:11:04.064] [INFO] monitorLogs - MQTT client connected +[2024-11-25T05:14:25.343] [INFO] monitorLogs - MQTT client error Error: Connection refused: Server unavailable + at MqttClient._handleConnack (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:1388:17) + at MqttClient._handlePacket (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:549:12) + at work (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:438:12) + at Writable.writable._write (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:452:5) + at doWrite (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:409:139) + at writeOrBuffer (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:398:5) + at Writable.write (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:307:11) + at Socket.ondata (internal/streams/readable.js:731:22) + at Socket.emit (events.js:400:28) + at addChunk (internal/streams/readable.js:293:12) { + code: 3 +} +[2024-11-25T05:14:26.303] [INFO] monitorLogs - MQTT client connected +[2024-11-25T06:11:16.542] [INFO] monitorLogs - MQTT client error Error: Connection refused: Server unavailable + at MqttClient._handleConnack (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:1388:17) + at MqttClient._handlePacket (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:549:12) + at work (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:438:12) + at Writable.writable._write (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:452:5) + at doWrite (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:409:139) + at writeOrBuffer (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:398:5) + at Writable.write (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:307:11) + at Socket.ondata (internal/streams/readable.js:731:22) + at Socket.emit (events.js:400:28) + at addChunk (internal/streams/readable.js:293:12) { + code: 3 +} +[2024-11-25T06:11:19.422] [INFO] monitorLogs - MQTT client connected +[2024-11-25T06:12:19.850] [INFO] monitorLogs - MQTT client connected +[2024-11-25T06:12:22.141] [INFO] monitorLogs - MQTT client connected +[2024-11-25T06:56:00.358] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-25T06:56:00.400] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-25T06:56:00.438] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-25T07:10:04.178] [INFO] monitorLogs - MQTT client error Error: Connection refused: Server unavailable + at MqttClient._handleConnack (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:1388:17) + at MqttClient._handlePacket (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:549:12) + at work (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:438:12) + at Writable.writable._write (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:452:5) + at doWrite (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:409:139) + at writeOrBuffer (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:398:5) + at Writable.write (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:307:11) + at Socket.ondata (internal/streams/readable.js:731:22) + at Socket.emit (events.js:400:28) + at addChunk (internal/streams/readable.js:293:12) { + code: 3 +} +[2024-11-25T07:10:20.289] [INFO] monitorLogs - MQTT client connected +[2024-11-25T08:11:25.873] [INFO] monitorLogs - MQTT client connected +[2024-11-25T13:59:05.870] [INFO] monitorLogs - MQTT client connected +[2024-11-25T14:00:22.340] [INFO] monitorLogs - MQTT client error Error: Connection refused: Server unavailable + at MqttClient._handleConnack (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:1388:17) + at MqttClient._handlePacket (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:549:12) + at work (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:438:12) + at Writable.writable._write (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:452:5) + at doWrite (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:409:139) + at writeOrBuffer (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:398:5) + at Writable.write (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:307:11) + at Socket.ondata (internal/streams/readable.js:731:22) + at Socket.emit (events.js:400:28) + at addChunk (internal/streams/readable.js:293:12) { + code: 3 +} +[2024-11-25T14:00:22.745] [INFO] monitorLogs - MQTT client connected +[2024-11-25T16:22:50.226] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-25T16:22:50.270] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-25T16:22:50.309] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-26T01:10:13.756] [INFO] monitorLogs - MQTT client error Error: Connection refused: Server unavailable + at MqttClient._handleConnack (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:1388:17) + at MqttClient._handlePacket (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:549:12) + at work (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:438:12) + at Writable.writable._write (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:452:5) + at doWrite (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:409:139) + at writeOrBuffer (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:398:5) + at Writable.write (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:307:11) + at Socket.ondata (internal/streams/readable.js:731:22) + at Socket.emit (events.js:400:28) + at addChunk (internal/streams/readable.js:293:12) { + code: 3 +} +[2024-11-26T01:10:17.875] [INFO] monitorLogs - MQTT client connected +[2024-11-26T01:11:14.964] [INFO] monitorLogs - MQTT client connected +[2024-11-26T03:21:14.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-26 03:21:14 +[2024-11-26T06:57:24.513] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-26T06:57:24.555] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-26T06:57:24.594] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-26T08:05:54.617] [INFO] monitorLogs - MQTT client connected +[2024-11-26T16:22:04.205] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-26T16:22:04.246] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-26T16:22:04.284] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-27T03:21:15.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-27 03:21:15 +[2024-11-27T06:58:47.310] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-27T06:58:47.351] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-27T06:58:47.391] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-27T16:21:20.980] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-27T16:21:21.024] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-27T16:21:21.063] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-28T03:21:16.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-28 03:21:16 +[2024-11-28T07:00:08.641] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-28T07:00:08.682] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-28T07:00:08.723] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-28T16:20:40.300] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-28T16:20:40.342] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-28T16:20:40.380] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-29T03:21:16.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-29 03:21:16 +[2024-11-29T07:01:28.426] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-29T07:01:28.467] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-29T07:01:28.505] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-29T09:09:24.408] [INFO] monitorLogs - MQTT client connected +[2024-11-29T16:20:02.201] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-29T16:20:02.243] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-29T16:20:02.282] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-30T03:21:17.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-30 03:21:17 +[2024-11-30T07:02:47.145] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-30T07:02:47.186] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-30T07:02:47.225] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-30T15:36:49.712] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2024-11-30T15:36:55.051] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 true turn off on startup +[2024-11-30T15:36:55.063] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 true turn off on startup +[2024-11-30T15:36:55.068] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 true turn off on startup +[2024-11-30T15:36:55.168] [INFO] monitorLogs - MQTT client connected +[2024-11-30T15:37:00.078] [INFO] monitorLogs - buildTasks - params undefined +[2024-11-30T15:37:00.079] [INFO] monitorLogs - buildTasks: profile for line 1 +[2024-11-30T15:37:00.080] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2024-11-30T15:37:00.084] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-30T15:37:00.086] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 1 2024-12-01T06:02:00.085Z +[2024-11-30T15:37:00.087] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 1 2024-11-30T15:19:00.087Z +[2024-11-30T15:37:00.088] [INFO] monitorLogs - -->time_points final 1 [ + { start_time: '07:02', value: 0, name: 'dawn' }, + { start_time: '16:19', value: 1, name: 'dusk' } +] +[2024-11-30T15:37:00.089] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2024-11-30T15:37:00.090] [INFO] monitorLogs - buildTasks: profile for line 2 +[2024-11-30T15:37:00.091] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2024-11-30T15:37:00.093] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-30T15:37:00.094] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 2 2024-12-01T06:02:00.094Z +[2024-11-30T15:37:00.095] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 2 2024-11-30T15:19:00.095Z +[2024-11-30T15:37:00.095] [INFO] monitorLogs - -->time_points final 2 [ + { start_time: '07:02', value: 0, name: 'dawn' }, + { start_time: '16:19', value: 1, name: 'dusk' } +] +[2024-11-30T15:37:00.096] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2024-11-30T15:37:00.097] [INFO] monitorLogs - buildTasks: profile for line 3 +[2024-11-30T15:37:00.098] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2024-11-30T15:37:00.100] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-30T15:37:00.101] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 3 2024-12-01T06:02:00.100Z +[2024-11-30T15:37:00.101] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 3 2024-11-30T15:19:00.101Z +[2024-11-30T15:37:00.102] [INFO] monitorLogs - -->time_points final 3 [ + { start_time: '07:02', value: 0, name: 'dawn' }, + { start_time: '16:19', value: 1, name: 'dusk' } +] +[2024-11-30T15:37:00.103] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2024-11-30T15:37:00.104] [INFO] monitorLogs - tasks created: 14 +[2024-11-30T15:37:00.113] [INFO] monitorLogs - -->FLOW bol spustený dz4ojlpP85JMgDLZWkQJ4D7aKYqQexEr62GXRV1y 2024-11-04 +[2024-11-30T16:19:00.217] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-30T16:19:00.260] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-30T16:19:00.300] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-01T03:36:56.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-01 03:36:56 +[2024-12-01T07:02:00.154] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-01T07:02:00.195] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-01T07:02:00.235] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-01T16:18:54.440] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-01T16:18:54.480] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-01T16:18:54.519] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-02T03:36:56.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-02 03:36:56 +[2024-12-02T07:05:19.143] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-02T07:05:19.193] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-02T07:05:19.233] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-02T16:18:24.622] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-02T16:18:24.667] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-02T16:18:24.705] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-03T03:36:57.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-03 03:36:57 +[2024-12-03T07:06:32.584] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-03T07:06:32.626] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-03T07:06:32.665] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-03T16:17:57.888] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-03T16:17:57.932] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-03T16:17:57.969] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-04T00:19:06.167] [INFO] monitorLogs - MQTT client connected +[2024-12-04T03:36:58.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-04 03:36:58 +[2024-12-04T07:07:44.390] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-04T07:07:44.433] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-04T07:07:44.471] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-04T08:53:08.049] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2024-12-04T08:53:13.444] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 true turn off on startup +[2024-12-04T08:53:13.456] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 true turn off on startup +[2024-12-04T08:53:13.461] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 true turn off on startup +[2024-12-04T08:53:18.472] [INFO] monitorLogs - buildTasks - params undefined +[2024-12-04T08:53:18.474] [INFO] monitorLogs - buildTasks: profile for line 1 +[2024-12-04T08:53:18.474] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2024-12-04T08:53:18.478] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-12-04T08:53:18.480] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 1 2024-12-05T06:07:00.479Z +[2024-12-04T08:53:18.481] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 1 2024-12-04T15:17:00.480Z +[2024-12-04T08:53:18.481] [INFO] monitorLogs - -->time_points final 1 [ + { start_time: '07:07', value: 0, name: 'dawn' }, + { start_time: '16:17', value: 1, name: 'dusk' } +] +[2024-12-04T08:53:18.483] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2024-12-04T08:53:18.484] [INFO] monitorLogs - buildTasks: profile for line 2 +[2024-12-04T08:53:18.484] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2024-12-04T08:53:18.487] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-12-04T08:53:18.488] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 2 2024-12-05T06:07:00.488Z +[2024-12-04T08:53:18.489] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 2 2024-12-04T15:17:00.489Z +[2024-12-04T08:53:18.489] [INFO] monitorLogs - -->time_points final 2 [ + { start_time: '07:07', value: 0, name: 'dawn' }, + { start_time: '16:17', value: 1, name: 'dusk' } +] +[2024-12-04T08:53:18.490] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2024-12-04T08:53:18.491] [INFO] monitorLogs - buildTasks: profile for line 3 +[2024-12-04T08:53:18.491] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2024-12-04T08:53:18.494] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-12-04T08:53:18.494] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 3 2024-12-05T06:07:00.494Z +[2024-12-04T08:53:18.495] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 3 2024-12-04T15:17:00.495Z +[2024-12-04T08:53:18.496] [INFO] monitorLogs - -->time_points final 3 [ + { start_time: '07:07', value: 0, name: 'dawn' }, + { start_time: '16:17', value: 1, name: 'dusk' } +] +[2024-12-04T08:53:18.497] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2024-12-04T08:53:18.498] [INFO] monitorLogs - tasks created: 14 +[2024-12-04T08:53:18.500] [INFO] monitorLogs - -->FLOW bol spustený dz4ojlpP85JMgDLZWkQJ4D7aKYqQexEr62GXRV1y 2024-11-04 +[2024-12-04T09:03:19.072] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2024-12-04T09:03:24.470] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 true turn off on startup +[2024-12-04T09:03:24.483] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 true turn off on startup +[2024-12-04T09:03:24.488] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 true turn off on startup +[2024-12-04T09:03:29.501] [INFO] monitorLogs - buildTasks - params undefined +[2024-12-04T09:03:29.502] [INFO] monitorLogs - buildTasks: profile for line 1 +[2024-12-04T09:03:29.502] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2024-12-04T09:03:29.507] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-12-04T09:03:29.508] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 1 2024-12-05T06:07:00.507Z +[2024-12-04T09:03:29.509] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 1 2024-12-04T15:17:00.509Z +[2024-12-04T09:03:29.510] [INFO] monitorLogs - -->time_points final 1 [ + { start_time: '07:07', value: 0, name: 'dawn' }, + { start_time: '16:17', value: 1, name: 'dusk' } +] +[2024-12-04T09:03:29.511] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2024-12-04T09:03:29.512] [INFO] monitorLogs - buildTasks: profile for line 2 +[2024-12-04T09:03:29.512] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2024-12-04T09:03:29.515] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-12-04T09:03:29.516] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 2 2024-12-05T06:07:00.515Z +[2024-12-04T09:03:29.516] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 2 2024-12-04T15:17:00.516Z +[2024-12-04T09:03:29.517] [INFO] monitorLogs - -->time_points final 2 [ + { start_time: '07:07', value: 0, name: 'dawn' }, + { start_time: '16:17', value: 1, name: 'dusk' } +] +[2024-12-04T09:03:29.518] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2024-12-04T09:03:29.519] [INFO] monitorLogs - buildTasks: profile for line 3 +[2024-12-04T09:03:29.519] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2024-12-04T09:03:29.521] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-12-04T09:03:29.522] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 3 2024-12-05T06:07:00.522Z +[2024-12-04T09:03:29.522] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 3 2024-12-04T15:17:00.522Z +[2024-12-04T09:03:29.523] [INFO] monitorLogs - -->time_points final 3 [ + { start_time: '07:07', value: 0, name: 'dawn' }, + { start_time: '16:17', value: 1, name: 'dusk' } +] +[2024-12-04T09:03:29.524] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2024-12-04T09:03:29.525] [INFO] monitorLogs - tasks created: 14 +[2024-12-04T09:03:29.528] [INFO] monitorLogs - -->FLOW bol spustený dz4ojlpP85JMgDLZWkQJ4D7aKYqQexEr62GXRV1y 2024-11-04 +[2024-12-04T09:03:31.511] [INFO] monitorLogs - MQTT client connected +[2024-12-04T16:17:00.737] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-04T16:17:00.782] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-04T16:17:00.822] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-05T03:03:24.013] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-05 03:03:24 +[2024-12-05T07:07:00.602] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-05T07:07:00.644] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-05T07:07:00.682] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-05T15:56:53.051] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:56:54.075] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:56:54.077] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:56:55.083] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:56:55.084] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:56:55.086] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:56:55.087] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:56:56.089] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:56:56.090] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:56:56.097] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:56:56.098] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:56:56.101] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:56:56.101] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:56:56.103] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:56:56.104] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:56:57.096] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:56:57.097] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:56:57.116] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:56:57.117] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:56:57.123] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:56:57.124] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:56:57.126] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:56:57.127] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:56:57.128] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:56:57.129] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:56:57.131] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:56:57.131] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:56:57.133] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:56:57.134] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:56:57.138] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:56:57.139] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:56:58.101] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:56:58.102] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:56:58.108] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:56:58.109] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:56:58.121] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:56:58.122] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:56:58.124] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:56:58.125] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:56:58.141] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:56:58.142] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:56:58.144] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:56:58.145] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:56:58.146] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:56:58.147] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:56:58.156] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:56:58.157] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:56:58.159] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:56:58.160] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:56:58.161] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:56:58.162] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:56:58.164] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:56:58.164] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:56:58.166] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:56:58.167] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:56:58.169] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:56:58.170] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:56:58.172] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:56:58.173] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:56:58.174] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:56:58.175] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:56:58.177] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:56:58.178] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:56:59.108] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:56:59.109] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:56:59.115] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:56:59.116] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:56:59.121] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:56:59.122] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:56:59.127] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:56:59.128] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:56:59.134] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:56:59.135] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:56:59.136] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:56:59.137] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:56:59.139] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:56:59.140] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:56:59.142] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:56:59.143] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:56:59.155] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:56:59.156] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:56:59.157] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:56:59.158] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:56:59.166] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:56:59.167] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:56:59.168] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:56:59.169] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:56:59.170] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:56:59.171] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:56:59.173] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:56:59.174] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:56:59.194] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:56:59.195] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:56:59.196] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:56:59.197] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:56:59.199] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:56:59.199] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:56:59.213] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:56:59.213] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:56:59.215] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:56:59.216] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:56:59.217] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:56:59.218] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:56:59.220] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:56:59.220] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:56:59.222] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:56:59.223] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:56:59.224] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:56:59.225] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:56:59.226] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:56:59.227] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:56:59.229] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:56:59.230] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:56:59.231] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:56:59.232] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:56:59.233] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:56:59.234] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:56:59.236] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:56:59.237] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:56:59.239] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:56:59.240] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:56:59.242] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:56:59.242] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:56:59.244] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:56:59.245] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:56:59.247] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:56:59.247] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:00.115] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:00.116] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:00.122] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:00.123] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:00.129] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:00.130] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:00.132] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:00.132] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:00.138] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:00.139] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:00.140] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:00.141] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:00.157] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:00.158] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:00.160] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:00.161] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:00.172] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:00.173] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:00.174] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:00.175] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:00.176] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:00.177] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:00.179] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:00.179] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:00.181] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:00.182] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:00.183] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:00.184] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:00.186] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:00.186] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:00.202] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:00.203] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:00.204] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:00.205] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:00.207] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:00.207] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:00.209] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:00.210] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:00.211] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:00.212] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:00.228] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:00.229] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:00.230] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:00.231] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:00.233] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:00.234] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:00.235] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:00.236] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:00.238] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:00.238] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:00.240] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:00.241] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:00.242] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:00.243] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:00.245] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:00.245] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:00.297] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:00.297] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:00.299] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:00.300] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:00.301] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:00.302] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:00.303] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:00.304] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:00.306] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:00.307] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:00.308] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:00.309] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:00.310] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:00.311] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:00.313] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:00.313] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:00.318] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:00.320] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:00.321] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:00.323] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:00.324] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:00.325] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:00.327] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:00.327] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:00.329] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:00.330] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:00.331] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:00.332] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:00.337] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:00.338] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:00.339] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:00.340] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:00.341] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:00.342] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:00.344] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:00.345] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:00.346] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:00.347] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:00.348] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:00.349] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:00.351] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:00.351] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:00.353] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:00.354] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:00.355] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:00.356] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:00.358] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:00.358] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:00.360] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:00.361] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:00.362] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:00.363] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:00.365] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:00.365] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:00.367] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:00.368] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:00.369] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:00.370] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:00.371] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:00.372] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:00.374] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:00.375] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:00.376] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:00.377] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:00.378] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:00.379] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:00.381] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:00.382] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:00.383] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:00.384] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:00.385] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:00.386] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.122] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.123] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.132] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.133] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.154] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.155] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.157] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.158] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.185] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.186] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.188] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.188] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.190] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.191] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.192] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.193] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.224] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.224] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.226] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.227] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.228] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.229] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.231] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.231] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.234] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.235] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.237] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.238] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.279] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.280] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.282] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.282] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.284] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.285] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.286] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.287] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.288] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.289] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.291] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.292] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.293] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.294] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.295] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.296] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.298] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.298] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.300] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.301] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.302] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.303] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.305] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.305] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.307] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.308] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.309] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.310] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.312] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.312] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.314] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.315] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.386] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.387] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.389] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.389] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.391] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.392] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.394] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.394] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.396] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.397] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.398] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.399] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.400] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.401] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.403] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.404] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.405] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.406] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.407] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.408] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.410] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.411] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.412] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.413] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.414] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.415] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.417] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.418] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.419] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.420] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.421] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.422] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.424] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.425] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.426] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.427] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.428] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.429] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.431] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.432] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.433] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.434] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.534] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.535] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.537] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.538] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.539] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.540] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.541] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.542] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.544] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.544] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.546] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.547] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.552] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.553] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.555] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.556] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.557] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.558] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.559] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.560] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.562] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.563] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.564] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.565] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.566] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.567] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.569] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.569] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.571] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.572] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.573] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.574] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.576] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.577] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.578] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.579] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.580] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.581] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.583] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.583] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.585] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.586] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.598] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.600] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.602] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.603] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.605] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.606] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.608] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.609] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.611] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.612] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.614] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.615] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.617] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.618] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.619] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.620] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.621] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.622] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.624] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.625] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.626] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.627] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.628] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.632] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.633] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.634] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.636] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.637] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.638] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.639] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.640] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.641] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.643] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.643] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.645] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.646] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.647] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.648] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.649] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.650] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.652] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.653] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.655] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.655] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.657] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.658] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.659] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.660] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.661] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.662] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.664] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.665] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.666] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.667] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.668] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.669] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.671] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.671] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.673] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.674] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.675] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.676] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.678] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.678] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.680] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.681] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.682] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.683] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.684] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.685] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.687] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.687] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.689] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.690] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.691] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.692] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.693] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.694] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.696] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.697] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.698] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.699] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.700] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.701] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.703] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.703] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.705] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.706] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.707] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.708] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.710] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.710] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.712] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.713] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.714] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.715] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.716] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.717] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.719] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.720] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.721] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.722] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.723] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.724] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.726] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.727] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.728] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.729] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.730] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.731] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:01.733] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:01.734] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:02.129] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:02.129] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:02.131] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:02.132] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:02.138] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:02.139] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:02.141] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:02.141] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:02.165] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:02.166] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:02.168] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:02.169] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:02.171] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:02.172] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:02.173] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:02.174] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:02.190] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:02.191] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:02.206] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:02.206] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:02.209] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:02.210] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:02.211] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:02.212] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:02.213] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:02.214] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:02.215] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:02.216] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:02.218] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:02.218] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:02.220] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:02.220] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:02.230] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:02.231] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:02.241] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:02.242] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:02.243] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:02.245] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:02.255] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:02.256] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:02.257] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:02.258] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:02.259] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:02.260] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:02.261] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:02.262] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:02.264] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:02.265] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:02.267] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:02.267] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:02.269] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:02.270] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:02.271] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:02.272] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:02.273] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:02.274] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:02.284] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:02.284] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:02.295] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:02.296] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:02.313] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:02.314] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:02.315] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:02.316] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:02.318] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:02.318] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:02.320] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:02.321] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:02.322] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:02.323] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:02.351] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:02.352] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:02.354] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:02.354] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:02.356] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:02.357] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:02.358] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:02.359] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:02.360] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:02.361] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:02.362] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:02.363] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:02.365] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:02.365] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:02.367] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:02.367] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:02.369] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:02.370] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:02.377] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:02.378] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:02.379] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:02.380] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:02.381] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:02.382] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:02.383] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T15:57:02.384] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-05T15:57:02.385] [INFO] monitorLogs - websocket error, reconnect +[2024-12-05T16:05:17.055] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2024-12-05T16:05:22.436] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 true turn off on startup +[2024-12-05T16:05:22.449] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 true turn off on startup +[2024-12-05T16:05:22.454] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 true turn off on startup +[2024-12-05T16:05:22.627] [INFO] monitorLogs - MQTT client connected +[2024-12-05T16:05:27.464] [INFO] monitorLogs - buildTasks - params undefined +[2024-12-05T16:05:27.465] [INFO] monitorLogs - buildTasks: profile for line 1 +[2024-12-05T16:05:27.466] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2024-12-05T16:05:27.470] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-12-05T16:05:27.472] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 1 2024-12-06T06:08:00.471Z +[2024-12-05T16:05:27.473] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 1 2024-12-05T15:17:00.473Z +[2024-12-05T16:05:27.474] [INFO] monitorLogs - -->time_points final 1 [ + { start_time: '07:08', value: 0, name: 'dawn' }, + { start_time: '16:17', value: 1, name: 'dusk' } +] +[2024-12-05T16:05:27.475] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2024-12-05T16:05:27.476] [INFO] monitorLogs - buildTasks: profile for line 2 +[2024-12-05T16:05:27.477] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2024-12-05T16:05:27.479] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-12-05T16:05:27.480] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 2 2024-12-06T06:08:00.480Z +[2024-12-05T16:05:27.480] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 2 2024-12-05T15:17:00.480Z +[2024-12-05T16:05:27.481] [INFO] monitorLogs - -->time_points final 2 [ + { start_time: '07:08', value: 0, name: 'dawn' }, + { start_time: '16:17', value: 1, name: 'dusk' } +] +[2024-12-05T16:05:27.482] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2024-12-05T16:05:27.483] [INFO] monitorLogs - buildTasks: profile for line 3 +[2024-12-05T16:05:27.483] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2024-12-05T16:05:27.485] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-12-05T16:05:27.486] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 3 2024-12-06T06:08:00.486Z +[2024-12-05T16:05:27.487] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 3 2024-12-05T15:17:00.487Z +[2024-12-05T16:05:27.488] [INFO] monitorLogs - -->time_points final 3 [ + { start_time: '07:08', value: 0, name: 'dawn' }, + { start_time: '16:17', value: 1, name: 'dusk' } +] +[2024-12-05T16:05:27.489] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2024-12-05T16:05:27.491] [INFO] monitorLogs - tasks created: 14 +[2024-12-05T16:05:27.499] [INFO] monitorLogs - -->FLOW bol spustený dz4ojlpP85JMgDLZWkQJ4D7aKYqQexEr62GXRV1y 2024-11-04 +[2024-12-05T16:17:00.747] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-05T16:17:00.791] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-05T16:17:00.834] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-06T03:05:24.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-06 03:05:24 +[2024-12-06T07:08:00.535] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-06T07:08:00.576] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-06T07:08:00.615] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-06T08:56:13.623] [INFO] monitorLogs - MQTT client connected +[2024-12-06T09:28:21.188] [INFO] monitorLogs - MQTT client connected +[2024-12-06T09:34:21.394] [INFO] monitorLogs - MQTT client connected +[2024-12-06T09:35:42.294] [INFO] monitorLogs - MQTT client connected +[2024-12-06T09:41:42.208] [INFO] monitorLogs - MQTT client connected +[2024-12-06T10:15:42.144] [INFO] monitorLogs - MQTT client connected +[2024-12-06T10:22:21.073] [INFO] monitorLogs - MQTT client connected +[2024-12-06T10:47:41.543] [INFO] monitorLogs - MQTT client connected +[2024-12-06T11:07:33.925] [INFO] monitorLogs - MQTT client connected +[2024-12-06T11:08:41.957] [INFO] monitorLogs - MQTT client connected +[2024-12-06T11:30:57.221] [INFO] monitorLogs - MQTT client connected +[2024-12-06T11:33:27.802] [INFO] monitorLogs - MQTT client connected +[2024-12-06T16:16:54.248] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-06T16:16:54.295] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-06T16:16:54.332] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-07T07:11:07.864] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-07T07:11:07.905] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-07T07:11:07.945] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-07T16:16:39.190] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-07T16:16:39.232] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-07T16:16:39.270] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-08T07:12:11.505] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-08T07:12:11.547] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-08T07:12:11.585] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-08T16:16:26.591] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-08T16:16:26.637] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-08T16:16:26.675] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-09T04:35:12.505] [INFO] monitorLogs - MQTT client connected +[2024-12-09T07:13:13.196] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-09T07:13:13.242] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-09T07:13:13.280] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-09T13:04:58.188] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-09T13:04:59.209] [INFO] monitorLogs - websocket error, reconnect +[2024-12-09T13:04:59.211] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-09T13:25:08.148] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2024-12-09T13:25:13.480] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 true turn off on startup +[2024-12-09T13:25:13.493] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 true turn off on startup +[2024-12-09T13:25:13.498] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 true turn off on startup +[2024-12-09T13:25:13.664] [INFO] monitorLogs - MQTT client connected +[2024-12-09T13:25:18.509] [INFO] monitorLogs - buildTasks - params undefined +[2024-12-09T13:25:18.511] [INFO] monitorLogs - buildTasks: profile for line 1 +[2024-12-09T13:25:18.511] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2024-12-09T13:25:18.517] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-12-09T13:25:18.519] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 1 2024-12-10T06:13:00.518Z +[2024-12-09T13:25:18.520] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 1 2024-12-09T15:16:00.520Z +[2024-12-09T13:25:18.521] [INFO] monitorLogs - -->time_points final 1 [ + { start_time: '07:13', value: 0, name: 'dawn' }, + { start_time: '16:16', value: 1, name: 'dusk' } +] +[2024-12-09T13:25:18.522] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2024-12-09T13:25:18.523] [INFO] monitorLogs - buildTasks: profile for line 2 +[2024-12-09T13:25:18.523] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2024-12-09T13:25:18.526] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-12-09T13:25:18.526] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 2 2024-12-10T06:13:00.526Z +[2024-12-09T13:25:18.527] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 2 2024-12-09T15:16:00.527Z +[2024-12-09T13:25:18.528] [INFO] monitorLogs - -->time_points final 2 [ + { start_time: '07:13', value: 0, name: 'dawn' }, + { start_time: '16:16', value: 1, name: 'dusk' } +] +[2024-12-09T13:25:18.529] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2024-12-09T13:25:18.530] [INFO] monitorLogs - buildTasks: profile for line 3 +[2024-12-09T13:25:18.530] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2024-12-09T13:25:18.532] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-12-09T13:25:18.533] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 3 2024-12-10T06:13:00.533Z +[2024-12-09T13:25:18.534] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 3 2024-12-09T15:16:00.534Z +[2024-12-09T13:25:18.535] [INFO] monitorLogs - -->time_points final 3 [ + { start_time: '07:13', value: 0, name: 'dawn' }, + { start_time: '16:16', value: 1, name: 'dusk' } +] +[2024-12-09T13:25:18.536] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2024-12-09T13:25:18.537] [INFO] monitorLogs - tasks created: 14 +[2024-12-09T13:25:18.546] [INFO] monitorLogs - -->FLOW bol spustený dz4ojlpP85JMgDLZWkQJ4D7aKYqQexEr62GXRV1y 2024-11-04 +[2024-12-09T16:16:00.633] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-09T16:16:00.677] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-09T16:16:00.719] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-10T03:25:16.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-10 03:25:16 +[2024-12-10T06:41:10.730] [INFO] monitorLogs - MQTT client connected +[2024-12-10T07:13:00.576] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-10T07:13:00.618] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-10T07:13:00.658] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-10T16:16:10.887] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-10T16:16:10.929] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-10T16:16:10.971] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-11T03:25:17.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-11 03:25:17 +[2024-12-11T07:15:09.918] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-11T07:15:09.957] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-11T07:15:09.995] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-11T16:16:07.474] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-11T16:16:07.516] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-11T16:16:07.554] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-12T03:25:17.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-12 03:25:17 +[2024-12-12T07:16:04.569] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-12T07:16:04.609] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-12T07:16:04.646] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-12T16:16:06.937] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-12T16:16:06.976] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-12T16:16:07.014] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-13T03:25:18.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-13 03:25:18 +[2024-12-13T07:09:12.262] [INFO] monitorLogs - MQTT client connected +[2024-12-13T07:10:56.700] [INFO] monitorLogs - MQTT client connected +[2024-12-13T07:16:57.047] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-13T07:16:57.088] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-13T07:16:57.125] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-13T16:16:09.536] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-13T16:16:09.580] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-13T16:16:09.619] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-14T03:25:18.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-14 03:25:18 +[2024-12-14T07:17:46.860] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-14T07:17:46.902] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-14T07:17:46.944] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-14T16:16:15.201] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-14T16:16:15.243] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-14T16:16:15.282] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-15T03:25:19.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-15 03:25:19 +[2024-12-15T07:18:34.133] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-15T07:18:34.176] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-15T07:18:34.215] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-15T16:16:23.617] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-15T16:16:23.659] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-15T16:16:23.697] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-16T03:25:19.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-16 03:25:19 +[2024-12-16T07:19:18.926] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-16T07:19:18.969] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-16T07:19:19.009] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-16T08:18:42.114] [INFO] monitorLogs - MQTT client connected +[2024-12-16T16:16:35.124] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-16T16:16:35.167] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-16T16:16:35.206] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-17T03:25:20.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-17 03:25:20 +[2024-12-17T07:20:01.281] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-17T07:20:01.323] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-17T07:20:01.362] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-17T08:54:11.507] [INFO] monitorLogs - MQTT client connected +[2024-12-17T16:16:49.918] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-17T16:16:49.961] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-17T16:16:50.009] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-18T03:25:21.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-18 03:25:21 +[2024-12-18T07:20:40.608] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-18T07:20:40.651] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-18T07:20:40.690] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-18T08:45:41.026] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2024-12-18T08:45:46.358] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 true turn off on startup +[2024-12-18T08:45:46.371] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 true turn off on startup +[2024-12-18T08:45:46.376] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 true turn off on startup +[2024-12-18T08:45:46.555] [INFO] monitorLogs - MQTT client connected +[2024-12-18T08:45:51.388] [INFO] monitorLogs - buildTasks - params undefined +[2024-12-18T08:45:51.390] [INFO] monitorLogs - buildTasks: profile for line 1 +[2024-12-18T08:45:51.390] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2024-12-18T08:45:51.395] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-12-18T08:45:51.397] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 1 2024-12-19T06:20:00.396Z +[2024-12-18T08:45:51.399] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 1 2024-12-18T15:17:00.399Z +[2024-12-18T08:45:51.400] [INFO] monitorLogs - -->time_points final 1 [ + { start_time: '07:20', value: 0, name: 'dawn' }, + { start_time: '16:17', value: 1, name: 'dusk' } +] +[2024-12-18T08:45:51.401] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2024-12-18T08:45:51.402] [INFO] monitorLogs - buildTasks: profile for line 2 +[2024-12-18T08:45:51.403] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2024-12-18T08:45:51.405] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-12-18T08:45:51.406] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 2 2024-12-19T06:20:00.406Z +[2024-12-18T08:45:51.407] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 2 2024-12-18T15:17:00.406Z +[2024-12-18T08:45:51.407] [INFO] monitorLogs - -->time_points final 2 [ + { start_time: '07:20', value: 0, name: 'dawn' }, + { start_time: '16:17', value: 1, name: 'dusk' } +] +[2024-12-18T08:45:51.408] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2024-12-18T08:45:51.409] [INFO] monitorLogs - buildTasks: profile for line 3 +[2024-12-18T08:45:51.410] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2024-12-18T08:45:51.412] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-12-18T08:45:51.413] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 3 2024-12-19T06:20:00.413Z +[2024-12-18T08:45:51.414] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 3 2024-12-18T15:17:00.414Z +[2024-12-18T08:45:51.415] [INFO] monitorLogs - -->time_points final 3 [ + { start_time: '07:20', value: 0, name: 'dawn' }, + { start_time: '16:17', value: 1, name: 'dusk' } +] +[2024-12-18T08:45:51.416] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2024-12-18T08:45:51.418] [INFO] monitorLogs - tasks created: 14 +[2024-12-18T08:45:51.426] [INFO] monitorLogs - -->FLOW bol spustený dz4ojlpP85JMgDLZWkQJ4D7aKYqQexEr62GXRV1y 2024-11-04 +[2024-12-18T13:21:25.083] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2024-12-18T13:21:30.453] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 true turn off on startup +[2024-12-18T13:21:30.465] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 true turn off on startup +[2024-12-18T13:21:30.470] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 true turn off on startup +[2024-12-18T13:21:30.618] [INFO] monitorLogs - MQTT client connected +[2024-12-18T13:21:35.482] [INFO] monitorLogs - buildTasks - params undefined +[2024-12-18T13:21:35.484] [INFO] monitorLogs - buildTasks: profile for line 1 +[2024-12-18T13:21:35.485] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2024-12-18T13:21:35.490] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-12-18T13:21:35.491] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 1 2024-12-19T06:20:00.490Z +[2024-12-18T13:21:35.492] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 1 2024-12-18T15:17:00.492Z +[2024-12-18T13:21:35.493] [INFO] monitorLogs - -->time_points final 1 [ + { start_time: '07:20', value: 0, name: 'dawn' }, + { start_time: '16:17', value: 1, name: 'dusk' } +] +[2024-12-18T13:21:35.494] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2024-12-18T13:21:35.496] [INFO] monitorLogs - buildTasks: profile for line 2 +[2024-12-18T13:21:35.496] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2024-12-18T13:21:35.499] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-12-18T13:21:35.500] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 2 2024-12-19T06:20:00.500Z +[2024-12-18T13:21:35.501] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 2 2024-12-18T15:17:00.501Z +[2024-12-18T13:21:35.501] [INFO] monitorLogs - -->time_points final 2 [ + { start_time: '07:20', value: 0, name: 'dawn' }, + { start_time: '16:17', value: 1, name: 'dusk' } +] +[2024-12-18T13:21:35.502] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2024-12-18T13:21:35.503] [INFO] monitorLogs - buildTasks: profile for line 3 +[2024-12-18T13:21:35.504] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2024-12-18T13:21:35.506] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-12-18T13:21:35.507] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 3 2024-12-19T06:20:00.506Z +[2024-12-18T13:21:35.507] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 3 2024-12-18T15:17:00.507Z +[2024-12-18T13:21:35.508] [INFO] monitorLogs - -->time_points final 3 [ + { start_time: '07:20', value: 0, name: 'dawn' }, + { start_time: '16:17', value: 1, name: 'dusk' } +] +[2024-12-18T13:21:35.509] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2024-12-18T13:21:35.510] [INFO] monitorLogs - tasks created: 14 +[2024-12-18T13:21:35.519] [INFO] monitorLogs - -->FLOW bol spustený dz4ojlpP85JMgDLZWkQJ4D7aKYqQexEr62GXRV1y 2024-11-04 +[2024-12-18T16:17:00.750] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-18T16:17:00.795] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-18T16:17:00.838] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-19T03:21:31.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-19 03:21:31 +[2024-12-19T07:20:00.661] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-19T07:20:00.703] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-19T07:20:00.742] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-19T16:17:27.817] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-19T16:17:27.857] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-19T16:17:27.896] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-20T03:21:32.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-20 03:21:32 +[2024-12-20T07:21:51.542] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-20T07:21:51.585] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-20T07:21:51.624] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-20T16:17:51.423] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-20T16:17:51.462] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-20T16:17:51.501] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-20T21:12:46.504] [INFO] monitorLogs - MQTT client connected +[2024-12-20T21:21:26.603] [INFO] monitorLogs - MQTT client connected +[2024-12-20T21:24:30.613] [INFO] monitorLogs - MQTT client connected +[2024-12-20T21:29:33.778] [INFO] monitorLogs - MQTT client connected +[2024-12-20T21:43:03.825] [INFO] monitorLogs - MQTT client connected +[2024-12-20T22:26:00.770] [INFO] monitorLogs - MQTT client connected +[2024-12-20T22:30:31.758] [INFO] monitorLogs - MQTT client connected +[2024-12-20T22:41:42.945] [INFO] monitorLogs - MQTT client connected +[2024-12-20T22:46:21.070] [INFO] monitorLogs - MQTT client connected +[2024-12-20T23:01:52.981] [INFO] monitorLogs - MQTT client connected +[2024-12-20T23:25:05.825] [INFO] monitorLogs - MQTT client connected +[2024-12-20T23:30:10.729] [INFO] monitorLogs - MQTT client connected +[2024-12-20T23:41:33.919] [INFO] monitorLogs - MQTT client connected +[2024-12-21T00:05:53.981] [INFO] monitorLogs - MQTT client connected +[2024-12-21T00:06:52.964] [INFO] monitorLogs - MQTT client connected +[2024-12-21T00:14:30.409] [INFO] monitorLogs - MQTT client connected +[2024-12-21T00:32:31.771] [INFO] monitorLogs - MQTT client connected +[2024-12-21T00:33:50.709] [INFO] monitorLogs - MQTT client connected +[2024-12-21T01:10:46.818] [INFO] monitorLogs - MQTT client connected +[2024-12-21T02:54:30.964] [INFO] monitorLogs - MQTT client connected +[2024-12-21T03:21:36.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-21 03:21:36 +[2024-12-21T07:22:22.759] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-21T07:22:22.801] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-21T07:22:22.840] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-21T16:18:17.799] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-21T16:18:17.839] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-21T16:18:17.877] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-22T03:21:33.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-22 03:21:33 +[2024-12-22T05:20:26.531] [INFO] monitorLogs - MQTT client connected +[2024-12-22T07:22:51.215] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-22T07:22:51.255] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-22T07:22:51.293] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-22T16:18:47.251] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-22T16:18:47.291] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-22T16:18:47.329] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-23T03:21:33.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-23 03:21:33 +[2024-12-23T07:23:16.945] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-23T07:23:16.986] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-23T07:23:17.024] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-23T07:41:38.144] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2024-12-23T07:41:43.490] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 true turn off on startup +[2024-12-23T07:41:43.502] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 true turn off on startup +[2024-12-23T07:41:43.507] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 true turn off on startup +[2024-12-23T07:41:43.658] [INFO] monitorLogs - MQTT client connected +[2024-12-23T07:41:48.517] [INFO] monitorLogs - buildTasks - params undefined +[2024-12-23T07:41:48.519] [INFO] monitorLogs - buildTasks: profile for line 1 +[2024-12-23T07:41:48.519] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2024-12-23T07:41:48.524] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-12-23T07:41:48.525] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 1 2024-12-24T06:23:00.524Z +[2024-12-23T07:41:48.527] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 1 2024-12-23T15:19:00.526Z +[2024-12-23T07:41:48.527] [INFO] monitorLogs - -->time_points final 1 [ + { start_time: '07:23', value: 0, name: 'dawn' }, + { start_time: '16:19', value: 1, name: 'dusk' } +] +[2024-12-23T07:41:48.529] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2024-12-23T07:41:48.529] [INFO] monitorLogs - buildTasks: profile for line 2 +[2024-12-23T07:41:48.530] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2024-12-23T07:41:48.533] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-12-23T07:41:48.533] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 2 2024-12-24T06:23:00.533Z +[2024-12-23T07:41:48.534] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 2 2024-12-23T15:19:00.534Z +[2024-12-23T07:41:48.535] [INFO] monitorLogs - -->time_points final 2 [ + { start_time: '07:23', value: 0, name: 'dawn' }, + { start_time: '16:19', value: 1, name: 'dusk' } +] +[2024-12-23T07:41:48.536] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2024-12-23T07:41:48.536] [INFO] monitorLogs - buildTasks: profile for line 3 +[2024-12-23T07:41:48.537] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2024-12-23T07:41:48.539] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-12-23T07:41:48.540] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 3 2024-12-24T06:23:00.540Z +[2024-12-23T07:41:48.541] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 3 2024-12-23T15:19:00.540Z +[2024-12-23T07:41:48.541] [INFO] monitorLogs - -->time_points final 3 [ + { start_time: '07:23', value: 0, name: 'dawn' }, + { start_time: '16:19', value: 1, name: 'dusk' } +] +[2024-12-23T07:41:48.542] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2024-12-23T07:41:48.544] [INFO] monitorLogs - tasks created: 14 +[2024-12-23T07:41:48.552] [INFO] monitorLogs - -->FLOW bol spustený dz4ojlpP85JMgDLZWkQJ4D7aKYqQexEr62GXRV1y 2024-11-04 +[2024-12-23T14:37:36.040] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2024-12-23T14:37:41.383] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 true turn off on startup +[2024-12-23T14:37:41.396] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 true turn off on startup +[2024-12-23T14:37:41.401] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 true turn off on startup +[2024-12-23T14:37:41.479] [INFO] monitorLogs - MQTT client connected +[2024-12-23T14:37:46.411] [INFO] monitorLogs - buildTasks - params undefined +[2024-12-23T14:37:46.412] [INFO] monitorLogs - buildTasks: profile for line 1 +[2024-12-23T14:37:46.413] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2024-12-23T14:37:46.417] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-12-23T14:37:46.419] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 1 2024-12-24T06:23:00.418Z +[2024-12-23T14:37:46.420] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 1 2024-12-23T15:19:00.420Z +[2024-12-23T14:37:46.421] [INFO] monitorLogs - -->time_points final 1 [ + { start_time: '07:23', value: 0, name: 'dawn' }, + { start_time: '16:19', value: 1, name: 'dusk' } +] +[2024-12-23T14:37:46.422] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2024-12-23T14:37:46.423] [INFO] monitorLogs - buildTasks: profile for line 2 +[2024-12-23T14:37:46.424] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2024-12-23T14:37:46.426] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-12-23T14:37:46.427] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 2 2024-12-24T06:23:00.427Z +[2024-12-23T14:37:46.428] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 2 2024-12-23T15:19:00.427Z +[2024-12-23T14:37:46.428] [INFO] monitorLogs - -->time_points final 2 [ + { start_time: '07:23', value: 0, name: 'dawn' }, + { start_time: '16:19', value: 1, name: 'dusk' } +] +[2024-12-23T14:37:46.429] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2024-12-23T14:37:46.430] [INFO] monitorLogs - buildTasks: profile for line 3 +[2024-12-23T14:37:46.430] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2024-12-23T14:37:46.433] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-12-23T14:37:46.433] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 3 2024-12-24T06:23:00.433Z +[2024-12-23T14:37:46.434] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 3 2024-12-23T15:19:00.434Z +[2024-12-23T14:37:46.435] [INFO] monitorLogs - -->time_points final 3 [ + { start_time: '07:23', value: 0, name: 'dawn' }, + { start_time: '16:19', value: 1, name: 'dusk' } +] +[2024-12-23T14:37:46.436] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2024-12-23T14:37:46.437] [INFO] monitorLogs - tasks created: 14 +[2024-12-23T14:37:46.446] [INFO] monitorLogs - -->FLOW bol spustený dz4ojlpP85JMgDLZWkQJ4D7aKYqQexEr62GXRV1y 2024-11-04 +[2024-12-23T16:19:00.661] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-23T16:19:00.704] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-23T16:19:00.744] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-24T03:37:42.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-24 03:37:42 +[2024-12-24T07:23:00.613] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-24T07:23:00.656] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-24T07:23:00.696] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-24T11:02:29.125] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2024-12-24T11:02:34.481] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 true turn off on startup +[2024-12-24T11:02:34.493] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 true turn off on startup +[2024-12-24T11:02:34.498] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 true turn off on startup +[2024-12-24T11:02:34.625] [INFO] monitorLogs - MQTT client connected +[2024-12-24T11:02:39.510] [INFO] monitorLogs - buildTasks - params undefined +[2024-12-24T11:02:39.512] [INFO] monitorLogs - buildTasks: profile for line 1 +[2024-12-24T11:02:39.513] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2024-12-24T11:02:39.518] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-12-24T11:02:39.519] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 1 2024-12-25T06:23:00.518Z +[2024-12-24T11:02:39.521] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 1 2024-12-24T15:19:00.520Z +[2024-12-24T11:02:39.521] [INFO] monitorLogs - -->time_points final 1 [ + { start_time: '07:23', value: 0, name: 'dawn' }, + { start_time: '16:19', value: 1, name: 'dusk' } +] +[2024-12-24T11:02:39.522] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2024-12-24T11:02:39.523] [INFO] monitorLogs - buildTasks: profile for line 2 +[2024-12-24T11:02:39.524] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2024-12-24T11:02:39.526] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-12-24T11:02:39.527] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 2 2024-12-25T06:23:00.527Z +[2024-12-24T11:02:39.528] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 2 2024-12-24T15:19:00.528Z +[2024-12-24T11:02:39.528] [INFO] monitorLogs - -->time_points final 2 [ + { start_time: '07:23', value: 0, name: 'dawn' }, + { start_time: '16:19', value: 1, name: 'dusk' } +] +[2024-12-24T11:02:39.529] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2024-12-24T11:02:39.530] [INFO] monitorLogs - buildTasks: profile for line 3 +[2024-12-24T11:02:39.531] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2024-12-24T11:02:39.533] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-12-24T11:02:39.533] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 3 2024-12-25T06:23:00.533Z +[2024-12-24T11:02:39.534] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 3 2024-12-24T15:19:00.534Z +[2024-12-24T11:02:39.535] [INFO] monitorLogs - -->time_points final 3 [ + { start_time: '07:23', value: 0, name: 'dawn' }, + { start_time: '16:19', value: 1, name: 'dusk' } +] +[2024-12-24T11:02:39.536] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2024-12-24T11:02:39.537] [INFO] monitorLogs - tasks created: 14 +[2024-12-24T11:02:39.546] [INFO] monitorLogs - -->FLOW bol spustený dz4ojlpP85JMgDLZWkQJ4D7aKYqQexEr62GXRV1y 2024-11-04 +[2024-12-24T16:19:00.698] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-24T16:19:00.743] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-24T16:19:00.784] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-25T03:02:35.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-25 03:02:35 +[2024-12-25T07:23:00.631] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-25T07:23:00.672] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-25T07:23:00.712] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-25T16:20:32.135] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-25T16:20:32.179] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-25T16:20:32.217] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-26T03:02:36.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-26 03:02:36 +[2024-12-26T07:24:16.362] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-26T07:24:16.404] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-26T07:24:16.442] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-26T16:21:12.768] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-26T16:21:12.810] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-26T16:21:12.850] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-27T03:02:36.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-27 03:02:36 +[2024-12-27T07:24:30.482] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-27T07:24:30.525] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-27T07:24:30.563] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-27T07:55:18.322] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2024-12-27T07:55:23.685] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 true turn off on startup +[2024-12-27T07:55:23.698] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 true turn off on startup +[2024-12-27T07:55:23.703] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 true turn off on startup +[2024-12-27T07:55:23.816] [INFO] monitorLogs - MQTT client connected +[2024-12-27T07:55:28.715] [INFO] monitorLogs - buildTasks - params undefined +[2024-12-27T07:55:28.716] [INFO] monitorLogs - buildTasks: profile for line 1 +[2024-12-27T07:55:28.717] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2024-12-27T07:55:28.722] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-12-27T07:55:28.723] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 1 2024-12-28T06:24:00.723Z +[2024-12-27T07:55:28.725] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 1 2024-12-27T15:21:00.725Z +[2024-12-27T07:55:28.726] [INFO] monitorLogs - -->time_points final 1 [ + { start_time: '07:24', value: 0, name: 'dawn' }, + { start_time: '16:21', value: 1, name: 'dusk' } +] +[2024-12-27T07:55:28.727] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2024-12-27T07:55:28.728] [INFO] monitorLogs - buildTasks: profile for line 2 +[2024-12-27T07:55:28.728] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2024-12-27T07:55:28.731] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-12-27T07:55:28.731] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 2 2024-12-28T06:24:00.731Z +[2024-12-27T07:55:28.732] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 2 2024-12-27T15:21:00.732Z +[2024-12-27T07:55:28.733] [INFO] monitorLogs - -->time_points final 2 [ + { start_time: '07:24', value: 0, name: 'dawn' }, + { start_time: '16:21', value: 1, name: 'dusk' } +] +[2024-12-27T07:55:28.734] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2024-12-27T07:55:28.735] [INFO] monitorLogs - buildTasks: profile for line 3 +[2024-12-27T07:55:28.735] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2024-12-27T07:55:28.737] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-12-27T07:55:28.738] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 3 2024-12-28T06:24:00.738Z +[2024-12-27T07:55:28.739] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 3 2024-12-27T15:21:00.739Z +[2024-12-27T07:55:28.739] [INFO] monitorLogs - -->time_points final 3 [ + { start_time: '07:24', value: 0, name: 'dawn' }, + { start_time: '16:21', value: 1, name: 'dusk' } +] +[2024-12-27T07:55:28.740] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2024-12-27T07:55:28.742] [INFO] monitorLogs - tasks created: 14 +[2024-12-27T07:55:28.751] [INFO] monitorLogs - -->FLOW bol spustený dz4ojlpP85JMgDLZWkQJ4D7aKYqQexEr62GXRV1y 2024-11-04 +[2024-12-27T16:21:01.020] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-27T16:21:01.064] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-27T16:21:01.103] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-28T03:55:25.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-28 03:55:25 +[2024-12-28T07:24:00.805] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-28T07:24:00.846] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-28T07:24:00.885] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-28T16:22:42.164] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-28T16:22:42.204] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-28T16:22:42.242] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-29T03:55:26.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-29 03:55:26 +[2024-12-29T07:24:49.339] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-29T07:24:49.382] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-29T07:24:49.420] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-29T16:23:30.768] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-29T16:23:30.811] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-29T16:23:30.850] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-30T03:55:26.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-30 03:55:26 +[2024-12-30T07:24:54.459] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-30T07:24:54.501] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-30T07:24:54.540] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-30T09:08:20.070] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2024-12-30T09:08:25.644] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 true turn off on startup +[2024-12-30T09:08:25.658] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 true turn off on startup +[2024-12-30T09:08:25.663] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 true turn off on startup +[2024-12-30T09:08:25.786] [INFO] monitorLogs - MQTT client connected +[2024-12-30T09:08:30.674] [INFO] monitorLogs - buildTasks - params undefined +[2024-12-30T09:08:30.676] [INFO] monitorLogs - buildTasks: profile for line 1 +[2024-12-30T09:08:30.676] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2024-12-30T09:08:30.682] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-12-30T09:08:30.684] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 1 2024-12-31T06:24:00.683Z +[2024-12-30T09:08:30.686] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 1 2024-12-30T15:24:00.685Z +[2024-12-30T09:08:30.686] [INFO] monitorLogs - -->time_points final 1 [ + { start_time: '07:24', value: 0, name: 'dawn' }, + { start_time: '16:24', value: 1, name: 'dusk' } +] +[2024-12-30T09:08:30.687] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2024-12-30T09:08:30.688] [INFO] monitorLogs - buildTasks: profile for line 2 +[2024-12-30T09:08:30.689] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2024-12-30T09:08:30.691] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-12-30T09:08:30.692] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 2 2024-12-31T06:24:00.692Z +[2024-12-30T09:08:30.693] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 2 2024-12-30T15:24:00.693Z +[2024-12-30T09:08:30.694] [INFO] monitorLogs - -->time_points final 2 [ + { start_time: '07:24', value: 0, name: 'dawn' }, + { start_time: '16:24', value: 1, name: 'dusk' } +] +[2024-12-30T09:08:30.695] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2024-12-30T09:08:30.695] [INFO] monitorLogs - buildTasks: profile for line 3 +[2024-12-30T09:08:30.696] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2024-12-30T09:08:30.698] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-12-30T09:08:30.699] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 3 2024-12-31T06:24:00.699Z +[2024-12-30T09:08:30.700] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 3 2024-12-30T15:24:00.699Z +[2024-12-30T09:08:30.700] [INFO] monitorLogs - -->time_points final 3 [ + { start_time: '07:24', value: 0, name: 'dawn' }, + { start_time: '16:24', value: 1, name: 'dusk' } +] +[2024-12-30T09:08:30.701] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2024-12-30T09:08:30.703] [INFO] monitorLogs - tasks created: 14 +[2024-12-30T09:08:30.711] [INFO] monitorLogs - -->FLOW bol spustený dz4ojlpP85JMgDLZWkQJ4D7aKYqQexEr62GXRV1y 2024-11-04 +[2024-12-30T16:24:00.782] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-30T16:24:00.827] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-30T16:24:00.867] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-31T03:08:26.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-31 03:08:26 +[2024-12-31T07:24:00.804] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-31T07:24:00.846] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-31T07:24:00.885] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-31T08:37:09.145] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2024-12-31T08:37:14.425] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 true turn off on startup +[2024-12-31T08:37:14.437] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 true turn off on startup +[2024-12-31T08:37:14.442] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 true turn off on startup +[2024-12-31T08:37:14.575] [INFO] monitorLogs - MQTT client connected +[2024-12-31T08:37:19.454] [INFO] monitorLogs - buildTasks - params undefined +[2024-12-31T08:37:19.456] [INFO] monitorLogs - buildTasks: profile for line 1 +[2024-12-31T08:37:19.457] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2024-12-31T08:37:19.461] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-12-31T08:37:19.463] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 1 2025-01-01T06:24:00.462Z +[2024-12-31T08:37:19.464] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 1 2024-12-31T15:25:00.464Z +[2024-12-31T08:37:19.465] [INFO] monitorLogs - -->time_points final 1 [ + { start_time: '07:24', value: 0, name: 'dawn' }, + { start_time: '16:25', value: 1, name: 'dusk' } +] +[2024-12-31T08:37:19.466] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2024-12-31T08:37:19.467] [INFO] monitorLogs - buildTasks: profile for line 2 +[2024-12-31T08:37:19.467] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2024-12-31T08:37:19.470] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-12-31T08:37:19.470] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 2 2025-01-01T06:24:00.470Z +[2024-12-31T08:37:19.471] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 2 2024-12-31T15:25:00.471Z +[2024-12-31T08:37:19.472] [INFO] monitorLogs - -->time_points final 2 [ + { start_time: '07:24', value: 0, name: 'dawn' }, + { start_time: '16:25', value: 1, name: 'dusk' } +] +[2024-12-31T08:37:19.473] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2024-12-31T08:37:19.474] [INFO] monitorLogs - buildTasks: profile for line 3 +[2024-12-31T08:37:19.474] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2024-12-31T08:37:19.476] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-12-31T08:37:19.477] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 3 2025-01-01T06:24:00.477Z +[2024-12-31T08:37:19.478] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 3 2024-12-31T15:25:00.478Z +[2024-12-31T08:37:19.493] [INFO] monitorLogs - -->time_points final 3 [ + { start_time: '07:24', value: 0, name: 'dawn' }, + { start_time: '16:25', value: 1, name: 'dusk' } +] +[2024-12-31T08:37:19.494] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2024-12-31T08:37:19.496] [INFO] monitorLogs - tasks created: 14 +[2024-12-31T08:37:19.505] [INFO] monitorLogs - -->FLOW bol spustený dz4ojlpP85JMgDLZWkQJ4D7aKYqQexEr62GXRV1y 2024-11-04 +[2024-12-31T16:25:00.664] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-31T16:25:00.706] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-31T16:25:00.746] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-01T03:37:15.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-01 03:37:15 +[2025-01-01T07:24:00.497] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-01T07:24:00.540] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-01T07:24:00.580] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-01T16:26:12.067] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-01T16:26:12.110] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-01T16:26:12.150] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-02T03:37:16.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-02 03:37:16 +[2025-01-02T07:24:51.973] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-02T07:24:52.017] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-02T07:24:52.057] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-02T08:47:39.263] [INFO] monitorLogs - MQTT client error Error: connect ECONNREFUSED 192.168.252.1:1883 + at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1159:16) { + errno: -111, + code: 'ECONNREFUSED', + syscall: 'connect', + address: '192.168.252.1', + port: 1883 +} +[2025-01-02T11:45:01.090] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-01-02T11:45:06.436] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 true turn off on startup +[2025-01-02T11:45:06.448] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 true turn off on startup +[2025-01-02T11:45:06.454] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 true turn off on startup +[2025-01-02T11:45:06.527] [INFO] monitorLogs - MQTT client error Error: connect ECONNREFUSED 192.168.252.1:1883 + at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1159:16) { + errno: -111, + code: 'ECONNREFUSED', + syscall: 'connect', + address: '192.168.252.1', + port: 1883 +} +[2025-01-02T11:45:11.466] [INFO] monitorLogs - buildTasks - params undefined +[2025-01-02T11:45:11.467] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-01-02T11:45:11.468] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-01-02T11:45:11.472] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-02T11:45:11.474] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 1 2025-01-03T06:24:00.473Z +[2025-01-02T11:45:11.475] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 1 2025-01-02T15:27:00.475Z +[2025-01-02T11:45:11.476] [INFO] monitorLogs - -->time_points final 1 [ + { start_time: '07:24', value: 0, name: 'dawn' }, + { start_time: '16:27', value: 1, name: 'dusk' } +] +[2025-01-02T11:45:11.477] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-01-02T11:45:11.478] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-01-02T11:45:11.479] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-01-02T11:45:11.481] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-02T11:45:11.482] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 2 2025-01-03T06:24:00.482Z +[2025-01-02T11:45:11.483] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 2 2025-01-02T15:27:00.483Z +[2025-01-02T11:45:11.483] [INFO] monitorLogs - -->time_points final 2 [ + { start_time: '07:24', value: 0, name: 'dawn' }, + { start_time: '16:27', value: 1, name: 'dusk' } +] +[2025-01-02T11:45:11.484] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-01-02T11:45:11.485] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-01-02T11:45:11.486] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-01-02T11:45:11.488] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-02T11:45:11.488] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 3 2025-01-03T06:24:00.488Z +[2025-01-02T11:45:11.489] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 3 2025-01-02T15:27:00.489Z +[2025-01-02T11:45:11.490] [INFO] monitorLogs - -->time_points final 3 [ + { start_time: '07:24', value: 0, name: 'dawn' }, + { start_time: '16:27', value: 1, name: 'dusk' } +] +[2025-01-02T11:45:11.491] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-01-02T11:45:11.492] [INFO] monitorLogs - tasks created: 14 +[2025-01-02T11:45:11.495] [INFO] monitorLogs - -->FLOW bol spustený dz4ojlpP85JMgDLZWkQJ4D7aKYqQexEr62GXRV1y 2025-01-02 +[2025-01-02T12:40:17.065] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-01-02T12:40:22.410] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 true turn off on startup +[2025-01-02T12:40:22.423] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 true turn off on startup +[2025-01-02T12:40:22.429] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 true turn off on startup +[2025-01-02T12:40:22.472] [INFO] monitorLogs - MQTT client error Error: connect ECONNREFUSED 192.168.252.1:1883 + at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1159:16) { + errno: -111, + code: 'ECONNREFUSED', + syscall: 'connect', + address: '192.168.252.1', + port: 1883 +} +[2025-01-02T12:40:27.440] [INFO] monitorLogs - buildTasks - params undefined +[2025-01-02T12:40:27.442] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-01-02T12:40:27.442] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-01-02T12:40:27.447] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-02T12:40:27.448] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 1 2025-01-03T06:24:00.447Z +[2025-01-02T12:40:27.449] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 1 2025-01-02T15:27:00.449Z +[2025-01-02T12:40:27.450] [INFO] monitorLogs - -->time_points final 1 [ + { start_time: '07:24', value: 0, name: 'dawn' }, + { start_time: '16:27', value: 1, name: 'dusk' } +] +[2025-01-02T12:40:27.451] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-01-02T12:40:27.452] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-01-02T12:40:27.453] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-01-02T12:40:27.455] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-02T12:40:27.456] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 2 2025-01-03T06:24:00.456Z +[2025-01-02T12:40:27.457] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 2 2025-01-02T15:27:00.456Z +[2025-01-02T12:40:27.457] [INFO] monitorLogs - -->time_points final 2 [ + { start_time: '07:24', value: 0, name: 'dawn' }, + { start_time: '16:27', value: 1, name: 'dusk' } +] +[2025-01-02T12:40:27.458] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-01-02T12:40:27.459] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-01-02T12:40:27.460] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-01-02T12:40:27.462] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-02T12:40:27.462] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 3 2025-01-03T06:24:00.462Z +[2025-01-02T12:40:27.463] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 3 2025-01-02T15:27:00.463Z +[2025-01-02T12:40:27.464] [INFO] monitorLogs - -->time_points final 3 [ + { start_time: '07:24', value: 0, name: 'dawn' }, + { start_time: '16:27', value: 1, name: 'dusk' } +] +[2025-01-02T12:40:27.465] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-01-02T12:40:27.466] [INFO] monitorLogs - tasks created: 14 +[2025-01-02T12:40:27.469] [INFO] monitorLogs - -->FLOW bol spustený dz4ojlpP85JMgDLZWkQJ4D7aKYqQexEr62GXRV1y 2025-01-02 +[2025-01-02T16:27:00.648] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-02T16:27:00.691] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-02T16:27:00.730] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-03T07:24:00.624] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-03T07:24:00.668] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-03T07:24:00.706] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-03T16:28:11.799] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-03T16:28:11.842] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-03T16:28:11.881] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-04T07:24:35.784] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-04T07:24:35.827] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-04T07:24:35.866] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-04T16:29:14.947] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-04T16:29:14.990] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-04T16:29:15.028] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-05T07:24:23.115] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-05T07:24:23.158] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-05T07:24:23.196] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-05T16:30:20.611] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-05T16:30:20.656] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-05T16:30:20.695] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-06T07:24:07.691] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-06T07:24:07.734] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-06T07:24:07.772] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-06T16:31:28.122] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-06T16:31:28.164] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-06T16:31:28.202] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-07T07:23:49.241] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-07T07:23:49.283] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-07T07:23:49.321] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-07T16:32:38.069] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-07T16:32:38.112] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-07T16:32:38.152] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-08T07:23:27.903] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-08T07:23:27.945] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-08T07:23:27.983] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-08T11:04:25.743] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-01-08T11:04:31.096] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 true turn off on startup +[2025-01-08T11:04:31.108] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 true turn off on startup +[2025-01-08T11:04:31.115] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 true turn off on startup +[2025-01-08T11:04:36.128] [INFO] monitorLogs - buildTasks - params undefined +[2025-01-08T11:04:36.129] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-01-08T11:04:36.130] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-01-08T11:04:36.134] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-08T11:04:36.136] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 1 2025-01-09T06:23:00.135Z +[2025-01-08T11:04:36.137] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 1 2025-01-08T15:33:00.137Z +[2025-01-08T11:04:36.138] [INFO] monitorLogs - -->time_points final 1 [ + { start_time: '07:23', value: 0, name: 'dawn' }, + { start_time: '16:33', value: 1, name: 'dusk' } +] +[2025-01-08T11:04:36.139] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-01-08T11:04:36.140] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-01-08T11:04:36.140] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-01-08T11:04:36.143] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-08T11:04:36.143] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 2 2025-01-09T06:23:00.143Z +[2025-01-08T11:04:36.144] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 2 2025-01-08T15:33:00.144Z +[2025-01-08T11:04:36.145] [INFO] monitorLogs - -->time_points final 2 [ + { start_time: '07:23', value: 0, name: 'dawn' }, + { start_time: '16:33', value: 1, name: 'dusk' } +] +[2025-01-08T11:04:36.146] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-01-08T11:04:36.147] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-01-08T11:04:36.147] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-01-08T11:04:36.149] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-08T11:04:36.150] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 3 2025-01-09T06:23:00.150Z +[2025-01-08T11:04:36.151] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 3 2025-01-08T15:33:00.150Z +[2025-01-08T11:04:36.151] [INFO] monitorLogs - -->time_points final 3 [ + { start_time: '07:23', value: 0, name: 'dawn' }, + { start_time: '16:33', value: 1, name: 'dusk' } +] +[2025-01-08T11:04:36.152] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-01-08T11:04:36.154] [INFO] monitorLogs - tasks created: 14 +[2025-01-08T11:04:36.157] [INFO] monitorLogs - -->FLOW bol spustený dz4ojlpP85JMgDLZWkQJ4D7aKYqQexEr62GXRV1y 2025-01-02 +[2025-01-08T12:08:17.263] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-01-08T12:08:22.604] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 true turn off on startup +[2025-01-08T12:08:22.617] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 true turn off on startup +[2025-01-08T12:08:22.624] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 true turn off on startup +[2025-01-08T12:08:27.635] [INFO] monitorLogs - buildTasks - params undefined +[2025-01-08T12:08:27.637] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-01-08T12:08:27.637] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-01-08T12:08:27.642] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-08T12:08:27.643] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 1 2025-01-09T06:23:00.642Z +[2025-01-08T12:08:27.644] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 1 2025-01-08T15:33:00.644Z +[2025-01-08T12:08:27.645] [INFO] monitorLogs - -->time_points final 1 [ + { start_time: '07:23', value: 0, name: 'dawn' }, + { start_time: '16:33', value: 1, name: 'dusk' } +] +[2025-01-08T12:08:27.646] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-01-08T12:08:27.647] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-01-08T12:08:27.647] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-01-08T12:08:27.650] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-08T12:08:27.651] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 2 2025-01-09T06:23:00.650Z +[2025-01-08T12:08:27.651] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 2 2025-01-08T15:33:00.651Z +[2025-01-08T12:08:27.652] [INFO] monitorLogs - -->time_points final 2 [ + { start_time: '07:23', value: 0, name: 'dawn' }, + { start_time: '16:33', value: 1, name: 'dusk' } +] +[2025-01-08T12:08:27.653] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-01-08T12:08:27.654] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-01-08T12:08:27.654] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-01-08T12:08:27.656] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-08T12:08:27.657] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 3 2025-01-09T06:23:00.657Z +[2025-01-08T12:08:27.658] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 3 2025-01-08T15:33:00.658Z +[2025-01-08T12:08:27.658] [INFO] monitorLogs - -->time_points final 3 [ + { start_time: '07:23', value: 0, name: 'dawn' }, + { start_time: '16:33', value: 1, name: 'dusk' } +] +[2025-01-08T12:08:27.659] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-01-08T12:08:27.661] [INFO] monitorLogs - tasks created: 14 +[2025-01-08T12:08:27.664] [INFO] monitorLogs - -->FLOW bol spustený dz4ojlpP85JMgDLZWkQJ4D7aKYqQexEr62GXRV1y 2025-01-02 +[2025-01-08T13:12:39.248] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-01-08T13:12:44.604] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 true turn off on startup +[2025-01-08T13:12:44.616] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 true turn off on startup +[2025-01-08T13:12:44.622] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 true turn off on startup +[2025-01-08T13:12:49.634] [INFO] monitorLogs - buildTasks - params undefined +[2025-01-08T13:12:49.636] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-01-08T13:12:49.636] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-01-08T13:12:49.640] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-08T13:12:49.642] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 1 2025-01-09T06:23:00.641Z +[2025-01-08T13:12:49.643] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 1 2025-01-08T15:33:00.643Z +[2025-01-08T13:12:49.644] [INFO] monitorLogs - -->time_points final 1 [ + { start_time: '07:23', value: 0, name: 'dawn' }, + { start_time: '16:33', value: 1, name: 'dusk' } +] +[2025-01-08T13:12:49.645] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-01-08T13:12:49.646] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-01-08T13:12:49.646] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-01-08T13:12:49.648] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-08T13:12:49.649] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 2 2025-01-09T06:23:00.649Z +[2025-01-08T13:12:49.650] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 2 2025-01-08T15:33:00.650Z +[2025-01-08T13:12:49.651] [INFO] monitorLogs - -->time_points final 2 [ + { start_time: '07:23', value: 0, name: 'dawn' }, + { start_time: '16:33', value: 1, name: 'dusk' } +] +[2025-01-08T13:12:49.652] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-01-08T13:12:49.652] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-01-08T13:12:49.653] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-01-08T13:12:49.655] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-08T13:12:49.656] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 3 2025-01-09T06:23:00.655Z +[2025-01-08T13:12:49.656] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 3 2025-01-08T15:33:00.656Z +[2025-01-08T13:12:49.657] [INFO] monitorLogs - -->time_points final 3 [ + { start_time: '07:23', value: 0, name: 'dawn' }, + { start_time: '16:33', value: 1, name: 'dusk' } +] +[2025-01-08T13:12:49.658] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-01-08T13:12:49.659] [INFO] monitorLogs - tasks created: 14 +[2025-01-08T13:12:49.662] [INFO] monitorLogs - -->FLOW bol spustený dz4ojlpP85JMgDLZWkQJ4D7aKYqQexEr62GXRV1y 2025-01-02 +[2025-01-08T14:17:02.310] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-01-08T14:17:07.663] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 true turn off on startup +[2025-01-08T14:17:07.676] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 true turn off on startup +[2025-01-08T14:17:07.682] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 true turn off on startup +[2025-01-08T14:17:12.693] [INFO] monitorLogs - buildTasks - params undefined +[2025-01-08T14:17:12.694] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-01-08T14:17:12.695] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-01-08T14:17:12.699] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-08T14:17:12.700] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 1 2025-01-09T06:23:00.699Z +[2025-01-08T14:17:12.702] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 1 2025-01-08T15:33:00.701Z +[2025-01-08T14:17:12.702] [INFO] monitorLogs - -->time_points final 1 [ + { start_time: '07:23', value: 0, name: 'dawn' }, + { start_time: '16:33', value: 1, name: 'dusk' } +] +[2025-01-08T14:17:12.703] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-01-08T14:17:12.704] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-01-08T14:17:12.705] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-01-08T14:17:12.707] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-08T14:17:12.708] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 2 2025-01-09T06:23:00.708Z +[2025-01-08T14:17:12.708] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 2 2025-01-08T15:33:00.708Z +[2025-01-08T14:17:12.709] [INFO] monitorLogs - -->time_points final 2 [ + { start_time: '07:23', value: 0, name: 'dawn' }, + { start_time: '16:33', value: 1, name: 'dusk' } +] +[2025-01-08T14:17:12.710] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-01-08T14:17:12.711] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-01-08T14:17:12.711] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-01-08T14:17:12.713] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-08T14:17:12.714] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 3 2025-01-09T06:23:00.714Z +[2025-01-08T14:17:12.715] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 3 2025-01-08T15:33:00.715Z +[2025-01-08T14:17:12.715] [INFO] monitorLogs - -->time_points final 3 [ + { start_time: '07:23', value: 0, name: 'dawn' }, + { start_time: '16:33', value: 1, name: 'dusk' } +] +[2025-01-08T14:17:12.716] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-01-08T14:17:12.718] [INFO] monitorLogs - tasks created: 14 +[2025-01-08T14:17:12.721] [INFO] monitorLogs - -->FLOW bol spustený dz4ojlpP85JMgDLZWkQJ4D7aKYqQexEr62GXRV1y 2025-01-02 +[2025-01-08T14:46:31.160] [INFO] monitorLogs - MQTT client error Error: connect ECONNREFUSED 192.168.252.1:1883 + at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1159:16) { + errno: -111, + code: 'ECONNREFUSED', + syscall: 'connect', + address: '192.168.252.1', + port: 1883 +} +[2025-01-08T16:30:36.893] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-01-08T16:30:42.222] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 true turn off on startup +[2025-01-08T16:30:42.235] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 true turn off on startup +[2025-01-08T16:30:42.242] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 true turn off on startup +[2025-01-08T16:30:42.256] [INFO] monitorLogs - MQTT client error Error: connect ECONNREFUSED 192.168.252.1:1883 + at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1159:16) { + errno: -111, + code: 'ECONNREFUSED', + syscall: 'connect', + address: '192.168.252.1', + port: 1883 +} +[2025-01-08T16:30:47.255] [INFO] monitorLogs - buildTasks - params undefined +[2025-01-08T16:30:47.257] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-01-08T16:30:47.257] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-01-08T16:30:47.263] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-08T16:30:47.264] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 1 2025-01-09T06:23:00.263Z +[2025-01-08T16:30:47.265] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 1 2025-01-08T15:33:00.265Z +[2025-01-08T16:30:47.266] [INFO] monitorLogs - -->time_points final 1 [ + { start_time: '07:23', value: 0, name: 'dawn' }, + { start_time: '16:33', value: 1, name: 'dusk' } +] +[2025-01-08T16:30:47.267] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-01-08T16:30:47.268] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-01-08T16:30:47.268] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-01-08T16:30:47.271] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-08T16:30:47.271] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 2 2025-01-09T06:23:00.271Z +[2025-01-08T16:30:47.272] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 2 2025-01-08T15:33:00.272Z +[2025-01-08T16:30:47.273] [INFO] monitorLogs - -->time_points final 2 [ + { start_time: '07:23', value: 0, name: 'dawn' }, + { start_time: '16:33', value: 1, name: 'dusk' } +] +[2025-01-08T16:30:47.274] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-01-08T16:30:47.274] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-01-08T16:30:47.275] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-01-08T16:30:47.277] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-08T16:30:47.278] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 3 2025-01-09T06:23:00.277Z +[2025-01-08T16:30:47.278] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 3 2025-01-08T15:33:00.278Z +[2025-01-08T16:30:47.279] [INFO] monitorLogs - -->time_points final 3 [ + { start_time: '07:23', value: 0, name: 'dawn' }, + { start_time: '16:33', value: 1, name: 'dusk' } +] +[2025-01-08T16:30:47.281] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-01-08T16:30:47.282] [INFO] monitorLogs - tasks created: 14 +[2025-01-08T16:30:47.290] [INFO] monitorLogs - -->FLOW bol spustený dz4ojlpP85JMgDLZWkQJ4D7aKYqQexEr62GXRV1y 2025-01-02 +[2025-01-08T16:31:34.097] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-01-08T16:31:39.463] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 true turn off on startup +[2025-01-08T16:31:39.477] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 true turn off on startup +[2025-01-08T16:31:39.483] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 true turn off on startup +[2025-01-08T16:31:39.498] [INFO] monitorLogs - MQTT client error Error: connect ECONNREFUSED 192.168.252.1:1883 + at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1159:16) { + errno: -111, + code: 'ECONNREFUSED', + syscall: 'connect', + address: '192.168.252.1', + port: 1883 +} +[2025-01-08T16:31:44.496] [INFO] monitorLogs - buildTasks - params undefined +[2025-01-08T16:31:44.497] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-01-08T16:31:44.498] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-01-08T16:31:44.503] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-08T16:31:44.504] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 1 2025-01-09T06:23:00.503Z +[2025-01-08T16:31:44.505] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 1 2025-01-08T15:33:00.505Z +[2025-01-08T16:31:44.506] [INFO] monitorLogs - -->time_points final 1 [ + { start_time: '07:23', value: 0, name: 'dawn' }, + { start_time: '16:33', value: 1, name: 'dusk' } +] +[2025-01-08T16:31:44.507] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-01-08T16:31:44.508] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-01-08T16:31:44.509] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-01-08T16:31:44.511] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-08T16:31:44.512] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 2 2025-01-09T06:23:00.511Z +[2025-01-08T16:31:44.512] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 2 2025-01-08T15:33:00.512Z +[2025-01-08T16:31:44.513] [INFO] monitorLogs - -->time_points final 2 [ + { start_time: '07:23', value: 0, name: 'dawn' }, + { start_time: '16:33', value: 1, name: 'dusk' } +] +[2025-01-08T16:31:44.514] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-01-08T16:31:44.515] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-01-08T16:31:44.515] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-01-08T16:31:44.518] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-08T16:31:44.518] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 3 2025-01-09T06:23:00.518Z +[2025-01-08T16:31:44.519] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 3 2025-01-08T15:33:00.519Z +[2025-01-08T16:31:44.520] [INFO] monitorLogs - -->time_points final 3 [ + { start_time: '07:23', value: 0, name: 'dawn' }, + { start_time: '16:33', value: 1, name: 'dusk' } +] +[2025-01-08T16:31:44.521] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-01-08T16:31:44.522] [INFO] monitorLogs - tasks created: 14 +[2025-01-08T16:31:44.529] [INFO] monitorLogs - -->FLOW bol spustený dz4ojlpP85JMgDLZWkQJ4D7aKYqQexEr62GXRV1y 2025-01-02 +[2025-01-08T16:33:00.517] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-08T16:33:00.560] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-08T16:33:00.602] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-09T03:31:43.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-09 03:31:43 +[2025-01-09T07:23:00.611] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-09T07:23:00.653] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-09T07:23:00.692] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-09T15:26:48.488] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-01-09T15:26:53.830] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 true turn off on startup +[2025-01-09T15:26:53.843] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 true turn off on startup +[2025-01-09T15:26:53.849] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 true turn off on startup +[2025-01-09T15:26:53.891] [INFO] monitorLogs - MQTT client error Error: connect ECONNREFUSED 192.168.252.1:1883 + at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1159:16) { + errno: -111, + code: 'ECONNREFUSED', + syscall: 'connect', + address: '192.168.252.1', + port: 1883 +} +[2025-01-09T15:26:58.860] [INFO] monitorLogs - buildTasks - params undefined +[2025-01-09T15:26:58.862] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-01-09T15:26:58.863] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-01-09T15:26:58.868] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-09T15:26:58.869] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 1 2025-01-10T06:23:00.868Z +[2025-01-09T15:26:58.870] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 1 2025-01-09T15:35:00.870Z +[2025-01-09T15:26:58.871] [INFO] monitorLogs - -->time_points final 1 [ + { start_time: '07:23', value: 0, name: 'dawn' }, + { start_time: '16:35', value: 1, name: 'dusk' } +] +[2025-01-09T15:26:58.872] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-01-09T15:26:58.873] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-01-09T15:26:58.873] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-01-09T15:26:58.876] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-09T15:26:58.877] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 2 2025-01-10T06:23:00.876Z +[2025-01-09T15:26:58.877] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 2 2025-01-09T15:35:00.877Z +[2025-01-09T15:26:58.878] [INFO] monitorLogs - -->time_points final 2 [ + { start_time: '07:23', value: 0, name: 'dawn' }, + { start_time: '16:35', value: 1, name: 'dusk' } +] +[2025-01-09T15:26:58.879] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-01-09T15:26:58.880] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-01-09T15:26:58.880] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-01-09T15:26:58.882] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-09T15:26:58.883] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 3 2025-01-10T06:23:00.883Z +[2025-01-09T15:26:58.884] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 3 2025-01-09T15:35:00.884Z +[2025-01-09T15:26:58.885] [INFO] monitorLogs - -->time_points final 3 [ + { start_time: '07:23', value: 0, name: 'dawn' }, + { start_time: '16:35', value: 1, name: 'dusk' } +] +[2025-01-09T15:26:58.886] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-01-09T15:26:58.887] [INFO] monitorLogs - tasks created: 14 +[2025-01-09T15:26:58.894] [INFO] monitorLogs - -->FLOW bol spustený dz4ojlpP85JMgDLZWkQJ4D7aKYqQexEr62GXRV1y 2025-01-02 +[2025-01-09T16:35:00.997] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-09T16:35:01.041] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-09T16:35:01.080] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-10T03:26:55.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-10 03:26:55 +[2025-01-10T07:23:00.953] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-10T07:23:00.993] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-10T07:23:01.031] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-10T14:41:06.063] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-01-10T14:41:11.433] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 true turn off on startup +[2025-01-10T14:41:11.446] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 true turn off on startup +[2025-01-10T14:41:11.452] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 true turn off on startup +[2025-01-10T14:41:11.466] [INFO] monitorLogs - MQTT client error Error: connect ECONNREFUSED 192.168.252.1:1883 + at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1159:16) { + errno: -111, + code: 'ECONNREFUSED', + syscall: 'connect', + address: '192.168.252.1', + port: 1883 +} +[2025-01-10T14:41:16.463] [INFO] monitorLogs - buildTasks - params undefined +[2025-01-10T14:41:16.465] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-01-10T14:41:16.466] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-01-10T14:41:16.471] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-10T14:41:16.472] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 1 2025-01-11T06:22:00.471Z +[2025-01-10T14:41:16.473] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 1 2025-01-10T15:36:00.473Z +[2025-01-10T14:41:16.474] [INFO] monitorLogs - -->time_points final 1 [ + { start_time: '07:22', value: 0, name: 'dawn' }, + { start_time: '16:36', value: 1, name: 'dusk' } +] +[2025-01-10T14:41:16.475] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-01-10T14:41:16.476] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-01-10T14:41:16.476] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-01-10T14:41:16.479] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-10T14:41:16.480] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 2 2025-01-11T06:22:00.479Z +[2025-01-10T14:41:16.480] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 2 2025-01-10T15:36:00.480Z +[2025-01-10T14:41:16.481] [INFO] monitorLogs - -->time_points final 2 [ + { start_time: '07:22', value: 0, name: 'dawn' }, + { start_time: '16:36', value: 1, name: 'dusk' } +] +[2025-01-10T14:41:16.482] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-01-10T14:41:16.483] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-01-10T14:41:16.483] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-01-10T14:41:16.485] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-10T14:41:16.486] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 3 2025-01-11T06:22:00.486Z +[2025-01-10T14:41:16.487] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 3 2025-01-10T15:36:00.487Z +[2025-01-10T14:41:16.487] [INFO] monitorLogs - -->time_points final 3 [ + { start_time: '07:22', value: 0, name: 'dawn' }, + { start_time: '16:36', value: 1, name: 'dusk' } +] +[2025-01-10T14:41:16.488] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-01-10T14:41:16.490] [INFO] monitorLogs - tasks created: 14 +[2025-01-10T14:41:16.497] [INFO] monitorLogs - -->FLOW bol spustený dz4ojlpP85JMgDLZWkQJ4D7aKYqQexEr62GXRV1y 2025-01-09 +[2025-01-10T15:58:16.549] [INFO] monitorLogs - MQTT client connected +[2025-01-10T16:36:00.761] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-10T16:36:00.804] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-10T16:36:00.844] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-11T03:41:12.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-11 03:41:12 +[2025-01-11T07:22:00.755] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-11T07:22:00.800] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-11T07:22:00.838] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-11T16:37:36.397] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-11T16:37:36.438] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-11T16:37:36.475] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-12T03:41:12.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-12 03:41:12 +[2025-01-12T07:21:34.652] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-12T07:21:34.694] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-12T07:21:34.732] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-12T16:38:55.460] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-12T16:38:55.500] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-12T16:38:55.538] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-13T03:41:13.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-13 03:41:13 +[2025-01-13T07:20:59.229] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-13T07:20:59.271] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-13T07:20:59.309] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-13T16:40:16.173] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-13T16:40:16.213] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-13T16:40:16.251] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-14T03:41:13.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-14 03:41:13 +[2025-01-14T07:20:21.327] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-14T07:20:21.369] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-14T07:20:21.407] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-14T16:41:38.472] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-14T16:41:38.515] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-14T16:41:38.553] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-15T03:41:14.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-15 03:41:14 +[2025-01-15T07:19:40.580] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-15T07:19:40.624] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-15T07:19:40.663] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-15T11:38:07.354] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-01-15T11:38:12.710] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 true turn off on startup +[2025-01-15T11:38:12.723] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 true turn off on startup +[2025-01-15T11:38:12.729] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 true turn off on startup +[2025-01-15T11:38:12.842] [INFO] monitorLogs - MQTT client connected +[2025-01-15T11:38:17.740] [INFO] monitorLogs - buildTasks - params undefined +[2025-01-15T11:38:17.742] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-01-15T11:38:17.743] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-01-15T11:38:17.748] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-15T11:38:17.749] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 1 2025-01-16T06:19:00.749Z +[2025-01-15T11:38:17.751] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 1 2025-01-15T15:43:00.751Z +[2025-01-15T11:38:17.751] [INFO] monitorLogs - -->time_points final 1 [ + { start_time: '07:19', value: 0, name: 'dawn' }, + { start_time: '16:43', value: 1, name: 'dusk' } +] +[2025-01-15T11:38:17.753] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-01-15T11:38:17.753] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-01-15T11:38:17.754] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-01-15T11:38:17.756] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-15T11:38:17.757] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 2 2025-01-16T06:19:00.757Z +[2025-01-15T11:38:17.758] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 2 2025-01-15T15:43:00.758Z +[2025-01-15T11:38:17.759] [INFO] monitorLogs - -->time_points final 2 [ + { start_time: '07:19', value: 0, name: 'dawn' }, + { start_time: '16:43', value: 1, name: 'dusk' } +] +[2025-01-15T11:38:17.760] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-01-15T11:38:17.760] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-01-15T11:38:17.761] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-01-15T11:38:17.763] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-15T11:38:17.764] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 3 2025-01-16T06:19:00.764Z +[2025-01-15T11:38:17.764] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 3 2025-01-15T15:43:00.764Z +[2025-01-15T11:38:17.765] [INFO] monitorLogs - -->time_points final 3 [ + { start_time: '07:19', value: 0, name: 'dawn' }, + { start_time: '16:43', value: 1, name: 'dusk' } +] +[2025-01-15T11:38:17.766] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-01-15T11:38:17.768] [INFO] monitorLogs - tasks created: 14 +[2025-01-15T11:38:17.776] [INFO] monitorLogs - -->FLOW bol spustený dz4ojlpP85JMgDLZWkQJ4D7aKYqQexEr62GXRV1y 2025-01-09 +[2025-01-15T16:43:00.894] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-15T16:43:00.937] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-15T16:43:00.977] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-16T03:38:12.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-16 03:38:12 +[2025-01-16T07:19:01.023] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-16T07:19:01.064] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-16T07:19:01.103] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-16T16:44:27.230] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-16T16:44:27.270] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-16T16:44:27.308] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-17T03:38:13.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-17 03:38:13 +[2025-01-17T07:18:11.602] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-17T07:18:11.643] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-17T07:18:11.680] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-17T16:45:53.676] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-17T16:45:53.716] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-17T16:45:53.753] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-18T03:38:14.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-18 03:38:14 +[2025-01-18T07:17:23.248] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-18T07:17:23.287] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-18T07:17:23.324] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-18T16:47:21.484] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-18T16:47:21.523] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-18T16:47:21.560] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-19T03:38:14.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-19 03:38:14 +[2025-01-19T07:16:32.328] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-19T07:16:32.367] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-19T07:16:32.404] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-19T16:48:50.387] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-19T16:48:50.427] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-19T16:48:50.464] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-20T01:30:14.181] [INFO] monitorLogs - MQTT client connected +[2025-01-20T03:38:15.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-20 03:38:15 +[2025-01-20T07:15:38.757] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-20T07:15:38.798] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-20T07:15:38.836] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-20T16:50:20.753] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-20T16:50:20.795] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-20T16:50:20.834] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-21T03:38:15.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-21 03:38:15 +[2025-01-21T06:21:32.029] [INFO] monitorLogs - MQTT client connected +[2025-01-21T06:22:33.000] [INFO] monitorLogs - MQTT client connected +[2025-01-21T07:14:42.982] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-21T07:14:43.024] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-21T07:14:43.062] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-21T16:51:51.713] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-21T16:51:51.756] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-21T16:51:51.795] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-22T03:38:16.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-22 03:38:16 +[2025-01-22T07:13:44.891] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-22T07:13:44.933] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-22T07:13:44.971] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-22T13:31:21.547] [INFO] monitorLogs - MQTT client connected +[2025-01-22T13:33:49.620] [INFO] monitorLogs - MQTT client connected +[2025-01-22T13:34:12.648] [INFO] monitorLogs - MQTT client connected +[2025-01-22T16:53:23.764] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-22T16:53:23.806] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-22T16:53:23.844] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-23T03:38:17.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-23 03:38:17 +[2025-01-23T07:12:44.354] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-23T07:12:44.396] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-23T07:12:44.435] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-23T08:49:40.102] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-01-23T08:49:45.458] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 true turn off on startup +[2025-01-23T08:49:45.471] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 true turn off on startup +[2025-01-23T08:49:45.477] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 true turn off on startup +[2025-01-23T08:49:45.631] [INFO] monitorLogs - MQTT client connected +[2025-01-23T08:49:50.488] [INFO] monitorLogs - buildTasks - params undefined +[2025-01-23T08:49:50.490] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-01-23T08:49:50.491] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-01-23T08:49:50.496] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-23T08:49:50.497] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 1 2025-01-24T06:12:00.496Z +[2025-01-23T08:49:50.499] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 1 2025-01-23T15:54:00.498Z +[2025-01-23T08:49:50.499] [INFO] monitorLogs - -->time_points final 1 [ + { start_time: '07:12', value: 0, name: 'dawn' }, + { start_time: '16:54', value: 1, name: 'dusk' } +] +[2025-01-23T08:49:50.501] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-01-23T08:49:50.502] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-01-23T08:49:50.503] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-01-23T08:49:50.506] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-23T08:49:50.506] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 2 2025-01-24T06:12:00.506Z +[2025-01-23T08:49:50.507] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 2 2025-01-23T15:54:00.507Z +[2025-01-23T08:49:50.508] [INFO] monitorLogs - -->time_points final 2 [ + { start_time: '07:12', value: 0, name: 'dawn' }, + { start_time: '16:54', value: 1, name: 'dusk' } +] +[2025-01-23T08:49:50.509] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-01-23T08:49:50.510] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-01-23T08:49:50.510] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-01-23T08:49:50.512] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-23T08:49:50.513] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 3 2025-01-24T06:12:00.513Z +[2025-01-23T08:49:50.514] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 3 2025-01-23T15:54:00.514Z +[2025-01-23T08:49:50.514] [INFO] monitorLogs - -->time_points final 3 [ + { start_time: '07:12', value: 0, name: 'dawn' }, + { start_time: '16:54', value: 1, name: 'dusk' } +] +[2025-01-23T08:49:50.515] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-01-23T08:49:50.517] [INFO] monitorLogs - tasks created: 14 +[2025-01-23T08:49:50.525] [INFO] monitorLogs - -->FLOW bol spustený dz4ojlpP85JMgDLZWkQJ4D7aKYqQexEr62GXRV1y 2025-01-09 +[2025-01-23T16:54:00.718] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-23T16:54:00.761] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-23T16:54:00.800] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-24T01:22:01.314] [INFO] monitorLogs - MQTT client connected +[2025-01-24T03:49:45.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-24 03:49:45 +[2025-01-24T07:12:00.695] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-24T07:12:00.738] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-24T07:12:00.777] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-24T16:56:30.815] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-24T16:56:30.859] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-24T16:56:30.897] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-25T03:49:46.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-25 03:49:46 +[2025-01-25T07:10:36.299] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-25T07:10:36.343] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-25T07:10:36.384] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-25T11:58:28.825] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-01-25T11:58:34.165] [INFO] monitorLogs - buildTasks - params undefined +[2025-01-25T11:58:34.169] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-01-25T11:58:34.171] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-01-25T11:58:34.172] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-01-25T11:58:34.176] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-25T11:58:34.177] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 1 2025-01-26T06:10:00.177Z +[2025-01-25T11:58:34.179] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 1 2025-01-25T15:58:00.179Z +[2025-01-25T11:58:34.179] [INFO] monitorLogs - -->time_points final 1 [ + { start_time: '07:10', value: 0, name: 'dawn' }, + { start_time: '16:58', value: 1, name: 'dusk' } +] +[2025-01-25T11:58:34.181] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-01-25T11:58:34.181] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-01-25T11:58:34.182] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-01-25T11:58:34.184] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-25T11:58:34.185] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 2 2025-01-26T06:10:00.185Z +[2025-01-25T11:58:34.186] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 2 2025-01-25T15:58:00.186Z +[2025-01-25T11:58:34.186] [INFO] monitorLogs - -->time_points final 2 [ + { start_time: '07:10', value: 0, name: 'dawn' }, + { start_time: '16:58', value: 1, name: 'dusk' } +] +[2025-01-25T11:58:34.187] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-01-25T11:58:34.189] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-01-25T11:58:34.190] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-01-25T11:58:34.192] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-25T11:58:34.193] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 3 2025-01-26T06:10:00.193Z +[2025-01-25T11:58:34.193] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 3 2025-01-25T15:58:00.193Z +[2025-01-25T11:58:34.194] [INFO] monitorLogs - -->time_points final 3 [ + { start_time: '07:10', value: 0, name: 'dawn' }, + { start_time: '16:58', value: 1, name: 'dusk' } +] +[2025-01-25T11:58:34.195] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-01-25T11:58:34.196] [INFO] monitorLogs - tasks created: 14 +[2025-01-25T11:58:34.199] [INFO] monitorLogs - -->FLOW bol spustený dz4ojlpP85JMgDLZWkQJ4D7aKYqQexEr62GXRV1y 2025-01-21 +[2025-01-25T11:58:34.291] [INFO] monitorLogs - MQTT client connected +[2025-01-25T11:58:34.502] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-25T11:58:34.804] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-25T11:58:35.107] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-25T12:11:33.791] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-01-25T12:11:39.162] [INFO] monitorLogs - buildTasks - params undefined +[2025-01-25T12:11:39.167] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-01-25T12:11:39.168] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-01-25T12:11:39.169] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-01-25T12:11:39.173] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-25T12:11:39.174] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 1 2025-01-26T06:10:00.173Z +[2025-01-25T12:11:39.176] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 1 2025-01-25T15:58:00.175Z +[2025-01-25T12:11:39.176] [INFO] monitorLogs - -->time_points final 1 [ + { start_time: '07:10', value: 0, name: 'dawn' }, + { start_time: '16:58', value: 1, name: 'dusk' } +] +[2025-01-25T12:11:39.178] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-01-25T12:11:39.178] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-01-25T12:11:39.179] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-01-25T12:11:39.181] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-25T12:11:39.182] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 2 2025-01-26T06:10:00.182Z +[2025-01-25T12:11:39.183] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 2 2025-01-25T15:58:00.183Z +[2025-01-25T12:11:39.184] [INFO] monitorLogs - -->time_points final 2 [ + { start_time: '07:10', value: 0, name: 'dawn' }, + { start_time: '16:58', value: 1, name: 'dusk' } +] +[2025-01-25T12:11:39.185] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-01-25T12:11:39.185] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-01-25T12:11:39.186] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-01-25T12:11:39.188] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-25T12:11:39.189] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 3 2025-01-26T06:10:00.189Z +[2025-01-25T12:11:39.189] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 3 2025-01-25T15:58:00.189Z +[2025-01-25T12:11:39.190] [INFO] monitorLogs - -->time_points final 3 [ + { start_time: '07:10', value: 0, name: 'dawn' }, + { start_time: '16:58', value: 1, name: 'dusk' } +] +[2025-01-25T12:11:39.191] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-01-25T12:11:39.192] [INFO] monitorLogs - tasks created: 14 +[2025-01-25T12:11:39.195] [INFO] monitorLogs - -->FLOW bol spustený dz4ojlpP85JMgDLZWkQJ4D7aKYqQexEr62GXRV1y 2025-01-21 +[2025-01-25T12:11:39.452] [INFO] monitorLogs - MQTT client connected +[2025-01-25T12:11:39.498] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-25T12:11:39.800] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-25T12:11:40.102] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-25T16:58:00.415] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-25T16:58:00.718] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-25T16:58:01.021] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-26T03:11:39.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-26 03:11:39 +[2025-01-26T07:10:00.331] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-26T07:10:00.634] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-26T07:10:00.937] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-26T16:59:40.586] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-26T16:59:40.889] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-26T16:59:41.191] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-27T03:11:40.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-27 03:11:40 +[2025-01-27T07:08:19.172] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-27T07:08:19.474] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-27T07:08:19.777] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-27T17:01:16.769] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-27T17:01:17.071] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-27T17:01:17.374] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-28T03:11:41.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-28 03:11:41 +[2025-01-28T07:07:07.564] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-28T07:07:07.869] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-28T07:07:08.172] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-28T08:51:11.124] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-01-28T08:51:16.417] [INFO] monitorLogs - buildTasks - params undefined +[2025-01-28T08:51:16.421] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-01-28T08:51:16.423] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-01-28T08:51:16.423] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-01-28T08:51:16.427] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-28T08:51:16.429] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 1 2025-01-29T06:07:00.428Z +[2025-01-28T08:51:16.430] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 1 2025-01-28T16:02:00.430Z +[2025-01-28T08:51:16.431] [INFO] monitorLogs - -->time_points final 1 [ + { start_time: '07:07', value: 0, name: 'dawn' }, + { start_time: '17:02', value: 1, name: 'dusk' } +] +[2025-01-28T08:51:16.432] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-01-28T08:51:16.433] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-01-28T08:51:16.434] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-01-28T08:51:16.436] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-28T08:51:16.437] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 2 2025-01-29T06:07:00.437Z +[2025-01-28T08:51:16.438] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 2 2025-01-28T16:02:00.438Z +[2025-01-28T08:51:16.438] [INFO] monitorLogs - -->time_points final 2 [ + { start_time: '07:07', value: 0, name: 'dawn' }, + { start_time: '17:02', value: 1, name: 'dusk' } +] +[2025-01-28T08:51:16.439] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-01-28T08:51:16.440] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-01-28T08:51:16.441] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-01-28T08:51:16.443] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-28T08:51:16.444] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 3 2025-01-29T06:07:00.443Z +[2025-01-28T08:51:16.444] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 3 2025-01-28T16:02:00.444Z +[2025-01-28T08:51:16.445] [INFO] monitorLogs - -->time_points final 3 [ + { start_time: '07:07', value: 0, name: 'dawn' }, + { start_time: '17:02', value: 1, name: 'dusk' } +] +[2025-01-28T08:51:16.446] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-01-28T08:51:16.447] [INFO] monitorLogs - tasks created: 14 +[2025-01-28T08:51:16.449] [INFO] monitorLogs - -->FLOW bol spustený dz4ojlpP85JMgDLZWkQJ4D7aKYqQexEr62GXRV1y 2025-01-21 +[2025-01-28T08:51:16.594] [INFO] monitorLogs - MQTT client connected +[2025-01-28T08:51:16.752] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-28T08:51:17.056] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-28T08:51:17.358] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-28T17:02:00.573] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-28T17:02:00.883] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-28T17:02:01.186] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-29T03:51:16.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-29 03:51:16 +[2025-01-29T07:07:00.710] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-29T07:07:01.013] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-29T07:07:01.316] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-29T17:04:30.287] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-29T17:04:30.590] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-29T17:04:30.893] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-30T03:51:17.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-30 03:51:17 +[2025-01-30T07:04:37.648] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-30T07:04:37.951] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-30T07:04:38.254] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-30T17:06:07.851] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-30T17:06:08.153] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-30T17:06:08.455] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-31T03:51:17.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-31 03:51:17 +[2025-01-31T07:03:19.948] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-31T07:03:20.250] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-31T07:03:20.553] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-31T08:08:01.925] [INFO] monitorLogs - MQTT client connected +[2025-01-31T17:07:45.937] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-31T17:07:46.239] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-31T17:07:46.542] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-02-01T03:51:18.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-01 03:51:18 +[2025-02-01T07:02:00.061] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-02-01T07:02:00.363] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-02-01T07:02:00.666] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-02-01T17:09:24.031] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-02-01T17:09:24.333] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-02-01T17:09:24.636] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-02-02T03:51:19.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-02 03:51:19 +[2025-02-02T07:00:38.312] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-02-02T07:00:38.615] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-02-02T07:00:38.917] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-02-02T17:11:02.827] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-02-02T17:11:03.130] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-02-02T17:11:03.432] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-02-03T03:51:20.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-03 03:51:20 +[2025-02-03T06:59:14.849] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-02-03T06:59:15.151] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-02-03T06:59:15.454] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-02-03T07:00:16.512] [INFO] monitorLogs - MQTT client connected +[2025-02-03T07:00:48.360] [INFO] monitorLogs - MQTT client connected +[2025-02-03T07:01:52.469] [INFO] monitorLogs - MQTT client connected +[2025-02-03T07:02:44.838] [INFO] monitorLogs - MQTT client connected +[2025-02-03T07:03:55.845] [INFO] monitorLogs - MQTT client connected +[2025-02-03T07:04:56.690] [INFO] monitorLogs - MQTT client connected +[2025-02-03T07:05:56.165] [INFO] monitorLogs - MQTT client connected +[2025-02-03T10:37:02.185] [INFO] monitorLogs - MQTT client connected +[2025-02-03T17:12:41.510] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-02-03T17:12:41.816] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-02-03T17:12:42.119] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-02-04T03:51:20.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-04 03:51:20 +[2025-02-04T06:57:49.223] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-02-04T06:57:49.527] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-02-04T06:57:49.828] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-02-04T17:14:20.654] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-02-04T17:14:20.961] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-02-04T17:14:21.262] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-02-05T03:51:21.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-05 03:51:21 +[2025-02-05T06:56:22.167] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-02-05T06:56:22.470] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-02-05T06:56:22.773] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-02-05T17:15:59.666] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-02-05T17:15:59.968] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-02-05T17:16:00.270] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-02-06T03:51:22.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-06 03:51:22 +[2025-02-06T06:54:53.099] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-02-06T06:54:53.401] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-02-06T06:54:53.703] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-02-06T17:17:39.017] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-02-06T17:17:39.320] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-02-06T17:17:39.622] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-02-07T03:51:22.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-07 03:51:22 +[2025-02-07T06:53:22.444] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-02-07T06:53:22.746] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-02-07T06:53:23.048] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-02-07T08:40:13.665] [INFO] monitorLogs - MQTT client connected +[2025-02-07T08:41:22.170] [INFO] monitorLogs - MQTT client connected +[2025-02-07T08:41:56.091] [INFO] monitorLogs - MQTT client connected +[2025-02-07T08:42:43.411] [INFO] monitorLogs - MQTT client connected +[2025-02-07T08:44:45.394] [INFO] monitorLogs - MQTT client connected +[2025-02-07T08:45:14.534] [INFO] monitorLogs - MQTT client connected +[2025-02-07T08:46:03.128] [INFO] monitorLogs - MQTT client connected +[2025-02-07T08:46:25.647] [INFO] monitorLogs - MQTT client connected +[2025-02-07T17:19:18.371] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-02-07T17:19:18.674] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-02-07T17:19:18.976] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-02-08T02:40:36.883] [INFO] monitorLogs - MQTT client connected +[2025-02-08T03:51:23.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-08 03:51:23 +[2025-02-08T06:51:50.157] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-02-08T06:51:50.459] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-02-08T06:51:50.761] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-02-08T17:20:57.840] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-02-08T17:20:58.143] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-02-08T17:20:58.445] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-02-09T03:51:24.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-09 03:51:24 +[2025-02-09T06:50:16.084] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-02-09T06:50:16.386] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-02-09T06:50:16.688] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-02-09T13:20:24.078] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-02-09T13:20:29.430] [INFO] monitorLogs - buildTasks - params undefined +[2025-02-09T13:20:29.435] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-02-09T13:20:29.436] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-02-09T13:20:29.437] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-02-09T13:20:29.441] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-02-09T13:20:29.442] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 1 2025-02-10T05:50:00.442Z +[2025-02-09T13:20:29.444] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 1 2025-02-09T16:22:00.444Z +[2025-02-09T13:20:29.445] [INFO] monitorLogs - -->time_points final 1 [ + { start_time: '06:50', value: 0, name: 'dawn' }, + { start_time: '17:22', value: 1, name: 'dusk' } +] +[2025-02-09T13:20:29.446] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-02-09T13:20:29.447] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-02-09T13:20:29.447] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-02-09T13:20:29.450] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-02-09T13:20:29.450] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 2 2025-02-10T05:50:00.450Z +[2025-02-09T13:20:29.451] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 2 2025-02-09T16:22:00.451Z +[2025-02-09T13:20:29.452] [INFO] monitorLogs - -->time_points final 2 [ + { start_time: '06:50', value: 0, name: 'dawn' }, + { start_time: '17:22', value: 1, name: 'dusk' } +] +[2025-02-09T13:20:29.453] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-02-09T13:20:29.454] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-02-09T13:20:29.454] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-02-09T13:20:29.456] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-02-09T13:20:29.457] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 3 2025-02-10T05:50:00.457Z +[2025-02-09T13:20:29.458] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 3 2025-02-09T16:22:00.458Z +[2025-02-09T13:20:29.458] [INFO] monitorLogs - -->time_points final 3 [ + { start_time: '06:50', value: 0, name: 'dawn' }, + { start_time: '17:22', value: 1, name: 'dusk' } +] +[2025-02-09T13:20:29.459] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-02-09T13:20:29.461] [INFO] monitorLogs - tasks created: 14 +[2025-02-09T13:20:29.463] [INFO] monitorLogs - -->FLOW bol spustený dz4ojlpP85JMgDLZWkQJ4D7aKYqQexEr62GXRV1y 2025-01-30 +[2025-02-09T13:20:29.599] [INFO] monitorLogs - MQTT client connected +[2025-02-09T13:20:29.766] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-02-09T13:20:30.069] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-02-09T13:20:30.372] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-02-09T17:22:00.502] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-02-09T17:22:00.805] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-02-09T17:22:01.107] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-02-10T03:20:30.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-10 03:20:30 +[2025-02-10T06:50:00.476] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-02-10T06:50:00.778] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-02-10T06:50:01.080] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-02-10T17:24:16.551] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-02-10T17:24:16.853] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-02-10T17:24:17.155] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-02-11T03:20:30.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-11 03:20:30 +[2025-02-11T06:47:03.362] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-02-11T06:47:03.665] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-02-11T06:47:03.967] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-02-11T13:32:21.557] [INFO] monitorLogs - MQTT client connected +[2025-02-11T17:25:55.922] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-02-11T17:25:56.225] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-02-11T17:25:56.527] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-02-12T03:20:31.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-12 03:20:31 +[2025-02-12T06:45:24.871] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-02-12T06:45:25.173] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-02-12T06:45:25.475] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-02-12T17:27:34.925] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-02-12T17:27:35.227] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-02-12T17:27:35.529] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-02-13T03:20:32.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-13 03:20:32 +[2025-02-13T06:43:44.946] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-02-13T06:43:45.248] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-02-13T06:43:45.550] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-02-13T13:17:17.854] [INFO] monitorLogs - MQTT client connected +[2025-02-13T13:17:53.566] [INFO] monitorLogs - MQTT client connected +[2025-02-13T13:18:54.447] [INFO] monitorLogs - MQTT client connected +[2025-02-13T13:20:59.565] [INFO] monitorLogs - MQTT client connected +[2025-02-13T13:23:04.510] [INFO] monitorLogs - MQTT client connected +[2025-02-13T13:26:05.805] [INFO] monitorLogs - MQTT client connected +[2025-02-13T13:28:24.789] [INFO] monitorLogs - MQTT client connected +[2025-02-13T15:23:00.111] [INFO] monitorLogs - MQTT client connected +[2025-02-13T17:29:14.099] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-02-13T17:29:14.403] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-02-13T17:29:14.705] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-02-14T03:20:32.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-14 03:20:32 +[2025-02-14T06:42:03.540] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-02-14T06:42:03.843] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-02-14T06:42:04.145] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-02-14T17:30:52.686] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-02-14T17:30:52.989] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-02-14T17:30:53.291] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-02-15T03:20:33.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-15 03:20:33 +[2025-02-15T06:40:20.811] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-02-15T06:40:21.114] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-02-15T06:40:21.416] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-02-15T17:32:31.619] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-02-15T17:32:31.921] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-02-15T17:32:32.223] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-02-16T03:20:34.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-16 03:20:34 +[2025-02-16T06:38:36.474] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-02-16T06:38:36.776] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-02-16T06:38:37.078] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-02-16T17:34:09.833] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-02-16T17:34:10.136] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-02-16T17:34:10.437] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-02-17T03:20:34.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-17 03:20:34 +[2025-02-17T06:36:51.319] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-02-17T06:36:51.621] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-02-17T06:36:51.922] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-02-17T07:03:53.504] [INFO] monitorLogs - MQTT client connected +[2025-02-17T07:05:17.168] [INFO] monitorLogs - MQTT client connected +[2025-02-17T08:02:49.253] [INFO] monitorLogs - MQTT client connected +[2025-02-17T08:04:29.787] [INFO] monitorLogs - MQTT client connected +[2025-02-17T08:06:18.382] [INFO] monitorLogs - MQTT client connected +[2025-02-17T08:56:21.978] [INFO] monitorLogs - MQTT client connected +[2025-02-17T17:35:48.182] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-02-17T17:35:48.490] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-02-17T17:35:48.792] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-02-18T03:20:35.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-18 03:20:35 +[2025-02-18T06:35:04.407] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-02-18T06:35:04.709] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-02-18T06:35:05.012] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-02-18T06:54:32.027] [INFO] monitorLogs - MQTT client connected +[2025-02-18T17:37:26.339] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-02-18T17:37:26.640] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-02-18T17:37:26.943] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-02-19T03:20:36.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-19 03:20:36 +[2025-02-19T06:33:16.583] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-02-19T06:33:16.884] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-02-19T06:33:17.187] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-02-19T14:18:32.995] [INFO] monitorLogs - MQTT client connected +[2025-02-19T15:06:46.382] [INFO] monitorLogs - MQTT client connected +[2025-02-19T15:10:00.457] [INFO] monitorLogs - MQTT client connected +[2025-02-19T15:12:58.791] [INFO] monitorLogs - MQTT client connected +[2025-02-19T17:39:03.852] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-02-19T17:39:04.155] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-02-19T17:39:04.457] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-02-20T03:20:36.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-20 03:20:36 +[2025-02-20T06:31:27.672] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-02-20T06:31:27.974] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-02-20T06:31:28.277] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-02-20T17:40:41.488] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-02-20T17:40:41.790] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-02-20T17:40:42.092] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-02-21T03:20:37.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-21 03:20:37 +[2025-02-21T06:29:37.288] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-02-21T06:29:37.591] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-02-21T06:29:37.893] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-02-21T17:42:18.515] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-02-21T17:42:18.817] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-02-21T17:42:19.119] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-02-22T03:20:38.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-22 03:20:38 +[2025-02-22T06:27:46.040] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-02-22T06:27:46.342] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-02-22T06:27:46.644] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-02-22T17:43:55.367] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-02-22T17:43:55.670] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-02-22T17:43:55.972] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-02-23T03:20:38.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-23 03:20:38 +[2025-02-23T06:25:53.768] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-02-23T06:25:54.070] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-02-23T06:25:54.372] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-02-23T17:45:31.938] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-02-23T17:45:32.240] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-02-23T17:45:32.542] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-02-24T03:20:39.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-24 03:20:39 +[2025-02-24T06:24:00.445] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-02-24T06:24:00.747] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-02-24T06:24:01.048] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-02-24T09:08:16.393] [INFO] monitorLogs - MQTT client connected +[2025-02-24T14:02:34.576] [INFO] monitorLogs - MQTT client connected +[2025-02-24T17:47:08.142] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-02-24T17:47:08.445] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-02-24T17:47:08.747] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-02-25T03:20:40.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-25 03:20:40 +[2025-02-25T06:22:06.297] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-02-25T06:22:06.600] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-02-25T06:22:06.902] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-02-25T06:50:17.135] [INFO] monitorLogs - MQTT client connected +[2025-02-25T06:51:14.727] [INFO] monitorLogs - MQTT client connected +[2025-02-25T06:52:16.934] [INFO] monitorLogs - MQTT client connected +[2025-02-25T06:54:57.065] [INFO] monitorLogs - MQTT client connected +[2025-02-25T06:55:54.467] [INFO] monitorLogs - MQTT client connected +[2025-02-25T06:58:19.044] [INFO] monitorLogs - MQTT client connected +[2025-02-25T07:11:20.288] [INFO] monitorLogs - MQTT client connected +[2025-02-25T07:12:11.713] [INFO] monitorLogs - MQTT client connected +[2025-02-25T07:13:52.757] [INFO] monitorLogs - MQTT client connected +[2025-02-25T07:15:33.772] [INFO] monitorLogs - MQTT client connected +[2025-02-25T07:16:53.555] [INFO] monitorLogs - MQTT client connected +[2025-02-25T07:17:39.301] [INFO] monitorLogs - MQTT client connected +[2025-02-25T12:37:22.814] [INFO] monitorLogs - MQTT client connected +[2025-02-25T12:38:04.431] [INFO] monitorLogs - MQTT client connected +[2025-02-25T14:06:03.693] [INFO] monitorLogs - MQTT client connected +[2025-02-25T14:09:11.272] [INFO] monitorLogs - MQTT client connected +[2025-02-25T14:10:09.011] [INFO] monitorLogs - MQTT client connected +[2025-02-25T14:10:32.398] [INFO] monitorLogs - MQTT client connected +[2025-02-25T14:11:27.605] [INFO] monitorLogs - MQTT client connected +[2025-02-25T14:13:23.863] [INFO] monitorLogs - MQTT client connected +[2025-02-25T14:14:16.085] [INFO] monitorLogs - MQTT client connected +[2025-02-25T14:15:53.431] [INFO] monitorLogs - MQTT client connected +[2025-02-25T14:20:53.534] [INFO] monitorLogs - MQTT client connected +[2025-02-25T17:48:43.958] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-02-25T17:48:44.260] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-02-25T17:48:44.562] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-02-26T03:20:41.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-26 03:20:41 +[2025-02-26T06:20:11.083] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-02-26T06:20:11.387] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-02-26T06:20:11.689] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-02-26T17:50:19.453] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-02-26T17:50:19.756] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-02-26T17:50:20.059] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-02-27T03:20:41.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-27 03:20:41 +[2025-02-27T06:18:14.875] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-02-27T06:18:15.178] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-02-27T06:18:15.479] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-02-27T17:51:54.793] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-02-27T17:51:55.095] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-02-27T17:51:55.397] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-02-28T03:20:42.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-28 03:20:42 +[2025-02-28T06:16:17.830] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-02-28T06:16:18.133] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-02-28T06:16:18.435] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-02-28T12:19:27.035] [INFO] monitorLogs - MQTT client connected +[2025-02-28T12:26:56.105] [INFO] monitorLogs - MQTT client connected +[2025-02-28T17:53:29.692] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-02-28T17:53:29.994] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-02-28T17:53:30.296] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-03-01T03:20:43.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-01 03:20:43 +[2025-03-01T06:14:19.965] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-03-01T06:14:20.267] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-03-01T06:14:20.569] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-03-01T17:55:04.176] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-03-01T17:55:04.479] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-03-01T17:55:04.781] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-03-02T03:20:43.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-02 03:20:43 +[2025-03-02T06:12:21.412] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-03-02T06:12:21.714] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-03-02T06:12:22.016] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-03-02T17:56:38.435] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-03-02T17:56:38.737] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-03-02T17:56:39.039] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-03-03T03:20:44.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-03 03:20:44 +[2025-03-03T06:10:21.895] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-03-03T06:10:22.198] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-03-03T06:10:22.499] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-03-03T17:58:12.357] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-03-03T17:58:12.659] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-03-03T17:58:12.961] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-03-04T03:20:45.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-04 03:20:45 +[2025-03-04T06:08:22.023] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-03-04T06:08:22.325] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-03-04T06:08:22.627] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-03-04T07:01:58.161] [INFO] monitorLogs - MQTT client connected +[2025-03-04T07:03:44.386] [INFO] monitorLogs - MQTT client connected +[2025-03-04T07:04:37.825] [INFO] monitorLogs - MQTT client connected +[2025-03-04T07:07:53.231] [INFO] monitorLogs - MQTT client connected +[2025-03-04T07:08:24.777] [INFO] monitorLogs - MQTT client connected +[2025-03-04T07:08:29.833] [INFO] monitorLogs - MQTT client connected +[2025-03-04T07:11:20.114] [INFO] monitorLogs - MQTT client connected +[2025-03-04T07:13:27.167] [INFO] monitorLogs - MQTT client connected +[2025-03-04T07:14:15.675] [INFO] monitorLogs - MQTT client connected +[2025-03-04T07:15:51.674] [INFO] monitorLogs - MQTT client connected +[2025-03-04T07:16:33.236] [INFO] monitorLogs - MQTT client connected +[2025-03-04T07:17:16.127] [INFO] monitorLogs - MQTT client connected +[2025-03-04T07:19:13.254] [INFO] monitorLogs - MQTT client connected +[2025-03-04T17:59:45.815] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-03-04T17:59:46.117] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-03-04T17:59:46.420] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-03-05T03:20:46.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-05 03:20:46 +[2025-03-05T06:06:21.204] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-03-05T06:06:21.506] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-03-05T06:06:21.808] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-03-05T18:01:19.178] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-03-05T18:01:19.480] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-03-05T18:01:19.782] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-03-06T03:20:47.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-06 03:20:47 +[2025-03-06T06:04:19.793] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-03-06T06:04:20.096] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-03-06T06:04:20.398] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-03-06T18:02:52.004] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-03-06T18:02:52.310] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-03-06T18:02:52.613] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-03-07T03:20:47.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-07 03:20:47 +[2025-03-07T06:02:17.846] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-03-07T06:02:18.149] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-03-07T06:02:18.451] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-03-07T18:04:24.498] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-03-07T18:04:24.800] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-03-07T18:04:25.102] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-03-08T03:20:49.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-08 03:20:49 +[2025-03-08T06:00:15.164] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-03-08T06:00:15.466] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-03-08T06:00:15.767] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-03-08T18:05:56.794] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-03-08T18:05:57.097] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-03-08T18:05:57.399] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-03-09T03:20:49.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-09 03:20:49 +[2025-03-09T05:58:11.943] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-03-09T05:58:12.246] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-03-09T05:58:12.548] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-03-09T18:07:28.814] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-03-09T18:07:29.117] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-03-09T18:07:29.419] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-03-10T03:20:50.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-10 03:20:50 +[2025-03-10T05:56:08.374] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-03-10T05:56:08.677] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-03-10T05:56:08.979] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-03-10T18:09:00.611] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-03-10T18:09:00.917] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-03-10T18:09:01.219] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-03-10T20:31:53.230] [INFO] monitorLogs - MQTT client connected +[2025-03-11T03:20:51.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-11 03:20:51 +[2025-03-11T05:54:04.475] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-03-11T05:54:04.777] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-03-11T05:54:05.079] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-03-11T08:18:49.987] [INFO] monitorLogs - MQTT client connected +[2025-03-11T08:19:38.437] [INFO] monitorLogs - MQTT client connected +[2025-03-11T08:21:08.327] [INFO] monitorLogs - MQTT client connected +[2025-03-11T08:21:52.806] [INFO] monitorLogs - MQTT client connected +[2025-03-11T08:22:41.844] [INFO] monitorLogs - MQTT client connected +[2025-03-11T08:23:57.446] [INFO] monitorLogs - MQTT client connected +[2025-03-11T08:25:39.226] [INFO] monitorLogs - MQTT client connected +[2025-03-11T18:10:32.194] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-03-11T18:10:32.496] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-03-11T18:10:32.799] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-03-12T03:20:52.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-12 03:20:52 +[2025-03-12T05:51:59.900] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-03-12T05:52:00.202] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-03-12T05:52:00.505] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-03-12T16:06:24.149] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-03-12T16:06:29.505] [INFO] monitorLogs - buildTasks - params undefined +[2025-03-12T16:06:29.510] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-03-12T16:06:29.511] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-03-12T16:06:29.512] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-03-12T16:06:29.516] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-03-12T16:06:29.518] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 1 2025-03-13T04:51:00.517Z +[2025-03-12T16:06:29.519] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 1 2025-03-12T17:12:00.519Z +[2025-03-12T16:06:29.520] [INFO] monitorLogs - -->time_points final 1 [ + { start_time: '05:51', value: 0, name: 'dawn' }, + { start_time: '18:12', value: 1, name: 'dusk' } +] +[2025-03-12T16:06:29.521] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-03-12T16:06:29.522] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-03-12T16:06:29.522] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-03-12T16:06:29.525] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-03-12T16:06:29.526] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 2 2025-03-13T04:51:00.525Z +[2025-03-12T16:06:29.526] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 2 2025-03-12T17:12:00.526Z +[2025-03-12T16:06:29.527] [INFO] monitorLogs - -->time_points final 2 [ + { start_time: '05:51', value: 0, name: 'dawn' }, + { start_time: '18:12', value: 1, name: 'dusk' } +] +[2025-03-12T16:06:29.528] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-03-12T16:06:29.529] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-03-12T16:06:29.530] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-03-12T16:06:29.532] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-03-12T16:06:29.532] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 3 2025-03-13T04:51:00.532Z +[2025-03-12T16:06:29.533] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 3 2025-03-12T17:12:00.533Z +[2025-03-12T16:06:29.534] [INFO] monitorLogs - -->time_points final 3 [ + { start_time: '05:51', value: 0, name: 'dawn' }, + { start_time: '18:12', value: 1, name: 'dusk' } +] +[2025-03-12T16:06:29.535] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-03-12T16:06:29.536] [INFO] monitorLogs - tasks created: 14 +[2025-03-12T16:06:29.538] [INFO] monitorLogs - -->FLOW bol spustený dz4ojlpP85JMgDLZWkQJ4D7aKYqQexEr62GXRV1y 2025-01-30 +[2025-03-12T16:06:29.625] [INFO] monitorLogs - MQTT client connected +[2025-03-12T16:06:29.842] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-03-12T16:06:30.145] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-03-12T16:06:30.448] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-03-12T18:12:00.564] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-03-12T18:12:00.868] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-03-12T18:12:01.169] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-03-13T03:06:31.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-13 03:06:31 +[2025-03-13T05:51:00.581] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-03-13T05:51:00.885] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-03-13T05:51:01.188] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-03-13T09:48:12.333] [INFO] monitorLogs - MQTT client connected +[2025-03-13T09:49:15.563] [INFO] monitorLogs - MQTT client connected +[2025-03-13T10:13:29.321] [INFO] monitorLogs - MQTT client connected +[2025-03-13T18:13:34.234] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-03-13T18:13:34.536] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-03-13T18:13:34.840] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-03-14T03:06:32.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-14 03:06:32 +[2025-03-14T05:47:49.769] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-03-14T05:47:50.072] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-03-14T05:47:50.374] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-03-14T18:15:04.690] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-03-14T18:15:04.994] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-03-14T18:15:05.296] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-03-15T03:06:32.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-15 03:06:32 +[2025-03-15T05:45:44.287] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-03-15T05:45:44.590] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-03-15T05:45:44.893] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-03-15T18:16:35.119] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-03-15T18:16:35.423] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-03-15T18:16:35.726] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-03-16T03:06:33.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-16 03:06:33 +[2025-03-16T05:43:38.448] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-03-16T05:43:38.750] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-03-16T05:43:39.053] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-03-16T18:18:05.571] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-03-16T18:18:05.874] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-03-16T18:18:06.176] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-03-17T03:06:34.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-17 03:06:34 +[2025-03-17T05:41:32.447] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-03-17T05:41:32.749] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-03-17T05:41:33.051] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-03-17T06:45:06.982] [INFO] monitorLogs - MQTT client connected +[2025-03-17T07:03:25.997] [INFO] monitorLogs - MQTT client connected +[2025-03-17T07:03:57.542] [INFO] monitorLogs - MQTT client connected +[2025-03-17T07:04:30.081] [INFO] monitorLogs - MQTT client connected +[2025-03-17T07:05:33.753] [INFO] monitorLogs - MQTT client connected +[2025-03-17T07:06:15.316] [INFO] monitorLogs - MQTT client connected +[2025-03-17T18:19:35.410] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-03-17T18:19:35.712] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-03-17T18:19:36.014] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-03-18T03:06:34.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-18 03:06:34 +[2025-03-18T05:39:26.162] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-03-18T05:39:26.464] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-03-18T05:39:26.766] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-03-18T11:24:15.945] [INFO] monitorLogs - MQTT client connected +[2025-03-18T18:21:05.316] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-03-18T18:21:05.619] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-03-18T18:21:05.921] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-03-19T03:06:35.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-19 03:06:35 +[2025-03-19T05:37:19.793] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-03-19T05:37:20.094] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-03-19T05:37:20.397] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-03-19T18:22:34.986] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-03-19T18:22:35.288] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-03-19T18:22:35.591] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-03-20T03:06:36.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-20 03:06:36 +[2025-03-20T05:35:13.046] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-03-20T05:35:13.348] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-03-20T05:35:13.650] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-03-20T18:24:04.440] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-03-20T18:24:04.742] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-03-20T18:24:05.044] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-03-21T03:06:37.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-21 03:06:37 +[2025-03-21T05:33:06.549] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-03-21T05:33:06.851] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-03-21T05:33:07.153] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-03-21T18:25:33.678] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-03-21T18:25:33.986] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-03-21T18:25:34.288] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-03-22T03:06:37.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-22 03:06:37 +[2025-03-22T05:30:59.758] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-03-22T05:31:00.061] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-03-22T05:31:00.364] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-03-22T18:27:03.012] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-03-22T18:27:03.313] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-03-22T18:27:03.616] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-03-23T03:06:38.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-23 03:06:38 +[2025-03-23T05:28:53.229] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-03-23T05:28:53.532] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-03-23T05:28:53.834] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-03-23T18:28:32.089] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-03-23T18:28:32.392] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-03-23T18:28:32.694] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-03-24T03:06:39.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-24 03:06:39 +[2025-03-24T05:26:46.032] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-03-24T05:26:46.335] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-03-24T05:26:46.637] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-03-24T09:38:05.931] [INFO] monitorLogs - MQTT client connected +[2025-03-24T10:49:42.061] [INFO] monitorLogs - MQTT client connected +[2025-03-24T12:29:18.797] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-03-24T12:29:24.145] [INFO] monitorLogs - buildTasks - params undefined +[2025-03-24T12:29:24.149] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-03-24T12:29:24.151] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-03-24T12:29:24.151] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-03-24T12:29:24.155] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-03-24T12:29:24.157] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 1 2025-03-25T04:26:00.156Z +[2025-03-24T12:29:24.158] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 1 2025-03-24T17:30:00.158Z +[2025-03-24T12:29:24.159] [INFO] monitorLogs - -->time_points final 1 [ + { start_time: '05:26', value: 0, name: 'dawn' }, + { start_time: '18:30', value: 1, name: 'dusk' } +] +[2025-03-24T12:29:24.160] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-03-24T12:29:24.161] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-03-24T12:29:24.162] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-03-24T12:29:24.164] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-03-24T12:29:24.165] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 2 2025-03-25T04:26:00.165Z +[2025-03-24T12:29:24.166] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 2 2025-03-24T17:30:00.166Z +[2025-03-24T12:29:24.166] [INFO] monitorLogs - -->time_points final 2 [ + { start_time: '05:26', value: 0, name: 'dawn' }, + { start_time: '18:30', value: 1, name: 'dusk' } +] +[2025-03-24T12:29:24.167] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-03-24T12:29:24.168] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-03-24T12:29:24.169] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-03-24T12:29:24.172] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-03-24T12:29:24.172] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 3 2025-03-25T04:26:00.172Z +[2025-03-24T12:29:24.173] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 3 2025-03-24T17:30:00.173Z +[2025-03-24T12:29:24.174] [INFO] monitorLogs - -->time_points final 3 [ + { start_time: '05:26', value: 0, name: 'dawn' }, + { start_time: '18:30', value: 1, name: 'dusk' } +] +[2025-03-24T12:29:24.175] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-03-24T12:29:24.176] [INFO] monitorLogs - tasks created: 14 +[2025-03-24T12:29:24.179] [INFO] monitorLogs - -->FLOW bol spustený dz4ojlpP85JMgDLZWkQJ4D7aKYqQexEr62GXRV1y 2025-01-30 +[2025-03-24T12:29:24.266] [INFO] monitorLogs - MQTT client connected +[2025-03-24T12:29:24.483] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-03-24T12:29:24.785] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-03-24T12:29:25.088] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-03-24T18:30:00.298] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-03-24T18:30:00.602] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-03-24T18:30:00.905] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-03-25T03:29:26.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-25 03:29:26 +[2025-03-25T05:26:00.328] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-03-25T05:26:00.631] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-03-25T05:26:00.933] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-03-25T12:58:18.378] [INFO] monitorLogs - MQTT client connected +[2025-03-25T13:14:17.550] [INFO] monitorLogs - MQTT client connected +[2025-03-25T18:31:29.767] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-03-25T18:31:30.070] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-03-25T18:31:30.372] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-03-26T03:29:27.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-26 03:29:27 +[2025-03-26T05:22:32.626] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-03-26T05:22:32.929] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-03-26T05:22:33.231] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-03-26T11:22:19.221] [INFO] monitorLogs - MQTT client connected +[2025-03-26T18:32:58.731] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-03-26T18:32:59.034] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-03-26T18:32:59.337] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-03-27T03:29:28.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-27 03:29:28 +[2025-03-27T05:20:26.108] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-03-27T05:20:26.411] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-03-27T05:20:26.713] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-03-27T18:34:27.444] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-03-27T18:34:27.747] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-03-27T18:34:28.049] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-03-28T03:29:28.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-28 03:29:28 +[2025-03-28T05:18:19.595] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-03-28T05:18:19.898] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-03-28T05:18:20.200] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-03-28T07:32:07.035] [INFO] monitorLogs - MQTT client connected +[2025-03-28T07:32:49.341] [INFO] monitorLogs - MQTT client connected +[2025-03-28T07:33:53.429] [INFO] monitorLogs - MQTT client connected +[2025-03-28T07:34:40.151] [INFO] monitorLogs - MQTT client connected +[2025-03-28T07:35:24.964] [INFO] monitorLogs - MQTT client connected +[2025-03-28T07:36:06.158] [INFO] monitorLogs - MQTT client connected +[2025-03-28T18:28:40.548] [INFO] monitorLogs - MQTT client connected +[2025-03-28T18:35:55.987] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-03-28T18:35:56.289] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-03-28T18:35:56.591] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-03-29T03:29:29.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-29 03:29:29 +[2025-03-29T05:16:13.374] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-03-29T05:16:13.677] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-03-29T05:16:13.979] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-03-29T18:37:24.458] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-03-29T18:37:24.762] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-03-29T18:37:25.065] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-03-30T03:29:30.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-30 03:29:30 +[2025-03-30T06:14:07.383] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-03-30T06:14:07.685] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-03-30T06:14:07.987] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-03-30T19:38:53.005] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-03-30T19:38:53.308] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-03-30T19:38:53.609] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-03-31T03:29:31.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-31 03:29:31 +[2025-03-31T06:12:01.437] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-03-31T06:12:01.739] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-03-31T06:12:02.041] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-03-31T06:44:29.823] [INFO] monitorLogs - MQTT client connected +[2025-03-31T06:45:16.481] [INFO] monitorLogs - MQTT client connected +[2025-03-31T06:46:24.329] [INFO] monitorLogs - MQTT client connected +[2025-03-31T06:46:53.209] [INFO] monitorLogs - MQTT client connected +[2025-03-31T06:48:15.448] [INFO] monitorLogs - MQTT client connected +[2025-03-31T06:48:58.328] [INFO] monitorLogs - MQTT client connected +[2025-03-31T06:49:28.014] [INFO] monitorLogs - MQTT client connected +[2025-03-31T06:50:14.295] [INFO] monitorLogs - MQTT client connected +[2025-03-31T19:40:21.501] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-03-31T19:40:21.804] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-03-31T19:40:22.106] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-04-01T03:29:32.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-01 03:29:32 +[2025-04-01T06:09:56.039] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-04-01T06:09:56.342] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-04-01T06:09:56.644] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-04-01T07:39:36.354] [INFO] monitorLogs - MQTT client connected +[2025-04-01T07:56:26.554] [INFO] monitorLogs - MQTT client connected +[2025-04-01T19:41:50.214] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-04-01T19:41:50.518] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-04-01T19:41:50.819] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-04-02T02:17:31.008] [INFO] monitorLogs - MQTT client connected +[2025-04-02T03:23:20.577] [INFO] monitorLogs - MQTT client connected +[2025-04-02T03:29:33.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-02 03:29:33 +[2025-04-02T06:07:50.675] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-04-02T06:07:50.978] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-04-02T06:07:51.279] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-04-02T19:43:18.665] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-04-02T19:43:18.972] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-04-02T19:43:19.275] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-04-03T03:29:34.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-03 03:29:34 +[2025-04-03T06:05:45.906] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-04-03T06:05:46.209] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-04-03T06:05:46.512] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-04-03T19:44:47.201] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-04-03T19:44:47.503] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-04-03T19:44:47.806] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-04-04T03:29:35.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-04 03:29:35 +[2025-04-04T06:03:41.421] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-04-04T06:03:41.723] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-04-04T06:03:42.025] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-04-04T19:46:15.764] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-04-04T19:46:16.067] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-04-04T19:46:16.369] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-04-05T03:29:36.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-05 03:29:36 +[2025-04-05T06:01:37.179] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-04-05T06:01:37.482] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-04-05T06:01:37.783] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-04-05T19:47:44.250] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-04-05T19:47:44.553] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-04-05T19:47:44.856] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-04-06T03:29:36.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-06 03:29:36 +[2025-04-06T05:59:33.533] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-04-06T05:59:33.836] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-04-06T05:59:34.138] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-04-06T19:49:12.714] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-04-06T19:49:13.016] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-04-06T19:49:13.318] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-04-07T03:29:37.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-07 03:29:37 +[2025-04-07T05:57:30.558] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-04-07T05:57:30.861] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-04-07T05:57:31.163] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-04-07T08:41:01.221] [INFO] monitorLogs - MQTT client connected +[2025-04-07T08:42:52.989] [INFO] monitorLogs - MQTT client connected +[2025-04-07T19:50:41.553] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-04-07T19:50:41.855] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-04-07T19:50:42.157] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-04-08T03:29:38.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-08 03:29:38 +[2025-04-08T05:55:27.881] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-04-08T05:55:28.183] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-04-08T05:55:28.485] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-04-08T19:52:10.152] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-04-08T19:52:10.460] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-04-08T19:52:10.763] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-04-09T03:29:39.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-09 03:29:39 +[2025-04-09T05:53:25.640] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-04-09T05:53:25.942] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-04-09T05:53:26.244] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-04-09T19:53:38.901] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-04-09T19:53:39.208] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-04-09T19:53:39.510] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-04-10T03:29:40.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-10 03:29:40 +[2025-04-10T05:51:24.047] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-04-10T05:51:24.350] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-04-10T05:51:24.652] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-04-10T07:06:08.222] [INFO] monitorLogs - MQTT client connected +[2025-04-10T19:55:07.569] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-04-10T19:55:07.872] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-04-10T19:55:08.174] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-04-11T00:29:20.949] [INFO] monitorLogs - MQTT client connected +[2025-04-11T03:29:40.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-11 03:29:40 +[2025-04-11T05:49:23.182] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-04-11T05:49:23.486] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-04-11T05:49:23.788] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-04-11T19:56:36.445] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-04-11T19:56:36.747] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-04-11T19:56:37.049] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-04-12T03:29:41.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-12 03:29:41 +[2025-04-12T05:47:22.922] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-04-12T05:47:23.224] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-04-12T05:47:23.526] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-04-12T19:58:05.343] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-04-12T19:58:05.645] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-04-12T19:58:05.947] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-04-13T03:29:42.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-13 03:29:42 +[2025-04-13T05:45:23.486] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-04-13T05:45:23.789] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-04-13T05:45:24.091] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-04-13T19:59:34.080] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-04-13T19:59:34.383] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-04-13T19:59:34.685] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-04-14T03:29:43.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-14 03:29:43 +[2025-04-14T05:43:24.486] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-04-14T05:43:24.788] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-04-14T05:43:25.092] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-04-14T07:48:47.550] [INFO] monitorLogs - MQTT client connected +[2025-04-14T16:19:20.002] [INFO] monitorLogs - MQTT client connected +[2025-04-14T20:01:03.132] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-04-14T20:01:03.435] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-04-14T20:01:03.737] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-04-15T03:29:44.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-15 03:29:44 +[2025-04-15T05:41:26.445] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-04-15T05:41:26.747] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-04-15T05:41:27.049] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-04-15T11:19:24.600] [INFO] monitorLogs - MQTT client connected +[2025-04-15T20:02:32.183] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-04-15T20:02:32.487] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-04-15T20:02:32.790] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-04-16T03:29:45.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-16 03:29:45 +[2025-04-16T05:39:29.029] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-04-16T05:39:29.332] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-04-16T05:39:29.633] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-04-16T20:04:00.978] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-04-16T20:04:01.281] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-04-16T20:04:01.583] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-04-17T03:29:47.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-17 03:29:47 +[2025-04-17T05:37:32.631] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-04-17T05:37:32.933] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-04-17T05:37:33.235] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-04-17T20:05:30.023] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-04-17T20:05:30.326] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-04-17T20:05:30.628] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-04-18T03:29:48.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-18 03:29:48 +[2025-04-18T05:35:36.885] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-04-18T05:35:37.187] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-04-18T05:35:37.489] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-04-18T20:06:59.253] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-04-18T20:06:59.555] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-04-18T20:06:59.857] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-04-19T03:29:49.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-19 03:29:49 +[2025-04-19T05:33:42.016] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-04-19T05:33:42.317] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-04-19T05:33:42.619] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-04-19T20:08:28.345] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-04-19T20:08:28.653] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-04-19T20:08:28.956] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-04-20T03:29:50.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-20 03:29:50 +[2025-04-20T05:31:48.374] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-04-20T05:31:48.676] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-04-20T05:31:48.979] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-04-20T20:09:57.331] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-04-20T20:09:57.639] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-04-20T20:09:57.942] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-04-21T03:29:51.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-21 03:29:51 +[2025-04-21T05:29:55.470] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-04-21T05:29:55.773] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-04-21T05:29:56.075] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-04-21T20:11:26.576] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-04-21T20:11:26.884] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-04-21T20:11:27.187] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-04-22T03:29:52.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-22 03:29:52 +[2025-04-22T05:28:03.346] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-04-22T05:28:03.648] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-04-22T05:28:03.951] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-04-22T12:13:19.431] [INFO] monitorLogs - MQTT client connected +[2025-04-22T20:12:55.524] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-04-22T20:12:55.828] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-04-22T20:12:56.130] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-04-23T03:29:53.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-23 03:29:53 +[2025-04-23T05:26:12.636] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-04-23T05:26:12.938] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-04-23T05:26:13.241] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-04-23T20:14:24.550] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-04-23T20:14:24.857] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-04-23T20:14:25.159] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-04-24T03:29:54.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-24 03:29:54 +[2025-04-24T05:24:22.842] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-04-24T05:24:23.145] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-04-24T05:24:23.447] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-04-24T17:06:41.553] [INFO] monitorLogs - MQTT client connected +[2025-04-24T18:01:42.252] [INFO] monitorLogs - MQTT client connected +[2025-04-24T18:03:43.609] [INFO] monitorLogs - MQTT client connected +[2025-04-24T20:15:53.665] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-04-24T20:15:53.967] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-04-24T20:15:54.269] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-04-25T03:29:56.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-25 03:29:56 +[2025-04-25T05:22:34.071] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-04-25T05:22:34.373] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-04-25T05:22:34.675] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-04-25T10:31:35.750] [INFO] monitorLogs - MQTT client connected +[2025-04-25T20:17:22.591] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-04-25T20:17:22.893] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-04-25T20:17:23.195] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-04-26T03:29:56.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-26 03:29:56 +[2025-04-26T05:20:46.523] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-04-26T05:20:46.825] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-04-26T05:20:47.128] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-04-26T20:18:51.519] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-04-26T20:18:51.822] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-04-26T20:18:52.124] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-04-27T03:29:58.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-27 03:29:58 +[2025-04-27T05:18:59.968] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-04-27T05:19:00.269] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-04-27T05:19:00.570] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-04-27T20:20:20.185] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-04-27T20:20:20.493] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-04-27T20:20:20.796] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-04-28T03:29:59.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-28 03:29:59 +[2025-04-28T05:17:14.946] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-04-28T05:17:15.248] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-04-28T05:17:15.550] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-04-28T20:21:48.850] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-04-28T20:21:49.153] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-04-28T20:21:49.456] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-04-29T03:30:00.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-29 03:30:00 +[2025-04-29T05:15:30.968] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-04-29T05:15:31.270] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-04-29T05:15:31.572] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-04-29T06:54:31.439] [INFO] monitorLogs - MQTT client connected +[2025-04-29T06:55:25.705] [INFO] monitorLogs - MQTT client connected +[2025-04-29T07:48:02.256] [INFO] monitorLogs - MQTT client connected +[2025-04-29T07:49:21.411] [INFO] monitorLogs - MQTT client connected +[2025-04-29T07:50:41.698] [INFO] monitorLogs - MQTT client connected +[2025-04-29T07:51:55.330] [INFO] monitorLogs - MQTT client connected +[2025-04-29T07:52:21.808] [INFO] monitorLogs - MQTT client connected +[2025-04-29T07:53:00.886] [INFO] monitorLogs - MQTT client connected +[2025-04-29T07:53:53.727] [INFO] monitorLogs - MQTT client connected +[2025-04-29T07:54:22.207] [INFO] monitorLogs - MQTT client connected +[2025-04-29T20:23:17.231] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-04-29T20:23:17.533] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-04-29T20:23:17.835] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-04-30T03:30:01.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-30 03:30:01 +[2025-04-30T05:13:48.012] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-04-30T05:13:48.315] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-04-30T05:13:48.616] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-04-30T16:58:05.145] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-04-30T16:58:10.489] [INFO] monitorLogs - buildTasks - params undefined +[2025-04-30T16:58:10.494] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-04-30T16:58:10.495] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-04-30T16:58:10.495] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-04-30T16:58:10.500] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-04-30T16:58:10.501] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 1 2025-05-01T03:13:00.500Z +[2025-04-30T16:58:10.502] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 1 2025-04-30T18:24:00.502Z +[2025-04-30T16:58:10.503] [INFO] monitorLogs - -->time_points final 1 [ + { start_time: '05:13', value: 0, name: 'dawn' }, + { start_time: '20:24', value: 1, name: 'dusk' } +] +[2025-04-30T16:58:10.504] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-04-30T16:58:10.505] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-04-30T16:58:10.506] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-04-30T16:58:10.508] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-04-30T16:58:10.509] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 2 2025-05-01T03:13:00.509Z +[2025-04-30T16:58:10.510] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 2 2025-04-30T18:24:00.509Z +[2025-04-30T16:58:10.510] [INFO] monitorLogs - -->time_points final 2 [ + { start_time: '05:13', value: 0, name: 'dawn' }, + { start_time: '20:24', value: 1, name: 'dusk' } +] +[2025-04-30T16:58:10.511] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-04-30T16:58:10.512] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-04-30T16:58:10.513] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-04-30T16:58:10.515] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-04-30T16:58:10.515] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 3 2025-05-01T03:13:00.515Z +[2025-04-30T16:58:10.516] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 3 2025-04-30T18:24:00.516Z +[2025-04-30T16:58:10.517] [INFO] monitorLogs - -->time_points final 3 [ + { start_time: '05:13', value: 0, name: 'dawn' }, + { start_time: '20:24', value: 1, name: 'dusk' } +] +[2025-04-30T16:58:10.518] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-04-30T16:58:10.519] [INFO] monitorLogs - tasks created: 14 +[2025-04-30T16:58:10.521] [INFO] monitorLogs - -->FLOW bol spustený dz4ojlpP85JMgDLZWkQJ4D7aKYqQexEr62GXRV1y 2025-04-24 +[2025-04-30T16:58:10.676] [INFO] monitorLogs - MQTT client connected +[2025-04-30T16:58:10.825] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-04-30T16:58:11.128] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-04-30T16:58:11.431] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-04-30T20:24:00.634] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-04-30T20:24:00.938] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-04-30T20:24:01.241] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-05-01T03:58:12.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-01 03:58:12 +[2025-05-01T05:13:00.541] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-05-01T05:13:00.844] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-05-01T05:13:01.147] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-05-01T20:26:13.806] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-05-01T20:26:14.114] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-05-01T20:26:14.418] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-05-02T03:58:13.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-02 03:58:13 +[2025-05-02T05:10:26.775] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-05-02T05:10:27.079] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-05-02T05:10:27.382] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-05-02T20:27:41.708] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-05-02T20:27:42.011] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-05-02T20:27:42.314] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-05-03T03:58:14.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-03 03:58:14 +[2025-05-03T05:08:48.138] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-05-03T05:08:48.441] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-05-03T05:08:48.743] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-05-03T20:29:09.066] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-05-03T20:29:09.368] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-05-03T20:29:09.670] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-05-04T03:58:16.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-04 03:58:16 +[2025-05-04T05:07:11.014] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-05-04T05:07:11.317] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-05-04T05:07:11.619] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-05-04T20:30:36.359] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-05-04T20:30:36.661] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-05-04T20:30:36.963] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-05-05T03:58:17.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-05 03:58:17 +[2025-05-05T05:05:35.041] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-05-05T05:05:35.352] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-05-05T05:05:35.655] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-05-05T20:32:03.314] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-05-05T20:32:03.617] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-05-05T20:32:03.919] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-05-06T03:58:18.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-06 03:58:18 +[2025-05-06T05:04:00.747] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-05-06T05:04:01.049] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-05-06T05:04:01.351] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-05-06T20:33:29.898] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-05-06T20:33:30.201] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-05-06T20:33:30.503] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-05-07T03:58:18.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-07 03:58:18 +[2025-05-07T05:02:28.139] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-05-07T05:02:28.442] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-05-07T05:02:28.744] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-05-07T19:28:36.163] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-05-07T19:28:41.485] [INFO] monitorLogs - buildTasks - params undefined +[2025-05-07T19:28:41.490] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-05-07T19:28:41.491] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-05-07T19:28:41.492] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-05-07T19:28:41.496] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-05-07T19:28:41.498] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 1 2025-05-08T03:02:00.497Z +[2025-05-07T19:28:41.499] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 1 2025-05-07T18:34:00.499Z +[2025-05-07T19:28:41.500] [INFO] monitorLogs - -->time_points final 1 [ + { start_time: '05:02', value: 0, name: 'dawn' }, + { start_time: '20:34', value: 1, name: 'dusk' } +] +[2025-05-07T19:28:41.501] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-05-07T19:28:41.502] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-05-07T19:28:41.502] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-05-07T19:28:41.504] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-05-07T19:28:41.505] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 2 2025-05-08T03:02:00.505Z +[2025-05-07T19:28:41.506] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 2 2025-05-07T18:34:00.506Z +[2025-05-07T19:28:41.507] [INFO] monitorLogs - -->time_points final 2 [ + { start_time: '05:02', value: 0, name: 'dawn' }, + { start_time: '20:34', value: 1, name: 'dusk' } +] +[2025-05-07T19:28:41.508] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-05-07T19:28:41.508] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-05-07T19:28:41.509] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-05-07T19:28:41.511] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-05-07T19:28:41.512] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 3 2025-05-08T03:02:00.512Z +[2025-05-07T19:28:41.513] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 3 2025-05-07T18:34:00.512Z +[2025-05-07T19:28:41.513] [INFO] monitorLogs - -->time_points final 3 [ + { start_time: '05:02', value: 0, name: 'dawn' }, + { start_time: '20:34', value: 1, name: 'dusk' } +] +[2025-05-07T19:28:41.514] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-05-07T19:28:41.515] [INFO] monitorLogs - tasks created: 14 +[2025-05-07T19:28:41.518] [INFO] monitorLogs - -->FLOW bol spustený dz4ojlpP85JMgDLZWkQJ4D7aKYqQexEr62GXRV1y 2025-04-24 +[2025-05-07T19:28:41.691] [INFO] monitorLogs - MQTT client connected +[2025-05-07T19:28:41.820] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-05-07T19:28:42.123] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-05-07T19:28:42.426] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-05-07T20:34:00.702] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-05-07T20:34:01.005] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-05-07T20:34:01.308] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-05-08T03:28:43.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-08 03:28:43 +[2025-05-08T05:02:00.511] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-05-08T05:02:00.813] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-05-08T05:02:01.116] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-05-08T20:36:21.840] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-05-08T20:36:22.148] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-05-08T20:36:22.450] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-05-09T03:28:44.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-09 03:28:44 +[2025-05-09T04:59:27.607] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-05-09T04:59:27.908] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-05-09T04:59:28.211] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-05-09T20:37:47.222] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-05-09T20:37:47.531] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-05-09T20:37:47.834] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-05-10T03:28:45.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-10 03:28:45 +[2025-05-10T04:57:59.757] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-05-10T04:58:00.060] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-05-10T04:58:00.362] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-05-10T20:39:11.645] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-05-10T20:39:11.954] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-05-10T20:39:12.257] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-05-11T03:28:47.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-11 03:28:47 +[2025-05-11T04:56:33.493] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-05-11T04:56:33.795] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-05-11T04:56:34.097] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-05-11T20:40:35.811] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-05-11T20:40:36.120] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-05-11T20:40:36.423] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-05-12T03:28:48.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-12 03:28:48 +[2025-05-12T04:55:08.944] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-05-12T04:55:09.246] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-05-12T04:55:09.548] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-05-12T09:48:02.291] [INFO] monitorLogs - MQTT client connected +[2025-05-12T10:53:19.963] [INFO] monitorLogs - MQTT client connected +[2025-05-12T20:41:59.305] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-05-12T20:41:59.608] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-05-12T20:41:59.910] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-05-13T03:28:49.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-13 03:28:49 +[2025-05-13T04:53:46.381] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-05-13T04:53:46.684] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-05-13T04:53:46.986] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-05-13T20:43:22.173] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-05-13T20:43:22.475] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-05-13T20:43:22.778] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-05-14T03:28:50.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-14 03:28:50 +[2025-05-14T04:52:25.450] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-05-14T04:52:25.753] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-05-14T04:52:26.055] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-05-14T07:43:41.687] [INFO] monitorLogs - MQTT client connected +[2025-05-14T07:44:05.116] [INFO] monitorLogs - MQTT client connected +[2025-05-14T09:41:53.028] [INFO] monitorLogs - MQTT client connected +[2025-05-14T10:08:36.250] [INFO] monitorLogs - MQTT client connected +[2025-05-14T10:44:48.340] [INFO] monitorLogs - MQTT client connected +[2025-05-14T10:45:13.009] [INFO] monitorLogs - MQTT client connected +[2025-05-14T10:46:34.568] [INFO] monitorLogs - MQTT client connected +[2025-05-14T10:47:24.134] [INFO] monitorLogs - MQTT client connected +[2025-05-14T10:48:47.549] [INFO] monitorLogs - MQTT client connected +[2025-05-14T10:52:02.543] [INFO] monitorLogs - MQTT client connected +[2025-05-14T10:53:03.624] [INFO] monitorLogs - MQTT client connected +[2025-05-14T10:53:55.705] [INFO] monitorLogs - MQTT client connected +[2025-05-14T10:55:32.263] [INFO] monitorLogs - MQTT client connected +[2025-05-14T20:44:44.148] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-05-14T20:44:44.451] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-05-14T20:44:44.754] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-05-15T03:28:51.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-15 03:28:51 +[2025-05-15T04:51:06.458] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-05-15T04:51:06.760] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-05-15T04:51:07.063] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-05-15T20:46:05.670] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-05-15T20:46:05.978] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-05-15T20:46:06.281] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-05-16T03:28:52.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-16 03:28:52 +[2025-05-16T04:49:49.404] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-05-16T04:49:49.706] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-05-16T04:49:50.009] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-05-16T20:47:26.058] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-05-16T20:47:26.365] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-05-16T20:47:26.668] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-05-17T03:28:53.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-17 03:28:53 +[2025-05-17T04:48:34.062] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-05-17T04:48:34.364] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-05-17T04:48:34.666] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-05-17T20:48:45.829] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-05-17T20:48:46.136] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-05-17T20:48:46.439] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-05-18T03:28:54.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-18 03:28:54 +[2025-05-18T04:47:20.773] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-05-18T04:47:21.076] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-05-18T04:47:21.379] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-05-18T13:24:47.083] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-05-18T13:24:52.426] [INFO] monitorLogs - buildTasks - params undefined +[2025-05-18T13:24:52.431] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-05-18T13:24:52.432] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-05-18T13:24:52.432] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-05-18T13:24:52.436] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-05-18T13:24:52.438] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 1 2025-05-19T02:47:00.437Z +[2025-05-18T13:24:52.439] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 1 2025-05-18T18:50:00.439Z +[2025-05-18T13:24:52.440] [INFO] monitorLogs - -->time_points final 1 [ + { start_time: '04:47', value: 0, name: 'dawn' }, + { start_time: '20:50', value: 1, name: 'dusk' } +] +[2025-05-18T13:24:52.441] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-05-18T13:24:52.442] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-05-18T13:24:52.443] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-05-18T13:24:52.445] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-05-18T13:24:52.446] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 2 2025-05-19T02:47:00.446Z +[2025-05-18T13:24:52.447] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 2 2025-05-18T18:50:00.446Z +[2025-05-18T13:24:52.447] [INFO] monitorLogs - -->time_points final 2 [ + { start_time: '04:47', value: 0, name: 'dawn' }, + { start_time: '20:50', value: 1, name: 'dusk' } +] +[2025-05-18T13:24:52.448] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-05-18T13:24:52.449] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-05-18T13:24:52.450] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-05-18T13:24:52.452] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-05-18T13:24:52.452] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 3 2025-05-19T02:47:00.452Z +[2025-05-18T13:24:52.453] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 3 2025-05-18T18:50:00.453Z +[2025-05-18T13:24:52.454] [INFO] monitorLogs - -->time_points final 3 [ + { start_time: '04:47', value: 0, name: 'dawn' }, + { start_time: '20:50', value: 1, name: 'dusk' } +] +[2025-05-18T13:24:52.455] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-05-18T13:24:52.456] [INFO] monitorLogs - tasks created: 14 +[2025-05-18T13:24:52.458] [INFO] monitorLogs - -->FLOW bol spustený dz4ojlpP85JMgDLZWkQJ4D7aKYqQexEr62GXRV1y 2025-04-24 +[2025-05-18T13:24:57.461] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-05-18T20:50:00.559] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-05-18T20:50:00.867] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-05-18T20:50:01.171] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-05-19T03:24:52.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-19 03:24:52 +[2025-05-19T04:47:00.734] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-05-19T04:47:01.036] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-05-19T04:47:01.339] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-05-19T20:51:22.172] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-05-19T20:51:22.480] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-05-19T20:51:22.783] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-05-20T03:24:53.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-20 03:24:53 +[2025-05-20T04:45:00.619] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-05-20T04:45:00.921] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-05-20T04:45:01.223] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-05-20T20:52:38.915] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-05-20T20:52:39.222] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-05-20T20:52:39.531] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-05-21T03:24:54.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-21 03:24:54 +[2025-05-21T04:43:53.430] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-05-21T04:43:53.733] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-05-21T04:43:54.036] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-05-21T20:53:54.389] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-05-21T20:53:54.697] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-05-21T20:53:54.999] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-05-22T03:24:56.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-22 03:24:56 +[2025-05-22T04:42:48.493] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-05-22T04:42:48.796] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-05-22T04:42:49.099] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-05-22T20:55:08.833] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-05-22T20:55:09.142] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-05-22T20:55:09.445] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-05-23T03:24:57.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-23 03:24:57 +[2025-05-23T04:41:45.655] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-05-23T04:41:45.958] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-05-23T04:41:46.260] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-05-23T20:56:21.882] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-05-23T20:56:22.190] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-05-23T20:56:22.493] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-05-24T03:24:58.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-24 03:24:58 +[2025-05-24T04:40:45.087] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-05-24T04:40:45.389] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-05-24T04:40:45.691] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-05-24T20:57:33.841] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-05-24T20:57:34.148] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-05-24T20:57:34.451] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-05-25T03:24:59.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-25 03:24:59 +[2025-05-25T04:39:46.559] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-05-25T04:39:46.869] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-05-25T04:39:47.171] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-05-25T20:58:44.402] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-05-25T20:58:44.710] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-05-25T20:58:45.012] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-05-26T03:25:00.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-26 03:25:00 +[2025-05-26T04:38:50.267] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-05-26T04:38:50.569] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-05-26T04:38:50.872] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-05-26T20:59:53.627] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-05-26T20:59:53.936] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-05-26T20:59:54.238] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-05-27T03:25:01.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-27 03:25:01 +[2025-05-27T04:37:56.446] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-05-27T04:37:56.748] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-05-27T04:37:57.050] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-05-27T21:01:01.542] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-05-27T21:01:01.850] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-05-27T21:01:02.152] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-05-28T03:25:07.726] [INFO] monitorLogs - setCorrectPlcTimeOnceADay - function error SyntaxError: Unexpected token < in JSON at position 0 + at JSON.parse () + at /home/unipi/flowserver/flow/cmd_manager.js:2411:28 + at Object.exec_callback [as callback] (/home/unipi/flowserver/node_modules/total.js/builders.js:5803:3) + at IncomingMessage.request_process_end (/home/unipi/flowserver/node_modules/total.js/utils.js:1184:11) + at IncomingMessage.emit (events.js:412:35) + at endReadableNT (internal/streams/readable.js:1334:12) + at processTicksAndRejections (internal/process/task_queues.js:82:21) 503: Service Unavailable
503
Service Unavailable
+[2025-05-28T04:37:04.975] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-05-28T04:37:05.279] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-05-28T04:37:05.581] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-05-28T21:02:07.705] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-05-28T21:02:08.011] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-05-28T21:02:08.314] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-05-29T03:25:03.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-29 03:25:03 +[2025-05-29T04:36:15.956] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-05-29T04:36:16.259] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-05-29T04:36:16.561] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-05-29T21:03:12.258] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-05-29T21:03:12.564] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-05-29T21:03:12.867] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-05-30T03:25:04.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-30 03:25:04 +[2025-05-30T04:35:29.242] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-05-30T04:35:29.544] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-05-30T04:35:29.847] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-05-30T21:04:15.418] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-05-30T21:04:15.726] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-05-30T21:04:16.028] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-05-31T03:25:06.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-31 03:25:06 +[2025-05-31T04:34:45.004] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-05-31T04:34:45.307] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-05-31T04:34:45.610] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-05-31T21:05:16.513] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-05-31T21:05:16.815] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-05-31T21:05:17.118] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-01T03:25:07.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-01 03:25:07 +[2025-06-01T04:34:03.200] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-01T04:34:03.503] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-01T04:34:03.805] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-01T21:06:16.396] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-01T21:06:16.704] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-01T21:06:17.006] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-02T03:25:08.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-02 03:25:08 +[2025-06-02T04:33:23.801] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-02T04:33:24.103] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-02T04:33:24.405] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-02T21:07:13.939] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-02T21:07:14.246] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-02T21:07:14.548] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-03T03:25:10.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-03 03:25:10 +[2025-06-03T04:32:46.867] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-03T04:32:47.170] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-03T04:32:47.472] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-03T21:08:09.667] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-03T21:08:09.975] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-03T21:08:10.277] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-04T03:25:11.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-04 03:25:11 +[2025-06-04T04:32:12.660] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-04T04:32:12.963] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-04T04:32:13.264] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-04T21:09:03.816] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-04T21:09:04.123] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-04T21:09:04.425] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-05T03:25:12.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-05 03:25:12 +[2025-06-05T04:31:40.668] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-05T04:31:40.971] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-05T04:31:41.273] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-05T21:09:55.669] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-05T21:09:55.977] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-05T21:09:56.281] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-06T03:25:14.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-06 03:25:14 +[2025-06-06T04:31:11.532] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-06T04:31:11.834] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-06T04:31:12.136] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-06T21:10:45.705] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-06T21:10:46.012] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-06T21:10:46.315] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-07T03:25:15.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-07 03:25:15 +[2025-06-07T04:30:45.201] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-07T04:30:45.503] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-07T04:30:45.805] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-07T21:11:33.475] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-07T21:11:33.781] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-07T21:11:34.083] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-08T03:25:17.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-08 03:25:17 +[2025-06-08T04:30:21.137] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-08T04:30:21.439] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-08T04:30:21.741] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-08T21:12:19.017] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-08T21:12:19.320] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-08T21:12:19.623] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-09T03:25:18.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-09 03:25:18 +[2025-06-09T04:29:59.919] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-09T04:30:00.222] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-09T04:30:00.524] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-09T21:13:02.429] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-09T21:13:02.737] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-09T21:13:03.041] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-10T03:25:19.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-10 03:25:19 +[2025-06-10T04:29:41.294] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-10T04:29:41.596] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-10T04:29:41.898] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-10T21:13:43.692] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-10T21:13:44.000] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-10T21:13:44.304] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-11T03:25:20.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-11 03:25:20 +[2025-06-11T04:29:25.128] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-11T04:29:25.431] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-11T04:29:25.733] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-11T21:14:22.641] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-11T21:14:22.950] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-11T21:14:23.252] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-12T03:25:21.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-12 03:25:21 +[2025-06-12T04:29:11.933] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-12T04:29:12.235] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-12T04:29:12.537] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-12T21:14:59.255] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-12T21:14:59.562] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-12T21:14:59.864] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-13T03:25:23.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-13 03:25:23 +[2025-06-13T04:29:01.310] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-13T04:29:01.612] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-13T04:29:01.914] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-13T15:26:48.993] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-06-13T15:26:54.344] [INFO] monitorLogs - buildTasks - params undefined +[2025-06-13T15:26:54.348] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-06-13T15:26:54.349] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-06-13T15:26:54.350] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-06-13T15:26:54.354] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-06-13T15:26:54.356] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 1 2025-06-14T02:29:00.355Z +[2025-06-13T15:26:54.357] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 1 2025-06-13T19:15:00.357Z +[2025-06-13T15:26:54.358] [INFO] monitorLogs - -->time_points final 1 [ + { start_time: '04:29', value: 0, name: 'dawn' }, + { start_time: '21:15', value: 1, name: 'dusk' } +] +[2025-06-13T15:26:54.359] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-06-13T15:26:54.360] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-06-13T15:26:54.360] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-06-13T15:26:54.363] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-06-13T15:26:54.363] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 2 2025-06-14T02:29:00.363Z +[2025-06-13T15:26:54.364] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 2 2025-06-13T19:15:00.364Z +[2025-06-13T15:26:54.365] [INFO] monitorLogs - -->time_points final 2 [ + { start_time: '04:29', value: 0, name: 'dawn' }, + { start_time: '21:15', value: 1, name: 'dusk' } +] +[2025-06-13T15:26:54.366] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-06-13T15:26:54.367] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-06-13T15:26:54.367] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-06-13T15:26:54.370] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-06-13T15:26:54.370] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 3 2025-06-14T02:29:00.370Z +[2025-06-13T15:26:54.371] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 3 2025-06-13T19:15:00.371Z +[2025-06-13T15:26:54.372] [INFO] monitorLogs - -->time_points final 3 [ + { start_time: '04:29', value: 0, name: 'dawn' }, + { start_time: '21:15', value: 1, name: 'dusk' } +] +[2025-06-13T15:26:54.373] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-06-13T15:26:54.374] [INFO] monitorLogs - tasks created: 14 +[2025-06-13T15:26:54.376] [INFO] monitorLogs - -->FLOW bol spustený dz4ojlpP85JMgDLZWkQJ4D7aKYqQexEr62GXRV1y 2025-04-24 +[2025-06-13T15:26:59.379] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-13T21:15:00.661] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-13T21:15:00.970] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-13T21:15:01.273] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-14T03:26:56.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-14 03:26:56 +[2025-06-14T04:29:00.632] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-14T04:29:00.935] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-14T04:29:01.238] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-14T21:16:05.238] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-14T21:16:05.548] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-14T21:16:05.850] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-15T03:26:57.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-15 03:26:57 +[2025-06-15T04:28:48.039] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-15T04:28:48.341] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-15T04:28:48.644] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-15T21:16:34.276] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-15T21:16:34.584] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-15T21:16:34.886] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-16T03:26:59.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-16 03:26:59 +[2025-06-16T04:28:45.364] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-16T04:28:45.667] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-16T04:28:45.969] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-16T21:17:01.294] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-16T21:17:01.602] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-16T21:17:01.904] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-17T03:27:00.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-17 03:27:00 +[2025-06-17T04:28:45.268] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-17T04:28:45.570] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-17T04:28:45.873] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-17T21:17:25.494] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-17T21:17:25.802] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-17T21:17:26.106] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-18T03:27:01.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-18 03:27:01 +[2025-06-18T04:28:48.017] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-18T04:28:48.319] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-18T04:28:48.621] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-18T21:17:47.001] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-18T21:17:47.307] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-18T21:17:47.610] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-19T03:27:02.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-19 03:27:02 +[2025-06-19T04:28:53.288] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-19T04:28:53.591] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-19T04:28:53.894] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-19T21:18:06.175] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-19T21:18:06.478] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-19T21:18:06.780] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-20T03:27:04.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-20 03:27:04 +[2025-06-20T04:29:01.219] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-20T04:29:01.521] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-20T04:29:01.823] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-20T21:18:22.621] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-20T21:18:22.923] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-20T21:18:23.225] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-21T03:27:05.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-21 03:27:05 +[2025-06-21T04:29:11.820] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-21T04:29:12.123] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-21T04:29:12.425] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-21T21:18:36.439] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-21T21:18:36.748] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-21T21:18:37.050] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-22T03:27:06.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-22 03:27:06 +[2025-06-22T04:29:25.203] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-22T04:29:25.506] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-22T04:29:25.809] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-22T21:18:47.487] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-22T21:18:47.796] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-22T21:18:48.099] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-23T03:27:08.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-23 03:27:08 +[2025-06-23T04:29:40.844] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-23T04:29:41.147] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-23T04:29:41.450] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-23T21:18:56.142] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-23T21:18:56.445] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-23T21:18:56.748] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-24T03:27:09.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-24 03:27:09 +[2025-06-24T04:29:59.187] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-24T04:29:59.491] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-24T04:29:59.794] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-24T21:19:01.925] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-24T21:19:02.229] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-24T21:19:02.531] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-25T03:27:11.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-25 03:27:11 +[2025-06-25T04:30:20.314] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-25T04:30:20.617] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-25T04:30:20.919] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-25T21:19:04.982] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-25T21:19:05.290] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-25T21:19:05.592] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-26T03:27:12.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-26 03:27:12 +[2025-06-26T04:30:43.686] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-26T04:30:43.989] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-26T04:30:44.292] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-26T21:19:05.194] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-26T21:19:05.501] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-26T21:19:05.803] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-27T03:27:14.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-27 03:27:14 +[2025-06-27T04:31:09.537] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-27T04:31:09.840] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-27T04:31:10.141] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-27T21:19:02.886] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-27T21:19:03.193] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-27T21:19:03.496] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-28T03:27:15.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-28 03:27:15 +[2025-06-28T04:31:37.707] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-28T04:31:38.009] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-28T04:31:38.311] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-28T21:18:57.551] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-28T21:18:57.859] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-28T21:18:58.162] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-29T03:27:17.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-29 03:27:17 +[2025-06-29T04:32:08.386] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-29T04:32:08.688] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-29T04:32:08.991] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-29T21:18:49.944] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-29T21:18:50.251] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-29T21:18:50.553] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-30T03:27:18.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-30 03:27:18 +[2025-06-30T04:32:41.453] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-30T04:32:41.755] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-30T04:32:42.058] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-30T21:18:39.334] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-30T21:18:39.642] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-30T21:18:39.944] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-01T03:27:20.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-01 03:27:20 +[2025-07-01T04:33:16.770] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-01T04:33:17.073] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-01T04:33:17.375] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-01T21:18:25.848] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-01T21:18:26.155] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-01T21:18:26.458] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-02T03:27:22.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-02 03:27:22 +[2025-07-02T04:33:54.440] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-02T04:33:54.742] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-02T04:33:55.043] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-02T21:18:10.055] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-02T21:18:10.362] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-02T21:18:10.665] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-03T03:27:23.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-03 03:27:23 +[2025-07-03T04:34:34.271] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-03T04:34:34.574] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-03T04:34:34.875] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-03T21:17:51.197] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-03T21:17:51.499] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-03T21:17:51.801] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-04T03:27:24.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-04 03:27:24 +[2025-07-04T04:35:16.141] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-04T04:35:16.443] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-04T04:35:16.745] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-04T21:17:29.742] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-04T21:17:30.049] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-04T21:17:30.352] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-05T03:27:26.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-05 03:27:26 +[2025-07-05T04:36:00.246] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-05T04:36:00.548] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-05T04:36:00.850] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-05T21:17:05.869] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-05T21:17:06.176] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-05T21:17:06.479] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-06T03:27:27.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-06 03:27:27 +[2025-07-06T04:36:46.520] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-06T04:36:46.822] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-06T04:36:47.124] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-06T21:16:39.101] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-06T21:16:39.409] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-06T21:16:39.712] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-07T03:27:28.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-07 03:27:28 +[2025-07-07T04:37:34.586] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-07T04:37:34.887] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-07T04:37:35.190] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-07T13:23:09.162] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-07-07T13:23:14.508] [INFO] monitorLogs - buildTasks - params undefined +[2025-07-07T13:23:14.513] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-07-07T13:23:14.514] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-07-07T13:23:14.514] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-07-07T13:23:14.518] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-07-07T13:23:14.520] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 1 2025-07-08T02:37:00.519Z +[2025-07-07T13:23:14.521] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 1 2025-07-07T19:16:00.521Z +[2025-07-07T13:23:14.522] [INFO] monitorLogs - -->time_points final 1 [ + { start_time: '04:37', value: 0, name: 'dawn' }, + { start_time: '21:16', value: 1, name: 'dusk' } +] +[2025-07-07T13:23:14.523] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-07-07T13:23:14.524] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-07-07T13:23:14.525] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-07-07T13:23:14.527] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-07-07T13:23:14.528] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 2 2025-07-08T02:37:00.528Z +[2025-07-07T13:23:14.529] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 2 2025-07-07T19:16:00.528Z +[2025-07-07T13:23:14.529] [INFO] monitorLogs - -->time_points final 2 [ + { start_time: '04:37', value: 0, name: 'dawn' }, + { start_time: '21:16', value: 1, name: 'dusk' } +] +[2025-07-07T13:23:14.530] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-07-07T13:23:14.531] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-07-07T13:23:14.532] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-07-07T13:23:14.534] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-07-07T13:23:14.534] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 3 2025-07-08T02:37:00.534Z +[2025-07-07T13:23:14.535] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 3 2025-07-07T19:16:00.535Z +[2025-07-07T13:23:14.536] [INFO] monitorLogs - -->time_points final 3 [ + { start_time: '04:37', value: 0, name: 'dawn' }, + { start_time: '21:16', value: 1, name: 'dusk' } +] +[2025-07-07T13:23:14.537] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-07-07T13:23:14.538] [INFO] monitorLogs - tasks created: 14 +[2025-07-07T13:23:14.540] [INFO] monitorLogs - -->FLOW bol spustený dz4ojlpP85JMgDLZWkQJ4D7aKYqQexEr62GXRV1y 2025-07-08 +[2025-07-07T13:23:19.543] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-07T13:44:48.056] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-07-07T13:44:53.407] [INFO] monitorLogs - buildTasks - params undefined +[2025-07-07T13:44:53.411] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-07-07T13:44:53.413] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-07-07T13:44:53.413] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-07-07T13:44:53.417] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-07-07T13:44:53.419] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 1 2025-07-08T02:37:00.418Z +[2025-07-07T13:44:53.420] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 1 2025-07-07T19:16:00.420Z +[2025-07-07T13:44:53.421] [INFO] monitorLogs - -->time_points final 1 [ + { start_time: '04:37', value: 0, name: 'dawn' }, + { start_time: '21:16', value: 1, name: 'dusk' } +] +[2025-07-07T13:44:53.422] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-07-07T13:44:53.423] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-07-07T13:44:53.424] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-07-07T13:44:53.426] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-07-07T13:44:53.427] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 2 2025-07-08T02:37:00.427Z +[2025-07-07T13:44:53.428] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 2 2025-07-07T19:16:00.427Z +[2025-07-07T13:44:53.428] [INFO] monitorLogs - -->time_points final 2 [ + { start_time: '04:37', value: 0, name: 'dawn' }, + { start_time: '21:16', value: 1, name: 'dusk' } +] +[2025-07-07T13:44:53.429] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-07-07T13:44:53.430] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-07-07T13:44:53.431] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-07-07T13:44:53.433] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-07-07T13:44:53.433] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 3 2025-07-08T02:37:00.433Z +[2025-07-07T13:44:53.434] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 3 2025-07-07T19:16:00.434Z +[2025-07-07T13:44:53.435] [INFO] monitorLogs - -->time_points final 3 [ + { start_time: '04:37', value: 0, name: 'dawn' }, + { start_time: '21:16', value: 1, name: 'dusk' } +] +[2025-07-07T13:44:53.436] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-07-07T13:44:53.437] [INFO] monitorLogs - tasks created: 14 +[2025-07-07T13:44:53.439] [INFO] monitorLogs - -->FLOW bol spustený dz4ojlpP85JMgDLZWkQJ4D7aKYqQexEr62GXRV1y 2025-07-08 +[2025-07-07T13:44:58.442] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-07T21:16:00.444] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-07T21:16:00.755] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-07T21:16:01.059] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-08T03:44:55.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-08 03:44:55 +[2025-07-08T04:37:00.565] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-08T04:37:00.868] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-08T04:37:01.170] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-08T21:15:37.484] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-08T21:15:37.793] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-08T21:15:38.095] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-09T03:44:56.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-09 03:44:56 +[2025-07-09T04:39:16.898] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-09T04:39:17.200] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-09T04:39:17.502] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-09T21:15:03.112] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-09T21:15:03.420] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-09T21:15:03.722] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-10T02:23:59.306] [INFO] monitorLogs - MQTT client error Error: connect ECONNREFUSED 192.168.252.1:1883 + at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1159:16) { + errno: -111, + code: 'ECONNREFUSED', + syscall: 'connect', + address: '192.168.252.1', + port: 1883 +} +[2025-07-10T03:44:58.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-10 03:44:58 +[2025-07-10T04:40:10.882] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-10T04:40:11.186] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-10T04:40:11.490] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-10T21:14:25.821] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-10T21:14:26.130] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-10T21:14:26.433] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-11T03:44:59.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-11 03:44:59 +[2025-07-11T04:41:06.761] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-11T04:41:07.064] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-11T04:41:07.365] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-11T21:13:46.155] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-11T21:13:46.468] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-11T21:13:46.771] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-12T03:45:00.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-12 03:45:00 +[2025-07-12T04:42:04.086] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-12T04:42:04.389] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-12T04:42:04.691] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-12T21:13:03.714] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-12T21:13:04.024] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-12T21:13:04.327] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-13T03:45:01.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-13 03:45:01 +[2025-07-13T04:43:03.485] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-13T04:43:03.786] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-13T04:43:04.089] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-13T21:12:18.959] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-13T21:12:19.267] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-13T21:12:19.569] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-14T03:45:03.013] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-14 03:45:03 +[2025-07-14T04:44:04.134] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-14T04:44:04.437] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-14T04:44:04.738] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-14T21:11:31.874] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-14T21:11:32.182] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-14T21:11:32.484] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-15T03:45:04.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-15 03:45:04 +[2025-07-15T04:45:06.410] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-15T04:45:06.712] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-15T04:45:07.014] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-15T21:10:42.308] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-15T21:10:42.616] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-15T21:10:42.918] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-16T03:45:06.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-16 03:45:06 +[2025-07-16T04:46:12.483] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-16T04:46:12.786] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-16T04:46:13.088] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-16T21:09:50.160] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-16T21:09:50.468] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-16T21:09:50.771] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-17T03:45:07.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-17 03:45:07 +[2025-07-17T04:47:15.638] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-17T04:47:15.940] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-17T04:47:16.243] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-17T21:08:55.728] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-17T21:08:56.036] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-17T21:08:56.339] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-18T03:45:09.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-18 03:45:09 +[2025-07-18T04:48:22.245] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-18T04:48:22.548] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-18T04:48:22.850] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-18T21:07:59.234] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-18T21:07:59.541] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-18T21:07:59.844] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-19T03:45:10.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-19 03:45:10 +[2025-07-19T04:49:30.477] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-19T04:49:30.780] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-19T04:49:31.082] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-19T21:07:00.166] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-19T21:07:00.473] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-19T21:07:00.776] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-20T03:45:11.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-20 03:45:11 +[2025-07-20T04:50:39.607] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-20T04:50:39.909] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-20T04:50:40.211] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-20T21:05:58.779] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-20T21:05:59.087] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-20T21:05:59.389] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-21T03:45:13.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-21 03:45:13 +[2025-07-21T04:51:50.041] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-21T04:51:50.344] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-21T04:51:50.646] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-21T21:04:55.256] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-21T21:04:55.565] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-21T21:04:55.868] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-22T03:45:14.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-22 03:45:14 +[2025-07-22T04:53:01.734] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-22T04:53:02.036] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-22T04:53:02.338] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-22T21:03:49.865] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-22T21:03:50.174] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-22T21:03:50.476] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-23T03:45:16.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-23 03:45:16 +[2025-07-23T04:54:14.453] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-23T04:54:14.755] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-23T04:54:15.057] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-23T21:02:41.970] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-23T21:02:42.279] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-23T21:02:42.582] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-24T03:45:17.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-24 03:45:17 +[2025-07-24T04:55:28.326] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-24T04:55:28.629] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-24T04:55:28.932] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-24T21:01:32.046] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-24T21:01:32.353] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-24T21:01:32.656] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-25T03:45:18.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-25 03:45:18 +[2025-07-25T04:56:43.034] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-25T04:56:43.336] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-25T04:56:43.638] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-25T21:00:20.103] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-25T21:00:20.411] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-25T21:00:20.714] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-26T03:45:20.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-26 03:45:20 +[2025-07-26T04:57:58.649] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-26T04:57:58.951] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-26T04:57:59.253] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-26T20:59:06.239] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-26T20:59:06.547] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-26T20:59:06.849] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-27T03:45:21.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-27 03:45:21 +[2025-07-27T04:59:15.085] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-27T04:59:15.387] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-27T04:59:15.690] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-27T20:57:51.073] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-27T20:57:51.380] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-27T20:57:51.683] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-28T03:45:22.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-28 03:45:22 +[2025-07-28T05:00:32.297] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-28T05:00:32.599] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-28T05:00:32.902] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-28T20:56:32.381] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-28T20:56:32.688] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-28T20:56:32.991] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-29T03:45:24.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-29 03:45:24 +[2025-07-29T05:01:50.535] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-29T05:01:50.837] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-29T05:01:51.138] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-29T12:19:36.996] [INFO] monitorLogs - MQTT client error Error: connect ECONNREFUSED 192.168.252.1:1883 + at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1159:16) { + errno: -111, + code: 'ECONNREFUSED', + syscall: 'connect', + address: '192.168.252.1', + port: 1883 +} +[2025-07-29T20:55:12.293] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-29T20:55:12.596] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-29T20:55:12.898] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-30T03:45:25.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-30 03:45:25 +[2025-07-30T05:03:09.313] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-30T05:03:09.615] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-30T05:03:09.917] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-30T20:53:50.812] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-30T20:53:51.121] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-30T20:53:51.424] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-31T03:45:26.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-31 03:45:26 +[2025-07-31T05:04:28.860] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-31T05:04:29.162] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-31T05:04:29.464] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-31T20:52:27.383] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-31T20:52:27.692] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-31T20:52:27.995] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-01T03:45:28.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-01 03:45:28 +[2025-08-01T05:05:48.712] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-01T05:05:49.015] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-01T05:05:49.318] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-01T20:51:02.101] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-01T20:51:02.410] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-01T20:51:02.714] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-02T03:45:29.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-02 03:45:29 +[2025-08-02T05:07:09.518] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-02T05:07:09.821] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-02T05:07:10.123] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-02T20:49:35.046] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-02T20:49:35.353] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-02T20:49:35.656] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-03T03:45:31.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-03 03:45:31 +[2025-08-03T05:08:30.545] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-03T05:08:30.847] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-03T05:08:31.150] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-03T20:48:06.369] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-03T20:48:06.676] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-03T20:48:06.978] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-04T03:45:32.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-04 03:45:32 +[2025-08-04T05:09:52.295] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-04T05:09:52.597] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-04T05:09:52.899] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-04T20:46:35.726] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-04T20:46:36.031] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-04T20:46:36.332] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-05T03:45:33.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-05 03:45:33 +[2025-08-05T05:11:14.351] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-05T05:11:14.653] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-05T05:11:14.956] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-05T20:45:03.730] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-05T20:45:04.037] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-05T20:45:04.340] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-06T03:45:35.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-06 03:45:35 +[2025-08-06T05:12:37.055] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-06T05:12:37.357] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-06T05:12:37.659] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-06T13:41:21.080] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-08-06T13:41:26.421] [INFO] monitorLogs - buildTasks - params undefined +[2025-08-06T13:41:26.425] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-08-06T13:41:26.426] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-08-06T13:41:26.427] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-08-06T13:41:26.431] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-08-06T13:41:26.432] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 1 2025-08-07T03:12:00.432Z +[2025-08-06T13:41:26.434] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 1 2025-08-06T18:43:00.433Z +[2025-08-06T13:41:26.434] [INFO] monitorLogs - -->time_points final 1 [ + { start_time: '05:12', value: 0, name: 'dawn' }, + { start_time: '20:43', value: 1, name: 'dusk' } +] +[2025-08-06T13:41:26.436] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-08-06T13:41:26.436] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-08-06T13:41:26.437] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-08-06T13:41:26.439] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-08-06T13:41:26.440] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 2 2025-08-07T03:12:00.440Z +[2025-08-06T13:41:26.441] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 2 2025-08-06T18:43:00.441Z +[2025-08-06T13:41:26.442] [INFO] monitorLogs - -->time_points final 2 [ + { start_time: '05:12', value: 0, name: 'dawn' }, + { start_time: '20:43', value: 1, name: 'dusk' } +] +[2025-08-06T13:41:26.443] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-08-06T13:41:26.443] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-08-06T13:41:26.444] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-08-06T13:41:26.446] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-08-06T13:41:26.447] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 3 2025-08-07T03:12:00.447Z +[2025-08-06T13:41:26.448] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 3 2025-08-06T18:43:00.448Z +[2025-08-06T13:41:26.449] [INFO] monitorLogs - -->time_points final 3 [ + { start_time: '05:12', value: 0, name: 'dawn' }, + { start_time: '20:43', value: 1, name: 'dusk' } +] +[2025-08-06T13:41:26.450] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-08-06T13:41:26.452] [INFO] monitorLogs - tasks created: 14 +[2025-08-06T13:41:26.454] [INFO] monitorLogs - -->FLOW bol spustený dz4ojlpP85JMgDLZWkQJ4D7aKYqQexEr62GXRV1y 2025-08-08 +[2025-08-06T13:41:31.456] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-06T20:43:00.692] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-06T20:43:01.000] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-06T20:43:01.302] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-07T03:41:28.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-07 03:41:28 +[2025-08-07T05:12:00.533] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-07T05:12:00.836] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-07T05:12:01.138] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-07T20:41:55.064] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-07T20:41:55.371] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-07T20:41:55.674] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-08T03:41:29.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-08 03:41:29 +[2025-08-08T05:15:23.009] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-08T05:15:23.312] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-08T05:15:23.615] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-08T20:40:18.318] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-08T20:40:18.620] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-08T20:40:18.922] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-09T03:41:31.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-09 03:41:31 +[2025-08-09T05:16:46.487] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-09T05:16:46.789] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-09T05:16:47.090] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-09T20:38:40.147] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-09T20:38:40.449] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-09T20:38:40.752] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-10T03:41:32.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-10 03:41:32 +[2025-08-10T05:18:10.095] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-10T05:18:10.398] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-10T05:18:10.700] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-10T20:37:00.715] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-10T20:37:01.018] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-10T20:37:01.320] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-11T03:41:34.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-11 03:41:34 +[2025-08-11T05:19:34.009] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-11T05:19:34.312] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-11T05:19:34.614] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-11T20:35:19.516] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-11T20:35:19.819] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-11T20:35:20.121] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-12T03:41:35.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-12 03:41:35 +[2025-08-12T05:20:58.405] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-12T05:20:58.708] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-12T05:20:59.009] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-12T20:33:37.253] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-12T20:33:37.561] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-12T20:33:37.864] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-13T03:41:37.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-13 03:41:37 +[2025-08-13T05:22:22.717] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-13T05:22:23.019] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-13T05:22:23.322] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-13T20:31:53.511] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-13T20:31:53.819] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-13T20:31:54.121] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-14T03:41:38.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-14 03:41:38 +[2025-08-14T05:23:46.906] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-14T05:23:47.209] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-14T05:23:47.512] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-14T20:30:08.531] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-14T20:30:08.839] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-14T20:30:09.142] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-15T03:41:40.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-15 03:41:40 +[2025-08-15T05:25:11.508] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-15T05:25:11.810] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-15T05:25:12.113] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-15T20:28:22.381] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-15T20:28:22.687] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-15T20:28:22.989] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-16T03:41:41.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-16 03:41:41 +[2025-08-16T05:26:36.257] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-16T05:26:36.560] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-16T05:26:36.862] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-16T20:26:34.879] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-16T20:26:35.182] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-16T20:26:35.484] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-17T03:41:43.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-17 03:41:43 +[2025-08-17T05:28:01.100] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-17T05:28:01.402] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-17T05:28:01.704] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-17T20:24:46.453] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-17T20:24:46.755] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-17T20:24:47.057] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-18T03:41:44.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-18 03:41:44 +[2025-08-18T05:29:25.660] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-18T05:29:25.962] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-18T05:29:26.264] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-18T20:22:56.640] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-18T20:22:56.942] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-18T20:22:57.244] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-19T03:41:46.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-19 03:41:46 +[2025-08-19T05:30:50.715] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-19T05:30:51.016] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-19T05:30:51.319] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-19T20:21:05.921] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-19T20:21:06.227] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-19T20:21:06.529] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-20T03:41:47.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-20 03:41:47 +[2025-08-20T05:32:15.327] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-20T05:32:15.629] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-20T05:32:15.931] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-20T20:19:14.036] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-20T20:19:14.342] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-20T20:19:14.644] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-21T03:41:49.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-21 03:41:49 +[2025-08-21T05:33:40.119] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-21T05:33:40.421] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-21T05:33:40.723] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-21T20:17:20.872] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-21T20:17:21.175] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-21T20:17:21.477] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-22T03:41:50.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-22 03:41:50 +[2025-08-22T05:35:05.015] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-22T05:35:05.318] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-22T05:35:05.621] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-22T20:15:26.942] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-22T20:15:27.245] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-22T20:15:27.547] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-23T03:41:51.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-23 03:41:51 +[2025-08-23T05:36:29.742] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-23T05:36:30.044] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-23T05:36:30.345] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-23T20:13:31.924] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-23T20:13:32.226] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-23T20:13:32.528] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-24T03:41:53.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-24 03:41:53 +[2025-08-24T05:37:54.647] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-24T05:37:54.949] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-24T05:37:55.251] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-24T20:11:36.146] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-24T20:11:36.448] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-24T20:11:36.751] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-25T03:41:54.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-25 03:41:54 +[2025-08-25T05:39:19.345] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-25T05:39:19.647] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-25T05:39:19.949] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-25T20:09:39.419] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-25T20:09:39.722] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-25T20:09:40.023] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-26T03:41:55.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-26 03:41:55 +[2025-08-26T05:40:43.970] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-26T05:40:44.272] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-26T05:40:44.574] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-26T20:07:41.760] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-26T20:07:42.066] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-26T20:07:42.368] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-27T03:41:57.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-27 03:41:57 +[2025-08-27T05:42:08.562] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-27T05:42:08.865] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-27T05:42:09.167] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-27T20:05:43.344] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-27T20:05:43.648] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-27T20:05:43.949] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-28T03:41:58.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-28 03:41:58 +[2025-08-28T05:43:32.947] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-28T05:43:33.250] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-28T05:43:33.552] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-28T20:03:44.198] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-28T20:03:44.500] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-28T20:03:44.802] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-29T03:41:59.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-29 03:41:59 +[2025-08-29T05:44:57.337] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-29T05:44:57.640] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-29T05:44:57.942] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-29T20:01:43.999] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-29T20:01:44.306] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-29T20:01:44.609] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-30T03:42:01.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-30 03:42:01 +[2025-08-30T05:46:21.909] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-30T05:46:22.211] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-30T05:46:22.514] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-30T19:59:43.327] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-30T19:59:43.629] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-30T19:59:43.931] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-31T03:42:02.014] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-31 03:42:02 +[2025-08-31T05:47:46.283] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-31T05:47:46.586] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-31T05:47:46.888] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-31T19:57:41.981] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-31T19:57:42.283] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-31T19:57:42.585] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-01T03:42:04.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-01 03:42:04 +[2025-09-01T05:49:10.423] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-01T05:49:10.725] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-01T05:49:11.027] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-01T07:47:55.939] [INFO] monitorLogs - turnLine on - (line, SETTINGS.maintenance_mode) 0 true command received from platform +[2025-09-01T07:48:06.814] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false command received from platform +[2025-09-01T07:48:59.606] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false command received from platform +[2025-09-01T07:49:06.884] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false command received from platform +[2025-09-01T08:14:43.913] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false command received from platform +[2025-09-01T08:14:48.074] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false command received from platform +[2025-09-01T08:14:52.554] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false command received from platform +[2025-09-01T08:14:57.355] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false command received from platform +[2025-09-01T13:39:50.100] [INFO] monitorLogs - turnLine on - (line, SETTINGS.maintenance_mode) 0 true command received from platform +[2025-09-01T13:39:54.257] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false command received from platform +[2025-09-01T13:40:09.937] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false command received from platform +[2025-09-01T13:40:19.218] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false command received from platform +[2025-09-01T19:55:41.497] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-01T19:55:41.799] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-01T19:55:42.101] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-02T03:42:05.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-02 03:42:05 +[2025-09-02T05:50:34.621] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-02T05:50:34.923] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-02T05:50:35.225] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-02T19:53:37.026] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-02T19:53:37.333] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-02T19:53:37.635] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-03T03:42:06.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-03 03:42:06 +[2025-09-03T05:51:58.560] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-03T05:51:58.862] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-03T05:51:59.165] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-03T19:51:33.604] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-03T19:51:33.908] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-03T19:51:34.212] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-04T03:42:08.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-04 03:42:08 +[2025-09-04T05:53:22.632] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-04T05:53:22.935] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-04T05:53:23.238] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-04T19:49:29.658] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-04T19:49:29.961] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-04T19:49:30.263] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-05T03:42:09.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-05 03:42:09 +[2025-09-05T05:54:46.668] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-05T05:54:46.971] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-05T05:54:47.272] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-05T19:47:25.422] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-05T19:47:25.724] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-05T19:47:26.026] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-06T03:42:11.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-06 03:42:11 +[2025-09-06T05:56:10.549] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-06T05:56:10.851] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-06T05:56:11.153] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-06T19:45:20.557] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-06T19:45:20.859] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-06T19:45:21.161] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-07T03:42:12.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-07 03:42:12 +[2025-09-07T05:57:34.535] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-07T05:57:34.837] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-07T05:57:35.139] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-07T19:43:17.722] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-07T19:43:18.023] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-07T19:43:18.325] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-08T03:42:13.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-08 03:42:13 +[2025-09-08T05:58:58.266] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-08T05:58:58.569] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-08T05:58:58.871] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-08T19:41:09.342] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-08T19:41:09.649] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-08T19:41:09.952] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-09T03:42:15.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-09 03:42:15 +[2025-09-09T06:00:21.939] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-09T06:00:22.242] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-09T06:00:22.543] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-09T19:39:03.014] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-09T19:39:03.317] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-09T19:39:03.619] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-10T03:42:16.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-10 03:42:16 +[2025-09-10T06:01:45.775] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-10T06:01:46.077] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-10T06:01:46.379] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-10T19:36:56.431] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-10T19:36:56.733] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-10T19:36:57.035] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-11T03:42:17.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-11 03:42:17 +[2025-09-11T06:03:09.382] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-11T06:03:09.685] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-11T06:03:09.987] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-11T19:34:49.600] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-11T19:34:49.907] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-11T19:34:50.209] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-12T03:42:19.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-12 03:42:19 +[2025-09-12T06:04:33.261] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-12T06:04:33.565] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-12T06:04:33.867] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-12T19:32:42.355] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-12T19:32:42.656] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-12T19:32:42.958] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-13T03:42:20.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-13 03:42:20 +[2025-09-13T06:05:56.799] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-13T06:05:57.102] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-13T06:05:57.404] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-13T19:30:34.745] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-13T19:30:35.047] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-13T19:30:35.350] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-14T03:42:21.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-14 03:42:21 +[2025-09-14T06:07:20.629] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-14T06:07:20.931] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-14T06:07:21.233] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-14T19:28:27.140] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-14T19:28:27.448] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-14T19:28:27.750] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-15T03:42:23.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-15 03:42:23 +[2025-09-15T06:08:44.393] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-15T06:08:44.695] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-15T06:08:44.997] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-15T19:26:19.092] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-15T19:26:19.399] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-15T19:26:19.702] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-16T03:42:24.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-16 03:42:24 +[2025-09-16T06:10:08.433] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-16T06:10:08.735] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-16T06:10:09.044] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-16T15:08:03.034] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-09-16T15:08:08.371] [INFO] monitorLogs - buildTasks - params undefined +[2025-09-16T15:08:08.375] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-09-16T15:08:08.377] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-09-16T15:08:08.378] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-09-16T15:08:08.382] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-16T15:08:08.383] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 1 2025-09-17T04:10:00.382Z +[2025-09-16T15:08:08.384] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 1 2025-09-16T17:24:00.384Z +[2025-09-16T15:08:08.385] [INFO] monitorLogs - -->time_points final 1 [ + { start_time: '06:10', value: 0, name: 'dawn' }, + { start_time: '19:24', value: 1, name: 'dusk' } +] +[2025-09-16T15:08:08.386] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-09-16T15:08:08.387] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-09-16T15:08:08.388] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-09-16T15:08:08.390] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-16T15:08:08.391] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 2 2025-09-17T04:10:00.390Z +[2025-09-16T15:08:08.391] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 2 2025-09-16T17:24:00.391Z +[2025-09-16T15:08:08.392] [INFO] monitorLogs - -->time_points final 2 [ + { start_time: '06:10', value: 0, name: 'dawn' }, + { start_time: '19:24', value: 1, name: 'dusk' } +] +[2025-09-16T15:08:08.393] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-09-16T15:08:08.394] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-09-16T15:08:08.394] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-09-16T15:08:08.397] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-16T15:08:08.397] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 3 2025-09-17T04:10:00.397Z +[2025-09-16T15:08:08.398] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 3 2025-09-16T17:24:00.398Z +[2025-09-16T15:08:08.399] [INFO] monitorLogs - -->time_points final 3 [ + { start_time: '06:10', value: 0, name: 'dawn' }, + { start_time: '19:24', value: 1, name: 'dusk' } +] +[2025-09-16T15:08:08.400] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-09-16T15:08:08.401] [INFO] monitorLogs - tasks created: 14 +[2025-09-16T15:08:08.403] [INFO] monitorLogs - -->FLOW bol spustený dz4ojlpP85JMgDLZWkQJ4D7aKYqQexEr62GXRV1y 2025-08-08 +[2025-09-16T15:08:13.671] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-16T19:24:00.426] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-16T19:24:00.732] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-16T19:24:01.035] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-17T03:08:10.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-17 03:08:10 +[2025-09-17T06:10:00.528] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-17T06:10:00.831] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-17T06:10:01.133] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-17T19:22:02.821] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-17T19:22:03.124] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-17T19:22:03.426] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-17T20:39:24.630] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-09-17T20:39:29.967] [INFO] monitorLogs - buildTasks - params undefined +[2025-09-17T20:39:29.972] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-09-17T20:39:29.974] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-09-17T20:39:29.974] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-09-17T20:39:29.978] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-17T20:39:29.980] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 1 2025-09-18T04:11:00.979Z +[2025-09-17T20:39:29.981] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 1 2025-09-18T17:22:00.981Z +[2025-09-17T20:39:29.982] [INFO] monitorLogs - -->time_points final 1 [ + { start_time: '06:11', value: 0, name: 'dawn' }, + { start_time: '19:22', value: 1, name: 'dusk' } +] +[2025-09-17T20:39:29.983] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-09-17T20:39:29.984] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-09-17T20:39:29.984] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-09-17T20:39:29.987] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-17T20:39:29.987] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 2 2025-09-18T04:11:00.987Z +[2025-09-17T20:39:29.988] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 2 2025-09-18T17:22:00.988Z +[2025-09-17T20:39:29.989] [INFO] monitorLogs - -->time_points final 2 [ + { start_time: '06:11', value: 0, name: 'dawn' }, + { start_time: '19:22', value: 1, name: 'dusk' } +] +[2025-09-17T20:39:29.990] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-09-17T20:39:29.991] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-09-17T20:39:29.991] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-09-17T20:39:29.993] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-17T20:39:29.994] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 3 2025-09-18T04:11:00.994Z +[2025-09-17T20:39:29.995] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 3 2025-09-18T17:22:00.995Z +[2025-09-17T20:39:29.995] [INFO] monitorLogs - -->time_points final 3 [ + { start_time: '06:11', value: 0, name: 'dawn' }, + { start_time: '19:22', value: 1, name: 'dusk' } +] +[2025-09-17T20:39:29.996] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-09-17T20:39:29.998] [INFO] monitorLogs - tasks created: 14 +[2025-09-17T20:39:30.000] [INFO] monitorLogs - -->FLOW bol spustený dz4ojlpP85JMgDLZWkQJ4D7aKYqQexEr62GXRV1y 2025-08-08 +[2025-09-17T20:39:35.002] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-18T03:39:31.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-18 03:39:31 +[2025-09-18T06:11:03.486] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-18T06:11:03.789] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-18T06:11:04.092] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-18T13:13:02.351] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false command received from platform +[2025-09-18T13:15:38.497] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false command received from platform +[2025-09-18T19:22:01.187] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-18T19:22:01.489] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-18T19:22:01.791] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-19T03:39:32.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-19 03:39:32 +[2025-09-19T06:14:20.262] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-19T06:14:20.565] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-19T06:14:20.867] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-19T11:18:56.662] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-09-19T11:19:02.005] [INFO] monitorLogs - buildTasks - params undefined +[2025-09-19T11:19:02.010] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-09-19T11:19:02.011] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-09-19T11:19:02.012] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-09-19T11:19:02.016] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-19T11:19:02.017] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 1 2025-09-20T04:14:00.016Z +[2025-09-19T11:19:02.018] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 1 2025-09-19T17:17:00.018Z +[2025-09-19T11:19:02.019] [INFO] monitorLogs - -->time_points final 1 [ + { start_time: '06:14', value: 0, name: 'dawn' }, + { start_time: '19:17', value: 1, name: 'dusk' } +] +[2025-09-19T11:19:02.020] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-09-19T11:19:02.021] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-09-19T11:19:02.022] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-09-19T11:19:02.024] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-19T11:19:02.025] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 2 2025-09-20T04:14:00.025Z +[2025-09-19T11:19:02.026] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 2 2025-09-19T17:17:00.026Z +[2025-09-19T11:19:02.026] [INFO] monitorLogs - -->time_points final 2 [ + { start_time: '06:14', value: 0, name: 'dawn' }, + { start_time: '19:17', value: 1, name: 'dusk' } +] +[2025-09-19T11:19:02.027] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-09-19T11:19:02.028] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-09-19T11:19:02.029] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-09-19T11:19:02.031] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-19T11:19:02.032] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 3 2025-09-20T04:14:00.031Z +[2025-09-19T11:19:02.032] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 3 2025-09-19T17:17:00.032Z +[2025-09-19T11:19:02.033] [INFO] monitorLogs - -->time_points final 3 [ + { start_time: '06:14', value: 0, name: 'dawn' }, + { start_time: '19:17', value: 1, name: 'dusk' } +] +[2025-09-19T11:19:02.034] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-09-19T11:19:02.035] [INFO] monitorLogs - tasks created: 14 +[2025-09-19T11:19:02.037] [INFO] monitorLogs - -->FLOW bol spustený dz4ojlpP85JMgDLZWkQJ4D7aKYqQexEr62GXRV1y 2025-08-08 +[2025-09-19T11:19:07.040] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-19T19:17:00.096] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-19T19:17:00.400] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-19T19:17:00.703] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-20T03:19:04.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-20 03:19:04 +[2025-09-20T06:14:00.214] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-20T06:14:00.518] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-20T06:14:00.819] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-20T19:15:37.865] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-20T19:15:38.168] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-20T19:15:38.471] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-21T01:29:20.121] [INFO] monitorLogs - MQTT client error Error: connect ECONNREFUSED 192.168.252.1:1883 + at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1159:16) { + errno: -111, + code: 'ECONNREFUSED', + syscall: 'connect', + address: '192.168.252.1', + port: 1883 +} +[2025-09-21T03:19:05.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-21 03:19:05 +[2025-09-21T06:17:08.624] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-21T06:17:08.927] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-21T06:17:09.229] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-21T18:10:33.026] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-09-21T18:10:38.357] [INFO] monitorLogs - buildTasks - params undefined +[2025-09-21T18:10:38.362] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-09-21T18:10:38.363] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-09-21T18:10:38.364] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-09-21T18:10:38.368] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-21T18:10:38.369] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 1 2025-09-22T04:17:00.368Z +[2025-09-21T18:10:38.371] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 1 2025-09-21T17:13:00.370Z +[2025-09-21T18:10:38.371] [INFO] monitorLogs - -->time_points final 1 [ + { start_time: '06:17', value: 0, name: 'dawn' }, + { start_time: '19:13', value: 1, name: 'dusk' } +] +[2025-09-21T18:10:38.373] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-09-21T18:10:38.373] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-09-21T18:10:38.374] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-09-21T18:10:38.376] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-21T18:10:38.377] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 2 2025-09-22T04:17:00.377Z +[2025-09-21T18:10:38.378] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 2 2025-09-21T17:13:00.378Z +[2025-09-21T18:10:38.379] [INFO] monitorLogs - -->time_points final 2 [ + { start_time: '06:17', value: 0, name: 'dawn' }, + { start_time: '19:13', value: 1, name: 'dusk' } +] +[2025-09-21T18:10:38.380] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-09-21T18:10:38.380] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-09-21T18:10:38.381] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-09-21T18:10:38.383] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-21T18:10:38.384] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 3 2025-09-22T04:17:00.384Z +[2025-09-21T18:10:38.385] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 3 2025-09-21T17:13:00.384Z +[2025-09-21T18:10:38.385] [INFO] monitorLogs - -->time_points final 3 [ + { start_time: '06:17', value: 0, name: 'dawn' }, + { start_time: '19:13', value: 1, name: 'dusk' } +] +[2025-09-21T18:10:38.386] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-09-21T18:10:38.387] [INFO] monitorLogs - tasks created: 14 +[2025-09-21T18:10:38.389] [INFO] monitorLogs - -->FLOW bol spustený dz4ojlpP85JMgDLZWkQJ4D7aKYqQexEr62GXRV1y 2025-08-08 +[2025-09-21T18:10:43.392] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-21T19:13:00.436] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-21T19:13:00.742] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-21T19:13:01.046] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-22T03:10:40.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-22 03:10:40 +[2025-09-22T06:17:00.607] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-22T06:17:00.910] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-22T06:17:01.213] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-22T19:11:21.077] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-22T19:11:21.380] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-22T19:11:21.683] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-23T03:10:42.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-23 03:10:42 +[2025-09-23T06:19:57.237] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-23T06:19:57.540] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-23T06:19:57.851] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-23T13:05:42.159] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-09-23T13:05:47.506] [INFO] monitorLogs - buildTasks - params undefined +[2025-09-23T13:05:47.511] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-09-23T13:05:47.512] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-09-23T13:05:47.513] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-09-23T13:05:47.517] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-23T13:05:47.518] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 1 2025-09-24T04:19:00.517Z +[2025-09-23T13:05:47.520] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 1 2025-09-23T17:09:00.519Z +[2025-09-23T13:05:47.520] [INFO] monitorLogs - -->time_points final 1 [ + { start_time: '06:19', value: 0, name: 'dawn' }, + { start_time: '19:09', value: 1, name: 'dusk' } +] +[2025-09-23T13:05:47.522] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-09-23T13:05:47.522] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-09-23T13:05:47.523] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-09-23T13:05:47.525] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-23T13:05:47.526] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 2 2025-09-24T04:19:00.526Z +[2025-09-23T13:05:47.527] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 2 2025-09-23T17:09:00.527Z +[2025-09-23T13:05:47.528] [INFO] monitorLogs - -->time_points final 2 [ + { start_time: '06:19', value: 0, name: 'dawn' }, + { start_time: '19:09', value: 1, name: 'dusk' } +] +[2025-09-23T13:05:47.529] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-09-23T13:05:47.529] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-09-23T13:05:47.530] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-09-23T13:05:47.532] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-23T13:05:47.533] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 3 2025-09-24T04:19:00.533Z +[2025-09-23T13:05:47.534] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 3 2025-09-23T17:09:00.534Z +[2025-09-23T13:05:47.534] [INFO] monitorLogs - -->time_points final 3 [ + { start_time: '06:19', value: 0, name: 'dawn' }, + { start_time: '19:09', value: 1, name: 'dusk' } +] +[2025-09-23T13:05:47.535] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-09-23T13:05:47.536] [INFO] monitorLogs - tasks created: 14 +[2025-09-23T13:05:47.539] [INFO] monitorLogs - -->FLOW bol spustený dz4ojlpP85JMgDLZWkQJ4D7aKYqQexEr62GXRV1y 2025-08-08 +[2025-09-23T13:05:52.540] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-23T14:32:13.764] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-09-23T14:32:19.099] [INFO] monitorLogs - buildTasks - params undefined +[2025-09-23T14:32:19.104] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-09-23T14:32:19.105] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-09-23T14:32:19.106] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-09-23T14:32:19.110] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-23T14:32:19.112] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 1 2025-09-24T04:19:00.111Z +[2025-09-23T14:32:19.113] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 1 2025-09-23T17:09:00.113Z +[2025-09-23T14:32:19.114] [INFO] monitorLogs - -->time_points final 1 [ + { start_time: '06:19', value: 0, name: 'dawn' }, + { start_time: '19:09', value: 1, name: 'dusk' } +] +[2025-09-23T14:32:19.115] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-09-23T14:32:19.116] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-09-23T14:32:19.116] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-09-23T14:32:19.119] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-23T14:32:19.119] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 2 2025-09-24T04:19:00.119Z +[2025-09-23T14:32:19.120] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 2 2025-09-23T17:09:00.120Z +[2025-09-23T14:32:19.121] [INFO] monitorLogs - -->time_points final 2 [ + { start_time: '06:19', value: 0, name: 'dawn' }, + { start_time: '19:09', value: 1, name: 'dusk' } +] +[2025-09-23T14:32:19.122] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-09-23T14:32:19.123] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-09-23T14:32:19.123] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-09-23T14:32:19.125] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-23T14:32:19.126] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 3 2025-09-24T04:19:00.126Z +[2025-09-23T14:32:19.127] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 3 2025-09-23T17:09:00.127Z +[2025-09-23T14:32:19.127] [INFO] monitorLogs - -->time_points final 3 [ + { start_time: '06:19', value: 0, name: 'dawn' }, + { start_time: '19:09', value: 1, name: 'dusk' } +] +[2025-09-23T14:32:19.128] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-09-23T14:32:19.130] [INFO] monitorLogs - tasks created: 14 +[2025-09-23T14:32:19.132] [INFO] monitorLogs - -->FLOW bol spustený dz4ojlpP85JMgDLZWkQJ4D7aKYqQexEr62GXRV1y 2025-08-08 +[2025-09-23T14:32:24.133] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-23T15:20:22.803] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false command received from platform +[2025-09-23T15:22:25.869] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false command received from platform +[2025-09-23T19:09:00.222] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-23T19:09:00.525] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-23T19:09:00.828] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-24T03:32:19.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-24 03:32:19 +[2025-09-24T06:19:00.221] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-24T06:19:00.524] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-24T06:19:00.827] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-24T19:07:04.359] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-24T19:07:04.666] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-24T19:07:04.969] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-25T03:32:21.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-25 03:32:21 +[2025-09-25T06:22:46.856] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-25T06:22:47.159] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-25T06:22:47.462] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-25T16:31:45.909] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-09-25T16:31:51.241] [INFO] monitorLogs - buildTasks - params undefined +[2025-09-25T16:31:51.246] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-09-25T16:31:51.247] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-09-25T16:31:51.248] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-09-25T16:31:51.252] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-25T16:31:51.254] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 1 2025-09-26T04:22:00.253Z +[2025-09-25T16:31:51.255] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 1 2025-09-25T17:04:00.255Z +[2025-09-25T16:31:51.256] [INFO] monitorLogs - -->time_points final 1 [ + { start_time: '06:22', value: 0, name: 'dawn' }, + { start_time: '19:04', value: 1, name: 'dusk' } +] +[2025-09-25T16:31:51.257] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-09-25T16:31:51.258] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-09-25T16:31:51.258] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-09-25T16:31:51.261] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-25T16:31:51.262] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 2 2025-09-26T04:22:00.261Z +[2025-09-25T16:31:51.262] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 2 2025-09-25T17:04:00.262Z +[2025-09-25T16:31:51.263] [INFO] monitorLogs - -->time_points final 2 [ + { start_time: '06:22', value: 0, name: 'dawn' }, + { start_time: '19:04', value: 1, name: 'dusk' } +] +[2025-09-25T16:31:51.264] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-09-25T16:31:51.265] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-09-25T16:31:51.265] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-09-25T16:31:51.268] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-25T16:31:51.268] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 3 2025-09-26T04:22:00.268Z +[2025-09-25T16:31:51.269] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 3 2025-09-25T17:04:00.269Z +[2025-09-25T16:31:51.270] [INFO] monitorLogs - -->time_points final 3 [ + { start_time: '06:22', value: 0, name: 'dawn' }, + { start_time: '19:04', value: 1, name: 'dusk' } +] +[2025-09-25T16:31:51.271] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-09-25T16:31:51.272] [INFO] monitorLogs - tasks created: 14 +[2025-09-25T16:31:51.274] [INFO] monitorLogs - -->FLOW bol spustený dz4ojlpP85JMgDLZWkQJ4D7aKYqQexEr62GXRV1y 2025-08-08 +[2025-09-25T16:31:56.276] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-25T19:04:00.373] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-25T19:04:00.680] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-25T19:04:00.983] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-26T03:31:52.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-26 03:31:52 +[2025-09-26T06:22:00.493] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-26T06:22:00.797] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-26T06:22:01.099] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-26T19:02:48.384] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-26T19:02:48.687] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-26T19:02:48.989] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-27T03:31:53.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-27 03:31:53 +[2025-09-27T06:25:36.993] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-27T06:25:37.296] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-27T06:25:37.599] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-27T19:00:40.868] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-27T19:00:41.171] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-27T19:00:41.473] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-28T03:31:54.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-28 03:31:54 +[2025-09-28T06:27:02.264] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-28T06:27:02.567] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-28T06:27:02.868] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-28T18:58:33.430] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-28T18:58:33.732] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-28T18:58:34.034] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-29T03:31:56.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-29 03:31:56 +[2025-09-29T06:28:28.122] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-29T06:28:28.425] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-29T06:28:28.728] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-29T18:56:26.220] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-29T18:56:26.522] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-29T18:56:26.824] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-30T03:31:57.015] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-30 03:31:57 +[2025-09-30T06:29:53.762] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-30T06:29:54.065] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-30T06:29:54.367] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-30T18:54:19.357] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-30T18:54:19.660] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-30T18:54:19.962] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-01T03:31:58.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-01 03:31:58 +[2025-10-01T06:31:19.856] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-10-01T06:31:20.158] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-10-01T06:31:20.460] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-01T18:52:12.887] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-01T18:52:13.194] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-10-01T18:52:13.497] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-10-02T03:31:59.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-02 03:31:59 +[2025-10-02T06:32:46.292] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-02T06:32:46.595] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-10-02T06:32:46.897] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-10-02T18:50:06.656] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-10-02T18:50:06.962] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-10-02T18:50:07.265] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-03T03:32:00.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-03 03:32:00 +[2025-10-03T06:34:13.090] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-10-03T06:34:13.393] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-10-03T06:34:13.696] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-03T14:47:29.510] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-03T14:47:34.852] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-03T14:47:34.857] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-03T14:47:34.859] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-03T14:47:34.859] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-10-03T14:47:34.863] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-03T14:47:34.865] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 1 2025-10-04T04:34:00.864Z +[2025-10-03T14:47:34.866] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 1 2025-10-03T16:48:00.866Z +[2025-10-03T14:47:34.867] [INFO] monitorLogs - -->time_points final 1 [ + { start_time: '06:34', value: 0, name: 'dawn' }, + { start_time: '18:48', value: 1, name: 'dusk' } +] +[2025-10-03T14:47:34.868] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-10-03T14:47:34.869] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-03T14:47:34.869] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-10-03T14:47:34.872] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-03T14:47:34.872] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 2 2025-10-04T04:34:00.872Z +[2025-10-03T14:47:34.873] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 2 2025-10-03T16:48:00.873Z +[2025-10-03T14:47:34.874] [INFO] monitorLogs - -->time_points final 2 [ + { start_time: '06:34', value: 0, name: 'dawn' }, + { start_time: '18:48', value: 1, name: 'dusk' } +] +[2025-10-03T14:47:34.875] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-10-03T14:47:34.876] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-03T14:47:34.876] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-10-03T14:47:34.879] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-03T14:47:34.879] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 3 2025-10-04T04:34:00.879Z +[2025-10-03T14:47:34.880] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 3 2025-10-03T16:48:00.880Z +[2025-10-03T14:47:34.881] [INFO] monitorLogs - -->time_points final 3 [ + { start_time: '06:34', value: 0, name: 'dawn' }, + { start_time: '18:48', value: 1, name: 'dusk' } +] +[2025-10-03T14:47:34.882] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-10-03T14:47:34.883] [INFO] monitorLogs - tasks created: 14 +[2025-10-03T14:47:34.885] [INFO] monitorLogs - -->FLOW bol spustený dz4ojlpP85JMgDLZWkQJ4D7aKYqQexEr62GXRV1y 2025-08-08 +[2025-10-03T14:47:39.886] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-03T18:48:01.063] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-03T18:48:01.371] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-10-03T18:48:01.674] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-10-04T03:47:36.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-04 03:47:36 +[2025-10-04T06:34:00.935] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-04T06:34:01.238] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-10-04T06:34:01.540] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-10-04T18:45:55.669] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-10-04T18:45:55.971] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-10-04T18:45:56.273] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-05T03:47:37.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-05 03:47:37 +[2025-10-05T06:37:07.255] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-10-05T06:37:07.557] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-10-05T06:37:07.860] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-05T18:43:50.642] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-05T18:43:50.944] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-10-05T18:43:51.247] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-10-06T03:47:38.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-06 03:47:38 +[2025-10-06T06:38:34.533] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-06T06:38:34.835] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-10-06T06:38:35.137] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-10-06T18:41:46.475] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-10-06T18:41:46.777] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-10-06T18:41:47.079] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-07T03:47:39.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-07 03:47:39 +[2025-10-07T06:40:02.634] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-10-07T06:40:02.936] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-10-07T06:40:03.238] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-07T18:39:42.834] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-07T18:39:43.137] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-10-07T18:39:43.439] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-10-08T03:47:40.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-08 03:47:40 +[2025-10-08T06:41:30.610] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-08T06:41:30.913] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-10-08T06:41:31.214] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-10-08T18:37:39.426] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-10-08T18:37:39.728] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-10-08T18:37:40.029] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-09T03:47:41.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-09 03:47:41 +[2025-10-09T06:42:59.257] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-10-09T06:42:59.560] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-10-09T06:42:59.862] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-09T16:52:37.667] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-09T16:52:43.001] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-09T16:52:43.006] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-09T16:52:43.008] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-09T16:52:43.008] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-10-09T16:52:43.012] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T16:52:43.014] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 1 2025-10-10T04:42:00.013Z +[2025-10-09T16:52:43.015] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 1 2025-10-09T16:35:00.015Z +[2025-10-09T16:52:43.016] [INFO] monitorLogs - -->time_points final 1 [ + { start_time: '06:42', value: 0, name: 'dawn' }, + { start_time: '18:35', value: 1, name: 'dusk' } +] +[2025-10-09T16:52:43.017] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-10-09T16:52:43.018] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-09T16:52:43.018] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-10-09T16:52:43.021] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T16:52:43.021] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 2 2025-10-10T04:42:00.021Z +[2025-10-09T16:52:43.022] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 2 2025-10-09T16:35:00.022Z +[2025-10-09T16:52:43.023] [INFO] monitorLogs - -->time_points final 2 [ + { start_time: '06:42', value: 0, name: 'dawn' }, + { start_time: '18:35', value: 1, name: 'dusk' } +] +[2025-10-09T16:52:43.024] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-10-09T16:52:43.025] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-09T16:52:43.025] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-10-09T16:52:43.028] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T16:52:43.028] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 3 2025-10-10T04:42:00.028Z +[2025-10-09T16:52:43.029] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 3 2025-10-09T16:35:00.029Z +[2025-10-09T16:52:43.030] [INFO] monitorLogs - -->time_points final 3 [ + { start_time: '06:42', value: 0, name: 'dawn' }, + { start_time: '18:35', value: 1, name: 'dusk' } +] +[2025-10-09T16:52:43.031] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-10-09T16:52:43.032] [INFO] monitorLogs - tasks created: 14 +[2025-10-09T16:52:43.034] [INFO] monitorLogs - -->FLOW bol spustený dz4ojlpP85JMgDLZWkQJ4D7aKYqQexEr62GXRV1y 2025-08-08 +[2025-10-09T16:52:48.036] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-09T18:35:00.097] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-09T18:35:00.400] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-10-09T18:35:00.703] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-10-09T19:05:10.316] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-09T19:05:15.656] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-09T19:05:15.661] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-09T19:05:15.662] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-09T19:05:15.663] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-10-09T19:05:15.667] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T19:05:15.668] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 1 2025-10-10T04:42:00.668Z +[2025-10-09T19:05:15.670] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 1 2025-10-10T16:35:00.670Z +[2025-10-09T19:05:15.671] [INFO] monitorLogs - -->time_points final 1 [ + { start_time: '06:42', value: 0, name: 'dawn' }, + { start_time: '18:35', value: 1, name: 'dusk' } +] +[2025-10-09T19:05:15.672] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-10-09T19:05:15.673] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-09T19:05:15.673] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-10-09T19:05:15.676] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T19:05:15.677] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 2 2025-10-10T04:42:00.677Z +[2025-10-09T19:05:15.678] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 2 2025-10-10T16:35:00.677Z +[2025-10-09T19:05:15.678] [INFO] monitorLogs - -->time_points final 2 [ + { start_time: '06:42', value: 0, name: 'dawn' }, + { start_time: '18:35', value: 1, name: 'dusk' } +] +[2025-10-09T19:05:15.679] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-10-09T19:05:15.680] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-09T19:05:15.681] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-10-09T19:05:15.683] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T19:05:15.684] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 3 2025-10-10T04:42:00.683Z +[2025-10-09T19:05:15.684] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 3 2025-10-10T16:35:00.684Z +[2025-10-09T19:05:15.685] [INFO] monitorLogs - -->time_points final 3 [ + { start_time: '06:42', value: 0, name: 'dawn' }, + { start_time: '18:35', value: 1, name: 'dusk' } +] +[2025-10-09T19:05:15.686] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-10-09T19:05:15.687] [INFO] monitorLogs - tasks created: 14 +[2025-10-09T19:05:15.690] [INFO] monitorLogs - -->FLOW bol spustený dz4ojlpP85JMgDLZWkQJ4D7aKYqQexEr62GXRV1y 2025-08-08 +[2025-10-09T19:05:20.692] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-10T03:05:17.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-10 03:05:17 +[2025-10-10T06:42:00.746] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-10T06:42:01.050] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-10-10T06:42:01.353] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-10-10T18:35:00.749] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-10T18:35:01.052] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-10-10T18:35:01.354] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-10-11T03:05:18.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-11 03:05:18 +[2025-10-11T06:45:57.284] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-10-11T06:45:57.587] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-10-11T06:45:57.889] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-11T18:31:33.863] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-10-11T18:31:34.166] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-10-11T18:31:34.468] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-12T03:05:19.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-12 03:05:19 +[2025-10-12T06:47:26.655] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-12T06:47:26.957] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-10-12T06:47:27.259] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-10-12T18:29:33.431] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-12T18:29:33.733] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-10-12T18:29:34.035] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-10-13T03:05:20.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-13 03:05:20 +[2025-10-13T06:48:56.602] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-10-13T06:48:56.906] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-10-13T06:48:57.209] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-13T18:27:33.915] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-10-13T18:27:34.218] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-10-13T18:27:34.520] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-14T03:05:21.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-14 03:05:21 +[2025-10-14T06:50:26.862] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-14T06:50:27.163] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-10-14T06:50:27.465] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-10-14T18:25:34.923] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-14T18:25:35.225] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-10-14T18:25:35.527] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-10-15T03:05:22.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-15 03:05:22 +[2025-10-15T06:51:57.594] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-10-15T06:51:57.897] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-10-15T06:51:58.199] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-15T11:33:58.124] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-15T11:34:03.467] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-15T11:34:03.472] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-15T11:34:03.473] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-15T11:34:03.474] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-10-15T11:34:03.478] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-15T11:34:03.479] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 1 2025-10-16T04:51:00.478Z +[2025-10-15T11:34:03.480] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 1 2025-10-15T16:23:00.480Z +[2025-10-15T11:34:03.481] [INFO] monitorLogs - -->time_points final 1 [ + { start_time: '06:51', value: 0, name: 'dawn' }, + { start_time: '18:23', value: 1, name: 'dusk' } +] +[2025-10-15T11:34:03.482] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-10-15T11:34:03.483] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-15T11:34:03.484] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-10-15T11:34:03.486] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-15T11:34:03.487] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 2 2025-10-16T04:51:00.487Z +[2025-10-15T11:34:03.488] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 2 2025-10-15T16:23:00.488Z +[2025-10-15T11:34:03.489] [INFO] monitorLogs - -->time_points final 2 [ + { start_time: '06:51', value: 0, name: 'dawn' }, + { start_time: '18:23', value: 1, name: 'dusk' } +] +[2025-10-15T11:34:03.490] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-10-15T11:34:03.490] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-15T11:34:03.491] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-10-15T11:34:03.493] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-15T11:34:03.494] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 3 2025-10-16T04:51:00.494Z +[2025-10-15T11:34:03.495] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 3 2025-10-15T16:23:00.494Z +[2025-10-15T11:34:03.495] [INFO] monitorLogs - -->time_points final 3 [ + { start_time: '06:51', value: 0, name: 'dawn' }, + { start_time: '18:23', value: 1, name: 'dusk' } +] +[2025-10-15T11:34:03.496] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-10-15T11:34:03.497] [INFO] monitorLogs - tasks created: 14 +[2025-10-15T11:34:03.500] [INFO] monitorLogs - -->FLOW bol spustený dz4ojlpP85JMgDLZWkQJ4D7aKYqQexEr62GXRV1y 2025-10-08 +[2025-10-15T11:34:08.502] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-15T18:23:00.531] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-15T18:23:00.839] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-10-15T18:23:01.144] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu diff --git a/RVO3/package-lock.json b/RVO3/package-lock.json new file mode 100755 index 0000000..3c5c1ba --- /dev/null +++ b/RVO3/package-lock.json @@ -0,0 +1,2139 @@ +{ + "name": "emptyproject", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "emptyproject", + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "bitwise": "^2.1.0", + "easy-crc": "0.0.2", + "jsmodbus": "^4.0.6", + "log4js": "^6.3.0", + "moment": "^2.30.1", + "mqtt": "^4.2.6", + "nodemailer": "^6.9.7", + "serialport": "^9.2.8", + "total.js": "^3.4.13" + } + }, + "node_modules/@serialport/binding-abstract": { + "version": "9.2.3", + "resolved": "https://registry.npmjs.org/@serialport/binding-abstract/-/binding-abstract-9.2.3.tgz", + "integrity": "sha512-cQs9tbIlG3P0IrOWyVirqlhWuJ7Ms2Zh9m2108z6Y5UW/iVj6wEOiW8EmK9QX9jmJXYllE7wgGgvVozP5oCj3w==", + "dependencies": { + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/binding-mock": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/binding-mock/-/binding-mock-9.2.4.tgz", + "integrity": "sha512-dpEhACCs44oQhh6ajJfJdvQdK38Vq0N4W6iD/gdplglDCK7qXRQCMUjJIeKdS/HSEiWkC3bwumUhUufdsOyT4g==", + "dependencies": { + "@serialport/binding-abstract": "9.2.3", + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/bindings": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/@serialport/bindings/-/bindings-9.2.8.tgz", + "integrity": "sha512-hSLxTe0tADZ3LMMGwvEJWOC/TaFQTyPeFalUCsJ1lSQ0k6bPF04JwrtB/C81GetmDBTNRY0GlD0SNtKCc7Dr5g==", + "hasInstallScript": true, + "dependencies": { + "@serialport/binding-abstract": "9.2.3", + "@serialport/parser-readline": "9.2.4", + "bindings": "^1.5.0", + "debug": "^4.3.2", + "nan": "^2.15.0", + "prebuild-install": "^7.0.0" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-byte-length": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-byte-length/-/parser-byte-length-9.2.4.tgz", + "integrity": "sha512-sQD/iw4ZMU3xW9PLi0/GlvU6Y623jGeWecbMkO7izUo/6P7gtfv1c9ikd5h0kwL8AoAOpQA1lxdHIKox+umBUg==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-cctalk": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-cctalk/-/parser-cctalk-9.2.4.tgz", + "integrity": "sha512-T4TU5vQMwmo9AB3gQLFDWbfJXlW5jd9guEsB/nqKjFHTv0FXPdZ7DQ2TpSp8RnHWxU3GX6kYTaDO20BKzc8GPQ==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-delimiter": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-delimiter/-/parser-delimiter-9.2.4.tgz", + "integrity": "sha512-4nvTAoYAgkxFiXrkI+3CA49Yd43CODjeszh89EK+I9c8wOZ+etZduRCzINYPiy26g7zO+GRAb9FoPCsY+sYcbQ==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-inter-byte-timeout": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-inter-byte-timeout/-/parser-inter-byte-timeout-9.2.4.tgz", + "integrity": "sha512-SOAdvr0oBQIOCXX198hiTlxs4JTKg9j5piapw5tNq52fwDOWdbYrFneT/wN04UTMKaDrJuEvXq6T4rv4j7nJ5A==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-readline": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-readline/-/parser-readline-9.2.4.tgz", + "integrity": "sha512-Z1/qrZTQUVhNSJP1hd9YfDvq0o7d87rNwAjjRKbVpa7Qi51tG5BnKt43IV3NFMyBlVcRe0rnIb3tJu57E0SOwg==", + "dependencies": { + "@serialport/parser-delimiter": "9.2.4" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-ready": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-ready/-/parser-ready-9.2.4.tgz", + "integrity": "sha512-Pyi94Itjl6qAURwIZr/gmZpMAyTmKXThm6vL5DoAWGQjcRHWB0gwv2TY2v7N+mQLJYUKU3cMnvnATXxHm7xjxw==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-regex": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-regex/-/parser-regex-9.2.4.tgz", + "integrity": "sha512-sI/cVvPOYz+Dbv4ZdnW16qAwvXiFf/1pGASQdbveRTlgJDdz7sRNlCBifzfTN2xljwvCTZYqiudKvDdC1TepRQ==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/stream": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/stream/-/stream-9.2.4.tgz", + "integrity": "sha512-bLye8Ub4vUFQGmkh8qEqehr7SE7EJs2yDs0h9jzuL5oKi+F34CFmWkEErO8GAOQ8YNn7p6b3GxUgs+0BrHHDZQ==", + "dependencies": { + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "node_modules/are-we-there-yet": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", + "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/base64-js": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", + "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==" + }, + "node_modules/bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "dependencies": { + "file-uri-to-path": "1.0.0" + } + }, + "node_modules/bitwise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/bitwise/-/bitwise-2.1.0.tgz", + "integrity": "sha512-XKgAhMXCh4H/3oNwAHAsAO0iC89s9cOiumgYwSHjSobGWxYjv62YhkL9QEdvGP151xypCtMlAfKK79GEcd2eRQ==" + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/bl/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/buffer": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz", + "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==", + "dependencies": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + }, + "node_modules/buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" + }, + "node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, + "node_modules/code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/commist": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/commist/-/commist-1.1.0.tgz", + "integrity": "sha512-rraC8NXWOEjhADbZe9QBNzLAN5Q3fsTPQtBV+fEVj6xKIgDgNiEVE6ZNfHpZOqfQ21YUzfVNUXLOEZquYvQPPg==", + "dependencies": { + "leven": "^2.1.0", + "minimist": "^1.1.0" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "node_modules/concat-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", + "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", + "engines": [ + "node >= 6.0" + ], + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.0.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/concat-stream/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" + }, + "node_modules/core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "node_modules/crc": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/crc/-/crc-3.4.0.tgz", + "integrity": "sha512-ycVC2+4/DLgXXq7QweYi2znhqDuZz6P5TQXnkQo8v15XY/5p/IWeZwsSE31Ifo8w15b8TWLsqhXOjXyilHuQxw==" + }, + "node_modules/date-format": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.11.tgz", + "integrity": "sha512-VS20KRyorrbMCQmpdl2hg5KaOUsda1RbnsJg461FfrcyCUg+pkd0b40BSW4niQyTheww4DBXQnS7HwSrKkipLw==", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" + }, + "node_modules/detect-libc": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz", + "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==", + "engines": { + "node": ">=8" + } + }, + "node_modules/duplexify": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.2.tgz", + "integrity": "sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw==", + "dependencies": { + "end-of-stream": "^1.4.1", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1", + "stream-shift": "^1.0.0" + } + }, + "node_modules/duplexify/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/easy-crc": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/easy-crc/-/easy-crc-0.0.2.tgz", + "integrity": "sha512-h6eqIdhJRe0p271/xZJbM/0klCi13mW5IB7ZEzEGH11yV4QXWAkD4yPErz0fXdhFrd6sZ4Q1k5Iky2kMsMNePw==" + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" + }, + "node_modules/flatted": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", + "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==" + }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, + "node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "node_modules/gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha512-14x4kjc6lkD3ltw589k0NrPD6cCNTD6CWoVUNpB85+DrtONoZn+Rug6xZU5RvSC4+TZPxA5AnBibQYAvZn41Hg==", + "dependencies": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "node_modules/github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==" + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" + }, + "node_modules/has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" + }, + "node_modules/help-me": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/help-me/-/help-me-3.0.0.tgz", + "integrity": "sha512-hx73jClhyk910sidBB7ERlnhMlFsJJIBqSVMFDwPN8o2v9nmp5KgLq1Xz1Bf1fCMMZ6mPrX159iG0VLy/fPMtQ==", + "dependencies": { + "glob": "^7.1.6", + "readable-stream": "^3.6.0" + } + }, + "node_modules/help-me/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, + "node_modules/is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==", + "dependencies": { + "number-is-nan": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "node_modules/js-sdsl": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz", + "integrity": "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/js-sdsl" + } + }, + "node_modules/jsmodbus": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/jsmodbus/-/jsmodbus-4.0.6.tgz", + "integrity": "sha512-gCmjoaERErK5Rn9Lu/BN07fY13MoWV7JKgGzrnkPlQPdPxYcwDhLtYcmpFFpZ4J9NPZZBSezi1UkLZO/DnNppA==", + "dependencies": { + "crc": "3.4.0", + "debug": "^3.1.0" + }, + "bin": { + "jsmodbus": "bin/jsmodbus.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/jsmodbus/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/leven": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", + "integrity": "sha1-wuep93IJTe6dNCAq6KzORoeHVYA=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/log4js": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.5.2.tgz", + "integrity": "sha512-DXtpNtt+KDOMT7RHUDIur/WsSA3rntlUh9Zg4XCdV42wUuMmbFkl38+LZ92Z5QvQA7mD5kAVkLiBSEH/tvUB8A==", + "dependencies": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "flatted": "^3.2.5", + "rfdc": "^1.3.0", + "streamroller": "^3.1.1" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" + }, + "node_modules/moment": { + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", + "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==", + "engines": { + "node": "*" + } + }, + "node_modules/mqtt": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/mqtt/-/mqtt-4.3.7.tgz", + "integrity": "sha512-ew3qwG/TJRorTz47eW46vZ5oBw5MEYbQZVaEji44j5lAUSQSqIEoul7Kua/BatBW0H0kKQcC9kwUHa1qzaWHSw==", + "dependencies": { + "commist": "^1.0.0", + "concat-stream": "^2.0.0", + "debug": "^4.1.1", + "duplexify": "^4.1.1", + "help-me": "^3.0.0", + "inherits": "^2.0.3", + "lru-cache": "^6.0.0", + "minimist": "^1.2.5", + "mqtt-packet": "^6.8.0", + "number-allocator": "^1.0.9", + "pump": "^3.0.0", + "readable-stream": "^3.6.0", + "reinterval": "^1.1.0", + "rfdc": "^1.3.0", + "split2": "^3.1.0", + "ws": "^7.5.5", + "xtend": "^4.0.2" + }, + "bin": { + "mqtt": "bin/mqtt.js", + "mqtt_pub": "bin/pub.js", + "mqtt_sub": "bin/sub.js" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/mqtt-packet": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/mqtt-packet/-/mqtt-packet-6.10.0.tgz", + "integrity": "sha512-ja8+mFKIHdB1Tpl6vac+sktqy3gA8t9Mduom1BA75cI+R9AHnZOiaBQwpGiWnaVJLDGRdNhQmFaAqd7tkKSMGA==", + "dependencies": { + "bl": "^4.0.2", + "debug": "^4.1.1", + "process-nextick-args": "^2.0.1" + } + }, + "node_modules/mqtt/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/nan": { + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.16.0.tgz", + "integrity": "sha512-UdAqHyFngu7TfQKsCBgAA6pWDkT8MAO7d0jyOecVhN5354xbLqdn8mV9Tat9gepAupm0bt2DbeaSC8vS52MuFA==" + }, + "node_modules/napi-build-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", + "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==" + }, + "node_modules/node-abi": { + "version": "3.22.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.22.0.tgz", + "integrity": "sha512-u4uAs/4Zzmp/jjsD9cyFYDXeISfUWaAVWshPmDZOFOv4Xl4SbzTXm53I04C2uRueYJ+0t5PEtLH/owbn2Npf/w==", + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/nodemailer": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.7.tgz", + "integrity": "sha512-rUtR77ksqex/eZRLmQ21LKVH5nAAsVicAtAYudK7JgwenEDZ0UIQ1adUGqErz7sMkWYxWTTU1aeP2Jga6WQyJw==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "dependencies": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "node_modules/number-allocator": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/number-allocator/-/number-allocator-1.0.14.tgz", + "integrity": "sha512-OrL44UTVAvkKdOdRQZIJpLkAdjXGTRda052sN4sO77bKEzYYqWKMBjQvrJFzqygI99gL6Z4u2xctPW1tB8ErvA==", + "dependencies": { + "debug": "^4.3.1", + "js-sdsl": "4.3.0" + } + }, + "node_modules/number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/prebuild-install": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.0.tgz", + "integrity": "sha512-CNcMgI1xBypOyGqjp3wOc8AAo1nMhZS3Cwd3iHIxOdAUbb+YxdNuM4Z5iIrZ8RLvOsf3F3bl7b7xGq6DjQoNYA==", + "dependencies": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^1.0.1", + "node-abi": "^3.3.0", + "npmlog": "^4.0.1", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + }, + "bin": { + "prebuild-install": "bin.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/reinterval": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reinterval/-/reinterval-1.1.0.tgz", + "integrity": "sha1-M2Hs+jymwYKDOA3Qu5VG85D17Oc=" + }, + "node_modules/rfdc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==" + }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/serialport": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/serialport/-/serialport-9.2.8.tgz", + "integrity": "sha512-FsWpMQgSJxi93JgWl5xM1f9/Z8IjRJuaUEoHqLf8FPBLw7gMhInuHOBhI2onQufWIYPGTz3H3oGcu1nCaK1EfA==", + "dependencies": { + "@serialport/binding-mock": "9.2.4", + "@serialport/bindings": "9.2.8", + "@serialport/parser-byte-length": "9.2.4", + "@serialport/parser-cctalk": "9.2.4", + "@serialport/parser-delimiter": "9.2.4", + "@serialport/parser-inter-byte-timeout": "9.2.4", + "@serialport/parser-readline": "9.2.4", + "@serialport/parser-ready": "9.2.4", + "@serialport/parser-regex": "9.2.4", + "@serialport/stream": "9.2.4", + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "node_modules/split2": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", + "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", + "dependencies": { + "readable-stream": "^3.0.0" + } + }, + "node_modules/split2/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==" + }, + "node_modules/streamroller": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.1.1.tgz", + "integrity": "sha512-iPhtd9unZ6zKdWgMeYGfSBuqCngyJy1B/GPi/lTpwGpa3bajuX30GjUVd0/Tn/Xhg0mr4DOSENozz9Y06qyonQ==", + "dependencies": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "fs-extra": "^10.1.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dependencies": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/tar-fs": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "dependencies": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tar-stream/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/total.js": { + "version": "3.4.13", + "resolved": "https://registry.npmjs.org/total.js/-/total.js-3.4.13.tgz", + "integrity": "sha512-lAH4gEixlPFbrE3xfKADAcHfO79IFq2wKa9GTsrgRzIR5MTg3mNH7+4IxvX1pK8faoYb/0oYSJ1YTsAa5hIFFQ==", + "bin": { + "total": "bin/totaljs", + "total.js": "bin/totaljs", + "totaljs": "bin/totaljs", + "totalpackage": "bin/tpm", + "tpm": "bin/tpm" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, + "node_modules/universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "node_modules/wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "node_modules/ws": { + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } + }, + "dependencies": { + "@serialport/binding-abstract": { + "version": "9.2.3", + "resolved": "https://registry.npmjs.org/@serialport/binding-abstract/-/binding-abstract-9.2.3.tgz", + "integrity": "sha512-cQs9tbIlG3P0IrOWyVirqlhWuJ7Ms2Zh9m2108z6Y5UW/iVj6wEOiW8EmK9QX9jmJXYllE7wgGgvVozP5oCj3w==", + "requires": { + "debug": "^4.3.2" + } + }, + "@serialport/binding-mock": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/binding-mock/-/binding-mock-9.2.4.tgz", + "integrity": "sha512-dpEhACCs44oQhh6ajJfJdvQdK38Vq0N4W6iD/gdplglDCK7qXRQCMUjJIeKdS/HSEiWkC3bwumUhUufdsOyT4g==", + "requires": { + "@serialport/binding-abstract": "9.2.3", + "debug": "^4.3.2" + } + }, + "@serialport/bindings": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/@serialport/bindings/-/bindings-9.2.8.tgz", + "integrity": "sha512-hSLxTe0tADZ3LMMGwvEJWOC/TaFQTyPeFalUCsJ1lSQ0k6bPF04JwrtB/C81GetmDBTNRY0GlD0SNtKCc7Dr5g==", + "requires": { + "@serialport/binding-abstract": "9.2.3", + "@serialport/parser-readline": "9.2.4", + "bindings": "^1.5.0", + "debug": "^4.3.2", + "nan": "^2.15.0", + "prebuild-install": "^7.0.0" + } + }, + "@serialport/parser-byte-length": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-byte-length/-/parser-byte-length-9.2.4.tgz", + "integrity": "sha512-sQD/iw4ZMU3xW9PLi0/GlvU6Y623jGeWecbMkO7izUo/6P7gtfv1c9ikd5h0kwL8AoAOpQA1lxdHIKox+umBUg==" + }, + "@serialport/parser-cctalk": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-cctalk/-/parser-cctalk-9.2.4.tgz", + "integrity": "sha512-T4TU5vQMwmo9AB3gQLFDWbfJXlW5jd9guEsB/nqKjFHTv0FXPdZ7DQ2TpSp8RnHWxU3GX6kYTaDO20BKzc8GPQ==" + }, + "@serialport/parser-delimiter": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-delimiter/-/parser-delimiter-9.2.4.tgz", + "integrity": "sha512-4nvTAoYAgkxFiXrkI+3CA49Yd43CODjeszh89EK+I9c8wOZ+etZduRCzINYPiy26g7zO+GRAb9FoPCsY+sYcbQ==" + }, + "@serialport/parser-inter-byte-timeout": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-inter-byte-timeout/-/parser-inter-byte-timeout-9.2.4.tgz", + "integrity": "sha512-SOAdvr0oBQIOCXX198hiTlxs4JTKg9j5piapw5tNq52fwDOWdbYrFneT/wN04UTMKaDrJuEvXq6T4rv4j7nJ5A==" + }, + "@serialport/parser-readline": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-readline/-/parser-readline-9.2.4.tgz", + "integrity": "sha512-Z1/qrZTQUVhNSJP1hd9YfDvq0o7d87rNwAjjRKbVpa7Qi51tG5BnKt43IV3NFMyBlVcRe0rnIb3tJu57E0SOwg==", + "requires": { + "@serialport/parser-delimiter": "9.2.4" + } + }, + "@serialport/parser-ready": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-ready/-/parser-ready-9.2.4.tgz", + "integrity": "sha512-Pyi94Itjl6qAURwIZr/gmZpMAyTmKXThm6vL5DoAWGQjcRHWB0gwv2TY2v7N+mQLJYUKU3cMnvnATXxHm7xjxw==" + }, + "@serialport/parser-regex": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-regex/-/parser-regex-9.2.4.tgz", + "integrity": "sha512-sI/cVvPOYz+Dbv4ZdnW16qAwvXiFf/1pGASQdbveRTlgJDdz7sRNlCBifzfTN2xljwvCTZYqiudKvDdC1TepRQ==" + }, + "@serialport/stream": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/stream/-/stream-9.2.4.tgz", + "integrity": "sha512-bLye8Ub4vUFQGmkh8qEqehr7SE7EJs2yDs0h9jzuL5oKi+F34CFmWkEErO8GAOQ8YNn7p6b3GxUgs+0BrHHDZQ==", + "requires": { + "debug": "^4.3.2" + } + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==" + }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "are-we-there-yet": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", + "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "base64-js": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", + "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==" + }, + "bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "requires": { + "file-uri-to-path": "1.0.0" + } + }, + "bitwise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/bitwise/-/bitwise-2.1.0.tgz", + "integrity": "sha512-XKgAhMXCh4H/3oNwAHAsAO0iC89s9cOiumgYwSHjSobGWxYjv62YhkL9QEdvGP151xypCtMlAfKK79GEcd2eRQ==" + }, + "bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "requires": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "buffer": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz", + "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==", + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" + }, + "chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==" + }, + "commist": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/commist/-/commist-1.1.0.tgz", + "integrity": "sha512-rraC8NXWOEjhADbZe9QBNzLAN5Q3fsTPQtBV+fEVj6xKIgDgNiEVE6ZNfHpZOqfQ21YUzfVNUXLOEZquYvQPPg==", + "requires": { + "leven": "^2.1.0", + "minimist": "^1.1.0" + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "concat-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", + "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.0.2", + "typedarray": "^0.0.6" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "crc": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/crc/-/crc-3.4.0.tgz", + "integrity": "sha512-ycVC2+4/DLgXXq7QweYi2znhqDuZz6P5TQXnkQo8v15XY/5p/IWeZwsSE31Ifo8w15b8TWLsqhXOjXyilHuQxw==" + }, + "date-format": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.11.tgz", + "integrity": "sha512-VS20KRyorrbMCQmpdl2hg5KaOUsda1RbnsJg461FfrcyCUg+pkd0b40BSW4niQyTheww4DBXQnS7HwSrKkipLw==" + }, + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "requires": { + "ms": "2.1.2" + } + }, + "decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "requires": { + "mimic-response": "^3.1.0" + } + }, + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==" + }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" + }, + "detect-libc": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz", + "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==" + }, + "duplexify": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.2.tgz", + "integrity": "sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw==", + "requires": { + "end-of-stream": "^1.4.1", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1", + "stream-shift": "^1.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "easy-crc": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/easy-crc/-/easy-crc-0.0.2.tgz", + "integrity": "sha512-h6eqIdhJRe0p271/xZJbM/0klCi13mW5IB7ZEzEGH11yV4QXWAkD4yPErz0fXdhFrd6sZ4Q1k5Iky2kMsMNePw==" + }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "requires": { + "once": "^1.4.0" + } + }, + "expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==" + }, + "file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" + }, + "flatted": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", + "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==" + }, + "fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, + "fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha512-14x4kjc6lkD3ltw589k0NrPD6cCNTD6CWoVUNpB85+DrtONoZn+Rug6xZU5RvSC4+TZPxA5AnBibQYAvZn41Hg==", + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==" + }, + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" + }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" + }, + "help-me": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/help-me/-/help-me-3.0.0.tgz", + "integrity": "sha512-hx73jClhyk910sidBB7ERlnhMlFsJJIBqSVMFDwPN8o2v9nmp5KgLq1Xz1Bf1fCMMZ6mPrX159iG0VLy/fPMtQ==", + "requires": { + "glob": "^7.1.6", + "readable-stream": "^3.6.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==", + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "js-sdsl": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz", + "integrity": "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==" + }, + "jsmodbus": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/jsmodbus/-/jsmodbus-4.0.6.tgz", + "integrity": "sha512-gCmjoaERErK5Rn9Lu/BN07fY13MoWV7JKgGzrnkPlQPdPxYcwDhLtYcmpFFpZ4J9NPZZBSezi1UkLZO/DnNppA==", + "requires": { + "crc": "3.4.0", + "debug": "^3.1.0" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "requires": { + "ms": "^2.1.1" + } + } + } + }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, + "leven": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", + "integrity": "sha1-wuep93IJTe6dNCAq6KzORoeHVYA=" + }, + "log4js": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.5.2.tgz", + "integrity": "sha512-DXtpNtt+KDOMT7RHUDIur/WsSA3rntlUh9Zg4XCdV42wUuMmbFkl38+LZ92Z5QvQA7mD5kAVkLiBSEH/tvUB8A==", + "requires": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "flatted": "^3.2.5", + "rfdc": "^1.3.0", + "streamroller": "^3.1.1" + } + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "requires": { + "yallist": "^4.0.0" + } + }, + "mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==" + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==" + }, + "mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" + }, + "moment": { + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", + "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==" + }, + "mqtt": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/mqtt/-/mqtt-4.3.7.tgz", + "integrity": "sha512-ew3qwG/TJRorTz47eW46vZ5oBw5MEYbQZVaEji44j5lAUSQSqIEoul7Kua/BatBW0H0kKQcC9kwUHa1qzaWHSw==", + "requires": { + "commist": "^1.0.0", + "concat-stream": "^2.0.0", + "debug": "^4.1.1", + "duplexify": "^4.1.1", + "help-me": "^3.0.0", + "inherits": "^2.0.3", + "lru-cache": "^6.0.0", + "minimist": "^1.2.5", + "mqtt-packet": "^6.8.0", + "number-allocator": "^1.0.9", + "pump": "^3.0.0", + "readable-stream": "^3.6.0", + "reinterval": "^1.1.0", + "rfdc": "^1.3.0", + "split2": "^3.1.0", + "ws": "^7.5.5", + "xtend": "^4.0.2" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "mqtt-packet": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/mqtt-packet/-/mqtt-packet-6.10.0.tgz", + "integrity": "sha512-ja8+mFKIHdB1Tpl6vac+sktqy3gA8t9Mduom1BA75cI+R9AHnZOiaBQwpGiWnaVJLDGRdNhQmFaAqd7tkKSMGA==", + "requires": { + "bl": "^4.0.2", + "debug": "^4.1.1", + "process-nextick-args": "^2.0.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "nan": { + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.16.0.tgz", + "integrity": "sha512-UdAqHyFngu7TfQKsCBgAA6pWDkT8MAO7d0jyOecVhN5354xbLqdn8mV9Tat9gepAupm0bt2DbeaSC8vS52MuFA==" + }, + "napi-build-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", + "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==" + }, + "node-abi": { + "version": "3.22.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.22.0.tgz", + "integrity": "sha512-u4uAs/4Zzmp/jjsD9cyFYDXeISfUWaAVWshPmDZOFOv4Xl4SbzTXm53I04C2uRueYJ+0t5PEtLH/owbn2Npf/w==", + "requires": { + "semver": "^7.3.5" + } + }, + "nodemailer": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.7.tgz", + "integrity": "sha512-rUtR77ksqex/eZRLmQ21LKVH5nAAsVicAtAYudK7JgwenEDZ0UIQ1adUGqErz7sMkWYxWTTU1aeP2Jga6WQyJw==" + }, + "npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "number-allocator": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/number-allocator/-/number-allocator-1.0.14.tgz", + "integrity": "sha512-OrL44UTVAvkKdOdRQZIJpLkAdjXGTRda052sN4sO77bKEzYYqWKMBjQvrJFzqygI99gL6Z4u2xctPW1tB8ErvA==", + "requires": { + "debug": "^4.3.1", + "js-sdsl": "4.3.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==" + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==" + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==" + }, + "prebuild-install": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.0.tgz", + "integrity": "sha512-CNcMgI1xBypOyGqjp3wOc8AAo1nMhZS3Cwd3iHIxOdAUbb+YxdNuM4Z5iIrZ8RLvOsf3F3bl7b7xGq6DjQoNYA==", + "requires": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^1.0.1", + "node-abi": "^3.3.0", + "npmlog": "^4.0.1", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + } + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + } + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "reinterval": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reinterval/-/reinterval-1.1.0.tgz", + "integrity": "sha1-M2Hs+jymwYKDOA3Qu5VG85D17Oc=" + }, + "rfdc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==" + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "requires": { + "lru-cache": "^6.0.0" + } + }, + "serialport": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/serialport/-/serialport-9.2.8.tgz", + "integrity": "sha512-FsWpMQgSJxi93JgWl5xM1f9/Z8IjRJuaUEoHqLf8FPBLw7gMhInuHOBhI2onQufWIYPGTz3H3oGcu1nCaK1EfA==", + "requires": { + "@serialport/binding-mock": "9.2.4", + "@serialport/bindings": "9.2.8", + "@serialport/parser-byte-length": "9.2.4", + "@serialport/parser-cctalk": "9.2.4", + "@serialport/parser-delimiter": "9.2.4", + "@serialport/parser-inter-byte-timeout": "9.2.4", + "@serialport/parser-readline": "9.2.4", + "@serialport/parser-ready": "9.2.4", + "@serialport/parser-regex": "9.2.4", + "@serialport/stream": "9.2.4", + "debug": "^4.3.2" + } + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==" + }, + "simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "requires": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "split2": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", + "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", + "requires": { + "readable-stream": "^3.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==" + }, + "streamroller": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.1.1.tgz", + "integrity": "sha512-iPhtd9unZ6zKdWgMeYGfSBuqCngyJy1B/GPi/lTpwGpa3bajuX30GjUVd0/Tn/Xhg0mr4DOSENozz9Y06qyonQ==", + "requires": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "fs-extra": "^10.1.0" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" + }, + "tar-fs": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "requires": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "requires": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "total.js": { + "version": "3.4.13", + "resolved": "https://registry.npmjs.org/total.js/-/total.js-3.4.13.tgz", + "integrity": "sha512-lAH4gEixlPFbrE3xfKADAcHfO79IFq2wKa9GTsrgRzIR5MTg3mNH7+4IxvX1pK8faoYb/0oYSJ1YTsAa5hIFFQ==" + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, + "universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==" + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "requires": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "ws": { + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "requires": {} + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } + } +} diff --git a/RVO3/package.json b/RVO3/package.json new file mode 100755 index 0000000..7f7c795 --- /dev/null +++ b/RVO3/package.json @@ -0,0 +1,30 @@ +{ + "name": "emptyproject", + "description": "Total.js empty project.", + "version": "1.0.0", + "main": "debug.js", + "dependencies": { + "bitwise": "^2.1.0", + "easy-crc": "0.0.2", + "jsmodbus": "^4.0.6", + "log4js": "^6.3.0", + "moment": "^2.30.1", + "mqtt": "^4.2.6", + "nodemailer": "^6.9.7", + "serialport": "^9.2.8", + "total.js": "^3.4.13" + }, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "https://github.com/totaljs/emptyproject-flow" + }, + "keywords": [ + "empty", + "project" + ], + "author": "Peter Širka", + "license": "MIT" +} diff --git a/RVO3/release.js b/RVO3/release.js new file mode 100755 index 0000000..02d52ff --- /dev/null +++ b/RVO3/release.js @@ -0,0 +1,15 @@ +// =================================================== +// FOR PRODUCTION +// Total.js - framework for Node.js platform +// https://www.totaljs.com +// =================================================== + +const options = {'ip':'0.0.0.0', 'port':12345}; + +// options.ip = '127.0.0.1'; +// options.port = parseInt(process.argv[2]); +// options.config = { name: 'Total.js' }; +// options.sleep = 3000; + +require('total.js').http('release', options); +// require('total.js').cluster.http(5, 'release', options); diff --git a/RVO3/release.js.json b/RVO3/release.js.json new file mode 100755 index 0000000..ffe9ecc --- /dev/null +++ b/RVO3/release.js.json @@ -0,0 +1,34 @@ +{ + "pid": 389, + "stats": [ + { + "id": null, + "version": { + "node": "v14.18.1", + "total": "3.4.13", + "app": "1.0.0" + }, + "pid": 389, + "thread": "", + "mode": "release", + "overload": 0, + "date": "2025-10-16T00:22:54.241Z", + "memory": 24.08, + "rm": 0, + "fm": 0, + "wm": 0, + "mm": 0, + "om": 2, + "em": 1, + "dbrm": 0, + "dbwm": 0, + "usage": 0, + "requests": 7, + "pending": 0, + "errors": 0, + "timeouts": 0, + "uptime": 890, + "online": 0 + } + ] +} \ No newline at end of file diff --git a/RVO3/report_data.log b/RVO3/report_data.log new file mode 100755 index 0000000..083ad93 --- /dev/null +++ b/RVO3/report_data.log @@ -0,0 +1,211 @@ +{ + "name": "rvo_senica_3_ip119", + "time": "2025-10-15T10:34:09.108Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_3_ip119", + "time": "2025-10-15T11:34:09.106Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_3_ip119", + "time": "2025-10-15T12:34:09.106Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_3_ip119", + "time": "2025-10-15T13:34:09.106Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_3_ip119", + "time": "2025-10-15T14:34:09.106Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_3_ip119", + "time": "2025-10-15T15:34:09.107Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_3_ip119", + "time": "2025-10-15T17:23:01.145Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_3_ip119", + "time": "2025-10-15T18:23:01.145Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_3_ip119", + "time": "2025-10-15T19:23:01.145Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_3_ip119", + "time": "2025-10-15T20:23:01.145Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_3_ip119", + "time": "2025-10-15T21:23:01.145Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_3_ip119", + "time": "2025-10-15T22:23:01.145Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_3_ip119", + "time": "2025-10-15T23:23:01.145Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_3_ip119", + "time": "2025-10-16T00:23:01.145Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +} \ No newline at end of file From f90398ae913968b932528772e7441f3ecda66c0e Mon Sep 17 00:00:00 2001 From: Jakub Klena Date: Thu, 16 Oct 2025 02:23:23 +0200 Subject: [PATCH 03/30] Backup senica-RVO4 on 16.10.2025 --- RVO4/addSwitch.py | 36 + RVO4/cloud_topic.py | 76 + RVO4/config | 12 + RVO4/createNode.py | 43 + RVO4/databases/accelerometer_db.js | 3055 ++++++++++++++++ RVO4/databases/modbus_config.js | 114 + RVO4/databases/nodes.table | 1 + .../nodes_original/nodes_original.table | 1 + RVO4/databases/notifications.table | 41 + RVO4/databases/pins.table | 14 + RVO4/databases/relays.table | 5 + RVO4/databases/settings.table | 2 + RVO4/databases/tbdata.nosql | 4 + RVO4/databases/tbdatacloud.nosql | 3 + RVO4/databases/total_energy.js | 38 + RVO4/debug.js | 16 + RVO4/err.txt | 77 + RVO4/flow/cloudmqttconnect.js | 357 ++ RVO4/flow/cmd_manager.js | 3071 ++++++++++++++++ RVO4/flow/code.js | 90 + RVO4/flow/comment.js | 11 + RVO4/flow/count.js | 60 + RVO4/flow/db_connector.js | 286 ++ RVO4/flow/db_init.js | 113 + RVO4/flow/debug.js | 100 + RVO4/flow/designer.json | 3102 +++++++++++++++++ RVO4/flow/dido_controller.js | 1486 ++++++++ RVO4/flow/helper/DataToTbHandler.js | 187 + RVO4/flow/helper/ErrorToServiceHandler.js | 91 + RVO4/flow/helper/db_helper.js | 44 + RVO4/flow/helper/logger.js | 30 + RVO4/flow/helper/md5.js | 5 + RVO4/flow/helper/notification_reporter.js | 121 + RVO4/flow/helper/register.js | 144 + RVO4/flow/helper/serialport_helper.js | 99 + RVO4/flow/helper/suncalc.js | 317 ++ RVO4/flow/helper/utils.js | 161 + RVO4/flow/httprequest.js | 137 + RVO4/flow/httpresponse.js | 76 + RVO4/flow/httproute.js | 326 ++ RVO4/flow/infosender.js | 81 + RVO4/flow/modbus_reader.js | 346 ++ RVO4/flow/monitorconsumption.js | 156 + RVO4/flow/monitordisk.js | 96 + RVO4/flow/monitormemory.js | 87 + RVO4/flow/nodesdb_changecheck.js | 77 + RVO4/flow/show_dbdata.js | 243 ++ RVO4/flow/slack_filter.js | 188 + RVO4/flow/thermometer.js | 99 + RVO4/flow/trigger.js | 79 + RVO4/flow/variables.txt | 0 RVO4/flow/virtualwirein.js | 43 + RVO4/flow/virtualwireout.js | 41 + RVO4/flow/wsmqttpublish.js | 448 +++ RVO4/monitor.txt | 306 ++ RVO4/package-lock.json | 2139 ++++++++++++ RVO4/package.json | 30 + RVO4/release.js | 15 + RVO4/release.js.json | 34 + RVO4/report_data.log | 196 ++ 60 files changed, 18656 insertions(+) create mode 100755 RVO4/addSwitch.py create mode 100755 RVO4/cloud_topic.py create mode 100755 RVO4/config create mode 100755 RVO4/createNode.py create mode 100755 RVO4/databases/accelerometer_db.js create mode 100755 RVO4/databases/modbus_config.js create mode 100755 RVO4/databases/nodes.table create mode 100755 RVO4/databases/nodes_original/nodes_original.table create mode 100755 RVO4/databases/notifications.table create mode 100755 RVO4/databases/pins.table create mode 100755 RVO4/databases/relays.table create mode 100755 RVO4/databases/settings.table create mode 100755 RVO4/databases/tbdata.nosql create mode 100755 RVO4/databases/tbdatacloud.nosql create mode 100755 RVO4/databases/total_energy.js create mode 100755 RVO4/debug.js create mode 100755 RVO4/err.txt create mode 100755 RVO4/flow/cloudmqttconnect.js create mode 100755 RVO4/flow/cmd_manager.js create mode 100755 RVO4/flow/code.js create mode 100755 RVO4/flow/comment.js create mode 100755 RVO4/flow/count.js create mode 100755 RVO4/flow/db_connector.js create mode 100755 RVO4/flow/db_init.js create mode 100755 RVO4/flow/debug.js create mode 100755 RVO4/flow/designer.json create mode 100755 RVO4/flow/dido_controller.js create mode 100755 RVO4/flow/helper/DataToTbHandler.js create mode 100755 RVO4/flow/helper/ErrorToServiceHandler.js create mode 100755 RVO4/flow/helper/db_helper.js create mode 100755 RVO4/flow/helper/logger.js create mode 100755 RVO4/flow/helper/md5.js create mode 100755 RVO4/flow/helper/notification_reporter.js create mode 100755 RVO4/flow/helper/register.js create mode 100755 RVO4/flow/helper/serialport_helper.js create mode 100755 RVO4/flow/helper/suncalc.js create mode 100755 RVO4/flow/helper/utils.js create mode 100755 RVO4/flow/httprequest.js create mode 100755 RVO4/flow/httpresponse.js create mode 100755 RVO4/flow/httproute.js create mode 100755 RVO4/flow/infosender.js create mode 100755 RVO4/flow/modbus_reader.js create mode 100755 RVO4/flow/monitorconsumption.js create mode 100755 RVO4/flow/monitordisk.js create mode 100755 RVO4/flow/monitormemory.js create mode 100755 RVO4/flow/nodesdb_changecheck.js create mode 100755 RVO4/flow/show_dbdata.js create mode 100755 RVO4/flow/slack_filter.js create mode 100755 RVO4/flow/thermometer.js create mode 100755 RVO4/flow/trigger.js create mode 100755 RVO4/flow/variables.txt create mode 100755 RVO4/flow/virtualwirein.js create mode 100755 RVO4/flow/virtualwireout.js create mode 100755 RVO4/flow/wsmqttpublish.js create mode 100755 RVO4/monitor.txt create mode 100755 RVO4/package-lock.json create mode 100755 RVO4/package.json create mode 100755 RVO4/release.js create mode 100755 RVO4/release.js.json create mode 100755 RVO4/report_data.log diff --git a/RVO4/addSwitch.py b/RVO4/addSwitch.py new file mode 100755 index 0000000..c35e96b --- /dev/null +++ b/RVO4/addSwitch.py @@ -0,0 +1,36 @@ +import os + +def process_set_file(): + """ + Checks if /root/flowserver exists, reads set.txt, and modifies the second line. + """ + default_folder = "/root/flowserver" if os.path.exists("/root/flowserver") else "/home/unipi/flowserver" + flag = 1 if default_folder == "/root/flowserver" else 0 + + try: + with open("/home/unipi/flowserver/databases/settings.table", "r") as f: + lines = f.readlines() + + if len(lines) >= 2: + lines[0] = lines[0].rstrip('\n') + "|main_switch:boolean\n" + second_line = lines[1].strip() # remove trailing newline + last_pipe_index = second_line.rfind("|") + + if last_pipe_index != -1: + modified_line = second_line[:last_pipe_index + 1] + str(flag) + "|" + second_line[last_pipe_index + 1:] + lines[1] = modified_line + else: + print("Warning: No '|' character found in the second line of set.txt") + + with open("/home/unipi/flowserver/databases/settings.table", "w") as f: + f.writelines(lines) + else: + print("Warning: settings.table has less than two lines.") + + except FileNotFoundError: + print("Error: settings.table not found.") + except Exception as e: + print(e) + +# if __name__ == "__main__": +process_set_file() diff --git a/RVO4/cloud_topic.py b/RVO4/cloud_topic.py new file mode 100755 index 0000000..77c31f1 --- /dev/null +++ b/RVO4/cloud_topic.py @@ -0,0 +1,76 @@ +# import os +# +# def modify_file(file_path): +# """ +# Modifies the given file by: +# 1. Appending "|cloud_topic" to the first line. +# 2. Inserting the text from the third "." to the first "|" on the second line after the last "|" character. +# +# Args: +# file_path (str): The path to the file to be modified. +# """ +# +# with open(file_path, 'r+') as f: +# lines = f.readlines() +# +# # Modify the first line +# lines[0] += "|cloud_topic:string" +# +# # Modify the second line +# second_line = lines[1].strip() # Remove leading/trailing whitespace +# first_pipe_index = second_line.find('|') +# third_dot_index = second_line.find('.', second_line.find('.', second_line.find('.') + 1) + 1) +# text_to_insert = second_line[third_dot_index:first_pipe_index] +# +# last_pipe_index = second_line.rfind('|') +# lines[1] = second_line[:last_pipe_index + 1] + text_to_insert + "|" + second_line[last_pipe_index + 1:] +# +# print(first_pipe_index, third_dot_index, text_to_insert, last_pipe_index) +# # Write the modified lines back to the file +# # f.seek(0) +# # f.writelines(lines) +# # f.truncate() +# +# # Example usage: +# file_path = "settings.table" # Replace with the actual file path +# modify_file(file_path) +# + + +def modify_file(file_path): + """ + Modifies the given file by: + 1. Appending "|cloud_topic" to the first line. + 2. Inserting the text between the third "." and the second "|" on the second line after the last "|" character. + + Args: + file_path (str): The path to the file to be modified. + """ + + with open(file_path, 'r+') as f: + lines = f.readlines() + + first_line = lines[0].strip() + first_line += "|cloud_topic:string\n" + # Modify the first line + lines[0] = first_line + + # Modify the second line + second_line = lines[1].strip() # Remove leading/trailing whitespace + first_pipe_index = second_line.find('|') + second_pipe_index = second_line.find('|', first_pipe_index + 1) + third_dot_index = second_line.find('.', second_line.find('.', second_line.find('.') + 1) + 1) + text_to_insert = "u" + second_line[third_dot_index+1:second_pipe_index] + + last_pipe_index = second_line.rfind('|') + lines[1] = second_line[:last_pipe_index + 1] + text_to_insert + "|" + second_line[last_pipe_index + 1:] + + print(first_pipe_index, third_dot_index, text_to_insert, last_pipe_index) + # Write the modified lines back to the file + f.seek(0) + f.writelines(lines) + f.truncate() + +# Example usage: +file_path = "/home/unipi/flowserver/databases/settings.table" # Replace with the actual file path +modify_file(file_path) diff --git a/RVO4/config b/RVO4/config new file mode 100755 index 0000000..cd0a8a9 --- /dev/null +++ b/RVO4/config @@ -0,0 +1,12 @@ +name : Total.js Flow +default_timezone : Europe/Bratislava + +// Packages settings +package#flow (Object) : { url: '/' } + + +table.relays : line:number|tbname:string|contactor:number|profile:string +table.nodes : node:number|pole_number:string|node_type:string|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|project_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|cloud_topic:string|has_main_switch:boolean|daily_report:boolean|send_changed_node_numbers:boolean +table.pins : pin:string|type:string|line:number +table.notifications : key:string|weight:string|sk:string|en:string diff --git a/RVO4/createNode.py b/RVO4/createNode.py new file mode 100755 index 0000000..a8cea91 --- /dev/null +++ b/RVO4/createNode.py @@ -0,0 +1,43 @@ +print("zaciname") +import re, json + +search_str = '|' +final = [] +counter = 1 +with open("/home/unipi/flowserver/databases/nodes.table", 'r') as file: +# with open("/home/rasta5man/dev/oms/flowserver/databases/nodes.table", 'r') as file: + # Read each line in the file + for line in file: + # Print each line + line = line.strip() + print(line) + if counter != 1: + i = [m.start() for m in re.finditer(re.escape(search_str), line)] + node = line[ i[0] + 1 : i[1] ] + tbname = line[ i[3] + 1 : i[4] ] + final.append({node:tbname}) + counter += 1 +print(json.dumps(final)) +f = open("/home/unipi/flowserver/databases/nodes_original/nodes_original.table", "w") +f.write(json.dumps(final)) +f.close() + + +# +# # ``d`` has to be replaced with a different character +# old_character = "'" +# +# # ``t`` will replace ``d` +# new_character = '"' +# resultant_string = 0; +# with open("/home/unipi/flowserver/databases/nodes_original/nodes_original.table", 'r') as file: +# for line in file: +# resultant_string = re.sub("'", '"', line) +# +# resultant_string = re.sub(" ", "", resultant_string) +# print(resultant_string) +# +# f = open("/home/unipi/flowserver/databases/nodes_original/nodes_original.table", "w") +# f.write(str(resultant_string)) +# f.close() +# diff --git a/RVO4/databases/accelerometer_db.js b/RVO4/databases/accelerometer_db.js new file mode 100755 index 0000000..fdfc7fd --- /dev/null +++ b/RVO4/databases/accelerometer_db.js @@ -0,0 +1,3055 @@ +let naklony = { + "3993": { "label": "1/3A", "naklon": 0 }, + "3989": { "label": "1/3B", "naklon": 15 }, + "3976": { "label": "1/1", "naklon": 0 }, + "4181": { "label": "1/2", "naklon": 0 }, + "4376": { "label": "1/4", "naklon": 15 }, + "3868": { "label": "1/5", "naklon": 15 }, + "3728": { "label": "1/6", "naklon": 15 }, + "3730": { "label": "1/7", "naklon": 0 }, + "4374": { "label": "1/8", "naklon": 0 }, + "3718": { "label": "1/9", "naklon": 15 }, + "4375": { "label": "1/10", "naklon": 15 }, + "4172": { "label": "1/11", "naklon": 15 }, + "4176": { "label": "1/12", "naklon": 15 }, + "3800": { "label": "2/1", "naklon": 5 }, + "3823": { "label": "2/2", "naklon": 5 }, + "3905": { "label": "2/3", "naklon": 5 }, + "3803": { "label": "2/4", "naklon": 5 }, + "3817": { "label": "2/5", "naklon": 5 }, + "3818": { "label": "2/6", "naklon": 5 }, + "3811": { "label": "2/7", "naklon": 5 }, + "3915": { "label": "2/8", "naklon": 5 }, + "3843": { "label": "2/9", "naklon": 10 }, + "3827": { "label": "2/10", "naklon": 10 }, + "4220": { "label": "2/11", "naklon": 10 }, + "3826": { "label": "2/12", "naklon": 10 }, + "3834": { "label": "2/13", "naklon": 10 }, + "3838": { "label": "2/14", "naklon": 10 }, + "2823": { "label": "2/15", "naklon": 10 }, + "3750": { "label": "2/16", "naklon": 10 }, + "3378": { "label": "2/17", "naklon": 0 }, + "3376": { "label": "2/18", "naklon": 0 }, + "3379": { "label": "2/19", "naklon": 0 }, + "3285": { "label": "2/20", "naklon": 0 }, + "3382": { "label": "2/21", "naklon": 0 }, + "3383": { "label": "2/22", "naklon": 0 }, + "3375": { "label": "2/24", "naklon": 0 }, + "3381": { "label": "2/25", "naklon": 0 }, + "3380": { "label": "2/26", "naklon": 0 }, + "3828": { "label": "2/27", "naklon": 10 }, + "3377": { "label": "2/28", "naklon": 0 }, + "3591": { "label": "7/1", "naklon": 0 }, + "3587": { "label": "7/2", "naklon": 0 }, + "3468": { "label": "7/3", "naklon": 0 }, + "3466": { "label": "7/4", "naklon": 0 }, + "3474": { "label": "7/5", "naklon": 0 }, + "3481": { "label": "7/6", "naklon": 0 }, + "3589": { "label": "7/7", "naklon": 0 }, + "3472": { "label": "7/8", "naklon": 0 }, + "3473": { "label": "7/9", "naklon": 0 }, + "3584": { "label": "7/10", "naklon": 0 }, + "3571": { "label": "7/11", "naklon": 0 }, + "3476": { "label": "7/12", "naklon": 0 }, + "3590": { "label": "7/13", "naklon": 0 }, + "3478": { "label": "7/14", "naklon": 0 }, + "3471": { "label": "7/15", "naklon": 0 }, + "3467": { "label": "7/16", "naklon": 0 }, + "3479": { "label": "7/17", "naklon": 0 }, + "3480": { "label": "7/18", "naklon": 0 }, + "3477": { "label": "7/19", "naklon": 0 }, + "3362": { "label": "12/1", "naklon": 0 }, + "3355": { "label": "12/2", "naklon": 0 }, + "3356": { "label": "12/3", "naklon": 0 }, + "3349": { "label": "12/4", "naklon": 0 }, + "3357": { "label": "12/5", "naklon": 0 }, + "3350": { "label": "12/6", "naklon": 0 }, + "3353": { "label": "12/7", "naklon": 0 }, + "3539": { "label": "12/8", "naklon": 0 }, + "3050": { "label": "12/9", "naklon": 0 }, + "3361": { "label": "12/10", "naklon": 0 }, + "3360": { "label": "12/11", "naklon": 0 }, + "3358": { "label": "12/12", "naklon": 0 }, + "3541": { "label": "12/13", "naklon": 0 }, + "3551": { "label": "12/14", "naklon": 0 }, + "3514": { "label": "12/15", "naklon": 0 }, + "3547": { "label": "12/16", "naklon": 0 }, + "3562": { "label": "12/17", "naklon": 0 }, + "3525": { "label": "12/18", "naklon": 0 }, + "3558": { "label": "12/19", "naklon": 0 }, + "3511": { "label": "12/20", "naklon": 0 }, + "3058": { "label": "12/21", "naklon": 0 }, + "3062": { "label": "12/22", "naklon": 0 }, + "3070": { "label": "12/23", "naklon": 0 }, + "3447": { "label": "12/24", "naklon": 0 }, + "3056": { "label": "12/25", "naklon": 0 }, + "3057": { "label": "12/26", "naklon": 0 }, + "3071": { "label": "12/27", "naklon": 0 }, + "3061": { "label": "12/28", "naklon": 0 }, + "3069": { "label": "12/29", "naklon": 0 }, + "3077": { "label": "12/30", "naklon": 0 }, + "3080": { "label": "12/31", "naklon": 0 }, + "3081": { "label": "12/32", "naklon": 0 }, + "3078": { "label": "12/33", "naklon": 0 }, + "4037": { "label": "12/34", "naklon": 0 }, + "3067": { "label": "12/35", "naklon": 0 }, + "3051": { "label": "12/36", "naklon": 0 }, + "2924": { "label": "12/37", "naklon": 0 }, + "3060": { "label": "12/38", "naklon": 0 }, + "3073": { "label": "12/39", "naklon": 0 }, + "3469": { "label": "12/40", "naklon": 0 }, + "2923": { "label": "12/41", "naklon": 0 }, + "2925": { "label": "12/42", "naklon": 0 }, + "3359": { "label": "12/43", "naklon": 0 }, + "3055": { "label": "12/44", "naklon": 0 }, + "2922": { "label": "12/45", "naklon": 0 }, + "3084": { "label": "12/46", "naklon": 0 }, + "3064": { "label": "12/47", "naklon": 0 }, + "3066": { "label": "12/48", "naklon": 0 }, + "3072": { "label": "12/49", "naklon": 0 }, + "3415": { "label": "13/13A", "naklon": 0 }, + "3409": { "label": "13/13B", "naklon": 0 }, + "3399": { "label": "13/13C", "naklon": 0 }, + "3410": { "label": "13/29A", "naklon": 0 }, + "3407": { "label": "13/29B", "naklon": 0 }, + "3405": { "label": "13/34A", "naklon": 0 }, + "3404": { "label": "13/34B", "naklon": 0 }, + "3392": { "label": "13/45A", "naklon": 0 }, + "3386": { "label": "13/45B", "naklon": 0 }, + "3303": { "label": "13/60A", "naklon": 3 }, + "3302": { "label": "13/60B", "naklon": 3 }, + "3319": { "label": "13/70A", "naklon": 6 }, + "3317": { "label": "13/70B", "naklon": 6 }, + "3326": { "label": "13/70C", "naklon": 6 }, + "3351": { "label": "13/73A", "naklon": 6 }, + "3313": { "label": "13/73B", "naklon": 6 }, + "3316": { "label": "13/83A", "naklon": 0 }, + "3320": { "label": "13/83B", "naklon": 0 }, + "3336": { "label": "13/95A", "naklon": 0 }, + "3323": { "label": "13/95B", "naklon": 0 }, + "3339": { "label": "13/98A", "naklon": 0 }, + "3333": { "label": "13/98B", "naklon": 0 }, + "3425": { "label": "13/1", "naklon": 0 }, + "3419": { "label": "13/2", "naklon": 0 }, + "3416": { "label": "13/3", "naklon": 0 }, + "3332": { "label": "13/4", "naklon": 0 }, + "3422": { "label": "13/5", "naklon": 0 }, + "3417": { "label": "13/6", "naklon": 0 }, + "3418": { "label": "13/7", "naklon": 0 }, + "3424": { "label": "13/8", "naklon": 0 }, + "3334": { "label": "13/9", "naklon": 0 }, + "4363": { "label": "13/10", "naklon": 0 }, + "3423": { "label": "13/11", "naklon": 0 }, + "3406": { "label": "13/12", "naklon": 0 }, + "3411": { "label": "13/14", "naklon": 0 }, + "3412": { "label": "13/15", "naklon": 0 }, + "3413": { "label": "13/16", "naklon": 0 }, + "3414": { "label": "13/17", "naklon": 0 }, + "3391": { "label": "13/18", "naklon": 0 }, + "3370": { "label": "13/19", "naklon": 0 }, + "3369": { "label": "13/20", "naklon": 0 }, + "3408": { "label": "13/21", "naklon": 0 }, + "3393": { "label": "13/22", "naklon": 0 }, + "3128": { "label": "13/23", "naklon": 0 }, + "3197": { "label": "13/24", "naklon": 0 }, + "4364": { "label": "13/25", "naklon": 0 }, + "3155": { "label": "13/26", "naklon": 0 }, + "3196": { "label": "13/27", "naklon": 0 }, + "3144": { "label": "13/28", "naklon": 0 }, + "3150": { "label": "13/30", "naklon": 0 }, + "3390": { "label": "13/31", "naklon": 0 }, + "3401": { "label": "13/32", "naklon": 0 }, + "3275": { "label": "13/33", "naklon": 0 }, + "3371": { "label": "13/35", "naklon": 0 }, + "3389": { "label": "13/36", "naklon": 0 }, + "3388": { "label": "13/37", "naklon": 0 }, + "3365": { "label": "13/38", "naklon": 0 }, + "3363": { "label": "13/39", "naklon": 0 }, + "3397": { "label": "13/40", "naklon": 0 }, + "3567": { "label": "13/40/1", "naklon": 0 }, + "3387": { "label": "13/41", "naklon": 0 }, + "3403": { "label": "13/42", "naklon": 0 }, + "3147": { "label": "13/43", "naklon": 0 }, + "3141": { "label": "13/44", "naklon": 0 }, + "3364": { "label": "13/46", "naklon": 0 }, + "3367": { "label": "13/47", "naklon": 0 }, + "3368": { "label": "13/48", "naklon": 0 }, + "3402": { "label": "13/49", "naklon": 0 }, + "3366": { "label": "13/50", "naklon": 0 }, + "3395": { "label": "13/51", "naklon": 0 }, + "3372": { "label": "13/52", "naklon": 0 }, + "3394": { "label": "13/53", "naklon": 0 }, + "3308": { "label": "13/54", "naklon": 0 }, + "3847": { "label": "13/54/1", "naklon": 0 }, + "3312": { "label": "13/55", "naklon": 3 }, + "3309": { "label": "13/56", "naklon": 3 }, + "3311": { "label": "13/57", "naklon": 3 }, + "3310": { "label": "13/58", "naklon": 3 }, + "4365": { "label": "13/59", "naklon": 3 }, + "4093": { "label": "13/60/1", "naklon": 3 }, + "3304": { "label": "13/61", "naklon": 3 }, + "3307": { "label": "13/62", "naklon": 3 }, + "3271": { "label": "13/63", "naklon": 3 }, + "3301": { "label": "13/64", "naklon": 3 }, + "4366": { "label": "13/65", "naklon": 3 }, + "3300": { "label": "13/66", "naklon": 3 }, + "3185": { "label": "13/67", "naklon": 0 }, + "3184": { "label": "13/68", "naklon": 0 }, + "3188": { "label": "13/69", "naklon": 0 }, + "3343": { "label": "13/71", "naklon": 6 }, + "3819": { "label": "13/71/1", "naklon": 6 }, + "3880": { "label": "13/71/2", "naklon": 6 }, + "3348": { "label": "13/72", "naklon": 6 }, + "3344": { "label": "13/74", "naklon": 6 }, + "3346": { "label": "13/75", "naklon": 6 }, + "3597": { "label": "13/75/1", "naklon": 6 }, + "3345": { "label": "13/76", "naklon": 6 }, + "3322": { "label": "13/77", "naklon": 0 }, + "3325": { "label": "13/78", "naklon": 0 }, + "4310": { "label": "13/78/1", "naklon": 0 }, + "3315": { "label": "13/79", "naklon": 0 }, + "3328": { "label": "13/80", "naklon": 0 }, + "3321": { "label": "13/81", "naklon": 0 }, + "3324": { "label": "13/82", "naklon": 0 }, + "3140": { "label": "13/84", "naklon": 0 }, + "3153": { "label": "13/85", "naklon": 0 }, + "3145": { "label": "13/86", "naklon": 0 }, + "3134": { "label": "13/87", "naklon": 0 }, + "3151": { "label": "13/88", "naklon": 0 }, + "3143": { "label": "13/89", "naklon": 0 }, + "3318": { "label": "13/90", "naklon": 0 }, + "3347": { "label": "13/91", "naklon": 0 }, + "3314": { "label": "13/94", "naklon": 0 }, + "3331": { "label": "13/96", "naklon": 0 }, + "3327": { "label": "13/97", "naklon": 0 }, + "3329": { "label": "13/99", "naklon": 0 }, + "3337": { "label": "13/100", "naklon": 0 }, + "3330": { "label": "13/101", "naklon": 0 }, + "3335": { "label": "13/102", "naklon": 0 }, + "3420": { "label": "13/103", "naklon": 0 }, + "3421": { "label": "13/104", "naklon": 0 }, + "4361": { "label": "13/105", "naklon": 0 }, + "4362": { "label": "13/106", "naklon": 0 }, + "3526": { "label": "13/107", "naklon": 0 }, + "4424": { "label": "13/108", "naklon": null }, + "3561": { "label": "13/109", "naklon": null }, + "3527": { "label": "13/110", "naklon": null }, + "3521": { "label": "13/111", "naklon": null }, + "3552": { "label": "13/112", "naklon": null }, + "3544": { "label": "13/113", "naklon": null }, + "3534": { "label": "13/114", "naklon": null }, + "3516": { "label": "13/115", "naklon": null }, + "3513": { "label": "13/116", "naklon": null }, + "3565": { "label": "13/117", "naklon": null }, + "3866": { "label": "13/118", "naklon": null }, + "3136": { "label": "14/1", "naklon": 0 }, + "3137": { "label": "14/2", "naklon": 0 }, + "3135": { "label": "14/3", "naklon": 0 }, + "3149": { "label": "14/4", "naklon": 0 }, + "3142": { "label": "14/5", "naklon": 0 }, + "3342": { "label": "14/6", "naklon": 0 }, + "3340": { "label": "14/7", "naklon": 0 }, + "3152": { "label": "14/8", "naklon": 0 }, + "3886": { "label": "14/9", "naklon": 0 }, + "3341": { "label": "14/10", "naklon": null }, + "3352": { "label": "14/11", "naklon": null }, + "3396": { "label": "15/1", "naklon": 5 }, + "2784": { "label": "15/2", "naklon": 5 }, + "2788": { "label": "15/3", "naklon": 5 }, + "2801": { "label": "15/4", "naklon": 5 }, + "2815": { "label": "15/5", "naklon": 5 }, + "2829": { "label": "15/6", "naklon": 5 }, + "2796": { "label": "15/7", "naklon": 5 }, + "2803": { "label": "15/8", "naklon": 5 }, + "4304": { "label": "15/8/1", "naklon": 5 }, + "4311": { "label": "15/8/2", "naklon": 5 }, + "2821": { "label": "15/9", "naklon": 5 }, + "3400": { "label": "15/10", "naklon": 5 }, + "2799": { "label": "15/11", "naklon": 5 }, + "2804": { "label": "15/12", "naklon": 5 }, + "4303": { "label": "15/12/1", "naklon": 5 }, + "4309": { "label": "15/12/2", "naklon": 5 }, + "2806": { "label": "15/13", "naklon": 5 }, + "2787": { "label": "15/14", "naklon": 5 }, + "2809": { "label": "15/15", "naklon": 5 }, + "2814": { "label": "15/16", "naklon": 0 }, + "3934": { "label": "15/17", "naklon": 0 }, + "3192": { "label": "15/18", "naklon": 0 }, + "2812": { "label": "15/19", "naklon": 0 }, + "4070": { "label": "15/20", "naklon": 0 }, + "2826": { "label": "15/21", "naklon": 0 }, + "2808": { "label": "15/22", "naklon": 3 }, + "2795": { "label": "15/23", "naklon": 3 }, + "2807": { "label": "15/24", "naklon": 3 }, + "2831": { "label": "15/25", "naklon": 0 }, + "2862": { "label": "15/26", "naklon": null }, + "2861": { "label": "15/27", "naklon": 0 }, + "2866": { "label": "15/28", "naklon": 0 }, + "3546": { "label": "15/28/1", "naklon": 0 }, + "4146": { "label": "15/29", "naklon": 0 }, + "3001": { "label": "15/29/1", "naklon": 0 }, + "2835": { "label": "15/30", "naklon": 0 }, + "2874": { "label": "15/31", "naklon": 0 }, + "2852": { "label": "15/32", "naklon": 0 }, + "2851": { "label": "15/33", "naklon": 0 }, + "3560": { "label": "15/33/1", "naklon": 0 }, + "2858": { "label": "15/34", "naklon": 0 }, + "4306": { "label": "15/34/1", "naklon": 0 }, + "2856": { "label": "15/35", "naklon": 0 }, + "2847": { "label": "15/36", "naklon": 0 }, + "3556": { "label": "15/36/1", "naklon": 0 }, + "3950": { "label": "15/37", "naklon": 0 }, + "2848": { "label": "15/38", "naklon": 0 }, + "2863": { "label": "15/39", "naklon": 0 }, + "4313": { "label": "15/39/1", "naklon": 0 }, + "2873": { "label": "15/40", "naklon": 0 }, + "2984": { "label": "15/40/1", "naklon": 0 }, + "2854": { "label": "15/41", "naklon": 0 }, + "2859": { "label": "15/42", "naklon": 0 }, + "2872": { "label": "15/43", "naklon": 0 }, + "2849": { "label": "15/44", "naklon": 0 }, + "2864": { "label": "15/45", "naklon": 0 }, + "3553": { "label": "15/46", "naklon": null }, + "3021": { "label": "15/47", "naklon": null }, + "3008": { "label": "15/47/1", "naklon": null }, + "3017": { "label": "15/48", "naklon": null }, + "3014": { "label": "15/49", "naklon": null }, + "2981": { "label": "15/50", "naklon": null }, + "3020": { "label": "15/51", "naklon": null }, + "3027": { "label": "15/52", "naklon": null }, + "3006": { "label": "15/53", "naklon": null }, + "3012": { "label": "15/54", "naklon": null }, + "2738": { "label": "15/55", "naklon": 0 }, + "2725": { "label": "15/56", "naklon": 0 }, + "3016": { "label": "15/57", "naklon": null }, + "3005": { "label": "15/58", "naklon": null }, + "3009": { "label": "15/58/1", "naklon": null }, + "3010": { "label": "15/59", "naklon": 0 }, + "3538": { "label": "15/59/1", "naklon": 0 }, + "4145": { "label": "15/59/2", "naklon": 0 }, + "2713": { "label": "15/60", "naklon": 0 }, + "2789": { "label": "15/61", "naklon": 0 }, + "2736": { "label": "15/62", "naklon": 0 }, + "2739": { "label": "15/63", "naklon": 0 }, + "4346": { "label": "15/64", "naklon": 0 }, + "2731": { "label": "15/65", "naklon": 0 }, + "2818": { "label": "15/66", "naklon": 0 }, + "3557": { "label": "15/66/1", "naklon": 0 }, + "2822": { "label": "15/67", "naklon": 0 }, + "2833": { "label": "15/68", "naklon": 0 }, + "2834": { "label": "15/69", "naklon": 0 }, + "3097": { "label": "15/70", "naklon": 0 }, + "2824": { "label": "15/71", "naklon": 0 }, + "2828": { "label": "15/72", "naklon": 0 }, + "2600": { "label": "15/73", "naklon": 0 }, + "4314": { "label": "15/73/1", "naklon": 0 }, + "2832": { "label": "15/74", "naklon": 0 }, + "4360": { "label": "15/75", "naklon": 0 }, + "2846": { "label": "15/76", "naklon": 0 }, + "2584": { "label": "15/77", "naklon": 0 }, + "2843": { "label": "15/78", "naklon": 0 }, + "4308": { "label": "15/78/1", "naklon": 0 }, + "4144": { "label": "15/79", "naklon": null }, + "2844": { "label": "15/80", "naklon": 0 }, + "2842": { "label": "15/81", "naklon": 0 }, + "2838": { "label": "15/82", "naklon": 0 }, + "2837": { "label": "15/83", "naklon": null }, + "3555": { "label": "15/83/1", "naklon": null }, + "2839": { "label": "15/84", "naklon": 0 }, + "2830": { "label": "15/85", "naklon": 0 }, + "4066": { "label": "15/86", "naklon": 0 }, + "2836": { "label": "15/87", "naklon": 0 }, + "2911": { "label": "15/88", "naklon": 0 }, + "2825": { "label": "15/89", "naklon": 0 }, + "2811": { "label": "15/90", "naklon": 0 }, + "3740": { "label": "15/94", "naklon": 15 }, + "2734": { "label": "15/95", "naklon": 15 }, + "3105": { "label": "15/96", "naklon": 15 }, + "2732": { "label": "15/97", "naklon": 15 }, + "2727": { "label": "15/98", "naklon": 15 }, + "2735": { "label": "15/99", "naklon": 15 }, + "3926": { "label": "15/100", "naklon": 15 }, + "2918": { "label": "15/101", "naklon": 0 }, + "2705": { "label": "15/102", "naklon": 10 }, + "2708": { "label": "15/103", "naklon": 10 }, + "2721": { "label": "15/104", "naklon": 10 }, + "2719": { "label": "15/105", "naklon": 10 }, + "2919": { "label": "15/106", "naklon": 10 }, + "3101": { "label": "15/107", "naklon": 10 }, + "2853": { "label": "15/108", "naklon": 10 }, + "2715": { "label": "15/109", "naklon": 10 }, + "2712": { "label": "15/110", "naklon": 0 }, + "2711": { "label": "15/111", "naklon": 0 }, + "2709": { "label": "15/112", "naklon": 0 }, + "2710": { "label": "15/113", "naklon": 0 }, + "2907": { "label": "15/114", "naklon": 0 }, + "2906": { "label": "15/115", "naklon": 0 }, + "2908": { "label": "15/116", "naklon": 0 }, + "2901": { "label": "15/117", "naklon": 0 }, + "2913": { "label": "15/118", "naklon": 0 }, + "3656": { "label": "15/119", "naklon": 0 }, + "2781": { "label": "15/120", "naklon": 0 }, + "2802": { "label": "15/121", "naklon": 0 }, + "2791": { "label": "15/122", "naklon": 0 }, + "2783": { "label": "15/123", "naklon": 0 }, + "2794": { "label": "15/124", "naklon": 0 }, + "3139": { "label": "15/125", "naklon": 0 }, + "3229": { "label": "15/126", "naklon": 5 }, + "3239": { "label": "15/127", "naklon": 5 }, + "3230": { "label": "15/128", "naklon": 5 }, + "4016": { "label": "15/129", "naklon": null }, + "3608": { "label": "16/16A", "naklon": 0 }, + "4151": { "label": "16/16B", "naklon": 0 }, + "3710": { "label": "16/1", "naklon": 0 }, + "3726": { "label": "16/2", "naklon": 0 }, + "3743": { "label": "16/3", "naklon": 0 }, + "3724": { "label": "16/4", "naklon": 0 }, + "3712": { "label": "16/5", "naklon": 0 }, + "3739": { "label": "16/6", "naklon": 0 }, + "3742": { "label": "16/7", "naklon": 0 }, + "3731": { "label": "16/8", "naklon": 0 }, + "3727": { "label": "16/9", "naklon": 0 }, + "3729": { "label": "16/10", "naklon": 0 }, + "3736": { "label": "16/11", "naklon": 0 }, + "3713": { "label": "16/12", "naklon": 0 }, + "3715": { "label": "16/13", "naklon": 0 }, + "3733": { "label": "16/14", "naklon": 0 }, + "3732": { "label": "16/15", "naklon": 0 }, + "3634": { "label": "16/17", "naklon": 0 }, + "3610": { "label": "16/18", "naklon": 0 }, + "3626": { "label": "16/19", "naklon": 0 }, + "3618": { "label": "16/20", "naklon": 0 }, + "3619": { "label": "16/21", "naklon": 0 }, + "3628": { "label": "16/22", "naklon": 0 }, + "3615": { "label": "16/23", "naklon": 0 }, + "3609": { "label": "16/24", "naklon": 0 }, + "3606": { "label": "16/25", "naklon": 0 }, + "3624": { "label": "16/26", "naklon": 0 }, + "3627": { "label": "16/27", "naklon": 0 }, + "3607": { "label": "16/28", "naklon": 0 }, + "4370": { "label": "16/29", "naklon": 0 }, + "3692": { "label": "16/30", "naklon": 0 }, + "3614": { "label": "16/31", "naklon": 0 }, + "3623": { "label": "16/32", "naklon": 0 }, + "4373": { "label": "16/33", "naklon": 0 }, + "3620": { "label": "16/34", "naklon": 0 }, + "3685": { "label": "16/35", "naklon": 0 }, + "3616": { "label": "16/36", "naklon": 0 }, + "3686": { "label": "16/37", "naklon": 0 }, + "3688": { "label": "16/38", "naklon": 0 }, + "3684": { "label": "16/39", "naklon": 0 }, + "3825": { "label": "16/40", "naklon": 0 }, + "3865": { "label": "16/41", "naklon": 0 }, + "3824": { "label": "16/42", "naklon": 0 }, + "3871": { "label": "16/43", "naklon": 0 }, + "3801": { "label": "16/44", "naklon": 0 }, + "3862": { "label": "16/45", "naklon": 0 }, + "3876": { "label": "16/46", "naklon": 0 }, + "3861": { "label": "16/47", "naklon": 0 }, + "4215": { "label": "16/48", "naklon": 0 }, + "3605": { "label": "16/49", "naklon": 10 }, + "3603": { "label": "16/50", "naklon": 10 }, + "3592": { "label": "16/51", "naklon": 10 }, + "3598": { "label": "16/52", "naklon": 10 }, + "3594": { "label": "16/53", "naklon": 10 }, + "3593": { "label": "16/54", "naklon": 10 }, + "3630": { "label": "16/55", "naklon": 10 }, + "3763": { "label": "16/56", "naklon": 10 }, + "3746": { "label": "16/57", "naklon": 10 }, + "3699": { "label": "16/58", "naklon": 0 }, + "3698": { "label": "16/59", "naklon": 0 }, + "3709": { "label": "16/60", "naklon": null }, + "3708": { "label": "16/61", "naklon": 0 }, + "3703": { "label": "16/62", "naklon": null }, + "3700": { "label": "16/63", "naklon": 0 }, + "3701": { "label": "16/64", "naklon": null }, + "3704": { "label": "16/65", "naklon": 0 }, + "3707": { "label": "16/66", "naklon": null }, + "3810": { "label": "16/67", "naklon": 0 }, + "4208": { "label": "16/68", "naklon": null }, + "3867": { "label": "16/69", "naklon": 0 }, + "4372": { "label": "16/70", "naklon": null }, + "3881": { "label": "16/71", "naklon": 0 }, + "4204": { "label": "16/72", "naklon": null }, + "3869": { "label": "16/73", "naklon": 0 }, + "4202": { "label": "16/74", "naklon": null }, + "3830": { "label": "16/75", "naklon": 0 }, + "3870": { "label": "16/76", "naklon": null }, + "3964": { "label": "16/77", "naklon": 0 }, + "3849": { "label": "16/78", "naklon": 0 }, + "3694": { "label": "16/79", "naklon": null }, + "3717": { "label": "16/80", "naklon": 0 }, + "3877": { "label": "16/81", "naklon": null }, + "3755": { "label": "16/82", "naklon": 0 }, + "3725": { "label": "16/83", "naklon": null }, + "3716": { "label": "16/84", "naklon": 0 }, + "3696": { "label": "16/85", "naklon": null }, + "3702": { "label": "16/86", "naklon": 0 }, + "3706": { "label": "16/87", "naklon": null }, + "3850": { "label": "16/88", "naklon": 0 }, + "3848": { "label": "16/89", "naklon": null }, + "3737": { "label": "16/90", "naklon": null }, + "3705": { "label": "16/91", "naklon": 0 }, + "3723": { "label": "16/92", "naklon": null }, + "3842": { "label": "16/93", "naklon": 0 }, + "3735": { "label": "16/94", "naklon": null }, + "3719": { "label": "16/95", "naklon": 0 }, + "3697": { "label": "16/96", "naklon": 0 }, + "3711": { "label": "16/97", "naklon": 0 }, + "4107": { "label": "16/98", "naklon": null }, + "4112": { "label": "16/99", "naklon": 5 }, + "4106": { "label": "16/100", "naklon": 5 }, + "4111": { "label": "16/101", "naklon": 5 }, + "4091": { "label": "16/102", "naklon": null }, + "4104": { "label": "16/103", "naklon": 5 }, + "4094": { "label": "16/104", "naklon": null }, + "4089": { "label": "16/105", "naklon": 5 }, + "4095": { "label": "16/106", "naklon": null }, + "4102": { "label": "16/107", "naklon": 5 }, + "4105": { "label": "16/108", "naklon": null }, + "3859": { "label": "16/109", "naklon": null }, + "4090": { "label": "16/110", "naklon": 5 }, + "4110": { "label": "16/111", "naklon": null }, + "4097": { "label": "16/112", "naklon": 5 }, + "4099": { "label": "16/113", "naklon": null }, + "4096": { "label": "16/114", "naklon": null }, + "4101": { "label": "16/115", "naklon": 5 }, + "4109": { "label": "16/116", "naklon": null }, + "4092": { "label": "16/117", "naklon": 5 }, + "3631": { "label": "16/118", "naklon": null }, + "3632": { "label": "16/119", "naklon": 0 }, + "3641": { "label": "16/120", "naklon": null }, + "3638": { "label": "16/121", "naklon": 0 }, + "3637": { "label": "16/122", "naklon": null }, + "4142": { "label": "16/123", "naklon": null }, + "4147": { "label": "16/124", "naklon": 5 }, + "4139": { "label": "16/125", "naklon": 5 }, + "3172": { "label": "20/30A", "naklon": 2 }, + "3164": { "label": "20/30B", "naklon": 2 }, + "3247": { "label": "20/1", "naklon": 10 }, + "3296": { "label": "20/2", "naklon": 10 }, + "3246": { "label": "20/3", "naklon": 10 }, + "3270": { "label": "20/4", "naklon": 10 }, + "3294": { "label": "20/5", "naklon": 10 }, + "3298": { "label": "20/6", "naklon": 10 }, + "3297": { "label": "20/7", "naklon": 10 }, + "3293": { "label": "20/8", "naklon": 10 }, + "3299": { "label": "20/9", "naklon": 10 }, + "3295": { "label": "20/10", "naklon": 10 }, + "3244": { "label": "20/11", "naklon": 10 }, + "3249": { "label": "20/12", "naklon": 10 }, + "3268": { "label": "20/13", "naklon": 10 }, + "3245": { "label": "20/14", "naklon": 10 }, + "3278": { "label": "20/15", "naklon": 10 }, + "3280": { "label": "20/16", "naklon": 10 }, + "3292": { "label": "20/17", "naklon": 10 }, + "3287": { "label": "20/18", "naklon": 10 }, + "3282": { "label": "20/19", "naklon": 10 }, + "3273": { "label": "20/20", "naklon": 0 }, + "3157": { "label": "20/21", "naklon": 0 }, + "3283": { "label": "20/22", "naklon": 0 }, + "3159": { "label": "20/23", "naklon": 0 }, + "3289": { "label": "20/24", "naklon": 0 }, + "3163": { "label": "20/25", "naklon": 0 }, + "3126": { "label": "20/26", "naklon": 0 }, + "3171": { "label": "20/27", "naklon": 0 }, + "3162": { "label": "20/28", "naklon": 0 }, + "3279": { "label": "20/29", "naklon": 10 }, + "3173": { "label": "20/31", "naklon": 0 }, + "3127": { "label": "20/32", "naklon": 0 }, + "3131": { "label": "20/33", "naklon": 0 }, + "3129": { "label": "20/34", "naklon": 0 }, + "3276": { "label": "20/35", "naklon": 2 }, + "3290": { "label": "20/36", "naklon": 2 }, + "3132": { "label": "20/37", "naklon": 0 }, + "3138": { "label": "20/38", "naklon": 0 }, + "3272": { "label": "20/39", "naklon": 0 }, + "3291": { "label": "20/40", "naklon": 0 }, + "3277": { "label": "20/41", "naklon": 10 }, + "3286": { "label": "20/42", "naklon": 10 }, + "3281": { "label": "20/43", "naklon": 10 }, + "3288": { "label": "20/44", "naklon": 10 }, + "3284": { "label": "20/45", "naklon": 10 }, + "3167": { "label": "20/46", "naklon": 10 }, + "3872": { "label": "20/47", "naklon": 0 }, + "3124": { "label": "20/48", "naklon": 0 }, + "3133": { "label": "20/49", "naklon": 0 }, + "3158": { "label": "20/50", "naklon": 0 }, + "3169": { "label": "20/51", "naklon": 0 }, + "3146": { "label": "20/52", "naklon": 0 }, + "3160": { "label": "20/53", "naklon": 0 }, + "3248": { "label": "20/54", "naklon": 0 }, + "3156": { "label": "20/55", "naklon": 0 }, + "3161": { "label": "20/56", "naklon": 0 }, + "3170": { "label": "20/57", "naklon": 0 }, + "3168": { "label": "20/58", "naklon": 0 }, + "3125": { "label": "20/59", "naklon": 0 }, + "3166": { "label": "20/60", "naklon": 0 }, + "3130": { "label": "20/61", "naklon": 0 }, + "3563": { "label": "20/62", "naklon": 0 }, + "3550": { "label": "20/63", "naklon": null }, + "3269": { "label": "20/67", "naklon": 0 }, + "2921": { "label": "21/1", "naklon": 0 }, + "2707": { "label": "21/2", "naklon": 0 }, + "2723": { "label": "21/3", "naklon": 0 }, + "2716": { "label": "21/4", "naklon": 0 }, + "2717": { "label": "21/5", "naklon": 0 }, + "2720": { "label": "21/6", "naklon": 0 }, + "2722": { "label": "21/7", "naklon": 0 }, + "2718": { "label": "21/8", "naklon": 0 }, + "2724": { "label": "21/9", "naklon": 0 }, + "2742": { "label": "21/10", "naklon": 0 }, + "2743": { "label": "21/11", "naklon": 0 }, + "2733": { "label": "21/12", "naklon": 0 }, + "2903": { "label": "21/14", "naklon": 0 }, + "2917": { "label": "21/15", "naklon": 0 }, + "2897": { "label": "21/16", "naklon": 0 }, + "2914": { "label": "21/17", "naklon": 0 }, + "2898": { "label": "21/18", "naklon": 0 }, + "2773": { "label": "21/19", "naklon": 0 }, + "2895": { "label": "21/20", "naklon": 0 }, + "2896": { "label": "21/21", "naklon": 0 }, + "2771": { "label": "21/22", "naklon": 0 }, + "2772": { "label": "21/23", "naklon": 0 }, + "2793": { "label": "21/24", "naklon": 0 }, + "2902": { "label": "21/25", "naklon": 0 }, + "2910": { "label": "21/26", "naklon": 0 }, + "2909": { "label": "21/27", "naklon": 0 }, + "2920": { "label": "21/28", "naklon": 0 }, + "2916": { "label": "21/29", "naklon": 0 }, + "2904": { "label": "21/30", "naklon": 0 }, + "2915": { "label": "21/31", "naklon": 0 }, + "2905": { "label": "21/32", "naklon": 0 }, + "2900": { "label": "21/33", "naklon": 0 }, + "2899": { "label": "21/34", "naklon": 0 }, + "2741": { "label": "21/36", "naklon": 0 }, + "2714": { "label": "21/37", "naklon": 0 }, + "2701": { "label": "21/38", "naklon": 0 }, + "2703": { "label": "21/39", "naklon": 0 }, + "2704": { "label": "21/40", "naklon": 0 }, + "2702": { "label": "21/41", "naklon": 0 }, + "2706": { "label": "21/42", "naklon": 0 }, + "2776": { "label": "21/43", "naklon": 0 }, + "2770": { "label": "21/44", "naklon": 0 }, + "2786": { "label": "21/45", "naklon": 0 }, + "2779": { "label": "21/46", "naklon": 0 }, + "2782": { "label": "21/47", "naklon": 0 }, + "2785": { "label": "21/48", "naklon": 0 }, + "2769": { "label": "21/49", "naklon": 0 }, + "3354": { "label": "21/50", "naklon": 0 }, + "2778": { "label": "21/51", "naklon": 0 }, + "2775": { "label": "21/52", "naklon": 0 }, + "2780": { "label": "21/53", "naklon": 0 }, + "2790": { "label": "21/54", "naklon": 0 }, + "2792": { "label": "21/55", "naklon": 0 }, + "2774": { "label": "21/56", "naklon": 0 }, + "2630": { "label": "22/1", "naklon": 0 }, + "2631": { "label": "22/2", "naklon": 0 }, + "2632": { "label": "22/3", "naklon": 0 }, + "2633": { "label": "22/4", "naklon": 0 }, + "2634": { "label": "22/5", "naklon": 0 }, + "2636": { "label": "22/6", "naklon": 0 }, + "4367": { "label": "22/7", "naklon": 0 }, + "2637": { "label": "22/8", "naklon": 0 }, + "2638": { "label": "22/9", "naklon": 0 }, + "2639": { "label": "22/10", "naklon": 0 }, + "2640": { "label": "22/11", "naklon": 0 }, + "2641": { "label": "22/12", "naklon": 0 }, + "2642": { "label": "22/13", "naklon": 0 }, + "2643": { "label": "22/14", "naklon": 0 }, + "2644": { "label": "22/15", "naklon": 0 }, + "2645": { "label": "22/16", "naklon": 0 }, + "2646": { "label": "22/17", "naklon": 0 }, + "2647": { "label": "22/18", "naklon": 0 }, + "2648": { "label": "22/19", "naklon": 0 }, + "2649": { "label": "22/20", "naklon": 0 }, + "2650": { "label": "22/21", "naklon": 0 }, + "2651": { "label": "22/22", "naklon": 0 }, + "4103": { "label": "22/23", "naklon": 0 }, + "2653": { "label": "22/24", "naklon": 0 }, + "2654": { "label": "22/25", "naklon": 0 }, + "2655": { "label": "22/26", "naklon": 0 }, + "2656": { "label": "22/27", "naklon": 0 }, + "2657": { "label": "22/28", "naklon": 0 }, + "2658": { "label": "22/29", "naklon": 0 }, + "2659": { "label": "22/30", "naklon": 0 }, + "2660": { "label": "22/31", "naklon": 0 }, + "2661": { "label": "22/32", "naklon": 0 }, + "3015": { "label": "22/32/1", "naklon": 0 }, + "2662": { "label": "22/33", "naklon": 0 }, + "2663": { "label": "22/34", "naklon": 0 }, + "2664": { "label": "22/35", "naklon": 0 }, + "2665": { "label": "22/36", "naklon": 0 }, + "2666": { "label": "22/37", "naklon": 0 }, + "2667": { "label": "22/38", "naklon": 0 }, + "2668": { "label": "22/39", "naklon": 0 }, + "2669": { "label": "22/40", "naklon": null }, + "2670": { "label": "22/41", "naklon": null }, + "2671": { "label": "22/42", "naklon": null }, + "3087": { "label": "23/9A", "naklon": 10 }, + "3090": { "label": "23/9B", "naklon": 10 }, + "3075": { "label": "23/1", "naklon": 0 }, + "3089": { "label": "23/2", "naklon": 0 }, + "3088": { "label": "23/3", "naklon": 0 }, + "3228": { "label": "23/4", "naklon": 10 }, + "2751": { "label": "23/5", "naklon": 10 }, + "3243": { "label": "23/6", "naklon": 10 }, + "4349": { "label": "23/7", "naklon": 10 }, + "3102": { "label": "23/8", "naklon": 10 }, + "3099": { "label": "23/10", "naklon": 10 }, + "3103": { "label": "23/11", "naklon": 10 }, + "3093": { "label": "23/12", "naklon": 10 }, + "3098": { "label": "23/13", "naklon": 10 }, + "3092": { "label": "23/14", "naklon": 10 }, + "3233": { "label": "23/15", "naklon": 0 }, + "3095": { "label": "23/16", "naklon": 0 }, + "4074": { "label": "23/17", "naklon": 0 }, + "2729": { "label": "23/18", "naklon": 0 }, + "3234": { "label": "23/19", "naklon": 0 }, + "3094": { "label": "23/20", "naklon": 0 }, + "2817": { "label": "23/21", "naklon": 0 }, + "3226": { "label": "23/22", "naklon": 0 }, + "3225": { "label": "23/23", "naklon": 0 }, + "3237": { "label": "23/24", "naklon": 0 }, + "4250": { "label": "23/25", "naklon": 0 }, + "3059": { "label": "23/26", "naklon": 10 }, + "3238": { "label": "23/27", "naklon": 10 }, + "3242": { "label": "23/28", "naklon": 10 }, + "3236": { "label": "23/29", "naklon": 10 }, + "3112": { "label": "23/30", "naklon": 10 }, + "3224": { "label": "23/31", "naklon": 0 }, + "4298": { "label": "23/32", "naklon": 10 }, + "4150": { "label": "23/33", "naklon": 10 }, + "3091": { "label": "23/34", "naklon": 10 }, + "3771": { "label": "25/1", "naklon": 5 }, + "3777": { "label": "25/2", "naklon": 5 }, + "3749": { "label": "25/3", "naklon": 5 }, + "3769": { "label": "25/4", "naklon": 5 }, + "3765": { "label": "25/5", "naklon": 5 }, + "3785": { "label": "25/6", "naklon": 5 }, + "3761": { "label": "25/7", "naklon": 5 }, + "3758": { "label": "25/8", "naklon": 5 }, + "3766": { "label": "25/9", "naklon": 5 }, + "3779": { "label": "25/10", "naklon": 5 }, + "3899": { "label": "25/11", "naklon": 10 }, + "3922": { "label": "25/12", "naklon": 10 }, + "3912": { "label": "25/13", "naklon": 10 }, + "3933": { "label": "25/14", "naklon": 10 }, + "3921": { "label": "25/15", "naklon": 10 }, + "4300": { "label": "25/16", "naklon": 10 }, + "3927": { "label": "25/17", "naklon": 10 }, + "3212": { "label": "25/18", "naklon": 10 }, + "3208": { "label": "25/19", "naklon": 10 }, + "3207": { "label": "25/20", "naklon": 10 }, + "4294": { "label": "25/21", "naklon": 10 }, + "3209": { "label": "25/22", "naklon": 10 }, + "3745": { "label": "25/23", "naklon": 10 }, + "3762": { "label": "25/24", "naklon": 10 }, + "3215": { "label": "25/25", "naklon": 10 }, + "3210": { "label": "25/26", "naklon": 10 }, + "3211": { "label": "25/27", "naklon": 10 }, + "3206": { "label": "25/28", "naklon": 10 }, + "3918": { "label": "25/29", "naklon": 5 }, + "3928": { "label": "25/30", "naklon": 5 }, + "3917": { "label": "25/31", "naklon": 5 }, + "4029": { "label": "25/32", "naklon": 0 }, + "4038": { "label": "25/33", "naklon": 0 }, + "4022": { "label": "25/34", "naklon": 0 }, + "3937": { "label": "25/35", "naklon": 0 }, + "3190": { "label": "25/36", "naklon": 0 }, + "3835": { "label": "25/37", "naklon": 0 }, + "3201": { "label": "25/38", "naklon": 0 }, + "3193": { "label": "25/39", "naklon": 0 }, + "3191": { "label": "25/40", "naklon": 0 }, + "3203": { "label": "25/41", "naklon": 0 }, + "4301": { "label": "25/42", "naklon": 0 }, + "3223": { "label": "25/43", "naklon": 0 }, + "3202": { "label": "25/44", "naklon": 0 }, + "3205": { "label": "25/45", "naklon": 0 }, + "3194": { "label": "25/46", "naklon": 0 }, + "3198": { "label": "25/47", "naklon": 0 }, + "3204": { "label": "25/48", "naklon": 0 }, + "3200": { "label": "25/49", "naklon": 0 }, + "3216": { "label": "25/50", "naklon": 0 }, + "3932": { "label": "25/51", "naklon": 5 }, + "3923": { "label": "25/52", "naklon": 5 }, + "3913": { "label": "25/53", "naklon": 5 }, + "3900": { "label": "25/54", "naklon": 5 }, + "4189": { "label": "25/55", "naklon": 10 }, + "4191": { "label": "25/56", "naklon": 10 }, + "3790": { "label": "25/57", "naklon": 10 }, + "4190": { "label": "25/58", "naklon": 10 }, + "4302": { "label": "25/59", "naklon": 0 }, + "4351": { "label": "25/60", "naklon": 0 }, + "4075": { "label": "25/61", "naklon": 0 }, + "4071": { "label": "25/62", "naklon": 0 }, + "3784": { "label": "25/63", "naklon": 0 }, + "4065": { "label": "25/64", "naklon": 0 }, + "4297": { "label": "25/65", "naklon": 0 }, + "4295": { "label": "25/66", "naklon": 0 }, + "4299": { "label": "25/67", "naklon": 0 }, + "3772": { "label": "25/68", "naklon": 0 }, + "3941": { "label": "25/69", "naklon": 0 }, + "3782": { "label": "25/70", "naklon": 0 }, + "4068": { "label": "25/71", "naklon": 0 }, + "4073": { "label": "25/72", "naklon": 0 }, + "3901": { "label": "25/73", "naklon": 5 }, + "4296": { "label": "25/74", "naklon": 5 }, + "3910": { "label": "25/75", "naklon": 5 }, + "4293": { "label": "25/76", "naklon": 5 }, + "3919": { "label": "25/77", "naklon": 5 }, + "3924": { "label": "25/78", "naklon": 5 }, + "3909": { "label": "25/79", "naklon": 5 }, + "3896": { "label": "25/80", "naklon": 5 }, + "3911": { "label": "25/81", "naklon": 5 }, + "2819": { "label": "25/82", "naklon": 15 }, + "3776": { "label": "25/83", "naklon": 15 }, + "3752": { "label": "25/84", "naklon": 15 }, + "4353": { "label": "25/85", "naklon": 15 }, + "3791": { "label": "25/86", "naklon": 0 }, + "3770": { "label": "25/87", "naklon": 0 }, + "3760": { "label": "25/88", "naklon": 0 }, + "3115": { "label": "25/89", "naklon": 0 }, + "3738": { "label": "25/90", "naklon": 0 }, + "3748": { "label": "25/91", "naklon": 0 }, + "3753": { "label": "25/92", "naklon": 0 }, + "3775": { "label": "25/93", "naklon": 0 }, + "3778": { "label": "25/94", "naklon": 5 }, + "4078": { "label": "25/95", "naklon": 5 }, + "4088": { "label": "25/96", "naklon": 5 }, + "3856": { "label": "25/97", "naklon": 5 }, + "4084": { "label": "25/98", "naklon": 5 }, + "4069": { "label": "25/99", "naklon": 5 }, + "4188": { "label": "25/100", "naklon": 5 }, + "4064": { "label": "25/101", "naklon": 5 }, + "3792": { "label": "25/102", "naklon": 5 }, + "3780": { "label": "25/103", "naklon": 5 }, + "4034": { "label": "25/104", "naklon": 5 }, + "4072": { "label": "25/105", "naklon": 5 }, + "3884": { "label": "25/106", "naklon": 5 }, + "3793": { "label": "25/107", "naklon": 5 }, + "3863": { "label": "25/108", "naklon": 5 }, + "3855": { "label": "25/109", "naklon": 5 }, + "3846": { "label": "33/1", "naklon": 0 }, + "3943": { "label": "33/2", "naklon": 0 }, + "3903": { "label": "33/3", "naklon": 0 }, + "3982": { "label": "33/4", "naklon": 0 }, + "3879": { "label": "33/5", "naklon": 0 }, + "3887": { "label": "33/6", "naklon": 0 }, + "3920": { "label": "33/7", "naklon": 5 }, + "3942": { "label": "33/8", "naklon": 5 }, + "3829": { "label": "33/9", "naklon": null }, + "3452": { "label": "34/79A", "naklon": 6 }, + "3460": { "label": "34/79B", "naklon": 6 }, + "3443": { "label": "34/90A", "naklon": 6 }, + "3445": { "label": "34/90B", "naklon": 6 }, + "3457": { "label": "34/90C", "naklon": 6 }, + "3461": { "label": "34/97A", "naklon": 6 }, + "3463": { "label": "34/97B", "naklon": 6 }, + "3426": { "label": "34/98A", "naklon": 6 }, + "3444": { "label": "34/98B", "naklon": 6 }, + "3453": { "label": "34/99A", "naklon": 6 }, + "3455": { "label": "34/99B", "naklon": 6 }, + "4009": { "label": "34/1", "naklon": 0 }, + "3602": { "label": "34/2", "naklon": 0 }, + "3441": { "label": "34/3", "naklon": 0 }, + "3464": { "label": "34/4", "naklon": 0 }, + "3883": { "label": "34/5", "naklon": 0 }, + "4098": { "label": "34/6", "naklon": 0 }, + "4003": { "label": "34/7", "naklon": 0 }, + "4004": { "label": "34/8", "naklon": 0 }, + "3888": { "label": "34/9", "naklon": 0 }, + "3997": { "label": "34/10", "naklon": 0 }, + "4006": { "label": "34/11", "naklon": 0 }, + "4000": { "label": "34/12", "naklon": 0 }, + "4011": { "label": "34/13", "naklon": 0 }, + "3999": { "label": "34/14", "naklon": 0 }, + "3981": { "label": "34/15", "naklon": 0 }, + "3988": { "label": "34/16", "naklon": 0 }, + "3986": { "label": "34/17", "naklon": 0 }, + "3998": { "label": "34/18", "naklon": 0 }, + "3983": { "label": "34/19", "naklon": 0 }, + "4005": { "label": "34/20", "naklon": 0 }, + "4001": { "label": "34/21", "naklon": 0 }, + "4008": { "label": "34/22", "naklon": 0 }, + "4002": { "label": "34/23", "naklon": 0 }, + "3996": { "label": "34/24", "naklon": 0 }, + "4007": { "label": "34/25", "naklon": 0 }, + "4113": { "label": "34/26", "naklon": 15 }, + "3595": { "label": "34/27", "naklon": 5 }, + "3599": { "label": "34/28", "naklon": 5 }, + "3601": { "label": "34/29", "naklon": 5 }, + "4205": { "label": "34/30", "naklon": 0 }, + "3987": { "label": "34/31", "naklon": null }, + "4214": { "label": "34/32", "naklon": 0 }, + "4226": { "label": "34/33", "naklon": 0 }, + "4209": { "label": "34/34", "naklon": 0 }, + "4201": { "label": "34/35", "naklon": 0 }, + "3440": { "label": "34/36", "naklon": 0 }, + "3465": { "label": "34/37", "naklon": 0 }, + "3446": { "label": "34/38", "naklon": 0 }, + "4039": { "label": "34/39", "naklon": 5 }, + "4057": { "label": "34/40", "naklon": 5 }, + "3985": { "label": "34/41", "naklon": 0 }, + "3882": { "label": "34/42", "naklon": 0 }, + "4040": { "label": "34/43", "naklon": 5 }, + "3231": { "label": "34/44", "naklon": 0 }, + "3227": { "label": "34/45", "naklon": 0 }, + "3431": { "label": "34/46", "naklon": 0 }, + "4013": { "label": "34/47", "naklon": 0 }, + "4045": { "label": "34/48", "naklon": 0 }, + "3949": { "label": "34/49", "naklon": 0 }, + "3953": { "label": "34/50", "naklon": 0 }, + "3952": { "label": "34/51", "naklon": 0 }, + "3995": { "label": "34/52", "naklon": 0 }, + "3992": { "label": "34/53", "naklon": 0 }, + "4198": { "label": "34/54", "naklon": 0 }, + "3935": { "label": "34/55", "naklon": 0 }, + "4050": { "label": "34/56", "naklon": 0 }, + "4049": { "label": "34/57", "naklon": 0 }, + "4054": { "label": "34/58", "naklon": 0 }, + "3663": { "label": "34/59", "naklon": 6 }, + "3661": { "label": "34/60", "naklon": 6 }, + "3664": { "label": "34/61", "naklon": 6 }, + "3660": { "label": "34/62", "naklon": 6 }, + "3662": { "label": "34/63", "naklon": 6 }, + "3665": { "label": "34/65", "naklon": 6 }, + "3667": { "label": "34/66", "naklon": 6 }, + "3675": { "label": "34/67", "naklon": 6 }, + "3666": { "label": "34/68", "naklon": 6 }, + "3652": { "label": "34/69", "naklon": 6 }, + "3458": { "label": "34/70", "naklon": 6 }, + "4425": { "label": "34/70/1", "naklon": 6 }, + "3459": { "label": "34/71", "naklon": 6 }, + "3435": { "label": "34/72", "naklon": 6 }, + "3448": { "label": "34/73", "naklon": 6 }, + "3451": { "label": "34/74", "naklon": 6 }, + "3442": { "label": "34/75", "naklon": 6 }, + "3449": { "label": "34/76", "naklon": 6 }, + "3450": { "label": "34/77", "naklon": 6 }, + "3433": { "label": "34/78", "naklon": 6 }, + "3432": { "label": "34/80", "naklon": 12 }, + "3470": { "label": "34/81", "naklon": 12 }, + "3438": { "label": "34/82", "naklon": 12 }, + "3439": { "label": "34/83", "naklon": 12 }, + "4028": { "label": "34/84", "naklon": 5 }, + "3596": { "label": "34/85", "naklon": 5 }, + "4021": { "label": "34/86", "naklon": 5 }, + "3437": { "label": "34/87", "naklon": 12 }, + "3428": { "label": "34/88", "naklon": 12 }, + "3430": { "label": "34/89", "naklon": 12 }, + "3454": { "label": "34/91", "naklon": 6 }, + "3492": { "label": "34/92", "naklon": 6 }, + "3462": { "label": "34/93", "naklon": 6 }, + "3427": { "label": "34/94", "naklon": 6 }, + "3434": { "label": "34/95", "naklon": 6 }, + "3456": { "label": "34/96", "naklon": 6 }, + "4307": { "label": "34/98/1", "naklon": 6 }, + "3968": { "label": "35/1", "naklon": 0 }, + "3969": { "label": "35/2", "naklon": 0 }, + "3947": { "label": "35/3", "naklon": 0 }, + "3979": { "label": "35/4", "naklon": 0 }, + "3959": { "label": "35/5", "naklon": 0 }, + "3948": { "label": "35/6", "naklon": 0 }, + "3961": { "label": "35/7", "naklon": 0 }, + "3956": { "label": "35/8", "naklon": 0 }, + "3604": { "label": "35/9", "naklon": 0 }, + "3944": { "label": "35/10", "naklon": 0 }, + "3960": { "label": "35/11", "naklon": 0 }, + "3958": { "label": "35/12", "naklon": 0 }, + "4036": { "label": "35/13", "naklon": 5 }, + "3893": { "label": "35/18", "naklon": 5 }, + "4108": { "label": "35/19", "naklon": 5 }, + "4017": { "label": "35/20", "naklon": 5 }, + "3963": { "label": "35/21", "naklon": 0 }, + "3658": { "label": "35/22", "naklon": 0 }, + "3975": { "label": "35/23", "naklon": 0 }, + "3980": { "label": "35/24", "naklon": 0 }, + "4012": { "label": "35/25", "naklon": 0 }, + "3655": { "label": "35/26", "naklon": 0 }, + "3962": { "label": "35/27", "naklon": 0 }, + "3945": { "label": "35/28", "naklon": 0 }, + "3569": { "label": "35/29", "naklon": 0 }, + "3429": { "label": "35/30", "naklon": 0 }, + "3657": { "label": "35/31", "naklon": 0 }, + "3646": { "label": "35/32", "naklon": 0 }, + "3622": { "label": "35/33", "naklon": 0 }, + "3612": { "label": "35/34", "naklon": 0 }, + "3955": { "label": "35/35", "naklon": 0 }, + "3878": { "label": "35/37", "naklon": 0 }, + "3965": { "label": "35/38", "naklon": 0 }, + "3970": { "label": "35/39", "naklon": 0 }, + "3611": { "label": "35/40", "naklon": 0 }, + "2635": { "label": "35/41", "naklon": 0 }, + "3978": { "label": "35/42", "naklon": 0 }, + "4213": { "label": "35/43", "naklon": 0 }, + "3984": { "label": "35/44", "naklon": 0 }, + "4218": { "label": "35/45", "naklon": 0 }, + "3973": { "label": "35/46", "naklon": 0 }, + "3974": { "label": "35/47", "naklon": 0 }, + "3759": { "label": "35/48", "naklon": 0 }, + "3844": { "label": "35/49", "naklon": 0 }, + "3804": { "label": "35/50", "naklon": 0 }, + "3831": { "label": "35/51", "naklon": 0 }, + "3643": { "label": "35/52", "naklon": 0 }, + "3966": { "label": "35/53", "naklon": 0 }, + "3971": { "label": "35/54", "naklon": 0 }, + "3650": { "label": "35/55", "naklon": 6 }, + "3651": { "label": "35/56", "naklon": 6 }, + "3669": { "label": "35/57", "naklon": 6 }, + "3648": { "label": "35/58", "naklon": 6 }, + "3645": { "label": "35/59", "naklon": 6 }, + "3659": { "label": "35/60", "naklon": 6 }, + "3647": { "label": "35/61", "naklon": 6 }, + "3644": { "label": "35/62", "naklon": 6 }, + "3671": { "label": "35/63", "naklon": 6 }, + "3682": { "label": "35/64", "naklon": 6 }, + "3672": { "label": "35/65", "naklon": 6 }, + "3683": { "label": "35/66", "naklon": 6 }, + "3673": { "label": "35/67", "naklon": 6 }, + "3674": { "label": "35/68", "naklon": 6 }, + "3679": { "label": "35/69", "naklon": 6 }, + "3649": { "label": "35/70", "naklon": 6 }, + "3687": { "label": "35/71", "naklon": 6 }, + "3677": { "label": "35/72", "naklon": 6 }, + "3690": { "label": "35/73", "naklon": 6 }, + "3691": { "label": "35/74", "naklon": 6 }, + "3676": { "label": "35/75", "naklon": 6 }, + "3680": { "label": "35/76", "naklon": 6 }, + "3668": { "label": "35/77", "naklon": 6 }, + "3681": { "label": "35/78", "naklon": 6 }, + "3670": { "label": "35/79", "naklon": 6 }, + "3689": { "label": "35/80", "naklon": 6 }, + "3678": { "label": "35/81", "naklon": 6 }, + "3693": { "label": "35/82", "naklon": 6 }, + "3654": { "label": "35/83", "naklon": null }, + "4086": { "label": "36/1", "naklon": 0 }, + "4085": { "label": "36/2", "naklon": 0 }, + "4083": { "label": "36/3", "naklon": 0 }, + "4087": { "label": "36/4", "naklon": 0 }, + "4077": { "label": "36/5", "naklon": 0 }, + "4082": { "label": "36/6", "naklon": 0 }, + "4186": { "label": "36/7", "naklon": 0 }, + "4206": { "label": "36/8", "naklon": 0 }, + "4080": { "label": "36/9", "naklon": 0 }, + "4081": { "label": "36/10", "naklon": 0 }, + "4210": { "label": "36/11", "naklon": 0 }, + "4079": { "label": "36/12", "naklon": 0 }, + "4076": { "label": "36/13", "naklon": 0 }, + "3852": { "label": "36/14", "naklon": 0 }, + "2813": { "label": "36/15", "naklon": 0 }, + "4219": { "label": "36/16", "naklon": 0 }, + "3104": { "label": "37/1A", "naklon": 15 }, + "3121": { "label": "37/1B", "naklon": 15 }, + "3113": { "label": "37/2", "naklon": 10 }, + "3118": { "label": "37/3", "naklon": 10 }, + "3111": { "label": "37/4", "naklon": 10 }, + "4020": { "label": "37/5", "naklon": 10 }, + "3119": { "label": "37/6", "naklon": 10 }, + "3110": { "label": "37/7", "naklon": 10 }, + "3108": { "label": "37/8", "naklon": 10 }, + "3107": { "label": "37/12", "naklon": 0 }, + "3199": { "label": "37/13", "naklon": 0 }, + "3120": { "label": "37/14", "naklon": 0 }, + "3122": { "label": "37/15", "naklon": 0 }, + "3908": { "label": "37/16", "naklon": 0 }, + "3114": { "label": "37/17", "naklon": 0 }, + "3105": { "label": "37/18", "naklon": 0 }, + "3116": { "label": "37/19", "naklon": 0 }, + "3106": { "label": "37/20", "naklon": 0 }, + "2887": { "label": "37/21", "naklon": 5 }, + "2888": { "label": "37/22", "naklon": 5 }, + "2877": { "label": "37/23", "naklon": 5 }, + "2891": { "label": "37/24", "naklon": 5 }, + "2886": { "label": "37/25", "naklon": 5 }, + "2892": { "label": "37/26", "naklon": 5 }, + "2882": { "label": "37/27", "naklon": 5 }, + "2883": { "label": "37/28", "naklon": 5 }, + "2876": { "label": "37/29", "naklon": 5 }, + "3109": { "label": "37/30", "naklon": 5 }, + "4152": { "label": "37/31", "naklon": 5 }, + "3117": { "label": "37/32", "naklon": 5 }, + "2870": { "label": "37/33", "naklon": 5 }, + "2867": { "label": "37/34", "naklon": 0 }, + "2865": { "label": "37/35", "naklon": 0 }, + "3096": { "label": "37/36", "naklon": 0 }, + "2871": { "label": "37/37", "naklon": 0 }, + "2884": { "label": "37/38", "naklon": 0 }, + "2855": { "label": "37/39", "naklon": 0 }, + "2878": { "label": "37/40", "naklon": 0 }, + "2889": { "label": "37/41", "naklon": 0 }, + "2879": { "label": "37/42", "naklon": 0 }, + "2850": { "label": "37/43", "naklon": 0 }, + "2894": { "label": "37/44", "naklon": 0 }, + "2880": { "label": "37/45", "naklon": 0 }, + "2893": { "label": "37/46", "naklon": 0 }, + "2890": { "label": "37/47", "naklon": 0 }, + "4355": { "label": "37/48", "naklon": 0 }, + "2885": { "label": "37/49", "naklon": 0 }, + "2875": { "label": "37/50", "naklon": 0 }, + "3486": { "label": "38/30A", "naklon": 5 }, + "3714": { "label": "38/30B", "naklon": 0 }, + "3483": { "label": "38/32A", "naklon": 5 }, + "3496": { "label": "38/32B", "naklon": 0 }, + "3487": { "label": "38/35A", "naklon": 5 }, + "3498": { "label": "38/35B", "naklon": 5 }, + "3578": { "label": "38/38A", "naklon": 5 }, + "3508": { "label": "38/38B", "naklon": 5 }, + "3787": { "label": "38/59A", "naklon": 5 }, + "3491": { "label": "38/59B", "naklon": 5 }, + "3568": { "label": "38/1", "naklon": null }, + "3502": { "label": "38/2", "naklon": 0 }, + "3836": { "label": "38/3", "naklon": 0 }, + "3588": { "label": "38/4", "naklon": 0 }, + "3493": { "label": "38/5", "naklon": 0 }, + "3580": { "label": "38/6", "naklon": 0 }, + "3572": { "label": "38/7", "naklon": 0 }, + "3506": { "label": "38/8", "naklon": 0 }, + "3503": { "label": "38/9", "naklon": 0 }, + "3579": { "label": "38/10", "naklon": 0 }, + "3586": { "label": "38/11", "naklon": 0 }, + "3495": { "label": "38/12", "naklon": 5 }, + "3492": { "label": "38/13", "naklon": 5 }, + "3532": { "label": "38/14", "naklon": 5 }, + "3574": { "label": "38/15", "naklon": 5 }, + "4140": { "label": "38/16", "naklon": 5 }, + "3795": { "label": "38/17", "naklon": 5 }, + "3788": { "label": "38/18", "naklon": 5 }, + "3796": { "label": "38/19", "naklon": 5 }, + "3797": { "label": "38/20", "naklon": 5 }, + "3798": { "label": "38/21", "naklon": 5 }, + "3786": { "label": "38/22", "naklon": 5 }, + "4067": { "label": "38/23", "naklon": 5 }, + "3773": { "label": "38/24", "naklon": 5 }, + "3774": { "label": "38/25", "naklon": 5 }, + "3789": { "label": "38/26", "naklon": 5 }, + "3520": { "label": "38/27", "naklon": null }, + "3577": { "label": "38/29", "naklon": 5 }, + "3530": { "label": "38/31", "naklon": null }, + "3488": { "label": "38/33", "naklon": 5 }, + "3505": { "label": "38/34", "naklon": 5 }, + "3497": { "label": "38/36", "naklon": 5 }, + "3490": { "label": "38/37", "naklon": 5 }, + "3585": { "label": "38/39", "naklon": 5 }, + "3582": { "label": "38/40", "naklon": 5 }, + "3507": { "label": "38/41", "naklon": 5 }, + "3484": { "label": "38/42", "naklon": 5 }, + "3501": { "label": "38/43", "naklon": 5 }, + "3581": { "label": "38/44", "naklon": 5 }, + "4192": { "label": "38/45", "naklon": 5 }, + "3576": { "label": "38/46", "naklon": 5 }, + "3489": { "label": "38/47", "naklon": 5 }, + "3573": { "label": "38/48", "naklon": 5 }, + "3504": { "label": "38/49", "naklon": 5 }, + "3794": { "label": "38/50", "naklon": 5 }, + "3485": { "label": "38/51", "naklon": 5 }, + "3482": { "label": "38/52", "naklon": 5 }, + "3575": { "label": "38/53", "naklon": 5 }, + "3499": { "label": "38/54", "naklon": 5 }, + "3494": { "label": "38/55", "naklon": 5 }, + "3583": { "label": "38/56", "naklon": 5 }, + "3570": { "label": "38/57", "naklon": 5 }, + "3500": { "label": "38/58", "naklon": 0 }, + "3510": { "label": "38/63", "naklon": null }, + "3512": { "label": "38/64", "naklon": null }, + "3535": { "label": "38/67", "naklon": null }, + "3531": { "label": "38/68", "naklon": null }, + "3537": { "label": "38/69", "naklon": null }, + "3522": { "label": "39/1", "naklon": 10 }, + "4018": { "label": "39/2", "naklon": 10 }, + "4019": { "label": "39/3", "naklon": 10 }, + "4154": { "label": "39/4", "naklon": 5 }, + "3907": { "label": "39/5", "naklon": 5 }, + "4148": { "label": "39/6", "naklon": 0 }, + "4153": { "label": "39/7", "naklon": 0 }, + "3938": { "label": "39/8", "naklon": 0 }, + "3802": { "label": "39/9", "naklon": 0 }, + "4015": { "label": "39/10", "naklon": 0 }, + "3929": { "label": "39/11", "naklon": 0 }, + "3946": { "label": "39/12", "naklon": 0 }, + "4014": { "label": "39/13", "naklon": 0 }, + "4155": { "label": "39/14", "naklon": 0 }, + "4149": { "label": "39/15", "naklon": 0 }, + "3642": { "label": "39/16", "naklon": 0 }, + "3636": { "label": "39/17", "naklon": 5 }, + "3991": { "label": "39/18", "naklon": 0 }, + "3994": { "label": "39/19", "naklon": 0 }, + "3990": { "label": "39/20", "naklon": 0 }, + "3967": { "label": "39/21", "naklon": 0 }, + "3977": { "label": "39/22", "naklon": 0 }, + "3757": { "label": "39/23", "naklon": 15 }, + "3633": { "label": "39/24", "naklon": 15 }, + "3744": { "label": "39/25", "naklon": 15 }, + "4023": { "label": "39/26", "naklon": 5 }, + "3720": { "label": "39/27", "naklon": 5 }, + "3734": { "label": "39/28", "naklon": 5 }, + "3741": { "label": "39/29", "naklon": 5 }, + "3721": { "label": "39/30", "naklon": 5 }, + "3845": { "label": "39/31", "naklon": 0 }, + "3840": { "label": "39/32", "naklon": 0 }, + "3837": { "label": "39/33", "naklon": null }, + "3839": { "label": "39/34", "naklon": 0 }, + "3542": { "label": "41/1", "naklon": null }, + "3566": { "label": "41/2", "naklon": null }, + "3548": { "label": "41/3", "naklon": null }, + "3515": { "label": "41/4", "naklon": null }, + "3559": { "label": "41/5", "naklon": null }, + "3509": { "label": "41/6", "naklon": null }, + "3524": { "label": "41/7", "naklon": null }, + "3518": { "label": "41/8", "naklon": null }, + "3182": { "label": "41/9", "naklon": null }, + "3187": { "label": "41/10", "naklon": null }, + "3195": { "label": "41/11", "naklon": 0 }, + "3857": { "label": "41/12", "naklon": 0 }, + "3183": { "label": "41/13", "naklon": 0 }, + "3177": { "label": "41/14", "naklon": 0 }, + "3189": { "label": "41/15", "naklon": 0 }, + "3186": { "label": "41/16", "naklon": 0 }, + "3178": { "label": "42/1", "naklon": 0 }, + "3219": { "label": "42/2", "naklon": 0 }, + "3475": { "label": "42/3", "naklon": 0 }, + "3175": { "label": "42/4", "naklon": 0 }, + "3222": { "label": "42/5", "naklon": 0 }, + "3221": { "label": "42/6", "naklon": 0 }, + "3181": { "label": "42/7", "naklon": 0 }, + "3180": { "label": "42/8", "naklon": 0 }, + "3218": { "label": "42/9", "naklon": 0 }, + "3176": { "label": "42/10", "naklon": 0 }, + "3174": { "label": "42/11", "naklon": 0 }, + "3220": { "label": "42/12", "naklon": 0 }, + "3533": { "label": "42/13", "naklon": null }, + "3543": { "label": "42/14", "naklon": null }, + "3554": { "label": "42/15", "naklon": null }, + "3549": { "label": "42/16", "naklon": null }, + "2857": { "label": "43/1", "naklon": 5 }, + "2752": { "label": "43/2", "naklon": 5 }, + "2753": { "label": "43/3", "naklon": 5 }, + "3024": { "label": "43/4", "naklon": 5 }, + "2754": { "label": "43/5", "naklon": 5 }, + "4423": { "label": "43/6", "naklon": 5 }, + "4368": { "label": "43/7", "naklon": 5 }, + "2978": { "label": "43/8", "naklon": 5 }, + "2868": { "label": "43/9", "naklon": 5 }, + "4377": { "label": "43/10", "naklon": 5 }, + "2757": { "label": "43/11", "naklon": 5 }, + "2970": { "label": "43/12", "naklon": 5 }, + "2758": { "label": "43/13", "naklon": 5 }, + "4378": { "label": "43/14", "naklon": 5 }, + "2759": { "label": "43/15", "naklon": 5 }, + "4342": { "label": "43/16", "naklon": 5 }, + "3026": { "label": "43/17", "naklon": null }, + "2986": { "label": "43/18", "naklon": null }, + "4343": { "label": "43/19", "naklon": null }, + "2760": { "label": "43/20", "naklon": null }, + "4379": { "label": "43/21", "naklon": null }, + "2971": { "label": "43/22", "naklon": null }, + "2761": { "label": "43/23", "naklon": null }, + "2762": { "label": "43/24", "naklon": null }, + "4339": { "label": "43/25", "naklon": null }, + "4380": { "label": "43/26", "naklon": null }, + "2975": { "label": "43/27", "naklon": null }, + "3003": { "label": "43/28", "naklon": null }, + "4338": { "label": "43/29", "naklon": null }, + "3002": { "label": "43/30", "naklon": null }, + "4345": { "label": "43/31", "naklon": null }, + "2979": { "label": "43/32", "naklon": null }, + "2989": { "label": "43/33", "naklon": null }, + "2996": { "label": "43/34", "naklon": null }, + "2972": { "label": "43/35", "naklon": null }, + "2988": { "label": "43/36", "naklon": null }, + "4344": { "label": "43/37", "naklon": null }, + "3022": { "label": "43/38", "naklon": null }, + "4341": { "label": "43/39", "naklon": null }, + "2983": { "label": "43/40", "naklon": null }, + "2995": { "label": "43/41", "naklon": null }, + "2763": { "label": "43/42", "naklon": null }, + "2764": { "label": "43/43", "naklon": null }, + "2765": { "label": "43/44", "naklon": null }, + "2766": { "label": "43/45", "naklon": null }, + "2767": { "label": "43/46", "naklon": null }, + "2768": { "label": "43/47", "naklon": null }, + "3018": { "label": "43/48", "naklon": null }, + "2982": { "label": "43/49", "naklon": null }, + "3019": { "label": "43/50", "naklon": 0 }, + "3013": { "label": "43/51", "naklon": null }, + "3007": { "label": "43/52", "naklon": null }, + "2980": { "label": "43/53", "naklon": null }, + "3011": { "label": "43/54", "naklon": null }, + "2672": { "label": "43/55", "naklon": null }, + "2673": { "label": "43/56", "naklon": null }, + "2674": { "label": "43/57", "naklon": null }, + "2675": { "label": "43/58", "naklon": null }, + "2676": { "label": "43/59", "naklon": null }, + "2677": { "label": "43/60", "naklon": null }, + "2678": { "label": "43/61", "naklon": null }, + "2679": { "label": "43/62", "naklon": null }, + "2680": { "label": "43/63", "naklon": null }, + "2840": { "label": "43/64", "naklon": null }, + "2682": { "label": "43/65", "naklon": null }, + "2683": { "label": "43/66", "naklon": null }, + "2684": { "label": "43/67", "naklon": 0 }, + "2685": { "label": "43/68", "naklon": null }, + "2686": { "label": "43/69", "naklon": null }, + "2687": { "label": "43/70", "naklon": null }, + "2688": { "label": "43/71", "naklon": null }, + "2689": { "label": "43/72", "naklon": null }, + "2690": { "label": "43/73", "naklon": null }, + "2691": { "label": "43/74", "naklon": null }, + "2692": { "label": "43/75", "naklon": null }, + "2693": { "label": "43/76", "naklon": 0 }, + "2694": { "label": "43/77", "naklon": null }, + "2695": { "label": "43/78", "naklon": null }, + "2696": { "label": "43/79", "naklon": 0 }, + "2697": { "label": "43/80", "naklon": null }, + "2698": { "label": "43/81", "naklon": 0 }, + "2699": { "label": "43/82", "naklon": null }, + "2700": { "label": "43/83", "naklon": 0 }, + "2744": { "label": "43/84", "naklon": null }, + "2745": { "label": "43/85", "naklon": 0 }, + "2746": { "label": "43/86", "naklon": null }, + "2747": { "label": "43/87", "naklon": 0 }, + "2748": { "label": "43/88", "naklon": null }, + "2749": { "label": "43/89", "naklon": 0 }, + "2841": { "label": "43/90", "naklon": null }, + "4237": { "label": "45/1", "naklon": 5 }, + "4226": { "label": "45/2", "naklon": 5 }, + "4242": { "label": "45/3", "naklon": 5 }, + "4179": { "label": "45/4", "naklon": 5 }, + "4247": { "label": "45/5", "naklon": 5 }, + "4245": { "label": "45/6", "naklon": 5 }, + "3872": { "label": "45/7", "naklon": 5 }, + "4175": { "label": "45/8", "naklon": 5 }, + "4236": { "label": "45/9", "naklon": 5 }, + "4170": { "label": "45/10", "naklon": 5 }, + "4238": { "label": "45/11", "naklon": 5 }, + "4246": { "label": "45/12", "naklon": 5 }, + "4166": { "label": "45/13", "naklon": 5 }, + "4227": { "label": "45/14", "naklon": 5 }, + "4171": { "label": "45/15", "naklon": 5 }, + "4180": { "label": "45/16", "naklon": 5 }, + "4244": { "label": "45/17", "naklon": 5 }, + "4199": { "label": "45/18", "naklon": 5 }, + "4239": { "label": "45/19", "naklon": 5 }, + "4207": { "label": "45/20", "naklon": 5 }, + "4223": { "label": "45/21", "naklon": 5 }, + "4230": { "label": "45/22", "naklon": 5 }, + "4233": { "label": "45/23", "naklon": 5 }, + "4222": { "label": "45/24", "naklon": 5 }, + "4217": { "label": "45/25", "naklon": 5 }, + "4243": { "label": "45/26", "naklon": 5 }, + "4200": { "label": "45/27", "naklon": 5 }, + "4228": { "label": "45/28", "naklon": 5 }, + "4211": { "label": "45/29", "naklon": 5 }, + "4234": { "label": "45/30", "naklon": 5 }, + "4235": { "label": "45/31", "naklon": 5 }, + "4203": { "label": "45/32", "naklon": 5 }, + "4240": { "label": "45/33", "naklon": 5 }, + "4224": { "label": "45/34", "naklon": 5 }, + "4232": { "label": "45/35", "naklon": 5 }, + "4231": { "label": "45/36", "naklon": 5 }, + "4161": { "label": "45/37", "naklon": 5 }, + "4225": { "label": "45/38", "naklon": 5 }, + "4241": { "label": "45/39", "naklon": 5 }, + "4229": { "label": "45/40", "naklon": 5 }, + "4221": { "label": "45/41", "naklon": 5 }, + "4212": { "label": "45/42", "naklon": 5 }, + "4216": { "label": "45/43", "naklon": 5 }, + "3864": { "label": "45/44", "naklon": null }, + "3806": { "label": "46/1", "naklon": 5 }, + "3813": { "label": "46/2", "naklon": 5 }, + "3815": { "label": "46/3", "naklon": 5 }, + "3807": { "label": "46/4", "naklon": 5 }, + "3895": { "label": "46/5", "naklon": 5 }, + "3809": { "label": "46/6", "naklon": 5 }, + "3820": { "label": "46/7", "naklon": 5 }, + "3805": { "label": "46/8", "naklon": 5 }, + "3894": { "label": "46/9", "naklon": 0 }, + "4055": { "label": "46/10", "naklon": 0 }, + "3812": { "label": "46/11", "naklon": 5 }, + "3822": { "label": "46/12", "naklon": 5 }, + "3821": { "label": "46/13", "naklon": 5 }, + "3808": { "label": "46/14", "naklon": 5 }, + "3799": { "label": "46/15", "naklon": 5 }, + "3816": { "label": "46/16", "naklon": 5 }, + "3751": { "label": "46/17", "naklon": 5 }, + "3814": { "label": "46/18", "naklon": 5 }, + "4044": { "label": "46/19", "naklon": 0 }, + "3931": { "label": "46/20", "naklon": 0 }, + "3902": { "label": "46/21", "naklon": 5 }, + "3916": { "label": "46/22", "naklon": 5 }, + "3892": { "label": "46/23", "naklon": 5 }, + "3914": { "label": "46/24", "naklon": 5 }, + "3898": { "label": "46/25", "naklon": 5 }, + "3897": { "label": "46/26", "naklon": 5 }, + "3885": { "label": "46/27", "naklon": 5 }, + "3906": { "label": "46/28", "naklon": 5 }, + "3930": { "label": "46/29", "naklon": 0 }, + "3936": { "label": "46/30", "naklon": 0 }, + "3860": { "label": "46/31", "naklon": 5 }, + "3841": { "label": "46/32", "naklon": 5 }, + "3873": { "label": "46/33", "naklon": 5 }, + "3854": { "label": "46/34", "naklon": 5 }, + "3939": { "label": "46/35", "naklon": 5 }, + "3858": { "label": "46/36", "naklon": 5 }, + "3940": { "label": "46/37", "naklon": 5 }, + "4035": { "label": "46/38", "naklon": 5 }, + "3373": { "label": "47/1", "naklon": 0 }, + "3374": { "label": "47/2", "naklon": 0 }, + "3384": { "label": "47/3", "naklon": 0 }, + "3385": { "label": "47/4", "naklon": 0 }, + "4051": { "label": "48/1", "naklon": 5 }, + "4041": { "label": "48/2", "naklon": 5 }, + "4056": { "label": "48/3", "naklon": 5 }, + "3875": { "label": "48/4", "naklon": 5 }, + "4061": { "label": "48/5", "naklon": 5 }, + "4047": { "label": "48/6", "naklon": 5 }, + "4060": { "label": "48/7", "naklon": 5 }, + "4059": { "label": "48/8", "naklon": 5 }, + "4058": { "label": "48/9", "naklon": 5 }, + "3635": { "label": "48/10", "naklon": 5 }, + "3640": { "label": "48/11", "naklon": 5 }, + "3747": { "label": "48/12", "naklon": 5 }, + "3629": { "label": "48/13", "naklon": 5 }, + "4048": { "label": "48/14", "naklon": 5 }, + "4063": { "label": "48/15", "naklon": 5 }, + "4062": { "label": "48/16", "naklon": 5 }, + "4043": { "label": "48/17", "naklon": 5 }, + "4052": { "label": "48/18", "naklon": 5 }, + "4042": { "label": "48/19", "naklon": 5 }, + "4053": { "label": "48/20", "naklon": 5 }, + "4167": { "label": "50/15A", "naklon": null }, + "4159": { "label": "50/15B", "naklon": null }, + "4183": { "label": "50/1", "naklon": 0 }, + "4157": { "label": "50/2", "naklon": 0 }, + "4160": { "label": "50/3", "naklon": 0 }, + "4173": { "label": "50/4", "naklon": 0 }, + "4177": { "label": "50/5", "naklon": 0 }, + "4174": { "label": "50/6", "naklon": 0 }, + "4178": { "label": "50/7", "naklon": 0 }, + "4195": { "label": "50/8", "naklon": 0 }, + "4169": { "label": "50/9", "naklon": 0 }, + "4162": { "label": "50/10", "naklon": 0 }, + "4158": { "label": "50/11", "naklon": 0 }, + "4182": { "label": "50/12", "naklon": 0 }, + "4194": { "label": "50/13", "naklon": 0 }, + "4184": { "label": "50/14", "naklon": 0 }, + "4197": { "label": "50/16", "naklon": null }, + "4164": { "label": "50/17", "naklon": null }, + "3306": { "label": "50/18", "naklon": null }, + "4168": { "label": "50/19", "naklon": null }, + "4193": { "label": "50/20", "naklon": null }, + "4187": { "label": "50/21", "naklon": null }, + "4163": { "label": "50/22", "naklon": null }, + "4165": { "label": "50/23", "naklon": null }, + "4185": { "label": "50/24", "naklon": null }, + "3904": { "label": "50/25", "naklon": null }, + "2619": { "label": "53/1", "naklon": 0 }, + "2623": { "label": "53/2", "naklon": 0 }, + "2617": { "label": "53/3", "naklon": 0 }, + "2622": { "label": "53/4", "naklon": 0 }, + "2618": { "label": "53/5", "naklon": 0 }, + "2626": { "label": "53/6", "naklon": 0 }, + "2869": { "label": "53/7", "naklon": 0 }, + "2613": { "label": "53/8", "naklon": 0 }, + "2608": { "label": "53/9", "naklon": 0 }, + "2611": { "label": "53/10", "naklon": 0 }, + "2598": { "label": "53/11", "naklon": 0 }, + "3528": { "label": "53/12", "naklon": 0 }, + "3545": { "label": "53/13", "naklon": 0 }, + "2620": { "label": "53/14", "naklon": 0 }, + "2612": { "label": "53/15", "naklon": 0 }, + "2615": { "label": "53/16", "naklon": 0 }, + "3722": { "label": "53/17", "naklon": 0 }, + "2624": { "label": "53/18", "naklon": 0 }, + "2609": { "label": "53/19", "naklon": 0 }, + "2625": { "label": "53/20", "naklon": 0 }, + "2602": { "label": "53/21", "naklon": 0 }, + "2610": { "label": "53/22", "naklon": 0 }, + "2599": { "label": "53/23", "naklon": 0 }, + "2605": { "label": "53/24", "naklon": 0 }, + "2593": { "label": "53/25", "naklon": 0 }, + "3074": { "label": "53/26", "naklon": 0 }, + "2740": { "label": "53/27", "naklon": 0 }, + "2614": { "label": "53/28", "naklon": 0 }, + "2601": { "label": "53/29", "naklon": 0 }, + "4196": { "label": "53/30", "naklon": 0 }, + "2607": { "label": "53/31", "naklon": 0 }, + "2582": { "label": "53/32", "naklon": 0 }, + "2594": { "label": "53/33", "naklon": 0 }, + "2589": { "label": "53/34", "naklon": 0 }, + "2596": { "label": "53/35", "naklon": 0 }, + "2603": { "label": "53/36", "naklon": 0 }, + "2597": { "label": "53/37", "naklon": 0 }, + "2590": { "label": "53/38", "naklon": 0 }, + "2581": { "label": "53/39", "naklon": 0 }, + "2583": { "label": "53/40", "naklon": 0 }, + "2580": { "label": "53/41", "naklon": 0 }, + "2579": { "label": "53/42", "naklon": 0 }, + "2797": { "label": "53/43", "naklon": 0 }, + "2577": { "label": "53/44", "naklon": 0 }, + "2586": { "label": "53/45", "naklon": 0 }, + "2588": { "label": "53/46", "naklon": 0 }, + "2591": { "label": "53/47", "naklon": 0 }, + "2592": { "label": "53/48", "naklon": 0 }, + "2573": { "label": "53/49", "naklon": 0 }, + "2595": { "label": "53/50", "naklon": 0 }, + "2587": { "label": "53/51", "naklon": 0 }, + "2578": { "label": "53/52", "naklon": 0 }, + "2574": { "label": "53/53", "naklon": 0 }, + "2571": { "label": "53/54", "naklon": 0 }, + "2570": { "label": "53/55", "naklon": 0 }, + "2576": { "label": "53/56", "naklon": 0 }, + "2881": { "label": "53/57", "naklon": 0 }, + "2575": { "label": "53/58", "naklon": 0 }, + "2572": { "label": "53/59", "naklon": 0 }, + "2569": { "label": "53/60", "naklon": 0 }, + "4324": { "label": "55/1", "naklon": 0 }, + "4319": { "label": "55/2", "naklon": 0 }, + "4327": { "label": "55/3", "naklon": 0 }, + "4333": { "label": "55/4", "naklon": 0 }, + "4332": { "label": "55/5", "naklon": 0 }, + "4320": { "label": "55/6", "naklon": 0 }, + "4317": { "label": "55/7", "naklon": 0 }, + "4318": { "label": "55/8", "naklon": 0 }, + "4328": { "label": "55/9", "naklon": 0 }, + "4323": { "label": "55/10", "naklon": 0 }, + "4325": { "label": "55/11", "naklon": 0 }, + "4326": { "label": "55/12", "naklon": 0 }, + "4316": { "label": "55/13", "naklon": 0 }, + "4322": { "label": "55/14", "naklon": 0 }, + "4331": { "label": "55/15", "naklon": 0 }, + "4321": { "label": "55/16", "naklon": 0 }, + "4315": { "label": "55/17", "naklon": 0 }, + "4329": { "label": "55/18", "naklon": 0 }, + "4334": { "label": "55/19", "naklon": 0 }, + "4330": { "label": "55/20", "naklon": 0 } +}; + + +let svetlaSorted = [{ "label": "1/3A", "node": 3993, "naklon": 0 }, +{ "label": "1/3B", "node": 3989, "naklon": 15 }, +{ "label": "1/1", "node": 3976, "naklon": 0 }, +{ "label": "1/2", "node": 4181, "naklon": 0 }, +{ "label": "1/4", "node": 4376, "naklon": 15 }, +{ "label": "1/5", "node": 3868, "naklon": 15 }, +{ "label": "1/6", "node": 3728, "naklon": 15 }, +{ "label": "1/7", "node": 3730, "naklon": 0 }, +{ "label": "1/8", "node": 4374, "naklon": 0 }, +{ "label": "1/9", "node": 3718, "naklon": 15 }, +{ "label": "1/10", "node": 4375, "naklon": 15 }, +{ "label": "1/11", "node": 4172, "naklon": 15 }, +{ "label": "1/12", "node": 4176, "naklon": 15 }, +{ "label": "2/1", "node": 3800, "naklon": 5 }, +{ "label": "2/2", "node": 3823, "naklon": 5 }, +{ "label": "2/3", "node": 3905, "naklon": 5 }, +{ "label": "2/4", "node": 3803, "naklon": 5 }, +{ "label": "2/5", "node": 3817, "naklon": 5 }, +{ "label": "2/6", "node": 3818, "naklon": 5 }, +{ "label": "2/7", "node": 3811, "naklon": 5 }, +{ "label": "2/8", "node": 3915, "naklon": 5 }, +{ "label": "2/9", "node": 3843, "naklon": 10 }, +{ "label": "2/10", "node": 3827, "naklon": 10 }, +{ "label": "2/11", "node": 4220, "naklon": 10 }, +{ "label": "2/12", "node": 3826, "naklon": 10 }, +{ "label": "2/13", "node": 3834, "naklon": 10 }, +{ "label": "2/14", "node": 3838, "naklon": 10 }, +{ "label": "2/15", "node": 2823, "naklon": 10 }, +{ "label": "2/16", "node": 3750, "naklon": 10 }, +{ "label": "2/17", "node": 3378, "naklon": 0 }, +{ "label": "2/18", "node": 3376, "naklon": 0 }, +{ "label": "2/19", "node": 3379, "naklon": 0 }, +{ "label": "2/20", "node": 3285, "naklon": 0 }, +{ "label": "2/21", "node": 3382, "naklon": 0 }, +{ "label": "2/22", "node": 3383, "naklon": 0 }, +{ "label": "2/24", "node": 3375, "naklon": 0 }, +{ "label": "2/25", "node": 3381, "naklon": 0 }, +{ "label": "2/26", "node": 3380, "naklon": 0 }, +{ "label": "2/27", "node": 3828, "naklon": 10 }, +{ "label": "2/28", "node": 3377, "naklon": 0 }, +{ "label": "7/1", "node": 3591, "naklon": 0 }, +{ "label": "7/2", "node": 3587, "naklon": 0 }, +{ "label": "7/3", "node": 3468, "naklon": 0 }, +{ "label": "7/4", "node": 3466, "naklon": 0 }, +{ "label": "7/5", "node": 3474, "naklon": 0 }, +{ "label": "7/6", "node": 3481, "naklon": 0 }, +{ "label": "7/7", "node": 3589, "naklon": 0 }, +{ "label": "7/8", "node": 3472, "naklon": 0 }, +{ "label": "7/9", "node": 3473, "naklon": 0 }, +{ "label": "7/10", "node": 3584, "naklon": 0 }, +{ "label": "7/11", "node": 3571, "naklon": 0 }, +{ "label": "7/12", "node": 3476, "naklon": 0 }, +{ "label": "7/13", "node": 3590, "naklon": 0 }, +{ "label": "7/14", "node": 3478, "naklon": 0 }, +{ "label": "7/15", "node": 3471, "naklon": 0 }, +{ "label": "7/16", "node": 3467, "naklon": 0 }, +{ "label": "7/17", "node": 3479, "naklon": 0 }, +{ "label": "7/18", "node": 3480, "naklon": 0 }, +{ "label": "7/19", "node": 3477, "naklon": 0 }, +{ "label": "12/1", "node": 3362, "naklon": 0 }, +{ "label": "12/2", "node": 3355, "naklon": 0 }, +{ "label": "12/3", "node": 3356, "naklon": 0 }, +{ "label": "12/4", "node": 3349, "naklon": 0 }, +{ "label": "12/5", "node": 3357, "naklon": 0 }, +{ "label": "12/6", "node": 3350, "naklon": 0 }, +{ "label": "12/7", "node": 3353, "naklon": 0 }, +{ "label": "12/8", "node": 3539, "naklon": 0 }, +{ "label": "12/9", "node": 3050, "naklon": 0 }, +{ "label": "12/10", "node": 3361, "naklon": 0 }, +{ "label": "12/11", "node": 3360, "naklon": 0 }, +{ "label": "12/12", "node": 3358, "naklon": 0 }, +{ "label": "12/13", "node": 3541, "naklon": 0 }, +{ "label": "12/14", "node": 3551, "naklon": 0 }, +{ "label": "12/15", "node": 3514, "naklon": 0 }, +{ "label": "12/16", "node": 3547, "naklon": 0 }, +{ "label": "12/17", "node": 3562, "naklon": 0 }, +{ "label": "12/18", "node": 3525, "naklon": 0 }, +{ "label": "12/19", "node": 3558, "naklon": 0 }, +{ "label": "12/20", "node": 3511, "naklon": 0 }, +{ "label": "12/21", "node": 3058, "naklon": 0 }, +{ "label": "12/22", "node": 3062, "naklon": 0 }, +{ "label": "12/23", "node": 3070, "naklon": 0 }, +{ "label": "12/24", "node": 3447, "naklon": 0 }, +{ "label": "12/25", "node": 3056, "naklon": 0 }, +{ "label": "12/26", "node": 3057, "naklon": 0 }, +{ "label": "12/27", "node": 3071, "naklon": 0 }, +{ "label": "12/28", "node": 3061, "naklon": 0 }, +{ "label": "12/29", "node": 3069, "naklon": 0 }, +{ "label": "12/30", "node": 3077, "naklon": 0 }, +{ "label": "12/31", "node": 3080, "naklon": 0 }, +{ "label": "12/32", "node": 3081, "naklon": 0 }, +{ "label": "12/33", "node": 3078, "naklon": 0 }, +{ "label": "12/34", "node": 4037, "naklon": 0 }, +{ "label": "12/35", "node": 3067, "naklon": 0 }, +{ "label": "12/36", "node": 3051, "naklon": 0 }, +{ "label": "12/37", "node": 2924, "naklon": 0 }, +{ "label": "12/38", "node": 3060, "naklon": 0 }, +{ "label": "12/39", "node": 3073, "naklon": 0 }, +{ "label": "12/40", "node": 3469, "naklon": 0 }, +{ "label": "12/41", "node": 2923, "naklon": 0 }, +{ "label": "12/42", "node": 2925, "naklon": 0 }, +{ "label": "12/43", "node": 3359, "naklon": 0 }, +{ "label": "12/44", "node": 3055, "naklon": 0 }, +{ "label": "12/45", "node": 2922, "naklon": 0 }, +{ "label": "12/46", "node": 3084, "naklon": 0 }, +{ "label": "12/47", "node": 3064, "naklon": 0 }, +{ "label": "12/48", "node": 3066, "naklon": 0 }, +{ "label": "12/49", "node": 3072, "naklon": 0 }, +{ "label": "13/13A", "node": 3415, "naklon": 0 }, +{ "label": "13/13B", "node": 3409, "naklon": 0 }, +{ "label": "13/13C", "node": 3399, "naklon": 0 }, +{ "label": "13/29A", "node": 3410, "naklon": 0 }, +{ "label": "13/29B", "node": 3407, "naklon": 0 }, +{ "label": "13/34A", "node": 3405, "naklon": 0 }, +{ "label": "13/34B", "node": 3404, "naklon": 0 }, +{ "label": "13/45A", "node": 3392, "naklon": 0 }, +{ "label": "13/45B", "node": 3386, "naklon": 0 }, +{ "label": "13/60A", "node": 3303, "naklon": 3 }, +{ "label": "13/60B", "node": 3302, "naklon": 3 }, +{ "label": "13/70A", "node": 3319, "naklon": 6 }, +{ "label": "13/70B", "node": 3317, "naklon": 6 }, +{ "label": "13/70C", "node": 3326, "naklon": 6 }, +{ "label": "13/73A", "node": 3351, "naklon": 6 }, +{ "label": "13/73B", "node": 3313, "naklon": 6 }, +{ "label": "13/83A", "node": 3316, "naklon": 0 }, +{ "label": "13/83B", "node": 3320, "naklon": 0 }, +{ "label": "13/95A", "node": 3336, "naklon": 0 }, +{ "label": "13/95B", "node": 3323, "naklon": 0 }, +{ "label": "13/98A", "node": 3339, "naklon": 0 }, +{ "label": "13/98B", "node": 3333, "naklon": 0 }, +{ "label": "13/1", "node": 3425, "naklon": 0 }, +{ "label": "13/2", "node": 3419, "naklon": 0 }, +{ "label": "13/3", "node": 3416, "naklon": 0 }, +{ "label": "13/4", "node": 3332, "naklon": 0 }, +{ "label": "13/5", "node": 3422, "naklon": 0 }, +{ "label": "13/6", "node": 3417, "naklon": 0 }, +{ "label": "13/7", "node": 3418, "naklon": 0 }, +{ "label": "13/8", "node": 3424, "naklon": 0 }, +{ "label": "13/9", "node": 3334, "naklon": 0 }, +{ "label": "13/10", "node": 4363, "naklon": 0 }, +{ "label": "13/11", "node": 3423, "naklon": 0 }, +{ "label": "13/12", "node": 3406, "naklon": 0 }, +{ "label": "13/14", "node": 3411, "naklon": 0 }, +{ "label": "13/15", "node": 3412, "naklon": 0 }, +{ "label": "13/16", "node": 3413, "naklon": 0 }, +{ "label": "13/17", "node": 3414, "naklon": 0 }, +{ "label": "13/18", "node": 3391, "naklon": 0 }, +{ "label": "13/19", "node": 3370, "naklon": 0 }, +{ "label": "13/20", "node": 3369, "naklon": 0 }, +{ "label": "13/21", "node": 3408, "naklon": 0 }, +{ "label": "13/22", "node": 3393, "naklon": 0 }, +{ "label": "13/23", "node": 3128, "naklon": 0 }, +{ "label": "13/24", "node": 3197, "naklon": 0 }, +{ "label": "13/25", "node": 4364, "naklon": 0 }, +{ "label": "13/26", "node": 3155, "naklon": 0 }, +{ "label": "13/27", "node": 3196, "naklon": 0 }, +{ "label": "13/28", "node": 3144, "naklon": 0 }, +{ "label": "13/30", "node": 3150, "naklon": 0 }, +{ "label": "13/31", "node": 3390, "naklon": 0 }, +{ "label": "13/32", "node": 3401, "naklon": 0 }, +{ "label": "13/33", "node": 3275, "naklon": 0 }, +{ "label": "13/35", "node": 3371, "naklon": 0 }, +{ "label": "13/36", "node": 3389, "naklon": 0 }, +{ "label": "13/37", "node": 3388, "naklon": 0 }, +{ "label": "13/38", "node": 3365, "naklon": 0 }, +{ "label": "13/39", "node": 3363, "naklon": 0 }, +{ "label": "13/40", "node": 3397, "naklon": 0 }, +{ "label": "13/40/1", "node": 3567, "naklon": 0 }, +{ "label": "13/41", "node": 3387, "naklon": 0 }, +{ "label": "13/42", "node": 3403, "naklon": 0 }, +{ "label": "13/43", "node": 3147, "naklon": 0 }, +{ "label": "13/44", "node": 3141, "naklon": 0 }, +{ "label": "13/46", "node": 3364, "naklon": 0 }, +{ "label": "13/47", "node": 3367, "naklon": 0 }, +{ "label": "13/48", "node": 3368, "naklon": 0 }, +{ "label": "13/49", "node": 3402, "naklon": 0 }, +{ "label": "13/50", "node": 3366, "naklon": 0 }, +{ "label": "13/51", "node": 3395, "naklon": 0 }, +{ "label": "13/52", "node": 3372, "naklon": 0 }, +{ "label": "13/53", "node": 3394, "naklon": 0 }, +{ "label": "13/54", "node": 3308, "naklon": 0 }, +{ "label": "13/54/1", "node": 3847, "naklon": 0 }, +{ "label": "13/55", "node": 3312, "naklon": 3 }, +{ "label": "13/56", "node": 3309, "naklon": 3 }, +{ "label": "13/57", "node": 3311, "naklon": 3 }, +{ "label": "13/58", "node": 3310, "naklon": 3 }, +{ "label": "13/59", "node": 4365, "naklon": 3 }, +{ "label": "13/60/1", "node": 4093, "naklon": 3 }, +{ "label": "13/61", "node": 3304, "naklon": 3 }, +{ "label": "13/62", "node": 3307, "naklon": 3 }, +{ "label": "13/63", "node": 3271, "naklon": 3 }, +{ "label": "13/64", "node": 3301, "naklon": 3 }, +{ "label": "13/65", "node": 4366, "naklon": 3 }, +{ "label": "13/66", "node": 3300, "naklon": 3 }, +{ "label": "13/67", "node": 3185, "naklon": 0 }, +{ "label": "13/68", "node": 3184, "naklon": 0 }, +{ "label": "13/69", "node": 3188, "naklon": 0 }, +{ "label": "13/71", "node": 3343, "naklon": 6 }, +{ "label": "13/71/1", "node": 3819, "naklon": 6 }, +{ "label": "13/71/2", "node": 3880, "naklon": 6 }, +{ "label": "13/72", "node": 3348, "naklon": 6 }, +{ "label": "13/74", "node": 3344, "naklon": 6 }, +{ "label": "13/75", "node": 3346, "naklon": 6 }, +{ "label": "13/75/1", "node": 3597, "naklon": 6 }, +{ "label": "13/76", "node": 3345, "naklon": 6 }, +{ "label": "13/77", "node": 3322, "naklon": 0 }, +{ "label": "13/78", "node": 3325, "naklon": 0 }, +{ "label": "13/78/1", "node": 4310, "naklon": 0 }, +{ "label": "13/79", "node": 3315, "naklon": 0 }, +{ "label": "13/80", "node": 3328, "naklon": 0 }, +{ "label": "13/81", "node": 3321, "naklon": 0 }, +{ "label": "13/82", "node": 3324, "naklon": 0 }, +{ "label": "13/84", "node": 3140, "naklon": 0 }, +{ "label": "13/85", "node": 3153, "naklon": 0 }, +{ "label": "13/86", "node": 3145, "naklon": 0 }, +{ "label": "13/87", "node": 3134, "naklon": 0 }, +{ "label": "13/88", "node": 3151, "naklon": 0 }, +{ "label": "13/89", "node": 3143, "naklon": 0 }, +{ "label": "13/90", "node": 3318, "naklon": 0 }, +{ "label": "13/91", "node": 3347, "naklon": 0 }, +{ "label": "13/94", "node": 3314, "naklon": 0 }, +{ "label": "13/96", "node": 3331, "naklon": 0 }, +{ "label": "13/97", "node": 3327, "naklon": 0 }, +{ "label": "13/99", "node": 3329, "naklon": 0 }, +{ "label": "13/100", "node": 3337, "naklon": 0 }, +{ "label": "13/101", "node": 3330, "naklon": 0 }, +{ "label": "13/102", "node": 3335, "naklon": 0 }, +{ "label": "13/103", "node": 3420, "naklon": 0 }, +{ "label": "13/104", "node": 3421, "naklon": 0 }, +{ "label": "13/105", "node": 4361, "naklon": 0 }, +{ "label": "13/106", "node": 4362, "naklon": 0 }, +{ "label": "13/107", "node": 3526, "naklon": 0 }, +{ "label": "13/108", "node": 4424, "naklon": null }, +{ "label": "13/109", "node": 3561, "naklon": null }, +{ "label": "13/110", "node": 3527, "naklon": null }, +{ "label": "13/111", "node": 3521, "naklon": null }, +{ "label": "13/112", "node": 3552, "naklon": null }, +{ "label": "13/113", "node": 3544, "naklon": null }, +{ "label": "13/114", "node": 3534, "naklon": null }, +{ "label": "13/115", "node": 3516, "naklon": null }, +{ "label": "13/116", "node": 3513, "naklon": null }, +{ "label": "13/117", "node": 3565, "naklon": null }, +{ "label": "13/118", "node": 3866, "naklon": null }, +{ "label": "14/1", "node": 3136, "naklon": 0 }, +{ "label": "14/2", "node": 3137, "naklon": 0 }, +{ "label": "14/3", "node": 3135, "naklon": 0 }, +{ "label": "14/4", "node": 3149, "naklon": 0 }, +{ "label": "14/5", "node": 3142, "naklon": 0 }, +{ "label": "14/6", "node": 3342, "naklon": 0 }, +{ "label": "14/7", "node": 3340, "naklon": 0 }, +{ "label": "14/8", "node": 3152, "naklon": 0 }, +{ "label": "14/9", "node": 3886, "naklon": 0 }, +{ "label": "14/10", "node": 3341, "naklon": null }, +{ "label": "14/11", "node": 3352, "naklon": null }, +{ "label": "15/1", "node": 3396, "naklon": 5 }, +{ "label": "15/2", "node": 2784, "naklon": 5 }, +{ "label": "15/3", "node": 2788, "naklon": 5 }, +{ "label": "15/4", "node": 2801, "naklon": 5 }, +{ "label": "15/5", "node": 2815, "naklon": 5 }, +{ "label": "15/6", "node": 2829, "naklon": 5 }, +{ "label": "15/7", "node": 2796, "naklon": 5 }, +{ "label": "15/8", "node": 2803, "naklon": 5 }, +{ "label": "15/8/1", "node": 4304, "naklon": 5 }, +{ "label": "15/8/2", "node": 4311, "naklon": 5 }, +{ "label": "15/9", "node": 2821, "naklon": 5 }, +{ "label": "15/10", "node": 3400, "naklon": 5 }, +{ "label": "15/11", "node": 2799, "naklon": 5 }, +{ "label": "15/12", "node": 2804, "naklon": 5 }, +{ "label": "15/12/1", "node": 4303, "naklon": 5 }, +{ "label": "15/12/2", "node": 4309, "naklon": 5 }, +{ "label": "15/13", "node": 2806, "naklon": 5 }, +{ "label": "15/14", "node": 2787, "naklon": 5 }, +{ "label": "15/15", "node": 2809, "naklon": 5 }, +{ "label": "15/16", "node": 2814, "naklon": 0 }, +{ "label": "15/17", "node": 3934, "naklon": 0 }, +{ "label": "15/18", "node": 3192, "naklon": 0 }, +{ "label": "15/19", "node": 2812, "naklon": 0 }, +{ "label": "15/20", "node": 4070, "naklon": 0 }, +{ "label": "15/21", "node": 2826, "naklon": 0 }, +{ "label": "15/22", "node": 2808, "naklon": 3 }, +{ "label": "15/23", "node": 2795, "naklon": 3 }, +{ "label": "15/24", "node": 2807, "naklon": 3 }, +{ "label": "15/25", "node": 2831, "naklon": 0 }, +{ "label": "15/26", "node": 2862, "naklon": null }, +{ "label": "15/27", "node": 2861, "naklon": 0 }, +{ "label": "15/28", "node": 2866, "naklon": 0 }, +{ "label": "15/28/1", "node": 3546, "naklon": 0 }, +{ "label": "15/29", "node": 4146, "naklon": 0 }, +{ "label": "15/29/1", "node": 3001, "naklon": 0 }, +{ "label": "15/30", "node": 2835, "naklon": 0 }, +{ "label": "15/31", "node": 2874, "naklon": 0 }, +{ "label": "15/32", "node": 2852, "naklon": 0 }, +{ "label": "15/33", "node": 2851, "naklon": 0 }, +{ "label": "15/33/1", "node": 3560, "naklon": 0 }, +{ "label": "15/34", "node": 2858, "naklon": 0 }, +{ "label": "15/34/1", "node": 4306, "naklon": 0 }, +{ "label": "15/35", "node": 2856, "naklon": 0 }, +{ "label": "15/36", "node": 2847, "naklon": 0 }, +{ "label": "15/36/1", "node": 3556, "naklon": 0 }, +{ "label": "15/37", "node": 3950, "naklon": 0 }, +{ "label": "15/38", "node": 2848, "naklon": 0 }, +{ "label": "15/39", "node": 2863, "naklon": 0 }, +{ "label": "15/39/1", "node": 4313, "naklon": 0 }, +{ "label": "15/40", "node": 2873, "naklon": 0 }, +{ "label": "15/40/1", "node": 2984, "naklon": 0 }, +{ "label": "15/41", "node": 2854, "naklon": 0 }, +{ "label": "15/42", "node": 2859, "naklon": 0 }, +{ "label": "15/43", "node": 2872, "naklon": 0 }, +{ "label": "15/44", "node": 2849, "naklon": 0 }, +{ "label": "15/45", "node": 2864, "naklon": 0 }, +{ "label": "15/46", "node": 3553, "naklon": null }, +{ "label": "15/47", "node": 3021, "naklon": null }, +{ "label": "15/47/1", "node": 3008, "naklon": null }, +{ "label": "15/48", "node": 3017, "naklon": null }, +{ "label": "15/49", "node": 3014, "naklon": null }, +{ "label": "15/50", "node": 2981, "naklon": null }, +{ "label": "15/51", "node": 3020, "naklon": null }, +{ "label": "15/52", "node": 3027, "naklon": null }, +{ "label": "15/53", "node": 3006, "naklon": null }, +{ "label": "15/54", "node": 3012, "naklon": null }, +{ "label": "15/55", "node": 2738, "naklon": 0 }, +{ "label": "15/56", "node": 2725, "naklon": 0 }, +{ "label": "15/57", "node": 3016, "naklon": null }, +{ "label": "15/58", "node": 3005, "naklon": null }, +{ "label": "15/58/1", "node": 3009, "naklon": null }, +{ "label": "15/59", "node": 3010, "naklon": 0 }, +{ "label": "15/59/1", "node": 3538, "naklon": 0 }, +{ "label": "15/59/2", "node": 4145, "naklon": 0 }, +{ "label": "15/60", "node": 2713, "naklon": 0 }, +{ "label": "15/61", "node": 2789, "naklon": 0 }, +{ "label": "15/62", "node": 2736, "naklon": 0 }, +{ "label": "15/63", "node": 2739, "naklon": 0 }, +{ "label": "15/64", "node": 4346, "naklon": 0 }, +{ "label": "15/65", "node": 2731, "naklon": 0 }, +{ "label": "15/66", "node": 2818, "naklon": 0 }, +{ "label": "15/66/1", "node": 3557, "naklon": 0 }, +{ "label": "15/67", "node": 2822, "naklon": 0 }, +{ "label": "15/68", "node": 2833, "naklon": 0 }, +{ "label": "15/69", "node": 2834, "naklon": 0 }, +{ "label": "15/70", "node": 3097, "naklon": 0 }, +{ "label": "15/71", "node": 2824, "naklon": 0 }, +{ "label": "15/72", "node": 2828, "naklon": 0 }, +{ "label": "15/73", "node": 2600, "naklon": 0 }, +{ "label": "15/73/1", "node": 4314, "naklon": 0 }, +{ "label": "15/74", "node": 2832, "naklon": 0 }, +{ "label": "15/75", "node": 4360, "naklon": 0 }, +{ "label": "15/76", "node": 2846, "naklon": 0 }, +{ "label": "15/77", "node": 2584, "naklon": 0 }, +{ "label": "15/78", "node": 2843, "naklon": 0 }, +{ "label": "15/78/1", "node": 4308, "naklon": 0 }, +{ "label": "15/79", "node": 4144, "naklon": null }, +{ "label": "15/80", "node": 2844, "naklon": 0 }, +{ "label": "15/81", "node": 2842, "naklon": 0 }, +{ "label": "15/82", "node": 2838, "naklon": 0 }, +{ "label": "15/83", "node": 2837, "naklon": null }, +{ "label": "15/83/1", "node": 3555, "naklon": null }, +{ "label": "15/84", "node": 2839, "naklon": 0 }, +{ "label": "15/85", "node": 2830, "naklon": 0 }, +{ "label": "15/86", "node": 4066, "naklon": 0 }, +{ "label": "15/87", "node": 2836, "naklon": 0 }, +{ "label": "15/88", "node": 2911, "naklon": 0 }, +{ "label": "15/89", "node": 2825, "naklon": 0 }, +{ "label": "15/90", "node": 2811, "naklon": 0 }, +{ "label": "15/94", "node": 3740, "naklon": 15 }, +{ "label": "15/95", "node": 2734, "naklon": 15 }, +{ "label": "15/96", "node": 3105, "naklon": 15 }, +{ "label": "15/97", "node": 2732, "naklon": 15 }, +{ "label": "15/98", "node": 2727, "naklon": 15 }, +{ "label": "15/99", "node": 2735, "naklon": 15 }, +{ "label": "15/100", "node": 3926, "naklon": 15 }, +{ "label": "15/101", "node": 2918, "naklon": 0 }, +{ "label": "15/102", "node": 2705, "naklon": 10 }, +{ "label": "15/103", "node": 2708, "naklon": 10 }, +{ "label": "15/104", "node": 2721, "naklon": 10 }, +{ "label": "15/105", "node": 2719, "naklon": 10 }, +{ "label": "15/106", "node": 2919, "naklon": 10 }, +{ "label": "15/107", "node": 3101, "naklon": 10 }, +{ "label": "15/108", "node": 2853, "naklon": 10 }, +{ "label": "15/109", "node": 2715, "naklon": 10 }, +{ "label": "15/110", "node": 2712, "naklon": 0 }, +{ "label": "15/111", "node": 2711, "naklon": 0 }, +{ "label": "15/112", "node": 2709, "naklon": 0 }, +{ "label": "15/113", "node": 2710, "naklon": 0 }, +{ "label": "15/114", "node": 2907, "naklon": 0 }, +{ "label": "15/115", "node": 2906, "naklon": 0 }, +{ "label": "15/116", "node": 2908, "naklon": 0 }, +{ "label": "15/117", "node": 2901, "naklon": 0 }, +{ "label": "15/118", "node": 2913, "naklon": 0 }, +{ "label": "15/119", "node": 3656, "naklon": 0 }, +{ "label": "15/120", "node": 2781, "naklon": 0 }, +{ "label": "15/121", "node": 2802, "naklon": 0 }, +{ "label": "15/122", "node": 2791, "naklon": 0 }, +{ "label": "15/123", "node": 2783, "naklon": 0 }, +{ "label": "15/124", "node": 2794, "naklon": 0 }, +{ "label": "15/125", "node": 3139, "naklon": 0 }, +{ "label": "15/126", "node": 3229, "naklon": 5 }, +{ "label": "15/127", "node": 3239, "naklon": 5 }, +{ "label": "15/128", "node": 3230, "naklon": 5 }, +{ "label": "15/129", "node": 4016, "naklon": null }, +{ "label": "16/16A", "node": 3608, "naklon": 0 }, +{ "label": "16/16B", "node": 4151, "naklon": 0 }, +{ "label": "16/1", "node": 3710, "naklon": 0 }, +{ "label": "16/2", "node": 3726, "naklon": 0 }, +{ "label": "16/3", "node": 3743, "naklon": 0 }, +{ "label": "16/4", "node": 3724, "naklon": 0 }, +{ "label": "16/5", "node": 3712, "naklon": 0 }, +{ "label": "16/6", "node": 3739, "naklon": 0 }, +{ "label": "16/7", "node": 3742, "naklon": 0 }, +{ "label": "16/8", "node": 3731, "naklon": 0 }, +{ "label": "16/9", "node": 3727, "naklon": 0 }, +{ "label": "16/10", "node": 3729, "naklon": 0 }, +{ "label": "16/11", "node": 3736, "naklon": 0 }, +{ "label": "16/12", "node": 3713, "naklon": 0 }, +{ "label": "16/13", "node": 3715, "naklon": 0 }, +{ "label": "16/14", "node": 3733, "naklon": 0 }, +{ "label": "16/15", "node": 3732, "naklon": 0 }, +{ "label": "16/17", "node": 3634, "naklon": 0 }, +{ "label": "16/18", "node": 3610, "naklon": 0 }, +{ "label": "16/19", "node": 3626, "naklon": 0 }, +{ "label": "16/20", "node": 3618, "naklon": 0 }, +{ "label": "16/21", "node": 3619, "naklon": 0 }, +{ "label": "16/22", "node": 3628, "naklon": 0 }, +{ "label": "16/23", "node": 3615, "naklon": 0 }, +{ "label": "16/24", "node": 3609, "naklon": 0 }, +{ "label": "16/25", "node": 3606, "naklon": 0 }, +{ "label": "16/26", "node": 3624, "naklon": 0 }, +{ "label": "16/27", "node": 3627, "naklon": 0 }, +{ "label": "16/28", "node": 3607, "naklon": 0 }, +{ "label": "16/29", "node": 4370, "naklon": 0 }, +{ "label": "16/30", "node": 3692, "naklon": 0 }, +{ "label": "16/31", "node": 3614, "naklon": 0 }, +{ "label": "16/32", "node": 3623, "naklon": 0 }, +{ "label": "16/33", "node": 4373, "naklon": 0 }, +{ "label": "16/34", "node": 3620, "naklon": 0 }, +{ "label": "16/35", "node": 3685, "naklon": 0 }, +{ "label": "16/36", "node": 3616, "naklon": 0 }, +{ "label": "16/37", "node": 3686, "naklon": 0 }, +{ "label": "16/38", "node": 3688, "naklon": 0 }, +{ "label": "16/39", "node": 3684, "naklon": 0 }, +{ "label": "16/40", "node": 3825, "naklon": 0 }, +{ "label": "16/41", "node": 3865, "naklon": 0 }, +{ "label": "16/42", "node": 3824, "naklon": 0 }, +{ "label": "16/43", "node": 3871, "naklon": 0 }, +{ "label": "16/44", "node": 3801, "naklon": 0 }, +{ "label": "16/45", "node": 3862, "naklon": 0 }, +{ "label": "16/46", "node": 3876, "naklon": 0 }, +{ "label": "16/47", "node": 3861, "naklon": 0 }, +{ "label": "16/48", "node": 4215, "naklon": 0 }, +{ "label": "16/49", "node": 3605, "naklon": 10 }, +{ "label": "16/50", "node": 3603, "naklon": 10 }, +{ "label": "16/51", "node": 3592, "naklon": 10 }, +{ "label": "16/52", "node": 3598, "naklon": 10 }, +{ "label": "16/53", "node": 3594, "naklon": 10 }, +{ "label": "16/54", "node": 3593, "naklon": 10 }, +{ "label": "16/55", "node": 3630, "naklon": 10 }, +{ "label": "16/56", "node": 3763, "naklon": 10 }, +{ "label": "16/57", "node": 3746, "naklon": 10 }, +{ "label": "16/58", "node": 3699, "naklon": 0 }, +{ "label": "16/59", "node": 3698, "naklon": 0 }, +{ "label": "16/60", "node": 3709, "naklon": null }, +{ "label": "16/61", "node": 3708, "naklon": 0 }, +{ "label": "16/62", "node": 3703, "naklon": null }, +{ "label": "16/63", "node": 3700, "naklon": 0 }, +{ "label": "16/64", "node": 3701, "naklon": null }, +{ "label": "16/65", "node": 3704, "naklon": 0 }, +{ "label": "16/66", "node": 3707, "naklon": null }, +{ "label": "16/67", "node": 3810, "naklon": 0 }, +{ "label": "16/68", "node": 4208, "naklon": null }, +{ "label": "16/69", "node": 3867, "naklon": 0 }, +{ "label": "16/70", "node": 4372, "naklon": null }, +{ "label": "16/71", "node": 3881, "naklon": 0 }, +{ "label": "16/72", "node": 4204, "naklon": null }, +{ "label": "16/73", "node": 3869, "naklon": 0 }, +{ "label": "16/74", "node": 4202, "naklon": null }, +{ "label": "16/75", "node": 3830, "naklon": 0 }, +{ "label": "16/76", "node": 3870, "naklon": null }, +{ "label": "16/77", "node": 3964, "naklon": 0 }, +{ "label": "16/78", "node": 3849, "naklon": 0 }, +{ "label": "16/79", "node": 3694, "naklon": null }, +{ "label": "16/80", "node": 3717, "naklon": 0 }, +{ "label": "16/81", "node": 3877, "naklon": null }, +{ "label": "16/82", "node": 3755, "naklon": 0 }, +{ "label": "16/83", "node": 3725, "naklon": null }, +{ "label": "16/84", "node": 3716, "naklon": 0 }, +{ "label": "16/85", "node": 3696, "naklon": null }, +{ "label": "16/86", "node": 3702, "naklon": 0 }, +{ "label": "16/87", "node": 3706, "naklon": null }, +{ "label": "16/88", "node": 3850, "naklon": 0 }, +{ "label": "16/89", "node": 3848, "naklon": null }, +{ "label": "16/90", "node": 3737, "naklon": null }, +{ "label": "16/91", "node": 3705, "naklon": 0 }, +{ "label": "16/92", "node": 3723, "naklon": null }, +{ "label": "16/93", "node": 3842, "naklon": 0 }, +{ "label": "16/94", "node": 3735, "naklon": null }, +{ "label": "16/95", "node": 3719, "naklon": 0 }, +{ "label": "16/96", "node": 3697, "naklon": 0 }, +{ "label": "16/97", "node": 3711, "naklon": 0 }, +{ "label": "16/98", "node": 4107, "naklon": null }, +{ "label": "16/99", "node": 4112, "naklon": 5 }, +{ "label": "16/100", "node": 4106, "naklon": 5 }, +{ "label": "16/101", "node": 4111, "naklon": 5 }, +{ "label": "16/102", "node": 4091, "naklon": null }, +{ "label": "16/103", "node": 4104, "naklon": 5 }, +{ "label": "16/104", "node": 4094, "naklon": null }, +{ "label": "16/105", "node": 4089, "naklon": 5 }, +{ "label": "16/106", "node": 4095, "naklon": null }, +{ "label": "16/107", "node": 4102, "naklon": 5 }, +{ "label": "16/108", "node": 4105, "naklon": null }, +{ "label": "16/109", "node": 3859, "naklon": null }, +{ "label": "16/110", "node": 4090, "naklon": 5 }, +{ "label": "16/111", "node": 4110, "naklon": null }, +{ "label": "16/112", "node": 4097, "naklon": 5 }, +{ "label": "16/113", "node": 4099, "naklon": null }, +{ "label": "16/114", "node": 4096, "naklon": null }, +{ "label": "16/115", "node": 4101, "naklon": 5 }, +{ "label": "16/116", "node": 4109, "naklon": null }, +{ "label": "16/117", "node": 4092, "naklon": 5 }, +{ "label": "16/118", "node": 3631, "naklon": null }, +{ "label": "16/119", "node": 3632, "naklon": 0 }, +{ "label": "16/120", "node": 3641, "naklon": null }, +{ "label": "16/121", "node": 3638, "naklon": 0 }, +{ "label": "16/122", "node": 3637, "naklon": null }, +{ "label": "16/123", "node": 4142, "naklon": null }, +{ "label": "16/124", "node": 4147, "naklon": 5 }, +{ "label": "16/125", "node": 4139, "naklon": 5 }, +{ "label": "20/30A", "node": 3172, "naklon": 2 }, +{ "label": "20/30B", "node": 3164, "naklon": 2 }, +{ "label": "20/1", "node": 3247, "naklon": 10 }, +{ "label": "20/2", "node": 3296, "naklon": 10 }, +{ "label": "20/3", "node": 3246, "naklon": 10 }, +{ "label": "20/4", "node": 3270, "naklon": 10 }, +{ "label": "20/5", "node": 3294, "naklon": 10 }, +{ "label": "20/6", "node": 3298, "naklon": 10 }, +{ "label": "20/7", "node": 3297, "naklon": 10 }, +{ "label": "20/8", "node": 3293, "naklon": 10 }, +{ "label": "20/9", "node": 3299, "naklon": 10 }, +{ "label": "20/10", "node": 3295, "naklon": 10 }, +{ "label": "20/11", "node": 3244, "naklon": 10 }, +{ "label": "20/12", "node": 3249, "naklon": 10 }, +{ "label": "20/13", "node": 3268, "naklon": 10 }, +{ "label": "20/14", "node": 3245, "naklon": 10 }, +{ "label": "20/15", "node": 3278, "naklon": 10 }, +{ "label": "20/16", "node": 3280, "naklon": 10 }, +{ "label": "20/17", "node": 3292, "naklon": 10 }, +{ "label": "20/18", "node": 3287, "naklon": 10 }, +{ "label": "20/19", "node": 3282, "naklon": 10 }, +{ "label": "20/20", "node": 3273, "naklon": 0 }, +{ "label": "20/21", "node": 3157, "naklon": 0 }, +{ "label": "20/22", "node": 3283, "naklon": 0 }, +{ "label": "20/23", "node": 3159, "naklon": 0 }, +{ "label": "20/24", "node": 3289, "naklon": 0 }, +{ "label": "20/25", "node": 3163, "naklon": 0 }, +{ "label": "20/26", "node": 3126, "naklon": 0 }, +{ "label": "20/27", "node": 3171, "naklon": 0 }, +{ "label": "20/28", "node": 3162, "naklon": 0 }, +{ "label": "20/29", "node": 3279, "naklon": 10 }, +{ "label": "20/31", "node": 3173, "naklon": 0 }, +{ "label": "20/32", "node": 3127, "naklon": 0 }, +{ "label": "20/33", "node": 3131, "naklon": 0 }, +{ "label": "20/34", "node": 3129, "naklon": 0 }, +{ "label": "20/35", "node": 3276, "naklon": 2 }, +{ "label": "20/36", "node": 3290, "naklon": 2 }, +{ "label": "20/37", "node": 3132, "naklon": 0 }, +{ "label": "20/38", "node": 3138, "naklon": 0 }, +{ "label": "20/39", "node": 3272, "naklon": 0 }, +{ "label": "20/40", "node": 3291, "naklon": 0 }, +{ "label": "20/41", "node": 3277, "naklon": 10 }, +{ "label": "20/42", "node": 3286, "naklon": 10 }, +{ "label": "20/43", "node": 3281, "naklon": 10 }, +{ "label": "20/44", "node": 3288, "naklon": 10 }, +{ "label": "20/45", "node": 3284, "naklon": 10 }, +{ "label": "20/46", "node": 3167, "naklon": 10 }, +{ "label": "20/47", "node": 3872, "naklon": 0 }, +{ "label": "20/48", "node": 3124, "naklon": 0 }, +{ "label": "20/49", "node": 3133, "naklon": 0 }, +{ "label": "20/50", "node": 3158, "naklon": 0 }, +{ "label": "20/51", "node": 3169, "naklon": 0 }, +{ "label": "20/52", "node": 3146, "naklon": 0 }, +{ "label": "20/53", "node": 3160, "naklon": 0 }, +{ "label": "20/54", "node": 3248, "naklon": 0 }, +{ "label": "20/55", "node": 3156, "naklon": 0 }, +{ "label": "20/56", "node": 3161, "naklon": 0 }, +{ "label": "20/57", "node": 3170, "naklon": 0 }, +{ "label": "20/58", "node": 3168, "naklon": 0 }, +{ "label": "20/59", "node": 3125, "naklon": 0 }, +{ "label": "20/60", "node": 3166, "naklon": 0 }, +{ "label": "20/61", "node": 3130, "naklon": 0 }, +{ "label": "20/62", "node": 3563, "naklon": 0 }, +{ "label": "20/63", "node": 3550, "naklon": null }, +{ "label": "20/67", "node": 3269, "naklon": 0 }, +{ "label": "21/1", "node": 2921, "naklon": 0 }, +{ "label": "21/2", "node": 2707, "naklon": 0 }, +{ "label": "21/3", "node": 2723, "naklon": 0 }, +{ "label": "21/4", "node": 2716, "naklon": 0 }, +{ "label": "21/5", "node": 2717, "naklon": 0 }, +{ "label": "21/6", "node": 2720, "naklon": 0 }, +{ "label": "21/7", "node": 2722, "naklon": 0 }, +{ "label": "21/8", "node": 2718, "naklon": 0 }, +{ "label": "21/9", "node": 2724, "naklon": 0 }, +{ "label": "21/10", "node": 2742, "naklon": 0 }, +{ "label": "21/11", "node": 2743, "naklon": 0 }, +{ "label": "21/12", "node": 2733, "naklon": 0 }, +{ "label": "21/14", "node": 2903, "naklon": 0 }, +{ "label": "21/15", "node": 2917, "naklon": 0 }, +{ "label": "21/16", "node": 2897, "naklon": 0 }, +{ "label": "21/17", "node": 2914, "naklon": 0 }, +{ "label": "21/18", "node": 2898, "naklon": 0 }, +{ "label": "21/19", "node": 2773, "naklon": 0 }, +{ "label": "21/20", "node": 2895, "naklon": 0 }, +{ "label": "21/21", "node": 2896, "naklon": 0 }, +{ "label": "21/22", "node": 2771, "naklon": 0 }, +{ "label": "21/23", "node": 2772, "naklon": 0 }, +{ "label": "21/24", "node": 2793, "naklon": 0 }, +{ "label": "21/25", "node": 2902, "naklon": 0 }, +{ "label": "21/26", "node": 2910, "naklon": 0 }, +{ "label": "21/27", "node": 2909, "naklon": 0 }, +{ "label": "21/28", "node": 2920, "naklon": 0 }, +{ "label": "21/29", "node": 2916, "naklon": 0 }, +{ "label": "21/30", "node": 2904, "naklon": 0 }, +{ "label": "21/31", "node": 2915, "naklon": 0 }, +{ "label": "21/32", "node": 2905, "naklon": 0 }, +{ "label": "21/33", "node": 2900, "naklon": 0 }, +{ "label": "21/34", "node": 2899, "naklon": 0 }, +{ "label": "21/36", "node": 2741, "naklon": 0 }, +{ "label": "21/37", "node": 2714, "naklon": 0 }, +{ "label": "21/38", "node": 2701, "naklon": 0 }, +{ "label": "21/39", "node": 2703, "naklon": 0 }, +{ "label": "21/40", "node": 2704, "naklon": 0 }, +{ "label": "21/41", "node": 2702, "naklon": 0 }, +{ "label": "21/42", "node": 2706, "naklon": 0 }, +{ "label": "21/43", "node": 2776, "naklon": 0 }, +{ "label": "21/44", "node": 2770, "naklon": 0 }, +{ "label": "21/45", "node": 2786, "naklon": 0 }, +{ "label": "21/46", "node": 2779, "naklon": 0 }, +{ "label": "21/47", "node": 2782, "naklon": 0 }, +{ "label": "21/48", "node": 2785, "naklon": 0 }, +{ "label": "21/49", "node": 2769, "naklon": 0 }, +{ "label": "21/50", "node": 3354, "naklon": 0 }, +{ "label": "21/51", "node": 2778, "naklon": 0 }, +{ "label": "21/52", "node": 2775, "naklon": 0 }, +{ "label": "21/53", "node": 2780, "naklon": 0 }, +{ "label": "21/54", "node": 2790, "naklon": 0 }, +{ "label": "21/55", "node": 2792, "naklon": 0 }, +{ "label": "21/56", "node": 2774, "naklon": 0 }, +{ "label": "22/1", "node": 2630, "naklon": 0 }, +{ "label": "22/2", "node": 2631, "naklon": 0 }, +{ "label": "22/3", "node": 2632, "naklon": 0 }, +{ "label": "22/4", "node": 2633, "naklon": 0 }, +{ "label": "22/5", "node": 2634, "naklon": 0 }, +{ "label": "22/6", "node": 2636, "naklon": 0 }, +{ "label": "22/7", "node": 4367, "naklon": 0 }, +{ "label": "22/8", "node": 2637, "naklon": 0 }, +{ "label": "22/9", "node": 2638, "naklon": 0 }, +{ "label": "22/10", "node": 2639, "naklon": 0 }, +{ "label": "22/11", "node": 2640, "naklon": 0 }, +{ "label": "22/12", "node": 2641, "naklon": 0 }, +{ "label": "22/13", "node": 2642, "naklon": 0 }, +{ "label": "22/14", "node": 2643, "naklon": 0 }, +{ "label": "22/15", "node": 2644, "naklon": 0 }, +{ "label": "22/16", "node": 2645, "naklon": 0 }, +{ "label": "22/17", "node": 2646, "naklon": 0 }, +{ "label": "22/18", "node": 2647, "naklon": 0 }, +{ "label": "22/19", "node": 2648, "naklon": 0 }, +{ "label": "22/20", "node": 2649, "naklon": 0 }, +{ "label": "22/21", "node": 2650, "naklon": 0 }, +{ "label": "22/22", "node": 2651, "naklon": 0 }, +{ "label": "22/23", "node": 4103, "naklon": 0 }, +{ "label": "22/24", "node": 2653, "naklon": 0 }, +{ "label": "22/25", "node": 2654, "naklon": 0 }, +{ "label": "22/26", "node": 2655, "naklon": 0 }, +{ "label": "22/27", "node": 2656, "naklon": 0 }, +{ "label": "22/28", "node": 2657, "naklon": 0 }, +{ "label": "22/29", "node": 2658, "naklon": 0 }, +{ "label": "22/30", "node": 2659, "naklon": 0 }, +{ "label": "22/31", "node": 2660, "naklon": 0 }, +{ "label": "22/32", "node": 2661, "naklon": 0 }, +{ "label": "22/32/1", "node": 3015, "naklon": 0 }, +{ "label": "22/33", "node": 2662, "naklon": 0 }, +{ "label": "22/34", "node": 2663, "naklon": 0 }, +{ "label": "22/35", "node": 2664, "naklon": 0 }, +{ "label": "22/36", "node": 2665, "naklon": 0 }, +{ "label": "22/37", "node": 2666, "naklon": 0 }, +{ "label": "22/38", "node": 2667, "naklon": 0 }, +{ "label": "22/39", "node": 2668, "naklon": 0 }, +{ "label": "22/40", "node": 2669, "naklon": null }, +{ "label": "22/41", "node": 2670, "naklon": null }, +{ "label": "22/42", "node": 2671, "naklon": null }, +{ "label": "23/9A", "node": 3087, "naklon": 10 }, +{ "label": "23/9B", "node": 3090, "naklon": 10 }, +{ "label": "23/1", "node": 3075, "naklon": 0 }, +{ "label": "23/2", "node": 3089, "naklon": 0 }, +{ "label": "23/3", "node": 3088, "naklon": 0 }, +{ "label": "23/4", "node": 3228, "naklon": 10 }, +{ "label": "23/5", "node": 2751, "naklon": 10 }, +{ "label": "23/6", "node": 3243, "naklon": 10 }, +{ "label": "23/7", "node": 4349, "naklon": 10 }, +{ "label": "23/8", "node": 3102, "naklon": 10 }, +{ "label": "23/10", "node": 3099, "naklon": 10 }, +{ "label": "23/11", "node": 3103, "naklon": 10 }, +{ "label": "23/12", "node": 3093, "naklon": 10 }, +{ "label": "23/13", "node": 3098, "naklon": 10 }, +{ "label": "23/14", "node": 3092, "naklon": 10 }, +{ "label": "23/15", "node": 3233, "naklon": 0 }, +{ "label": "23/16", "node": 3095, "naklon": 0 }, +{ "label": "23/17", "node": 4074, "naklon": 0 }, +{ "label": "23/18", "node": 2729, "naklon": 0 }, +{ "label": "23/19", "node": 3234, "naklon": 0 }, +{ "label": "23/20", "node": 3094, "naklon": 0 }, +{ "label": "23/21", "node": 2817, "naklon": 0 }, +{ "label": "23/22", "node": 3226, "naklon": 0 }, +{ "label": "23/23", "node": 3225, "naklon": 0 }, +{ "label": "23/24", "node": 3237, "naklon": 0 }, +{ "label": "23/25", "node": 4250, "naklon": 0 }, +{ "label": "23/26", "node": 3059, "naklon": 10 }, +{ "label": "23/27", "node": 3238, "naklon": 10 }, +{ "label": "23/28", "node": 3242, "naklon": 10 }, +{ "label": "23/29", "node": 3236, "naklon": 10 }, +{ "label": "23/30", "node": 3112, "naklon": 10 }, +{ "label": "23/31", "node": 3224, "naklon": 0 }, +{ "label": "23/32", "node": 4298, "naklon": 10 }, +{ "label": "23/33", "node": 4150, "naklon": 10 }, +{ "label": "23/34", "node": 3091, "naklon": 10 }, +{ "label": "25/1", "node": 3771, "naklon": 5 }, +{ "label": "25/2", "node": 3777, "naklon": 5 }, +{ "label": "25/3", "node": 3749, "naklon": 5 }, +{ "label": "25/4", "node": 3769, "naklon": 5 }, +{ "label": "25/5", "node": 3765, "naklon": 5 }, +{ "label": "25/6", "node": 3785, "naklon": 5 }, +{ "label": "25/7", "node": 3761, "naklon": 5 }, +{ "label": "25/8", "node": 3758, "naklon": 5 }, +{ "label": "25/9", "node": 3766, "naklon": 5 }, +{ "label": "25/10", "node": 3779, "naklon": 5 }, +{ "label": "25/11", "node": 3899, "naklon": 10 }, +{ "label": "25/12", "node": 3922, "naklon": 10 }, +{ "label": "25/13", "node": 3912, "naklon": 10 }, +{ "label": "25/14", "node": 3933, "naklon": 10 }, +{ "label": "25/15", "node": 3921, "naklon": 10 }, +{ "label": "25/16", "node": 4300, "naklon": 10 }, +{ "label": "25/17", "node": 3927, "naklon": 10 }, +{ "label": "25/18", "node": 3212, "naklon": 10 }, +{ "label": "25/19", "node": 3208, "naklon": 10 }, +{ "label": "25/20", "node": 3207, "naklon": 10 }, +{ "label": "25/21", "node": 4294, "naklon": 10 }, +{ "label": "25/22", "node": 3209, "naklon": 10 }, +{ "label": "25/23", "node": 3745, "naklon": 10 }, +{ "label": "25/24", "node": 3762, "naklon": 10 }, +{ "label": "25/25", "node": 3215, "naklon": 10 }, +{ "label": "25/26", "node": 3210, "naklon": 10 }, +{ "label": "25/27", "node": 3211, "naklon": 10 }, +{ "label": "25/28", "node": 3206, "naklon": 10 }, +{ "label": "25/29", "node": 3918, "naklon": 5 }, +{ "label": "25/30", "node": 3928, "naklon": 5 }, +{ "label": "25/31", "node": 3917, "naklon": 5 }, +{ "label": "25/32", "node": 4029, "naklon": 0 }, +{ "label": "25/33", "node": 4038, "naklon": 0 }, +{ "label": "25/34", "node": 4022, "naklon": 0 }, +{ "label": "25/35", "node": 3937, "naklon": 0 }, +{ "label": "25/36", "node": 3190, "naklon": 0 }, +{ "label": "25/37", "node": 3835, "naklon": 0 }, +{ "label": "25/38", "node": 3201, "naklon": 0 }, +{ "label": "25/39", "node": 3193, "naklon": 0 }, +{ "label": "25/40", "node": 3191, "naklon": 0 }, +{ "label": "25/41", "node": 3203, "naklon": 0 }, +{ "label": "25/42", "node": 4301, "naklon": 0 }, +{ "label": "25/43", "node": 3223, "naklon": 0 }, +{ "label": "25/44", "node": 3202, "naklon": 0 }, +{ "label": "25/45", "node": 3205, "naklon": 0 }, +{ "label": "25/46", "node": 3194, "naklon": 0 }, +{ "label": "25/47", "node": 3198, "naklon": 0 }, +{ "label": "25/48", "node": 3204, "naklon": 0 }, +{ "label": "25/49", "node": 3200, "naklon": 0 }, +{ "label": "25/50", "node": 3216, "naklon": 0 }, +{ "label": "25/51", "node": 3932, "naklon": 5 }, +{ "label": "25/52", "node": 3923, "naklon": 5 }, +{ "label": "25/53", "node": 3913, "naklon": 5 }, +{ "label": "25/54", "node": 3900, "naklon": 5 }, +{ "label": "25/55", "node": 4189, "naklon": 10 }, +{ "label": "25/56", "node": 4191, "naklon": 10 }, +{ "label": "25/57", "node": 3790, "naklon": 10 }, +{ "label": "25/58", "node": 4190, "naklon": 10 }, +{ "label": "25/59", "node": 4302, "naklon": 0 }, +{ "label": "25/60", "node": 4351, "naklon": 0 }, +{ "label": "25/61", "node": 4075, "naklon": 0 }, +{ "label": "25/62", "node": 4071, "naklon": 0 }, +{ "label": "25/63", "node": 3784, "naklon": 0 }, +{ "label": "25/64", "node": 4065, "naklon": 0 }, +{ "label": "25/65", "node": 4297, "naklon": 0 }, +{ "label": "25/66", "node": 4295, "naklon": 0 }, +{ "label": "25/67", "node": 4299, "naklon": 0 }, +{ "label": "25/68", "node": 3772, "naklon": 0 }, +{ "label": "25/69", "node": 3941, "naklon": 0 }, +{ "label": "25/70", "node": 3782, "naklon": 0 }, +{ "label": "25/71", "node": 4068, "naklon": 0 }, +{ "label": "25/72", "node": 4073, "naklon": 0 }, +{ "label": "25/73", "node": 3901, "naklon": 5 }, +{ "label": "25/74", "node": 4296, "naklon": 5 }, +{ "label": "25/75", "node": 3910, "naklon": 5 }, +{ "label": "25/76", "node": 4293, "naklon": 5 }, +{ "label": "25/77", "node": 3919, "naklon": 5 }, +{ "label": "25/78", "node": 3924, "naklon": 5 }, +{ "label": "25/79", "node": 3909, "naklon": 5 }, +{ "label": "25/80", "node": 3896, "naklon": 5 }, +{ "label": "25/81", "node": 3911, "naklon": 5 }, +{ "label": "25/82", "node": 2819, "naklon": 15 }, +{ "label": "25/83", "node": 3776, "naklon": 15 }, +{ "label": "25/84", "node": 3752, "naklon": 15 }, +{ "label": "25/85", "node": 4353, "naklon": 15 }, +{ "label": "25/86", "node": 3791, "naklon": 0 }, +{ "label": "25/87", "node": 3770, "naklon": 0 }, +{ "label": "25/88", "node": 3760, "naklon": 0 }, +{ "label": "25/89", "node": 3115, "naklon": 0 }, +{ "label": "25/90", "node": 3738, "naklon": 0 }, +{ "label": "25/91", "node": 3748, "naklon": 0 }, +{ "label": "25/92", "node": 3753, "naklon": 0 }, +{ "label": "25/93", "node": 3775, "naklon": 0 }, +{ "label": "25/94", "node": 3778, "naklon": 5 }, +{ "label": "25/95", "node": 4078, "naklon": 5 }, +{ "label": "25/96", "node": 4088, "naklon": 5 }, +{ "label": "25/97", "node": 3856, "naklon": 5 }, +{ "label": "25/98", "node": 4084, "naklon": 5 }, +{ "label": "25/99", "node": 4069, "naklon": 5 }, +{ "label": "25/100", "node": 4188, "naklon": 5 }, +{ "label": "25/101", "node": 4064, "naklon": 5 }, +{ "label": "25/102", "node": 3792, "naklon": 5 }, +{ "label": "25/103", "node": 3780, "naklon": 5 }, +{ "label": "25/104", "node": 4034, "naklon": 5 }, +{ "label": "25/105", "node": 4072, "naklon": 5 }, +{ "label": "25/106", "node": 3884, "naklon": 5 }, +{ "label": "25/107", "node": 3793, "naklon": 5 }, +{ "label": "25/108", "node": 3863, "naklon": 5 }, +{ "label": "25/109", "node": 3855, "naklon": 5 }, +{ "label": "33/1", "node": 3846, "naklon": 0 }, +{ "label": "33/2", "node": 3943, "naklon": 0 }, +{ "label": "33/3", "node": 3903, "naklon": 0 }, +{ "label": "33/4", "node": 3982, "naklon": 0 }, +{ "label": "33/5", "node": 3879, "naklon": 0 }, +{ "label": "33/6", "node": 3887, "naklon": 0 }, +{ "label": "33/7", "node": 3920, "naklon": 5 }, +{ "label": "33/8", "node": 3942, "naklon": 5 }, +{ "label": "33/9", "node": 3829, "naklon": null }, +{ "label": "34/79A", "node": 3452, "naklon": 6 }, +{ "label": "34/79B", "node": 3460, "naklon": 6 }, +{ "label": "34/90A", "node": 3443, "naklon": 6 }, +{ "label": "34/90B", "node": 3445, "naklon": 6 }, +{ "label": "34/90C", "node": 3457, "naklon": 6 }, +{ "label": "34/97A", "node": 3461, "naklon": 6 }, +{ "label": "34/97B", "node": 3463, "naklon": 6 }, +{ "label": "34/98A", "node": 3426, "naklon": 6 }, +{ "label": "34/98B", "node": 3444, "naklon": 6 }, +{ "label": "34/99A", "node": 3453, "naklon": 6 }, +{ "label": "34/99B", "node": 3455, "naklon": 6 }, +{ "label": "34/1", "node": 4009, "naklon": 0 }, +{ "label": "34/2", "node": 3602, "naklon": 0 }, +{ "label": "34/3", "node": 3441, "naklon": 0 }, +{ "label": "34/4", "node": 3464, "naklon": 0 }, +{ "label": "34/5", "node": 3883, "naklon": 0 }, +{ "label": "34/6", "node": 4098, "naklon": 0 }, +{ "label": "34/7", "node": 4003, "naklon": 0 }, +{ "label": "34/8", "node": 4004, "naklon": 0 }, +{ "label": "34/9", "node": 3888, "naklon": 0 }, +{ "label": "34/10", "node": 3997, "naklon": 0 }, +{ "label": "34/11", "node": 4006, "naklon": 0 }, +{ "label": "34/12", "node": 4000, "naklon": 0 }, +{ "label": "34/13", "node": 4011, "naklon": 0 }, +{ "label": "34/14", "node": 3999, "naklon": 0 }, +{ "label": "34/15", "node": 3981, "naklon": 0 }, +{ "label": "34/16", "node": 3988, "naklon": 0 }, +{ "label": "34/17", "node": 3986, "naklon": 0 }, +{ "label": "34/18", "node": 3998, "naklon": 0 }, +{ "label": "34/19", "node": 3983, "naklon": 0 }, +{ "label": "34/20", "node": 4005, "naklon": 0 }, +{ "label": "34/21", "node": 4001, "naklon": 0 }, +{ "label": "34/22", "node": 4008, "naklon": 0 }, +{ "label": "34/23", "node": 4002, "naklon": 0 }, +{ "label": "34/24", "node": 3996, "naklon": 0 }, +{ "label": "34/25", "node": 4007, "naklon": 0 }, +{ "label": "34/26", "node": 4113, "naklon": 15 }, +{ "label": "34/27", "node": 3595, "naklon": 5 }, +{ "label": "34/28", "node": 3599, "naklon": 5 }, +{ "label": "34/29", "node": 3601, "naklon": 5 }, +{ "label": "34/30", "node": 4205, "naklon": 0 }, +{ "label": "34/31", "node": 3987, "naklon": null }, +{ "label": "34/32", "node": 4214, "naklon": 0 }, +{ "label": "34/33", "node": 4226, "naklon": 0 }, +{ "label": "34/34", "node": 4209, "naklon": 0 }, +{ "label": "34/35", "node": 4201, "naklon": 0 }, +{ "label": "34/36", "node": 3440, "naklon": 0 }, +{ "label": "34/37", "node": 3465, "naklon": 0 }, +{ "label": "34/38", "node": 3446, "naklon": 0 }, +{ "label": "34/39", "node": 4039, "naklon": 5 }, +{ "label": "34/40", "node": 4057, "naklon": 5 }, +{ "label": "34/41", "node": 3985, "naklon": 0 }, +{ "label": "34/42", "node": 3882, "naklon": 0 }, +{ "label": "34/43", "node": 4040, "naklon": 5 }, +{ "label": "34/44", "node": 3231, "naklon": 0 }, +{ "label": "34/45", "node": 3227, "naklon": 0 }, +{ "label": "34/46", "node": 3431, "naklon": 0 }, +{ "label": "34/47", "node": 4013, "naklon": 0 }, +{ "label": "34/48", "node": 4045, "naklon": 0 }, +{ "label": "34/49", "node": 3949, "naklon": 0 }, +{ "label": "34/50", "node": 3953, "naklon": 0 }, +{ "label": "34/51", "node": 3952, "naklon": 0 }, +{ "label": "34/52", "node": 3995, "naklon": 0 }, +{ "label": "34/53", "node": 3992, "naklon": 0 }, +{ "label": "34/54", "node": 4198, "naklon": 0 }, +{ "label": "34/55", "node": 3935, "naklon": 0 }, +{ "label": "34/56", "node": 4050, "naklon": 0 }, +{ "label": "34/57", "node": 4049, "naklon": 0 }, +{ "label": "34/58", "node": 4054, "naklon": 0 }, +{ "label": "34/59", "node": 3663, "naklon": 6 }, +{ "label": "34/60", "node": 3661, "naklon": 6 }, +{ "label": "34/61", "node": 3664, "naklon": 6 }, +{ "label": "34/62", "node": 3660, "naklon": 6 }, +{ "label": "34/63", "node": 3662, "naklon": 6 }, +{ "label": "34/65", "node": 3665, "naklon": 6 }, +{ "label": "34/66", "node": 3667, "naklon": 6 }, +{ "label": "34/67", "node": 3675, "naklon": 6 }, +{ "label": "34/68", "node": 3666, "naklon": 6 }, +{ "label": "34/69", "node": 3652, "naklon": 6 }, +{ "label": "34/70", "node": 3458, "naklon": 6 }, +{ "label": "34/70/1", "node": 4425, "naklon": 6 }, +{ "label": "34/71", "node": 3459, "naklon": 6 }, +{ "label": "34/72", "node": 3435, "naklon": 6 }, +{ "label": "34/73", "node": 3448, "naklon": 6 }, +{ "label": "34/74", "node": 3451, "naklon": 6 }, +{ "label": "34/75", "node": 3442, "naklon": 6 }, +{ "label": "34/76", "node": 3449, "naklon": 6 }, +{ "label": "34/77", "node": 3450, "naklon": 6 }, +{ "label": "34/78", "node": 3433, "naklon": 6 }, +{ "label": "34/80", "node": 3432, "naklon": 12 }, +{ "label": "34/81", "node": 3470, "naklon": 12 }, +{ "label": "34/82", "node": 3438, "naklon": 12 }, +{ "label": "34/83", "node": 3439, "naklon": 12 }, +{ "label": "34/84", "node": 4028, "naklon": 5 }, +{ "label": "34/85", "node": 3596, "naklon": 5 }, +{ "label": "34/86", "node": 4021, "naklon": 5 }, +{ "label": "34/87", "node": 3437, "naklon": 12 }, +{ "label": "34/88", "node": 3428, "naklon": 12 }, +{ "label": "34/89", "node": 3430, "naklon": 12 }, +{ "label": "34/91", "node": 3454, "naklon": 6 }, +{ "label": "34/92", "node": 3492, "naklon": 6 }, +{ "label": "34/93", "node": 3462, "naklon": 6 }, +{ "label": "34/94", "node": 3427, "naklon": 6 }, +{ "label": "34/95", "node": 3434, "naklon": 6 }, +{ "label": "34/96", "node": 3456, "naklon": 6 }, +{ "label": "34/98/1", "node": 4307, "naklon": 6 }, +{ "label": "35/1", "node": 3968, "naklon": 0 }, +{ "label": "35/2", "node": 3969, "naklon": 0 }, +{ "label": "35/3", "node": 3947, "naklon": 0 }, +{ "label": "35/4", "node": 3979, "naklon": 0 }, +{ "label": "35/5", "node": 3959, "naklon": 0 }, +{ "label": "35/6", "node": 3948, "naklon": 0 }, +{ "label": "35/7", "node": 3961, "naklon": 0 }, +{ "label": "35/8", "node": 3956, "naklon": 0 }, +{ "label": "35/9", "node": 3604, "naklon": 0 }, +{ "label": "35/10", "node": 3944, "naklon": 0 }, +{ "label": "35/11", "node": 3960, "naklon": 0 }, +{ "label": "35/12", "node": 3958, "naklon": 0 }, +{ "label": "35/13", "node": 4036, "naklon": 5 }, +{ "label": "35/18", "node": 3893, "naklon": 5 }, +{ "label": "35/19", "node": 4108, "naklon": 5 }, +{ "label": "35/20", "node": 4017, "naklon": 5 }, +{ "label": "35/21", "node": 3963, "naklon": 0 }, +{ "label": "35/22", "node": 3658, "naklon": 0 }, +{ "label": "35/23", "node": 3975, "naklon": 0 }, +{ "label": "35/24", "node": 3980, "naklon": 0 }, +{ "label": "35/25", "node": 4012, "naklon": 0 }, +{ "label": "35/26", "node": 3655, "naklon": 0 }, +{ "label": "35/27", "node": 3962, "naklon": 0 }, +{ "label": "35/28", "node": 3945, "naklon": 0 }, +{ "label": "35/29", "node": 3569, "naklon": 0 }, +{ "label": "35/30", "node": 3429, "naklon": 0 }, +{ "label": "35/31", "node": 3657, "naklon": 0 }, +{ "label": "35/32", "node": 3646, "naklon": 0 }, +{ "label": "35/33", "node": 3622, "naklon": 0 }, +{ "label": "35/34", "node": 3612, "naklon": 0 }, +{ "label": "35/35", "node": 3955, "naklon": 0 }, +{ "label": "35/37", "node": 3878, "naklon": 0 }, +{ "label": "35/38", "node": 3965, "naklon": 0 }, +{ "label": "35/39", "node": 3970, "naklon": 0 }, +{ "label": "35/40", "node": 3611, "naklon": 0 }, +{ "label": "35/41", "node": 2635, "naklon": 0 }, +{ "label": "35/42", "node": 3978, "naklon": 0 }, +{ "label": "35/43", "node": 4213, "naklon": 0 }, +{ "label": "35/44", "node": 3984, "naklon": 0 }, +{ "label": "35/45", "node": 4218, "naklon": 0 }, +{ "label": "35/46", "node": 3973, "naklon": 0 }, +{ "label": "35/47", "node": 3974, "naklon": 0 }, +{ "label": "35/48", "node": 3759, "naklon": 0 }, +{ "label": "35/49", "node": 3844, "naklon": 0 }, +{ "label": "35/50", "node": 3804, "naklon": 0 }, +{ "label": "35/51", "node": 3831, "naklon": 0 }, +{ "label": "35/52", "node": 3643, "naklon": 0 }, +{ "label": "35/53", "node": 3966, "naklon": 0 }, +{ "label": "35/54", "node": 3971, "naklon": 0 }, +{ "label": "35/55", "node": 3650, "naklon": 6 }, +{ "label": "35/56", "node": 3651, "naklon": 6 }, +{ "label": "35/57", "node": 3669, "naklon": 6 }, +{ "label": "35/58", "node": 3648, "naklon": 6 }, +{ "label": "35/59", "node": 3645, "naklon": 6 }, +{ "label": "35/60", "node": 3659, "naklon": 6 }, +{ "label": "35/61", "node": 3647, "naklon": 6 }, +{ "label": "35/62", "node": 3644, "naklon": 6 }, +{ "label": "35/63", "node": 3671, "naklon": 6 }, +{ "label": "35/64", "node": 3682, "naklon": 6 }, +{ "label": "35/65", "node": 3672, "naklon": 6 }, +{ "label": "35/66", "node": 3683, "naklon": 6 }, +{ "label": "35/67", "node": 3673, "naklon": 6 }, +{ "label": "35/68", "node": 3674, "naklon": 6 }, +{ "label": "35/69", "node": 3679, "naklon": 6 }, +{ "label": "35/70", "node": 3649, "naklon": 6 }, +{ "label": "35/71", "node": 3687, "naklon": 6 }, +{ "label": "35/72", "node": 3677, "naklon": 6 }, +{ "label": "35/73", "node": 3690, "naklon": 6 }, +{ "label": "35/74", "node": 3691, "naklon": 6 }, +{ "label": "35/75", "node": 3676, "naklon": 6 }, +{ "label": "35/76", "node": 3680, "naklon": 6 }, +{ "label": "35/77", "node": 3668, "naklon": 6 }, +{ "label": "35/78", "node": 3681, "naklon": 6 }, +{ "label": "35/79", "node": 3670, "naklon": 6 }, +{ "label": "35/80", "node": 3689, "naklon": 6 }, +{ "label": "35/81", "node": 3678, "naklon": 6 }, +{ "label": "35/82", "node": 3693, "naklon": 6 }, +{ "label": "35/83", "node": 3654, "naklon": null }, +{ "label": "36/1", "node": 4086, "naklon": 0 }, +{ "label": "36/2", "node": 4085, "naklon": 0 }, +{ "label": "36/3", "node": 4083, "naklon": 0 }, +{ "label": "36/4", "node": 4087, "naklon": 0 }, +{ "label": "36/5", "node": 4077, "naklon": 0 }, +{ "label": "36/6", "node": 4082, "naklon": 0 }, +{ "label": "36/7", "node": 4186, "naklon": 0 }, +{ "label": "36/8", "node": 4206, "naklon": 0 }, +{ "label": "36/9", "node": 4080, "naklon": 0 }, +{ "label": "36/10", "node": 4081, "naklon": 0 }, +{ "label": "36/11", "node": 4210, "naklon": 0 }, +{ "label": "36/12", "node": 4079, "naklon": 0 }, +{ "label": "36/13", "node": 4076, "naklon": 0 }, +{ "label": "36/14", "node": 3852, "naklon": 0 }, +{ "label": "36/15", "node": 2813, "naklon": 0 }, +{ "label": "36/16", "node": 4219, "naklon": 0 }, +{ "label": "37/1A", "node": 3104, "naklon": 15 }, +{ "label": "37/1B", "node": 3121, "naklon": 15 }, +{ "label": "37/2", "node": 3113, "naklon": 10 }, +{ "label": "37/3", "node": 3118, "naklon": 10 }, +{ "label": "37/4", "node": 3111, "naklon": 10 }, +{ "label": "37/5", "node": 4020, "naklon": 10 }, +{ "label": "37/6", "node": 3119, "naklon": 10 }, +{ "label": "37/7", "node": 3110, "naklon": 10 }, +{ "label": "37/8", "node": 3108, "naklon": 10 }, +{ "label": "37/12", "node": 3107, "naklon": 0 }, +{ "label": "37/13", "node": 3199, "naklon": 0 }, +{ "label": "37/14", "node": 3120, "naklon": 0 }, +{ "label": "37/15", "node": 3122, "naklon": 0 }, +{ "label": "37/16", "node": 3908, "naklon": 0 }, +{ "label": "37/17", "node": 3114, "naklon": 0 }, +{ "label": "37/18", "node": 3105, "naklon": 0 }, +{ "label": "37/19", "node": 3116, "naklon": 0 }, +{ "label": "37/20", "node": 3106, "naklon": 0 }, +{ "label": "37/21", "node": 2887, "naklon": 5 }, +{ "label": "37/22", "node": 2888, "naklon": 5 }, +{ "label": "37/23", "node": 2877, "naklon": 5 }, +{ "label": "37/24", "node": 2891, "naklon": 5 }, +{ "label": "37/25", "node": 2886, "naklon": 5 }, +{ "label": "37/26", "node": 2892, "naklon": 5 }, +{ "label": "37/27", "node": 2882, "naklon": 5 }, +{ "label": "37/28", "node": 2883, "naklon": 5 }, +{ "label": "37/29", "node": 2876, "naklon": 5 }, +{ "label": "37/30", "node": 3109, "naklon": 5 }, +{ "label": "37/31", "node": 4152, "naklon": 5 }, +{ "label": "37/32", "node": 3117, "naklon": 5 }, +{ "label": "37/33", "node": 2870, "naklon": 5 }, +{ "label": "37/34", "node": 2867, "naklon": 0 }, +{ "label": "37/35", "node": 2865, "naklon": 0 }, +{ "label": "37/36", "node": 3096, "naklon": 0 }, +{ "label": "37/37", "node": 2871, "naklon": 0 }, +{ "label": "37/38", "node": 2884, "naklon": 0 }, +{ "label": "37/39", "node": 2855, "naklon": 0 }, +{ "label": "37/40", "node": 2878, "naklon": 0 }, +{ "label": "37/41", "node": 2889, "naklon": 0 }, +{ "label": "37/42", "node": 2879, "naklon": 0 }, +{ "label": "37/43", "node": 2850, "naklon": 0 }, +{ "label": "37/44", "node": 2894, "naklon": 0 }, +{ "label": "37/45", "node": 2880, "naklon": 0 }, +{ "label": "37/46", "node": 2893, "naklon": 0 }, +{ "label": "37/47", "node": 2890, "naklon": 0 }, +{ "label": "37/48", "node": 4355, "naklon": 0 }, +{ "label": "37/49", "node": 2885, "naklon": 0 }, +{ "label": "37/50", "node": 2875, "naklon": 0 }, +{ "label": "38/30A", "node": 3486, "naklon": 5 }, +{ "label": "38/30B", "node": 3714, "naklon": 0 }, +{ "label": "38/32A", "node": 3483, "naklon": 5 }, +{ "label": "38/32B", "node": 3496, "naklon": 0 }, +{ "label": "38/35A", "node": 3487, "naklon": 5 }, +{ "label": "38/35B", "node": 3498, "naklon": 5 }, +{ "label": "38/38A", "node": 3578, "naklon": 5 }, +{ "label": "38/38B", "node": 3508, "naklon": 5 }, +{ "label": "38/59A", "node": 3787, "naklon": 5 }, +{ "label": "38/59B", "node": 3491, "naklon": 5 }, +{ "label": "38/1", "node": 3568, "naklon": null }, +{ "label": "38/2", "node": 3502, "naklon": 0 }, +{ "label": "38/3", "node": 3836, "naklon": 0 }, +{ "label": "38/4", "node": 3588, "naklon": 0 }, +{ "label": "38/5", "node": 3493, "naklon": 0 }, +{ "label": "38/6", "node": 3580, "naklon": 0 }, +{ "label": "38/7", "node": 3572, "naklon": 0 }, +{ "label": "38/8", "node": 3506, "naklon": 0 }, +{ "label": "38/9", "node": 3503, "naklon": 0 }, +{ "label": "38/10", "node": 3579, "naklon": 0 }, +{ "label": "38/11", "node": 3586, "naklon": 0 }, +{ "label": "38/12", "node": 3495, "naklon": 5 }, +{ "label": "38/13", "node": 3492, "naklon": 5 }, +{ "label": "38/14", "node": 3532, "naklon": 5 }, +{ "label": "38/15", "node": 3574, "naklon": 5 }, +{ "label": "38/16", "node": 4140, "naklon": 5 }, +{ "label": "38/17", "node": 3795, "naklon": 5 }, +{ "label": "38/18", "node": 3788, "naklon": 5 }, +{ "label": "38/19", "node": 3796, "naklon": 5 }, +{ "label": "38/20", "node": 3797, "naklon": 5 }, +{ "label": "38/21", "node": 3798, "naklon": 5 }, +{ "label": "38/22", "node": 3786, "naklon": 5 }, +{ "label": "38/23", "node": 4067, "naklon": 5 }, +{ "label": "38/24", "node": 3773, "naklon": 5 }, +{ "label": "38/25", "node": 3774, "naklon": 5 }, +{ "label": "38/26", "node": 3789, "naklon": 5 }, +{ "label": "38/27", "node": 3520, "naklon": null }, +{ "label": "38/29", "node": 3577, "naklon": 5 }, +{ "label": "38/31", "node": 3530, "naklon": null }, +{ "label": "38/33", "node": 3488, "naklon": 5 }, +{ "label": "38/34", "node": 3505, "naklon": 5 }, +{ "label": "38/36", "node": 3497, "naklon": 5 }, +{ "label": "38/37", "node": 3490, "naklon": 5 }, +{ "label": "38/39", "node": 3585, "naklon": 5 }, +{ "label": "38/40", "node": 3582, "naklon": 5 }, +{ "label": "38/41", "node": 3507, "naklon": 5 }, +{ "label": "38/42", "node": 3484, "naklon": 5 }, +{ "label": "38/43", "node": 3501, "naklon": 5 }, +{ "label": "38/44", "node": 3581, "naklon": 5 }, +{ "label": "38/45", "node": 4192, "naklon": 5 }, +{ "label": "38/46", "node": 3576, "naklon": 5 }, +{ "label": "38/47", "node": 3489, "naklon": 5 }, +{ "label": "38/48", "node": 3573, "naklon": 5 }, +{ "label": "38/49", "node": 3504, "naklon": 5 }, +{ "label": "38/50", "node": 3794, "naklon": 5 }, +{ "label": "38/51", "node": 3485, "naklon": 5 }, +{ "label": "38/52", "node": 3482, "naklon": 5 }, +{ "label": "38/53", "node": 3575, "naklon": 5 }, +{ "label": "38/54", "node": 3499, "naklon": 5 }, +{ "label": "38/55", "node": 3494, "naklon": 5 }, +{ "label": "38/56", "node": 3583, "naklon": 5 }, +{ "label": "38/57", "node": 3570, "naklon": 5 }, +{ "label": "38/58", "node": 3500, "naklon": 0 }, +{ "label": "38/63", "node": 3510, "naklon": null }, +{ "label": "38/64", "node": 3512, "naklon": null }, +{ "label": "38/67", "node": 3535, "naklon": null }, +{ "label": "38/68", "node": 3531, "naklon": null }, +{ "label": "38/69", "node": 3537, "naklon": null }, +{ "label": "39/1", "node": 3522, "naklon": 10 }, +{ "label": "39/2", "node": 4018, "naklon": 10 }, +{ "label": "39/3", "node": 4019, "naklon": 10 }, +{ "label": "39/4", "node": 4154, "naklon": 5 }, +{ "label": "39/5", "node": 3907, "naklon": 5 }, +{ "label": "39/6", "node": 4148, "naklon": 0 }, +{ "label": "39/7", "node": 4153, "naklon": 0 }, +{ "label": "39/8", "node": 3938, "naklon": 0 }, +{ "label": "39/9", "node": 3802, "naklon": 0 }, +{ "label": "39/10", "node": 4015, "naklon": 0 }, +{ "label": "39/11", "node": 3929, "naklon": 0 }, +{ "label": "39/12", "node": 3946, "naklon": 0 }, +{ "label": "39/13", "node": 4014, "naklon": 0 }, +{ "label": "39/14", "node": 4155, "naklon": 0 }, +{ "label": "39/15", "node": 4149, "naklon": 0 }, +{ "label": "39/16", "node": 3642, "naklon": 0 }, +{ "label": "39/17", "node": 3636, "naklon": 5 }, +{ "label": "39/18", "node": 3991, "naklon": 0 }, +{ "label": "39/19", "node": 3994, "naklon": 0 }, +{ "label": "39/20", "node": 3990, "naklon": 0 }, +{ "label": "39/21", "node": 3967, "naklon": 0 }, +{ "label": "39/22", "node": 3977, "naklon": 0 }, +{ "label": "39/23", "node": 3757, "naklon": 15 }, +{ "label": "39/24", "node": 3633, "naklon": 15 }, +{ "label": "39/25", "node": 3744, "naklon": 15 }, +{ "label": "39/26", "node": 4023, "naklon": 5 }, +{ "label": "39/27", "node": 3720, "naklon": 5 }, +{ "label": "39/28", "node": 3734, "naklon": 5 }, +{ "label": "39/29", "node": 3741, "naklon": 5 }, +{ "label": "39/30", "node": 3721, "naklon": 5 }, +{ "label": "39/31", "node": 3845, "naklon": 0 }, +{ "label": "39/32", "node": 3840, "naklon": 0 }, +{ "label": "39/33", "node": 3837, "naklon": null }, +{ "label": "39/34", "node": 3839, "naklon": 0 }, +{ "label": "41/1", "node": 3542, "naklon": null }, +{ "label": "41/2", "node": 3566, "naklon": null }, +{ "label": "41/3", "node": 3548, "naklon": null }, +{ "label": "41/4", "node": 3515, "naklon": null }, +{ "label": "41/5", "node": 3559, "naklon": null }, +{ "label": "41/6", "node": 3509, "naklon": null }, +{ "label": "41/7", "node": 3524, "naklon": null }, +{ "label": "41/8", "node": 3518, "naklon": null }, +{ "label": "41/9", "node": 3182, "naklon": null }, +{ "label": "41/10", "node": 3187, "naklon": null }, +{ "label": "41/11", "node": 3195, "naklon": 0 }, +{ "label": "41/12", "node": 3857, "naklon": 0 }, +{ "label": "41/13", "node": 3183, "naklon": 0 }, +{ "label": "41/14", "node": 3177, "naklon": 0 }, +{ "label": "41/15", "node": 3189, "naklon": 0 }, +{ "label": "41/16", "node": 3186, "naklon": 0 }, +{ "label": "42/1", "node": 3178, "naklon": 0 }, +{ "label": "42/2", "node": 3219, "naklon": 0 }, +{ "label": "42/3", "node": 3475, "naklon": 0 }, +{ "label": "42/4", "node": 3175, "naklon": 0 }, +{ "label": "42/5", "node": 3222, "naklon": 0 }, +{ "label": "42/6", "node": 3221, "naklon": 0 }, +{ "label": "42/7", "node": 3181, "naklon": 0 }, +{ "label": "42/8", "node": 3180, "naklon": 0 }, +{ "label": "42/9", "node": 3218, "naklon": 0 }, +{ "label": "42/10", "node": 3176, "naklon": 0 }, +{ "label": "42/11", "node": 3174, "naklon": 0 }, +{ "label": "42/12", "node": 3220, "naklon": 0 }, +{ "label": "42/13", "node": 3533, "naklon": null }, +{ "label": "42/14", "node": 3543, "naklon": null }, +{ "label": "42/15", "node": 3554, "naklon": null }, +{ "label": "42/16", "node": 3549, "naklon": null }, +{ "label": "43/1", "node": 2857, "naklon": 5 }, +{ "label": "43/2", "node": 2752, "naklon": 5 }, +{ "label": "43/3", "node": 2753, "naklon": 5 }, +{ "label": "43/4", "node": 3024, "naklon": 5 }, +{ "label": "43/5", "node": 2754, "naklon": 5 }, +{ "label": "43/6", "node": 4423, "naklon": 5 }, +{ "label": "43/7", "node": 4368, "naklon": 5 }, +{ "label": "43/8", "node": 2978, "naklon": 5 }, +{ "label": "43/9", "node": 2868, "naklon": 5 }, +{ "label": "43/10", "node": 4377, "naklon": 5 }, +{ "label": "43/11", "node": 2757, "naklon": 5 }, +{ "label": "43/12", "node": 2970, "naklon": 5 }, +{ "label": "43/13", "node": 2758, "naklon": 5 }, +{ "label": "43/14", "node": 4378, "naklon": 5 }, +{ "label": "43/15", "node": 2759, "naklon": 5 }, +{ "label": "43/16", "node": 4342, "naklon": 5 }, +{ "label": "43/17", "node": 3026, "naklon": null }, +{ "label": "43/18", "node": 2986, "naklon": null }, +{ "label": "43/19", "node": 4343, "naklon": null }, +{ "label": "43/20", "node": 2760, "naklon": null }, +{ "label": "43/21", "node": 4379, "naklon": null }, +{ "label": "43/22", "node": 2971, "naklon": null }, +{ "label": "43/23", "node": 2761, "naklon": null }, +{ "label": "43/24", "node": 2762, "naklon": null }, +{ "label": "43/25", "node": 4339, "naklon": null }, +{ "label": "43/26", "node": 4380, "naklon": null }, +{ "label": "43/27", "node": 2975, "naklon": null }, +{ "label": "43/28", "node": 3003, "naklon": null }, +{ "label": "43/29", "node": 4338, "naklon": null }, +{ "label": "43/30", "node": 3002, "naklon": null }, +{ "label": "43/31", "node": 4345, "naklon": null }, +{ "label": "43/32", "node": 2979, "naklon": null }, +{ "label": "43/33", "node": 2989, "naklon": null }, +{ "label": "43/34", "node": 2996, "naklon": null }, +{ "label": "43/35", "node": 2972, "naklon": null }, +{ "label": "43/36", "node": 2988, "naklon": null }, +{ "label": "43/37", "node": 4344, "naklon": null }, +{ "label": "43/38", "node": 3022, "naklon": null }, +{ "label": "43/39", "node": 4341, "naklon": null }, +{ "label": "43/40", "node": 2983, "naklon": null }, +{ "label": "43/41", "node": 2995, "naklon": null }, +{ "label": "43/42", "node": 2763, "naklon": null }, +{ "label": "43/43", "node": 2764, "naklon": null }, +{ "label": "43/44", "node": 2765, "naklon": null }, +{ "label": "43/45", "node": 2766, "naklon": null }, +{ "label": "43/46", "node": 2767, "naklon": null }, +{ "label": "43/47", "node": 2768, "naklon": null }, +{ "label": "43/48", "node": 3018, "naklon": null }, +{ "label": "43/49", "node": 2982, "naklon": null }, +{ "label": "43/50", "node": 3019, "naklon": 0 }, +{ "label": "43/51", "node": 3013, "naklon": null }, +{ "label": "43/52", "node": 3007, "naklon": null }, +{ "label": "43/53", "node": 2980, "naklon": null }, +{ "label": "43/54", "node": 3011, "naklon": null }, +{ "label": "43/55", "node": 2672, "naklon": null }, +{ "label": "43/56", "node": 2673, "naklon": null }, +{ "label": "43/57", "node": 2674, "naklon": null }, +{ "label": "43/58", "node": 2675, "naklon": null }, +{ "label": "43/59", "node": 2676, "naklon": null }, +{ "label": "43/60", "node": 2677, "naklon": null }, +{ "label": "43/61", "node": 2678, "naklon": null }, +{ "label": "43/62", "node": 2679, "naklon": null }, +{ "label": "43/63", "node": 2680, "naklon": null }, +{ "label": "43/64", "node": 2840, "naklon": null }, +{ "label": "43/65", "node": 2682, "naklon": null }, +{ "label": "43/66", "node": 2683, "naklon": null }, +{ "label": "43/67", "node": 2684, "naklon": 0 }, +{ "label": "43/68", "node": 2685, "naklon": null }, +{ "label": "43/69", "node": 2686, "naklon": null }, +{ "label": "43/70", "node": 2687, "naklon": null }, +{ "label": "43/71", "node": 2688, "naklon": null }, +{ "label": "43/72", "node": 2689, "naklon": null }, +{ "label": "43/73", "node": 2690, "naklon": null }, +{ "label": "43/74", "node": 2691, "naklon": null }, +{ "label": "43/75", "node": 2692, "naklon": null }, +{ "label": "43/76", "node": 2693, "naklon": 0 }, +{ "label": "43/77", "node": 2694, "naklon": null }, +{ "label": "43/78", "node": 2695, "naklon": null }, +{ "label": "43/79", "node": 2696, "naklon": 0 }, +{ "label": "43/80", "node": 2697, "naklon": null }, +{ "label": "43/81", "node": 2698, "naklon": 0 }, +{ "label": "43/82", "node": 2699, "naklon": null }, +{ "label": "43/83", "node": 2700, "naklon": 0 }, +{ "label": "43/84", "node": 2744, "naklon": null }, +{ "label": "43/85", "node": 2745, "naklon": 0 }, +{ "label": "43/86", "node": 2746, "naklon": null }, +{ "label": "43/87", "node": 2747, "naklon": 0 }, +{ "label": "43/88", "node": 2748, "naklon": null }, +{ "label": "43/89", "node": 2749, "naklon": 0 }, +{ "label": "43/90", "node": 2841, "naklon": null }, +{ "label": "45/1", "node": 4237, "naklon": 5 }, +{ "label": "45/2", "node": 4226, "naklon": 5 }, +{ "label": "45/3", "node": 4242, "naklon": 5 }, +{ "label": "45/4", "node": 4179, "naklon": 5 }, +{ "label": "45/5", "node": 4247, "naklon": 5 }, +{ "label": "45/6", "node": 4245, "naklon": 5 }, +{ "label": "45/7", "node": 3872, "naklon": 5 }, +{ "label": "45/8", "node": 4175, "naklon": 5 }, +{ "label": "45/9", "node": 4236, "naklon": 5 }, +{ "label": "45/10", "node": 4170, "naklon": 5 }, +{ "label": "45/11", "node": 4238, "naklon": 5 }, +{ "label": "45/12", "node": 4246, "naklon": 5 }, +{ "label": "45/13", "node": 4166, "naklon": 5 }, +{ "label": "45/14", "node": 4227, "naklon": 5 }, +{ "label": "45/15", "node": 4171, "naklon": 5 }, +{ "label": "45/16", "node": 4180, "naklon": 5 }, +{ "label": "45/17", "node": 4244, "naklon": 5 }, +{ "label": "45/18", "node": 4199, "naklon": 5 }, +{ "label": "45/19", "node": 4239, "naklon": 5 }, +{ "label": "45/20", "node": 4207, "naklon": 5 }, +{ "label": "45/21", "node": 4223, "naklon": 5 }, +{ "label": "45/22", "node": 4230, "naklon": 5 }, +{ "label": "45/23", "node": 4233, "naklon": 5 }, +{ "label": "45/24", "node": 4222, "naklon": 5 }, +{ "label": "45/25", "node": 4217, "naklon": 5 }, +{ "label": "45/26", "node": 4243, "naklon": 5 }, +{ "label": "45/27", "node": 4200, "naklon": 5 }, +{ "label": "45/28", "node": 4228, "naklon": 5 }, +{ "label": "45/29", "node": 4211, "naklon": 5 }, +{ "label": "45/30", "node": 4234, "naklon": 5 }, +{ "label": "45/31", "node": 4235, "naklon": 5 }, +{ "label": "45/32", "node": 4203, "naklon": 5 }, +{ "label": "45/33", "node": 4240, "naklon": 5 }, +{ "label": "45/34", "node": 4224, "naklon": 5 }, +{ "label": "45/35", "node": 4232, "naklon": 5 }, +{ "label": "45/36", "node": 4231, "naklon": 5 }, +{ "label": "45/37", "node": 4161, "naklon": 5 }, +{ "label": "45/38", "node": 4225, "naklon": 5 }, +{ "label": "45/39", "node": 4241, "naklon": 5 }, +{ "label": "45/40", "node": 4229, "naklon": 5 }, +{ "label": "45/41", "node": 4221, "naklon": 5 }, +{ "label": "45/42", "node": 4212, "naklon": 5 }, +{ "label": "45/43", "node": 4216, "naklon": 5 }, +{ "label": "45/44", "node": 3864, "naklon": null }, +{ "label": "46/1", "node": 3806, "naklon": 5 }, +{ "label": "46/2", "node": 3813, "naklon": 5 }, +{ "label": "46/3", "node": 3815, "naklon": 5 }, +{ "label": "46/4", "node": 3807, "naklon": 5 }, +{ "label": "46/5", "node": 3895, "naklon": 5 }, +{ "label": "46/6", "node": 3809, "naklon": 5 }, +{ "label": "46/7", "node": 3820, "naklon": 5 }, +{ "label": "46/8", "node": 3805, "naklon": 5 }, +{ "label": "46/9", "node": 3894, "naklon": 0 }, +{ "label": "46/10", "node": 4055, "naklon": 0 }, +{ "label": "46/11", "node": 3812, "naklon": 5 }, +{ "label": "46/12", "node": 3822, "naklon": 5 }, +{ "label": "46/13", "node": 3821, "naklon": 5 }, +{ "label": "46/14", "node": 3808, "naklon": 5 }, +{ "label": "46/15", "node": 3799, "naklon": 5 }, +{ "label": "46/16", "node": 3816, "naklon": 5 }, +{ "label": "46/17", "node": 3751, "naklon": 5 }, +{ "label": "46/18", "node": 3814, "naklon": 5 }, +{ "label": "46/19", "node": 4044, "naklon": 0 }, +{ "label": "46/20", "node": 3931, "naklon": 0 }, +{ "label": "46/21", "node": 3902, "naklon": 5 }, +{ "label": "46/22", "node": 3916, "naklon": 5 }, +{ "label": "46/23", "node": 3892, "naklon": 5 }, +{ "label": "46/24", "node": 3914, "naklon": 5 }, +{ "label": "46/25", "node": 3898, "naklon": 5 }, +{ "label": "46/26", "node": 3897, "naklon": 5 }, +{ "label": "46/27", "node": 3885, "naklon": 5 }, +{ "label": "46/28", "node": 3906, "naklon": 5 }, +{ "label": "46/29", "node": 3930, "naklon": 0 }, +{ "label": "46/30", "node": 3936, "naklon": 0 }, +{ "label": "46/31", "node": 3860, "naklon": 5 }, +{ "label": "46/32", "node": 3841, "naklon": 5 }, +{ "label": "46/33", "node": 3873, "naklon": 5 }, +{ "label": "46/34", "node": 3854, "naklon": 5 }, +{ "label": "46/35", "node": 3939, "naklon": 5 }, +{ "label": "46/36", "node": 3858, "naklon": 5 }, +{ "label": "46/37", "node": 3940, "naklon": 5 }, +{ "label": "46/38", "node": 4035, "naklon": 5 }, +{ "label": "47/1", "node": 3373, "naklon": 0 }, +{ "label": "47/2", "node": 3374, "naklon": 0 }, +{ "label": "47/3", "node": 3384, "naklon": 0 }, +{ "label": "47/4", "node": 3385, "naklon": 0 }, +{ "label": "48/1", "node": 4051, "naklon": 5 }, +{ "label": "48/2", "node": 4041, "naklon": 5 }, +{ "label": "48/3", "node": 4056, "naklon": 5 }, +{ "label": "48/4", "node": 3875, "naklon": 5 }, +{ "label": "48/5", "node": 4061, "naklon": 5 }, +{ "label": "48/6", "node": 4047, "naklon": 5 }, +{ "label": "48/7", "node": 4060, "naklon": 5 }, +{ "label": "48/8", "node": 4059, "naklon": 5 }, +{ "label": "48/9", "node": 4058, "naklon": 5 }, +{ "label": "48/10", "node": 3635, "naklon": 5 }, +{ "label": "48/11", "node": 3640, "naklon": 5 }, +{ "label": "48/12", "node": 3747, "naklon": 5 }, +{ "label": "48/13", "node": 3629, "naklon": 5 }, +{ "label": "48/14", "node": 4048, "naklon": 5 }, +{ "label": "48/15", "node": 4063, "naklon": 5 }, +{ "label": "48/16", "node": 4062, "naklon": 5 }, +{ "label": "48/17", "node": 4043, "naklon": 5 }, +{ "label": "48/18", "node": 4052, "naklon": 5 }, +{ "label": "48/19", "node": 4042, "naklon": 5 }, +{ "label": "48/20", "node": 4053, "naklon": 5 }, +{ "label": "50/15A", "node": 4167, "naklon": null }, +{ "label": "50/15B", "node": 4159, "naklon": null }, +{ "label": "50/1", "node": 4183, "naklon": 0 }, +{ "label": "50/2", "node": 4157, "naklon": 0 }, +{ "label": "50/3", "node": 4160, "naklon": 0 }, +{ "label": "50/4", "node": 4173, "naklon": 0 }, +{ "label": "50/5", "node": 4177, "naklon": 0 }, +{ "label": "50/6", "node": 4174, "naklon": 0 }, +{ "label": "50/7", "node": 4178, "naklon": 0 }, +{ "label": "50/8", "node": 4195, "naklon": 0 }, +{ "label": "50/9", "node": 4169, "naklon": 0 }, +{ "label": "50/10", "node": 4162, "naklon": 0 }, +{ "label": "50/11", "node": 4158, "naklon": 0 }, +{ "label": "50/12", "node": 4182, "naklon": 0 }, +{ "label": "50/13", "node": 4194, "naklon": 0 }, +{ "label": "50/14", "node": 4184, "naklon": 0 }, +{ "label": "50/16", "node": 4197, "naklon": null }, +{ "label": "50/17", "node": 4164, "naklon": null }, +{ "label": "50/18", "node": 3306, "naklon": null }, +{ "label": "50/19", "node": 4168, "naklon": null }, +{ "label": "50/20", "node": 4193, "naklon": null }, +{ "label": "50/21", "node": 4187, "naklon": null }, +{ "label": "50/22", "node": 4163, "naklon": null }, +{ "label": "50/23", "node": 4165, "naklon": null }, +{ "label": "50/24", "node": 4185, "naklon": null }, +{ "label": "50/25", "node": 3904, "naklon": null }, +{ "label": "53/1", "node": 2619, "naklon": 0 }, +{ "label": "53/2", "node": 2623, "naklon": 0 }, +{ "label": "53/3", "node": 2617, "naklon": 0 }, +{ "label": "53/4", "node": 2622, "naklon": 0 }, +{ "label": "53/5", "node": 2618, "naklon": 0 }, +{ "label": "53/6", "node": 2626, "naklon": 0 }, +{ "label": "53/7", "node": 2869, "naklon": 0 }, +{ "label": "53/8", "node": 2613, "naklon": 0 }, +{ "label": "53/9", "node": 2608, "naklon": 0 }, +{ "label": "53/10", "node": 2611, "naklon": 0 }, +{ "label": "53/11", "node": 2598, "naklon": 0 }, +{ "label": "53/12", "node": 3528, "naklon": 0 }, +{ "label": "53/13", "node": 3545, "naklon": 0 }, +{ "label": "53/14", "node": 2620, "naklon": 0 }, +{ "label": "53/15", "node": 2612, "naklon": 0 }, +{ "label": "53/16", "node": 2615, "naklon": 0 }, +{ "label": "53/17", "node": 3722, "naklon": 0 }, +{ "label": "53/18", "node": 2624, "naklon": 0 }, +{ "label": "53/19", "node": 2609, "naklon": 0 }, +{ "label": "53/20", "node": 2625, "naklon": 0 }, +{ "label": "53/21", "node": 2602, "naklon": 0 }, +{ "label": "53/22", "node": 2610, "naklon": 0 }, +{ "label": "53/23", "node": 2599, "naklon": 0 }, +{ "label": "53/24", "node": 2605, "naklon": 0 }, +{ "label": "53/25", "node": 2593, "naklon": 0 }, +{ "label": "53/26", "node": 3074, "naklon": 0 }, +{ "label": "53/27", "node": 2740, "naklon": 0 }, +{ "label": "53/28", "node": 2614, "naklon": 0 }, +{ "label": "53/29", "node": 2601, "naklon": 0 }, +{ "label": "53/30", "node": 4196, "naklon": 0 }, +{ "label": "53/31", "node": 2607, "naklon": 0 }, +{ "label": "53/32", "node": 2582, "naklon": 0 }, +{ "label": "53/33", "node": 2594, "naklon": 0 }, +{ "label": "53/34", "node": 2589, "naklon": 0 }, +{ "label": "53/35", "node": 2596, "naklon": 0 }, +{ "label": "53/36", "node": 2603, "naklon": 0 }, +{ "label": "53/37", "node": 2597, "naklon": 0 }, +{ "label": "53/38", "node": 2590, "naklon": 0 }, +{ "label": "53/39", "node": 2581, "naklon": 0 }, +{ "label": "53/40", "node": 2583, "naklon": 0 }, +{ "label": "53/41", "node": 2580, "naklon": 0 }, +{ "label": "53/42", "node": 2579, "naklon": 0 }, +{ "label": "53/43", "node": 2797, "naklon": 0 }, +{ "label": "53/44", "node": 2577, "naklon": 0 }, +{ "label": "53/45", "node": 2586, "naklon": 0 }, +{ "label": "53/46", "node": 2588, "naklon": 0 }, +{ "label": "53/47", "node": 2591, "naklon": 0 }, +{ "label": "53/48", "node": 2592, "naklon": 0 }, +{ "label": "53/49", "node": 2573, "naklon": 0 }, +{ "label": "53/50", "node": 2595, "naklon": 0 }, +{ "label": "53/51", "node": 2587, "naklon": 0 }, +{ "label": "53/52", "node": 2578, "naklon": 0 }, +{ "label": "53/53", "node": 2574, "naklon": 0 }, +{ "label": "53/54", "node": 2571, "naklon": 0 }, +{ "label": "53/55", "node": 2570, "naklon": 0 }, +{ "label": "53/56", "node": 2576, "naklon": 0 }, +{ "label": "53/57", "node": 2881, "naklon": 0 }, +{ "label": "53/58", "node": 2575, "naklon": 0 }, +{ "label": "53/59", "node": 2572, "naklon": 0 }, +{ "label": "53/60", "node": 2569, "naklon": 0 }, +{ "label": "55/1", "node": 4324, "naklon": 0 }, +{ "label": "55/2", "node": 4319, "naklon": 0 }, +{ "label": "55/3", "node": 4327, "naklon": 0 }, +{ "label": "55/4", "node": 4333, "naklon": 0 }, +{ "label": "55/5", "node": 4332, "naklon": 0 }, +{ "label": "55/6", "node": 4320, "naklon": 0 }, +{ "label": "55/7", "node": 4317, "naklon": 0 }, +{ "label": "55/8", "node": 4318, "naklon": 0 }, +{ "label": "55/9", "node": 4328, "naklon": 0 }, +{ "label": "55/10", "node": 4323, "naklon": 0 }, +{ "label": "55/11", "node": 4325, "naklon": 0 }, +{ "label": "55/12", "node": 4326, "naklon": 0 }, +{ "label": "55/13", "node": 4316, "naklon": 0 }, +{ "label": "55/14", "node": 4322, "naklon": 0 }, +{ "label": "55/15", "node": 4331, "naklon": 0 }, +{ "label": "55/16", "node": 4321, "naklon": 0 }, +{ "label": "55/17", "node": 4315, "naklon": 0 }, +{ "label": "55/18", "node": 4329, "naklon": 0 }, +{ "label": "55/19", "node": 4334, "naklon": 0 }, +{ "label": "55/20", "node": 4330, "naklon": 0 } +]; + +module.exports = { naklony }; diff --git a/RVO4/databases/modbus_config.js b/RVO4/databases/modbus_config.js new file mode 100755 index 0000000..b73116a --- /dev/null +++ b/RVO4/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/RVO4/databases/nodes.table b/RVO4/databases/nodes.table new file mode 100755 index 0000000..0f4ee51 --- /dev/null +++ b/RVO4/databases/nodes.table @@ -0,0 +1 @@ +node:number|pole_number:string|node_type:string|tbname:string|line:number|profile:string|processed:boolean|status:boolean|time_of_last_communication:number \ No newline at end of file diff --git a/RVO4/databases/nodes_original/nodes_original.table b/RVO4/databases/nodes_original/nodes_original.table new file mode 100755 index 0000000..0637a08 --- /dev/null +++ b/RVO4/databases/nodes_original/nodes_original.table @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/RVO4/databases/notifications.table b/RVO4/databases/notifications.table new file mode 100755 index 0000000..f7c96cb --- /dev/null +++ b/RVO4/databases/notifications.table @@ -0,0 +1,41 @@ +key:string|weight:string|sk:string|en:string ++|switching_profile_point_applied_to_line|INFORMATIONAL|Aplikovaný bod spínacieho profilu na línií č. ${line} : ${value}|Switching profile point applied to line no. ${line} : ${value}|............... ++|dusk_has_occured|INFORMATIONAL|Nastal súmrak: ${value}|Dusk has occured: ${value}|............... ++|dawn_has_occured|INFORMATIONAL|Nastal úsvit: ${value}|Dawn has occured: ${value}|............... ++|dimming_profile_was_successfully_received_by_node|NOTICE|Stmievací profil bol úspešne prijatý nodom č. ${node}|Dimming profile was successfully received by node no. ${node}|............... ++|master_node_is_responding_again|NOTICE|Master node začal znovu odpovedať|Master node is responding again|............... ++|command_was_sent_from_terminal_interface|DEBUG|Z terminálu bol odoslaný príkaz|A command was sent from terminal interface|............... ++|master_node_is_not_responding|ALERT|Master node neodpovedá|Master node is not responding|............... ++|configuration_of_dimming_profile_to_node_failed|ALERT|Konfigurácia stmievacieho profilu pre node č. ${node} zlyhala|Configuration of dimming profile to node no. ${node} has failed|............... ++|circuit_breaker_was_turned_on_line|NOTICE|Zapnutie ističa na línii č. ${line}|Circuit breaker was turned on - line no. ${line}|............... ++|circuit_breaker_was_turned_off_line|ERROR|Vypnutie ističa na línií č. ${line}|Circuit breaker was turned off - line no. ${line}|............... ++|dimming_profile_was_processed_for_node|INFORMATIONAL|Stmievací profil bol spracovaný pre node č. ${node}|Dimming profile was processed for node no. ${node}|............... ++|switching_profile_was_processed_for_line|INFORMATIONAL|Spínací profil bol spracovaný pre líniu č. ${line}|Switching profile was processed for line no. ${line}|............... ++|thermometer_is_not_responding|WARNING|Teplomer neodpovedá|Thermometer is not responding|............... ++|thermometer_is_responding_again|NOTICE|Teplomer znovu odpovedá|Thermometer is responding again|............... ++|thermometer_sends_invalid_data|WARNING|Teplomer posiela neplatné hodnoty|Thermometer sends invalid data|............... ++|main_switch_has_been_turned_off|CRITICAL|Hlavný vypínač bol vypnutý|Main switch has been turned off|............... ++|main_switch_has_been_turned_on|NOTICE|Hlavný vypínač bol zapnutý|Main switch has been turned on|............... ++|power_supply_has_disconnected_input|ALERT|Napájací zdroj nemá napätie na vstupe|Power supply has disconnected input|............... ++|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_main_open|NOTICE|Hlavné dvere boli otvorené|Main door has been opened|............... ++|door_em_open|NOTICE|Dvere silovej časti boli otvorené|Power door has been opened|............... ++|door_main_open_without_permission|WARNING|Hlavné dvere boli otvorené bez povolenia - zapnutá siréna|Main door has been opened without permission - alarm is on|............... ++|door_em_open_without_permission|WARNING|Dvere silovej časti boli otvorené bez povolenia|Power door has been opened without permission|............... ++|door_main_close|NOTICE|Hlavné dvere boli zatvorené|Main door has been closed|............... ++|door_em_close|NOTICE|Dvere silovej časti boli zatvorené|Power door has been closed|............... ++|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|............... ++|electrometer_ok|NOTICE|Elektromer znovu odpovedá|Electrometer is responding again|............... ++|no_voltage_on_phase|CRITICAL|Na fáze č. ${phase} nie je napätie|No voltage detected on phase no. ${phase}|............... ++|voltage_on_phase_restored|NOTICE|Napätie na fáze č. ${phase} bolo obnovené|Voltage on phase no. ${phase} has been restored|............... ++|flow_start|NOTICE|FLOW bol spustený|FLOW has been started |............... ++|twilight_sensor_nok|ERROR|Sensor súmraku neodpovedá|Twilight sensor is not responding|............... ++|twilight_sensor_ok|NOTICE|Sensor súmraku znovu odpovedá|Twilight sensor is responding again|............... ++|lamps_have_turned_on|NOTICE|Lampy sa zapli|Lamps have turned on|............... ++|lamps_have_turned_off|NOTICE|Lampy sa vypli|Lamps have turned off|............... ++|flow_restart|NOTICE|FLOW bol reštartovaný|FLOW has been restarted|............... ++|nodes_db_changed|NOTICE|Zmena v node databáze|Node db has changed|............... diff --git a/RVO4/databases/pins.table b/RVO4/databases/pins.table new file mode 100755 index 0000000..0eb3d05 --- /dev/null +++ b/RVO4/databases/pins.table @@ -0,0 +1,14 @@ +pin:string|type:string|line:number +*|input1_01|door_condition|0|........... +*|input1_02|rotary_switch_state|0|........... +*|input1_03|rotary_switch_state|0|........... +*|input1_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/RVO4/databases/relays.table b/RVO4/databases/relays.table new file mode 100755 index 0000000..999fda8 --- /dev/null +++ b/RVO4/databases/relays.table @@ -0,0 +1,5 @@ +line:number|tbname:string|contactor:number|profile:string ++|0|d5xjWYMwEJon6rLlK7yE9Q7qgV4DaOeNB9ZX3Gzb|1||........... ++|1|52dD6ZlV1QaOpRBmbAqK4rkKnGzWMLj4eJq38Pgo|9|{"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|rDbQ84xzwgdqEoPm3kbJjZk9anOZY1RXyBv2LVM6|9|{"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|E6Kg9oDnLWyzPRMva7vrow7Jxp4VG58qO2w1lZYe|9|{"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/RVO4/databases/settings.table b/RVO4/databases/settings.table new file mode 100755 index 0000000..2cc6054 --- /dev/null +++ b/RVO4/databases/settings.table @@ -0,0 +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|project_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|cloud_topic:string|has_main_switch:boolean|daily_report:boolean|send_changed_node_numbers:boolean ++|rvo_senica_4_10.0.0.136|en|28.4327950E0000|48.70826502|17.28455203|192.168.252.1|rvo_senica_4_10.0.0.136|e2pmiokiydRjmeD5TgRP|1883|0|72|unipi|ttyUSB0|1|20|5|6|3|u136|0|1|1|................................................... diff --git a/RVO4/databases/tbdata.nosql b/RVO4/databases/tbdata.nosql new file mode 100755 index 0000000..a4e9774 --- /dev/null +++ b/RVO4/databases/tbdata.nosql @@ -0,0 +1,4 @@ +-"d5xjWYMwEJon6rLlK7yE9Q7qgV4DaOeNB9ZX3Gzb":[{"ts":1760521973690,"values":{"_event":{"type":"notice","status":"new","source":{"func":"modbus_reader","component":"1699965957410","component_name":"Modbus reader","edge":"d5xjWYMwEJon6rLlK7yE9Q7qgV4DaOeNB9ZX3Gzb"},"message":{"sk":"rvo_senica_4_10.0.0.136: FLOW bol reštartovaný","en":"rvo_senica_4_10.0.0.136: FLOW has been restarted"},"message_data":""}}}],"id":"3000173001jj71b"} +-"d5xjWYMwEJon6rLlK7yE9Q7qgV4DaOeNB9ZX3Gzb":[{"ts":1760521973764,"values":{"edge_fw_version":"2025-10-08","maintenance_mode":false}}],"id":"3000173002jj70b"} +-"d5xjWYMwEJon6rLlK7yE9Q7qgV4DaOeNB9ZX3Gzb":[{"ts":1760521973777,"values":{"statecode":2,"power_mode":"Automatic"}}],"id":"3000173004jj70b"} +-"d5xjWYMwEJon6rLlK7yE9Q7qgV4DaOeNB9ZX3Gzb":[{"ts":1760521973805,"values":{"_event":{"type":"notice","status":"new","source":{"func":"rsPort.open()","component":"1699963668903","component_name":"DIDO_Controller","edge":"d5xjWYMwEJon6rLlK7yE9Q7qgV4DaOeNB9ZX3Gzb"},"message":{"sk":"rvo_senica_4_10.0.0.136: FLOW bol spustený","en":"rvo_senica_4_10.0.0.136: FLOW has been started "},"message_data":""}}}],"id":"3000173006jj70b"} diff --git a/RVO4/databases/tbdatacloud.nosql b/RVO4/databases/tbdatacloud.nosql new file mode 100755 index 0000000..e642556 --- /dev/null +++ b/RVO4/databases/tbdatacloud.nosql @@ -0,0 +1,3 @@ +-"d5xjWYMwEJon6rLlK7yE9Q7qgV4DaOeNB9ZX3Gzb":[{"ts":1760521973764,"values":{"edge_fw_version":"2025-10-08","maintenance_mode":false}}],"id":"3000173003jj71b"} +-"d5xjWYMwEJon6rLlK7yE9Q7qgV4DaOeNB9ZX3Gzb":[{"ts":1760521973777,"values":{"statecode":2,"power_mode":"Automatic"}}],"id":"3000173005jj71b"} +-"d5xjWYMwEJon6rLlK7yE9Q7qgV4DaOeNB9ZX3Gzb":[{"ts":1760521973805,"values":{"_event":{"type":"notice","status":"new","source":{"func":"rsPort.open()","component":"1699963668903","component_name":"DIDO_Controller","edge":"d5xjWYMwEJon6rLlK7yE9Q7qgV4DaOeNB9ZX3Gzb"},"message":{"sk":"rvo_senica_4_10.0.0.136: FLOW bol spustený","en":"rvo_senica_4_10.0.0.136: FLOW has been started "},"message_data":""}}}],"id":"3000173007jj71b"} diff --git a/RVO4/databases/total_energy.js b/RVO4/databases/total_energy.js new file mode 100755 index 0000000..dde340e --- /dev/null +++ b/RVO4/databases/total_energy.js @@ -0,0 +1,38 @@ +//key is rvo_number, value is max energy when lamps are on +const total_energy = { + 1: 580, + 2: 1100, + 3: 3700, + 4: 4100, + 7: 360, + 12: 1700, + 13: 5400, + 14: 440, + 15: 6100, + 16: 4800, + 20: 1600, + 21: 1000, + 22: 2600, + 23: 1000, + 25: 2600, + 33: 240, + 34: 4000, + 35: 2700, + 36: 820, + 37: 1400, + 35: 3500, + 39: 1170, + 41: 740, + 42: 660, + 43: 4900, + 45: 930, + 46: 700, + 47: 1100, + 48: 1500, + 50: 3200, + 53: 1250, + 55: 1000, + 56: 5500 +} + +module.exports = total_energy; diff --git a/RVO4/debug.js b/RVO4/debug.js new file mode 100755 index 0000000..9818194 --- /dev/null +++ b/RVO4/debug.js @@ -0,0 +1,16 @@ +// =================================================== +// FOR DEVELOPMENT +// Total.js - framework for Node.js platform +// https://www.totaljs.com +// =================================================== + +const options = {}; + +// options.ip = '127.0.0.1'; +// options.port = parseInt(process.argv[2]); +// options.config = { name: 'Total.js' }; +// options.sleep = 3000; +// options.inspector = 9229; +// options.watch = ['private']; + +require('total.js/debug')(options); \ No newline at end of file diff --git a/RVO4/err.txt b/RVO4/err.txt new file mode 100755 index 0000000..b123b27 --- /dev/null +++ b/RVO4/err.txt @@ -0,0 +1,77 @@ +[2024-10-21T21:27:43.095] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-21T22:28:14.562] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-21T23:28:57.629] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-22T00:29:34.860] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-22T01:30:08.257] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-22T02:30:51.310] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-22T03:31:16.897] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-22T04:31:37.692] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-22T05:32:11.062] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-22T06:33:23.211] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-22T07:34:02.435] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-22T08:34:43.511] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-22T09:35:07.142] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-22T10:35:30.785] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-22T11:36:02.218] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-22T12:36:33.619] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-22T13:37:22.453] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-22T14:37:59.643] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-22T15:38:31.039] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-22T16:38:50.788] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-22T17:39:20.256] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-22T18:40:01.375] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-22T19:40:34.735] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-22T20:41:04.222] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-22T21:41:33.674] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-22T22:42:12.861] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-22T23:42:44.266] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-23T00:43:25.390] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-23T01:43:41.279] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-23T02:44:08.845] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-23T03:44:31.576] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-23T04:45:04.951] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-23T05:45:42.188] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-23T06:46:13.606] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-23T07:46:33.384] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-23T08:47:02.843] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-23T09:47:36.128] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-23T10:48:13.327] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-23T11:48:31.115] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-23T12:49:31.607] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-23T13:49:53.306] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-23T14:50:11.124] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-23T15:50:17.283] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-12-05T14:06:37.446] [ERROR] errLogs - Thermometer Thermometer: temperatureAddress is not defined +[2025-09-23T14:06:30.370] [ERROR] errLogs - uncaughtException: Cannot read property 'getHours' of undefined +[2025-09-23T14:06:30.371] [ERROR] errLogs - TypeError: Cannot read property 'getHours' of undefined + at Timeout.emptyReportToSend [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:06:30.372] [ERROR] errLogs - uncaughtException: Cannot read property 'getHours' of undefined +[2025-09-23T14:06:30.373] [ERROR] errLogs - TypeError: Cannot read property 'getHours' of undefined + at Timeout.emptyReportToSend [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:06:30.382] [ERROR] errLogs - uncaughtException: Cannot read property 'getHours' of undefined +[2025-09-23T14:06:30.383] [ERROR] errLogs - TypeError: Cannot read property 'getHours' of undefined + at Timeout.emptyReportToSend [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:06:36.097] [ERROR] errLogs - uncaughtException: date.getHours is not a function +[2025-09-23T14:06:36.097] [ERROR] errLogs - TypeError: date.getHours is not a function + at emptyReportToSend (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at Timeout.dailyReportCheck [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1351:5) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:06:36.098] [ERROR] errLogs - uncaughtException: date.getHours is not a function +[2025-09-23T14:06:36.099] [ERROR] errLogs - TypeError: date.getHours is not a function + at emptyReportToSend (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at Timeout.dailyReportCheck [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1351:5) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:06:36.104] [ERROR] errLogs - uncaughtException: date.getHours is not a function +[2025-09-23T14:06:36.105] [ERROR] errLogs - TypeError: date.getHours is not a function + at emptyReportToSend (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at Timeout.dailyReportCheck [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1351:5) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) diff --git a/RVO4/flow/cloudmqttconnect.js b/RVO4/flow/cloudmqttconnect.js new file mode 100755 index 0000000..b03491f --- /dev/null +++ b/RVO4/flow/cloudmqttconnect.js @@ -0,0 +1,357 @@ +exports.id = 'cloudmqttconnect'; +exports.title = 'Cloud connect mqtt'; +exports.group = 'MQTT'; +exports.color = '#888600'; +exports.version = '1.0.2'; +exports.icon = 'sign-out'; +exports.input = 2; +exports.output = 2; +exports.options = { host: 'tb-stage.worksys.io', port: 1883, clientid: "", username: "" }; + +exports.html = `
+
+
+
Hostname or IP address (if not empty - setting will override db setting)
+
+
+
Port
+
+
+
+
+
@(Client id)
+
+
+
topic
+
+
+
`; + + + +const { promisifyBuilder } = require('./helper/db_helper'); +const fs = require('fs'); +const mqtt = require('mqtt'); +const nosql = NOSQL('tbdatacloud'); + +const SEND_TO = { + debug: 0, + rpcCall: 1, +} + +//CONFIG +let saveTelemetryOnError = true;//backup_on_failure overrides this value +//------------------------ + +const noSqlFileSizeLimit = 4194304;//use 5MB - 4194304 +let insertNoSqlCounter = 0; +let insertBackupNoSqlCounter = 0; +let processingData = false; + +let backup_on_failure = true;//== saveTelemetryOnError - create backup client send failure +let restore_from_backup = 50; //how many rows process at once? +let restore_backup_wait = 3;//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; + + +exports.install = function(instance) { + + var client; + var opts; + var clientReady = false; + + let o = {}; //options + + function main() { + loadSettings(); + } + + //set opts according to db settings + function loadSettings() { + + o = instance.options; + if (!o.topic) o.topic = FLOW.GLOBALS.settings.cloud_topic; + + opts = { + host: o.host, + port: o.port, + clientId: o.clientid, + username: o.username, + rejectUnauthorized: false, + resubscribe: false + }; + + console.log("wsmqttpublich -> loadSettings from instance.options", o); + + if (!o.topic) { + instance.status("Not configured", "white"); + console.log("Cloud mqtt connect: no topic selected"); + return; + } + + connectToTbServer(); + } + + function connectToTbServer() { + var url = "mqtt://" + opts.host + ":" + opts.port; + console.log("MQTT URL: ", url); + + client = mqtt.connect(url, opts); + + client.on('connect', function() { + client.subscribe(`${o.topic}_backward`, (err) => { + if (!err) { + console.log("MQTT subscribed"); + } + }); + instance.status("Connected", "green"); + clientReady = true; + sendClientError = true; + }); + + client.on('reconnect', function() { + instance.status("Reconnecting", "yellow"); + clientReady = false; + }); + + client.on('message', function(topic, message) { + // message is type of buffer + message = message.toString(); + if (message[0] === '{') { + TRY(function() { + + message = JSON.parse(message); + if (message.hasOwnProperty("device") && message.hasOwnProperty("data") && message.data.hasOwnProperty("id")) { + client.publish(`${o.topic}_forward`, `{"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 } }); + } + + }, () => instance.debug('MQTT: Error parsing data', message)); + } + + instance.send(SEND_TO.rpcCall, { "topic": o.topic, "content": message }); + }); + + client.on('close', function() { + clientReady = false; + + instance.status("Disconnected", "red"); + instance.send(SEND_TO.debug, { "message": "Client CLOSE signal received !" }); + }); + + client.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) { + console.log('MQTT client error', err); + sendClientError = false; + } + clientReady = false; + }); + + } + + + instance.on('0', function(data) { + + if (clientReady) { + //do we have some data in backup file? if any, process data from database + if (saveTelemetryOnError) { + //read telemetry data and send back to server + if (!processingData) processDataFromDatabase(); + } + + let stringifiedJson = JSON.stringify(data.data) + client.publish(`${o.topic}_forward`, stringifiedJson, { qos: 1 }); + } + 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 (saveTelemetryOnError && o.topic) { + //create new file from tbdata.nosql, if file size exceeds given limit, and clear tbdata.nosql + makeBackupFromDbFile(); + + //write to tb + data.data.id = UID(); + nosql.insert(data.data); + } + } + }); + + instance.on("1", _ => { + main(); + }) + + instance.close = function(done) { + if (clientReady) { + client.end(); + } + }; + + + function getDbBackupFileCounter(type) { + var files = fs.readdirSync(__dirname + "/../databases"); + + let counter = 0; + for (var i = 0; i < files.length; i++) { + + if (files[i] == "tbdatacloud.nosql") continue; + + if (files[i].endsWith(".nosql")) { + + let pos = files[i].indexOf("."); + if (pos > -1) { + + let fileCounter = counter; + let firstDigit = files[i].slice(0, pos); + + fileCounter = parseInt(firstDigit); + if (isNaN(fileCounter)) fileCounter = 0; + //console.log("getDbBackupFileCounter digit:", files[i], firstDigit, fileCounter, isNaN(fileCounter), type); + + if (type == "max") { + if (fileCounter > counter) { + counter = fileCounter; + } + } + else if (type == "min") { + if (counter == 0) counter = fileCounter; + + if (fileCounter < counter) { + counter = fileCounter; + } + } + } + } + + } + + if (type == "max") counter++; + + return counter; + } + + const makeBackupFromDbFile = async () => { + + if (!saveTelemetryOnError) return; + + //to avoid large file: tbdata.nosql + + //init value is 0! + if (insertNoSqlCounter > 0) { + --insertNoSqlCounter; + return; + } + + insertNoSqlCounter = 100; + + let source = __dirname + "/../databases/tbdatacloud.nosql"; + + var stats = fs.statSync(source); + var fileSizeInBytes = stats.size; + + if (fileSizeInBytes > noSqlFileSizeLimit) { + + let counter = 1; + counter = getDbBackupFileCounter("max"); + + let destination = __dirname + "/../databases/" + counter + "." + "tbdatacloud.nosql"; + + //make backup file + fs.copyFileSync(source, destination); + //fs.renameSync(p, p + "." + counter); + + //clear tbdata.nosql + fs.writeFileSync(source, ""); + fs.truncateSync(source, 0); + + } + } + + const processDataFromDatabase = async () => { + + if (restore_from_backup <= 0) return; + + //calculate diff + const now = new Date(); + let currentTime = now.getTime(); + let diff = currentTime - lastRestoreTime; + + if ((diff / 1000) < restore_backup_wait) { + //console.log("*********restore_backup_wait", diff, restore_backup_wait); + return; + } + + processingData = true; + + //get filename to process + let counter = getDbBackupFileCounter("min"); + + //we have some backup files + let dataBase = 'tbdata'; + + var nosql; + if (counter == 0) dataBase = 'tbdatacloud'; + else dataBase = counter + "." + 'tbdatacloud'; + + nosql = NOSQL(dataBase); + + //select all data - use limit restore_from_backup + let records = await promisifyBuilder(nosql.find().take(restore_from_backup)); + + for (let i = 0; i < records.length; i++) { + if (clientReady) { + + let item = records[i]; + let id = item.id; + + if (id !== undefined) { + //console.log("------------processDataFromDatabase - remove", id, dataBase, i); + + try { + + let message = JSON.parse(JSON.stringify(item)); + delete message.id; + client.publish(`${o.topic}_forward`, JSON.stringify(message), { qos: 1 }); + + //remove from database + await promisifyBuilder(nosql.remove().where("id", id)); + + } catch (error) { + //process error + console.log("processDataFromDatabase", error); + } + + } + + } + else { + processingData = false; + return; + } + } + + if (records.length > 0) { + //clean backup file + if (counter > 0) nosql.clean(); + } + + //no data in db, remove + if (records.length == 0) { + if (counter > 0) nosql.drop(); + } + + const d = new Date(); + lastRestoreTime = d.getTime(); + + processingData = false; + + } + + instance.on('options', main); + +}; diff --git a/RVO4/flow/cmd_manager.js b/RVO4/flow/cmd_manager.js new file mode 100755 index 0000000..25912df --- /dev/null +++ b/RVO4/flow/cmd_manager.js @@ -0,0 +1,3071 @@ +exports.id = 'cmd_manager'; +exports.title = 'CMD Manager'; +exports.group = 'Worksys'; +exports.color = '#5D9CEC'; +exports.version = '0.0.3'; +exports.output = ['red', 'blue', 'yellow', 'blue', 'white', 'green']; +exports.input = 3; +exports.icon = 'cloud-upload'; + +exports.html = ` +
+
+
+
RPC - run RPC calls

+
+
+
@(User)
+
+
+
@(Password)
+
+
+
@(My edge)
+
+
+
+`; +exports.readme = `Manager for CMD calls`; + + +exports.install = function(instance) { + + 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, isEmptyObject, emptyJsObject, writeToFile, addToArrayIfUnique } = require('./helper/utils'); + const bitwise = require('bitwise'); + + var SunCalc = require('./helper/suncalc'); + const DataToTbHandler = require('./helper/DataToTbHandler'); + const errorHandler = require('./helper/ErrorToServiceHandler'); + const { sendNotification } = require('./helper/notification_reporter'); + const process = require('process'); + const { errLogger, logger, monitor } = require('./helper/logger'); + + //for accelerometer purposes + const { naklony } = require("../databases/accelerometer_db"); + + const dbNodes = TABLE("nodes"); + const dbRelays = TABLE("relays"); + + let GLOBALS; + let SETTINGS; + let rsPort; + let tbHandler; + + // runTasks intervals + const SHORT_INTERVAL = 30; + const LONG_INTERVAL = 300; + + //send data to following instances: + const SEND_TO = { + debug: 0, + tb: 1, + http_response: 2, + dido_controller: 3, + infoSender: 4, + dailyReport: 5 + } + + 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 + } + + 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 sendNodeReadout = null; // interval for sending agregate data from node + + 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["1"] = minutes; // dimming + priorities["76"] = minutes; // power + + minutes = 5; + priorities["75"] = minutes; // current + priorities["79"] = minutes; // energy + priorities["87"] = minutes; // aktualny cas + //priorities["84"] = minutes; //accelerometer + + minutes = 10; + priorities["74"] = minutes; // voltage + priorities["77"] = minutes; // power factor + priorities["78"] = minutes; // frequency + + minutes = 60; + priorities["0"] = minutes; // statecode + priorities["6"] = minutes; // dusk + priorities["7"] = minutes; // dawn + priorities["8"] = minutes; // profile + + minutes = 60 * 24; + priorities["89"] = minutes; // verzia fw + priorities["80"] = minutes; // lifetime + + //prikazy kt sa budu spustat na dany node - see config.js in terminal-oms.app. (1 - dimming) + let listOfCommands = [0, 1, 6, 7, 8, 74, 75, 76, 77, 78, 79, 80, 87, 89]; + + 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; + + // holds dusk, dawn (and more) values + let sunCalcResult; + + //helper container for counting resolved group of commands (commands related to set profile) + let cmdCounter = {};//key is node, value is counter + + //TODO: is this set working?? According to previous checks, sets do not work + //if sending of profile to node fails, we send notification and push node into set, so we do not send notification twice + const nodeProfileSendFail = new Set(); + + //we expect to get current temperature in Senica from senica-prod01 + let temperatureInSenica = null; + let accelerometerInterval = null; + + //NOTE: daily reports senica: + //rvo_is_on status, we monitor all nodes - if true, power and dimming should be not 0, if false, 24/7 nodes should be 0, other rvo should not respond + let rvo_is_on; + let previous_rvo_is_on_value; + let handleDailyReport; //setInterval for dailyReportHandler function + let dailyReport = {}; //data needed for daily report + let reportToSend = {}; //final report which we send to cloud + let breakerCounter = null; // status of breakers after flow starts is not in report + let rvoPeriod; // interval of checking dusk dawn and if rvo_is_on + let initialReportStatus = false; + + const DAILY_REPORT_HANDLER_TIME = 3_600_000; + const SET_SUNCALC_RESULT_TIME = 3_600_000; + const SET_RVO_PERIOD_TIME = 300_000; + const ADD_NODE_TO_REPORT_TIME = 3_600_000; + + //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); + + let now = new Date(); + console.log("Cmd-mngr installed", now.toLocaleString("sk-SK")); + + sunCalcResult = calculateDuskDawn(); + + handleRsPort(); + + customTasksInterval = setInterval(reportEdgeDateTimeAndNumberOfLuminaires, 120_000); + setTimeout(reportEdgeDateTimeAndNumberOfLuminaires, 4000); + + //dailyReport related + emptyReportToSend(); + breakerCounter = Object.keys(relaysData).length - 1; // we get number of lines (breakers) except of line 0 + rvoPeriod = setInterval(setRvoPeriod, SET_RVO_PERIOD_TIME); + setTimeout(setRvoPeriod, 3000); + setInterval(setSunCalcResult, SET_SUNCALC_RESULT_TIME); + handleDailyReport = setInterval(dailyReportHandler, DAILY_REPORT_HANDLER_TIME); + + + setCorrectTime = setInterval(setCorrectPlcTimeOnceADay, 60000 * 60); // 1 hour + setCorrectPlcTimeOnceADay(); + + sendNodeReadout = setInterval(sendNodesData, 150_000); + accelerometerInterval = setInterval(accelerometerData, 60000 * 30); //30 min + } + + + 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" + //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 + // if node regular readout does not respond, we repeat request + params.repeatCounter = 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-mngr: 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.byte4 = 96; + params.recipient = 1; + params.register = 8; + params.rw = 1;//write + params.timestamp = timestamp; + 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.byte4 = 96; + params.recipient = 1; + params.register = 8; + params.rw = 1;//write + params.timestamp = timestamp; + 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). + */ + + 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.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.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 + { + + logger.debug("processNodeProfile: Threshold lux level for DUSK/DAWN", node); + + let params = getParams(); + params.type = "set_node_profile"; + params.address = node; + params.register = 96; + params.recipient = 1; + params.rw = 1;//write + params.timestamp = timestamp; + 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(); + params.type = "set_node_profile"; + params.address = node; + params.register = 97; + params.recipient = 1; + params.rw = 1;//write + params.timestamp = timestamp; + 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.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); + + 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); + + console.log("proces profile finished *********************") + } + + + 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; + }); + } + + + 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) { + for (let k in nodesData) { + 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`); + } + } + } + + + function loadRelaysData(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 (value.contactor == 1) processAllNodeProfilesOnLine(value.line); + } + } + + + function reportOnlineNodeStatus(line) { + //Po zapnutí línie broadcastovo aktualizovať predtým čas a o 3 sek neskor - status, brightness + + logger.debug("Cmd-mngr: ----->reportOnlineNodeStatus for line", line); + + const d = new Date(); + + // broadcast actual time + let params = getParams(); + params.address = 0xffffffff;//Broadcast + params.byte1 = d.getHours(); + params.byte2 = d.getMinutes(); + params.recipient = 2;//2 broadcast, address = 0 + params.register = 87;//Actual time + params.rw = 1;//write + params.type = "node-onetime-write"; + params.timestamp = d.getTime() + 30000; + params.info = "run broadcast: Actual time"; + //params.debug = true; + + tasks.push(params); + + let sec = 3; + setTimeout(function() { + //Po zapnutí línie - spraviť hromadný refresh stavu práve zapnutých svietidiel + + let time = Date.now(); + + for (let k in nodesData) { + + //potrebujem nody k danej linii + 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].node_status_before_offline === true || nodesData[k].status === true) { + status = "OK"; + nodesData[k].time_of_last_communication = time; + } + + nodesData[k].readout.status = status; + + updateNodeStatus(k, status === "OK" ? true : false); + if (nodesData[k].hasOwnProperty("node_status_before_offline")) delete nodesData[k].node_status_before_offline; + sendTelemetry({ status: status }, tbname, time); + + //vyreportovanie dimming, current, input power pre liniu pre vsetky nody + //Prud + { + let params = getParams(); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 75;//prud + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = time + 4000; + params.info = 'read current'; + //params.debug = true; + tasks.push(params); + } + + //vykon + { + let params = getParams(); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 76;//výkon + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = time + 4100; + params.info = 'read power'; + //params.debug = true; + + tasks.push(params); + } + //dimming + { + let params = getParams(); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 1;//dimming + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = time + 4200; + params.info = 'read dimming'; + //params.debug = true; + + tasks.push(params); + } + + } + } + + }, sec * 1000); + } + + + function reportOfflineNodeStatus(line) { + + logger.info("Cmd-mngr: ------>reportOffLineNodeStatus for line ", line); + + values = {}; + values["dimming"] = 0;//brightness + values["power"] = 0;//výkon + values["current"] = 0;//prúd + values["status"] = "OFFLINE"; + + const date = Date.now(); + + Object.keys(nodesData).forEach(node => { + + //potrebujem nody k danej linii + if (line == nodesData[node].line || line == undefined) { + + let tbname = nodesData[node].tbname; + let nodeStatus = nodesData[node].status; + + //in case we have reported offline node status, we return (continue with next node) + if (nodeStatus === "OFFLINE") return; + + nodesData[node].node_status_before_offline = nodeStatus; + nodesData[node].status = "OFFLINE"; + nodesData[node].readout = {}; + + sendTelemetry({ ...values }, tbname, date); + } + }); + + } + + + function turnLine(onOrOff, line, info) { + let obj = { + line: line, + command: onOrOff, + info: info + }; + + //to assure, handleDailyReportFunction do not run before rvo_is_on variable changes. So after every line switch we reset the timer + clearInterval(handleDailyReport); + handleDailyReport = setInterval(dailyReportHandler, DAILY_REPORT_HANDLER_TIME); + + //logger.debug("linia", line, obj); + instance.send(SEND_TO.dido_controller, obj); + } + + + 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"; + 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]) { + //CRC_ERROR + message = "NOK"; + error = "CRC_ERROR c1"; + instance.send(SEND_TO.debug, "CRC_ERROR c1"); + } + + 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") { + instance.send(SEND_TO.debug, bytes); + instance.send(SEND_TO.debug, "RESPONSE " + type + " - " + bytes[4]); + + //logger.debug(SEND_TO.debug, "RESPONSE " + type + " - " + bytes[4], bytes); + + error = "type is: " + type; + + message = "NOK"; + } + + return { message, type, error }; + } + + + //BUILD TASKS// + function buildTasks(params) { + + //return; + console.log("buidTAaasks start ****************", params); + monitor.info("buildTasks - params", params); + + let processLine; //defined line + let init = false; + let processLineProfiles = true; + let processBroadcast = true; + let processNodes = true; + + if (params == undefined) { + init = true; + tasks = []; + logger.debug("-->buildTasks clear tasks"); + } + else { + processLineProfiles = params.processLineProfiles; + processBroadcast = false; + processNodes = false; + + processLine = params.line; + } + + let now = new Date(); + + //process line profiles + if (processLineProfiles) { + + let keys = Object.keys(relaysData); + + for (let i = 0; i < keys.length; i++) { + + let line = parseInt(keys[i]); + let profilestr = relaysData[line].profile; + + if (processLine != undefined) { + if (processLine != line) continue; + } + + try { + + /** + * we process line profiles: timepoints, astro clock, lux_sensor, offsets ... + */ + if (profilestr === "") throw ("Profile is not defined"); + let profile = JSON.parse(profilestr); + 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; + + // add name to regular profile timepoint and delete unused end_time key: + time_points.forEach(point => { + point.name = "profileTimepoint" + delete point.end_time; + }); + + //monitor.info("buildTasks: time_points", time_points); + + + /** + * 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 astro clock true, we remove all regular profile points + time_points = []; + + //TODO: when astro clock == true, is offset calculated ??? + //let duskAstroClockOffset = profile.dusk_astro_clock_offset; + //let dawnAstroClockOffset = profile.dawn_astro_clock_offset; + //console.log("line astro clock offsets dusk a dawn: ", duskAstroClockOffset, dawnAstroClockOffset); + // maybe add dusk dawn offset to calculateDuskDawn ?? what dusk dawn will be if dawn_lux_sensor == true?? + //let sunCalcResult = calculateDuskDawn(new Date(), line, duskAstroClockOffset, dawnAstroClockOffset); + + 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 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); + + 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); + + 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(':'); + + let ad = new Date(); + ad.setHours(parseInt(ahours), parseInt(aminutes), 0); + + let bd = new Date(); + bd.setHours(parseInt(bhours), parseInt(bminutes), 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++) { + + let start_time = new Date(); + let [hours, minutes] = time_points[t].start_time.split(':'); + start_time.setHours(parseInt(hours), parseInt(minutes), 0); + + //task is in 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(); + params.type = "relay"; + params.line = parseInt(line); + params.value = time_points[t].value; + params.tbname = relaysData[line].tbname; + params.timestamp = start_time.getTime(); + + // 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; + + //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)) { + 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; + + params.debug = true; + + //turn on/off line + tasks.push(params); + monitor.info("TimePoint params: ", params.info, start_time); + } + + monitor.info("-->time_points final", line, time_points); + + //ensure to turn on/off according to calculated currentValue + let params = getParams(); + params.type = "relay"; + params.line = parseInt(line); + params.tbname = relaysData[line].tbname; + params.value = currentValue; + params.timestamp = i; + params.debug = true; + + //logger.debug(now.toLocaleString("sk-SK")); + 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; + + tasks.push(params); + + } catch (error) { + if (profilestr !== "") { + //errLogger.error(profilestr, error); + console.log(`Cmd_mngr: Unable to process line profile ${line}. Error: `, error); + errorHandler.sendMessageToService(profilestr + "-" + error, 0, "js_error"); + } else { + turnLine("off", line, "No line profile. Switching it off on startup"); + } + } + + } + //logger.debug("tasks:"); + //logger.debug(tasks); + } + + + //NOTE: PROCESS DEFAULT BROADCASTS - Time of dusk, Time of dawn, Actual Time + if (processBroadcast) { + + let d = new Date(); + let time = d.getTime(); + //let sunCalcResult = calculateDuskDawn(); + + { + let params = getParams(); + + params.address = 0xffffffff;//broadcast + params.byte1 = sunCalcResult["dusk_hours"]; + params.byte2 = sunCalcResult["dusk_minutes"]; + params.recipient = 2;//2 broadcast, + params.register = 6;//Time of dusk + params.rw = 1;//write + params.type = "node-regular-write"; + params.timestamp = time + 60000; + params.addMinutesToTimestamp = 60 * 3; //kazde 3 hodiny zisti novy dusk + params.info = "Broadcast-duskTime"; + + tasks.push(params); + } + + { + let params = getParams(); + + params.address = 0xffffffff;//broadcast + params.byte1 = sunCalcResult["dawn_hours"]; + params.byte2 = sunCalcResult["dawn_minutes"]; + params.recipient = 2; //2 broadcast + params.register = 7;//Time of dawn + params.rw = 1;//write + params.type = "node-regular-write"; + params.timestamp = time + 60001; + params.addMinutesToTimestamp = 60 * 3; //kazde 3 hodiny zisti novy dawn + params.info = "Broadcast-dawnTime"; + + tasks.push(params); + } + + { + let params = getParams(); + + params.address = 0xffffffff;//broadcast + params.byte1 = d.getHours(); + params.byte2 = d.getMinutes(); + params.recipient = 2; //2 broadcast + params.register = 87;//Actual time + params.rw = 1;//write + params.type = "node-regular-write"; + params.timestamp = time + 60002; + params.addMinutesToTimestamp = 5; + params.info = "run broadcast: Actual time"; + + tasks.push(params); + } + + } + + //process nodes & tasks - read node's data + if (processNodes) { + + let time = Date.now(); + + for (let k in nodesData) { + let address = parseInt(k); + let tbname = nodesData[k].tbname; + let register = 0; + + for (let i = 0; i < listOfCommands.length; i++) { + + register = listOfCommands[i]; + let addMinutesToTimestamp = priorities[register]; + + let params = getParams(); + + params.address = address; + params.recipient = 1; + params.register = register; + params.type = register == 1 ? "node-dimming-read" : "node-regular-read"; + params.tbname = tbname; + params.timestamp = time + 5000 + i * 500 + addMinutesToTimestamp * 1000; //to make slight time difference + params.addMinutesToTimestamp = addMinutesToTimestamp; + params.info = "Node regular read command"; + + tasks.push(params); + } + + } + } + + + //niektore ulohy sa vygeneruju iba 1x pri starte!!! + if (!init) return; + + + //Master node FW version - modifies SETTINGS.masterNodeIsResponding + { + let params = getParams(); + params.type = "cmd-master"; + params.register = 4; + params.address = 0; + params.timestamp = 0; + params.addMinutesToTimestamp = 5; + params.tbname = SETTINGS.rvoTbName; + params.info = "Master node FW verzia"; + //params.debug = true; + + tasks.push(params); + } + + //kazdu hodinu skontrolovat nastavenie profilov + { + let params = getParams(); + params.type = "process_profiles"; + params.timestamp = Date.now() + 60001; + params.addMinutesToTimestamp = 60;//60 = every hour + params.info = "detekcia nespracovaných profilov linie a nodov"; + //params.debug = true; + + tasks.push(params); + } + + monitor.info("tasks created:", tasks.length); + } + + + /** + * We process line profile, where "astro_clock": true + * example profile: + * + "dawn_lux_sensor": true, + "dusk_lux_sensor": true, + "dawn_lux_sensor_value": 5, + "dusk_lux_sensor_value": 5, + "dawn_astro_clock_offset": 0, + "dusk_astro_clock_offset": 10, + "dawn_lux_sensor_time_window": 30, + "dusk_lux_sensor_time_window": 30, + "dawn_astro_clock_time_window": 60, + "dusk_astro_clock_time_window": 60 + + * if dawn: if currentTimestamp is in timewindow "dawnTime + and - dawn_lux_sensor_time_window" and lux value >= lux_sensor_value, we switch off the line. + * if dusk: we do oposite + * + * dawn: usvit - lux je nad hranicou - vypnem + * dusk: sumrak - lux je pod hranicou - zapnem + */ + 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++) { + + let line = keys[i]; //line is turned off by default + let profilestr = relaysData[line].profile; + const contactor = relaysData[line].contactor; + + try { + + let profile = JSON.parse(profilestr); + if (Object.keys(profile).length === 0) throw ("turnOnOffLinesAccordingToLuxSensor - profile is not defined"); + + 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 (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"); + } + } + } + + //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 (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"); + } + } + } + + } + + } catch (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) { + //MASTER + if (node == 0) return; + + let nodeObj = nodesData[node]; + if (nodeObj == undefined) return; + + let nodeCurrentStatus = nodeObj.status; + const now = Date.now(); + + let data = null; + + if (nodeCurrentStatus === "OFFLINE") { + data = { status: newStatus }; + nodeDbStatusModify(node, data); + return; + } + else 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; + } + + } + + + 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 }; + } + }); + }); + } + + + function processDailyReport() { + + const now = Date.now(); + + for (const [key, value] of Object.entries(dailyReport)) { + + if (["name", "time", "dusk_and_dawn"].includes(key)) continue; + + let poleNumber = nodesData[key]["pole_number"]; + let line = dailyReport[key].line; + let nodeType = nodesData[key]["node_type"]; + let fullNodeName = key // key == nodeNumber + + if (poleNumber && nodeType) { + fullNodeName = SETTINGS.rvo_number + "/" + poleNumber + "_" + line + "L_" + key + "_" + nodeType; + } else { + fullNodeName = key; + } + + if (rvo_is_on) { + + if (value.initialTs) { + if (value.initialTs + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["night_no_data"], fullNodeName); + console.log('report nedostava ziadne data uz hodinu', fullNodeName); + value.initialTs = now; + } + } + if (value.dimmingIsZeroTime) { + if (value.dimmingIsZeroTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["night_dimming=0"], fullNodeName); + console.log("report node dimming je 0 ale ma svietit", fullNodeName); + value.dimmingIsZeroTime = now; + } + } + if (value.powerIsZeroTime) { + if (value.powerIsZeroTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["night_power=0"], fullNodeName); + console.log("report node power je 0 ale ma svietit", fullNodeName); + value.powerIsZeroTime = now; + } + } + + } else { + + let contactorStatus = relaysData[line].contactor; + if (contactorStatus === 1) { + + if (value.initialTs) { + if (value.initialTs + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["day_24/7_no_data"], fullNodeName); + console.log('node je na 24/7 ale nedostava ziadne data uz hodinu', fullNodeName); + value.initialTs = now; + } + } + if (value.dimmingIsOnButShouldBeOffTime) { + if (value.dimmingIsOnButShouldBeOffTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["day_24/7_dimming>0"], fullNodeName); + console.log("report dimming je > 0 ale nema svietit", fullNodeName); + value.dimmingIsOnButShouldBeOffTime = now; + } + } + if (value.powerIsOnButShouldBeOffTime) { + if (value.powerIsOnButShouldBeOffTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["day_24/7_power>0"], fullNodeName); + console.log("report power je > 0 ale nema svietit", fullNodeName); + value.powerIsOnButShouldBeOffTime = now; + } + } + + } + + } + + } + + let report = {}; + report["name"] = SETTINGS.rvo_name; + report["time"] = new Date(); + report["report"] = reportToSend; + + writeToFile(F.path.root("report_data.log"), report, true); + instance.send(SEND_TO.dailyReport, report); + } + + + function dailyReportHandler() { + + if (!SETTINGS.daily_report) return; + + // after dawn we empty reportToSend and start to get data for a new day + const date = new Date(); + const hour = date.getHours(); + const minute = date.getMinutes(); + + console.log("now: ", hour, minute, "suncalc: ", sunCalcResult.dawn_hours, sunCalcResult.dawn_minutes); + + if (hour === sunCalcResult.dawn_hours) { + + //NOTE: ak je este pred usvitom, spracujeme report a posleme na cloud, ak uz je po usvite, resetujeme report plnime data noveho dna + if (minute >= sunCalcResult.dawn_minutes - 2) { + emptyReportToSend(); + emptyDailyReport(); + console.log("Podmienka 1 v dailyReport handler"); + } else { + processDailyReport(); + emptyReportToSend(); + emptyDailyReport(); + console.log("Podmienka 2 v dailyReport handler"); + } + + initialReportStatus = true; + + // ak sa funkcia spusti o hodinu alebo 2 neskor, ako je usvit (moze sa to stat, kedze kazde zapnutie/vypnutie linii odznova spusti casovac. + } else if (hour === sunCalcResult.dawn_hours + 1 || hour === sunCalcResult.dawn_hours + 2) { + if (!initialReportStatus) { + emptyReportToSend(); + emptyDailyReport(); + initialReportStatus = true; + console.log("Podmienka 3 v dailyReport handler"); + } else { + processDailyReport(); + initialReportStatus = true; + console.log("Podmienka 4 v dailyReport handler"); + } + } else { + processDailyReport(); + initialReportStatus = false; + console.log("Podmienka 5 v dailyReport handler"); + } + + console.log("initialReportStatus: ", initialReportStatus); + + } + + function emptyReportToSend() { + emptyJsObject(reportToSend); + reportToSend["contactor"] = { off: [], on: [] }; + reportToSend["night_no_data"] = []; + reportToSend["night_dimming=0"] = []; + reportToSend["night_power=0"] = []; + reportToSend["day_24/7_no_data"] = []; + reportToSend["day_24/7_dimming>0"] = []; + reportToSend["day_24/7_power>0"] = []; + console.log(`resetuje sa reportToSend`); + } + + + //NOTE: ked je initialTs stale rovnaky a zistime ze linie su vypnute (relaysData.line.contactor) - zistim, ci je node na tej linii. Vieme, ze ak je linia vypnuta je to v poriadku lebo nie je na 24/7 linii + //ak je na 24/7 linii, reportujeme, ze neprijima data + function emptyDailyReport() { + const ts = Date.now(); + emptyJsObject(dailyReport); + + //NOTE: do dailyReport dame vsetky nody a pravidelne kontrolujeme ci maju data + //ked nastane sumrak/usvit a svetla maju zacat/prestat svietit, dailyReport spravime nanovo: + for (const [key, value] of Object.entries(nodesData)) { + dailyReport[value.node] = { line: value.line, initialTs: ts }; + } + + console.log("dailyReport: ", dailyReport); + } + + + async function runTasks() { + + clearInterval(interval); + + let currentTimestamp = Date.now(); + + //sort tasks based on timestamp + 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) { + instance.send(SEND_TO.debug, "no tasks created"); + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + if (!rsPort.isOpen) { + instance.send(SEND_TO.debug, "!rsPort.isOpen"); + //await rsPort.open(); + //console.log("Cmd-mngr: !rsPort.isOpen"); + } + + let currentTask = tasks[0]; + + if (currentTask.debug) { + //logger.debug("--->task to process", currentTask); + } + + if (currentTask.timestamp <= currentTimestamp) { + let params = { ...tasks[0] }; + + //allow terminal commands + if (SETTINGS.maintenance_mode && params.type !== "cmd-terminal") { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + let type = params.type; + let tbname = params.tbname; + let node = params.address; + let register = params.register; + let line = null; + let itIsNodeCommand; + + if (nodesData[node] !== undefined) { + line = nodesData[node].line; + itIsNodeCommand = true; + } + + if (params.line !== undefined) line = params.line; + + if (params.addMinutesToTimestamp > 0 || params.timePointName) { + tasks[0].timestamp = currentTimestamp + tasks[0].addMinutesToTimestamp * 60000; + } else { + tasks.shift(); + } + + //kontrola nespracovanych profilov nodov + //TODO: co ked niektore nody neprijimaju profily? kazdu hodinu zahltuju "tasks" array + if (type == "process_profiles") { + //na vsetky zapnutych liniach sa spracuju nespracovane profily nodov + loadRelaysData(); + interval = setInterval(runTasks, SHORT_INTERVAL); + return; + } + + //relay + if (type == "relay") { + + const timePointName = params.timePointName; + const value = params.value; + + let date = new Date(); + date.setDate(date.getDate() + 1);//next day + + let sunCalcResult; + if (timePointName) sunCalcResult = calculateDuskDawn(date, params.line); + + + if (timePointName == "dawn") { + tasks[0].timestamp = sunCalcResult.dawn_time; + } + else if (timePointName == "dusk") { + tasks[0].timestamp = sunCalcResult.dusk_time; + } + else if (timePointName == "luxOn") { + tasks[0].timestamp = sunCalcResult.dusk_time + params.dusk_lux_sensor_time_window * 60000; + } + else if (timePointName == "luxOff") { + tasks[0].timestamp = sunCalcResult.dawn_time + params.dawn_lux_sensor_time_window * 60000; + } + else if (timePointName == "profileTimepoint") { + tasks[0].timestamp = currentTimestamp + tasks[0].addMinutesToTimestamp * 60000; + } + + let info = "aplikovany bod profilu"; + let onOrOff = ""; + value == 1 ? onOrOff = "on" : onOrOff = "off"; + + turnLine(onOrOff, params.line, info); + + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + if (!SETTINGS.masterNodeIsResponding) { + //ak neodpoveda, nebudeme vykonavat ziadne commands, okrem cmd-terminal cmd-master + errorHandler.sendMessageToService("Master node is not responding"); + + let stop = true; + + if (type === "cmd-terminal" || type === "cmd-master") stop = false; + if (stop) { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + } + + let contactorStatus = 1; + if (relaysData[line] != undefined) contactorStatus = relaysData[line].contactor; + + if (line === 0 || contactorStatus === 0 || FLOW.deviceStatus.state_of_breaker[line] === "Off") { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + // TODO: -> status offline for rvo if rotary_switch_state is OFF, this is source of errors + // check if rotary_switch_state == "Off" + // state_of_braker: disconnected = true? + + if (!rsPort.isOpen) { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + //RE-CALCULATE VALUES + //set actual time for broadcast + if (register == 87 && params.recipient === 2) { + var d = new Date(); + params.byte1 = d.getHours();//h + params.byte2 = d.getMinutes();//m + } + + //SET DUSK/DAWN FOR BROADCAST + //Time of dusk + if (register == 6 && params.recipient === 2) { + + if (type != "cmd-terminal") { + params.byte1 = sunCalcResult["dusk_hours"];//h + params.byte2 = sunCalcResult["dusk_minutes"];//m + } + } + + //Time of dawn + if (register == 7 && params.recipient === 2) { + if (type != "cmd-terminal") { + params.byte1 = sunCalcResult["dawn_hours"];//h + params.byte2 = sunCalcResult["dawn_minutes"];//m + } + } + //----------------------- + + instance.send(SEND_TO.debug, "address: " + node + " register:" + register + "type: " + type); + + var startTime, endTime; + startTime = new Date(); + + let saveToTb = true; + if (!tbname) saveToTb = false; + + let resp = com_generic(node, params.recipient, params.rw, register, params.name, params.byte1, params.byte2, params.byte3, params.byte4); + let readBytes = 11; + let timeout = 4000; + + + // await keyword is important, otherwise incorrect data is returned! + await writeData(rsPort, resp, readBytes, timeout).then(function(data) { + + //sometimes happens, that status of node changes to OK, NOK even if line was turned off and should be status OFFLINE. To prevent this, we return if line contactor is 0: + if (itIsNodeCommand && line && relaysData[line].contactor !== 1) return; + + 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); + + //ak sa odpoved zacina 0 - je to v poriadku, inak je NOK + let message = result.message; // OK, NOK + let message_type = result.type; + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + console.log("detected response:", result); + logger.debug("Cmd-mngr: writeData done " + message_type + " duration: " + timeDiff + " type: " + params.debug, params, result); + } + } + + let values = {}; + + //CMD FINISHED + if (message == "OK") { + + updateNodeStatus(node, true); + + //write + if (type == "set_node_profile") { + let result = cmdCounterResolve(node); + if (result == 0) { + dbNodes.modify({ processed: true }).where("node", node).make(function(builder) { + builder.callback(function(err, response) { + + sendNotification("Cmd-mngr: process cmd", SETTINGS.rvoTbName, "dimming_profile_was_successfully_received_by_node", { node: node }, "", SEND_TO.tb, instance); + + logger.debug("--> profil úspešne odoslaný na node č. " + node); + nodesData[node].processed = true; + nodeProfileSendFail.delete(node); + }); + }); + } + } + + //parse read response + if (params.rw == 0) { + values = processResponse(register, dataBytes); //read + } + + if (itIsNodeCommand) { + values.comm_status = "OK"; + values.status = "OK"; + nodesData[node].readout = { ...nodesData[node].readout, ...values }; + + + if (SETTINGS.daily_report) { + //TODO: co ak nedostavame odpovede z nodu ? Musime vyreportovat!! + //v dailyReport teda musi byt kompletny zoznam nodov a neustale kontrolovat, ci maju data, ak nie report node - neodpoveda + if (register === 1) { + + let now = Date.now(); + + if (rvo_is_on === true) { + + if ("dimmingIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].dimmingIsOnButShouldBeOffTime; + + if (values.dimming > 0) { + if ("dimmingIsZeroTime" in dailyReport[node]) delete dailyReport[node].dimmingIsZeroTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if (!("dimmingIsZeroTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], dimmingIsZeroTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } else { + + if ("dimmingIsZeroTime" in dailyReport[node]) delete dailyReport[node].dimmingIsZeroTime; + + if (values.dimming > 0) { + if (!("dimmingIsOnButShouldBeOffTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], dimmingIsOnButShouldBeOffTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if ("dimmingIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].dimmingIsOnButShouldBeOffTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } + } + + if (register === 76) { + + let now = Date.now(); + + if (rvo_is_on === true) { + + if ("powerIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].powerIsOnButShouldBeOffTime; + + if (values.power > 1) { + if ("powerIsZeroTime" in dailyReport[node]) delete dailyReport[node].powerIsZeroTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if (!("powerIsZeroTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], powerIsZeroTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } else { + + if ("powerIsZeroTime" in dailyReport[node]) delete dailyReport[node].powerIsZeroTime; + + if (values.power > 1) { + if (!("powerIsOnButShouldBeOffTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], powerIsOnButShouldBeOffTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if ("powerIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].powerIsOnButShouldBeOffTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } + } + } + + } + + //master node + if (node == 0) { + sendNotification("Cmd-mngr: 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; + } + + if (params.debug) { + //logger.debug("saveToTb", saveToTb, tbname, values); + } + + if (saveToTb && type != "node-regular-read") { + sendTelemetry(values, tbname); + } + else { + if (type == "cmd-terminal") { + terminalCommandResponse(params, "SUCCESS", data); + } + } + + } + else { + terminalCommandResponse(params, "ERROR", data); + handleNokResponseOnRsPort("handleNOK else block", params, itIsNodeCommand, saveToTb); + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + //logger.debug("writeData err: ", error, result, params); + logger.debug("writeData err: ", tbname, node, register, values); + } + } + + //logger.debug(error, result, params); + } + }).catch(function(reason) { + + //console.log("writeData catch exception", reason); + instance.send(SEND_TO.debug, reason); + + terminalCommandResponse(params, "FAILURE", null, reason); + handleNokResponseOnRsPort("handleNOK catch block", params, itIsNodeCommand, saveToTb); + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + logger.debug("-->WRITE FAILED: " + reason, params.debug, params); + } + } + + }); + + } + 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); + } + + + // if node does not respond to request, we repeat request 3 times: + function repeatCommand(params) { + params.repeatCounter++; + if (params.repeatCounter < 4) { + params.timestamp = 0; + params.addMinutesToTimestamp = 0; + tasks.push(params); + } + } + + function handleNokResponseOnRsPort(message, params, itIsNodeCommand, saveToTb) { + + let node = params.address; + let register = params.register; + let type = params.type; + let tbName = params.tbname; + if (!tbName) return; + + let values = {}; + + let updateStatus = updateNodeStatus(node, false); + + if (itIsNodeCommand) { + values.comm_status = "NOK"; + nodesData[node].readout.comm_status = "NOK"; + repeatCommand(params); + } + + if (updateStatus) { + values.status = "NOK"; + nodesData[node].readout.status = "NOK"; + } + + if (type === "node-regular-read") return; + + //master node + if (node == 0) { + sendNotification("Cmd-mngr: 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; + + if (register == 4) values["master_node_version"] = "NOK"; + } + + if (type == "set_node_profile") { + delete cmdCounter[node]; + logger.debug("profil nebol úspešne odoslaný na node č. ", params); + + if (!nodeProfileSendFail.has(node)) { + sendNotification("Cmd-mngr: process cmd", tbName, "configuration_of_dimming_profile_to_node_failed", { node: node }, "", SEND_TO.tb, instance); + nodeProfileSendFail.add(node); + } + } + + // console.log("------",node, register, type, itIsNodeCommand, updateStatus, saveToTb, values); + if (saveToTb) { + sendTelemetry(values, tbName); + } + + } + + + function sendNodesData() { + Object.keys(nodesData).forEach(node => { + if (nodesData[node]["status"] !== "OFFLINE") { + sendTelemetry(nodesData[node].readout, nodesData[node].tbname); + nodesData[node].readout = {}; + } + }) + } + + + /** + * 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; + } + + 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); + + //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 === "OFFLINE") { + nodeObj.node_status_before_offline === true ? number_of_ok_luminaires++ : number_of_nok_luminaires++; + } + else if (nodeObj.status == true) 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 - ts % 60000 //round to full minute + }; + + sendTelemetry(values, SETTINGS.rvoTbName, ts); + } + + + function setSunCalcResult() { + //if next day, we get new dusk and dawn. To make sure, in local timezone 2:00 means 00:00 in utc (it means next day) + if (new Date().getHours() === 2) { + sunCalcResult = calculateDuskDawn(); + console.log("Novy suncalc: ", sunCalcResult); + } + } + + + function setRvoPeriod() { + + if (!SETTINGS.daily_report) return; + + const ts = Date.now(); + + previous_rvo_is_on_value = rvo_is_on; + + if (ts < sunCalcResult.dawn_time - 1_800_000) { // nodes should be on (00:00 -> 06:00 ( - pol hodina, lebo rvo vypina skor) + rvo_is_on = true; + } else if (sunCalcResult.dawn_time - 1_800_000 < ts && ts < sunCalcResult.dusk_time + 1_800_000) { // nodes should be off 06:00 -> 21:00 + rvo_is_on = false; + } else if (sunCalcResult.dusk_time + 1_800_000 < ts) { // nodes should be on 21:00 -> 00:00 + rvo_is_on = true; + } + + if (previous_rvo_is_on_value !== rvo_is_on) { + emptyDailyReport(); + console.log("rvo_is: ", rvo_is_on, previous_rvo_is_on_value); + } + } + + + function handleRsPort() { + + if (rsPort) { + rsPort.removeAllListeners(); + rsPort = null; + } + + //! 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-mngr: rsPort opened success"); + + 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); + + }).catch(function(reason) { + instance.send(SEND_TO.debug, "Cmd-mngr: RPC runSyncExec - promise rejected:" + reason); + }); + }); + + rsPort.on('error', function(err) { + errorHandler.sendMessageToService([exports.title, "unable to open port", SETTINGS.serial_port, err.message], 0); + monitor.info("Cmd-mngr: Error on rsPort", err.message); + }); + + rsPort.on("close", () => { + monitor.info("Cmd-mngr: rsPort closed, reconnecting..."); + setTimeout(handleRsPort, 1000); + }); + + rsPort.open(); + } + + + instance.on("close", () => { + clearInterval(interval); + clearInterval(customTasksInterval); + clearInterval(setCorrectTime); + clearInterval(sendNodeReadout); + clearInterval(accelerometerInterval); + rsPort.close(); + }); + + instance.on("0", _ => { + main(); + }) + + + instance.on("2", _ => { + console.log("dailyReport, reportToSend, rvo_is_on", dailyReport, reportToSend, rvo_is_on, previous_rvo_is_on_value); + }) + + instance.on("1", 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(); + return; + } + else if (flowdata.data == "close") { + rsPort.close(); + return; + } + else if (flowdata.data == "clean") { + tasks = []; + return; + } + else if (flowdata.data == "buildtasks") { + //build & run + return; + } + else if (flowdata.data == "run") { + //durations = []; + + if (tasks.length == 0) { + + buildTasks(); + + if (rsPort.isOpen) { + interval = setInterval(runTasks, 100); + } + else { + instance.send(SEND_TO.debug, "port is not opened!!!"); + } + } + } + else { + //terminal data - object + //logger.debug("flowdata", flowdata.data); + + if (typeof flowdata.data === 'object') { + //logger.debug("dido", flowdata.data); + if (flowdata.data.hasOwnProperty("sender")) { + //data from dido_controller + if (flowdata.data.sender == "dido_controller") { + + if (flowdata.data.hasOwnProperty("cmd")) { + let cmd = flowdata.data.cmd; + + if (cmd == "buildTasks") { + clearInterval(interval); + + logger.debug("-->Cmd-mngr: BUILD TASKS"); + buildTasks(); + + //logger.debug("tasks:"); + //logger.debug(tasks); + + logger.debug("-->Cmd-mngr: RUN TASKS"); + interval = setInterval(runTasks, 5000); + } + else if (cmd == "reload_relays") { + loadRelaysData(flowdata.data.line); + + if (flowdata.data.dataChanged) { + if (!flowdata.data.value) { + reportOfflineNodeStatus(flowdata.data.line); + } + else { + reportOnlineNodeStatus(flowdata.data.line); + } + } + + } + else if (cmd == "rotary_switch_state") { + let value = flowdata.data.value; + + //state was changed + if (rotary_switch_state != value) { + if (value == "Off") { + //vyreportovat vsetky svietdla + reportOfflineNodeStatus(); + } + + rotary_switch_state = value; + } + } + 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) { + + // we send lux_sensor value to all nodes: + let params = getParams(PRIORITY_TYPES.node_broadcast); + + params.recipient = 2;//2 broadcast, address = 0 + params.address = 0xffffffff;//Broadcast + + let ba = longToByteArray(lux_sensor); + + params.byte3 = ba[1];//msb + params.byte4 = ba[0]; + params.timestamp = PRIORITY_TYPES.node_broadcast; + params.info = "run broadcast: Actual Lux level from cabinet"; + params.register = 95;//Actual Lux level from cabinet + params.rw = 1;//write + + tasks.push(params); + + //process profiles + turnOnOffLinesAccordingToLuxSensor(lux_sensor); + } + } + else if (cmd == "state_of_breaker") { + //istic linie + + breakerCounter--; + + let value = flowdata.data.value; + let line = parseInt(flowdata.data.line); + + let dataChanged = false; + if (state_of_breaker[line] != value) dataChanged = true; + + state_of_breaker[line] = value; + + let status = "OK"; + if (value == "Off") status = "NOK"; + + if (dataChanged) { + + if (relaysData.hasOwnProperty(line)) { + let tbname = relaysData[line].tbname; + + if (value == "Off") { + sendNotification("Cmd-mngr: onData", tbname, "circuit_breaker_was_turned_off_line", { line: line }, "", SEND_TO.tb, instance, "circuit_breaker"); + if (breakerCounter < 0) reportToSend["contactor"]["off"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + else { + sendNotification("Cmd-mngr: onData", tbname, "circuit_breaker_was_turned_on_line", { line: line }, "", SEND_TO.tb, instance, "circuit_breaker"); + if (breakerCounter < 0) reportToSend["contactor"]["on"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + + //report status liniu + sendTelemetry({ status: status }, tbname) + + //current value + if (value == "Off") reportOfflineNodeStatus(line); //vyreportovat vsetky svietidla na linii + } + + } + } + else { + logger.debug("undefined cmd", cmd); + } + } + } + + return; + } + + //data from worksys + if (flowdata.data.hasOwnProperty("topic")) { + + let data = getNested(flowdata.data, "content", "data"); + + //if we get temperature in senica from senica-prod01 + let temperature = getNested(flowdata.data, "content", "senica_temperature"); + + if (temperature !== undefined) { + temperatureInSenica = temperature; + return; + } + + if (data === undefined) { + console.log("Invalid rpc command came from platform"); + return; + } + + let command = data.params.command; + let method = data.method; + let profile = data.params.payload; + if (profile == undefined) profile = ""; + let entity = data.params.entities[0]; + let entity_type = entity.entity_type; + let tbname = entity.tb_name; + + instance.send(SEND_TO.debug, flowdata.data); + 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") { + + //let command = data.params.command; + let value = data.params.payload.value; + + if (command == "dimming") { + + let nodeWasFound = false; + let keys = Object.keys(nodesData); + + //logger.debug("-----", keys); + + 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); + + value = parseInt(value); + if (value > 0) value = value + 128; + + params.type = "node-onetime-write"; + params.tbname = tbname; + params.address = node; + params.register = 1; + params.recipient = 1; + params.byte4 = value; + params.rw = 1; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'set dimming from platform'; + //params.debug = true; + + //debug(params); + logger.debug("dimming", params); + + tasks.push(params); + + 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); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 1; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read dimming (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + //pridame aj vyreportovanie - vykon + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 76; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read Input Power (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + //pridame aj vyreportovanie - prud svietidla + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 75; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read Input Current (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + //pridame aj vyreportovanie - power faktor - ucinnik + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 77; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read power factor (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + }, 4000); + + nodeWasFound = true; + break; + } + } + + if (!nodeWasFound) { + logger.debug("set dimming from platform", "unable to find tbname", tbname); + } + } + else { + instance.send(SEND_TO.debug, "undefined command " + command); + logger.debug("undefined command", command); + } + + return; + } + 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++) { + let node = keys[i]; + if (tbname == nodesData[node].tbname) { + + 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"); + + //profil úspešne prijatý pre node č. xx + sendNotification("Cmd-mngr", tbname, "dimming_profile_was_processed_for_node", { node: node }, profile, SEND_TO.tb, instance); + + nodesData[node].processed = false; + nodesData[node].profile = profile; + + processNodeProfile(node); + }); + }); + } + } + } + else { + + instance.send(SEND_TO.debug, "unknown method " + method); + logger.debug("unknown method", method); + + return; + } + } + + //nastav profil linie z platformy + 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") { + + 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++) { + let line = keys[i]; + if (tbname == relaysData[line].tbname) { + //zmazeme tasky + 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) { + + //update profile + logger.debug("worksys - update relay profile done:", profile); + instance.send(SEND_TO.debug, "worksys - update relay profile done"); + + relaysData[line].profile = profile; + + loadRelaysData(line) + logger.debug("loadRelaysData DONE for line", line); + + buildTasks({ processLineProfiles: true, line: line }); + + sendNotification("Cmd-mngr: set profile from worksys", tbname, "switching_profile_was_processed_for_line", { line: line }, profile, SEND_TO.tb, instance); + }); + }); + break; + } + } + } + else if (method == "set_command") { + let value = data.params.payload.value; + + 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; + + 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"); + if (line != 0) reportToSend["contactor"]["off"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + else { + turnLine("on", line, "command received from platform"); + if (line != 0) reportToSend["contactor"]["on"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + } + } + else { + instance.send(SEND_TO.debug, "undefined method " + method); + logger.debug("undefined method", method); + } + + return; + } + else { + instance.send(SEND_TO.debug, "UNKNOW entity_type " + entity_type); + logger.debug("UNKNOW entity_type", entity_type); + } + return; + } + + //terminal + if (!rsPort.isOpen) await rsPort.open(); + + let params = flowdata.data.body; + if (params == undefined) { + //logger.debug("Cmd-mngr: flowdata.data.body is undefined"); + return; + } + + params.priority = PRIORITY_TYPES.terminal; + params.type = "cmd-terminal"; + params.tbname = ""; + params.timestamp = PRIORITY_TYPES.terminal; + params.addMinutesToTimestamp = 0;// do not repeat task!!! + params.debug = true; + + let timestamp = Date.now(); + params.refFlowdataKey = timestamp; + //params.refFlowdata = flowdata; + //refFlowdata = flowdata; + + //console.log("flowdata", flowdata); + + cleanUpRefFlowdataObj(); + + refFlowdataObj[timestamp] = flowdata; + + //fix + //params.address = params.adress; + logger.debug("received from terminal", params); + logger.debug("date/time:", new Date()); + logger.debug("tasks length:", tasks.length); + + //tasks = []; + + //add to tasks + tasks.push(params); + + } + } + }) + + + //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) + } + + + /** + * 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; + + RESTBuilder.make(function(builder) { + + if (!builder) return; + + builder.method('GET'); + builder.url('http://192.168.252.2:8004/gettime?projects_id=1'); + + builder.callback(function(err, response, output) { + + 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); + } + + }); + } + + } 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); + + } else { + //console.log("Read-only", stdout); + + 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]: [ + { + "ts": date, + "values": values + } + ] + } + + tbHandler.sendToTb(dataToTb, instance); + } + + + function calculateDuskDawn(date, line, duskOffset = 0, dawnOffset = 0) { + + if (date === undefined) date = new Date(); + + 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); + } + + //if(profile.dawn_lux_sensor == false) + { + if (profile.hasOwnProperty("dawn_astro_clock_offset")) dawn_astro_clock_offset = parseInt(profile.dawn_astro_clock_offset); + } + + } + + } catch (error) { + if (profilestr != "") { + logger.debug(profilestr); + logger.debug(error); + } + } + + 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; + } + + //Dimming, CCT + else if (register == 1) { + let brightness = 0; + let dimming = byte0; + if (dimming > 128) { + //dimming = -128; + brightness = dimming - 128; + } + + //cct + //Ak Byte3 == 1: CCT = (Byte2*256)+Byte1 + let cct; + if (byte3 == 1) cct = byte2 * 256 + byte1; + else cct = bytesToInt(bytes.slice(0, 3)); + + //cct podla auditu + + values["dimming"] = brightness; + return values; + } + + // + else if (register == 4) { + values["master_node_version"] = bytes[1] + "." + bytes[2]; + //logger.debug("FW Version", register, bytes); + } + + //Napätie + else if (register == 74) { + let voltage = (bytesToInt(bytes) * 0.1).toFixed(1); + values["voltage"] = Number(voltage); + } + + //Prúd + else if (register == 75) { + let current = bytesToInt(bytes); + values["current"] = current; + } + + //výkon + else if (register == 76) { + let power = (bytesToInt(bytes) * 0.1).toFixed(2); + values["power"] = Number(power); + } + + //účinník + else if (register == 77) { + let power_factor = Math.cos(bytesToInt(bytes) * 0.1 * (Math.PI / 180)).toFixed(2); + values["power_factor"] = Number(power_factor); + } + + //frekvencia + else if (register == 78) { + let frequency = (bytesToInt(bytes) * 0.1).toFixed(2); + values["frequency"] = Number(frequency); + } + + //energia + else if (register == 79) { + let energy = bytesToInt(bytes); + values["energy"] = energy / 1000; //energia v kWh -> delit 1000 + } + + //doba života + else if (register == 80) { + let lifetime = (bytesToInt(bytes) / 60).toFixed(2); + values["lifetime"] = Number(lifetime); + } + + //nastavenie profilu + else if (register == 8) { + let time_schedule_settings = bytesToInt(bytes); + values["time_schedule_settings"] = time_schedule_settings; + } + + //naklon - nateraz sa z nodu nevycitava! kvoli problemom s accelerometrom a vracanymi hodnotami, posielame temp a x y z vo funkcii accelerometerData() + else if (register == 84) { + values["temperature"] = byte3 >= 128 ? (byte3 - 128) * (-1) : byte3; + values["inclination_x"] = byte2 >= 128 ? (byte2 - 128) * (-1) : byte2; + values["inclination_y"] = byte1 >= 128 ? (byte1 - 128) * (-1) : byte1; + values["inclination_z"] = byte0 >= 128 ? (byte0 - 128) * (-1) : byte0; + } + + //FW verzia nodu + else if (register == 89) { + //formát: "Byte3: Byte2.Byte1 (Byte0)" + values["fw_version"] = byte3 + ":" + byte2 + "." + byte1 + "(" + byte0 + ")"; + } + + else if (register == 87 || register == 6 || register == 7) { + var d = new Date(); + d.setHours(byte3, byte2, 0, 0); + let timestamp = d.getTime(); + + //aktuálny čas + if (register == 87) values["actual_time"] = timestamp; + //čas súmraku + else if (register == 6) values["dusk_time"] = timestamp; + //čas úsvitu + else if (register == 7) values["dawn_time"] = timestamp; + } + + 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; + + } + + + function getObjectByTbValue(object, tbname) { + return object[Object.keys(object).find(key => object[key].tbname === tbname)]; + } + + + function isObject(item) { + return (typeof item === "object" && !Array.isArray(item) && item !== null); + } + + + // we fake data, that should be received from accelerometer, as they are a bit unreliable. (temperature, x,y,z) + function accelerometerData() { + + if (temperatureInSenica === null) return; + + //clone nodesData and relaysData objects + let nodesData_clone = JSON.parse(JSON.stringify(nodesData)); + let relaysData_clone = JSON.parse(JSON.stringify(relaysData)); + + for (const key in relaysData_clone) { + + const lineData = relaysData_clone[key]; + const lineNumber = lineData.line; + const contactor = lineData.contactor; + + if (lineNumber === 0) continue; + + if (contactor === 1) { + + let date = Date.now(); + + Object.keys(nodesData_clone).forEach((node, index) => { + + setTimeout(function() { + + if (nodesData_clone[node].line === lineNumber) { + + // NOTE: if status of luminaire is NOK or OFFLINE, we do not send data; + let status = nodesData_clone[node].status; + if (status === "OFFLINE" || !status) return; + + let x = null; + if (naklony.hasOwnProperty(node)) x = naklony[node].naklon; + if (x === null) x = 0; + + sendTelemetry({ temperature: Math.round(temperatureInSenica + 10 + Math.floor(Math.random() * 3)), inclination_x: x, inclination_y: 0, inclination_z: 0 }, nodesData_clone[node].tbname, date); + } + + }, (index + 1) * 500); + }) + + } + } + } + + +} // end of instance.export + diff --git a/RVO4/flow/code.js b/RVO4/flow/code.js new file mode 100755 index 0000000..63b31bf --- /dev/null +++ b/RVO4/flow/code.js @@ -0,0 +1,90 @@ +exports.id = 'code'; +exports.title = 'Code'; +exports.group = 'Common'; +exports.color = '#656D78'; +exports.input = true; +exports.output = 1; +exports.author = 'Peter Širka'; +exports.icon = 'code'; +exports.version = '1.2.0'; +exports.options = { outputs: 1, code: 'send(0, value);', keepmessage: true }; + +exports.html = `
+
+
+
@(Number of outputs)
+
@(Minimum is 1)
+
+
+
@(Code)
+
@(Keep message instance)
+
+`; + +exports.readme = `# Code + +This component executes custom JavaScript code as it is and it doesn't contain any secure scope. + +\`\`\`javascript +// value {Object} contains received data +// send(outputIndex, newValue) sends a new value +// error(value) sends an error +// instance {Object} a current component instance +// flowdata {Object} a current flowdata +// repository {Object} a current repository of flowdata +// Example: + +// send() can be execute multiple times +send(0, value); +\`\`\``; + +exports.install = function(instance) { + + var fn; + + instance.on('data', function(response) { + if (fn) { + try { + fn(response.data, instance, response, instance.options, response.repository, require); + } catch (e) { + response.data = e; + instance.throw(response); + } + } + }); + + instance.reconfigure = function() { + try { + if (instance.options.code) { + instance.status(''); + var code = 'var send = function(index, value) { if (options.keepmessage) { flowdata.data = value; instance.send2(index, flowdata); } else instance.send2(index, value);}; var error = function(err) { instance.throw(err); }; ' + instance.options.code; + fn = new Function('value', 'instance', 'flowdata', 'options', 'repository', 'require', code); + } else { + instance.status('Not configured', 'red'); + fn = null; + } + } catch (e) { + fn = null; + instance.error('Code: ' + e.message); + } + }; + + instance.on('options', instance.reconfigure); + instance.reconfigure(); +}; \ No newline at end of file diff --git a/RVO4/flow/comment.js b/RVO4/flow/comment.js new file mode 100755 index 0000000..1e0cd13 --- /dev/null +++ b/RVO4/flow/comment.js @@ -0,0 +1,11 @@ +exports.id = 'comment'; +exports.title = 'Comment'; +exports.group = 'Common'; +exports.color = '#704cff'; +exports.author = 'Martin Smola'; +exports.icon = 'comment'; +exports.traffic = false; +exports.version = '1.0.0'; +exports.readme = '# Comment'; + +exports.install = function() {}; diff --git a/RVO4/flow/count.js b/RVO4/flow/count.js new file mode 100755 index 0000000..fa92ee9 --- /dev/null +++ b/RVO4/flow/count.js @@ -0,0 +1,60 @@ +exports.id = 'count'; +exports.title = 'Count'; +exports.version = '1.0.1'; +exports.author = 'John Graves'; +exports.color = '#656D78'; +exports.icon = 'plus-square'; +exports.input = 2; +exports.output = 1; +exports.options = { increment: 1, initialvalue: 1 }; +exports.readme = `# Counter + +Counter Number of times called.`; + +exports.html = `
+
@(Initial Value)
+
@(Increment)
+

Example Video

+
`; + +exports.readme = `# Count + +This component counts the number of messages received. + +__Response:__ + +Integer value based on the initial value and increment settings. + +__Arguments:__ +- Initial Value: What number should be output on the receipt of the first message. +- Increment: What should the increment be for each following message received.`; + +exports.install = function(instance) { + + var count = 0; + var initialCall = true; + + instance.on('data', function(flowdata) { + var index = flowdata.index; + if (index) { + instance.debug('Reset Count.'); + count = instance.options.initialvalue; + initialCall = true; + } else { + // If this is the first time, set the value to 'initial value' + if(initialCall) { + initialCall = false; + count = instance.options.initialvalue; + } else + count = count+instance.options.increment; + instance.status('Count:' + count); + instance.send2(count); + } + }); + + instance.on('options', function() { + count = instance.options.initialvalue; + initialCall = true; + }); + +}; diff --git a/RVO4/flow/db_connector.js b/RVO4/flow/db_connector.js new file mode 100755 index 0000000..65ee94b --- /dev/null +++ b/RVO4/flow/db_connector.js @@ -0,0 +1,286 @@ +exports.id = 'db_connector'; +exports.title = 'DbConnector'; +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.html = `
+
+
+
DbConnector
+
+
+
`; + +exports.readme = `# read/write data to tables`; + +const instanceSendTo = { + debug: 0, + http_response: 1, +} + +const { promisifyBuilder, makeMapFromDbResult } = require('./helper/db_helper.js'); + +function extractWhereParams(params) +{ + let name = params[0]; + let operator = '='; + let value = params[1]; + + if(params.length == 3) + { + operator = params[1]; + value = params[2]; + } + + return {name: name, operator: operator, value: value}; +} + +exports.install = function(instance) { + + let refFlowdata = null;//holds reference to httprequest flowdata + + instance.on("close", () => { + + }) + + + instance.on("data", async function(flowdata) { + + let params = flowdata.data.body; + console.log("DbConnector", params); + + refFlowdata = flowdata; + + if(refFlowdata != undefined) + { + //make http response + let responseObj = {}; + responseObj["type"] = "SUCESS"; + + try{ + + let table = params.table; + let action = params.action; + + + if(params.data != undefined) + { + let className = params.data.className; + + if(className == "SqlQueryBuilder") + { + let type = params.data.type; + + console.log("SqlQueryBuilder---->", params.data); + + if(type == "SELECT") + { + let table = params.data.queryData.tables[0].table; + + const db = TABLE(table); + var builder = db.find(); + + let result = await promisifyBuilder(builder); + + let response = {}; + response["result"] = result; + response["success"] = true; + + responseObj["data"] = response; + + //console.log(responseObj); + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + } + + return; + } + } + + + console.log("db_connector---->", table, action); + + //actions: read, replace, insert, delete, update... + + if(action == "read") + { + const db = TABLE(params.table); + + //where builder.where('age', '<', 15); + //builder.where('id', 3403); + + var builder = db.find(); + + //https://docs.totaljs.com/latest/en.html#api~DatabaseBuilder~builder.where + if(params.hasOwnProperty("where")) + { + //optionalCan contain "=", "<=", "<", ">=", ">". + //Default value: '=' + + //1.["production_line", 1] + //2. ["or", ["production_line", 1], ["production_line", 2], "end"] + + if (Array.isArray(params.where)) { + + let multipleConditions = false; + + if(params.where[0] == "or") multipleConditions = true; + if (Array.isArray(params.where[0])) multipleConditions = true; + + if(multipleConditions) + { + + for(var i = 0; i < params.where.length; i++) + { + const item = params.where[i]; + + if(item === "or") builder.or(); + + if (Array.isArray(item)) + { + const { name, operator, value } = extractWhereParams(item); + builder.where(name, operator, value); + } + + if(item === "end") builder.end(); + + } + + } + else + { + const { name, operator, value } = extractWhereParams(params.where); + builder.where(name, operator, value); + } + + } + + /* + if(params.where.length >=2 ) + { + let name = params.where[0]; + let operator = '='; + let value = params.where[1]; + + if(params.where.length == 3) + { + operator = params.where[1]; + value = params.where[2]; + } + + builder.where(name, operator, value); + } + */ + } + + if(params.hasOwnProperty("between")) + { + builder.between(params.between[0], params.between[1], params.between[2]); + } + + let response = await promisifyBuilder(builder); + responseObj["data"] = response; + + //console.log(responseObj); + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + + return; + } + + if(action == "delete") + { + + } + + + if(action == "update") + { + //! data receiving from terminal (params) + // { + // hostname: 'localhost', + // table: 'settings', + // action: 'update', + // body: { + // rvo_name: 'terrrr', + // lang: 'en', + // temperature_adress: '28.427B45920702', + // latitude: 48.70826502, + // longitude: 17.28455203, + // mqtt_host: '192.168.252.4', + // mqtt_clientid: 'showroom_test_panel_led', + // mqtt_username: 'xmRd6RJxW53WZe4vMFLU', + // mqtt_port: 1883, + // maintanace_mode: false + // } + // } + const tableToModify = TABLE(params.table); + const newValues = params.body; + + tableToModify.modify(newValues).make(function(builder) { + + builder.callback(function(err, response) { + + if(!err) + { + responseObj["data"] = response; + responseObj["tableUpdated"] = true; + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + } + }); + }); + + } + + if(action == "replace") + { + //truncate table + const db = TABLE(params.table); + var builder = db.remove(); + db.clean(); + + //insert data + let data = params.data; + + for(let i = 0; i < data.length; i++) + { + //console.log(data[i]); + db.insert(data[i]); + } + + console.log("insert done"); + + let responseObj = {}; + responseObj["type"] = "SUCESS"; + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + + + } + + + + } catch (error) { + //console.log(error); + responseObj["type"] = "ERROR"; + responseObj["message"] = error; + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + } + } + }) +} + + diff --git a/RVO4/flow/db_init.js b/RVO4/flow/db_init.js new file mode 100755 index 0000000..b399878 --- /dev/null +++ b/RVO4/flow/db_init.js @@ -0,0 +1,113 @@ +exports.id = 'db_init'; +exports.title = 'DB Initialization'; +exports.group = 'Worksys'; +exports.color = '#888600'; +exports.version = '1.0.2'; +exports.icon = 'sign-out'; +exports.output = 2; + +exports.readme = ` + # DB initialization +`; + +const { promisifyBuilder, makeMapFromDbResult } = require('./helper/db_helper.js'); +const { initNotification } = require('./helper/notification_reporter'); +const errorHandler = require('./helper/ErrorToServiceHandler'); +const total_energy = require('../databases/total_energy'); + +const SEND_TO = { + db_init: 0, + infoSender: 1 +}; + + +exports.install = async function(instance) { + const dbNodes = TABLE("nodes"); + const dbRelays = TABLE("relays"); + const dbSettings = TABLE("settings"); + 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 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.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"]; + Object.keys(dbs.nodesData).forEach(node => dbs.nodesData[node].readout = {}) + + let rvo_number = responseSettings[0]["rvo_name"].match(/\D+(\d{1,2})_/)[1]; + + dbs.settings = { + edge_fw_version: "2025-10-08", //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"], + phases: responseSettings[0]["phases"], + cloud_topic: responseSettings[0]["cloud_topic"], + has_main_switch: responseSettings[0]["has_main_switch"], + daily_report: responseSettings[0]["daily_report"], + send_changed_node_numbers: responseSettings[0]["send_changed_node_numbers"], + rvo_number: rvo_number, + + //dynamic values + masterNodeIsResponding: true, //cmd_manager + maintenance_mode: false, + } + + + dbs.settings.energy_to_switch_lamps = total_energy[rvo_number]; + if (dbs.settings.energy_to_switch_lamps === undefined) console.log('=============== db_init.js: energy_to_switch_lamps is undefined'); + + FLOW.dbLoaded = true; + errorHandler.setProjectId(dbs.settings.project_id); + initNotification(); + + //APP START - send to data services + const toService = { + id: dbs.settings.project_id, + name: dbs.settings.rvo_name, + fw_version: dbs.settings.edge_fw_version, + startdate: new Date().toISOString().slice(0, 19).replace('T', ' '), + js_error: "", + error_message: "" + }; + + instance.send(SEND_TO.infoSender, toService); + console.log("----------------> START - message send to service", toService); + + setTimeout(() => { + console.log("DB_INIT - data loaded"); + instance.send(SEND_TO.db_init, "_") + }, 5000) + +}; + diff --git a/RVO4/flow/debug.js b/RVO4/flow/debug.js new file mode 100755 index 0000000..00cb259 --- /dev/null +++ b/RVO4/flow/debug.js @@ -0,0 +1,100 @@ +exports.id = 'debug'; +exports.title = 'Debug'; +exports.author = 'Peter Širka'; +exports.color = '#967ADC'; +exports.click = true; +exports.input = true; +exports.icon = 'bug'; +exports.version = '2.0.4'; +exports.options = { enabled: true, repository: false, type: 'data' }; +exports.readme = `# Debug + +Prints data to the debug tab.`; + +exports.html = `
+
+
+
@(Output type)
+
@(Path to the property (leave empty to show the whole data object))
+
@(A group name)
+
@(Enabled)
+
+
+
`; + +exports.install = function(instance) { + + instance.on('data', function(response) { + if (instance.options.enabled) { + + var opt = instance.options; + var rep = response.repository; + var val = response.data; + var id = response.id; + + switch (instance.options.type){ + case 'both': + var data = {}; + data.repository = rep; + data.data = val instanceof Error ? { error: val.message, stack: val.stack } : val; + instance.debug(safeparse(opt.property ? U.get(data, opt.property) : data), undefined, opt.group, id); + break; + case 'repository': + instance.debug(safeparse(opt.property ? U.get(rep, opt.property) : rep), undefined, opt.group, id); + break; + case 'data': + default: + if (val instanceof Error) + instance.debug({ error: val.message, stack: val.stack }, undefined, opt.group, id); + else + instance.debug(safeparse(opt.property ? U.get(val, opt.property) : val), undefined, opt.group, id); + break; + } + } + }); + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + instance.save(); + }); + + instance.on('options', function() { + instance.custom.status(); + }); + + instance.custom.status = function() { + instance.status(instance.options.enabled ? 'Enabled' : 'Disabled'); + }; + + instance.custom.status(); + + function safeparse(o) { + + if (o instanceof Buffer) + return o; + + if (o === undefined) + return 'undefined'; + + if (o === null) + return 'null'; + + var cache = []; + var str = JSON.stringify(o, function(key, value) { + if (typeof value === 'object' && value !== null) { + if (cache.indexOf(value) !== -1) { + try { + return JSON.parse(JSON.stringify(value)); + } catch (error) { + return; + } + } + cache.push(value); + } + return value; + }); + cache = null; + return JSON.parse(str); + } +}; diff --git a/RVO4/flow/designer.json b/RVO4/flow/designer.json new file mode 100755 index 0000000..580f5a3 --- /dev/null +++ b/RVO4/flow/designer.json @@ -0,0 +1,3102 @@ +{ + "tabs": [ + { + "name": "MAIN PUSH", + "linker": "main-push", + "id": "1612772287426", + "index": 0 + }, + { + "name": "CMD manager", + "linker": "cmd-manager", + "id": "1615551125555", + "index": 1 + }, + { + "name": "Devices", + "linker": "devices", + "id": "1611921777196", + "index": 2 + } + ], + "components": [ + { + "id": "1611951142547", + "component": "debug", + "tab": "1611921777196", + "name": "ERROR", + "x": 598, + "y": 60, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#DA4453", + "notes": "" + }, + { + "id": "1612776786008", + "component": "wsmqttpublish", + "tab": "1612772287426", + "name": "WS MQTT publish", + "x": 281.75, + "y": 174, + "connections": { + "0": [ + { + "index": "0", + "id": "1615551060773" + } + ], + "1": [ + { + "index": "0", + "id": "1618300858252" + }, + { + "index": "0", + "id": "1618558465485" + } + ], + "2": [ + { + "index": "0", + "id": "1634303685503" + } + ], + "3": [ + { + "index": "0", + "id": "1731068754606" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Connected", + "color": "green" + }, + "options": { + "username": "", + "clientid": "", + "port": "1883", + "host": "" + }, + "color": "#888600", + "notes": "" + }, + { + "id": "1612778461252", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "tb-push", + "x": 72.75, + "y": 328, + "connections": { + "0": [ + { + "index": "0", + "id": "1612783322136" + }, + { + "index": "1", + "id": "1612776786008" + }, + { + "index": "0", + "id": "1731068754606" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1612783322136", + "component": "debug", + "tab": "1612772287426", + "name": "to TB", + "x": 283.75, + "y": 324, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615551060773", + "component": "debug", + "tab": "1612772287426", + "name": "errors from MQTT Broker", + "x": 594, + "y": 57, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#DA4453", + "notes": "" + }, + { + "id": "1615563373927", + "component": "debug", + "tab": "1615551125555", + "name": "Debug", + "x": 755, + "y": 155, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#DA4453", + "notes": "" + }, + { + "id": "1615566865233", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "tb-push", + "x": 755, + "y": 248, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1615798582262", + "component": "debug", + "tab": "1615551125555", + "name": "CMD_debug", + "x": 755, + "y": 346, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615802995322", + "component": "debug", + "tab": "1611921777196", + "name": "Debug", + "x": 596.8833312988281, + "y": 566.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Disabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": false + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615809128443", + "component": "debug", + "tab": "1611921777196", + "name": "tempToTb", + "x": 595.8833312988281, + "y": 658.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615809595184", + "component": "virtualwireout", + "tab": "1611921777196", + "name": "tb-push", + "x": 597.8833312988281, + "y": 377.25, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1616165795916", + "component": "httproute", + "tab": "1615551125555", + "name": "POST /terminal", + "x": 135, + "y": 547, + "connections": { + "0": [ + { + "index": "0", + "id": "1684060205000" + }, + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Listening", + "color": "green" + }, + "options": { + "timeout": 10, + "cachepolicy": 0, + "cacheexpire": "5 minutes", + "size": 5, + "url": "/terminal", + "method": "POST", + "name": "", + "flags": [ + "id:1616165795916", + "post", + 10000 + ], + "emptyresponse": false + }, + "color": "#5D9CEC", + "notes": "### Configuration\n\n- __POST /terminal__\n- flags: \n- maximum request data length: __5 kB__\n- empty response: __false__\n- cache policy: __no cache__\n- cache expire: __5 minutes__", + "cloning": false + }, + { + "id": "1616165824813", + "component": "httpresponse", + "tab": "1615551125555", + "name": "HTTP Response", + "x": 753, + "y": 423, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "json" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1617104731852", + "component": "debug", + "tab": "1615551125555", + "name": "DIDO_Debug", + "x": 669, + "y": 1040, + "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": "turnOff line", + "x": 133, + "y": 1161, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "object", + "data": "{line: 3, command: \"turnOff\", force: true}" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1617115013095", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "tb-push", + "x": 669, + "y": 1150, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1617284749681", + "component": "trigger", + "tab": "1615551125555", + "name": "update profile / node", + "x": 112, + "y": 208, + "connections": { + "0": [ + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "data": "profile_nodes", + "datatype": "string" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1618235171399", + "component": "trigger", + "tab": "1615551125555", + "name": "tun tasks", + "x": 184, + "y": 279, + "connections": { + "0": [ + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "data": "run" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1618300858252", + "component": "debug", + "tab": "1612772287426", + "name": "wsmqtt-exit1", + "x": 597.8833312988281, + "y": 149, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1618393583970", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "to-cmd-manager", + "x": 668.8833312988281, + "y": 1269, + "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": 132.88333129882812, + "y": 367, + "connections": { + "0": [ + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "platform-rpc-call", + "color": "gray" + }, + "options": { + "wirename": "platform-rpc-call" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1618393759854", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "cmd_to_dido", + "x": 119.88333129882812, + "y": 1007, + "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": 752.8833312988281, + "y": 527, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "cmd_to_dido", + "color": "gray" + }, + "options": { + "wirename": "cmd_to_dido" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1618558465485", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "platform-rpc-call", + "x": 597.8833312988281, + "y": 247, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "platform-rpc-call", + "color": "gray" + }, + "options": { + "wirename": "platform-rpc-call" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1618572059773", + "component": "trigger", + "tab": "1615551125555", + "name": "turnOn line", + "x": 132, + "y": 1085, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "data": "{line: 1, command: \"turnOn\", force: true}", + "datatype": "object" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1619515097737", + "component": "cmd_manager", + "tab": "1615551125555", + "name": "CMD Manager", + "x": 452.1091003417969, + "y": 341.05455017089844, + "connections": { + "0": [ + { + "index": "0", + "id": "1615563373927" + } + ], + "1": [ + { + "index": "0", + "id": "1615566865233" + }, + { + "index": "0", + "id": "1615798582262" + } + ], + "2": [ + { + "index": "0", + "id": "1616165824813" + } + ], + "3": [ + { + "index": "0", + "id": "1618393827655" + } + ], + "4": [ + { + "index": "0", + "id": "1635936391935" + } + ], + "5": [ + { + "index": "0", + "id": "1757006030239" + }, + { + "index": "0", + "id": "1757006060377" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1619605019281", + "component": "httproute", + "tab": "1615551125555", + "name": "GET db", + "x": 173, + "y": 653, + "connections": { + "0": [ + { + "index": "0", + "id": "1684060205000" + }, + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Listening", + "color": "green" + }, + "options": { + "timeout": 5, + "cachepolicy": 0, + "cacheexpire": "5 minutes", + "size": 5, + "url": "/db", + "method": "GET", + "name": "", + "flags": [ + "id:1619605019281", + "get", + 5000 + ] + }, + "color": "#5D9CEC", + "notes": "### Configuration\n\n- __GET /db__\n- flags: undefined\n- maximum request data length: __5 kB__\n- empty response: __undefined__\n- cache policy: __no cache__\n- cache expire: __5 minutes__", + "cloning": false + }, + { + "id": "1619784672383", + "component": "trigger", + "tab": "1615551125555", + "name": "turnOnAlarm", + "x": 120, + "y": 1234, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "object", + "data": "{command: \"turnOnAlarm\"}" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1619784812964", + "component": "trigger", + "tab": "1615551125555", + "name": "turnOffAlarm", + "x": 118, + "y": 1307, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "object", + "data": "{command: \"turnOffAlarm\"}" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1621340721628", + "component": "virtualwireout", + "tab": "1611921777196", + "name": "modbus_to_dido", + "x": 599, + "y": 471, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "modbus_to_dido", + "color": "gray" + }, + "options": { + "wirename": "modbus_to_dido" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1622640022885", + "component": "httproute", + "tab": "1615551125555", + "name": "POST /db_connector", + "x": 98, + "y": 1586, + "connections": { + "0": [ + { + "index": "0", + "id": "1622640073521" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Listening", + "color": "green" + }, + "options": { + "timeout": 5, + "cachepolicy": 0, + "cacheexpire": "5 minutes", + "size": 5, + "url": "/db_connector", + "method": "POST", + "flags": [ + "id:1622640022885", + "post", + 5000 + ] + }, + "color": "#5D9CEC", + "notes": "### Configuration\n\n- __POST /db_connector__\n- flags: \n- maximum request data length: __5 kB__\n- empty response: __undefined__\n- cache policy: __no cache__\n- cache expire: __5 minutes__", + "cloning": false + }, + { + "id": "1622640073521", + "component": "db_connector", + "tab": "1615551125555", + "name": "DbConnector", + "x": 372, + "y": 1572, + "connections": { + "1": [ + { + "index": "0", + "id": "1622641420685" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "edge": "undefined" + }, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1622641420685", + "component": "httpresponse", + "tab": "1615551125555", + "name": "HTTP Response", + "x": 596, + "y": 1586, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1634303504177", + "component": "monitormemory", + "tab": "1612772287426", + "name": "RAM", + "x": 69.88333129882812, + "y": 888.5, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465281992" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "858.88 MB / 985.68 MB", + "color": "gray" + }, + "options": { + "enabled": true, + "interval": 30000 + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1634303533779", + "component": "monitordisk", + "tab": "1612772287426", + "name": "disk", + "x": 70.88333129882812, + "y": 982.5, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465821120" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "5.78 GB / 7.26 GB", + "color": "gray" + }, + "options": { + "enabled": true, + "path": "/", + "interval": 30000 + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1634303595494", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "send-to-services", + "x": 51.883331298828125, + "y": 1400.5, + "connections": { + "0": [ + { + "index": "0", + "id": "1634463186563" + }, + { + "index": "1", + "id": "1634488120710" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1634303602169", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "send-to-services", + "x": 426.8833312988281, + "y": 878.5, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1634303685503", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "send-to-services", + "x": 600.8833312988281, + "y": 341.5, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1634303743260", + "component": "httprequest", + "tab": "1612772287426", + "name": "192.168.252.2:8004/sentmessage", + "reference": "", + "x": 506.8833312988281, + "y": 1331.7333374023438, + "connections": { + "0": [ + { + "index": "0", + "id": "1635327431236" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "url": "http://192.168.252.2:8004/sentmessage", + "method": "POST", + "stringify": "json" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1634463186563", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 305.75, + "y": 1442, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634464580289", + "component": "code", + "tab": "1612772287426", + "name": "Code", + "x": 245, + "y": 787, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465243324" + }, + { + "index": "0", + "id": "1634303602169" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "keepmessage": true, + "code": "let response = {};\nresponse.cpu = value.cpu;\nresponse.uptime = value.uptime;\n\nsend(0, response);", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1634465243324", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 428, + "y": 784, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634465281992", + "component": "code", + "tab": "1612772287426", + "name": "Code", + "x": 245, + "y": 884, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465338103" + }, + { + "index": "0", + "id": "1634303602169" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "keepmessage": true, + "code": "value.sender = \"ram\";\n\nlet response = {};\n\nresponse.memory_total = Math.round(value.total / (1024 ** 2));\nresponse.memory_free = Math.round(value.free / (1024 ** 2));\nresponse.memory_used = Math.round(value.used / (1024 ** 2));\n\nsend(0, response);", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1634465338103", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 429, + "y": 976, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634465821120", + "component": "code", + "tab": "1612772287426", + "name": "Code", + "x": 245, + "y": 978, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465892500" + }, + { + "index": "0", + "id": "1634303602169" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "keepmessage": true, + "code": "value.sender = \"hdd\";\n\nlet response = {};\n\nresponse.hdd_total = Math.round(value.total / (1024 ** 2));\nresponse.hdd_free = Math.round(value.free / (1024 ** 2));\nresponse.hdd_used = Math.round(value.used / (1024 ** 2));\n\nsend(0, response);", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1634465892500", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 432, + "y": 1068, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634484067516", + "component": "debug", + "tab": "1612772287426", + "name": "Send info", + "x": 513, + "y": 1441, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634488120710", + "component": "infosender", + "tab": "1612772287426", + "name": "Info sender", + "x": 301, + "y": 1336, + "connections": { + "0": [ + { + "index": "0", + "id": "1634484067516" + }, + { + "index": "0", + "id": "1634303743260" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "edge": "undefined" + }, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1635327431236", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 837.8833312988281, + "y": 1325.5, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1635936391935", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "send-to-services", + "x": 753, + "y": 623, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1637069803394", + "component": "monitorconsumption", + "tab": "1612772287426", + "name": "CPU", + "x": 69, + "y": 791, + "connections": { + "0": [ + { + "index": "0", + "id": "1634464580289" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "49.2% / 69.91 MB", + "color": "gray" + }, + "options": { + "monitorfiles": true, + "monitorconnections": true, + "monitorsize": true, + "monitorconsumption": true, + "enabled": true, + "interval": 30000 + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1683664161036", + "component": "debug", + "tab": "1615551125555", + "name": "CMDtoDIDO", + "x": 392, + "y": 1012, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1683981346282", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "from-dido-controller", + "x": 112, + "y": 459, + "connections": { + "0": [ + { + "index": "0", + "id": "1684055037116" + }, + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "from-dido-controller", + "color": "gray" + }, + "options": { + "wirename": "from-dido-controller" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1684055037116", + "component": "debug", + "tab": "1615551125555", + "name": "from dido to cmd", + "x": 451, + "y": 532, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1684060205000", + "component": "debug", + "tab": "1615551125555", + "name": "HTTP routes", + "x": 450, + "y": 639, + "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": "MDBToDido", + "x": 598, + "y": 147, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1699963668903", + "component": "dido_controller", + "tab": "1615551125555", + "name": "DIDO_Controller", + "x": 397, + "y": 1131, + "connections": { + "0": [ + { + "index": "0", + "id": "1617104731852" + } + ], + "1": [ + { + "index": "0", + "id": "1617104731852" + }, + { + "index": "0", + "id": "1617115013095" + } + ], + "2": [ + { + "index": "0", + "id": "1618393583970" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "edge": "undefined" + }, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1699964678894", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "modbus_to_dido", + "x": 96, + "y": 924, + "connections": { + "0": [ + { + "index": "0", + "id": "1699963668903" + }, + { + "index": "0", + "id": "1699964793925" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "modbus_to_dido", + "color": "gray" + }, + "options": { + "wirename": "modbus_to_dido" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1699964793925", + "component": "debug", + "tab": "1615551125555", + "name": "modbusToDido", + "x": 388, + "y": 920, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1699965957410", + "component": "modbus_reader", + "tab": "1611921777196", + "name": "Modbus reader", + "x": 232, + "y": 175, + "connections": { + "0": [ + { + "index": "0", + "id": "1611951142547" + } + ], + "1": [ + { + "index": "0", + "id": "1621340721628" + }, + { + "index": "0", + "id": "1684179110403" + }, + { + "index": "0", + "id": "1717441414646" + } + ], + "2": [ + { + "index": "0", + "id": "1615809595184" + }, + { + "index": "0", + "id": "1714752862828" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1700411878636", + "component": "thermometer", + "tab": "1611921777196", + "name": "Thermometer", + "x": 234.75, + "y": 444, + "connections": { + "0": [ + { + "index": "0", + "id": "1615802995322" + } + ], + "1": [ + { + "index": "0", + "id": "1615809595184" + }, + { + "index": "0", + "id": "1615809128443" + } + ], + "2": [ + { + "index": "0", + "id": "1621340721628" + }, + { + "index": "0", + "id": "1732889185927" + }, + { + "index": "0", + "id": "1717441414646" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#5CB36D", + "notes": "" + }, + { + "id": "1714752862828", + "component": "debug", + "tab": "1611921777196", + "name": "MDBToTb", + "x": 766, + "y": 324, + "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": 764.0833282470703, + "y": 222, + "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\telse if(value.status === \"NOK-thermometer\")\n\t{\n\t\tsend(0, {\"thermometer\": \"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\telse if(value.values.hasOwnProperty(\"temperature\"))\n\t{\n\t\tsend(0, {\"thermometer\": \"OK\"});\n\t}\n}", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1717442627834", + "component": "debug", + "tab": "1611921777196", + "name": "modbus service", + "x": 966.0833282470703, + "y": 165, + "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": 968.0833282470703, + "y": 268, + "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": 88.75, + "y": 1685, + "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": 296, + "y": 1671, + "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\", \"Flow has been restarted\", \"Node db has changed\"]", + "types": "[\"emergency\", \"critical\", \"error\", \"alert\"]", + "name": "" + }, + "color": "#30E193", + "notes": "" + }, + { + "id": "1718016073501", + "component": "httprequest", + "tab": "1612772287426", + "name": "http://192.168.252.2:8004/slack", + "x": 495, + "y": 1753, + "connections": { + "0": [ + { + "index": "0", + "id": "1718016086212" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "url": "http://192.168.252.2:8004/slack", + "method": "POST", + "stringify": "json" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1718016086212", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 832, + "y": 1664, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "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": 87, + "y": 1591, + "connections": { + "0": [ + { + "index": "0", + "id": "1718016052341" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "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\": \"\" } } } ] }", + "datatype": "object" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1729855334955", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "platform-rpc-call", + "x": 599.9333343505859, + "y": 541.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "platform-rpc-call", + "color": "gray" + }, + "options": { + "wirename": "platform-rpc-call" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1729855371093", + "component": "debug", + "tab": "1612772287426", + "name": "rpc cloud", + "x": 601.9333343505859, + "y": 440.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1731068658334", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 75.75, + "y": 184, + "connections": { + "0": [ + { + "index": "0", + "id": "1612776786008" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731068754606", + "component": "cloudmqttconnect", + "tab": "1612772287426", + "name": "MQTT to senica-prod01", + "x": 284.75, + "y": 452, + "connections": { + "1": [ + { + "index": "0", + "id": "1729855371093" + }, + { + "index": "0", + "id": "1729855334955" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Connected", + "color": "green" + }, + "options": { + "username": "", + "clientid": "", + "port": "2764", + "host": "192.168.252.2", + "topic": "" + }, + "color": "#888600", + "notes": "" + }, + { + "id": "1731069001548", + "component": "db_init", + "tab": "1612772287426", + "name": "DB Initialization", + "x": 1003.75, + "y": 240.25, + "connections": { + "0": [ + { + "index": "0", + "id": "1731069033416" + } + ], + "1": [ + { + "index": "0", + "id": "1747561603739" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#888600", + "notes": "" + }, + { + "id": "1731069033416", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "db-init", + "x": 1244.75, + "y": 233.25, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069059135", + "component": "showdb", + "tab": "1612772287426", + "name": "Show db data", + "x": 1186.75, + "y": 821.25, + "connections": { + "0": [ + { + "index": "0", + "id": "1731069079243" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#888600", + "notes": "" + }, + { + "id": "1731069079243", + "component": "debug", + "tab": "1612772287426", + "name": "dbData", + "x": 1390.75, + "y": 870.25, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1731069116691", + "component": "trigger", + "tab": "1612772287426", + "name": "settings", + "x": 934.75, + "y": 669.75, + "connections": { + "0": [ + { + "index": "0", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069131637", + "component": "trigger", + "tab": "1612772287426", + "name": "relaysData", + "x": 876.75, + "y": 733.75, + "connections": { + "0": [ + { + "index": "1", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069137374", + "component": "trigger", + "tab": "1612772287426", + "name": "nodesData", + "x": 852.75, + "y": 794.75, + "connections": { + "0": [ + { + "index": "2", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069179846", + "component": "trigger", + "tab": "1612772287426", + "name": "pinsData", + "x": 850.75, + "y": 861.75, + "connections": { + "0": [ + { + "index": "3", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069192937", + "component": "trigger", + "tab": "1612772287426", + "name": "sample data", + "x": 857.75, + "y": 928.75, + "connections": { + "0": [ + { + "index": "4", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069264443", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 63.75, + "y": 1279, + "connections": { + "0": [ + { + "index": "0", + "id": "1634488120710" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069334626", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "db-init", + "x": 172.88333129882812, + "y": 129, + "connections": { + "0": [ + { + "index": "0", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069548145", + "component": "virtualwirein", + "tab": "1611921777196", + "name": "db-init", + "x": 46.75, + "y": 192, + "connections": { + "0": [ + { + "index": "0", + "id": "1699965957410" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069567152", + "component": "virtualwirein", + "tab": "1611921777196", + "name": "db-init", + "x": 44.75, + "y": 465, + "connections": { + "0": [ + { + "index": "0", + "id": "1700411878636" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731070156936", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "db-init", + "x": 126.88333129882812, + "y": 1377, + "connections": { + "0": [ + { + "index": "2", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731234189516", + "component": "trigger", + "tab": "1612772287426", + "name": "monitor.txt", + "x": 882.75, + "y": 991.75, + "connections": { + "0": [ + { + "index": "5", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731234189551", + "component": "trigger", + "tab": "1612772287426", + "name": "err.txt", + "x": 904.75, + "y": 1053.75, + "connections": { + "0": [ + { + "index": "6", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1732700042559", + "component": "nodesdb_change_check", + "tab": "1612772287426", + "name": "Nodes DB change check", + "x": 266.8833312988281, + "y": 1980.2333984375, + "connections": { + "0": [ + { + "index": "0", + "id": "1732700071298" + }, + { + "index": "0", + "id": "1732700642917" + } + ], + "1": [ + { + "index": "0", + "id": "1759958914348" + }, + { + "index": "0", + "id": "1759959003114" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#888600", + "notes": "" + }, + { + "id": "1732700057052", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 76.75, + "y": 1988, + "connections": { + "0": [ + { + "index": "0", + "id": "1732700042559" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1732700071298", + "component": "debug", + "tab": "1612772287426", + "name": "nodesChange", + "x": 571.8833312988281, + "y": 2018.2333984375, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1732700642917", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "tb-push", + "x": 567.8833312988281, + "y": 1933, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1732889185927", + "component": "debug", + "tab": "1611921777196", + "name": "tempToDido", + "x": 594.8833312988281, + "y": 753, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1733574412965", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 72.75, + "y": 474, + "connections": { + "0": [ + { + "index": "1", + "id": "1731068754606" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1747561603739", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "send-to-services", + "x": 1243.8833312988281, + "y": 334.5, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1747562867845", + "component": "comment", + "tab": "1612772287426", + "name": "FLOW STARTING POINT", + "x": 1003.5666656494141, + "y": 178, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#704cff", + "notes": "" + }, + { + "id": "1749211698385", + "component": "trigger", + "tab": "1612772287426", + "name": "deviceStatus", + "x": 911.75, + "y": 1116.75, + "connections": { + "0": [ + { + "index": "7", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1757006030239", + "component": "httprequest", + "tab": "1615551125555", + "name": "192.168.252.2:8015/daily_report", + "x": 756.5666656494141, + "y": 715.4499969482422, + "connections": { + "0": [ + { + "index": "0", + "id": "1757006045804" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "stringify": "json", + "method": "POST", + "url": "http://192.168.252.2:8015/daily_report" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1757006045804", + "component": "debug", + "tab": "1615551125555", + "name": "ddd", + "x": 1091.566665649414, + "y": 711.4499969482422, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1757006060377", + "component": "debug", + "tab": "1615551125555", + "name": "reportDebug", + "x": 749.5666656494141, + "y": 799.4499969482422, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1759958914348", + "component": "httprequest", + "tab": "1612772287426", + "name": "http://192.168.252.2:8015/node_numbers", + "x": 571, + "y": 2111, + "connections": { + "0": [ + { + "index": "0", + "id": "1759958927094" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "stringify": "json", + "method": "POST", + "url": "http://192.168.252.2:8015/node_numbers" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1759958927094", + "component": "debug", + "tab": "1612772287426", + "name": "nodesChangeCloud", + "x": 951.8833312988281, + "y": 2109.2333984375, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1759959003114", + "component": "debug", + "tab": "1612772287426", + "name": "nodeChangeCloud1", + "x": 574, + "y": 2218, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1760020290879", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 84.75, + "y": 1787, + "connections": { + "0": [ + { + "index": "1", + "id": "1718016052341" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + } + ], + "version": 615 +} diff --git a/RVO4/flow/dido_controller.js b/RVO4/flow/dido_controller.js new file mode 100755 index 0000000..d16fb19 --- /dev/null +++ b/RVO4/flow/dido_controller.js @@ -0,0 +1,1486 @@ +exports.id = 'dido_controller'; +exports.title = 'DIDO_Controller'; +exports.version = '2.0.0'; +exports.group = 'Worksys'; +exports.color = '#2134B0'; +exports.input = 3; +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 + +state_of_main_switch - reportovat stav hlaveho istica : 0-> off 1-> on +rotary_switch_state - sem by sa mal reportovat stav vstupov manual a auto pola nasledovnej logiky: Manual = 1 a Auto = 0 -> Manu +Manual = 0 a Auto = 0 -> Off, Manual = 0 a Auto = 1 -> Automatic + +door_condition - pin 6, dverový kontakt -> 1 -> vyreportuje Closed, 0 -> vyreportuje Ope +twilight_sensor - hodnotu, ktoru vracia ten analogovy vstup (17) treba poslat sem ako float number. Zrejme tu potom pridame nejaky koeficient prevodu na luxy + +Na kazdu liniu +state_of_breaker - podla indexu istica sa reportuje jeho stav, teda istic na liniu 1: 0-> off, 1-> on +state_of_contactor - podla indexu stkaca sa reportuje jeho stav, teda stykac 1 na liniu 1: 0-> off, 1-> on +*/ + +const { errLogger, logger, monitor } = require('./helper/logger'); +const SerialPort = require('serialport'); +const WebSocket = require('ws'); +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 errorHandler = require('./helper/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 hasMainSwitch; + +let alarmStatus = "OFF"; + +const SEND_TO = { + debug: 0, + tb: 1, + cmd_manager: 2 +} + + +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 = {}; + let rsPortReceivedData = []; + + //to be able to get proper twilight values + let twilight_sensor_interval = 5;//minutes + let twilight_sensor = []; + const twilight_sensor_array = []; + let twilightError = false; + + monitor.info("DIDO_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-we make it global to see it from outside + FLOW.deviceStatus = { //key is device name: temperature,.... + "state_of_main_switch": "Off", //Hlavny istic (alebo druhy dverovy kontakt) + "rotary_switch_state": "Off", //Prevadzkovy + "door_condition": "closed", //Dverový kontakt + "em": "OK", //elektromer rvo + "temperature": "OK", //templomer + "battery": "OK", //Bateria + "power_supply": "OK", //Zdroj + "master_node": "OK", //MN - GLOBALS.settings.masterNodeIsResponding + "no_voltage": "OK", //GLOBALS.settings.no_voltage - vypadok napatia na faze + "state_of_breaker": {}, //"Off",//Istic + "state_of_contactor": {}, //"Off",//Stykac + "twilight_sensor": "OK" //lux sensor + }; + let deviceStatus = FLOW.deviceStatus; + + + function main() { + + GLOBALS = FLOW.GLOBALS; + SETTINGS = FLOW.GLOBALS.settings; + rvoTbName = SETTINGS.rvoTbName; + pinsData = GLOBALS.pinsData; + relaysData = GLOBALS.relaysData; + + tbHandler = new DataToTbHandler(SEND_TO.tb); + tbHandler.setSender(exports.title); + + controller_type = SETTINGS.controller_type; //"lm" or "unipi" + hasMainSwitch = SETTINGS.has_main_switch; + + if (controller_type == "") controller_type = "lm"; + + 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, "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; + } + } + + //report RVO version relaysData[0].tbname; + let values = {}; + values["edge_fw_version"] = SETTINGS.edge_fw_version; + values["maintenance_mode"] = SETTINGS.maintenance_mode; + + sendTelemetry(values, rvoTbName); + + 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); + } + + + function handleRsPort() { + + if (rsPort) { + rsPort.removeAllListeners(); + rsPort = null; + } + + //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('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) { + if (!err) { + monitor.info(exports.title + "--->Digital in_out has been set (runSyncExec was sucessfull)"); + + turnAlarm("off"); + 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('error', err => { + let message = "Dido: rsPort error: " + err.message; + logger.debug(message); + monitor.info(message); + errorHandler.sendMessageToService(message); + }) + + rsPort.on("close", () => { + let message = "Dido: rsPort closed - reconnecting ..."; + logger.debug(message); + monitor.info(message); + setTimeout(handleRsPort, 1000); + }) + + rsPort.open(); + } + + + function handleWebSocket() { + + if (ws) { + ws.removeAllListeners(); + ws = null; + } + + //to keep websocket opened, we send request every 150 seconds + let startRequests = null; + + console.log("handleWebSocket function called"); + ws = new WebSocket('ws:/0.0.0.0:1234/ws'); + + ws.onopen = function open() { + + instance.send(0, exports.title + " running"); + turnAlarm("off"); + + initialSetting(); + + setTimeout(function() { ws.send(JSON.stringify({ cmd: "all" })) }, 5000); + // we request dev info about neuron device from evok to keep websocket connection alive + // for some reason this request returns no data, but connection keeps alive + startRequests = setInterval(() => { + ws.send(JSON.stringify({ "cmd": "filter", "dev": ["neuron"] })); + }, 150000) + }; + + + // 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 = async 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; + + 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 => { + logger.debug('Dido: websocket error', err); + }) + + ws.onclose = function() { + logger.debug('Dido: websocket onclose, reconnecting...') + clearInterval(startRequests); + setTimeout(handleWebSocket, 1000); + } + } + + 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 turnAlarm(onOrOff) { + let value = 0; + if (onOrOff == "on") value = 1; + + if (value == 1 && SETTINGS.maintenance_mode) return; + + alarmStatus = "OFF"; + if (value == 1) alarmStatus = "ON"; + + if (rsPort) { + let arr = [0x55]; + arr.push(13); + arr.push(0); + arr.push(value); + + rsPort.write(Buffer.from(arr), function(err) { + logger.debug(`sirena - ${onOrOff}`); + }); + } + else if (ws) { + let cmd = { "cmd": "set", "dev": "relay", "circuit": "1_01", "value": value }; + ws.send(JSON.stringify(cmd)); + logger.debug(`sirena - ${onOrOff}`); + } + } + + + 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") { + bits.push(0); + } + else bits.push(1); + + if (deviceStatus["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); + } + + + // turn line on or off + function turnLine(onOrOff, line, pin, force, info) { + //onOrOff => "on" or "off" + let value = 0; + if (onOrOff == "on") value = 1; + + if (force == undefined) force = false; + + if (line == 0) { + if (value == 1 && alarmStatus == "ON") turnAlarm("off"); + SETTINGS.maintenance_mode = value ? true : false; + + 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); + return; + } + + if (pin === undefined) pin = getPin(line); + + if (pin === undefined) { + errLogger.error("pin is undefined!", line); + return; + } + + if (!force) { + if (relaysData[line].contactor == value) { + instance.send(SEND_TO.debug, `line is already ${onOrOff} ` + line); + logger.debug(`Dido: turnLine: line is already ${onOrOff} `, line); + return; + } + } + + // if(!rsPort.isOpen && !ws) + if (!rsPort && !ws) { + errLogger.error("Dido - port or websocket is not opened"); + return; + } + + if (rsPort) { + let arr = [0x55]; + arr.push(pin); + arr.push(0); + arr.push(value); + + rsPort.write(Buffer.from(arr), function(err) { + if (err === undefined) { + monitor.info(`Dido: turnLine ${onOrOff} zapisal do rsPort-u`, line, pin, arr, info); + switchLogic(arr); + } + else { + monitor.info(`Dido: turnLine ${onOrOff} WRITE error`, err); + } + }); + + } + else if (ws) { + //pin = "relay1_03" or "input1_01" ... we must make just "1_01" with slice method + monitor.info(`Dido: turnLine ${onOrOff} - (line, pin, force)`, line, pin, force, info); + let cmd = { "cmd": "set", "dev": "relay", "circuit": pin.slice(5), "value": value }; + ws.send(JSON.stringify(cmd)); + } + + //if rvo is 24/7, it has just one switching profile point at 13:00. we do not want to send notification as it repeats every day. + //const d = new Date(); + //if(d.getHours() != 13) sendNotification("Dido_controller: ", SETTINGS.rvoTbName, "switching_profile_point_applied_to_line", { line: line, value: onOrOff }, "", SEND_TO.tb, instance); + } + + + // 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; + + // 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) { + const status = flowdata.data.status; + if (status == "NOK-twilight_sensor") { + deviceStatus["twilight_sensor"] = "NOK"; + } + else if (status == "NOK-em340" || status == "NOK-em111") { + deviceStatus["em"] = "NOK"; + } + else if (status == "NOK-thermometer") { + deviceStatus["temperature"] = "NOK"; + } + } + else if ("values" in flowdata.data) { + 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" + } + else if (values.hasOwnProperty("temperature")) { + deviceStatus["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"; + } + + sendTelemetry(values, rvoTbName); + } + + sendRvoStatus(); + }) + + + + + // we expect array as flowdata.data + instance.on("1", flowdata => { + + //console.log(flowdata.data); + + if (!flowdata.data instanceof Object) return; + + let obj = flowdata.data; + let line = obj.line; + 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"); + }) + + + function calculateStateCode() { + + let bits = []; + + //Hlavny istic - state_of_main_switch => v rvo senica je to druhy door pre silovu cast (EM) + if (deviceStatus["state_of_main_switch"] === "closed" || deviceStatus["state_of_main_switch"] === "Off") { + bits.push(0); + } + else { + bits.push(1); + } + + //Prevadzkovy mod - Manual, Off, Automatic, maintenance_mode = true/false // DAVA 2 BITY + if (!SETTINGS.maintenance_mode) { + if (deviceStatus["rotary_switch_state"] === "Manual") { + bits.push(0); + bits.push(1); + } + + if (deviceStatus["rotary_switch_state"] === "Automatic") { + bits.push(0); + bits.push(0); + } + + if (deviceStatus["rotary_switch_state"] === "Off") { + bits.push(1); + bits.push(0); + } + } + else { + bits.push(1); + bits.push(1); + } + + //Dverovy kontakt + if (deviceStatus["door_condition"] === "closed") { + bits.push(0); + } + else { + bits.push(1); + } + + //EM + if (deviceStatus["em"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //Teplomer + if (deviceStatus["temperature"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //Batéria + if (deviceStatus["battery"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //Zdroj + if (deviceStatus["power_supply"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //MN + if (deviceStatus["master_node"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //výpadok napätia na fáze + if (deviceStatus["no_voltage"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + if (deviceStatus["twilight_sensor"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + // doplnime do 16 bitov (2 byty) + for (let i = bits.length; i < 16; i++) { + bits.push(0); + } + + // console.log("calculateStateCode - deviceStatus", deviceStatus); + // 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; + } + + + async function sendRvoStatus() { + + if (SETTINGS === undefined) return; + SETTINGS.masterNodeIsResponding ? deviceStatus["master_node"] = "OK" : deviceStatus["master_node"] = "NOK"; + + 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 pinsForRvoStatus(controllerType, hasMainSwitch) { + + let pins = []; + + if (controllerType === "lm") { + pins = [1, 4, 6]; + if (hasMainSwitch === 1) { + pins = [4, 6]; + } + } else if (controllerType === "unipi") { + pins = ["input1_01", "input1_04", "input1_05"]; + if (hasMainSwitch === 1) { + pins = ["input1_01", "input1_04"]; + } + } + + return pins; + } + + + function checkRvoStatus() { + + // 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 + //set RVO state + let status = "OK"; + + for (const [key, value] of Object.entries(deviceStatus)) { + if (["em", "twilight_sensor", "temperature", "master_node"].includes(key) && value === "NOK") status = "NOK"; + } + + if (status === "OK") { + + let pinIndexes = pinsForRvoStatus(controller_type, hasMainSwitch); + + for (const pinIndex of pinIndexes) { + if (previousValues[pinIndex] === 0) { + if ((pinIndex === 6 || pinIndex === 'input1_01' || pinIndex === 'input1_05') && SETTINGS.maintenance_mode) continue; + status = "NOK"; + break; + } + } + } + + // battery status. If value is 1 - battery is NOK + if (previousValues[5] === 1) status = "NOK"; + if (SETTINGS.no_voltage.size > 0) status = "NOK"; + + // console.log("rvo status",status) + return status; + } + + + // we pass array to function in case of rsPort ==> switchLogic([55,3,0,1]) ==> [[55,3,0,1]] + // we pass two values in case of websocket ==> switchLogic("relay1_03",1) ==> ["relay1_03",1] + const switchLogic = (...args) => { + + let values = {}; + let pinIndex, newPinValue, twilight; + + //data from rsPort + if (args.length == 1) { + pinIndex = args[0][1] + 1; + if (pinIndex === 17) pinIndex--; + newPinValue = args[0][3]; + twilight = args[0][2]; + } + //data from websocket + else { + pinIndex = args[0]; + newPinValue = args[1]; + } + + 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; + + //default value + let value = "On"; + if (newPinValue === 0) value = "Off"; + + //Hlavny istic + if (type === "state_of_main_switch" && hasMainSwitch) { + if (newPinValue === 0 && newPinValue !== previousValues[pinIndex]) { + sendNotification("switchLogic", rvoTbName, "main_switch_has_been_turned_off", {}, "", SEND_TO.tb, instance, "state_of_main_switch"); + 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"); + deviceStatus["state_of_main_switch"] = "On"; + } + } + + //Prevadzkovy mod + 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"; + + deviceStatus["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, "power_supply_has_disconnected_input", {}, "", SEND_TO.tb, instance, "power_supply"); + + deviceStatus["power_supply"] = "NOK"; + } + else if (newPinValue === 1 && newPinValue !== previousValues[pinIndex]) { + sendNotification("switchLogic", rvoTbName, "power_supply_works_correctly", {}, "", SEND_TO.tb, instance, "power_supply"); + + deviceStatus["power_supply"] = "OK"; + } + } + + //Bateria - 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"); + + deviceStatus["battery"] = "NOK"; + } + else if (newPinValue === 0 && newPinValue !== previousValues[pinIndex]) { + sendNotification("switchLogic", rvoTbName, "battery_level_is_ok", {}, "", SEND_TO.tb, instance, "battery_level"); + + deviceStatus["battery"] = "OK"; + } + } + + //Dverovy kontakt - pin 6 + //! Ak je rvo s dvoma dverovymi kontaktami, ked pride z evoku signal z input1_05, co bol predytm "state_of_main switch" handlujeme ho teraz ako 'door_condition' + else if (type == "door_condition" || type === "state_of_main_switch") { + newPinValue === 0 ? value = "open" : value = "closed"; + + let door = "door_main"; + if (type === "state_of_main_switch") door = "door_em"; + + if (value === "open") { + if (SETTINGS.maintenance_mode) { + sendNotification("switchLogic", rvoTbName, door + "_open", {}, "", SEND_TO.tb, instance, door); + } else { + sendNotification("switchLogic", rvoTbName, door + "_open_without_permission", {}, "", SEND_TO.tb, instance, door); + + // 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 (value === "closed") { + if (alarmStatus == "ON") turnAlarm("off"); + sendNotification("switchLogic", rvoTbName, door + "_close", {}, "", SEND_TO.tb, instance, door); + } + + deviceStatus[type] = value; + } + + //lux sensor + else if (type == "twilight_sensor") { + //! TODO - to show nok status, if lux value is not changing more then 10 times. + //Daylight is far more than 1000. So most of the day, when it is sunshine comes just value 1000. But lux sensor is not NOK. + //This is not the case in LM. If value from LM is the same 10x, there is 99% possibility, that sensor is NOK. + value = newPinValue; + + if (controller_type === 'lm') { + value = parseFloat(newPinValue + (256 * twilight)); + + 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 && !twilightError) { + twilightError = true; + let value = twilight_sensor_array.shift(); + + newPinValue = 0; + } + else if (set.size !== 1 && twilightError) { + //sendNotification("switchLogic", rvoTbName, 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) { + 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); + } + } + + 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); + } + + deviceStatus["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 (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 }); + + //mame iba 3 istice. vyreportujeme a ohandlujeme liniu na tom istom istici ako paralelna linia (napr linia 1, paralelna s nou je linia 4, key je string "4") + // ak je 7 linii, na 1 istici je linia 1,4,7 + + if (line == 1) { + + const lineOnSameBraker = [4, 7]; + + for (var i = 0; i < lineOnSameBraker.length; i++) { + if (!relaysData.hasOwnProperty(lineOnSameBraker[i])) continue; + + 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; + reportLineStatus(lineOnSameBraker[i]); + + values[type] = value; + const tbname = relaysData[lineOnSameBraker[i]].tbname; + sendTelemetry(values, tbname); + + delete values[type]; + } + + } + else { + const lineOnSameBraker = line + 3 + ""; + + if (relaysData.hasOwnProperty(lineOnSameBraker)) { + 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; + reportLineStatus(line + 3); + + values[type] = value; + const tbname = relaysData[lineOnSameBraker].tbname; + sendTelemetry(values, tbname); + + delete values[type]; + } + } + + } + + if (value == "Off") values["status"] = "NOK"; + deviceStatus["state_of_breaker"][line] = value; + + reportLineStatus(line); + } + else return; + + values[type] = value; + + if (type == "rotary_switch_state") { + if (SETTINGS.maintenance_mode) value = "maintenance"; + value = value.toLowerCase(); + values["power_mode"] = value; + } + + if (newPinValue != previousValues[pinIndex]) previousValues[pinIndex] = newPinValue; + if (Object.keys(values).length > 0 && tbname) sendTelemetry(values, tbname); + } + + + function sendTelemetry(values, tbname, date = Date.now()) { + let dataToTb = { + [tbname]: [ + { + "ts": date, + "values": values + } + ] + }; + + tbHandler.sendToTb(dataToTb, instance); + } + + + function isObject(item) { + return (typeof item === "object" && !Array.isArray(item) && item !== null); + } + +} //end of 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 +// *|input1_01|state_of_main_switch|0|........... +// *|input1_02|rotary_switch_state|0|........... +// *|input1_03|rotary_switch_state|0|........... +// *|intut1_04|power_supply|0|........... +// *|input1_05|door_condition|0|........... +// *|input1_06|state_of_breaker|1|........... +// *|input1_07|state_of_breaker|2|........... +// *|input1_08|state_of_breaker|3|........... +// *|relay1_02|state_of_contactor|1|........... +// *|relay1_03|state_of_contactor|2|........... +// *|relay1_04|state_of_contactor|3|........... +// *|287D8776E0013CE9|temperature|0|........... + + +//! pins_data --> from UNIPI +// { +// 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 } +// } + +//! relays_data +// { +// '0': { +// line: 0, +// tbname: 'KjbN4q7JPZmexgdnz2yKQ98YAWwO0Q3BMX6ERLoV', +// contactor: 1, +// profile: '' +// }, +// '1': { +// line: 1, +// tbname: 'RMgnK93rkoAazbqdQ4yBG95Z1YXGx6pmwBeVEP2O', +// contactor: 0, +// profile: '{"intervals":[{"value":0,"end_time":"20:00","start_time":"13:00"},{"value":1,"end_time":"10:00","start_time":"20:00"},{"value":0,"end_time":"10:20","start_time":"10:00"},{"value":1,"end_time":"10:40","start_time":"10:20"},{"value":0,"end_time":"11:00","start_time":"10:40"},{"value":1,"end_time":"11:30","start_time":"11:00"},{"value":0,"end_time":"11:50","start_time":"11:30"},{"value":1,"end_time":"13:00","start_time":"11:50"}],"astro_clock":false,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' +// }, +// '2': { +// line: 2, +// tbname: 'dlE1VQjYrNx9gZRmb38gG08oLBO4qaAk2M6JPnG7', +// contactor: 0, +// profile: '{"intervals":[{"value":0,"end_time":"20:00","start_time":"13:00"},{"value":1,"end_time":"10:00","start_time":"20:00"},{"value":0,"end_time":"10:20","start_time":"10:00"},{"value":1,"end_time":"10:40","start_time":"10:20"},{"value":0,"end_time":"11:00","start_time":"10:40"},{"value":1,"end_time":"11:30","start_time":"11:00"},{"value":0,"end_time":"11:50","start_time":"11:30"},{"value":1,"end_time":"13:00","start_time":"11:50"}],"astro_clock":false,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' +// }, +// '3': { +// line: 3, +// tbname: 'vnmG4kJxaXWNBgMQq0D7Aj5e9oZzOAlr6LdR3w2V', +// contactor: 0, +// profile: '{"intervals":[{"value":0,"end_time":"20:30","start_time":"13:00"},{"value":1,"end_time":"00:10","start_time":"20:30"},{"value":0,"end_time":"13:00","start_time":"05:40"},{"value":1,"end_time":"05:40","start_time":"00:10"}],"astro_clock":true,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' +// } +// } + + + + + +// { +// "jbN4q7JPZmexgdnz2yKbWGDYAWwO0Q3BMX6ERLoV": [ +// { +// "ts": 1700409326353, +// "values": { +// "_event": { +// "type": "notice", +// "status": "new", +// "source": { +// "func": "rsPort.open()", +// "component": "1700343402190", +// "component_name": "DIDO_Controller", +// "edge": "jbN4q7JPZmexgdnz2yKbWGDYAWwO0Q3BMX6ERLoV" +// }, +// "message": "al_shariff_10.0.0.38: FLOW has been started ", +// "message_data": "" +// } +// } +// } +// ] +// } diff --git a/RVO4/flow/helper/DataToTbHandler.js b/RVO4/flow/helper/DataToTbHandler.js new file mode 100755 index 0000000..716ef7b --- /dev/null +++ b/RVO4/flow/helper/DataToTbHandler.js @@ -0,0 +1,187 @@ +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; + this.itIsNodeReadout = false; + this.sender = ""; + + // if attribute change difference is less than limit value, we do not send to tb. + this.attributeChangeLimit = { + temperature: 0.5, + Phase_1_voltage: 2, + Phase_2_voltage: 2, + Phase_3_voltage: 2, + Phase_1_current: 0.1, + Phase_2_current: 0.1, + Phase_3_current: 0.1, + Phase_1_power: 2, + Phase_2_power: 2, + Phase_3_power: 2, + total_power: 2, + total_energy: 1, + Phase_1_pow_factor: 0.1, + Phase_2_pow_factor: 0.1, + Phase_3_pow_factor: 0.1, + power_factor: 0.1, + lifetime: 2, + voltage: 2, + power: 2, + frequency: 3, + energy: 0.1, + current: 2, + inclination_x: 10, + inclination_y: 10, + inclination_z: 10 + }; + + } + + dump() { + console.log("----------------------------"); + console.log("previousValues", this.previousValues); + console.log("----------------------------"); + } + + setSender(sender) { + this.sender = sender; + } + + isEmptyObject(obj) { + for (var _ in obj) { + return false; + } + return true; + } + + + sendToTb(data, instance) { + + //not to modify data object, we do deep copy: + let dataCopy = JSON.parse(JSON.stringify(data)); + + let keys = Object.keys(dataCopy); + + if (keys.length == 0) { + if (this.debug) console.log("sendToTb received empty object", dataCopy); + return; + } + + let tbname = keys[0]; + let ts; + + let arrayOfValues = dataCopy[tbname]; + let arrayOfValuesToSend = []; + + for (let i = 0; i < arrayOfValues.length; i++) { + + ts = arrayOfValues[i].ts; + let values = this.prepareValuesForTb(tbname, ts, arrayOfValues[i].values); + + if (!this.isEmptyObject(values)) { + arrayOfValuesToSend.push({ ts: ts, values: values }); + } + + } + + if (arrayOfValuesToSend.length == 0) { + //if(this.debug) console.log("data not sent - empty array"); + return; + } + + this.messageCounter++; + + let dataToTbModified = { + [tbname]: arrayOfValuesToSend + } + + //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); + instance.send(this.index, dataToTbModified); + } + + + getDiffTimestamp(key) { + //TODO set different value for given key!!! + //if(key == "status") this.timeToHoldTbValue = 2*60*60;//2h + return this.timeToHoldTbValue * 1000; + } + + + prepareValuesForTb(tbname, timestamp, values) { + + let keys = Object.keys(values); + + if (keys.includes("lifetime")) this.itIsNodeReadout = true; + + if (!this.previousValues.hasOwnProperty(tbname)) { + this.previousValues[tbname] = {}; + } + + //if(this.debug) console.log("prepareValuesForTb", tbname, timestamp, values); + + for (let i = 0; i < keys.length; i++) { + + let key = keys[i]; + let value = values[key]; + + if (!this.previousValues[tbname].hasOwnProperty(key)) { + this.previousValues[tbname][key] = { ts: timestamp, value: value }; + continue; + } + + // attributeData ==> {voltage: {ts:333333, value:5}} + let attributeData = this.previousValues[tbname][key]; + let attributeToChange = false; + if (key in this.attributeChangeLimit) attributeToChange = true; + let limit = this.attributeChangeLimit[key]; + let timestampDiffToRemoveKey; + + //this will ensure "node statecode" will be sent just once an hour + if (this.itIsNodeReadout && key === "statecode") { + attributeData.value = value; + this.itIsNodeReadout = false; + timestampDiffToRemoveKey = 1 * 60 * 60 * 1000; // 1 hour + } + + if (key === "twilight_sensor" && value > 100) { + attributeData.value = value; + } + + //if edge, master or node version do not change, send just once a day: + if (["edge_fw_version", "master_node_version", "fw_version"].includes(key)) { + timestampDiffToRemoveKey = 24 * 60 * 60 * 1000; + } + + if (attributeData.value === value || attributeToChange && Math.abs(attributeData.value - value) < limit) { + + let diff = timestamp - attributeData.ts; + if (!timestampDiffToRemoveKey) timestampDiffToRemoveKey = this.getDiffTimestamp(key); + + if (diff > timestampDiffToRemoveKey) { + attributeData.ts = Date.now(); + //if(this.debug) console.log(this.sender + ": update ts for key", key, "diff is", diff, "messageCounter", this.messageCounter); + } + else { + delete values[key]; + //if(this.debug) console.log(this.sender + ": delete key", key, "diff is", diff, "messageCounter", this.messageCounter, timestampDiffToRemoveKey); + } + } + else { + attributeData.value = value; + attributeData.ts = timestamp; + } + + } + + return values; + } +} + +module.exports = DataToTbHandler; + diff --git a/RVO4/flow/helper/ErrorToServiceHandler.js b/RVO4/flow/helper/ErrorToServiceHandler.js new file mode 100755 index 0000000..2b27c32 --- /dev/null +++ b/RVO4/flow/helper/ErrorToServiceHandler.js @@ -0,0 +1,91 @@ +const { MD5 } = require('./md5.js'); +const { networkInterfaces } = require('os'); + +class ErrorToServiceHandler { + constructor() { + this.previousValues = {}; + + this.project_id = undefined; + + const nets = networkInterfaces(); + this.ipAddresses = {}; + + for (const name of Object.keys(nets)) { + for (const net of nets[name]) { + // Skip over non-IPv4 and internal (i.e. 127.0.0.1) addresses + if (net.family === 'IPv4' && !net.internal) { + if (!this.ipAddresses[name]) { + this.ipAddresses[name] = []; + } + this.ipAddresses[name].push(net.address); + } + } + } + } + + setProjectId(project_id) { + this.project_id = project_id; + } + + processMessage(message, seconds) { + if (Array.isArray(message)) message = message.join(', '); + + let key = MD5(message); + let ts = Date.now(); + + //keep in memory - default value is 1h + if (seconds === undefined) seconds = 60 * 60; + + if (!this.previousValues.hasOwnProperty(key)) { + this.previousValues[key] = { ts: ts, duration: seconds }; + } + + let diff = (ts - this.previousValues[key].ts); + if (diff < this.previousValues[key].duration * 1000) return false; + + this.previousValues[key].ts = ts; + + return message; + } + + sendMessageToService(message, seconds, message_type) { + + // if error occures too early FLOW.GLOBALS.settings.project_id is still undefined + if (this.project_id === undefined) { + console.log("ErrorToServiceHandler.js: no project_id"); + return; + } + + let f = this.processMessage(message, seconds); + if (f === false) return; + + if (message_type === undefined) message_type = "error_message"; + + let toService = { + id: this.project_id, + ipAddresses: this.ipAddresses + }; + + //js_error || error_message + toService[message_type] = message; + + console.log("ErrorToServiceHandler------------------------>send to service", toService); + + RESTBuilder.make(function(builder) { + builder.method('POST'); + builder.post(toService); + builder.url('http://192.168.252.2:8004/sentmessage'); + + builder.callback(function(err, response, output) { + console.log("process.on error send", err, response, output, toService); + }); + }); + + } +} + +const errorHandler = new ErrorToServiceHandler(); + + +module.exports = errorHandler; +//module.exports = ErrorToServiceHandler; diff --git a/RVO4/flow/helper/db_helper.js b/RVO4/flow/helper/db_helper.js new file mode 100755 index 0000000..40e796c --- /dev/null +++ b/RVO4/flow/helper/db_helper.js @@ -0,0 +1,44 @@ +function promisifyBuilder(builder) +{ + return new Promise((resolve, reject) => { + + try{ + + builder.callback(function(err, response) { + + if(err != null) reject(err); + resolve(response); + }); + + } catch (error) { + reject(error); + } + }) +} + +function makeMapFromDbResult(response, ...keys) +{ + let s = "-"; + let data = {}; + + for(let i = 0; i < response.length; i++) + { + let record = response[i]; + + let k = []; + for(let j = 0; j < keys.length; j++) + { + k.push( record[keys[j]] ); + } + + let key = k.join(s); + data[ key ] = record; + } + + return data; +} + +module.exports = { + promisifyBuilder, + makeMapFromDbResult + } \ No newline at end of file diff --git a/RVO4/flow/helper/logger.js b/RVO4/flow/helper/logger.js new file mode 100755 index 0000000..2585639 --- /dev/null +++ b/RVO4/flow/helper/logger.js @@ -0,0 +1,30 @@ +//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/RVO4/flow/helper/md5.js b/RVO4/flow/helper/md5.js new file mode 100755 index 0000000..d3b0480 --- /dev/null +++ b/RVO4/flow/helper/md5.js @@ -0,0 +1,5 @@ +function MD5(d){var r = M(V(Y(X(d),8*d.length)));return r.toLowerCase()};function M(d){for(var _,m="0123456789ABCDEF",f="",r=0;r>>4&15)+m.charAt(15&_);return f}function X(d){for(var _=Array(d.length>>2),m=0;m<_.length;m++)_[m]=0;for(m=0;m<8*d.length;m+=8)_[m>>5]|=(255&d.charCodeAt(m/8))<>5]>>>m%32&255);return _}function Y(d,_){d[_>>5]|=128<<_%32,d[14+(_+64>>>9<<4)]=_;for(var m=1732584193,f=-271733879,r=-1732584194,i=271733878,n=0;n>16)+(_>>16)+(m>>16)<<16|65535&m}function bit_rol(d,_){return d<<_|d>>>32-_} + +module.exports = { + MD5 +} \ No newline at end of file diff --git a/RVO4/flow/helper/notification_reporter.js b/RVO4/flow/helper/notification_reporter.js new file mode 100755 index 0000000..839c12c --- /dev/null +++ b/RVO4/flow/helper/notification_reporter.js @@ -0,0 +1,121 @@ +//key is device, value = message {} +let sentValues = {}; +let notificationsData = null; +let rvoName; + +//sendNotification("CMD Manager: process cmd", SETTINGS.rvoTbName, "dimming_profile_was_successfully_received_by_node", { node: node }, "", SEND_TO.tb, instance); + +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 +}; + +function getKey(map, val) { + return Object.keys(map).findItem(key => map[key] === val); +} + +//https://stackoverflow.com/questions/41117799/string-interpolation-on-variable +var template = (tpl, args) => tpl.replace(/\${(\w+)}/g, (_, v) => args[v]); + + +function initNotification() { + notificationsData = FLOW.GLOBALS.notificationsData; + rvoName = FLOW.GLOBALS.settings.rvo_name; +} + + +function sendNotification(func, device, key, params, extra, tb_output, instance, saveKey) { + + let storeToSendValues = true; + if (saveKey == undefined) storeToSendValues = false; + + let weight = ""; + let message = {}; + + let notification = notificationsData[key]; + + if (notification) { + weight = notification.weight.toLowerCase(); + + Object.keys(notification).forEach(item => { + if (["en", "sk", "de", "cz", "it", "es"].includes(item)) { + message[item] = rvoName + ": " + template(notification[item], params); + } + }) + } + else { + //console.error("sendNotification: Notifications: undefined key", key, func, notificationsData); + console.error("sendNotification: Notifications: undefined key", key, func); + return false; + } + + //detect invalid err weight + if (getKey(ERRWEIGHT, weight) == undefined) { + console.error("sendNotification: Notifications: undefined weight", weight, key, func); + return false; + } + + if (sentValues.hasOwnProperty(saveKey)) { + if (JSON.stringify(sentValues[saveKey]) == JSON.stringify(message)) { + return false; + } + } + + if (sentValues[saveKey] == undefined) { + if (storeToSendValues) { + //do not send - flow is was started + sentValues[saveKey] = message; + return false; + } + } + + if (storeToSendValues) sentValues[saveKey] = message; + + let content = { + "type": weight, + "status": "new", + "source": { + "func": func, + "component": instance.id, + "component_name": instance.name, + "edge": device + }, + "message": message, + "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 + + return true; + +} + +module.exports = { + sendNotification, + ERRWEIGHT, + initNotification +} + diff --git a/RVO4/flow/helper/register.js b/RVO4/flow/helper/register.js new file mode 100755 index 0000000..fc1d008 --- /dev/null +++ b/RVO4/flow/helper/register.js @@ -0,0 +1,144 @@ +/* +0 - cislo registra / prikaz +1 - recepient - 0 = master, 1 = slave (slave je automaticky group a broadcast) +2 - r/rw - read/write +3- register name - nazov registra / prikazu (len pre info - zobrazenie v aplikacii) + +4,5,6,7, - jednotlive byte-y - nazov byte-u +4-7 - RES. a prazdny string "" sa nezobrazia!!! +*/ + +//124 zaznamov +const registers = [ + ["0","1","R","Status","","",""], + ["1","1","RW","Dimming","R-Channel ","G-Channel","B-Channel ","W - Channel"], + ["2","1","R","Device types","","",".",""], + ["3","1","RW","Group addresses 1-4","Groups Add. 4","Groups Add. 3","Groups Add. 2","Groups Add. 1"], + ["4","1","RW","Group addresses 5-8","Groups Add. 8","Groups Add. 7","Groups Add. 6","Groups Add. 5"], + ["5","1","RW","Serial number (MAC)","","","",""], + ["6","1","RW","Time of dusk","HH","MM","SS","EXTRA"], + ["7","1","RW","Time of dawn","HH","MM","SS","EXTRA"], + ["8","1","RW","Time Schedule settings","TBD","TBD","Movement sensor","Time Schedule"], + ["9","1","RW","TS1 Time point 1","HH","MM","SS","Ext. Device"], + ["10","1","RW","TS1 Time point 1 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["11","1","RW","TS1 Time point 2","HH","MM","SS","Ext. Device"], + ["12","1","RW","TS1 Time point 2 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["13","1","RW","TS1 Time point 3","HH","MM","SS","Ext. Device"], + ["14","1","RW","TS1 Time point 3 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["15","1","RW","TS1 Time point 4","HH","MM","SS","Ext. Device"], + ["16","1","RW","TS1 Time point 4 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["17","1","RW","TS1 Time point 5","HH","MM","SS","Ext. Device"], + ["18","1","RW","TS1 Time point 5 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["19","1","RW","TS1 Time point 6","HH","MM","SS","Ext. Device"], + ["20","1","RW","TS1 Time point 6 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["21","1","RW","TS1 Time point 7","HH","MM","SS","Ext. Device"], + ["22","1","RW","TS1 Time point 7 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["23","1","RW","TS1 Time point 8","HH","MM","SS","Ext. Device"], + ["24","1","RW","TS1 Time point 8 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["25","1","RW","TS1 Time point 9","HH","MM","SS","Ext. Device"], + ["26","1","RW","TS1 Time point 9 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["27","1","RW","TS1 Time point 10","HH","MM","SS","Ext. Device"], + ["28","1","RW","TS1 Time point 10 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["29","1","RW","TS1 Time point 11","HH","MM","SS","Ext. Device"], + ["30","1","RW","TS1 Time point 11 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["31","1","RW","TS1 Time point 12","HH","MM","SS","Ext. Device"], + ["32","1","RW","TS1 Time point 12 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["33","1","RW","TS1 Time point 13","HH","MM","SS","Ext. Device"], + ["34","1","RW","TS1 Time point 13 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["35","1","RW","TS1 Time point 14","HH","MM","SS","Ext. Device"], + ["36","1","RW","TS1 Time point 14 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["37","1","RW","TS1 Time point 15","HH","MM","SS","Ext. Device"], + ["38","1","RW","TS1 Time point 15 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["39","1","RW","TS1 Time point 16","HH","MM","SS","Ext. Device"], + ["40","1","RW","TS1 Time point 16 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["41","1","RW","TS2 Time point 1","HH","MM","SS","Ext. Device"], + ["42","1","RW","TS2 Time point 1 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["43","1","RW","TS2 Time point 2","HH","MM","SS","Ext. Device"], + ["44","1","RW","TS2 Time point 2 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["45","1","RW","TS2 Time point 3","HH","MM","SS","Ext. Device"], + ["46","1","RW","TS2 Time point 3 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["47","1","RW","TS2 Time point 4","HH","MM","SS","Ext. Device"], + ["48","1","RW","TS2 Time point 4 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["49","1","RW","TS2 Time point 5","HH","MM","SS","Ext. Device"], + ["50","1","RW","TS2 Time point 5 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["51","1","RW","TS2 Time point 6","HH","MM","SS","Ext. Device"], + ["52","1","RW","TS2 Time point 6 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["53","1","RW","TS2 Time point 7","HH","MM","SS","Ext. Device"], + ["54","1","RW","TS2 Time point 7 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["55","1","RW","TS2 Time point 8","HH","MM","SS","Ext. Device"], + ["56","1","RW","TS2 Time point 8 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["57","1","RW","TS2 Time point 9","HH","MM","SS","Ext. Device"], + ["58","1","RW","TS2 Time point 9 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["59","1","RW","TS2 Time point 10","HH","MM","SS","Ext. Device"], + ["60","1","RW","TS2 Time point 10 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["61","1","RW","TS2 Time point 11","HH","MM","SS","Ext. Device"], + ["62","1","RW","TS2 Time point 11 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["63","1","RW","TS2 Time point 12","HH","MM","SS","Ext. Device"], + ["64","1","RW","TS2 Time point 12 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["65","1","RW","TS2 Time point 13","HH","MM","SS","Ext. Device"], + ["66","1","RW","TS2 Time point 13 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["67","1","RW","TS2 Time point 14","HH","MM","SS","Ext. Device"], + ["68","1","RW","TS2 Time point 14 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["69","1","RW","TS2 Time point 15","HH","MM","SS","Ext. Device"], + ["70","1","RW","TS2 Time point 15 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["71","1","RW","TS2 Time point 16","HH","MM","SS","Ext. Device"], + ["72","1","RW","TS2 Time point 16 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["73","1","RW","Power meter status","TBD","","",""], + ["74","1","R","Input Voltage","","","",""], + ["75","1","R","Input Current","","","",""], + ["76","1","R","Input Power","","","",""], + ["77","1","R","Cos phi","","","",""], + ["78","1","R","Frequency","","","",""], + ["79","1","RW","Energy","","","",""], + ["80","1","RW","Lifetime","","","",""], + ["81","1","RW","Power on cycles (input)","","","",""], + ["82","1","RW","Power on cycles (relay)","","","",""], + ["83","1","R","Time since last power on","","","",""], + ["84","1","R","Accelerometer data","","","",""], + ["85","1","RW","GPS latitude","pos/neg","deg","min ","sec"], + ["86","1","RW","GPS longitude","pos/neg","deg","min ","sec"], + ["87","1","RW","Actual time","HH","MM","SS","RES."], + ["88","1","RW","Actual date","Day of week","Day","Month","Year"], + ["89","1","R","Production data 1","","","",""], + ["90","1","R","Production data 2","","","",""], + ["91","1","RW","Network ID","NID3","NID2","NID1","NID0"], + ["95","1","RW","Actual Lux level from cabinet","RES.","RES.","HB","LB"], + ["96","1","RW","Threshold lux level","Dusk HB","Dusk LB","Dawn HB","Dawn LB"], + ["97","1","RW","Adjust period","Dusk HB","Dusk LB","Dawn HB","Dawn LB"], + ["98","1","RW","Offset","RES.","RES.","Dusk","Dawn"], + ["99","1","RW","CCT min/max range","max-H","max-L","min-H","min-L"], + ["100","1","RW","DALI interface","Cmd ID","Add","Cmd","Resp"], + ["101","1","RW","Module FW ver","v1","v2","v3","v4"], + ["102","1","RW","Module MAC-H","unused","unused","M1","M2"], + ["103","1","RW","Module MAC-L","M3","M4","M5","M6"], + ["122","1","R","FW update status/control register","Byte3","Byte2","Byte1","Byte0"], + ["123","1","R","FW update - data index","Byte3","Byte2","Byte1","Byte0"], + ["124","1","R","FW update - data","Byte3","Byte2","Byte1","Byte0"], + ["0","0","R","Status","","","",""], + ["1","0","RW","Control register","RES.","RES.","RES.","init mode enable"], + ["2","0","R","Device types","","","",""], + ["3","0","R","Serial number (MAC)","","","",""], + ["4","0","R","Production data 1","","","",""], + ["5","0","R","Production data 2","","","",""], + ["6","0","RW","Network ID","NID3","NID2","NID1","NID0"], + ["7","0","RW","RS232 settings","param.","param.","Baudrate H","Baudrate L"], + ["8","0","R","Accelerometer data","","","",""], + ["9","0","RW","Module FW ver","v1","v2","v3","v4"], + ["10","0","RW","Module MAC-H","unused","unused","M1","M2"], + ["11","0","RW","Module MAC-L","M3","M4","M5","M6"], + ["32","0","RW","FW update status/control register","Byte3","Byte2","Byte1","Byte0"], + ["33","0","RW","FW update - data index","Byte3","Byte2","Byte1","Byte0"], + ["34","0","RW","FW update - data","Byte3","Byte2","Byte1","Byte0"], + ["125","0","RW","Debug Register","Byte3","Byte2","Byte1","Byte0"], + ["126","0","RW","Network Control Register","Byte3","Byte2","Byte1","Byte0"], + ["127","0","R","Network Status Register","Byte3","Byte2","Byte1","Byte0"], + ["128","0","RW","Node XX Serial Number Register","SER3","SER2","SER1","SER0"], + ["256","0","R","Node XX Network Status Register","","","",""] +]; + +let register = {}; + +module.exports = { + registers, + register +} \ No newline at end of file diff --git a/RVO4/flow/helper/serialport_helper.js b/RVO4/flow/helper/serialport_helper.js new file mode 100755 index 0000000..7f5920d --- /dev/null +++ b/RVO4/flow/helper/serialport_helper.js @@ -0,0 +1,99 @@ +const { exec } = require('child_process'); + +function openPort(port) { + return new Promise((resolve, reject) => { + + var callbackError = function(err) { + port.removeListener('error', callbackError); + port.removeListener('open', callbackError); + + reject(err.message); + }; + + var callbackOpen = function(data) { + port.removeListener('error', callbackError); + port.removeListener('open', callbackOpen); + + resolve("port open: ok"); + }; + + port.on('error', callbackError); + port.on('open', callbackOpen); + + port.open(); + + }) +} + +function runSyncExec(command) { + return new Promise((resolve, reject) => { + + exec(command, (error, stdout, stderr) => { + if (error == null) resolve(stdout); + reject(error); + }); + + }) +} + +async function writeData(port, data, readbytes, timeout) { + return new Promise((resolve, reject) => { + + // 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) { + + port.write(Buffer.from(data), function(err) { + if (err) { + reject(err.message); + } + }); + + 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 +} diff --git a/RVO4/flow/helper/suncalc.js b/RVO4/flow/helper/suncalc.js new file mode 100755 index 0000000..c9ca56d --- /dev/null +++ b/RVO4/flow/helper/suncalc.js @@ -0,0 +1,317 @@ +/* + (c) 2011-2015, Vladimir Agafonkin + SunCalc is a JavaScript library for calculating sun/moon position and light phases. + https://github.com/mourner/suncalc +*/ + +(function () { 'use strict'; + +// shortcuts for easier to read formulas + +var PI = Math.PI, + sin = Math.sin, + cos = Math.cos, + tan = Math.tan, + asin = Math.asin, + atan = Math.atan2, + acos = Math.acos, + rad = PI / 180; + +// sun calculations are based on http://aa.quae.nl/en/reken/zonpositie.html formulas + + +// date/time constants and conversions + +var dayMs = 1000 * 60 * 60 * 24, + J1970 = 2440588, + J2000 = 2451545; + +function toJulian(date) { return date.valueOf() / dayMs - 0.5 + J1970; } +function fromJulian(j) { return new Date((j + 0.5 - J1970) * dayMs); } +function toDays(date) { return toJulian(date) - J2000; } + + +// general calculations for position + +var e = rad * 23.4397; // obliquity of the Earth + +function rightAscension(l, b) { return atan(sin(l) * cos(e) - tan(b) * sin(e), cos(l)); } +function declination(l, b) { return asin(sin(b) * cos(e) + cos(b) * sin(e) * sin(l)); } + +function azimuth(H, phi, dec) { return atan(sin(H), cos(H) * sin(phi) - tan(dec) * cos(phi)); } +function altitude(H, phi, dec) { return asin(sin(phi) * sin(dec) + cos(phi) * cos(dec) * cos(H)); } + +function siderealTime(d, lw) { return rad * (280.16 + 360.9856235 * d) - lw; } + +function astroRefraction(h) { + if (h < 0) // the following formula works for positive altitudes only. + h = 0; // if h = -0.08901179 a div/0 would occur. + + // formula 16.4 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + // 1.02 / tan(h + 10.26 / (h + 5.10)) h in degrees, result in arc minutes -> converted to rad: + return 0.0002967 / Math.tan(h + 0.00312536 / (h + 0.08901179)); +} + +// general sun calculations + +function solarMeanAnomaly(d) { return rad * (357.5291 + 0.98560028 * d); } + +function eclipticLongitude(M) { + + var C = rad * (1.9148 * sin(M) + 0.02 * sin(2 * M) + 0.0003 * sin(3 * M)), // equation of center + P = rad * 102.9372; // perihelion of the Earth + + return M + C + P + PI; +} + +function sunCoords(d) { + + var M = solarMeanAnomaly(d), + L = eclipticLongitude(M); + + return { + dec: declination(L, 0), + ra: rightAscension(L, 0) + }; +} + + +var SunCalc = {}; + + +// calculates sun position for a given date and latitude/longitude + +SunCalc.getPosition = function (date, lat, lng) { + + var lw = rad * -lng, + phi = rad * lat, + d = toDays(date), + + c = sunCoords(d), + H = siderealTime(d, lw) - c.ra; + + return { + azimuth: azimuth(H, phi, c.dec), + altitude: altitude(H, phi, c.dec) + }; +}; + + +// sun times configuration (angle, morning name, evening name) + +var times = SunCalc.times = [ + [-0.833, 'sunrise', 'sunset' ], + [ -0.3, 'sunriseEnd', 'sunsetStart' ], + [ -6, 'dawn', 'dusk' ], + [ -12, 'nauticalDawn', 'nauticalDusk'], + [ -18, 'nightEnd', 'night' ], + [ 6, 'goldenHourEnd', 'goldenHour' ] +]; + +// adds a custom time to the times config + +SunCalc.addTime = function (angle, riseName, setName) { + times.push([angle, riseName, setName]); +}; + + +// calculations for sun times + +var J0 = 0.0009; + +function julianCycle(d, lw) { return Math.round(d - J0 - lw / (2 * PI)); } + +function approxTransit(Ht, lw, n) { return J0 + (Ht + lw) / (2 * PI) + n; } +function solarTransitJ(ds, M, L) { return J2000 + ds + 0.0053 * sin(M) - 0.0069 * sin(2 * L); } + +function hourAngle(h, phi, d) { return acos((sin(h) - sin(phi) * sin(d)) / (cos(phi) * cos(d))); } +function observerAngle(height) { return -2.076 * Math.sqrt(height) / 60; } + +// returns set time for the given sun altitude +function getSetJ(h, lw, phi, dec, n, M, L) { + + var w = hourAngle(h, phi, dec), + a = approxTransit(w, lw, n); + return solarTransitJ(a, M, L); +} + + +// calculates sun times for a given date, latitude/longitude, and, optionally, +// the observer height (in meters) relative to the horizon + +SunCalc.getTimes = function (date, lat, lng, height) { + + height = height || 0; + + var lw = rad * -lng, + phi = rad * lat, + + dh = observerAngle(height), + + d = toDays(date), + n = julianCycle(d, lw), + ds = approxTransit(0, lw, n), + + M = solarMeanAnomaly(ds), + L = eclipticLongitude(M), + dec = declination(L, 0), + + Jnoon = solarTransitJ(ds, M, L), + + i, len, time, h0, Jset, Jrise; + + + var result = { + solarNoon: fromJulian(Jnoon), + nadir: fromJulian(Jnoon - 0.5) + }; + + for (i = 0, len = times.length; i < len; i += 1) { + time = times[i]; + h0 = (time[0] + dh) * rad; + + Jset = getSetJ(h0, lw, phi, dec, n, M, L); + Jrise = Jnoon - (Jset - Jnoon); + + result[time[1]] = fromJulian(Jrise); + result[time[2]] = fromJulian(Jset); + } + + return result; +}; + + +// moon calculations, based on http://aa.quae.nl/en/reken/hemelpositie.html formulas + +function moonCoords(d) { // geocentric ecliptic coordinates of the moon + + var L = rad * (218.316 + 13.176396 * d), // ecliptic longitude + M = rad * (134.963 + 13.064993 * d), // mean anomaly + F = rad * (93.272 + 13.229350 * d), // mean distance + + l = L + rad * 6.289 * sin(M), // longitude + b = rad * 5.128 * sin(F), // latitude + dt = 385001 - 20905 * cos(M); // distance to the moon in km + + return { + ra: rightAscension(l, b), + dec: declination(l, b), + dist: dt + }; +} + +SunCalc.getMoonPosition = function (date, lat, lng) { + + var lw = rad * -lng, + phi = rad * lat, + d = toDays(date), + + c = moonCoords(d), + H = siderealTime(d, lw) - c.ra, + h = altitude(H, phi, c.dec), + // formula 14.1 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + pa = atan(sin(H), tan(phi) * cos(c.dec) - sin(c.dec) * cos(H)); + + h = h + astroRefraction(h); // altitude correction for refraction + + return { + azimuth: azimuth(H, phi, c.dec), + altitude: h, + distance: c.dist, + parallacticAngle: pa + }; +}; + + +// calculations for illumination parameters of the moon, +// based on http://idlastro.gsfc.nasa.gov/ftp/pro/astro/mphase.pro formulas and +// Chapter 48 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + +SunCalc.getMoonIllumination = function (date) { + + var d = toDays(date || new Date()), + s = sunCoords(d), + m = moonCoords(d), + + sdist = 149598000, // distance from Earth to Sun in km + + phi = acos(sin(s.dec) * sin(m.dec) + cos(s.dec) * cos(m.dec) * cos(s.ra - m.ra)), + inc = atan(sdist * sin(phi), m.dist - sdist * cos(phi)), + angle = atan(cos(s.dec) * sin(s.ra - m.ra), sin(s.dec) * cos(m.dec) - + cos(s.dec) * sin(m.dec) * cos(s.ra - m.ra)); + + return { + fraction: (1 + cos(inc)) / 2, + phase: 0.5 + 0.5 * inc * (angle < 0 ? -1 : 1) / Math.PI, + angle: angle + }; +}; + + +function hoursLater(date, h) { + return new Date(date.valueOf() + h * dayMs / 24); +} + +// calculations for moon rise/set times are based on http://www.stargazing.net/kepler/moonrise.html article + +SunCalc.getMoonTimes = function (date, lat, lng, inUTC) { + var t = new Date(date); + if (inUTC) t.setUTCHours(0, 0, 0, 0); + else t.setHours(0, 0, 0, 0); + + var hc = 0.133 * rad, + h0 = SunCalc.getMoonPosition(t, lat, lng).altitude - hc, + h1, h2, rise, set, a, b, xe, ye, d, roots, x1, x2, dx; + + // go in 2-hour chunks, each time seeing if a 3-point quadratic curve crosses zero (which means rise or set) + for (var i = 1; i <= 24; i += 2) { + h1 = SunCalc.getMoonPosition(hoursLater(t, i), lat, lng).altitude - hc; + h2 = SunCalc.getMoonPosition(hoursLater(t, i + 1), lat, lng).altitude - hc; + + a = (h0 + h2) / 2 - h1; + b = (h2 - h0) / 2; + xe = -b / (2 * a); + ye = (a * xe + b) * xe + h1; + d = b * b - 4 * a * h1; + roots = 0; + + if (d >= 0) { + dx = Math.sqrt(d) / (Math.abs(a) * 2); + x1 = xe - dx; + x2 = xe + dx; + if (Math.abs(x1) <= 1) roots++; + if (Math.abs(x2) <= 1) roots++; + if (x1 < -1) x1 = x2; + } + + if (roots === 1) { + if (h0 < 0) rise = i + x1; + else set = i + x1; + + } else if (roots === 2) { + rise = i + (ye < 0 ? x2 : x1); + set = i + (ye < 0 ? x1 : x2); + } + + if (rise && set) break; + + h0 = h2; + } + + var result = {}; + + if (rise) result.rise = hoursLater(t, rise); + if (set) result.set = hoursLater(t, set); + + if (!rise && !set) result[ye > 0 ? 'alwaysUp' : 'alwaysDown'] = true; + + return result; +}; + + +// export as Node module / AMD module / browser variable +if (typeof exports === 'object' && typeof module !== 'undefined') module.exports = SunCalc; +else if (typeof define === 'function' && define.amd) define(SunCalc); +else window.SunCalc = SunCalc; + +}()); diff --git a/RVO4/flow/helper/utils.js b/RVO4/flow/helper/utils.js new file mode 100755 index 0000000..dbffe45 --- /dev/null +++ b/RVO4/flow/helper/utils.js @@ -0,0 +1,161 @@ +const fs = require('fs').promises; + +function bytesToInt(bytes, numberOfBytes) { + let buffer = []; + if (Array.isArray(bytes)) { + buffer = bytes.slice(0); + if (numberOfBytes != undefined) { + buffer = bytes.slice(bytes.length - numberOfBytes); + } + } + else buffer.push(bytes); + + let result = 0; + for (let i = 0; i < buffer.length; i++) { + result = (result << 8) | buffer[i]; + } + + return result >>> 0; //ensure it's an unsigned 32-bit number +} + +function resizeArray(arr, newSize, defaultValue) { + while (newSize > arr.length) + arr.push(defaultValue); + arr.length = newSize; +} + +longToByteArray = function(/*long*/long) { + // we want to represent the input as a 8-bytes array + var byteArray = [0, 0, 0, 0, 0, 0, 0, 0]; + + for (var index = 0; index < byteArray.length; index++) { + var byte = long & 0xff; + byteArray[index] = byte; + long = (long - byte) / 256; + } + + return byteArray; +}; + +function addDays(date, days) { + var result = new Date(date); + result.setDate(result.getDate() + days); + return result; +} + +/* +sleep(2000).then(() => { + // Do something after the sleep! + + +}); +*/ + +function sleep(time) { + return new Promise((resolve) => setTimeout(resolve, time)); +} + +function isEmptyObject(obj) { + for (var name in obj) { + return false; + } + return true; +} + +function emptyJsObject(jsObject) { + Object.keys(jsObject).forEach(key => delete jsObject[key]); +} + +function convertUTCDateToLocalDate(date) { + var newDate = new Date(date); + newDate.setMinutes(date.getMinutes() + date.getTimezoneOffset()); + return newDate; +} + +function addZeroBefore(n) { + return (n < 10 ? '0' : '') + n; +} + + +/** + * Asynchronously writes data to a file. + * + * @param {string} filePath The path to the file. + * @param {string} data The data to write to the file. + * @param {boolean} [append=false] If true, appends the data to the file. If false, it overwrites the file. + */ +async function writeToFile(filePath, data, append = false) { + if (typeof data !== 'string') data = JSON.stringify(data, null, 2); + try { + if (append) { + // Append the data to the end of the file. This is the simplest way to append. + await fs.appendFile(filePath, data, 'utf8'); + console.log(`Successfully appended data to ${filePath} using fs.appendFile.`); + } else { + // Overwrite the file with the new data. + await fs.writeFile(filePath, data, 'utf8'); + console.log(`Successfully wrote (overwrote) data to ${filePath} using fs.writeFile.`); + } + } catch (error) { + console.error(`Error writing to file ${filePath}:`, error); + } +} + + + /** + * Checks if an item is present in an array and adds it if it's not. + * * @param {Array} arr The array to check. + * @param {*} item The item to add. + * @returns {Array} The modified array. + */ +const addToArrayIfUnique = (arr, item) => { + if (!arr.includes(item)) { + arr.push(item); + } + return arr; +}; + + +var convertBase = function() { + + function convertBase(baseFrom, baseTo) { + return function(num) { + return parseInt(num, baseFrom).toString(baseTo); + + }; + } + + // binary to decimal + convertBase.bin2dec = convertBase(2, 10); + + // binary to hexadecimal + convertBase.bin2hex = convertBase(2, 16); + + // decimal to binary + convertBase.dec2bin = convertBase(10, 2); + + // decimal to hexadecimal + convertBase.dec2hex = convertBase(10, 16); + + // hexadecimal to binary + convertBase.hex2bin = convertBase(16, 2); + + // hexadecimal to decimal + convertBase.hex2dec = convertBase(16, 10); + + return convertBase; +}(); + +module.exports = { + bytesToInt, + longToByteArray, + addDays, + addZeroBefore, + resizeArray, + isEmptyObject, + emptyJsObject, + sleep, + convertUTCDateToLocalDate, + writeToFile, + addToArrayIfUnique +} diff --git a/RVO4/flow/httprequest.js b/RVO4/flow/httprequest.js new file mode 100755 index 0000000..469c8cb --- /dev/null +++ b/RVO4/flow/httprequest.js @@ -0,0 +1,137 @@ +exports.id = 'httprequest'; +exports.title = 'HTTP Request'; +exports.group = 'HTTP'; +exports.color = '#5D9CEC'; +exports.input = true; +exports.version = '2.0.1'; +exports.output = 1; +exports.author = 'Peter Širka'; +exports.icon = 'cloud-upload'; + +exports.html = `
+
@(URL address)
+
+
+
@(HTTP method)
+
+
+
@(Serialization)
+
+
+
@(Download the content in chunks)
+
@(Keep persistent cookies)
+
@(Disable DNS cache)
+
@(Keep alive connection)
+
+
+
+
@(Custom headers)
+
@(Cookies)
+
+
+
+ +
+
+
+
@(User)
+
+
+
@(Password)
+
+
+
+
+
`; + +exports.readme = `# Request + +This component creates a request with received data. + +__Response:__ +\`\`\`javascript +{ + data: String, + headers: Object, + status: Number, + host: String +} +\`\`\` + +__Dynamic arguments__: +Are performed via FlowData repository and can be used for URL address or for custom headers/cookies/auth. Use \`repository\` component for creating of dynamic arguments. Dynamic values are replaced in the form \`{key}\`: + +- url address e.g. \`https://.../{key}/\` +- headers values e.g. \`{token}\` +- cookies values e.g. \`{token}\``; + +exports.install = function(instance) { + + var can = false; + var flags = null; + var cookies2 = null; + + instance.on('data', function(response) { + can && instance.custom.send(response); + }); + + instance.custom.send = function(response) { + var options = instance.options; + + var headers = null; + var cookies = null; + + options.headers && Object.keys(options.headers).forEach(function(key) { + !headers && (headers = {}); + headers[key] = response.arg(options.headers[key]); + }); + + if (options.username && options.userpassword) { + !headers && (headers = {}); + headers['Authorization'] = 'Basic ' + U.createBuffer(response.arg(options.username + ':' + options.userpassword)).toString('base64'); + } + + options.cookies && Object.keys(options.cookies).forEach(function(key) { + !cookies && (cookies = {}); + cookies[key] = response.arg(options.cookies[key]); + }); + + if (options.chunks) { + U.download(response.arg(options.url), flags, options.stringify === 'none' ? null : response.data, function(err, response) { + response.on('data', (chunks) => instance.send2(chunks)); + }, cookies || cookies2, headers); + } else { + U.request(response.arg(options.url), flags, options.stringify === 'none' ? null : response.data, 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) + instance.error(err, response); + }, cookies || cookies2, headers); + } + }; + + instance.reconfigure = function() { + var options = instance.options; + can = options.url && options.url && options.method && options.stringify ? true : false; + instance.status(can ? '' : 'Not configured', can ? undefined : 'red'); + + if (!can) + return; + + flags = []; + flags.push(options.method.toLowerCase()); + options.stringify === 'json' && flags.push('json'); + options.stringify === 'raw' && flags.push('raw'); + options.keepalive && flags.push('keepalive'); + !options.nodns && flags.push('dnscache'); + if (options.persistentcookies) { + flags.push('cookies'); + cookies2 = {}; + } else + cookies2 = null; + }; + + instance.on('options', instance.reconfigure); + instance.reconfigure(); +}; \ No newline at end of file diff --git a/RVO4/flow/httpresponse.js b/RVO4/flow/httpresponse.js new file mode 100755 index 0000000..160a3bb --- /dev/null +++ b/RVO4/flow/httpresponse.js @@ -0,0 +1,76 @@ +exports.id = 'httpresponse'; +exports.title = 'HTTP Response'; +exports.group = 'HTTP'; +exports.color = '#5D9CEC'; +exports.icon = 'arrow-right'; +exports.input = true; +exports.output = ['#666D76']; +exports.version = '2.0.0'; +exports.author = 'Martin Smola'; +exports.readme = `# HTTP response + +HTTP response will respond with data recieved using data-type set in Settings form or plain text if not set. Output is the message duration \`Number\` in seconds.`; + +exports.html = `
+
@(Response data-type)
+
JSON is by default.
+
`; + +exports.install = function(instance) { + + var dursum = 0; + var durcount = 0; + + instance.on('data', function(flowdata) { + + var ctrl = flowdata.repository.controller; + var data = flowdata.data; + + if (!ctrl) { + instance.throw('No controller to use for response!'); + return; + } + + durcount++; + dursum += ((new Date() - flowdata.begin) / 1000).floor(2); + setTimeout2(instance.id, instance.custom.duration, 500, 10); + + ctrl.$flowdata = flowdata; + + var datatype = instance.options.datatype || 'json'; + if (datatype === 'emptyresponse') + return ctrl.plain(''); + + if (datatype !== 'json' && typeof(data) !== 'string') { + instance.throw('Incorect type of data, expected string, got ' + typeof(data)); + ctrl.plain(data == null ? '' : data.toString()); + return; + } + + switch(datatype) { + case 'html': + ctrl.content(data, 'text/html'); + break; + case 'plain': + ctrl.plain(data); + break; + case 'xml': + ctrl.content(data, 'text/xml'); + break; + default: + ctrl.json(data); + break; + } + }); + + instance.on('service', function() { + dursum = 0; + durcount = 0; + }); + + instance.custom.duration = function() { + var avg = (dursum / durcount).floor(2); + instance.status(avg + ' sec.'); + instance.send2(0, avg); + }; +}; diff --git a/RVO4/flow/httproute.js b/RVO4/flow/httproute.js new file mode 100755 index 0000000..583a19d --- /dev/null +++ b/RVO4/flow/httproute.js @@ -0,0 +1,326 @@ +exports.id = 'httproute'; +exports.title = 'HTTP Route'; +exports.group = 'HTTP'; +exports.color = '#5D9CEC'; +exports.icon = 'globe'; +exports.input = false; +exports.output = ['#6CAC5A', '#37BC9B']; +exports.version = '1.2.3'; +exports.author = 'Martin Smola'; +exports.cloning = false; +exports.options = { method: 'GET', url: '', size: 5, cacheexpire: '5 minutes', cachepolicy: 0, timeout: 5 }; +exports.dateupdated = '2021-01-21 18:30d'; +exports.readme = `# HTTP route + +__Outputs__: +- first output: raw data (cache is empty or is disabled) +- second output: cached data + +If one of the outputs is disabled then automatic responce with code "503 service unavailable" is sent. + +When a request comes in bellow object is available at \`flowdata.data\`: + +\`\`\`javascript +{ + params: { id: '1' }, // params for dynamic routes, e.g. /test/{id} + query: { msg: 'Hello' }, // parsed query string, e.g. /test/1?msg=Hello + body: { test: 'OK' }, // object if json requests otherwise string + headers: {}, // headers data + session: {}, // session data + user: {}, // user data + files: [], // uploaded files + url: '/users/', // a relative URL address + referrer: '/', // referrer + mobile: false, // determines mobile device + robot: false, // determines search robots/crawlsers + language: 'en' // determines language +} +\`\`\` + +See [documentation for flags](https://docs.totaljs.com/latest/en.html#api~HttpRouteOptionsFlags~unauthorize). These method flags are set automatically e.g. \`get, post, put, patch or delete\` + +--- + +\`id:ROUTE_ID\` flag cannot be used since it's already used by this component internally`; + +exports.html = `
+
+ +
+ +
+
+
@(HTTP method)
+
+
+
@(URL address)
+
+
+
+
+
@(Additional flags)
+
@(Separate flags by comma e.g. json, authorize)
+
+
+
@(Max. request size)
+
@(In kB kilobytes)
+
+
+
@(Timeout)
+
@(In seconds.)
+
+
+
+
+
+
@(Automatically respond with 200 OK?)
+
@(If not checked you need to use HTTP response component to respond to the request.)
+
+
@(Custom headers)
+
@(Cookies)
+
+
+
+
+
+
@(Cache policy)
+
@(User instance must contain id property.)
+
+
+
@(Expiration)
+
@(E.g. 5 minutes)
+
+
+
+`; + +exports.install = function(instance) { + + var route; + + var uninstall = function(id) { + if (F.is4) { + route && route.remove(); + route = null; + } else + UNINSTALL('route', id); + }; + + instance.custom.emptyresponse = function(self) { + self.plain(); + }; + + instance.reconfigure = function() { + + var options = instance.options; + + if (!options.url) { + instance.status('Not configured', 'red'); + return; + } + + if (typeof(options.flags) === 'string') + options.flags = options.flags.split(',').trim(); + + uninstall('id:' + instance.id); + + var flags = options.flags || []; + + flags.push('id:' + instance.id); + + if (!F.is4) + flags.push(options.method.toLowerCase()); + + options.timeout && flags.push(options.timeout * 1000); + + // Make unique values + flags = flags.filter(function(v, i, a) { + if(F.is4 && v.toString().toLowerCase() === options.method.toLowerCase()) + return false; // remove method + return a.indexOf(v) === i; + }); + + options.flags = flags; + var handler = function() { + + if (instance.paused || (instance.isDisabled && (instance.isDisabled('output', 0) || instance.isDisabled('output', 1)))) { + instance.status('503 Service Unavailable'); + this.status = 503; + this.json(); + return; + } + + var key; + var self = this; + + if (instance.options.emptyresponse) { + instance.status('200 OK'); + setTimeout(instance.custom.emptyresponse, 100, self); + + if (instance.hasConnection(0)) { + var data = instance.make({ + query: self.query, + body: self.body, + session: self.session, + user: self.user, + files: self.files, + headers: self.req.headers, + url: self.url, + params: self.params + }); + instance.send2(0, data); + } + + return; + } + + switch (instance.options.cachepolicy) { + case 1: // URL + key = 'rro' + instance.id + self.url.hash(); + break; + case 2: // URL + query + case 3: // URL + query + user + key = self.url; + var keys = Object.keys(self.query); + keys.sort(); + for (var i = 0, length = keys.length; i < length; i++) + key += keys[i] + self.query[keys[i]] + '&'; + if (instance.options.cachepolicy === 3 && self.user) + key += 'iduser' + self.user.id; + key = 'rro' + instance.id + key.hash(); + break; + } + + if (key && F.cache.get2(key)) { + var data = instance.make(F.cache.get2(key)); + data.repository.controller = self; + instance.send2(1, data); + } else { + + var data = instance.make({ + query: self.query, + body: self.body, + session: self.session, + user: self.user, + files: self.files, + headers: self.req.headers, + url: self.url, + params: self.params, + mobile: self.mobile, + robot: self.robot, + referrer: self.referrer, + language: self.language + }); + + data.repository.controller = self; + instance.send2(0, data); + key && FINISHED(self.res, () => F.cache.set(key, self.$flowdata.data, instance.options.cacheexpire)); + } + }; + + if (F.is4) + route = ROUTE(options.method.toUpperCase() + ' ' + options.url, handler, flags, options.size || 5); + else + F.route(options.url, handler, flags, options.size || 5); + + instance.status('Listening', 'green'); + }; + + instance.reconfigure(); + instance.on('options', instance.reconfigure); + instance.on('close', function(){ + uninstall('id:' + instance.id); + }); +}; + +// check url exists +FLOW.trigger('httproutecheckurl', function(next, data) { + var url = data.url; + var method = data.method; + if (url[url.length - 1] !== '/') + url += '/'; + var exists = F.routes.web.findItem(r => r.urlraw === url && r.method === method); + next(exists != null); +}); + +exports.uninstall = function() { + FLOW.trigger('httproutecheckurl', null); +}; diff --git a/RVO4/flow/infosender.js b/RVO4/flow/infosender.js new file mode 100755 index 0000000..587724f --- /dev/null +++ b/RVO4/flow/infosender.js @@ -0,0 +1,81 @@ +exports.id = 'infosender'; +exports.title = 'Info sender'; +exports.version = '1.0.0'; +exports.group = 'Worksys'; +exports.color = '#2134B0'; +exports.input = 2; +exports.output = 1 +exports.icon = 'bolt'; + +const { networkInterfaces } = require('os'); + +exports.html = `
+
+
+
CSV Import
+
+
+
`; + +exports.readme = `# send all data to projects.worksys.io, required to monitor status of controller(unipi)`; + +exports.install = function(instance) { + + let id; + let allValues = {}; + let sendAllValuesInterval; + let configured = false; + + let now = new Date(); + console.log(exports.title, "INSTALLED", now.toLocaleString("sk-SK")); + + const nets = networkInterfaces(); + let ipAddresses = Object.create(null); // Or just '{}', an empty object + + for (const name of Object.keys(nets)) { + for (const net of nets[name]) { + // Skip over non-IPv4 and internal (i.e. 127.0.0.1) addresses + if (net.family === 'IPv4' && !net.internal) { + if (!ipAddresses[name]) { + ipAddresses[name] = []; + } + ipAddresses[name].push(net.address); + } + } + } + + function sendValues() { + if (!configured) return; + + if (Object.keys(allValues).length > 0) { + let dataToSend = { ...allValues }; + dataToSend.id = id; + dataToSend.ipAddresses = ipAddresses; + + instance.send(0, dataToSend); + + allValues = {}; + } + } + + instance.on("close", () => { + clearInterval(sendAllValuesInterval); + }) + + instance.on("0", _ => { + id = FLOW.GLOBALS.settings.project_id; + if (id) configured = true; + else console.log(exports.title, "InfoSender: Unable to send data, no id"); + }) + + instance.on("1", flowdata => { + allValues = { ...allValues, ...flowdata.data }; + //console.log("DATA RECEIVED", flowdata.data); + }) + + sendAllValuesInterval = setInterval(() => { + sendValues(); + }, 60000 * 3); + +} + diff --git a/RVO4/flow/modbus_reader.js b/RVO4/flow/modbus_reader.js new file mode 100755 index 0000000..d6d9dad --- /dev/null +++ b/RVO4/flow/modbus_reader.js @@ -0,0 +1,346 @@ +exports.id = 'modbus_reader'; +exports.title = 'Modbus reader'; +exports.version = '2.0.0'; +exports.group = 'Worksys'; +exports.color = '#2134B0'; +exports.input = 1; +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; +//number of phases inRVO +let phases; +//phases where voltage is 0 (set) +let noVoltage; +let energyToSwitchLamps; + +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.phases = this.buildPhases(); + + this.startSocket(); + } + + buildPhases = () => { + let a = []; + for (let i = 1; i <= phases; i++) { + a.push(`Phase_${i}_voltage`) + } + return a; + } + + startSocket = () => { + + let obj = this; + + if (this.socket) { + this.socket.removeAllListeners(); + this.socket = null; + } + + 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('Modbus_reader: Socket connection error', e); //'ECONNREFUSED' or 'ECONNRESET' ?? + }); + + this.socket.on('close', function() { + console.log('Modbus_reader: Socket connection closed - Waiting 10 seconds before connecting 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 we just start to loop devices from the beginning, or there is just 1 device in config, we wait whole timeoutInterval + if (this.indexInDeviceConfig == 0 || deviceConfig.length === 1) 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 (this.phases.includes(singleValue)) { + let l = singleValue.split("_"); + let phase = parseInt(l[1]); + + // console.log(values[singleValue], tbName); + + if (values[singleValue] == 0) { + noVoltage.add(phase); + sendNotification("modbus_reader: checkNullVoltage", tbName, "no_voltage_on_phase", { phase: phase }, "", SEND_TO.tb, instance, "voltage" + phase); + // console.log('no voltage') + } + else { + noVoltage.delete(phase); + // console.log('voltage detected') + sendNotification("modbus_reader: checkNullVoltage", tbName, "voltage_on_phase_restored", { phase: phase }, "", SEND_TO.tb, instance, "voltage" + phase); + } + } + }) + } + + /** + * function sends notification to slack and to tb, if EM total_power value changes more than numberOfNodes*15. This should show, that RVO lamps has been switched on or off + */ + lampSwitchNotification = (values) => { + + if (!values.hasOwnProperty("total_power")) return; + + const actualTotalPower = values.total_power; + + if (actualTotalPower > energyToSwitchLamps && 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 <= energyToSwitchLamps && 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; + } + + function main() { + + phases = FLOW.GLOBALS.settings.phases; + tbName = FLOW.GLOBALS.settings.rvoTbName; + noVoltage = FLOW.GLOBALS.settings.no_voltage; + energyToSwitchLamps = FLOW.GLOBALS.settings.energy_to_switch_lamps / 2.5; //half value is enought to show if lamps are turned on or off + if (deviceConfig.length) mainSocket = new SocketWithClients(); + else console.log("Modbus_reader: no modbus device in configuration"); + + // this notification is to show, that flow (unipi) has been restarted + sendNotification("modbus_reader", tbName, "flow_restart", {}, "", SEND_TO.slack, instance); + } + + instance.on("0", function(_) { + main(); + }) + +} + diff --git a/RVO4/flow/monitorconsumption.js b/RVO4/flow/monitorconsumption.js new file mode 100755 index 0000000..64cc58e --- /dev/null +++ b/RVO4/flow/monitorconsumption.js @@ -0,0 +1,156 @@ +exports.id = 'monitorconsumption'; +exports.title = 'Consumption'; +exports.version = '1.0.0'; +exports.author = 'Peter Širka'; +exports.group = 'Monitoring'; +exports.color = '#967ADC'; +exports.input = 0; +exports.output = 1; +exports.icon = 'bug'; +exports.options = { interval: 5000, enabled: true, monitorconsumption: true, monitorsize: true, monitorconnections: true, monitorfiles: true }; +exports.click = true; +exports.readme = `# Consumption monitoring + +This component measure CPU and memory consumption, open files and open connections of this application. It uses these Linux commands: \`ps\`, \`lsof\`, \`netstat\` and \`df\`. + +__Data Example__: + +\`\`\`javascript +{ + cpu: 0, // percentage + memory: 4096, // in bytes + size: 34303, // directory size in bytes + files: 34, // count of open files + connections: 343, // count of connections + uptime: '1-12:34:00' +} +\`\`\``; + +exports.html = `
+
+
+
@(Interval in milliseconds)
+
+
+
+
Monitor: Consumption + uptime
+
Monitor: Count of open files
+
Monitor: Count of open connections
+
Monitor: Directory size
+
`; + +exports.install = function(instance) { + + var current = { cpu: 0, memory: 0, files: 0, connections: 0, size: 0, uptime: '', counter: 0 }; + var tproc = null; + var Exec = require('child_process').exec; + var reg_empty = /\s{2,}/g; + var reg_appdisksize = /^[\d.,]+/; + + instance.custom.run = function() { + + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + + var arr = []; + + // Get CPU and Memory consumption + instance.options.monitorconsumption && arr.push(function(next) { + Exec('ps -p {0} -o %cpu,rss,etime'.format(process.pid), function(err, response) { + + if (err) { + instance.throw(err); + } else { + var line = response.split('\n')[1]; + line = line.trim().replace(reg_empty, ' ').split(' '); + var cpu = line[0].parseFloat(); + current.cpu = cpu.floor(1); + current.memory = line[1].parseInt2() * 1024; // kB to bytes + current.uptime = line[2]; + } + + next(); + }); + }); + + // Get count of open files + instance.options.monitorfiles && arr.push(function(next) { + Exec('lsof -a -p {0} | wc -l'.format(process.pid), function(err, response) { + if (err) + instance.throw(err); + else + current.files = response.trim().parseInt2(); + next(); + }); + }); + + // Get count of opened network connections + instance.options.monitorconnections && arr.push(function(next) { + Exec('netstat -an | grep :{0} | wc -l'.format(F.port), function(err, response) { + if (err) { + instance.throw(err); + } else { + current.connections = response.trim().parseInt2() - 1; + if (current.connections < 0) + current.connections = 0; + } + next(); + }); + }); + + // Get directory size + instance.options.monitorsize && current.counter % 5 !== 0 && arr.push(function(next) { + Exec('du -hsb ' + process.cwd(), function(err, response) { + if (err) { + instance.throw(err); + } else { + var match = response.trim().match(reg_appdisksize); + match && (current.size = match.toString().trim().parseInt2()); + } + next(); + }); + }); + + arr.async(function() { + + tproc && clearTimeout(tproc); + + if (instance.options.enabled) { + tproc = setTimeout(instance.custom.run, instance.options.interval); + instance.send2(current); + } + + instance.custom.status(); + current.counter++; + }); + }; + + instance.custom.status = function() { + if (instance.options.enabled) + instance.status('{0}% / {1}'.format(current.cpu, current.memory.filesize())); + else + instance.status('Disabled', 'red'); + }; + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + + if (instance.options.enabled) { + current.counter = 0; + instance.custom.run(); + } + + }); + + instance.on('close', function() { + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + }); + + setTimeout(instance.custom.run, 1000); +}; \ No newline at end of file diff --git a/RVO4/flow/monitordisk.js b/RVO4/flow/monitordisk.js new file mode 100755 index 0000000..f4fdaa0 --- /dev/null +++ b/RVO4/flow/monitordisk.js @@ -0,0 +1,96 @@ +exports.id = 'monitordisk'; +exports.title = 'Disk'; +exports.version = '1.0.0'; +exports.author = 'Peter Širka'; +exports.group = 'Monitoring'; +exports.color = '#F6BB42'; +exports.output = 1; +exports.icon = 'hdd-o'; +exports.click = true; +exports.options = { interval: 8000, path: '/', enabled: true }; +exports.readme = `# Disk monitoring + +This component monitors disk \`bytes\` consumption in Linux systems. It uses \`df\` command. + +__Data Example__: + +\`\`\`javascript +{ + total: 474549649408, + used: 39125245952, + free: 411294994432 +} +\`\`\``; + +exports.html = `
+
+
+
@(Interval in milliseconds)
+
+
+
@(Path)
+
+
+
`; + +exports.install = function(instance) { + + var current = { total: 0, used: 0, free: 0, path: '', type: '', percentUsed: 0 }; + var tproc = null; + + instance.custom.run = function() { + + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + + if (!instance.options.enabled) + return; + + require('child_process').exec('df -hTB1 ' + instance.options.path, function(err, response) { + + tproc = setTimeout(instance.custom.run, instance.options.interval); + + if (err) { + instance.error(err); + return; + } + + response.parseTerminal(function(line) { + if (line[0][0] !== '/') + return; + current.total = line[2].parseInt(); + current.free = line[4].parseInt(); + current.used = line[3].parseInt(); + current.path = instance.options.path || '/'; + current.type = line[1]; + current.percentUsed = line[5]; + instance.custom.status(); + instance.send2(current); + }); + }); + }; + + instance.custom.status = function() { + if (instance.options.enabled) + instance.status(current.free.filesize() + ' / ' + current.total.filesize()); + else + instance.status('Disabled', 'red'); + }; + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + instance.options.enabled && instance.custom.run(); + }); + + instance.on('close', function() { + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + }); + + setTimeout(instance.custom.run, 1000); +}; \ No newline at end of file diff --git a/RVO4/flow/monitormemory.js b/RVO4/flow/monitormemory.js new file mode 100755 index 0000000..2decbc4 --- /dev/null +++ b/RVO4/flow/monitormemory.js @@ -0,0 +1,87 @@ +exports.id = 'monitormemory'; +exports.title = 'Memory'; +exports.version = '1.0.0'; +exports.author = 'Peter Širka'; +exports.group = 'Monitoring'; +exports.color = '#F6BB42'; +exports.output = 1; +exports.click = true; +exports.icon = 'microchip'; +exports.options = { interval: 8000, enabled: true }; +exports.readme = `# Memory monitoring + +This component monitors memory \`bytes\` consumption in Linux systems. It uses \`free\` command. + +__Data Example__: + +\`\`\`javascript +{ + total: 33558769664, + used: 1998868480, + free: 2653708288 +} +\`\`\``; + +exports.html = `
+
+
+
@(Interval in milliseconds)
+
+
+
`; + +exports.install = function(instance) { + + var current = { total: 0, used: 0, free: 0 }; + var tproc = null; + + instance.custom.run = function() { + + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + + if (!instance.options.enabled) + return; + + require('child_process').exec('free -b -t', function(err, response) { + + tproc = setTimeout(instance.custom.run, instance.options.interval); + + if (err) { + instance.error(err); + return; + } + + var memory = response.split('\n')[1].match(/\d+/g); + current.total = memory[0].parseInt(); + current.used = memory[1].parseInt() - memory[3].parseInt(); + current.free = current.total - current.used; + instance.custom.status(); + instance.send2(current); + }); + }; + + instance.custom.status = function() { + if (instance.options.enabled) + instance.status(current.free.filesize() + ' / ' + current.total.filesize()); + else + instance.status('Disabled', 'red'); + }; + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + instance.options.enabled && instance.custom.run(); + }); + + instance.on('close', function() { + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + }); + + setTimeout(instance.custom.run, 1000); +}; \ No newline at end of file diff --git a/RVO4/flow/nodesdb_changecheck.js b/RVO4/flow/nodesdb_changecheck.js new file mode 100755 index 0000000..9adab62 --- /dev/null +++ b/RVO4/flow/nodesdb_changecheck.js @@ -0,0 +1,77 @@ +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 = 2; +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); + } + } + + //kedze do slacku posielame stringy, na cloud musime previest vsetky stringy spat na objekty: + // Funkcia na parsovanie všetkých reťazcov v poli + const parseArray = (arr) => { + return arr.map(jsonString => JSON.parse(jsonString)); + }; + + 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); + if (FLOW.GLOBALS.settings.send_changed_node_numbers) instance.send(1, { aktualneNody: parseArray(zmenene), originalne: parseArray(Array.from(set2)) }); + } + 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/RVO4/flow/show_dbdata.js b/RVO4/flow/show_dbdata.js new file mode 100755 index 0000000..1e23ff7 --- /dev/null +++ b/RVO4/flow/show_dbdata.js @@ -0,0 +1,243 @@ +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 = 8; +exports.output = 1; + +const { exec } = require('child_process'); + +exports.install = 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 }) + }) + instance.on("5", _ => { + exec("sudo tail -n 25 monitor.txt", (err, stdout, stderr) => { + if (err || stderr) instance.send(0, { err, stderr }); + else instance.send(0, stdout); + }) + }) + instance.on("6", _ => { + exec("sudo tail -n 25 err.txt", (err, stdout, stderr) => { + if (err || stderr) instance.send(0, { err, stderr }); + else instance.send(0, stdout); + }) + }) + instance.on("7", _ => { + instance.send(0, FLOW.deviceStatus); + }) +}; + + +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/RVO4/flow/slack_filter.js b/RVO4/flow/slack_filter.js new file mode 100755 index 0000000..6618523 --- /dev/null +++ b/RVO4/flow/slack_filter.js @@ -0,0 +1,188 @@ +exports.id = 'slack_filter'; +exports.title = 'Slack Filter'; +exports.group = 'Citysys'; +exports.color = '#30E193'; +exports.input = 2; +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 = `
+
+
+
@(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('0', 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']['en']; + 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"] = []; + } + + instance.options.name = FLOW.GLOBALS.settings.rvo_name; + if (instance.options.name) { + instance.status('Running'); + running = true; + } else { + instance.status('Please run options again', 'red'); + running = false; + } + } catch (e) { + instance.error('Citysys connector: ' + e.message); + } + }; + + instance.on('options', instance.reconfigure); + + instance.on("1", _ => { + instance.reconfigure(); + }) +}; diff --git a/RVO4/flow/thermometer.js b/RVO4/flow/thermometer.js new file mode 100755 index 0000000..fc7074d --- /dev/null +++ b/RVO4/flow/thermometer.js @@ -0,0 +1,99 @@ +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 = 5;//minutes +let NUMBER_OF_FAILURES_TO_SEND_ERROR = 13; + +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) => { + + 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); + setTimeout(main, 20000); + }) +}; diff --git a/RVO4/flow/trigger.js b/RVO4/flow/trigger.js new file mode 100755 index 0000000..27545a8 --- /dev/null +++ b/RVO4/flow/trigger.js @@ -0,0 +1,79 @@ +exports.id = 'trigger'; +exports.title = 'Trigger'; +exports.group = 'Inputs'; +exports.color = '#F6BB42'; +exports.click = true; +exports.output = 1; +exports.version = '1.1.0'; +exports.author = 'Martin Smola'; +exports.icon = 'play'; + +exports.html = `
+
@(Data type (String by default))
+
@(Data)
+
Trigger 5s after initialization.
+
@(Useful when there's a need to run certain flow when the app restarts, etc.)
+
`; + +exports.readme = `# Trigger + +- Clicking on the component starts the chain +- Settings allows to set a data-type and a value`; + +exports.install = function(instance) { + + var value; + + instance.on('click', () => instance.send2(value)); + + instance.reconfigure = function() { + var options = instance.options; + value = null; + switch (options.datatype) { + case 'integer': + value = options.data.parseInt2('error'); + value = value === 'error' ? NaN : value; + break; + case 'float': + value = options.data.parseFloat2('error'); + value = value === 'error' ? NaN : value; + break; + case 'date': + options.data = options.data.toString(); + var num = options.data.parseInt('error'); + num === 'error' && (num = options.data.parseDate('error')); + num === 'error' && (num = null); + value = num ? new Date(num).toUTCString() : num; + break; + case 'object': + try { + value = (new Function('return ' + options.data))(); + } catch (e) { + instance.error(e); + } + break; + case 'boolean': + value = options.data.parseBoolean(); + break; + case 'buffer': + try { + value = U.createBuffer(options.data); + } catch (e) { + instance.error(e); + } + break; + case 'string': + default: + value = '' + (options.data || ''); + break; + } + }; + + instance.on('options', instance.reconfigure); + instance.reconfigure(); + + if (instance.options.restart) + setTimeout(function(){ + instance.send2(value); + }, 5000); +}; diff --git a/RVO4/flow/variables.txt b/RVO4/flow/variables.txt new file mode 100755 index 0000000..e69de29 diff --git a/RVO4/flow/virtualwirein.js b/RVO4/flow/virtualwirein.js new file mode 100755 index 0000000..38a4e42 --- /dev/null +++ b/RVO4/flow/virtualwirein.js @@ -0,0 +1,43 @@ +exports.id = 'virtualwirein'; +exports.title = 'Virtual wire in'; +exports.version = '1.0.0'; +exports.author = 'Martin Smola'; +exports.color = '#303E4D'; +exports.icon = 'sign-in'; +exports.input = false; +exports.output = 1; +exports.options = {}; +exports.readme = `# Virtual wire in + +When the wires between the components are mess it's time to use Virtual wire.`; + +exports.html = `
+
@(Wire name)
+
+`; + +exports.install = function(instance) { + + instance.custom.reconfigure = function(options){ + if (instance.options.wirename) { + instance.status(instance.options.wirename); + } else + instance.status('Not configured', 'red'); + }; + + ON('virtualwire', function(wirename, flowdata){ + if (instance.options.wirename && instance.options.wirename === wirename) + instance.send(flowdata); + }); + + instance.on('options', instance.custom.reconfigure); + instance.custom.reconfigure(); +}; diff --git a/RVO4/flow/virtualwireout.js b/RVO4/flow/virtualwireout.js new file mode 100755 index 0000000..94a1e4f --- /dev/null +++ b/RVO4/flow/virtualwireout.js @@ -0,0 +1,41 @@ +exports.id = 'virtualwireout'; +exports.title = 'Virtual wire out'; +exports.version = '1.0.0'; +exports.author = 'Martin Smola'; +exports.color = '#303E4D'; +exports.icon = 'sign-out'; +exports.input = true; +exports.options = {}; +exports.readme = `# Virtual wire out + +When the wires between the components are mess it's time to use Virtual wire.`; + +exports.html = `
+
@(Wire name)
+
+`; + +exports.install = function(instance) { + + instance.custom.reconfigure = function(){ + if (instance.options.wirename) { + instance.status(instance.options.wirename); + } else + instance.status('Not configured', 'red'); + }; + + instance.on('data', function(flowdata) { + EMIT('virtualwire', instance.options.wirename, flowdata); + }); + + instance.on('options', instance.custom.reconfigure); + instance.custom.reconfigure(); +}; diff --git a/RVO4/flow/wsmqttpublish.js b/RVO4/flow/wsmqttpublish.js new file mode 100755 index 0000000..0eba804 --- /dev/null +++ b/RVO4/flow/wsmqttpublish.js @@ -0,0 +1,448 @@ +exports.id = 'wsmqttpublish'; +exports.title = 'WS MQTT publish'; +exports.group = 'MQTT'; +exports.color = '#888600'; +exports.version = '1.0.2'; +exports.icon = 'sign-out'; +exports.input = 2; +exports.output = 3; +exports.options = { host: 'tb-stage.worksys.io', port: 1883, clientid: "", username: "" }; + +exports.html = `
+
+
+
Hostname or IP address (if not empty - setting will override db setting)
+
+
+
Port
+
+
+
+
+
@(Client id)
+
+
+
@(Username)
+
+
+
`; + + +exports.readme = ` +# WS MQTT Publish + +Version 1.0.3. + +Added: +- database collections, +- 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 = { + debug: 0, + rpcCall: 1, + services: 2 +} + +//CONFIG +let createTelemetryBackup = true; +let saveTelemetryOnError = true;//backup_on_failure overrides this value +//------------------------ + +let rollers; +if (createTelemetryBackup) rollers = require('streamroller'); + +const noSqlFileSizeLimit = 4194304;//use 5MB - 4194304 +let insertNoSqlCounter = 0; +let insertBackupNoSqlCounter = 0; +let processingData = false; + +let backup_on_failure = false;//== saveTelemetryOnError - create backup client 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; + +process.on('uncaughtException', function(err) { + + errLogger.error('uncaughtException:', err.message) + errLogger.error(err.stack); + + //TODO + //send to service + + //process.exit(1); +}) + +const nosql = NOSQL('tbdata'); +const nosqlBackup = NOSQL('/backup/tbdata'); + + +exports.install = function(instance) { + + var client; + var opts; + var clientReady = false; + + // wsmqtt status for notification purposes on projects.worksys.io database + let wsmqttName = null; + let sendWsStatusVar = null; + let wsmqtt_status = 'disconnected'; + + 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'; + } + + function sendWsStatus() { + instance.send(SEND_TO.services, { [wsmqttName]: wsmqtt_status }); + } + + + function main() { + if (!FLOW.dbLoaded) return; + + loadSettings(); + clearInterval(sendWsStatus); + sendWsStatusVar = setInterval(sendWsStatus, 180000); + } + + //set opts according to db settings + function loadSettings() { + + if (instance.options.host !== "") { + //override settings from database + var o = instance.options; + opts = { + host: o.host, + port: o.port, + clientId: o.clientid, + username: o.username, + rejectUnauthorized: false, + resubscribe: false + }; + + wsmqttName = getWsmqttName(o.host); + + console.log("wsmqttpublich -> loadSettings from instance.options", instance.options); + } + else { + + const SETTINGS = FLOW.GLOBALS.settings; + backup_on_failure = SETTINGS.backup_on_failure; + saveTelemetryOnError = backup_on_failure; + + restore_from_backup = SETTINGS.restore_from_backup; + restore_backup_wait = SETTINGS.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; + + opts = { + host: mqtt_host, + port: mqtt_port, + keepalive: 10, + clientId: mqtt_clientid, + username: mqtt_username, + rejectUnauthorized: false, + resubscribe: false + }; + + wsmqttName = getWsmqttName(mqtt_host); + } + + connectToTbServer(); + } + + function connectToTbServer() { + 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"); + //monitor.info("MQTT client connected"); + + sendClientError = true; + clientReady = true; + wsmqtt_status = 'connected'; + }); + + client.on('reconnect', function() { + instance.status("Reconnecting", "yellow"); + clientReady = false; + }); + + client.on('message', function(topic, message) { + // message is type of buffer + message = message.toString(); + if (message[0] === '{') { + TRY(function() { + + message = JSON.parse(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 } }); + } + + }, () => instance.debug('MQTT: Error parsing data', message)); + } + + instance.send(SEND_TO.rpcCall, { "topic": topic, "content": message }); + }); + + client.on('close', function() { + clientReady = false; + wsmqtt_status = 'disconnected'; + + instance.status("Disconnected", "red"); + instance.send(SEND_TO.debug, { "message": "Client CLOSE signal received !" }); + }); + + client.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; + wsmqtt_status = 'disconnected'; + }); + + } + + + instance.on("0", _ => { + main(); + }) + + + instance.on('1', function(data) { + + if (clientReady) { + //do we have some data in backup file? if any, process data from database + if (saveTelemetryOnError) { + //read telemetry data and send back to server + if (!processingData) processDataFromDatabase(); + } + + let stringifiedJson = JSON.stringify(data.data); + client.publish("v1/gateway/telemetry", stringifiedJson, { qos: 1 }); + + //backup telemetry + if (createTelemetryBackup) { + data.data.id = UID(); + nosqlBackup.insert(data.data); + + insertBackupNoSqlCounter++; + if (insertBackupNoSqlCounter > 150) { + let options = { compress: true }; + let path = __dirname + "/../databases/backup/tbdata.nosql"; + var stream = new rollers.RollingFileStream(path, noSqlFileSizeLimit, 150, options); + stream.write(""); + stream.end(); + + insertBackupNoSqlCounter = 0; + } + } + + } + 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 (saveTelemetryOnError) { + //create new file from tbdata.nosql, if file size exceeds given limit, and clear tbdata.nosql + makeBackupFromDbFile(); + + //write to tb + data.data.id = UID(); + nosql.insert(data.data); + } + } + }); + + + instance.close = function(done) { + if (clientReady) { + client.end(); + clearInterval(sendWsStatusVar); + } + }; + + + function getDbBackupFileCounter(type) { + var files = fs.readdirSync(__dirname + "/../databases"); + + let counter = 0; + for (var i = 0; i < files.length; i++) { + + if (files[i] == "tbdata.nosql") continue; + + if (files[i].endsWith(".nosql")) { + + let pos = files[i].indexOf("."); + if (pos > -1) { + + let fileCounter = counter; + let firstDigit = files[i].slice(0, pos); + + fileCounter = parseInt(firstDigit); + if (isNaN(fileCounter)) fileCounter = 0; + //console.log("getDbBackupFileCounter digit:", files[i], firstDigit, fileCounter, isNaN(fileCounter), type); + + if (type == "max") { + if (fileCounter > counter) { + counter = fileCounter; + } + } + else if (type == "min") { + if (counter == 0) counter = fileCounter; + + if (fileCounter < counter) { + counter = fileCounter; + } + } + } + } + + } + + if (type == "max") counter++; + + return counter; + } + + const makeBackupFromDbFile = async () => { + + if (!saveTelemetryOnError) return; + + //to avoid large file: tbdata.nosql + + //init value is 0! + if (insertNoSqlCounter > 0) { + --insertNoSqlCounter; + return; + } + + insertNoSqlCounter = 100; + + let source = __dirname + "/../databases/tbdata.nosql"; + + var stats = fs.statSync(source); + var fileSizeInBytes = stats.size; + + if (fileSizeInBytes > noSqlFileSizeLimit) { + + let counter = 1; + counter = getDbBackupFileCounter("max"); + + let destination = __dirname + "/../databases/" + counter + "." + "tbdata.nosql"; + + //make backup file + fs.copyFileSync(source, destination); + //fs.renameSync(p, p + "." + counter); + + //clear tbdata.nosql + fs.writeFileSync(source, ""); + fs.truncateSync(source, 0); + + } + } + + const processDataFromDatabase = async () => { + + if (restore_from_backup <= 0) return; + + //calculate diff + const now = new Date(); + let currentTime = now.getTime(); + let diff = currentTime - lastRestoreTime; + + if ((diff / 1000) < restore_backup_wait) { + //console.log("*********restore_backup_wait", diff, restore_backup_wait); + return; + } + + processingData = true; + + //get filename to process + let counter = getDbBackupFileCounter("min"); + + //we have some backup files + let dataBase = 'tbdata'; + + var nosql; + if (counter == 0) dataBase = 'tbdata'; + else dataBase = counter + "." + 'tbdata'; + + nosql = NOSQL(dataBase); + + //select all data - use limit restore_from_backup + let records = await promisifyBuilder(nosql.find().take(restore_from_backup)); + + for (let i = 0; i < records.length; i++) { + if (clientReady) { + + let item = records[i]; + let id = item.id; + + if (id !== undefined) { + //console.log("------------processDataFromDatabase - remove", id, dataBase, i); + + try { + + let message = JSON.parse(JSON.stringify(item)); + delete message.id; + + client.publish("v1/gateway/telemetry", JSON.stringify(message), { qos: 1 }); + + //remove from database + await promisifyBuilder(nosql.remove().where("id", id)); + + } catch (error) { + //process error + console.log("processDataFromDatabase", error); + } + + } + + } + else { + processingData = false; + return; + } + } + + if (records.length > 0) { + //clean backup file + if (counter > 0) nosql.clean(); + } + + //no data in db, remove + if (records.length == 0) { + if (counter > 0) nosql.drop(); + } + + const d = new Date(); + lastRestoreTime = d.getTime(); + + processingData = false; + + } + + instance.on('options', main); + //instance.reconfigure(); +}; diff --git a/RVO4/monitor.txt b/RVO4/monitor.txt new file mode 100755 index 0000000..77fbcc0 --- /dev/null +++ b/RVO4/monitor.txt @@ -0,0 +1,306 @@ +[2025-10-09T16:53:32.353] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-09T16:53:37.697] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-09T16:53:37.702] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-09T16:53:37.703] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-09T16:53:37.704] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-09T16:53:37.708] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T16:53:37.709] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-10-10T05:32:00.709Z +[2025-10-09T16:53:37.711] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-10-09T16:45:00.710Z +[2025-10-09T16:53:37.711] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T16:53:37.713] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-10-09T16:53:37.714] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-09T16:53:37.714] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-09T16:53:37.717] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T16:53:37.717] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-10-10T05:32:00.717Z +[2025-10-09T16:53:37.718] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-10-09T16:45:00.718Z +[2025-10-09T16:53:37.719] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T16:53:37.720] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-10-09T16:53:37.721] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-09T16:53:37.722] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-09T16:53:37.724] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T16:53:37.725] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-10-10T05:32:00.724Z +[2025-10-09T16:53:37.725] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-10-09T16:45:00.725Z +[2025-10-09T16:53:37.726] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T16:53:37.727] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-10-09T16:53:37.728] [INFO] monitorLogs - tasks created: 14 +[2025-10-09T16:53:37.730] [INFO] monitorLogs - -->FLOW bol spustený d5xjWYMwEJon6rLlK7yE9Q7qgV4DaOeNB9ZX3Gzb 2025-08-08 +[2025-10-09T16:53:42.735] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-09T18:26:08.007] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-09T18:26:08.010] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-09T18:26:08.012] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-09T19:06:04.709] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-09T19:06:10.047] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-09T19:06:10.052] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-09T19:06:10.053] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-09T19:06:10.054] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-09T19:06:10.058] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T19:06:10.059] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-10-10T05:32:00.059Z +[2025-10-09T19:06:10.061] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-10-10T16:45:00.061Z +[2025-10-09T19:06:10.062] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T19:06:10.063] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-10-09T19:06:10.064] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-09T19:06:10.064] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-09T19:06:10.067] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T19:06:10.067] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-10-10T05:32:00.067Z +[2025-10-09T19:06:10.068] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-10-10T16:45:00.068Z +[2025-10-09T19:06:10.069] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T19:06:10.070] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-10-09T19:06:10.071] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-09T19:06:10.071] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-09T19:06:10.073] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T19:06:10.074] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-10-10T05:32:00.074Z +[2025-10-09T19:06:10.075] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-10-10T16:45:00.075Z +[2025-10-09T19:06:10.075] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T19:06:10.077] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-10-09T19:06:10.078] [INFO] monitorLogs - tasks created: 14 +[2025-10-09T19:06:10.080] [INFO] monitorLogs - -->FLOW bol spustený d5xjWYMwEJon6rLlK7yE9Q7qgV4DaOeNB9ZX3Gzb 2025-08-08 +[2025-10-09T19:06:15.085] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-10T03:06:11.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-10 03:06:11 +[2025-10-10T06:53:17.130] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-10T06:53:17.134] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-10T06:53:17.137] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-10T18:23:38.783] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-10T18:23:38.786] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-10T18:23:38.788] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-11T03:06:11.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-11 03:06:11 +[2025-10-11T06:54:14.476] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-11T06:54:14.486] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-11T06:54:14.488] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-11T18:25:43.433] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-11T18:25:43.436] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-11T18:25:43.437] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-12T03:06:12.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-12 03:06:12 +[2025-10-12T06:52:16.165] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-12T06:52:16.167] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-12T06:52:16.169] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-12T18:23:16.100] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-12T18:23:16.102] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-12T18:23:16.104] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-13T03:06:13.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-13 03:06:13 +[2025-10-13T06:48:27.426] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-13T06:48:27.428] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-13T06:48:27.430] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-13T18:24:44.775] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-13T18:24:44.777] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-13T18:24:44.778] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-14T03:06:14.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-14 03:06:14 +[2025-10-14T06:50:19.261] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-14T06:50:19.263] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-14T06:50:19.265] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-14T18:20:51.002] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-14T18:20:51.008] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-14T18:20:51.010] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-15T03:06:14.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-15 03:06:14 +[2025-10-15T06:57:38.574] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-15T06:57:38.576] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-15T06:57:38.578] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-15T11:52:48.434] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-15T11:52:53.773] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-15T11:52:53.778] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-15T11:52:53.779] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-15T11:52:53.780] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-15T11:52:53.784] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-15T11:52:53.786] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-10-16T05:41:00.785Z +[2025-10-15T11:52:53.787] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-10-15T16:33:00.787Z +[2025-10-15T11:52:53.788] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:41', name: 'luxOff' }, + { value: 1, start_time: '18:33', name: 'luxOn' } +] +[2025-10-15T11:52:53.789] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-10-15T11:52:53.790] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-15T11:52:53.791] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-15T11:52:53.793] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-15T11:52:53.794] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-10-16T05:41:00.793Z +[2025-10-15T11:52:53.795] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-10-15T16:33:00.794Z +[2025-10-15T11:52:53.795] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:41', name: 'luxOff' }, + { value: 1, start_time: '18:33', name: 'luxOn' } +] +[2025-10-15T11:52:53.796] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-10-15T11:52:53.797] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-15T11:52:53.797] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-15T11:52:53.800] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-15T11:52:53.800] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-10-16T05:41:00.800Z +[2025-10-15T11:52:53.801] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-10-15T16:33:00.801Z +[2025-10-15T11:52:53.802] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:41', name: 'luxOff' }, + { value: 1, start_time: '18:33', name: 'luxOn' } +] +[2025-10-15T11:52:53.803] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-10-15T11:52:53.804] [INFO] monitorLogs - tasks created: 14 +[2025-10-15T11:52:53.806] [INFO] monitorLogs - -->FLOW bol spustený d5xjWYMwEJon6rLlK7yE9Q7qgV4DaOeNB9ZX3Gzb 2025-10-08 +[2025-10-15T11:52:58.810] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-15T18:17:59.312] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-15T18:17:59.318] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-15T18:17:59.321] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor diff --git a/RVO4/package-lock.json b/RVO4/package-lock.json new file mode 100755 index 0000000..3c5c1ba --- /dev/null +++ b/RVO4/package-lock.json @@ -0,0 +1,2139 @@ +{ + "name": "emptyproject", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "emptyproject", + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "bitwise": "^2.1.0", + "easy-crc": "0.0.2", + "jsmodbus": "^4.0.6", + "log4js": "^6.3.0", + "moment": "^2.30.1", + "mqtt": "^4.2.6", + "nodemailer": "^6.9.7", + "serialport": "^9.2.8", + "total.js": "^3.4.13" + } + }, + "node_modules/@serialport/binding-abstract": { + "version": "9.2.3", + "resolved": "https://registry.npmjs.org/@serialport/binding-abstract/-/binding-abstract-9.2.3.tgz", + "integrity": "sha512-cQs9tbIlG3P0IrOWyVirqlhWuJ7Ms2Zh9m2108z6Y5UW/iVj6wEOiW8EmK9QX9jmJXYllE7wgGgvVozP5oCj3w==", + "dependencies": { + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/binding-mock": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/binding-mock/-/binding-mock-9.2.4.tgz", + "integrity": "sha512-dpEhACCs44oQhh6ajJfJdvQdK38Vq0N4W6iD/gdplglDCK7qXRQCMUjJIeKdS/HSEiWkC3bwumUhUufdsOyT4g==", + "dependencies": { + "@serialport/binding-abstract": "9.2.3", + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/bindings": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/@serialport/bindings/-/bindings-9.2.8.tgz", + "integrity": "sha512-hSLxTe0tADZ3LMMGwvEJWOC/TaFQTyPeFalUCsJ1lSQ0k6bPF04JwrtB/C81GetmDBTNRY0GlD0SNtKCc7Dr5g==", + "hasInstallScript": true, + "dependencies": { + "@serialport/binding-abstract": "9.2.3", + "@serialport/parser-readline": "9.2.4", + "bindings": "^1.5.0", + "debug": "^4.3.2", + "nan": "^2.15.0", + "prebuild-install": "^7.0.0" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-byte-length": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-byte-length/-/parser-byte-length-9.2.4.tgz", + "integrity": "sha512-sQD/iw4ZMU3xW9PLi0/GlvU6Y623jGeWecbMkO7izUo/6P7gtfv1c9ikd5h0kwL8AoAOpQA1lxdHIKox+umBUg==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-cctalk": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-cctalk/-/parser-cctalk-9.2.4.tgz", + "integrity": "sha512-T4TU5vQMwmo9AB3gQLFDWbfJXlW5jd9guEsB/nqKjFHTv0FXPdZ7DQ2TpSp8RnHWxU3GX6kYTaDO20BKzc8GPQ==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-delimiter": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-delimiter/-/parser-delimiter-9.2.4.tgz", + "integrity": "sha512-4nvTAoYAgkxFiXrkI+3CA49Yd43CODjeszh89EK+I9c8wOZ+etZduRCzINYPiy26g7zO+GRAb9FoPCsY+sYcbQ==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-inter-byte-timeout": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-inter-byte-timeout/-/parser-inter-byte-timeout-9.2.4.tgz", + "integrity": "sha512-SOAdvr0oBQIOCXX198hiTlxs4JTKg9j5piapw5tNq52fwDOWdbYrFneT/wN04UTMKaDrJuEvXq6T4rv4j7nJ5A==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-readline": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-readline/-/parser-readline-9.2.4.tgz", + "integrity": "sha512-Z1/qrZTQUVhNSJP1hd9YfDvq0o7d87rNwAjjRKbVpa7Qi51tG5BnKt43IV3NFMyBlVcRe0rnIb3tJu57E0SOwg==", + "dependencies": { + "@serialport/parser-delimiter": "9.2.4" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-ready": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-ready/-/parser-ready-9.2.4.tgz", + "integrity": "sha512-Pyi94Itjl6qAURwIZr/gmZpMAyTmKXThm6vL5DoAWGQjcRHWB0gwv2TY2v7N+mQLJYUKU3cMnvnATXxHm7xjxw==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-regex": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-regex/-/parser-regex-9.2.4.tgz", + "integrity": "sha512-sI/cVvPOYz+Dbv4ZdnW16qAwvXiFf/1pGASQdbveRTlgJDdz7sRNlCBifzfTN2xljwvCTZYqiudKvDdC1TepRQ==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/stream": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/stream/-/stream-9.2.4.tgz", + "integrity": "sha512-bLye8Ub4vUFQGmkh8qEqehr7SE7EJs2yDs0h9jzuL5oKi+F34CFmWkEErO8GAOQ8YNn7p6b3GxUgs+0BrHHDZQ==", + "dependencies": { + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "node_modules/are-we-there-yet": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", + "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/base64-js": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", + "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==" + }, + "node_modules/bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "dependencies": { + "file-uri-to-path": "1.0.0" + } + }, + "node_modules/bitwise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/bitwise/-/bitwise-2.1.0.tgz", + "integrity": "sha512-XKgAhMXCh4H/3oNwAHAsAO0iC89s9cOiumgYwSHjSobGWxYjv62YhkL9QEdvGP151xypCtMlAfKK79GEcd2eRQ==" + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/bl/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/buffer": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz", + "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==", + "dependencies": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + }, + "node_modules/buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" + }, + "node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, + "node_modules/code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/commist": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/commist/-/commist-1.1.0.tgz", + "integrity": "sha512-rraC8NXWOEjhADbZe9QBNzLAN5Q3fsTPQtBV+fEVj6xKIgDgNiEVE6ZNfHpZOqfQ21YUzfVNUXLOEZquYvQPPg==", + "dependencies": { + "leven": "^2.1.0", + "minimist": "^1.1.0" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "node_modules/concat-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", + "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", + "engines": [ + "node >= 6.0" + ], + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.0.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/concat-stream/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" + }, + "node_modules/core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "node_modules/crc": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/crc/-/crc-3.4.0.tgz", + "integrity": "sha512-ycVC2+4/DLgXXq7QweYi2znhqDuZz6P5TQXnkQo8v15XY/5p/IWeZwsSE31Ifo8w15b8TWLsqhXOjXyilHuQxw==" + }, + "node_modules/date-format": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.11.tgz", + "integrity": "sha512-VS20KRyorrbMCQmpdl2hg5KaOUsda1RbnsJg461FfrcyCUg+pkd0b40BSW4niQyTheww4DBXQnS7HwSrKkipLw==", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" + }, + "node_modules/detect-libc": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz", + "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==", + "engines": { + "node": ">=8" + } + }, + "node_modules/duplexify": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.2.tgz", + "integrity": "sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw==", + "dependencies": { + "end-of-stream": "^1.4.1", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1", + "stream-shift": "^1.0.0" + } + }, + "node_modules/duplexify/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/easy-crc": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/easy-crc/-/easy-crc-0.0.2.tgz", + "integrity": "sha512-h6eqIdhJRe0p271/xZJbM/0klCi13mW5IB7ZEzEGH11yV4QXWAkD4yPErz0fXdhFrd6sZ4Q1k5Iky2kMsMNePw==" + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" + }, + "node_modules/flatted": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", + "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==" + }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, + "node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "node_modules/gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha512-14x4kjc6lkD3ltw589k0NrPD6cCNTD6CWoVUNpB85+DrtONoZn+Rug6xZU5RvSC4+TZPxA5AnBibQYAvZn41Hg==", + "dependencies": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "node_modules/github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==" + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" + }, + "node_modules/has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" + }, + "node_modules/help-me": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/help-me/-/help-me-3.0.0.tgz", + "integrity": "sha512-hx73jClhyk910sidBB7ERlnhMlFsJJIBqSVMFDwPN8o2v9nmp5KgLq1Xz1Bf1fCMMZ6mPrX159iG0VLy/fPMtQ==", + "dependencies": { + "glob": "^7.1.6", + "readable-stream": "^3.6.0" + } + }, + "node_modules/help-me/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, + "node_modules/is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==", + "dependencies": { + "number-is-nan": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "node_modules/js-sdsl": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz", + "integrity": "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/js-sdsl" + } + }, + "node_modules/jsmodbus": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/jsmodbus/-/jsmodbus-4.0.6.tgz", + "integrity": "sha512-gCmjoaERErK5Rn9Lu/BN07fY13MoWV7JKgGzrnkPlQPdPxYcwDhLtYcmpFFpZ4J9NPZZBSezi1UkLZO/DnNppA==", + "dependencies": { + "crc": "3.4.0", + "debug": "^3.1.0" + }, + "bin": { + "jsmodbus": "bin/jsmodbus.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/jsmodbus/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/leven": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", + "integrity": "sha1-wuep93IJTe6dNCAq6KzORoeHVYA=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/log4js": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.5.2.tgz", + "integrity": "sha512-DXtpNtt+KDOMT7RHUDIur/WsSA3rntlUh9Zg4XCdV42wUuMmbFkl38+LZ92Z5QvQA7mD5kAVkLiBSEH/tvUB8A==", + "dependencies": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "flatted": "^3.2.5", + "rfdc": "^1.3.0", + "streamroller": "^3.1.1" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" + }, + "node_modules/moment": { + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", + "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==", + "engines": { + "node": "*" + } + }, + "node_modules/mqtt": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/mqtt/-/mqtt-4.3.7.tgz", + "integrity": "sha512-ew3qwG/TJRorTz47eW46vZ5oBw5MEYbQZVaEji44j5lAUSQSqIEoul7Kua/BatBW0H0kKQcC9kwUHa1qzaWHSw==", + "dependencies": { + "commist": "^1.0.0", + "concat-stream": "^2.0.0", + "debug": "^4.1.1", + "duplexify": "^4.1.1", + "help-me": "^3.0.0", + "inherits": "^2.0.3", + "lru-cache": "^6.0.0", + "minimist": "^1.2.5", + "mqtt-packet": "^6.8.0", + "number-allocator": "^1.0.9", + "pump": "^3.0.0", + "readable-stream": "^3.6.0", + "reinterval": "^1.1.0", + "rfdc": "^1.3.0", + "split2": "^3.1.0", + "ws": "^7.5.5", + "xtend": "^4.0.2" + }, + "bin": { + "mqtt": "bin/mqtt.js", + "mqtt_pub": "bin/pub.js", + "mqtt_sub": "bin/sub.js" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/mqtt-packet": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/mqtt-packet/-/mqtt-packet-6.10.0.tgz", + "integrity": "sha512-ja8+mFKIHdB1Tpl6vac+sktqy3gA8t9Mduom1BA75cI+R9AHnZOiaBQwpGiWnaVJLDGRdNhQmFaAqd7tkKSMGA==", + "dependencies": { + "bl": "^4.0.2", + "debug": "^4.1.1", + "process-nextick-args": "^2.0.1" + } + }, + "node_modules/mqtt/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/nan": { + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.16.0.tgz", + "integrity": "sha512-UdAqHyFngu7TfQKsCBgAA6pWDkT8MAO7d0jyOecVhN5354xbLqdn8mV9Tat9gepAupm0bt2DbeaSC8vS52MuFA==" + }, + "node_modules/napi-build-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", + "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==" + }, + "node_modules/node-abi": { + "version": "3.22.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.22.0.tgz", + "integrity": "sha512-u4uAs/4Zzmp/jjsD9cyFYDXeISfUWaAVWshPmDZOFOv4Xl4SbzTXm53I04C2uRueYJ+0t5PEtLH/owbn2Npf/w==", + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/nodemailer": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.7.tgz", + "integrity": "sha512-rUtR77ksqex/eZRLmQ21LKVH5nAAsVicAtAYudK7JgwenEDZ0UIQ1adUGqErz7sMkWYxWTTU1aeP2Jga6WQyJw==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "dependencies": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "node_modules/number-allocator": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/number-allocator/-/number-allocator-1.0.14.tgz", + "integrity": "sha512-OrL44UTVAvkKdOdRQZIJpLkAdjXGTRda052sN4sO77bKEzYYqWKMBjQvrJFzqygI99gL6Z4u2xctPW1tB8ErvA==", + "dependencies": { + "debug": "^4.3.1", + "js-sdsl": "4.3.0" + } + }, + "node_modules/number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/prebuild-install": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.0.tgz", + "integrity": "sha512-CNcMgI1xBypOyGqjp3wOc8AAo1nMhZS3Cwd3iHIxOdAUbb+YxdNuM4Z5iIrZ8RLvOsf3F3bl7b7xGq6DjQoNYA==", + "dependencies": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^1.0.1", + "node-abi": "^3.3.0", + "npmlog": "^4.0.1", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + }, + "bin": { + "prebuild-install": "bin.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/reinterval": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reinterval/-/reinterval-1.1.0.tgz", + "integrity": "sha1-M2Hs+jymwYKDOA3Qu5VG85D17Oc=" + }, + "node_modules/rfdc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==" + }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/serialport": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/serialport/-/serialport-9.2.8.tgz", + "integrity": "sha512-FsWpMQgSJxi93JgWl5xM1f9/Z8IjRJuaUEoHqLf8FPBLw7gMhInuHOBhI2onQufWIYPGTz3H3oGcu1nCaK1EfA==", + "dependencies": { + "@serialport/binding-mock": "9.2.4", + "@serialport/bindings": "9.2.8", + "@serialport/parser-byte-length": "9.2.4", + "@serialport/parser-cctalk": "9.2.4", + "@serialport/parser-delimiter": "9.2.4", + "@serialport/parser-inter-byte-timeout": "9.2.4", + "@serialport/parser-readline": "9.2.4", + "@serialport/parser-ready": "9.2.4", + "@serialport/parser-regex": "9.2.4", + "@serialport/stream": "9.2.4", + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "node_modules/split2": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", + "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", + "dependencies": { + "readable-stream": "^3.0.0" + } + }, + "node_modules/split2/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==" + }, + "node_modules/streamroller": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.1.1.tgz", + "integrity": "sha512-iPhtd9unZ6zKdWgMeYGfSBuqCngyJy1B/GPi/lTpwGpa3bajuX30GjUVd0/Tn/Xhg0mr4DOSENozz9Y06qyonQ==", + "dependencies": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "fs-extra": "^10.1.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dependencies": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/tar-fs": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "dependencies": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tar-stream/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/total.js": { + "version": "3.4.13", + "resolved": "https://registry.npmjs.org/total.js/-/total.js-3.4.13.tgz", + "integrity": "sha512-lAH4gEixlPFbrE3xfKADAcHfO79IFq2wKa9GTsrgRzIR5MTg3mNH7+4IxvX1pK8faoYb/0oYSJ1YTsAa5hIFFQ==", + "bin": { + "total": "bin/totaljs", + "total.js": "bin/totaljs", + "totaljs": "bin/totaljs", + "totalpackage": "bin/tpm", + "tpm": "bin/tpm" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, + "node_modules/universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "node_modules/wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "node_modules/ws": { + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } + }, + "dependencies": { + "@serialport/binding-abstract": { + "version": "9.2.3", + "resolved": "https://registry.npmjs.org/@serialport/binding-abstract/-/binding-abstract-9.2.3.tgz", + "integrity": "sha512-cQs9tbIlG3P0IrOWyVirqlhWuJ7Ms2Zh9m2108z6Y5UW/iVj6wEOiW8EmK9QX9jmJXYllE7wgGgvVozP5oCj3w==", + "requires": { + "debug": "^4.3.2" + } + }, + "@serialport/binding-mock": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/binding-mock/-/binding-mock-9.2.4.tgz", + "integrity": "sha512-dpEhACCs44oQhh6ajJfJdvQdK38Vq0N4W6iD/gdplglDCK7qXRQCMUjJIeKdS/HSEiWkC3bwumUhUufdsOyT4g==", + "requires": { + "@serialport/binding-abstract": "9.2.3", + "debug": "^4.3.2" + } + }, + "@serialport/bindings": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/@serialport/bindings/-/bindings-9.2.8.tgz", + "integrity": "sha512-hSLxTe0tADZ3LMMGwvEJWOC/TaFQTyPeFalUCsJ1lSQ0k6bPF04JwrtB/C81GetmDBTNRY0GlD0SNtKCc7Dr5g==", + "requires": { + "@serialport/binding-abstract": "9.2.3", + "@serialport/parser-readline": "9.2.4", + "bindings": "^1.5.0", + "debug": "^4.3.2", + "nan": "^2.15.0", + "prebuild-install": "^7.0.0" + } + }, + "@serialport/parser-byte-length": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-byte-length/-/parser-byte-length-9.2.4.tgz", + "integrity": "sha512-sQD/iw4ZMU3xW9PLi0/GlvU6Y623jGeWecbMkO7izUo/6P7gtfv1c9ikd5h0kwL8AoAOpQA1lxdHIKox+umBUg==" + }, + "@serialport/parser-cctalk": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-cctalk/-/parser-cctalk-9.2.4.tgz", + "integrity": "sha512-T4TU5vQMwmo9AB3gQLFDWbfJXlW5jd9guEsB/nqKjFHTv0FXPdZ7DQ2TpSp8RnHWxU3GX6kYTaDO20BKzc8GPQ==" + }, + "@serialport/parser-delimiter": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-delimiter/-/parser-delimiter-9.2.4.tgz", + "integrity": "sha512-4nvTAoYAgkxFiXrkI+3CA49Yd43CODjeszh89EK+I9c8wOZ+etZduRCzINYPiy26g7zO+GRAb9FoPCsY+sYcbQ==" + }, + "@serialport/parser-inter-byte-timeout": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-inter-byte-timeout/-/parser-inter-byte-timeout-9.2.4.tgz", + "integrity": "sha512-SOAdvr0oBQIOCXX198hiTlxs4JTKg9j5piapw5tNq52fwDOWdbYrFneT/wN04UTMKaDrJuEvXq6T4rv4j7nJ5A==" + }, + "@serialport/parser-readline": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-readline/-/parser-readline-9.2.4.tgz", + "integrity": "sha512-Z1/qrZTQUVhNSJP1hd9YfDvq0o7d87rNwAjjRKbVpa7Qi51tG5BnKt43IV3NFMyBlVcRe0rnIb3tJu57E0SOwg==", + "requires": { + "@serialport/parser-delimiter": "9.2.4" + } + }, + "@serialport/parser-ready": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-ready/-/parser-ready-9.2.4.tgz", + "integrity": "sha512-Pyi94Itjl6qAURwIZr/gmZpMAyTmKXThm6vL5DoAWGQjcRHWB0gwv2TY2v7N+mQLJYUKU3cMnvnATXxHm7xjxw==" + }, + "@serialport/parser-regex": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-regex/-/parser-regex-9.2.4.tgz", + "integrity": "sha512-sI/cVvPOYz+Dbv4ZdnW16qAwvXiFf/1pGASQdbveRTlgJDdz7sRNlCBifzfTN2xljwvCTZYqiudKvDdC1TepRQ==" + }, + "@serialport/stream": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/stream/-/stream-9.2.4.tgz", + "integrity": "sha512-bLye8Ub4vUFQGmkh8qEqehr7SE7EJs2yDs0h9jzuL5oKi+F34CFmWkEErO8GAOQ8YNn7p6b3GxUgs+0BrHHDZQ==", + "requires": { + "debug": "^4.3.2" + } + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==" + }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "are-we-there-yet": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", + "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "base64-js": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", + "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==" + }, + "bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "requires": { + "file-uri-to-path": "1.0.0" + } + }, + "bitwise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/bitwise/-/bitwise-2.1.0.tgz", + "integrity": "sha512-XKgAhMXCh4H/3oNwAHAsAO0iC89s9cOiumgYwSHjSobGWxYjv62YhkL9QEdvGP151xypCtMlAfKK79GEcd2eRQ==" + }, + "bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "requires": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "buffer": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz", + "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==", + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" + }, + "chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==" + }, + "commist": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/commist/-/commist-1.1.0.tgz", + "integrity": "sha512-rraC8NXWOEjhADbZe9QBNzLAN5Q3fsTPQtBV+fEVj6xKIgDgNiEVE6ZNfHpZOqfQ21YUzfVNUXLOEZquYvQPPg==", + "requires": { + "leven": "^2.1.0", + "minimist": "^1.1.0" + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "concat-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", + "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.0.2", + "typedarray": "^0.0.6" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "crc": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/crc/-/crc-3.4.0.tgz", + "integrity": "sha512-ycVC2+4/DLgXXq7QweYi2znhqDuZz6P5TQXnkQo8v15XY/5p/IWeZwsSE31Ifo8w15b8TWLsqhXOjXyilHuQxw==" + }, + "date-format": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.11.tgz", + "integrity": "sha512-VS20KRyorrbMCQmpdl2hg5KaOUsda1RbnsJg461FfrcyCUg+pkd0b40BSW4niQyTheww4DBXQnS7HwSrKkipLw==" + }, + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "requires": { + "ms": "2.1.2" + } + }, + "decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "requires": { + "mimic-response": "^3.1.0" + } + }, + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==" + }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" + }, + "detect-libc": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz", + "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==" + }, + "duplexify": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.2.tgz", + "integrity": "sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw==", + "requires": { + "end-of-stream": "^1.4.1", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1", + "stream-shift": "^1.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "easy-crc": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/easy-crc/-/easy-crc-0.0.2.tgz", + "integrity": "sha512-h6eqIdhJRe0p271/xZJbM/0klCi13mW5IB7ZEzEGH11yV4QXWAkD4yPErz0fXdhFrd6sZ4Q1k5Iky2kMsMNePw==" + }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "requires": { + "once": "^1.4.0" + } + }, + "expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==" + }, + "file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" + }, + "flatted": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", + "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==" + }, + "fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, + "fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha512-14x4kjc6lkD3ltw589k0NrPD6cCNTD6CWoVUNpB85+DrtONoZn+Rug6xZU5RvSC4+TZPxA5AnBibQYAvZn41Hg==", + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==" + }, + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" + }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" + }, + "help-me": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/help-me/-/help-me-3.0.0.tgz", + "integrity": "sha512-hx73jClhyk910sidBB7ERlnhMlFsJJIBqSVMFDwPN8o2v9nmp5KgLq1Xz1Bf1fCMMZ6mPrX159iG0VLy/fPMtQ==", + "requires": { + "glob": "^7.1.6", + "readable-stream": "^3.6.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==", + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "js-sdsl": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz", + "integrity": "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==" + }, + "jsmodbus": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/jsmodbus/-/jsmodbus-4.0.6.tgz", + "integrity": "sha512-gCmjoaERErK5Rn9Lu/BN07fY13MoWV7JKgGzrnkPlQPdPxYcwDhLtYcmpFFpZ4J9NPZZBSezi1UkLZO/DnNppA==", + "requires": { + "crc": "3.4.0", + "debug": "^3.1.0" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "requires": { + "ms": "^2.1.1" + } + } + } + }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, + "leven": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", + "integrity": "sha1-wuep93IJTe6dNCAq6KzORoeHVYA=" + }, + "log4js": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.5.2.tgz", + "integrity": "sha512-DXtpNtt+KDOMT7RHUDIur/WsSA3rntlUh9Zg4XCdV42wUuMmbFkl38+LZ92Z5QvQA7mD5kAVkLiBSEH/tvUB8A==", + "requires": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "flatted": "^3.2.5", + "rfdc": "^1.3.0", + "streamroller": "^3.1.1" + } + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "requires": { + "yallist": "^4.0.0" + } + }, + "mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==" + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==" + }, + "mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" + }, + "moment": { + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", + "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==" + }, + "mqtt": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/mqtt/-/mqtt-4.3.7.tgz", + "integrity": "sha512-ew3qwG/TJRorTz47eW46vZ5oBw5MEYbQZVaEji44j5lAUSQSqIEoul7Kua/BatBW0H0kKQcC9kwUHa1qzaWHSw==", + "requires": { + "commist": "^1.0.0", + "concat-stream": "^2.0.0", + "debug": "^4.1.1", + "duplexify": "^4.1.1", + "help-me": "^3.0.0", + "inherits": "^2.0.3", + "lru-cache": "^6.0.0", + "minimist": "^1.2.5", + "mqtt-packet": "^6.8.0", + "number-allocator": "^1.0.9", + "pump": "^3.0.0", + "readable-stream": "^3.6.0", + "reinterval": "^1.1.0", + "rfdc": "^1.3.0", + "split2": "^3.1.0", + "ws": "^7.5.5", + "xtend": "^4.0.2" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "mqtt-packet": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/mqtt-packet/-/mqtt-packet-6.10.0.tgz", + "integrity": "sha512-ja8+mFKIHdB1Tpl6vac+sktqy3gA8t9Mduom1BA75cI+R9AHnZOiaBQwpGiWnaVJLDGRdNhQmFaAqd7tkKSMGA==", + "requires": { + "bl": "^4.0.2", + "debug": "^4.1.1", + "process-nextick-args": "^2.0.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "nan": { + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.16.0.tgz", + "integrity": "sha512-UdAqHyFngu7TfQKsCBgAA6pWDkT8MAO7d0jyOecVhN5354xbLqdn8mV9Tat9gepAupm0bt2DbeaSC8vS52MuFA==" + }, + "napi-build-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", + "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==" + }, + "node-abi": { + "version": "3.22.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.22.0.tgz", + "integrity": "sha512-u4uAs/4Zzmp/jjsD9cyFYDXeISfUWaAVWshPmDZOFOv4Xl4SbzTXm53I04C2uRueYJ+0t5PEtLH/owbn2Npf/w==", + "requires": { + "semver": "^7.3.5" + } + }, + "nodemailer": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.7.tgz", + "integrity": "sha512-rUtR77ksqex/eZRLmQ21LKVH5nAAsVicAtAYudK7JgwenEDZ0UIQ1adUGqErz7sMkWYxWTTU1aeP2Jga6WQyJw==" + }, + "npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "number-allocator": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/number-allocator/-/number-allocator-1.0.14.tgz", + "integrity": "sha512-OrL44UTVAvkKdOdRQZIJpLkAdjXGTRda052sN4sO77bKEzYYqWKMBjQvrJFzqygI99gL6Z4u2xctPW1tB8ErvA==", + "requires": { + "debug": "^4.3.1", + "js-sdsl": "4.3.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==" + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==" + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==" + }, + "prebuild-install": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.0.tgz", + "integrity": "sha512-CNcMgI1xBypOyGqjp3wOc8AAo1nMhZS3Cwd3iHIxOdAUbb+YxdNuM4Z5iIrZ8RLvOsf3F3bl7b7xGq6DjQoNYA==", + "requires": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^1.0.1", + "node-abi": "^3.3.0", + "npmlog": "^4.0.1", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + } + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + } + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "reinterval": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reinterval/-/reinterval-1.1.0.tgz", + "integrity": "sha1-M2Hs+jymwYKDOA3Qu5VG85D17Oc=" + }, + "rfdc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==" + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "requires": { + "lru-cache": "^6.0.0" + } + }, + "serialport": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/serialport/-/serialport-9.2.8.tgz", + "integrity": "sha512-FsWpMQgSJxi93JgWl5xM1f9/Z8IjRJuaUEoHqLf8FPBLw7gMhInuHOBhI2onQufWIYPGTz3H3oGcu1nCaK1EfA==", + "requires": { + "@serialport/binding-mock": "9.2.4", + "@serialport/bindings": "9.2.8", + "@serialport/parser-byte-length": "9.2.4", + "@serialport/parser-cctalk": "9.2.4", + "@serialport/parser-delimiter": "9.2.4", + "@serialport/parser-inter-byte-timeout": "9.2.4", + "@serialport/parser-readline": "9.2.4", + "@serialport/parser-ready": "9.2.4", + "@serialport/parser-regex": "9.2.4", + "@serialport/stream": "9.2.4", + "debug": "^4.3.2" + } + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==" + }, + "simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "requires": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "split2": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", + "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", + "requires": { + "readable-stream": "^3.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==" + }, + "streamroller": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.1.1.tgz", + "integrity": "sha512-iPhtd9unZ6zKdWgMeYGfSBuqCngyJy1B/GPi/lTpwGpa3bajuX30GjUVd0/Tn/Xhg0mr4DOSENozz9Y06qyonQ==", + "requires": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "fs-extra": "^10.1.0" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" + }, + "tar-fs": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "requires": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "requires": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "total.js": { + "version": "3.4.13", + "resolved": "https://registry.npmjs.org/total.js/-/total.js-3.4.13.tgz", + "integrity": "sha512-lAH4gEixlPFbrE3xfKADAcHfO79IFq2wKa9GTsrgRzIR5MTg3mNH7+4IxvX1pK8faoYb/0oYSJ1YTsAa5hIFFQ==" + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, + "universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==" + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "requires": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "ws": { + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "requires": {} + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } + } +} diff --git a/RVO4/package.json b/RVO4/package.json new file mode 100755 index 0000000..7f7c795 --- /dev/null +++ b/RVO4/package.json @@ -0,0 +1,30 @@ +{ + "name": "emptyproject", + "description": "Total.js empty project.", + "version": "1.0.0", + "main": "debug.js", + "dependencies": { + "bitwise": "^2.1.0", + "easy-crc": "0.0.2", + "jsmodbus": "^4.0.6", + "log4js": "^6.3.0", + "moment": "^2.30.1", + "mqtt": "^4.2.6", + "nodemailer": "^6.9.7", + "serialport": "^9.2.8", + "total.js": "^3.4.13" + }, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "https://github.com/totaljs/emptyproject-flow" + }, + "keywords": [ + "empty", + "project" + ], + "author": "Peter Širka", + "license": "MIT" +} diff --git a/RVO4/release.js b/RVO4/release.js new file mode 100755 index 0000000..02d52ff --- /dev/null +++ b/RVO4/release.js @@ -0,0 +1,15 @@ +// =================================================== +// FOR PRODUCTION +// Total.js - framework for Node.js platform +// https://www.totaljs.com +// =================================================== + +const options = {'ip':'0.0.0.0', 'port':12345}; + +// options.ip = '127.0.0.1'; +// options.port = parseInt(process.argv[2]); +// options.config = { name: 'Total.js' }; +// options.sleep = 3000; + +require('total.js').http('release', options); +// require('total.js').cluster.http(5, 'release', options); diff --git a/RVO4/release.js.json b/RVO4/release.js.json new file mode 100755 index 0000000..aab492d --- /dev/null +++ b/RVO4/release.js.json @@ -0,0 +1,34 @@ +{ + "pid": 395, + "stats": [ + { + "id": null, + "version": { + "node": "v14.18.1", + "total": "3.4.13", + "app": "1.0.0" + }, + "pid": 395, + "thread": "", + "mode": "release", + "overload": 0, + "date": "2025-10-16T00:22:44.451Z", + "memory": 24.77, + "rm": 0, + "fm": 0, + "wm": 0, + "mm": 0, + "om": 0, + "em": 0, + "dbrm": 0, + "dbwm": 0, + "usage": 0, + "requests": 7, + "pending": 0, + "errors": 0, + "timeouts": 0, + "uptime": 871, + "online": 0 + } + ] +} \ No newline at end of file diff --git a/RVO4/report_data.log b/RVO4/report_data.log new file mode 100755 index 0000000..99ed5b1 --- /dev/null +++ b/RVO4/report_data.log @@ -0,0 +1,196 @@ +{ + "name": "rvo_senica_4_10.0.0.136", + "time": "2025-10-15T10:52:59.420Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_4_10.0.0.136", + "time": "2025-10-15T11:52:59.415Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_4_10.0.0.136", + "time": "2025-10-15T12:52:59.415Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_4_10.0.0.136", + "time": "2025-10-15T13:52:59.416Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_4_10.0.0.136", + "time": "2025-10-15T14:52:59.415Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_4_10.0.0.136", + "time": "2025-10-15T15:52:59.416Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_4_10.0.0.136", + "time": "2025-10-15T17:33:01.420Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_4_10.0.0.136", + "time": "2025-10-15T18:33:01.420Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_4_10.0.0.136", + "time": "2025-10-15T19:33:01.421Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_4_10.0.0.136", + "time": "2025-10-15T20:33:01.422Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_4_10.0.0.136", + "time": "2025-10-15T21:33:01.422Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_4_10.0.0.136", + "time": "2025-10-15T22:33:01.423Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_4_10.0.0.136", + "time": "2025-10-15T23:33:01.423Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +} \ No newline at end of file From 3e545e29ff9155b0788193f83589aec86eaefe99 Mon Sep 17 00:00:00 2001 From: Jakub Klena Date: Thu, 16 Oct 2025 02:23:32 +0200 Subject: [PATCH 04/30] Backup senica-RVO7 on 16.10.2025 --- RVO7/addSwitch.py | 36 + RVO7/cloud_topic.py | 76 + RVO7/config | 12 + RVO7/createNode.py | 43 + RVO7/databases/accelerometer_db.js | 3055 +++++++++++++++ RVO7/databases/modbus_config.js | 114 + RVO7/databases/nodes.table | 20 + .../nodes_original/nodes_original.table | 1 + RVO7/databases/notifications.table | 41 + RVO7/databases/pins.table | 14 + RVO7/databases/relays.table | 5 + RVO7/databases/settings.table | 2 + RVO7/databases/tbdata.nosql | 6 + RVO7/databases/tbdatacloud.nosql | 3 + RVO7/databases/total_energy.js | 38 + RVO7/debug.js | 16 + RVO7/err.txt | 53 + RVO7/flow/cloudmqttconnect.js | 357 ++ RVO7/flow/cmd_manager.js | 3071 +++++++++++++++ RVO7/flow/code.js | 90 + RVO7/flow/comment.js | 11 + RVO7/flow/count.js | 60 + RVO7/flow/db_connector.js | 286 ++ RVO7/flow/db_init.js | 113 + RVO7/flow/debug.js | 100 + RVO7/flow/designer.json | 3102 +++++++++++++++ RVO7/flow/dido_controller.js | 1486 ++++++++ RVO7/flow/helper/DataToTbHandler.js | 187 + RVO7/flow/helper/ErrorToServiceHandler.js | 91 + RVO7/flow/helper/db_helper.js | 44 + RVO7/flow/helper/logger.js | 30 + RVO7/flow/helper/md5.js | 5 + RVO7/flow/helper/notification_reporter.js | 121 + RVO7/flow/helper/register.js | 144 + RVO7/flow/helper/serialport_helper.js | 99 + RVO7/flow/helper/suncalc.js | 317 ++ RVO7/flow/helper/utils.js | 161 + RVO7/flow/httprequest.js | 137 + RVO7/flow/httpresponse.js | 76 + RVO7/flow/httproute.js | 326 ++ RVO7/flow/infosender.js | 81 + RVO7/flow/modbus_reader.js | 346 ++ RVO7/flow/monitorconsumption.js | 156 + RVO7/flow/monitordisk.js | 96 + RVO7/flow/monitormemory.js | 87 + RVO7/flow/nodesdb_changecheck.js | 77 + RVO7/flow/show_dbdata.js | 243 ++ RVO7/flow/slack_filter.js | 188 + RVO7/flow/thermometer.js | 99 + RVO7/flow/trigger.js | 79 + RVO7/flow/variables.txt | 0 RVO7/flow/virtualwirein.js | 43 + RVO7/flow/virtualwireout.js | 41 + RVO7/flow/wsmqttpublish.js | 448 +++ RVO7/monitor.txt | 3390 +++++++++++++++++ RVO7/package-lock.json | 2139 +++++++++++ RVO7/package.json | 30 + RVO7/release.js | 15 + RVO7/release.js.json | 34 + RVO7/report_data.log | 151 + 60 files changed, 21692 insertions(+) create mode 100755 RVO7/addSwitch.py create mode 100755 RVO7/cloud_topic.py create mode 100755 RVO7/config create mode 100755 RVO7/createNode.py create mode 100755 RVO7/databases/accelerometer_db.js create mode 100755 RVO7/databases/modbus_config.js create mode 100755 RVO7/databases/nodes.table create mode 100755 RVO7/databases/nodes_original/nodes_original.table create mode 100755 RVO7/databases/notifications.table create mode 100755 RVO7/databases/pins.table create mode 100755 RVO7/databases/relays.table create mode 100755 RVO7/databases/settings.table create mode 100755 RVO7/databases/tbdata.nosql create mode 100755 RVO7/databases/tbdatacloud.nosql create mode 100755 RVO7/databases/total_energy.js create mode 100755 RVO7/debug.js create mode 100755 RVO7/err.txt create mode 100755 RVO7/flow/cloudmqttconnect.js create mode 100755 RVO7/flow/cmd_manager.js create mode 100755 RVO7/flow/code.js create mode 100755 RVO7/flow/comment.js create mode 100755 RVO7/flow/count.js create mode 100755 RVO7/flow/db_connector.js create mode 100755 RVO7/flow/db_init.js create mode 100755 RVO7/flow/debug.js create mode 100755 RVO7/flow/designer.json create mode 100755 RVO7/flow/dido_controller.js create mode 100755 RVO7/flow/helper/DataToTbHandler.js create mode 100755 RVO7/flow/helper/ErrorToServiceHandler.js create mode 100755 RVO7/flow/helper/db_helper.js create mode 100755 RVO7/flow/helper/logger.js create mode 100755 RVO7/flow/helper/md5.js create mode 100755 RVO7/flow/helper/notification_reporter.js create mode 100755 RVO7/flow/helper/register.js create mode 100755 RVO7/flow/helper/serialport_helper.js create mode 100755 RVO7/flow/helper/suncalc.js create mode 100755 RVO7/flow/helper/utils.js create mode 100755 RVO7/flow/httprequest.js create mode 100755 RVO7/flow/httpresponse.js create mode 100755 RVO7/flow/httproute.js create mode 100755 RVO7/flow/infosender.js create mode 100755 RVO7/flow/modbus_reader.js create mode 100755 RVO7/flow/monitorconsumption.js create mode 100755 RVO7/flow/monitordisk.js create mode 100755 RVO7/flow/monitormemory.js create mode 100755 RVO7/flow/nodesdb_changecheck.js create mode 100755 RVO7/flow/show_dbdata.js create mode 100755 RVO7/flow/slack_filter.js create mode 100755 RVO7/flow/thermometer.js create mode 100755 RVO7/flow/trigger.js create mode 100755 RVO7/flow/variables.txt create mode 100755 RVO7/flow/virtualwirein.js create mode 100755 RVO7/flow/virtualwireout.js create mode 100755 RVO7/flow/wsmqttpublish.js create mode 100755 RVO7/monitor.txt create mode 100755 RVO7/package-lock.json create mode 100755 RVO7/package.json create mode 100755 RVO7/release.js create mode 100755 RVO7/release.js.json create mode 100755 RVO7/report_data.log diff --git a/RVO7/addSwitch.py b/RVO7/addSwitch.py new file mode 100755 index 0000000..c35e96b --- /dev/null +++ b/RVO7/addSwitch.py @@ -0,0 +1,36 @@ +import os + +def process_set_file(): + """ + Checks if /root/flowserver exists, reads set.txt, and modifies the second line. + """ + default_folder = "/root/flowserver" if os.path.exists("/root/flowserver") else "/home/unipi/flowserver" + flag = 1 if default_folder == "/root/flowserver" else 0 + + try: + with open("/home/unipi/flowserver/databases/settings.table", "r") as f: + lines = f.readlines() + + if len(lines) >= 2: + lines[0] = lines[0].rstrip('\n') + "|main_switch:boolean\n" + second_line = lines[1].strip() # remove trailing newline + last_pipe_index = second_line.rfind("|") + + if last_pipe_index != -1: + modified_line = second_line[:last_pipe_index + 1] + str(flag) + "|" + second_line[last_pipe_index + 1:] + lines[1] = modified_line + else: + print("Warning: No '|' character found in the second line of set.txt") + + with open("/home/unipi/flowserver/databases/settings.table", "w") as f: + f.writelines(lines) + else: + print("Warning: settings.table has less than two lines.") + + except FileNotFoundError: + print("Error: settings.table not found.") + except Exception as e: + print(e) + +# if __name__ == "__main__": +process_set_file() diff --git a/RVO7/cloud_topic.py b/RVO7/cloud_topic.py new file mode 100755 index 0000000..77c31f1 --- /dev/null +++ b/RVO7/cloud_topic.py @@ -0,0 +1,76 @@ +# import os +# +# def modify_file(file_path): +# """ +# Modifies the given file by: +# 1. Appending "|cloud_topic" to the first line. +# 2. Inserting the text from the third "." to the first "|" on the second line after the last "|" character. +# +# Args: +# file_path (str): The path to the file to be modified. +# """ +# +# with open(file_path, 'r+') as f: +# lines = f.readlines() +# +# # Modify the first line +# lines[0] += "|cloud_topic:string" +# +# # Modify the second line +# second_line = lines[1].strip() # Remove leading/trailing whitespace +# first_pipe_index = second_line.find('|') +# third_dot_index = second_line.find('.', second_line.find('.', second_line.find('.') + 1) + 1) +# text_to_insert = second_line[third_dot_index:first_pipe_index] +# +# last_pipe_index = second_line.rfind('|') +# lines[1] = second_line[:last_pipe_index + 1] + text_to_insert + "|" + second_line[last_pipe_index + 1:] +# +# print(first_pipe_index, third_dot_index, text_to_insert, last_pipe_index) +# # Write the modified lines back to the file +# # f.seek(0) +# # f.writelines(lines) +# # f.truncate() +# +# # Example usage: +# file_path = "settings.table" # Replace with the actual file path +# modify_file(file_path) +# + + +def modify_file(file_path): + """ + Modifies the given file by: + 1. Appending "|cloud_topic" to the first line. + 2. Inserting the text between the third "." and the second "|" on the second line after the last "|" character. + + Args: + file_path (str): The path to the file to be modified. + """ + + with open(file_path, 'r+') as f: + lines = f.readlines() + + first_line = lines[0].strip() + first_line += "|cloud_topic:string\n" + # Modify the first line + lines[0] = first_line + + # Modify the second line + second_line = lines[1].strip() # Remove leading/trailing whitespace + first_pipe_index = second_line.find('|') + second_pipe_index = second_line.find('|', first_pipe_index + 1) + third_dot_index = second_line.find('.', second_line.find('.', second_line.find('.') + 1) + 1) + text_to_insert = "u" + second_line[third_dot_index+1:second_pipe_index] + + last_pipe_index = second_line.rfind('|') + lines[1] = second_line[:last_pipe_index + 1] + text_to_insert + "|" + second_line[last_pipe_index + 1:] + + print(first_pipe_index, third_dot_index, text_to_insert, last_pipe_index) + # Write the modified lines back to the file + f.seek(0) + f.writelines(lines) + f.truncate() + +# Example usage: +file_path = "/home/unipi/flowserver/databases/settings.table" # Replace with the actual file path +modify_file(file_path) diff --git a/RVO7/config b/RVO7/config new file mode 100755 index 0000000..cd0a8a9 --- /dev/null +++ b/RVO7/config @@ -0,0 +1,12 @@ +name : Total.js Flow +default_timezone : Europe/Bratislava + +// Packages settings +package#flow (Object) : { url: '/' } + + +table.relays : line:number|tbname:string|contactor:number|profile:string +table.nodes : node:number|pole_number:string|node_type:string|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|project_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|cloud_topic:string|has_main_switch:boolean|daily_report:boolean|send_changed_node_numbers:boolean +table.pins : pin:string|type:string|line:number +table.notifications : key:string|weight:string|sk:string|en:string diff --git a/RVO7/createNode.py b/RVO7/createNode.py new file mode 100755 index 0000000..a8cea91 --- /dev/null +++ b/RVO7/createNode.py @@ -0,0 +1,43 @@ +print("zaciname") +import re, json + +search_str = '|' +final = [] +counter = 1 +with open("/home/unipi/flowserver/databases/nodes.table", 'r') as file: +# with open("/home/rasta5man/dev/oms/flowserver/databases/nodes.table", 'r') as file: + # Read each line in the file + for line in file: + # Print each line + line = line.strip() + print(line) + if counter != 1: + i = [m.start() for m in re.finditer(re.escape(search_str), line)] + node = line[ i[0] + 1 : i[1] ] + tbname = line[ i[3] + 1 : i[4] ] + final.append({node:tbname}) + counter += 1 +print(json.dumps(final)) +f = open("/home/unipi/flowserver/databases/nodes_original/nodes_original.table", "w") +f.write(json.dumps(final)) +f.close() + + +# +# # ``d`` has to be replaced with a different character +# old_character = "'" +# +# # ``t`` will replace ``d` +# new_character = '"' +# resultant_string = 0; +# with open("/home/unipi/flowserver/databases/nodes_original/nodes_original.table", 'r') as file: +# for line in file: +# resultant_string = re.sub("'", '"', line) +# +# resultant_string = re.sub(" ", "", resultant_string) +# print(resultant_string) +# +# f = open("/home/unipi/flowserver/databases/nodes_original/nodes_original.table", "w") +# f.write(str(resultant_string)) +# f.close() +# diff --git a/RVO7/databases/accelerometer_db.js b/RVO7/databases/accelerometer_db.js new file mode 100755 index 0000000..fdfc7fd --- /dev/null +++ b/RVO7/databases/accelerometer_db.js @@ -0,0 +1,3055 @@ +let naklony = { + "3993": { "label": "1/3A", "naklon": 0 }, + "3989": { "label": "1/3B", "naklon": 15 }, + "3976": { "label": "1/1", "naklon": 0 }, + "4181": { "label": "1/2", "naklon": 0 }, + "4376": { "label": "1/4", "naklon": 15 }, + "3868": { "label": "1/5", "naklon": 15 }, + "3728": { "label": "1/6", "naklon": 15 }, + "3730": { "label": "1/7", "naklon": 0 }, + "4374": { "label": "1/8", "naklon": 0 }, + "3718": { "label": "1/9", "naklon": 15 }, + "4375": { "label": "1/10", "naklon": 15 }, + "4172": { "label": "1/11", "naklon": 15 }, + "4176": { "label": "1/12", "naklon": 15 }, + "3800": { "label": "2/1", "naklon": 5 }, + "3823": { "label": "2/2", "naklon": 5 }, + "3905": { "label": "2/3", "naklon": 5 }, + "3803": { "label": "2/4", "naklon": 5 }, + "3817": { "label": "2/5", "naklon": 5 }, + "3818": { "label": "2/6", "naklon": 5 }, + "3811": { "label": "2/7", "naklon": 5 }, + "3915": { "label": "2/8", "naklon": 5 }, + "3843": { "label": "2/9", "naklon": 10 }, + "3827": { "label": "2/10", "naklon": 10 }, + "4220": { "label": "2/11", "naklon": 10 }, + "3826": { "label": "2/12", "naklon": 10 }, + "3834": { "label": "2/13", "naklon": 10 }, + "3838": { "label": "2/14", "naklon": 10 }, + "2823": { "label": "2/15", "naklon": 10 }, + "3750": { "label": "2/16", "naklon": 10 }, + "3378": { "label": "2/17", "naklon": 0 }, + "3376": { "label": "2/18", "naklon": 0 }, + "3379": { "label": "2/19", "naklon": 0 }, + "3285": { "label": "2/20", "naklon": 0 }, + "3382": { "label": "2/21", "naklon": 0 }, + "3383": { "label": "2/22", "naklon": 0 }, + "3375": { "label": "2/24", "naklon": 0 }, + "3381": { "label": "2/25", "naklon": 0 }, + "3380": { "label": "2/26", "naklon": 0 }, + "3828": { "label": "2/27", "naklon": 10 }, + "3377": { "label": "2/28", "naklon": 0 }, + "3591": { "label": "7/1", "naklon": 0 }, + "3587": { "label": "7/2", "naklon": 0 }, + "3468": { "label": "7/3", "naklon": 0 }, + "3466": { "label": "7/4", "naklon": 0 }, + "3474": { "label": "7/5", "naklon": 0 }, + "3481": { "label": "7/6", "naklon": 0 }, + "3589": { "label": "7/7", "naklon": 0 }, + "3472": { "label": "7/8", "naklon": 0 }, + "3473": { "label": "7/9", "naklon": 0 }, + "3584": { "label": "7/10", "naklon": 0 }, + "3571": { "label": "7/11", "naklon": 0 }, + "3476": { "label": "7/12", "naklon": 0 }, + "3590": { "label": "7/13", "naklon": 0 }, + "3478": { "label": "7/14", "naklon": 0 }, + "3471": { "label": "7/15", "naklon": 0 }, + "3467": { "label": "7/16", "naklon": 0 }, + "3479": { "label": "7/17", "naklon": 0 }, + "3480": { "label": "7/18", "naklon": 0 }, + "3477": { "label": "7/19", "naklon": 0 }, + "3362": { "label": "12/1", "naklon": 0 }, + "3355": { "label": "12/2", "naklon": 0 }, + "3356": { "label": "12/3", "naklon": 0 }, + "3349": { "label": "12/4", "naklon": 0 }, + "3357": { "label": "12/5", "naklon": 0 }, + "3350": { "label": "12/6", "naklon": 0 }, + "3353": { "label": "12/7", "naklon": 0 }, + "3539": { "label": "12/8", "naklon": 0 }, + "3050": { "label": "12/9", "naklon": 0 }, + "3361": { "label": "12/10", "naklon": 0 }, + "3360": { "label": "12/11", "naklon": 0 }, + "3358": { "label": "12/12", "naklon": 0 }, + "3541": { "label": "12/13", "naklon": 0 }, + "3551": { "label": "12/14", "naklon": 0 }, + "3514": { "label": "12/15", "naklon": 0 }, + "3547": { "label": "12/16", "naklon": 0 }, + "3562": { "label": "12/17", "naklon": 0 }, + "3525": { "label": "12/18", "naklon": 0 }, + "3558": { "label": "12/19", "naklon": 0 }, + "3511": { "label": "12/20", "naklon": 0 }, + "3058": { "label": "12/21", "naklon": 0 }, + "3062": { "label": "12/22", "naklon": 0 }, + "3070": { "label": "12/23", "naklon": 0 }, + "3447": { "label": "12/24", "naklon": 0 }, + "3056": { "label": "12/25", "naklon": 0 }, + "3057": { "label": "12/26", "naklon": 0 }, + "3071": { "label": "12/27", "naklon": 0 }, + "3061": { "label": "12/28", "naklon": 0 }, + "3069": { "label": "12/29", "naklon": 0 }, + "3077": { "label": "12/30", "naklon": 0 }, + "3080": { "label": "12/31", "naklon": 0 }, + "3081": { "label": "12/32", "naklon": 0 }, + "3078": { "label": "12/33", "naklon": 0 }, + "4037": { "label": "12/34", "naklon": 0 }, + "3067": { "label": "12/35", "naklon": 0 }, + "3051": { "label": "12/36", "naklon": 0 }, + "2924": { "label": "12/37", "naklon": 0 }, + "3060": { "label": "12/38", "naklon": 0 }, + "3073": { "label": "12/39", "naklon": 0 }, + "3469": { "label": "12/40", "naklon": 0 }, + "2923": { "label": "12/41", "naklon": 0 }, + "2925": { "label": "12/42", "naklon": 0 }, + "3359": { "label": "12/43", "naklon": 0 }, + "3055": { "label": "12/44", "naklon": 0 }, + "2922": { "label": "12/45", "naklon": 0 }, + "3084": { "label": "12/46", "naklon": 0 }, + "3064": { "label": "12/47", "naklon": 0 }, + "3066": { "label": "12/48", "naklon": 0 }, + "3072": { "label": "12/49", "naklon": 0 }, + "3415": { "label": "13/13A", "naklon": 0 }, + "3409": { "label": "13/13B", "naklon": 0 }, + "3399": { "label": "13/13C", "naklon": 0 }, + "3410": { "label": "13/29A", "naklon": 0 }, + "3407": { "label": "13/29B", "naklon": 0 }, + "3405": { "label": "13/34A", "naklon": 0 }, + "3404": { "label": "13/34B", "naklon": 0 }, + "3392": { "label": "13/45A", "naklon": 0 }, + "3386": { "label": "13/45B", "naklon": 0 }, + "3303": { "label": "13/60A", "naklon": 3 }, + "3302": { "label": "13/60B", "naklon": 3 }, + "3319": { "label": "13/70A", "naklon": 6 }, + "3317": { "label": "13/70B", "naklon": 6 }, + "3326": { "label": "13/70C", "naklon": 6 }, + "3351": { "label": "13/73A", "naklon": 6 }, + "3313": { "label": "13/73B", "naklon": 6 }, + "3316": { "label": "13/83A", "naklon": 0 }, + "3320": { "label": "13/83B", "naklon": 0 }, + "3336": { "label": "13/95A", "naklon": 0 }, + "3323": { "label": "13/95B", "naklon": 0 }, + "3339": { "label": "13/98A", "naklon": 0 }, + "3333": { "label": "13/98B", "naklon": 0 }, + "3425": { "label": "13/1", "naklon": 0 }, + "3419": { "label": "13/2", "naklon": 0 }, + "3416": { "label": "13/3", "naklon": 0 }, + "3332": { "label": "13/4", "naklon": 0 }, + "3422": { "label": "13/5", "naklon": 0 }, + "3417": { "label": "13/6", "naklon": 0 }, + "3418": { "label": "13/7", "naklon": 0 }, + "3424": { "label": "13/8", "naklon": 0 }, + "3334": { "label": "13/9", "naklon": 0 }, + "4363": { "label": "13/10", "naklon": 0 }, + "3423": { "label": "13/11", "naklon": 0 }, + "3406": { "label": "13/12", "naklon": 0 }, + "3411": { "label": "13/14", "naklon": 0 }, + "3412": { "label": "13/15", "naklon": 0 }, + "3413": { "label": "13/16", "naklon": 0 }, + "3414": { "label": "13/17", "naklon": 0 }, + "3391": { "label": "13/18", "naklon": 0 }, + "3370": { "label": "13/19", "naklon": 0 }, + "3369": { "label": "13/20", "naklon": 0 }, + "3408": { "label": "13/21", "naklon": 0 }, + "3393": { "label": "13/22", "naklon": 0 }, + "3128": { "label": "13/23", "naklon": 0 }, + "3197": { "label": "13/24", "naklon": 0 }, + "4364": { "label": "13/25", "naklon": 0 }, + "3155": { "label": "13/26", "naklon": 0 }, + "3196": { "label": "13/27", "naklon": 0 }, + "3144": { "label": "13/28", "naklon": 0 }, + "3150": { "label": "13/30", "naklon": 0 }, + "3390": { "label": "13/31", "naklon": 0 }, + "3401": { "label": "13/32", "naklon": 0 }, + "3275": { "label": "13/33", "naklon": 0 }, + "3371": { "label": "13/35", "naklon": 0 }, + "3389": { "label": "13/36", "naklon": 0 }, + "3388": { "label": "13/37", "naklon": 0 }, + "3365": { "label": "13/38", "naklon": 0 }, + "3363": { "label": "13/39", "naklon": 0 }, + "3397": { "label": "13/40", "naklon": 0 }, + "3567": { "label": "13/40/1", "naklon": 0 }, + "3387": { "label": "13/41", "naklon": 0 }, + "3403": { "label": "13/42", "naklon": 0 }, + "3147": { "label": "13/43", "naklon": 0 }, + "3141": { "label": "13/44", "naklon": 0 }, + "3364": { "label": "13/46", "naklon": 0 }, + "3367": { "label": "13/47", "naklon": 0 }, + "3368": { "label": "13/48", "naklon": 0 }, + "3402": { "label": "13/49", "naklon": 0 }, + "3366": { "label": "13/50", "naklon": 0 }, + "3395": { "label": "13/51", "naklon": 0 }, + "3372": { "label": "13/52", "naklon": 0 }, + "3394": { "label": "13/53", "naklon": 0 }, + "3308": { "label": "13/54", "naklon": 0 }, + "3847": { "label": "13/54/1", "naklon": 0 }, + "3312": { "label": "13/55", "naklon": 3 }, + "3309": { "label": "13/56", "naklon": 3 }, + "3311": { "label": "13/57", "naklon": 3 }, + "3310": { "label": "13/58", "naklon": 3 }, + "4365": { "label": "13/59", "naklon": 3 }, + "4093": { "label": "13/60/1", "naklon": 3 }, + "3304": { "label": "13/61", "naklon": 3 }, + "3307": { "label": "13/62", "naklon": 3 }, + "3271": { "label": "13/63", "naklon": 3 }, + "3301": { "label": "13/64", "naklon": 3 }, + "4366": { "label": "13/65", "naklon": 3 }, + "3300": { "label": "13/66", "naklon": 3 }, + "3185": { "label": "13/67", "naklon": 0 }, + "3184": { "label": "13/68", "naklon": 0 }, + "3188": { "label": "13/69", "naklon": 0 }, + "3343": { "label": "13/71", "naklon": 6 }, + "3819": { "label": "13/71/1", "naklon": 6 }, + "3880": { "label": "13/71/2", "naklon": 6 }, + "3348": { "label": "13/72", "naklon": 6 }, + "3344": { "label": "13/74", "naklon": 6 }, + "3346": { "label": "13/75", "naklon": 6 }, + "3597": { "label": "13/75/1", "naklon": 6 }, + "3345": { "label": "13/76", "naklon": 6 }, + "3322": { "label": "13/77", "naklon": 0 }, + "3325": { "label": "13/78", "naklon": 0 }, + "4310": { "label": "13/78/1", "naklon": 0 }, + "3315": { "label": "13/79", "naklon": 0 }, + "3328": { "label": "13/80", "naklon": 0 }, + "3321": { "label": "13/81", "naklon": 0 }, + "3324": { "label": "13/82", "naklon": 0 }, + "3140": { "label": "13/84", "naklon": 0 }, + "3153": { "label": "13/85", "naklon": 0 }, + "3145": { "label": "13/86", "naklon": 0 }, + "3134": { "label": "13/87", "naklon": 0 }, + "3151": { "label": "13/88", "naklon": 0 }, + "3143": { "label": "13/89", "naklon": 0 }, + "3318": { "label": "13/90", "naklon": 0 }, + "3347": { "label": "13/91", "naklon": 0 }, + "3314": { "label": "13/94", "naklon": 0 }, + "3331": { "label": "13/96", "naklon": 0 }, + "3327": { "label": "13/97", "naklon": 0 }, + "3329": { "label": "13/99", "naklon": 0 }, + "3337": { "label": "13/100", "naklon": 0 }, + "3330": { "label": "13/101", "naklon": 0 }, + "3335": { "label": "13/102", "naklon": 0 }, + "3420": { "label": "13/103", "naklon": 0 }, + "3421": { "label": "13/104", "naklon": 0 }, + "4361": { "label": "13/105", "naklon": 0 }, + "4362": { "label": "13/106", "naklon": 0 }, + "3526": { "label": "13/107", "naklon": 0 }, + "4424": { "label": "13/108", "naklon": null }, + "3561": { "label": "13/109", "naklon": null }, + "3527": { "label": "13/110", "naklon": null }, + "3521": { "label": "13/111", "naklon": null }, + "3552": { "label": "13/112", "naklon": null }, + "3544": { "label": "13/113", "naklon": null }, + "3534": { "label": "13/114", "naklon": null }, + "3516": { "label": "13/115", "naklon": null }, + "3513": { "label": "13/116", "naklon": null }, + "3565": { "label": "13/117", "naklon": null }, + "3866": { "label": "13/118", "naklon": null }, + "3136": { "label": "14/1", "naklon": 0 }, + "3137": { "label": "14/2", "naklon": 0 }, + "3135": { "label": "14/3", "naklon": 0 }, + "3149": { "label": "14/4", "naklon": 0 }, + "3142": { "label": "14/5", "naklon": 0 }, + "3342": { "label": "14/6", "naklon": 0 }, + "3340": { "label": "14/7", "naklon": 0 }, + "3152": { "label": "14/8", "naklon": 0 }, + "3886": { "label": "14/9", "naklon": 0 }, + "3341": { "label": "14/10", "naklon": null }, + "3352": { "label": "14/11", "naklon": null }, + "3396": { "label": "15/1", "naklon": 5 }, + "2784": { "label": "15/2", "naklon": 5 }, + "2788": { "label": "15/3", "naklon": 5 }, + "2801": { "label": "15/4", "naklon": 5 }, + "2815": { "label": "15/5", "naklon": 5 }, + "2829": { "label": "15/6", "naklon": 5 }, + "2796": { "label": "15/7", "naklon": 5 }, + "2803": { "label": "15/8", "naklon": 5 }, + "4304": { "label": "15/8/1", "naklon": 5 }, + "4311": { "label": "15/8/2", "naklon": 5 }, + "2821": { "label": "15/9", "naklon": 5 }, + "3400": { "label": "15/10", "naklon": 5 }, + "2799": { "label": "15/11", "naklon": 5 }, + "2804": { "label": "15/12", "naklon": 5 }, + "4303": { "label": "15/12/1", "naklon": 5 }, + "4309": { "label": "15/12/2", "naklon": 5 }, + "2806": { "label": "15/13", "naklon": 5 }, + "2787": { "label": "15/14", "naklon": 5 }, + "2809": { "label": "15/15", "naklon": 5 }, + "2814": { "label": "15/16", "naklon": 0 }, + "3934": { "label": "15/17", "naklon": 0 }, + "3192": { "label": "15/18", "naklon": 0 }, + "2812": { "label": "15/19", "naklon": 0 }, + "4070": { "label": "15/20", "naklon": 0 }, + "2826": { "label": "15/21", "naklon": 0 }, + "2808": { "label": "15/22", "naklon": 3 }, + "2795": { "label": "15/23", "naklon": 3 }, + "2807": { "label": "15/24", "naklon": 3 }, + "2831": { "label": "15/25", "naklon": 0 }, + "2862": { "label": "15/26", "naklon": null }, + "2861": { "label": "15/27", "naklon": 0 }, + "2866": { "label": "15/28", "naklon": 0 }, + "3546": { "label": "15/28/1", "naklon": 0 }, + "4146": { "label": "15/29", "naklon": 0 }, + "3001": { "label": "15/29/1", "naklon": 0 }, + "2835": { "label": "15/30", "naklon": 0 }, + "2874": { "label": "15/31", "naklon": 0 }, + "2852": { "label": "15/32", "naklon": 0 }, + "2851": { "label": "15/33", "naklon": 0 }, + "3560": { "label": "15/33/1", "naklon": 0 }, + "2858": { "label": "15/34", "naklon": 0 }, + "4306": { "label": "15/34/1", "naklon": 0 }, + "2856": { "label": "15/35", "naklon": 0 }, + "2847": { "label": "15/36", "naklon": 0 }, + "3556": { "label": "15/36/1", "naklon": 0 }, + "3950": { "label": "15/37", "naklon": 0 }, + "2848": { "label": "15/38", "naklon": 0 }, + "2863": { "label": "15/39", "naklon": 0 }, + "4313": { "label": "15/39/1", "naklon": 0 }, + "2873": { "label": "15/40", "naklon": 0 }, + "2984": { "label": "15/40/1", "naklon": 0 }, + "2854": { "label": "15/41", "naklon": 0 }, + "2859": { "label": "15/42", "naklon": 0 }, + "2872": { "label": "15/43", "naklon": 0 }, + "2849": { "label": "15/44", "naklon": 0 }, + "2864": { "label": "15/45", "naklon": 0 }, + "3553": { "label": "15/46", "naklon": null }, + "3021": { "label": "15/47", "naklon": null }, + "3008": { "label": "15/47/1", "naklon": null }, + "3017": { "label": "15/48", "naklon": null }, + "3014": { "label": "15/49", "naklon": null }, + "2981": { "label": "15/50", "naklon": null }, + "3020": { "label": "15/51", "naklon": null }, + "3027": { "label": "15/52", "naklon": null }, + "3006": { "label": "15/53", "naklon": null }, + "3012": { "label": "15/54", "naklon": null }, + "2738": { "label": "15/55", "naklon": 0 }, + "2725": { "label": "15/56", "naklon": 0 }, + "3016": { "label": "15/57", "naklon": null }, + "3005": { "label": "15/58", "naklon": null }, + "3009": { "label": "15/58/1", "naklon": null }, + "3010": { "label": "15/59", "naklon": 0 }, + "3538": { "label": "15/59/1", "naklon": 0 }, + "4145": { "label": "15/59/2", "naklon": 0 }, + "2713": { "label": "15/60", "naklon": 0 }, + "2789": { "label": "15/61", "naklon": 0 }, + "2736": { "label": "15/62", "naklon": 0 }, + "2739": { "label": "15/63", "naklon": 0 }, + "4346": { "label": "15/64", "naklon": 0 }, + "2731": { "label": "15/65", "naklon": 0 }, + "2818": { "label": "15/66", "naklon": 0 }, + "3557": { "label": "15/66/1", "naklon": 0 }, + "2822": { "label": "15/67", "naklon": 0 }, + "2833": { "label": "15/68", "naklon": 0 }, + "2834": { "label": "15/69", "naklon": 0 }, + "3097": { "label": "15/70", "naklon": 0 }, + "2824": { "label": "15/71", "naklon": 0 }, + "2828": { "label": "15/72", "naklon": 0 }, + "2600": { "label": "15/73", "naklon": 0 }, + "4314": { "label": "15/73/1", "naklon": 0 }, + "2832": { "label": "15/74", "naklon": 0 }, + "4360": { "label": "15/75", "naklon": 0 }, + "2846": { "label": "15/76", "naklon": 0 }, + "2584": { "label": "15/77", "naklon": 0 }, + "2843": { "label": "15/78", "naklon": 0 }, + "4308": { "label": "15/78/1", "naklon": 0 }, + "4144": { "label": "15/79", "naklon": null }, + "2844": { "label": "15/80", "naklon": 0 }, + "2842": { "label": "15/81", "naklon": 0 }, + "2838": { "label": "15/82", "naklon": 0 }, + "2837": { "label": "15/83", "naklon": null }, + "3555": { "label": "15/83/1", "naklon": null }, + "2839": { "label": "15/84", "naklon": 0 }, + "2830": { "label": "15/85", "naklon": 0 }, + "4066": { "label": "15/86", "naklon": 0 }, + "2836": { "label": "15/87", "naklon": 0 }, + "2911": { "label": "15/88", "naklon": 0 }, + "2825": { "label": "15/89", "naklon": 0 }, + "2811": { "label": "15/90", "naklon": 0 }, + "3740": { "label": "15/94", "naklon": 15 }, + "2734": { "label": "15/95", "naklon": 15 }, + "3105": { "label": "15/96", "naklon": 15 }, + "2732": { "label": "15/97", "naklon": 15 }, + "2727": { "label": "15/98", "naklon": 15 }, + "2735": { "label": "15/99", "naklon": 15 }, + "3926": { "label": "15/100", "naklon": 15 }, + "2918": { "label": "15/101", "naklon": 0 }, + "2705": { "label": "15/102", "naklon": 10 }, + "2708": { "label": "15/103", "naklon": 10 }, + "2721": { "label": "15/104", "naklon": 10 }, + "2719": { "label": "15/105", "naklon": 10 }, + "2919": { "label": "15/106", "naklon": 10 }, + "3101": { "label": "15/107", "naklon": 10 }, + "2853": { "label": "15/108", "naklon": 10 }, + "2715": { "label": "15/109", "naklon": 10 }, + "2712": { "label": "15/110", "naklon": 0 }, + "2711": { "label": "15/111", "naklon": 0 }, + "2709": { "label": "15/112", "naklon": 0 }, + "2710": { "label": "15/113", "naklon": 0 }, + "2907": { "label": "15/114", "naklon": 0 }, + "2906": { "label": "15/115", "naklon": 0 }, + "2908": { "label": "15/116", "naklon": 0 }, + "2901": { "label": "15/117", "naklon": 0 }, + "2913": { "label": "15/118", "naklon": 0 }, + "3656": { "label": "15/119", "naklon": 0 }, + "2781": { "label": "15/120", "naklon": 0 }, + "2802": { "label": "15/121", "naklon": 0 }, + "2791": { "label": "15/122", "naklon": 0 }, + "2783": { "label": "15/123", "naklon": 0 }, + "2794": { "label": "15/124", "naklon": 0 }, + "3139": { "label": "15/125", "naklon": 0 }, + "3229": { "label": "15/126", "naklon": 5 }, + "3239": { "label": "15/127", "naklon": 5 }, + "3230": { "label": "15/128", "naklon": 5 }, + "4016": { "label": "15/129", "naklon": null }, + "3608": { "label": "16/16A", "naklon": 0 }, + "4151": { "label": "16/16B", "naklon": 0 }, + "3710": { "label": "16/1", "naklon": 0 }, + "3726": { "label": "16/2", "naklon": 0 }, + "3743": { "label": "16/3", "naklon": 0 }, + "3724": { "label": "16/4", "naklon": 0 }, + "3712": { "label": "16/5", "naklon": 0 }, + "3739": { "label": "16/6", "naklon": 0 }, + "3742": { "label": "16/7", "naklon": 0 }, + "3731": { "label": "16/8", "naklon": 0 }, + "3727": { "label": "16/9", "naklon": 0 }, + "3729": { "label": "16/10", "naklon": 0 }, + "3736": { "label": "16/11", "naklon": 0 }, + "3713": { "label": "16/12", "naklon": 0 }, + "3715": { "label": "16/13", "naklon": 0 }, + "3733": { "label": "16/14", "naklon": 0 }, + "3732": { "label": "16/15", "naklon": 0 }, + "3634": { "label": "16/17", "naklon": 0 }, + "3610": { "label": "16/18", "naklon": 0 }, + "3626": { "label": "16/19", "naklon": 0 }, + "3618": { "label": "16/20", "naklon": 0 }, + "3619": { "label": "16/21", "naklon": 0 }, + "3628": { "label": "16/22", "naklon": 0 }, + "3615": { "label": "16/23", "naklon": 0 }, + "3609": { "label": "16/24", "naklon": 0 }, + "3606": { "label": "16/25", "naklon": 0 }, + "3624": { "label": "16/26", "naklon": 0 }, + "3627": { "label": "16/27", "naklon": 0 }, + "3607": { "label": "16/28", "naklon": 0 }, + "4370": { "label": "16/29", "naklon": 0 }, + "3692": { "label": "16/30", "naklon": 0 }, + "3614": { "label": "16/31", "naklon": 0 }, + "3623": { "label": "16/32", "naklon": 0 }, + "4373": { "label": "16/33", "naklon": 0 }, + "3620": { "label": "16/34", "naklon": 0 }, + "3685": { "label": "16/35", "naklon": 0 }, + "3616": { "label": "16/36", "naklon": 0 }, + "3686": { "label": "16/37", "naklon": 0 }, + "3688": { "label": "16/38", "naklon": 0 }, + "3684": { "label": "16/39", "naklon": 0 }, + "3825": { "label": "16/40", "naklon": 0 }, + "3865": { "label": "16/41", "naklon": 0 }, + "3824": { "label": "16/42", "naklon": 0 }, + "3871": { "label": "16/43", "naklon": 0 }, + "3801": { "label": "16/44", "naklon": 0 }, + "3862": { "label": "16/45", "naklon": 0 }, + "3876": { "label": "16/46", "naklon": 0 }, + "3861": { "label": "16/47", "naklon": 0 }, + "4215": { "label": "16/48", "naklon": 0 }, + "3605": { "label": "16/49", "naklon": 10 }, + "3603": { "label": "16/50", "naklon": 10 }, + "3592": { "label": "16/51", "naklon": 10 }, + "3598": { "label": "16/52", "naklon": 10 }, + "3594": { "label": "16/53", "naklon": 10 }, + "3593": { "label": "16/54", "naklon": 10 }, + "3630": { "label": "16/55", "naklon": 10 }, + "3763": { "label": "16/56", "naklon": 10 }, + "3746": { "label": "16/57", "naklon": 10 }, + "3699": { "label": "16/58", "naklon": 0 }, + "3698": { "label": "16/59", "naklon": 0 }, + "3709": { "label": "16/60", "naklon": null }, + "3708": { "label": "16/61", "naklon": 0 }, + "3703": { "label": "16/62", "naklon": null }, + "3700": { "label": "16/63", "naklon": 0 }, + "3701": { "label": "16/64", "naklon": null }, + "3704": { "label": "16/65", "naklon": 0 }, + "3707": { "label": "16/66", "naklon": null }, + "3810": { "label": "16/67", "naklon": 0 }, + "4208": { "label": "16/68", "naklon": null }, + "3867": { "label": "16/69", "naklon": 0 }, + "4372": { "label": "16/70", "naklon": null }, + "3881": { "label": "16/71", "naklon": 0 }, + "4204": { "label": "16/72", "naklon": null }, + "3869": { "label": "16/73", "naklon": 0 }, + "4202": { "label": "16/74", "naklon": null }, + "3830": { "label": "16/75", "naklon": 0 }, + "3870": { "label": "16/76", "naklon": null }, + "3964": { "label": "16/77", "naklon": 0 }, + "3849": { "label": "16/78", "naklon": 0 }, + "3694": { "label": "16/79", "naklon": null }, + "3717": { "label": "16/80", "naklon": 0 }, + "3877": { "label": "16/81", "naklon": null }, + "3755": { "label": "16/82", "naklon": 0 }, + "3725": { "label": "16/83", "naklon": null }, + "3716": { "label": "16/84", "naklon": 0 }, + "3696": { "label": "16/85", "naklon": null }, + "3702": { "label": "16/86", "naklon": 0 }, + "3706": { "label": "16/87", "naklon": null }, + "3850": { "label": "16/88", "naklon": 0 }, + "3848": { "label": "16/89", "naklon": null }, + "3737": { "label": "16/90", "naklon": null }, + "3705": { "label": "16/91", "naklon": 0 }, + "3723": { "label": "16/92", "naklon": null }, + "3842": { "label": "16/93", "naklon": 0 }, + "3735": { "label": "16/94", "naklon": null }, + "3719": { "label": "16/95", "naklon": 0 }, + "3697": { "label": "16/96", "naklon": 0 }, + "3711": { "label": "16/97", "naklon": 0 }, + "4107": { "label": "16/98", "naklon": null }, + "4112": { "label": "16/99", "naklon": 5 }, + "4106": { "label": "16/100", "naklon": 5 }, + "4111": { "label": "16/101", "naklon": 5 }, + "4091": { "label": "16/102", "naklon": null }, + "4104": { "label": "16/103", "naklon": 5 }, + "4094": { "label": "16/104", "naklon": null }, + "4089": { "label": "16/105", "naklon": 5 }, + "4095": { "label": "16/106", "naklon": null }, + "4102": { "label": "16/107", "naklon": 5 }, + "4105": { "label": "16/108", "naklon": null }, + "3859": { "label": "16/109", "naklon": null }, + "4090": { "label": "16/110", "naklon": 5 }, + "4110": { "label": "16/111", "naklon": null }, + "4097": { "label": "16/112", "naklon": 5 }, + "4099": { "label": "16/113", "naklon": null }, + "4096": { "label": "16/114", "naklon": null }, + "4101": { "label": "16/115", "naklon": 5 }, + "4109": { "label": "16/116", "naklon": null }, + "4092": { "label": "16/117", "naklon": 5 }, + "3631": { "label": "16/118", "naklon": null }, + "3632": { "label": "16/119", "naklon": 0 }, + "3641": { "label": "16/120", "naklon": null }, + "3638": { "label": "16/121", "naklon": 0 }, + "3637": { "label": "16/122", "naklon": null }, + "4142": { "label": "16/123", "naklon": null }, + "4147": { "label": "16/124", "naklon": 5 }, + "4139": { "label": "16/125", "naklon": 5 }, + "3172": { "label": "20/30A", "naklon": 2 }, + "3164": { "label": "20/30B", "naklon": 2 }, + "3247": { "label": "20/1", "naklon": 10 }, + "3296": { "label": "20/2", "naklon": 10 }, + "3246": { "label": "20/3", "naklon": 10 }, + "3270": { "label": "20/4", "naklon": 10 }, + "3294": { "label": "20/5", "naklon": 10 }, + "3298": { "label": "20/6", "naklon": 10 }, + "3297": { "label": "20/7", "naklon": 10 }, + "3293": { "label": "20/8", "naklon": 10 }, + "3299": { "label": "20/9", "naklon": 10 }, + "3295": { "label": "20/10", "naklon": 10 }, + "3244": { "label": "20/11", "naklon": 10 }, + "3249": { "label": "20/12", "naklon": 10 }, + "3268": { "label": "20/13", "naklon": 10 }, + "3245": { "label": "20/14", "naklon": 10 }, + "3278": { "label": "20/15", "naklon": 10 }, + "3280": { "label": "20/16", "naklon": 10 }, + "3292": { "label": "20/17", "naklon": 10 }, + "3287": { "label": "20/18", "naklon": 10 }, + "3282": { "label": "20/19", "naklon": 10 }, + "3273": { "label": "20/20", "naklon": 0 }, + "3157": { "label": "20/21", "naklon": 0 }, + "3283": { "label": "20/22", "naklon": 0 }, + "3159": { "label": "20/23", "naklon": 0 }, + "3289": { "label": "20/24", "naklon": 0 }, + "3163": { "label": "20/25", "naklon": 0 }, + "3126": { "label": "20/26", "naklon": 0 }, + "3171": { "label": "20/27", "naklon": 0 }, + "3162": { "label": "20/28", "naklon": 0 }, + "3279": { "label": "20/29", "naklon": 10 }, + "3173": { "label": "20/31", "naklon": 0 }, + "3127": { "label": "20/32", "naklon": 0 }, + "3131": { "label": "20/33", "naklon": 0 }, + "3129": { "label": "20/34", "naklon": 0 }, + "3276": { "label": "20/35", "naklon": 2 }, + "3290": { "label": "20/36", "naklon": 2 }, + "3132": { "label": "20/37", "naklon": 0 }, + "3138": { "label": "20/38", "naklon": 0 }, + "3272": { "label": "20/39", "naklon": 0 }, + "3291": { "label": "20/40", "naklon": 0 }, + "3277": { "label": "20/41", "naklon": 10 }, + "3286": { "label": "20/42", "naklon": 10 }, + "3281": { "label": "20/43", "naklon": 10 }, + "3288": { "label": "20/44", "naklon": 10 }, + "3284": { "label": "20/45", "naklon": 10 }, + "3167": { "label": "20/46", "naklon": 10 }, + "3872": { "label": "20/47", "naklon": 0 }, + "3124": { "label": "20/48", "naklon": 0 }, + "3133": { "label": "20/49", "naklon": 0 }, + "3158": { "label": "20/50", "naklon": 0 }, + "3169": { "label": "20/51", "naklon": 0 }, + "3146": { "label": "20/52", "naklon": 0 }, + "3160": { "label": "20/53", "naklon": 0 }, + "3248": { "label": "20/54", "naklon": 0 }, + "3156": { "label": "20/55", "naklon": 0 }, + "3161": { "label": "20/56", "naklon": 0 }, + "3170": { "label": "20/57", "naklon": 0 }, + "3168": { "label": "20/58", "naklon": 0 }, + "3125": { "label": "20/59", "naklon": 0 }, + "3166": { "label": "20/60", "naklon": 0 }, + "3130": { "label": "20/61", "naklon": 0 }, + "3563": { "label": "20/62", "naklon": 0 }, + "3550": { "label": "20/63", "naklon": null }, + "3269": { "label": "20/67", "naklon": 0 }, + "2921": { "label": "21/1", "naklon": 0 }, + "2707": { "label": "21/2", "naklon": 0 }, + "2723": { "label": "21/3", "naklon": 0 }, + "2716": { "label": "21/4", "naklon": 0 }, + "2717": { "label": "21/5", "naklon": 0 }, + "2720": { "label": "21/6", "naklon": 0 }, + "2722": { "label": "21/7", "naklon": 0 }, + "2718": { "label": "21/8", "naklon": 0 }, + "2724": { "label": "21/9", "naklon": 0 }, + "2742": { "label": "21/10", "naklon": 0 }, + "2743": { "label": "21/11", "naklon": 0 }, + "2733": { "label": "21/12", "naklon": 0 }, + "2903": { "label": "21/14", "naklon": 0 }, + "2917": { "label": "21/15", "naklon": 0 }, + "2897": { "label": "21/16", "naklon": 0 }, + "2914": { "label": "21/17", "naklon": 0 }, + "2898": { "label": "21/18", "naklon": 0 }, + "2773": { "label": "21/19", "naklon": 0 }, + "2895": { "label": "21/20", "naklon": 0 }, + "2896": { "label": "21/21", "naklon": 0 }, + "2771": { "label": "21/22", "naklon": 0 }, + "2772": { "label": "21/23", "naklon": 0 }, + "2793": { "label": "21/24", "naklon": 0 }, + "2902": { "label": "21/25", "naklon": 0 }, + "2910": { "label": "21/26", "naklon": 0 }, + "2909": { "label": "21/27", "naklon": 0 }, + "2920": { "label": "21/28", "naklon": 0 }, + "2916": { "label": "21/29", "naklon": 0 }, + "2904": { "label": "21/30", "naklon": 0 }, + "2915": { "label": "21/31", "naklon": 0 }, + "2905": { "label": "21/32", "naklon": 0 }, + "2900": { "label": "21/33", "naklon": 0 }, + "2899": { "label": "21/34", "naklon": 0 }, + "2741": { "label": "21/36", "naklon": 0 }, + "2714": { "label": "21/37", "naklon": 0 }, + "2701": { "label": "21/38", "naklon": 0 }, + "2703": { "label": "21/39", "naklon": 0 }, + "2704": { "label": "21/40", "naklon": 0 }, + "2702": { "label": "21/41", "naklon": 0 }, + "2706": { "label": "21/42", "naklon": 0 }, + "2776": { "label": "21/43", "naklon": 0 }, + "2770": { "label": "21/44", "naklon": 0 }, + "2786": { "label": "21/45", "naklon": 0 }, + "2779": { "label": "21/46", "naklon": 0 }, + "2782": { "label": "21/47", "naklon": 0 }, + "2785": { "label": "21/48", "naklon": 0 }, + "2769": { "label": "21/49", "naklon": 0 }, + "3354": { "label": "21/50", "naklon": 0 }, + "2778": { "label": "21/51", "naklon": 0 }, + "2775": { "label": "21/52", "naklon": 0 }, + "2780": { "label": "21/53", "naklon": 0 }, + "2790": { "label": "21/54", "naklon": 0 }, + "2792": { "label": "21/55", "naklon": 0 }, + "2774": { "label": "21/56", "naklon": 0 }, + "2630": { "label": "22/1", "naklon": 0 }, + "2631": { "label": "22/2", "naklon": 0 }, + "2632": { "label": "22/3", "naklon": 0 }, + "2633": { "label": "22/4", "naklon": 0 }, + "2634": { "label": "22/5", "naklon": 0 }, + "2636": { "label": "22/6", "naklon": 0 }, + "4367": { "label": "22/7", "naklon": 0 }, + "2637": { "label": "22/8", "naklon": 0 }, + "2638": { "label": "22/9", "naklon": 0 }, + "2639": { "label": "22/10", "naklon": 0 }, + "2640": { "label": "22/11", "naklon": 0 }, + "2641": { "label": "22/12", "naklon": 0 }, + "2642": { "label": "22/13", "naklon": 0 }, + "2643": { "label": "22/14", "naklon": 0 }, + "2644": { "label": "22/15", "naklon": 0 }, + "2645": { "label": "22/16", "naklon": 0 }, + "2646": { "label": "22/17", "naklon": 0 }, + "2647": { "label": "22/18", "naklon": 0 }, + "2648": { "label": "22/19", "naklon": 0 }, + "2649": { "label": "22/20", "naklon": 0 }, + "2650": { "label": "22/21", "naklon": 0 }, + "2651": { "label": "22/22", "naklon": 0 }, + "4103": { "label": "22/23", "naklon": 0 }, + "2653": { "label": "22/24", "naklon": 0 }, + "2654": { "label": "22/25", "naklon": 0 }, + "2655": { "label": "22/26", "naklon": 0 }, + "2656": { "label": "22/27", "naklon": 0 }, + "2657": { "label": "22/28", "naklon": 0 }, + "2658": { "label": "22/29", "naklon": 0 }, + "2659": { "label": "22/30", "naklon": 0 }, + "2660": { "label": "22/31", "naklon": 0 }, + "2661": { "label": "22/32", "naklon": 0 }, + "3015": { "label": "22/32/1", "naklon": 0 }, + "2662": { "label": "22/33", "naklon": 0 }, + "2663": { "label": "22/34", "naklon": 0 }, + "2664": { "label": "22/35", "naklon": 0 }, + "2665": { "label": "22/36", "naklon": 0 }, + "2666": { "label": "22/37", "naklon": 0 }, + "2667": { "label": "22/38", "naklon": 0 }, + "2668": { "label": "22/39", "naklon": 0 }, + "2669": { "label": "22/40", "naklon": null }, + "2670": { "label": "22/41", "naklon": null }, + "2671": { "label": "22/42", "naklon": null }, + "3087": { "label": "23/9A", "naklon": 10 }, + "3090": { "label": "23/9B", "naklon": 10 }, + "3075": { "label": "23/1", "naklon": 0 }, + "3089": { "label": "23/2", "naklon": 0 }, + "3088": { "label": "23/3", "naklon": 0 }, + "3228": { "label": "23/4", "naklon": 10 }, + "2751": { "label": "23/5", "naklon": 10 }, + "3243": { "label": "23/6", "naklon": 10 }, + "4349": { "label": "23/7", "naklon": 10 }, + "3102": { "label": "23/8", "naklon": 10 }, + "3099": { "label": "23/10", "naklon": 10 }, + "3103": { "label": "23/11", "naklon": 10 }, + "3093": { "label": "23/12", "naklon": 10 }, + "3098": { "label": "23/13", "naklon": 10 }, + "3092": { "label": "23/14", "naklon": 10 }, + "3233": { "label": "23/15", "naklon": 0 }, + "3095": { "label": "23/16", "naklon": 0 }, + "4074": { "label": "23/17", "naklon": 0 }, + "2729": { "label": "23/18", "naklon": 0 }, + "3234": { "label": "23/19", "naklon": 0 }, + "3094": { "label": "23/20", "naklon": 0 }, + "2817": { "label": "23/21", "naklon": 0 }, + "3226": { "label": "23/22", "naklon": 0 }, + "3225": { "label": "23/23", "naklon": 0 }, + "3237": { "label": "23/24", "naklon": 0 }, + "4250": { "label": "23/25", "naklon": 0 }, + "3059": { "label": "23/26", "naklon": 10 }, + "3238": { "label": "23/27", "naklon": 10 }, + "3242": { "label": "23/28", "naklon": 10 }, + "3236": { "label": "23/29", "naklon": 10 }, + "3112": { "label": "23/30", "naklon": 10 }, + "3224": { "label": "23/31", "naklon": 0 }, + "4298": { "label": "23/32", "naklon": 10 }, + "4150": { "label": "23/33", "naklon": 10 }, + "3091": { "label": "23/34", "naklon": 10 }, + "3771": { "label": "25/1", "naklon": 5 }, + "3777": { "label": "25/2", "naklon": 5 }, + "3749": { "label": "25/3", "naklon": 5 }, + "3769": { "label": "25/4", "naklon": 5 }, + "3765": { "label": "25/5", "naklon": 5 }, + "3785": { "label": "25/6", "naklon": 5 }, + "3761": { "label": "25/7", "naklon": 5 }, + "3758": { "label": "25/8", "naklon": 5 }, + "3766": { "label": "25/9", "naklon": 5 }, + "3779": { "label": "25/10", "naklon": 5 }, + "3899": { "label": "25/11", "naklon": 10 }, + "3922": { "label": "25/12", "naklon": 10 }, + "3912": { "label": "25/13", "naklon": 10 }, + "3933": { "label": "25/14", "naklon": 10 }, + "3921": { "label": "25/15", "naklon": 10 }, + "4300": { "label": "25/16", "naklon": 10 }, + "3927": { "label": "25/17", "naklon": 10 }, + "3212": { "label": "25/18", "naklon": 10 }, + "3208": { "label": "25/19", "naklon": 10 }, + "3207": { "label": "25/20", "naklon": 10 }, + "4294": { "label": "25/21", "naklon": 10 }, + "3209": { "label": "25/22", "naklon": 10 }, + "3745": { "label": "25/23", "naklon": 10 }, + "3762": { "label": "25/24", "naklon": 10 }, + "3215": { "label": "25/25", "naklon": 10 }, + "3210": { "label": "25/26", "naklon": 10 }, + "3211": { "label": "25/27", "naklon": 10 }, + "3206": { "label": "25/28", "naklon": 10 }, + "3918": { "label": "25/29", "naklon": 5 }, + "3928": { "label": "25/30", "naklon": 5 }, + "3917": { "label": "25/31", "naklon": 5 }, + "4029": { "label": "25/32", "naklon": 0 }, + "4038": { "label": "25/33", "naklon": 0 }, + "4022": { "label": "25/34", "naklon": 0 }, + "3937": { "label": "25/35", "naklon": 0 }, + "3190": { "label": "25/36", "naklon": 0 }, + "3835": { "label": "25/37", "naklon": 0 }, + "3201": { "label": "25/38", "naklon": 0 }, + "3193": { "label": "25/39", "naklon": 0 }, + "3191": { "label": "25/40", "naklon": 0 }, + "3203": { "label": "25/41", "naklon": 0 }, + "4301": { "label": "25/42", "naklon": 0 }, + "3223": { "label": "25/43", "naklon": 0 }, + "3202": { "label": "25/44", "naklon": 0 }, + "3205": { "label": "25/45", "naklon": 0 }, + "3194": { "label": "25/46", "naklon": 0 }, + "3198": { "label": "25/47", "naklon": 0 }, + "3204": { "label": "25/48", "naklon": 0 }, + "3200": { "label": "25/49", "naklon": 0 }, + "3216": { "label": "25/50", "naklon": 0 }, + "3932": { "label": "25/51", "naklon": 5 }, + "3923": { "label": "25/52", "naklon": 5 }, + "3913": { "label": "25/53", "naklon": 5 }, + "3900": { "label": "25/54", "naklon": 5 }, + "4189": { "label": "25/55", "naklon": 10 }, + "4191": { "label": "25/56", "naklon": 10 }, + "3790": { "label": "25/57", "naklon": 10 }, + "4190": { "label": "25/58", "naklon": 10 }, + "4302": { "label": "25/59", "naklon": 0 }, + "4351": { "label": "25/60", "naklon": 0 }, + "4075": { "label": "25/61", "naklon": 0 }, + "4071": { "label": "25/62", "naklon": 0 }, + "3784": { "label": "25/63", "naklon": 0 }, + "4065": { "label": "25/64", "naklon": 0 }, + "4297": { "label": "25/65", "naklon": 0 }, + "4295": { "label": "25/66", "naklon": 0 }, + "4299": { "label": "25/67", "naklon": 0 }, + "3772": { "label": "25/68", "naklon": 0 }, + "3941": { "label": "25/69", "naklon": 0 }, + "3782": { "label": "25/70", "naklon": 0 }, + "4068": { "label": "25/71", "naklon": 0 }, + "4073": { "label": "25/72", "naklon": 0 }, + "3901": { "label": "25/73", "naklon": 5 }, + "4296": { "label": "25/74", "naklon": 5 }, + "3910": { "label": "25/75", "naklon": 5 }, + "4293": { "label": "25/76", "naklon": 5 }, + "3919": { "label": "25/77", "naklon": 5 }, + "3924": { "label": "25/78", "naklon": 5 }, + "3909": { "label": "25/79", "naklon": 5 }, + "3896": { "label": "25/80", "naklon": 5 }, + "3911": { "label": "25/81", "naklon": 5 }, + "2819": { "label": "25/82", "naklon": 15 }, + "3776": { "label": "25/83", "naklon": 15 }, + "3752": { "label": "25/84", "naklon": 15 }, + "4353": { "label": "25/85", "naklon": 15 }, + "3791": { "label": "25/86", "naklon": 0 }, + "3770": { "label": "25/87", "naklon": 0 }, + "3760": { "label": "25/88", "naklon": 0 }, + "3115": { "label": "25/89", "naklon": 0 }, + "3738": { "label": "25/90", "naklon": 0 }, + "3748": { "label": "25/91", "naklon": 0 }, + "3753": { "label": "25/92", "naklon": 0 }, + "3775": { "label": "25/93", "naklon": 0 }, + "3778": { "label": "25/94", "naklon": 5 }, + "4078": { "label": "25/95", "naklon": 5 }, + "4088": { "label": "25/96", "naklon": 5 }, + "3856": { "label": "25/97", "naklon": 5 }, + "4084": { "label": "25/98", "naklon": 5 }, + "4069": { "label": "25/99", "naklon": 5 }, + "4188": { "label": "25/100", "naklon": 5 }, + "4064": { "label": "25/101", "naklon": 5 }, + "3792": { "label": "25/102", "naklon": 5 }, + "3780": { "label": "25/103", "naklon": 5 }, + "4034": { "label": "25/104", "naklon": 5 }, + "4072": { "label": "25/105", "naklon": 5 }, + "3884": { "label": "25/106", "naklon": 5 }, + "3793": { "label": "25/107", "naklon": 5 }, + "3863": { "label": "25/108", "naklon": 5 }, + "3855": { "label": "25/109", "naklon": 5 }, + "3846": { "label": "33/1", "naklon": 0 }, + "3943": { "label": "33/2", "naklon": 0 }, + "3903": { "label": "33/3", "naklon": 0 }, + "3982": { "label": "33/4", "naklon": 0 }, + "3879": { "label": "33/5", "naklon": 0 }, + "3887": { "label": "33/6", "naklon": 0 }, + "3920": { "label": "33/7", "naklon": 5 }, + "3942": { "label": "33/8", "naklon": 5 }, + "3829": { "label": "33/9", "naklon": null }, + "3452": { "label": "34/79A", "naklon": 6 }, + "3460": { "label": "34/79B", "naklon": 6 }, + "3443": { "label": "34/90A", "naklon": 6 }, + "3445": { "label": "34/90B", "naklon": 6 }, + "3457": { "label": "34/90C", "naklon": 6 }, + "3461": { "label": "34/97A", "naklon": 6 }, + "3463": { "label": "34/97B", "naklon": 6 }, + "3426": { "label": "34/98A", "naklon": 6 }, + "3444": { "label": "34/98B", "naklon": 6 }, + "3453": { "label": "34/99A", "naklon": 6 }, + "3455": { "label": "34/99B", "naklon": 6 }, + "4009": { "label": "34/1", "naklon": 0 }, + "3602": { "label": "34/2", "naklon": 0 }, + "3441": { "label": "34/3", "naklon": 0 }, + "3464": { "label": "34/4", "naklon": 0 }, + "3883": { "label": "34/5", "naklon": 0 }, + "4098": { "label": "34/6", "naklon": 0 }, + "4003": { "label": "34/7", "naklon": 0 }, + "4004": { "label": "34/8", "naklon": 0 }, + "3888": { "label": "34/9", "naklon": 0 }, + "3997": { "label": "34/10", "naklon": 0 }, + "4006": { "label": "34/11", "naklon": 0 }, + "4000": { "label": "34/12", "naklon": 0 }, + "4011": { "label": "34/13", "naklon": 0 }, + "3999": { "label": "34/14", "naklon": 0 }, + "3981": { "label": "34/15", "naklon": 0 }, + "3988": { "label": "34/16", "naklon": 0 }, + "3986": { "label": "34/17", "naklon": 0 }, + "3998": { "label": "34/18", "naklon": 0 }, + "3983": { "label": "34/19", "naklon": 0 }, + "4005": { "label": "34/20", "naklon": 0 }, + "4001": { "label": "34/21", "naklon": 0 }, + "4008": { "label": "34/22", "naklon": 0 }, + "4002": { "label": "34/23", "naklon": 0 }, + "3996": { "label": "34/24", "naklon": 0 }, + "4007": { "label": "34/25", "naklon": 0 }, + "4113": { "label": "34/26", "naklon": 15 }, + "3595": { "label": "34/27", "naklon": 5 }, + "3599": { "label": "34/28", "naklon": 5 }, + "3601": { "label": "34/29", "naklon": 5 }, + "4205": { "label": "34/30", "naklon": 0 }, + "3987": { "label": "34/31", "naklon": null }, + "4214": { "label": "34/32", "naklon": 0 }, + "4226": { "label": "34/33", "naklon": 0 }, + "4209": { "label": "34/34", "naklon": 0 }, + "4201": { "label": "34/35", "naklon": 0 }, + "3440": { "label": "34/36", "naklon": 0 }, + "3465": { "label": "34/37", "naklon": 0 }, + "3446": { "label": "34/38", "naklon": 0 }, + "4039": { "label": "34/39", "naklon": 5 }, + "4057": { "label": "34/40", "naklon": 5 }, + "3985": { "label": "34/41", "naklon": 0 }, + "3882": { "label": "34/42", "naklon": 0 }, + "4040": { "label": "34/43", "naklon": 5 }, + "3231": { "label": "34/44", "naklon": 0 }, + "3227": { "label": "34/45", "naklon": 0 }, + "3431": { "label": "34/46", "naklon": 0 }, + "4013": { "label": "34/47", "naklon": 0 }, + "4045": { "label": "34/48", "naklon": 0 }, + "3949": { "label": "34/49", "naklon": 0 }, + "3953": { "label": "34/50", "naklon": 0 }, + "3952": { "label": "34/51", "naklon": 0 }, + "3995": { "label": "34/52", "naklon": 0 }, + "3992": { "label": "34/53", "naklon": 0 }, + "4198": { "label": "34/54", "naklon": 0 }, + "3935": { "label": "34/55", "naklon": 0 }, + "4050": { "label": "34/56", "naklon": 0 }, + "4049": { "label": "34/57", "naklon": 0 }, + "4054": { "label": "34/58", "naklon": 0 }, + "3663": { "label": "34/59", "naklon": 6 }, + "3661": { "label": "34/60", "naklon": 6 }, + "3664": { "label": "34/61", "naklon": 6 }, + "3660": { "label": "34/62", "naklon": 6 }, + "3662": { "label": "34/63", "naklon": 6 }, + "3665": { "label": "34/65", "naklon": 6 }, + "3667": { "label": "34/66", "naklon": 6 }, + "3675": { "label": "34/67", "naklon": 6 }, + "3666": { "label": "34/68", "naklon": 6 }, + "3652": { "label": "34/69", "naklon": 6 }, + "3458": { "label": "34/70", "naklon": 6 }, + "4425": { "label": "34/70/1", "naklon": 6 }, + "3459": { "label": "34/71", "naklon": 6 }, + "3435": { "label": "34/72", "naklon": 6 }, + "3448": { "label": "34/73", "naklon": 6 }, + "3451": { "label": "34/74", "naklon": 6 }, + "3442": { "label": "34/75", "naklon": 6 }, + "3449": { "label": "34/76", "naklon": 6 }, + "3450": { "label": "34/77", "naklon": 6 }, + "3433": { "label": "34/78", "naklon": 6 }, + "3432": { "label": "34/80", "naklon": 12 }, + "3470": { "label": "34/81", "naklon": 12 }, + "3438": { "label": "34/82", "naklon": 12 }, + "3439": { "label": "34/83", "naklon": 12 }, + "4028": { "label": "34/84", "naklon": 5 }, + "3596": { "label": "34/85", "naklon": 5 }, + "4021": { "label": "34/86", "naklon": 5 }, + "3437": { "label": "34/87", "naklon": 12 }, + "3428": { "label": "34/88", "naklon": 12 }, + "3430": { "label": "34/89", "naklon": 12 }, + "3454": { "label": "34/91", "naklon": 6 }, + "3492": { "label": "34/92", "naklon": 6 }, + "3462": { "label": "34/93", "naklon": 6 }, + "3427": { "label": "34/94", "naklon": 6 }, + "3434": { "label": "34/95", "naklon": 6 }, + "3456": { "label": "34/96", "naklon": 6 }, + "4307": { "label": "34/98/1", "naklon": 6 }, + "3968": { "label": "35/1", "naklon": 0 }, + "3969": { "label": "35/2", "naklon": 0 }, + "3947": { "label": "35/3", "naklon": 0 }, + "3979": { "label": "35/4", "naklon": 0 }, + "3959": { "label": "35/5", "naklon": 0 }, + "3948": { "label": "35/6", "naklon": 0 }, + "3961": { "label": "35/7", "naklon": 0 }, + "3956": { "label": "35/8", "naklon": 0 }, + "3604": { "label": "35/9", "naklon": 0 }, + "3944": { "label": "35/10", "naklon": 0 }, + "3960": { "label": "35/11", "naklon": 0 }, + "3958": { "label": "35/12", "naklon": 0 }, + "4036": { "label": "35/13", "naklon": 5 }, + "3893": { "label": "35/18", "naklon": 5 }, + "4108": { "label": "35/19", "naklon": 5 }, + "4017": { "label": "35/20", "naklon": 5 }, + "3963": { "label": "35/21", "naklon": 0 }, + "3658": { "label": "35/22", "naklon": 0 }, + "3975": { "label": "35/23", "naklon": 0 }, + "3980": { "label": "35/24", "naklon": 0 }, + "4012": { "label": "35/25", "naklon": 0 }, + "3655": { "label": "35/26", "naklon": 0 }, + "3962": { "label": "35/27", "naklon": 0 }, + "3945": { "label": "35/28", "naklon": 0 }, + "3569": { "label": "35/29", "naklon": 0 }, + "3429": { "label": "35/30", "naklon": 0 }, + "3657": { "label": "35/31", "naklon": 0 }, + "3646": { "label": "35/32", "naklon": 0 }, + "3622": { "label": "35/33", "naklon": 0 }, + "3612": { "label": "35/34", "naklon": 0 }, + "3955": { "label": "35/35", "naklon": 0 }, + "3878": { "label": "35/37", "naklon": 0 }, + "3965": { "label": "35/38", "naklon": 0 }, + "3970": { "label": "35/39", "naklon": 0 }, + "3611": { "label": "35/40", "naklon": 0 }, + "2635": { "label": "35/41", "naklon": 0 }, + "3978": { "label": "35/42", "naklon": 0 }, + "4213": { "label": "35/43", "naklon": 0 }, + "3984": { "label": "35/44", "naklon": 0 }, + "4218": { "label": "35/45", "naklon": 0 }, + "3973": { "label": "35/46", "naklon": 0 }, + "3974": { "label": "35/47", "naklon": 0 }, + "3759": { "label": "35/48", "naklon": 0 }, + "3844": { "label": "35/49", "naklon": 0 }, + "3804": { "label": "35/50", "naklon": 0 }, + "3831": { "label": "35/51", "naklon": 0 }, + "3643": { "label": "35/52", "naklon": 0 }, + "3966": { "label": "35/53", "naklon": 0 }, + "3971": { "label": "35/54", "naklon": 0 }, + "3650": { "label": "35/55", "naklon": 6 }, + "3651": { "label": "35/56", "naklon": 6 }, + "3669": { "label": "35/57", "naklon": 6 }, + "3648": { "label": "35/58", "naklon": 6 }, + "3645": { "label": "35/59", "naklon": 6 }, + "3659": { "label": "35/60", "naklon": 6 }, + "3647": { "label": "35/61", "naklon": 6 }, + "3644": { "label": "35/62", "naklon": 6 }, + "3671": { "label": "35/63", "naklon": 6 }, + "3682": { "label": "35/64", "naklon": 6 }, + "3672": { "label": "35/65", "naklon": 6 }, + "3683": { "label": "35/66", "naklon": 6 }, + "3673": { "label": "35/67", "naklon": 6 }, + "3674": { "label": "35/68", "naklon": 6 }, + "3679": { "label": "35/69", "naklon": 6 }, + "3649": { "label": "35/70", "naklon": 6 }, + "3687": { "label": "35/71", "naklon": 6 }, + "3677": { "label": "35/72", "naklon": 6 }, + "3690": { "label": "35/73", "naklon": 6 }, + "3691": { "label": "35/74", "naklon": 6 }, + "3676": { "label": "35/75", "naklon": 6 }, + "3680": { "label": "35/76", "naklon": 6 }, + "3668": { "label": "35/77", "naklon": 6 }, + "3681": { "label": "35/78", "naklon": 6 }, + "3670": { "label": "35/79", "naklon": 6 }, + "3689": { "label": "35/80", "naklon": 6 }, + "3678": { "label": "35/81", "naklon": 6 }, + "3693": { "label": "35/82", "naklon": 6 }, + "3654": { "label": "35/83", "naklon": null }, + "4086": { "label": "36/1", "naklon": 0 }, + "4085": { "label": "36/2", "naklon": 0 }, + "4083": { "label": "36/3", "naklon": 0 }, + "4087": { "label": "36/4", "naklon": 0 }, + "4077": { "label": "36/5", "naklon": 0 }, + "4082": { "label": "36/6", "naklon": 0 }, + "4186": { "label": "36/7", "naklon": 0 }, + "4206": { "label": "36/8", "naklon": 0 }, + "4080": { "label": "36/9", "naklon": 0 }, + "4081": { "label": "36/10", "naklon": 0 }, + "4210": { "label": "36/11", "naklon": 0 }, + "4079": { "label": "36/12", "naklon": 0 }, + "4076": { "label": "36/13", "naklon": 0 }, + "3852": { "label": "36/14", "naklon": 0 }, + "2813": { "label": "36/15", "naklon": 0 }, + "4219": { "label": "36/16", "naklon": 0 }, + "3104": { "label": "37/1A", "naklon": 15 }, + "3121": { "label": "37/1B", "naklon": 15 }, + "3113": { "label": "37/2", "naklon": 10 }, + "3118": { "label": "37/3", "naklon": 10 }, + "3111": { "label": "37/4", "naklon": 10 }, + "4020": { "label": "37/5", "naklon": 10 }, + "3119": { "label": "37/6", "naklon": 10 }, + "3110": { "label": "37/7", "naklon": 10 }, + "3108": { "label": "37/8", "naklon": 10 }, + "3107": { "label": "37/12", "naklon": 0 }, + "3199": { "label": "37/13", "naklon": 0 }, + "3120": { "label": "37/14", "naklon": 0 }, + "3122": { "label": "37/15", "naklon": 0 }, + "3908": { "label": "37/16", "naklon": 0 }, + "3114": { "label": "37/17", "naklon": 0 }, + "3105": { "label": "37/18", "naklon": 0 }, + "3116": { "label": "37/19", "naklon": 0 }, + "3106": { "label": "37/20", "naklon": 0 }, + "2887": { "label": "37/21", "naklon": 5 }, + "2888": { "label": "37/22", "naklon": 5 }, + "2877": { "label": "37/23", "naklon": 5 }, + "2891": { "label": "37/24", "naklon": 5 }, + "2886": { "label": "37/25", "naklon": 5 }, + "2892": { "label": "37/26", "naklon": 5 }, + "2882": { "label": "37/27", "naklon": 5 }, + "2883": { "label": "37/28", "naklon": 5 }, + "2876": { "label": "37/29", "naklon": 5 }, + "3109": { "label": "37/30", "naklon": 5 }, + "4152": { "label": "37/31", "naklon": 5 }, + "3117": { "label": "37/32", "naklon": 5 }, + "2870": { "label": "37/33", "naklon": 5 }, + "2867": { "label": "37/34", "naklon": 0 }, + "2865": { "label": "37/35", "naklon": 0 }, + "3096": { "label": "37/36", "naklon": 0 }, + "2871": { "label": "37/37", "naklon": 0 }, + "2884": { "label": "37/38", "naklon": 0 }, + "2855": { "label": "37/39", "naklon": 0 }, + "2878": { "label": "37/40", "naklon": 0 }, + "2889": { "label": "37/41", "naklon": 0 }, + "2879": { "label": "37/42", "naklon": 0 }, + "2850": { "label": "37/43", "naklon": 0 }, + "2894": { "label": "37/44", "naklon": 0 }, + "2880": { "label": "37/45", "naklon": 0 }, + "2893": { "label": "37/46", "naklon": 0 }, + "2890": { "label": "37/47", "naklon": 0 }, + "4355": { "label": "37/48", "naklon": 0 }, + "2885": { "label": "37/49", "naklon": 0 }, + "2875": { "label": "37/50", "naklon": 0 }, + "3486": { "label": "38/30A", "naklon": 5 }, + "3714": { "label": "38/30B", "naklon": 0 }, + "3483": { "label": "38/32A", "naklon": 5 }, + "3496": { "label": "38/32B", "naklon": 0 }, + "3487": { "label": "38/35A", "naklon": 5 }, + "3498": { "label": "38/35B", "naklon": 5 }, + "3578": { "label": "38/38A", "naklon": 5 }, + "3508": { "label": "38/38B", "naklon": 5 }, + "3787": { "label": "38/59A", "naklon": 5 }, + "3491": { "label": "38/59B", "naklon": 5 }, + "3568": { "label": "38/1", "naklon": null }, + "3502": { "label": "38/2", "naklon": 0 }, + "3836": { "label": "38/3", "naklon": 0 }, + "3588": { "label": "38/4", "naklon": 0 }, + "3493": { "label": "38/5", "naklon": 0 }, + "3580": { "label": "38/6", "naklon": 0 }, + "3572": { "label": "38/7", "naklon": 0 }, + "3506": { "label": "38/8", "naklon": 0 }, + "3503": { "label": "38/9", "naklon": 0 }, + "3579": { "label": "38/10", "naklon": 0 }, + "3586": { "label": "38/11", "naklon": 0 }, + "3495": { "label": "38/12", "naklon": 5 }, + "3492": { "label": "38/13", "naklon": 5 }, + "3532": { "label": "38/14", "naklon": 5 }, + "3574": { "label": "38/15", "naklon": 5 }, + "4140": { "label": "38/16", "naklon": 5 }, + "3795": { "label": "38/17", "naklon": 5 }, + "3788": { "label": "38/18", "naklon": 5 }, + "3796": { "label": "38/19", "naklon": 5 }, + "3797": { "label": "38/20", "naklon": 5 }, + "3798": { "label": "38/21", "naklon": 5 }, + "3786": { "label": "38/22", "naklon": 5 }, + "4067": { "label": "38/23", "naklon": 5 }, + "3773": { "label": "38/24", "naklon": 5 }, + "3774": { "label": "38/25", "naklon": 5 }, + "3789": { "label": "38/26", "naklon": 5 }, + "3520": { "label": "38/27", "naklon": null }, + "3577": { "label": "38/29", "naklon": 5 }, + "3530": { "label": "38/31", "naklon": null }, + "3488": { "label": "38/33", "naklon": 5 }, + "3505": { "label": "38/34", "naklon": 5 }, + "3497": { "label": "38/36", "naklon": 5 }, + "3490": { "label": "38/37", "naklon": 5 }, + "3585": { "label": "38/39", "naklon": 5 }, + "3582": { "label": "38/40", "naklon": 5 }, + "3507": { "label": "38/41", "naklon": 5 }, + "3484": { "label": "38/42", "naklon": 5 }, + "3501": { "label": "38/43", "naklon": 5 }, + "3581": { "label": "38/44", "naklon": 5 }, + "4192": { "label": "38/45", "naklon": 5 }, + "3576": { "label": "38/46", "naklon": 5 }, + "3489": { "label": "38/47", "naklon": 5 }, + "3573": { "label": "38/48", "naklon": 5 }, + "3504": { "label": "38/49", "naklon": 5 }, + "3794": { "label": "38/50", "naklon": 5 }, + "3485": { "label": "38/51", "naklon": 5 }, + "3482": { "label": "38/52", "naklon": 5 }, + "3575": { "label": "38/53", "naklon": 5 }, + "3499": { "label": "38/54", "naklon": 5 }, + "3494": { "label": "38/55", "naklon": 5 }, + "3583": { "label": "38/56", "naklon": 5 }, + "3570": { "label": "38/57", "naklon": 5 }, + "3500": { "label": "38/58", "naklon": 0 }, + "3510": { "label": "38/63", "naklon": null }, + "3512": { "label": "38/64", "naklon": null }, + "3535": { "label": "38/67", "naklon": null }, + "3531": { "label": "38/68", "naklon": null }, + "3537": { "label": "38/69", "naklon": null }, + "3522": { "label": "39/1", "naklon": 10 }, + "4018": { "label": "39/2", "naklon": 10 }, + "4019": { "label": "39/3", "naklon": 10 }, + "4154": { "label": "39/4", "naklon": 5 }, + "3907": { "label": "39/5", "naklon": 5 }, + "4148": { "label": "39/6", "naklon": 0 }, + "4153": { "label": "39/7", "naklon": 0 }, + "3938": { "label": "39/8", "naklon": 0 }, + "3802": { "label": "39/9", "naklon": 0 }, + "4015": { "label": "39/10", "naklon": 0 }, + "3929": { "label": "39/11", "naklon": 0 }, + "3946": { "label": "39/12", "naklon": 0 }, + "4014": { "label": "39/13", "naklon": 0 }, + "4155": { "label": "39/14", "naklon": 0 }, + "4149": { "label": "39/15", "naklon": 0 }, + "3642": { "label": "39/16", "naklon": 0 }, + "3636": { "label": "39/17", "naklon": 5 }, + "3991": { "label": "39/18", "naklon": 0 }, + "3994": { "label": "39/19", "naklon": 0 }, + "3990": { "label": "39/20", "naklon": 0 }, + "3967": { "label": "39/21", "naklon": 0 }, + "3977": { "label": "39/22", "naklon": 0 }, + "3757": { "label": "39/23", "naklon": 15 }, + "3633": { "label": "39/24", "naklon": 15 }, + "3744": { "label": "39/25", "naklon": 15 }, + "4023": { "label": "39/26", "naklon": 5 }, + "3720": { "label": "39/27", "naklon": 5 }, + "3734": { "label": "39/28", "naklon": 5 }, + "3741": { "label": "39/29", "naklon": 5 }, + "3721": { "label": "39/30", "naklon": 5 }, + "3845": { "label": "39/31", "naklon": 0 }, + "3840": { "label": "39/32", "naklon": 0 }, + "3837": { "label": "39/33", "naklon": null }, + "3839": { "label": "39/34", "naklon": 0 }, + "3542": { "label": "41/1", "naklon": null }, + "3566": { "label": "41/2", "naklon": null }, + "3548": { "label": "41/3", "naklon": null }, + "3515": { "label": "41/4", "naklon": null }, + "3559": { "label": "41/5", "naklon": null }, + "3509": { "label": "41/6", "naklon": null }, + "3524": { "label": "41/7", "naklon": null }, + "3518": { "label": "41/8", "naklon": null }, + "3182": { "label": "41/9", "naklon": null }, + "3187": { "label": "41/10", "naklon": null }, + "3195": { "label": "41/11", "naklon": 0 }, + "3857": { "label": "41/12", "naklon": 0 }, + "3183": { "label": "41/13", "naklon": 0 }, + "3177": { "label": "41/14", "naklon": 0 }, + "3189": { "label": "41/15", "naklon": 0 }, + "3186": { "label": "41/16", "naklon": 0 }, + "3178": { "label": "42/1", "naklon": 0 }, + "3219": { "label": "42/2", "naklon": 0 }, + "3475": { "label": "42/3", "naklon": 0 }, + "3175": { "label": "42/4", "naklon": 0 }, + "3222": { "label": "42/5", "naklon": 0 }, + "3221": { "label": "42/6", "naklon": 0 }, + "3181": { "label": "42/7", "naklon": 0 }, + "3180": { "label": "42/8", "naklon": 0 }, + "3218": { "label": "42/9", "naklon": 0 }, + "3176": { "label": "42/10", "naklon": 0 }, + "3174": { "label": "42/11", "naklon": 0 }, + "3220": { "label": "42/12", "naklon": 0 }, + "3533": { "label": "42/13", "naklon": null }, + "3543": { "label": "42/14", "naklon": null }, + "3554": { "label": "42/15", "naklon": null }, + "3549": { "label": "42/16", "naklon": null }, + "2857": { "label": "43/1", "naklon": 5 }, + "2752": { "label": "43/2", "naklon": 5 }, + "2753": { "label": "43/3", "naklon": 5 }, + "3024": { "label": "43/4", "naklon": 5 }, + "2754": { "label": "43/5", "naklon": 5 }, + "4423": { "label": "43/6", "naklon": 5 }, + "4368": { "label": "43/7", "naklon": 5 }, + "2978": { "label": "43/8", "naklon": 5 }, + "2868": { "label": "43/9", "naklon": 5 }, + "4377": { "label": "43/10", "naklon": 5 }, + "2757": { "label": "43/11", "naklon": 5 }, + "2970": { "label": "43/12", "naklon": 5 }, + "2758": { "label": "43/13", "naklon": 5 }, + "4378": { "label": "43/14", "naklon": 5 }, + "2759": { "label": "43/15", "naklon": 5 }, + "4342": { "label": "43/16", "naklon": 5 }, + "3026": { "label": "43/17", "naklon": null }, + "2986": { "label": "43/18", "naklon": null }, + "4343": { "label": "43/19", "naklon": null }, + "2760": { "label": "43/20", "naklon": null }, + "4379": { "label": "43/21", "naklon": null }, + "2971": { "label": "43/22", "naklon": null }, + "2761": { "label": "43/23", "naklon": null }, + "2762": { "label": "43/24", "naklon": null }, + "4339": { "label": "43/25", "naklon": null }, + "4380": { "label": "43/26", "naklon": null }, + "2975": { "label": "43/27", "naklon": null }, + "3003": { "label": "43/28", "naklon": null }, + "4338": { "label": "43/29", "naklon": null }, + "3002": { "label": "43/30", "naklon": null }, + "4345": { "label": "43/31", "naklon": null }, + "2979": { "label": "43/32", "naklon": null }, + "2989": { "label": "43/33", "naklon": null }, + "2996": { "label": "43/34", "naklon": null }, + "2972": { "label": "43/35", "naklon": null }, + "2988": { "label": "43/36", "naklon": null }, + "4344": { "label": "43/37", "naklon": null }, + "3022": { "label": "43/38", "naklon": null }, + "4341": { "label": "43/39", "naklon": null }, + "2983": { "label": "43/40", "naklon": null }, + "2995": { "label": "43/41", "naklon": null }, + "2763": { "label": "43/42", "naklon": null }, + "2764": { "label": "43/43", "naklon": null }, + "2765": { "label": "43/44", "naklon": null }, + "2766": { "label": "43/45", "naklon": null }, + "2767": { "label": "43/46", "naklon": null }, + "2768": { "label": "43/47", "naklon": null }, + "3018": { "label": "43/48", "naklon": null }, + "2982": { "label": "43/49", "naklon": null }, + "3019": { "label": "43/50", "naklon": 0 }, + "3013": { "label": "43/51", "naklon": null }, + "3007": { "label": "43/52", "naklon": null }, + "2980": { "label": "43/53", "naklon": null }, + "3011": { "label": "43/54", "naklon": null }, + "2672": { "label": "43/55", "naklon": null }, + "2673": { "label": "43/56", "naklon": null }, + "2674": { "label": "43/57", "naklon": null }, + "2675": { "label": "43/58", "naklon": null }, + "2676": { "label": "43/59", "naklon": null }, + "2677": { "label": "43/60", "naklon": null }, + "2678": { "label": "43/61", "naklon": null }, + "2679": { "label": "43/62", "naklon": null }, + "2680": { "label": "43/63", "naklon": null }, + "2840": { "label": "43/64", "naklon": null }, + "2682": { "label": "43/65", "naklon": null }, + "2683": { "label": "43/66", "naklon": null }, + "2684": { "label": "43/67", "naklon": 0 }, + "2685": { "label": "43/68", "naklon": null }, + "2686": { "label": "43/69", "naklon": null }, + "2687": { "label": "43/70", "naklon": null }, + "2688": { "label": "43/71", "naklon": null }, + "2689": { "label": "43/72", "naklon": null }, + "2690": { "label": "43/73", "naklon": null }, + "2691": { "label": "43/74", "naklon": null }, + "2692": { "label": "43/75", "naklon": null }, + "2693": { "label": "43/76", "naklon": 0 }, + "2694": { "label": "43/77", "naklon": null }, + "2695": { "label": "43/78", "naklon": null }, + "2696": { "label": "43/79", "naklon": 0 }, + "2697": { "label": "43/80", "naklon": null }, + "2698": { "label": "43/81", "naklon": 0 }, + "2699": { "label": "43/82", "naklon": null }, + "2700": { "label": "43/83", "naklon": 0 }, + "2744": { "label": "43/84", "naklon": null }, + "2745": { "label": "43/85", "naklon": 0 }, + "2746": { "label": "43/86", "naklon": null }, + "2747": { "label": "43/87", "naklon": 0 }, + "2748": { "label": "43/88", "naklon": null }, + "2749": { "label": "43/89", "naklon": 0 }, + "2841": { "label": "43/90", "naklon": null }, + "4237": { "label": "45/1", "naklon": 5 }, + "4226": { "label": "45/2", "naklon": 5 }, + "4242": { "label": "45/3", "naklon": 5 }, + "4179": { "label": "45/4", "naklon": 5 }, + "4247": { "label": "45/5", "naklon": 5 }, + "4245": { "label": "45/6", "naklon": 5 }, + "3872": { "label": "45/7", "naklon": 5 }, + "4175": { "label": "45/8", "naklon": 5 }, + "4236": { "label": "45/9", "naklon": 5 }, + "4170": { "label": "45/10", "naklon": 5 }, + "4238": { "label": "45/11", "naklon": 5 }, + "4246": { "label": "45/12", "naklon": 5 }, + "4166": { "label": "45/13", "naklon": 5 }, + "4227": { "label": "45/14", "naklon": 5 }, + "4171": { "label": "45/15", "naklon": 5 }, + "4180": { "label": "45/16", "naklon": 5 }, + "4244": { "label": "45/17", "naklon": 5 }, + "4199": { "label": "45/18", "naklon": 5 }, + "4239": { "label": "45/19", "naklon": 5 }, + "4207": { "label": "45/20", "naklon": 5 }, + "4223": { "label": "45/21", "naklon": 5 }, + "4230": { "label": "45/22", "naklon": 5 }, + "4233": { "label": "45/23", "naklon": 5 }, + "4222": { "label": "45/24", "naklon": 5 }, + "4217": { "label": "45/25", "naklon": 5 }, + "4243": { "label": "45/26", "naklon": 5 }, + "4200": { "label": "45/27", "naklon": 5 }, + "4228": { "label": "45/28", "naklon": 5 }, + "4211": { "label": "45/29", "naklon": 5 }, + "4234": { "label": "45/30", "naklon": 5 }, + "4235": { "label": "45/31", "naklon": 5 }, + "4203": { "label": "45/32", "naklon": 5 }, + "4240": { "label": "45/33", "naklon": 5 }, + "4224": { "label": "45/34", "naklon": 5 }, + "4232": { "label": "45/35", "naklon": 5 }, + "4231": { "label": "45/36", "naklon": 5 }, + "4161": { "label": "45/37", "naklon": 5 }, + "4225": { "label": "45/38", "naklon": 5 }, + "4241": { "label": "45/39", "naklon": 5 }, + "4229": { "label": "45/40", "naklon": 5 }, + "4221": { "label": "45/41", "naklon": 5 }, + "4212": { "label": "45/42", "naklon": 5 }, + "4216": { "label": "45/43", "naklon": 5 }, + "3864": { "label": "45/44", "naklon": null }, + "3806": { "label": "46/1", "naklon": 5 }, + "3813": { "label": "46/2", "naklon": 5 }, + "3815": { "label": "46/3", "naklon": 5 }, + "3807": { "label": "46/4", "naklon": 5 }, + "3895": { "label": "46/5", "naklon": 5 }, + "3809": { "label": "46/6", "naklon": 5 }, + "3820": { "label": "46/7", "naklon": 5 }, + "3805": { "label": "46/8", "naklon": 5 }, + "3894": { "label": "46/9", "naklon": 0 }, + "4055": { "label": "46/10", "naklon": 0 }, + "3812": { "label": "46/11", "naklon": 5 }, + "3822": { "label": "46/12", "naklon": 5 }, + "3821": { "label": "46/13", "naklon": 5 }, + "3808": { "label": "46/14", "naklon": 5 }, + "3799": { "label": "46/15", "naklon": 5 }, + "3816": { "label": "46/16", "naklon": 5 }, + "3751": { "label": "46/17", "naklon": 5 }, + "3814": { "label": "46/18", "naklon": 5 }, + "4044": { "label": "46/19", "naklon": 0 }, + "3931": { "label": "46/20", "naklon": 0 }, + "3902": { "label": "46/21", "naklon": 5 }, + "3916": { "label": "46/22", "naklon": 5 }, + "3892": { "label": "46/23", "naklon": 5 }, + "3914": { "label": "46/24", "naklon": 5 }, + "3898": { "label": "46/25", "naklon": 5 }, + "3897": { "label": "46/26", "naklon": 5 }, + "3885": { "label": "46/27", "naklon": 5 }, + "3906": { "label": "46/28", "naklon": 5 }, + "3930": { "label": "46/29", "naklon": 0 }, + "3936": { "label": "46/30", "naklon": 0 }, + "3860": { "label": "46/31", "naklon": 5 }, + "3841": { "label": "46/32", "naklon": 5 }, + "3873": { "label": "46/33", "naklon": 5 }, + "3854": { "label": "46/34", "naklon": 5 }, + "3939": { "label": "46/35", "naklon": 5 }, + "3858": { "label": "46/36", "naklon": 5 }, + "3940": { "label": "46/37", "naklon": 5 }, + "4035": { "label": "46/38", "naklon": 5 }, + "3373": { "label": "47/1", "naklon": 0 }, + "3374": { "label": "47/2", "naklon": 0 }, + "3384": { "label": "47/3", "naklon": 0 }, + "3385": { "label": "47/4", "naklon": 0 }, + "4051": { "label": "48/1", "naklon": 5 }, + "4041": { "label": "48/2", "naklon": 5 }, + "4056": { "label": "48/3", "naklon": 5 }, + "3875": { "label": "48/4", "naklon": 5 }, + "4061": { "label": "48/5", "naklon": 5 }, + "4047": { "label": "48/6", "naklon": 5 }, + "4060": { "label": "48/7", "naklon": 5 }, + "4059": { "label": "48/8", "naklon": 5 }, + "4058": { "label": "48/9", "naklon": 5 }, + "3635": { "label": "48/10", "naklon": 5 }, + "3640": { "label": "48/11", "naklon": 5 }, + "3747": { "label": "48/12", "naklon": 5 }, + "3629": { "label": "48/13", "naklon": 5 }, + "4048": { "label": "48/14", "naklon": 5 }, + "4063": { "label": "48/15", "naklon": 5 }, + "4062": { "label": "48/16", "naklon": 5 }, + "4043": { "label": "48/17", "naklon": 5 }, + "4052": { "label": "48/18", "naklon": 5 }, + "4042": { "label": "48/19", "naklon": 5 }, + "4053": { "label": "48/20", "naklon": 5 }, + "4167": { "label": "50/15A", "naklon": null }, + "4159": { "label": "50/15B", "naklon": null }, + "4183": { "label": "50/1", "naklon": 0 }, + "4157": { "label": "50/2", "naklon": 0 }, + "4160": { "label": "50/3", "naklon": 0 }, + "4173": { "label": "50/4", "naklon": 0 }, + "4177": { "label": "50/5", "naklon": 0 }, + "4174": { "label": "50/6", "naklon": 0 }, + "4178": { "label": "50/7", "naklon": 0 }, + "4195": { "label": "50/8", "naklon": 0 }, + "4169": { "label": "50/9", "naklon": 0 }, + "4162": { "label": "50/10", "naklon": 0 }, + "4158": { "label": "50/11", "naklon": 0 }, + "4182": { "label": "50/12", "naklon": 0 }, + "4194": { "label": "50/13", "naklon": 0 }, + "4184": { "label": "50/14", "naklon": 0 }, + "4197": { "label": "50/16", "naklon": null }, + "4164": { "label": "50/17", "naklon": null }, + "3306": { "label": "50/18", "naklon": null }, + "4168": { "label": "50/19", "naklon": null }, + "4193": { "label": "50/20", "naklon": null }, + "4187": { "label": "50/21", "naklon": null }, + "4163": { "label": "50/22", "naklon": null }, + "4165": { "label": "50/23", "naklon": null }, + "4185": { "label": "50/24", "naklon": null }, + "3904": { "label": "50/25", "naklon": null }, + "2619": { "label": "53/1", "naklon": 0 }, + "2623": { "label": "53/2", "naklon": 0 }, + "2617": { "label": "53/3", "naklon": 0 }, + "2622": { "label": "53/4", "naklon": 0 }, + "2618": { "label": "53/5", "naklon": 0 }, + "2626": { "label": "53/6", "naklon": 0 }, + "2869": { "label": "53/7", "naklon": 0 }, + "2613": { "label": "53/8", "naklon": 0 }, + "2608": { "label": "53/9", "naklon": 0 }, + "2611": { "label": "53/10", "naklon": 0 }, + "2598": { "label": "53/11", "naklon": 0 }, + "3528": { "label": "53/12", "naklon": 0 }, + "3545": { "label": "53/13", "naklon": 0 }, + "2620": { "label": "53/14", "naklon": 0 }, + "2612": { "label": "53/15", "naklon": 0 }, + "2615": { "label": "53/16", "naklon": 0 }, + "3722": { "label": "53/17", "naklon": 0 }, + "2624": { "label": "53/18", "naklon": 0 }, + "2609": { "label": "53/19", "naklon": 0 }, + "2625": { "label": "53/20", "naklon": 0 }, + "2602": { "label": "53/21", "naklon": 0 }, + "2610": { "label": "53/22", "naklon": 0 }, + "2599": { "label": "53/23", "naklon": 0 }, + "2605": { "label": "53/24", "naklon": 0 }, + "2593": { "label": "53/25", "naklon": 0 }, + "3074": { "label": "53/26", "naklon": 0 }, + "2740": { "label": "53/27", "naklon": 0 }, + "2614": { "label": "53/28", "naklon": 0 }, + "2601": { "label": "53/29", "naklon": 0 }, + "4196": { "label": "53/30", "naklon": 0 }, + "2607": { "label": "53/31", "naklon": 0 }, + "2582": { "label": "53/32", "naklon": 0 }, + "2594": { "label": "53/33", "naklon": 0 }, + "2589": { "label": "53/34", "naklon": 0 }, + "2596": { "label": "53/35", "naklon": 0 }, + "2603": { "label": "53/36", "naklon": 0 }, + "2597": { "label": "53/37", "naklon": 0 }, + "2590": { "label": "53/38", "naklon": 0 }, + "2581": { "label": "53/39", "naklon": 0 }, + "2583": { "label": "53/40", "naklon": 0 }, + "2580": { "label": "53/41", "naklon": 0 }, + "2579": { "label": "53/42", "naklon": 0 }, + "2797": { "label": "53/43", "naklon": 0 }, + "2577": { "label": "53/44", "naklon": 0 }, + "2586": { "label": "53/45", "naklon": 0 }, + "2588": { "label": "53/46", "naklon": 0 }, + "2591": { "label": "53/47", "naklon": 0 }, + "2592": { "label": "53/48", "naklon": 0 }, + "2573": { "label": "53/49", "naklon": 0 }, + "2595": { "label": "53/50", "naklon": 0 }, + "2587": { "label": "53/51", "naklon": 0 }, + "2578": { "label": "53/52", "naklon": 0 }, + "2574": { "label": "53/53", "naklon": 0 }, + "2571": { "label": "53/54", "naklon": 0 }, + "2570": { "label": "53/55", "naklon": 0 }, + "2576": { "label": "53/56", "naklon": 0 }, + "2881": { "label": "53/57", "naklon": 0 }, + "2575": { "label": "53/58", "naklon": 0 }, + "2572": { "label": "53/59", "naklon": 0 }, + "2569": { "label": "53/60", "naklon": 0 }, + "4324": { "label": "55/1", "naklon": 0 }, + "4319": { "label": "55/2", "naklon": 0 }, + "4327": { "label": "55/3", "naklon": 0 }, + "4333": { "label": "55/4", "naklon": 0 }, + "4332": { "label": "55/5", "naklon": 0 }, + "4320": { "label": "55/6", "naklon": 0 }, + "4317": { "label": "55/7", "naklon": 0 }, + "4318": { "label": "55/8", "naklon": 0 }, + "4328": { "label": "55/9", "naklon": 0 }, + "4323": { "label": "55/10", "naklon": 0 }, + "4325": { "label": "55/11", "naklon": 0 }, + "4326": { "label": "55/12", "naklon": 0 }, + "4316": { "label": "55/13", "naklon": 0 }, + "4322": { "label": "55/14", "naklon": 0 }, + "4331": { "label": "55/15", "naklon": 0 }, + "4321": { "label": "55/16", "naklon": 0 }, + "4315": { "label": "55/17", "naklon": 0 }, + "4329": { "label": "55/18", "naklon": 0 }, + "4334": { "label": "55/19", "naklon": 0 }, + "4330": { "label": "55/20", "naklon": 0 } +}; + + +let svetlaSorted = [{ "label": "1/3A", "node": 3993, "naklon": 0 }, +{ "label": "1/3B", "node": 3989, "naklon": 15 }, +{ "label": "1/1", "node": 3976, "naklon": 0 }, +{ "label": "1/2", "node": 4181, "naklon": 0 }, +{ "label": "1/4", "node": 4376, "naklon": 15 }, +{ "label": "1/5", "node": 3868, "naklon": 15 }, +{ "label": "1/6", "node": 3728, "naklon": 15 }, +{ "label": "1/7", "node": 3730, "naklon": 0 }, +{ "label": "1/8", "node": 4374, "naklon": 0 }, +{ "label": "1/9", "node": 3718, "naklon": 15 }, +{ "label": "1/10", "node": 4375, "naklon": 15 }, +{ "label": "1/11", "node": 4172, "naklon": 15 }, +{ "label": "1/12", "node": 4176, "naklon": 15 }, +{ "label": "2/1", "node": 3800, "naklon": 5 }, +{ "label": "2/2", "node": 3823, "naklon": 5 }, +{ "label": "2/3", "node": 3905, "naklon": 5 }, +{ "label": "2/4", "node": 3803, "naklon": 5 }, +{ "label": "2/5", "node": 3817, "naklon": 5 }, +{ "label": "2/6", "node": 3818, "naklon": 5 }, +{ "label": "2/7", "node": 3811, "naklon": 5 }, +{ "label": "2/8", "node": 3915, "naklon": 5 }, +{ "label": "2/9", "node": 3843, "naklon": 10 }, +{ "label": "2/10", "node": 3827, "naklon": 10 }, +{ "label": "2/11", "node": 4220, "naklon": 10 }, +{ "label": "2/12", "node": 3826, "naklon": 10 }, +{ "label": "2/13", "node": 3834, "naklon": 10 }, +{ "label": "2/14", "node": 3838, "naklon": 10 }, +{ "label": "2/15", "node": 2823, "naklon": 10 }, +{ "label": "2/16", "node": 3750, "naklon": 10 }, +{ "label": "2/17", "node": 3378, "naklon": 0 }, +{ "label": "2/18", "node": 3376, "naklon": 0 }, +{ "label": "2/19", "node": 3379, "naklon": 0 }, +{ "label": "2/20", "node": 3285, "naklon": 0 }, +{ "label": "2/21", "node": 3382, "naklon": 0 }, +{ "label": "2/22", "node": 3383, "naklon": 0 }, +{ "label": "2/24", "node": 3375, "naklon": 0 }, +{ "label": "2/25", "node": 3381, "naklon": 0 }, +{ "label": "2/26", "node": 3380, "naklon": 0 }, +{ "label": "2/27", "node": 3828, "naklon": 10 }, +{ "label": "2/28", "node": 3377, "naklon": 0 }, +{ "label": "7/1", "node": 3591, "naklon": 0 }, +{ "label": "7/2", "node": 3587, "naklon": 0 }, +{ "label": "7/3", "node": 3468, "naklon": 0 }, +{ "label": "7/4", "node": 3466, "naklon": 0 }, +{ "label": "7/5", "node": 3474, "naklon": 0 }, +{ "label": "7/6", "node": 3481, "naklon": 0 }, +{ "label": "7/7", "node": 3589, "naklon": 0 }, +{ "label": "7/8", "node": 3472, "naklon": 0 }, +{ "label": "7/9", "node": 3473, "naklon": 0 }, +{ "label": "7/10", "node": 3584, "naklon": 0 }, +{ "label": "7/11", "node": 3571, "naklon": 0 }, +{ "label": "7/12", "node": 3476, "naklon": 0 }, +{ "label": "7/13", "node": 3590, "naklon": 0 }, +{ "label": "7/14", "node": 3478, "naklon": 0 }, +{ "label": "7/15", "node": 3471, "naklon": 0 }, +{ "label": "7/16", "node": 3467, "naklon": 0 }, +{ "label": "7/17", "node": 3479, "naklon": 0 }, +{ "label": "7/18", "node": 3480, "naklon": 0 }, +{ "label": "7/19", "node": 3477, "naklon": 0 }, +{ "label": "12/1", "node": 3362, "naklon": 0 }, +{ "label": "12/2", "node": 3355, "naklon": 0 }, +{ "label": "12/3", "node": 3356, "naklon": 0 }, +{ "label": "12/4", "node": 3349, "naklon": 0 }, +{ "label": "12/5", "node": 3357, "naklon": 0 }, +{ "label": "12/6", "node": 3350, "naklon": 0 }, +{ "label": "12/7", "node": 3353, "naklon": 0 }, +{ "label": "12/8", "node": 3539, "naklon": 0 }, +{ "label": "12/9", "node": 3050, "naklon": 0 }, +{ "label": "12/10", "node": 3361, "naklon": 0 }, +{ "label": "12/11", "node": 3360, "naklon": 0 }, +{ "label": "12/12", "node": 3358, "naklon": 0 }, +{ "label": "12/13", "node": 3541, "naklon": 0 }, +{ "label": "12/14", "node": 3551, "naklon": 0 }, +{ "label": "12/15", "node": 3514, "naklon": 0 }, +{ "label": "12/16", "node": 3547, "naklon": 0 }, +{ "label": "12/17", "node": 3562, "naklon": 0 }, +{ "label": "12/18", "node": 3525, "naklon": 0 }, +{ "label": "12/19", "node": 3558, "naklon": 0 }, +{ "label": "12/20", "node": 3511, "naklon": 0 }, +{ "label": "12/21", "node": 3058, "naklon": 0 }, +{ "label": "12/22", "node": 3062, "naklon": 0 }, +{ "label": "12/23", "node": 3070, "naklon": 0 }, +{ "label": "12/24", "node": 3447, "naklon": 0 }, +{ "label": "12/25", "node": 3056, "naklon": 0 }, +{ "label": "12/26", "node": 3057, "naklon": 0 }, +{ "label": "12/27", "node": 3071, "naklon": 0 }, +{ "label": "12/28", "node": 3061, "naklon": 0 }, +{ "label": "12/29", "node": 3069, "naklon": 0 }, +{ "label": "12/30", "node": 3077, "naklon": 0 }, +{ "label": "12/31", "node": 3080, "naklon": 0 }, +{ "label": "12/32", "node": 3081, "naklon": 0 }, +{ "label": "12/33", "node": 3078, "naklon": 0 }, +{ "label": "12/34", "node": 4037, "naklon": 0 }, +{ "label": "12/35", "node": 3067, "naklon": 0 }, +{ "label": "12/36", "node": 3051, "naklon": 0 }, +{ "label": "12/37", "node": 2924, "naklon": 0 }, +{ "label": "12/38", "node": 3060, "naklon": 0 }, +{ "label": "12/39", "node": 3073, "naklon": 0 }, +{ "label": "12/40", "node": 3469, "naklon": 0 }, +{ "label": "12/41", "node": 2923, "naklon": 0 }, +{ "label": "12/42", "node": 2925, "naklon": 0 }, +{ "label": "12/43", "node": 3359, "naklon": 0 }, +{ "label": "12/44", "node": 3055, "naklon": 0 }, +{ "label": "12/45", "node": 2922, "naklon": 0 }, +{ "label": "12/46", "node": 3084, "naklon": 0 }, +{ "label": "12/47", "node": 3064, "naklon": 0 }, +{ "label": "12/48", "node": 3066, "naklon": 0 }, +{ "label": "12/49", "node": 3072, "naklon": 0 }, +{ "label": "13/13A", "node": 3415, "naklon": 0 }, +{ "label": "13/13B", "node": 3409, "naklon": 0 }, +{ "label": "13/13C", "node": 3399, "naklon": 0 }, +{ "label": "13/29A", "node": 3410, "naklon": 0 }, +{ "label": "13/29B", "node": 3407, "naklon": 0 }, +{ "label": "13/34A", "node": 3405, "naklon": 0 }, +{ "label": "13/34B", "node": 3404, "naklon": 0 }, +{ "label": "13/45A", "node": 3392, "naklon": 0 }, +{ "label": "13/45B", "node": 3386, "naklon": 0 }, +{ "label": "13/60A", "node": 3303, "naklon": 3 }, +{ "label": "13/60B", "node": 3302, "naklon": 3 }, +{ "label": "13/70A", "node": 3319, "naklon": 6 }, +{ "label": "13/70B", "node": 3317, "naklon": 6 }, +{ "label": "13/70C", "node": 3326, "naklon": 6 }, +{ "label": "13/73A", "node": 3351, "naklon": 6 }, +{ "label": "13/73B", "node": 3313, "naklon": 6 }, +{ "label": "13/83A", "node": 3316, "naklon": 0 }, +{ "label": "13/83B", "node": 3320, "naklon": 0 }, +{ "label": "13/95A", "node": 3336, "naklon": 0 }, +{ "label": "13/95B", "node": 3323, "naklon": 0 }, +{ "label": "13/98A", "node": 3339, "naklon": 0 }, +{ "label": "13/98B", "node": 3333, "naklon": 0 }, +{ "label": "13/1", "node": 3425, "naklon": 0 }, +{ "label": "13/2", "node": 3419, "naklon": 0 }, +{ "label": "13/3", "node": 3416, "naklon": 0 }, +{ "label": "13/4", "node": 3332, "naklon": 0 }, +{ "label": "13/5", "node": 3422, "naklon": 0 }, +{ "label": "13/6", "node": 3417, "naklon": 0 }, +{ "label": "13/7", "node": 3418, "naklon": 0 }, +{ "label": "13/8", "node": 3424, "naklon": 0 }, +{ "label": "13/9", "node": 3334, "naklon": 0 }, +{ "label": "13/10", "node": 4363, "naklon": 0 }, +{ "label": "13/11", "node": 3423, "naklon": 0 }, +{ "label": "13/12", "node": 3406, "naklon": 0 }, +{ "label": "13/14", "node": 3411, "naklon": 0 }, +{ "label": "13/15", "node": 3412, "naklon": 0 }, +{ "label": "13/16", "node": 3413, "naklon": 0 }, +{ "label": "13/17", "node": 3414, "naklon": 0 }, +{ "label": "13/18", "node": 3391, "naklon": 0 }, +{ "label": "13/19", "node": 3370, "naklon": 0 }, +{ "label": "13/20", "node": 3369, "naklon": 0 }, +{ "label": "13/21", "node": 3408, "naklon": 0 }, +{ "label": "13/22", "node": 3393, "naklon": 0 }, +{ "label": "13/23", "node": 3128, "naklon": 0 }, +{ "label": "13/24", "node": 3197, "naklon": 0 }, +{ "label": "13/25", "node": 4364, "naklon": 0 }, +{ "label": "13/26", "node": 3155, "naklon": 0 }, +{ "label": "13/27", "node": 3196, "naklon": 0 }, +{ "label": "13/28", "node": 3144, "naklon": 0 }, +{ "label": "13/30", "node": 3150, "naklon": 0 }, +{ "label": "13/31", "node": 3390, "naklon": 0 }, +{ "label": "13/32", "node": 3401, "naklon": 0 }, +{ "label": "13/33", "node": 3275, "naklon": 0 }, +{ "label": "13/35", "node": 3371, "naklon": 0 }, +{ "label": "13/36", "node": 3389, "naklon": 0 }, +{ "label": "13/37", "node": 3388, "naklon": 0 }, +{ "label": "13/38", "node": 3365, "naklon": 0 }, +{ "label": "13/39", "node": 3363, "naklon": 0 }, +{ "label": "13/40", "node": 3397, "naklon": 0 }, +{ "label": "13/40/1", "node": 3567, "naklon": 0 }, +{ "label": "13/41", "node": 3387, "naklon": 0 }, +{ "label": "13/42", "node": 3403, "naklon": 0 }, +{ "label": "13/43", "node": 3147, "naklon": 0 }, +{ "label": "13/44", "node": 3141, "naklon": 0 }, +{ "label": "13/46", "node": 3364, "naklon": 0 }, +{ "label": "13/47", "node": 3367, "naklon": 0 }, +{ "label": "13/48", "node": 3368, "naklon": 0 }, +{ "label": "13/49", "node": 3402, "naklon": 0 }, +{ "label": "13/50", "node": 3366, "naklon": 0 }, +{ "label": "13/51", "node": 3395, "naklon": 0 }, +{ "label": "13/52", "node": 3372, "naklon": 0 }, +{ "label": "13/53", "node": 3394, "naklon": 0 }, +{ "label": "13/54", "node": 3308, "naklon": 0 }, +{ "label": "13/54/1", "node": 3847, "naklon": 0 }, +{ "label": "13/55", "node": 3312, "naklon": 3 }, +{ "label": "13/56", "node": 3309, "naklon": 3 }, +{ "label": "13/57", "node": 3311, "naklon": 3 }, +{ "label": "13/58", "node": 3310, "naklon": 3 }, +{ "label": "13/59", "node": 4365, "naklon": 3 }, +{ "label": "13/60/1", "node": 4093, "naklon": 3 }, +{ "label": "13/61", "node": 3304, "naklon": 3 }, +{ "label": "13/62", "node": 3307, "naklon": 3 }, +{ "label": "13/63", "node": 3271, "naklon": 3 }, +{ "label": "13/64", "node": 3301, "naklon": 3 }, +{ "label": "13/65", "node": 4366, "naklon": 3 }, +{ "label": "13/66", "node": 3300, "naklon": 3 }, +{ "label": "13/67", "node": 3185, "naklon": 0 }, +{ "label": "13/68", "node": 3184, "naklon": 0 }, +{ "label": "13/69", "node": 3188, "naklon": 0 }, +{ "label": "13/71", "node": 3343, "naklon": 6 }, +{ "label": "13/71/1", "node": 3819, "naklon": 6 }, +{ "label": "13/71/2", "node": 3880, "naklon": 6 }, +{ "label": "13/72", "node": 3348, "naklon": 6 }, +{ "label": "13/74", "node": 3344, "naklon": 6 }, +{ "label": "13/75", "node": 3346, "naklon": 6 }, +{ "label": "13/75/1", "node": 3597, "naklon": 6 }, +{ "label": "13/76", "node": 3345, "naklon": 6 }, +{ "label": "13/77", "node": 3322, "naklon": 0 }, +{ "label": "13/78", "node": 3325, "naklon": 0 }, +{ "label": "13/78/1", "node": 4310, "naklon": 0 }, +{ "label": "13/79", "node": 3315, "naklon": 0 }, +{ "label": "13/80", "node": 3328, "naklon": 0 }, +{ "label": "13/81", "node": 3321, "naklon": 0 }, +{ "label": "13/82", "node": 3324, "naklon": 0 }, +{ "label": "13/84", "node": 3140, "naklon": 0 }, +{ "label": "13/85", "node": 3153, "naklon": 0 }, +{ "label": "13/86", "node": 3145, "naklon": 0 }, +{ "label": "13/87", "node": 3134, "naklon": 0 }, +{ "label": "13/88", "node": 3151, "naklon": 0 }, +{ "label": "13/89", "node": 3143, "naklon": 0 }, +{ "label": "13/90", "node": 3318, "naklon": 0 }, +{ "label": "13/91", "node": 3347, "naklon": 0 }, +{ "label": "13/94", "node": 3314, "naklon": 0 }, +{ "label": "13/96", "node": 3331, "naklon": 0 }, +{ "label": "13/97", "node": 3327, "naklon": 0 }, +{ "label": "13/99", "node": 3329, "naklon": 0 }, +{ "label": "13/100", "node": 3337, "naklon": 0 }, +{ "label": "13/101", "node": 3330, "naklon": 0 }, +{ "label": "13/102", "node": 3335, "naklon": 0 }, +{ "label": "13/103", "node": 3420, "naklon": 0 }, +{ "label": "13/104", "node": 3421, "naklon": 0 }, +{ "label": "13/105", "node": 4361, "naklon": 0 }, +{ "label": "13/106", "node": 4362, "naklon": 0 }, +{ "label": "13/107", "node": 3526, "naklon": 0 }, +{ "label": "13/108", "node": 4424, "naklon": null }, +{ "label": "13/109", "node": 3561, "naklon": null }, +{ "label": "13/110", "node": 3527, "naklon": null }, +{ "label": "13/111", "node": 3521, "naklon": null }, +{ "label": "13/112", "node": 3552, "naklon": null }, +{ "label": "13/113", "node": 3544, "naklon": null }, +{ "label": "13/114", "node": 3534, "naklon": null }, +{ "label": "13/115", "node": 3516, "naklon": null }, +{ "label": "13/116", "node": 3513, "naklon": null }, +{ "label": "13/117", "node": 3565, "naklon": null }, +{ "label": "13/118", "node": 3866, "naklon": null }, +{ "label": "14/1", "node": 3136, "naklon": 0 }, +{ "label": "14/2", "node": 3137, "naklon": 0 }, +{ "label": "14/3", "node": 3135, "naklon": 0 }, +{ "label": "14/4", "node": 3149, "naklon": 0 }, +{ "label": "14/5", "node": 3142, "naklon": 0 }, +{ "label": "14/6", "node": 3342, "naklon": 0 }, +{ "label": "14/7", "node": 3340, "naklon": 0 }, +{ "label": "14/8", "node": 3152, "naklon": 0 }, +{ "label": "14/9", "node": 3886, "naklon": 0 }, +{ "label": "14/10", "node": 3341, "naklon": null }, +{ "label": "14/11", "node": 3352, "naklon": null }, +{ "label": "15/1", "node": 3396, "naklon": 5 }, +{ "label": "15/2", "node": 2784, "naklon": 5 }, +{ "label": "15/3", "node": 2788, "naklon": 5 }, +{ "label": "15/4", "node": 2801, "naklon": 5 }, +{ "label": "15/5", "node": 2815, "naklon": 5 }, +{ "label": "15/6", "node": 2829, "naklon": 5 }, +{ "label": "15/7", "node": 2796, "naklon": 5 }, +{ "label": "15/8", "node": 2803, "naklon": 5 }, +{ "label": "15/8/1", "node": 4304, "naklon": 5 }, +{ "label": "15/8/2", "node": 4311, "naklon": 5 }, +{ "label": "15/9", "node": 2821, "naklon": 5 }, +{ "label": "15/10", "node": 3400, "naklon": 5 }, +{ "label": "15/11", "node": 2799, "naklon": 5 }, +{ "label": "15/12", "node": 2804, "naklon": 5 }, +{ "label": "15/12/1", "node": 4303, "naklon": 5 }, +{ "label": "15/12/2", "node": 4309, "naklon": 5 }, +{ "label": "15/13", "node": 2806, "naklon": 5 }, +{ "label": "15/14", "node": 2787, "naklon": 5 }, +{ "label": "15/15", "node": 2809, "naklon": 5 }, +{ "label": "15/16", "node": 2814, "naklon": 0 }, +{ "label": "15/17", "node": 3934, "naklon": 0 }, +{ "label": "15/18", "node": 3192, "naklon": 0 }, +{ "label": "15/19", "node": 2812, "naklon": 0 }, +{ "label": "15/20", "node": 4070, "naklon": 0 }, +{ "label": "15/21", "node": 2826, "naklon": 0 }, +{ "label": "15/22", "node": 2808, "naklon": 3 }, +{ "label": "15/23", "node": 2795, "naklon": 3 }, +{ "label": "15/24", "node": 2807, "naklon": 3 }, +{ "label": "15/25", "node": 2831, "naklon": 0 }, +{ "label": "15/26", "node": 2862, "naklon": null }, +{ "label": "15/27", "node": 2861, "naklon": 0 }, +{ "label": "15/28", "node": 2866, "naklon": 0 }, +{ "label": "15/28/1", "node": 3546, "naklon": 0 }, +{ "label": "15/29", "node": 4146, "naklon": 0 }, +{ "label": "15/29/1", "node": 3001, "naklon": 0 }, +{ "label": "15/30", "node": 2835, "naklon": 0 }, +{ "label": "15/31", "node": 2874, "naklon": 0 }, +{ "label": "15/32", "node": 2852, "naklon": 0 }, +{ "label": "15/33", "node": 2851, "naklon": 0 }, +{ "label": "15/33/1", "node": 3560, "naklon": 0 }, +{ "label": "15/34", "node": 2858, "naklon": 0 }, +{ "label": "15/34/1", "node": 4306, "naklon": 0 }, +{ "label": "15/35", "node": 2856, "naklon": 0 }, +{ "label": "15/36", "node": 2847, "naklon": 0 }, +{ "label": "15/36/1", "node": 3556, "naklon": 0 }, +{ "label": "15/37", "node": 3950, "naklon": 0 }, +{ "label": "15/38", "node": 2848, "naklon": 0 }, +{ "label": "15/39", "node": 2863, "naklon": 0 }, +{ "label": "15/39/1", "node": 4313, "naklon": 0 }, +{ "label": "15/40", "node": 2873, "naklon": 0 }, +{ "label": "15/40/1", "node": 2984, "naklon": 0 }, +{ "label": "15/41", "node": 2854, "naklon": 0 }, +{ "label": "15/42", "node": 2859, "naklon": 0 }, +{ "label": "15/43", "node": 2872, "naklon": 0 }, +{ "label": "15/44", "node": 2849, "naklon": 0 }, +{ "label": "15/45", "node": 2864, "naklon": 0 }, +{ "label": "15/46", "node": 3553, "naklon": null }, +{ "label": "15/47", "node": 3021, "naklon": null }, +{ "label": "15/47/1", "node": 3008, "naklon": null }, +{ "label": "15/48", "node": 3017, "naklon": null }, +{ "label": "15/49", "node": 3014, "naklon": null }, +{ "label": "15/50", "node": 2981, "naklon": null }, +{ "label": "15/51", "node": 3020, "naklon": null }, +{ "label": "15/52", "node": 3027, "naklon": null }, +{ "label": "15/53", "node": 3006, "naklon": null }, +{ "label": "15/54", "node": 3012, "naklon": null }, +{ "label": "15/55", "node": 2738, "naklon": 0 }, +{ "label": "15/56", "node": 2725, "naklon": 0 }, +{ "label": "15/57", "node": 3016, "naklon": null }, +{ "label": "15/58", "node": 3005, "naklon": null }, +{ "label": "15/58/1", "node": 3009, "naklon": null }, +{ "label": "15/59", "node": 3010, "naklon": 0 }, +{ "label": "15/59/1", "node": 3538, "naklon": 0 }, +{ "label": "15/59/2", "node": 4145, "naklon": 0 }, +{ "label": "15/60", "node": 2713, "naklon": 0 }, +{ "label": "15/61", "node": 2789, "naklon": 0 }, +{ "label": "15/62", "node": 2736, "naklon": 0 }, +{ "label": "15/63", "node": 2739, "naklon": 0 }, +{ "label": "15/64", "node": 4346, "naklon": 0 }, +{ "label": "15/65", "node": 2731, "naklon": 0 }, +{ "label": "15/66", "node": 2818, "naklon": 0 }, +{ "label": "15/66/1", "node": 3557, "naklon": 0 }, +{ "label": "15/67", "node": 2822, "naklon": 0 }, +{ "label": "15/68", "node": 2833, "naklon": 0 }, +{ "label": "15/69", "node": 2834, "naklon": 0 }, +{ "label": "15/70", "node": 3097, "naklon": 0 }, +{ "label": "15/71", "node": 2824, "naklon": 0 }, +{ "label": "15/72", "node": 2828, "naklon": 0 }, +{ "label": "15/73", "node": 2600, "naklon": 0 }, +{ "label": "15/73/1", "node": 4314, "naklon": 0 }, +{ "label": "15/74", "node": 2832, "naklon": 0 }, +{ "label": "15/75", "node": 4360, "naklon": 0 }, +{ "label": "15/76", "node": 2846, "naklon": 0 }, +{ "label": "15/77", "node": 2584, "naklon": 0 }, +{ "label": "15/78", "node": 2843, "naklon": 0 }, +{ "label": "15/78/1", "node": 4308, "naklon": 0 }, +{ "label": "15/79", "node": 4144, "naklon": null }, +{ "label": "15/80", "node": 2844, "naklon": 0 }, +{ "label": "15/81", "node": 2842, "naklon": 0 }, +{ "label": "15/82", "node": 2838, "naklon": 0 }, +{ "label": "15/83", "node": 2837, "naklon": null }, +{ "label": "15/83/1", "node": 3555, "naklon": null }, +{ "label": "15/84", "node": 2839, "naklon": 0 }, +{ "label": "15/85", "node": 2830, "naklon": 0 }, +{ "label": "15/86", "node": 4066, "naklon": 0 }, +{ "label": "15/87", "node": 2836, "naklon": 0 }, +{ "label": "15/88", "node": 2911, "naklon": 0 }, +{ "label": "15/89", "node": 2825, "naklon": 0 }, +{ "label": "15/90", "node": 2811, "naklon": 0 }, +{ "label": "15/94", "node": 3740, "naklon": 15 }, +{ "label": "15/95", "node": 2734, "naklon": 15 }, +{ "label": "15/96", "node": 3105, "naklon": 15 }, +{ "label": "15/97", "node": 2732, "naklon": 15 }, +{ "label": "15/98", "node": 2727, "naklon": 15 }, +{ "label": "15/99", "node": 2735, "naklon": 15 }, +{ "label": "15/100", "node": 3926, "naklon": 15 }, +{ "label": "15/101", "node": 2918, "naklon": 0 }, +{ "label": "15/102", "node": 2705, "naklon": 10 }, +{ "label": "15/103", "node": 2708, "naklon": 10 }, +{ "label": "15/104", "node": 2721, "naklon": 10 }, +{ "label": "15/105", "node": 2719, "naklon": 10 }, +{ "label": "15/106", "node": 2919, "naklon": 10 }, +{ "label": "15/107", "node": 3101, "naklon": 10 }, +{ "label": "15/108", "node": 2853, "naklon": 10 }, +{ "label": "15/109", "node": 2715, "naklon": 10 }, +{ "label": "15/110", "node": 2712, "naklon": 0 }, +{ "label": "15/111", "node": 2711, "naklon": 0 }, +{ "label": "15/112", "node": 2709, "naklon": 0 }, +{ "label": "15/113", "node": 2710, "naklon": 0 }, +{ "label": "15/114", "node": 2907, "naklon": 0 }, +{ "label": "15/115", "node": 2906, "naklon": 0 }, +{ "label": "15/116", "node": 2908, "naklon": 0 }, +{ "label": "15/117", "node": 2901, "naklon": 0 }, +{ "label": "15/118", "node": 2913, "naklon": 0 }, +{ "label": "15/119", "node": 3656, "naklon": 0 }, +{ "label": "15/120", "node": 2781, "naklon": 0 }, +{ "label": "15/121", "node": 2802, "naklon": 0 }, +{ "label": "15/122", "node": 2791, "naklon": 0 }, +{ "label": "15/123", "node": 2783, "naklon": 0 }, +{ "label": "15/124", "node": 2794, "naklon": 0 }, +{ "label": "15/125", "node": 3139, "naklon": 0 }, +{ "label": "15/126", "node": 3229, "naklon": 5 }, +{ "label": "15/127", "node": 3239, "naklon": 5 }, +{ "label": "15/128", "node": 3230, "naklon": 5 }, +{ "label": "15/129", "node": 4016, "naklon": null }, +{ "label": "16/16A", "node": 3608, "naklon": 0 }, +{ "label": "16/16B", "node": 4151, "naklon": 0 }, +{ "label": "16/1", "node": 3710, "naklon": 0 }, +{ "label": "16/2", "node": 3726, "naklon": 0 }, +{ "label": "16/3", "node": 3743, "naklon": 0 }, +{ "label": "16/4", "node": 3724, "naklon": 0 }, +{ "label": "16/5", "node": 3712, "naklon": 0 }, +{ "label": "16/6", "node": 3739, "naklon": 0 }, +{ "label": "16/7", "node": 3742, "naklon": 0 }, +{ "label": "16/8", "node": 3731, "naklon": 0 }, +{ "label": "16/9", "node": 3727, "naklon": 0 }, +{ "label": "16/10", "node": 3729, "naklon": 0 }, +{ "label": "16/11", "node": 3736, "naklon": 0 }, +{ "label": "16/12", "node": 3713, "naklon": 0 }, +{ "label": "16/13", "node": 3715, "naklon": 0 }, +{ "label": "16/14", "node": 3733, "naklon": 0 }, +{ "label": "16/15", "node": 3732, "naklon": 0 }, +{ "label": "16/17", "node": 3634, "naklon": 0 }, +{ "label": "16/18", "node": 3610, "naklon": 0 }, +{ "label": "16/19", "node": 3626, "naklon": 0 }, +{ "label": "16/20", "node": 3618, "naklon": 0 }, +{ "label": "16/21", "node": 3619, "naklon": 0 }, +{ "label": "16/22", "node": 3628, "naklon": 0 }, +{ "label": "16/23", "node": 3615, "naklon": 0 }, +{ "label": "16/24", "node": 3609, "naklon": 0 }, +{ "label": "16/25", "node": 3606, "naklon": 0 }, +{ "label": "16/26", "node": 3624, "naklon": 0 }, +{ "label": "16/27", "node": 3627, "naklon": 0 }, +{ "label": "16/28", "node": 3607, "naklon": 0 }, +{ "label": "16/29", "node": 4370, "naklon": 0 }, +{ "label": "16/30", "node": 3692, "naklon": 0 }, +{ "label": "16/31", "node": 3614, "naklon": 0 }, +{ "label": "16/32", "node": 3623, "naklon": 0 }, +{ "label": "16/33", "node": 4373, "naklon": 0 }, +{ "label": "16/34", "node": 3620, "naklon": 0 }, +{ "label": "16/35", "node": 3685, "naklon": 0 }, +{ "label": "16/36", "node": 3616, "naklon": 0 }, +{ "label": "16/37", "node": 3686, "naklon": 0 }, +{ "label": "16/38", "node": 3688, "naklon": 0 }, +{ "label": "16/39", "node": 3684, "naklon": 0 }, +{ "label": "16/40", "node": 3825, "naklon": 0 }, +{ "label": "16/41", "node": 3865, "naklon": 0 }, +{ "label": "16/42", "node": 3824, "naklon": 0 }, +{ "label": "16/43", "node": 3871, "naklon": 0 }, +{ "label": "16/44", "node": 3801, "naklon": 0 }, +{ "label": "16/45", "node": 3862, "naklon": 0 }, +{ "label": "16/46", "node": 3876, "naklon": 0 }, +{ "label": "16/47", "node": 3861, "naklon": 0 }, +{ "label": "16/48", "node": 4215, "naklon": 0 }, +{ "label": "16/49", "node": 3605, "naklon": 10 }, +{ "label": "16/50", "node": 3603, "naklon": 10 }, +{ "label": "16/51", "node": 3592, "naklon": 10 }, +{ "label": "16/52", "node": 3598, "naklon": 10 }, +{ "label": "16/53", "node": 3594, "naklon": 10 }, +{ "label": "16/54", "node": 3593, "naklon": 10 }, +{ "label": "16/55", "node": 3630, "naklon": 10 }, +{ "label": "16/56", "node": 3763, "naklon": 10 }, +{ "label": "16/57", "node": 3746, "naklon": 10 }, +{ "label": "16/58", "node": 3699, "naklon": 0 }, +{ "label": "16/59", "node": 3698, "naklon": 0 }, +{ "label": "16/60", "node": 3709, "naklon": null }, +{ "label": "16/61", "node": 3708, "naklon": 0 }, +{ "label": "16/62", "node": 3703, "naklon": null }, +{ "label": "16/63", "node": 3700, "naklon": 0 }, +{ "label": "16/64", "node": 3701, "naklon": null }, +{ "label": "16/65", "node": 3704, "naklon": 0 }, +{ "label": "16/66", "node": 3707, "naklon": null }, +{ "label": "16/67", "node": 3810, "naklon": 0 }, +{ "label": "16/68", "node": 4208, "naklon": null }, +{ "label": "16/69", "node": 3867, "naklon": 0 }, +{ "label": "16/70", "node": 4372, "naklon": null }, +{ "label": "16/71", "node": 3881, "naklon": 0 }, +{ "label": "16/72", "node": 4204, "naklon": null }, +{ "label": "16/73", "node": 3869, "naklon": 0 }, +{ "label": "16/74", "node": 4202, "naklon": null }, +{ "label": "16/75", "node": 3830, "naklon": 0 }, +{ "label": "16/76", "node": 3870, "naklon": null }, +{ "label": "16/77", "node": 3964, "naklon": 0 }, +{ "label": "16/78", "node": 3849, "naklon": 0 }, +{ "label": "16/79", "node": 3694, "naklon": null }, +{ "label": "16/80", "node": 3717, "naklon": 0 }, +{ "label": "16/81", "node": 3877, "naklon": null }, +{ "label": "16/82", "node": 3755, "naklon": 0 }, +{ "label": "16/83", "node": 3725, "naklon": null }, +{ "label": "16/84", "node": 3716, "naklon": 0 }, +{ "label": "16/85", "node": 3696, "naklon": null }, +{ "label": "16/86", "node": 3702, "naklon": 0 }, +{ "label": "16/87", "node": 3706, "naklon": null }, +{ "label": "16/88", "node": 3850, "naklon": 0 }, +{ "label": "16/89", "node": 3848, "naklon": null }, +{ "label": "16/90", "node": 3737, "naklon": null }, +{ "label": "16/91", "node": 3705, "naklon": 0 }, +{ "label": "16/92", "node": 3723, "naklon": null }, +{ "label": "16/93", "node": 3842, "naklon": 0 }, +{ "label": "16/94", "node": 3735, "naklon": null }, +{ "label": "16/95", "node": 3719, "naklon": 0 }, +{ "label": "16/96", "node": 3697, "naklon": 0 }, +{ "label": "16/97", "node": 3711, "naklon": 0 }, +{ "label": "16/98", "node": 4107, "naklon": null }, +{ "label": "16/99", "node": 4112, "naklon": 5 }, +{ "label": "16/100", "node": 4106, "naklon": 5 }, +{ "label": "16/101", "node": 4111, "naklon": 5 }, +{ "label": "16/102", "node": 4091, "naklon": null }, +{ "label": "16/103", "node": 4104, "naklon": 5 }, +{ "label": "16/104", "node": 4094, "naklon": null }, +{ "label": "16/105", "node": 4089, "naklon": 5 }, +{ "label": "16/106", "node": 4095, "naklon": null }, +{ "label": "16/107", "node": 4102, "naklon": 5 }, +{ "label": "16/108", "node": 4105, "naklon": null }, +{ "label": "16/109", "node": 3859, "naklon": null }, +{ "label": "16/110", "node": 4090, "naklon": 5 }, +{ "label": "16/111", "node": 4110, "naklon": null }, +{ "label": "16/112", "node": 4097, "naklon": 5 }, +{ "label": "16/113", "node": 4099, "naklon": null }, +{ "label": "16/114", "node": 4096, "naklon": null }, +{ "label": "16/115", "node": 4101, "naklon": 5 }, +{ "label": "16/116", "node": 4109, "naklon": null }, +{ "label": "16/117", "node": 4092, "naklon": 5 }, +{ "label": "16/118", "node": 3631, "naklon": null }, +{ "label": "16/119", "node": 3632, "naklon": 0 }, +{ "label": "16/120", "node": 3641, "naklon": null }, +{ "label": "16/121", "node": 3638, "naklon": 0 }, +{ "label": "16/122", "node": 3637, "naklon": null }, +{ "label": "16/123", "node": 4142, "naklon": null }, +{ "label": "16/124", "node": 4147, "naklon": 5 }, +{ "label": "16/125", "node": 4139, "naklon": 5 }, +{ "label": "20/30A", "node": 3172, "naklon": 2 }, +{ "label": "20/30B", "node": 3164, "naklon": 2 }, +{ "label": "20/1", "node": 3247, "naklon": 10 }, +{ "label": "20/2", "node": 3296, "naklon": 10 }, +{ "label": "20/3", "node": 3246, "naklon": 10 }, +{ "label": "20/4", "node": 3270, "naklon": 10 }, +{ "label": "20/5", "node": 3294, "naklon": 10 }, +{ "label": "20/6", "node": 3298, "naklon": 10 }, +{ "label": "20/7", "node": 3297, "naklon": 10 }, +{ "label": "20/8", "node": 3293, "naklon": 10 }, +{ "label": "20/9", "node": 3299, "naklon": 10 }, +{ "label": "20/10", "node": 3295, "naklon": 10 }, +{ "label": "20/11", "node": 3244, "naklon": 10 }, +{ "label": "20/12", "node": 3249, "naklon": 10 }, +{ "label": "20/13", "node": 3268, "naklon": 10 }, +{ "label": "20/14", "node": 3245, "naklon": 10 }, +{ "label": "20/15", "node": 3278, "naklon": 10 }, +{ "label": "20/16", "node": 3280, "naklon": 10 }, +{ "label": "20/17", "node": 3292, "naklon": 10 }, +{ "label": "20/18", "node": 3287, "naklon": 10 }, +{ "label": "20/19", "node": 3282, "naklon": 10 }, +{ "label": "20/20", "node": 3273, "naklon": 0 }, +{ "label": "20/21", "node": 3157, "naklon": 0 }, +{ "label": "20/22", "node": 3283, "naklon": 0 }, +{ "label": "20/23", "node": 3159, "naklon": 0 }, +{ "label": "20/24", "node": 3289, "naklon": 0 }, +{ "label": "20/25", "node": 3163, "naklon": 0 }, +{ "label": "20/26", "node": 3126, "naklon": 0 }, +{ "label": "20/27", "node": 3171, "naklon": 0 }, +{ "label": "20/28", "node": 3162, "naklon": 0 }, +{ "label": "20/29", "node": 3279, "naklon": 10 }, +{ "label": "20/31", "node": 3173, "naklon": 0 }, +{ "label": "20/32", "node": 3127, "naklon": 0 }, +{ "label": "20/33", "node": 3131, "naklon": 0 }, +{ "label": "20/34", "node": 3129, "naklon": 0 }, +{ "label": "20/35", "node": 3276, "naklon": 2 }, +{ "label": "20/36", "node": 3290, "naklon": 2 }, +{ "label": "20/37", "node": 3132, "naklon": 0 }, +{ "label": "20/38", "node": 3138, "naklon": 0 }, +{ "label": "20/39", "node": 3272, "naklon": 0 }, +{ "label": "20/40", "node": 3291, "naklon": 0 }, +{ "label": "20/41", "node": 3277, "naklon": 10 }, +{ "label": "20/42", "node": 3286, "naklon": 10 }, +{ "label": "20/43", "node": 3281, "naklon": 10 }, +{ "label": "20/44", "node": 3288, "naklon": 10 }, +{ "label": "20/45", "node": 3284, "naklon": 10 }, +{ "label": "20/46", "node": 3167, "naklon": 10 }, +{ "label": "20/47", "node": 3872, "naklon": 0 }, +{ "label": "20/48", "node": 3124, "naklon": 0 }, +{ "label": "20/49", "node": 3133, "naklon": 0 }, +{ "label": "20/50", "node": 3158, "naklon": 0 }, +{ "label": "20/51", "node": 3169, "naklon": 0 }, +{ "label": "20/52", "node": 3146, "naklon": 0 }, +{ "label": "20/53", "node": 3160, "naklon": 0 }, +{ "label": "20/54", "node": 3248, "naklon": 0 }, +{ "label": "20/55", "node": 3156, "naklon": 0 }, +{ "label": "20/56", "node": 3161, "naklon": 0 }, +{ "label": "20/57", "node": 3170, "naklon": 0 }, +{ "label": "20/58", "node": 3168, "naklon": 0 }, +{ "label": "20/59", "node": 3125, "naklon": 0 }, +{ "label": "20/60", "node": 3166, "naklon": 0 }, +{ "label": "20/61", "node": 3130, "naklon": 0 }, +{ "label": "20/62", "node": 3563, "naklon": 0 }, +{ "label": "20/63", "node": 3550, "naklon": null }, +{ "label": "20/67", "node": 3269, "naklon": 0 }, +{ "label": "21/1", "node": 2921, "naklon": 0 }, +{ "label": "21/2", "node": 2707, "naklon": 0 }, +{ "label": "21/3", "node": 2723, "naklon": 0 }, +{ "label": "21/4", "node": 2716, "naklon": 0 }, +{ "label": "21/5", "node": 2717, "naklon": 0 }, +{ "label": "21/6", "node": 2720, "naklon": 0 }, +{ "label": "21/7", "node": 2722, "naklon": 0 }, +{ "label": "21/8", "node": 2718, "naklon": 0 }, +{ "label": "21/9", "node": 2724, "naklon": 0 }, +{ "label": "21/10", "node": 2742, "naklon": 0 }, +{ "label": "21/11", "node": 2743, "naklon": 0 }, +{ "label": "21/12", "node": 2733, "naklon": 0 }, +{ "label": "21/14", "node": 2903, "naklon": 0 }, +{ "label": "21/15", "node": 2917, "naklon": 0 }, +{ "label": "21/16", "node": 2897, "naklon": 0 }, +{ "label": "21/17", "node": 2914, "naklon": 0 }, +{ "label": "21/18", "node": 2898, "naklon": 0 }, +{ "label": "21/19", "node": 2773, "naklon": 0 }, +{ "label": "21/20", "node": 2895, "naklon": 0 }, +{ "label": "21/21", "node": 2896, "naklon": 0 }, +{ "label": "21/22", "node": 2771, "naklon": 0 }, +{ "label": "21/23", "node": 2772, "naklon": 0 }, +{ "label": "21/24", "node": 2793, "naklon": 0 }, +{ "label": "21/25", "node": 2902, "naklon": 0 }, +{ "label": "21/26", "node": 2910, "naklon": 0 }, +{ "label": "21/27", "node": 2909, "naklon": 0 }, +{ "label": "21/28", "node": 2920, "naklon": 0 }, +{ "label": "21/29", "node": 2916, "naklon": 0 }, +{ "label": "21/30", "node": 2904, "naklon": 0 }, +{ "label": "21/31", "node": 2915, "naklon": 0 }, +{ "label": "21/32", "node": 2905, "naklon": 0 }, +{ "label": "21/33", "node": 2900, "naklon": 0 }, +{ "label": "21/34", "node": 2899, "naklon": 0 }, +{ "label": "21/36", "node": 2741, "naklon": 0 }, +{ "label": "21/37", "node": 2714, "naklon": 0 }, +{ "label": "21/38", "node": 2701, "naklon": 0 }, +{ "label": "21/39", "node": 2703, "naklon": 0 }, +{ "label": "21/40", "node": 2704, "naklon": 0 }, +{ "label": "21/41", "node": 2702, "naklon": 0 }, +{ "label": "21/42", "node": 2706, "naklon": 0 }, +{ "label": "21/43", "node": 2776, "naklon": 0 }, +{ "label": "21/44", "node": 2770, "naklon": 0 }, +{ "label": "21/45", "node": 2786, "naklon": 0 }, +{ "label": "21/46", "node": 2779, "naklon": 0 }, +{ "label": "21/47", "node": 2782, "naklon": 0 }, +{ "label": "21/48", "node": 2785, "naklon": 0 }, +{ "label": "21/49", "node": 2769, "naklon": 0 }, +{ "label": "21/50", "node": 3354, "naklon": 0 }, +{ "label": "21/51", "node": 2778, "naklon": 0 }, +{ "label": "21/52", "node": 2775, "naklon": 0 }, +{ "label": "21/53", "node": 2780, "naklon": 0 }, +{ "label": "21/54", "node": 2790, "naklon": 0 }, +{ "label": "21/55", "node": 2792, "naklon": 0 }, +{ "label": "21/56", "node": 2774, "naklon": 0 }, +{ "label": "22/1", "node": 2630, "naklon": 0 }, +{ "label": "22/2", "node": 2631, "naklon": 0 }, +{ "label": "22/3", "node": 2632, "naklon": 0 }, +{ "label": "22/4", "node": 2633, "naklon": 0 }, +{ "label": "22/5", "node": 2634, "naklon": 0 }, +{ "label": "22/6", "node": 2636, "naklon": 0 }, +{ "label": "22/7", "node": 4367, "naklon": 0 }, +{ "label": "22/8", "node": 2637, "naklon": 0 }, +{ "label": "22/9", "node": 2638, "naklon": 0 }, +{ "label": "22/10", "node": 2639, "naklon": 0 }, +{ "label": "22/11", "node": 2640, "naklon": 0 }, +{ "label": "22/12", "node": 2641, "naklon": 0 }, +{ "label": "22/13", "node": 2642, "naklon": 0 }, +{ "label": "22/14", "node": 2643, "naklon": 0 }, +{ "label": "22/15", "node": 2644, "naklon": 0 }, +{ "label": "22/16", "node": 2645, "naklon": 0 }, +{ "label": "22/17", "node": 2646, "naklon": 0 }, +{ "label": "22/18", "node": 2647, "naklon": 0 }, +{ "label": "22/19", "node": 2648, "naklon": 0 }, +{ "label": "22/20", "node": 2649, "naklon": 0 }, +{ "label": "22/21", "node": 2650, "naklon": 0 }, +{ "label": "22/22", "node": 2651, "naklon": 0 }, +{ "label": "22/23", "node": 4103, "naklon": 0 }, +{ "label": "22/24", "node": 2653, "naklon": 0 }, +{ "label": "22/25", "node": 2654, "naklon": 0 }, +{ "label": "22/26", "node": 2655, "naklon": 0 }, +{ "label": "22/27", "node": 2656, "naklon": 0 }, +{ "label": "22/28", "node": 2657, "naklon": 0 }, +{ "label": "22/29", "node": 2658, "naklon": 0 }, +{ "label": "22/30", "node": 2659, "naklon": 0 }, +{ "label": "22/31", "node": 2660, "naklon": 0 }, +{ "label": "22/32", "node": 2661, "naklon": 0 }, +{ "label": "22/32/1", "node": 3015, "naklon": 0 }, +{ "label": "22/33", "node": 2662, "naklon": 0 }, +{ "label": "22/34", "node": 2663, "naklon": 0 }, +{ "label": "22/35", "node": 2664, "naklon": 0 }, +{ "label": "22/36", "node": 2665, "naklon": 0 }, +{ "label": "22/37", "node": 2666, "naklon": 0 }, +{ "label": "22/38", "node": 2667, "naklon": 0 }, +{ "label": "22/39", "node": 2668, "naklon": 0 }, +{ "label": "22/40", "node": 2669, "naklon": null }, +{ "label": "22/41", "node": 2670, "naklon": null }, +{ "label": "22/42", "node": 2671, "naklon": null }, +{ "label": "23/9A", "node": 3087, "naklon": 10 }, +{ "label": "23/9B", "node": 3090, "naklon": 10 }, +{ "label": "23/1", "node": 3075, "naklon": 0 }, +{ "label": "23/2", "node": 3089, "naklon": 0 }, +{ "label": "23/3", "node": 3088, "naklon": 0 }, +{ "label": "23/4", "node": 3228, "naklon": 10 }, +{ "label": "23/5", "node": 2751, "naklon": 10 }, +{ "label": "23/6", "node": 3243, "naklon": 10 }, +{ "label": "23/7", "node": 4349, "naklon": 10 }, +{ "label": "23/8", "node": 3102, "naklon": 10 }, +{ "label": "23/10", "node": 3099, "naklon": 10 }, +{ "label": "23/11", "node": 3103, "naklon": 10 }, +{ "label": "23/12", "node": 3093, "naklon": 10 }, +{ "label": "23/13", "node": 3098, "naklon": 10 }, +{ "label": "23/14", "node": 3092, "naklon": 10 }, +{ "label": "23/15", "node": 3233, "naklon": 0 }, +{ "label": "23/16", "node": 3095, "naklon": 0 }, +{ "label": "23/17", "node": 4074, "naklon": 0 }, +{ "label": "23/18", "node": 2729, "naklon": 0 }, +{ "label": "23/19", "node": 3234, "naklon": 0 }, +{ "label": "23/20", "node": 3094, "naklon": 0 }, +{ "label": "23/21", "node": 2817, "naklon": 0 }, +{ "label": "23/22", "node": 3226, "naklon": 0 }, +{ "label": "23/23", "node": 3225, "naklon": 0 }, +{ "label": "23/24", "node": 3237, "naklon": 0 }, +{ "label": "23/25", "node": 4250, "naklon": 0 }, +{ "label": "23/26", "node": 3059, "naklon": 10 }, +{ "label": "23/27", "node": 3238, "naklon": 10 }, +{ "label": "23/28", "node": 3242, "naklon": 10 }, +{ "label": "23/29", "node": 3236, "naklon": 10 }, +{ "label": "23/30", "node": 3112, "naklon": 10 }, +{ "label": "23/31", "node": 3224, "naklon": 0 }, +{ "label": "23/32", "node": 4298, "naklon": 10 }, +{ "label": "23/33", "node": 4150, "naklon": 10 }, +{ "label": "23/34", "node": 3091, "naklon": 10 }, +{ "label": "25/1", "node": 3771, "naklon": 5 }, +{ "label": "25/2", "node": 3777, "naklon": 5 }, +{ "label": "25/3", "node": 3749, "naklon": 5 }, +{ "label": "25/4", "node": 3769, "naklon": 5 }, +{ "label": "25/5", "node": 3765, "naklon": 5 }, +{ "label": "25/6", "node": 3785, "naklon": 5 }, +{ "label": "25/7", "node": 3761, "naklon": 5 }, +{ "label": "25/8", "node": 3758, "naklon": 5 }, +{ "label": "25/9", "node": 3766, "naklon": 5 }, +{ "label": "25/10", "node": 3779, "naklon": 5 }, +{ "label": "25/11", "node": 3899, "naklon": 10 }, +{ "label": "25/12", "node": 3922, "naklon": 10 }, +{ "label": "25/13", "node": 3912, "naklon": 10 }, +{ "label": "25/14", "node": 3933, "naklon": 10 }, +{ "label": "25/15", "node": 3921, "naklon": 10 }, +{ "label": "25/16", "node": 4300, "naklon": 10 }, +{ "label": "25/17", "node": 3927, "naklon": 10 }, +{ "label": "25/18", "node": 3212, "naklon": 10 }, +{ "label": "25/19", "node": 3208, "naklon": 10 }, +{ "label": "25/20", "node": 3207, "naklon": 10 }, +{ "label": "25/21", "node": 4294, "naklon": 10 }, +{ "label": "25/22", "node": 3209, "naklon": 10 }, +{ "label": "25/23", "node": 3745, "naklon": 10 }, +{ "label": "25/24", "node": 3762, "naklon": 10 }, +{ "label": "25/25", "node": 3215, "naklon": 10 }, +{ "label": "25/26", "node": 3210, "naklon": 10 }, +{ "label": "25/27", "node": 3211, "naklon": 10 }, +{ "label": "25/28", "node": 3206, "naklon": 10 }, +{ "label": "25/29", "node": 3918, "naklon": 5 }, +{ "label": "25/30", "node": 3928, "naklon": 5 }, +{ "label": "25/31", "node": 3917, "naklon": 5 }, +{ "label": "25/32", "node": 4029, "naklon": 0 }, +{ "label": "25/33", "node": 4038, "naklon": 0 }, +{ "label": "25/34", "node": 4022, "naklon": 0 }, +{ "label": "25/35", "node": 3937, "naklon": 0 }, +{ "label": "25/36", "node": 3190, "naklon": 0 }, +{ "label": "25/37", "node": 3835, "naklon": 0 }, +{ "label": "25/38", "node": 3201, "naklon": 0 }, +{ "label": "25/39", "node": 3193, "naklon": 0 }, +{ "label": "25/40", "node": 3191, "naklon": 0 }, +{ "label": "25/41", "node": 3203, "naklon": 0 }, +{ "label": "25/42", "node": 4301, "naklon": 0 }, +{ "label": "25/43", "node": 3223, "naklon": 0 }, +{ "label": "25/44", "node": 3202, "naklon": 0 }, +{ "label": "25/45", "node": 3205, "naklon": 0 }, +{ "label": "25/46", "node": 3194, "naklon": 0 }, +{ "label": "25/47", "node": 3198, "naklon": 0 }, +{ "label": "25/48", "node": 3204, "naklon": 0 }, +{ "label": "25/49", "node": 3200, "naklon": 0 }, +{ "label": "25/50", "node": 3216, "naklon": 0 }, +{ "label": "25/51", "node": 3932, "naklon": 5 }, +{ "label": "25/52", "node": 3923, "naklon": 5 }, +{ "label": "25/53", "node": 3913, "naklon": 5 }, +{ "label": "25/54", "node": 3900, "naklon": 5 }, +{ "label": "25/55", "node": 4189, "naklon": 10 }, +{ "label": "25/56", "node": 4191, "naklon": 10 }, +{ "label": "25/57", "node": 3790, "naklon": 10 }, +{ "label": "25/58", "node": 4190, "naklon": 10 }, +{ "label": "25/59", "node": 4302, "naklon": 0 }, +{ "label": "25/60", "node": 4351, "naklon": 0 }, +{ "label": "25/61", "node": 4075, "naklon": 0 }, +{ "label": "25/62", "node": 4071, "naklon": 0 }, +{ "label": "25/63", "node": 3784, "naklon": 0 }, +{ "label": "25/64", "node": 4065, "naklon": 0 }, +{ "label": "25/65", "node": 4297, "naklon": 0 }, +{ "label": "25/66", "node": 4295, "naklon": 0 }, +{ "label": "25/67", "node": 4299, "naklon": 0 }, +{ "label": "25/68", "node": 3772, "naklon": 0 }, +{ "label": "25/69", "node": 3941, "naklon": 0 }, +{ "label": "25/70", "node": 3782, "naklon": 0 }, +{ "label": "25/71", "node": 4068, "naklon": 0 }, +{ "label": "25/72", "node": 4073, "naklon": 0 }, +{ "label": "25/73", "node": 3901, "naklon": 5 }, +{ "label": "25/74", "node": 4296, "naklon": 5 }, +{ "label": "25/75", "node": 3910, "naklon": 5 }, +{ "label": "25/76", "node": 4293, "naklon": 5 }, +{ "label": "25/77", "node": 3919, "naklon": 5 }, +{ "label": "25/78", "node": 3924, "naklon": 5 }, +{ "label": "25/79", "node": 3909, "naklon": 5 }, +{ "label": "25/80", "node": 3896, "naklon": 5 }, +{ "label": "25/81", "node": 3911, "naklon": 5 }, +{ "label": "25/82", "node": 2819, "naklon": 15 }, +{ "label": "25/83", "node": 3776, "naklon": 15 }, +{ "label": "25/84", "node": 3752, "naklon": 15 }, +{ "label": "25/85", "node": 4353, "naklon": 15 }, +{ "label": "25/86", "node": 3791, "naklon": 0 }, +{ "label": "25/87", "node": 3770, "naklon": 0 }, +{ "label": "25/88", "node": 3760, "naklon": 0 }, +{ "label": "25/89", "node": 3115, "naklon": 0 }, +{ "label": "25/90", "node": 3738, "naklon": 0 }, +{ "label": "25/91", "node": 3748, "naklon": 0 }, +{ "label": "25/92", "node": 3753, "naklon": 0 }, +{ "label": "25/93", "node": 3775, "naklon": 0 }, +{ "label": "25/94", "node": 3778, "naklon": 5 }, +{ "label": "25/95", "node": 4078, "naklon": 5 }, +{ "label": "25/96", "node": 4088, "naklon": 5 }, +{ "label": "25/97", "node": 3856, "naklon": 5 }, +{ "label": "25/98", "node": 4084, "naklon": 5 }, +{ "label": "25/99", "node": 4069, "naklon": 5 }, +{ "label": "25/100", "node": 4188, "naklon": 5 }, +{ "label": "25/101", "node": 4064, "naklon": 5 }, +{ "label": "25/102", "node": 3792, "naklon": 5 }, +{ "label": "25/103", "node": 3780, "naklon": 5 }, +{ "label": "25/104", "node": 4034, "naklon": 5 }, +{ "label": "25/105", "node": 4072, "naklon": 5 }, +{ "label": "25/106", "node": 3884, "naklon": 5 }, +{ "label": "25/107", "node": 3793, "naklon": 5 }, +{ "label": "25/108", "node": 3863, "naklon": 5 }, +{ "label": "25/109", "node": 3855, "naklon": 5 }, +{ "label": "33/1", "node": 3846, "naklon": 0 }, +{ "label": "33/2", "node": 3943, "naklon": 0 }, +{ "label": "33/3", "node": 3903, "naklon": 0 }, +{ "label": "33/4", "node": 3982, "naklon": 0 }, +{ "label": "33/5", "node": 3879, "naklon": 0 }, +{ "label": "33/6", "node": 3887, "naklon": 0 }, +{ "label": "33/7", "node": 3920, "naklon": 5 }, +{ "label": "33/8", "node": 3942, "naklon": 5 }, +{ "label": "33/9", "node": 3829, "naklon": null }, +{ "label": "34/79A", "node": 3452, "naklon": 6 }, +{ "label": "34/79B", "node": 3460, "naklon": 6 }, +{ "label": "34/90A", "node": 3443, "naklon": 6 }, +{ "label": "34/90B", "node": 3445, "naklon": 6 }, +{ "label": "34/90C", "node": 3457, "naklon": 6 }, +{ "label": "34/97A", "node": 3461, "naklon": 6 }, +{ "label": "34/97B", "node": 3463, "naklon": 6 }, +{ "label": "34/98A", "node": 3426, "naklon": 6 }, +{ "label": "34/98B", "node": 3444, "naklon": 6 }, +{ "label": "34/99A", "node": 3453, "naklon": 6 }, +{ "label": "34/99B", "node": 3455, "naklon": 6 }, +{ "label": "34/1", "node": 4009, "naklon": 0 }, +{ "label": "34/2", "node": 3602, "naklon": 0 }, +{ "label": "34/3", "node": 3441, "naklon": 0 }, +{ "label": "34/4", "node": 3464, "naklon": 0 }, +{ "label": "34/5", "node": 3883, "naklon": 0 }, +{ "label": "34/6", "node": 4098, "naklon": 0 }, +{ "label": "34/7", "node": 4003, "naklon": 0 }, +{ "label": "34/8", "node": 4004, "naklon": 0 }, +{ "label": "34/9", "node": 3888, "naklon": 0 }, +{ "label": "34/10", "node": 3997, "naklon": 0 }, +{ "label": "34/11", "node": 4006, "naklon": 0 }, +{ "label": "34/12", "node": 4000, "naklon": 0 }, +{ "label": "34/13", "node": 4011, "naklon": 0 }, +{ "label": "34/14", "node": 3999, "naklon": 0 }, +{ "label": "34/15", "node": 3981, "naklon": 0 }, +{ "label": "34/16", "node": 3988, "naklon": 0 }, +{ "label": "34/17", "node": 3986, "naklon": 0 }, +{ "label": "34/18", "node": 3998, "naklon": 0 }, +{ "label": "34/19", "node": 3983, "naklon": 0 }, +{ "label": "34/20", "node": 4005, "naklon": 0 }, +{ "label": "34/21", "node": 4001, "naklon": 0 }, +{ "label": "34/22", "node": 4008, "naklon": 0 }, +{ "label": "34/23", "node": 4002, "naklon": 0 }, +{ "label": "34/24", "node": 3996, "naklon": 0 }, +{ "label": "34/25", "node": 4007, "naklon": 0 }, +{ "label": "34/26", "node": 4113, "naklon": 15 }, +{ "label": "34/27", "node": 3595, "naklon": 5 }, +{ "label": "34/28", "node": 3599, "naklon": 5 }, +{ "label": "34/29", "node": 3601, "naklon": 5 }, +{ "label": "34/30", "node": 4205, "naklon": 0 }, +{ "label": "34/31", "node": 3987, "naklon": null }, +{ "label": "34/32", "node": 4214, "naklon": 0 }, +{ "label": "34/33", "node": 4226, "naklon": 0 }, +{ "label": "34/34", "node": 4209, "naklon": 0 }, +{ "label": "34/35", "node": 4201, "naklon": 0 }, +{ "label": "34/36", "node": 3440, "naklon": 0 }, +{ "label": "34/37", "node": 3465, "naklon": 0 }, +{ "label": "34/38", "node": 3446, "naklon": 0 }, +{ "label": "34/39", "node": 4039, "naklon": 5 }, +{ "label": "34/40", "node": 4057, "naklon": 5 }, +{ "label": "34/41", "node": 3985, "naklon": 0 }, +{ "label": "34/42", "node": 3882, "naklon": 0 }, +{ "label": "34/43", "node": 4040, "naklon": 5 }, +{ "label": "34/44", "node": 3231, "naklon": 0 }, +{ "label": "34/45", "node": 3227, "naklon": 0 }, +{ "label": "34/46", "node": 3431, "naklon": 0 }, +{ "label": "34/47", "node": 4013, "naklon": 0 }, +{ "label": "34/48", "node": 4045, "naklon": 0 }, +{ "label": "34/49", "node": 3949, "naklon": 0 }, +{ "label": "34/50", "node": 3953, "naklon": 0 }, +{ "label": "34/51", "node": 3952, "naklon": 0 }, +{ "label": "34/52", "node": 3995, "naklon": 0 }, +{ "label": "34/53", "node": 3992, "naklon": 0 }, +{ "label": "34/54", "node": 4198, "naklon": 0 }, +{ "label": "34/55", "node": 3935, "naklon": 0 }, +{ "label": "34/56", "node": 4050, "naklon": 0 }, +{ "label": "34/57", "node": 4049, "naklon": 0 }, +{ "label": "34/58", "node": 4054, "naklon": 0 }, +{ "label": "34/59", "node": 3663, "naklon": 6 }, +{ "label": "34/60", "node": 3661, "naklon": 6 }, +{ "label": "34/61", "node": 3664, "naklon": 6 }, +{ "label": "34/62", "node": 3660, "naklon": 6 }, +{ "label": "34/63", "node": 3662, "naklon": 6 }, +{ "label": "34/65", "node": 3665, "naklon": 6 }, +{ "label": "34/66", "node": 3667, "naklon": 6 }, +{ "label": "34/67", "node": 3675, "naklon": 6 }, +{ "label": "34/68", "node": 3666, "naklon": 6 }, +{ "label": "34/69", "node": 3652, "naklon": 6 }, +{ "label": "34/70", "node": 3458, "naklon": 6 }, +{ "label": "34/70/1", "node": 4425, "naklon": 6 }, +{ "label": "34/71", "node": 3459, "naklon": 6 }, +{ "label": "34/72", "node": 3435, "naklon": 6 }, +{ "label": "34/73", "node": 3448, "naklon": 6 }, +{ "label": "34/74", "node": 3451, "naklon": 6 }, +{ "label": "34/75", "node": 3442, "naklon": 6 }, +{ "label": "34/76", "node": 3449, "naklon": 6 }, +{ "label": "34/77", "node": 3450, "naklon": 6 }, +{ "label": "34/78", "node": 3433, "naklon": 6 }, +{ "label": "34/80", "node": 3432, "naklon": 12 }, +{ "label": "34/81", "node": 3470, "naklon": 12 }, +{ "label": "34/82", "node": 3438, "naklon": 12 }, +{ "label": "34/83", "node": 3439, "naklon": 12 }, +{ "label": "34/84", "node": 4028, "naklon": 5 }, +{ "label": "34/85", "node": 3596, "naklon": 5 }, +{ "label": "34/86", "node": 4021, "naklon": 5 }, +{ "label": "34/87", "node": 3437, "naklon": 12 }, +{ "label": "34/88", "node": 3428, "naklon": 12 }, +{ "label": "34/89", "node": 3430, "naklon": 12 }, +{ "label": "34/91", "node": 3454, "naklon": 6 }, +{ "label": "34/92", "node": 3492, "naklon": 6 }, +{ "label": "34/93", "node": 3462, "naklon": 6 }, +{ "label": "34/94", "node": 3427, "naklon": 6 }, +{ "label": "34/95", "node": 3434, "naklon": 6 }, +{ "label": "34/96", "node": 3456, "naklon": 6 }, +{ "label": "34/98/1", "node": 4307, "naklon": 6 }, +{ "label": "35/1", "node": 3968, "naklon": 0 }, +{ "label": "35/2", "node": 3969, "naklon": 0 }, +{ "label": "35/3", "node": 3947, "naklon": 0 }, +{ "label": "35/4", "node": 3979, "naklon": 0 }, +{ "label": "35/5", "node": 3959, "naklon": 0 }, +{ "label": "35/6", "node": 3948, "naklon": 0 }, +{ "label": "35/7", "node": 3961, "naklon": 0 }, +{ "label": "35/8", "node": 3956, "naklon": 0 }, +{ "label": "35/9", "node": 3604, "naklon": 0 }, +{ "label": "35/10", "node": 3944, "naklon": 0 }, +{ "label": "35/11", "node": 3960, "naklon": 0 }, +{ "label": "35/12", "node": 3958, "naklon": 0 }, +{ "label": "35/13", "node": 4036, "naklon": 5 }, +{ "label": "35/18", "node": 3893, "naklon": 5 }, +{ "label": "35/19", "node": 4108, "naklon": 5 }, +{ "label": "35/20", "node": 4017, "naklon": 5 }, +{ "label": "35/21", "node": 3963, "naklon": 0 }, +{ "label": "35/22", "node": 3658, "naklon": 0 }, +{ "label": "35/23", "node": 3975, "naklon": 0 }, +{ "label": "35/24", "node": 3980, "naklon": 0 }, +{ "label": "35/25", "node": 4012, "naklon": 0 }, +{ "label": "35/26", "node": 3655, "naklon": 0 }, +{ "label": "35/27", "node": 3962, "naklon": 0 }, +{ "label": "35/28", "node": 3945, "naklon": 0 }, +{ "label": "35/29", "node": 3569, "naklon": 0 }, +{ "label": "35/30", "node": 3429, "naklon": 0 }, +{ "label": "35/31", "node": 3657, "naklon": 0 }, +{ "label": "35/32", "node": 3646, "naklon": 0 }, +{ "label": "35/33", "node": 3622, "naklon": 0 }, +{ "label": "35/34", "node": 3612, "naklon": 0 }, +{ "label": "35/35", "node": 3955, "naklon": 0 }, +{ "label": "35/37", "node": 3878, "naklon": 0 }, +{ "label": "35/38", "node": 3965, "naklon": 0 }, +{ "label": "35/39", "node": 3970, "naklon": 0 }, +{ "label": "35/40", "node": 3611, "naklon": 0 }, +{ "label": "35/41", "node": 2635, "naklon": 0 }, +{ "label": "35/42", "node": 3978, "naklon": 0 }, +{ "label": "35/43", "node": 4213, "naklon": 0 }, +{ "label": "35/44", "node": 3984, "naklon": 0 }, +{ "label": "35/45", "node": 4218, "naklon": 0 }, +{ "label": "35/46", "node": 3973, "naklon": 0 }, +{ "label": "35/47", "node": 3974, "naklon": 0 }, +{ "label": "35/48", "node": 3759, "naklon": 0 }, +{ "label": "35/49", "node": 3844, "naklon": 0 }, +{ "label": "35/50", "node": 3804, "naklon": 0 }, +{ "label": "35/51", "node": 3831, "naklon": 0 }, +{ "label": "35/52", "node": 3643, "naklon": 0 }, +{ "label": "35/53", "node": 3966, "naklon": 0 }, +{ "label": "35/54", "node": 3971, "naklon": 0 }, +{ "label": "35/55", "node": 3650, "naklon": 6 }, +{ "label": "35/56", "node": 3651, "naklon": 6 }, +{ "label": "35/57", "node": 3669, "naklon": 6 }, +{ "label": "35/58", "node": 3648, "naklon": 6 }, +{ "label": "35/59", "node": 3645, "naklon": 6 }, +{ "label": "35/60", "node": 3659, "naklon": 6 }, +{ "label": "35/61", "node": 3647, "naklon": 6 }, +{ "label": "35/62", "node": 3644, "naklon": 6 }, +{ "label": "35/63", "node": 3671, "naklon": 6 }, +{ "label": "35/64", "node": 3682, "naklon": 6 }, +{ "label": "35/65", "node": 3672, "naklon": 6 }, +{ "label": "35/66", "node": 3683, "naklon": 6 }, +{ "label": "35/67", "node": 3673, "naklon": 6 }, +{ "label": "35/68", "node": 3674, "naklon": 6 }, +{ "label": "35/69", "node": 3679, "naklon": 6 }, +{ "label": "35/70", "node": 3649, "naklon": 6 }, +{ "label": "35/71", "node": 3687, "naklon": 6 }, +{ "label": "35/72", "node": 3677, "naklon": 6 }, +{ "label": "35/73", "node": 3690, "naklon": 6 }, +{ "label": "35/74", "node": 3691, "naklon": 6 }, +{ "label": "35/75", "node": 3676, "naklon": 6 }, +{ "label": "35/76", "node": 3680, "naklon": 6 }, +{ "label": "35/77", "node": 3668, "naklon": 6 }, +{ "label": "35/78", "node": 3681, "naklon": 6 }, +{ "label": "35/79", "node": 3670, "naklon": 6 }, +{ "label": "35/80", "node": 3689, "naklon": 6 }, +{ "label": "35/81", "node": 3678, "naklon": 6 }, +{ "label": "35/82", "node": 3693, "naklon": 6 }, +{ "label": "35/83", "node": 3654, "naklon": null }, +{ "label": "36/1", "node": 4086, "naklon": 0 }, +{ "label": "36/2", "node": 4085, "naklon": 0 }, +{ "label": "36/3", "node": 4083, "naklon": 0 }, +{ "label": "36/4", "node": 4087, "naklon": 0 }, +{ "label": "36/5", "node": 4077, "naklon": 0 }, +{ "label": "36/6", "node": 4082, "naklon": 0 }, +{ "label": "36/7", "node": 4186, "naklon": 0 }, +{ "label": "36/8", "node": 4206, "naklon": 0 }, +{ "label": "36/9", "node": 4080, "naklon": 0 }, +{ "label": "36/10", "node": 4081, "naklon": 0 }, +{ "label": "36/11", "node": 4210, "naklon": 0 }, +{ "label": "36/12", "node": 4079, "naklon": 0 }, +{ "label": "36/13", "node": 4076, "naklon": 0 }, +{ "label": "36/14", "node": 3852, "naklon": 0 }, +{ "label": "36/15", "node": 2813, "naklon": 0 }, +{ "label": "36/16", "node": 4219, "naklon": 0 }, +{ "label": "37/1A", "node": 3104, "naklon": 15 }, +{ "label": "37/1B", "node": 3121, "naklon": 15 }, +{ "label": "37/2", "node": 3113, "naklon": 10 }, +{ "label": "37/3", "node": 3118, "naklon": 10 }, +{ "label": "37/4", "node": 3111, "naklon": 10 }, +{ "label": "37/5", "node": 4020, "naklon": 10 }, +{ "label": "37/6", "node": 3119, "naklon": 10 }, +{ "label": "37/7", "node": 3110, "naklon": 10 }, +{ "label": "37/8", "node": 3108, "naklon": 10 }, +{ "label": "37/12", "node": 3107, "naklon": 0 }, +{ "label": "37/13", "node": 3199, "naklon": 0 }, +{ "label": "37/14", "node": 3120, "naklon": 0 }, +{ "label": "37/15", "node": 3122, "naklon": 0 }, +{ "label": "37/16", "node": 3908, "naklon": 0 }, +{ "label": "37/17", "node": 3114, "naklon": 0 }, +{ "label": "37/18", "node": 3105, "naklon": 0 }, +{ "label": "37/19", "node": 3116, "naklon": 0 }, +{ "label": "37/20", "node": 3106, "naklon": 0 }, +{ "label": "37/21", "node": 2887, "naklon": 5 }, +{ "label": "37/22", "node": 2888, "naklon": 5 }, +{ "label": "37/23", "node": 2877, "naklon": 5 }, +{ "label": "37/24", "node": 2891, "naklon": 5 }, +{ "label": "37/25", "node": 2886, "naklon": 5 }, +{ "label": "37/26", "node": 2892, "naklon": 5 }, +{ "label": "37/27", "node": 2882, "naklon": 5 }, +{ "label": "37/28", "node": 2883, "naklon": 5 }, +{ "label": "37/29", "node": 2876, "naklon": 5 }, +{ "label": "37/30", "node": 3109, "naklon": 5 }, +{ "label": "37/31", "node": 4152, "naklon": 5 }, +{ "label": "37/32", "node": 3117, "naklon": 5 }, +{ "label": "37/33", "node": 2870, "naklon": 5 }, +{ "label": "37/34", "node": 2867, "naklon": 0 }, +{ "label": "37/35", "node": 2865, "naklon": 0 }, +{ "label": "37/36", "node": 3096, "naklon": 0 }, +{ "label": "37/37", "node": 2871, "naklon": 0 }, +{ "label": "37/38", "node": 2884, "naklon": 0 }, +{ "label": "37/39", "node": 2855, "naklon": 0 }, +{ "label": "37/40", "node": 2878, "naklon": 0 }, +{ "label": "37/41", "node": 2889, "naklon": 0 }, +{ "label": "37/42", "node": 2879, "naklon": 0 }, +{ "label": "37/43", "node": 2850, "naklon": 0 }, +{ "label": "37/44", "node": 2894, "naklon": 0 }, +{ "label": "37/45", "node": 2880, "naklon": 0 }, +{ "label": "37/46", "node": 2893, "naklon": 0 }, +{ "label": "37/47", "node": 2890, "naklon": 0 }, +{ "label": "37/48", "node": 4355, "naklon": 0 }, +{ "label": "37/49", "node": 2885, "naklon": 0 }, +{ "label": "37/50", "node": 2875, "naklon": 0 }, +{ "label": "38/30A", "node": 3486, "naklon": 5 }, +{ "label": "38/30B", "node": 3714, "naklon": 0 }, +{ "label": "38/32A", "node": 3483, "naklon": 5 }, +{ "label": "38/32B", "node": 3496, "naklon": 0 }, +{ "label": "38/35A", "node": 3487, "naklon": 5 }, +{ "label": "38/35B", "node": 3498, "naklon": 5 }, +{ "label": "38/38A", "node": 3578, "naklon": 5 }, +{ "label": "38/38B", "node": 3508, "naklon": 5 }, +{ "label": "38/59A", "node": 3787, "naklon": 5 }, +{ "label": "38/59B", "node": 3491, "naklon": 5 }, +{ "label": "38/1", "node": 3568, "naklon": null }, +{ "label": "38/2", "node": 3502, "naklon": 0 }, +{ "label": "38/3", "node": 3836, "naklon": 0 }, +{ "label": "38/4", "node": 3588, "naklon": 0 }, +{ "label": "38/5", "node": 3493, "naklon": 0 }, +{ "label": "38/6", "node": 3580, "naklon": 0 }, +{ "label": "38/7", "node": 3572, "naklon": 0 }, +{ "label": "38/8", "node": 3506, "naklon": 0 }, +{ "label": "38/9", "node": 3503, "naklon": 0 }, +{ "label": "38/10", "node": 3579, "naklon": 0 }, +{ "label": "38/11", "node": 3586, "naklon": 0 }, +{ "label": "38/12", "node": 3495, "naklon": 5 }, +{ "label": "38/13", "node": 3492, "naklon": 5 }, +{ "label": "38/14", "node": 3532, "naklon": 5 }, +{ "label": "38/15", "node": 3574, "naklon": 5 }, +{ "label": "38/16", "node": 4140, "naklon": 5 }, +{ "label": "38/17", "node": 3795, "naklon": 5 }, +{ "label": "38/18", "node": 3788, "naklon": 5 }, +{ "label": "38/19", "node": 3796, "naklon": 5 }, +{ "label": "38/20", "node": 3797, "naklon": 5 }, +{ "label": "38/21", "node": 3798, "naklon": 5 }, +{ "label": "38/22", "node": 3786, "naklon": 5 }, +{ "label": "38/23", "node": 4067, "naklon": 5 }, +{ "label": "38/24", "node": 3773, "naklon": 5 }, +{ "label": "38/25", "node": 3774, "naklon": 5 }, +{ "label": "38/26", "node": 3789, "naklon": 5 }, +{ "label": "38/27", "node": 3520, "naklon": null }, +{ "label": "38/29", "node": 3577, "naklon": 5 }, +{ "label": "38/31", "node": 3530, "naklon": null }, +{ "label": "38/33", "node": 3488, "naklon": 5 }, +{ "label": "38/34", "node": 3505, "naklon": 5 }, +{ "label": "38/36", "node": 3497, "naklon": 5 }, +{ "label": "38/37", "node": 3490, "naklon": 5 }, +{ "label": "38/39", "node": 3585, "naklon": 5 }, +{ "label": "38/40", "node": 3582, "naklon": 5 }, +{ "label": "38/41", "node": 3507, "naklon": 5 }, +{ "label": "38/42", "node": 3484, "naklon": 5 }, +{ "label": "38/43", "node": 3501, "naklon": 5 }, +{ "label": "38/44", "node": 3581, "naklon": 5 }, +{ "label": "38/45", "node": 4192, "naklon": 5 }, +{ "label": "38/46", "node": 3576, "naklon": 5 }, +{ "label": "38/47", "node": 3489, "naklon": 5 }, +{ "label": "38/48", "node": 3573, "naklon": 5 }, +{ "label": "38/49", "node": 3504, "naklon": 5 }, +{ "label": "38/50", "node": 3794, "naklon": 5 }, +{ "label": "38/51", "node": 3485, "naklon": 5 }, +{ "label": "38/52", "node": 3482, "naklon": 5 }, +{ "label": "38/53", "node": 3575, "naklon": 5 }, +{ "label": "38/54", "node": 3499, "naklon": 5 }, +{ "label": "38/55", "node": 3494, "naklon": 5 }, +{ "label": "38/56", "node": 3583, "naklon": 5 }, +{ "label": "38/57", "node": 3570, "naklon": 5 }, +{ "label": "38/58", "node": 3500, "naklon": 0 }, +{ "label": "38/63", "node": 3510, "naklon": null }, +{ "label": "38/64", "node": 3512, "naklon": null }, +{ "label": "38/67", "node": 3535, "naklon": null }, +{ "label": "38/68", "node": 3531, "naklon": null }, +{ "label": "38/69", "node": 3537, "naklon": null }, +{ "label": "39/1", "node": 3522, "naklon": 10 }, +{ "label": "39/2", "node": 4018, "naklon": 10 }, +{ "label": "39/3", "node": 4019, "naklon": 10 }, +{ "label": "39/4", "node": 4154, "naklon": 5 }, +{ "label": "39/5", "node": 3907, "naklon": 5 }, +{ "label": "39/6", "node": 4148, "naklon": 0 }, +{ "label": "39/7", "node": 4153, "naklon": 0 }, +{ "label": "39/8", "node": 3938, "naklon": 0 }, +{ "label": "39/9", "node": 3802, "naklon": 0 }, +{ "label": "39/10", "node": 4015, "naklon": 0 }, +{ "label": "39/11", "node": 3929, "naklon": 0 }, +{ "label": "39/12", "node": 3946, "naklon": 0 }, +{ "label": "39/13", "node": 4014, "naklon": 0 }, +{ "label": "39/14", "node": 4155, "naklon": 0 }, +{ "label": "39/15", "node": 4149, "naklon": 0 }, +{ "label": "39/16", "node": 3642, "naklon": 0 }, +{ "label": "39/17", "node": 3636, "naklon": 5 }, +{ "label": "39/18", "node": 3991, "naklon": 0 }, +{ "label": "39/19", "node": 3994, "naklon": 0 }, +{ "label": "39/20", "node": 3990, "naklon": 0 }, +{ "label": "39/21", "node": 3967, "naklon": 0 }, +{ "label": "39/22", "node": 3977, "naklon": 0 }, +{ "label": "39/23", "node": 3757, "naklon": 15 }, +{ "label": "39/24", "node": 3633, "naklon": 15 }, +{ "label": "39/25", "node": 3744, "naklon": 15 }, +{ "label": "39/26", "node": 4023, "naklon": 5 }, +{ "label": "39/27", "node": 3720, "naklon": 5 }, +{ "label": "39/28", "node": 3734, "naklon": 5 }, +{ "label": "39/29", "node": 3741, "naklon": 5 }, +{ "label": "39/30", "node": 3721, "naklon": 5 }, +{ "label": "39/31", "node": 3845, "naklon": 0 }, +{ "label": "39/32", "node": 3840, "naklon": 0 }, +{ "label": "39/33", "node": 3837, "naklon": null }, +{ "label": "39/34", "node": 3839, "naklon": 0 }, +{ "label": "41/1", "node": 3542, "naklon": null }, +{ "label": "41/2", "node": 3566, "naklon": null }, +{ "label": "41/3", "node": 3548, "naklon": null }, +{ "label": "41/4", "node": 3515, "naklon": null }, +{ "label": "41/5", "node": 3559, "naklon": null }, +{ "label": "41/6", "node": 3509, "naklon": null }, +{ "label": "41/7", "node": 3524, "naklon": null }, +{ "label": "41/8", "node": 3518, "naklon": null }, +{ "label": "41/9", "node": 3182, "naklon": null }, +{ "label": "41/10", "node": 3187, "naklon": null }, +{ "label": "41/11", "node": 3195, "naklon": 0 }, +{ "label": "41/12", "node": 3857, "naklon": 0 }, +{ "label": "41/13", "node": 3183, "naklon": 0 }, +{ "label": "41/14", "node": 3177, "naklon": 0 }, +{ "label": "41/15", "node": 3189, "naklon": 0 }, +{ "label": "41/16", "node": 3186, "naklon": 0 }, +{ "label": "42/1", "node": 3178, "naklon": 0 }, +{ "label": "42/2", "node": 3219, "naklon": 0 }, +{ "label": "42/3", "node": 3475, "naklon": 0 }, +{ "label": "42/4", "node": 3175, "naklon": 0 }, +{ "label": "42/5", "node": 3222, "naklon": 0 }, +{ "label": "42/6", "node": 3221, "naklon": 0 }, +{ "label": "42/7", "node": 3181, "naklon": 0 }, +{ "label": "42/8", "node": 3180, "naklon": 0 }, +{ "label": "42/9", "node": 3218, "naklon": 0 }, +{ "label": "42/10", "node": 3176, "naklon": 0 }, +{ "label": "42/11", "node": 3174, "naklon": 0 }, +{ "label": "42/12", "node": 3220, "naklon": 0 }, +{ "label": "42/13", "node": 3533, "naklon": null }, +{ "label": "42/14", "node": 3543, "naklon": null }, +{ "label": "42/15", "node": 3554, "naklon": null }, +{ "label": "42/16", "node": 3549, "naklon": null }, +{ "label": "43/1", "node": 2857, "naklon": 5 }, +{ "label": "43/2", "node": 2752, "naklon": 5 }, +{ "label": "43/3", "node": 2753, "naklon": 5 }, +{ "label": "43/4", "node": 3024, "naklon": 5 }, +{ "label": "43/5", "node": 2754, "naklon": 5 }, +{ "label": "43/6", "node": 4423, "naklon": 5 }, +{ "label": "43/7", "node": 4368, "naklon": 5 }, +{ "label": "43/8", "node": 2978, "naklon": 5 }, +{ "label": "43/9", "node": 2868, "naklon": 5 }, +{ "label": "43/10", "node": 4377, "naklon": 5 }, +{ "label": "43/11", "node": 2757, "naklon": 5 }, +{ "label": "43/12", "node": 2970, "naklon": 5 }, +{ "label": "43/13", "node": 2758, "naklon": 5 }, +{ "label": "43/14", "node": 4378, "naklon": 5 }, +{ "label": "43/15", "node": 2759, "naklon": 5 }, +{ "label": "43/16", "node": 4342, "naklon": 5 }, +{ "label": "43/17", "node": 3026, "naklon": null }, +{ "label": "43/18", "node": 2986, "naklon": null }, +{ "label": "43/19", "node": 4343, "naklon": null }, +{ "label": "43/20", "node": 2760, "naklon": null }, +{ "label": "43/21", "node": 4379, "naklon": null }, +{ "label": "43/22", "node": 2971, "naklon": null }, +{ "label": "43/23", "node": 2761, "naklon": null }, +{ "label": "43/24", "node": 2762, "naklon": null }, +{ "label": "43/25", "node": 4339, "naklon": null }, +{ "label": "43/26", "node": 4380, "naklon": null }, +{ "label": "43/27", "node": 2975, "naklon": null }, +{ "label": "43/28", "node": 3003, "naklon": null }, +{ "label": "43/29", "node": 4338, "naklon": null }, +{ "label": "43/30", "node": 3002, "naklon": null }, +{ "label": "43/31", "node": 4345, "naklon": null }, +{ "label": "43/32", "node": 2979, "naklon": null }, +{ "label": "43/33", "node": 2989, "naklon": null }, +{ "label": "43/34", "node": 2996, "naklon": null }, +{ "label": "43/35", "node": 2972, "naklon": null }, +{ "label": "43/36", "node": 2988, "naklon": null }, +{ "label": "43/37", "node": 4344, "naklon": null }, +{ "label": "43/38", "node": 3022, "naklon": null }, +{ "label": "43/39", "node": 4341, "naklon": null }, +{ "label": "43/40", "node": 2983, "naklon": null }, +{ "label": "43/41", "node": 2995, "naklon": null }, +{ "label": "43/42", "node": 2763, "naklon": null }, +{ "label": "43/43", "node": 2764, "naklon": null }, +{ "label": "43/44", "node": 2765, "naklon": null }, +{ "label": "43/45", "node": 2766, "naklon": null }, +{ "label": "43/46", "node": 2767, "naklon": null }, +{ "label": "43/47", "node": 2768, "naklon": null }, +{ "label": "43/48", "node": 3018, "naklon": null }, +{ "label": "43/49", "node": 2982, "naklon": null }, +{ "label": "43/50", "node": 3019, "naklon": 0 }, +{ "label": "43/51", "node": 3013, "naklon": null }, +{ "label": "43/52", "node": 3007, "naklon": null }, +{ "label": "43/53", "node": 2980, "naklon": null }, +{ "label": "43/54", "node": 3011, "naklon": null }, +{ "label": "43/55", "node": 2672, "naklon": null }, +{ "label": "43/56", "node": 2673, "naklon": null }, +{ "label": "43/57", "node": 2674, "naklon": null }, +{ "label": "43/58", "node": 2675, "naklon": null }, +{ "label": "43/59", "node": 2676, "naklon": null }, +{ "label": "43/60", "node": 2677, "naklon": null }, +{ "label": "43/61", "node": 2678, "naklon": null }, +{ "label": "43/62", "node": 2679, "naklon": null }, +{ "label": "43/63", "node": 2680, "naklon": null }, +{ "label": "43/64", "node": 2840, "naklon": null }, +{ "label": "43/65", "node": 2682, "naklon": null }, +{ "label": "43/66", "node": 2683, "naklon": null }, +{ "label": "43/67", "node": 2684, "naklon": 0 }, +{ "label": "43/68", "node": 2685, "naklon": null }, +{ "label": "43/69", "node": 2686, "naklon": null }, +{ "label": "43/70", "node": 2687, "naklon": null }, +{ "label": "43/71", "node": 2688, "naklon": null }, +{ "label": "43/72", "node": 2689, "naklon": null }, +{ "label": "43/73", "node": 2690, "naklon": null }, +{ "label": "43/74", "node": 2691, "naklon": null }, +{ "label": "43/75", "node": 2692, "naklon": null }, +{ "label": "43/76", "node": 2693, "naklon": 0 }, +{ "label": "43/77", "node": 2694, "naklon": null }, +{ "label": "43/78", "node": 2695, "naklon": null }, +{ "label": "43/79", "node": 2696, "naklon": 0 }, +{ "label": "43/80", "node": 2697, "naklon": null }, +{ "label": "43/81", "node": 2698, "naklon": 0 }, +{ "label": "43/82", "node": 2699, "naklon": null }, +{ "label": "43/83", "node": 2700, "naklon": 0 }, +{ "label": "43/84", "node": 2744, "naklon": null }, +{ "label": "43/85", "node": 2745, "naklon": 0 }, +{ "label": "43/86", "node": 2746, "naklon": null }, +{ "label": "43/87", "node": 2747, "naklon": 0 }, +{ "label": "43/88", "node": 2748, "naklon": null }, +{ "label": "43/89", "node": 2749, "naklon": 0 }, +{ "label": "43/90", "node": 2841, "naklon": null }, +{ "label": "45/1", "node": 4237, "naklon": 5 }, +{ "label": "45/2", "node": 4226, "naklon": 5 }, +{ "label": "45/3", "node": 4242, "naklon": 5 }, +{ "label": "45/4", "node": 4179, "naklon": 5 }, +{ "label": "45/5", "node": 4247, "naklon": 5 }, +{ "label": "45/6", "node": 4245, "naklon": 5 }, +{ "label": "45/7", "node": 3872, "naklon": 5 }, +{ "label": "45/8", "node": 4175, "naklon": 5 }, +{ "label": "45/9", "node": 4236, "naklon": 5 }, +{ "label": "45/10", "node": 4170, "naklon": 5 }, +{ "label": "45/11", "node": 4238, "naklon": 5 }, +{ "label": "45/12", "node": 4246, "naklon": 5 }, +{ "label": "45/13", "node": 4166, "naklon": 5 }, +{ "label": "45/14", "node": 4227, "naklon": 5 }, +{ "label": "45/15", "node": 4171, "naklon": 5 }, +{ "label": "45/16", "node": 4180, "naklon": 5 }, +{ "label": "45/17", "node": 4244, "naklon": 5 }, +{ "label": "45/18", "node": 4199, "naklon": 5 }, +{ "label": "45/19", "node": 4239, "naklon": 5 }, +{ "label": "45/20", "node": 4207, "naklon": 5 }, +{ "label": "45/21", "node": 4223, "naklon": 5 }, +{ "label": "45/22", "node": 4230, "naklon": 5 }, +{ "label": "45/23", "node": 4233, "naklon": 5 }, +{ "label": "45/24", "node": 4222, "naklon": 5 }, +{ "label": "45/25", "node": 4217, "naklon": 5 }, +{ "label": "45/26", "node": 4243, "naklon": 5 }, +{ "label": "45/27", "node": 4200, "naklon": 5 }, +{ "label": "45/28", "node": 4228, "naklon": 5 }, +{ "label": "45/29", "node": 4211, "naklon": 5 }, +{ "label": "45/30", "node": 4234, "naklon": 5 }, +{ "label": "45/31", "node": 4235, "naklon": 5 }, +{ "label": "45/32", "node": 4203, "naklon": 5 }, +{ "label": "45/33", "node": 4240, "naklon": 5 }, +{ "label": "45/34", "node": 4224, "naklon": 5 }, +{ "label": "45/35", "node": 4232, "naklon": 5 }, +{ "label": "45/36", "node": 4231, "naklon": 5 }, +{ "label": "45/37", "node": 4161, "naklon": 5 }, +{ "label": "45/38", "node": 4225, "naklon": 5 }, +{ "label": "45/39", "node": 4241, "naklon": 5 }, +{ "label": "45/40", "node": 4229, "naklon": 5 }, +{ "label": "45/41", "node": 4221, "naklon": 5 }, +{ "label": "45/42", "node": 4212, "naklon": 5 }, +{ "label": "45/43", "node": 4216, "naklon": 5 }, +{ "label": "45/44", "node": 3864, "naklon": null }, +{ "label": "46/1", "node": 3806, "naklon": 5 }, +{ "label": "46/2", "node": 3813, "naklon": 5 }, +{ "label": "46/3", "node": 3815, "naklon": 5 }, +{ "label": "46/4", "node": 3807, "naklon": 5 }, +{ "label": "46/5", "node": 3895, "naklon": 5 }, +{ "label": "46/6", "node": 3809, "naklon": 5 }, +{ "label": "46/7", "node": 3820, "naklon": 5 }, +{ "label": "46/8", "node": 3805, "naklon": 5 }, +{ "label": "46/9", "node": 3894, "naklon": 0 }, +{ "label": "46/10", "node": 4055, "naklon": 0 }, +{ "label": "46/11", "node": 3812, "naklon": 5 }, +{ "label": "46/12", "node": 3822, "naklon": 5 }, +{ "label": "46/13", "node": 3821, "naklon": 5 }, +{ "label": "46/14", "node": 3808, "naklon": 5 }, +{ "label": "46/15", "node": 3799, "naklon": 5 }, +{ "label": "46/16", "node": 3816, "naklon": 5 }, +{ "label": "46/17", "node": 3751, "naklon": 5 }, +{ "label": "46/18", "node": 3814, "naklon": 5 }, +{ "label": "46/19", "node": 4044, "naklon": 0 }, +{ "label": "46/20", "node": 3931, "naklon": 0 }, +{ "label": "46/21", "node": 3902, "naklon": 5 }, +{ "label": "46/22", "node": 3916, "naklon": 5 }, +{ "label": "46/23", "node": 3892, "naklon": 5 }, +{ "label": "46/24", "node": 3914, "naklon": 5 }, +{ "label": "46/25", "node": 3898, "naklon": 5 }, +{ "label": "46/26", "node": 3897, "naklon": 5 }, +{ "label": "46/27", "node": 3885, "naklon": 5 }, +{ "label": "46/28", "node": 3906, "naklon": 5 }, +{ "label": "46/29", "node": 3930, "naklon": 0 }, +{ "label": "46/30", "node": 3936, "naklon": 0 }, +{ "label": "46/31", "node": 3860, "naklon": 5 }, +{ "label": "46/32", "node": 3841, "naklon": 5 }, +{ "label": "46/33", "node": 3873, "naklon": 5 }, +{ "label": "46/34", "node": 3854, "naklon": 5 }, +{ "label": "46/35", "node": 3939, "naklon": 5 }, +{ "label": "46/36", "node": 3858, "naklon": 5 }, +{ "label": "46/37", "node": 3940, "naklon": 5 }, +{ "label": "46/38", "node": 4035, "naklon": 5 }, +{ "label": "47/1", "node": 3373, "naklon": 0 }, +{ "label": "47/2", "node": 3374, "naklon": 0 }, +{ "label": "47/3", "node": 3384, "naklon": 0 }, +{ "label": "47/4", "node": 3385, "naklon": 0 }, +{ "label": "48/1", "node": 4051, "naklon": 5 }, +{ "label": "48/2", "node": 4041, "naklon": 5 }, +{ "label": "48/3", "node": 4056, "naklon": 5 }, +{ "label": "48/4", "node": 3875, "naklon": 5 }, +{ "label": "48/5", "node": 4061, "naklon": 5 }, +{ "label": "48/6", "node": 4047, "naklon": 5 }, +{ "label": "48/7", "node": 4060, "naklon": 5 }, +{ "label": "48/8", "node": 4059, "naklon": 5 }, +{ "label": "48/9", "node": 4058, "naklon": 5 }, +{ "label": "48/10", "node": 3635, "naklon": 5 }, +{ "label": "48/11", "node": 3640, "naklon": 5 }, +{ "label": "48/12", "node": 3747, "naklon": 5 }, +{ "label": "48/13", "node": 3629, "naklon": 5 }, +{ "label": "48/14", "node": 4048, "naklon": 5 }, +{ "label": "48/15", "node": 4063, "naklon": 5 }, +{ "label": "48/16", "node": 4062, "naklon": 5 }, +{ "label": "48/17", "node": 4043, "naklon": 5 }, +{ "label": "48/18", "node": 4052, "naklon": 5 }, +{ "label": "48/19", "node": 4042, "naklon": 5 }, +{ "label": "48/20", "node": 4053, "naklon": 5 }, +{ "label": "50/15A", "node": 4167, "naklon": null }, +{ "label": "50/15B", "node": 4159, "naklon": null }, +{ "label": "50/1", "node": 4183, "naklon": 0 }, +{ "label": "50/2", "node": 4157, "naklon": 0 }, +{ "label": "50/3", "node": 4160, "naklon": 0 }, +{ "label": "50/4", "node": 4173, "naklon": 0 }, +{ "label": "50/5", "node": 4177, "naklon": 0 }, +{ "label": "50/6", "node": 4174, "naklon": 0 }, +{ "label": "50/7", "node": 4178, "naklon": 0 }, +{ "label": "50/8", "node": 4195, "naklon": 0 }, +{ "label": "50/9", "node": 4169, "naklon": 0 }, +{ "label": "50/10", "node": 4162, "naklon": 0 }, +{ "label": "50/11", "node": 4158, "naklon": 0 }, +{ "label": "50/12", "node": 4182, "naklon": 0 }, +{ "label": "50/13", "node": 4194, "naklon": 0 }, +{ "label": "50/14", "node": 4184, "naklon": 0 }, +{ "label": "50/16", "node": 4197, "naklon": null }, +{ "label": "50/17", "node": 4164, "naklon": null }, +{ "label": "50/18", "node": 3306, "naklon": null }, +{ "label": "50/19", "node": 4168, "naklon": null }, +{ "label": "50/20", "node": 4193, "naklon": null }, +{ "label": "50/21", "node": 4187, "naklon": null }, +{ "label": "50/22", "node": 4163, "naklon": null }, +{ "label": "50/23", "node": 4165, "naklon": null }, +{ "label": "50/24", "node": 4185, "naklon": null }, +{ "label": "50/25", "node": 3904, "naklon": null }, +{ "label": "53/1", "node": 2619, "naklon": 0 }, +{ "label": "53/2", "node": 2623, "naklon": 0 }, +{ "label": "53/3", "node": 2617, "naklon": 0 }, +{ "label": "53/4", "node": 2622, "naklon": 0 }, +{ "label": "53/5", "node": 2618, "naklon": 0 }, +{ "label": "53/6", "node": 2626, "naklon": 0 }, +{ "label": "53/7", "node": 2869, "naklon": 0 }, +{ "label": "53/8", "node": 2613, "naklon": 0 }, +{ "label": "53/9", "node": 2608, "naklon": 0 }, +{ "label": "53/10", "node": 2611, "naklon": 0 }, +{ "label": "53/11", "node": 2598, "naklon": 0 }, +{ "label": "53/12", "node": 3528, "naklon": 0 }, +{ "label": "53/13", "node": 3545, "naklon": 0 }, +{ "label": "53/14", "node": 2620, "naklon": 0 }, +{ "label": "53/15", "node": 2612, "naklon": 0 }, +{ "label": "53/16", "node": 2615, "naklon": 0 }, +{ "label": "53/17", "node": 3722, "naklon": 0 }, +{ "label": "53/18", "node": 2624, "naklon": 0 }, +{ "label": "53/19", "node": 2609, "naklon": 0 }, +{ "label": "53/20", "node": 2625, "naklon": 0 }, +{ "label": "53/21", "node": 2602, "naklon": 0 }, +{ "label": "53/22", "node": 2610, "naklon": 0 }, +{ "label": "53/23", "node": 2599, "naklon": 0 }, +{ "label": "53/24", "node": 2605, "naklon": 0 }, +{ "label": "53/25", "node": 2593, "naklon": 0 }, +{ "label": "53/26", "node": 3074, "naklon": 0 }, +{ "label": "53/27", "node": 2740, "naklon": 0 }, +{ "label": "53/28", "node": 2614, "naklon": 0 }, +{ "label": "53/29", "node": 2601, "naklon": 0 }, +{ "label": "53/30", "node": 4196, "naklon": 0 }, +{ "label": "53/31", "node": 2607, "naklon": 0 }, +{ "label": "53/32", "node": 2582, "naklon": 0 }, +{ "label": "53/33", "node": 2594, "naklon": 0 }, +{ "label": "53/34", "node": 2589, "naklon": 0 }, +{ "label": "53/35", "node": 2596, "naklon": 0 }, +{ "label": "53/36", "node": 2603, "naklon": 0 }, +{ "label": "53/37", "node": 2597, "naklon": 0 }, +{ "label": "53/38", "node": 2590, "naklon": 0 }, +{ "label": "53/39", "node": 2581, "naklon": 0 }, +{ "label": "53/40", "node": 2583, "naklon": 0 }, +{ "label": "53/41", "node": 2580, "naklon": 0 }, +{ "label": "53/42", "node": 2579, "naklon": 0 }, +{ "label": "53/43", "node": 2797, "naklon": 0 }, +{ "label": "53/44", "node": 2577, "naklon": 0 }, +{ "label": "53/45", "node": 2586, "naklon": 0 }, +{ "label": "53/46", "node": 2588, "naklon": 0 }, +{ "label": "53/47", "node": 2591, "naklon": 0 }, +{ "label": "53/48", "node": 2592, "naklon": 0 }, +{ "label": "53/49", "node": 2573, "naklon": 0 }, +{ "label": "53/50", "node": 2595, "naklon": 0 }, +{ "label": "53/51", "node": 2587, "naklon": 0 }, +{ "label": "53/52", "node": 2578, "naklon": 0 }, +{ "label": "53/53", "node": 2574, "naklon": 0 }, +{ "label": "53/54", "node": 2571, "naklon": 0 }, +{ "label": "53/55", "node": 2570, "naklon": 0 }, +{ "label": "53/56", "node": 2576, "naklon": 0 }, +{ "label": "53/57", "node": 2881, "naklon": 0 }, +{ "label": "53/58", "node": 2575, "naklon": 0 }, +{ "label": "53/59", "node": 2572, "naklon": 0 }, +{ "label": "53/60", "node": 2569, "naklon": 0 }, +{ "label": "55/1", "node": 4324, "naklon": 0 }, +{ "label": "55/2", "node": 4319, "naklon": 0 }, +{ "label": "55/3", "node": 4327, "naklon": 0 }, +{ "label": "55/4", "node": 4333, "naklon": 0 }, +{ "label": "55/5", "node": 4332, "naklon": 0 }, +{ "label": "55/6", "node": 4320, "naklon": 0 }, +{ "label": "55/7", "node": 4317, "naklon": 0 }, +{ "label": "55/8", "node": 4318, "naklon": 0 }, +{ "label": "55/9", "node": 4328, "naklon": 0 }, +{ "label": "55/10", "node": 4323, "naklon": 0 }, +{ "label": "55/11", "node": 4325, "naklon": 0 }, +{ "label": "55/12", "node": 4326, "naklon": 0 }, +{ "label": "55/13", "node": 4316, "naklon": 0 }, +{ "label": "55/14", "node": 4322, "naklon": 0 }, +{ "label": "55/15", "node": 4331, "naklon": 0 }, +{ "label": "55/16", "node": 4321, "naklon": 0 }, +{ "label": "55/17", "node": 4315, "naklon": 0 }, +{ "label": "55/18", "node": 4329, "naklon": 0 }, +{ "label": "55/19", "node": 4334, "naklon": 0 }, +{ "label": "55/20", "node": 4330, "naklon": 0 } +]; + +module.exports = { naklony }; diff --git a/RVO7/databases/modbus_config.js b/RVO7/databases/modbus_config.js new file mode 100755 index 0000000..b73116a --- /dev/null +++ b/RVO7/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/RVO7/databases/nodes.table b/RVO7/databases/nodes.table new file mode 100755 index 0000000..31e5331 --- /dev/null +++ b/RVO7/databases/nodes.table @@ -0,0 +1,20 @@ +node:number|pole_number:string|node_type:string|tbname:string|line:number|profile:string|processed:boolean|status:boolean|time_of_last_communication:number ++|3474|5|NEMA|PLBJzmK1r3Gynd6OW0gKx80e5wV4vx9bDEqNgYR8|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":8,"dusk_lux_sensor_value":8,"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|1760573837878|............. ++|3468|3|NEMA|wvKJdZML6mXP4DzWBAXx56AjxNloa5g23Ve9Y1ry|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":8,"dusk_lux_sensor_value":8,"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|1760573854353|............. ++|3476|12|NEMA|3a5oqJN1bgnx4Ol9dk89zo7ByE6jQ8mKDWMpGrLV|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":8,"dusk_lux_sensor_value":8,"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|1760573838949|............. ++|3471|15|NEMA|Nzp2OoJlqn6r1ZgvdA3B6o7abBwP5G4eE3RQmyxD|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":8,"dusk_lux_sensor_value":8,"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|1760573835609|............. ++|3477|19|NEMA|E6Kg9oDnLWyzPRMva7v5MJkJxp4VG58qO2w1lZYe|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":8,"dusk_lux_sensor_value":8,"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|1760573839412|............. ++|3478|14|NEMA|wvKJdZML6mXP4DzWBAXx5KAjxNloa5g23Ve9Y1ry|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":8,"dusk_lux_sensor_value":8,"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|1760573843982|............. ++|3472|8|NEMA|roKgWqY95V3mXMRzyAjKnP0bLjexpJPvaGDBw826|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":8,"dusk_lux_sensor_value":8,"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|1760573835752|............. ++|3473|9|NEMA|nJL5lPMwBx23YpqRe0rprQ7damXvWVbOrD4gNzy8|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":8,"dusk_lux_sensor_value":8,"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|1760573836839|............. ++|3587|2|NEMA|EjgWGnXaLy9opPOz20n4qZ786BlYM3w1deVQvbKr|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":8,"dusk_lux_sensor_value":8,"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|1760573849463|............. ++|3589|7|NEMA|E6Kg9oDnLWyzPRMva7v5MXkJxp4VG58qO2w1lZYe|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":8,"dusk_lux_sensor_value":8,"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|1760573853746|............. ++|3590|13|NEMA|EjgWGnXaLy9opPOz20n4qB786BlYM3w1deVQvbKr|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":8,"dusk_lux_sensor_value":8,"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|1760573850358|............. ++|3591|1|NEMA|3a5oqJN1bgnx4Ol9dk89z37ByE6jQ8mKDWMpGrLV|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":8,"dusk_lux_sensor_value":8,"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|1760573852707|............. ++|3466|4|NEMA|Nzp2OoJlqn6r1ZgvdA3B6r7abBwP5G4eE3RQmyxD|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":8,"dusk_lux_sensor_value":8,"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|1760573853315|............. ++|3467|16|NEMA|PLBJzmK1r3Gynd6OW0gKxe0e5wV4vx9bDEqNgYR8|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":8,"dusk_lux_sensor_value":8,"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|1760573832541|............. ++|3479|17|NEMA|52dD6ZlV1QaOpRBmbAqGjekKnGzWMLj4eJq38Pgo|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":8,"dusk_lux_sensor_value":8,"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|1760573844302|............. ++|3480|18|NEMA|rDbQ84xzwgdqEoPm3kbENY09anOZY1RXyBv2LVM6|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":8,"dusk_lux_sensor_value":8,"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|1760573843806|............. ++|3481|6|NEMA|rDbQ84xzwgdqEoPm3kbENO09anOZY1RXyBv2LVM6|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":8,"dusk_lux_sensor_value":8,"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|1760573849176|............. ++|3571|11|NEMA|eod9aRWLVl34Gx1Dn7VNej72rz6qjgmpEXwQJN5Z|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":8,"dusk_lux_sensor_value":8,"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|1760573847689|............... ++|3584|10|NEMA|ZmRwd93QL4gaezxEbAx2ELk1prn2XjlPvGyqJ6BO|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":8,"dusk_lux_sensor_value":8,"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|1760573847977|............. diff --git a/RVO7/databases/nodes_original/nodes_original.table b/RVO7/databases/nodes_original/nodes_original.table new file mode 100755 index 0000000..280b3a4 --- /dev/null +++ b/RVO7/databases/nodes_original/nodes_original.table @@ -0,0 +1 @@ +[{"3474": "PLBJzmK1r3Gynd6OW0gKx80e5wV4vx9bDEqNgYR8"}, {"3468": "wvKJdZML6mXP4DzWBAXx56AjxNloa5g23Ve9Y1ry"}, {"3476": "3a5oqJN1bgnx4Ol9dk89zo7ByE6jQ8mKDWMpGrLV"}, {"3471": "Nzp2OoJlqn6r1ZgvdA3B6o7abBwP5G4eE3RQmyxD"}, {"3477": "E6Kg9oDnLWyzPRMva7v5MJkJxp4VG58qO2w1lZYe"}, {"3478": "wvKJdZML6mXP4DzWBAXx5KAjxNloa5g23Ve9Y1ry"}, {"3472": "roKgWqY95V3mXMRzyAjKnP0bLjexpJPvaGDBw826"}, {"3473": "nJL5lPMwBx23YpqRe0rprQ7damXvWVbOrD4gNzy8"}, {"3587": "EjgWGnXaLy9opPOz20n4qZ786BlYM3w1deVQvbKr"}, {"3589": "E6Kg9oDnLWyzPRMva7v5MXkJxp4VG58qO2w1lZYe"}, {"3590": "EjgWGnXaLy9opPOz20n4qB786BlYM3w1deVQvbKr"}, {"3591": "3a5oqJN1bgnx4Ol9dk89z37ByE6jQ8mKDWMpGrLV"}, {"3466": "Nzp2OoJlqn6r1ZgvdA3B6r7abBwP5G4eE3RQmyxD"}, {"3467": "PLBJzmK1r3Gynd6OW0gKxe0e5wV4vx9bDEqNgYR8"}, {"3479": "52dD6ZlV1QaOpRBmbAqGjekKnGzWMLj4eJq38Pgo"}, {"3480": "rDbQ84xzwgdqEoPm3kbENY09anOZY1RXyBv2LVM6"}, {"3481": "rDbQ84xzwgdqEoPm3kbENO09anOZY1RXyBv2LVM6"}, {"3571": "eod9aRWLVl34Gx1Dn7VNej72rz6qjgmpEXwQJN5Z"}, {"3584": "ZmRwd93QL4gaezxEbAx2ELk1prn2XjlPvGyqJ6BO"}] \ No newline at end of file diff --git a/RVO7/databases/notifications.table b/RVO7/databases/notifications.table new file mode 100755 index 0000000..f7c96cb --- /dev/null +++ b/RVO7/databases/notifications.table @@ -0,0 +1,41 @@ +key:string|weight:string|sk:string|en:string ++|switching_profile_point_applied_to_line|INFORMATIONAL|Aplikovaný bod spínacieho profilu na línií č. ${line} : ${value}|Switching profile point applied to line no. ${line} : ${value}|............... ++|dusk_has_occured|INFORMATIONAL|Nastal súmrak: ${value}|Dusk has occured: ${value}|............... ++|dawn_has_occured|INFORMATIONAL|Nastal úsvit: ${value}|Dawn has occured: ${value}|............... ++|dimming_profile_was_successfully_received_by_node|NOTICE|Stmievací profil bol úspešne prijatý nodom č. ${node}|Dimming profile was successfully received by node no. ${node}|............... ++|master_node_is_responding_again|NOTICE|Master node začal znovu odpovedať|Master node is responding again|............... ++|command_was_sent_from_terminal_interface|DEBUG|Z terminálu bol odoslaný príkaz|A command was sent from terminal interface|............... ++|master_node_is_not_responding|ALERT|Master node neodpovedá|Master node is not responding|............... ++|configuration_of_dimming_profile_to_node_failed|ALERT|Konfigurácia stmievacieho profilu pre node č. ${node} zlyhala|Configuration of dimming profile to node no. ${node} has failed|............... ++|circuit_breaker_was_turned_on_line|NOTICE|Zapnutie ističa na línii č. ${line}|Circuit breaker was turned on - line no. ${line}|............... ++|circuit_breaker_was_turned_off_line|ERROR|Vypnutie ističa na línií č. ${line}|Circuit breaker was turned off - line no. ${line}|............... ++|dimming_profile_was_processed_for_node|INFORMATIONAL|Stmievací profil bol spracovaný pre node č. ${node}|Dimming profile was processed for node no. ${node}|............... ++|switching_profile_was_processed_for_line|INFORMATIONAL|Spínací profil bol spracovaný pre líniu č. ${line}|Switching profile was processed for line no. ${line}|............... ++|thermometer_is_not_responding|WARNING|Teplomer neodpovedá|Thermometer is not responding|............... ++|thermometer_is_responding_again|NOTICE|Teplomer znovu odpovedá|Thermometer is responding again|............... ++|thermometer_sends_invalid_data|WARNING|Teplomer posiela neplatné hodnoty|Thermometer sends invalid data|............... ++|main_switch_has_been_turned_off|CRITICAL|Hlavný vypínač bol vypnutý|Main switch has been turned off|............... ++|main_switch_has_been_turned_on|NOTICE|Hlavný vypínač bol zapnutý|Main switch has been turned on|............... ++|power_supply_has_disconnected_input|ALERT|Napájací zdroj nemá napätie na vstupe|Power supply has disconnected input|............... ++|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_main_open|NOTICE|Hlavné dvere boli otvorené|Main door has been opened|............... ++|door_em_open|NOTICE|Dvere silovej časti boli otvorené|Power door has been opened|............... ++|door_main_open_without_permission|WARNING|Hlavné dvere boli otvorené bez povolenia - zapnutá siréna|Main door has been opened without permission - alarm is on|............... ++|door_em_open_without_permission|WARNING|Dvere silovej časti boli otvorené bez povolenia|Power door has been opened without permission|............... ++|door_main_close|NOTICE|Hlavné dvere boli zatvorené|Main door has been closed|............... ++|door_em_close|NOTICE|Dvere silovej časti boli zatvorené|Power door has been closed|............... ++|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|............... ++|electrometer_ok|NOTICE|Elektromer znovu odpovedá|Electrometer is responding again|............... ++|no_voltage_on_phase|CRITICAL|Na fáze č. ${phase} nie je napätie|No voltage detected on phase no. ${phase}|............... ++|voltage_on_phase_restored|NOTICE|Napätie na fáze č. ${phase} bolo obnovené|Voltage on phase no. ${phase} has been restored|............... ++|flow_start|NOTICE|FLOW bol spustený|FLOW has been started |............... ++|twilight_sensor_nok|ERROR|Sensor súmraku neodpovedá|Twilight sensor is not responding|............... ++|twilight_sensor_ok|NOTICE|Sensor súmraku znovu odpovedá|Twilight sensor is responding again|............... ++|lamps_have_turned_on|NOTICE|Lampy sa zapli|Lamps have turned on|............... ++|lamps_have_turned_off|NOTICE|Lampy sa vypli|Lamps have turned off|............... ++|flow_restart|NOTICE|FLOW bol reštartovaný|FLOW has been restarted|............... ++|nodes_db_changed|NOTICE|Zmena v node databáze|Node db has changed|............... diff --git a/RVO7/databases/pins.table b/RVO7/databases/pins.table new file mode 100755 index 0000000..0eb3d05 --- /dev/null +++ b/RVO7/databases/pins.table @@ -0,0 +1,14 @@ +pin:string|type:string|line:number +*|input1_01|door_condition|0|........... +*|input1_02|rotary_switch_state|0|........... +*|input1_03|rotary_switch_state|0|........... +*|input1_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/RVO7/databases/relays.table b/RVO7/databases/relays.table new file mode 100755 index 0000000..4b7a177 --- /dev/null +++ b/RVO7/databases/relays.table @@ -0,0 +1,5 @@ +line:number|tbname:string|contactor:number|profile:string ++|0|d9x2V5LGYBzXp4mMRAOmKnkPloaqJwnQj6DgrNe3|1||........... ++|1|aw4eELG2DlPMdn1JW0BMVWAqQXOZRN3xB5yp8VKr|9|{"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|ZmRwd93QL4gaezxEbAx2ERk1prn2XjlPvGyqJ6BO|9|{"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|eod9aRWLVl34Gx1Dn7VNeW72rz6qjgmpEXwQJN5Z|9|{"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}|.................................................................................................................. diff --git a/RVO7/databases/settings.table b/RVO7/databases/settings.table new file mode 100755 index 0000000..289d3d2 --- /dev/null +++ b/RVO7/databases/settings.table @@ -0,0 +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|project_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|cloud_topic:string|has_main_switch:boolean|daily_report:boolean|send_changed_node_numbers:boolean ++|rvo_senica_7_ip126|en|28.95619C0E0000|48.70826502|17.28455203|192.168.252.1|rvo_senica_7_ip126|YsLTUaCioE4YdsSQkohC|1883|0|62|unipi|ttyUSB0|1|20|5|6|3|u126|0|1|1|................................................... diff --git a/RVO7/databases/tbdata.nosql b/RVO7/databases/tbdata.nosql new file mode 100755 index 0000000..cbe6dec --- /dev/null +++ b/RVO7/databases/tbdata.nosql @@ -0,0 +1,6 @@ +-"EjgWGnXaLy9opPOz20n4qZ786BlYM3w1deVQvbKr":[{"ts":1760512168402,"values":{"comm_status":"OK"}}],"id":"3000009002jy70b"} +-"d9x2V5LGYBzXp4mMRAOmKnkPloaqJwnQj6DgrNe3":[{"ts":1760512363935,"values":{"Phase_2_power":7.4}}],"id":"3000012002kj70b"} +-"d9x2V5LGYBzXp4mMRAOmKnkPloaqJwnQj6DgrNe3":[{"ts":1760535385421,"values":{"_event":{"type":"notice","status":"new","source":{"func":"modbus_reader","component":"1699965957410","component_name":"Modbus reader","edge":"d9x2V5LGYBzXp4mMRAOmKnkPloaqJwnQj6DgrNe3"},"message":{"sk":"rvo_senica_7_ip126: FLOW bol reštartovaný","en":"rvo_senica_7_ip126: FLOW has been restarted"},"message_data":""}}}],"id":"3000396001te71b"} +-"d9x2V5LGYBzXp4mMRAOmKnkPloaqJwnQj6DgrNe3":[{"ts":1760535385497,"values":{"edge_fw_version":"2025-10-08","maintenance_mode":false}}],"id":"3000396002te70b"} +-"d9x2V5LGYBzXp4mMRAOmKnkPloaqJwnQj6DgrNe3":[{"ts":1760535385510,"values":{"statecode":2,"power_mode":"Automatic"}}],"id":"3000396004te70b"} +-"d9x2V5LGYBzXp4mMRAOmKnkPloaqJwnQj6DgrNe3":[{"ts":1760535385533,"values":{"_event":{"type":"notice","status":"new","source":{"func":"rsPort.open()","component":"1699963668903","component_name":"DIDO_Controller","edge":"d9x2V5LGYBzXp4mMRAOmKnkPloaqJwnQj6DgrNe3"},"message":{"sk":"rvo_senica_7_ip126: FLOW bol spustený","en":"rvo_senica_7_ip126: FLOW has been started "},"message_data":""}}}],"id":"3000396006te70b"} diff --git a/RVO7/databases/tbdatacloud.nosql b/RVO7/databases/tbdatacloud.nosql new file mode 100755 index 0000000..70d50e4 --- /dev/null +++ b/RVO7/databases/tbdatacloud.nosql @@ -0,0 +1,3 @@ +-"d9x2V5LGYBzXp4mMRAOmKnkPloaqJwnQj6DgrNe3":[{"ts":1760535385497,"values":{"edge_fw_version":"2025-10-08","maintenance_mode":false}}],"id":"3000396003te71b"} +-"d9x2V5LGYBzXp4mMRAOmKnkPloaqJwnQj6DgrNe3":[{"ts":1760535385510,"values":{"statecode":2,"power_mode":"Automatic"}}],"id":"3000396005te71b"} +-"d9x2V5LGYBzXp4mMRAOmKnkPloaqJwnQj6DgrNe3":[{"ts":1760535385533,"values":{"_event":{"type":"notice","status":"new","source":{"func":"rsPort.open()","component":"1699963668903","component_name":"DIDO_Controller","edge":"d9x2V5LGYBzXp4mMRAOmKnkPloaqJwnQj6DgrNe3"},"message":{"sk":"rvo_senica_7_ip126: FLOW bol spustený","en":"rvo_senica_7_ip126: FLOW has been started "},"message_data":""}}}],"id":"3000396007te71b"} diff --git a/RVO7/databases/total_energy.js b/RVO7/databases/total_energy.js new file mode 100755 index 0000000..dde340e --- /dev/null +++ b/RVO7/databases/total_energy.js @@ -0,0 +1,38 @@ +//key is rvo_number, value is max energy when lamps are on +const total_energy = { + 1: 580, + 2: 1100, + 3: 3700, + 4: 4100, + 7: 360, + 12: 1700, + 13: 5400, + 14: 440, + 15: 6100, + 16: 4800, + 20: 1600, + 21: 1000, + 22: 2600, + 23: 1000, + 25: 2600, + 33: 240, + 34: 4000, + 35: 2700, + 36: 820, + 37: 1400, + 35: 3500, + 39: 1170, + 41: 740, + 42: 660, + 43: 4900, + 45: 930, + 46: 700, + 47: 1100, + 48: 1500, + 50: 3200, + 53: 1250, + 55: 1000, + 56: 5500 +} + +module.exports = total_energy; diff --git a/RVO7/debug.js b/RVO7/debug.js new file mode 100755 index 0000000..9818194 --- /dev/null +++ b/RVO7/debug.js @@ -0,0 +1,16 @@ +// =================================================== +// FOR DEVELOPMENT +// Total.js - framework for Node.js platform +// https://www.totaljs.com +// =================================================== + +const options = {}; + +// options.ip = '127.0.0.1'; +// options.port = parseInt(process.argv[2]); +// options.config = { name: 'Total.js' }; +// options.sleep = 3000; +// options.inspector = 9229; +// options.watch = ['private']; + +require('total.js/debug')(options); \ No newline at end of file diff --git a/RVO7/err.txt b/RVO7/err.txt new file mode 100755 index 0000000..ccd7808 --- /dev/null +++ b/RVO7/err.txt @@ -0,0 +1,53 @@ +[2024-10-24T20:10:18.748] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-24T21:10:50.075] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-24T22:11:02.037] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-24T23:11:06.288] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-25T00:11:35.707] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-25T01:12:05.113] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-25T02:12:30.670] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-25T03:12:48.440] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-25T04:12:53.945] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-25T05:13:05.571] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-25T06:13:21.398] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-25T07:13:48.830] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-25T08:14:37.596] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-25T09:15:03.167] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-25T10:15:15.076] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-25T11:15:23.135] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-25T12:15:37.011] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-25T13:16:02.586] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-25T14:16:45.579] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-25T15:17:28.542] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2025-09-23T14:02:05.628] [ERROR] errLogs - uncaughtException: Cannot read property 'getHours' of undefined +[2025-09-23T14:02:05.629] [ERROR] errLogs - TypeError: Cannot read property 'getHours' of undefined + at Timeout.emptyReportToSend [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:02:05.630] [ERROR] errLogs - uncaughtException: Cannot read property 'getHours' of undefined +[2025-09-23T14:02:05.630] [ERROR] errLogs - TypeError: Cannot read property 'getHours' of undefined + at Timeout.emptyReportToSend [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:02:05.639] [ERROR] errLogs - uncaughtException: Cannot read property 'getHours' of undefined +[2025-09-23T14:02:05.640] [ERROR] errLogs - TypeError: Cannot read property 'getHours' of undefined + at Timeout.emptyReportToSend [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:02:11.368] [ERROR] errLogs - uncaughtException: date.getHours is not a function +[2025-09-23T14:02:11.368] [ERROR] errLogs - TypeError: date.getHours is not a function + at emptyReportToSend (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at Timeout.dailyReportCheck [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1351:5) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:02:11.369] [ERROR] errLogs - uncaughtException: date.getHours is not a function +[2025-09-23T14:02:11.369] [ERROR] errLogs - TypeError: date.getHours is not a function + at emptyReportToSend (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at Timeout.dailyReportCheck [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1351:5) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:02:11.373] [ERROR] errLogs - uncaughtException: date.getHours is not a function +[2025-09-23T14:02:11.373] [ERROR] errLogs - TypeError: date.getHours is not a function + at emptyReportToSend (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at Timeout.dailyReportCheck [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1351:5) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) diff --git a/RVO7/flow/cloudmqttconnect.js b/RVO7/flow/cloudmqttconnect.js new file mode 100755 index 0000000..b03491f --- /dev/null +++ b/RVO7/flow/cloudmqttconnect.js @@ -0,0 +1,357 @@ +exports.id = 'cloudmqttconnect'; +exports.title = 'Cloud connect mqtt'; +exports.group = 'MQTT'; +exports.color = '#888600'; +exports.version = '1.0.2'; +exports.icon = 'sign-out'; +exports.input = 2; +exports.output = 2; +exports.options = { host: 'tb-stage.worksys.io', port: 1883, clientid: "", username: "" }; + +exports.html = `
+
+
+
Hostname or IP address (if not empty - setting will override db setting)
+
+
+
Port
+
+
+
+
+
@(Client id)
+
+
+
topic
+
+
+
`; + + + +const { promisifyBuilder } = require('./helper/db_helper'); +const fs = require('fs'); +const mqtt = require('mqtt'); +const nosql = NOSQL('tbdatacloud'); + +const SEND_TO = { + debug: 0, + rpcCall: 1, +} + +//CONFIG +let saveTelemetryOnError = true;//backup_on_failure overrides this value +//------------------------ + +const noSqlFileSizeLimit = 4194304;//use 5MB - 4194304 +let insertNoSqlCounter = 0; +let insertBackupNoSqlCounter = 0; +let processingData = false; + +let backup_on_failure = true;//== saveTelemetryOnError - create backup client send failure +let restore_from_backup = 50; //how many rows process at once? +let restore_backup_wait = 3;//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; + + +exports.install = function(instance) { + + var client; + var opts; + var clientReady = false; + + let o = {}; //options + + function main() { + loadSettings(); + } + + //set opts according to db settings + function loadSettings() { + + o = instance.options; + if (!o.topic) o.topic = FLOW.GLOBALS.settings.cloud_topic; + + opts = { + host: o.host, + port: o.port, + clientId: o.clientid, + username: o.username, + rejectUnauthorized: false, + resubscribe: false + }; + + console.log("wsmqttpublich -> loadSettings from instance.options", o); + + if (!o.topic) { + instance.status("Not configured", "white"); + console.log("Cloud mqtt connect: no topic selected"); + return; + } + + connectToTbServer(); + } + + function connectToTbServer() { + var url = "mqtt://" + opts.host + ":" + opts.port; + console.log("MQTT URL: ", url); + + client = mqtt.connect(url, opts); + + client.on('connect', function() { + client.subscribe(`${o.topic}_backward`, (err) => { + if (!err) { + console.log("MQTT subscribed"); + } + }); + instance.status("Connected", "green"); + clientReady = true; + sendClientError = true; + }); + + client.on('reconnect', function() { + instance.status("Reconnecting", "yellow"); + clientReady = false; + }); + + client.on('message', function(topic, message) { + // message is type of buffer + message = message.toString(); + if (message[0] === '{') { + TRY(function() { + + message = JSON.parse(message); + if (message.hasOwnProperty("device") && message.hasOwnProperty("data") && message.data.hasOwnProperty("id")) { + client.publish(`${o.topic}_forward`, `{"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 } }); + } + + }, () => instance.debug('MQTT: Error parsing data', message)); + } + + instance.send(SEND_TO.rpcCall, { "topic": o.topic, "content": message }); + }); + + client.on('close', function() { + clientReady = false; + + instance.status("Disconnected", "red"); + instance.send(SEND_TO.debug, { "message": "Client CLOSE signal received !" }); + }); + + client.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) { + console.log('MQTT client error', err); + sendClientError = false; + } + clientReady = false; + }); + + } + + + instance.on('0', function(data) { + + if (clientReady) { + //do we have some data in backup file? if any, process data from database + if (saveTelemetryOnError) { + //read telemetry data and send back to server + if (!processingData) processDataFromDatabase(); + } + + let stringifiedJson = JSON.stringify(data.data) + client.publish(`${o.topic}_forward`, stringifiedJson, { qos: 1 }); + } + 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 (saveTelemetryOnError && o.topic) { + //create new file from tbdata.nosql, if file size exceeds given limit, and clear tbdata.nosql + makeBackupFromDbFile(); + + //write to tb + data.data.id = UID(); + nosql.insert(data.data); + } + } + }); + + instance.on("1", _ => { + main(); + }) + + instance.close = function(done) { + if (clientReady) { + client.end(); + } + }; + + + function getDbBackupFileCounter(type) { + var files = fs.readdirSync(__dirname + "/../databases"); + + let counter = 0; + for (var i = 0; i < files.length; i++) { + + if (files[i] == "tbdatacloud.nosql") continue; + + if (files[i].endsWith(".nosql")) { + + let pos = files[i].indexOf("."); + if (pos > -1) { + + let fileCounter = counter; + let firstDigit = files[i].slice(0, pos); + + fileCounter = parseInt(firstDigit); + if (isNaN(fileCounter)) fileCounter = 0; + //console.log("getDbBackupFileCounter digit:", files[i], firstDigit, fileCounter, isNaN(fileCounter), type); + + if (type == "max") { + if (fileCounter > counter) { + counter = fileCounter; + } + } + else if (type == "min") { + if (counter == 0) counter = fileCounter; + + if (fileCounter < counter) { + counter = fileCounter; + } + } + } + } + + } + + if (type == "max") counter++; + + return counter; + } + + const makeBackupFromDbFile = async () => { + + if (!saveTelemetryOnError) return; + + //to avoid large file: tbdata.nosql + + //init value is 0! + if (insertNoSqlCounter > 0) { + --insertNoSqlCounter; + return; + } + + insertNoSqlCounter = 100; + + let source = __dirname + "/../databases/tbdatacloud.nosql"; + + var stats = fs.statSync(source); + var fileSizeInBytes = stats.size; + + if (fileSizeInBytes > noSqlFileSizeLimit) { + + let counter = 1; + counter = getDbBackupFileCounter("max"); + + let destination = __dirname + "/../databases/" + counter + "." + "tbdatacloud.nosql"; + + //make backup file + fs.copyFileSync(source, destination); + //fs.renameSync(p, p + "." + counter); + + //clear tbdata.nosql + fs.writeFileSync(source, ""); + fs.truncateSync(source, 0); + + } + } + + const processDataFromDatabase = async () => { + + if (restore_from_backup <= 0) return; + + //calculate diff + const now = new Date(); + let currentTime = now.getTime(); + let diff = currentTime - lastRestoreTime; + + if ((diff / 1000) < restore_backup_wait) { + //console.log("*********restore_backup_wait", diff, restore_backup_wait); + return; + } + + processingData = true; + + //get filename to process + let counter = getDbBackupFileCounter("min"); + + //we have some backup files + let dataBase = 'tbdata'; + + var nosql; + if (counter == 0) dataBase = 'tbdatacloud'; + else dataBase = counter + "." + 'tbdatacloud'; + + nosql = NOSQL(dataBase); + + //select all data - use limit restore_from_backup + let records = await promisifyBuilder(nosql.find().take(restore_from_backup)); + + for (let i = 0; i < records.length; i++) { + if (clientReady) { + + let item = records[i]; + let id = item.id; + + if (id !== undefined) { + //console.log("------------processDataFromDatabase - remove", id, dataBase, i); + + try { + + let message = JSON.parse(JSON.stringify(item)); + delete message.id; + client.publish(`${o.topic}_forward`, JSON.stringify(message), { qos: 1 }); + + //remove from database + await promisifyBuilder(nosql.remove().where("id", id)); + + } catch (error) { + //process error + console.log("processDataFromDatabase", error); + } + + } + + } + else { + processingData = false; + return; + } + } + + if (records.length > 0) { + //clean backup file + if (counter > 0) nosql.clean(); + } + + //no data in db, remove + if (records.length == 0) { + if (counter > 0) nosql.drop(); + } + + const d = new Date(); + lastRestoreTime = d.getTime(); + + processingData = false; + + } + + instance.on('options', main); + +}; diff --git a/RVO7/flow/cmd_manager.js b/RVO7/flow/cmd_manager.js new file mode 100755 index 0000000..25912df --- /dev/null +++ b/RVO7/flow/cmd_manager.js @@ -0,0 +1,3071 @@ +exports.id = 'cmd_manager'; +exports.title = 'CMD Manager'; +exports.group = 'Worksys'; +exports.color = '#5D9CEC'; +exports.version = '0.0.3'; +exports.output = ['red', 'blue', 'yellow', 'blue', 'white', 'green']; +exports.input = 3; +exports.icon = 'cloud-upload'; + +exports.html = ` +
+
+
+
RPC - run RPC calls

+
+
+
@(User)
+
+
+
@(Password)
+
+
+
@(My edge)
+
+
+
+`; +exports.readme = `Manager for CMD calls`; + + +exports.install = function(instance) { + + 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, isEmptyObject, emptyJsObject, writeToFile, addToArrayIfUnique } = require('./helper/utils'); + const bitwise = require('bitwise'); + + var SunCalc = require('./helper/suncalc'); + const DataToTbHandler = require('./helper/DataToTbHandler'); + const errorHandler = require('./helper/ErrorToServiceHandler'); + const { sendNotification } = require('./helper/notification_reporter'); + const process = require('process'); + const { errLogger, logger, monitor } = require('./helper/logger'); + + //for accelerometer purposes + const { naklony } = require("../databases/accelerometer_db"); + + const dbNodes = TABLE("nodes"); + const dbRelays = TABLE("relays"); + + let GLOBALS; + let SETTINGS; + let rsPort; + let tbHandler; + + // runTasks intervals + const SHORT_INTERVAL = 30; + const LONG_INTERVAL = 300; + + //send data to following instances: + const SEND_TO = { + debug: 0, + tb: 1, + http_response: 2, + dido_controller: 3, + infoSender: 4, + dailyReport: 5 + } + + 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 + } + + 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 sendNodeReadout = null; // interval for sending agregate data from node + + 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["1"] = minutes; // dimming + priorities["76"] = minutes; // power + + minutes = 5; + priorities["75"] = minutes; // current + priorities["79"] = minutes; // energy + priorities["87"] = minutes; // aktualny cas + //priorities["84"] = minutes; //accelerometer + + minutes = 10; + priorities["74"] = minutes; // voltage + priorities["77"] = minutes; // power factor + priorities["78"] = minutes; // frequency + + minutes = 60; + priorities["0"] = minutes; // statecode + priorities["6"] = minutes; // dusk + priorities["7"] = minutes; // dawn + priorities["8"] = minutes; // profile + + minutes = 60 * 24; + priorities["89"] = minutes; // verzia fw + priorities["80"] = minutes; // lifetime + + //prikazy kt sa budu spustat na dany node - see config.js in terminal-oms.app. (1 - dimming) + let listOfCommands = [0, 1, 6, 7, 8, 74, 75, 76, 77, 78, 79, 80, 87, 89]; + + 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; + + // holds dusk, dawn (and more) values + let sunCalcResult; + + //helper container for counting resolved group of commands (commands related to set profile) + let cmdCounter = {};//key is node, value is counter + + //TODO: is this set working?? According to previous checks, sets do not work + //if sending of profile to node fails, we send notification and push node into set, so we do not send notification twice + const nodeProfileSendFail = new Set(); + + //we expect to get current temperature in Senica from senica-prod01 + let temperatureInSenica = null; + let accelerometerInterval = null; + + //NOTE: daily reports senica: + //rvo_is_on status, we monitor all nodes - if true, power and dimming should be not 0, if false, 24/7 nodes should be 0, other rvo should not respond + let rvo_is_on; + let previous_rvo_is_on_value; + let handleDailyReport; //setInterval for dailyReportHandler function + let dailyReport = {}; //data needed for daily report + let reportToSend = {}; //final report which we send to cloud + let breakerCounter = null; // status of breakers after flow starts is not in report + let rvoPeriod; // interval of checking dusk dawn and if rvo_is_on + let initialReportStatus = false; + + const DAILY_REPORT_HANDLER_TIME = 3_600_000; + const SET_SUNCALC_RESULT_TIME = 3_600_000; + const SET_RVO_PERIOD_TIME = 300_000; + const ADD_NODE_TO_REPORT_TIME = 3_600_000; + + //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); + + let now = new Date(); + console.log("Cmd-mngr installed", now.toLocaleString("sk-SK")); + + sunCalcResult = calculateDuskDawn(); + + handleRsPort(); + + customTasksInterval = setInterval(reportEdgeDateTimeAndNumberOfLuminaires, 120_000); + setTimeout(reportEdgeDateTimeAndNumberOfLuminaires, 4000); + + //dailyReport related + emptyReportToSend(); + breakerCounter = Object.keys(relaysData).length - 1; // we get number of lines (breakers) except of line 0 + rvoPeriod = setInterval(setRvoPeriod, SET_RVO_PERIOD_TIME); + setTimeout(setRvoPeriod, 3000); + setInterval(setSunCalcResult, SET_SUNCALC_RESULT_TIME); + handleDailyReport = setInterval(dailyReportHandler, DAILY_REPORT_HANDLER_TIME); + + + setCorrectTime = setInterval(setCorrectPlcTimeOnceADay, 60000 * 60); // 1 hour + setCorrectPlcTimeOnceADay(); + + sendNodeReadout = setInterval(sendNodesData, 150_000); + accelerometerInterval = setInterval(accelerometerData, 60000 * 30); //30 min + } + + + 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" + //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 + // if node regular readout does not respond, we repeat request + params.repeatCounter = 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-mngr: 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.byte4 = 96; + params.recipient = 1; + params.register = 8; + params.rw = 1;//write + params.timestamp = timestamp; + 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.byte4 = 96; + params.recipient = 1; + params.register = 8; + params.rw = 1;//write + params.timestamp = timestamp; + 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). + */ + + 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.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.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 + { + + logger.debug("processNodeProfile: Threshold lux level for DUSK/DAWN", node); + + let params = getParams(); + params.type = "set_node_profile"; + params.address = node; + params.register = 96; + params.recipient = 1; + params.rw = 1;//write + params.timestamp = timestamp; + 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(); + params.type = "set_node_profile"; + params.address = node; + params.register = 97; + params.recipient = 1; + params.rw = 1;//write + params.timestamp = timestamp; + 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.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); + + 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); + + console.log("proces profile finished *********************") + } + + + 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; + }); + } + + + 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) { + for (let k in nodesData) { + 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`); + } + } + } + + + function loadRelaysData(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 (value.contactor == 1) processAllNodeProfilesOnLine(value.line); + } + } + + + function reportOnlineNodeStatus(line) { + //Po zapnutí línie broadcastovo aktualizovať predtým čas a o 3 sek neskor - status, brightness + + logger.debug("Cmd-mngr: ----->reportOnlineNodeStatus for line", line); + + const d = new Date(); + + // broadcast actual time + let params = getParams(); + params.address = 0xffffffff;//Broadcast + params.byte1 = d.getHours(); + params.byte2 = d.getMinutes(); + params.recipient = 2;//2 broadcast, address = 0 + params.register = 87;//Actual time + params.rw = 1;//write + params.type = "node-onetime-write"; + params.timestamp = d.getTime() + 30000; + params.info = "run broadcast: Actual time"; + //params.debug = true; + + tasks.push(params); + + let sec = 3; + setTimeout(function() { + //Po zapnutí línie - spraviť hromadný refresh stavu práve zapnutých svietidiel + + let time = Date.now(); + + for (let k in nodesData) { + + //potrebujem nody k danej linii + 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].node_status_before_offline === true || nodesData[k].status === true) { + status = "OK"; + nodesData[k].time_of_last_communication = time; + } + + nodesData[k].readout.status = status; + + updateNodeStatus(k, status === "OK" ? true : false); + if (nodesData[k].hasOwnProperty("node_status_before_offline")) delete nodesData[k].node_status_before_offline; + sendTelemetry({ status: status }, tbname, time); + + //vyreportovanie dimming, current, input power pre liniu pre vsetky nody + //Prud + { + let params = getParams(); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 75;//prud + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = time + 4000; + params.info = 'read current'; + //params.debug = true; + tasks.push(params); + } + + //vykon + { + let params = getParams(); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 76;//výkon + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = time + 4100; + params.info = 'read power'; + //params.debug = true; + + tasks.push(params); + } + //dimming + { + let params = getParams(); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 1;//dimming + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = time + 4200; + params.info = 'read dimming'; + //params.debug = true; + + tasks.push(params); + } + + } + } + + }, sec * 1000); + } + + + function reportOfflineNodeStatus(line) { + + logger.info("Cmd-mngr: ------>reportOffLineNodeStatus for line ", line); + + values = {}; + values["dimming"] = 0;//brightness + values["power"] = 0;//výkon + values["current"] = 0;//prúd + values["status"] = "OFFLINE"; + + const date = Date.now(); + + Object.keys(nodesData).forEach(node => { + + //potrebujem nody k danej linii + if (line == nodesData[node].line || line == undefined) { + + let tbname = nodesData[node].tbname; + let nodeStatus = nodesData[node].status; + + //in case we have reported offline node status, we return (continue with next node) + if (nodeStatus === "OFFLINE") return; + + nodesData[node].node_status_before_offline = nodeStatus; + nodesData[node].status = "OFFLINE"; + nodesData[node].readout = {}; + + sendTelemetry({ ...values }, tbname, date); + } + }); + + } + + + function turnLine(onOrOff, line, info) { + let obj = { + line: line, + command: onOrOff, + info: info + }; + + //to assure, handleDailyReportFunction do not run before rvo_is_on variable changes. So after every line switch we reset the timer + clearInterval(handleDailyReport); + handleDailyReport = setInterval(dailyReportHandler, DAILY_REPORT_HANDLER_TIME); + + //logger.debug("linia", line, obj); + instance.send(SEND_TO.dido_controller, obj); + } + + + 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"; + 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]) { + //CRC_ERROR + message = "NOK"; + error = "CRC_ERROR c1"; + instance.send(SEND_TO.debug, "CRC_ERROR c1"); + } + + 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") { + instance.send(SEND_TO.debug, bytes); + instance.send(SEND_TO.debug, "RESPONSE " + type + " - " + bytes[4]); + + //logger.debug(SEND_TO.debug, "RESPONSE " + type + " - " + bytes[4], bytes); + + error = "type is: " + type; + + message = "NOK"; + } + + return { message, type, error }; + } + + + //BUILD TASKS// + function buildTasks(params) { + + //return; + console.log("buidTAaasks start ****************", params); + monitor.info("buildTasks - params", params); + + let processLine; //defined line + let init = false; + let processLineProfiles = true; + let processBroadcast = true; + let processNodes = true; + + if (params == undefined) { + init = true; + tasks = []; + logger.debug("-->buildTasks clear tasks"); + } + else { + processLineProfiles = params.processLineProfiles; + processBroadcast = false; + processNodes = false; + + processLine = params.line; + } + + let now = new Date(); + + //process line profiles + if (processLineProfiles) { + + let keys = Object.keys(relaysData); + + for (let i = 0; i < keys.length; i++) { + + let line = parseInt(keys[i]); + let profilestr = relaysData[line].profile; + + if (processLine != undefined) { + if (processLine != line) continue; + } + + try { + + /** + * we process line profiles: timepoints, astro clock, lux_sensor, offsets ... + */ + if (profilestr === "") throw ("Profile is not defined"); + let profile = JSON.parse(profilestr); + 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; + + // add name to regular profile timepoint and delete unused end_time key: + time_points.forEach(point => { + point.name = "profileTimepoint" + delete point.end_time; + }); + + //monitor.info("buildTasks: time_points", time_points); + + + /** + * 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 astro clock true, we remove all regular profile points + time_points = []; + + //TODO: when astro clock == true, is offset calculated ??? + //let duskAstroClockOffset = profile.dusk_astro_clock_offset; + //let dawnAstroClockOffset = profile.dawn_astro_clock_offset; + //console.log("line astro clock offsets dusk a dawn: ", duskAstroClockOffset, dawnAstroClockOffset); + // maybe add dusk dawn offset to calculateDuskDawn ?? what dusk dawn will be if dawn_lux_sensor == true?? + //let sunCalcResult = calculateDuskDawn(new Date(), line, duskAstroClockOffset, dawnAstroClockOffset); + + 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 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); + + 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); + + 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(':'); + + let ad = new Date(); + ad.setHours(parseInt(ahours), parseInt(aminutes), 0); + + let bd = new Date(); + bd.setHours(parseInt(bhours), parseInt(bminutes), 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++) { + + let start_time = new Date(); + let [hours, minutes] = time_points[t].start_time.split(':'); + start_time.setHours(parseInt(hours), parseInt(minutes), 0); + + //task is in 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(); + params.type = "relay"; + params.line = parseInt(line); + params.value = time_points[t].value; + params.tbname = relaysData[line].tbname; + params.timestamp = start_time.getTime(); + + // 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; + + //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)) { + 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; + + params.debug = true; + + //turn on/off line + tasks.push(params); + monitor.info("TimePoint params: ", params.info, start_time); + } + + monitor.info("-->time_points final", line, time_points); + + //ensure to turn on/off according to calculated currentValue + let params = getParams(); + params.type = "relay"; + params.line = parseInt(line); + params.tbname = relaysData[line].tbname; + params.value = currentValue; + params.timestamp = i; + params.debug = true; + + //logger.debug(now.toLocaleString("sk-SK")); + 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; + + tasks.push(params); + + } catch (error) { + if (profilestr !== "") { + //errLogger.error(profilestr, error); + console.log(`Cmd_mngr: Unable to process line profile ${line}. Error: `, error); + errorHandler.sendMessageToService(profilestr + "-" + error, 0, "js_error"); + } else { + turnLine("off", line, "No line profile. Switching it off on startup"); + } + } + + } + //logger.debug("tasks:"); + //logger.debug(tasks); + } + + + //NOTE: PROCESS DEFAULT BROADCASTS - Time of dusk, Time of dawn, Actual Time + if (processBroadcast) { + + let d = new Date(); + let time = d.getTime(); + //let sunCalcResult = calculateDuskDawn(); + + { + let params = getParams(); + + params.address = 0xffffffff;//broadcast + params.byte1 = sunCalcResult["dusk_hours"]; + params.byte2 = sunCalcResult["dusk_minutes"]; + params.recipient = 2;//2 broadcast, + params.register = 6;//Time of dusk + params.rw = 1;//write + params.type = "node-regular-write"; + params.timestamp = time + 60000; + params.addMinutesToTimestamp = 60 * 3; //kazde 3 hodiny zisti novy dusk + params.info = "Broadcast-duskTime"; + + tasks.push(params); + } + + { + let params = getParams(); + + params.address = 0xffffffff;//broadcast + params.byte1 = sunCalcResult["dawn_hours"]; + params.byte2 = sunCalcResult["dawn_minutes"]; + params.recipient = 2; //2 broadcast + params.register = 7;//Time of dawn + params.rw = 1;//write + params.type = "node-regular-write"; + params.timestamp = time + 60001; + params.addMinutesToTimestamp = 60 * 3; //kazde 3 hodiny zisti novy dawn + params.info = "Broadcast-dawnTime"; + + tasks.push(params); + } + + { + let params = getParams(); + + params.address = 0xffffffff;//broadcast + params.byte1 = d.getHours(); + params.byte2 = d.getMinutes(); + params.recipient = 2; //2 broadcast + params.register = 87;//Actual time + params.rw = 1;//write + params.type = "node-regular-write"; + params.timestamp = time + 60002; + params.addMinutesToTimestamp = 5; + params.info = "run broadcast: Actual time"; + + tasks.push(params); + } + + } + + //process nodes & tasks - read node's data + if (processNodes) { + + let time = Date.now(); + + for (let k in nodesData) { + let address = parseInt(k); + let tbname = nodesData[k].tbname; + let register = 0; + + for (let i = 0; i < listOfCommands.length; i++) { + + register = listOfCommands[i]; + let addMinutesToTimestamp = priorities[register]; + + let params = getParams(); + + params.address = address; + params.recipient = 1; + params.register = register; + params.type = register == 1 ? "node-dimming-read" : "node-regular-read"; + params.tbname = tbname; + params.timestamp = time + 5000 + i * 500 + addMinutesToTimestamp * 1000; //to make slight time difference + params.addMinutesToTimestamp = addMinutesToTimestamp; + params.info = "Node regular read command"; + + tasks.push(params); + } + + } + } + + + //niektore ulohy sa vygeneruju iba 1x pri starte!!! + if (!init) return; + + + //Master node FW version - modifies SETTINGS.masterNodeIsResponding + { + let params = getParams(); + params.type = "cmd-master"; + params.register = 4; + params.address = 0; + params.timestamp = 0; + params.addMinutesToTimestamp = 5; + params.tbname = SETTINGS.rvoTbName; + params.info = "Master node FW verzia"; + //params.debug = true; + + tasks.push(params); + } + + //kazdu hodinu skontrolovat nastavenie profilov + { + let params = getParams(); + params.type = "process_profiles"; + params.timestamp = Date.now() + 60001; + params.addMinutesToTimestamp = 60;//60 = every hour + params.info = "detekcia nespracovaných profilov linie a nodov"; + //params.debug = true; + + tasks.push(params); + } + + monitor.info("tasks created:", tasks.length); + } + + + /** + * We process line profile, where "astro_clock": true + * example profile: + * + "dawn_lux_sensor": true, + "dusk_lux_sensor": true, + "dawn_lux_sensor_value": 5, + "dusk_lux_sensor_value": 5, + "dawn_astro_clock_offset": 0, + "dusk_astro_clock_offset": 10, + "dawn_lux_sensor_time_window": 30, + "dusk_lux_sensor_time_window": 30, + "dawn_astro_clock_time_window": 60, + "dusk_astro_clock_time_window": 60 + + * if dawn: if currentTimestamp is in timewindow "dawnTime + and - dawn_lux_sensor_time_window" and lux value >= lux_sensor_value, we switch off the line. + * if dusk: we do oposite + * + * dawn: usvit - lux je nad hranicou - vypnem + * dusk: sumrak - lux je pod hranicou - zapnem + */ + 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++) { + + let line = keys[i]; //line is turned off by default + let profilestr = relaysData[line].profile; + const contactor = relaysData[line].contactor; + + try { + + let profile = JSON.parse(profilestr); + if (Object.keys(profile).length === 0) throw ("turnOnOffLinesAccordingToLuxSensor - profile is not defined"); + + 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 (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"); + } + } + } + + //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 (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"); + } + } + } + + } + + } catch (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) { + //MASTER + if (node == 0) return; + + let nodeObj = nodesData[node]; + if (nodeObj == undefined) return; + + let nodeCurrentStatus = nodeObj.status; + const now = Date.now(); + + let data = null; + + if (nodeCurrentStatus === "OFFLINE") { + data = { status: newStatus }; + nodeDbStatusModify(node, data); + return; + } + else 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; + } + + } + + + 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 }; + } + }); + }); + } + + + function processDailyReport() { + + const now = Date.now(); + + for (const [key, value] of Object.entries(dailyReport)) { + + if (["name", "time", "dusk_and_dawn"].includes(key)) continue; + + let poleNumber = nodesData[key]["pole_number"]; + let line = dailyReport[key].line; + let nodeType = nodesData[key]["node_type"]; + let fullNodeName = key // key == nodeNumber + + if (poleNumber && nodeType) { + fullNodeName = SETTINGS.rvo_number + "/" + poleNumber + "_" + line + "L_" + key + "_" + nodeType; + } else { + fullNodeName = key; + } + + if (rvo_is_on) { + + if (value.initialTs) { + if (value.initialTs + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["night_no_data"], fullNodeName); + console.log('report nedostava ziadne data uz hodinu', fullNodeName); + value.initialTs = now; + } + } + if (value.dimmingIsZeroTime) { + if (value.dimmingIsZeroTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["night_dimming=0"], fullNodeName); + console.log("report node dimming je 0 ale ma svietit", fullNodeName); + value.dimmingIsZeroTime = now; + } + } + if (value.powerIsZeroTime) { + if (value.powerIsZeroTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["night_power=0"], fullNodeName); + console.log("report node power je 0 ale ma svietit", fullNodeName); + value.powerIsZeroTime = now; + } + } + + } else { + + let contactorStatus = relaysData[line].contactor; + if (contactorStatus === 1) { + + if (value.initialTs) { + if (value.initialTs + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["day_24/7_no_data"], fullNodeName); + console.log('node je na 24/7 ale nedostava ziadne data uz hodinu', fullNodeName); + value.initialTs = now; + } + } + if (value.dimmingIsOnButShouldBeOffTime) { + if (value.dimmingIsOnButShouldBeOffTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["day_24/7_dimming>0"], fullNodeName); + console.log("report dimming je > 0 ale nema svietit", fullNodeName); + value.dimmingIsOnButShouldBeOffTime = now; + } + } + if (value.powerIsOnButShouldBeOffTime) { + if (value.powerIsOnButShouldBeOffTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["day_24/7_power>0"], fullNodeName); + console.log("report power je > 0 ale nema svietit", fullNodeName); + value.powerIsOnButShouldBeOffTime = now; + } + } + + } + + } + + } + + let report = {}; + report["name"] = SETTINGS.rvo_name; + report["time"] = new Date(); + report["report"] = reportToSend; + + writeToFile(F.path.root("report_data.log"), report, true); + instance.send(SEND_TO.dailyReport, report); + } + + + function dailyReportHandler() { + + if (!SETTINGS.daily_report) return; + + // after dawn we empty reportToSend and start to get data for a new day + const date = new Date(); + const hour = date.getHours(); + const minute = date.getMinutes(); + + console.log("now: ", hour, minute, "suncalc: ", sunCalcResult.dawn_hours, sunCalcResult.dawn_minutes); + + if (hour === sunCalcResult.dawn_hours) { + + //NOTE: ak je este pred usvitom, spracujeme report a posleme na cloud, ak uz je po usvite, resetujeme report plnime data noveho dna + if (minute >= sunCalcResult.dawn_minutes - 2) { + emptyReportToSend(); + emptyDailyReport(); + console.log("Podmienka 1 v dailyReport handler"); + } else { + processDailyReport(); + emptyReportToSend(); + emptyDailyReport(); + console.log("Podmienka 2 v dailyReport handler"); + } + + initialReportStatus = true; + + // ak sa funkcia spusti o hodinu alebo 2 neskor, ako je usvit (moze sa to stat, kedze kazde zapnutie/vypnutie linii odznova spusti casovac. + } else if (hour === sunCalcResult.dawn_hours + 1 || hour === sunCalcResult.dawn_hours + 2) { + if (!initialReportStatus) { + emptyReportToSend(); + emptyDailyReport(); + initialReportStatus = true; + console.log("Podmienka 3 v dailyReport handler"); + } else { + processDailyReport(); + initialReportStatus = true; + console.log("Podmienka 4 v dailyReport handler"); + } + } else { + processDailyReport(); + initialReportStatus = false; + console.log("Podmienka 5 v dailyReport handler"); + } + + console.log("initialReportStatus: ", initialReportStatus); + + } + + function emptyReportToSend() { + emptyJsObject(reportToSend); + reportToSend["contactor"] = { off: [], on: [] }; + reportToSend["night_no_data"] = []; + reportToSend["night_dimming=0"] = []; + reportToSend["night_power=0"] = []; + reportToSend["day_24/7_no_data"] = []; + reportToSend["day_24/7_dimming>0"] = []; + reportToSend["day_24/7_power>0"] = []; + console.log(`resetuje sa reportToSend`); + } + + + //NOTE: ked je initialTs stale rovnaky a zistime ze linie su vypnute (relaysData.line.contactor) - zistim, ci je node na tej linii. Vieme, ze ak je linia vypnuta je to v poriadku lebo nie je na 24/7 linii + //ak je na 24/7 linii, reportujeme, ze neprijima data + function emptyDailyReport() { + const ts = Date.now(); + emptyJsObject(dailyReport); + + //NOTE: do dailyReport dame vsetky nody a pravidelne kontrolujeme ci maju data + //ked nastane sumrak/usvit a svetla maju zacat/prestat svietit, dailyReport spravime nanovo: + for (const [key, value] of Object.entries(nodesData)) { + dailyReport[value.node] = { line: value.line, initialTs: ts }; + } + + console.log("dailyReport: ", dailyReport); + } + + + async function runTasks() { + + clearInterval(interval); + + let currentTimestamp = Date.now(); + + //sort tasks based on timestamp + 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) { + instance.send(SEND_TO.debug, "no tasks created"); + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + if (!rsPort.isOpen) { + instance.send(SEND_TO.debug, "!rsPort.isOpen"); + //await rsPort.open(); + //console.log("Cmd-mngr: !rsPort.isOpen"); + } + + let currentTask = tasks[0]; + + if (currentTask.debug) { + //logger.debug("--->task to process", currentTask); + } + + if (currentTask.timestamp <= currentTimestamp) { + let params = { ...tasks[0] }; + + //allow terminal commands + if (SETTINGS.maintenance_mode && params.type !== "cmd-terminal") { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + let type = params.type; + let tbname = params.tbname; + let node = params.address; + let register = params.register; + let line = null; + let itIsNodeCommand; + + if (nodesData[node] !== undefined) { + line = nodesData[node].line; + itIsNodeCommand = true; + } + + if (params.line !== undefined) line = params.line; + + if (params.addMinutesToTimestamp > 0 || params.timePointName) { + tasks[0].timestamp = currentTimestamp + tasks[0].addMinutesToTimestamp * 60000; + } else { + tasks.shift(); + } + + //kontrola nespracovanych profilov nodov + //TODO: co ked niektore nody neprijimaju profily? kazdu hodinu zahltuju "tasks" array + if (type == "process_profiles") { + //na vsetky zapnutych liniach sa spracuju nespracovane profily nodov + loadRelaysData(); + interval = setInterval(runTasks, SHORT_INTERVAL); + return; + } + + //relay + if (type == "relay") { + + const timePointName = params.timePointName; + const value = params.value; + + let date = new Date(); + date.setDate(date.getDate() + 1);//next day + + let sunCalcResult; + if (timePointName) sunCalcResult = calculateDuskDawn(date, params.line); + + + if (timePointName == "dawn") { + tasks[0].timestamp = sunCalcResult.dawn_time; + } + else if (timePointName == "dusk") { + tasks[0].timestamp = sunCalcResult.dusk_time; + } + else if (timePointName == "luxOn") { + tasks[0].timestamp = sunCalcResult.dusk_time + params.dusk_lux_sensor_time_window * 60000; + } + else if (timePointName == "luxOff") { + tasks[0].timestamp = sunCalcResult.dawn_time + params.dawn_lux_sensor_time_window * 60000; + } + else if (timePointName == "profileTimepoint") { + tasks[0].timestamp = currentTimestamp + tasks[0].addMinutesToTimestamp * 60000; + } + + let info = "aplikovany bod profilu"; + let onOrOff = ""; + value == 1 ? onOrOff = "on" : onOrOff = "off"; + + turnLine(onOrOff, params.line, info); + + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + if (!SETTINGS.masterNodeIsResponding) { + //ak neodpoveda, nebudeme vykonavat ziadne commands, okrem cmd-terminal cmd-master + errorHandler.sendMessageToService("Master node is not responding"); + + let stop = true; + + if (type === "cmd-terminal" || type === "cmd-master") stop = false; + if (stop) { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + } + + let contactorStatus = 1; + if (relaysData[line] != undefined) contactorStatus = relaysData[line].contactor; + + if (line === 0 || contactorStatus === 0 || FLOW.deviceStatus.state_of_breaker[line] === "Off") { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + // TODO: -> status offline for rvo if rotary_switch_state is OFF, this is source of errors + // check if rotary_switch_state == "Off" + // state_of_braker: disconnected = true? + + if (!rsPort.isOpen) { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + //RE-CALCULATE VALUES + //set actual time for broadcast + if (register == 87 && params.recipient === 2) { + var d = new Date(); + params.byte1 = d.getHours();//h + params.byte2 = d.getMinutes();//m + } + + //SET DUSK/DAWN FOR BROADCAST + //Time of dusk + if (register == 6 && params.recipient === 2) { + + if (type != "cmd-terminal") { + params.byte1 = sunCalcResult["dusk_hours"];//h + params.byte2 = sunCalcResult["dusk_minutes"];//m + } + } + + //Time of dawn + if (register == 7 && params.recipient === 2) { + if (type != "cmd-terminal") { + params.byte1 = sunCalcResult["dawn_hours"];//h + params.byte2 = sunCalcResult["dawn_minutes"];//m + } + } + //----------------------- + + instance.send(SEND_TO.debug, "address: " + node + " register:" + register + "type: " + type); + + var startTime, endTime; + startTime = new Date(); + + let saveToTb = true; + if (!tbname) saveToTb = false; + + let resp = com_generic(node, params.recipient, params.rw, register, params.name, params.byte1, params.byte2, params.byte3, params.byte4); + let readBytes = 11; + let timeout = 4000; + + + // await keyword is important, otherwise incorrect data is returned! + await writeData(rsPort, resp, readBytes, timeout).then(function(data) { + + //sometimes happens, that status of node changes to OK, NOK even if line was turned off and should be status OFFLINE. To prevent this, we return if line contactor is 0: + if (itIsNodeCommand && line && relaysData[line].contactor !== 1) return; + + 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); + + //ak sa odpoved zacina 0 - je to v poriadku, inak je NOK + let message = result.message; // OK, NOK + let message_type = result.type; + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + console.log("detected response:", result); + logger.debug("Cmd-mngr: writeData done " + message_type + " duration: " + timeDiff + " type: " + params.debug, params, result); + } + } + + let values = {}; + + //CMD FINISHED + if (message == "OK") { + + updateNodeStatus(node, true); + + //write + if (type == "set_node_profile") { + let result = cmdCounterResolve(node); + if (result == 0) { + dbNodes.modify({ processed: true }).where("node", node).make(function(builder) { + builder.callback(function(err, response) { + + sendNotification("Cmd-mngr: process cmd", SETTINGS.rvoTbName, "dimming_profile_was_successfully_received_by_node", { node: node }, "", SEND_TO.tb, instance); + + logger.debug("--> profil úspešne odoslaný na node č. " + node); + nodesData[node].processed = true; + nodeProfileSendFail.delete(node); + }); + }); + } + } + + //parse read response + if (params.rw == 0) { + values = processResponse(register, dataBytes); //read + } + + if (itIsNodeCommand) { + values.comm_status = "OK"; + values.status = "OK"; + nodesData[node].readout = { ...nodesData[node].readout, ...values }; + + + if (SETTINGS.daily_report) { + //TODO: co ak nedostavame odpovede z nodu ? Musime vyreportovat!! + //v dailyReport teda musi byt kompletny zoznam nodov a neustale kontrolovat, ci maju data, ak nie report node - neodpoveda + if (register === 1) { + + let now = Date.now(); + + if (rvo_is_on === true) { + + if ("dimmingIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].dimmingIsOnButShouldBeOffTime; + + if (values.dimming > 0) { + if ("dimmingIsZeroTime" in dailyReport[node]) delete dailyReport[node].dimmingIsZeroTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if (!("dimmingIsZeroTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], dimmingIsZeroTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } else { + + if ("dimmingIsZeroTime" in dailyReport[node]) delete dailyReport[node].dimmingIsZeroTime; + + if (values.dimming > 0) { + if (!("dimmingIsOnButShouldBeOffTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], dimmingIsOnButShouldBeOffTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if ("dimmingIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].dimmingIsOnButShouldBeOffTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } + } + + if (register === 76) { + + let now = Date.now(); + + if (rvo_is_on === true) { + + if ("powerIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].powerIsOnButShouldBeOffTime; + + if (values.power > 1) { + if ("powerIsZeroTime" in dailyReport[node]) delete dailyReport[node].powerIsZeroTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if (!("powerIsZeroTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], powerIsZeroTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } else { + + if ("powerIsZeroTime" in dailyReport[node]) delete dailyReport[node].powerIsZeroTime; + + if (values.power > 1) { + if (!("powerIsOnButShouldBeOffTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], powerIsOnButShouldBeOffTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if ("powerIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].powerIsOnButShouldBeOffTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } + } + } + + } + + //master node + if (node == 0) { + sendNotification("Cmd-mngr: 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; + } + + if (params.debug) { + //logger.debug("saveToTb", saveToTb, tbname, values); + } + + if (saveToTb && type != "node-regular-read") { + sendTelemetry(values, tbname); + } + else { + if (type == "cmd-terminal") { + terminalCommandResponse(params, "SUCCESS", data); + } + } + + } + else { + terminalCommandResponse(params, "ERROR", data); + handleNokResponseOnRsPort("handleNOK else block", params, itIsNodeCommand, saveToTb); + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + //logger.debug("writeData err: ", error, result, params); + logger.debug("writeData err: ", tbname, node, register, values); + } + } + + //logger.debug(error, result, params); + } + }).catch(function(reason) { + + //console.log("writeData catch exception", reason); + instance.send(SEND_TO.debug, reason); + + terminalCommandResponse(params, "FAILURE", null, reason); + handleNokResponseOnRsPort("handleNOK catch block", params, itIsNodeCommand, saveToTb); + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + logger.debug("-->WRITE FAILED: " + reason, params.debug, params); + } + } + + }); + + } + 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); + } + + + // if node does not respond to request, we repeat request 3 times: + function repeatCommand(params) { + params.repeatCounter++; + if (params.repeatCounter < 4) { + params.timestamp = 0; + params.addMinutesToTimestamp = 0; + tasks.push(params); + } + } + + function handleNokResponseOnRsPort(message, params, itIsNodeCommand, saveToTb) { + + let node = params.address; + let register = params.register; + let type = params.type; + let tbName = params.tbname; + if (!tbName) return; + + let values = {}; + + let updateStatus = updateNodeStatus(node, false); + + if (itIsNodeCommand) { + values.comm_status = "NOK"; + nodesData[node].readout.comm_status = "NOK"; + repeatCommand(params); + } + + if (updateStatus) { + values.status = "NOK"; + nodesData[node].readout.status = "NOK"; + } + + if (type === "node-regular-read") return; + + //master node + if (node == 0) { + sendNotification("Cmd-mngr: 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; + + if (register == 4) values["master_node_version"] = "NOK"; + } + + if (type == "set_node_profile") { + delete cmdCounter[node]; + logger.debug("profil nebol úspešne odoslaný na node č. ", params); + + if (!nodeProfileSendFail.has(node)) { + sendNotification("Cmd-mngr: process cmd", tbName, "configuration_of_dimming_profile_to_node_failed", { node: node }, "", SEND_TO.tb, instance); + nodeProfileSendFail.add(node); + } + } + + // console.log("------",node, register, type, itIsNodeCommand, updateStatus, saveToTb, values); + if (saveToTb) { + sendTelemetry(values, tbName); + } + + } + + + function sendNodesData() { + Object.keys(nodesData).forEach(node => { + if (nodesData[node]["status"] !== "OFFLINE") { + sendTelemetry(nodesData[node].readout, nodesData[node].tbname); + nodesData[node].readout = {}; + } + }) + } + + + /** + * 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; + } + + 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); + + //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 === "OFFLINE") { + nodeObj.node_status_before_offline === true ? number_of_ok_luminaires++ : number_of_nok_luminaires++; + } + else if (nodeObj.status == true) 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 - ts % 60000 //round to full minute + }; + + sendTelemetry(values, SETTINGS.rvoTbName, ts); + } + + + function setSunCalcResult() { + //if next day, we get new dusk and dawn. To make sure, in local timezone 2:00 means 00:00 in utc (it means next day) + if (new Date().getHours() === 2) { + sunCalcResult = calculateDuskDawn(); + console.log("Novy suncalc: ", sunCalcResult); + } + } + + + function setRvoPeriod() { + + if (!SETTINGS.daily_report) return; + + const ts = Date.now(); + + previous_rvo_is_on_value = rvo_is_on; + + if (ts < sunCalcResult.dawn_time - 1_800_000) { // nodes should be on (00:00 -> 06:00 ( - pol hodina, lebo rvo vypina skor) + rvo_is_on = true; + } else if (sunCalcResult.dawn_time - 1_800_000 < ts && ts < sunCalcResult.dusk_time + 1_800_000) { // nodes should be off 06:00 -> 21:00 + rvo_is_on = false; + } else if (sunCalcResult.dusk_time + 1_800_000 < ts) { // nodes should be on 21:00 -> 00:00 + rvo_is_on = true; + } + + if (previous_rvo_is_on_value !== rvo_is_on) { + emptyDailyReport(); + console.log("rvo_is: ", rvo_is_on, previous_rvo_is_on_value); + } + } + + + function handleRsPort() { + + if (rsPort) { + rsPort.removeAllListeners(); + rsPort = null; + } + + //! 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-mngr: rsPort opened success"); + + 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); + + }).catch(function(reason) { + instance.send(SEND_TO.debug, "Cmd-mngr: RPC runSyncExec - promise rejected:" + reason); + }); + }); + + rsPort.on('error', function(err) { + errorHandler.sendMessageToService([exports.title, "unable to open port", SETTINGS.serial_port, err.message], 0); + monitor.info("Cmd-mngr: Error on rsPort", err.message); + }); + + rsPort.on("close", () => { + monitor.info("Cmd-mngr: rsPort closed, reconnecting..."); + setTimeout(handleRsPort, 1000); + }); + + rsPort.open(); + } + + + instance.on("close", () => { + clearInterval(interval); + clearInterval(customTasksInterval); + clearInterval(setCorrectTime); + clearInterval(sendNodeReadout); + clearInterval(accelerometerInterval); + rsPort.close(); + }); + + instance.on("0", _ => { + main(); + }) + + + instance.on("2", _ => { + console.log("dailyReport, reportToSend, rvo_is_on", dailyReport, reportToSend, rvo_is_on, previous_rvo_is_on_value); + }) + + instance.on("1", 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(); + return; + } + else if (flowdata.data == "close") { + rsPort.close(); + return; + } + else if (flowdata.data == "clean") { + tasks = []; + return; + } + else if (flowdata.data == "buildtasks") { + //build & run + return; + } + else if (flowdata.data == "run") { + //durations = []; + + if (tasks.length == 0) { + + buildTasks(); + + if (rsPort.isOpen) { + interval = setInterval(runTasks, 100); + } + else { + instance.send(SEND_TO.debug, "port is not opened!!!"); + } + } + } + else { + //terminal data - object + //logger.debug("flowdata", flowdata.data); + + if (typeof flowdata.data === 'object') { + //logger.debug("dido", flowdata.data); + if (flowdata.data.hasOwnProperty("sender")) { + //data from dido_controller + if (flowdata.data.sender == "dido_controller") { + + if (flowdata.data.hasOwnProperty("cmd")) { + let cmd = flowdata.data.cmd; + + if (cmd == "buildTasks") { + clearInterval(interval); + + logger.debug("-->Cmd-mngr: BUILD TASKS"); + buildTasks(); + + //logger.debug("tasks:"); + //logger.debug(tasks); + + logger.debug("-->Cmd-mngr: RUN TASKS"); + interval = setInterval(runTasks, 5000); + } + else if (cmd == "reload_relays") { + loadRelaysData(flowdata.data.line); + + if (flowdata.data.dataChanged) { + if (!flowdata.data.value) { + reportOfflineNodeStatus(flowdata.data.line); + } + else { + reportOnlineNodeStatus(flowdata.data.line); + } + } + + } + else if (cmd == "rotary_switch_state") { + let value = flowdata.data.value; + + //state was changed + if (rotary_switch_state != value) { + if (value == "Off") { + //vyreportovat vsetky svietdla + reportOfflineNodeStatus(); + } + + rotary_switch_state = value; + } + } + 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) { + + // we send lux_sensor value to all nodes: + let params = getParams(PRIORITY_TYPES.node_broadcast); + + params.recipient = 2;//2 broadcast, address = 0 + params.address = 0xffffffff;//Broadcast + + let ba = longToByteArray(lux_sensor); + + params.byte3 = ba[1];//msb + params.byte4 = ba[0]; + params.timestamp = PRIORITY_TYPES.node_broadcast; + params.info = "run broadcast: Actual Lux level from cabinet"; + params.register = 95;//Actual Lux level from cabinet + params.rw = 1;//write + + tasks.push(params); + + //process profiles + turnOnOffLinesAccordingToLuxSensor(lux_sensor); + } + } + else if (cmd == "state_of_breaker") { + //istic linie + + breakerCounter--; + + let value = flowdata.data.value; + let line = parseInt(flowdata.data.line); + + let dataChanged = false; + if (state_of_breaker[line] != value) dataChanged = true; + + state_of_breaker[line] = value; + + let status = "OK"; + if (value == "Off") status = "NOK"; + + if (dataChanged) { + + if (relaysData.hasOwnProperty(line)) { + let tbname = relaysData[line].tbname; + + if (value == "Off") { + sendNotification("Cmd-mngr: onData", tbname, "circuit_breaker_was_turned_off_line", { line: line }, "", SEND_TO.tb, instance, "circuit_breaker"); + if (breakerCounter < 0) reportToSend["contactor"]["off"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + else { + sendNotification("Cmd-mngr: onData", tbname, "circuit_breaker_was_turned_on_line", { line: line }, "", SEND_TO.tb, instance, "circuit_breaker"); + if (breakerCounter < 0) reportToSend["contactor"]["on"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + + //report status liniu + sendTelemetry({ status: status }, tbname) + + //current value + if (value == "Off") reportOfflineNodeStatus(line); //vyreportovat vsetky svietidla na linii + } + + } + } + else { + logger.debug("undefined cmd", cmd); + } + } + } + + return; + } + + //data from worksys + if (flowdata.data.hasOwnProperty("topic")) { + + let data = getNested(flowdata.data, "content", "data"); + + //if we get temperature in senica from senica-prod01 + let temperature = getNested(flowdata.data, "content", "senica_temperature"); + + if (temperature !== undefined) { + temperatureInSenica = temperature; + return; + } + + if (data === undefined) { + console.log("Invalid rpc command came from platform"); + return; + } + + let command = data.params.command; + let method = data.method; + let profile = data.params.payload; + if (profile == undefined) profile = ""; + let entity = data.params.entities[0]; + let entity_type = entity.entity_type; + let tbname = entity.tb_name; + + instance.send(SEND_TO.debug, flowdata.data); + 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") { + + //let command = data.params.command; + let value = data.params.payload.value; + + if (command == "dimming") { + + let nodeWasFound = false; + let keys = Object.keys(nodesData); + + //logger.debug("-----", keys); + + 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); + + value = parseInt(value); + if (value > 0) value = value + 128; + + params.type = "node-onetime-write"; + params.tbname = tbname; + params.address = node; + params.register = 1; + params.recipient = 1; + params.byte4 = value; + params.rw = 1; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'set dimming from platform'; + //params.debug = true; + + //debug(params); + logger.debug("dimming", params); + + tasks.push(params); + + 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); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 1; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read dimming (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + //pridame aj vyreportovanie - vykon + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 76; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read Input Power (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + //pridame aj vyreportovanie - prud svietidla + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 75; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read Input Current (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + //pridame aj vyreportovanie - power faktor - ucinnik + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 77; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read power factor (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + }, 4000); + + nodeWasFound = true; + break; + } + } + + if (!nodeWasFound) { + logger.debug("set dimming from platform", "unable to find tbname", tbname); + } + } + else { + instance.send(SEND_TO.debug, "undefined command " + command); + logger.debug("undefined command", command); + } + + return; + } + 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++) { + let node = keys[i]; + if (tbname == nodesData[node].tbname) { + + 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"); + + //profil úspešne prijatý pre node č. xx + sendNotification("Cmd-mngr", tbname, "dimming_profile_was_processed_for_node", { node: node }, profile, SEND_TO.tb, instance); + + nodesData[node].processed = false; + nodesData[node].profile = profile; + + processNodeProfile(node); + }); + }); + } + } + } + else { + + instance.send(SEND_TO.debug, "unknown method " + method); + logger.debug("unknown method", method); + + return; + } + } + + //nastav profil linie z platformy + 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") { + + 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++) { + let line = keys[i]; + if (tbname == relaysData[line].tbname) { + //zmazeme tasky + 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) { + + //update profile + logger.debug("worksys - update relay profile done:", profile); + instance.send(SEND_TO.debug, "worksys - update relay profile done"); + + relaysData[line].profile = profile; + + loadRelaysData(line) + logger.debug("loadRelaysData DONE for line", line); + + buildTasks({ processLineProfiles: true, line: line }); + + sendNotification("Cmd-mngr: set profile from worksys", tbname, "switching_profile_was_processed_for_line", { line: line }, profile, SEND_TO.tb, instance); + }); + }); + break; + } + } + } + else if (method == "set_command") { + let value = data.params.payload.value; + + 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; + + 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"); + if (line != 0) reportToSend["contactor"]["off"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + else { + turnLine("on", line, "command received from platform"); + if (line != 0) reportToSend["contactor"]["on"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + } + } + else { + instance.send(SEND_TO.debug, "undefined method " + method); + logger.debug("undefined method", method); + } + + return; + } + else { + instance.send(SEND_TO.debug, "UNKNOW entity_type " + entity_type); + logger.debug("UNKNOW entity_type", entity_type); + } + return; + } + + //terminal + if (!rsPort.isOpen) await rsPort.open(); + + let params = flowdata.data.body; + if (params == undefined) { + //logger.debug("Cmd-mngr: flowdata.data.body is undefined"); + return; + } + + params.priority = PRIORITY_TYPES.terminal; + params.type = "cmd-terminal"; + params.tbname = ""; + params.timestamp = PRIORITY_TYPES.terminal; + params.addMinutesToTimestamp = 0;// do not repeat task!!! + params.debug = true; + + let timestamp = Date.now(); + params.refFlowdataKey = timestamp; + //params.refFlowdata = flowdata; + //refFlowdata = flowdata; + + //console.log("flowdata", flowdata); + + cleanUpRefFlowdataObj(); + + refFlowdataObj[timestamp] = flowdata; + + //fix + //params.address = params.adress; + logger.debug("received from terminal", params); + logger.debug("date/time:", new Date()); + logger.debug("tasks length:", tasks.length); + + //tasks = []; + + //add to tasks + tasks.push(params); + + } + } + }) + + + //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) + } + + + /** + * 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; + + RESTBuilder.make(function(builder) { + + if (!builder) return; + + builder.method('GET'); + builder.url('http://192.168.252.2:8004/gettime?projects_id=1'); + + builder.callback(function(err, response, output) { + + 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); + } + + }); + } + + } 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); + + } else { + //console.log("Read-only", stdout); + + 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]: [ + { + "ts": date, + "values": values + } + ] + } + + tbHandler.sendToTb(dataToTb, instance); + } + + + function calculateDuskDawn(date, line, duskOffset = 0, dawnOffset = 0) { + + if (date === undefined) date = new Date(); + + 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); + } + + //if(profile.dawn_lux_sensor == false) + { + if (profile.hasOwnProperty("dawn_astro_clock_offset")) dawn_astro_clock_offset = parseInt(profile.dawn_astro_clock_offset); + } + + } + + } catch (error) { + if (profilestr != "") { + logger.debug(profilestr); + logger.debug(error); + } + } + + 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; + } + + //Dimming, CCT + else if (register == 1) { + let brightness = 0; + let dimming = byte0; + if (dimming > 128) { + //dimming = -128; + brightness = dimming - 128; + } + + //cct + //Ak Byte3 == 1: CCT = (Byte2*256)+Byte1 + let cct; + if (byte3 == 1) cct = byte2 * 256 + byte1; + else cct = bytesToInt(bytes.slice(0, 3)); + + //cct podla auditu + + values["dimming"] = brightness; + return values; + } + + // + else if (register == 4) { + values["master_node_version"] = bytes[1] + "." + bytes[2]; + //logger.debug("FW Version", register, bytes); + } + + //Napätie + else if (register == 74) { + let voltage = (bytesToInt(bytes) * 0.1).toFixed(1); + values["voltage"] = Number(voltage); + } + + //Prúd + else if (register == 75) { + let current = bytesToInt(bytes); + values["current"] = current; + } + + //výkon + else if (register == 76) { + let power = (bytesToInt(bytes) * 0.1).toFixed(2); + values["power"] = Number(power); + } + + //účinník + else if (register == 77) { + let power_factor = Math.cos(bytesToInt(bytes) * 0.1 * (Math.PI / 180)).toFixed(2); + values["power_factor"] = Number(power_factor); + } + + //frekvencia + else if (register == 78) { + let frequency = (bytesToInt(bytes) * 0.1).toFixed(2); + values["frequency"] = Number(frequency); + } + + //energia + else if (register == 79) { + let energy = bytesToInt(bytes); + values["energy"] = energy / 1000; //energia v kWh -> delit 1000 + } + + //doba života + else if (register == 80) { + let lifetime = (bytesToInt(bytes) / 60).toFixed(2); + values["lifetime"] = Number(lifetime); + } + + //nastavenie profilu + else if (register == 8) { + let time_schedule_settings = bytesToInt(bytes); + values["time_schedule_settings"] = time_schedule_settings; + } + + //naklon - nateraz sa z nodu nevycitava! kvoli problemom s accelerometrom a vracanymi hodnotami, posielame temp a x y z vo funkcii accelerometerData() + else if (register == 84) { + values["temperature"] = byte3 >= 128 ? (byte3 - 128) * (-1) : byte3; + values["inclination_x"] = byte2 >= 128 ? (byte2 - 128) * (-1) : byte2; + values["inclination_y"] = byte1 >= 128 ? (byte1 - 128) * (-1) : byte1; + values["inclination_z"] = byte0 >= 128 ? (byte0 - 128) * (-1) : byte0; + } + + //FW verzia nodu + else if (register == 89) { + //formát: "Byte3: Byte2.Byte1 (Byte0)" + values["fw_version"] = byte3 + ":" + byte2 + "." + byte1 + "(" + byte0 + ")"; + } + + else if (register == 87 || register == 6 || register == 7) { + var d = new Date(); + d.setHours(byte3, byte2, 0, 0); + let timestamp = d.getTime(); + + //aktuálny čas + if (register == 87) values["actual_time"] = timestamp; + //čas súmraku + else if (register == 6) values["dusk_time"] = timestamp; + //čas úsvitu + else if (register == 7) values["dawn_time"] = timestamp; + } + + 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; + + } + + + function getObjectByTbValue(object, tbname) { + return object[Object.keys(object).find(key => object[key].tbname === tbname)]; + } + + + function isObject(item) { + return (typeof item === "object" && !Array.isArray(item) && item !== null); + } + + + // we fake data, that should be received from accelerometer, as they are a bit unreliable. (temperature, x,y,z) + function accelerometerData() { + + if (temperatureInSenica === null) return; + + //clone nodesData and relaysData objects + let nodesData_clone = JSON.parse(JSON.stringify(nodesData)); + let relaysData_clone = JSON.parse(JSON.stringify(relaysData)); + + for (const key in relaysData_clone) { + + const lineData = relaysData_clone[key]; + const lineNumber = lineData.line; + const contactor = lineData.contactor; + + if (lineNumber === 0) continue; + + if (contactor === 1) { + + let date = Date.now(); + + Object.keys(nodesData_clone).forEach((node, index) => { + + setTimeout(function() { + + if (nodesData_clone[node].line === lineNumber) { + + // NOTE: if status of luminaire is NOK or OFFLINE, we do not send data; + let status = nodesData_clone[node].status; + if (status === "OFFLINE" || !status) return; + + let x = null; + if (naklony.hasOwnProperty(node)) x = naklony[node].naklon; + if (x === null) x = 0; + + sendTelemetry({ temperature: Math.round(temperatureInSenica + 10 + Math.floor(Math.random() * 3)), inclination_x: x, inclination_y: 0, inclination_z: 0 }, nodesData_clone[node].tbname, date); + } + + }, (index + 1) * 500); + }) + + } + } + } + + +} // end of instance.export + diff --git a/RVO7/flow/code.js b/RVO7/flow/code.js new file mode 100755 index 0000000..63b31bf --- /dev/null +++ b/RVO7/flow/code.js @@ -0,0 +1,90 @@ +exports.id = 'code'; +exports.title = 'Code'; +exports.group = 'Common'; +exports.color = '#656D78'; +exports.input = true; +exports.output = 1; +exports.author = 'Peter Širka'; +exports.icon = 'code'; +exports.version = '1.2.0'; +exports.options = { outputs: 1, code: 'send(0, value);', keepmessage: true }; + +exports.html = `
+
+
+
@(Number of outputs)
+
@(Minimum is 1)
+
+
+
@(Code)
+
@(Keep message instance)
+
+`; + +exports.readme = `# Code + +This component executes custom JavaScript code as it is and it doesn't contain any secure scope. + +\`\`\`javascript +// value {Object} contains received data +// send(outputIndex, newValue) sends a new value +// error(value) sends an error +// instance {Object} a current component instance +// flowdata {Object} a current flowdata +// repository {Object} a current repository of flowdata +// Example: + +// send() can be execute multiple times +send(0, value); +\`\`\``; + +exports.install = function(instance) { + + var fn; + + instance.on('data', function(response) { + if (fn) { + try { + fn(response.data, instance, response, instance.options, response.repository, require); + } catch (e) { + response.data = e; + instance.throw(response); + } + } + }); + + instance.reconfigure = function() { + try { + if (instance.options.code) { + instance.status(''); + var code = 'var send = function(index, value) { if (options.keepmessage) { flowdata.data = value; instance.send2(index, flowdata); } else instance.send2(index, value);}; var error = function(err) { instance.throw(err); }; ' + instance.options.code; + fn = new Function('value', 'instance', 'flowdata', 'options', 'repository', 'require', code); + } else { + instance.status('Not configured', 'red'); + fn = null; + } + } catch (e) { + fn = null; + instance.error('Code: ' + e.message); + } + }; + + instance.on('options', instance.reconfigure); + instance.reconfigure(); +}; \ No newline at end of file diff --git a/RVO7/flow/comment.js b/RVO7/flow/comment.js new file mode 100755 index 0000000..1e0cd13 --- /dev/null +++ b/RVO7/flow/comment.js @@ -0,0 +1,11 @@ +exports.id = 'comment'; +exports.title = 'Comment'; +exports.group = 'Common'; +exports.color = '#704cff'; +exports.author = 'Martin Smola'; +exports.icon = 'comment'; +exports.traffic = false; +exports.version = '1.0.0'; +exports.readme = '# Comment'; + +exports.install = function() {}; diff --git a/RVO7/flow/count.js b/RVO7/flow/count.js new file mode 100755 index 0000000..fa92ee9 --- /dev/null +++ b/RVO7/flow/count.js @@ -0,0 +1,60 @@ +exports.id = 'count'; +exports.title = 'Count'; +exports.version = '1.0.1'; +exports.author = 'John Graves'; +exports.color = '#656D78'; +exports.icon = 'plus-square'; +exports.input = 2; +exports.output = 1; +exports.options = { increment: 1, initialvalue: 1 }; +exports.readme = `# Counter + +Counter Number of times called.`; + +exports.html = `
+
@(Initial Value)
+
@(Increment)
+

Example Video

+
`; + +exports.readme = `# Count + +This component counts the number of messages received. + +__Response:__ + +Integer value based on the initial value and increment settings. + +__Arguments:__ +- Initial Value: What number should be output on the receipt of the first message. +- Increment: What should the increment be for each following message received.`; + +exports.install = function(instance) { + + var count = 0; + var initialCall = true; + + instance.on('data', function(flowdata) { + var index = flowdata.index; + if (index) { + instance.debug('Reset Count.'); + count = instance.options.initialvalue; + initialCall = true; + } else { + // If this is the first time, set the value to 'initial value' + if(initialCall) { + initialCall = false; + count = instance.options.initialvalue; + } else + count = count+instance.options.increment; + instance.status('Count:' + count); + instance.send2(count); + } + }); + + instance.on('options', function() { + count = instance.options.initialvalue; + initialCall = true; + }); + +}; diff --git a/RVO7/flow/db_connector.js b/RVO7/flow/db_connector.js new file mode 100755 index 0000000..65ee94b --- /dev/null +++ b/RVO7/flow/db_connector.js @@ -0,0 +1,286 @@ +exports.id = 'db_connector'; +exports.title = 'DbConnector'; +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.html = `
+
+
+
DbConnector
+
+
+
`; + +exports.readme = `# read/write data to tables`; + +const instanceSendTo = { + debug: 0, + http_response: 1, +} + +const { promisifyBuilder, makeMapFromDbResult } = require('./helper/db_helper.js'); + +function extractWhereParams(params) +{ + let name = params[0]; + let operator = '='; + let value = params[1]; + + if(params.length == 3) + { + operator = params[1]; + value = params[2]; + } + + return {name: name, operator: operator, value: value}; +} + +exports.install = function(instance) { + + let refFlowdata = null;//holds reference to httprequest flowdata + + instance.on("close", () => { + + }) + + + instance.on("data", async function(flowdata) { + + let params = flowdata.data.body; + console.log("DbConnector", params); + + refFlowdata = flowdata; + + if(refFlowdata != undefined) + { + //make http response + let responseObj = {}; + responseObj["type"] = "SUCESS"; + + try{ + + let table = params.table; + let action = params.action; + + + if(params.data != undefined) + { + let className = params.data.className; + + if(className == "SqlQueryBuilder") + { + let type = params.data.type; + + console.log("SqlQueryBuilder---->", params.data); + + if(type == "SELECT") + { + let table = params.data.queryData.tables[0].table; + + const db = TABLE(table); + var builder = db.find(); + + let result = await promisifyBuilder(builder); + + let response = {}; + response["result"] = result; + response["success"] = true; + + responseObj["data"] = response; + + //console.log(responseObj); + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + } + + return; + } + } + + + console.log("db_connector---->", table, action); + + //actions: read, replace, insert, delete, update... + + if(action == "read") + { + const db = TABLE(params.table); + + //where builder.where('age', '<', 15); + //builder.where('id', 3403); + + var builder = db.find(); + + //https://docs.totaljs.com/latest/en.html#api~DatabaseBuilder~builder.where + if(params.hasOwnProperty("where")) + { + //optionalCan contain "=", "<=", "<", ">=", ">". + //Default value: '=' + + //1.["production_line", 1] + //2. ["or", ["production_line", 1], ["production_line", 2], "end"] + + if (Array.isArray(params.where)) { + + let multipleConditions = false; + + if(params.where[0] == "or") multipleConditions = true; + if (Array.isArray(params.where[0])) multipleConditions = true; + + if(multipleConditions) + { + + for(var i = 0; i < params.where.length; i++) + { + const item = params.where[i]; + + if(item === "or") builder.or(); + + if (Array.isArray(item)) + { + const { name, operator, value } = extractWhereParams(item); + builder.where(name, operator, value); + } + + if(item === "end") builder.end(); + + } + + } + else + { + const { name, operator, value } = extractWhereParams(params.where); + builder.where(name, operator, value); + } + + } + + /* + if(params.where.length >=2 ) + { + let name = params.where[0]; + let operator = '='; + let value = params.where[1]; + + if(params.where.length == 3) + { + operator = params.where[1]; + value = params.where[2]; + } + + builder.where(name, operator, value); + } + */ + } + + if(params.hasOwnProperty("between")) + { + builder.between(params.between[0], params.between[1], params.between[2]); + } + + let response = await promisifyBuilder(builder); + responseObj["data"] = response; + + //console.log(responseObj); + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + + return; + } + + if(action == "delete") + { + + } + + + if(action == "update") + { + //! data receiving from terminal (params) + // { + // hostname: 'localhost', + // table: 'settings', + // action: 'update', + // body: { + // rvo_name: 'terrrr', + // lang: 'en', + // temperature_adress: '28.427B45920702', + // latitude: 48.70826502, + // longitude: 17.28455203, + // mqtt_host: '192.168.252.4', + // mqtt_clientid: 'showroom_test_panel_led', + // mqtt_username: 'xmRd6RJxW53WZe4vMFLU', + // mqtt_port: 1883, + // maintanace_mode: false + // } + // } + const tableToModify = TABLE(params.table); + const newValues = params.body; + + tableToModify.modify(newValues).make(function(builder) { + + builder.callback(function(err, response) { + + if(!err) + { + responseObj["data"] = response; + responseObj["tableUpdated"] = true; + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + } + }); + }); + + } + + if(action == "replace") + { + //truncate table + const db = TABLE(params.table); + var builder = db.remove(); + db.clean(); + + //insert data + let data = params.data; + + for(let i = 0; i < data.length; i++) + { + //console.log(data[i]); + db.insert(data[i]); + } + + console.log("insert done"); + + let responseObj = {}; + responseObj["type"] = "SUCESS"; + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + + + } + + + + } catch (error) { + //console.log(error); + responseObj["type"] = "ERROR"; + responseObj["message"] = error; + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + } + } + }) +} + + diff --git a/RVO7/flow/db_init.js b/RVO7/flow/db_init.js new file mode 100755 index 0000000..b399878 --- /dev/null +++ b/RVO7/flow/db_init.js @@ -0,0 +1,113 @@ +exports.id = 'db_init'; +exports.title = 'DB Initialization'; +exports.group = 'Worksys'; +exports.color = '#888600'; +exports.version = '1.0.2'; +exports.icon = 'sign-out'; +exports.output = 2; + +exports.readme = ` + # DB initialization +`; + +const { promisifyBuilder, makeMapFromDbResult } = require('./helper/db_helper.js'); +const { initNotification } = require('./helper/notification_reporter'); +const errorHandler = require('./helper/ErrorToServiceHandler'); +const total_energy = require('../databases/total_energy'); + +const SEND_TO = { + db_init: 0, + infoSender: 1 +}; + + +exports.install = async function(instance) { + const dbNodes = TABLE("nodes"); + const dbRelays = TABLE("relays"); + const dbSettings = TABLE("settings"); + 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 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.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"]; + Object.keys(dbs.nodesData).forEach(node => dbs.nodesData[node].readout = {}) + + let rvo_number = responseSettings[0]["rvo_name"].match(/\D+(\d{1,2})_/)[1]; + + dbs.settings = { + edge_fw_version: "2025-10-08", //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"], + phases: responseSettings[0]["phases"], + cloud_topic: responseSettings[0]["cloud_topic"], + has_main_switch: responseSettings[0]["has_main_switch"], + daily_report: responseSettings[0]["daily_report"], + send_changed_node_numbers: responseSettings[0]["send_changed_node_numbers"], + rvo_number: rvo_number, + + //dynamic values + masterNodeIsResponding: true, //cmd_manager + maintenance_mode: false, + } + + + dbs.settings.energy_to_switch_lamps = total_energy[rvo_number]; + if (dbs.settings.energy_to_switch_lamps === undefined) console.log('=============== db_init.js: energy_to_switch_lamps is undefined'); + + FLOW.dbLoaded = true; + errorHandler.setProjectId(dbs.settings.project_id); + initNotification(); + + //APP START - send to data services + const toService = { + id: dbs.settings.project_id, + name: dbs.settings.rvo_name, + fw_version: dbs.settings.edge_fw_version, + startdate: new Date().toISOString().slice(0, 19).replace('T', ' '), + js_error: "", + error_message: "" + }; + + instance.send(SEND_TO.infoSender, toService); + console.log("----------------> START - message send to service", toService); + + setTimeout(() => { + console.log("DB_INIT - data loaded"); + instance.send(SEND_TO.db_init, "_") + }, 5000) + +}; + diff --git a/RVO7/flow/debug.js b/RVO7/flow/debug.js new file mode 100755 index 0000000..00cb259 --- /dev/null +++ b/RVO7/flow/debug.js @@ -0,0 +1,100 @@ +exports.id = 'debug'; +exports.title = 'Debug'; +exports.author = 'Peter Širka'; +exports.color = '#967ADC'; +exports.click = true; +exports.input = true; +exports.icon = 'bug'; +exports.version = '2.0.4'; +exports.options = { enabled: true, repository: false, type: 'data' }; +exports.readme = `# Debug + +Prints data to the debug tab.`; + +exports.html = `
+
+
+
@(Output type)
+
@(Path to the property (leave empty to show the whole data object))
+
@(A group name)
+
@(Enabled)
+
+
+
`; + +exports.install = function(instance) { + + instance.on('data', function(response) { + if (instance.options.enabled) { + + var opt = instance.options; + var rep = response.repository; + var val = response.data; + var id = response.id; + + switch (instance.options.type){ + case 'both': + var data = {}; + data.repository = rep; + data.data = val instanceof Error ? { error: val.message, stack: val.stack } : val; + instance.debug(safeparse(opt.property ? U.get(data, opt.property) : data), undefined, opt.group, id); + break; + case 'repository': + instance.debug(safeparse(opt.property ? U.get(rep, opt.property) : rep), undefined, opt.group, id); + break; + case 'data': + default: + if (val instanceof Error) + instance.debug({ error: val.message, stack: val.stack }, undefined, opt.group, id); + else + instance.debug(safeparse(opt.property ? U.get(val, opt.property) : val), undefined, opt.group, id); + break; + } + } + }); + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + instance.save(); + }); + + instance.on('options', function() { + instance.custom.status(); + }); + + instance.custom.status = function() { + instance.status(instance.options.enabled ? 'Enabled' : 'Disabled'); + }; + + instance.custom.status(); + + function safeparse(o) { + + if (o instanceof Buffer) + return o; + + if (o === undefined) + return 'undefined'; + + if (o === null) + return 'null'; + + var cache = []; + var str = JSON.stringify(o, function(key, value) { + if (typeof value === 'object' && value !== null) { + if (cache.indexOf(value) !== -1) { + try { + return JSON.parse(JSON.stringify(value)); + } catch (error) { + return; + } + } + cache.push(value); + } + return value; + }); + cache = null; + return JSON.parse(str); + } +}; diff --git a/RVO7/flow/designer.json b/RVO7/flow/designer.json new file mode 100755 index 0000000..580f5a3 --- /dev/null +++ b/RVO7/flow/designer.json @@ -0,0 +1,3102 @@ +{ + "tabs": [ + { + "name": "MAIN PUSH", + "linker": "main-push", + "id": "1612772287426", + "index": 0 + }, + { + "name": "CMD manager", + "linker": "cmd-manager", + "id": "1615551125555", + "index": 1 + }, + { + "name": "Devices", + "linker": "devices", + "id": "1611921777196", + "index": 2 + } + ], + "components": [ + { + "id": "1611951142547", + "component": "debug", + "tab": "1611921777196", + "name": "ERROR", + "x": 598, + "y": 60, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#DA4453", + "notes": "" + }, + { + "id": "1612776786008", + "component": "wsmqttpublish", + "tab": "1612772287426", + "name": "WS MQTT publish", + "x": 281.75, + "y": 174, + "connections": { + "0": [ + { + "index": "0", + "id": "1615551060773" + } + ], + "1": [ + { + "index": "0", + "id": "1618300858252" + }, + { + "index": "0", + "id": "1618558465485" + } + ], + "2": [ + { + "index": "0", + "id": "1634303685503" + } + ], + "3": [ + { + "index": "0", + "id": "1731068754606" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Connected", + "color": "green" + }, + "options": { + "username": "", + "clientid": "", + "port": "1883", + "host": "" + }, + "color": "#888600", + "notes": "" + }, + { + "id": "1612778461252", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "tb-push", + "x": 72.75, + "y": 328, + "connections": { + "0": [ + { + "index": "0", + "id": "1612783322136" + }, + { + "index": "1", + "id": "1612776786008" + }, + { + "index": "0", + "id": "1731068754606" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1612783322136", + "component": "debug", + "tab": "1612772287426", + "name": "to TB", + "x": 283.75, + "y": 324, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615551060773", + "component": "debug", + "tab": "1612772287426", + "name": "errors from MQTT Broker", + "x": 594, + "y": 57, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#DA4453", + "notes": "" + }, + { + "id": "1615563373927", + "component": "debug", + "tab": "1615551125555", + "name": "Debug", + "x": 755, + "y": 155, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#DA4453", + "notes": "" + }, + { + "id": "1615566865233", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "tb-push", + "x": 755, + "y": 248, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1615798582262", + "component": "debug", + "tab": "1615551125555", + "name": "CMD_debug", + "x": 755, + "y": 346, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615802995322", + "component": "debug", + "tab": "1611921777196", + "name": "Debug", + "x": 596.8833312988281, + "y": 566.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Disabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": false + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615809128443", + "component": "debug", + "tab": "1611921777196", + "name": "tempToTb", + "x": 595.8833312988281, + "y": 658.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615809595184", + "component": "virtualwireout", + "tab": "1611921777196", + "name": "tb-push", + "x": 597.8833312988281, + "y": 377.25, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1616165795916", + "component": "httproute", + "tab": "1615551125555", + "name": "POST /terminal", + "x": 135, + "y": 547, + "connections": { + "0": [ + { + "index": "0", + "id": "1684060205000" + }, + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Listening", + "color": "green" + }, + "options": { + "timeout": 10, + "cachepolicy": 0, + "cacheexpire": "5 minutes", + "size": 5, + "url": "/terminal", + "method": "POST", + "name": "", + "flags": [ + "id:1616165795916", + "post", + 10000 + ], + "emptyresponse": false + }, + "color": "#5D9CEC", + "notes": "### Configuration\n\n- __POST /terminal__\n- flags: \n- maximum request data length: __5 kB__\n- empty response: __false__\n- cache policy: __no cache__\n- cache expire: __5 minutes__", + "cloning": false + }, + { + "id": "1616165824813", + "component": "httpresponse", + "tab": "1615551125555", + "name": "HTTP Response", + "x": 753, + "y": 423, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "json" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1617104731852", + "component": "debug", + "tab": "1615551125555", + "name": "DIDO_Debug", + "x": 669, + "y": 1040, + "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": "turnOff line", + "x": 133, + "y": 1161, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "object", + "data": "{line: 3, command: \"turnOff\", force: true}" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1617115013095", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "tb-push", + "x": 669, + "y": 1150, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1617284749681", + "component": "trigger", + "tab": "1615551125555", + "name": "update profile / node", + "x": 112, + "y": 208, + "connections": { + "0": [ + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "data": "profile_nodes", + "datatype": "string" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1618235171399", + "component": "trigger", + "tab": "1615551125555", + "name": "tun tasks", + "x": 184, + "y": 279, + "connections": { + "0": [ + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "data": "run" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1618300858252", + "component": "debug", + "tab": "1612772287426", + "name": "wsmqtt-exit1", + "x": 597.8833312988281, + "y": 149, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1618393583970", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "to-cmd-manager", + "x": 668.8833312988281, + "y": 1269, + "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": 132.88333129882812, + "y": 367, + "connections": { + "0": [ + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "platform-rpc-call", + "color": "gray" + }, + "options": { + "wirename": "platform-rpc-call" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1618393759854", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "cmd_to_dido", + "x": 119.88333129882812, + "y": 1007, + "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": 752.8833312988281, + "y": 527, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "cmd_to_dido", + "color": "gray" + }, + "options": { + "wirename": "cmd_to_dido" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1618558465485", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "platform-rpc-call", + "x": 597.8833312988281, + "y": 247, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "platform-rpc-call", + "color": "gray" + }, + "options": { + "wirename": "platform-rpc-call" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1618572059773", + "component": "trigger", + "tab": "1615551125555", + "name": "turnOn line", + "x": 132, + "y": 1085, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "data": "{line: 1, command: \"turnOn\", force: true}", + "datatype": "object" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1619515097737", + "component": "cmd_manager", + "tab": "1615551125555", + "name": "CMD Manager", + "x": 452.1091003417969, + "y": 341.05455017089844, + "connections": { + "0": [ + { + "index": "0", + "id": "1615563373927" + } + ], + "1": [ + { + "index": "0", + "id": "1615566865233" + }, + { + "index": "0", + "id": "1615798582262" + } + ], + "2": [ + { + "index": "0", + "id": "1616165824813" + } + ], + "3": [ + { + "index": "0", + "id": "1618393827655" + } + ], + "4": [ + { + "index": "0", + "id": "1635936391935" + } + ], + "5": [ + { + "index": "0", + "id": "1757006030239" + }, + { + "index": "0", + "id": "1757006060377" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1619605019281", + "component": "httproute", + "tab": "1615551125555", + "name": "GET db", + "x": 173, + "y": 653, + "connections": { + "0": [ + { + "index": "0", + "id": "1684060205000" + }, + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Listening", + "color": "green" + }, + "options": { + "timeout": 5, + "cachepolicy": 0, + "cacheexpire": "5 minutes", + "size": 5, + "url": "/db", + "method": "GET", + "name": "", + "flags": [ + "id:1619605019281", + "get", + 5000 + ] + }, + "color": "#5D9CEC", + "notes": "### Configuration\n\n- __GET /db__\n- flags: undefined\n- maximum request data length: __5 kB__\n- empty response: __undefined__\n- cache policy: __no cache__\n- cache expire: __5 minutes__", + "cloning": false + }, + { + "id": "1619784672383", + "component": "trigger", + "tab": "1615551125555", + "name": "turnOnAlarm", + "x": 120, + "y": 1234, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "object", + "data": "{command: \"turnOnAlarm\"}" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1619784812964", + "component": "trigger", + "tab": "1615551125555", + "name": "turnOffAlarm", + "x": 118, + "y": 1307, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "object", + "data": "{command: \"turnOffAlarm\"}" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1621340721628", + "component": "virtualwireout", + "tab": "1611921777196", + "name": "modbus_to_dido", + "x": 599, + "y": 471, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "modbus_to_dido", + "color": "gray" + }, + "options": { + "wirename": "modbus_to_dido" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1622640022885", + "component": "httproute", + "tab": "1615551125555", + "name": "POST /db_connector", + "x": 98, + "y": 1586, + "connections": { + "0": [ + { + "index": "0", + "id": "1622640073521" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Listening", + "color": "green" + }, + "options": { + "timeout": 5, + "cachepolicy": 0, + "cacheexpire": "5 minutes", + "size": 5, + "url": "/db_connector", + "method": "POST", + "flags": [ + "id:1622640022885", + "post", + 5000 + ] + }, + "color": "#5D9CEC", + "notes": "### Configuration\n\n- __POST /db_connector__\n- flags: \n- maximum request data length: __5 kB__\n- empty response: __undefined__\n- cache policy: __no cache__\n- cache expire: __5 minutes__", + "cloning": false + }, + { + "id": "1622640073521", + "component": "db_connector", + "tab": "1615551125555", + "name": "DbConnector", + "x": 372, + "y": 1572, + "connections": { + "1": [ + { + "index": "0", + "id": "1622641420685" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "edge": "undefined" + }, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1622641420685", + "component": "httpresponse", + "tab": "1615551125555", + "name": "HTTP Response", + "x": 596, + "y": 1586, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1634303504177", + "component": "monitormemory", + "tab": "1612772287426", + "name": "RAM", + "x": 69.88333129882812, + "y": 888.5, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465281992" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "858.88 MB / 985.68 MB", + "color": "gray" + }, + "options": { + "enabled": true, + "interval": 30000 + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1634303533779", + "component": "monitordisk", + "tab": "1612772287426", + "name": "disk", + "x": 70.88333129882812, + "y": 982.5, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465821120" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "5.78 GB / 7.26 GB", + "color": "gray" + }, + "options": { + "enabled": true, + "path": "/", + "interval": 30000 + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1634303595494", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "send-to-services", + "x": 51.883331298828125, + "y": 1400.5, + "connections": { + "0": [ + { + "index": "0", + "id": "1634463186563" + }, + { + "index": "1", + "id": "1634488120710" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1634303602169", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "send-to-services", + "x": 426.8833312988281, + "y": 878.5, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1634303685503", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "send-to-services", + "x": 600.8833312988281, + "y": 341.5, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1634303743260", + "component": "httprequest", + "tab": "1612772287426", + "name": "192.168.252.2:8004/sentmessage", + "reference": "", + "x": 506.8833312988281, + "y": 1331.7333374023438, + "connections": { + "0": [ + { + "index": "0", + "id": "1635327431236" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "url": "http://192.168.252.2:8004/sentmessage", + "method": "POST", + "stringify": "json" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1634463186563", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 305.75, + "y": 1442, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634464580289", + "component": "code", + "tab": "1612772287426", + "name": "Code", + "x": 245, + "y": 787, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465243324" + }, + { + "index": "0", + "id": "1634303602169" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "keepmessage": true, + "code": "let response = {};\nresponse.cpu = value.cpu;\nresponse.uptime = value.uptime;\n\nsend(0, response);", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1634465243324", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 428, + "y": 784, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634465281992", + "component": "code", + "tab": "1612772287426", + "name": "Code", + "x": 245, + "y": 884, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465338103" + }, + { + "index": "0", + "id": "1634303602169" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "keepmessage": true, + "code": "value.sender = \"ram\";\n\nlet response = {};\n\nresponse.memory_total = Math.round(value.total / (1024 ** 2));\nresponse.memory_free = Math.round(value.free / (1024 ** 2));\nresponse.memory_used = Math.round(value.used / (1024 ** 2));\n\nsend(0, response);", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1634465338103", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 429, + "y": 976, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634465821120", + "component": "code", + "tab": "1612772287426", + "name": "Code", + "x": 245, + "y": 978, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465892500" + }, + { + "index": "0", + "id": "1634303602169" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "keepmessage": true, + "code": "value.sender = \"hdd\";\n\nlet response = {};\n\nresponse.hdd_total = Math.round(value.total / (1024 ** 2));\nresponse.hdd_free = Math.round(value.free / (1024 ** 2));\nresponse.hdd_used = Math.round(value.used / (1024 ** 2));\n\nsend(0, response);", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1634465892500", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 432, + "y": 1068, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634484067516", + "component": "debug", + "tab": "1612772287426", + "name": "Send info", + "x": 513, + "y": 1441, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634488120710", + "component": "infosender", + "tab": "1612772287426", + "name": "Info sender", + "x": 301, + "y": 1336, + "connections": { + "0": [ + { + "index": "0", + "id": "1634484067516" + }, + { + "index": "0", + "id": "1634303743260" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "edge": "undefined" + }, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1635327431236", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 837.8833312988281, + "y": 1325.5, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1635936391935", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "send-to-services", + "x": 753, + "y": 623, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1637069803394", + "component": "monitorconsumption", + "tab": "1612772287426", + "name": "CPU", + "x": 69, + "y": 791, + "connections": { + "0": [ + { + "index": "0", + "id": "1634464580289" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "49.2% / 69.91 MB", + "color": "gray" + }, + "options": { + "monitorfiles": true, + "monitorconnections": true, + "monitorsize": true, + "monitorconsumption": true, + "enabled": true, + "interval": 30000 + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1683664161036", + "component": "debug", + "tab": "1615551125555", + "name": "CMDtoDIDO", + "x": 392, + "y": 1012, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1683981346282", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "from-dido-controller", + "x": 112, + "y": 459, + "connections": { + "0": [ + { + "index": "0", + "id": "1684055037116" + }, + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "from-dido-controller", + "color": "gray" + }, + "options": { + "wirename": "from-dido-controller" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1684055037116", + "component": "debug", + "tab": "1615551125555", + "name": "from dido to cmd", + "x": 451, + "y": 532, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1684060205000", + "component": "debug", + "tab": "1615551125555", + "name": "HTTP routes", + "x": 450, + "y": 639, + "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": "MDBToDido", + "x": 598, + "y": 147, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1699963668903", + "component": "dido_controller", + "tab": "1615551125555", + "name": "DIDO_Controller", + "x": 397, + "y": 1131, + "connections": { + "0": [ + { + "index": "0", + "id": "1617104731852" + } + ], + "1": [ + { + "index": "0", + "id": "1617104731852" + }, + { + "index": "0", + "id": "1617115013095" + } + ], + "2": [ + { + "index": "0", + "id": "1618393583970" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "edge": "undefined" + }, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1699964678894", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "modbus_to_dido", + "x": 96, + "y": 924, + "connections": { + "0": [ + { + "index": "0", + "id": "1699963668903" + }, + { + "index": "0", + "id": "1699964793925" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "modbus_to_dido", + "color": "gray" + }, + "options": { + "wirename": "modbus_to_dido" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1699964793925", + "component": "debug", + "tab": "1615551125555", + "name": "modbusToDido", + "x": 388, + "y": 920, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1699965957410", + "component": "modbus_reader", + "tab": "1611921777196", + "name": "Modbus reader", + "x": 232, + "y": 175, + "connections": { + "0": [ + { + "index": "0", + "id": "1611951142547" + } + ], + "1": [ + { + "index": "0", + "id": "1621340721628" + }, + { + "index": "0", + "id": "1684179110403" + }, + { + "index": "0", + "id": "1717441414646" + } + ], + "2": [ + { + "index": "0", + "id": "1615809595184" + }, + { + "index": "0", + "id": "1714752862828" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1700411878636", + "component": "thermometer", + "tab": "1611921777196", + "name": "Thermometer", + "x": 234.75, + "y": 444, + "connections": { + "0": [ + { + "index": "0", + "id": "1615802995322" + } + ], + "1": [ + { + "index": "0", + "id": "1615809595184" + }, + { + "index": "0", + "id": "1615809128443" + } + ], + "2": [ + { + "index": "0", + "id": "1621340721628" + }, + { + "index": "0", + "id": "1732889185927" + }, + { + "index": "0", + "id": "1717441414646" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#5CB36D", + "notes": "" + }, + { + "id": "1714752862828", + "component": "debug", + "tab": "1611921777196", + "name": "MDBToTb", + "x": 766, + "y": 324, + "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": 764.0833282470703, + "y": 222, + "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\telse if(value.status === \"NOK-thermometer\")\n\t{\n\t\tsend(0, {\"thermometer\": \"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\telse if(value.values.hasOwnProperty(\"temperature\"))\n\t{\n\t\tsend(0, {\"thermometer\": \"OK\"});\n\t}\n}", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1717442627834", + "component": "debug", + "tab": "1611921777196", + "name": "modbus service", + "x": 966.0833282470703, + "y": 165, + "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": 968.0833282470703, + "y": 268, + "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": 88.75, + "y": 1685, + "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": 296, + "y": 1671, + "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\", \"Flow has been restarted\", \"Node db has changed\"]", + "types": "[\"emergency\", \"critical\", \"error\", \"alert\"]", + "name": "" + }, + "color": "#30E193", + "notes": "" + }, + { + "id": "1718016073501", + "component": "httprequest", + "tab": "1612772287426", + "name": "http://192.168.252.2:8004/slack", + "x": 495, + "y": 1753, + "connections": { + "0": [ + { + "index": "0", + "id": "1718016086212" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "url": "http://192.168.252.2:8004/slack", + "method": "POST", + "stringify": "json" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1718016086212", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 832, + "y": 1664, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "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": 87, + "y": 1591, + "connections": { + "0": [ + { + "index": "0", + "id": "1718016052341" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "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\": \"\" } } } ] }", + "datatype": "object" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1729855334955", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "platform-rpc-call", + "x": 599.9333343505859, + "y": 541.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "platform-rpc-call", + "color": "gray" + }, + "options": { + "wirename": "platform-rpc-call" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1729855371093", + "component": "debug", + "tab": "1612772287426", + "name": "rpc cloud", + "x": 601.9333343505859, + "y": 440.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1731068658334", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 75.75, + "y": 184, + "connections": { + "0": [ + { + "index": "0", + "id": "1612776786008" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731068754606", + "component": "cloudmqttconnect", + "tab": "1612772287426", + "name": "MQTT to senica-prod01", + "x": 284.75, + "y": 452, + "connections": { + "1": [ + { + "index": "0", + "id": "1729855371093" + }, + { + "index": "0", + "id": "1729855334955" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Connected", + "color": "green" + }, + "options": { + "username": "", + "clientid": "", + "port": "2764", + "host": "192.168.252.2", + "topic": "" + }, + "color": "#888600", + "notes": "" + }, + { + "id": "1731069001548", + "component": "db_init", + "tab": "1612772287426", + "name": "DB Initialization", + "x": 1003.75, + "y": 240.25, + "connections": { + "0": [ + { + "index": "0", + "id": "1731069033416" + } + ], + "1": [ + { + "index": "0", + "id": "1747561603739" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#888600", + "notes": "" + }, + { + "id": "1731069033416", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "db-init", + "x": 1244.75, + "y": 233.25, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069059135", + "component": "showdb", + "tab": "1612772287426", + "name": "Show db data", + "x": 1186.75, + "y": 821.25, + "connections": { + "0": [ + { + "index": "0", + "id": "1731069079243" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#888600", + "notes": "" + }, + { + "id": "1731069079243", + "component": "debug", + "tab": "1612772287426", + "name": "dbData", + "x": 1390.75, + "y": 870.25, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1731069116691", + "component": "trigger", + "tab": "1612772287426", + "name": "settings", + "x": 934.75, + "y": 669.75, + "connections": { + "0": [ + { + "index": "0", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069131637", + "component": "trigger", + "tab": "1612772287426", + "name": "relaysData", + "x": 876.75, + "y": 733.75, + "connections": { + "0": [ + { + "index": "1", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069137374", + "component": "trigger", + "tab": "1612772287426", + "name": "nodesData", + "x": 852.75, + "y": 794.75, + "connections": { + "0": [ + { + "index": "2", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069179846", + "component": "trigger", + "tab": "1612772287426", + "name": "pinsData", + "x": 850.75, + "y": 861.75, + "connections": { + "0": [ + { + "index": "3", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069192937", + "component": "trigger", + "tab": "1612772287426", + "name": "sample data", + "x": 857.75, + "y": 928.75, + "connections": { + "0": [ + { + "index": "4", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069264443", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 63.75, + "y": 1279, + "connections": { + "0": [ + { + "index": "0", + "id": "1634488120710" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069334626", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "db-init", + "x": 172.88333129882812, + "y": 129, + "connections": { + "0": [ + { + "index": "0", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069548145", + "component": "virtualwirein", + "tab": "1611921777196", + "name": "db-init", + "x": 46.75, + "y": 192, + "connections": { + "0": [ + { + "index": "0", + "id": "1699965957410" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069567152", + "component": "virtualwirein", + "tab": "1611921777196", + "name": "db-init", + "x": 44.75, + "y": 465, + "connections": { + "0": [ + { + "index": "0", + "id": "1700411878636" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731070156936", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "db-init", + "x": 126.88333129882812, + "y": 1377, + "connections": { + "0": [ + { + "index": "2", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731234189516", + "component": "trigger", + "tab": "1612772287426", + "name": "monitor.txt", + "x": 882.75, + "y": 991.75, + "connections": { + "0": [ + { + "index": "5", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731234189551", + "component": "trigger", + "tab": "1612772287426", + "name": "err.txt", + "x": 904.75, + "y": 1053.75, + "connections": { + "0": [ + { + "index": "6", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1732700042559", + "component": "nodesdb_change_check", + "tab": "1612772287426", + "name": "Nodes DB change check", + "x": 266.8833312988281, + "y": 1980.2333984375, + "connections": { + "0": [ + { + "index": "0", + "id": "1732700071298" + }, + { + "index": "0", + "id": "1732700642917" + } + ], + "1": [ + { + "index": "0", + "id": "1759958914348" + }, + { + "index": "0", + "id": "1759959003114" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#888600", + "notes": "" + }, + { + "id": "1732700057052", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 76.75, + "y": 1988, + "connections": { + "0": [ + { + "index": "0", + "id": "1732700042559" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1732700071298", + "component": "debug", + "tab": "1612772287426", + "name": "nodesChange", + "x": 571.8833312988281, + "y": 2018.2333984375, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1732700642917", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "tb-push", + "x": 567.8833312988281, + "y": 1933, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1732889185927", + "component": "debug", + "tab": "1611921777196", + "name": "tempToDido", + "x": 594.8833312988281, + "y": 753, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1733574412965", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 72.75, + "y": 474, + "connections": { + "0": [ + { + "index": "1", + "id": "1731068754606" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1747561603739", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "send-to-services", + "x": 1243.8833312988281, + "y": 334.5, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1747562867845", + "component": "comment", + "tab": "1612772287426", + "name": "FLOW STARTING POINT", + "x": 1003.5666656494141, + "y": 178, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#704cff", + "notes": "" + }, + { + "id": "1749211698385", + "component": "trigger", + "tab": "1612772287426", + "name": "deviceStatus", + "x": 911.75, + "y": 1116.75, + "connections": { + "0": [ + { + "index": "7", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1757006030239", + "component": "httprequest", + "tab": "1615551125555", + "name": "192.168.252.2:8015/daily_report", + "x": 756.5666656494141, + "y": 715.4499969482422, + "connections": { + "0": [ + { + "index": "0", + "id": "1757006045804" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "stringify": "json", + "method": "POST", + "url": "http://192.168.252.2:8015/daily_report" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1757006045804", + "component": "debug", + "tab": "1615551125555", + "name": "ddd", + "x": 1091.566665649414, + "y": 711.4499969482422, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1757006060377", + "component": "debug", + "tab": "1615551125555", + "name": "reportDebug", + "x": 749.5666656494141, + "y": 799.4499969482422, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1759958914348", + "component": "httprequest", + "tab": "1612772287426", + "name": "http://192.168.252.2:8015/node_numbers", + "x": 571, + "y": 2111, + "connections": { + "0": [ + { + "index": "0", + "id": "1759958927094" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "stringify": "json", + "method": "POST", + "url": "http://192.168.252.2:8015/node_numbers" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1759958927094", + "component": "debug", + "tab": "1612772287426", + "name": "nodesChangeCloud", + "x": 951.8833312988281, + "y": 2109.2333984375, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1759959003114", + "component": "debug", + "tab": "1612772287426", + "name": "nodeChangeCloud1", + "x": 574, + "y": 2218, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1760020290879", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 84.75, + "y": 1787, + "connections": { + "0": [ + { + "index": "1", + "id": "1718016052341" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + } + ], + "version": 615 +} diff --git a/RVO7/flow/dido_controller.js b/RVO7/flow/dido_controller.js new file mode 100755 index 0000000..d16fb19 --- /dev/null +++ b/RVO7/flow/dido_controller.js @@ -0,0 +1,1486 @@ +exports.id = 'dido_controller'; +exports.title = 'DIDO_Controller'; +exports.version = '2.0.0'; +exports.group = 'Worksys'; +exports.color = '#2134B0'; +exports.input = 3; +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 + +state_of_main_switch - reportovat stav hlaveho istica : 0-> off 1-> on +rotary_switch_state - sem by sa mal reportovat stav vstupov manual a auto pola nasledovnej logiky: Manual = 1 a Auto = 0 -> Manu +Manual = 0 a Auto = 0 -> Off, Manual = 0 a Auto = 1 -> Automatic + +door_condition - pin 6, dverový kontakt -> 1 -> vyreportuje Closed, 0 -> vyreportuje Ope +twilight_sensor - hodnotu, ktoru vracia ten analogovy vstup (17) treba poslat sem ako float number. Zrejme tu potom pridame nejaky koeficient prevodu na luxy + +Na kazdu liniu +state_of_breaker - podla indexu istica sa reportuje jeho stav, teda istic na liniu 1: 0-> off, 1-> on +state_of_contactor - podla indexu stkaca sa reportuje jeho stav, teda stykac 1 na liniu 1: 0-> off, 1-> on +*/ + +const { errLogger, logger, monitor } = require('./helper/logger'); +const SerialPort = require('serialport'); +const WebSocket = require('ws'); +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 errorHandler = require('./helper/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 hasMainSwitch; + +let alarmStatus = "OFF"; + +const SEND_TO = { + debug: 0, + tb: 1, + cmd_manager: 2 +} + + +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 = {}; + let rsPortReceivedData = []; + + //to be able to get proper twilight values + let twilight_sensor_interval = 5;//minutes + let twilight_sensor = []; + const twilight_sensor_array = []; + let twilightError = false; + + monitor.info("DIDO_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-we make it global to see it from outside + FLOW.deviceStatus = { //key is device name: temperature,.... + "state_of_main_switch": "Off", //Hlavny istic (alebo druhy dverovy kontakt) + "rotary_switch_state": "Off", //Prevadzkovy + "door_condition": "closed", //Dverový kontakt + "em": "OK", //elektromer rvo + "temperature": "OK", //templomer + "battery": "OK", //Bateria + "power_supply": "OK", //Zdroj + "master_node": "OK", //MN - GLOBALS.settings.masterNodeIsResponding + "no_voltage": "OK", //GLOBALS.settings.no_voltage - vypadok napatia na faze + "state_of_breaker": {}, //"Off",//Istic + "state_of_contactor": {}, //"Off",//Stykac + "twilight_sensor": "OK" //lux sensor + }; + let deviceStatus = FLOW.deviceStatus; + + + function main() { + + GLOBALS = FLOW.GLOBALS; + SETTINGS = FLOW.GLOBALS.settings; + rvoTbName = SETTINGS.rvoTbName; + pinsData = GLOBALS.pinsData; + relaysData = GLOBALS.relaysData; + + tbHandler = new DataToTbHandler(SEND_TO.tb); + tbHandler.setSender(exports.title); + + controller_type = SETTINGS.controller_type; //"lm" or "unipi" + hasMainSwitch = SETTINGS.has_main_switch; + + if (controller_type == "") controller_type = "lm"; + + 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, "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; + } + } + + //report RVO version relaysData[0].tbname; + let values = {}; + values["edge_fw_version"] = SETTINGS.edge_fw_version; + values["maintenance_mode"] = SETTINGS.maintenance_mode; + + sendTelemetry(values, rvoTbName); + + 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); + } + + + function handleRsPort() { + + if (rsPort) { + rsPort.removeAllListeners(); + rsPort = null; + } + + //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('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) { + if (!err) { + monitor.info(exports.title + "--->Digital in_out has been set (runSyncExec was sucessfull)"); + + turnAlarm("off"); + 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('error', err => { + let message = "Dido: rsPort error: " + err.message; + logger.debug(message); + monitor.info(message); + errorHandler.sendMessageToService(message); + }) + + rsPort.on("close", () => { + let message = "Dido: rsPort closed - reconnecting ..."; + logger.debug(message); + monitor.info(message); + setTimeout(handleRsPort, 1000); + }) + + rsPort.open(); + } + + + function handleWebSocket() { + + if (ws) { + ws.removeAllListeners(); + ws = null; + } + + //to keep websocket opened, we send request every 150 seconds + let startRequests = null; + + console.log("handleWebSocket function called"); + ws = new WebSocket('ws:/0.0.0.0:1234/ws'); + + ws.onopen = function open() { + + instance.send(0, exports.title + " running"); + turnAlarm("off"); + + initialSetting(); + + setTimeout(function() { ws.send(JSON.stringify({ cmd: "all" })) }, 5000); + // we request dev info about neuron device from evok to keep websocket connection alive + // for some reason this request returns no data, but connection keeps alive + startRequests = setInterval(() => { + ws.send(JSON.stringify({ "cmd": "filter", "dev": ["neuron"] })); + }, 150000) + }; + + + // 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 = async 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; + + 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 => { + logger.debug('Dido: websocket error', err); + }) + + ws.onclose = function() { + logger.debug('Dido: websocket onclose, reconnecting...') + clearInterval(startRequests); + setTimeout(handleWebSocket, 1000); + } + } + + 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 turnAlarm(onOrOff) { + let value = 0; + if (onOrOff == "on") value = 1; + + if (value == 1 && SETTINGS.maintenance_mode) return; + + alarmStatus = "OFF"; + if (value == 1) alarmStatus = "ON"; + + if (rsPort) { + let arr = [0x55]; + arr.push(13); + arr.push(0); + arr.push(value); + + rsPort.write(Buffer.from(arr), function(err) { + logger.debug(`sirena - ${onOrOff}`); + }); + } + else if (ws) { + let cmd = { "cmd": "set", "dev": "relay", "circuit": "1_01", "value": value }; + ws.send(JSON.stringify(cmd)); + logger.debug(`sirena - ${onOrOff}`); + } + } + + + 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") { + bits.push(0); + } + else bits.push(1); + + if (deviceStatus["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); + } + + + // turn line on or off + function turnLine(onOrOff, line, pin, force, info) { + //onOrOff => "on" or "off" + let value = 0; + if (onOrOff == "on") value = 1; + + if (force == undefined) force = false; + + if (line == 0) { + if (value == 1 && alarmStatus == "ON") turnAlarm("off"); + SETTINGS.maintenance_mode = value ? true : false; + + 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); + return; + } + + if (pin === undefined) pin = getPin(line); + + if (pin === undefined) { + errLogger.error("pin is undefined!", line); + return; + } + + if (!force) { + if (relaysData[line].contactor == value) { + instance.send(SEND_TO.debug, `line is already ${onOrOff} ` + line); + logger.debug(`Dido: turnLine: line is already ${onOrOff} `, line); + return; + } + } + + // if(!rsPort.isOpen && !ws) + if (!rsPort && !ws) { + errLogger.error("Dido - port or websocket is not opened"); + return; + } + + if (rsPort) { + let arr = [0x55]; + arr.push(pin); + arr.push(0); + arr.push(value); + + rsPort.write(Buffer.from(arr), function(err) { + if (err === undefined) { + monitor.info(`Dido: turnLine ${onOrOff} zapisal do rsPort-u`, line, pin, arr, info); + switchLogic(arr); + } + else { + monitor.info(`Dido: turnLine ${onOrOff} WRITE error`, err); + } + }); + + } + else if (ws) { + //pin = "relay1_03" or "input1_01" ... we must make just "1_01" with slice method + monitor.info(`Dido: turnLine ${onOrOff} - (line, pin, force)`, line, pin, force, info); + let cmd = { "cmd": "set", "dev": "relay", "circuit": pin.slice(5), "value": value }; + ws.send(JSON.stringify(cmd)); + } + + //if rvo is 24/7, it has just one switching profile point at 13:00. we do not want to send notification as it repeats every day. + //const d = new Date(); + //if(d.getHours() != 13) sendNotification("Dido_controller: ", SETTINGS.rvoTbName, "switching_profile_point_applied_to_line", { line: line, value: onOrOff }, "", SEND_TO.tb, instance); + } + + + // 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; + + // 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) { + const status = flowdata.data.status; + if (status == "NOK-twilight_sensor") { + deviceStatus["twilight_sensor"] = "NOK"; + } + else if (status == "NOK-em340" || status == "NOK-em111") { + deviceStatus["em"] = "NOK"; + } + else if (status == "NOK-thermometer") { + deviceStatus["temperature"] = "NOK"; + } + } + else if ("values" in flowdata.data) { + 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" + } + else if (values.hasOwnProperty("temperature")) { + deviceStatus["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"; + } + + sendTelemetry(values, rvoTbName); + } + + sendRvoStatus(); + }) + + + + + // we expect array as flowdata.data + instance.on("1", flowdata => { + + //console.log(flowdata.data); + + if (!flowdata.data instanceof Object) return; + + let obj = flowdata.data; + let line = obj.line; + 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"); + }) + + + function calculateStateCode() { + + let bits = []; + + //Hlavny istic - state_of_main_switch => v rvo senica je to druhy door pre silovu cast (EM) + if (deviceStatus["state_of_main_switch"] === "closed" || deviceStatus["state_of_main_switch"] === "Off") { + bits.push(0); + } + else { + bits.push(1); + } + + //Prevadzkovy mod - Manual, Off, Automatic, maintenance_mode = true/false // DAVA 2 BITY + if (!SETTINGS.maintenance_mode) { + if (deviceStatus["rotary_switch_state"] === "Manual") { + bits.push(0); + bits.push(1); + } + + if (deviceStatus["rotary_switch_state"] === "Automatic") { + bits.push(0); + bits.push(0); + } + + if (deviceStatus["rotary_switch_state"] === "Off") { + bits.push(1); + bits.push(0); + } + } + else { + bits.push(1); + bits.push(1); + } + + //Dverovy kontakt + if (deviceStatus["door_condition"] === "closed") { + bits.push(0); + } + else { + bits.push(1); + } + + //EM + if (deviceStatus["em"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //Teplomer + if (deviceStatus["temperature"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //Batéria + if (deviceStatus["battery"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //Zdroj + if (deviceStatus["power_supply"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //MN + if (deviceStatus["master_node"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //výpadok napätia na fáze + if (deviceStatus["no_voltage"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + if (deviceStatus["twilight_sensor"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + // doplnime do 16 bitov (2 byty) + for (let i = bits.length; i < 16; i++) { + bits.push(0); + } + + // console.log("calculateStateCode - deviceStatus", deviceStatus); + // 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; + } + + + async function sendRvoStatus() { + + if (SETTINGS === undefined) return; + SETTINGS.masterNodeIsResponding ? deviceStatus["master_node"] = "OK" : deviceStatus["master_node"] = "NOK"; + + 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 pinsForRvoStatus(controllerType, hasMainSwitch) { + + let pins = []; + + if (controllerType === "lm") { + pins = [1, 4, 6]; + if (hasMainSwitch === 1) { + pins = [4, 6]; + } + } else if (controllerType === "unipi") { + pins = ["input1_01", "input1_04", "input1_05"]; + if (hasMainSwitch === 1) { + pins = ["input1_01", "input1_04"]; + } + } + + return pins; + } + + + function checkRvoStatus() { + + // 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 + //set RVO state + let status = "OK"; + + for (const [key, value] of Object.entries(deviceStatus)) { + if (["em", "twilight_sensor", "temperature", "master_node"].includes(key) && value === "NOK") status = "NOK"; + } + + if (status === "OK") { + + let pinIndexes = pinsForRvoStatus(controller_type, hasMainSwitch); + + for (const pinIndex of pinIndexes) { + if (previousValues[pinIndex] === 0) { + if ((pinIndex === 6 || pinIndex === 'input1_01' || pinIndex === 'input1_05') && SETTINGS.maintenance_mode) continue; + status = "NOK"; + break; + } + } + } + + // battery status. If value is 1 - battery is NOK + if (previousValues[5] === 1) status = "NOK"; + if (SETTINGS.no_voltage.size > 0) status = "NOK"; + + // console.log("rvo status",status) + return status; + } + + + // we pass array to function in case of rsPort ==> switchLogic([55,3,0,1]) ==> [[55,3,0,1]] + // we pass two values in case of websocket ==> switchLogic("relay1_03",1) ==> ["relay1_03",1] + const switchLogic = (...args) => { + + let values = {}; + let pinIndex, newPinValue, twilight; + + //data from rsPort + if (args.length == 1) { + pinIndex = args[0][1] + 1; + if (pinIndex === 17) pinIndex--; + newPinValue = args[0][3]; + twilight = args[0][2]; + } + //data from websocket + else { + pinIndex = args[0]; + newPinValue = args[1]; + } + + 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; + + //default value + let value = "On"; + if (newPinValue === 0) value = "Off"; + + //Hlavny istic + if (type === "state_of_main_switch" && hasMainSwitch) { + if (newPinValue === 0 && newPinValue !== previousValues[pinIndex]) { + sendNotification("switchLogic", rvoTbName, "main_switch_has_been_turned_off", {}, "", SEND_TO.tb, instance, "state_of_main_switch"); + 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"); + deviceStatus["state_of_main_switch"] = "On"; + } + } + + //Prevadzkovy mod + 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"; + + deviceStatus["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, "power_supply_has_disconnected_input", {}, "", SEND_TO.tb, instance, "power_supply"); + + deviceStatus["power_supply"] = "NOK"; + } + else if (newPinValue === 1 && newPinValue !== previousValues[pinIndex]) { + sendNotification("switchLogic", rvoTbName, "power_supply_works_correctly", {}, "", SEND_TO.tb, instance, "power_supply"); + + deviceStatus["power_supply"] = "OK"; + } + } + + //Bateria - 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"); + + deviceStatus["battery"] = "NOK"; + } + else if (newPinValue === 0 && newPinValue !== previousValues[pinIndex]) { + sendNotification("switchLogic", rvoTbName, "battery_level_is_ok", {}, "", SEND_TO.tb, instance, "battery_level"); + + deviceStatus["battery"] = "OK"; + } + } + + //Dverovy kontakt - pin 6 + //! Ak je rvo s dvoma dverovymi kontaktami, ked pride z evoku signal z input1_05, co bol predytm "state_of_main switch" handlujeme ho teraz ako 'door_condition' + else if (type == "door_condition" || type === "state_of_main_switch") { + newPinValue === 0 ? value = "open" : value = "closed"; + + let door = "door_main"; + if (type === "state_of_main_switch") door = "door_em"; + + if (value === "open") { + if (SETTINGS.maintenance_mode) { + sendNotification("switchLogic", rvoTbName, door + "_open", {}, "", SEND_TO.tb, instance, door); + } else { + sendNotification("switchLogic", rvoTbName, door + "_open_without_permission", {}, "", SEND_TO.tb, instance, door); + + // 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 (value === "closed") { + if (alarmStatus == "ON") turnAlarm("off"); + sendNotification("switchLogic", rvoTbName, door + "_close", {}, "", SEND_TO.tb, instance, door); + } + + deviceStatus[type] = value; + } + + //lux sensor + else if (type == "twilight_sensor") { + //! TODO - to show nok status, if lux value is not changing more then 10 times. + //Daylight is far more than 1000. So most of the day, when it is sunshine comes just value 1000. But lux sensor is not NOK. + //This is not the case in LM. If value from LM is the same 10x, there is 99% possibility, that sensor is NOK. + value = newPinValue; + + if (controller_type === 'lm') { + value = parseFloat(newPinValue + (256 * twilight)); + + 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 && !twilightError) { + twilightError = true; + let value = twilight_sensor_array.shift(); + + newPinValue = 0; + } + else if (set.size !== 1 && twilightError) { + //sendNotification("switchLogic", rvoTbName, 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) { + 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); + } + } + + 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); + } + + deviceStatus["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 (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 }); + + //mame iba 3 istice. vyreportujeme a ohandlujeme liniu na tom istom istici ako paralelna linia (napr linia 1, paralelna s nou je linia 4, key je string "4") + // ak je 7 linii, na 1 istici je linia 1,4,7 + + if (line == 1) { + + const lineOnSameBraker = [4, 7]; + + for (var i = 0; i < lineOnSameBraker.length; i++) { + if (!relaysData.hasOwnProperty(lineOnSameBraker[i])) continue; + + 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; + reportLineStatus(lineOnSameBraker[i]); + + values[type] = value; + const tbname = relaysData[lineOnSameBraker[i]].tbname; + sendTelemetry(values, tbname); + + delete values[type]; + } + + } + else { + const lineOnSameBraker = line + 3 + ""; + + if (relaysData.hasOwnProperty(lineOnSameBraker)) { + 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; + reportLineStatus(line + 3); + + values[type] = value; + const tbname = relaysData[lineOnSameBraker].tbname; + sendTelemetry(values, tbname); + + delete values[type]; + } + } + + } + + if (value == "Off") values["status"] = "NOK"; + deviceStatus["state_of_breaker"][line] = value; + + reportLineStatus(line); + } + else return; + + values[type] = value; + + if (type == "rotary_switch_state") { + if (SETTINGS.maintenance_mode) value = "maintenance"; + value = value.toLowerCase(); + values["power_mode"] = value; + } + + if (newPinValue != previousValues[pinIndex]) previousValues[pinIndex] = newPinValue; + if (Object.keys(values).length > 0 && tbname) sendTelemetry(values, tbname); + } + + + function sendTelemetry(values, tbname, date = Date.now()) { + let dataToTb = { + [tbname]: [ + { + "ts": date, + "values": values + } + ] + }; + + tbHandler.sendToTb(dataToTb, instance); + } + + + function isObject(item) { + return (typeof item === "object" && !Array.isArray(item) && item !== null); + } + +} //end of 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 +// *|input1_01|state_of_main_switch|0|........... +// *|input1_02|rotary_switch_state|0|........... +// *|input1_03|rotary_switch_state|0|........... +// *|intut1_04|power_supply|0|........... +// *|input1_05|door_condition|0|........... +// *|input1_06|state_of_breaker|1|........... +// *|input1_07|state_of_breaker|2|........... +// *|input1_08|state_of_breaker|3|........... +// *|relay1_02|state_of_contactor|1|........... +// *|relay1_03|state_of_contactor|2|........... +// *|relay1_04|state_of_contactor|3|........... +// *|287D8776E0013CE9|temperature|0|........... + + +//! pins_data --> from UNIPI +// { +// 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 } +// } + +//! relays_data +// { +// '0': { +// line: 0, +// tbname: 'KjbN4q7JPZmexgdnz2yKQ98YAWwO0Q3BMX6ERLoV', +// contactor: 1, +// profile: '' +// }, +// '1': { +// line: 1, +// tbname: 'RMgnK93rkoAazbqdQ4yBG95Z1YXGx6pmwBeVEP2O', +// contactor: 0, +// profile: '{"intervals":[{"value":0,"end_time":"20:00","start_time":"13:00"},{"value":1,"end_time":"10:00","start_time":"20:00"},{"value":0,"end_time":"10:20","start_time":"10:00"},{"value":1,"end_time":"10:40","start_time":"10:20"},{"value":0,"end_time":"11:00","start_time":"10:40"},{"value":1,"end_time":"11:30","start_time":"11:00"},{"value":0,"end_time":"11:50","start_time":"11:30"},{"value":1,"end_time":"13:00","start_time":"11:50"}],"astro_clock":false,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' +// }, +// '2': { +// line: 2, +// tbname: 'dlE1VQjYrNx9gZRmb38gG08oLBO4qaAk2M6JPnG7', +// contactor: 0, +// profile: '{"intervals":[{"value":0,"end_time":"20:00","start_time":"13:00"},{"value":1,"end_time":"10:00","start_time":"20:00"},{"value":0,"end_time":"10:20","start_time":"10:00"},{"value":1,"end_time":"10:40","start_time":"10:20"},{"value":0,"end_time":"11:00","start_time":"10:40"},{"value":1,"end_time":"11:30","start_time":"11:00"},{"value":0,"end_time":"11:50","start_time":"11:30"},{"value":1,"end_time":"13:00","start_time":"11:50"}],"astro_clock":false,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' +// }, +// '3': { +// line: 3, +// tbname: 'vnmG4kJxaXWNBgMQq0D7Aj5e9oZzOAlr6LdR3w2V', +// contactor: 0, +// profile: '{"intervals":[{"value":0,"end_time":"20:30","start_time":"13:00"},{"value":1,"end_time":"00:10","start_time":"20:30"},{"value":0,"end_time":"13:00","start_time":"05:40"},{"value":1,"end_time":"05:40","start_time":"00:10"}],"astro_clock":true,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' +// } +// } + + + + + +// { +// "jbN4q7JPZmexgdnz2yKbWGDYAWwO0Q3BMX6ERLoV": [ +// { +// "ts": 1700409326353, +// "values": { +// "_event": { +// "type": "notice", +// "status": "new", +// "source": { +// "func": "rsPort.open()", +// "component": "1700343402190", +// "component_name": "DIDO_Controller", +// "edge": "jbN4q7JPZmexgdnz2yKbWGDYAWwO0Q3BMX6ERLoV" +// }, +// "message": "al_shariff_10.0.0.38: FLOW has been started ", +// "message_data": "" +// } +// } +// } +// ] +// } diff --git a/RVO7/flow/helper/DataToTbHandler.js b/RVO7/flow/helper/DataToTbHandler.js new file mode 100755 index 0000000..716ef7b --- /dev/null +++ b/RVO7/flow/helper/DataToTbHandler.js @@ -0,0 +1,187 @@ +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; + this.itIsNodeReadout = false; + this.sender = ""; + + // if attribute change difference is less than limit value, we do not send to tb. + this.attributeChangeLimit = { + temperature: 0.5, + Phase_1_voltage: 2, + Phase_2_voltage: 2, + Phase_3_voltage: 2, + Phase_1_current: 0.1, + Phase_2_current: 0.1, + Phase_3_current: 0.1, + Phase_1_power: 2, + Phase_2_power: 2, + Phase_3_power: 2, + total_power: 2, + total_energy: 1, + Phase_1_pow_factor: 0.1, + Phase_2_pow_factor: 0.1, + Phase_3_pow_factor: 0.1, + power_factor: 0.1, + lifetime: 2, + voltage: 2, + power: 2, + frequency: 3, + energy: 0.1, + current: 2, + inclination_x: 10, + inclination_y: 10, + inclination_z: 10 + }; + + } + + dump() { + console.log("----------------------------"); + console.log("previousValues", this.previousValues); + console.log("----------------------------"); + } + + setSender(sender) { + this.sender = sender; + } + + isEmptyObject(obj) { + for (var _ in obj) { + return false; + } + return true; + } + + + sendToTb(data, instance) { + + //not to modify data object, we do deep copy: + let dataCopy = JSON.parse(JSON.stringify(data)); + + let keys = Object.keys(dataCopy); + + if (keys.length == 0) { + if (this.debug) console.log("sendToTb received empty object", dataCopy); + return; + } + + let tbname = keys[0]; + let ts; + + let arrayOfValues = dataCopy[tbname]; + let arrayOfValuesToSend = []; + + for (let i = 0; i < arrayOfValues.length; i++) { + + ts = arrayOfValues[i].ts; + let values = this.prepareValuesForTb(tbname, ts, arrayOfValues[i].values); + + if (!this.isEmptyObject(values)) { + arrayOfValuesToSend.push({ ts: ts, values: values }); + } + + } + + if (arrayOfValuesToSend.length == 0) { + //if(this.debug) console.log("data not sent - empty array"); + return; + } + + this.messageCounter++; + + let dataToTbModified = { + [tbname]: arrayOfValuesToSend + } + + //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); + instance.send(this.index, dataToTbModified); + } + + + getDiffTimestamp(key) { + //TODO set different value for given key!!! + //if(key == "status") this.timeToHoldTbValue = 2*60*60;//2h + return this.timeToHoldTbValue * 1000; + } + + + prepareValuesForTb(tbname, timestamp, values) { + + let keys = Object.keys(values); + + if (keys.includes("lifetime")) this.itIsNodeReadout = true; + + if (!this.previousValues.hasOwnProperty(tbname)) { + this.previousValues[tbname] = {}; + } + + //if(this.debug) console.log("prepareValuesForTb", tbname, timestamp, values); + + for (let i = 0; i < keys.length; i++) { + + let key = keys[i]; + let value = values[key]; + + if (!this.previousValues[tbname].hasOwnProperty(key)) { + this.previousValues[tbname][key] = { ts: timestamp, value: value }; + continue; + } + + // attributeData ==> {voltage: {ts:333333, value:5}} + let attributeData = this.previousValues[tbname][key]; + let attributeToChange = false; + if (key in this.attributeChangeLimit) attributeToChange = true; + let limit = this.attributeChangeLimit[key]; + let timestampDiffToRemoveKey; + + //this will ensure "node statecode" will be sent just once an hour + if (this.itIsNodeReadout && key === "statecode") { + attributeData.value = value; + this.itIsNodeReadout = false; + timestampDiffToRemoveKey = 1 * 60 * 60 * 1000; // 1 hour + } + + if (key === "twilight_sensor" && value > 100) { + attributeData.value = value; + } + + //if edge, master or node version do not change, send just once a day: + if (["edge_fw_version", "master_node_version", "fw_version"].includes(key)) { + timestampDiffToRemoveKey = 24 * 60 * 60 * 1000; + } + + if (attributeData.value === value || attributeToChange && Math.abs(attributeData.value - value) < limit) { + + let diff = timestamp - attributeData.ts; + if (!timestampDiffToRemoveKey) timestampDiffToRemoveKey = this.getDiffTimestamp(key); + + if (diff > timestampDiffToRemoveKey) { + attributeData.ts = Date.now(); + //if(this.debug) console.log(this.sender + ": update ts for key", key, "diff is", diff, "messageCounter", this.messageCounter); + } + else { + delete values[key]; + //if(this.debug) console.log(this.sender + ": delete key", key, "diff is", diff, "messageCounter", this.messageCounter, timestampDiffToRemoveKey); + } + } + else { + attributeData.value = value; + attributeData.ts = timestamp; + } + + } + + return values; + } +} + +module.exports = DataToTbHandler; + diff --git a/RVO7/flow/helper/ErrorToServiceHandler.js b/RVO7/flow/helper/ErrorToServiceHandler.js new file mode 100755 index 0000000..2b27c32 --- /dev/null +++ b/RVO7/flow/helper/ErrorToServiceHandler.js @@ -0,0 +1,91 @@ +const { MD5 } = require('./md5.js'); +const { networkInterfaces } = require('os'); + +class ErrorToServiceHandler { + constructor() { + this.previousValues = {}; + + this.project_id = undefined; + + const nets = networkInterfaces(); + this.ipAddresses = {}; + + for (const name of Object.keys(nets)) { + for (const net of nets[name]) { + // Skip over non-IPv4 and internal (i.e. 127.0.0.1) addresses + if (net.family === 'IPv4' && !net.internal) { + if (!this.ipAddresses[name]) { + this.ipAddresses[name] = []; + } + this.ipAddresses[name].push(net.address); + } + } + } + } + + setProjectId(project_id) { + this.project_id = project_id; + } + + processMessage(message, seconds) { + if (Array.isArray(message)) message = message.join(', '); + + let key = MD5(message); + let ts = Date.now(); + + //keep in memory - default value is 1h + if (seconds === undefined) seconds = 60 * 60; + + if (!this.previousValues.hasOwnProperty(key)) { + this.previousValues[key] = { ts: ts, duration: seconds }; + } + + let diff = (ts - this.previousValues[key].ts); + if (diff < this.previousValues[key].duration * 1000) return false; + + this.previousValues[key].ts = ts; + + return message; + } + + sendMessageToService(message, seconds, message_type) { + + // if error occures too early FLOW.GLOBALS.settings.project_id is still undefined + if (this.project_id === undefined) { + console.log("ErrorToServiceHandler.js: no project_id"); + return; + } + + let f = this.processMessage(message, seconds); + if (f === false) return; + + if (message_type === undefined) message_type = "error_message"; + + let toService = { + id: this.project_id, + ipAddresses: this.ipAddresses + }; + + //js_error || error_message + toService[message_type] = message; + + console.log("ErrorToServiceHandler------------------------>send to service", toService); + + RESTBuilder.make(function(builder) { + builder.method('POST'); + builder.post(toService); + builder.url('http://192.168.252.2:8004/sentmessage'); + + builder.callback(function(err, response, output) { + console.log("process.on error send", err, response, output, toService); + }); + }); + + } +} + +const errorHandler = new ErrorToServiceHandler(); + + +module.exports = errorHandler; +//module.exports = ErrorToServiceHandler; diff --git a/RVO7/flow/helper/db_helper.js b/RVO7/flow/helper/db_helper.js new file mode 100755 index 0000000..40e796c --- /dev/null +++ b/RVO7/flow/helper/db_helper.js @@ -0,0 +1,44 @@ +function promisifyBuilder(builder) +{ + return new Promise((resolve, reject) => { + + try{ + + builder.callback(function(err, response) { + + if(err != null) reject(err); + resolve(response); + }); + + } catch (error) { + reject(error); + } + }) +} + +function makeMapFromDbResult(response, ...keys) +{ + let s = "-"; + let data = {}; + + for(let i = 0; i < response.length; i++) + { + let record = response[i]; + + let k = []; + for(let j = 0; j < keys.length; j++) + { + k.push( record[keys[j]] ); + } + + let key = k.join(s); + data[ key ] = record; + } + + return data; +} + +module.exports = { + promisifyBuilder, + makeMapFromDbResult + } \ No newline at end of file diff --git a/RVO7/flow/helper/logger.js b/RVO7/flow/helper/logger.js new file mode 100755 index 0000000..2585639 --- /dev/null +++ b/RVO7/flow/helper/logger.js @@ -0,0 +1,30 @@ +//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/RVO7/flow/helper/md5.js b/RVO7/flow/helper/md5.js new file mode 100755 index 0000000..d3b0480 --- /dev/null +++ b/RVO7/flow/helper/md5.js @@ -0,0 +1,5 @@ +function MD5(d){var r = M(V(Y(X(d),8*d.length)));return r.toLowerCase()};function M(d){for(var _,m="0123456789ABCDEF",f="",r=0;r>>4&15)+m.charAt(15&_);return f}function X(d){for(var _=Array(d.length>>2),m=0;m<_.length;m++)_[m]=0;for(m=0;m<8*d.length;m+=8)_[m>>5]|=(255&d.charCodeAt(m/8))<>5]>>>m%32&255);return _}function Y(d,_){d[_>>5]|=128<<_%32,d[14+(_+64>>>9<<4)]=_;for(var m=1732584193,f=-271733879,r=-1732584194,i=271733878,n=0;n>16)+(_>>16)+(m>>16)<<16|65535&m}function bit_rol(d,_){return d<<_|d>>>32-_} + +module.exports = { + MD5 +} \ No newline at end of file diff --git a/RVO7/flow/helper/notification_reporter.js b/RVO7/flow/helper/notification_reporter.js new file mode 100755 index 0000000..839c12c --- /dev/null +++ b/RVO7/flow/helper/notification_reporter.js @@ -0,0 +1,121 @@ +//key is device, value = message {} +let sentValues = {}; +let notificationsData = null; +let rvoName; + +//sendNotification("CMD Manager: process cmd", SETTINGS.rvoTbName, "dimming_profile_was_successfully_received_by_node", { node: node }, "", SEND_TO.tb, instance); + +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 +}; + +function getKey(map, val) { + return Object.keys(map).findItem(key => map[key] === val); +} + +//https://stackoverflow.com/questions/41117799/string-interpolation-on-variable +var template = (tpl, args) => tpl.replace(/\${(\w+)}/g, (_, v) => args[v]); + + +function initNotification() { + notificationsData = FLOW.GLOBALS.notificationsData; + rvoName = FLOW.GLOBALS.settings.rvo_name; +} + + +function sendNotification(func, device, key, params, extra, tb_output, instance, saveKey) { + + let storeToSendValues = true; + if (saveKey == undefined) storeToSendValues = false; + + let weight = ""; + let message = {}; + + let notification = notificationsData[key]; + + if (notification) { + weight = notification.weight.toLowerCase(); + + Object.keys(notification).forEach(item => { + if (["en", "sk", "de", "cz", "it", "es"].includes(item)) { + message[item] = rvoName + ": " + template(notification[item], params); + } + }) + } + else { + //console.error("sendNotification: Notifications: undefined key", key, func, notificationsData); + console.error("sendNotification: Notifications: undefined key", key, func); + return false; + } + + //detect invalid err weight + if (getKey(ERRWEIGHT, weight) == undefined) { + console.error("sendNotification: Notifications: undefined weight", weight, key, func); + return false; + } + + if (sentValues.hasOwnProperty(saveKey)) { + if (JSON.stringify(sentValues[saveKey]) == JSON.stringify(message)) { + return false; + } + } + + if (sentValues[saveKey] == undefined) { + if (storeToSendValues) { + //do not send - flow is was started + sentValues[saveKey] = message; + return false; + } + } + + if (storeToSendValues) sentValues[saveKey] = message; + + let content = { + "type": weight, + "status": "new", + "source": { + "func": func, + "component": instance.id, + "component_name": instance.name, + "edge": device + }, + "message": message, + "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 + + return true; + +} + +module.exports = { + sendNotification, + ERRWEIGHT, + initNotification +} + diff --git a/RVO7/flow/helper/register.js b/RVO7/flow/helper/register.js new file mode 100755 index 0000000..fc1d008 --- /dev/null +++ b/RVO7/flow/helper/register.js @@ -0,0 +1,144 @@ +/* +0 - cislo registra / prikaz +1 - recepient - 0 = master, 1 = slave (slave je automaticky group a broadcast) +2 - r/rw - read/write +3- register name - nazov registra / prikazu (len pre info - zobrazenie v aplikacii) + +4,5,6,7, - jednotlive byte-y - nazov byte-u +4-7 - RES. a prazdny string "" sa nezobrazia!!! +*/ + +//124 zaznamov +const registers = [ + ["0","1","R","Status","","",""], + ["1","1","RW","Dimming","R-Channel ","G-Channel","B-Channel ","W - Channel"], + ["2","1","R","Device types","","",".",""], + ["3","1","RW","Group addresses 1-4","Groups Add. 4","Groups Add. 3","Groups Add. 2","Groups Add. 1"], + ["4","1","RW","Group addresses 5-8","Groups Add. 8","Groups Add. 7","Groups Add. 6","Groups Add. 5"], + ["5","1","RW","Serial number (MAC)","","","",""], + ["6","1","RW","Time of dusk","HH","MM","SS","EXTRA"], + ["7","1","RW","Time of dawn","HH","MM","SS","EXTRA"], + ["8","1","RW","Time Schedule settings","TBD","TBD","Movement sensor","Time Schedule"], + ["9","1","RW","TS1 Time point 1","HH","MM","SS","Ext. Device"], + ["10","1","RW","TS1 Time point 1 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["11","1","RW","TS1 Time point 2","HH","MM","SS","Ext. Device"], + ["12","1","RW","TS1 Time point 2 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["13","1","RW","TS1 Time point 3","HH","MM","SS","Ext. Device"], + ["14","1","RW","TS1 Time point 3 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["15","1","RW","TS1 Time point 4","HH","MM","SS","Ext. Device"], + ["16","1","RW","TS1 Time point 4 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["17","1","RW","TS1 Time point 5","HH","MM","SS","Ext. Device"], + ["18","1","RW","TS1 Time point 5 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["19","1","RW","TS1 Time point 6","HH","MM","SS","Ext. Device"], + ["20","1","RW","TS1 Time point 6 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["21","1","RW","TS1 Time point 7","HH","MM","SS","Ext. Device"], + ["22","1","RW","TS1 Time point 7 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["23","1","RW","TS1 Time point 8","HH","MM","SS","Ext. Device"], + ["24","1","RW","TS1 Time point 8 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["25","1","RW","TS1 Time point 9","HH","MM","SS","Ext. Device"], + ["26","1","RW","TS1 Time point 9 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["27","1","RW","TS1 Time point 10","HH","MM","SS","Ext. Device"], + ["28","1","RW","TS1 Time point 10 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["29","1","RW","TS1 Time point 11","HH","MM","SS","Ext. Device"], + ["30","1","RW","TS1 Time point 11 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["31","1","RW","TS1 Time point 12","HH","MM","SS","Ext. Device"], + ["32","1","RW","TS1 Time point 12 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["33","1","RW","TS1 Time point 13","HH","MM","SS","Ext. Device"], + ["34","1","RW","TS1 Time point 13 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["35","1","RW","TS1 Time point 14","HH","MM","SS","Ext. Device"], + ["36","1","RW","TS1 Time point 14 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["37","1","RW","TS1 Time point 15","HH","MM","SS","Ext. Device"], + ["38","1","RW","TS1 Time point 15 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["39","1","RW","TS1 Time point 16","HH","MM","SS","Ext. Device"], + ["40","1","RW","TS1 Time point 16 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["41","1","RW","TS2 Time point 1","HH","MM","SS","Ext. Device"], + ["42","1","RW","TS2 Time point 1 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["43","1","RW","TS2 Time point 2","HH","MM","SS","Ext. Device"], + ["44","1","RW","TS2 Time point 2 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["45","1","RW","TS2 Time point 3","HH","MM","SS","Ext. Device"], + ["46","1","RW","TS2 Time point 3 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["47","1","RW","TS2 Time point 4","HH","MM","SS","Ext. Device"], + ["48","1","RW","TS2 Time point 4 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["49","1","RW","TS2 Time point 5","HH","MM","SS","Ext. Device"], + ["50","1","RW","TS2 Time point 5 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["51","1","RW","TS2 Time point 6","HH","MM","SS","Ext. Device"], + ["52","1","RW","TS2 Time point 6 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["53","1","RW","TS2 Time point 7","HH","MM","SS","Ext. Device"], + ["54","1","RW","TS2 Time point 7 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["55","1","RW","TS2 Time point 8","HH","MM","SS","Ext. Device"], + ["56","1","RW","TS2 Time point 8 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["57","1","RW","TS2 Time point 9","HH","MM","SS","Ext. Device"], + ["58","1","RW","TS2 Time point 9 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["59","1","RW","TS2 Time point 10","HH","MM","SS","Ext. Device"], + ["60","1","RW","TS2 Time point 10 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["61","1","RW","TS2 Time point 11","HH","MM","SS","Ext. Device"], + ["62","1","RW","TS2 Time point 11 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["63","1","RW","TS2 Time point 12","HH","MM","SS","Ext. Device"], + ["64","1","RW","TS2 Time point 12 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["65","1","RW","TS2 Time point 13","HH","MM","SS","Ext. Device"], + ["66","1","RW","TS2 Time point 13 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["67","1","RW","TS2 Time point 14","HH","MM","SS","Ext. Device"], + ["68","1","RW","TS2 Time point 14 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["69","1","RW","TS2 Time point 15","HH","MM","SS","Ext. Device"], + ["70","1","RW","TS2 Time point 15 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["71","1","RW","TS2 Time point 16","HH","MM","SS","Ext. Device"], + ["72","1","RW","TS2 Time point 16 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["73","1","RW","Power meter status","TBD","","",""], + ["74","1","R","Input Voltage","","","",""], + ["75","1","R","Input Current","","","",""], + ["76","1","R","Input Power","","","",""], + ["77","1","R","Cos phi","","","",""], + ["78","1","R","Frequency","","","",""], + ["79","1","RW","Energy","","","",""], + ["80","1","RW","Lifetime","","","",""], + ["81","1","RW","Power on cycles (input)","","","",""], + ["82","1","RW","Power on cycles (relay)","","","",""], + ["83","1","R","Time since last power on","","","",""], + ["84","1","R","Accelerometer data","","","",""], + ["85","1","RW","GPS latitude","pos/neg","deg","min ","sec"], + ["86","1","RW","GPS longitude","pos/neg","deg","min ","sec"], + ["87","1","RW","Actual time","HH","MM","SS","RES."], + ["88","1","RW","Actual date","Day of week","Day","Month","Year"], + ["89","1","R","Production data 1","","","",""], + ["90","1","R","Production data 2","","","",""], + ["91","1","RW","Network ID","NID3","NID2","NID1","NID0"], + ["95","1","RW","Actual Lux level from cabinet","RES.","RES.","HB","LB"], + ["96","1","RW","Threshold lux level","Dusk HB","Dusk LB","Dawn HB","Dawn LB"], + ["97","1","RW","Adjust period","Dusk HB","Dusk LB","Dawn HB","Dawn LB"], + ["98","1","RW","Offset","RES.","RES.","Dusk","Dawn"], + ["99","1","RW","CCT min/max range","max-H","max-L","min-H","min-L"], + ["100","1","RW","DALI interface","Cmd ID","Add","Cmd","Resp"], + ["101","1","RW","Module FW ver","v1","v2","v3","v4"], + ["102","1","RW","Module MAC-H","unused","unused","M1","M2"], + ["103","1","RW","Module MAC-L","M3","M4","M5","M6"], + ["122","1","R","FW update status/control register","Byte3","Byte2","Byte1","Byte0"], + ["123","1","R","FW update - data index","Byte3","Byte2","Byte1","Byte0"], + ["124","1","R","FW update - data","Byte3","Byte2","Byte1","Byte0"], + ["0","0","R","Status","","","",""], + ["1","0","RW","Control register","RES.","RES.","RES.","init mode enable"], + ["2","0","R","Device types","","","",""], + ["3","0","R","Serial number (MAC)","","","",""], + ["4","0","R","Production data 1","","","",""], + ["5","0","R","Production data 2","","","",""], + ["6","0","RW","Network ID","NID3","NID2","NID1","NID0"], + ["7","0","RW","RS232 settings","param.","param.","Baudrate H","Baudrate L"], + ["8","0","R","Accelerometer data","","","",""], + ["9","0","RW","Module FW ver","v1","v2","v3","v4"], + ["10","0","RW","Module MAC-H","unused","unused","M1","M2"], + ["11","0","RW","Module MAC-L","M3","M4","M5","M6"], + ["32","0","RW","FW update status/control register","Byte3","Byte2","Byte1","Byte0"], + ["33","0","RW","FW update - data index","Byte3","Byte2","Byte1","Byte0"], + ["34","0","RW","FW update - data","Byte3","Byte2","Byte1","Byte0"], + ["125","0","RW","Debug Register","Byte3","Byte2","Byte1","Byte0"], + ["126","0","RW","Network Control Register","Byte3","Byte2","Byte1","Byte0"], + ["127","0","R","Network Status Register","Byte3","Byte2","Byte1","Byte0"], + ["128","0","RW","Node XX Serial Number Register","SER3","SER2","SER1","SER0"], + ["256","0","R","Node XX Network Status Register","","","",""] +]; + +let register = {}; + +module.exports = { + registers, + register +} \ No newline at end of file diff --git a/RVO7/flow/helper/serialport_helper.js b/RVO7/flow/helper/serialport_helper.js new file mode 100755 index 0000000..7f5920d --- /dev/null +++ b/RVO7/flow/helper/serialport_helper.js @@ -0,0 +1,99 @@ +const { exec } = require('child_process'); + +function openPort(port) { + return new Promise((resolve, reject) => { + + var callbackError = function(err) { + port.removeListener('error', callbackError); + port.removeListener('open', callbackError); + + reject(err.message); + }; + + var callbackOpen = function(data) { + port.removeListener('error', callbackError); + port.removeListener('open', callbackOpen); + + resolve("port open: ok"); + }; + + port.on('error', callbackError); + port.on('open', callbackOpen); + + port.open(); + + }) +} + +function runSyncExec(command) { + return new Promise((resolve, reject) => { + + exec(command, (error, stdout, stderr) => { + if (error == null) resolve(stdout); + reject(error); + }); + + }) +} + +async function writeData(port, data, readbytes, timeout) { + return new Promise((resolve, reject) => { + + // 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) { + + port.write(Buffer.from(data), function(err) { + if (err) { + reject(err.message); + } + }); + + 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 +} diff --git a/RVO7/flow/helper/suncalc.js b/RVO7/flow/helper/suncalc.js new file mode 100755 index 0000000..c9ca56d --- /dev/null +++ b/RVO7/flow/helper/suncalc.js @@ -0,0 +1,317 @@ +/* + (c) 2011-2015, Vladimir Agafonkin + SunCalc is a JavaScript library for calculating sun/moon position and light phases. + https://github.com/mourner/suncalc +*/ + +(function () { 'use strict'; + +// shortcuts for easier to read formulas + +var PI = Math.PI, + sin = Math.sin, + cos = Math.cos, + tan = Math.tan, + asin = Math.asin, + atan = Math.atan2, + acos = Math.acos, + rad = PI / 180; + +// sun calculations are based on http://aa.quae.nl/en/reken/zonpositie.html formulas + + +// date/time constants and conversions + +var dayMs = 1000 * 60 * 60 * 24, + J1970 = 2440588, + J2000 = 2451545; + +function toJulian(date) { return date.valueOf() / dayMs - 0.5 + J1970; } +function fromJulian(j) { return new Date((j + 0.5 - J1970) * dayMs); } +function toDays(date) { return toJulian(date) - J2000; } + + +// general calculations for position + +var e = rad * 23.4397; // obliquity of the Earth + +function rightAscension(l, b) { return atan(sin(l) * cos(e) - tan(b) * sin(e), cos(l)); } +function declination(l, b) { return asin(sin(b) * cos(e) + cos(b) * sin(e) * sin(l)); } + +function azimuth(H, phi, dec) { return atan(sin(H), cos(H) * sin(phi) - tan(dec) * cos(phi)); } +function altitude(H, phi, dec) { return asin(sin(phi) * sin(dec) + cos(phi) * cos(dec) * cos(H)); } + +function siderealTime(d, lw) { return rad * (280.16 + 360.9856235 * d) - lw; } + +function astroRefraction(h) { + if (h < 0) // the following formula works for positive altitudes only. + h = 0; // if h = -0.08901179 a div/0 would occur. + + // formula 16.4 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + // 1.02 / tan(h + 10.26 / (h + 5.10)) h in degrees, result in arc minutes -> converted to rad: + return 0.0002967 / Math.tan(h + 0.00312536 / (h + 0.08901179)); +} + +// general sun calculations + +function solarMeanAnomaly(d) { return rad * (357.5291 + 0.98560028 * d); } + +function eclipticLongitude(M) { + + var C = rad * (1.9148 * sin(M) + 0.02 * sin(2 * M) + 0.0003 * sin(3 * M)), // equation of center + P = rad * 102.9372; // perihelion of the Earth + + return M + C + P + PI; +} + +function sunCoords(d) { + + var M = solarMeanAnomaly(d), + L = eclipticLongitude(M); + + return { + dec: declination(L, 0), + ra: rightAscension(L, 0) + }; +} + + +var SunCalc = {}; + + +// calculates sun position for a given date and latitude/longitude + +SunCalc.getPosition = function (date, lat, lng) { + + var lw = rad * -lng, + phi = rad * lat, + d = toDays(date), + + c = sunCoords(d), + H = siderealTime(d, lw) - c.ra; + + return { + azimuth: azimuth(H, phi, c.dec), + altitude: altitude(H, phi, c.dec) + }; +}; + + +// sun times configuration (angle, morning name, evening name) + +var times = SunCalc.times = [ + [-0.833, 'sunrise', 'sunset' ], + [ -0.3, 'sunriseEnd', 'sunsetStart' ], + [ -6, 'dawn', 'dusk' ], + [ -12, 'nauticalDawn', 'nauticalDusk'], + [ -18, 'nightEnd', 'night' ], + [ 6, 'goldenHourEnd', 'goldenHour' ] +]; + +// adds a custom time to the times config + +SunCalc.addTime = function (angle, riseName, setName) { + times.push([angle, riseName, setName]); +}; + + +// calculations for sun times + +var J0 = 0.0009; + +function julianCycle(d, lw) { return Math.round(d - J0 - lw / (2 * PI)); } + +function approxTransit(Ht, lw, n) { return J0 + (Ht + lw) / (2 * PI) + n; } +function solarTransitJ(ds, M, L) { return J2000 + ds + 0.0053 * sin(M) - 0.0069 * sin(2 * L); } + +function hourAngle(h, phi, d) { return acos((sin(h) - sin(phi) * sin(d)) / (cos(phi) * cos(d))); } +function observerAngle(height) { return -2.076 * Math.sqrt(height) / 60; } + +// returns set time for the given sun altitude +function getSetJ(h, lw, phi, dec, n, M, L) { + + var w = hourAngle(h, phi, dec), + a = approxTransit(w, lw, n); + return solarTransitJ(a, M, L); +} + + +// calculates sun times for a given date, latitude/longitude, and, optionally, +// the observer height (in meters) relative to the horizon + +SunCalc.getTimes = function (date, lat, lng, height) { + + height = height || 0; + + var lw = rad * -lng, + phi = rad * lat, + + dh = observerAngle(height), + + d = toDays(date), + n = julianCycle(d, lw), + ds = approxTransit(0, lw, n), + + M = solarMeanAnomaly(ds), + L = eclipticLongitude(M), + dec = declination(L, 0), + + Jnoon = solarTransitJ(ds, M, L), + + i, len, time, h0, Jset, Jrise; + + + var result = { + solarNoon: fromJulian(Jnoon), + nadir: fromJulian(Jnoon - 0.5) + }; + + for (i = 0, len = times.length; i < len; i += 1) { + time = times[i]; + h0 = (time[0] + dh) * rad; + + Jset = getSetJ(h0, lw, phi, dec, n, M, L); + Jrise = Jnoon - (Jset - Jnoon); + + result[time[1]] = fromJulian(Jrise); + result[time[2]] = fromJulian(Jset); + } + + return result; +}; + + +// moon calculations, based on http://aa.quae.nl/en/reken/hemelpositie.html formulas + +function moonCoords(d) { // geocentric ecliptic coordinates of the moon + + var L = rad * (218.316 + 13.176396 * d), // ecliptic longitude + M = rad * (134.963 + 13.064993 * d), // mean anomaly + F = rad * (93.272 + 13.229350 * d), // mean distance + + l = L + rad * 6.289 * sin(M), // longitude + b = rad * 5.128 * sin(F), // latitude + dt = 385001 - 20905 * cos(M); // distance to the moon in km + + return { + ra: rightAscension(l, b), + dec: declination(l, b), + dist: dt + }; +} + +SunCalc.getMoonPosition = function (date, lat, lng) { + + var lw = rad * -lng, + phi = rad * lat, + d = toDays(date), + + c = moonCoords(d), + H = siderealTime(d, lw) - c.ra, + h = altitude(H, phi, c.dec), + // formula 14.1 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + pa = atan(sin(H), tan(phi) * cos(c.dec) - sin(c.dec) * cos(H)); + + h = h + astroRefraction(h); // altitude correction for refraction + + return { + azimuth: azimuth(H, phi, c.dec), + altitude: h, + distance: c.dist, + parallacticAngle: pa + }; +}; + + +// calculations for illumination parameters of the moon, +// based on http://idlastro.gsfc.nasa.gov/ftp/pro/astro/mphase.pro formulas and +// Chapter 48 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + +SunCalc.getMoonIllumination = function (date) { + + var d = toDays(date || new Date()), + s = sunCoords(d), + m = moonCoords(d), + + sdist = 149598000, // distance from Earth to Sun in km + + phi = acos(sin(s.dec) * sin(m.dec) + cos(s.dec) * cos(m.dec) * cos(s.ra - m.ra)), + inc = atan(sdist * sin(phi), m.dist - sdist * cos(phi)), + angle = atan(cos(s.dec) * sin(s.ra - m.ra), sin(s.dec) * cos(m.dec) - + cos(s.dec) * sin(m.dec) * cos(s.ra - m.ra)); + + return { + fraction: (1 + cos(inc)) / 2, + phase: 0.5 + 0.5 * inc * (angle < 0 ? -1 : 1) / Math.PI, + angle: angle + }; +}; + + +function hoursLater(date, h) { + return new Date(date.valueOf() + h * dayMs / 24); +} + +// calculations for moon rise/set times are based on http://www.stargazing.net/kepler/moonrise.html article + +SunCalc.getMoonTimes = function (date, lat, lng, inUTC) { + var t = new Date(date); + if (inUTC) t.setUTCHours(0, 0, 0, 0); + else t.setHours(0, 0, 0, 0); + + var hc = 0.133 * rad, + h0 = SunCalc.getMoonPosition(t, lat, lng).altitude - hc, + h1, h2, rise, set, a, b, xe, ye, d, roots, x1, x2, dx; + + // go in 2-hour chunks, each time seeing if a 3-point quadratic curve crosses zero (which means rise or set) + for (var i = 1; i <= 24; i += 2) { + h1 = SunCalc.getMoonPosition(hoursLater(t, i), lat, lng).altitude - hc; + h2 = SunCalc.getMoonPosition(hoursLater(t, i + 1), lat, lng).altitude - hc; + + a = (h0 + h2) / 2 - h1; + b = (h2 - h0) / 2; + xe = -b / (2 * a); + ye = (a * xe + b) * xe + h1; + d = b * b - 4 * a * h1; + roots = 0; + + if (d >= 0) { + dx = Math.sqrt(d) / (Math.abs(a) * 2); + x1 = xe - dx; + x2 = xe + dx; + if (Math.abs(x1) <= 1) roots++; + if (Math.abs(x2) <= 1) roots++; + if (x1 < -1) x1 = x2; + } + + if (roots === 1) { + if (h0 < 0) rise = i + x1; + else set = i + x1; + + } else if (roots === 2) { + rise = i + (ye < 0 ? x2 : x1); + set = i + (ye < 0 ? x1 : x2); + } + + if (rise && set) break; + + h0 = h2; + } + + var result = {}; + + if (rise) result.rise = hoursLater(t, rise); + if (set) result.set = hoursLater(t, set); + + if (!rise && !set) result[ye > 0 ? 'alwaysUp' : 'alwaysDown'] = true; + + return result; +}; + + +// export as Node module / AMD module / browser variable +if (typeof exports === 'object' && typeof module !== 'undefined') module.exports = SunCalc; +else if (typeof define === 'function' && define.amd) define(SunCalc); +else window.SunCalc = SunCalc; + +}()); diff --git a/RVO7/flow/helper/utils.js b/RVO7/flow/helper/utils.js new file mode 100755 index 0000000..dbffe45 --- /dev/null +++ b/RVO7/flow/helper/utils.js @@ -0,0 +1,161 @@ +const fs = require('fs').promises; + +function bytesToInt(bytes, numberOfBytes) { + let buffer = []; + if (Array.isArray(bytes)) { + buffer = bytes.slice(0); + if (numberOfBytes != undefined) { + buffer = bytes.slice(bytes.length - numberOfBytes); + } + } + else buffer.push(bytes); + + let result = 0; + for (let i = 0; i < buffer.length; i++) { + result = (result << 8) | buffer[i]; + } + + return result >>> 0; //ensure it's an unsigned 32-bit number +} + +function resizeArray(arr, newSize, defaultValue) { + while (newSize > arr.length) + arr.push(defaultValue); + arr.length = newSize; +} + +longToByteArray = function(/*long*/long) { + // we want to represent the input as a 8-bytes array + var byteArray = [0, 0, 0, 0, 0, 0, 0, 0]; + + for (var index = 0; index < byteArray.length; index++) { + var byte = long & 0xff; + byteArray[index] = byte; + long = (long - byte) / 256; + } + + return byteArray; +}; + +function addDays(date, days) { + var result = new Date(date); + result.setDate(result.getDate() + days); + return result; +} + +/* +sleep(2000).then(() => { + // Do something after the sleep! + + +}); +*/ + +function sleep(time) { + return new Promise((resolve) => setTimeout(resolve, time)); +} + +function isEmptyObject(obj) { + for (var name in obj) { + return false; + } + return true; +} + +function emptyJsObject(jsObject) { + Object.keys(jsObject).forEach(key => delete jsObject[key]); +} + +function convertUTCDateToLocalDate(date) { + var newDate = new Date(date); + newDate.setMinutes(date.getMinutes() + date.getTimezoneOffset()); + return newDate; +} + +function addZeroBefore(n) { + return (n < 10 ? '0' : '') + n; +} + + +/** + * Asynchronously writes data to a file. + * + * @param {string} filePath The path to the file. + * @param {string} data The data to write to the file. + * @param {boolean} [append=false] If true, appends the data to the file. If false, it overwrites the file. + */ +async function writeToFile(filePath, data, append = false) { + if (typeof data !== 'string') data = JSON.stringify(data, null, 2); + try { + if (append) { + // Append the data to the end of the file. This is the simplest way to append. + await fs.appendFile(filePath, data, 'utf8'); + console.log(`Successfully appended data to ${filePath} using fs.appendFile.`); + } else { + // Overwrite the file with the new data. + await fs.writeFile(filePath, data, 'utf8'); + console.log(`Successfully wrote (overwrote) data to ${filePath} using fs.writeFile.`); + } + } catch (error) { + console.error(`Error writing to file ${filePath}:`, error); + } +} + + + /** + * Checks if an item is present in an array and adds it if it's not. + * * @param {Array} arr The array to check. + * @param {*} item The item to add. + * @returns {Array} The modified array. + */ +const addToArrayIfUnique = (arr, item) => { + if (!arr.includes(item)) { + arr.push(item); + } + return arr; +}; + + +var convertBase = function() { + + function convertBase(baseFrom, baseTo) { + return function(num) { + return parseInt(num, baseFrom).toString(baseTo); + + }; + } + + // binary to decimal + convertBase.bin2dec = convertBase(2, 10); + + // binary to hexadecimal + convertBase.bin2hex = convertBase(2, 16); + + // decimal to binary + convertBase.dec2bin = convertBase(10, 2); + + // decimal to hexadecimal + convertBase.dec2hex = convertBase(10, 16); + + // hexadecimal to binary + convertBase.hex2bin = convertBase(16, 2); + + // hexadecimal to decimal + convertBase.hex2dec = convertBase(16, 10); + + return convertBase; +}(); + +module.exports = { + bytesToInt, + longToByteArray, + addDays, + addZeroBefore, + resizeArray, + isEmptyObject, + emptyJsObject, + sleep, + convertUTCDateToLocalDate, + writeToFile, + addToArrayIfUnique +} diff --git a/RVO7/flow/httprequest.js b/RVO7/flow/httprequest.js new file mode 100755 index 0000000..469c8cb --- /dev/null +++ b/RVO7/flow/httprequest.js @@ -0,0 +1,137 @@ +exports.id = 'httprequest'; +exports.title = 'HTTP Request'; +exports.group = 'HTTP'; +exports.color = '#5D9CEC'; +exports.input = true; +exports.version = '2.0.1'; +exports.output = 1; +exports.author = 'Peter Širka'; +exports.icon = 'cloud-upload'; + +exports.html = `
+
@(URL address)
+
+
+
@(HTTP method)
+
+
+
@(Serialization)
+
+
+
@(Download the content in chunks)
+
@(Keep persistent cookies)
+
@(Disable DNS cache)
+
@(Keep alive connection)
+
+
+
+
@(Custom headers)
+
@(Cookies)
+
+
+
+ +
+
+
+
@(User)
+
+
+
@(Password)
+
+
+
+
+
`; + +exports.readme = `# Request + +This component creates a request with received data. + +__Response:__ +\`\`\`javascript +{ + data: String, + headers: Object, + status: Number, + host: String +} +\`\`\` + +__Dynamic arguments__: +Are performed via FlowData repository and can be used for URL address or for custom headers/cookies/auth. Use \`repository\` component for creating of dynamic arguments. Dynamic values are replaced in the form \`{key}\`: + +- url address e.g. \`https://.../{key}/\` +- headers values e.g. \`{token}\` +- cookies values e.g. \`{token}\``; + +exports.install = function(instance) { + + var can = false; + var flags = null; + var cookies2 = null; + + instance.on('data', function(response) { + can && instance.custom.send(response); + }); + + instance.custom.send = function(response) { + var options = instance.options; + + var headers = null; + var cookies = null; + + options.headers && Object.keys(options.headers).forEach(function(key) { + !headers && (headers = {}); + headers[key] = response.arg(options.headers[key]); + }); + + if (options.username && options.userpassword) { + !headers && (headers = {}); + headers['Authorization'] = 'Basic ' + U.createBuffer(response.arg(options.username + ':' + options.userpassword)).toString('base64'); + } + + options.cookies && Object.keys(options.cookies).forEach(function(key) { + !cookies && (cookies = {}); + cookies[key] = response.arg(options.cookies[key]); + }); + + if (options.chunks) { + U.download(response.arg(options.url), flags, options.stringify === 'none' ? null : response.data, function(err, response) { + response.on('data', (chunks) => instance.send2(chunks)); + }, cookies || cookies2, headers); + } else { + U.request(response.arg(options.url), flags, options.stringify === 'none' ? null : response.data, 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) + instance.error(err, response); + }, cookies || cookies2, headers); + } + }; + + instance.reconfigure = function() { + var options = instance.options; + can = options.url && options.url && options.method && options.stringify ? true : false; + instance.status(can ? '' : 'Not configured', can ? undefined : 'red'); + + if (!can) + return; + + flags = []; + flags.push(options.method.toLowerCase()); + options.stringify === 'json' && flags.push('json'); + options.stringify === 'raw' && flags.push('raw'); + options.keepalive && flags.push('keepalive'); + !options.nodns && flags.push('dnscache'); + if (options.persistentcookies) { + flags.push('cookies'); + cookies2 = {}; + } else + cookies2 = null; + }; + + instance.on('options', instance.reconfigure); + instance.reconfigure(); +}; \ No newline at end of file diff --git a/RVO7/flow/httpresponse.js b/RVO7/flow/httpresponse.js new file mode 100755 index 0000000..160a3bb --- /dev/null +++ b/RVO7/flow/httpresponse.js @@ -0,0 +1,76 @@ +exports.id = 'httpresponse'; +exports.title = 'HTTP Response'; +exports.group = 'HTTP'; +exports.color = '#5D9CEC'; +exports.icon = 'arrow-right'; +exports.input = true; +exports.output = ['#666D76']; +exports.version = '2.0.0'; +exports.author = 'Martin Smola'; +exports.readme = `# HTTP response + +HTTP response will respond with data recieved using data-type set in Settings form or plain text if not set. Output is the message duration \`Number\` in seconds.`; + +exports.html = `
+
@(Response data-type)
+
JSON is by default.
+
`; + +exports.install = function(instance) { + + var dursum = 0; + var durcount = 0; + + instance.on('data', function(flowdata) { + + var ctrl = flowdata.repository.controller; + var data = flowdata.data; + + if (!ctrl) { + instance.throw('No controller to use for response!'); + return; + } + + durcount++; + dursum += ((new Date() - flowdata.begin) / 1000).floor(2); + setTimeout2(instance.id, instance.custom.duration, 500, 10); + + ctrl.$flowdata = flowdata; + + var datatype = instance.options.datatype || 'json'; + if (datatype === 'emptyresponse') + return ctrl.plain(''); + + if (datatype !== 'json' && typeof(data) !== 'string') { + instance.throw('Incorect type of data, expected string, got ' + typeof(data)); + ctrl.plain(data == null ? '' : data.toString()); + return; + } + + switch(datatype) { + case 'html': + ctrl.content(data, 'text/html'); + break; + case 'plain': + ctrl.plain(data); + break; + case 'xml': + ctrl.content(data, 'text/xml'); + break; + default: + ctrl.json(data); + break; + } + }); + + instance.on('service', function() { + dursum = 0; + durcount = 0; + }); + + instance.custom.duration = function() { + var avg = (dursum / durcount).floor(2); + instance.status(avg + ' sec.'); + instance.send2(0, avg); + }; +}; diff --git a/RVO7/flow/httproute.js b/RVO7/flow/httproute.js new file mode 100755 index 0000000..583a19d --- /dev/null +++ b/RVO7/flow/httproute.js @@ -0,0 +1,326 @@ +exports.id = 'httproute'; +exports.title = 'HTTP Route'; +exports.group = 'HTTP'; +exports.color = '#5D9CEC'; +exports.icon = 'globe'; +exports.input = false; +exports.output = ['#6CAC5A', '#37BC9B']; +exports.version = '1.2.3'; +exports.author = 'Martin Smola'; +exports.cloning = false; +exports.options = { method: 'GET', url: '', size: 5, cacheexpire: '5 minutes', cachepolicy: 0, timeout: 5 }; +exports.dateupdated = '2021-01-21 18:30d'; +exports.readme = `# HTTP route + +__Outputs__: +- first output: raw data (cache is empty or is disabled) +- second output: cached data + +If one of the outputs is disabled then automatic responce with code "503 service unavailable" is sent. + +When a request comes in bellow object is available at \`flowdata.data\`: + +\`\`\`javascript +{ + params: { id: '1' }, // params for dynamic routes, e.g. /test/{id} + query: { msg: 'Hello' }, // parsed query string, e.g. /test/1?msg=Hello + body: { test: 'OK' }, // object if json requests otherwise string + headers: {}, // headers data + session: {}, // session data + user: {}, // user data + files: [], // uploaded files + url: '/users/', // a relative URL address + referrer: '/', // referrer + mobile: false, // determines mobile device + robot: false, // determines search robots/crawlsers + language: 'en' // determines language +} +\`\`\` + +See [documentation for flags](https://docs.totaljs.com/latest/en.html#api~HttpRouteOptionsFlags~unauthorize). These method flags are set automatically e.g. \`get, post, put, patch or delete\` + +--- + +\`id:ROUTE_ID\` flag cannot be used since it's already used by this component internally`; + +exports.html = `
+
+ +
+ +
+
+
@(HTTP method)
+
+
+
@(URL address)
+
+
+
+
+
@(Additional flags)
+
@(Separate flags by comma e.g. json, authorize)
+
+
+
@(Max. request size)
+
@(In kB kilobytes)
+
+
+
@(Timeout)
+
@(In seconds.)
+
+
+
+
+
+
@(Automatically respond with 200 OK?)
+
@(If not checked you need to use HTTP response component to respond to the request.)
+
+
@(Custom headers)
+
@(Cookies)
+
+
+
+
+
+
@(Cache policy)
+
@(User instance must contain id property.)
+
+
+
@(Expiration)
+
@(E.g. 5 minutes)
+
+
+
+`; + +exports.install = function(instance) { + + var route; + + var uninstall = function(id) { + if (F.is4) { + route && route.remove(); + route = null; + } else + UNINSTALL('route', id); + }; + + instance.custom.emptyresponse = function(self) { + self.plain(); + }; + + instance.reconfigure = function() { + + var options = instance.options; + + if (!options.url) { + instance.status('Not configured', 'red'); + return; + } + + if (typeof(options.flags) === 'string') + options.flags = options.flags.split(',').trim(); + + uninstall('id:' + instance.id); + + var flags = options.flags || []; + + flags.push('id:' + instance.id); + + if (!F.is4) + flags.push(options.method.toLowerCase()); + + options.timeout && flags.push(options.timeout * 1000); + + // Make unique values + flags = flags.filter(function(v, i, a) { + if(F.is4 && v.toString().toLowerCase() === options.method.toLowerCase()) + return false; // remove method + return a.indexOf(v) === i; + }); + + options.flags = flags; + var handler = function() { + + if (instance.paused || (instance.isDisabled && (instance.isDisabled('output', 0) || instance.isDisabled('output', 1)))) { + instance.status('503 Service Unavailable'); + this.status = 503; + this.json(); + return; + } + + var key; + var self = this; + + if (instance.options.emptyresponse) { + instance.status('200 OK'); + setTimeout(instance.custom.emptyresponse, 100, self); + + if (instance.hasConnection(0)) { + var data = instance.make({ + query: self.query, + body: self.body, + session: self.session, + user: self.user, + files: self.files, + headers: self.req.headers, + url: self.url, + params: self.params + }); + instance.send2(0, data); + } + + return; + } + + switch (instance.options.cachepolicy) { + case 1: // URL + key = 'rro' + instance.id + self.url.hash(); + break; + case 2: // URL + query + case 3: // URL + query + user + key = self.url; + var keys = Object.keys(self.query); + keys.sort(); + for (var i = 0, length = keys.length; i < length; i++) + key += keys[i] + self.query[keys[i]] + '&'; + if (instance.options.cachepolicy === 3 && self.user) + key += 'iduser' + self.user.id; + key = 'rro' + instance.id + key.hash(); + break; + } + + if (key && F.cache.get2(key)) { + var data = instance.make(F.cache.get2(key)); + data.repository.controller = self; + instance.send2(1, data); + } else { + + var data = instance.make({ + query: self.query, + body: self.body, + session: self.session, + user: self.user, + files: self.files, + headers: self.req.headers, + url: self.url, + params: self.params, + mobile: self.mobile, + robot: self.robot, + referrer: self.referrer, + language: self.language + }); + + data.repository.controller = self; + instance.send2(0, data); + key && FINISHED(self.res, () => F.cache.set(key, self.$flowdata.data, instance.options.cacheexpire)); + } + }; + + if (F.is4) + route = ROUTE(options.method.toUpperCase() + ' ' + options.url, handler, flags, options.size || 5); + else + F.route(options.url, handler, flags, options.size || 5); + + instance.status('Listening', 'green'); + }; + + instance.reconfigure(); + instance.on('options', instance.reconfigure); + instance.on('close', function(){ + uninstall('id:' + instance.id); + }); +}; + +// check url exists +FLOW.trigger('httproutecheckurl', function(next, data) { + var url = data.url; + var method = data.method; + if (url[url.length - 1] !== '/') + url += '/'; + var exists = F.routes.web.findItem(r => r.urlraw === url && r.method === method); + next(exists != null); +}); + +exports.uninstall = function() { + FLOW.trigger('httproutecheckurl', null); +}; diff --git a/RVO7/flow/infosender.js b/RVO7/flow/infosender.js new file mode 100755 index 0000000..587724f --- /dev/null +++ b/RVO7/flow/infosender.js @@ -0,0 +1,81 @@ +exports.id = 'infosender'; +exports.title = 'Info sender'; +exports.version = '1.0.0'; +exports.group = 'Worksys'; +exports.color = '#2134B0'; +exports.input = 2; +exports.output = 1 +exports.icon = 'bolt'; + +const { networkInterfaces } = require('os'); + +exports.html = `
+
+
+
CSV Import
+
+
+
`; + +exports.readme = `# send all data to projects.worksys.io, required to monitor status of controller(unipi)`; + +exports.install = function(instance) { + + let id; + let allValues = {}; + let sendAllValuesInterval; + let configured = false; + + let now = new Date(); + console.log(exports.title, "INSTALLED", now.toLocaleString("sk-SK")); + + const nets = networkInterfaces(); + let ipAddresses = Object.create(null); // Or just '{}', an empty object + + for (const name of Object.keys(nets)) { + for (const net of nets[name]) { + // Skip over non-IPv4 and internal (i.e. 127.0.0.1) addresses + if (net.family === 'IPv4' && !net.internal) { + if (!ipAddresses[name]) { + ipAddresses[name] = []; + } + ipAddresses[name].push(net.address); + } + } + } + + function sendValues() { + if (!configured) return; + + if (Object.keys(allValues).length > 0) { + let dataToSend = { ...allValues }; + dataToSend.id = id; + dataToSend.ipAddresses = ipAddresses; + + instance.send(0, dataToSend); + + allValues = {}; + } + } + + instance.on("close", () => { + clearInterval(sendAllValuesInterval); + }) + + instance.on("0", _ => { + id = FLOW.GLOBALS.settings.project_id; + if (id) configured = true; + else console.log(exports.title, "InfoSender: Unable to send data, no id"); + }) + + instance.on("1", flowdata => { + allValues = { ...allValues, ...flowdata.data }; + //console.log("DATA RECEIVED", flowdata.data); + }) + + sendAllValuesInterval = setInterval(() => { + sendValues(); + }, 60000 * 3); + +} + diff --git a/RVO7/flow/modbus_reader.js b/RVO7/flow/modbus_reader.js new file mode 100755 index 0000000..d6d9dad --- /dev/null +++ b/RVO7/flow/modbus_reader.js @@ -0,0 +1,346 @@ +exports.id = 'modbus_reader'; +exports.title = 'Modbus reader'; +exports.version = '2.0.0'; +exports.group = 'Worksys'; +exports.color = '#2134B0'; +exports.input = 1; +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; +//number of phases inRVO +let phases; +//phases where voltage is 0 (set) +let noVoltage; +let energyToSwitchLamps; + +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.phases = this.buildPhases(); + + this.startSocket(); + } + + buildPhases = () => { + let a = []; + for (let i = 1; i <= phases; i++) { + a.push(`Phase_${i}_voltage`) + } + return a; + } + + startSocket = () => { + + let obj = this; + + if (this.socket) { + this.socket.removeAllListeners(); + this.socket = null; + } + + 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('Modbus_reader: Socket connection error', e); //'ECONNREFUSED' or 'ECONNRESET' ?? + }); + + this.socket.on('close', function() { + console.log('Modbus_reader: Socket connection closed - Waiting 10 seconds before connecting 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 we just start to loop devices from the beginning, or there is just 1 device in config, we wait whole timeoutInterval + if (this.indexInDeviceConfig == 0 || deviceConfig.length === 1) 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 (this.phases.includes(singleValue)) { + let l = singleValue.split("_"); + let phase = parseInt(l[1]); + + // console.log(values[singleValue], tbName); + + if (values[singleValue] == 0) { + noVoltage.add(phase); + sendNotification("modbus_reader: checkNullVoltage", tbName, "no_voltage_on_phase", { phase: phase }, "", SEND_TO.tb, instance, "voltage" + phase); + // console.log('no voltage') + } + else { + noVoltage.delete(phase); + // console.log('voltage detected') + sendNotification("modbus_reader: checkNullVoltage", tbName, "voltage_on_phase_restored", { phase: phase }, "", SEND_TO.tb, instance, "voltage" + phase); + } + } + }) + } + + /** + * function sends notification to slack and to tb, if EM total_power value changes more than numberOfNodes*15. This should show, that RVO lamps has been switched on or off + */ + lampSwitchNotification = (values) => { + + if (!values.hasOwnProperty("total_power")) return; + + const actualTotalPower = values.total_power; + + if (actualTotalPower > energyToSwitchLamps && 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 <= energyToSwitchLamps && 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; + } + + function main() { + + phases = FLOW.GLOBALS.settings.phases; + tbName = FLOW.GLOBALS.settings.rvoTbName; + noVoltage = FLOW.GLOBALS.settings.no_voltage; + energyToSwitchLamps = FLOW.GLOBALS.settings.energy_to_switch_lamps / 2.5; //half value is enought to show if lamps are turned on or off + if (deviceConfig.length) mainSocket = new SocketWithClients(); + else console.log("Modbus_reader: no modbus device in configuration"); + + // this notification is to show, that flow (unipi) has been restarted + sendNotification("modbus_reader", tbName, "flow_restart", {}, "", SEND_TO.slack, instance); + } + + instance.on("0", function(_) { + main(); + }) + +} + diff --git a/RVO7/flow/monitorconsumption.js b/RVO7/flow/monitorconsumption.js new file mode 100755 index 0000000..64cc58e --- /dev/null +++ b/RVO7/flow/monitorconsumption.js @@ -0,0 +1,156 @@ +exports.id = 'monitorconsumption'; +exports.title = 'Consumption'; +exports.version = '1.0.0'; +exports.author = 'Peter Širka'; +exports.group = 'Monitoring'; +exports.color = '#967ADC'; +exports.input = 0; +exports.output = 1; +exports.icon = 'bug'; +exports.options = { interval: 5000, enabled: true, monitorconsumption: true, monitorsize: true, monitorconnections: true, monitorfiles: true }; +exports.click = true; +exports.readme = `# Consumption monitoring + +This component measure CPU and memory consumption, open files and open connections of this application. It uses these Linux commands: \`ps\`, \`lsof\`, \`netstat\` and \`df\`. + +__Data Example__: + +\`\`\`javascript +{ + cpu: 0, // percentage + memory: 4096, // in bytes + size: 34303, // directory size in bytes + files: 34, // count of open files + connections: 343, // count of connections + uptime: '1-12:34:00' +} +\`\`\``; + +exports.html = `
+
+
+
@(Interval in milliseconds)
+
+
+
+
Monitor: Consumption + uptime
+
Monitor: Count of open files
+
Monitor: Count of open connections
+
Monitor: Directory size
+
`; + +exports.install = function(instance) { + + var current = { cpu: 0, memory: 0, files: 0, connections: 0, size: 0, uptime: '', counter: 0 }; + var tproc = null; + var Exec = require('child_process').exec; + var reg_empty = /\s{2,}/g; + var reg_appdisksize = /^[\d.,]+/; + + instance.custom.run = function() { + + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + + var arr = []; + + // Get CPU and Memory consumption + instance.options.monitorconsumption && arr.push(function(next) { + Exec('ps -p {0} -o %cpu,rss,etime'.format(process.pid), function(err, response) { + + if (err) { + instance.throw(err); + } else { + var line = response.split('\n')[1]; + line = line.trim().replace(reg_empty, ' ').split(' '); + var cpu = line[0].parseFloat(); + current.cpu = cpu.floor(1); + current.memory = line[1].parseInt2() * 1024; // kB to bytes + current.uptime = line[2]; + } + + next(); + }); + }); + + // Get count of open files + instance.options.monitorfiles && arr.push(function(next) { + Exec('lsof -a -p {0} | wc -l'.format(process.pid), function(err, response) { + if (err) + instance.throw(err); + else + current.files = response.trim().parseInt2(); + next(); + }); + }); + + // Get count of opened network connections + instance.options.monitorconnections && arr.push(function(next) { + Exec('netstat -an | grep :{0} | wc -l'.format(F.port), function(err, response) { + if (err) { + instance.throw(err); + } else { + current.connections = response.trim().parseInt2() - 1; + if (current.connections < 0) + current.connections = 0; + } + next(); + }); + }); + + // Get directory size + instance.options.monitorsize && current.counter % 5 !== 0 && arr.push(function(next) { + Exec('du -hsb ' + process.cwd(), function(err, response) { + if (err) { + instance.throw(err); + } else { + var match = response.trim().match(reg_appdisksize); + match && (current.size = match.toString().trim().parseInt2()); + } + next(); + }); + }); + + arr.async(function() { + + tproc && clearTimeout(tproc); + + if (instance.options.enabled) { + tproc = setTimeout(instance.custom.run, instance.options.interval); + instance.send2(current); + } + + instance.custom.status(); + current.counter++; + }); + }; + + instance.custom.status = function() { + if (instance.options.enabled) + instance.status('{0}% / {1}'.format(current.cpu, current.memory.filesize())); + else + instance.status('Disabled', 'red'); + }; + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + + if (instance.options.enabled) { + current.counter = 0; + instance.custom.run(); + } + + }); + + instance.on('close', function() { + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + }); + + setTimeout(instance.custom.run, 1000); +}; \ No newline at end of file diff --git a/RVO7/flow/monitordisk.js b/RVO7/flow/monitordisk.js new file mode 100755 index 0000000..f4fdaa0 --- /dev/null +++ b/RVO7/flow/monitordisk.js @@ -0,0 +1,96 @@ +exports.id = 'monitordisk'; +exports.title = 'Disk'; +exports.version = '1.0.0'; +exports.author = 'Peter Širka'; +exports.group = 'Monitoring'; +exports.color = '#F6BB42'; +exports.output = 1; +exports.icon = 'hdd-o'; +exports.click = true; +exports.options = { interval: 8000, path: '/', enabled: true }; +exports.readme = `# Disk monitoring + +This component monitors disk \`bytes\` consumption in Linux systems. It uses \`df\` command. + +__Data Example__: + +\`\`\`javascript +{ + total: 474549649408, + used: 39125245952, + free: 411294994432 +} +\`\`\``; + +exports.html = `
+
+
+
@(Interval in milliseconds)
+
+
+
@(Path)
+
+
+
`; + +exports.install = function(instance) { + + var current = { total: 0, used: 0, free: 0, path: '', type: '', percentUsed: 0 }; + var tproc = null; + + instance.custom.run = function() { + + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + + if (!instance.options.enabled) + return; + + require('child_process').exec('df -hTB1 ' + instance.options.path, function(err, response) { + + tproc = setTimeout(instance.custom.run, instance.options.interval); + + if (err) { + instance.error(err); + return; + } + + response.parseTerminal(function(line) { + if (line[0][0] !== '/') + return; + current.total = line[2].parseInt(); + current.free = line[4].parseInt(); + current.used = line[3].parseInt(); + current.path = instance.options.path || '/'; + current.type = line[1]; + current.percentUsed = line[5]; + instance.custom.status(); + instance.send2(current); + }); + }); + }; + + instance.custom.status = function() { + if (instance.options.enabled) + instance.status(current.free.filesize() + ' / ' + current.total.filesize()); + else + instance.status('Disabled', 'red'); + }; + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + instance.options.enabled && instance.custom.run(); + }); + + instance.on('close', function() { + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + }); + + setTimeout(instance.custom.run, 1000); +}; \ No newline at end of file diff --git a/RVO7/flow/monitormemory.js b/RVO7/flow/monitormemory.js new file mode 100755 index 0000000..2decbc4 --- /dev/null +++ b/RVO7/flow/monitormemory.js @@ -0,0 +1,87 @@ +exports.id = 'monitormemory'; +exports.title = 'Memory'; +exports.version = '1.0.0'; +exports.author = 'Peter Širka'; +exports.group = 'Monitoring'; +exports.color = '#F6BB42'; +exports.output = 1; +exports.click = true; +exports.icon = 'microchip'; +exports.options = { interval: 8000, enabled: true }; +exports.readme = `# Memory monitoring + +This component monitors memory \`bytes\` consumption in Linux systems. It uses \`free\` command. + +__Data Example__: + +\`\`\`javascript +{ + total: 33558769664, + used: 1998868480, + free: 2653708288 +} +\`\`\``; + +exports.html = `
+
+
+
@(Interval in milliseconds)
+
+
+
`; + +exports.install = function(instance) { + + var current = { total: 0, used: 0, free: 0 }; + var tproc = null; + + instance.custom.run = function() { + + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + + if (!instance.options.enabled) + return; + + require('child_process').exec('free -b -t', function(err, response) { + + tproc = setTimeout(instance.custom.run, instance.options.interval); + + if (err) { + instance.error(err); + return; + } + + var memory = response.split('\n')[1].match(/\d+/g); + current.total = memory[0].parseInt(); + current.used = memory[1].parseInt() - memory[3].parseInt(); + current.free = current.total - current.used; + instance.custom.status(); + instance.send2(current); + }); + }; + + instance.custom.status = function() { + if (instance.options.enabled) + instance.status(current.free.filesize() + ' / ' + current.total.filesize()); + else + instance.status('Disabled', 'red'); + }; + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + instance.options.enabled && instance.custom.run(); + }); + + instance.on('close', function() { + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + }); + + setTimeout(instance.custom.run, 1000); +}; \ No newline at end of file diff --git a/RVO7/flow/nodesdb_changecheck.js b/RVO7/flow/nodesdb_changecheck.js new file mode 100755 index 0000000..9adab62 --- /dev/null +++ b/RVO7/flow/nodesdb_changecheck.js @@ -0,0 +1,77 @@ +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 = 2; +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); + } + } + + //kedze do slacku posielame stringy, na cloud musime previest vsetky stringy spat na objekty: + // Funkcia na parsovanie všetkých reťazcov v poli + const parseArray = (arr) => { + return arr.map(jsonString => JSON.parse(jsonString)); + }; + + 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); + if (FLOW.GLOBALS.settings.send_changed_node_numbers) instance.send(1, { aktualneNody: parseArray(zmenene), originalne: parseArray(Array.from(set2)) }); + } + 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/RVO7/flow/show_dbdata.js b/RVO7/flow/show_dbdata.js new file mode 100755 index 0000000..1e23ff7 --- /dev/null +++ b/RVO7/flow/show_dbdata.js @@ -0,0 +1,243 @@ +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 = 8; +exports.output = 1; + +const { exec } = require('child_process'); + +exports.install = 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 }) + }) + instance.on("5", _ => { + exec("sudo tail -n 25 monitor.txt", (err, stdout, stderr) => { + if (err || stderr) instance.send(0, { err, stderr }); + else instance.send(0, stdout); + }) + }) + instance.on("6", _ => { + exec("sudo tail -n 25 err.txt", (err, stdout, stderr) => { + if (err || stderr) instance.send(0, { err, stderr }); + else instance.send(0, stdout); + }) + }) + instance.on("7", _ => { + instance.send(0, FLOW.deviceStatus); + }) +}; + + +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/RVO7/flow/slack_filter.js b/RVO7/flow/slack_filter.js new file mode 100755 index 0000000..6618523 --- /dev/null +++ b/RVO7/flow/slack_filter.js @@ -0,0 +1,188 @@ +exports.id = 'slack_filter'; +exports.title = 'Slack Filter'; +exports.group = 'Citysys'; +exports.color = '#30E193'; +exports.input = 2; +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 = `
+
+
+
@(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('0', 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']['en']; + 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"] = []; + } + + instance.options.name = FLOW.GLOBALS.settings.rvo_name; + if (instance.options.name) { + instance.status('Running'); + running = true; + } else { + instance.status('Please run options again', 'red'); + running = false; + } + } catch (e) { + instance.error('Citysys connector: ' + e.message); + } + }; + + instance.on('options', instance.reconfigure); + + instance.on("1", _ => { + instance.reconfigure(); + }) +}; diff --git a/RVO7/flow/thermometer.js b/RVO7/flow/thermometer.js new file mode 100755 index 0000000..fc7074d --- /dev/null +++ b/RVO7/flow/thermometer.js @@ -0,0 +1,99 @@ +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 = 5;//minutes +let NUMBER_OF_FAILURES_TO_SEND_ERROR = 13; + +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) => { + + 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); + setTimeout(main, 20000); + }) +}; diff --git a/RVO7/flow/trigger.js b/RVO7/flow/trigger.js new file mode 100755 index 0000000..27545a8 --- /dev/null +++ b/RVO7/flow/trigger.js @@ -0,0 +1,79 @@ +exports.id = 'trigger'; +exports.title = 'Trigger'; +exports.group = 'Inputs'; +exports.color = '#F6BB42'; +exports.click = true; +exports.output = 1; +exports.version = '1.1.0'; +exports.author = 'Martin Smola'; +exports.icon = 'play'; + +exports.html = `
+
@(Data type (String by default))
+
@(Data)
+
Trigger 5s after initialization.
+
@(Useful when there's a need to run certain flow when the app restarts, etc.)
+
`; + +exports.readme = `# Trigger + +- Clicking on the component starts the chain +- Settings allows to set a data-type and a value`; + +exports.install = function(instance) { + + var value; + + instance.on('click', () => instance.send2(value)); + + instance.reconfigure = function() { + var options = instance.options; + value = null; + switch (options.datatype) { + case 'integer': + value = options.data.parseInt2('error'); + value = value === 'error' ? NaN : value; + break; + case 'float': + value = options.data.parseFloat2('error'); + value = value === 'error' ? NaN : value; + break; + case 'date': + options.data = options.data.toString(); + var num = options.data.parseInt('error'); + num === 'error' && (num = options.data.parseDate('error')); + num === 'error' && (num = null); + value = num ? new Date(num).toUTCString() : num; + break; + case 'object': + try { + value = (new Function('return ' + options.data))(); + } catch (e) { + instance.error(e); + } + break; + case 'boolean': + value = options.data.parseBoolean(); + break; + case 'buffer': + try { + value = U.createBuffer(options.data); + } catch (e) { + instance.error(e); + } + break; + case 'string': + default: + value = '' + (options.data || ''); + break; + } + }; + + instance.on('options', instance.reconfigure); + instance.reconfigure(); + + if (instance.options.restart) + setTimeout(function(){ + instance.send2(value); + }, 5000); +}; diff --git a/RVO7/flow/variables.txt b/RVO7/flow/variables.txt new file mode 100755 index 0000000..e69de29 diff --git a/RVO7/flow/virtualwirein.js b/RVO7/flow/virtualwirein.js new file mode 100755 index 0000000..38a4e42 --- /dev/null +++ b/RVO7/flow/virtualwirein.js @@ -0,0 +1,43 @@ +exports.id = 'virtualwirein'; +exports.title = 'Virtual wire in'; +exports.version = '1.0.0'; +exports.author = 'Martin Smola'; +exports.color = '#303E4D'; +exports.icon = 'sign-in'; +exports.input = false; +exports.output = 1; +exports.options = {}; +exports.readme = `# Virtual wire in + +When the wires between the components are mess it's time to use Virtual wire.`; + +exports.html = `
+
@(Wire name)
+
+`; + +exports.install = function(instance) { + + instance.custom.reconfigure = function(options){ + if (instance.options.wirename) { + instance.status(instance.options.wirename); + } else + instance.status('Not configured', 'red'); + }; + + ON('virtualwire', function(wirename, flowdata){ + if (instance.options.wirename && instance.options.wirename === wirename) + instance.send(flowdata); + }); + + instance.on('options', instance.custom.reconfigure); + instance.custom.reconfigure(); +}; diff --git a/RVO7/flow/virtualwireout.js b/RVO7/flow/virtualwireout.js new file mode 100755 index 0000000..94a1e4f --- /dev/null +++ b/RVO7/flow/virtualwireout.js @@ -0,0 +1,41 @@ +exports.id = 'virtualwireout'; +exports.title = 'Virtual wire out'; +exports.version = '1.0.0'; +exports.author = 'Martin Smola'; +exports.color = '#303E4D'; +exports.icon = 'sign-out'; +exports.input = true; +exports.options = {}; +exports.readme = `# Virtual wire out + +When the wires between the components are mess it's time to use Virtual wire.`; + +exports.html = `
+
@(Wire name)
+
+`; + +exports.install = function(instance) { + + instance.custom.reconfigure = function(){ + if (instance.options.wirename) { + instance.status(instance.options.wirename); + } else + instance.status('Not configured', 'red'); + }; + + instance.on('data', function(flowdata) { + EMIT('virtualwire', instance.options.wirename, flowdata); + }); + + instance.on('options', instance.custom.reconfigure); + instance.custom.reconfigure(); +}; diff --git a/RVO7/flow/wsmqttpublish.js b/RVO7/flow/wsmqttpublish.js new file mode 100755 index 0000000..0eba804 --- /dev/null +++ b/RVO7/flow/wsmqttpublish.js @@ -0,0 +1,448 @@ +exports.id = 'wsmqttpublish'; +exports.title = 'WS MQTT publish'; +exports.group = 'MQTT'; +exports.color = '#888600'; +exports.version = '1.0.2'; +exports.icon = 'sign-out'; +exports.input = 2; +exports.output = 3; +exports.options = { host: 'tb-stage.worksys.io', port: 1883, clientid: "", username: "" }; + +exports.html = `
+
+
+
Hostname or IP address (if not empty - setting will override db setting)
+
+
+
Port
+
+
+
+
+
@(Client id)
+
+
+
@(Username)
+
+
+
`; + + +exports.readme = ` +# WS MQTT Publish + +Version 1.0.3. + +Added: +- database collections, +- 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 = { + debug: 0, + rpcCall: 1, + services: 2 +} + +//CONFIG +let createTelemetryBackup = true; +let saveTelemetryOnError = true;//backup_on_failure overrides this value +//------------------------ + +let rollers; +if (createTelemetryBackup) rollers = require('streamroller'); + +const noSqlFileSizeLimit = 4194304;//use 5MB - 4194304 +let insertNoSqlCounter = 0; +let insertBackupNoSqlCounter = 0; +let processingData = false; + +let backup_on_failure = false;//== saveTelemetryOnError - create backup client 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; + +process.on('uncaughtException', function(err) { + + errLogger.error('uncaughtException:', err.message) + errLogger.error(err.stack); + + //TODO + //send to service + + //process.exit(1); +}) + +const nosql = NOSQL('tbdata'); +const nosqlBackup = NOSQL('/backup/tbdata'); + + +exports.install = function(instance) { + + var client; + var opts; + var clientReady = false; + + // wsmqtt status for notification purposes on projects.worksys.io database + let wsmqttName = null; + let sendWsStatusVar = null; + let wsmqtt_status = 'disconnected'; + + 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'; + } + + function sendWsStatus() { + instance.send(SEND_TO.services, { [wsmqttName]: wsmqtt_status }); + } + + + function main() { + if (!FLOW.dbLoaded) return; + + loadSettings(); + clearInterval(sendWsStatus); + sendWsStatusVar = setInterval(sendWsStatus, 180000); + } + + //set opts according to db settings + function loadSettings() { + + if (instance.options.host !== "") { + //override settings from database + var o = instance.options; + opts = { + host: o.host, + port: o.port, + clientId: o.clientid, + username: o.username, + rejectUnauthorized: false, + resubscribe: false + }; + + wsmqttName = getWsmqttName(o.host); + + console.log("wsmqttpublich -> loadSettings from instance.options", instance.options); + } + else { + + const SETTINGS = FLOW.GLOBALS.settings; + backup_on_failure = SETTINGS.backup_on_failure; + saveTelemetryOnError = backup_on_failure; + + restore_from_backup = SETTINGS.restore_from_backup; + restore_backup_wait = SETTINGS.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; + + opts = { + host: mqtt_host, + port: mqtt_port, + keepalive: 10, + clientId: mqtt_clientid, + username: mqtt_username, + rejectUnauthorized: false, + resubscribe: false + }; + + wsmqttName = getWsmqttName(mqtt_host); + } + + connectToTbServer(); + } + + function connectToTbServer() { + 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"); + //monitor.info("MQTT client connected"); + + sendClientError = true; + clientReady = true; + wsmqtt_status = 'connected'; + }); + + client.on('reconnect', function() { + instance.status("Reconnecting", "yellow"); + clientReady = false; + }); + + client.on('message', function(topic, message) { + // message is type of buffer + message = message.toString(); + if (message[0] === '{') { + TRY(function() { + + message = JSON.parse(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 } }); + } + + }, () => instance.debug('MQTT: Error parsing data', message)); + } + + instance.send(SEND_TO.rpcCall, { "topic": topic, "content": message }); + }); + + client.on('close', function() { + clientReady = false; + wsmqtt_status = 'disconnected'; + + instance.status("Disconnected", "red"); + instance.send(SEND_TO.debug, { "message": "Client CLOSE signal received !" }); + }); + + client.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; + wsmqtt_status = 'disconnected'; + }); + + } + + + instance.on("0", _ => { + main(); + }) + + + instance.on('1', function(data) { + + if (clientReady) { + //do we have some data in backup file? if any, process data from database + if (saveTelemetryOnError) { + //read telemetry data and send back to server + if (!processingData) processDataFromDatabase(); + } + + let stringifiedJson = JSON.stringify(data.data); + client.publish("v1/gateway/telemetry", stringifiedJson, { qos: 1 }); + + //backup telemetry + if (createTelemetryBackup) { + data.data.id = UID(); + nosqlBackup.insert(data.data); + + insertBackupNoSqlCounter++; + if (insertBackupNoSqlCounter > 150) { + let options = { compress: true }; + let path = __dirname + "/../databases/backup/tbdata.nosql"; + var stream = new rollers.RollingFileStream(path, noSqlFileSizeLimit, 150, options); + stream.write(""); + stream.end(); + + insertBackupNoSqlCounter = 0; + } + } + + } + 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 (saveTelemetryOnError) { + //create new file from tbdata.nosql, if file size exceeds given limit, and clear tbdata.nosql + makeBackupFromDbFile(); + + //write to tb + data.data.id = UID(); + nosql.insert(data.data); + } + } + }); + + + instance.close = function(done) { + if (clientReady) { + client.end(); + clearInterval(sendWsStatusVar); + } + }; + + + function getDbBackupFileCounter(type) { + var files = fs.readdirSync(__dirname + "/../databases"); + + let counter = 0; + for (var i = 0; i < files.length; i++) { + + if (files[i] == "tbdata.nosql") continue; + + if (files[i].endsWith(".nosql")) { + + let pos = files[i].indexOf("."); + if (pos > -1) { + + let fileCounter = counter; + let firstDigit = files[i].slice(0, pos); + + fileCounter = parseInt(firstDigit); + if (isNaN(fileCounter)) fileCounter = 0; + //console.log("getDbBackupFileCounter digit:", files[i], firstDigit, fileCounter, isNaN(fileCounter), type); + + if (type == "max") { + if (fileCounter > counter) { + counter = fileCounter; + } + } + else if (type == "min") { + if (counter == 0) counter = fileCounter; + + if (fileCounter < counter) { + counter = fileCounter; + } + } + } + } + + } + + if (type == "max") counter++; + + return counter; + } + + const makeBackupFromDbFile = async () => { + + if (!saveTelemetryOnError) return; + + //to avoid large file: tbdata.nosql + + //init value is 0! + if (insertNoSqlCounter > 0) { + --insertNoSqlCounter; + return; + } + + insertNoSqlCounter = 100; + + let source = __dirname + "/../databases/tbdata.nosql"; + + var stats = fs.statSync(source); + var fileSizeInBytes = stats.size; + + if (fileSizeInBytes > noSqlFileSizeLimit) { + + let counter = 1; + counter = getDbBackupFileCounter("max"); + + let destination = __dirname + "/../databases/" + counter + "." + "tbdata.nosql"; + + //make backup file + fs.copyFileSync(source, destination); + //fs.renameSync(p, p + "." + counter); + + //clear tbdata.nosql + fs.writeFileSync(source, ""); + fs.truncateSync(source, 0); + + } + } + + const processDataFromDatabase = async () => { + + if (restore_from_backup <= 0) return; + + //calculate diff + const now = new Date(); + let currentTime = now.getTime(); + let diff = currentTime - lastRestoreTime; + + if ((diff / 1000) < restore_backup_wait) { + //console.log("*********restore_backup_wait", diff, restore_backup_wait); + return; + } + + processingData = true; + + //get filename to process + let counter = getDbBackupFileCounter("min"); + + //we have some backup files + let dataBase = 'tbdata'; + + var nosql; + if (counter == 0) dataBase = 'tbdata'; + else dataBase = counter + "." + 'tbdata'; + + nosql = NOSQL(dataBase); + + //select all data - use limit restore_from_backup + let records = await promisifyBuilder(nosql.find().take(restore_from_backup)); + + for (let i = 0; i < records.length; i++) { + if (clientReady) { + + let item = records[i]; + let id = item.id; + + if (id !== undefined) { + //console.log("------------processDataFromDatabase - remove", id, dataBase, i); + + try { + + let message = JSON.parse(JSON.stringify(item)); + delete message.id; + + client.publish("v1/gateway/telemetry", JSON.stringify(message), { qos: 1 }); + + //remove from database + await promisifyBuilder(nosql.remove().where("id", id)); + + } catch (error) { + //process error + console.log("processDataFromDatabase", error); + } + + } + + } + else { + processingData = false; + return; + } + } + + if (records.length > 0) { + //clean backup file + if (counter > 0) nosql.clean(); + } + + //no data in db, remove + if (records.length == 0) { + if (counter > 0) nosql.drop(); + } + + const d = new Date(); + lastRestoreTime = d.getTime(); + + processingData = false; + + } + + instance.on('options', main); + //instance.reconfigure(); +}; diff --git a/RVO7/monitor.txt b/RVO7/monitor.txt new file mode 100755 index 0000000..a25b5ec --- /dev/null +++ b/RVO7/monitor.txt @@ -0,0 +1,3390 @@ +[2024-10-11T13:29:55.140] [INFO] monitorLogs - MQTT broker error Error: connect ECONNREFUSED 192.168.252.1:1883 + at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1159:16) { + errno: -111, + code: 'ECONNREFUSED', + syscall: 'connect', + address: '192.168.252.1', + port: 1883 +} +[2024-10-11T13:30:04.976] [INFO] monitorLogs - MQTT broker connected +[2024-10-12T03:32:52.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-12 03:32:52 +[2024-10-12T13:00:20.116] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-12T13:00:20.151] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-12T13:00:20.185] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-12T14:55:34.246] [INFO] monitorLogs - MQTT broker connected +[2024-10-13T03:32:53.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-13 03:32:53 +[2024-10-13T13:00:20.327] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-13T13:00:20.361] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-13T13:00:20.396] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-14T03:32:55.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-14 03:32:55 +[2024-10-14T13:00:20.452] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-14T13:00:20.490] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-14T13:00:20.526] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-15T03:32:57.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-15 03:32:57 +[2024-10-15T06:44:04.283] [INFO] monitorLogs - MQTT broker connected +[2024-10-15T06:49:33.188] [INFO] monitorLogs - MQTT broker connected +[2024-10-15T07:25:32.891] [INFO] monitorLogs - MQTT broker connected +[2024-10-15T07:39:46.642] [INFO] monitorLogs - MQTT broker connected +[2024-10-15T07:53:56.618] [INFO] monitorLogs - MQTT broker connected +[2024-10-15T08:10:35.321] [INFO] monitorLogs - MQTT broker connected +[2024-10-15T13:00:20.497] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-15T13:00:20.530] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-15T13:00:20.563] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-16T03:32:58.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-16 03:32:58 +[2024-10-16T08:50:16.400] [INFO] monitorLogs - MQTT broker connected +[2024-10-16T08:50:52.684] [INFO] monitorLogs - MQTT broker connected +[2024-10-16T08:55:07.462] [INFO] monitorLogs - MQTT broker connected +[2024-10-16T09:00:17.503] [INFO] monitorLogs - MQTT broker connected +[2024-10-16T09:00:59.503] [INFO] monitorLogs - MQTT broker connected +[2024-10-16T09:02:05.885] [INFO] monitorLogs - MQTT broker connected +[2024-10-16T09:03:39.659] [INFO] monitorLogs - MQTT broker connected +[2024-10-16T09:06:42.275] [INFO] monitorLogs - MQTT broker connected +[2024-10-16T09:50:08.762] [INFO] monitorLogs - MQTT broker connected +[2024-10-16T10:02:32.484] [INFO] monitorLogs - MQTT broker connected +[2024-10-16T10:05:45.753] [INFO] monitorLogs - MQTT broker connected +[2024-10-16T10:30:38.818] [INFO] monitorLogs - MQTT broker connected +[2024-10-16T10:31:32.953] [INFO] monitorLogs - MQTT broker connected +[2024-10-16T10:36:17.056] [INFO] monitorLogs - MQTT broker connected +[2024-10-16T10:48:28.375] [INFO] monitorLogs - MQTT broker connected +[2024-10-16T10:50:10.046] [INFO] monitorLogs - MQTT broker connected +[2024-10-16T10:50:51.967] [INFO] monitorLogs - MQTT broker connected +[2024-10-16T10:51:37.673] [INFO] monitorLogs - MQTT broker connected +[2024-10-16T13:00:20.739] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-16T13:00:20.773] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-16T13:00:20.806] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-17T03:33:00.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-17 03:33:00 +[2024-10-17T08:31:47.416] [INFO] monitorLogs - MQTT broker connected +[2024-10-17T08:34:16.594] [INFO] monitorLogs - MQTT broker connected +[2024-10-17T08:36:19.613] [INFO] monitorLogs - MQTT broker connected +[2024-10-17T08:42:18.983] [INFO] monitorLogs - MQTT broker connected +[2024-10-17T13:00:20.798] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-17T13:00:20.831] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-17T13:00:20.864] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-17T13:40:58.418] [INFO] monitorLogs - MQTT broker connected +[2024-10-17T13:46:06.656] [INFO] monitorLogs - MQTT broker connected +[2024-10-17T13:48:06.889] [INFO] monitorLogs - MQTT broker connected +[2024-10-17T13:50:58.922] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T03:33:01.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-18 03:33:01 +[2024-10-18T13:00:21.269] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-18T13:00:21.302] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-18T13:00:21.336] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-18T16:22:17.213] [INFO] monitorLogs - MQTT broker error Error: Connection refused: Server unavailable + at MqttClient._handleConnack (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:1388:17) + at MqttClient._handlePacket (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:549:12) + at work (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:438:12) + at Writable.writable._write (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:452:5) + at doWrite (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:409:139) + at writeOrBuffer (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:398:5) + at Writable.write (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:307:11) + at Socket.ondata (internal/streams/readable.js:731:22) + at Socket.emit (events.js:400:28) + at addChunk (internal/streams/readable.js:293:12) { + code: 3 +} +[2024-10-18T16:22:38.228] [INFO] monitorLogs - MQTT broker error Error: Connection refused: Server unavailable + at MqttClient._handleConnack (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:1388:17) + at MqttClient._handlePacket (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:549:12) + at work (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:438:12) + at Writable.writable._write (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:452:5) + at doWrite (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:409:139) + at writeOrBuffer (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:398:5) + at Writable.write (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:307:11) + at Socket.ondata (internal/streams/readable.js:731:22) + at Socket.emit (events.js:400:28) + at addChunk (internal/streams/readable.js:293:12) { + code: 3 +} +[2024-10-18T16:22:51.673] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T17:20:13.307] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T17:20:13.682] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T17:29:24.560] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T17:40:47.150] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T17:40:47.307] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T17:50:04.503] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T17:50:05.696] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T17:54:26.506] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T18:03:28.462] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T18:03:29.895] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T18:14:50.914] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T18:15:35.076] [INFO] monitorLogs - MQTT broker error Error: Connection refused: Server unavailable + at MqttClient._handleConnack (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:1388:17) + at MqttClient._handlePacket (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:549:12) + at work (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:438:12) + at Writable.writable._write (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:452:5) + at doWrite (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:409:139) + at writeOrBuffer (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:398:5) + at Writable.write (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:307:11) + at Socket.ondata (internal/streams/readable.js:731:22) + at Socket.emit (events.js:400:28) + at addChunk (internal/streams/readable.js:293:12) { + code: 3 +} +[2024-10-18T18:15:35.216] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T18:20:07.621] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T18:36:52.492] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T20:03:32.369] [INFO] monitorLogs - MQTT broker error Error: Connection refused: Server unavailable + at MqttClient._handleConnack (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:1388:17) + at MqttClient._handlePacket (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:549:12) + at work (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:438:12) + at Writable.writable._write (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:452:5) + at doWrite (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:409:139) + at writeOrBuffer (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:398:5) + at Writable.write (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:307:11) + at Socket.ondata (internal/streams/readable.js:731:22) + at Socket.emit (events.js:400:28) + at addChunk (internal/streams/readable.js:293:12) { + code: 3 +} +[2024-10-18T20:03:32.622] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T20:30:05.982] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T20:30:06.265] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T20:30:06.414] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T20:44:08.881] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T20:44:09.032] [INFO] monitorLogs - MQTT broker connected +[2024-10-19T03:33:03.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-19 03:33:03 +[2024-10-19T13:00:21.284] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-19T13:00:21.317] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-19T13:00:21.351] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-19T17:03:21.118] [INFO] monitorLogs - MQTT broker error Error: Connection refused: Server unavailable + at MqttClient._handleConnack (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:1388:17) + at MqttClient._handlePacket (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:549:12) + at work (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:438:12) + at Writable.writable._write (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:452:5) + at doWrite (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:409:139) + at writeOrBuffer (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:398:5) + at Writable.write (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:307:11) + at Socket.ondata (internal/streams/readable.js:731:22) + at Socket.emit (events.js:400:28) + at addChunk (internal/streams/readable.js:293:12) { + code: 3 +} +[2024-10-19T17:03:28.168] [INFO] monitorLogs - MQTT broker connected +[2024-10-20T03:33:04.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-20 03:33:04 +[2024-10-20T13:00:21.326] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-20T13:00:21.362] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-20T13:00:21.401] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-21T03:25:05.550] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T03:33:06.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-21 03:33:06 +[2024-10-21T03:51:33.910] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T03:51:34.063] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T04:10:10.045] [INFO] monitorLogs - MQTT broker error Error: Connection refused: Server unavailable + at MqttClient._handleConnack (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:1388:17) + at MqttClient._handlePacket (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:549:12) + at work (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:438:12) + at Writable.writable._write (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:452:5) + at doWrite (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:409:139) + at writeOrBuffer (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:398:5) + at Writable.write (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:307:11) + at Socket.ondata (internal/streams/readable.js:731:22) + at Socket.emit (events.js:400:28) + at addChunk (internal/streams/readable.js:293:12) { + code: 3 +} +[2024-10-21T04:10:16.051] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T04:10:16.955] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T04:10:18.244] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T04:20:11.097] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T04:37:32.029] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T04:37:32.212] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T04:45:55.686] [INFO] monitorLogs - MQTT broker error Error: Connection refused: Server unavailable + at MqttClient._handleConnack (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:1388:17) + at MqttClient._handlePacket (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:549:12) + at work (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:438:12) + at Writable.writable._write (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:452:5) + at doWrite (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:409:139) + at writeOrBuffer (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:398:5) + at Writable.write (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:307:11) + at Socket.ondata (internal/streams/readable.js:731:22) + at Socket.emit (events.js:400:28) + at addChunk (internal/streams/readable.js:293:12) { + code: 3 +} +[2024-10-21T04:46:08.488] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T07:59:58.336] [INFO] monitorLogs - MQTT broker error Error: Connection refused: Server unavailable + at MqttClient._handleConnack (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:1388:17) + at MqttClient._handlePacket (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:549:12) + at work (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:438:12) + at Writable.writable._write (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:452:5) + at doWrite (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:409:139) + at writeOrBuffer (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:398:5) + at Writable.write (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:307:11) + at Socket.ondata (internal/streams/readable.js:731:22) + at Socket.emit (events.js:400:28) + at addChunk (internal/streams/readable.js:293:12) { + code: 3 +} +[2024-10-21T08:00:15.615] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T09:11:24.200] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T09:11:24.550] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T09:55:22.378] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T09:55:22.541] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T10:04:14.845] [INFO] monitorLogs - MQTT broker error Error: Connection refused: Server unavailable + at MqttClient._handleConnack (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:1388:17) + at MqttClient._handlePacket (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:549:12) + at work (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:438:12) + at Writable.writable._write (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:452:5) + at doWrite (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:409:139) + at writeOrBuffer (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:398:5) + at Writable.write (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:307:11) + at Socket.ondata (internal/streams/readable.js:731:22) + at Socket.emit (events.js:400:28) + at addChunk (internal/streams/readable.js:293:12) { + code: 3 +} +[2024-10-21T10:07:34.522] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T10:07:45.302] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T10:23:09.952] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T10:23:11.412] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T10:36:42.324] [INFO] monitorLogs - MQTT broker error Error: Connection refused: Server unavailable + at MqttClient._handleConnack (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:1388:17) + at MqttClient._handlePacket (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:549:12) + at work (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:438:12) + at Writable.writable._write (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:452:5) + at doWrite (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:409:139) + at writeOrBuffer (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:398:5) + at Writable.write (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:307:11) + at Socket.ondata (internal/streams/readable.js:731:22) + at Socket.emit (events.js:400:28) + at addChunk (internal/streams/readable.js:293:12) { + code: 3 +} +[2024-10-21T10:36:42.605] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T10:42:06.159] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T10:44:26.881] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T10:44:33.601] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T11:40:33.933] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T11:45:20.705] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T11:54:50.933] [INFO] monitorLogs - MQTT broker error Error: Connection refused: Server unavailable + at MqttClient._handleConnack (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:1388:17) + at MqttClient._handlePacket (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:549:12) + at work (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:438:12) + at Writable.writable._write (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:452:5) + at doWrite (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:409:139) + at writeOrBuffer (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:398:5) + at Writable.write (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:307:11) + at Socket.ondata (internal/streams/readable.js:731:22) + at Socket.emit (events.js:400:28) + at addChunk (internal/streams/readable.js:293:12) { + code: 3 +} +[2024-10-21T11:56:16.064] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T11:56:16.214] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T13:00:21.349] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-21T13:00:21.383] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-21T13:00:21.416] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-22T03:33:08.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-22 03:33:08 +[2024-10-22T13:00:21.390] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-22T13:00:21.425] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-22T13:00:21.460] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-23T03:33:09.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-23 03:33:09 +[2024-10-23T13:00:21.449] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-23T13:00:21.483] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-23T13:00:21.516] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-24T03:33:11.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-24 03:33:11 +[2024-10-24T10:29:09.446] [INFO] monitorLogs - MQTT broker connected +[2024-10-24T13:00:21.591] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-24T13:00:21.624] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-24T13:00:21.657] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-25T03:33:12.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-25 03:33:12 +[2024-10-25T13:00:21.740] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-25T13:00:21.774] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-25T13:00:21.809] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-25T15:55:43.796] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2024-10-25T15:55:44.160] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 true turn off on startup +[2024-10-25T15:55:44.177] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 true turn off on startup +[2024-10-25T15:55:44.185] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 true turn off on startup +[2024-10-25T15:55:44.259] [INFO] monitorLogs - MQTT broker connected +[2024-10-25T15:55:49.200] [INFO] monitorLogs - buildTasks - params undefined +[2024-10-25T15:55:49.202] [INFO] monitorLogs - buildTasks: profile for line 1 +[2024-10-25T15:55:49.203] [INFO] monitorLogs - 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 +} +[2024-10-25T15:55:49.208] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-10-25T15:55:49.211] [INFO] monitorLogs - profileTimepoint: turn on line: 1 2024-10-26T11:00:00.209Z +[2024-10-25T15:55:49.213] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2024-10-25T15:55:49.215] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2024-10-25T15:55:49.216] [INFO] monitorLogs - buildTasks: profile for line 2 +[2024-10-25T15:55:49.217] [INFO] monitorLogs - 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 +} +[2024-10-25T15:55:49.220] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-10-25T15:55:49.221] [INFO] monitorLogs - profileTimepoint: turn on line: 2 2024-10-26T11:00:00.221Z +[2024-10-25T15:55:49.223] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2024-10-25T15:55:49.225] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2024-10-25T15:55:49.226] [INFO] monitorLogs - buildTasks: profile for line 3 +[2024-10-25T15:55:49.227] [INFO] monitorLogs - 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 +} +[2024-10-25T15:55:49.231] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-10-25T15:55:49.232] [INFO] monitorLogs - profileTimepoint: turn on line: 3 2024-10-26T11:00:00.232Z +[2024-10-25T15:55:49.234] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2024-10-25T15:55:49.235] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2024-10-25T15:55:49.242] [INFO] monitorLogs - tasks created: 315 +[2024-10-25T15:55:49.246] [INFO] monitorLogs - -->FLOW bol spustený d9x2V5LGYBzXp4mMRAOmKnkPloaqJwnQj6DgrNe3 2024-09-23 +[2024-10-25T15:55:49.555] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-25T15:55:49.598] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-25T15:55:49.640] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-25T15:58:24.661] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2024-10-25T15:58:25.066] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 true turn off on startup +[2024-10-25T15:58:25.082] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 true turn off on startup +[2024-10-25T15:58:25.088] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 true turn off on startup +[2024-10-25T15:58:25.212] [INFO] monitorLogs - MQTT broker connected +[2024-10-25T15:58:30.100] [INFO] monitorLogs - buildTasks - params undefined +[2024-10-25T15:58:30.101] [INFO] monitorLogs - buildTasks: profile for line 1 +[2024-10-25T15:58:30.102] [INFO] monitorLogs - 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 +} +[2024-10-25T15:58:30.105] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-10-25T15:58:30.107] [INFO] monitorLogs - profileTimepoint: turn on line: 1 2024-10-26T11:00:00.106Z +[2024-10-25T15:58:30.108] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2024-10-25T15:58:30.109] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2024-10-25T15:58:30.110] [INFO] monitorLogs - buildTasks: profile for line 2 +[2024-10-25T15:58:30.111] [INFO] monitorLogs - 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 +} +[2024-10-25T15:58:30.112] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-10-25T15:58:30.113] [INFO] monitorLogs - profileTimepoint: turn on line: 2 2024-10-26T11:00:00.113Z +[2024-10-25T15:58:30.114] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2024-10-25T15:58:30.115] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2024-10-25T15:58:30.116] [INFO] monitorLogs - buildTasks: profile for line 3 +[2024-10-25T15:58:30.117] [INFO] monitorLogs - 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 +} +[2024-10-25T15:58:30.118] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-10-25T15:58:30.119] [INFO] monitorLogs - profileTimepoint: turn on line: 3 2024-10-26T11:00:00.119Z +[2024-10-25T15:58:30.120] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2024-10-25T15:58:30.121] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2024-10-25T15:58:30.125] [INFO] monitorLogs - tasks created: 315 +[2024-10-25T15:58:30.128] [INFO] monitorLogs - -->FLOW bol spustený d9x2V5LGYBzXp4mMRAOmKnkPloaqJwnQj6DgrNe3 2024-09-23 +[2024-10-25T15:58:30.433] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-25T15:58:30.472] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-25T15:58:30.513] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-26T03:58:26.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-26 03:58:26 +[2024-10-26T13:00:00.145] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-26T13:00:00.180] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-26T13:00:00.215] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-27T03:58:28.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-27 03:58:28 +[2024-10-27T12:00:00.234] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-27T12:00:00.269] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-27T12:00:00.304] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-28T03:58:29.126] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-28 03:58:29 +[2024-10-28T12:00:00.315] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-28T12:00:00.350] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-28T12:00:00.384] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-28T12:49:23.097] [INFO] monitorLogs - MQTT broker connected +[2024-10-29T03:58:31.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-29 03:58:31 +[2024-10-29T12:00:00.507] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-29T12:00:00.542] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-29T12:00:00.575] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-30T03:58:32.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-30 03:58:32 +[2024-10-30T12:00:00.575] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-30T12:00:00.611] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-30T12:00:00.646] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-31T03:58:34.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-31 03:58:34 +[2024-10-31T12:00:00.613] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-31T12:00:00.648] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-31T12:00:00.683] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-01T03:58:36.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-01 03:58:36 +[2024-11-01T12:00:00.879] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-01T12:00:00.915] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-01T12:00:00.950] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-02T03:58:37.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-02 03:58:37 +[2024-11-02T12:00:01.083] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-02T12:00:01.119] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-02T12:00:01.153] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-03T03:58:39.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-03 03:58:39 +[2024-11-03T12:00:01.325] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-03T12:00:01.360] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-03T12:00:01.394] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-04T03:58:40.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-04 03:58:40 +[2024-11-04T12:00:01.344] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-04T12:00:01.379] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-04T12:00:01.413] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-04T14:12:54.156] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2024-11-04T14:12:54.511] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 true turn off on startup +[2024-11-04T14:12:54.528] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 true turn off on startup +[2024-11-04T14:12:54.534] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 true turn off on startup +[2024-11-04T14:12:54.623] [INFO] monitorLogs - MQTT broker connected +[2024-11-04T14:12:59.545] [INFO] monitorLogs - buildTasks - params undefined +[2024-11-04T14:12:59.547] [INFO] monitorLogs - buildTasks: profile for line 1 +[2024-11-04T14:12:59.548] [INFO] monitorLogs - 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 +} +[2024-11-04T14:12:59.550] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-04T14:12:59.552] [INFO] monitorLogs - profileTimepoint: turn on line: 1 2024-11-05T12:00:00.551Z +[2024-11-04T14:12:59.553] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2024-11-04T14:12:59.554] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2024-11-04T14:12:59.555] [INFO] monitorLogs - buildTasks: profile for line 2 +[2024-11-04T14:12:59.555] [INFO] monitorLogs - 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 +} +[2024-11-04T14:12:59.557] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-04T14:12:59.558] [INFO] monitorLogs - profileTimepoint: turn on line: 2 2024-11-05T12:00:00.557Z +[2024-11-04T14:12:59.559] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2024-11-04T14:12:59.560] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2024-11-04T14:12:59.560] [INFO] monitorLogs - buildTasks: profile for line 3 +[2024-11-04T14:12:59.561] [INFO] monitorLogs - 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 +} +[2024-11-04T14:12:59.562] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-04T14:12:59.563] [INFO] monitorLogs - profileTimepoint: turn on line: 3 2024-11-05T12:00:00.563Z +[2024-11-04T14:12:59.564] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2024-11-04T14:12:59.565] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2024-11-04T14:12:59.569] [INFO] monitorLogs - tasks created: 315 +[2024-11-04T14:12:59.572] [INFO] monitorLogs - -->FLOW bol spustený d9x2V5LGYBzXp4mMRAOmKnkPloaqJwnQj6DgrNe3 2024-09-23 +[2024-11-04T14:12:59.879] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-04T14:12:59.920] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-04T14:12:59.963] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-05T03:12:56.018] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-05 03:12:56 +[2024-11-05T07:20:49.060] [INFO] monitorLogs - MQTT broker connected +[2024-11-05T08:06:40.988] [INFO] monitorLogs - MQTT broker connected +[2024-11-05T08:30:51.526] [INFO] monitorLogs - MQTT broker connected +[2024-11-05T13:00:00.761] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-05T13:00:00.797] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-05T13:00:00.832] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-05T22:56:11.005] [INFO] monitorLogs - MQTT broker connected +[2024-11-06T03:12:58.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-06 03:12:58 +[2024-11-06T13:00:01.091] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-06T13:00:01.129] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-06T13:00:01.165] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-06T14:59:30.074] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2024-11-06T14:59:30.487] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 true turn off on startup +[2024-11-06T14:59:30.503] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 true turn off on startup +[2024-11-06T14:59:30.508] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 true turn off on startup +[2024-11-06T14:59:31.989] [INFO] monitorLogs - MQTT broker connected +[2024-11-06T14:59:35.520] [INFO] monitorLogs - buildTasks - params undefined +[2024-11-06T14:59:35.522] [INFO] monitorLogs - buildTasks: profile for line 1 +[2024-11-06T14:59:35.523] [INFO] monitorLogs - 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 +} +[2024-11-06T14:59:35.526] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-06T14:59:35.528] [INFO] monitorLogs - profileTimepoint: turn on line: 1 2024-11-07T12:00:00.527Z +[2024-11-06T14:59:35.530] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2024-11-06T14:59:35.531] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2024-11-06T14:59:35.532] [INFO] monitorLogs - buildTasks: profile for line 2 +[2024-11-06T14:59:35.533] [INFO] monitorLogs - 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 +} +[2024-11-06T14:59:35.534] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-06T14:59:35.535] [INFO] monitorLogs - profileTimepoint: turn on line: 2 2024-11-07T12:00:00.535Z +[2024-11-06T14:59:35.536] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2024-11-06T14:59:35.537] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2024-11-06T14:59:35.538] [INFO] monitorLogs - buildTasks: profile for line 3 +[2024-11-06T14:59:35.538] [INFO] monitorLogs - 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 +} +[2024-11-06T14:59:35.540] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-06T14:59:35.541] [INFO] monitorLogs - profileTimepoint: turn on line: 3 2024-11-07T12:00:00.540Z +[2024-11-06T14:59:35.541] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2024-11-06T14:59:35.542] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2024-11-06T14:59:35.545] [INFO] monitorLogs - tasks created: 315 +[2024-11-06T14:59:35.548] [INFO] monitorLogs - -->FLOW bol spustený d9x2V5LGYBzXp4mMRAOmKnkPloaqJwnQj6DgrNe3 2024-09-23 +[2024-11-06T14:59:35.855] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-06T14:59:35.894] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-06T14:59:35.935] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-07T01:40:51.178] [INFO] monitorLogs - MQTT broker connected +[2024-11-07T03:59:30.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-07 03:59:30 +[2024-11-07T13:00:00.689] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-07T13:00:00.724] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-07T13:00:00.760] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-08T03:59:32.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-08 03:59:32 +[2024-11-08T13:00:00.714] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-08T13:00:00.751] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-08T13:00:00.785] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-09T03:59:33.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-09 03:59:33 +[2024-11-09T13:00:00.762] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-09T13:00:00.798] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-09T13:00:00.833] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-10T03:59:35.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-10 03:59:35 +[2024-11-10T13:00:00.837] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-10T13:00:00.873] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-10T13:00:00.908] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-10T15:02:16.205] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2024-11-10T15:02:21.591] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 true turn off on startup +[2024-11-10T15:02:21.593] [INFO] monitorLogs - turnLine: off pin (relay) relay1_02 +[2024-11-10T15:02:21.606] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 true turn off on startup +[2024-11-10T15:02:21.606] [INFO] monitorLogs - turnLine: off pin (relay) relay1_03 +[2024-11-10T15:02:21.612] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 true turn off on startup +[2024-11-10T15:02:21.613] [INFO] monitorLogs - turnLine: off pin (relay) relay1_04 +[2024-11-10T15:02:21.701] [INFO] monitorLogs - MQTT client connected +[2024-11-10T15:02:26.624] [INFO] monitorLogs - buildTasks - params undefined +[2024-11-10T15:02:26.626] [INFO] monitorLogs - buildTasks: profile for line 1 +[2024-11-10T15:02:26.627] [INFO] monitorLogs - 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 +} +[2024-11-10T15:02:26.630] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-10T15:02:26.631] [INFO] monitorLogs - profileTimepoint: turn on line: 1 2024-11-11T12:00:00.630Z +[2024-11-10T15:02:26.632] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2024-11-10T15:02:26.633] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2024-11-10T15:02:26.634] [INFO] monitorLogs - buildTasks: profile for line 2 +[2024-11-10T15:02:26.635] [INFO] monitorLogs - 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 +} +[2024-11-10T15:02:26.636] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-10T15:02:26.637] [INFO] monitorLogs - profileTimepoint: turn on line: 2 2024-11-11T12:00:00.637Z +[2024-11-10T15:02:26.638] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2024-11-10T15:02:26.639] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2024-11-10T15:02:26.640] [INFO] monitorLogs - buildTasks: profile for line 3 +[2024-11-10T15:02:26.640] [INFO] monitorLogs - 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 +} +[2024-11-10T15:02:26.642] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-10T15:02:26.642] [INFO] monitorLogs - profileTimepoint: turn on line: 3 2024-11-11T12:00:00.642Z +[2024-11-10T15:02:26.643] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2024-11-10T15:02:26.644] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2024-11-10T15:02:26.647] [INFO] monitorLogs - tasks created: 315 +[2024-11-10T15:02:26.650] [INFO] monitorLogs - -->FLOW bol spustený d9x2V5LGYBzXp4mMRAOmKnkPloaqJwnQj6DgrNe3 2024-11-04 +[2024-11-10T15:02:26.956] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-10T15:02:26.956] [INFO] monitorLogs - turnLine: on pin (relay) relay1_02 +[2024-11-10T15:02:26.998] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-10T15:02:26.999] [INFO] monitorLogs - turnLine: on pin (relay) relay1_03 +[2024-11-10T15:02:27.042] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-10T15:02:27.043] [INFO] monitorLogs - turnLine: on pin (relay) relay1_04 +[2024-11-11T03:02:24.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-11 03:02:24 +[2024-11-11T13:00:00.872] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-11T13:00:00.909] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-11T13:00:00.944] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-11T23:08:47.886] [INFO] monitorLogs - MQTT client connected +[2024-11-12T03:02:25.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-12 03:02:25 +[2024-11-12T13:00:01.438] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-12T13:00:01.474] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-12T13:00:01.509] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-13T03:02:27.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-13 03:02:27 +[2024-11-13T10:22:13.952] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2024-11-13T10:22:19.270] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 true turn off on startup +[2024-11-13T10:22:19.283] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 true turn off on startup +[2024-11-13T10:22:19.289] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 true turn off on startup +[2024-11-13T10:22:20.309] [INFO] monitorLogs - MQTT client connected +[2024-11-13T10:22:24.299] [INFO] monitorLogs - buildTasks - params undefined +[2024-11-13T10:22:24.301] [INFO] monitorLogs - buildTasks: profile for line 1 +[2024-11-13T10:22:24.302] [INFO] monitorLogs - 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 +} +[2024-11-13T10:22:24.305] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-13T10:22:24.306] [INFO] monitorLogs - profileTimepoint: turn on line: 1 2024-11-13T12:00:00.306Z +[2024-11-13T10:22:24.308] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2024-11-13T10:22:24.309] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2024-11-13T10:22:24.310] [INFO] monitorLogs - buildTasks: profile for line 2 +[2024-11-13T10:22:24.311] [INFO] monitorLogs - 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 +} +[2024-11-13T10:22:24.312] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-13T10:22:24.313] [INFO] monitorLogs - profileTimepoint: turn on line: 2 2024-11-13T12:00:00.313Z +[2024-11-13T10:22:24.314] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2024-11-13T10:22:24.315] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2024-11-13T10:22:24.316] [INFO] monitorLogs - buildTasks: profile for line 3 +[2024-11-13T10:22:24.316] [INFO] monitorLogs - 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 +} +[2024-11-13T10:22:24.318] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-13T10:22:24.318] [INFO] monitorLogs - profileTimepoint: turn on line: 3 2024-11-13T12:00:00.318Z +[2024-11-13T10:22:24.319] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2024-11-13T10:22:24.320] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2024-11-13T10:22:24.323] [INFO] monitorLogs - tasks created: 315 +[2024-11-13T10:22:24.329] [INFO] monitorLogs - -->FLOW bol spustený d9x2V5LGYBzXp4mMRAOmKnkPloaqJwnQj6DgrNe3 2024-11-04 +[2024-11-13T10:22:24.632] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-13T10:22:24.672] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-13T10:22:24.714] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-14T03:22:21.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-14 03:22:21 +[2024-11-15T03:22:23.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-15 03:22:23 +[2024-11-16T03:22:24.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-16 03:22:24 +[2024-11-17T03:22:26.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-17 03:22:26 +[2024-11-18T03:22:27.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-18 03:22:27 +[2024-11-19T03:22:29.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-19 03:22:29 +[2024-11-20T03:22:36.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-20 03:22:36 +[2024-11-21T03:22:32.013] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-21 03:22:32 +[2024-11-21T12:45:01.837] [INFO] monitorLogs - MQTT client connected +[2024-11-22T03:22:34.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-22 03:22:34 +[2024-11-23T03:22:35.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-23 03:22:35 +[2024-11-23T03:27:09.910] [INFO] monitorLogs - MQTT client error Error: Connection refused: Server unavailable + at MqttClient._handleConnack (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:1388:17) + at MqttClient._handlePacket (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:549:12) + at work (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:438:12) + at Writable.writable._write (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:452:5) + at doWrite (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:409:139) + at writeOrBuffer (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:398:5) + at Writable.write (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:307:11) + at Socket.ondata (internal/streams/readable.js:731:22) + at Socket.emit (events.js:400:28) + at addChunk (internal/streams/readable.js:293:12) { + code: 3 +} +[2024-11-23T03:27:12.035] [INFO] monitorLogs - MQTT client connected +[2024-11-23T21:13:56.209] [INFO] monitorLogs - MQTT client error Error: Connection refused: Server unavailable + at MqttClient._handleConnack (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:1388:17) + at MqttClient._handlePacket (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:549:12) + at work (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:438:12) + at Writable.writable._write (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:452:5) + at doWrite (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:409:139) + at writeOrBuffer (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:398:5) + at Writable.write (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:307:11) + at Socket.ondata (internal/streams/readable.js:731:22) + at Socket.emit (events.js:400:28) + at addChunk (internal/streams/readable.js:293:12) { + code: 3 +} +[2024-11-23T21:13:58.774] [INFO] monitorLogs - MQTT client connected +[2024-11-23T21:14:43.566] [INFO] monitorLogs - MQTT client connected +[2024-11-23T21:23:46.277] [INFO] monitorLogs - MQTT client connected +[2024-11-24T03:22:36.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-24 03:22:36 +[2024-11-25T03:22:38.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-25 03:22:38 +[2024-11-25T08:40:58.891] [INFO] monitorLogs - MQTT client connected +[2024-11-26T03:22:39.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-26 03:22:39 +[2024-11-27T03:22:41.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-27 03:22:41 +[2024-11-29T03:22:44.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-29 03:22:44 +[2024-11-30T03:22:45.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-30 03:22:45 +[2024-11-30T15:43:31.554] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2024-11-30T15:43:36.876] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 true turn off on startup +[2024-11-30T15:43:36.889] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 true turn off on startup +[2024-11-30T15:43:36.894] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 true turn off on startup +[2024-11-30T15:43:37.002] [INFO] monitorLogs - MQTT client connected +[2024-11-30T15:43:41.906] [INFO] monitorLogs - buildTasks - params undefined +[2024-11-30T15:43:41.907] [INFO] monitorLogs - buildTasks: profile for line 1 +[2024-11-30T15:43:41.908] [INFO] monitorLogs - 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 +} +[2024-11-30T15:43:41.911] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-30T15:43:41.913] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2024-12-01T12:00:00.912Z +[2024-11-30T15:43:41.914] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2024-11-30T15:43:41.916] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2024-11-30T15:43:41.916] [INFO] monitorLogs - buildTasks: profile for line 2 +[2024-11-30T15:43:41.917] [INFO] monitorLogs - 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 +} +[2024-11-30T15:43:41.918] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-30T15:43:41.919] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2024-12-01T12:00:00.919Z +[2024-11-30T15:43:41.920] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2024-11-30T15:43:41.921] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2024-11-30T15:43:41.922] [INFO] monitorLogs - buildTasks: profile for line 3 +[2024-11-30T15:43:41.922] [INFO] monitorLogs - 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 +} +[2024-11-30T15:43:41.924] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-30T15:43:41.924] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2024-12-01T12:00:00.924Z +[2024-11-30T15:43:41.925] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2024-11-30T15:43:41.926] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2024-11-30T15:43:41.929] [INFO] monitorLogs - tasks created: 315 +[2024-11-30T15:43:41.932] [INFO] monitorLogs - -->FLOW bol spustený d9x2V5LGYBzXp4mMRAOmKnkPloaqJwnQj6DgrNe3 2024-11-04 +[2024-11-30T15:43:42.236] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-30T15:43:42.282] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-30T15:43:42.325] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-01T03:43:39.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-01 03:43:39 +[2024-12-02T03:43:40.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-02 03:43:40 +[2024-12-03T03:43:42.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-03 03:43:42 +[2024-12-04T00:19:10.575] [INFO] monitorLogs - MQTT client connected +[2024-12-04T03:43:43.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-04 03:43:43 +[2024-12-05T03:43:45.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-05 03:43:45 +[2024-12-05T14:18:01.970] [INFO] monitorLogs - MQTT client connected +[2024-12-06T03:43:46.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-06 03:43:46 +[2024-12-07T03:43:48.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-07 03:43:48 +[2024-12-08T03:43:49.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-08 03:43:49 +[2024-12-09T03:43:51.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-09 03:43:51 +[2024-12-09T09:15:41.653] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-09T09:15:42.674] [INFO] monitorLogs - websocket error, reconnect +[2024-12-09T09:15:42.676] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-09T09:20:26.096] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2024-12-09T09:20:31.442] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 true turn off on startup +[2024-12-09T09:20:31.455] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 true turn off on startup +[2024-12-09T09:20:31.460] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 true turn off on startup +[2024-12-09T09:20:31.621] [INFO] monitorLogs - MQTT client connected +[2024-12-09T09:20:36.471] [INFO] monitorLogs - buildTasks - params undefined +[2024-12-09T09:20:36.473] [INFO] monitorLogs - buildTasks: profile for line 1 +[2024-12-09T09:20:36.474] [INFO] monitorLogs - 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 +} +[2024-12-09T09:20:36.477] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-12-09T09:20:36.478] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2024-12-09T12:00:00.477Z +[2024-12-09T09:20:36.479] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2024-12-09T09:20:36.480] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2024-12-09T09:20:36.481] [INFO] monitorLogs - buildTasks: profile for line 2 +[2024-12-09T09:20:36.482] [INFO] monitorLogs - 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 +} +[2024-12-09T09:20:36.483] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-12-09T09:20:36.484] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2024-12-09T12:00:00.484Z +[2024-12-09T09:20:36.485] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2024-12-09T09:20:36.486] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2024-12-09T09:20:36.487] [INFO] monitorLogs - buildTasks: profile for line 3 +[2024-12-09T09:20:36.487] [INFO] monitorLogs - 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 +} +[2024-12-09T09:20:36.488] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-12-09T09:20:36.489] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2024-12-09T12:00:00.489Z +[2024-12-09T09:20:36.490] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2024-12-09T09:20:36.491] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2024-12-09T09:20:36.494] [INFO] monitorLogs - tasks created: 315 +[2024-12-09T09:20:36.498] [INFO] monitorLogs - -->FLOW bol spustený d9x2V5LGYBzXp4mMRAOmKnkPloaqJwnQj6DgrNe3 2024-11-04 +[2024-12-09T09:20:36.802] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-09T09:20:36.844] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-09T09:20:36.886] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-10T03:20:33.013] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-10 03:20:33 +[2024-12-10T06:40:53.654] [INFO] monitorLogs - MQTT client connected +[2024-12-11T03:20:34.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-11 03:20:34 +[2024-12-12T03:20:35.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-12 03:20:35 +[2024-12-13T03:20:37.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-13 03:20:37 +[2024-12-14T03:20:38.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-14 03:20:38 +[2024-12-15T03:20:40.016] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-15 03:20:40 +[2024-12-16T03:20:41.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-16 03:20:41 +[2024-12-17T03:20:43.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-17 03:20:43 +[2024-12-18T03:20:44.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-18 03:20:44 +[2024-12-19T03:20:48.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-19 03:20:48 +[2024-12-20T03:20:48.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-20 03:20:48 +[2024-12-21T03:20:49.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-21 03:20:49 +[2024-12-22T03:20:50.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-22 03:20:50 +[2024-12-23T03:20:52.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-23 03:20:52 +[2024-12-24T03:20:53.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-24 03:20:53 +[2024-12-25T03:20:54.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-25 03:20:54 +[2024-12-26T03:20:56.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-26 03:20:56 +[2024-12-27T03:20:57.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-27 03:20:57 +[2024-12-28T03:20:58.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-28 03:20:58 +[2024-12-29T03:21:00.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-29 03:21:00 +[2024-12-30T03:21:01.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-30 03:21:01 +[2024-12-31T03:21:02.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-31 03:21:02 +[2025-01-01T03:21:04.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-01 03:21:04 +[2025-01-02T03:21:05.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-02 03:21:05 +[2025-01-02T08:47:38.961] [INFO] monitorLogs - MQTT client error Error: connect ECONNREFUSED 192.168.252.1:1883 + at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1159:16) { + errno: -111, + code: 'ECONNREFUSED', + syscall: 'connect', + address: '192.168.252.1', + port: 1883 +} +[2025-01-02T11:44:41.048] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-01-02T11:44:46.394] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 true turn off on startup +[2025-01-02T11:44:46.408] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 true turn off on startup +[2025-01-02T11:44:46.414] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 true turn off on startup +[2025-01-02T11:44:46.493] [INFO] monitorLogs - MQTT client error Error: connect ECONNREFUSED 192.168.252.1:1883 + at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1159:16) { + errno: -111, + code: 'ECONNREFUSED', + syscall: 'connect', + address: '192.168.252.1', + port: 1883 +} +[2025-01-02T11:44:51.425] [INFO] monitorLogs - buildTasks - params undefined +[2025-01-02T11:44:51.427] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-01-02T11:44:51.428] [INFO] monitorLogs - 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 +} +[2025-01-02T11:44:51.431] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-02T11:44:51.432] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-01-02T12:00:00.432Z +[2025-01-02T11:44:51.433] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-01-02T11:44:51.435] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-01-02T11:44:51.436] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-01-02T11:44:51.437] [INFO] monitorLogs - 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 +} +[2025-01-02T11:44:51.439] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-02T11:44:51.439] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-01-02T12:00:00.439Z +[2025-01-02T11:44:51.440] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-01-02T11:44:51.441] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-01-02T11:44:51.442] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-01-02T11:44:51.443] [INFO] monitorLogs - 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 +} +[2025-01-02T11:44:51.444] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-02T11:44:51.445] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-01-02T12:00:00.444Z +[2025-01-02T11:44:51.445] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-01-02T11:44:51.446] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-01-02T11:44:51.450] [INFO] monitorLogs - tasks created: 315 +[2025-01-02T11:44:51.452] [INFO] monitorLogs - -->FLOW bol spustený d9x2V5LGYBzXp4mMRAOmKnkPloaqJwnQj6DgrNe3 2025-01-02 +[2025-01-02T11:44:51.758] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-02T11:44:51.797] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-02T11:44:51.838] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-03T03:44:48.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-03 03:44:48 +[2025-01-03T10:12:23.609] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-01-03T10:12:28.953] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 true turn off on startup +[2025-01-03T10:12:28.967] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 true turn off on startup +[2025-01-03T10:12:28.974] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 true turn off on startup +[2025-01-03T10:12:29.025] [INFO] monitorLogs - MQTT client error Error: connect ECONNREFUSED 192.168.252.1:1883 + at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1159:16) { + errno: -111, + code: 'ECONNREFUSED', + syscall: 'connect', + address: '192.168.252.1', + port: 1883 +} +[2025-01-03T10:12:33.985] [INFO] monitorLogs - buildTasks - params undefined +[2025-01-03T10:12:33.987] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-01-03T10:12:33.987] [INFO] monitorLogs - 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 +} +[2025-01-03T10:12:33.990] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-03T10:12:33.991] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-01-03T12:00:00.991Z +[2025-01-03T10:12:33.992] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-01-03T10:12:33.993] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-01-03T10:12:33.994] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-01-03T10:12:33.997] [INFO] monitorLogs - 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 +} +[2025-01-03T10:12:33.999] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-03T10:12:34.000] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-01-03T12:00:00.000Z +[2025-01-03T10:12:34.001] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-01-03T10:12:34.002] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-01-03T10:12:34.002] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-01-03T10:12:34.003] [INFO] monitorLogs - 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 +} +[2025-01-03T10:12:34.005] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-03T10:12:34.005] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-01-03T12:00:00.005Z +[2025-01-03T10:12:34.006] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-01-03T10:12:34.007] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-01-03T10:12:34.010] [INFO] monitorLogs - tasks created: 315 +[2025-01-03T10:12:34.013] [INFO] monitorLogs - -->FLOW bol spustený d9x2V5LGYBzXp4mMRAOmKnkPloaqJwnQj6DgrNe3 2025-01-02 +[2025-01-03T10:12:34.317] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-03T10:12:34.358] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-03T10:12:34.400] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-04T03:12:30.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-04 03:12:30 +[2025-01-05T03:12:32.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-05 03:12:32 +[2025-01-06T03:12:33.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-06 03:12:33 +[2025-01-07T03:12:35.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-07 03:12:35 +[2025-01-08T03:12:36.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-08 03:12:36 +[2025-01-09T03:12:38.014] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-09 03:12:38 +[2025-01-09T15:21:30.312] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-01-09T15:21:35.647] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 true turn off on startup +[2025-01-09T15:21:35.661] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 true turn off on startup +[2025-01-09T15:21:35.667] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 true turn off on startup +[2025-01-09T15:21:35.682] [INFO] monitorLogs - MQTT client error Error: connect ECONNREFUSED 192.168.252.1:1883 + at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1159:16) { + errno: -111, + code: 'ECONNREFUSED', + syscall: 'connect', + address: '192.168.252.1', + port: 1883 +} +[2025-01-09T15:21:40.679] [INFO] monitorLogs - buildTasks - params undefined +[2025-01-09T15:21:40.681] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-01-09T15:21:40.682] [INFO] monitorLogs - 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 +} +[2025-01-09T15:21:40.685] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-09T15:21:40.686] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-01-10T12:00:00.685Z +[2025-01-09T15:21:40.687] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-01-09T15:21:40.688] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-01-09T15:21:40.689] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-01-09T15:21:40.690] [INFO] monitorLogs - 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 +} +[2025-01-09T15:21:40.691] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-09T15:21:40.692] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-01-10T12:00:00.692Z +[2025-01-09T15:21:40.693] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-01-09T15:21:40.694] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-01-09T15:21:40.695] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-01-09T15:21:40.695] [INFO] monitorLogs - 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 +} +[2025-01-09T15:21:40.697] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-09T15:21:40.697] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-01-10T12:00:00.697Z +[2025-01-09T15:21:40.698] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-01-09T15:21:40.699] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-01-09T15:21:40.702] [INFO] monitorLogs - tasks created: 315 +[2025-01-09T15:21:40.705] [INFO] monitorLogs - -->FLOW bol spustený d9x2V5LGYBzXp4mMRAOmKnkPloaqJwnQj6DgrNe3 2025-01-02 +[2025-01-09T15:21:41.010] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-09T15:21:41.051] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-09T15:21:41.091] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-10T03:21:37.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-10 03:21:37 +[2025-01-10T14:34:02.018] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-01-10T14:34:07.372] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 true turn off on startup +[2025-01-10T14:34:07.385] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 true turn off on startup +[2025-01-10T14:34:07.392] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 true turn off on startup +[2025-01-10T14:34:08.608] [INFO] monitorLogs - MQTT client error Error: connect ECONNREFUSED 192.168.252.1:1883 + at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1159:16) { + errno: -111, + code: 'ECONNREFUSED', + syscall: 'connect', + address: '192.168.252.1', + port: 1883 +} +[2025-01-10T14:34:12.402] [INFO] monitorLogs - buildTasks - params undefined +[2025-01-10T14:34:12.404] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-01-10T14:34:12.405] [INFO] monitorLogs - 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 +} +[2025-01-10T14:34:12.408] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-10T14:34:12.409] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-01-11T12:00:00.408Z +[2025-01-10T14:34:12.410] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-01-10T14:34:12.411] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-01-10T14:34:12.412] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-01-10T14:34:12.412] [INFO] monitorLogs - 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 +} +[2025-01-10T14:34:12.414] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-10T14:34:12.415] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-01-11T12:00:00.414Z +[2025-01-10T14:34:12.416] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-01-10T14:34:12.417] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-01-10T14:34:12.417] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-01-10T14:34:12.418] [INFO] monitorLogs - 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 +} +[2025-01-10T14:34:12.419] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-10T14:34:12.420] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-01-11T12:00:00.420Z +[2025-01-10T14:34:12.420] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-01-10T14:34:12.421] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-01-10T14:34:12.424] [INFO] monitorLogs - tasks created: 315 +[2025-01-10T14:34:12.431] [INFO] monitorLogs - -->FLOW bol spustený d9x2V5LGYBzXp4mMRAOmKnkPloaqJwnQj6DgrNe3 2025-01-09 +[2025-01-10T14:34:12.733] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-10T14:34:12.772] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-10T14:34:12.812] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-10T15:58:14.593] [INFO] monitorLogs - MQTT client connected +[2025-01-10T17:20:17.138] [INFO] monitorLogs - websocket onclose, reconnect +[2025-01-10T17:20:19.248] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 true turn off on startup +[2025-01-10T17:20:19.262] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 true turn off on startup +[2025-01-10T17:20:19.269] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 true turn off on startup +[2025-01-10T17:24:05.019] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-01-10T17:24:10.370] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 true turn off on startup +[2025-01-10T17:24:10.383] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 true turn off on startup +[2025-01-10T17:24:10.389] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 true turn off on startup +[2025-01-10T17:24:10.630] [INFO] monitorLogs - MQTT client connected +[2025-01-10T17:24:15.400] [INFO] monitorLogs - buildTasks - params undefined +[2025-01-10T17:24:15.402] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-01-10T17:24:15.403] [INFO] monitorLogs - 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 +} +[2025-01-10T17:24:15.406] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-10T17:24:15.407] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-01-11T12:00:00.406Z +[2025-01-10T17:24:15.408] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-01-10T17:24:15.410] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-01-10T17:24:15.410] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-01-10T17:24:15.411] [INFO] monitorLogs - 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 +} +[2025-01-10T17:24:15.413] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-10T17:24:15.414] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-01-11T12:00:00.413Z +[2025-01-10T17:24:15.415] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-01-10T17:24:15.416] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-01-10T17:24:15.416] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-01-10T17:24:15.417] [INFO] monitorLogs - 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 +} +[2025-01-10T17:24:15.418] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-10T17:24:15.419] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-01-11T12:00:00.419Z +[2025-01-10T17:24:15.420] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-01-10T17:24:15.421] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-01-10T17:24:15.424] [INFO] monitorLogs - tasks created: 315 +[2025-01-10T17:24:15.427] [INFO] monitorLogs - -->FLOW bol spustený d9x2V5LGYBzXp4mMRAOmKnkPloaqJwnQj6DgrNe3 2025-01-09 +[2025-01-10T17:24:15.733] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-10T17:24:15.775] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-10T17:24:15.815] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-11T03:24:12.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-11 03:24:12 +[2025-01-12T03:24:13.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-12 03:24:13 +[2025-01-13T03:24:15.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-13 03:24:15 +[2025-01-14T03:24:16.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-14 03:24:16 +[2025-01-14T07:53:22.912] [INFO] monitorLogs - MQTT client connected +[2025-01-15T03:24:17.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-15 03:24:17 +[2025-01-16T03:24:19.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-16 03:24:19 +[2025-01-17T03:24:20.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-17 03:24:20 +[2025-01-18T03:24:22.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-18 03:24:22 +[2025-01-19T03:24:23.013] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-19 03:24:23 +[2025-01-20T01:33:57.332] [INFO] monitorLogs - MQTT client connected +[2025-01-20T03:24:25.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-20 03:24:25 +[2025-01-21T03:24:26.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-21 03:24:26 +[2025-01-21T06:23:47.480] [INFO] monitorLogs - MQTT client connected +[2025-01-22T03:24:27.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-22 03:24:27 +[2025-01-22T13:29:52.980] [INFO] monitorLogs - MQTT client connected +[2025-01-22T13:30:33.301] [INFO] monitorLogs - MQTT client connected +[2025-01-22T13:31:22.282] [INFO] monitorLogs - MQTT client connected +[2025-01-23T03:24:28.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-23 03:24:28 +[2025-01-24T03:24:30.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-24 03:24:30 +[2025-01-25T03:24:31.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-25 03:24:31 +[2025-01-26T03:24:33.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-26 03:24:33 +[2025-01-27T03:24:34.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-27 03:24:34 +[2025-01-28T03:24:36.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-28 03:24:36 +[2025-01-29T03:24:37.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-29 03:24:37 +[2025-01-30T03:24:39.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-30 03:24:39 +[2025-01-31T03:24:40.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-31 03:24:40 +[2025-02-01T03:24:42.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-01 03:24:42 +[2025-02-02T03:24:43.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-02 03:24:43 +[2025-02-03T03:24:45.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-03 03:24:45 +[2025-02-03T07:03:46.157] [INFO] monitorLogs - MQTT client connected +[2025-02-03T07:04:21.638] [INFO] monitorLogs - MQTT client connected +[2025-02-03T10:36:14.249] [INFO] monitorLogs - MQTT client connected +[2025-02-04T03:24:46.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-04 03:24:46 +[2025-02-05T03:24:47.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-05 03:24:47 +[2025-02-06T03:24:49.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-06 03:24:49 +[2025-02-07T03:24:50.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-07 03:24:50 +[2025-02-07T08:39:58.720] [INFO] monitorLogs - MQTT client connected +[2025-02-07T08:40:25.518] [INFO] monitorLogs - MQTT client connected +[2025-02-07T08:42:37.623] [INFO] monitorLogs - MQTT client connected +[2025-02-08T02:40:33.626] [INFO] monitorLogs - MQTT client connected +[2025-02-08T03:24:52.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-08 03:24:52 +[2025-02-09T03:24:53.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-09 03:24:53 +[2025-02-09T13:14:45.055] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-02-09T13:14:50.400] [INFO] monitorLogs - buildTasks - params undefined +[2025-02-09T13:14:50.404] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-02-09T13:14:50.406] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-02-09T13:14:50.406] [INFO] monitorLogs - 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 +} +[2025-02-09T13:14:50.409] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-02-09T13:14:50.411] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-02-10T12:00:00.410Z +[2025-02-09T13:14:50.412] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-02-09T13:14:50.413] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-02-09T13:14:50.414] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-02-09T13:14:50.414] [INFO] monitorLogs - 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 +} +[2025-02-09T13:14:50.416] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-02-09T13:14:50.417] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-02-10T12:00:00.416Z +[2025-02-09T13:14:50.417] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-02-09T13:14:50.419] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-02-09T13:14:50.419] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-02-09T13:14:50.420] [INFO] monitorLogs - 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 +} +[2025-02-09T13:14:50.421] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-02-09T13:14:50.422] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-02-10T12:00:00.422Z +[2025-02-09T13:14:50.423] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-02-09T13:14:50.423] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-02-09T13:14:50.426] [INFO] monitorLogs - tasks created: 296 +[2025-02-09T13:14:50.428] [INFO] monitorLogs - -->FLOW bol spustený d9x2V5LGYBzXp4mMRAOmKnkPloaqJwnQj6DgrNe3 2025-01-30 +[2025-02-09T13:14:50.584] [INFO] monitorLogs - MQTT client connected +[2025-02-09T13:14:50.734] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-02-09T13:14:51.037] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-02-09T13:14:51.340] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-02-10T03:14:52.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-10 03:14:52 +[2025-02-11T03:14:54.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-11 03:14:54 +[2025-02-12T03:14:55.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-12 03:14:55 +[2025-02-12T11:26:47.611] [INFO] monitorLogs - MQTT client connected +[2025-02-13T03:14:56.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-13 03:14:56 +[2025-02-13T13:18:00.412] [INFO] monitorLogs - MQTT client connected +[2025-02-13T13:19:56.167] [INFO] monitorLogs - MQTT client connected +[2025-02-13T13:22:57.808] [INFO] monitorLogs - MQTT client connected +[2025-02-13T13:26:20.496] [INFO] monitorLogs - MQTT client connected +[2025-02-13T13:28:26.949] [INFO] monitorLogs - MQTT client connected +[2025-02-13T13:31:17.767] [INFO] monitorLogs - MQTT client connected +[2025-02-13T15:23:10.670] [INFO] monitorLogs - MQTT client connected +[2025-02-14T03:14:58.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-14 03:14:58 +[2025-02-15T03:14:59.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-15 03:14:59 +[2025-02-16T03:15:00.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-16 03:15:00 +[2025-02-17T03:15:02.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-17 03:15:02 +[2025-02-17T07:03:49.982] [INFO] monitorLogs - MQTT client connected +[2025-02-17T08:04:10.401] [INFO] monitorLogs - MQTT client connected +[2025-02-17T08:05:59.558] [INFO] monitorLogs - MQTT client connected +[2025-02-17T08:56:42.033] [INFO] monitorLogs - MQTT client connected +[2025-02-18T03:15:03.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-18 03:15:03 +[2025-02-19T03:15:04.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-19 03:15:04 +[2025-02-19T14:18:29.456] [INFO] monitorLogs - MQTT client connected +[2025-02-19T15:06:42.414] [INFO] monitorLogs - MQTT client connected +[2025-02-19T15:09:56.796] [INFO] monitorLogs - MQTT client connected +[2025-02-19T15:12:58.981] [INFO] monitorLogs - MQTT client connected +[2025-02-20T03:15:06.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-20 03:15:06 +[2025-02-21T03:15:07.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-21 03:15:07 +[2025-02-22T03:15:08.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-22 03:15:08 +[2025-02-23T03:15:10.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-23 03:15:10 +[2025-02-24T03:15:11.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-24 03:15:11 +[2025-02-24T09:09:24.953] [INFO] monitorLogs - MQTT client connected +[2025-02-24T12:48:08.049] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-02-24T12:48:13.405] [INFO] monitorLogs - buildTasks - params undefined +[2025-02-24T12:48:13.409] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-02-24T12:48:13.411] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-02-24T12:48:13.411] [INFO] monitorLogs - 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 +} +[2025-02-24T12:48:13.414] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-02-24T12:48:13.415] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-02-24T12:00:00.415Z +[2025-02-24T12:48:13.417] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-02-24T12:48:13.418] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-02-24T12:48:13.418] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-02-24T12:48:13.419] [INFO] monitorLogs - 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 +} +[2025-02-24T12:48:13.421] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-02-24T12:48:13.421] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-02-24T12:00:00.421Z +[2025-02-24T12:48:13.422] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-02-24T12:48:13.423] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-02-24T12:48:13.424] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-02-24T12:48:13.424] [INFO] monitorLogs - 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 +} +[2025-02-24T12:48:13.426] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-02-24T12:48:13.426] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-02-24T12:00:00.426Z +[2025-02-24T12:48:13.427] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-02-24T12:48:13.428] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-02-24T12:48:13.431] [INFO] monitorLogs - tasks created: 296 +[2025-02-24T12:48:13.434] [INFO] monitorLogs - -->FLOW bol spustený d9x2V5LGYBzXp4mMRAOmKnkPloaqJwnQj6DgrNe3 2025-01-30 +[2025-02-24T12:48:13.739] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-02-24T12:48:13.784] [INFO] monitorLogs - MQTT client connected +[2025-02-24T12:48:14.042] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-02-24T12:48:14.345] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-02-24T12:49:41.087] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-02-24T12:49:46.427] [INFO] monitorLogs - buildTasks - params undefined +[2025-02-24T12:49:46.432] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-02-24T12:49:46.433] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-02-24T12:49:46.434] [INFO] monitorLogs - 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 +} +[2025-02-24T12:49:46.437] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-02-24T12:49:46.438] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-02-24T12:00:00.437Z +[2025-02-24T12:49:46.439] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-02-24T12:49:46.441] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-02-24T12:49:46.441] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-02-24T12:49:46.442] [INFO] monitorLogs - 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 +} +[2025-02-24T12:49:46.443] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-02-24T12:49:46.444] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-02-24T12:00:00.444Z +[2025-02-24T12:49:46.445] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-02-24T12:49:46.446] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-02-24T12:49:46.447] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-02-24T12:49:46.447] [INFO] monitorLogs - 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 +} +[2025-02-24T12:49:46.449] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-02-24T12:49:46.449] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-02-24T12:00:00.449Z +[2025-02-24T12:49:46.450] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-02-24T12:49:46.451] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-02-24T12:49:46.454] [INFO] monitorLogs - tasks created: 296 +[2025-02-24T12:49:46.456] [INFO] monitorLogs - -->FLOW bol spustený d9x2V5LGYBzXp4mMRAOmKnkPloaqJwnQj6DgrNe3 2025-01-30 +[2025-02-24T12:49:46.537] [INFO] monitorLogs - MQTT client connected +[2025-02-24T12:49:46.761] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-02-24T12:49:47.065] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-02-24T12:49:47.368] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-02-24T13:05:36.154] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-02-24T13:05:41.501] [INFO] monitorLogs - buildTasks - params undefined +[2025-02-24T13:05:41.506] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-02-24T13:05:41.507] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-02-24T13:05:41.508] [INFO] monitorLogs - 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 +} +[2025-02-24T13:05:41.511] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-02-24T13:05:41.512] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-02-25T12:00:00.512Z +[2025-02-24T13:05:41.514] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-02-24T13:05:41.515] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-02-24T13:05:41.516] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-02-24T13:05:41.516] [INFO] monitorLogs - 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 +} +[2025-02-24T13:05:41.518] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-02-24T13:05:41.518] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-02-25T12:00:00.518Z +[2025-02-24T13:05:41.519] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-02-24T13:05:41.520] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-02-24T13:05:41.521] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-02-24T13:05:41.522] [INFO] monitorLogs - 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 +} +[2025-02-24T13:05:41.523] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-02-24T13:05:41.524] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-02-25T12:00:00.523Z +[2025-02-24T13:05:41.524] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-02-24T13:05:41.525] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-02-24T13:05:41.528] [INFO] monitorLogs - tasks created: 296 +[2025-02-24T13:05:41.530] [INFO] monitorLogs - -->FLOW bol spustený d9x2V5LGYBzXp4mMRAOmKnkPloaqJwnQj6DgrNe3 2025-01-30 +[2025-02-24T13:05:41.708] [INFO] monitorLogs - MQTT client connected +[2025-02-24T13:05:41.835] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-02-24T13:05:42.139] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-02-24T13:05:42.443] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-02-24T14:01:01.067] [INFO] monitorLogs - MQTT client connected +[2025-02-24T14:01:55.510] [INFO] monitorLogs - MQTT client connected +[2025-02-25T03:05:43.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-25 03:05:43 +[2025-02-25T06:51:17.513] [INFO] monitorLogs - MQTT client connected +[2025-02-25T06:52:29.807] [INFO] monitorLogs - MQTT client connected +[2025-02-25T06:52:59.445] [INFO] monitorLogs - MQTT client connected +[2025-02-25T06:56:21.963] [INFO] monitorLogs - MQTT client connected +[2025-02-25T06:56:53.429] [INFO] monitorLogs - MQTT client connected +[2025-02-25T06:58:34.626] [INFO] monitorLogs - MQTT client connected +[2025-02-25T07:11:36.614] [INFO] monitorLogs - MQTT client connected +[2025-02-25T07:12:11.371] [INFO] monitorLogs - MQTT client connected +[2025-02-25T07:13:18.812] [INFO] monitorLogs - MQTT client connected +[2025-02-25T07:14:33.307] [INFO] monitorLogs - MQTT client connected +[2025-02-25T07:15:29.627] [INFO] monitorLogs - MQTT client connected +[2025-02-25T07:16:14.848] [INFO] monitorLogs - MQTT client connected +[2025-02-25T07:16:41.249] [INFO] monitorLogs - MQTT client connected +[2025-02-25T07:18:13.910] [INFO] monitorLogs - MQTT client connected +[2025-02-25T12:37:25.094] [INFO] monitorLogs - MQTT client connected +[2025-02-25T12:37:57.402] [INFO] monitorLogs - MQTT client connected +[2025-02-25T12:38:35.407] [INFO] monitorLogs - MQTT client connected +[2025-02-25T14:05:56.525] [INFO] monitorLogs - MQTT client connected +[2025-02-25T14:07:49.007] [INFO] monitorLogs - MQTT client connected +[2025-02-25T14:10:11.243] [INFO] monitorLogs - MQTT client connected +[2025-02-25T14:11:36.074] [INFO] monitorLogs - MQTT client connected +[2025-02-25T14:12:35.842] [INFO] monitorLogs - MQTT client connected +[2025-02-25T14:14:10.400] [INFO] monitorLogs - MQTT client connected +[2025-02-25T14:14:48.326] [INFO] monitorLogs - MQTT client connected +[2025-02-25T14:15:10.880] [INFO] monitorLogs - MQTT client connected +[2025-02-25T14:20:51.149] [INFO] monitorLogs - MQTT client connected +[2025-02-26T03:05:45.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-26 03:05:45 +[2025-02-27T03:05:46.018] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-27 03:05:46 +[2025-02-28T03:05:48.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-28 03:05:48 +[2025-02-28T12:19:58.680] [INFO] monitorLogs - MQTT client connected +[2025-03-01T03:05:49.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-01 03:05:49 +[2025-03-02T03:05:51.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-02 03:05:51 +[2025-03-03T03:05:52.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-03 03:05:52 +[2025-03-04T03:05:54.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-04 03:05:54 +[2025-03-04T07:06:01.866] [INFO] monitorLogs - MQTT client connected +[2025-03-04T07:07:25.590] [INFO] monitorLogs - MQTT client connected +[2025-03-04T07:08:42.214] [INFO] monitorLogs - MQTT client connected +[2025-03-04T07:09:36.699] [INFO] monitorLogs - MQTT client connected +[2025-03-04T07:12:21.918] [INFO] monitorLogs - MQTT client connected +[2025-03-04T07:17:32.739] [INFO] monitorLogs - MQTT client connected +[2025-03-04T07:18:20.348] [INFO] monitorLogs - MQTT client connected +[2025-03-04T07:18:57.466] [INFO] monitorLogs - MQTT client connected +[2025-03-05T03:05:55.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-05 03:05:55 +[2025-03-06T03:05:57.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-06 03:05:57 +[2025-03-07T03:05:58.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-07 03:05:58 +[2025-03-08T03:06:00.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-08 03:06:00 +[2025-03-09T03:06:01.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-09 03:06:01 +[2025-03-10T03:06:03.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-10 03:06:03 +[2025-03-10T20:32:02.094] [INFO] monitorLogs - MQTT client connected +[2025-03-11T03:06:04.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-11 03:06:04 +[2025-03-11T08:19:30.360] [INFO] monitorLogs - MQTT client connected +[2025-03-11T08:22:01.015] [INFO] monitorLogs - MQTT client connected +[2025-03-11T08:23:45.333] [INFO] monitorLogs - MQTT client connected +[2025-03-11T08:24:54.855] [INFO] monitorLogs - MQTT client connected +[2025-03-11T08:25:43.948] [INFO] monitorLogs - MQTT client connected +[2025-03-12T03:06:06.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-12 03:06:06 +[2025-03-12T15:58:34.917] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-03-12T15:58:40.255] [INFO] monitorLogs - buildTasks - params undefined +[2025-03-12T15:58:40.260] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-03-12T15:58:40.261] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-03-12T15:58:40.262] [INFO] monitorLogs - 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 +} +[2025-03-12T15:58:40.265] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-03-12T15:58:40.266] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-03-13T12:00:00.265Z +[2025-03-12T15:58:40.268] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-03-12T15:58:40.269] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-03-12T15:58:40.269] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-03-12T15:58:40.270] [INFO] monitorLogs - 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 +} +[2025-03-12T15:58:40.272] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-03-12T15:58:40.272] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-03-13T12:00:00.272Z +[2025-03-12T15:58:40.273] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-03-12T15:58:40.274] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-03-12T15:58:40.275] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-03-12T15:58:40.275] [INFO] monitorLogs - 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 +} +[2025-03-12T15:58:40.277] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-03-12T15:58:40.278] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-03-13T12:00:00.278Z +[2025-03-12T15:58:40.279] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-03-12T15:58:40.280] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-03-12T15:58:40.282] [INFO] monitorLogs - tasks created: 296 +[2025-03-12T15:58:40.285] [INFO] monitorLogs - -->FLOW bol spustený d9x2V5LGYBzXp4mMRAOmKnkPloaqJwnQj6DgrNe3 2025-01-30 +[2025-03-12T15:58:40.363] [INFO] monitorLogs - MQTT client connected +[2025-03-12T15:58:40.589] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-03-12T15:58:40.893] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-03-12T15:58:41.196] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-03-13T03:58:41.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-13 03:58:41 +[2025-03-13T09:47:40.869] [INFO] monitorLogs - MQTT client connected +[2025-03-13T09:49:24.122] [INFO] monitorLogs - MQTT client connected +[2025-03-13T09:50:27.132] [INFO] monitorLogs - MQTT client connected +[2025-03-13T10:13:25.261] [INFO] monitorLogs - MQTT client connected +[2025-03-14T03:58:43.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-14 03:58:43 +[2025-03-14T11:37:47.038] [INFO] monitorLogs - MQTT client connected +[2025-03-15T03:58:44.023] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-15 03:58:44 +[2025-03-16T03:58:46.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-16 03:58:46 +[2025-03-17T03:58:47.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-17 03:58:47 +[2025-03-17T07:05:44.289] [INFO] monitorLogs - MQTT client connected +[2025-03-18T03:58:49.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-18 03:58:49 +[2025-03-19T03:58:50.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-19 03:58:50 +[2025-03-20T03:58:52.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-20 03:58:52 +[2025-03-21T03:58:53.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-21 03:58:53 +[2025-03-22T03:58:55.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-22 03:58:55 +[2025-03-23T03:58:56.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-23 03:58:56 +[2025-03-24T03:58:57.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-24 03:58:57 +[2025-03-24T07:03:55.423] [INFO] monitorLogs - MQTT client connected +[2025-03-24T07:43:29.743] [INFO] monitorLogs - MQTT client connected +[2025-03-24T08:09:32.511] [INFO] monitorLogs - MQTT client connected +[2025-03-24T08:39:39.150] [INFO] monitorLogs - MQTT client connected +[2025-03-24T09:29:26.377] [INFO] monitorLogs - MQTT client connected +[2025-03-24T10:03:47.407] [INFO] monitorLogs - MQTT client connected +[2025-03-24T11:52:19.742] [INFO] monitorLogs - MQTT client connected +[2025-03-24T12:22:00.527] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-03-24T12:22:05.872] [INFO] monitorLogs - buildTasks - params undefined +[2025-03-24T12:22:05.877] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-03-24T12:22:05.878] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-03-24T12:22:05.879] [INFO] monitorLogs - 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 +} +[2025-03-24T12:22:05.881] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-03-24T12:22:05.883] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-03-24T12:00:00.882Z +[2025-03-24T12:22:05.884] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-03-24T12:22:05.885] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-03-24T12:22:05.886] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-03-24T12:22:05.887] [INFO] monitorLogs - 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 +} +[2025-03-24T12:22:05.888] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-03-24T12:22:05.889] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-03-24T12:00:00.889Z +[2025-03-24T12:22:05.890] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-03-24T12:22:05.891] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-03-24T12:22:05.891] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-03-24T12:22:05.892] [INFO] monitorLogs - 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 +} +[2025-03-24T12:22:05.893] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-03-24T12:22:05.894] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-03-24T12:00:00.894Z +[2025-03-24T12:22:05.895] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-03-24T12:22:05.896] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-03-24T12:22:05.898] [INFO] monitorLogs - tasks created: 296 +[2025-03-24T12:22:05.901] [INFO] monitorLogs - -->FLOW bol spustený d9x2V5LGYBzXp4mMRAOmKnkPloaqJwnQj6DgrNe3 2025-01-30 +[2025-03-24T12:22:06.206] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-03-24T12:22:06.417] [INFO] monitorLogs - MQTT client connected +[2025-03-24T12:22:06.509] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-03-24T12:22:06.812] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-03-25T03:22:08.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-25 03:22:08 +[2025-03-25T12:59:07.276] [INFO] monitorLogs - MQTT client connected +[2025-03-25T13:15:40.352] [INFO] monitorLogs - MQTT client connected +[2025-03-26T03:22:10.015] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-26 03:22:10 +[2025-03-27T03:22:11.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-27 03:22:11 +[2025-03-28T03:22:13.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-28 03:22:13 +[2025-03-28T07:34:55.709] [INFO] monitorLogs - MQTT client connected +[2025-03-28T07:37:05.747] [INFO] monitorLogs - MQTT client connected +[2025-03-28T18:28:35.798] [INFO] monitorLogs - MQTT client connected +[2025-03-29T03:22:14.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-29 03:22:14 +[2025-03-30T03:22:15.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-30 03:22:15 +[2025-03-31T03:22:17.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-31 03:22:17 +[2025-03-31T06:47:28.915] [INFO] monitorLogs - MQTT client connected +[2025-03-31T06:48:49.873] [INFO] monitorLogs - MQTT client connected +[2025-03-31T06:49:06.309] [INFO] monitorLogs - MQTT client connected +[2025-03-31T06:50:12.227] [INFO] monitorLogs - MQTT client connected +[2025-04-01T03:22:18.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-01 03:22:18 +[2025-04-01T07:39:17.484] [INFO] monitorLogs - MQTT client connected +[2025-04-01T07:40:27.016] [INFO] monitorLogs - MQTT client connected +[2025-04-01T07:55:23.361] [INFO] monitorLogs - MQTT client connected +[2025-04-01T07:56:52.479] [INFO] monitorLogs - MQTT client connected +[2025-04-02T02:17:42.220] [INFO] monitorLogs - MQTT client connected +[2025-04-02T03:24:21.173] [INFO] monitorLogs - MQTT client connected +[2025-04-03T03:22:21.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-03 03:22:21 +[2025-04-04T03:22:23.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-04 03:22:23 +[2025-04-04T06:52:21.662] [INFO] monitorLogs - MQTT client connected +[2025-04-05T03:22:24.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-05 03:22:24 +[2025-04-06T03:22:26.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-06 03:22:26 +[2025-04-07T03:22:27.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-07 03:22:27 +[2025-04-07T08:33:05.873] [INFO] monitorLogs - MQTT client connected +[2025-04-07T08:38:27.466] [INFO] monitorLogs - MQTT client connected +[2025-04-08T03:22:29.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-08 03:22:29 +[2025-04-09T03:22:30.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-09 03:22:30 +[2025-04-10T03:22:31.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-10 03:22:31 +[2025-04-11T00:29:20.906] [INFO] monitorLogs - MQTT client connected +[2025-04-11T03:22:33.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-11 03:22:33 +[2025-04-12T03:22:34.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-12 03:22:34 +[2025-04-13T03:22:36.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-13 03:22:36 +[2025-04-14T03:22:37.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-14 03:22:37 +[2025-04-14T16:19:21.499] [INFO] monitorLogs - MQTT client connected +[2025-04-15T03:22:39.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-15 03:22:39 +[2025-04-15T11:19:26.113] [INFO] monitorLogs - MQTT client connected +[2025-04-16T03:22:40.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-16 03:22:40 +[2025-04-17T03:22:42.013] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-17 03:22:42 +[2025-04-18T03:22:43.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-18 03:22:43 +[2025-04-19T03:22:45.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-19 03:22:45 +[2025-04-20T03:22:46.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-20 03:22:46 +[2025-04-21T03:22:48.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-21 03:22:48 +[2025-04-22T03:22:49.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-22 03:22:49 +[2025-04-22T12:13:43.163] [INFO] monitorLogs - MQTT client connected +[2025-04-23T03:22:51.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-23 03:22:51 +[2025-04-23T08:21:46.430] [INFO] monitorLogs - MQTT client connected +[2025-04-24T03:22:52.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-24 03:22:52 +[2025-04-24T18:03:49.267] [INFO] monitorLogs - MQTT client connected +[2025-04-25T03:22:54.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-25 03:22:54 +[2025-04-25T10:30:24.515] [INFO] monitorLogs - MQTT client connected +[2025-04-25T10:31:00.527] [INFO] monitorLogs - MQTT client connected +[2025-04-25T11:23:34.917] [INFO] monitorLogs - MQTT client connected +[2025-04-26T03:22:55.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-26 03:22:55 +[2025-04-27T03:22:57.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-27 03:22:57 +[2025-04-28T03:22:58.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-28 03:22:58 +[2025-04-29T03:23:00.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-29 03:23:00 +[2025-04-29T06:54:53.427] [INFO] monitorLogs - MQTT client connected +[2025-04-29T06:56:18.662] [INFO] monitorLogs - MQTT client connected +[2025-04-29T07:48:12.125] [INFO] monitorLogs - MQTT client connected +[2025-04-29T07:48:26.322] [INFO] monitorLogs - MQTT client connected +[2025-04-29T07:49:27.000] [INFO] monitorLogs - MQTT client connected +[2025-04-29T07:50:33.142] [INFO] monitorLogs - MQTT client connected +[2025-04-29T07:51:53.000] [INFO] monitorLogs - MQTT client connected +[2025-04-29T07:52:18.480] [INFO] monitorLogs - MQTT client connected +[2025-04-29T07:54:00.309] [INFO] monitorLogs - MQTT client connected +[2025-04-29T07:54:41.602] [INFO] monitorLogs - MQTT client connected +[2025-04-30T03:23:01.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-30 03:23:01 +[2025-04-30T16:51:02.134] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-04-30T16:51:07.480] [INFO] monitorLogs - buildTasks - params undefined +[2025-04-30T16:51:07.485] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-04-30T16:51:07.486] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-04-30T16:51:07.487] [INFO] monitorLogs - 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 +} +[2025-04-30T16:51:07.490] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-04-30T16:51:07.491] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-05-01T11:00:00.490Z +[2025-04-30T16:51:07.492] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-04-30T16:51:07.494] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-04-30T16:51:07.494] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-04-30T16:51:07.495] [INFO] monitorLogs - 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 +} +[2025-04-30T16:51:07.496] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-04-30T16:51:07.497] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-05-01T11:00:00.497Z +[2025-04-30T16:51:07.498] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-04-30T16:51:07.499] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-04-30T16:51:07.500] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-04-30T16:51:07.500] [INFO] monitorLogs - 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 +} +[2025-04-30T16:51:07.502] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-04-30T16:51:07.502] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-05-01T11:00:00.502Z +[2025-04-30T16:51:07.503] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-04-30T16:51:07.504] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-04-30T16:51:07.507] [INFO] monitorLogs - tasks created: 277 +[2025-04-30T16:51:07.509] [INFO] monitorLogs - -->FLOW bol spustený d9x2V5LGYBzXp4mMRAOmKnkPloaqJwnQj6DgrNe3 2025-04-24 +[2025-04-30T16:51:07.654] [INFO] monitorLogs - MQTT client connected +[2025-04-30T16:51:07.814] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-04-30T16:51:08.118] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-04-30T16:51:08.421] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-05-01T03:51:09.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-01 03:51:09 +[2025-05-02T03:51:11.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-02 03:51:11 +[2025-05-03T03:51:13.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-03 03:51:13 +[2025-05-04T03:51:14.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-04 03:51:14 +[2025-05-05T03:51:16.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-05 03:51:16 +[2025-05-06T03:51:17.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-06 03:51:17 +[2025-05-06T08:16:17.330] [INFO] monitorLogs - MQTT client connected +[2025-05-07T03:51:19.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-07 03:51:19 +[2025-05-07T10:58:22.419] [INFO] monitorLogs - MQTT client connected +[2025-05-07T19:23:12.087] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-05-07T19:23:17.423] [INFO] monitorLogs - buildTasks - params undefined +[2025-05-07T19:23:17.427] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-05-07T19:23:17.429] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-05-07T19:23:17.430] [INFO] monitorLogs - 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 +} +[2025-05-07T19:23:17.433] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-05-07T19:23:17.434] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-05-08T11:00:00.434Z +[2025-05-07T19:23:17.436] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-05-07T19:23:17.437] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-05-07T19:23:17.438] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-05-07T19:23:17.438] [INFO] monitorLogs - 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 +} +[2025-05-07T19:23:17.440] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-05-07T19:23:17.440] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-05-08T11:00:00.440Z +[2025-05-07T19:23:17.441] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-05-07T19:23:17.442] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-05-07T19:23:17.443] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-05-07T19:23:17.443] [INFO] monitorLogs - 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 +} +[2025-05-07T19:23:17.445] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-05-07T19:23:17.446] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-05-08T11:00:00.445Z +[2025-05-07T19:23:17.446] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-05-07T19:23:17.447] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-05-07T19:23:17.450] [INFO] monitorLogs - tasks created: 277 +[2025-05-07T19:23:17.452] [INFO] monitorLogs - -->FLOW bol spustený d9x2V5LGYBzXp4mMRAOmKnkPloaqJwnQj6DgrNe3 2025-04-24 +[2025-05-07T19:23:17.620] [INFO] monitorLogs - MQTT client connected +[2025-05-07T19:23:17.757] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-05-07T19:23:18.060] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-05-07T19:23:18.363] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-05-08T03:23:19.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-08 03:23:19 +[2025-05-09T03:23:20.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-09 03:23:20 +[2025-05-10T03:23:22.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-10 03:23:22 +[2025-05-11T03:23:23.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-11 03:23:23 +[2025-05-12T03:23:25.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-12 03:23:25 +[2025-05-12T09:50:02.151] [INFO] monitorLogs - MQTT client connected +[2025-05-12T09:51:27.678] [INFO] monitorLogs - MQTT client connected +[2025-05-12T10:51:42.282] [INFO] monitorLogs - MQTT client connected +[2025-05-13T03:23:27.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-13 03:23:27 +[2025-05-14T03:23:28.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-14 03:23:28 +[2025-05-14T08:14:25.073] [INFO] monitorLogs - MQTT client connected +[2025-05-14T09:42:03.303] [INFO] monitorLogs - MQTT client connected +[2025-05-14T10:08:00.583] [INFO] monitorLogs - MQTT client connected +[2025-05-14T10:09:01.884] [INFO] monitorLogs - MQTT client connected +[2025-05-14T10:45:25.997] [INFO] monitorLogs - MQTT client connected +[2025-05-14T10:48:41.212] [INFO] monitorLogs - MQTT client connected +[2025-05-14T10:51:32.112] [INFO] monitorLogs - MQTT client connected +[2025-05-14T10:51:59.809] [INFO] monitorLogs - MQTT client connected +[2025-05-14T10:52:34.048] [INFO] monitorLogs - MQTT client connected +[2025-05-14T10:54:43.385] [INFO] monitorLogs - MQTT client connected +[2025-05-15T03:23:30.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-15 03:23:30 +[2025-05-16T03:23:31.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-16 03:23:31 +[2025-05-16T10:01:03.658] [INFO] monitorLogs - MQTT client connected +[2025-05-17T03:23:33.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-17 03:23:33 +[2025-05-18T03:23:34.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-18 03:23:34 +[2025-05-19T03:23:36.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-19 03:23:36 +[2025-05-20T03:23:37.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-20 03:23:37 +[2025-05-20T08:26:43.581] [INFO] monitorLogs - MQTT client connected +[2025-05-20T08:32:58.435] [INFO] monitorLogs - MQTT client connected +[2025-05-21T03:23:39.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-21 03:23:39 +[2025-05-22T03:23:40.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-22 03:23:40 +[2025-05-23T03:23:42.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-23 03:23:42 +[2025-05-23T10:54:19.461] [INFO] monitorLogs - MQTT client connected +[2025-05-24T03:23:43.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-24 03:23:43 +[2025-05-25T03:23:45.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-25 03:23:45 +[2025-05-26T03:23:47.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-26 03:23:47 +[2025-05-26T08:40:44.009] [INFO] monitorLogs - MQTT client connected +[2025-05-27T03:23:48.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-27 03:23:48 +[2025-05-27T11:01:52.803] [INFO] monitorLogs - MQTT client connected +[2025-05-27T12:47:22.582] [INFO] monitorLogs - MQTT client connected +[2025-05-27T12:48:26.689] [INFO] monitorLogs - MQTT client connected +[2025-05-27T12:49:58.749] [INFO] monitorLogs - MQTT client connected +[2025-05-27T12:51:39.546] [INFO] monitorLogs - MQTT client connected +[2025-05-28T03:23:50.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-28 03:23:50 +[2025-05-28T10:12:14.964] [INFO] monitorLogs - MQTT client connected +[2025-05-29T03:23:51.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-29 03:23:51 +[2025-05-30T03:23:53.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-30 03:23:53 +[2025-05-31T03:23:54.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-31 03:23:54 +[2025-05-31T13:39:31.418] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-05-31T13:39:36.761] [INFO] monitorLogs - buildTasks - params undefined +[2025-05-31T13:39:36.765] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-05-31T13:39:36.766] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-05-31T13:39:36.767] [INFO] monitorLogs - 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 +} +[2025-05-31T13:39:36.770] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-05-31T13:39:36.771] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-06-01T11:00:00.770Z +[2025-05-31T13:39:36.772] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-05-31T13:39:36.774] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-05-31T13:39:36.774] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-05-31T13:39:36.775] [INFO] monitorLogs - 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 +} +[2025-05-31T13:39:36.776] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-05-31T13:39:36.777] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-06-01T11:00:00.777Z +[2025-05-31T13:39:36.778] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-05-31T13:39:36.779] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-05-31T13:39:36.780] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-05-31T13:39:36.780] [INFO] monitorLogs - 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 +} +[2025-05-31T13:39:36.782] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-05-31T13:39:36.782] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-06-01T11:00:00.782Z +[2025-05-31T13:39:36.783] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-05-31T13:39:36.784] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-05-31T13:39:36.786] [INFO] monitorLogs - tasks created: 277 +[2025-05-31T13:39:36.789] [INFO] monitorLogs - -->FLOW bol spustený d9x2V5LGYBzXp4mMRAOmKnkPloaqJwnQj6DgrNe3 2025-04-24 +[2025-05-31T13:39:41.793] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-01T03:39:40.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-01 03:39:40 +[2025-06-02T03:39:41.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-02 03:39:41 +[2025-06-03T03:39:43.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-03 03:39:43 +[2025-06-04T03:39:44.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-04 03:39:44 +[2025-06-05T03:39:46.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-05 03:39:46 +[2025-06-06T03:39:48.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-06 03:39:48 +[2025-06-07T03:39:49.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-07 03:39:49 +[2025-06-08T03:39:51.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-08 03:39:51 +[2025-06-09T03:39:53.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-09 03:39:53 +[2025-06-10T03:39:54.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-10 03:39:54 +[2025-06-11T03:39:56.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-11 03:39:56 +[2025-06-12T03:39:57.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-12 03:39:57 +[2025-06-13T03:39:59.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-13 03:39:59 +[2025-06-13T15:21:23.133] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-06-13T15:21:28.474] [INFO] monitorLogs - buildTasks - params undefined +[2025-06-13T15:21:28.478] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-06-13T15:21:28.479] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-06-13T15:21:28.480] [INFO] monitorLogs - 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 +} +[2025-06-13T15:21:28.483] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-06-13T15:21:28.484] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-06-14T11:00:00.483Z +[2025-06-13T15:21:28.485] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-06-13T15:21:28.486] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-06-13T15:21:28.487] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-06-13T15:21:28.488] [INFO] monitorLogs - 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 +} +[2025-06-13T15:21:28.489] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-06-13T15:21:28.490] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-06-14T11:00:00.490Z +[2025-06-13T15:21:28.491] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-06-13T15:21:28.492] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-06-13T15:21:28.493] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-06-13T15:21:28.493] [INFO] monitorLogs - 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 +} +[2025-06-13T15:21:28.494] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-06-13T15:21:28.495] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-06-14T11:00:00.495Z +[2025-06-13T15:21:28.496] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-06-13T15:21:28.497] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-06-13T15:21:28.499] [INFO] monitorLogs - tasks created: 277 +[2025-06-13T15:21:28.502] [INFO] monitorLogs - -->FLOW bol spustený d9x2V5LGYBzXp4mMRAOmKnkPloaqJwnQj6DgrNe3 2025-04-24 +[2025-06-13T15:21:33.506] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-14T03:21:30.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-14 03:21:30 +[2025-06-15T03:21:36.296] [INFO] monitorLogs - setCorrectPlcTimeOnceADay - function error SyntaxError: Unexpected token < in JSON at position 0 + at JSON.parse () + at /home/unipi/flowserver/flow/cmd_manager.js:2424:28 + at Object.exec_callback [as callback] (/home/unipi/flowserver/node_modules/total.js/builders.js:5803:3) + at IncomingMessage.request_process_end (/home/unipi/flowserver/node_modules/total.js/utils.js:1184:11) + at IncomingMessage.emit (events.js:412:35) + at endReadableNT (internal/streams/readable.js:1334:12) + at processTicksAndRejections (internal/process/task_queues.js:82:21) 503: Service Unavailable
503
Service Unavailable
+[2025-06-16T03:21:34.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-16 03:21:34 +[2025-06-17T03:21:35.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-17 03:21:35 +[2025-06-18T03:21:37.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-18 03:21:37 +[2025-06-19T03:21:38.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-19 03:21:38 +[2025-06-20T03:21:40.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-20 03:21:40 +[2025-06-21T03:21:42.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-21 03:21:42 +[2025-06-22T03:21:43.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-22 03:21:43 +[2025-06-23T03:21:45.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-23 03:21:45 +[2025-06-24T03:21:47.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-24 03:21:47 +[2025-06-25T03:21:48.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-25 03:21:48 +[2025-06-26T03:21:50.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-26 03:21:50 +[2025-06-27T03:21:52.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-27 03:21:52 +[2025-06-28T03:21:54.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-28 03:21:54 +[2025-06-29T03:21:55.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-29 03:21:55 +[2025-06-30T03:21:57.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-30 03:21:57 +[2025-07-01T03:21:59.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-01 03:21:59 +[2025-07-02T03:22:01.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-02 03:22:01 +[2025-07-03T03:22:02.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-03 03:22:02 +[2025-07-04T03:22:04.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-04 03:22:04 +[2025-07-05T03:22:06.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-05 03:22:06 +[2025-07-06T03:22:08.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-06 03:22:08 +[2025-07-07T03:22:09.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-07 03:22:09 +[2025-07-07T13:17:50.109] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-07-07T13:17:55.454] [INFO] monitorLogs - buildTasks - params undefined +[2025-07-07T13:17:55.459] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-07-07T13:17:55.460] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-07-07T13:17:55.461] [INFO] monitorLogs - 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 +} +[2025-07-07T13:17:55.463] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-07-07T13:17:55.465] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-07-08T11:00:00.464Z +[2025-07-07T13:17:55.466] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-07-07T13:17:55.467] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-07-07T13:17:55.468] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-07-07T13:17:55.468] [INFO] monitorLogs - 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 +} +[2025-07-07T13:17:55.470] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-07-07T13:17:55.471] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-07-08T11:00:00.470Z +[2025-07-07T13:17:55.471] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-07-07T13:17:55.472] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-07-07T13:17:55.473] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-07-07T13:17:55.474] [INFO] monitorLogs - 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 +} +[2025-07-07T13:17:55.475] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-07-07T13:17:55.476] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-07-08T11:00:00.476Z +[2025-07-07T13:17:55.476] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-07-07T13:17:55.477] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-07-07T13:17:55.480] [INFO] monitorLogs - tasks created: 277 +[2025-07-07T13:17:55.482] [INFO] monitorLogs - -->FLOW bol spustený d9x2V5LGYBzXp4mMRAOmKnkPloaqJwnQj6DgrNe3 2025-07-08 +[2025-07-07T13:18:00.487] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-07T13:39:57.185] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-07-07T13:40:02.526] [INFO] monitorLogs - buildTasks - params undefined +[2025-07-07T13:40:02.530] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-07-07T13:40:02.531] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-07-07T13:40:02.532] [INFO] monitorLogs - 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 +} +[2025-07-07T13:40:02.535] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-07-07T13:40:02.536] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-07-08T11:00:00.535Z +[2025-07-07T13:40:02.537] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-07-07T13:40:02.538] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-07-07T13:40:02.539] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-07-07T13:40:02.540] [INFO] monitorLogs - 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 +} +[2025-07-07T13:40:02.541] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-07-07T13:40:02.542] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-07-08T11:00:00.542Z +[2025-07-07T13:40:02.543] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-07-07T13:40:02.544] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-07-07T13:40:02.545] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-07-07T13:40:02.545] [INFO] monitorLogs - 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 +} +[2025-07-07T13:40:02.547] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-07-07T13:40:02.547] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-07-08T11:00:00.547Z +[2025-07-07T13:40:02.548] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-07-07T13:40:02.549] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-07-07T13:40:02.552] [INFO] monitorLogs - tasks created: 277 +[2025-07-07T13:40:02.554] [INFO] monitorLogs - -->FLOW bol spustený d9x2V5LGYBzXp4mMRAOmKnkPloaqJwnQj6DgrNe3 2025-07-08 +[2025-07-07T13:40:07.558] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-08T03:40:05.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-08 03:40:05 +[2025-07-09T03:40:06.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-09 03:40:06 +[2025-07-10T02:24:04.672] [INFO] monitorLogs - MQTT client error Error: connect ECONNREFUSED 192.168.252.1:1883 + at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1159:16) { + errno: -111, + code: 'ECONNREFUSED', + syscall: 'connect', + address: '192.168.252.1', + port: 1883 +} +[2025-07-10T03:40:08.018] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-10 03:40:08 +[2025-07-11T03:40:09.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-11 03:40:09 +[2025-07-12T03:40:11.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-12 03:40:11 +[2025-07-13T03:40:13.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-13 03:40:13 +[2025-07-14T03:40:14.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-14 03:40:14 +[2025-07-15T03:40:16.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-15 03:40:16 +[2025-07-16T03:40:18.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-16 03:40:18 +[2025-07-17T03:40:19.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-17 03:40:19 +[2025-07-18T03:40:21.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-18 03:40:21 +[2025-07-19T03:40:23.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-19 03:40:23 +[2025-07-20T03:40:24.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-20 03:40:24 +[2025-07-21T03:40:26.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-21 03:40:26 +[2025-07-22T03:40:28.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-22 03:40:28 +[2025-07-23T03:40:29.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-23 03:40:29 +[2025-07-24T03:40:31.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-24 03:40:31 +[2025-07-25T03:40:33.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-25 03:40:33 +[2025-07-26T03:40:34.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-26 03:40:34 +[2025-07-27T03:40:36.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-27 03:40:36 +[2025-07-28T03:40:37.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-28 03:40:37 +[2025-07-29T03:40:39.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-29 03:40:39 +[2025-07-29T12:19:47.921] [INFO] monitorLogs - MQTT client error Error: connect ECONNREFUSED 192.168.252.1:1883 + at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1159:16) { + errno: -111, + code: 'ECONNREFUSED', + syscall: 'connect', + address: '192.168.252.1', + port: 1883 +} +[2025-07-30T03:40:41.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-30 03:40:41 +[2025-07-31T03:40:42.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-31 03:40:42 +[2025-08-01T03:40:44.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-01 03:40:44 +[2025-08-02T03:40:46.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-02 03:40:46 +[2025-08-03T03:40:47.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-03 03:40:47 +[2025-08-04T03:40:49.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-04 03:40:49 +[2025-08-05T03:40:50.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-05 03:40:50 +[2025-08-06T03:40:52.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-06 03:40:52 +[2025-08-06T13:35:51.164] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-08-06T13:35:56.509] [INFO] monitorLogs - buildTasks - params undefined +[2025-08-06T13:35:56.514] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-08-06T13:35:56.515] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-08-06T13:35:56.516] [INFO] monitorLogs - 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 +} +[2025-08-06T13:35:56.518] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-08-06T13:35:56.520] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-08-07T11:00:00.519Z +[2025-08-06T13:35:56.521] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-08-06T13:35:56.522] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-08-06T13:35:56.523] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-08-06T13:35:56.523] [INFO] monitorLogs - 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 +} +[2025-08-06T13:35:56.525] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-08-06T13:35:56.525] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-08-07T11:00:00.525Z +[2025-08-06T13:35:56.526] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-08-06T13:35:56.527] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-08-06T13:35:56.528] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-08-06T13:35:56.528] [INFO] monitorLogs - 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 +} +[2025-08-06T13:35:56.530] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-08-06T13:35:56.530] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-08-07T11:00:00.530Z +[2025-08-06T13:35:56.531] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-08-06T13:35:56.532] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-08-06T13:35:56.535] [INFO] monitorLogs - tasks created: 277 +[2025-08-06T13:35:56.537] [INFO] monitorLogs - -->FLOW bol spustený d9x2V5LGYBzXp4mMRAOmKnkPloaqJwnQj6DgrNe3 2025-08-08 +[2025-08-06T13:36:01.542] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-07T03:35:58.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-07 03:35:58 +[2025-08-08T03:36:00.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-08 03:36:00 +[2025-08-09T03:36:02.019] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-09 03:36:02 +[2025-08-10T03:36:04.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-10 03:36:04 +[2025-08-11T03:36:05.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-11 03:36:05 +[2025-08-12T03:36:07.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-12 03:36:07 +[2025-08-13T03:36:09.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-13 03:36:09 +[2025-08-14T03:36:11.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-14 03:36:11 +[2025-08-15T03:36:12.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-15 03:36:12 +[2025-08-16T03:36:14.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-16 03:36:14 +[2025-08-17T03:36:16.013] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-17 03:36:16 +[2025-08-18T03:36:17.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-18 03:36:17 +[2025-08-19T03:36:19.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-19 03:36:19 +[2025-08-20T03:36:20.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-20 03:36:20 +[2025-08-21T03:36:22.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-21 03:36:22 +[2025-08-22T03:36:24.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-22 03:36:24 +[2025-08-23T03:36:25.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-23 03:36:25 +[2025-08-24T03:36:27.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-24 03:36:27 +[2025-08-25T03:36:28.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-25 03:36:28 +[2025-08-26T03:36:30.013] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-26 03:36:30 +[2025-08-27T03:36:32.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-27 03:36:32 +[2025-08-28T03:36:33.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-28 03:36:33 +[2025-08-29T03:36:35.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-29 03:36:35 +[2025-08-30T03:36:37.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-30 03:36:37 +[2025-08-31T03:36:38.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-31 03:36:38 +[2025-09-01T03:36:40.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-01 03:36:40 +[2025-09-02T03:36:42.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-02 03:36:42 +[2025-09-03T03:36:43.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-03 03:36:43 +[2025-09-04T03:36:45.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-04 03:36:45 +[2025-09-05T03:36:47.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-05 03:36:47 +[2025-09-06T03:36:48.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-06 03:36:48 +[2025-09-07T03:36:50.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-07 03:36:50 +[2025-09-08T03:36:51.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-08 03:36:51 +[2025-09-09T03:36:53.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-09 03:36:53 +[2025-09-10T03:36:55.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-10 03:36:55 +[2025-09-11T03:36:56.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-11 03:36:56 +[2025-09-12T03:36:58.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-12 03:36:58 +[2025-09-13T03:36:59.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-13 03:36:59 +[2025-09-14T03:37:01.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-14 03:37:01 +[2025-09-15T03:37:02.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-15 03:37:02 +[2025-09-16T03:37:04.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-16 03:37:04 +[2025-09-16T15:40:12.512] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-09-16T15:40:17.849] [INFO] monitorLogs - buildTasks - params undefined +[2025-09-16T15:40:17.853] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-09-16T15:40:17.854] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-09-16T15:40:17.855] [INFO] monitorLogs - 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 +} +[2025-09-16T15:40:17.858] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-16T15:40:17.859] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-09-17T11:00:00.858Z +[2025-09-16T15:40:17.860] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-09-16T15:40:17.861] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-09-16T15:40:17.862] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-09-16T15:40:17.863] [INFO] monitorLogs - 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 +} +[2025-09-16T15:40:17.864] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-16T15:40:17.865] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-09-17T11:00:00.865Z +[2025-09-16T15:40:17.866] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-09-16T15:40:17.867] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-09-16T15:40:17.868] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-09-16T15:40:17.868] [INFO] monitorLogs - 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 +} +[2025-09-16T15:40:17.870] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-16T15:40:17.870] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-09-17T11:00:00.870Z +[2025-09-16T15:40:17.871] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-09-16T15:40:17.872] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-09-16T15:40:17.874] [INFO] monitorLogs - tasks created: 277 +[2025-09-16T15:40:17.877] [INFO] monitorLogs - -->FLOW bol spustený d9x2V5LGYBzXp4mMRAOmKnkPloaqJwnQj6DgrNe3 2025-08-08 +[2025-09-16T15:40:22.898] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-17T03:40:20.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-17 03:40:20 +[2025-09-17T20:34:35.718] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-09-17T20:34:41.056] [INFO] monitorLogs - buildTasks - params undefined +[2025-09-17T20:34:41.061] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-09-17T20:34:41.062] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-09-17T20:34:41.063] [INFO] monitorLogs - 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 +} +[2025-09-17T20:34:41.065] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-17T20:34:41.067] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-09-18T11:00:00.066Z +[2025-09-17T20:34:41.068] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-09-17T20:34:41.069] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-09-17T20:34:41.070] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-09-17T20:34:41.070] [INFO] monitorLogs - 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 +} +[2025-09-17T20:34:41.072] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-17T20:34:41.073] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-09-18T11:00:00.072Z +[2025-09-17T20:34:41.073] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-09-17T20:34:41.074] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-09-17T20:34:41.075] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-09-17T20:34:41.076] [INFO] monitorLogs - 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 +} +[2025-09-17T20:34:41.077] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-17T20:34:41.078] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-09-18T11:00:00.078Z +[2025-09-17T20:34:41.078] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-09-17T20:34:41.079] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-09-17T20:34:41.082] [INFO] monitorLogs - tasks created: 277 +[2025-09-17T20:34:41.084] [INFO] monitorLogs - -->FLOW bol spustený d9x2V5LGYBzXp4mMRAOmKnkPloaqJwnQj6DgrNe3 2025-08-08 +[2025-09-17T20:34:46.106] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-18T03:34:42.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-18 03:34:42 +[2025-09-19T03:34:44.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-19 03:34:44 +[2025-09-19T11:14:06.392] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-09-19T11:14:11.733] [INFO] monitorLogs - buildTasks - params undefined +[2025-09-19T11:14:11.737] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-09-19T11:14:11.738] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-09-19T11:14:11.739] [INFO] monitorLogs - 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 +} +[2025-09-19T11:14:11.742] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-19T11:14:11.743] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-09-19T11:00:00.742Z +[2025-09-19T11:14:11.744] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-09-19T11:14:11.746] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-09-19T11:14:11.747] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-09-19T11:14:11.748] [INFO] monitorLogs - 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 +} +[2025-09-19T11:14:11.750] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-19T11:14:11.751] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-09-19T11:00:00.751Z +[2025-09-19T11:14:11.752] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-09-19T11:14:11.753] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-09-19T11:14:11.753] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-09-19T11:14:11.754] [INFO] monitorLogs - 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 +} +[2025-09-19T11:14:11.755] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-19T11:14:11.756] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-09-19T11:00:00.756Z +[2025-09-19T11:14:11.757] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-09-19T11:14:11.758] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-09-19T11:14:11.760] [INFO] monitorLogs - tasks created: 277 +[2025-09-19T11:14:11.762] [INFO] monitorLogs - -->FLOW bol spustený d9x2V5LGYBzXp4mMRAOmKnkPloaqJwnQj6DgrNe3 2025-08-08 +[2025-09-19T11:14:16.783] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-20T03:14:14.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-20 03:14:14 +[2025-09-21T01:29:23.321] [INFO] monitorLogs - MQTT client error Error: connect ECONNREFUSED 192.168.252.1:1883 + at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1159:16) { + errno: -111, + code: 'ECONNREFUSED', + syscall: 'connect', + address: '192.168.252.1', + port: 1883 +} +[2025-09-21T03:14:15.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-21 03:14:15 +[2025-09-21T18:07:14.111] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-09-21T18:07:19.456] [INFO] monitorLogs - buildTasks - params undefined +[2025-09-21T18:07:19.461] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-09-21T18:07:19.462] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-09-21T18:07:19.462] [INFO] monitorLogs - 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 +} +[2025-09-21T18:07:19.465] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-21T18:07:19.466] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-09-22T11:00:00.466Z +[2025-09-21T18:07:19.468] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-09-21T18:07:19.469] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-09-21T18:07:19.470] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-09-21T18:07:19.470] [INFO] monitorLogs - 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 +} +[2025-09-21T18:07:19.472] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-21T18:07:19.472] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-09-22T11:00:00.472Z +[2025-09-21T18:07:19.473] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-09-21T18:07:19.474] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-09-21T18:07:19.475] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-09-21T18:07:19.476] [INFO] monitorLogs - 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 +} +[2025-09-21T18:07:19.477] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-21T18:07:19.478] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-09-22T11:00:00.477Z +[2025-09-21T18:07:19.478] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-09-21T18:07:19.479] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-09-21T18:07:19.482] [INFO] monitorLogs - tasks created: 277 +[2025-09-21T18:07:19.484] [INFO] monitorLogs - -->FLOW bol spustený d9x2V5LGYBzXp4mMRAOmKnkPloaqJwnQj6DgrNe3 2025-08-08 +[2025-09-21T18:07:24.505] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-22T03:07:22.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-22 03:07:22 +[2025-09-23T03:07:23.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-23 03:07:23 +[2025-09-23T13:02:00.356] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-09-23T13:02:05.727] [INFO] monitorLogs - buildTasks - params undefined +[2025-09-23T13:02:05.732] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-09-23T13:02:05.733] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-09-23T13:02:05.734] [INFO] monitorLogs - 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 +} +[2025-09-23T13:02:05.736] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-23T13:02:05.738] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-09-24T11:00:00.737Z +[2025-09-23T13:02:05.739] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-09-23T13:02:05.740] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-09-23T13:02:05.741] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-09-23T13:02:05.742] [INFO] monitorLogs - 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 +} +[2025-09-23T13:02:05.743] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-23T13:02:05.744] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-09-24T11:00:00.744Z +[2025-09-23T13:02:05.745] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-09-23T13:02:05.746] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-09-23T13:02:05.746] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-09-23T13:02:05.747] [INFO] monitorLogs - 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 +} +[2025-09-23T13:02:05.748] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-23T13:02:05.749] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-09-24T11:00:00.749Z +[2025-09-23T13:02:05.750] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-09-23T13:02:05.750] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-09-23T13:02:05.753] [INFO] monitorLogs - tasks created: 277 +[2025-09-23T13:02:05.755] [INFO] monitorLogs - -->FLOW bol spustený d9x2V5LGYBzXp4mMRAOmKnkPloaqJwnQj6DgrNe3 2025-08-08 +[2025-09-23T13:02:10.759] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-23T14:28:32.508] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-09-23T14:28:37.851] [INFO] monitorLogs - buildTasks - params undefined +[2025-09-23T14:28:37.856] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-09-23T14:28:37.857] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-09-23T14:28:37.857] [INFO] monitorLogs - 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 +} +[2025-09-23T14:28:37.860] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-23T14:28:37.861] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-09-24T11:00:00.861Z +[2025-09-23T14:28:37.863] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-09-23T14:28:37.864] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-09-23T14:28:37.865] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-09-23T14:28:37.865] [INFO] monitorLogs - 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 +} +[2025-09-23T14:28:37.867] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-23T14:28:37.867] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-09-24T11:00:00.867Z +[2025-09-23T14:28:37.868] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-09-23T14:28:37.869] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-09-23T14:28:37.870] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-09-23T14:28:37.870] [INFO] monitorLogs - 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 +} +[2025-09-23T14:28:37.872] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-23T14:28:37.873] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-09-24T11:00:00.872Z +[2025-09-23T14:28:37.873] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-09-23T14:28:37.874] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-09-23T14:28:37.876] [INFO] monitorLogs - tasks created: 277 +[2025-09-23T14:28:37.879] [INFO] monitorLogs - -->FLOW bol spustený d9x2V5LGYBzXp4mMRAOmKnkPloaqJwnQj6DgrNe3 2025-08-08 +[2025-09-23T14:28:42.898] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-24T03:28:39.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-24 03:28:39 +[2025-09-25T03:28:41.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-25 03:28:41 +[2025-09-25T16:27:14.848] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-09-25T16:27:20.182] [INFO] monitorLogs - buildTasks - params undefined +[2025-09-25T16:27:20.187] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-09-25T16:27:20.188] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-09-25T16:27:20.189] [INFO] monitorLogs - 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 +} +[2025-09-25T16:27:20.191] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-25T16:27:20.193] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-09-26T11:00:00.192Z +[2025-09-25T16:27:20.194] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-09-25T16:27:20.195] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-09-25T16:27:20.196] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-09-25T16:27:20.197] [INFO] monitorLogs - 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 +} +[2025-09-25T16:27:20.198] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-25T16:27:20.199] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-09-26T11:00:00.198Z +[2025-09-25T16:27:20.199] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-09-25T16:27:20.201] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-09-25T16:27:20.201] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-09-25T16:27:20.202] [INFO] monitorLogs - 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 +} +[2025-09-25T16:27:20.203] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-25T16:27:20.204] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-09-26T11:00:00.204Z +[2025-09-25T16:27:20.204] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-09-25T16:27:20.205] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-09-25T16:27:20.208] [INFO] monitorLogs - tasks created: 277 +[2025-09-25T16:27:20.210] [INFO] monitorLogs - -->FLOW bol spustený d9x2V5LGYBzXp4mMRAOmKnkPloaqJwnQj6DgrNe3 2025-08-08 +[2025-09-25T16:27:25.231] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-26T03:27:21.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-26 03:27:21 +[2025-09-27T03:27:23.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-27 03:27:23 +[2025-09-28T03:27:24.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-28 03:27:24 +[2025-09-29T03:27:26.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-29 03:27:26 +[2025-09-30T03:27:28.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-30 03:27:28 +[2025-10-01T03:27:29.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-01 03:27:29 +[2025-10-02T03:27:31.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-02 03:27:31 +[2025-10-03T03:27:33.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-03 03:27:33 +[2025-10-03T14:42:58.656] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-03T14:43:03.996] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-03T14:43:04.001] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-03T14:43:04.002] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-03T14:43:04.003] [INFO] monitorLogs - 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 +} +[2025-10-03T14:43:04.006] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-03T14:43:04.007] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-10-04T11:00:00.006Z +[2025-10-03T14:43:04.008] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-03T14:43:04.009] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-10-03T14:43:04.010] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-03T14:43:04.011] [INFO] monitorLogs - 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 +} +[2025-10-03T14:43:04.012] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-03T14:43:04.013] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-10-04T11:00:00.013Z +[2025-10-03T14:43:04.014] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-03T14:43:04.015] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-10-03T14:43:04.016] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-03T14:43:04.017] [INFO] monitorLogs - 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 +} +[2025-10-03T14:43:04.019] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-03T14:43:04.020] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-10-04T11:00:00.020Z +[2025-10-03T14:43:04.021] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-03T14:43:04.022] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-10-03T14:43:04.024] [INFO] monitorLogs - tasks created: 277 +[2025-10-03T14:43:04.027] [INFO] monitorLogs - -->FLOW bol spustený d9x2V5LGYBzXp4mMRAOmKnkPloaqJwnQj6DgrNe3 2025-08-08 +[2025-10-03T14:43:09.047] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-04T03:43:05.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-04 03:43:05 +[2025-10-05T03:43:07.014] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-05 03:43:07 +[2025-10-06T03:43:09.013] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-06 03:43:09 +[2025-10-07T03:43:10.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-07 03:43:10 +[2025-10-08T03:43:12.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-08 03:43:12 +[2025-10-09T03:43:14.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-09 03:43:14 +[2025-10-09T16:48:33.868] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-09T16:48:39.204] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-09T16:48:39.209] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-09T16:48:39.210] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-09T16:48:39.211] [INFO] monitorLogs - 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 +} +[2025-10-09T16:48:39.213] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T16:48:39.215] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-10-10T11:00:00.214Z +[2025-10-09T16:48:39.216] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-09T16:48:39.217] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-10-09T16:48:39.218] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-09T16:48:39.219] [INFO] monitorLogs - 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 +} +[2025-10-09T16:48:39.220] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T16:48:39.221] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-10-10T11:00:00.220Z +[2025-10-09T16:48:39.221] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-09T16:48:39.223] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-10-09T16:48:39.223] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-09T16:48:39.224] [INFO] monitorLogs - 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 +} +[2025-10-09T16:48:39.225] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T16:48:39.226] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-10-10T11:00:00.226Z +[2025-10-09T16:48:39.227] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-09T16:48:39.228] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-10-09T16:48:39.230] [INFO] monitorLogs - tasks created: 277 +[2025-10-09T16:48:39.232] [INFO] monitorLogs - -->FLOW bol spustený d9x2V5LGYBzXp4mMRAOmKnkPloaqJwnQj6DgrNe3 2025-08-08 +[2025-10-09T16:48:44.251] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-09T19:00:39.218] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-09T19:00:44.559] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-09T19:00:44.564] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-09T19:00:44.565] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-09T19:00:44.565] [INFO] monitorLogs - 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 +} +[2025-10-09T19:00:44.568] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T19:00:44.570] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-10-10T11:00:00.569Z +[2025-10-09T19:00:44.571] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-09T19:00:44.572] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-10-09T19:00:44.573] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-09T19:00:44.573] [INFO] monitorLogs - 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 +} +[2025-10-09T19:00:44.575] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T19:00:44.576] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-10-10T11:00:00.576Z +[2025-10-09T19:00:44.577] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-09T19:00:44.578] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-10-09T19:00:44.579] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-09T19:00:44.580] [INFO] monitorLogs - 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 +} +[2025-10-09T19:00:44.581] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T19:00:44.582] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-10-10T11:00:00.582Z +[2025-10-09T19:00:44.582] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-09T19:00:44.583] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-10-09T19:00:44.586] [INFO] monitorLogs - tasks created: 277 +[2025-10-09T19:00:44.588] [INFO] monitorLogs - -->FLOW bol spustený d9x2V5LGYBzXp4mMRAOmKnkPloaqJwnQj6DgrNe3 2025-08-08 +[2025-10-09T19:00:49.610] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-10T03:00:46.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-10 03:00:46 +[2025-10-11T03:00:47.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-11 03:00:47 +[2025-10-12T03:00:49.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-12 03:00:49 +[2025-10-13T03:00:50.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-13 03:00:50 +[2025-10-14T03:00:52.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-14 03:00:52 +[2025-10-15T03:00:53.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-15 03:00:53 +[2025-10-15T15:36:20.165] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-15T15:36:25.506] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-15T15:36:25.511] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-15T15:36:25.512] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-15T15:36:25.512] [INFO] monitorLogs - 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 +} +[2025-10-15T15:36:25.515] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-15T15:36:25.517] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-10-16T11:00:00.516Z +[2025-10-15T15:36:25.518] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-15T15:36:25.519] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-10-15T15:36:25.520] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-15T15:36:25.520] [INFO] monitorLogs - 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 +} +[2025-10-15T15:36:25.522] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-15T15:36:25.522] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-10-16T11:00:00.522Z +[2025-10-15T15:36:25.523] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-15T15:36:25.524] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-10-15T15:36:25.525] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-15T15:36:25.525] [INFO] monitorLogs - 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 +} +[2025-10-15T15:36:25.527] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-15T15:36:25.528] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-10-16T11:00:00.527Z +[2025-10-15T15:36:25.528] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-15T15:36:25.529] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-10-15T15:36:25.531] [INFO] monitorLogs - tasks created: 277 +[2025-10-15T15:36:25.534] [INFO] monitorLogs - -->FLOW bol spustený d9x2V5LGYBzXp4mMRAOmKnkPloaqJwnQj6DgrNe3 2025-10-08 +[2025-10-15T15:36:30.555] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu diff --git a/RVO7/package-lock.json b/RVO7/package-lock.json new file mode 100755 index 0000000..3c5c1ba --- /dev/null +++ b/RVO7/package-lock.json @@ -0,0 +1,2139 @@ +{ + "name": "emptyproject", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "emptyproject", + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "bitwise": "^2.1.0", + "easy-crc": "0.0.2", + "jsmodbus": "^4.0.6", + "log4js": "^6.3.0", + "moment": "^2.30.1", + "mqtt": "^4.2.6", + "nodemailer": "^6.9.7", + "serialport": "^9.2.8", + "total.js": "^3.4.13" + } + }, + "node_modules/@serialport/binding-abstract": { + "version": "9.2.3", + "resolved": "https://registry.npmjs.org/@serialport/binding-abstract/-/binding-abstract-9.2.3.tgz", + "integrity": "sha512-cQs9tbIlG3P0IrOWyVirqlhWuJ7Ms2Zh9m2108z6Y5UW/iVj6wEOiW8EmK9QX9jmJXYllE7wgGgvVozP5oCj3w==", + "dependencies": { + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/binding-mock": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/binding-mock/-/binding-mock-9.2.4.tgz", + "integrity": "sha512-dpEhACCs44oQhh6ajJfJdvQdK38Vq0N4W6iD/gdplglDCK7qXRQCMUjJIeKdS/HSEiWkC3bwumUhUufdsOyT4g==", + "dependencies": { + "@serialport/binding-abstract": "9.2.3", + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/bindings": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/@serialport/bindings/-/bindings-9.2.8.tgz", + "integrity": "sha512-hSLxTe0tADZ3LMMGwvEJWOC/TaFQTyPeFalUCsJ1lSQ0k6bPF04JwrtB/C81GetmDBTNRY0GlD0SNtKCc7Dr5g==", + "hasInstallScript": true, + "dependencies": { + "@serialport/binding-abstract": "9.2.3", + "@serialport/parser-readline": "9.2.4", + "bindings": "^1.5.0", + "debug": "^4.3.2", + "nan": "^2.15.0", + "prebuild-install": "^7.0.0" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-byte-length": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-byte-length/-/parser-byte-length-9.2.4.tgz", + "integrity": "sha512-sQD/iw4ZMU3xW9PLi0/GlvU6Y623jGeWecbMkO7izUo/6P7gtfv1c9ikd5h0kwL8AoAOpQA1lxdHIKox+umBUg==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-cctalk": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-cctalk/-/parser-cctalk-9.2.4.tgz", + "integrity": "sha512-T4TU5vQMwmo9AB3gQLFDWbfJXlW5jd9guEsB/nqKjFHTv0FXPdZ7DQ2TpSp8RnHWxU3GX6kYTaDO20BKzc8GPQ==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-delimiter": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-delimiter/-/parser-delimiter-9.2.4.tgz", + "integrity": "sha512-4nvTAoYAgkxFiXrkI+3CA49Yd43CODjeszh89EK+I9c8wOZ+etZduRCzINYPiy26g7zO+GRAb9FoPCsY+sYcbQ==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-inter-byte-timeout": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-inter-byte-timeout/-/parser-inter-byte-timeout-9.2.4.tgz", + "integrity": "sha512-SOAdvr0oBQIOCXX198hiTlxs4JTKg9j5piapw5tNq52fwDOWdbYrFneT/wN04UTMKaDrJuEvXq6T4rv4j7nJ5A==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-readline": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-readline/-/parser-readline-9.2.4.tgz", + "integrity": "sha512-Z1/qrZTQUVhNSJP1hd9YfDvq0o7d87rNwAjjRKbVpa7Qi51tG5BnKt43IV3NFMyBlVcRe0rnIb3tJu57E0SOwg==", + "dependencies": { + "@serialport/parser-delimiter": "9.2.4" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-ready": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-ready/-/parser-ready-9.2.4.tgz", + "integrity": "sha512-Pyi94Itjl6qAURwIZr/gmZpMAyTmKXThm6vL5DoAWGQjcRHWB0gwv2TY2v7N+mQLJYUKU3cMnvnATXxHm7xjxw==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-regex": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-regex/-/parser-regex-9.2.4.tgz", + "integrity": "sha512-sI/cVvPOYz+Dbv4ZdnW16qAwvXiFf/1pGASQdbveRTlgJDdz7sRNlCBifzfTN2xljwvCTZYqiudKvDdC1TepRQ==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/stream": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/stream/-/stream-9.2.4.tgz", + "integrity": "sha512-bLye8Ub4vUFQGmkh8qEqehr7SE7EJs2yDs0h9jzuL5oKi+F34CFmWkEErO8GAOQ8YNn7p6b3GxUgs+0BrHHDZQ==", + "dependencies": { + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "node_modules/are-we-there-yet": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", + "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/base64-js": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", + "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==" + }, + "node_modules/bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "dependencies": { + "file-uri-to-path": "1.0.0" + } + }, + "node_modules/bitwise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/bitwise/-/bitwise-2.1.0.tgz", + "integrity": "sha512-XKgAhMXCh4H/3oNwAHAsAO0iC89s9cOiumgYwSHjSobGWxYjv62YhkL9QEdvGP151xypCtMlAfKK79GEcd2eRQ==" + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/bl/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/buffer": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz", + "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==", + "dependencies": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + }, + "node_modules/buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" + }, + "node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, + "node_modules/code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/commist": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/commist/-/commist-1.1.0.tgz", + "integrity": "sha512-rraC8NXWOEjhADbZe9QBNzLAN5Q3fsTPQtBV+fEVj6xKIgDgNiEVE6ZNfHpZOqfQ21YUzfVNUXLOEZquYvQPPg==", + "dependencies": { + "leven": "^2.1.0", + "minimist": "^1.1.0" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "node_modules/concat-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", + "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", + "engines": [ + "node >= 6.0" + ], + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.0.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/concat-stream/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" + }, + "node_modules/core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "node_modules/crc": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/crc/-/crc-3.4.0.tgz", + "integrity": "sha512-ycVC2+4/DLgXXq7QweYi2znhqDuZz6P5TQXnkQo8v15XY/5p/IWeZwsSE31Ifo8w15b8TWLsqhXOjXyilHuQxw==" + }, + "node_modules/date-format": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.11.tgz", + "integrity": "sha512-VS20KRyorrbMCQmpdl2hg5KaOUsda1RbnsJg461FfrcyCUg+pkd0b40BSW4niQyTheww4DBXQnS7HwSrKkipLw==", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" + }, + "node_modules/detect-libc": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz", + "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==", + "engines": { + "node": ">=8" + } + }, + "node_modules/duplexify": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.2.tgz", + "integrity": "sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw==", + "dependencies": { + "end-of-stream": "^1.4.1", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1", + "stream-shift": "^1.0.0" + } + }, + "node_modules/duplexify/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/easy-crc": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/easy-crc/-/easy-crc-0.0.2.tgz", + "integrity": "sha512-h6eqIdhJRe0p271/xZJbM/0klCi13mW5IB7ZEzEGH11yV4QXWAkD4yPErz0fXdhFrd6sZ4Q1k5Iky2kMsMNePw==" + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" + }, + "node_modules/flatted": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", + "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==" + }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, + "node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "node_modules/gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha512-14x4kjc6lkD3ltw589k0NrPD6cCNTD6CWoVUNpB85+DrtONoZn+Rug6xZU5RvSC4+TZPxA5AnBibQYAvZn41Hg==", + "dependencies": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "node_modules/github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==" + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" + }, + "node_modules/has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" + }, + "node_modules/help-me": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/help-me/-/help-me-3.0.0.tgz", + "integrity": "sha512-hx73jClhyk910sidBB7ERlnhMlFsJJIBqSVMFDwPN8o2v9nmp5KgLq1Xz1Bf1fCMMZ6mPrX159iG0VLy/fPMtQ==", + "dependencies": { + "glob": "^7.1.6", + "readable-stream": "^3.6.0" + } + }, + "node_modules/help-me/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, + "node_modules/is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==", + "dependencies": { + "number-is-nan": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "node_modules/js-sdsl": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz", + "integrity": "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/js-sdsl" + } + }, + "node_modules/jsmodbus": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/jsmodbus/-/jsmodbus-4.0.6.tgz", + "integrity": "sha512-gCmjoaERErK5Rn9Lu/BN07fY13MoWV7JKgGzrnkPlQPdPxYcwDhLtYcmpFFpZ4J9NPZZBSezi1UkLZO/DnNppA==", + "dependencies": { + "crc": "3.4.0", + "debug": "^3.1.0" + }, + "bin": { + "jsmodbus": "bin/jsmodbus.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/jsmodbus/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/leven": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", + "integrity": "sha1-wuep93IJTe6dNCAq6KzORoeHVYA=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/log4js": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.5.2.tgz", + "integrity": "sha512-DXtpNtt+KDOMT7RHUDIur/WsSA3rntlUh9Zg4XCdV42wUuMmbFkl38+LZ92Z5QvQA7mD5kAVkLiBSEH/tvUB8A==", + "dependencies": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "flatted": "^3.2.5", + "rfdc": "^1.3.0", + "streamroller": "^3.1.1" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" + }, + "node_modules/moment": { + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", + "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==", + "engines": { + "node": "*" + } + }, + "node_modules/mqtt": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/mqtt/-/mqtt-4.3.7.tgz", + "integrity": "sha512-ew3qwG/TJRorTz47eW46vZ5oBw5MEYbQZVaEji44j5lAUSQSqIEoul7Kua/BatBW0H0kKQcC9kwUHa1qzaWHSw==", + "dependencies": { + "commist": "^1.0.0", + "concat-stream": "^2.0.0", + "debug": "^4.1.1", + "duplexify": "^4.1.1", + "help-me": "^3.0.0", + "inherits": "^2.0.3", + "lru-cache": "^6.0.0", + "minimist": "^1.2.5", + "mqtt-packet": "^6.8.0", + "number-allocator": "^1.0.9", + "pump": "^3.0.0", + "readable-stream": "^3.6.0", + "reinterval": "^1.1.0", + "rfdc": "^1.3.0", + "split2": "^3.1.0", + "ws": "^7.5.5", + "xtend": "^4.0.2" + }, + "bin": { + "mqtt": "bin/mqtt.js", + "mqtt_pub": "bin/pub.js", + "mqtt_sub": "bin/sub.js" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/mqtt-packet": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/mqtt-packet/-/mqtt-packet-6.10.0.tgz", + "integrity": "sha512-ja8+mFKIHdB1Tpl6vac+sktqy3gA8t9Mduom1BA75cI+R9AHnZOiaBQwpGiWnaVJLDGRdNhQmFaAqd7tkKSMGA==", + "dependencies": { + "bl": "^4.0.2", + "debug": "^4.1.1", + "process-nextick-args": "^2.0.1" + } + }, + "node_modules/mqtt/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/nan": { + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.16.0.tgz", + "integrity": "sha512-UdAqHyFngu7TfQKsCBgAA6pWDkT8MAO7d0jyOecVhN5354xbLqdn8mV9Tat9gepAupm0bt2DbeaSC8vS52MuFA==" + }, + "node_modules/napi-build-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", + "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==" + }, + "node_modules/node-abi": { + "version": "3.22.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.22.0.tgz", + "integrity": "sha512-u4uAs/4Zzmp/jjsD9cyFYDXeISfUWaAVWshPmDZOFOv4Xl4SbzTXm53I04C2uRueYJ+0t5PEtLH/owbn2Npf/w==", + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/nodemailer": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.7.tgz", + "integrity": "sha512-rUtR77ksqex/eZRLmQ21LKVH5nAAsVicAtAYudK7JgwenEDZ0UIQ1adUGqErz7sMkWYxWTTU1aeP2Jga6WQyJw==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "dependencies": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "node_modules/number-allocator": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/number-allocator/-/number-allocator-1.0.14.tgz", + "integrity": "sha512-OrL44UTVAvkKdOdRQZIJpLkAdjXGTRda052sN4sO77bKEzYYqWKMBjQvrJFzqygI99gL6Z4u2xctPW1tB8ErvA==", + "dependencies": { + "debug": "^4.3.1", + "js-sdsl": "4.3.0" + } + }, + "node_modules/number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/prebuild-install": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.0.tgz", + "integrity": "sha512-CNcMgI1xBypOyGqjp3wOc8AAo1nMhZS3Cwd3iHIxOdAUbb+YxdNuM4Z5iIrZ8RLvOsf3F3bl7b7xGq6DjQoNYA==", + "dependencies": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^1.0.1", + "node-abi": "^3.3.0", + "npmlog": "^4.0.1", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + }, + "bin": { + "prebuild-install": "bin.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/reinterval": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reinterval/-/reinterval-1.1.0.tgz", + "integrity": "sha1-M2Hs+jymwYKDOA3Qu5VG85D17Oc=" + }, + "node_modules/rfdc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==" + }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/serialport": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/serialport/-/serialport-9.2.8.tgz", + "integrity": "sha512-FsWpMQgSJxi93JgWl5xM1f9/Z8IjRJuaUEoHqLf8FPBLw7gMhInuHOBhI2onQufWIYPGTz3H3oGcu1nCaK1EfA==", + "dependencies": { + "@serialport/binding-mock": "9.2.4", + "@serialport/bindings": "9.2.8", + "@serialport/parser-byte-length": "9.2.4", + "@serialport/parser-cctalk": "9.2.4", + "@serialport/parser-delimiter": "9.2.4", + "@serialport/parser-inter-byte-timeout": "9.2.4", + "@serialport/parser-readline": "9.2.4", + "@serialport/parser-ready": "9.2.4", + "@serialport/parser-regex": "9.2.4", + "@serialport/stream": "9.2.4", + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "node_modules/split2": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", + "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", + "dependencies": { + "readable-stream": "^3.0.0" + } + }, + "node_modules/split2/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==" + }, + "node_modules/streamroller": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.1.1.tgz", + "integrity": "sha512-iPhtd9unZ6zKdWgMeYGfSBuqCngyJy1B/GPi/lTpwGpa3bajuX30GjUVd0/Tn/Xhg0mr4DOSENozz9Y06qyonQ==", + "dependencies": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "fs-extra": "^10.1.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dependencies": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/tar-fs": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "dependencies": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tar-stream/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/total.js": { + "version": "3.4.13", + "resolved": "https://registry.npmjs.org/total.js/-/total.js-3.4.13.tgz", + "integrity": "sha512-lAH4gEixlPFbrE3xfKADAcHfO79IFq2wKa9GTsrgRzIR5MTg3mNH7+4IxvX1pK8faoYb/0oYSJ1YTsAa5hIFFQ==", + "bin": { + "total": "bin/totaljs", + "total.js": "bin/totaljs", + "totaljs": "bin/totaljs", + "totalpackage": "bin/tpm", + "tpm": "bin/tpm" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, + "node_modules/universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "node_modules/wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "node_modules/ws": { + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } + }, + "dependencies": { + "@serialport/binding-abstract": { + "version": "9.2.3", + "resolved": "https://registry.npmjs.org/@serialport/binding-abstract/-/binding-abstract-9.2.3.tgz", + "integrity": "sha512-cQs9tbIlG3P0IrOWyVirqlhWuJ7Ms2Zh9m2108z6Y5UW/iVj6wEOiW8EmK9QX9jmJXYllE7wgGgvVozP5oCj3w==", + "requires": { + "debug": "^4.3.2" + } + }, + "@serialport/binding-mock": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/binding-mock/-/binding-mock-9.2.4.tgz", + "integrity": "sha512-dpEhACCs44oQhh6ajJfJdvQdK38Vq0N4W6iD/gdplglDCK7qXRQCMUjJIeKdS/HSEiWkC3bwumUhUufdsOyT4g==", + "requires": { + "@serialport/binding-abstract": "9.2.3", + "debug": "^4.3.2" + } + }, + "@serialport/bindings": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/@serialport/bindings/-/bindings-9.2.8.tgz", + "integrity": "sha512-hSLxTe0tADZ3LMMGwvEJWOC/TaFQTyPeFalUCsJ1lSQ0k6bPF04JwrtB/C81GetmDBTNRY0GlD0SNtKCc7Dr5g==", + "requires": { + "@serialport/binding-abstract": "9.2.3", + "@serialport/parser-readline": "9.2.4", + "bindings": "^1.5.0", + "debug": "^4.3.2", + "nan": "^2.15.0", + "prebuild-install": "^7.0.0" + } + }, + "@serialport/parser-byte-length": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-byte-length/-/parser-byte-length-9.2.4.tgz", + "integrity": "sha512-sQD/iw4ZMU3xW9PLi0/GlvU6Y623jGeWecbMkO7izUo/6P7gtfv1c9ikd5h0kwL8AoAOpQA1lxdHIKox+umBUg==" + }, + "@serialport/parser-cctalk": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-cctalk/-/parser-cctalk-9.2.4.tgz", + "integrity": "sha512-T4TU5vQMwmo9AB3gQLFDWbfJXlW5jd9guEsB/nqKjFHTv0FXPdZ7DQ2TpSp8RnHWxU3GX6kYTaDO20BKzc8GPQ==" + }, + "@serialport/parser-delimiter": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-delimiter/-/parser-delimiter-9.2.4.tgz", + "integrity": "sha512-4nvTAoYAgkxFiXrkI+3CA49Yd43CODjeszh89EK+I9c8wOZ+etZduRCzINYPiy26g7zO+GRAb9FoPCsY+sYcbQ==" + }, + "@serialport/parser-inter-byte-timeout": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-inter-byte-timeout/-/parser-inter-byte-timeout-9.2.4.tgz", + "integrity": "sha512-SOAdvr0oBQIOCXX198hiTlxs4JTKg9j5piapw5tNq52fwDOWdbYrFneT/wN04UTMKaDrJuEvXq6T4rv4j7nJ5A==" + }, + "@serialport/parser-readline": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-readline/-/parser-readline-9.2.4.tgz", + "integrity": "sha512-Z1/qrZTQUVhNSJP1hd9YfDvq0o7d87rNwAjjRKbVpa7Qi51tG5BnKt43IV3NFMyBlVcRe0rnIb3tJu57E0SOwg==", + "requires": { + "@serialport/parser-delimiter": "9.2.4" + } + }, + "@serialport/parser-ready": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-ready/-/parser-ready-9.2.4.tgz", + "integrity": "sha512-Pyi94Itjl6qAURwIZr/gmZpMAyTmKXThm6vL5DoAWGQjcRHWB0gwv2TY2v7N+mQLJYUKU3cMnvnATXxHm7xjxw==" + }, + "@serialport/parser-regex": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-regex/-/parser-regex-9.2.4.tgz", + "integrity": "sha512-sI/cVvPOYz+Dbv4ZdnW16qAwvXiFf/1pGASQdbveRTlgJDdz7sRNlCBifzfTN2xljwvCTZYqiudKvDdC1TepRQ==" + }, + "@serialport/stream": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/stream/-/stream-9.2.4.tgz", + "integrity": "sha512-bLye8Ub4vUFQGmkh8qEqehr7SE7EJs2yDs0h9jzuL5oKi+F34CFmWkEErO8GAOQ8YNn7p6b3GxUgs+0BrHHDZQ==", + "requires": { + "debug": "^4.3.2" + } + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==" + }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "are-we-there-yet": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", + "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "base64-js": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", + "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==" + }, + "bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "requires": { + "file-uri-to-path": "1.0.0" + } + }, + "bitwise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/bitwise/-/bitwise-2.1.0.tgz", + "integrity": "sha512-XKgAhMXCh4H/3oNwAHAsAO0iC89s9cOiumgYwSHjSobGWxYjv62YhkL9QEdvGP151xypCtMlAfKK79GEcd2eRQ==" + }, + "bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "requires": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "buffer": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz", + "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==", + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" + }, + "chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==" + }, + "commist": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/commist/-/commist-1.1.0.tgz", + "integrity": "sha512-rraC8NXWOEjhADbZe9QBNzLAN5Q3fsTPQtBV+fEVj6xKIgDgNiEVE6ZNfHpZOqfQ21YUzfVNUXLOEZquYvQPPg==", + "requires": { + "leven": "^2.1.0", + "minimist": "^1.1.0" + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "concat-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", + "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.0.2", + "typedarray": "^0.0.6" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "crc": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/crc/-/crc-3.4.0.tgz", + "integrity": "sha512-ycVC2+4/DLgXXq7QweYi2znhqDuZz6P5TQXnkQo8v15XY/5p/IWeZwsSE31Ifo8w15b8TWLsqhXOjXyilHuQxw==" + }, + "date-format": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.11.tgz", + "integrity": "sha512-VS20KRyorrbMCQmpdl2hg5KaOUsda1RbnsJg461FfrcyCUg+pkd0b40BSW4niQyTheww4DBXQnS7HwSrKkipLw==" + }, + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "requires": { + "ms": "2.1.2" + } + }, + "decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "requires": { + "mimic-response": "^3.1.0" + } + }, + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==" + }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" + }, + "detect-libc": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz", + "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==" + }, + "duplexify": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.2.tgz", + "integrity": "sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw==", + "requires": { + "end-of-stream": "^1.4.1", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1", + "stream-shift": "^1.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "easy-crc": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/easy-crc/-/easy-crc-0.0.2.tgz", + "integrity": "sha512-h6eqIdhJRe0p271/xZJbM/0klCi13mW5IB7ZEzEGH11yV4QXWAkD4yPErz0fXdhFrd6sZ4Q1k5Iky2kMsMNePw==" + }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "requires": { + "once": "^1.4.0" + } + }, + "expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==" + }, + "file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" + }, + "flatted": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", + "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==" + }, + "fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, + "fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha512-14x4kjc6lkD3ltw589k0NrPD6cCNTD6CWoVUNpB85+DrtONoZn+Rug6xZU5RvSC4+TZPxA5AnBibQYAvZn41Hg==", + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==" + }, + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" + }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" + }, + "help-me": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/help-me/-/help-me-3.0.0.tgz", + "integrity": "sha512-hx73jClhyk910sidBB7ERlnhMlFsJJIBqSVMFDwPN8o2v9nmp5KgLq1Xz1Bf1fCMMZ6mPrX159iG0VLy/fPMtQ==", + "requires": { + "glob": "^7.1.6", + "readable-stream": "^3.6.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==", + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "js-sdsl": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz", + "integrity": "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==" + }, + "jsmodbus": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/jsmodbus/-/jsmodbus-4.0.6.tgz", + "integrity": "sha512-gCmjoaERErK5Rn9Lu/BN07fY13MoWV7JKgGzrnkPlQPdPxYcwDhLtYcmpFFpZ4J9NPZZBSezi1UkLZO/DnNppA==", + "requires": { + "crc": "3.4.0", + "debug": "^3.1.0" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "requires": { + "ms": "^2.1.1" + } + } + } + }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, + "leven": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", + "integrity": "sha1-wuep93IJTe6dNCAq6KzORoeHVYA=" + }, + "log4js": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.5.2.tgz", + "integrity": "sha512-DXtpNtt+KDOMT7RHUDIur/WsSA3rntlUh9Zg4XCdV42wUuMmbFkl38+LZ92Z5QvQA7mD5kAVkLiBSEH/tvUB8A==", + "requires": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "flatted": "^3.2.5", + "rfdc": "^1.3.0", + "streamroller": "^3.1.1" + } + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "requires": { + "yallist": "^4.0.0" + } + }, + "mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==" + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==" + }, + "mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" + }, + "moment": { + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", + "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==" + }, + "mqtt": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/mqtt/-/mqtt-4.3.7.tgz", + "integrity": "sha512-ew3qwG/TJRorTz47eW46vZ5oBw5MEYbQZVaEji44j5lAUSQSqIEoul7Kua/BatBW0H0kKQcC9kwUHa1qzaWHSw==", + "requires": { + "commist": "^1.0.0", + "concat-stream": "^2.0.0", + "debug": "^4.1.1", + "duplexify": "^4.1.1", + "help-me": "^3.0.0", + "inherits": "^2.0.3", + "lru-cache": "^6.0.0", + "minimist": "^1.2.5", + "mqtt-packet": "^6.8.0", + "number-allocator": "^1.0.9", + "pump": "^3.0.0", + "readable-stream": "^3.6.0", + "reinterval": "^1.1.0", + "rfdc": "^1.3.0", + "split2": "^3.1.0", + "ws": "^7.5.5", + "xtend": "^4.0.2" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "mqtt-packet": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/mqtt-packet/-/mqtt-packet-6.10.0.tgz", + "integrity": "sha512-ja8+mFKIHdB1Tpl6vac+sktqy3gA8t9Mduom1BA75cI+R9AHnZOiaBQwpGiWnaVJLDGRdNhQmFaAqd7tkKSMGA==", + "requires": { + "bl": "^4.0.2", + "debug": "^4.1.1", + "process-nextick-args": "^2.0.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "nan": { + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.16.0.tgz", + "integrity": "sha512-UdAqHyFngu7TfQKsCBgAA6pWDkT8MAO7d0jyOecVhN5354xbLqdn8mV9Tat9gepAupm0bt2DbeaSC8vS52MuFA==" + }, + "napi-build-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", + "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==" + }, + "node-abi": { + "version": "3.22.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.22.0.tgz", + "integrity": "sha512-u4uAs/4Zzmp/jjsD9cyFYDXeISfUWaAVWshPmDZOFOv4Xl4SbzTXm53I04C2uRueYJ+0t5PEtLH/owbn2Npf/w==", + "requires": { + "semver": "^7.3.5" + } + }, + "nodemailer": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.7.tgz", + "integrity": "sha512-rUtR77ksqex/eZRLmQ21LKVH5nAAsVicAtAYudK7JgwenEDZ0UIQ1adUGqErz7sMkWYxWTTU1aeP2Jga6WQyJw==" + }, + "npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "number-allocator": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/number-allocator/-/number-allocator-1.0.14.tgz", + "integrity": "sha512-OrL44UTVAvkKdOdRQZIJpLkAdjXGTRda052sN4sO77bKEzYYqWKMBjQvrJFzqygI99gL6Z4u2xctPW1tB8ErvA==", + "requires": { + "debug": "^4.3.1", + "js-sdsl": "4.3.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==" + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==" + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==" + }, + "prebuild-install": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.0.tgz", + "integrity": "sha512-CNcMgI1xBypOyGqjp3wOc8AAo1nMhZS3Cwd3iHIxOdAUbb+YxdNuM4Z5iIrZ8RLvOsf3F3bl7b7xGq6DjQoNYA==", + "requires": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^1.0.1", + "node-abi": "^3.3.0", + "npmlog": "^4.0.1", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + } + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + } + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "reinterval": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reinterval/-/reinterval-1.1.0.tgz", + "integrity": "sha1-M2Hs+jymwYKDOA3Qu5VG85D17Oc=" + }, + "rfdc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==" + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "requires": { + "lru-cache": "^6.0.0" + } + }, + "serialport": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/serialport/-/serialport-9.2.8.tgz", + "integrity": "sha512-FsWpMQgSJxi93JgWl5xM1f9/Z8IjRJuaUEoHqLf8FPBLw7gMhInuHOBhI2onQufWIYPGTz3H3oGcu1nCaK1EfA==", + "requires": { + "@serialport/binding-mock": "9.2.4", + "@serialport/bindings": "9.2.8", + "@serialport/parser-byte-length": "9.2.4", + "@serialport/parser-cctalk": "9.2.4", + "@serialport/parser-delimiter": "9.2.4", + "@serialport/parser-inter-byte-timeout": "9.2.4", + "@serialport/parser-readline": "9.2.4", + "@serialport/parser-ready": "9.2.4", + "@serialport/parser-regex": "9.2.4", + "@serialport/stream": "9.2.4", + "debug": "^4.3.2" + } + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==" + }, + "simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "requires": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "split2": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", + "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", + "requires": { + "readable-stream": "^3.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==" + }, + "streamroller": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.1.1.tgz", + "integrity": "sha512-iPhtd9unZ6zKdWgMeYGfSBuqCngyJy1B/GPi/lTpwGpa3bajuX30GjUVd0/Tn/Xhg0mr4DOSENozz9Y06qyonQ==", + "requires": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "fs-extra": "^10.1.0" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" + }, + "tar-fs": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "requires": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "requires": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "total.js": { + "version": "3.4.13", + "resolved": "https://registry.npmjs.org/total.js/-/total.js-3.4.13.tgz", + "integrity": "sha512-lAH4gEixlPFbrE3xfKADAcHfO79IFq2wKa9GTsrgRzIR5MTg3mNH7+4IxvX1pK8faoYb/0oYSJ1YTsAa5hIFFQ==" + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, + "universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==" + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "requires": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "ws": { + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "requires": {} + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } + } +} diff --git a/RVO7/package.json b/RVO7/package.json new file mode 100755 index 0000000..7f7c795 --- /dev/null +++ b/RVO7/package.json @@ -0,0 +1,30 @@ +{ + "name": "emptyproject", + "description": "Total.js empty project.", + "version": "1.0.0", + "main": "debug.js", + "dependencies": { + "bitwise": "^2.1.0", + "easy-crc": "0.0.2", + "jsmodbus": "^4.0.6", + "log4js": "^6.3.0", + "moment": "^2.30.1", + "mqtt": "^4.2.6", + "nodemailer": "^6.9.7", + "serialport": "^9.2.8", + "total.js": "^3.4.13" + }, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "https://github.com/totaljs/emptyproject-flow" + }, + "keywords": [ + "empty", + "project" + ], + "author": "Peter Širka", + "license": "MIT" +} diff --git a/RVO7/release.js b/RVO7/release.js new file mode 100755 index 0000000..02d52ff --- /dev/null +++ b/RVO7/release.js @@ -0,0 +1,15 @@ +// =================================================== +// FOR PRODUCTION +// Total.js - framework for Node.js platform +// https://www.totaljs.com +// =================================================== + +const options = {'ip':'0.0.0.0', 'port':12345}; + +// options.ip = '127.0.0.1'; +// options.port = parseInt(process.argv[2]); +// options.config = { name: 'Total.js' }; +// options.sleep = 3000; + +require('total.js').http('release', options); +// require('total.js').cluster.http(5, 'release', options); diff --git a/RVO7/release.js.json b/RVO7/release.js.json new file mode 100755 index 0000000..4e1d5f4 --- /dev/null +++ b/RVO7/release.js.json @@ -0,0 +1,34 @@ +{ + "pid": 385, + "stats": [ + { + "id": null, + "version": { + "node": "v14.18.1", + "total": "3.4.13", + "app": "1.0.0" + }, + "pid": 385, + "thread": "", + "mode": "release", + "overload": 0, + "date": "2025-10-16T00:23:16.156Z", + "memory": 24.36, + "rm": 0, + "fm": 0, + "wm": 0, + "mm": 0, + "om": 2, + "em": 0, + "dbrm": 0, + "dbwm": 0, + "usage": 0, + "requests": 0, + "pending": 0, + "errors": 0, + "timeouts": 0, + "uptime": 648, + "online": 0 + } + ] +} \ No newline at end of file diff --git a/RVO7/report_data.log b/RVO7/report_data.log new file mode 100755 index 0000000..b69d7cc --- /dev/null +++ b/RVO7/report_data.log @@ -0,0 +1,151 @@ +{ + "name": "rvo_senica_7_ip126", + "time": "2025-10-15T14:36:31.162Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_7_ip126", + "time": "2025-10-15T15:36:31.161Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_7_ip126", + "time": "2025-10-15T16:36:31.161Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_7_ip126", + "time": "2025-10-15T17:36:31.162Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_7_ip126", + "time": "2025-10-15T18:36:31.162Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_7_ip126", + "time": "2025-10-15T19:36:31.162Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_7_ip126", + "time": "2025-10-15T20:36:31.162Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_7_ip126", + "time": "2025-10-15T21:36:31.162Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_7_ip126", + "time": "2025-10-15T22:36:31.162Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_7_ip126", + "time": "2025-10-15T23:36:31.161Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +} \ No newline at end of file From b58e3182e2e314819eebf2868fa5c648936bec84 Mon Sep 17 00:00:00 2001 From: Jakub Klena Date: Thu, 16 Oct 2025 02:23:41 +0200 Subject: [PATCH 05/30] Backup senica-RVO12 on 16.10.2025 --- RVO12/addSwitch.py | 36 + RVO12/cloud_topic.py | 76 + RVO12/config | 12 + RVO12/createNode.py | 43 + RVO12/databases/accelerometer_db.js | 3055 ++++++++++++++++ RVO12/databases/modbus_config.js | 114 + RVO12/databases/nodes.table | 50 + .../nodes_original/nodes_original.table | 1 + RVO12/databases/notifications.table | 41 + RVO12/databases/pins.table | 14 + RVO12/databases/relays.table | 5 + RVO12/databases/settings.table | 2 + RVO12/databases/tbdata.nosql | 4 + RVO12/databases/tbdatacloud.nosql | 3 + RVO12/databases/total_energy.js | 38 + RVO12/debug.js | 16 + RVO12/err.txt | 33 + RVO12/flow/cloudmqttconnect.js | 357 ++ RVO12/flow/cmd_manager.js | 3071 ++++++++++++++++ RVO12/flow/code.js | 90 + RVO12/flow/comment.js | 11 + RVO12/flow/count.js | 60 + RVO12/flow/db_connector.js | 286 ++ RVO12/flow/db_init.js | 113 + RVO12/flow/debug.js | 100 + RVO12/flow/designer.json | 3102 +++++++++++++++++ RVO12/flow/dido_controller.js | 1486 ++++++++ RVO12/flow/helper/DataToTbHandler.js | 187 + RVO12/flow/helper/ErrorToServiceHandler.js | 91 + RVO12/flow/helper/db_helper.js | 44 + RVO12/flow/helper/logger.js | 30 + RVO12/flow/helper/md5.js | 5 + RVO12/flow/helper/notification_reporter.js | 121 + RVO12/flow/helper/register.js | 144 + RVO12/flow/helper/serialport_helper.js | 99 + RVO12/flow/helper/suncalc.js | 317 ++ RVO12/flow/helper/utils.js | 161 + RVO12/flow/httprequest.js | 137 + RVO12/flow/httpresponse.js | 76 + RVO12/flow/httproute.js | 326 ++ RVO12/flow/infosender.js | 81 + RVO12/flow/modbus_reader.js | 346 ++ RVO12/flow/monitorconsumption.js | 156 + RVO12/flow/monitordisk.js | 96 + RVO12/flow/monitormemory.js | 87 + RVO12/flow/nodesdb_changecheck.js | 77 + RVO12/flow/show_dbdata.js | 243 ++ RVO12/flow/slack_filter.js | 188 + RVO12/flow/thermometer.js | 99 + RVO12/flow/trigger.js | 79 + RVO12/flow/variables.txt | 0 RVO12/flow/virtualwirein.js | 43 + RVO12/flow/virtualwireout.js | 41 + RVO12/flow/wsmqttpublish.js | 448 +++ RVO12/monitor.txt | 306 ++ RVO12/package-lock.json | 2139 ++++++++++++ RVO12/package.json | 30 + RVO12/release.js | 15 + RVO12/release.js.json | 34 + RVO12/report_data.log | 181 + 60 files changed, 18646 insertions(+) create mode 100755 RVO12/addSwitch.py create mode 100755 RVO12/cloud_topic.py create mode 100755 RVO12/config create mode 100755 RVO12/createNode.py create mode 100755 RVO12/databases/accelerometer_db.js create mode 100755 RVO12/databases/modbus_config.js create mode 100755 RVO12/databases/nodes.table create mode 100755 RVO12/databases/nodes_original/nodes_original.table create mode 100755 RVO12/databases/notifications.table create mode 100755 RVO12/databases/pins.table create mode 100755 RVO12/databases/relays.table create mode 100755 RVO12/databases/settings.table create mode 100755 RVO12/databases/tbdata.nosql create mode 100755 RVO12/databases/tbdatacloud.nosql create mode 100755 RVO12/databases/total_energy.js create mode 100755 RVO12/debug.js create mode 100755 RVO12/err.txt create mode 100755 RVO12/flow/cloudmqttconnect.js create mode 100755 RVO12/flow/cmd_manager.js create mode 100755 RVO12/flow/code.js create mode 100755 RVO12/flow/comment.js create mode 100755 RVO12/flow/count.js create mode 100755 RVO12/flow/db_connector.js create mode 100755 RVO12/flow/db_init.js create mode 100755 RVO12/flow/debug.js create mode 100755 RVO12/flow/designer.json create mode 100755 RVO12/flow/dido_controller.js create mode 100755 RVO12/flow/helper/DataToTbHandler.js create mode 100755 RVO12/flow/helper/ErrorToServiceHandler.js create mode 100755 RVO12/flow/helper/db_helper.js create mode 100755 RVO12/flow/helper/logger.js create mode 100755 RVO12/flow/helper/md5.js create mode 100755 RVO12/flow/helper/notification_reporter.js create mode 100755 RVO12/flow/helper/register.js create mode 100755 RVO12/flow/helper/serialport_helper.js create mode 100755 RVO12/flow/helper/suncalc.js create mode 100755 RVO12/flow/helper/utils.js create mode 100755 RVO12/flow/httprequest.js create mode 100755 RVO12/flow/httpresponse.js create mode 100755 RVO12/flow/httproute.js create mode 100755 RVO12/flow/infosender.js create mode 100755 RVO12/flow/modbus_reader.js create mode 100755 RVO12/flow/monitorconsumption.js create mode 100755 RVO12/flow/monitordisk.js create mode 100755 RVO12/flow/monitormemory.js create mode 100755 RVO12/flow/nodesdb_changecheck.js create mode 100755 RVO12/flow/show_dbdata.js create mode 100755 RVO12/flow/slack_filter.js create mode 100755 RVO12/flow/thermometer.js create mode 100755 RVO12/flow/trigger.js create mode 100755 RVO12/flow/variables.txt create mode 100755 RVO12/flow/virtualwirein.js create mode 100755 RVO12/flow/virtualwireout.js create mode 100755 RVO12/flow/wsmqttpublish.js create mode 100755 RVO12/monitor.txt create mode 100755 RVO12/package-lock.json create mode 100755 RVO12/package.json create mode 100755 RVO12/release.js create mode 100755 RVO12/release.js.json create mode 100755 RVO12/report_data.log diff --git a/RVO12/addSwitch.py b/RVO12/addSwitch.py new file mode 100755 index 0000000..c35e96b --- /dev/null +++ b/RVO12/addSwitch.py @@ -0,0 +1,36 @@ +import os + +def process_set_file(): + """ + Checks if /root/flowserver exists, reads set.txt, and modifies the second line. + """ + default_folder = "/root/flowserver" if os.path.exists("/root/flowserver") else "/home/unipi/flowserver" + flag = 1 if default_folder == "/root/flowserver" else 0 + + try: + with open("/home/unipi/flowserver/databases/settings.table", "r") as f: + lines = f.readlines() + + if len(lines) >= 2: + lines[0] = lines[0].rstrip('\n') + "|main_switch:boolean\n" + second_line = lines[1].strip() # remove trailing newline + last_pipe_index = second_line.rfind("|") + + if last_pipe_index != -1: + modified_line = second_line[:last_pipe_index + 1] + str(flag) + "|" + second_line[last_pipe_index + 1:] + lines[1] = modified_line + else: + print("Warning: No '|' character found in the second line of set.txt") + + with open("/home/unipi/flowserver/databases/settings.table", "w") as f: + f.writelines(lines) + else: + print("Warning: settings.table has less than two lines.") + + except FileNotFoundError: + print("Error: settings.table not found.") + except Exception as e: + print(e) + +# if __name__ == "__main__": +process_set_file() diff --git a/RVO12/cloud_topic.py b/RVO12/cloud_topic.py new file mode 100755 index 0000000..77c31f1 --- /dev/null +++ b/RVO12/cloud_topic.py @@ -0,0 +1,76 @@ +# import os +# +# def modify_file(file_path): +# """ +# Modifies the given file by: +# 1. Appending "|cloud_topic" to the first line. +# 2. Inserting the text from the third "." to the first "|" on the second line after the last "|" character. +# +# Args: +# file_path (str): The path to the file to be modified. +# """ +# +# with open(file_path, 'r+') as f: +# lines = f.readlines() +# +# # Modify the first line +# lines[0] += "|cloud_topic:string" +# +# # Modify the second line +# second_line = lines[1].strip() # Remove leading/trailing whitespace +# first_pipe_index = second_line.find('|') +# third_dot_index = second_line.find('.', second_line.find('.', second_line.find('.') + 1) + 1) +# text_to_insert = second_line[third_dot_index:first_pipe_index] +# +# last_pipe_index = second_line.rfind('|') +# lines[1] = second_line[:last_pipe_index + 1] + text_to_insert + "|" + second_line[last_pipe_index + 1:] +# +# print(first_pipe_index, third_dot_index, text_to_insert, last_pipe_index) +# # Write the modified lines back to the file +# # f.seek(0) +# # f.writelines(lines) +# # f.truncate() +# +# # Example usage: +# file_path = "settings.table" # Replace with the actual file path +# modify_file(file_path) +# + + +def modify_file(file_path): + """ + Modifies the given file by: + 1. Appending "|cloud_topic" to the first line. + 2. Inserting the text between the third "." and the second "|" on the second line after the last "|" character. + + Args: + file_path (str): The path to the file to be modified. + """ + + with open(file_path, 'r+') as f: + lines = f.readlines() + + first_line = lines[0].strip() + first_line += "|cloud_topic:string\n" + # Modify the first line + lines[0] = first_line + + # Modify the second line + second_line = lines[1].strip() # Remove leading/trailing whitespace + first_pipe_index = second_line.find('|') + second_pipe_index = second_line.find('|', first_pipe_index + 1) + third_dot_index = second_line.find('.', second_line.find('.', second_line.find('.') + 1) + 1) + text_to_insert = "u" + second_line[third_dot_index+1:second_pipe_index] + + last_pipe_index = second_line.rfind('|') + lines[1] = second_line[:last_pipe_index + 1] + text_to_insert + "|" + second_line[last_pipe_index + 1:] + + print(first_pipe_index, third_dot_index, text_to_insert, last_pipe_index) + # Write the modified lines back to the file + f.seek(0) + f.writelines(lines) + f.truncate() + +# Example usage: +file_path = "/home/unipi/flowserver/databases/settings.table" # Replace with the actual file path +modify_file(file_path) diff --git a/RVO12/config b/RVO12/config new file mode 100755 index 0000000..cd0a8a9 --- /dev/null +++ b/RVO12/config @@ -0,0 +1,12 @@ +name : Total.js Flow +default_timezone : Europe/Bratislava + +// Packages settings +package#flow (Object) : { url: '/' } + + +table.relays : line:number|tbname:string|contactor:number|profile:string +table.nodes : node:number|pole_number:string|node_type:string|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|project_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|cloud_topic:string|has_main_switch:boolean|daily_report:boolean|send_changed_node_numbers:boolean +table.pins : pin:string|type:string|line:number +table.notifications : key:string|weight:string|sk:string|en:string diff --git a/RVO12/createNode.py b/RVO12/createNode.py new file mode 100755 index 0000000..a8cea91 --- /dev/null +++ b/RVO12/createNode.py @@ -0,0 +1,43 @@ +print("zaciname") +import re, json + +search_str = '|' +final = [] +counter = 1 +with open("/home/unipi/flowserver/databases/nodes.table", 'r') as file: +# with open("/home/rasta5man/dev/oms/flowserver/databases/nodes.table", 'r') as file: + # Read each line in the file + for line in file: + # Print each line + line = line.strip() + print(line) + if counter != 1: + i = [m.start() for m in re.finditer(re.escape(search_str), line)] + node = line[ i[0] + 1 : i[1] ] + tbname = line[ i[3] + 1 : i[4] ] + final.append({node:tbname}) + counter += 1 +print(json.dumps(final)) +f = open("/home/unipi/flowserver/databases/nodes_original/nodes_original.table", "w") +f.write(json.dumps(final)) +f.close() + + +# +# # ``d`` has to be replaced with a different character +# old_character = "'" +# +# # ``t`` will replace ``d` +# new_character = '"' +# resultant_string = 0; +# with open("/home/unipi/flowserver/databases/nodes_original/nodes_original.table", 'r') as file: +# for line in file: +# resultant_string = re.sub("'", '"', line) +# +# resultant_string = re.sub(" ", "", resultant_string) +# print(resultant_string) +# +# f = open("/home/unipi/flowserver/databases/nodes_original/nodes_original.table", "w") +# f.write(str(resultant_string)) +# f.close() +# diff --git a/RVO12/databases/accelerometer_db.js b/RVO12/databases/accelerometer_db.js new file mode 100755 index 0000000..fdfc7fd --- /dev/null +++ b/RVO12/databases/accelerometer_db.js @@ -0,0 +1,3055 @@ +let naklony = { + "3993": { "label": "1/3A", "naklon": 0 }, + "3989": { "label": "1/3B", "naklon": 15 }, + "3976": { "label": "1/1", "naklon": 0 }, + "4181": { "label": "1/2", "naklon": 0 }, + "4376": { "label": "1/4", "naklon": 15 }, + "3868": { "label": "1/5", "naklon": 15 }, + "3728": { "label": "1/6", "naklon": 15 }, + "3730": { "label": "1/7", "naklon": 0 }, + "4374": { "label": "1/8", "naklon": 0 }, + "3718": { "label": "1/9", "naklon": 15 }, + "4375": { "label": "1/10", "naklon": 15 }, + "4172": { "label": "1/11", "naklon": 15 }, + "4176": { "label": "1/12", "naklon": 15 }, + "3800": { "label": "2/1", "naklon": 5 }, + "3823": { "label": "2/2", "naklon": 5 }, + "3905": { "label": "2/3", "naklon": 5 }, + "3803": { "label": "2/4", "naklon": 5 }, + "3817": { "label": "2/5", "naklon": 5 }, + "3818": { "label": "2/6", "naklon": 5 }, + "3811": { "label": "2/7", "naklon": 5 }, + "3915": { "label": "2/8", "naklon": 5 }, + "3843": { "label": "2/9", "naklon": 10 }, + "3827": { "label": "2/10", "naklon": 10 }, + "4220": { "label": "2/11", "naklon": 10 }, + "3826": { "label": "2/12", "naklon": 10 }, + "3834": { "label": "2/13", "naklon": 10 }, + "3838": { "label": "2/14", "naklon": 10 }, + "2823": { "label": "2/15", "naklon": 10 }, + "3750": { "label": "2/16", "naklon": 10 }, + "3378": { "label": "2/17", "naklon": 0 }, + "3376": { "label": "2/18", "naklon": 0 }, + "3379": { "label": "2/19", "naklon": 0 }, + "3285": { "label": "2/20", "naklon": 0 }, + "3382": { "label": "2/21", "naklon": 0 }, + "3383": { "label": "2/22", "naklon": 0 }, + "3375": { "label": "2/24", "naklon": 0 }, + "3381": { "label": "2/25", "naklon": 0 }, + "3380": { "label": "2/26", "naklon": 0 }, + "3828": { "label": "2/27", "naklon": 10 }, + "3377": { "label": "2/28", "naklon": 0 }, + "3591": { "label": "7/1", "naklon": 0 }, + "3587": { "label": "7/2", "naklon": 0 }, + "3468": { "label": "7/3", "naklon": 0 }, + "3466": { "label": "7/4", "naklon": 0 }, + "3474": { "label": "7/5", "naklon": 0 }, + "3481": { "label": "7/6", "naklon": 0 }, + "3589": { "label": "7/7", "naklon": 0 }, + "3472": { "label": "7/8", "naklon": 0 }, + "3473": { "label": "7/9", "naklon": 0 }, + "3584": { "label": "7/10", "naklon": 0 }, + "3571": { "label": "7/11", "naklon": 0 }, + "3476": { "label": "7/12", "naklon": 0 }, + "3590": { "label": "7/13", "naklon": 0 }, + "3478": { "label": "7/14", "naklon": 0 }, + "3471": { "label": "7/15", "naklon": 0 }, + "3467": { "label": "7/16", "naklon": 0 }, + "3479": { "label": "7/17", "naklon": 0 }, + "3480": { "label": "7/18", "naklon": 0 }, + "3477": { "label": "7/19", "naklon": 0 }, + "3362": { "label": "12/1", "naklon": 0 }, + "3355": { "label": "12/2", "naklon": 0 }, + "3356": { "label": "12/3", "naklon": 0 }, + "3349": { "label": "12/4", "naklon": 0 }, + "3357": { "label": "12/5", "naklon": 0 }, + "3350": { "label": "12/6", "naklon": 0 }, + "3353": { "label": "12/7", "naklon": 0 }, + "3539": { "label": "12/8", "naklon": 0 }, + "3050": { "label": "12/9", "naklon": 0 }, + "3361": { "label": "12/10", "naklon": 0 }, + "3360": { "label": "12/11", "naklon": 0 }, + "3358": { "label": "12/12", "naklon": 0 }, + "3541": { "label": "12/13", "naklon": 0 }, + "3551": { "label": "12/14", "naklon": 0 }, + "3514": { "label": "12/15", "naklon": 0 }, + "3547": { "label": "12/16", "naklon": 0 }, + "3562": { "label": "12/17", "naklon": 0 }, + "3525": { "label": "12/18", "naklon": 0 }, + "3558": { "label": "12/19", "naklon": 0 }, + "3511": { "label": "12/20", "naklon": 0 }, + "3058": { "label": "12/21", "naklon": 0 }, + "3062": { "label": "12/22", "naklon": 0 }, + "3070": { "label": "12/23", "naklon": 0 }, + "3447": { "label": "12/24", "naklon": 0 }, + "3056": { "label": "12/25", "naklon": 0 }, + "3057": { "label": "12/26", "naklon": 0 }, + "3071": { "label": "12/27", "naklon": 0 }, + "3061": { "label": "12/28", "naklon": 0 }, + "3069": { "label": "12/29", "naklon": 0 }, + "3077": { "label": "12/30", "naklon": 0 }, + "3080": { "label": "12/31", "naklon": 0 }, + "3081": { "label": "12/32", "naklon": 0 }, + "3078": { "label": "12/33", "naklon": 0 }, + "4037": { "label": "12/34", "naklon": 0 }, + "3067": { "label": "12/35", "naklon": 0 }, + "3051": { "label": "12/36", "naklon": 0 }, + "2924": { "label": "12/37", "naklon": 0 }, + "3060": { "label": "12/38", "naklon": 0 }, + "3073": { "label": "12/39", "naklon": 0 }, + "3469": { "label": "12/40", "naklon": 0 }, + "2923": { "label": "12/41", "naklon": 0 }, + "2925": { "label": "12/42", "naklon": 0 }, + "3359": { "label": "12/43", "naklon": 0 }, + "3055": { "label": "12/44", "naklon": 0 }, + "2922": { "label": "12/45", "naklon": 0 }, + "3084": { "label": "12/46", "naklon": 0 }, + "3064": { "label": "12/47", "naklon": 0 }, + "3066": { "label": "12/48", "naklon": 0 }, + "3072": { "label": "12/49", "naklon": 0 }, + "3415": { "label": "13/13A", "naklon": 0 }, + "3409": { "label": "13/13B", "naklon": 0 }, + "3399": { "label": "13/13C", "naklon": 0 }, + "3410": { "label": "13/29A", "naklon": 0 }, + "3407": { "label": "13/29B", "naklon": 0 }, + "3405": { "label": "13/34A", "naklon": 0 }, + "3404": { "label": "13/34B", "naklon": 0 }, + "3392": { "label": "13/45A", "naklon": 0 }, + "3386": { "label": "13/45B", "naklon": 0 }, + "3303": { "label": "13/60A", "naklon": 3 }, + "3302": { "label": "13/60B", "naklon": 3 }, + "3319": { "label": "13/70A", "naklon": 6 }, + "3317": { "label": "13/70B", "naklon": 6 }, + "3326": { "label": "13/70C", "naklon": 6 }, + "3351": { "label": "13/73A", "naklon": 6 }, + "3313": { "label": "13/73B", "naklon": 6 }, + "3316": { "label": "13/83A", "naklon": 0 }, + "3320": { "label": "13/83B", "naklon": 0 }, + "3336": { "label": "13/95A", "naklon": 0 }, + "3323": { "label": "13/95B", "naklon": 0 }, + "3339": { "label": "13/98A", "naklon": 0 }, + "3333": { "label": "13/98B", "naklon": 0 }, + "3425": { "label": "13/1", "naklon": 0 }, + "3419": { "label": "13/2", "naklon": 0 }, + "3416": { "label": "13/3", "naklon": 0 }, + "3332": { "label": "13/4", "naklon": 0 }, + "3422": { "label": "13/5", "naklon": 0 }, + "3417": { "label": "13/6", "naklon": 0 }, + "3418": { "label": "13/7", "naklon": 0 }, + "3424": { "label": "13/8", "naklon": 0 }, + "3334": { "label": "13/9", "naklon": 0 }, + "4363": { "label": "13/10", "naklon": 0 }, + "3423": { "label": "13/11", "naklon": 0 }, + "3406": { "label": "13/12", "naklon": 0 }, + "3411": { "label": "13/14", "naklon": 0 }, + "3412": { "label": "13/15", "naklon": 0 }, + "3413": { "label": "13/16", "naklon": 0 }, + "3414": { "label": "13/17", "naklon": 0 }, + "3391": { "label": "13/18", "naklon": 0 }, + "3370": { "label": "13/19", "naklon": 0 }, + "3369": { "label": "13/20", "naklon": 0 }, + "3408": { "label": "13/21", "naklon": 0 }, + "3393": { "label": "13/22", "naklon": 0 }, + "3128": { "label": "13/23", "naklon": 0 }, + "3197": { "label": "13/24", "naklon": 0 }, + "4364": { "label": "13/25", "naklon": 0 }, + "3155": { "label": "13/26", "naklon": 0 }, + "3196": { "label": "13/27", "naklon": 0 }, + "3144": { "label": "13/28", "naklon": 0 }, + "3150": { "label": "13/30", "naklon": 0 }, + "3390": { "label": "13/31", "naklon": 0 }, + "3401": { "label": "13/32", "naklon": 0 }, + "3275": { "label": "13/33", "naklon": 0 }, + "3371": { "label": "13/35", "naklon": 0 }, + "3389": { "label": "13/36", "naklon": 0 }, + "3388": { "label": "13/37", "naklon": 0 }, + "3365": { "label": "13/38", "naklon": 0 }, + "3363": { "label": "13/39", "naklon": 0 }, + "3397": { "label": "13/40", "naklon": 0 }, + "3567": { "label": "13/40/1", "naklon": 0 }, + "3387": { "label": "13/41", "naklon": 0 }, + "3403": { "label": "13/42", "naklon": 0 }, + "3147": { "label": "13/43", "naklon": 0 }, + "3141": { "label": "13/44", "naklon": 0 }, + "3364": { "label": "13/46", "naklon": 0 }, + "3367": { "label": "13/47", "naklon": 0 }, + "3368": { "label": "13/48", "naklon": 0 }, + "3402": { "label": "13/49", "naklon": 0 }, + "3366": { "label": "13/50", "naklon": 0 }, + "3395": { "label": "13/51", "naklon": 0 }, + "3372": { "label": "13/52", "naklon": 0 }, + "3394": { "label": "13/53", "naklon": 0 }, + "3308": { "label": "13/54", "naklon": 0 }, + "3847": { "label": "13/54/1", "naklon": 0 }, + "3312": { "label": "13/55", "naklon": 3 }, + "3309": { "label": "13/56", "naklon": 3 }, + "3311": { "label": "13/57", "naklon": 3 }, + "3310": { "label": "13/58", "naklon": 3 }, + "4365": { "label": "13/59", "naklon": 3 }, + "4093": { "label": "13/60/1", "naklon": 3 }, + "3304": { "label": "13/61", "naklon": 3 }, + "3307": { "label": "13/62", "naklon": 3 }, + "3271": { "label": "13/63", "naklon": 3 }, + "3301": { "label": "13/64", "naklon": 3 }, + "4366": { "label": "13/65", "naklon": 3 }, + "3300": { "label": "13/66", "naklon": 3 }, + "3185": { "label": "13/67", "naklon": 0 }, + "3184": { "label": "13/68", "naklon": 0 }, + "3188": { "label": "13/69", "naklon": 0 }, + "3343": { "label": "13/71", "naklon": 6 }, + "3819": { "label": "13/71/1", "naklon": 6 }, + "3880": { "label": "13/71/2", "naklon": 6 }, + "3348": { "label": "13/72", "naklon": 6 }, + "3344": { "label": "13/74", "naklon": 6 }, + "3346": { "label": "13/75", "naklon": 6 }, + "3597": { "label": "13/75/1", "naklon": 6 }, + "3345": { "label": "13/76", "naklon": 6 }, + "3322": { "label": "13/77", "naklon": 0 }, + "3325": { "label": "13/78", "naklon": 0 }, + "4310": { "label": "13/78/1", "naklon": 0 }, + "3315": { "label": "13/79", "naklon": 0 }, + "3328": { "label": "13/80", "naklon": 0 }, + "3321": { "label": "13/81", "naklon": 0 }, + "3324": { "label": "13/82", "naklon": 0 }, + "3140": { "label": "13/84", "naklon": 0 }, + "3153": { "label": "13/85", "naklon": 0 }, + "3145": { "label": "13/86", "naklon": 0 }, + "3134": { "label": "13/87", "naklon": 0 }, + "3151": { "label": "13/88", "naklon": 0 }, + "3143": { "label": "13/89", "naklon": 0 }, + "3318": { "label": "13/90", "naklon": 0 }, + "3347": { "label": "13/91", "naklon": 0 }, + "3314": { "label": "13/94", "naklon": 0 }, + "3331": { "label": "13/96", "naklon": 0 }, + "3327": { "label": "13/97", "naklon": 0 }, + "3329": { "label": "13/99", "naklon": 0 }, + "3337": { "label": "13/100", "naklon": 0 }, + "3330": { "label": "13/101", "naklon": 0 }, + "3335": { "label": "13/102", "naklon": 0 }, + "3420": { "label": "13/103", "naklon": 0 }, + "3421": { "label": "13/104", "naklon": 0 }, + "4361": { "label": "13/105", "naklon": 0 }, + "4362": { "label": "13/106", "naklon": 0 }, + "3526": { "label": "13/107", "naklon": 0 }, + "4424": { "label": "13/108", "naklon": null }, + "3561": { "label": "13/109", "naklon": null }, + "3527": { "label": "13/110", "naklon": null }, + "3521": { "label": "13/111", "naklon": null }, + "3552": { "label": "13/112", "naklon": null }, + "3544": { "label": "13/113", "naklon": null }, + "3534": { "label": "13/114", "naklon": null }, + "3516": { "label": "13/115", "naklon": null }, + "3513": { "label": "13/116", "naklon": null }, + "3565": { "label": "13/117", "naklon": null }, + "3866": { "label": "13/118", "naklon": null }, + "3136": { "label": "14/1", "naklon": 0 }, + "3137": { "label": "14/2", "naklon": 0 }, + "3135": { "label": "14/3", "naklon": 0 }, + "3149": { "label": "14/4", "naklon": 0 }, + "3142": { "label": "14/5", "naklon": 0 }, + "3342": { "label": "14/6", "naklon": 0 }, + "3340": { "label": "14/7", "naklon": 0 }, + "3152": { "label": "14/8", "naklon": 0 }, + "3886": { "label": "14/9", "naklon": 0 }, + "3341": { "label": "14/10", "naklon": null }, + "3352": { "label": "14/11", "naklon": null }, + "3396": { "label": "15/1", "naklon": 5 }, + "2784": { "label": "15/2", "naklon": 5 }, + "2788": { "label": "15/3", "naklon": 5 }, + "2801": { "label": "15/4", "naklon": 5 }, + "2815": { "label": "15/5", "naklon": 5 }, + "2829": { "label": "15/6", "naklon": 5 }, + "2796": { "label": "15/7", "naklon": 5 }, + "2803": { "label": "15/8", "naklon": 5 }, + "4304": { "label": "15/8/1", "naklon": 5 }, + "4311": { "label": "15/8/2", "naklon": 5 }, + "2821": { "label": "15/9", "naklon": 5 }, + "3400": { "label": "15/10", "naklon": 5 }, + "2799": { "label": "15/11", "naklon": 5 }, + "2804": { "label": "15/12", "naklon": 5 }, + "4303": { "label": "15/12/1", "naklon": 5 }, + "4309": { "label": "15/12/2", "naklon": 5 }, + "2806": { "label": "15/13", "naklon": 5 }, + "2787": { "label": "15/14", "naklon": 5 }, + "2809": { "label": "15/15", "naklon": 5 }, + "2814": { "label": "15/16", "naklon": 0 }, + "3934": { "label": "15/17", "naklon": 0 }, + "3192": { "label": "15/18", "naklon": 0 }, + "2812": { "label": "15/19", "naklon": 0 }, + "4070": { "label": "15/20", "naklon": 0 }, + "2826": { "label": "15/21", "naklon": 0 }, + "2808": { "label": "15/22", "naklon": 3 }, + "2795": { "label": "15/23", "naklon": 3 }, + "2807": { "label": "15/24", "naklon": 3 }, + "2831": { "label": "15/25", "naklon": 0 }, + "2862": { "label": "15/26", "naklon": null }, + "2861": { "label": "15/27", "naklon": 0 }, + "2866": { "label": "15/28", "naklon": 0 }, + "3546": { "label": "15/28/1", "naklon": 0 }, + "4146": { "label": "15/29", "naklon": 0 }, + "3001": { "label": "15/29/1", "naklon": 0 }, + "2835": { "label": "15/30", "naklon": 0 }, + "2874": { "label": "15/31", "naklon": 0 }, + "2852": { "label": "15/32", "naklon": 0 }, + "2851": { "label": "15/33", "naklon": 0 }, + "3560": { "label": "15/33/1", "naklon": 0 }, + "2858": { "label": "15/34", "naklon": 0 }, + "4306": { "label": "15/34/1", "naklon": 0 }, + "2856": { "label": "15/35", "naklon": 0 }, + "2847": { "label": "15/36", "naklon": 0 }, + "3556": { "label": "15/36/1", "naklon": 0 }, + "3950": { "label": "15/37", "naklon": 0 }, + "2848": { "label": "15/38", "naklon": 0 }, + "2863": { "label": "15/39", "naklon": 0 }, + "4313": { "label": "15/39/1", "naklon": 0 }, + "2873": { "label": "15/40", "naklon": 0 }, + "2984": { "label": "15/40/1", "naklon": 0 }, + "2854": { "label": "15/41", "naklon": 0 }, + "2859": { "label": "15/42", "naklon": 0 }, + "2872": { "label": "15/43", "naklon": 0 }, + "2849": { "label": "15/44", "naklon": 0 }, + "2864": { "label": "15/45", "naklon": 0 }, + "3553": { "label": "15/46", "naklon": null }, + "3021": { "label": "15/47", "naklon": null }, + "3008": { "label": "15/47/1", "naklon": null }, + "3017": { "label": "15/48", "naklon": null }, + "3014": { "label": "15/49", "naklon": null }, + "2981": { "label": "15/50", "naklon": null }, + "3020": { "label": "15/51", "naklon": null }, + "3027": { "label": "15/52", "naklon": null }, + "3006": { "label": "15/53", "naklon": null }, + "3012": { "label": "15/54", "naklon": null }, + "2738": { "label": "15/55", "naklon": 0 }, + "2725": { "label": "15/56", "naklon": 0 }, + "3016": { "label": "15/57", "naklon": null }, + "3005": { "label": "15/58", "naklon": null }, + "3009": { "label": "15/58/1", "naklon": null }, + "3010": { "label": "15/59", "naklon": 0 }, + "3538": { "label": "15/59/1", "naklon": 0 }, + "4145": { "label": "15/59/2", "naklon": 0 }, + "2713": { "label": "15/60", "naklon": 0 }, + "2789": { "label": "15/61", "naklon": 0 }, + "2736": { "label": "15/62", "naklon": 0 }, + "2739": { "label": "15/63", "naklon": 0 }, + "4346": { "label": "15/64", "naklon": 0 }, + "2731": { "label": "15/65", "naklon": 0 }, + "2818": { "label": "15/66", "naklon": 0 }, + "3557": { "label": "15/66/1", "naklon": 0 }, + "2822": { "label": "15/67", "naklon": 0 }, + "2833": { "label": "15/68", "naklon": 0 }, + "2834": { "label": "15/69", "naklon": 0 }, + "3097": { "label": "15/70", "naklon": 0 }, + "2824": { "label": "15/71", "naklon": 0 }, + "2828": { "label": "15/72", "naklon": 0 }, + "2600": { "label": "15/73", "naklon": 0 }, + "4314": { "label": "15/73/1", "naklon": 0 }, + "2832": { "label": "15/74", "naklon": 0 }, + "4360": { "label": "15/75", "naklon": 0 }, + "2846": { "label": "15/76", "naklon": 0 }, + "2584": { "label": "15/77", "naklon": 0 }, + "2843": { "label": "15/78", "naklon": 0 }, + "4308": { "label": "15/78/1", "naklon": 0 }, + "4144": { "label": "15/79", "naklon": null }, + "2844": { "label": "15/80", "naklon": 0 }, + "2842": { "label": "15/81", "naklon": 0 }, + "2838": { "label": "15/82", "naklon": 0 }, + "2837": { "label": "15/83", "naklon": null }, + "3555": { "label": "15/83/1", "naklon": null }, + "2839": { "label": "15/84", "naklon": 0 }, + "2830": { "label": "15/85", "naklon": 0 }, + "4066": { "label": "15/86", "naklon": 0 }, + "2836": { "label": "15/87", "naklon": 0 }, + "2911": { "label": "15/88", "naklon": 0 }, + "2825": { "label": "15/89", "naklon": 0 }, + "2811": { "label": "15/90", "naklon": 0 }, + "3740": { "label": "15/94", "naklon": 15 }, + "2734": { "label": "15/95", "naklon": 15 }, + "3105": { "label": "15/96", "naklon": 15 }, + "2732": { "label": "15/97", "naklon": 15 }, + "2727": { "label": "15/98", "naklon": 15 }, + "2735": { "label": "15/99", "naklon": 15 }, + "3926": { "label": "15/100", "naklon": 15 }, + "2918": { "label": "15/101", "naklon": 0 }, + "2705": { "label": "15/102", "naklon": 10 }, + "2708": { "label": "15/103", "naklon": 10 }, + "2721": { "label": "15/104", "naklon": 10 }, + "2719": { "label": "15/105", "naklon": 10 }, + "2919": { "label": "15/106", "naklon": 10 }, + "3101": { "label": "15/107", "naklon": 10 }, + "2853": { "label": "15/108", "naklon": 10 }, + "2715": { "label": "15/109", "naklon": 10 }, + "2712": { "label": "15/110", "naklon": 0 }, + "2711": { "label": "15/111", "naklon": 0 }, + "2709": { "label": "15/112", "naklon": 0 }, + "2710": { "label": "15/113", "naklon": 0 }, + "2907": { "label": "15/114", "naklon": 0 }, + "2906": { "label": "15/115", "naklon": 0 }, + "2908": { "label": "15/116", "naklon": 0 }, + "2901": { "label": "15/117", "naklon": 0 }, + "2913": { "label": "15/118", "naklon": 0 }, + "3656": { "label": "15/119", "naklon": 0 }, + "2781": { "label": "15/120", "naklon": 0 }, + "2802": { "label": "15/121", "naklon": 0 }, + "2791": { "label": "15/122", "naklon": 0 }, + "2783": { "label": "15/123", "naklon": 0 }, + "2794": { "label": "15/124", "naklon": 0 }, + "3139": { "label": "15/125", "naklon": 0 }, + "3229": { "label": "15/126", "naklon": 5 }, + "3239": { "label": "15/127", "naklon": 5 }, + "3230": { "label": "15/128", "naklon": 5 }, + "4016": { "label": "15/129", "naklon": null }, + "3608": { "label": "16/16A", "naklon": 0 }, + "4151": { "label": "16/16B", "naklon": 0 }, + "3710": { "label": "16/1", "naklon": 0 }, + "3726": { "label": "16/2", "naklon": 0 }, + "3743": { "label": "16/3", "naklon": 0 }, + "3724": { "label": "16/4", "naklon": 0 }, + "3712": { "label": "16/5", "naklon": 0 }, + "3739": { "label": "16/6", "naklon": 0 }, + "3742": { "label": "16/7", "naklon": 0 }, + "3731": { "label": "16/8", "naklon": 0 }, + "3727": { "label": "16/9", "naklon": 0 }, + "3729": { "label": "16/10", "naklon": 0 }, + "3736": { "label": "16/11", "naklon": 0 }, + "3713": { "label": "16/12", "naklon": 0 }, + "3715": { "label": "16/13", "naklon": 0 }, + "3733": { "label": "16/14", "naklon": 0 }, + "3732": { "label": "16/15", "naklon": 0 }, + "3634": { "label": "16/17", "naklon": 0 }, + "3610": { "label": "16/18", "naklon": 0 }, + "3626": { "label": "16/19", "naklon": 0 }, + "3618": { "label": "16/20", "naklon": 0 }, + "3619": { "label": "16/21", "naklon": 0 }, + "3628": { "label": "16/22", "naklon": 0 }, + "3615": { "label": "16/23", "naklon": 0 }, + "3609": { "label": "16/24", "naklon": 0 }, + "3606": { "label": "16/25", "naklon": 0 }, + "3624": { "label": "16/26", "naklon": 0 }, + "3627": { "label": "16/27", "naklon": 0 }, + "3607": { "label": "16/28", "naklon": 0 }, + "4370": { "label": "16/29", "naklon": 0 }, + "3692": { "label": "16/30", "naklon": 0 }, + "3614": { "label": "16/31", "naklon": 0 }, + "3623": { "label": "16/32", "naklon": 0 }, + "4373": { "label": "16/33", "naklon": 0 }, + "3620": { "label": "16/34", "naklon": 0 }, + "3685": { "label": "16/35", "naklon": 0 }, + "3616": { "label": "16/36", "naklon": 0 }, + "3686": { "label": "16/37", "naklon": 0 }, + "3688": { "label": "16/38", "naklon": 0 }, + "3684": { "label": "16/39", "naklon": 0 }, + "3825": { "label": "16/40", "naklon": 0 }, + "3865": { "label": "16/41", "naklon": 0 }, + "3824": { "label": "16/42", "naklon": 0 }, + "3871": { "label": "16/43", "naklon": 0 }, + "3801": { "label": "16/44", "naklon": 0 }, + "3862": { "label": "16/45", "naklon": 0 }, + "3876": { "label": "16/46", "naklon": 0 }, + "3861": { "label": "16/47", "naklon": 0 }, + "4215": { "label": "16/48", "naklon": 0 }, + "3605": { "label": "16/49", "naklon": 10 }, + "3603": { "label": "16/50", "naklon": 10 }, + "3592": { "label": "16/51", "naklon": 10 }, + "3598": { "label": "16/52", "naklon": 10 }, + "3594": { "label": "16/53", "naklon": 10 }, + "3593": { "label": "16/54", "naklon": 10 }, + "3630": { "label": "16/55", "naklon": 10 }, + "3763": { "label": "16/56", "naklon": 10 }, + "3746": { "label": "16/57", "naklon": 10 }, + "3699": { "label": "16/58", "naklon": 0 }, + "3698": { "label": "16/59", "naklon": 0 }, + "3709": { "label": "16/60", "naklon": null }, + "3708": { "label": "16/61", "naklon": 0 }, + "3703": { "label": "16/62", "naklon": null }, + "3700": { "label": "16/63", "naklon": 0 }, + "3701": { "label": "16/64", "naklon": null }, + "3704": { "label": "16/65", "naklon": 0 }, + "3707": { "label": "16/66", "naklon": null }, + "3810": { "label": "16/67", "naklon": 0 }, + "4208": { "label": "16/68", "naklon": null }, + "3867": { "label": "16/69", "naklon": 0 }, + "4372": { "label": "16/70", "naklon": null }, + "3881": { "label": "16/71", "naklon": 0 }, + "4204": { "label": "16/72", "naklon": null }, + "3869": { "label": "16/73", "naklon": 0 }, + "4202": { "label": "16/74", "naklon": null }, + "3830": { "label": "16/75", "naklon": 0 }, + "3870": { "label": "16/76", "naklon": null }, + "3964": { "label": "16/77", "naklon": 0 }, + "3849": { "label": "16/78", "naklon": 0 }, + "3694": { "label": "16/79", "naklon": null }, + "3717": { "label": "16/80", "naklon": 0 }, + "3877": { "label": "16/81", "naklon": null }, + "3755": { "label": "16/82", "naklon": 0 }, + "3725": { "label": "16/83", "naklon": null }, + "3716": { "label": "16/84", "naklon": 0 }, + "3696": { "label": "16/85", "naklon": null }, + "3702": { "label": "16/86", "naklon": 0 }, + "3706": { "label": "16/87", "naklon": null }, + "3850": { "label": "16/88", "naklon": 0 }, + "3848": { "label": "16/89", "naklon": null }, + "3737": { "label": "16/90", "naklon": null }, + "3705": { "label": "16/91", "naklon": 0 }, + "3723": { "label": "16/92", "naklon": null }, + "3842": { "label": "16/93", "naklon": 0 }, + "3735": { "label": "16/94", "naklon": null }, + "3719": { "label": "16/95", "naklon": 0 }, + "3697": { "label": "16/96", "naklon": 0 }, + "3711": { "label": "16/97", "naklon": 0 }, + "4107": { "label": "16/98", "naklon": null }, + "4112": { "label": "16/99", "naklon": 5 }, + "4106": { "label": "16/100", "naklon": 5 }, + "4111": { "label": "16/101", "naklon": 5 }, + "4091": { "label": "16/102", "naklon": null }, + "4104": { "label": "16/103", "naklon": 5 }, + "4094": { "label": "16/104", "naklon": null }, + "4089": { "label": "16/105", "naklon": 5 }, + "4095": { "label": "16/106", "naklon": null }, + "4102": { "label": "16/107", "naklon": 5 }, + "4105": { "label": "16/108", "naklon": null }, + "3859": { "label": "16/109", "naklon": null }, + "4090": { "label": "16/110", "naklon": 5 }, + "4110": { "label": "16/111", "naklon": null }, + "4097": { "label": "16/112", "naklon": 5 }, + "4099": { "label": "16/113", "naklon": null }, + "4096": { "label": "16/114", "naklon": null }, + "4101": { "label": "16/115", "naklon": 5 }, + "4109": { "label": "16/116", "naklon": null }, + "4092": { "label": "16/117", "naklon": 5 }, + "3631": { "label": "16/118", "naklon": null }, + "3632": { "label": "16/119", "naklon": 0 }, + "3641": { "label": "16/120", "naklon": null }, + "3638": { "label": "16/121", "naklon": 0 }, + "3637": { "label": "16/122", "naklon": null }, + "4142": { "label": "16/123", "naklon": null }, + "4147": { "label": "16/124", "naklon": 5 }, + "4139": { "label": "16/125", "naklon": 5 }, + "3172": { "label": "20/30A", "naklon": 2 }, + "3164": { "label": "20/30B", "naklon": 2 }, + "3247": { "label": "20/1", "naklon": 10 }, + "3296": { "label": "20/2", "naklon": 10 }, + "3246": { "label": "20/3", "naklon": 10 }, + "3270": { "label": "20/4", "naklon": 10 }, + "3294": { "label": "20/5", "naklon": 10 }, + "3298": { "label": "20/6", "naklon": 10 }, + "3297": { "label": "20/7", "naklon": 10 }, + "3293": { "label": "20/8", "naklon": 10 }, + "3299": { "label": "20/9", "naklon": 10 }, + "3295": { "label": "20/10", "naklon": 10 }, + "3244": { "label": "20/11", "naklon": 10 }, + "3249": { "label": "20/12", "naklon": 10 }, + "3268": { "label": "20/13", "naklon": 10 }, + "3245": { "label": "20/14", "naklon": 10 }, + "3278": { "label": "20/15", "naklon": 10 }, + "3280": { "label": "20/16", "naklon": 10 }, + "3292": { "label": "20/17", "naklon": 10 }, + "3287": { "label": "20/18", "naklon": 10 }, + "3282": { "label": "20/19", "naklon": 10 }, + "3273": { "label": "20/20", "naklon": 0 }, + "3157": { "label": "20/21", "naklon": 0 }, + "3283": { "label": "20/22", "naklon": 0 }, + "3159": { "label": "20/23", "naklon": 0 }, + "3289": { "label": "20/24", "naklon": 0 }, + "3163": { "label": "20/25", "naklon": 0 }, + "3126": { "label": "20/26", "naklon": 0 }, + "3171": { "label": "20/27", "naklon": 0 }, + "3162": { "label": "20/28", "naklon": 0 }, + "3279": { "label": "20/29", "naklon": 10 }, + "3173": { "label": "20/31", "naklon": 0 }, + "3127": { "label": "20/32", "naklon": 0 }, + "3131": { "label": "20/33", "naklon": 0 }, + "3129": { "label": "20/34", "naklon": 0 }, + "3276": { "label": "20/35", "naklon": 2 }, + "3290": { "label": "20/36", "naklon": 2 }, + "3132": { "label": "20/37", "naklon": 0 }, + "3138": { "label": "20/38", "naklon": 0 }, + "3272": { "label": "20/39", "naklon": 0 }, + "3291": { "label": "20/40", "naklon": 0 }, + "3277": { "label": "20/41", "naklon": 10 }, + "3286": { "label": "20/42", "naklon": 10 }, + "3281": { "label": "20/43", "naklon": 10 }, + "3288": { "label": "20/44", "naklon": 10 }, + "3284": { "label": "20/45", "naklon": 10 }, + "3167": { "label": "20/46", "naklon": 10 }, + "3872": { "label": "20/47", "naklon": 0 }, + "3124": { "label": "20/48", "naklon": 0 }, + "3133": { "label": "20/49", "naklon": 0 }, + "3158": { "label": "20/50", "naklon": 0 }, + "3169": { "label": "20/51", "naklon": 0 }, + "3146": { "label": "20/52", "naklon": 0 }, + "3160": { "label": "20/53", "naklon": 0 }, + "3248": { "label": "20/54", "naklon": 0 }, + "3156": { "label": "20/55", "naklon": 0 }, + "3161": { "label": "20/56", "naklon": 0 }, + "3170": { "label": "20/57", "naklon": 0 }, + "3168": { "label": "20/58", "naklon": 0 }, + "3125": { "label": "20/59", "naklon": 0 }, + "3166": { "label": "20/60", "naklon": 0 }, + "3130": { "label": "20/61", "naklon": 0 }, + "3563": { "label": "20/62", "naklon": 0 }, + "3550": { "label": "20/63", "naklon": null }, + "3269": { "label": "20/67", "naklon": 0 }, + "2921": { "label": "21/1", "naklon": 0 }, + "2707": { "label": "21/2", "naklon": 0 }, + "2723": { "label": "21/3", "naklon": 0 }, + "2716": { "label": "21/4", "naklon": 0 }, + "2717": { "label": "21/5", "naklon": 0 }, + "2720": { "label": "21/6", "naklon": 0 }, + "2722": { "label": "21/7", "naklon": 0 }, + "2718": { "label": "21/8", "naklon": 0 }, + "2724": { "label": "21/9", "naklon": 0 }, + "2742": { "label": "21/10", "naklon": 0 }, + "2743": { "label": "21/11", "naklon": 0 }, + "2733": { "label": "21/12", "naklon": 0 }, + "2903": { "label": "21/14", "naklon": 0 }, + "2917": { "label": "21/15", "naklon": 0 }, + "2897": { "label": "21/16", "naklon": 0 }, + "2914": { "label": "21/17", "naklon": 0 }, + "2898": { "label": "21/18", "naklon": 0 }, + "2773": { "label": "21/19", "naklon": 0 }, + "2895": { "label": "21/20", "naklon": 0 }, + "2896": { "label": "21/21", "naklon": 0 }, + "2771": { "label": "21/22", "naklon": 0 }, + "2772": { "label": "21/23", "naklon": 0 }, + "2793": { "label": "21/24", "naklon": 0 }, + "2902": { "label": "21/25", "naklon": 0 }, + "2910": { "label": "21/26", "naklon": 0 }, + "2909": { "label": "21/27", "naklon": 0 }, + "2920": { "label": "21/28", "naklon": 0 }, + "2916": { "label": "21/29", "naklon": 0 }, + "2904": { "label": "21/30", "naklon": 0 }, + "2915": { "label": "21/31", "naklon": 0 }, + "2905": { "label": "21/32", "naklon": 0 }, + "2900": { "label": "21/33", "naklon": 0 }, + "2899": { "label": "21/34", "naklon": 0 }, + "2741": { "label": "21/36", "naklon": 0 }, + "2714": { "label": "21/37", "naklon": 0 }, + "2701": { "label": "21/38", "naklon": 0 }, + "2703": { "label": "21/39", "naklon": 0 }, + "2704": { "label": "21/40", "naklon": 0 }, + "2702": { "label": "21/41", "naklon": 0 }, + "2706": { "label": "21/42", "naklon": 0 }, + "2776": { "label": "21/43", "naklon": 0 }, + "2770": { "label": "21/44", "naklon": 0 }, + "2786": { "label": "21/45", "naklon": 0 }, + "2779": { "label": "21/46", "naklon": 0 }, + "2782": { "label": "21/47", "naklon": 0 }, + "2785": { "label": "21/48", "naklon": 0 }, + "2769": { "label": "21/49", "naklon": 0 }, + "3354": { "label": "21/50", "naklon": 0 }, + "2778": { "label": "21/51", "naklon": 0 }, + "2775": { "label": "21/52", "naklon": 0 }, + "2780": { "label": "21/53", "naklon": 0 }, + "2790": { "label": "21/54", "naklon": 0 }, + "2792": { "label": "21/55", "naklon": 0 }, + "2774": { "label": "21/56", "naklon": 0 }, + "2630": { "label": "22/1", "naklon": 0 }, + "2631": { "label": "22/2", "naklon": 0 }, + "2632": { "label": "22/3", "naklon": 0 }, + "2633": { "label": "22/4", "naklon": 0 }, + "2634": { "label": "22/5", "naklon": 0 }, + "2636": { "label": "22/6", "naklon": 0 }, + "4367": { "label": "22/7", "naklon": 0 }, + "2637": { "label": "22/8", "naklon": 0 }, + "2638": { "label": "22/9", "naklon": 0 }, + "2639": { "label": "22/10", "naklon": 0 }, + "2640": { "label": "22/11", "naklon": 0 }, + "2641": { "label": "22/12", "naklon": 0 }, + "2642": { "label": "22/13", "naklon": 0 }, + "2643": { "label": "22/14", "naklon": 0 }, + "2644": { "label": "22/15", "naklon": 0 }, + "2645": { "label": "22/16", "naklon": 0 }, + "2646": { "label": "22/17", "naklon": 0 }, + "2647": { "label": "22/18", "naklon": 0 }, + "2648": { "label": "22/19", "naklon": 0 }, + "2649": { "label": "22/20", "naklon": 0 }, + "2650": { "label": "22/21", "naklon": 0 }, + "2651": { "label": "22/22", "naklon": 0 }, + "4103": { "label": "22/23", "naklon": 0 }, + "2653": { "label": "22/24", "naklon": 0 }, + "2654": { "label": "22/25", "naklon": 0 }, + "2655": { "label": "22/26", "naklon": 0 }, + "2656": { "label": "22/27", "naklon": 0 }, + "2657": { "label": "22/28", "naklon": 0 }, + "2658": { "label": "22/29", "naklon": 0 }, + "2659": { "label": "22/30", "naklon": 0 }, + "2660": { "label": "22/31", "naklon": 0 }, + "2661": { "label": "22/32", "naklon": 0 }, + "3015": { "label": "22/32/1", "naklon": 0 }, + "2662": { "label": "22/33", "naklon": 0 }, + "2663": { "label": "22/34", "naklon": 0 }, + "2664": { "label": "22/35", "naklon": 0 }, + "2665": { "label": "22/36", "naklon": 0 }, + "2666": { "label": "22/37", "naklon": 0 }, + "2667": { "label": "22/38", "naklon": 0 }, + "2668": { "label": "22/39", "naklon": 0 }, + "2669": { "label": "22/40", "naklon": null }, + "2670": { "label": "22/41", "naklon": null }, + "2671": { "label": "22/42", "naklon": null }, + "3087": { "label": "23/9A", "naklon": 10 }, + "3090": { "label": "23/9B", "naklon": 10 }, + "3075": { "label": "23/1", "naklon": 0 }, + "3089": { "label": "23/2", "naklon": 0 }, + "3088": { "label": "23/3", "naklon": 0 }, + "3228": { "label": "23/4", "naklon": 10 }, + "2751": { "label": "23/5", "naklon": 10 }, + "3243": { "label": "23/6", "naklon": 10 }, + "4349": { "label": "23/7", "naklon": 10 }, + "3102": { "label": "23/8", "naklon": 10 }, + "3099": { "label": "23/10", "naklon": 10 }, + "3103": { "label": "23/11", "naklon": 10 }, + "3093": { "label": "23/12", "naklon": 10 }, + "3098": { "label": "23/13", "naklon": 10 }, + "3092": { "label": "23/14", "naklon": 10 }, + "3233": { "label": "23/15", "naklon": 0 }, + "3095": { "label": "23/16", "naklon": 0 }, + "4074": { "label": "23/17", "naklon": 0 }, + "2729": { "label": "23/18", "naklon": 0 }, + "3234": { "label": "23/19", "naklon": 0 }, + "3094": { "label": "23/20", "naklon": 0 }, + "2817": { "label": "23/21", "naklon": 0 }, + "3226": { "label": "23/22", "naklon": 0 }, + "3225": { "label": "23/23", "naklon": 0 }, + "3237": { "label": "23/24", "naklon": 0 }, + "4250": { "label": "23/25", "naklon": 0 }, + "3059": { "label": "23/26", "naklon": 10 }, + "3238": { "label": "23/27", "naklon": 10 }, + "3242": { "label": "23/28", "naklon": 10 }, + "3236": { "label": "23/29", "naklon": 10 }, + "3112": { "label": "23/30", "naklon": 10 }, + "3224": { "label": "23/31", "naklon": 0 }, + "4298": { "label": "23/32", "naklon": 10 }, + "4150": { "label": "23/33", "naklon": 10 }, + "3091": { "label": "23/34", "naklon": 10 }, + "3771": { "label": "25/1", "naklon": 5 }, + "3777": { "label": "25/2", "naklon": 5 }, + "3749": { "label": "25/3", "naklon": 5 }, + "3769": { "label": "25/4", "naklon": 5 }, + "3765": { "label": "25/5", "naklon": 5 }, + "3785": { "label": "25/6", "naklon": 5 }, + "3761": { "label": "25/7", "naklon": 5 }, + "3758": { "label": "25/8", "naklon": 5 }, + "3766": { "label": "25/9", "naklon": 5 }, + "3779": { "label": "25/10", "naklon": 5 }, + "3899": { "label": "25/11", "naklon": 10 }, + "3922": { "label": "25/12", "naklon": 10 }, + "3912": { "label": "25/13", "naklon": 10 }, + "3933": { "label": "25/14", "naklon": 10 }, + "3921": { "label": "25/15", "naklon": 10 }, + "4300": { "label": "25/16", "naklon": 10 }, + "3927": { "label": "25/17", "naklon": 10 }, + "3212": { "label": "25/18", "naklon": 10 }, + "3208": { "label": "25/19", "naklon": 10 }, + "3207": { "label": "25/20", "naklon": 10 }, + "4294": { "label": "25/21", "naklon": 10 }, + "3209": { "label": "25/22", "naklon": 10 }, + "3745": { "label": "25/23", "naklon": 10 }, + "3762": { "label": "25/24", "naklon": 10 }, + "3215": { "label": "25/25", "naklon": 10 }, + "3210": { "label": "25/26", "naklon": 10 }, + "3211": { "label": "25/27", "naklon": 10 }, + "3206": { "label": "25/28", "naklon": 10 }, + "3918": { "label": "25/29", "naklon": 5 }, + "3928": { "label": "25/30", "naklon": 5 }, + "3917": { "label": "25/31", "naklon": 5 }, + "4029": { "label": "25/32", "naklon": 0 }, + "4038": { "label": "25/33", "naklon": 0 }, + "4022": { "label": "25/34", "naklon": 0 }, + "3937": { "label": "25/35", "naklon": 0 }, + "3190": { "label": "25/36", "naklon": 0 }, + "3835": { "label": "25/37", "naklon": 0 }, + "3201": { "label": "25/38", "naklon": 0 }, + "3193": { "label": "25/39", "naklon": 0 }, + "3191": { "label": "25/40", "naklon": 0 }, + "3203": { "label": "25/41", "naklon": 0 }, + "4301": { "label": "25/42", "naklon": 0 }, + "3223": { "label": "25/43", "naklon": 0 }, + "3202": { "label": "25/44", "naklon": 0 }, + "3205": { "label": "25/45", "naklon": 0 }, + "3194": { "label": "25/46", "naklon": 0 }, + "3198": { "label": "25/47", "naklon": 0 }, + "3204": { "label": "25/48", "naklon": 0 }, + "3200": { "label": "25/49", "naklon": 0 }, + "3216": { "label": "25/50", "naklon": 0 }, + "3932": { "label": "25/51", "naklon": 5 }, + "3923": { "label": "25/52", "naklon": 5 }, + "3913": { "label": "25/53", "naklon": 5 }, + "3900": { "label": "25/54", "naklon": 5 }, + "4189": { "label": "25/55", "naklon": 10 }, + "4191": { "label": "25/56", "naklon": 10 }, + "3790": { "label": "25/57", "naklon": 10 }, + "4190": { "label": "25/58", "naklon": 10 }, + "4302": { "label": "25/59", "naklon": 0 }, + "4351": { "label": "25/60", "naklon": 0 }, + "4075": { "label": "25/61", "naklon": 0 }, + "4071": { "label": "25/62", "naklon": 0 }, + "3784": { "label": "25/63", "naklon": 0 }, + "4065": { "label": "25/64", "naklon": 0 }, + "4297": { "label": "25/65", "naklon": 0 }, + "4295": { "label": "25/66", "naklon": 0 }, + "4299": { "label": "25/67", "naklon": 0 }, + "3772": { "label": "25/68", "naklon": 0 }, + "3941": { "label": "25/69", "naklon": 0 }, + "3782": { "label": "25/70", "naklon": 0 }, + "4068": { "label": "25/71", "naklon": 0 }, + "4073": { "label": "25/72", "naklon": 0 }, + "3901": { "label": "25/73", "naklon": 5 }, + "4296": { "label": "25/74", "naklon": 5 }, + "3910": { "label": "25/75", "naklon": 5 }, + "4293": { "label": "25/76", "naklon": 5 }, + "3919": { "label": "25/77", "naklon": 5 }, + "3924": { "label": "25/78", "naklon": 5 }, + "3909": { "label": "25/79", "naklon": 5 }, + "3896": { "label": "25/80", "naklon": 5 }, + "3911": { "label": "25/81", "naklon": 5 }, + "2819": { "label": "25/82", "naklon": 15 }, + "3776": { "label": "25/83", "naklon": 15 }, + "3752": { "label": "25/84", "naklon": 15 }, + "4353": { "label": "25/85", "naklon": 15 }, + "3791": { "label": "25/86", "naklon": 0 }, + "3770": { "label": "25/87", "naklon": 0 }, + "3760": { "label": "25/88", "naklon": 0 }, + "3115": { "label": "25/89", "naklon": 0 }, + "3738": { "label": "25/90", "naklon": 0 }, + "3748": { "label": "25/91", "naklon": 0 }, + "3753": { "label": "25/92", "naklon": 0 }, + "3775": { "label": "25/93", "naklon": 0 }, + "3778": { "label": "25/94", "naklon": 5 }, + "4078": { "label": "25/95", "naklon": 5 }, + "4088": { "label": "25/96", "naklon": 5 }, + "3856": { "label": "25/97", "naklon": 5 }, + "4084": { "label": "25/98", "naklon": 5 }, + "4069": { "label": "25/99", "naklon": 5 }, + "4188": { "label": "25/100", "naklon": 5 }, + "4064": { "label": "25/101", "naklon": 5 }, + "3792": { "label": "25/102", "naklon": 5 }, + "3780": { "label": "25/103", "naklon": 5 }, + "4034": { "label": "25/104", "naklon": 5 }, + "4072": { "label": "25/105", "naklon": 5 }, + "3884": { "label": "25/106", "naklon": 5 }, + "3793": { "label": "25/107", "naklon": 5 }, + "3863": { "label": "25/108", "naklon": 5 }, + "3855": { "label": "25/109", "naklon": 5 }, + "3846": { "label": "33/1", "naklon": 0 }, + "3943": { "label": "33/2", "naklon": 0 }, + "3903": { "label": "33/3", "naklon": 0 }, + "3982": { "label": "33/4", "naklon": 0 }, + "3879": { "label": "33/5", "naklon": 0 }, + "3887": { "label": "33/6", "naklon": 0 }, + "3920": { "label": "33/7", "naklon": 5 }, + "3942": { "label": "33/8", "naklon": 5 }, + "3829": { "label": "33/9", "naklon": null }, + "3452": { "label": "34/79A", "naklon": 6 }, + "3460": { "label": "34/79B", "naklon": 6 }, + "3443": { "label": "34/90A", "naklon": 6 }, + "3445": { "label": "34/90B", "naklon": 6 }, + "3457": { "label": "34/90C", "naklon": 6 }, + "3461": { "label": "34/97A", "naklon": 6 }, + "3463": { "label": "34/97B", "naklon": 6 }, + "3426": { "label": "34/98A", "naklon": 6 }, + "3444": { "label": "34/98B", "naklon": 6 }, + "3453": { "label": "34/99A", "naklon": 6 }, + "3455": { "label": "34/99B", "naklon": 6 }, + "4009": { "label": "34/1", "naklon": 0 }, + "3602": { "label": "34/2", "naklon": 0 }, + "3441": { "label": "34/3", "naklon": 0 }, + "3464": { "label": "34/4", "naklon": 0 }, + "3883": { "label": "34/5", "naklon": 0 }, + "4098": { "label": "34/6", "naklon": 0 }, + "4003": { "label": "34/7", "naklon": 0 }, + "4004": { "label": "34/8", "naklon": 0 }, + "3888": { "label": "34/9", "naklon": 0 }, + "3997": { "label": "34/10", "naklon": 0 }, + "4006": { "label": "34/11", "naklon": 0 }, + "4000": { "label": "34/12", "naklon": 0 }, + "4011": { "label": "34/13", "naklon": 0 }, + "3999": { "label": "34/14", "naklon": 0 }, + "3981": { "label": "34/15", "naklon": 0 }, + "3988": { "label": "34/16", "naklon": 0 }, + "3986": { "label": "34/17", "naklon": 0 }, + "3998": { "label": "34/18", "naklon": 0 }, + "3983": { "label": "34/19", "naklon": 0 }, + "4005": { "label": "34/20", "naklon": 0 }, + "4001": { "label": "34/21", "naklon": 0 }, + "4008": { "label": "34/22", "naklon": 0 }, + "4002": { "label": "34/23", "naklon": 0 }, + "3996": { "label": "34/24", "naklon": 0 }, + "4007": { "label": "34/25", "naklon": 0 }, + "4113": { "label": "34/26", "naklon": 15 }, + "3595": { "label": "34/27", "naklon": 5 }, + "3599": { "label": "34/28", "naklon": 5 }, + "3601": { "label": "34/29", "naklon": 5 }, + "4205": { "label": "34/30", "naklon": 0 }, + "3987": { "label": "34/31", "naklon": null }, + "4214": { "label": "34/32", "naklon": 0 }, + "4226": { "label": "34/33", "naklon": 0 }, + "4209": { "label": "34/34", "naklon": 0 }, + "4201": { "label": "34/35", "naklon": 0 }, + "3440": { "label": "34/36", "naklon": 0 }, + "3465": { "label": "34/37", "naklon": 0 }, + "3446": { "label": "34/38", "naklon": 0 }, + "4039": { "label": "34/39", "naklon": 5 }, + "4057": { "label": "34/40", "naklon": 5 }, + "3985": { "label": "34/41", "naklon": 0 }, + "3882": { "label": "34/42", "naklon": 0 }, + "4040": { "label": "34/43", "naklon": 5 }, + "3231": { "label": "34/44", "naklon": 0 }, + "3227": { "label": "34/45", "naklon": 0 }, + "3431": { "label": "34/46", "naklon": 0 }, + "4013": { "label": "34/47", "naklon": 0 }, + "4045": { "label": "34/48", "naklon": 0 }, + "3949": { "label": "34/49", "naklon": 0 }, + "3953": { "label": "34/50", "naklon": 0 }, + "3952": { "label": "34/51", "naklon": 0 }, + "3995": { "label": "34/52", "naklon": 0 }, + "3992": { "label": "34/53", "naklon": 0 }, + "4198": { "label": "34/54", "naklon": 0 }, + "3935": { "label": "34/55", "naklon": 0 }, + "4050": { "label": "34/56", "naklon": 0 }, + "4049": { "label": "34/57", "naklon": 0 }, + "4054": { "label": "34/58", "naklon": 0 }, + "3663": { "label": "34/59", "naklon": 6 }, + "3661": { "label": "34/60", "naklon": 6 }, + "3664": { "label": "34/61", "naklon": 6 }, + "3660": { "label": "34/62", "naklon": 6 }, + "3662": { "label": "34/63", "naklon": 6 }, + "3665": { "label": "34/65", "naklon": 6 }, + "3667": { "label": "34/66", "naklon": 6 }, + "3675": { "label": "34/67", "naklon": 6 }, + "3666": { "label": "34/68", "naklon": 6 }, + "3652": { "label": "34/69", "naklon": 6 }, + "3458": { "label": "34/70", "naklon": 6 }, + "4425": { "label": "34/70/1", "naklon": 6 }, + "3459": { "label": "34/71", "naklon": 6 }, + "3435": { "label": "34/72", "naklon": 6 }, + "3448": { "label": "34/73", "naklon": 6 }, + "3451": { "label": "34/74", "naklon": 6 }, + "3442": { "label": "34/75", "naklon": 6 }, + "3449": { "label": "34/76", "naklon": 6 }, + "3450": { "label": "34/77", "naklon": 6 }, + "3433": { "label": "34/78", "naklon": 6 }, + "3432": { "label": "34/80", "naklon": 12 }, + "3470": { "label": "34/81", "naklon": 12 }, + "3438": { "label": "34/82", "naklon": 12 }, + "3439": { "label": "34/83", "naklon": 12 }, + "4028": { "label": "34/84", "naklon": 5 }, + "3596": { "label": "34/85", "naklon": 5 }, + "4021": { "label": "34/86", "naklon": 5 }, + "3437": { "label": "34/87", "naklon": 12 }, + "3428": { "label": "34/88", "naklon": 12 }, + "3430": { "label": "34/89", "naklon": 12 }, + "3454": { "label": "34/91", "naklon": 6 }, + "3492": { "label": "34/92", "naklon": 6 }, + "3462": { "label": "34/93", "naklon": 6 }, + "3427": { "label": "34/94", "naklon": 6 }, + "3434": { "label": "34/95", "naklon": 6 }, + "3456": { "label": "34/96", "naklon": 6 }, + "4307": { "label": "34/98/1", "naklon": 6 }, + "3968": { "label": "35/1", "naklon": 0 }, + "3969": { "label": "35/2", "naklon": 0 }, + "3947": { "label": "35/3", "naklon": 0 }, + "3979": { "label": "35/4", "naklon": 0 }, + "3959": { "label": "35/5", "naklon": 0 }, + "3948": { "label": "35/6", "naklon": 0 }, + "3961": { "label": "35/7", "naklon": 0 }, + "3956": { "label": "35/8", "naklon": 0 }, + "3604": { "label": "35/9", "naklon": 0 }, + "3944": { "label": "35/10", "naklon": 0 }, + "3960": { "label": "35/11", "naklon": 0 }, + "3958": { "label": "35/12", "naklon": 0 }, + "4036": { "label": "35/13", "naklon": 5 }, + "3893": { "label": "35/18", "naklon": 5 }, + "4108": { "label": "35/19", "naklon": 5 }, + "4017": { "label": "35/20", "naklon": 5 }, + "3963": { "label": "35/21", "naklon": 0 }, + "3658": { "label": "35/22", "naklon": 0 }, + "3975": { "label": "35/23", "naklon": 0 }, + "3980": { "label": "35/24", "naklon": 0 }, + "4012": { "label": "35/25", "naklon": 0 }, + "3655": { "label": "35/26", "naklon": 0 }, + "3962": { "label": "35/27", "naklon": 0 }, + "3945": { "label": "35/28", "naklon": 0 }, + "3569": { "label": "35/29", "naklon": 0 }, + "3429": { "label": "35/30", "naklon": 0 }, + "3657": { "label": "35/31", "naklon": 0 }, + "3646": { "label": "35/32", "naklon": 0 }, + "3622": { "label": "35/33", "naklon": 0 }, + "3612": { "label": "35/34", "naklon": 0 }, + "3955": { "label": "35/35", "naklon": 0 }, + "3878": { "label": "35/37", "naklon": 0 }, + "3965": { "label": "35/38", "naklon": 0 }, + "3970": { "label": "35/39", "naklon": 0 }, + "3611": { "label": "35/40", "naklon": 0 }, + "2635": { "label": "35/41", "naklon": 0 }, + "3978": { "label": "35/42", "naklon": 0 }, + "4213": { "label": "35/43", "naklon": 0 }, + "3984": { "label": "35/44", "naklon": 0 }, + "4218": { "label": "35/45", "naklon": 0 }, + "3973": { "label": "35/46", "naklon": 0 }, + "3974": { "label": "35/47", "naklon": 0 }, + "3759": { "label": "35/48", "naklon": 0 }, + "3844": { "label": "35/49", "naklon": 0 }, + "3804": { "label": "35/50", "naklon": 0 }, + "3831": { "label": "35/51", "naklon": 0 }, + "3643": { "label": "35/52", "naklon": 0 }, + "3966": { "label": "35/53", "naklon": 0 }, + "3971": { "label": "35/54", "naklon": 0 }, + "3650": { "label": "35/55", "naklon": 6 }, + "3651": { "label": "35/56", "naklon": 6 }, + "3669": { "label": "35/57", "naklon": 6 }, + "3648": { "label": "35/58", "naklon": 6 }, + "3645": { "label": "35/59", "naklon": 6 }, + "3659": { "label": "35/60", "naklon": 6 }, + "3647": { "label": "35/61", "naklon": 6 }, + "3644": { "label": "35/62", "naklon": 6 }, + "3671": { "label": "35/63", "naklon": 6 }, + "3682": { "label": "35/64", "naklon": 6 }, + "3672": { "label": "35/65", "naklon": 6 }, + "3683": { "label": "35/66", "naklon": 6 }, + "3673": { "label": "35/67", "naklon": 6 }, + "3674": { "label": "35/68", "naklon": 6 }, + "3679": { "label": "35/69", "naklon": 6 }, + "3649": { "label": "35/70", "naklon": 6 }, + "3687": { "label": "35/71", "naklon": 6 }, + "3677": { "label": "35/72", "naklon": 6 }, + "3690": { "label": "35/73", "naklon": 6 }, + "3691": { "label": "35/74", "naklon": 6 }, + "3676": { "label": "35/75", "naklon": 6 }, + "3680": { "label": "35/76", "naklon": 6 }, + "3668": { "label": "35/77", "naklon": 6 }, + "3681": { "label": "35/78", "naklon": 6 }, + "3670": { "label": "35/79", "naklon": 6 }, + "3689": { "label": "35/80", "naklon": 6 }, + "3678": { "label": "35/81", "naklon": 6 }, + "3693": { "label": "35/82", "naklon": 6 }, + "3654": { "label": "35/83", "naklon": null }, + "4086": { "label": "36/1", "naklon": 0 }, + "4085": { "label": "36/2", "naklon": 0 }, + "4083": { "label": "36/3", "naklon": 0 }, + "4087": { "label": "36/4", "naklon": 0 }, + "4077": { "label": "36/5", "naklon": 0 }, + "4082": { "label": "36/6", "naklon": 0 }, + "4186": { "label": "36/7", "naklon": 0 }, + "4206": { "label": "36/8", "naklon": 0 }, + "4080": { "label": "36/9", "naklon": 0 }, + "4081": { "label": "36/10", "naklon": 0 }, + "4210": { "label": "36/11", "naklon": 0 }, + "4079": { "label": "36/12", "naklon": 0 }, + "4076": { "label": "36/13", "naklon": 0 }, + "3852": { "label": "36/14", "naklon": 0 }, + "2813": { "label": "36/15", "naklon": 0 }, + "4219": { "label": "36/16", "naklon": 0 }, + "3104": { "label": "37/1A", "naklon": 15 }, + "3121": { "label": "37/1B", "naklon": 15 }, + "3113": { "label": "37/2", "naklon": 10 }, + "3118": { "label": "37/3", "naklon": 10 }, + "3111": { "label": "37/4", "naklon": 10 }, + "4020": { "label": "37/5", "naklon": 10 }, + "3119": { "label": "37/6", "naklon": 10 }, + "3110": { "label": "37/7", "naklon": 10 }, + "3108": { "label": "37/8", "naklon": 10 }, + "3107": { "label": "37/12", "naklon": 0 }, + "3199": { "label": "37/13", "naklon": 0 }, + "3120": { "label": "37/14", "naklon": 0 }, + "3122": { "label": "37/15", "naklon": 0 }, + "3908": { "label": "37/16", "naklon": 0 }, + "3114": { "label": "37/17", "naklon": 0 }, + "3105": { "label": "37/18", "naklon": 0 }, + "3116": { "label": "37/19", "naklon": 0 }, + "3106": { "label": "37/20", "naklon": 0 }, + "2887": { "label": "37/21", "naklon": 5 }, + "2888": { "label": "37/22", "naklon": 5 }, + "2877": { "label": "37/23", "naklon": 5 }, + "2891": { "label": "37/24", "naklon": 5 }, + "2886": { "label": "37/25", "naklon": 5 }, + "2892": { "label": "37/26", "naklon": 5 }, + "2882": { "label": "37/27", "naklon": 5 }, + "2883": { "label": "37/28", "naklon": 5 }, + "2876": { "label": "37/29", "naklon": 5 }, + "3109": { "label": "37/30", "naklon": 5 }, + "4152": { "label": "37/31", "naklon": 5 }, + "3117": { "label": "37/32", "naklon": 5 }, + "2870": { "label": "37/33", "naklon": 5 }, + "2867": { "label": "37/34", "naklon": 0 }, + "2865": { "label": "37/35", "naklon": 0 }, + "3096": { "label": "37/36", "naklon": 0 }, + "2871": { "label": "37/37", "naklon": 0 }, + "2884": { "label": "37/38", "naklon": 0 }, + "2855": { "label": "37/39", "naklon": 0 }, + "2878": { "label": "37/40", "naklon": 0 }, + "2889": { "label": "37/41", "naklon": 0 }, + "2879": { "label": "37/42", "naklon": 0 }, + "2850": { "label": "37/43", "naklon": 0 }, + "2894": { "label": "37/44", "naklon": 0 }, + "2880": { "label": "37/45", "naklon": 0 }, + "2893": { "label": "37/46", "naklon": 0 }, + "2890": { "label": "37/47", "naklon": 0 }, + "4355": { "label": "37/48", "naklon": 0 }, + "2885": { "label": "37/49", "naklon": 0 }, + "2875": { "label": "37/50", "naklon": 0 }, + "3486": { "label": "38/30A", "naklon": 5 }, + "3714": { "label": "38/30B", "naklon": 0 }, + "3483": { "label": "38/32A", "naklon": 5 }, + "3496": { "label": "38/32B", "naklon": 0 }, + "3487": { "label": "38/35A", "naklon": 5 }, + "3498": { "label": "38/35B", "naklon": 5 }, + "3578": { "label": "38/38A", "naklon": 5 }, + "3508": { "label": "38/38B", "naklon": 5 }, + "3787": { "label": "38/59A", "naklon": 5 }, + "3491": { "label": "38/59B", "naklon": 5 }, + "3568": { "label": "38/1", "naklon": null }, + "3502": { "label": "38/2", "naklon": 0 }, + "3836": { "label": "38/3", "naklon": 0 }, + "3588": { "label": "38/4", "naklon": 0 }, + "3493": { "label": "38/5", "naklon": 0 }, + "3580": { "label": "38/6", "naklon": 0 }, + "3572": { "label": "38/7", "naklon": 0 }, + "3506": { "label": "38/8", "naklon": 0 }, + "3503": { "label": "38/9", "naklon": 0 }, + "3579": { "label": "38/10", "naklon": 0 }, + "3586": { "label": "38/11", "naklon": 0 }, + "3495": { "label": "38/12", "naklon": 5 }, + "3492": { "label": "38/13", "naklon": 5 }, + "3532": { "label": "38/14", "naklon": 5 }, + "3574": { "label": "38/15", "naklon": 5 }, + "4140": { "label": "38/16", "naklon": 5 }, + "3795": { "label": "38/17", "naklon": 5 }, + "3788": { "label": "38/18", "naklon": 5 }, + "3796": { "label": "38/19", "naklon": 5 }, + "3797": { "label": "38/20", "naklon": 5 }, + "3798": { "label": "38/21", "naklon": 5 }, + "3786": { "label": "38/22", "naklon": 5 }, + "4067": { "label": "38/23", "naklon": 5 }, + "3773": { "label": "38/24", "naklon": 5 }, + "3774": { "label": "38/25", "naklon": 5 }, + "3789": { "label": "38/26", "naklon": 5 }, + "3520": { "label": "38/27", "naklon": null }, + "3577": { "label": "38/29", "naklon": 5 }, + "3530": { "label": "38/31", "naklon": null }, + "3488": { "label": "38/33", "naklon": 5 }, + "3505": { "label": "38/34", "naklon": 5 }, + "3497": { "label": "38/36", "naklon": 5 }, + "3490": { "label": "38/37", "naklon": 5 }, + "3585": { "label": "38/39", "naklon": 5 }, + "3582": { "label": "38/40", "naklon": 5 }, + "3507": { "label": "38/41", "naklon": 5 }, + "3484": { "label": "38/42", "naklon": 5 }, + "3501": { "label": "38/43", "naklon": 5 }, + "3581": { "label": "38/44", "naklon": 5 }, + "4192": { "label": "38/45", "naklon": 5 }, + "3576": { "label": "38/46", "naklon": 5 }, + "3489": { "label": "38/47", "naklon": 5 }, + "3573": { "label": "38/48", "naklon": 5 }, + "3504": { "label": "38/49", "naklon": 5 }, + "3794": { "label": "38/50", "naklon": 5 }, + "3485": { "label": "38/51", "naklon": 5 }, + "3482": { "label": "38/52", "naklon": 5 }, + "3575": { "label": "38/53", "naklon": 5 }, + "3499": { "label": "38/54", "naklon": 5 }, + "3494": { "label": "38/55", "naklon": 5 }, + "3583": { "label": "38/56", "naklon": 5 }, + "3570": { "label": "38/57", "naklon": 5 }, + "3500": { "label": "38/58", "naklon": 0 }, + "3510": { "label": "38/63", "naklon": null }, + "3512": { "label": "38/64", "naklon": null }, + "3535": { "label": "38/67", "naklon": null }, + "3531": { "label": "38/68", "naklon": null }, + "3537": { "label": "38/69", "naklon": null }, + "3522": { "label": "39/1", "naklon": 10 }, + "4018": { "label": "39/2", "naklon": 10 }, + "4019": { "label": "39/3", "naklon": 10 }, + "4154": { "label": "39/4", "naklon": 5 }, + "3907": { "label": "39/5", "naklon": 5 }, + "4148": { "label": "39/6", "naklon": 0 }, + "4153": { "label": "39/7", "naklon": 0 }, + "3938": { "label": "39/8", "naklon": 0 }, + "3802": { "label": "39/9", "naklon": 0 }, + "4015": { "label": "39/10", "naklon": 0 }, + "3929": { "label": "39/11", "naklon": 0 }, + "3946": { "label": "39/12", "naklon": 0 }, + "4014": { "label": "39/13", "naklon": 0 }, + "4155": { "label": "39/14", "naklon": 0 }, + "4149": { "label": "39/15", "naklon": 0 }, + "3642": { "label": "39/16", "naklon": 0 }, + "3636": { "label": "39/17", "naklon": 5 }, + "3991": { "label": "39/18", "naklon": 0 }, + "3994": { "label": "39/19", "naklon": 0 }, + "3990": { "label": "39/20", "naklon": 0 }, + "3967": { "label": "39/21", "naklon": 0 }, + "3977": { "label": "39/22", "naklon": 0 }, + "3757": { "label": "39/23", "naklon": 15 }, + "3633": { "label": "39/24", "naklon": 15 }, + "3744": { "label": "39/25", "naklon": 15 }, + "4023": { "label": "39/26", "naklon": 5 }, + "3720": { "label": "39/27", "naklon": 5 }, + "3734": { "label": "39/28", "naklon": 5 }, + "3741": { "label": "39/29", "naklon": 5 }, + "3721": { "label": "39/30", "naklon": 5 }, + "3845": { "label": "39/31", "naklon": 0 }, + "3840": { "label": "39/32", "naklon": 0 }, + "3837": { "label": "39/33", "naklon": null }, + "3839": { "label": "39/34", "naklon": 0 }, + "3542": { "label": "41/1", "naklon": null }, + "3566": { "label": "41/2", "naklon": null }, + "3548": { "label": "41/3", "naklon": null }, + "3515": { "label": "41/4", "naklon": null }, + "3559": { "label": "41/5", "naklon": null }, + "3509": { "label": "41/6", "naklon": null }, + "3524": { "label": "41/7", "naklon": null }, + "3518": { "label": "41/8", "naklon": null }, + "3182": { "label": "41/9", "naklon": null }, + "3187": { "label": "41/10", "naklon": null }, + "3195": { "label": "41/11", "naklon": 0 }, + "3857": { "label": "41/12", "naklon": 0 }, + "3183": { "label": "41/13", "naklon": 0 }, + "3177": { "label": "41/14", "naklon": 0 }, + "3189": { "label": "41/15", "naklon": 0 }, + "3186": { "label": "41/16", "naklon": 0 }, + "3178": { "label": "42/1", "naklon": 0 }, + "3219": { "label": "42/2", "naklon": 0 }, + "3475": { "label": "42/3", "naklon": 0 }, + "3175": { "label": "42/4", "naklon": 0 }, + "3222": { "label": "42/5", "naklon": 0 }, + "3221": { "label": "42/6", "naklon": 0 }, + "3181": { "label": "42/7", "naklon": 0 }, + "3180": { "label": "42/8", "naklon": 0 }, + "3218": { "label": "42/9", "naklon": 0 }, + "3176": { "label": "42/10", "naklon": 0 }, + "3174": { "label": "42/11", "naklon": 0 }, + "3220": { "label": "42/12", "naklon": 0 }, + "3533": { "label": "42/13", "naklon": null }, + "3543": { "label": "42/14", "naklon": null }, + "3554": { "label": "42/15", "naklon": null }, + "3549": { "label": "42/16", "naklon": null }, + "2857": { "label": "43/1", "naklon": 5 }, + "2752": { "label": "43/2", "naklon": 5 }, + "2753": { "label": "43/3", "naklon": 5 }, + "3024": { "label": "43/4", "naklon": 5 }, + "2754": { "label": "43/5", "naklon": 5 }, + "4423": { "label": "43/6", "naklon": 5 }, + "4368": { "label": "43/7", "naklon": 5 }, + "2978": { "label": "43/8", "naklon": 5 }, + "2868": { "label": "43/9", "naklon": 5 }, + "4377": { "label": "43/10", "naklon": 5 }, + "2757": { "label": "43/11", "naklon": 5 }, + "2970": { "label": "43/12", "naklon": 5 }, + "2758": { "label": "43/13", "naklon": 5 }, + "4378": { "label": "43/14", "naklon": 5 }, + "2759": { "label": "43/15", "naklon": 5 }, + "4342": { "label": "43/16", "naklon": 5 }, + "3026": { "label": "43/17", "naklon": null }, + "2986": { "label": "43/18", "naklon": null }, + "4343": { "label": "43/19", "naklon": null }, + "2760": { "label": "43/20", "naklon": null }, + "4379": { "label": "43/21", "naklon": null }, + "2971": { "label": "43/22", "naklon": null }, + "2761": { "label": "43/23", "naklon": null }, + "2762": { "label": "43/24", "naklon": null }, + "4339": { "label": "43/25", "naklon": null }, + "4380": { "label": "43/26", "naklon": null }, + "2975": { "label": "43/27", "naklon": null }, + "3003": { "label": "43/28", "naklon": null }, + "4338": { "label": "43/29", "naklon": null }, + "3002": { "label": "43/30", "naklon": null }, + "4345": { "label": "43/31", "naklon": null }, + "2979": { "label": "43/32", "naklon": null }, + "2989": { "label": "43/33", "naklon": null }, + "2996": { "label": "43/34", "naklon": null }, + "2972": { "label": "43/35", "naklon": null }, + "2988": { "label": "43/36", "naklon": null }, + "4344": { "label": "43/37", "naklon": null }, + "3022": { "label": "43/38", "naklon": null }, + "4341": { "label": "43/39", "naklon": null }, + "2983": { "label": "43/40", "naklon": null }, + "2995": { "label": "43/41", "naklon": null }, + "2763": { "label": "43/42", "naklon": null }, + "2764": { "label": "43/43", "naklon": null }, + "2765": { "label": "43/44", "naklon": null }, + "2766": { "label": "43/45", "naklon": null }, + "2767": { "label": "43/46", "naklon": null }, + "2768": { "label": "43/47", "naklon": null }, + "3018": { "label": "43/48", "naklon": null }, + "2982": { "label": "43/49", "naklon": null }, + "3019": { "label": "43/50", "naklon": 0 }, + "3013": { "label": "43/51", "naklon": null }, + "3007": { "label": "43/52", "naklon": null }, + "2980": { "label": "43/53", "naklon": null }, + "3011": { "label": "43/54", "naklon": null }, + "2672": { "label": "43/55", "naklon": null }, + "2673": { "label": "43/56", "naklon": null }, + "2674": { "label": "43/57", "naklon": null }, + "2675": { "label": "43/58", "naklon": null }, + "2676": { "label": "43/59", "naklon": null }, + "2677": { "label": "43/60", "naklon": null }, + "2678": { "label": "43/61", "naklon": null }, + "2679": { "label": "43/62", "naklon": null }, + "2680": { "label": "43/63", "naklon": null }, + "2840": { "label": "43/64", "naklon": null }, + "2682": { "label": "43/65", "naklon": null }, + "2683": { "label": "43/66", "naklon": null }, + "2684": { "label": "43/67", "naklon": 0 }, + "2685": { "label": "43/68", "naklon": null }, + "2686": { "label": "43/69", "naklon": null }, + "2687": { "label": "43/70", "naklon": null }, + "2688": { "label": "43/71", "naklon": null }, + "2689": { "label": "43/72", "naklon": null }, + "2690": { "label": "43/73", "naklon": null }, + "2691": { "label": "43/74", "naklon": null }, + "2692": { "label": "43/75", "naklon": null }, + "2693": { "label": "43/76", "naklon": 0 }, + "2694": { "label": "43/77", "naklon": null }, + "2695": { "label": "43/78", "naklon": null }, + "2696": { "label": "43/79", "naklon": 0 }, + "2697": { "label": "43/80", "naklon": null }, + "2698": { "label": "43/81", "naklon": 0 }, + "2699": { "label": "43/82", "naklon": null }, + "2700": { "label": "43/83", "naklon": 0 }, + "2744": { "label": "43/84", "naklon": null }, + "2745": { "label": "43/85", "naklon": 0 }, + "2746": { "label": "43/86", "naklon": null }, + "2747": { "label": "43/87", "naklon": 0 }, + "2748": { "label": "43/88", "naklon": null }, + "2749": { "label": "43/89", "naklon": 0 }, + "2841": { "label": "43/90", "naklon": null }, + "4237": { "label": "45/1", "naklon": 5 }, + "4226": { "label": "45/2", "naklon": 5 }, + "4242": { "label": "45/3", "naklon": 5 }, + "4179": { "label": "45/4", "naklon": 5 }, + "4247": { "label": "45/5", "naklon": 5 }, + "4245": { "label": "45/6", "naklon": 5 }, + "3872": { "label": "45/7", "naklon": 5 }, + "4175": { "label": "45/8", "naklon": 5 }, + "4236": { "label": "45/9", "naklon": 5 }, + "4170": { "label": "45/10", "naklon": 5 }, + "4238": { "label": "45/11", "naklon": 5 }, + "4246": { "label": "45/12", "naklon": 5 }, + "4166": { "label": "45/13", "naklon": 5 }, + "4227": { "label": "45/14", "naklon": 5 }, + "4171": { "label": "45/15", "naklon": 5 }, + "4180": { "label": "45/16", "naklon": 5 }, + "4244": { "label": "45/17", "naklon": 5 }, + "4199": { "label": "45/18", "naklon": 5 }, + "4239": { "label": "45/19", "naklon": 5 }, + "4207": { "label": "45/20", "naklon": 5 }, + "4223": { "label": "45/21", "naklon": 5 }, + "4230": { "label": "45/22", "naklon": 5 }, + "4233": { "label": "45/23", "naklon": 5 }, + "4222": { "label": "45/24", "naklon": 5 }, + "4217": { "label": "45/25", "naklon": 5 }, + "4243": { "label": "45/26", "naklon": 5 }, + "4200": { "label": "45/27", "naklon": 5 }, + "4228": { "label": "45/28", "naklon": 5 }, + "4211": { "label": "45/29", "naklon": 5 }, + "4234": { "label": "45/30", "naklon": 5 }, + "4235": { "label": "45/31", "naklon": 5 }, + "4203": { "label": "45/32", "naklon": 5 }, + "4240": { "label": "45/33", "naklon": 5 }, + "4224": { "label": "45/34", "naklon": 5 }, + "4232": { "label": "45/35", "naklon": 5 }, + "4231": { "label": "45/36", "naklon": 5 }, + "4161": { "label": "45/37", "naklon": 5 }, + "4225": { "label": "45/38", "naklon": 5 }, + "4241": { "label": "45/39", "naklon": 5 }, + "4229": { "label": "45/40", "naklon": 5 }, + "4221": { "label": "45/41", "naklon": 5 }, + "4212": { "label": "45/42", "naklon": 5 }, + "4216": { "label": "45/43", "naklon": 5 }, + "3864": { "label": "45/44", "naklon": null }, + "3806": { "label": "46/1", "naklon": 5 }, + "3813": { "label": "46/2", "naklon": 5 }, + "3815": { "label": "46/3", "naklon": 5 }, + "3807": { "label": "46/4", "naklon": 5 }, + "3895": { "label": "46/5", "naklon": 5 }, + "3809": { "label": "46/6", "naklon": 5 }, + "3820": { "label": "46/7", "naklon": 5 }, + "3805": { "label": "46/8", "naklon": 5 }, + "3894": { "label": "46/9", "naklon": 0 }, + "4055": { "label": "46/10", "naklon": 0 }, + "3812": { "label": "46/11", "naklon": 5 }, + "3822": { "label": "46/12", "naklon": 5 }, + "3821": { "label": "46/13", "naklon": 5 }, + "3808": { "label": "46/14", "naklon": 5 }, + "3799": { "label": "46/15", "naklon": 5 }, + "3816": { "label": "46/16", "naklon": 5 }, + "3751": { "label": "46/17", "naklon": 5 }, + "3814": { "label": "46/18", "naklon": 5 }, + "4044": { "label": "46/19", "naklon": 0 }, + "3931": { "label": "46/20", "naklon": 0 }, + "3902": { "label": "46/21", "naklon": 5 }, + "3916": { "label": "46/22", "naklon": 5 }, + "3892": { "label": "46/23", "naklon": 5 }, + "3914": { "label": "46/24", "naklon": 5 }, + "3898": { "label": "46/25", "naklon": 5 }, + "3897": { "label": "46/26", "naklon": 5 }, + "3885": { "label": "46/27", "naklon": 5 }, + "3906": { "label": "46/28", "naklon": 5 }, + "3930": { "label": "46/29", "naklon": 0 }, + "3936": { "label": "46/30", "naklon": 0 }, + "3860": { "label": "46/31", "naklon": 5 }, + "3841": { "label": "46/32", "naklon": 5 }, + "3873": { "label": "46/33", "naklon": 5 }, + "3854": { "label": "46/34", "naklon": 5 }, + "3939": { "label": "46/35", "naklon": 5 }, + "3858": { "label": "46/36", "naklon": 5 }, + "3940": { "label": "46/37", "naklon": 5 }, + "4035": { "label": "46/38", "naklon": 5 }, + "3373": { "label": "47/1", "naklon": 0 }, + "3374": { "label": "47/2", "naklon": 0 }, + "3384": { "label": "47/3", "naklon": 0 }, + "3385": { "label": "47/4", "naklon": 0 }, + "4051": { "label": "48/1", "naklon": 5 }, + "4041": { "label": "48/2", "naklon": 5 }, + "4056": { "label": "48/3", "naklon": 5 }, + "3875": { "label": "48/4", "naklon": 5 }, + "4061": { "label": "48/5", "naklon": 5 }, + "4047": { "label": "48/6", "naklon": 5 }, + "4060": { "label": "48/7", "naklon": 5 }, + "4059": { "label": "48/8", "naklon": 5 }, + "4058": { "label": "48/9", "naklon": 5 }, + "3635": { "label": "48/10", "naklon": 5 }, + "3640": { "label": "48/11", "naklon": 5 }, + "3747": { "label": "48/12", "naklon": 5 }, + "3629": { "label": "48/13", "naklon": 5 }, + "4048": { "label": "48/14", "naklon": 5 }, + "4063": { "label": "48/15", "naklon": 5 }, + "4062": { "label": "48/16", "naklon": 5 }, + "4043": { "label": "48/17", "naklon": 5 }, + "4052": { "label": "48/18", "naklon": 5 }, + "4042": { "label": "48/19", "naklon": 5 }, + "4053": { "label": "48/20", "naklon": 5 }, + "4167": { "label": "50/15A", "naklon": null }, + "4159": { "label": "50/15B", "naklon": null }, + "4183": { "label": "50/1", "naklon": 0 }, + "4157": { "label": "50/2", "naklon": 0 }, + "4160": { "label": "50/3", "naklon": 0 }, + "4173": { "label": "50/4", "naklon": 0 }, + "4177": { "label": "50/5", "naklon": 0 }, + "4174": { "label": "50/6", "naklon": 0 }, + "4178": { "label": "50/7", "naklon": 0 }, + "4195": { "label": "50/8", "naklon": 0 }, + "4169": { "label": "50/9", "naklon": 0 }, + "4162": { "label": "50/10", "naklon": 0 }, + "4158": { "label": "50/11", "naklon": 0 }, + "4182": { "label": "50/12", "naklon": 0 }, + "4194": { "label": "50/13", "naklon": 0 }, + "4184": { "label": "50/14", "naklon": 0 }, + "4197": { "label": "50/16", "naklon": null }, + "4164": { "label": "50/17", "naklon": null }, + "3306": { "label": "50/18", "naklon": null }, + "4168": { "label": "50/19", "naklon": null }, + "4193": { "label": "50/20", "naklon": null }, + "4187": { "label": "50/21", "naklon": null }, + "4163": { "label": "50/22", "naklon": null }, + "4165": { "label": "50/23", "naklon": null }, + "4185": { "label": "50/24", "naklon": null }, + "3904": { "label": "50/25", "naklon": null }, + "2619": { "label": "53/1", "naklon": 0 }, + "2623": { "label": "53/2", "naklon": 0 }, + "2617": { "label": "53/3", "naklon": 0 }, + "2622": { "label": "53/4", "naklon": 0 }, + "2618": { "label": "53/5", "naklon": 0 }, + "2626": { "label": "53/6", "naklon": 0 }, + "2869": { "label": "53/7", "naklon": 0 }, + "2613": { "label": "53/8", "naklon": 0 }, + "2608": { "label": "53/9", "naklon": 0 }, + "2611": { "label": "53/10", "naklon": 0 }, + "2598": { "label": "53/11", "naklon": 0 }, + "3528": { "label": "53/12", "naklon": 0 }, + "3545": { "label": "53/13", "naklon": 0 }, + "2620": { "label": "53/14", "naklon": 0 }, + "2612": { "label": "53/15", "naklon": 0 }, + "2615": { "label": "53/16", "naklon": 0 }, + "3722": { "label": "53/17", "naklon": 0 }, + "2624": { "label": "53/18", "naklon": 0 }, + "2609": { "label": "53/19", "naklon": 0 }, + "2625": { "label": "53/20", "naklon": 0 }, + "2602": { "label": "53/21", "naklon": 0 }, + "2610": { "label": "53/22", "naklon": 0 }, + "2599": { "label": "53/23", "naklon": 0 }, + "2605": { "label": "53/24", "naklon": 0 }, + "2593": { "label": "53/25", "naklon": 0 }, + "3074": { "label": "53/26", "naklon": 0 }, + "2740": { "label": "53/27", "naklon": 0 }, + "2614": { "label": "53/28", "naklon": 0 }, + "2601": { "label": "53/29", "naklon": 0 }, + "4196": { "label": "53/30", "naklon": 0 }, + "2607": { "label": "53/31", "naklon": 0 }, + "2582": { "label": "53/32", "naklon": 0 }, + "2594": { "label": "53/33", "naklon": 0 }, + "2589": { "label": "53/34", "naklon": 0 }, + "2596": { "label": "53/35", "naklon": 0 }, + "2603": { "label": "53/36", "naklon": 0 }, + "2597": { "label": "53/37", "naklon": 0 }, + "2590": { "label": "53/38", "naklon": 0 }, + "2581": { "label": "53/39", "naklon": 0 }, + "2583": { "label": "53/40", "naklon": 0 }, + "2580": { "label": "53/41", "naklon": 0 }, + "2579": { "label": "53/42", "naklon": 0 }, + "2797": { "label": "53/43", "naklon": 0 }, + "2577": { "label": "53/44", "naklon": 0 }, + "2586": { "label": "53/45", "naklon": 0 }, + "2588": { "label": "53/46", "naklon": 0 }, + "2591": { "label": "53/47", "naklon": 0 }, + "2592": { "label": "53/48", "naklon": 0 }, + "2573": { "label": "53/49", "naklon": 0 }, + "2595": { "label": "53/50", "naklon": 0 }, + "2587": { "label": "53/51", "naklon": 0 }, + "2578": { "label": "53/52", "naklon": 0 }, + "2574": { "label": "53/53", "naklon": 0 }, + "2571": { "label": "53/54", "naklon": 0 }, + "2570": { "label": "53/55", "naklon": 0 }, + "2576": { "label": "53/56", "naklon": 0 }, + "2881": { "label": "53/57", "naklon": 0 }, + "2575": { "label": "53/58", "naklon": 0 }, + "2572": { "label": "53/59", "naklon": 0 }, + "2569": { "label": "53/60", "naklon": 0 }, + "4324": { "label": "55/1", "naklon": 0 }, + "4319": { "label": "55/2", "naklon": 0 }, + "4327": { "label": "55/3", "naklon": 0 }, + "4333": { "label": "55/4", "naklon": 0 }, + "4332": { "label": "55/5", "naklon": 0 }, + "4320": { "label": "55/6", "naklon": 0 }, + "4317": { "label": "55/7", "naklon": 0 }, + "4318": { "label": "55/8", "naklon": 0 }, + "4328": { "label": "55/9", "naklon": 0 }, + "4323": { "label": "55/10", "naklon": 0 }, + "4325": { "label": "55/11", "naklon": 0 }, + "4326": { "label": "55/12", "naklon": 0 }, + "4316": { "label": "55/13", "naklon": 0 }, + "4322": { "label": "55/14", "naklon": 0 }, + "4331": { "label": "55/15", "naklon": 0 }, + "4321": { "label": "55/16", "naklon": 0 }, + "4315": { "label": "55/17", "naklon": 0 }, + "4329": { "label": "55/18", "naklon": 0 }, + "4334": { "label": "55/19", "naklon": 0 }, + "4330": { "label": "55/20", "naklon": 0 } +}; + + +let svetlaSorted = [{ "label": "1/3A", "node": 3993, "naklon": 0 }, +{ "label": "1/3B", "node": 3989, "naklon": 15 }, +{ "label": "1/1", "node": 3976, "naklon": 0 }, +{ "label": "1/2", "node": 4181, "naklon": 0 }, +{ "label": "1/4", "node": 4376, "naklon": 15 }, +{ "label": "1/5", "node": 3868, "naklon": 15 }, +{ "label": "1/6", "node": 3728, "naklon": 15 }, +{ "label": "1/7", "node": 3730, "naklon": 0 }, +{ "label": "1/8", "node": 4374, "naklon": 0 }, +{ "label": "1/9", "node": 3718, "naklon": 15 }, +{ "label": "1/10", "node": 4375, "naklon": 15 }, +{ "label": "1/11", "node": 4172, "naklon": 15 }, +{ "label": "1/12", "node": 4176, "naklon": 15 }, +{ "label": "2/1", "node": 3800, "naklon": 5 }, +{ "label": "2/2", "node": 3823, "naklon": 5 }, +{ "label": "2/3", "node": 3905, "naklon": 5 }, +{ "label": "2/4", "node": 3803, "naklon": 5 }, +{ "label": "2/5", "node": 3817, "naklon": 5 }, +{ "label": "2/6", "node": 3818, "naklon": 5 }, +{ "label": "2/7", "node": 3811, "naklon": 5 }, +{ "label": "2/8", "node": 3915, "naklon": 5 }, +{ "label": "2/9", "node": 3843, "naklon": 10 }, +{ "label": "2/10", "node": 3827, "naklon": 10 }, +{ "label": "2/11", "node": 4220, "naklon": 10 }, +{ "label": "2/12", "node": 3826, "naklon": 10 }, +{ "label": "2/13", "node": 3834, "naklon": 10 }, +{ "label": "2/14", "node": 3838, "naklon": 10 }, +{ "label": "2/15", "node": 2823, "naklon": 10 }, +{ "label": "2/16", "node": 3750, "naklon": 10 }, +{ "label": "2/17", "node": 3378, "naklon": 0 }, +{ "label": "2/18", "node": 3376, "naklon": 0 }, +{ "label": "2/19", "node": 3379, "naklon": 0 }, +{ "label": "2/20", "node": 3285, "naklon": 0 }, +{ "label": "2/21", "node": 3382, "naklon": 0 }, +{ "label": "2/22", "node": 3383, "naklon": 0 }, +{ "label": "2/24", "node": 3375, "naklon": 0 }, +{ "label": "2/25", "node": 3381, "naklon": 0 }, +{ "label": "2/26", "node": 3380, "naklon": 0 }, +{ "label": "2/27", "node": 3828, "naklon": 10 }, +{ "label": "2/28", "node": 3377, "naklon": 0 }, +{ "label": "7/1", "node": 3591, "naklon": 0 }, +{ "label": "7/2", "node": 3587, "naklon": 0 }, +{ "label": "7/3", "node": 3468, "naklon": 0 }, +{ "label": "7/4", "node": 3466, "naklon": 0 }, +{ "label": "7/5", "node": 3474, "naklon": 0 }, +{ "label": "7/6", "node": 3481, "naklon": 0 }, +{ "label": "7/7", "node": 3589, "naklon": 0 }, +{ "label": "7/8", "node": 3472, "naklon": 0 }, +{ "label": "7/9", "node": 3473, "naklon": 0 }, +{ "label": "7/10", "node": 3584, "naklon": 0 }, +{ "label": "7/11", "node": 3571, "naklon": 0 }, +{ "label": "7/12", "node": 3476, "naklon": 0 }, +{ "label": "7/13", "node": 3590, "naklon": 0 }, +{ "label": "7/14", "node": 3478, "naklon": 0 }, +{ "label": "7/15", "node": 3471, "naklon": 0 }, +{ "label": "7/16", "node": 3467, "naklon": 0 }, +{ "label": "7/17", "node": 3479, "naklon": 0 }, +{ "label": "7/18", "node": 3480, "naklon": 0 }, +{ "label": "7/19", "node": 3477, "naklon": 0 }, +{ "label": "12/1", "node": 3362, "naklon": 0 }, +{ "label": "12/2", "node": 3355, "naklon": 0 }, +{ "label": "12/3", "node": 3356, "naklon": 0 }, +{ "label": "12/4", "node": 3349, "naklon": 0 }, +{ "label": "12/5", "node": 3357, "naklon": 0 }, +{ "label": "12/6", "node": 3350, "naklon": 0 }, +{ "label": "12/7", "node": 3353, "naklon": 0 }, +{ "label": "12/8", "node": 3539, "naklon": 0 }, +{ "label": "12/9", "node": 3050, "naklon": 0 }, +{ "label": "12/10", "node": 3361, "naklon": 0 }, +{ "label": "12/11", "node": 3360, "naklon": 0 }, +{ "label": "12/12", "node": 3358, "naklon": 0 }, +{ "label": "12/13", "node": 3541, "naklon": 0 }, +{ "label": "12/14", "node": 3551, "naklon": 0 }, +{ "label": "12/15", "node": 3514, "naklon": 0 }, +{ "label": "12/16", "node": 3547, "naklon": 0 }, +{ "label": "12/17", "node": 3562, "naklon": 0 }, +{ "label": "12/18", "node": 3525, "naklon": 0 }, +{ "label": "12/19", "node": 3558, "naklon": 0 }, +{ "label": "12/20", "node": 3511, "naklon": 0 }, +{ "label": "12/21", "node": 3058, "naklon": 0 }, +{ "label": "12/22", "node": 3062, "naklon": 0 }, +{ "label": "12/23", "node": 3070, "naklon": 0 }, +{ "label": "12/24", "node": 3447, "naklon": 0 }, +{ "label": "12/25", "node": 3056, "naklon": 0 }, +{ "label": "12/26", "node": 3057, "naklon": 0 }, +{ "label": "12/27", "node": 3071, "naklon": 0 }, +{ "label": "12/28", "node": 3061, "naklon": 0 }, +{ "label": "12/29", "node": 3069, "naklon": 0 }, +{ "label": "12/30", "node": 3077, "naklon": 0 }, +{ "label": "12/31", "node": 3080, "naklon": 0 }, +{ "label": "12/32", "node": 3081, "naklon": 0 }, +{ "label": "12/33", "node": 3078, "naklon": 0 }, +{ "label": "12/34", "node": 4037, "naklon": 0 }, +{ "label": "12/35", "node": 3067, "naklon": 0 }, +{ "label": "12/36", "node": 3051, "naklon": 0 }, +{ "label": "12/37", "node": 2924, "naklon": 0 }, +{ "label": "12/38", "node": 3060, "naklon": 0 }, +{ "label": "12/39", "node": 3073, "naklon": 0 }, +{ "label": "12/40", "node": 3469, "naklon": 0 }, +{ "label": "12/41", "node": 2923, "naklon": 0 }, +{ "label": "12/42", "node": 2925, "naklon": 0 }, +{ "label": "12/43", "node": 3359, "naklon": 0 }, +{ "label": "12/44", "node": 3055, "naklon": 0 }, +{ "label": "12/45", "node": 2922, "naklon": 0 }, +{ "label": "12/46", "node": 3084, "naklon": 0 }, +{ "label": "12/47", "node": 3064, "naklon": 0 }, +{ "label": "12/48", "node": 3066, "naklon": 0 }, +{ "label": "12/49", "node": 3072, "naklon": 0 }, +{ "label": "13/13A", "node": 3415, "naklon": 0 }, +{ "label": "13/13B", "node": 3409, "naklon": 0 }, +{ "label": "13/13C", "node": 3399, "naklon": 0 }, +{ "label": "13/29A", "node": 3410, "naklon": 0 }, +{ "label": "13/29B", "node": 3407, "naklon": 0 }, +{ "label": "13/34A", "node": 3405, "naklon": 0 }, +{ "label": "13/34B", "node": 3404, "naklon": 0 }, +{ "label": "13/45A", "node": 3392, "naklon": 0 }, +{ "label": "13/45B", "node": 3386, "naklon": 0 }, +{ "label": "13/60A", "node": 3303, "naklon": 3 }, +{ "label": "13/60B", "node": 3302, "naklon": 3 }, +{ "label": "13/70A", "node": 3319, "naklon": 6 }, +{ "label": "13/70B", "node": 3317, "naklon": 6 }, +{ "label": "13/70C", "node": 3326, "naklon": 6 }, +{ "label": "13/73A", "node": 3351, "naklon": 6 }, +{ "label": "13/73B", "node": 3313, "naklon": 6 }, +{ "label": "13/83A", "node": 3316, "naklon": 0 }, +{ "label": "13/83B", "node": 3320, "naklon": 0 }, +{ "label": "13/95A", "node": 3336, "naklon": 0 }, +{ "label": "13/95B", "node": 3323, "naklon": 0 }, +{ "label": "13/98A", "node": 3339, "naklon": 0 }, +{ "label": "13/98B", "node": 3333, "naklon": 0 }, +{ "label": "13/1", "node": 3425, "naklon": 0 }, +{ "label": "13/2", "node": 3419, "naklon": 0 }, +{ "label": "13/3", "node": 3416, "naklon": 0 }, +{ "label": "13/4", "node": 3332, "naklon": 0 }, +{ "label": "13/5", "node": 3422, "naklon": 0 }, +{ "label": "13/6", "node": 3417, "naklon": 0 }, +{ "label": "13/7", "node": 3418, "naklon": 0 }, +{ "label": "13/8", "node": 3424, "naklon": 0 }, +{ "label": "13/9", "node": 3334, "naklon": 0 }, +{ "label": "13/10", "node": 4363, "naklon": 0 }, +{ "label": "13/11", "node": 3423, "naklon": 0 }, +{ "label": "13/12", "node": 3406, "naklon": 0 }, +{ "label": "13/14", "node": 3411, "naklon": 0 }, +{ "label": "13/15", "node": 3412, "naklon": 0 }, +{ "label": "13/16", "node": 3413, "naklon": 0 }, +{ "label": "13/17", "node": 3414, "naklon": 0 }, +{ "label": "13/18", "node": 3391, "naklon": 0 }, +{ "label": "13/19", "node": 3370, "naklon": 0 }, +{ "label": "13/20", "node": 3369, "naklon": 0 }, +{ "label": "13/21", "node": 3408, "naklon": 0 }, +{ "label": "13/22", "node": 3393, "naklon": 0 }, +{ "label": "13/23", "node": 3128, "naklon": 0 }, +{ "label": "13/24", "node": 3197, "naklon": 0 }, +{ "label": "13/25", "node": 4364, "naklon": 0 }, +{ "label": "13/26", "node": 3155, "naklon": 0 }, +{ "label": "13/27", "node": 3196, "naklon": 0 }, +{ "label": "13/28", "node": 3144, "naklon": 0 }, +{ "label": "13/30", "node": 3150, "naklon": 0 }, +{ "label": "13/31", "node": 3390, "naklon": 0 }, +{ "label": "13/32", "node": 3401, "naklon": 0 }, +{ "label": "13/33", "node": 3275, "naklon": 0 }, +{ "label": "13/35", "node": 3371, "naklon": 0 }, +{ "label": "13/36", "node": 3389, "naklon": 0 }, +{ "label": "13/37", "node": 3388, "naklon": 0 }, +{ "label": "13/38", "node": 3365, "naklon": 0 }, +{ "label": "13/39", "node": 3363, "naklon": 0 }, +{ "label": "13/40", "node": 3397, "naklon": 0 }, +{ "label": "13/40/1", "node": 3567, "naklon": 0 }, +{ "label": "13/41", "node": 3387, "naklon": 0 }, +{ "label": "13/42", "node": 3403, "naklon": 0 }, +{ "label": "13/43", "node": 3147, "naklon": 0 }, +{ "label": "13/44", "node": 3141, "naklon": 0 }, +{ "label": "13/46", "node": 3364, "naklon": 0 }, +{ "label": "13/47", "node": 3367, "naklon": 0 }, +{ "label": "13/48", "node": 3368, "naklon": 0 }, +{ "label": "13/49", "node": 3402, "naklon": 0 }, +{ "label": "13/50", "node": 3366, "naklon": 0 }, +{ "label": "13/51", "node": 3395, "naklon": 0 }, +{ "label": "13/52", "node": 3372, "naklon": 0 }, +{ "label": "13/53", "node": 3394, "naklon": 0 }, +{ "label": "13/54", "node": 3308, "naklon": 0 }, +{ "label": "13/54/1", "node": 3847, "naklon": 0 }, +{ "label": "13/55", "node": 3312, "naklon": 3 }, +{ "label": "13/56", "node": 3309, "naklon": 3 }, +{ "label": "13/57", "node": 3311, "naklon": 3 }, +{ "label": "13/58", "node": 3310, "naklon": 3 }, +{ "label": "13/59", "node": 4365, "naklon": 3 }, +{ "label": "13/60/1", "node": 4093, "naklon": 3 }, +{ "label": "13/61", "node": 3304, "naklon": 3 }, +{ "label": "13/62", "node": 3307, "naklon": 3 }, +{ "label": "13/63", "node": 3271, "naklon": 3 }, +{ "label": "13/64", "node": 3301, "naklon": 3 }, +{ "label": "13/65", "node": 4366, "naklon": 3 }, +{ "label": "13/66", "node": 3300, "naklon": 3 }, +{ "label": "13/67", "node": 3185, "naklon": 0 }, +{ "label": "13/68", "node": 3184, "naklon": 0 }, +{ "label": "13/69", "node": 3188, "naklon": 0 }, +{ "label": "13/71", "node": 3343, "naklon": 6 }, +{ "label": "13/71/1", "node": 3819, "naklon": 6 }, +{ "label": "13/71/2", "node": 3880, "naklon": 6 }, +{ "label": "13/72", "node": 3348, "naklon": 6 }, +{ "label": "13/74", "node": 3344, "naklon": 6 }, +{ "label": "13/75", "node": 3346, "naklon": 6 }, +{ "label": "13/75/1", "node": 3597, "naklon": 6 }, +{ "label": "13/76", "node": 3345, "naklon": 6 }, +{ "label": "13/77", "node": 3322, "naklon": 0 }, +{ "label": "13/78", "node": 3325, "naklon": 0 }, +{ "label": "13/78/1", "node": 4310, "naklon": 0 }, +{ "label": "13/79", "node": 3315, "naklon": 0 }, +{ "label": "13/80", "node": 3328, "naklon": 0 }, +{ "label": "13/81", "node": 3321, "naklon": 0 }, +{ "label": "13/82", "node": 3324, "naklon": 0 }, +{ "label": "13/84", "node": 3140, "naklon": 0 }, +{ "label": "13/85", "node": 3153, "naklon": 0 }, +{ "label": "13/86", "node": 3145, "naklon": 0 }, +{ "label": "13/87", "node": 3134, "naklon": 0 }, +{ "label": "13/88", "node": 3151, "naklon": 0 }, +{ "label": "13/89", "node": 3143, "naklon": 0 }, +{ "label": "13/90", "node": 3318, "naklon": 0 }, +{ "label": "13/91", "node": 3347, "naklon": 0 }, +{ "label": "13/94", "node": 3314, "naklon": 0 }, +{ "label": "13/96", "node": 3331, "naklon": 0 }, +{ "label": "13/97", "node": 3327, "naklon": 0 }, +{ "label": "13/99", "node": 3329, "naklon": 0 }, +{ "label": "13/100", "node": 3337, "naklon": 0 }, +{ "label": "13/101", "node": 3330, "naklon": 0 }, +{ "label": "13/102", "node": 3335, "naklon": 0 }, +{ "label": "13/103", "node": 3420, "naklon": 0 }, +{ "label": "13/104", "node": 3421, "naklon": 0 }, +{ "label": "13/105", "node": 4361, "naklon": 0 }, +{ "label": "13/106", "node": 4362, "naklon": 0 }, +{ "label": "13/107", "node": 3526, "naklon": 0 }, +{ "label": "13/108", "node": 4424, "naklon": null }, +{ "label": "13/109", "node": 3561, "naklon": null }, +{ "label": "13/110", "node": 3527, "naklon": null }, +{ "label": "13/111", "node": 3521, "naklon": null }, +{ "label": "13/112", "node": 3552, "naklon": null }, +{ "label": "13/113", "node": 3544, "naklon": null }, +{ "label": "13/114", "node": 3534, "naklon": null }, +{ "label": "13/115", "node": 3516, "naklon": null }, +{ "label": "13/116", "node": 3513, "naklon": null }, +{ "label": "13/117", "node": 3565, "naklon": null }, +{ "label": "13/118", "node": 3866, "naklon": null }, +{ "label": "14/1", "node": 3136, "naklon": 0 }, +{ "label": "14/2", "node": 3137, "naklon": 0 }, +{ "label": "14/3", "node": 3135, "naklon": 0 }, +{ "label": "14/4", "node": 3149, "naklon": 0 }, +{ "label": "14/5", "node": 3142, "naklon": 0 }, +{ "label": "14/6", "node": 3342, "naklon": 0 }, +{ "label": "14/7", "node": 3340, "naklon": 0 }, +{ "label": "14/8", "node": 3152, "naklon": 0 }, +{ "label": "14/9", "node": 3886, "naklon": 0 }, +{ "label": "14/10", "node": 3341, "naklon": null }, +{ "label": "14/11", "node": 3352, "naklon": null }, +{ "label": "15/1", "node": 3396, "naklon": 5 }, +{ "label": "15/2", "node": 2784, "naklon": 5 }, +{ "label": "15/3", "node": 2788, "naklon": 5 }, +{ "label": "15/4", "node": 2801, "naklon": 5 }, +{ "label": "15/5", "node": 2815, "naklon": 5 }, +{ "label": "15/6", "node": 2829, "naklon": 5 }, +{ "label": "15/7", "node": 2796, "naklon": 5 }, +{ "label": "15/8", "node": 2803, "naklon": 5 }, +{ "label": "15/8/1", "node": 4304, "naklon": 5 }, +{ "label": "15/8/2", "node": 4311, "naklon": 5 }, +{ "label": "15/9", "node": 2821, "naklon": 5 }, +{ "label": "15/10", "node": 3400, "naklon": 5 }, +{ "label": "15/11", "node": 2799, "naklon": 5 }, +{ "label": "15/12", "node": 2804, "naklon": 5 }, +{ "label": "15/12/1", "node": 4303, "naklon": 5 }, +{ "label": "15/12/2", "node": 4309, "naklon": 5 }, +{ "label": "15/13", "node": 2806, "naklon": 5 }, +{ "label": "15/14", "node": 2787, "naklon": 5 }, +{ "label": "15/15", "node": 2809, "naklon": 5 }, +{ "label": "15/16", "node": 2814, "naklon": 0 }, +{ "label": "15/17", "node": 3934, "naklon": 0 }, +{ "label": "15/18", "node": 3192, "naklon": 0 }, +{ "label": "15/19", "node": 2812, "naklon": 0 }, +{ "label": "15/20", "node": 4070, "naklon": 0 }, +{ "label": "15/21", "node": 2826, "naklon": 0 }, +{ "label": "15/22", "node": 2808, "naklon": 3 }, +{ "label": "15/23", "node": 2795, "naklon": 3 }, +{ "label": "15/24", "node": 2807, "naklon": 3 }, +{ "label": "15/25", "node": 2831, "naklon": 0 }, +{ "label": "15/26", "node": 2862, "naklon": null }, +{ "label": "15/27", "node": 2861, "naklon": 0 }, +{ "label": "15/28", "node": 2866, "naklon": 0 }, +{ "label": "15/28/1", "node": 3546, "naklon": 0 }, +{ "label": "15/29", "node": 4146, "naklon": 0 }, +{ "label": "15/29/1", "node": 3001, "naklon": 0 }, +{ "label": "15/30", "node": 2835, "naklon": 0 }, +{ "label": "15/31", "node": 2874, "naklon": 0 }, +{ "label": "15/32", "node": 2852, "naklon": 0 }, +{ "label": "15/33", "node": 2851, "naklon": 0 }, +{ "label": "15/33/1", "node": 3560, "naklon": 0 }, +{ "label": "15/34", "node": 2858, "naklon": 0 }, +{ "label": "15/34/1", "node": 4306, "naklon": 0 }, +{ "label": "15/35", "node": 2856, "naklon": 0 }, +{ "label": "15/36", "node": 2847, "naklon": 0 }, +{ "label": "15/36/1", "node": 3556, "naklon": 0 }, +{ "label": "15/37", "node": 3950, "naklon": 0 }, +{ "label": "15/38", "node": 2848, "naklon": 0 }, +{ "label": "15/39", "node": 2863, "naklon": 0 }, +{ "label": "15/39/1", "node": 4313, "naklon": 0 }, +{ "label": "15/40", "node": 2873, "naklon": 0 }, +{ "label": "15/40/1", "node": 2984, "naklon": 0 }, +{ "label": "15/41", "node": 2854, "naklon": 0 }, +{ "label": "15/42", "node": 2859, "naklon": 0 }, +{ "label": "15/43", "node": 2872, "naklon": 0 }, +{ "label": "15/44", "node": 2849, "naklon": 0 }, +{ "label": "15/45", "node": 2864, "naklon": 0 }, +{ "label": "15/46", "node": 3553, "naklon": null }, +{ "label": "15/47", "node": 3021, "naklon": null }, +{ "label": "15/47/1", "node": 3008, "naklon": null }, +{ "label": "15/48", "node": 3017, "naklon": null }, +{ "label": "15/49", "node": 3014, "naklon": null }, +{ "label": "15/50", "node": 2981, "naklon": null }, +{ "label": "15/51", "node": 3020, "naklon": null }, +{ "label": "15/52", "node": 3027, "naklon": null }, +{ "label": "15/53", "node": 3006, "naklon": null }, +{ "label": "15/54", "node": 3012, "naklon": null }, +{ "label": "15/55", "node": 2738, "naklon": 0 }, +{ "label": "15/56", "node": 2725, "naklon": 0 }, +{ "label": "15/57", "node": 3016, "naklon": null }, +{ "label": "15/58", "node": 3005, "naklon": null }, +{ "label": "15/58/1", "node": 3009, "naklon": null }, +{ "label": "15/59", "node": 3010, "naklon": 0 }, +{ "label": "15/59/1", "node": 3538, "naklon": 0 }, +{ "label": "15/59/2", "node": 4145, "naklon": 0 }, +{ "label": "15/60", "node": 2713, "naklon": 0 }, +{ "label": "15/61", "node": 2789, "naklon": 0 }, +{ "label": "15/62", "node": 2736, "naklon": 0 }, +{ "label": "15/63", "node": 2739, "naklon": 0 }, +{ "label": "15/64", "node": 4346, "naklon": 0 }, +{ "label": "15/65", "node": 2731, "naklon": 0 }, +{ "label": "15/66", "node": 2818, "naklon": 0 }, +{ "label": "15/66/1", "node": 3557, "naklon": 0 }, +{ "label": "15/67", "node": 2822, "naklon": 0 }, +{ "label": "15/68", "node": 2833, "naklon": 0 }, +{ "label": "15/69", "node": 2834, "naklon": 0 }, +{ "label": "15/70", "node": 3097, "naklon": 0 }, +{ "label": "15/71", "node": 2824, "naklon": 0 }, +{ "label": "15/72", "node": 2828, "naklon": 0 }, +{ "label": "15/73", "node": 2600, "naklon": 0 }, +{ "label": "15/73/1", "node": 4314, "naklon": 0 }, +{ "label": "15/74", "node": 2832, "naklon": 0 }, +{ "label": "15/75", "node": 4360, "naklon": 0 }, +{ "label": "15/76", "node": 2846, "naklon": 0 }, +{ "label": "15/77", "node": 2584, "naklon": 0 }, +{ "label": "15/78", "node": 2843, "naklon": 0 }, +{ "label": "15/78/1", "node": 4308, "naklon": 0 }, +{ "label": "15/79", "node": 4144, "naklon": null }, +{ "label": "15/80", "node": 2844, "naklon": 0 }, +{ "label": "15/81", "node": 2842, "naklon": 0 }, +{ "label": "15/82", "node": 2838, "naklon": 0 }, +{ "label": "15/83", "node": 2837, "naklon": null }, +{ "label": "15/83/1", "node": 3555, "naklon": null }, +{ "label": "15/84", "node": 2839, "naklon": 0 }, +{ "label": "15/85", "node": 2830, "naklon": 0 }, +{ "label": "15/86", "node": 4066, "naklon": 0 }, +{ "label": "15/87", "node": 2836, "naklon": 0 }, +{ "label": "15/88", "node": 2911, "naklon": 0 }, +{ "label": "15/89", "node": 2825, "naklon": 0 }, +{ "label": "15/90", "node": 2811, "naklon": 0 }, +{ "label": "15/94", "node": 3740, "naklon": 15 }, +{ "label": "15/95", "node": 2734, "naklon": 15 }, +{ "label": "15/96", "node": 3105, "naklon": 15 }, +{ "label": "15/97", "node": 2732, "naklon": 15 }, +{ "label": "15/98", "node": 2727, "naklon": 15 }, +{ "label": "15/99", "node": 2735, "naklon": 15 }, +{ "label": "15/100", "node": 3926, "naklon": 15 }, +{ "label": "15/101", "node": 2918, "naklon": 0 }, +{ "label": "15/102", "node": 2705, "naklon": 10 }, +{ "label": "15/103", "node": 2708, "naklon": 10 }, +{ "label": "15/104", "node": 2721, "naklon": 10 }, +{ "label": "15/105", "node": 2719, "naklon": 10 }, +{ "label": "15/106", "node": 2919, "naklon": 10 }, +{ "label": "15/107", "node": 3101, "naklon": 10 }, +{ "label": "15/108", "node": 2853, "naklon": 10 }, +{ "label": "15/109", "node": 2715, "naklon": 10 }, +{ "label": "15/110", "node": 2712, "naklon": 0 }, +{ "label": "15/111", "node": 2711, "naklon": 0 }, +{ "label": "15/112", "node": 2709, "naklon": 0 }, +{ "label": "15/113", "node": 2710, "naklon": 0 }, +{ "label": "15/114", "node": 2907, "naklon": 0 }, +{ "label": "15/115", "node": 2906, "naklon": 0 }, +{ "label": "15/116", "node": 2908, "naklon": 0 }, +{ "label": "15/117", "node": 2901, "naklon": 0 }, +{ "label": "15/118", "node": 2913, "naklon": 0 }, +{ "label": "15/119", "node": 3656, "naklon": 0 }, +{ "label": "15/120", "node": 2781, "naklon": 0 }, +{ "label": "15/121", "node": 2802, "naklon": 0 }, +{ "label": "15/122", "node": 2791, "naklon": 0 }, +{ "label": "15/123", "node": 2783, "naklon": 0 }, +{ "label": "15/124", "node": 2794, "naklon": 0 }, +{ "label": "15/125", "node": 3139, "naklon": 0 }, +{ "label": "15/126", "node": 3229, "naklon": 5 }, +{ "label": "15/127", "node": 3239, "naklon": 5 }, +{ "label": "15/128", "node": 3230, "naklon": 5 }, +{ "label": "15/129", "node": 4016, "naklon": null }, +{ "label": "16/16A", "node": 3608, "naklon": 0 }, +{ "label": "16/16B", "node": 4151, "naklon": 0 }, +{ "label": "16/1", "node": 3710, "naklon": 0 }, +{ "label": "16/2", "node": 3726, "naklon": 0 }, +{ "label": "16/3", "node": 3743, "naklon": 0 }, +{ "label": "16/4", "node": 3724, "naklon": 0 }, +{ "label": "16/5", "node": 3712, "naklon": 0 }, +{ "label": "16/6", "node": 3739, "naklon": 0 }, +{ "label": "16/7", "node": 3742, "naklon": 0 }, +{ "label": "16/8", "node": 3731, "naklon": 0 }, +{ "label": "16/9", "node": 3727, "naklon": 0 }, +{ "label": "16/10", "node": 3729, "naklon": 0 }, +{ "label": "16/11", "node": 3736, "naklon": 0 }, +{ "label": "16/12", "node": 3713, "naklon": 0 }, +{ "label": "16/13", "node": 3715, "naklon": 0 }, +{ "label": "16/14", "node": 3733, "naklon": 0 }, +{ "label": "16/15", "node": 3732, "naklon": 0 }, +{ "label": "16/17", "node": 3634, "naklon": 0 }, +{ "label": "16/18", "node": 3610, "naklon": 0 }, +{ "label": "16/19", "node": 3626, "naklon": 0 }, +{ "label": "16/20", "node": 3618, "naklon": 0 }, +{ "label": "16/21", "node": 3619, "naklon": 0 }, +{ "label": "16/22", "node": 3628, "naklon": 0 }, +{ "label": "16/23", "node": 3615, "naklon": 0 }, +{ "label": "16/24", "node": 3609, "naklon": 0 }, +{ "label": "16/25", "node": 3606, "naklon": 0 }, +{ "label": "16/26", "node": 3624, "naklon": 0 }, +{ "label": "16/27", "node": 3627, "naklon": 0 }, +{ "label": "16/28", "node": 3607, "naklon": 0 }, +{ "label": "16/29", "node": 4370, "naklon": 0 }, +{ "label": "16/30", "node": 3692, "naklon": 0 }, +{ "label": "16/31", "node": 3614, "naklon": 0 }, +{ "label": "16/32", "node": 3623, "naklon": 0 }, +{ "label": "16/33", "node": 4373, "naklon": 0 }, +{ "label": "16/34", "node": 3620, "naklon": 0 }, +{ "label": "16/35", "node": 3685, "naklon": 0 }, +{ "label": "16/36", "node": 3616, "naklon": 0 }, +{ "label": "16/37", "node": 3686, "naklon": 0 }, +{ "label": "16/38", "node": 3688, "naklon": 0 }, +{ "label": "16/39", "node": 3684, "naklon": 0 }, +{ "label": "16/40", "node": 3825, "naklon": 0 }, +{ "label": "16/41", "node": 3865, "naklon": 0 }, +{ "label": "16/42", "node": 3824, "naklon": 0 }, +{ "label": "16/43", "node": 3871, "naklon": 0 }, +{ "label": "16/44", "node": 3801, "naklon": 0 }, +{ "label": "16/45", "node": 3862, "naklon": 0 }, +{ "label": "16/46", "node": 3876, "naklon": 0 }, +{ "label": "16/47", "node": 3861, "naklon": 0 }, +{ "label": "16/48", "node": 4215, "naklon": 0 }, +{ "label": "16/49", "node": 3605, "naklon": 10 }, +{ "label": "16/50", "node": 3603, "naklon": 10 }, +{ "label": "16/51", "node": 3592, "naklon": 10 }, +{ "label": "16/52", "node": 3598, "naklon": 10 }, +{ "label": "16/53", "node": 3594, "naklon": 10 }, +{ "label": "16/54", "node": 3593, "naklon": 10 }, +{ "label": "16/55", "node": 3630, "naklon": 10 }, +{ "label": "16/56", "node": 3763, "naklon": 10 }, +{ "label": "16/57", "node": 3746, "naklon": 10 }, +{ "label": "16/58", "node": 3699, "naklon": 0 }, +{ "label": "16/59", "node": 3698, "naklon": 0 }, +{ "label": "16/60", "node": 3709, "naklon": null }, +{ "label": "16/61", "node": 3708, "naklon": 0 }, +{ "label": "16/62", "node": 3703, "naklon": null }, +{ "label": "16/63", "node": 3700, "naklon": 0 }, +{ "label": "16/64", "node": 3701, "naklon": null }, +{ "label": "16/65", "node": 3704, "naklon": 0 }, +{ "label": "16/66", "node": 3707, "naklon": null }, +{ "label": "16/67", "node": 3810, "naklon": 0 }, +{ "label": "16/68", "node": 4208, "naklon": null }, +{ "label": "16/69", "node": 3867, "naklon": 0 }, +{ "label": "16/70", "node": 4372, "naklon": null }, +{ "label": "16/71", "node": 3881, "naklon": 0 }, +{ "label": "16/72", "node": 4204, "naklon": null }, +{ "label": "16/73", "node": 3869, "naklon": 0 }, +{ "label": "16/74", "node": 4202, "naklon": null }, +{ "label": "16/75", "node": 3830, "naklon": 0 }, +{ "label": "16/76", "node": 3870, "naklon": null }, +{ "label": "16/77", "node": 3964, "naklon": 0 }, +{ "label": "16/78", "node": 3849, "naklon": 0 }, +{ "label": "16/79", "node": 3694, "naklon": null }, +{ "label": "16/80", "node": 3717, "naklon": 0 }, +{ "label": "16/81", "node": 3877, "naklon": null }, +{ "label": "16/82", "node": 3755, "naklon": 0 }, +{ "label": "16/83", "node": 3725, "naklon": null }, +{ "label": "16/84", "node": 3716, "naklon": 0 }, +{ "label": "16/85", "node": 3696, "naklon": null }, +{ "label": "16/86", "node": 3702, "naklon": 0 }, +{ "label": "16/87", "node": 3706, "naklon": null }, +{ "label": "16/88", "node": 3850, "naklon": 0 }, +{ "label": "16/89", "node": 3848, "naklon": null }, +{ "label": "16/90", "node": 3737, "naklon": null }, +{ "label": "16/91", "node": 3705, "naklon": 0 }, +{ "label": "16/92", "node": 3723, "naklon": null }, +{ "label": "16/93", "node": 3842, "naklon": 0 }, +{ "label": "16/94", "node": 3735, "naklon": null }, +{ "label": "16/95", "node": 3719, "naklon": 0 }, +{ "label": "16/96", "node": 3697, "naklon": 0 }, +{ "label": "16/97", "node": 3711, "naklon": 0 }, +{ "label": "16/98", "node": 4107, "naklon": null }, +{ "label": "16/99", "node": 4112, "naklon": 5 }, +{ "label": "16/100", "node": 4106, "naklon": 5 }, +{ "label": "16/101", "node": 4111, "naklon": 5 }, +{ "label": "16/102", "node": 4091, "naklon": null }, +{ "label": "16/103", "node": 4104, "naklon": 5 }, +{ "label": "16/104", "node": 4094, "naklon": null }, +{ "label": "16/105", "node": 4089, "naklon": 5 }, +{ "label": "16/106", "node": 4095, "naklon": null }, +{ "label": "16/107", "node": 4102, "naklon": 5 }, +{ "label": "16/108", "node": 4105, "naklon": null }, +{ "label": "16/109", "node": 3859, "naklon": null }, +{ "label": "16/110", "node": 4090, "naklon": 5 }, +{ "label": "16/111", "node": 4110, "naklon": null }, +{ "label": "16/112", "node": 4097, "naklon": 5 }, +{ "label": "16/113", "node": 4099, "naklon": null }, +{ "label": "16/114", "node": 4096, "naklon": null }, +{ "label": "16/115", "node": 4101, "naklon": 5 }, +{ "label": "16/116", "node": 4109, "naklon": null }, +{ "label": "16/117", "node": 4092, "naklon": 5 }, +{ "label": "16/118", "node": 3631, "naklon": null }, +{ "label": "16/119", "node": 3632, "naklon": 0 }, +{ "label": "16/120", "node": 3641, "naklon": null }, +{ "label": "16/121", "node": 3638, "naklon": 0 }, +{ "label": "16/122", "node": 3637, "naklon": null }, +{ "label": "16/123", "node": 4142, "naklon": null }, +{ "label": "16/124", "node": 4147, "naklon": 5 }, +{ "label": "16/125", "node": 4139, "naklon": 5 }, +{ "label": "20/30A", "node": 3172, "naklon": 2 }, +{ "label": "20/30B", "node": 3164, "naklon": 2 }, +{ "label": "20/1", "node": 3247, "naklon": 10 }, +{ "label": "20/2", "node": 3296, "naklon": 10 }, +{ "label": "20/3", "node": 3246, "naklon": 10 }, +{ "label": "20/4", "node": 3270, "naklon": 10 }, +{ "label": "20/5", "node": 3294, "naklon": 10 }, +{ "label": "20/6", "node": 3298, "naklon": 10 }, +{ "label": "20/7", "node": 3297, "naklon": 10 }, +{ "label": "20/8", "node": 3293, "naklon": 10 }, +{ "label": "20/9", "node": 3299, "naklon": 10 }, +{ "label": "20/10", "node": 3295, "naklon": 10 }, +{ "label": "20/11", "node": 3244, "naklon": 10 }, +{ "label": "20/12", "node": 3249, "naklon": 10 }, +{ "label": "20/13", "node": 3268, "naklon": 10 }, +{ "label": "20/14", "node": 3245, "naklon": 10 }, +{ "label": "20/15", "node": 3278, "naklon": 10 }, +{ "label": "20/16", "node": 3280, "naklon": 10 }, +{ "label": "20/17", "node": 3292, "naklon": 10 }, +{ "label": "20/18", "node": 3287, "naklon": 10 }, +{ "label": "20/19", "node": 3282, "naklon": 10 }, +{ "label": "20/20", "node": 3273, "naklon": 0 }, +{ "label": "20/21", "node": 3157, "naklon": 0 }, +{ "label": "20/22", "node": 3283, "naklon": 0 }, +{ "label": "20/23", "node": 3159, "naklon": 0 }, +{ "label": "20/24", "node": 3289, "naklon": 0 }, +{ "label": "20/25", "node": 3163, "naklon": 0 }, +{ "label": "20/26", "node": 3126, "naklon": 0 }, +{ "label": "20/27", "node": 3171, "naklon": 0 }, +{ "label": "20/28", "node": 3162, "naklon": 0 }, +{ "label": "20/29", "node": 3279, "naklon": 10 }, +{ "label": "20/31", "node": 3173, "naklon": 0 }, +{ "label": "20/32", "node": 3127, "naklon": 0 }, +{ "label": "20/33", "node": 3131, "naklon": 0 }, +{ "label": "20/34", "node": 3129, "naklon": 0 }, +{ "label": "20/35", "node": 3276, "naklon": 2 }, +{ "label": "20/36", "node": 3290, "naklon": 2 }, +{ "label": "20/37", "node": 3132, "naklon": 0 }, +{ "label": "20/38", "node": 3138, "naklon": 0 }, +{ "label": "20/39", "node": 3272, "naklon": 0 }, +{ "label": "20/40", "node": 3291, "naklon": 0 }, +{ "label": "20/41", "node": 3277, "naklon": 10 }, +{ "label": "20/42", "node": 3286, "naklon": 10 }, +{ "label": "20/43", "node": 3281, "naklon": 10 }, +{ "label": "20/44", "node": 3288, "naklon": 10 }, +{ "label": "20/45", "node": 3284, "naklon": 10 }, +{ "label": "20/46", "node": 3167, "naklon": 10 }, +{ "label": "20/47", "node": 3872, "naklon": 0 }, +{ "label": "20/48", "node": 3124, "naklon": 0 }, +{ "label": "20/49", "node": 3133, "naklon": 0 }, +{ "label": "20/50", "node": 3158, "naklon": 0 }, +{ "label": "20/51", "node": 3169, "naklon": 0 }, +{ "label": "20/52", "node": 3146, "naklon": 0 }, +{ "label": "20/53", "node": 3160, "naklon": 0 }, +{ "label": "20/54", "node": 3248, "naklon": 0 }, +{ "label": "20/55", "node": 3156, "naklon": 0 }, +{ "label": "20/56", "node": 3161, "naklon": 0 }, +{ "label": "20/57", "node": 3170, "naklon": 0 }, +{ "label": "20/58", "node": 3168, "naklon": 0 }, +{ "label": "20/59", "node": 3125, "naklon": 0 }, +{ "label": "20/60", "node": 3166, "naklon": 0 }, +{ "label": "20/61", "node": 3130, "naklon": 0 }, +{ "label": "20/62", "node": 3563, "naklon": 0 }, +{ "label": "20/63", "node": 3550, "naklon": null }, +{ "label": "20/67", "node": 3269, "naklon": 0 }, +{ "label": "21/1", "node": 2921, "naklon": 0 }, +{ "label": "21/2", "node": 2707, "naklon": 0 }, +{ "label": "21/3", "node": 2723, "naklon": 0 }, +{ "label": "21/4", "node": 2716, "naklon": 0 }, +{ "label": "21/5", "node": 2717, "naklon": 0 }, +{ "label": "21/6", "node": 2720, "naklon": 0 }, +{ "label": "21/7", "node": 2722, "naklon": 0 }, +{ "label": "21/8", "node": 2718, "naklon": 0 }, +{ "label": "21/9", "node": 2724, "naklon": 0 }, +{ "label": "21/10", "node": 2742, "naklon": 0 }, +{ "label": "21/11", "node": 2743, "naklon": 0 }, +{ "label": "21/12", "node": 2733, "naklon": 0 }, +{ "label": "21/14", "node": 2903, "naklon": 0 }, +{ "label": "21/15", "node": 2917, "naklon": 0 }, +{ "label": "21/16", "node": 2897, "naklon": 0 }, +{ "label": "21/17", "node": 2914, "naklon": 0 }, +{ "label": "21/18", "node": 2898, "naklon": 0 }, +{ "label": "21/19", "node": 2773, "naklon": 0 }, +{ "label": "21/20", "node": 2895, "naklon": 0 }, +{ "label": "21/21", "node": 2896, "naklon": 0 }, +{ "label": "21/22", "node": 2771, "naklon": 0 }, +{ "label": "21/23", "node": 2772, "naklon": 0 }, +{ "label": "21/24", "node": 2793, "naklon": 0 }, +{ "label": "21/25", "node": 2902, "naklon": 0 }, +{ "label": "21/26", "node": 2910, "naklon": 0 }, +{ "label": "21/27", "node": 2909, "naklon": 0 }, +{ "label": "21/28", "node": 2920, "naklon": 0 }, +{ "label": "21/29", "node": 2916, "naklon": 0 }, +{ "label": "21/30", "node": 2904, "naklon": 0 }, +{ "label": "21/31", "node": 2915, "naklon": 0 }, +{ "label": "21/32", "node": 2905, "naklon": 0 }, +{ "label": "21/33", "node": 2900, "naklon": 0 }, +{ "label": "21/34", "node": 2899, "naklon": 0 }, +{ "label": "21/36", "node": 2741, "naklon": 0 }, +{ "label": "21/37", "node": 2714, "naklon": 0 }, +{ "label": "21/38", "node": 2701, "naklon": 0 }, +{ "label": "21/39", "node": 2703, "naklon": 0 }, +{ "label": "21/40", "node": 2704, "naklon": 0 }, +{ "label": "21/41", "node": 2702, "naklon": 0 }, +{ "label": "21/42", "node": 2706, "naklon": 0 }, +{ "label": "21/43", "node": 2776, "naklon": 0 }, +{ "label": "21/44", "node": 2770, "naklon": 0 }, +{ "label": "21/45", "node": 2786, "naklon": 0 }, +{ "label": "21/46", "node": 2779, "naklon": 0 }, +{ "label": "21/47", "node": 2782, "naklon": 0 }, +{ "label": "21/48", "node": 2785, "naklon": 0 }, +{ "label": "21/49", "node": 2769, "naklon": 0 }, +{ "label": "21/50", "node": 3354, "naklon": 0 }, +{ "label": "21/51", "node": 2778, "naklon": 0 }, +{ "label": "21/52", "node": 2775, "naklon": 0 }, +{ "label": "21/53", "node": 2780, "naklon": 0 }, +{ "label": "21/54", "node": 2790, "naklon": 0 }, +{ "label": "21/55", "node": 2792, "naklon": 0 }, +{ "label": "21/56", "node": 2774, "naklon": 0 }, +{ "label": "22/1", "node": 2630, "naklon": 0 }, +{ "label": "22/2", "node": 2631, "naklon": 0 }, +{ "label": "22/3", "node": 2632, "naklon": 0 }, +{ "label": "22/4", "node": 2633, "naklon": 0 }, +{ "label": "22/5", "node": 2634, "naklon": 0 }, +{ "label": "22/6", "node": 2636, "naklon": 0 }, +{ "label": "22/7", "node": 4367, "naklon": 0 }, +{ "label": "22/8", "node": 2637, "naklon": 0 }, +{ "label": "22/9", "node": 2638, "naklon": 0 }, +{ "label": "22/10", "node": 2639, "naklon": 0 }, +{ "label": "22/11", "node": 2640, "naklon": 0 }, +{ "label": "22/12", "node": 2641, "naklon": 0 }, +{ "label": "22/13", "node": 2642, "naklon": 0 }, +{ "label": "22/14", "node": 2643, "naklon": 0 }, +{ "label": "22/15", "node": 2644, "naklon": 0 }, +{ "label": "22/16", "node": 2645, "naklon": 0 }, +{ "label": "22/17", "node": 2646, "naklon": 0 }, +{ "label": "22/18", "node": 2647, "naklon": 0 }, +{ "label": "22/19", "node": 2648, "naklon": 0 }, +{ "label": "22/20", "node": 2649, "naklon": 0 }, +{ "label": "22/21", "node": 2650, "naklon": 0 }, +{ "label": "22/22", "node": 2651, "naklon": 0 }, +{ "label": "22/23", "node": 4103, "naklon": 0 }, +{ "label": "22/24", "node": 2653, "naklon": 0 }, +{ "label": "22/25", "node": 2654, "naklon": 0 }, +{ "label": "22/26", "node": 2655, "naklon": 0 }, +{ "label": "22/27", "node": 2656, "naklon": 0 }, +{ "label": "22/28", "node": 2657, "naklon": 0 }, +{ "label": "22/29", "node": 2658, "naklon": 0 }, +{ "label": "22/30", "node": 2659, "naklon": 0 }, +{ "label": "22/31", "node": 2660, "naklon": 0 }, +{ "label": "22/32", "node": 2661, "naklon": 0 }, +{ "label": "22/32/1", "node": 3015, "naklon": 0 }, +{ "label": "22/33", "node": 2662, "naklon": 0 }, +{ "label": "22/34", "node": 2663, "naklon": 0 }, +{ "label": "22/35", "node": 2664, "naklon": 0 }, +{ "label": "22/36", "node": 2665, "naklon": 0 }, +{ "label": "22/37", "node": 2666, "naklon": 0 }, +{ "label": "22/38", "node": 2667, "naklon": 0 }, +{ "label": "22/39", "node": 2668, "naklon": 0 }, +{ "label": "22/40", "node": 2669, "naklon": null }, +{ "label": "22/41", "node": 2670, "naklon": null }, +{ "label": "22/42", "node": 2671, "naklon": null }, +{ "label": "23/9A", "node": 3087, "naklon": 10 }, +{ "label": "23/9B", "node": 3090, "naklon": 10 }, +{ "label": "23/1", "node": 3075, "naklon": 0 }, +{ "label": "23/2", "node": 3089, "naklon": 0 }, +{ "label": "23/3", "node": 3088, "naklon": 0 }, +{ "label": "23/4", "node": 3228, "naklon": 10 }, +{ "label": "23/5", "node": 2751, "naklon": 10 }, +{ "label": "23/6", "node": 3243, "naklon": 10 }, +{ "label": "23/7", "node": 4349, "naklon": 10 }, +{ "label": "23/8", "node": 3102, "naklon": 10 }, +{ "label": "23/10", "node": 3099, "naklon": 10 }, +{ "label": "23/11", "node": 3103, "naklon": 10 }, +{ "label": "23/12", "node": 3093, "naklon": 10 }, +{ "label": "23/13", "node": 3098, "naklon": 10 }, +{ "label": "23/14", "node": 3092, "naklon": 10 }, +{ "label": "23/15", "node": 3233, "naklon": 0 }, +{ "label": "23/16", "node": 3095, "naklon": 0 }, +{ "label": "23/17", "node": 4074, "naklon": 0 }, +{ "label": "23/18", "node": 2729, "naklon": 0 }, +{ "label": "23/19", "node": 3234, "naklon": 0 }, +{ "label": "23/20", "node": 3094, "naklon": 0 }, +{ "label": "23/21", "node": 2817, "naklon": 0 }, +{ "label": "23/22", "node": 3226, "naklon": 0 }, +{ "label": "23/23", "node": 3225, "naklon": 0 }, +{ "label": "23/24", "node": 3237, "naklon": 0 }, +{ "label": "23/25", "node": 4250, "naklon": 0 }, +{ "label": "23/26", "node": 3059, "naklon": 10 }, +{ "label": "23/27", "node": 3238, "naklon": 10 }, +{ "label": "23/28", "node": 3242, "naklon": 10 }, +{ "label": "23/29", "node": 3236, "naklon": 10 }, +{ "label": "23/30", "node": 3112, "naklon": 10 }, +{ "label": "23/31", "node": 3224, "naklon": 0 }, +{ "label": "23/32", "node": 4298, "naklon": 10 }, +{ "label": "23/33", "node": 4150, "naklon": 10 }, +{ "label": "23/34", "node": 3091, "naklon": 10 }, +{ "label": "25/1", "node": 3771, "naklon": 5 }, +{ "label": "25/2", "node": 3777, "naklon": 5 }, +{ "label": "25/3", "node": 3749, "naklon": 5 }, +{ "label": "25/4", "node": 3769, "naklon": 5 }, +{ "label": "25/5", "node": 3765, "naklon": 5 }, +{ "label": "25/6", "node": 3785, "naklon": 5 }, +{ "label": "25/7", "node": 3761, "naklon": 5 }, +{ "label": "25/8", "node": 3758, "naklon": 5 }, +{ "label": "25/9", "node": 3766, "naklon": 5 }, +{ "label": "25/10", "node": 3779, "naklon": 5 }, +{ "label": "25/11", "node": 3899, "naklon": 10 }, +{ "label": "25/12", "node": 3922, "naklon": 10 }, +{ "label": "25/13", "node": 3912, "naklon": 10 }, +{ "label": "25/14", "node": 3933, "naklon": 10 }, +{ "label": "25/15", "node": 3921, "naklon": 10 }, +{ "label": "25/16", "node": 4300, "naklon": 10 }, +{ "label": "25/17", "node": 3927, "naklon": 10 }, +{ "label": "25/18", "node": 3212, "naklon": 10 }, +{ "label": "25/19", "node": 3208, "naklon": 10 }, +{ "label": "25/20", "node": 3207, "naklon": 10 }, +{ "label": "25/21", "node": 4294, "naklon": 10 }, +{ "label": "25/22", "node": 3209, "naklon": 10 }, +{ "label": "25/23", "node": 3745, "naklon": 10 }, +{ "label": "25/24", "node": 3762, "naklon": 10 }, +{ "label": "25/25", "node": 3215, "naklon": 10 }, +{ "label": "25/26", "node": 3210, "naklon": 10 }, +{ "label": "25/27", "node": 3211, "naklon": 10 }, +{ "label": "25/28", "node": 3206, "naklon": 10 }, +{ "label": "25/29", "node": 3918, "naklon": 5 }, +{ "label": "25/30", "node": 3928, "naklon": 5 }, +{ "label": "25/31", "node": 3917, "naklon": 5 }, +{ "label": "25/32", "node": 4029, "naklon": 0 }, +{ "label": "25/33", "node": 4038, "naklon": 0 }, +{ "label": "25/34", "node": 4022, "naklon": 0 }, +{ "label": "25/35", "node": 3937, "naklon": 0 }, +{ "label": "25/36", "node": 3190, "naklon": 0 }, +{ "label": "25/37", "node": 3835, "naklon": 0 }, +{ "label": "25/38", "node": 3201, "naklon": 0 }, +{ "label": "25/39", "node": 3193, "naklon": 0 }, +{ "label": "25/40", "node": 3191, "naklon": 0 }, +{ "label": "25/41", "node": 3203, "naklon": 0 }, +{ "label": "25/42", "node": 4301, "naklon": 0 }, +{ "label": "25/43", "node": 3223, "naklon": 0 }, +{ "label": "25/44", "node": 3202, "naklon": 0 }, +{ "label": "25/45", "node": 3205, "naklon": 0 }, +{ "label": "25/46", "node": 3194, "naklon": 0 }, +{ "label": "25/47", "node": 3198, "naklon": 0 }, +{ "label": "25/48", "node": 3204, "naklon": 0 }, +{ "label": "25/49", "node": 3200, "naklon": 0 }, +{ "label": "25/50", "node": 3216, "naklon": 0 }, +{ "label": "25/51", "node": 3932, "naklon": 5 }, +{ "label": "25/52", "node": 3923, "naklon": 5 }, +{ "label": "25/53", "node": 3913, "naklon": 5 }, +{ "label": "25/54", "node": 3900, "naklon": 5 }, +{ "label": "25/55", "node": 4189, "naklon": 10 }, +{ "label": "25/56", "node": 4191, "naklon": 10 }, +{ "label": "25/57", "node": 3790, "naklon": 10 }, +{ "label": "25/58", "node": 4190, "naklon": 10 }, +{ "label": "25/59", "node": 4302, "naklon": 0 }, +{ "label": "25/60", "node": 4351, "naklon": 0 }, +{ "label": "25/61", "node": 4075, "naklon": 0 }, +{ "label": "25/62", "node": 4071, "naklon": 0 }, +{ "label": "25/63", "node": 3784, "naklon": 0 }, +{ "label": "25/64", "node": 4065, "naklon": 0 }, +{ "label": "25/65", "node": 4297, "naklon": 0 }, +{ "label": "25/66", "node": 4295, "naklon": 0 }, +{ "label": "25/67", "node": 4299, "naklon": 0 }, +{ "label": "25/68", "node": 3772, "naklon": 0 }, +{ "label": "25/69", "node": 3941, "naklon": 0 }, +{ "label": "25/70", "node": 3782, "naklon": 0 }, +{ "label": "25/71", "node": 4068, "naklon": 0 }, +{ "label": "25/72", "node": 4073, "naklon": 0 }, +{ "label": "25/73", "node": 3901, "naklon": 5 }, +{ "label": "25/74", "node": 4296, "naklon": 5 }, +{ "label": "25/75", "node": 3910, "naklon": 5 }, +{ "label": "25/76", "node": 4293, "naklon": 5 }, +{ "label": "25/77", "node": 3919, "naklon": 5 }, +{ "label": "25/78", "node": 3924, "naklon": 5 }, +{ "label": "25/79", "node": 3909, "naklon": 5 }, +{ "label": "25/80", "node": 3896, "naklon": 5 }, +{ "label": "25/81", "node": 3911, "naklon": 5 }, +{ "label": "25/82", "node": 2819, "naklon": 15 }, +{ "label": "25/83", "node": 3776, "naklon": 15 }, +{ "label": "25/84", "node": 3752, "naklon": 15 }, +{ "label": "25/85", "node": 4353, "naklon": 15 }, +{ "label": "25/86", "node": 3791, "naklon": 0 }, +{ "label": "25/87", "node": 3770, "naklon": 0 }, +{ "label": "25/88", "node": 3760, "naklon": 0 }, +{ "label": "25/89", "node": 3115, "naklon": 0 }, +{ "label": "25/90", "node": 3738, "naklon": 0 }, +{ "label": "25/91", "node": 3748, "naklon": 0 }, +{ "label": "25/92", "node": 3753, "naklon": 0 }, +{ "label": "25/93", "node": 3775, "naklon": 0 }, +{ "label": "25/94", "node": 3778, "naklon": 5 }, +{ "label": "25/95", "node": 4078, "naklon": 5 }, +{ "label": "25/96", "node": 4088, "naklon": 5 }, +{ "label": "25/97", "node": 3856, "naklon": 5 }, +{ "label": "25/98", "node": 4084, "naklon": 5 }, +{ "label": "25/99", "node": 4069, "naklon": 5 }, +{ "label": "25/100", "node": 4188, "naklon": 5 }, +{ "label": "25/101", "node": 4064, "naklon": 5 }, +{ "label": "25/102", "node": 3792, "naklon": 5 }, +{ "label": "25/103", "node": 3780, "naklon": 5 }, +{ "label": "25/104", "node": 4034, "naklon": 5 }, +{ "label": "25/105", "node": 4072, "naklon": 5 }, +{ "label": "25/106", "node": 3884, "naklon": 5 }, +{ "label": "25/107", "node": 3793, "naklon": 5 }, +{ "label": "25/108", "node": 3863, "naklon": 5 }, +{ "label": "25/109", "node": 3855, "naklon": 5 }, +{ "label": "33/1", "node": 3846, "naklon": 0 }, +{ "label": "33/2", "node": 3943, "naklon": 0 }, +{ "label": "33/3", "node": 3903, "naklon": 0 }, +{ "label": "33/4", "node": 3982, "naklon": 0 }, +{ "label": "33/5", "node": 3879, "naklon": 0 }, +{ "label": "33/6", "node": 3887, "naklon": 0 }, +{ "label": "33/7", "node": 3920, "naklon": 5 }, +{ "label": "33/8", "node": 3942, "naklon": 5 }, +{ "label": "33/9", "node": 3829, "naklon": null }, +{ "label": "34/79A", "node": 3452, "naklon": 6 }, +{ "label": "34/79B", "node": 3460, "naklon": 6 }, +{ "label": "34/90A", "node": 3443, "naklon": 6 }, +{ "label": "34/90B", "node": 3445, "naklon": 6 }, +{ "label": "34/90C", "node": 3457, "naklon": 6 }, +{ "label": "34/97A", "node": 3461, "naklon": 6 }, +{ "label": "34/97B", "node": 3463, "naklon": 6 }, +{ "label": "34/98A", "node": 3426, "naklon": 6 }, +{ "label": "34/98B", "node": 3444, "naklon": 6 }, +{ "label": "34/99A", "node": 3453, "naklon": 6 }, +{ "label": "34/99B", "node": 3455, "naklon": 6 }, +{ "label": "34/1", "node": 4009, "naklon": 0 }, +{ "label": "34/2", "node": 3602, "naklon": 0 }, +{ "label": "34/3", "node": 3441, "naklon": 0 }, +{ "label": "34/4", "node": 3464, "naklon": 0 }, +{ "label": "34/5", "node": 3883, "naklon": 0 }, +{ "label": "34/6", "node": 4098, "naklon": 0 }, +{ "label": "34/7", "node": 4003, "naklon": 0 }, +{ "label": "34/8", "node": 4004, "naklon": 0 }, +{ "label": "34/9", "node": 3888, "naklon": 0 }, +{ "label": "34/10", "node": 3997, "naklon": 0 }, +{ "label": "34/11", "node": 4006, "naklon": 0 }, +{ "label": "34/12", "node": 4000, "naklon": 0 }, +{ "label": "34/13", "node": 4011, "naklon": 0 }, +{ "label": "34/14", "node": 3999, "naklon": 0 }, +{ "label": "34/15", "node": 3981, "naklon": 0 }, +{ "label": "34/16", "node": 3988, "naklon": 0 }, +{ "label": "34/17", "node": 3986, "naklon": 0 }, +{ "label": "34/18", "node": 3998, "naklon": 0 }, +{ "label": "34/19", "node": 3983, "naklon": 0 }, +{ "label": "34/20", "node": 4005, "naklon": 0 }, +{ "label": "34/21", "node": 4001, "naklon": 0 }, +{ "label": "34/22", "node": 4008, "naklon": 0 }, +{ "label": "34/23", "node": 4002, "naklon": 0 }, +{ "label": "34/24", "node": 3996, "naklon": 0 }, +{ "label": "34/25", "node": 4007, "naklon": 0 }, +{ "label": "34/26", "node": 4113, "naklon": 15 }, +{ "label": "34/27", "node": 3595, "naklon": 5 }, +{ "label": "34/28", "node": 3599, "naklon": 5 }, +{ "label": "34/29", "node": 3601, "naklon": 5 }, +{ "label": "34/30", "node": 4205, "naklon": 0 }, +{ "label": "34/31", "node": 3987, "naklon": null }, +{ "label": "34/32", "node": 4214, "naklon": 0 }, +{ "label": "34/33", "node": 4226, "naklon": 0 }, +{ "label": "34/34", "node": 4209, "naklon": 0 }, +{ "label": "34/35", "node": 4201, "naklon": 0 }, +{ "label": "34/36", "node": 3440, "naklon": 0 }, +{ "label": "34/37", "node": 3465, "naklon": 0 }, +{ "label": "34/38", "node": 3446, "naklon": 0 }, +{ "label": "34/39", "node": 4039, "naklon": 5 }, +{ "label": "34/40", "node": 4057, "naklon": 5 }, +{ "label": "34/41", "node": 3985, "naklon": 0 }, +{ "label": "34/42", "node": 3882, "naklon": 0 }, +{ "label": "34/43", "node": 4040, "naklon": 5 }, +{ "label": "34/44", "node": 3231, "naklon": 0 }, +{ "label": "34/45", "node": 3227, "naklon": 0 }, +{ "label": "34/46", "node": 3431, "naklon": 0 }, +{ "label": "34/47", "node": 4013, "naklon": 0 }, +{ "label": "34/48", "node": 4045, "naklon": 0 }, +{ "label": "34/49", "node": 3949, "naklon": 0 }, +{ "label": "34/50", "node": 3953, "naklon": 0 }, +{ "label": "34/51", "node": 3952, "naklon": 0 }, +{ "label": "34/52", "node": 3995, "naklon": 0 }, +{ "label": "34/53", "node": 3992, "naklon": 0 }, +{ "label": "34/54", "node": 4198, "naklon": 0 }, +{ "label": "34/55", "node": 3935, "naklon": 0 }, +{ "label": "34/56", "node": 4050, "naklon": 0 }, +{ "label": "34/57", "node": 4049, "naklon": 0 }, +{ "label": "34/58", "node": 4054, "naklon": 0 }, +{ "label": "34/59", "node": 3663, "naklon": 6 }, +{ "label": "34/60", "node": 3661, "naklon": 6 }, +{ "label": "34/61", "node": 3664, "naklon": 6 }, +{ "label": "34/62", "node": 3660, "naklon": 6 }, +{ "label": "34/63", "node": 3662, "naklon": 6 }, +{ "label": "34/65", "node": 3665, "naklon": 6 }, +{ "label": "34/66", "node": 3667, "naklon": 6 }, +{ "label": "34/67", "node": 3675, "naklon": 6 }, +{ "label": "34/68", "node": 3666, "naklon": 6 }, +{ "label": "34/69", "node": 3652, "naklon": 6 }, +{ "label": "34/70", "node": 3458, "naklon": 6 }, +{ "label": "34/70/1", "node": 4425, "naklon": 6 }, +{ "label": "34/71", "node": 3459, "naklon": 6 }, +{ "label": "34/72", "node": 3435, "naklon": 6 }, +{ "label": "34/73", "node": 3448, "naklon": 6 }, +{ "label": "34/74", "node": 3451, "naklon": 6 }, +{ "label": "34/75", "node": 3442, "naklon": 6 }, +{ "label": "34/76", "node": 3449, "naklon": 6 }, +{ "label": "34/77", "node": 3450, "naklon": 6 }, +{ "label": "34/78", "node": 3433, "naklon": 6 }, +{ "label": "34/80", "node": 3432, "naklon": 12 }, +{ "label": "34/81", "node": 3470, "naklon": 12 }, +{ "label": "34/82", "node": 3438, "naklon": 12 }, +{ "label": "34/83", "node": 3439, "naklon": 12 }, +{ "label": "34/84", "node": 4028, "naklon": 5 }, +{ "label": "34/85", "node": 3596, "naklon": 5 }, +{ "label": "34/86", "node": 4021, "naklon": 5 }, +{ "label": "34/87", "node": 3437, "naklon": 12 }, +{ "label": "34/88", "node": 3428, "naklon": 12 }, +{ "label": "34/89", "node": 3430, "naklon": 12 }, +{ "label": "34/91", "node": 3454, "naklon": 6 }, +{ "label": "34/92", "node": 3492, "naklon": 6 }, +{ "label": "34/93", "node": 3462, "naklon": 6 }, +{ "label": "34/94", "node": 3427, "naklon": 6 }, +{ "label": "34/95", "node": 3434, "naklon": 6 }, +{ "label": "34/96", "node": 3456, "naklon": 6 }, +{ "label": "34/98/1", "node": 4307, "naklon": 6 }, +{ "label": "35/1", "node": 3968, "naklon": 0 }, +{ "label": "35/2", "node": 3969, "naklon": 0 }, +{ "label": "35/3", "node": 3947, "naklon": 0 }, +{ "label": "35/4", "node": 3979, "naklon": 0 }, +{ "label": "35/5", "node": 3959, "naklon": 0 }, +{ "label": "35/6", "node": 3948, "naklon": 0 }, +{ "label": "35/7", "node": 3961, "naklon": 0 }, +{ "label": "35/8", "node": 3956, "naklon": 0 }, +{ "label": "35/9", "node": 3604, "naklon": 0 }, +{ "label": "35/10", "node": 3944, "naklon": 0 }, +{ "label": "35/11", "node": 3960, "naklon": 0 }, +{ "label": "35/12", "node": 3958, "naklon": 0 }, +{ "label": "35/13", "node": 4036, "naklon": 5 }, +{ "label": "35/18", "node": 3893, "naklon": 5 }, +{ "label": "35/19", "node": 4108, "naklon": 5 }, +{ "label": "35/20", "node": 4017, "naklon": 5 }, +{ "label": "35/21", "node": 3963, "naklon": 0 }, +{ "label": "35/22", "node": 3658, "naklon": 0 }, +{ "label": "35/23", "node": 3975, "naklon": 0 }, +{ "label": "35/24", "node": 3980, "naklon": 0 }, +{ "label": "35/25", "node": 4012, "naklon": 0 }, +{ "label": "35/26", "node": 3655, "naklon": 0 }, +{ "label": "35/27", "node": 3962, "naklon": 0 }, +{ "label": "35/28", "node": 3945, "naklon": 0 }, +{ "label": "35/29", "node": 3569, "naklon": 0 }, +{ "label": "35/30", "node": 3429, "naklon": 0 }, +{ "label": "35/31", "node": 3657, "naklon": 0 }, +{ "label": "35/32", "node": 3646, "naklon": 0 }, +{ "label": "35/33", "node": 3622, "naklon": 0 }, +{ "label": "35/34", "node": 3612, "naklon": 0 }, +{ "label": "35/35", "node": 3955, "naklon": 0 }, +{ "label": "35/37", "node": 3878, "naklon": 0 }, +{ "label": "35/38", "node": 3965, "naklon": 0 }, +{ "label": "35/39", "node": 3970, "naklon": 0 }, +{ "label": "35/40", "node": 3611, "naklon": 0 }, +{ "label": "35/41", "node": 2635, "naklon": 0 }, +{ "label": "35/42", "node": 3978, "naklon": 0 }, +{ "label": "35/43", "node": 4213, "naklon": 0 }, +{ "label": "35/44", "node": 3984, "naklon": 0 }, +{ "label": "35/45", "node": 4218, "naklon": 0 }, +{ "label": "35/46", "node": 3973, "naklon": 0 }, +{ "label": "35/47", "node": 3974, "naklon": 0 }, +{ "label": "35/48", "node": 3759, "naklon": 0 }, +{ "label": "35/49", "node": 3844, "naklon": 0 }, +{ "label": "35/50", "node": 3804, "naklon": 0 }, +{ "label": "35/51", "node": 3831, "naklon": 0 }, +{ "label": "35/52", "node": 3643, "naklon": 0 }, +{ "label": "35/53", "node": 3966, "naklon": 0 }, +{ "label": "35/54", "node": 3971, "naklon": 0 }, +{ "label": "35/55", "node": 3650, "naklon": 6 }, +{ "label": "35/56", "node": 3651, "naklon": 6 }, +{ "label": "35/57", "node": 3669, "naklon": 6 }, +{ "label": "35/58", "node": 3648, "naklon": 6 }, +{ "label": "35/59", "node": 3645, "naklon": 6 }, +{ "label": "35/60", "node": 3659, "naklon": 6 }, +{ "label": "35/61", "node": 3647, "naklon": 6 }, +{ "label": "35/62", "node": 3644, "naklon": 6 }, +{ "label": "35/63", "node": 3671, "naklon": 6 }, +{ "label": "35/64", "node": 3682, "naklon": 6 }, +{ "label": "35/65", "node": 3672, "naklon": 6 }, +{ "label": "35/66", "node": 3683, "naklon": 6 }, +{ "label": "35/67", "node": 3673, "naklon": 6 }, +{ "label": "35/68", "node": 3674, "naklon": 6 }, +{ "label": "35/69", "node": 3679, "naklon": 6 }, +{ "label": "35/70", "node": 3649, "naklon": 6 }, +{ "label": "35/71", "node": 3687, "naklon": 6 }, +{ "label": "35/72", "node": 3677, "naklon": 6 }, +{ "label": "35/73", "node": 3690, "naklon": 6 }, +{ "label": "35/74", "node": 3691, "naklon": 6 }, +{ "label": "35/75", "node": 3676, "naklon": 6 }, +{ "label": "35/76", "node": 3680, "naklon": 6 }, +{ "label": "35/77", "node": 3668, "naklon": 6 }, +{ "label": "35/78", "node": 3681, "naklon": 6 }, +{ "label": "35/79", "node": 3670, "naklon": 6 }, +{ "label": "35/80", "node": 3689, "naklon": 6 }, +{ "label": "35/81", "node": 3678, "naklon": 6 }, +{ "label": "35/82", "node": 3693, "naklon": 6 }, +{ "label": "35/83", "node": 3654, "naklon": null }, +{ "label": "36/1", "node": 4086, "naklon": 0 }, +{ "label": "36/2", "node": 4085, "naklon": 0 }, +{ "label": "36/3", "node": 4083, "naklon": 0 }, +{ "label": "36/4", "node": 4087, "naklon": 0 }, +{ "label": "36/5", "node": 4077, "naklon": 0 }, +{ "label": "36/6", "node": 4082, "naklon": 0 }, +{ "label": "36/7", "node": 4186, "naklon": 0 }, +{ "label": "36/8", "node": 4206, "naklon": 0 }, +{ "label": "36/9", "node": 4080, "naklon": 0 }, +{ "label": "36/10", "node": 4081, "naklon": 0 }, +{ "label": "36/11", "node": 4210, "naklon": 0 }, +{ "label": "36/12", "node": 4079, "naklon": 0 }, +{ "label": "36/13", "node": 4076, "naklon": 0 }, +{ "label": "36/14", "node": 3852, "naklon": 0 }, +{ "label": "36/15", "node": 2813, "naklon": 0 }, +{ "label": "36/16", "node": 4219, "naklon": 0 }, +{ "label": "37/1A", "node": 3104, "naklon": 15 }, +{ "label": "37/1B", "node": 3121, "naklon": 15 }, +{ "label": "37/2", "node": 3113, "naklon": 10 }, +{ "label": "37/3", "node": 3118, "naklon": 10 }, +{ "label": "37/4", "node": 3111, "naklon": 10 }, +{ "label": "37/5", "node": 4020, "naklon": 10 }, +{ "label": "37/6", "node": 3119, "naklon": 10 }, +{ "label": "37/7", "node": 3110, "naklon": 10 }, +{ "label": "37/8", "node": 3108, "naklon": 10 }, +{ "label": "37/12", "node": 3107, "naklon": 0 }, +{ "label": "37/13", "node": 3199, "naklon": 0 }, +{ "label": "37/14", "node": 3120, "naklon": 0 }, +{ "label": "37/15", "node": 3122, "naklon": 0 }, +{ "label": "37/16", "node": 3908, "naklon": 0 }, +{ "label": "37/17", "node": 3114, "naklon": 0 }, +{ "label": "37/18", "node": 3105, "naklon": 0 }, +{ "label": "37/19", "node": 3116, "naklon": 0 }, +{ "label": "37/20", "node": 3106, "naklon": 0 }, +{ "label": "37/21", "node": 2887, "naklon": 5 }, +{ "label": "37/22", "node": 2888, "naklon": 5 }, +{ "label": "37/23", "node": 2877, "naklon": 5 }, +{ "label": "37/24", "node": 2891, "naklon": 5 }, +{ "label": "37/25", "node": 2886, "naklon": 5 }, +{ "label": "37/26", "node": 2892, "naklon": 5 }, +{ "label": "37/27", "node": 2882, "naklon": 5 }, +{ "label": "37/28", "node": 2883, "naklon": 5 }, +{ "label": "37/29", "node": 2876, "naklon": 5 }, +{ "label": "37/30", "node": 3109, "naklon": 5 }, +{ "label": "37/31", "node": 4152, "naklon": 5 }, +{ "label": "37/32", "node": 3117, "naklon": 5 }, +{ "label": "37/33", "node": 2870, "naklon": 5 }, +{ "label": "37/34", "node": 2867, "naklon": 0 }, +{ "label": "37/35", "node": 2865, "naklon": 0 }, +{ "label": "37/36", "node": 3096, "naklon": 0 }, +{ "label": "37/37", "node": 2871, "naklon": 0 }, +{ "label": "37/38", "node": 2884, "naklon": 0 }, +{ "label": "37/39", "node": 2855, "naklon": 0 }, +{ "label": "37/40", "node": 2878, "naklon": 0 }, +{ "label": "37/41", "node": 2889, "naklon": 0 }, +{ "label": "37/42", "node": 2879, "naklon": 0 }, +{ "label": "37/43", "node": 2850, "naklon": 0 }, +{ "label": "37/44", "node": 2894, "naklon": 0 }, +{ "label": "37/45", "node": 2880, "naklon": 0 }, +{ "label": "37/46", "node": 2893, "naklon": 0 }, +{ "label": "37/47", "node": 2890, "naklon": 0 }, +{ "label": "37/48", "node": 4355, "naklon": 0 }, +{ "label": "37/49", "node": 2885, "naklon": 0 }, +{ "label": "37/50", "node": 2875, "naklon": 0 }, +{ "label": "38/30A", "node": 3486, "naklon": 5 }, +{ "label": "38/30B", "node": 3714, "naklon": 0 }, +{ "label": "38/32A", "node": 3483, "naklon": 5 }, +{ "label": "38/32B", "node": 3496, "naklon": 0 }, +{ "label": "38/35A", "node": 3487, "naklon": 5 }, +{ "label": "38/35B", "node": 3498, "naklon": 5 }, +{ "label": "38/38A", "node": 3578, "naklon": 5 }, +{ "label": "38/38B", "node": 3508, "naklon": 5 }, +{ "label": "38/59A", "node": 3787, "naklon": 5 }, +{ "label": "38/59B", "node": 3491, "naklon": 5 }, +{ "label": "38/1", "node": 3568, "naklon": null }, +{ "label": "38/2", "node": 3502, "naklon": 0 }, +{ "label": "38/3", "node": 3836, "naklon": 0 }, +{ "label": "38/4", "node": 3588, "naklon": 0 }, +{ "label": "38/5", "node": 3493, "naklon": 0 }, +{ "label": "38/6", "node": 3580, "naklon": 0 }, +{ "label": "38/7", "node": 3572, "naklon": 0 }, +{ "label": "38/8", "node": 3506, "naklon": 0 }, +{ "label": "38/9", "node": 3503, "naklon": 0 }, +{ "label": "38/10", "node": 3579, "naklon": 0 }, +{ "label": "38/11", "node": 3586, "naklon": 0 }, +{ "label": "38/12", "node": 3495, "naklon": 5 }, +{ "label": "38/13", "node": 3492, "naklon": 5 }, +{ "label": "38/14", "node": 3532, "naklon": 5 }, +{ "label": "38/15", "node": 3574, "naklon": 5 }, +{ "label": "38/16", "node": 4140, "naklon": 5 }, +{ "label": "38/17", "node": 3795, "naklon": 5 }, +{ "label": "38/18", "node": 3788, "naklon": 5 }, +{ "label": "38/19", "node": 3796, "naklon": 5 }, +{ "label": "38/20", "node": 3797, "naklon": 5 }, +{ "label": "38/21", "node": 3798, "naklon": 5 }, +{ "label": "38/22", "node": 3786, "naklon": 5 }, +{ "label": "38/23", "node": 4067, "naklon": 5 }, +{ "label": "38/24", "node": 3773, "naklon": 5 }, +{ "label": "38/25", "node": 3774, "naklon": 5 }, +{ "label": "38/26", "node": 3789, "naklon": 5 }, +{ "label": "38/27", "node": 3520, "naklon": null }, +{ "label": "38/29", "node": 3577, "naklon": 5 }, +{ "label": "38/31", "node": 3530, "naklon": null }, +{ "label": "38/33", "node": 3488, "naklon": 5 }, +{ "label": "38/34", "node": 3505, "naklon": 5 }, +{ "label": "38/36", "node": 3497, "naklon": 5 }, +{ "label": "38/37", "node": 3490, "naklon": 5 }, +{ "label": "38/39", "node": 3585, "naklon": 5 }, +{ "label": "38/40", "node": 3582, "naklon": 5 }, +{ "label": "38/41", "node": 3507, "naklon": 5 }, +{ "label": "38/42", "node": 3484, "naklon": 5 }, +{ "label": "38/43", "node": 3501, "naklon": 5 }, +{ "label": "38/44", "node": 3581, "naklon": 5 }, +{ "label": "38/45", "node": 4192, "naklon": 5 }, +{ "label": "38/46", "node": 3576, "naklon": 5 }, +{ "label": "38/47", "node": 3489, "naklon": 5 }, +{ "label": "38/48", "node": 3573, "naklon": 5 }, +{ "label": "38/49", "node": 3504, "naklon": 5 }, +{ "label": "38/50", "node": 3794, "naklon": 5 }, +{ "label": "38/51", "node": 3485, "naklon": 5 }, +{ "label": "38/52", "node": 3482, "naklon": 5 }, +{ "label": "38/53", "node": 3575, "naklon": 5 }, +{ "label": "38/54", "node": 3499, "naklon": 5 }, +{ "label": "38/55", "node": 3494, "naklon": 5 }, +{ "label": "38/56", "node": 3583, "naklon": 5 }, +{ "label": "38/57", "node": 3570, "naklon": 5 }, +{ "label": "38/58", "node": 3500, "naklon": 0 }, +{ "label": "38/63", "node": 3510, "naklon": null }, +{ "label": "38/64", "node": 3512, "naklon": null }, +{ "label": "38/67", "node": 3535, "naklon": null }, +{ "label": "38/68", "node": 3531, "naklon": null }, +{ "label": "38/69", "node": 3537, "naklon": null }, +{ "label": "39/1", "node": 3522, "naklon": 10 }, +{ "label": "39/2", "node": 4018, "naklon": 10 }, +{ "label": "39/3", "node": 4019, "naklon": 10 }, +{ "label": "39/4", "node": 4154, "naklon": 5 }, +{ "label": "39/5", "node": 3907, "naklon": 5 }, +{ "label": "39/6", "node": 4148, "naklon": 0 }, +{ "label": "39/7", "node": 4153, "naklon": 0 }, +{ "label": "39/8", "node": 3938, "naklon": 0 }, +{ "label": "39/9", "node": 3802, "naklon": 0 }, +{ "label": "39/10", "node": 4015, "naklon": 0 }, +{ "label": "39/11", "node": 3929, "naklon": 0 }, +{ "label": "39/12", "node": 3946, "naklon": 0 }, +{ "label": "39/13", "node": 4014, "naklon": 0 }, +{ "label": "39/14", "node": 4155, "naklon": 0 }, +{ "label": "39/15", "node": 4149, "naklon": 0 }, +{ "label": "39/16", "node": 3642, "naklon": 0 }, +{ "label": "39/17", "node": 3636, "naklon": 5 }, +{ "label": "39/18", "node": 3991, "naklon": 0 }, +{ "label": "39/19", "node": 3994, "naklon": 0 }, +{ "label": "39/20", "node": 3990, "naklon": 0 }, +{ "label": "39/21", "node": 3967, "naklon": 0 }, +{ "label": "39/22", "node": 3977, "naklon": 0 }, +{ "label": "39/23", "node": 3757, "naklon": 15 }, +{ "label": "39/24", "node": 3633, "naklon": 15 }, +{ "label": "39/25", "node": 3744, "naklon": 15 }, +{ "label": "39/26", "node": 4023, "naklon": 5 }, +{ "label": "39/27", "node": 3720, "naklon": 5 }, +{ "label": "39/28", "node": 3734, "naklon": 5 }, +{ "label": "39/29", "node": 3741, "naklon": 5 }, +{ "label": "39/30", "node": 3721, "naklon": 5 }, +{ "label": "39/31", "node": 3845, "naklon": 0 }, +{ "label": "39/32", "node": 3840, "naklon": 0 }, +{ "label": "39/33", "node": 3837, "naklon": null }, +{ "label": "39/34", "node": 3839, "naklon": 0 }, +{ "label": "41/1", "node": 3542, "naklon": null }, +{ "label": "41/2", "node": 3566, "naklon": null }, +{ "label": "41/3", "node": 3548, "naklon": null }, +{ "label": "41/4", "node": 3515, "naklon": null }, +{ "label": "41/5", "node": 3559, "naklon": null }, +{ "label": "41/6", "node": 3509, "naklon": null }, +{ "label": "41/7", "node": 3524, "naklon": null }, +{ "label": "41/8", "node": 3518, "naklon": null }, +{ "label": "41/9", "node": 3182, "naklon": null }, +{ "label": "41/10", "node": 3187, "naklon": null }, +{ "label": "41/11", "node": 3195, "naklon": 0 }, +{ "label": "41/12", "node": 3857, "naklon": 0 }, +{ "label": "41/13", "node": 3183, "naklon": 0 }, +{ "label": "41/14", "node": 3177, "naklon": 0 }, +{ "label": "41/15", "node": 3189, "naklon": 0 }, +{ "label": "41/16", "node": 3186, "naklon": 0 }, +{ "label": "42/1", "node": 3178, "naklon": 0 }, +{ "label": "42/2", "node": 3219, "naklon": 0 }, +{ "label": "42/3", "node": 3475, "naklon": 0 }, +{ "label": "42/4", "node": 3175, "naklon": 0 }, +{ "label": "42/5", "node": 3222, "naklon": 0 }, +{ "label": "42/6", "node": 3221, "naklon": 0 }, +{ "label": "42/7", "node": 3181, "naklon": 0 }, +{ "label": "42/8", "node": 3180, "naklon": 0 }, +{ "label": "42/9", "node": 3218, "naklon": 0 }, +{ "label": "42/10", "node": 3176, "naklon": 0 }, +{ "label": "42/11", "node": 3174, "naklon": 0 }, +{ "label": "42/12", "node": 3220, "naklon": 0 }, +{ "label": "42/13", "node": 3533, "naklon": null }, +{ "label": "42/14", "node": 3543, "naklon": null }, +{ "label": "42/15", "node": 3554, "naklon": null }, +{ "label": "42/16", "node": 3549, "naklon": null }, +{ "label": "43/1", "node": 2857, "naklon": 5 }, +{ "label": "43/2", "node": 2752, "naklon": 5 }, +{ "label": "43/3", "node": 2753, "naklon": 5 }, +{ "label": "43/4", "node": 3024, "naklon": 5 }, +{ "label": "43/5", "node": 2754, "naklon": 5 }, +{ "label": "43/6", "node": 4423, "naklon": 5 }, +{ "label": "43/7", "node": 4368, "naklon": 5 }, +{ "label": "43/8", "node": 2978, "naklon": 5 }, +{ "label": "43/9", "node": 2868, "naklon": 5 }, +{ "label": "43/10", "node": 4377, "naklon": 5 }, +{ "label": "43/11", "node": 2757, "naklon": 5 }, +{ "label": "43/12", "node": 2970, "naklon": 5 }, +{ "label": "43/13", "node": 2758, "naklon": 5 }, +{ "label": "43/14", "node": 4378, "naklon": 5 }, +{ "label": "43/15", "node": 2759, "naklon": 5 }, +{ "label": "43/16", "node": 4342, "naklon": 5 }, +{ "label": "43/17", "node": 3026, "naklon": null }, +{ "label": "43/18", "node": 2986, "naklon": null }, +{ "label": "43/19", "node": 4343, "naklon": null }, +{ "label": "43/20", "node": 2760, "naklon": null }, +{ "label": "43/21", "node": 4379, "naklon": null }, +{ "label": "43/22", "node": 2971, "naklon": null }, +{ "label": "43/23", "node": 2761, "naklon": null }, +{ "label": "43/24", "node": 2762, "naklon": null }, +{ "label": "43/25", "node": 4339, "naklon": null }, +{ "label": "43/26", "node": 4380, "naklon": null }, +{ "label": "43/27", "node": 2975, "naklon": null }, +{ "label": "43/28", "node": 3003, "naklon": null }, +{ "label": "43/29", "node": 4338, "naklon": null }, +{ "label": "43/30", "node": 3002, "naklon": null }, +{ "label": "43/31", "node": 4345, "naklon": null }, +{ "label": "43/32", "node": 2979, "naklon": null }, +{ "label": "43/33", "node": 2989, "naklon": null }, +{ "label": "43/34", "node": 2996, "naklon": null }, +{ "label": "43/35", "node": 2972, "naklon": null }, +{ "label": "43/36", "node": 2988, "naklon": null }, +{ "label": "43/37", "node": 4344, "naklon": null }, +{ "label": "43/38", "node": 3022, "naklon": null }, +{ "label": "43/39", "node": 4341, "naklon": null }, +{ "label": "43/40", "node": 2983, "naklon": null }, +{ "label": "43/41", "node": 2995, "naklon": null }, +{ "label": "43/42", "node": 2763, "naklon": null }, +{ "label": "43/43", "node": 2764, "naklon": null }, +{ "label": "43/44", "node": 2765, "naklon": null }, +{ "label": "43/45", "node": 2766, "naklon": null }, +{ "label": "43/46", "node": 2767, "naklon": null }, +{ "label": "43/47", "node": 2768, "naklon": null }, +{ "label": "43/48", "node": 3018, "naklon": null }, +{ "label": "43/49", "node": 2982, "naklon": null }, +{ "label": "43/50", "node": 3019, "naklon": 0 }, +{ "label": "43/51", "node": 3013, "naklon": null }, +{ "label": "43/52", "node": 3007, "naklon": null }, +{ "label": "43/53", "node": 2980, "naklon": null }, +{ "label": "43/54", "node": 3011, "naklon": null }, +{ "label": "43/55", "node": 2672, "naklon": null }, +{ "label": "43/56", "node": 2673, "naklon": null }, +{ "label": "43/57", "node": 2674, "naklon": null }, +{ "label": "43/58", "node": 2675, "naklon": null }, +{ "label": "43/59", "node": 2676, "naklon": null }, +{ "label": "43/60", "node": 2677, "naklon": null }, +{ "label": "43/61", "node": 2678, "naklon": null }, +{ "label": "43/62", "node": 2679, "naklon": null }, +{ "label": "43/63", "node": 2680, "naklon": null }, +{ "label": "43/64", "node": 2840, "naklon": null }, +{ "label": "43/65", "node": 2682, "naklon": null }, +{ "label": "43/66", "node": 2683, "naklon": null }, +{ "label": "43/67", "node": 2684, "naklon": 0 }, +{ "label": "43/68", "node": 2685, "naklon": null }, +{ "label": "43/69", "node": 2686, "naklon": null }, +{ "label": "43/70", "node": 2687, "naklon": null }, +{ "label": "43/71", "node": 2688, "naklon": null }, +{ "label": "43/72", "node": 2689, "naklon": null }, +{ "label": "43/73", "node": 2690, "naklon": null }, +{ "label": "43/74", "node": 2691, "naklon": null }, +{ "label": "43/75", "node": 2692, "naklon": null }, +{ "label": "43/76", "node": 2693, "naklon": 0 }, +{ "label": "43/77", "node": 2694, "naklon": null }, +{ "label": "43/78", "node": 2695, "naklon": null }, +{ "label": "43/79", "node": 2696, "naklon": 0 }, +{ "label": "43/80", "node": 2697, "naklon": null }, +{ "label": "43/81", "node": 2698, "naklon": 0 }, +{ "label": "43/82", "node": 2699, "naklon": null }, +{ "label": "43/83", "node": 2700, "naklon": 0 }, +{ "label": "43/84", "node": 2744, "naklon": null }, +{ "label": "43/85", "node": 2745, "naklon": 0 }, +{ "label": "43/86", "node": 2746, "naklon": null }, +{ "label": "43/87", "node": 2747, "naklon": 0 }, +{ "label": "43/88", "node": 2748, "naklon": null }, +{ "label": "43/89", "node": 2749, "naklon": 0 }, +{ "label": "43/90", "node": 2841, "naklon": null }, +{ "label": "45/1", "node": 4237, "naklon": 5 }, +{ "label": "45/2", "node": 4226, "naklon": 5 }, +{ "label": "45/3", "node": 4242, "naklon": 5 }, +{ "label": "45/4", "node": 4179, "naklon": 5 }, +{ "label": "45/5", "node": 4247, "naklon": 5 }, +{ "label": "45/6", "node": 4245, "naklon": 5 }, +{ "label": "45/7", "node": 3872, "naklon": 5 }, +{ "label": "45/8", "node": 4175, "naklon": 5 }, +{ "label": "45/9", "node": 4236, "naklon": 5 }, +{ "label": "45/10", "node": 4170, "naklon": 5 }, +{ "label": "45/11", "node": 4238, "naklon": 5 }, +{ "label": "45/12", "node": 4246, "naklon": 5 }, +{ "label": "45/13", "node": 4166, "naklon": 5 }, +{ "label": "45/14", "node": 4227, "naklon": 5 }, +{ "label": "45/15", "node": 4171, "naklon": 5 }, +{ "label": "45/16", "node": 4180, "naklon": 5 }, +{ "label": "45/17", "node": 4244, "naklon": 5 }, +{ "label": "45/18", "node": 4199, "naklon": 5 }, +{ "label": "45/19", "node": 4239, "naklon": 5 }, +{ "label": "45/20", "node": 4207, "naklon": 5 }, +{ "label": "45/21", "node": 4223, "naklon": 5 }, +{ "label": "45/22", "node": 4230, "naklon": 5 }, +{ "label": "45/23", "node": 4233, "naklon": 5 }, +{ "label": "45/24", "node": 4222, "naklon": 5 }, +{ "label": "45/25", "node": 4217, "naklon": 5 }, +{ "label": "45/26", "node": 4243, "naklon": 5 }, +{ "label": "45/27", "node": 4200, "naklon": 5 }, +{ "label": "45/28", "node": 4228, "naklon": 5 }, +{ "label": "45/29", "node": 4211, "naklon": 5 }, +{ "label": "45/30", "node": 4234, "naklon": 5 }, +{ "label": "45/31", "node": 4235, "naklon": 5 }, +{ "label": "45/32", "node": 4203, "naklon": 5 }, +{ "label": "45/33", "node": 4240, "naklon": 5 }, +{ "label": "45/34", "node": 4224, "naklon": 5 }, +{ "label": "45/35", "node": 4232, "naklon": 5 }, +{ "label": "45/36", "node": 4231, "naklon": 5 }, +{ "label": "45/37", "node": 4161, "naklon": 5 }, +{ "label": "45/38", "node": 4225, "naklon": 5 }, +{ "label": "45/39", "node": 4241, "naklon": 5 }, +{ "label": "45/40", "node": 4229, "naklon": 5 }, +{ "label": "45/41", "node": 4221, "naklon": 5 }, +{ "label": "45/42", "node": 4212, "naklon": 5 }, +{ "label": "45/43", "node": 4216, "naklon": 5 }, +{ "label": "45/44", "node": 3864, "naklon": null }, +{ "label": "46/1", "node": 3806, "naklon": 5 }, +{ "label": "46/2", "node": 3813, "naklon": 5 }, +{ "label": "46/3", "node": 3815, "naklon": 5 }, +{ "label": "46/4", "node": 3807, "naklon": 5 }, +{ "label": "46/5", "node": 3895, "naklon": 5 }, +{ "label": "46/6", "node": 3809, "naklon": 5 }, +{ "label": "46/7", "node": 3820, "naklon": 5 }, +{ "label": "46/8", "node": 3805, "naklon": 5 }, +{ "label": "46/9", "node": 3894, "naklon": 0 }, +{ "label": "46/10", "node": 4055, "naklon": 0 }, +{ "label": "46/11", "node": 3812, "naklon": 5 }, +{ "label": "46/12", "node": 3822, "naklon": 5 }, +{ "label": "46/13", "node": 3821, "naklon": 5 }, +{ "label": "46/14", "node": 3808, "naklon": 5 }, +{ "label": "46/15", "node": 3799, "naklon": 5 }, +{ "label": "46/16", "node": 3816, "naklon": 5 }, +{ "label": "46/17", "node": 3751, "naklon": 5 }, +{ "label": "46/18", "node": 3814, "naklon": 5 }, +{ "label": "46/19", "node": 4044, "naklon": 0 }, +{ "label": "46/20", "node": 3931, "naklon": 0 }, +{ "label": "46/21", "node": 3902, "naklon": 5 }, +{ "label": "46/22", "node": 3916, "naklon": 5 }, +{ "label": "46/23", "node": 3892, "naklon": 5 }, +{ "label": "46/24", "node": 3914, "naklon": 5 }, +{ "label": "46/25", "node": 3898, "naklon": 5 }, +{ "label": "46/26", "node": 3897, "naklon": 5 }, +{ "label": "46/27", "node": 3885, "naklon": 5 }, +{ "label": "46/28", "node": 3906, "naklon": 5 }, +{ "label": "46/29", "node": 3930, "naklon": 0 }, +{ "label": "46/30", "node": 3936, "naklon": 0 }, +{ "label": "46/31", "node": 3860, "naklon": 5 }, +{ "label": "46/32", "node": 3841, "naklon": 5 }, +{ "label": "46/33", "node": 3873, "naklon": 5 }, +{ "label": "46/34", "node": 3854, "naklon": 5 }, +{ "label": "46/35", "node": 3939, "naklon": 5 }, +{ "label": "46/36", "node": 3858, "naklon": 5 }, +{ "label": "46/37", "node": 3940, "naklon": 5 }, +{ "label": "46/38", "node": 4035, "naklon": 5 }, +{ "label": "47/1", "node": 3373, "naklon": 0 }, +{ "label": "47/2", "node": 3374, "naklon": 0 }, +{ "label": "47/3", "node": 3384, "naklon": 0 }, +{ "label": "47/4", "node": 3385, "naklon": 0 }, +{ "label": "48/1", "node": 4051, "naklon": 5 }, +{ "label": "48/2", "node": 4041, "naklon": 5 }, +{ "label": "48/3", "node": 4056, "naklon": 5 }, +{ "label": "48/4", "node": 3875, "naklon": 5 }, +{ "label": "48/5", "node": 4061, "naklon": 5 }, +{ "label": "48/6", "node": 4047, "naklon": 5 }, +{ "label": "48/7", "node": 4060, "naklon": 5 }, +{ "label": "48/8", "node": 4059, "naklon": 5 }, +{ "label": "48/9", "node": 4058, "naklon": 5 }, +{ "label": "48/10", "node": 3635, "naklon": 5 }, +{ "label": "48/11", "node": 3640, "naklon": 5 }, +{ "label": "48/12", "node": 3747, "naklon": 5 }, +{ "label": "48/13", "node": 3629, "naklon": 5 }, +{ "label": "48/14", "node": 4048, "naklon": 5 }, +{ "label": "48/15", "node": 4063, "naklon": 5 }, +{ "label": "48/16", "node": 4062, "naklon": 5 }, +{ "label": "48/17", "node": 4043, "naklon": 5 }, +{ "label": "48/18", "node": 4052, "naklon": 5 }, +{ "label": "48/19", "node": 4042, "naklon": 5 }, +{ "label": "48/20", "node": 4053, "naklon": 5 }, +{ "label": "50/15A", "node": 4167, "naklon": null }, +{ "label": "50/15B", "node": 4159, "naklon": null }, +{ "label": "50/1", "node": 4183, "naklon": 0 }, +{ "label": "50/2", "node": 4157, "naklon": 0 }, +{ "label": "50/3", "node": 4160, "naklon": 0 }, +{ "label": "50/4", "node": 4173, "naklon": 0 }, +{ "label": "50/5", "node": 4177, "naklon": 0 }, +{ "label": "50/6", "node": 4174, "naklon": 0 }, +{ "label": "50/7", "node": 4178, "naklon": 0 }, +{ "label": "50/8", "node": 4195, "naklon": 0 }, +{ "label": "50/9", "node": 4169, "naklon": 0 }, +{ "label": "50/10", "node": 4162, "naklon": 0 }, +{ "label": "50/11", "node": 4158, "naklon": 0 }, +{ "label": "50/12", "node": 4182, "naklon": 0 }, +{ "label": "50/13", "node": 4194, "naklon": 0 }, +{ "label": "50/14", "node": 4184, "naklon": 0 }, +{ "label": "50/16", "node": 4197, "naklon": null }, +{ "label": "50/17", "node": 4164, "naklon": null }, +{ "label": "50/18", "node": 3306, "naklon": null }, +{ "label": "50/19", "node": 4168, "naklon": null }, +{ "label": "50/20", "node": 4193, "naklon": null }, +{ "label": "50/21", "node": 4187, "naklon": null }, +{ "label": "50/22", "node": 4163, "naklon": null }, +{ "label": "50/23", "node": 4165, "naklon": null }, +{ "label": "50/24", "node": 4185, "naklon": null }, +{ "label": "50/25", "node": 3904, "naklon": null }, +{ "label": "53/1", "node": 2619, "naklon": 0 }, +{ "label": "53/2", "node": 2623, "naklon": 0 }, +{ "label": "53/3", "node": 2617, "naklon": 0 }, +{ "label": "53/4", "node": 2622, "naklon": 0 }, +{ "label": "53/5", "node": 2618, "naklon": 0 }, +{ "label": "53/6", "node": 2626, "naklon": 0 }, +{ "label": "53/7", "node": 2869, "naklon": 0 }, +{ "label": "53/8", "node": 2613, "naklon": 0 }, +{ "label": "53/9", "node": 2608, "naklon": 0 }, +{ "label": "53/10", "node": 2611, "naklon": 0 }, +{ "label": "53/11", "node": 2598, "naklon": 0 }, +{ "label": "53/12", "node": 3528, "naklon": 0 }, +{ "label": "53/13", "node": 3545, "naklon": 0 }, +{ "label": "53/14", "node": 2620, "naklon": 0 }, +{ "label": "53/15", "node": 2612, "naklon": 0 }, +{ "label": "53/16", "node": 2615, "naklon": 0 }, +{ "label": "53/17", "node": 3722, "naklon": 0 }, +{ "label": "53/18", "node": 2624, "naklon": 0 }, +{ "label": "53/19", "node": 2609, "naklon": 0 }, +{ "label": "53/20", "node": 2625, "naklon": 0 }, +{ "label": "53/21", "node": 2602, "naklon": 0 }, +{ "label": "53/22", "node": 2610, "naklon": 0 }, +{ "label": "53/23", "node": 2599, "naklon": 0 }, +{ "label": "53/24", "node": 2605, "naklon": 0 }, +{ "label": "53/25", "node": 2593, "naklon": 0 }, +{ "label": "53/26", "node": 3074, "naklon": 0 }, +{ "label": "53/27", "node": 2740, "naklon": 0 }, +{ "label": "53/28", "node": 2614, "naklon": 0 }, +{ "label": "53/29", "node": 2601, "naklon": 0 }, +{ "label": "53/30", "node": 4196, "naklon": 0 }, +{ "label": "53/31", "node": 2607, "naklon": 0 }, +{ "label": "53/32", "node": 2582, "naklon": 0 }, +{ "label": "53/33", "node": 2594, "naklon": 0 }, +{ "label": "53/34", "node": 2589, "naklon": 0 }, +{ "label": "53/35", "node": 2596, "naklon": 0 }, +{ "label": "53/36", "node": 2603, "naklon": 0 }, +{ "label": "53/37", "node": 2597, "naklon": 0 }, +{ "label": "53/38", "node": 2590, "naklon": 0 }, +{ "label": "53/39", "node": 2581, "naklon": 0 }, +{ "label": "53/40", "node": 2583, "naklon": 0 }, +{ "label": "53/41", "node": 2580, "naklon": 0 }, +{ "label": "53/42", "node": 2579, "naklon": 0 }, +{ "label": "53/43", "node": 2797, "naklon": 0 }, +{ "label": "53/44", "node": 2577, "naklon": 0 }, +{ "label": "53/45", "node": 2586, "naklon": 0 }, +{ "label": "53/46", "node": 2588, "naklon": 0 }, +{ "label": "53/47", "node": 2591, "naklon": 0 }, +{ "label": "53/48", "node": 2592, "naklon": 0 }, +{ "label": "53/49", "node": 2573, "naklon": 0 }, +{ "label": "53/50", "node": 2595, "naklon": 0 }, +{ "label": "53/51", "node": 2587, "naklon": 0 }, +{ "label": "53/52", "node": 2578, "naklon": 0 }, +{ "label": "53/53", "node": 2574, "naklon": 0 }, +{ "label": "53/54", "node": 2571, "naklon": 0 }, +{ "label": "53/55", "node": 2570, "naklon": 0 }, +{ "label": "53/56", "node": 2576, "naklon": 0 }, +{ "label": "53/57", "node": 2881, "naklon": 0 }, +{ "label": "53/58", "node": 2575, "naklon": 0 }, +{ "label": "53/59", "node": 2572, "naklon": 0 }, +{ "label": "53/60", "node": 2569, "naklon": 0 }, +{ "label": "55/1", "node": 4324, "naklon": 0 }, +{ "label": "55/2", "node": 4319, "naklon": 0 }, +{ "label": "55/3", "node": 4327, "naklon": 0 }, +{ "label": "55/4", "node": 4333, "naklon": 0 }, +{ "label": "55/5", "node": 4332, "naklon": 0 }, +{ "label": "55/6", "node": 4320, "naklon": 0 }, +{ "label": "55/7", "node": 4317, "naklon": 0 }, +{ "label": "55/8", "node": 4318, "naklon": 0 }, +{ "label": "55/9", "node": 4328, "naklon": 0 }, +{ "label": "55/10", "node": 4323, "naklon": 0 }, +{ "label": "55/11", "node": 4325, "naklon": 0 }, +{ "label": "55/12", "node": 4326, "naklon": 0 }, +{ "label": "55/13", "node": 4316, "naklon": 0 }, +{ "label": "55/14", "node": 4322, "naklon": 0 }, +{ "label": "55/15", "node": 4331, "naklon": 0 }, +{ "label": "55/16", "node": 4321, "naklon": 0 }, +{ "label": "55/17", "node": 4315, "naklon": 0 }, +{ "label": "55/18", "node": 4329, "naklon": 0 }, +{ "label": "55/19", "node": 4334, "naklon": 0 }, +{ "label": "55/20", "node": 4330, "naklon": 0 } +]; + +module.exports = { naklony }; diff --git a/RVO12/databases/modbus_config.js b/RVO12/databases/modbus_config.js new file mode 100755 index 0000000..b73116a --- /dev/null +++ b/RVO12/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/RVO12/databases/nodes.table b/RVO12/databases/nodes.table new file mode 100755 index 0000000..22e2fd9 --- /dev/null +++ b/RVO12/databases/nodes.table @@ -0,0 +1,50 @@ +node:number|pole_number:string|node_type:string|tbname:string|line:number|profile:string|processed:boolean|status:boolean|time_of_last_communication:number ++|3356|3|NEMA|aw4eELG2DlPMdn1JW0BM4qAqQXOZRN3xB5yp8VKr|1||1|1|1760573661937|............. ++|3349|4|NEMA|ZmRwd93QL4gaezxEbAx2XXk1prn2XjlPvGyqJ6BO|1||1|1|1760573672834|............. ++|3350|6|NEMA|3a5oqJN1bgnx4Ol9dk89dw7ByE6jQ8mKDWMpGrLV|1||1|1|1760573647972|............. ++|3357|5|NEMA|eod9aRWLVl34Gx1Dn7VNmb72rz6qjgmpEXwQJN5Z|1||1|1|1760573662304|............. ++|3355|2|NEMA|B5EoxeMVp4zwr8nqW0GBnoARjvD1PNamOGbLg63Z|1||1|1|1760573625012|............. ++|3358|12|IP65|1JMYvnx2RzKEo4aWQ7DGdVkL8yZV3m9NBePXbrdj|1||1|1|1760573626194|............. ++|3359|43|NEMA|1JMYvnx2RzKEo4aWQ7DGrzkL8yZV3m9NBePXbrdj|1||1|1|1760573623734|............. ++|3360|11|NEMA|Z5KyJe9nEg1QNbWlX0w4q9koDjBLdqzR83VGv624|1||1|1|1760573623957|............. ++|3361|10|NEMA|3JjOWdylwgNLzxVab7Na4ykZ2vG64rq8PEB5QmDo|1||1|1|1760573624197|............. ++|3362|1|NEMA|d9x2V5LGYBzXp4mMRAOmrnkPloaqJwnQj6DgrNe3|1||1|1|1760573667657|............. ++|3447|24|NEMA|nJL5lPMwBx23YpqRe0rpJ37damXvWVbOrD4gNzy8|1||1|1|1760573670853|............. ++|3469|40|NEMA|RO8rjaBDy21qPQJzW7omoD0pK3xmNleVZg9Ed4Gw|1||1|1|1760573900263|............. ++|3511|20|IP65|PLBJzmK1r3Gynd6OW0gKLY0e5wV4vx9bDEqNgYR8|1||1|1|1760573671396|............. ++|3514|15|IP65|K94XLav1glVRnyQ6r01PbNAme3YJwBxM5oOzdP2j|1||1|1|1760574198710|............. ++|3525|18|IP65|3a5oqJN1bgnx4Ol9dk89Ma7ByE6jQ8mKDWMpGrLV|1||1|1|1760574176421|............. ++|3541|13|IP65|PjLblDgRBO6WQqnxmkJ1mY0Jv3ewZN4p5a89yKdY|1||1|1|1760574176869|............. ++|3539|8|IP65|JX1ObgmqGZ54DMyYL7aD2VkEVdve38WKRzwjNrQ9|1||1|1|1760574176645|............. ++|3547|16|IP65|B5EoxeMVp4zwr8nqW0GBVeARjvD1PNamOGbLg63Z|1||1|1|1760574177093|............. ++|3551|14|IP65|gRoJEyXVx4qD9er287L4K57wBzGldaPjLWQKm3Mv|1||1|1|1760574177300|............. ++|3558|19|IP65|wvKJdZML6mXP4DzWBAXxmzAjxNloa5g23Ve9Y1ry|1||1|1|1760574209015|............. ++|3562|17|IP65|ZmRwd93QL4gaezxEbAx2JWk1prn2XjlPvGyqJ6BO|1||1|1|1760573633416|............. ++|2922|45|NEMA|dz4ojlpP85JMgDLZWkQJ6j7aKYqQexEr62GXRV1y|1||1|1|1760573638625|............. ++|2924|37|NEMA|OzNMgZ9n43qPbjXmy7zw3GA2DKdYvW5e6pxGRrVa|1||1|1|1760573775092|............. ++|2925|42|NEMA|Z5KyJe9nEg1QNbWlX0w48MkoDjBLdqzR83VGv624|1||1|1|1760573700300|............. ++|3050|9|NEMA|RO8rjaBDy21qPQJzW7omWd0pK3xmNleVZg9Ed4Gw|1||1|1|1760573750742|............. ++|3051|36|NEMA|g9OxBZ5KRwNznlY6pAppDmAWXvjdEL4eGQobMDy2|1||1|1|1760573751365|............. ++|3055|44|NEMA|PjLblDgRBO6WQqnxmkJ1Ea0Jv3ewZN4p5a89yKdY|1||1|1|1760573755631|............. ++|4163|25|NEMA|ZmRwd93QL4gaezxEbAx2Jwk1prn2XjlPvGyqJ6BO|1||1|1|1760573637938|............. ++|3057|26|NEMA|eod9aRWLVl34Gx1Dn7VN9D72rz6qjgmpEXwQJN5Z|1||1|1|1760573701834|............. ++|3058|21|NEMA|rDbQ84xzwgdqEoPm3kbEpL09anOZY1RXyBv2LVM6|1||1|1|1760573702217|............. ++|3060|38|NEMA|JX1ObgmqGZ54DMyYL7aD1JkEVdve38WKRzwjNrQ9|1||1|1|1760573702440|............. ++|3062|22|NEMA|E6Kg9oDnLWyzPRMva7v5JBkJxp4VG58qO2w1lZYe|1||1|1|1760573759130|............. ++|3064|47|NEMA|gRoJEyXVx4qD9er287L4ZO7wBzGldaPjLWQKm3Mv|1||1|1|1760573703463|............. ++|3066|48|NEMA|5dBNwRp9graYJxZn409N1qklVov1b2QLPDqGm6XK|1||1|1|1760573704710|............. ++|3067|35|NEMA|JzwxZXOvDj1bVrN4nkW5E8A8qdyBl3MRKLpGPgaQ|1||1|1|1760573838844|............. ++|3070|23|NEMA|roKgWqY95V3mXMRzyAjKJ30bLjexpJPvaGDBw826|1||1|1|1760573614019|............. ++|3071|27|NEMA|3a5oqJN1bgnx4Ol9dk89Mq7ByE6jQ8mKDWMpGrLV|1||1|1|1760573589812|............. ++|3072|49|NEMA|zrR51V2ajQ9ZLygPKkEMqKkYDq38xOJolENBXGnv|1||1|1|1760573589972|............. ++|3073|39|NEMA|RvmwNz8QPblKp41GD7lKoKkJrLVYoBO92dMegn6W|1||1|1|1760573590291|............. ++|3077|30|NEMA|Nzp2OoJlqn6r1ZgvdA3BjE7abBwP5G4eE3RQmyxD|1||1|1|1760573614722|............. ++|2923|41|NEMA|dz4ojlpP85JMgDLZWkQJZg7aKYqQexEr62GXRV1y|1||1|1|1760573373122|............. ++|3353|7|NEMA|JX1ObgmqGZ54DMyYL7aDVMkEVdve38WKRzwjNrQ9|1||1|1|1760573374863|............. ++|3069|29|NEMA|RO8rjaBDy21qPQJzW7omMW0pK3xmNleVZg9Ed4Gw|1||1|1|1760573613875|............. ++|3061|28|NEMA|RvmwNz8QPblKp41GD7lKd9kJrLVYoBO92dMegn6W|1||1|1|1760573757772|............. ++|4037|34|NEMA|PjLblDgRBO6WQqnxmkJ1dB0Jv3ewZN4p5a89yKdY|1||1|1|1760573633832|............. ++|3078|33|NEMA|1JMYvnx2RzKEo4aWQ7DGgLkL8yZV3m9NBePXbrdj|1||1|1|1760573713993|............. ++|3080|31|NEMA|3JjOWdylwgNLzxVab7Na9bkZ2vG64rq8PEB5QmDo|1||1|1|1760573714200|............. ++|3081|32|NEMA|Z5KyJe9nEg1QNbWlX0w4B8koDjBLdqzR83VGv624|1||1|1|1760573714983|............. ++|3084|46|NEMA|d5xjWYMwEJon6rLlK7yEPP7qgV4DaOeNB9ZX3Gzb|1||1|1|1760573718386|............. diff --git a/RVO12/databases/nodes_original/nodes_original.table b/RVO12/databases/nodes_original/nodes_original.table new file mode 100755 index 0000000..f3e5262 --- /dev/null +++ b/RVO12/databases/nodes_original/nodes_original.table @@ -0,0 +1 @@ +[{"3356": "aw4eELG2DlPMdn1JW0BM4qAqQXOZRN3xB5yp8VKr"}, {"3349": "ZmRwd93QL4gaezxEbAx2XXk1prn2XjlPvGyqJ6BO"}, {"3350": "3a5oqJN1bgnx4Ol9dk89dw7ByE6jQ8mKDWMpGrLV"}, {"3357": "eod9aRWLVl34Gx1Dn7VNmb72rz6qjgmpEXwQJN5Z"}, {"3355": "B5EoxeMVp4zwr8nqW0GBnoARjvD1PNamOGbLg63Z"}, {"3358": "1JMYvnx2RzKEo4aWQ7DGdVkL8yZV3m9NBePXbrdj"}, {"3359": "1JMYvnx2RzKEo4aWQ7DGrzkL8yZV3m9NBePXbrdj"}, {"3360": "Z5KyJe9nEg1QNbWlX0w4q9koDjBLdqzR83VGv624"}, {"3361": "3JjOWdylwgNLzxVab7Na4ykZ2vG64rq8PEB5QmDo"}, {"3362": "d9x2V5LGYBzXp4mMRAOmrnkPloaqJwnQj6DgrNe3"}, {"3447": "nJL5lPMwBx23YpqRe0rpJ37damXvWVbOrD4gNzy8"}, {"3469": "RO8rjaBDy21qPQJzW7omoD0pK3xmNleVZg9Ed4Gw"}, {"3511": "PLBJzmK1r3Gynd6OW0gKLY0e5wV4vx9bDEqNgYR8"}, {"3514": "K94XLav1glVRnyQ6r01PbNAme3YJwBxM5oOzdP2j"}, {"3525": "3a5oqJN1bgnx4Ol9dk89Ma7ByE6jQ8mKDWMpGrLV"}, {"3541": "PjLblDgRBO6WQqnxmkJ1mY0Jv3ewZN4p5a89yKdY"}, {"3539": "JX1ObgmqGZ54DMyYL7aD2VkEVdve38WKRzwjNrQ9"}, {"3547": "B5EoxeMVp4zwr8nqW0GBVeARjvD1PNamOGbLg63Z"}, {"3551": "gRoJEyXVx4qD9er287L4K57wBzGldaPjLWQKm3Mv"}, {"3558": "wvKJdZML6mXP4DzWBAXxmzAjxNloa5g23Ve9Y1ry"}, {"3562": "ZmRwd93QL4gaezxEbAx2JWk1prn2XjlPvGyqJ6BO"}, {"2922": "dz4ojlpP85JMgDLZWkQJ6j7aKYqQexEr62GXRV1y"}, {"2924": "OzNMgZ9n43qPbjXmy7zw3GA2DKdYvW5e6pxGRrVa"}, {"2925": "Z5KyJe9nEg1QNbWlX0w48MkoDjBLdqzR83VGv624"}, {"3050": "RO8rjaBDy21qPQJzW7omWd0pK3xmNleVZg9Ed4Gw"}, {"3051": "g9OxBZ5KRwNznlY6pAppDmAWXvjdEL4eGQobMDy2"}, {"3055": "PjLblDgRBO6WQqnxmkJ1Ea0Jv3ewZN4p5a89yKdY"}, {"4163": "ZmRwd93QL4gaezxEbAx2Jwk1prn2XjlPvGyqJ6BO"}, {"3057": "eod9aRWLVl34Gx1Dn7VN9D72rz6qjgmpEXwQJN5Z"}, {"3058": "rDbQ84xzwgdqEoPm3kbEpL09anOZY1RXyBv2LVM6"}, {"3060": "JX1ObgmqGZ54DMyYL7aD1JkEVdve38WKRzwjNrQ9"}, {"3062": "E6Kg9oDnLWyzPRMva7v5JBkJxp4VG58qO2w1lZYe"}, {"3064": "gRoJEyXVx4qD9er287L4ZO7wBzGldaPjLWQKm3Mv"}, {"3066": "5dBNwRp9graYJxZn409N1qklVov1b2QLPDqGm6XK"}, {"3067": "JzwxZXOvDj1bVrN4nkW5E8A8qdyBl3MRKLpGPgaQ"}, {"3070": "roKgWqY95V3mXMRzyAjKJ30bLjexpJPvaGDBw826"}, {"3071": "3a5oqJN1bgnx4Ol9dk89Mq7ByE6jQ8mKDWMpGrLV"}, {"3072": "zrR51V2ajQ9ZLygPKkEMqKkYDq38xOJolENBXGnv"}, {"3073": "RvmwNz8QPblKp41GD7lKoKkJrLVYoBO92dMegn6W"}, {"3077": "Nzp2OoJlqn6r1ZgvdA3BjE7abBwP5G4eE3RQmyxD"}, {"2923": "dz4ojlpP85JMgDLZWkQJZg7aKYqQexEr62GXRV1y"}, {"3353": "JX1ObgmqGZ54DMyYL7aDVMkEVdve38WKRzwjNrQ9"}, {"3069": "RO8rjaBDy21qPQJzW7omMW0pK3xmNleVZg9Ed4Gw"}, {"3061": "RvmwNz8QPblKp41GD7lKd9kJrLVYoBO92dMegn6W"}, {"4037": "PjLblDgRBO6WQqnxmkJ1dB0Jv3ewZN4p5a89yKdY"}, {"3078": "1JMYvnx2RzKEo4aWQ7DGgLkL8yZV3m9NBePXbrdj"}, {"3080": "3JjOWdylwgNLzxVab7Na9bkZ2vG64rq8PEB5QmDo"}, {"3081": "Z5KyJe9nEg1QNbWlX0w4B8koDjBLdqzR83VGv624"}, {"3084": "d5xjWYMwEJon6rLlK7yEPP7qgV4DaOeNB9ZX3Gzb"}] \ No newline at end of file diff --git a/RVO12/databases/notifications.table b/RVO12/databases/notifications.table new file mode 100755 index 0000000..f7c96cb --- /dev/null +++ b/RVO12/databases/notifications.table @@ -0,0 +1,41 @@ +key:string|weight:string|sk:string|en:string ++|switching_profile_point_applied_to_line|INFORMATIONAL|Aplikovaný bod spínacieho profilu na línií č. ${line} : ${value}|Switching profile point applied to line no. ${line} : ${value}|............... ++|dusk_has_occured|INFORMATIONAL|Nastal súmrak: ${value}|Dusk has occured: ${value}|............... ++|dawn_has_occured|INFORMATIONAL|Nastal úsvit: ${value}|Dawn has occured: ${value}|............... ++|dimming_profile_was_successfully_received_by_node|NOTICE|Stmievací profil bol úspešne prijatý nodom č. ${node}|Dimming profile was successfully received by node no. ${node}|............... ++|master_node_is_responding_again|NOTICE|Master node začal znovu odpovedať|Master node is responding again|............... ++|command_was_sent_from_terminal_interface|DEBUG|Z terminálu bol odoslaný príkaz|A command was sent from terminal interface|............... ++|master_node_is_not_responding|ALERT|Master node neodpovedá|Master node is not responding|............... ++|configuration_of_dimming_profile_to_node_failed|ALERT|Konfigurácia stmievacieho profilu pre node č. ${node} zlyhala|Configuration of dimming profile to node no. ${node} has failed|............... ++|circuit_breaker_was_turned_on_line|NOTICE|Zapnutie ističa na línii č. ${line}|Circuit breaker was turned on - line no. ${line}|............... ++|circuit_breaker_was_turned_off_line|ERROR|Vypnutie ističa na línií č. ${line}|Circuit breaker was turned off - line no. ${line}|............... ++|dimming_profile_was_processed_for_node|INFORMATIONAL|Stmievací profil bol spracovaný pre node č. ${node}|Dimming profile was processed for node no. ${node}|............... ++|switching_profile_was_processed_for_line|INFORMATIONAL|Spínací profil bol spracovaný pre líniu č. ${line}|Switching profile was processed for line no. ${line}|............... ++|thermometer_is_not_responding|WARNING|Teplomer neodpovedá|Thermometer is not responding|............... ++|thermometer_is_responding_again|NOTICE|Teplomer znovu odpovedá|Thermometer is responding again|............... ++|thermometer_sends_invalid_data|WARNING|Teplomer posiela neplatné hodnoty|Thermometer sends invalid data|............... ++|main_switch_has_been_turned_off|CRITICAL|Hlavný vypínač bol vypnutý|Main switch has been turned off|............... ++|main_switch_has_been_turned_on|NOTICE|Hlavný vypínač bol zapnutý|Main switch has been turned on|............... ++|power_supply_has_disconnected_input|ALERT|Napájací zdroj nemá napätie na vstupe|Power supply has disconnected input|............... ++|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_main_open|NOTICE|Hlavné dvere boli otvorené|Main door has been opened|............... ++|door_em_open|NOTICE|Dvere silovej časti boli otvorené|Power door has been opened|............... ++|door_main_open_without_permission|WARNING|Hlavné dvere boli otvorené bez povolenia - zapnutá siréna|Main door has been opened without permission - alarm is on|............... ++|door_em_open_without_permission|WARNING|Dvere silovej časti boli otvorené bez povolenia|Power door has been opened without permission|............... ++|door_main_close|NOTICE|Hlavné dvere boli zatvorené|Main door has been closed|............... ++|door_em_close|NOTICE|Dvere silovej časti boli zatvorené|Power door has been closed|............... ++|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|............... ++|electrometer_ok|NOTICE|Elektromer znovu odpovedá|Electrometer is responding again|............... ++|no_voltage_on_phase|CRITICAL|Na fáze č. ${phase} nie je napätie|No voltage detected on phase no. ${phase}|............... ++|voltage_on_phase_restored|NOTICE|Napätie na fáze č. ${phase} bolo obnovené|Voltage on phase no. ${phase} has been restored|............... ++|flow_start|NOTICE|FLOW bol spustený|FLOW has been started |............... ++|twilight_sensor_nok|ERROR|Sensor súmraku neodpovedá|Twilight sensor is not responding|............... ++|twilight_sensor_ok|NOTICE|Sensor súmraku znovu odpovedá|Twilight sensor is responding again|............... ++|lamps_have_turned_on|NOTICE|Lampy sa zapli|Lamps have turned on|............... ++|lamps_have_turned_off|NOTICE|Lampy sa vypli|Lamps have turned off|............... ++|flow_restart|NOTICE|FLOW bol reštartovaný|FLOW has been restarted|............... ++|nodes_db_changed|NOTICE|Zmena v node databáze|Node db has changed|............... diff --git a/RVO12/databases/pins.table b/RVO12/databases/pins.table new file mode 100755 index 0000000..0eb3d05 --- /dev/null +++ b/RVO12/databases/pins.table @@ -0,0 +1,14 @@ +pin:string|type:string|line:number +*|input1_01|door_condition|0|........... +*|input1_02|rotary_switch_state|0|........... +*|input1_03|rotary_switch_state|0|........... +*|input1_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/RVO12/databases/relays.table b/RVO12/databases/relays.table new file mode 100755 index 0000000..f3533e6 --- /dev/null +++ b/RVO12/databases/relays.table @@ -0,0 +1,5 @@ +line:number|tbname:string|contactor:number|profile:string ++|0|XMBbew5z4ELrZa2mRAd3zV78vPN6gy3DdVYlpKjq|1||........... ++|3|WlVJBygjDZMeKX3vnAMRxj08NqdmG2x1Y69LQ4P5|9|{"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}|................................................................................................................................................................................................................................................................................................................................... ++|1|gYbDLqlyZVoRerQpB72MELkWJnwM5z24POKa8Exj|9|{"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|zdQO8GwxDqjRgP4137YVd6ANyKlpem2nL65rvVJY|9|{"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/RVO12/databases/settings.table b/RVO12/databases/settings.table new file mode 100755 index 0000000..359075c --- /dev/null +++ b/RVO12/databases/settings.table @@ -0,0 +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|project_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|cloud_topic:string|has_main_switch:boolean|daily_report:boolean|send_changed_node_numbers:boolean ++|rvo_senica_12_ip112|en|28.592C9C0E0000|48.70826502|17.28455203|192.168.252.1|rvo_senica_12_ip112|6t93IKyPbNAjsAyNtMzk|1883|0|54|unipi|ttyUSB0|1|20|5|6|3|u112|0|1|1|................................................... diff --git a/RVO12/databases/tbdata.nosql b/RVO12/databases/tbdata.nosql new file mode 100755 index 0000000..88ac37f --- /dev/null +++ b/RVO12/databases/tbdata.nosql @@ -0,0 +1,4 @@ +-"XMBbew5z4ELrZa2mRAd3zV78vPN6gy3DdVYlpKjq":[{"ts":1760522735786,"values":{"_event":{"type":"notice","status":"new","source":{"func":"modbus_reader","component":"1699965957410","component_name":"Modbus reader","edge":"XMBbew5z4ELrZa2mRAd3zV78vPN6gy3DdVYlpKjq"},"message":{"sk":"rvo_senica_12_ip112: FLOW bol reštartovaný","en":"rvo_senica_12_ip112: FLOW has been restarted"},"message_data":""}}}],"id":"3000185001rk71b"} +-"XMBbew5z4ELrZa2mRAd3zV78vPN6gy3DdVYlpKjq":[{"ts":1760522735879,"values":{"edge_fw_version":"2025-10-08","maintenance_mode":false}}],"id":"3000185002rk70b"} +-"XMBbew5z4ELrZa2mRAd3zV78vPN6gy3DdVYlpKjq":[{"ts":1760522735892,"values":{"statecode":2,"power_mode":"Automatic"}}],"id":"3000185004rk70b"} +-"XMBbew5z4ELrZa2mRAd3zV78vPN6gy3DdVYlpKjq":[{"ts":1760522735941,"values":{"_event":{"type":"notice","status":"new","source":{"func":"rsPort.open()","component":"1699963668903","component_name":"DIDO_Controller","edge":"XMBbew5z4ELrZa2mRAd3zV78vPN6gy3DdVYlpKjq"},"message":{"sk":"rvo_senica_12_ip112: FLOW bol spustený","en":"rvo_senica_12_ip112: FLOW has been started "},"message_data":""}}}],"id":"3000185006rk70b"} diff --git a/RVO12/databases/tbdatacloud.nosql b/RVO12/databases/tbdatacloud.nosql new file mode 100755 index 0000000..583d415 --- /dev/null +++ b/RVO12/databases/tbdatacloud.nosql @@ -0,0 +1,3 @@ +-"XMBbew5z4ELrZa2mRAd3zV78vPN6gy3DdVYlpKjq":[{"ts":1760522735879,"values":{"edge_fw_version":"2025-10-08","maintenance_mode":false}}],"id":"3000185003rk71b"} +-"XMBbew5z4ELrZa2mRAd3zV78vPN6gy3DdVYlpKjq":[{"ts":1760522735892,"values":{"statecode":2,"power_mode":"Automatic"}}],"id":"3000185005rk71b"} +-"XMBbew5z4ELrZa2mRAd3zV78vPN6gy3DdVYlpKjq":[{"ts":1760522735941,"values":{"_event":{"type":"notice","status":"new","source":{"func":"rsPort.open()","component":"1699963668903","component_name":"DIDO_Controller","edge":"XMBbew5z4ELrZa2mRAd3zV78vPN6gy3DdVYlpKjq"},"message":{"sk":"rvo_senica_12_ip112: FLOW bol spustený","en":"rvo_senica_12_ip112: FLOW has been started "},"message_data":""}}}],"id":"3000185007rk71b"} diff --git a/RVO12/databases/total_energy.js b/RVO12/databases/total_energy.js new file mode 100755 index 0000000..dde340e --- /dev/null +++ b/RVO12/databases/total_energy.js @@ -0,0 +1,38 @@ +//key is rvo_number, value is max energy when lamps are on +const total_energy = { + 1: 580, + 2: 1100, + 3: 3700, + 4: 4100, + 7: 360, + 12: 1700, + 13: 5400, + 14: 440, + 15: 6100, + 16: 4800, + 20: 1600, + 21: 1000, + 22: 2600, + 23: 1000, + 25: 2600, + 33: 240, + 34: 4000, + 35: 2700, + 36: 820, + 37: 1400, + 35: 3500, + 39: 1170, + 41: 740, + 42: 660, + 43: 4900, + 45: 930, + 46: 700, + 47: 1100, + 48: 1500, + 50: 3200, + 53: 1250, + 55: 1000, + 56: 5500 +} + +module.exports = total_energy; diff --git a/RVO12/debug.js b/RVO12/debug.js new file mode 100755 index 0000000..9818194 --- /dev/null +++ b/RVO12/debug.js @@ -0,0 +1,16 @@ +// =================================================== +// FOR DEVELOPMENT +// Total.js - framework for Node.js platform +// https://www.totaljs.com +// =================================================== + +const options = {}; + +// options.ip = '127.0.0.1'; +// options.port = parseInt(process.argv[2]); +// options.config = { name: 'Total.js' }; +// options.sleep = 3000; +// options.inspector = 9229; +// options.watch = ['private']; + +require('total.js/debug')(options); \ No newline at end of file diff --git a/RVO12/err.txt b/RVO12/err.txt new file mode 100755 index 0000000..744606e --- /dev/null +++ b/RVO12/err.txt @@ -0,0 +1,33 @@ +[2025-09-23T14:10:11.539] [ERROR] errLogs - uncaughtException: Cannot read property 'getHours' of undefined +[2025-09-23T14:10:11.540] [ERROR] errLogs - TypeError: Cannot read property 'getHours' of undefined + at Timeout.emptyReportToSend [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:10:11.541] [ERROR] errLogs - uncaughtException: Cannot read property 'getHours' of undefined +[2025-09-23T14:10:11.542] [ERROR] errLogs - TypeError: Cannot read property 'getHours' of undefined + at Timeout.emptyReportToSend [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:10:11.551] [ERROR] errLogs - uncaughtException: Cannot read property 'getHours' of undefined +[2025-09-23T14:10:11.551] [ERROR] errLogs - TypeError: Cannot read property 'getHours' of undefined + at Timeout.emptyReportToSend [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:10:17.289] [ERROR] errLogs - uncaughtException: date.getHours is not a function +[2025-09-23T14:10:17.290] [ERROR] errLogs - TypeError: date.getHours is not a function + at emptyReportToSend (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at Timeout.dailyReportCheck [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1351:5) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:10:17.291] [ERROR] errLogs - uncaughtException: date.getHours is not a function +[2025-09-23T14:10:17.291] [ERROR] errLogs - TypeError: date.getHours is not a function + at emptyReportToSend (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at Timeout.dailyReportCheck [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1351:5) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:10:17.296] [ERROR] errLogs - uncaughtException: date.getHours is not a function +[2025-09-23T14:10:17.297] [ERROR] errLogs - TypeError: date.getHours is not a function + at emptyReportToSend (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at Timeout.dailyReportCheck [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1351:5) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) diff --git a/RVO12/flow/cloudmqttconnect.js b/RVO12/flow/cloudmqttconnect.js new file mode 100755 index 0000000..b03491f --- /dev/null +++ b/RVO12/flow/cloudmqttconnect.js @@ -0,0 +1,357 @@ +exports.id = 'cloudmqttconnect'; +exports.title = 'Cloud connect mqtt'; +exports.group = 'MQTT'; +exports.color = '#888600'; +exports.version = '1.0.2'; +exports.icon = 'sign-out'; +exports.input = 2; +exports.output = 2; +exports.options = { host: 'tb-stage.worksys.io', port: 1883, clientid: "", username: "" }; + +exports.html = `
+
+
+
Hostname or IP address (if not empty - setting will override db setting)
+
+
+
Port
+
+
+
+
+
@(Client id)
+
+
+
topic
+
+
+
`; + + + +const { promisifyBuilder } = require('./helper/db_helper'); +const fs = require('fs'); +const mqtt = require('mqtt'); +const nosql = NOSQL('tbdatacloud'); + +const SEND_TO = { + debug: 0, + rpcCall: 1, +} + +//CONFIG +let saveTelemetryOnError = true;//backup_on_failure overrides this value +//------------------------ + +const noSqlFileSizeLimit = 4194304;//use 5MB - 4194304 +let insertNoSqlCounter = 0; +let insertBackupNoSqlCounter = 0; +let processingData = false; + +let backup_on_failure = true;//== saveTelemetryOnError - create backup client send failure +let restore_from_backup = 50; //how many rows process at once? +let restore_backup_wait = 3;//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; + + +exports.install = function(instance) { + + var client; + var opts; + var clientReady = false; + + let o = {}; //options + + function main() { + loadSettings(); + } + + //set opts according to db settings + function loadSettings() { + + o = instance.options; + if (!o.topic) o.topic = FLOW.GLOBALS.settings.cloud_topic; + + opts = { + host: o.host, + port: o.port, + clientId: o.clientid, + username: o.username, + rejectUnauthorized: false, + resubscribe: false + }; + + console.log("wsmqttpublich -> loadSettings from instance.options", o); + + if (!o.topic) { + instance.status("Not configured", "white"); + console.log("Cloud mqtt connect: no topic selected"); + return; + } + + connectToTbServer(); + } + + function connectToTbServer() { + var url = "mqtt://" + opts.host + ":" + opts.port; + console.log("MQTT URL: ", url); + + client = mqtt.connect(url, opts); + + client.on('connect', function() { + client.subscribe(`${o.topic}_backward`, (err) => { + if (!err) { + console.log("MQTT subscribed"); + } + }); + instance.status("Connected", "green"); + clientReady = true; + sendClientError = true; + }); + + client.on('reconnect', function() { + instance.status("Reconnecting", "yellow"); + clientReady = false; + }); + + client.on('message', function(topic, message) { + // message is type of buffer + message = message.toString(); + if (message[0] === '{') { + TRY(function() { + + message = JSON.parse(message); + if (message.hasOwnProperty("device") && message.hasOwnProperty("data") && message.data.hasOwnProperty("id")) { + client.publish(`${o.topic}_forward`, `{"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 } }); + } + + }, () => instance.debug('MQTT: Error parsing data', message)); + } + + instance.send(SEND_TO.rpcCall, { "topic": o.topic, "content": message }); + }); + + client.on('close', function() { + clientReady = false; + + instance.status("Disconnected", "red"); + instance.send(SEND_TO.debug, { "message": "Client CLOSE signal received !" }); + }); + + client.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) { + console.log('MQTT client error', err); + sendClientError = false; + } + clientReady = false; + }); + + } + + + instance.on('0', function(data) { + + if (clientReady) { + //do we have some data in backup file? if any, process data from database + if (saveTelemetryOnError) { + //read telemetry data and send back to server + if (!processingData) processDataFromDatabase(); + } + + let stringifiedJson = JSON.stringify(data.data) + client.publish(`${o.topic}_forward`, stringifiedJson, { qos: 1 }); + } + 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 (saveTelemetryOnError && o.topic) { + //create new file from tbdata.nosql, if file size exceeds given limit, and clear tbdata.nosql + makeBackupFromDbFile(); + + //write to tb + data.data.id = UID(); + nosql.insert(data.data); + } + } + }); + + instance.on("1", _ => { + main(); + }) + + instance.close = function(done) { + if (clientReady) { + client.end(); + } + }; + + + function getDbBackupFileCounter(type) { + var files = fs.readdirSync(__dirname + "/../databases"); + + let counter = 0; + for (var i = 0; i < files.length; i++) { + + if (files[i] == "tbdatacloud.nosql") continue; + + if (files[i].endsWith(".nosql")) { + + let pos = files[i].indexOf("."); + if (pos > -1) { + + let fileCounter = counter; + let firstDigit = files[i].slice(0, pos); + + fileCounter = parseInt(firstDigit); + if (isNaN(fileCounter)) fileCounter = 0; + //console.log("getDbBackupFileCounter digit:", files[i], firstDigit, fileCounter, isNaN(fileCounter), type); + + if (type == "max") { + if (fileCounter > counter) { + counter = fileCounter; + } + } + else if (type == "min") { + if (counter == 0) counter = fileCounter; + + if (fileCounter < counter) { + counter = fileCounter; + } + } + } + } + + } + + if (type == "max") counter++; + + return counter; + } + + const makeBackupFromDbFile = async () => { + + if (!saveTelemetryOnError) return; + + //to avoid large file: tbdata.nosql + + //init value is 0! + if (insertNoSqlCounter > 0) { + --insertNoSqlCounter; + return; + } + + insertNoSqlCounter = 100; + + let source = __dirname + "/../databases/tbdatacloud.nosql"; + + var stats = fs.statSync(source); + var fileSizeInBytes = stats.size; + + if (fileSizeInBytes > noSqlFileSizeLimit) { + + let counter = 1; + counter = getDbBackupFileCounter("max"); + + let destination = __dirname + "/../databases/" + counter + "." + "tbdatacloud.nosql"; + + //make backup file + fs.copyFileSync(source, destination); + //fs.renameSync(p, p + "." + counter); + + //clear tbdata.nosql + fs.writeFileSync(source, ""); + fs.truncateSync(source, 0); + + } + } + + const processDataFromDatabase = async () => { + + if (restore_from_backup <= 0) return; + + //calculate diff + const now = new Date(); + let currentTime = now.getTime(); + let diff = currentTime - lastRestoreTime; + + if ((diff / 1000) < restore_backup_wait) { + //console.log("*********restore_backup_wait", diff, restore_backup_wait); + return; + } + + processingData = true; + + //get filename to process + let counter = getDbBackupFileCounter("min"); + + //we have some backup files + let dataBase = 'tbdata'; + + var nosql; + if (counter == 0) dataBase = 'tbdatacloud'; + else dataBase = counter + "." + 'tbdatacloud'; + + nosql = NOSQL(dataBase); + + //select all data - use limit restore_from_backup + let records = await promisifyBuilder(nosql.find().take(restore_from_backup)); + + for (let i = 0; i < records.length; i++) { + if (clientReady) { + + let item = records[i]; + let id = item.id; + + if (id !== undefined) { + //console.log("------------processDataFromDatabase - remove", id, dataBase, i); + + try { + + let message = JSON.parse(JSON.stringify(item)); + delete message.id; + client.publish(`${o.topic}_forward`, JSON.stringify(message), { qos: 1 }); + + //remove from database + await promisifyBuilder(nosql.remove().where("id", id)); + + } catch (error) { + //process error + console.log("processDataFromDatabase", error); + } + + } + + } + else { + processingData = false; + return; + } + } + + if (records.length > 0) { + //clean backup file + if (counter > 0) nosql.clean(); + } + + //no data in db, remove + if (records.length == 0) { + if (counter > 0) nosql.drop(); + } + + const d = new Date(); + lastRestoreTime = d.getTime(); + + processingData = false; + + } + + instance.on('options', main); + +}; diff --git a/RVO12/flow/cmd_manager.js b/RVO12/flow/cmd_manager.js new file mode 100755 index 0000000..25912df --- /dev/null +++ b/RVO12/flow/cmd_manager.js @@ -0,0 +1,3071 @@ +exports.id = 'cmd_manager'; +exports.title = 'CMD Manager'; +exports.group = 'Worksys'; +exports.color = '#5D9CEC'; +exports.version = '0.0.3'; +exports.output = ['red', 'blue', 'yellow', 'blue', 'white', 'green']; +exports.input = 3; +exports.icon = 'cloud-upload'; + +exports.html = ` +
+
+
+
RPC - run RPC calls

+
+
+
@(User)
+
+
+
@(Password)
+
+
+
@(My edge)
+
+
+
+`; +exports.readme = `Manager for CMD calls`; + + +exports.install = function(instance) { + + 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, isEmptyObject, emptyJsObject, writeToFile, addToArrayIfUnique } = require('./helper/utils'); + const bitwise = require('bitwise'); + + var SunCalc = require('./helper/suncalc'); + const DataToTbHandler = require('./helper/DataToTbHandler'); + const errorHandler = require('./helper/ErrorToServiceHandler'); + const { sendNotification } = require('./helper/notification_reporter'); + const process = require('process'); + const { errLogger, logger, monitor } = require('./helper/logger'); + + //for accelerometer purposes + const { naklony } = require("../databases/accelerometer_db"); + + const dbNodes = TABLE("nodes"); + const dbRelays = TABLE("relays"); + + let GLOBALS; + let SETTINGS; + let rsPort; + let tbHandler; + + // runTasks intervals + const SHORT_INTERVAL = 30; + const LONG_INTERVAL = 300; + + //send data to following instances: + const SEND_TO = { + debug: 0, + tb: 1, + http_response: 2, + dido_controller: 3, + infoSender: 4, + dailyReport: 5 + } + + 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 + } + + 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 sendNodeReadout = null; // interval for sending agregate data from node + + 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["1"] = minutes; // dimming + priorities["76"] = minutes; // power + + minutes = 5; + priorities["75"] = minutes; // current + priorities["79"] = minutes; // energy + priorities["87"] = minutes; // aktualny cas + //priorities["84"] = minutes; //accelerometer + + minutes = 10; + priorities["74"] = minutes; // voltage + priorities["77"] = minutes; // power factor + priorities["78"] = minutes; // frequency + + minutes = 60; + priorities["0"] = minutes; // statecode + priorities["6"] = minutes; // dusk + priorities["7"] = minutes; // dawn + priorities["8"] = minutes; // profile + + minutes = 60 * 24; + priorities["89"] = minutes; // verzia fw + priorities["80"] = minutes; // lifetime + + //prikazy kt sa budu spustat na dany node - see config.js in terminal-oms.app. (1 - dimming) + let listOfCommands = [0, 1, 6, 7, 8, 74, 75, 76, 77, 78, 79, 80, 87, 89]; + + 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; + + // holds dusk, dawn (and more) values + let sunCalcResult; + + //helper container for counting resolved group of commands (commands related to set profile) + let cmdCounter = {};//key is node, value is counter + + //TODO: is this set working?? According to previous checks, sets do not work + //if sending of profile to node fails, we send notification and push node into set, so we do not send notification twice + const nodeProfileSendFail = new Set(); + + //we expect to get current temperature in Senica from senica-prod01 + let temperatureInSenica = null; + let accelerometerInterval = null; + + //NOTE: daily reports senica: + //rvo_is_on status, we monitor all nodes - if true, power and dimming should be not 0, if false, 24/7 nodes should be 0, other rvo should not respond + let rvo_is_on; + let previous_rvo_is_on_value; + let handleDailyReport; //setInterval for dailyReportHandler function + let dailyReport = {}; //data needed for daily report + let reportToSend = {}; //final report which we send to cloud + let breakerCounter = null; // status of breakers after flow starts is not in report + let rvoPeriod; // interval of checking dusk dawn and if rvo_is_on + let initialReportStatus = false; + + const DAILY_REPORT_HANDLER_TIME = 3_600_000; + const SET_SUNCALC_RESULT_TIME = 3_600_000; + const SET_RVO_PERIOD_TIME = 300_000; + const ADD_NODE_TO_REPORT_TIME = 3_600_000; + + //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); + + let now = new Date(); + console.log("Cmd-mngr installed", now.toLocaleString("sk-SK")); + + sunCalcResult = calculateDuskDawn(); + + handleRsPort(); + + customTasksInterval = setInterval(reportEdgeDateTimeAndNumberOfLuminaires, 120_000); + setTimeout(reportEdgeDateTimeAndNumberOfLuminaires, 4000); + + //dailyReport related + emptyReportToSend(); + breakerCounter = Object.keys(relaysData).length - 1; // we get number of lines (breakers) except of line 0 + rvoPeriod = setInterval(setRvoPeriod, SET_RVO_PERIOD_TIME); + setTimeout(setRvoPeriod, 3000); + setInterval(setSunCalcResult, SET_SUNCALC_RESULT_TIME); + handleDailyReport = setInterval(dailyReportHandler, DAILY_REPORT_HANDLER_TIME); + + + setCorrectTime = setInterval(setCorrectPlcTimeOnceADay, 60000 * 60); // 1 hour + setCorrectPlcTimeOnceADay(); + + sendNodeReadout = setInterval(sendNodesData, 150_000); + accelerometerInterval = setInterval(accelerometerData, 60000 * 30); //30 min + } + + + 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" + //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 + // if node regular readout does not respond, we repeat request + params.repeatCounter = 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-mngr: 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.byte4 = 96; + params.recipient = 1; + params.register = 8; + params.rw = 1;//write + params.timestamp = timestamp; + 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.byte4 = 96; + params.recipient = 1; + params.register = 8; + params.rw = 1;//write + params.timestamp = timestamp; + 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). + */ + + 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.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.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 + { + + logger.debug("processNodeProfile: Threshold lux level for DUSK/DAWN", node); + + let params = getParams(); + params.type = "set_node_profile"; + params.address = node; + params.register = 96; + params.recipient = 1; + params.rw = 1;//write + params.timestamp = timestamp; + 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(); + params.type = "set_node_profile"; + params.address = node; + params.register = 97; + params.recipient = 1; + params.rw = 1;//write + params.timestamp = timestamp; + 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.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); + + 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); + + console.log("proces profile finished *********************") + } + + + 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; + }); + } + + + 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) { + for (let k in nodesData) { + 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`); + } + } + } + + + function loadRelaysData(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 (value.contactor == 1) processAllNodeProfilesOnLine(value.line); + } + } + + + function reportOnlineNodeStatus(line) { + //Po zapnutí línie broadcastovo aktualizovať predtým čas a o 3 sek neskor - status, brightness + + logger.debug("Cmd-mngr: ----->reportOnlineNodeStatus for line", line); + + const d = new Date(); + + // broadcast actual time + let params = getParams(); + params.address = 0xffffffff;//Broadcast + params.byte1 = d.getHours(); + params.byte2 = d.getMinutes(); + params.recipient = 2;//2 broadcast, address = 0 + params.register = 87;//Actual time + params.rw = 1;//write + params.type = "node-onetime-write"; + params.timestamp = d.getTime() + 30000; + params.info = "run broadcast: Actual time"; + //params.debug = true; + + tasks.push(params); + + let sec = 3; + setTimeout(function() { + //Po zapnutí línie - spraviť hromadný refresh stavu práve zapnutých svietidiel + + let time = Date.now(); + + for (let k in nodesData) { + + //potrebujem nody k danej linii + 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].node_status_before_offline === true || nodesData[k].status === true) { + status = "OK"; + nodesData[k].time_of_last_communication = time; + } + + nodesData[k].readout.status = status; + + updateNodeStatus(k, status === "OK" ? true : false); + if (nodesData[k].hasOwnProperty("node_status_before_offline")) delete nodesData[k].node_status_before_offline; + sendTelemetry({ status: status }, tbname, time); + + //vyreportovanie dimming, current, input power pre liniu pre vsetky nody + //Prud + { + let params = getParams(); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 75;//prud + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = time + 4000; + params.info = 'read current'; + //params.debug = true; + tasks.push(params); + } + + //vykon + { + let params = getParams(); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 76;//výkon + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = time + 4100; + params.info = 'read power'; + //params.debug = true; + + tasks.push(params); + } + //dimming + { + let params = getParams(); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 1;//dimming + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = time + 4200; + params.info = 'read dimming'; + //params.debug = true; + + tasks.push(params); + } + + } + } + + }, sec * 1000); + } + + + function reportOfflineNodeStatus(line) { + + logger.info("Cmd-mngr: ------>reportOffLineNodeStatus for line ", line); + + values = {}; + values["dimming"] = 0;//brightness + values["power"] = 0;//výkon + values["current"] = 0;//prúd + values["status"] = "OFFLINE"; + + const date = Date.now(); + + Object.keys(nodesData).forEach(node => { + + //potrebujem nody k danej linii + if (line == nodesData[node].line || line == undefined) { + + let tbname = nodesData[node].tbname; + let nodeStatus = nodesData[node].status; + + //in case we have reported offline node status, we return (continue with next node) + if (nodeStatus === "OFFLINE") return; + + nodesData[node].node_status_before_offline = nodeStatus; + nodesData[node].status = "OFFLINE"; + nodesData[node].readout = {}; + + sendTelemetry({ ...values }, tbname, date); + } + }); + + } + + + function turnLine(onOrOff, line, info) { + let obj = { + line: line, + command: onOrOff, + info: info + }; + + //to assure, handleDailyReportFunction do not run before rvo_is_on variable changes. So after every line switch we reset the timer + clearInterval(handleDailyReport); + handleDailyReport = setInterval(dailyReportHandler, DAILY_REPORT_HANDLER_TIME); + + //logger.debug("linia", line, obj); + instance.send(SEND_TO.dido_controller, obj); + } + + + 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"; + 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]) { + //CRC_ERROR + message = "NOK"; + error = "CRC_ERROR c1"; + instance.send(SEND_TO.debug, "CRC_ERROR c1"); + } + + 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") { + instance.send(SEND_TO.debug, bytes); + instance.send(SEND_TO.debug, "RESPONSE " + type + " - " + bytes[4]); + + //logger.debug(SEND_TO.debug, "RESPONSE " + type + " - " + bytes[4], bytes); + + error = "type is: " + type; + + message = "NOK"; + } + + return { message, type, error }; + } + + + //BUILD TASKS// + function buildTasks(params) { + + //return; + console.log("buidTAaasks start ****************", params); + monitor.info("buildTasks - params", params); + + let processLine; //defined line + let init = false; + let processLineProfiles = true; + let processBroadcast = true; + let processNodes = true; + + if (params == undefined) { + init = true; + tasks = []; + logger.debug("-->buildTasks clear tasks"); + } + else { + processLineProfiles = params.processLineProfiles; + processBroadcast = false; + processNodes = false; + + processLine = params.line; + } + + let now = new Date(); + + //process line profiles + if (processLineProfiles) { + + let keys = Object.keys(relaysData); + + for (let i = 0; i < keys.length; i++) { + + let line = parseInt(keys[i]); + let profilestr = relaysData[line].profile; + + if (processLine != undefined) { + if (processLine != line) continue; + } + + try { + + /** + * we process line profiles: timepoints, astro clock, lux_sensor, offsets ... + */ + if (profilestr === "") throw ("Profile is not defined"); + let profile = JSON.parse(profilestr); + 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; + + // add name to regular profile timepoint and delete unused end_time key: + time_points.forEach(point => { + point.name = "profileTimepoint" + delete point.end_time; + }); + + //monitor.info("buildTasks: time_points", time_points); + + + /** + * 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 astro clock true, we remove all regular profile points + time_points = []; + + //TODO: when astro clock == true, is offset calculated ??? + //let duskAstroClockOffset = profile.dusk_astro_clock_offset; + //let dawnAstroClockOffset = profile.dawn_astro_clock_offset; + //console.log("line astro clock offsets dusk a dawn: ", duskAstroClockOffset, dawnAstroClockOffset); + // maybe add dusk dawn offset to calculateDuskDawn ?? what dusk dawn will be if dawn_lux_sensor == true?? + //let sunCalcResult = calculateDuskDawn(new Date(), line, duskAstroClockOffset, dawnAstroClockOffset); + + 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 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); + + 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); + + 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(':'); + + let ad = new Date(); + ad.setHours(parseInt(ahours), parseInt(aminutes), 0); + + let bd = new Date(); + bd.setHours(parseInt(bhours), parseInt(bminutes), 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++) { + + let start_time = new Date(); + let [hours, minutes] = time_points[t].start_time.split(':'); + start_time.setHours(parseInt(hours), parseInt(minutes), 0); + + //task is in 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(); + params.type = "relay"; + params.line = parseInt(line); + params.value = time_points[t].value; + params.tbname = relaysData[line].tbname; + params.timestamp = start_time.getTime(); + + // 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; + + //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)) { + 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; + + params.debug = true; + + //turn on/off line + tasks.push(params); + monitor.info("TimePoint params: ", params.info, start_time); + } + + monitor.info("-->time_points final", line, time_points); + + //ensure to turn on/off according to calculated currentValue + let params = getParams(); + params.type = "relay"; + params.line = parseInt(line); + params.tbname = relaysData[line].tbname; + params.value = currentValue; + params.timestamp = i; + params.debug = true; + + //logger.debug(now.toLocaleString("sk-SK")); + 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; + + tasks.push(params); + + } catch (error) { + if (profilestr !== "") { + //errLogger.error(profilestr, error); + console.log(`Cmd_mngr: Unable to process line profile ${line}. Error: `, error); + errorHandler.sendMessageToService(profilestr + "-" + error, 0, "js_error"); + } else { + turnLine("off", line, "No line profile. Switching it off on startup"); + } + } + + } + //logger.debug("tasks:"); + //logger.debug(tasks); + } + + + //NOTE: PROCESS DEFAULT BROADCASTS - Time of dusk, Time of dawn, Actual Time + if (processBroadcast) { + + let d = new Date(); + let time = d.getTime(); + //let sunCalcResult = calculateDuskDawn(); + + { + let params = getParams(); + + params.address = 0xffffffff;//broadcast + params.byte1 = sunCalcResult["dusk_hours"]; + params.byte2 = sunCalcResult["dusk_minutes"]; + params.recipient = 2;//2 broadcast, + params.register = 6;//Time of dusk + params.rw = 1;//write + params.type = "node-regular-write"; + params.timestamp = time + 60000; + params.addMinutesToTimestamp = 60 * 3; //kazde 3 hodiny zisti novy dusk + params.info = "Broadcast-duskTime"; + + tasks.push(params); + } + + { + let params = getParams(); + + params.address = 0xffffffff;//broadcast + params.byte1 = sunCalcResult["dawn_hours"]; + params.byte2 = sunCalcResult["dawn_minutes"]; + params.recipient = 2; //2 broadcast + params.register = 7;//Time of dawn + params.rw = 1;//write + params.type = "node-regular-write"; + params.timestamp = time + 60001; + params.addMinutesToTimestamp = 60 * 3; //kazde 3 hodiny zisti novy dawn + params.info = "Broadcast-dawnTime"; + + tasks.push(params); + } + + { + let params = getParams(); + + params.address = 0xffffffff;//broadcast + params.byte1 = d.getHours(); + params.byte2 = d.getMinutes(); + params.recipient = 2; //2 broadcast + params.register = 87;//Actual time + params.rw = 1;//write + params.type = "node-regular-write"; + params.timestamp = time + 60002; + params.addMinutesToTimestamp = 5; + params.info = "run broadcast: Actual time"; + + tasks.push(params); + } + + } + + //process nodes & tasks - read node's data + if (processNodes) { + + let time = Date.now(); + + for (let k in nodesData) { + let address = parseInt(k); + let tbname = nodesData[k].tbname; + let register = 0; + + for (let i = 0; i < listOfCommands.length; i++) { + + register = listOfCommands[i]; + let addMinutesToTimestamp = priorities[register]; + + let params = getParams(); + + params.address = address; + params.recipient = 1; + params.register = register; + params.type = register == 1 ? "node-dimming-read" : "node-regular-read"; + params.tbname = tbname; + params.timestamp = time + 5000 + i * 500 + addMinutesToTimestamp * 1000; //to make slight time difference + params.addMinutesToTimestamp = addMinutesToTimestamp; + params.info = "Node regular read command"; + + tasks.push(params); + } + + } + } + + + //niektore ulohy sa vygeneruju iba 1x pri starte!!! + if (!init) return; + + + //Master node FW version - modifies SETTINGS.masterNodeIsResponding + { + let params = getParams(); + params.type = "cmd-master"; + params.register = 4; + params.address = 0; + params.timestamp = 0; + params.addMinutesToTimestamp = 5; + params.tbname = SETTINGS.rvoTbName; + params.info = "Master node FW verzia"; + //params.debug = true; + + tasks.push(params); + } + + //kazdu hodinu skontrolovat nastavenie profilov + { + let params = getParams(); + params.type = "process_profiles"; + params.timestamp = Date.now() + 60001; + params.addMinutesToTimestamp = 60;//60 = every hour + params.info = "detekcia nespracovaných profilov linie a nodov"; + //params.debug = true; + + tasks.push(params); + } + + monitor.info("tasks created:", tasks.length); + } + + + /** + * We process line profile, where "astro_clock": true + * example profile: + * + "dawn_lux_sensor": true, + "dusk_lux_sensor": true, + "dawn_lux_sensor_value": 5, + "dusk_lux_sensor_value": 5, + "dawn_astro_clock_offset": 0, + "dusk_astro_clock_offset": 10, + "dawn_lux_sensor_time_window": 30, + "dusk_lux_sensor_time_window": 30, + "dawn_astro_clock_time_window": 60, + "dusk_astro_clock_time_window": 60 + + * if dawn: if currentTimestamp is in timewindow "dawnTime + and - dawn_lux_sensor_time_window" and lux value >= lux_sensor_value, we switch off the line. + * if dusk: we do oposite + * + * dawn: usvit - lux je nad hranicou - vypnem + * dusk: sumrak - lux je pod hranicou - zapnem + */ + 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++) { + + let line = keys[i]; //line is turned off by default + let profilestr = relaysData[line].profile; + const contactor = relaysData[line].contactor; + + try { + + let profile = JSON.parse(profilestr); + if (Object.keys(profile).length === 0) throw ("turnOnOffLinesAccordingToLuxSensor - profile is not defined"); + + 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 (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"); + } + } + } + + //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 (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"); + } + } + } + + } + + } catch (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) { + //MASTER + if (node == 0) return; + + let nodeObj = nodesData[node]; + if (nodeObj == undefined) return; + + let nodeCurrentStatus = nodeObj.status; + const now = Date.now(); + + let data = null; + + if (nodeCurrentStatus === "OFFLINE") { + data = { status: newStatus }; + nodeDbStatusModify(node, data); + return; + } + else 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; + } + + } + + + 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 }; + } + }); + }); + } + + + function processDailyReport() { + + const now = Date.now(); + + for (const [key, value] of Object.entries(dailyReport)) { + + if (["name", "time", "dusk_and_dawn"].includes(key)) continue; + + let poleNumber = nodesData[key]["pole_number"]; + let line = dailyReport[key].line; + let nodeType = nodesData[key]["node_type"]; + let fullNodeName = key // key == nodeNumber + + if (poleNumber && nodeType) { + fullNodeName = SETTINGS.rvo_number + "/" + poleNumber + "_" + line + "L_" + key + "_" + nodeType; + } else { + fullNodeName = key; + } + + if (rvo_is_on) { + + if (value.initialTs) { + if (value.initialTs + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["night_no_data"], fullNodeName); + console.log('report nedostava ziadne data uz hodinu', fullNodeName); + value.initialTs = now; + } + } + if (value.dimmingIsZeroTime) { + if (value.dimmingIsZeroTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["night_dimming=0"], fullNodeName); + console.log("report node dimming je 0 ale ma svietit", fullNodeName); + value.dimmingIsZeroTime = now; + } + } + if (value.powerIsZeroTime) { + if (value.powerIsZeroTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["night_power=0"], fullNodeName); + console.log("report node power je 0 ale ma svietit", fullNodeName); + value.powerIsZeroTime = now; + } + } + + } else { + + let contactorStatus = relaysData[line].contactor; + if (contactorStatus === 1) { + + if (value.initialTs) { + if (value.initialTs + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["day_24/7_no_data"], fullNodeName); + console.log('node je na 24/7 ale nedostava ziadne data uz hodinu', fullNodeName); + value.initialTs = now; + } + } + if (value.dimmingIsOnButShouldBeOffTime) { + if (value.dimmingIsOnButShouldBeOffTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["day_24/7_dimming>0"], fullNodeName); + console.log("report dimming je > 0 ale nema svietit", fullNodeName); + value.dimmingIsOnButShouldBeOffTime = now; + } + } + if (value.powerIsOnButShouldBeOffTime) { + if (value.powerIsOnButShouldBeOffTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["day_24/7_power>0"], fullNodeName); + console.log("report power je > 0 ale nema svietit", fullNodeName); + value.powerIsOnButShouldBeOffTime = now; + } + } + + } + + } + + } + + let report = {}; + report["name"] = SETTINGS.rvo_name; + report["time"] = new Date(); + report["report"] = reportToSend; + + writeToFile(F.path.root("report_data.log"), report, true); + instance.send(SEND_TO.dailyReport, report); + } + + + function dailyReportHandler() { + + if (!SETTINGS.daily_report) return; + + // after dawn we empty reportToSend and start to get data for a new day + const date = new Date(); + const hour = date.getHours(); + const minute = date.getMinutes(); + + console.log("now: ", hour, minute, "suncalc: ", sunCalcResult.dawn_hours, sunCalcResult.dawn_minutes); + + if (hour === sunCalcResult.dawn_hours) { + + //NOTE: ak je este pred usvitom, spracujeme report a posleme na cloud, ak uz je po usvite, resetujeme report plnime data noveho dna + if (minute >= sunCalcResult.dawn_minutes - 2) { + emptyReportToSend(); + emptyDailyReport(); + console.log("Podmienka 1 v dailyReport handler"); + } else { + processDailyReport(); + emptyReportToSend(); + emptyDailyReport(); + console.log("Podmienka 2 v dailyReport handler"); + } + + initialReportStatus = true; + + // ak sa funkcia spusti o hodinu alebo 2 neskor, ako je usvit (moze sa to stat, kedze kazde zapnutie/vypnutie linii odznova spusti casovac. + } else if (hour === sunCalcResult.dawn_hours + 1 || hour === sunCalcResult.dawn_hours + 2) { + if (!initialReportStatus) { + emptyReportToSend(); + emptyDailyReport(); + initialReportStatus = true; + console.log("Podmienka 3 v dailyReport handler"); + } else { + processDailyReport(); + initialReportStatus = true; + console.log("Podmienka 4 v dailyReport handler"); + } + } else { + processDailyReport(); + initialReportStatus = false; + console.log("Podmienka 5 v dailyReport handler"); + } + + console.log("initialReportStatus: ", initialReportStatus); + + } + + function emptyReportToSend() { + emptyJsObject(reportToSend); + reportToSend["contactor"] = { off: [], on: [] }; + reportToSend["night_no_data"] = []; + reportToSend["night_dimming=0"] = []; + reportToSend["night_power=0"] = []; + reportToSend["day_24/7_no_data"] = []; + reportToSend["day_24/7_dimming>0"] = []; + reportToSend["day_24/7_power>0"] = []; + console.log(`resetuje sa reportToSend`); + } + + + //NOTE: ked je initialTs stale rovnaky a zistime ze linie su vypnute (relaysData.line.contactor) - zistim, ci je node na tej linii. Vieme, ze ak je linia vypnuta je to v poriadku lebo nie je na 24/7 linii + //ak je na 24/7 linii, reportujeme, ze neprijima data + function emptyDailyReport() { + const ts = Date.now(); + emptyJsObject(dailyReport); + + //NOTE: do dailyReport dame vsetky nody a pravidelne kontrolujeme ci maju data + //ked nastane sumrak/usvit a svetla maju zacat/prestat svietit, dailyReport spravime nanovo: + for (const [key, value] of Object.entries(nodesData)) { + dailyReport[value.node] = { line: value.line, initialTs: ts }; + } + + console.log("dailyReport: ", dailyReport); + } + + + async function runTasks() { + + clearInterval(interval); + + let currentTimestamp = Date.now(); + + //sort tasks based on timestamp + 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) { + instance.send(SEND_TO.debug, "no tasks created"); + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + if (!rsPort.isOpen) { + instance.send(SEND_TO.debug, "!rsPort.isOpen"); + //await rsPort.open(); + //console.log("Cmd-mngr: !rsPort.isOpen"); + } + + let currentTask = tasks[0]; + + if (currentTask.debug) { + //logger.debug("--->task to process", currentTask); + } + + if (currentTask.timestamp <= currentTimestamp) { + let params = { ...tasks[0] }; + + //allow terminal commands + if (SETTINGS.maintenance_mode && params.type !== "cmd-terminal") { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + let type = params.type; + let tbname = params.tbname; + let node = params.address; + let register = params.register; + let line = null; + let itIsNodeCommand; + + if (nodesData[node] !== undefined) { + line = nodesData[node].line; + itIsNodeCommand = true; + } + + if (params.line !== undefined) line = params.line; + + if (params.addMinutesToTimestamp > 0 || params.timePointName) { + tasks[0].timestamp = currentTimestamp + tasks[0].addMinutesToTimestamp * 60000; + } else { + tasks.shift(); + } + + //kontrola nespracovanych profilov nodov + //TODO: co ked niektore nody neprijimaju profily? kazdu hodinu zahltuju "tasks" array + if (type == "process_profiles") { + //na vsetky zapnutych liniach sa spracuju nespracovane profily nodov + loadRelaysData(); + interval = setInterval(runTasks, SHORT_INTERVAL); + return; + } + + //relay + if (type == "relay") { + + const timePointName = params.timePointName; + const value = params.value; + + let date = new Date(); + date.setDate(date.getDate() + 1);//next day + + let sunCalcResult; + if (timePointName) sunCalcResult = calculateDuskDawn(date, params.line); + + + if (timePointName == "dawn") { + tasks[0].timestamp = sunCalcResult.dawn_time; + } + else if (timePointName == "dusk") { + tasks[0].timestamp = sunCalcResult.dusk_time; + } + else if (timePointName == "luxOn") { + tasks[0].timestamp = sunCalcResult.dusk_time + params.dusk_lux_sensor_time_window * 60000; + } + else if (timePointName == "luxOff") { + tasks[0].timestamp = sunCalcResult.dawn_time + params.dawn_lux_sensor_time_window * 60000; + } + else if (timePointName == "profileTimepoint") { + tasks[0].timestamp = currentTimestamp + tasks[0].addMinutesToTimestamp * 60000; + } + + let info = "aplikovany bod profilu"; + let onOrOff = ""; + value == 1 ? onOrOff = "on" : onOrOff = "off"; + + turnLine(onOrOff, params.line, info); + + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + if (!SETTINGS.masterNodeIsResponding) { + //ak neodpoveda, nebudeme vykonavat ziadne commands, okrem cmd-terminal cmd-master + errorHandler.sendMessageToService("Master node is not responding"); + + let stop = true; + + if (type === "cmd-terminal" || type === "cmd-master") stop = false; + if (stop) { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + } + + let contactorStatus = 1; + if (relaysData[line] != undefined) contactorStatus = relaysData[line].contactor; + + if (line === 0 || contactorStatus === 0 || FLOW.deviceStatus.state_of_breaker[line] === "Off") { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + // TODO: -> status offline for rvo if rotary_switch_state is OFF, this is source of errors + // check if rotary_switch_state == "Off" + // state_of_braker: disconnected = true? + + if (!rsPort.isOpen) { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + //RE-CALCULATE VALUES + //set actual time for broadcast + if (register == 87 && params.recipient === 2) { + var d = new Date(); + params.byte1 = d.getHours();//h + params.byte2 = d.getMinutes();//m + } + + //SET DUSK/DAWN FOR BROADCAST + //Time of dusk + if (register == 6 && params.recipient === 2) { + + if (type != "cmd-terminal") { + params.byte1 = sunCalcResult["dusk_hours"];//h + params.byte2 = sunCalcResult["dusk_minutes"];//m + } + } + + //Time of dawn + if (register == 7 && params.recipient === 2) { + if (type != "cmd-terminal") { + params.byte1 = sunCalcResult["dawn_hours"];//h + params.byte2 = sunCalcResult["dawn_minutes"];//m + } + } + //----------------------- + + instance.send(SEND_TO.debug, "address: " + node + " register:" + register + "type: " + type); + + var startTime, endTime; + startTime = new Date(); + + let saveToTb = true; + if (!tbname) saveToTb = false; + + let resp = com_generic(node, params.recipient, params.rw, register, params.name, params.byte1, params.byte2, params.byte3, params.byte4); + let readBytes = 11; + let timeout = 4000; + + + // await keyword is important, otherwise incorrect data is returned! + await writeData(rsPort, resp, readBytes, timeout).then(function(data) { + + //sometimes happens, that status of node changes to OK, NOK even if line was turned off and should be status OFFLINE. To prevent this, we return if line contactor is 0: + if (itIsNodeCommand && line && relaysData[line].contactor !== 1) return; + + 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); + + //ak sa odpoved zacina 0 - je to v poriadku, inak je NOK + let message = result.message; // OK, NOK + let message_type = result.type; + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + console.log("detected response:", result); + logger.debug("Cmd-mngr: writeData done " + message_type + " duration: " + timeDiff + " type: " + params.debug, params, result); + } + } + + let values = {}; + + //CMD FINISHED + if (message == "OK") { + + updateNodeStatus(node, true); + + //write + if (type == "set_node_profile") { + let result = cmdCounterResolve(node); + if (result == 0) { + dbNodes.modify({ processed: true }).where("node", node).make(function(builder) { + builder.callback(function(err, response) { + + sendNotification("Cmd-mngr: process cmd", SETTINGS.rvoTbName, "dimming_profile_was_successfully_received_by_node", { node: node }, "", SEND_TO.tb, instance); + + logger.debug("--> profil úspešne odoslaný na node č. " + node); + nodesData[node].processed = true; + nodeProfileSendFail.delete(node); + }); + }); + } + } + + //parse read response + if (params.rw == 0) { + values = processResponse(register, dataBytes); //read + } + + if (itIsNodeCommand) { + values.comm_status = "OK"; + values.status = "OK"; + nodesData[node].readout = { ...nodesData[node].readout, ...values }; + + + if (SETTINGS.daily_report) { + //TODO: co ak nedostavame odpovede z nodu ? Musime vyreportovat!! + //v dailyReport teda musi byt kompletny zoznam nodov a neustale kontrolovat, ci maju data, ak nie report node - neodpoveda + if (register === 1) { + + let now = Date.now(); + + if (rvo_is_on === true) { + + if ("dimmingIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].dimmingIsOnButShouldBeOffTime; + + if (values.dimming > 0) { + if ("dimmingIsZeroTime" in dailyReport[node]) delete dailyReport[node].dimmingIsZeroTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if (!("dimmingIsZeroTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], dimmingIsZeroTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } else { + + if ("dimmingIsZeroTime" in dailyReport[node]) delete dailyReport[node].dimmingIsZeroTime; + + if (values.dimming > 0) { + if (!("dimmingIsOnButShouldBeOffTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], dimmingIsOnButShouldBeOffTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if ("dimmingIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].dimmingIsOnButShouldBeOffTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } + } + + if (register === 76) { + + let now = Date.now(); + + if (rvo_is_on === true) { + + if ("powerIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].powerIsOnButShouldBeOffTime; + + if (values.power > 1) { + if ("powerIsZeroTime" in dailyReport[node]) delete dailyReport[node].powerIsZeroTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if (!("powerIsZeroTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], powerIsZeroTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } else { + + if ("powerIsZeroTime" in dailyReport[node]) delete dailyReport[node].powerIsZeroTime; + + if (values.power > 1) { + if (!("powerIsOnButShouldBeOffTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], powerIsOnButShouldBeOffTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if ("powerIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].powerIsOnButShouldBeOffTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } + } + } + + } + + //master node + if (node == 0) { + sendNotification("Cmd-mngr: 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; + } + + if (params.debug) { + //logger.debug("saveToTb", saveToTb, tbname, values); + } + + if (saveToTb && type != "node-regular-read") { + sendTelemetry(values, tbname); + } + else { + if (type == "cmd-terminal") { + terminalCommandResponse(params, "SUCCESS", data); + } + } + + } + else { + terminalCommandResponse(params, "ERROR", data); + handleNokResponseOnRsPort("handleNOK else block", params, itIsNodeCommand, saveToTb); + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + //logger.debug("writeData err: ", error, result, params); + logger.debug("writeData err: ", tbname, node, register, values); + } + } + + //logger.debug(error, result, params); + } + }).catch(function(reason) { + + //console.log("writeData catch exception", reason); + instance.send(SEND_TO.debug, reason); + + terminalCommandResponse(params, "FAILURE", null, reason); + handleNokResponseOnRsPort("handleNOK catch block", params, itIsNodeCommand, saveToTb); + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + logger.debug("-->WRITE FAILED: " + reason, params.debug, params); + } + } + + }); + + } + 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); + } + + + // if node does not respond to request, we repeat request 3 times: + function repeatCommand(params) { + params.repeatCounter++; + if (params.repeatCounter < 4) { + params.timestamp = 0; + params.addMinutesToTimestamp = 0; + tasks.push(params); + } + } + + function handleNokResponseOnRsPort(message, params, itIsNodeCommand, saveToTb) { + + let node = params.address; + let register = params.register; + let type = params.type; + let tbName = params.tbname; + if (!tbName) return; + + let values = {}; + + let updateStatus = updateNodeStatus(node, false); + + if (itIsNodeCommand) { + values.comm_status = "NOK"; + nodesData[node].readout.comm_status = "NOK"; + repeatCommand(params); + } + + if (updateStatus) { + values.status = "NOK"; + nodesData[node].readout.status = "NOK"; + } + + if (type === "node-regular-read") return; + + //master node + if (node == 0) { + sendNotification("Cmd-mngr: 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; + + if (register == 4) values["master_node_version"] = "NOK"; + } + + if (type == "set_node_profile") { + delete cmdCounter[node]; + logger.debug("profil nebol úspešne odoslaný na node č. ", params); + + if (!nodeProfileSendFail.has(node)) { + sendNotification("Cmd-mngr: process cmd", tbName, "configuration_of_dimming_profile_to_node_failed", { node: node }, "", SEND_TO.tb, instance); + nodeProfileSendFail.add(node); + } + } + + // console.log("------",node, register, type, itIsNodeCommand, updateStatus, saveToTb, values); + if (saveToTb) { + sendTelemetry(values, tbName); + } + + } + + + function sendNodesData() { + Object.keys(nodesData).forEach(node => { + if (nodesData[node]["status"] !== "OFFLINE") { + sendTelemetry(nodesData[node].readout, nodesData[node].tbname); + nodesData[node].readout = {}; + } + }) + } + + + /** + * 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; + } + + 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); + + //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 === "OFFLINE") { + nodeObj.node_status_before_offline === true ? number_of_ok_luminaires++ : number_of_nok_luminaires++; + } + else if (nodeObj.status == true) 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 - ts % 60000 //round to full minute + }; + + sendTelemetry(values, SETTINGS.rvoTbName, ts); + } + + + function setSunCalcResult() { + //if next day, we get new dusk and dawn. To make sure, in local timezone 2:00 means 00:00 in utc (it means next day) + if (new Date().getHours() === 2) { + sunCalcResult = calculateDuskDawn(); + console.log("Novy suncalc: ", sunCalcResult); + } + } + + + function setRvoPeriod() { + + if (!SETTINGS.daily_report) return; + + const ts = Date.now(); + + previous_rvo_is_on_value = rvo_is_on; + + if (ts < sunCalcResult.dawn_time - 1_800_000) { // nodes should be on (00:00 -> 06:00 ( - pol hodina, lebo rvo vypina skor) + rvo_is_on = true; + } else if (sunCalcResult.dawn_time - 1_800_000 < ts && ts < sunCalcResult.dusk_time + 1_800_000) { // nodes should be off 06:00 -> 21:00 + rvo_is_on = false; + } else if (sunCalcResult.dusk_time + 1_800_000 < ts) { // nodes should be on 21:00 -> 00:00 + rvo_is_on = true; + } + + if (previous_rvo_is_on_value !== rvo_is_on) { + emptyDailyReport(); + console.log("rvo_is: ", rvo_is_on, previous_rvo_is_on_value); + } + } + + + function handleRsPort() { + + if (rsPort) { + rsPort.removeAllListeners(); + rsPort = null; + } + + //! 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-mngr: rsPort opened success"); + + 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); + + }).catch(function(reason) { + instance.send(SEND_TO.debug, "Cmd-mngr: RPC runSyncExec - promise rejected:" + reason); + }); + }); + + rsPort.on('error', function(err) { + errorHandler.sendMessageToService([exports.title, "unable to open port", SETTINGS.serial_port, err.message], 0); + monitor.info("Cmd-mngr: Error on rsPort", err.message); + }); + + rsPort.on("close", () => { + monitor.info("Cmd-mngr: rsPort closed, reconnecting..."); + setTimeout(handleRsPort, 1000); + }); + + rsPort.open(); + } + + + instance.on("close", () => { + clearInterval(interval); + clearInterval(customTasksInterval); + clearInterval(setCorrectTime); + clearInterval(sendNodeReadout); + clearInterval(accelerometerInterval); + rsPort.close(); + }); + + instance.on("0", _ => { + main(); + }) + + + instance.on("2", _ => { + console.log("dailyReport, reportToSend, rvo_is_on", dailyReport, reportToSend, rvo_is_on, previous_rvo_is_on_value); + }) + + instance.on("1", 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(); + return; + } + else if (flowdata.data == "close") { + rsPort.close(); + return; + } + else if (flowdata.data == "clean") { + tasks = []; + return; + } + else if (flowdata.data == "buildtasks") { + //build & run + return; + } + else if (flowdata.data == "run") { + //durations = []; + + if (tasks.length == 0) { + + buildTasks(); + + if (rsPort.isOpen) { + interval = setInterval(runTasks, 100); + } + else { + instance.send(SEND_TO.debug, "port is not opened!!!"); + } + } + } + else { + //terminal data - object + //logger.debug("flowdata", flowdata.data); + + if (typeof flowdata.data === 'object') { + //logger.debug("dido", flowdata.data); + if (flowdata.data.hasOwnProperty("sender")) { + //data from dido_controller + if (flowdata.data.sender == "dido_controller") { + + if (flowdata.data.hasOwnProperty("cmd")) { + let cmd = flowdata.data.cmd; + + if (cmd == "buildTasks") { + clearInterval(interval); + + logger.debug("-->Cmd-mngr: BUILD TASKS"); + buildTasks(); + + //logger.debug("tasks:"); + //logger.debug(tasks); + + logger.debug("-->Cmd-mngr: RUN TASKS"); + interval = setInterval(runTasks, 5000); + } + else if (cmd == "reload_relays") { + loadRelaysData(flowdata.data.line); + + if (flowdata.data.dataChanged) { + if (!flowdata.data.value) { + reportOfflineNodeStatus(flowdata.data.line); + } + else { + reportOnlineNodeStatus(flowdata.data.line); + } + } + + } + else if (cmd == "rotary_switch_state") { + let value = flowdata.data.value; + + //state was changed + if (rotary_switch_state != value) { + if (value == "Off") { + //vyreportovat vsetky svietdla + reportOfflineNodeStatus(); + } + + rotary_switch_state = value; + } + } + 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) { + + // we send lux_sensor value to all nodes: + let params = getParams(PRIORITY_TYPES.node_broadcast); + + params.recipient = 2;//2 broadcast, address = 0 + params.address = 0xffffffff;//Broadcast + + let ba = longToByteArray(lux_sensor); + + params.byte3 = ba[1];//msb + params.byte4 = ba[0]; + params.timestamp = PRIORITY_TYPES.node_broadcast; + params.info = "run broadcast: Actual Lux level from cabinet"; + params.register = 95;//Actual Lux level from cabinet + params.rw = 1;//write + + tasks.push(params); + + //process profiles + turnOnOffLinesAccordingToLuxSensor(lux_sensor); + } + } + else if (cmd == "state_of_breaker") { + //istic linie + + breakerCounter--; + + let value = flowdata.data.value; + let line = parseInt(flowdata.data.line); + + let dataChanged = false; + if (state_of_breaker[line] != value) dataChanged = true; + + state_of_breaker[line] = value; + + let status = "OK"; + if (value == "Off") status = "NOK"; + + if (dataChanged) { + + if (relaysData.hasOwnProperty(line)) { + let tbname = relaysData[line].tbname; + + if (value == "Off") { + sendNotification("Cmd-mngr: onData", tbname, "circuit_breaker_was_turned_off_line", { line: line }, "", SEND_TO.tb, instance, "circuit_breaker"); + if (breakerCounter < 0) reportToSend["contactor"]["off"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + else { + sendNotification("Cmd-mngr: onData", tbname, "circuit_breaker_was_turned_on_line", { line: line }, "", SEND_TO.tb, instance, "circuit_breaker"); + if (breakerCounter < 0) reportToSend["contactor"]["on"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + + //report status liniu + sendTelemetry({ status: status }, tbname) + + //current value + if (value == "Off") reportOfflineNodeStatus(line); //vyreportovat vsetky svietidla na linii + } + + } + } + else { + logger.debug("undefined cmd", cmd); + } + } + } + + return; + } + + //data from worksys + if (flowdata.data.hasOwnProperty("topic")) { + + let data = getNested(flowdata.data, "content", "data"); + + //if we get temperature in senica from senica-prod01 + let temperature = getNested(flowdata.data, "content", "senica_temperature"); + + if (temperature !== undefined) { + temperatureInSenica = temperature; + return; + } + + if (data === undefined) { + console.log("Invalid rpc command came from platform"); + return; + } + + let command = data.params.command; + let method = data.method; + let profile = data.params.payload; + if (profile == undefined) profile = ""; + let entity = data.params.entities[0]; + let entity_type = entity.entity_type; + let tbname = entity.tb_name; + + instance.send(SEND_TO.debug, flowdata.data); + 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") { + + //let command = data.params.command; + let value = data.params.payload.value; + + if (command == "dimming") { + + let nodeWasFound = false; + let keys = Object.keys(nodesData); + + //logger.debug("-----", keys); + + 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); + + value = parseInt(value); + if (value > 0) value = value + 128; + + params.type = "node-onetime-write"; + params.tbname = tbname; + params.address = node; + params.register = 1; + params.recipient = 1; + params.byte4 = value; + params.rw = 1; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'set dimming from platform'; + //params.debug = true; + + //debug(params); + logger.debug("dimming", params); + + tasks.push(params); + + 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); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 1; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read dimming (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + //pridame aj vyreportovanie - vykon + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 76; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read Input Power (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + //pridame aj vyreportovanie - prud svietidla + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 75; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read Input Current (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + //pridame aj vyreportovanie - power faktor - ucinnik + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 77; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read power factor (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + }, 4000); + + nodeWasFound = true; + break; + } + } + + if (!nodeWasFound) { + logger.debug("set dimming from platform", "unable to find tbname", tbname); + } + } + else { + instance.send(SEND_TO.debug, "undefined command " + command); + logger.debug("undefined command", command); + } + + return; + } + 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++) { + let node = keys[i]; + if (tbname == nodesData[node].tbname) { + + 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"); + + //profil úspešne prijatý pre node č. xx + sendNotification("Cmd-mngr", tbname, "dimming_profile_was_processed_for_node", { node: node }, profile, SEND_TO.tb, instance); + + nodesData[node].processed = false; + nodesData[node].profile = profile; + + processNodeProfile(node); + }); + }); + } + } + } + else { + + instance.send(SEND_TO.debug, "unknown method " + method); + logger.debug("unknown method", method); + + return; + } + } + + //nastav profil linie z platformy + 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") { + + 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++) { + let line = keys[i]; + if (tbname == relaysData[line].tbname) { + //zmazeme tasky + 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) { + + //update profile + logger.debug("worksys - update relay profile done:", profile); + instance.send(SEND_TO.debug, "worksys - update relay profile done"); + + relaysData[line].profile = profile; + + loadRelaysData(line) + logger.debug("loadRelaysData DONE for line", line); + + buildTasks({ processLineProfiles: true, line: line }); + + sendNotification("Cmd-mngr: set profile from worksys", tbname, "switching_profile_was_processed_for_line", { line: line }, profile, SEND_TO.tb, instance); + }); + }); + break; + } + } + } + else if (method == "set_command") { + let value = data.params.payload.value; + + 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; + + 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"); + if (line != 0) reportToSend["contactor"]["off"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + else { + turnLine("on", line, "command received from platform"); + if (line != 0) reportToSend["contactor"]["on"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + } + } + else { + instance.send(SEND_TO.debug, "undefined method " + method); + logger.debug("undefined method", method); + } + + return; + } + else { + instance.send(SEND_TO.debug, "UNKNOW entity_type " + entity_type); + logger.debug("UNKNOW entity_type", entity_type); + } + return; + } + + //terminal + if (!rsPort.isOpen) await rsPort.open(); + + let params = flowdata.data.body; + if (params == undefined) { + //logger.debug("Cmd-mngr: flowdata.data.body is undefined"); + return; + } + + params.priority = PRIORITY_TYPES.terminal; + params.type = "cmd-terminal"; + params.tbname = ""; + params.timestamp = PRIORITY_TYPES.terminal; + params.addMinutesToTimestamp = 0;// do not repeat task!!! + params.debug = true; + + let timestamp = Date.now(); + params.refFlowdataKey = timestamp; + //params.refFlowdata = flowdata; + //refFlowdata = flowdata; + + //console.log("flowdata", flowdata); + + cleanUpRefFlowdataObj(); + + refFlowdataObj[timestamp] = flowdata; + + //fix + //params.address = params.adress; + logger.debug("received from terminal", params); + logger.debug("date/time:", new Date()); + logger.debug("tasks length:", tasks.length); + + //tasks = []; + + //add to tasks + tasks.push(params); + + } + } + }) + + + //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) + } + + + /** + * 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; + + RESTBuilder.make(function(builder) { + + if (!builder) return; + + builder.method('GET'); + builder.url('http://192.168.252.2:8004/gettime?projects_id=1'); + + builder.callback(function(err, response, output) { + + 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); + } + + }); + } + + } 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); + + } else { + //console.log("Read-only", stdout); + + 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]: [ + { + "ts": date, + "values": values + } + ] + } + + tbHandler.sendToTb(dataToTb, instance); + } + + + function calculateDuskDawn(date, line, duskOffset = 0, dawnOffset = 0) { + + if (date === undefined) date = new Date(); + + 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); + } + + //if(profile.dawn_lux_sensor == false) + { + if (profile.hasOwnProperty("dawn_astro_clock_offset")) dawn_astro_clock_offset = parseInt(profile.dawn_astro_clock_offset); + } + + } + + } catch (error) { + if (profilestr != "") { + logger.debug(profilestr); + logger.debug(error); + } + } + + 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; + } + + //Dimming, CCT + else if (register == 1) { + let brightness = 0; + let dimming = byte0; + if (dimming > 128) { + //dimming = -128; + brightness = dimming - 128; + } + + //cct + //Ak Byte3 == 1: CCT = (Byte2*256)+Byte1 + let cct; + if (byte3 == 1) cct = byte2 * 256 + byte1; + else cct = bytesToInt(bytes.slice(0, 3)); + + //cct podla auditu + + values["dimming"] = brightness; + return values; + } + + // + else if (register == 4) { + values["master_node_version"] = bytes[1] + "." + bytes[2]; + //logger.debug("FW Version", register, bytes); + } + + //Napätie + else if (register == 74) { + let voltage = (bytesToInt(bytes) * 0.1).toFixed(1); + values["voltage"] = Number(voltage); + } + + //Prúd + else if (register == 75) { + let current = bytesToInt(bytes); + values["current"] = current; + } + + //výkon + else if (register == 76) { + let power = (bytesToInt(bytes) * 0.1).toFixed(2); + values["power"] = Number(power); + } + + //účinník + else if (register == 77) { + let power_factor = Math.cos(bytesToInt(bytes) * 0.1 * (Math.PI / 180)).toFixed(2); + values["power_factor"] = Number(power_factor); + } + + //frekvencia + else if (register == 78) { + let frequency = (bytesToInt(bytes) * 0.1).toFixed(2); + values["frequency"] = Number(frequency); + } + + //energia + else if (register == 79) { + let energy = bytesToInt(bytes); + values["energy"] = energy / 1000; //energia v kWh -> delit 1000 + } + + //doba života + else if (register == 80) { + let lifetime = (bytesToInt(bytes) / 60).toFixed(2); + values["lifetime"] = Number(lifetime); + } + + //nastavenie profilu + else if (register == 8) { + let time_schedule_settings = bytesToInt(bytes); + values["time_schedule_settings"] = time_schedule_settings; + } + + //naklon - nateraz sa z nodu nevycitava! kvoli problemom s accelerometrom a vracanymi hodnotami, posielame temp a x y z vo funkcii accelerometerData() + else if (register == 84) { + values["temperature"] = byte3 >= 128 ? (byte3 - 128) * (-1) : byte3; + values["inclination_x"] = byte2 >= 128 ? (byte2 - 128) * (-1) : byte2; + values["inclination_y"] = byte1 >= 128 ? (byte1 - 128) * (-1) : byte1; + values["inclination_z"] = byte0 >= 128 ? (byte0 - 128) * (-1) : byte0; + } + + //FW verzia nodu + else if (register == 89) { + //formát: "Byte3: Byte2.Byte1 (Byte0)" + values["fw_version"] = byte3 + ":" + byte2 + "." + byte1 + "(" + byte0 + ")"; + } + + else if (register == 87 || register == 6 || register == 7) { + var d = new Date(); + d.setHours(byte3, byte2, 0, 0); + let timestamp = d.getTime(); + + //aktuálny čas + if (register == 87) values["actual_time"] = timestamp; + //čas súmraku + else if (register == 6) values["dusk_time"] = timestamp; + //čas úsvitu + else if (register == 7) values["dawn_time"] = timestamp; + } + + 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; + + } + + + function getObjectByTbValue(object, tbname) { + return object[Object.keys(object).find(key => object[key].tbname === tbname)]; + } + + + function isObject(item) { + return (typeof item === "object" && !Array.isArray(item) && item !== null); + } + + + // we fake data, that should be received from accelerometer, as they are a bit unreliable. (temperature, x,y,z) + function accelerometerData() { + + if (temperatureInSenica === null) return; + + //clone nodesData and relaysData objects + let nodesData_clone = JSON.parse(JSON.stringify(nodesData)); + let relaysData_clone = JSON.parse(JSON.stringify(relaysData)); + + for (const key in relaysData_clone) { + + const lineData = relaysData_clone[key]; + const lineNumber = lineData.line; + const contactor = lineData.contactor; + + if (lineNumber === 0) continue; + + if (contactor === 1) { + + let date = Date.now(); + + Object.keys(nodesData_clone).forEach((node, index) => { + + setTimeout(function() { + + if (nodesData_clone[node].line === lineNumber) { + + // NOTE: if status of luminaire is NOK or OFFLINE, we do not send data; + let status = nodesData_clone[node].status; + if (status === "OFFLINE" || !status) return; + + let x = null; + if (naklony.hasOwnProperty(node)) x = naklony[node].naklon; + if (x === null) x = 0; + + sendTelemetry({ temperature: Math.round(temperatureInSenica + 10 + Math.floor(Math.random() * 3)), inclination_x: x, inclination_y: 0, inclination_z: 0 }, nodesData_clone[node].tbname, date); + } + + }, (index + 1) * 500); + }) + + } + } + } + + +} // end of instance.export + diff --git a/RVO12/flow/code.js b/RVO12/flow/code.js new file mode 100755 index 0000000..63b31bf --- /dev/null +++ b/RVO12/flow/code.js @@ -0,0 +1,90 @@ +exports.id = 'code'; +exports.title = 'Code'; +exports.group = 'Common'; +exports.color = '#656D78'; +exports.input = true; +exports.output = 1; +exports.author = 'Peter Širka'; +exports.icon = 'code'; +exports.version = '1.2.0'; +exports.options = { outputs: 1, code: 'send(0, value);', keepmessage: true }; + +exports.html = `
+
+
+
@(Number of outputs)
+
@(Minimum is 1)
+
+
+
@(Code)
+
@(Keep message instance)
+
+`; + +exports.readme = `# Code + +This component executes custom JavaScript code as it is and it doesn't contain any secure scope. + +\`\`\`javascript +// value {Object} contains received data +// send(outputIndex, newValue) sends a new value +// error(value) sends an error +// instance {Object} a current component instance +// flowdata {Object} a current flowdata +// repository {Object} a current repository of flowdata +// Example: + +// send() can be execute multiple times +send(0, value); +\`\`\``; + +exports.install = function(instance) { + + var fn; + + instance.on('data', function(response) { + if (fn) { + try { + fn(response.data, instance, response, instance.options, response.repository, require); + } catch (e) { + response.data = e; + instance.throw(response); + } + } + }); + + instance.reconfigure = function() { + try { + if (instance.options.code) { + instance.status(''); + var code = 'var send = function(index, value) { if (options.keepmessage) { flowdata.data = value; instance.send2(index, flowdata); } else instance.send2(index, value);}; var error = function(err) { instance.throw(err); }; ' + instance.options.code; + fn = new Function('value', 'instance', 'flowdata', 'options', 'repository', 'require', code); + } else { + instance.status('Not configured', 'red'); + fn = null; + } + } catch (e) { + fn = null; + instance.error('Code: ' + e.message); + } + }; + + instance.on('options', instance.reconfigure); + instance.reconfigure(); +}; \ No newline at end of file diff --git a/RVO12/flow/comment.js b/RVO12/flow/comment.js new file mode 100755 index 0000000..1e0cd13 --- /dev/null +++ b/RVO12/flow/comment.js @@ -0,0 +1,11 @@ +exports.id = 'comment'; +exports.title = 'Comment'; +exports.group = 'Common'; +exports.color = '#704cff'; +exports.author = 'Martin Smola'; +exports.icon = 'comment'; +exports.traffic = false; +exports.version = '1.0.0'; +exports.readme = '# Comment'; + +exports.install = function() {}; diff --git a/RVO12/flow/count.js b/RVO12/flow/count.js new file mode 100755 index 0000000..fa92ee9 --- /dev/null +++ b/RVO12/flow/count.js @@ -0,0 +1,60 @@ +exports.id = 'count'; +exports.title = 'Count'; +exports.version = '1.0.1'; +exports.author = 'John Graves'; +exports.color = '#656D78'; +exports.icon = 'plus-square'; +exports.input = 2; +exports.output = 1; +exports.options = { increment: 1, initialvalue: 1 }; +exports.readme = `# Counter + +Counter Number of times called.`; + +exports.html = `
+
@(Initial Value)
+
@(Increment)
+

Example Video

+
`; + +exports.readme = `# Count + +This component counts the number of messages received. + +__Response:__ + +Integer value based on the initial value and increment settings. + +__Arguments:__ +- Initial Value: What number should be output on the receipt of the first message. +- Increment: What should the increment be for each following message received.`; + +exports.install = function(instance) { + + var count = 0; + var initialCall = true; + + instance.on('data', function(flowdata) { + var index = flowdata.index; + if (index) { + instance.debug('Reset Count.'); + count = instance.options.initialvalue; + initialCall = true; + } else { + // If this is the first time, set the value to 'initial value' + if(initialCall) { + initialCall = false; + count = instance.options.initialvalue; + } else + count = count+instance.options.increment; + instance.status('Count:' + count); + instance.send2(count); + } + }); + + instance.on('options', function() { + count = instance.options.initialvalue; + initialCall = true; + }); + +}; diff --git a/RVO12/flow/db_connector.js b/RVO12/flow/db_connector.js new file mode 100755 index 0000000..65ee94b --- /dev/null +++ b/RVO12/flow/db_connector.js @@ -0,0 +1,286 @@ +exports.id = 'db_connector'; +exports.title = 'DbConnector'; +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.html = `
+
+
+
DbConnector
+
+
+
`; + +exports.readme = `# read/write data to tables`; + +const instanceSendTo = { + debug: 0, + http_response: 1, +} + +const { promisifyBuilder, makeMapFromDbResult } = require('./helper/db_helper.js'); + +function extractWhereParams(params) +{ + let name = params[0]; + let operator = '='; + let value = params[1]; + + if(params.length == 3) + { + operator = params[1]; + value = params[2]; + } + + return {name: name, operator: operator, value: value}; +} + +exports.install = function(instance) { + + let refFlowdata = null;//holds reference to httprequest flowdata + + instance.on("close", () => { + + }) + + + instance.on("data", async function(flowdata) { + + let params = flowdata.data.body; + console.log("DbConnector", params); + + refFlowdata = flowdata; + + if(refFlowdata != undefined) + { + //make http response + let responseObj = {}; + responseObj["type"] = "SUCESS"; + + try{ + + let table = params.table; + let action = params.action; + + + if(params.data != undefined) + { + let className = params.data.className; + + if(className == "SqlQueryBuilder") + { + let type = params.data.type; + + console.log("SqlQueryBuilder---->", params.data); + + if(type == "SELECT") + { + let table = params.data.queryData.tables[0].table; + + const db = TABLE(table); + var builder = db.find(); + + let result = await promisifyBuilder(builder); + + let response = {}; + response["result"] = result; + response["success"] = true; + + responseObj["data"] = response; + + //console.log(responseObj); + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + } + + return; + } + } + + + console.log("db_connector---->", table, action); + + //actions: read, replace, insert, delete, update... + + if(action == "read") + { + const db = TABLE(params.table); + + //where builder.where('age', '<', 15); + //builder.where('id', 3403); + + var builder = db.find(); + + //https://docs.totaljs.com/latest/en.html#api~DatabaseBuilder~builder.where + if(params.hasOwnProperty("where")) + { + //optionalCan contain "=", "<=", "<", ">=", ">". + //Default value: '=' + + //1.["production_line", 1] + //2. ["or", ["production_line", 1], ["production_line", 2], "end"] + + if (Array.isArray(params.where)) { + + let multipleConditions = false; + + if(params.where[0] == "or") multipleConditions = true; + if (Array.isArray(params.where[0])) multipleConditions = true; + + if(multipleConditions) + { + + for(var i = 0; i < params.where.length; i++) + { + const item = params.where[i]; + + if(item === "or") builder.or(); + + if (Array.isArray(item)) + { + const { name, operator, value } = extractWhereParams(item); + builder.where(name, operator, value); + } + + if(item === "end") builder.end(); + + } + + } + else + { + const { name, operator, value } = extractWhereParams(params.where); + builder.where(name, operator, value); + } + + } + + /* + if(params.where.length >=2 ) + { + let name = params.where[0]; + let operator = '='; + let value = params.where[1]; + + if(params.where.length == 3) + { + operator = params.where[1]; + value = params.where[2]; + } + + builder.where(name, operator, value); + } + */ + } + + if(params.hasOwnProperty("between")) + { + builder.between(params.between[0], params.between[1], params.between[2]); + } + + let response = await promisifyBuilder(builder); + responseObj["data"] = response; + + //console.log(responseObj); + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + + return; + } + + if(action == "delete") + { + + } + + + if(action == "update") + { + //! data receiving from terminal (params) + // { + // hostname: 'localhost', + // table: 'settings', + // action: 'update', + // body: { + // rvo_name: 'terrrr', + // lang: 'en', + // temperature_adress: '28.427B45920702', + // latitude: 48.70826502, + // longitude: 17.28455203, + // mqtt_host: '192.168.252.4', + // mqtt_clientid: 'showroom_test_panel_led', + // mqtt_username: 'xmRd6RJxW53WZe4vMFLU', + // mqtt_port: 1883, + // maintanace_mode: false + // } + // } + const tableToModify = TABLE(params.table); + const newValues = params.body; + + tableToModify.modify(newValues).make(function(builder) { + + builder.callback(function(err, response) { + + if(!err) + { + responseObj["data"] = response; + responseObj["tableUpdated"] = true; + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + } + }); + }); + + } + + if(action == "replace") + { + //truncate table + const db = TABLE(params.table); + var builder = db.remove(); + db.clean(); + + //insert data + let data = params.data; + + for(let i = 0; i < data.length; i++) + { + //console.log(data[i]); + db.insert(data[i]); + } + + console.log("insert done"); + + let responseObj = {}; + responseObj["type"] = "SUCESS"; + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + + + } + + + + } catch (error) { + //console.log(error); + responseObj["type"] = "ERROR"; + responseObj["message"] = error; + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + } + } + }) +} + + diff --git a/RVO12/flow/db_init.js b/RVO12/flow/db_init.js new file mode 100755 index 0000000..b399878 --- /dev/null +++ b/RVO12/flow/db_init.js @@ -0,0 +1,113 @@ +exports.id = 'db_init'; +exports.title = 'DB Initialization'; +exports.group = 'Worksys'; +exports.color = '#888600'; +exports.version = '1.0.2'; +exports.icon = 'sign-out'; +exports.output = 2; + +exports.readme = ` + # DB initialization +`; + +const { promisifyBuilder, makeMapFromDbResult } = require('./helper/db_helper.js'); +const { initNotification } = require('./helper/notification_reporter'); +const errorHandler = require('./helper/ErrorToServiceHandler'); +const total_energy = require('../databases/total_energy'); + +const SEND_TO = { + db_init: 0, + infoSender: 1 +}; + + +exports.install = async function(instance) { + const dbNodes = TABLE("nodes"); + const dbRelays = TABLE("relays"); + const dbSettings = TABLE("settings"); + 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 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.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"]; + Object.keys(dbs.nodesData).forEach(node => dbs.nodesData[node].readout = {}) + + let rvo_number = responseSettings[0]["rvo_name"].match(/\D+(\d{1,2})_/)[1]; + + dbs.settings = { + edge_fw_version: "2025-10-08", //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"], + phases: responseSettings[0]["phases"], + cloud_topic: responseSettings[0]["cloud_topic"], + has_main_switch: responseSettings[0]["has_main_switch"], + daily_report: responseSettings[0]["daily_report"], + send_changed_node_numbers: responseSettings[0]["send_changed_node_numbers"], + rvo_number: rvo_number, + + //dynamic values + masterNodeIsResponding: true, //cmd_manager + maintenance_mode: false, + } + + + dbs.settings.energy_to_switch_lamps = total_energy[rvo_number]; + if (dbs.settings.energy_to_switch_lamps === undefined) console.log('=============== db_init.js: energy_to_switch_lamps is undefined'); + + FLOW.dbLoaded = true; + errorHandler.setProjectId(dbs.settings.project_id); + initNotification(); + + //APP START - send to data services + const toService = { + id: dbs.settings.project_id, + name: dbs.settings.rvo_name, + fw_version: dbs.settings.edge_fw_version, + startdate: new Date().toISOString().slice(0, 19).replace('T', ' '), + js_error: "", + error_message: "" + }; + + instance.send(SEND_TO.infoSender, toService); + console.log("----------------> START - message send to service", toService); + + setTimeout(() => { + console.log("DB_INIT - data loaded"); + instance.send(SEND_TO.db_init, "_") + }, 5000) + +}; + diff --git a/RVO12/flow/debug.js b/RVO12/flow/debug.js new file mode 100755 index 0000000..00cb259 --- /dev/null +++ b/RVO12/flow/debug.js @@ -0,0 +1,100 @@ +exports.id = 'debug'; +exports.title = 'Debug'; +exports.author = 'Peter Širka'; +exports.color = '#967ADC'; +exports.click = true; +exports.input = true; +exports.icon = 'bug'; +exports.version = '2.0.4'; +exports.options = { enabled: true, repository: false, type: 'data' }; +exports.readme = `# Debug + +Prints data to the debug tab.`; + +exports.html = `
+
+
+
@(Output type)
+
@(Path to the property (leave empty to show the whole data object))
+
@(A group name)
+
@(Enabled)
+
+
+
`; + +exports.install = function(instance) { + + instance.on('data', function(response) { + if (instance.options.enabled) { + + var opt = instance.options; + var rep = response.repository; + var val = response.data; + var id = response.id; + + switch (instance.options.type){ + case 'both': + var data = {}; + data.repository = rep; + data.data = val instanceof Error ? { error: val.message, stack: val.stack } : val; + instance.debug(safeparse(opt.property ? U.get(data, opt.property) : data), undefined, opt.group, id); + break; + case 'repository': + instance.debug(safeparse(opt.property ? U.get(rep, opt.property) : rep), undefined, opt.group, id); + break; + case 'data': + default: + if (val instanceof Error) + instance.debug({ error: val.message, stack: val.stack }, undefined, opt.group, id); + else + instance.debug(safeparse(opt.property ? U.get(val, opt.property) : val), undefined, opt.group, id); + break; + } + } + }); + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + instance.save(); + }); + + instance.on('options', function() { + instance.custom.status(); + }); + + instance.custom.status = function() { + instance.status(instance.options.enabled ? 'Enabled' : 'Disabled'); + }; + + instance.custom.status(); + + function safeparse(o) { + + if (o instanceof Buffer) + return o; + + if (o === undefined) + return 'undefined'; + + if (o === null) + return 'null'; + + var cache = []; + var str = JSON.stringify(o, function(key, value) { + if (typeof value === 'object' && value !== null) { + if (cache.indexOf(value) !== -1) { + try { + return JSON.parse(JSON.stringify(value)); + } catch (error) { + return; + } + } + cache.push(value); + } + return value; + }); + cache = null; + return JSON.parse(str); + } +}; diff --git a/RVO12/flow/designer.json b/RVO12/flow/designer.json new file mode 100755 index 0000000..580f5a3 --- /dev/null +++ b/RVO12/flow/designer.json @@ -0,0 +1,3102 @@ +{ + "tabs": [ + { + "name": "MAIN PUSH", + "linker": "main-push", + "id": "1612772287426", + "index": 0 + }, + { + "name": "CMD manager", + "linker": "cmd-manager", + "id": "1615551125555", + "index": 1 + }, + { + "name": "Devices", + "linker": "devices", + "id": "1611921777196", + "index": 2 + } + ], + "components": [ + { + "id": "1611951142547", + "component": "debug", + "tab": "1611921777196", + "name": "ERROR", + "x": 598, + "y": 60, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#DA4453", + "notes": "" + }, + { + "id": "1612776786008", + "component": "wsmqttpublish", + "tab": "1612772287426", + "name": "WS MQTT publish", + "x": 281.75, + "y": 174, + "connections": { + "0": [ + { + "index": "0", + "id": "1615551060773" + } + ], + "1": [ + { + "index": "0", + "id": "1618300858252" + }, + { + "index": "0", + "id": "1618558465485" + } + ], + "2": [ + { + "index": "0", + "id": "1634303685503" + } + ], + "3": [ + { + "index": "0", + "id": "1731068754606" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Connected", + "color": "green" + }, + "options": { + "username": "", + "clientid": "", + "port": "1883", + "host": "" + }, + "color": "#888600", + "notes": "" + }, + { + "id": "1612778461252", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "tb-push", + "x": 72.75, + "y": 328, + "connections": { + "0": [ + { + "index": "0", + "id": "1612783322136" + }, + { + "index": "1", + "id": "1612776786008" + }, + { + "index": "0", + "id": "1731068754606" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1612783322136", + "component": "debug", + "tab": "1612772287426", + "name": "to TB", + "x": 283.75, + "y": 324, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615551060773", + "component": "debug", + "tab": "1612772287426", + "name": "errors from MQTT Broker", + "x": 594, + "y": 57, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#DA4453", + "notes": "" + }, + { + "id": "1615563373927", + "component": "debug", + "tab": "1615551125555", + "name": "Debug", + "x": 755, + "y": 155, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#DA4453", + "notes": "" + }, + { + "id": "1615566865233", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "tb-push", + "x": 755, + "y": 248, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1615798582262", + "component": "debug", + "tab": "1615551125555", + "name": "CMD_debug", + "x": 755, + "y": 346, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615802995322", + "component": "debug", + "tab": "1611921777196", + "name": "Debug", + "x": 596.8833312988281, + "y": 566.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Disabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": false + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615809128443", + "component": "debug", + "tab": "1611921777196", + "name": "tempToTb", + "x": 595.8833312988281, + "y": 658.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615809595184", + "component": "virtualwireout", + "tab": "1611921777196", + "name": "tb-push", + "x": 597.8833312988281, + "y": 377.25, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1616165795916", + "component": "httproute", + "tab": "1615551125555", + "name": "POST /terminal", + "x": 135, + "y": 547, + "connections": { + "0": [ + { + "index": "0", + "id": "1684060205000" + }, + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Listening", + "color": "green" + }, + "options": { + "timeout": 10, + "cachepolicy": 0, + "cacheexpire": "5 minutes", + "size": 5, + "url": "/terminal", + "method": "POST", + "name": "", + "flags": [ + "id:1616165795916", + "post", + 10000 + ], + "emptyresponse": false + }, + "color": "#5D9CEC", + "notes": "### Configuration\n\n- __POST /terminal__\n- flags: \n- maximum request data length: __5 kB__\n- empty response: __false__\n- cache policy: __no cache__\n- cache expire: __5 minutes__", + "cloning": false + }, + { + "id": "1616165824813", + "component": "httpresponse", + "tab": "1615551125555", + "name": "HTTP Response", + "x": 753, + "y": 423, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "json" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1617104731852", + "component": "debug", + "tab": "1615551125555", + "name": "DIDO_Debug", + "x": 669, + "y": 1040, + "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": "turnOff line", + "x": 133, + "y": 1161, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "object", + "data": "{line: 3, command: \"turnOff\", force: true}" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1617115013095", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "tb-push", + "x": 669, + "y": 1150, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1617284749681", + "component": "trigger", + "tab": "1615551125555", + "name": "update profile / node", + "x": 112, + "y": 208, + "connections": { + "0": [ + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "data": "profile_nodes", + "datatype": "string" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1618235171399", + "component": "trigger", + "tab": "1615551125555", + "name": "tun tasks", + "x": 184, + "y": 279, + "connections": { + "0": [ + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "data": "run" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1618300858252", + "component": "debug", + "tab": "1612772287426", + "name": "wsmqtt-exit1", + "x": 597.8833312988281, + "y": 149, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1618393583970", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "to-cmd-manager", + "x": 668.8833312988281, + "y": 1269, + "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": 132.88333129882812, + "y": 367, + "connections": { + "0": [ + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "platform-rpc-call", + "color": "gray" + }, + "options": { + "wirename": "platform-rpc-call" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1618393759854", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "cmd_to_dido", + "x": 119.88333129882812, + "y": 1007, + "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": 752.8833312988281, + "y": 527, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "cmd_to_dido", + "color": "gray" + }, + "options": { + "wirename": "cmd_to_dido" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1618558465485", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "platform-rpc-call", + "x": 597.8833312988281, + "y": 247, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "platform-rpc-call", + "color": "gray" + }, + "options": { + "wirename": "platform-rpc-call" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1618572059773", + "component": "trigger", + "tab": "1615551125555", + "name": "turnOn line", + "x": 132, + "y": 1085, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "data": "{line: 1, command: \"turnOn\", force: true}", + "datatype": "object" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1619515097737", + "component": "cmd_manager", + "tab": "1615551125555", + "name": "CMD Manager", + "x": 452.1091003417969, + "y": 341.05455017089844, + "connections": { + "0": [ + { + "index": "0", + "id": "1615563373927" + } + ], + "1": [ + { + "index": "0", + "id": "1615566865233" + }, + { + "index": "0", + "id": "1615798582262" + } + ], + "2": [ + { + "index": "0", + "id": "1616165824813" + } + ], + "3": [ + { + "index": "0", + "id": "1618393827655" + } + ], + "4": [ + { + "index": "0", + "id": "1635936391935" + } + ], + "5": [ + { + "index": "0", + "id": "1757006030239" + }, + { + "index": "0", + "id": "1757006060377" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1619605019281", + "component": "httproute", + "tab": "1615551125555", + "name": "GET db", + "x": 173, + "y": 653, + "connections": { + "0": [ + { + "index": "0", + "id": "1684060205000" + }, + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Listening", + "color": "green" + }, + "options": { + "timeout": 5, + "cachepolicy": 0, + "cacheexpire": "5 minutes", + "size": 5, + "url": "/db", + "method": "GET", + "name": "", + "flags": [ + "id:1619605019281", + "get", + 5000 + ] + }, + "color": "#5D9CEC", + "notes": "### Configuration\n\n- __GET /db__\n- flags: undefined\n- maximum request data length: __5 kB__\n- empty response: __undefined__\n- cache policy: __no cache__\n- cache expire: __5 minutes__", + "cloning": false + }, + { + "id": "1619784672383", + "component": "trigger", + "tab": "1615551125555", + "name": "turnOnAlarm", + "x": 120, + "y": 1234, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "object", + "data": "{command: \"turnOnAlarm\"}" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1619784812964", + "component": "trigger", + "tab": "1615551125555", + "name": "turnOffAlarm", + "x": 118, + "y": 1307, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "object", + "data": "{command: \"turnOffAlarm\"}" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1621340721628", + "component": "virtualwireout", + "tab": "1611921777196", + "name": "modbus_to_dido", + "x": 599, + "y": 471, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "modbus_to_dido", + "color": "gray" + }, + "options": { + "wirename": "modbus_to_dido" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1622640022885", + "component": "httproute", + "tab": "1615551125555", + "name": "POST /db_connector", + "x": 98, + "y": 1586, + "connections": { + "0": [ + { + "index": "0", + "id": "1622640073521" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Listening", + "color": "green" + }, + "options": { + "timeout": 5, + "cachepolicy": 0, + "cacheexpire": "5 minutes", + "size": 5, + "url": "/db_connector", + "method": "POST", + "flags": [ + "id:1622640022885", + "post", + 5000 + ] + }, + "color": "#5D9CEC", + "notes": "### Configuration\n\n- __POST /db_connector__\n- flags: \n- maximum request data length: __5 kB__\n- empty response: __undefined__\n- cache policy: __no cache__\n- cache expire: __5 minutes__", + "cloning": false + }, + { + "id": "1622640073521", + "component": "db_connector", + "tab": "1615551125555", + "name": "DbConnector", + "x": 372, + "y": 1572, + "connections": { + "1": [ + { + "index": "0", + "id": "1622641420685" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "edge": "undefined" + }, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1622641420685", + "component": "httpresponse", + "tab": "1615551125555", + "name": "HTTP Response", + "x": 596, + "y": 1586, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1634303504177", + "component": "monitormemory", + "tab": "1612772287426", + "name": "RAM", + "x": 69.88333129882812, + "y": 888.5, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465281992" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "858.88 MB / 985.68 MB", + "color": "gray" + }, + "options": { + "enabled": true, + "interval": 30000 + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1634303533779", + "component": "monitordisk", + "tab": "1612772287426", + "name": "disk", + "x": 70.88333129882812, + "y": 982.5, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465821120" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "5.78 GB / 7.26 GB", + "color": "gray" + }, + "options": { + "enabled": true, + "path": "/", + "interval": 30000 + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1634303595494", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "send-to-services", + "x": 51.883331298828125, + "y": 1400.5, + "connections": { + "0": [ + { + "index": "0", + "id": "1634463186563" + }, + { + "index": "1", + "id": "1634488120710" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1634303602169", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "send-to-services", + "x": 426.8833312988281, + "y": 878.5, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1634303685503", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "send-to-services", + "x": 600.8833312988281, + "y": 341.5, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1634303743260", + "component": "httprequest", + "tab": "1612772287426", + "name": "192.168.252.2:8004/sentmessage", + "reference": "", + "x": 506.8833312988281, + "y": 1331.7333374023438, + "connections": { + "0": [ + { + "index": "0", + "id": "1635327431236" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "url": "http://192.168.252.2:8004/sentmessage", + "method": "POST", + "stringify": "json" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1634463186563", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 305.75, + "y": 1442, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634464580289", + "component": "code", + "tab": "1612772287426", + "name": "Code", + "x": 245, + "y": 787, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465243324" + }, + { + "index": "0", + "id": "1634303602169" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "keepmessage": true, + "code": "let response = {};\nresponse.cpu = value.cpu;\nresponse.uptime = value.uptime;\n\nsend(0, response);", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1634465243324", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 428, + "y": 784, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634465281992", + "component": "code", + "tab": "1612772287426", + "name": "Code", + "x": 245, + "y": 884, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465338103" + }, + { + "index": "0", + "id": "1634303602169" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "keepmessage": true, + "code": "value.sender = \"ram\";\n\nlet response = {};\n\nresponse.memory_total = Math.round(value.total / (1024 ** 2));\nresponse.memory_free = Math.round(value.free / (1024 ** 2));\nresponse.memory_used = Math.round(value.used / (1024 ** 2));\n\nsend(0, response);", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1634465338103", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 429, + "y": 976, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634465821120", + "component": "code", + "tab": "1612772287426", + "name": "Code", + "x": 245, + "y": 978, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465892500" + }, + { + "index": "0", + "id": "1634303602169" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "keepmessage": true, + "code": "value.sender = \"hdd\";\n\nlet response = {};\n\nresponse.hdd_total = Math.round(value.total / (1024 ** 2));\nresponse.hdd_free = Math.round(value.free / (1024 ** 2));\nresponse.hdd_used = Math.round(value.used / (1024 ** 2));\n\nsend(0, response);", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1634465892500", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 432, + "y": 1068, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634484067516", + "component": "debug", + "tab": "1612772287426", + "name": "Send info", + "x": 513, + "y": 1441, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634488120710", + "component": "infosender", + "tab": "1612772287426", + "name": "Info sender", + "x": 301, + "y": 1336, + "connections": { + "0": [ + { + "index": "0", + "id": "1634484067516" + }, + { + "index": "0", + "id": "1634303743260" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "edge": "undefined" + }, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1635327431236", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 837.8833312988281, + "y": 1325.5, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1635936391935", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "send-to-services", + "x": 753, + "y": 623, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1637069803394", + "component": "monitorconsumption", + "tab": "1612772287426", + "name": "CPU", + "x": 69, + "y": 791, + "connections": { + "0": [ + { + "index": "0", + "id": "1634464580289" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "49.2% / 69.91 MB", + "color": "gray" + }, + "options": { + "monitorfiles": true, + "monitorconnections": true, + "monitorsize": true, + "monitorconsumption": true, + "enabled": true, + "interval": 30000 + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1683664161036", + "component": "debug", + "tab": "1615551125555", + "name": "CMDtoDIDO", + "x": 392, + "y": 1012, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1683981346282", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "from-dido-controller", + "x": 112, + "y": 459, + "connections": { + "0": [ + { + "index": "0", + "id": "1684055037116" + }, + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "from-dido-controller", + "color": "gray" + }, + "options": { + "wirename": "from-dido-controller" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1684055037116", + "component": "debug", + "tab": "1615551125555", + "name": "from dido to cmd", + "x": 451, + "y": 532, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1684060205000", + "component": "debug", + "tab": "1615551125555", + "name": "HTTP routes", + "x": 450, + "y": 639, + "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": "MDBToDido", + "x": 598, + "y": 147, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1699963668903", + "component": "dido_controller", + "tab": "1615551125555", + "name": "DIDO_Controller", + "x": 397, + "y": 1131, + "connections": { + "0": [ + { + "index": "0", + "id": "1617104731852" + } + ], + "1": [ + { + "index": "0", + "id": "1617104731852" + }, + { + "index": "0", + "id": "1617115013095" + } + ], + "2": [ + { + "index": "0", + "id": "1618393583970" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "edge": "undefined" + }, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1699964678894", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "modbus_to_dido", + "x": 96, + "y": 924, + "connections": { + "0": [ + { + "index": "0", + "id": "1699963668903" + }, + { + "index": "0", + "id": "1699964793925" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "modbus_to_dido", + "color": "gray" + }, + "options": { + "wirename": "modbus_to_dido" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1699964793925", + "component": "debug", + "tab": "1615551125555", + "name": "modbusToDido", + "x": 388, + "y": 920, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1699965957410", + "component": "modbus_reader", + "tab": "1611921777196", + "name": "Modbus reader", + "x": 232, + "y": 175, + "connections": { + "0": [ + { + "index": "0", + "id": "1611951142547" + } + ], + "1": [ + { + "index": "0", + "id": "1621340721628" + }, + { + "index": "0", + "id": "1684179110403" + }, + { + "index": "0", + "id": "1717441414646" + } + ], + "2": [ + { + "index": "0", + "id": "1615809595184" + }, + { + "index": "0", + "id": "1714752862828" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1700411878636", + "component": "thermometer", + "tab": "1611921777196", + "name": "Thermometer", + "x": 234.75, + "y": 444, + "connections": { + "0": [ + { + "index": "0", + "id": "1615802995322" + } + ], + "1": [ + { + "index": "0", + "id": "1615809595184" + }, + { + "index": "0", + "id": "1615809128443" + } + ], + "2": [ + { + "index": "0", + "id": "1621340721628" + }, + { + "index": "0", + "id": "1732889185927" + }, + { + "index": "0", + "id": "1717441414646" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#5CB36D", + "notes": "" + }, + { + "id": "1714752862828", + "component": "debug", + "tab": "1611921777196", + "name": "MDBToTb", + "x": 766, + "y": 324, + "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": 764.0833282470703, + "y": 222, + "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\telse if(value.status === \"NOK-thermometer\")\n\t{\n\t\tsend(0, {\"thermometer\": \"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\telse if(value.values.hasOwnProperty(\"temperature\"))\n\t{\n\t\tsend(0, {\"thermometer\": \"OK\"});\n\t}\n}", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1717442627834", + "component": "debug", + "tab": "1611921777196", + "name": "modbus service", + "x": 966.0833282470703, + "y": 165, + "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": 968.0833282470703, + "y": 268, + "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": 88.75, + "y": 1685, + "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": 296, + "y": 1671, + "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\", \"Flow has been restarted\", \"Node db has changed\"]", + "types": "[\"emergency\", \"critical\", \"error\", \"alert\"]", + "name": "" + }, + "color": "#30E193", + "notes": "" + }, + { + "id": "1718016073501", + "component": "httprequest", + "tab": "1612772287426", + "name": "http://192.168.252.2:8004/slack", + "x": 495, + "y": 1753, + "connections": { + "0": [ + { + "index": "0", + "id": "1718016086212" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "url": "http://192.168.252.2:8004/slack", + "method": "POST", + "stringify": "json" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1718016086212", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 832, + "y": 1664, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "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": 87, + "y": 1591, + "connections": { + "0": [ + { + "index": "0", + "id": "1718016052341" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "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\": \"\" } } } ] }", + "datatype": "object" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1729855334955", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "platform-rpc-call", + "x": 599.9333343505859, + "y": 541.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "platform-rpc-call", + "color": "gray" + }, + "options": { + "wirename": "platform-rpc-call" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1729855371093", + "component": "debug", + "tab": "1612772287426", + "name": "rpc cloud", + "x": 601.9333343505859, + "y": 440.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1731068658334", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 75.75, + "y": 184, + "connections": { + "0": [ + { + "index": "0", + "id": "1612776786008" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731068754606", + "component": "cloudmqttconnect", + "tab": "1612772287426", + "name": "MQTT to senica-prod01", + "x": 284.75, + "y": 452, + "connections": { + "1": [ + { + "index": "0", + "id": "1729855371093" + }, + { + "index": "0", + "id": "1729855334955" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Connected", + "color": "green" + }, + "options": { + "username": "", + "clientid": "", + "port": "2764", + "host": "192.168.252.2", + "topic": "" + }, + "color": "#888600", + "notes": "" + }, + { + "id": "1731069001548", + "component": "db_init", + "tab": "1612772287426", + "name": "DB Initialization", + "x": 1003.75, + "y": 240.25, + "connections": { + "0": [ + { + "index": "0", + "id": "1731069033416" + } + ], + "1": [ + { + "index": "0", + "id": "1747561603739" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#888600", + "notes": "" + }, + { + "id": "1731069033416", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "db-init", + "x": 1244.75, + "y": 233.25, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069059135", + "component": "showdb", + "tab": "1612772287426", + "name": "Show db data", + "x": 1186.75, + "y": 821.25, + "connections": { + "0": [ + { + "index": "0", + "id": "1731069079243" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#888600", + "notes": "" + }, + { + "id": "1731069079243", + "component": "debug", + "tab": "1612772287426", + "name": "dbData", + "x": 1390.75, + "y": 870.25, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1731069116691", + "component": "trigger", + "tab": "1612772287426", + "name": "settings", + "x": 934.75, + "y": 669.75, + "connections": { + "0": [ + { + "index": "0", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069131637", + "component": "trigger", + "tab": "1612772287426", + "name": "relaysData", + "x": 876.75, + "y": 733.75, + "connections": { + "0": [ + { + "index": "1", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069137374", + "component": "trigger", + "tab": "1612772287426", + "name": "nodesData", + "x": 852.75, + "y": 794.75, + "connections": { + "0": [ + { + "index": "2", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069179846", + "component": "trigger", + "tab": "1612772287426", + "name": "pinsData", + "x": 850.75, + "y": 861.75, + "connections": { + "0": [ + { + "index": "3", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069192937", + "component": "trigger", + "tab": "1612772287426", + "name": "sample data", + "x": 857.75, + "y": 928.75, + "connections": { + "0": [ + { + "index": "4", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069264443", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 63.75, + "y": 1279, + "connections": { + "0": [ + { + "index": "0", + "id": "1634488120710" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069334626", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "db-init", + "x": 172.88333129882812, + "y": 129, + "connections": { + "0": [ + { + "index": "0", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069548145", + "component": "virtualwirein", + "tab": "1611921777196", + "name": "db-init", + "x": 46.75, + "y": 192, + "connections": { + "0": [ + { + "index": "0", + "id": "1699965957410" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069567152", + "component": "virtualwirein", + "tab": "1611921777196", + "name": "db-init", + "x": 44.75, + "y": 465, + "connections": { + "0": [ + { + "index": "0", + "id": "1700411878636" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731070156936", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "db-init", + "x": 126.88333129882812, + "y": 1377, + "connections": { + "0": [ + { + "index": "2", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731234189516", + "component": "trigger", + "tab": "1612772287426", + "name": "monitor.txt", + "x": 882.75, + "y": 991.75, + "connections": { + "0": [ + { + "index": "5", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731234189551", + "component": "trigger", + "tab": "1612772287426", + "name": "err.txt", + "x": 904.75, + "y": 1053.75, + "connections": { + "0": [ + { + "index": "6", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1732700042559", + "component": "nodesdb_change_check", + "tab": "1612772287426", + "name": "Nodes DB change check", + "x": 266.8833312988281, + "y": 1980.2333984375, + "connections": { + "0": [ + { + "index": "0", + "id": "1732700071298" + }, + { + "index": "0", + "id": "1732700642917" + } + ], + "1": [ + { + "index": "0", + "id": "1759958914348" + }, + { + "index": "0", + "id": "1759959003114" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#888600", + "notes": "" + }, + { + "id": "1732700057052", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 76.75, + "y": 1988, + "connections": { + "0": [ + { + "index": "0", + "id": "1732700042559" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1732700071298", + "component": "debug", + "tab": "1612772287426", + "name": "nodesChange", + "x": 571.8833312988281, + "y": 2018.2333984375, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1732700642917", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "tb-push", + "x": 567.8833312988281, + "y": 1933, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1732889185927", + "component": "debug", + "tab": "1611921777196", + "name": "tempToDido", + "x": 594.8833312988281, + "y": 753, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1733574412965", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 72.75, + "y": 474, + "connections": { + "0": [ + { + "index": "1", + "id": "1731068754606" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1747561603739", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "send-to-services", + "x": 1243.8833312988281, + "y": 334.5, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1747562867845", + "component": "comment", + "tab": "1612772287426", + "name": "FLOW STARTING POINT", + "x": 1003.5666656494141, + "y": 178, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#704cff", + "notes": "" + }, + { + "id": "1749211698385", + "component": "trigger", + "tab": "1612772287426", + "name": "deviceStatus", + "x": 911.75, + "y": 1116.75, + "connections": { + "0": [ + { + "index": "7", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1757006030239", + "component": "httprequest", + "tab": "1615551125555", + "name": "192.168.252.2:8015/daily_report", + "x": 756.5666656494141, + "y": 715.4499969482422, + "connections": { + "0": [ + { + "index": "0", + "id": "1757006045804" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "stringify": "json", + "method": "POST", + "url": "http://192.168.252.2:8015/daily_report" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1757006045804", + "component": "debug", + "tab": "1615551125555", + "name": "ddd", + "x": 1091.566665649414, + "y": 711.4499969482422, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1757006060377", + "component": "debug", + "tab": "1615551125555", + "name": "reportDebug", + "x": 749.5666656494141, + "y": 799.4499969482422, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1759958914348", + "component": "httprequest", + "tab": "1612772287426", + "name": "http://192.168.252.2:8015/node_numbers", + "x": 571, + "y": 2111, + "connections": { + "0": [ + { + "index": "0", + "id": "1759958927094" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "stringify": "json", + "method": "POST", + "url": "http://192.168.252.2:8015/node_numbers" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1759958927094", + "component": "debug", + "tab": "1612772287426", + "name": "nodesChangeCloud", + "x": 951.8833312988281, + "y": 2109.2333984375, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1759959003114", + "component": "debug", + "tab": "1612772287426", + "name": "nodeChangeCloud1", + "x": 574, + "y": 2218, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1760020290879", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 84.75, + "y": 1787, + "connections": { + "0": [ + { + "index": "1", + "id": "1718016052341" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + } + ], + "version": 615 +} diff --git a/RVO12/flow/dido_controller.js b/RVO12/flow/dido_controller.js new file mode 100755 index 0000000..d16fb19 --- /dev/null +++ b/RVO12/flow/dido_controller.js @@ -0,0 +1,1486 @@ +exports.id = 'dido_controller'; +exports.title = 'DIDO_Controller'; +exports.version = '2.0.0'; +exports.group = 'Worksys'; +exports.color = '#2134B0'; +exports.input = 3; +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 + +state_of_main_switch - reportovat stav hlaveho istica : 0-> off 1-> on +rotary_switch_state - sem by sa mal reportovat stav vstupov manual a auto pola nasledovnej logiky: Manual = 1 a Auto = 0 -> Manu +Manual = 0 a Auto = 0 -> Off, Manual = 0 a Auto = 1 -> Automatic + +door_condition - pin 6, dverový kontakt -> 1 -> vyreportuje Closed, 0 -> vyreportuje Ope +twilight_sensor - hodnotu, ktoru vracia ten analogovy vstup (17) treba poslat sem ako float number. Zrejme tu potom pridame nejaky koeficient prevodu na luxy + +Na kazdu liniu +state_of_breaker - podla indexu istica sa reportuje jeho stav, teda istic na liniu 1: 0-> off, 1-> on +state_of_contactor - podla indexu stkaca sa reportuje jeho stav, teda stykac 1 na liniu 1: 0-> off, 1-> on +*/ + +const { errLogger, logger, monitor } = require('./helper/logger'); +const SerialPort = require('serialport'); +const WebSocket = require('ws'); +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 errorHandler = require('./helper/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 hasMainSwitch; + +let alarmStatus = "OFF"; + +const SEND_TO = { + debug: 0, + tb: 1, + cmd_manager: 2 +} + + +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 = {}; + let rsPortReceivedData = []; + + //to be able to get proper twilight values + let twilight_sensor_interval = 5;//minutes + let twilight_sensor = []; + const twilight_sensor_array = []; + let twilightError = false; + + monitor.info("DIDO_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-we make it global to see it from outside + FLOW.deviceStatus = { //key is device name: temperature,.... + "state_of_main_switch": "Off", //Hlavny istic (alebo druhy dverovy kontakt) + "rotary_switch_state": "Off", //Prevadzkovy + "door_condition": "closed", //Dverový kontakt + "em": "OK", //elektromer rvo + "temperature": "OK", //templomer + "battery": "OK", //Bateria + "power_supply": "OK", //Zdroj + "master_node": "OK", //MN - GLOBALS.settings.masterNodeIsResponding + "no_voltage": "OK", //GLOBALS.settings.no_voltage - vypadok napatia na faze + "state_of_breaker": {}, //"Off",//Istic + "state_of_contactor": {}, //"Off",//Stykac + "twilight_sensor": "OK" //lux sensor + }; + let deviceStatus = FLOW.deviceStatus; + + + function main() { + + GLOBALS = FLOW.GLOBALS; + SETTINGS = FLOW.GLOBALS.settings; + rvoTbName = SETTINGS.rvoTbName; + pinsData = GLOBALS.pinsData; + relaysData = GLOBALS.relaysData; + + tbHandler = new DataToTbHandler(SEND_TO.tb); + tbHandler.setSender(exports.title); + + controller_type = SETTINGS.controller_type; //"lm" or "unipi" + hasMainSwitch = SETTINGS.has_main_switch; + + if (controller_type == "") controller_type = "lm"; + + 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, "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; + } + } + + //report RVO version relaysData[0].tbname; + let values = {}; + values["edge_fw_version"] = SETTINGS.edge_fw_version; + values["maintenance_mode"] = SETTINGS.maintenance_mode; + + sendTelemetry(values, rvoTbName); + + 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); + } + + + function handleRsPort() { + + if (rsPort) { + rsPort.removeAllListeners(); + rsPort = null; + } + + //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('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) { + if (!err) { + monitor.info(exports.title + "--->Digital in_out has been set (runSyncExec was sucessfull)"); + + turnAlarm("off"); + 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('error', err => { + let message = "Dido: rsPort error: " + err.message; + logger.debug(message); + monitor.info(message); + errorHandler.sendMessageToService(message); + }) + + rsPort.on("close", () => { + let message = "Dido: rsPort closed - reconnecting ..."; + logger.debug(message); + monitor.info(message); + setTimeout(handleRsPort, 1000); + }) + + rsPort.open(); + } + + + function handleWebSocket() { + + if (ws) { + ws.removeAllListeners(); + ws = null; + } + + //to keep websocket opened, we send request every 150 seconds + let startRequests = null; + + console.log("handleWebSocket function called"); + ws = new WebSocket('ws:/0.0.0.0:1234/ws'); + + ws.onopen = function open() { + + instance.send(0, exports.title + " running"); + turnAlarm("off"); + + initialSetting(); + + setTimeout(function() { ws.send(JSON.stringify({ cmd: "all" })) }, 5000); + // we request dev info about neuron device from evok to keep websocket connection alive + // for some reason this request returns no data, but connection keeps alive + startRequests = setInterval(() => { + ws.send(JSON.stringify({ "cmd": "filter", "dev": ["neuron"] })); + }, 150000) + }; + + + // 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 = async 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; + + 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 => { + logger.debug('Dido: websocket error', err); + }) + + ws.onclose = function() { + logger.debug('Dido: websocket onclose, reconnecting...') + clearInterval(startRequests); + setTimeout(handleWebSocket, 1000); + } + } + + 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 turnAlarm(onOrOff) { + let value = 0; + if (onOrOff == "on") value = 1; + + if (value == 1 && SETTINGS.maintenance_mode) return; + + alarmStatus = "OFF"; + if (value == 1) alarmStatus = "ON"; + + if (rsPort) { + let arr = [0x55]; + arr.push(13); + arr.push(0); + arr.push(value); + + rsPort.write(Buffer.from(arr), function(err) { + logger.debug(`sirena - ${onOrOff}`); + }); + } + else if (ws) { + let cmd = { "cmd": "set", "dev": "relay", "circuit": "1_01", "value": value }; + ws.send(JSON.stringify(cmd)); + logger.debug(`sirena - ${onOrOff}`); + } + } + + + 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") { + bits.push(0); + } + else bits.push(1); + + if (deviceStatus["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); + } + + + // turn line on or off + function turnLine(onOrOff, line, pin, force, info) { + //onOrOff => "on" or "off" + let value = 0; + if (onOrOff == "on") value = 1; + + if (force == undefined) force = false; + + if (line == 0) { + if (value == 1 && alarmStatus == "ON") turnAlarm("off"); + SETTINGS.maintenance_mode = value ? true : false; + + 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); + return; + } + + if (pin === undefined) pin = getPin(line); + + if (pin === undefined) { + errLogger.error("pin is undefined!", line); + return; + } + + if (!force) { + if (relaysData[line].contactor == value) { + instance.send(SEND_TO.debug, `line is already ${onOrOff} ` + line); + logger.debug(`Dido: turnLine: line is already ${onOrOff} `, line); + return; + } + } + + // if(!rsPort.isOpen && !ws) + if (!rsPort && !ws) { + errLogger.error("Dido - port or websocket is not opened"); + return; + } + + if (rsPort) { + let arr = [0x55]; + arr.push(pin); + arr.push(0); + arr.push(value); + + rsPort.write(Buffer.from(arr), function(err) { + if (err === undefined) { + monitor.info(`Dido: turnLine ${onOrOff} zapisal do rsPort-u`, line, pin, arr, info); + switchLogic(arr); + } + else { + monitor.info(`Dido: turnLine ${onOrOff} WRITE error`, err); + } + }); + + } + else if (ws) { + //pin = "relay1_03" or "input1_01" ... we must make just "1_01" with slice method + monitor.info(`Dido: turnLine ${onOrOff} - (line, pin, force)`, line, pin, force, info); + let cmd = { "cmd": "set", "dev": "relay", "circuit": pin.slice(5), "value": value }; + ws.send(JSON.stringify(cmd)); + } + + //if rvo is 24/7, it has just one switching profile point at 13:00. we do not want to send notification as it repeats every day. + //const d = new Date(); + //if(d.getHours() != 13) sendNotification("Dido_controller: ", SETTINGS.rvoTbName, "switching_profile_point_applied_to_line", { line: line, value: onOrOff }, "", SEND_TO.tb, instance); + } + + + // 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; + + // 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) { + const status = flowdata.data.status; + if (status == "NOK-twilight_sensor") { + deviceStatus["twilight_sensor"] = "NOK"; + } + else if (status == "NOK-em340" || status == "NOK-em111") { + deviceStatus["em"] = "NOK"; + } + else if (status == "NOK-thermometer") { + deviceStatus["temperature"] = "NOK"; + } + } + else if ("values" in flowdata.data) { + 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" + } + else if (values.hasOwnProperty("temperature")) { + deviceStatus["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"; + } + + sendTelemetry(values, rvoTbName); + } + + sendRvoStatus(); + }) + + + + + // we expect array as flowdata.data + instance.on("1", flowdata => { + + //console.log(flowdata.data); + + if (!flowdata.data instanceof Object) return; + + let obj = flowdata.data; + let line = obj.line; + 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"); + }) + + + function calculateStateCode() { + + let bits = []; + + //Hlavny istic - state_of_main_switch => v rvo senica je to druhy door pre silovu cast (EM) + if (deviceStatus["state_of_main_switch"] === "closed" || deviceStatus["state_of_main_switch"] === "Off") { + bits.push(0); + } + else { + bits.push(1); + } + + //Prevadzkovy mod - Manual, Off, Automatic, maintenance_mode = true/false // DAVA 2 BITY + if (!SETTINGS.maintenance_mode) { + if (deviceStatus["rotary_switch_state"] === "Manual") { + bits.push(0); + bits.push(1); + } + + if (deviceStatus["rotary_switch_state"] === "Automatic") { + bits.push(0); + bits.push(0); + } + + if (deviceStatus["rotary_switch_state"] === "Off") { + bits.push(1); + bits.push(0); + } + } + else { + bits.push(1); + bits.push(1); + } + + //Dverovy kontakt + if (deviceStatus["door_condition"] === "closed") { + bits.push(0); + } + else { + bits.push(1); + } + + //EM + if (deviceStatus["em"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //Teplomer + if (deviceStatus["temperature"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //Batéria + if (deviceStatus["battery"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //Zdroj + if (deviceStatus["power_supply"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //MN + if (deviceStatus["master_node"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //výpadok napätia na fáze + if (deviceStatus["no_voltage"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + if (deviceStatus["twilight_sensor"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + // doplnime do 16 bitov (2 byty) + for (let i = bits.length; i < 16; i++) { + bits.push(0); + } + + // console.log("calculateStateCode - deviceStatus", deviceStatus); + // 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; + } + + + async function sendRvoStatus() { + + if (SETTINGS === undefined) return; + SETTINGS.masterNodeIsResponding ? deviceStatus["master_node"] = "OK" : deviceStatus["master_node"] = "NOK"; + + 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 pinsForRvoStatus(controllerType, hasMainSwitch) { + + let pins = []; + + if (controllerType === "lm") { + pins = [1, 4, 6]; + if (hasMainSwitch === 1) { + pins = [4, 6]; + } + } else if (controllerType === "unipi") { + pins = ["input1_01", "input1_04", "input1_05"]; + if (hasMainSwitch === 1) { + pins = ["input1_01", "input1_04"]; + } + } + + return pins; + } + + + function checkRvoStatus() { + + // 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 + //set RVO state + let status = "OK"; + + for (const [key, value] of Object.entries(deviceStatus)) { + if (["em", "twilight_sensor", "temperature", "master_node"].includes(key) && value === "NOK") status = "NOK"; + } + + if (status === "OK") { + + let pinIndexes = pinsForRvoStatus(controller_type, hasMainSwitch); + + for (const pinIndex of pinIndexes) { + if (previousValues[pinIndex] === 0) { + if ((pinIndex === 6 || pinIndex === 'input1_01' || pinIndex === 'input1_05') && SETTINGS.maintenance_mode) continue; + status = "NOK"; + break; + } + } + } + + // battery status. If value is 1 - battery is NOK + if (previousValues[5] === 1) status = "NOK"; + if (SETTINGS.no_voltage.size > 0) status = "NOK"; + + // console.log("rvo status",status) + return status; + } + + + // we pass array to function in case of rsPort ==> switchLogic([55,3,0,1]) ==> [[55,3,0,1]] + // we pass two values in case of websocket ==> switchLogic("relay1_03",1) ==> ["relay1_03",1] + const switchLogic = (...args) => { + + let values = {}; + let pinIndex, newPinValue, twilight; + + //data from rsPort + if (args.length == 1) { + pinIndex = args[0][1] + 1; + if (pinIndex === 17) pinIndex--; + newPinValue = args[0][3]; + twilight = args[0][2]; + } + //data from websocket + else { + pinIndex = args[0]; + newPinValue = args[1]; + } + + 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; + + //default value + let value = "On"; + if (newPinValue === 0) value = "Off"; + + //Hlavny istic + if (type === "state_of_main_switch" && hasMainSwitch) { + if (newPinValue === 0 && newPinValue !== previousValues[pinIndex]) { + sendNotification("switchLogic", rvoTbName, "main_switch_has_been_turned_off", {}, "", SEND_TO.tb, instance, "state_of_main_switch"); + 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"); + deviceStatus["state_of_main_switch"] = "On"; + } + } + + //Prevadzkovy mod + 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"; + + deviceStatus["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, "power_supply_has_disconnected_input", {}, "", SEND_TO.tb, instance, "power_supply"); + + deviceStatus["power_supply"] = "NOK"; + } + else if (newPinValue === 1 && newPinValue !== previousValues[pinIndex]) { + sendNotification("switchLogic", rvoTbName, "power_supply_works_correctly", {}, "", SEND_TO.tb, instance, "power_supply"); + + deviceStatus["power_supply"] = "OK"; + } + } + + //Bateria - 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"); + + deviceStatus["battery"] = "NOK"; + } + else if (newPinValue === 0 && newPinValue !== previousValues[pinIndex]) { + sendNotification("switchLogic", rvoTbName, "battery_level_is_ok", {}, "", SEND_TO.tb, instance, "battery_level"); + + deviceStatus["battery"] = "OK"; + } + } + + //Dverovy kontakt - pin 6 + //! Ak je rvo s dvoma dverovymi kontaktami, ked pride z evoku signal z input1_05, co bol predytm "state_of_main switch" handlujeme ho teraz ako 'door_condition' + else if (type == "door_condition" || type === "state_of_main_switch") { + newPinValue === 0 ? value = "open" : value = "closed"; + + let door = "door_main"; + if (type === "state_of_main_switch") door = "door_em"; + + if (value === "open") { + if (SETTINGS.maintenance_mode) { + sendNotification("switchLogic", rvoTbName, door + "_open", {}, "", SEND_TO.tb, instance, door); + } else { + sendNotification("switchLogic", rvoTbName, door + "_open_without_permission", {}, "", SEND_TO.tb, instance, door); + + // 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 (value === "closed") { + if (alarmStatus == "ON") turnAlarm("off"); + sendNotification("switchLogic", rvoTbName, door + "_close", {}, "", SEND_TO.tb, instance, door); + } + + deviceStatus[type] = value; + } + + //lux sensor + else if (type == "twilight_sensor") { + //! TODO - to show nok status, if lux value is not changing more then 10 times. + //Daylight is far more than 1000. So most of the day, when it is sunshine comes just value 1000. But lux sensor is not NOK. + //This is not the case in LM. If value from LM is the same 10x, there is 99% possibility, that sensor is NOK. + value = newPinValue; + + if (controller_type === 'lm') { + value = parseFloat(newPinValue + (256 * twilight)); + + 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 && !twilightError) { + twilightError = true; + let value = twilight_sensor_array.shift(); + + newPinValue = 0; + } + else if (set.size !== 1 && twilightError) { + //sendNotification("switchLogic", rvoTbName, 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) { + 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); + } + } + + 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); + } + + deviceStatus["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 (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 }); + + //mame iba 3 istice. vyreportujeme a ohandlujeme liniu na tom istom istici ako paralelna linia (napr linia 1, paralelna s nou je linia 4, key je string "4") + // ak je 7 linii, na 1 istici je linia 1,4,7 + + if (line == 1) { + + const lineOnSameBraker = [4, 7]; + + for (var i = 0; i < lineOnSameBraker.length; i++) { + if (!relaysData.hasOwnProperty(lineOnSameBraker[i])) continue; + + 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; + reportLineStatus(lineOnSameBraker[i]); + + values[type] = value; + const tbname = relaysData[lineOnSameBraker[i]].tbname; + sendTelemetry(values, tbname); + + delete values[type]; + } + + } + else { + const lineOnSameBraker = line + 3 + ""; + + if (relaysData.hasOwnProperty(lineOnSameBraker)) { + 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; + reportLineStatus(line + 3); + + values[type] = value; + const tbname = relaysData[lineOnSameBraker].tbname; + sendTelemetry(values, tbname); + + delete values[type]; + } + } + + } + + if (value == "Off") values["status"] = "NOK"; + deviceStatus["state_of_breaker"][line] = value; + + reportLineStatus(line); + } + else return; + + values[type] = value; + + if (type == "rotary_switch_state") { + if (SETTINGS.maintenance_mode) value = "maintenance"; + value = value.toLowerCase(); + values["power_mode"] = value; + } + + if (newPinValue != previousValues[pinIndex]) previousValues[pinIndex] = newPinValue; + if (Object.keys(values).length > 0 && tbname) sendTelemetry(values, tbname); + } + + + function sendTelemetry(values, tbname, date = Date.now()) { + let dataToTb = { + [tbname]: [ + { + "ts": date, + "values": values + } + ] + }; + + tbHandler.sendToTb(dataToTb, instance); + } + + + function isObject(item) { + return (typeof item === "object" && !Array.isArray(item) && item !== null); + } + +} //end of 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 +// *|input1_01|state_of_main_switch|0|........... +// *|input1_02|rotary_switch_state|0|........... +// *|input1_03|rotary_switch_state|0|........... +// *|intut1_04|power_supply|0|........... +// *|input1_05|door_condition|0|........... +// *|input1_06|state_of_breaker|1|........... +// *|input1_07|state_of_breaker|2|........... +// *|input1_08|state_of_breaker|3|........... +// *|relay1_02|state_of_contactor|1|........... +// *|relay1_03|state_of_contactor|2|........... +// *|relay1_04|state_of_contactor|3|........... +// *|287D8776E0013CE9|temperature|0|........... + + +//! pins_data --> from UNIPI +// { +// 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 } +// } + +//! relays_data +// { +// '0': { +// line: 0, +// tbname: 'KjbN4q7JPZmexgdnz2yKQ98YAWwO0Q3BMX6ERLoV', +// contactor: 1, +// profile: '' +// }, +// '1': { +// line: 1, +// tbname: 'RMgnK93rkoAazbqdQ4yBG95Z1YXGx6pmwBeVEP2O', +// contactor: 0, +// profile: '{"intervals":[{"value":0,"end_time":"20:00","start_time":"13:00"},{"value":1,"end_time":"10:00","start_time":"20:00"},{"value":0,"end_time":"10:20","start_time":"10:00"},{"value":1,"end_time":"10:40","start_time":"10:20"},{"value":0,"end_time":"11:00","start_time":"10:40"},{"value":1,"end_time":"11:30","start_time":"11:00"},{"value":0,"end_time":"11:50","start_time":"11:30"},{"value":1,"end_time":"13:00","start_time":"11:50"}],"astro_clock":false,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' +// }, +// '2': { +// line: 2, +// tbname: 'dlE1VQjYrNx9gZRmb38gG08oLBO4qaAk2M6JPnG7', +// contactor: 0, +// profile: '{"intervals":[{"value":0,"end_time":"20:00","start_time":"13:00"},{"value":1,"end_time":"10:00","start_time":"20:00"},{"value":0,"end_time":"10:20","start_time":"10:00"},{"value":1,"end_time":"10:40","start_time":"10:20"},{"value":0,"end_time":"11:00","start_time":"10:40"},{"value":1,"end_time":"11:30","start_time":"11:00"},{"value":0,"end_time":"11:50","start_time":"11:30"},{"value":1,"end_time":"13:00","start_time":"11:50"}],"astro_clock":false,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' +// }, +// '3': { +// line: 3, +// tbname: 'vnmG4kJxaXWNBgMQq0D7Aj5e9oZzOAlr6LdR3w2V', +// contactor: 0, +// profile: '{"intervals":[{"value":0,"end_time":"20:30","start_time":"13:00"},{"value":1,"end_time":"00:10","start_time":"20:30"},{"value":0,"end_time":"13:00","start_time":"05:40"},{"value":1,"end_time":"05:40","start_time":"00:10"}],"astro_clock":true,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' +// } +// } + + + + + +// { +// "jbN4q7JPZmexgdnz2yKbWGDYAWwO0Q3BMX6ERLoV": [ +// { +// "ts": 1700409326353, +// "values": { +// "_event": { +// "type": "notice", +// "status": "new", +// "source": { +// "func": "rsPort.open()", +// "component": "1700343402190", +// "component_name": "DIDO_Controller", +// "edge": "jbN4q7JPZmexgdnz2yKbWGDYAWwO0Q3BMX6ERLoV" +// }, +// "message": "al_shariff_10.0.0.38: FLOW has been started ", +// "message_data": "" +// } +// } +// } +// ] +// } diff --git a/RVO12/flow/helper/DataToTbHandler.js b/RVO12/flow/helper/DataToTbHandler.js new file mode 100755 index 0000000..716ef7b --- /dev/null +++ b/RVO12/flow/helper/DataToTbHandler.js @@ -0,0 +1,187 @@ +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; + this.itIsNodeReadout = false; + this.sender = ""; + + // if attribute change difference is less than limit value, we do not send to tb. + this.attributeChangeLimit = { + temperature: 0.5, + Phase_1_voltage: 2, + Phase_2_voltage: 2, + Phase_3_voltage: 2, + Phase_1_current: 0.1, + Phase_2_current: 0.1, + Phase_3_current: 0.1, + Phase_1_power: 2, + Phase_2_power: 2, + Phase_3_power: 2, + total_power: 2, + total_energy: 1, + Phase_1_pow_factor: 0.1, + Phase_2_pow_factor: 0.1, + Phase_3_pow_factor: 0.1, + power_factor: 0.1, + lifetime: 2, + voltage: 2, + power: 2, + frequency: 3, + energy: 0.1, + current: 2, + inclination_x: 10, + inclination_y: 10, + inclination_z: 10 + }; + + } + + dump() { + console.log("----------------------------"); + console.log("previousValues", this.previousValues); + console.log("----------------------------"); + } + + setSender(sender) { + this.sender = sender; + } + + isEmptyObject(obj) { + for (var _ in obj) { + return false; + } + return true; + } + + + sendToTb(data, instance) { + + //not to modify data object, we do deep copy: + let dataCopy = JSON.parse(JSON.stringify(data)); + + let keys = Object.keys(dataCopy); + + if (keys.length == 0) { + if (this.debug) console.log("sendToTb received empty object", dataCopy); + return; + } + + let tbname = keys[0]; + let ts; + + let arrayOfValues = dataCopy[tbname]; + let arrayOfValuesToSend = []; + + for (let i = 0; i < arrayOfValues.length; i++) { + + ts = arrayOfValues[i].ts; + let values = this.prepareValuesForTb(tbname, ts, arrayOfValues[i].values); + + if (!this.isEmptyObject(values)) { + arrayOfValuesToSend.push({ ts: ts, values: values }); + } + + } + + if (arrayOfValuesToSend.length == 0) { + //if(this.debug) console.log("data not sent - empty array"); + return; + } + + this.messageCounter++; + + let dataToTbModified = { + [tbname]: arrayOfValuesToSend + } + + //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); + instance.send(this.index, dataToTbModified); + } + + + getDiffTimestamp(key) { + //TODO set different value for given key!!! + //if(key == "status") this.timeToHoldTbValue = 2*60*60;//2h + return this.timeToHoldTbValue * 1000; + } + + + prepareValuesForTb(tbname, timestamp, values) { + + let keys = Object.keys(values); + + if (keys.includes("lifetime")) this.itIsNodeReadout = true; + + if (!this.previousValues.hasOwnProperty(tbname)) { + this.previousValues[tbname] = {}; + } + + //if(this.debug) console.log("prepareValuesForTb", tbname, timestamp, values); + + for (let i = 0; i < keys.length; i++) { + + let key = keys[i]; + let value = values[key]; + + if (!this.previousValues[tbname].hasOwnProperty(key)) { + this.previousValues[tbname][key] = { ts: timestamp, value: value }; + continue; + } + + // attributeData ==> {voltage: {ts:333333, value:5}} + let attributeData = this.previousValues[tbname][key]; + let attributeToChange = false; + if (key in this.attributeChangeLimit) attributeToChange = true; + let limit = this.attributeChangeLimit[key]; + let timestampDiffToRemoveKey; + + //this will ensure "node statecode" will be sent just once an hour + if (this.itIsNodeReadout && key === "statecode") { + attributeData.value = value; + this.itIsNodeReadout = false; + timestampDiffToRemoveKey = 1 * 60 * 60 * 1000; // 1 hour + } + + if (key === "twilight_sensor" && value > 100) { + attributeData.value = value; + } + + //if edge, master or node version do not change, send just once a day: + if (["edge_fw_version", "master_node_version", "fw_version"].includes(key)) { + timestampDiffToRemoveKey = 24 * 60 * 60 * 1000; + } + + if (attributeData.value === value || attributeToChange && Math.abs(attributeData.value - value) < limit) { + + let diff = timestamp - attributeData.ts; + if (!timestampDiffToRemoveKey) timestampDiffToRemoveKey = this.getDiffTimestamp(key); + + if (diff > timestampDiffToRemoveKey) { + attributeData.ts = Date.now(); + //if(this.debug) console.log(this.sender + ": update ts for key", key, "diff is", diff, "messageCounter", this.messageCounter); + } + else { + delete values[key]; + //if(this.debug) console.log(this.sender + ": delete key", key, "diff is", diff, "messageCounter", this.messageCounter, timestampDiffToRemoveKey); + } + } + else { + attributeData.value = value; + attributeData.ts = timestamp; + } + + } + + return values; + } +} + +module.exports = DataToTbHandler; + diff --git a/RVO12/flow/helper/ErrorToServiceHandler.js b/RVO12/flow/helper/ErrorToServiceHandler.js new file mode 100755 index 0000000..2b27c32 --- /dev/null +++ b/RVO12/flow/helper/ErrorToServiceHandler.js @@ -0,0 +1,91 @@ +const { MD5 } = require('./md5.js'); +const { networkInterfaces } = require('os'); + +class ErrorToServiceHandler { + constructor() { + this.previousValues = {}; + + this.project_id = undefined; + + const nets = networkInterfaces(); + this.ipAddresses = {}; + + for (const name of Object.keys(nets)) { + for (const net of nets[name]) { + // Skip over non-IPv4 and internal (i.e. 127.0.0.1) addresses + if (net.family === 'IPv4' && !net.internal) { + if (!this.ipAddresses[name]) { + this.ipAddresses[name] = []; + } + this.ipAddresses[name].push(net.address); + } + } + } + } + + setProjectId(project_id) { + this.project_id = project_id; + } + + processMessage(message, seconds) { + if (Array.isArray(message)) message = message.join(', '); + + let key = MD5(message); + let ts = Date.now(); + + //keep in memory - default value is 1h + if (seconds === undefined) seconds = 60 * 60; + + if (!this.previousValues.hasOwnProperty(key)) { + this.previousValues[key] = { ts: ts, duration: seconds }; + } + + let diff = (ts - this.previousValues[key].ts); + if (diff < this.previousValues[key].duration * 1000) return false; + + this.previousValues[key].ts = ts; + + return message; + } + + sendMessageToService(message, seconds, message_type) { + + // if error occures too early FLOW.GLOBALS.settings.project_id is still undefined + if (this.project_id === undefined) { + console.log("ErrorToServiceHandler.js: no project_id"); + return; + } + + let f = this.processMessage(message, seconds); + if (f === false) return; + + if (message_type === undefined) message_type = "error_message"; + + let toService = { + id: this.project_id, + ipAddresses: this.ipAddresses + }; + + //js_error || error_message + toService[message_type] = message; + + console.log("ErrorToServiceHandler------------------------>send to service", toService); + + RESTBuilder.make(function(builder) { + builder.method('POST'); + builder.post(toService); + builder.url('http://192.168.252.2:8004/sentmessage'); + + builder.callback(function(err, response, output) { + console.log("process.on error send", err, response, output, toService); + }); + }); + + } +} + +const errorHandler = new ErrorToServiceHandler(); + + +module.exports = errorHandler; +//module.exports = ErrorToServiceHandler; diff --git a/RVO12/flow/helper/db_helper.js b/RVO12/flow/helper/db_helper.js new file mode 100755 index 0000000..40e796c --- /dev/null +++ b/RVO12/flow/helper/db_helper.js @@ -0,0 +1,44 @@ +function promisifyBuilder(builder) +{ + return new Promise((resolve, reject) => { + + try{ + + builder.callback(function(err, response) { + + if(err != null) reject(err); + resolve(response); + }); + + } catch (error) { + reject(error); + } + }) +} + +function makeMapFromDbResult(response, ...keys) +{ + let s = "-"; + let data = {}; + + for(let i = 0; i < response.length; i++) + { + let record = response[i]; + + let k = []; + for(let j = 0; j < keys.length; j++) + { + k.push( record[keys[j]] ); + } + + let key = k.join(s); + data[ key ] = record; + } + + return data; +} + +module.exports = { + promisifyBuilder, + makeMapFromDbResult + } \ No newline at end of file diff --git a/RVO12/flow/helper/logger.js b/RVO12/flow/helper/logger.js new file mode 100755 index 0000000..2585639 --- /dev/null +++ b/RVO12/flow/helper/logger.js @@ -0,0 +1,30 @@ +//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/RVO12/flow/helper/md5.js b/RVO12/flow/helper/md5.js new file mode 100755 index 0000000..d3b0480 --- /dev/null +++ b/RVO12/flow/helper/md5.js @@ -0,0 +1,5 @@ +function MD5(d){var r = M(V(Y(X(d),8*d.length)));return r.toLowerCase()};function M(d){for(var _,m="0123456789ABCDEF",f="",r=0;r>>4&15)+m.charAt(15&_);return f}function X(d){for(var _=Array(d.length>>2),m=0;m<_.length;m++)_[m]=0;for(m=0;m<8*d.length;m+=8)_[m>>5]|=(255&d.charCodeAt(m/8))<>5]>>>m%32&255);return _}function Y(d,_){d[_>>5]|=128<<_%32,d[14+(_+64>>>9<<4)]=_;for(var m=1732584193,f=-271733879,r=-1732584194,i=271733878,n=0;n>16)+(_>>16)+(m>>16)<<16|65535&m}function bit_rol(d,_){return d<<_|d>>>32-_} + +module.exports = { + MD5 +} \ No newline at end of file diff --git a/RVO12/flow/helper/notification_reporter.js b/RVO12/flow/helper/notification_reporter.js new file mode 100755 index 0000000..839c12c --- /dev/null +++ b/RVO12/flow/helper/notification_reporter.js @@ -0,0 +1,121 @@ +//key is device, value = message {} +let sentValues = {}; +let notificationsData = null; +let rvoName; + +//sendNotification("CMD Manager: process cmd", SETTINGS.rvoTbName, "dimming_profile_was_successfully_received_by_node", { node: node }, "", SEND_TO.tb, instance); + +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 +}; + +function getKey(map, val) { + return Object.keys(map).findItem(key => map[key] === val); +} + +//https://stackoverflow.com/questions/41117799/string-interpolation-on-variable +var template = (tpl, args) => tpl.replace(/\${(\w+)}/g, (_, v) => args[v]); + + +function initNotification() { + notificationsData = FLOW.GLOBALS.notificationsData; + rvoName = FLOW.GLOBALS.settings.rvo_name; +} + + +function sendNotification(func, device, key, params, extra, tb_output, instance, saveKey) { + + let storeToSendValues = true; + if (saveKey == undefined) storeToSendValues = false; + + let weight = ""; + let message = {}; + + let notification = notificationsData[key]; + + if (notification) { + weight = notification.weight.toLowerCase(); + + Object.keys(notification).forEach(item => { + if (["en", "sk", "de", "cz", "it", "es"].includes(item)) { + message[item] = rvoName + ": " + template(notification[item], params); + } + }) + } + else { + //console.error("sendNotification: Notifications: undefined key", key, func, notificationsData); + console.error("sendNotification: Notifications: undefined key", key, func); + return false; + } + + //detect invalid err weight + if (getKey(ERRWEIGHT, weight) == undefined) { + console.error("sendNotification: Notifications: undefined weight", weight, key, func); + return false; + } + + if (sentValues.hasOwnProperty(saveKey)) { + if (JSON.stringify(sentValues[saveKey]) == JSON.stringify(message)) { + return false; + } + } + + if (sentValues[saveKey] == undefined) { + if (storeToSendValues) { + //do not send - flow is was started + sentValues[saveKey] = message; + return false; + } + } + + if (storeToSendValues) sentValues[saveKey] = message; + + let content = { + "type": weight, + "status": "new", + "source": { + "func": func, + "component": instance.id, + "component_name": instance.name, + "edge": device + }, + "message": message, + "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 + + return true; + +} + +module.exports = { + sendNotification, + ERRWEIGHT, + initNotification +} + diff --git a/RVO12/flow/helper/register.js b/RVO12/flow/helper/register.js new file mode 100755 index 0000000..fc1d008 --- /dev/null +++ b/RVO12/flow/helper/register.js @@ -0,0 +1,144 @@ +/* +0 - cislo registra / prikaz +1 - recepient - 0 = master, 1 = slave (slave je automaticky group a broadcast) +2 - r/rw - read/write +3- register name - nazov registra / prikazu (len pre info - zobrazenie v aplikacii) + +4,5,6,7, - jednotlive byte-y - nazov byte-u +4-7 - RES. a prazdny string "" sa nezobrazia!!! +*/ + +//124 zaznamov +const registers = [ + ["0","1","R","Status","","",""], + ["1","1","RW","Dimming","R-Channel ","G-Channel","B-Channel ","W - Channel"], + ["2","1","R","Device types","","",".",""], + ["3","1","RW","Group addresses 1-4","Groups Add. 4","Groups Add. 3","Groups Add. 2","Groups Add. 1"], + ["4","1","RW","Group addresses 5-8","Groups Add. 8","Groups Add. 7","Groups Add. 6","Groups Add. 5"], + ["5","1","RW","Serial number (MAC)","","","",""], + ["6","1","RW","Time of dusk","HH","MM","SS","EXTRA"], + ["7","1","RW","Time of dawn","HH","MM","SS","EXTRA"], + ["8","1","RW","Time Schedule settings","TBD","TBD","Movement sensor","Time Schedule"], + ["9","1","RW","TS1 Time point 1","HH","MM","SS","Ext. Device"], + ["10","1","RW","TS1 Time point 1 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["11","1","RW","TS1 Time point 2","HH","MM","SS","Ext. Device"], + ["12","1","RW","TS1 Time point 2 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["13","1","RW","TS1 Time point 3","HH","MM","SS","Ext. Device"], + ["14","1","RW","TS1 Time point 3 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["15","1","RW","TS1 Time point 4","HH","MM","SS","Ext. Device"], + ["16","1","RW","TS1 Time point 4 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["17","1","RW","TS1 Time point 5","HH","MM","SS","Ext. Device"], + ["18","1","RW","TS1 Time point 5 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["19","1","RW","TS1 Time point 6","HH","MM","SS","Ext. Device"], + ["20","1","RW","TS1 Time point 6 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["21","1","RW","TS1 Time point 7","HH","MM","SS","Ext. Device"], + ["22","1","RW","TS1 Time point 7 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["23","1","RW","TS1 Time point 8","HH","MM","SS","Ext. Device"], + ["24","1","RW","TS1 Time point 8 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["25","1","RW","TS1 Time point 9","HH","MM","SS","Ext. Device"], + ["26","1","RW","TS1 Time point 9 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["27","1","RW","TS1 Time point 10","HH","MM","SS","Ext. Device"], + ["28","1","RW","TS1 Time point 10 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["29","1","RW","TS1 Time point 11","HH","MM","SS","Ext. Device"], + ["30","1","RW","TS1 Time point 11 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["31","1","RW","TS1 Time point 12","HH","MM","SS","Ext. Device"], + ["32","1","RW","TS1 Time point 12 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["33","1","RW","TS1 Time point 13","HH","MM","SS","Ext. Device"], + ["34","1","RW","TS1 Time point 13 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["35","1","RW","TS1 Time point 14","HH","MM","SS","Ext. Device"], + ["36","1","RW","TS1 Time point 14 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["37","1","RW","TS1 Time point 15","HH","MM","SS","Ext. Device"], + ["38","1","RW","TS1 Time point 15 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["39","1","RW","TS1 Time point 16","HH","MM","SS","Ext. Device"], + ["40","1","RW","TS1 Time point 16 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["41","1","RW","TS2 Time point 1","HH","MM","SS","Ext. Device"], + ["42","1","RW","TS2 Time point 1 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["43","1","RW","TS2 Time point 2","HH","MM","SS","Ext. Device"], + ["44","1","RW","TS2 Time point 2 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["45","1","RW","TS2 Time point 3","HH","MM","SS","Ext. Device"], + ["46","1","RW","TS2 Time point 3 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["47","1","RW","TS2 Time point 4","HH","MM","SS","Ext. Device"], + ["48","1","RW","TS2 Time point 4 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["49","1","RW","TS2 Time point 5","HH","MM","SS","Ext. Device"], + ["50","1","RW","TS2 Time point 5 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["51","1","RW","TS2 Time point 6","HH","MM","SS","Ext. Device"], + ["52","1","RW","TS2 Time point 6 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["53","1","RW","TS2 Time point 7","HH","MM","SS","Ext. Device"], + ["54","1","RW","TS2 Time point 7 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["55","1","RW","TS2 Time point 8","HH","MM","SS","Ext. Device"], + ["56","1","RW","TS2 Time point 8 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["57","1","RW","TS2 Time point 9","HH","MM","SS","Ext. Device"], + ["58","1","RW","TS2 Time point 9 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["59","1","RW","TS2 Time point 10","HH","MM","SS","Ext. Device"], + ["60","1","RW","TS2 Time point 10 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["61","1","RW","TS2 Time point 11","HH","MM","SS","Ext. Device"], + ["62","1","RW","TS2 Time point 11 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["63","1","RW","TS2 Time point 12","HH","MM","SS","Ext. Device"], + ["64","1","RW","TS2 Time point 12 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["65","1","RW","TS2 Time point 13","HH","MM","SS","Ext. Device"], + ["66","1","RW","TS2 Time point 13 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["67","1","RW","TS2 Time point 14","HH","MM","SS","Ext. Device"], + ["68","1","RW","TS2 Time point 14 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["69","1","RW","TS2 Time point 15","HH","MM","SS","Ext. Device"], + ["70","1","RW","TS2 Time point 15 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["71","1","RW","TS2 Time point 16","HH","MM","SS","Ext. Device"], + ["72","1","RW","TS2 Time point 16 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["73","1","RW","Power meter status","TBD","","",""], + ["74","1","R","Input Voltage","","","",""], + ["75","1","R","Input Current","","","",""], + ["76","1","R","Input Power","","","",""], + ["77","1","R","Cos phi","","","",""], + ["78","1","R","Frequency","","","",""], + ["79","1","RW","Energy","","","",""], + ["80","1","RW","Lifetime","","","",""], + ["81","1","RW","Power on cycles (input)","","","",""], + ["82","1","RW","Power on cycles (relay)","","","",""], + ["83","1","R","Time since last power on","","","",""], + ["84","1","R","Accelerometer data","","","",""], + ["85","1","RW","GPS latitude","pos/neg","deg","min ","sec"], + ["86","1","RW","GPS longitude","pos/neg","deg","min ","sec"], + ["87","1","RW","Actual time","HH","MM","SS","RES."], + ["88","1","RW","Actual date","Day of week","Day","Month","Year"], + ["89","1","R","Production data 1","","","",""], + ["90","1","R","Production data 2","","","",""], + ["91","1","RW","Network ID","NID3","NID2","NID1","NID0"], + ["95","1","RW","Actual Lux level from cabinet","RES.","RES.","HB","LB"], + ["96","1","RW","Threshold lux level","Dusk HB","Dusk LB","Dawn HB","Dawn LB"], + ["97","1","RW","Adjust period","Dusk HB","Dusk LB","Dawn HB","Dawn LB"], + ["98","1","RW","Offset","RES.","RES.","Dusk","Dawn"], + ["99","1","RW","CCT min/max range","max-H","max-L","min-H","min-L"], + ["100","1","RW","DALI interface","Cmd ID","Add","Cmd","Resp"], + ["101","1","RW","Module FW ver","v1","v2","v3","v4"], + ["102","1","RW","Module MAC-H","unused","unused","M1","M2"], + ["103","1","RW","Module MAC-L","M3","M4","M5","M6"], + ["122","1","R","FW update status/control register","Byte3","Byte2","Byte1","Byte0"], + ["123","1","R","FW update - data index","Byte3","Byte2","Byte1","Byte0"], + ["124","1","R","FW update - data","Byte3","Byte2","Byte1","Byte0"], + ["0","0","R","Status","","","",""], + ["1","0","RW","Control register","RES.","RES.","RES.","init mode enable"], + ["2","0","R","Device types","","","",""], + ["3","0","R","Serial number (MAC)","","","",""], + ["4","0","R","Production data 1","","","",""], + ["5","0","R","Production data 2","","","",""], + ["6","0","RW","Network ID","NID3","NID2","NID1","NID0"], + ["7","0","RW","RS232 settings","param.","param.","Baudrate H","Baudrate L"], + ["8","0","R","Accelerometer data","","","",""], + ["9","0","RW","Module FW ver","v1","v2","v3","v4"], + ["10","0","RW","Module MAC-H","unused","unused","M1","M2"], + ["11","0","RW","Module MAC-L","M3","M4","M5","M6"], + ["32","0","RW","FW update status/control register","Byte3","Byte2","Byte1","Byte0"], + ["33","0","RW","FW update - data index","Byte3","Byte2","Byte1","Byte0"], + ["34","0","RW","FW update - data","Byte3","Byte2","Byte1","Byte0"], + ["125","0","RW","Debug Register","Byte3","Byte2","Byte1","Byte0"], + ["126","0","RW","Network Control Register","Byte3","Byte2","Byte1","Byte0"], + ["127","0","R","Network Status Register","Byte3","Byte2","Byte1","Byte0"], + ["128","0","RW","Node XX Serial Number Register","SER3","SER2","SER1","SER0"], + ["256","0","R","Node XX Network Status Register","","","",""] +]; + +let register = {}; + +module.exports = { + registers, + register +} \ No newline at end of file diff --git a/RVO12/flow/helper/serialport_helper.js b/RVO12/flow/helper/serialport_helper.js new file mode 100755 index 0000000..7f5920d --- /dev/null +++ b/RVO12/flow/helper/serialport_helper.js @@ -0,0 +1,99 @@ +const { exec } = require('child_process'); + +function openPort(port) { + return new Promise((resolve, reject) => { + + var callbackError = function(err) { + port.removeListener('error', callbackError); + port.removeListener('open', callbackError); + + reject(err.message); + }; + + var callbackOpen = function(data) { + port.removeListener('error', callbackError); + port.removeListener('open', callbackOpen); + + resolve("port open: ok"); + }; + + port.on('error', callbackError); + port.on('open', callbackOpen); + + port.open(); + + }) +} + +function runSyncExec(command) { + return new Promise((resolve, reject) => { + + exec(command, (error, stdout, stderr) => { + if (error == null) resolve(stdout); + reject(error); + }); + + }) +} + +async function writeData(port, data, readbytes, timeout) { + return new Promise((resolve, reject) => { + + // 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) { + + port.write(Buffer.from(data), function(err) { + if (err) { + reject(err.message); + } + }); + + 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 +} diff --git a/RVO12/flow/helper/suncalc.js b/RVO12/flow/helper/suncalc.js new file mode 100755 index 0000000..c9ca56d --- /dev/null +++ b/RVO12/flow/helper/suncalc.js @@ -0,0 +1,317 @@ +/* + (c) 2011-2015, Vladimir Agafonkin + SunCalc is a JavaScript library for calculating sun/moon position and light phases. + https://github.com/mourner/suncalc +*/ + +(function () { 'use strict'; + +// shortcuts for easier to read formulas + +var PI = Math.PI, + sin = Math.sin, + cos = Math.cos, + tan = Math.tan, + asin = Math.asin, + atan = Math.atan2, + acos = Math.acos, + rad = PI / 180; + +// sun calculations are based on http://aa.quae.nl/en/reken/zonpositie.html formulas + + +// date/time constants and conversions + +var dayMs = 1000 * 60 * 60 * 24, + J1970 = 2440588, + J2000 = 2451545; + +function toJulian(date) { return date.valueOf() / dayMs - 0.5 + J1970; } +function fromJulian(j) { return new Date((j + 0.5 - J1970) * dayMs); } +function toDays(date) { return toJulian(date) - J2000; } + + +// general calculations for position + +var e = rad * 23.4397; // obliquity of the Earth + +function rightAscension(l, b) { return atan(sin(l) * cos(e) - tan(b) * sin(e), cos(l)); } +function declination(l, b) { return asin(sin(b) * cos(e) + cos(b) * sin(e) * sin(l)); } + +function azimuth(H, phi, dec) { return atan(sin(H), cos(H) * sin(phi) - tan(dec) * cos(phi)); } +function altitude(H, phi, dec) { return asin(sin(phi) * sin(dec) + cos(phi) * cos(dec) * cos(H)); } + +function siderealTime(d, lw) { return rad * (280.16 + 360.9856235 * d) - lw; } + +function astroRefraction(h) { + if (h < 0) // the following formula works for positive altitudes only. + h = 0; // if h = -0.08901179 a div/0 would occur. + + // formula 16.4 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + // 1.02 / tan(h + 10.26 / (h + 5.10)) h in degrees, result in arc minutes -> converted to rad: + return 0.0002967 / Math.tan(h + 0.00312536 / (h + 0.08901179)); +} + +// general sun calculations + +function solarMeanAnomaly(d) { return rad * (357.5291 + 0.98560028 * d); } + +function eclipticLongitude(M) { + + var C = rad * (1.9148 * sin(M) + 0.02 * sin(2 * M) + 0.0003 * sin(3 * M)), // equation of center + P = rad * 102.9372; // perihelion of the Earth + + return M + C + P + PI; +} + +function sunCoords(d) { + + var M = solarMeanAnomaly(d), + L = eclipticLongitude(M); + + return { + dec: declination(L, 0), + ra: rightAscension(L, 0) + }; +} + + +var SunCalc = {}; + + +// calculates sun position for a given date and latitude/longitude + +SunCalc.getPosition = function (date, lat, lng) { + + var lw = rad * -lng, + phi = rad * lat, + d = toDays(date), + + c = sunCoords(d), + H = siderealTime(d, lw) - c.ra; + + return { + azimuth: azimuth(H, phi, c.dec), + altitude: altitude(H, phi, c.dec) + }; +}; + + +// sun times configuration (angle, morning name, evening name) + +var times = SunCalc.times = [ + [-0.833, 'sunrise', 'sunset' ], + [ -0.3, 'sunriseEnd', 'sunsetStart' ], + [ -6, 'dawn', 'dusk' ], + [ -12, 'nauticalDawn', 'nauticalDusk'], + [ -18, 'nightEnd', 'night' ], + [ 6, 'goldenHourEnd', 'goldenHour' ] +]; + +// adds a custom time to the times config + +SunCalc.addTime = function (angle, riseName, setName) { + times.push([angle, riseName, setName]); +}; + + +// calculations for sun times + +var J0 = 0.0009; + +function julianCycle(d, lw) { return Math.round(d - J0 - lw / (2 * PI)); } + +function approxTransit(Ht, lw, n) { return J0 + (Ht + lw) / (2 * PI) + n; } +function solarTransitJ(ds, M, L) { return J2000 + ds + 0.0053 * sin(M) - 0.0069 * sin(2 * L); } + +function hourAngle(h, phi, d) { return acos((sin(h) - sin(phi) * sin(d)) / (cos(phi) * cos(d))); } +function observerAngle(height) { return -2.076 * Math.sqrt(height) / 60; } + +// returns set time for the given sun altitude +function getSetJ(h, lw, phi, dec, n, M, L) { + + var w = hourAngle(h, phi, dec), + a = approxTransit(w, lw, n); + return solarTransitJ(a, M, L); +} + + +// calculates sun times for a given date, latitude/longitude, and, optionally, +// the observer height (in meters) relative to the horizon + +SunCalc.getTimes = function (date, lat, lng, height) { + + height = height || 0; + + var lw = rad * -lng, + phi = rad * lat, + + dh = observerAngle(height), + + d = toDays(date), + n = julianCycle(d, lw), + ds = approxTransit(0, lw, n), + + M = solarMeanAnomaly(ds), + L = eclipticLongitude(M), + dec = declination(L, 0), + + Jnoon = solarTransitJ(ds, M, L), + + i, len, time, h0, Jset, Jrise; + + + var result = { + solarNoon: fromJulian(Jnoon), + nadir: fromJulian(Jnoon - 0.5) + }; + + for (i = 0, len = times.length; i < len; i += 1) { + time = times[i]; + h0 = (time[0] + dh) * rad; + + Jset = getSetJ(h0, lw, phi, dec, n, M, L); + Jrise = Jnoon - (Jset - Jnoon); + + result[time[1]] = fromJulian(Jrise); + result[time[2]] = fromJulian(Jset); + } + + return result; +}; + + +// moon calculations, based on http://aa.quae.nl/en/reken/hemelpositie.html formulas + +function moonCoords(d) { // geocentric ecliptic coordinates of the moon + + var L = rad * (218.316 + 13.176396 * d), // ecliptic longitude + M = rad * (134.963 + 13.064993 * d), // mean anomaly + F = rad * (93.272 + 13.229350 * d), // mean distance + + l = L + rad * 6.289 * sin(M), // longitude + b = rad * 5.128 * sin(F), // latitude + dt = 385001 - 20905 * cos(M); // distance to the moon in km + + return { + ra: rightAscension(l, b), + dec: declination(l, b), + dist: dt + }; +} + +SunCalc.getMoonPosition = function (date, lat, lng) { + + var lw = rad * -lng, + phi = rad * lat, + d = toDays(date), + + c = moonCoords(d), + H = siderealTime(d, lw) - c.ra, + h = altitude(H, phi, c.dec), + // formula 14.1 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + pa = atan(sin(H), tan(phi) * cos(c.dec) - sin(c.dec) * cos(H)); + + h = h + astroRefraction(h); // altitude correction for refraction + + return { + azimuth: azimuth(H, phi, c.dec), + altitude: h, + distance: c.dist, + parallacticAngle: pa + }; +}; + + +// calculations for illumination parameters of the moon, +// based on http://idlastro.gsfc.nasa.gov/ftp/pro/astro/mphase.pro formulas and +// Chapter 48 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + +SunCalc.getMoonIllumination = function (date) { + + var d = toDays(date || new Date()), + s = sunCoords(d), + m = moonCoords(d), + + sdist = 149598000, // distance from Earth to Sun in km + + phi = acos(sin(s.dec) * sin(m.dec) + cos(s.dec) * cos(m.dec) * cos(s.ra - m.ra)), + inc = atan(sdist * sin(phi), m.dist - sdist * cos(phi)), + angle = atan(cos(s.dec) * sin(s.ra - m.ra), sin(s.dec) * cos(m.dec) - + cos(s.dec) * sin(m.dec) * cos(s.ra - m.ra)); + + return { + fraction: (1 + cos(inc)) / 2, + phase: 0.5 + 0.5 * inc * (angle < 0 ? -1 : 1) / Math.PI, + angle: angle + }; +}; + + +function hoursLater(date, h) { + return new Date(date.valueOf() + h * dayMs / 24); +} + +// calculations for moon rise/set times are based on http://www.stargazing.net/kepler/moonrise.html article + +SunCalc.getMoonTimes = function (date, lat, lng, inUTC) { + var t = new Date(date); + if (inUTC) t.setUTCHours(0, 0, 0, 0); + else t.setHours(0, 0, 0, 0); + + var hc = 0.133 * rad, + h0 = SunCalc.getMoonPosition(t, lat, lng).altitude - hc, + h1, h2, rise, set, a, b, xe, ye, d, roots, x1, x2, dx; + + // go in 2-hour chunks, each time seeing if a 3-point quadratic curve crosses zero (which means rise or set) + for (var i = 1; i <= 24; i += 2) { + h1 = SunCalc.getMoonPosition(hoursLater(t, i), lat, lng).altitude - hc; + h2 = SunCalc.getMoonPosition(hoursLater(t, i + 1), lat, lng).altitude - hc; + + a = (h0 + h2) / 2 - h1; + b = (h2 - h0) / 2; + xe = -b / (2 * a); + ye = (a * xe + b) * xe + h1; + d = b * b - 4 * a * h1; + roots = 0; + + if (d >= 0) { + dx = Math.sqrt(d) / (Math.abs(a) * 2); + x1 = xe - dx; + x2 = xe + dx; + if (Math.abs(x1) <= 1) roots++; + if (Math.abs(x2) <= 1) roots++; + if (x1 < -1) x1 = x2; + } + + if (roots === 1) { + if (h0 < 0) rise = i + x1; + else set = i + x1; + + } else if (roots === 2) { + rise = i + (ye < 0 ? x2 : x1); + set = i + (ye < 0 ? x1 : x2); + } + + if (rise && set) break; + + h0 = h2; + } + + var result = {}; + + if (rise) result.rise = hoursLater(t, rise); + if (set) result.set = hoursLater(t, set); + + if (!rise && !set) result[ye > 0 ? 'alwaysUp' : 'alwaysDown'] = true; + + return result; +}; + + +// export as Node module / AMD module / browser variable +if (typeof exports === 'object' && typeof module !== 'undefined') module.exports = SunCalc; +else if (typeof define === 'function' && define.amd) define(SunCalc); +else window.SunCalc = SunCalc; + +}()); diff --git a/RVO12/flow/helper/utils.js b/RVO12/flow/helper/utils.js new file mode 100755 index 0000000..dbffe45 --- /dev/null +++ b/RVO12/flow/helper/utils.js @@ -0,0 +1,161 @@ +const fs = require('fs').promises; + +function bytesToInt(bytes, numberOfBytes) { + let buffer = []; + if (Array.isArray(bytes)) { + buffer = bytes.slice(0); + if (numberOfBytes != undefined) { + buffer = bytes.slice(bytes.length - numberOfBytes); + } + } + else buffer.push(bytes); + + let result = 0; + for (let i = 0; i < buffer.length; i++) { + result = (result << 8) | buffer[i]; + } + + return result >>> 0; //ensure it's an unsigned 32-bit number +} + +function resizeArray(arr, newSize, defaultValue) { + while (newSize > arr.length) + arr.push(defaultValue); + arr.length = newSize; +} + +longToByteArray = function(/*long*/long) { + // we want to represent the input as a 8-bytes array + var byteArray = [0, 0, 0, 0, 0, 0, 0, 0]; + + for (var index = 0; index < byteArray.length; index++) { + var byte = long & 0xff; + byteArray[index] = byte; + long = (long - byte) / 256; + } + + return byteArray; +}; + +function addDays(date, days) { + var result = new Date(date); + result.setDate(result.getDate() + days); + return result; +} + +/* +sleep(2000).then(() => { + // Do something after the sleep! + + +}); +*/ + +function sleep(time) { + return new Promise((resolve) => setTimeout(resolve, time)); +} + +function isEmptyObject(obj) { + for (var name in obj) { + return false; + } + return true; +} + +function emptyJsObject(jsObject) { + Object.keys(jsObject).forEach(key => delete jsObject[key]); +} + +function convertUTCDateToLocalDate(date) { + var newDate = new Date(date); + newDate.setMinutes(date.getMinutes() + date.getTimezoneOffset()); + return newDate; +} + +function addZeroBefore(n) { + return (n < 10 ? '0' : '') + n; +} + + +/** + * Asynchronously writes data to a file. + * + * @param {string} filePath The path to the file. + * @param {string} data The data to write to the file. + * @param {boolean} [append=false] If true, appends the data to the file. If false, it overwrites the file. + */ +async function writeToFile(filePath, data, append = false) { + if (typeof data !== 'string') data = JSON.stringify(data, null, 2); + try { + if (append) { + // Append the data to the end of the file. This is the simplest way to append. + await fs.appendFile(filePath, data, 'utf8'); + console.log(`Successfully appended data to ${filePath} using fs.appendFile.`); + } else { + // Overwrite the file with the new data. + await fs.writeFile(filePath, data, 'utf8'); + console.log(`Successfully wrote (overwrote) data to ${filePath} using fs.writeFile.`); + } + } catch (error) { + console.error(`Error writing to file ${filePath}:`, error); + } +} + + + /** + * Checks if an item is present in an array and adds it if it's not. + * * @param {Array} arr The array to check. + * @param {*} item The item to add. + * @returns {Array} The modified array. + */ +const addToArrayIfUnique = (arr, item) => { + if (!arr.includes(item)) { + arr.push(item); + } + return arr; +}; + + +var convertBase = function() { + + function convertBase(baseFrom, baseTo) { + return function(num) { + return parseInt(num, baseFrom).toString(baseTo); + + }; + } + + // binary to decimal + convertBase.bin2dec = convertBase(2, 10); + + // binary to hexadecimal + convertBase.bin2hex = convertBase(2, 16); + + // decimal to binary + convertBase.dec2bin = convertBase(10, 2); + + // decimal to hexadecimal + convertBase.dec2hex = convertBase(10, 16); + + // hexadecimal to binary + convertBase.hex2bin = convertBase(16, 2); + + // hexadecimal to decimal + convertBase.hex2dec = convertBase(16, 10); + + return convertBase; +}(); + +module.exports = { + bytesToInt, + longToByteArray, + addDays, + addZeroBefore, + resizeArray, + isEmptyObject, + emptyJsObject, + sleep, + convertUTCDateToLocalDate, + writeToFile, + addToArrayIfUnique +} diff --git a/RVO12/flow/httprequest.js b/RVO12/flow/httprequest.js new file mode 100755 index 0000000..469c8cb --- /dev/null +++ b/RVO12/flow/httprequest.js @@ -0,0 +1,137 @@ +exports.id = 'httprequest'; +exports.title = 'HTTP Request'; +exports.group = 'HTTP'; +exports.color = '#5D9CEC'; +exports.input = true; +exports.version = '2.0.1'; +exports.output = 1; +exports.author = 'Peter Širka'; +exports.icon = 'cloud-upload'; + +exports.html = `
+
@(URL address)
+
+
+
@(HTTP method)
+
+
+
@(Serialization)
+
+
+
@(Download the content in chunks)
+
@(Keep persistent cookies)
+
@(Disable DNS cache)
+
@(Keep alive connection)
+
+
+
+
@(Custom headers)
+
@(Cookies)
+
+
+
+ +
+
+
+
@(User)
+
+
+
@(Password)
+
+
+
+
+
`; + +exports.readme = `# Request + +This component creates a request with received data. + +__Response:__ +\`\`\`javascript +{ + data: String, + headers: Object, + status: Number, + host: String +} +\`\`\` + +__Dynamic arguments__: +Are performed via FlowData repository and can be used for URL address or for custom headers/cookies/auth. Use \`repository\` component for creating of dynamic arguments. Dynamic values are replaced in the form \`{key}\`: + +- url address e.g. \`https://.../{key}/\` +- headers values e.g. \`{token}\` +- cookies values e.g. \`{token}\``; + +exports.install = function(instance) { + + var can = false; + var flags = null; + var cookies2 = null; + + instance.on('data', function(response) { + can && instance.custom.send(response); + }); + + instance.custom.send = function(response) { + var options = instance.options; + + var headers = null; + var cookies = null; + + options.headers && Object.keys(options.headers).forEach(function(key) { + !headers && (headers = {}); + headers[key] = response.arg(options.headers[key]); + }); + + if (options.username && options.userpassword) { + !headers && (headers = {}); + headers['Authorization'] = 'Basic ' + U.createBuffer(response.arg(options.username + ':' + options.userpassword)).toString('base64'); + } + + options.cookies && Object.keys(options.cookies).forEach(function(key) { + !cookies && (cookies = {}); + cookies[key] = response.arg(options.cookies[key]); + }); + + if (options.chunks) { + U.download(response.arg(options.url), flags, options.stringify === 'none' ? null : response.data, function(err, response) { + response.on('data', (chunks) => instance.send2(chunks)); + }, cookies || cookies2, headers); + } else { + U.request(response.arg(options.url), flags, options.stringify === 'none' ? null : response.data, 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) + instance.error(err, response); + }, cookies || cookies2, headers); + } + }; + + instance.reconfigure = function() { + var options = instance.options; + can = options.url && options.url && options.method && options.stringify ? true : false; + instance.status(can ? '' : 'Not configured', can ? undefined : 'red'); + + if (!can) + return; + + flags = []; + flags.push(options.method.toLowerCase()); + options.stringify === 'json' && flags.push('json'); + options.stringify === 'raw' && flags.push('raw'); + options.keepalive && flags.push('keepalive'); + !options.nodns && flags.push('dnscache'); + if (options.persistentcookies) { + flags.push('cookies'); + cookies2 = {}; + } else + cookies2 = null; + }; + + instance.on('options', instance.reconfigure); + instance.reconfigure(); +}; \ No newline at end of file diff --git a/RVO12/flow/httpresponse.js b/RVO12/flow/httpresponse.js new file mode 100755 index 0000000..160a3bb --- /dev/null +++ b/RVO12/flow/httpresponse.js @@ -0,0 +1,76 @@ +exports.id = 'httpresponse'; +exports.title = 'HTTP Response'; +exports.group = 'HTTP'; +exports.color = '#5D9CEC'; +exports.icon = 'arrow-right'; +exports.input = true; +exports.output = ['#666D76']; +exports.version = '2.0.0'; +exports.author = 'Martin Smola'; +exports.readme = `# HTTP response + +HTTP response will respond with data recieved using data-type set in Settings form or plain text if not set. Output is the message duration \`Number\` in seconds.`; + +exports.html = `
+
@(Response data-type)
+
JSON is by default.
+
`; + +exports.install = function(instance) { + + var dursum = 0; + var durcount = 0; + + instance.on('data', function(flowdata) { + + var ctrl = flowdata.repository.controller; + var data = flowdata.data; + + if (!ctrl) { + instance.throw('No controller to use for response!'); + return; + } + + durcount++; + dursum += ((new Date() - flowdata.begin) / 1000).floor(2); + setTimeout2(instance.id, instance.custom.duration, 500, 10); + + ctrl.$flowdata = flowdata; + + var datatype = instance.options.datatype || 'json'; + if (datatype === 'emptyresponse') + return ctrl.plain(''); + + if (datatype !== 'json' && typeof(data) !== 'string') { + instance.throw('Incorect type of data, expected string, got ' + typeof(data)); + ctrl.plain(data == null ? '' : data.toString()); + return; + } + + switch(datatype) { + case 'html': + ctrl.content(data, 'text/html'); + break; + case 'plain': + ctrl.plain(data); + break; + case 'xml': + ctrl.content(data, 'text/xml'); + break; + default: + ctrl.json(data); + break; + } + }); + + instance.on('service', function() { + dursum = 0; + durcount = 0; + }); + + instance.custom.duration = function() { + var avg = (dursum / durcount).floor(2); + instance.status(avg + ' sec.'); + instance.send2(0, avg); + }; +}; diff --git a/RVO12/flow/httproute.js b/RVO12/flow/httproute.js new file mode 100755 index 0000000..583a19d --- /dev/null +++ b/RVO12/flow/httproute.js @@ -0,0 +1,326 @@ +exports.id = 'httproute'; +exports.title = 'HTTP Route'; +exports.group = 'HTTP'; +exports.color = '#5D9CEC'; +exports.icon = 'globe'; +exports.input = false; +exports.output = ['#6CAC5A', '#37BC9B']; +exports.version = '1.2.3'; +exports.author = 'Martin Smola'; +exports.cloning = false; +exports.options = { method: 'GET', url: '', size: 5, cacheexpire: '5 minutes', cachepolicy: 0, timeout: 5 }; +exports.dateupdated = '2021-01-21 18:30d'; +exports.readme = `# HTTP route + +__Outputs__: +- first output: raw data (cache is empty or is disabled) +- second output: cached data + +If one of the outputs is disabled then automatic responce with code "503 service unavailable" is sent. + +When a request comes in bellow object is available at \`flowdata.data\`: + +\`\`\`javascript +{ + params: { id: '1' }, // params for dynamic routes, e.g. /test/{id} + query: { msg: 'Hello' }, // parsed query string, e.g. /test/1?msg=Hello + body: { test: 'OK' }, // object if json requests otherwise string + headers: {}, // headers data + session: {}, // session data + user: {}, // user data + files: [], // uploaded files + url: '/users/', // a relative URL address + referrer: '/', // referrer + mobile: false, // determines mobile device + robot: false, // determines search robots/crawlsers + language: 'en' // determines language +} +\`\`\` + +See [documentation for flags](https://docs.totaljs.com/latest/en.html#api~HttpRouteOptionsFlags~unauthorize). These method flags are set automatically e.g. \`get, post, put, patch or delete\` + +--- + +\`id:ROUTE_ID\` flag cannot be used since it's already used by this component internally`; + +exports.html = `
+
+ +
+ +
+
+
@(HTTP method)
+
+
+
@(URL address)
+
+
+
+
+
@(Additional flags)
+
@(Separate flags by comma e.g. json, authorize)
+
+
+
@(Max. request size)
+
@(In kB kilobytes)
+
+
+
@(Timeout)
+
@(In seconds.)
+
+
+
+
+
+
@(Automatically respond with 200 OK?)
+
@(If not checked you need to use HTTP response component to respond to the request.)
+
+
@(Custom headers)
+
@(Cookies)
+
+
+
+
+
+
@(Cache policy)
+
@(User instance must contain id property.)
+
+
+
@(Expiration)
+
@(E.g. 5 minutes)
+
+
+
+`; + +exports.install = function(instance) { + + var route; + + var uninstall = function(id) { + if (F.is4) { + route && route.remove(); + route = null; + } else + UNINSTALL('route', id); + }; + + instance.custom.emptyresponse = function(self) { + self.plain(); + }; + + instance.reconfigure = function() { + + var options = instance.options; + + if (!options.url) { + instance.status('Not configured', 'red'); + return; + } + + if (typeof(options.flags) === 'string') + options.flags = options.flags.split(',').trim(); + + uninstall('id:' + instance.id); + + var flags = options.flags || []; + + flags.push('id:' + instance.id); + + if (!F.is4) + flags.push(options.method.toLowerCase()); + + options.timeout && flags.push(options.timeout * 1000); + + // Make unique values + flags = flags.filter(function(v, i, a) { + if(F.is4 && v.toString().toLowerCase() === options.method.toLowerCase()) + return false; // remove method + return a.indexOf(v) === i; + }); + + options.flags = flags; + var handler = function() { + + if (instance.paused || (instance.isDisabled && (instance.isDisabled('output', 0) || instance.isDisabled('output', 1)))) { + instance.status('503 Service Unavailable'); + this.status = 503; + this.json(); + return; + } + + var key; + var self = this; + + if (instance.options.emptyresponse) { + instance.status('200 OK'); + setTimeout(instance.custom.emptyresponse, 100, self); + + if (instance.hasConnection(0)) { + var data = instance.make({ + query: self.query, + body: self.body, + session: self.session, + user: self.user, + files: self.files, + headers: self.req.headers, + url: self.url, + params: self.params + }); + instance.send2(0, data); + } + + return; + } + + switch (instance.options.cachepolicy) { + case 1: // URL + key = 'rro' + instance.id + self.url.hash(); + break; + case 2: // URL + query + case 3: // URL + query + user + key = self.url; + var keys = Object.keys(self.query); + keys.sort(); + for (var i = 0, length = keys.length; i < length; i++) + key += keys[i] + self.query[keys[i]] + '&'; + if (instance.options.cachepolicy === 3 && self.user) + key += 'iduser' + self.user.id; + key = 'rro' + instance.id + key.hash(); + break; + } + + if (key && F.cache.get2(key)) { + var data = instance.make(F.cache.get2(key)); + data.repository.controller = self; + instance.send2(1, data); + } else { + + var data = instance.make({ + query: self.query, + body: self.body, + session: self.session, + user: self.user, + files: self.files, + headers: self.req.headers, + url: self.url, + params: self.params, + mobile: self.mobile, + robot: self.robot, + referrer: self.referrer, + language: self.language + }); + + data.repository.controller = self; + instance.send2(0, data); + key && FINISHED(self.res, () => F.cache.set(key, self.$flowdata.data, instance.options.cacheexpire)); + } + }; + + if (F.is4) + route = ROUTE(options.method.toUpperCase() + ' ' + options.url, handler, flags, options.size || 5); + else + F.route(options.url, handler, flags, options.size || 5); + + instance.status('Listening', 'green'); + }; + + instance.reconfigure(); + instance.on('options', instance.reconfigure); + instance.on('close', function(){ + uninstall('id:' + instance.id); + }); +}; + +// check url exists +FLOW.trigger('httproutecheckurl', function(next, data) { + var url = data.url; + var method = data.method; + if (url[url.length - 1] !== '/') + url += '/'; + var exists = F.routes.web.findItem(r => r.urlraw === url && r.method === method); + next(exists != null); +}); + +exports.uninstall = function() { + FLOW.trigger('httproutecheckurl', null); +}; diff --git a/RVO12/flow/infosender.js b/RVO12/flow/infosender.js new file mode 100755 index 0000000..587724f --- /dev/null +++ b/RVO12/flow/infosender.js @@ -0,0 +1,81 @@ +exports.id = 'infosender'; +exports.title = 'Info sender'; +exports.version = '1.0.0'; +exports.group = 'Worksys'; +exports.color = '#2134B0'; +exports.input = 2; +exports.output = 1 +exports.icon = 'bolt'; + +const { networkInterfaces } = require('os'); + +exports.html = `
+
+
+
CSV Import
+
+
+
`; + +exports.readme = `# send all data to projects.worksys.io, required to monitor status of controller(unipi)`; + +exports.install = function(instance) { + + let id; + let allValues = {}; + let sendAllValuesInterval; + let configured = false; + + let now = new Date(); + console.log(exports.title, "INSTALLED", now.toLocaleString("sk-SK")); + + const nets = networkInterfaces(); + let ipAddresses = Object.create(null); // Or just '{}', an empty object + + for (const name of Object.keys(nets)) { + for (const net of nets[name]) { + // Skip over non-IPv4 and internal (i.e. 127.0.0.1) addresses + if (net.family === 'IPv4' && !net.internal) { + if (!ipAddresses[name]) { + ipAddresses[name] = []; + } + ipAddresses[name].push(net.address); + } + } + } + + function sendValues() { + if (!configured) return; + + if (Object.keys(allValues).length > 0) { + let dataToSend = { ...allValues }; + dataToSend.id = id; + dataToSend.ipAddresses = ipAddresses; + + instance.send(0, dataToSend); + + allValues = {}; + } + } + + instance.on("close", () => { + clearInterval(sendAllValuesInterval); + }) + + instance.on("0", _ => { + id = FLOW.GLOBALS.settings.project_id; + if (id) configured = true; + else console.log(exports.title, "InfoSender: Unable to send data, no id"); + }) + + instance.on("1", flowdata => { + allValues = { ...allValues, ...flowdata.data }; + //console.log("DATA RECEIVED", flowdata.data); + }) + + sendAllValuesInterval = setInterval(() => { + sendValues(); + }, 60000 * 3); + +} + diff --git a/RVO12/flow/modbus_reader.js b/RVO12/flow/modbus_reader.js new file mode 100755 index 0000000..d6d9dad --- /dev/null +++ b/RVO12/flow/modbus_reader.js @@ -0,0 +1,346 @@ +exports.id = 'modbus_reader'; +exports.title = 'Modbus reader'; +exports.version = '2.0.0'; +exports.group = 'Worksys'; +exports.color = '#2134B0'; +exports.input = 1; +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; +//number of phases inRVO +let phases; +//phases where voltage is 0 (set) +let noVoltage; +let energyToSwitchLamps; + +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.phases = this.buildPhases(); + + this.startSocket(); + } + + buildPhases = () => { + let a = []; + for (let i = 1; i <= phases; i++) { + a.push(`Phase_${i}_voltage`) + } + return a; + } + + startSocket = () => { + + let obj = this; + + if (this.socket) { + this.socket.removeAllListeners(); + this.socket = null; + } + + 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('Modbus_reader: Socket connection error', e); //'ECONNREFUSED' or 'ECONNRESET' ?? + }); + + this.socket.on('close', function() { + console.log('Modbus_reader: Socket connection closed - Waiting 10 seconds before connecting 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 we just start to loop devices from the beginning, or there is just 1 device in config, we wait whole timeoutInterval + if (this.indexInDeviceConfig == 0 || deviceConfig.length === 1) 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 (this.phases.includes(singleValue)) { + let l = singleValue.split("_"); + let phase = parseInt(l[1]); + + // console.log(values[singleValue], tbName); + + if (values[singleValue] == 0) { + noVoltage.add(phase); + sendNotification("modbus_reader: checkNullVoltage", tbName, "no_voltage_on_phase", { phase: phase }, "", SEND_TO.tb, instance, "voltage" + phase); + // console.log('no voltage') + } + else { + noVoltage.delete(phase); + // console.log('voltage detected') + sendNotification("modbus_reader: checkNullVoltage", tbName, "voltage_on_phase_restored", { phase: phase }, "", SEND_TO.tb, instance, "voltage" + phase); + } + } + }) + } + + /** + * function sends notification to slack and to tb, if EM total_power value changes more than numberOfNodes*15. This should show, that RVO lamps has been switched on or off + */ + lampSwitchNotification = (values) => { + + if (!values.hasOwnProperty("total_power")) return; + + const actualTotalPower = values.total_power; + + if (actualTotalPower > energyToSwitchLamps && 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 <= energyToSwitchLamps && 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; + } + + function main() { + + phases = FLOW.GLOBALS.settings.phases; + tbName = FLOW.GLOBALS.settings.rvoTbName; + noVoltage = FLOW.GLOBALS.settings.no_voltage; + energyToSwitchLamps = FLOW.GLOBALS.settings.energy_to_switch_lamps / 2.5; //half value is enought to show if lamps are turned on or off + if (deviceConfig.length) mainSocket = new SocketWithClients(); + else console.log("Modbus_reader: no modbus device in configuration"); + + // this notification is to show, that flow (unipi) has been restarted + sendNotification("modbus_reader", tbName, "flow_restart", {}, "", SEND_TO.slack, instance); + } + + instance.on("0", function(_) { + main(); + }) + +} + diff --git a/RVO12/flow/monitorconsumption.js b/RVO12/flow/monitorconsumption.js new file mode 100755 index 0000000..64cc58e --- /dev/null +++ b/RVO12/flow/monitorconsumption.js @@ -0,0 +1,156 @@ +exports.id = 'monitorconsumption'; +exports.title = 'Consumption'; +exports.version = '1.0.0'; +exports.author = 'Peter Širka'; +exports.group = 'Monitoring'; +exports.color = '#967ADC'; +exports.input = 0; +exports.output = 1; +exports.icon = 'bug'; +exports.options = { interval: 5000, enabled: true, monitorconsumption: true, monitorsize: true, monitorconnections: true, monitorfiles: true }; +exports.click = true; +exports.readme = `# Consumption monitoring + +This component measure CPU and memory consumption, open files and open connections of this application. It uses these Linux commands: \`ps\`, \`lsof\`, \`netstat\` and \`df\`. + +__Data Example__: + +\`\`\`javascript +{ + cpu: 0, // percentage + memory: 4096, // in bytes + size: 34303, // directory size in bytes + files: 34, // count of open files + connections: 343, // count of connections + uptime: '1-12:34:00' +} +\`\`\``; + +exports.html = `
+
+
+
@(Interval in milliseconds)
+
+
+
+
Monitor: Consumption + uptime
+
Monitor: Count of open files
+
Monitor: Count of open connections
+
Monitor: Directory size
+
`; + +exports.install = function(instance) { + + var current = { cpu: 0, memory: 0, files: 0, connections: 0, size: 0, uptime: '', counter: 0 }; + var tproc = null; + var Exec = require('child_process').exec; + var reg_empty = /\s{2,}/g; + var reg_appdisksize = /^[\d.,]+/; + + instance.custom.run = function() { + + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + + var arr = []; + + // Get CPU and Memory consumption + instance.options.monitorconsumption && arr.push(function(next) { + Exec('ps -p {0} -o %cpu,rss,etime'.format(process.pid), function(err, response) { + + if (err) { + instance.throw(err); + } else { + var line = response.split('\n')[1]; + line = line.trim().replace(reg_empty, ' ').split(' '); + var cpu = line[0].parseFloat(); + current.cpu = cpu.floor(1); + current.memory = line[1].parseInt2() * 1024; // kB to bytes + current.uptime = line[2]; + } + + next(); + }); + }); + + // Get count of open files + instance.options.monitorfiles && arr.push(function(next) { + Exec('lsof -a -p {0} | wc -l'.format(process.pid), function(err, response) { + if (err) + instance.throw(err); + else + current.files = response.trim().parseInt2(); + next(); + }); + }); + + // Get count of opened network connections + instance.options.monitorconnections && arr.push(function(next) { + Exec('netstat -an | grep :{0} | wc -l'.format(F.port), function(err, response) { + if (err) { + instance.throw(err); + } else { + current.connections = response.trim().parseInt2() - 1; + if (current.connections < 0) + current.connections = 0; + } + next(); + }); + }); + + // Get directory size + instance.options.monitorsize && current.counter % 5 !== 0 && arr.push(function(next) { + Exec('du -hsb ' + process.cwd(), function(err, response) { + if (err) { + instance.throw(err); + } else { + var match = response.trim().match(reg_appdisksize); + match && (current.size = match.toString().trim().parseInt2()); + } + next(); + }); + }); + + arr.async(function() { + + tproc && clearTimeout(tproc); + + if (instance.options.enabled) { + tproc = setTimeout(instance.custom.run, instance.options.interval); + instance.send2(current); + } + + instance.custom.status(); + current.counter++; + }); + }; + + instance.custom.status = function() { + if (instance.options.enabled) + instance.status('{0}% / {1}'.format(current.cpu, current.memory.filesize())); + else + instance.status('Disabled', 'red'); + }; + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + + if (instance.options.enabled) { + current.counter = 0; + instance.custom.run(); + } + + }); + + instance.on('close', function() { + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + }); + + setTimeout(instance.custom.run, 1000); +}; \ No newline at end of file diff --git a/RVO12/flow/monitordisk.js b/RVO12/flow/monitordisk.js new file mode 100755 index 0000000..f4fdaa0 --- /dev/null +++ b/RVO12/flow/monitordisk.js @@ -0,0 +1,96 @@ +exports.id = 'monitordisk'; +exports.title = 'Disk'; +exports.version = '1.0.0'; +exports.author = 'Peter Širka'; +exports.group = 'Monitoring'; +exports.color = '#F6BB42'; +exports.output = 1; +exports.icon = 'hdd-o'; +exports.click = true; +exports.options = { interval: 8000, path: '/', enabled: true }; +exports.readme = `# Disk monitoring + +This component monitors disk \`bytes\` consumption in Linux systems. It uses \`df\` command. + +__Data Example__: + +\`\`\`javascript +{ + total: 474549649408, + used: 39125245952, + free: 411294994432 +} +\`\`\``; + +exports.html = `
+
+
+
@(Interval in milliseconds)
+
+
+
@(Path)
+
+
+
`; + +exports.install = function(instance) { + + var current = { total: 0, used: 0, free: 0, path: '', type: '', percentUsed: 0 }; + var tproc = null; + + instance.custom.run = function() { + + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + + if (!instance.options.enabled) + return; + + require('child_process').exec('df -hTB1 ' + instance.options.path, function(err, response) { + + tproc = setTimeout(instance.custom.run, instance.options.interval); + + if (err) { + instance.error(err); + return; + } + + response.parseTerminal(function(line) { + if (line[0][0] !== '/') + return; + current.total = line[2].parseInt(); + current.free = line[4].parseInt(); + current.used = line[3].parseInt(); + current.path = instance.options.path || '/'; + current.type = line[1]; + current.percentUsed = line[5]; + instance.custom.status(); + instance.send2(current); + }); + }); + }; + + instance.custom.status = function() { + if (instance.options.enabled) + instance.status(current.free.filesize() + ' / ' + current.total.filesize()); + else + instance.status('Disabled', 'red'); + }; + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + instance.options.enabled && instance.custom.run(); + }); + + instance.on('close', function() { + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + }); + + setTimeout(instance.custom.run, 1000); +}; \ No newline at end of file diff --git a/RVO12/flow/monitormemory.js b/RVO12/flow/monitormemory.js new file mode 100755 index 0000000..2decbc4 --- /dev/null +++ b/RVO12/flow/monitormemory.js @@ -0,0 +1,87 @@ +exports.id = 'monitormemory'; +exports.title = 'Memory'; +exports.version = '1.0.0'; +exports.author = 'Peter Širka'; +exports.group = 'Monitoring'; +exports.color = '#F6BB42'; +exports.output = 1; +exports.click = true; +exports.icon = 'microchip'; +exports.options = { interval: 8000, enabled: true }; +exports.readme = `# Memory monitoring + +This component monitors memory \`bytes\` consumption in Linux systems. It uses \`free\` command. + +__Data Example__: + +\`\`\`javascript +{ + total: 33558769664, + used: 1998868480, + free: 2653708288 +} +\`\`\``; + +exports.html = `
+
+
+
@(Interval in milliseconds)
+
+
+
`; + +exports.install = function(instance) { + + var current = { total: 0, used: 0, free: 0 }; + var tproc = null; + + instance.custom.run = function() { + + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + + if (!instance.options.enabled) + return; + + require('child_process').exec('free -b -t', function(err, response) { + + tproc = setTimeout(instance.custom.run, instance.options.interval); + + if (err) { + instance.error(err); + return; + } + + var memory = response.split('\n')[1].match(/\d+/g); + current.total = memory[0].parseInt(); + current.used = memory[1].parseInt() - memory[3].parseInt(); + current.free = current.total - current.used; + instance.custom.status(); + instance.send2(current); + }); + }; + + instance.custom.status = function() { + if (instance.options.enabled) + instance.status(current.free.filesize() + ' / ' + current.total.filesize()); + else + instance.status('Disabled', 'red'); + }; + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + instance.options.enabled && instance.custom.run(); + }); + + instance.on('close', function() { + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + }); + + setTimeout(instance.custom.run, 1000); +}; \ No newline at end of file diff --git a/RVO12/flow/nodesdb_changecheck.js b/RVO12/flow/nodesdb_changecheck.js new file mode 100755 index 0000000..9adab62 --- /dev/null +++ b/RVO12/flow/nodesdb_changecheck.js @@ -0,0 +1,77 @@ +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 = 2; +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); + } + } + + //kedze do slacku posielame stringy, na cloud musime previest vsetky stringy spat na objekty: + // Funkcia na parsovanie všetkých reťazcov v poli + const parseArray = (arr) => { + return arr.map(jsonString => JSON.parse(jsonString)); + }; + + 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); + if (FLOW.GLOBALS.settings.send_changed_node_numbers) instance.send(1, { aktualneNody: parseArray(zmenene), originalne: parseArray(Array.from(set2)) }); + } + 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/RVO12/flow/show_dbdata.js b/RVO12/flow/show_dbdata.js new file mode 100755 index 0000000..1e23ff7 --- /dev/null +++ b/RVO12/flow/show_dbdata.js @@ -0,0 +1,243 @@ +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 = 8; +exports.output = 1; + +const { exec } = require('child_process'); + +exports.install = 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 }) + }) + instance.on("5", _ => { + exec("sudo tail -n 25 monitor.txt", (err, stdout, stderr) => { + if (err || stderr) instance.send(0, { err, stderr }); + else instance.send(0, stdout); + }) + }) + instance.on("6", _ => { + exec("sudo tail -n 25 err.txt", (err, stdout, stderr) => { + if (err || stderr) instance.send(0, { err, stderr }); + else instance.send(0, stdout); + }) + }) + instance.on("7", _ => { + instance.send(0, FLOW.deviceStatus); + }) +}; + + +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/RVO12/flow/slack_filter.js b/RVO12/flow/slack_filter.js new file mode 100755 index 0000000..6618523 --- /dev/null +++ b/RVO12/flow/slack_filter.js @@ -0,0 +1,188 @@ +exports.id = 'slack_filter'; +exports.title = 'Slack Filter'; +exports.group = 'Citysys'; +exports.color = '#30E193'; +exports.input = 2; +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 = `
+
+
+
@(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('0', 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']['en']; + 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"] = []; + } + + instance.options.name = FLOW.GLOBALS.settings.rvo_name; + if (instance.options.name) { + instance.status('Running'); + running = true; + } else { + instance.status('Please run options again', 'red'); + running = false; + } + } catch (e) { + instance.error('Citysys connector: ' + e.message); + } + }; + + instance.on('options', instance.reconfigure); + + instance.on("1", _ => { + instance.reconfigure(); + }) +}; diff --git a/RVO12/flow/thermometer.js b/RVO12/flow/thermometer.js new file mode 100755 index 0000000..fc7074d --- /dev/null +++ b/RVO12/flow/thermometer.js @@ -0,0 +1,99 @@ +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 = 5;//minutes +let NUMBER_OF_FAILURES_TO_SEND_ERROR = 13; + +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) => { + + 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); + setTimeout(main, 20000); + }) +}; diff --git a/RVO12/flow/trigger.js b/RVO12/flow/trigger.js new file mode 100755 index 0000000..27545a8 --- /dev/null +++ b/RVO12/flow/trigger.js @@ -0,0 +1,79 @@ +exports.id = 'trigger'; +exports.title = 'Trigger'; +exports.group = 'Inputs'; +exports.color = '#F6BB42'; +exports.click = true; +exports.output = 1; +exports.version = '1.1.0'; +exports.author = 'Martin Smola'; +exports.icon = 'play'; + +exports.html = `
+
@(Data type (String by default))
+
@(Data)
+
Trigger 5s after initialization.
+
@(Useful when there's a need to run certain flow when the app restarts, etc.)
+
`; + +exports.readme = `# Trigger + +- Clicking on the component starts the chain +- Settings allows to set a data-type and a value`; + +exports.install = function(instance) { + + var value; + + instance.on('click', () => instance.send2(value)); + + instance.reconfigure = function() { + var options = instance.options; + value = null; + switch (options.datatype) { + case 'integer': + value = options.data.parseInt2('error'); + value = value === 'error' ? NaN : value; + break; + case 'float': + value = options.data.parseFloat2('error'); + value = value === 'error' ? NaN : value; + break; + case 'date': + options.data = options.data.toString(); + var num = options.data.parseInt('error'); + num === 'error' && (num = options.data.parseDate('error')); + num === 'error' && (num = null); + value = num ? new Date(num).toUTCString() : num; + break; + case 'object': + try { + value = (new Function('return ' + options.data))(); + } catch (e) { + instance.error(e); + } + break; + case 'boolean': + value = options.data.parseBoolean(); + break; + case 'buffer': + try { + value = U.createBuffer(options.data); + } catch (e) { + instance.error(e); + } + break; + case 'string': + default: + value = '' + (options.data || ''); + break; + } + }; + + instance.on('options', instance.reconfigure); + instance.reconfigure(); + + if (instance.options.restart) + setTimeout(function(){ + instance.send2(value); + }, 5000); +}; diff --git a/RVO12/flow/variables.txt b/RVO12/flow/variables.txt new file mode 100755 index 0000000..e69de29 diff --git a/RVO12/flow/virtualwirein.js b/RVO12/flow/virtualwirein.js new file mode 100755 index 0000000..38a4e42 --- /dev/null +++ b/RVO12/flow/virtualwirein.js @@ -0,0 +1,43 @@ +exports.id = 'virtualwirein'; +exports.title = 'Virtual wire in'; +exports.version = '1.0.0'; +exports.author = 'Martin Smola'; +exports.color = '#303E4D'; +exports.icon = 'sign-in'; +exports.input = false; +exports.output = 1; +exports.options = {}; +exports.readme = `# Virtual wire in + +When the wires between the components are mess it's time to use Virtual wire.`; + +exports.html = `
+
@(Wire name)
+
+`; + +exports.install = function(instance) { + + instance.custom.reconfigure = function(options){ + if (instance.options.wirename) { + instance.status(instance.options.wirename); + } else + instance.status('Not configured', 'red'); + }; + + ON('virtualwire', function(wirename, flowdata){ + if (instance.options.wirename && instance.options.wirename === wirename) + instance.send(flowdata); + }); + + instance.on('options', instance.custom.reconfigure); + instance.custom.reconfigure(); +}; diff --git a/RVO12/flow/virtualwireout.js b/RVO12/flow/virtualwireout.js new file mode 100755 index 0000000..94a1e4f --- /dev/null +++ b/RVO12/flow/virtualwireout.js @@ -0,0 +1,41 @@ +exports.id = 'virtualwireout'; +exports.title = 'Virtual wire out'; +exports.version = '1.0.0'; +exports.author = 'Martin Smola'; +exports.color = '#303E4D'; +exports.icon = 'sign-out'; +exports.input = true; +exports.options = {}; +exports.readme = `# Virtual wire out + +When the wires between the components are mess it's time to use Virtual wire.`; + +exports.html = `
+
@(Wire name)
+
+`; + +exports.install = function(instance) { + + instance.custom.reconfigure = function(){ + if (instance.options.wirename) { + instance.status(instance.options.wirename); + } else + instance.status('Not configured', 'red'); + }; + + instance.on('data', function(flowdata) { + EMIT('virtualwire', instance.options.wirename, flowdata); + }); + + instance.on('options', instance.custom.reconfigure); + instance.custom.reconfigure(); +}; diff --git a/RVO12/flow/wsmqttpublish.js b/RVO12/flow/wsmqttpublish.js new file mode 100755 index 0000000..0eba804 --- /dev/null +++ b/RVO12/flow/wsmqttpublish.js @@ -0,0 +1,448 @@ +exports.id = 'wsmqttpublish'; +exports.title = 'WS MQTT publish'; +exports.group = 'MQTT'; +exports.color = '#888600'; +exports.version = '1.0.2'; +exports.icon = 'sign-out'; +exports.input = 2; +exports.output = 3; +exports.options = { host: 'tb-stage.worksys.io', port: 1883, clientid: "", username: "" }; + +exports.html = `
+
+
+
Hostname or IP address (if not empty - setting will override db setting)
+
+
+
Port
+
+
+
+
+
@(Client id)
+
+
+
@(Username)
+
+
+
`; + + +exports.readme = ` +# WS MQTT Publish + +Version 1.0.3. + +Added: +- database collections, +- 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 = { + debug: 0, + rpcCall: 1, + services: 2 +} + +//CONFIG +let createTelemetryBackup = true; +let saveTelemetryOnError = true;//backup_on_failure overrides this value +//------------------------ + +let rollers; +if (createTelemetryBackup) rollers = require('streamroller'); + +const noSqlFileSizeLimit = 4194304;//use 5MB - 4194304 +let insertNoSqlCounter = 0; +let insertBackupNoSqlCounter = 0; +let processingData = false; + +let backup_on_failure = false;//== saveTelemetryOnError - create backup client 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; + +process.on('uncaughtException', function(err) { + + errLogger.error('uncaughtException:', err.message) + errLogger.error(err.stack); + + //TODO + //send to service + + //process.exit(1); +}) + +const nosql = NOSQL('tbdata'); +const nosqlBackup = NOSQL('/backup/tbdata'); + + +exports.install = function(instance) { + + var client; + var opts; + var clientReady = false; + + // wsmqtt status for notification purposes on projects.worksys.io database + let wsmqttName = null; + let sendWsStatusVar = null; + let wsmqtt_status = 'disconnected'; + + 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'; + } + + function sendWsStatus() { + instance.send(SEND_TO.services, { [wsmqttName]: wsmqtt_status }); + } + + + function main() { + if (!FLOW.dbLoaded) return; + + loadSettings(); + clearInterval(sendWsStatus); + sendWsStatusVar = setInterval(sendWsStatus, 180000); + } + + //set opts according to db settings + function loadSettings() { + + if (instance.options.host !== "") { + //override settings from database + var o = instance.options; + opts = { + host: o.host, + port: o.port, + clientId: o.clientid, + username: o.username, + rejectUnauthorized: false, + resubscribe: false + }; + + wsmqttName = getWsmqttName(o.host); + + console.log("wsmqttpublich -> loadSettings from instance.options", instance.options); + } + else { + + const SETTINGS = FLOW.GLOBALS.settings; + backup_on_failure = SETTINGS.backup_on_failure; + saveTelemetryOnError = backup_on_failure; + + restore_from_backup = SETTINGS.restore_from_backup; + restore_backup_wait = SETTINGS.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; + + opts = { + host: mqtt_host, + port: mqtt_port, + keepalive: 10, + clientId: mqtt_clientid, + username: mqtt_username, + rejectUnauthorized: false, + resubscribe: false + }; + + wsmqttName = getWsmqttName(mqtt_host); + } + + connectToTbServer(); + } + + function connectToTbServer() { + 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"); + //monitor.info("MQTT client connected"); + + sendClientError = true; + clientReady = true; + wsmqtt_status = 'connected'; + }); + + client.on('reconnect', function() { + instance.status("Reconnecting", "yellow"); + clientReady = false; + }); + + client.on('message', function(topic, message) { + // message is type of buffer + message = message.toString(); + if (message[0] === '{') { + TRY(function() { + + message = JSON.parse(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 } }); + } + + }, () => instance.debug('MQTT: Error parsing data', message)); + } + + instance.send(SEND_TO.rpcCall, { "topic": topic, "content": message }); + }); + + client.on('close', function() { + clientReady = false; + wsmqtt_status = 'disconnected'; + + instance.status("Disconnected", "red"); + instance.send(SEND_TO.debug, { "message": "Client CLOSE signal received !" }); + }); + + client.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; + wsmqtt_status = 'disconnected'; + }); + + } + + + instance.on("0", _ => { + main(); + }) + + + instance.on('1', function(data) { + + if (clientReady) { + //do we have some data in backup file? if any, process data from database + if (saveTelemetryOnError) { + //read telemetry data and send back to server + if (!processingData) processDataFromDatabase(); + } + + let stringifiedJson = JSON.stringify(data.data); + client.publish("v1/gateway/telemetry", stringifiedJson, { qos: 1 }); + + //backup telemetry + if (createTelemetryBackup) { + data.data.id = UID(); + nosqlBackup.insert(data.data); + + insertBackupNoSqlCounter++; + if (insertBackupNoSqlCounter > 150) { + let options = { compress: true }; + let path = __dirname + "/../databases/backup/tbdata.nosql"; + var stream = new rollers.RollingFileStream(path, noSqlFileSizeLimit, 150, options); + stream.write(""); + stream.end(); + + insertBackupNoSqlCounter = 0; + } + } + + } + 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 (saveTelemetryOnError) { + //create new file from tbdata.nosql, if file size exceeds given limit, and clear tbdata.nosql + makeBackupFromDbFile(); + + //write to tb + data.data.id = UID(); + nosql.insert(data.data); + } + } + }); + + + instance.close = function(done) { + if (clientReady) { + client.end(); + clearInterval(sendWsStatusVar); + } + }; + + + function getDbBackupFileCounter(type) { + var files = fs.readdirSync(__dirname + "/../databases"); + + let counter = 0; + for (var i = 0; i < files.length; i++) { + + if (files[i] == "tbdata.nosql") continue; + + if (files[i].endsWith(".nosql")) { + + let pos = files[i].indexOf("."); + if (pos > -1) { + + let fileCounter = counter; + let firstDigit = files[i].slice(0, pos); + + fileCounter = parseInt(firstDigit); + if (isNaN(fileCounter)) fileCounter = 0; + //console.log("getDbBackupFileCounter digit:", files[i], firstDigit, fileCounter, isNaN(fileCounter), type); + + if (type == "max") { + if (fileCounter > counter) { + counter = fileCounter; + } + } + else if (type == "min") { + if (counter == 0) counter = fileCounter; + + if (fileCounter < counter) { + counter = fileCounter; + } + } + } + } + + } + + if (type == "max") counter++; + + return counter; + } + + const makeBackupFromDbFile = async () => { + + if (!saveTelemetryOnError) return; + + //to avoid large file: tbdata.nosql + + //init value is 0! + if (insertNoSqlCounter > 0) { + --insertNoSqlCounter; + return; + } + + insertNoSqlCounter = 100; + + let source = __dirname + "/../databases/tbdata.nosql"; + + var stats = fs.statSync(source); + var fileSizeInBytes = stats.size; + + if (fileSizeInBytes > noSqlFileSizeLimit) { + + let counter = 1; + counter = getDbBackupFileCounter("max"); + + let destination = __dirname + "/../databases/" + counter + "." + "tbdata.nosql"; + + //make backup file + fs.copyFileSync(source, destination); + //fs.renameSync(p, p + "." + counter); + + //clear tbdata.nosql + fs.writeFileSync(source, ""); + fs.truncateSync(source, 0); + + } + } + + const processDataFromDatabase = async () => { + + if (restore_from_backup <= 0) return; + + //calculate diff + const now = new Date(); + let currentTime = now.getTime(); + let diff = currentTime - lastRestoreTime; + + if ((diff / 1000) < restore_backup_wait) { + //console.log("*********restore_backup_wait", diff, restore_backup_wait); + return; + } + + processingData = true; + + //get filename to process + let counter = getDbBackupFileCounter("min"); + + //we have some backup files + let dataBase = 'tbdata'; + + var nosql; + if (counter == 0) dataBase = 'tbdata'; + else dataBase = counter + "." + 'tbdata'; + + nosql = NOSQL(dataBase); + + //select all data - use limit restore_from_backup + let records = await promisifyBuilder(nosql.find().take(restore_from_backup)); + + for (let i = 0; i < records.length; i++) { + if (clientReady) { + + let item = records[i]; + let id = item.id; + + if (id !== undefined) { + //console.log("------------processDataFromDatabase - remove", id, dataBase, i); + + try { + + let message = JSON.parse(JSON.stringify(item)); + delete message.id; + + client.publish("v1/gateway/telemetry", JSON.stringify(message), { qos: 1 }); + + //remove from database + await promisifyBuilder(nosql.remove().where("id", id)); + + } catch (error) { + //process error + console.log("processDataFromDatabase", error); + } + + } + + } + else { + processingData = false; + return; + } + } + + if (records.length > 0) { + //clean backup file + if (counter > 0) nosql.clean(); + } + + //no data in db, remove + if (records.length == 0) { + if (counter > 0) nosql.drop(); + } + + const d = new Date(); + lastRestoreTime = d.getTime(); + + processingData = false; + + } + + instance.on('options', main); + //instance.reconfigure(); +}; diff --git a/RVO12/monitor.txt b/RVO12/monitor.txt new file mode 100755 index 0000000..abbf3d2 --- /dev/null +++ b/RVO12/monitor.txt @@ -0,0 +1,306 @@ +[2025-10-09T16:58:03.940] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-09T16:58:09.296] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-09T16:58:09.300] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-09T16:58:09.302] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-09T16:58:09.302] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-09T16:58:09.306] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T16:58:09.308] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-10-10T05:32:00.307Z +[2025-10-09T16:58:09.309] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-10-09T16:45:00.309Z +[2025-10-09T16:58:09.310] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T16:58:09.311] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-10-09T16:58:09.312] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-09T16:58:09.313] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-09T16:58:09.315] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T16:58:09.316] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-10-10T05:32:00.316Z +[2025-10-09T16:58:09.316] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-10-09T16:45:00.316Z +[2025-10-09T16:58:09.317] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T16:58:09.318] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-10-09T16:58:09.319] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-09T16:58:09.319] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-09T16:58:09.322] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T16:58:09.322] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-10-10T05:32:00.322Z +[2025-10-09T16:58:09.323] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-10-09T16:45:00.323Z +[2025-10-09T16:58:09.324] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T16:58:09.325] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-10-09T16:58:09.347] [INFO] monitorLogs - tasks created: 700 +[2025-10-09T16:58:09.350] [INFO] monitorLogs - -->FLOW bol spustený XMBbew5z4ELrZa2mRAd3zV78vPN6gy3DdVYlpKjq 2025-08-08 +[2025-10-09T16:58:14.354] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-09T18:17:41.369] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-09T18:17:41.372] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-09T18:17:41.375] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-09T19:11:01.928] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-09T19:11:07.278] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-09T19:11:07.283] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-09T19:11:07.284] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-09T19:11:07.285] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-09T19:11:07.290] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T19:11:07.291] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-10-10T05:32:00.290Z +[2025-10-09T19:11:07.292] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-10-10T16:45:00.292Z +[2025-10-09T19:11:07.293] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T19:11:07.294] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-10-09T19:11:07.295] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-09T19:11:07.296] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-09T19:11:07.298] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T19:11:07.299] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-10-10T05:32:00.299Z +[2025-10-09T19:11:07.300] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-10-10T16:45:00.300Z +[2025-10-09T19:11:07.300] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T19:11:07.301] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-10-09T19:11:07.302] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-09T19:11:07.303] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-09T19:11:07.305] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T19:11:07.306] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-10-10T05:32:00.305Z +[2025-10-09T19:11:07.306] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-10-10T16:45:00.306Z +[2025-10-09T19:11:07.307] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T19:11:07.308] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-10-09T19:11:07.312] [INFO] monitorLogs - tasks created: 700 +[2025-10-09T19:11:07.315] [INFO] monitorLogs - -->FLOW bol spustený XMBbew5z4ELrZa2mRAd3zV78vPN6gy3DdVYlpKjq 2025-08-08 +[2025-10-09T19:11:12.319] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-10T03:11:09.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-10 03:11:09 +[2025-10-10T07:08:32.757] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-10T07:08:32.763] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-10T07:08:32.766] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-10T18:08:28.689] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-10T18:08:28.695] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-10T18:08:28.697] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-11T03:11:10.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-11 03:11:10 +[2025-10-11T07:08:49.665] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-11T07:08:49.671] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-11T07:08:49.673] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-11T18:16:08.236] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-11T18:16:08.239] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-11T18:16:08.241] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-12T03:11:12.015] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-12 03:11:12 +[2025-10-12T07:08:35.330] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-12T07:08:35.334] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-12T07:08:35.336] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-12T18:08:22.993] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-12T18:08:22.995] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-12T18:08:22.998] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-13T03:11:13.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-13 03:11:13 +[2025-10-13T07:05:35.808] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-13T07:05:35.813] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-13T07:05:35.815] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-13T18:16:54.676] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-13T18:16:54.678] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-13T18:16:54.680] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-14T03:11:15.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-14 03:11:15 +[2025-10-14T07:06:31.920] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-14T07:06:31.926] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-14T07:06:31.928] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-14T18:05:42.761] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-14T18:05:42.767] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-14T18:05:42.769] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-15T03:11:17.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-15 03:11:17 +[2025-10-15T07:15:31.240] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-15T07:15:31.245] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-15T07:15:31.247] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-15T12:05:30.519] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-15T12:05:35.888] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-15T12:05:35.893] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-15T12:05:35.894] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-15T12:05:35.895] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-15T12:05:35.899] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-15T12:05:35.901] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-10-16T05:41:00.900Z +[2025-10-15T12:05:35.902] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-10-15T16:33:00.902Z +[2025-10-15T12:05:35.903] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:41', name: 'luxOff' }, + { value: 1, start_time: '18:33', name: 'luxOn' } +] +[2025-10-15T12:05:35.904] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-10-15T12:05:35.905] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-15T12:05:35.905] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-15T12:05:35.908] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-15T12:05:35.908] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-10-16T05:41:00.908Z +[2025-10-15T12:05:35.909] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-10-15T16:33:00.909Z +[2025-10-15T12:05:35.910] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:41', name: 'luxOff' }, + { value: 1, start_time: '18:33', name: 'luxOn' } +] +[2025-10-15T12:05:35.911] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-10-15T12:05:35.912] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-15T12:05:35.912] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-15T12:05:35.914] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-15T12:05:35.915] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-10-16T05:41:00.915Z +[2025-10-15T12:05:35.916] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-10-15T16:33:00.916Z +[2025-10-15T12:05:35.916] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:41', name: 'luxOff' }, + { value: 1, start_time: '18:33', name: 'luxOn' } +] +[2025-10-15T12:05:35.917] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-10-15T12:05:35.939] [INFO] monitorLogs - tasks created: 700 +[2025-10-15T12:05:35.942] [INFO] monitorLogs - -->FLOW bol spustený XMBbew5z4ELrZa2mRAd3zV78vPN6gy3DdVYlpKjq 2025-10-08 +[2025-10-15T12:05:40.949] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-15T18:01:37.245] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-15T18:01:37.252] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-15T18:01:37.255] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor diff --git a/RVO12/package-lock.json b/RVO12/package-lock.json new file mode 100755 index 0000000..3c5c1ba --- /dev/null +++ b/RVO12/package-lock.json @@ -0,0 +1,2139 @@ +{ + "name": "emptyproject", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "emptyproject", + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "bitwise": "^2.1.0", + "easy-crc": "0.0.2", + "jsmodbus": "^4.0.6", + "log4js": "^6.3.0", + "moment": "^2.30.1", + "mqtt": "^4.2.6", + "nodemailer": "^6.9.7", + "serialport": "^9.2.8", + "total.js": "^3.4.13" + } + }, + "node_modules/@serialport/binding-abstract": { + "version": "9.2.3", + "resolved": "https://registry.npmjs.org/@serialport/binding-abstract/-/binding-abstract-9.2.3.tgz", + "integrity": "sha512-cQs9tbIlG3P0IrOWyVirqlhWuJ7Ms2Zh9m2108z6Y5UW/iVj6wEOiW8EmK9QX9jmJXYllE7wgGgvVozP5oCj3w==", + "dependencies": { + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/binding-mock": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/binding-mock/-/binding-mock-9.2.4.tgz", + "integrity": "sha512-dpEhACCs44oQhh6ajJfJdvQdK38Vq0N4W6iD/gdplglDCK7qXRQCMUjJIeKdS/HSEiWkC3bwumUhUufdsOyT4g==", + "dependencies": { + "@serialport/binding-abstract": "9.2.3", + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/bindings": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/@serialport/bindings/-/bindings-9.2.8.tgz", + "integrity": "sha512-hSLxTe0tADZ3LMMGwvEJWOC/TaFQTyPeFalUCsJ1lSQ0k6bPF04JwrtB/C81GetmDBTNRY0GlD0SNtKCc7Dr5g==", + "hasInstallScript": true, + "dependencies": { + "@serialport/binding-abstract": "9.2.3", + "@serialport/parser-readline": "9.2.4", + "bindings": "^1.5.0", + "debug": "^4.3.2", + "nan": "^2.15.0", + "prebuild-install": "^7.0.0" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-byte-length": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-byte-length/-/parser-byte-length-9.2.4.tgz", + "integrity": "sha512-sQD/iw4ZMU3xW9PLi0/GlvU6Y623jGeWecbMkO7izUo/6P7gtfv1c9ikd5h0kwL8AoAOpQA1lxdHIKox+umBUg==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-cctalk": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-cctalk/-/parser-cctalk-9.2.4.tgz", + "integrity": "sha512-T4TU5vQMwmo9AB3gQLFDWbfJXlW5jd9guEsB/nqKjFHTv0FXPdZ7DQ2TpSp8RnHWxU3GX6kYTaDO20BKzc8GPQ==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-delimiter": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-delimiter/-/parser-delimiter-9.2.4.tgz", + "integrity": "sha512-4nvTAoYAgkxFiXrkI+3CA49Yd43CODjeszh89EK+I9c8wOZ+etZduRCzINYPiy26g7zO+GRAb9FoPCsY+sYcbQ==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-inter-byte-timeout": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-inter-byte-timeout/-/parser-inter-byte-timeout-9.2.4.tgz", + "integrity": "sha512-SOAdvr0oBQIOCXX198hiTlxs4JTKg9j5piapw5tNq52fwDOWdbYrFneT/wN04UTMKaDrJuEvXq6T4rv4j7nJ5A==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-readline": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-readline/-/parser-readline-9.2.4.tgz", + "integrity": "sha512-Z1/qrZTQUVhNSJP1hd9YfDvq0o7d87rNwAjjRKbVpa7Qi51tG5BnKt43IV3NFMyBlVcRe0rnIb3tJu57E0SOwg==", + "dependencies": { + "@serialport/parser-delimiter": "9.2.4" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-ready": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-ready/-/parser-ready-9.2.4.tgz", + "integrity": "sha512-Pyi94Itjl6qAURwIZr/gmZpMAyTmKXThm6vL5DoAWGQjcRHWB0gwv2TY2v7N+mQLJYUKU3cMnvnATXxHm7xjxw==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-regex": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-regex/-/parser-regex-9.2.4.tgz", + "integrity": "sha512-sI/cVvPOYz+Dbv4ZdnW16qAwvXiFf/1pGASQdbveRTlgJDdz7sRNlCBifzfTN2xljwvCTZYqiudKvDdC1TepRQ==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/stream": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/stream/-/stream-9.2.4.tgz", + "integrity": "sha512-bLye8Ub4vUFQGmkh8qEqehr7SE7EJs2yDs0h9jzuL5oKi+F34CFmWkEErO8GAOQ8YNn7p6b3GxUgs+0BrHHDZQ==", + "dependencies": { + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "node_modules/are-we-there-yet": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", + "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/base64-js": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", + "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==" + }, + "node_modules/bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "dependencies": { + "file-uri-to-path": "1.0.0" + } + }, + "node_modules/bitwise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/bitwise/-/bitwise-2.1.0.tgz", + "integrity": "sha512-XKgAhMXCh4H/3oNwAHAsAO0iC89s9cOiumgYwSHjSobGWxYjv62YhkL9QEdvGP151xypCtMlAfKK79GEcd2eRQ==" + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/bl/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/buffer": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz", + "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==", + "dependencies": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + }, + "node_modules/buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" + }, + "node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, + "node_modules/code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/commist": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/commist/-/commist-1.1.0.tgz", + "integrity": "sha512-rraC8NXWOEjhADbZe9QBNzLAN5Q3fsTPQtBV+fEVj6xKIgDgNiEVE6ZNfHpZOqfQ21YUzfVNUXLOEZquYvQPPg==", + "dependencies": { + "leven": "^2.1.0", + "minimist": "^1.1.0" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "node_modules/concat-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", + "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", + "engines": [ + "node >= 6.0" + ], + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.0.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/concat-stream/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" + }, + "node_modules/core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "node_modules/crc": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/crc/-/crc-3.4.0.tgz", + "integrity": "sha512-ycVC2+4/DLgXXq7QweYi2znhqDuZz6P5TQXnkQo8v15XY/5p/IWeZwsSE31Ifo8w15b8TWLsqhXOjXyilHuQxw==" + }, + "node_modules/date-format": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.11.tgz", + "integrity": "sha512-VS20KRyorrbMCQmpdl2hg5KaOUsda1RbnsJg461FfrcyCUg+pkd0b40BSW4niQyTheww4DBXQnS7HwSrKkipLw==", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" + }, + "node_modules/detect-libc": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz", + "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==", + "engines": { + "node": ">=8" + } + }, + "node_modules/duplexify": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.2.tgz", + "integrity": "sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw==", + "dependencies": { + "end-of-stream": "^1.4.1", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1", + "stream-shift": "^1.0.0" + } + }, + "node_modules/duplexify/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/easy-crc": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/easy-crc/-/easy-crc-0.0.2.tgz", + "integrity": "sha512-h6eqIdhJRe0p271/xZJbM/0klCi13mW5IB7ZEzEGH11yV4QXWAkD4yPErz0fXdhFrd6sZ4Q1k5Iky2kMsMNePw==" + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" + }, + "node_modules/flatted": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", + "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==" + }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, + "node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "node_modules/gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha512-14x4kjc6lkD3ltw589k0NrPD6cCNTD6CWoVUNpB85+DrtONoZn+Rug6xZU5RvSC4+TZPxA5AnBibQYAvZn41Hg==", + "dependencies": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "node_modules/github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==" + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" + }, + "node_modules/has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" + }, + "node_modules/help-me": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/help-me/-/help-me-3.0.0.tgz", + "integrity": "sha512-hx73jClhyk910sidBB7ERlnhMlFsJJIBqSVMFDwPN8o2v9nmp5KgLq1Xz1Bf1fCMMZ6mPrX159iG0VLy/fPMtQ==", + "dependencies": { + "glob": "^7.1.6", + "readable-stream": "^3.6.0" + } + }, + "node_modules/help-me/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, + "node_modules/is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==", + "dependencies": { + "number-is-nan": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "node_modules/js-sdsl": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz", + "integrity": "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/js-sdsl" + } + }, + "node_modules/jsmodbus": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/jsmodbus/-/jsmodbus-4.0.6.tgz", + "integrity": "sha512-gCmjoaERErK5Rn9Lu/BN07fY13MoWV7JKgGzrnkPlQPdPxYcwDhLtYcmpFFpZ4J9NPZZBSezi1UkLZO/DnNppA==", + "dependencies": { + "crc": "3.4.0", + "debug": "^3.1.0" + }, + "bin": { + "jsmodbus": "bin/jsmodbus.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/jsmodbus/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/leven": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", + "integrity": "sha1-wuep93IJTe6dNCAq6KzORoeHVYA=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/log4js": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.5.2.tgz", + "integrity": "sha512-DXtpNtt+KDOMT7RHUDIur/WsSA3rntlUh9Zg4XCdV42wUuMmbFkl38+LZ92Z5QvQA7mD5kAVkLiBSEH/tvUB8A==", + "dependencies": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "flatted": "^3.2.5", + "rfdc": "^1.3.0", + "streamroller": "^3.1.1" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" + }, + "node_modules/moment": { + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", + "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==", + "engines": { + "node": "*" + } + }, + "node_modules/mqtt": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/mqtt/-/mqtt-4.3.7.tgz", + "integrity": "sha512-ew3qwG/TJRorTz47eW46vZ5oBw5MEYbQZVaEji44j5lAUSQSqIEoul7Kua/BatBW0H0kKQcC9kwUHa1qzaWHSw==", + "dependencies": { + "commist": "^1.0.0", + "concat-stream": "^2.0.0", + "debug": "^4.1.1", + "duplexify": "^4.1.1", + "help-me": "^3.0.0", + "inherits": "^2.0.3", + "lru-cache": "^6.0.0", + "minimist": "^1.2.5", + "mqtt-packet": "^6.8.0", + "number-allocator": "^1.0.9", + "pump": "^3.0.0", + "readable-stream": "^3.6.0", + "reinterval": "^1.1.0", + "rfdc": "^1.3.0", + "split2": "^3.1.0", + "ws": "^7.5.5", + "xtend": "^4.0.2" + }, + "bin": { + "mqtt": "bin/mqtt.js", + "mqtt_pub": "bin/pub.js", + "mqtt_sub": "bin/sub.js" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/mqtt-packet": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/mqtt-packet/-/mqtt-packet-6.10.0.tgz", + "integrity": "sha512-ja8+mFKIHdB1Tpl6vac+sktqy3gA8t9Mduom1BA75cI+R9AHnZOiaBQwpGiWnaVJLDGRdNhQmFaAqd7tkKSMGA==", + "dependencies": { + "bl": "^4.0.2", + "debug": "^4.1.1", + "process-nextick-args": "^2.0.1" + } + }, + "node_modules/mqtt/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/nan": { + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.16.0.tgz", + "integrity": "sha512-UdAqHyFngu7TfQKsCBgAA6pWDkT8MAO7d0jyOecVhN5354xbLqdn8mV9Tat9gepAupm0bt2DbeaSC8vS52MuFA==" + }, + "node_modules/napi-build-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", + "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==" + }, + "node_modules/node-abi": { + "version": "3.22.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.22.0.tgz", + "integrity": "sha512-u4uAs/4Zzmp/jjsD9cyFYDXeISfUWaAVWshPmDZOFOv4Xl4SbzTXm53I04C2uRueYJ+0t5PEtLH/owbn2Npf/w==", + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/nodemailer": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.7.tgz", + "integrity": "sha512-rUtR77ksqex/eZRLmQ21LKVH5nAAsVicAtAYudK7JgwenEDZ0UIQ1adUGqErz7sMkWYxWTTU1aeP2Jga6WQyJw==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "dependencies": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "node_modules/number-allocator": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/number-allocator/-/number-allocator-1.0.14.tgz", + "integrity": "sha512-OrL44UTVAvkKdOdRQZIJpLkAdjXGTRda052sN4sO77bKEzYYqWKMBjQvrJFzqygI99gL6Z4u2xctPW1tB8ErvA==", + "dependencies": { + "debug": "^4.3.1", + "js-sdsl": "4.3.0" + } + }, + "node_modules/number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/prebuild-install": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.0.tgz", + "integrity": "sha512-CNcMgI1xBypOyGqjp3wOc8AAo1nMhZS3Cwd3iHIxOdAUbb+YxdNuM4Z5iIrZ8RLvOsf3F3bl7b7xGq6DjQoNYA==", + "dependencies": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^1.0.1", + "node-abi": "^3.3.0", + "npmlog": "^4.0.1", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + }, + "bin": { + "prebuild-install": "bin.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/reinterval": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reinterval/-/reinterval-1.1.0.tgz", + "integrity": "sha1-M2Hs+jymwYKDOA3Qu5VG85D17Oc=" + }, + "node_modules/rfdc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==" + }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/serialport": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/serialport/-/serialport-9.2.8.tgz", + "integrity": "sha512-FsWpMQgSJxi93JgWl5xM1f9/Z8IjRJuaUEoHqLf8FPBLw7gMhInuHOBhI2onQufWIYPGTz3H3oGcu1nCaK1EfA==", + "dependencies": { + "@serialport/binding-mock": "9.2.4", + "@serialport/bindings": "9.2.8", + "@serialport/parser-byte-length": "9.2.4", + "@serialport/parser-cctalk": "9.2.4", + "@serialport/parser-delimiter": "9.2.4", + "@serialport/parser-inter-byte-timeout": "9.2.4", + "@serialport/parser-readline": "9.2.4", + "@serialport/parser-ready": "9.2.4", + "@serialport/parser-regex": "9.2.4", + "@serialport/stream": "9.2.4", + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "node_modules/split2": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", + "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", + "dependencies": { + "readable-stream": "^3.0.0" + } + }, + "node_modules/split2/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==" + }, + "node_modules/streamroller": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.1.1.tgz", + "integrity": "sha512-iPhtd9unZ6zKdWgMeYGfSBuqCngyJy1B/GPi/lTpwGpa3bajuX30GjUVd0/Tn/Xhg0mr4DOSENozz9Y06qyonQ==", + "dependencies": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "fs-extra": "^10.1.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dependencies": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/tar-fs": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "dependencies": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tar-stream/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/total.js": { + "version": "3.4.13", + "resolved": "https://registry.npmjs.org/total.js/-/total.js-3.4.13.tgz", + "integrity": "sha512-lAH4gEixlPFbrE3xfKADAcHfO79IFq2wKa9GTsrgRzIR5MTg3mNH7+4IxvX1pK8faoYb/0oYSJ1YTsAa5hIFFQ==", + "bin": { + "total": "bin/totaljs", + "total.js": "bin/totaljs", + "totaljs": "bin/totaljs", + "totalpackage": "bin/tpm", + "tpm": "bin/tpm" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, + "node_modules/universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "node_modules/wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "node_modules/ws": { + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } + }, + "dependencies": { + "@serialport/binding-abstract": { + "version": "9.2.3", + "resolved": "https://registry.npmjs.org/@serialport/binding-abstract/-/binding-abstract-9.2.3.tgz", + "integrity": "sha512-cQs9tbIlG3P0IrOWyVirqlhWuJ7Ms2Zh9m2108z6Y5UW/iVj6wEOiW8EmK9QX9jmJXYllE7wgGgvVozP5oCj3w==", + "requires": { + "debug": "^4.3.2" + } + }, + "@serialport/binding-mock": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/binding-mock/-/binding-mock-9.2.4.tgz", + "integrity": "sha512-dpEhACCs44oQhh6ajJfJdvQdK38Vq0N4W6iD/gdplglDCK7qXRQCMUjJIeKdS/HSEiWkC3bwumUhUufdsOyT4g==", + "requires": { + "@serialport/binding-abstract": "9.2.3", + "debug": "^4.3.2" + } + }, + "@serialport/bindings": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/@serialport/bindings/-/bindings-9.2.8.tgz", + "integrity": "sha512-hSLxTe0tADZ3LMMGwvEJWOC/TaFQTyPeFalUCsJ1lSQ0k6bPF04JwrtB/C81GetmDBTNRY0GlD0SNtKCc7Dr5g==", + "requires": { + "@serialport/binding-abstract": "9.2.3", + "@serialport/parser-readline": "9.2.4", + "bindings": "^1.5.0", + "debug": "^4.3.2", + "nan": "^2.15.0", + "prebuild-install": "^7.0.0" + } + }, + "@serialport/parser-byte-length": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-byte-length/-/parser-byte-length-9.2.4.tgz", + "integrity": "sha512-sQD/iw4ZMU3xW9PLi0/GlvU6Y623jGeWecbMkO7izUo/6P7gtfv1c9ikd5h0kwL8AoAOpQA1lxdHIKox+umBUg==" + }, + "@serialport/parser-cctalk": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-cctalk/-/parser-cctalk-9.2.4.tgz", + "integrity": "sha512-T4TU5vQMwmo9AB3gQLFDWbfJXlW5jd9guEsB/nqKjFHTv0FXPdZ7DQ2TpSp8RnHWxU3GX6kYTaDO20BKzc8GPQ==" + }, + "@serialport/parser-delimiter": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-delimiter/-/parser-delimiter-9.2.4.tgz", + "integrity": "sha512-4nvTAoYAgkxFiXrkI+3CA49Yd43CODjeszh89EK+I9c8wOZ+etZduRCzINYPiy26g7zO+GRAb9FoPCsY+sYcbQ==" + }, + "@serialport/parser-inter-byte-timeout": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-inter-byte-timeout/-/parser-inter-byte-timeout-9.2.4.tgz", + "integrity": "sha512-SOAdvr0oBQIOCXX198hiTlxs4JTKg9j5piapw5tNq52fwDOWdbYrFneT/wN04UTMKaDrJuEvXq6T4rv4j7nJ5A==" + }, + "@serialport/parser-readline": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-readline/-/parser-readline-9.2.4.tgz", + "integrity": "sha512-Z1/qrZTQUVhNSJP1hd9YfDvq0o7d87rNwAjjRKbVpa7Qi51tG5BnKt43IV3NFMyBlVcRe0rnIb3tJu57E0SOwg==", + "requires": { + "@serialport/parser-delimiter": "9.2.4" + } + }, + "@serialport/parser-ready": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-ready/-/parser-ready-9.2.4.tgz", + "integrity": "sha512-Pyi94Itjl6qAURwIZr/gmZpMAyTmKXThm6vL5DoAWGQjcRHWB0gwv2TY2v7N+mQLJYUKU3cMnvnATXxHm7xjxw==" + }, + "@serialport/parser-regex": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-regex/-/parser-regex-9.2.4.tgz", + "integrity": "sha512-sI/cVvPOYz+Dbv4ZdnW16qAwvXiFf/1pGASQdbveRTlgJDdz7sRNlCBifzfTN2xljwvCTZYqiudKvDdC1TepRQ==" + }, + "@serialport/stream": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/stream/-/stream-9.2.4.tgz", + "integrity": "sha512-bLye8Ub4vUFQGmkh8qEqehr7SE7EJs2yDs0h9jzuL5oKi+F34CFmWkEErO8GAOQ8YNn7p6b3GxUgs+0BrHHDZQ==", + "requires": { + "debug": "^4.3.2" + } + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==" + }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "are-we-there-yet": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", + "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "base64-js": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", + "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==" + }, + "bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "requires": { + "file-uri-to-path": "1.0.0" + } + }, + "bitwise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/bitwise/-/bitwise-2.1.0.tgz", + "integrity": "sha512-XKgAhMXCh4H/3oNwAHAsAO0iC89s9cOiumgYwSHjSobGWxYjv62YhkL9QEdvGP151xypCtMlAfKK79GEcd2eRQ==" + }, + "bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "requires": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "buffer": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz", + "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==", + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" + }, + "chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==" + }, + "commist": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/commist/-/commist-1.1.0.tgz", + "integrity": "sha512-rraC8NXWOEjhADbZe9QBNzLAN5Q3fsTPQtBV+fEVj6xKIgDgNiEVE6ZNfHpZOqfQ21YUzfVNUXLOEZquYvQPPg==", + "requires": { + "leven": "^2.1.0", + "minimist": "^1.1.0" + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "concat-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", + "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.0.2", + "typedarray": "^0.0.6" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "crc": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/crc/-/crc-3.4.0.tgz", + "integrity": "sha512-ycVC2+4/DLgXXq7QweYi2znhqDuZz6P5TQXnkQo8v15XY/5p/IWeZwsSE31Ifo8w15b8TWLsqhXOjXyilHuQxw==" + }, + "date-format": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.11.tgz", + "integrity": "sha512-VS20KRyorrbMCQmpdl2hg5KaOUsda1RbnsJg461FfrcyCUg+pkd0b40BSW4niQyTheww4DBXQnS7HwSrKkipLw==" + }, + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "requires": { + "ms": "2.1.2" + } + }, + "decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "requires": { + "mimic-response": "^3.1.0" + } + }, + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==" + }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" + }, + "detect-libc": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz", + "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==" + }, + "duplexify": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.2.tgz", + "integrity": "sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw==", + "requires": { + "end-of-stream": "^1.4.1", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1", + "stream-shift": "^1.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "easy-crc": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/easy-crc/-/easy-crc-0.0.2.tgz", + "integrity": "sha512-h6eqIdhJRe0p271/xZJbM/0klCi13mW5IB7ZEzEGH11yV4QXWAkD4yPErz0fXdhFrd6sZ4Q1k5Iky2kMsMNePw==" + }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "requires": { + "once": "^1.4.0" + } + }, + "expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==" + }, + "file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" + }, + "flatted": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", + "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==" + }, + "fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, + "fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha512-14x4kjc6lkD3ltw589k0NrPD6cCNTD6CWoVUNpB85+DrtONoZn+Rug6xZU5RvSC4+TZPxA5AnBibQYAvZn41Hg==", + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==" + }, + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" + }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" + }, + "help-me": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/help-me/-/help-me-3.0.0.tgz", + "integrity": "sha512-hx73jClhyk910sidBB7ERlnhMlFsJJIBqSVMFDwPN8o2v9nmp5KgLq1Xz1Bf1fCMMZ6mPrX159iG0VLy/fPMtQ==", + "requires": { + "glob": "^7.1.6", + "readable-stream": "^3.6.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==", + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "js-sdsl": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz", + "integrity": "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==" + }, + "jsmodbus": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/jsmodbus/-/jsmodbus-4.0.6.tgz", + "integrity": "sha512-gCmjoaERErK5Rn9Lu/BN07fY13MoWV7JKgGzrnkPlQPdPxYcwDhLtYcmpFFpZ4J9NPZZBSezi1UkLZO/DnNppA==", + "requires": { + "crc": "3.4.0", + "debug": "^3.1.0" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "requires": { + "ms": "^2.1.1" + } + } + } + }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, + "leven": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", + "integrity": "sha1-wuep93IJTe6dNCAq6KzORoeHVYA=" + }, + "log4js": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.5.2.tgz", + "integrity": "sha512-DXtpNtt+KDOMT7RHUDIur/WsSA3rntlUh9Zg4XCdV42wUuMmbFkl38+LZ92Z5QvQA7mD5kAVkLiBSEH/tvUB8A==", + "requires": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "flatted": "^3.2.5", + "rfdc": "^1.3.0", + "streamroller": "^3.1.1" + } + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "requires": { + "yallist": "^4.0.0" + } + }, + "mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==" + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==" + }, + "mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" + }, + "moment": { + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", + "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==" + }, + "mqtt": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/mqtt/-/mqtt-4.3.7.tgz", + "integrity": "sha512-ew3qwG/TJRorTz47eW46vZ5oBw5MEYbQZVaEji44j5lAUSQSqIEoul7Kua/BatBW0H0kKQcC9kwUHa1qzaWHSw==", + "requires": { + "commist": "^1.0.0", + "concat-stream": "^2.0.0", + "debug": "^4.1.1", + "duplexify": "^4.1.1", + "help-me": "^3.0.0", + "inherits": "^2.0.3", + "lru-cache": "^6.0.0", + "minimist": "^1.2.5", + "mqtt-packet": "^6.8.0", + "number-allocator": "^1.0.9", + "pump": "^3.0.0", + "readable-stream": "^3.6.0", + "reinterval": "^1.1.0", + "rfdc": "^1.3.0", + "split2": "^3.1.0", + "ws": "^7.5.5", + "xtend": "^4.0.2" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "mqtt-packet": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/mqtt-packet/-/mqtt-packet-6.10.0.tgz", + "integrity": "sha512-ja8+mFKIHdB1Tpl6vac+sktqy3gA8t9Mduom1BA75cI+R9AHnZOiaBQwpGiWnaVJLDGRdNhQmFaAqd7tkKSMGA==", + "requires": { + "bl": "^4.0.2", + "debug": "^4.1.1", + "process-nextick-args": "^2.0.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "nan": { + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.16.0.tgz", + "integrity": "sha512-UdAqHyFngu7TfQKsCBgAA6pWDkT8MAO7d0jyOecVhN5354xbLqdn8mV9Tat9gepAupm0bt2DbeaSC8vS52MuFA==" + }, + "napi-build-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", + "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==" + }, + "node-abi": { + "version": "3.22.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.22.0.tgz", + "integrity": "sha512-u4uAs/4Zzmp/jjsD9cyFYDXeISfUWaAVWshPmDZOFOv4Xl4SbzTXm53I04C2uRueYJ+0t5PEtLH/owbn2Npf/w==", + "requires": { + "semver": "^7.3.5" + } + }, + "nodemailer": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.7.tgz", + "integrity": "sha512-rUtR77ksqex/eZRLmQ21LKVH5nAAsVicAtAYudK7JgwenEDZ0UIQ1adUGqErz7sMkWYxWTTU1aeP2Jga6WQyJw==" + }, + "npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "number-allocator": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/number-allocator/-/number-allocator-1.0.14.tgz", + "integrity": "sha512-OrL44UTVAvkKdOdRQZIJpLkAdjXGTRda052sN4sO77bKEzYYqWKMBjQvrJFzqygI99gL6Z4u2xctPW1tB8ErvA==", + "requires": { + "debug": "^4.3.1", + "js-sdsl": "4.3.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==" + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==" + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==" + }, + "prebuild-install": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.0.tgz", + "integrity": "sha512-CNcMgI1xBypOyGqjp3wOc8AAo1nMhZS3Cwd3iHIxOdAUbb+YxdNuM4Z5iIrZ8RLvOsf3F3bl7b7xGq6DjQoNYA==", + "requires": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^1.0.1", + "node-abi": "^3.3.0", + "npmlog": "^4.0.1", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + } + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + } + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "reinterval": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reinterval/-/reinterval-1.1.0.tgz", + "integrity": "sha1-M2Hs+jymwYKDOA3Qu5VG85D17Oc=" + }, + "rfdc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==" + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "requires": { + "lru-cache": "^6.0.0" + } + }, + "serialport": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/serialport/-/serialport-9.2.8.tgz", + "integrity": "sha512-FsWpMQgSJxi93JgWl5xM1f9/Z8IjRJuaUEoHqLf8FPBLw7gMhInuHOBhI2onQufWIYPGTz3H3oGcu1nCaK1EfA==", + "requires": { + "@serialport/binding-mock": "9.2.4", + "@serialport/bindings": "9.2.8", + "@serialport/parser-byte-length": "9.2.4", + "@serialport/parser-cctalk": "9.2.4", + "@serialport/parser-delimiter": "9.2.4", + "@serialport/parser-inter-byte-timeout": "9.2.4", + "@serialport/parser-readline": "9.2.4", + "@serialport/parser-ready": "9.2.4", + "@serialport/parser-regex": "9.2.4", + "@serialport/stream": "9.2.4", + "debug": "^4.3.2" + } + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==" + }, + "simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "requires": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "split2": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", + "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", + "requires": { + "readable-stream": "^3.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==" + }, + "streamroller": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.1.1.tgz", + "integrity": "sha512-iPhtd9unZ6zKdWgMeYGfSBuqCngyJy1B/GPi/lTpwGpa3bajuX30GjUVd0/Tn/Xhg0mr4DOSENozz9Y06qyonQ==", + "requires": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "fs-extra": "^10.1.0" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" + }, + "tar-fs": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "requires": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "requires": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "total.js": { + "version": "3.4.13", + "resolved": "https://registry.npmjs.org/total.js/-/total.js-3.4.13.tgz", + "integrity": "sha512-lAH4gEixlPFbrE3xfKADAcHfO79IFq2wKa9GTsrgRzIR5MTg3mNH7+4IxvX1pK8faoYb/0oYSJ1YTsAa5hIFFQ==" + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, + "universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==" + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "requires": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "ws": { + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "requires": {} + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } + } +} diff --git a/RVO12/package.json b/RVO12/package.json new file mode 100755 index 0000000..7f7c795 --- /dev/null +++ b/RVO12/package.json @@ -0,0 +1,30 @@ +{ + "name": "emptyproject", + "description": "Total.js empty project.", + "version": "1.0.0", + "main": "debug.js", + "dependencies": { + "bitwise": "^2.1.0", + "easy-crc": "0.0.2", + "jsmodbus": "^4.0.6", + "log4js": "^6.3.0", + "moment": "^2.30.1", + "mqtt": "^4.2.6", + "nodemailer": "^6.9.7", + "serialport": "^9.2.8", + "total.js": "^3.4.13" + }, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "https://github.com/totaljs/emptyproject-flow" + }, + "keywords": [ + "empty", + "project" + ], + "author": "Peter Širka", + "license": "MIT" +} diff --git a/RVO12/release.js b/RVO12/release.js new file mode 100755 index 0000000..02d52ff --- /dev/null +++ b/RVO12/release.js @@ -0,0 +1,15 @@ +// =================================================== +// FOR PRODUCTION +// Total.js - framework for Node.js platform +// https://www.totaljs.com +// =================================================== + +const options = {'ip':'0.0.0.0', 'port':12345}; + +// options.ip = '127.0.0.1'; +// options.port = parseInt(process.argv[2]); +// options.config = { name: 'Total.js' }; +// options.sleep = 3000; + +require('total.js').http('release', options); +// require('total.js').cluster.http(5, 'release', options); diff --git a/RVO12/release.js.json b/RVO12/release.js.json new file mode 100755 index 0000000..ab2a334 --- /dev/null +++ b/RVO12/release.js.json @@ -0,0 +1,34 @@ +{ + "pid": 416, + "stats": [ + { + "id": null, + "version": { + "node": "v14.18.1", + "total": "3.4.13", + "app": "1.0.0" + }, + "pid": 416, + "thread": "", + "mode": "release", + "overload": 0, + "date": "2025-10-16T00:23:26.526Z", + "memory": 28.83, + "rm": 0, + "fm": 0, + "wm": 0, + "mm": 0, + "om": 10, + "em": 0, + "dbrm": 0, + "dbwm": 0, + "usage": 0, + "requests": 7, + "pending": 0, + "errors": 0, + "timeouts": 0, + "uptime": 859, + "online": 0 + } + ] +} \ No newline at end of file diff --git a/RVO12/report_data.log b/RVO12/report_data.log new file mode 100755 index 0000000..d13597d --- /dev/null +++ b/RVO12/report_data.log @@ -0,0 +1,181 @@ +{ + "name": "rvo_senica_12_ip112", + "time": "2025-10-15T11:05:41.559Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_12_ip112", + "time": "2025-10-15T12:05:41.557Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_12_ip112", + "time": "2025-10-15T13:05:41.557Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_12_ip112", + "time": "2025-10-15T14:05:41.557Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_12_ip112", + "time": "2025-10-15T15:05:41.558Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_12_ip112", + "time": "2025-10-15T17:33:37.600Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_12_ip112", + "time": "2025-10-15T18:33:37.600Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_12_ip112", + "time": "2025-10-15T19:33:37.602Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_12_ip112", + "time": "2025-10-15T20:33:37.603Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_12_ip112", + "time": "2025-10-15T21:33:37.603Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_12_ip112", + "time": "2025-10-15T22:33:37.604Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_12_ip112", + "time": "2025-10-15T23:33:37.604Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +} \ No newline at end of file From 1ee6e66bf43ee39cccc9d93b29104e95ae98f8ae Mon Sep 17 00:00:00 2001 From: Jakub Klena Date: Thu, 16 Oct 2025 02:23:55 +0200 Subject: [PATCH 06/30] Backup senica-RVO13 on 16.10.2025 --- RVO13/addSwitch.py | 36 + RVO13/cloud_topic.py | 76 + RVO13/config | 12 + RVO13/createNode.py | 43 + RVO13/databases/accelerometer_db.js | 3055 +++++ RVO13/databases/modbus_config.js | 114 + RVO13/databases/nodes.table | 136 + .../nodes_original/nodes_original.table | 1 + RVO13/databases/notifications.table | 41 + RVO13/databases/pins.table | 15 + RVO13/databases/relays.table | 6 + RVO13/databases/settings.table | 2 + RVO13/databases/tbdata.nosql | 6 + RVO13/databases/tbdatacloud.nosql | 3 + RVO13/databases/total_energy.js | 38 + RVO13/debug.js | 16 + RVO13/err.txt | 33 + RVO13/flow/cloudmqttconnect.js | 357 + RVO13/flow/cmd_manager.js | 3071 +++++ RVO13/flow/code.js | 90 + RVO13/flow/comment.js | 11 + RVO13/flow/count.js | 60 + RVO13/flow/db_connector.js | 286 + RVO13/flow/db_init.js | 113 + RVO13/flow/debug.js | 100 + RVO13/flow/designer.json | 3102 +++++ RVO13/flow/dido_controller.js | 1486 +++ RVO13/flow/helper/DataToTbHandler.js | 187 + RVO13/flow/helper/ErrorToServiceHandler.js | 91 + RVO13/flow/helper/db_helper.js | 44 + RVO13/flow/helper/logger.js | 30 + RVO13/flow/helper/md5.js | 5 + RVO13/flow/helper/notification_reporter.js | 121 + RVO13/flow/helper/register.js | 144 + RVO13/flow/helper/serialport_helper.js | 99 + RVO13/flow/helper/suncalc.js | 317 + RVO13/flow/helper/utils.js | 161 + RVO13/flow/httprequest.js | 137 + RVO13/flow/httpresponse.js | 76 + RVO13/flow/httproute.js | 326 + RVO13/flow/infosender.js | 81 + RVO13/flow/modbus_reader.js | 346 + RVO13/flow/monitorconsumption.js | 156 + RVO13/flow/monitordisk.js | 96 + RVO13/flow/monitormemory.js | 87 + RVO13/flow/nodesdb_changecheck.js | 77 + RVO13/flow/show_dbdata.js | 243 + RVO13/flow/slack_filter.js | 188 + RVO13/flow/thermometer.js | 98 + RVO13/flow/trigger.js | 79 + RVO13/flow/variables.txt | 0 RVO13/flow/virtualwirein.js | 43 + RVO13/flow/virtualwireout.js | 41 + RVO13/flow/wsmqttpublish.js | 448 + RVO13/flow_3_2_25/cloudmqttconnect.js | 374 + RVO13/flow_3_2_25/cmd_manager.js | 2988 +++++ RVO13/flow_3_2_25/code.js | 90 + RVO13/flow_3_2_25/comment.js | 11 + RVO13/flow_3_2_25/db_connector.js | 286 + RVO13/flow_3_2_25/db_init.js | 106 + RVO13/flow_3_2_25/debug.js | 100 + RVO13/flow_3_2_25/designer.json | 2846 ++++ RVO13/flow_3_2_25/dido_controller.js | 1524 +++ RVO13/flow_3_2_25/helper/DataToTbHandler.js | 166 + .../helper/ErrorToServiceHandler.js | 126 + RVO13/flow_3_2_25/helper/db_helper.js | 44 + RVO13/flow_3_2_25/helper/logger.js | 30 + RVO13/flow_3_2_25/helper/md5.js | 5 + .../helper/notification_reporter.js | 131 + RVO13/flow_3_2_25/helper/register.js | 144 + RVO13/flow_3_2_25/helper/serialport_helper.js | 100 + RVO13/flow_3_2_25/helper/suncalc.js | 317 + RVO13/flow_3_2_25/helper/utils.js | 124 + RVO13/flow_3_2_25/httprequest.js | 137 + RVO13/flow_3_2_25/httpresponse.js | 76 + RVO13/flow_3_2_25/httproute.js | 326 + RVO13/flow_3_2_25/infosender.js | 101 + RVO13/flow_3_2_25/modbus_reader.js | 367 + RVO13/flow_3_2_25/monitorconsumption.js | 156 + RVO13/flow_3_2_25/monitordisk.js | 96 + RVO13/flow_3_2_25/monitormemory.js | 87 + RVO13/flow_3_2_25/nodesdb_changecheck.js | 70 + RVO13/flow_3_2_25/show_dbdata.js | 241 + RVO13/flow_3_2_25/slack_filter.js | 187 + RVO13/flow_3_2_25/thermometer.js | 98 + RVO13/flow_3_2_25/trigger.js | 79 + RVO13/flow_3_2_25/variables.txt | 0 RVO13/flow_3_2_25/virtualwirein.js | 43 + RVO13/flow_3_2_25/virtualwireout.js | 41 + RVO13/flow_3_2_25/wsmqttpublish.js | 477 + RVO13/monitor.txt | 11116 ++++++++++++++++ RVO13/package-lock.json | 2139 +++ RVO13/package.json | 30 + RVO13/release.js | 15 + RVO13/release.js.json | 34 + RVO13/report_data.log | 210 + 96 files changed, 41668 insertions(+) create mode 100755 RVO13/addSwitch.py create mode 100755 RVO13/cloud_topic.py create mode 100755 RVO13/config create mode 100755 RVO13/createNode.py create mode 100755 RVO13/databases/accelerometer_db.js create mode 100755 RVO13/databases/modbus_config.js create mode 100755 RVO13/databases/nodes.table create mode 100755 RVO13/databases/nodes_original/nodes_original.table create mode 100755 RVO13/databases/notifications.table create mode 100755 RVO13/databases/pins.table create mode 100755 RVO13/databases/relays.table create mode 100755 RVO13/databases/settings.table create mode 100755 RVO13/databases/tbdata.nosql create mode 100755 RVO13/databases/tbdatacloud.nosql create mode 100755 RVO13/databases/total_energy.js create mode 100755 RVO13/debug.js create mode 100755 RVO13/err.txt create mode 100755 RVO13/flow/cloudmqttconnect.js create mode 100755 RVO13/flow/cmd_manager.js create mode 100755 RVO13/flow/code.js create mode 100755 RVO13/flow/comment.js create mode 100755 RVO13/flow/count.js create mode 100755 RVO13/flow/db_connector.js create mode 100755 RVO13/flow/db_init.js create mode 100755 RVO13/flow/debug.js create mode 100755 RVO13/flow/designer.json create mode 100755 RVO13/flow/dido_controller.js create mode 100755 RVO13/flow/helper/DataToTbHandler.js create mode 100755 RVO13/flow/helper/ErrorToServiceHandler.js create mode 100755 RVO13/flow/helper/db_helper.js create mode 100755 RVO13/flow/helper/logger.js create mode 100755 RVO13/flow/helper/md5.js create mode 100755 RVO13/flow/helper/notification_reporter.js create mode 100755 RVO13/flow/helper/register.js create mode 100755 RVO13/flow/helper/serialport_helper.js create mode 100755 RVO13/flow/helper/suncalc.js create mode 100755 RVO13/flow/helper/utils.js create mode 100755 RVO13/flow/httprequest.js create mode 100755 RVO13/flow/httpresponse.js create mode 100755 RVO13/flow/httproute.js create mode 100755 RVO13/flow/infosender.js create mode 100755 RVO13/flow/modbus_reader.js create mode 100755 RVO13/flow/monitorconsumption.js create mode 100755 RVO13/flow/monitordisk.js create mode 100755 RVO13/flow/monitormemory.js create mode 100755 RVO13/flow/nodesdb_changecheck.js create mode 100755 RVO13/flow/show_dbdata.js create mode 100755 RVO13/flow/slack_filter.js create mode 100755 RVO13/flow/thermometer.js create mode 100755 RVO13/flow/trigger.js create mode 100755 RVO13/flow/variables.txt create mode 100755 RVO13/flow/virtualwirein.js create mode 100755 RVO13/flow/virtualwireout.js create mode 100755 RVO13/flow/wsmqttpublish.js create mode 100755 RVO13/flow_3_2_25/cloudmqttconnect.js create mode 100755 RVO13/flow_3_2_25/cmd_manager.js create mode 100755 RVO13/flow_3_2_25/code.js create mode 100755 RVO13/flow_3_2_25/comment.js create mode 100755 RVO13/flow_3_2_25/db_connector.js create mode 100755 RVO13/flow_3_2_25/db_init.js create mode 100755 RVO13/flow_3_2_25/debug.js create mode 100755 RVO13/flow_3_2_25/designer.json create mode 100755 RVO13/flow_3_2_25/dido_controller.js create mode 100755 RVO13/flow_3_2_25/helper/DataToTbHandler.js create mode 100755 RVO13/flow_3_2_25/helper/ErrorToServiceHandler.js create mode 100755 RVO13/flow_3_2_25/helper/db_helper.js create mode 100755 RVO13/flow_3_2_25/helper/logger.js create mode 100755 RVO13/flow_3_2_25/helper/md5.js create mode 100755 RVO13/flow_3_2_25/helper/notification_reporter.js create mode 100755 RVO13/flow_3_2_25/helper/register.js create mode 100755 RVO13/flow_3_2_25/helper/serialport_helper.js create mode 100755 RVO13/flow_3_2_25/helper/suncalc.js create mode 100755 RVO13/flow_3_2_25/helper/utils.js create mode 100755 RVO13/flow_3_2_25/httprequest.js create mode 100755 RVO13/flow_3_2_25/httpresponse.js create mode 100755 RVO13/flow_3_2_25/httproute.js create mode 100755 RVO13/flow_3_2_25/infosender.js create mode 100755 RVO13/flow_3_2_25/modbus_reader.js create mode 100755 RVO13/flow_3_2_25/monitorconsumption.js create mode 100755 RVO13/flow_3_2_25/monitordisk.js create mode 100755 RVO13/flow_3_2_25/monitormemory.js create mode 100755 RVO13/flow_3_2_25/nodesdb_changecheck.js create mode 100755 RVO13/flow_3_2_25/show_dbdata.js create mode 100755 RVO13/flow_3_2_25/slack_filter.js create mode 100755 RVO13/flow_3_2_25/thermometer.js create mode 100755 RVO13/flow_3_2_25/trigger.js create mode 100755 RVO13/flow_3_2_25/variables.txt create mode 100755 RVO13/flow_3_2_25/virtualwirein.js create mode 100755 RVO13/flow_3_2_25/virtualwireout.js create mode 100755 RVO13/flow_3_2_25/wsmqttpublish.js create mode 100755 RVO13/monitor.txt create mode 100755 RVO13/package-lock.json create mode 100755 RVO13/package.json create mode 100755 RVO13/release.js create mode 100755 RVO13/release.js.json create mode 100755 RVO13/report_data.log diff --git a/RVO13/addSwitch.py b/RVO13/addSwitch.py new file mode 100755 index 0000000..c35e96b --- /dev/null +++ b/RVO13/addSwitch.py @@ -0,0 +1,36 @@ +import os + +def process_set_file(): + """ + Checks if /root/flowserver exists, reads set.txt, and modifies the second line. + """ + default_folder = "/root/flowserver" if os.path.exists("/root/flowserver") else "/home/unipi/flowserver" + flag = 1 if default_folder == "/root/flowserver" else 0 + + try: + with open("/home/unipi/flowserver/databases/settings.table", "r") as f: + lines = f.readlines() + + if len(lines) >= 2: + lines[0] = lines[0].rstrip('\n') + "|main_switch:boolean\n" + second_line = lines[1].strip() # remove trailing newline + last_pipe_index = second_line.rfind("|") + + if last_pipe_index != -1: + modified_line = second_line[:last_pipe_index + 1] + str(flag) + "|" + second_line[last_pipe_index + 1:] + lines[1] = modified_line + else: + print("Warning: No '|' character found in the second line of set.txt") + + with open("/home/unipi/flowserver/databases/settings.table", "w") as f: + f.writelines(lines) + else: + print("Warning: settings.table has less than two lines.") + + except FileNotFoundError: + print("Error: settings.table not found.") + except Exception as e: + print(e) + +# if __name__ == "__main__": +process_set_file() diff --git a/RVO13/cloud_topic.py b/RVO13/cloud_topic.py new file mode 100755 index 0000000..77c31f1 --- /dev/null +++ b/RVO13/cloud_topic.py @@ -0,0 +1,76 @@ +# import os +# +# def modify_file(file_path): +# """ +# Modifies the given file by: +# 1. Appending "|cloud_topic" to the first line. +# 2. Inserting the text from the third "." to the first "|" on the second line after the last "|" character. +# +# Args: +# file_path (str): The path to the file to be modified. +# """ +# +# with open(file_path, 'r+') as f: +# lines = f.readlines() +# +# # Modify the first line +# lines[0] += "|cloud_topic:string" +# +# # Modify the second line +# second_line = lines[1].strip() # Remove leading/trailing whitespace +# first_pipe_index = second_line.find('|') +# third_dot_index = second_line.find('.', second_line.find('.', second_line.find('.') + 1) + 1) +# text_to_insert = second_line[third_dot_index:first_pipe_index] +# +# last_pipe_index = second_line.rfind('|') +# lines[1] = second_line[:last_pipe_index + 1] + text_to_insert + "|" + second_line[last_pipe_index + 1:] +# +# print(first_pipe_index, third_dot_index, text_to_insert, last_pipe_index) +# # Write the modified lines back to the file +# # f.seek(0) +# # f.writelines(lines) +# # f.truncate() +# +# # Example usage: +# file_path = "settings.table" # Replace with the actual file path +# modify_file(file_path) +# + + +def modify_file(file_path): + """ + Modifies the given file by: + 1. Appending "|cloud_topic" to the first line. + 2. Inserting the text between the third "." and the second "|" on the second line after the last "|" character. + + Args: + file_path (str): The path to the file to be modified. + """ + + with open(file_path, 'r+') as f: + lines = f.readlines() + + first_line = lines[0].strip() + first_line += "|cloud_topic:string\n" + # Modify the first line + lines[0] = first_line + + # Modify the second line + second_line = lines[1].strip() # Remove leading/trailing whitespace + first_pipe_index = second_line.find('|') + second_pipe_index = second_line.find('|', first_pipe_index + 1) + third_dot_index = second_line.find('.', second_line.find('.', second_line.find('.') + 1) + 1) + text_to_insert = "u" + second_line[third_dot_index+1:second_pipe_index] + + last_pipe_index = second_line.rfind('|') + lines[1] = second_line[:last_pipe_index + 1] + text_to_insert + "|" + second_line[last_pipe_index + 1:] + + print(first_pipe_index, third_dot_index, text_to_insert, last_pipe_index) + # Write the modified lines back to the file + f.seek(0) + f.writelines(lines) + f.truncate() + +# Example usage: +file_path = "/home/unipi/flowserver/databases/settings.table" # Replace with the actual file path +modify_file(file_path) diff --git a/RVO13/config b/RVO13/config new file mode 100755 index 0000000..cd0a8a9 --- /dev/null +++ b/RVO13/config @@ -0,0 +1,12 @@ +name : Total.js Flow +default_timezone : Europe/Bratislava + +// Packages settings +package#flow (Object) : { url: '/' } + + +table.relays : line:number|tbname:string|contactor:number|profile:string +table.nodes : node:number|pole_number:string|node_type:string|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|project_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|cloud_topic:string|has_main_switch:boolean|daily_report:boolean|send_changed_node_numbers:boolean +table.pins : pin:string|type:string|line:number +table.notifications : key:string|weight:string|sk:string|en:string diff --git a/RVO13/createNode.py b/RVO13/createNode.py new file mode 100755 index 0000000..a8cea91 --- /dev/null +++ b/RVO13/createNode.py @@ -0,0 +1,43 @@ +print("zaciname") +import re, json + +search_str = '|' +final = [] +counter = 1 +with open("/home/unipi/flowserver/databases/nodes.table", 'r') as file: +# with open("/home/rasta5man/dev/oms/flowserver/databases/nodes.table", 'r') as file: + # Read each line in the file + for line in file: + # Print each line + line = line.strip() + print(line) + if counter != 1: + i = [m.start() for m in re.finditer(re.escape(search_str), line)] + node = line[ i[0] + 1 : i[1] ] + tbname = line[ i[3] + 1 : i[4] ] + final.append({node:tbname}) + counter += 1 +print(json.dumps(final)) +f = open("/home/unipi/flowserver/databases/nodes_original/nodes_original.table", "w") +f.write(json.dumps(final)) +f.close() + + +# +# # ``d`` has to be replaced with a different character +# old_character = "'" +# +# # ``t`` will replace ``d` +# new_character = '"' +# resultant_string = 0; +# with open("/home/unipi/flowserver/databases/nodes_original/nodes_original.table", 'r') as file: +# for line in file: +# resultant_string = re.sub("'", '"', line) +# +# resultant_string = re.sub(" ", "", resultant_string) +# print(resultant_string) +# +# f = open("/home/unipi/flowserver/databases/nodes_original/nodes_original.table", "w") +# f.write(str(resultant_string)) +# f.close() +# diff --git a/RVO13/databases/accelerometer_db.js b/RVO13/databases/accelerometer_db.js new file mode 100755 index 0000000..fdfc7fd --- /dev/null +++ b/RVO13/databases/accelerometer_db.js @@ -0,0 +1,3055 @@ +let naklony = { + "3993": { "label": "1/3A", "naklon": 0 }, + "3989": { "label": "1/3B", "naklon": 15 }, + "3976": { "label": "1/1", "naklon": 0 }, + "4181": { "label": "1/2", "naklon": 0 }, + "4376": { "label": "1/4", "naklon": 15 }, + "3868": { "label": "1/5", "naklon": 15 }, + "3728": { "label": "1/6", "naklon": 15 }, + "3730": { "label": "1/7", "naklon": 0 }, + "4374": { "label": "1/8", "naklon": 0 }, + "3718": { "label": "1/9", "naklon": 15 }, + "4375": { "label": "1/10", "naklon": 15 }, + "4172": { "label": "1/11", "naklon": 15 }, + "4176": { "label": "1/12", "naklon": 15 }, + "3800": { "label": "2/1", "naklon": 5 }, + "3823": { "label": "2/2", "naklon": 5 }, + "3905": { "label": "2/3", "naklon": 5 }, + "3803": { "label": "2/4", "naklon": 5 }, + "3817": { "label": "2/5", "naklon": 5 }, + "3818": { "label": "2/6", "naklon": 5 }, + "3811": { "label": "2/7", "naklon": 5 }, + "3915": { "label": "2/8", "naklon": 5 }, + "3843": { "label": "2/9", "naklon": 10 }, + "3827": { "label": "2/10", "naklon": 10 }, + "4220": { "label": "2/11", "naklon": 10 }, + "3826": { "label": "2/12", "naklon": 10 }, + "3834": { "label": "2/13", "naklon": 10 }, + "3838": { "label": "2/14", "naklon": 10 }, + "2823": { "label": "2/15", "naklon": 10 }, + "3750": { "label": "2/16", "naklon": 10 }, + "3378": { "label": "2/17", "naklon": 0 }, + "3376": { "label": "2/18", "naklon": 0 }, + "3379": { "label": "2/19", "naklon": 0 }, + "3285": { "label": "2/20", "naklon": 0 }, + "3382": { "label": "2/21", "naklon": 0 }, + "3383": { "label": "2/22", "naklon": 0 }, + "3375": { "label": "2/24", "naklon": 0 }, + "3381": { "label": "2/25", "naklon": 0 }, + "3380": { "label": "2/26", "naklon": 0 }, + "3828": { "label": "2/27", "naklon": 10 }, + "3377": { "label": "2/28", "naklon": 0 }, + "3591": { "label": "7/1", "naklon": 0 }, + "3587": { "label": "7/2", "naklon": 0 }, + "3468": { "label": "7/3", "naklon": 0 }, + "3466": { "label": "7/4", "naklon": 0 }, + "3474": { "label": "7/5", "naklon": 0 }, + "3481": { "label": "7/6", "naklon": 0 }, + "3589": { "label": "7/7", "naklon": 0 }, + "3472": { "label": "7/8", "naklon": 0 }, + "3473": { "label": "7/9", "naklon": 0 }, + "3584": { "label": "7/10", "naklon": 0 }, + "3571": { "label": "7/11", "naklon": 0 }, + "3476": { "label": "7/12", "naklon": 0 }, + "3590": { "label": "7/13", "naklon": 0 }, + "3478": { "label": "7/14", "naklon": 0 }, + "3471": { "label": "7/15", "naklon": 0 }, + "3467": { "label": "7/16", "naklon": 0 }, + "3479": { "label": "7/17", "naklon": 0 }, + "3480": { "label": "7/18", "naklon": 0 }, + "3477": { "label": "7/19", "naklon": 0 }, + "3362": { "label": "12/1", "naklon": 0 }, + "3355": { "label": "12/2", "naklon": 0 }, + "3356": { "label": "12/3", "naklon": 0 }, + "3349": { "label": "12/4", "naklon": 0 }, + "3357": { "label": "12/5", "naklon": 0 }, + "3350": { "label": "12/6", "naklon": 0 }, + "3353": { "label": "12/7", "naklon": 0 }, + "3539": { "label": "12/8", "naklon": 0 }, + "3050": { "label": "12/9", "naklon": 0 }, + "3361": { "label": "12/10", "naklon": 0 }, + "3360": { "label": "12/11", "naklon": 0 }, + "3358": { "label": "12/12", "naklon": 0 }, + "3541": { "label": "12/13", "naklon": 0 }, + "3551": { "label": "12/14", "naklon": 0 }, + "3514": { "label": "12/15", "naklon": 0 }, + "3547": { "label": "12/16", "naklon": 0 }, + "3562": { "label": "12/17", "naklon": 0 }, + "3525": { "label": "12/18", "naklon": 0 }, + "3558": { "label": "12/19", "naklon": 0 }, + "3511": { "label": "12/20", "naklon": 0 }, + "3058": { "label": "12/21", "naklon": 0 }, + "3062": { "label": "12/22", "naklon": 0 }, + "3070": { "label": "12/23", "naklon": 0 }, + "3447": { "label": "12/24", "naklon": 0 }, + "3056": { "label": "12/25", "naklon": 0 }, + "3057": { "label": "12/26", "naklon": 0 }, + "3071": { "label": "12/27", "naklon": 0 }, + "3061": { "label": "12/28", "naklon": 0 }, + "3069": { "label": "12/29", "naklon": 0 }, + "3077": { "label": "12/30", "naklon": 0 }, + "3080": { "label": "12/31", "naklon": 0 }, + "3081": { "label": "12/32", "naklon": 0 }, + "3078": { "label": "12/33", "naklon": 0 }, + "4037": { "label": "12/34", "naklon": 0 }, + "3067": { "label": "12/35", "naklon": 0 }, + "3051": { "label": "12/36", "naklon": 0 }, + "2924": { "label": "12/37", "naklon": 0 }, + "3060": { "label": "12/38", "naklon": 0 }, + "3073": { "label": "12/39", "naklon": 0 }, + "3469": { "label": "12/40", "naklon": 0 }, + "2923": { "label": "12/41", "naklon": 0 }, + "2925": { "label": "12/42", "naklon": 0 }, + "3359": { "label": "12/43", "naklon": 0 }, + "3055": { "label": "12/44", "naklon": 0 }, + "2922": { "label": "12/45", "naklon": 0 }, + "3084": { "label": "12/46", "naklon": 0 }, + "3064": { "label": "12/47", "naklon": 0 }, + "3066": { "label": "12/48", "naklon": 0 }, + "3072": { "label": "12/49", "naklon": 0 }, + "3415": { "label": "13/13A", "naklon": 0 }, + "3409": { "label": "13/13B", "naklon": 0 }, + "3399": { "label": "13/13C", "naklon": 0 }, + "3410": { "label": "13/29A", "naklon": 0 }, + "3407": { "label": "13/29B", "naklon": 0 }, + "3405": { "label": "13/34A", "naklon": 0 }, + "3404": { "label": "13/34B", "naklon": 0 }, + "3392": { "label": "13/45A", "naklon": 0 }, + "3386": { "label": "13/45B", "naklon": 0 }, + "3303": { "label": "13/60A", "naklon": 3 }, + "3302": { "label": "13/60B", "naklon": 3 }, + "3319": { "label": "13/70A", "naklon": 6 }, + "3317": { "label": "13/70B", "naklon": 6 }, + "3326": { "label": "13/70C", "naklon": 6 }, + "3351": { "label": "13/73A", "naklon": 6 }, + "3313": { "label": "13/73B", "naklon": 6 }, + "3316": { "label": "13/83A", "naklon": 0 }, + "3320": { "label": "13/83B", "naklon": 0 }, + "3336": { "label": "13/95A", "naklon": 0 }, + "3323": { "label": "13/95B", "naklon": 0 }, + "3339": { "label": "13/98A", "naklon": 0 }, + "3333": { "label": "13/98B", "naklon": 0 }, + "3425": { "label": "13/1", "naklon": 0 }, + "3419": { "label": "13/2", "naklon": 0 }, + "3416": { "label": "13/3", "naklon": 0 }, + "3332": { "label": "13/4", "naklon": 0 }, + "3422": { "label": "13/5", "naklon": 0 }, + "3417": { "label": "13/6", "naklon": 0 }, + "3418": { "label": "13/7", "naklon": 0 }, + "3424": { "label": "13/8", "naklon": 0 }, + "3334": { "label": "13/9", "naklon": 0 }, + "4363": { "label": "13/10", "naklon": 0 }, + "3423": { "label": "13/11", "naklon": 0 }, + "3406": { "label": "13/12", "naklon": 0 }, + "3411": { "label": "13/14", "naklon": 0 }, + "3412": { "label": "13/15", "naklon": 0 }, + "3413": { "label": "13/16", "naklon": 0 }, + "3414": { "label": "13/17", "naklon": 0 }, + "3391": { "label": "13/18", "naklon": 0 }, + "3370": { "label": "13/19", "naklon": 0 }, + "3369": { "label": "13/20", "naklon": 0 }, + "3408": { "label": "13/21", "naklon": 0 }, + "3393": { "label": "13/22", "naklon": 0 }, + "3128": { "label": "13/23", "naklon": 0 }, + "3197": { "label": "13/24", "naklon": 0 }, + "4364": { "label": "13/25", "naklon": 0 }, + "3155": { "label": "13/26", "naklon": 0 }, + "3196": { "label": "13/27", "naklon": 0 }, + "3144": { "label": "13/28", "naklon": 0 }, + "3150": { "label": "13/30", "naklon": 0 }, + "3390": { "label": "13/31", "naklon": 0 }, + "3401": { "label": "13/32", "naklon": 0 }, + "3275": { "label": "13/33", "naklon": 0 }, + "3371": { "label": "13/35", "naklon": 0 }, + "3389": { "label": "13/36", "naklon": 0 }, + "3388": { "label": "13/37", "naklon": 0 }, + "3365": { "label": "13/38", "naklon": 0 }, + "3363": { "label": "13/39", "naklon": 0 }, + "3397": { "label": "13/40", "naklon": 0 }, + "3567": { "label": "13/40/1", "naklon": 0 }, + "3387": { "label": "13/41", "naklon": 0 }, + "3403": { "label": "13/42", "naklon": 0 }, + "3147": { "label": "13/43", "naklon": 0 }, + "3141": { "label": "13/44", "naklon": 0 }, + "3364": { "label": "13/46", "naklon": 0 }, + "3367": { "label": "13/47", "naklon": 0 }, + "3368": { "label": "13/48", "naklon": 0 }, + "3402": { "label": "13/49", "naklon": 0 }, + "3366": { "label": "13/50", "naklon": 0 }, + "3395": { "label": "13/51", "naklon": 0 }, + "3372": { "label": "13/52", "naklon": 0 }, + "3394": { "label": "13/53", "naklon": 0 }, + "3308": { "label": "13/54", "naklon": 0 }, + "3847": { "label": "13/54/1", "naklon": 0 }, + "3312": { "label": "13/55", "naklon": 3 }, + "3309": { "label": "13/56", "naklon": 3 }, + "3311": { "label": "13/57", "naklon": 3 }, + "3310": { "label": "13/58", "naklon": 3 }, + "4365": { "label": "13/59", "naklon": 3 }, + "4093": { "label": "13/60/1", "naklon": 3 }, + "3304": { "label": "13/61", "naklon": 3 }, + "3307": { "label": "13/62", "naklon": 3 }, + "3271": { "label": "13/63", "naklon": 3 }, + "3301": { "label": "13/64", "naklon": 3 }, + "4366": { "label": "13/65", "naklon": 3 }, + "3300": { "label": "13/66", "naklon": 3 }, + "3185": { "label": "13/67", "naklon": 0 }, + "3184": { "label": "13/68", "naklon": 0 }, + "3188": { "label": "13/69", "naklon": 0 }, + "3343": { "label": "13/71", "naklon": 6 }, + "3819": { "label": "13/71/1", "naklon": 6 }, + "3880": { "label": "13/71/2", "naklon": 6 }, + "3348": { "label": "13/72", "naklon": 6 }, + "3344": { "label": "13/74", "naklon": 6 }, + "3346": { "label": "13/75", "naklon": 6 }, + "3597": { "label": "13/75/1", "naklon": 6 }, + "3345": { "label": "13/76", "naklon": 6 }, + "3322": { "label": "13/77", "naklon": 0 }, + "3325": { "label": "13/78", "naklon": 0 }, + "4310": { "label": "13/78/1", "naklon": 0 }, + "3315": { "label": "13/79", "naklon": 0 }, + "3328": { "label": "13/80", "naklon": 0 }, + "3321": { "label": "13/81", "naklon": 0 }, + "3324": { "label": "13/82", "naklon": 0 }, + "3140": { "label": "13/84", "naklon": 0 }, + "3153": { "label": "13/85", "naklon": 0 }, + "3145": { "label": "13/86", "naklon": 0 }, + "3134": { "label": "13/87", "naklon": 0 }, + "3151": { "label": "13/88", "naklon": 0 }, + "3143": { "label": "13/89", "naklon": 0 }, + "3318": { "label": "13/90", "naklon": 0 }, + "3347": { "label": "13/91", "naklon": 0 }, + "3314": { "label": "13/94", "naklon": 0 }, + "3331": { "label": "13/96", "naklon": 0 }, + "3327": { "label": "13/97", "naklon": 0 }, + "3329": { "label": "13/99", "naklon": 0 }, + "3337": { "label": "13/100", "naklon": 0 }, + "3330": { "label": "13/101", "naklon": 0 }, + "3335": { "label": "13/102", "naklon": 0 }, + "3420": { "label": "13/103", "naklon": 0 }, + "3421": { "label": "13/104", "naklon": 0 }, + "4361": { "label": "13/105", "naklon": 0 }, + "4362": { "label": "13/106", "naklon": 0 }, + "3526": { "label": "13/107", "naklon": 0 }, + "4424": { "label": "13/108", "naklon": null }, + "3561": { "label": "13/109", "naklon": null }, + "3527": { "label": "13/110", "naklon": null }, + "3521": { "label": "13/111", "naklon": null }, + "3552": { "label": "13/112", "naklon": null }, + "3544": { "label": "13/113", "naklon": null }, + "3534": { "label": "13/114", "naklon": null }, + "3516": { "label": "13/115", "naklon": null }, + "3513": { "label": "13/116", "naklon": null }, + "3565": { "label": "13/117", "naklon": null }, + "3866": { "label": "13/118", "naklon": null }, + "3136": { "label": "14/1", "naklon": 0 }, + "3137": { "label": "14/2", "naklon": 0 }, + "3135": { "label": "14/3", "naklon": 0 }, + "3149": { "label": "14/4", "naklon": 0 }, + "3142": { "label": "14/5", "naklon": 0 }, + "3342": { "label": "14/6", "naklon": 0 }, + "3340": { "label": "14/7", "naklon": 0 }, + "3152": { "label": "14/8", "naklon": 0 }, + "3886": { "label": "14/9", "naklon": 0 }, + "3341": { "label": "14/10", "naklon": null }, + "3352": { "label": "14/11", "naklon": null }, + "3396": { "label": "15/1", "naklon": 5 }, + "2784": { "label": "15/2", "naklon": 5 }, + "2788": { "label": "15/3", "naklon": 5 }, + "2801": { "label": "15/4", "naklon": 5 }, + "2815": { "label": "15/5", "naklon": 5 }, + "2829": { "label": "15/6", "naklon": 5 }, + "2796": { "label": "15/7", "naklon": 5 }, + "2803": { "label": "15/8", "naklon": 5 }, + "4304": { "label": "15/8/1", "naklon": 5 }, + "4311": { "label": "15/8/2", "naklon": 5 }, + "2821": { "label": "15/9", "naklon": 5 }, + "3400": { "label": "15/10", "naklon": 5 }, + "2799": { "label": "15/11", "naklon": 5 }, + "2804": { "label": "15/12", "naklon": 5 }, + "4303": { "label": "15/12/1", "naklon": 5 }, + "4309": { "label": "15/12/2", "naklon": 5 }, + "2806": { "label": "15/13", "naklon": 5 }, + "2787": { "label": "15/14", "naklon": 5 }, + "2809": { "label": "15/15", "naklon": 5 }, + "2814": { "label": "15/16", "naklon": 0 }, + "3934": { "label": "15/17", "naklon": 0 }, + "3192": { "label": "15/18", "naklon": 0 }, + "2812": { "label": "15/19", "naklon": 0 }, + "4070": { "label": "15/20", "naklon": 0 }, + "2826": { "label": "15/21", "naklon": 0 }, + "2808": { "label": "15/22", "naklon": 3 }, + "2795": { "label": "15/23", "naklon": 3 }, + "2807": { "label": "15/24", "naklon": 3 }, + "2831": { "label": "15/25", "naklon": 0 }, + "2862": { "label": "15/26", "naklon": null }, + "2861": { "label": "15/27", "naklon": 0 }, + "2866": { "label": "15/28", "naklon": 0 }, + "3546": { "label": "15/28/1", "naklon": 0 }, + "4146": { "label": "15/29", "naklon": 0 }, + "3001": { "label": "15/29/1", "naklon": 0 }, + "2835": { "label": "15/30", "naklon": 0 }, + "2874": { "label": "15/31", "naklon": 0 }, + "2852": { "label": "15/32", "naklon": 0 }, + "2851": { "label": "15/33", "naklon": 0 }, + "3560": { "label": "15/33/1", "naklon": 0 }, + "2858": { "label": "15/34", "naklon": 0 }, + "4306": { "label": "15/34/1", "naklon": 0 }, + "2856": { "label": "15/35", "naklon": 0 }, + "2847": { "label": "15/36", "naklon": 0 }, + "3556": { "label": "15/36/1", "naklon": 0 }, + "3950": { "label": "15/37", "naklon": 0 }, + "2848": { "label": "15/38", "naklon": 0 }, + "2863": { "label": "15/39", "naklon": 0 }, + "4313": { "label": "15/39/1", "naklon": 0 }, + "2873": { "label": "15/40", "naklon": 0 }, + "2984": { "label": "15/40/1", "naklon": 0 }, + "2854": { "label": "15/41", "naklon": 0 }, + "2859": { "label": "15/42", "naklon": 0 }, + "2872": { "label": "15/43", "naklon": 0 }, + "2849": { "label": "15/44", "naklon": 0 }, + "2864": { "label": "15/45", "naklon": 0 }, + "3553": { "label": "15/46", "naklon": null }, + "3021": { "label": "15/47", "naklon": null }, + "3008": { "label": "15/47/1", "naklon": null }, + "3017": { "label": "15/48", "naklon": null }, + "3014": { "label": "15/49", "naklon": null }, + "2981": { "label": "15/50", "naklon": null }, + "3020": { "label": "15/51", "naklon": null }, + "3027": { "label": "15/52", "naklon": null }, + "3006": { "label": "15/53", "naklon": null }, + "3012": { "label": "15/54", "naklon": null }, + "2738": { "label": "15/55", "naklon": 0 }, + "2725": { "label": "15/56", "naklon": 0 }, + "3016": { "label": "15/57", "naklon": null }, + "3005": { "label": "15/58", "naklon": null }, + "3009": { "label": "15/58/1", "naklon": null }, + "3010": { "label": "15/59", "naklon": 0 }, + "3538": { "label": "15/59/1", "naklon": 0 }, + "4145": { "label": "15/59/2", "naklon": 0 }, + "2713": { "label": "15/60", "naklon": 0 }, + "2789": { "label": "15/61", "naklon": 0 }, + "2736": { "label": "15/62", "naklon": 0 }, + "2739": { "label": "15/63", "naklon": 0 }, + "4346": { "label": "15/64", "naklon": 0 }, + "2731": { "label": "15/65", "naklon": 0 }, + "2818": { "label": "15/66", "naklon": 0 }, + "3557": { "label": "15/66/1", "naklon": 0 }, + "2822": { "label": "15/67", "naklon": 0 }, + "2833": { "label": "15/68", "naklon": 0 }, + "2834": { "label": "15/69", "naklon": 0 }, + "3097": { "label": "15/70", "naklon": 0 }, + "2824": { "label": "15/71", "naklon": 0 }, + "2828": { "label": "15/72", "naklon": 0 }, + "2600": { "label": "15/73", "naklon": 0 }, + "4314": { "label": "15/73/1", "naklon": 0 }, + "2832": { "label": "15/74", "naklon": 0 }, + "4360": { "label": "15/75", "naklon": 0 }, + "2846": { "label": "15/76", "naklon": 0 }, + "2584": { "label": "15/77", "naklon": 0 }, + "2843": { "label": "15/78", "naklon": 0 }, + "4308": { "label": "15/78/1", "naklon": 0 }, + "4144": { "label": "15/79", "naklon": null }, + "2844": { "label": "15/80", "naklon": 0 }, + "2842": { "label": "15/81", "naklon": 0 }, + "2838": { "label": "15/82", "naklon": 0 }, + "2837": { "label": "15/83", "naklon": null }, + "3555": { "label": "15/83/1", "naklon": null }, + "2839": { "label": "15/84", "naklon": 0 }, + "2830": { "label": "15/85", "naklon": 0 }, + "4066": { "label": "15/86", "naklon": 0 }, + "2836": { "label": "15/87", "naklon": 0 }, + "2911": { "label": "15/88", "naklon": 0 }, + "2825": { "label": "15/89", "naklon": 0 }, + "2811": { "label": "15/90", "naklon": 0 }, + "3740": { "label": "15/94", "naklon": 15 }, + "2734": { "label": "15/95", "naklon": 15 }, + "3105": { "label": "15/96", "naklon": 15 }, + "2732": { "label": "15/97", "naklon": 15 }, + "2727": { "label": "15/98", "naklon": 15 }, + "2735": { "label": "15/99", "naklon": 15 }, + "3926": { "label": "15/100", "naklon": 15 }, + "2918": { "label": "15/101", "naklon": 0 }, + "2705": { "label": "15/102", "naklon": 10 }, + "2708": { "label": "15/103", "naklon": 10 }, + "2721": { "label": "15/104", "naklon": 10 }, + "2719": { "label": "15/105", "naklon": 10 }, + "2919": { "label": "15/106", "naklon": 10 }, + "3101": { "label": "15/107", "naklon": 10 }, + "2853": { "label": "15/108", "naklon": 10 }, + "2715": { "label": "15/109", "naklon": 10 }, + "2712": { "label": "15/110", "naklon": 0 }, + "2711": { "label": "15/111", "naklon": 0 }, + "2709": { "label": "15/112", "naklon": 0 }, + "2710": { "label": "15/113", "naklon": 0 }, + "2907": { "label": "15/114", "naklon": 0 }, + "2906": { "label": "15/115", "naklon": 0 }, + "2908": { "label": "15/116", "naklon": 0 }, + "2901": { "label": "15/117", "naklon": 0 }, + "2913": { "label": "15/118", "naklon": 0 }, + "3656": { "label": "15/119", "naklon": 0 }, + "2781": { "label": "15/120", "naklon": 0 }, + "2802": { "label": "15/121", "naklon": 0 }, + "2791": { "label": "15/122", "naklon": 0 }, + "2783": { "label": "15/123", "naklon": 0 }, + "2794": { "label": "15/124", "naklon": 0 }, + "3139": { "label": "15/125", "naklon": 0 }, + "3229": { "label": "15/126", "naklon": 5 }, + "3239": { "label": "15/127", "naklon": 5 }, + "3230": { "label": "15/128", "naklon": 5 }, + "4016": { "label": "15/129", "naklon": null }, + "3608": { "label": "16/16A", "naklon": 0 }, + "4151": { "label": "16/16B", "naklon": 0 }, + "3710": { "label": "16/1", "naklon": 0 }, + "3726": { "label": "16/2", "naklon": 0 }, + "3743": { "label": "16/3", "naklon": 0 }, + "3724": { "label": "16/4", "naklon": 0 }, + "3712": { "label": "16/5", "naklon": 0 }, + "3739": { "label": "16/6", "naklon": 0 }, + "3742": { "label": "16/7", "naklon": 0 }, + "3731": { "label": "16/8", "naklon": 0 }, + "3727": { "label": "16/9", "naklon": 0 }, + "3729": { "label": "16/10", "naklon": 0 }, + "3736": { "label": "16/11", "naklon": 0 }, + "3713": { "label": "16/12", "naklon": 0 }, + "3715": { "label": "16/13", "naklon": 0 }, + "3733": { "label": "16/14", "naklon": 0 }, + "3732": { "label": "16/15", "naklon": 0 }, + "3634": { "label": "16/17", "naklon": 0 }, + "3610": { "label": "16/18", "naklon": 0 }, + "3626": { "label": "16/19", "naklon": 0 }, + "3618": { "label": "16/20", "naklon": 0 }, + "3619": { "label": "16/21", "naklon": 0 }, + "3628": { "label": "16/22", "naklon": 0 }, + "3615": { "label": "16/23", "naklon": 0 }, + "3609": { "label": "16/24", "naklon": 0 }, + "3606": { "label": "16/25", "naklon": 0 }, + "3624": { "label": "16/26", "naklon": 0 }, + "3627": { "label": "16/27", "naklon": 0 }, + "3607": { "label": "16/28", "naklon": 0 }, + "4370": { "label": "16/29", "naklon": 0 }, + "3692": { "label": "16/30", "naklon": 0 }, + "3614": { "label": "16/31", "naklon": 0 }, + "3623": { "label": "16/32", "naklon": 0 }, + "4373": { "label": "16/33", "naklon": 0 }, + "3620": { "label": "16/34", "naklon": 0 }, + "3685": { "label": "16/35", "naklon": 0 }, + "3616": { "label": "16/36", "naklon": 0 }, + "3686": { "label": "16/37", "naklon": 0 }, + "3688": { "label": "16/38", "naklon": 0 }, + "3684": { "label": "16/39", "naklon": 0 }, + "3825": { "label": "16/40", "naklon": 0 }, + "3865": { "label": "16/41", "naklon": 0 }, + "3824": { "label": "16/42", "naklon": 0 }, + "3871": { "label": "16/43", "naklon": 0 }, + "3801": { "label": "16/44", "naklon": 0 }, + "3862": { "label": "16/45", "naklon": 0 }, + "3876": { "label": "16/46", "naklon": 0 }, + "3861": { "label": "16/47", "naklon": 0 }, + "4215": { "label": "16/48", "naklon": 0 }, + "3605": { "label": "16/49", "naklon": 10 }, + "3603": { "label": "16/50", "naklon": 10 }, + "3592": { "label": "16/51", "naklon": 10 }, + "3598": { "label": "16/52", "naklon": 10 }, + "3594": { "label": "16/53", "naklon": 10 }, + "3593": { "label": "16/54", "naklon": 10 }, + "3630": { "label": "16/55", "naklon": 10 }, + "3763": { "label": "16/56", "naklon": 10 }, + "3746": { "label": "16/57", "naklon": 10 }, + "3699": { "label": "16/58", "naklon": 0 }, + "3698": { "label": "16/59", "naklon": 0 }, + "3709": { "label": "16/60", "naklon": null }, + "3708": { "label": "16/61", "naklon": 0 }, + "3703": { "label": "16/62", "naklon": null }, + "3700": { "label": "16/63", "naklon": 0 }, + "3701": { "label": "16/64", "naklon": null }, + "3704": { "label": "16/65", "naklon": 0 }, + "3707": { "label": "16/66", "naklon": null }, + "3810": { "label": "16/67", "naklon": 0 }, + "4208": { "label": "16/68", "naklon": null }, + "3867": { "label": "16/69", "naklon": 0 }, + "4372": { "label": "16/70", "naklon": null }, + "3881": { "label": "16/71", "naklon": 0 }, + "4204": { "label": "16/72", "naklon": null }, + "3869": { "label": "16/73", "naklon": 0 }, + "4202": { "label": "16/74", "naklon": null }, + "3830": { "label": "16/75", "naklon": 0 }, + "3870": { "label": "16/76", "naklon": null }, + "3964": { "label": "16/77", "naklon": 0 }, + "3849": { "label": "16/78", "naklon": 0 }, + "3694": { "label": "16/79", "naklon": null }, + "3717": { "label": "16/80", "naklon": 0 }, + "3877": { "label": "16/81", "naklon": null }, + "3755": { "label": "16/82", "naklon": 0 }, + "3725": { "label": "16/83", "naklon": null }, + "3716": { "label": "16/84", "naklon": 0 }, + "3696": { "label": "16/85", "naklon": null }, + "3702": { "label": "16/86", "naklon": 0 }, + "3706": { "label": "16/87", "naklon": null }, + "3850": { "label": "16/88", "naklon": 0 }, + "3848": { "label": "16/89", "naklon": null }, + "3737": { "label": "16/90", "naklon": null }, + "3705": { "label": "16/91", "naklon": 0 }, + "3723": { "label": "16/92", "naklon": null }, + "3842": { "label": "16/93", "naklon": 0 }, + "3735": { "label": "16/94", "naklon": null }, + "3719": { "label": "16/95", "naklon": 0 }, + "3697": { "label": "16/96", "naklon": 0 }, + "3711": { "label": "16/97", "naklon": 0 }, + "4107": { "label": "16/98", "naklon": null }, + "4112": { "label": "16/99", "naklon": 5 }, + "4106": { "label": "16/100", "naklon": 5 }, + "4111": { "label": "16/101", "naklon": 5 }, + "4091": { "label": "16/102", "naklon": null }, + "4104": { "label": "16/103", "naklon": 5 }, + "4094": { "label": "16/104", "naklon": null }, + "4089": { "label": "16/105", "naklon": 5 }, + "4095": { "label": "16/106", "naklon": null }, + "4102": { "label": "16/107", "naklon": 5 }, + "4105": { "label": "16/108", "naklon": null }, + "3859": { "label": "16/109", "naklon": null }, + "4090": { "label": "16/110", "naklon": 5 }, + "4110": { "label": "16/111", "naklon": null }, + "4097": { "label": "16/112", "naklon": 5 }, + "4099": { "label": "16/113", "naklon": null }, + "4096": { "label": "16/114", "naklon": null }, + "4101": { "label": "16/115", "naklon": 5 }, + "4109": { "label": "16/116", "naklon": null }, + "4092": { "label": "16/117", "naklon": 5 }, + "3631": { "label": "16/118", "naklon": null }, + "3632": { "label": "16/119", "naklon": 0 }, + "3641": { "label": "16/120", "naklon": null }, + "3638": { "label": "16/121", "naklon": 0 }, + "3637": { "label": "16/122", "naklon": null }, + "4142": { "label": "16/123", "naklon": null }, + "4147": { "label": "16/124", "naklon": 5 }, + "4139": { "label": "16/125", "naklon": 5 }, + "3172": { "label": "20/30A", "naklon": 2 }, + "3164": { "label": "20/30B", "naklon": 2 }, + "3247": { "label": "20/1", "naklon": 10 }, + "3296": { "label": "20/2", "naklon": 10 }, + "3246": { "label": "20/3", "naklon": 10 }, + "3270": { "label": "20/4", "naklon": 10 }, + "3294": { "label": "20/5", "naklon": 10 }, + "3298": { "label": "20/6", "naklon": 10 }, + "3297": { "label": "20/7", "naklon": 10 }, + "3293": { "label": "20/8", "naklon": 10 }, + "3299": { "label": "20/9", "naklon": 10 }, + "3295": { "label": "20/10", "naklon": 10 }, + "3244": { "label": "20/11", "naklon": 10 }, + "3249": { "label": "20/12", "naklon": 10 }, + "3268": { "label": "20/13", "naklon": 10 }, + "3245": { "label": "20/14", "naklon": 10 }, + "3278": { "label": "20/15", "naklon": 10 }, + "3280": { "label": "20/16", "naklon": 10 }, + "3292": { "label": "20/17", "naklon": 10 }, + "3287": { "label": "20/18", "naklon": 10 }, + "3282": { "label": "20/19", "naklon": 10 }, + "3273": { "label": "20/20", "naklon": 0 }, + "3157": { "label": "20/21", "naklon": 0 }, + "3283": { "label": "20/22", "naklon": 0 }, + "3159": { "label": "20/23", "naklon": 0 }, + "3289": { "label": "20/24", "naklon": 0 }, + "3163": { "label": "20/25", "naklon": 0 }, + "3126": { "label": "20/26", "naklon": 0 }, + "3171": { "label": "20/27", "naklon": 0 }, + "3162": { "label": "20/28", "naklon": 0 }, + "3279": { "label": "20/29", "naklon": 10 }, + "3173": { "label": "20/31", "naklon": 0 }, + "3127": { "label": "20/32", "naklon": 0 }, + "3131": { "label": "20/33", "naklon": 0 }, + "3129": { "label": "20/34", "naklon": 0 }, + "3276": { "label": "20/35", "naklon": 2 }, + "3290": { "label": "20/36", "naklon": 2 }, + "3132": { "label": "20/37", "naklon": 0 }, + "3138": { "label": "20/38", "naklon": 0 }, + "3272": { "label": "20/39", "naklon": 0 }, + "3291": { "label": "20/40", "naklon": 0 }, + "3277": { "label": "20/41", "naklon": 10 }, + "3286": { "label": "20/42", "naklon": 10 }, + "3281": { "label": "20/43", "naklon": 10 }, + "3288": { "label": "20/44", "naklon": 10 }, + "3284": { "label": "20/45", "naklon": 10 }, + "3167": { "label": "20/46", "naklon": 10 }, + "3872": { "label": "20/47", "naklon": 0 }, + "3124": { "label": "20/48", "naklon": 0 }, + "3133": { "label": "20/49", "naklon": 0 }, + "3158": { "label": "20/50", "naklon": 0 }, + "3169": { "label": "20/51", "naklon": 0 }, + "3146": { "label": "20/52", "naklon": 0 }, + "3160": { "label": "20/53", "naklon": 0 }, + "3248": { "label": "20/54", "naklon": 0 }, + "3156": { "label": "20/55", "naklon": 0 }, + "3161": { "label": "20/56", "naklon": 0 }, + "3170": { "label": "20/57", "naklon": 0 }, + "3168": { "label": "20/58", "naklon": 0 }, + "3125": { "label": "20/59", "naklon": 0 }, + "3166": { "label": "20/60", "naklon": 0 }, + "3130": { "label": "20/61", "naklon": 0 }, + "3563": { "label": "20/62", "naklon": 0 }, + "3550": { "label": "20/63", "naklon": null }, + "3269": { "label": "20/67", "naklon": 0 }, + "2921": { "label": "21/1", "naklon": 0 }, + "2707": { "label": "21/2", "naklon": 0 }, + "2723": { "label": "21/3", "naklon": 0 }, + "2716": { "label": "21/4", "naklon": 0 }, + "2717": { "label": "21/5", "naklon": 0 }, + "2720": { "label": "21/6", "naklon": 0 }, + "2722": { "label": "21/7", "naklon": 0 }, + "2718": { "label": "21/8", "naklon": 0 }, + "2724": { "label": "21/9", "naklon": 0 }, + "2742": { "label": "21/10", "naklon": 0 }, + "2743": { "label": "21/11", "naklon": 0 }, + "2733": { "label": "21/12", "naklon": 0 }, + "2903": { "label": "21/14", "naklon": 0 }, + "2917": { "label": "21/15", "naklon": 0 }, + "2897": { "label": "21/16", "naklon": 0 }, + "2914": { "label": "21/17", "naklon": 0 }, + "2898": { "label": "21/18", "naklon": 0 }, + "2773": { "label": "21/19", "naklon": 0 }, + "2895": { "label": "21/20", "naklon": 0 }, + "2896": { "label": "21/21", "naklon": 0 }, + "2771": { "label": "21/22", "naklon": 0 }, + "2772": { "label": "21/23", "naklon": 0 }, + "2793": { "label": "21/24", "naklon": 0 }, + "2902": { "label": "21/25", "naklon": 0 }, + "2910": { "label": "21/26", "naklon": 0 }, + "2909": { "label": "21/27", "naklon": 0 }, + "2920": { "label": "21/28", "naklon": 0 }, + "2916": { "label": "21/29", "naklon": 0 }, + "2904": { "label": "21/30", "naklon": 0 }, + "2915": { "label": "21/31", "naklon": 0 }, + "2905": { "label": "21/32", "naklon": 0 }, + "2900": { "label": "21/33", "naklon": 0 }, + "2899": { "label": "21/34", "naklon": 0 }, + "2741": { "label": "21/36", "naklon": 0 }, + "2714": { "label": "21/37", "naklon": 0 }, + "2701": { "label": "21/38", "naklon": 0 }, + "2703": { "label": "21/39", "naklon": 0 }, + "2704": { "label": "21/40", "naklon": 0 }, + "2702": { "label": "21/41", "naklon": 0 }, + "2706": { "label": "21/42", "naklon": 0 }, + "2776": { "label": "21/43", "naklon": 0 }, + "2770": { "label": "21/44", "naklon": 0 }, + "2786": { "label": "21/45", "naklon": 0 }, + "2779": { "label": "21/46", "naklon": 0 }, + "2782": { "label": "21/47", "naklon": 0 }, + "2785": { "label": "21/48", "naklon": 0 }, + "2769": { "label": "21/49", "naklon": 0 }, + "3354": { "label": "21/50", "naklon": 0 }, + "2778": { "label": "21/51", "naklon": 0 }, + "2775": { "label": "21/52", "naklon": 0 }, + "2780": { "label": "21/53", "naklon": 0 }, + "2790": { "label": "21/54", "naklon": 0 }, + "2792": { "label": "21/55", "naklon": 0 }, + "2774": { "label": "21/56", "naklon": 0 }, + "2630": { "label": "22/1", "naklon": 0 }, + "2631": { "label": "22/2", "naklon": 0 }, + "2632": { "label": "22/3", "naklon": 0 }, + "2633": { "label": "22/4", "naklon": 0 }, + "2634": { "label": "22/5", "naklon": 0 }, + "2636": { "label": "22/6", "naklon": 0 }, + "4367": { "label": "22/7", "naklon": 0 }, + "2637": { "label": "22/8", "naklon": 0 }, + "2638": { "label": "22/9", "naklon": 0 }, + "2639": { "label": "22/10", "naklon": 0 }, + "2640": { "label": "22/11", "naklon": 0 }, + "2641": { "label": "22/12", "naklon": 0 }, + "2642": { "label": "22/13", "naklon": 0 }, + "2643": { "label": "22/14", "naklon": 0 }, + "2644": { "label": "22/15", "naklon": 0 }, + "2645": { "label": "22/16", "naklon": 0 }, + "2646": { "label": "22/17", "naklon": 0 }, + "2647": { "label": "22/18", "naklon": 0 }, + "2648": { "label": "22/19", "naklon": 0 }, + "2649": { "label": "22/20", "naklon": 0 }, + "2650": { "label": "22/21", "naklon": 0 }, + "2651": { "label": "22/22", "naklon": 0 }, + "4103": { "label": "22/23", "naklon": 0 }, + "2653": { "label": "22/24", "naklon": 0 }, + "2654": { "label": "22/25", "naklon": 0 }, + "2655": { "label": "22/26", "naklon": 0 }, + "2656": { "label": "22/27", "naklon": 0 }, + "2657": { "label": "22/28", "naklon": 0 }, + "2658": { "label": "22/29", "naklon": 0 }, + "2659": { "label": "22/30", "naklon": 0 }, + "2660": { "label": "22/31", "naklon": 0 }, + "2661": { "label": "22/32", "naklon": 0 }, + "3015": { "label": "22/32/1", "naklon": 0 }, + "2662": { "label": "22/33", "naklon": 0 }, + "2663": { "label": "22/34", "naklon": 0 }, + "2664": { "label": "22/35", "naklon": 0 }, + "2665": { "label": "22/36", "naklon": 0 }, + "2666": { "label": "22/37", "naklon": 0 }, + "2667": { "label": "22/38", "naklon": 0 }, + "2668": { "label": "22/39", "naklon": 0 }, + "2669": { "label": "22/40", "naklon": null }, + "2670": { "label": "22/41", "naklon": null }, + "2671": { "label": "22/42", "naklon": null }, + "3087": { "label": "23/9A", "naklon": 10 }, + "3090": { "label": "23/9B", "naklon": 10 }, + "3075": { "label": "23/1", "naklon": 0 }, + "3089": { "label": "23/2", "naklon": 0 }, + "3088": { "label": "23/3", "naklon": 0 }, + "3228": { "label": "23/4", "naklon": 10 }, + "2751": { "label": "23/5", "naklon": 10 }, + "3243": { "label": "23/6", "naklon": 10 }, + "4349": { "label": "23/7", "naklon": 10 }, + "3102": { "label": "23/8", "naklon": 10 }, + "3099": { "label": "23/10", "naklon": 10 }, + "3103": { "label": "23/11", "naklon": 10 }, + "3093": { "label": "23/12", "naklon": 10 }, + "3098": { "label": "23/13", "naklon": 10 }, + "3092": { "label": "23/14", "naklon": 10 }, + "3233": { "label": "23/15", "naklon": 0 }, + "3095": { "label": "23/16", "naklon": 0 }, + "4074": { "label": "23/17", "naklon": 0 }, + "2729": { "label": "23/18", "naklon": 0 }, + "3234": { "label": "23/19", "naklon": 0 }, + "3094": { "label": "23/20", "naklon": 0 }, + "2817": { "label": "23/21", "naklon": 0 }, + "3226": { "label": "23/22", "naklon": 0 }, + "3225": { "label": "23/23", "naklon": 0 }, + "3237": { "label": "23/24", "naklon": 0 }, + "4250": { "label": "23/25", "naklon": 0 }, + "3059": { "label": "23/26", "naklon": 10 }, + "3238": { "label": "23/27", "naklon": 10 }, + "3242": { "label": "23/28", "naklon": 10 }, + "3236": { "label": "23/29", "naklon": 10 }, + "3112": { "label": "23/30", "naklon": 10 }, + "3224": { "label": "23/31", "naklon": 0 }, + "4298": { "label": "23/32", "naklon": 10 }, + "4150": { "label": "23/33", "naklon": 10 }, + "3091": { "label": "23/34", "naklon": 10 }, + "3771": { "label": "25/1", "naklon": 5 }, + "3777": { "label": "25/2", "naklon": 5 }, + "3749": { "label": "25/3", "naklon": 5 }, + "3769": { "label": "25/4", "naklon": 5 }, + "3765": { "label": "25/5", "naklon": 5 }, + "3785": { "label": "25/6", "naklon": 5 }, + "3761": { "label": "25/7", "naklon": 5 }, + "3758": { "label": "25/8", "naklon": 5 }, + "3766": { "label": "25/9", "naklon": 5 }, + "3779": { "label": "25/10", "naklon": 5 }, + "3899": { "label": "25/11", "naklon": 10 }, + "3922": { "label": "25/12", "naklon": 10 }, + "3912": { "label": "25/13", "naklon": 10 }, + "3933": { "label": "25/14", "naklon": 10 }, + "3921": { "label": "25/15", "naklon": 10 }, + "4300": { "label": "25/16", "naklon": 10 }, + "3927": { "label": "25/17", "naklon": 10 }, + "3212": { "label": "25/18", "naklon": 10 }, + "3208": { "label": "25/19", "naklon": 10 }, + "3207": { "label": "25/20", "naklon": 10 }, + "4294": { "label": "25/21", "naklon": 10 }, + "3209": { "label": "25/22", "naklon": 10 }, + "3745": { "label": "25/23", "naklon": 10 }, + "3762": { "label": "25/24", "naklon": 10 }, + "3215": { "label": "25/25", "naklon": 10 }, + "3210": { "label": "25/26", "naklon": 10 }, + "3211": { "label": "25/27", "naklon": 10 }, + "3206": { "label": "25/28", "naklon": 10 }, + "3918": { "label": "25/29", "naklon": 5 }, + "3928": { "label": "25/30", "naklon": 5 }, + "3917": { "label": "25/31", "naklon": 5 }, + "4029": { "label": "25/32", "naklon": 0 }, + "4038": { "label": "25/33", "naklon": 0 }, + "4022": { "label": "25/34", "naklon": 0 }, + "3937": { "label": "25/35", "naklon": 0 }, + "3190": { "label": "25/36", "naklon": 0 }, + "3835": { "label": "25/37", "naklon": 0 }, + "3201": { "label": "25/38", "naklon": 0 }, + "3193": { "label": "25/39", "naklon": 0 }, + "3191": { "label": "25/40", "naklon": 0 }, + "3203": { "label": "25/41", "naklon": 0 }, + "4301": { "label": "25/42", "naklon": 0 }, + "3223": { "label": "25/43", "naklon": 0 }, + "3202": { "label": "25/44", "naklon": 0 }, + "3205": { "label": "25/45", "naklon": 0 }, + "3194": { "label": "25/46", "naklon": 0 }, + "3198": { "label": "25/47", "naklon": 0 }, + "3204": { "label": "25/48", "naklon": 0 }, + "3200": { "label": "25/49", "naklon": 0 }, + "3216": { "label": "25/50", "naklon": 0 }, + "3932": { "label": "25/51", "naklon": 5 }, + "3923": { "label": "25/52", "naklon": 5 }, + "3913": { "label": "25/53", "naklon": 5 }, + "3900": { "label": "25/54", "naklon": 5 }, + "4189": { "label": "25/55", "naklon": 10 }, + "4191": { "label": "25/56", "naklon": 10 }, + "3790": { "label": "25/57", "naklon": 10 }, + "4190": { "label": "25/58", "naklon": 10 }, + "4302": { "label": "25/59", "naklon": 0 }, + "4351": { "label": "25/60", "naklon": 0 }, + "4075": { "label": "25/61", "naklon": 0 }, + "4071": { "label": "25/62", "naklon": 0 }, + "3784": { "label": "25/63", "naklon": 0 }, + "4065": { "label": "25/64", "naklon": 0 }, + "4297": { "label": "25/65", "naklon": 0 }, + "4295": { "label": "25/66", "naklon": 0 }, + "4299": { "label": "25/67", "naklon": 0 }, + "3772": { "label": "25/68", "naklon": 0 }, + "3941": { "label": "25/69", "naklon": 0 }, + "3782": { "label": "25/70", "naklon": 0 }, + "4068": { "label": "25/71", "naklon": 0 }, + "4073": { "label": "25/72", "naklon": 0 }, + "3901": { "label": "25/73", "naklon": 5 }, + "4296": { "label": "25/74", "naklon": 5 }, + "3910": { "label": "25/75", "naklon": 5 }, + "4293": { "label": "25/76", "naklon": 5 }, + "3919": { "label": "25/77", "naklon": 5 }, + "3924": { "label": "25/78", "naklon": 5 }, + "3909": { "label": "25/79", "naklon": 5 }, + "3896": { "label": "25/80", "naklon": 5 }, + "3911": { "label": "25/81", "naklon": 5 }, + "2819": { "label": "25/82", "naklon": 15 }, + "3776": { "label": "25/83", "naklon": 15 }, + "3752": { "label": "25/84", "naklon": 15 }, + "4353": { "label": "25/85", "naklon": 15 }, + "3791": { "label": "25/86", "naklon": 0 }, + "3770": { "label": "25/87", "naklon": 0 }, + "3760": { "label": "25/88", "naklon": 0 }, + "3115": { "label": "25/89", "naklon": 0 }, + "3738": { "label": "25/90", "naklon": 0 }, + "3748": { "label": "25/91", "naklon": 0 }, + "3753": { "label": "25/92", "naklon": 0 }, + "3775": { "label": "25/93", "naklon": 0 }, + "3778": { "label": "25/94", "naklon": 5 }, + "4078": { "label": "25/95", "naklon": 5 }, + "4088": { "label": "25/96", "naklon": 5 }, + "3856": { "label": "25/97", "naklon": 5 }, + "4084": { "label": "25/98", "naklon": 5 }, + "4069": { "label": "25/99", "naklon": 5 }, + "4188": { "label": "25/100", "naklon": 5 }, + "4064": { "label": "25/101", "naklon": 5 }, + "3792": { "label": "25/102", "naklon": 5 }, + "3780": { "label": "25/103", "naklon": 5 }, + "4034": { "label": "25/104", "naklon": 5 }, + "4072": { "label": "25/105", "naklon": 5 }, + "3884": { "label": "25/106", "naklon": 5 }, + "3793": { "label": "25/107", "naklon": 5 }, + "3863": { "label": "25/108", "naklon": 5 }, + "3855": { "label": "25/109", "naklon": 5 }, + "3846": { "label": "33/1", "naklon": 0 }, + "3943": { "label": "33/2", "naklon": 0 }, + "3903": { "label": "33/3", "naklon": 0 }, + "3982": { "label": "33/4", "naklon": 0 }, + "3879": { "label": "33/5", "naklon": 0 }, + "3887": { "label": "33/6", "naklon": 0 }, + "3920": { "label": "33/7", "naklon": 5 }, + "3942": { "label": "33/8", "naklon": 5 }, + "3829": { "label": "33/9", "naklon": null }, + "3452": { "label": "34/79A", "naklon": 6 }, + "3460": { "label": "34/79B", "naklon": 6 }, + "3443": { "label": "34/90A", "naklon": 6 }, + "3445": { "label": "34/90B", "naklon": 6 }, + "3457": { "label": "34/90C", "naklon": 6 }, + "3461": { "label": "34/97A", "naklon": 6 }, + "3463": { "label": "34/97B", "naklon": 6 }, + "3426": { "label": "34/98A", "naklon": 6 }, + "3444": { "label": "34/98B", "naklon": 6 }, + "3453": { "label": "34/99A", "naklon": 6 }, + "3455": { "label": "34/99B", "naklon": 6 }, + "4009": { "label": "34/1", "naklon": 0 }, + "3602": { "label": "34/2", "naklon": 0 }, + "3441": { "label": "34/3", "naklon": 0 }, + "3464": { "label": "34/4", "naklon": 0 }, + "3883": { "label": "34/5", "naklon": 0 }, + "4098": { "label": "34/6", "naklon": 0 }, + "4003": { "label": "34/7", "naklon": 0 }, + "4004": { "label": "34/8", "naklon": 0 }, + "3888": { "label": "34/9", "naklon": 0 }, + "3997": { "label": "34/10", "naklon": 0 }, + "4006": { "label": "34/11", "naklon": 0 }, + "4000": { "label": "34/12", "naklon": 0 }, + "4011": { "label": "34/13", "naklon": 0 }, + "3999": { "label": "34/14", "naklon": 0 }, + "3981": { "label": "34/15", "naklon": 0 }, + "3988": { "label": "34/16", "naklon": 0 }, + "3986": { "label": "34/17", "naklon": 0 }, + "3998": { "label": "34/18", "naklon": 0 }, + "3983": { "label": "34/19", "naklon": 0 }, + "4005": { "label": "34/20", "naklon": 0 }, + "4001": { "label": "34/21", "naklon": 0 }, + "4008": { "label": "34/22", "naklon": 0 }, + "4002": { "label": "34/23", "naklon": 0 }, + "3996": { "label": "34/24", "naklon": 0 }, + "4007": { "label": "34/25", "naklon": 0 }, + "4113": { "label": "34/26", "naklon": 15 }, + "3595": { "label": "34/27", "naklon": 5 }, + "3599": { "label": "34/28", "naklon": 5 }, + "3601": { "label": "34/29", "naklon": 5 }, + "4205": { "label": "34/30", "naklon": 0 }, + "3987": { "label": "34/31", "naklon": null }, + "4214": { "label": "34/32", "naklon": 0 }, + "4226": { "label": "34/33", "naklon": 0 }, + "4209": { "label": "34/34", "naklon": 0 }, + "4201": { "label": "34/35", "naklon": 0 }, + "3440": { "label": "34/36", "naklon": 0 }, + "3465": { "label": "34/37", "naklon": 0 }, + "3446": { "label": "34/38", "naklon": 0 }, + "4039": { "label": "34/39", "naklon": 5 }, + "4057": { "label": "34/40", "naklon": 5 }, + "3985": { "label": "34/41", "naklon": 0 }, + "3882": { "label": "34/42", "naklon": 0 }, + "4040": { "label": "34/43", "naklon": 5 }, + "3231": { "label": "34/44", "naklon": 0 }, + "3227": { "label": "34/45", "naklon": 0 }, + "3431": { "label": "34/46", "naklon": 0 }, + "4013": { "label": "34/47", "naklon": 0 }, + "4045": { "label": "34/48", "naklon": 0 }, + "3949": { "label": "34/49", "naklon": 0 }, + "3953": { "label": "34/50", "naklon": 0 }, + "3952": { "label": "34/51", "naklon": 0 }, + "3995": { "label": "34/52", "naklon": 0 }, + "3992": { "label": "34/53", "naklon": 0 }, + "4198": { "label": "34/54", "naklon": 0 }, + "3935": { "label": "34/55", "naklon": 0 }, + "4050": { "label": "34/56", "naklon": 0 }, + "4049": { "label": "34/57", "naklon": 0 }, + "4054": { "label": "34/58", "naklon": 0 }, + "3663": { "label": "34/59", "naklon": 6 }, + "3661": { "label": "34/60", "naklon": 6 }, + "3664": { "label": "34/61", "naklon": 6 }, + "3660": { "label": "34/62", "naklon": 6 }, + "3662": { "label": "34/63", "naklon": 6 }, + "3665": { "label": "34/65", "naklon": 6 }, + "3667": { "label": "34/66", "naklon": 6 }, + "3675": { "label": "34/67", "naklon": 6 }, + "3666": { "label": "34/68", "naklon": 6 }, + "3652": { "label": "34/69", "naklon": 6 }, + "3458": { "label": "34/70", "naklon": 6 }, + "4425": { "label": "34/70/1", "naklon": 6 }, + "3459": { "label": "34/71", "naklon": 6 }, + "3435": { "label": "34/72", "naklon": 6 }, + "3448": { "label": "34/73", "naklon": 6 }, + "3451": { "label": "34/74", "naklon": 6 }, + "3442": { "label": "34/75", "naklon": 6 }, + "3449": { "label": "34/76", "naklon": 6 }, + "3450": { "label": "34/77", "naklon": 6 }, + "3433": { "label": "34/78", "naklon": 6 }, + "3432": { "label": "34/80", "naklon": 12 }, + "3470": { "label": "34/81", "naklon": 12 }, + "3438": { "label": "34/82", "naklon": 12 }, + "3439": { "label": "34/83", "naklon": 12 }, + "4028": { "label": "34/84", "naklon": 5 }, + "3596": { "label": "34/85", "naklon": 5 }, + "4021": { "label": "34/86", "naklon": 5 }, + "3437": { "label": "34/87", "naklon": 12 }, + "3428": { "label": "34/88", "naklon": 12 }, + "3430": { "label": "34/89", "naklon": 12 }, + "3454": { "label": "34/91", "naklon": 6 }, + "3492": { "label": "34/92", "naklon": 6 }, + "3462": { "label": "34/93", "naklon": 6 }, + "3427": { "label": "34/94", "naklon": 6 }, + "3434": { "label": "34/95", "naklon": 6 }, + "3456": { "label": "34/96", "naklon": 6 }, + "4307": { "label": "34/98/1", "naklon": 6 }, + "3968": { "label": "35/1", "naklon": 0 }, + "3969": { "label": "35/2", "naklon": 0 }, + "3947": { "label": "35/3", "naklon": 0 }, + "3979": { "label": "35/4", "naklon": 0 }, + "3959": { "label": "35/5", "naklon": 0 }, + "3948": { "label": "35/6", "naklon": 0 }, + "3961": { "label": "35/7", "naklon": 0 }, + "3956": { "label": "35/8", "naklon": 0 }, + "3604": { "label": "35/9", "naklon": 0 }, + "3944": { "label": "35/10", "naklon": 0 }, + "3960": { "label": "35/11", "naklon": 0 }, + "3958": { "label": "35/12", "naklon": 0 }, + "4036": { "label": "35/13", "naklon": 5 }, + "3893": { "label": "35/18", "naklon": 5 }, + "4108": { "label": "35/19", "naklon": 5 }, + "4017": { "label": "35/20", "naklon": 5 }, + "3963": { "label": "35/21", "naklon": 0 }, + "3658": { "label": "35/22", "naklon": 0 }, + "3975": { "label": "35/23", "naklon": 0 }, + "3980": { "label": "35/24", "naklon": 0 }, + "4012": { "label": "35/25", "naklon": 0 }, + "3655": { "label": "35/26", "naklon": 0 }, + "3962": { "label": "35/27", "naklon": 0 }, + "3945": { "label": "35/28", "naklon": 0 }, + "3569": { "label": "35/29", "naklon": 0 }, + "3429": { "label": "35/30", "naklon": 0 }, + "3657": { "label": "35/31", "naklon": 0 }, + "3646": { "label": "35/32", "naklon": 0 }, + "3622": { "label": "35/33", "naklon": 0 }, + "3612": { "label": "35/34", "naklon": 0 }, + "3955": { "label": "35/35", "naklon": 0 }, + "3878": { "label": "35/37", "naklon": 0 }, + "3965": { "label": "35/38", "naklon": 0 }, + "3970": { "label": "35/39", "naklon": 0 }, + "3611": { "label": "35/40", "naklon": 0 }, + "2635": { "label": "35/41", "naklon": 0 }, + "3978": { "label": "35/42", "naklon": 0 }, + "4213": { "label": "35/43", "naklon": 0 }, + "3984": { "label": "35/44", "naklon": 0 }, + "4218": { "label": "35/45", "naklon": 0 }, + "3973": { "label": "35/46", "naklon": 0 }, + "3974": { "label": "35/47", "naklon": 0 }, + "3759": { "label": "35/48", "naklon": 0 }, + "3844": { "label": "35/49", "naklon": 0 }, + "3804": { "label": "35/50", "naklon": 0 }, + "3831": { "label": "35/51", "naklon": 0 }, + "3643": { "label": "35/52", "naklon": 0 }, + "3966": { "label": "35/53", "naklon": 0 }, + "3971": { "label": "35/54", "naklon": 0 }, + "3650": { "label": "35/55", "naklon": 6 }, + "3651": { "label": "35/56", "naklon": 6 }, + "3669": { "label": "35/57", "naklon": 6 }, + "3648": { "label": "35/58", "naklon": 6 }, + "3645": { "label": "35/59", "naklon": 6 }, + "3659": { "label": "35/60", "naklon": 6 }, + "3647": { "label": "35/61", "naklon": 6 }, + "3644": { "label": "35/62", "naklon": 6 }, + "3671": { "label": "35/63", "naklon": 6 }, + "3682": { "label": "35/64", "naklon": 6 }, + "3672": { "label": "35/65", "naklon": 6 }, + "3683": { "label": "35/66", "naklon": 6 }, + "3673": { "label": "35/67", "naklon": 6 }, + "3674": { "label": "35/68", "naklon": 6 }, + "3679": { "label": "35/69", "naklon": 6 }, + "3649": { "label": "35/70", "naklon": 6 }, + "3687": { "label": "35/71", "naklon": 6 }, + "3677": { "label": "35/72", "naklon": 6 }, + "3690": { "label": "35/73", "naklon": 6 }, + "3691": { "label": "35/74", "naklon": 6 }, + "3676": { "label": "35/75", "naklon": 6 }, + "3680": { "label": "35/76", "naklon": 6 }, + "3668": { "label": "35/77", "naklon": 6 }, + "3681": { "label": "35/78", "naklon": 6 }, + "3670": { "label": "35/79", "naklon": 6 }, + "3689": { "label": "35/80", "naklon": 6 }, + "3678": { "label": "35/81", "naklon": 6 }, + "3693": { "label": "35/82", "naklon": 6 }, + "3654": { "label": "35/83", "naklon": null }, + "4086": { "label": "36/1", "naklon": 0 }, + "4085": { "label": "36/2", "naklon": 0 }, + "4083": { "label": "36/3", "naklon": 0 }, + "4087": { "label": "36/4", "naklon": 0 }, + "4077": { "label": "36/5", "naklon": 0 }, + "4082": { "label": "36/6", "naklon": 0 }, + "4186": { "label": "36/7", "naklon": 0 }, + "4206": { "label": "36/8", "naklon": 0 }, + "4080": { "label": "36/9", "naklon": 0 }, + "4081": { "label": "36/10", "naklon": 0 }, + "4210": { "label": "36/11", "naklon": 0 }, + "4079": { "label": "36/12", "naklon": 0 }, + "4076": { "label": "36/13", "naklon": 0 }, + "3852": { "label": "36/14", "naklon": 0 }, + "2813": { "label": "36/15", "naklon": 0 }, + "4219": { "label": "36/16", "naklon": 0 }, + "3104": { "label": "37/1A", "naklon": 15 }, + "3121": { "label": "37/1B", "naklon": 15 }, + "3113": { "label": "37/2", "naklon": 10 }, + "3118": { "label": "37/3", "naklon": 10 }, + "3111": { "label": "37/4", "naklon": 10 }, + "4020": { "label": "37/5", "naklon": 10 }, + "3119": { "label": "37/6", "naklon": 10 }, + "3110": { "label": "37/7", "naklon": 10 }, + "3108": { "label": "37/8", "naklon": 10 }, + "3107": { "label": "37/12", "naklon": 0 }, + "3199": { "label": "37/13", "naklon": 0 }, + "3120": { "label": "37/14", "naklon": 0 }, + "3122": { "label": "37/15", "naklon": 0 }, + "3908": { "label": "37/16", "naklon": 0 }, + "3114": { "label": "37/17", "naklon": 0 }, + "3105": { "label": "37/18", "naklon": 0 }, + "3116": { "label": "37/19", "naklon": 0 }, + "3106": { "label": "37/20", "naklon": 0 }, + "2887": { "label": "37/21", "naklon": 5 }, + "2888": { "label": "37/22", "naklon": 5 }, + "2877": { "label": "37/23", "naklon": 5 }, + "2891": { "label": "37/24", "naklon": 5 }, + "2886": { "label": "37/25", "naklon": 5 }, + "2892": { "label": "37/26", "naklon": 5 }, + "2882": { "label": "37/27", "naklon": 5 }, + "2883": { "label": "37/28", "naklon": 5 }, + "2876": { "label": "37/29", "naklon": 5 }, + "3109": { "label": "37/30", "naklon": 5 }, + "4152": { "label": "37/31", "naklon": 5 }, + "3117": { "label": "37/32", "naklon": 5 }, + "2870": { "label": "37/33", "naklon": 5 }, + "2867": { "label": "37/34", "naklon": 0 }, + "2865": { "label": "37/35", "naklon": 0 }, + "3096": { "label": "37/36", "naklon": 0 }, + "2871": { "label": "37/37", "naklon": 0 }, + "2884": { "label": "37/38", "naklon": 0 }, + "2855": { "label": "37/39", "naklon": 0 }, + "2878": { "label": "37/40", "naklon": 0 }, + "2889": { "label": "37/41", "naklon": 0 }, + "2879": { "label": "37/42", "naklon": 0 }, + "2850": { "label": "37/43", "naklon": 0 }, + "2894": { "label": "37/44", "naklon": 0 }, + "2880": { "label": "37/45", "naklon": 0 }, + "2893": { "label": "37/46", "naklon": 0 }, + "2890": { "label": "37/47", "naklon": 0 }, + "4355": { "label": "37/48", "naklon": 0 }, + "2885": { "label": "37/49", "naklon": 0 }, + "2875": { "label": "37/50", "naklon": 0 }, + "3486": { "label": "38/30A", "naklon": 5 }, + "3714": { "label": "38/30B", "naklon": 0 }, + "3483": { "label": "38/32A", "naklon": 5 }, + "3496": { "label": "38/32B", "naklon": 0 }, + "3487": { "label": "38/35A", "naklon": 5 }, + "3498": { "label": "38/35B", "naklon": 5 }, + "3578": { "label": "38/38A", "naklon": 5 }, + "3508": { "label": "38/38B", "naklon": 5 }, + "3787": { "label": "38/59A", "naklon": 5 }, + "3491": { "label": "38/59B", "naklon": 5 }, + "3568": { "label": "38/1", "naklon": null }, + "3502": { "label": "38/2", "naklon": 0 }, + "3836": { "label": "38/3", "naklon": 0 }, + "3588": { "label": "38/4", "naklon": 0 }, + "3493": { "label": "38/5", "naklon": 0 }, + "3580": { "label": "38/6", "naklon": 0 }, + "3572": { "label": "38/7", "naklon": 0 }, + "3506": { "label": "38/8", "naklon": 0 }, + "3503": { "label": "38/9", "naklon": 0 }, + "3579": { "label": "38/10", "naklon": 0 }, + "3586": { "label": "38/11", "naklon": 0 }, + "3495": { "label": "38/12", "naklon": 5 }, + "3492": { "label": "38/13", "naklon": 5 }, + "3532": { "label": "38/14", "naklon": 5 }, + "3574": { "label": "38/15", "naklon": 5 }, + "4140": { "label": "38/16", "naklon": 5 }, + "3795": { "label": "38/17", "naklon": 5 }, + "3788": { "label": "38/18", "naklon": 5 }, + "3796": { "label": "38/19", "naklon": 5 }, + "3797": { "label": "38/20", "naklon": 5 }, + "3798": { "label": "38/21", "naklon": 5 }, + "3786": { "label": "38/22", "naklon": 5 }, + "4067": { "label": "38/23", "naklon": 5 }, + "3773": { "label": "38/24", "naklon": 5 }, + "3774": { "label": "38/25", "naklon": 5 }, + "3789": { "label": "38/26", "naklon": 5 }, + "3520": { "label": "38/27", "naklon": null }, + "3577": { "label": "38/29", "naklon": 5 }, + "3530": { "label": "38/31", "naklon": null }, + "3488": { "label": "38/33", "naklon": 5 }, + "3505": { "label": "38/34", "naklon": 5 }, + "3497": { "label": "38/36", "naklon": 5 }, + "3490": { "label": "38/37", "naklon": 5 }, + "3585": { "label": "38/39", "naklon": 5 }, + "3582": { "label": "38/40", "naklon": 5 }, + "3507": { "label": "38/41", "naklon": 5 }, + "3484": { "label": "38/42", "naklon": 5 }, + "3501": { "label": "38/43", "naklon": 5 }, + "3581": { "label": "38/44", "naklon": 5 }, + "4192": { "label": "38/45", "naklon": 5 }, + "3576": { "label": "38/46", "naklon": 5 }, + "3489": { "label": "38/47", "naklon": 5 }, + "3573": { "label": "38/48", "naklon": 5 }, + "3504": { "label": "38/49", "naklon": 5 }, + "3794": { "label": "38/50", "naklon": 5 }, + "3485": { "label": "38/51", "naklon": 5 }, + "3482": { "label": "38/52", "naklon": 5 }, + "3575": { "label": "38/53", "naklon": 5 }, + "3499": { "label": "38/54", "naklon": 5 }, + "3494": { "label": "38/55", "naklon": 5 }, + "3583": { "label": "38/56", "naklon": 5 }, + "3570": { "label": "38/57", "naklon": 5 }, + "3500": { "label": "38/58", "naklon": 0 }, + "3510": { "label": "38/63", "naklon": null }, + "3512": { "label": "38/64", "naklon": null }, + "3535": { "label": "38/67", "naklon": null }, + "3531": { "label": "38/68", "naklon": null }, + "3537": { "label": "38/69", "naklon": null }, + "3522": { "label": "39/1", "naklon": 10 }, + "4018": { "label": "39/2", "naklon": 10 }, + "4019": { "label": "39/3", "naklon": 10 }, + "4154": { "label": "39/4", "naklon": 5 }, + "3907": { "label": "39/5", "naklon": 5 }, + "4148": { "label": "39/6", "naklon": 0 }, + "4153": { "label": "39/7", "naklon": 0 }, + "3938": { "label": "39/8", "naklon": 0 }, + "3802": { "label": "39/9", "naklon": 0 }, + "4015": { "label": "39/10", "naklon": 0 }, + "3929": { "label": "39/11", "naklon": 0 }, + "3946": { "label": "39/12", "naklon": 0 }, + "4014": { "label": "39/13", "naklon": 0 }, + "4155": { "label": "39/14", "naklon": 0 }, + "4149": { "label": "39/15", "naklon": 0 }, + "3642": { "label": "39/16", "naklon": 0 }, + "3636": { "label": "39/17", "naklon": 5 }, + "3991": { "label": "39/18", "naklon": 0 }, + "3994": { "label": "39/19", "naklon": 0 }, + "3990": { "label": "39/20", "naklon": 0 }, + "3967": { "label": "39/21", "naklon": 0 }, + "3977": { "label": "39/22", "naklon": 0 }, + "3757": { "label": "39/23", "naklon": 15 }, + "3633": { "label": "39/24", "naklon": 15 }, + "3744": { "label": "39/25", "naklon": 15 }, + "4023": { "label": "39/26", "naklon": 5 }, + "3720": { "label": "39/27", "naklon": 5 }, + "3734": { "label": "39/28", "naklon": 5 }, + "3741": { "label": "39/29", "naklon": 5 }, + "3721": { "label": "39/30", "naklon": 5 }, + "3845": { "label": "39/31", "naklon": 0 }, + "3840": { "label": "39/32", "naklon": 0 }, + "3837": { "label": "39/33", "naklon": null }, + "3839": { "label": "39/34", "naklon": 0 }, + "3542": { "label": "41/1", "naklon": null }, + "3566": { "label": "41/2", "naklon": null }, + "3548": { "label": "41/3", "naklon": null }, + "3515": { "label": "41/4", "naklon": null }, + "3559": { "label": "41/5", "naklon": null }, + "3509": { "label": "41/6", "naklon": null }, + "3524": { "label": "41/7", "naklon": null }, + "3518": { "label": "41/8", "naklon": null }, + "3182": { "label": "41/9", "naklon": null }, + "3187": { "label": "41/10", "naklon": null }, + "3195": { "label": "41/11", "naklon": 0 }, + "3857": { "label": "41/12", "naklon": 0 }, + "3183": { "label": "41/13", "naklon": 0 }, + "3177": { "label": "41/14", "naklon": 0 }, + "3189": { "label": "41/15", "naklon": 0 }, + "3186": { "label": "41/16", "naklon": 0 }, + "3178": { "label": "42/1", "naklon": 0 }, + "3219": { "label": "42/2", "naklon": 0 }, + "3475": { "label": "42/3", "naklon": 0 }, + "3175": { "label": "42/4", "naklon": 0 }, + "3222": { "label": "42/5", "naklon": 0 }, + "3221": { "label": "42/6", "naklon": 0 }, + "3181": { "label": "42/7", "naklon": 0 }, + "3180": { "label": "42/8", "naklon": 0 }, + "3218": { "label": "42/9", "naklon": 0 }, + "3176": { "label": "42/10", "naklon": 0 }, + "3174": { "label": "42/11", "naklon": 0 }, + "3220": { "label": "42/12", "naklon": 0 }, + "3533": { "label": "42/13", "naklon": null }, + "3543": { "label": "42/14", "naklon": null }, + "3554": { "label": "42/15", "naklon": null }, + "3549": { "label": "42/16", "naklon": null }, + "2857": { "label": "43/1", "naklon": 5 }, + "2752": { "label": "43/2", "naklon": 5 }, + "2753": { "label": "43/3", "naklon": 5 }, + "3024": { "label": "43/4", "naklon": 5 }, + "2754": { "label": "43/5", "naklon": 5 }, + "4423": { "label": "43/6", "naklon": 5 }, + "4368": { "label": "43/7", "naklon": 5 }, + "2978": { "label": "43/8", "naklon": 5 }, + "2868": { "label": "43/9", "naklon": 5 }, + "4377": { "label": "43/10", "naklon": 5 }, + "2757": { "label": "43/11", "naklon": 5 }, + "2970": { "label": "43/12", "naklon": 5 }, + "2758": { "label": "43/13", "naklon": 5 }, + "4378": { "label": "43/14", "naklon": 5 }, + "2759": { "label": "43/15", "naklon": 5 }, + "4342": { "label": "43/16", "naklon": 5 }, + "3026": { "label": "43/17", "naklon": null }, + "2986": { "label": "43/18", "naklon": null }, + "4343": { "label": "43/19", "naklon": null }, + "2760": { "label": "43/20", "naklon": null }, + "4379": { "label": "43/21", "naklon": null }, + "2971": { "label": "43/22", "naklon": null }, + "2761": { "label": "43/23", "naklon": null }, + "2762": { "label": "43/24", "naklon": null }, + "4339": { "label": "43/25", "naklon": null }, + "4380": { "label": "43/26", "naklon": null }, + "2975": { "label": "43/27", "naklon": null }, + "3003": { "label": "43/28", "naklon": null }, + "4338": { "label": "43/29", "naklon": null }, + "3002": { "label": "43/30", "naklon": null }, + "4345": { "label": "43/31", "naklon": null }, + "2979": { "label": "43/32", "naklon": null }, + "2989": { "label": "43/33", "naklon": null }, + "2996": { "label": "43/34", "naklon": null }, + "2972": { "label": "43/35", "naklon": null }, + "2988": { "label": "43/36", "naklon": null }, + "4344": { "label": "43/37", "naklon": null }, + "3022": { "label": "43/38", "naklon": null }, + "4341": { "label": "43/39", "naklon": null }, + "2983": { "label": "43/40", "naklon": null }, + "2995": { "label": "43/41", "naklon": null }, + "2763": { "label": "43/42", "naklon": null }, + "2764": { "label": "43/43", "naklon": null }, + "2765": { "label": "43/44", "naklon": null }, + "2766": { "label": "43/45", "naklon": null }, + "2767": { "label": "43/46", "naklon": null }, + "2768": { "label": "43/47", "naklon": null }, + "3018": { "label": "43/48", "naklon": null }, + "2982": { "label": "43/49", "naklon": null }, + "3019": { "label": "43/50", "naklon": 0 }, + "3013": { "label": "43/51", "naklon": null }, + "3007": { "label": "43/52", "naklon": null }, + "2980": { "label": "43/53", "naklon": null }, + "3011": { "label": "43/54", "naklon": null }, + "2672": { "label": "43/55", "naklon": null }, + "2673": { "label": "43/56", "naklon": null }, + "2674": { "label": "43/57", "naklon": null }, + "2675": { "label": "43/58", "naklon": null }, + "2676": { "label": "43/59", "naklon": null }, + "2677": { "label": "43/60", "naklon": null }, + "2678": { "label": "43/61", "naklon": null }, + "2679": { "label": "43/62", "naklon": null }, + "2680": { "label": "43/63", "naklon": null }, + "2840": { "label": "43/64", "naklon": null }, + "2682": { "label": "43/65", "naklon": null }, + "2683": { "label": "43/66", "naklon": null }, + "2684": { "label": "43/67", "naklon": 0 }, + "2685": { "label": "43/68", "naklon": null }, + "2686": { "label": "43/69", "naklon": null }, + "2687": { "label": "43/70", "naklon": null }, + "2688": { "label": "43/71", "naklon": null }, + "2689": { "label": "43/72", "naklon": null }, + "2690": { "label": "43/73", "naklon": null }, + "2691": { "label": "43/74", "naklon": null }, + "2692": { "label": "43/75", "naklon": null }, + "2693": { "label": "43/76", "naklon": 0 }, + "2694": { "label": "43/77", "naklon": null }, + "2695": { "label": "43/78", "naklon": null }, + "2696": { "label": "43/79", "naklon": 0 }, + "2697": { "label": "43/80", "naklon": null }, + "2698": { "label": "43/81", "naklon": 0 }, + "2699": { "label": "43/82", "naklon": null }, + "2700": { "label": "43/83", "naklon": 0 }, + "2744": { "label": "43/84", "naklon": null }, + "2745": { "label": "43/85", "naklon": 0 }, + "2746": { "label": "43/86", "naklon": null }, + "2747": { "label": "43/87", "naklon": 0 }, + "2748": { "label": "43/88", "naklon": null }, + "2749": { "label": "43/89", "naklon": 0 }, + "2841": { "label": "43/90", "naklon": null }, + "4237": { "label": "45/1", "naklon": 5 }, + "4226": { "label": "45/2", "naklon": 5 }, + "4242": { "label": "45/3", "naklon": 5 }, + "4179": { "label": "45/4", "naklon": 5 }, + "4247": { "label": "45/5", "naklon": 5 }, + "4245": { "label": "45/6", "naklon": 5 }, + "3872": { "label": "45/7", "naklon": 5 }, + "4175": { "label": "45/8", "naklon": 5 }, + "4236": { "label": "45/9", "naklon": 5 }, + "4170": { "label": "45/10", "naklon": 5 }, + "4238": { "label": "45/11", "naklon": 5 }, + "4246": { "label": "45/12", "naklon": 5 }, + "4166": { "label": "45/13", "naklon": 5 }, + "4227": { "label": "45/14", "naklon": 5 }, + "4171": { "label": "45/15", "naklon": 5 }, + "4180": { "label": "45/16", "naklon": 5 }, + "4244": { "label": "45/17", "naklon": 5 }, + "4199": { "label": "45/18", "naklon": 5 }, + "4239": { "label": "45/19", "naklon": 5 }, + "4207": { "label": "45/20", "naklon": 5 }, + "4223": { "label": "45/21", "naklon": 5 }, + "4230": { "label": "45/22", "naklon": 5 }, + "4233": { "label": "45/23", "naklon": 5 }, + "4222": { "label": "45/24", "naklon": 5 }, + "4217": { "label": "45/25", "naklon": 5 }, + "4243": { "label": "45/26", "naklon": 5 }, + "4200": { "label": "45/27", "naklon": 5 }, + "4228": { "label": "45/28", "naklon": 5 }, + "4211": { "label": "45/29", "naklon": 5 }, + "4234": { "label": "45/30", "naklon": 5 }, + "4235": { "label": "45/31", "naklon": 5 }, + "4203": { "label": "45/32", "naklon": 5 }, + "4240": { "label": "45/33", "naklon": 5 }, + "4224": { "label": "45/34", "naklon": 5 }, + "4232": { "label": "45/35", "naklon": 5 }, + "4231": { "label": "45/36", "naklon": 5 }, + "4161": { "label": "45/37", "naklon": 5 }, + "4225": { "label": "45/38", "naklon": 5 }, + "4241": { "label": "45/39", "naklon": 5 }, + "4229": { "label": "45/40", "naklon": 5 }, + "4221": { "label": "45/41", "naklon": 5 }, + "4212": { "label": "45/42", "naklon": 5 }, + "4216": { "label": "45/43", "naklon": 5 }, + "3864": { "label": "45/44", "naklon": null }, + "3806": { "label": "46/1", "naklon": 5 }, + "3813": { "label": "46/2", "naklon": 5 }, + "3815": { "label": "46/3", "naklon": 5 }, + "3807": { "label": "46/4", "naklon": 5 }, + "3895": { "label": "46/5", "naklon": 5 }, + "3809": { "label": "46/6", "naklon": 5 }, + "3820": { "label": "46/7", "naklon": 5 }, + "3805": { "label": "46/8", "naklon": 5 }, + "3894": { "label": "46/9", "naklon": 0 }, + "4055": { "label": "46/10", "naklon": 0 }, + "3812": { "label": "46/11", "naklon": 5 }, + "3822": { "label": "46/12", "naklon": 5 }, + "3821": { "label": "46/13", "naklon": 5 }, + "3808": { "label": "46/14", "naklon": 5 }, + "3799": { "label": "46/15", "naklon": 5 }, + "3816": { "label": "46/16", "naklon": 5 }, + "3751": { "label": "46/17", "naklon": 5 }, + "3814": { "label": "46/18", "naklon": 5 }, + "4044": { "label": "46/19", "naklon": 0 }, + "3931": { "label": "46/20", "naklon": 0 }, + "3902": { "label": "46/21", "naklon": 5 }, + "3916": { "label": "46/22", "naklon": 5 }, + "3892": { "label": "46/23", "naklon": 5 }, + "3914": { "label": "46/24", "naklon": 5 }, + "3898": { "label": "46/25", "naklon": 5 }, + "3897": { "label": "46/26", "naklon": 5 }, + "3885": { "label": "46/27", "naklon": 5 }, + "3906": { "label": "46/28", "naklon": 5 }, + "3930": { "label": "46/29", "naklon": 0 }, + "3936": { "label": "46/30", "naklon": 0 }, + "3860": { "label": "46/31", "naklon": 5 }, + "3841": { "label": "46/32", "naklon": 5 }, + "3873": { "label": "46/33", "naklon": 5 }, + "3854": { "label": "46/34", "naklon": 5 }, + "3939": { "label": "46/35", "naklon": 5 }, + "3858": { "label": "46/36", "naklon": 5 }, + "3940": { "label": "46/37", "naklon": 5 }, + "4035": { "label": "46/38", "naklon": 5 }, + "3373": { "label": "47/1", "naklon": 0 }, + "3374": { "label": "47/2", "naklon": 0 }, + "3384": { "label": "47/3", "naklon": 0 }, + "3385": { "label": "47/4", "naklon": 0 }, + "4051": { "label": "48/1", "naklon": 5 }, + "4041": { "label": "48/2", "naklon": 5 }, + "4056": { "label": "48/3", "naklon": 5 }, + "3875": { "label": "48/4", "naklon": 5 }, + "4061": { "label": "48/5", "naklon": 5 }, + "4047": { "label": "48/6", "naklon": 5 }, + "4060": { "label": "48/7", "naklon": 5 }, + "4059": { "label": "48/8", "naklon": 5 }, + "4058": { "label": "48/9", "naklon": 5 }, + "3635": { "label": "48/10", "naklon": 5 }, + "3640": { "label": "48/11", "naklon": 5 }, + "3747": { "label": "48/12", "naklon": 5 }, + "3629": { "label": "48/13", "naklon": 5 }, + "4048": { "label": "48/14", "naklon": 5 }, + "4063": { "label": "48/15", "naklon": 5 }, + "4062": { "label": "48/16", "naklon": 5 }, + "4043": { "label": "48/17", "naklon": 5 }, + "4052": { "label": "48/18", "naklon": 5 }, + "4042": { "label": "48/19", "naklon": 5 }, + "4053": { "label": "48/20", "naklon": 5 }, + "4167": { "label": "50/15A", "naklon": null }, + "4159": { "label": "50/15B", "naklon": null }, + "4183": { "label": "50/1", "naklon": 0 }, + "4157": { "label": "50/2", "naklon": 0 }, + "4160": { "label": "50/3", "naklon": 0 }, + "4173": { "label": "50/4", "naklon": 0 }, + "4177": { "label": "50/5", "naklon": 0 }, + "4174": { "label": "50/6", "naklon": 0 }, + "4178": { "label": "50/7", "naklon": 0 }, + "4195": { "label": "50/8", "naklon": 0 }, + "4169": { "label": "50/9", "naklon": 0 }, + "4162": { "label": "50/10", "naklon": 0 }, + "4158": { "label": "50/11", "naklon": 0 }, + "4182": { "label": "50/12", "naklon": 0 }, + "4194": { "label": "50/13", "naklon": 0 }, + "4184": { "label": "50/14", "naklon": 0 }, + "4197": { "label": "50/16", "naklon": null }, + "4164": { "label": "50/17", "naklon": null }, + "3306": { "label": "50/18", "naklon": null }, + "4168": { "label": "50/19", "naklon": null }, + "4193": { "label": "50/20", "naklon": null }, + "4187": { "label": "50/21", "naklon": null }, + "4163": { "label": "50/22", "naklon": null }, + "4165": { "label": "50/23", "naklon": null }, + "4185": { "label": "50/24", "naklon": null }, + "3904": { "label": "50/25", "naklon": null }, + "2619": { "label": "53/1", "naklon": 0 }, + "2623": { "label": "53/2", "naklon": 0 }, + "2617": { "label": "53/3", "naklon": 0 }, + "2622": { "label": "53/4", "naklon": 0 }, + "2618": { "label": "53/5", "naklon": 0 }, + "2626": { "label": "53/6", "naklon": 0 }, + "2869": { "label": "53/7", "naklon": 0 }, + "2613": { "label": "53/8", "naklon": 0 }, + "2608": { "label": "53/9", "naklon": 0 }, + "2611": { "label": "53/10", "naklon": 0 }, + "2598": { "label": "53/11", "naklon": 0 }, + "3528": { "label": "53/12", "naklon": 0 }, + "3545": { "label": "53/13", "naklon": 0 }, + "2620": { "label": "53/14", "naklon": 0 }, + "2612": { "label": "53/15", "naklon": 0 }, + "2615": { "label": "53/16", "naklon": 0 }, + "3722": { "label": "53/17", "naklon": 0 }, + "2624": { "label": "53/18", "naklon": 0 }, + "2609": { "label": "53/19", "naklon": 0 }, + "2625": { "label": "53/20", "naklon": 0 }, + "2602": { "label": "53/21", "naklon": 0 }, + "2610": { "label": "53/22", "naklon": 0 }, + "2599": { "label": "53/23", "naklon": 0 }, + "2605": { "label": "53/24", "naklon": 0 }, + "2593": { "label": "53/25", "naklon": 0 }, + "3074": { "label": "53/26", "naklon": 0 }, + "2740": { "label": "53/27", "naklon": 0 }, + "2614": { "label": "53/28", "naklon": 0 }, + "2601": { "label": "53/29", "naklon": 0 }, + "4196": { "label": "53/30", "naklon": 0 }, + "2607": { "label": "53/31", "naklon": 0 }, + "2582": { "label": "53/32", "naklon": 0 }, + "2594": { "label": "53/33", "naklon": 0 }, + "2589": { "label": "53/34", "naklon": 0 }, + "2596": { "label": "53/35", "naklon": 0 }, + "2603": { "label": "53/36", "naklon": 0 }, + "2597": { "label": "53/37", "naklon": 0 }, + "2590": { "label": "53/38", "naklon": 0 }, + "2581": { "label": "53/39", "naklon": 0 }, + "2583": { "label": "53/40", "naklon": 0 }, + "2580": { "label": "53/41", "naklon": 0 }, + "2579": { "label": "53/42", "naklon": 0 }, + "2797": { "label": "53/43", "naklon": 0 }, + "2577": { "label": "53/44", "naklon": 0 }, + "2586": { "label": "53/45", "naklon": 0 }, + "2588": { "label": "53/46", "naklon": 0 }, + "2591": { "label": "53/47", "naklon": 0 }, + "2592": { "label": "53/48", "naklon": 0 }, + "2573": { "label": "53/49", "naklon": 0 }, + "2595": { "label": "53/50", "naklon": 0 }, + "2587": { "label": "53/51", "naklon": 0 }, + "2578": { "label": "53/52", "naklon": 0 }, + "2574": { "label": "53/53", "naklon": 0 }, + "2571": { "label": "53/54", "naklon": 0 }, + "2570": { "label": "53/55", "naklon": 0 }, + "2576": { "label": "53/56", "naklon": 0 }, + "2881": { "label": "53/57", "naklon": 0 }, + "2575": { "label": "53/58", "naklon": 0 }, + "2572": { "label": "53/59", "naklon": 0 }, + "2569": { "label": "53/60", "naklon": 0 }, + "4324": { "label": "55/1", "naklon": 0 }, + "4319": { "label": "55/2", "naklon": 0 }, + "4327": { "label": "55/3", "naklon": 0 }, + "4333": { "label": "55/4", "naklon": 0 }, + "4332": { "label": "55/5", "naklon": 0 }, + "4320": { "label": "55/6", "naklon": 0 }, + "4317": { "label": "55/7", "naklon": 0 }, + "4318": { "label": "55/8", "naklon": 0 }, + "4328": { "label": "55/9", "naklon": 0 }, + "4323": { "label": "55/10", "naklon": 0 }, + "4325": { "label": "55/11", "naklon": 0 }, + "4326": { "label": "55/12", "naklon": 0 }, + "4316": { "label": "55/13", "naklon": 0 }, + "4322": { "label": "55/14", "naklon": 0 }, + "4331": { "label": "55/15", "naklon": 0 }, + "4321": { "label": "55/16", "naklon": 0 }, + "4315": { "label": "55/17", "naklon": 0 }, + "4329": { "label": "55/18", "naklon": 0 }, + "4334": { "label": "55/19", "naklon": 0 }, + "4330": { "label": "55/20", "naklon": 0 } +}; + + +let svetlaSorted = [{ "label": "1/3A", "node": 3993, "naklon": 0 }, +{ "label": "1/3B", "node": 3989, "naklon": 15 }, +{ "label": "1/1", "node": 3976, "naklon": 0 }, +{ "label": "1/2", "node": 4181, "naklon": 0 }, +{ "label": "1/4", "node": 4376, "naklon": 15 }, +{ "label": "1/5", "node": 3868, "naklon": 15 }, +{ "label": "1/6", "node": 3728, "naklon": 15 }, +{ "label": "1/7", "node": 3730, "naklon": 0 }, +{ "label": "1/8", "node": 4374, "naklon": 0 }, +{ "label": "1/9", "node": 3718, "naklon": 15 }, +{ "label": "1/10", "node": 4375, "naklon": 15 }, +{ "label": "1/11", "node": 4172, "naklon": 15 }, +{ "label": "1/12", "node": 4176, "naklon": 15 }, +{ "label": "2/1", "node": 3800, "naklon": 5 }, +{ "label": "2/2", "node": 3823, "naklon": 5 }, +{ "label": "2/3", "node": 3905, "naklon": 5 }, +{ "label": "2/4", "node": 3803, "naklon": 5 }, +{ "label": "2/5", "node": 3817, "naklon": 5 }, +{ "label": "2/6", "node": 3818, "naklon": 5 }, +{ "label": "2/7", "node": 3811, "naklon": 5 }, +{ "label": "2/8", "node": 3915, "naklon": 5 }, +{ "label": "2/9", "node": 3843, "naklon": 10 }, +{ "label": "2/10", "node": 3827, "naklon": 10 }, +{ "label": "2/11", "node": 4220, "naklon": 10 }, +{ "label": "2/12", "node": 3826, "naklon": 10 }, +{ "label": "2/13", "node": 3834, "naklon": 10 }, +{ "label": "2/14", "node": 3838, "naklon": 10 }, +{ "label": "2/15", "node": 2823, "naklon": 10 }, +{ "label": "2/16", "node": 3750, "naklon": 10 }, +{ "label": "2/17", "node": 3378, "naklon": 0 }, +{ "label": "2/18", "node": 3376, "naklon": 0 }, +{ "label": "2/19", "node": 3379, "naklon": 0 }, +{ "label": "2/20", "node": 3285, "naklon": 0 }, +{ "label": "2/21", "node": 3382, "naklon": 0 }, +{ "label": "2/22", "node": 3383, "naklon": 0 }, +{ "label": "2/24", "node": 3375, "naklon": 0 }, +{ "label": "2/25", "node": 3381, "naklon": 0 }, +{ "label": "2/26", "node": 3380, "naklon": 0 }, +{ "label": "2/27", "node": 3828, "naklon": 10 }, +{ "label": "2/28", "node": 3377, "naklon": 0 }, +{ "label": "7/1", "node": 3591, "naklon": 0 }, +{ "label": "7/2", "node": 3587, "naklon": 0 }, +{ "label": "7/3", "node": 3468, "naklon": 0 }, +{ "label": "7/4", "node": 3466, "naklon": 0 }, +{ "label": "7/5", "node": 3474, "naklon": 0 }, +{ "label": "7/6", "node": 3481, "naklon": 0 }, +{ "label": "7/7", "node": 3589, "naklon": 0 }, +{ "label": "7/8", "node": 3472, "naklon": 0 }, +{ "label": "7/9", "node": 3473, "naklon": 0 }, +{ "label": "7/10", "node": 3584, "naklon": 0 }, +{ "label": "7/11", "node": 3571, "naklon": 0 }, +{ "label": "7/12", "node": 3476, "naklon": 0 }, +{ "label": "7/13", "node": 3590, "naklon": 0 }, +{ "label": "7/14", "node": 3478, "naklon": 0 }, +{ "label": "7/15", "node": 3471, "naklon": 0 }, +{ "label": "7/16", "node": 3467, "naklon": 0 }, +{ "label": "7/17", "node": 3479, "naklon": 0 }, +{ "label": "7/18", "node": 3480, "naklon": 0 }, +{ "label": "7/19", "node": 3477, "naklon": 0 }, +{ "label": "12/1", "node": 3362, "naklon": 0 }, +{ "label": "12/2", "node": 3355, "naklon": 0 }, +{ "label": "12/3", "node": 3356, "naklon": 0 }, +{ "label": "12/4", "node": 3349, "naklon": 0 }, +{ "label": "12/5", "node": 3357, "naklon": 0 }, +{ "label": "12/6", "node": 3350, "naklon": 0 }, +{ "label": "12/7", "node": 3353, "naklon": 0 }, +{ "label": "12/8", "node": 3539, "naklon": 0 }, +{ "label": "12/9", "node": 3050, "naklon": 0 }, +{ "label": "12/10", "node": 3361, "naklon": 0 }, +{ "label": "12/11", "node": 3360, "naklon": 0 }, +{ "label": "12/12", "node": 3358, "naklon": 0 }, +{ "label": "12/13", "node": 3541, "naklon": 0 }, +{ "label": "12/14", "node": 3551, "naklon": 0 }, +{ "label": "12/15", "node": 3514, "naklon": 0 }, +{ "label": "12/16", "node": 3547, "naklon": 0 }, +{ "label": "12/17", "node": 3562, "naklon": 0 }, +{ "label": "12/18", "node": 3525, "naklon": 0 }, +{ "label": "12/19", "node": 3558, "naklon": 0 }, +{ "label": "12/20", "node": 3511, "naklon": 0 }, +{ "label": "12/21", "node": 3058, "naklon": 0 }, +{ "label": "12/22", "node": 3062, "naklon": 0 }, +{ "label": "12/23", "node": 3070, "naklon": 0 }, +{ "label": "12/24", "node": 3447, "naklon": 0 }, +{ "label": "12/25", "node": 3056, "naklon": 0 }, +{ "label": "12/26", "node": 3057, "naklon": 0 }, +{ "label": "12/27", "node": 3071, "naklon": 0 }, +{ "label": "12/28", "node": 3061, "naklon": 0 }, +{ "label": "12/29", "node": 3069, "naklon": 0 }, +{ "label": "12/30", "node": 3077, "naklon": 0 }, +{ "label": "12/31", "node": 3080, "naklon": 0 }, +{ "label": "12/32", "node": 3081, "naklon": 0 }, +{ "label": "12/33", "node": 3078, "naklon": 0 }, +{ "label": "12/34", "node": 4037, "naklon": 0 }, +{ "label": "12/35", "node": 3067, "naklon": 0 }, +{ "label": "12/36", "node": 3051, "naklon": 0 }, +{ "label": "12/37", "node": 2924, "naklon": 0 }, +{ "label": "12/38", "node": 3060, "naklon": 0 }, +{ "label": "12/39", "node": 3073, "naklon": 0 }, +{ "label": "12/40", "node": 3469, "naklon": 0 }, +{ "label": "12/41", "node": 2923, "naklon": 0 }, +{ "label": "12/42", "node": 2925, "naklon": 0 }, +{ "label": "12/43", "node": 3359, "naklon": 0 }, +{ "label": "12/44", "node": 3055, "naklon": 0 }, +{ "label": "12/45", "node": 2922, "naklon": 0 }, +{ "label": "12/46", "node": 3084, "naklon": 0 }, +{ "label": "12/47", "node": 3064, "naklon": 0 }, +{ "label": "12/48", "node": 3066, "naklon": 0 }, +{ "label": "12/49", "node": 3072, "naklon": 0 }, +{ "label": "13/13A", "node": 3415, "naklon": 0 }, +{ "label": "13/13B", "node": 3409, "naklon": 0 }, +{ "label": "13/13C", "node": 3399, "naklon": 0 }, +{ "label": "13/29A", "node": 3410, "naklon": 0 }, +{ "label": "13/29B", "node": 3407, "naklon": 0 }, +{ "label": "13/34A", "node": 3405, "naklon": 0 }, +{ "label": "13/34B", "node": 3404, "naklon": 0 }, +{ "label": "13/45A", "node": 3392, "naklon": 0 }, +{ "label": "13/45B", "node": 3386, "naklon": 0 }, +{ "label": "13/60A", "node": 3303, "naklon": 3 }, +{ "label": "13/60B", "node": 3302, "naklon": 3 }, +{ "label": "13/70A", "node": 3319, "naklon": 6 }, +{ "label": "13/70B", "node": 3317, "naklon": 6 }, +{ "label": "13/70C", "node": 3326, "naklon": 6 }, +{ "label": "13/73A", "node": 3351, "naklon": 6 }, +{ "label": "13/73B", "node": 3313, "naklon": 6 }, +{ "label": "13/83A", "node": 3316, "naklon": 0 }, +{ "label": "13/83B", "node": 3320, "naklon": 0 }, +{ "label": "13/95A", "node": 3336, "naklon": 0 }, +{ "label": "13/95B", "node": 3323, "naklon": 0 }, +{ "label": "13/98A", "node": 3339, "naklon": 0 }, +{ "label": "13/98B", "node": 3333, "naklon": 0 }, +{ "label": "13/1", "node": 3425, "naklon": 0 }, +{ "label": "13/2", "node": 3419, "naklon": 0 }, +{ "label": "13/3", "node": 3416, "naklon": 0 }, +{ "label": "13/4", "node": 3332, "naklon": 0 }, +{ "label": "13/5", "node": 3422, "naklon": 0 }, +{ "label": "13/6", "node": 3417, "naklon": 0 }, +{ "label": "13/7", "node": 3418, "naklon": 0 }, +{ "label": "13/8", "node": 3424, "naklon": 0 }, +{ "label": "13/9", "node": 3334, "naklon": 0 }, +{ "label": "13/10", "node": 4363, "naklon": 0 }, +{ "label": "13/11", "node": 3423, "naklon": 0 }, +{ "label": "13/12", "node": 3406, "naklon": 0 }, +{ "label": "13/14", "node": 3411, "naklon": 0 }, +{ "label": "13/15", "node": 3412, "naklon": 0 }, +{ "label": "13/16", "node": 3413, "naklon": 0 }, +{ "label": "13/17", "node": 3414, "naklon": 0 }, +{ "label": "13/18", "node": 3391, "naklon": 0 }, +{ "label": "13/19", "node": 3370, "naklon": 0 }, +{ "label": "13/20", "node": 3369, "naklon": 0 }, +{ "label": "13/21", "node": 3408, "naklon": 0 }, +{ "label": "13/22", "node": 3393, "naklon": 0 }, +{ "label": "13/23", "node": 3128, "naklon": 0 }, +{ "label": "13/24", "node": 3197, "naklon": 0 }, +{ "label": "13/25", "node": 4364, "naklon": 0 }, +{ "label": "13/26", "node": 3155, "naklon": 0 }, +{ "label": "13/27", "node": 3196, "naklon": 0 }, +{ "label": "13/28", "node": 3144, "naklon": 0 }, +{ "label": "13/30", "node": 3150, "naklon": 0 }, +{ "label": "13/31", "node": 3390, "naklon": 0 }, +{ "label": "13/32", "node": 3401, "naklon": 0 }, +{ "label": "13/33", "node": 3275, "naklon": 0 }, +{ "label": "13/35", "node": 3371, "naklon": 0 }, +{ "label": "13/36", "node": 3389, "naklon": 0 }, +{ "label": "13/37", "node": 3388, "naklon": 0 }, +{ "label": "13/38", "node": 3365, "naklon": 0 }, +{ "label": "13/39", "node": 3363, "naklon": 0 }, +{ "label": "13/40", "node": 3397, "naklon": 0 }, +{ "label": "13/40/1", "node": 3567, "naklon": 0 }, +{ "label": "13/41", "node": 3387, "naklon": 0 }, +{ "label": "13/42", "node": 3403, "naklon": 0 }, +{ "label": "13/43", "node": 3147, "naklon": 0 }, +{ "label": "13/44", "node": 3141, "naklon": 0 }, +{ "label": "13/46", "node": 3364, "naklon": 0 }, +{ "label": "13/47", "node": 3367, "naklon": 0 }, +{ "label": "13/48", "node": 3368, "naklon": 0 }, +{ "label": "13/49", "node": 3402, "naklon": 0 }, +{ "label": "13/50", "node": 3366, "naklon": 0 }, +{ "label": "13/51", "node": 3395, "naklon": 0 }, +{ "label": "13/52", "node": 3372, "naklon": 0 }, +{ "label": "13/53", "node": 3394, "naklon": 0 }, +{ "label": "13/54", "node": 3308, "naklon": 0 }, +{ "label": "13/54/1", "node": 3847, "naklon": 0 }, +{ "label": "13/55", "node": 3312, "naklon": 3 }, +{ "label": "13/56", "node": 3309, "naklon": 3 }, +{ "label": "13/57", "node": 3311, "naklon": 3 }, +{ "label": "13/58", "node": 3310, "naklon": 3 }, +{ "label": "13/59", "node": 4365, "naklon": 3 }, +{ "label": "13/60/1", "node": 4093, "naklon": 3 }, +{ "label": "13/61", "node": 3304, "naklon": 3 }, +{ "label": "13/62", "node": 3307, "naklon": 3 }, +{ "label": "13/63", "node": 3271, "naklon": 3 }, +{ "label": "13/64", "node": 3301, "naklon": 3 }, +{ "label": "13/65", "node": 4366, "naklon": 3 }, +{ "label": "13/66", "node": 3300, "naklon": 3 }, +{ "label": "13/67", "node": 3185, "naklon": 0 }, +{ "label": "13/68", "node": 3184, "naklon": 0 }, +{ "label": "13/69", "node": 3188, "naklon": 0 }, +{ "label": "13/71", "node": 3343, "naklon": 6 }, +{ "label": "13/71/1", "node": 3819, "naklon": 6 }, +{ "label": "13/71/2", "node": 3880, "naklon": 6 }, +{ "label": "13/72", "node": 3348, "naklon": 6 }, +{ "label": "13/74", "node": 3344, "naklon": 6 }, +{ "label": "13/75", "node": 3346, "naklon": 6 }, +{ "label": "13/75/1", "node": 3597, "naklon": 6 }, +{ "label": "13/76", "node": 3345, "naklon": 6 }, +{ "label": "13/77", "node": 3322, "naklon": 0 }, +{ "label": "13/78", "node": 3325, "naklon": 0 }, +{ "label": "13/78/1", "node": 4310, "naklon": 0 }, +{ "label": "13/79", "node": 3315, "naklon": 0 }, +{ "label": "13/80", "node": 3328, "naklon": 0 }, +{ "label": "13/81", "node": 3321, "naklon": 0 }, +{ "label": "13/82", "node": 3324, "naklon": 0 }, +{ "label": "13/84", "node": 3140, "naklon": 0 }, +{ "label": "13/85", "node": 3153, "naklon": 0 }, +{ "label": "13/86", "node": 3145, "naklon": 0 }, +{ "label": "13/87", "node": 3134, "naklon": 0 }, +{ "label": "13/88", "node": 3151, "naklon": 0 }, +{ "label": "13/89", "node": 3143, "naklon": 0 }, +{ "label": "13/90", "node": 3318, "naklon": 0 }, +{ "label": "13/91", "node": 3347, "naklon": 0 }, +{ "label": "13/94", "node": 3314, "naklon": 0 }, +{ "label": "13/96", "node": 3331, "naklon": 0 }, +{ "label": "13/97", "node": 3327, "naklon": 0 }, +{ "label": "13/99", "node": 3329, "naklon": 0 }, +{ "label": "13/100", "node": 3337, "naklon": 0 }, +{ "label": "13/101", "node": 3330, "naklon": 0 }, +{ "label": "13/102", "node": 3335, "naklon": 0 }, +{ "label": "13/103", "node": 3420, "naklon": 0 }, +{ "label": "13/104", "node": 3421, "naklon": 0 }, +{ "label": "13/105", "node": 4361, "naklon": 0 }, +{ "label": "13/106", "node": 4362, "naklon": 0 }, +{ "label": "13/107", "node": 3526, "naklon": 0 }, +{ "label": "13/108", "node": 4424, "naklon": null }, +{ "label": "13/109", "node": 3561, "naklon": null }, +{ "label": "13/110", "node": 3527, "naklon": null }, +{ "label": "13/111", "node": 3521, "naklon": null }, +{ "label": "13/112", "node": 3552, "naklon": null }, +{ "label": "13/113", "node": 3544, "naklon": null }, +{ "label": "13/114", "node": 3534, "naklon": null }, +{ "label": "13/115", "node": 3516, "naklon": null }, +{ "label": "13/116", "node": 3513, "naklon": null }, +{ "label": "13/117", "node": 3565, "naklon": null }, +{ "label": "13/118", "node": 3866, "naklon": null }, +{ "label": "14/1", "node": 3136, "naklon": 0 }, +{ "label": "14/2", "node": 3137, "naklon": 0 }, +{ "label": "14/3", "node": 3135, "naklon": 0 }, +{ "label": "14/4", "node": 3149, "naklon": 0 }, +{ "label": "14/5", "node": 3142, "naklon": 0 }, +{ "label": "14/6", "node": 3342, "naklon": 0 }, +{ "label": "14/7", "node": 3340, "naklon": 0 }, +{ "label": "14/8", "node": 3152, "naklon": 0 }, +{ "label": "14/9", "node": 3886, "naklon": 0 }, +{ "label": "14/10", "node": 3341, "naklon": null }, +{ "label": "14/11", "node": 3352, "naklon": null }, +{ "label": "15/1", "node": 3396, "naklon": 5 }, +{ "label": "15/2", "node": 2784, "naklon": 5 }, +{ "label": "15/3", "node": 2788, "naklon": 5 }, +{ "label": "15/4", "node": 2801, "naklon": 5 }, +{ "label": "15/5", "node": 2815, "naklon": 5 }, +{ "label": "15/6", "node": 2829, "naklon": 5 }, +{ "label": "15/7", "node": 2796, "naklon": 5 }, +{ "label": "15/8", "node": 2803, "naklon": 5 }, +{ "label": "15/8/1", "node": 4304, "naklon": 5 }, +{ "label": "15/8/2", "node": 4311, "naklon": 5 }, +{ "label": "15/9", "node": 2821, "naklon": 5 }, +{ "label": "15/10", "node": 3400, "naklon": 5 }, +{ "label": "15/11", "node": 2799, "naklon": 5 }, +{ "label": "15/12", "node": 2804, "naklon": 5 }, +{ "label": "15/12/1", "node": 4303, "naklon": 5 }, +{ "label": "15/12/2", "node": 4309, "naklon": 5 }, +{ "label": "15/13", "node": 2806, "naklon": 5 }, +{ "label": "15/14", "node": 2787, "naklon": 5 }, +{ "label": "15/15", "node": 2809, "naklon": 5 }, +{ "label": "15/16", "node": 2814, "naklon": 0 }, +{ "label": "15/17", "node": 3934, "naklon": 0 }, +{ "label": "15/18", "node": 3192, "naklon": 0 }, +{ "label": "15/19", "node": 2812, "naklon": 0 }, +{ "label": "15/20", "node": 4070, "naklon": 0 }, +{ "label": "15/21", "node": 2826, "naklon": 0 }, +{ "label": "15/22", "node": 2808, "naklon": 3 }, +{ "label": "15/23", "node": 2795, "naklon": 3 }, +{ "label": "15/24", "node": 2807, "naklon": 3 }, +{ "label": "15/25", "node": 2831, "naklon": 0 }, +{ "label": "15/26", "node": 2862, "naklon": null }, +{ "label": "15/27", "node": 2861, "naklon": 0 }, +{ "label": "15/28", "node": 2866, "naklon": 0 }, +{ "label": "15/28/1", "node": 3546, "naklon": 0 }, +{ "label": "15/29", "node": 4146, "naklon": 0 }, +{ "label": "15/29/1", "node": 3001, "naklon": 0 }, +{ "label": "15/30", "node": 2835, "naklon": 0 }, +{ "label": "15/31", "node": 2874, "naklon": 0 }, +{ "label": "15/32", "node": 2852, "naklon": 0 }, +{ "label": "15/33", "node": 2851, "naklon": 0 }, +{ "label": "15/33/1", "node": 3560, "naklon": 0 }, +{ "label": "15/34", "node": 2858, "naklon": 0 }, +{ "label": "15/34/1", "node": 4306, "naklon": 0 }, +{ "label": "15/35", "node": 2856, "naklon": 0 }, +{ "label": "15/36", "node": 2847, "naklon": 0 }, +{ "label": "15/36/1", "node": 3556, "naklon": 0 }, +{ "label": "15/37", "node": 3950, "naklon": 0 }, +{ "label": "15/38", "node": 2848, "naklon": 0 }, +{ "label": "15/39", "node": 2863, "naklon": 0 }, +{ "label": "15/39/1", "node": 4313, "naklon": 0 }, +{ "label": "15/40", "node": 2873, "naklon": 0 }, +{ "label": "15/40/1", "node": 2984, "naklon": 0 }, +{ "label": "15/41", "node": 2854, "naklon": 0 }, +{ "label": "15/42", "node": 2859, "naklon": 0 }, +{ "label": "15/43", "node": 2872, "naklon": 0 }, +{ "label": "15/44", "node": 2849, "naklon": 0 }, +{ "label": "15/45", "node": 2864, "naklon": 0 }, +{ "label": "15/46", "node": 3553, "naklon": null }, +{ "label": "15/47", "node": 3021, "naklon": null }, +{ "label": "15/47/1", "node": 3008, "naklon": null }, +{ "label": "15/48", "node": 3017, "naklon": null }, +{ "label": "15/49", "node": 3014, "naklon": null }, +{ "label": "15/50", "node": 2981, "naklon": null }, +{ "label": "15/51", "node": 3020, "naklon": null }, +{ "label": "15/52", "node": 3027, "naklon": null }, +{ "label": "15/53", "node": 3006, "naklon": null }, +{ "label": "15/54", "node": 3012, "naklon": null }, +{ "label": "15/55", "node": 2738, "naklon": 0 }, +{ "label": "15/56", "node": 2725, "naklon": 0 }, +{ "label": "15/57", "node": 3016, "naklon": null }, +{ "label": "15/58", "node": 3005, "naklon": null }, +{ "label": "15/58/1", "node": 3009, "naklon": null }, +{ "label": "15/59", "node": 3010, "naklon": 0 }, +{ "label": "15/59/1", "node": 3538, "naklon": 0 }, +{ "label": "15/59/2", "node": 4145, "naklon": 0 }, +{ "label": "15/60", "node": 2713, "naklon": 0 }, +{ "label": "15/61", "node": 2789, "naklon": 0 }, +{ "label": "15/62", "node": 2736, "naklon": 0 }, +{ "label": "15/63", "node": 2739, "naklon": 0 }, +{ "label": "15/64", "node": 4346, "naklon": 0 }, +{ "label": "15/65", "node": 2731, "naklon": 0 }, +{ "label": "15/66", "node": 2818, "naklon": 0 }, +{ "label": "15/66/1", "node": 3557, "naklon": 0 }, +{ "label": "15/67", "node": 2822, "naklon": 0 }, +{ "label": "15/68", "node": 2833, "naklon": 0 }, +{ "label": "15/69", "node": 2834, "naklon": 0 }, +{ "label": "15/70", "node": 3097, "naklon": 0 }, +{ "label": "15/71", "node": 2824, "naklon": 0 }, +{ "label": "15/72", "node": 2828, "naklon": 0 }, +{ "label": "15/73", "node": 2600, "naklon": 0 }, +{ "label": "15/73/1", "node": 4314, "naklon": 0 }, +{ "label": "15/74", "node": 2832, "naklon": 0 }, +{ "label": "15/75", "node": 4360, "naklon": 0 }, +{ "label": "15/76", "node": 2846, "naklon": 0 }, +{ "label": "15/77", "node": 2584, "naklon": 0 }, +{ "label": "15/78", "node": 2843, "naklon": 0 }, +{ "label": "15/78/1", "node": 4308, "naklon": 0 }, +{ "label": "15/79", "node": 4144, "naklon": null }, +{ "label": "15/80", "node": 2844, "naklon": 0 }, +{ "label": "15/81", "node": 2842, "naklon": 0 }, +{ "label": "15/82", "node": 2838, "naklon": 0 }, +{ "label": "15/83", "node": 2837, "naklon": null }, +{ "label": "15/83/1", "node": 3555, "naklon": null }, +{ "label": "15/84", "node": 2839, "naklon": 0 }, +{ "label": "15/85", "node": 2830, "naklon": 0 }, +{ "label": "15/86", "node": 4066, "naklon": 0 }, +{ "label": "15/87", "node": 2836, "naklon": 0 }, +{ "label": "15/88", "node": 2911, "naklon": 0 }, +{ "label": "15/89", "node": 2825, "naklon": 0 }, +{ "label": "15/90", "node": 2811, "naklon": 0 }, +{ "label": "15/94", "node": 3740, "naklon": 15 }, +{ "label": "15/95", "node": 2734, "naklon": 15 }, +{ "label": "15/96", "node": 3105, "naklon": 15 }, +{ "label": "15/97", "node": 2732, "naklon": 15 }, +{ "label": "15/98", "node": 2727, "naklon": 15 }, +{ "label": "15/99", "node": 2735, "naklon": 15 }, +{ "label": "15/100", "node": 3926, "naklon": 15 }, +{ "label": "15/101", "node": 2918, "naklon": 0 }, +{ "label": "15/102", "node": 2705, "naklon": 10 }, +{ "label": "15/103", "node": 2708, "naklon": 10 }, +{ "label": "15/104", "node": 2721, "naklon": 10 }, +{ "label": "15/105", "node": 2719, "naklon": 10 }, +{ "label": "15/106", "node": 2919, "naklon": 10 }, +{ "label": "15/107", "node": 3101, "naklon": 10 }, +{ "label": "15/108", "node": 2853, "naklon": 10 }, +{ "label": "15/109", "node": 2715, "naklon": 10 }, +{ "label": "15/110", "node": 2712, "naklon": 0 }, +{ "label": "15/111", "node": 2711, "naklon": 0 }, +{ "label": "15/112", "node": 2709, "naklon": 0 }, +{ "label": "15/113", "node": 2710, "naklon": 0 }, +{ "label": "15/114", "node": 2907, "naklon": 0 }, +{ "label": "15/115", "node": 2906, "naklon": 0 }, +{ "label": "15/116", "node": 2908, "naklon": 0 }, +{ "label": "15/117", "node": 2901, "naklon": 0 }, +{ "label": "15/118", "node": 2913, "naklon": 0 }, +{ "label": "15/119", "node": 3656, "naklon": 0 }, +{ "label": "15/120", "node": 2781, "naklon": 0 }, +{ "label": "15/121", "node": 2802, "naklon": 0 }, +{ "label": "15/122", "node": 2791, "naklon": 0 }, +{ "label": "15/123", "node": 2783, "naklon": 0 }, +{ "label": "15/124", "node": 2794, "naklon": 0 }, +{ "label": "15/125", "node": 3139, "naklon": 0 }, +{ "label": "15/126", "node": 3229, "naklon": 5 }, +{ "label": "15/127", "node": 3239, "naklon": 5 }, +{ "label": "15/128", "node": 3230, "naklon": 5 }, +{ "label": "15/129", "node": 4016, "naklon": null }, +{ "label": "16/16A", "node": 3608, "naklon": 0 }, +{ "label": "16/16B", "node": 4151, "naklon": 0 }, +{ "label": "16/1", "node": 3710, "naklon": 0 }, +{ "label": "16/2", "node": 3726, "naklon": 0 }, +{ "label": "16/3", "node": 3743, "naklon": 0 }, +{ "label": "16/4", "node": 3724, "naklon": 0 }, +{ "label": "16/5", "node": 3712, "naklon": 0 }, +{ "label": "16/6", "node": 3739, "naklon": 0 }, +{ "label": "16/7", "node": 3742, "naklon": 0 }, +{ "label": "16/8", "node": 3731, "naklon": 0 }, +{ "label": "16/9", "node": 3727, "naklon": 0 }, +{ "label": "16/10", "node": 3729, "naklon": 0 }, +{ "label": "16/11", "node": 3736, "naklon": 0 }, +{ "label": "16/12", "node": 3713, "naklon": 0 }, +{ "label": "16/13", "node": 3715, "naklon": 0 }, +{ "label": "16/14", "node": 3733, "naklon": 0 }, +{ "label": "16/15", "node": 3732, "naklon": 0 }, +{ "label": "16/17", "node": 3634, "naklon": 0 }, +{ "label": "16/18", "node": 3610, "naklon": 0 }, +{ "label": "16/19", "node": 3626, "naklon": 0 }, +{ "label": "16/20", "node": 3618, "naklon": 0 }, +{ "label": "16/21", "node": 3619, "naklon": 0 }, +{ "label": "16/22", "node": 3628, "naklon": 0 }, +{ "label": "16/23", "node": 3615, "naklon": 0 }, +{ "label": "16/24", "node": 3609, "naklon": 0 }, +{ "label": "16/25", "node": 3606, "naklon": 0 }, +{ "label": "16/26", "node": 3624, "naklon": 0 }, +{ "label": "16/27", "node": 3627, "naklon": 0 }, +{ "label": "16/28", "node": 3607, "naklon": 0 }, +{ "label": "16/29", "node": 4370, "naklon": 0 }, +{ "label": "16/30", "node": 3692, "naklon": 0 }, +{ "label": "16/31", "node": 3614, "naklon": 0 }, +{ "label": "16/32", "node": 3623, "naklon": 0 }, +{ "label": "16/33", "node": 4373, "naklon": 0 }, +{ "label": "16/34", "node": 3620, "naklon": 0 }, +{ "label": "16/35", "node": 3685, "naklon": 0 }, +{ "label": "16/36", "node": 3616, "naklon": 0 }, +{ "label": "16/37", "node": 3686, "naklon": 0 }, +{ "label": "16/38", "node": 3688, "naklon": 0 }, +{ "label": "16/39", "node": 3684, "naklon": 0 }, +{ "label": "16/40", "node": 3825, "naklon": 0 }, +{ "label": "16/41", "node": 3865, "naklon": 0 }, +{ "label": "16/42", "node": 3824, "naklon": 0 }, +{ "label": "16/43", "node": 3871, "naklon": 0 }, +{ "label": "16/44", "node": 3801, "naklon": 0 }, +{ "label": "16/45", "node": 3862, "naklon": 0 }, +{ "label": "16/46", "node": 3876, "naklon": 0 }, +{ "label": "16/47", "node": 3861, "naklon": 0 }, +{ "label": "16/48", "node": 4215, "naklon": 0 }, +{ "label": "16/49", "node": 3605, "naklon": 10 }, +{ "label": "16/50", "node": 3603, "naklon": 10 }, +{ "label": "16/51", "node": 3592, "naklon": 10 }, +{ "label": "16/52", "node": 3598, "naklon": 10 }, +{ "label": "16/53", "node": 3594, "naklon": 10 }, +{ "label": "16/54", "node": 3593, "naklon": 10 }, +{ "label": "16/55", "node": 3630, "naklon": 10 }, +{ "label": "16/56", "node": 3763, "naklon": 10 }, +{ "label": "16/57", "node": 3746, "naklon": 10 }, +{ "label": "16/58", "node": 3699, "naklon": 0 }, +{ "label": "16/59", "node": 3698, "naklon": 0 }, +{ "label": "16/60", "node": 3709, "naklon": null }, +{ "label": "16/61", "node": 3708, "naklon": 0 }, +{ "label": "16/62", "node": 3703, "naklon": null }, +{ "label": "16/63", "node": 3700, "naklon": 0 }, +{ "label": "16/64", "node": 3701, "naklon": null }, +{ "label": "16/65", "node": 3704, "naklon": 0 }, +{ "label": "16/66", "node": 3707, "naklon": null }, +{ "label": "16/67", "node": 3810, "naklon": 0 }, +{ "label": "16/68", "node": 4208, "naklon": null }, +{ "label": "16/69", "node": 3867, "naklon": 0 }, +{ "label": "16/70", "node": 4372, "naklon": null }, +{ "label": "16/71", "node": 3881, "naklon": 0 }, +{ "label": "16/72", "node": 4204, "naklon": null }, +{ "label": "16/73", "node": 3869, "naklon": 0 }, +{ "label": "16/74", "node": 4202, "naklon": null }, +{ "label": "16/75", "node": 3830, "naklon": 0 }, +{ "label": "16/76", "node": 3870, "naklon": null }, +{ "label": "16/77", "node": 3964, "naklon": 0 }, +{ "label": "16/78", "node": 3849, "naklon": 0 }, +{ "label": "16/79", "node": 3694, "naklon": null }, +{ "label": "16/80", "node": 3717, "naklon": 0 }, +{ "label": "16/81", "node": 3877, "naklon": null }, +{ "label": "16/82", "node": 3755, "naklon": 0 }, +{ "label": "16/83", "node": 3725, "naklon": null }, +{ "label": "16/84", "node": 3716, "naklon": 0 }, +{ "label": "16/85", "node": 3696, "naklon": null }, +{ "label": "16/86", "node": 3702, "naklon": 0 }, +{ "label": "16/87", "node": 3706, "naklon": null }, +{ "label": "16/88", "node": 3850, "naklon": 0 }, +{ "label": "16/89", "node": 3848, "naklon": null }, +{ "label": "16/90", "node": 3737, "naklon": null }, +{ "label": "16/91", "node": 3705, "naklon": 0 }, +{ "label": "16/92", "node": 3723, "naklon": null }, +{ "label": "16/93", "node": 3842, "naklon": 0 }, +{ "label": "16/94", "node": 3735, "naklon": null }, +{ "label": "16/95", "node": 3719, "naklon": 0 }, +{ "label": "16/96", "node": 3697, "naklon": 0 }, +{ "label": "16/97", "node": 3711, "naklon": 0 }, +{ "label": "16/98", "node": 4107, "naklon": null }, +{ "label": "16/99", "node": 4112, "naklon": 5 }, +{ "label": "16/100", "node": 4106, "naklon": 5 }, +{ "label": "16/101", "node": 4111, "naklon": 5 }, +{ "label": "16/102", "node": 4091, "naklon": null }, +{ "label": "16/103", "node": 4104, "naklon": 5 }, +{ "label": "16/104", "node": 4094, "naklon": null }, +{ "label": "16/105", "node": 4089, "naklon": 5 }, +{ "label": "16/106", "node": 4095, "naklon": null }, +{ "label": "16/107", "node": 4102, "naklon": 5 }, +{ "label": "16/108", "node": 4105, "naklon": null }, +{ "label": "16/109", "node": 3859, "naklon": null }, +{ "label": "16/110", "node": 4090, "naklon": 5 }, +{ "label": "16/111", "node": 4110, "naklon": null }, +{ "label": "16/112", "node": 4097, "naklon": 5 }, +{ "label": "16/113", "node": 4099, "naklon": null }, +{ "label": "16/114", "node": 4096, "naklon": null }, +{ "label": "16/115", "node": 4101, "naklon": 5 }, +{ "label": "16/116", "node": 4109, "naklon": null }, +{ "label": "16/117", "node": 4092, "naklon": 5 }, +{ "label": "16/118", "node": 3631, "naklon": null }, +{ "label": "16/119", "node": 3632, "naklon": 0 }, +{ "label": "16/120", "node": 3641, "naklon": null }, +{ "label": "16/121", "node": 3638, "naklon": 0 }, +{ "label": "16/122", "node": 3637, "naklon": null }, +{ "label": "16/123", "node": 4142, "naklon": null }, +{ "label": "16/124", "node": 4147, "naklon": 5 }, +{ "label": "16/125", "node": 4139, "naklon": 5 }, +{ "label": "20/30A", "node": 3172, "naklon": 2 }, +{ "label": "20/30B", "node": 3164, "naklon": 2 }, +{ "label": "20/1", "node": 3247, "naklon": 10 }, +{ "label": "20/2", "node": 3296, "naklon": 10 }, +{ "label": "20/3", "node": 3246, "naklon": 10 }, +{ "label": "20/4", "node": 3270, "naklon": 10 }, +{ "label": "20/5", "node": 3294, "naklon": 10 }, +{ "label": "20/6", "node": 3298, "naklon": 10 }, +{ "label": "20/7", "node": 3297, "naklon": 10 }, +{ "label": "20/8", "node": 3293, "naklon": 10 }, +{ "label": "20/9", "node": 3299, "naklon": 10 }, +{ "label": "20/10", "node": 3295, "naklon": 10 }, +{ "label": "20/11", "node": 3244, "naklon": 10 }, +{ "label": "20/12", "node": 3249, "naklon": 10 }, +{ "label": "20/13", "node": 3268, "naklon": 10 }, +{ "label": "20/14", "node": 3245, "naklon": 10 }, +{ "label": "20/15", "node": 3278, "naklon": 10 }, +{ "label": "20/16", "node": 3280, "naklon": 10 }, +{ "label": "20/17", "node": 3292, "naklon": 10 }, +{ "label": "20/18", "node": 3287, "naklon": 10 }, +{ "label": "20/19", "node": 3282, "naklon": 10 }, +{ "label": "20/20", "node": 3273, "naklon": 0 }, +{ "label": "20/21", "node": 3157, "naklon": 0 }, +{ "label": "20/22", "node": 3283, "naklon": 0 }, +{ "label": "20/23", "node": 3159, "naklon": 0 }, +{ "label": "20/24", "node": 3289, "naklon": 0 }, +{ "label": "20/25", "node": 3163, "naklon": 0 }, +{ "label": "20/26", "node": 3126, "naklon": 0 }, +{ "label": "20/27", "node": 3171, "naklon": 0 }, +{ "label": "20/28", "node": 3162, "naklon": 0 }, +{ "label": "20/29", "node": 3279, "naklon": 10 }, +{ "label": "20/31", "node": 3173, "naklon": 0 }, +{ "label": "20/32", "node": 3127, "naklon": 0 }, +{ "label": "20/33", "node": 3131, "naklon": 0 }, +{ "label": "20/34", "node": 3129, "naklon": 0 }, +{ "label": "20/35", "node": 3276, "naklon": 2 }, +{ "label": "20/36", "node": 3290, "naklon": 2 }, +{ "label": "20/37", "node": 3132, "naklon": 0 }, +{ "label": "20/38", "node": 3138, "naklon": 0 }, +{ "label": "20/39", "node": 3272, "naklon": 0 }, +{ "label": "20/40", "node": 3291, "naklon": 0 }, +{ "label": "20/41", "node": 3277, "naklon": 10 }, +{ "label": "20/42", "node": 3286, "naklon": 10 }, +{ "label": "20/43", "node": 3281, "naklon": 10 }, +{ "label": "20/44", "node": 3288, "naklon": 10 }, +{ "label": "20/45", "node": 3284, "naklon": 10 }, +{ "label": "20/46", "node": 3167, "naklon": 10 }, +{ "label": "20/47", "node": 3872, "naklon": 0 }, +{ "label": "20/48", "node": 3124, "naklon": 0 }, +{ "label": "20/49", "node": 3133, "naklon": 0 }, +{ "label": "20/50", "node": 3158, "naklon": 0 }, +{ "label": "20/51", "node": 3169, "naklon": 0 }, +{ "label": "20/52", "node": 3146, "naklon": 0 }, +{ "label": "20/53", "node": 3160, "naklon": 0 }, +{ "label": "20/54", "node": 3248, "naklon": 0 }, +{ "label": "20/55", "node": 3156, "naklon": 0 }, +{ "label": "20/56", "node": 3161, "naklon": 0 }, +{ "label": "20/57", "node": 3170, "naklon": 0 }, +{ "label": "20/58", "node": 3168, "naklon": 0 }, +{ "label": "20/59", "node": 3125, "naklon": 0 }, +{ "label": "20/60", "node": 3166, "naklon": 0 }, +{ "label": "20/61", "node": 3130, "naklon": 0 }, +{ "label": "20/62", "node": 3563, "naklon": 0 }, +{ "label": "20/63", "node": 3550, "naklon": null }, +{ "label": "20/67", "node": 3269, "naklon": 0 }, +{ "label": "21/1", "node": 2921, "naklon": 0 }, +{ "label": "21/2", "node": 2707, "naklon": 0 }, +{ "label": "21/3", "node": 2723, "naklon": 0 }, +{ "label": "21/4", "node": 2716, "naklon": 0 }, +{ "label": "21/5", "node": 2717, "naklon": 0 }, +{ "label": "21/6", "node": 2720, "naklon": 0 }, +{ "label": "21/7", "node": 2722, "naklon": 0 }, +{ "label": "21/8", "node": 2718, "naklon": 0 }, +{ "label": "21/9", "node": 2724, "naklon": 0 }, +{ "label": "21/10", "node": 2742, "naklon": 0 }, +{ "label": "21/11", "node": 2743, "naklon": 0 }, +{ "label": "21/12", "node": 2733, "naklon": 0 }, +{ "label": "21/14", "node": 2903, "naklon": 0 }, +{ "label": "21/15", "node": 2917, "naklon": 0 }, +{ "label": "21/16", "node": 2897, "naklon": 0 }, +{ "label": "21/17", "node": 2914, "naklon": 0 }, +{ "label": "21/18", "node": 2898, "naklon": 0 }, +{ "label": "21/19", "node": 2773, "naklon": 0 }, +{ "label": "21/20", "node": 2895, "naklon": 0 }, +{ "label": "21/21", "node": 2896, "naklon": 0 }, +{ "label": "21/22", "node": 2771, "naklon": 0 }, +{ "label": "21/23", "node": 2772, "naklon": 0 }, +{ "label": "21/24", "node": 2793, "naklon": 0 }, +{ "label": "21/25", "node": 2902, "naklon": 0 }, +{ "label": "21/26", "node": 2910, "naklon": 0 }, +{ "label": "21/27", "node": 2909, "naklon": 0 }, +{ "label": "21/28", "node": 2920, "naklon": 0 }, +{ "label": "21/29", "node": 2916, "naklon": 0 }, +{ "label": "21/30", "node": 2904, "naklon": 0 }, +{ "label": "21/31", "node": 2915, "naklon": 0 }, +{ "label": "21/32", "node": 2905, "naklon": 0 }, +{ "label": "21/33", "node": 2900, "naklon": 0 }, +{ "label": "21/34", "node": 2899, "naklon": 0 }, +{ "label": "21/36", "node": 2741, "naklon": 0 }, +{ "label": "21/37", "node": 2714, "naklon": 0 }, +{ "label": "21/38", "node": 2701, "naklon": 0 }, +{ "label": "21/39", "node": 2703, "naklon": 0 }, +{ "label": "21/40", "node": 2704, "naklon": 0 }, +{ "label": "21/41", "node": 2702, "naklon": 0 }, +{ "label": "21/42", "node": 2706, "naklon": 0 }, +{ "label": "21/43", "node": 2776, "naklon": 0 }, +{ "label": "21/44", "node": 2770, "naklon": 0 }, +{ "label": "21/45", "node": 2786, "naklon": 0 }, +{ "label": "21/46", "node": 2779, "naklon": 0 }, +{ "label": "21/47", "node": 2782, "naklon": 0 }, +{ "label": "21/48", "node": 2785, "naklon": 0 }, +{ "label": "21/49", "node": 2769, "naklon": 0 }, +{ "label": "21/50", "node": 3354, "naklon": 0 }, +{ "label": "21/51", "node": 2778, "naklon": 0 }, +{ "label": "21/52", "node": 2775, "naklon": 0 }, +{ "label": "21/53", "node": 2780, "naklon": 0 }, +{ "label": "21/54", "node": 2790, "naklon": 0 }, +{ "label": "21/55", "node": 2792, "naklon": 0 }, +{ "label": "21/56", "node": 2774, "naklon": 0 }, +{ "label": "22/1", "node": 2630, "naklon": 0 }, +{ "label": "22/2", "node": 2631, "naklon": 0 }, +{ "label": "22/3", "node": 2632, "naklon": 0 }, +{ "label": "22/4", "node": 2633, "naklon": 0 }, +{ "label": "22/5", "node": 2634, "naklon": 0 }, +{ "label": "22/6", "node": 2636, "naklon": 0 }, +{ "label": "22/7", "node": 4367, "naklon": 0 }, +{ "label": "22/8", "node": 2637, "naklon": 0 }, +{ "label": "22/9", "node": 2638, "naklon": 0 }, +{ "label": "22/10", "node": 2639, "naklon": 0 }, +{ "label": "22/11", "node": 2640, "naklon": 0 }, +{ "label": "22/12", "node": 2641, "naklon": 0 }, +{ "label": "22/13", "node": 2642, "naklon": 0 }, +{ "label": "22/14", "node": 2643, "naklon": 0 }, +{ "label": "22/15", "node": 2644, "naklon": 0 }, +{ "label": "22/16", "node": 2645, "naklon": 0 }, +{ "label": "22/17", "node": 2646, "naklon": 0 }, +{ "label": "22/18", "node": 2647, "naklon": 0 }, +{ "label": "22/19", "node": 2648, "naklon": 0 }, +{ "label": "22/20", "node": 2649, "naklon": 0 }, +{ "label": "22/21", "node": 2650, "naklon": 0 }, +{ "label": "22/22", "node": 2651, "naklon": 0 }, +{ "label": "22/23", "node": 4103, "naklon": 0 }, +{ "label": "22/24", "node": 2653, "naklon": 0 }, +{ "label": "22/25", "node": 2654, "naklon": 0 }, +{ "label": "22/26", "node": 2655, "naklon": 0 }, +{ "label": "22/27", "node": 2656, "naklon": 0 }, +{ "label": "22/28", "node": 2657, "naklon": 0 }, +{ "label": "22/29", "node": 2658, "naklon": 0 }, +{ "label": "22/30", "node": 2659, "naklon": 0 }, +{ "label": "22/31", "node": 2660, "naklon": 0 }, +{ "label": "22/32", "node": 2661, "naklon": 0 }, +{ "label": "22/32/1", "node": 3015, "naklon": 0 }, +{ "label": "22/33", "node": 2662, "naklon": 0 }, +{ "label": "22/34", "node": 2663, "naklon": 0 }, +{ "label": "22/35", "node": 2664, "naklon": 0 }, +{ "label": "22/36", "node": 2665, "naklon": 0 }, +{ "label": "22/37", "node": 2666, "naklon": 0 }, +{ "label": "22/38", "node": 2667, "naklon": 0 }, +{ "label": "22/39", "node": 2668, "naklon": 0 }, +{ "label": "22/40", "node": 2669, "naklon": null }, +{ "label": "22/41", "node": 2670, "naklon": null }, +{ "label": "22/42", "node": 2671, "naklon": null }, +{ "label": "23/9A", "node": 3087, "naklon": 10 }, +{ "label": "23/9B", "node": 3090, "naklon": 10 }, +{ "label": "23/1", "node": 3075, "naklon": 0 }, +{ "label": "23/2", "node": 3089, "naklon": 0 }, +{ "label": "23/3", "node": 3088, "naklon": 0 }, +{ "label": "23/4", "node": 3228, "naklon": 10 }, +{ "label": "23/5", "node": 2751, "naklon": 10 }, +{ "label": "23/6", "node": 3243, "naklon": 10 }, +{ "label": "23/7", "node": 4349, "naklon": 10 }, +{ "label": "23/8", "node": 3102, "naklon": 10 }, +{ "label": "23/10", "node": 3099, "naklon": 10 }, +{ "label": "23/11", "node": 3103, "naklon": 10 }, +{ "label": "23/12", "node": 3093, "naklon": 10 }, +{ "label": "23/13", "node": 3098, "naklon": 10 }, +{ "label": "23/14", "node": 3092, "naklon": 10 }, +{ "label": "23/15", "node": 3233, "naklon": 0 }, +{ "label": "23/16", "node": 3095, "naklon": 0 }, +{ "label": "23/17", "node": 4074, "naklon": 0 }, +{ "label": "23/18", "node": 2729, "naklon": 0 }, +{ "label": "23/19", "node": 3234, "naklon": 0 }, +{ "label": "23/20", "node": 3094, "naklon": 0 }, +{ "label": "23/21", "node": 2817, "naklon": 0 }, +{ "label": "23/22", "node": 3226, "naklon": 0 }, +{ "label": "23/23", "node": 3225, "naklon": 0 }, +{ "label": "23/24", "node": 3237, "naklon": 0 }, +{ "label": "23/25", "node": 4250, "naklon": 0 }, +{ "label": "23/26", "node": 3059, "naklon": 10 }, +{ "label": "23/27", "node": 3238, "naklon": 10 }, +{ "label": "23/28", "node": 3242, "naklon": 10 }, +{ "label": "23/29", "node": 3236, "naklon": 10 }, +{ "label": "23/30", "node": 3112, "naklon": 10 }, +{ "label": "23/31", "node": 3224, "naklon": 0 }, +{ "label": "23/32", "node": 4298, "naklon": 10 }, +{ "label": "23/33", "node": 4150, "naklon": 10 }, +{ "label": "23/34", "node": 3091, "naklon": 10 }, +{ "label": "25/1", "node": 3771, "naklon": 5 }, +{ "label": "25/2", "node": 3777, "naklon": 5 }, +{ "label": "25/3", "node": 3749, "naklon": 5 }, +{ "label": "25/4", "node": 3769, "naklon": 5 }, +{ "label": "25/5", "node": 3765, "naklon": 5 }, +{ "label": "25/6", "node": 3785, "naklon": 5 }, +{ "label": "25/7", "node": 3761, "naklon": 5 }, +{ "label": "25/8", "node": 3758, "naklon": 5 }, +{ "label": "25/9", "node": 3766, "naklon": 5 }, +{ "label": "25/10", "node": 3779, "naklon": 5 }, +{ "label": "25/11", "node": 3899, "naklon": 10 }, +{ "label": "25/12", "node": 3922, "naklon": 10 }, +{ "label": "25/13", "node": 3912, "naklon": 10 }, +{ "label": "25/14", "node": 3933, "naklon": 10 }, +{ "label": "25/15", "node": 3921, "naklon": 10 }, +{ "label": "25/16", "node": 4300, "naklon": 10 }, +{ "label": "25/17", "node": 3927, "naklon": 10 }, +{ "label": "25/18", "node": 3212, "naklon": 10 }, +{ "label": "25/19", "node": 3208, "naklon": 10 }, +{ "label": "25/20", "node": 3207, "naklon": 10 }, +{ "label": "25/21", "node": 4294, "naklon": 10 }, +{ "label": "25/22", "node": 3209, "naklon": 10 }, +{ "label": "25/23", "node": 3745, "naklon": 10 }, +{ "label": "25/24", "node": 3762, "naklon": 10 }, +{ "label": "25/25", "node": 3215, "naklon": 10 }, +{ "label": "25/26", "node": 3210, "naklon": 10 }, +{ "label": "25/27", "node": 3211, "naklon": 10 }, +{ "label": "25/28", "node": 3206, "naklon": 10 }, +{ "label": "25/29", "node": 3918, "naklon": 5 }, +{ "label": "25/30", "node": 3928, "naklon": 5 }, +{ "label": "25/31", "node": 3917, "naklon": 5 }, +{ "label": "25/32", "node": 4029, "naklon": 0 }, +{ "label": "25/33", "node": 4038, "naklon": 0 }, +{ "label": "25/34", "node": 4022, "naklon": 0 }, +{ "label": "25/35", "node": 3937, "naklon": 0 }, +{ "label": "25/36", "node": 3190, "naklon": 0 }, +{ "label": "25/37", "node": 3835, "naklon": 0 }, +{ "label": "25/38", "node": 3201, "naklon": 0 }, +{ "label": "25/39", "node": 3193, "naklon": 0 }, +{ "label": "25/40", "node": 3191, "naklon": 0 }, +{ "label": "25/41", "node": 3203, "naklon": 0 }, +{ "label": "25/42", "node": 4301, "naklon": 0 }, +{ "label": "25/43", "node": 3223, "naklon": 0 }, +{ "label": "25/44", "node": 3202, "naklon": 0 }, +{ "label": "25/45", "node": 3205, "naklon": 0 }, +{ "label": "25/46", "node": 3194, "naklon": 0 }, +{ "label": "25/47", "node": 3198, "naklon": 0 }, +{ "label": "25/48", "node": 3204, "naklon": 0 }, +{ "label": "25/49", "node": 3200, "naklon": 0 }, +{ "label": "25/50", "node": 3216, "naklon": 0 }, +{ "label": "25/51", "node": 3932, "naklon": 5 }, +{ "label": "25/52", "node": 3923, "naklon": 5 }, +{ "label": "25/53", "node": 3913, "naklon": 5 }, +{ "label": "25/54", "node": 3900, "naklon": 5 }, +{ "label": "25/55", "node": 4189, "naklon": 10 }, +{ "label": "25/56", "node": 4191, "naklon": 10 }, +{ "label": "25/57", "node": 3790, "naklon": 10 }, +{ "label": "25/58", "node": 4190, "naklon": 10 }, +{ "label": "25/59", "node": 4302, "naklon": 0 }, +{ "label": "25/60", "node": 4351, "naklon": 0 }, +{ "label": "25/61", "node": 4075, "naklon": 0 }, +{ "label": "25/62", "node": 4071, "naklon": 0 }, +{ "label": "25/63", "node": 3784, "naklon": 0 }, +{ "label": "25/64", "node": 4065, "naklon": 0 }, +{ "label": "25/65", "node": 4297, "naklon": 0 }, +{ "label": "25/66", "node": 4295, "naklon": 0 }, +{ "label": "25/67", "node": 4299, "naklon": 0 }, +{ "label": "25/68", "node": 3772, "naklon": 0 }, +{ "label": "25/69", "node": 3941, "naklon": 0 }, +{ "label": "25/70", "node": 3782, "naklon": 0 }, +{ "label": "25/71", "node": 4068, "naklon": 0 }, +{ "label": "25/72", "node": 4073, "naklon": 0 }, +{ "label": "25/73", "node": 3901, "naklon": 5 }, +{ "label": "25/74", "node": 4296, "naklon": 5 }, +{ "label": "25/75", "node": 3910, "naklon": 5 }, +{ "label": "25/76", "node": 4293, "naklon": 5 }, +{ "label": "25/77", "node": 3919, "naklon": 5 }, +{ "label": "25/78", "node": 3924, "naklon": 5 }, +{ "label": "25/79", "node": 3909, "naklon": 5 }, +{ "label": "25/80", "node": 3896, "naklon": 5 }, +{ "label": "25/81", "node": 3911, "naklon": 5 }, +{ "label": "25/82", "node": 2819, "naklon": 15 }, +{ "label": "25/83", "node": 3776, "naklon": 15 }, +{ "label": "25/84", "node": 3752, "naklon": 15 }, +{ "label": "25/85", "node": 4353, "naklon": 15 }, +{ "label": "25/86", "node": 3791, "naklon": 0 }, +{ "label": "25/87", "node": 3770, "naklon": 0 }, +{ "label": "25/88", "node": 3760, "naklon": 0 }, +{ "label": "25/89", "node": 3115, "naklon": 0 }, +{ "label": "25/90", "node": 3738, "naklon": 0 }, +{ "label": "25/91", "node": 3748, "naklon": 0 }, +{ "label": "25/92", "node": 3753, "naklon": 0 }, +{ "label": "25/93", "node": 3775, "naklon": 0 }, +{ "label": "25/94", "node": 3778, "naklon": 5 }, +{ "label": "25/95", "node": 4078, "naklon": 5 }, +{ "label": "25/96", "node": 4088, "naklon": 5 }, +{ "label": "25/97", "node": 3856, "naklon": 5 }, +{ "label": "25/98", "node": 4084, "naklon": 5 }, +{ "label": "25/99", "node": 4069, "naklon": 5 }, +{ "label": "25/100", "node": 4188, "naklon": 5 }, +{ "label": "25/101", "node": 4064, "naklon": 5 }, +{ "label": "25/102", "node": 3792, "naklon": 5 }, +{ "label": "25/103", "node": 3780, "naklon": 5 }, +{ "label": "25/104", "node": 4034, "naklon": 5 }, +{ "label": "25/105", "node": 4072, "naklon": 5 }, +{ "label": "25/106", "node": 3884, "naklon": 5 }, +{ "label": "25/107", "node": 3793, "naklon": 5 }, +{ "label": "25/108", "node": 3863, "naklon": 5 }, +{ "label": "25/109", "node": 3855, "naklon": 5 }, +{ "label": "33/1", "node": 3846, "naklon": 0 }, +{ "label": "33/2", "node": 3943, "naklon": 0 }, +{ "label": "33/3", "node": 3903, "naklon": 0 }, +{ "label": "33/4", "node": 3982, "naklon": 0 }, +{ "label": "33/5", "node": 3879, "naklon": 0 }, +{ "label": "33/6", "node": 3887, "naklon": 0 }, +{ "label": "33/7", "node": 3920, "naklon": 5 }, +{ "label": "33/8", "node": 3942, "naklon": 5 }, +{ "label": "33/9", "node": 3829, "naklon": null }, +{ "label": "34/79A", "node": 3452, "naklon": 6 }, +{ "label": "34/79B", "node": 3460, "naklon": 6 }, +{ "label": "34/90A", "node": 3443, "naklon": 6 }, +{ "label": "34/90B", "node": 3445, "naklon": 6 }, +{ "label": "34/90C", "node": 3457, "naklon": 6 }, +{ "label": "34/97A", "node": 3461, "naklon": 6 }, +{ "label": "34/97B", "node": 3463, "naklon": 6 }, +{ "label": "34/98A", "node": 3426, "naklon": 6 }, +{ "label": "34/98B", "node": 3444, "naklon": 6 }, +{ "label": "34/99A", "node": 3453, "naklon": 6 }, +{ "label": "34/99B", "node": 3455, "naklon": 6 }, +{ "label": "34/1", "node": 4009, "naklon": 0 }, +{ "label": "34/2", "node": 3602, "naklon": 0 }, +{ "label": "34/3", "node": 3441, "naklon": 0 }, +{ "label": "34/4", "node": 3464, "naklon": 0 }, +{ "label": "34/5", "node": 3883, "naklon": 0 }, +{ "label": "34/6", "node": 4098, "naklon": 0 }, +{ "label": "34/7", "node": 4003, "naklon": 0 }, +{ "label": "34/8", "node": 4004, "naklon": 0 }, +{ "label": "34/9", "node": 3888, "naklon": 0 }, +{ "label": "34/10", "node": 3997, "naklon": 0 }, +{ "label": "34/11", "node": 4006, "naklon": 0 }, +{ "label": "34/12", "node": 4000, "naklon": 0 }, +{ "label": "34/13", "node": 4011, "naklon": 0 }, +{ "label": "34/14", "node": 3999, "naklon": 0 }, +{ "label": "34/15", "node": 3981, "naklon": 0 }, +{ "label": "34/16", "node": 3988, "naklon": 0 }, +{ "label": "34/17", "node": 3986, "naklon": 0 }, +{ "label": "34/18", "node": 3998, "naklon": 0 }, +{ "label": "34/19", "node": 3983, "naklon": 0 }, +{ "label": "34/20", "node": 4005, "naklon": 0 }, +{ "label": "34/21", "node": 4001, "naklon": 0 }, +{ "label": "34/22", "node": 4008, "naklon": 0 }, +{ "label": "34/23", "node": 4002, "naklon": 0 }, +{ "label": "34/24", "node": 3996, "naklon": 0 }, +{ "label": "34/25", "node": 4007, "naklon": 0 }, +{ "label": "34/26", "node": 4113, "naklon": 15 }, +{ "label": "34/27", "node": 3595, "naklon": 5 }, +{ "label": "34/28", "node": 3599, "naklon": 5 }, +{ "label": "34/29", "node": 3601, "naklon": 5 }, +{ "label": "34/30", "node": 4205, "naklon": 0 }, +{ "label": "34/31", "node": 3987, "naklon": null }, +{ "label": "34/32", "node": 4214, "naklon": 0 }, +{ "label": "34/33", "node": 4226, "naklon": 0 }, +{ "label": "34/34", "node": 4209, "naklon": 0 }, +{ "label": "34/35", "node": 4201, "naklon": 0 }, +{ "label": "34/36", "node": 3440, "naklon": 0 }, +{ "label": "34/37", "node": 3465, "naklon": 0 }, +{ "label": "34/38", "node": 3446, "naklon": 0 }, +{ "label": "34/39", "node": 4039, "naklon": 5 }, +{ "label": "34/40", "node": 4057, "naklon": 5 }, +{ "label": "34/41", "node": 3985, "naklon": 0 }, +{ "label": "34/42", "node": 3882, "naklon": 0 }, +{ "label": "34/43", "node": 4040, "naklon": 5 }, +{ "label": "34/44", "node": 3231, "naklon": 0 }, +{ "label": "34/45", "node": 3227, "naklon": 0 }, +{ "label": "34/46", "node": 3431, "naklon": 0 }, +{ "label": "34/47", "node": 4013, "naklon": 0 }, +{ "label": "34/48", "node": 4045, "naklon": 0 }, +{ "label": "34/49", "node": 3949, "naklon": 0 }, +{ "label": "34/50", "node": 3953, "naklon": 0 }, +{ "label": "34/51", "node": 3952, "naklon": 0 }, +{ "label": "34/52", "node": 3995, "naklon": 0 }, +{ "label": "34/53", "node": 3992, "naklon": 0 }, +{ "label": "34/54", "node": 4198, "naklon": 0 }, +{ "label": "34/55", "node": 3935, "naklon": 0 }, +{ "label": "34/56", "node": 4050, "naklon": 0 }, +{ "label": "34/57", "node": 4049, "naklon": 0 }, +{ "label": "34/58", "node": 4054, "naklon": 0 }, +{ "label": "34/59", "node": 3663, "naklon": 6 }, +{ "label": "34/60", "node": 3661, "naklon": 6 }, +{ "label": "34/61", "node": 3664, "naklon": 6 }, +{ "label": "34/62", "node": 3660, "naklon": 6 }, +{ "label": "34/63", "node": 3662, "naklon": 6 }, +{ "label": "34/65", "node": 3665, "naklon": 6 }, +{ "label": "34/66", "node": 3667, "naklon": 6 }, +{ "label": "34/67", "node": 3675, "naklon": 6 }, +{ "label": "34/68", "node": 3666, "naklon": 6 }, +{ "label": "34/69", "node": 3652, "naklon": 6 }, +{ "label": "34/70", "node": 3458, "naklon": 6 }, +{ "label": "34/70/1", "node": 4425, "naklon": 6 }, +{ "label": "34/71", "node": 3459, "naklon": 6 }, +{ "label": "34/72", "node": 3435, "naklon": 6 }, +{ "label": "34/73", "node": 3448, "naklon": 6 }, +{ "label": "34/74", "node": 3451, "naklon": 6 }, +{ "label": "34/75", "node": 3442, "naklon": 6 }, +{ "label": "34/76", "node": 3449, "naklon": 6 }, +{ "label": "34/77", "node": 3450, "naklon": 6 }, +{ "label": "34/78", "node": 3433, "naklon": 6 }, +{ "label": "34/80", "node": 3432, "naklon": 12 }, +{ "label": "34/81", "node": 3470, "naklon": 12 }, +{ "label": "34/82", "node": 3438, "naklon": 12 }, +{ "label": "34/83", "node": 3439, "naklon": 12 }, +{ "label": "34/84", "node": 4028, "naklon": 5 }, +{ "label": "34/85", "node": 3596, "naklon": 5 }, +{ "label": "34/86", "node": 4021, "naklon": 5 }, +{ "label": "34/87", "node": 3437, "naklon": 12 }, +{ "label": "34/88", "node": 3428, "naklon": 12 }, +{ "label": "34/89", "node": 3430, "naklon": 12 }, +{ "label": "34/91", "node": 3454, "naklon": 6 }, +{ "label": "34/92", "node": 3492, "naklon": 6 }, +{ "label": "34/93", "node": 3462, "naklon": 6 }, +{ "label": "34/94", "node": 3427, "naklon": 6 }, +{ "label": "34/95", "node": 3434, "naklon": 6 }, +{ "label": "34/96", "node": 3456, "naklon": 6 }, +{ "label": "34/98/1", "node": 4307, "naklon": 6 }, +{ "label": "35/1", "node": 3968, "naklon": 0 }, +{ "label": "35/2", "node": 3969, "naklon": 0 }, +{ "label": "35/3", "node": 3947, "naklon": 0 }, +{ "label": "35/4", "node": 3979, "naklon": 0 }, +{ "label": "35/5", "node": 3959, "naklon": 0 }, +{ "label": "35/6", "node": 3948, "naklon": 0 }, +{ "label": "35/7", "node": 3961, "naklon": 0 }, +{ "label": "35/8", "node": 3956, "naklon": 0 }, +{ "label": "35/9", "node": 3604, "naklon": 0 }, +{ "label": "35/10", "node": 3944, "naklon": 0 }, +{ "label": "35/11", "node": 3960, "naklon": 0 }, +{ "label": "35/12", "node": 3958, "naklon": 0 }, +{ "label": "35/13", "node": 4036, "naklon": 5 }, +{ "label": "35/18", "node": 3893, "naklon": 5 }, +{ "label": "35/19", "node": 4108, "naklon": 5 }, +{ "label": "35/20", "node": 4017, "naklon": 5 }, +{ "label": "35/21", "node": 3963, "naklon": 0 }, +{ "label": "35/22", "node": 3658, "naklon": 0 }, +{ "label": "35/23", "node": 3975, "naklon": 0 }, +{ "label": "35/24", "node": 3980, "naklon": 0 }, +{ "label": "35/25", "node": 4012, "naklon": 0 }, +{ "label": "35/26", "node": 3655, "naklon": 0 }, +{ "label": "35/27", "node": 3962, "naklon": 0 }, +{ "label": "35/28", "node": 3945, "naklon": 0 }, +{ "label": "35/29", "node": 3569, "naklon": 0 }, +{ "label": "35/30", "node": 3429, "naklon": 0 }, +{ "label": "35/31", "node": 3657, "naklon": 0 }, +{ "label": "35/32", "node": 3646, "naklon": 0 }, +{ "label": "35/33", "node": 3622, "naklon": 0 }, +{ "label": "35/34", "node": 3612, "naklon": 0 }, +{ "label": "35/35", "node": 3955, "naklon": 0 }, +{ "label": "35/37", "node": 3878, "naklon": 0 }, +{ "label": "35/38", "node": 3965, "naklon": 0 }, +{ "label": "35/39", "node": 3970, "naklon": 0 }, +{ "label": "35/40", "node": 3611, "naklon": 0 }, +{ "label": "35/41", "node": 2635, "naklon": 0 }, +{ "label": "35/42", "node": 3978, "naklon": 0 }, +{ "label": "35/43", "node": 4213, "naklon": 0 }, +{ "label": "35/44", "node": 3984, "naklon": 0 }, +{ "label": "35/45", "node": 4218, "naklon": 0 }, +{ "label": "35/46", "node": 3973, "naklon": 0 }, +{ "label": "35/47", "node": 3974, "naklon": 0 }, +{ "label": "35/48", "node": 3759, "naklon": 0 }, +{ "label": "35/49", "node": 3844, "naklon": 0 }, +{ "label": "35/50", "node": 3804, "naklon": 0 }, +{ "label": "35/51", "node": 3831, "naklon": 0 }, +{ "label": "35/52", "node": 3643, "naklon": 0 }, +{ "label": "35/53", "node": 3966, "naklon": 0 }, +{ "label": "35/54", "node": 3971, "naklon": 0 }, +{ "label": "35/55", "node": 3650, "naklon": 6 }, +{ "label": "35/56", "node": 3651, "naklon": 6 }, +{ "label": "35/57", "node": 3669, "naklon": 6 }, +{ "label": "35/58", "node": 3648, "naklon": 6 }, +{ "label": "35/59", "node": 3645, "naklon": 6 }, +{ "label": "35/60", "node": 3659, "naklon": 6 }, +{ "label": "35/61", "node": 3647, "naklon": 6 }, +{ "label": "35/62", "node": 3644, "naklon": 6 }, +{ "label": "35/63", "node": 3671, "naklon": 6 }, +{ "label": "35/64", "node": 3682, "naklon": 6 }, +{ "label": "35/65", "node": 3672, "naklon": 6 }, +{ "label": "35/66", "node": 3683, "naklon": 6 }, +{ "label": "35/67", "node": 3673, "naklon": 6 }, +{ "label": "35/68", "node": 3674, "naklon": 6 }, +{ "label": "35/69", "node": 3679, "naklon": 6 }, +{ "label": "35/70", "node": 3649, "naklon": 6 }, +{ "label": "35/71", "node": 3687, "naklon": 6 }, +{ "label": "35/72", "node": 3677, "naklon": 6 }, +{ "label": "35/73", "node": 3690, "naklon": 6 }, +{ "label": "35/74", "node": 3691, "naklon": 6 }, +{ "label": "35/75", "node": 3676, "naklon": 6 }, +{ "label": "35/76", "node": 3680, "naklon": 6 }, +{ "label": "35/77", "node": 3668, "naklon": 6 }, +{ "label": "35/78", "node": 3681, "naklon": 6 }, +{ "label": "35/79", "node": 3670, "naklon": 6 }, +{ "label": "35/80", "node": 3689, "naklon": 6 }, +{ "label": "35/81", "node": 3678, "naklon": 6 }, +{ "label": "35/82", "node": 3693, "naklon": 6 }, +{ "label": "35/83", "node": 3654, "naklon": null }, +{ "label": "36/1", "node": 4086, "naklon": 0 }, +{ "label": "36/2", "node": 4085, "naklon": 0 }, +{ "label": "36/3", "node": 4083, "naklon": 0 }, +{ "label": "36/4", "node": 4087, "naklon": 0 }, +{ "label": "36/5", "node": 4077, "naklon": 0 }, +{ "label": "36/6", "node": 4082, "naklon": 0 }, +{ "label": "36/7", "node": 4186, "naklon": 0 }, +{ "label": "36/8", "node": 4206, "naklon": 0 }, +{ "label": "36/9", "node": 4080, "naklon": 0 }, +{ "label": "36/10", "node": 4081, "naklon": 0 }, +{ "label": "36/11", "node": 4210, "naklon": 0 }, +{ "label": "36/12", "node": 4079, "naklon": 0 }, +{ "label": "36/13", "node": 4076, "naklon": 0 }, +{ "label": "36/14", "node": 3852, "naklon": 0 }, +{ "label": "36/15", "node": 2813, "naklon": 0 }, +{ "label": "36/16", "node": 4219, "naklon": 0 }, +{ "label": "37/1A", "node": 3104, "naklon": 15 }, +{ "label": "37/1B", "node": 3121, "naklon": 15 }, +{ "label": "37/2", "node": 3113, "naklon": 10 }, +{ "label": "37/3", "node": 3118, "naklon": 10 }, +{ "label": "37/4", "node": 3111, "naklon": 10 }, +{ "label": "37/5", "node": 4020, "naklon": 10 }, +{ "label": "37/6", "node": 3119, "naklon": 10 }, +{ "label": "37/7", "node": 3110, "naklon": 10 }, +{ "label": "37/8", "node": 3108, "naklon": 10 }, +{ "label": "37/12", "node": 3107, "naklon": 0 }, +{ "label": "37/13", "node": 3199, "naklon": 0 }, +{ "label": "37/14", "node": 3120, "naklon": 0 }, +{ "label": "37/15", "node": 3122, "naklon": 0 }, +{ "label": "37/16", "node": 3908, "naklon": 0 }, +{ "label": "37/17", "node": 3114, "naklon": 0 }, +{ "label": "37/18", "node": 3105, "naklon": 0 }, +{ "label": "37/19", "node": 3116, "naklon": 0 }, +{ "label": "37/20", "node": 3106, "naklon": 0 }, +{ "label": "37/21", "node": 2887, "naklon": 5 }, +{ "label": "37/22", "node": 2888, "naklon": 5 }, +{ "label": "37/23", "node": 2877, "naklon": 5 }, +{ "label": "37/24", "node": 2891, "naklon": 5 }, +{ "label": "37/25", "node": 2886, "naklon": 5 }, +{ "label": "37/26", "node": 2892, "naklon": 5 }, +{ "label": "37/27", "node": 2882, "naklon": 5 }, +{ "label": "37/28", "node": 2883, "naklon": 5 }, +{ "label": "37/29", "node": 2876, "naklon": 5 }, +{ "label": "37/30", "node": 3109, "naklon": 5 }, +{ "label": "37/31", "node": 4152, "naklon": 5 }, +{ "label": "37/32", "node": 3117, "naklon": 5 }, +{ "label": "37/33", "node": 2870, "naklon": 5 }, +{ "label": "37/34", "node": 2867, "naklon": 0 }, +{ "label": "37/35", "node": 2865, "naklon": 0 }, +{ "label": "37/36", "node": 3096, "naklon": 0 }, +{ "label": "37/37", "node": 2871, "naklon": 0 }, +{ "label": "37/38", "node": 2884, "naklon": 0 }, +{ "label": "37/39", "node": 2855, "naklon": 0 }, +{ "label": "37/40", "node": 2878, "naklon": 0 }, +{ "label": "37/41", "node": 2889, "naklon": 0 }, +{ "label": "37/42", "node": 2879, "naklon": 0 }, +{ "label": "37/43", "node": 2850, "naklon": 0 }, +{ "label": "37/44", "node": 2894, "naklon": 0 }, +{ "label": "37/45", "node": 2880, "naklon": 0 }, +{ "label": "37/46", "node": 2893, "naklon": 0 }, +{ "label": "37/47", "node": 2890, "naklon": 0 }, +{ "label": "37/48", "node": 4355, "naklon": 0 }, +{ "label": "37/49", "node": 2885, "naklon": 0 }, +{ "label": "37/50", "node": 2875, "naklon": 0 }, +{ "label": "38/30A", "node": 3486, "naklon": 5 }, +{ "label": "38/30B", "node": 3714, "naklon": 0 }, +{ "label": "38/32A", "node": 3483, "naklon": 5 }, +{ "label": "38/32B", "node": 3496, "naklon": 0 }, +{ "label": "38/35A", "node": 3487, "naklon": 5 }, +{ "label": "38/35B", "node": 3498, "naklon": 5 }, +{ "label": "38/38A", "node": 3578, "naklon": 5 }, +{ "label": "38/38B", "node": 3508, "naklon": 5 }, +{ "label": "38/59A", "node": 3787, "naklon": 5 }, +{ "label": "38/59B", "node": 3491, "naklon": 5 }, +{ "label": "38/1", "node": 3568, "naklon": null }, +{ "label": "38/2", "node": 3502, "naklon": 0 }, +{ "label": "38/3", "node": 3836, "naklon": 0 }, +{ "label": "38/4", "node": 3588, "naklon": 0 }, +{ "label": "38/5", "node": 3493, "naklon": 0 }, +{ "label": "38/6", "node": 3580, "naklon": 0 }, +{ "label": "38/7", "node": 3572, "naklon": 0 }, +{ "label": "38/8", "node": 3506, "naklon": 0 }, +{ "label": "38/9", "node": 3503, "naklon": 0 }, +{ "label": "38/10", "node": 3579, "naklon": 0 }, +{ "label": "38/11", "node": 3586, "naklon": 0 }, +{ "label": "38/12", "node": 3495, "naklon": 5 }, +{ "label": "38/13", "node": 3492, "naklon": 5 }, +{ "label": "38/14", "node": 3532, "naklon": 5 }, +{ "label": "38/15", "node": 3574, "naklon": 5 }, +{ "label": "38/16", "node": 4140, "naklon": 5 }, +{ "label": "38/17", "node": 3795, "naklon": 5 }, +{ "label": "38/18", "node": 3788, "naklon": 5 }, +{ "label": "38/19", "node": 3796, "naklon": 5 }, +{ "label": "38/20", "node": 3797, "naklon": 5 }, +{ "label": "38/21", "node": 3798, "naklon": 5 }, +{ "label": "38/22", "node": 3786, "naklon": 5 }, +{ "label": "38/23", "node": 4067, "naklon": 5 }, +{ "label": "38/24", "node": 3773, "naklon": 5 }, +{ "label": "38/25", "node": 3774, "naklon": 5 }, +{ "label": "38/26", "node": 3789, "naklon": 5 }, +{ "label": "38/27", "node": 3520, "naklon": null }, +{ "label": "38/29", "node": 3577, "naklon": 5 }, +{ "label": "38/31", "node": 3530, "naklon": null }, +{ "label": "38/33", "node": 3488, "naklon": 5 }, +{ "label": "38/34", "node": 3505, "naklon": 5 }, +{ "label": "38/36", "node": 3497, "naklon": 5 }, +{ "label": "38/37", "node": 3490, "naklon": 5 }, +{ "label": "38/39", "node": 3585, "naklon": 5 }, +{ "label": "38/40", "node": 3582, "naklon": 5 }, +{ "label": "38/41", "node": 3507, "naklon": 5 }, +{ "label": "38/42", "node": 3484, "naklon": 5 }, +{ "label": "38/43", "node": 3501, "naklon": 5 }, +{ "label": "38/44", "node": 3581, "naklon": 5 }, +{ "label": "38/45", "node": 4192, "naklon": 5 }, +{ "label": "38/46", "node": 3576, "naklon": 5 }, +{ "label": "38/47", "node": 3489, "naklon": 5 }, +{ "label": "38/48", "node": 3573, "naklon": 5 }, +{ "label": "38/49", "node": 3504, "naklon": 5 }, +{ "label": "38/50", "node": 3794, "naklon": 5 }, +{ "label": "38/51", "node": 3485, "naklon": 5 }, +{ "label": "38/52", "node": 3482, "naklon": 5 }, +{ "label": "38/53", "node": 3575, "naklon": 5 }, +{ "label": "38/54", "node": 3499, "naklon": 5 }, +{ "label": "38/55", "node": 3494, "naklon": 5 }, +{ "label": "38/56", "node": 3583, "naklon": 5 }, +{ "label": "38/57", "node": 3570, "naklon": 5 }, +{ "label": "38/58", "node": 3500, "naklon": 0 }, +{ "label": "38/63", "node": 3510, "naklon": null }, +{ "label": "38/64", "node": 3512, "naklon": null }, +{ "label": "38/67", "node": 3535, "naklon": null }, +{ "label": "38/68", "node": 3531, "naklon": null }, +{ "label": "38/69", "node": 3537, "naklon": null }, +{ "label": "39/1", "node": 3522, "naklon": 10 }, +{ "label": "39/2", "node": 4018, "naklon": 10 }, +{ "label": "39/3", "node": 4019, "naklon": 10 }, +{ "label": "39/4", "node": 4154, "naklon": 5 }, +{ "label": "39/5", "node": 3907, "naklon": 5 }, +{ "label": "39/6", "node": 4148, "naklon": 0 }, +{ "label": "39/7", "node": 4153, "naklon": 0 }, +{ "label": "39/8", "node": 3938, "naklon": 0 }, +{ "label": "39/9", "node": 3802, "naklon": 0 }, +{ "label": "39/10", "node": 4015, "naklon": 0 }, +{ "label": "39/11", "node": 3929, "naklon": 0 }, +{ "label": "39/12", "node": 3946, "naklon": 0 }, +{ "label": "39/13", "node": 4014, "naklon": 0 }, +{ "label": "39/14", "node": 4155, "naklon": 0 }, +{ "label": "39/15", "node": 4149, "naklon": 0 }, +{ "label": "39/16", "node": 3642, "naklon": 0 }, +{ "label": "39/17", "node": 3636, "naklon": 5 }, +{ "label": "39/18", "node": 3991, "naklon": 0 }, +{ "label": "39/19", "node": 3994, "naklon": 0 }, +{ "label": "39/20", "node": 3990, "naklon": 0 }, +{ "label": "39/21", "node": 3967, "naklon": 0 }, +{ "label": "39/22", "node": 3977, "naklon": 0 }, +{ "label": "39/23", "node": 3757, "naklon": 15 }, +{ "label": "39/24", "node": 3633, "naklon": 15 }, +{ "label": "39/25", "node": 3744, "naklon": 15 }, +{ "label": "39/26", "node": 4023, "naklon": 5 }, +{ "label": "39/27", "node": 3720, "naklon": 5 }, +{ "label": "39/28", "node": 3734, "naklon": 5 }, +{ "label": "39/29", "node": 3741, "naklon": 5 }, +{ "label": "39/30", "node": 3721, "naklon": 5 }, +{ "label": "39/31", "node": 3845, "naklon": 0 }, +{ "label": "39/32", "node": 3840, "naklon": 0 }, +{ "label": "39/33", "node": 3837, "naklon": null }, +{ "label": "39/34", "node": 3839, "naklon": 0 }, +{ "label": "41/1", "node": 3542, "naklon": null }, +{ "label": "41/2", "node": 3566, "naklon": null }, +{ "label": "41/3", "node": 3548, "naklon": null }, +{ "label": "41/4", "node": 3515, "naklon": null }, +{ "label": "41/5", "node": 3559, "naklon": null }, +{ "label": "41/6", "node": 3509, "naklon": null }, +{ "label": "41/7", "node": 3524, "naklon": null }, +{ "label": "41/8", "node": 3518, "naklon": null }, +{ "label": "41/9", "node": 3182, "naklon": null }, +{ "label": "41/10", "node": 3187, "naklon": null }, +{ "label": "41/11", "node": 3195, "naklon": 0 }, +{ "label": "41/12", "node": 3857, "naklon": 0 }, +{ "label": "41/13", "node": 3183, "naklon": 0 }, +{ "label": "41/14", "node": 3177, "naklon": 0 }, +{ "label": "41/15", "node": 3189, "naklon": 0 }, +{ "label": "41/16", "node": 3186, "naklon": 0 }, +{ "label": "42/1", "node": 3178, "naklon": 0 }, +{ "label": "42/2", "node": 3219, "naklon": 0 }, +{ "label": "42/3", "node": 3475, "naklon": 0 }, +{ "label": "42/4", "node": 3175, "naklon": 0 }, +{ "label": "42/5", "node": 3222, "naklon": 0 }, +{ "label": "42/6", "node": 3221, "naklon": 0 }, +{ "label": "42/7", "node": 3181, "naklon": 0 }, +{ "label": "42/8", "node": 3180, "naklon": 0 }, +{ "label": "42/9", "node": 3218, "naklon": 0 }, +{ "label": "42/10", "node": 3176, "naklon": 0 }, +{ "label": "42/11", "node": 3174, "naklon": 0 }, +{ "label": "42/12", "node": 3220, "naklon": 0 }, +{ "label": "42/13", "node": 3533, "naklon": null }, +{ "label": "42/14", "node": 3543, "naklon": null }, +{ "label": "42/15", "node": 3554, "naklon": null }, +{ "label": "42/16", "node": 3549, "naklon": null }, +{ "label": "43/1", "node": 2857, "naklon": 5 }, +{ "label": "43/2", "node": 2752, "naklon": 5 }, +{ "label": "43/3", "node": 2753, "naklon": 5 }, +{ "label": "43/4", "node": 3024, "naklon": 5 }, +{ "label": "43/5", "node": 2754, "naklon": 5 }, +{ "label": "43/6", "node": 4423, "naklon": 5 }, +{ "label": "43/7", "node": 4368, "naklon": 5 }, +{ "label": "43/8", "node": 2978, "naklon": 5 }, +{ "label": "43/9", "node": 2868, "naklon": 5 }, +{ "label": "43/10", "node": 4377, "naklon": 5 }, +{ "label": "43/11", "node": 2757, "naklon": 5 }, +{ "label": "43/12", "node": 2970, "naklon": 5 }, +{ "label": "43/13", "node": 2758, "naklon": 5 }, +{ "label": "43/14", "node": 4378, "naklon": 5 }, +{ "label": "43/15", "node": 2759, "naklon": 5 }, +{ "label": "43/16", "node": 4342, "naklon": 5 }, +{ "label": "43/17", "node": 3026, "naklon": null }, +{ "label": "43/18", "node": 2986, "naklon": null }, +{ "label": "43/19", "node": 4343, "naklon": null }, +{ "label": "43/20", "node": 2760, "naklon": null }, +{ "label": "43/21", "node": 4379, "naklon": null }, +{ "label": "43/22", "node": 2971, "naklon": null }, +{ "label": "43/23", "node": 2761, "naklon": null }, +{ "label": "43/24", "node": 2762, "naklon": null }, +{ "label": "43/25", "node": 4339, "naklon": null }, +{ "label": "43/26", "node": 4380, "naklon": null }, +{ "label": "43/27", "node": 2975, "naklon": null }, +{ "label": "43/28", "node": 3003, "naklon": null }, +{ "label": "43/29", "node": 4338, "naklon": null }, +{ "label": "43/30", "node": 3002, "naklon": null }, +{ "label": "43/31", "node": 4345, "naklon": null }, +{ "label": "43/32", "node": 2979, "naklon": null }, +{ "label": "43/33", "node": 2989, "naklon": null }, +{ "label": "43/34", "node": 2996, "naklon": null }, +{ "label": "43/35", "node": 2972, "naklon": null }, +{ "label": "43/36", "node": 2988, "naklon": null }, +{ "label": "43/37", "node": 4344, "naklon": null }, +{ "label": "43/38", "node": 3022, "naklon": null }, +{ "label": "43/39", "node": 4341, "naklon": null }, +{ "label": "43/40", "node": 2983, "naklon": null }, +{ "label": "43/41", "node": 2995, "naklon": null }, +{ "label": "43/42", "node": 2763, "naklon": null }, +{ "label": "43/43", "node": 2764, "naklon": null }, +{ "label": "43/44", "node": 2765, "naklon": null }, +{ "label": "43/45", "node": 2766, "naklon": null }, +{ "label": "43/46", "node": 2767, "naklon": null }, +{ "label": "43/47", "node": 2768, "naklon": null }, +{ "label": "43/48", "node": 3018, "naklon": null }, +{ "label": "43/49", "node": 2982, "naklon": null }, +{ "label": "43/50", "node": 3019, "naklon": 0 }, +{ "label": "43/51", "node": 3013, "naklon": null }, +{ "label": "43/52", "node": 3007, "naklon": null }, +{ "label": "43/53", "node": 2980, "naklon": null }, +{ "label": "43/54", "node": 3011, "naklon": null }, +{ "label": "43/55", "node": 2672, "naklon": null }, +{ "label": "43/56", "node": 2673, "naklon": null }, +{ "label": "43/57", "node": 2674, "naklon": null }, +{ "label": "43/58", "node": 2675, "naklon": null }, +{ "label": "43/59", "node": 2676, "naklon": null }, +{ "label": "43/60", "node": 2677, "naklon": null }, +{ "label": "43/61", "node": 2678, "naklon": null }, +{ "label": "43/62", "node": 2679, "naklon": null }, +{ "label": "43/63", "node": 2680, "naklon": null }, +{ "label": "43/64", "node": 2840, "naklon": null }, +{ "label": "43/65", "node": 2682, "naklon": null }, +{ "label": "43/66", "node": 2683, "naklon": null }, +{ "label": "43/67", "node": 2684, "naklon": 0 }, +{ "label": "43/68", "node": 2685, "naklon": null }, +{ "label": "43/69", "node": 2686, "naklon": null }, +{ "label": "43/70", "node": 2687, "naklon": null }, +{ "label": "43/71", "node": 2688, "naklon": null }, +{ "label": "43/72", "node": 2689, "naklon": null }, +{ "label": "43/73", "node": 2690, "naklon": null }, +{ "label": "43/74", "node": 2691, "naklon": null }, +{ "label": "43/75", "node": 2692, "naklon": null }, +{ "label": "43/76", "node": 2693, "naklon": 0 }, +{ "label": "43/77", "node": 2694, "naklon": null }, +{ "label": "43/78", "node": 2695, "naklon": null }, +{ "label": "43/79", "node": 2696, "naklon": 0 }, +{ "label": "43/80", "node": 2697, "naklon": null }, +{ "label": "43/81", "node": 2698, "naklon": 0 }, +{ "label": "43/82", "node": 2699, "naklon": null }, +{ "label": "43/83", "node": 2700, "naklon": 0 }, +{ "label": "43/84", "node": 2744, "naklon": null }, +{ "label": "43/85", "node": 2745, "naklon": 0 }, +{ "label": "43/86", "node": 2746, "naklon": null }, +{ "label": "43/87", "node": 2747, "naklon": 0 }, +{ "label": "43/88", "node": 2748, "naklon": null }, +{ "label": "43/89", "node": 2749, "naklon": 0 }, +{ "label": "43/90", "node": 2841, "naklon": null }, +{ "label": "45/1", "node": 4237, "naklon": 5 }, +{ "label": "45/2", "node": 4226, "naklon": 5 }, +{ "label": "45/3", "node": 4242, "naklon": 5 }, +{ "label": "45/4", "node": 4179, "naklon": 5 }, +{ "label": "45/5", "node": 4247, "naklon": 5 }, +{ "label": "45/6", "node": 4245, "naklon": 5 }, +{ "label": "45/7", "node": 3872, "naklon": 5 }, +{ "label": "45/8", "node": 4175, "naklon": 5 }, +{ "label": "45/9", "node": 4236, "naklon": 5 }, +{ "label": "45/10", "node": 4170, "naklon": 5 }, +{ "label": "45/11", "node": 4238, "naklon": 5 }, +{ "label": "45/12", "node": 4246, "naklon": 5 }, +{ "label": "45/13", "node": 4166, "naklon": 5 }, +{ "label": "45/14", "node": 4227, "naklon": 5 }, +{ "label": "45/15", "node": 4171, "naklon": 5 }, +{ "label": "45/16", "node": 4180, "naklon": 5 }, +{ "label": "45/17", "node": 4244, "naklon": 5 }, +{ "label": "45/18", "node": 4199, "naklon": 5 }, +{ "label": "45/19", "node": 4239, "naklon": 5 }, +{ "label": "45/20", "node": 4207, "naklon": 5 }, +{ "label": "45/21", "node": 4223, "naklon": 5 }, +{ "label": "45/22", "node": 4230, "naklon": 5 }, +{ "label": "45/23", "node": 4233, "naklon": 5 }, +{ "label": "45/24", "node": 4222, "naklon": 5 }, +{ "label": "45/25", "node": 4217, "naklon": 5 }, +{ "label": "45/26", "node": 4243, "naklon": 5 }, +{ "label": "45/27", "node": 4200, "naklon": 5 }, +{ "label": "45/28", "node": 4228, "naklon": 5 }, +{ "label": "45/29", "node": 4211, "naklon": 5 }, +{ "label": "45/30", "node": 4234, "naklon": 5 }, +{ "label": "45/31", "node": 4235, "naklon": 5 }, +{ "label": "45/32", "node": 4203, "naklon": 5 }, +{ "label": "45/33", "node": 4240, "naklon": 5 }, +{ "label": "45/34", "node": 4224, "naklon": 5 }, +{ "label": "45/35", "node": 4232, "naklon": 5 }, +{ "label": "45/36", "node": 4231, "naklon": 5 }, +{ "label": "45/37", "node": 4161, "naklon": 5 }, +{ "label": "45/38", "node": 4225, "naklon": 5 }, +{ "label": "45/39", "node": 4241, "naklon": 5 }, +{ "label": "45/40", "node": 4229, "naklon": 5 }, +{ "label": "45/41", "node": 4221, "naklon": 5 }, +{ "label": "45/42", "node": 4212, "naklon": 5 }, +{ "label": "45/43", "node": 4216, "naklon": 5 }, +{ "label": "45/44", "node": 3864, "naklon": null }, +{ "label": "46/1", "node": 3806, "naklon": 5 }, +{ "label": "46/2", "node": 3813, "naklon": 5 }, +{ "label": "46/3", "node": 3815, "naklon": 5 }, +{ "label": "46/4", "node": 3807, "naklon": 5 }, +{ "label": "46/5", "node": 3895, "naklon": 5 }, +{ "label": "46/6", "node": 3809, "naklon": 5 }, +{ "label": "46/7", "node": 3820, "naklon": 5 }, +{ "label": "46/8", "node": 3805, "naklon": 5 }, +{ "label": "46/9", "node": 3894, "naklon": 0 }, +{ "label": "46/10", "node": 4055, "naklon": 0 }, +{ "label": "46/11", "node": 3812, "naklon": 5 }, +{ "label": "46/12", "node": 3822, "naklon": 5 }, +{ "label": "46/13", "node": 3821, "naklon": 5 }, +{ "label": "46/14", "node": 3808, "naklon": 5 }, +{ "label": "46/15", "node": 3799, "naklon": 5 }, +{ "label": "46/16", "node": 3816, "naklon": 5 }, +{ "label": "46/17", "node": 3751, "naklon": 5 }, +{ "label": "46/18", "node": 3814, "naklon": 5 }, +{ "label": "46/19", "node": 4044, "naklon": 0 }, +{ "label": "46/20", "node": 3931, "naklon": 0 }, +{ "label": "46/21", "node": 3902, "naklon": 5 }, +{ "label": "46/22", "node": 3916, "naklon": 5 }, +{ "label": "46/23", "node": 3892, "naklon": 5 }, +{ "label": "46/24", "node": 3914, "naklon": 5 }, +{ "label": "46/25", "node": 3898, "naklon": 5 }, +{ "label": "46/26", "node": 3897, "naklon": 5 }, +{ "label": "46/27", "node": 3885, "naklon": 5 }, +{ "label": "46/28", "node": 3906, "naklon": 5 }, +{ "label": "46/29", "node": 3930, "naklon": 0 }, +{ "label": "46/30", "node": 3936, "naklon": 0 }, +{ "label": "46/31", "node": 3860, "naklon": 5 }, +{ "label": "46/32", "node": 3841, "naklon": 5 }, +{ "label": "46/33", "node": 3873, "naklon": 5 }, +{ "label": "46/34", "node": 3854, "naklon": 5 }, +{ "label": "46/35", "node": 3939, "naklon": 5 }, +{ "label": "46/36", "node": 3858, "naklon": 5 }, +{ "label": "46/37", "node": 3940, "naklon": 5 }, +{ "label": "46/38", "node": 4035, "naklon": 5 }, +{ "label": "47/1", "node": 3373, "naklon": 0 }, +{ "label": "47/2", "node": 3374, "naklon": 0 }, +{ "label": "47/3", "node": 3384, "naklon": 0 }, +{ "label": "47/4", "node": 3385, "naklon": 0 }, +{ "label": "48/1", "node": 4051, "naklon": 5 }, +{ "label": "48/2", "node": 4041, "naklon": 5 }, +{ "label": "48/3", "node": 4056, "naklon": 5 }, +{ "label": "48/4", "node": 3875, "naklon": 5 }, +{ "label": "48/5", "node": 4061, "naklon": 5 }, +{ "label": "48/6", "node": 4047, "naklon": 5 }, +{ "label": "48/7", "node": 4060, "naklon": 5 }, +{ "label": "48/8", "node": 4059, "naklon": 5 }, +{ "label": "48/9", "node": 4058, "naklon": 5 }, +{ "label": "48/10", "node": 3635, "naklon": 5 }, +{ "label": "48/11", "node": 3640, "naklon": 5 }, +{ "label": "48/12", "node": 3747, "naklon": 5 }, +{ "label": "48/13", "node": 3629, "naklon": 5 }, +{ "label": "48/14", "node": 4048, "naklon": 5 }, +{ "label": "48/15", "node": 4063, "naklon": 5 }, +{ "label": "48/16", "node": 4062, "naklon": 5 }, +{ "label": "48/17", "node": 4043, "naklon": 5 }, +{ "label": "48/18", "node": 4052, "naklon": 5 }, +{ "label": "48/19", "node": 4042, "naklon": 5 }, +{ "label": "48/20", "node": 4053, "naklon": 5 }, +{ "label": "50/15A", "node": 4167, "naklon": null }, +{ "label": "50/15B", "node": 4159, "naklon": null }, +{ "label": "50/1", "node": 4183, "naklon": 0 }, +{ "label": "50/2", "node": 4157, "naklon": 0 }, +{ "label": "50/3", "node": 4160, "naklon": 0 }, +{ "label": "50/4", "node": 4173, "naklon": 0 }, +{ "label": "50/5", "node": 4177, "naklon": 0 }, +{ "label": "50/6", "node": 4174, "naklon": 0 }, +{ "label": "50/7", "node": 4178, "naklon": 0 }, +{ "label": "50/8", "node": 4195, "naklon": 0 }, +{ "label": "50/9", "node": 4169, "naklon": 0 }, +{ "label": "50/10", "node": 4162, "naklon": 0 }, +{ "label": "50/11", "node": 4158, "naklon": 0 }, +{ "label": "50/12", "node": 4182, "naklon": 0 }, +{ "label": "50/13", "node": 4194, "naklon": 0 }, +{ "label": "50/14", "node": 4184, "naklon": 0 }, +{ "label": "50/16", "node": 4197, "naklon": null }, +{ "label": "50/17", "node": 4164, "naklon": null }, +{ "label": "50/18", "node": 3306, "naklon": null }, +{ "label": "50/19", "node": 4168, "naklon": null }, +{ "label": "50/20", "node": 4193, "naklon": null }, +{ "label": "50/21", "node": 4187, "naklon": null }, +{ "label": "50/22", "node": 4163, "naklon": null }, +{ "label": "50/23", "node": 4165, "naklon": null }, +{ "label": "50/24", "node": 4185, "naklon": null }, +{ "label": "50/25", "node": 3904, "naklon": null }, +{ "label": "53/1", "node": 2619, "naklon": 0 }, +{ "label": "53/2", "node": 2623, "naklon": 0 }, +{ "label": "53/3", "node": 2617, "naklon": 0 }, +{ "label": "53/4", "node": 2622, "naklon": 0 }, +{ "label": "53/5", "node": 2618, "naklon": 0 }, +{ "label": "53/6", "node": 2626, "naklon": 0 }, +{ "label": "53/7", "node": 2869, "naklon": 0 }, +{ "label": "53/8", "node": 2613, "naklon": 0 }, +{ "label": "53/9", "node": 2608, "naklon": 0 }, +{ "label": "53/10", "node": 2611, "naklon": 0 }, +{ "label": "53/11", "node": 2598, "naklon": 0 }, +{ "label": "53/12", "node": 3528, "naklon": 0 }, +{ "label": "53/13", "node": 3545, "naklon": 0 }, +{ "label": "53/14", "node": 2620, "naklon": 0 }, +{ "label": "53/15", "node": 2612, "naklon": 0 }, +{ "label": "53/16", "node": 2615, "naklon": 0 }, +{ "label": "53/17", "node": 3722, "naklon": 0 }, +{ "label": "53/18", "node": 2624, "naklon": 0 }, +{ "label": "53/19", "node": 2609, "naklon": 0 }, +{ "label": "53/20", "node": 2625, "naklon": 0 }, +{ "label": "53/21", "node": 2602, "naklon": 0 }, +{ "label": "53/22", "node": 2610, "naklon": 0 }, +{ "label": "53/23", "node": 2599, "naklon": 0 }, +{ "label": "53/24", "node": 2605, "naklon": 0 }, +{ "label": "53/25", "node": 2593, "naklon": 0 }, +{ "label": "53/26", "node": 3074, "naklon": 0 }, +{ "label": "53/27", "node": 2740, "naklon": 0 }, +{ "label": "53/28", "node": 2614, "naklon": 0 }, +{ "label": "53/29", "node": 2601, "naklon": 0 }, +{ "label": "53/30", "node": 4196, "naklon": 0 }, +{ "label": "53/31", "node": 2607, "naklon": 0 }, +{ "label": "53/32", "node": 2582, "naklon": 0 }, +{ "label": "53/33", "node": 2594, "naklon": 0 }, +{ "label": "53/34", "node": 2589, "naklon": 0 }, +{ "label": "53/35", "node": 2596, "naklon": 0 }, +{ "label": "53/36", "node": 2603, "naklon": 0 }, +{ "label": "53/37", "node": 2597, "naklon": 0 }, +{ "label": "53/38", "node": 2590, "naklon": 0 }, +{ "label": "53/39", "node": 2581, "naklon": 0 }, +{ "label": "53/40", "node": 2583, "naklon": 0 }, +{ "label": "53/41", "node": 2580, "naklon": 0 }, +{ "label": "53/42", "node": 2579, "naklon": 0 }, +{ "label": "53/43", "node": 2797, "naklon": 0 }, +{ "label": "53/44", "node": 2577, "naklon": 0 }, +{ "label": "53/45", "node": 2586, "naklon": 0 }, +{ "label": "53/46", "node": 2588, "naklon": 0 }, +{ "label": "53/47", "node": 2591, "naklon": 0 }, +{ "label": "53/48", "node": 2592, "naklon": 0 }, +{ "label": "53/49", "node": 2573, "naklon": 0 }, +{ "label": "53/50", "node": 2595, "naklon": 0 }, +{ "label": "53/51", "node": 2587, "naklon": 0 }, +{ "label": "53/52", "node": 2578, "naklon": 0 }, +{ "label": "53/53", "node": 2574, "naklon": 0 }, +{ "label": "53/54", "node": 2571, "naklon": 0 }, +{ "label": "53/55", "node": 2570, "naklon": 0 }, +{ "label": "53/56", "node": 2576, "naklon": 0 }, +{ "label": "53/57", "node": 2881, "naklon": 0 }, +{ "label": "53/58", "node": 2575, "naklon": 0 }, +{ "label": "53/59", "node": 2572, "naklon": 0 }, +{ "label": "53/60", "node": 2569, "naklon": 0 }, +{ "label": "55/1", "node": 4324, "naklon": 0 }, +{ "label": "55/2", "node": 4319, "naklon": 0 }, +{ "label": "55/3", "node": 4327, "naklon": 0 }, +{ "label": "55/4", "node": 4333, "naklon": 0 }, +{ "label": "55/5", "node": 4332, "naklon": 0 }, +{ "label": "55/6", "node": 4320, "naklon": 0 }, +{ "label": "55/7", "node": 4317, "naklon": 0 }, +{ "label": "55/8", "node": 4318, "naklon": 0 }, +{ "label": "55/9", "node": 4328, "naklon": 0 }, +{ "label": "55/10", "node": 4323, "naklon": 0 }, +{ "label": "55/11", "node": 4325, "naklon": 0 }, +{ "label": "55/12", "node": 4326, "naklon": 0 }, +{ "label": "55/13", "node": 4316, "naklon": 0 }, +{ "label": "55/14", "node": 4322, "naklon": 0 }, +{ "label": "55/15", "node": 4331, "naklon": 0 }, +{ "label": "55/16", "node": 4321, "naklon": 0 }, +{ "label": "55/17", "node": 4315, "naklon": 0 }, +{ "label": "55/18", "node": 4329, "naklon": 0 }, +{ "label": "55/19", "node": 4334, "naklon": 0 }, +{ "label": "55/20", "node": 4330, "naklon": 0 } +]; + +module.exports = { naklony }; diff --git a/RVO13/databases/modbus_config.js b/RVO13/databases/modbus_config.js new file mode 100755 index 0000000..b73116a --- /dev/null +++ b/RVO13/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/RVO13/databases/nodes.table b/RVO13/databases/nodes.table new file mode 100755 index 0000000..ac9b259 --- /dev/null +++ b/RVO13/databases/nodes.table @@ -0,0 +1,136 @@ +node:number|pole_number:string|node_type:string|tbname:string|line:number|profile:string|processed:boolean|status:boolean|time_of_last_communication:number ++|3271|63|NEMA|XMBbew5z4ELrZa2mRAd38x78vPN6gy3DdVYlpKjq|1||1|1|1760573731205| ++|3140|84|NEMA|dz4ojlpP85JMgDLZWkQJR37aKYqQexEr62GXRV1y|1||1|1|1760573859208| ++|3141|44|NEMA|EjgWGnXaLy9opPOz20n4dQ786BlYM3w1deVQvbKr|1||1|1|1760573859528| ++|3143|89|NEMA|B5EoxeMVp4zwr8nqW0GB9GARjvD1PNamOGbLg63Z|1||1|1|1760573860806| ++|3128|23|NEMA|pE5X8NQPaow6vlOZxk6aJw0q42ezGBMyWgDVjR3L|1||1|1|1760573858426| ++|3134|87|NEMA|K94XLav1glVRnyQ6r01PR3Ame3YJwBxM5oOzdP2j|1||1|1|1760573859033| ++|4250|28|NEMA|OzNMgZ9n43qPbjXmy7zw6GA2DKdYvW5e6pxGRrVa|1||1|1|1760573849462| ++|3145|86|NEMA|gRoJEyXVx4qD9er287L4eE7wBzGldaPjLWQKm3Mv|1||1|1|1760573861222| ++|3150|30|NEMA|RO8rjaBDy21qPQJzW7om2D0pK3xmNleVZg9Ed4Gw|1||1|1|1760573861653| ++|3151|88|NEMA|d9x2V5LGYBzXp4mMRAOm6VkPloaqJwnQj6DgrNe3|1||1|1|1760573861909| ++|3153|85|NEMA|d5xjWYMwEJon6rLlK7yE8x7qgV4DaOeNB9ZX3Gzb|1||1|1|1760573862117| ++|3155|26|NEMA|JzwxZXOvDj1bVrN4nkW5o8A8qdyBl3MRKLpGPgaQ|1||1|1|1760573862868| ++|3184|68|NEMA|zrR51V2ajQ9ZLygPKkEMY1kYDq38xOJolENBXGnv|1||1|1|1760573863155| ++|3185|67|NEMA|5dBNwRp9graYJxZn409N8vklVov1b2QLPDqGm6XK|1||1|1|1760573865536| ++|3188|69|NEMA|BaY3Xpy1EbKGjLq2O7ma497rx8owgQz9P4dDJRmN|1||1|1|1760573869403| ++|3196|27|NEMA|g9OxBZ5KRwNznlY6pAppYmAWXvjdEL4eGQobMDy2|1||1|1|1760574145845| ++|3197|24|NEMA|6lQGaY9RDywdVzObj0Pa5rkPg4NBn3exEK51LWZq|1||1|1|1760574146036| ++|3275|33|NEMA|1JMYvnx2RzKEo4aWQ7DGLzkL8yZV3m9NBePXbrdj|1||1|1|1760574203143| ++|3301|64|NEMA|gYbDLqlyZVoRerQpB72MB4kWJnwM5z24POKa8Exj|1||1|1|1760573734050| ++|3302|60B|NEMA|E6Kg9oDnLWyzPRMva7v5K9kJxp4VG58qO2w1lZYe|1||1|1|1760573734369| ++|3303|60A|NEMA|rDbQ84xzwgdqEoPm3kbExD09anOZY1RXyBv2LVM6|1||1|1|1760573736622| ++|3304|61|NEMA|roKgWqY95V3mXMRzyAjKbn0bLjexpJPvaGDBw826|1||1|1|1760573737117| ++|3307|62|NEMA|nJL5lPMwBx23YpqRe0rp9b7damXvWVbOrD4gNzy8|1||1|1|1760573744308| ++|3308|54|NEMA|3a5oqJN1bgnx4Ol9dk89K17ByE6jQ8mKDWMpGrLV|1||1|1|1760573744643| ++|3309|56|NEMA|wvKJdZML6mXP4DzWBAXxLVAjxNloa5g23Ve9Y1ry|1||1|1|1760573744867| ++|3310|58|NEMA|PLBJzmK1r3Gynd6OW0gK3q0e5wV4vx9bDEqNgYR8|1||1|1|1760573747775| ++|3311|57|07-Repeater|Nzp2OoJlqn6r1ZgvdA3BMv7abBwP5G4eE3RQmyxD|1||1|1|1760573729432| ++|3312|55|NEMA|EjgWGnXaLy9opPOz20n4dd786BlYM3w1deVQvbKr|1||1|1|1760573748638| ++|3313|73B|NEMA|6lQGaY9RDywdVzObj0PaPbkPg4NBn3exEK51LWZq|1||1|1|1760573749053| ++|3314|94|NEMA|EjgWGnXaLy9opPOz20n45d786BlYM3w1deVQvbKr|1||1|1|1760573749325| ++|3315|79|NEMA|RvmwNz8QPblKp41GD7lKeYkJrLVYoBO92dMegn6W|1||1|1|1760573749485| ++|3316|83A|NEMA|1JMYvnx2RzKEo4aWQ7DG2XkL8yZV3m9NBePXbrdj|1||1|1|1760573749724| ++|3317|70B|NEMA|apKVJBwOyrP35m2lv7KYKz0YXbeWNd64En9GxRqg|1||1|1|1760573753016| ++|2726|90|NEMA|aw4eELG2DlPMdn1JW0BMrQAqQXOZRN3xB5yp8VKr|1||1|1|1760573857394| ++|3319|70A|NEMA|DbQY6zyveZRwK5drV0Z8n87joE4XJM83N9xl2nWq|1||1|1|1760573753639| ++|3320|83B|NEMA|PjLblDgRBO6WQqnxmkJ1Bb0Jv3ewZN4p5a89yKdY|1||1|1|1760573754470| ++|3321|81|NEMA|3JjOWdylwgNLzxVab7Na5JkZ2vG64rq8PEB5QmDo|1||1|1|1760573757522| ++|3322|77|NEMA|OzNMgZ9n43qPbjXmy7zwneA2DKdYvW5e6pxGRrVa|1||1|1|1760573757761| ++|3324|82|NEMA|Z5KyJe9nEg1QNbWlX0w4xPkoDjBLdqzR83VGv624|1||1|1|1760573614021| ++|3325|78|NEMA|JX1ObgmqGZ54DMyYL7aDjlkEVdve38WKRzwjNrQ9|1||1|1|1760573614213| ++|3326|70C|NEMA|o9vbeQlLMVg8j5dq4keLYK0NxZpEmnXzwYKO1ar2|1||1|1|1760573617855| ++|3327|97|NEMA|52dD6ZlV1QaOpRBmbAqGRNkKnGzWMLj4eJq38Pgo|1||1|1|1760573618063| ++|4152|80|NEMA|RO8rjaBDy21qPQJzW7om610pK3xmNleVZg9Ed4Gw|1||1|1|1760573849254| ++|3442|101|NEMA|XMBbew5z4ELrZa2mRAd32x78vPN6gy3DdVYlpKjq|1||1|1|1760574093644| ++|3331|96|NEMA|PLBJzmK1r3Gynd6OW0gK9q0e5wV4vx9bDEqNgYR8|1||1|1|1760573761603| ++|3332|4|Kamera|EjgWGnXaLy9opPOz20n4oQ786BlYM3w1deVQvbKr|1||1|1|1760573767316| ++|3333|98B|NEMA|E6Kg9oDnLWyzPRMva7v5l9kJxp4VG58qO2w1lZYe|1||1|1|1760573767476| ++|3334|9|NEMA|rDbQ84xzwgdqEoPm3kbEoW09anOZY1RXyBv2LVM6|1||1|1|1760573767636| ++|3335|102|NEMA|gYbDLqlyZVoRerQpB72MW4kWJnwM5z24POKa8Exj|1||1|1|1760573767812| ++|3336|95A|NEMA|wvKJdZML6mXP4DzWBAXxVVAjxNloa5g23Ve9Y1ry|1||1|1|1760573768115| ++|3337|100|NEMA|nJL5lPMwBx23YpqRe0rpWb7damXvWVbOrD4gNzy8|1||1|1|1760573768291| ++|3339|98A|NEMA|rDbQ84xzwgdqEoPm3kbErD09anOZY1RXyBv2LVM6|1||1|1|1760573772893| ++|4014|71|NEMA|gP1eOZVj3Q9lv5aDEk45za7rdpqW8yLm2BbKzJxM|1||1|1|1760573712638| ++|3344|74|NEMA|m6EYyZoJ4gWexdjVPAR5WV7RDOq9wv2N5XzKGplr|1||1|1|1760573647207| ++|2887|76|NEMA|g9OxBZ5KRwNznlY6pAppPOAWXvjdEL4eGQobMDy2|1||1|1|1760573857659| ++|3346|75|NEMA|JzwxZXOvDj1bVrN4nkW5xzA8qdyBl3MRKLpGPgaQ|1||1|1|1760573779061| ++|3347|91|NEMA|ZmRwd93QL4gaezxEbAx2Vbk1prn2XjlPvGyqJ6BO|1||1|1|1760573779252| ++|4119|72|NEMA|2O14VBzl8aDmWdNw3A59aGAGyZ5qLJoEMpj6R9ng|1||1|1|1760573849046| ++|3351|73A|NEMA|pE5X8NQPaow6vlOZxk6alz0q42ezGBMyWgDVjR3L|1||1|1|1760573918823| ++|3363|39|NEMA|B5EoxeMVp4zwr8nqW0GBL5ARjvD1PNamOGbLg63Z|1||1|1|1760573780035| ++|3364|46|NEMA|PLBJzmK1r3Gynd6OW0gK3z0e5wV4vx9bDEqNgYR8|1||1|1|1760573780227| ++|3365|38|NEMA|d9x2V5LGYBzXp4mMRAOmL1kPloaqJwnQj6DgrNe3|1||1|1|1760573780387| ++|3366|50|NEMA|roKgWqY95V3mXMRzyAjKb60bLjexpJPvaGDBw826|1||1|1|1760573780595| ++|3367|47|NEMA|52dD6ZlV1QaOpRBmbAqGMbkKnGzWMLj4eJq38Pgo|1||1|1|1760573781889| ++|3368|48|NEMA|rDbQ84xzwgdqEoPm3kbExW09anOZY1RXyBv2LVM6|1||1|1|1760573782368| ++|3369|20|NEMA|o9vbeQlLMVg8j5dq4keLOy0NxZpEmnXzwYKO1ar2|1||1|1|1760573782736| ++|3370|19|NEMA|apKVJBwOyrP35m2lv7KYmd0YXbeWNd64En9GxRqg|1||1|1|1760573782911| ++|3371|35|NEMA|d5xjWYMwEJon6rLlK7yE5w7qgV4DaOeNB9ZX3Gzb|1||1|1|1760573783231| ++|3386|45B|NEMA|Nzp2OoJlqn6r1ZgvdA3BME7abBwP5G4eE3RQmyxD|1||1|1|1760573783758| ++|3388|37|NEMA|K94XLav1glVRnyQ6r01P2WAme3YJwBxM5oOzdP2j|1||1|1|1760573785468| ++|3389|36|NEMA|gRoJEyXVx4qD9er287L4LO7wBzGldaPjLWQKm3Mv|1||1|1|1760573785724| ++|3390|31|NEMA|3JjOWdylwgNLzxVab7NaLwkZ2vG64rq8PEB5QmDo|1||1|1|1760573785884| ++|3391|18|NEMA|DbQY6zyveZRwK5drV0Z8oj7joE4XJM83N9xl2nWq|1||1|1|1760573786155| ++|3393|22|NEMA|2O14VBzl8aDmWdNw3A59JOAGyZ5qLJoEMpj6R9ng|1||1|1|1760573927915| ++|3394|53|NEMA|eod9aRWLVl34Gx1Dn7VNL972rz6qjgmpEXwQJN5Z|1||1|1|1760573928331| ++|3338|51|NEMA|nJL5lPMwBx23YpqRe0rp947damXvWVbOrD4gNzy8|1||1|1|1760573768467| ++|3397|40|NEMA|aw4eELG2DlPMdn1JW0BMaZAqQXOZRN3xB5yp8VKr|1||1|1|1760573928906| ++|3401|32|NEMA|Z5KyJe9nEg1QNbWlX0w4eMkoDjBLdqzR83VGv624|1||1|1|1760573808573| ++|3402|49|NEMA|E6Kg9oDnLWyzPRMva7v5KykJxp4VG58qO2w1lZYe|1||1|1|1760573808845| ++|3403|42|NEMA|eod9aRWLVl34Gx1Dn7VNLD72rz6qjgmpEXwQJN5Z|1||1|1|1760573790421| ++|3404|34B|NEMA|dz4ojlpP85JMgDLZWkQJLj7aKYqQexEr62GXRV1y|1||1|1|1760573878494| ++|3405|34A|NEMA|PjLblDgRBO6WQqnxmkJ1La0Jv3ewZN4p5a89yKdY|1||1|1|1760573809388| ++|3406|12|NEMA|nJL5lPMwBx23YpqRe0rpo47damXvWVbOrD4gNzy8|1||1|1|1760574075652| ++|3407|29B|NEMA|RvmwNz8QPblKp41GD7lKjKkJrLVYoBO92dMegn6W|1||1|1|1760573809819| ++|3409|13B|NEMA|gYbDLqlyZVoRerQpB72MJvkWJnwM5z24POKa8Exj|1||1|1|1760574076243| ++|3410|29A|NEMA|JX1ObgmqGZ54DMyYL7aDLJkEVdve38WKRzwjNrQ9|1||1|1|1760574076451| ++|3411|14|NEMA|WlVJBygjDZMeKX3vnAMRKL08NqdmG2x1Y69LQ4P5|1||1|1|1760574076818| ++|3412|15|NEMA|5dBNwRp9graYJxZn409Nx8klVov1b2QLPDqGm6XK|1||1|1|1760574076978| ++|3413|16|NEMA|zrR51V2ajQ9ZLygPKkEMdWkYDq38xOJolENBXGnv|1||1|1|1760574077186| ++|3414|17|NEMA|BaY3Xpy1EbKGjLq2O7mao27rx8owgQz9P4dDJRmN|1||1|1|1760574077393| ++|3415|13A|NEMA|XMBbew5z4ELrZa2mRAd3o978vPN6gy3DdVYlpKjq|1||1|1|1760574091391| ++|3416|3|NEMA|3a5oqJN1bgnx4Ol9dk891q7ByE6jQ8mKDWMpGrLV|1||1|1|1760573901567| ++|3417|6|NEMA|Nzp2OoJlqn6r1ZgvdA3BJE7abBwP5G4eE3RQmyxD|1||1|1|1760573904251| ++|3418|7|NEMA|PLBJzmK1r3Gynd6OW0gKoz0e5wV4vx9bDEqNgYR8|1||1|1|1760574092349| ++|3419|2|NEMA|eod9aRWLVl34Gx1Dn7VNzD72rz6qjgmpEXwQJN5Z|1||1|1|1760574092509| ++|3420|103|NEMA|zdQO8GwxDqjRgP4137YV8XANyKlpem2nL65rvVJY|1||1|1|1760574092653| ++|3628|104|NEMA|WlVJBygjDZMeKX3vnAMR4P08NqdmG2x1Y69LQ4P5|1||1|1|1760573652033| ++|3422|5|NEMA|wvKJdZML6mXP4DzWBAXxo8AjxNloa5g23Ve9Y1ry|1||1|1|1760574092813| ++|3154|11|NEMA|roKgWqY95V3mXMRzyAjKo60bLjexpJPvaGDBw826|1||1|1|1760573862676| ++|3425|1|NEMA|ZmRwd93QL4gaezxEbAx2nwk1prn2XjlPvGyqJ6BO|1||1|1|1760574093292| ++|3513|116|IP65|2O14VBzl8aDmWdNw3A59QDAGyZ5qLJoEMpj6R9ng|1||1|1|1760573812823| ++|3516|115|IP65|6lQGaY9RDywdVzObj0PamXkPg4NBn3exEK51LWZq|1||1|1|1760573814309| ++|3521|111|IP65|DbQY6zyveZRwK5drV0Z8pr7joE4XJM83N9xl2nWq|1||1|1|1760573816339| ++|3526|107|NEMA|JzwxZXOvDj1bVrN4nkWw1Lk8qdyBl3MRKLpGPgaQ|1||1|1|1760573819119| ++|3527|110|IP65|BaY3Xpy1EbKGjLq2O7ma2b7rx8owgQz9P4dDJRmN|1||1|1|1760573819902| ++|3534|114|IP65|gP1eOZVj3Q9lv5aDEk45Qn7rdpqW8yLm2BbKzJxM|1||1|1|1760573991126| ++|3544|113|IP65|o9vbeQlLMVg8j5dq4keL3D0NxZpEmnXzwYKO1ar2|1||1|1|1760573992772| ++|3552|112|IP65|apKVJBwOyrP35m2lv7KY260YXbeWNd64En9GxRqg|1||1|1|1760573996607| ++|3561|109|IP65|BaY3Xpy1EbKGjLq2O7maV97rx8owgQz9P4dDJRmN|1||1|1|1760573997150| ++|3565|117|IP65|pE5X8NQPaow6vlOZxk6aQb0q42ezGBMyWgDVjR3L|1||1|1|1760574105196| ++|3567|40/1|IP65|gP1eOZVj3Q9lv5aDEk4EXZ7rdpqW8yLm2BbKzJxM|1||1|1|1760573651266| ++|3597|75/1|prechod|WlVJBygjDZMeKX3vnAMzgL08NqdmG2x1Y69LQ4P5|1||1|1|1760573651522| ++|3328|71/1|prechod|gYbDLqlyZVoRerQpB72rzv7WJnwM5z24POKa8Exj|1||1|1|1760573884662| ++|3847|54/1|prechod|XMBbew5z4ELrZa2mRAd5r908vPN6gy3DdVYlpKjq|1||1|1|1760574112642| ++|3822|71/2|prechod|zdQO8GwxDqjRgP4137Y1bo7NyKlpem2nL65rvVJY|1||1|1|1760573787689| ++|4361|105|NEMA|5dBNwRp9graYJxZn409NMvklVov1b2QLPDqGm6XK|1||1|1|1760573850277| ++|4362|106|NEMA|zrR51V2ajQ9ZLygPKkEMW1kYDq38xOJolENBXGnv|1||1|1|1760573850676| ++|4363|10|NEMA|E6Kg9oDnLWyzPRMva7v5VykJxp4VG58qO2w1lZYe|1||1|1|1760573851235| ++|4364|25|NEMA|m6EYyZoJ4gWexdjVPAR5PL7RDOq9wv2N5XzKGplr|1||1|1|1760573851411| ++|4365|59|NEMA|52dD6ZlV1QaOpRBmbAqGMNkKnGzWMLj4eJq38Pgo|1||1|1|1760573851747| ++|4366|65|NEMA|zdQO8GwxDqjRgP4137YVLXANyKlpem2nL65rvVJY|1||1|1|1760573853121| ++|3866|118|prechod|RvmwNz8QPblKp41GD7lDZK7JrLVYoBO92dMegn6W|1||1|0|1760287656776| ++|4093|60/1|prechod|JX1ObgmqGZ54DMyYL7a9gJ7EVdve38WKRzwjNrQ9|1||1|1|1760574172864| ++|4310|78/1|IP65|2O14VBzl8aDmWdNw3A51WlAGyZ5qLJoEMpj6R9ng|1||1|1|1760573849829| ++|4424|108|IP65|m6EYyZoJ4gWexdjVPARNjPARDOq9wv2N5XzKGplr|1||1|1|1760573853664| ++|3387|41|NEMA|ZmRwd93QL4gaezxEbAx24wk1prn2XjlPvGyqJ6BO|1||1|1|1760573784126| ++|3392|45A|NEMA|wvKJdZML6mXP4DzWBAXxL8AjxNloa5g23Ve9Y1ry|1||1|1|1760573927356| ++|3323|95B|NEMA|Nzp2OoJlqn6r1ZgvdA3Bpv7abBwP5G4eE3RQmyxD|1||1|1|1760573613254| ++|3372|52|Kamera|ZmRwd93QL4gaezxEbAx24bk1prn2XjlPvGyqJ6BO|1||1|1|1760573783503| ++|3147|43|NEMA|3a5oqJN1bgnx4Ol9dk89Kq7ByE6jQ8mKDWMpGrLV|1||1|1|1760573861397| ++|3408|21|NEMA|gP1eOZVj3Q9lv5aDEk45JP7rdpqW8yLm2BbKzJxM|1||1|1|1760574076067| ++|3424|8|NEMA|52dD6ZlV1QaOpRBmbAqGobkKnGzWMLj4eJq38Pgo|1||1|1|1760574093148| ++|3300|66|NEMA|WlVJBygjDZMeKX3vnAMRLP08NqdmG2x1Y69LQ4P5|1||1|1|1760573733442| ++|3329|99|NEMA|roKgWqY95V3mXMRzyAjKZn0bLjexpJPvaGDBw826|1||1|1|1760573761165| ++|3399|13C|NEMA|zdQO8GwxDqjRgP4137YVooANyKlpem2nL65rvVJY|1||1|1|1760573929145| diff --git a/RVO13/databases/nodes_original/nodes_original.table b/RVO13/databases/nodes_original/nodes_original.table new file mode 100755 index 0000000..542ce21 --- /dev/null +++ b/RVO13/databases/nodes_original/nodes_original.table @@ -0,0 +1 @@ +[{"3271": "XMBbew5z4ELrZa2mRAd38x78vPN6gy3DdVYlpKjq"}, {"3140": "dz4ojlpP85JMgDLZWkQJR37aKYqQexEr62GXRV1y"}, {"3141": "EjgWGnXaLy9opPOz20n4dQ786BlYM3w1deVQvbKr"}, {"3143": "B5EoxeMVp4zwr8nqW0GB9GARjvD1PNamOGbLg63Z"}, {"3128": "pE5X8NQPaow6vlOZxk6aJw0q42ezGBMyWgDVjR3L"}, {"3134": "K94XLav1glVRnyQ6r01PR3Ame3YJwBxM5oOzdP2j"}, {"4250": "OzNMgZ9n43qPbjXmy7zw6GA2DKdYvW5e6pxGRrVa"}, {"3145": "gRoJEyXVx4qD9er287L4eE7wBzGldaPjLWQKm3Mv"}, {"3150": "RO8rjaBDy21qPQJzW7om2D0pK3xmNleVZg9Ed4Gw"}, {"3151": "d9x2V5LGYBzXp4mMRAOm6VkPloaqJwnQj6DgrNe3"}, {"3153": "d5xjWYMwEJon6rLlK7yE8x7qgV4DaOeNB9ZX3Gzb"}, {"3155": "JzwxZXOvDj1bVrN4nkW5o8A8qdyBl3MRKLpGPgaQ"}, {"3184": "zrR51V2ajQ9ZLygPKkEMY1kYDq38xOJolENBXGnv"}, {"3185": "5dBNwRp9graYJxZn409N8vklVov1b2QLPDqGm6XK"}, {"3188": "BaY3Xpy1EbKGjLq2O7ma497rx8owgQz9P4dDJRmN"}, {"3196": "g9OxBZ5KRwNznlY6pAppYmAWXvjdEL4eGQobMDy2"}, {"3197": "6lQGaY9RDywdVzObj0Pa5rkPg4NBn3exEK51LWZq"}, {"3275": "1JMYvnx2RzKEo4aWQ7DGLzkL8yZV3m9NBePXbrdj"}, {"3301": "gYbDLqlyZVoRerQpB72MB4kWJnwM5z24POKa8Exj"}, {"3302": "E6Kg9oDnLWyzPRMva7v5K9kJxp4VG58qO2w1lZYe"}, {"3303": "rDbQ84xzwgdqEoPm3kbExD09anOZY1RXyBv2LVM6"}, {"3304": "roKgWqY95V3mXMRzyAjKbn0bLjexpJPvaGDBw826"}, {"3307": "nJL5lPMwBx23YpqRe0rp9b7damXvWVbOrD4gNzy8"}, {"3308": "3a5oqJN1bgnx4Ol9dk89K17ByE6jQ8mKDWMpGrLV"}, {"3309": "wvKJdZML6mXP4DzWBAXxLVAjxNloa5g23Ve9Y1ry"}, {"3310": "PLBJzmK1r3Gynd6OW0gK3q0e5wV4vx9bDEqNgYR8"}, {"3311": "Nzp2OoJlqn6r1ZgvdA3BMv7abBwP5G4eE3RQmyxD"}, {"3312": "EjgWGnXaLy9opPOz20n4dd786BlYM3w1deVQvbKr"}, {"3313": "6lQGaY9RDywdVzObj0PaPbkPg4NBn3exEK51LWZq"}, {"3314": "EjgWGnXaLy9opPOz20n45d786BlYM3w1deVQvbKr"}, {"3315": "RvmwNz8QPblKp41GD7lKeYkJrLVYoBO92dMegn6W"}, {"3316": "1JMYvnx2RzKEo4aWQ7DG2XkL8yZV3m9NBePXbrdj"}, {"3317": "apKVJBwOyrP35m2lv7KYKz0YXbeWNd64En9GxRqg"}, {"2726": "aw4eELG2DlPMdn1JW0BMrQAqQXOZRN3xB5yp8VKr"}, {"3319": "DbQY6zyveZRwK5drV0Z8n87joE4XJM83N9xl2nWq"}, {"3320": "PjLblDgRBO6WQqnxmkJ1Bb0Jv3ewZN4p5a89yKdY"}, {"3321": "3JjOWdylwgNLzxVab7Na5JkZ2vG64rq8PEB5QmDo"}, {"3322": "OzNMgZ9n43qPbjXmy7zwneA2DKdYvW5e6pxGRrVa"}, {"3324": "Z5KyJe9nEg1QNbWlX0w4xPkoDjBLdqzR83VGv624"}, {"3325": "JX1ObgmqGZ54DMyYL7aDjlkEVdve38WKRzwjNrQ9"}, {"3326": "o9vbeQlLMVg8j5dq4keLYK0NxZpEmnXzwYKO1ar2"}, {"3327": "52dD6ZlV1QaOpRBmbAqGRNkKnGzWMLj4eJq38Pgo"}, {"4152": "RO8rjaBDy21qPQJzW7om610pK3xmNleVZg9Ed4Gw"}, {"3442": "XMBbew5z4ELrZa2mRAd32x78vPN6gy3DdVYlpKjq"}, {"3331": "PLBJzmK1r3Gynd6OW0gK9q0e5wV4vx9bDEqNgYR8"}, {"3332": "EjgWGnXaLy9opPOz20n4oQ786BlYM3w1deVQvbKr"}, {"3333": "E6Kg9oDnLWyzPRMva7v5l9kJxp4VG58qO2w1lZYe"}, {"3334": "rDbQ84xzwgdqEoPm3kbEoW09anOZY1RXyBv2LVM6"}, {"3335": "gYbDLqlyZVoRerQpB72MW4kWJnwM5z24POKa8Exj"}, {"3336": "wvKJdZML6mXP4DzWBAXxVVAjxNloa5g23Ve9Y1ry"}, {"3337": "nJL5lPMwBx23YpqRe0rpWb7damXvWVbOrD4gNzy8"}, {"3339": "rDbQ84xzwgdqEoPm3kbErD09anOZY1RXyBv2LVM6"}, {"4014": "gP1eOZVj3Q9lv5aDEk45za7rdpqW8yLm2BbKzJxM"}, {"3344": "m6EYyZoJ4gWexdjVPAR5WV7RDOq9wv2N5XzKGplr"}, {"2887": "g9OxBZ5KRwNznlY6pAppPOAWXvjdEL4eGQobMDy2"}, {"3346": "JzwxZXOvDj1bVrN4nkW5xzA8qdyBl3MRKLpGPgaQ"}, {"3347": "ZmRwd93QL4gaezxEbAx2Vbk1prn2XjlPvGyqJ6BO"}, {"4119": "2O14VBzl8aDmWdNw3A59aGAGyZ5qLJoEMpj6R9ng"}, {"3351": "pE5X8NQPaow6vlOZxk6alz0q42ezGBMyWgDVjR3L"}, {"3363": "B5EoxeMVp4zwr8nqW0GBL5ARjvD1PNamOGbLg63Z"}, {"3364": "PLBJzmK1r3Gynd6OW0gK3z0e5wV4vx9bDEqNgYR8"}, {"3365": "d9x2V5LGYBzXp4mMRAOmL1kPloaqJwnQj6DgrNe3"}, {"3366": "roKgWqY95V3mXMRzyAjKb60bLjexpJPvaGDBw826"}, {"3367": "52dD6ZlV1QaOpRBmbAqGMbkKnGzWMLj4eJq38Pgo"}, {"3368": "rDbQ84xzwgdqEoPm3kbExW09anOZY1RXyBv2LVM6"}, {"3369": "o9vbeQlLMVg8j5dq4keLOy0NxZpEmnXzwYKO1ar2"}, {"3370": "apKVJBwOyrP35m2lv7KYmd0YXbeWNd64En9GxRqg"}, {"3371": "d5xjWYMwEJon6rLlK7yE5w7qgV4DaOeNB9ZX3Gzb"}, {"3386": "Nzp2OoJlqn6r1ZgvdA3BME7abBwP5G4eE3RQmyxD"}, {"3388": "K94XLav1glVRnyQ6r01P2WAme3YJwBxM5oOzdP2j"}, {"3389": "gRoJEyXVx4qD9er287L4LO7wBzGldaPjLWQKm3Mv"}, {"3390": "3JjOWdylwgNLzxVab7NaLwkZ2vG64rq8PEB5QmDo"}, {"3391": "DbQY6zyveZRwK5drV0Z8oj7joE4XJM83N9xl2nWq"}, {"3393": "2O14VBzl8aDmWdNw3A59JOAGyZ5qLJoEMpj6R9ng"}, {"3394": "eod9aRWLVl34Gx1Dn7VNL972rz6qjgmpEXwQJN5Z"}, {"3338": "nJL5lPMwBx23YpqRe0rp947damXvWVbOrD4gNzy8"}, {"3397": "aw4eELG2DlPMdn1JW0BMaZAqQXOZRN3xB5yp8VKr"}, {"3401": "Z5KyJe9nEg1QNbWlX0w4eMkoDjBLdqzR83VGv624"}, {"3402": "E6Kg9oDnLWyzPRMva7v5KykJxp4VG58qO2w1lZYe"}, {"3403": "eod9aRWLVl34Gx1Dn7VNLD72rz6qjgmpEXwQJN5Z"}, {"3404": "dz4ojlpP85JMgDLZWkQJLj7aKYqQexEr62GXRV1y"}, {"3405": "PjLblDgRBO6WQqnxmkJ1La0Jv3ewZN4p5a89yKdY"}, {"3406": "nJL5lPMwBx23YpqRe0rpo47damXvWVbOrD4gNzy8"}, {"3407": "RvmwNz8QPblKp41GD7lKjKkJrLVYoBO92dMegn6W"}, {"3409": "gYbDLqlyZVoRerQpB72MJvkWJnwM5z24POKa8Exj"}, {"3410": "JX1ObgmqGZ54DMyYL7aDLJkEVdve38WKRzwjNrQ9"}, {"3411": "WlVJBygjDZMeKX3vnAMRKL08NqdmG2x1Y69LQ4P5"}, {"3412": "5dBNwRp9graYJxZn409Nx8klVov1b2QLPDqGm6XK"}, {"3413": "zrR51V2ajQ9ZLygPKkEMdWkYDq38xOJolENBXGnv"}, {"3414": "BaY3Xpy1EbKGjLq2O7mao27rx8owgQz9P4dDJRmN"}, {"3415": "XMBbew5z4ELrZa2mRAd3o978vPN6gy3DdVYlpKjq"}, {"3416": "3a5oqJN1bgnx4Ol9dk891q7ByE6jQ8mKDWMpGrLV"}, {"3417": "Nzp2OoJlqn6r1ZgvdA3BJE7abBwP5G4eE3RQmyxD"}, {"3418": "PLBJzmK1r3Gynd6OW0gKoz0e5wV4vx9bDEqNgYR8"}, {"3419": "eod9aRWLVl34Gx1Dn7VNzD72rz6qjgmpEXwQJN5Z"}, {"3420": "zdQO8GwxDqjRgP4137YV8XANyKlpem2nL65rvVJY"}, {"3628": "WlVJBygjDZMeKX3vnAMR4P08NqdmG2x1Y69LQ4P5"}, {"3422": "wvKJdZML6mXP4DzWBAXxo8AjxNloa5g23Ve9Y1ry"}, {"3154": "roKgWqY95V3mXMRzyAjKo60bLjexpJPvaGDBw826"}, {"3425": "ZmRwd93QL4gaezxEbAx2nwk1prn2XjlPvGyqJ6BO"}, {"3513": "2O14VBzl8aDmWdNw3A59QDAGyZ5qLJoEMpj6R9ng"}, {"3516": "6lQGaY9RDywdVzObj0PamXkPg4NBn3exEK51LWZq"}, {"3521": "DbQY6zyveZRwK5drV0Z8pr7joE4XJM83N9xl2nWq"}, {"3526": "JzwxZXOvDj1bVrN4nkWw1Lk8qdyBl3MRKLpGPgaQ"}, {"3527": "BaY3Xpy1EbKGjLq2O7ma2b7rx8owgQz9P4dDJRmN"}, {"3534": "gP1eOZVj3Q9lv5aDEk45Qn7rdpqW8yLm2BbKzJxM"}, {"3544": "o9vbeQlLMVg8j5dq4keL3D0NxZpEmnXzwYKO1ar2"}, {"3552": "apKVJBwOyrP35m2lv7KY260YXbeWNd64En9GxRqg"}, {"3561": "BaY3Xpy1EbKGjLq2O7maV97rx8owgQz9P4dDJRmN"}, {"3565": "pE5X8NQPaow6vlOZxk6aQb0q42ezGBMyWgDVjR3L"}, {"3567": "gP1eOZVj3Q9lv5aDEk4EXZ7rdpqW8yLm2BbKzJxM"}, {"3597": "WlVJBygjDZMeKX3vnAMzgL08NqdmG2x1Y69LQ4P5"}, {"3328": "gYbDLqlyZVoRerQpB72rzv7WJnwM5z24POKa8Exj"}, {"3847": "XMBbew5z4ELrZa2mRAd5r908vPN6gy3DdVYlpKjq"}, {"3822": "zdQO8GwxDqjRgP4137Y1bo7NyKlpem2nL65rvVJY"}, {"4361": "5dBNwRp9graYJxZn409NMvklVov1b2QLPDqGm6XK"}, {"4362": "zrR51V2ajQ9ZLygPKkEMW1kYDq38xOJolENBXGnv"}, {"4363": "E6Kg9oDnLWyzPRMva7v5VykJxp4VG58qO2w1lZYe"}, {"4364": "m6EYyZoJ4gWexdjVPAR5PL7RDOq9wv2N5XzKGplr"}, {"4365": "52dD6ZlV1QaOpRBmbAqGMNkKnGzWMLj4eJq38Pgo"}, {"4366": "zdQO8GwxDqjRgP4137YVLXANyKlpem2nL65rvVJY"}, {"3866": "RvmwNz8QPblKp41GD7lDZK7JrLVYoBO92dMegn6W"}, {"4093": "JX1ObgmqGZ54DMyYL7a9gJ7EVdve38WKRzwjNrQ9"}, {"4310": "2O14VBzl8aDmWdNw3A51WlAGyZ5qLJoEMpj6R9ng"}, {"4424": "m6EYyZoJ4gWexdjVPARNjPARDOq9wv2N5XzKGplr"}, {"3387": "ZmRwd93QL4gaezxEbAx24wk1prn2XjlPvGyqJ6BO"}, {"3392": "wvKJdZML6mXP4DzWBAXxL8AjxNloa5g23Ve9Y1ry"}, {"3323": "Nzp2OoJlqn6r1ZgvdA3Bpv7abBwP5G4eE3RQmyxD"}, {"3372": "ZmRwd93QL4gaezxEbAx24bk1prn2XjlPvGyqJ6BO"}, {"3147": "3a5oqJN1bgnx4Ol9dk89Kq7ByE6jQ8mKDWMpGrLV"}, {"3408": "gP1eOZVj3Q9lv5aDEk45JP7rdpqW8yLm2BbKzJxM"}, {"3424": "52dD6ZlV1QaOpRBmbAqGobkKnGzWMLj4eJq38Pgo"}, {"3300": "WlVJBygjDZMeKX3vnAMRLP08NqdmG2x1Y69LQ4P5"}, {"3329": "roKgWqY95V3mXMRzyAjKZn0bLjexpJPvaGDBw826"}, {"3399": "zdQO8GwxDqjRgP4137YVooANyKlpem2nL65rvVJY"}] \ No newline at end of file diff --git a/RVO13/databases/notifications.table b/RVO13/databases/notifications.table new file mode 100755 index 0000000..f7c96cb --- /dev/null +++ b/RVO13/databases/notifications.table @@ -0,0 +1,41 @@ +key:string|weight:string|sk:string|en:string ++|switching_profile_point_applied_to_line|INFORMATIONAL|Aplikovaný bod spínacieho profilu na línií č. ${line} : ${value}|Switching profile point applied to line no. ${line} : ${value}|............... ++|dusk_has_occured|INFORMATIONAL|Nastal súmrak: ${value}|Dusk has occured: ${value}|............... ++|dawn_has_occured|INFORMATIONAL|Nastal úsvit: ${value}|Dawn has occured: ${value}|............... ++|dimming_profile_was_successfully_received_by_node|NOTICE|Stmievací profil bol úspešne prijatý nodom č. ${node}|Dimming profile was successfully received by node no. ${node}|............... ++|master_node_is_responding_again|NOTICE|Master node začal znovu odpovedať|Master node is responding again|............... ++|command_was_sent_from_terminal_interface|DEBUG|Z terminálu bol odoslaný príkaz|A command was sent from terminal interface|............... ++|master_node_is_not_responding|ALERT|Master node neodpovedá|Master node is not responding|............... ++|configuration_of_dimming_profile_to_node_failed|ALERT|Konfigurácia stmievacieho profilu pre node č. ${node} zlyhala|Configuration of dimming profile to node no. ${node} has failed|............... ++|circuit_breaker_was_turned_on_line|NOTICE|Zapnutie ističa na línii č. ${line}|Circuit breaker was turned on - line no. ${line}|............... ++|circuit_breaker_was_turned_off_line|ERROR|Vypnutie ističa na línií č. ${line}|Circuit breaker was turned off - line no. ${line}|............... ++|dimming_profile_was_processed_for_node|INFORMATIONAL|Stmievací profil bol spracovaný pre node č. ${node}|Dimming profile was processed for node no. ${node}|............... ++|switching_profile_was_processed_for_line|INFORMATIONAL|Spínací profil bol spracovaný pre líniu č. ${line}|Switching profile was processed for line no. ${line}|............... ++|thermometer_is_not_responding|WARNING|Teplomer neodpovedá|Thermometer is not responding|............... ++|thermometer_is_responding_again|NOTICE|Teplomer znovu odpovedá|Thermometer is responding again|............... ++|thermometer_sends_invalid_data|WARNING|Teplomer posiela neplatné hodnoty|Thermometer sends invalid data|............... ++|main_switch_has_been_turned_off|CRITICAL|Hlavný vypínač bol vypnutý|Main switch has been turned off|............... ++|main_switch_has_been_turned_on|NOTICE|Hlavný vypínač bol zapnutý|Main switch has been turned on|............... ++|power_supply_has_disconnected_input|ALERT|Napájací zdroj nemá napätie na vstupe|Power supply has disconnected input|............... ++|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_main_open|NOTICE|Hlavné dvere boli otvorené|Main door has been opened|............... ++|door_em_open|NOTICE|Dvere silovej časti boli otvorené|Power door has been opened|............... ++|door_main_open_without_permission|WARNING|Hlavné dvere boli otvorené bez povolenia - zapnutá siréna|Main door has been opened without permission - alarm is on|............... ++|door_em_open_without_permission|WARNING|Dvere silovej časti boli otvorené bez povolenia|Power door has been opened without permission|............... ++|door_main_close|NOTICE|Hlavné dvere boli zatvorené|Main door has been closed|............... ++|door_em_close|NOTICE|Dvere silovej časti boli zatvorené|Power door has been closed|............... ++|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|............... ++|electrometer_ok|NOTICE|Elektromer znovu odpovedá|Electrometer is responding again|............... ++|no_voltage_on_phase|CRITICAL|Na fáze č. ${phase} nie je napätie|No voltage detected on phase no. ${phase}|............... ++|voltage_on_phase_restored|NOTICE|Napätie na fáze č. ${phase} bolo obnovené|Voltage on phase no. ${phase} has been restored|............... ++|flow_start|NOTICE|FLOW bol spustený|FLOW has been started |............... ++|twilight_sensor_nok|ERROR|Sensor súmraku neodpovedá|Twilight sensor is not responding|............... ++|twilight_sensor_ok|NOTICE|Sensor súmraku znovu odpovedá|Twilight sensor is responding again|............... ++|lamps_have_turned_on|NOTICE|Lampy sa zapli|Lamps have turned on|............... ++|lamps_have_turned_off|NOTICE|Lampy sa vypli|Lamps have turned off|............... ++|flow_restart|NOTICE|FLOW bol reštartovaný|FLOW has been restarted|............... ++|nodes_db_changed|NOTICE|Zmena v node databáze|Node db has changed|............... diff --git a/RVO13/databases/pins.table b/RVO13/databases/pins.table new file mode 100755 index 0000000..6417b40 --- /dev/null +++ b/RVO13/databases/pins.table @@ -0,0 +1,15 @@ +pin:string|type:string|line:number +*|input1_01|door_condition|0|........... +*|input1_02|rotary_switch_state|0|........... +*|input1_03|rotary_switch_state|0|........... +*|input1_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|........... +*|relay1_05|state_of_contactor|4|........... +*|28F46E9D0E00008B|temperature|0|........... +*|twilight_sensor|twilight_sensor|0|........... diff --git a/RVO13/databases/relays.table b/RVO13/databases/relays.table new file mode 100755 index 0000000..97dd649 --- /dev/null +++ b/RVO13/databases/relays.table @@ -0,0 +1,6 @@ +line:number|tbname:string|contactor:number|profile:string ++|0|wvKJdZML6mXP4DzWBAXxwBAjxNloa5g23Ve9Y1ry|1||........... ++|1|d9x2V5LGYBzXp4mMRAOm41kPloaqJwnQj6DgrNe3|9|{"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|B5EoxeMVp4zwr8nqW0GBY5ARjvD1PNamOGbLg63Z|9|{"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|aw4eELG2DlPMdn1JW0BMvZAqQXOZRN3xB5yp8VKr|9|{"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}|........... ++|4|PLBJzmK1r3Gynd6OW0gKX20e5wV4vx9bDEqNgYR8|9|{"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/RVO13/databases/settings.table b/RVO13/databases/settings.table new file mode 100755 index 0000000..3f855f0 --- /dev/null +++ b/RVO13/databases/settings.table @@ -0,0 +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|project_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|cloud_topic:string|has_main_switch:boolean|daily_report:boolean|send_changed_node_numbers:boolean ++|rvo_senica_13_ip123|en|28.023A9C0E0000|48.70826502|17.28455203|192.168.252.1|rvo_senica_13_ip123|aVbwODdQlqbtbkOg4sjM|1883|0|58|unipi|ttyUSB0|1|20|5|6|3|u123|0|1|1|................................................... diff --git a/RVO13/databases/tbdata.nosql b/RVO13/databases/tbdata.nosql new file mode 100755 index 0000000..ac5f399 --- /dev/null +++ b/RVO13/databases/tbdata.nosql @@ -0,0 +1,6 @@ +-"wvKJdZML6mXP4DzWBAXxwBAjxNloa5g23Ve9Y1ry":[{"ts":1760509628558,"values":{"twilight_sensor":1141}}],"id":"2999967001hm71b"} +-"wvKJdZML6mXP4DzWBAXxwBAjxNloa5g23Ve9Y1ry":[{"ts":1760509635207,"values":{"temperature":15.75}}],"id":"2999967002hm70b"} +-"wvKJdZML6mXP4DzWBAXxwBAjxNloa5g23Ve9Y1ry":[{"ts":1760521261417,"values":{"_event":{"type":"notice","status":"new","source":{"func":"modbus_reader","component":"1699965957410","component_name":"Modbus reader","edge":"wvKJdZML6mXP4DzWBAXxwBAjxNloa5g23Ve9Y1ry"},"message":{"sk":"rvo_senica_13_ip123: FLOW bol reštartovaný","en":"rvo_senica_13_ip123: FLOW has been restarted"},"message_data":""}}}],"id":"3000161001lf71b"} +-"wvKJdZML6mXP4DzWBAXxwBAjxNloa5g23Ve9Y1ry":[{"ts":1760521261516,"values":{"edge_fw_version":"2025-10-08","maintenance_mode":false}}],"id":"3000161002lf70b"} +-"wvKJdZML6mXP4DzWBAXxwBAjxNloa5g23Ve9Y1ry":[{"ts":1760521261529,"values":{"statecode":2,"power_mode":"Automatic"}}],"id":"3000161004lf70b"} +-"wvKJdZML6mXP4DzWBAXxwBAjxNloa5g23Ve9Y1ry":[{"ts":1760521261589,"values":{"_event":{"type":"notice","status":"new","source":{"func":"rsPort.open()","component":"1699963668903","component_name":"DIDO_Controller","edge":"wvKJdZML6mXP4DzWBAXxwBAjxNloa5g23Ve9Y1ry"},"message":{"sk":"rvo_senica_13_ip123: FLOW bol spustený","en":"rvo_senica_13_ip123: FLOW has been started "},"message_data":""}}}],"id":"3000161006lf70b"} diff --git a/RVO13/databases/tbdatacloud.nosql b/RVO13/databases/tbdatacloud.nosql new file mode 100755 index 0000000..f3537c4 --- /dev/null +++ b/RVO13/databases/tbdatacloud.nosql @@ -0,0 +1,3 @@ +-"wvKJdZML6mXP4DzWBAXxwBAjxNloa5g23Ve9Y1ry":[{"ts":1760521261516,"values":{"edge_fw_version":"2025-10-08","maintenance_mode":false}}],"id":"3000161003lf71b"} +-"wvKJdZML6mXP4DzWBAXxwBAjxNloa5g23Ve9Y1ry":[{"ts":1760521261529,"values":{"statecode":2,"power_mode":"Automatic"}}],"id":"3000161005lf71b"} +-"wvKJdZML6mXP4DzWBAXxwBAjxNloa5g23Ve9Y1ry":[{"ts":1760521261589,"values":{"_event":{"type":"notice","status":"new","source":{"func":"rsPort.open()","component":"1699963668903","component_name":"DIDO_Controller","edge":"wvKJdZML6mXP4DzWBAXxwBAjxNloa5g23Ve9Y1ry"},"message":{"sk":"rvo_senica_13_ip123: FLOW bol spustený","en":"rvo_senica_13_ip123: FLOW has been started "},"message_data":""}}}],"id":"3000161007lf71b"} diff --git a/RVO13/databases/total_energy.js b/RVO13/databases/total_energy.js new file mode 100755 index 0000000..dde340e --- /dev/null +++ b/RVO13/databases/total_energy.js @@ -0,0 +1,38 @@ +//key is rvo_number, value is max energy when lamps are on +const total_energy = { + 1: 580, + 2: 1100, + 3: 3700, + 4: 4100, + 7: 360, + 12: 1700, + 13: 5400, + 14: 440, + 15: 6100, + 16: 4800, + 20: 1600, + 21: 1000, + 22: 2600, + 23: 1000, + 25: 2600, + 33: 240, + 34: 4000, + 35: 2700, + 36: 820, + 37: 1400, + 35: 3500, + 39: 1170, + 41: 740, + 42: 660, + 43: 4900, + 45: 930, + 46: 700, + 47: 1100, + 48: 1500, + 50: 3200, + 53: 1250, + 55: 1000, + 56: 5500 +} + +module.exports = total_energy; diff --git a/RVO13/debug.js b/RVO13/debug.js new file mode 100755 index 0000000..9818194 --- /dev/null +++ b/RVO13/debug.js @@ -0,0 +1,16 @@ +// =================================================== +// FOR DEVELOPMENT +// Total.js - framework for Node.js platform +// https://www.totaljs.com +// =================================================== + +const options = {}; + +// options.ip = '127.0.0.1'; +// options.port = parseInt(process.argv[2]); +// options.config = { name: 'Total.js' }; +// options.sleep = 3000; +// options.inspector = 9229; +// options.watch = ['private']; + +require('total.js/debug')(options); \ No newline at end of file diff --git a/RVO13/err.txt b/RVO13/err.txt new file mode 100755 index 0000000..1b29018 --- /dev/null +++ b/RVO13/err.txt @@ -0,0 +1,33 @@ +[2025-09-23T14:03:10.813] [ERROR] errLogs - uncaughtException: Cannot read property 'getHours' of undefined +[2025-09-23T14:03:10.814] [ERROR] errLogs - TypeError: Cannot read property 'getHours' of undefined + at Timeout.emptyReportToSend [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:03:10.815] [ERROR] errLogs - uncaughtException: Cannot read property 'getHours' of undefined +[2025-09-23T14:03:10.815] [ERROR] errLogs - TypeError: Cannot read property 'getHours' of undefined + at Timeout.emptyReportToSend [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:03:10.825] [ERROR] errLogs - uncaughtException: Cannot read property 'getHours' of undefined +[2025-09-23T14:03:10.826] [ERROR] errLogs - TypeError: Cannot read property 'getHours' of undefined + at Timeout.emptyReportToSend [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:03:16.908] [ERROR] errLogs - uncaughtException: date.getHours is not a function +[2025-09-23T14:03:16.909] [ERROR] errLogs - TypeError: date.getHours is not a function + at emptyReportToSend (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at Timeout.dailyReportCheck [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1351:5) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:03:16.910] [ERROR] errLogs - uncaughtException: date.getHours is not a function +[2025-09-23T14:03:16.910] [ERROR] errLogs - TypeError: date.getHours is not a function + at emptyReportToSend (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at Timeout.dailyReportCheck [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1351:5) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:03:16.915] [ERROR] errLogs - uncaughtException: date.getHours is not a function +[2025-09-23T14:03:16.916] [ERROR] errLogs - TypeError: date.getHours is not a function + at emptyReportToSend (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at Timeout.dailyReportCheck [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1351:5) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) diff --git a/RVO13/flow/cloudmqttconnect.js b/RVO13/flow/cloudmqttconnect.js new file mode 100755 index 0000000..b03491f --- /dev/null +++ b/RVO13/flow/cloudmqttconnect.js @@ -0,0 +1,357 @@ +exports.id = 'cloudmqttconnect'; +exports.title = 'Cloud connect mqtt'; +exports.group = 'MQTT'; +exports.color = '#888600'; +exports.version = '1.0.2'; +exports.icon = 'sign-out'; +exports.input = 2; +exports.output = 2; +exports.options = { host: 'tb-stage.worksys.io', port: 1883, clientid: "", username: "" }; + +exports.html = `
+
+
+
Hostname or IP address (if not empty - setting will override db setting)
+
+
+
Port
+
+
+
+
+
@(Client id)
+
+
+
topic
+
+
+
`; + + + +const { promisifyBuilder } = require('./helper/db_helper'); +const fs = require('fs'); +const mqtt = require('mqtt'); +const nosql = NOSQL('tbdatacloud'); + +const SEND_TO = { + debug: 0, + rpcCall: 1, +} + +//CONFIG +let saveTelemetryOnError = true;//backup_on_failure overrides this value +//------------------------ + +const noSqlFileSizeLimit = 4194304;//use 5MB - 4194304 +let insertNoSqlCounter = 0; +let insertBackupNoSqlCounter = 0; +let processingData = false; + +let backup_on_failure = true;//== saveTelemetryOnError - create backup client send failure +let restore_from_backup = 50; //how many rows process at once? +let restore_backup_wait = 3;//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; + + +exports.install = function(instance) { + + var client; + var opts; + var clientReady = false; + + let o = {}; //options + + function main() { + loadSettings(); + } + + //set opts according to db settings + function loadSettings() { + + o = instance.options; + if (!o.topic) o.topic = FLOW.GLOBALS.settings.cloud_topic; + + opts = { + host: o.host, + port: o.port, + clientId: o.clientid, + username: o.username, + rejectUnauthorized: false, + resubscribe: false + }; + + console.log("wsmqttpublich -> loadSettings from instance.options", o); + + if (!o.topic) { + instance.status("Not configured", "white"); + console.log("Cloud mqtt connect: no topic selected"); + return; + } + + connectToTbServer(); + } + + function connectToTbServer() { + var url = "mqtt://" + opts.host + ":" + opts.port; + console.log("MQTT URL: ", url); + + client = mqtt.connect(url, opts); + + client.on('connect', function() { + client.subscribe(`${o.topic}_backward`, (err) => { + if (!err) { + console.log("MQTT subscribed"); + } + }); + instance.status("Connected", "green"); + clientReady = true; + sendClientError = true; + }); + + client.on('reconnect', function() { + instance.status("Reconnecting", "yellow"); + clientReady = false; + }); + + client.on('message', function(topic, message) { + // message is type of buffer + message = message.toString(); + if (message[0] === '{') { + TRY(function() { + + message = JSON.parse(message); + if (message.hasOwnProperty("device") && message.hasOwnProperty("data") && message.data.hasOwnProperty("id")) { + client.publish(`${o.topic}_forward`, `{"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 } }); + } + + }, () => instance.debug('MQTT: Error parsing data', message)); + } + + instance.send(SEND_TO.rpcCall, { "topic": o.topic, "content": message }); + }); + + client.on('close', function() { + clientReady = false; + + instance.status("Disconnected", "red"); + instance.send(SEND_TO.debug, { "message": "Client CLOSE signal received !" }); + }); + + client.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) { + console.log('MQTT client error', err); + sendClientError = false; + } + clientReady = false; + }); + + } + + + instance.on('0', function(data) { + + if (clientReady) { + //do we have some data in backup file? if any, process data from database + if (saveTelemetryOnError) { + //read telemetry data and send back to server + if (!processingData) processDataFromDatabase(); + } + + let stringifiedJson = JSON.stringify(data.data) + client.publish(`${o.topic}_forward`, stringifiedJson, { qos: 1 }); + } + 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 (saveTelemetryOnError && o.topic) { + //create new file from tbdata.nosql, if file size exceeds given limit, and clear tbdata.nosql + makeBackupFromDbFile(); + + //write to tb + data.data.id = UID(); + nosql.insert(data.data); + } + } + }); + + instance.on("1", _ => { + main(); + }) + + instance.close = function(done) { + if (clientReady) { + client.end(); + } + }; + + + function getDbBackupFileCounter(type) { + var files = fs.readdirSync(__dirname + "/../databases"); + + let counter = 0; + for (var i = 0; i < files.length; i++) { + + if (files[i] == "tbdatacloud.nosql") continue; + + if (files[i].endsWith(".nosql")) { + + let pos = files[i].indexOf("."); + if (pos > -1) { + + let fileCounter = counter; + let firstDigit = files[i].slice(0, pos); + + fileCounter = parseInt(firstDigit); + if (isNaN(fileCounter)) fileCounter = 0; + //console.log("getDbBackupFileCounter digit:", files[i], firstDigit, fileCounter, isNaN(fileCounter), type); + + if (type == "max") { + if (fileCounter > counter) { + counter = fileCounter; + } + } + else if (type == "min") { + if (counter == 0) counter = fileCounter; + + if (fileCounter < counter) { + counter = fileCounter; + } + } + } + } + + } + + if (type == "max") counter++; + + return counter; + } + + const makeBackupFromDbFile = async () => { + + if (!saveTelemetryOnError) return; + + //to avoid large file: tbdata.nosql + + //init value is 0! + if (insertNoSqlCounter > 0) { + --insertNoSqlCounter; + return; + } + + insertNoSqlCounter = 100; + + let source = __dirname + "/../databases/tbdatacloud.nosql"; + + var stats = fs.statSync(source); + var fileSizeInBytes = stats.size; + + if (fileSizeInBytes > noSqlFileSizeLimit) { + + let counter = 1; + counter = getDbBackupFileCounter("max"); + + let destination = __dirname + "/../databases/" + counter + "." + "tbdatacloud.nosql"; + + //make backup file + fs.copyFileSync(source, destination); + //fs.renameSync(p, p + "." + counter); + + //clear tbdata.nosql + fs.writeFileSync(source, ""); + fs.truncateSync(source, 0); + + } + } + + const processDataFromDatabase = async () => { + + if (restore_from_backup <= 0) return; + + //calculate diff + const now = new Date(); + let currentTime = now.getTime(); + let diff = currentTime - lastRestoreTime; + + if ((diff / 1000) < restore_backup_wait) { + //console.log("*********restore_backup_wait", diff, restore_backup_wait); + return; + } + + processingData = true; + + //get filename to process + let counter = getDbBackupFileCounter("min"); + + //we have some backup files + let dataBase = 'tbdata'; + + var nosql; + if (counter == 0) dataBase = 'tbdatacloud'; + else dataBase = counter + "." + 'tbdatacloud'; + + nosql = NOSQL(dataBase); + + //select all data - use limit restore_from_backup + let records = await promisifyBuilder(nosql.find().take(restore_from_backup)); + + for (let i = 0; i < records.length; i++) { + if (clientReady) { + + let item = records[i]; + let id = item.id; + + if (id !== undefined) { + //console.log("------------processDataFromDatabase - remove", id, dataBase, i); + + try { + + let message = JSON.parse(JSON.stringify(item)); + delete message.id; + client.publish(`${o.topic}_forward`, JSON.stringify(message), { qos: 1 }); + + //remove from database + await promisifyBuilder(nosql.remove().where("id", id)); + + } catch (error) { + //process error + console.log("processDataFromDatabase", error); + } + + } + + } + else { + processingData = false; + return; + } + } + + if (records.length > 0) { + //clean backup file + if (counter > 0) nosql.clean(); + } + + //no data in db, remove + if (records.length == 0) { + if (counter > 0) nosql.drop(); + } + + const d = new Date(); + lastRestoreTime = d.getTime(); + + processingData = false; + + } + + instance.on('options', main); + +}; diff --git a/RVO13/flow/cmd_manager.js b/RVO13/flow/cmd_manager.js new file mode 100755 index 0000000..25912df --- /dev/null +++ b/RVO13/flow/cmd_manager.js @@ -0,0 +1,3071 @@ +exports.id = 'cmd_manager'; +exports.title = 'CMD Manager'; +exports.group = 'Worksys'; +exports.color = '#5D9CEC'; +exports.version = '0.0.3'; +exports.output = ['red', 'blue', 'yellow', 'blue', 'white', 'green']; +exports.input = 3; +exports.icon = 'cloud-upload'; + +exports.html = ` +
+
+
+
RPC - run RPC calls

+
+
+
@(User)
+
+
+
@(Password)
+
+
+
@(My edge)
+
+
+
+`; +exports.readme = `Manager for CMD calls`; + + +exports.install = function(instance) { + + 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, isEmptyObject, emptyJsObject, writeToFile, addToArrayIfUnique } = require('./helper/utils'); + const bitwise = require('bitwise'); + + var SunCalc = require('./helper/suncalc'); + const DataToTbHandler = require('./helper/DataToTbHandler'); + const errorHandler = require('./helper/ErrorToServiceHandler'); + const { sendNotification } = require('./helper/notification_reporter'); + const process = require('process'); + const { errLogger, logger, monitor } = require('./helper/logger'); + + //for accelerometer purposes + const { naklony } = require("../databases/accelerometer_db"); + + const dbNodes = TABLE("nodes"); + const dbRelays = TABLE("relays"); + + let GLOBALS; + let SETTINGS; + let rsPort; + let tbHandler; + + // runTasks intervals + const SHORT_INTERVAL = 30; + const LONG_INTERVAL = 300; + + //send data to following instances: + const SEND_TO = { + debug: 0, + tb: 1, + http_response: 2, + dido_controller: 3, + infoSender: 4, + dailyReport: 5 + } + + 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 + } + + 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 sendNodeReadout = null; // interval for sending agregate data from node + + 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["1"] = minutes; // dimming + priorities["76"] = minutes; // power + + minutes = 5; + priorities["75"] = minutes; // current + priorities["79"] = minutes; // energy + priorities["87"] = minutes; // aktualny cas + //priorities["84"] = minutes; //accelerometer + + minutes = 10; + priorities["74"] = minutes; // voltage + priorities["77"] = minutes; // power factor + priorities["78"] = minutes; // frequency + + minutes = 60; + priorities["0"] = minutes; // statecode + priorities["6"] = minutes; // dusk + priorities["7"] = minutes; // dawn + priorities["8"] = minutes; // profile + + minutes = 60 * 24; + priorities["89"] = minutes; // verzia fw + priorities["80"] = minutes; // lifetime + + //prikazy kt sa budu spustat na dany node - see config.js in terminal-oms.app. (1 - dimming) + let listOfCommands = [0, 1, 6, 7, 8, 74, 75, 76, 77, 78, 79, 80, 87, 89]; + + 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; + + // holds dusk, dawn (and more) values + let sunCalcResult; + + //helper container for counting resolved group of commands (commands related to set profile) + let cmdCounter = {};//key is node, value is counter + + //TODO: is this set working?? According to previous checks, sets do not work + //if sending of profile to node fails, we send notification and push node into set, so we do not send notification twice + const nodeProfileSendFail = new Set(); + + //we expect to get current temperature in Senica from senica-prod01 + let temperatureInSenica = null; + let accelerometerInterval = null; + + //NOTE: daily reports senica: + //rvo_is_on status, we monitor all nodes - if true, power and dimming should be not 0, if false, 24/7 nodes should be 0, other rvo should not respond + let rvo_is_on; + let previous_rvo_is_on_value; + let handleDailyReport; //setInterval for dailyReportHandler function + let dailyReport = {}; //data needed for daily report + let reportToSend = {}; //final report which we send to cloud + let breakerCounter = null; // status of breakers after flow starts is not in report + let rvoPeriod; // interval of checking dusk dawn and if rvo_is_on + let initialReportStatus = false; + + const DAILY_REPORT_HANDLER_TIME = 3_600_000; + const SET_SUNCALC_RESULT_TIME = 3_600_000; + const SET_RVO_PERIOD_TIME = 300_000; + const ADD_NODE_TO_REPORT_TIME = 3_600_000; + + //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); + + let now = new Date(); + console.log("Cmd-mngr installed", now.toLocaleString("sk-SK")); + + sunCalcResult = calculateDuskDawn(); + + handleRsPort(); + + customTasksInterval = setInterval(reportEdgeDateTimeAndNumberOfLuminaires, 120_000); + setTimeout(reportEdgeDateTimeAndNumberOfLuminaires, 4000); + + //dailyReport related + emptyReportToSend(); + breakerCounter = Object.keys(relaysData).length - 1; // we get number of lines (breakers) except of line 0 + rvoPeriod = setInterval(setRvoPeriod, SET_RVO_PERIOD_TIME); + setTimeout(setRvoPeriod, 3000); + setInterval(setSunCalcResult, SET_SUNCALC_RESULT_TIME); + handleDailyReport = setInterval(dailyReportHandler, DAILY_REPORT_HANDLER_TIME); + + + setCorrectTime = setInterval(setCorrectPlcTimeOnceADay, 60000 * 60); // 1 hour + setCorrectPlcTimeOnceADay(); + + sendNodeReadout = setInterval(sendNodesData, 150_000); + accelerometerInterval = setInterval(accelerometerData, 60000 * 30); //30 min + } + + + 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" + //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 + // if node regular readout does not respond, we repeat request + params.repeatCounter = 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-mngr: 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.byte4 = 96; + params.recipient = 1; + params.register = 8; + params.rw = 1;//write + params.timestamp = timestamp; + 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.byte4 = 96; + params.recipient = 1; + params.register = 8; + params.rw = 1;//write + params.timestamp = timestamp; + 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). + */ + + 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.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.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 + { + + logger.debug("processNodeProfile: Threshold lux level for DUSK/DAWN", node); + + let params = getParams(); + params.type = "set_node_profile"; + params.address = node; + params.register = 96; + params.recipient = 1; + params.rw = 1;//write + params.timestamp = timestamp; + 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(); + params.type = "set_node_profile"; + params.address = node; + params.register = 97; + params.recipient = 1; + params.rw = 1;//write + params.timestamp = timestamp; + 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.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); + + 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); + + console.log("proces profile finished *********************") + } + + + 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; + }); + } + + + 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) { + for (let k in nodesData) { + 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`); + } + } + } + + + function loadRelaysData(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 (value.contactor == 1) processAllNodeProfilesOnLine(value.line); + } + } + + + function reportOnlineNodeStatus(line) { + //Po zapnutí línie broadcastovo aktualizovať predtým čas a o 3 sek neskor - status, brightness + + logger.debug("Cmd-mngr: ----->reportOnlineNodeStatus for line", line); + + const d = new Date(); + + // broadcast actual time + let params = getParams(); + params.address = 0xffffffff;//Broadcast + params.byte1 = d.getHours(); + params.byte2 = d.getMinutes(); + params.recipient = 2;//2 broadcast, address = 0 + params.register = 87;//Actual time + params.rw = 1;//write + params.type = "node-onetime-write"; + params.timestamp = d.getTime() + 30000; + params.info = "run broadcast: Actual time"; + //params.debug = true; + + tasks.push(params); + + let sec = 3; + setTimeout(function() { + //Po zapnutí línie - spraviť hromadný refresh stavu práve zapnutých svietidiel + + let time = Date.now(); + + for (let k in nodesData) { + + //potrebujem nody k danej linii + 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].node_status_before_offline === true || nodesData[k].status === true) { + status = "OK"; + nodesData[k].time_of_last_communication = time; + } + + nodesData[k].readout.status = status; + + updateNodeStatus(k, status === "OK" ? true : false); + if (nodesData[k].hasOwnProperty("node_status_before_offline")) delete nodesData[k].node_status_before_offline; + sendTelemetry({ status: status }, tbname, time); + + //vyreportovanie dimming, current, input power pre liniu pre vsetky nody + //Prud + { + let params = getParams(); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 75;//prud + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = time + 4000; + params.info = 'read current'; + //params.debug = true; + tasks.push(params); + } + + //vykon + { + let params = getParams(); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 76;//výkon + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = time + 4100; + params.info = 'read power'; + //params.debug = true; + + tasks.push(params); + } + //dimming + { + let params = getParams(); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 1;//dimming + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = time + 4200; + params.info = 'read dimming'; + //params.debug = true; + + tasks.push(params); + } + + } + } + + }, sec * 1000); + } + + + function reportOfflineNodeStatus(line) { + + logger.info("Cmd-mngr: ------>reportOffLineNodeStatus for line ", line); + + values = {}; + values["dimming"] = 0;//brightness + values["power"] = 0;//výkon + values["current"] = 0;//prúd + values["status"] = "OFFLINE"; + + const date = Date.now(); + + Object.keys(nodesData).forEach(node => { + + //potrebujem nody k danej linii + if (line == nodesData[node].line || line == undefined) { + + let tbname = nodesData[node].tbname; + let nodeStatus = nodesData[node].status; + + //in case we have reported offline node status, we return (continue with next node) + if (nodeStatus === "OFFLINE") return; + + nodesData[node].node_status_before_offline = nodeStatus; + nodesData[node].status = "OFFLINE"; + nodesData[node].readout = {}; + + sendTelemetry({ ...values }, tbname, date); + } + }); + + } + + + function turnLine(onOrOff, line, info) { + let obj = { + line: line, + command: onOrOff, + info: info + }; + + //to assure, handleDailyReportFunction do not run before rvo_is_on variable changes. So after every line switch we reset the timer + clearInterval(handleDailyReport); + handleDailyReport = setInterval(dailyReportHandler, DAILY_REPORT_HANDLER_TIME); + + //logger.debug("linia", line, obj); + instance.send(SEND_TO.dido_controller, obj); + } + + + 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"; + 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]) { + //CRC_ERROR + message = "NOK"; + error = "CRC_ERROR c1"; + instance.send(SEND_TO.debug, "CRC_ERROR c1"); + } + + 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") { + instance.send(SEND_TO.debug, bytes); + instance.send(SEND_TO.debug, "RESPONSE " + type + " - " + bytes[4]); + + //logger.debug(SEND_TO.debug, "RESPONSE " + type + " - " + bytes[4], bytes); + + error = "type is: " + type; + + message = "NOK"; + } + + return { message, type, error }; + } + + + //BUILD TASKS// + function buildTasks(params) { + + //return; + console.log("buidTAaasks start ****************", params); + monitor.info("buildTasks - params", params); + + let processLine; //defined line + let init = false; + let processLineProfiles = true; + let processBroadcast = true; + let processNodes = true; + + if (params == undefined) { + init = true; + tasks = []; + logger.debug("-->buildTasks clear tasks"); + } + else { + processLineProfiles = params.processLineProfiles; + processBroadcast = false; + processNodes = false; + + processLine = params.line; + } + + let now = new Date(); + + //process line profiles + if (processLineProfiles) { + + let keys = Object.keys(relaysData); + + for (let i = 0; i < keys.length; i++) { + + let line = parseInt(keys[i]); + let profilestr = relaysData[line].profile; + + if (processLine != undefined) { + if (processLine != line) continue; + } + + try { + + /** + * we process line profiles: timepoints, astro clock, lux_sensor, offsets ... + */ + if (profilestr === "") throw ("Profile is not defined"); + let profile = JSON.parse(profilestr); + 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; + + // add name to regular profile timepoint and delete unused end_time key: + time_points.forEach(point => { + point.name = "profileTimepoint" + delete point.end_time; + }); + + //monitor.info("buildTasks: time_points", time_points); + + + /** + * 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 astro clock true, we remove all regular profile points + time_points = []; + + //TODO: when astro clock == true, is offset calculated ??? + //let duskAstroClockOffset = profile.dusk_astro_clock_offset; + //let dawnAstroClockOffset = profile.dawn_astro_clock_offset; + //console.log("line astro clock offsets dusk a dawn: ", duskAstroClockOffset, dawnAstroClockOffset); + // maybe add dusk dawn offset to calculateDuskDawn ?? what dusk dawn will be if dawn_lux_sensor == true?? + //let sunCalcResult = calculateDuskDawn(new Date(), line, duskAstroClockOffset, dawnAstroClockOffset); + + 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 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); + + 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); + + 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(':'); + + let ad = new Date(); + ad.setHours(parseInt(ahours), parseInt(aminutes), 0); + + let bd = new Date(); + bd.setHours(parseInt(bhours), parseInt(bminutes), 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++) { + + let start_time = new Date(); + let [hours, minutes] = time_points[t].start_time.split(':'); + start_time.setHours(parseInt(hours), parseInt(minutes), 0); + + //task is in 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(); + params.type = "relay"; + params.line = parseInt(line); + params.value = time_points[t].value; + params.tbname = relaysData[line].tbname; + params.timestamp = start_time.getTime(); + + // 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; + + //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)) { + 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; + + params.debug = true; + + //turn on/off line + tasks.push(params); + monitor.info("TimePoint params: ", params.info, start_time); + } + + monitor.info("-->time_points final", line, time_points); + + //ensure to turn on/off according to calculated currentValue + let params = getParams(); + params.type = "relay"; + params.line = parseInt(line); + params.tbname = relaysData[line].tbname; + params.value = currentValue; + params.timestamp = i; + params.debug = true; + + //logger.debug(now.toLocaleString("sk-SK")); + 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; + + tasks.push(params); + + } catch (error) { + if (profilestr !== "") { + //errLogger.error(profilestr, error); + console.log(`Cmd_mngr: Unable to process line profile ${line}. Error: `, error); + errorHandler.sendMessageToService(profilestr + "-" + error, 0, "js_error"); + } else { + turnLine("off", line, "No line profile. Switching it off on startup"); + } + } + + } + //logger.debug("tasks:"); + //logger.debug(tasks); + } + + + //NOTE: PROCESS DEFAULT BROADCASTS - Time of dusk, Time of dawn, Actual Time + if (processBroadcast) { + + let d = new Date(); + let time = d.getTime(); + //let sunCalcResult = calculateDuskDawn(); + + { + let params = getParams(); + + params.address = 0xffffffff;//broadcast + params.byte1 = sunCalcResult["dusk_hours"]; + params.byte2 = sunCalcResult["dusk_minutes"]; + params.recipient = 2;//2 broadcast, + params.register = 6;//Time of dusk + params.rw = 1;//write + params.type = "node-regular-write"; + params.timestamp = time + 60000; + params.addMinutesToTimestamp = 60 * 3; //kazde 3 hodiny zisti novy dusk + params.info = "Broadcast-duskTime"; + + tasks.push(params); + } + + { + let params = getParams(); + + params.address = 0xffffffff;//broadcast + params.byte1 = sunCalcResult["dawn_hours"]; + params.byte2 = sunCalcResult["dawn_minutes"]; + params.recipient = 2; //2 broadcast + params.register = 7;//Time of dawn + params.rw = 1;//write + params.type = "node-regular-write"; + params.timestamp = time + 60001; + params.addMinutesToTimestamp = 60 * 3; //kazde 3 hodiny zisti novy dawn + params.info = "Broadcast-dawnTime"; + + tasks.push(params); + } + + { + let params = getParams(); + + params.address = 0xffffffff;//broadcast + params.byte1 = d.getHours(); + params.byte2 = d.getMinutes(); + params.recipient = 2; //2 broadcast + params.register = 87;//Actual time + params.rw = 1;//write + params.type = "node-regular-write"; + params.timestamp = time + 60002; + params.addMinutesToTimestamp = 5; + params.info = "run broadcast: Actual time"; + + tasks.push(params); + } + + } + + //process nodes & tasks - read node's data + if (processNodes) { + + let time = Date.now(); + + for (let k in nodesData) { + let address = parseInt(k); + let tbname = nodesData[k].tbname; + let register = 0; + + for (let i = 0; i < listOfCommands.length; i++) { + + register = listOfCommands[i]; + let addMinutesToTimestamp = priorities[register]; + + let params = getParams(); + + params.address = address; + params.recipient = 1; + params.register = register; + params.type = register == 1 ? "node-dimming-read" : "node-regular-read"; + params.tbname = tbname; + params.timestamp = time + 5000 + i * 500 + addMinutesToTimestamp * 1000; //to make slight time difference + params.addMinutesToTimestamp = addMinutesToTimestamp; + params.info = "Node regular read command"; + + tasks.push(params); + } + + } + } + + + //niektore ulohy sa vygeneruju iba 1x pri starte!!! + if (!init) return; + + + //Master node FW version - modifies SETTINGS.masterNodeIsResponding + { + let params = getParams(); + params.type = "cmd-master"; + params.register = 4; + params.address = 0; + params.timestamp = 0; + params.addMinutesToTimestamp = 5; + params.tbname = SETTINGS.rvoTbName; + params.info = "Master node FW verzia"; + //params.debug = true; + + tasks.push(params); + } + + //kazdu hodinu skontrolovat nastavenie profilov + { + let params = getParams(); + params.type = "process_profiles"; + params.timestamp = Date.now() + 60001; + params.addMinutesToTimestamp = 60;//60 = every hour + params.info = "detekcia nespracovaných profilov linie a nodov"; + //params.debug = true; + + tasks.push(params); + } + + monitor.info("tasks created:", tasks.length); + } + + + /** + * We process line profile, where "astro_clock": true + * example profile: + * + "dawn_lux_sensor": true, + "dusk_lux_sensor": true, + "dawn_lux_sensor_value": 5, + "dusk_lux_sensor_value": 5, + "dawn_astro_clock_offset": 0, + "dusk_astro_clock_offset": 10, + "dawn_lux_sensor_time_window": 30, + "dusk_lux_sensor_time_window": 30, + "dawn_astro_clock_time_window": 60, + "dusk_astro_clock_time_window": 60 + + * if dawn: if currentTimestamp is in timewindow "dawnTime + and - dawn_lux_sensor_time_window" and lux value >= lux_sensor_value, we switch off the line. + * if dusk: we do oposite + * + * dawn: usvit - lux je nad hranicou - vypnem + * dusk: sumrak - lux je pod hranicou - zapnem + */ + 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++) { + + let line = keys[i]; //line is turned off by default + let profilestr = relaysData[line].profile; + const contactor = relaysData[line].contactor; + + try { + + let profile = JSON.parse(profilestr); + if (Object.keys(profile).length === 0) throw ("turnOnOffLinesAccordingToLuxSensor - profile is not defined"); + + 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 (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"); + } + } + } + + //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 (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"); + } + } + } + + } + + } catch (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) { + //MASTER + if (node == 0) return; + + let nodeObj = nodesData[node]; + if (nodeObj == undefined) return; + + let nodeCurrentStatus = nodeObj.status; + const now = Date.now(); + + let data = null; + + if (nodeCurrentStatus === "OFFLINE") { + data = { status: newStatus }; + nodeDbStatusModify(node, data); + return; + } + else 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; + } + + } + + + 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 }; + } + }); + }); + } + + + function processDailyReport() { + + const now = Date.now(); + + for (const [key, value] of Object.entries(dailyReport)) { + + if (["name", "time", "dusk_and_dawn"].includes(key)) continue; + + let poleNumber = nodesData[key]["pole_number"]; + let line = dailyReport[key].line; + let nodeType = nodesData[key]["node_type"]; + let fullNodeName = key // key == nodeNumber + + if (poleNumber && nodeType) { + fullNodeName = SETTINGS.rvo_number + "/" + poleNumber + "_" + line + "L_" + key + "_" + nodeType; + } else { + fullNodeName = key; + } + + if (rvo_is_on) { + + if (value.initialTs) { + if (value.initialTs + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["night_no_data"], fullNodeName); + console.log('report nedostava ziadne data uz hodinu', fullNodeName); + value.initialTs = now; + } + } + if (value.dimmingIsZeroTime) { + if (value.dimmingIsZeroTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["night_dimming=0"], fullNodeName); + console.log("report node dimming je 0 ale ma svietit", fullNodeName); + value.dimmingIsZeroTime = now; + } + } + if (value.powerIsZeroTime) { + if (value.powerIsZeroTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["night_power=0"], fullNodeName); + console.log("report node power je 0 ale ma svietit", fullNodeName); + value.powerIsZeroTime = now; + } + } + + } else { + + let contactorStatus = relaysData[line].contactor; + if (contactorStatus === 1) { + + if (value.initialTs) { + if (value.initialTs + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["day_24/7_no_data"], fullNodeName); + console.log('node je na 24/7 ale nedostava ziadne data uz hodinu', fullNodeName); + value.initialTs = now; + } + } + if (value.dimmingIsOnButShouldBeOffTime) { + if (value.dimmingIsOnButShouldBeOffTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["day_24/7_dimming>0"], fullNodeName); + console.log("report dimming je > 0 ale nema svietit", fullNodeName); + value.dimmingIsOnButShouldBeOffTime = now; + } + } + if (value.powerIsOnButShouldBeOffTime) { + if (value.powerIsOnButShouldBeOffTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["day_24/7_power>0"], fullNodeName); + console.log("report power je > 0 ale nema svietit", fullNodeName); + value.powerIsOnButShouldBeOffTime = now; + } + } + + } + + } + + } + + let report = {}; + report["name"] = SETTINGS.rvo_name; + report["time"] = new Date(); + report["report"] = reportToSend; + + writeToFile(F.path.root("report_data.log"), report, true); + instance.send(SEND_TO.dailyReport, report); + } + + + function dailyReportHandler() { + + if (!SETTINGS.daily_report) return; + + // after dawn we empty reportToSend and start to get data for a new day + const date = new Date(); + const hour = date.getHours(); + const minute = date.getMinutes(); + + console.log("now: ", hour, minute, "suncalc: ", sunCalcResult.dawn_hours, sunCalcResult.dawn_minutes); + + if (hour === sunCalcResult.dawn_hours) { + + //NOTE: ak je este pred usvitom, spracujeme report a posleme na cloud, ak uz je po usvite, resetujeme report plnime data noveho dna + if (minute >= sunCalcResult.dawn_minutes - 2) { + emptyReportToSend(); + emptyDailyReport(); + console.log("Podmienka 1 v dailyReport handler"); + } else { + processDailyReport(); + emptyReportToSend(); + emptyDailyReport(); + console.log("Podmienka 2 v dailyReport handler"); + } + + initialReportStatus = true; + + // ak sa funkcia spusti o hodinu alebo 2 neskor, ako je usvit (moze sa to stat, kedze kazde zapnutie/vypnutie linii odznova spusti casovac. + } else if (hour === sunCalcResult.dawn_hours + 1 || hour === sunCalcResult.dawn_hours + 2) { + if (!initialReportStatus) { + emptyReportToSend(); + emptyDailyReport(); + initialReportStatus = true; + console.log("Podmienka 3 v dailyReport handler"); + } else { + processDailyReport(); + initialReportStatus = true; + console.log("Podmienka 4 v dailyReport handler"); + } + } else { + processDailyReport(); + initialReportStatus = false; + console.log("Podmienka 5 v dailyReport handler"); + } + + console.log("initialReportStatus: ", initialReportStatus); + + } + + function emptyReportToSend() { + emptyJsObject(reportToSend); + reportToSend["contactor"] = { off: [], on: [] }; + reportToSend["night_no_data"] = []; + reportToSend["night_dimming=0"] = []; + reportToSend["night_power=0"] = []; + reportToSend["day_24/7_no_data"] = []; + reportToSend["day_24/7_dimming>0"] = []; + reportToSend["day_24/7_power>0"] = []; + console.log(`resetuje sa reportToSend`); + } + + + //NOTE: ked je initialTs stale rovnaky a zistime ze linie su vypnute (relaysData.line.contactor) - zistim, ci je node na tej linii. Vieme, ze ak je linia vypnuta je to v poriadku lebo nie je na 24/7 linii + //ak je na 24/7 linii, reportujeme, ze neprijima data + function emptyDailyReport() { + const ts = Date.now(); + emptyJsObject(dailyReport); + + //NOTE: do dailyReport dame vsetky nody a pravidelne kontrolujeme ci maju data + //ked nastane sumrak/usvit a svetla maju zacat/prestat svietit, dailyReport spravime nanovo: + for (const [key, value] of Object.entries(nodesData)) { + dailyReport[value.node] = { line: value.line, initialTs: ts }; + } + + console.log("dailyReport: ", dailyReport); + } + + + async function runTasks() { + + clearInterval(interval); + + let currentTimestamp = Date.now(); + + //sort tasks based on timestamp + 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) { + instance.send(SEND_TO.debug, "no tasks created"); + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + if (!rsPort.isOpen) { + instance.send(SEND_TO.debug, "!rsPort.isOpen"); + //await rsPort.open(); + //console.log("Cmd-mngr: !rsPort.isOpen"); + } + + let currentTask = tasks[0]; + + if (currentTask.debug) { + //logger.debug("--->task to process", currentTask); + } + + if (currentTask.timestamp <= currentTimestamp) { + let params = { ...tasks[0] }; + + //allow terminal commands + if (SETTINGS.maintenance_mode && params.type !== "cmd-terminal") { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + let type = params.type; + let tbname = params.tbname; + let node = params.address; + let register = params.register; + let line = null; + let itIsNodeCommand; + + if (nodesData[node] !== undefined) { + line = nodesData[node].line; + itIsNodeCommand = true; + } + + if (params.line !== undefined) line = params.line; + + if (params.addMinutesToTimestamp > 0 || params.timePointName) { + tasks[0].timestamp = currentTimestamp + tasks[0].addMinutesToTimestamp * 60000; + } else { + tasks.shift(); + } + + //kontrola nespracovanych profilov nodov + //TODO: co ked niektore nody neprijimaju profily? kazdu hodinu zahltuju "tasks" array + if (type == "process_profiles") { + //na vsetky zapnutych liniach sa spracuju nespracovane profily nodov + loadRelaysData(); + interval = setInterval(runTasks, SHORT_INTERVAL); + return; + } + + //relay + if (type == "relay") { + + const timePointName = params.timePointName; + const value = params.value; + + let date = new Date(); + date.setDate(date.getDate() + 1);//next day + + let sunCalcResult; + if (timePointName) sunCalcResult = calculateDuskDawn(date, params.line); + + + if (timePointName == "dawn") { + tasks[0].timestamp = sunCalcResult.dawn_time; + } + else if (timePointName == "dusk") { + tasks[0].timestamp = sunCalcResult.dusk_time; + } + else if (timePointName == "luxOn") { + tasks[0].timestamp = sunCalcResult.dusk_time + params.dusk_lux_sensor_time_window * 60000; + } + else if (timePointName == "luxOff") { + tasks[0].timestamp = sunCalcResult.dawn_time + params.dawn_lux_sensor_time_window * 60000; + } + else if (timePointName == "profileTimepoint") { + tasks[0].timestamp = currentTimestamp + tasks[0].addMinutesToTimestamp * 60000; + } + + let info = "aplikovany bod profilu"; + let onOrOff = ""; + value == 1 ? onOrOff = "on" : onOrOff = "off"; + + turnLine(onOrOff, params.line, info); + + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + if (!SETTINGS.masterNodeIsResponding) { + //ak neodpoveda, nebudeme vykonavat ziadne commands, okrem cmd-terminal cmd-master + errorHandler.sendMessageToService("Master node is not responding"); + + let stop = true; + + if (type === "cmd-terminal" || type === "cmd-master") stop = false; + if (stop) { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + } + + let contactorStatus = 1; + if (relaysData[line] != undefined) contactorStatus = relaysData[line].contactor; + + if (line === 0 || contactorStatus === 0 || FLOW.deviceStatus.state_of_breaker[line] === "Off") { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + // TODO: -> status offline for rvo if rotary_switch_state is OFF, this is source of errors + // check if rotary_switch_state == "Off" + // state_of_braker: disconnected = true? + + if (!rsPort.isOpen) { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + //RE-CALCULATE VALUES + //set actual time for broadcast + if (register == 87 && params.recipient === 2) { + var d = new Date(); + params.byte1 = d.getHours();//h + params.byte2 = d.getMinutes();//m + } + + //SET DUSK/DAWN FOR BROADCAST + //Time of dusk + if (register == 6 && params.recipient === 2) { + + if (type != "cmd-terminal") { + params.byte1 = sunCalcResult["dusk_hours"];//h + params.byte2 = sunCalcResult["dusk_minutes"];//m + } + } + + //Time of dawn + if (register == 7 && params.recipient === 2) { + if (type != "cmd-terminal") { + params.byte1 = sunCalcResult["dawn_hours"];//h + params.byte2 = sunCalcResult["dawn_minutes"];//m + } + } + //----------------------- + + instance.send(SEND_TO.debug, "address: " + node + " register:" + register + "type: " + type); + + var startTime, endTime; + startTime = new Date(); + + let saveToTb = true; + if (!tbname) saveToTb = false; + + let resp = com_generic(node, params.recipient, params.rw, register, params.name, params.byte1, params.byte2, params.byte3, params.byte4); + let readBytes = 11; + let timeout = 4000; + + + // await keyword is important, otherwise incorrect data is returned! + await writeData(rsPort, resp, readBytes, timeout).then(function(data) { + + //sometimes happens, that status of node changes to OK, NOK even if line was turned off and should be status OFFLINE. To prevent this, we return if line contactor is 0: + if (itIsNodeCommand && line && relaysData[line].contactor !== 1) return; + + 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); + + //ak sa odpoved zacina 0 - je to v poriadku, inak je NOK + let message = result.message; // OK, NOK + let message_type = result.type; + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + console.log("detected response:", result); + logger.debug("Cmd-mngr: writeData done " + message_type + " duration: " + timeDiff + " type: " + params.debug, params, result); + } + } + + let values = {}; + + //CMD FINISHED + if (message == "OK") { + + updateNodeStatus(node, true); + + //write + if (type == "set_node_profile") { + let result = cmdCounterResolve(node); + if (result == 0) { + dbNodes.modify({ processed: true }).where("node", node).make(function(builder) { + builder.callback(function(err, response) { + + sendNotification("Cmd-mngr: process cmd", SETTINGS.rvoTbName, "dimming_profile_was_successfully_received_by_node", { node: node }, "", SEND_TO.tb, instance); + + logger.debug("--> profil úspešne odoslaný na node č. " + node); + nodesData[node].processed = true; + nodeProfileSendFail.delete(node); + }); + }); + } + } + + //parse read response + if (params.rw == 0) { + values = processResponse(register, dataBytes); //read + } + + if (itIsNodeCommand) { + values.comm_status = "OK"; + values.status = "OK"; + nodesData[node].readout = { ...nodesData[node].readout, ...values }; + + + if (SETTINGS.daily_report) { + //TODO: co ak nedostavame odpovede z nodu ? Musime vyreportovat!! + //v dailyReport teda musi byt kompletny zoznam nodov a neustale kontrolovat, ci maju data, ak nie report node - neodpoveda + if (register === 1) { + + let now = Date.now(); + + if (rvo_is_on === true) { + + if ("dimmingIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].dimmingIsOnButShouldBeOffTime; + + if (values.dimming > 0) { + if ("dimmingIsZeroTime" in dailyReport[node]) delete dailyReport[node].dimmingIsZeroTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if (!("dimmingIsZeroTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], dimmingIsZeroTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } else { + + if ("dimmingIsZeroTime" in dailyReport[node]) delete dailyReport[node].dimmingIsZeroTime; + + if (values.dimming > 0) { + if (!("dimmingIsOnButShouldBeOffTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], dimmingIsOnButShouldBeOffTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if ("dimmingIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].dimmingIsOnButShouldBeOffTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } + } + + if (register === 76) { + + let now = Date.now(); + + if (rvo_is_on === true) { + + if ("powerIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].powerIsOnButShouldBeOffTime; + + if (values.power > 1) { + if ("powerIsZeroTime" in dailyReport[node]) delete dailyReport[node].powerIsZeroTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if (!("powerIsZeroTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], powerIsZeroTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } else { + + if ("powerIsZeroTime" in dailyReport[node]) delete dailyReport[node].powerIsZeroTime; + + if (values.power > 1) { + if (!("powerIsOnButShouldBeOffTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], powerIsOnButShouldBeOffTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if ("powerIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].powerIsOnButShouldBeOffTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } + } + } + + } + + //master node + if (node == 0) { + sendNotification("Cmd-mngr: 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; + } + + if (params.debug) { + //logger.debug("saveToTb", saveToTb, tbname, values); + } + + if (saveToTb && type != "node-regular-read") { + sendTelemetry(values, tbname); + } + else { + if (type == "cmd-terminal") { + terminalCommandResponse(params, "SUCCESS", data); + } + } + + } + else { + terminalCommandResponse(params, "ERROR", data); + handleNokResponseOnRsPort("handleNOK else block", params, itIsNodeCommand, saveToTb); + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + //logger.debug("writeData err: ", error, result, params); + logger.debug("writeData err: ", tbname, node, register, values); + } + } + + //logger.debug(error, result, params); + } + }).catch(function(reason) { + + //console.log("writeData catch exception", reason); + instance.send(SEND_TO.debug, reason); + + terminalCommandResponse(params, "FAILURE", null, reason); + handleNokResponseOnRsPort("handleNOK catch block", params, itIsNodeCommand, saveToTb); + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + logger.debug("-->WRITE FAILED: " + reason, params.debug, params); + } + } + + }); + + } + 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); + } + + + // if node does not respond to request, we repeat request 3 times: + function repeatCommand(params) { + params.repeatCounter++; + if (params.repeatCounter < 4) { + params.timestamp = 0; + params.addMinutesToTimestamp = 0; + tasks.push(params); + } + } + + function handleNokResponseOnRsPort(message, params, itIsNodeCommand, saveToTb) { + + let node = params.address; + let register = params.register; + let type = params.type; + let tbName = params.tbname; + if (!tbName) return; + + let values = {}; + + let updateStatus = updateNodeStatus(node, false); + + if (itIsNodeCommand) { + values.comm_status = "NOK"; + nodesData[node].readout.comm_status = "NOK"; + repeatCommand(params); + } + + if (updateStatus) { + values.status = "NOK"; + nodesData[node].readout.status = "NOK"; + } + + if (type === "node-regular-read") return; + + //master node + if (node == 0) { + sendNotification("Cmd-mngr: 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; + + if (register == 4) values["master_node_version"] = "NOK"; + } + + if (type == "set_node_profile") { + delete cmdCounter[node]; + logger.debug("profil nebol úspešne odoslaný na node č. ", params); + + if (!nodeProfileSendFail.has(node)) { + sendNotification("Cmd-mngr: process cmd", tbName, "configuration_of_dimming_profile_to_node_failed", { node: node }, "", SEND_TO.tb, instance); + nodeProfileSendFail.add(node); + } + } + + // console.log("------",node, register, type, itIsNodeCommand, updateStatus, saveToTb, values); + if (saveToTb) { + sendTelemetry(values, tbName); + } + + } + + + function sendNodesData() { + Object.keys(nodesData).forEach(node => { + if (nodesData[node]["status"] !== "OFFLINE") { + sendTelemetry(nodesData[node].readout, nodesData[node].tbname); + nodesData[node].readout = {}; + } + }) + } + + + /** + * 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; + } + + 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); + + //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 === "OFFLINE") { + nodeObj.node_status_before_offline === true ? number_of_ok_luminaires++ : number_of_nok_luminaires++; + } + else if (nodeObj.status == true) 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 - ts % 60000 //round to full minute + }; + + sendTelemetry(values, SETTINGS.rvoTbName, ts); + } + + + function setSunCalcResult() { + //if next day, we get new dusk and dawn. To make sure, in local timezone 2:00 means 00:00 in utc (it means next day) + if (new Date().getHours() === 2) { + sunCalcResult = calculateDuskDawn(); + console.log("Novy suncalc: ", sunCalcResult); + } + } + + + function setRvoPeriod() { + + if (!SETTINGS.daily_report) return; + + const ts = Date.now(); + + previous_rvo_is_on_value = rvo_is_on; + + if (ts < sunCalcResult.dawn_time - 1_800_000) { // nodes should be on (00:00 -> 06:00 ( - pol hodina, lebo rvo vypina skor) + rvo_is_on = true; + } else if (sunCalcResult.dawn_time - 1_800_000 < ts && ts < sunCalcResult.dusk_time + 1_800_000) { // nodes should be off 06:00 -> 21:00 + rvo_is_on = false; + } else if (sunCalcResult.dusk_time + 1_800_000 < ts) { // nodes should be on 21:00 -> 00:00 + rvo_is_on = true; + } + + if (previous_rvo_is_on_value !== rvo_is_on) { + emptyDailyReport(); + console.log("rvo_is: ", rvo_is_on, previous_rvo_is_on_value); + } + } + + + function handleRsPort() { + + if (rsPort) { + rsPort.removeAllListeners(); + rsPort = null; + } + + //! 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-mngr: rsPort opened success"); + + 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); + + }).catch(function(reason) { + instance.send(SEND_TO.debug, "Cmd-mngr: RPC runSyncExec - promise rejected:" + reason); + }); + }); + + rsPort.on('error', function(err) { + errorHandler.sendMessageToService([exports.title, "unable to open port", SETTINGS.serial_port, err.message], 0); + monitor.info("Cmd-mngr: Error on rsPort", err.message); + }); + + rsPort.on("close", () => { + monitor.info("Cmd-mngr: rsPort closed, reconnecting..."); + setTimeout(handleRsPort, 1000); + }); + + rsPort.open(); + } + + + instance.on("close", () => { + clearInterval(interval); + clearInterval(customTasksInterval); + clearInterval(setCorrectTime); + clearInterval(sendNodeReadout); + clearInterval(accelerometerInterval); + rsPort.close(); + }); + + instance.on("0", _ => { + main(); + }) + + + instance.on("2", _ => { + console.log("dailyReport, reportToSend, rvo_is_on", dailyReport, reportToSend, rvo_is_on, previous_rvo_is_on_value); + }) + + instance.on("1", 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(); + return; + } + else if (flowdata.data == "close") { + rsPort.close(); + return; + } + else if (flowdata.data == "clean") { + tasks = []; + return; + } + else if (flowdata.data == "buildtasks") { + //build & run + return; + } + else if (flowdata.data == "run") { + //durations = []; + + if (tasks.length == 0) { + + buildTasks(); + + if (rsPort.isOpen) { + interval = setInterval(runTasks, 100); + } + else { + instance.send(SEND_TO.debug, "port is not opened!!!"); + } + } + } + else { + //terminal data - object + //logger.debug("flowdata", flowdata.data); + + if (typeof flowdata.data === 'object') { + //logger.debug("dido", flowdata.data); + if (flowdata.data.hasOwnProperty("sender")) { + //data from dido_controller + if (flowdata.data.sender == "dido_controller") { + + if (flowdata.data.hasOwnProperty("cmd")) { + let cmd = flowdata.data.cmd; + + if (cmd == "buildTasks") { + clearInterval(interval); + + logger.debug("-->Cmd-mngr: BUILD TASKS"); + buildTasks(); + + //logger.debug("tasks:"); + //logger.debug(tasks); + + logger.debug("-->Cmd-mngr: RUN TASKS"); + interval = setInterval(runTasks, 5000); + } + else if (cmd == "reload_relays") { + loadRelaysData(flowdata.data.line); + + if (flowdata.data.dataChanged) { + if (!flowdata.data.value) { + reportOfflineNodeStatus(flowdata.data.line); + } + else { + reportOnlineNodeStatus(flowdata.data.line); + } + } + + } + else if (cmd == "rotary_switch_state") { + let value = flowdata.data.value; + + //state was changed + if (rotary_switch_state != value) { + if (value == "Off") { + //vyreportovat vsetky svietdla + reportOfflineNodeStatus(); + } + + rotary_switch_state = value; + } + } + 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) { + + // we send lux_sensor value to all nodes: + let params = getParams(PRIORITY_TYPES.node_broadcast); + + params.recipient = 2;//2 broadcast, address = 0 + params.address = 0xffffffff;//Broadcast + + let ba = longToByteArray(lux_sensor); + + params.byte3 = ba[1];//msb + params.byte4 = ba[0]; + params.timestamp = PRIORITY_TYPES.node_broadcast; + params.info = "run broadcast: Actual Lux level from cabinet"; + params.register = 95;//Actual Lux level from cabinet + params.rw = 1;//write + + tasks.push(params); + + //process profiles + turnOnOffLinesAccordingToLuxSensor(lux_sensor); + } + } + else if (cmd == "state_of_breaker") { + //istic linie + + breakerCounter--; + + let value = flowdata.data.value; + let line = parseInt(flowdata.data.line); + + let dataChanged = false; + if (state_of_breaker[line] != value) dataChanged = true; + + state_of_breaker[line] = value; + + let status = "OK"; + if (value == "Off") status = "NOK"; + + if (dataChanged) { + + if (relaysData.hasOwnProperty(line)) { + let tbname = relaysData[line].tbname; + + if (value == "Off") { + sendNotification("Cmd-mngr: onData", tbname, "circuit_breaker_was_turned_off_line", { line: line }, "", SEND_TO.tb, instance, "circuit_breaker"); + if (breakerCounter < 0) reportToSend["contactor"]["off"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + else { + sendNotification("Cmd-mngr: onData", tbname, "circuit_breaker_was_turned_on_line", { line: line }, "", SEND_TO.tb, instance, "circuit_breaker"); + if (breakerCounter < 0) reportToSend["contactor"]["on"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + + //report status liniu + sendTelemetry({ status: status }, tbname) + + //current value + if (value == "Off") reportOfflineNodeStatus(line); //vyreportovat vsetky svietidla na linii + } + + } + } + else { + logger.debug("undefined cmd", cmd); + } + } + } + + return; + } + + //data from worksys + if (flowdata.data.hasOwnProperty("topic")) { + + let data = getNested(flowdata.data, "content", "data"); + + //if we get temperature in senica from senica-prod01 + let temperature = getNested(flowdata.data, "content", "senica_temperature"); + + if (temperature !== undefined) { + temperatureInSenica = temperature; + return; + } + + if (data === undefined) { + console.log("Invalid rpc command came from platform"); + return; + } + + let command = data.params.command; + let method = data.method; + let profile = data.params.payload; + if (profile == undefined) profile = ""; + let entity = data.params.entities[0]; + let entity_type = entity.entity_type; + let tbname = entity.tb_name; + + instance.send(SEND_TO.debug, flowdata.data); + 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") { + + //let command = data.params.command; + let value = data.params.payload.value; + + if (command == "dimming") { + + let nodeWasFound = false; + let keys = Object.keys(nodesData); + + //logger.debug("-----", keys); + + 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); + + value = parseInt(value); + if (value > 0) value = value + 128; + + params.type = "node-onetime-write"; + params.tbname = tbname; + params.address = node; + params.register = 1; + params.recipient = 1; + params.byte4 = value; + params.rw = 1; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'set dimming from platform'; + //params.debug = true; + + //debug(params); + logger.debug("dimming", params); + + tasks.push(params); + + 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); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 1; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read dimming (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + //pridame aj vyreportovanie - vykon + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 76; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read Input Power (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + //pridame aj vyreportovanie - prud svietidla + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 75; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read Input Current (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + //pridame aj vyreportovanie - power faktor - ucinnik + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 77; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read power factor (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + }, 4000); + + nodeWasFound = true; + break; + } + } + + if (!nodeWasFound) { + logger.debug("set dimming from platform", "unable to find tbname", tbname); + } + } + else { + instance.send(SEND_TO.debug, "undefined command " + command); + logger.debug("undefined command", command); + } + + return; + } + 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++) { + let node = keys[i]; + if (tbname == nodesData[node].tbname) { + + 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"); + + //profil úspešne prijatý pre node č. xx + sendNotification("Cmd-mngr", tbname, "dimming_profile_was_processed_for_node", { node: node }, profile, SEND_TO.tb, instance); + + nodesData[node].processed = false; + nodesData[node].profile = profile; + + processNodeProfile(node); + }); + }); + } + } + } + else { + + instance.send(SEND_TO.debug, "unknown method " + method); + logger.debug("unknown method", method); + + return; + } + } + + //nastav profil linie z platformy + 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") { + + 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++) { + let line = keys[i]; + if (tbname == relaysData[line].tbname) { + //zmazeme tasky + 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) { + + //update profile + logger.debug("worksys - update relay profile done:", profile); + instance.send(SEND_TO.debug, "worksys - update relay profile done"); + + relaysData[line].profile = profile; + + loadRelaysData(line) + logger.debug("loadRelaysData DONE for line", line); + + buildTasks({ processLineProfiles: true, line: line }); + + sendNotification("Cmd-mngr: set profile from worksys", tbname, "switching_profile_was_processed_for_line", { line: line }, profile, SEND_TO.tb, instance); + }); + }); + break; + } + } + } + else if (method == "set_command") { + let value = data.params.payload.value; + + 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; + + 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"); + if (line != 0) reportToSend["contactor"]["off"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + else { + turnLine("on", line, "command received from platform"); + if (line != 0) reportToSend["contactor"]["on"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + } + } + else { + instance.send(SEND_TO.debug, "undefined method " + method); + logger.debug("undefined method", method); + } + + return; + } + else { + instance.send(SEND_TO.debug, "UNKNOW entity_type " + entity_type); + logger.debug("UNKNOW entity_type", entity_type); + } + return; + } + + //terminal + if (!rsPort.isOpen) await rsPort.open(); + + let params = flowdata.data.body; + if (params == undefined) { + //logger.debug("Cmd-mngr: flowdata.data.body is undefined"); + return; + } + + params.priority = PRIORITY_TYPES.terminal; + params.type = "cmd-terminal"; + params.tbname = ""; + params.timestamp = PRIORITY_TYPES.terminal; + params.addMinutesToTimestamp = 0;// do not repeat task!!! + params.debug = true; + + let timestamp = Date.now(); + params.refFlowdataKey = timestamp; + //params.refFlowdata = flowdata; + //refFlowdata = flowdata; + + //console.log("flowdata", flowdata); + + cleanUpRefFlowdataObj(); + + refFlowdataObj[timestamp] = flowdata; + + //fix + //params.address = params.adress; + logger.debug("received from terminal", params); + logger.debug("date/time:", new Date()); + logger.debug("tasks length:", tasks.length); + + //tasks = []; + + //add to tasks + tasks.push(params); + + } + } + }) + + + //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) + } + + + /** + * 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; + + RESTBuilder.make(function(builder) { + + if (!builder) return; + + builder.method('GET'); + builder.url('http://192.168.252.2:8004/gettime?projects_id=1'); + + builder.callback(function(err, response, output) { + + 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); + } + + }); + } + + } 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); + + } else { + //console.log("Read-only", stdout); + + 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]: [ + { + "ts": date, + "values": values + } + ] + } + + tbHandler.sendToTb(dataToTb, instance); + } + + + function calculateDuskDawn(date, line, duskOffset = 0, dawnOffset = 0) { + + if (date === undefined) date = new Date(); + + 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); + } + + //if(profile.dawn_lux_sensor == false) + { + if (profile.hasOwnProperty("dawn_astro_clock_offset")) dawn_astro_clock_offset = parseInt(profile.dawn_astro_clock_offset); + } + + } + + } catch (error) { + if (profilestr != "") { + logger.debug(profilestr); + logger.debug(error); + } + } + + 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; + } + + //Dimming, CCT + else if (register == 1) { + let brightness = 0; + let dimming = byte0; + if (dimming > 128) { + //dimming = -128; + brightness = dimming - 128; + } + + //cct + //Ak Byte3 == 1: CCT = (Byte2*256)+Byte1 + let cct; + if (byte3 == 1) cct = byte2 * 256 + byte1; + else cct = bytesToInt(bytes.slice(0, 3)); + + //cct podla auditu + + values["dimming"] = brightness; + return values; + } + + // + else if (register == 4) { + values["master_node_version"] = bytes[1] + "." + bytes[2]; + //logger.debug("FW Version", register, bytes); + } + + //Napätie + else if (register == 74) { + let voltage = (bytesToInt(bytes) * 0.1).toFixed(1); + values["voltage"] = Number(voltage); + } + + //Prúd + else if (register == 75) { + let current = bytesToInt(bytes); + values["current"] = current; + } + + //výkon + else if (register == 76) { + let power = (bytesToInt(bytes) * 0.1).toFixed(2); + values["power"] = Number(power); + } + + //účinník + else if (register == 77) { + let power_factor = Math.cos(bytesToInt(bytes) * 0.1 * (Math.PI / 180)).toFixed(2); + values["power_factor"] = Number(power_factor); + } + + //frekvencia + else if (register == 78) { + let frequency = (bytesToInt(bytes) * 0.1).toFixed(2); + values["frequency"] = Number(frequency); + } + + //energia + else if (register == 79) { + let energy = bytesToInt(bytes); + values["energy"] = energy / 1000; //energia v kWh -> delit 1000 + } + + //doba života + else if (register == 80) { + let lifetime = (bytesToInt(bytes) / 60).toFixed(2); + values["lifetime"] = Number(lifetime); + } + + //nastavenie profilu + else if (register == 8) { + let time_schedule_settings = bytesToInt(bytes); + values["time_schedule_settings"] = time_schedule_settings; + } + + //naklon - nateraz sa z nodu nevycitava! kvoli problemom s accelerometrom a vracanymi hodnotami, posielame temp a x y z vo funkcii accelerometerData() + else if (register == 84) { + values["temperature"] = byte3 >= 128 ? (byte3 - 128) * (-1) : byte3; + values["inclination_x"] = byte2 >= 128 ? (byte2 - 128) * (-1) : byte2; + values["inclination_y"] = byte1 >= 128 ? (byte1 - 128) * (-1) : byte1; + values["inclination_z"] = byte0 >= 128 ? (byte0 - 128) * (-1) : byte0; + } + + //FW verzia nodu + else if (register == 89) { + //formát: "Byte3: Byte2.Byte1 (Byte0)" + values["fw_version"] = byte3 + ":" + byte2 + "." + byte1 + "(" + byte0 + ")"; + } + + else if (register == 87 || register == 6 || register == 7) { + var d = new Date(); + d.setHours(byte3, byte2, 0, 0); + let timestamp = d.getTime(); + + //aktuálny čas + if (register == 87) values["actual_time"] = timestamp; + //čas súmraku + else if (register == 6) values["dusk_time"] = timestamp; + //čas úsvitu + else if (register == 7) values["dawn_time"] = timestamp; + } + + 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; + + } + + + function getObjectByTbValue(object, tbname) { + return object[Object.keys(object).find(key => object[key].tbname === tbname)]; + } + + + function isObject(item) { + return (typeof item === "object" && !Array.isArray(item) && item !== null); + } + + + // we fake data, that should be received from accelerometer, as they are a bit unreliable. (temperature, x,y,z) + function accelerometerData() { + + if (temperatureInSenica === null) return; + + //clone nodesData and relaysData objects + let nodesData_clone = JSON.parse(JSON.stringify(nodesData)); + let relaysData_clone = JSON.parse(JSON.stringify(relaysData)); + + for (const key in relaysData_clone) { + + const lineData = relaysData_clone[key]; + const lineNumber = lineData.line; + const contactor = lineData.contactor; + + if (lineNumber === 0) continue; + + if (contactor === 1) { + + let date = Date.now(); + + Object.keys(nodesData_clone).forEach((node, index) => { + + setTimeout(function() { + + if (nodesData_clone[node].line === lineNumber) { + + // NOTE: if status of luminaire is NOK or OFFLINE, we do not send data; + let status = nodesData_clone[node].status; + if (status === "OFFLINE" || !status) return; + + let x = null; + if (naklony.hasOwnProperty(node)) x = naklony[node].naklon; + if (x === null) x = 0; + + sendTelemetry({ temperature: Math.round(temperatureInSenica + 10 + Math.floor(Math.random() * 3)), inclination_x: x, inclination_y: 0, inclination_z: 0 }, nodesData_clone[node].tbname, date); + } + + }, (index + 1) * 500); + }) + + } + } + } + + +} // end of instance.export + diff --git a/RVO13/flow/code.js b/RVO13/flow/code.js new file mode 100755 index 0000000..63b31bf --- /dev/null +++ b/RVO13/flow/code.js @@ -0,0 +1,90 @@ +exports.id = 'code'; +exports.title = 'Code'; +exports.group = 'Common'; +exports.color = '#656D78'; +exports.input = true; +exports.output = 1; +exports.author = 'Peter Širka'; +exports.icon = 'code'; +exports.version = '1.2.0'; +exports.options = { outputs: 1, code: 'send(0, value);', keepmessage: true }; + +exports.html = `
+
+
+
@(Number of outputs)
+
@(Minimum is 1)
+
+
+
@(Code)
+
@(Keep message instance)
+
+`; + +exports.readme = `# Code + +This component executes custom JavaScript code as it is and it doesn't contain any secure scope. + +\`\`\`javascript +// value {Object} contains received data +// send(outputIndex, newValue) sends a new value +// error(value) sends an error +// instance {Object} a current component instance +// flowdata {Object} a current flowdata +// repository {Object} a current repository of flowdata +// Example: + +// send() can be execute multiple times +send(0, value); +\`\`\``; + +exports.install = function(instance) { + + var fn; + + instance.on('data', function(response) { + if (fn) { + try { + fn(response.data, instance, response, instance.options, response.repository, require); + } catch (e) { + response.data = e; + instance.throw(response); + } + } + }); + + instance.reconfigure = function() { + try { + if (instance.options.code) { + instance.status(''); + var code = 'var send = function(index, value) { if (options.keepmessage) { flowdata.data = value; instance.send2(index, flowdata); } else instance.send2(index, value);}; var error = function(err) { instance.throw(err); }; ' + instance.options.code; + fn = new Function('value', 'instance', 'flowdata', 'options', 'repository', 'require', code); + } else { + instance.status('Not configured', 'red'); + fn = null; + } + } catch (e) { + fn = null; + instance.error('Code: ' + e.message); + } + }; + + instance.on('options', instance.reconfigure); + instance.reconfigure(); +}; \ No newline at end of file diff --git a/RVO13/flow/comment.js b/RVO13/flow/comment.js new file mode 100755 index 0000000..1e0cd13 --- /dev/null +++ b/RVO13/flow/comment.js @@ -0,0 +1,11 @@ +exports.id = 'comment'; +exports.title = 'Comment'; +exports.group = 'Common'; +exports.color = '#704cff'; +exports.author = 'Martin Smola'; +exports.icon = 'comment'; +exports.traffic = false; +exports.version = '1.0.0'; +exports.readme = '# Comment'; + +exports.install = function() {}; diff --git a/RVO13/flow/count.js b/RVO13/flow/count.js new file mode 100755 index 0000000..fa92ee9 --- /dev/null +++ b/RVO13/flow/count.js @@ -0,0 +1,60 @@ +exports.id = 'count'; +exports.title = 'Count'; +exports.version = '1.0.1'; +exports.author = 'John Graves'; +exports.color = '#656D78'; +exports.icon = 'plus-square'; +exports.input = 2; +exports.output = 1; +exports.options = { increment: 1, initialvalue: 1 }; +exports.readme = `# Counter + +Counter Number of times called.`; + +exports.html = `
+
@(Initial Value)
+
@(Increment)
+

Example Video

+
`; + +exports.readme = `# Count + +This component counts the number of messages received. + +__Response:__ + +Integer value based on the initial value and increment settings. + +__Arguments:__ +- Initial Value: What number should be output on the receipt of the first message. +- Increment: What should the increment be for each following message received.`; + +exports.install = function(instance) { + + var count = 0; + var initialCall = true; + + instance.on('data', function(flowdata) { + var index = flowdata.index; + if (index) { + instance.debug('Reset Count.'); + count = instance.options.initialvalue; + initialCall = true; + } else { + // If this is the first time, set the value to 'initial value' + if(initialCall) { + initialCall = false; + count = instance.options.initialvalue; + } else + count = count+instance.options.increment; + instance.status('Count:' + count); + instance.send2(count); + } + }); + + instance.on('options', function() { + count = instance.options.initialvalue; + initialCall = true; + }); + +}; diff --git a/RVO13/flow/db_connector.js b/RVO13/flow/db_connector.js new file mode 100755 index 0000000..65ee94b --- /dev/null +++ b/RVO13/flow/db_connector.js @@ -0,0 +1,286 @@ +exports.id = 'db_connector'; +exports.title = 'DbConnector'; +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.html = `
+
+
+
DbConnector
+
+
+
`; + +exports.readme = `# read/write data to tables`; + +const instanceSendTo = { + debug: 0, + http_response: 1, +} + +const { promisifyBuilder, makeMapFromDbResult } = require('./helper/db_helper.js'); + +function extractWhereParams(params) +{ + let name = params[0]; + let operator = '='; + let value = params[1]; + + if(params.length == 3) + { + operator = params[1]; + value = params[2]; + } + + return {name: name, operator: operator, value: value}; +} + +exports.install = function(instance) { + + let refFlowdata = null;//holds reference to httprequest flowdata + + instance.on("close", () => { + + }) + + + instance.on("data", async function(flowdata) { + + let params = flowdata.data.body; + console.log("DbConnector", params); + + refFlowdata = flowdata; + + if(refFlowdata != undefined) + { + //make http response + let responseObj = {}; + responseObj["type"] = "SUCESS"; + + try{ + + let table = params.table; + let action = params.action; + + + if(params.data != undefined) + { + let className = params.data.className; + + if(className == "SqlQueryBuilder") + { + let type = params.data.type; + + console.log("SqlQueryBuilder---->", params.data); + + if(type == "SELECT") + { + let table = params.data.queryData.tables[0].table; + + const db = TABLE(table); + var builder = db.find(); + + let result = await promisifyBuilder(builder); + + let response = {}; + response["result"] = result; + response["success"] = true; + + responseObj["data"] = response; + + //console.log(responseObj); + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + } + + return; + } + } + + + console.log("db_connector---->", table, action); + + //actions: read, replace, insert, delete, update... + + if(action == "read") + { + const db = TABLE(params.table); + + //where builder.where('age', '<', 15); + //builder.where('id', 3403); + + var builder = db.find(); + + //https://docs.totaljs.com/latest/en.html#api~DatabaseBuilder~builder.where + if(params.hasOwnProperty("where")) + { + //optionalCan contain "=", "<=", "<", ">=", ">". + //Default value: '=' + + //1.["production_line", 1] + //2. ["or", ["production_line", 1], ["production_line", 2], "end"] + + if (Array.isArray(params.where)) { + + let multipleConditions = false; + + if(params.where[0] == "or") multipleConditions = true; + if (Array.isArray(params.where[0])) multipleConditions = true; + + if(multipleConditions) + { + + for(var i = 0; i < params.where.length; i++) + { + const item = params.where[i]; + + if(item === "or") builder.or(); + + if (Array.isArray(item)) + { + const { name, operator, value } = extractWhereParams(item); + builder.where(name, operator, value); + } + + if(item === "end") builder.end(); + + } + + } + else + { + const { name, operator, value } = extractWhereParams(params.where); + builder.where(name, operator, value); + } + + } + + /* + if(params.where.length >=2 ) + { + let name = params.where[0]; + let operator = '='; + let value = params.where[1]; + + if(params.where.length == 3) + { + operator = params.where[1]; + value = params.where[2]; + } + + builder.where(name, operator, value); + } + */ + } + + if(params.hasOwnProperty("between")) + { + builder.between(params.between[0], params.between[1], params.between[2]); + } + + let response = await promisifyBuilder(builder); + responseObj["data"] = response; + + //console.log(responseObj); + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + + return; + } + + if(action == "delete") + { + + } + + + if(action == "update") + { + //! data receiving from terminal (params) + // { + // hostname: 'localhost', + // table: 'settings', + // action: 'update', + // body: { + // rvo_name: 'terrrr', + // lang: 'en', + // temperature_adress: '28.427B45920702', + // latitude: 48.70826502, + // longitude: 17.28455203, + // mqtt_host: '192.168.252.4', + // mqtt_clientid: 'showroom_test_panel_led', + // mqtt_username: 'xmRd6RJxW53WZe4vMFLU', + // mqtt_port: 1883, + // maintanace_mode: false + // } + // } + const tableToModify = TABLE(params.table); + const newValues = params.body; + + tableToModify.modify(newValues).make(function(builder) { + + builder.callback(function(err, response) { + + if(!err) + { + responseObj["data"] = response; + responseObj["tableUpdated"] = true; + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + } + }); + }); + + } + + if(action == "replace") + { + //truncate table + const db = TABLE(params.table); + var builder = db.remove(); + db.clean(); + + //insert data + let data = params.data; + + for(let i = 0; i < data.length; i++) + { + //console.log(data[i]); + db.insert(data[i]); + } + + console.log("insert done"); + + let responseObj = {}; + responseObj["type"] = "SUCESS"; + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + + + } + + + + } catch (error) { + //console.log(error); + responseObj["type"] = "ERROR"; + responseObj["message"] = error; + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + } + } + }) +} + + diff --git a/RVO13/flow/db_init.js b/RVO13/flow/db_init.js new file mode 100755 index 0000000..b399878 --- /dev/null +++ b/RVO13/flow/db_init.js @@ -0,0 +1,113 @@ +exports.id = 'db_init'; +exports.title = 'DB Initialization'; +exports.group = 'Worksys'; +exports.color = '#888600'; +exports.version = '1.0.2'; +exports.icon = 'sign-out'; +exports.output = 2; + +exports.readme = ` + # DB initialization +`; + +const { promisifyBuilder, makeMapFromDbResult } = require('./helper/db_helper.js'); +const { initNotification } = require('./helper/notification_reporter'); +const errorHandler = require('./helper/ErrorToServiceHandler'); +const total_energy = require('../databases/total_energy'); + +const SEND_TO = { + db_init: 0, + infoSender: 1 +}; + + +exports.install = async function(instance) { + const dbNodes = TABLE("nodes"); + const dbRelays = TABLE("relays"); + const dbSettings = TABLE("settings"); + 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 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.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"]; + Object.keys(dbs.nodesData).forEach(node => dbs.nodesData[node].readout = {}) + + let rvo_number = responseSettings[0]["rvo_name"].match(/\D+(\d{1,2})_/)[1]; + + dbs.settings = { + edge_fw_version: "2025-10-08", //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"], + phases: responseSettings[0]["phases"], + cloud_topic: responseSettings[0]["cloud_topic"], + has_main_switch: responseSettings[0]["has_main_switch"], + daily_report: responseSettings[0]["daily_report"], + send_changed_node_numbers: responseSettings[0]["send_changed_node_numbers"], + rvo_number: rvo_number, + + //dynamic values + masterNodeIsResponding: true, //cmd_manager + maintenance_mode: false, + } + + + dbs.settings.energy_to_switch_lamps = total_energy[rvo_number]; + if (dbs.settings.energy_to_switch_lamps === undefined) console.log('=============== db_init.js: energy_to_switch_lamps is undefined'); + + FLOW.dbLoaded = true; + errorHandler.setProjectId(dbs.settings.project_id); + initNotification(); + + //APP START - send to data services + const toService = { + id: dbs.settings.project_id, + name: dbs.settings.rvo_name, + fw_version: dbs.settings.edge_fw_version, + startdate: new Date().toISOString().slice(0, 19).replace('T', ' '), + js_error: "", + error_message: "" + }; + + instance.send(SEND_TO.infoSender, toService); + console.log("----------------> START - message send to service", toService); + + setTimeout(() => { + console.log("DB_INIT - data loaded"); + instance.send(SEND_TO.db_init, "_") + }, 5000) + +}; + diff --git a/RVO13/flow/debug.js b/RVO13/flow/debug.js new file mode 100755 index 0000000..00cb259 --- /dev/null +++ b/RVO13/flow/debug.js @@ -0,0 +1,100 @@ +exports.id = 'debug'; +exports.title = 'Debug'; +exports.author = 'Peter Širka'; +exports.color = '#967ADC'; +exports.click = true; +exports.input = true; +exports.icon = 'bug'; +exports.version = '2.0.4'; +exports.options = { enabled: true, repository: false, type: 'data' }; +exports.readme = `# Debug + +Prints data to the debug tab.`; + +exports.html = `
+
+
+
@(Output type)
+
@(Path to the property (leave empty to show the whole data object))
+
@(A group name)
+
@(Enabled)
+
+
+
`; + +exports.install = function(instance) { + + instance.on('data', function(response) { + if (instance.options.enabled) { + + var opt = instance.options; + var rep = response.repository; + var val = response.data; + var id = response.id; + + switch (instance.options.type){ + case 'both': + var data = {}; + data.repository = rep; + data.data = val instanceof Error ? { error: val.message, stack: val.stack } : val; + instance.debug(safeparse(opt.property ? U.get(data, opt.property) : data), undefined, opt.group, id); + break; + case 'repository': + instance.debug(safeparse(opt.property ? U.get(rep, opt.property) : rep), undefined, opt.group, id); + break; + case 'data': + default: + if (val instanceof Error) + instance.debug({ error: val.message, stack: val.stack }, undefined, opt.group, id); + else + instance.debug(safeparse(opt.property ? U.get(val, opt.property) : val), undefined, opt.group, id); + break; + } + } + }); + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + instance.save(); + }); + + instance.on('options', function() { + instance.custom.status(); + }); + + instance.custom.status = function() { + instance.status(instance.options.enabled ? 'Enabled' : 'Disabled'); + }; + + instance.custom.status(); + + function safeparse(o) { + + if (o instanceof Buffer) + return o; + + if (o === undefined) + return 'undefined'; + + if (o === null) + return 'null'; + + var cache = []; + var str = JSON.stringify(o, function(key, value) { + if (typeof value === 'object' && value !== null) { + if (cache.indexOf(value) !== -1) { + try { + return JSON.parse(JSON.stringify(value)); + } catch (error) { + return; + } + } + cache.push(value); + } + return value; + }); + cache = null; + return JSON.parse(str); + } +}; diff --git a/RVO13/flow/designer.json b/RVO13/flow/designer.json new file mode 100755 index 0000000..580f5a3 --- /dev/null +++ b/RVO13/flow/designer.json @@ -0,0 +1,3102 @@ +{ + "tabs": [ + { + "name": "MAIN PUSH", + "linker": "main-push", + "id": "1612772287426", + "index": 0 + }, + { + "name": "CMD manager", + "linker": "cmd-manager", + "id": "1615551125555", + "index": 1 + }, + { + "name": "Devices", + "linker": "devices", + "id": "1611921777196", + "index": 2 + } + ], + "components": [ + { + "id": "1611951142547", + "component": "debug", + "tab": "1611921777196", + "name": "ERROR", + "x": 598, + "y": 60, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#DA4453", + "notes": "" + }, + { + "id": "1612776786008", + "component": "wsmqttpublish", + "tab": "1612772287426", + "name": "WS MQTT publish", + "x": 281.75, + "y": 174, + "connections": { + "0": [ + { + "index": "0", + "id": "1615551060773" + } + ], + "1": [ + { + "index": "0", + "id": "1618300858252" + }, + { + "index": "0", + "id": "1618558465485" + } + ], + "2": [ + { + "index": "0", + "id": "1634303685503" + } + ], + "3": [ + { + "index": "0", + "id": "1731068754606" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Connected", + "color": "green" + }, + "options": { + "username": "", + "clientid": "", + "port": "1883", + "host": "" + }, + "color": "#888600", + "notes": "" + }, + { + "id": "1612778461252", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "tb-push", + "x": 72.75, + "y": 328, + "connections": { + "0": [ + { + "index": "0", + "id": "1612783322136" + }, + { + "index": "1", + "id": "1612776786008" + }, + { + "index": "0", + "id": "1731068754606" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1612783322136", + "component": "debug", + "tab": "1612772287426", + "name": "to TB", + "x": 283.75, + "y": 324, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615551060773", + "component": "debug", + "tab": "1612772287426", + "name": "errors from MQTT Broker", + "x": 594, + "y": 57, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#DA4453", + "notes": "" + }, + { + "id": "1615563373927", + "component": "debug", + "tab": "1615551125555", + "name": "Debug", + "x": 755, + "y": 155, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#DA4453", + "notes": "" + }, + { + "id": "1615566865233", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "tb-push", + "x": 755, + "y": 248, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1615798582262", + "component": "debug", + "tab": "1615551125555", + "name": "CMD_debug", + "x": 755, + "y": 346, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615802995322", + "component": "debug", + "tab": "1611921777196", + "name": "Debug", + "x": 596.8833312988281, + "y": 566.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Disabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": false + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615809128443", + "component": "debug", + "tab": "1611921777196", + "name": "tempToTb", + "x": 595.8833312988281, + "y": 658.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615809595184", + "component": "virtualwireout", + "tab": "1611921777196", + "name": "tb-push", + "x": 597.8833312988281, + "y": 377.25, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1616165795916", + "component": "httproute", + "tab": "1615551125555", + "name": "POST /terminal", + "x": 135, + "y": 547, + "connections": { + "0": [ + { + "index": "0", + "id": "1684060205000" + }, + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Listening", + "color": "green" + }, + "options": { + "timeout": 10, + "cachepolicy": 0, + "cacheexpire": "5 minutes", + "size": 5, + "url": "/terminal", + "method": "POST", + "name": "", + "flags": [ + "id:1616165795916", + "post", + 10000 + ], + "emptyresponse": false + }, + "color": "#5D9CEC", + "notes": "### Configuration\n\n- __POST /terminal__\n- flags: \n- maximum request data length: __5 kB__\n- empty response: __false__\n- cache policy: __no cache__\n- cache expire: __5 minutes__", + "cloning": false + }, + { + "id": "1616165824813", + "component": "httpresponse", + "tab": "1615551125555", + "name": "HTTP Response", + "x": 753, + "y": 423, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "json" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1617104731852", + "component": "debug", + "tab": "1615551125555", + "name": "DIDO_Debug", + "x": 669, + "y": 1040, + "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": "turnOff line", + "x": 133, + "y": 1161, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "object", + "data": "{line: 3, command: \"turnOff\", force: true}" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1617115013095", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "tb-push", + "x": 669, + "y": 1150, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1617284749681", + "component": "trigger", + "tab": "1615551125555", + "name": "update profile / node", + "x": 112, + "y": 208, + "connections": { + "0": [ + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "data": "profile_nodes", + "datatype": "string" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1618235171399", + "component": "trigger", + "tab": "1615551125555", + "name": "tun tasks", + "x": 184, + "y": 279, + "connections": { + "0": [ + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "data": "run" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1618300858252", + "component": "debug", + "tab": "1612772287426", + "name": "wsmqtt-exit1", + "x": 597.8833312988281, + "y": 149, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1618393583970", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "to-cmd-manager", + "x": 668.8833312988281, + "y": 1269, + "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": 132.88333129882812, + "y": 367, + "connections": { + "0": [ + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "platform-rpc-call", + "color": "gray" + }, + "options": { + "wirename": "platform-rpc-call" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1618393759854", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "cmd_to_dido", + "x": 119.88333129882812, + "y": 1007, + "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": 752.8833312988281, + "y": 527, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "cmd_to_dido", + "color": "gray" + }, + "options": { + "wirename": "cmd_to_dido" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1618558465485", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "platform-rpc-call", + "x": 597.8833312988281, + "y": 247, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "platform-rpc-call", + "color": "gray" + }, + "options": { + "wirename": "platform-rpc-call" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1618572059773", + "component": "trigger", + "tab": "1615551125555", + "name": "turnOn line", + "x": 132, + "y": 1085, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "data": "{line: 1, command: \"turnOn\", force: true}", + "datatype": "object" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1619515097737", + "component": "cmd_manager", + "tab": "1615551125555", + "name": "CMD Manager", + "x": 452.1091003417969, + "y": 341.05455017089844, + "connections": { + "0": [ + { + "index": "0", + "id": "1615563373927" + } + ], + "1": [ + { + "index": "0", + "id": "1615566865233" + }, + { + "index": "0", + "id": "1615798582262" + } + ], + "2": [ + { + "index": "0", + "id": "1616165824813" + } + ], + "3": [ + { + "index": "0", + "id": "1618393827655" + } + ], + "4": [ + { + "index": "0", + "id": "1635936391935" + } + ], + "5": [ + { + "index": "0", + "id": "1757006030239" + }, + { + "index": "0", + "id": "1757006060377" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1619605019281", + "component": "httproute", + "tab": "1615551125555", + "name": "GET db", + "x": 173, + "y": 653, + "connections": { + "0": [ + { + "index": "0", + "id": "1684060205000" + }, + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Listening", + "color": "green" + }, + "options": { + "timeout": 5, + "cachepolicy": 0, + "cacheexpire": "5 minutes", + "size": 5, + "url": "/db", + "method": "GET", + "name": "", + "flags": [ + "id:1619605019281", + "get", + 5000 + ] + }, + "color": "#5D9CEC", + "notes": "### Configuration\n\n- __GET /db__\n- flags: undefined\n- maximum request data length: __5 kB__\n- empty response: __undefined__\n- cache policy: __no cache__\n- cache expire: __5 minutes__", + "cloning": false + }, + { + "id": "1619784672383", + "component": "trigger", + "tab": "1615551125555", + "name": "turnOnAlarm", + "x": 120, + "y": 1234, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "object", + "data": "{command: \"turnOnAlarm\"}" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1619784812964", + "component": "trigger", + "tab": "1615551125555", + "name": "turnOffAlarm", + "x": 118, + "y": 1307, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "object", + "data": "{command: \"turnOffAlarm\"}" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1621340721628", + "component": "virtualwireout", + "tab": "1611921777196", + "name": "modbus_to_dido", + "x": 599, + "y": 471, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "modbus_to_dido", + "color": "gray" + }, + "options": { + "wirename": "modbus_to_dido" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1622640022885", + "component": "httproute", + "tab": "1615551125555", + "name": "POST /db_connector", + "x": 98, + "y": 1586, + "connections": { + "0": [ + { + "index": "0", + "id": "1622640073521" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Listening", + "color": "green" + }, + "options": { + "timeout": 5, + "cachepolicy": 0, + "cacheexpire": "5 minutes", + "size": 5, + "url": "/db_connector", + "method": "POST", + "flags": [ + "id:1622640022885", + "post", + 5000 + ] + }, + "color": "#5D9CEC", + "notes": "### Configuration\n\n- __POST /db_connector__\n- flags: \n- maximum request data length: __5 kB__\n- empty response: __undefined__\n- cache policy: __no cache__\n- cache expire: __5 minutes__", + "cloning": false + }, + { + "id": "1622640073521", + "component": "db_connector", + "tab": "1615551125555", + "name": "DbConnector", + "x": 372, + "y": 1572, + "connections": { + "1": [ + { + "index": "0", + "id": "1622641420685" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "edge": "undefined" + }, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1622641420685", + "component": "httpresponse", + "tab": "1615551125555", + "name": "HTTP Response", + "x": 596, + "y": 1586, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1634303504177", + "component": "monitormemory", + "tab": "1612772287426", + "name": "RAM", + "x": 69.88333129882812, + "y": 888.5, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465281992" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "858.88 MB / 985.68 MB", + "color": "gray" + }, + "options": { + "enabled": true, + "interval": 30000 + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1634303533779", + "component": "monitordisk", + "tab": "1612772287426", + "name": "disk", + "x": 70.88333129882812, + "y": 982.5, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465821120" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "5.78 GB / 7.26 GB", + "color": "gray" + }, + "options": { + "enabled": true, + "path": "/", + "interval": 30000 + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1634303595494", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "send-to-services", + "x": 51.883331298828125, + "y": 1400.5, + "connections": { + "0": [ + { + "index": "0", + "id": "1634463186563" + }, + { + "index": "1", + "id": "1634488120710" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1634303602169", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "send-to-services", + "x": 426.8833312988281, + "y": 878.5, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1634303685503", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "send-to-services", + "x": 600.8833312988281, + "y": 341.5, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1634303743260", + "component": "httprequest", + "tab": "1612772287426", + "name": "192.168.252.2:8004/sentmessage", + "reference": "", + "x": 506.8833312988281, + "y": 1331.7333374023438, + "connections": { + "0": [ + { + "index": "0", + "id": "1635327431236" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "url": "http://192.168.252.2:8004/sentmessage", + "method": "POST", + "stringify": "json" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1634463186563", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 305.75, + "y": 1442, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634464580289", + "component": "code", + "tab": "1612772287426", + "name": "Code", + "x": 245, + "y": 787, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465243324" + }, + { + "index": "0", + "id": "1634303602169" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "keepmessage": true, + "code": "let response = {};\nresponse.cpu = value.cpu;\nresponse.uptime = value.uptime;\n\nsend(0, response);", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1634465243324", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 428, + "y": 784, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634465281992", + "component": "code", + "tab": "1612772287426", + "name": "Code", + "x": 245, + "y": 884, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465338103" + }, + { + "index": "0", + "id": "1634303602169" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "keepmessage": true, + "code": "value.sender = \"ram\";\n\nlet response = {};\n\nresponse.memory_total = Math.round(value.total / (1024 ** 2));\nresponse.memory_free = Math.round(value.free / (1024 ** 2));\nresponse.memory_used = Math.round(value.used / (1024 ** 2));\n\nsend(0, response);", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1634465338103", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 429, + "y": 976, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634465821120", + "component": "code", + "tab": "1612772287426", + "name": "Code", + "x": 245, + "y": 978, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465892500" + }, + { + "index": "0", + "id": "1634303602169" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "keepmessage": true, + "code": "value.sender = \"hdd\";\n\nlet response = {};\n\nresponse.hdd_total = Math.round(value.total / (1024 ** 2));\nresponse.hdd_free = Math.round(value.free / (1024 ** 2));\nresponse.hdd_used = Math.round(value.used / (1024 ** 2));\n\nsend(0, response);", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1634465892500", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 432, + "y": 1068, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634484067516", + "component": "debug", + "tab": "1612772287426", + "name": "Send info", + "x": 513, + "y": 1441, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634488120710", + "component": "infosender", + "tab": "1612772287426", + "name": "Info sender", + "x": 301, + "y": 1336, + "connections": { + "0": [ + { + "index": "0", + "id": "1634484067516" + }, + { + "index": "0", + "id": "1634303743260" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "edge": "undefined" + }, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1635327431236", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 837.8833312988281, + "y": 1325.5, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1635936391935", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "send-to-services", + "x": 753, + "y": 623, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1637069803394", + "component": "monitorconsumption", + "tab": "1612772287426", + "name": "CPU", + "x": 69, + "y": 791, + "connections": { + "0": [ + { + "index": "0", + "id": "1634464580289" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "49.2% / 69.91 MB", + "color": "gray" + }, + "options": { + "monitorfiles": true, + "monitorconnections": true, + "monitorsize": true, + "monitorconsumption": true, + "enabled": true, + "interval": 30000 + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1683664161036", + "component": "debug", + "tab": "1615551125555", + "name": "CMDtoDIDO", + "x": 392, + "y": 1012, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1683981346282", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "from-dido-controller", + "x": 112, + "y": 459, + "connections": { + "0": [ + { + "index": "0", + "id": "1684055037116" + }, + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "from-dido-controller", + "color": "gray" + }, + "options": { + "wirename": "from-dido-controller" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1684055037116", + "component": "debug", + "tab": "1615551125555", + "name": "from dido to cmd", + "x": 451, + "y": 532, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1684060205000", + "component": "debug", + "tab": "1615551125555", + "name": "HTTP routes", + "x": 450, + "y": 639, + "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": "MDBToDido", + "x": 598, + "y": 147, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1699963668903", + "component": "dido_controller", + "tab": "1615551125555", + "name": "DIDO_Controller", + "x": 397, + "y": 1131, + "connections": { + "0": [ + { + "index": "0", + "id": "1617104731852" + } + ], + "1": [ + { + "index": "0", + "id": "1617104731852" + }, + { + "index": "0", + "id": "1617115013095" + } + ], + "2": [ + { + "index": "0", + "id": "1618393583970" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "edge": "undefined" + }, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1699964678894", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "modbus_to_dido", + "x": 96, + "y": 924, + "connections": { + "0": [ + { + "index": "0", + "id": "1699963668903" + }, + { + "index": "0", + "id": "1699964793925" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "modbus_to_dido", + "color": "gray" + }, + "options": { + "wirename": "modbus_to_dido" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1699964793925", + "component": "debug", + "tab": "1615551125555", + "name": "modbusToDido", + "x": 388, + "y": 920, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1699965957410", + "component": "modbus_reader", + "tab": "1611921777196", + "name": "Modbus reader", + "x": 232, + "y": 175, + "connections": { + "0": [ + { + "index": "0", + "id": "1611951142547" + } + ], + "1": [ + { + "index": "0", + "id": "1621340721628" + }, + { + "index": "0", + "id": "1684179110403" + }, + { + "index": "0", + "id": "1717441414646" + } + ], + "2": [ + { + "index": "0", + "id": "1615809595184" + }, + { + "index": "0", + "id": "1714752862828" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1700411878636", + "component": "thermometer", + "tab": "1611921777196", + "name": "Thermometer", + "x": 234.75, + "y": 444, + "connections": { + "0": [ + { + "index": "0", + "id": "1615802995322" + } + ], + "1": [ + { + "index": "0", + "id": "1615809595184" + }, + { + "index": "0", + "id": "1615809128443" + } + ], + "2": [ + { + "index": "0", + "id": "1621340721628" + }, + { + "index": "0", + "id": "1732889185927" + }, + { + "index": "0", + "id": "1717441414646" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#5CB36D", + "notes": "" + }, + { + "id": "1714752862828", + "component": "debug", + "tab": "1611921777196", + "name": "MDBToTb", + "x": 766, + "y": 324, + "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": 764.0833282470703, + "y": 222, + "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\telse if(value.status === \"NOK-thermometer\")\n\t{\n\t\tsend(0, {\"thermometer\": \"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\telse if(value.values.hasOwnProperty(\"temperature\"))\n\t{\n\t\tsend(0, {\"thermometer\": \"OK\"});\n\t}\n}", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1717442627834", + "component": "debug", + "tab": "1611921777196", + "name": "modbus service", + "x": 966.0833282470703, + "y": 165, + "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": 968.0833282470703, + "y": 268, + "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": 88.75, + "y": 1685, + "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": 296, + "y": 1671, + "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\", \"Flow has been restarted\", \"Node db has changed\"]", + "types": "[\"emergency\", \"critical\", \"error\", \"alert\"]", + "name": "" + }, + "color": "#30E193", + "notes": "" + }, + { + "id": "1718016073501", + "component": "httprequest", + "tab": "1612772287426", + "name": "http://192.168.252.2:8004/slack", + "x": 495, + "y": 1753, + "connections": { + "0": [ + { + "index": "0", + "id": "1718016086212" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "url": "http://192.168.252.2:8004/slack", + "method": "POST", + "stringify": "json" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1718016086212", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 832, + "y": 1664, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "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": 87, + "y": 1591, + "connections": { + "0": [ + { + "index": "0", + "id": "1718016052341" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "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\": \"\" } } } ] }", + "datatype": "object" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1729855334955", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "platform-rpc-call", + "x": 599.9333343505859, + "y": 541.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "platform-rpc-call", + "color": "gray" + }, + "options": { + "wirename": "platform-rpc-call" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1729855371093", + "component": "debug", + "tab": "1612772287426", + "name": "rpc cloud", + "x": 601.9333343505859, + "y": 440.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1731068658334", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 75.75, + "y": 184, + "connections": { + "0": [ + { + "index": "0", + "id": "1612776786008" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731068754606", + "component": "cloudmqttconnect", + "tab": "1612772287426", + "name": "MQTT to senica-prod01", + "x": 284.75, + "y": 452, + "connections": { + "1": [ + { + "index": "0", + "id": "1729855371093" + }, + { + "index": "0", + "id": "1729855334955" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Connected", + "color": "green" + }, + "options": { + "username": "", + "clientid": "", + "port": "2764", + "host": "192.168.252.2", + "topic": "" + }, + "color": "#888600", + "notes": "" + }, + { + "id": "1731069001548", + "component": "db_init", + "tab": "1612772287426", + "name": "DB Initialization", + "x": 1003.75, + "y": 240.25, + "connections": { + "0": [ + { + "index": "0", + "id": "1731069033416" + } + ], + "1": [ + { + "index": "0", + "id": "1747561603739" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#888600", + "notes": "" + }, + { + "id": "1731069033416", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "db-init", + "x": 1244.75, + "y": 233.25, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069059135", + "component": "showdb", + "tab": "1612772287426", + "name": "Show db data", + "x": 1186.75, + "y": 821.25, + "connections": { + "0": [ + { + "index": "0", + "id": "1731069079243" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#888600", + "notes": "" + }, + { + "id": "1731069079243", + "component": "debug", + "tab": "1612772287426", + "name": "dbData", + "x": 1390.75, + "y": 870.25, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1731069116691", + "component": "trigger", + "tab": "1612772287426", + "name": "settings", + "x": 934.75, + "y": 669.75, + "connections": { + "0": [ + { + "index": "0", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069131637", + "component": "trigger", + "tab": "1612772287426", + "name": "relaysData", + "x": 876.75, + "y": 733.75, + "connections": { + "0": [ + { + "index": "1", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069137374", + "component": "trigger", + "tab": "1612772287426", + "name": "nodesData", + "x": 852.75, + "y": 794.75, + "connections": { + "0": [ + { + "index": "2", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069179846", + "component": "trigger", + "tab": "1612772287426", + "name": "pinsData", + "x": 850.75, + "y": 861.75, + "connections": { + "0": [ + { + "index": "3", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069192937", + "component": "trigger", + "tab": "1612772287426", + "name": "sample data", + "x": 857.75, + "y": 928.75, + "connections": { + "0": [ + { + "index": "4", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069264443", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 63.75, + "y": 1279, + "connections": { + "0": [ + { + "index": "0", + "id": "1634488120710" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069334626", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "db-init", + "x": 172.88333129882812, + "y": 129, + "connections": { + "0": [ + { + "index": "0", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069548145", + "component": "virtualwirein", + "tab": "1611921777196", + "name": "db-init", + "x": 46.75, + "y": 192, + "connections": { + "0": [ + { + "index": "0", + "id": "1699965957410" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069567152", + "component": "virtualwirein", + "tab": "1611921777196", + "name": "db-init", + "x": 44.75, + "y": 465, + "connections": { + "0": [ + { + "index": "0", + "id": "1700411878636" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731070156936", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "db-init", + "x": 126.88333129882812, + "y": 1377, + "connections": { + "0": [ + { + "index": "2", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731234189516", + "component": "trigger", + "tab": "1612772287426", + "name": "monitor.txt", + "x": 882.75, + "y": 991.75, + "connections": { + "0": [ + { + "index": "5", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731234189551", + "component": "trigger", + "tab": "1612772287426", + "name": "err.txt", + "x": 904.75, + "y": 1053.75, + "connections": { + "0": [ + { + "index": "6", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1732700042559", + "component": "nodesdb_change_check", + "tab": "1612772287426", + "name": "Nodes DB change check", + "x": 266.8833312988281, + "y": 1980.2333984375, + "connections": { + "0": [ + { + "index": "0", + "id": "1732700071298" + }, + { + "index": "0", + "id": "1732700642917" + } + ], + "1": [ + { + "index": "0", + "id": "1759958914348" + }, + { + "index": "0", + "id": "1759959003114" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#888600", + "notes": "" + }, + { + "id": "1732700057052", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 76.75, + "y": 1988, + "connections": { + "0": [ + { + "index": "0", + "id": "1732700042559" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1732700071298", + "component": "debug", + "tab": "1612772287426", + "name": "nodesChange", + "x": 571.8833312988281, + "y": 2018.2333984375, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1732700642917", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "tb-push", + "x": 567.8833312988281, + "y": 1933, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1732889185927", + "component": "debug", + "tab": "1611921777196", + "name": "tempToDido", + "x": 594.8833312988281, + "y": 753, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1733574412965", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 72.75, + "y": 474, + "connections": { + "0": [ + { + "index": "1", + "id": "1731068754606" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1747561603739", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "send-to-services", + "x": 1243.8833312988281, + "y": 334.5, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1747562867845", + "component": "comment", + "tab": "1612772287426", + "name": "FLOW STARTING POINT", + "x": 1003.5666656494141, + "y": 178, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#704cff", + "notes": "" + }, + { + "id": "1749211698385", + "component": "trigger", + "tab": "1612772287426", + "name": "deviceStatus", + "x": 911.75, + "y": 1116.75, + "connections": { + "0": [ + { + "index": "7", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1757006030239", + "component": "httprequest", + "tab": "1615551125555", + "name": "192.168.252.2:8015/daily_report", + "x": 756.5666656494141, + "y": 715.4499969482422, + "connections": { + "0": [ + { + "index": "0", + "id": "1757006045804" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "stringify": "json", + "method": "POST", + "url": "http://192.168.252.2:8015/daily_report" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1757006045804", + "component": "debug", + "tab": "1615551125555", + "name": "ddd", + "x": 1091.566665649414, + "y": 711.4499969482422, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1757006060377", + "component": "debug", + "tab": "1615551125555", + "name": "reportDebug", + "x": 749.5666656494141, + "y": 799.4499969482422, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1759958914348", + "component": "httprequest", + "tab": "1612772287426", + "name": "http://192.168.252.2:8015/node_numbers", + "x": 571, + "y": 2111, + "connections": { + "0": [ + { + "index": "0", + "id": "1759958927094" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "stringify": "json", + "method": "POST", + "url": "http://192.168.252.2:8015/node_numbers" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1759958927094", + "component": "debug", + "tab": "1612772287426", + "name": "nodesChangeCloud", + "x": 951.8833312988281, + "y": 2109.2333984375, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1759959003114", + "component": "debug", + "tab": "1612772287426", + "name": "nodeChangeCloud1", + "x": 574, + "y": 2218, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1760020290879", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 84.75, + "y": 1787, + "connections": { + "0": [ + { + "index": "1", + "id": "1718016052341" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + } + ], + "version": 615 +} diff --git a/RVO13/flow/dido_controller.js b/RVO13/flow/dido_controller.js new file mode 100755 index 0000000..d16fb19 --- /dev/null +++ b/RVO13/flow/dido_controller.js @@ -0,0 +1,1486 @@ +exports.id = 'dido_controller'; +exports.title = 'DIDO_Controller'; +exports.version = '2.0.0'; +exports.group = 'Worksys'; +exports.color = '#2134B0'; +exports.input = 3; +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 + +state_of_main_switch - reportovat stav hlaveho istica : 0-> off 1-> on +rotary_switch_state - sem by sa mal reportovat stav vstupov manual a auto pola nasledovnej logiky: Manual = 1 a Auto = 0 -> Manu +Manual = 0 a Auto = 0 -> Off, Manual = 0 a Auto = 1 -> Automatic + +door_condition - pin 6, dverový kontakt -> 1 -> vyreportuje Closed, 0 -> vyreportuje Ope +twilight_sensor - hodnotu, ktoru vracia ten analogovy vstup (17) treba poslat sem ako float number. Zrejme tu potom pridame nejaky koeficient prevodu na luxy + +Na kazdu liniu +state_of_breaker - podla indexu istica sa reportuje jeho stav, teda istic na liniu 1: 0-> off, 1-> on +state_of_contactor - podla indexu stkaca sa reportuje jeho stav, teda stykac 1 na liniu 1: 0-> off, 1-> on +*/ + +const { errLogger, logger, monitor } = require('./helper/logger'); +const SerialPort = require('serialport'); +const WebSocket = require('ws'); +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 errorHandler = require('./helper/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 hasMainSwitch; + +let alarmStatus = "OFF"; + +const SEND_TO = { + debug: 0, + tb: 1, + cmd_manager: 2 +} + + +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 = {}; + let rsPortReceivedData = []; + + //to be able to get proper twilight values + let twilight_sensor_interval = 5;//minutes + let twilight_sensor = []; + const twilight_sensor_array = []; + let twilightError = false; + + monitor.info("DIDO_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-we make it global to see it from outside + FLOW.deviceStatus = { //key is device name: temperature,.... + "state_of_main_switch": "Off", //Hlavny istic (alebo druhy dverovy kontakt) + "rotary_switch_state": "Off", //Prevadzkovy + "door_condition": "closed", //Dverový kontakt + "em": "OK", //elektromer rvo + "temperature": "OK", //templomer + "battery": "OK", //Bateria + "power_supply": "OK", //Zdroj + "master_node": "OK", //MN - GLOBALS.settings.masterNodeIsResponding + "no_voltage": "OK", //GLOBALS.settings.no_voltage - vypadok napatia na faze + "state_of_breaker": {}, //"Off",//Istic + "state_of_contactor": {}, //"Off",//Stykac + "twilight_sensor": "OK" //lux sensor + }; + let deviceStatus = FLOW.deviceStatus; + + + function main() { + + GLOBALS = FLOW.GLOBALS; + SETTINGS = FLOW.GLOBALS.settings; + rvoTbName = SETTINGS.rvoTbName; + pinsData = GLOBALS.pinsData; + relaysData = GLOBALS.relaysData; + + tbHandler = new DataToTbHandler(SEND_TO.tb); + tbHandler.setSender(exports.title); + + controller_type = SETTINGS.controller_type; //"lm" or "unipi" + hasMainSwitch = SETTINGS.has_main_switch; + + if (controller_type == "") controller_type = "lm"; + + 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, "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; + } + } + + //report RVO version relaysData[0].tbname; + let values = {}; + values["edge_fw_version"] = SETTINGS.edge_fw_version; + values["maintenance_mode"] = SETTINGS.maintenance_mode; + + sendTelemetry(values, rvoTbName); + + 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); + } + + + function handleRsPort() { + + if (rsPort) { + rsPort.removeAllListeners(); + rsPort = null; + } + + //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('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) { + if (!err) { + monitor.info(exports.title + "--->Digital in_out has been set (runSyncExec was sucessfull)"); + + turnAlarm("off"); + 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('error', err => { + let message = "Dido: rsPort error: " + err.message; + logger.debug(message); + monitor.info(message); + errorHandler.sendMessageToService(message); + }) + + rsPort.on("close", () => { + let message = "Dido: rsPort closed - reconnecting ..."; + logger.debug(message); + monitor.info(message); + setTimeout(handleRsPort, 1000); + }) + + rsPort.open(); + } + + + function handleWebSocket() { + + if (ws) { + ws.removeAllListeners(); + ws = null; + } + + //to keep websocket opened, we send request every 150 seconds + let startRequests = null; + + console.log("handleWebSocket function called"); + ws = new WebSocket('ws:/0.0.0.0:1234/ws'); + + ws.onopen = function open() { + + instance.send(0, exports.title + " running"); + turnAlarm("off"); + + initialSetting(); + + setTimeout(function() { ws.send(JSON.stringify({ cmd: "all" })) }, 5000); + // we request dev info about neuron device from evok to keep websocket connection alive + // for some reason this request returns no data, but connection keeps alive + startRequests = setInterval(() => { + ws.send(JSON.stringify({ "cmd": "filter", "dev": ["neuron"] })); + }, 150000) + }; + + + // 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 = async 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; + + 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 => { + logger.debug('Dido: websocket error', err); + }) + + ws.onclose = function() { + logger.debug('Dido: websocket onclose, reconnecting...') + clearInterval(startRequests); + setTimeout(handleWebSocket, 1000); + } + } + + 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 turnAlarm(onOrOff) { + let value = 0; + if (onOrOff == "on") value = 1; + + if (value == 1 && SETTINGS.maintenance_mode) return; + + alarmStatus = "OFF"; + if (value == 1) alarmStatus = "ON"; + + if (rsPort) { + let arr = [0x55]; + arr.push(13); + arr.push(0); + arr.push(value); + + rsPort.write(Buffer.from(arr), function(err) { + logger.debug(`sirena - ${onOrOff}`); + }); + } + else if (ws) { + let cmd = { "cmd": "set", "dev": "relay", "circuit": "1_01", "value": value }; + ws.send(JSON.stringify(cmd)); + logger.debug(`sirena - ${onOrOff}`); + } + } + + + 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") { + bits.push(0); + } + else bits.push(1); + + if (deviceStatus["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); + } + + + // turn line on or off + function turnLine(onOrOff, line, pin, force, info) { + //onOrOff => "on" or "off" + let value = 0; + if (onOrOff == "on") value = 1; + + if (force == undefined) force = false; + + if (line == 0) { + if (value == 1 && alarmStatus == "ON") turnAlarm("off"); + SETTINGS.maintenance_mode = value ? true : false; + + 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); + return; + } + + if (pin === undefined) pin = getPin(line); + + if (pin === undefined) { + errLogger.error("pin is undefined!", line); + return; + } + + if (!force) { + if (relaysData[line].contactor == value) { + instance.send(SEND_TO.debug, `line is already ${onOrOff} ` + line); + logger.debug(`Dido: turnLine: line is already ${onOrOff} `, line); + return; + } + } + + // if(!rsPort.isOpen && !ws) + if (!rsPort && !ws) { + errLogger.error("Dido - port or websocket is not opened"); + return; + } + + if (rsPort) { + let arr = [0x55]; + arr.push(pin); + arr.push(0); + arr.push(value); + + rsPort.write(Buffer.from(arr), function(err) { + if (err === undefined) { + monitor.info(`Dido: turnLine ${onOrOff} zapisal do rsPort-u`, line, pin, arr, info); + switchLogic(arr); + } + else { + monitor.info(`Dido: turnLine ${onOrOff} WRITE error`, err); + } + }); + + } + else if (ws) { + //pin = "relay1_03" or "input1_01" ... we must make just "1_01" with slice method + monitor.info(`Dido: turnLine ${onOrOff} - (line, pin, force)`, line, pin, force, info); + let cmd = { "cmd": "set", "dev": "relay", "circuit": pin.slice(5), "value": value }; + ws.send(JSON.stringify(cmd)); + } + + //if rvo is 24/7, it has just one switching profile point at 13:00. we do not want to send notification as it repeats every day. + //const d = new Date(); + //if(d.getHours() != 13) sendNotification("Dido_controller: ", SETTINGS.rvoTbName, "switching_profile_point_applied_to_line", { line: line, value: onOrOff }, "", SEND_TO.tb, instance); + } + + + // 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; + + // 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) { + const status = flowdata.data.status; + if (status == "NOK-twilight_sensor") { + deviceStatus["twilight_sensor"] = "NOK"; + } + else if (status == "NOK-em340" || status == "NOK-em111") { + deviceStatus["em"] = "NOK"; + } + else if (status == "NOK-thermometer") { + deviceStatus["temperature"] = "NOK"; + } + } + else if ("values" in flowdata.data) { + 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" + } + else if (values.hasOwnProperty("temperature")) { + deviceStatus["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"; + } + + sendTelemetry(values, rvoTbName); + } + + sendRvoStatus(); + }) + + + + + // we expect array as flowdata.data + instance.on("1", flowdata => { + + //console.log(flowdata.data); + + if (!flowdata.data instanceof Object) return; + + let obj = flowdata.data; + let line = obj.line; + 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"); + }) + + + function calculateStateCode() { + + let bits = []; + + //Hlavny istic - state_of_main_switch => v rvo senica je to druhy door pre silovu cast (EM) + if (deviceStatus["state_of_main_switch"] === "closed" || deviceStatus["state_of_main_switch"] === "Off") { + bits.push(0); + } + else { + bits.push(1); + } + + //Prevadzkovy mod - Manual, Off, Automatic, maintenance_mode = true/false // DAVA 2 BITY + if (!SETTINGS.maintenance_mode) { + if (deviceStatus["rotary_switch_state"] === "Manual") { + bits.push(0); + bits.push(1); + } + + if (deviceStatus["rotary_switch_state"] === "Automatic") { + bits.push(0); + bits.push(0); + } + + if (deviceStatus["rotary_switch_state"] === "Off") { + bits.push(1); + bits.push(0); + } + } + else { + bits.push(1); + bits.push(1); + } + + //Dverovy kontakt + if (deviceStatus["door_condition"] === "closed") { + bits.push(0); + } + else { + bits.push(1); + } + + //EM + if (deviceStatus["em"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //Teplomer + if (deviceStatus["temperature"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //Batéria + if (deviceStatus["battery"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //Zdroj + if (deviceStatus["power_supply"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //MN + if (deviceStatus["master_node"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //výpadok napätia na fáze + if (deviceStatus["no_voltage"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + if (deviceStatus["twilight_sensor"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + // doplnime do 16 bitov (2 byty) + for (let i = bits.length; i < 16; i++) { + bits.push(0); + } + + // console.log("calculateStateCode - deviceStatus", deviceStatus); + // 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; + } + + + async function sendRvoStatus() { + + if (SETTINGS === undefined) return; + SETTINGS.masterNodeIsResponding ? deviceStatus["master_node"] = "OK" : deviceStatus["master_node"] = "NOK"; + + 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 pinsForRvoStatus(controllerType, hasMainSwitch) { + + let pins = []; + + if (controllerType === "lm") { + pins = [1, 4, 6]; + if (hasMainSwitch === 1) { + pins = [4, 6]; + } + } else if (controllerType === "unipi") { + pins = ["input1_01", "input1_04", "input1_05"]; + if (hasMainSwitch === 1) { + pins = ["input1_01", "input1_04"]; + } + } + + return pins; + } + + + function checkRvoStatus() { + + // 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 + //set RVO state + let status = "OK"; + + for (const [key, value] of Object.entries(deviceStatus)) { + if (["em", "twilight_sensor", "temperature", "master_node"].includes(key) && value === "NOK") status = "NOK"; + } + + if (status === "OK") { + + let pinIndexes = pinsForRvoStatus(controller_type, hasMainSwitch); + + for (const pinIndex of pinIndexes) { + if (previousValues[pinIndex] === 0) { + if ((pinIndex === 6 || pinIndex === 'input1_01' || pinIndex === 'input1_05') && SETTINGS.maintenance_mode) continue; + status = "NOK"; + break; + } + } + } + + // battery status. If value is 1 - battery is NOK + if (previousValues[5] === 1) status = "NOK"; + if (SETTINGS.no_voltage.size > 0) status = "NOK"; + + // console.log("rvo status",status) + return status; + } + + + // we pass array to function in case of rsPort ==> switchLogic([55,3,0,1]) ==> [[55,3,0,1]] + // we pass two values in case of websocket ==> switchLogic("relay1_03",1) ==> ["relay1_03",1] + const switchLogic = (...args) => { + + let values = {}; + let pinIndex, newPinValue, twilight; + + //data from rsPort + if (args.length == 1) { + pinIndex = args[0][1] + 1; + if (pinIndex === 17) pinIndex--; + newPinValue = args[0][3]; + twilight = args[0][2]; + } + //data from websocket + else { + pinIndex = args[0]; + newPinValue = args[1]; + } + + 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; + + //default value + let value = "On"; + if (newPinValue === 0) value = "Off"; + + //Hlavny istic + if (type === "state_of_main_switch" && hasMainSwitch) { + if (newPinValue === 0 && newPinValue !== previousValues[pinIndex]) { + sendNotification("switchLogic", rvoTbName, "main_switch_has_been_turned_off", {}, "", SEND_TO.tb, instance, "state_of_main_switch"); + 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"); + deviceStatus["state_of_main_switch"] = "On"; + } + } + + //Prevadzkovy mod + 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"; + + deviceStatus["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, "power_supply_has_disconnected_input", {}, "", SEND_TO.tb, instance, "power_supply"); + + deviceStatus["power_supply"] = "NOK"; + } + else if (newPinValue === 1 && newPinValue !== previousValues[pinIndex]) { + sendNotification("switchLogic", rvoTbName, "power_supply_works_correctly", {}, "", SEND_TO.tb, instance, "power_supply"); + + deviceStatus["power_supply"] = "OK"; + } + } + + //Bateria - 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"); + + deviceStatus["battery"] = "NOK"; + } + else if (newPinValue === 0 && newPinValue !== previousValues[pinIndex]) { + sendNotification("switchLogic", rvoTbName, "battery_level_is_ok", {}, "", SEND_TO.tb, instance, "battery_level"); + + deviceStatus["battery"] = "OK"; + } + } + + //Dverovy kontakt - pin 6 + //! Ak je rvo s dvoma dverovymi kontaktami, ked pride z evoku signal z input1_05, co bol predytm "state_of_main switch" handlujeme ho teraz ako 'door_condition' + else if (type == "door_condition" || type === "state_of_main_switch") { + newPinValue === 0 ? value = "open" : value = "closed"; + + let door = "door_main"; + if (type === "state_of_main_switch") door = "door_em"; + + if (value === "open") { + if (SETTINGS.maintenance_mode) { + sendNotification("switchLogic", rvoTbName, door + "_open", {}, "", SEND_TO.tb, instance, door); + } else { + sendNotification("switchLogic", rvoTbName, door + "_open_without_permission", {}, "", SEND_TO.tb, instance, door); + + // 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 (value === "closed") { + if (alarmStatus == "ON") turnAlarm("off"); + sendNotification("switchLogic", rvoTbName, door + "_close", {}, "", SEND_TO.tb, instance, door); + } + + deviceStatus[type] = value; + } + + //lux sensor + else if (type == "twilight_sensor") { + //! TODO - to show nok status, if lux value is not changing more then 10 times. + //Daylight is far more than 1000. So most of the day, when it is sunshine comes just value 1000. But lux sensor is not NOK. + //This is not the case in LM. If value from LM is the same 10x, there is 99% possibility, that sensor is NOK. + value = newPinValue; + + if (controller_type === 'lm') { + value = parseFloat(newPinValue + (256 * twilight)); + + 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 && !twilightError) { + twilightError = true; + let value = twilight_sensor_array.shift(); + + newPinValue = 0; + } + else if (set.size !== 1 && twilightError) { + //sendNotification("switchLogic", rvoTbName, 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) { + 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); + } + } + + 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); + } + + deviceStatus["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 (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 }); + + //mame iba 3 istice. vyreportujeme a ohandlujeme liniu na tom istom istici ako paralelna linia (napr linia 1, paralelna s nou je linia 4, key je string "4") + // ak je 7 linii, na 1 istici je linia 1,4,7 + + if (line == 1) { + + const lineOnSameBraker = [4, 7]; + + for (var i = 0; i < lineOnSameBraker.length; i++) { + if (!relaysData.hasOwnProperty(lineOnSameBraker[i])) continue; + + 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; + reportLineStatus(lineOnSameBraker[i]); + + values[type] = value; + const tbname = relaysData[lineOnSameBraker[i]].tbname; + sendTelemetry(values, tbname); + + delete values[type]; + } + + } + else { + const lineOnSameBraker = line + 3 + ""; + + if (relaysData.hasOwnProperty(lineOnSameBraker)) { + 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; + reportLineStatus(line + 3); + + values[type] = value; + const tbname = relaysData[lineOnSameBraker].tbname; + sendTelemetry(values, tbname); + + delete values[type]; + } + } + + } + + if (value == "Off") values["status"] = "NOK"; + deviceStatus["state_of_breaker"][line] = value; + + reportLineStatus(line); + } + else return; + + values[type] = value; + + if (type == "rotary_switch_state") { + if (SETTINGS.maintenance_mode) value = "maintenance"; + value = value.toLowerCase(); + values["power_mode"] = value; + } + + if (newPinValue != previousValues[pinIndex]) previousValues[pinIndex] = newPinValue; + if (Object.keys(values).length > 0 && tbname) sendTelemetry(values, tbname); + } + + + function sendTelemetry(values, tbname, date = Date.now()) { + let dataToTb = { + [tbname]: [ + { + "ts": date, + "values": values + } + ] + }; + + tbHandler.sendToTb(dataToTb, instance); + } + + + function isObject(item) { + return (typeof item === "object" && !Array.isArray(item) && item !== null); + } + +} //end of 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 +// *|input1_01|state_of_main_switch|0|........... +// *|input1_02|rotary_switch_state|0|........... +// *|input1_03|rotary_switch_state|0|........... +// *|intut1_04|power_supply|0|........... +// *|input1_05|door_condition|0|........... +// *|input1_06|state_of_breaker|1|........... +// *|input1_07|state_of_breaker|2|........... +// *|input1_08|state_of_breaker|3|........... +// *|relay1_02|state_of_contactor|1|........... +// *|relay1_03|state_of_contactor|2|........... +// *|relay1_04|state_of_contactor|3|........... +// *|287D8776E0013CE9|temperature|0|........... + + +//! pins_data --> from UNIPI +// { +// 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 } +// } + +//! relays_data +// { +// '0': { +// line: 0, +// tbname: 'KjbN4q7JPZmexgdnz2yKQ98YAWwO0Q3BMX6ERLoV', +// contactor: 1, +// profile: '' +// }, +// '1': { +// line: 1, +// tbname: 'RMgnK93rkoAazbqdQ4yBG95Z1YXGx6pmwBeVEP2O', +// contactor: 0, +// profile: '{"intervals":[{"value":0,"end_time":"20:00","start_time":"13:00"},{"value":1,"end_time":"10:00","start_time":"20:00"},{"value":0,"end_time":"10:20","start_time":"10:00"},{"value":1,"end_time":"10:40","start_time":"10:20"},{"value":0,"end_time":"11:00","start_time":"10:40"},{"value":1,"end_time":"11:30","start_time":"11:00"},{"value":0,"end_time":"11:50","start_time":"11:30"},{"value":1,"end_time":"13:00","start_time":"11:50"}],"astro_clock":false,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' +// }, +// '2': { +// line: 2, +// tbname: 'dlE1VQjYrNx9gZRmb38gG08oLBO4qaAk2M6JPnG7', +// contactor: 0, +// profile: '{"intervals":[{"value":0,"end_time":"20:00","start_time":"13:00"},{"value":1,"end_time":"10:00","start_time":"20:00"},{"value":0,"end_time":"10:20","start_time":"10:00"},{"value":1,"end_time":"10:40","start_time":"10:20"},{"value":0,"end_time":"11:00","start_time":"10:40"},{"value":1,"end_time":"11:30","start_time":"11:00"},{"value":0,"end_time":"11:50","start_time":"11:30"},{"value":1,"end_time":"13:00","start_time":"11:50"}],"astro_clock":false,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' +// }, +// '3': { +// line: 3, +// tbname: 'vnmG4kJxaXWNBgMQq0D7Aj5e9oZzOAlr6LdR3w2V', +// contactor: 0, +// profile: '{"intervals":[{"value":0,"end_time":"20:30","start_time":"13:00"},{"value":1,"end_time":"00:10","start_time":"20:30"},{"value":0,"end_time":"13:00","start_time":"05:40"},{"value":1,"end_time":"05:40","start_time":"00:10"}],"astro_clock":true,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' +// } +// } + + + + + +// { +// "jbN4q7JPZmexgdnz2yKbWGDYAWwO0Q3BMX6ERLoV": [ +// { +// "ts": 1700409326353, +// "values": { +// "_event": { +// "type": "notice", +// "status": "new", +// "source": { +// "func": "rsPort.open()", +// "component": "1700343402190", +// "component_name": "DIDO_Controller", +// "edge": "jbN4q7JPZmexgdnz2yKbWGDYAWwO0Q3BMX6ERLoV" +// }, +// "message": "al_shariff_10.0.0.38: FLOW has been started ", +// "message_data": "" +// } +// } +// } +// ] +// } diff --git a/RVO13/flow/helper/DataToTbHandler.js b/RVO13/flow/helper/DataToTbHandler.js new file mode 100755 index 0000000..716ef7b --- /dev/null +++ b/RVO13/flow/helper/DataToTbHandler.js @@ -0,0 +1,187 @@ +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; + this.itIsNodeReadout = false; + this.sender = ""; + + // if attribute change difference is less than limit value, we do not send to tb. + this.attributeChangeLimit = { + temperature: 0.5, + Phase_1_voltage: 2, + Phase_2_voltage: 2, + Phase_3_voltage: 2, + Phase_1_current: 0.1, + Phase_2_current: 0.1, + Phase_3_current: 0.1, + Phase_1_power: 2, + Phase_2_power: 2, + Phase_3_power: 2, + total_power: 2, + total_energy: 1, + Phase_1_pow_factor: 0.1, + Phase_2_pow_factor: 0.1, + Phase_3_pow_factor: 0.1, + power_factor: 0.1, + lifetime: 2, + voltage: 2, + power: 2, + frequency: 3, + energy: 0.1, + current: 2, + inclination_x: 10, + inclination_y: 10, + inclination_z: 10 + }; + + } + + dump() { + console.log("----------------------------"); + console.log("previousValues", this.previousValues); + console.log("----------------------------"); + } + + setSender(sender) { + this.sender = sender; + } + + isEmptyObject(obj) { + for (var _ in obj) { + return false; + } + return true; + } + + + sendToTb(data, instance) { + + //not to modify data object, we do deep copy: + let dataCopy = JSON.parse(JSON.stringify(data)); + + let keys = Object.keys(dataCopy); + + if (keys.length == 0) { + if (this.debug) console.log("sendToTb received empty object", dataCopy); + return; + } + + let tbname = keys[0]; + let ts; + + let arrayOfValues = dataCopy[tbname]; + let arrayOfValuesToSend = []; + + for (let i = 0; i < arrayOfValues.length; i++) { + + ts = arrayOfValues[i].ts; + let values = this.prepareValuesForTb(tbname, ts, arrayOfValues[i].values); + + if (!this.isEmptyObject(values)) { + arrayOfValuesToSend.push({ ts: ts, values: values }); + } + + } + + if (arrayOfValuesToSend.length == 0) { + //if(this.debug) console.log("data not sent - empty array"); + return; + } + + this.messageCounter++; + + let dataToTbModified = { + [tbname]: arrayOfValuesToSend + } + + //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); + instance.send(this.index, dataToTbModified); + } + + + getDiffTimestamp(key) { + //TODO set different value for given key!!! + //if(key == "status") this.timeToHoldTbValue = 2*60*60;//2h + return this.timeToHoldTbValue * 1000; + } + + + prepareValuesForTb(tbname, timestamp, values) { + + let keys = Object.keys(values); + + if (keys.includes("lifetime")) this.itIsNodeReadout = true; + + if (!this.previousValues.hasOwnProperty(tbname)) { + this.previousValues[tbname] = {}; + } + + //if(this.debug) console.log("prepareValuesForTb", tbname, timestamp, values); + + for (let i = 0; i < keys.length; i++) { + + let key = keys[i]; + let value = values[key]; + + if (!this.previousValues[tbname].hasOwnProperty(key)) { + this.previousValues[tbname][key] = { ts: timestamp, value: value }; + continue; + } + + // attributeData ==> {voltage: {ts:333333, value:5}} + let attributeData = this.previousValues[tbname][key]; + let attributeToChange = false; + if (key in this.attributeChangeLimit) attributeToChange = true; + let limit = this.attributeChangeLimit[key]; + let timestampDiffToRemoveKey; + + //this will ensure "node statecode" will be sent just once an hour + if (this.itIsNodeReadout && key === "statecode") { + attributeData.value = value; + this.itIsNodeReadout = false; + timestampDiffToRemoveKey = 1 * 60 * 60 * 1000; // 1 hour + } + + if (key === "twilight_sensor" && value > 100) { + attributeData.value = value; + } + + //if edge, master or node version do not change, send just once a day: + if (["edge_fw_version", "master_node_version", "fw_version"].includes(key)) { + timestampDiffToRemoveKey = 24 * 60 * 60 * 1000; + } + + if (attributeData.value === value || attributeToChange && Math.abs(attributeData.value - value) < limit) { + + let diff = timestamp - attributeData.ts; + if (!timestampDiffToRemoveKey) timestampDiffToRemoveKey = this.getDiffTimestamp(key); + + if (diff > timestampDiffToRemoveKey) { + attributeData.ts = Date.now(); + //if(this.debug) console.log(this.sender + ": update ts for key", key, "diff is", diff, "messageCounter", this.messageCounter); + } + else { + delete values[key]; + //if(this.debug) console.log(this.sender + ": delete key", key, "diff is", diff, "messageCounter", this.messageCounter, timestampDiffToRemoveKey); + } + } + else { + attributeData.value = value; + attributeData.ts = timestamp; + } + + } + + return values; + } +} + +module.exports = DataToTbHandler; + diff --git a/RVO13/flow/helper/ErrorToServiceHandler.js b/RVO13/flow/helper/ErrorToServiceHandler.js new file mode 100755 index 0000000..2b27c32 --- /dev/null +++ b/RVO13/flow/helper/ErrorToServiceHandler.js @@ -0,0 +1,91 @@ +const { MD5 } = require('./md5.js'); +const { networkInterfaces } = require('os'); + +class ErrorToServiceHandler { + constructor() { + this.previousValues = {}; + + this.project_id = undefined; + + const nets = networkInterfaces(); + this.ipAddresses = {}; + + for (const name of Object.keys(nets)) { + for (const net of nets[name]) { + // Skip over non-IPv4 and internal (i.e. 127.0.0.1) addresses + if (net.family === 'IPv4' && !net.internal) { + if (!this.ipAddresses[name]) { + this.ipAddresses[name] = []; + } + this.ipAddresses[name].push(net.address); + } + } + } + } + + setProjectId(project_id) { + this.project_id = project_id; + } + + processMessage(message, seconds) { + if (Array.isArray(message)) message = message.join(', '); + + let key = MD5(message); + let ts = Date.now(); + + //keep in memory - default value is 1h + if (seconds === undefined) seconds = 60 * 60; + + if (!this.previousValues.hasOwnProperty(key)) { + this.previousValues[key] = { ts: ts, duration: seconds }; + } + + let diff = (ts - this.previousValues[key].ts); + if (diff < this.previousValues[key].duration * 1000) return false; + + this.previousValues[key].ts = ts; + + return message; + } + + sendMessageToService(message, seconds, message_type) { + + // if error occures too early FLOW.GLOBALS.settings.project_id is still undefined + if (this.project_id === undefined) { + console.log("ErrorToServiceHandler.js: no project_id"); + return; + } + + let f = this.processMessage(message, seconds); + if (f === false) return; + + if (message_type === undefined) message_type = "error_message"; + + let toService = { + id: this.project_id, + ipAddresses: this.ipAddresses + }; + + //js_error || error_message + toService[message_type] = message; + + console.log("ErrorToServiceHandler------------------------>send to service", toService); + + RESTBuilder.make(function(builder) { + builder.method('POST'); + builder.post(toService); + builder.url('http://192.168.252.2:8004/sentmessage'); + + builder.callback(function(err, response, output) { + console.log("process.on error send", err, response, output, toService); + }); + }); + + } +} + +const errorHandler = new ErrorToServiceHandler(); + + +module.exports = errorHandler; +//module.exports = ErrorToServiceHandler; diff --git a/RVO13/flow/helper/db_helper.js b/RVO13/flow/helper/db_helper.js new file mode 100755 index 0000000..40e796c --- /dev/null +++ b/RVO13/flow/helper/db_helper.js @@ -0,0 +1,44 @@ +function promisifyBuilder(builder) +{ + return new Promise((resolve, reject) => { + + try{ + + builder.callback(function(err, response) { + + if(err != null) reject(err); + resolve(response); + }); + + } catch (error) { + reject(error); + } + }) +} + +function makeMapFromDbResult(response, ...keys) +{ + let s = "-"; + let data = {}; + + for(let i = 0; i < response.length; i++) + { + let record = response[i]; + + let k = []; + for(let j = 0; j < keys.length; j++) + { + k.push( record[keys[j]] ); + } + + let key = k.join(s); + data[ key ] = record; + } + + return data; +} + +module.exports = { + promisifyBuilder, + makeMapFromDbResult + } \ No newline at end of file diff --git a/RVO13/flow/helper/logger.js b/RVO13/flow/helper/logger.js new file mode 100755 index 0000000..2585639 --- /dev/null +++ b/RVO13/flow/helper/logger.js @@ -0,0 +1,30 @@ +//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/RVO13/flow/helper/md5.js b/RVO13/flow/helper/md5.js new file mode 100755 index 0000000..d3b0480 --- /dev/null +++ b/RVO13/flow/helper/md5.js @@ -0,0 +1,5 @@ +function MD5(d){var r = M(V(Y(X(d),8*d.length)));return r.toLowerCase()};function M(d){for(var _,m="0123456789ABCDEF",f="",r=0;r>>4&15)+m.charAt(15&_);return f}function X(d){for(var _=Array(d.length>>2),m=0;m<_.length;m++)_[m]=0;for(m=0;m<8*d.length;m+=8)_[m>>5]|=(255&d.charCodeAt(m/8))<>5]>>>m%32&255);return _}function Y(d,_){d[_>>5]|=128<<_%32,d[14+(_+64>>>9<<4)]=_;for(var m=1732584193,f=-271733879,r=-1732584194,i=271733878,n=0;n>16)+(_>>16)+(m>>16)<<16|65535&m}function bit_rol(d,_){return d<<_|d>>>32-_} + +module.exports = { + MD5 +} \ No newline at end of file diff --git a/RVO13/flow/helper/notification_reporter.js b/RVO13/flow/helper/notification_reporter.js new file mode 100755 index 0000000..839c12c --- /dev/null +++ b/RVO13/flow/helper/notification_reporter.js @@ -0,0 +1,121 @@ +//key is device, value = message {} +let sentValues = {}; +let notificationsData = null; +let rvoName; + +//sendNotification("CMD Manager: process cmd", SETTINGS.rvoTbName, "dimming_profile_was_successfully_received_by_node", { node: node }, "", SEND_TO.tb, instance); + +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 +}; + +function getKey(map, val) { + return Object.keys(map).findItem(key => map[key] === val); +} + +//https://stackoverflow.com/questions/41117799/string-interpolation-on-variable +var template = (tpl, args) => tpl.replace(/\${(\w+)}/g, (_, v) => args[v]); + + +function initNotification() { + notificationsData = FLOW.GLOBALS.notificationsData; + rvoName = FLOW.GLOBALS.settings.rvo_name; +} + + +function sendNotification(func, device, key, params, extra, tb_output, instance, saveKey) { + + let storeToSendValues = true; + if (saveKey == undefined) storeToSendValues = false; + + let weight = ""; + let message = {}; + + let notification = notificationsData[key]; + + if (notification) { + weight = notification.weight.toLowerCase(); + + Object.keys(notification).forEach(item => { + if (["en", "sk", "de", "cz", "it", "es"].includes(item)) { + message[item] = rvoName + ": " + template(notification[item], params); + } + }) + } + else { + //console.error("sendNotification: Notifications: undefined key", key, func, notificationsData); + console.error("sendNotification: Notifications: undefined key", key, func); + return false; + } + + //detect invalid err weight + if (getKey(ERRWEIGHT, weight) == undefined) { + console.error("sendNotification: Notifications: undefined weight", weight, key, func); + return false; + } + + if (sentValues.hasOwnProperty(saveKey)) { + if (JSON.stringify(sentValues[saveKey]) == JSON.stringify(message)) { + return false; + } + } + + if (sentValues[saveKey] == undefined) { + if (storeToSendValues) { + //do not send - flow is was started + sentValues[saveKey] = message; + return false; + } + } + + if (storeToSendValues) sentValues[saveKey] = message; + + let content = { + "type": weight, + "status": "new", + "source": { + "func": func, + "component": instance.id, + "component_name": instance.name, + "edge": device + }, + "message": message, + "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 + + return true; + +} + +module.exports = { + sendNotification, + ERRWEIGHT, + initNotification +} + diff --git a/RVO13/flow/helper/register.js b/RVO13/flow/helper/register.js new file mode 100755 index 0000000..fc1d008 --- /dev/null +++ b/RVO13/flow/helper/register.js @@ -0,0 +1,144 @@ +/* +0 - cislo registra / prikaz +1 - recepient - 0 = master, 1 = slave (slave je automaticky group a broadcast) +2 - r/rw - read/write +3- register name - nazov registra / prikazu (len pre info - zobrazenie v aplikacii) + +4,5,6,7, - jednotlive byte-y - nazov byte-u +4-7 - RES. a prazdny string "" sa nezobrazia!!! +*/ + +//124 zaznamov +const registers = [ + ["0","1","R","Status","","",""], + ["1","1","RW","Dimming","R-Channel ","G-Channel","B-Channel ","W - Channel"], + ["2","1","R","Device types","","",".",""], + ["3","1","RW","Group addresses 1-4","Groups Add. 4","Groups Add. 3","Groups Add. 2","Groups Add. 1"], + ["4","1","RW","Group addresses 5-8","Groups Add. 8","Groups Add. 7","Groups Add. 6","Groups Add. 5"], + ["5","1","RW","Serial number (MAC)","","","",""], + ["6","1","RW","Time of dusk","HH","MM","SS","EXTRA"], + ["7","1","RW","Time of dawn","HH","MM","SS","EXTRA"], + ["8","1","RW","Time Schedule settings","TBD","TBD","Movement sensor","Time Schedule"], + ["9","1","RW","TS1 Time point 1","HH","MM","SS","Ext. Device"], + ["10","1","RW","TS1 Time point 1 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["11","1","RW","TS1 Time point 2","HH","MM","SS","Ext. Device"], + ["12","1","RW","TS1 Time point 2 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["13","1","RW","TS1 Time point 3","HH","MM","SS","Ext. Device"], + ["14","1","RW","TS1 Time point 3 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["15","1","RW","TS1 Time point 4","HH","MM","SS","Ext. Device"], + ["16","1","RW","TS1 Time point 4 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["17","1","RW","TS1 Time point 5","HH","MM","SS","Ext. Device"], + ["18","1","RW","TS1 Time point 5 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["19","1","RW","TS1 Time point 6","HH","MM","SS","Ext. Device"], + ["20","1","RW","TS1 Time point 6 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["21","1","RW","TS1 Time point 7","HH","MM","SS","Ext. Device"], + ["22","1","RW","TS1 Time point 7 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["23","1","RW","TS1 Time point 8","HH","MM","SS","Ext. Device"], + ["24","1","RW","TS1 Time point 8 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["25","1","RW","TS1 Time point 9","HH","MM","SS","Ext. Device"], + ["26","1","RW","TS1 Time point 9 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["27","1","RW","TS1 Time point 10","HH","MM","SS","Ext. Device"], + ["28","1","RW","TS1 Time point 10 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["29","1","RW","TS1 Time point 11","HH","MM","SS","Ext. Device"], + ["30","1","RW","TS1 Time point 11 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["31","1","RW","TS1 Time point 12","HH","MM","SS","Ext. Device"], + ["32","1","RW","TS1 Time point 12 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["33","1","RW","TS1 Time point 13","HH","MM","SS","Ext. Device"], + ["34","1","RW","TS1 Time point 13 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["35","1","RW","TS1 Time point 14","HH","MM","SS","Ext. Device"], + ["36","1","RW","TS1 Time point 14 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["37","1","RW","TS1 Time point 15","HH","MM","SS","Ext. Device"], + ["38","1","RW","TS1 Time point 15 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["39","1","RW","TS1 Time point 16","HH","MM","SS","Ext. Device"], + ["40","1","RW","TS1 Time point 16 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["41","1","RW","TS2 Time point 1","HH","MM","SS","Ext. Device"], + ["42","1","RW","TS2 Time point 1 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["43","1","RW","TS2 Time point 2","HH","MM","SS","Ext. Device"], + ["44","1","RW","TS2 Time point 2 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["45","1","RW","TS2 Time point 3","HH","MM","SS","Ext. Device"], + ["46","1","RW","TS2 Time point 3 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["47","1","RW","TS2 Time point 4","HH","MM","SS","Ext. Device"], + ["48","1","RW","TS2 Time point 4 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["49","1","RW","TS2 Time point 5","HH","MM","SS","Ext. Device"], + ["50","1","RW","TS2 Time point 5 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["51","1","RW","TS2 Time point 6","HH","MM","SS","Ext. Device"], + ["52","1","RW","TS2 Time point 6 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["53","1","RW","TS2 Time point 7","HH","MM","SS","Ext. Device"], + ["54","1","RW","TS2 Time point 7 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["55","1","RW","TS2 Time point 8","HH","MM","SS","Ext. Device"], + ["56","1","RW","TS2 Time point 8 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["57","1","RW","TS2 Time point 9","HH","MM","SS","Ext. Device"], + ["58","1","RW","TS2 Time point 9 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["59","1","RW","TS2 Time point 10","HH","MM","SS","Ext. Device"], + ["60","1","RW","TS2 Time point 10 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["61","1","RW","TS2 Time point 11","HH","MM","SS","Ext. Device"], + ["62","1","RW","TS2 Time point 11 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["63","1","RW","TS2 Time point 12","HH","MM","SS","Ext. Device"], + ["64","1","RW","TS2 Time point 12 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["65","1","RW","TS2 Time point 13","HH","MM","SS","Ext. Device"], + ["66","1","RW","TS2 Time point 13 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["67","1","RW","TS2 Time point 14","HH","MM","SS","Ext. Device"], + ["68","1","RW","TS2 Time point 14 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["69","1","RW","TS2 Time point 15","HH","MM","SS","Ext. Device"], + ["70","1","RW","TS2 Time point 15 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["71","1","RW","TS2 Time point 16","HH","MM","SS","Ext. Device"], + ["72","1","RW","TS2 Time point 16 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["73","1","RW","Power meter status","TBD","","",""], + ["74","1","R","Input Voltage","","","",""], + ["75","1","R","Input Current","","","",""], + ["76","1","R","Input Power","","","",""], + ["77","1","R","Cos phi","","","",""], + ["78","1","R","Frequency","","","",""], + ["79","1","RW","Energy","","","",""], + ["80","1","RW","Lifetime","","","",""], + ["81","1","RW","Power on cycles (input)","","","",""], + ["82","1","RW","Power on cycles (relay)","","","",""], + ["83","1","R","Time since last power on","","","",""], + ["84","1","R","Accelerometer data","","","",""], + ["85","1","RW","GPS latitude","pos/neg","deg","min ","sec"], + ["86","1","RW","GPS longitude","pos/neg","deg","min ","sec"], + ["87","1","RW","Actual time","HH","MM","SS","RES."], + ["88","1","RW","Actual date","Day of week","Day","Month","Year"], + ["89","1","R","Production data 1","","","",""], + ["90","1","R","Production data 2","","","",""], + ["91","1","RW","Network ID","NID3","NID2","NID1","NID0"], + ["95","1","RW","Actual Lux level from cabinet","RES.","RES.","HB","LB"], + ["96","1","RW","Threshold lux level","Dusk HB","Dusk LB","Dawn HB","Dawn LB"], + ["97","1","RW","Adjust period","Dusk HB","Dusk LB","Dawn HB","Dawn LB"], + ["98","1","RW","Offset","RES.","RES.","Dusk","Dawn"], + ["99","1","RW","CCT min/max range","max-H","max-L","min-H","min-L"], + ["100","1","RW","DALI interface","Cmd ID","Add","Cmd","Resp"], + ["101","1","RW","Module FW ver","v1","v2","v3","v4"], + ["102","1","RW","Module MAC-H","unused","unused","M1","M2"], + ["103","1","RW","Module MAC-L","M3","M4","M5","M6"], + ["122","1","R","FW update status/control register","Byte3","Byte2","Byte1","Byte0"], + ["123","1","R","FW update - data index","Byte3","Byte2","Byte1","Byte0"], + ["124","1","R","FW update - data","Byte3","Byte2","Byte1","Byte0"], + ["0","0","R","Status","","","",""], + ["1","0","RW","Control register","RES.","RES.","RES.","init mode enable"], + ["2","0","R","Device types","","","",""], + ["3","0","R","Serial number (MAC)","","","",""], + ["4","0","R","Production data 1","","","",""], + ["5","0","R","Production data 2","","","",""], + ["6","0","RW","Network ID","NID3","NID2","NID1","NID0"], + ["7","0","RW","RS232 settings","param.","param.","Baudrate H","Baudrate L"], + ["8","0","R","Accelerometer data","","","",""], + ["9","0","RW","Module FW ver","v1","v2","v3","v4"], + ["10","0","RW","Module MAC-H","unused","unused","M1","M2"], + ["11","0","RW","Module MAC-L","M3","M4","M5","M6"], + ["32","0","RW","FW update status/control register","Byte3","Byte2","Byte1","Byte0"], + ["33","0","RW","FW update - data index","Byte3","Byte2","Byte1","Byte0"], + ["34","0","RW","FW update - data","Byte3","Byte2","Byte1","Byte0"], + ["125","0","RW","Debug Register","Byte3","Byte2","Byte1","Byte0"], + ["126","0","RW","Network Control Register","Byte3","Byte2","Byte1","Byte0"], + ["127","0","R","Network Status Register","Byte3","Byte2","Byte1","Byte0"], + ["128","0","RW","Node XX Serial Number Register","SER3","SER2","SER1","SER0"], + ["256","0","R","Node XX Network Status Register","","","",""] +]; + +let register = {}; + +module.exports = { + registers, + register +} \ No newline at end of file diff --git a/RVO13/flow/helper/serialport_helper.js b/RVO13/flow/helper/serialport_helper.js new file mode 100755 index 0000000..7f5920d --- /dev/null +++ b/RVO13/flow/helper/serialport_helper.js @@ -0,0 +1,99 @@ +const { exec } = require('child_process'); + +function openPort(port) { + return new Promise((resolve, reject) => { + + var callbackError = function(err) { + port.removeListener('error', callbackError); + port.removeListener('open', callbackError); + + reject(err.message); + }; + + var callbackOpen = function(data) { + port.removeListener('error', callbackError); + port.removeListener('open', callbackOpen); + + resolve("port open: ok"); + }; + + port.on('error', callbackError); + port.on('open', callbackOpen); + + port.open(); + + }) +} + +function runSyncExec(command) { + return new Promise((resolve, reject) => { + + exec(command, (error, stdout, stderr) => { + if (error == null) resolve(stdout); + reject(error); + }); + + }) +} + +async function writeData(port, data, readbytes, timeout) { + return new Promise((resolve, reject) => { + + // 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) { + + port.write(Buffer.from(data), function(err) { + if (err) { + reject(err.message); + } + }); + + 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 +} diff --git a/RVO13/flow/helper/suncalc.js b/RVO13/flow/helper/suncalc.js new file mode 100755 index 0000000..c9ca56d --- /dev/null +++ b/RVO13/flow/helper/suncalc.js @@ -0,0 +1,317 @@ +/* + (c) 2011-2015, Vladimir Agafonkin + SunCalc is a JavaScript library for calculating sun/moon position and light phases. + https://github.com/mourner/suncalc +*/ + +(function () { 'use strict'; + +// shortcuts for easier to read formulas + +var PI = Math.PI, + sin = Math.sin, + cos = Math.cos, + tan = Math.tan, + asin = Math.asin, + atan = Math.atan2, + acos = Math.acos, + rad = PI / 180; + +// sun calculations are based on http://aa.quae.nl/en/reken/zonpositie.html formulas + + +// date/time constants and conversions + +var dayMs = 1000 * 60 * 60 * 24, + J1970 = 2440588, + J2000 = 2451545; + +function toJulian(date) { return date.valueOf() / dayMs - 0.5 + J1970; } +function fromJulian(j) { return new Date((j + 0.5 - J1970) * dayMs); } +function toDays(date) { return toJulian(date) - J2000; } + + +// general calculations for position + +var e = rad * 23.4397; // obliquity of the Earth + +function rightAscension(l, b) { return atan(sin(l) * cos(e) - tan(b) * sin(e), cos(l)); } +function declination(l, b) { return asin(sin(b) * cos(e) + cos(b) * sin(e) * sin(l)); } + +function azimuth(H, phi, dec) { return atan(sin(H), cos(H) * sin(phi) - tan(dec) * cos(phi)); } +function altitude(H, phi, dec) { return asin(sin(phi) * sin(dec) + cos(phi) * cos(dec) * cos(H)); } + +function siderealTime(d, lw) { return rad * (280.16 + 360.9856235 * d) - lw; } + +function astroRefraction(h) { + if (h < 0) // the following formula works for positive altitudes only. + h = 0; // if h = -0.08901179 a div/0 would occur. + + // formula 16.4 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + // 1.02 / tan(h + 10.26 / (h + 5.10)) h in degrees, result in arc minutes -> converted to rad: + return 0.0002967 / Math.tan(h + 0.00312536 / (h + 0.08901179)); +} + +// general sun calculations + +function solarMeanAnomaly(d) { return rad * (357.5291 + 0.98560028 * d); } + +function eclipticLongitude(M) { + + var C = rad * (1.9148 * sin(M) + 0.02 * sin(2 * M) + 0.0003 * sin(3 * M)), // equation of center + P = rad * 102.9372; // perihelion of the Earth + + return M + C + P + PI; +} + +function sunCoords(d) { + + var M = solarMeanAnomaly(d), + L = eclipticLongitude(M); + + return { + dec: declination(L, 0), + ra: rightAscension(L, 0) + }; +} + + +var SunCalc = {}; + + +// calculates sun position for a given date and latitude/longitude + +SunCalc.getPosition = function (date, lat, lng) { + + var lw = rad * -lng, + phi = rad * lat, + d = toDays(date), + + c = sunCoords(d), + H = siderealTime(d, lw) - c.ra; + + return { + azimuth: azimuth(H, phi, c.dec), + altitude: altitude(H, phi, c.dec) + }; +}; + + +// sun times configuration (angle, morning name, evening name) + +var times = SunCalc.times = [ + [-0.833, 'sunrise', 'sunset' ], + [ -0.3, 'sunriseEnd', 'sunsetStart' ], + [ -6, 'dawn', 'dusk' ], + [ -12, 'nauticalDawn', 'nauticalDusk'], + [ -18, 'nightEnd', 'night' ], + [ 6, 'goldenHourEnd', 'goldenHour' ] +]; + +// adds a custom time to the times config + +SunCalc.addTime = function (angle, riseName, setName) { + times.push([angle, riseName, setName]); +}; + + +// calculations for sun times + +var J0 = 0.0009; + +function julianCycle(d, lw) { return Math.round(d - J0 - lw / (2 * PI)); } + +function approxTransit(Ht, lw, n) { return J0 + (Ht + lw) / (2 * PI) + n; } +function solarTransitJ(ds, M, L) { return J2000 + ds + 0.0053 * sin(M) - 0.0069 * sin(2 * L); } + +function hourAngle(h, phi, d) { return acos((sin(h) - sin(phi) * sin(d)) / (cos(phi) * cos(d))); } +function observerAngle(height) { return -2.076 * Math.sqrt(height) / 60; } + +// returns set time for the given sun altitude +function getSetJ(h, lw, phi, dec, n, M, L) { + + var w = hourAngle(h, phi, dec), + a = approxTransit(w, lw, n); + return solarTransitJ(a, M, L); +} + + +// calculates sun times for a given date, latitude/longitude, and, optionally, +// the observer height (in meters) relative to the horizon + +SunCalc.getTimes = function (date, lat, lng, height) { + + height = height || 0; + + var lw = rad * -lng, + phi = rad * lat, + + dh = observerAngle(height), + + d = toDays(date), + n = julianCycle(d, lw), + ds = approxTransit(0, lw, n), + + M = solarMeanAnomaly(ds), + L = eclipticLongitude(M), + dec = declination(L, 0), + + Jnoon = solarTransitJ(ds, M, L), + + i, len, time, h0, Jset, Jrise; + + + var result = { + solarNoon: fromJulian(Jnoon), + nadir: fromJulian(Jnoon - 0.5) + }; + + for (i = 0, len = times.length; i < len; i += 1) { + time = times[i]; + h0 = (time[0] + dh) * rad; + + Jset = getSetJ(h0, lw, phi, dec, n, M, L); + Jrise = Jnoon - (Jset - Jnoon); + + result[time[1]] = fromJulian(Jrise); + result[time[2]] = fromJulian(Jset); + } + + return result; +}; + + +// moon calculations, based on http://aa.quae.nl/en/reken/hemelpositie.html formulas + +function moonCoords(d) { // geocentric ecliptic coordinates of the moon + + var L = rad * (218.316 + 13.176396 * d), // ecliptic longitude + M = rad * (134.963 + 13.064993 * d), // mean anomaly + F = rad * (93.272 + 13.229350 * d), // mean distance + + l = L + rad * 6.289 * sin(M), // longitude + b = rad * 5.128 * sin(F), // latitude + dt = 385001 - 20905 * cos(M); // distance to the moon in km + + return { + ra: rightAscension(l, b), + dec: declination(l, b), + dist: dt + }; +} + +SunCalc.getMoonPosition = function (date, lat, lng) { + + var lw = rad * -lng, + phi = rad * lat, + d = toDays(date), + + c = moonCoords(d), + H = siderealTime(d, lw) - c.ra, + h = altitude(H, phi, c.dec), + // formula 14.1 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + pa = atan(sin(H), tan(phi) * cos(c.dec) - sin(c.dec) * cos(H)); + + h = h + astroRefraction(h); // altitude correction for refraction + + return { + azimuth: azimuth(H, phi, c.dec), + altitude: h, + distance: c.dist, + parallacticAngle: pa + }; +}; + + +// calculations for illumination parameters of the moon, +// based on http://idlastro.gsfc.nasa.gov/ftp/pro/astro/mphase.pro formulas and +// Chapter 48 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + +SunCalc.getMoonIllumination = function (date) { + + var d = toDays(date || new Date()), + s = sunCoords(d), + m = moonCoords(d), + + sdist = 149598000, // distance from Earth to Sun in km + + phi = acos(sin(s.dec) * sin(m.dec) + cos(s.dec) * cos(m.dec) * cos(s.ra - m.ra)), + inc = atan(sdist * sin(phi), m.dist - sdist * cos(phi)), + angle = atan(cos(s.dec) * sin(s.ra - m.ra), sin(s.dec) * cos(m.dec) - + cos(s.dec) * sin(m.dec) * cos(s.ra - m.ra)); + + return { + fraction: (1 + cos(inc)) / 2, + phase: 0.5 + 0.5 * inc * (angle < 0 ? -1 : 1) / Math.PI, + angle: angle + }; +}; + + +function hoursLater(date, h) { + return new Date(date.valueOf() + h * dayMs / 24); +} + +// calculations for moon rise/set times are based on http://www.stargazing.net/kepler/moonrise.html article + +SunCalc.getMoonTimes = function (date, lat, lng, inUTC) { + var t = new Date(date); + if (inUTC) t.setUTCHours(0, 0, 0, 0); + else t.setHours(0, 0, 0, 0); + + var hc = 0.133 * rad, + h0 = SunCalc.getMoonPosition(t, lat, lng).altitude - hc, + h1, h2, rise, set, a, b, xe, ye, d, roots, x1, x2, dx; + + // go in 2-hour chunks, each time seeing if a 3-point quadratic curve crosses zero (which means rise or set) + for (var i = 1; i <= 24; i += 2) { + h1 = SunCalc.getMoonPosition(hoursLater(t, i), lat, lng).altitude - hc; + h2 = SunCalc.getMoonPosition(hoursLater(t, i + 1), lat, lng).altitude - hc; + + a = (h0 + h2) / 2 - h1; + b = (h2 - h0) / 2; + xe = -b / (2 * a); + ye = (a * xe + b) * xe + h1; + d = b * b - 4 * a * h1; + roots = 0; + + if (d >= 0) { + dx = Math.sqrt(d) / (Math.abs(a) * 2); + x1 = xe - dx; + x2 = xe + dx; + if (Math.abs(x1) <= 1) roots++; + if (Math.abs(x2) <= 1) roots++; + if (x1 < -1) x1 = x2; + } + + if (roots === 1) { + if (h0 < 0) rise = i + x1; + else set = i + x1; + + } else if (roots === 2) { + rise = i + (ye < 0 ? x2 : x1); + set = i + (ye < 0 ? x1 : x2); + } + + if (rise && set) break; + + h0 = h2; + } + + var result = {}; + + if (rise) result.rise = hoursLater(t, rise); + if (set) result.set = hoursLater(t, set); + + if (!rise && !set) result[ye > 0 ? 'alwaysUp' : 'alwaysDown'] = true; + + return result; +}; + + +// export as Node module / AMD module / browser variable +if (typeof exports === 'object' && typeof module !== 'undefined') module.exports = SunCalc; +else if (typeof define === 'function' && define.amd) define(SunCalc); +else window.SunCalc = SunCalc; + +}()); diff --git a/RVO13/flow/helper/utils.js b/RVO13/flow/helper/utils.js new file mode 100755 index 0000000..dbffe45 --- /dev/null +++ b/RVO13/flow/helper/utils.js @@ -0,0 +1,161 @@ +const fs = require('fs').promises; + +function bytesToInt(bytes, numberOfBytes) { + let buffer = []; + if (Array.isArray(bytes)) { + buffer = bytes.slice(0); + if (numberOfBytes != undefined) { + buffer = bytes.slice(bytes.length - numberOfBytes); + } + } + else buffer.push(bytes); + + let result = 0; + for (let i = 0; i < buffer.length; i++) { + result = (result << 8) | buffer[i]; + } + + return result >>> 0; //ensure it's an unsigned 32-bit number +} + +function resizeArray(arr, newSize, defaultValue) { + while (newSize > arr.length) + arr.push(defaultValue); + arr.length = newSize; +} + +longToByteArray = function(/*long*/long) { + // we want to represent the input as a 8-bytes array + var byteArray = [0, 0, 0, 0, 0, 0, 0, 0]; + + for (var index = 0; index < byteArray.length; index++) { + var byte = long & 0xff; + byteArray[index] = byte; + long = (long - byte) / 256; + } + + return byteArray; +}; + +function addDays(date, days) { + var result = new Date(date); + result.setDate(result.getDate() + days); + return result; +} + +/* +sleep(2000).then(() => { + // Do something after the sleep! + + +}); +*/ + +function sleep(time) { + return new Promise((resolve) => setTimeout(resolve, time)); +} + +function isEmptyObject(obj) { + for (var name in obj) { + return false; + } + return true; +} + +function emptyJsObject(jsObject) { + Object.keys(jsObject).forEach(key => delete jsObject[key]); +} + +function convertUTCDateToLocalDate(date) { + var newDate = new Date(date); + newDate.setMinutes(date.getMinutes() + date.getTimezoneOffset()); + return newDate; +} + +function addZeroBefore(n) { + return (n < 10 ? '0' : '') + n; +} + + +/** + * Asynchronously writes data to a file. + * + * @param {string} filePath The path to the file. + * @param {string} data The data to write to the file. + * @param {boolean} [append=false] If true, appends the data to the file. If false, it overwrites the file. + */ +async function writeToFile(filePath, data, append = false) { + if (typeof data !== 'string') data = JSON.stringify(data, null, 2); + try { + if (append) { + // Append the data to the end of the file. This is the simplest way to append. + await fs.appendFile(filePath, data, 'utf8'); + console.log(`Successfully appended data to ${filePath} using fs.appendFile.`); + } else { + // Overwrite the file with the new data. + await fs.writeFile(filePath, data, 'utf8'); + console.log(`Successfully wrote (overwrote) data to ${filePath} using fs.writeFile.`); + } + } catch (error) { + console.error(`Error writing to file ${filePath}:`, error); + } +} + + + /** + * Checks if an item is present in an array and adds it if it's not. + * * @param {Array} arr The array to check. + * @param {*} item The item to add. + * @returns {Array} The modified array. + */ +const addToArrayIfUnique = (arr, item) => { + if (!arr.includes(item)) { + arr.push(item); + } + return arr; +}; + + +var convertBase = function() { + + function convertBase(baseFrom, baseTo) { + return function(num) { + return parseInt(num, baseFrom).toString(baseTo); + + }; + } + + // binary to decimal + convertBase.bin2dec = convertBase(2, 10); + + // binary to hexadecimal + convertBase.bin2hex = convertBase(2, 16); + + // decimal to binary + convertBase.dec2bin = convertBase(10, 2); + + // decimal to hexadecimal + convertBase.dec2hex = convertBase(10, 16); + + // hexadecimal to binary + convertBase.hex2bin = convertBase(16, 2); + + // hexadecimal to decimal + convertBase.hex2dec = convertBase(16, 10); + + return convertBase; +}(); + +module.exports = { + bytesToInt, + longToByteArray, + addDays, + addZeroBefore, + resizeArray, + isEmptyObject, + emptyJsObject, + sleep, + convertUTCDateToLocalDate, + writeToFile, + addToArrayIfUnique +} diff --git a/RVO13/flow/httprequest.js b/RVO13/flow/httprequest.js new file mode 100755 index 0000000..469c8cb --- /dev/null +++ b/RVO13/flow/httprequest.js @@ -0,0 +1,137 @@ +exports.id = 'httprequest'; +exports.title = 'HTTP Request'; +exports.group = 'HTTP'; +exports.color = '#5D9CEC'; +exports.input = true; +exports.version = '2.0.1'; +exports.output = 1; +exports.author = 'Peter Širka'; +exports.icon = 'cloud-upload'; + +exports.html = `
+
@(URL address)
+
+
+
@(HTTP method)
+
+
+
@(Serialization)
+
+
+
@(Download the content in chunks)
+
@(Keep persistent cookies)
+
@(Disable DNS cache)
+
@(Keep alive connection)
+
+
+
+
@(Custom headers)
+
@(Cookies)
+
+
+
+ +
+
+
+
@(User)
+
+
+
@(Password)
+
+
+
+
+
`; + +exports.readme = `# Request + +This component creates a request with received data. + +__Response:__ +\`\`\`javascript +{ + data: String, + headers: Object, + status: Number, + host: String +} +\`\`\` + +__Dynamic arguments__: +Are performed via FlowData repository and can be used for URL address or for custom headers/cookies/auth. Use \`repository\` component for creating of dynamic arguments. Dynamic values are replaced in the form \`{key}\`: + +- url address e.g. \`https://.../{key}/\` +- headers values e.g. \`{token}\` +- cookies values e.g. \`{token}\``; + +exports.install = function(instance) { + + var can = false; + var flags = null; + var cookies2 = null; + + instance.on('data', function(response) { + can && instance.custom.send(response); + }); + + instance.custom.send = function(response) { + var options = instance.options; + + var headers = null; + var cookies = null; + + options.headers && Object.keys(options.headers).forEach(function(key) { + !headers && (headers = {}); + headers[key] = response.arg(options.headers[key]); + }); + + if (options.username && options.userpassword) { + !headers && (headers = {}); + headers['Authorization'] = 'Basic ' + U.createBuffer(response.arg(options.username + ':' + options.userpassword)).toString('base64'); + } + + options.cookies && Object.keys(options.cookies).forEach(function(key) { + !cookies && (cookies = {}); + cookies[key] = response.arg(options.cookies[key]); + }); + + if (options.chunks) { + U.download(response.arg(options.url), flags, options.stringify === 'none' ? null : response.data, function(err, response) { + response.on('data', (chunks) => instance.send2(chunks)); + }, cookies || cookies2, headers); + } else { + U.request(response.arg(options.url), flags, options.stringify === 'none' ? null : response.data, 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) + instance.error(err, response); + }, cookies || cookies2, headers); + } + }; + + instance.reconfigure = function() { + var options = instance.options; + can = options.url && options.url && options.method && options.stringify ? true : false; + instance.status(can ? '' : 'Not configured', can ? undefined : 'red'); + + if (!can) + return; + + flags = []; + flags.push(options.method.toLowerCase()); + options.stringify === 'json' && flags.push('json'); + options.stringify === 'raw' && flags.push('raw'); + options.keepalive && flags.push('keepalive'); + !options.nodns && flags.push('dnscache'); + if (options.persistentcookies) { + flags.push('cookies'); + cookies2 = {}; + } else + cookies2 = null; + }; + + instance.on('options', instance.reconfigure); + instance.reconfigure(); +}; \ No newline at end of file diff --git a/RVO13/flow/httpresponse.js b/RVO13/flow/httpresponse.js new file mode 100755 index 0000000..160a3bb --- /dev/null +++ b/RVO13/flow/httpresponse.js @@ -0,0 +1,76 @@ +exports.id = 'httpresponse'; +exports.title = 'HTTP Response'; +exports.group = 'HTTP'; +exports.color = '#5D9CEC'; +exports.icon = 'arrow-right'; +exports.input = true; +exports.output = ['#666D76']; +exports.version = '2.0.0'; +exports.author = 'Martin Smola'; +exports.readme = `# HTTP response + +HTTP response will respond with data recieved using data-type set in Settings form or plain text if not set. Output is the message duration \`Number\` in seconds.`; + +exports.html = `
+
@(Response data-type)
+
JSON is by default.
+
`; + +exports.install = function(instance) { + + var dursum = 0; + var durcount = 0; + + instance.on('data', function(flowdata) { + + var ctrl = flowdata.repository.controller; + var data = flowdata.data; + + if (!ctrl) { + instance.throw('No controller to use for response!'); + return; + } + + durcount++; + dursum += ((new Date() - flowdata.begin) / 1000).floor(2); + setTimeout2(instance.id, instance.custom.duration, 500, 10); + + ctrl.$flowdata = flowdata; + + var datatype = instance.options.datatype || 'json'; + if (datatype === 'emptyresponse') + return ctrl.plain(''); + + if (datatype !== 'json' && typeof(data) !== 'string') { + instance.throw('Incorect type of data, expected string, got ' + typeof(data)); + ctrl.plain(data == null ? '' : data.toString()); + return; + } + + switch(datatype) { + case 'html': + ctrl.content(data, 'text/html'); + break; + case 'plain': + ctrl.plain(data); + break; + case 'xml': + ctrl.content(data, 'text/xml'); + break; + default: + ctrl.json(data); + break; + } + }); + + instance.on('service', function() { + dursum = 0; + durcount = 0; + }); + + instance.custom.duration = function() { + var avg = (dursum / durcount).floor(2); + instance.status(avg + ' sec.'); + instance.send2(0, avg); + }; +}; diff --git a/RVO13/flow/httproute.js b/RVO13/flow/httproute.js new file mode 100755 index 0000000..583a19d --- /dev/null +++ b/RVO13/flow/httproute.js @@ -0,0 +1,326 @@ +exports.id = 'httproute'; +exports.title = 'HTTP Route'; +exports.group = 'HTTP'; +exports.color = '#5D9CEC'; +exports.icon = 'globe'; +exports.input = false; +exports.output = ['#6CAC5A', '#37BC9B']; +exports.version = '1.2.3'; +exports.author = 'Martin Smola'; +exports.cloning = false; +exports.options = { method: 'GET', url: '', size: 5, cacheexpire: '5 minutes', cachepolicy: 0, timeout: 5 }; +exports.dateupdated = '2021-01-21 18:30d'; +exports.readme = `# HTTP route + +__Outputs__: +- first output: raw data (cache is empty or is disabled) +- second output: cached data + +If one of the outputs is disabled then automatic responce with code "503 service unavailable" is sent. + +When a request comes in bellow object is available at \`flowdata.data\`: + +\`\`\`javascript +{ + params: { id: '1' }, // params for dynamic routes, e.g. /test/{id} + query: { msg: 'Hello' }, // parsed query string, e.g. /test/1?msg=Hello + body: { test: 'OK' }, // object if json requests otherwise string + headers: {}, // headers data + session: {}, // session data + user: {}, // user data + files: [], // uploaded files + url: '/users/', // a relative URL address + referrer: '/', // referrer + mobile: false, // determines mobile device + robot: false, // determines search robots/crawlsers + language: 'en' // determines language +} +\`\`\` + +See [documentation for flags](https://docs.totaljs.com/latest/en.html#api~HttpRouteOptionsFlags~unauthorize). These method flags are set automatically e.g. \`get, post, put, patch or delete\` + +--- + +\`id:ROUTE_ID\` flag cannot be used since it's already used by this component internally`; + +exports.html = `
+
+ +
+ +
+
+
@(HTTP method)
+
+
+
@(URL address)
+
+
+
+
+
@(Additional flags)
+
@(Separate flags by comma e.g. json, authorize)
+
+
+
@(Max. request size)
+
@(In kB kilobytes)
+
+
+
@(Timeout)
+
@(In seconds.)
+
+
+
+
+
+
@(Automatically respond with 200 OK?)
+
@(If not checked you need to use HTTP response component to respond to the request.)
+
+
@(Custom headers)
+
@(Cookies)
+
+
+
+
+
+
@(Cache policy)
+
@(User instance must contain id property.)
+
+
+
@(Expiration)
+
@(E.g. 5 minutes)
+
+
+
+`; + +exports.install = function(instance) { + + var route; + + var uninstall = function(id) { + if (F.is4) { + route && route.remove(); + route = null; + } else + UNINSTALL('route', id); + }; + + instance.custom.emptyresponse = function(self) { + self.plain(); + }; + + instance.reconfigure = function() { + + var options = instance.options; + + if (!options.url) { + instance.status('Not configured', 'red'); + return; + } + + if (typeof(options.flags) === 'string') + options.flags = options.flags.split(',').trim(); + + uninstall('id:' + instance.id); + + var flags = options.flags || []; + + flags.push('id:' + instance.id); + + if (!F.is4) + flags.push(options.method.toLowerCase()); + + options.timeout && flags.push(options.timeout * 1000); + + // Make unique values + flags = flags.filter(function(v, i, a) { + if(F.is4 && v.toString().toLowerCase() === options.method.toLowerCase()) + return false; // remove method + return a.indexOf(v) === i; + }); + + options.flags = flags; + var handler = function() { + + if (instance.paused || (instance.isDisabled && (instance.isDisabled('output', 0) || instance.isDisabled('output', 1)))) { + instance.status('503 Service Unavailable'); + this.status = 503; + this.json(); + return; + } + + var key; + var self = this; + + if (instance.options.emptyresponse) { + instance.status('200 OK'); + setTimeout(instance.custom.emptyresponse, 100, self); + + if (instance.hasConnection(0)) { + var data = instance.make({ + query: self.query, + body: self.body, + session: self.session, + user: self.user, + files: self.files, + headers: self.req.headers, + url: self.url, + params: self.params + }); + instance.send2(0, data); + } + + return; + } + + switch (instance.options.cachepolicy) { + case 1: // URL + key = 'rro' + instance.id + self.url.hash(); + break; + case 2: // URL + query + case 3: // URL + query + user + key = self.url; + var keys = Object.keys(self.query); + keys.sort(); + for (var i = 0, length = keys.length; i < length; i++) + key += keys[i] + self.query[keys[i]] + '&'; + if (instance.options.cachepolicy === 3 && self.user) + key += 'iduser' + self.user.id; + key = 'rro' + instance.id + key.hash(); + break; + } + + if (key && F.cache.get2(key)) { + var data = instance.make(F.cache.get2(key)); + data.repository.controller = self; + instance.send2(1, data); + } else { + + var data = instance.make({ + query: self.query, + body: self.body, + session: self.session, + user: self.user, + files: self.files, + headers: self.req.headers, + url: self.url, + params: self.params, + mobile: self.mobile, + robot: self.robot, + referrer: self.referrer, + language: self.language + }); + + data.repository.controller = self; + instance.send2(0, data); + key && FINISHED(self.res, () => F.cache.set(key, self.$flowdata.data, instance.options.cacheexpire)); + } + }; + + if (F.is4) + route = ROUTE(options.method.toUpperCase() + ' ' + options.url, handler, flags, options.size || 5); + else + F.route(options.url, handler, flags, options.size || 5); + + instance.status('Listening', 'green'); + }; + + instance.reconfigure(); + instance.on('options', instance.reconfigure); + instance.on('close', function(){ + uninstall('id:' + instance.id); + }); +}; + +// check url exists +FLOW.trigger('httproutecheckurl', function(next, data) { + var url = data.url; + var method = data.method; + if (url[url.length - 1] !== '/') + url += '/'; + var exists = F.routes.web.findItem(r => r.urlraw === url && r.method === method); + next(exists != null); +}); + +exports.uninstall = function() { + FLOW.trigger('httproutecheckurl', null); +}; diff --git a/RVO13/flow/infosender.js b/RVO13/flow/infosender.js new file mode 100755 index 0000000..587724f --- /dev/null +++ b/RVO13/flow/infosender.js @@ -0,0 +1,81 @@ +exports.id = 'infosender'; +exports.title = 'Info sender'; +exports.version = '1.0.0'; +exports.group = 'Worksys'; +exports.color = '#2134B0'; +exports.input = 2; +exports.output = 1 +exports.icon = 'bolt'; + +const { networkInterfaces } = require('os'); + +exports.html = `
+
+
+
CSV Import
+
+
+
`; + +exports.readme = `# send all data to projects.worksys.io, required to monitor status of controller(unipi)`; + +exports.install = function(instance) { + + let id; + let allValues = {}; + let sendAllValuesInterval; + let configured = false; + + let now = new Date(); + console.log(exports.title, "INSTALLED", now.toLocaleString("sk-SK")); + + const nets = networkInterfaces(); + let ipAddresses = Object.create(null); // Or just '{}', an empty object + + for (const name of Object.keys(nets)) { + for (const net of nets[name]) { + // Skip over non-IPv4 and internal (i.e. 127.0.0.1) addresses + if (net.family === 'IPv4' && !net.internal) { + if (!ipAddresses[name]) { + ipAddresses[name] = []; + } + ipAddresses[name].push(net.address); + } + } + } + + function sendValues() { + if (!configured) return; + + if (Object.keys(allValues).length > 0) { + let dataToSend = { ...allValues }; + dataToSend.id = id; + dataToSend.ipAddresses = ipAddresses; + + instance.send(0, dataToSend); + + allValues = {}; + } + } + + instance.on("close", () => { + clearInterval(sendAllValuesInterval); + }) + + instance.on("0", _ => { + id = FLOW.GLOBALS.settings.project_id; + if (id) configured = true; + else console.log(exports.title, "InfoSender: Unable to send data, no id"); + }) + + instance.on("1", flowdata => { + allValues = { ...allValues, ...flowdata.data }; + //console.log("DATA RECEIVED", flowdata.data); + }) + + sendAllValuesInterval = setInterval(() => { + sendValues(); + }, 60000 * 3); + +} + diff --git a/RVO13/flow/modbus_reader.js b/RVO13/flow/modbus_reader.js new file mode 100755 index 0000000..d6d9dad --- /dev/null +++ b/RVO13/flow/modbus_reader.js @@ -0,0 +1,346 @@ +exports.id = 'modbus_reader'; +exports.title = 'Modbus reader'; +exports.version = '2.0.0'; +exports.group = 'Worksys'; +exports.color = '#2134B0'; +exports.input = 1; +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; +//number of phases inRVO +let phases; +//phases where voltage is 0 (set) +let noVoltage; +let energyToSwitchLamps; + +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.phases = this.buildPhases(); + + this.startSocket(); + } + + buildPhases = () => { + let a = []; + for (let i = 1; i <= phases; i++) { + a.push(`Phase_${i}_voltage`) + } + return a; + } + + startSocket = () => { + + let obj = this; + + if (this.socket) { + this.socket.removeAllListeners(); + this.socket = null; + } + + 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('Modbus_reader: Socket connection error', e); //'ECONNREFUSED' or 'ECONNRESET' ?? + }); + + this.socket.on('close', function() { + console.log('Modbus_reader: Socket connection closed - Waiting 10 seconds before connecting 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 we just start to loop devices from the beginning, or there is just 1 device in config, we wait whole timeoutInterval + if (this.indexInDeviceConfig == 0 || deviceConfig.length === 1) 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 (this.phases.includes(singleValue)) { + let l = singleValue.split("_"); + let phase = parseInt(l[1]); + + // console.log(values[singleValue], tbName); + + if (values[singleValue] == 0) { + noVoltage.add(phase); + sendNotification("modbus_reader: checkNullVoltage", tbName, "no_voltage_on_phase", { phase: phase }, "", SEND_TO.tb, instance, "voltage" + phase); + // console.log('no voltage') + } + else { + noVoltage.delete(phase); + // console.log('voltage detected') + sendNotification("modbus_reader: checkNullVoltage", tbName, "voltage_on_phase_restored", { phase: phase }, "", SEND_TO.tb, instance, "voltage" + phase); + } + } + }) + } + + /** + * function sends notification to slack and to tb, if EM total_power value changes more than numberOfNodes*15. This should show, that RVO lamps has been switched on or off + */ + lampSwitchNotification = (values) => { + + if (!values.hasOwnProperty("total_power")) return; + + const actualTotalPower = values.total_power; + + if (actualTotalPower > energyToSwitchLamps && 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 <= energyToSwitchLamps && 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; + } + + function main() { + + phases = FLOW.GLOBALS.settings.phases; + tbName = FLOW.GLOBALS.settings.rvoTbName; + noVoltage = FLOW.GLOBALS.settings.no_voltage; + energyToSwitchLamps = FLOW.GLOBALS.settings.energy_to_switch_lamps / 2.5; //half value is enought to show if lamps are turned on or off + if (deviceConfig.length) mainSocket = new SocketWithClients(); + else console.log("Modbus_reader: no modbus device in configuration"); + + // this notification is to show, that flow (unipi) has been restarted + sendNotification("modbus_reader", tbName, "flow_restart", {}, "", SEND_TO.slack, instance); + } + + instance.on("0", function(_) { + main(); + }) + +} + diff --git a/RVO13/flow/monitorconsumption.js b/RVO13/flow/monitorconsumption.js new file mode 100755 index 0000000..64cc58e --- /dev/null +++ b/RVO13/flow/monitorconsumption.js @@ -0,0 +1,156 @@ +exports.id = 'monitorconsumption'; +exports.title = 'Consumption'; +exports.version = '1.0.0'; +exports.author = 'Peter Širka'; +exports.group = 'Monitoring'; +exports.color = '#967ADC'; +exports.input = 0; +exports.output = 1; +exports.icon = 'bug'; +exports.options = { interval: 5000, enabled: true, monitorconsumption: true, monitorsize: true, monitorconnections: true, monitorfiles: true }; +exports.click = true; +exports.readme = `# Consumption monitoring + +This component measure CPU and memory consumption, open files and open connections of this application. It uses these Linux commands: \`ps\`, \`lsof\`, \`netstat\` and \`df\`. + +__Data Example__: + +\`\`\`javascript +{ + cpu: 0, // percentage + memory: 4096, // in bytes + size: 34303, // directory size in bytes + files: 34, // count of open files + connections: 343, // count of connections + uptime: '1-12:34:00' +} +\`\`\``; + +exports.html = `
+
+
+
@(Interval in milliseconds)
+
+
+
+
Monitor: Consumption + uptime
+
Monitor: Count of open files
+
Monitor: Count of open connections
+
Monitor: Directory size
+
`; + +exports.install = function(instance) { + + var current = { cpu: 0, memory: 0, files: 0, connections: 0, size: 0, uptime: '', counter: 0 }; + var tproc = null; + var Exec = require('child_process').exec; + var reg_empty = /\s{2,}/g; + var reg_appdisksize = /^[\d.,]+/; + + instance.custom.run = function() { + + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + + var arr = []; + + // Get CPU and Memory consumption + instance.options.monitorconsumption && arr.push(function(next) { + Exec('ps -p {0} -o %cpu,rss,etime'.format(process.pid), function(err, response) { + + if (err) { + instance.throw(err); + } else { + var line = response.split('\n')[1]; + line = line.trim().replace(reg_empty, ' ').split(' '); + var cpu = line[0].parseFloat(); + current.cpu = cpu.floor(1); + current.memory = line[1].parseInt2() * 1024; // kB to bytes + current.uptime = line[2]; + } + + next(); + }); + }); + + // Get count of open files + instance.options.monitorfiles && arr.push(function(next) { + Exec('lsof -a -p {0} | wc -l'.format(process.pid), function(err, response) { + if (err) + instance.throw(err); + else + current.files = response.trim().parseInt2(); + next(); + }); + }); + + // Get count of opened network connections + instance.options.monitorconnections && arr.push(function(next) { + Exec('netstat -an | grep :{0} | wc -l'.format(F.port), function(err, response) { + if (err) { + instance.throw(err); + } else { + current.connections = response.trim().parseInt2() - 1; + if (current.connections < 0) + current.connections = 0; + } + next(); + }); + }); + + // Get directory size + instance.options.monitorsize && current.counter % 5 !== 0 && arr.push(function(next) { + Exec('du -hsb ' + process.cwd(), function(err, response) { + if (err) { + instance.throw(err); + } else { + var match = response.trim().match(reg_appdisksize); + match && (current.size = match.toString().trim().parseInt2()); + } + next(); + }); + }); + + arr.async(function() { + + tproc && clearTimeout(tproc); + + if (instance.options.enabled) { + tproc = setTimeout(instance.custom.run, instance.options.interval); + instance.send2(current); + } + + instance.custom.status(); + current.counter++; + }); + }; + + instance.custom.status = function() { + if (instance.options.enabled) + instance.status('{0}% / {1}'.format(current.cpu, current.memory.filesize())); + else + instance.status('Disabled', 'red'); + }; + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + + if (instance.options.enabled) { + current.counter = 0; + instance.custom.run(); + } + + }); + + instance.on('close', function() { + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + }); + + setTimeout(instance.custom.run, 1000); +}; \ No newline at end of file diff --git a/RVO13/flow/monitordisk.js b/RVO13/flow/monitordisk.js new file mode 100755 index 0000000..f4fdaa0 --- /dev/null +++ b/RVO13/flow/monitordisk.js @@ -0,0 +1,96 @@ +exports.id = 'monitordisk'; +exports.title = 'Disk'; +exports.version = '1.0.0'; +exports.author = 'Peter Širka'; +exports.group = 'Monitoring'; +exports.color = '#F6BB42'; +exports.output = 1; +exports.icon = 'hdd-o'; +exports.click = true; +exports.options = { interval: 8000, path: '/', enabled: true }; +exports.readme = `# Disk monitoring + +This component monitors disk \`bytes\` consumption in Linux systems. It uses \`df\` command. + +__Data Example__: + +\`\`\`javascript +{ + total: 474549649408, + used: 39125245952, + free: 411294994432 +} +\`\`\``; + +exports.html = `
+
+
+
@(Interval in milliseconds)
+
+
+
@(Path)
+
+
+
`; + +exports.install = function(instance) { + + var current = { total: 0, used: 0, free: 0, path: '', type: '', percentUsed: 0 }; + var tproc = null; + + instance.custom.run = function() { + + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + + if (!instance.options.enabled) + return; + + require('child_process').exec('df -hTB1 ' + instance.options.path, function(err, response) { + + tproc = setTimeout(instance.custom.run, instance.options.interval); + + if (err) { + instance.error(err); + return; + } + + response.parseTerminal(function(line) { + if (line[0][0] !== '/') + return; + current.total = line[2].parseInt(); + current.free = line[4].parseInt(); + current.used = line[3].parseInt(); + current.path = instance.options.path || '/'; + current.type = line[1]; + current.percentUsed = line[5]; + instance.custom.status(); + instance.send2(current); + }); + }); + }; + + instance.custom.status = function() { + if (instance.options.enabled) + instance.status(current.free.filesize() + ' / ' + current.total.filesize()); + else + instance.status('Disabled', 'red'); + }; + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + instance.options.enabled && instance.custom.run(); + }); + + instance.on('close', function() { + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + }); + + setTimeout(instance.custom.run, 1000); +}; \ No newline at end of file diff --git a/RVO13/flow/monitormemory.js b/RVO13/flow/monitormemory.js new file mode 100755 index 0000000..2decbc4 --- /dev/null +++ b/RVO13/flow/monitormemory.js @@ -0,0 +1,87 @@ +exports.id = 'monitormemory'; +exports.title = 'Memory'; +exports.version = '1.0.0'; +exports.author = 'Peter Širka'; +exports.group = 'Monitoring'; +exports.color = '#F6BB42'; +exports.output = 1; +exports.click = true; +exports.icon = 'microchip'; +exports.options = { interval: 8000, enabled: true }; +exports.readme = `# Memory monitoring + +This component monitors memory \`bytes\` consumption in Linux systems. It uses \`free\` command. + +__Data Example__: + +\`\`\`javascript +{ + total: 33558769664, + used: 1998868480, + free: 2653708288 +} +\`\`\``; + +exports.html = `
+
+
+
@(Interval in milliseconds)
+
+
+
`; + +exports.install = function(instance) { + + var current = { total: 0, used: 0, free: 0 }; + var tproc = null; + + instance.custom.run = function() { + + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + + if (!instance.options.enabled) + return; + + require('child_process').exec('free -b -t', function(err, response) { + + tproc = setTimeout(instance.custom.run, instance.options.interval); + + if (err) { + instance.error(err); + return; + } + + var memory = response.split('\n')[1].match(/\d+/g); + current.total = memory[0].parseInt(); + current.used = memory[1].parseInt() - memory[3].parseInt(); + current.free = current.total - current.used; + instance.custom.status(); + instance.send2(current); + }); + }; + + instance.custom.status = function() { + if (instance.options.enabled) + instance.status(current.free.filesize() + ' / ' + current.total.filesize()); + else + instance.status('Disabled', 'red'); + }; + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + instance.options.enabled && instance.custom.run(); + }); + + instance.on('close', function() { + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + }); + + setTimeout(instance.custom.run, 1000); +}; \ No newline at end of file diff --git a/RVO13/flow/nodesdb_changecheck.js b/RVO13/flow/nodesdb_changecheck.js new file mode 100755 index 0000000..9adab62 --- /dev/null +++ b/RVO13/flow/nodesdb_changecheck.js @@ -0,0 +1,77 @@ +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 = 2; +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); + } + } + + //kedze do slacku posielame stringy, na cloud musime previest vsetky stringy spat na objekty: + // Funkcia na parsovanie všetkých reťazcov v poli + const parseArray = (arr) => { + return arr.map(jsonString => JSON.parse(jsonString)); + }; + + 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); + if (FLOW.GLOBALS.settings.send_changed_node_numbers) instance.send(1, { aktualneNody: parseArray(zmenene), originalne: parseArray(Array.from(set2)) }); + } + 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/RVO13/flow/show_dbdata.js b/RVO13/flow/show_dbdata.js new file mode 100755 index 0000000..1e23ff7 --- /dev/null +++ b/RVO13/flow/show_dbdata.js @@ -0,0 +1,243 @@ +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 = 8; +exports.output = 1; + +const { exec } = require('child_process'); + +exports.install = 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 }) + }) + instance.on("5", _ => { + exec("sudo tail -n 25 monitor.txt", (err, stdout, stderr) => { + if (err || stderr) instance.send(0, { err, stderr }); + else instance.send(0, stdout); + }) + }) + instance.on("6", _ => { + exec("sudo tail -n 25 err.txt", (err, stdout, stderr) => { + if (err || stderr) instance.send(0, { err, stderr }); + else instance.send(0, stdout); + }) + }) + instance.on("7", _ => { + instance.send(0, FLOW.deviceStatus); + }) +}; + + +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/RVO13/flow/slack_filter.js b/RVO13/flow/slack_filter.js new file mode 100755 index 0000000..6618523 --- /dev/null +++ b/RVO13/flow/slack_filter.js @@ -0,0 +1,188 @@ +exports.id = 'slack_filter'; +exports.title = 'Slack Filter'; +exports.group = 'Citysys'; +exports.color = '#30E193'; +exports.input = 2; +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 = `
+
+
+
@(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('0', 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']['en']; + 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"] = []; + } + + instance.options.name = FLOW.GLOBALS.settings.rvo_name; + if (instance.options.name) { + instance.status('Running'); + running = true; + } else { + instance.status('Please run options again', 'red'); + running = false; + } + } catch (e) { + instance.error('Citysys connector: ' + e.message); + } + }; + + instance.on('options', instance.reconfigure); + + instance.on("1", _ => { + instance.reconfigure(); + }) +}; diff --git a/RVO13/flow/thermometer.js b/RVO13/flow/thermometer.js new file mode 100755 index 0000000..fa015c6 --- /dev/null +++ b/RVO13/flow/thermometer.js @@ -0,0 +1,98 @@ +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 = 5;//minutes +let NUMBER_OF_FAILURES_TO_SEND_ERROR = 13; + +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) => { + + 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); + setTimeout(main, 20000); + }) +}; diff --git a/RVO13/flow/trigger.js b/RVO13/flow/trigger.js new file mode 100755 index 0000000..27545a8 --- /dev/null +++ b/RVO13/flow/trigger.js @@ -0,0 +1,79 @@ +exports.id = 'trigger'; +exports.title = 'Trigger'; +exports.group = 'Inputs'; +exports.color = '#F6BB42'; +exports.click = true; +exports.output = 1; +exports.version = '1.1.0'; +exports.author = 'Martin Smola'; +exports.icon = 'play'; + +exports.html = `
+
@(Data type (String by default))
+
@(Data)
+
Trigger 5s after initialization.
+
@(Useful when there's a need to run certain flow when the app restarts, etc.)
+
`; + +exports.readme = `# Trigger + +- Clicking on the component starts the chain +- Settings allows to set a data-type and a value`; + +exports.install = function(instance) { + + var value; + + instance.on('click', () => instance.send2(value)); + + instance.reconfigure = function() { + var options = instance.options; + value = null; + switch (options.datatype) { + case 'integer': + value = options.data.parseInt2('error'); + value = value === 'error' ? NaN : value; + break; + case 'float': + value = options.data.parseFloat2('error'); + value = value === 'error' ? NaN : value; + break; + case 'date': + options.data = options.data.toString(); + var num = options.data.parseInt('error'); + num === 'error' && (num = options.data.parseDate('error')); + num === 'error' && (num = null); + value = num ? new Date(num).toUTCString() : num; + break; + case 'object': + try { + value = (new Function('return ' + options.data))(); + } catch (e) { + instance.error(e); + } + break; + case 'boolean': + value = options.data.parseBoolean(); + break; + case 'buffer': + try { + value = U.createBuffer(options.data); + } catch (e) { + instance.error(e); + } + break; + case 'string': + default: + value = '' + (options.data || ''); + break; + } + }; + + instance.on('options', instance.reconfigure); + instance.reconfigure(); + + if (instance.options.restart) + setTimeout(function(){ + instance.send2(value); + }, 5000); +}; diff --git a/RVO13/flow/variables.txt b/RVO13/flow/variables.txt new file mode 100755 index 0000000..e69de29 diff --git a/RVO13/flow/virtualwirein.js b/RVO13/flow/virtualwirein.js new file mode 100755 index 0000000..38a4e42 --- /dev/null +++ b/RVO13/flow/virtualwirein.js @@ -0,0 +1,43 @@ +exports.id = 'virtualwirein'; +exports.title = 'Virtual wire in'; +exports.version = '1.0.0'; +exports.author = 'Martin Smola'; +exports.color = '#303E4D'; +exports.icon = 'sign-in'; +exports.input = false; +exports.output = 1; +exports.options = {}; +exports.readme = `# Virtual wire in + +When the wires between the components are mess it's time to use Virtual wire.`; + +exports.html = `
+
@(Wire name)
+
+`; + +exports.install = function(instance) { + + instance.custom.reconfigure = function(options){ + if (instance.options.wirename) { + instance.status(instance.options.wirename); + } else + instance.status('Not configured', 'red'); + }; + + ON('virtualwire', function(wirename, flowdata){ + if (instance.options.wirename && instance.options.wirename === wirename) + instance.send(flowdata); + }); + + instance.on('options', instance.custom.reconfigure); + instance.custom.reconfigure(); +}; diff --git a/RVO13/flow/virtualwireout.js b/RVO13/flow/virtualwireout.js new file mode 100755 index 0000000..94a1e4f --- /dev/null +++ b/RVO13/flow/virtualwireout.js @@ -0,0 +1,41 @@ +exports.id = 'virtualwireout'; +exports.title = 'Virtual wire out'; +exports.version = '1.0.0'; +exports.author = 'Martin Smola'; +exports.color = '#303E4D'; +exports.icon = 'sign-out'; +exports.input = true; +exports.options = {}; +exports.readme = `# Virtual wire out + +When the wires between the components are mess it's time to use Virtual wire.`; + +exports.html = `
+
@(Wire name)
+
+`; + +exports.install = function(instance) { + + instance.custom.reconfigure = function(){ + if (instance.options.wirename) { + instance.status(instance.options.wirename); + } else + instance.status('Not configured', 'red'); + }; + + instance.on('data', function(flowdata) { + EMIT('virtualwire', instance.options.wirename, flowdata); + }); + + instance.on('options', instance.custom.reconfigure); + instance.custom.reconfigure(); +}; diff --git a/RVO13/flow/wsmqttpublish.js b/RVO13/flow/wsmqttpublish.js new file mode 100755 index 0000000..0eba804 --- /dev/null +++ b/RVO13/flow/wsmqttpublish.js @@ -0,0 +1,448 @@ +exports.id = 'wsmqttpublish'; +exports.title = 'WS MQTT publish'; +exports.group = 'MQTT'; +exports.color = '#888600'; +exports.version = '1.0.2'; +exports.icon = 'sign-out'; +exports.input = 2; +exports.output = 3; +exports.options = { host: 'tb-stage.worksys.io', port: 1883, clientid: "", username: "" }; + +exports.html = `
+
+
+
Hostname or IP address (if not empty - setting will override db setting)
+
+
+
Port
+
+
+
+
+
@(Client id)
+
+
+
@(Username)
+
+
+
`; + + +exports.readme = ` +# WS MQTT Publish + +Version 1.0.3. + +Added: +- database collections, +- 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 = { + debug: 0, + rpcCall: 1, + services: 2 +} + +//CONFIG +let createTelemetryBackup = true; +let saveTelemetryOnError = true;//backup_on_failure overrides this value +//------------------------ + +let rollers; +if (createTelemetryBackup) rollers = require('streamroller'); + +const noSqlFileSizeLimit = 4194304;//use 5MB - 4194304 +let insertNoSqlCounter = 0; +let insertBackupNoSqlCounter = 0; +let processingData = false; + +let backup_on_failure = false;//== saveTelemetryOnError - create backup client 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; + +process.on('uncaughtException', function(err) { + + errLogger.error('uncaughtException:', err.message) + errLogger.error(err.stack); + + //TODO + //send to service + + //process.exit(1); +}) + +const nosql = NOSQL('tbdata'); +const nosqlBackup = NOSQL('/backup/tbdata'); + + +exports.install = function(instance) { + + var client; + var opts; + var clientReady = false; + + // wsmqtt status for notification purposes on projects.worksys.io database + let wsmqttName = null; + let sendWsStatusVar = null; + let wsmqtt_status = 'disconnected'; + + 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'; + } + + function sendWsStatus() { + instance.send(SEND_TO.services, { [wsmqttName]: wsmqtt_status }); + } + + + function main() { + if (!FLOW.dbLoaded) return; + + loadSettings(); + clearInterval(sendWsStatus); + sendWsStatusVar = setInterval(sendWsStatus, 180000); + } + + //set opts according to db settings + function loadSettings() { + + if (instance.options.host !== "") { + //override settings from database + var o = instance.options; + opts = { + host: o.host, + port: o.port, + clientId: o.clientid, + username: o.username, + rejectUnauthorized: false, + resubscribe: false + }; + + wsmqttName = getWsmqttName(o.host); + + console.log("wsmqttpublich -> loadSettings from instance.options", instance.options); + } + else { + + const SETTINGS = FLOW.GLOBALS.settings; + backup_on_failure = SETTINGS.backup_on_failure; + saveTelemetryOnError = backup_on_failure; + + restore_from_backup = SETTINGS.restore_from_backup; + restore_backup_wait = SETTINGS.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; + + opts = { + host: mqtt_host, + port: mqtt_port, + keepalive: 10, + clientId: mqtt_clientid, + username: mqtt_username, + rejectUnauthorized: false, + resubscribe: false + }; + + wsmqttName = getWsmqttName(mqtt_host); + } + + connectToTbServer(); + } + + function connectToTbServer() { + 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"); + //monitor.info("MQTT client connected"); + + sendClientError = true; + clientReady = true; + wsmqtt_status = 'connected'; + }); + + client.on('reconnect', function() { + instance.status("Reconnecting", "yellow"); + clientReady = false; + }); + + client.on('message', function(topic, message) { + // message is type of buffer + message = message.toString(); + if (message[0] === '{') { + TRY(function() { + + message = JSON.parse(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 } }); + } + + }, () => instance.debug('MQTT: Error parsing data', message)); + } + + instance.send(SEND_TO.rpcCall, { "topic": topic, "content": message }); + }); + + client.on('close', function() { + clientReady = false; + wsmqtt_status = 'disconnected'; + + instance.status("Disconnected", "red"); + instance.send(SEND_TO.debug, { "message": "Client CLOSE signal received !" }); + }); + + client.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; + wsmqtt_status = 'disconnected'; + }); + + } + + + instance.on("0", _ => { + main(); + }) + + + instance.on('1', function(data) { + + if (clientReady) { + //do we have some data in backup file? if any, process data from database + if (saveTelemetryOnError) { + //read telemetry data and send back to server + if (!processingData) processDataFromDatabase(); + } + + let stringifiedJson = JSON.stringify(data.data); + client.publish("v1/gateway/telemetry", stringifiedJson, { qos: 1 }); + + //backup telemetry + if (createTelemetryBackup) { + data.data.id = UID(); + nosqlBackup.insert(data.data); + + insertBackupNoSqlCounter++; + if (insertBackupNoSqlCounter > 150) { + let options = { compress: true }; + let path = __dirname + "/../databases/backup/tbdata.nosql"; + var stream = new rollers.RollingFileStream(path, noSqlFileSizeLimit, 150, options); + stream.write(""); + stream.end(); + + insertBackupNoSqlCounter = 0; + } + } + + } + 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 (saveTelemetryOnError) { + //create new file from tbdata.nosql, if file size exceeds given limit, and clear tbdata.nosql + makeBackupFromDbFile(); + + //write to tb + data.data.id = UID(); + nosql.insert(data.data); + } + } + }); + + + instance.close = function(done) { + if (clientReady) { + client.end(); + clearInterval(sendWsStatusVar); + } + }; + + + function getDbBackupFileCounter(type) { + var files = fs.readdirSync(__dirname + "/../databases"); + + let counter = 0; + for (var i = 0; i < files.length; i++) { + + if (files[i] == "tbdata.nosql") continue; + + if (files[i].endsWith(".nosql")) { + + let pos = files[i].indexOf("."); + if (pos > -1) { + + let fileCounter = counter; + let firstDigit = files[i].slice(0, pos); + + fileCounter = parseInt(firstDigit); + if (isNaN(fileCounter)) fileCounter = 0; + //console.log("getDbBackupFileCounter digit:", files[i], firstDigit, fileCounter, isNaN(fileCounter), type); + + if (type == "max") { + if (fileCounter > counter) { + counter = fileCounter; + } + } + else if (type == "min") { + if (counter == 0) counter = fileCounter; + + if (fileCounter < counter) { + counter = fileCounter; + } + } + } + } + + } + + if (type == "max") counter++; + + return counter; + } + + const makeBackupFromDbFile = async () => { + + if (!saveTelemetryOnError) return; + + //to avoid large file: tbdata.nosql + + //init value is 0! + if (insertNoSqlCounter > 0) { + --insertNoSqlCounter; + return; + } + + insertNoSqlCounter = 100; + + let source = __dirname + "/../databases/tbdata.nosql"; + + var stats = fs.statSync(source); + var fileSizeInBytes = stats.size; + + if (fileSizeInBytes > noSqlFileSizeLimit) { + + let counter = 1; + counter = getDbBackupFileCounter("max"); + + let destination = __dirname + "/../databases/" + counter + "." + "tbdata.nosql"; + + //make backup file + fs.copyFileSync(source, destination); + //fs.renameSync(p, p + "." + counter); + + //clear tbdata.nosql + fs.writeFileSync(source, ""); + fs.truncateSync(source, 0); + + } + } + + const processDataFromDatabase = async () => { + + if (restore_from_backup <= 0) return; + + //calculate diff + const now = new Date(); + let currentTime = now.getTime(); + let diff = currentTime - lastRestoreTime; + + if ((diff / 1000) < restore_backup_wait) { + //console.log("*********restore_backup_wait", diff, restore_backup_wait); + return; + } + + processingData = true; + + //get filename to process + let counter = getDbBackupFileCounter("min"); + + //we have some backup files + let dataBase = 'tbdata'; + + var nosql; + if (counter == 0) dataBase = 'tbdata'; + else dataBase = counter + "." + 'tbdata'; + + nosql = NOSQL(dataBase); + + //select all data - use limit restore_from_backup + let records = await promisifyBuilder(nosql.find().take(restore_from_backup)); + + for (let i = 0; i < records.length; i++) { + if (clientReady) { + + let item = records[i]; + let id = item.id; + + if (id !== undefined) { + //console.log("------------processDataFromDatabase - remove", id, dataBase, i); + + try { + + let message = JSON.parse(JSON.stringify(item)); + delete message.id; + + client.publish("v1/gateway/telemetry", JSON.stringify(message), { qos: 1 }); + + //remove from database + await promisifyBuilder(nosql.remove().where("id", id)); + + } catch (error) { + //process error + console.log("processDataFromDatabase", error); + } + + } + + } + else { + processingData = false; + return; + } + } + + if (records.length > 0) { + //clean backup file + if (counter > 0) nosql.clean(); + } + + //no data in db, remove + if (records.length == 0) { + if (counter > 0) nosql.drop(); + } + + const d = new Date(); + lastRestoreTime = d.getTime(); + + processingData = false; + + } + + instance.on('options', main); + //instance.reconfigure(); +}; diff --git a/RVO13/flow_3_2_25/cloudmqttconnect.js b/RVO13/flow_3_2_25/cloudmqttconnect.js new file mode 100755 index 0000000..d619784 --- /dev/null +++ b/RVO13/flow_3_2_25/cloudmqttconnect.js @@ -0,0 +1,374 @@ +exports.id = 'cloudmqttconnect'; +exports.title = 'Cloud connect mqtt'; +exports.group = 'MQTT'; +exports.color = '#888600'; +exports.version = '1.0.2'; +exports.icon = 'sign-out'; +exports.input = 2; +exports.output = 2; +exports.options = { host: 'tb-stage.worksys.io', port: 1883, clientid: "", username: "" }; + +exports.html = `
+
+
+
Hostname or IP address (if not empty - setting will override db setting)
+
+
+
Port
+
+
+
+
+
@(Client id)
+
+
+
topic
+
+
+
`; + + + +const { promisifyBuilder } = require('./helper/db_helper'); +const fs = require('fs'); +const mqtt = require('mqtt'); +const nosql = NOSQL('tbdatacloud'); + +const SEND_TO = { + debug: 0, + rpcCall: 1, +} + +//CONFIG +let saveTelemetryOnError = true;//backup_on_failure overrides this value +//------------------------ + +const noSqlFileSizeLimit = 4194304;//use 5MB - 4194304 +let insertNoSqlCounter = 0; +let insertBackupNoSqlCounter = 0; +let processingData = false; + +let backup_on_failure = true;//== saveTelemetryOnError - create backup client send failure +let restore_from_backup = 50; //how many rows process at once? +let restore_backup_wait = 3;//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; + + +exports.install = function(instance) { + + var client; + var opts; + var clientReady = false; + + let o = null; //options + + function main() + { + loadSettings(); + } + + //set opts according to db settings + function loadSettings() + { + + o = instance.options; + if(!o.topic) o.topic = FLOW.GLOBALS.settings.cloud_topic; + + opts = { + host: o.host, + port: o.port, + clientId: o.clientid, + username: o.username, + rejectUnauthorized: false, + resubscribe: false + }; + + console.log("wsmqttpublich -> loadSettings from instance.options",o); + + connectToTbServer(); + } + + function connectToTbServer() + { + var url = "mqtt://" + opts.host + ":" + opts.port; + console.log("MQTT URL: ", url); + + client = mqtt.connect(url, opts); + + client.on('connect', function() { + client.subscribe(`${o.topic}_backward`, (err) => { + if (!err) { + console.log("MQTT subscribed"); + } + }); + instance.status("Connected", "green"); + clientReady = true; + sendClientError = true; + }); + + client.on('reconnect', function() { + instance.status("Reconnecting", "yellow"); + clientReady = false; + }); + + client.on('message', function(topic, message) { + // message is type of buffer + message = message.toString(); + if (message[0] === '{') { + TRY(function() { + + message = JSON.parse(message); + if (message.hasOwnProperty("device") && message.hasOwnProperty("data") && message.data.hasOwnProperty("id")) { + client.publish(`${o.topic}_forward`, `{"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}}); + } + + }, () => instance.debug('MQTT: Error parsing data', message)); + } + + instance.send(SEND_TO.rpcCall, {"topic":o.topic, "content":message }); + }); + + client.on('close', function() { + clientReady = false; + + instance.status("Disconnected", "red"); + instance.send(SEND_TO.debug, {"message":"Client CLOSE signal received !"}); + }); + + client.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) { + console.log('MQTT client error', err); + sendClientError = false; + } + clientReady = false; + }); + + } + + + instance.on('0', function(data) { + + if(clientReady) + { + //do we have some data in backup file? if any, process data from database + if(saveTelemetryOnError) + { + //read telemetry data and send back to server + if(!processingData) processDataFromDatabase(); + } + + let stringifiedJson = JSON.stringify(data.data) + client.publish(`${o.topic}_forward`, stringifiedJson, {qos: 1}); + } + 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(saveTelemetryOnError) + { + //create new file from tbdata.nosql, if file size exceeds given limit, and clear tbdata.nosql + makeBackupFromDbFile(); + + //write to tb + data.data.id = UID(); + nosql.insert(data.data); + } + } + }); + + instance.on("1", _ => { + main(); + }) + + instance.close = function(done) { + if(clientReady){ + client.end(); + } + }; + + + function getDbBackupFileCounter(type) + { + var files = fs.readdirSync(__dirname + "/../databases"); + + let counter = 0; + for(var i = 0; i < files.length; i++) + { + + if(files[i] == "tbdatacloud.nosql") continue; + + if(files[i].endsWith(".nosql")) + { + + let pos = files[i].indexOf("."); + if(pos > -1) + { + + let fileCounter = counter; + let firstDigit = files[i].slice(0, pos); + + fileCounter = parseInt(firstDigit); + if(isNaN(fileCounter)) fileCounter = 0; + //console.log("getDbBackupFileCounter digit:", files[i], firstDigit, fileCounter, isNaN(fileCounter), type); + + if(type == "max") + { + if(fileCounter > counter) + { + counter = fileCounter; + } + } + else if(type == "min") + { + if(counter == 0) counter = fileCounter; + + if(fileCounter < counter) + { + counter = fileCounter; + } + } + } + } + + } + + if(type == "max") counter++; + + return counter; + } + + const makeBackupFromDbFile = async () => { + + if(!saveTelemetryOnError) return; + + //to avoid large file: tbdata.nosql + + //init value is 0! + if(insertNoSqlCounter > 0) + { + --insertNoSqlCounter; + return; + } + + insertNoSqlCounter = 100; + + let source = __dirname + "/../databases/tbdatacloud.nosql"; + + var stats = fs.statSync(source); + var fileSizeInBytes = stats.size; + + if(fileSizeInBytes > noSqlFileSizeLimit) + { + + let counter = 1; + counter = getDbBackupFileCounter("max"); + + let destination = __dirname + "/../databases/" + counter + "." + "tbdatacloud.nosql"; + + //make backup file + fs.copyFileSync(source, destination); + //fs.renameSync(p, p + "." + counter); + + //clear tbdata.nosql + fs.writeFileSync(source, ""); + fs.truncateSync(source, 0); + + } + } + + const processDataFromDatabase = async () => { + + if(restore_from_backup <= 0) return; + + //calculate diff + const now = new Date(); + let currentTime = now.getTime(); + let diff = currentTime - lastRestoreTime; + + if( (diff / 1000) < restore_backup_wait) + { + //console.log("*********restore_backup_wait", diff, restore_backup_wait); + return; + } + + processingData = true; + + //get filename to process + let counter = getDbBackupFileCounter("min"); + + //we have some backup files + let dataBase = 'tbdata'; + + var nosql; + if(counter == 0) dataBase = 'tbdatacloud'; + else dataBase = counter + "." + 'tbdatacloud'; + + nosql = NOSQL(dataBase); + + //select all data - use limit restore_from_backup + let records = await promisifyBuilder(nosql.find().take(restore_from_backup)); + + for(let i = 0; i < records.length; i++) + { + if(clientReady) { + + let item = records[i]; + let id = item.id; + + if(id !== undefined) + { + //console.log("------------processDataFromDatabase - remove", id, dataBase, i); + + try { + + let message = JSON.parse(JSON.stringify(item)); + delete message.id; + client.publish(`${o.topic}_forward`, JSON.stringify(message), {qos:1}); + + //remove from database + await promisifyBuilder(nosql.remove().where("id", id)); + + } catch(error) { + //process error + console.log("processDataFromDatabase", error); + } + + } + + } + else + { + processingData = false; + return; + } + } + + if(records.length > 0) + { + //clean backup file + if(counter > 0) nosql.clean(); + } + + //no data in db, remove + if(records.length == 0) + { + if(counter > 0) nosql.drop(); + } + + const d = new Date(); + lastRestoreTime = d.getTime(); + + processingData = false; + + } + + instance.on('options', main); + +}; diff --git a/RVO13/flow_3_2_25/cmd_manager.js b/RVO13/flow_3_2_25/cmd_manager.js new file mode 100755 index 0000000..a960aaa --- /dev/null +++ b/RVO13/flow_3_2_25/cmd_manager.js @@ -0,0 +1,2988 @@ +exports.id = 'cmd_manager'; +exports.title = 'CMD Manager'; +exports.group = 'Worksys'; +exports.color = '#5D9CEC'; +exports.version = '0.0.3'; +exports.output = ['red', 'blue', 'yellow', 'blue', 'white']; +exports.input = 3; +exports.icon = 'cloud-upload'; + +exports.html = ` +
+
+
+
RPC - run RPC calls

+
+
+
@(User)
+
+
+
@(Password)
+
+
+
@(My edge)
+
+
+
+`; +exports.readme = `Manager for CMD calls`; + + +exports.install = function(instance) { + + 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'); + + 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'); + + const dbNodes = TABLE("nodes"); + const dbRelays = TABLE("relays"); + + let GLOBALS; + let SETTINGS; + let rsPort; + let tbHandler; + + // runTasks intervals + const SHORT_INTERVAL = 30; + const LONG_INTERVAL = 300; + + //send data to following instances: + const SEND_TO = { + debug: 0, + tb: 1, + http_response: 2, + dido_controller: 3, + infoSender: 4 + } + + 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 + } + + 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 + + //if sending of profile to node fails, we send notification and push node into set, so we do not send notification twice + const nodeProfileSendFail = new Set(); + + //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(); + } + + + 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" + //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); + + 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); + + console.log("proces profile finished *********************") + } + + + 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; + }); + } + + + 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) { + for (let k in nodesData) { + 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`); + } + } + } + + + function loadRelaysData(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 (value.contactor == 1) processAllNodeProfilesOnLine(value.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 = {}; + + 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.byte1 = hours;//h + params.byte2 = minutes;//m + params.byte3 = seconds;//s + params.byte4 = 0; + params.recipient = 2;//2 broadcast, address = 0 + params.register = 87;//Actual time + params.rw = 1;//write + + //other values + params.type = "cmd"; + params.timestamp = Date.now() + 60000; + params.addMinutesToTimestamp = addMinutesToTimestamp; + params.info = "run broadcast: Actual time"; + + tasks.push(params); + + let sec = 3; + 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) { + 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); + + 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'; + //params.debug = true; + + tasks.push(params); + } + + //Prúd + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "cmd"; + params.tbname = tbname; + params.address = node; + params.register = 75;//prud + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read current'; + //params.debug = true; + + tasks.push(params); + } + + //výkon + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "cmd"; + params.tbname = tbname; + params.address = node; + params.register = 76;//výkon + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read power'; + //params.debug = true; + + tasks.push(params); + } + } + } + }, sec * 1000); + } + + + 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"; + + const date = Date.now(); + + // 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); + }) + + } + + + function turnLine(onOrOff, line, info) { + let obj = { + line: line, + command: onOrOff, + info: info + }; + + logger.debug("linia", line, obj); + instance.send(SEND_TO.dido_controller, obj); + } + + + + 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"; + 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]) { + //CRC_ERROR + message = "NOK"; + error = "CRC_ERROR c1"; + instance.send(SEND_TO.debug, "CRC_ERROR c1"); + } + + 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") { + instance.send(SEND_TO.debug, bytes); + instance.send(SEND_TO.debug, "RESPONSE " + type + " - " + bytes[4]); + + //logger.debug(SEND_TO.debug, "RESPONSE " + type + " - " + bytes[4], bytes); + + error = "type is: " + type; + + message = "NOK"; + } + + return { message, type, error }; + } + + + //BUILD TASKS// + function buildTasks(params) { + //report SETTINGS.edge_fw_version as fw_version + //report date as startdate + + //return; + console.log("buidTAaasks start ****************", params); + + monitor.info("buildTasks - params", params); + + let processLine; //defined line + let init = false; + let processLineProfiles = true; + let processBroadcast = true; + let processNodes = true; + + if (params == undefined) { + init = true; + tasks = []; + logger.debug("-->buildTasks clear tasks"); + } + else { + processLineProfiles = false; + processBroadcast = false; + processNodes = false; + + processLineProfiles = params.processLineProfiles; + processLine = params.line; + } + + //load profiles pre vsetky linie: + let now = new Date(); + + if (processLineProfiles) { + //process line profiles + let keys = Object.keys(relaysData); + 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; + } + + try { + + /** + * we process line profiles: timepoints, astro clock, lux_sensor, offsets ... + */ + if (profilestr === "") throw ("Profile is not defined"); + let profile = JSON.parse(profilestr); + 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; + + // add name to regular profile timepoint and delete unused end_time key: + time_points.forEach(point => { + point.name = "profileTimepoint" + delete point.end_time; + }); + + //monitor.info("buildTasks: time_points", time_points); + + + /** + * 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 astro clock true, we remove all regular profile points + time_points = []; + + 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 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); + + 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); + + 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(':'); + + let ad = new Date(); + ad.setHours(parseInt(ahours), parseInt(aminutes), 0); + + let bd = new Date(); + bd.setHours(parseInt(bhours), parseInt(bminutes), 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++) { + + let start_time = new Date(); + let [hours, minutes] = time_points[t].start_time.split(':'); + start_time.setHours(parseInt(hours), parseInt(minutes), 0); + + //task is in 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); + params.value = time_points[t].value; + params.tbname = relaysData[line].tbname; + params.timestamp = start_time.getTime(); + + 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; + + //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)) { + 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; + + params.debug = true; + + //turn on/off line + tasks.push(params); + monitor.info("TimePoint params: ", params.info, start_time); + } + + monitor.info("-->time_points final", line, time_points); + + //ensure to turn on/off according to calculated currentValue + let params = getParams(PRIORITY_TYPES.terminal); + params.type = "relay"; + params.line = parseInt(line); + params.tbname = relaysData[line].tbname; + params.value = currentValue; + + params.timestamp = PRIORITY_TYPES.terminal; + params.addMinutesToTimestamp = 0; + params.debug = true; + + //logger.debug(now.toLocaleString("sk-SK")); + 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; + + tasks.push(params); + + } catch (error) { + if (profilestr !== "") { + //errLogger.error(profilestr, error); + errorHandler.sendMessageToService(profilestr + "-" + error, 0, "js_error"); + } + } + + } + + //logger.debug("tasks:"); + //logger.debug(tasks); + } + + + //PROCESS DEFAULT BROADCASTS + //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.register = 6;//Time of dusk - Reg 6 + params.rw = 1;//write + + //other values + params.type = "cmd"; + params.timestamp = Date.now() + 60000; + params.addMinutesToTimestamp = addMinutesToTimestamp; + params.info = "Broadcast-duskTime"; + + tasks.push(params); + } + + { + + //run broadcast Time of dawn + 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 + params.byte3 = 0;//s + params.byte4 = 0; + params.recipient = 2; //2 broadcast + params.register = 7;//Time of dawn - Reg 6 + params.rw = 1;//write + + //other values + params.type = "cmd"; + params.timestamp = Date.now() + 60000; + params.addMinutesToTimestamp = addMinutesToTimestamp; + params.info = "Broadcast-dawnTime"; + + tasks.push(params); + } + + { + //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 + params.byte3 = seconds;//s + params.byte4 = 0; + params.recipient = 2; //2 broadcast + params.register = 87;//Actual time + params.rw = 1;//write + + //other values + params.type = "cmd"; + params.timestamp = Date.now() + 60000; + params.addMinutesToTimestamp = addMinutesToTimestamp; + params.info = "run broadcast: Actual time"; + + tasks.push(params); + } + + } + + //process nodes & tasks + //reportovanie pre platformu + 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++) { + register = listOfCommands[i]; + + let params = getParams(PRIORITY_TYPES.node_cmd); + + //core rpc values + params.address = address; + params.byte1 = 0; + params.byte2 = 0; + params.byte3 = 0; + params.byte4 = 0; + 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) { + timestampStart = timestampStart + addMinutesToTimestamp * 60000; + } + + //other values + params.type = "cmd"; + params.tbname = tbname; + params.timestamp = timestampStart; + params.addMinutesToTimestamp = addMinutesToTimestamp; + params.info = "generated cmd - buildTasks (node)"; + + tasks.push(params); + + } + } + } + + + //niektore ulohy sa vygeneruju iba 1x pri starte!!! + if (!init) return; + + + //Priebežne (raz za cca 5 minút) je potrebné vyčítať z Master nodu verziu jeho FW. + //Jedná sa o register 10. Rovnaká interpretácia ako pri FW verzii nodu. + //Adresa mastera je 0. V prípade že kedykoľvek nastane situácia že Master Node neodpovedá (napríklad pri vyčítaní telemetrie z nodu nevráti žiadne dáta), + //tak treba vyreportovať string "NOK". + { + let params = getParams(PRIORITY_TYPES.fw_detection); + params.type = "cmd-master"; + params.register = 4; + params.address = 0; + params.timestamp = Date.now() + 60000; + params.addMinutesToTimestamp = 5; + params.tbname = SETTINGS.rvoTbName; + params.info = "Master node FW verzia"; + //params.debug = true; + + //this will set SETTINGS.masterNodeIsResponding + + tasks.push(params); + } + + //kazdu hodinu skontrolovat nastavenie profilov + { + let params = getParams(PRIORITY_TYPES.fw_detection); + params.type = "process_profiles"; + params.timestamp = Date.now() + 60000; + params.addMinutesToTimestamp = 60;//60 = every hour + params.info = "detekcia nespracovaných profilov linie a nodov"; + //params.debug = true; + + tasks.push(params); + } + + monitor.info("tasks created:", tasks.length); + } + + + /** + * We process line profile, where "astro_clock": true + * example profile: + * + "dawn_lux_sensor": true, + "dusk_lux_sensor": true, + "dawn_lux_sensor_value": 5, + "dusk_lux_sensor_value": 5, + "dawn_astro_clock_offset": 0, + "dusk_astro_clock_offset": 10, + "dawn_lux_sensor_time_window": 30, + "dusk_lux_sensor_time_window": 30, + "dawn_astro_clock_time_window": 60, + "dusk_astro_clock_time_window": 60 + + * if dawn: if currentTimestamp is in timewindow "dawnTime + and - dawn_lux_sensor_time_window" and lux value >= lux_sensor_value, we switch off the line. + * if dusk: we do oposite + * + * dawn: usvit - lux je nad hranicou - vypnem + * dusk: sumrak - lux je pod hranicou - zapnem + */ + 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++) { + + let line = keys[i]; //line is turned off by default + let profilestr = relaysData[line].profile; + const contactor = relaysData[line].contactor; + + try { + + let profile = JSON.parse(profilestr); + if (Object.keys(profile).length === 0) throw ("turnOnOffLinesAccordingToLuxSensor - profile is not defined"); + + 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 (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"); + } + } + } + + //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 (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"); + } + } + } + + } + + } catch (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) { + //MASTER + if (node == 0) return; + + let nodeObj = nodesData[node]; + 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; + } + + } + + + 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 }; + } + }); + }); + } + + + async function runTasks() { + + clearInterval(interval); + + let currentTimestamp = Date.now(); + + //report dusk, dawn--------------------------------- + if (reportDuskDawn.dusk_time < currentTimestamp) { + //vyreportuj iba ak nie je velky rozdiel napr. 60 sekund + 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); + reportDuskDawn.dusk_time_reported = sunCalcResult.dusk_time; + } + } + + var nextDay = new Date(); + nextDay.setDate(nextDay.getDate() + 1); + + sunCalcResult = calculateDuskDawn(nextDay); + reportDuskDawn.dusk_time = sunCalcResult.dusk_time; + } + + if (reportDuskDawn.dawn_time < currentTimestamp) { + //vyreportuj iba ak nie je velky rozdiel napr. 60 sekund + 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); + reportDuskDawn.dawn_time_reported = sunCalcResult.dawn_time; + } + } + + var nextDay = new Date(); + nextDay.setDate(nextDay.getDate() + 1); + + sunCalcResult = calculateDuskDawn(nextDay); + reportDuskDawn.dawn_time = sunCalcResult.dawn_time; + + } + //-------------------------------------------------------- + + //sort tasks based on timestamp + 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) { + instance.send(SEND_TO.debug, "no tasks created"); + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + 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) { + //logger.debug("--->task to process", currentTask); + } + + if (currentTask.timestamp <= currentTimestamp) { + let params = { ...tasks[0] }; + + //allow terminal commands + if (SETTINGS.maintenance_mode && params.type !== "cmd-terminal") { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + let type = params.type; + let tbname = params.tbname; + let node = params.address; + + let line = null; + + //rpc related + if (nodesData[node] !== undefined) line = nodesData[node].line; + if (params.line !== undefined) line = params.line; + + let repeatTask = false; + if (params.addMinutesToTimestamp > 0 || params.timePointName) repeatTask = true; + + if (repeatTask) { + if (type === "cmd" || type === "cmd-master") { + //set next start time automatically + tasks[0].timestamp = currentTimestamp + tasks[0].addMinutesToTimestamp * 60000; + } + } + else { + tasks.shift(); + } + + //kontrola nespracovanych profilov nodov + if (type == "process_profiles") { + tasks[0].timestamp = currentTimestamp + tasks[0].addMinutesToTimestamp * 60000; + + //vsetky linie kt. su zapnute, a spracuju sa nespracovane profily nodov + loadRelaysData(); + + interval = setInterval(runTasks, SHORT_INTERVAL); + return; + } + + //relay + if (type == "relay") { + + const timePointName = params.timePointName; + const value = params.value; + + let date = new Date(); + date.setDate(date.getDate() + 1);//next day + + let sunCalcResult; + if (timePointName) sunCalcResult = calculateDuskDawn(date, params.line); + + if (timePointName == "dawn") { + tasks[0].timestamp = sunCalcResult.dawn_time; + } + else if (timePointName == "dusk") { + tasks[0].timestamp = sunCalcResult.dusk_time; + } + else if (timePointName == "luxOn") { + tasks[0].timestamp = sunCalcResult.dusk_time + params.dusk_lux_sensor_time_window * 60000; + } + else if (timePointName == "luxOff") { + tasks[0].timestamp = sunCalcResult.dawn_time + params.dawn_lux_sensor_time_window * 60000; + } + else if (timePointName == "profileTimepoint") { + tasks[0].timestamp = currentTimestamp + tasks[0].addMinutesToTimestamp * 60000; + } + + let info = "aplikovany bod profilu"; + let onOrOff = ""; + value == 1 ? onOrOff = "on" : onOrOff = "off"; + + turnLine(onOrOff, params.line, info); + + interval = setInterval(runTasks, SHORT_INTERVAL); + return; + } + + //zhodeny hlavny istic + let disconnected = false; + //if(rotary_switch_state == "Off") disconnected = true; + + //state_of_breaker[line] - alebo istic linie + 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" }; + + 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; + + if (!disconnectedReport[tbname]) { + sendTelemetry(values, tbname) + } + + interval = setInterval(runTasks, SHORT_INTERVAL); + + return; + } + + disconnectedReport[tbname] = false; + + const register = params.register; + + //high_priority + if (!SETTINGS.masterNodeIsResponding) { + //ak neodpoveda, nebudeme vykonavat ziadne commands, okrem cmd-terminal, a fw version + errorHandler.sendMessageToService("Master node is not responding"); + + let stop = true; + + //fw version - register == 4 + if (type == "cmd-terminal" || register == 4) stop = false; + if (stop) { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + } + + let contactorStatus = 1; + if (relaysData[line] != undefined) contactorStatus = relaysData[line].contactor; + + if (line == 0 || contactorStatus == 0) { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + // TODO: -> status offline for rvo if rotary_switch_state is OFF, this is source of errors + // + // let relayStatus = 1; + // if (relaysData[line] != undefined) { + // relayStatus = relaysData[line].contactor; + // } + + // if (line == 0) relayStatus = 0; + // if (type == "cmd-terminal") relayStatus = 1; + + // //check if rotary_switch_state == "Off" + // if (relayStatus == 0) { + // console.log("------------------------------------relayStatus", relayStatus, line); + // let values = { "status": "OFFLINE" }; + + // if(tbname) sendTelemetry(values, tbname) + + // interval = setInterval(runTasks, SHORT_INTERVAL); + // return; + // } + + if (!rsPort.isOpen) { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + //RE-CALCULATE VALUES + //set actual time for broadcast + if (register == 87 && params.recipient === 2) { + var d = new Date(); + params.byte1 = d.getHours();//h + params.byte2 = d.getMinutes();//m + params.byte3 = 0;//s + params.byte4 = 0; + } + + //SET DUSK/DAWN FOR BROADCAST + //Time of dusk + if (register == 6 && params.recipient === 2) { + + if (type != "cmd-terminal") { + let sunCalcResult = calculateDuskDawn(); + params.byte1 = sunCalcResult["dusk_hours"];//h + params.byte2 = sunCalcResult["dusk_minutes"];//m + params.byte3 = 0;//s + params.byte4 = 0; + + //TODO astrohodiny + let dusk = "Time of dusk: " + sunCalcResult["dusk"]; + } + } + + //Time of dawn + if (register == 7 && params.recipient === 2) { + if (type != "cmd-terminal") { + let sunCalcResult = calculateDuskDawn(); + params.byte1 = sunCalcResult["dawn_hours"];//h + params.byte2 = sunCalcResult["dawn_minutes"];//m + params.byte3 = 0;//s + params.byte4 = 0; + + //TODO astrohodiny + let dawn = "Time of dawn: " + sunCalcResult["dawn"]; + } + + } + //----------------------- + + instance.send(SEND_TO.debug, "address: " + node + " register:" + register + "type: " + 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(node, params.recipient, params.rw, register, params.name, params.byte1, params.byte2, params.byte3, params.byte4); + let readBytes = 11; + let timeout = 4000; + + // await keyword is important, otherwise incorrect data is returned! + 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); + + //ak sa odpoved zacina 0 - je to v poriadku, inak je NOK + let message = result.message; // OK, NOK + let message_type = result.type; + let error = result.error; + + if (params.debug != "generated cmd") { + //debug("writeData: done " + message_type + " duration: " + timeDiff + " message_type: " + params.debug, params); + } + + // 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); + // } + // } + + //debug("writeData: done " + message_type + " duration: " + timeDiff + " message_type: " + params.debug); + //debug("writeData done", message_type, "duration", timeDiff, "message_type", params.debug, result); + + let values = {}; + + //CMD FINISHED + if (message == "OK") { + + updateNodeStatus(node, true); + + //write + if (type == "set_node_profile") { + let result = cmdCounterResolve(node); + if (result == 0) { + dbNodes.modify({ processed: true }).where("node", node).make(function(builder) { + builder.callback(function(err, response) { + + sendNotification("CMD Manager: process cmd", SETTINGS.rvoTbName, "dimming_profile_was_successfully_received_by_node", { node: node }, "", SEND_TO.tb, instance); + + logger.debug("--> profil úspešne odoslaný na node č. " + node); + nodesData[node].processed = true; + nodeProfileSendFail.delete(node); + }); + }); + } + } + + //parse read response + if (params.rw == 0) { + values = processResponse(register, dataBytes); //read + } + + if (itIsNodeCommand) { + values.comm_status = "OK"; + values.status = "OK"; + } + + //master node + if (node == 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; + } + + //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.debug) { + //logger.debug("saveToTb", saveToTb, tbname, values); + } + + if (saveToTb) { + sendTelemetry(values, tbname) + } + else { + if (type == "cmd-terminal") { + terminalCommandResponse(params, "SUCCESS", data); + } + } + + } + else { + + terminalCommandResponse(params, "ERROR", data) + handleNokResponseOnRsPort("handleNOK else block", params, itIsNodeCommand, saveToTb); + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + //logger.debug("writeData err: ", error, result, params); + logger.debug("writeData err: ", tbname, node, register, values); + } + } + + //logger.debug(error, result, params); + } + }).catch(function(reason) { + + console.log("writeData catch exception", reason); + instance.send(SEND_TO.debug, reason); + + terminalCommandResponse(params, "FAILURE", null, reason); + handleNokResponseOnRsPort("handleNOK catch block", params, itIsNodeCommand, saveToTb); + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + logger.debug("-->WRITE FAILED: " + reason, params.debug, params); + } + } + + }); + + } + 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); + } + + + function handleNokResponseOnRsPort(message, params, itIsNodeCommand, saveToTb) { + + let node = params.address; + let register = params.register; + let type = params.type; + let tbName = params.tbname; + if (!tbName) return; + + let values = {}; + + // console.log(message); + let updateStatus = updateNodeStatus(node, false); + + //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; + + if (register == 4) values["master_node_version"] = "NOK"; + } + + if (type == "set_node_profile") { + delete cmdCounter[node]; + logger.debug("profil nebol úspešne odoslaný na node č. ", params); + + if (!nodeProfileSendFail.has(node)) { + sendNotification("CMD Manager: process cmd", tbName, "configuration_of_dimming_profile_to_node_failed", { node: node }, "", SEND_TO.tb, instance); + nodeProfileSendFail.add(node); + } + } + + if (itIsNodeCommand) { + values.comm_status = "NOK"; + } + + 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); + }); + }); + + 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); + + instance.send(SEND_TO.debug, err.message); + }); + + rsPort.on("close", () => { + setTimeout(() => rsPort.open(), 1000); + }); + + 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.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(); + return; + } + else if (flowdata.data == "close") { + rsPort.close(); + return; + } + else if (flowdata.data == "clean") { + tasks = []; + return; + } + else if (flowdata.data == "buildtasks") { + //build & run + return; + } + else if (flowdata.data == "run") { + //durations = []; + + if (tasks.length == 0) { + + buildTasks(); + + if (rsPort.isOpen) { + interval = setInterval(runTasks, 100); + } + else { + instance.send(SEND_TO.debug, "port is not opened!!!"); + } + } + } + else { + //terminal data - object + //logger.debug("flowdata", flowdata.data); + + if (typeof flowdata.data === 'object') { + //logger.debug("dido", flowdata.data); + if (flowdata.data.hasOwnProperty("sender")) { + //data from dido_controller + if (flowdata.data.sender == "dido_controller") { + + if (flowdata.data.hasOwnProperty("cmd")) { + let cmd = flowdata.data.cmd; + + if (cmd == "buildTasks") { + clearInterval(interval); + + logger.debug("-->CMD MANAGER - BUILD TASKS"); + buildTasks(); + + //logger.debug("tasks:"); + //logger.debug(tasks); + + logger.debug("-->CMD MANAGER - RUN TASKS"); + interval = setInterval(runTasks, LONG_INTERVAL); + } + else if (cmd == "reload_relays") { + loadRelaysData(flowdata.data.line); + + if (flowdata.data.dataChanged) { + if (!flowdata.data.value) { + reportOfflineNodeStatus(flowdata.data.line); + } + else { + reportOnlineNodeStatus(flowdata.data.line); + } + } + + } + else if (cmd == "rotary_switch_state") { + let value = flowdata.data.value; + + //state was changed + if (rotary_switch_state != value) { + if (value == "Off") { + //vyreportovat vsetky svietdla + reportOfflineNodeStatus(); + } + + rotary_switch_state = value; + } + } + 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) { + + // we send lux_sensor value to all nodes: + let params = getParams(PRIORITY_TYPES.node_broadcast); + + params.recipient = 2;//2 broadcast, address = 0 + params.address = 0xffffffff;//Broadcast + + let ba = longToByteArray(lux_sensor); + + params.byte3 = ba[1];//msb + params.byte4 = ba[0]; + params.timestamp = PRIORITY_TYPES.node_broadcast; + params.info = "run broadcast: Actual Lux level from cabinet"; + params.register = 95;//Actual Lux level from cabinet + params.rw = 1;//write + + tasks.push(params); + + //process profiles + turnOnOffLinesAccordingToLuxSensor(lux_sensor); + } + } + else if (cmd == "state_of_breaker") { + //istic linie + let value = flowdata.data.value; + let line = parseInt(flowdata.data.line); + + let dataChanged = false; + if (state_of_breaker[line] != value) dataChanged = true; + + state_of_breaker[line] = value; + + let status = "OK"; + if (value == "Off") status = "NOK"; + + if (dataChanged) { + + 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"); + + //report status liniu + sendTelemetry({ status: status }, tbname) + + //current value + if (value == "Off") reportOfflineNodeStatus(line); //vyreportovat vsetky svietidla na linii + } + + } + } + else { + logger.debug("undefined cmd", cmd); + } + } + } + + return; + } + + //data from worksys + 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 command = data.params.command; + let method = data.method; + let profile = data.params.payload; + if (profile == undefined) profile = ""; + let entity = data.params.entities[0]; + let entity_type = entity.entity_type; + let tbname = entity.tb_name; + + instance.send(SEND_TO.debug, flowdata.data); + 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") { + + //let command = data.params.command; + let value = data.params.payload.value; + + if (command == "dimming") { + + let nodeWasFound = false; + let keys = Object.keys(nodesData); + + //logger.debug("-----", keys); + + 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); + + 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; + + //ak linia je + + //debug(params); + logger.debug("dimming", params); + + tasks.push(params); + + 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); + + 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); + } + + //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; + + tasks.push(params); + } + + //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; + + tasks.push(params); + } + + //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; + + tasks.push(params); + } + + }, 4000); + + + nodeWasFound = true; + + break; + } + } + + if (!nodeWasFound) { + logger.debug("set dimming from platform", "unable to find tbname", tbname); + } + } + else { + instance.send(SEND_TO.debug, "undefined command " + command); + logger.debug("undefined command", command); + } + + return; + } + 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++) { + let node = keys[i]; + if (tbname == nodesData[node].tbname) { + + 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"); + + //profil úspešne prijatý pre node č. xx + 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; + + processNodeProfile(node); + }); + }); + } + } + } + else { + + instance.send(SEND_TO.debug, "unknown method " + method); + logger.debug("unknown method", method); + + return; + } + } + + //nastav profil linie z platformy + 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") { + + 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++) { + let line = keys[i]; + if (tbname == relaysData[line].tbname) { + //zmazeme tasky + 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) { + + //update profile + 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); + + }); + }); + break; + } + } + } + else if (method == "set_command") { + let value = data.params.payload.value; + + 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; + + 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"); + } + } + else { + instance.send(SEND_TO.debug, "undefined method " + method); + logger.debug("undefined method", method); + } + + return; + } + else { + instance.send(SEND_TO.debug, "UNKNOW entity_type " + entity_type); + logger.debug("UNKNOW entity_type", entity_type); + } + return; + } + + //terminal + if (!rsPort.isOpen) await rsPort.open(); + + let params = flowdata.data.body; + if (params == undefined) { + //logger.debug("CMD manager flowdata.data.body is undefined"); + return; + } + + params.priority = PRIORITY_TYPES.terminal; + params.type = "cmd-terminal"; + params.tbname = ""; + params.timestamp = PRIORITY_TYPES.terminal; + params.addMinutesToTimestamp = 0;// do not repeat task!!! + params.debug = true; + + let timestamp = Date.now(); + params.refFlowdataKey = timestamp; + //params.refFlowdata = flowdata; + //refFlowdata = flowdata; + + //console.log("flowdata", flowdata); + + cleanUpRefFlowdataObj(); + + refFlowdataObj[timestamp] = flowdata; + + //fix + //params.address = params.adress; + logger.debug("received from terminal", params); + logger.debug("date/time:", new Date()); + logger.debug("tasks length:", tasks.length); + + //tasks = []; + + //add to tasks + tasks.push(params); + + } + } + }) + + + //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) + } + + + /** + * 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; + + RESTBuilder.make(function(builder) { + + if (!builder) return; + + builder.method('GET'); + builder.url('http://192.168.252.2:8004/gettime?projects_id=1'); + + builder.callback(function(err, response, output) { + + 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); + } + + }); + } + + } 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); + + } else { + //console.log("Read-only", stdout); + + 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]: [ + { + "ts": date, + "values": values + } + ] + } + + 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); + } + + //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); + } + } + + 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; + } + + //Dimming, CCT + if (register == 1) { + let brightness = 0; + let dimming = byte0; + if (dimming > 128) { + //dimming = -128; + brightness = dimming - 128; + } + + //cct + //Ak Byte3 == 1: CCT = (Byte2*256)+Byte1 + let cct; + if (byte3 == 1) cct = byte2 * 256 + byte1; + else cct = bytesToInt(bytes.slice(0, 3)); + + //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; + } + + 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, 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 + ")"; + } + + 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; + + } + + function getObjectByTbValue(object, tbname) { + return object[Object.keys(object).find(key => object[key].tbname === tbname)]; + } + + function isObject(item) { + return (typeof item === "object" && !Array.isArray(item) && item !== null); + } + +} // end of instance.export + diff --git a/RVO13/flow_3_2_25/code.js b/RVO13/flow_3_2_25/code.js new file mode 100755 index 0000000..63b31bf --- /dev/null +++ b/RVO13/flow_3_2_25/code.js @@ -0,0 +1,90 @@ +exports.id = 'code'; +exports.title = 'Code'; +exports.group = 'Common'; +exports.color = '#656D78'; +exports.input = true; +exports.output = 1; +exports.author = 'Peter Širka'; +exports.icon = 'code'; +exports.version = '1.2.0'; +exports.options = { outputs: 1, code: 'send(0, value);', keepmessage: true }; + +exports.html = `
+
+
+
@(Number of outputs)
+
@(Minimum is 1)
+
+
+
@(Code)
+
@(Keep message instance)
+
+`; + +exports.readme = `# Code + +This component executes custom JavaScript code as it is and it doesn't contain any secure scope. + +\`\`\`javascript +// value {Object} contains received data +// send(outputIndex, newValue) sends a new value +// error(value) sends an error +// instance {Object} a current component instance +// flowdata {Object} a current flowdata +// repository {Object} a current repository of flowdata +// Example: + +// send() can be execute multiple times +send(0, value); +\`\`\``; + +exports.install = function(instance) { + + var fn; + + instance.on('data', function(response) { + if (fn) { + try { + fn(response.data, instance, response, instance.options, response.repository, require); + } catch (e) { + response.data = e; + instance.throw(response); + } + } + }); + + instance.reconfigure = function() { + try { + if (instance.options.code) { + instance.status(''); + var code = 'var send = function(index, value) { if (options.keepmessage) { flowdata.data = value; instance.send2(index, flowdata); } else instance.send2(index, value);}; var error = function(err) { instance.throw(err); }; ' + instance.options.code; + fn = new Function('value', 'instance', 'flowdata', 'options', 'repository', 'require', code); + } else { + instance.status('Not configured', 'red'); + fn = null; + } + } catch (e) { + fn = null; + instance.error('Code: ' + e.message); + } + }; + + instance.on('options', instance.reconfigure); + instance.reconfigure(); +}; \ No newline at end of file diff --git a/RVO13/flow_3_2_25/comment.js b/RVO13/flow_3_2_25/comment.js new file mode 100755 index 0000000..1e0cd13 --- /dev/null +++ b/RVO13/flow_3_2_25/comment.js @@ -0,0 +1,11 @@ +exports.id = 'comment'; +exports.title = 'Comment'; +exports.group = 'Common'; +exports.color = '#704cff'; +exports.author = 'Martin Smola'; +exports.icon = 'comment'; +exports.traffic = false; +exports.version = '1.0.0'; +exports.readme = '# Comment'; + +exports.install = function() {}; diff --git a/RVO13/flow_3_2_25/db_connector.js b/RVO13/flow_3_2_25/db_connector.js new file mode 100755 index 0000000..65ee94b --- /dev/null +++ b/RVO13/flow_3_2_25/db_connector.js @@ -0,0 +1,286 @@ +exports.id = 'db_connector'; +exports.title = 'DbConnector'; +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.html = `
+
+
+
DbConnector
+
+
+
`; + +exports.readme = `# read/write data to tables`; + +const instanceSendTo = { + debug: 0, + http_response: 1, +} + +const { promisifyBuilder, makeMapFromDbResult } = require('./helper/db_helper.js'); + +function extractWhereParams(params) +{ + let name = params[0]; + let operator = '='; + let value = params[1]; + + if(params.length == 3) + { + operator = params[1]; + value = params[2]; + } + + return {name: name, operator: operator, value: value}; +} + +exports.install = function(instance) { + + let refFlowdata = null;//holds reference to httprequest flowdata + + instance.on("close", () => { + + }) + + + instance.on("data", async function(flowdata) { + + let params = flowdata.data.body; + console.log("DbConnector", params); + + refFlowdata = flowdata; + + if(refFlowdata != undefined) + { + //make http response + let responseObj = {}; + responseObj["type"] = "SUCESS"; + + try{ + + let table = params.table; + let action = params.action; + + + if(params.data != undefined) + { + let className = params.data.className; + + if(className == "SqlQueryBuilder") + { + let type = params.data.type; + + console.log("SqlQueryBuilder---->", params.data); + + if(type == "SELECT") + { + let table = params.data.queryData.tables[0].table; + + const db = TABLE(table); + var builder = db.find(); + + let result = await promisifyBuilder(builder); + + let response = {}; + response["result"] = result; + response["success"] = true; + + responseObj["data"] = response; + + //console.log(responseObj); + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + } + + return; + } + } + + + console.log("db_connector---->", table, action); + + //actions: read, replace, insert, delete, update... + + if(action == "read") + { + const db = TABLE(params.table); + + //where builder.where('age', '<', 15); + //builder.where('id', 3403); + + var builder = db.find(); + + //https://docs.totaljs.com/latest/en.html#api~DatabaseBuilder~builder.where + if(params.hasOwnProperty("where")) + { + //optionalCan contain "=", "<=", "<", ">=", ">". + //Default value: '=' + + //1.["production_line", 1] + //2. ["or", ["production_line", 1], ["production_line", 2], "end"] + + if (Array.isArray(params.where)) { + + let multipleConditions = false; + + if(params.where[0] == "or") multipleConditions = true; + if (Array.isArray(params.where[0])) multipleConditions = true; + + if(multipleConditions) + { + + for(var i = 0; i < params.where.length; i++) + { + const item = params.where[i]; + + if(item === "or") builder.or(); + + if (Array.isArray(item)) + { + const { name, operator, value } = extractWhereParams(item); + builder.where(name, operator, value); + } + + if(item === "end") builder.end(); + + } + + } + else + { + const { name, operator, value } = extractWhereParams(params.where); + builder.where(name, operator, value); + } + + } + + /* + if(params.where.length >=2 ) + { + let name = params.where[0]; + let operator = '='; + let value = params.where[1]; + + if(params.where.length == 3) + { + operator = params.where[1]; + value = params.where[2]; + } + + builder.where(name, operator, value); + } + */ + } + + if(params.hasOwnProperty("between")) + { + builder.between(params.between[0], params.between[1], params.between[2]); + } + + let response = await promisifyBuilder(builder); + responseObj["data"] = response; + + //console.log(responseObj); + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + + return; + } + + if(action == "delete") + { + + } + + + if(action == "update") + { + //! data receiving from terminal (params) + // { + // hostname: 'localhost', + // table: 'settings', + // action: 'update', + // body: { + // rvo_name: 'terrrr', + // lang: 'en', + // temperature_adress: '28.427B45920702', + // latitude: 48.70826502, + // longitude: 17.28455203, + // mqtt_host: '192.168.252.4', + // mqtt_clientid: 'showroom_test_panel_led', + // mqtt_username: 'xmRd6RJxW53WZe4vMFLU', + // mqtt_port: 1883, + // maintanace_mode: false + // } + // } + const tableToModify = TABLE(params.table); + const newValues = params.body; + + tableToModify.modify(newValues).make(function(builder) { + + builder.callback(function(err, response) { + + if(!err) + { + responseObj["data"] = response; + responseObj["tableUpdated"] = true; + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + } + }); + }); + + } + + if(action == "replace") + { + //truncate table + const db = TABLE(params.table); + var builder = db.remove(); + db.clean(); + + //insert data + let data = params.data; + + for(let i = 0; i < data.length; i++) + { + //console.log(data[i]); + db.insert(data[i]); + } + + console.log("insert done"); + + let responseObj = {}; + responseObj["type"] = "SUCESS"; + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + + + } + + + + } catch (error) { + //console.log(error); + responseObj["type"] = "ERROR"; + responseObj["message"] = error; + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + } + } + }) +} + + diff --git a/RVO13/flow_3_2_25/db_init.js b/RVO13/flow_3_2_25/db_init.js new file mode 100755 index 0000000..ddd0aa0 --- /dev/null +++ b/RVO13/flow_3_2_25/db_init.js @@ -0,0 +1,106 @@ +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 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 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.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 : "2025-01-09", //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"], + phases: responseSettings[0]["phases"], + cloud_topic: responseSettings[0]["cloud_topic"], + + //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/RVO13/flow_3_2_25/debug.js b/RVO13/flow_3_2_25/debug.js new file mode 100755 index 0000000..00cb259 --- /dev/null +++ b/RVO13/flow_3_2_25/debug.js @@ -0,0 +1,100 @@ +exports.id = 'debug'; +exports.title = 'Debug'; +exports.author = 'Peter Širka'; +exports.color = '#967ADC'; +exports.click = true; +exports.input = true; +exports.icon = 'bug'; +exports.version = '2.0.4'; +exports.options = { enabled: true, repository: false, type: 'data' }; +exports.readme = `# Debug + +Prints data to the debug tab.`; + +exports.html = `
+
+
+
@(Output type)
+
@(Path to the property (leave empty to show the whole data object))
+
@(A group name)
+
@(Enabled)
+
+
+
`; + +exports.install = function(instance) { + + instance.on('data', function(response) { + if (instance.options.enabled) { + + var opt = instance.options; + var rep = response.repository; + var val = response.data; + var id = response.id; + + switch (instance.options.type){ + case 'both': + var data = {}; + data.repository = rep; + data.data = val instanceof Error ? { error: val.message, stack: val.stack } : val; + instance.debug(safeparse(opt.property ? U.get(data, opt.property) : data), undefined, opt.group, id); + break; + case 'repository': + instance.debug(safeparse(opt.property ? U.get(rep, opt.property) : rep), undefined, opt.group, id); + break; + case 'data': + default: + if (val instanceof Error) + instance.debug({ error: val.message, stack: val.stack }, undefined, opt.group, id); + else + instance.debug(safeparse(opt.property ? U.get(val, opt.property) : val), undefined, opt.group, id); + break; + } + } + }); + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + instance.save(); + }); + + instance.on('options', function() { + instance.custom.status(); + }); + + instance.custom.status = function() { + instance.status(instance.options.enabled ? 'Enabled' : 'Disabled'); + }; + + instance.custom.status(); + + function safeparse(o) { + + if (o instanceof Buffer) + return o; + + if (o === undefined) + return 'undefined'; + + if (o === null) + return 'null'; + + var cache = []; + var str = JSON.stringify(o, function(key, value) { + if (typeof value === 'object' && value !== null) { + if (cache.indexOf(value) !== -1) { + try { + return JSON.parse(JSON.stringify(value)); + } catch (error) { + return; + } + } + cache.push(value); + } + return value; + }); + cache = null; + return JSON.parse(str); + } +}; diff --git a/RVO13/flow_3_2_25/designer.json b/RVO13/flow_3_2_25/designer.json new file mode 100755 index 0000000..3af15b8 --- /dev/null +++ b/RVO13/flow_3_2_25/designer.json @@ -0,0 +1,2846 @@ +{ + "tabs": [ + { + "name": "MAIN PUSH", + "linker": "main-push", + "id": "1612772287426", + "index": 0 + }, + { + "name": "CMD manager", + "linker": "cmd-manager", + "id": "1615551125555", + "index": 1 + }, + { + "name": "Devices", + "linker": "devices", + "id": "1611921777196", + "index": 2 + } + ], + "components": [ + { + "id": "1611951142547", + "component": "debug", + "tab": "1611921777196", + "name": "ERROR", + "x": 598, + "y": 60, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#DA4453", + "notes": "" + }, + { + "id": "1612776786008", + "component": "wsmqttpublish", + "tab": "1612772287426", + "name": "WS MQTT publish", + "x": 304.75, + "y": 237, + "connections": { + "0": [ + { + "index": "0", + "id": "1615551060773" + } + ], + "1": [ + { + "index": "0", + "id": "1618300858252" + }, + { + "index": "0", + "id": "1618558465485" + } + ], + "2": [ + { + "index": "0", + "id": "1618300863816" + }, + { + "index": "0", + "id": "1634303685503" + } + ], + "3": [ + { + "index": "0", + "id": "1731068754606" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Connected", + "color": "green" + }, + "options": { + "username": "", + "clientid": "", + "port": "1883", + "host": "" + }, + "color": "#888600", + "notes": "" + }, + { + "id": "1612778461252", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "tb-push", + "x": 86.75, + "y": 375, + "connections": { + "0": [ + { + "index": "0", + "id": "1612783322136" + }, + { + "index": "1", + "id": "1612776786008" + }, + { + "index": "0", + "id": "1731068754606" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1612783322136", + "component": "debug", + "tab": "1612772287426", + "name": "to TB", + "x": 306.75, + "y": 371, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615551060773", + "component": "debug", + "tab": "1612772287426", + "name": "errors from MQTT Broker", + "x": 650, + "y": 76, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#DA4453", + "notes": "" + }, + { + "id": "1615563373927", + "component": "debug", + "tab": "1615551125555", + "name": "Debug", + "x": 753, + "y": 150, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#DA4453", + "notes": "" + }, + { + "id": "1615566865233", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "tb-push", + "x": 761, + "y": 251, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1615798582262", + "component": "debug", + "tab": "1615551125555", + "name": "CMD_debug", + "x": 765, + "y": 350, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615802995322", + "component": "debug", + "tab": "1611921777196", + "name": "Debug", + "x": 595.8833312988281, + "y": 557.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Disabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": false + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615809128443", + "component": "debug", + "tab": "1611921777196", + "name": "tempToTb", + "x": 598.8833312988281, + "y": 654.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615809595184", + "component": "virtualwireout", + "tab": "1611921777196", + "name": "tb-push", + "x": 594.8833312988281, + "y": 350.25, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1616165795916", + "component": "httproute", + "tab": "1615551125555", + "name": "POST /terminal", + "x": 114, + "y": 546, + "connections": { + "0": [ + { + "index": "0", + "id": "1684060205000" + }, + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Listening", + "color": "green" + }, + "options": { + "timeout": 10, + "cachepolicy": 0, + "cacheexpire": "5 minutes", + "size": 5, + "url": "/terminal", + "method": "POST", + "name": "", + "flags": [ + "id:1616165795916", + "post", + 10000 + ], + "emptyresponse": false + }, + "color": "#5D9CEC", + "notes": "### Configuration\n\n- __POST /terminal__\n- flags: \n- maximum request data length: __5 kB__\n- empty response: __false__\n- cache policy: __no cache__\n- cache expire: __5 minutes__", + "cloning": false + }, + { + "id": "1616165824813", + "component": "httpresponse", + "tab": "1615551125555", + "name": "HTTP Response", + "x": 772, + "y": 443, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "json" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1617104731852", + "component": "debug", + "tab": "1615551125555", + "name": "DIDO_Debug", + "x": 669, + "y": 1040, + "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": "turnOff line", + "x": 88, + "y": 1158, + "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": 669, + "y": 1150, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1617284749681", + "component": "trigger", + "tab": "1615551125555", + "name": "update profile / node", + "x": 112, + "y": 215, + "connections": { + "0": [ + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "string", + "data": "profile_nodes" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1618235171399", + "component": "trigger", + "tab": "1615551125555", + "name": "tun tasks", + "x": 119, + "y": 280, + "connections": { + "0": [ + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "data": "run" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1618300858252", + "component": "debug", + "tab": "1612772287426", + "name": "wsmqtt-exit1", + "x": 650.8833312988281, + "y": 160, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1618300863816", + "component": "debug", + "tab": "1612772287426", + "name": "wsmqtt-exit2", + "x": 845.8833312988281, + "y": 320, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1618393583970", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "to-cmd-manager", + "x": 668.8833312988281, + "y": 1269, + "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": 119.88333129882812, + "y": 369, + "connections": { + "0": [ + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "platform-rpc-call", + "color": "gray" + }, + "options": { + "wirename": "platform-rpc-call" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1618393759854", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "cmd_to_dido", + "x": 93.88333129882812, + "y": 1007, + "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": 779.8833312988281, + "y": 552, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "cmd_to_dido", + "color": "gray" + }, + "options": { + "wirename": "cmd_to_dido" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1618558465485", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "platform-rpc-call", + "x": 649.8833312988281, + "y": 246, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "platform-rpc-call", + "color": "gray" + }, + "options": { + "wirename": "platform-rpc-call" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1618572059773", + "component": "trigger", + "tab": "1615551125555", + "name": "turnOn line", + "x": 89, + "y": 1085, + "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": 452.1091003417969, + "y": 341.05455017089844, + "connections": { + "0": [ + { + "index": "0", + "id": "1615563373927" + } + ], + "1": [ + { + "index": "0", + "id": "1615566865233" + }, + { + "index": "0", + "id": "1615798582262" + } + ], + "2": [ + { + "index": "0", + "id": "1616165824813" + } + ], + "3": [ + { + "index": "0", + "id": "1618393827655" + } + ], + "4": [ + { + "index": "0", + "id": "1635936391935" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1619605019281", + "component": "httproute", + "tab": "1615551125555", + "name": "GET db", + "x": 115, + "y": 651, + "connections": { + "0": [ + { + "index": "0", + "id": "1684060205000" + }, + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Listening", + "color": "green" + }, + "options": { + "timeout": 5, + "cachepolicy": 0, + "cacheexpire": "5 minutes", + "size": 5, + "url": "/db", + "method": "GET", + "name": "", + "flags": [ + "id:1619605019281", + "get", + 5000 + ] + }, + "color": "#5D9CEC", + "notes": "### Configuration\n\n- __GET /db__\n- flags: undefined\n- maximum request data length: __5 kB__\n- empty response: __undefined__\n- cache policy: __no cache__\n- cache expire: __5 minutes__", + "cloning": false + }, + { + "id": "1619784672383", + "component": "trigger", + "tab": "1615551125555", + "name": "turnOnAlarm", + "x": 85, + "y": 1231, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "data": "{command: \"turnOnAlarm\"}", + "datatype": "object" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1619784812964", + "component": "trigger", + "tab": "1615551125555", + "name": "turnOffAlarm", + "x": 84, + "y": 1304, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "data": "{command: \"turnOffAlarm\"}", + "datatype": "object" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1621340721628", + "component": "virtualwireout", + "tab": "1611921777196", + "name": "modbus_to_dido", + "x": 596, + "y": 462, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "modbus_to_dido", + "color": "gray" + }, + "options": { + "wirename": "modbus_to_dido" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1622640022885", + "component": "httproute", + "tab": "1615551125555", + "name": "POST /db_connector", + "x": 98, + "y": 1586, + "connections": { + "0": [ + { + "index": "0", + "id": "1622640073521" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Listening", + "color": "green" + }, + "options": { + "timeout": 5, + "cachepolicy": 0, + "cacheexpire": "5 minutes", + "size": 5, + "url": "/db_connector", + "method": "POST", + "flags": [ + "id:1622640022885", + "post", + 5000 + ] + }, + "color": "#5D9CEC", + "notes": "### Configuration\n\n- __POST /db_connector__\n- flags: \n- maximum request data length: __5 kB__\n- empty response: __undefined__\n- cache policy: __no cache__\n- cache expire: __5 minutes__", + "cloning": false + }, + { + "id": "1622640073521", + "component": "db_connector", + "tab": "1615551125555", + "name": "DbConnector", + "x": 372, + "y": 1572, + "connections": { + "1": [ + { + "index": "0", + "id": "1622641420685" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "edge": "undefined" + }, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1622641420685", + "component": "httpresponse", + "tab": "1615551125555", + "name": "HTTP Response", + "x": 596, + "y": 1586, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1634303504177", + "component": "monitormemory", + "tab": "1612772287426", + "name": "RAM", + "x": 69.88333129882812, + "y": 885.5, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465281992" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "799.50 MB / 987.80 MB", + "color": "gray" + }, + "options": { + "enabled": true, + "interval": 30000 + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1634303533779", + "component": "monitordisk", + "tab": "1612772287426", + "name": "disk", + "x": 70.88333129882812, + "y": 982.5, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465821120" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "5.73 GB / 7.26 GB", + "color": "gray" + }, + "options": { + "enabled": true, + "path": "/", + "interval": 30000 + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1634303595494", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "send-to-services", + "x": 51.883331298828125, + "y": 1400.5, + "connections": { + "0": [ + { + "index": "0", + "id": "1634463186563" + }, + { + "index": "1", + "id": "1634488120710" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1634303602169", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "send-to-services", + "x": 426.8833312988281, + "y": 878.5, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1634303685503", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "send-to-services", + "x": 650.8833312988281, + "y": 355.5, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1634303743260", + "component": "httprequest", + "tab": "1612772287426", + "name": "192.168.252.2:8004/sentmessage", + "reference": "", + "x": 480.8833312988281, + "y": 1334.7333374023438, + "connections": { + "0": [ + { + "index": "0", + "id": "1635327431236" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "stringify": "json", + "method": "POST", + "url": "http://192.168.252.2:8004/sentmessage" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1634463186563", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 280.75, + "y": 1446, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634464580289", + "component": "code", + "tab": "1612772287426", + "name": "Code", + "x": 253, + "y": 788, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465243324" + }, + { + "index": "0", + "id": "1634303602169" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "keepmessage": true, + "code": "let response = {};\nresponse.cpu = value.cpu;\nresponse.uptime = value.uptime;\n\nsend(0, response);", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1634465243324", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 428, + "y": 784, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634465281992", + "component": "code", + "tab": "1612772287426", + "name": "Code", + "x": 242, + "y": 884, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465338103" + }, + { + "index": "0", + "id": "1634303602169" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "keepmessage": true, + "code": "value.sender = \"ram\";\n//let total = value.total/1024/1024;\n//let free = value.free/1024/1024;\n//let used = value.used/1024/1024;\nlet response = {};\n//value.memory_total = (total).toFixed(0) + ' MB';\n//value.memory_free = (free).toFixed(0) + ' MB';\n//value.memory_used = (used).toFixed(0) + ' MB';\n\nresponse.memory_total = value.total;\nresponse.memory_free = value.free;\nresponse.memory_used = value.used;\n\nsend(0, response);", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1634465338103", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 429, + "y": 976, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634465821120", + "component": "code", + "tab": "1612772287426", + "name": "Code", + "x": 245, + "y": 978, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465892500" + }, + { + "index": "0", + "id": "1634303602169" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "keepmessage": true, + "code": "value.sender = \"hdd\";\n//let total = value.total/1024/1024;\n//let free = value.free/1024/1024;\n//let used = value.used/1024/1024;\nlet response = {};\n//value.hdd_total = (total).toFixed(0) + ' MB';\n//value.hdd_free = (free).toFixed(0) + ' MB';\n//value.used = (used).toFixed(0) + ' MB';\n\nresponse.hdd_total = value.total;\nresponse.hdd_free = value.free;\nresponse.hdd_used = value.used;\n\nsend(0, response);", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1634465892500", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 432, + "y": 1068, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634484067516", + "component": "debug", + "tab": "1612772287426", + "name": "Send info", + "x": 480, + "y": 1441, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634488120710", + "component": "infosender", + "tab": "1612772287426", + "name": "Info sender", + "x": 285, + "y": 1338, + "connections": { + "0": [ + { + "index": "0", + "id": "1634484067516" + }, + { + "index": "0", + "id": "1634303743260" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "edge": "undefined" + }, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1635327431236", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 795.8833312988281, + "y": 1329.5, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1635936391935", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "send-to-services", + "x": 778, + "y": 656, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1637069803394", + "component": "monitorconsumption", + "tab": "1612772287426", + "name": "CPU", + "x": 69, + "y": 791, + "connections": { + "0": [ + { + "index": "0", + "id": "1634464580289" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "0.9% / 59.33 MB", + "color": "gray" + }, + "options": { + "monitorfiles": true, + "monitorconnections": true, + "monitorsize": true, + "monitorconsumption": true, + "enabled": true, + "interval": 30000 + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1683664161036", + "component": "debug", + "tab": "1615551125555", + "name": "CMDtoDIDO", + "x": 392, + "y": 1012, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1683981346282", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "from-dido-controller", + "x": 113, + "y": 456, + "connections": { + "0": [ + { + "index": "0", + "id": "1684055037116" + }, + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "from-dido-controller", + "color": "gray" + }, + "options": { + "wirename": "from-dido-controller" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1684055037116", + "component": "debug", + "tab": "1615551125555", + "name": "from dido to cmd", + "x": 448, + "y": 519, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1684060205000", + "component": "debug", + "tab": "1615551125555", + "name": "HTTP routes", + "x": 447, + "y": 620, + "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": "MDBToDido", + "x": 598, + "y": 147, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1699963668903", + "component": "dido_controller", + "tab": "1615551125555", + "name": "DIDO_Controller", + "x": 397, + "y": 1131, + "connections": { + "0": [ + { + "index": "0", + "id": "1617104731852" + } + ], + "1": [ + { + "index": "0", + "id": "1617104731852" + }, + { + "index": "0", + "id": "1617115013095" + } + ], + "2": [ + { + "index": "0", + "id": "1618393583970" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "edge": "undefined" + }, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1699964678894", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "modbus_to_dido", + "x": 96, + "y": 924, + "connections": { + "0": [ + { + "index": "0", + "id": "1699963668903" + }, + { + "index": "0", + "id": "1699964793925" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "modbus_to_dido", + "color": "gray" + }, + "options": { + "wirename": "modbus_to_dido" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1699964793925", + "component": "debug", + "tab": "1615551125555", + "name": "modbusToDido", + "x": 388, + "y": 920, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1699965957410", + "component": "modbus_reader", + "tab": "1611921777196", + "name": "Modbus reader", + "x": 232, + "y": 175, + "connections": { + "0": [ + { + "index": "0", + "id": "1611951142547" + } + ], + "1": [ + { + "index": "0", + "id": "1621340721628" + }, + { + "index": "0", + "id": "1684179110403" + }, + { + "index": "0", + "id": "1717441414646" + } + ], + "2": [ + { + "index": "0", + "id": "1615809595184" + }, + { + "index": "0", + "id": "1714752862828" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1700411878636", + "component": "thermometer", + "tab": "1611921777196", + "name": "Thermometer", + "x": 234.75, + "y": 444, + "connections": { + "0": [ + { + "index": "0", + "id": "1615802995322" + } + ], + "1": [ + { + "index": "0", + "id": "1615809595184" + }, + { + "index": "0", + "id": "1615809128443" + } + ], + "2": [ + { + "index": "0", + "id": "1621340721628" + }, + { + "index": "0", + "id": "1732889185927" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#5CB36D", + "notes": "" + }, + { + "id": "1714752862828", + "component": "debug", + "tab": "1611921777196", + "name": "MDBToTb", + "x": 599, + "y": 257, + "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": 755.0833282470703, + "y": 209, + "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": 966.0833282470703, + "y": 152, + "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": 968.0833282470703, + "y": 268, + "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": 77.75, + "y": 1630, + "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": 296, + "y": 1671, + "connections": { + "0": [ + { + "index": "0", + "id": "1718016086212" + }, + { + "index": "0", + "id": "1718016073501" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Running", + "color": "gray" + }, + "options": { + "name": "rvo_senica_13_10.0.0.123", + "types": "[\"emergency\", \"critical\", \"error\", \"alert\"]", + "message_includes": "[\"is responding again\", \"Flow has been restarted\", \"Node db has changed\"]", + "tag_on_include": "[{\"user_id\":\"U072JE5JUQG\", \"includes\":[\"Electrometer\", \"Twilight sensor\"]}]", + "slack_channel": "C071KN2Q8SK" + }, + "color": "#30E193", + "notes": "" + }, + { + "id": "1718016073501", + "component": "httprequest", + "tab": "1612772287426", + "name": "http://192.168.252.2:8004/slack", + "x": 495, + "y": 1753, + "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": 832, + "y": 1664, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "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": 79, + "y": 1723, + "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": "" + }, + { + "id": "1729855334955", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "platform-rpc-call", + "x": 649.9333343505859, + "y": 541.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "platform-rpc-call", + "color": "gray" + }, + "options": { + "wirename": "platform-rpc-call" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1729855371093", + "component": "debug", + "tab": "1612772287426", + "name": "rpc cloud", + "x": 650.9333343505859, + "y": 451.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1731068658334", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 90.75, + "y": 250, + "connections": { + "0": [ + { + "index": "0", + "id": "1612776786008" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731068754606", + "component": "cloudmqttconnect", + "tab": "1612772287426", + "name": "MQTT client - to senica-prod01", + "x": 304.75, + "y": 474, + "connections": { + "1": [ + { + "index": "0", + "id": "1729855371093" + }, + { + "index": "0", + "id": "1729855334955" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Connected", + "color": "green" + }, + "options": { + "username": "", + "clientid": "", + "port": "2764", + "host": "192.168.252.2", + "topic": "u123" + }, + "color": "#888600", + "notes": "" + }, + { + "id": "1731069001548", + "component": "db_init", + "tab": "1612772287426", + "name": "DB Initialization", + "x": 91.75, + "y": 55.25, + "connections": { + "0": [ + { + "index": "0", + "id": "1731069033416" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#888600", + "notes": "" + }, + { + "id": "1731069033416", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "db-init", + "x": 343.75, + "y": 50.25, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069059135", + "component": "showdb", + "tab": "1612772287426", + "name": "Show db data", + "x": 1121.75, + "y": 814.25, + "connections": { + "0": [ + { + "index": "0", + "id": "1731069079243" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#888600", + "notes": "" + }, + { + "id": "1731069079243", + "component": "debug", + "tab": "1612772287426", + "name": "dbData", + "x": 1315.75, + "y": 853.25, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1731069116691", + "component": "trigger", + "tab": "1612772287426", + "name": "settings", + "x": 911.75, + "y": 710.75, + "connections": { + "0": [ + { + "index": "0", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069131637", + "component": "trigger", + "tab": "1612772287426", + "name": "relaysData", + "x": 832.75, + "y": 775.75, + "connections": { + "0": [ + { + "index": "1", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069137374", + "component": "trigger", + "tab": "1612772287426", + "name": "nodesData", + "x": 747.75, + "y": 840.75, + "connections": { + "0": [ + { + "index": "2", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069179846", + "component": "trigger", + "tab": "1612772287426", + "name": "pinsData", + "x": 803.75, + "y": 899.75, + "connections": { + "0": [ + { + "index": "3", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069192937", + "component": "trigger", + "tab": "1612772287426", + "name": "sample data", + "x": 858.75, + "y": 959.75, + "connections": { + "0": [ + { + "index": "4", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069264443", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 63.75, + "y": 1279, + "connections": { + "0": [ + { + "index": "0", + "id": "1634488120710" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069334626", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "db-init", + "x": 151.88333129882812, + "y": 148, + "connections": { + "0": [ + { + "index": "0", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069548145", + "component": "virtualwirein", + "tab": "1611921777196", + "name": "db-init", + "x": 46.75, + "y": 192, + "connections": { + "0": [ + { + "index": "0", + "id": "1699965957410" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069567152", + "component": "virtualwirein", + "tab": "1611921777196", + "name": "db-init", + "x": 44.75, + "y": 465, + "connections": { + "0": [ + { + "index": "0", + "id": "1700411878636" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731070156936", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "db-init", + "x": 89.88333129882812, + "y": 1381, + "connections": { + "0": [ + { + "index": "2", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731234189516", + "component": "trigger", + "tab": "1612772287426", + "name": "monitor.txt", + "x": 915.75, + "y": 1017.75, + "connections": { + "0": [ + { + "index": "5", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731234189551", + "component": "trigger", + "tab": "1612772287426", + "name": "err.txt", + "x": 966.75, + "y": 1080.75, + "connections": { + "0": [ + { + "index": "6", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1732700042559", + "component": "nodesdb_change_check", + "tab": "1612772287426", + "name": "Nodes DB change check", + "x": 263.8833312988281, + "y": 1993.2333984375, + "connections": { + "0": [ + { + "index": "0", + "id": "1732700071298" + }, + { + "index": "0", + "id": "1732700642917" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#888600", + "notes": "" + }, + { + "id": "1732700057052", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 84.75, + "y": 1994, + "connections": { + "0": [ + { + "index": "0", + "id": "1732700042559" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1732700071298", + "component": "debug", + "tab": "1612772287426", + "name": "nodesChange", + "x": 561.8833312988281, + "y": 2055.2333984375, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1732700642917", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "tb-push", + "x": 557.8833312988281, + "y": 1949, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1732889185927", + "component": "debug", + "tab": "1611921777196", + "name": "tempToDido", + "x": 594.8833312988281, + "y": 745, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1733574412965", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 86.75, + "y": 495, + "connections": { + "0": [ + { + "index": "1", + "id": "1731068754606" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + } + ], + "version": 615 +} \ No newline at end of file diff --git a/RVO13/flow_3_2_25/dido_controller.js b/RVO13/flow_3_2_25/dido_controller.js new file mode 100755 index 0000000..8415921 --- /dev/null +++ b/RVO13/flow_3_2_25/dido_controller.js @@ -0,0 +1,1524 @@ +exports.id = 'dido_controller'; +exports.title = 'DIDO_Controller'; +exports.version = '2.0.0'; +exports.group = 'Worksys'; +exports.color = '#2134B0'; +exports.input = 3; +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 { 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 +} + + +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 = {}; + 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"); + + //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 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 + }; + + + function main() { + + GLOBALS = FLOW.GLOBALS; + SETTINGS = FLOW.GLOBALS.settings; + rvoTbName = SETTINGS.rvoTbName; + pinsData = GLOBALS.pinsData; + relaysData = GLOBALS.relaysData; + + 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"; + + 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, "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; + turnLine("off", 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; + + sendTelemetry(values, rvoTbName); + + 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) { + if (!err) { + monitor.info(exports.title + "--->Digital in_out has been set (runSyncExec was sucessfull)"); + + turnAlarm("off"); + 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() { + + //to keep websocket opened, we send request every 150 seconds + let startRequests = null; + + console.log("handleWebSocket function called"); + ws = new WebSocket('ws:/0.0.0.0:1234/ws'); + + ws.onopen = function open() { + + instance.send(0, exports.title + " running"); + turnAlarm("off"); + + // useTurnOffCounter = true; + // turnOffCounter = relaysData.length - 1; + initialSetting(); + ws.send(JSON.stringify({ "cmd": "all" })); + + // we request dev info about neuron device from evok to keep websocket connection alive + // for some reason this request returns no data, but connection keeps alive + // https://evok.api-docs.io/1.0/mpqzDwPwirsoq7i5A/websocket + startRequests = setInterval(() => { + // console.log(" *** data from evok requested"); + ws.send(JSON.stringify({ "cmd": "filter", "dev": ["neuron"] })); + }, 150000) + }; + + + // 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 = async 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; + + 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) => { + monitor.info('websocket error, reconnect') + instance.send(SEND_TO.debug, err.message); + clearInterval(startRequests); + ws = null; + setTimeout(handleWebSocket, 1000); + }) + + + ws.onclose = function() { + // connection closed, discard old websocket and create a new one in 5s + // stopRequests(); + monitor.info('websocket onclose, reconnect') + clearInterval(startRequests); + ws = null; + console.log("ws is null now, reconnecting..."); + setTimeout(handleWebSocket, 1000); + } + } + + 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 turnAlarm(onOrOff) { + let value = 0; + if (onOrOff == "on") value = 1; + + if (value == 1 && SETTINGS.maintenance_mode) return; + + alarmStatus = "OFF"; + if (value == 1) alarmStatus = "ON"; + + if (rsPort) { + let arr = [0x55]; + arr.push(13); + arr.push(0); + arr.push(value); + + rsPort.write(Buffer.from(arr), function(err) { + logger.debug(`sirena - ${onOrOff}`); + }); + } + else if (ws) { + let cmd = { "cmd": "set", "dev": "relay", "circuit": "1_01", "value": value }; + ws.send(JSON.stringify(cmd)); + logger.debug(`sirena - ${onOrOff}`); + } + } + + + 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") { + bits.push(0); + } + else bits.push(1); + + if (deviceStatus["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); + } + + + // turn line on or off + function turnLine(onOrOff, line, pin, force, info) { + //onOrOff => "on" or "off" + let value = 0; + if (onOrOff == "on") value = 1; + + if (force == undefined) force = false; + + if (line == 0) { + if (value == 1 && alarmStatus == "ON") turnAlarm("off"); + SETTINGS.maintenance_mode = value ? true : false; + + 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); + return; + } + + if (pin === undefined) pin = getPin(line); + + if (pin === undefined) { + errLogger.error("pin is undefined!", line); + return; + } + + if (!force) { + if (relaysData[line].contactor == value) { + instance.send(SEND_TO.debug, `line is already ${onOrOff} ` + line); + logger.debug(`turnLine: line is already ${onOrOff} `, 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(value); + + rsPort.write(Buffer.from(arr), function(err) { + if (err === undefined) { + monitor.info(`turnLine ${onOrOff} zapisal do rsPort-u`, line, pin, arr, info); + switchLogic(arr); + } + else { + monitor.info(`turnLine ${onOrOff} 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 }; + ws.send(JSON.stringify(cmd)); + switchLogic(pin, value) + } + + //if rvo is 24/7, it has just one switching profile point at 13:00. we do not want to send notification as it repeats every day. + //const d = new Date(); + //if(d.getHours() != 13) sendNotification("Dido_controller: ", SETTINGS.rvoTbName, "switching_profile_point_applied_to_line", { line: line, value: onOrOff }, "", SEND_TO.tb, instance); + } + + + // 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; + + // 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) { + const status = flowdata.data.status; + if (status == "NOK-twilight_sensor") { + deviceStatus["twilight_sensor"] = "NOK"; + } + else if (status == "NOK-em340" || status == "NOK-em111") { + deviceStatus["em"] = "NOK"; + } + else if (status == "NOK-thermometer") { + deviceStatus["temperature"] = "NOK"; + } + } + else if ("values" in flowdata.data) { + 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" + } + else if (values.hasOwnProperty("temperature")) { + deviceStatus["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"; + } + + sendTelemetry(values, rvoTbName); + } + + sendRvoStatus(); + }) + + + // we expect array as flowdata.data + instance.on("1", flowdata => { + + console.log(flowdata.data); + + if (!flowdata.data instanceof Object) return; + + let obj = flowdata.data; + let line = obj.line; + 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"); + + //! ake data prichadzaju z cmd_manager.js ??? + //TODO transform to websocket + if (Array.isArray(obj)) { + + rsPort.write(Buffer.from(obj), function(err) { + switchLogic(obj); + + instance.send(SEND_TO.debug, { "WRITE": obj }); + }); + } + }) + + + function calculateStateCode() { + + 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") { + bits.push(0); + } + else { + bits.push(1); + } + + //Prevádzkový mód - Manual, Off, Automatic, maintenance_mode = true/false // DAVA 2 BITY + if (!SETTINGS.maintenance_mode) { + if (deviceStatus["rotary_switch_state"] == "Manual") { + bits.push(0); + bits.push(1); + } + + if (deviceStatus["rotary_switch_state"] == "Automatic") { + bits.push(0); + bits.push(0); + } + + if (deviceStatus["rotary_switch_state"] == "Off") { + bits.push(1); + bits.push(0); + } + } + else { + bits.push(1); + bits.push(1); + } + + //Dverový kontakt + if (deviceStatus["door_condition"] == "closed") { + bits.push(0); + } + else { + bits.push(1); + } + + //EM + if (deviceStatus["em"] == "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //Teplomer + if (deviceStatus["temperature"] == "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //Batéria + if (deviceStatus["battery"] == "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //Zdroj + if (deviceStatus["power_supply"] == "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //MN + if (deviceStatus["master_node"] == "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //výpadok napätia na fáze + if (deviceStatus["no_voltage"] == "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + if (deviceStatus["twilight_sensor"] == "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + // doplnime do 16 bitov (2 byty) + for (let i = bits.length; i < 16; i++) { + bits.push(0); + } + + // console.log("calculateStateCode - deviceStatus", deviceStatus); + // 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; + } + + + async function sendRvoStatus() { + + if (SETTINGS === undefined) return; + SETTINGS.masterNodeIsResponding ? deviceStatus["master_node"] = "OK" : deviceStatus["master_node"] = "NOK"; + + 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() { + + // 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 + //set RVO state + let status = "OK"; + + for (const [key, value] of Object.entries(deviceStatus)) { + if (["em", "twilight_sensor", "temperature", "master_node"].includes(key) && value == "NOK") status = "NOK"; + } + + if (status == "OK") { + let pinIndexes = [1, 4, 6]; + if (controller_type == 'unipi') pinIndexes = ['input1_01', 'input1_04', 'input1_05']; + + for (const pinIndex of pinIndexes) { + if (previousValues[pinIndex] === 0) { + if ((pinIndex === 6 || pinIndex === 'input1_01' || pinIndex === 'input1_05') && SETTINGS.maintenance_mode) continue; + status = "NOK"; + break; + } + } + } + + // battery status. If value is 1 - battery is NOK + if (previousValues[5] === 1) status = "NOK"; + if (SETTINGS.no_voltage.size > 0) status = "NOK"; + + // console.log("rvo status",status) + return status; + } + + + // we pass array to function in case of rsPort ==> switchLogic([55,3,0,1]) ==> [[55,3,0,1]] + // we pass two values in case of websocket ==> switchLogic("relay1_03",1) ==> ["relay1_03",1] + const switchLogic = (...args) => { + + let values = {}; + let pinIndex, newPinValue, twilight; + + //data from rsPort + if (args.length == 1) { + pinIndex = args[0][1] + 1; + if (pinIndex === 17) pinIndex--; + newPinValue = args[0][3]; + twilight = args[0][2]; + } + //data from websocket + else { + pinIndex = args[0]; + newPinValue = args[1]; + } + + 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; + + //default value + let value = "On"; + if (newPinValue === 0) value = "Off"; + + //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"; + + // 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"); + + // deviceStatus["state_of_main_switch"] = "On"; + // } + // } + + //Prevádzkový mód + 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"; + + deviceStatus["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, "power_supply_has_disconnected_input", {}, "", SEND_TO.tb, instance, "power_supply"); + + deviceStatus["power_supply"] = "NOK"; + } + else if (newPinValue === 1 && newPinValue !== previousValues[pinIndex]) { + sendNotification("switchLogic", rvoTbName, "power_supply_works_correctly", {}, "", SEND_TO.tb, instance, "power_supply"); + + deviceStatus["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"); + + deviceStatus["battery"] = "NOK"; + } + else if (newPinValue === 0 && newPinValue !== previousValues[pinIndex]) { + sendNotification("switchLogic", rvoTbName, "battery_level_is_ok", {}, "", SEND_TO.tb, instance, "battery_level"); + + deviceStatus["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' + else if (type == "door_condition" || type === "state_of_main_switch") { + newPinValue === 0 ? value = "open" : value = "closed"; + + 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, "door_opened_without_permission", {}, "", SEND_TO.tb, instance, "rvo_door"); + + // 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 (value === "closed") { + if (alarmStatus == "ON") turnAlarm("off"); + sendNotification("switchLogic", rvoTbName, "door_closed", {}, "", SEND_TO.tb, instance, "rvo_door"); + } + + deviceStatus[type] = value; + } + + //lux sensor + else if (type == "twilight_sensor") { + //! TODO - to show nok status, if lux value is not changing more then 10 times. + //Daylight is far more than 1000. So most of the day, when it is sunshine comes just value 1000. But lux sensor is not NOK. + //This is not the case in LM. If value from LM is the same 10x, there is 99% possibility, that sensor is NOK. + value = newPinValue; + + if (controller_type === 'lm') { + value = parseFloat(newPinValue + (256 * twilight)); + + 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 && !twilightError) { + twilightError = true; + let value = twilight_sensor_array.shift(); + + newPinValue = 0; + } + else if (set.size !== 1 && twilightError) { + //sendNotification("switchLogic", rvoTbName, 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) { + 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); + } + } + + 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); + } + + deviceStatus["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) + // { + // let time = 0; + // if(value) time = 1000 * 10;//10 sekund + + // let dataChanged = false; + // if(relaysData[line].contactor != newPinValue) dataChanged = true; + // relaysData[line].contactor = newPinValue; // 0,1 + + // //ak bola predchadzajuci stav off a novy stav je on, budu sa nastavovat nespracovane node profiles + // //a budu sa odosielat commandy, tie vsak mozu zlyhat, a preto potrebujeme ich spusti trochu neskor + // setTimeout(function(){ + // instance.send(SEND_TO.cmd_manager, {sender: "dido_controller", cmd: "reload_relays", line: line, time: time, value: value, dataChanged: dataChanged}); + // }, time); + + // reportLineStatus(line); + // } + // else + // { + // errLogger.error("modify table relays failed", err); + // } + + // }); + // }); + } + + 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 }); + + //mame iba 3 istice. vyreportujeme a ohandlujeme liniu na tom istom istici ako paralelna linia (napr linia 1, paralelna s nou je linia 4, key je string "4") + // ak je 7 linii, na 1 istici je linia 1,4,7 + + if (line == 1) { + + const lineOnSameBraker = [4, 7]; + + for (var i = 0; i < lineOnSameBraker.length; i++) { + if (!relaysData.hasOwnProperty(lineOnSameBraker[i])) continue; + + 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; + reportLineStatus(lineOnSameBraker[i]); + + values[type] = value; + const tbname = relaysData[lineOnSameBraker[i]].tbname; + sendTelemetry(values, tbname); + + delete values[type]; + } + + } + else { + const lineOnSameBraker = line + 3 + ""; + + if (relaysData.hasOwnProperty(lineOnSameBraker)) { + 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; + reportLineStatus(line + 3); + + values[type] = value; + const tbname = relaysData[lineOnSameBraker].tbname; + sendTelemetry(values, tbname); + + delete values[type]; + } + } + + } + + if (value == "Off") values["status"] = "NOK"; + deviceStatus["state_of_breaker"][line] = value; + + reportLineStatus(line); + } + else return; + + values[type] = value; + + if (type == "rotary_switch_state") { + if (SETTINGS.maintenance_mode) value = "maintenance"; + value = value.toLowerCase(); + values["power_mode"] = value; + } + + if (newPinValue != previousValues[pinIndex]) previousValues[pinIndex] = newPinValue; + if (Object.keys(values).length > 0 && tbname) sendTelemetry(values, tbname); + } + + + function sendTelemetry(values, tbname, date = Date.now()) { + let dataToTb = { + [tbname]: [ + { + "ts": date, + "values": values + } + ] + }; + + tbHandler.sendToTb(dataToTb, instance); + } + + + function isObject(item) { + return (typeof item === "object" && !Array.isArray(item) && item !== null); + } + +} //end of 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 +// *|input1_01|state_of_main_switch|0|........... +// *|input1_02|rotary_switch_state|0|........... +// *|input1_03|rotary_switch_state|0|........... +// *|intut1_04|power_supply|0|........... +// *|input1_05|door_condition|0|........... +// *|input1_06|state_of_breaker|1|........... +// *|input1_07|state_of_breaker|2|........... +// *|input1_08|state_of_breaker|3|........... +// *|relay1_02|state_of_contactor|1|........... +// *|relay1_03|state_of_contactor|2|........... +// *|relay1_04|state_of_contactor|3|........... +// *|287D8776E0013CE9|temperature|0|........... + + +//! pins_data --> from UNIPI +// { +// 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 } +// } + +//! relays_data +// { +// '0': { +// line: 0, +// tbname: 'KjbN4q7JPZmexgdnz2yKQ98YAWwO0Q3BMX6ERLoV', +// contactor: 1, +// profile: '' +// }, +// '1': { +// line: 1, +// tbname: 'RMgnK93rkoAazbqdQ4yBG95Z1YXGx6pmwBeVEP2O', +// contactor: 0, +// profile: '{"intervals":[{"value":0,"end_time":"20:00","start_time":"13:00"},{"value":1,"end_time":"10:00","start_time":"20:00"},{"value":0,"end_time":"10:20","start_time":"10:00"},{"value":1,"end_time":"10:40","start_time":"10:20"},{"value":0,"end_time":"11:00","start_time":"10:40"},{"value":1,"end_time":"11:30","start_time":"11:00"},{"value":0,"end_time":"11:50","start_time":"11:30"},{"value":1,"end_time":"13:00","start_time":"11:50"}],"astro_clock":false,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' +// }, +// '2': { +// line: 2, +// tbname: 'dlE1VQjYrNx9gZRmb38gG08oLBO4qaAk2M6JPnG7', +// contactor: 0, +// profile: '{"intervals":[{"value":0,"end_time":"20:00","start_time":"13:00"},{"value":1,"end_time":"10:00","start_time":"20:00"},{"value":0,"end_time":"10:20","start_time":"10:00"},{"value":1,"end_time":"10:40","start_time":"10:20"},{"value":0,"end_time":"11:00","start_time":"10:40"},{"value":1,"end_time":"11:30","start_time":"11:00"},{"value":0,"end_time":"11:50","start_time":"11:30"},{"value":1,"end_time":"13:00","start_time":"11:50"}],"astro_clock":false,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' +// }, +// '3': { +// line: 3, +// tbname: 'vnmG4kJxaXWNBgMQq0D7Aj5e9oZzOAlr6LdR3w2V', +// contactor: 0, +// profile: '{"intervals":[{"value":0,"end_time":"20:30","start_time":"13:00"},{"value":1,"end_time":"00:10","start_time":"20:30"},{"value":0,"end_time":"13:00","start_time":"05:40"},{"value":1,"end_time":"05:40","start_time":"00:10"}],"astro_clock":true,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' +// } +// } + + + + + +// { +// "jbN4q7JPZmexgdnz2yKbWGDYAWwO0Q3BMX6ERLoV": [ +// { +// "ts": 1700409326353, +// "values": { +// "_event": { +// "type": "notice", +// "status": "new", +// "source": { +// "func": "rsPort.open()", +// "component": "1700343402190", +// "component_name": "DIDO_Controller", +// "edge": "jbN4q7JPZmexgdnz2yKbWGDYAWwO0Q3BMX6ERLoV" +// }, +// "message": "al_shariff_10.0.0.38: FLOW has been started ", +// "message_data": "" +// } +// } +// } +// ] +// } diff --git a/RVO13/flow_3_2_25/helper/DataToTbHandler.js b/RVO13/flow_3_2_25/helper/DataToTbHandler.js new file mode 100755 index 0000000..65e4ec3 --- /dev/null +++ b/RVO13/flow_3_2_25/helper/DataToTbHandler.js @@ -0,0 +1,166 @@ +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; + + this.sender = ""; + + // if attribute difference is less than limit value, we do not send to tb. + this.attributeChangeLimit = { + temperature: 0.5, + Phase_1_voltage: 2, + Phase_2_voltage: 2, + Phase_3_voltage: 2, + Phase_1_current: 0.1, + Phase_2_current: 0.1, + Phase_3_current: 0.1, + Phase_1_power: 2, + Phase_2_power: 2, + Phase_3_power: 2, + total_power: 2, + Phase_1_pow_factor: 0.1, + Phase_2_pow_factor: 0.1, + Phase_3_pow_factor: 0.1, + power_factor: 0.1, + lifetime: 0.5, + voltage: 2, + power: 2, + frequency: 3, + energy: 0.1, + current: 2, + inclination_x: 10, + inclination_y: 10, + inclination_z: 10 + }; + } + + dump() { + console.log("----------------------------"); + console.log("previousValues", this.previousValues); + console.log("----------------------------"); + } + + setSender(sender) { + this.sender = sender; + } + + isEmptyObject(obj) { + for (var name in obj) { + return false; + } + return true; + } + + sendToTb(dataToTb, instance) { + + let keys = Object.keys(dataToTb); + + if(keys.length == 0) + { + if(this.debug) console.log("sendToTb received empty object", dataToTb); + return; + } + + let tbname = keys[0]; + let ts; + + let arrayOfValues = dataToTb[tbname]; + let arrayOfValuesToSend = []; + + for(let i = 0; i < arrayOfValues.length; i++) + { + ts = arrayOfValues[i].ts; + let values = this.prepareValuesForTb(tbname, ts, arrayOfValues[i].values); + + if(!this.isEmptyObject(values)) + { + arrayOfValuesToSend.push({ts: ts, values: values}); + } + } + + if(arrayOfValuesToSend.length == 0) + { + //if(this.debug) console.log("data not sent - empty array"); + return; + } + + this.messageCounter++; + + let dataToTbModified = { + [tbname]: arrayOfValuesToSend + } + + //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); + instance.send(this.index, dataToTbModified); + } + + getDiffTimestamp(key) { + //TODO set different value for given key!!! + //if(key == "status") this.timeToHoldTbValue = 2*60*60;//2h + return this.timeToHoldTbValue * 1000; + } + + prepareValuesForTb(tbname, timestamp, values) { + + let keys = Object.keys(values); + if(!this.previousValues.hasOwnProperty(tbname)) + { + this.previousValues[tbname] = {}; + } + + //if(this.debug) console.log("prepareValuesForTb", tbname, timestamp, values); + + for(let i = 0; i < keys.length; i++) + { + let key = keys[i]; + let value = values[key]; + + if(!this.previousValues[tbname].hasOwnProperty(key)) + { + this.previousValues[tbname][key] = {ts: timestamp, value: value}; + continue; + } + + // attributeData ==> voltage: {ts:333333, value:5} + let attributeData = this.previousValues[tbname][key]; + let attributeToChange = false; + if(key in this.attributeChangeLimit) attributeToChange = true; + let limit = this.attributeChangeLimit[key]; + + if(attributeData.value === value || attributeToChange && Math.abs(attributeData.value - value) < limit) + { + let diff = timestamp - attributeData.ts; + let timestampDiffToRemoveKey = this.getDiffTimestamp(key); + if(diff > timestampDiffToRemoveKey) + { + attributeData.ts = Date.now(); + //if(this.debug) console.log(this.sender + ": update ts for key", key, "diff is", diff, "messageCounter", this.messageCounter); + } + else + { + delete values[key]; + //if(this.debug) console.log(this.sender + ": delete key", key, "diff is", diff, "messageCounter", this.messageCounter, timestampDiffToRemoveKey); + } + } + else + { + attributeData.value = value; + attributeData.ts = timestamp; + } + + } + + return values; + } +} + +module.exports = DataToTbHandler; + diff --git a/RVO13/flow_3_2_25/helper/ErrorToServiceHandler.js b/RVO13/flow_3_2_25/helper/ErrorToServiceHandler.js new file mode 100755 index 0000000..110ea8b --- /dev/null +++ b/RVO13/flow_3_2_25/helper/ErrorToServiceHandler.js @@ -0,0 +1,126 @@ +const { MD5 } = require('./md5.js'); +const { networkInterfaces } = require('os'); + +class ErrorToServiceHandler +{ + constructor() { + this.previousValues = {}; + + this.projects_id = undefined; + + const nets = networkInterfaces(); + this.ipAddresses = Object.create(null); // Or just '{}', an empty object + + for (const name of Object.keys(nets)) { + for (const net of nets[name]) { + // Skip over non-IPv4 and internal (i.e. 127.0.0.1) addresses + if (net.family === 'IPv4' && !net.internal) { + if (!this.ipAddresses[name]) { + this.ipAddresses[name] = []; + } + this.ipAddresses[name].push(net.address); + } + } + } + + //console.log(this.ipAddresses); + + } + + setProjectsId(projects_id) + { + this.projects_id = projects_id; + } + + processMessage(message, seconds, message_type) + { + if(message_type == undefined) message_type = "error_message"; + if(Array.isArray(message)) message = message.join(', '); + + let key = MD5(message); + let timestamp = new Date().getTime(); + + //keep in memory - default value is 1h + if (seconds === undefined) seconds = 60*60; + + if(!this.previousValues.hasOwnProperty(key)) + { + this.previousValues[key] = {ts: timestamp, duration: seconds}; + } + + let diff = (timestamp - this.previousValues[key].ts); + if(diff < this.previousValues[key].duration*1000) return false; + + this.previousValues[key].ts = timestamp; + + return true; + } + + sendMessageToService(message, seconds, message_type) + { + + let f = this.processMessage(message, seconds, message_type); + if(!f) return; + + /* + //------------- + if(message_type == undefined) message_type = "error_message"; + if(Array.isArray(message)) message = message.join(', '); + + let key = MD5(message); + let timestamp = new Date().getTime(); + + //keep in memory + if (seconds === undefined) seconds = 60*60; + + if(!this.previousValues.hasOwnProperty(key)) + { + this.previousValues[key] = {ts: timestamp, duration: seconds}; + } + + let diff = (timestamp - this.previousValues[key].ts); + if(diff < this.previousValues[key].duration*1000) return; + + this.previousValues[key].ts = timestamp; + */ + + //------------------------- + + //send to service + + let dataToInfoSender = {id: this.projects_id}; + + //js_error || error_message + dataToInfoSender[message_type] = message; + dataToInfoSender.ipAddresses = this.ipAddresses; + + 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) + { + console.log("this.projects_id is undefined"); + return; + } + */ + + RESTBuilder.make(function(builder) { + builder.method('POST'); + builder.post(dataToInfoSender); + builder.url('http://192.168.252.2:8004/sentmessage'); + + builder.callback(function(err, response, output) { + console.log("process.on error send", err, response, output, dataToInfoSender); + }); + }); + + + } +} + +module.exports = ErrorToServiceHandler; \ No newline at end of file diff --git a/RVO13/flow_3_2_25/helper/db_helper.js b/RVO13/flow_3_2_25/helper/db_helper.js new file mode 100755 index 0000000..40e796c --- /dev/null +++ b/RVO13/flow_3_2_25/helper/db_helper.js @@ -0,0 +1,44 @@ +function promisifyBuilder(builder) +{ + return new Promise((resolve, reject) => { + + try{ + + builder.callback(function(err, response) { + + if(err != null) reject(err); + resolve(response); + }); + + } catch (error) { + reject(error); + } + }) +} + +function makeMapFromDbResult(response, ...keys) +{ + let s = "-"; + let data = {}; + + for(let i = 0; i < response.length; i++) + { + let record = response[i]; + + let k = []; + for(let j = 0; j < keys.length; j++) + { + k.push( record[keys[j]] ); + } + + let key = k.join(s); + data[ key ] = record; + } + + return data; +} + +module.exports = { + promisifyBuilder, + makeMapFromDbResult + } \ No newline at end of file diff --git a/RVO13/flow_3_2_25/helper/logger.js b/RVO13/flow_3_2_25/helper/logger.js new file mode 100755 index 0000000..2585639 --- /dev/null +++ b/RVO13/flow_3_2_25/helper/logger.js @@ -0,0 +1,30 @@ +//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/RVO13/flow_3_2_25/helper/md5.js b/RVO13/flow_3_2_25/helper/md5.js new file mode 100755 index 0000000..d3b0480 --- /dev/null +++ b/RVO13/flow_3_2_25/helper/md5.js @@ -0,0 +1,5 @@ +function MD5(d){var r = M(V(Y(X(d),8*d.length)));return r.toLowerCase()};function M(d){for(var _,m="0123456789ABCDEF",f="",r=0;r>>4&15)+m.charAt(15&_);return f}function X(d){for(var _=Array(d.length>>2),m=0;m<_.length;m++)_[m]=0;for(m=0;m<8*d.length;m+=8)_[m>>5]|=(255&d.charCodeAt(m/8))<>5]>>>m%32&255);return _}function Y(d,_){d[_>>5]|=128<<_%32,d[14+(_+64>>>9<<4)]=_;for(var m=1732584193,f=-271733879,r=-1732584194,i=271733878,n=0;n>16)+(_>>16)+(m>>16)<<16|65535&m}function bit_rol(d,_){return d<<_|d>>>32-_} + +module.exports = { + MD5 +} \ No newline at end of file diff --git a/RVO13/flow_3_2_25/helper/notification_reporter.js b/RVO13/flow_3_2_25/helper/notification_reporter.js new file mode 100755 index 0000000..61c0aef --- /dev/null +++ b/RVO13/flow_3_2_25/helper/notification_reporter.js @@ -0,0 +1,131 @@ +//key is device, value = str +let sentValues= {}; +let notificationsData = null; + +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 +}; + +function getKey(map, val) { + return Object.keys(map).findItem(key => map[key] === val); +} + +//https://stackoverflow.com/questions/41117799/string-interpolation-on-variable +var template = (tpl, args) => tpl.replace(/\${(\w+)}/g, (_, v) => args[v]); + + +function initNotification() { + notificationsData = FLOW.GLOBALS.notificationsData; +} + +function sendNotification(func, device, key, params, extra, tb_output, instance, saveKey) { + + // return; + + let storeToSendValues = true; + if(saveKey == undefined) storeToSendValues = false; + + let lang = FLOW.GLOBALS.settings.language; + if(lang != "en" || lang != "sk") lang = "en"; + + let tpl = key; + let weight = ""; + + if(notificationsData[key]) + { + weight = notificationsData[key].weight; + weight = weight.toLowerCase(); + + tpl = notificationsData[key][lang]; + tpl = template(tpl, params); + } + else + { + //console.error("sendNotification: Notifications: undefined key", key, func, notificationsData); + console.error("sendNotification: Notifications: undefined key", key, func ); + return false; + } + + //detect invalid err weight + if(getKey(ERRWEIGHT, weight) == undefined) + { + console.error("sendNotification: Notifications: undefined weight", weight, key, func); + return false; + } + + if(sentValues.hasOwnProperty(saveKey)) + { + if(sentValues[saveKey] == tpl) + { + return false; + } + } + + if(sentValues[saveKey] == undefined) + { + if(storeToSendValues) + { + //do not send - flow is was started + sentValues[saveKey] = tpl; + return false; + } + } + + if(saveKey == "rvo_door") + { + //console.log("******", saveKey, sentValues[saveKey], tpl); + } + + if(storeToSendValues) sentValues[saveKey] = tpl; + + let str = FLOW.GLOBALS.settings.rvo_name; + if(str != "") str = str + ": "; + str = str + tpl; + + 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 + + return true; + +} + +module.exports = { + sendNotification, + ERRWEIGHT, + initNotification +} diff --git a/RVO13/flow_3_2_25/helper/register.js b/RVO13/flow_3_2_25/helper/register.js new file mode 100755 index 0000000..fc1d008 --- /dev/null +++ b/RVO13/flow_3_2_25/helper/register.js @@ -0,0 +1,144 @@ +/* +0 - cislo registra / prikaz +1 - recepient - 0 = master, 1 = slave (slave je automaticky group a broadcast) +2 - r/rw - read/write +3- register name - nazov registra / prikazu (len pre info - zobrazenie v aplikacii) + +4,5,6,7, - jednotlive byte-y - nazov byte-u +4-7 - RES. a prazdny string "" sa nezobrazia!!! +*/ + +//124 zaznamov +const registers = [ + ["0","1","R","Status","","",""], + ["1","1","RW","Dimming","R-Channel ","G-Channel","B-Channel ","W - Channel"], + ["2","1","R","Device types","","",".",""], + ["3","1","RW","Group addresses 1-4","Groups Add. 4","Groups Add. 3","Groups Add. 2","Groups Add. 1"], + ["4","1","RW","Group addresses 5-8","Groups Add. 8","Groups Add. 7","Groups Add. 6","Groups Add. 5"], + ["5","1","RW","Serial number (MAC)","","","",""], + ["6","1","RW","Time of dusk","HH","MM","SS","EXTRA"], + ["7","1","RW","Time of dawn","HH","MM","SS","EXTRA"], + ["8","1","RW","Time Schedule settings","TBD","TBD","Movement sensor","Time Schedule"], + ["9","1","RW","TS1 Time point 1","HH","MM","SS","Ext. Device"], + ["10","1","RW","TS1 Time point 1 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["11","1","RW","TS1 Time point 2","HH","MM","SS","Ext. Device"], + ["12","1","RW","TS1 Time point 2 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["13","1","RW","TS1 Time point 3","HH","MM","SS","Ext. Device"], + ["14","1","RW","TS1 Time point 3 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["15","1","RW","TS1 Time point 4","HH","MM","SS","Ext. Device"], + ["16","1","RW","TS1 Time point 4 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["17","1","RW","TS1 Time point 5","HH","MM","SS","Ext. Device"], + ["18","1","RW","TS1 Time point 5 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["19","1","RW","TS1 Time point 6","HH","MM","SS","Ext. Device"], + ["20","1","RW","TS1 Time point 6 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["21","1","RW","TS1 Time point 7","HH","MM","SS","Ext. Device"], + ["22","1","RW","TS1 Time point 7 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["23","1","RW","TS1 Time point 8","HH","MM","SS","Ext. Device"], + ["24","1","RW","TS1 Time point 8 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["25","1","RW","TS1 Time point 9","HH","MM","SS","Ext. Device"], + ["26","1","RW","TS1 Time point 9 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["27","1","RW","TS1 Time point 10","HH","MM","SS","Ext. Device"], + ["28","1","RW","TS1 Time point 10 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["29","1","RW","TS1 Time point 11","HH","MM","SS","Ext. Device"], + ["30","1","RW","TS1 Time point 11 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["31","1","RW","TS1 Time point 12","HH","MM","SS","Ext. Device"], + ["32","1","RW","TS1 Time point 12 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["33","1","RW","TS1 Time point 13","HH","MM","SS","Ext. Device"], + ["34","1","RW","TS1 Time point 13 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["35","1","RW","TS1 Time point 14","HH","MM","SS","Ext. Device"], + ["36","1","RW","TS1 Time point 14 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["37","1","RW","TS1 Time point 15","HH","MM","SS","Ext. Device"], + ["38","1","RW","TS1 Time point 15 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["39","1","RW","TS1 Time point 16","HH","MM","SS","Ext. Device"], + ["40","1","RW","TS1 Time point 16 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["41","1","RW","TS2 Time point 1","HH","MM","SS","Ext. Device"], + ["42","1","RW","TS2 Time point 1 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["43","1","RW","TS2 Time point 2","HH","MM","SS","Ext. Device"], + ["44","1","RW","TS2 Time point 2 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["45","1","RW","TS2 Time point 3","HH","MM","SS","Ext. Device"], + ["46","1","RW","TS2 Time point 3 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["47","1","RW","TS2 Time point 4","HH","MM","SS","Ext. Device"], + ["48","1","RW","TS2 Time point 4 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["49","1","RW","TS2 Time point 5","HH","MM","SS","Ext. Device"], + ["50","1","RW","TS2 Time point 5 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["51","1","RW","TS2 Time point 6","HH","MM","SS","Ext. Device"], + ["52","1","RW","TS2 Time point 6 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["53","1","RW","TS2 Time point 7","HH","MM","SS","Ext. Device"], + ["54","1","RW","TS2 Time point 7 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["55","1","RW","TS2 Time point 8","HH","MM","SS","Ext. Device"], + ["56","1","RW","TS2 Time point 8 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["57","1","RW","TS2 Time point 9","HH","MM","SS","Ext. Device"], + ["58","1","RW","TS2 Time point 9 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["59","1","RW","TS2 Time point 10","HH","MM","SS","Ext. Device"], + ["60","1","RW","TS2 Time point 10 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["61","1","RW","TS2 Time point 11","HH","MM","SS","Ext. Device"], + ["62","1","RW","TS2 Time point 11 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["63","1","RW","TS2 Time point 12","HH","MM","SS","Ext. Device"], + ["64","1","RW","TS2 Time point 12 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["65","1","RW","TS2 Time point 13","HH","MM","SS","Ext. Device"], + ["66","1","RW","TS2 Time point 13 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["67","1","RW","TS2 Time point 14","HH","MM","SS","Ext. Device"], + ["68","1","RW","TS2 Time point 14 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["69","1","RW","TS2 Time point 15","HH","MM","SS","Ext. Device"], + ["70","1","RW","TS2 Time point 15 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["71","1","RW","TS2 Time point 16","HH","MM","SS","Ext. Device"], + ["72","1","RW","TS2 Time point 16 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["73","1","RW","Power meter status","TBD","","",""], + ["74","1","R","Input Voltage","","","",""], + ["75","1","R","Input Current","","","",""], + ["76","1","R","Input Power","","","",""], + ["77","1","R","Cos phi","","","",""], + ["78","1","R","Frequency","","","",""], + ["79","1","RW","Energy","","","",""], + ["80","1","RW","Lifetime","","","",""], + ["81","1","RW","Power on cycles (input)","","","",""], + ["82","1","RW","Power on cycles (relay)","","","",""], + ["83","1","R","Time since last power on","","","",""], + ["84","1","R","Accelerometer data","","","",""], + ["85","1","RW","GPS latitude","pos/neg","deg","min ","sec"], + ["86","1","RW","GPS longitude","pos/neg","deg","min ","sec"], + ["87","1","RW","Actual time","HH","MM","SS","RES."], + ["88","1","RW","Actual date","Day of week","Day","Month","Year"], + ["89","1","R","Production data 1","","","",""], + ["90","1","R","Production data 2","","","",""], + ["91","1","RW","Network ID","NID3","NID2","NID1","NID0"], + ["95","1","RW","Actual Lux level from cabinet","RES.","RES.","HB","LB"], + ["96","1","RW","Threshold lux level","Dusk HB","Dusk LB","Dawn HB","Dawn LB"], + ["97","1","RW","Adjust period","Dusk HB","Dusk LB","Dawn HB","Dawn LB"], + ["98","1","RW","Offset","RES.","RES.","Dusk","Dawn"], + ["99","1","RW","CCT min/max range","max-H","max-L","min-H","min-L"], + ["100","1","RW","DALI interface","Cmd ID","Add","Cmd","Resp"], + ["101","1","RW","Module FW ver","v1","v2","v3","v4"], + ["102","1","RW","Module MAC-H","unused","unused","M1","M2"], + ["103","1","RW","Module MAC-L","M3","M4","M5","M6"], + ["122","1","R","FW update status/control register","Byte3","Byte2","Byte1","Byte0"], + ["123","1","R","FW update - data index","Byte3","Byte2","Byte1","Byte0"], + ["124","1","R","FW update - data","Byte3","Byte2","Byte1","Byte0"], + ["0","0","R","Status","","","",""], + ["1","0","RW","Control register","RES.","RES.","RES.","init mode enable"], + ["2","0","R","Device types","","","",""], + ["3","0","R","Serial number (MAC)","","","",""], + ["4","0","R","Production data 1","","","",""], + ["5","0","R","Production data 2","","","",""], + ["6","0","RW","Network ID","NID3","NID2","NID1","NID0"], + ["7","0","RW","RS232 settings","param.","param.","Baudrate H","Baudrate L"], + ["8","0","R","Accelerometer data","","","",""], + ["9","0","RW","Module FW ver","v1","v2","v3","v4"], + ["10","0","RW","Module MAC-H","unused","unused","M1","M2"], + ["11","0","RW","Module MAC-L","M3","M4","M5","M6"], + ["32","0","RW","FW update status/control register","Byte3","Byte2","Byte1","Byte0"], + ["33","0","RW","FW update - data index","Byte3","Byte2","Byte1","Byte0"], + ["34","0","RW","FW update - data","Byte3","Byte2","Byte1","Byte0"], + ["125","0","RW","Debug Register","Byte3","Byte2","Byte1","Byte0"], + ["126","0","RW","Network Control Register","Byte3","Byte2","Byte1","Byte0"], + ["127","0","R","Network Status Register","Byte3","Byte2","Byte1","Byte0"], + ["128","0","RW","Node XX Serial Number Register","SER3","SER2","SER1","SER0"], + ["256","0","R","Node XX Network Status Register","","","",""] +]; + +let register = {}; + +module.exports = { + registers, + register +} \ No newline at end of file diff --git a/RVO13/flow_3_2_25/helper/serialport_helper.js b/RVO13/flow_3_2_25/helper/serialport_helper.js new file mode 100755 index 0000000..8efa6af --- /dev/null +++ b/RVO13/flow_3_2_25/helper/serialport_helper.js @@ -0,0 +1,100 @@ +const { exec } = require('child_process'); + +function openPort(port){ + return new Promise((resolve, reject) => { + + var callbackError = function(err) { + port.removeListener('error', callbackError); + port.removeListener('open', callbackError); + + reject(err.message); + }; + + var callbackOpen = function(data) { + port.removeListener('error', callbackError); + port.removeListener('open', callbackOpen); + + resolve("port open: ok"); + }; + + port.on('error', callbackError); + port.on('open', callbackOpen); + + port.open(); + + }) +} + +function runSyncExec(command){ + return new Promise((resolve, reject) => { + + exec(command, (error, stdout, stderr) => { + if(error == null) resolve(stdout); + reject(error); + }); + + }) +} + +async function writeData(port, data, readbytes, timeout){ + return new Promise((resolve, reject) => { + + // 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) { + + port.write(Buffer.from(data), function(err) { + if (err) { + reject(err.message); + } + }); + + 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 +} diff --git a/RVO13/flow_3_2_25/helper/suncalc.js b/RVO13/flow_3_2_25/helper/suncalc.js new file mode 100755 index 0000000..c9ca56d --- /dev/null +++ b/RVO13/flow_3_2_25/helper/suncalc.js @@ -0,0 +1,317 @@ +/* + (c) 2011-2015, Vladimir Agafonkin + SunCalc is a JavaScript library for calculating sun/moon position and light phases. + https://github.com/mourner/suncalc +*/ + +(function () { 'use strict'; + +// shortcuts for easier to read formulas + +var PI = Math.PI, + sin = Math.sin, + cos = Math.cos, + tan = Math.tan, + asin = Math.asin, + atan = Math.atan2, + acos = Math.acos, + rad = PI / 180; + +// sun calculations are based on http://aa.quae.nl/en/reken/zonpositie.html formulas + + +// date/time constants and conversions + +var dayMs = 1000 * 60 * 60 * 24, + J1970 = 2440588, + J2000 = 2451545; + +function toJulian(date) { return date.valueOf() / dayMs - 0.5 + J1970; } +function fromJulian(j) { return new Date((j + 0.5 - J1970) * dayMs); } +function toDays(date) { return toJulian(date) - J2000; } + + +// general calculations for position + +var e = rad * 23.4397; // obliquity of the Earth + +function rightAscension(l, b) { return atan(sin(l) * cos(e) - tan(b) * sin(e), cos(l)); } +function declination(l, b) { return asin(sin(b) * cos(e) + cos(b) * sin(e) * sin(l)); } + +function azimuth(H, phi, dec) { return atan(sin(H), cos(H) * sin(phi) - tan(dec) * cos(phi)); } +function altitude(H, phi, dec) { return asin(sin(phi) * sin(dec) + cos(phi) * cos(dec) * cos(H)); } + +function siderealTime(d, lw) { return rad * (280.16 + 360.9856235 * d) - lw; } + +function astroRefraction(h) { + if (h < 0) // the following formula works for positive altitudes only. + h = 0; // if h = -0.08901179 a div/0 would occur. + + // formula 16.4 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + // 1.02 / tan(h + 10.26 / (h + 5.10)) h in degrees, result in arc minutes -> converted to rad: + return 0.0002967 / Math.tan(h + 0.00312536 / (h + 0.08901179)); +} + +// general sun calculations + +function solarMeanAnomaly(d) { return rad * (357.5291 + 0.98560028 * d); } + +function eclipticLongitude(M) { + + var C = rad * (1.9148 * sin(M) + 0.02 * sin(2 * M) + 0.0003 * sin(3 * M)), // equation of center + P = rad * 102.9372; // perihelion of the Earth + + return M + C + P + PI; +} + +function sunCoords(d) { + + var M = solarMeanAnomaly(d), + L = eclipticLongitude(M); + + return { + dec: declination(L, 0), + ra: rightAscension(L, 0) + }; +} + + +var SunCalc = {}; + + +// calculates sun position for a given date and latitude/longitude + +SunCalc.getPosition = function (date, lat, lng) { + + var lw = rad * -lng, + phi = rad * lat, + d = toDays(date), + + c = sunCoords(d), + H = siderealTime(d, lw) - c.ra; + + return { + azimuth: azimuth(H, phi, c.dec), + altitude: altitude(H, phi, c.dec) + }; +}; + + +// sun times configuration (angle, morning name, evening name) + +var times = SunCalc.times = [ + [-0.833, 'sunrise', 'sunset' ], + [ -0.3, 'sunriseEnd', 'sunsetStart' ], + [ -6, 'dawn', 'dusk' ], + [ -12, 'nauticalDawn', 'nauticalDusk'], + [ -18, 'nightEnd', 'night' ], + [ 6, 'goldenHourEnd', 'goldenHour' ] +]; + +// adds a custom time to the times config + +SunCalc.addTime = function (angle, riseName, setName) { + times.push([angle, riseName, setName]); +}; + + +// calculations for sun times + +var J0 = 0.0009; + +function julianCycle(d, lw) { return Math.round(d - J0 - lw / (2 * PI)); } + +function approxTransit(Ht, lw, n) { return J0 + (Ht + lw) / (2 * PI) + n; } +function solarTransitJ(ds, M, L) { return J2000 + ds + 0.0053 * sin(M) - 0.0069 * sin(2 * L); } + +function hourAngle(h, phi, d) { return acos((sin(h) - sin(phi) * sin(d)) / (cos(phi) * cos(d))); } +function observerAngle(height) { return -2.076 * Math.sqrt(height) / 60; } + +// returns set time for the given sun altitude +function getSetJ(h, lw, phi, dec, n, M, L) { + + var w = hourAngle(h, phi, dec), + a = approxTransit(w, lw, n); + return solarTransitJ(a, M, L); +} + + +// calculates sun times for a given date, latitude/longitude, and, optionally, +// the observer height (in meters) relative to the horizon + +SunCalc.getTimes = function (date, lat, lng, height) { + + height = height || 0; + + var lw = rad * -lng, + phi = rad * lat, + + dh = observerAngle(height), + + d = toDays(date), + n = julianCycle(d, lw), + ds = approxTransit(0, lw, n), + + M = solarMeanAnomaly(ds), + L = eclipticLongitude(M), + dec = declination(L, 0), + + Jnoon = solarTransitJ(ds, M, L), + + i, len, time, h0, Jset, Jrise; + + + var result = { + solarNoon: fromJulian(Jnoon), + nadir: fromJulian(Jnoon - 0.5) + }; + + for (i = 0, len = times.length; i < len; i += 1) { + time = times[i]; + h0 = (time[0] + dh) * rad; + + Jset = getSetJ(h0, lw, phi, dec, n, M, L); + Jrise = Jnoon - (Jset - Jnoon); + + result[time[1]] = fromJulian(Jrise); + result[time[2]] = fromJulian(Jset); + } + + return result; +}; + + +// moon calculations, based on http://aa.quae.nl/en/reken/hemelpositie.html formulas + +function moonCoords(d) { // geocentric ecliptic coordinates of the moon + + var L = rad * (218.316 + 13.176396 * d), // ecliptic longitude + M = rad * (134.963 + 13.064993 * d), // mean anomaly + F = rad * (93.272 + 13.229350 * d), // mean distance + + l = L + rad * 6.289 * sin(M), // longitude + b = rad * 5.128 * sin(F), // latitude + dt = 385001 - 20905 * cos(M); // distance to the moon in km + + return { + ra: rightAscension(l, b), + dec: declination(l, b), + dist: dt + }; +} + +SunCalc.getMoonPosition = function (date, lat, lng) { + + var lw = rad * -lng, + phi = rad * lat, + d = toDays(date), + + c = moonCoords(d), + H = siderealTime(d, lw) - c.ra, + h = altitude(H, phi, c.dec), + // formula 14.1 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + pa = atan(sin(H), tan(phi) * cos(c.dec) - sin(c.dec) * cos(H)); + + h = h + astroRefraction(h); // altitude correction for refraction + + return { + azimuth: azimuth(H, phi, c.dec), + altitude: h, + distance: c.dist, + parallacticAngle: pa + }; +}; + + +// calculations for illumination parameters of the moon, +// based on http://idlastro.gsfc.nasa.gov/ftp/pro/astro/mphase.pro formulas and +// Chapter 48 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + +SunCalc.getMoonIllumination = function (date) { + + var d = toDays(date || new Date()), + s = sunCoords(d), + m = moonCoords(d), + + sdist = 149598000, // distance from Earth to Sun in km + + phi = acos(sin(s.dec) * sin(m.dec) + cos(s.dec) * cos(m.dec) * cos(s.ra - m.ra)), + inc = atan(sdist * sin(phi), m.dist - sdist * cos(phi)), + angle = atan(cos(s.dec) * sin(s.ra - m.ra), sin(s.dec) * cos(m.dec) - + cos(s.dec) * sin(m.dec) * cos(s.ra - m.ra)); + + return { + fraction: (1 + cos(inc)) / 2, + phase: 0.5 + 0.5 * inc * (angle < 0 ? -1 : 1) / Math.PI, + angle: angle + }; +}; + + +function hoursLater(date, h) { + return new Date(date.valueOf() + h * dayMs / 24); +} + +// calculations for moon rise/set times are based on http://www.stargazing.net/kepler/moonrise.html article + +SunCalc.getMoonTimes = function (date, lat, lng, inUTC) { + var t = new Date(date); + if (inUTC) t.setUTCHours(0, 0, 0, 0); + else t.setHours(0, 0, 0, 0); + + var hc = 0.133 * rad, + h0 = SunCalc.getMoonPosition(t, lat, lng).altitude - hc, + h1, h2, rise, set, a, b, xe, ye, d, roots, x1, x2, dx; + + // go in 2-hour chunks, each time seeing if a 3-point quadratic curve crosses zero (which means rise or set) + for (var i = 1; i <= 24; i += 2) { + h1 = SunCalc.getMoonPosition(hoursLater(t, i), lat, lng).altitude - hc; + h2 = SunCalc.getMoonPosition(hoursLater(t, i + 1), lat, lng).altitude - hc; + + a = (h0 + h2) / 2 - h1; + b = (h2 - h0) / 2; + xe = -b / (2 * a); + ye = (a * xe + b) * xe + h1; + d = b * b - 4 * a * h1; + roots = 0; + + if (d >= 0) { + dx = Math.sqrt(d) / (Math.abs(a) * 2); + x1 = xe - dx; + x2 = xe + dx; + if (Math.abs(x1) <= 1) roots++; + if (Math.abs(x2) <= 1) roots++; + if (x1 < -1) x1 = x2; + } + + if (roots === 1) { + if (h0 < 0) rise = i + x1; + else set = i + x1; + + } else if (roots === 2) { + rise = i + (ye < 0 ? x2 : x1); + set = i + (ye < 0 ? x1 : x2); + } + + if (rise && set) break; + + h0 = h2; + } + + var result = {}; + + if (rise) result.rise = hoursLater(t, rise); + if (set) result.set = hoursLater(t, set); + + if (!rise && !set) result[ye > 0 ? 'alwaysUp' : 'alwaysDown'] = true; + + return result; +}; + + +// export as Node module / AMD module / browser variable +if (typeof exports === 'object' && typeof module !== 'undefined') module.exports = SunCalc; +else if (typeof define === 'function' && define.amd) define(SunCalc); +else window.SunCalc = SunCalc; + +}()); diff --git a/RVO13/flow_3_2_25/helper/utils.js b/RVO13/flow_3_2_25/helper/utils.js new file mode 100755 index 0000000..a16210c --- /dev/null +++ b/RVO13/flow_3_2_25/helper/utils.js @@ -0,0 +1,124 @@ +function bytesToInt(bytes, numberOfBytes) +{ + let buffer = []; + if(Array.isArray(bytes)) + { + buffer = bytes.slice(0); + if(numberOfBytes != undefined) + { + buffer = bytes.slice(bytes.length - numberOfBytes); + } + } + else buffer.push(bytes); + + //var decimal = (buffer[0] << 24) + (buffer[1] << 16) + (buffer[2] << 8) + buffer[3]; + let l = (buffer.length - 1) * 8; + + let decimal = 0; + for(let i = 0; i < buffer.length; i++) + { + var s = buffer[i] << l; + if(l < 8) s = buffer[i] + decimal = decimal + s; + + l = l - 8; + + } + + return decimal; +} + +function resizeArray(arr, newSize, defaultValue) { + while(newSize > arr.length) + arr.push(defaultValue); + arr.length = newSize; +} + +longToByteArray = function(/*long*/long) { + // we want to represent the input as a 8-bytes array + var byteArray = [0, 0, 0, 0, 0, 0, 0, 0]; + + for ( var index = 0; index < byteArray.length; index ++ ) { + var byte = long & 0xff; + byteArray [ index ] = byte; + long = (long - byte) / 256 ; + } + + return byteArray; + }; + +function addDays(date, days) { + var result = new Date(date); + result.setDate(result.getDate() + days); + return result; +} + +/* +sleep(2000).then(() => { + // Do something after the sleep! + + +}); +*/ + +function sleep (time) { + return new Promise((resolve) => setTimeout(resolve, time)); +} + +function isEmptyObject( obj ) { + for ( var name in obj ) { + return false; + } + return true; +} + +function convertUTCDateToLocalDate(date) { + var newDate = new Date(date); + newDate.setMinutes(date.getMinutes() + date.getTimezoneOffset()); + return newDate; +} + +function addZeroBefore(n) { + return (n < 10 ? '0' : '') + n; +} + +var convertBase = function () { + + function convertBase(baseFrom, baseTo) { + return function (num) { + return parseInt(num, baseFrom).toString(baseTo); + + }; + } + + // binary to decimal + convertBase.bin2dec = convertBase(2, 10); + + // binary to hexadecimal + convertBase.bin2hex = convertBase(2, 16); + + // decimal to binary + convertBase.dec2bin = convertBase(10, 2); + + // decimal to hexadecimal + convertBase.dec2hex = convertBase(10, 16); + + // hexadecimal to binary + convertBase.hex2bin = convertBase(16, 2); + + // hexadecimal to decimal + convertBase.hex2dec = convertBase(16, 10); + + return convertBase; + }(); + +module.exports = { + bytesToInt, + longToByteArray, + addDays, + addZeroBefore, + resizeArray, + isEmptyObject, + sleep, + convertUTCDateToLocalDate +} \ No newline at end of file diff --git a/RVO13/flow_3_2_25/httprequest.js b/RVO13/flow_3_2_25/httprequest.js new file mode 100755 index 0000000..469c8cb --- /dev/null +++ b/RVO13/flow_3_2_25/httprequest.js @@ -0,0 +1,137 @@ +exports.id = 'httprequest'; +exports.title = 'HTTP Request'; +exports.group = 'HTTP'; +exports.color = '#5D9CEC'; +exports.input = true; +exports.version = '2.0.1'; +exports.output = 1; +exports.author = 'Peter Širka'; +exports.icon = 'cloud-upload'; + +exports.html = `
+
@(URL address)
+
+
+
@(HTTP method)
+
+
+
@(Serialization)
+
+
+
@(Download the content in chunks)
+
@(Keep persistent cookies)
+
@(Disable DNS cache)
+
@(Keep alive connection)
+
+
+
+
@(Custom headers)
+
@(Cookies)
+
+
+
+ +
+
+
+
@(User)
+
+
+
@(Password)
+
+
+
+
+
`; + +exports.readme = `# Request + +This component creates a request with received data. + +__Response:__ +\`\`\`javascript +{ + data: String, + headers: Object, + status: Number, + host: String +} +\`\`\` + +__Dynamic arguments__: +Are performed via FlowData repository and can be used for URL address or for custom headers/cookies/auth. Use \`repository\` component for creating of dynamic arguments. Dynamic values are replaced in the form \`{key}\`: + +- url address e.g. \`https://.../{key}/\` +- headers values e.g. \`{token}\` +- cookies values e.g. \`{token}\``; + +exports.install = function(instance) { + + var can = false; + var flags = null; + var cookies2 = null; + + instance.on('data', function(response) { + can && instance.custom.send(response); + }); + + instance.custom.send = function(response) { + var options = instance.options; + + var headers = null; + var cookies = null; + + options.headers && Object.keys(options.headers).forEach(function(key) { + !headers && (headers = {}); + headers[key] = response.arg(options.headers[key]); + }); + + if (options.username && options.userpassword) { + !headers && (headers = {}); + headers['Authorization'] = 'Basic ' + U.createBuffer(response.arg(options.username + ':' + options.userpassword)).toString('base64'); + } + + options.cookies && Object.keys(options.cookies).forEach(function(key) { + !cookies && (cookies = {}); + cookies[key] = response.arg(options.cookies[key]); + }); + + if (options.chunks) { + U.download(response.arg(options.url), flags, options.stringify === 'none' ? null : response.data, function(err, response) { + response.on('data', (chunks) => instance.send2(chunks)); + }, cookies || cookies2, headers); + } else { + U.request(response.arg(options.url), flags, options.stringify === 'none' ? null : response.data, 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) + instance.error(err, response); + }, cookies || cookies2, headers); + } + }; + + instance.reconfigure = function() { + var options = instance.options; + can = options.url && options.url && options.method && options.stringify ? true : false; + instance.status(can ? '' : 'Not configured', can ? undefined : 'red'); + + if (!can) + return; + + flags = []; + flags.push(options.method.toLowerCase()); + options.stringify === 'json' && flags.push('json'); + options.stringify === 'raw' && flags.push('raw'); + options.keepalive && flags.push('keepalive'); + !options.nodns && flags.push('dnscache'); + if (options.persistentcookies) { + flags.push('cookies'); + cookies2 = {}; + } else + cookies2 = null; + }; + + instance.on('options', instance.reconfigure); + instance.reconfigure(); +}; \ No newline at end of file diff --git a/RVO13/flow_3_2_25/httpresponse.js b/RVO13/flow_3_2_25/httpresponse.js new file mode 100755 index 0000000..160a3bb --- /dev/null +++ b/RVO13/flow_3_2_25/httpresponse.js @@ -0,0 +1,76 @@ +exports.id = 'httpresponse'; +exports.title = 'HTTP Response'; +exports.group = 'HTTP'; +exports.color = '#5D9CEC'; +exports.icon = 'arrow-right'; +exports.input = true; +exports.output = ['#666D76']; +exports.version = '2.0.0'; +exports.author = 'Martin Smola'; +exports.readme = `# HTTP response + +HTTP response will respond with data recieved using data-type set in Settings form or plain text if not set. Output is the message duration \`Number\` in seconds.`; + +exports.html = `
+
@(Response data-type)
+
JSON is by default.
+
`; + +exports.install = function(instance) { + + var dursum = 0; + var durcount = 0; + + instance.on('data', function(flowdata) { + + var ctrl = flowdata.repository.controller; + var data = flowdata.data; + + if (!ctrl) { + instance.throw('No controller to use for response!'); + return; + } + + durcount++; + dursum += ((new Date() - flowdata.begin) / 1000).floor(2); + setTimeout2(instance.id, instance.custom.duration, 500, 10); + + ctrl.$flowdata = flowdata; + + var datatype = instance.options.datatype || 'json'; + if (datatype === 'emptyresponse') + return ctrl.plain(''); + + if (datatype !== 'json' && typeof(data) !== 'string') { + instance.throw('Incorect type of data, expected string, got ' + typeof(data)); + ctrl.plain(data == null ? '' : data.toString()); + return; + } + + switch(datatype) { + case 'html': + ctrl.content(data, 'text/html'); + break; + case 'plain': + ctrl.plain(data); + break; + case 'xml': + ctrl.content(data, 'text/xml'); + break; + default: + ctrl.json(data); + break; + } + }); + + instance.on('service', function() { + dursum = 0; + durcount = 0; + }); + + instance.custom.duration = function() { + var avg = (dursum / durcount).floor(2); + instance.status(avg + ' sec.'); + instance.send2(0, avg); + }; +}; diff --git a/RVO13/flow_3_2_25/httproute.js b/RVO13/flow_3_2_25/httproute.js new file mode 100755 index 0000000..583a19d --- /dev/null +++ b/RVO13/flow_3_2_25/httproute.js @@ -0,0 +1,326 @@ +exports.id = 'httproute'; +exports.title = 'HTTP Route'; +exports.group = 'HTTP'; +exports.color = '#5D9CEC'; +exports.icon = 'globe'; +exports.input = false; +exports.output = ['#6CAC5A', '#37BC9B']; +exports.version = '1.2.3'; +exports.author = 'Martin Smola'; +exports.cloning = false; +exports.options = { method: 'GET', url: '', size: 5, cacheexpire: '5 minutes', cachepolicy: 0, timeout: 5 }; +exports.dateupdated = '2021-01-21 18:30d'; +exports.readme = `# HTTP route + +__Outputs__: +- first output: raw data (cache is empty or is disabled) +- second output: cached data + +If one of the outputs is disabled then automatic responce with code "503 service unavailable" is sent. + +When a request comes in bellow object is available at \`flowdata.data\`: + +\`\`\`javascript +{ + params: { id: '1' }, // params for dynamic routes, e.g. /test/{id} + query: { msg: 'Hello' }, // parsed query string, e.g. /test/1?msg=Hello + body: { test: 'OK' }, // object if json requests otherwise string + headers: {}, // headers data + session: {}, // session data + user: {}, // user data + files: [], // uploaded files + url: '/users/', // a relative URL address + referrer: '/', // referrer + mobile: false, // determines mobile device + robot: false, // determines search robots/crawlsers + language: 'en' // determines language +} +\`\`\` + +See [documentation for flags](https://docs.totaljs.com/latest/en.html#api~HttpRouteOptionsFlags~unauthorize). These method flags are set automatically e.g. \`get, post, put, patch or delete\` + +--- + +\`id:ROUTE_ID\` flag cannot be used since it's already used by this component internally`; + +exports.html = `
+
+ +
+ +
+
+
@(HTTP method)
+
+
+
@(URL address)
+
+
+
+
+
@(Additional flags)
+
@(Separate flags by comma e.g. json, authorize)
+
+
+
@(Max. request size)
+
@(In kB kilobytes)
+
+
+
@(Timeout)
+
@(In seconds.)
+
+
+
+
+
+
@(Automatically respond with 200 OK?)
+
@(If not checked you need to use HTTP response component to respond to the request.)
+
+
@(Custom headers)
+
@(Cookies)
+
+
+
+
+
+
@(Cache policy)
+
@(User instance must contain id property.)
+
+
+
@(Expiration)
+
@(E.g. 5 minutes)
+
+
+
+`; + +exports.install = function(instance) { + + var route; + + var uninstall = function(id) { + if (F.is4) { + route && route.remove(); + route = null; + } else + UNINSTALL('route', id); + }; + + instance.custom.emptyresponse = function(self) { + self.plain(); + }; + + instance.reconfigure = function() { + + var options = instance.options; + + if (!options.url) { + instance.status('Not configured', 'red'); + return; + } + + if (typeof(options.flags) === 'string') + options.flags = options.flags.split(',').trim(); + + uninstall('id:' + instance.id); + + var flags = options.flags || []; + + flags.push('id:' + instance.id); + + if (!F.is4) + flags.push(options.method.toLowerCase()); + + options.timeout && flags.push(options.timeout * 1000); + + // Make unique values + flags = flags.filter(function(v, i, a) { + if(F.is4 && v.toString().toLowerCase() === options.method.toLowerCase()) + return false; // remove method + return a.indexOf(v) === i; + }); + + options.flags = flags; + var handler = function() { + + if (instance.paused || (instance.isDisabled && (instance.isDisabled('output', 0) || instance.isDisabled('output', 1)))) { + instance.status('503 Service Unavailable'); + this.status = 503; + this.json(); + return; + } + + var key; + var self = this; + + if (instance.options.emptyresponse) { + instance.status('200 OK'); + setTimeout(instance.custom.emptyresponse, 100, self); + + if (instance.hasConnection(0)) { + var data = instance.make({ + query: self.query, + body: self.body, + session: self.session, + user: self.user, + files: self.files, + headers: self.req.headers, + url: self.url, + params: self.params + }); + instance.send2(0, data); + } + + return; + } + + switch (instance.options.cachepolicy) { + case 1: // URL + key = 'rro' + instance.id + self.url.hash(); + break; + case 2: // URL + query + case 3: // URL + query + user + key = self.url; + var keys = Object.keys(self.query); + keys.sort(); + for (var i = 0, length = keys.length; i < length; i++) + key += keys[i] + self.query[keys[i]] + '&'; + if (instance.options.cachepolicy === 3 && self.user) + key += 'iduser' + self.user.id; + key = 'rro' + instance.id + key.hash(); + break; + } + + if (key && F.cache.get2(key)) { + var data = instance.make(F.cache.get2(key)); + data.repository.controller = self; + instance.send2(1, data); + } else { + + var data = instance.make({ + query: self.query, + body: self.body, + session: self.session, + user: self.user, + files: self.files, + headers: self.req.headers, + url: self.url, + params: self.params, + mobile: self.mobile, + robot: self.robot, + referrer: self.referrer, + language: self.language + }); + + data.repository.controller = self; + instance.send2(0, data); + key && FINISHED(self.res, () => F.cache.set(key, self.$flowdata.data, instance.options.cacheexpire)); + } + }; + + if (F.is4) + route = ROUTE(options.method.toUpperCase() + ' ' + options.url, handler, flags, options.size || 5); + else + F.route(options.url, handler, flags, options.size || 5); + + instance.status('Listening', 'green'); + }; + + instance.reconfigure(); + instance.on('options', instance.reconfigure); + instance.on('close', function(){ + uninstall('id:' + instance.id); + }); +}; + +// check url exists +FLOW.trigger('httproutecheckurl', function(next, data) { + var url = data.url; + var method = data.method; + if (url[url.length - 1] !== '/') + url += '/'; + var exists = F.routes.web.findItem(r => r.urlraw === url && r.method === method); + next(exists != null); +}); + +exports.uninstall = function() { + FLOW.trigger('httproutecheckurl', null); +}; diff --git a/RVO13/flow_3_2_25/infosender.js b/RVO13/flow_3_2_25/infosender.js new file mode 100755 index 0000000..c7afd83 --- /dev/null +++ b/RVO13/flow_3_2_25/infosender.js @@ -0,0 +1,101 @@ +exports.id = 'infosender'; +exports.title = 'Info sender'; +exports.version = '1.0.0'; +exports.group = 'Worksys'; +exports.color = '#2134B0'; +exports.input = 2; +exports.output = 1 +exports.icon = 'bolt'; + +const { networkInterfaces } = require('os'); + +exports.html = `
+
+
+
CSV Import
+
+
+
`; + +exports.readme = `# send all data to projects.worksys.io, required to monitor status of controller(unipi)`; + +exports.install = function(instance) { + + let id; + let allValues = {}; + let sendAllValuesInterval; + let configured = false; + + let now = new Date(); + console.log(exports.title, "INSTALLED", now.toLocaleString("sk-SK")); + + const nets = networkInterfaces(); + let ipAddresses = Object.create(null); // Or just '{}', an empty object + + for (const name of Object.keys(nets)) { + for (const net of nets[name]) { + // Skip over non-IPv4 and internal (i.e. 127.0.0.1) addresses + if (net.family === 'IPv4' && !net.internal) { + if (!ipAddresses[name]) { + ipAddresses[name] = []; + } + ipAddresses[name].push(net.address); + } + } + } + + function sendValues() + { + if(!configured) return; + + if(Object.keys(allValues).length > 0) + { + if(id) + { + delete allValues.__force__; + let dataToSend = {...allValues}; + dataToSend.id = id; + dataToSend.ipAddresses = ipAddresses; + + instance.send(0, dataToSend); + + allValues = {}; + } + else + { + console.log(exports.title, "unable to send data, no id"); + } + + } + } + + instance.on("close", () => { + clearInterval(sendAllValuesInterval); + }) + + instance.on("0", _ => { + id = FLOW.GLOBALS.settings.project_id; + configured = true; + }) + + instance.on("1", flowdata => { + + allValues = { ...allValues, ...flowdata.data}; + //console.log("DATA RECEIVED", flowdata.data); + + //__force__ + if(flowdata.data.hasOwnProperty("__force__")) + { + if(flowdata.data.__force__) + { + sendValues(); + } + } + }) + + sendAllValuesInterval = setInterval(() => { + sendValues(); + }, 60000*3); + +} + diff --git a/RVO13/flow_3_2_25/modbus_reader.js b/RVO13/flow_3_2_25/modbus_reader.js new file mode 100755 index 0000000..b907148 --- /dev/null +++ b/RVO13/flow_3_2_25/modbus_reader.js @@ -0,0 +1,367 @@ +exports.id = 'modbus_reader'; +exports.title = 'Modbus reader'; +exports.version = '2.0.0'; +exports.group = 'Worksys'; +exports.color = '#2134B0'; +exports.input = 1; +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; +//number of phases inRVO +let phases; +//phases where voltage is 0 (set) +let noVoltage; + +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.phases = this.buildPhases(); + + this.startSocket(); + } + + buildPhases = () => { + let a = []; + for (let i = 1; i<= phases; i++) { + a.push(`Phase_${i}_voltage`) + } + return a; + } + + 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 (this.phases.includes(singleValue)) + { + let l = singleValue.split("_"); + let phase = parseInt(l[1]); + + // console.log(values[singleValue], tbName); + + if(values[singleValue] == 0) + { + noVoltage.add(phase); + sendNotification("modbus_reader: checkNullVoltage", tbName, "no_voltage_on_phase", {phase: phase}, "", SEND_TO.tb, instance, "voltage" + phase ); + // console.log('no voltage') + } + else + { + noVoltage.delete(phase); + // console.log('voltage detected') + sendNotification("modbus_reader: checkNullVoltage", tbName, "voltage_on_phase_restored", {phase: phase}, "", SEND_TO.tb, instance, "voltage" + phase); + } + } + }) + } + + /** + * function sends notification to slack and to tb, if EM total_power value changes more than numberOfNodes*15. This should show, that RVO lamps has been switched on or off + */ + lampSwitchNotification = (values) => { + + if(!values.hasOwnProperty("total_power")) return; + + const actualTotalPower = values.total_power; + + const numberOfNodes = Object.keys(FLOW.GLOBALS.nodesData).length; + if(numberOfNodes == 0) numberOfNodes = 20; // to make sure, we send notification if totalPower is more than 300 + + if(actualTotalPower > numberOfNodes * 15 && this.onNotificationSent == false) + { + sendNotification("modbus_reader: lampSwitchNotification", tbName, "lamps_have_turned_on", {}, "", SEND_TO.tb, instance); + this.onNotificationSent = true; + this.offNotificationSent = false; + } + else if(actualTotalPower <= numberOfNodes * 15 && this.offNotificationSent == false) + { + 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; + } + + function main() { + + phases = FLOW.GLOBALS.settings.phases; + tbName = FLOW.GLOBALS.settings.rvoTbName; + noVoltage = FLOW.GLOBALS.settings.no_voltage; + mainSocket = new SocketWithClients(); + + // this notification is to show, that flow (unipi) has been restarted + sendNotification("modbus_reader", tbName, "flow_restart", {}, "", SEND_TO.slack, instance); + } + + instance.on("0", function(_) { + main(); + }) + +} + diff --git a/RVO13/flow_3_2_25/monitorconsumption.js b/RVO13/flow_3_2_25/monitorconsumption.js new file mode 100755 index 0000000..64cc58e --- /dev/null +++ b/RVO13/flow_3_2_25/monitorconsumption.js @@ -0,0 +1,156 @@ +exports.id = 'monitorconsumption'; +exports.title = 'Consumption'; +exports.version = '1.0.0'; +exports.author = 'Peter Širka'; +exports.group = 'Monitoring'; +exports.color = '#967ADC'; +exports.input = 0; +exports.output = 1; +exports.icon = 'bug'; +exports.options = { interval: 5000, enabled: true, monitorconsumption: true, monitorsize: true, monitorconnections: true, monitorfiles: true }; +exports.click = true; +exports.readme = `# Consumption monitoring + +This component measure CPU and memory consumption, open files and open connections of this application. It uses these Linux commands: \`ps\`, \`lsof\`, \`netstat\` and \`df\`. + +__Data Example__: + +\`\`\`javascript +{ + cpu: 0, // percentage + memory: 4096, // in bytes + size: 34303, // directory size in bytes + files: 34, // count of open files + connections: 343, // count of connections + uptime: '1-12:34:00' +} +\`\`\``; + +exports.html = `
+
+
+
@(Interval in milliseconds)
+
+
+
+
Monitor: Consumption + uptime
+
Monitor: Count of open files
+
Monitor: Count of open connections
+
Monitor: Directory size
+
`; + +exports.install = function(instance) { + + var current = { cpu: 0, memory: 0, files: 0, connections: 0, size: 0, uptime: '', counter: 0 }; + var tproc = null; + var Exec = require('child_process').exec; + var reg_empty = /\s{2,}/g; + var reg_appdisksize = /^[\d.,]+/; + + instance.custom.run = function() { + + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + + var arr = []; + + // Get CPU and Memory consumption + instance.options.monitorconsumption && arr.push(function(next) { + Exec('ps -p {0} -o %cpu,rss,etime'.format(process.pid), function(err, response) { + + if (err) { + instance.throw(err); + } else { + var line = response.split('\n')[1]; + line = line.trim().replace(reg_empty, ' ').split(' '); + var cpu = line[0].parseFloat(); + current.cpu = cpu.floor(1); + current.memory = line[1].parseInt2() * 1024; // kB to bytes + current.uptime = line[2]; + } + + next(); + }); + }); + + // Get count of open files + instance.options.monitorfiles && arr.push(function(next) { + Exec('lsof -a -p {0} | wc -l'.format(process.pid), function(err, response) { + if (err) + instance.throw(err); + else + current.files = response.trim().parseInt2(); + next(); + }); + }); + + // Get count of opened network connections + instance.options.monitorconnections && arr.push(function(next) { + Exec('netstat -an | grep :{0} | wc -l'.format(F.port), function(err, response) { + if (err) { + instance.throw(err); + } else { + current.connections = response.trim().parseInt2() - 1; + if (current.connections < 0) + current.connections = 0; + } + next(); + }); + }); + + // Get directory size + instance.options.monitorsize && current.counter % 5 !== 0 && arr.push(function(next) { + Exec('du -hsb ' + process.cwd(), function(err, response) { + if (err) { + instance.throw(err); + } else { + var match = response.trim().match(reg_appdisksize); + match && (current.size = match.toString().trim().parseInt2()); + } + next(); + }); + }); + + arr.async(function() { + + tproc && clearTimeout(tproc); + + if (instance.options.enabled) { + tproc = setTimeout(instance.custom.run, instance.options.interval); + instance.send2(current); + } + + instance.custom.status(); + current.counter++; + }); + }; + + instance.custom.status = function() { + if (instance.options.enabled) + instance.status('{0}% / {1}'.format(current.cpu, current.memory.filesize())); + else + instance.status('Disabled', 'red'); + }; + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + + if (instance.options.enabled) { + current.counter = 0; + instance.custom.run(); + } + + }); + + instance.on('close', function() { + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + }); + + setTimeout(instance.custom.run, 1000); +}; \ No newline at end of file diff --git a/RVO13/flow_3_2_25/monitordisk.js b/RVO13/flow_3_2_25/monitordisk.js new file mode 100755 index 0000000..f4fdaa0 --- /dev/null +++ b/RVO13/flow_3_2_25/monitordisk.js @@ -0,0 +1,96 @@ +exports.id = 'monitordisk'; +exports.title = 'Disk'; +exports.version = '1.0.0'; +exports.author = 'Peter Širka'; +exports.group = 'Monitoring'; +exports.color = '#F6BB42'; +exports.output = 1; +exports.icon = 'hdd-o'; +exports.click = true; +exports.options = { interval: 8000, path: '/', enabled: true }; +exports.readme = `# Disk monitoring + +This component monitors disk \`bytes\` consumption in Linux systems. It uses \`df\` command. + +__Data Example__: + +\`\`\`javascript +{ + total: 474549649408, + used: 39125245952, + free: 411294994432 +} +\`\`\``; + +exports.html = `
+
+
+
@(Interval in milliseconds)
+
+
+
@(Path)
+
+
+
`; + +exports.install = function(instance) { + + var current = { total: 0, used: 0, free: 0, path: '', type: '', percentUsed: 0 }; + var tproc = null; + + instance.custom.run = function() { + + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + + if (!instance.options.enabled) + return; + + require('child_process').exec('df -hTB1 ' + instance.options.path, function(err, response) { + + tproc = setTimeout(instance.custom.run, instance.options.interval); + + if (err) { + instance.error(err); + return; + } + + response.parseTerminal(function(line) { + if (line[0][0] !== '/') + return; + current.total = line[2].parseInt(); + current.free = line[4].parseInt(); + current.used = line[3].parseInt(); + current.path = instance.options.path || '/'; + current.type = line[1]; + current.percentUsed = line[5]; + instance.custom.status(); + instance.send2(current); + }); + }); + }; + + instance.custom.status = function() { + if (instance.options.enabled) + instance.status(current.free.filesize() + ' / ' + current.total.filesize()); + else + instance.status('Disabled', 'red'); + }; + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + instance.options.enabled && instance.custom.run(); + }); + + instance.on('close', function() { + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + }); + + setTimeout(instance.custom.run, 1000); +}; \ No newline at end of file diff --git a/RVO13/flow_3_2_25/monitormemory.js b/RVO13/flow_3_2_25/monitormemory.js new file mode 100755 index 0000000..2decbc4 --- /dev/null +++ b/RVO13/flow_3_2_25/monitormemory.js @@ -0,0 +1,87 @@ +exports.id = 'monitormemory'; +exports.title = 'Memory'; +exports.version = '1.0.0'; +exports.author = 'Peter Širka'; +exports.group = 'Monitoring'; +exports.color = '#F6BB42'; +exports.output = 1; +exports.click = true; +exports.icon = 'microchip'; +exports.options = { interval: 8000, enabled: true }; +exports.readme = `# Memory monitoring + +This component monitors memory \`bytes\` consumption in Linux systems. It uses \`free\` command. + +__Data Example__: + +\`\`\`javascript +{ + total: 33558769664, + used: 1998868480, + free: 2653708288 +} +\`\`\``; + +exports.html = `
+
+
+
@(Interval in milliseconds)
+
+
+
`; + +exports.install = function(instance) { + + var current = { total: 0, used: 0, free: 0 }; + var tproc = null; + + instance.custom.run = function() { + + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + + if (!instance.options.enabled) + return; + + require('child_process').exec('free -b -t', function(err, response) { + + tproc = setTimeout(instance.custom.run, instance.options.interval); + + if (err) { + instance.error(err); + return; + } + + var memory = response.split('\n')[1].match(/\d+/g); + current.total = memory[0].parseInt(); + current.used = memory[1].parseInt() - memory[3].parseInt(); + current.free = current.total - current.used; + instance.custom.status(); + instance.send2(current); + }); + }; + + instance.custom.status = function() { + if (instance.options.enabled) + instance.status(current.free.filesize() + ' / ' + current.total.filesize()); + else + instance.status('Disabled', 'red'); + }; + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + instance.options.enabled && instance.custom.run(); + }); + + instance.on('close', function() { + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + }); + + setTimeout(instance.custom.run, 1000); +}; \ No newline at end of file diff --git a/RVO13/flow_3_2_25/nodesdb_changecheck.js b/RVO13/flow_3_2_25/nodesdb_changecheck.js new file mode 100755 index 0000000..be1e700 --- /dev/null +++ b/RVO13/flow_3_2_25/nodesdb_changecheck.js @@ -0,0 +1,70 @@ +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/RVO13/flow_3_2_25/show_dbdata.js b/RVO13/flow_3_2_25/show_dbdata.js new file mode 100755 index 0000000..d01eecd --- /dev/null +++ b/RVO13/flow_3_2_25/show_dbdata.js @@ -0,0 +1,241 @@ +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 = 7; +exports.output = 1; + +const { exec } = require('child_process'); + +exports.install = 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}) + }) + instance.on("5", _ => { + exec("sudo tail -n 25 monitor.txt" , (err, stdout, stderr) => { + if (err || stderr) instance.send(0,{err, stderr}); + else instance.send(0,stdout); + }) + }) + instance.on("6", _ => { + exec("sudo tail -n 25 err.txt" , (err, stdout, stderr) => { + if (err || stderr) instance.send(0,{err, stderr}); + else instance.send(0,stdout); + }) + }) +}; + + + +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/RVO13/flow_3_2_25/slack_filter.js b/RVO13/flow_3_2_25/slack_filter.js new file mode 100755 index 0000000..753c24a --- /dev/null +++ b/RVO13/flow_3_2_25/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 = `
+
+
+
@(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"] = []; + } + + instance.options.name = FLOW.GLOBALS.settings.rvo_name; + if (instance.options.name) { + instance.status('Running'); + running = true; + } else { + instance.status('Please run options again', 'red'); + running = false; + } + } catch (e) { + instance.error('Citysys connector: ' + e.message); + } + }; + + instance.on('options', instance.reconfigure); + setTimeout(instance.reconfigure, 10000); + + +}; diff --git a/RVO13/flow_3_2_25/thermometer.js b/RVO13/flow_3_2_25/thermometer.js new file mode 100755 index 0000000..fa015c6 --- /dev/null +++ b/RVO13/flow_3_2_25/thermometer.js @@ -0,0 +1,98 @@ +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 = 5;//minutes +let NUMBER_OF_FAILURES_TO_SEND_ERROR = 13; + +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) => { + + 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); + setTimeout(main, 20000); + }) +}; diff --git a/RVO13/flow_3_2_25/trigger.js b/RVO13/flow_3_2_25/trigger.js new file mode 100755 index 0000000..27545a8 --- /dev/null +++ b/RVO13/flow_3_2_25/trigger.js @@ -0,0 +1,79 @@ +exports.id = 'trigger'; +exports.title = 'Trigger'; +exports.group = 'Inputs'; +exports.color = '#F6BB42'; +exports.click = true; +exports.output = 1; +exports.version = '1.1.0'; +exports.author = 'Martin Smola'; +exports.icon = 'play'; + +exports.html = `
+
@(Data type (String by default))
+
@(Data)
+
Trigger 5s after initialization.
+
@(Useful when there's a need to run certain flow when the app restarts, etc.)
+
`; + +exports.readme = `# Trigger + +- Clicking on the component starts the chain +- Settings allows to set a data-type and a value`; + +exports.install = function(instance) { + + var value; + + instance.on('click', () => instance.send2(value)); + + instance.reconfigure = function() { + var options = instance.options; + value = null; + switch (options.datatype) { + case 'integer': + value = options.data.parseInt2('error'); + value = value === 'error' ? NaN : value; + break; + case 'float': + value = options.data.parseFloat2('error'); + value = value === 'error' ? NaN : value; + break; + case 'date': + options.data = options.data.toString(); + var num = options.data.parseInt('error'); + num === 'error' && (num = options.data.parseDate('error')); + num === 'error' && (num = null); + value = num ? new Date(num).toUTCString() : num; + break; + case 'object': + try { + value = (new Function('return ' + options.data))(); + } catch (e) { + instance.error(e); + } + break; + case 'boolean': + value = options.data.parseBoolean(); + break; + case 'buffer': + try { + value = U.createBuffer(options.data); + } catch (e) { + instance.error(e); + } + break; + case 'string': + default: + value = '' + (options.data || ''); + break; + } + }; + + instance.on('options', instance.reconfigure); + instance.reconfigure(); + + if (instance.options.restart) + setTimeout(function(){ + instance.send2(value); + }, 5000); +}; diff --git a/RVO13/flow_3_2_25/variables.txt b/RVO13/flow_3_2_25/variables.txt new file mode 100755 index 0000000..e69de29 diff --git a/RVO13/flow_3_2_25/virtualwirein.js b/RVO13/flow_3_2_25/virtualwirein.js new file mode 100755 index 0000000..38a4e42 --- /dev/null +++ b/RVO13/flow_3_2_25/virtualwirein.js @@ -0,0 +1,43 @@ +exports.id = 'virtualwirein'; +exports.title = 'Virtual wire in'; +exports.version = '1.0.0'; +exports.author = 'Martin Smola'; +exports.color = '#303E4D'; +exports.icon = 'sign-in'; +exports.input = false; +exports.output = 1; +exports.options = {}; +exports.readme = `# Virtual wire in + +When the wires between the components are mess it's time to use Virtual wire.`; + +exports.html = `
+
@(Wire name)
+
+`; + +exports.install = function(instance) { + + instance.custom.reconfigure = function(options){ + if (instance.options.wirename) { + instance.status(instance.options.wirename); + } else + instance.status('Not configured', 'red'); + }; + + ON('virtualwire', function(wirename, flowdata){ + if (instance.options.wirename && instance.options.wirename === wirename) + instance.send(flowdata); + }); + + instance.on('options', instance.custom.reconfigure); + instance.custom.reconfigure(); +}; diff --git a/RVO13/flow_3_2_25/virtualwireout.js b/RVO13/flow_3_2_25/virtualwireout.js new file mode 100755 index 0000000..94a1e4f --- /dev/null +++ b/RVO13/flow_3_2_25/virtualwireout.js @@ -0,0 +1,41 @@ +exports.id = 'virtualwireout'; +exports.title = 'Virtual wire out'; +exports.version = '1.0.0'; +exports.author = 'Martin Smola'; +exports.color = '#303E4D'; +exports.icon = 'sign-out'; +exports.input = true; +exports.options = {}; +exports.readme = `# Virtual wire out + +When the wires between the components are mess it's time to use Virtual wire.`; + +exports.html = `
+
@(Wire name)
+
+`; + +exports.install = function(instance) { + + instance.custom.reconfigure = function(){ + if (instance.options.wirename) { + instance.status(instance.options.wirename); + } else + instance.status('Not configured', 'red'); + }; + + instance.on('data', function(flowdata) { + EMIT('virtualwire', instance.options.wirename, flowdata); + }); + + instance.on('options', instance.custom.reconfigure); + instance.custom.reconfigure(); +}; diff --git a/RVO13/flow_3_2_25/wsmqttpublish.js b/RVO13/flow_3_2_25/wsmqttpublish.js new file mode 100755 index 0000000..b2a218d --- /dev/null +++ b/RVO13/flow_3_2_25/wsmqttpublish.js @@ -0,0 +1,477 @@ +exports.id = 'wsmqttpublish'; +exports.title = 'WS MQTT publish'; +exports.group = 'MQTT'; +exports.color = '#888600'; +exports.version = '1.0.2'; +exports.icon = 'sign-out'; +exports.input = 2; +exports.output = 3; +exports.options = { host: 'tb-stage.worksys.io', port: 1883, clientid: "", username: "" }; + +exports.html = `
+
+
+
Hostname or IP address (if not empty - setting will override db setting)
+
+
+
Port
+
+
+
+
+
@(Client id)
+
+
+
@(Username)
+
+
+
`; + + +exports.readme = ` +# WS MQTT Publish + +Version 1.0.3. + +Added: +- database collections, +- 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 = { + debug: 0, + rpcCall: 1, + services: 2 +} + +//CONFIG +let createTelemetryBackup = true; +let saveTelemetryOnError = true;//backup_on_failure overrides this value +//------------------------ + +let rollers; +if(createTelemetryBackup) rollers = require('streamroller'); + +const noSqlFileSizeLimit = 4194304;//use 5MB - 4194304 +let insertNoSqlCounter = 0; +let insertBackupNoSqlCounter = 0; +let processingData = false; + +let backup_on_failure = false;//== saveTelemetryOnError - create backup client 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; + +process.on('uncaughtException', function (err) { + + errLogger.error('uncaughtException:', err.message) + errLogger.error(err.stack); + + //TODO + //send to service + + //process.exit(1); +}) + +const nosql = NOSQL('tbdata'); +const nosqlBackup = NOSQL('/backup/tbdata'); + + +exports.install = function(instance) { + + var client; + var opts; + var clientReady = false; + + // wsmqtt status for notification purposes on projects.worksys.io database + let wsmqttName = null; + let sendWsStatusVar = null; + let wsmqtt_status = 'disconnected'; + + 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'; + } + + function sendWsStatus() + { + instance.send(SEND_TO.services, {[wsmqttName]: wsmqtt_status}); + } + + + function main() + { + if(!FLOW.dbLoaded) return; + + loadSettings(); + clearInterval(sendWsStatus); + sendWsStatusVar = setInterval(sendWsStatus, 180000); + } + + //set opts according to db settings + function loadSettings() + { + + if(instance.options.host !== "") + { + //override settings from database + var o = instance.options; + opts = { + host: o.host, + port: o.port, + clientId: o.clientid, + username: o.username, + rejectUnauthorized: false, + resubscribe: false + }; + + wsmqttName = getWsmqttName(o.host); + + console.log("wsmqttpublich -> loadSettings from instance.options", instance.options); + } + else + { + + const SETTINGS = FLOW.GLOBALS.settings; + backup_on_failure = SETTINGS.backup_on_failure; + saveTelemetryOnError = backup_on_failure; + + restore_from_backup = SETTINGS.restore_from_backup; + restore_backup_wait = SETTINGS.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; + + opts = { + host: mqtt_host, + port: mqtt_port, + keepalive: 10, + clientId: mqtt_clientid, + username: mqtt_username, + rejectUnauthorized: false, + resubscribe: false + }; + + wsmqttName = getWsmqttName(mqtt_host); + } + + connectToTbServer(); + } + + function connectToTbServer() + { + 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"); + monitor.info("MQTT client connected"); + + sendClientError = true; + clientReady = true; + wsmqtt_status = 'connected'; + }); + + client.on('reconnect', function() { + instance.status("Reconnecting", "yellow"); + clientReady = false; + }); + + client.on('message', function(topic, message) { + // message is type of buffer + message = message.toString(); + if (message[0] === '{') { + TRY(function() { + + message = JSON.parse(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}}); + } + + }, () => instance.debug('MQTT: Error parsing data', message)); + } + + instance.send(SEND_TO.rpcCall, {"topic":topic, "content":message }); + }); + + client.on('close', function() { + clientReady = false; + wsmqtt_status = 'disconnected'; + + instance.status("Disconnected", "red"); + instance.send(SEND_TO.debug, {"message":"Client CLOSE signal received !"}); + }); + + client.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; + wsmqtt_status = 'disconnected'; + }); + + } + + + instance.on("0", _ => { + main(); + }) + + + instance.on('1', function(data) { + + if(clientReady) + { + //do we have some data in backup file? if any, process data from database + if(saveTelemetryOnError) + { + //read telemetry data and send back to server + if(!processingData) processDataFromDatabase(); + } + + let stringifiedJson = JSON.stringify(data.data); + client.publish("v1/gateway/telemetry", stringifiedJson, {qos: 1}); + + //backup telemetry + if(createTelemetryBackup) + { + data.data.id = UID(); + nosqlBackup.insert(data.data); + + insertBackupNoSqlCounter++; + if(insertBackupNoSqlCounter > 150) + { + let options = {compress: true}; + let path = __dirname + "/../databases/backup/tbdata.nosql"; + var stream = new rollers.RollingFileStream(path, noSqlFileSizeLimit, 150, options); + stream.write(""); + stream.end(); + + insertBackupNoSqlCounter = 0; + } + } + + } + 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(saveTelemetryOnError) + { + //create new file from tbdata.nosql, if file size exceeds given limit, and clear tbdata.nosql + makeBackupFromDbFile(); + + //write to tb + data.data.id = UID(); + nosql.insert(data.data); + } + } + }); + + + instance.close = function(done) { + if(clientReady){ + client.end(); + clearInterval(sendWsStatusVar); + } + }; + + + function getDbBackupFileCounter(type) + { + var files = fs.readdirSync(__dirname + "/../databases"); + + let counter = 0; + for(var i = 0; i < files.length; i++) + { + + if(files[i] == "tbdata.nosql") continue; + + if(files[i].endsWith(".nosql")) + { + + let pos = files[i].indexOf("."); + if(pos > -1) + { + + let fileCounter = counter; + let firstDigit = files[i].slice(0, pos); + + fileCounter = parseInt(firstDigit); + if(isNaN(fileCounter)) fileCounter = 0; + //console.log("getDbBackupFileCounter digit:", files[i], firstDigit, fileCounter, isNaN(fileCounter), type); + + if(type == "max") + { + if(fileCounter > counter) + { + counter = fileCounter; + } + } + else if(type == "min") + { + if(counter == 0) counter = fileCounter; + + if(fileCounter < counter) + { + counter = fileCounter; + } + } + } + } + + } + + if(type == "max") counter++; + + return counter; + } + + const makeBackupFromDbFile = async () => { + + if(!saveTelemetryOnError) return; + + //to avoid large file: tbdata.nosql + + //init value is 0! + if(insertNoSqlCounter > 0) + { + --insertNoSqlCounter; + return; + } + + insertNoSqlCounter = 100; + + let source = __dirname + "/../databases/tbdata.nosql"; + + var stats = fs.statSync(source); + var fileSizeInBytes = stats.size; + + if(fileSizeInBytes > noSqlFileSizeLimit) + { + + let counter = 1; + counter = getDbBackupFileCounter("max"); + + let destination = __dirname + "/../databases/" + counter + "." + "tbdata.nosql"; + + //make backup file + fs.copyFileSync(source, destination); + //fs.renameSync(p, p + "." + counter); + + //clear tbdata.nosql + fs.writeFileSync(source, ""); + fs.truncateSync(source, 0); + + } + } + + const processDataFromDatabase = async () => { + + if(restore_from_backup <= 0) return; + + //calculate diff + const now = new Date(); + let currentTime = now.getTime(); + let diff = currentTime - lastRestoreTime; + + if( (diff / 1000) < restore_backup_wait) + { + //console.log("*********restore_backup_wait", diff, restore_backup_wait); + return; + } + + processingData = true; + + //get filename to process + let counter = getDbBackupFileCounter("min"); + + //we have some backup files + let dataBase = 'tbdata'; + + var nosql; + if(counter == 0) dataBase = 'tbdata'; + else dataBase = counter + "." + 'tbdata'; + + nosql = NOSQL(dataBase); + + //select all data - use limit restore_from_backup + let records = await promisifyBuilder(nosql.find().take(restore_from_backup)); + + for(let i = 0; i < records.length; i++) + { + if(clientReady) { + + let item = records[i]; + let id = item.id; + + if(id !== undefined) + { + //console.log("------------processDataFromDatabase - remove", id, dataBase, i); + + try { + + let message = JSON.parse(JSON.stringify(item)); + delete message.id; + + client.publish("v1/gateway/telemetry", JSON.stringify(message), {qos:1}); + + //remove from database + await promisifyBuilder(nosql.remove().where("id", id)); + + } catch(error) { + //process error + console.log("processDataFromDatabase", error); + } + + } + + } + else + { + processingData = false; + return; + } + } + + if(records.length > 0) + { + //clean backup file + if(counter > 0) nosql.clean(); + } + + //no data in db, remove + if(records.length == 0) + { + if(counter > 0) nosql.drop(); + } + + const d = new Date(); + lastRestoreTime = d.getTime(); + + processingData = false; + + } + + instance.on('options', main); + //instance.reconfigure(); +}; diff --git a/RVO13/monitor.txt b/RVO13/monitor.txt new file mode 100755 index 0000000..3c4dfc3 --- /dev/null +++ b/RVO13/monitor.txt @@ -0,0 +1,11116 @@ +[2024-10-11T13:29:53.206] [INFO] monitorLogs - MQTT broker error Error: connect ECONNREFUSED 192.168.252.1:1883 + at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1159:16) { + errno: -111, + code: 'ECONNREFUSED', + syscall: 'connect', + address: '192.168.252.1', + port: 1883 +} +[2024-10-11T13:30:23.427] [INFO] monitorLogs - MQTT broker connected +[2024-10-11T18:20:59.605] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-10-11T18:20:59.608] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-10-11T18:20:59.610] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-10-11T18:20:59.613] [INFO] monitorLogs - turnOnLine (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2024-10-11T18:41:03.247] [INFO] monitorLogs - turnOnLine (line, pin, force) 4 relay1_05 false aplikovany bod profilu +[2024-10-11T18:41:03.283] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-11T18:41:03.319] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-11T18:41:03.356] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-12T03:23:16.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-12 03:23:16 +[2024-10-12T06:53:38.136] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-10-12T06:53:38.139] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-10-12T06:53:38.142] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-10-12T06:53:38.145] [INFO] monitorLogs - turnOffLine (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2024-10-12T07:37:50.205] [INFO] monitorLogs - turnOffLine (line, pin, force) 4 relay1_05 false aplikovany bod profilu +[2024-10-12T07:37:50.240] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-12T07:37:50.275] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-12T07:37:50.310] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-12T14:55:18.268] [INFO] monitorLogs - MQTT broker connected +[2024-10-12T18:19:19.683] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-10-12T18:19:19.686] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-10-12T18:19:19.689] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-10-12T18:19:19.692] [INFO] monitorLogs - turnOnLine (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2024-10-12T18:39:05.118] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-12T18:39:05.153] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-12T18:39:05.189] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-12T18:39:05.225] [INFO] monitorLogs - turnOnLine (line, pin, force) 4 relay1_05 false aplikovany bod profilu +[2024-10-13T03:23:18.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-13 03:23:18 +[2024-10-13T07:00:24.151] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-10-13T07:00:24.154] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-10-13T07:00:24.157] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-10-13T07:00:24.160] [INFO] monitorLogs - turnOffLine (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2024-10-13T07:14:40.150] [INFO] monitorLogs - MQTT broker connected +[2024-10-13T07:39:20.629] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-13T07:39:20.664] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-13T07:39:20.699] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-13T07:39:20.735] [INFO] monitorLogs - turnOffLine (line, pin, force) 4 relay1_05 false aplikovany bod profilu +[2024-10-13T18:15:05.452] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-10-13T18:15:05.455] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-10-13T18:15:05.457] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-10-13T18:15:05.460] [INFO] monitorLogs - turnOnLine (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2024-10-13T18:37:04.739] [INFO] monitorLogs - turnOnLine (line, pin, force) 4 relay1_05 false aplikovany bod profilu +[2024-10-13T18:37:04.775] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-13T18:37:04.810] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-13T18:37:04.846] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-14T03:23:19.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-14 03:23:19 +[2024-10-14T06:56:10.225] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-10-14T06:56:10.227] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-10-14T06:56:10.230] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-10-14T06:56:10.232] [INFO] monitorLogs - turnOffLine (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2024-10-14T07:40:50.517] [INFO] monitorLogs - turnOffLine (line, pin, force) 4 relay1_05 false aplikovany bod profilu +[2024-10-14T07:40:50.553] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-14T07:40:50.590] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-14T07:40:50.625] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-14T18:15:33.933] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-10-14T18:15:33.936] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-10-14T18:15:33.938] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-10-14T18:15:33.941] [INFO] monitorLogs - turnOnLine (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2024-10-14T18:35:04.111] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-14T18:35:04.148] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-14T18:35:04.183] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-14T18:35:04.218] [INFO] monitorLogs - turnOnLine (line, pin, force) 4 relay1_05 false aplikovany bod profilu +[2024-10-15T03:23:20.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-15 03:23:20 +[2024-10-15T06:44:37.529] [INFO] monitorLogs - MQTT broker connected +[2024-10-15T06:46:13.786] [INFO] monitorLogs - MQTT broker connected +[2024-10-15T07:12:04.054] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-10-15T07:12:04.057] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-10-15T07:12:04.059] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-10-15T07:12:04.061] [INFO] monitorLogs - turnOffLine (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2024-10-15T07:25:51.416] [INFO] monitorLogs - MQTT broker connected +[2024-10-15T07:27:03.421] [INFO] monitorLogs - MQTT broker connected +[2024-10-15T07:39:52.737] [INFO] monitorLogs - MQTT broker connected +[2024-10-15T07:42:21.068] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-15T07:42:21.104] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-15T07:42:21.139] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-15T07:42:21.175] [INFO] monitorLogs - turnOffLine (line, pin, force) 4 relay1_05 false aplikovany bod profilu +[2024-10-15T07:43:23.791] [INFO] monitorLogs - MQTT broker connected +[2024-10-15T07:47:14.419] [INFO] monitorLogs - MQTT broker connected +[2024-10-15T07:50:44.446] [INFO] monitorLogs - MQTT broker connected +[2024-10-15T07:56:15.564] [INFO] monitorLogs - MQTT broker connected +[2024-10-15T08:02:19.056] [INFO] monitorLogs - MQTT broker connected +[2024-10-15T08:05:48.126] [INFO] monitorLogs - MQTT broker connected +[2024-10-15T08:08:57.684] [INFO] monitorLogs - MQTT broker connected +[2024-10-15T18:13:20.753] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-10-15T18:13:20.755] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-10-15T18:13:20.759] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-10-15T18:13:20.762] [INFO] monitorLogs - turnOnLine (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2024-10-15T18:33:06.230] [INFO] monitorLogs - turnOnLine (line, pin, force) 4 relay1_05 false aplikovany bod profilu +[2024-10-15T18:33:06.266] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-15T18:33:06.302] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-15T18:33:06.337] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-16T02:26:06.099] [INFO] monitorLogs - MQTT broker connected +[2024-10-16T03:23:21.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-16 03:23:21 +[2024-10-16T06:59:04.277] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-10-16T06:59:04.279] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-10-16T06:59:04.282] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-10-16T06:59:04.284] [INFO] monitorLogs - turnOffLine (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2024-10-16T07:43:52.431] [INFO] monitorLogs - turnOffLine (line, pin, force) 4 relay1_05 false aplikovany bod profilu +[2024-10-16T07:43:52.466] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-16T07:43:52.502] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-16T07:43:52.538] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-16T08:52:07.766] [INFO] monitorLogs - MQTT broker connected +[2024-10-16T08:52:42.385] [INFO] monitorLogs - MQTT broker connected +[2024-10-16T08:54:01.823] [INFO] monitorLogs - MQTT broker connected +[2024-10-16T09:00:19.002] [INFO] monitorLogs - MQTT broker connected +[2024-10-16T09:01:23.254] [INFO] monitorLogs - MQTT broker connected +[2024-10-16T09:02:16.036] [INFO] monitorLogs - MQTT broker connected +[2024-10-16T09:03:07.227] [INFO] monitorLogs - MQTT broker connected +[2024-10-16T09:03:53.269] [INFO] monitorLogs - MQTT broker connected +[2024-10-16T09:05:19.530] [INFO] monitorLogs - MQTT broker connected +[2024-10-16T09:05:44.602] [INFO] monitorLogs - MQTT broker connected +[2024-10-16T09:07:13.738] [INFO] monitorLogs - MQTT broker connected +[2024-10-16T09:48:25.786] [INFO] monitorLogs - MQTT broker connected +[2024-10-16T09:49:43.966] [INFO] monitorLogs - MQTT broker connected +[2024-10-16T09:50:14.328] [INFO] monitorLogs - MQTT broker connected +[2024-10-16T09:56:54.590] [INFO] monitorLogs - MQTT broker connected +[2024-10-16T09:58:45.159] [INFO] monitorLogs - MQTT broker connected +[2024-10-16T10:00:31.406] [INFO] monitorLogs - MQTT broker connected +[2024-10-16T10:02:13.985] [INFO] monitorLogs - MQTT broker connected +[2024-10-16T10:04:05.171] [INFO] monitorLogs - MQTT broker connected +[2024-10-16T10:04:46.415] [INFO] monitorLogs - MQTT broker connected +[2024-10-16T10:05:31.359] [INFO] monitorLogs - MQTT broker connected +[2024-10-16T10:31:38.499] [INFO] monitorLogs - MQTT broker connected +[2024-10-16T10:32:02.703] [INFO] monitorLogs - MQTT broker connected +[2024-10-16T10:35:01.110] [INFO] monitorLogs - MQTT broker connected +[2024-10-16T10:36:02.460] [INFO] monitorLogs - MQTT broker connected +[2024-10-16T10:38:11.860] [INFO] monitorLogs - MQTT broker connected +[2024-10-16T10:43:15.588] [INFO] monitorLogs - MQTT broker connected +[2024-10-16T10:49:14.565] [INFO] monitorLogs - MQTT broker connected +[2024-10-16T10:50:20.710] [INFO] monitorLogs - MQTT broker connected +[2024-10-16T10:51:33.949] [INFO] monitorLogs - MQTT broker connected +[2024-10-16T10:54:44.352] [INFO] monitorLogs - MQTT broker connected +[2024-10-16T10:55:41.995] [INFO] monitorLogs - MQTT broker connected +[2024-10-16T18:12:07.033] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-10-16T18:12:07.036] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-10-16T18:12:07.038] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-10-16T18:12:07.040] [INFO] monitorLogs - turnOnLine (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2024-10-16T18:31:09.371] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-16T18:31:09.407] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-16T18:31:09.443] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-16T18:31:09.479] [INFO] monitorLogs - turnOnLine (line, pin, force) 4 relay1_05 false aplikovany bod profilu +[2024-10-17T03:23:22.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-17 03:23:22 +[2024-10-17T07:02:39.116] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-10-17T07:02:39.119] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-10-17T07:02:39.121] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-10-17T07:02:39.123] [INFO] monitorLogs - turnOffLine (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2024-10-17T07:45:23.843] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-17T07:45:23.880] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-17T07:45:23.915] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-17T07:45:23.951] [INFO] monitorLogs - turnOffLine (line, pin, force) 4 relay1_05 false aplikovany bod profilu +[2024-10-17T08:30:28.213] [INFO] monitorLogs - MQTT broker connected +[2024-10-17T08:33:00.218] [INFO] monitorLogs - MQTT broker connected +[2024-10-17T08:33:41.811] [INFO] monitorLogs - MQTT broker connected +[2024-10-17T08:35:40.725] [INFO] monitorLogs - MQTT broker connected +[2024-10-17T08:39:18.314] [INFO] monitorLogs - MQTT broker connected +[2024-10-17T08:42:56.150] [INFO] monitorLogs - MQTT broker connected +[2024-10-17T13:39:14.119] [INFO] monitorLogs - MQTT broker connected +[2024-10-17T13:45:07.386] [INFO] monitorLogs - MQTT broker connected +[2024-10-17T13:46:04.074] [INFO] monitorLogs - MQTT broker connected +[2024-10-17T13:47:06.744] [INFO] monitorLogs - MQTT broker connected +[2024-10-17T18:11:11.361] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-10-17T18:11:11.365] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-10-17T18:11:11.368] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-10-17T18:11:11.371] [INFO] monitorLogs - turnOnLine (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2024-10-17T18:29:15.543] [INFO] monitorLogs - turnOnLine (line, pin, force) 4 relay1_05 false aplikovany bod profilu +[2024-10-17T18:29:15.580] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-17T18:29:15.616] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-17T18:29:15.653] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-18T03:23:23.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-18 03:23:23 +[2024-10-18T07:01:53.929] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-10-18T07:01:53.932] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-10-18T07:01:53.934] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-10-18T07:01:53.937] [INFO] monitorLogs - turnOffLine (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2024-10-18T07:46:55.424] [INFO] monitorLogs - turnOffLine (line, pin, force) 4 relay1_05 false aplikovany bod profilu +[2024-10-18T07:46:55.459] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-18T07:46:55.496] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-18T07:46:55.532] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-18T09:49:36.999] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T16:22:17.210] [INFO] monitorLogs - MQTT broker error Error: Connection refused: Server unavailable + at MqttClient._handleConnack (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:1388:17) + at MqttClient._handlePacket (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:549:12) + at work (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:438:12) + at Writable.writable._write (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:452:5) + at doWrite (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:409:139) + at writeOrBuffer (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:398:5) + at Writable.write (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:307:11) + at Socket.ondata (internal/streams/readable.js:731:22) + at Socket.emit (events.js:400:28) + at addChunk (internal/streams/readable.js:293:12) { + code: 3 +} +[2024-10-18T16:22:48.726] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T17:20:12.756] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T17:20:13.903] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T17:27:58.196] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T17:29:24.595] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T17:29:50.442] [INFO] monitorLogs - MQTT broker error Error: Connection refused: Server unavailable + at MqttClient._handleConnack (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:1388:17) + at MqttClient._handlePacket (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:549:12) + at work (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:438:12) + at Writable.writable._write (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:452:5) + at doWrite (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:409:139) + at writeOrBuffer (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:398:5) + at Writable.write (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:307:11) + at Socket.ondata (internal/streams/readable.js:731:22) + at Socket.emit (events.js:400:28) + at addChunk (internal/streams/readable.js:293:12) { + code: 3 +} +[2024-10-18T17:29:50.590] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T17:30:29.846] [INFO] monitorLogs - MQTT broker error Error: Connection refused: Server unavailable + at MqttClient._handleConnack (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:1388:17) + at MqttClient._handlePacket (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:549:12) + at work (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:438:12) + at Writable.writable._write (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:452:5) + at doWrite (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:409:139) + at writeOrBuffer (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:398:5) + at Writable.write (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:307:11) + at Socket.ondata (internal/streams/readable.js:731:22) + at Socket.emit (events.js:400:28) + at addChunk (internal/streams/readable.js:293:12) { + code: 3 +} +[2024-10-18T17:30:29.986] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T17:31:23.389] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T17:31:59.502] [INFO] monitorLogs - MQTT broker error Error: Connection refused: Server unavailable + at MqttClient._handleConnack (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:1388:17) + at MqttClient._handlePacket (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:549:12) + at work (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:438:12) + at Writable.writable._write (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:452:5) + at doWrite (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:409:139) + at writeOrBuffer (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:398:5) + at Writable.write (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:307:11) + at Socket.ondata (internal/streams/readable.js:731:22) + at Socket.emit (events.js:400:28) + at addChunk (internal/streams/readable.js:293:12) { + code: 3 +} +[2024-10-18T17:40:47.243] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T17:50:04.905] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T17:50:05.756] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T17:54:26.622] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T17:54:59.293] [INFO] monitorLogs - MQTT broker error Error: Connection refused: Server unavailable + at MqttClient._handleConnack (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:1388:17) + at MqttClient._handlePacket (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:549:12) + at work (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:438:12) + at Writable.writable._write (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:452:5) + at doWrite (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:409:139) + at writeOrBuffer (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:398:5) + at Writable.write (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:307:11) + at Socket.ondata (internal/streams/readable.js:731:22) + at Socket.emit (events.js:400:28) + at addChunk (internal/streams/readable.js:293:12) { + code: 3 +} +[2024-10-18T18:03:29.793] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T18:08:24.399] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-10-18T18:08:24.402] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-10-18T18:08:24.404] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-10-18T18:08:24.407] [INFO] monitorLogs - turnOnLine (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2024-10-18T18:15:35.118] [INFO] monitorLogs - MQTT broker error Error: Connection refused: Server unavailable + at MqttClient._handleConnack (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:1388:17) + at MqttClient._handlePacket (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:549:12) + at work (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:438:12) + at Writable.writable._write (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:452:5) + at doWrite (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:409:139) + at writeOrBuffer (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:398:5) + at Writable.write (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:307:11) + at Socket.ondata (internal/streams/readable.js:731:22) + at Socket.emit (events.js:400:28) + at addChunk (internal/streams/readable.js:293:12) { + code: 3 +} +[2024-10-18T18:15:35.262] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T18:27:20.167] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-18T18:27:20.202] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-18T18:27:20.237] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-18T18:27:20.272] [INFO] monitorLogs - turnOnLine (line, pin, force) 4 relay1_05 false aplikovany bod profilu +[2024-10-18T18:36:52.538] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T20:03:33.103] [INFO] monitorLogs - MQTT broker error Error: Connection refused: Server unavailable + at MqttClient._handleConnack (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:1388:17) + at MqttClient._handlePacket (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:549:12) + at work (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:438:12) + at Writable.writable._write (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:452:5) + at doWrite (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:409:139) + at writeOrBuffer (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:398:5) + at Writable.write (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:307:11) + at Socket.ondata (internal/streams/readable.js:731:22) + at Socket.emit (events.js:400:28) + at addChunk (internal/streams/readable.js:293:12) { + code: 3 +} +[2024-10-18T20:03:39.855] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T20:06:38.895] [INFO] monitorLogs - MQTT broker error Error: Connection refused: Server unavailable + at MqttClient._handleConnack (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:1388:17) + at MqttClient._handlePacket (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:549:12) + at work (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:438:12) + at Writable.writable._write (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:452:5) + at doWrite (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:409:139) + at writeOrBuffer (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:398:5) + at Writable.write (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:307:11) + at Socket.ondata (internal/streams/readable.js:731:22) + at Socket.emit (events.js:400:28) + at addChunk (internal/streams/readable.js:293:12) { + code: 3 +} +[2024-10-18T20:30:06.329] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T20:30:06.505] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T20:44:09.072] [INFO] monitorLogs - MQTT broker connected +[2024-10-19T03:23:25.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-19 03:23:25 +[2024-10-19T07:06:26.641] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-10-19T07:06:26.644] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-10-19T07:06:26.647] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-10-19T07:06:26.650] [INFO] monitorLogs - turnOffLine (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2024-10-19T07:48:27.719] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-19T07:48:27.754] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-19T07:48:27.790] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-19T07:48:27.826] [INFO] monitorLogs - turnOffLine (line, pin, force) 4 relay1_05 false aplikovany bod profilu +[2024-10-19T17:03:21.827] [INFO] monitorLogs - MQTT broker error Error: Connection refused: Server unavailable + at MqttClient._handleConnack (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:1388:17) + at MqttClient._handlePacket (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:549:12) + at work (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:438:12) + at Writable.writable._write (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:452:5) + at doWrite (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:409:139) + at writeOrBuffer (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:398:5) + at Writable.write (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:307:11) + at Socket.ondata (internal/streams/readable.js:731:22) + at Socket.emit (events.js:400:28) + at addChunk (internal/streams/readable.js:293:12) { + code: 3 +} +[2024-10-19T17:03:28.545] [INFO] monitorLogs - MQTT broker connected +[2024-10-19T18:04:02.807] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-10-19T18:04:02.811] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-10-19T18:04:02.814] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-10-19T18:04:02.816] [INFO] monitorLogs - turnOnLine (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2024-10-19T18:25:24.251] [INFO] monitorLogs - turnOnLine (line, pin, force) 4 relay1_05 false aplikovany bod profilu +[2024-10-19T18:25:24.287] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-19T18:25:24.323] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-19T18:25:24.358] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-20T03:23:26.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-20 03:23:26 +[2024-10-20T07:03:52.485] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-10-20T07:03:52.488] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-10-20T07:03:52.490] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-10-20T07:03:52.493] [INFO] monitorLogs - turnOffLine (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2024-10-20T07:50:00.095] [INFO] monitorLogs - turnOffLine (line, pin, force) 4 relay1_05 false aplikovany bod profilu +[2024-10-20T07:50:00.131] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-20T07:50:00.166] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-20T07:50:00.202] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-20T14:29:14.194] [INFO] monitorLogs - MQTT broker error Error: Connection refused: Server unavailable + at MqttClient._handleConnack (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:1388:17) + at MqttClient._handlePacket (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:549:12) + at work (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:438:12) + at Writable.writable._write (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:452:5) + at doWrite (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:409:139) + at writeOrBuffer (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:398:5) + at Writable.write (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:307:11) + at Socket.ondata (internal/streams/readable.js:731:22) + at Socket.emit (events.js:400:28) + at addChunk (internal/streams/readable.js:293:12) { + code: 3 +} +[2024-10-20T14:29:14.342] [INFO] monitorLogs - MQTT broker connected +[2024-10-20T14:29:36.904] [INFO] monitorLogs - MQTT broker error Error: Connection refused: Server unavailable + at MqttClient._handleConnack (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:1388:17) + at MqttClient._handlePacket (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:549:12) + at work (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:438:12) + at Writable.writable._write (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:452:5) + at doWrite (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:409:139) + at writeOrBuffer (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:398:5) + at Writable.write (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:307:11) + at Socket.ondata (internal/streams/readable.js:731:22) + at Socket.emit (events.js:400:28) + at addChunk (internal/streams/readable.js:293:12) { + code: 3 +} +[2024-10-20T14:29:37.024] [INFO] monitorLogs - MQTT broker connected +[2024-10-20T18:03:39.690] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-10-20T18:03:39.693] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-10-20T18:03:39.695] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-10-20T18:03:39.698] [INFO] monitorLogs - turnOnLine (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2024-10-20T18:23:31.116] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-20T18:23:31.153] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-20T18:23:31.188] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-20T18:23:31.224] [INFO] monitorLogs - turnOnLine (line, pin, force) 4 relay1_05 false aplikovany bod profilu +[2024-10-21T03:23:27.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-21 03:23:27 +[2024-10-21T03:51:33.755] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T03:51:33.922] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T04:10:16.689] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T04:10:18.191] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T04:37:28.104] [INFO] monitorLogs - MQTT broker error Error: Connection refused: Server unavailable + at MqttClient._handleConnack (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:1388:17) + at MqttClient._handlePacket (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:549:12) + at work (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:438:12) + at Writable.writable._write (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:452:5) + at doWrite (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:409:139) + at writeOrBuffer (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:398:5) + at Writable.write (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:307:11) + at Socket.ondata (internal/streams/readable.js:731:22) + at Socket.emit (events.js:400:28) + at addChunk (internal/streams/readable.js:293:12) { + code: 3 +} +[2024-10-21T04:37:30.781] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T04:37:32.197] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T06:59:56.459] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T07:05:36.844] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-10-21T07:05:36.847] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-10-21T07:05:36.849] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-10-21T07:05:36.851] [INFO] monitorLogs - turnOffLine (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2024-10-21T07:48:55.584] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T07:51:32.924] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-21T07:51:32.960] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-21T07:51:32.996] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-21T07:51:33.031] [INFO] monitorLogs - turnOffLine (line, pin, force) 4 relay1_05 false aplikovany bod profilu +[2024-10-21T07:59:58.352] [INFO] monitorLogs - MQTT broker error Error: Connection refused: Server unavailable + at MqttClient._handleConnack (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:1388:17) + at MqttClient._handlePacket (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:549:12) + at work (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:438:12) + at Writable.writable._write (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:452:5) + at doWrite (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:409:139) + at writeOrBuffer (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:398:5) + at Writable.write (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:307:11) + at Socket.ondata (internal/streams/readable.js:731:22) + at Socket.emit (events.js:400:28) + at addChunk (internal/streams/readable.js:293:12) { + code: 3 +} +[2024-10-21T08:00:07.907] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T09:11:24.180] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T09:11:24.630] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T09:22:04.374] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T09:55:22.429] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T09:55:22.634] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T10:04:14.903] [INFO] monitorLogs - MQTT broker error Error: Connection refused: Server unavailable + at MqttClient._handleConnack (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:1388:17) + at MqttClient._handlePacket (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:549:12) + at work (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:438:12) + at Writable.writable._write (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:452:5) + at doWrite (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:409:139) + at writeOrBuffer (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:398:5) + at Writable.write (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:307:11) + at Socket.ondata (internal/streams/readable.js:731:22) + at Socket.emit (events.js:400:28) + at addChunk (internal/streams/readable.js:293:12) { + code: 3 +} +[2024-10-21T10:07:34.580] [INFO] monitorLogs - MQTT broker error Error: Connection refused: Server unavailable + at MqttClient._handleConnack (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:1388:17) + at MqttClient._handlePacket (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:549:12) + at work (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:438:12) + at Writable.writable._write (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:452:5) + at doWrite (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:409:139) + at writeOrBuffer (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:398:5) + at Writable.write (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:307:11) + at Socket.ondata (internal/streams/readable.js:731:22) + at Socket.emit (events.js:400:28) + at addChunk (internal/streams/readable.js:293:12) { + code: 3 +} +[2024-10-21T10:07:37.684] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T10:08:29.523] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T10:23:10.193] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T10:23:10.684] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T10:35:23.767] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T10:36:42.448] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T10:44:27.050] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T10:44:33.555] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T11:45:20.752] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T11:45:21.071] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T11:56:16.404] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T18:02:35.588] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-10-21T18:02:35.591] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-10-21T18:02:35.594] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-10-21T18:02:35.598] [INFO] monitorLogs - turnOnLine (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2024-10-21T18:21:39.212] [INFO] monitorLogs - turnOnLine (line, pin, force) 4 relay1_05 false aplikovany bod profilu +[2024-10-21T18:21:39.247] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-21T18:21:39.283] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-21T18:21:39.319] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-22T03:23:28.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-22 03:23:28 +[2024-10-22T07:08:02.052] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-10-22T07:08:02.069] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-10-22T07:08:02.071] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-10-22T07:08:02.073] [INFO] monitorLogs - turnOffLine (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2024-10-22T07:53:06.123] [INFO] monitorLogs - turnOffLine (line, pin, force) 4 relay1_05 false aplikovany bod profilu +[2024-10-22T07:53:06.158] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-22T07:53:06.193] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-22T07:53:06.229] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-22T18:02:08.528] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-10-22T18:02:08.531] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-10-22T18:02:08.533] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-10-22T18:02:08.535] [INFO] monitorLogs - turnOnLine (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2024-10-22T18:19:51.050] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-22T18:19:51.086] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-22T18:19:51.122] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-22T18:19:51.158] [INFO] monitorLogs - turnOnLine (line, pin, force) 4 relay1_05 false aplikovany bod profilu +[2024-10-23T03:23:29.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-23 03:23:29 +[2024-10-23T07:10:55.469] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-10-23T07:10:55.472] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-10-23T07:10:55.474] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-10-23T07:10:55.476] [INFO] monitorLogs - turnOffLine (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2024-10-23T07:54:39.767] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-23T07:54:39.802] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-23T07:54:39.837] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-23T07:54:39.873] [INFO] monitorLogs - turnOffLine (line, pin, force) 4 relay1_05 false aplikovany bod profilu +[2024-10-23T16:09:32.159] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2024-10-23T16:09:32.507] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 true turn off on startup +[2024-10-23T16:09:32.521] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 true turn off on startup +[2024-10-23T16:09:32.526] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 true turn off on startup +[2024-10-23T16:09:32.532] [INFO] monitorLogs - turnOffLine (line, pin, force) 4 relay1_05 true turn off on startup +[2024-10-23T16:09:33.996] [INFO] monitorLogs - MQTT broker connected +[2024-10-23T16:09:37.544] [INFO] monitorLogs - buildTasks - params undefined +[2024-10-23T16:09:37.546] [INFO] monitorLogs - buildTasks: profile for line 1 +[2024-10-23T16:09:37.547] [INFO] monitorLogs - profile: { + 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 +} +[2024-10-23T16:09:37.552] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-10-23T16:09:37.554] [INFO] monitorLogs - luxOff: turn off line: 1 2024-10-24T05:54:00.553Z +[2024-10-23T16:09:37.555] [INFO] monitorLogs - luxOn: turn on line: 1 2024-10-23T16:17:00.555Z +[2024-10-23T16:09:37.556] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:54', name: 'luxOff' }, + { value: 1, start_time: '18:17', name: 'luxOn' } +] +[2024-10-23T16:09:37.557] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2024-10-23T16:09:37.558] [INFO] monitorLogs - buildTasks: profile for line 2 +[2024-10-23T16:09:37.558] [INFO] monitorLogs - profile: { + 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 +} +[2024-10-23T16:09:37.561] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-10-23T16:09:37.561] [INFO] monitorLogs - luxOff: turn off line: 2 2024-10-24T05:54:00.561Z +[2024-10-23T16:09:37.562] [INFO] monitorLogs - luxOn: turn on line: 2 2024-10-23T16:17:00.562Z +[2024-10-23T16:09:37.562] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:54', name: 'luxOff' }, + { value: 1, start_time: '18:17', name: 'luxOn' } +] +[2024-10-23T16:09:37.563] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2024-10-23T16:09:37.564] [INFO] monitorLogs - buildTasks: profile for line 3 +[2024-10-23T16:09:37.565] [INFO] monitorLogs - profile: { + 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 +} +[2024-10-23T16:09:37.567] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-10-23T16:09:37.567] [INFO] monitorLogs - luxOff: turn off line: 3 2024-10-24T05:54:00.567Z +[2024-10-23T16:09:37.568] [INFO] monitorLogs - luxOn: turn on line: 3 2024-10-23T16:17:00.568Z +[2024-10-23T16:09:37.569] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:54', name: 'luxOff' }, + { value: 1, start_time: '18:17', name: 'luxOn' } +] +[2024-10-23T16:09:37.570] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2024-10-23T16:09:37.570] [INFO] monitorLogs - buildTasks: profile for line 4 +[2024-10-23T16:09:37.571] [INFO] monitorLogs - profile: { + 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 +} +[2024-10-23T16:09:37.573] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-10-23T16:09:37.574] [INFO] monitorLogs - luxOff: turn off line: 4 2024-10-24T05:54:00.573Z +[2024-10-23T16:09:37.574] [INFO] monitorLogs - luxOn: turn on line: 4 2024-10-23T16:17:00.574Z +[2024-10-23T16:09:37.575] [INFO] monitorLogs - -->time_points final 4 [ + { value: 0, start_time: '7:54', name: 'luxOff' }, + { value: 1, start_time: '18:17', name: 'luxOn' } +] +[2024-10-23T16:09:37.576] [INFO] monitorLogs - -->currentValue for relay 4 0 +[2024-10-23T16:09:37.589] [INFO] monitorLogs - tasks created: 2177 +[2024-10-23T16:09:37.593] [INFO] monitorLogs - -->FLOW bol spustený wvKJdZML6mXP4DzWBAXxwBAjxNloa5g23Ve9Y1ry 2024-09-23 +[2024-10-23T16:09:37.901] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-23T16:09:37.940] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-23T16:09:37.977] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-23T16:09:38.015] [INFO] monitorLogs - turnOffLine (line, pin, force) 4 relay1_05 false aplikovany bod profilu +[2024-10-23T17:56:48.922] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-10-23T17:56:48.933] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-10-23T17:56:48.939] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-10-23T17:56:48.945] [INFO] monitorLogs - turnOnLine (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2024-10-23T18:17:02.258] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-23T18:17:02.298] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-23T18:17:02.336] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-23T18:17:02.374] [INFO] monitorLogs - turnOnLine (line, pin, force) 4 relay1_05 false aplikovany bod profilu +[2024-10-24T03:09:33.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-24 03:09:33 +[2024-10-24T07:13:10.996] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-10-24T07:13:11.005] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-10-24T07:13:11.010] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-10-24T07:13:11.016] [INFO] monitorLogs - turnOffLine (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2024-10-24T07:53:58.586] [INFO] monitorLogs - MQTT broker connected +[2024-10-24T07:54:00.567] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-24T07:54:00.602] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-24T07:54:00.638] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-24T07:54:00.674] [INFO] monitorLogs - turnOffLine (line, pin, force) 4 relay1_05 false aplikovany bod profilu +[2024-10-24T17:58:25.018] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-10-24T17:58:25.043] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-10-24T17:58:25.049] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-10-24T17:58:25.054] [INFO] monitorLogs - turnOnLine (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2024-10-24T18:16:12.775] [INFO] monitorLogs - turnOnLine (line, pin, force) 4 relay1_05 false aplikovany bod profilu +[2024-10-24T18:16:12.811] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-24T18:16:12.847] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-24T18:16:12.884] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-25T03:09:35.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-25 03:09:35 +[2024-10-25T07:15:30.378] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-10-25T07:15:30.387] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-10-25T07:15:30.392] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-10-25T07:15:30.397] [INFO] monitorLogs - turnOffLine (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2024-10-25T07:57:47.738] [INFO] monitorLogs - turnOffLine (line, pin, force) 4 relay1_05 false aplikovany bod profilu +[2024-10-25T07:57:47.773] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-25T07:57:47.809] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-25T07:57:47.845] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-25T12:53:55.201] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2024-10-25T12:53:55.529] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 true turn off on startup +[2024-10-25T12:53:55.543] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 true turn off on startup +[2024-10-25T12:53:55.549] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 true turn off on startup +[2024-10-25T12:53:55.554] [INFO] monitorLogs - turnOffLine (line, pin, force) 4 relay1_05 true turn off on startup +[2024-10-25T12:53:55.620] [INFO] monitorLogs - MQTT broker connected +[2024-10-25T12:54:00.566] [INFO] monitorLogs - buildTasks - params undefined +[2024-10-25T12:54:00.568] [INFO] monitorLogs - buildTasks: profile for line 1 +[2024-10-25T12:54:00.569] [INFO] monitorLogs - profile: { + 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 +} +[2024-10-25T12:54:00.575] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-10-25T12:54:00.576] [INFO] monitorLogs - luxOff: turn off line: 1 2024-10-26T05:57:00.575Z +[2024-10-25T12:54:00.577] [INFO] monitorLogs - luxOn: turn on line: 1 2024-10-25T16:14:00.577Z +[2024-10-25T12:54:00.578] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:57', name: 'luxOff' }, + { value: 1, start_time: '18:14', name: 'luxOn' } +] +[2024-10-25T12:54:00.579] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2024-10-25T12:54:00.580] [INFO] monitorLogs - buildTasks: profile for line 2 +[2024-10-25T12:54:00.581] [INFO] monitorLogs - profile: { + 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 +} +[2024-10-25T12:54:00.583] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-10-25T12:54:00.584] [INFO] monitorLogs - luxOff: turn off line: 2 2024-10-26T05:57:00.584Z +[2024-10-25T12:54:00.585] [INFO] monitorLogs - luxOn: turn on line: 2 2024-10-25T16:14:00.585Z +[2024-10-25T12:54:00.585] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:57', name: 'luxOff' }, + { value: 1, start_time: '18:14', name: 'luxOn' } +] +[2024-10-25T12:54:00.587] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2024-10-25T12:54:00.587] [INFO] monitorLogs - buildTasks: profile for line 3 +[2024-10-25T12:54:00.588] [INFO] monitorLogs - profile: { + 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 +} +[2024-10-25T12:54:00.590] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-10-25T12:54:00.591] [INFO] monitorLogs - luxOff: turn off line: 3 2024-10-26T05:57:00.591Z +[2024-10-25T12:54:00.591] [INFO] monitorLogs - luxOn: turn on line: 3 2024-10-25T16:14:00.591Z +[2024-10-25T12:54:00.592] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:57', name: 'luxOff' }, + { value: 1, start_time: '18:14', name: 'luxOn' } +] +[2024-10-25T12:54:00.593] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2024-10-25T12:54:00.594] [INFO] monitorLogs - buildTasks: profile for line 4 +[2024-10-25T12:54:00.594] [INFO] monitorLogs - profile: { + 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 +} +[2024-10-25T12:54:00.597] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-10-25T12:54:00.597] [INFO] monitorLogs - luxOff: turn off line: 4 2024-10-26T05:57:00.597Z +[2024-10-25T12:54:00.598] [INFO] monitorLogs - luxOn: turn on line: 4 2024-10-25T16:14:00.598Z +[2024-10-25T12:54:00.599] [INFO] monitorLogs - -->time_points final 4 [ + { value: 0, start_time: '7:57', name: 'luxOff' }, + { value: 1, start_time: '18:14', name: 'luxOn' } +] +[2024-10-25T12:54:00.600] [INFO] monitorLogs - -->currentValue for relay 4 0 +[2024-10-25T12:54:00.614] [INFO] monitorLogs - tasks created: 2177 +[2024-10-25T12:54:00.617] [INFO] monitorLogs - -->FLOW bol spustený wvKJdZML6mXP4DzWBAXxwBAjxNloa5g23Ve9Y1ry 2024-09-23 +[2024-10-25T12:54:00.926] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-25T12:54:00.965] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-25T12:54:01.003] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-25T12:54:01.039] [INFO] monitorLogs - turnOffLine (line, pin, force) 4 relay1_05 false aplikovany bod profilu +[2024-10-25T13:38:38.056] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2024-10-25T13:38:38.383] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 true turn off on startup +[2024-10-25T13:38:38.397] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 true turn off on startup +[2024-10-25T13:38:38.403] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 true turn off on startup +[2024-10-25T13:38:38.408] [INFO] monitorLogs - turnOffLine (line, pin, force) 4 relay1_05 true turn off on startup +[2024-10-25T13:38:38.475] [INFO] monitorLogs - MQTT broker connected +[2024-10-25T13:38:43.421] [INFO] monitorLogs - buildTasks - params undefined +[2024-10-25T13:38:43.423] [INFO] monitorLogs - buildTasks: profile for line 1 +[2024-10-25T13:38:43.423] [INFO] monitorLogs - profile: { + 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 +} +[2024-10-25T13:38:43.428] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-10-25T13:38:43.430] [INFO] monitorLogs - luxOff: turn off line: 1 2024-10-26T05:57:00.429Z +[2024-10-25T13:38:43.431] [INFO] monitorLogs - luxOn: turn on line: 1 2024-10-25T16:14:00.431Z +[2024-10-25T13:38:43.432] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:57', name: 'luxOff' }, + { value: 1, start_time: '18:14', name: 'luxOn' } +] +[2024-10-25T13:38:43.433] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2024-10-25T13:38:43.434] [INFO] monitorLogs - buildTasks: profile for line 2 +[2024-10-25T13:38:43.435] [INFO] monitorLogs - profile: { + 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 +} +[2024-10-25T13:38:43.437] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-10-25T13:38:43.438] [INFO] monitorLogs - luxOff: turn off line: 2 2024-10-26T05:57:00.438Z +[2024-10-25T13:38:43.439] [INFO] monitorLogs - luxOn: turn on line: 2 2024-10-25T16:14:00.439Z +[2024-10-25T13:38:43.440] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:57', name: 'luxOff' }, + { value: 1, start_time: '18:14', name: 'luxOn' } +] +[2024-10-25T13:38:43.441] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2024-10-25T13:38:43.441] [INFO] monitorLogs - buildTasks: profile for line 3 +[2024-10-25T13:38:43.442] [INFO] monitorLogs - profile: { + 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 +} +[2024-10-25T13:38:43.444] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-10-25T13:38:43.445] [INFO] monitorLogs - luxOff: turn off line: 3 2024-10-26T05:57:00.445Z +[2024-10-25T13:38:43.446] [INFO] monitorLogs - luxOn: turn on line: 3 2024-10-25T16:14:00.446Z +[2024-10-25T13:38:43.447] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:57', name: 'luxOff' }, + { value: 1, start_time: '18:14', name: 'luxOn' } +] +[2024-10-25T13:38:43.448] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2024-10-25T13:38:43.449] [INFO] monitorLogs - buildTasks: profile for line 4 +[2024-10-25T13:38:43.449] [INFO] monitorLogs - profile: { + 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 +} +[2024-10-25T13:38:43.452] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-10-25T13:38:43.452] [INFO] monitorLogs - luxOff: turn off line: 4 2024-10-26T05:57:00.452Z +[2024-10-25T13:38:43.453] [INFO] monitorLogs - luxOn: turn on line: 4 2024-10-25T16:14:00.453Z +[2024-10-25T13:38:43.454] [INFO] monitorLogs - -->time_points final 4 [ + { value: 0, start_time: '7:57', name: 'luxOff' }, + { value: 1, start_time: '18:14', name: 'luxOn' } +] +[2024-10-25T13:38:43.455] [INFO] monitorLogs - -->currentValue for relay 4 0 +[2024-10-25T13:38:43.469] [INFO] monitorLogs - tasks created: 2177 +[2024-10-25T13:38:43.472] [INFO] monitorLogs - -->FLOW bol spustený wvKJdZML6mXP4DzWBAXxwBAjxNloa5g23Ve9Y1ry 2024-09-23 +[2024-10-25T13:38:43.781] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-25T13:38:43.819] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-25T13:38:43.856] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-25T13:38:43.894] [INFO] monitorLogs - turnOffLine (line, pin, force) 4 relay1_05 false aplikovany bod profilu +[2024-10-25T17:55:17.368] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-10-25T17:55:17.379] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-10-25T17:55:17.390] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-10-25T17:55:17.397] [INFO] monitorLogs - turnOnLine (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2024-10-25T18:14:02.743] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-25T18:14:02.782] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-25T18:14:02.820] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-25T18:14:02.859] [INFO] monitorLogs - turnOnLine (line, pin, force) 4 relay1_05 false aplikovany bod profilu +[2024-10-26T03:38:39.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-26 03:38:39 +[2024-10-26T07:26:33.949] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-10-26T07:26:33.959] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-10-26T07:26:33.964] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-10-26T07:26:33.971] [INFO] monitorLogs - turnOffLine (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2024-10-26T07:57:00.446] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-26T07:57:00.483] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-26T07:57:00.518] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-26T07:57:00.554] [INFO] monitorLogs - turnOffLine (line, pin, force) 4 relay1_05 false aplikovany bod profilu +[2024-10-26T17:53:18.832] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-10-26T17:53:18.843] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-10-26T17:53:18.848] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-10-26T17:53:18.853] [INFO] monitorLogs - turnOnLine (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2024-10-26T18:12:36.902] [INFO] monitorLogs - turnOnLine (line, pin, force) 4 relay1_05 false aplikovany bod profilu +[2024-10-26T18:12:36.938] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-26T18:12:36.975] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-26T18:12:37.011] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-27T03:38:40.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-27 03:38:40 +[2024-10-27T06:16:36.786] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-10-27T06:16:36.808] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-10-27T06:16:36.814] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-10-27T06:16:36.820] [INFO] monitorLogs - turnOffLine (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2024-10-27T07:00:56.556] [INFO] monitorLogs - turnOffLine (line, pin, force) 4 relay1_05 false aplikovany bod profilu +[2024-10-27T07:00:56.593] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-27T07:00:56.629] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-27T07:00:56.665] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-27T16:54:08.173] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-10-27T16:54:08.182] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-10-27T16:54:08.187] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-10-27T16:54:08.192] [INFO] monitorLogs - turnOnLine (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2024-10-27T17:10:52.304] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-27T17:10:52.341] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-27T17:10:52.377] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-27T17:10:52.414] [INFO] monitorLogs - turnOnLine (line, pin, force) 4 relay1_05 false aplikovany bod profilu +[2024-10-28T03:38:41.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-28 03:38:41 +[2024-10-28T06:17:27.756] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-10-28T06:17:27.767] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-10-28T06:17:27.774] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-10-28T06:17:27.779] [INFO] monitorLogs - turnOffLine (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2024-10-28T07:02:31.689] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-28T07:02:31.725] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-28T07:02:31.761] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-28T07:02:31.797] [INFO] monitorLogs - turnOffLine (line, pin, force) 4 relay1_05 false aplikovany bod profilu +[2024-10-28T15:26:18.296] [INFO] monitorLogs - MQTT broker connected +[2024-10-28T16:53:35.431] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-10-28T16:53:35.452] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-10-28T16:53:35.457] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-10-28T16:53:35.462] [INFO] monitorLogs - turnOnLine (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2024-10-28T17:09:10.878] [INFO] monitorLogs - turnOnLine (line, pin, force) 4 relay1_05 false aplikovany bod profilu +[2024-10-28T17:09:10.914] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-28T17:09:10.950] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-28T17:09:10.986] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-29T03:38:43.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-29 03:38:43 +[2024-10-29T06:22:09.042] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-10-29T06:22:09.059] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-10-29T06:22:09.064] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-10-29T06:22:09.070] [INFO] monitorLogs - turnOffLine (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2024-10-29T07:04:06.562] [INFO] monitorLogs - turnOffLine (line, pin, force) 4 relay1_05 false aplikovany bod profilu +[2024-10-29T07:04:06.598] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-29T07:04:06.634] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-29T07:04:06.669] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-29T16:50:26.480] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-10-29T16:50:26.489] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-10-29T16:50:26.494] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-10-29T16:50:26.499] [INFO] monitorLogs - turnOnLine (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2024-10-29T17:07:28.174] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-29T17:07:28.210] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-29T17:07:28.247] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-29T17:07:28.284] [INFO] monitorLogs - turnOnLine (line, pin, force) 4 relay1_05 false aplikovany bod profilu +[2024-10-30T03:38:44.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-30 03:38:44 +[2024-10-30T06:23:21.115] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-10-30T06:23:21.133] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-10-30T06:23:21.138] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-10-30T06:23:21.143] [INFO] monitorLogs - turnOffLine (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2024-10-30T07:05:41.963] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-30T07:05:42.005] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-30T07:05:42.041] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-30T07:05:42.076] [INFO] monitorLogs - turnOffLine (line, pin, force) 4 relay1_05 false aplikovany bod profilu +[2024-10-30T09:01:23.520] [INFO] monitorLogs - MQTT broker connected +[2024-10-30T16:51:20.863] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-10-30T16:51:20.872] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-10-30T16:51:20.878] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-10-30T16:51:20.883] [INFO] monitorLogs - turnOnLine (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2024-10-30T17:05:47.192] [INFO] monitorLogs - turnOnLine (line, pin, force) 4 relay1_05 false aplikovany bod profilu +[2024-10-30T17:05:47.227] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-30T17:05:47.265] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-30T17:05:47.302] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-31T03:38:45.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-31 03:38:45 +[2024-10-31T06:31:26.284] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-10-31T06:31:26.291] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-10-31T06:31:26.297] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-10-31T06:31:26.301] [INFO] monitorLogs - turnOffLine (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2024-10-31T07:07:17.236] [INFO] monitorLogs - turnOffLine (line, pin, force) 4 relay1_05 false aplikovany bod profilu +[2024-10-31T07:07:17.273] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-31T07:07:17.308] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-31T07:07:17.344] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-31T16:44:35.785] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-10-31T16:44:35.795] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-10-31T16:44:35.800] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-10-31T16:44:35.805] [INFO] monitorLogs - turnOnLine (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2024-10-31T17:04:07.824] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-31T17:04:07.861] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-31T17:04:07.897] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-31T17:04:07.933] [INFO] monitorLogs - turnOnLine (line, pin, force) 4 relay1_05 false aplikovany bod profilu +[2024-11-01T03:38:46.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-01 03:38:46 +[2024-11-01T06:28:20.065] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-11-01T06:28:20.073] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-11-01T06:28:20.077] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-11-01T06:28:20.089] [INFO] monitorLogs - turnOffLine (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2024-11-01T07:08:52.860] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-01T07:08:52.896] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-01T07:08:52.932] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-01T07:08:52.968] [INFO] monitorLogs - turnOffLine (line, pin, force) 4 relay1_05 false aplikovany bod profilu +[2024-11-01T16:46:09.719] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-11-01T16:46:09.736] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-11-01T16:46:09.741] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-11-01T16:46:09.746] [INFO] monitorLogs - turnOnLine (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2024-11-01T17:02:32.262] [INFO] monitorLogs - turnOnLine (line, pin, force) 4 relay1_05 false aplikovany bod profilu +[2024-11-01T17:02:32.298] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-01T17:02:32.334] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-01T17:02:32.370] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-02T03:38:47.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-02 03:38:47 +[2024-11-02T06:36:30.501] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-11-02T06:36:30.515] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-11-02T06:36:30.520] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-11-02T06:36:30.525] [INFO] monitorLogs - turnOffLine (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2024-11-02T07:10:28.704] [INFO] monitorLogs - turnOffLine (line, pin, force) 4 relay1_05 false aplikovany bod profilu +[2024-11-02T07:10:28.742] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-02T07:10:28.778] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-02T07:10:28.814] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-02T16:43:01.131] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-11-02T16:43:01.147] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-11-02T16:43:01.151] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-11-02T16:43:01.156] [INFO] monitorLogs - turnOnLine (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2024-11-02T17:00:53.751] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-02T17:00:53.787] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-02T17:00:53.823] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-02T17:00:53.860] [INFO] monitorLogs - turnOnLine (line, pin, force) 4 relay1_05 false aplikovany bod profilu +[2024-11-03T03:38:48.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-03 03:38:48 +[2024-11-03T06:27:44.817] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-11-03T06:27:44.842] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-11-03T06:27:44.847] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-11-03T06:27:44.851] [INFO] monitorLogs - turnOffLine (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2024-11-03T07:12:04.362] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-03T07:12:04.399] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-03T07:12:04.434] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-03T07:12:04.469] [INFO] monitorLogs - turnOffLine (line, pin, force) 4 relay1_05 false aplikovany bod profilu +[2024-11-03T16:45:32.229] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-11-03T16:45:32.236] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-11-03T16:45:32.242] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-11-03T16:45:32.250] [INFO] monitorLogs - turnOnLine (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2024-11-03T16:59:18.911] [INFO] monitorLogs - turnOnLine (line, pin, force) 4 relay1_05 false aplikovany bod profilu +[2024-11-03T16:59:18.948] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-03T16:59:18.984] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-03T16:59:19.020] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-04T03:38:49.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-04 03:38:49 +[2024-11-04T06:27:23.396] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-11-04T06:27:23.406] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-11-04T06:27:23.411] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-11-04T06:27:23.417] [INFO] monitorLogs - turnOffLine (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2024-11-04T07:13:40.278] [INFO] monitorLogs - turnOffLine (line, pin, force) 4 relay1_05 false aplikovany bod profilu +[2024-11-04T07:13:40.315] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-04T07:13:40.350] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-04T07:13:40.385] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-04T14:13:00.271] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2024-11-04T14:13:00.600] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 true turn off on startup +[2024-11-04T14:13:00.614] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 true turn off on startup +[2024-11-04T14:13:00.620] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 true turn off on startup +[2024-11-04T14:13:00.626] [INFO] monitorLogs - turnOffLine (line, pin, force) 4 relay1_05 true turn off on startup +[2024-11-04T14:13:01.889] [INFO] monitorLogs - MQTT broker connected +[2024-11-04T14:13:05.637] [INFO] monitorLogs - buildTasks - params undefined +[2024-11-04T14:13:05.638] [INFO] monitorLogs - buildTasks: profile for line 1 +[2024-11-04T14:13:05.639] [INFO] monitorLogs - profile: { + 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 +} +[2024-11-04T14:13:05.643] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-04T14:13:05.645] [INFO] monitorLogs - luxOff: turn off line: 1 2024-11-05T06:13:00.644Z +[2024-11-04T14:13:05.646] [INFO] monitorLogs - luxOn: turn on line: 1 2024-11-04T15:57:00.646Z +[2024-11-04T14:13:05.647] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:13', name: 'luxOff' }, + { value: 1, start_time: '16:57', name: 'luxOn' } +] +[2024-11-04T14:13:05.649] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2024-11-04T14:13:05.650] [INFO] monitorLogs - buildTasks: profile for line 2 +[2024-11-04T14:13:05.650] [INFO] monitorLogs - profile: { + 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 +} +[2024-11-04T14:13:05.653] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-04T14:13:05.653] [INFO] monitorLogs - luxOff: turn off line: 2 2024-11-05T06:13:00.653Z +[2024-11-04T14:13:05.654] [INFO] monitorLogs - luxOn: turn on line: 2 2024-11-04T15:57:00.654Z +[2024-11-04T14:13:05.655] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:13', name: 'luxOff' }, + { value: 1, start_time: '16:57', name: 'luxOn' } +] +[2024-11-04T14:13:05.656] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2024-11-04T14:13:05.657] [INFO] monitorLogs - buildTasks: profile for line 3 +[2024-11-04T14:13:05.657] [INFO] monitorLogs - profile: { + 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 +} +[2024-11-04T14:13:05.659] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-04T14:13:05.660] [INFO] monitorLogs - luxOff: turn off line: 3 2024-11-05T06:13:00.660Z +[2024-11-04T14:13:05.661] [INFO] monitorLogs - luxOn: turn on line: 3 2024-11-04T15:57:00.661Z +[2024-11-04T14:13:05.662] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:13', name: 'luxOff' }, + { value: 1, start_time: '16:57', name: 'luxOn' } +] +[2024-11-04T14:13:05.663] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2024-11-04T14:13:05.663] [INFO] monitorLogs - buildTasks: profile for line 4 +[2024-11-04T14:13:05.664] [INFO] monitorLogs - profile: { + 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 +} +[2024-11-04T14:13:05.666] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-04T14:13:05.667] [INFO] monitorLogs - luxOff: turn off line: 4 2024-11-05T06:13:00.667Z +[2024-11-04T14:13:05.667] [INFO] monitorLogs - luxOn: turn on line: 4 2024-11-04T15:57:00.667Z +[2024-11-04T14:13:05.668] [INFO] monitorLogs - -->time_points final 4 [ + { value: 0, start_time: '7:13', name: 'luxOff' }, + { value: 1, start_time: '16:57', name: 'luxOn' } +] +[2024-11-04T14:13:05.669] [INFO] monitorLogs - -->currentValue for relay 4 0 +[2024-11-04T14:13:05.687] [INFO] monitorLogs - tasks created: 2177 +[2024-11-04T14:13:05.690] [INFO] monitorLogs - -->FLOW bol spustený wvKJdZML6mXP4DzWBAXxwBAjxNloa5g23Ve9Y1ry 2024-09-23 +[2024-11-04T14:13:05.999] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-04T14:13:06.038] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-04T14:13:06.077] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-04T14:13:06.116] [INFO] monitorLogs - turnOffLine (line, pin, force) 4 relay1_05 false aplikovany bod profilu +[2024-11-04T16:44:03.698] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-11-04T16:44:03.709] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-11-04T16:44:03.715] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-11-04T16:44:03.721] [INFO] monitorLogs - turnOnLine (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2024-11-04T16:57:02.511] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-04T16:57:02.550] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-04T16:57:02.588] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-04T16:57:02.631] [INFO] monitorLogs - turnOnLine (line, pin, force) 4 relay1_05 false aplikovany bod profilu +[2024-11-05T03:13:01.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-05 03:13:01 +[2024-11-05T06:29:58.144] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-11-05T06:29:58.155] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-11-05T06:29:58.160] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-11-05T06:29:58.166] [INFO] monitorLogs - turnOffLine (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2024-11-05T07:13:00.832] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-05T07:13:00.869] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-05T07:13:00.907] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-05T07:13:00.942] [INFO] monitorLogs - turnOffLine (line, pin, force) 4 relay1_05 false aplikovany bod profilu +[2024-11-05T08:06:22.294] [INFO] monitorLogs - MQTT broker connected +[2024-11-05T08:08:22.120] [INFO] monitorLogs - MQTT broker connected +[2024-11-05T16:38:21.155] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-11-05T16:38:21.164] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-11-05T16:38:21.169] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-11-05T16:38:21.174] [INFO] monitorLogs - turnOnLine (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2024-11-05T16:56:15.047] [INFO] monitorLogs - turnOnLine (line, pin, force) 4 relay1_05 false aplikovany bod profilu +[2024-11-05T16:56:15.084] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-05T16:56:15.119] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-05T16:56:15.157] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-05T22:56:02.474] [INFO] monitorLogs - MQTT broker connected +[2024-11-06T03:13:02.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-06 03:13:02 +[2024-11-06T06:29:36.861] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-11-06T06:29:36.880] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-11-06T06:29:36.886] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-11-06T06:29:36.891] [INFO] monitorLogs - turnOffLine (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2024-11-06T07:16:52.117] [INFO] monitorLogs - turnOffLine (line, pin, force) 4 relay1_05 false aplikovany bod profilu +[2024-11-06T07:16:52.153] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-06T07:16:52.190] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-06T07:16:52.228] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-06T16:38:23.002] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-11-06T16:38:23.010] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-11-06T16:38:23.015] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-11-06T16:38:23.020] [INFO] monitorLogs - turnOnLine (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2024-11-06T16:54:47.000] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-06T16:54:47.038] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-06T16:54:47.074] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-06T16:54:47.111] [INFO] monitorLogs - turnOnLine (line, pin, force) 4 relay1_05 false aplikovany bod profilu +[2024-11-07T01:40:50.691] [INFO] monitorLogs - MQTT broker connected +[2024-11-07T03:13:09.449] [INFO] monitorLogs - setCorrectPlcTimeOnceADay - function error SyntaxError: Unexpected token < in JSON at position 0 + at JSON.parse () + at /home/unipi/flowserver/flow/cmd_manager.js:2898:26 + at Object.exec_callback [as callback] (/home/unipi/flowserver/node_modules/total.js/builders.js:5803:3) + at IncomingMessage.request_process_end (/home/unipi/flowserver/node_modules/total.js/utils.js:1184:11) + at IncomingMessage.emit (events.js:412:35) + at endReadableNT (internal/streams/readable.js:1334:12) + at processTicksAndRejections (internal/process/task_queues.js:82:21) 503: Service Unavailable
503
Service Unavailable
+[2024-11-07T06:33:52.358] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-11-07T06:33:52.373] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-11-07T06:33:52.377] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-11-07T06:33:52.382] [INFO] monitorLogs - turnOffLine (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2024-11-07T07:18:27.675] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-07T07:18:27.711] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-07T07:18:27.746] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-07T07:18:27.782] [INFO] monitorLogs - turnOffLine (line, pin, force) 4 relay1_05 false aplikovany bod profilu +[2024-11-07T16:36:43.936] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-11-07T16:36:43.944] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-11-07T16:36:43.949] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-11-07T16:36:43.953] [INFO] monitorLogs - turnOnLine (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2024-11-07T16:53:18.668] [INFO] monitorLogs - turnOnLine (line, pin, force) 4 relay1_05 false aplikovany bod profilu +[2024-11-07T16:53:18.705] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-07T16:53:18.741] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-07T16:53:18.778] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-08T03:13:04.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-08 03:13:04 +[2024-11-08T06:35:12.898] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-11-08T06:35:12.913] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-11-08T06:35:12.918] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-11-08T06:35:12.923] [INFO] monitorLogs - turnOffLine (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2024-11-08T07:20:03.220] [INFO] monitorLogs - turnOffLine (line, pin, force) 4 relay1_05 false aplikovany bod profilu +[2024-11-08T07:20:03.255] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-08T07:20:03.291] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-08T07:20:03.326] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-08T16:35:41.638] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-11-08T16:35:41.646] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-11-08T16:35:41.650] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-11-08T16:35:41.656] [INFO] monitorLogs - turnOnLine (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2024-11-08T16:51:53.735] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-08T16:51:53.772] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-08T16:51:53.808] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-08T16:51:53.844] [INFO] monitorLogs - turnOnLine (line, pin, force) 4 relay1_05 false aplikovany bod profilu +[2024-11-09T03:13:05.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-09 03:13:05 +[2024-11-09T06:35:02.106] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-11-09T06:35:02.116] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-11-09T06:35:02.121] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-11-09T06:35:02.127] [INFO] monitorLogs - turnOffLine (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2024-11-09T07:21:38.808] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-09T07:21:38.844] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-09T07:21:38.879] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-09T07:21:38.916] [INFO] monitorLogs - turnOffLine (line, pin, force) 4 relay1_05 false aplikovany bod profilu +[2024-11-09T11:04:06.036] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2024-11-09T11:04:11.529] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 true turn off on startup +[2024-11-09T11:04:11.531] [INFO] monitorLogs - turnLine: off pin (relay) relay1_02 +[2024-11-09T11:04:11.544] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 true turn off on startup +[2024-11-09T11:04:11.544] [INFO] monitorLogs - turnLine: off pin (relay) relay1_03 +[2024-11-09T11:04:11.550] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 true turn off on startup +[2024-11-09T11:04:11.551] [INFO] monitorLogs - turnLine: off pin (relay) relay1_04 +[2024-11-09T11:04:11.557] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 true turn off on startup +[2024-11-09T11:04:11.558] [INFO] monitorLogs - turnLine: off pin (relay) relay1_05 +[2024-11-09T11:04:11.677] [INFO] monitorLogs - MQTT client connected +[2024-11-09T11:04:16.573] [INFO] monitorLogs - buildTasks - params undefined +[2024-11-09T11:04:16.574] [INFO] monitorLogs - buildTasks: profile for line 1 +[2024-11-09T11:04:16.575] [INFO] monitorLogs - profile: { + 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 +} +[2024-11-09T11:04:16.579] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-09T11:04:16.580] [INFO] monitorLogs - luxOff: turn off line: 1 2024-11-10T06:21:00.579Z +[2024-11-09T11:04:16.582] [INFO] monitorLogs - luxOn: turn on line: 1 2024-11-09T15:50:00.582Z +[2024-11-09T11:04:16.582] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:21', name: 'luxOff' }, + { value: 1, start_time: '16:50', name: 'luxOn' } +] +[2024-11-09T11:04:16.583] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2024-11-09T11:04:16.584] [INFO] monitorLogs - buildTasks: profile for line 2 +[2024-11-09T11:04:16.585] [INFO] monitorLogs - profile: { + 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 +} +[2024-11-09T11:04:16.587] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-09T11:04:16.588] [INFO] monitorLogs - luxOff: turn off line: 2 2024-11-10T06:21:00.588Z +[2024-11-09T11:04:16.589] [INFO] monitorLogs - luxOn: turn on line: 2 2024-11-09T15:50:00.588Z +[2024-11-09T11:04:16.589] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:21', name: 'luxOff' }, + { value: 1, start_time: '16:50', name: 'luxOn' } +] +[2024-11-09T11:04:16.590] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2024-11-09T11:04:16.591] [INFO] monitorLogs - buildTasks: profile for line 3 +[2024-11-09T11:04:16.591] [INFO] monitorLogs - profile: { + 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 +} +[2024-11-09T11:04:16.593] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-09T11:04:16.594] [INFO] monitorLogs - luxOff: turn off line: 3 2024-11-10T06:21:00.594Z +[2024-11-09T11:04:16.595] [INFO] monitorLogs - luxOn: turn on line: 3 2024-11-09T15:50:00.595Z +[2024-11-09T11:04:16.595] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:21', name: 'luxOff' }, + { value: 1, start_time: '16:50', name: 'luxOn' } +] +[2024-11-09T11:04:16.596] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2024-11-09T11:04:16.597] [INFO] monitorLogs - buildTasks: profile for line 4 +[2024-11-09T11:04:16.597] [INFO] monitorLogs - profile: { + 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 +} +[2024-11-09T11:04:16.600] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-09T11:04:16.600] [INFO] monitorLogs - luxOff: turn off line: 4 2024-11-10T06:21:00.600Z +[2024-11-09T11:04:16.601] [INFO] monitorLogs - luxOn: turn on line: 4 2024-11-09T15:50:00.601Z +[2024-11-09T11:04:16.602] [INFO] monitorLogs - -->time_points final 4 [ + { value: 0, start_time: '7:21', name: 'luxOff' }, + { value: 1, start_time: '16:50', name: 'luxOn' } +] +[2024-11-09T11:04:16.603] [INFO] monitorLogs - -->currentValue for relay 4 0 +[2024-11-09T11:04:16.619] [INFO] monitorLogs - tasks created: 2177 +[2024-11-09T11:04:16.622] [INFO] monitorLogs - -->FLOW bol spustený wvKJdZML6mXP4DzWBAXxwBAjxNloa5g23Ve9Y1ry 2024-11-04 +[2024-11-09T11:04:16.930] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-09T11:04:16.968] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-09T11:04:17.007] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-09T11:04:17.044] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false aplikovany bod profilu +[2024-11-09T13:22:18.007] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2024-11-09T13:22:23.422] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 true turn off on startup +[2024-11-09T13:22:23.424] [INFO] monitorLogs - turnLine: off pin (relay) relay1_02 +[2024-11-09T13:22:23.438] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 true turn off on startup +[2024-11-09T13:22:23.439] [INFO] monitorLogs - turnLine: off pin (relay) relay1_03 +[2024-11-09T13:22:23.445] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 true turn off on startup +[2024-11-09T13:22:23.446] [INFO] monitorLogs - turnLine: off pin (relay) relay1_04 +[2024-11-09T13:22:23.452] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 true turn off on startup +[2024-11-09T13:22:23.453] [INFO] monitorLogs - turnLine: off pin (relay) relay1_05 +[2024-11-09T13:22:23.538] [INFO] monitorLogs - MQTT client connected +[2024-11-09T13:22:28.467] [INFO] monitorLogs - buildTasks - params undefined +[2024-11-09T13:22:28.468] [INFO] monitorLogs - buildTasks: profile for line 1 +[2024-11-09T13:22:28.469] [INFO] monitorLogs - profile: { + 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 +} +[2024-11-09T13:22:28.473] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-09T13:22:28.475] [INFO] monitorLogs - luxOff: turn off line: 1 2024-11-10T06:21:00.474Z +[2024-11-09T13:22:28.476] [INFO] monitorLogs - luxOn: turn on line: 1 2024-11-09T15:50:00.476Z +[2024-11-09T13:22:28.477] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:21', name: 'luxOff' }, + { value: 1, start_time: '16:50', name: 'luxOn' } +] +[2024-11-09T13:22:28.478] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2024-11-09T13:22:28.479] [INFO] monitorLogs - buildTasks: profile for line 2 +[2024-11-09T13:22:28.479] [INFO] monitorLogs - profile: { + 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 +} +[2024-11-09T13:22:28.482] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-09T13:22:28.482] [INFO] monitorLogs - luxOff: turn off line: 2 2024-11-10T06:21:00.482Z +[2024-11-09T13:22:28.483] [INFO] monitorLogs - luxOn: turn on line: 2 2024-11-09T15:50:00.483Z +[2024-11-09T13:22:28.484] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:21', name: 'luxOff' }, + { value: 1, start_time: '16:50', name: 'luxOn' } +] +[2024-11-09T13:22:28.485] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2024-11-09T13:22:28.486] [INFO] monitorLogs - buildTasks: profile for line 3 +[2024-11-09T13:22:28.486] [INFO] monitorLogs - profile: { + 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 +} +[2024-11-09T13:22:28.488] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-09T13:22:28.489] [INFO] monitorLogs - luxOff: turn off line: 3 2024-11-10T06:21:00.489Z +[2024-11-09T13:22:28.490] [INFO] monitorLogs - luxOn: turn on line: 3 2024-11-09T15:50:00.489Z +[2024-11-09T13:22:28.490] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:21', name: 'luxOff' }, + { value: 1, start_time: '16:50', name: 'luxOn' } +] +[2024-11-09T13:22:28.491] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2024-11-09T13:22:28.492] [INFO] monitorLogs - buildTasks: profile for line 4 +[2024-11-09T13:22:28.493] [INFO] monitorLogs - profile: { + 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 +} +[2024-11-09T13:22:28.495] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-09T13:22:28.496] [INFO] monitorLogs - luxOff: turn off line: 4 2024-11-10T06:21:00.495Z +[2024-11-09T13:22:28.497] [INFO] monitorLogs - luxOn: turn on line: 4 2024-11-09T15:50:00.496Z +[2024-11-09T13:22:28.497] [INFO] monitorLogs - -->time_points final 4 [ + { value: 0, start_time: '7:21', name: 'luxOff' }, + { value: 1, start_time: '16:50', name: 'luxOn' } +] +[2024-11-09T13:22:28.498] [INFO] monitorLogs - -->currentValue for relay 4 0 +[2024-11-09T13:22:28.517] [INFO] monitorLogs - tasks created: 2177 +[2024-11-09T13:22:28.520] [INFO] monitorLogs - -->FLOW bol spustený wvKJdZML6mXP4DzWBAXxwBAjxNloa5g23Ve9Y1ry 2024-11-04 +[2024-11-09T13:22:28.828] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-09T13:22:28.867] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-09T13:22:28.909] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-09T13:22:28.948] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false aplikovany bod profilu +[2024-11-09T16:34:00.468] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-11-09T16:34:00.469] [INFO] monitorLogs - turnLine: on pin (relay) relay1_02 +[2024-11-09T16:34:00.482] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-11-09T16:34:00.483] [INFO] monitorLogs - turnLine: on pin (relay) relay1_03 +[2024-11-09T16:34:00.491] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-11-09T16:34:00.492] [INFO] monitorLogs - turnLine: on pin (relay) relay1_04 +[2024-11-09T16:34:00.499] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2024-11-09T16:34:00.499] [INFO] monitorLogs - turnLine: on pin (relay) relay1_05 +[2024-11-09T16:50:01.021] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-09T16:50:01.072] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-09T16:50:01.110] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-09T16:50:01.149] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false aplikovany bod profilu +[2024-11-10T03:22:26.013] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-10 03:22:26 +[2024-11-10T06:37:19.114] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-11-10T06:37:19.116] [INFO] monitorLogs - turnLine: off pin (relay) relay1_02 +[2024-11-10T06:37:19.129] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-11-10T06:37:19.130] [INFO] monitorLogs - turnLine: off pin (relay) relay1_03 +[2024-11-10T06:37:19.138] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-11-10T06:37:19.139] [INFO] monitorLogs - turnLine: off pin (relay) relay1_04 +[2024-11-10T06:37:19.145] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2024-11-10T06:37:19.146] [INFO] monitorLogs - turnLine: off pin (relay) relay1_05 +[2024-11-10T07:21:00.531] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-10T07:21:00.567] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-10T07:21:00.604] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-10T07:21:00.640] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false aplikovany bod profilu +[2024-11-10T16:31:12.516] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-11-10T16:31:12.518] [INFO] monitorLogs - turnLine: on pin (relay) relay1_02 +[2024-11-10T16:31:12.529] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-11-10T16:31:12.530] [INFO] monitorLogs - turnLine: on pin (relay) relay1_03 +[2024-11-10T16:31:12.537] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-11-10T16:31:12.538] [INFO] monitorLogs - turnLine: on pin (relay) relay1_04 +[2024-11-10T16:31:12.544] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2024-11-10T16:31:12.544] [INFO] monitorLogs - turnLine: on pin (relay) relay1_05 +[2024-11-10T16:49:05.756] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false aplikovany bod profilu +[2024-11-10T16:49:05.793] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-10T16:49:05.829] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-10T16:49:05.867] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-11T03:22:27.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-11 03:22:27 +[2024-11-11T06:53:08.623] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-11-11T06:53:08.625] [INFO] monitorLogs - turnLine: off pin (relay) relay1_02 +[2024-11-11T06:53:08.638] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-11-11T06:53:08.638] [INFO] monitorLogs - turnLine: off pin (relay) relay1_03 +[2024-11-11T06:53:08.646] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-11-11T06:53:08.647] [INFO] monitorLogs - turnLine: off pin (relay) relay1_04 +[2024-11-11T06:53:08.653] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2024-11-11T06:53:08.654] [INFO] monitorLogs - turnLine: off pin (relay) relay1_05 +[2024-11-11T07:24:49.101] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false aplikovany bod profilu +[2024-11-11T07:24:49.137] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-11T07:24:49.174] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-11T07:24:49.210] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-11T08:28:13.811] [INFO] monitorLogs - MQTT client connected +[2024-11-11T08:31:52.025] [INFO] monitorLogs - MQTT client connected +[2024-11-11T16:19:32.825] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-11-11T16:19:32.826] [INFO] monitorLogs - turnLine: on pin (relay) relay1_02 +[2024-11-11T16:19:32.853] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-11-11T16:19:32.853] [INFO] monitorLogs - turnLine: on pin (relay) relay1_03 +[2024-11-11T16:19:32.860] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-11-11T16:19:32.861] [INFO] monitorLogs - turnLine: on pin (relay) relay1_04 +[2024-11-11T16:19:32.867] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2024-11-11T16:19:32.868] [INFO] monitorLogs - turnLine: on pin (relay) relay1_05 +[2024-11-11T16:47:46.491] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-11T16:47:46.529] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-11T16:47:46.565] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-11T16:47:46.601] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false aplikovany bod profilu +[2024-11-11T23:08:38.787] [INFO] monitorLogs - MQTT client connected +[2024-11-12T03:22:28.013] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-12 03:22:28 +[2024-11-12T06:53:07.377] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-11-12T06:53:07.379] [INFO] monitorLogs - turnLine: off pin (relay) relay1_02 +[2024-11-12T06:53:07.390] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-11-12T06:53:07.391] [INFO] monitorLogs - turnLine: off pin (relay) relay1_03 +[2024-11-12T06:53:07.399] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-11-12T06:53:07.400] [INFO] monitorLogs - turnLine: off pin (relay) relay1_04 +[2024-11-12T06:53:07.408] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2024-11-12T06:53:07.409] [INFO] monitorLogs - turnLine: off pin (relay) relay1_05 +[2024-11-12T07:02:40.756] [INFO] monitorLogs - MQTT client connected +[2024-11-12T07:26:23.877] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-12T07:26:23.914] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-12T07:26:23.950] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-12T07:26:23.987] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false aplikovany bod profilu +[2024-11-12T10:27:31.224] [INFO] monitorLogs - MQTT client connected +[2024-11-12T16:17:23.741] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-11-12T16:17:23.741] [INFO] monitorLogs - turnLine: on pin (relay) relay1_02 +[2024-11-12T16:17:23.752] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-11-12T16:17:23.752] [INFO] monitorLogs - turnLine: on pin (relay) relay1_03 +[2024-11-12T16:17:23.759] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-11-12T16:17:23.760] [INFO] monitorLogs - turnLine: on pin (relay) relay1_04 +[2024-11-12T16:17:23.766] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2024-11-12T16:17:23.766] [INFO] monitorLogs - turnLine: on pin (relay) relay1_05 +[2024-11-12T16:46:27.765] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false aplikovany bod profilu +[2024-11-12T16:46:27.802] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-12T16:46:27.838] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-12T16:46:27.874] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-13T03:22:29.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-13 03:22:29 +[2024-11-13T06:59:34.672] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-11-13T06:59:34.673] [INFO] monitorLogs - turnLine: off pin (relay) relay1_02 +[2024-11-13T06:59:34.685] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-11-13T06:59:34.685] [INFO] monitorLogs - turnLine: off pin (relay) relay1_03 +[2024-11-13T06:59:34.695] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-11-13T06:59:34.696] [INFO] monitorLogs - turnLine: off pin (relay) relay1_04 +[2024-11-13T06:59:34.704] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2024-11-13T06:59:34.705] [INFO] monitorLogs - turnLine: off pin (relay) relay1_05 +[2024-11-13T07:27:58.010] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false aplikovany bod profilu +[2024-11-13T07:27:58.048] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-13T07:27:58.085] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-13T07:27:58.122] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-13T10:12:36.027] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2024-11-13T10:12:41.358] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 true turn off on startup +[2024-11-13T10:12:41.373] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 true turn off on startup +[2024-11-13T10:12:41.380] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 true turn off on startup +[2024-11-13T10:12:41.388] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 true turn off on startup +[2024-11-13T10:12:41.501] [INFO] monitorLogs - MQTT client connected +[2024-11-13T10:12:46.402] [INFO] monitorLogs - buildTasks - params undefined +[2024-11-13T10:12:46.404] [INFO] monitorLogs - buildTasks: profile for line 1 +[2024-11-13T10:12:46.405] [INFO] monitorLogs - profile: { + 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 +} +[2024-11-13T10:12:46.409] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-13T10:12:46.411] [INFO] monitorLogs - luxOff: turn off line: 1 2024-11-14T06:27:00.410Z +[2024-11-13T10:12:46.412] [INFO] monitorLogs - luxOn: turn on line: 1 2024-11-13T15:45:00.412Z +[2024-11-13T10:12:46.413] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:27', name: 'luxOff' }, + { value: 1, start_time: '16:45', name: 'luxOn' } +] +[2024-11-13T10:12:46.414] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2024-11-13T10:12:46.415] [INFO] monitorLogs - buildTasks: profile for line 2 +[2024-11-13T10:12:46.415] [INFO] monitorLogs - profile: { + 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 +} +[2024-11-13T10:12:46.418] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-13T10:12:46.419] [INFO] monitorLogs - luxOff: turn off line: 2 2024-11-14T06:27:00.419Z +[2024-11-13T10:12:46.420] [INFO] monitorLogs - luxOn: turn on line: 2 2024-11-13T15:45:00.420Z +[2024-11-13T10:12:46.421] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:27', name: 'luxOff' }, + { value: 1, start_time: '16:45', name: 'luxOn' } +] +[2024-11-13T10:12:46.422] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2024-11-13T10:12:46.422] [INFO] monitorLogs - buildTasks: profile for line 3 +[2024-11-13T10:12:46.423] [INFO] monitorLogs - profile: { + 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 +} +[2024-11-13T10:12:46.425] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-13T10:12:46.426] [INFO] monitorLogs - luxOff: turn off line: 3 2024-11-14T06:27:00.426Z +[2024-11-13T10:12:46.426] [INFO] monitorLogs - luxOn: turn on line: 3 2024-11-13T15:45:00.426Z +[2024-11-13T10:12:46.427] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:27', name: 'luxOff' }, + { value: 1, start_time: '16:45', name: 'luxOn' } +] +[2024-11-13T10:12:46.428] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2024-11-13T10:12:46.429] [INFO] monitorLogs - buildTasks: profile for line 4 +[2024-11-13T10:12:46.429] [INFO] monitorLogs - profile: { + 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 +} +[2024-11-13T10:12:46.436] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-13T10:12:46.436] [INFO] monitorLogs - luxOff: turn off line: 4 2024-11-14T06:27:00.436Z +[2024-11-13T10:12:46.437] [INFO] monitorLogs - luxOn: turn on line: 4 2024-11-13T15:45:00.437Z +[2024-11-13T10:12:46.438] [INFO] monitorLogs - -->time_points final 4 [ + { value: 0, start_time: '7:27', name: 'luxOff' }, + { value: 1, start_time: '16:45', name: 'luxOn' } +] +[2024-11-13T10:12:46.439] [INFO] monitorLogs - -->currentValue for relay 4 0 +[2024-11-13T10:12:46.460] [INFO] monitorLogs - tasks created: 2177 +[2024-11-13T10:12:46.463] [INFO] monitorLogs - -->FLOW bol spustený wvKJdZML6mXP4DzWBAXxwBAjxNloa5g23Ve9Y1ry 2024-11-04 +[2024-11-13T16:18:17.494] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-11-13T16:18:17.507] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-11-13T16:18:17.514] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-11-13T16:18:17.521] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2024-11-14T03:12:42.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-14 03:12:42 +[2024-11-14T06:54:24.550] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-11-14T06:54:24.562] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-11-14T06:54:24.570] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-11-14T06:54:24.577] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2024-11-14T16:22:19.646] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-11-14T16:22:19.655] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-11-14T16:22:19.661] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-11-14T16:22:19.668] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2024-11-15T03:12:43.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-15 03:12:43 +[2024-11-15T06:47:11.689] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-11-15T06:47:11.702] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-11-15T06:47:11.711] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-11-15T06:47:11.718] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2024-11-15T15:35:24.114] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2024-11-15T15:35:29.471] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 true turn off on startup +[2024-11-15T15:35:29.486] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 true turn off on startup +[2024-11-15T15:35:29.493] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 true turn off on startup +[2024-11-15T15:35:29.501] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 true turn off on startup +[2024-11-15T15:35:29.626] [INFO] monitorLogs - MQTT client connected +[2024-11-15T15:35:34.514] [INFO] monitorLogs - buildTasks - params undefined +[2024-11-15T15:35:34.516] [INFO] monitorLogs - buildTasks: profile for line 1 +[2024-11-15T15:35:34.517] [INFO] monitorLogs - profile: { + 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 +} +[2024-11-15T15:35:34.522] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-15T15:35:34.523] [INFO] monitorLogs - luxOff: turn off line: 1 2024-11-16T06:31:00.523Z +[2024-11-15T15:35:34.525] [INFO] monitorLogs - luxOn: turn on line: 1 2024-11-15T15:42:00.525Z +[2024-11-15T15:35:34.526] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:31', name: 'luxOff' }, + { value: 1, start_time: '16:42', name: 'luxOn' } +] +[2024-11-15T15:35:34.527] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2024-11-15T15:35:34.528] [INFO] monitorLogs - buildTasks: profile for line 2 +[2024-11-15T15:35:34.529] [INFO] monitorLogs - profile: { + 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 +} +[2024-11-15T15:35:34.531] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-15T15:35:34.532] [INFO] monitorLogs - luxOff: turn off line: 2 2024-11-16T06:31:00.532Z +[2024-11-15T15:35:34.533] [INFO] monitorLogs - luxOn: turn on line: 2 2024-11-15T15:42:00.532Z +[2024-11-15T15:35:34.533] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:31', name: 'luxOff' }, + { value: 1, start_time: '16:42', name: 'luxOn' } +] +[2024-11-15T15:35:34.534] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2024-11-15T15:35:34.535] [INFO] monitorLogs - buildTasks: profile for line 3 +[2024-11-15T15:35:34.535] [INFO] monitorLogs - profile: { + 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 +} +[2024-11-15T15:35:34.538] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-15T15:35:34.538] [INFO] monitorLogs - luxOff: turn off line: 3 2024-11-16T06:31:00.538Z +[2024-11-15T15:35:34.539] [INFO] monitorLogs - luxOn: turn on line: 3 2024-11-15T15:42:00.539Z +[2024-11-15T15:35:34.540] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:31', name: 'luxOff' }, + { value: 1, start_time: '16:42', name: 'luxOn' } +] +[2024-11-15T15:35:34.541] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2024-11-15T15:35:34.542] [INFO] monitorLogs - buildTasks: profile for line 4 +[2024-11-15T15:35:34.542] [INFO] monitorLogs - profile: { + 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 +} +[2024-11-15T15:35:34.544] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-15T15:35:34.545] [INFO] monitorLogs - luxOff: turn off line: 4 2024-11-16T06:31:00.545Z +[2024-11-15T15:35:34.546] [INFO] monitorLogs - luxOn: turn on line: 4 2024-11-15T15:42:00.546Z +[2024-11-15T15:35:34.547] [INFO] monitorLogs - -->time_points final 4 [ + { value: 0, start_time: '7:31', name: 'luxOff' }, + { value: 1, start_time: '16:42', name: 'luxOn' } +] +[2024-11-15T15:35:34.548] [INFO] monitorLogs - -->currentValue for relay 4 0 +[2024-11-15T15:35:34.566] [INFO] monitorLogs - tasks created: 2177 +[2024-11-15T15:35:34.570] [INFO] monitorLogs - -->FLOW bol spustený wvKJdZML6mXP4DzWBAXxwBAjxNloa5g23Ve9Y1ry 2024-11-04 +[2024-11-15T16:19:07.190] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-11-15T16:19:07.201] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-11-15T16:19:07.210] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-11-15T16:19:07.217] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2024-11-16T03:35:31.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-16 03:35:31 +[2024-11-16T06:46:50.682] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-11-16T06:46:50.694] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-11-16T06:46:50.702] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-11-16T06:46:50.709] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2024-11-16T16:26:32.811] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-11-16T16:26:32.819] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-11-16T16:26:32.826] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-11-16T16:26:32.831] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2024-11-17T03:35:32.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-17 03:35:32 +[2024-11-17T06:51:46.138] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-11-17T06:51:46.150] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-11-17T06:51:46.160] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-11-17T06:51:46.166] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2024-11-17T16:25:25.697] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-11-17T16:25:25.712] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-11-17T16:25:25.718] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-11-17T16:25:25.725] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2024-11-18T03:35:33.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-18 03:35:33 +[2024-11-18T06:49:56.982] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-11-18T06:49:56.995] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-11-18T06:49:57.002] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-11-18T06:49:57.009] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2024-11-18T16:12:34.994] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-11-18T16:12:35.004] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-11-18T16:12:35.010] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-11-18T16:12:35.016] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2024-11-19T03:35:44.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-19 03:35:44 +[2024-11-19T06:58:20.098] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-11-19T06:58:20.110] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-11-19T06:58:20.116] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-11-19T06:58:20.124] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2024-11-19T14:47:59.001] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false command received from platform +[2024-11-19T14:48:10.725] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false command received from platform +[2024-11-19T14:48:19.765] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false command received from platform +[2024-11-19T14:48:49.213] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false command received from platform +[2024-11-19T14:53:50.001] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false command received from platform +[2024-11-19T14:53:55.121] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false command received from platform +[2024-11-19T14:54:04.402] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false command received from platform +[2024-11-19T14:54:12.081] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false command received from platform +[2024-11-19T16:15:46.301] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-11-19T16:15:46.308] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-11-19T16:15:46.314] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-11-19T16:15:46.320] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2024-11-20T03:35:35.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-20 03:35:35 +[2024-11-20T07:11:08.585] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-11-20T07:11:08.597] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-11-20T07:11:08.604] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-11-20T07:11:08.611] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2024-11-20T16:22:11.207] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-11-20T16:22:11.218] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-11-20T16:22:11.225] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-11-20T16:22:11.231] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2024-11-21T03:35:36.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-21 03:35:36 +[2024-11-21T06:58:23.664] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-11-21T06:58:23.676] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-11-21T06:58:23.684] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-11-21T06:58:23.691] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2024-11-21T16:17:24.488] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-11-21T16:17:24.497] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-11-21T16:17:24.503] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-11-21T16:17:24.510] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2024-11-22T03:35:38.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-22 03:35:38 +[2024-11-22T07:20:58.256] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-11-22T07:20:58.267] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-11-22T07:20:58.273] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-11-22T07:20:58.282] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2024-11-22T09:16:21.962] [INFO] monitorLogs - MQTT client connected +[2024-11-22T16:18:17.943] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-11-22T16:18:17.954] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-11-22T16:18:17.960] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-11-22T16:18:17.966] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2024-11-23T03:35:41.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-23 03:35:41 +[2024-11-23T07:01:30.747] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-11-23T07:01:30.757] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-11-23T07:01:30.764] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-11-23T07:01:30.773] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2024-11-23T16:20:25.470] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-11-23T16:20:25.482] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-11-23T16:20:25.489] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-11-23T16:20:25.495] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2024-11-24T03:35:39.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-24 03:35:39 +[2024-11-24T07:05:19.314] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-11-24T07:05:19.326] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-11-24T07:05:19.333] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-11-24T07:05:19.341] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2024-11-24T16:12:34.099] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-11-24T16:12:34.112] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-11-24T16:12:34.119] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-11-24T16:12:34.126] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2024-11-24T23:11:31.795] [INFO] monitorLogs - MQTT client connected +[2024-11-25T01:27:48.010] [INFO] monitorLogs - MQTT client error Error: Connection refused: Server unavailable + at MqttClient._handleConnack (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:1388:17) + at MqttClient._handlePacket (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:549:12) + at work (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:438:12) + at Writable.writable._write (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:452:5) + at doWrite (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:409:139) + at writeOrBuffer (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:398:5) + at Writable.write (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:307:11) + at Socket.ondata (internal/streams/readable.js:731:22) + at Socket.emit (events.js:400:28) + at addChunk (internal/streams/readable.js:293:12) { + code: 3 +} +[2024-11-25T01:27:49.290] [INFO] monitorLogs - MQTT client connected +[2024-11-25T02:12:01.745] [INFO] monitorLogs - MQTT client connected +[2024-11-25T03:35:40.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-25 03:35:40 +[2024-11-25T06:58:10.898] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-11-25T06:58:10.911] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-11-25T06:58:10.918] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-11-25T06:58:10.926] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2024-11-25T07:10:02.352] [INFO] monitorLogs - MQTT client error Error: Connection refused: Server unavailable + at MqttClient._handleConnack (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:1388:17) + at MqttClient._handlePacket (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:549:12) + at work (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:438:12) + at Writable.writable._write (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:452:5) + at doWrite (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:409:139) + at writeOrBuffer (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:398:5) + at Writable.write (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:307:11) + at Socket.ondata (internal/streams/readable.js:731:22) + at Socket.emit (events.js:400:28) + at addChunk (internal/streams/readable.js:293:12) { + code: 3 +} +[2024-11-25T07:10:04.519] [INFO] monitorLogs - MQTT client connected +[2024-11-25T07:13:33.665] [INFO] monitorLogs - MQTT client error Error: Connection refused: Server unavailable + at MqttClient._handleConnack (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:1388:17) + at MqttClient._handlePacket (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:549:12) + at work (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:438:12) + at Writable.writable._write (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:452:5) + at doWrite (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:409:139) + at writeOrBuffer (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:398:5) + at Writable.write (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:307:11) + at Socket.ondata (internal/streams/readable.js:731:22) + at Socket.emit (events.js:400:28) + at addChunk (internal/streams/readable.js:293:12) { + code: 3 +} +[2024-11-25T07:13:35.585] [INFO] monitorLogs - MQTT client connected +[2024-11-25T08:08:42.479] [INFO] monitorLogs - MQTT client connected +[2024-11-25T08:10:41.349] [INFO] monitorLogs - MQTT client connected +[2024-11-25T08:36:01.149] [INFO] monitorLogs - MQTT client connected +[2024-11-25T08:40:40.075] [INFO] monitorLogs - MQTT client connected +[2024-11-25T13:56:13.369] [INFO] monitorLogs - MQTT client connected +[2024-11-25T14:01:12.564] [INFO] monitorLogs - MQTT client connected +[2024-11-25T16:17:39.174] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-11-25T16:17:39.186] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-11-25T16:17:39.194] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-11-25T16:17:39.201] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2024-11-26T03:35:41.013] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-26 03:35:41 +[2024-11-26T07:05:02.609] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-11-26T07:05:02.621] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-11-26T07:05:02.628] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-11-26T07:05:02.635] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2024-11-26T16:09:15.521] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-11-26T16:09:15.531] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-11-26T16:09:15.537] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-11-26T16:09:15.543] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2024-11-27T03:35:42.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-27 03:35:42 +[2024-11-27T07:02:39.237] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-11-27T07:02:39.250] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-11-27T07:02:39.259] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-11-27T07:02:39.266] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2024-11-27T15:42:29.461] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2024-11-27T15:42:34.785] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 true turn off on startup +[2024-11-27T15:42:34.801] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 true turn off on startup +[2024-11-27T15:42:34.807] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 true turn off on startup +[2024-11-27T15:42:34.814] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 true turn off on startup +[2024-11-27T15:42:34.903] [INFO] monitorLogs - MQTT client connected +[2024-11-27T15:42:39.825] [INFO] monitorLogs - buildTasks - params undefined +[2024-11-27T15:42:39.826] [INFO] monitorLogs - buildTasks: profile for line 1 +[2024-11-27T15:42:39.827] [INFO] monitorLogs - profile: { + 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 +} +[2024-11-27T15:42:39.832] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-27T15:42:39.834] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2024-11-28T06:48:00.833Z +[2024-11-27T15:42:39.835] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2024-11-27T15:31:00.835Z +[2024-11-27T15:42:39.836] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:48', name: 'luxOff' }, + { value: 1, start_time: '16:31', name: 'luxOn' } +] +[2024-11-27T15:42:39.837] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2024-11-27T15:42:39.838] [INFO] monitorLogs - buildTasks: profile for line 2 +[2024-11-27T15:42:39.838] [INFO] monitorLogs - profile: { + 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 +} +[2024-11-27T15:42:39.841] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-27T15:42:39.841] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2024-11-28T06:48:00.841Z +[2024-11-27T15:42:39.842] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2024-11-27T15:31:00.842Z +[2024-11-27T15:42:39.843] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:48', name: 'luxOff' }, + { value: 1, start_time: '16:31', name: 'luxOn' } +] +[2024-11-27T15:42:39.844] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2024-11-27T15:42:39.845] [INFO] monitorLogs - buildTasks: profile for line 3 +[2024-11-27T15:42:39.845] [INFO] monitorLogs - profile: { + 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 +} +[2024-11-27T15:42:39.847] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-27T15:42:39.848] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2024-11-28T06:48:00.848Z +[2024-11-27T15:42:39.849] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2024-11-27T15:31:00.849Z +[2024-11-27T15:42:39.850] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:48', name: 'luxOff' }, + { value: 1, start_time: '16:31', name: 'luxOn' } +] +[2024-11-27T15:42:39.851] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2024-11-27T15:42:39.851] [INFO] monitorLogs - buildTasks: profile for line 4 +[2024-11-27T15:42:39.852] [INFO] monitorLogs - profile: { + 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 +} +[2024-11-27T15:42:39.854] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-27T15:42:39.855] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 4 2024-11-28T06:48:00.854Z +[2024-11-27T15:42:39.855] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 4 2024-11-27T15:31:00.855Z +[2024-11-27T15:42:39.856] [INFO] monitorLogs - -->time_points final 4 [ + { value: 0, start_time: '7:48', name: 'luxOff' }, + { value: 1, start_time: '16:31', name: 'luxOn' } +] +[2024-11-27T15:42:39.857] [INFO] monitorLogs - -->currentValue for relay 4 0 +[2024-11-27T15:42:39.875] [INFO] monitorLogs - tasks created: 2177 +[2024-11-27T15:42:39.879] [INFO] monitorLogs - -->FLOW bol spustený wvKJdZML6mXP4DzWBAXxwBAjxNloa5g23Ve9Y1ry 2024-11-04 +[2024-11-27T16:15:56.894] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-11-27T16:15:56.904] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-11-27T16:15:56.912] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-11-27T16:15:56.919] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2024-11-28T03:42:36.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-28 03:42:36 +[2024-11-28T07:20:19.089] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-11-28T07:20:19.102] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-11-28T07:20:19.109] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-11-28T07:20:19.117] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2024-11-28T16:14:45.484] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-11-28T16:14:45.497] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-11-28T16:14:45.504] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-11-28T16:14:45.510] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2024-11-29T03:42:37.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-29 03:42:37 +[2024-11-29T07:16:41.811] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-11-29T07:16:41.830] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-11-29T07:16:41.839] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-11-29T07:16:41.847] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2024-11-29T16:04:04.717] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-11-29T16:04:04.727] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-11-29T16:04:04.738] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-11-29T16:04:04.745] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2024-11-30T03:42:38.013] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-30 03:42:38 +[2024-11-30T07:04:59.066] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-11-30T07:04:59.079] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-11-30T07:04:59.085] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-11-30T07:04:59.096] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2024-11-30T16:17:07.902] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-11-30T16:17:07.914] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-11-30T16:17:07.921] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-11-30T16:17:07.927] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2024-12-01T03:42:39.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-01 03:42:39 +[2024-12-01T07:05:51.770] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-12-01T07:05:51.782] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-12-01T07:05:51.789] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-12-01T07:05:51.797] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2024-12-01T16:15:06.461] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-12-01T16:15:06.473] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-12-01T16:15:06.479] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-12-01T16:15:06.485] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2024-12-02T03:42:40.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-02 03:42:40 +[2024-12-02T07:07:00.949] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-12-02T07:07:00.961] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-12-02T07:07:00.969] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-12-02T07:07:00.976] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2024-12-02T16:13:59.962] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-12-02T16:13:59.975] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-12-02T16:13:59.981] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-12-02T16:13:59.988] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2024-12-03T03:42:41.013] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-03 03:42:41 +[2024-12-03T07:09:34.517] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-12-03T07:09:34.530] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-12-03T07:09:34.538] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-12-03T07:09:34.545] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2024-12-03T16:08:46.816] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-12-03T16:08:46.830] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-12-03T16:08:46.837] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-12-03T16:08:46.844] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2024-12-04T00:19:06.204] [INFO] monitorLogs - MQTT client connected +[2024-12-04T03:42:42.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-04 03:42:42 +[2024-12-04T07:21:11.629] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-12-04T07:21:11.640] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-12-04T07:21:11.646] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-12-04T07:21:11.656] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2024-12-04T16:07:10.907] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-12-04T16:07:10.918] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-12-04T16:07:10.924] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-12-04T16:07:10.931] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2024-12-05T03:42:43.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-05 03:42:43 +[2024-12-05T07:09:53.460] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-12-05T07:09:53.474] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-12-05T07:09:53.480] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-12-05T07:09:53.488] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2024-12-05T14:33:05.985] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2024-12-05T14:33:11.391] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 true turn off on startup +[2024-12-05T14:33:11.405] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 true turn off on startup +[2024-12-05T14:33:11.412] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 true turn off on startup +[2024-12-05T14:33:11.418] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 true turn off on startup +[2024-12-05T14:33:16.430] [INFO] monitorLogs - buildTasks - params undefined +[2024-12-05T14:33:16.431] [INFO] monitorLogs - buildTasks: profile for line 1 +[2024-12-05T14:33:16.432] [INFO] monitorLogs - profile: { + 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 +} +[2024-12-05T14:33:16.436] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-12-05T14:33:16.438] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2024-12-06T06:58:00.437Z +[2024-12-05T14:33:16.439] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2024-12-05T15:27:00.438Z +[2024-12-05T14:33:16.439] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:58', name: 'luxOff' }, + { value: 1, start_time: '16:27', name: 'luxOn' } +] +[2024-12-05T14:33:16.440] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2024-12-05T14:33:16.441] [INFO] monitorLogs - buildTasks: profile for line 2 +[2024-12-05T14:33:16.442] [INFO] monitorLogs - profile: { + 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 +} +[2024-12-05T14:33:16.444] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-12-05T14:33:16.445] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2024-12-06T06:58:00.445Z +[2024-12-05T14:33:16.445] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2024-12-05T15:27:00.445Z +[2024-12-05T14:33:16.446] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:58', name: 'luxOff' }, + { value: 1, start_time: '16:27', name: 'luxOn' } +] +[2024-12-05T14:33:16.447] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2024-12-05T14:33:16.448] [INFO] monitorLogs - buildTasks: profile for line 3 +[2024-12-05T14:33:16.448] [INFO] monitorLogs - profile: { + 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 +} +[2024-12-05T14:33:16.450] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-12-05T14:33:16.451] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2024-12-06T06:58:00.451Z +[2024-12-05T14:33:16.451] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2024-12-05T15:27:00.451Z +[2024-12-05T14:33:16.452] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:58', name: 'luxOff' }, + { value: 1, start_time: '16:27', name: 'luxOn' } +] +[2024-12-05T14:33:16.453] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2024-12-05T14:33:16.454] [INFO] monitorLogs - buildTasks: profile for line 4 +[2024-12-05T14:33:16.454] [INFO] monitorLogs - profile: { + 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 +} +[2024-12-05T14:33:16.456] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-12-05T14:33:16.457] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 4 2024-12-06T06:58:00.457Z +[2024-12-05T14:33:16.458] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 4 2024-12-05T15:27:00.457Z +[2024-12-05T14:33:16.458] [INFO] monitorLogs - -->time_points final 4 [ + { value: 0, start_time: '7:58', name: 'luxOff' }, + { value: 1, start_time: '16:27', name: 'luxOn' } +] +[2024-12-05T14:33:16.459] [INFO] monitorLogs - -->currentValue for relay 4 0 +[2024-12-05T14:33:16.473] [INFO] monitorLogs - tasks created: 2177 +[2024-12-05T14:33:16.475] [INFO] monitorLogs - -->FLOW bol spustený wvKJdZML6mXP4DzWBAXxwBAjxNloa5g23Ve9Y1ry 2024-11-04 +[2024-12-05T14:40:52.161] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2024-12-05T14:40:57.571] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 true turn off on startup +[2024-12-05T14:40:57.587] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 true turn off on startup +[2024-12-05T14:40:57.593] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 true turn off on startup +[2024-12-05T14:40:57.600] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 true turn off on startup +[2024-12-05T14:40:57.680] [INFO] monitorLogs - MQTT client connected +[2024-12-05T14:41:02.611] [INFO] monitorLogs - buildTasks - params undefined +[2024-12-05T14:41:02.613] [INFO] monitorLogs - buildTasks: profile for line 1 +[2024-12-05T14:41:02.613] [INFO] monitorLogs - profile: { + 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 +} +[2024-12-05T14:41:02.617] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-12-05T14:41:02.619] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2024-12-06T06:58:00.618Z +[2024-12-05T14:41:02.620] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2024-12-05T15:27:00.620Z +[2024-12-05T14:41:02.621] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:58', name: 'luxOff' }, + { value: 1, start_time: '16:27', name: 'luxOn' } +] +[2024-12-05T14:41:02.622] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2024-12-05T14:41:02.623] [INFO] monitorLogs - buildTasks: profile for line 2 +[2024-12-05T14:41:02.623] [INFO] monitorLogs - profile: { + 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 +} +[2024-12-05T14:41:02.626] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-12-05T14:41:02.626] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2024-12-06T06:58:00.626Z +[2024-12-05T14:41:02.627] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2024-12-05T15:27:00.627Z +[2024-12-05T14:41:02.628] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:58', name: 'luxOff' }, + { value: 1, start_time: '16:27', name: 'luxOn' } +] +[2024-12-05T14:41:02.629] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2024-12-05T14:41:02.629] [INFO] monitorLogs - buildTasks: profile for line 3 +[2024-12-05T14:41:02.630] [INFO] monitorLogs - profile: { + 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 +} +[2024-12-05T14:41:02.632] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-12-05T14:41:02.633] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2024-12-06T06:58:00.632Z +[2024-12-05T14:41:02.633] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2024-12-05T15:27:00.633Z +[2024-12-05T14:41:02.634] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:58', name: 'luxOff' }, + { value: 1, start_time: '16:27', name: 'luxOn' } +] +[2024-12-05T14:41:02.635] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2024-12-05T14:41:02.636] [INFO] monitorLogs - buildTasks: profile for line 4 +[2024-12-05T14:41:02.636] [INFO] monitorLogs - profile: { + 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 +} +[2024-12-05T14:41:02.638] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-12-05T14:41:02.639] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 4 2024-12-06T06:58:00.639Z +[2024-12-05T14:41:02.640] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 4 2024-12-05T15:27:00.640Z +[2024-12-05T14:41:02.640] [INFO] monitorLogs - -->time_points final 4 [ + { value: 0, start_time: '7:58', name: 'luxOff' }, + { value: 1, start_time: '16:27', name: 'luxOn' } +] +[2024-12-05T14:41:02.641] [INFO] monitorLogs - -->currentValue for relay 4 0 +[2024-12-05T14:41:02.655] [INFO] monitorLogs - tasks created: 2177 +[2024-12-05T14:41:02.658] [INFO] monitorLogs - -->FLOW bol spustený wvKJdZML6mXP4DzWBAXxwBAjxNloa5g23Ve9Y1ry 2024-11-04 +[2024-12-05T16:13:25.922] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-12-05T16:13:25.933] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-12-05T16:13:25.940] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-12-05T16:13:25.947] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2024-12-05T17:23:08.112] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2024-12-05T17:23:13.507] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 true turn off on startup +[2024-12-05T17:23:13.521] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 true turn off on startup +[2024-12-05T17:23:13.527] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 true turn off on startup +[2024-12-05T17:23:13.533] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 true turn off on startup +[2024-12-05T17:23:13.671] [INFO] monitorLogs - MQTT client connected +[2024-12-05T17:23:18.544] [INFO] monitorLogs - buildTasks - params undefined +[2024-12-05T17:23:18.546] [INFO] monitorLogs - buildTasks: profile for line 1 +[2024-12-05T17:23:18.546] [INFO] monitorLogs - profile: { + 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 +} +[2024-12-05T17:23:18.551] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-12-05T17:23:18.552] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2024-12-06T06:58:00.551Z +[2024-12-05T17:23:18.553] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2024-12-06T15:27:00.553Z +[2024-12-05T17:23:18.554] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:58', name: 'luxOff' }, + { value: 1, start_time: '16:27', name: 'luxOn' } +] +[2024-12-05T17:23:18.555] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2024-12-05T17:23:18.556] [INFO] monitorLogs - buildTasks: profile for line 2 +[2024-12-05T17:23:18.556] [INFO] monitorLogs - profile: { + 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 +} +[2024-12-05T17:23:18.558] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-12-05T17:23:18.559] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2024-12-06T06:58:00.559Z +[2024-12-05T17:23:18.560] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2024-12-06T15:27:00.560Z +[2024-12-05T17:23:18.560] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:58', name: 'luxOff' }, + { value: 1, start_time: '16:27', name: 'luxOn' } +] +[2024-12-05T17:23:18.561] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2024-12-05T17:23:18.562] [INFO] monitorLogs - buildTasks: profile for line 3 +[2024-12-05T17:23:18.563] [INFO] monitorLogs - profile: { + 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 +} +[2024-12-05T17:23:18.565] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-12-05T17:23:18.565] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2024-12-06T06:58:00.565Z +[2024-12-05T17:23:18.566] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2024-12-06T15:27:00.566Z +[2024-12-05T17:23:18.566] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:58', name: 'luxOff' }, + { value: 1, start_time: '16:27', name: 'luxOn' } +] +[2024-12-05T17:23:18.567] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2024-12-05T17:23:18.568] [INFO] monitorLogs - buildTasks: profile for line 4 +[2024-12-05T17:23:18.569] [INFO] monitorLogs - profile: { + 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 +} +[2024-12-05T17:23:18.571] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-12-05T17:23:18.571] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 4 2024-12-06T06:58:00.571Z +[2024-12-05T17:23:18.572] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 4 2024-12-06T15:27:00.572Z +[2024-12-05T17:23:18.573] [INFO] monitorLogs - -->time_points final 4 [ + { value: 0, start_time: '7:58', name: 'luxOff' }, + { value: 1, start_time: '16:27', name: 'luxOn' } +] +[2024-12-05T17:23:18.574] [INFO] monitorLogs - -->currentValue for relay 4 1 +[2024-12-05T17:23:18.587] [INFO] monitorLogs - tasks created: 2177 +[2024-12-05T17:23:18.590] [INFO] monitorLogs - -->FLOW bol spustený wvKJdZML6mXP4DzWBAXxwBAjxNloa5g23Ve9Y1ry 2024-11-04 +[2024-12-05T17:23:18.897] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-05T17:23:18.941] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-05T17:23:18.984] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-05T17:23:19.027] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false aplikovany bod profilu +[2024-12-06T03:23:15.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-06 03:23:15 +[2024-12-06T07:24:08.436] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-12-06T07:24:08.449] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-12-06T07:24:08.456] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-12-06T07:24:08.464] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2024-12-06T15:58:15.625] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-12-06T15:58:15.636] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-12-06T15:58:15.643] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-12-06T15:58:15.650] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2024-12-07T03:23:16.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-07 03:23:16 +[2024-12-07T07:23:08.447] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-12-07T07:23:08.460] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-12-07T07:23:08.467] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-12-07T07:23:08.475] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2024-12-07T16:07:17.126] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-12-07T16:07:17.139] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-12-07T16:07:17.146] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-12-07T16:07:17.153] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2024-12-08T03:23:17.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-08 03:23:17 +[2024-12-08T07:27:21.476] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-12-08T07:27:21.491] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-12-08T07:27:21.499] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-12-08T07:27:21.506] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2024-12-08T12:48:53.734] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-08T12:48:54.822] [INFO] monitorLogs - websocket error, reconnect +[2024-12-08T12:48:54.824] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-08T12:55:33.589] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2024-12-08T12:55:38.986] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 true turn off on startup +[2024-12-08T12:55:39.001] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 true turn off on startup +[2024-12-08T12:55:39.008] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 true turn off on startup +[2024-12-08T12:55:39.014] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 true turn off on startup +[2024-12-08T12:55:39.140] [INFO] monitorLogs - MQTT client connected +[2024-12-08T12:55:44.026] [INFO] monitorLogs - buildTasks - params undefined +[2024-12-08T12:55:44.027] [INFO] monitorLogs - buildTasks: profile for line 1 +[2024-12-08T12:55:44.028] [INFO] monitorLogs - profile: { + 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 +} +[2024-12-08T12:55:44.034] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-12-08T12:55:44.036] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2024-12-09T07:02:00.035Z +[2024-12-08T12:55:44.037] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2024-12-08T15:26:00.037Z +[2024-12-08T12:55:44.038] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '8:2', name: 'luxOff' }, + { value: 1, start_time: '16:26', name: 'luxOn' } +] +[2024-12-08T12:55:44.039] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2024-12-08T12:55:44.041] [INFO] monitorLogs - buildTasks: profile for line 2 +[2024-12-08T12:55:44.041] [INFO] monitorLogs - profile: { + 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 +} +[2024-12-08T12:55:44.043] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-12-08T12:55:44.044] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2024-12-09T07:02:00.044Z +[2024-12-08T12:55:44.045] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2024-12-08T15:26:00.045Z +[2024-12-08T12:55:44.046] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '8:2', name: 'luxOff' }, + { value: 1, start_time: '16:26', name: 'luxOn' } +] +[2024-12-08T12:55:44.047] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2024-12-08T12:55:44.047] [INFO] monitorLogs - buildTasks: profile for line 3 +[2024-12-08T12:55:44.048] [INFO] monitorLogs - profile: { + 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 +} +[2024-12-08T12:55:44.050] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-12-08T12:55:44.051] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2024-12-09T07:02:00.050Z +[2024-12-08T12:55:44.051] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2024-12-08T15:26:00.051Z +[2024-12-08T12:55:44.052] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '8:2', name: 'luxOff' }, + { value: 1, start_time: '16:26', name: 'luxOn' } +] +[2024-12-08T12:55:44.053] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2024-12-08T12:55:44.054] [INFO] monitorLogs - buildTasks: profile for line 4 +[2024-12-08T12:55:44.054] [INFO] monitorLogs - profile: { + 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 +} +[2024-12-08T12:55:44.056] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-12-08T12:55:44.057] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 4 2024-12-09T07:02:00.057Z +[2024-12-08T12:55:44.058] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 4 2024-12-08T15:26:00.058Z +[2024-12-08T12:55:44.058] [INFO] monitorLogs - -->time_points final 4 [ + { value: 0, start_time: '8:2', name: 'luxOff' }, + { value: 1, start_time: '16:26', name: 'luxOn' } +] +[2024-12-08T12:55:44.059] [INFO] monitorLogs - -->currentValue for relay 4 0 +[2024-12-08T12:55:44.077] [INFO] monitorLogs - tasks created: 2177 +[2024-12-08T12:55:44.081] [INFO] monitorLogs - -->FLOW bol spustený wvKJdZML6mXP4DzWBAXxwBAjxNloa5g23Ve9Y1ry 2024-11-04 +[2024-12-08T16:11:43.016] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-12-08T16:11:43.034] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-12-08T16:11:43.042] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-12-08T16:11:43.050] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2024-12-09T03:55:41.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-09 03:55:41 +[2024-12-09T07:26:55.766] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-12-09T07:26:55.779] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-12-09T07:26:55.786] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-12-09T07:26:55.793] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2024-12-09T16:10:37.800] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-12-09T16:10:37.810] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-12-09T16:10:37.816] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-12-09T16:10:37.822] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2024-12-10T03:55:42.014] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-10 03:55:42 +[2024-12-10T06:40:58.730] [INFO] monitorLogs - MQTT client connected +[2024-12-10T07:26:09.001] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-12-10T07:26:09.014] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-12-10T07:26:09.023] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-12-10T07:26:09.030] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2024-12-10T16:07:39.330] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-12-10T16:07:39.341] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-12-10T16:07:39.347] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-12-10T16:07:39.353] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2024-12-11T03:55:43.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-11 03:55:43 +[2024-12-11T07:25:10.662] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-12-11T07:25:10.674] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-12-11T07:25:10.681] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-12-11T07:25:10.689] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2024-12-11T16:03:36.654] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-12-11T16:03:36.689] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-12-11T16:03:36.695] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-12-11T16:03:36.701] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2024-12-12T03:55:44.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-12 03:55:44 +[2024-12-12T07:18:50.715] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-12-12T07:18:50.727] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-12-12T07:18:50.733] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-12-12T07:18:50.741] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2024-12-12T13:55:42.120] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2024-12-12T13:55:47.455] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 true turn off on startup +[2024-12-12T13:55:47.470] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 true turn off on startup +[2024-12-12T13:55:47.477] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 true turn off on startup +[2024-12-12T13:55:47.483] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 true turn off on startup +[2024-12-12T13:55:47.620] [INFO] monitorLogs - MQTT client connected +[2024-12-12T13:55:52.502] [INFO] monitorLogs - buildTasks - params undefined +[2024-12-12T13:55:52.503] [INFO] monitorLogs - buildTasks: profile for line 1 +[2024-12-12T13:55:52.504] [INFO] monitorLogs - profile: { + 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 +} +[2024-12-12T13:55:52.508] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-12-12T13:55:52.509] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2024-12-13T07:06:00.509Z +[2024-12-12T13:55:52.511] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2024-12-12T15:26:00.510Z +[2024-12-12T13:55:52.511] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '8:6', name: 'luxOff' }, + { value: 1, start_time: '16:26', name: 'luxOn' } +] +[2024-12-12T13:55:52.513] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2024-12-12T13:55:52.513] [INFO] monitorLogs - buildTasks: profile for line 2 +[2024-12-12T13:55:52.514] [INFO] monitorLogs - profile: { + 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 +} +[2024-12-12T13:55:52.516] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-12-12T13:55:52.517] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2024-12-13T07:06:00.517Z +[2024-12-12T13:55:52.518] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2024-12-12T15:26:00.518Z +[2024-12-12T13:55:52.518] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '8:6', name: 'luxOff' }, + { value: 1, start_time: '16:26', name: 'luxOn' } +] +[2024-12-12T13:55:52.519] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2024-12-12T13:55:52.520] [INFO] monitorLogs - buildTasks: profile for line 3 +[2024-12-12T13:55:52.520] [INFO] monitorLogs - profile: { + 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 +} +[2024-12-12T13:55:52.523] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-12-12T13:55:52.523] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2024-12-13T07:06:00.523Z +[2024-12-12T13:55:52.524] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2024-12-12T15:26:00.524Z +[2024-12-12T13:55:52.525] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '8:6', name: 'luxOff' }, + { value: 1, start_time: '16:26', name: 'luxOn' } +] +[2024-12-12T13:55:52.525] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2024-12-12T13:55:52.526] [INFO] monitorLogs - buildTasks: profile for line 4 +[2024-12-12T13:55:52.527] [INFO] monitorLogs - profile: { + 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 +} +[2024-12-12T13:55:52.529] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-12-12T13:55:52.529] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 4 2024-12-13T07:06:00.529Z +[2024-12-12T13:55:52.530] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 4 2024-12-12T15:26:00.530Z +[2024-12-12T13:55:52.531] [INFO] monitorLogs - -->time_points final 4 [ + { value: 0, start_time: '8:6', name: 'luxOff' }, + { value: 1, start_time: '16:26', name: 'luxOn' } +] +[2024-12-12T13:55:52.532] [INFO] monitorLogs - -->currentValue for relay 4 0 +[2024-12-12T13:55:52.545] [INFO] monitorLogs - tasks created: 2209 +[2024-12-12T13:55:52.549] [INFO] monitorLogs - -->FLOW bol spustený wvKJdZML6mXP4DzWBAXxwBAjxNloa5g23Ve9Y1ry 2024-11-04 +[2024-12-12T16:05:02.490] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-12-12T16:05:02.527] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-12-12T16:05:02.535] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-12-12T16:05:02.543] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2024-12-13T03:55:50.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-13 03:55:50 +[2024-12-13T07:22:48.882] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-12-13T07:22:48.894] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-12-13T07:22:48.901] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-12-13T07:22:48.909] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2024-12-13T16:05:55.666] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-12-13T16:05:55.697] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-12-13T16:05:55.705] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-12-13T16:05:55.713] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2024-12-14T03:55:51.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-14 03:55:51 +[2024-12-14T07:35:49.856] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-12-14T07:35:49.879] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-12-14T07:35:49.887] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-12-14T07:35:49.896] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2024-12-14T16:03:02.387] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-12-14T16:03:02.398] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-12-14T16:03:02.405] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-12-14T16:03:02.411] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2024-12-15T03:55:52.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-15 03:55:52 +[2024-12-15T07:30:50.616] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-12-15T07:30:50.636] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-12-15T07:30:50.642] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-12-15T07:30:50.649] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2024-12-15T16:06:34.132] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-12-15T16:06:34.142] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-12-15T16:06:34.149] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-12-15T16:06:34.155] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2024-12-16T03:55:53.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-16 03:55:53 +[2024-12-16T07:38:28.511] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-12-16T07:38:28.523] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-12-16T07:38:28.530] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-12-16T07:38:28.538] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2024-12-16T08:17:02.788] [INFO] monitorLogs - MQTT client connected +[2024-12-16T16:02:00.887] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-12-16T16:02:00.898] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-12-16T16:02:00.905] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-12-16T16:02:00.912] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2024-12-17T03:55:54.013] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-17 03:55:54 +[2024-12-17T07:26:39.192] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-12-17T07:26:39.204] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-12-17T07:26:39.211] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-12-17T07:26:39.218] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2024-12-17T16:05:38.660] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-12-17T16:05:38.671] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-12-17T16:05:38.678] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-12-17T16:05:38.685] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2024-12-18T03:55:55.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-18 03:55:55 +[2024-12-18T07:23:42.922] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-12-18T07:23:42.934] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-12-18T07:23:42.941] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-12-18T07:23:42.949] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2024-12-18T16:12:10.946] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-12-18T16:12:10.961] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-12-18T16:12:10.966] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-12-18T16:12:10.972] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2024-12-19T03:55:57.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-19 03:55:57 +[2024-12-19T07:24:48.042] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-12-19T07:24:48.054] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-12-19T07:24:48.061] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-12-19T07:24:48.068] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2024-12-19T16:08:02.453] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-12-19T16:08:02.465] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-12-19T16:08:02.473] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-12-19T16:08:02.479] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2024-12-20T03:55:59.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-20 03:55:59 +[2024-12-20T07:30:17.406] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-12-20T07:30:17.439] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-12-20T07:30:17.447] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-12-20T07:30:17.453] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2024-12-20T16:08:53.431] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-12-20T16:08:53.442] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-12-20T16:08:53.449] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-12-20T16:08:53.456] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2024-12-21T03:55:58.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-21 03:55:58 +[2024-12-21T07:27:20.699] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-12-21T07:27:20.710] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-12-21T07:27:20.717] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-12-21T07:27:20.726] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2024-12-21T16:17:31.095] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-12-21T16:17:31.138] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-12-21T16:17:31.146] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-12-21T16:17:31.152] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2024-12-22T03:56:00.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-22 03:56:00 +[2024-12-22T07:34:03.732] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-12-22T07:34:03.743] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-12-22T07:34:03.750] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-12-22T07:34:03.757] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2024-12-22T15:50:25.385] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-12-22T15:50:25.399] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-12-22T15:50:25.404] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-12-22T15:50:25.411] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2024-12-23T03:56:00.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-23 03:56:00 +[2024-12-23T07:34:42.537] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-12-23T07:34:42.549] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-12-23T07:34:42.555] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-12-23T07:34:42.563] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2024-12-23T16:12:14.201] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-12-23T16:12:14.215] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-12-23T16:12:14.222] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-12-23T16:12:14.229] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2024-12-24T03:56:01.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-24 03:56:01 +[2024-12-24T07:39:20.044] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-12-24T07:39:20.056] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-12-24T07:39:20.064] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-12-24T07:39:20.072] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2024-12-24T16:04:24.963] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-12-24T16:04:24.973] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-12-24T16:04:24.981] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-12-24T16:04:24.987] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2024-12-25T03:56:02.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-25 03:56:02 +[2024-12-25T07:25:49.892] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-12-25T07:25:49.904] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-12-25T07:25:49.911] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-12-25T07:25:49.921] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2024-12-25T16:19:08.311] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-12-25T16:19:08.323] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-12-25T16:19:08.336] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-12-25T16:19:08.343] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2024-12-26T03:56:03.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-26 03:56:03 +[2024-12-26T07:25:44.059] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-12-26T07:25:44.070] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-12-26T07:25:44.077] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-12-26T07:25:44.087] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2024-12-26T16:20:03.763] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-12-26T16:20:03.790] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-12-26T16:20:03.796] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-12-26T16:20:03.803] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2024-12-27T03:56:04.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-27 03:56:04 +[2024-12-27T07:27:22.824] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-12-27T07:27:22.836] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-12-27T07:27:22.842] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-12-27T07:27:22.849] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2024-12-27T16:20:46.201] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-12-27T16:20:46.230] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-12-27T16:20:46.237] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-12-27T16:20:46.242] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2024-12-28T03:56:06.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-28 03:56:06 +[2024-12-28T07:27:40.518] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-12-28T07:27:40.529] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-12-28T07:27:40.537] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-12-28T07:27:40.544] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2024-12-28T16:21:25.134] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-12-28T16:21:25.155] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-12-28T16:21:25.162] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-12-28T16:21:25.168] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2024-12-29T03:56:07.016] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-29 03:56:07 +[2024-12-29T07:26:14.999] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-12-29T07:26:15.011] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-12-29T07:26:15.018] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-12-29T07:26:15.025] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2024-12-29T16:21:25.223] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-12-29T16:21:25.257] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-12-29T16:21:25.264] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-12-29T16:21:25.270] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2024-12-30T03:56:08.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-30 03:56:08 +[2024-12-30T07:26:24.390] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-12-30T07:26:24.402] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-12-30T07:26:24.408] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-12-30T07:26:24.415] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2024-12-30T16:24:55.636] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-12-30T16:24:55.644] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-12-30T16:24:55.653] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-12-30T16:24:55.659] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2024-12-31T03:56:09.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-31 03:56:09 +[2024-12-31T07:33:05.860] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-12-31T07:33:05.871] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-12-31T07:33:05.878] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-12-31T07:33:05.885] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2024-12-31T16:14:57.194] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-12-31T16:14:57.206] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-12-31T16:14:57.213] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-12-31T16:14:57.218] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-01-01T03:56:10.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-01 03:56:10 +[2025-01-01T07:34:23.919] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-01-01T07:34:23.936] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-01-01T07:34:23.943] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-01-01T07:34:23.950] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-01-01T16:21:26.398] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-01-01T16:21:26.426] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-01-01T16:21:26.432] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-01-01T16:21:26.438] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-01-02T03:56:12.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-02 03:56:12 +[2025-01-02T07:25:50.321] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-01-02T07:25:50.335] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-01-02T07:25:50.343] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-01-02T07:25:50.350] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-01-02T08:47:39.190] [INFO] monitorLogs - MQTT client error Error: connect ECONNREFUSED 192.168.252.1:1883 + at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1159:16) { + errno: -111, + code: 'ECONNREFUSED', + syscall: 'connect', + address: '192.168.252.1', + port: 1883 +} +[2025-01-02T11:44:47.179] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-01-02T11:44:52.535] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 true turn off on startup +[2025-01-02T11:44:52.551] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 true turn off on startup +[2025-01-02T11:44:52.558] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 true turn off on startup +[2025-01-02T11:44:52.565] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 true turn off on startup +[2025-01-02T11:44:52.621] [INFO] monitorLogs - MQTT client error Error: connect ECONNREFUSED 192.168.252.1:1883 + at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1159:16) { + errno: -111, + code: 'ECONNREFUSED', + syscall: 'connect', + address: '192.168.252.1', + port: 1883 +} +[2025-01-02T11:44:57.578] [INFO] monitorLogs - buildTasks - params undefined +[2025-01-02T11:44:57.580] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-01-02T11:44:57.581] [INFO] monitorLogs - profile: { + 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 +} +[2025-01-02T11:44:57.585] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-02T11:44:57.587] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-01-03T07:14:00.586Z +[2025-01-02T11:44:57.588] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-01-02T15:37:00.587Z +[2025-01-02T11:44:57.588] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '8:14', name: 'luxOff' }, + { value: 1, start_time: '16:37', name: 'luxOn' } +] +[2025-01-02T11:44:57.590] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-01-02T11:44:57.590] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-01-02T11:44:57.591] [INFO] monitorLogs - profile: { + 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 +} +[2025-01-02T11:44:57.593] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-02T11:44:57.594] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-01-03T07:14:00.594Z +[2025-01-02T11:44:57.595] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-01-02T15:37:00.595Z +[2025-01-02T11:44:57.595] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '8:14', name: 'luxOff' }, + { value: 1, start_time: '16:37', name: 'luxOn' } +] +[2025-01-02T11:44:57.596] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-01-02T11:44:57.597] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-01-02T11:44:57.598] [INFO] monitorLogs - profile: { + 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 +} +[2025-01-02T11:44:57.600] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-02T11:44:57.600] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-01-03T07:14:00.600Z +[2025-01-02T11:44:57.601] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-01-02T15:37:00.601Z +[2025-01-02T11:44:57.602] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '8:14', name: 'luxOff' }, + { value: 1, start_time: '16:37', name: 'luxOn' } +] +[2025-01-02T11:44:57.603] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-01-02T11:44:57.603] [INFO] monitorLogs - buildTasks: profile for line 4 +[2025-01-02T11:44:57.604] [INFO] monitorLogs - profile: { + 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 +} +[2025-01-02T11:44:57.606] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-02T11:44:57.607] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 4 2025-01-03T07:14:00.607Z +[2025-01-02T11:44:57.607] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 4 2025-01-02T15:37:00.607Z +[2025-01-02T11:44:57.608] [INFO] monitorLogs - -->time_points final 4 [ + { value: 0, start_time: '8:14', name: 'luxOff' }, + { value: 1, start_time: '16:37', name: 'luxOn' } +] +[2025-01-02T11:44:57.609] [INFO] monitorLogs - -->currentValue for relay 4 0 +[2025-01-02T11:44:57.629] [INFO] monitorLogs - tasks created: 2209 +[2025-01-02T11:44:57.632] [INFO] monitorLogs - -->FLOW bol spustený wvKJdZML6mXP4DzWBAXxwBAjxNloa5g23Ve9Y1ry 2025-01-02 +[2025-01-02T16:14:15.052] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-01-02T16:14:15.065] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-01-02T16:14:15.074] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-01-02T16:14:15.081] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-01-03T03:44:54.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-03 03:44:54 +[2025-01-03T07:28:32.458] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-01-03T07:28:32.470] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-01-03T07:28:32.482] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-01-03T07:28:32.490] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-01-03T10:13:32.966] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-01-03T10:13:38.312] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 true turn off on startup +[2025-01-03T10:13:38.328] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 true turn off on startup +[2025-01-03T10:13:38.336] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 true turn off on startup +[2025-01-03T10:13:38.344] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 true turn off on startup +[2025-01-03T10:13:38.360] [INFO] monitorLogs - MQTT client error Error: connect ECONNREFUSED 192.168.252.1:1883 + at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1159:16) { + errno: -111, + code: 'ECONNREFUSED', + syscall: 'connect', + address: '192.168.252.1', + port: 1883 +} +[2025-01-03T10:13:43.359] [INFO] monitorLogs - buildTasks - params undefined +[2025-01-03T10:13:43.360] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-01-03T10:13:43.361] [INFO] monitorLogs - profile: { + 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 +} +[2025-01-03T10:13:43.365] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-03T10:13:43.366] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-01-04T07:14:00.366Z +[2025-01-03T10:13:43.368] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-01-03T15:38:00.367Z +[2025-01-03T10:13:43.368] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '8:14', name: 'luxOff' }, + { value: 1, start_time: '16:38', name: 'luxOn' } +] +[2025-01-03T10:13:43.369] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-01-03T10:13:43.370] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-01-03T10:13:43.371] [INFO] monitorLogs - profile: { + 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 +} +[2025-01-03T10:13:43.373] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-03T10:13:43.374] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-01-04T07:14:00.374Z +[2025-01-03T10:13:43.375] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-01-03T15:38:00.374Z +[2025-01-03T10:13:43.375] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '8:14', name: 'luxOff' }, + { value: 1, start_time: '16:38', name: 'luxOn' } +] +[2025-01-03T10:13:43.376] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-01-03T10:13:43.377] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-01-03T10:13:43.377] [INFO] monitorLogs - profile: { + 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 +} +[2025-01-03T10:13:43.380] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-03T10:13:43.380] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-01-04T07:14:00.380Z +[2025-01-03T10:13:43.381] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-01-03T15:38:00.381Z +[2025-01-03T10:13:43.382] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '8:14', name: 'luxOff' }, + { value: 1, start_time: '16:38', name: 'luxOn' } +] +[2025-01-03T10:13:43.383] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-01-03T10:13:43.384] [INFO] monitorLogs - buildTasks: profile for line 4 +[2025-01-03T10:13:43.385] [INFO] monitorLogs - profile: { + 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 +} +[2025-01-03T10:13:43.387] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-03T10:13:43.388] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 4 2025-01-04T07:14:00.388Z +[2025-01-03T10:13:43.389] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 4 2025-01-03T15:38:00.389Z +[2025-01-03T10:13:43.389] [INFO] monitorLogs - -->time_points final 4 [ + { value: 0, start_time: '8:14', name: 'luxOff' }, + { value: 1, start_time: '16:38', name: 'luxOn' } +] +[2025-01-03T10:13:43.390] [INFO] monitorLogs - -->currentValue for relay 4 0 +[2025-01-03T10:13:43.408] [INFO] monitorLogs - tasks created: 2209 +[2025-01-03T10:13:43.411] [INFO] monitorLogs - -->FLOW bol spustený wvKJdZML6mXP4DzWBAXxwBAjxNloa5g23Ve9Y1ry 2025-01-02 +[2025-01-03T16:24:41.013] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-01-03T16:24:41.027] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-01-03T16:24:41.034] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-01-03T16:24:41.042] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-01-04T03:13:40.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-04 03:13:40 +[2025-01-04T07:27:47.311] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-01-04T07:27:47.353] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-01-04T07:27:47.360] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-01-04T07:27:47.367] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-01-04T16:24:12.618] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-01-04T16:24:12.667] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-01-04T16:24:12.675] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-01-04T16:24:12.682] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-01-05T03:13:41.013] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-05 03:13:41 +[2025-01-05T07:38:02.733] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-01-05T07:38:02.747] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-01-05T07:38:02.756] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-01-05T07:38:02.764] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-01-05T16:13:55.170] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-01-05T16:13:55.272] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-01-05T16:13:55.281] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-01-05T16:13:55.288] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-01-06T03:13:42.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-06 03:13:42 +[2025-01-06T07:34:17.571] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-01-06T07:34:17.584] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-01-06T07:34:17.592] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-01-06T07:34:17.600] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-01-06T16:25:18.069] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-01-06T16:25:18.109] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-01-06T16:25:18.116] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-01-06T16:25:18.123] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-01-07T03:13:43.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-07 03:13:43 +[2025-01-07T07:36:02.307] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-01-07T07:36:02.320] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-01-07T07:36:02.328] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-01-07T07:36:02.339] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-01-07T16:19:53.088] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-01-07T16:19:53.128] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-01-07T16:19:53.136] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-01-07T16:19:53.142] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-01-08T03:13:44.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-08 03:13:44 +[2025-01-08T07:30:08.175] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-01-08T07:30:08.189] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-01-08T07:30:08.197] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-01-08T07:30:08.205] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-01-08T16:27:51.312] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-01-08T16:27:51.326] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-01-08T16:27:51.335] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-01-08T16:27:51.343] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-01-09T03:13:45.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-09 03:13:45 +[2025-01-09T07:34:20.180] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-01-09T07:34:20.193] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-01-09T07:34:20.203] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-01-09T07:34:20.210] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-01-09T15:23:06.347] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-01-09T15:23:11.686] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 true turn off on startup +[2025-01-09T15:23:11.702] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 true turn off on startup +[2025-01-09T15:23:11.709] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 true turn off on startup +[2025-01-09T15:23:11.716] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 true turn off on startup +[2025-01-09T15:23:11.731] [INFO] monitorLogs - MQTT client error Error: connect ECONNREFUSED 192.168.252.1:1883 + at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1159:16) { + errno: -111, + code: 'ECONNREFUSED', + syscall: 'connect', + address: '192.168.252.1', + port: 1883 +} +[2025-01-09T15:23:16.733] [INFO] monitorLogs - buildTasks - params undefined +[2025-01-09T15:23:16.734] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-01-09T15:23:16.734] [INFO] monitorLogs - profile: { + 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 +} +[2025-01-09T15:23:16.738] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-09T15:23:16.740] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-01-10T07:13:00.739Z +[2025-01-09T15:23:16.741] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-01-09T15:45:00.741Z +[2025-01-09T15:23:16.742] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '8:13', name: 'luxOff' }, + { value: 1, start_time: '16:45', name: 'luxOn' } +] +[2025-01-09T15:23:16.743] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-01-09T15:23:16.744] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-01-09T15:23:16.744] [INFO] monitorLogs - profile: { + 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 +} +[2025-01-09T15:23:16.747] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-09T15:23:16.747] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-01-10T07:13:00.747Z +[2025-01-09T15:23:16.748] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-01-09T15:45:00.748Z +[2025-01-09T15:23:16.749] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '8:13', name: 'luxOff' }, + { value: 1, start_time: '16:45', name: 'luxOn' } +] +[2025-01-09T15:23:16.750] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-01-09T15:23:16.750] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-01-09T15:23:16.751] [INFO] monitorLogs - profile: { + 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 +} +[2025-01-09T15:23:16.753] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-09T15:23:16.754] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-01-10T07:13:00.754Z +[2025-01-09T15:23:16.754] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-01-09T15:45:00.754Z +[2025-01-09T15:23:16.755] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '8:13', name: 'luxOff' }, + { value: 1, start_time: '16:45', name: 'luxOn' } +] +[2025-01-09T15:23:16.756] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-01-09T15:23:16.757] [INFO] monitorLogs - buildTasks: profile for line 4 +[2025-01-09T15:23:16.757] [INFO] monitorLogs - profile: { + 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 +} +[2025-01-09T15:23:16.759] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-09T15:23:16.760] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 4 2025-01-10T07:13:00.760Z +[2025-01-09T15:23:16.761] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 4 2025-01-09T15:45:00.761Z +[2025-01-09T15:23:16.762] [INFO] monitorLogs - -->time_points final 4 [ + { value: 0, start_time: '8:13', name: 'luxOff' }, + { value: 1, start_time: '16:45', name: 'luxOn' } +] +[2025-01-09T15:23:16.763] [INFO] monitorLogs - -->currentValue for relay 4 0 +[2025-01-09T15:23:16.782] [INFO] monitorLogs - tasks created: 2209 +[2025-01-09T15:23:16.785] [INFO] monitorLogs - -->FLOW bol spustený wvKJdZML6mXP4DzWBAXxwBAjxNloa5g23Ve9Y1ry 2025-01-02 +[2025-01-09T16:29:43.606] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-01-09T16:29:43.619] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-01-09T16:29:43.626] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-01-09T16:29:43.633] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-01-10T03:23:13.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-10 03:23:13 +[2025-01-10T07:33:05.403] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-01-10T07:33:05.417] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-01-10T07:33:05.424] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-01-10T07:33:05.431] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-01-10T14:36:10.556] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-01-10T14:36:15.907] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 true turn off on startup +[2025-01-10T14:36:15.924] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 true turn off on startup +[2025-01-10T14:36:15.931] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 true turn off on startup +[2025-01-10T14:36:15.938] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 true turn off on startup +[2025-01-10T14:36:15.995] [INFO] monitorLogs - MQTT client error Error: connect ECONNREFUSED 192.168.252.1:1883 + at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1159:16) { + errno: -111, + code: 'ECONNREFUSED', + syscall: 'connect', + address: '192.168.252.1', + port: 1883 +} +[2025-01-10T14:36:20.951] [INFO] monitorLogs - buildTasks - params undefined +[2025-01-10T14:36:20.953] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-01-10T14:36:20.953] [INFO] monitorLogs - profile: { + 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 +} +[2025-01-10T14:36:20.958] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-10T14:36:20.959] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-01-11T07:12:00.958Z +[2025-01-10T14:36:20.960] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-01-10T15:46:00.960Z +[2025-01-10T14:36:20.961] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '8:12', name: 'luxOff' }, + { value: 1, start_time: '16:46', name: 'luxOn' } +] +[2025-01-10T14:36:20.962] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-01-10T14:36:20.963] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-01-10T14:36:20.963] [INFO] monitorLogs - profile: { + 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 +} +[2025-01-10T14:36:20.966] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-10T14:36:20.966] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-01-11T07:12:00.966Z +[2025-01-10T14:36:20.967] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-01-10T15:46:00.967Z +[2025-01-10T14:36:20.968] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '8:12', name: 'luxOff' }, + { value: 1, start_time: '16:46', name: 'luxOn' } +] +[2025-01-10T14:36:20.969] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-01-10T14:36:20.969] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-01-10T14:36:20.970] [INFO] monitorLogs - profile: { + 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 +} +[2025-01-10T14:36:20.972] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-10T14:36:20.973] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-01-11T07:12:00.973Z +[2025-01-10T14:36:20.974] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-01-10T15:46:00.974Z +[2025-01-10T14:36:20.974] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '8:12', name: 'luxOff' }, + { value: 1, start_time: '16:46', name: 'luxOn' } +] +[2025-01-10T14:36:20.975] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-01-10T14:36:20.976] [INFO] monitorLogs - buildTasks: profile for line 4 +[2025-01-10T14:36:20.977] [INFO] monitorLogs - profile: { + 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 +} +[2025-01-10T14:36:20.979] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-10T14:36:20.979] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 4 2025-01-11T07:12:00.979Z +[2025-01-10T14:36:20.980] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 4 2025-01-10T15:46:00.980Z +[2025-01-10T14:36:20.981] [INFO] monitorLogs - -->time_points final 4 [ + { value: 0, start_time: '8:12', name: 'luxOff' }, + { value: 1, start_time: '16:46', name: 'luxOn' } +] +[2025-01-10T14:36:20.982] [INFO] monitorLogs - -->currentValue for relay 4 0 +[2025-01-10T14:36:21.000] [INFO] monitorLogs - tasks created: 2209 +[2025-01-10T14:36:21.003] [INFO] monitorLogs - -->FLOW bol spustený wvKJdZML6mXP4DzWBAXxwBAjxNloa5g23Ve9Y1ry 2025-01-09 +[2025-01-10T15:58:14.198] [INFO] monitorLogs - MQTT client connected +[2025-01-10T16:24:42.541] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-01-10T16:24:42.553] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-01-10T16:24:42.560] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-01-10T16:24:42.567] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-01-11T03:36:18.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-11 03:36:18 +[2025-01-11T07:27:51.855] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-01-11T07:27:51.873] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-01-11T07:27:51.880] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-01-11T07:27:51.888] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-01-11T16:30:03.708] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-01-11T16:30:03.721] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-01-11T16:30:03.727] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-01-11T16:30:03.734] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-01-12T03:36:19.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-12 03:36:19 +[2025-01-12T07:33:30.914] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-01-12T07:33:30.932] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-01-12T07:33:30.940] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-01-12T07:33:30.947] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-01-12T16:27:56.467] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-01-12T16:27:56.481] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-01-12T16:27:56.487] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-01-12T16:27:56.495] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-01-13T03:36:21.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-13 03:36:21 +[2025-01-13T07:41:10.592] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-01-13T07:41:10.606] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-01-13T07:41:10.614] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-01-13T07:41:10.621] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-01-13T16:35:45.748] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-01-13T16:35:45.760] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-01-13T16:35:45.767] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-01-13T16:35:45.773] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-01-14T03:36:22.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-14 03:36:22 +[2025-01-14T07:21:16.402] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-01-14T07:21:16.416] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-01-14T07:21:16.426] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-01-14T07:21:16.432] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-01-14T16:36:13.169] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-01-14T16:36:13.181] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-01-14T16:36:13.188] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-01-14T16:36:13.194] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-01-15T03:36:23.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-15 03:36:23 +[2025-01-15T07:29:34.232] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-01-15T07:29:34.244] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-01-15T07:29:34.251] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-01-15T07:29:34.257] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-01-15T16:29:32.996] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-01-15T16:29:33.012] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-01-15T16:29:33.019] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-01-15T16:29:33.025] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-01-16T03:36:24.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-16 03:36:24 +[2025-01-16T07:24:07.468] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-01-16T07:24:07.497] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-01-16T07:24:07.506] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-01-16T07:24:07.514] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-01-16T16:31:51.084] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-01-16T16:31:51.096] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-01-16T16:31:51.103] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-01-16T16:31:51.111] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-01-17T03:36:25.015] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-17 03:36:25 +[2025-01-17T07:31:23.250] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-01-17T07:31:23.264] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-01-17T07:31:23.271] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-01-17T07:31:23.278] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-01-17T16:37:19.748] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-01-17T16:37:19.760] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-01-17T16:37:19.767] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-01-17T16:37:19.786] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-01-18T03:36:26.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-18 03:36:26 +[2025-01-18T07:25:52.668] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-01-18T07:25:52.686] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-01-18T07:25:52.693] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-01-18T07:25:52.700] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-01-18T16:42:03.037] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-01-18T16:42:03.049] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-01-18T16:42:03.055] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-01-18T16:42:03.061] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-01-19T03:36:27.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-19 03:36:27 +[2025-01-19T07:24:56.651] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-01-19T07:24:56.663] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-01-19T07:24:56.670] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-01-19T07:24:56.678] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-01-19T16:38:01.348] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-01-19T16:38:01.360] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-01-19T16:38:01.368] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-01-19T16:38:01.374] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-01-20T03:36:28.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-20 03:36:28 +[2025-01-20T07:27:20.192] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-01-20T07:27:20.205] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-01-20T07:27:20.213] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-01-20T07:27:20.221] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-01-20T16:38:28.114] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-01-20T16:38:28.126] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-01-20T16:38:28.132] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-01-20T16:38:28.139] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-01-21T03:36:29.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-21 03:36:29 +[2025-01-21T06:21:43.681] [INFO] monitorLogs - MQTT client connected +[2025-01-21T06:23:31.502] [INFO] monitorLogs - MQTT client connected +[2025-01-21T07:33:58.633] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-01-21T07:33:58.645] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-01-21T07:33:58.652] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-01-21T07:33:58.660] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-01-21T16:40:19.206] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-01-21T16:40:19.219] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-01-21T16:40:19.225] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-01-21T16:40:19.232] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-01-22T03:36:31.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-22 03:36:31 +[2025-01-22T07:28:41.132] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-01-22T07:28:41.144] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-01-22T07:28:41.154] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-01-22T07:28:41.161] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-01-22T13:29:49.656] [INFO] monitorLogs - MQTT client connected +[2025-01-22T13:30:13.718] [INFO] monitorLogs - MQTT client connected +[2025-01-22T13:30:44.748] [INFO] monitorLogs - MQTT client connected +[2025-01-22T16:38:18.799] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-01-22T16:38:18.812] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-01-22T16:38:18.820] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-01-22T16:38:18.826] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-01-23T03:36:32.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-23 03:36:32 +[2025-01-23T07:25:28.189] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-01-23T07:25:28.204] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-01-23T07:25:28.213] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-01-23T07:25:28.220] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-01-23T16:43:38.676] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-01-23T16:43:38.688] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-01-23T16:43:38.694] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-01-23T16:43:38.700] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-01-24T03:36:33.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-24 03:36:33 +[2025-01-24T07:16:57.247] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-01-24T07:16:57.260] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-01-24T07:16:57.268] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-01-24T07:16:57.275] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-01-24T16:51:52.082] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-01-24T16:51:52.093] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-01-24T16:51:52.099] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-01-24T16:51:52.105] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-01-25T03:36:34.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-25 03:36:34 +[2025-01-25T07:19:34.699] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-01-25T07:19:34.713] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-01-25T07:19:34.720] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-01-25T07:19:34.727] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-01-25T16:45:49.468] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-01-25T16:45:49.482] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-01-25T16:45:49.490] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-01-25T16:45:49.498] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-01-26T03:36:35.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-26 03:36:35 +[2025-01-26T07:17:28.385] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-01-26T07:17:28.397] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-01-26T07:17:28.405] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-01-26T07:17:28.412] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-01-26T16:53:14.706] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-01-26T16:53:14.719] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-01-26T16:53:14.726] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-01-26T16:53:14.732] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-01-27T03:36:36.013] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-27 03:36:36 +[2025-01-27T07:10:59.370] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-01-27T07:10:59.384] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-01-27T07:10:59.391] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-01-27T07:10:59.398] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-01-27T16:56:57.288] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-01-27T16:56:57.301] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-01-27T16:56:57.307] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-01-27T16:56:57.313] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-01-28T03:36:37.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-28 03:36:37 +[2025-01-28T07:19:19.106] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-01-28T07:19:19.119] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-01-28T07:19:19.127] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-01-28T07:19:19.133] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-01-28T16:50:12.891] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-01-28T16:50:12.906] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-01-28T16:50:12.912] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-01-28T16:50:12.919] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-01-29T03:36:38.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-29 03:36:38 +[2025-01-29T07:11:09.482] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-01-29T07:11:09.495] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-01-29T07:11:09.502] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-01-29T07:11:09.508] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-01-29T17:01:01.500] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-01-29T17:01:01.513] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-01-29T17:01:01.520] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-01-29T17:01:01.526] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-01-30T03:36:39.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-30 03:36:39 +[2025-01-30T07:08:28.670] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-01-30T07:08:28.686] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-01-30T07:08:28.695] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-01-30T07:08:28.704] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-01-30T17:02:24.407] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-01-30T17:02:24.421] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-01-30T17:02:24.428] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-01-30T17:02:24.435] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-01-31T03:36:40.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-31 03:36:40 +[2025-01-31T07:07:20.821] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-01-31T07:07:20.836] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-01-31T07:07:20.845] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-01-31T07:07:20.852] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-01-31T08:08:54.336] [INFO] monitorLogs - MQTT client connected +[2025-01-31T17:03:37.264] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-01-31T17:03:37.278] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-01-31T17:03:37.285] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-01-31T17:03:37.291] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-02-01T03:36:41.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-01 03:36:41 +[2025-02-01T07:05:38.383] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-02-01T07:05:38.396] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-02-01T07:05:38.406] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-02-01T07:05:38.413] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-02-01T08:59:33.131] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-02-01T08:59:38.473] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 true turn off on startup +[2025-02-01T08:59:38.488] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 true turn off on startup +[2025-02-01T08:59:38.495] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 true turn off on startup +[2025-02-01T08:59:38.502] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 true turn off on startup +[2025-02-01T08:59:38.591] [INFO] monitorLogs - MQTT client connected +[2025-02-01T08:59:43.518] [INFO] monitorLogs - buildTasks - params undefined +[2025-02-01T08:59:43.519] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-02-01T08:59:43.522] [INFO] monitorLogs - profile: { + 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 +} +[2025-02-01T08:59:43.527] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-02-01T08:59:43.529] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-02-02T06:51:00.528Z +[2025-02-01T08:59:43.530] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-02-01T16:19:00.530Z +[2025-02-01T08:59:43.531] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:51', name: 'luxOff' }, + { value: 1, start_time: '17:19', name: 'luxOn' } +] +[2025-02-01T08:59:43.532] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-02-01T08:59:43.533] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-02-01T08:59:43.534] [INFO] monitorLogs - profile: { + 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 +} +[2025-02-01T08:59:43.536] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-02-01T08:59:43.537] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-02-02T06:51:00.537Z +[2025-02-01T08:59:43.538] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-02-01T16:19:00.538Z +[2025-02-01T08:59:43.538] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:51', name: 'luxOff' }, + { value: 1, start_time: '17:19', name: 'luxOn' } +] +[2025-02-01T08:59:43.539] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-02-01T08:59:43.540] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-02-01T08:59:43.541] [INFO] monitorLogs - profile: { + 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 +} +[2025-02-01T08:59:43.543] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-02-01T08:59:43.544] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-02-02T06:51:00.543Z +[2025-02-01T08:59:43.545] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-02-01T16:19:00.544Z +[2025-02-01T08:59:43.545] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:51', name: 'luxOff' }, + { value: 1, start_time: '17:19', name: 'luxOn' } +] +[2025-02-01T08:59:43.546] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-02-01T08:59:43.547] [INFO] monitorLogs - buildTasks: profile for line 4 +[2025-02-01T08:59:43.547] [INFO] monitorLogs - profile: { + 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 +} +[2025-02-01T08:59:43.550] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-02-01T08:59:43.550] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 4 2025-02-02T06:51:00.550Z +[2025-02-01T08:59:43.551] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 4 2025-02-01T16:19:00.551Z +[2025-02-01T08:59:43.552] [INFO] monitorLogs - -->time_points final 4 [ + { value: 0, start_time: '7:51', name: 'luxOff' }, + { value: 1, start_time: '17:19', name: 'luxOn' } +] +[2025-02-01T08:59:43.553] [INFO] monitorLogs - -->currentValue for relay 4 0 +[2025-02-01T08:59:43.569] [INFO] monitorLogs - tasks created: 2209 +[2025-02-01T08:59:43.573] [INFO] monitorLogs - -->FLOW bol spustený wvKJdZML6mXP4DzWBAXxwBAjxNloa5g23Ve9Y1ry 2025-01-09 +[2025-02-01T09:13:47.167] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-02-01T09:13:52.517] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 true turn off on startup +[2025-02-01T09:13:52.533] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 true turn off on startup +[2025-02-01T09:13:52.539] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 true turn off on startup +[2025-02-01T09:13:52.547] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 true turn off on startup +[2025-02-01T09:13:52.693] [INFO] monitorLogs - MQTT client connected +[2025-02-01T09:13:57.561] [INFO] monitorLogs - buildTasks - params undefined +[2025-02-01T09:13:57.563] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-02-01T09:13:57.564] [INFO] monitorLogs - profile: { + 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 +} +[2025-02-01T09:13:57.568] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-02-01T09:13:57.569] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-02-02T06:51:00.569Z +[2025-02-01T09:13:57.571] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-02-01T16:19:00.571Z +[2025-02-01T09:13:57.571] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:51', name: 'luxOff' }, + { value: 1, start_time: '17:19', name: 'luxOn' } +] +[2025-02-01T09:13:57.573] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-02-01T09:13:57.574] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-02-01T09:13:57.574] [INFO] monitorLogs - profile: { + 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 +} +[2025-02-01T09:13:57.577] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-02-01T09:13:57.577] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-02-02T06:51:00.577Z +[2025-02-01T09:13:57.578] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-02-01T16:19:00.578Z +[2025-02-01T09:13:57.579] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:51', name: 'luxOff' }, + { value: 1, start_time: '17:19', name: 'luxOn' } +] +[2025-02-01T09:13:57.580] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-02-01T09:13:57.580] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-02-01T09:13:57.581] [INFO] monitorLogs - profile: { + 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 +} +[2025-02-01T09:13:57.583] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-02-01T09:13:57.584] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-02-02T06:51:00.584Z +[2025-02-01T09:13:57.585] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-02-01T16:19:00.584Z +[2025-02-01T09:13:57.585] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:51', name: 'luxOff' }, + { value: 1, start_time: '17:19', name: 'luxOn' } +] +[2025-02-01T09:13:57.586] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-02-01T09:13:57.587] [INFO] monitorLogs - buildTasks: profile for line 4 +[2025-02-01T09:13:57.587] [INFO] monitorLogs - profile: { + 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 +} +[2025-02-01T09:13:57.590] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-02-01T09:13:57.590] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 4 2025-02-02T06:51:00.590Z +[2025-02-01T09:13:57.591] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 4 2025-02-01T16:19:00.591Z +[2025-02-01T09:13:57.592] [INFO] monitorLogs - -->time_points final 4 [ + { value: 0, start_time: '7:51', name: 'luxOff' }, + { value: 1, start_time: '17:19', name: 'luxOn' } +] +[2025-02-01T09:13:57.593] [INFO] monitorLogs - -->currentValue for relay 4 0 +[2025-02-01T09:13:57.607] [INFO] monitorLogs - tasks created: 2209 +[2025-02-01T09:13:57.611] [INFO] monitorLogs - -->FLOW bol spustený wvKJdZML6mXP4DzWBAXxwBAjxNloa5g23Ve9Y1ry 2025-01-09 +[2025-02-01T17:05:21.549] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-02-01T17:05:21.574] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-02-01T17:05:21.582] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-02-01T17:05:21.589] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-02-02T03:13:54.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-02 03:13:54 +[2025-02-02T07:11:02.847] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-02-02T07:11:02.859] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-02-02T07:11:02.866] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-02-02T07:11:02.873] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-02-02T17:08:08.347] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-02-02T17:08:08.378] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-02-02T17:08:08.385] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-02-02T17:08:08.393] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-02-03T03:13:55.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-03 03:13:55 +[2025-02-03T07:02:09.650] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-02-03T07:02:09.681] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-02-03T07:02:09.687] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-02-03T07:02:09.694] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-02-03T07:05:06.186] [INFO] monitorLogs - MQTT client connected +[2025-02-03T10:36:34.462] [INFO] monitorLogs - MQTT client connected +[2025-02-03T10:36:56.994] [INFO] monitorLogs - MQTT client connected +[2025-02-03T15:04:46.856] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-02-03T15:04:52.232] [INFO] monitorLogs - buildTasks - params undefined +[2025-02-03T15:04:52.237] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-02-03T15:04:52.238] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-02-03T15:04:52.239] [INFO] monitorLogs - profile: { + 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 +} +[2025-02-03T15:04:52.243] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-02-03T15:04:52.245] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-02-04T06:49:00.244Z +[2025-02-03T15:04:52.246] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-02-03T16:22:00.246Z +[2025-02-03T15:04:52.247] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:49', name: 'luxOff' }, + { value: 1, start_time: '17:22', name: 'luxOn' } +] +[2025-02-03T15:04:52.249] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-02-03T15:04:52.250] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-02-03T15:04:52.250] [INFO] monitorLogs - profile: { + 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 +} +[2025-02-03T15:04:52.253] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-02-03T15:04:52.253] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-02-04T06:49:00.253Z +[2025-02-03T15:04:52.254] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-02-03T16:22:00.254Z +[2025-02-03T15:04:52.255] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:49', name: 'luxOff' }, + { value: 1, start_time: '17:22', name: 'luxOn' } +] +[2025-02-03T15:04:52.256] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-02-03T15:04:52.256] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-02-03T15:04:52.257] [INFO] monitorLogs - profile: { + 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 +} +[2025-02-03T15:04:52.259] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-02-03T15:04:52.260] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-02-04T06:49:00.260Z +[2025-02-03T15:04:52.260] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-02-03T16:22:00.260Z +[2025-02-03T15:04:52.261] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:49', name: 'luxOff' }, + { value: 1, start_time: '17:22', name: 'luxOn' } +] +[2025-02-03T15:04:52.262] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-02-03T15:04:52.262] [INFO] monitorLogs - buildTasks: profile for line 4 +[2025-02-03T15:04:52.263] [INFO] monitorLogs - profile: { + 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 +} +[2025-02-03T15:04:52.265] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-02-03T15:04:52.266] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 4 2025-02-04T06:49:00.266Z +[2025-02-03T15:04:52.266] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 4 2025-02-03T16:22:00.266Z +[2025-02-03T15:04:52.267] [INFO] monitorLogs - -->time_points final 4 [ + { value: 0, start_time: '7:49', name: 'luxOff' }, + { value: 1, start_time: '17:22', name: 'luxOn' } +] +[2025-02-03T15:04:52.268] [INFO] monitorLogs - -->currentValue for relay 4 0 +[2025-02-03T15:04:52.279] [INFO] monitorLogs - tasks created: 2072 +[2025-02-03T15:04:52.282] [INFO] monitorLogs - -->FLOW bol spustený wvKJdZML6mXP4DzWBAXxwBAjxNloa5g23Ve9Y1ry 2025-01-30 +[2025-02-03T15:04:52.372] [INFO] monitorLogs - MQTT client connected +[2025-02-03T15:04:52.599] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-02-03T15:04:52.905] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-02-03T15:04:53.211] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-02-03T15:04:53.517] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false aplikovany bod profilu +[2025-02-03T15:13:07.141] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-02-03T15:13:12.527] [INFO] monitorLogs - buildTasks - params undefined +[2025-02-03T15:13:12.532] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-02-03T15:13:12.533] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-02-03T15:13:12.534] [INFO] monitorLogs - profile: { + 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 +} +[2025-02-03T15:13:12.538] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-02-03T15:13:12.540] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-02-04T06:49:00.539Z +[2025-02-03T15:13:12.542] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-02-03T16:22:00.541Z +[2025-02-03T15:13:12.542] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:49', name: 'luxOff' }, + { value: 1, start_time: '17:22', name: 'luxOn' } +] +[2025-02-03T15:13:12.544] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-02-03T15:13:12.545] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-02-03T15:13:12.545] [INFO] monitorLogs - profile: { + 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 +} +[2025-02-03T15:13:12.548] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-02-03T15:13:12.548] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-02-04T06:49:00.548Z +[2025-02-03T15:13:12.549] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-02-03T16:22:00.549Z +[2025-02-03T15:13:12.550] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:49', name: 'luxOff' }, + { value: 1, start_time: '17:22', name: 'luxOn' } +] +[2025-02-03T15:13:12.551] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-02-03T15:13:12.552] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-02-03T15:13:12.552] [INFO] monitorLogs - profile: { + 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 +} +[2025-02-03T15:13:12.555] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-02-03T15:13:12.555] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-02-04T06:49:00.555Z +[2025-02-03T15:13:12.556] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-02-03T16:22:00.556Z +[2025-02-03T15:13:12.557] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:49', name: 'luxOff' }, + { value: 1, start_time: '17:22', name: 'luxOn' } +] +[2025-02-03T15:13:12.558] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-02-03T15:13:12.558] [INFO] monitorLogs - buildTasks: profile for line 4 +[2025-02-03T15:13:12.559] [INFO] monitorLogs - profile: { + 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 +} +[2025-02-03T15:13:12.561] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-02-03T15:13:12.562] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 4 2025-02-04T06:49:00.562Z +[2025-02-03T15:13:12.563] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 4 2025-02-03T16:22:00.562Z +[2025-02-03T15:13:12.563] [INFO] monitorLogs - -->time_points final 4 [ + { value: 0, start_time: '7:49', name: 'luxOff' }, + { value: 1, start_time: '17:22', name: 'luxOn' } +] +[2025-02-03T15:13:12.564] [INFO] monitorLogs - -->currentValue for relay 4 0 +[2025-02-03T15:13:12.576] [INFO] monitorLogs - tasks created: 2072 +[2025-02-03T15:13:12.579] [INFO] monitorLogs - -->FLOW bol spustený wvKJdZML6mXP4DzWBAXxwBAjxNloa5g23Ve9Y1ry 2025-01-30 +[2025-02-03T15:13:12.663] [INFO] monitorLogs - MQTT client connected +[2025-02-03T15:13:12.896] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-02-03T15:13:13.202] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-02-03T15:13:13.508] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-02-03T15:13:13.814] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false aplikovany bod profilu +[2025-02-03T17:09:33.273] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-02-03T17:09:33.277] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-02-03T17:09:33.279] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-02-03T17:09:33.282] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-02-04T03:13:15.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-04 03:13:15 +[2025-02-04T06:59:23.288] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-02-04T06:59:23.291] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-02-04T06:59:23.293] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-02-04T06:59:23.295] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-02-04T17:11:20.259] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-02-04T17:11:20.261] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-02-04T17:11:20.263] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-02-04T17:11:20.265] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-02-05T03:13:16.072] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-05 03:13:16 +[2025-02-05T06:59:19.692] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-02-05T06:59:19.697] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-02-05T06:59:19.699] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-02-05T06:59:19.701] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-02-05T17:12:35.895] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-02-05T17:12:35.901] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-02-05T17:12:35.903] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-02-05T17:12:35.905] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-02-06T03:13:17.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-06 03:13:17 +[2025-02-06T07:00:36.358] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-02-06T07:00:36.364] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-02-06T07:00:36.366] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-02-06T07:00:36.368] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-02-06T17:11:10.280] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-02-06T17:11:10.299] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-02-06T17:11:10.301] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-02-06T17:11:10.302] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-02-07T03:13:18.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-07 03:13:18 +[2025-02-07T06:58:19.797] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-02-07T06:58:19.802] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-02-07T06:58:19.804] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-02-07T06:58:19.806] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-02-07T08:40:53.803] [INFO] monitorLogs - MQTT client connected +[2025-02-07T08:41:41.085] [INFO] monitorLogs - MQTT client connected +[2025-02-07T08:44:28.883] [INFO] monitorLogs - MQTT client connected +[2025-02-07T08:45:40.051] [INFO] monitorLogs - MQTT client connected +[2025-02-07T17:09:20.513] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-02-07T17:09:20.519] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-02-07T17:09:20.521] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-02-07T17:09:20.523] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-02-08T02:40:39.675] [INFO] monitorLogs - MQTT client connected +[2025-02-08T03:13:19.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-08 03:13:19 +[2025-02-08T06:56:12.492] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-02-08T06:56:12.500] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-02-08T06:56:12.502] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-02-08T06:56:12.504] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-02-08T17:17:03.511] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-02-08T17:17:03.523] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-02-08T17:17:03.525] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-02-08T17:17:03.527] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-02-09T03:13:20.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-09 03:13:20 +[2025-02-09T07:01:31.000] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-02-09T07:01:31.006] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-02-09T07:01:31.009] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-02-09T07:01:31.010] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-02-09T17:10:33.570] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-02-09T17:10:33.577] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-02-09T17:10:33.578] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-02-09T17:10:33.580] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-02-10T03:13:21.016] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-10 03:13:21 +[2025-02-10T06:51:05.190] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-02-10T06:51:05.196] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-02-10T06:51:05.198] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-02-10T06:51:05.200] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-02-10T17:19:10.170] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-02-10T17:19:10.188] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-02-10T17:19:10.190] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-02-10T17:19:10.192] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-02-11T03:13:22.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-11 03:13:22 +[2025-02-11T06:50:31.922] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-02-11T06:50:31.927] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-02-11T06:50:31.929] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-02-11T06:50:31.930] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-02-11T17:20:54.427] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-02-11T17:20:54.438] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-02-11T17:20:54.440] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-02-11T17:20:54.442] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-02-12T03:13:23.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-12 03:13:23 +[2025-02-12T06:59:29.412] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-02-12T06:59:29.417] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-02-12T06:59:29.419] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-02-12T06:59:29.421] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-02-12T17:13:22.435] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-02-12T17:13:22.460] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-02-12T17:13:22.463] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-02-12T17:13:22.465] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-02-13T03:13:24.013] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-13 03:13:24 +[2025-02-13T06:59:13.005] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-02-13T06:59:13.010] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-02-13T06:59:13.012] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-02-13T06:59:13.013] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-02-13T13:18:04.024] [INFO] monitorLogs - MQTT client connected +[2025-02-13T13:18:34.205] [INFO] monitorLogs - MQTT client connected +[2025-02-13T13:19:09.038] [INFO] monitorLogs - MQTT client connected +[2025-02-13T13:19:57.621] [INFO] monitorLogs - MQTT client connected +[2025-02-13T13:21:02.259] [INFO] monitorLogs - MQTT client connected +[2025-02-13T13:24:02.077] [INFO] monitorLogs - MQTT client connected +[2025-02-13T13:28:49.452] [INFO] monitorLogs - MQTT client connected +[2025-02-13T13:32:17.606] [INFO] monitorLogs - MQTT client connected +[2025-02-13T15:22:58.303] [INFO] monitorLogs - MQTT client connected +[2025-02-13T17:15:31.150] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-02-13T17:15:31.153] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-02-13T17:15:31.155] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-02-13T17:15:31.156] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-02-14T03:13:25.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-14 03:13:25 +[2025-02-14T06:45:52.230] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-02-14T06:45:52.236] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-02-14T06:45:52.238] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-02-14T06:45:52.240] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-02-14T17:16:33.565] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-02-14T17:16:33.579] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-02-14T17:16:33.581] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-02-14T17:16:33.583] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-02-15T03:13:27.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-15 03:13:27 +[2025-02-15T06:47:07.257] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-02-15T06:47:07.262] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-02-15T06:47:07.264] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-02-15T06:47:07.266] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-02-15T17:22:35.227] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-02-15T17:22:35.246] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-02-15T17:22:35.248] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-02-15T17:22:35.250] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-02-16T03:13:28.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-16 03:13:28 +[2025-02-16T06:42:38.939] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-02-16T06:42:38.945] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-02-16T06:42:38.947] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-02-16T06:42:38.949] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-02-16T17:28:18.733] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-02-16T17:28:18.745] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-02-16T17:28:18.747] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-02-16T17:28:18.749] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-02-17T03:13:29.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-17 03:13:29 +[2025-02-17T06:42:02.910] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-02-17T06:42:02.915] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-02-17T06:42:02.990] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-02-17T06:42:02.992] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-02-17T07:03:55.767] [INFO] monitorLogs - MQTT client connected +[2025-02-17T08:02:40.953] [INFO] monitorLogs - MQTT client connected +[2025-02-17T08:03:58.523] [INFO] monitorLogs - MQTT client connected +[2025-02-17T08:04:20.047] [INFO] monitorLogs - MQTT client connected +[2025-02-17T08:44:44.636] [INFO] monitorLogs - MQTT client connected +[2025-02-17T17:20:42.691] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-02-17T17:20:42.694] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-02-17T17:20:42.696] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-02-17T17:20:42.698] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-02-18T03:13:30.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-18 03:13:30 +[2025-02-18T06:45:21.346] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-02-18T06:45:21.352] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-02-18T06:45:21.354] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-02-18T06:45:21.356] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-02-18T06:54:35.369] [INFO] monitorLogs - MQTT client connected +[2025-02-18T13:03:28.105] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-02-18T13:03:33.498] [INFO] monitorLogs - buildTasks - params undefined +[2025-02-18T13:03:33.503] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-02-18T13:03:33.505] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-02-18T13:03:33.505] [INFO] monitorLogs - profile: { + 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 +} +[2025-02-18T13:03:33.510] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-02-18T13:03:33.511] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-02-19T06:25:00.510Z +[2025-02-18T13:03:33.512] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-02-18T16:47:00.512Z +[2025-02-18T13:03:33.513] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:25', name: 'luxOff' }, + { value: 1, start_time: '17:47', name: 'luxOn' } +] +[2025-02-18T13:03:33.514] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-02-18T13:03:33.515] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-02-18T13:03:33.516] [INFO] monitorLogs - profile: { + 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 +} +[2025-02-18T13:03:33.518] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-02-18T13:03:33.519] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-02-19T06:25:00.519Z +[2025-02-18T13:03:33.520] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-02-18T16:47:00.520Z +[2025-02-18T13:03:33.521] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:25', name: 'luxOff' }, + { value: 1, start_time: '17:47', name: 'luxOn' } +] +[2025-02-18T13:03:33.522] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-02-18T13:03:33.522] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-02-18T13:03:33.523] [INFO] monitorLogs - profile: { + 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 +} +[2025-02-18T13:03:33.525] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-02-18T13:03:33.526] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-02-19T06:25:00.526Z +[2025-02-18T13:03:33.527] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-02-18T16:47:00.527Z +[2025-02-18T13:03:33.528] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:25', name: 'luxOff' }, + { value: 1, start_time: '17:47', name: 'luxOn' } +] +[2025-02-18T13:03:33.529] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-02-18T13:03:33.529] [INFO] monitorLogs - buildTasks: profile for line 4 +[2025-02-18T13:03:33.530] [INFO] monitorLogs - profile: { + 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 +} +[2025-02-18T13:03:33.532] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-02-18T13:03:33.533] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 4 2025-02-19T06:25:00.533Z +[2025-02-18T13:03:33.533] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 4 2025-02-18T16:47:00.533Z +[2025-02-18T13:03:33.534] [INFO] monitorLogs - -->time_points final 4 [ + { value: 0, start_time: '7:25', name: 'luxOff' }, + { value: 1, start_time: '17:47', name: 'luxOn' } +] +[2025-02-18T13:03:33.535] [INFO] monitorLogs - -->currentValue for relay 4 0 +[2025-02-18T13:03:33.547] [INFO] monitorLogs - tasks created: 2042 +[2025-02-18T13:03:33.550] [INFO] monitorLogs - -->FLOW bol spustený wvKJdZML6mXP4DzWBAXxwBAjxNloa5g23Ve9Y1ry 2025-01-30 +[2025-02-18T13:03:33.631] [INFO] monitorLogs - MQTT client connected +[2025-02-18T13:03:33.866] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-02-18T13:03:34.172] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-02-18T13:03:34.478] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-02-18T13:03:34.784] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false aplikovany bod profilu +[2025-02-18T17:34:08.684] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-02-18T17:34:08.688] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-02-18T17:34:08.690] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-02-18T17:34:08.692] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-02-19T03:03:35.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-19 03:03:35 +[2025-02-19T06:34:37.683] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-02-19T06:34:37.688] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-02-19T06:34:37.690] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-02-19T06:34:37.691] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-02-19T14:18:29.181] [INFO] monitorLogs - MQTT client connected +[2025-02-19T15:06:37.590] [INFO] monitorLogs - MQTT client connected +[2025-02-19T15:09:58.141] [INFO] monitorLogs - MQTT client connected +[2025-02-19T15:12:57.114] [INFO] monitorLogs - MQTT client connected +[2025-02-19T17:34:03.686] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-02-19T17:34:03.688] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-02-19T17:34:03.690] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-02-19T17:34:03.692] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-02-20T03:03:36.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-20 03:03:36 +[2025-02-20T06:33:03.161] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-02-20T06:33:03.164] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-02-20T06:33:03.166] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-02-20T06:33:03.168] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-02-20T09:20:00.347] [INFO] monitorLogs - MQTT client connected +[2025-02-20T17:35:17.232] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-02-20T17:35:17.255] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-02-20T17:35:17.257] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-02-20T17:35:17.258] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-02-21T03:03:38.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-21 03:03:38 +[2025-02-21T06:32:18.657] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-02-21T06:32:18.662] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-02-21T06:32:18.664] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-02-21T06:32:18.666] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-02-21T06:56:29.429] [INFO] monitorLogs - MQTT client connected +[2025-02-21T17:35:58.323] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-02-21T17:35:58.345] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-02-21T17:35:58.348] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-02-21T17:35:58.350] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-02-22T03:03:39.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-22 03:03:39 +[2025-02-22T06:30:50.812] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-02-22T06:30:50.818] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-02-22T06:30:50.819] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-02-22T06:30:50.821] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-02-22T17:39:07.045] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-02-22T17:39:07.056] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-02-22T17:39:07.057] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-02-22T17:39:07.059] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-02-23T03:03:40.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-23 03:03:40 +[2025-02-23T06:29:01.924] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-02-23T06:29:01.927] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-02-23T06:29:01.929] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-02-23T06:29:01.930] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-02-23T17:30:55.595] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-02-23T17:30:55.625] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-02-23T17:30:55.628] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-02-23T17:30:55.629] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-02-24T03:03:41.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-24 03:03:41 +[2025-02-24T06:28:49.601] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-02-24T06:28:49.606] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-02-24T06:28:49.609] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-02-24T06:28:49.611] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-02-24T14:02:51.017] [INFO] monitorLogs - MQTT client connected +[2025-02-24T14:15:01.000] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false command received from platform +[2025-02-24T14:16:03.715] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false command received from platform +[2025-02-24T14:16:56.506] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false command received from platform +[2025-02-24T14:20:32.390] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false command received from platform +[2025-02-24T14:21:23.392] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false command received from platform +[2025-02-24T14:21:29.594] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false command received from platform +[2025-02-24T14:21:35.542] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false command received from platform +[2025-02-24T14:21:43.870] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false command received from platform +[2025-02-24T17:41:50.929] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-02-24T17:41:50.931] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-02-24T17:41:50.933] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-02-24T17:41:50.935] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-02-25T03:03:42.017] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-25 03:03:42 +[2025-02-25T06:27:06.721] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-02-25T06:27:06.726] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-02-25T06:27:06.728] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-02-25T06:27:06.730] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-02-25T06:50:58.915] [INFO] monitorLogs - MQTT client connected +[2025-02-25T06:51:32.126] [INFO] monitorLogs - MQTT client connected +[2025-02-25T06:53:25.917] [INFO] monitorLogs - MQTT client connected +[2025-02-25T06:53:39.483] [INFO] monitorLogs - MQTT client connected +[2025-02-25T06:55:03.883] [INFO] monitorLogs - MQTT client connected +[2025-02-25T06:56:16.384] [INFO] monitorLogs - MQTT client connected +[2025-02-25T06:56:40.990] [INFO] monitorLogs - MQTT client connected +[2025-02-25T07:10:48.844] [INFO] monitorLogs - MQTT client connected +[2025-02-25T07:11:35.953] [INFO] monitorLogs - MQTT client connected +[2025-02-25T07:12:11.979] [INFO] monitorLogs - MQTT client connected +[2025-02-25T07:13:27.552] [INFO] monitorLogs - MQTT client connected +[2025-02-25T07:14:25.674] [INFO] monitorLogs - MQTT client connected +[2025-02-25T07:15:28.265] [INFO] monitorLogs - MQTT client connected +[2025-02-25T07:16:14.950] [INFO] monitorLogs - MQTT client connected +[2025-02-25T07:17:00.749] [INFO] monitorLogs - MQTT client connected +[2025-02-25T07:17:28.910] [INFO] monitorLogs - MQTT client connected +[2025-02-25T07:18:14.849] [INFO] monitorLogs - MQTT client connected +[2025-02-25T12:36:39.151] [INFO] monitorLogs - MQTT client connected +[2025-02-25T12:37:23.341] [INFO] monitorLogs - MQTT client connected +[2025-02-25T12:38:08.042] [INFO] monitorLogs - MQTT client connected +[2025-02-25T12:39:13.655] [INFO] monitorLogs - MQTT client connected +[2025-02-25T14:05:57.454] [INFO] monitorLogs - MQTT client connected +[2025-02-25T14:07:20.807] [INFO] monitorLogs - MQTT client connected +[2025-02-25T14:08:26.087] [INFO] monitorLogs - MQTT client connected +[2025-02-25T14:09:30.085] [INFO] monitorLogs - MQTT client connected +[2025-02-25T14:09:43.671] [INFO] monitorLogs - MQTT client connected +[2025-02-25T14:11:56.535] [INFO] monitorLogs - MQTT client connected +[2025-02-25T14:12:55.279] [INFO] monitorLogs - MQTT client connected +[2025-02-25T14:13:17.563] [INFO] monitorLogs - MQTT client connected +[2025-02-25T14:20:57.365] [INFO] monitorLogs - MQTT client connected +[2025-02-25T17:39:50.796] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-02-25T17:39:50.798] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-02-25T17:39:50.800] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-02-25T17:39:50.801] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-02-26T03:03:43.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-26 03:03:43 +[2025-02-26T06:38:53.295] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-02-26T06:38:53.301] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-02-26T06:38:53.303] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-02-26T06:38:53.304] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-02-26T17:36:35.372] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-02-26T17:36:35.384] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-02-26T17:36:35.386] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-02-26T17:36:35.388] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-02-27T03:03:44.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-27 03:03:44 +[2025-02-27T06:31:17.266] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-02-27T06:31:17.269] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-02-27T06:31:17.271] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-02-27T06:31:17.273] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-02-27T17:37:49.039] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-02-27T17:37:49.066] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-02-27T17:37:49.068] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-02-27T17:37:49.069] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-02-28T03:03:45.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-28 03:03:45 +[2025-02-28T06:21:46.328] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-02-28T06:21:46.334] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-02-28T06:21:46.336] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-02-28T06:21:46.337] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-02-28T12:20:27.277] [INFO] monitorLogs - MQTT client connected +[2025-02-28T12:26:52.601] [INFO] monitorLogs - MQTT client connected +[2025-02-28T17:47:30.122] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-02-28T17:47:30.143] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-02-28T17:47:30.145] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-02-28T17:47:30.146] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-03-01T03:03:46.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-01 03:03:46 +[2025-03-01T06:20:48.903] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-03-01T06:20:48.908] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-03-01T06:20:48.910] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-03-01T06:20:48.912] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-03-01T17:49:13.513] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-03-01T17:49:13.520] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-03-01T17:49:13.522] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-03-01T17:49:13.523] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-03-02T03:03:47.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-02 03:03:47 +[2025-03-02T06:18:02.709] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-03-02T06:18:02.715] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-03-02T06:18:02.718] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-03-02T06:18:02.719] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-03-02T17:53:48.296] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-03-02T17:53:48.298] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-03-02T17:53:48.300] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-03-02T17:53:48.302] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-03-03T03:03:48.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-03 03:03:48 +[2025-03-03T06:13:22.055] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-03-03T06:13:22.061] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-03-03T06:13:22.063] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-03-03T06:13:22.065] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-03-03T06:48:32.839] [INFO] monitorLogs - MQTT client connected +[2025-03-03T17:54:58.660] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-03-03T17:54:58.675] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-03-03T17:54:58.677] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-03-03T17:54:58.679] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-03-04T03:03:49.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-04 03:03:49 +[2025-03-04T06:11:57.720] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-03-04T06:11:57.723] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-03-04T06:11:57.725] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-03-04T06:11:57.727] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-03-04T07:05:19.797] [INFO] monitorLogs - MQTT client connected +[2025-03-04T07:09:39.591] [INFO] monitorLogs - MQTT client connected +[2025-03-04T07:12:19.256] [INFO] monitorLogs - MQTT client connected +[2025-03-04T07:13:32.591] [INFO] monitorLogs - MQTT client connected +[2025-03-04T07:14:47.511] [INFO] monitorLogs - MQTT client connected +[2025-03-04T07:15:41.133] [INFO] monitorLogs - MQTT client connected +[2025-03-04T07:16:19.995] [INFO] monitorLogs - MQTT client connected +[2025-03-04T07:17:00.468] [INFO] monitorLogs - MQTT client connected +[2025-03-04T07:21:48.584] [INFO] monitorLogs - MQTT client connected +[2025-03-04T07:25:31.047] [INFO] monitorLogs - MQTT client connected +[2025-03-04T17:55:56.922] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-03-04T17:55:56.934] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-03-04T17:55:56.936] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-03-04T17:55:56.937] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-03-05T03:03:50.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-05 03:03:50 +[2025-03-05T06:10:40.860] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-03-05T06:10:40.863] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-03-05T06:10:40.865] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-03-05T06:10:40.866] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-03-05T17:56:36.586] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-03-05T17:56:36.593] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-03-05T17:56:36.595] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-03-05T17:56:36.596] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-03-06T03:03:52.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-06 03:03:52 +[2025-03-06T06:07:39.074] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-03-06T06:07:39.077] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-03-06T06:07:39.079] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-03-06T06:07:39.081] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-03-06T17:57:19.714] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-03-06T17:57:19.716] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-03-06T17:57:19.718] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-03-06T17:57:19.719] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-03-07T03:03:53.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-07 03:03:53 +[2025-03-07T06:07:25.294] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-03-07T06:07:25.297] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-03-07T06:07:25.299] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-03-07T06:07:25.301] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-03-07T18:00:00.232] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-03-07T18:00:00.241] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-03-07T18:00:00.243] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-03-07T18:00:00.245] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-03-08T03:03:54.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-08 03:03:54 +[2025-03-08T06:02:52.692] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-03-08T06:02:52.696] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-03-08T06:02:52.698] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-03-08T06:02:52.700] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-03-08T18:00:37.394] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-03-08T18:00:37.415] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-03-08T18:00:37.417] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-03-08T18:00:37.420] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-03-09T03:03:55.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-09 03:03:55 +[2025-03-09T06:04:26.449] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-03-09T06:04:26.452] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-03-09T06:04:26.454] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-03-09T06:04:26.456] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-03-09T18:01:17.034] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-03-09T18:01:17.045] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-03-09T18:01:17.046] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-03-09T18:01:17.048] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-03-10T03:03:57.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-10 03:03:57 +[2025-03-10T06:04:00.352] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-03-10T06:04:00.355] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-03-10T06:04:00.357] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-03-10T06:04:00.360] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-03-10T06:44:26.581] [INFO] monitorLogs - MQTT client connected +[2025-03-10T17:43:12.015] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-03-10T17:43:12.028] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-03-10T17:43:12.029] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-03-10T17:43:12.031] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-03-10T20:31:54.079] [INFO] monitorLogs - MQTT client connected +[2025-03-11T03:03:58.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-11 03:03:58 +[2025-03-11T05:59:26.038] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-03-11T05:59:26.043] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-03-11T05:59:26.045] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-03-11T05:59:26.046] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-03-11T08:18:58.438] [INFO] monitorLogs - MQTT client connected +[2025-03-11T08:20:33.731] [INFO] monitorLogs - MQTT client connected +[2025-03-11T08:21:18.851] [INFO] monitorLogs - MQTT client connected +[2025-03-11T08:23:17.186] [INFO] monitorLogs - MQTT client connected +[2025-03-11T08:24:02.689] [INFO] monitorLogs - MQTT client connected +[2025-03-11T08:24:56.429] [INFO] monitorLogs - MQTT client connected +[2025-03-11T17:58:28.015] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-03-11T17:58:28.028] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-03-11T17:58:28.029] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-03-11T17:58:28.031] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-03-12T03:03:59.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-12 03:03:59 +[2025-03-12T05:58:33.527] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-03-12T05:58:33.530] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-03-12T05:58:33.533] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-03-12T05:58:33.535] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-03-12T16:00:56.055] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-03-12T16:01:01.430] [INFO] monitorLogs - buildTasks - params undefined +[2025-03-12T16:01:01.435] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-03-12T16:01:01.436] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-03-12T16:01:01.437] [INFO] monitorLogs - profile: { + 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 +} +[2025-03-12T16:01:01.441] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-03-12T16:01:01.442] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-03-13T05:41:00.441Z +[2025-03-12T16:01:01.444] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-03-12T17:22:00.444Z +[2025-03-12T16:01:01.445] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '6:41', name: 'luxOff' }, + { value: 1, start_time: '18:22', name: 'luxOn' } +] +[2025-03-12T16:01:01.446] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-03-12T16:01:01.447] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-03-12T16:01:01.448] [INFO] monitorLogs - profile: { + 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 +} +[2025-03-12T16:01:01.450] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-03-12T16:01:01.451] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-03-13T05:41:00.451Z +[2025-03-12T16:01:01.452] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-03-12T17:22:00.452Z +[2025-03-12T16:01:01.452] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '6:41', name: 'luxOff' }, + { value: 1, start_time: '18:22', name: 'luxOn' } +] +[2025-03-12T16:01:01.453] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-03-12T16:01:01.454] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-03-12T16:01:01.455] [INFO] monitorLogs - profile: { + 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 +} +[2025-03-12T16:01:01.457] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-03-12T16:01:01.458] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-03-13T05:41:00.457Z +[2025-03-12T16:01:01.458] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-03-12T17:22:00.458Z +[2025-03-12T16:01:01.459] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '6:41', name: 'luxOff' }, + { value: 1, start_time: '18:22', name: 'luxOn' } +] +[2025-03-12T16:01:01.460] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-03-12T16:01:01.461] [INFO] monitorLogs - buildTasks: profile for line 4 +[2025-03-12T16:01:01.461] [INFO] monitorLogs - profile: { + 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 +} +[2025-03-12T16:01:01.464] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-03-12T16:01:01.464] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 4 2025-03-13T05:41:00.464Z +[2025-03-12T16:01:01.465] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 4 2025-03-12T17:22:00.465Z +[2025-03-12T16:01:01.466] [INFO] monitorLogs - -->time_points final 4 [ + { value: 0, start_time: '6:41', name: 'luxOff' }, + { value: 1, start_time: '18:22', name: 'luxOn' } +] +[2025-03-12T16:01:01.467] [INFO] monitorLogs - -->currentValue for relay 4 0 +[2025-03-12T16:01:01.478] [INFO] monitorLogs - tasks created: 2042 +[2025-03-12T16:01:01.481] [INFO] monitorLogs - -->FLOW bol spustený wvKJdZML6mXP4DzWBAXxwBAjxNloa5g23Ve9Y1ry 2025-01-30 +[2025-03-12T16:01:01.561] [INFO] monitorLogs - MQTT client connected +[2025-03-12T16:01:01.798] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-03-12T16:01:02.103] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-03-12T16:01:02.408] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-03-12T16:01:02.714] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false aplikovany bod profilu +[2025-03-12T18:06:20.400] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-03-12T18:06:20.402] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-03-12T18:06:20.405] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-03-12T18:06:20.408] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-03-13T03:01:03.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-13 03:01:03 +[2025-03-13T06:10:19.097] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-03-13T06:10:19.105] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-03-13T06:10:19.107] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-03-13T06:10:19.109] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-03-13T09:49:08.053] [INFO] monitorLogs - MQTT client connected +[2025-03-13T09:50:20.691] [INFO] monitorLogs - MQTT client connected +[2025-03-13T09:50:42.218] [INFO] monitorLogs - MQTT client connected +[2025-03-13T10:13:24.940] [INFO] monitorLogs - MQTT client connected +[2025-03-13T18:06:32.908] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-03-13T18:06:32.925] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-03-13T18:06:32.927] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-03-13T18:06:32.929] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-03-14T03:01:04.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-14 03:01:04 +[2025-03-14T06:03:38.156] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-03-14T06:03:38.164] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-03-14T06:03:38.167] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-03-14T06:03:38.169] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-03-14T18:00:47.588] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-03-14T18:00:47.591] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-03-14T18:00:47.593] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-03-14T18:00:47.595] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-03-15T03:01:05.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-15 03:01:05 +[2025-03-15T06:05:58.853] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-03-15T06:05:58.860] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-03-15T06:05:58.863] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-03-15T06:05:58.865] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-03-15T18:08:29.055] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-03-15T18:08:29.058] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-03-15T18:08:29.059] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-03-15T18:08:29.061] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-03-16T03:01:06.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-16 03:01:06 +[2025-03-16T05:51:29.672] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-03-16T05:51:29.680] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-03-16T05:51:29.682] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-03-16T05:51:29.684] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-03-16T18:15:17.534] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-03-16T18:15:17.536] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-03-16T18:15:17.538] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-03-16T18:15:17.540] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-03-17T03:01:07.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-17 03:01:07 +[2025-03-17T05:54:46.141] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-03-17T05:54:46.145] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-03-17T05:54:46.147] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-03-17T05:54:46.150] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-03-17T07:06:15.821] [INFO] monitorLogs - MQTT client connected +[2025-03-17T18:14:47.547] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-03-17T18:14:47.551] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-03-17T18:14:47.554] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-03-17T18:14:47.556] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-03-18T03:01:08.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-18 03:01:08 +[2025-03-18T05:42:49.036] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-03-18T05:42:49.045] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-03-18T05:42:49.047] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-03-18T05:42:49.049] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-03-18T18:19:04.220] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-03-18T18:19:04.230] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-03-18T18:19:04.233] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-03-18T18:19:04.235] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-03-19T03:01:09.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-19 03:01:09 +[2025-03-19T05:38:34.081] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-03-19T05:38:34.088] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-03-19T05:38:34.090] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-03-19T05:38:34.092] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-03-19T18:19:04.847] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-03-19T18:19:04.850] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-03-19T18:19:04.852] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-03-19T18:19:04.853] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-03-20T03:01:10.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-20 03:01:10 +[2025-03-20T05:37:17.292] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-03-20T05:37:17.299] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-03-20T05:37:17.301] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-03-20T05:37:17.303] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-03-20T18:19:59.629] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-03-20T18:19:59.638] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-03-20T18:19:59.640] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-03-20T18:19:59.642] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-03-21T03:01:11.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-21 03:01:11 +[2025-03-21T05:34:39.313] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-03-21T05:34:39.322] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-03-21T05:34:39.324] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-03-21T05:34:39.326] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-03-21T18:19:53.048] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-03-21T18:19:53.054] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-03-21T18:19:53.056] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-03-21T18:19:53.058] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-03-22T03:01:13.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-22 03:01:13 +[2025-03-22T05:33:43.386] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-03-22T05:33:43.389] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-03-22T05:33:43.392] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-03-22T05:33:43.394] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-03-22T18:15:04.712] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-03-22T18:15:04.714] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-03-22T18:15:04.716] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-03-22T18:15:04.717] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-03-23T03:01:14.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-23 03:01:14 +[2025-03-23T05:40:46.834] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-03-23T05:40:46.844] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-03-23T05:40:46.846] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-03-23T05:40:46.848] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-03-23T18:23:34.067] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-03-23T18:23:34.078] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-03-23T18:23:34.080] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-03-23T18:23:34.082] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-03-24T03:01:15.013] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-24 03:01:15 +[2025-03-24T05:35:06.286] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-03-24T05:35:06.295] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-03-24T05:35:06.297] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-03-24T05:35:06.299] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-03-24T08:09:11.213] [INFO] monitorLogs - MQTT client connected +[2025-03-24T09:35:01.042] [INFO] monitorLogs - MQTT client connected +[2025-03-24T12:24:26.590] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-03-24T12:24:31.970] [INFO] monitorLogs - buildTasks - params undefined +[2025-03-24T12:24:31.975] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-03-24T12:24:31.976] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-03-24T12:24:31.977] [INFO] monitorLogs - profile: { + 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 +} +[2025-03-24T12:24:31.981] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-03-24T12:24:31.983] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-03-25T05:16:00.982Z +[2025-03-24T12:24:31.984] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-03-24T17:40:00.984Z +[2025-03-24T12:24:31.985] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '6:16', name: 'luxOff' }, + { value: 1, start_time: '18:40', name: 'luxOn' } +] +[2025-03-24T12:24:31.986] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-03-24T12:24:31.987] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-03-24T12:24:31.987] [INFO] monitorLogs - profile: { + 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 +} +[2025-03-24T12:24:31.990] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-03-24T12:24:31.990] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-03-25T05:16:00.990Z +[2025-03-24T12:24:31.991] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-03-24T17:40:00.991Z +[2025-03-24T12:24:31.992] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '6:16', name: 'luxOff' }, + { value: 1, start_time: '18:40', name: 'luxOn' } +] +[2025-03-24T12:24:31.993] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-03-24T12:24:31.994] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-03-24T12:24:31.994] [INFO] monitorLogs - profile: { + 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 +} +[2025-03-24T12:24:31.996] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-03-24T12:24:31.997] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-03-25T05:16:00.997Z +[2025-03-24T12:24:31.998] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-03-24T17:40:00.998Z +[2025-03-24T12:24:31.998] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '6:16', name: 'luxOff' }, + { value: 1, start_time: '18:40', name: 'luxOn' } +] +[2025-03-24T12:24:31.999] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-03-24T12:24:32.000] [INFO] monitorLogs - buildTasks: profile for line 4 +[2025-03-24T12:24:32.001] [INFO] monitorLogs - profile: { + 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 +} +[2025-03-24T12:24:32.003] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-03-24T12:24:32.004] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 4 2025-03-25T05:16:00.003Z +[2025-03-24T12:24:32.004] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 4 2025-03-24T17:40:00.004Z +[2025-03-24T12:24:32.005] [INFO] monitorLogs - -->time_points final 4 [ + { value: 0, start_time: '6:16', name: 'luxOff' }, + { value: 1, start_time: '18:40', name: 'luxOn' } +] +[2025-03-24T12:24:32.006] [INFO] monitorLogs - -->currentValue for relay 4 0 +[2025-03-24T12:24:32.018] [INFO] monitorLogs - tasks created: 2042 +[2025-03-24T12:24:32.020] [INFO] monitorLogs - -->FLOW bol spustený wvKJdZML6mXP4DzWBAXxwBAjxNloa5g23Ve9Y1ry 2025-01-30 +[2025-03-24T12:24:32.142] [INFO] monitorLogs - MQTT client connected +[2025-03-24T12:24:32.337] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-03-24T12:24:32.643] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-03-24T12:24:32.949] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-03-24T12:24:33.255] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false aplikovany bod profilu +[2025-03-24T18:23:08.374] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-03-24T18:23:08.377] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-03-24T18:23:08.380] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-03-24T18:23:08.382] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-03-25T03:24:34.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-25 03:24:34 +[2025-03-25T05:33:53.957] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-03-25T05:33:53.960] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-03-25T05:33:53.963] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-03-25T05:33:53.965] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-03-25T18:27:37.207] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-03-25T18:27:37.218] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-03-25T18:27:37.221] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-03-25T18:27:37.223] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-03-26T03:24:35.030] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-26 03:24:35 +[2025-03-26T05:26:50.409] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-03-26T05:26:50.413] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-03-26T05:26:50.415] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-03-26T05:26:50.417] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-03-26T18:27:29.612] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-03-26T18:27:29.615] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-03-26T18:27:29.617] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-03-26T18:27:29.618] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-03-27T03:24:36.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-27 03:24:36 +[2025-03-27T05:26:09.964] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-03-27T05:26:09.972] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-03-27T05:26:09.974] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-03-27T05:26:09.976] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-03-27T18:31:39.285] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-03-27T18:31:39.288] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-03-27T18:31:39.290] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-03-27T18:31:39.291] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-03-28T03:24:37.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-28 03:24:37 +[2025-03-28T05:22:37.785] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-03-28T05:22:37.789] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-03-28T05:22:37.794] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-03-28T05:22:37.795] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-03-28T07:34:55.527] [INFO] monitorLogs - MQTT client connected +[2025-03-28T07:35:37.986] [INFO] monitorLogs - MQTT client connected +[2025-03-28T07:37:46.428] [INFO] monitorLogs - MQTT client connected +[2025-03-28T07:38:19.847] [INFO] monitorLogs - MQTT client connected +[2025-03-28T18:19:43.819] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-03-28T18:19:43.846] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-03-28T18:19:43.849] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-03-28T18:19:43.851] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-03-28T18:30:10.300] [INFO] monitorLogs - MQTT client connected +[2025-03-29T03:24:38.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-29 03:24:38 +[2025-03-29T05:33:03.104] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-03-29T05:33:03.108] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-03-29T05:33:03.110] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-03-29T05:33:03.112] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-03-29T18:14:55.382] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-03-29T18:14:55.385] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-03-29T18:14:55.387] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-03-29T18:14:55.389] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-03-30T03:24:39.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-30 03:24:39 +[2025-03-30T06:30:06.669] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-03-30T06:30:06.678] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-03-30T06:30:06.680] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-03-30T06:30:06.682] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-03-30T19:22:28.180] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-03-30T19:22:28.182] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-03-30T19:22:28.184] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-03-30T19:22:28.186] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-03-31T03:24:41.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-31 03:24:41 +[2025-03-31T06:16:09.087] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-03-31T06:16:09.096] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-03-31T06:16:09.098] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-03-31T06:16:09.100] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-03-31T06:50:30.486] [INFO] monitorLogs - MQTT client connected +[2025-03-31T19:35:58.538] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-03-31T19:35:58.553] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-03-31T19:35:58.555] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-03-31T19:35:58.557] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-04-01T03:24:42.017] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-01 03:24:42 +[2025-04-01T06:19:07.283] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-04-01T06:19:07.287] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-04-01T06:19:07.289] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-04-01T06:19:07.290] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-04-01T07:40:39.558] [INFO] monitorLogs - MQTT client connected +[2025-04-01T19:35:16.973] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-04-01T19:35:16.983] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-04-01T19:35:16.985] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-04-01T19:35:16.987] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-04-02T02:17:53.172] [INFO] monitorLogs - MQTT client connected +[2025-04-02T03:23:56.846] [INFO] monitorLogs - MQTT client connected +[2025-04-02T03:24:43.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-02 03:24:43 +[2025-04-02T06:13:43.026] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-04-02T06:13:43.043] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-04-02T06:13:43.046] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-04-02T06:13:43.048] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-04-02T19:37:37.823] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-04-02T19:37:37.827] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-04-02T19:37:37.829] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-04-02T19:37:37.830] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-04-03T03:24:44.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-03 03:24:44 +[2025-04-03T06:07:00.185] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-04-03T06:07:00.193] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-04-03T06:07:00.195] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-04-03T06:07:00.197] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-04-03T19:40:33.420] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-04-03T19:40:33.456] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-04-03T19:40:33.458] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-04-03T19:40:33.460] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-04-04T03:24:45.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-04 03:24:45 +[2025-04-04T06:04:15.024] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-04-04T06:04:15.028] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-04-04T06:04:15.030] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-04-04T06:04:15.032] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-04-04T19:42:25.328] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-04-04T19:42:25.343] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-04-04T19:42:25.345] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-04-04T19:42:25.346] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-04-05T03:24:46.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-05 03:24:46 +[2025-04-05T06:05:22.634] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-04-05T06:05:22.641] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-04-05T06:05:22.643] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-04-05T06:05:22.645] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-04-05T19:43:02.314] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-04-05T19:43:02.322] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-04-05T19:43:02.325] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-04-05T19:43:02.327] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-04-06T03:24:47.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-06 03:24:47 +[2025-04-06T06:03:08.650] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-04-06T06:03:08.654] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-04-06T06:03:08.656] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-04-06T06:03:08.658] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-04-06T19:43:11.726] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-04-06T19:43:11.785] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-04-06T19:43:11.787] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-04-06T19:43:11.789] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-04-07T03:24:48.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-07 03:24:48 +[2025-04-07T06:11:39.808] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-04-07T06:11:39.811] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-04-07T06:11:39.814] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-04-07T06:11:39.816] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-04-07T08:32:42.621] [INFO] monitorLogs - MQTT client connected +[2025-04-07T19:32:12.345] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-04-07T19:32:12.350] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-04-07T19:32:12.352] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-04-07T19:32:12.354] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-04-08T03:24:49.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-08 03:24:49 +[2025-04-08T06:12:06.984] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-04-08T06:12:06.993] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-04-08T06:12:06.995] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-04-08T06:12:06.997] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-04-08T19:48:22.827] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-04-08T19:48:22.835] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-04-08T19:48:22.837] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-04-08T19:48:22.839] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-04-09T03:24:50.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-09 03:24:50 +[2025-04-09T05:55:29.114] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-04-09T05:55:29.118] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-04-09T05:55:29.120] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-04-09T05:55:29.122] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-04-09T19:48:31.190] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-04-09T19:48:31.196] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-04-09T19:48:31.198] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-04-09T19:48:31.200] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-04-10T03:24:52.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-10 03:24:52 +[2025-04-10T06:02:52.251] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-04-10T06:02:52.255] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-04-10T06:02:52.257] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-04-10T06:02:52.259] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-04-10T07:09:26.550] [INFO] monitorLogs - MQTT client connected +[2025-04-10T12:19:17.920] [INFO] monitorLogs - MQTT client connected +[2025-04-10T19:48:52.281] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-04-10T19:48:52.292] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-04-10T19:48:52.294] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-04-10T19:48:52.295] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-04-11T00:29:17.296] [INFO] monitorLogs - MQTT client connected +[2025-04-11T03:24:53.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-11 03:24:53 +[2025-04-11T05:53:41.329] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-04-11T05:53:41.337] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-04-11T05:53:41.339] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-04-11T05:53:41.341] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-04-11T19:48:14.507] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-04-11T19:48:14.509] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-04-11T19:48:14.511] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-04-11T19:48:14.513] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-04-12T03:24:54.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-12 03:24:54 +[2025-04-12T05:55:17.843] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-04-12T05:55:17.851] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-04-12T05:55:17.853] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-04-12T05:55:17.855] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-04-12T19:55:32.964] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-04-12T19:55:32.981] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-04-12T19:55:32.983] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-04-12T19:55:32.986] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-04-13T03:24:55.014] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-13 03:24:55 +[2025-04-13T05:46:31.976] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-04-13T05:46:31.980] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-04-13T05:46:31.982] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-04-13T05:46:31.984] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-04-13T19:48:28.692] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-04-13T19:48:28.706] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-04-13T19:48:28.708] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-04-13T19:48:28.710] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-04-14T03:24:56.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-14 03:24:56 +[2025-04-14T05:47:35.362] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-04-14T05:47:35.366] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-04-14T05:47:35.368] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-04-14T05:47:35.369] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-04-14T16:19:21.413] [INFO] monitorLogs - MQTT client connected +[2025-04-14T19:53:26.600] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-04-14T19:53:26.602] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-04-14T19:53:26.604] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-04-14T19:53:26.606] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-04-15T03:24:58.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-15 03:24:58 +[2025-04-15T06:02:42.209] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-04-15T06:02:42.213] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-04-15T06:02:42.215] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-04-15T06:02:42.217] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-04-15T11:19:33.941] [INFO] monitorLogs - MQTT client connected +[2025-04-15T19:55:09.552] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-04-15T19:55:09.556] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-04-15T19:55:09.558] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-04-15T19:55:09.560] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-04-16T03:24:59.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-16 03:24:59 +[2025-04-16T05:41:43.669] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-04-16T05:41:43.673] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-04-16T05:41:43.676] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-04-16T05:41:43.678] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-04-16T19:59:17.974] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-04-16T19:59:17.981] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-04-16T19:59:17.983] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-04-16T19:59:17.985] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-04-17T03:25:00.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-17 03:25:00 +[2025-04-17T05:42:52.608] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-04-17T05:42:52.616] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-04-17T05:42:52.618] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-04-17T05:42:52.620] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-04-17T19:44:42.438] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-04-17T19:44:42.442] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-04-17T19:44:42.443] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-04-17T19:44:42.445] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-04-18T03:25:02.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-18 03:25:02 +[2025-04-18T05:56:06.726] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-04-18T05:56:06.735] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-04-18T05:56:06.737] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-04-18T05:56:06.739] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-04-18T19:41:08.232] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-04-18T19:41:08.239] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-04-18T19:41:08.241] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-04-18T19:41:08.243] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-04-19T03:25:03.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-19 03:25:03 +[2025-04-19T05:37:57.963] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-04-19T05:37:57.970] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-04-19T05:37:57.972] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-04-19T05:37:57.975] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-04-19T20:04:51.090] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-04-19T20:04:51.098] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-04-19T20:04:51.100] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-04-19T20:04:51.101] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-04-20T03:25:04.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-20 03:25:04 +[2025-04-20T05:35:01.506] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-04-20T05:35:01.509] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-04-20T05:35:01.512] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-04-20T05:35:01.514] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-04-20T20:04:21.954] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-04-20T20:04:21.956] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-04-20T20:04:21.958] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-04-20T20:04:21.959] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-04-21T03:25:06.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-21 03:25:06 +[2025-04-21T05:34:29.572] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-04-21T05:34:29.576] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-04-21T05:34:29.578] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-04-21T05:34:29.580] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-04-21T20:05:36.680] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-04-21T20:05:36.683] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-04-21T20:05:36.685] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-04-21T20:05:36.687] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-04-22T03:25:07.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-22 03:25:07 +[2025-04-22T05:32:29.910] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-04-22T05:32:29.914] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-04-22T05:32:29.916] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-04-22T05:32:29.918] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-04-22T20:08:47.425] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-04-22T20:08:47.433] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-04-22T20:08:47.435] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-04-22T20:08:47.437] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-04-23T03:25:09.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-23 03:25:09 +[2025-04-23T05:38:01.371] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-04-23T05:38:01.375] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-04-23T05:38:01.377] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-04-23T05:38:01.380] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-04-23T07:05:46.432] [INFO] monitorLogs - MQTT client connected +[2025-04-23T20:07:25.627] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-04-23T20:07:25.629] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-04-23T20:07:25.631] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-04-23T20:07:25.633] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-04-24T03:25:10.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-24 03:25:10 +[2025-04-24T05:33:26.810] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-04-24T05:33:26.817] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-04-24T05:33:26.819] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-04-24T05:33:26.821] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-04-24T18:02:44.367] [INFO] monitorLogs - MQTT client connected +[2025-04-24T18:04:50.485] [INFO] monitorLogs - MQTT client connected +[2025-04-24T18:06:10.839] [INFO] monitorLogs - MQTT client connected +[2025-04-24T20:04:05.522] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-04-24T20:04:05.527] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-04-24T20:04:05.529] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-04-24T20:04:05.531] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-04-25T03:25:11.013] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-25 03:25:11 +[2025-04-25T05:47:41.731] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-04-25T05:47:41.739] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-04-25T05:47:41.741] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-04-25T05:47:41.743] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-04-25T11:23:53.712] [INFO] monitorLogs - MQTT client connected +[2025-04-25T12:15:01.683] [INFO] monitorLogs - MQTT client connected +[2025-04-25T20:06:31.409] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-04-25T20:06:31.412] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-04-25T20:06:31.414] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-04-25T20:06:31.416] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-04-26T03:25:13.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-26 03:25:13 +[2025-04-26T05:28:52.323] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-04-26T05:28:52.327] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-04-26T05:28:52.329] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-04-26T05:28:52.332] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-04-26T20:14:12.328] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-04-26T20:14:12.330] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-04-26T20:14:12.332] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-04-26T20:14:12.334] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-04-27T03:25:14.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-27 03:25:14 +[2025-04-27T05:23:36.026] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-04-27T05:23:36.030] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-04-27T05:23:36.032] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-04-27T05:23:36.034] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-04-27T20:14:50.643] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-04-27T20:14:50.650] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-04-27T20:14:50.652] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-04-27T20:14:50.655] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-04-28T03:25:15.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-28 03:25:15 +[2025-04-28T05:21:06.872] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-04-28T05:21:06.880] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-04-28T05:21:06.883] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-04-28T05:21:06.884] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-04-28T20:18:27.770] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-04-28T20:18:27.778] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-04-28T20:18:27.780] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-04-28T20:18:27.782] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-04-29T03:25:16.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-29 03:25:16 +[2025-04-29T05:21:28.382] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-04-29T05:21:28.385] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-04-29T05:21:28.387] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-04-29T05:21:28.389] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-04-29T06:46:58.875] [INFO] monitorLogs - MQTT client connected +[2025-04-29T06:53:27.273] [INFO] monitorLogs - MQTT client connected +[2025-04-29T06:54:26.143] [INFO] monitorLogs - MQTT client connected +[2025-04-29T06:56:07.544] [INFO] monitorLogs - MQTT client connected +[2025-04-29T07:49:21.323] [INFO] monitorLogs - MQTT client connected +[2025-04-29T07:50:05.216] [INFO] monitorLogs - MQTT client connected +[2025-04-29T07:52:02.456] [INFO] monitorLogs - MQTT client connected +[2025-04-29T07:53:25.498] [INFO] monitorLogs - MQTT client connected +[2025-04-29T07:54:07.815] [INFO] monitorLogs - MQTT client connected +[2025-04-29T09:12:16.267] [INFO] monitorLogs - MQTT client connected +[2025-04-29T20:18:50.801] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-04-29T20:18:50.803] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-04-29T20:18:50.805] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-04-29T20:18:50.807] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-04-30T03:25:18.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-30 03:25:18 +[2025-04-30T05:20:54.878] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-04-30T05:20:54.882] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-04-30T05:20:54.884] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-04-30T05:20:54.886] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-04-30T16:53:09.217] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-04-30T16:53:14.598] [INFO] monitorLogs - buildTasks - params undefined +[2025-04-30T16:53:14.602] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-04-30T16:53:14.604] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-04-30T16:53:14.604] [INFO] monitorLogs - profile: { + 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 +} +[2025-04-30T16:53:14.609] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-04-30T16:53:14.610] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-05-01T04:03:00.609Z +[2025-04-30T16:53:14.612] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-04-30T18:34:00.611Z +[2025-04-30T16:53:14.612] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '6:3', name: 'luxOff' }, + { value: 1, start_time: '20:34', name: 'luxOn' } +] +[2025-04-30T16:53:14.613] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-04-30T16:53:14.614] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-04-30T16:53:14.615] [INFO] monitorLogs - profile: { + 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 +} +[2025-04-30T16:53:14.617] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-04-30T16:53:14.618] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-05-01T04:03:00.618Z +[2025-04-30T16:53:14.619] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-04-30T18:34:00.619Z +[2025-04-30T16:53:14.619] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '6:3', name: 'luxOff' }, + { value: 1, start_time: '20:34', name: 'luxOn' } +] +[2025-04-30T16:53:14.620] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-04-30T16:53:14.621] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-04-30T16:53:14.622] [INFO] monitorLogs - profile: { + 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 +} +[2025-04-30T16:53:14.624] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-04-30T16:53:14.625] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-05-01T04:03:00.625Z +[2025-04-30T16:53:14.625] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-04-30T18:34:00.625Z +[2025-04-30T16:53:14.626] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '6:3', name: 'luxOff' }, + { value: 1, start_time: '20:34', name: 'luxOn' } +] +[2025-04-30T16:53:14.627] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-04-30T16:53:14.628] [INFO] monitorLogs - buildTasks: profile for line 4 +[2025-04-30T16:53:14.628] [INFO] monitorLogs - profile: { + 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 +} +[2025-04-30T16:53:14.631] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-04-30T16:53:14.632] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 4 2025-05-01T04:03:00.632Z +[2025-04-30T16:53:14.633] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 4 2025-04-30T18:34:00.633Z +[2025-04-30T16:53:14.634] [INFO] monitorLogs - -->time_points final 4 [ + { value: 0, start_time: '6:3', name: 'luxOff' }, + { value: 1, start_time: '20:34', name: 'luxOn' } +] +[2025-04-30T16:53:14.635] [INFO] monitorLogs - -->currentValue for relay 4 0 +[2025-04-30T16:53:14.662] [INFO] monitorLogs - tasks created: 1907 +[2025-04-30T16:53:14.664] [INFO] monitorLogs - -->FLOW bol spustený wvKJdZML6mXP4DzWBAXxwBAjxNloa5g23Ve9Y1ry 2025-04-24 +[2025-04-30T16:53:14.759] [INFO] monitorLogs - MQTT client connected +[2025-04-30T16:53:14.981] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-04-30T16:53:15.286] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-04-30T16:53:15.592] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-04-30T16:53:15.898] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false aplikovany bod profilu +[2025-04-30T20:18:32.671] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-04-30T20:18:32.674] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-04-30T20:18:32.677] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-04-30T20:18:32.679] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-05-01T03:53:16.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-01 03:53:16 +[2025-05-01T05:18:07.241] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-05-01T05:18:07.249] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-05-01T05:18:07.251] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-05-01T05:18:07.253] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-05-01T20:23:05.437] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-05-01T20:23:05.446] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-05-01T20:23:05.448] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-05-01T20:23:05.450] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-05-02T03:53:17.033] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-02 03:53:17 +[2025-05-02T05:14:35.576] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-05-02T05:14:35.579] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-05-02T05:14:35.581] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-05-02T05:14:35.583] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-05-02T20:21:56.901] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-05-02T20:21:56.909] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-05-02T20:21:56.911] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-05-02T20:21:56.914] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-05-03T03:53:19.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-03 03:53:19 +[2025-05-03T05:14:36.125] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-05-03T05:14:36.129] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-05-03T05:14:36.131] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-05-03T05:14:36.133] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-05-03T20:07:20.635] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-05-03T20:07:20.643] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-05-03T20:07:20.645] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-05-03T20:07:20.647] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-05-04T03:53:20.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-04 03:53:20 +[2025-05-04T05:21:10.631] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-05-04T05:21:10.640] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-05-04T05:21:10.642] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-05-04T05:21:10.644] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-05-04T20:24:43.339] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-05-04T20:24:43.346] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-05-04T20:24:43.348] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-05-04T20:24:43.350] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-05-05T03:53:22.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-05 03:53:22 +[2025-05-05T05:20:21.911] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-05-05T05:20:21.915] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-05-05T05:20:21.917] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-05-05T05:20:21.919] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-05-05T20:05:11.658] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-05-05T20:05:11.661] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-05-05T20:05:11.663] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-05-05T20:05:11.665] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-05-06T03:53:23.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-06 03:53:23 +[2025-05-06T05:18:25.599] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-05-06T05:18:25.603] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-05-06T05:18:25.605] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-05-06T05:18:25.607] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-05-06T08:24:16.217] [INFO] monitorLogs - MQTT client connected +[2025-05-06T20:25:06.779] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-05-06T20:25:06.782] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-05-06T20:25:06.784] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-05-06T20:25:06.785] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-05-07T03:53:24.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-07 03:53:24 +[2025-05-07T05:15:38.337] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-05-07T05:15:38.341] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-05-07T05:15:38.343] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-05-07T05:15:38.346] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-05-07T19:24:48.167] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-05-07T19:24:53.533] [INFO] monitorLogs - buildTasks - params undefined +[2025-05-07T19:24:53.537] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-05-07T19:24:53.539] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-05-07T19:24:53.539] [INFO] monitorLogs - profile: { + 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 +} +[2025-05-07T19:24:53.543] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-05-07T19:24:53.545] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-05-08T03:52:00.544Z +[2025-05-07T19:24:53.546] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-05-07T18:44:00.546Z +[2025-05-07T19:24:53.547] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '5:52', name: 'luxOff' }, + { value: 1, start_time: '20:44', name: 'luxOn' } +] +[2025-05-07T19:24:53.548] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-05-07T19:24:53.549] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-05-07T19:24:53.549] [INFO] monitorLogs - profile: { + 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 +} +[2025-05-07T19:24:53.552] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-05-07T19:24:53.553] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-05-08T03:52:00.552Z +[2025-05-07T19:24:53.553] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-05-07T18:44:00.553Z +[2025-05-07T19:24:53.554] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '5:52', name: 'luxOff' }, + { value: 1, start_time: '20:44', name: 'luxOn' } +] +[2025-05-07T19:24:53.555] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-05-07T19:24:53.556] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-05-07T19:24:53.556] [INFO] monitorLogs - profile: { + 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 +} +[2025-05-07T19:24:53.558] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-05-07T19:24:53.559] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-05-08T03:52:00.559Z +[2025-05-07T19:24:53.560] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-05-07T18:44:00.560Z +[2025-05-07T19:24:53.560] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '5:52', name: 'luxOff' }, + { value: 1, start_time: '20:44', name: 'luxOn' } +] +[2025-05-07T19:24:53.561] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-05-07T19:24:53.562] [INFO] monitorLogs - buildTasks: profile for line 4 +[2025-05-07T19:24:53.563] [INFO] monitorLogs - profile: { + 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 +} +[2025-05-07T19:24:53.565] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-05-07T19:24:53.565] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 4 2025-05-08T03:52:00.565Z +[2025-05-07T19:24:53.566] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 4 2025-05-07T18:44:00.566Z +[2025-05-07T19:24:53.567] [INFO] monitorLogs - -->time_points final 4 [ + { value: 0, start_time: '5:52', name: 'luxOff' }, + { value: 1, start_time: '20:44', name: 'luxOn' } +] +[2025-05-07T19:24:53.568] [INFO] monitorLogs - -->currentValue for relay 4 0 +[2025-05-07T19:24:53.595] [INFO] monitorLogs - tasks created: 1907 +[2025-05-07T19:24:53.599] [INFO] monitorLogs - -->FLOW bol spustený wvKJdZML6mXP4DzWBAXxwBAjxNloa5g23Ve9Y1ry 2025-04-24 +[2025-05-07T19:24:53.698] [INFO] monitorLogs - MQTT client connected +[2025-05-07T19:24:53.914] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-05-07T19:24:54.220] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-05-07T19:24:54.524] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-05-07T19:24:54.830] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false aplikovany bod profilu +[2025-05-07T20:21:52.643] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-05-07T20:21:52.646] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-05-07T20:21:52.648] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-05-07T20:21:52.651] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-05-08T03:24:56.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-08 03:24:56 +[2025-05-08T05:14:55.017] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-05-08T05:14:55.021] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-05-08T05:14:55.024] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-05-08T05:14:55.026] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-05-08T20:29:21.036] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-05-08T20:29:21.046] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-05-08T20:29:21.049] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-05-08T20:29:21.051] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-05-09T03:24:57.024] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-09 03:24:57 +[2025-05-09T05:04:00.477] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-05-09T05:04:00.481] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-05-09T05:04:00.484] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-05-09T05:04:00.487] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-05-09T08:19:45.153] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-05-09T08:19:50.533] [INFO] monitorLogs - buildTasks - params undefined +[2025-05-09T08:19:50.538] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-05-09T08:19:50.539] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-05-09T08:19:50.539] [INFO] monitorLogs - profile: { + 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 +} +[2025-05-09T08:19:50.544] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-05-09T08:19:50.545] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-05-10T03:49:00.544Z +[2025-05-09T08:19:50.547] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-05-09T18:47:00.546Z +[2025-05-09T08:19:50.547] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '5:49', name: 'luxOff' }, + { value: 1, start_time: '20:47', name: 'luxOn' } +] +[2025-05-09T08:19:50.548] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-05-09T08:19:50.549] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-05-09T08:19:50.550] [INFO] monitorLogs - profile: { + 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 +} +[2025-05-09T08:19:50.552] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-05-09T08:19:50.553] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-05-10T03:49:00.553Z +[2025-05-09T08:19:50.554] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-05-09T18:47:00.554Z +[2025-05-09T08:19:50.554] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '5:49', name: 'luxOff' }, + { value: 1, start_time: '20:47', name: 'luxOn' } +] +[2025-05-09T08:19:50.555] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-05-09T08:19:50.556] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-05-09T08:19:50.557] [INFO] monitorLogs - profile: { + 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 +} +[2025-05-09T08:19:50.559] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-05-09T08:19:50.560] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-05-10T03:49:00.559Z +[2025-05-09T08:19:50.560] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-05-09T18:47:00.560Z +[2025-05-09T08:19:50.561] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '5:49', name: 'luxOff' }, + { value: 1, start_time: '20:47', name: 'luxOn' } +] +[2025-05-09T08:19:50.562] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-05-09T08:19:50.563] [INFO] monitorLogs - buildTasks: profile for line 4 +[2025-05-09T08:19:50.563] [INFO] monitorLogs - profile: { + 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 +} +[2025-05-09T08:19:50.565] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-05-09T08:19:50.566] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 4 2025-05-10T03:49:00.566Z +[2025-05-09T08:19:50.567] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 4 2025-05-09T18:47:00.567Z +[2025-05-09T08:19:50.567] [INFO] monitorLogs - -->time_points final 4 [ + { value: 0, start_time: '5:49', name: 'luxOff' }, + { value: 1, start_time: '20:47', name: 'luxOn' } +] +[2025-05-09T08:19:50.568] [INFO] monitorLogs - -->currentValue for relay 4 0 +[2025-05-09T08:19:50.578] [INFO] monitorLogs - tasks created: 1907 +[2025-05-09T08:19:50.581] [INFO] monitorLogs - -->FLOW bol spustený wvKJdZML6mXP4DzWBAXxwBAjxNloa5g23Ve9Y1ry 2025-04-24 +[2025-05-09T08:19:50.680] [INFO] monitorLogs - MQTT client connected +[2025-05-09T08:19:50.897] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-05-09T08:19:51.202] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-05-09T08:19:51.508] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-05-09T08:19:51.814] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false aplikovany bod profilu +[2025-05-09T20:32:58.234] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-05-09T20:32:58.242] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-05-09T20:32:58.245] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-05-09T20:32:58.247] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-05-10T03:19:53.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-10 03:19:53 +[2025-05-10T05:01:50.373] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-05-10T05:01:50.377] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-05-10T05:01:50.379] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-05-10T05:01:50.381] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-05-10T20:29:47.352] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-05-10T20:29:47.361] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-05-10T20:29:47.363] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-05-10T20:29:47.365] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-05-11T03:19:54.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-11 03:19:54 +[2025-05-11T05:07:03.360] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-05-11T05:07:03.364] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-05-11T05:07:03.366] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-05-11T05:07:03.368] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-05-11T20:38:45.455] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-05-11T20:38:45.464] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-05-11T20:38:45.466] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-05-11T20:38:45.468] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-05-12T03:19:55.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-12 03:19:55 +[2025-05-12T04:10:16.170] [INFO] monitorLogs - MQTT client connected +[2025-05-12T04:59:22.379] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-05-12T04:59:22.382] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-05-12T04:59:22.384] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-05-12T04:59:22.386] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-05-12T09:49:22.405] [INFO] monitorLogs - MQTT client connected +[2025-05-12T10:55:47.279] [INFO] monitorLogs - MQTT client connected +[2025-05-12T20:37:52.478] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-05-12T20:37:52.482] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-05-12T20:37:52.484] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-05-12T20:37:52.487] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-05-13T03:19:56.017] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-13 03:19:56 +[2025-05-13T04:58:04.061] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-05-13T04:58:04.065] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-05-13T04:58:04.068] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-05-13T04:58:04.070] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-05-13T20:39:06.980] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-05-13T20:39:06.988] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-05-13T20:39:06.991] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-05-13T20:39:06.993] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-05-14T03:19:58.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-14 03:19:58 +[2025-05-14T04:57:17.965] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-05-14T04:57:17.974] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-05-14T04:57:17.976] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-05-14T04:57:17.978] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-05-14T08:40:50.802] [INFO] monitorLogs - MQTT client connected +[2025-05-14T09:43:33.239] [INFO] monitorLogs - MQTT client connected +[2025-05-14T10:08:41.651] [INFO] monitorLogs - MQTT client connected +[2025-05-14T10:49:02.497] [INFO] monitorLogs - MQTT client connected +[2025-05-14T10:54:51.316] [INFO] monitorLogs - MQTT client connected +[2025-05-14T10:55:14.939] [INFO] monitorLogs - MQTT client connected +[2025-05-14T20:35:04.262] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-05-14T20:35:04.265] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-05-14T20:35:04.267] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-05-14T20:35:04.268] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-05-15T03:19:59.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-15 03:19:59 +[2025-05-15T05:07:00.933] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-05-15T05:07:00.941] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-05-15T05:07:00.944] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-05-15T05:07:00.945] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-05-15T08:58:52.983] [INFO] monitorLogs - MQTT client connected +[2025-05-15T20:31:47.301] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-05-15T20:31:47.318] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-05-15T20:31:47.320] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-05-15T20:31:47.322] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-05-16T03:20:00.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-16 03:20:00 +[2025-05-16T04:54:08.490] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-05-16T04:54:08.494] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-05-16T04:54:08.496] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-05-16T04:54:08.498] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-05-16T20:44:09.854] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-05-16T20:44:09.864] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-05-16T20:44:09.866] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-05-16T20:44:09.868] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-05-17T03:20:01.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-17 03:20:01 +[2025-05-17T05:07:41.171] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-05-17T05:07:41.178] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-05-17T05:07:41.180] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-05-17T05:07:41.183] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-05-17T20:32:24.929] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-05-17T20:32:24.941] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-05-17T20:32:24.943] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-05-17T20:32:24.945] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-05-18T03:20:02.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-18 03:20:02 +[2025-05-18T05:14:23.212] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-05-18T05:14:23.215] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-05-18T05:14:23.218] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-05-18T05:14:23.220] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-05-18T13:25:50.521] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-05-18T13:25:55.911] [INFO] monitorLogs - buildTasks - params undefined +[2025-05-18T13:25:55.916] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-05-18T13:25:55.917] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-05-18T13:25:55.918] [INFO] monitorLogs - profile: { + 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 +} +[2025-05-18T13:25:55.922] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-05-18T13:25:55.924] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-05-19T03:37:00.923Z +[2025-05-18T13:25:55.925] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-05-18T19:00:00.925Z +[2025-05-18T13:25:55.926] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '5:37', name: 'luxOff' }, + { value: 1, start_time: '21:0', name: 'luxOn' } +] +[2025-05-18T13:25:55.927] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-05-18T13:25:55.928] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-05-18T13:25:55.928] [INFO] monitorLogs - profile: { + 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 +} +[2025-05-18T13:25:55.931] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-05-18T13:25:55.931] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-05-19T03:37:00.931Z +[2025-05-18T13:25:55.932] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-05-18T19:00:00.932Z +[2025-05-18T13:25:55.933] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '5:37', name: 'luxOff' }, + { value: 1, start_time: '21:0', name: 'luxOn' } +] +[2025-05-18T13:25:55.934] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-05-18T13:25:55.935] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-05-18T13:25:55.935] [INFO] monitorLogs - profile: { + 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 +} +[2025-05-18T13:25:55.937] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-05-18T13:25:55.938] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-05-19T03:37:00.938Z +[2025-05-18T13:25:55.939] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-05-18T19:00:00.939Z +[2025-05-18T13:25:55.939] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '5:37', name: 'luxOff' }, + { value: 1, start_time: '21:0', name: 'luxOn' } +] +[2025-05-18T13:25:55.940] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-05-18T13:25:55.941] [INFO] monitorLogs - buildTasks: profile for line 4 +[2025-05-18T13:25:55.942] [INFO] monitorLogs - profile: { + 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 +} +[2025-05-18T13:25:55.944] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-05-18T13:25:55.945] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 4 2025-05-19T03:37:00.944Z +[2025-05-18T13:25:55.945] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 4 2025-05-18T19:00:00.945Z +[2025-05-18T13:25:55.946] [INFO] monitorLogs - -->time_points final 4 [ + { value: 0, start_time: '5:37', name: 'luxOff' }, + { value: 1, start_time: '21:0', name: 'luxOn' } +] +[2025-05-18T13:25:55.947] [INFO] monitorLogs - -->currentValue for relay 4 0 +[2025-05-18T13:25:55.973] [INFO] monitorLogs - tasks created: 1907 +[2025-05-18T13:25:55.975] [INFO] monitorLogs - -->FLOW bol spustený wvKJdZML6mXP4DzWBAXxwBAjxNloa5g23Ve9Y1ry 2025-04-24 +[2025-05-18T13:26:00.992] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-05-18T20:40:21.136] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-05-18T20:40:21.146] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-05-18T20:40:21.148] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-05-18T20:40:21.151] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-05-19T03:25:58.013] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-19 03:25:58 +[2025-05-19T05:08:51.798] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-05-19T05:08:51.802] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-05-19T05:08:51.804] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-05-19T05:08:51.807] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-05-19T20:18:45.411] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-05-19T20:18:45.417] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-05-19T20:18:45.419] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-05-19T20:18:45.421] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-05-20T03:25:59.019] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-20 03:25:59 +[2025-05-20T05:06:50.132] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-05-20T05:06:50.136] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-05-20T05:06:50.138] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-05-20T05:06:50.140] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-05-20T20:48:28.378] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-05-20T20:48:28.385] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-05-20T20:48:28.388] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-05-20T20:48:28.390] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-05-21T03:26:00.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-21 03:26:00 +[2025-05-21T04:46:05.523] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-05-21T04:46:05.531] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-05-21T04:46:05.534] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-05-21T04:46:05.536] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-05-21T20:43:38.976] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-05-21T20:43:38.984] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-05-21T20:43:38.986] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-05-21T20:43:38.988] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-05-22T03:26:02.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-22 03:26:02 +[2025-05-22T04:49:36.504] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-05-22T04:49:36.508] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-05-22T04:49:36.510] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-05-22T04:49:36.512] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-05-22T20:38:54.237] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-05-22T20:38:54.245] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-05-22T20:38:54.247] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-05-22T20:38:54.249] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-05-23T03:26:03.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-23 03:26:03 +[2025-05-23T04:52:25.798] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-05-23T04:52:25.801] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-05-23T04:52:25.804] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-05-23T04:52:25.806] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-05-23T20:53:54.167] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-05-23T20:53:54.175] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-05-23T20:53:54.177] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-05-23T20:53:54.179] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-05-24T03:26:04.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-24 03:26:04 +[2025-05-24T04:46:04.037] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-05-24T04:46:04.041] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-05-24T04:46:04.043] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-05-24T04:46:04.046] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-05-24T20:51:44.412] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-05-24T20:51:44.420] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-05-24T20:51:44.422] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-05-24T20:51:44.424] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-05-25T03:26:06.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-25 03:26:06 +[2025-05-25T04:42:58.878] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-05-25T04:42:58.882] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-05-25T04:42:58.884] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-05-25T04:42:58.886] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-05-25T20:54:08.543] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-05-25T20:54:08.551] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-05-25T20:54:08.553] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-05-25T20:54:08.555] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-05-26T03:26:07.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-26 03:26:07 +[2025-05-26T04:57:06.975] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-05-26T04:57:06.979] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-05-26T04:57:06.981] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-05-26T04:57:06.984] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-05-26T16:31:31.188] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-05-26T16:31:36.546] [INFO] monitorLogs - buildTasks - params undefined +[2025-05-26T16:31:36.550] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-05-26T16:31:36.551] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-05-26T16:31:36.552] [INFO] monitorLogs - profile: { + 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 +} +[2025-05-26T16:31:36.556] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-05-26T16:31:36.558] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-05-27T03:28:00.557Z +[2025-05-26T16:31:36.559] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-05-26T19:09:00.559Z +[2025-05-26T16:31:36.560] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '5:28', name: 'luxOff' }, + { value: 1, start_time: '21:9', name: 'luxOn' } +] +[2025-05-26T16:31:36.561] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-05-26T16:31:36.562] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-05-26T16:31:36.562] [INFO] monitorLogs - profile: { + 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 +} +[2025-05-26T16:31:36.565] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-05-26T16:31:36.566] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-05-27T03:28:00.565Z +[2025-05-26T16:31:36.566] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-05-26T19:09:00.566Z +[2025-05-26T16:31:36.567] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '5:28', name: 'luxOff' }, + { value: 1, start_time: '21:9', name: 'luxOn' } +] +[2025-05-26T16:31:36.568] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-05-26T16:31:36.569] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-05-26T16:31:36.569] [INFO] monitorLogs - profile: { + 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 +} +[2025-05-26T16:31:36.572] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-05-26T16:31:36.572] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-05-27T03:28:00.572Z +[2025-05-26T16:31:36.573] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-05-26T19:09:00.573Z +[2025-05-26T16:31:36.574] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '5:28', name: 'luxOff' }, + { value: 1, start_time: '21:9', name: 'luxOn' } +] +[2025-05-26T16:31:36.575] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-05-26T16:31:36.575] [INFO] monitorLogs - buildTasks: profile for line 4 +[2025-05-26T16:31:36.576] [INFO] monitorLogs - profile: { + 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 +} +[2025-05-26T16:31:36.578] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-05-26T16:31:36.579] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 4 2025-05-27T03:28:00.579Z +[2025-05-26T16:31:36.579] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 4 2025-05-26T19:09:00.579Z +[2025-05-26T16:31:36.580] [INFO] monitorLogs - -->time_points final 4 [ + { value: 0, start_time: '5:28', name: 'luxOff' }, + { value: 1, start_time: '21:9', name: 'luxOn' } +] +[2025-05-26T16:31:36.581] [INFO] monitorLogs - -->currentValue for relay 4 0 +[2025-05-26T16:31:36.607] [INFO] monitorLogs - tasks created: 1907 +[2025-05-26T16:31:36.610] [INFO] monitorLogs - -->FLOW bol spustený wvKJdZML6mXP4DzWBAXxwBAjxNloa5g23Ve9Y1ry 2025-04-24 +[2025-05-26T16:31:41.627] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-05-26T20:51:56.638] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-05-26T20:51:56.646] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-05-26T20:51:56.649] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-05-26T20:51:56.651] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-05-27T03:31:38.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-27 03:31:38 +[2025-05-27T04:41:41.860] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-05-27T04:41:41.869] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-05-27T04:41:41.871] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-05-27T04:41:41.873] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-05-27T20:56:52.155] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-05-27T20:56:52.163] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-05-27T20:56:52.165] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-05-27T20:56:52.167] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-05-28T03:31:40.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-28 03:31:40 +[2025-05-28T04:40:57.304] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-05-28T04:40:57.308] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-05-28T04:40:57.310] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-05-28T04:40:57.312] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-05-28T20:56:10.917] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-05-28T20:56:10.931] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-05-28T20:56:10.933] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-05-28T20:56:10.935] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-05-29T03:31:41.059] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-29 03:31:41 +[2025-05-29T04:41:12.912] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-05-29T04:41:12.915] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-05-29T04:41:12.918] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-05-29T04:41:12.921] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-05-29T20:57:39.371] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-05-29T20:57:39.373] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-05-29T20:57:39.375] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-05-29T20:57:39.377] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-05-30T03:31:42.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-30 03:31:42 +[2025-05-30T04:39:41.197] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-05-30T04:39:41.201] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-05-30T04:39:41.203] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-05-30T04:39:41.206] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-05-30T21:00:18.311] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-05-30T21:00:18.318] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-05-30T21:00:18.320] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-05-30T21:00:18.322] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-05-31T03:31:44.013] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-31 03:31:44 +[2025-05-31T04:37:03.982] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-05-31T04:37:03.985] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-05-31T04:37:03.987] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-05-31T04:37:03.989] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-05-31T20:51:27.297] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-05-31T20:51:27.313] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-05-31T20:51:27.315] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-05-31T20:51:27.317] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-06-01T03:31:45.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-01 03:31:45 +[2025-06-01T04:39:43.269] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-06-01T04:39:43.272] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-06-01T04:39:43.274] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-06-01T04:39:43.276] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-06-01T20:55:47.822] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-06-01T20:55:47.850] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-06-01T20:55:47.852] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-06-01T20:55:47.854] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-06-02T03:31:47.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-02 03:31:47 +[2025-06-02T04:38:53.394] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-06-02T04:38:53.398] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-06-02T04:38:53.400] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-06-02T04:38:53.402] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-06-02T20:34:19.224] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-06-02T20:34:19.236] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-06-02T20:34:19.238] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-06-02T20:34:19.240] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-06-03T03:31:48.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-03 03:31:48 +[2025-06-03T04:48:57.007] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-06-03T04:48:57.011] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-06-03T04:48:57.013] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-06-03T04:48:57.015] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-06-03T21:02:18.360] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-06-03T21:02:18.367] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-06-03T21:02:18.369] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-06-03T21:02:18.371] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-06-04T03:31:50.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-04 03:31:50 +[2025-06-04T04:37:15.759] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-06-04T04:37:15.763] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-06-04T04:37:15.765] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-06-04T04:37:15.767] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-06-04T21:01:01.189] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-06-04T21:01:01.197] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-06-04T21:01:01.200] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-06-04T21:01:01.201] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-06-05T03:31:51.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-05 03:31:51 +[2025-06-05T04:38:32.802] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-06-05T04:38:32.805] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-06-05T04:38:32.808] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-06-05T04:38:32.810] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-06-05T20:59:18.161] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-06-05T20:59:18.169] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-06-05T20:59:18.171] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-06-05T20:59:18.173] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-06-06T03:31:53.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-06 03:31:53 +[2025-06-06T04:38:02.148] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-06-06T04:38:02.152] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-06-06T04:38:02.154] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-06-06T04:38:02.156] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-06-06T21:06:13.942] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-06-06T21:06:13.947] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-06-06T21:06:13.949] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-06-06T21:06:13.951] [INFO] monitorLogs - turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-06-07T03:31:54.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-07 03:31:54 +[2025-06-07T04:46:06.866] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-06-07T04:46:06.869] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-06-07T04:46:06.872] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-06-07T04:46:06.874] [INFO] monitorLogs - turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-06-07T13:58:22.189] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-06-07T13:58:27.550] [INFO] monitorLogs - buildTasks - params undefined +[2025-06-07T13:58:27.554] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-06-07T13:58:27.555] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-06-07T13:58:27.556] [INFO] monitorLogs - profile: { + 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 +} +[2025-06-07T13:58:27.560] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-06-07T13:58:27.562] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-06-08T03:20:00.561Z +[2025-06-07T13:58:27.563] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-06-07T19:21:00.563Z +[2025-06-07T13:58:27.564] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '5:20', name: 'luxOff' }, + { value: 1, start_time: '21:21', name: 'luxOn' } +] +[2025-06-07T13:58:27.565] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-06-07T13:58:27.566] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-06-07T13:58:27.566] [INFO] monitorLogs - profile: { + 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 +} +[2025-06-07T13:58:27.569] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-06-07T13:58:27.569] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-06-08T03:20:00.569Z +[2025-06-07T13:58:27.570] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-06-07T19:21:00.570Z +[2025-06-07T13:58:27.571] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '5:20', name: 'luxOff' }, + { value: 1, start_time: '21:21', name: 'luxOn' } +] +[2025-06-07T13:58:27.572] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-06-07T13:58:27.573] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-06-07T13:58:27.573] [INFO] monitorLogs - profile: { + 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 +} +[2025-06-07T13:58:27.575] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-06-07T13:58:27.576] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-06-08T03:20:00.576Z +[2025-06-07T13:58:27.577] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-06-07T19:21:00.577Z +[2025-06-07T13:58:27.578] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '5:20', name: 'luxOff' }, + { value: 1, start_time: '21:21', name: 'luxOn' } +] +[2025-06-07T13:58:27.578] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-06-07T13:58:27.579] [INFO] monitorLogs - buildTasks: profile for line 4 +[2025-06-07T13:58:27.580] [INFO] monitorLogs - profile: { + 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 +} +[2025-06-07T13:58:27.582] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-06-07T13:58:27.583] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 4 2025-06-08T03:20:00.582Z +[2025-06-07T13:58:27.583] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 4 2025-06-07T19:21:00.583Z +[2025-06-07T13:58:27.584] [INFO] monitorLogs - -->time_points final 4 [ + { value: 0, start_time: '5:20', name: 'luxOff' }, + { value: 1, start_time: '21:21', name: 'luxOn' } +] +[2025-06-07T13:58:27.585] [INFO] monitorLogs - -->currentValue for relay 4 0 +[2025-06-07T13:58:27.612] [INFO] monitorLogs - tasks created: 1907 +[2025-06-07T13:58:27.615] [INFO] monitorLogs - -->FLOW bol spustený wvKJdZML6mXP4DzWBAXxwBAjxNloa5g23Ve9Y1ry 2025-04-24 +[2025-06-07T13:58:32.627] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-07T20:44:14.344] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-06-07T20:44:14.351] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-06-07T20:44:14.353] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-06-07T20:44:14.355] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-06-08T03:58:30.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-08 03:58:30 +[2025-06-08T04:33:16.705] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-06-08T04:33:16.717] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-06-08T04:33:16.719] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-06-08T04:33:16.721] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-06-08T21:06:42.410] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-06-08T21:06:42.429] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-06-08T21:06:42.431] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-06-08T21:06:42.433] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-06-09T03:58:31.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-09 03:58:31 +[2025-06-09T04:35:07.682] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-06-09T04:35:07.685] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-06-09T04:35:07.687] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-06-09T04:35:07.690] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-06-09T21:07:52.863] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-06-09T21:07:52.868] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-06-09T21:07:52.870] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-06-09T21:07:52.872] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-06-10T03:58:33.015] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-10 03:58:33 +[2025-06-10T04:36:01.689] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-06-10T04:36:01.693] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-06-10T04:36:01.695] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-06-10T04:36:01.697] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-06-10T21:04:12.318] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-06-10T21:04:12.323] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-06-10T21:04:12.325] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-06-10T21:04:12.327] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-06-11T03:58:34.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-11 03:58:34 +[2025-06-11T04:39:26.735] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-06-11T04:39:26.739] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-06-11T04:39:26.741] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-06-11T04:39:26.743] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-06-11T21:11:21.667] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-06-11T21:11:21.672] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-06-11T21:11:21.674] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-06-11T21:11:21.676] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-06-12T03:58:35.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-12 03:58:35 +[2025-06-12T04:32:59.178] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-06-12T04:32:59.181] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-06-12T04:32:59.183] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-06-12T04:32:59.185] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-06-12T21:11:44.434] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-06-12T21:11:44.451] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-06-12T21:11:44.453] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-06-12T21:11:44.455] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-06-13T03:58:37.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-13 03:58:37 +[2025-06-13T04:33:38.016] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-06-13T04:33:38.020] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-06-13T04:33:38.021] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-06-13T04:33:38.023] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-06-13T15:23:00.188] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-06-13T15:23:05.564] [INFO] monitorLogs - buildTasks - params undefined +[2025-06-13T15:23:05.569] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-06-13T15:23:05.570] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-06-13T15:23:05.570] [INFO] monitorLogs - profile: { + 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 +} +[2025-06-13T15:23:05.574] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-06-13T15:23:05.576] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-06-14T03:19:00.575Z +[2025-06-13T15:23:05.577] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-06-13T19:25:00.577Z +[2025-06-13T15:23:05.578] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '5:19', name: 'luxOff' }, + { value: 1, start_time: '21:25', name: 'luxOn' } +] +[2025-06-13T15:23:05.579] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-06-13T15:23:05.580] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-06-13T15:23:05.581] [INFO] monitorLogs - profile: { + 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 +} +[2025-06-13T15:23:05.583] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-06-13T15:23:05.584] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-06-14T03:19:00.583Z +[2025-06-13T15:23:05.585] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-06-13T19:25:00.584Z +[2025-06-13T15:23:05.585] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '5:19', name: 'luxOff' }, + { value: 1, start_time: '21:25', name: 'luxOn' } +] +[2025-06-13T15:23:05.586] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-06-13T15:23:05.587] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-06-13T15:23:05.587] [INFO] monitorLogs - profile: { + 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 +} +[2025-06-13T15:23:05.590] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-06-13T15:23:05.590] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-06-14T03:19:00.590Z +[2025-06-13T15:23:05.591] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-06-13T19:25:00.591Z +[2025-06-13T15:23:05.592] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '5:19', name: 'luxOff' }, + { value: 1, start_time: '21:25', name: 'luxOn' } +] +[2025-06-13T15:23:05.593] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-06-13T15:23:05.594] [INFO] monitorLogs - buildTasks: profile for line 4 +[2025-06-13T15:23:05.594] [INFO] monitorLogs - profile: { + 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 +} +[2025-06-13T15:23:05.596] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-06-13T15:23:05.597] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 4 2025-06-14T03:19:00.597Z +[2025-06-13T15:23:05.598] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 4 2025-06-13T19:25:00.598Z +[2025-06-13T15:23:05.598] [INFO] monitorLogs - -->time_points final 4 [ + { value: 0, start_time: '5:19', name: 'luxOff' }, + { value: 1, start_time: '21:25', name: 'luxOn' } +] +[2025-06-13T15:23:05.600] [INFO] monitorLogs - -->currentValue for relay 4 0 +[2025-06-13T15:23:05.626] [INFO] monitorLogs - tasks created: 1907 +[2025-06-13T15:23:05.629] [INFO] monitorLogs - -->FLOW bol spustený wvKJdZML6mXP4DzWBAXxwBAjxNloa5g23Ve9Y1ry 2025-04-24 +[2025-06-13T15:23:10.646] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-13T21:12:30.418] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-06-13T21:12:30.426] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-06-13T21:12:30.429] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-06-13T21:12:30.431] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-06-14T03:23:08.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-14 03:23:08 +[2025-06-14T04:31:32.157] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-06-14T04:31:32.162] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-06-14T04:31:32.165] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-06-14T04:31:32.167] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-06-14T21:15:02.399] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-06-14T21:15:02.407] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-06-14T21:15:02.410] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-06-14T21:15:02.412] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-06-15T03:23:17.198] [INFO] monitorLogs - setCorrectPlcTimeOnceADay - function error SyntaxError: Unexpected token < in JSON at position 0 + at JSON.parse () + at /home/unipi/flowserver/flow/cmd_manager.js:2424:28 + at Object.exec_callback [as callback] (/home/unipi/flowserver/node_modules/total.js/builders.js:5803:3) + at IncomingMessage.request_process_end (/home/unipi/flowserver/node_modules/total.js/utils.js:1184:11) + at IncomingMessage.emit (events.js:412:35) + at endReadableNT (internal/streams/readable.js:1334:12) + at processTicksAndRejections (internal/process/task_queues.js:82:21) 503: Service Unavailable
503
Service Unavailable
+[2025-06-15T04:32:17.565] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-06-15T04:32:17.570] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-06-15T04:32:17.573] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-06-15T04:32:17.575] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-06-15T21:11:12.761] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-06-15T21:11:12.779] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-06-15T21:11:12.781] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-06-15T21:11:12.783] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-06-16T03:23:11.013] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-16 03:23:11 +[2025-06-16T04:30:09.522] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-06-16T04:30:09.525] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-06-16T04:30:09.528] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-06-16T04:30:09.530] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-06-16T20:48:04.180] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-06-16T20:48:04.192] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-06-16T20:48:04.195] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-06-16T20:48:04.197] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-06-17T03:23:12.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-17 03:23:12 +[2025-06-17T04:41:00.911] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-06-17T04:41:00.915] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-06-17T04:41:00.917] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-06-17T04:41:00.919] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-06-17T21:10:11.370] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-06-17T21:10:11.385] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-06-17T21:10:11.387] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-06-17T21:10:11.389] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-06-18T03:23:13.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-18 03:23:13 +[2025-06-18T04:32:04.122] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-06-18T04:32:04.126] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-06-18T04:32:04.129] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-06-18T04:32:04.132] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-06-18T21:11:41.791] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-06-18T21:11:41.803] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-06-18T21:11:41.806] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-06-18T21:11:41.808] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-06-19T03:23:15.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-19 03:23:15 +[2025-06-19T04:33:19.924] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-06-19T04:33:19.928] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-06-19T04:33:19.930] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-06-19T04:33:19.933] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-06-19T21:15:19.477] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-06-19T21:15:19.505] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-06-19T21:15:19.507] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-06-19T21:15:19.509] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-06-20T03:23:17.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-20 03:23:17 +[2025-06-20T04:34:19.086] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-06-20T04:34:19.089] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-06-20T04:34:19.091] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-06-20T04:34:19.093] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-06-20T21:14:03.739] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-06-20T21:14:03.757] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-06-20T21:14:03.760] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-06-20T21:14:03.762] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-06-21T03:23:18.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-21 03:23:18 +[2025-06-21T04:33:27.394] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-06-21T04:33:27.398] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-06-21T04:33:27.400] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-06-21T04:33:27.402] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-06-21T21:14:45.877] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-06-21T21:14:45.903] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-06-21T21:14:45.905] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-06-21T21:14:45.907] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-06-22T03:23:19.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-22 03:23:19 +[2025-06-22T04:34:38.744] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-06-22T04:34:38.748] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-06-22T04:34:38.750] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-06-22T04:34:38.752] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-06-22T21:13:20.562] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-06-22T21:13:20.578] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-06-22T21:13:20.580] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-06-22T21:13:20.583] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-06-23T03:23:21.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-23 03:23:21 +[2025-06-23T04:35:17.963] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-06-23T04:35:17.967] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-06-23T04:35:17.969] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-06-23T04:35:17.971] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-06-23T21:02:47.830] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-06-23T21:02:47.837] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-06-23T21:02:47.839] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-06-23T21:02:47.841] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-06-24T03:23:23.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-24 03:23:23 +[2025-06-24T04:35:43.662] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-06-24T04:35:43.665] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-06-24T04:35:43.667] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-06-24T04:35:43.669] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-06-24T21:13:44.898] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-06-24T21:13:44.905] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-06-24T21:13:44.907] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-06-24T21:13:44.909] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-06-25T03:23:24.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-25 03:23:24 +[2025-06-25T04:35:29.928] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-06-25T04:35:29.932] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-06-25T04:35:29.934] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-06-25T04:35:29.936] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-06-25T21:14:42.234] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-06-25T21:14:42.246] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-06-25T21:14:42.248] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-06-25T21:14:42.251] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-06-26T03:23:26.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-26 03:23:26 +[2025-06-26T04:34:32.356] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-06-26T04:34:32.360] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-06-26T04:34:32.362] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-06-26T04:34:32.365] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-06-26T20:39:47.224] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-06-26T20:39:47.243] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-06-26T20:39:47.245] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-06-26T20:39:47.248] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-06-27T03:23:28.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-27 03:23:28 +[2025-06-27T04:39:16.233] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-06-27T04:39:16.237] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-06-27T04:39:16.239] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-06-27T04:39:16.241] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-06-27T21:08:59.320] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-06-27T21:08:59.344] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-06-27T21:08:59.347] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-06-27T21:08:59.349] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-06-28T03:23:29.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-28 03:23:29 +[2025-06-28T04:46:54.083] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-06-28T04:46:54.086] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-06-28T04:46:54.089] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-06-28T04:46:54.091] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-06-28T21:15:33.449] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-06-28T21:15:33.455] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-06-28T21:15:33.457] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-06-28T21:15:33.459] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-06-29T03:23:31.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-29 03:23:31 +[2025-06-29T04:35:21.577] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-06-29T04:35:21.581] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-06-29T04:35:21.583] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-06-29T04:35:21.585] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-06-29T21:14:47.996] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-06-29T21:14:48.012] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-06-29T21:14:48.014] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-06-29T21:14:48.016] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-06-30T03:23:32.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-30 03:23:32 +[2025-06-30T04:36:42.734] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-06-30T04:36:42.737] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-06-30T04:36:42.740] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-06-30T04:36:42.742] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-06-30T21:17:42.271] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-06-30T21:17:42.297] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-06-30T21:17:42.299] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-06-30T21:17:42.301] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-07-01T03:23:34.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-01 03:23:34 +[2025-07-01T04:37:22.690] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-01T04:37:22.694] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-01T04:37:22.696] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-01T04:37:22.698] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-07-01T09:49:47.089] [INFO] monitorLogs - turnLine on - (line, SETTINGS.maintenance_mode) 0 true command received from platform +[2025-07-01T09:49:57.922] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false command received from platform +[2025-07-01T09:50:10.404] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false command received from platform +[2025-07-01T09:50:23.843] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false command received from platform +[2025-07-01T09:50:33.441] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false command received from platform +[2025-07-01T09:50:40.161] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false command received from platform +[2025-07-01T09:54:19.357] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false command received from platform +[2025-07-01T09:54:54.877] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false command received from platform +[2025-07-01T09:59:05.148] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false command received from platform +[2025-07-01T09:59:31.530] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false command received from platform +[2025-07-01T10:06:57.427] [INFO] monitorLogs - turnLine on - (line, SETTINGS.maintenance_mode) 0 true command received from platform +[2025-07-01T10:07:10.225] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false command received from platform +[2025-07-01T10:07:16.304] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false command received from platform +[2025-07-01T10:07:23.344] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false command received from platform +[2025-07-01T10:07:42.596] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false command received from platform +[2025-07-01T21:16:21.858] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-01T21:16:21.883] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-01T21:16:21.885] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-01T21:16:21.888] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-07-02T03:23:36.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-02 03:23:36 +[2025-07-02T04:36:52.331] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-02T04:36:52.335] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-02T04:36:52.338] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-02T04:36:52.340] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-07-02T21:10:53.168] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-07-02T21:10:58.531] [INFO] monitorLogs - buildTasks - params undefined +[2025-07-02T21:10:58.536] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-07-02T21:10:58.537] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-07-02T21:10:58.537] [INFO] monitorLogs - profile: { + 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 +} +[2025-07-02T21:10:58.541] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-07-02T21:10:58.543] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-07-03T03:23:00.542Z +[2025-07-02T21:10:58.544] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-07-02T19:28:00.544Z +[2025-07-02T21:10:58.545] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '5:23', name: 'luxOff' }, + { value: 1, start_time: '21:28', name: 'luxOn' } +] +[2025-07-02T21:10:58.546] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-07-02T21:10:58.547] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-07-02T21:10:58.547] [INFO] monitorLogs - profile: { + 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 +} +[2025-07-02T21:10:58.550] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-07-02T21:10:58.550] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-07-03T03:23:00.550Z +[2025-07-02T21:10:58.551] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-07-02T19:28:00.551Z +[2025-07-02T21:10:58.552] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '5:23', name: 'luxOff' }, + { value: 1, start_time: '21:28', name: 'luxOn' } +] +[2025-07-02T21:10:58.553] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-07-02T21:10:58.554] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-07-02T21:10:58.554] [INFO] monitorLogs - profile: { + 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 +} +[2025-07-02T21:10:58.557] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-07-02T21:10:58.557] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-07-03T03:23:00.557Z +[2025-07-02T21:10:58.558] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-07-02T19:28:00.558Z +[2025-07-02T21:10:58.559] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '5:23', name: 'luxOff' }, + { value: 1, start_time: '21:28', name: 'luxOn' } +] +[2025-07-02T21:10:58.560] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-07-02T21:10:58.560] [INFO] monitorLogs - buildTasks: profile for line 4 +[2025-07-02T21:10:58.561] [INFO] monitorLogs - profile: { + 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 +} +[2025-07-02T21:10:58.563] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-07-02T21:10:58.564] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 4 2025-07-03T03:23:00.563Z +[2025-07-02T21:10:58.564] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 4 2025-07-02T19:28:00.564Z +[2025-07-02T21:10:58.565] [INFO] monitorLogs - -->time_points final 4 [ + { value: 0, start_time: '5:23', name: 'luxOff' }, + { value: 1, start_time: '21:28', name: 'luxOn' } +] +[2025-07-02T21:10:58.566] [INFO] monitorLogs - -->currentValue for relay 4 0 +[2025-07-02T21:10:58.593] [INFO] monitorLogs - tasks created: 1907 +[2025-07-02T21:10:58.596] [INFO] monitorLogs - -->FLOW bol spustený wvKJdZML6mXP4DzWBAXxwBAjxNloa5g23Ve9Y1ry 2025-04-24 +[2025-07-02T21:11:03.612] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-02T21:16:28.173] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-02T21:16:28.176] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-02T21:16:28.179] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-02T21:16:28.182] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-07-03T03:11:01.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-03 03:11:01 +[2025-07-03T04:36:55.874] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-03T04:36:55.877] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-03T04:36:55.879] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-03T04:36:55.881] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-07-03T21:02:16.885] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-03T21:02:16.892] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-03T21:02:16.894] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-03T21:02:16.896] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-07-04T03:11:03.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-04 03:11:03 +[2025-07-04T04:57:57.426] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-04T04:57:57.429] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-04T04:57:57.431] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-04T04:57:57.433] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-07-04T21:12:33.721] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-04T21:12:33.730] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-04T21:12:33.732] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-04T21:12:33.734] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-07-05T03:11:04.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-05 03:11:04 +[2025-07-05T04:40:15.242] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-05T04:40:15.245] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-05T04:40:15.247] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-05T04:40:15.249] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-07-05T21:09:18.083] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-05T21:09:18.094] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-05T21:09:18.096] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-05T21:09:18.098] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-07-06T03:11:06.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-06 03:11:06 +[2025-07-06T04:41:46.867] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-06T04:41:46.870] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-06T04:41:46.872] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-06T04:41:46.874] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-07-06T20:31:39.720] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-06T20:31:39.727] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-06T20:31:39.729] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-06T20:31:39.730] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-07-07T03:11:07.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-07 03:11:07 +[2025-07-07T04:54:31.065] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-07T04:54:31.067] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-07T04:54:31.069] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-07T04:54:31.071] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-07-07T13:19:30.252] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-07-07T13:19:35.615] [INFO] monitorLogs - buildTasks - params undefined +[2025-07-07T13:19:35.620] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-07-07T13:19:35.621] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-07-07T13:19:35.621] [INFO] monitorLogs - profile: { + 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 +} +[2025-07-07T13:19:35.626] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-07-07T13:19:35.627] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-07-08T03:27:00.626Z +[2025-07-07T13:19:35.628] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-07-07T19:26:00.628Z +[2025-07-07T13:19:35.629] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '5:27', name: 'luxOff' }, + { value: 1, start_time: '21:26', name: 'luxOn' } +] +[2025-07-07T13:19:35.630] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-07-07T13:19:35.631] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-07-07T13:19:35.631] [INFO] monitorLogs - profile: { + 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 +} +[2025-07-07T13:19:35.634] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-07-07T13:19:35.635] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-07-08T03:27:00.634Z +[2025-07-07T13:19:35.635] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-07-07T19:26:00.635Z +[2025-07-07T13:19:35.636] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '5:27', name: 'luxOff' }, + { value: 1, start_time: '21:26', name: 'luxOn' } +] +[2025-07-07T13:19:35.637] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-07-07T13:19:35.638] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-07-07T13:19:35.638] [INFO] monitorLogs - profile: { + 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 +} +[2025-07-07T13:19:35.641] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-07-07T13:19:35.642] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-07-08T03:27:00.642Z +[2025-07-07T13:19:35.643] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-07-07T19:26:00.643Z +[2025-07-07T13:19:35.644] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '5:27', name: 'luxOff' }, + { value: 1, start_time: '21:26', name: 'luxOn' } +] +[2025-07-07T13:19:35.645] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-07-07T13:19:35.645] [INFO] monitorLogs - buildTasks: profile for line 4 +[2025-07-07T13:19:35.646] [INFO] monitorLogs - profile: { + 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 +} +[2025-07-07T13:19:35.648] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-07-07T13:19:35.649] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 4 2025-07-08T03:27:00.649Z +[2025-07-07T13:19:35.650] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 4 2025-07-07T19:26:00.649Z +[2025-07-07T13:19:35.650] [INFO] monitorLogs - -->time_points final 4 [ + { value: 0, start_time: '5:27', name: 'luxOff' }, + { value: 1, start_time: '21:26', name: 'luxOn' } +] +[2025-07-07T13:19:35.651] [INFO] monitorLogs - -->currentValue for relay 4 0 +[2025-07-07T13:19:35.679] [INFO] monitorLogs - tasks created: 1907 +[2025-07-07T13:19:35.682] [INFO] monitorLogs - -->FLOW bol spustený wvKJdZML6mXP4DzWBAXxwBAjxNloa5g23Ve9Y1ry 2025-07-08 +[2025-07-07T13:19:40.696] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-07T13:41:32.130] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-07-07T13:41:37.485] [INFO] monitorLogs - buildTasks - params undefined +[2025-07-07T13:41:37.490] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-07-07T13:41:37.491] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-07-07T13:41:37.492] [INFO] monitorLogs - profile: { + 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 +} +[2025-07-07T13:41:37.496] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-07-07T13:41:37.497] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-07-08T03:27:00.496Z +[2025-07-07T13:41:37.499] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-07-07T19:26:00.498Z +[2025-07-07T13:41:37.499] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '5:27', name: 'luxOff' }, + { value: 1, start_time: '21:26', name: 'luxOn' } +] +[2025-07-07T13:41:37.501] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-07-07T13:41:37.501] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-07-07T13:41:37.502] [INFO] monitorLogs - profile: { + 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 +} +[2025-07-07T13:41:37.504] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-07-07T13:41:37.505] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-07-08T03:27:00.505Z +[2025-07-07T13:41:37.506] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-07-07T19:26:00.506Z +[2025-07-07T13:41:37.506] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '5:27', name: 'luxOff' }, + { value: 1, start_time: '21:26', name: 'luxOn' } +] +[2025-07-07T13:41:37.507] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-07-07T13:41:37.508] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-07-07T13:41:37.509] [INFO] monitorLogs - profile: { + 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 +} +[2025-07-07T13:41:37.511] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-07-07T13:41:37.512] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-07-08T03:27:00.511Z +[2025-07-07T13:41:37.512] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-07-07T19:26:00.512Z +[2025-07-07T13:41:37.513] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '5:27', name: 'luxOff' }, + { value: 1, start_time: '21:26', name: 'luxOn' } +] +[2025-07-07T13:41:37.514] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-07-07T13:41:37.515] [INFO] monitorLogs - buildTasks: profile for line 4 +[2025-07-07T13:41:37.515] [INFO] monitorLogs - profile: { + 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 +} +[2025-07-07T13:41:37.517] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-07-07T13:41:37.518] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 4 2025-07-08T03:27:00.518Z +[2025-07-07T13:41:37.519] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 4 2025-07-07T19:26:00.519Z +[2025-07-07T13:41:37.519] [INFO] monitorLogs - -->time_points final 4 [ + { value: 0, start_time: '5:27', name: 'luxOff' }, + { value: 1, start_time: '21:26', name: 'luxOn' } +] +[2025-07-07T13:41:37.520] [INFO] monitorLogs - -->currentValue for relay 4 0 +[2025-07-07T13:41:37.548] [INFO] monitorLogs - tasks created: 1907 +[2025-07-07T13:41:37.551] [INFO] monitorLogs - -->FLOW bol spustený wvKJdZML6mXP4DzWBAXxwBAjxNloa5g23Ve9Y1ry 2025-07-08 +[2025-07-07T13:41:42.568] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-07T21:09:53.527] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-07T21:09:53.540] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-07T21:09:53.543] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-07T21:09:53.546] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-07-08T03:41:40.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-08 03:41:40 +[2025-07-08T04:59:11.432] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-08T04:59:11.434] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-08T04:59:11.436] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-08T04:59:11.438] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-07-08T20:45:49.844] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-08T20:45:49.866] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-08T20:45:49.869] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-08T20:45:49.871] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-07-09T03:41:42.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-09 03:41:42 +[2025-07-09T05:10:10.781] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-09T05:10:10.784] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-09T05:10:10.786] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-09T05:10:10.788] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-07-09T21:07:37.616] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-09T21:07:37.623] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-09T21:07:37.625] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-09T21:07:37.627] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-07-10T02:24:03.632] [INFO] monitorLogs - MQTT client error Error: connect ECONNREFUSED 192.168.252.1:1883 + at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1159:16) { + errno: -111, + code: 'ECONNREFUSED', + syscall: 'connect', + address: '192.168.252.1', + port: 1883 +} +[2025-07-10T03:41:43.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-10 03:41:43 +[2025-07-10T04:47:34.143] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-10T04:47:34.146] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-10T04:47:34.148] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-10T04:47:34.150] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-07-10T07:31:36.163] [INFO] monitorLogs - turnLine on - (line, SETTINGS.maintenance_mode) 0 true command received from platform +[2025-07-10T21:03:15.594] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-10T21:03:15.614] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-10T21:03:15.617] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-10T21:03:15.619] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-07-11T03:41:45.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-11 03:41:45 +[2025-07-11T04:49:14.792] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-11T04:49:14.795] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-11T04:49:14.797] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-11T04:49:14.799] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-07-11T21:06:47.691] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-11T21:06:47.699] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-11T21:06:47.702] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-11T21:06:47.704] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-07-12T03:41:46.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-12 03:41:46 +[2025-07-12T04:49:40.132] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-12T04:49:40.146] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-12T04:49:40.148] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-12T04:49:40.151] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-07-12T21:03:58.292] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-12T21:03:58.302] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-12T21:03:58.304] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-12T21:03:58.307] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-07-13T03:41:48.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-13 03:41:48 +[2025-07-13T04:51:36.578] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-13T04:51:36.581] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-13T04:51:36.584] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-13T04:51:36.586] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-07-13T21:05:25.619] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-13T21:05:25.638] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-13T21:05:25.640] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-13T21:05:25.642] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-07-14T03:41:49.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-14 03:41:49 +[2025-07-14T04:50:12.337] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-14T04:50:12.341] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-14T04:50:12.343] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-14T04:50:12.345] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-07-14T21:04:55.820] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-14T21:04:55.828] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-14T21:04:55.830] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-14T21:04:55.832] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-07-15T03:41:51.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-15 03:41:51 +[2025-07-15T04:52:11.673] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-15T04:52:11.676] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-15T04:52:11.679] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-15T04:52:11.682] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-07-15T20:55:51.722] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-15T20:55:51.742] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-15T20:55:51.745] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-15T20:55:51.747] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-07-16T03:41:52.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-16 03:41:52 +[2025-07-16T04:51:36.791] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-16T04:51:36.793] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-16T04:51:36.795] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-16T04:51:36.798] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-07-16T20:46:47.159] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-16T20:46:47.168] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-16T20:46:47.170] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-16T20:46:47.172] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-07-17T03:41:54.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-17 03:41:54 +[2025-07-17T04:57:23.619] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-17T04:57:23.623] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-17T04:57:23.625] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-17T04:57:23.627] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-07-17T20:56:39.553] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-17T20:56:39.572] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-17T20:56:39.574] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-17T20:56:39.576] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-07-18T03:41:55.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-18 03:41:55 +[2025-07-18T05:19:09.232] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-18T05:19:09.235] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-18T05:19:09.237] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-18T05:19:09.239] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-07-18T21:02:38.717] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-18T21:02:38.730] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-18T21:02:38.732] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-18T21:02:38.734] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-07-19T03:41:57.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-19 03:41:57 +[2025-07-19T05:00:19.288] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-19T05:00:19.291] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-19T05:00:19.293] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-19T05:00:19.296] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-07-19T21:01:26.207] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-19T21:01:26.215] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-19T21:01:26.217] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-19T21:01:26.219] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-07-20T03:41:58.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-20 03:41:58 +[2025-07-20T04:57:19.531] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-20T04:57:19.534] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-20T04:57:19.536] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-20T04:57:19.538] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-07-20T20:57:14.985] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-20T20:57:14.995] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-20T20:57:14.997] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-20T20:57:14.999] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-07-21T03:42:00.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-21 03:42:00 +[2025-07-21T04:55:57.655] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-21T04:55:57.657] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-21T04:55:57.659] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-21T04:55:57.661] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-07-21T19:20:06.137] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-07-21T19:20:11.488] [INFO] monitorLogs - buildTasks - params undefined +[2025-07-21T19:20:11.492] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-07-21T19:20:11.493] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-07-21T19:20:11.494] [INFO] monitorLogs - profile: { + 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 +} +[2025-07-21T19:20:11.498] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-07-21T19:20:11.500] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-07-22T03:41:00.499Z +[2025-07-21T19:20:11.501] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-07-21T19:14:00.501Z +[2025-07-21T19:20:11.502] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '5:41', name: 'luxOff' }, + { value: 1, start_time: '21:14', name: 'luxOn' } +] +[2025-07-21T19:20:11.503] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-07-21T19:20:11.504] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-07-21T19:20:11.504] [INFO] monitorLogs - profile: { + 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 +} +[2025-07-21T19:20:11.507] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-07-21T19:20:11.507] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-07-22T03:41:00.507Z +[2025-07-21T19:20:11.508] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-07-21T19:14:00.508Z +[2025-07-21T19:20:11.509] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '5:41', name: 'luxOff' }, + { value: 1, start_time: '21:14', name: 'luxOn' } +] +[2025-07-21T19:20:11.510] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-07-21T19:20:11.511] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-07-21T19:20:11.511] [INFO] monitorLogs - profile: { + 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 +} +[2025-07-21T19:20:11.514] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-07-21T19:20:11.514] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-07-22T03:41:00.514Z +[2025-07-21T19:20:11.515] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-07-21T19:14:00.515Z +[2025-07-21T19:20:11.516] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '5:41', name: 'luxOff' }, + { value: 1, start_time: '21:14', name: 'luxOn' } +] +[2025-07-21T19:20:11.517] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-07-21T19:20:11.517] [INFO] monitorLogs - buildTasks: profile for line 4 +[2025-07-21T19:20:11.518] [INFO] monitorLogs - profile: { + 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 +} +[2025-07-21T19:20:11.520] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-07-21T19:20:11.521] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 4 2025-07-22T03:41:00.521Z +[2025-07-21T19:20:11.521] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 4 2025-07-21T19:14:00.521Z +[2025-07-21T19:20:11.522] [INFO] monitorLogs - -->time_points final 4 [ + { value: 0, start_time: '5:41', name: 'luxOff' }, + { value: 1, start_time: '21:14', name: 'luxOn' } +] +[2025-07-21T19:20:11.523] [INFO] monitorLogs - -->currentValue for relay 4 0 +[2025-07-21T19:20:11.549] [INFO] monitorLogs - tasks created: 1907 +[2025-07-21T19:20:11.552] [INFO] monitorLogs - -->FLOW bol spustený wvKJdZML6mXP4DzWBAXxwBAjxNloa5g23Ve9Y1ry 2025-07-08 +[2025-07-21T19:20:16.568] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-21T20:30:49.706] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-21T20:30:49.709] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-21T20:30:49.711] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-21T20:30:49.714] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-07-22T03:20:14.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-22 03:20:14 +[2025-07-22T04:59:17.900] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-22T04:59:17.903] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-22T04:59:17.905] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-22T04:59:17.907] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-07-22T20:58:22.363] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-22T20:58:22.376] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-22T20:58:22.378] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-22T20:58:22.380] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-07-23T03:20:16.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-23 03:20:16 +[2025-07-23T04:58:05.146] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-23T04:58:05.149] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-23T04:58:05.151] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-23T04:58:05.154] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-07-23T20:55:38.508] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-23T20:55:38.516] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-23T20:55:38.518] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-23T20:55:38.520] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-07-24T03:20:17.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-24 03:20:17 +[2025-07-24T05:03:20.547] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-24T05:03:20.549] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-24T05:03:20.552] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-24T05:03:20.554] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-07-24T20:42:38.502] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-24T20:42:38.513] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-24T20:42:38.515] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-24T20:42:38.517] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-07-25T03:20:19.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-25 03:20:19 +[2025-07-25T05:05:52.190] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-25T05:05:52.193] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-25T05:05:52.195] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-25T05:05:52.198] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-07-25T20:42:48.653] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-25T20:42:48.659] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-25T20:42:48.661] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-25T20:42:48.664] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-07-26T03:20:20.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-26 03:20:20 +[2025-07-26T05:05:28.786] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-26T05:05:28.788] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-26T05:05:28.790] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-26T05:05:28.792] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-07-26T20:46:46.825] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-26T20:46:46.854] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-26T20:46:46.857] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-26T20:46:46.861] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-07-27T03:20:22.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-27 03:20:22 +[2025-07-27T05:09:48.957] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-27T05:09:48.960] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-27T05:09:48.963] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-27T05:09:48.966] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-07-27T20:31:47.089] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-27T20:31:47.096] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-27T20:31:47.098] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-27T20:31:47.100] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-07-28T03:20:23.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-28 03:20:23 +[2025-07-28T05:10:46.380] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-28T05:10:46.383] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-28T05:10:46.385] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-28T05:10:46.387] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-07-28T20:40:41.246] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-28T20:40:41.265] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-28T20:40:41.267] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-28T20:40:41.269] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-07-29T03:20:25.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-29 03:20:25 +[2025-07-29T05:10:02.900] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-29T05:10:02.903] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-29T05:10:02.905] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-29T05:10:02.907] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-07-29T12:19:38.732] [INFO] monitorLogs - MQTT client error Error: connect ECONNREFUSED 192.168.252.1:1883 + at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1159:16) { + errno: -111, + code: 'ECONNREFUSED', + syscall: 'connect', + address: '192.168.252.1', + port: 1883 +} +[2025-07-29T20:46:38.810] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-29T20:46:38.818] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-29T20:46:38.820] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-29T20:46:38.822] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-07-30T03:20:26.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-30 03:20:26 +[2025-07-30T05:09:13.228] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-30T05:09:13.231] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-30T05:09:13.233] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-30T05:09:13.236] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-07-30T20:41:12.901] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-30T20:41:12.912] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-30T20:41:12.914] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-30T20:41:12.916] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-07-31T03:20:28.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-31 03:20:28 +[2025-07-31T05:09:20.577] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-31T05:09:20.580] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-31T05:09:20.582] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-31T05:09:20.583] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-07-31T20:43:39.852] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-31T20:43:39.859] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-31T20:43:39.861] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-31T20:43:39.863] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-08-01T03:20:29.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-01 03:20:29 +[2025-08-01T05:12:11.935] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-01T05:12:11.937] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-01T05:12:11.939] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-01T05:12:11.941] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-08-01T20:24:34.963] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-01T20:24:34.970] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-01T20:24:34.978] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-01T20:24:34.980] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-08-02T03:20:31.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-02 03:20:31 +[2025-08-02T05:14:29.629] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-02T05:14:29.632] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-02T05:14:29.634] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-02T05:14:29.636] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-08-02T20:34:51.510] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-02T20:34:51.521] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-02T20:34:51.523] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-02T20:34:51.525] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-08-03T03:20:32.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-03 03:20:32 +[2025-08-03T05:24:43.192] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-03T05:24:43.195] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-03T05:24:43.197] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-03T05:24:43.199] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-08-03T20:37:36.203] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-03T20:37:36.210] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-03T20:37:36.213] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-03T20:37:36.215] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-08-04T03:20:34.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-04 03:20:34 +[2025-08-04T05:16:54.078] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-04T05:16:54.082] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-04T05:16:54.084] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-04T05:16:54.085] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-08-04T20:39:42.525] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-04T20:39:42.537] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-04T20:39:42.540] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-04T20:39:42.542] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-08-05T03:20:35.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-05 03:20:35 +[2025-08-05T05:21:26.363] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-05T05:21:26.365] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-05T05:21:26.367] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-05T05:21:26.369] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-08-05T16:10:43.146] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-08-05T16:10:48.521] [INFO] monitorLogs - buildTasks - params undefined +[2025-08-05T16:10:48.525] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-08-05T16:10:48.526] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-08-05T16:10:48.527] [INFO] monitorLogs - profile: { + 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 +} +[2025-08-05T16:10:48.531] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-08-05T16:10:48.533] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-08-06T04:01:00.532Z +[2025-08-05T16:10:48.534] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-08-05T18:55:00.534Z +[2025-08-05T16:10:48.535] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '6:1', name: 'luxOff' }, + { value: 1, start_time: '20:55', name: 'luxOn' } +] +[2025-08-05T16:10:48.536] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-08-05T16:10:48.537] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-08-05T16:10:48.537] [INFO] monitorLogs - profile: { + 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 +} +[2025-08-05T16:10:48.540] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-08-05T16:10:48.540] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-08-06T04:01:00.540Z +[2025-08-05T16:10:48.541] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-08-05T18:55:00.541Z +[2025-08-05T16:10:48.542] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '6:1', name: 'luxOff' }, + { value: 1, start_time: '20:55', name: 'luxOn' } +] +[2025-08-05T16:10:48.543] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-08-05T16:10:48.544] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-08-05T16:10:48.544] [INFO] monitorLogs - profile: { + 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 +} +[2025-08-05T16:10:48.546] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-08-05T16:10:48.547] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-08-06T04:01:00.547Z +[2025-08-05T16:10:48.548] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-08-05T18:55:00.548Z +[2025-08-05T16:10:48.549] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '6:1', name: 'luxOff' }, + { value: 1, start_time: '20:55', name: 'luxOn' } +] +[2025-08-05T16:10:48.549] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-08-05T16:10:48.550] [INFO] monitorLogs - buildTasks: profile for line 4 +[2025-08-05T16:10:48.551] [INFO] monitorLogs - profile: { + 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 +} +[2025-08-05T16:10:48.553] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-08-05T16:10:48.553] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 4 2025-08-06T04:01:00.553Z +[2025-08-05T16:10:48.554] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 4 2025-08-05T18:55:00.554Z +[2025-08-05T16:10:48.555] [INFO] monitorLogs - -->time_points final 4 [ + { value: 0, start_time: '6:1', name: 'luxOff' }, + { value: 1, start_time: '20:55', name: 'luxOn' } +] +[2025-08-05T16:10:48.556] [INFO] monitorLogs - -->currentValue for relay 4 0 +[2025-08-05T16:10:48.583] [INFO] monitorLogs - tasks created: 1907 +[2025-08-05T16:10:48.585] [INFO] monitorLogs - -->FLOW bol spustený wvKJdZML6mXP4DzWBAXxwBAjxNloa5g23Ve9Y1ry 2025-07-08 +[2025-08-05T16:10:53.602] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-05T20:34:40.048] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-05T20:34:40.056] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-05T20:34:40.059] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-05T20:34:40.062] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-08-06T03:10:51.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-06 03:10:51 +[2025-08-06T05:19:56.668] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-06T05:19:56.672] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-06T05:19:56.674] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-06T05:19:56.676] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-08-06T13:37:29.136] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-08-06T13:37:34.495] [INFO] monitorLogs - buildTasks - params undefined +[2025-08-06T13:37:34.499] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-08-06T13:37:34.500] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-08-06T13:37:34.501] [INFO] monitorLogs - profile: { + 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 +} +[2025-08-06T13:37:34.505] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-08-06T13:37:34.506] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-08-07T04:02:00.505Z +[2025-08-06T13:37:34.508] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-08-06T18:53:00.507Z +[2025-08-06T13:37:34.508] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '6:2', name: 'luxOff' }, + { value: 1, start_time: '20:53', name: 'luxOn' } +] +[2025-08-06T13:37:34.510] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-08-06T13:37:34.510] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-08-06T13:37:34.511] [INFO] monitorLogs - profile: { + 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 +} +[2025-08-06T13:37:34.514] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-08-06T13:37:34.515] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-08-07T04:02:00.515Z +[2025-08-06T13:37:34.516] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-08-06T18:53:00.516Z +[2025-08-06T13:37:34.516] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '6:2', name: 'luxOff' }, + { value: 1, start_time: '20:53', name: 'luxOn' } +] +[2025-08-06T13:37:34.517] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-08-06T13:37:34.518] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-08-06T13:37:34.519] [INFO] monitorLogs - profile: { + 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 +} +[2025-08-06T13:37:34.521] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-08-06T13:37:34.522] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-08-07T04:02:00.521Z +[2025-08-06T13:37:34.522] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-08-06T18:53:00.522Z +[2025-08-06T13:37:34.523] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '6:2', name: 'luxOff' }, + { value: 1, start_time: '20:53', name: 'luxOn' } +] +[2025-08-06T13:37:34.524] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-08-06T13:37:34.525] [INFO] monitorLogs - buildTasks: profile for line 4 +[2025-08-06T13:37:34.525] [INFO] monitorLogs - profile: { + 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 +} +[2025-08-06T13:37:34.527] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-08-06T13:37:34.528] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 4 2025-08-07T04:02:00.528Z +[2025-08-06T13:37:34.529] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 4 2025-08-06T18:53:00.529Z +[2025-08-06T13:37:34.529] [INFO] monitorLogs - -->time_points final 4 [ + { value: 0, start_time: '6:2', name: 'luxOff' }, + { value: 1, start_time: '20:53', name: 'luxOn' } +] +[2025-08-06T13:37:34.530] [INFO] monitorLogs - -->currentValue for relay 4 0 +[2025-08-06T13:37:34.557] [INFO] monitorLogs - tasks created: 1907 +[2025-08-06T13:37:34.560] [INFO] monitorLogs - -->FLOW bol spustený wvKJdZML6mXP4DzWBAXxwBAjxNloa5g23Ve9Y1ry 2025-08-08 +[2025-08-06T13:37:39.576] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-06T20:32:52.553] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-06T20:32:52.562] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-06T20:32:52.565] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-06T20:32:52.567] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-08-07T03:37:37.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-07 03:37:37 +[2025-08-07T05:22:10.903] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-07T05:22:10.906] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-07T05:22:10.908] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-07T05:22:10.911] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-08-07T20:33:55.706] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-07T20:33:55.713] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-07T20:33:55.716] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-07T20:33:55.718] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-08-08T03:37:38.022] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-08 03:37:38 +[2025-08-08T05:20:24.278] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-08T05:20:24.281] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-08T05:20:24.283] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-08T05:20:24.286] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-08-08T20:32:16.776] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-08T20:32:16.784] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-08T20:32:16.786] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-08T20:32:16.788] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-08-09T03:37:40.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-09 03:37:40 +[2025-08-09T05:23:40.239] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-09T05:23:40.241] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-09T05:23:40.244] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-09T05:23:40.246] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-08-09T20:33:32.701] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-09T20:33:32.708] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-09T20:33:32.711] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-09T20:33:32.713] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-08-10T03:37:41.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-10 03:37:41 +[2025-08-10T05:23:59.603] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-10T05:23:59.605] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-10T05:23:59.607] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-10T05:23:59.610] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-08-10T20:29:32.935] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-10T20:29:32.943] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-10T20:29:32.946] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-10T20:29:32.948] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-08-11T03:37:43.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-11 03:37:43 +[2025-08-11T05:26:06.352] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-11T05:26:06.355] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-11T05:26:06.357] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-11T05:26:06.359] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-08-11T20:30:10.287] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-11T20:30:10.295] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-11T20:30:10.297] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-11T20:30:10.299] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-08-12T03:37:45.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-12 03:37:45 +[2025-08-12T05:25:57.159] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-12T05:25:57.162] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-12T05:25:57.164] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-12T05:25:57.166] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-08-12T20:25:55.637] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-12T20:25:55.647] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-12T20:25:55.649] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-12T20:25:55.651] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-08-13T03:37:46.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-13 03:37:46 +[2025-08-13T05:26:53.557] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-13T05:26:53.560] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-13T05:26:53.562] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-13T05:26:53.564] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-08-13T20:22:32.750] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-13T20:22:32.757] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-13T20:22:32.760] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-13T20:22:32.762] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-08-14T03:37:48.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-14 03:37:48 +[2025-08-14T05:30:13.707] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-14T05:30:13.711] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-14T05:30:13.713] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-14T05:30:13.715] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-08-14T20:21:31.085] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-14T20:21:31.093] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-14T20:21:31.095] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-14T20:21:31.097] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-08-15T03:37:50.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-15 03:37:50 +[2025-08-15T05:31:00.405] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-15T05:31:00.407] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-15T05:31:00.410] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-15T05:31:00.412] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-08-15T20:19:29.604] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-15T20:19:29.612] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-15T20:19:29.614] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-15T20:19:29.616] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-08-16T03:37:51.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-16 03:37:51 +[2025-08-16T05:33:29.448] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-16T05:33:29.450] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-16T05:33:29.453] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-16T05:33:29.455] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-08-16T20:15:56.915] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-16T20:15:56.922] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-16T20:15:56.925] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-16T20:15:56.927] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-08-17T03:37:53.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-17 03:37:53 +[2025-08-17T05:36:07.053] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-17T05:36:07.056] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-17T05:36:07.058] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-17T05:36:07.060] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-08-17T20:15:20.427] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-17T20:15:20.435] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-17T20:15:20.437] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-17T20:15:20.439] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-08-18T03:37:55.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-18 03:37:55 +[2025-08-18T05:36:42.153] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-18T05:36:42.156] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-18T05:36:42.158] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-18T05:36:42.160] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-08-18T20:17:32.220] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-18T20:17:32.228] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-18T20:17:32.230] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-18T20:17:32.233] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-08-19T03:37:56.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-19 03:37:56 +[2025-08-19T05:36:03.001] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-19T05:36:03.004] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-19T05:36:03.006] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-19T05:36:03.008] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-08-19T20:13:57.410] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-19T20:13:57.416] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-19T20:13:57.418] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-19T20:13:57.420] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-08-20T03:37:58.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-20 03:37:58 +[2025-08-20T05:37:22.885] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-20T05:37:22.888] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-20T05:37:22.891] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-20T05:37:22.893] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-08-20T08:56:13.214] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-08-20T08:56:18.571] [INFO] monitorLogs - buildTasks - params undefined +[2025-08-20T08:56:18.576] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-08-20T08:56:18.578] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-08-20T08:56:18.578] [INFO] monitorLogs - profile: { + 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 +} +[2025-08-20T08:56:18.583] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-08-20T08:56:18.584] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-08-21T04:22:00.583Z +[2025-08-20T08:56:18.586] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-08-20T18:29:00.586Z +[2025-08-20T08:56:18.587] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '6:22', name: 'luxOff' }, + { value: 1, start_time: '20:29', name: 'luxOn' } +] +[2025-08-20T08:56:18.588] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-08-20T08:56:18.589] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-08-20T08:56:18.589] [INFO] monitorLogs - profile: { + 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 +} +[2025-08-20T08:56:18.592] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-08-20T08:56:18.593] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-08-21T04:22:00.593Z +[2025-08-20T08:56:18.594] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-08-20T18:29:00.594Z +[2025-08-20T08:56:18.595] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '6:22', name: 'luxOff' }, + { value: 1, start_time: '20:29', name: 'luxOn' } +] +[2025-08-20T08:56:18.596] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-08-20T08:56:18.597] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-08-20T08:56:18.597] [INFO] monitorLogs - profile: { + 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 +} +[2025-08-20T08:56:18.600] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-08-20T08:56:18.601] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-08-21T04:22:00.600Z +[2025-08-20T08:56:18.601] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-08-20T18:29:00.601Z +[2025-08-20T08:56:18.602] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '6:22', name: 'luxOff' }, + { value: 1, start_time: '20:29', name: 'luxOn' } +] +[2025-08-20T08:56:18.603] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-08-20T08:56:18.604] [INFO] monitorLogs - buildTasks: profile for line 4 +[2025-08-20T08:56:18.605] [INFO] monitorLogs - profile: { + 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 +} +[2025-08-20T08:56:18.607] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-08-20T08:56:18.608] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 4 2025-08-21T04:22:00.608Z +[2025-08-20T08:56:18.609] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 4 2025-08-20T18:29:00.609Z +[2025-08-20T08:56:18.610] [INFO] monitorLogs - -->time_points final 4 [ + { value: 0, start_time: '6:22', name: 'luxOff' }, + { value: 1, start_time: '20:29', name: 'luxOn' } +] +[2025-08-20T08:56:18.611] [INFO] monitorLogs - -->currentValue for relay 4 0 +[2025-08-20T08:56:18.632] [INFO] monitorLogs - tasks created: 1907 +[2025-08-20T08:56:18.637] [INFO] monitorLogs - -->FLOW bol spustený wvKJdZML6mXP4DzWBAXxwBAjxNloa5g23Ve9Y1ry 2025-08-08 +[2025-08-20T08:56:23.650] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-20T11:52:17.901] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false command received from platform +[2025-08-20T11:52:26.527] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false command received from platform +[2025-08-20T11:52:32.286] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false command received from platform +[2025-08-20T11:52:37.725] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false command received from platform +[2025-08-20T11:59:40.117] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-08-20T11:59:45.482] [INFO] monitorLogs - buildTasks - params undefined +[2025-08-20T11:59:45.487] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-08-20T11:59:45.488] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-08-20T11:59:45.488] [INFO] monitorLogs - profile: { + 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 +} +[2025-08-20T11:59:45.493] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-08-20T11:59:45.494] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-08-21T04:22:00.493Z +[2025-08-20T11:59:45.495] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-08-20T18:29:00.495Z +[2025-08-20T11:59:45.496] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '6:22', name: 'luxOff' }, + { value: 1, start_time: '20:29', name: 'luxOn' } +] +[2025-08-20T11:59:45.497] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-08-20T11:59:45.498] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-08-20T11:59:45.499] [INFO] monitorLogs - profile: { + 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 +} +[2025-08-20T11:59:45.501] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-08-20T11:59:45.502] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-08-21T04:22:00.501Z +[2025-08-20T11:59:45.502] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-08-20T18:29:00.502Z +[2025-08-20T11:59:45.503] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '6:22', name: 'luxOff' }, + { value: 1, start_time: '20:29', name: 'luxOn' } +] +[2025-08-20T11:59:45.504] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-08-20T11:59:45.505] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-08-20T11:59:45.505] [INFO] monitorLogs - profile: { + 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 +} +[2025-08-20T11:59:45.508] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-08-20T11:59:45.508] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-08-21T04:22:00.508Z +[2025-08-20T11:59:45.509] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-08-20T18:29:00.509Z +[2025-08-20T11:59:45.510] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '6:22', name: 'luxOff' }, + { value: 1, start_time: '20:29', name: 'luxOn' } +] +[2025-08-20T11:59:45.511] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-08-20T11:59:45.511] [INFO] monitorLogs - buildTasks: profile for line 4 +[2025-08-20T11:59:45.512] [INFO] monitorLogs - profile: { + 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 +} +[2025-08-20T11:59:45.514] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-08-20T11:59:45.515] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 4 2025-08-21T04:22:00.515Z +[2025-08-20T11:59:45.515] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 4 2025-08-20T18:29:00.515Z +[2025-08-20T11:59:45.516] [INFO] monitorLogs - -->time_points final 4 [ + { value: 0, start_time: '6:22', name: 'luxOff' }, + { value: 1, start_time: '20:29', name: 'luxOn' } +] +[2025-08-20T11:59:45.517] [INFO] monitorLogs - -->currentValue for relay 4 0 +[2025-08-20T11:59:45.544] [INFO] monitorLogs - tasks created: 1907 +[2025-08-20T11:59:45.546] [INFO] monitorLogs - -->FLOW bol spustený wvKJdZML6mXP4DzWBAXxwBAjxNloa5g23Ve9Y1ry 2025-08-08 +[2025-08-20T11:59:50.563] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-20T11:59:50.868] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-20T11:59:51.173] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-20T11:59:51.478] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false aplikovany bod profilu +[2025-08-20T20:09:56.424] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-20T20:09:56.433] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-20T20:09:56.435] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-20T20:09:56.438] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-08-21T03:59:47.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-21 03:59:47 +[2025-08-21T05:42:00.604] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-21T05:42:00.607] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-21T05:42:00.609] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-21T05:42:00.611] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-08-21T15:54:25.171] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-08-21T15:54:30.529] [INFO] monitorLogs - buildTasks - params undefined +[2025-08-21T15:54:30.534] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-08-21T15:54:30.535] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-08-21T15:54:30.535] [INFO] monitorLogs - profile: { + 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 +} +[2025-08-21T15:54:30.540] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-08-21T15:54:30.541] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-08-22T04:23:00.540Z +[2025-08-21T15:54:30.542] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-08-21T18:27:00.542Z +[2025-08-21T15:54:30.543] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '6:23', name: 'luxOff' }, + { value: 1, start_time: '20:27', name: 'luxOn' } +] +[2025-08-21T15:54:30.544] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-08-21T15:54:30.545] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-08-21T15:54:30.546] [INFO] monitorLogs - profile: { + 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 +} +[2025-08-21T15:54:30.548] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-08-21T15:54:30.549] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-08-22T04:23:00.549Z +[2025-08-21T15:54:30.550] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-08-21T18:27:00.550Z +[2025-08-21T15:54:30.550] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '6:23', name: 'luxOff' }, + { value: 1, start_time: '20:27', name: 'luxOn' } +] +[2025-08-21T15:54:30.551] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-08-21T15:54:30.552] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-08-21T15:54:30.553] [INFO] monitorLogs - profile: { + 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 +} +[2025-08-21T15:54:30.555] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-08-21T15:54:30.555] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-08-22T04:23:00.555Z +[2025-08-21T15:54:30.556] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-08-21T18:27:00.556Z +[2025-08-21T15:54:30.557] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '6:23', name: 'luxOff' }, + { value: 1, start_time: '20:27', name: 'luxOn' } +] +[2025-08-21T15:54:30.558] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-08-21T15:54:30.559] [INFO] monitorLogs - buildTasks: profile for line 4 +[2025-08-21T15:54:30.559] [INFO] monitorLogs - profile: { + 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 +} +[2025-08-21T15:54:30.561] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-08-21T15:54:30.562] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 4 2025-08-22T04:23:00.562Z +[2025-08-21T15:54:30.563] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 4 2025-08-21T18:27:00.563Z +[2025-08-21T15:54:30.563] [INFO] monitorLogs - -->time_points final 4 [ + { value: 0, start_time: '6:23', name: 'luxOff' }, + { value: 1, start_time: '20:27', name: 'luxOn' } +] +[2025-08-21T15:54:30.564] [INFO] monitorLogs - -->currentValue for relay 4 0 +[2025-08-21T15:54:30.591] [INFO] monitorLogs - tasks created: 1907 +[2025-08-21T15:54:30.595] [INFO] monitorLogs - -->FLOW bol spustený wvKJdZML6mXP4DzWBAXxwBAjxNloa5g23Ve9Y1ry 2025-08-08 +[2025-08-21T15:54:35.611] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-21T19:51:21.806] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-21T19:51:21.814] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-21T19:51:21.817] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-21T19:51:21.820] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-08-22T03:54:34.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-22 03:54:34 +[2025-08-22T05:47:20.337] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-22T05:47:20.340] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-22T05:47:20.342] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-22T05:47:20.344] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-08-22T20:06:10.633] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-22T20:06:10.649] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-22T20:06:10.651] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-22T20:06:10.653] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-08-23T03:54:35.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-23 03:54:35 +[2025-08-23T05:46:08.500] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-23T05:46:08.504] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-23T05:46:08.507] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-23T05:46:08.509] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-08-23T20:02:50.820] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-23T20:02:50.828] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-23T20:02:50.831] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-23T20:02:50.833] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-08-24T03:54:37.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-24 03:54:37 +[2025-08-24T05:45:47.112] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-24T05:45:47.116] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-24T05:45:47.119] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-24T05:45:47.121] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-08-24T20:04:05.986] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-24T20:04:06.004] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-24T20:04:06.007] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-24T20:04:06.009] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-08-25T03:54:38.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-25 03:54:38 +[2025-08-25T05:48:01.629] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-25T05:48:01.638] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-25T05:48:01.640] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-25T05:48:01.642] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-08-25T19:59:03.004] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-25T19:59:03.025] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-25T19:59:03.028] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-25T19:59:03.030] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-08-26T03:54:39.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-26 03:54:39 +[2025-08-26T05:47:36.982] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-26T05:47:36.986] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-26T05:47:36.988] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-26T05:47:36.990] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-08-26T19:57:47.841] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-26T19:57:47.856] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-26T19:57:47.859] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-26T19:57:47.861] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-08-27T03:54:41.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-27 03:54:41 +[2025-08-27T05:50:17.368] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-27T05:50:17.372] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-27T05:50:17.374] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-27T05:50:17.376] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-08-27T19:56:25.065] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-27T19:56:25.083] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-27T19:56:25.085] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-27T19:56:25.087] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-08-28T03:54:42.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-28 03:54:42 +[2025-08-28T05:48:55.811] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-28T05:48:55.815] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-28T05:48:55.817] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-28T05:48:55.819] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-08-28T19:52:59.922] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-28T19:52:59.933] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-28T19:52:59.935] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-28T19:52:59.938] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-08-29T03:54:44.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-29 03:54:44 +[2025-08-29T05:53:39.380] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-29T05:53:39.384] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-29T05:53:39.386] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-29T05:53:39.388] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-08-29T19:41:17.571] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-29T19:41:17.577] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-29T19:41:17.579] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-29T19:41:17.581] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-08-30T03:54:46.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-30 03:54:46 +[2025-08-30T05:54:41.370] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-30T05:54:41.373] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-30T05:54:41.375] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-30T05:54:41.377] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-08-30T19:32:21.311] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-30T19:32:21.318] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-30T19:32:21.320] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-30T19:32:21.322] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-08-31T03:54:47.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-31 03:54:47 +[2025-08-31T06:12:05.542] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-31T06:12:05.545] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-31T06:12:05.547] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-31T06:12:05.550] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-08-31T19:51:04.699] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-31T19:51:04.716] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-31T19:51:04.718] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-31T19:51:04.720] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-09-01T03:54:49.014] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-01 03:54:49 +[2025-09-01T05:59:15.074] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-01T05:59:15.077] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-01T05:59:15.080] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-01T05:59:15.081] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-09-01T19:46:55.681] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-01T19:46:55.695] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-01T19:46:55.697] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-01T19:46:55.699] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-09-02T03:54:50.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-02 03:54:50 +[2025-09-02T05:56:05.501] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-02T05:56:05.504] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-02T05:56:05.507] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-02T05:56:05.509] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-09-02T19:36:40.175] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-02T19:36:40.192] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-02T19:36:40.194] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-02T19:36:40.196] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-09-03T03:54:52.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-03 03:54:52 +[2025-09-03T06:04:06.594] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-03T06:04:06.598] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-03T06:04:06.600] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-03T06:04:06.602] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-09-03T19:42:13.923] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-03T19:42:13.936] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-03T19:42:13.938] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-03T19:42:13.941] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-09-04T03:54:53.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-04 03:54:53 +[2025-09-04T06:01:38.869] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-04T06:01:38.878] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-04T06:01:38.880] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-04T06:01:38.882] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-09-04T19:40:21.014] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-04T19:40:21.029] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-04T19:40:21.031] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-04T19:40:21.033] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-09-05T03:54:55.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-05 03:54:55 +[2025-09-05T06:01:59.134] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-05T06:01:59.143] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-05T06:01:59.145] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-05T06:01:59.147] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-09-05T19:37:16.465] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-05T19:37:16.472] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-05T19:37:16.474] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-05T19:37:16.476] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-09-06T03:54:57.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-06 03:54:57 +[2025-09-06T06:16:23.728] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-06T06:16:23.735] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-06T06:16:23.738] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-06T06:16:23.740] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-09-06T18:06:42.142] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-09-06T18:06:47.511] [INFO] monitorLogs - buildTasks - params undefined +[2025-09-06T18:06:47.516] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-09-06T18:06:47.517] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-09-06T18:06:47.517] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-06T18:06:47.521] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-06T18:06:47.523] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-09-07T04:46:00.522Z +[2025-09-06T18:06:47.524] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-09-06T17:55:00.524Z +[2025-09-06T18:06:47.525] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '6:46', name: 'luxOff' }, + { value: 1, start_time: '19:55', name: 'luxOn' } +] +[2025-09-06T18:06:47.526] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-09-06T18:06:47.527] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-09-06T18:06:47.527] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-06T18:06:47.530] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-06T18:06:47.531] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-09-07T04:46:00.530Z +[2025-09-06T18:06:47.531] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-09-06T17:55:00.531Z +[2025-09-06T18:06:47.532] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '6:46', name: 'luxOff' }, + { value: 1, start_time: '19:55', name: 'luxOn' } +] +[2025-09-06T18:06:47.534] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-09-06T18:06:47.535] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-09-06T18:06:47.535] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-06T18:06:47.538] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-06T18:06:47.538] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-09-07T04:46:00.538Z +[2025-09-06T18:06:47.539] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-09-06T17:55:00.539Z +[2025-09-06T18:06:47.540] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '6:46', name: 'luxOff' }, + { value: 1, start_time: '19:55', name: 'luxOn' } +] +[2025-09-06T18:06:47.541] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-09-06T18:06:47.541] [INFO] monitorLogs - buildTasks: profile for line 4 +[2025-09-06T18:06:47.542] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-06T18:06:47.544] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-06T18:06:47.545] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 4 2025-09-07T04:46:00.545Z +[2025-09-06T18:06:47.546] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 4 2025-09-06T17:55:00.545Z +[2025-09-06T18:06:47.546] [INFO] monitorLogs - -->time_points final 4 [ + { value: 0, start_time: '6:46', name: 'luxOff' }, + { value: 1, start_time: '19:55', name: 'luxOn' } +] +[2025-09-06T18:06:47.547] [INFO] monitorLogs - -->currentValue for relay 4 0 +[2025-09-06T18:06:47.550] [INFO] monitorLogs - tasks created: 287 +[2025-09-06T18:06:47.552] [INFO] monitorLogs - -->FLOW bol spustený wvKJdZML6mXP4DzWBAXxwBAjxNloa5g23Ve9Y1ry 2025-08-08 +[2025-09-06T18:06:52.555] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-06T19:35:37.413] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-06T19:35:37.416] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-06T19:35:37.419] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-06T19:35:37.421] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-09-07T03:06:49.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-07 03:06:49 +[2025-09-07T06:03:44.027] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-07T06:03:44.036] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-07T06:03:44.038] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-07T06:03:44.040] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-09-07T19:31:47.622] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-07T19:31:47.649] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-07T19:31:47.651] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-07T19:31:47.653] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-09-07T23:33:43.320] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-09-07T23:33:48.705] [INFO] monitorLogs - buildTasks - params undefined +[2025-09-07T23:33:48.710] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-09-07T23:33:48.711] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-09-07T23:33:48.712] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-07T23:33:48.717] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-07T23:33:48.719] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-09-08T04:47:00.718Z +[2025-09-07T23:33:48.720] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-09-08T17:53:00.720Z +[2025-09-07T23:33:48.721] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '6:47', name: 'luxOff' }, + { value: 1, start_time: '19:53', name: 'luxOn' } +] +[2025-09-07T23:33:48.723] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-09-07T23:33:48.724] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-09-07T23:33:48.724] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-07T23:33:48.727] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-07T23:33:48.728] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-09-08T04:47:00.728Z +[2025-09-07T23:33:48.729] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-09-08T17:53:00.729Z +[2025-09-07T23:33:48.729] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '6:47', name: 'luxOff' }, + { value: 1, start_time: '19:53', name: 'luxOn' } +] +[2025-09-07T23:33:48.731] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-09-07T23:33:48.731] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-09-07T23:33:48.732] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-07T23:33:48.735] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-07T23:33:48.735] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-09-08T04:47:00.735Z +[2025-09-07T23:33:48.736] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-09-08T17:53:00.736Z +[2025-09-07T23:33:48.737] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '6:47', name: 'luxOff' }, + { value: 1, start_time: '19:53', name: 'luxOn' } +] +[2025-09-07T23:33:48.738] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-09-07T23:33:48.739] [INFO] monitorLogs - buildTasks: profile for line 4 +[2025-09-07T23:33:48.740] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-07T23:33:48.742] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-07T23:33:48.743] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 4 2025-09-08T04:47:00.742Z +[2025-09-07T23:33:48.744] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 4 2025-09-08T17:53:00.744Z +[2025-09-07T23:33:48.744] [INFO] monitorLogs - -->time_points final 4 [ + { value: 0, start_time: '6:47', name: 'luxOff' }, + { value: 1, start_time: '19:53', name: 'luxOn' } +] +[2025-09-07T23:33:48.746] [INFO] monitorLogs - -->currentValue for relay 4 1 +[2025-09-07T23:33:48.749] [INFO] monitorLogs - tasks created: 287 +[2025-09-07T23:33:48.752] [INFO] monitorLogs - -->FLOW bol spustený wvKJdZML6mXP4DzWBAXxwBAjxNloa5g23Ve9Y1ry 2025-08-08 +[2025-09-07T23:33:53.755] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-07T23:35:33.911] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-09-07T23:35:39.309] [INFO] monitorLogs - buildTasks - params undefined +[2025-09-07T23:35:39.314] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-09-07T23:35:39.315] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-09-07T23:35:39.316] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-07T23:35:39.321] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-07T23:35:39.322] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-09-08T04:47:00.321Z +[2025-09-07T23:35:39.324] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-09-08T17:53:00.323Z +[2025-09-07T23:35:39.325] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '6:47', name: 'luxOff' }, + { value: 1, start_time: '19:53', name: 'luxOn' } +] +[2025-09-07T23:35:39.326] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-09-07T23:35:39.327] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-09-07T23:35:39.327] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-07T23:35:39.330] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-07T23:35:39.331] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-09-08T04:47:00.331Z +[2025-09-07T23:35:39.332] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-09-08T17:53:00.332Z +[2025-09-07T23:35:39.333] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '6:47', name: 'luxOff' }, + { value: 1, start_time: '19:53', name: 'luxOn' } +] +[2025-09-07T23:35:39.334] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-09-07T23:35:39.335] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-09-07T23:35:39.335] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-07T23:35:39.338] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-07T23:35:39.339] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-09-08T04:47:00.339Z +[2025-09-07T23:35:39.340] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-09-08T17:53:00.339Z +[2025-09-07T23:35:39.340] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '6:47', name: 'luxOff' }, + { value: 1, start_time: '19:53', name: 'luxOn' } +] +[2025-09-07T23:35:39.341] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-09-07T23:35:39.342] [INFO] monitorLogs - buildTasks: profile for line 4 +[2025-09-07T23:35:39.343] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-07T23:35:39.345] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-07T23:35:39.346] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 4 2025-09-08T04:47:00.346Z +[2025-09-07T23:35:39.347] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 4 2025-09-08T17:53:00.347Z +[2025-09-07T23:35:39.348] [INFO] monitorLogs - -->time_points final 4 [ + { value: 0, start_time: '6:47', name: 'luxOff' }, + { value: 1, start_time: '19:53', name: 'luxOn' } +] +[2025-09-07T23:35:39.349] [INFO] monitorLogs - -->currentValue for relay 4 1 +[2025-09-07T23:35:39.353] [INFO] monitorLogs - tasks created: 287 +[2025-09-07T23:35:39.355] [INFO] monitorLogs - -->FLOW bol spustený wvKJdZML6mXP4DzWBAXxwBAjxNloa5g23Ve9Y1ry 2025-08-08 +[2025-09-07T23:35:44.357] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-08T03:35:41.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-08 03:35:41 +[2025-09-08T06:07:04.017] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-08T06:07:04.023] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-08T06:07:04.025] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-08T06:07:04.027] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-09-08T16:02:31.164] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-09-08T16:02:36.515] [INFO] monitorLogs - buildTasks - params undefined +[2025-09-08T16:02:36.520] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-09-08T16:02:36.521] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-09-08T16:02:36.522] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-08T16:02:36.526] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-08T16:02:36.527] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-09-09T04:48:00.526Z +[2025-09-08T16:02:36.529] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-09-08T17:51:00.528Z +[2025-09-08T16:02:36.529] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '6:48', name: 'luxOff' }, + { value: 1, start_time: '19:51', name: 'luxOn' } +] +[2025-09-08T16:02:36.530] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-09-08T16:02:36.531] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-09-08T16:02:36.532] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-08T16:02:36.534] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-08T16:02:36.535] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-09-09T04:48:00.535Z +[2025-09-08T16:02:36.536] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-09-08T17:51:00.536Z +[2025-09-08T16:02:36.537] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '6:48', name: 'luxOff' }, + { value: 1, start_time: '19:51', name: 'luxOn' } +] +[2025-09-08T16:02:36.537] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-09-08T16:02:36.538] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-09-08T16:02:36.539] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-08T16:02:36.541] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-08T16:02:36.542] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-09-09T04:48:00.541Z +[2025-09-08T16:02:36.542] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-09-08T17:51:00.542Z +[2025-09-08T16:02:36.543] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '6:48', name: 'luxOff' }, + { value: 1, start_time: '19:51', name: 'luxOn' } +] +[2025-09-08T16:02:36.544] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-09-08T16:02:36.545] [INFO] monitorLogs - buildTasks: profile for line 4 +[2025-09-08T16:02:36.545] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-08T16:02:36.547] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-08T16:02:36.548] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 4 2025-09-09T04:48:00.548Z +[2025-09-08T16:02:36.549] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 4 2025-09-08T17:51:00.549Z +[2025-09-08T16:02:36.549] [INFO] monitorLogs - -->time_points final 4 [ + { value: 0, start_time: '6:48', name: 'luxOff' }, + { value: 1, start_time: '19:51', name: 'luxOn' } +] +[2025-09-08T16:02:36.550] [INFO] monitorLogs - -->currentValue for relay 4 0 +[2025-09-08T16:02:36.576] [INFO] monitorLogs - tasks created: 1907 +[2025-09-08T16:02:36.579] [INFO] monitorLogs - -->FLOW bol spustený wvKJdZML6mXP4DzWBAXxwBAjxNloa5g23Ve9Y1ry 2025-08-08 +[2025-09-08T16:02:41.593] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-08T19:31:14.024] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-08T19:31:14.030] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-08T19:31:14.033] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-08T19:31:14.035] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-09-09T03:02:39.014] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-09 03:02:39 +[2025-09-09T06:08:27.197] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-09T06:08:27.202] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-09T06:08:27.204] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-09T06:08:27.206] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-09-09T19:27:01.347] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-09T19:27:01.354] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-09T19:27:01.356] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-09T19:27:01.357] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-09-10T03:02:41.085] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-10 03:02:41 +[2025-09-10T06:10:47.329] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-10T06:10:47.335] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-10T06:10:47.337] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-10T06:10:47.339] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-09-10T09:15:32.994] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-09-10T09:15:38.358] [INFO] monitorLogs - buildTasks - params undefined +[2025-09-10T09:15:38.362] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-09-10T09:15:38.363] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-09-10T09:15:38.364] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-10T09:15:38.368] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-10T09:15:38.369] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-09-11T04:51:00.369Z +[2025-09-10T09:15:38.371] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-09-10T17:46:00.371Z +[2025-09-10T09:15:38.371] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '6:51', name: 'luxOff' }, + { value: 1, start_time: '19:46', name: 'luxOn' } +] +[2025-09-10T09:15:38.373] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-09-10T09:15:38.373] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-09-10T09:15:38.374] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-10T09:15:38.376] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-10T09:15:38.377] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-09-11T04:51:00.377Z +[2025-09-10T09:15:38.378] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-09-10T17:46:00.378Z +[2025-09-10T09:15:38.379] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '6:51', name: 'luxOff' }, + { value: 1, start_time: '19:46', name: 'luxOn' } +] +[2025-09-10T09:15:38.380] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-09-10T09:15:38.380] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-09-10T09:15:38.381] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-10T09:15:38.383] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-10T09:15:38.384] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-09-11T04:51:00.384Z +[2025-09-10T09:15:38.384] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-09-10T17:46:00.384Z +[2025-09-10T09:15:38.385] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '6:51', name: 'luxOff' }, + { value: 1, start_time: '19:46', name: 'luxOn' } +] +[2025-09-10T09:15:38.386] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-09-10T09:15:38.387] [INFO] monitorLogs - buildTasks: profile for line 4 +[2025-09-10T09:15:38.387] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-10T09:15:38.390] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-10T09:15:38.390] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 4 2025-09-11T04:51:00.390Z +[2025-09-10T09:15:38.392] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 4 2025-09-10T17:46:00.391Z +[2025-09-10T09:15:38.393] [INFO] monitorLogs - -->time_points final 4 [ + { value: 0, start_time: '6:51', name: 'luxOff' }, + { value: 1, start_time: '19:46', name: 'luxOn' } +] +[2025-09-10T09:15:38.394] [INFO] monitorLogs - -->currentValue for relay 4 0 +[2025-09-10T09:15:38.421] [INFO] monitorLogs - tasks created: 1907 +[2025-09-10T09:15:38.424] [INFO] monitorLogs - -->FLOW bol spustený wvKJdZML6mXP4DzWBAXxwBAjxNloa5g23Ve9Y1ry 2025-08-08 +[2025-09-10T09:15:43.439] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-10T11:38:11.690] [INFO] monitorLogs - turnLine on - (line, SETTINGS.maintenance_mode) 0 true command received from platform +[2025-09-10T11:38:19.397] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false command received from platform +[2025-09-10T11:44:05.272] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false command received from platform +[2025-09-10T11:44:12.955] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false command received from platform +[2025-09-10T16:28:09.420] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-09-10T16:28:14.782] [INFO] monitorLogs - buildTasks - params undefined +[2025-09-10T16:28:14.786] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-09-10T16:28:14.787] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-09-10T16:28:14.788] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-10T16:28:14.792] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-10T16:28:14.793] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-09-11T04:51:00.793Z +[2025-09-10T16:28:14.795] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-09-10T17:46:00.795Z +[2025-09-10T16:28:14.796] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '6:51', name: 'luxOff' }, + { value: 1, start_time: '19:46', name: 'luxOn' } +] +[2025-09-10T16:28:14.797] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-09-10T16:28:14.798] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-09-10T16:28:14.798] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-10T16:28:14.801] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-10T16:28:14.801] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-09-11T04:51:00.801Z +[2025-09-10T16:28:14.802] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-09-10T17:46:00.802Z +[2025-09-10T16:28:14.803] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '6:51', name: 'luxOff' }, + { value: 1, start_time: '19:46', name: 'luxOn' } +] +[2025-09-10T16:28:14.804] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-09-10T16:28:14.805] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-09-10T16:28:14.805] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-10T16:28:14.807] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-10T16:28:14.808] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-09-11T04:51:00.808Z +[2025-09-10T16:28:14.809] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-09-10T17:46:00.809Z +[2025-09-10T16:28:14.809] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '6:51', name: 'luxOff' }, + { value: 1, start_time: '19:46', name: 'luxOn' } +] +[2025-09-10T16:28:14.810] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-09-10T16:28:14.811] [INFO] monitorLogs - buildTasks: profile for line 4 +[2025-09-10T16:28:14.812] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-10T16:28:14.814] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-10T16:28:14.815] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 4 2025-09-11T04:51:00.814Z +[2025-09-10T16:28:14.815] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 4 2025-09-10T17:46:00.815Z +[2025-09-10T16:28:14.816] [INFO] monitorLogs - -->time_points final 4 [ + { value: 0, start_time: '6:51', name: 'luxOff' }, + { value: 1, start_time: '19:46', name: 'luxOn' } +] +[2025-09-10T16:28:14.818] [INFO] monitorLogs - -->currentValue for relay 4 0 +[2025-09-10T16:28:14.844] [INFO] monitorLogs - tasks created: 1907 +[2025-09-10T16:28:14.847] [INFO] monitorLogs - -->FLOW bol spustený wvKJdZML6mXP4DzWBAXxwBAjxNloa5g23Ve9Y1ry 2025-08-08 +[2025-09-10T16:28:19.863] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-10T19:15:40.269] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-10T19:15:40.276] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-10T19:15:40.278] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-10T19:15:40.280] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-09-11T03:28:17.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-11 03:28:17 +[2025-09-11T06:16:55.310] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-11T06:16:55.327] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-11T06:16:55.329] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-11T06:16:55.331] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-09-11T19:26:37.019] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-11T19:26:37.029] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-11T19:26:37.032] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-11T19:26:37.034] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-09-12T03:28:18.018] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-12 03:28:18 +[2025-09-12T06:12:31.567] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-12T06:12:31.573] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-12T06:12:31.575] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-12T06:12:31.577] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-09-12T19:13:30.563] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-12T19:13:30.577] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-12T19:13:30.579] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-12T19:13:30.588] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-09-13T03:28:20.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-13 03:28:20 +[2025-09-13T06:28:04.568] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-13T06:28:04.571] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-13T06:28:04.573] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-13T06:28:04.575] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-09-13T19:16:52.152] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-13T19:16:52.157] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-13T19:16:52.159] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-13T19:16:52.161] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-09-14T03:28:21.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-14 03:28:21 +[2025-09-14T06:28:09.826] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-14T06:28:09.829] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-14T06:28:09.831] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-14T06:28:09.833] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-09-14T19:17:47.247] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-14T19:17:47.255] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-14T19:17:47.257] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-14T19:17:47.258] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-09-14T22:46:14.691] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-09-14T22:46:20.053] [INFO] monitorLogs - buildTasks - params undefined +[2025-09-14T22:46:20.058] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-09-14T22:46:20.059] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-09-14T22:46:20.059] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-14T22:46:20.063] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-14T22:46:20.065] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-09-15T04:57:00.064Z +[2025-09-14T22:46:20.066] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-09-15T17:38:00.066Z +[2025-09-14T22:46:20.067] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '6:57', name: 'luxOff' }, + { value: 1, start_time: '19:38', name: 'luxOn' } +] +[2025-09-14T22:46:20.068] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-09-14T22:46:20.069] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-09-14T22:46:20.070] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-14T22:46:20.072] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-14T22:46:20.073] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-09-15T04:57:00.073Z +[2025-09-14T22:46:20.074] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-09-15T17:38:00.073Z +[2025-09-14T22:46:20.074] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '6:57', name: 'luxOff' }, + { value: 1, start_time: '19:38', name: 'luxOn' } +] +[2025-09-14T22:46:20.075] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-09-14T22:46:20.076] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-09-14T22:46:20.077] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-14T22:46:20.079] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-14T22:46:20.079] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-09-15T04:57:00.079Z +[2025-09-14T22:46:20.080] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-09-15T17:38:00.080Z +[2025-09-14T22:46:20.081] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '6:57', name: 'luxOff' }, + { value: 1, start_time: '19:38', name: 'luxOn' } +] +[2025-09-14T22:46:20.082] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-09-14T22:46:20.083] [INFO] monitorLogs - buildTasks: profile for line 4 +[2025-09-14T22:46:20.083] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-14T22:46:20.085] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-14T22:46:20.086] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 4 2025-09-15T04:57:00.086Z +[2025-09-14T22:46:20.087] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 4 2025-09-15T17:38:00.087Z +[2025-09-14T22:46:20.088] [INFO] monitorLogs - -->time_points final 4 [ + { value: 0, start_time: '6:57', name: 'luxOff' }, + { value: 1, start_time: '19:38', name: 'luxOn' } +] +[2025-09-14T22:46:20.089] [INFO] monitorLogs - -->currentValue for relay 4 1 +[2025-09-14T22:46:20.115] [INFO] monitorLogs - tasks created: 1907 +[2025-09-14T22:46:20.117] [INFO] monitorLogs - -->FLOW bol spustený wvKJdZML6mXP4DzWBAXxwBAjxNloa5g23Ve9Y1ry 2025-08-08 +[2025-09-14T22:46:25.130] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-15T03:46:22.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-15 03:46:22 +[2025-09-15T06:15:27.978] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-15T06:15:27.984] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-15T06:15:27.986] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-15T06:15:27.988] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-09-15T19:17:56.426] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-15T19:17:56.432] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-15T19:17:56.434] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-15T19:17:56.436] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-09-16T03:46:23.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-16 03:46:23 +[2025-09-16T06:32:33.237] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-16T06:32:33.241] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-16T06:32:33.243] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-16T06:32:33.245] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-09-16T19:11:59.055] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-16T19:11:59.061] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-16T19:11:59.063] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-16T19:11:59.065] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-09-17T03:46:25.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-17 03:46:25 +[2025-09-17T06:23:56.514] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-17T06:23:56.517] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-17T06:23:56.519] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-17T06:23:56.521] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-09-17T19:14:20.335] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-17T19:14:20.344] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-17T19:14:20.346] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-17T19:14:20.348] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-09-17T20:36:12.586] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-09-17T20:36:17.942] [INFO] monitorLogs - buildTasks - params undefined +[2025-09-17T20:36:17.947] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-09-17T20:36:17.948] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-09-17T20:36:17.949] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-17T20:36:17.953] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-17T20:36:17.954] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-09-18T05:01:00.953Z +[2025-09-17T20:36:17.955] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-09-18T17:32:00.955Z +[2025-09-17T20:36:17.956] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:1', name: 'luxOff' }, + { value: 1, start_time: '19:32', name: 'luxOn' } +] +[2025-09-17T20:36:17.957] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-09-17T20:36:17.958] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-09-17T20:36:17.959] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-17T20:36:17.961] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-17T20:36:17.962] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-09-18T05:01:00.962Z +[2025-09-17T20:36:17.963] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-09-18T17:32:00.962Z +[2025-09-17T20:36:17.963] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:1', name: 'luxOff' }, + { value: 1, start_time: '19:32', name: 'luxOn' } +] +[2025-09-17T20:36:17.964] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-09-17T20:36:17.965] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-09-17T20:36:17.966] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-17T20:36:17.968] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-17T20:36:17.968] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-09-18T05:01:00.968Z +[2025-09-17T20:36:17.969] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-09-18T17:32:00.969Z +[2025-09-17T20:36:17.970] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:1', name: 'luxOff' }, + { value: 1, start_time: '19:32', name: 'luxOn' } +] +[2025-09-17T20:36:17.971] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-09-17T20:36:17.971] [INFO] monitorLogs - buildTasks: profile for line 4 +[2025-09-17T20:36:17.972] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-17T20:36:17.974] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-17T20:36:17.975] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 4 2025-09-18T05:01:00.975Z +[2025-09-17T20:36:17.976] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 4 2025-09-18T17:32:00.975Z +[2025-09-17T20:36:17.976] [INFO] monitorLogs - -->time_points final 4 [ + { value: 0, start_time: '7:1', name: 'luxOff' }, + { value: 1, start_time: '19:32', name: 'luxOn' } +] +[2025-09-17T20:36:17.977] [INFO] monitorLogs - -->currentValue for relay 4 1 +[2025-09-17T20:36:18.004] [INFO] monitorLogs - tasks created: 1907 +[2025-09-17T20:36:18.006] [INFO] monitorLogs - -->FLOW bol spustený wvKJdZML6mXP4DzWBAXxwBAjxNloa5g23Ve9Y1ry 2025-08-08 +[2025-09-17T20:36:23.023] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-18T03:36:19.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-18 03:36:19 +[2025-09-18T06:21:46.890] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-18T06:21:46.896] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-18T06:21:46.898] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-18T06:21:46.900] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-09-18T19:11:07.215] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-18T19:11:07.221] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-18T19:11:07.223] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-18T19:11:07.225] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-09-19T03:36:21.014] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-19 03:36:21 +[2025-09-19T06:20:41.513] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-19T06:20:41.516] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-19T06:20:41.520] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-19T06:20:41.522] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-09-19T11:15:44.526] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-09-19T11:15:49.888] [INFO] monitorLogs - buildTasks - params undefined +[2025-09-19T11:15:49.893] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-09-19T11:15:49.894] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-09-19T11:15:49.894] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-19T11:15:49.898] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-19T11:15:49.900] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-09-20T05:04:00.899Z +[2025-09-19T11:15:49.901] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-09-19T17:27:00.901Z +[2025-09-19T11:15:49.902] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:4', name: 'luxOff' }, + { value: 1, start_time: '19:27', name: 'luxOn' } +] +[2025-09-19T11:15:49.903] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-09-19T11:15:49.904] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-09-19T11:15:49.904] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-19T11:15:49.907] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-19T11:15:49.907] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-09-20T05:04:00.907Z +[2025-09-19T11:15:49.908] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-09-19T17:27:00.908Z +[2025-09-19T11:15:49.909] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:4', name: 'luxOff' }, + { value: 1, start_time: '19:27', name: 'luxOn' } +] +[2025-09-19T11:15:49.910] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-09-19T11:15:49.911] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-09-19T11:15:49.911] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-19T11:15:49.913] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-19T11:15:49.914] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-09-20T05:04:00.914Z +[2025-09-19T11:15:49.915] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-09-19T17:27:00.915Z +[2025-09-19T11:15:49.915] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:4', name: 'luxOff' }, + { value: 1, start_time: '19:27', name: 'luxOn' } +] +[2025-09-19T11:15:49.917] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-09-19T11:15:49.917] [INFO] monitorLogs - buildTasks: profile for line 4 +[2025-09-19T11:15:49.918] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-19T11:15:49.920] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-19T11:15:49.921] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 4 2025-09-20T05:04:00.921Z +[2025-09-19T11:15:49.922] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 4 2025-09-19T17:27:00.921Z +[2025-09-19T11:15:49.922] [INFO] monitorLogs - -->time_points final 4 [ + { value: 0, start_time: '7:4', name: 'luxOff' }, + { value: 1, start_time: '19:27', name: 'luxOn' } +] +[2025-09-19T11:15:49.923] [INFO] monitorLogs - -->currentValue for relay 4 0 +[2025-09-19T11:15:49.950] [INFO] monitorLogs - tasks created: 1907 +[2025-09-19T11:15:49.953] [INFO] monitorLogs - -->FLOW bol spustený wvKJdZML6mXP4DzWBAXxwBAjxNloa5g23Ve9Y1ry 2025-08-08 +[2025-09-19T11:15:54.968] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-19T19:09:49.012] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-19T19:09:49.017] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-19T19:09:49.020] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-19T19:09:49.022] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-09-20T03:15:52.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-20 03:15:52 +[2025-09-20T06:23:31.385] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-20T06:23:31.391] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-20T06:23:31.393] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-20T06:23:31.395] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-09-20T19:06:57.551] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-20T19:06:57.558] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-20T19:06:57.560] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-20T19:06:57.561] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-09-21T01:29:20.998] [INFO] monitorLogs - MQTT client error Error: connect ECONNREFUSED 192.168.252.1:1883 + at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1159:16) { + errno: -111, + code: 'ECONNREFUSED', + syscall: 'connect', + address: '192.168.252.1', + port: 1883 +} +[2025-09-21T03:15:53.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-21 03:15:53 +[2025-09-21T06:24:54.476] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-21T06:24:54.482] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-21T06:24:54.484] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-21T06:24:54.486] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-09-21T18:08:21.046] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-09-21T18:08:26.395] [INFO] monitorLogs - buildTasks - params undefined +[2025-09-21T18:08:26.400] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-09-21T18:08:26.401] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-09-21T18:08:26.402] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-21T18:08:26.406] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-21T18:08:26.407] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-09-22T05:07:00.406Z +[2025-09-21T18:08:26.409] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-09-21T17:23:00.408Z +[2025-09-21T18:08:26.409] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:7', name: 'luxOff' }, + { value: 1, start_time: '19:23', name: 'luxOn' } +] +[2025-09-21T18:08:26.411] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-09-21T18:08:26.411] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-09-21T18:08:26.412] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-21T18:08:26.414] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-21T18:08:26.415] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-09-22T05:07:00.415Z +[2025-09-21T18:08:26.416] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-09-21T17:23:00.416Z +[2025-09-21T18:08:26.417] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:7', name: 'luxOff' }, + { value: 1, start_time: '19:23', name: 'luxOn' } +] +[2025-09-21T18:08:26.418] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-09-21T18:08:26.418] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-09-21T18:08:26.419] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-21T18:08:26.421] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-21T18:08:26.422] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-09-22T05:07:00.422Z +[2025-09-21T18:08:26.423] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-09-21T17:23:00.422Z +[2025-09-21T18:08:26.423] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:7', name: 'luxOff' }, + { value: 1, start_time: '19:23', name: 'luxOn' } +] +[2025-09-21T18:08:26.424] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-09-21T18:08:26.425] [INFO] monitorLogs - buildTasks: profile for line 4 +[2025-09-21T18:08:26.426] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-21T18:08:26.428] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-21T18:08:26.428] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 4 2025-09-22T05:07:00.428Z +[2025-09-21T18:08:26.429] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 4 2025-09-21T17:23:00.429Z +[2025-09-21T18:08:26.430] [INFO] monitorLogs - -->time_points final 4 [ + { value: 0, start_time: '7:7', name: 'luxOff' }, + { value: 1, start_time: '19:23', name: 'luxOn' } +] +[2025-09-21T18:08:26.431] [INFO] monitorLogs - -->currentValue for relay 4 0 +[2025-09-21T18:08:26.457] [INFO] monitorLogs - tasks created: 1907 +[2025-09-21T18:08:26.459] [INFO] monitorLogs - -->FLOW bol spustený wvKJdZML6mXP4DzWBAXxwBAjxNloa5g23Ve9Y1ry 2025-08-08 +[2025-09-21T18:08:31.473] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-21T19:03:27.661] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-21T19:03:27.664] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-21T19:03:27.666] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-21T19:03:27.668] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-09-22T03:08:29.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-22 03:08:29 +[2025-09-22T06:26:22.577] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-22T06:26:22.583] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-22T06:26:22.585] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-22T06:26:22.588] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-09-22T18:57:43.372] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-22T18:57:43.379] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-22T18:57:43.381] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-22T18:57:43.383] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-09-23T03:08:30.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-23 03:08:30 +[2025-09-23T06:31:01.400] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-23T06:31:01.405] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-23T06:31:01.409] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-23T06:31:01.411] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-09-23T13:03:05.557] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-09-23T13:03:10.911] [INFO] monitorLogs - buildTasks - params undefined +[2025-09-23T13:03:10.916] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-09-23T13:03:10.917] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-09-23T13:03:10.918] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-23T13:03:10.922] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-23T13:03:10.923] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-09-24T05:09:00.922Z +[2025-09-23T13:03:10.925] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-09-23T17:19:00.924Z +[2025-09-23T13:03:10.925] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:9', name: 'luxOff' }, + { value: 1, start_time: '19:19', name: 'luxOn' } +] +[2025-09-23T13:03:10.927] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-09-23T13:03:10.927] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-09-23T13:03:10.928] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-23T13:03:10.930] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-23T13:03:10.931] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-09-24T05:09:00.931Z +[2025-09-23T13:03:10.932] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-09-23T17:19:00.932Z +[2025-09-23T13:03:10.933] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:9', name: 'luxOff' }, + { value: 1, start_time: '19:19', name: 'luxOn' } +] +[2025-09-23T13:03:10.934] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-09-23T13:03:10.934] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-09-23T13:03:10.935] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-23T13:03:10.937] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-23T13:03:10.938] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-09-24T05:09:00.937Z +[2025-09-23T13:03:10.938] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-09-23T17:19:00.938Z +[2025-09-23T13:03:10.939] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:9', name: 'luxOff' }, + { value: 1, start_time: '19:19', name: 'luxOn' } +] +[2025-09-23T13:03:10.940] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-09-23T13:03:10.941] [INFO] monitorLogs - buildTasks: profile for line 4 +[2025-09-23T13:03:10.941] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-23T13:03:10.943] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-23T13:03:10.944] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 4 2025-09-24T05:09:00.944Z +[2025-09-23T13:03:10.945] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 4 2025-09-23T17:19:00.945Z +[2025-09-23T13:03:10.945] [INFO] monitorLogs - -->time_points final 4 [ + { value: 0, start_time: '7:9', name: 'luxOff' }, + { value: 1, start_time: '19:19', name: 'luxOn' } +] +[2025-09-23T13:03:10.946] [INFO] monitorLogs - -->currentValue for relay 4 0 +[2025-09-23T13:03:10.973] [INFO] monitorLogs - tasks created: 1907 +[2025-09-23T13:03:10.976] [INFO] monitorLogs - -->FLOW bol spustený wvKJdZML6mXP4DzWBAXxwBAjxNloa5g23Ve9Y1ry 2025-08-08 +[2025-09-23T13:03:15.992] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-23T14:29:37.518] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-09-23T14:29:42.868] [INFO] monitorLogs - buildTasks - params undefined +[2025-09-23T14:29:42.873] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-09-23T14:29:42.874] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-09-23T14:29:42.874] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-23T14:29:42.879] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-23T14:29:42.880] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-09-24T05:09:00.879Z +[2025-09-23T14:29:42.882] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-09-23T17:19:00.881Z +[2025-09-23T14:29:42.882] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:9', name: 'luxOff' }, + { value: 1, start_time: '19:19', name: 'luxOn' } +] +[2025-09-23T14:29:42.883] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-09-23T14:29:42.884] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-09-23T14:29:42.885] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-23T14:29:42.887] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-23T14:29:42.888] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-09-24T05:09:00.888Z +[2025-09-23T14:29:42.889] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-09-23T17:19:00.889Z +[2025-09-23T14:29:42.890] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:9', name: 'luxOff' }, + { value: 1, start_time: '19:19', name: 'luxOn' } +] +[2025-09-23T14:29:42.891] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-09-23T14:29:42.891] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-09-23T14:29:42.892] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-23T14:29:42.894] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-23T14:29:42.895] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-09-24T05:09:00.895Z +[2025-09-23T14:29:42.896] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-09-23T17:19:00.895Z +[2025-09-23T14:29:42.896] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:9', name: 'luxOff' }, + { value: 1, start_time: '19:19', name: 'luxOn' } +] +[2025-09-23T14:29:42.897] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-09-23T14:29:42.898] [INFO] monitorLogs - buildTasks: profile for line 4 +[2025-09-23T14:29:42.898] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-23T14:29:42.901] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-23T14:29:42.901] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 4 2025-09-24T05:09:00.901Z +[2025-09-23T14:29:42.902] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 4 2025-09-23T17:19:00.902Z +[2025-09-23T14:29:42.903] [INFO] monitorLogs - -->time_points final 4 [ + { value: 0, start_time: '7:9', name: 'luxOff' }, + { value: 1, start_time: '19:19', name: 'luxOn' } +] +[2025-09-23T14:29:42.904] [INFO] monitorLogs - -->currentValue for relay 4 0 +[2025-09-23T14:29:42.930] [INFO] monitorLogs - tasks created: 1907 +[2025-09-23T14:29:42.933] [INFO] monitorLogs - -->FLOW bol spustený wvKJdZML6mXP4DzWBAXxwBAjxNloa5g23Ve9Y1ry 2025-08-08 +[2025-09-23T14:29:47.946] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-23T18:49:34.210] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-23T18:49:34.217] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-23T18:49:34.220] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-23T18:49:34.222] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-09-24T03:29:45.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-24 03:29:45 +[2025-09-24T06:45:33.738] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-24T06:45:33.743] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-24T06:45:33.745] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-24T06:45:33.748] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-09-24T18:48:37.951] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-24T18:48:37.966] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-24T18:48:37.968] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-24T18:48:37.970] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-09-25T03:29:47.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-25 03:29:47 +[2025-09-25T06:49:04.003] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-25T06:49:04.007] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-25T06:49:04.009] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-25T06:49:04.011] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-09-25T16:24:53.151] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-09-25T16:24:58.507] [INFO] monitorLogs - buildTasks - params undefined +[2025-09-25T16:24:58.512] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-09-25T16:24:58.513] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-09-25T16:24:58.514] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-25T16:24:58.518] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-25T16:24:58.519] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-09-26T05:12:00.519Z +[2025-09-25T16:24:58.521] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-09-25T17:14:00.521Z +[2025-09-25T16:24:58.521] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:12', name: 'luxOff' }, + { value: 1, start_time: '19:14', name: 'luxOn' } +] +[2025-09-25T16:24:58.523] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-09-25T16:24:58.524] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-09-25T16:24:58.525] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-25T16:24:58.527] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-25T16:24:58.528] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-09-26T05:12:00.528Z +[2025-09-25T16:24:58.529] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-09-25T17:14:00.529Z +[2025-09-25T16:24:58.530] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:12', name: 'luxOff' }, + { value: 1, start_time: '19:14', name: 'luxOn' } +] +[2025-09-25T16:24:58.531] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-09-25T16:24:58.531] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-09-25T16:24:58.532] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-25T16:24:58.534] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-25T16:24:58.535] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-09-26T05:12:00.535Z +[2025-09-25T16:24:58.535] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-09-25T17:14:00.535Z +[2025-09-25T16:24:58.536] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:12', name: 'luxOff' }, + { value: 1, start_time: '19:14', name: 'luxOn' } +] +[2025-09-25T16:24:58.537] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-09-25T16:24:58.538] [INFO] monitorLogs - buildTasks: profile for line 4 +[2025-09-25T16:24:58.538] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-25T16:24:58.541] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-25T16:24:58.541] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 4 2025-09-26T05:12:00.541Z +[2025-09-25T16:24:58.542] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 4 2025-09-25T17:14:00.542Z +[2025-09-25T16:24:58.542] [INFO] monitorLogs - -->time_points final 4 [ + { value: 0, start_time: '7:12', name: 'luxOff' }, + { value: 1, start_time: '19:14', name: 'luxOn' } +] +[2025-09-25T16:24:58.543] [INFO] monitorLogs - -->currentValue for relay 4 0 +[2025-09-25T16:24:58.569] [INFO] monitorLogs - tasks created: 1907 +[2025-09-25T16:24:58.571] [INFO] monitorLogs - -->FLOW bol spustený wvKJdZML6mXP4DzWBAXxwBAjxNloa5g23Ve9Y1ry 2025-08-08 +[2025-09-25T16:25:03.586] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-25T16:28:35.806] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-09-25T16:28:41.155] [INFO] monitorLogs - buildTasks - params undefined +[2025-09-25T16:28:41.160] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-09-25T16:28:41.161] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-09-25T16:28:41.162] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-25T16:28:41.167] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-25T16:28:41.169] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-09-26T05:12:00.168Z +[2025-09-25T16:28:41.170] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-09-25T17:14:00.170Z +[2025-09-25T16:28:41.171] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:12', name: 'luxOff' }, + { value: 1, start_time: '19:14', name: 'luxOn' } +] +[2025-09-25T16:28:41.172] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-09-25T16:28:41.173] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-09-25T16:28:41.174] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-25T16:28:41.176] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-25T16:28:41.177] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-09-26T05:12:00.177Z +[2025-09-25T16:28:41.178] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-09-25T17:14:00.177Z +[2025-09-25T16:28:41.178] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:12', name: 'luxOff' }, + { value: 1, start_time: '19:14', name: 'luxOn' } +] +[2025-09-25T16:28:41.179] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-09-25T16:28:41.180] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-09-25T16:28:41.180] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-25T16:28:41.183] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-25T16:28:41.183] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-09-26T05:12:00.183Z +[2025-09-25T16:28:41.184] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-09-25T17:14:00.184Z +[2025-09-25T16:28:41.185] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:12', name: 'luxOff' }, + { value: 1, start_time: '19:14', name: 'luxOn' } +] +[2025-09-25T16:28:41.186] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-09-25T16:28:41.186] [INFO] monitorLogs - buildTasks: profile for line 4 +[2025-09-25T16:28:41.187] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-25T16:28:41.189] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-25T16:28:41.190] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 4 2025-09-26T05:12:00.190Z +[2025-09-25T16:28:41.190] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 4 2025-09-25T17:14:00.190Z +[2025-09-25T16:28:41.191] [INFO] monitorLogs - -->time_points final 4 [ + { value: 0, start_time: '7:12', name: 'luxOff' }, + { value: 1, start_time: '19:14', name: 'luxOn' } +] +[2025-09-25T16:28:41.192] [INFO] monitorLogs - -->currentValue for relay 4 0 +[2025-09-25T16:28:41.219] [INFO] monitorLogs - tasks created: 1907 +[2025-09-25T16:28:41.221] [INFO] monitorLogs - -->FLOW bol spustený wvKJdZML6mXP4DzWBAXxwBAjxNloa5g23Ve9Y1ry 2025-08-08 +[2025-09-25T16:28:46.237] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-25T18:30:50.642] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-25T18:30:50.644] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-25T18:30:50.647] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-25T18:30:50.649] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-09-26T03:28:43.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-26 03:28:43 +[2025-09-26T06:48:07.650] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-26T06:48:07.655] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-26T06:48:07.657] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-26T06:48:07.659] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-09-26T18:50:37.017] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-26T18:50:37.023] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-26T18:50:37.026] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-26T18:50:37.027] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-09-27T03:28:44.013] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-27 03:28:44 +[2025-09-27T06:42:42.847] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-27T06:42:42.853] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-27T06:42:42.856] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-27T06:42:42.857] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-09-27T18:50:37.543] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-27T18:50:37.553] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-27T18:50:37.555] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-27T18:50:37.557] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-09-28T03:28:46.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-28 03:28:46 +[2025-09-28T06:38:32.416] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-28T06:38:32.422] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-28T06:38:32.425] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-28T06:38:32.427] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-09-28T18:50:17.587] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-28T18:50:17.594] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-28T18:50:17.596] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-28T18:50:17.599] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-09-29T03:28:47.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-29 03:28:47 +[2025-09-29T06:35:52.152] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-29T06:35:52.158] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-29T06:35:52.160] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-29T06:35:52.162] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-09-29T18:46:35.111] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-29T18:46:35.117] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-29T18:46:35.119] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-29T18:46:35.120] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-09-30T03:28:48.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-30 03:28:48 +[2025-09-30T06:36:36.152] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-30T06:36:36.158] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-30T06:36:36.160] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-30T06:36:36.161] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-09-30T18:43:51.234] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-30T18:43:51.239] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-30T18:43:51.241] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-30T18:43:51.243] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-10-01T03:28:49.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-01 03:28:49 +[2025-10-01T06:43:25.401] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-01T06:43:25.406] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-01T06:43:25.409] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-01T06:43:25.410] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-10-01T18:43:15.244] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-01T18:43:15.246] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-01T18:43:15.248] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-01T18:43:15.250] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-10-02T03:28:50.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-02 03:28:50 +[2025-10-02T06:41:51.667] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-02T06:41:51.673] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-02T06:41:51.675] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-02T06:41:51.677] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-10-02T18:42:26.319] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-02T18:42:26.328] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-02T18:42:26.330] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-02T18:42:26.332] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-10-03T03:28:51.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-03 03:28:51 +[2025-10-03T06:41:38.620] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-03T06:41:38.625] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-03T06:41:38.627] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-03T06:41:38.629] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-10-03T14:44:19.936] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-03T14:44:25.293] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-03T14:44:25.297] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-03T14:44:25.299] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-03T14:44:25.299] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-03T14:44:25.303] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-03T14:44:25.305] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-10-04T05:24:00.304Z +[2025-10-03T14:44:25.306] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-10-03T16:58:00.306Z +[2025-10-03T14:44:25.307] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:24', name: 'luxOff' }, + { value: 1, start_time: '18:58', name: 'luxOn' } +] +[2025-10-03T14:44:25.308] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-10-03T14:44:25.309] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-03T14:44:25.309] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-03T14:44:25.312] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-03T14:44:25.312] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-10-04T05:24:00.312Z +[2025-10-03T14:44:25.313] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-10-03T16:58:00.313Z +[2025-10-03T14:44:25.314] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:24', name: 'luxOff' }, + { value: 1, start_time: '18:58', name: 'luxOn' } +] +[2025-10-03T14:44:25.315] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-10-03T14:44:25.316] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-03T14:44:25.316] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-03T14:44:25.318] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-03T14:44:25.319] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-10-04T05:24:00.319Z +[2025-10-03T14:44:25.320] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-10-03T16:58:00.320Z +[2025-10-03T14:44:25.320] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:24', name: 'luxOff' }, + { value: 1, start_time: '18:58', name: 'luxOn' } +] +[2025-10-03T14:44:25.321] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-10-03T14:44:25.322] [INFO] monitorLogs - buildTasks: profile for line 4 +[2025-10-03T14:44:25.323] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-03T14:44:25.325] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-03T14:44:25.325] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 4 2025-10-04T05:24:00.325Z +[2025-10-03T14:44:25.326] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 4 2025-10-03T16:58:00.326Z +[2025-10-03T14:44:25.327] [INFO] monitorLogs - -->time_points final 4 [ + { value: 0, start_time: '7:24', name: 'luxOff' }, + { value: 1, start_time: '18:58', name: 'luxOn' } +] +[2025-10-03T14:44:25.328] [INFO] monitorLogs - -->currentValue for relay 4 0 +[2025-10-03T14:44:25.356] [INFO] monitorLogs - tasks created: 1907 +[2025-10-03T14:44:25.359] [INFO] monitorLogs - -->FLOW bol spustený wvKJdZML6mXP4DzWBAXxwBAjxNloa5g23Ve9Y1ry 2025-08-08 +[2025-10-03T14:44:30.374] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-03T18:38:58.687] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-03T18:38:58.693] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-03T18:38:58.696] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-03T18:38:58.698] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-10-04T03:44:27.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-04 03:44:27 +[2025-10-04T06:44:39.788] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-04T06:44:39.793] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-04T06:44:39.795] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-04T06:44:39.797] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-10-04T18:26:18.192] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-04T18:26:18.198] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-04T18:26:18.200] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-04T18:26:18.202] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-10-05T03:44:28.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-05 03:44:28 +[2025-10-05T06:45:35.869] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-05T06:45:35.876] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-05T06:45:35.877] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-05T06:45:35.879] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-10-05T18:32:43.751] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-05T18:32:43.758] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-05T18:32:43.761] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-05T18:32:43.762] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-10-06T03:44:30.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-06 03:44:30 +[2025-10-06T06:55:38.408] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-06T06:55:38.413] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-06T06:55:38.415] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-06T06:55:38.417] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-10-06T18:24:12.892] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-06T18:24:12.897] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-06T18:24:12.899] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-06T18:24:12.901] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-10-07T03:44:31.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-07 03:44:31 +[2025-10-07T06:50:43.724] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-07T06:50:43.729] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-07T06:50:43.731] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-07T06:50:43.733] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-10-07T18:27:37.496] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-07T18:27:37.511] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-07T18:27:37.513] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-07T18:27:37.515] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-10-08T03:44:32.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-08 03:44:32 +[2025-10-08T06:49:06.339] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-08T06:49:06.343] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-08T06:49:06.346] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-08T06:49:06.348] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-10-08T18:27:08.752] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-08T18:27:08.758] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-08T18:27:08.760] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-08T18:27:08.761] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-10-09T03:44:33.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-09 03:44:33 +[2025-10-09T07:04:44.179] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-09T07:04:44.184] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-09T07:04:44.186] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-09T07:04:44.188] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-10-09T16:36:58.097] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-09T16:37:03.465] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-09T16:37:03.469] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-09T16:37:03.470] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-09T16:37:03.471] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-09T16:37:03.476] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T16:37:03.477] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-10-10T05:32:00.476Z +[2025-10-09T16:37:03.478] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-10-09T16:45:00.478Z +[2025-10-09T16:37:03.479] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T16:37:03.480] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-10-09T16:37:03.481] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-09T16:37:03.482] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-09T16:37:03.484] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T16:37:03.485] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-10-10T05:32:00.485Z +[2025-10-09T16:37:03.485] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-10-09T16:45:00.485Z +[2025-10-09T16:37:03.486] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T16:37:03.487] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-10-09T16:37:03.488] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-09T16:37:03.488] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-09T16:37:03.491] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T16:37:03.491] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-10-10T05:32:00.491Z +[2025-10-09T16:37:03.492] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-10-09T16:45:00.492Z +[2025-10-09T16:37:03.493] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T16:37:03.494] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-10-09T16:37:03.494] [INFO] monitorLogs - buildTasks: profile for line 4 +[2025-10-09T16:37:03.495] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-09T16:37:03.497] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T16:37:03.498] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 4 2025-10-10T05:32:00.498Z +[2025-10-09T16:37:03.499] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 4 2025-10-09T16:45:00.498Z +[2025-10-09T16:37:03.499] [INFO] monitorLogs - -->time_points final 4 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T16:37:03.500] [INFO] monitorLogs - -->currentValue for relay 4 0 +[2025-10-09T16:37:03.526] [INFO] monitorLogs - tasks created: 1907 +[2025-10-09T16:37:03.529] [INFO] monitorLogs - -->FLOW bol spustený wvKJdZML6mXP4DzWBAXxwBAjxNloa5g23Ve9Y1ry 2025-08-08 +[2025-10-09T16:37:08.545] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-09T18:21:22.593] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-09T18:21:22.600] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-09T18:21:22.602] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-09T18:21:22.605] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-10-09T19:02:00.403] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-09T19:02:05.756] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-09T19:02:05.761] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-09T19:02:05.762] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-09T19:02:05.763] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-09T19:02:05.767] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T19:02:05.768] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-10-10T05:32:00.768Z +[2025-10-09T19:02:05.770] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-10-10T16:45:00.770Z +[2025-10-09T19:02:05.771] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T19:02:05.772] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-10-09T19:02:05.773] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-09T19:02:05.773] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-09T19:02:05.776] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T19:02:05.776] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-10-10T05:32:00.776Z +[2025-10-09T19:02:05.777] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-10-10T16:45:00.777Z +[2025-10-09T19:02:05.778] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T19:02:05.779] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-10-09T19:02:05.779] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-09T19:02:05.780] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-09T19:02:05.782] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T19:02:05.783] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-10-10T05:32:00.783Z +[2025-10-09T19:02:05.784] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-10-10T16:45:00.783Z +[2025-10-09T19:02:05.784] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T19:02:05.785] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-10-09T19:02:05.786] [INFO] monitorLogs - buildTasks: profile for line 4 +[2025-10-09T19:02:05.786] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-09T19:02:05.789] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T19:02:05.789] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 4 2025-10-10T05:32:00.789Z +[2025-10-09T19:02:05.790] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 4 2025-10-10T16:45:00.790Z +[2025-10-09T19:02:05.791] [INFO] monitorLogs - -->time_points final 4 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T19:02:05.792] [INFO] monitorLogs - -->currentValue for relay 4 1 +[2025-10-09T19:02:05.818] [INFO] monitorLogs - tasks created: 1907 +[2025-10-09T19:02:05.820] [INFO] monitorLogs - -->FLOW bol spustený wvKJdZML6mXP4DzWBAXxwBAjxNloa5g23Ve9Y1ry 2025-08-08 +[2025-10-09T19:02:10.834] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-10T03:02:08.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-10 03:02:08 +[2025-10-10T07:00:09.729] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-10T07:00:09.735] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-10T07:00:09.737] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-10T07:00:09.739] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-10-10T18:15:10.052] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-10T18:15:10.058] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-10T18:15:10.060] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-10T18:15:10.062] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-10-11T03:02:09.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-11 03:02:09 +[2025-10-11T06:59:52.969] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-11T06:59:52.974] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-11T06:59:52.976] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-11T06:59:52.978] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-10-11T18:21:47.767] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-11T18:21:47.772] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-11T18:21:47.774] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-11T18:21:47.776] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-10-12T03:02:10.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-12 03:02:10 +[2025-10-12T06:59:30.821] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-12T06:59:30.827] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-12T06:59:30.829] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-12T06:59:30.831] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-10-12T18:15:34.930] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-12T18:15:34.936] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-12T18:15:34.938] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-12T18:15:34.940] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-10-13T03:02:12.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-13 03:02:12 +[2025-10-13T06:57:49.794] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-13T06:57:49.799] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-13T06:57:49.801] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-13T06:57:49.803] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-10-13T18:21:34.515] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-13T18:21:34.518] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-13T18:21:34.520] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-13T18:21:34.522] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-10-14T03:02:13.013] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-14 03:02:13 +[2025-10-14T07:00:29.121] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-14T07:00:29.133] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-14T07:00:29.136] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-14T07:00:29.138] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-10-14T18:11:34.724] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-14T18:11:34.749] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-14T18:11:34.751] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-14T18:11:34.753] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-10-15T03:02:14.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-15 03:02:14 +[2025-10-15T07:05:17.808] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-15T07:05:17.814] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-15T07:05:17.817] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-15T07:05:17.818] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-10-15T08:12:42.443] [INFO] monitorLogs - turnLine on - (line, SETTINGS.maintenance_mode) 0 true command received from platform +[2025-10-15T08:13:05.469] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false command received from platform +[2025-10-15T08:13:16.661] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false command received from platform +[2025-10-15T08:13:30.659] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false command received from platform +[2025-10-15T08:13:44.180] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false command received from platform +[2025-10-15T08:15:39.698] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false command received from platform +[2025-10-15T08:15:49.618] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false command received from platform +[2025-10-15T08:15:59.538] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false command received from platform +[2025-10-15T08:16:10.146] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false command received from platform +[2025-10-15T08:16:16.187] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false command received from platform +[2025-10-15T11:40:56.144] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-15T11:41:01.525] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-15T11:41:01.530] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-15T11:41:01.531] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-15T11:41:01.532] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-15T11:41:01.536] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-15T11:41:01.538] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-10-16T05:41:00.537Z +[2025-10-15T11:41:01.539] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-10-15T16:33:00.539Z +[2025-10-15T11:41:01.540] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:41', name: 'luxOff' }, + { value: 1, start_time: '18:33', name: 'luxOn' } +] +[2025-10-15T11:41:01.541] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-10-15T11:41:01.542] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-15T11:41:01.542] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-15T11:41:01.545] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-15T11:41:01.545] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-10-16T05:41:00.545Z +[2025-10-15T11:41:01.546] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-10-15T16:33:00.546Z +[2025-10-15T11:41:01.547] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:41', name: 'luxOff' }, + { value: 1, start_time: '18:33', name: 'luxOn' } +] +[2025-10-15T11:41:01.548] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-10-15T11:41:01.549] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-15T11:41:01.549] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-15T11:41:01.551] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-15T11:41:01.552] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-10-16T05:41:00.552Z +[2025-10-15T11:41:01.553] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-10-15T16:33:00.553Z +[2025-10-15T11:41:01.553] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:41', name: 'luxOff' }, + { value: 1, start_time: '18:33', name: 'luxOn' } +] +[2025-10-15T11:41:01.554] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-10-15T11:41:01.555] [INFO] monitorLogs - buildTasks: profile for line 4 +[2025-10-15T11:41:01.556] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-15T11:41:01.558] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-15T11:41:01.558] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 4 2025-10-16T05:41:00.558Z +[2025-10-15T11:41:01.559] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 4 2025-10-15T16:33:00.559Z +[2025-10-15T11:41:01.560] [INFO] monitorLogs - -->time_points final 4 [ + { value: 0, start_time: '7:41', name: 'luxOff' }, + { value: 1, start_time: '18:33', name: 'luxOn' } +] +[2025-10-15T11:41:01.561] [INFO] monitorLogs - -->currentValue for relay 4 0 +[2025-10-15T11:41:01.587] [INFO] monitorLogs - tasks created: 1907 +[2025-10-15T11:41:01.590] [INFO] monitorLogs - -->FLOW bol spustený wvKJdZML6mXP4DzWBAXxwBAjxNloa5g23Ve9Y1ry 2025-10-08 +[2025-10-15T11:41:06.606] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-15T18:10:05.309] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-15T18:10:05.315] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-15T18:10:05.317] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-15T18:10:05.320] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor diff --git a/RVO13/package-lock.json b/RVO13/package-lock.json new file mode 100755 index 0000000..3c5c1ba --- /dev/null +++ b/RVO13/package-lock.json @@ -0,0 +1,2139 @@ +{ + "name": "emptyproject", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "emptyproject", + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "bitwise": "^2.1.0", + "easy-crc": "0.0.2", + "jsmodbus": "^4.0.6", + "log4js": "^6.3.0", + "moment": "^2.30.1", + "mqtt": "^4.2.6", + "nodemailer": "^6.9.7", + "serialport": "^9.2.8", + "total.js": "^3.4.13" + } + }, + "node_modules/@serialport/binding-abstract": { + "version": "9.2.3", + "resolved": "https://registry.npmjs.org/@serialport/binding-abstract/-/binding-abstract-9.2.3.tgz", + "integrity": "sha512-cQs9tbIlG3P0IrOWyVirqlhWuJ7Ms2Zh9m2108z6Y5UW/iVj6wEOiW8EmK9QX9jmJXYllE7wgGgvVozP5oCj3w==", + "dependencies": { + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/binding-mock": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/binding-mock/-/binding-mock-9.2.4.tgz", + "integrity": "sha512-dpEhACCs44oQhh6ajJfJdvQdK38Vq0N4W6iD/gdplglDCK7qXRQCMUjJIeKdS/HSEiWkC3bwumUhUufdsOyT4g==", + "dependencies": { + "@serialport/binding-abstract": "9.2.3", + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/bindings": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/@serialport/bindings/-/bindings-9.2.8.tgz", + "integrity": "sha512-hSLxTe0tADZ3LMMGwvEJWOC/TaFQTyPeFalUCsJ1lSQ0k6bPF04JwrtB/C81GetmDBTNRY0GlD0SNtKCc7Dr5g==", + "hasInstallScript": true, + "dependencies": { + "@serialport/binding-abstract": "9.2.3", + "@serialport/parser-readline": "9.2.4", + "bindings": "^1.5.0", + "debug": "^4.3.2", + "nan": "^2.15.0", + "prebuild-install": "^7.0.0" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-byte-length": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-byte-length/-/parser-byte-length-9.2.4.tgz", + "integrity": "sha512-sQD/iw4ZMU3xW9PLi0/GlvU6Y623jGeWecbMkO7izUo/6P7gtfv1c9ikd5h0kwL8AoAOpQA1lxdHIKox+umBUg==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-cctalk": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-cctalk/-/parser-cctalk-9.2.4.tgz", + "integrity": "sha512-T4TU5vQMwmo9AB3gQLFDWbfJXlW5jd9guEsB/nqKjFHTv0FXPdZ7DQ2TpSp8RnHWxU3GX6kYTaDO20BKzc8GPQ==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-delimiter": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-delimiter/-/parser-delimiter-9.2.4.tgz", + "integrity": "sha512-4nvTAoYAgkxFiXrkI+3CA49Yd43CODjeszh89EK+I9c8wOZ+etZduRCzINYPiy26g7zO+GRAb9FoPCsY+sYcbQ==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-inter-byte-timeout": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-inter-byte-timeout/-/parser-inter-byte-timeout-9.2.4.tgz", + "integrity": "sha512-SOAdvr0oBQIOCXX198hiTlxs4JTKg9j5piapw5tNq52fwDOWdbYrFneT/wN04UTMKaDrJuEvXq6T4rv4j7nJ5A==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-readline": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-readline/-/parser-readline-9.2.4.tgz", + "integrity": "sha512-Z1/qrZTQUVhNSJP1hd9YfDvq0o7d87rNwAjjRKbVpa7Qi51tG5BnKt43IV3NFMyBlVcRe0rnIb3tJu57E0SOwg==", + "dependencies": { + "@serialport/parser-delimiter": "9.2.4" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-ready": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-ready/-/parser-ready-9.2.4.tgz", + "integrity": "sha512-Pyi94Itjl6qAURwIZr/gmZpMAyTmKXThm6vL5DoAWGQjcRHWB0gwv2TY2v7N+mQLJYUKU3cMnvnATXxHm7xjxw==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-regex": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-regex/-/parser-regex-9.2.4.tgz", + "integrity": "sha512-sI/cVvPOYz+Dbv4ZdnW16qAwvXiFf/1pGASQdbveRTlgJDdz7sRNlCBifzfTN2xljwvCTZYqiudKvDdC1TepRQ==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/stream": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/stream/-/stream-9.2.4.tgz", + "integrity": "sha512-bLye8Ub4vUFQGmkh8qEqehr7SE7EJs2yDs0h9jzuL5oKi+F34CFmWkEErO8GAOQ8YNn7p6b3GxUgs+0BrHHDZQ==", + "dependencies": { + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "node_modules/are-we-there-yet": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", + "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/base64-js": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", + "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==" + }, + "node_modules/bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "dependencies": { + "file-uri-to-path": "1.0.0" + } + }, + "node_modules/bitwise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/bitwise/-/bitwise-2.1.0.tgz", + "integrity": "sha512-XKgAhMXCh4H/3oNwAHAsAO0iC89s9cOiumgYwSHjSobGWxYjv62YhkL9QEdvGP151xypCtMlAfKK79GEcd2eRQ==" + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/bl/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/buffer": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz", + "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==", + "dependencies": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + }, + "node_modules/buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" + }, + "node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, + "node_modules/code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/commist": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/commist/-/commist-1.1.0.tgz", + "integrity": "sha512-rraC8NXWOEjhADbZe9QBNzLAN5Q3fsTPQtBV+fEVj6xKIgDgNiEVE6ZNfHpZOqfQ21YUzfVNUXLOEZquYvQPPg==", + "dependencies": { + "leven": "^2.1.0", + "minimist": "^1.1.0" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "node_modules/concat-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", + "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", + "engines": [ + "node >= 6.0" + ], + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.0.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/concat-stream/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" + }, + "node_modules/core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "node_modules/crc": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/crc/-/crc-3.4.0.tgz", + "integrity": "sha512-ycVC2+4/DLgXXq7QweYi2znhqDuZz6P5TQXnkQo8v15XY/5p/IWeZwsSE31Ifo8w15b8TWLsqhXOjXyilHuQxw==" + }, + "node_modules/date-format": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.11.tgz", + "integrity": "sha512-VS20KRyorrbMCQmpdl2hg5KaOUsda1RbnsJg461FfrcyCUg+pkd0b40BSW4niQyTheww4DBXQnS7HwSrKkipLw==", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" + }, + "node_modules/detect-libc": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz", + "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==", + "engines": { + "node": ">=8" + } + }, + "node_modules/duplexify": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.2.tgz", + "integrity": "sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw==", + "dependencies": { + "end-of-stream": "^1.4.1", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1", + "stream-shift": "^1.0.0" + } + }, + "node_modules/duplexify/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/easy-crc": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/easy-crc/-/easy-crc-0.0.2.tgz", + "integrity": "sha512-h6eqIdhJRe0p271/xZJbM/0klCi13mW5IB7ZEzEGH11yV4QXWAkD4yPErz0fXdhFrd6sZ4Q1k5Iky2kMsMNePw==" + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" + }, + "node_modules/flatted": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", + "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==" + }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, + "node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "node_modules/gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha512-14x4kjc6lkD3ltw589k0NrPD6cCNTD6CWoVUNpB85+DrtONoZn+Rug6xZU5RvSC4+TZPxA5AnBibQYAvZn41Hg==", + "dependencies": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "node_modules/github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==" + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" + }, + "node_modules/has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" + }, + "node_modules/help-me": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/help-me/-/help-me-3.0.0.tgz", + "integrity": "sha512-hx73jClhyk910sidBB7ERlnhMlFsJJIBqSVMFDwPN8o2v9nmp5KgLq1Xz1Bf1fCMMZ6mPrX159iG0VLy/fPMtQ==", + "dependencies": { + "glob": "^7.1.6", + "readable-stream": "^3.6.0" + } + }, + "node_modules/help-me/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, + "node_modules/is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==", + "dependencies": { + "number-is-nan": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "node_modules/js-sdsl": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz", + "integrity": "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/js-sdsl" + } + }, + "node_modules/jsmodbus": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/jsmodbus/-/jsmodbus-4.0.6.tgz", + "integrity": "sha512-gCmjoaERErK5Rn9Lu/BN07fY13MoWV7JKgGzrnkPlQPdPxYcwDhLtYcmpFFpZ4J9NPZZBSezi1UkLZO/DnNppA==", + "dependencies": { + "crc": "3.4.0", + "debug": "^3.1.0" + }, + "bin": { + "jsmodbus": "bin/jsmodbus.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/jsmodbus/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/leven": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", + "integrity": "sha1-wuep93IJTe6dNCAq6KzORoeHVYA=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/log4js": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.5.2.tgz", + "integrity": "sha512-DXtpNtt+KDOMT7RHUDIur/WsSA3rntlUh9Zg4XCdV42wUuMmbFkl38+LZ92Z5QvQA7mD5kAVkLiBSEH/tvUB8A==", + "dependencies": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "flatted": "^3.2.5", + "rfdc": "^1.3.0", + "streamroller": "^3.1.1" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" + }, + "node_modules/moment": { + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", + "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==", + "engines": { + "node": "*" + } + }, + "node_modules/mqtt": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/mqtt/-/mqtt-4.3.7.tgz", + "integrity": "sha512-ew3qwG/TJRorTz47eW46vZ5oBw5MEYbQZVaEji44j5lAUSQSqIEoul7Kua/BatBW0H0kKQcC9kwUHa1qzaWHSw==", + "dependencies": { + "commist": "^1.0.0", + "concat-stream": "^2.0.0", + "debug": "^4.1.1", + "duplexify": "^4.1.1", + "help-me": "^3.0.0", + "inherits": "^2.0.3", + "lru-cache": "^6.0.0", + "minimist": "^1.2.5", + "mqtt-packet": "^6.8.0", + "number-allocator": "^1.0.9", + "pump": "^3.0.0", + "readable-stream": "^3.6.0", + "reinterval": "^1.1.0", + "rfdc": "^1.3.0", + "split2": "^3.1.0", + "ws": "^7.5.5", + "xtend": "^4.0.2" + }, + "bin": { + "mqtt": "bin/mqtt.js", + "mqtt_pub": "bin/pub.js", + "mqtt_sub": "bin/sub.js" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/mqtt-packet": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/mqtt-packet/-/mqtt-packet-6.10.0.tgz", + "integrity": "sha512-ja8+mFKIHdB1Tpl6vac+sktqy3gA8t9Mduom1BA75cI+R9AHnZOiaBQwpGiWnaVJLDGRdNhQmFaAqd7tkKSMGA==", + "dependencies": { + "bl": "^4.0.2", + "debug": "^4.1.1", + "process-nextick-args": "^2.0.1" + } + }, + "node_modules/mqtt/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/nan": { + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.16.0.tgz", + "integrity": "sha512-UdAqHyFngu7TfQKsCBgAA6pWDkT8MAO7d0jyOecVhN5354xbLqdn8mV9Tat9gepAupm0bt2DbeaSC8vS52MuFA==" + }, + "node_modules/napi-build-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", + "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==" + }, + "node_modules/node-abi": { + "version": "3.22.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.22.0.tgz", + "integrity": "sha512-u4uAs/4Zzmp/jjsD9cyFYDXeISfUWaAVWshPmDZOFOv4Xl4SbzTXm53I04C2uRueYJ+0t5PEtLH/owbn2Npf/w==", + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/nodemailer": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.7.tgz", + "integrity": "sha512-rUtR77ksqex/eZRLmQ21LKVH5nAAsVicAtAYudK7JgwenEDZ0UIQ1adUGqErz7sMkWYxWTTU1aeP2Jga6WQyJw==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "dependencies": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "node_modules/number-allocator": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/number-allocator/-/number-allocator-1.0.14.tgz", + "integrity": "sha512-OrL44UTVAvkKdOdRQZIJpLkAdjXGTRda052sN4sO77bKEzYYqWKMBjQvrJFzqygI99gL6Z4u2xctPW1tB8ErvA==", + "dependencies": { + "debug": "^4.3.1", + "js-sdsl": "4.3.0" + } + }, + "node_modules/number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/prebuild-install": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.0.tgz", + "integrity": "sha512-CNcMgI1xBypOyGqjp3wOc8AAo1nMhZS3Cwd3iHIxOdAUbb+YxdNuM4Z5iIrZ8RLvOsf3F3bl7b7xGq6DjQoNYA==", + "dependencies": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^1.0.1", + "node-abi": "^3.3.0", + "npmlog": "^4.0.1", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + }, + "bin": { + "prebuild-install": "bin.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/reinterval": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reinterval/-/reinterval-1.1.0.tgz", + "integrity": "sha1-M2Hs+jymwYKDOA3Qu5VG85D17Oc=" + }, + "node_modules/rfdc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==" + }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/serialport": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/serialport/-/serialport-9.2.8.tgz", + "integrity": "sha512-FsWpMQgSJxi93JgWl5xM1f9/Z8IjRJuaUEoHqLf8FPBLw7gMhInuHOBhI2onQufWIYPGTz3H3oGcu1nCaK1EfA==", + "dependencies": { + "@serialport/binding-mock": "9.2.4", + "@serialport/bindings": "9.2.8", + "@serialport/parser-byte-length": "9.2.4", + "@serialport/parser-cctalk": "9.2.4", + "@serialport/parser-delimiter": "9.2.4", + "@serialport/parser-inter-byte-timeout": "9.2.4", + "@serialport/parser-readline": "9.2.4", + "@serialport/parser-ready": "9.2.4", + "@serialport/parser-regex": "9.2.4", + "@serialport/stream": "9.2.4", + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "node_modules/split2": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", + "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", + "dependencies": { + "readable-stream": "^3.0.0" + } + }, + "node_modules/split2/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==" + }, + "node_modules/streamroller": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.1.1.tgz", + "integrity": "sha512-iPhtd9unZ6zKdWgMeYGfSBuqCngyJy1B/GPi/lTpwGpa3bajuX30GjUVd0/Tn/Xhg0mr4DOSENozz9Y06qyonQ==", + "dependencies": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "fs-extra": "^10.1.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dependencies": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/tar-fs": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "dependencies": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tar-stream/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/total.js": { + "version": "3.4.13", + "resolved": "https://registry.npmjs.org/total.js/-/total.js-3.4.13.tgz", + "integrity": "sha512-lAH4gEixlPFbrE3xfKADAcHfO79IFq2wKa9GTsrgRzIR5MTg3mNH7+4IxvX1pK8faoYb/0oYSJ1YTsAa5hIFFQ==", + "bin": { + "total": "bin/totaljs", + "total.js": "bin/totaljs", + "totaljs": "bin/totaljs", + "totalpackage": "bin/tpm", + "tpm": "bin/tpm" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, + "node_modules/universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "node_modules/wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "node_modules/ws": { + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } + }, + "dependencies": { + "@serialport/binding-abstract": { + "version": "9.2.3", + "resolved": "https://registry.npmjs.org/@serialport/binding-abstract/-/binding-abstract-9.2.3.tgz", + "integrity": "sha512-cQs9tbIlG3P0IrOWyVirqlhWuJ7Ms2Zh9m2108z6Y5UW/iVj6wEOiW8EmK9QX9jmJXYllE7wgGgvVozP5oCj3w==", + "requires": { + "debug": "^4.3.2" + } + }, + "@serialport/binding-mock": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/binding-mock/-/binding-mock-9.2.4.tgz", + "integrity": "sha512-dpEhACCs44oQhh6ajJfJdvQdK38Vq0N4W6iD/gdplglDCK7qXRQCMUjJIeKdS/HSEiWkC3bwumUhUufdsOyT4g==", + "requires": { + "@serialport/binding-abstract": "9.2.3", + "debug": "^4.3.2" + } + }, + "@serialport/bindings": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/@serialport/bindings/-/bindings-9.2.8.tgz", + "integrity": "sha512-hSLxTe0tADZ3LMMGwvEJWOC/TaFQTyPeFalUCsJ1lSQ0k6bPF04JwrtB/C81GetmDBTNRY0GlD0SNtKCc7Dr5g==", + "requires": { + "@serialport/binding-abstract": "9.2.3", + "@serialport/parser-readline": "9.2.4", + "bindings": "^1.5.0", + "debug": "^4.3.2", + "nan": "^2.15.0", + "prebuild-install": "^7.0.0" + } + }, + "@serialport/parser-byte-length": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-byte-length/-/parser-byte-length-9.2.4.tgz", + "integrity": "sha512-sQD/iw4ZMU3xW9PLi0/GlvU6Y623jGeWecbMkO7izUo/6P7gtfv1c9ikd5h0kwL8AoAOpQA1lxdHIKox+umBUg==" + }, + "@serialport/parser-cctalk": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-cctalk/-/parser-cctalk-9.2.4.tgz", + "integrity": "sha512-T4TU5vQMwmo9AB3gQLFDWbfJXlW5jd9guEsB/nqKjFHTv0FXPdZ7DQ2TpSp8RnHWxU3GX6kYTaDO20BKzc8GPQ==" + }, + "@serialport/parser-delimiter": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-delimiter/-/parser-delimiter-9.2.4.tgz", + "integrity": "sha512-4nvTAoYAgkxFiXrkI+3CA49Yd43CODjeszh89EK+I9c8wOZ+etZduRCzINYPiy26g7zO+GRAb9FoPCsY+sYcbQ==" + }, + "@serialport/parser-inter-byte-timeout": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-inter-byte-timeout/-/parser-inter-byte-timeout-9.2.4.tgz", + "integrity": "sha512-SOAdvr0oBQIOCXX198hiTlxs4JTKg9j5piapw5tNq52fwDOWdbYrFneT/wN04UTMKaDrJuEvXq6T4rv4j7nJ5A==" + }, + "@serialport/parser-readline": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-readline/-/parser-readline-9.2.4.tgz", + "integrity": "sha512-Z1/qrZTQUVhNSJP1hd9YfDvq0o7d87rNwAjjRKbVpa7Qi51tG5BnKt43IV3NFMyBlVcRe0rnIb3tJu57E0SOwg==", + "requires": { + "@serialport/parser-delimiter": "9.2.4" + } + }, + "@serialport/parser-ready": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-ready/-/parser-ready-9.2.4.tgz", + "integrity": "sha512-Pyi94Itjl6qAURwIZr/gmZpMAyTmKXThm6vL5DoAWGQjcRHWB0gwv2TY2v7N+mQLJYUKU3cMnvnATXxHm7xjxw==" + }, + "@serialport/parser-regex": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-regex/-/parser-regex-9.2.4.tgz", + "integrity": "sha512-sI/cVvPOYz+Dbv4ZdnW16qAwvXiFf/1pGASQdbveRTlgJDdz7sRNlCBifzfTN2xljwvCTZYqiudKvDdC1TepRQ==" + }, + "@serialport/stream": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/stream/-/stream-9.2.4.tgz", + "integrity": "sha512-bLye8Ub4vUFQGmkh8qEqehr7SE7EJs2yDs0h9jzuL5oKi+F34CFmWkEErO8GAOQ8YNn7p6b3GxUgs+0BrHHDZQ==", + "requires": { + "debug": "^4.3.2" + } + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==" + }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "are-we-there-yet": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", + "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "base64-js": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", + "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==" + }, + "bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "requires": { + "file-uri-to-path": "1.0.0" + } + }, + "bitwise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/bitwise/-/bitwise-2.1.0.tgz", + "integrity": "sha512-XKgAhMXCh4H/3oNwAHAsAO0iC89s9cOiumgYwSHjSobGWxYjv62YhkL9QEdvGP151xypCtMlAfKK79GEcd2eRQ==" + }, + "bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "requires": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "buffer": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz", + "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==", + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" + }, + "chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==" + }, + "commist": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/commist/-/commist-1.1.0.tgz", + "integrity": "sha512-rraC8NXWOEjhADbZe9QBNzLAN5Q3fsTPQtBV+fEVj6xKIgDgNiEVE6ZNfHpZOqfQ21YUzfVNUXLOEZquYvQPPg==", + "requires": { + "leven": "^2.1.0", + "minimist": "^1.1.0" + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "concat-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", + "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.0.2", + "typedarray": "^0.0.6" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "crc": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/crc/-/crc-3.4.0.tgz", + "integrity": "sha512-ycVC2+4/DLgXXq7QweYi2znhqDuZz6P5TQXnkQo8v15XY/5p/IWeZwsSE31Ifo8w15b8TWLsqhXOjXyilHuQxw==" + }, + "date-format": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.11.tgz", + "integrity": "sha512-VS20KRyorrbMCQmpdl2hg5KaOUsda1RbnsJg461FfrcyCUg+pkd0b40BSW4niQyTheww4DBXQnS7HwSrKkipLw==" + }, + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "requires": { + "ms": "2.1.2" + } + }, + "decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "requires": { + "mimic-response": "^3.1.0" + } + }, + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==" + }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" + }, + "detect-libc": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz", + "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==" + }, + "duplexify": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.2.tgz", + "integrity": "sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw==", + "requires": { + "end-of-stream": "^1.4.1", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1", + "stream-shift": "^1.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "easy-crc": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/easy-crc/-/easy-crc-0.0.2.tgz", + "integrity": "sha512-h6eqIdhJRe0p271/xZJbM/0klCi13mW5IB7ZEzEGH11yV4QXWAkD4yPErz0fXdhFrd6sZ4Q1k5Iky2kMsMNePw==" + }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "requires": { + "once": "^1.4.0" + } + }, + "expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==" + }, + "file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" + }, + "flatted": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", + "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==" + }, + "fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, + "fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha512-14x4kjc6lkD3ltw589k0NrPD6cCNTD6CWoVUNpB85+DrtONoZn+Rug6xZU5RvSC4+TZPxA5AnBibQYAvZn41Hg==", + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==" + }, + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" + }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" + }, + "help-me": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/help-me/-/help-me-3.0.0.tgz", + "integrity": "sha512-hx73jClhyk910sidBB7ERlnhMlFsJJIBqSVMFDwPN8o2v9nmp5KgLq1Xz1Bf1fCMMZ6mPrX159iG0VLy/fPMtQ==", + "requires": { + "glob": "^7.1.6", + "readable-stream": "^3.6.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==", + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "js-sdsl": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz", + "integrity": "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==" + }, + "jsmodbus": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/jsmodbus/-/jsmodbus-4.0.6.tgz", + "integrity": "sha512-gCmjoaERErK5Rn9Lu/BN07fY13MoWV7JKgGzrnkPlQPdPxYcwDhLtYcmpFFpZ4J9NPZZBSezi1UkLZO/DnNppA==", + "requires": { + "crc": "3.4.0", + "debug": "^3.1.0" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "requires": { + "ms": "^2.1.1" + } + } + } + }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, + "leven": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", + "integrity": "sha1-wuep93IJTe6dNCAq6KzORoeHVYA=" + }, + "log4js": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.5.2.tgz", + "integrity": "sha512-DXtpNtt+KDOMT7RHUDIur/WsSA3rntlUh9Zg4XCdV42wUuMmbFkl38+LZ92Z5QvQA7mD5kAVkLiBSEH/tvUB8A==", + "requires": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "flatted": "^3.2.5", + "rfdc": "^1.3.0", + "streamroller": "^3.1.1" + } + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "requires": { + "yallist": "^4.0.0" + } + }, + "mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==" + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==" + }, + "mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" + }, + "moment": { + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", + "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==" + }, + "mqtt": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/mqtt/-/mqtt-4.3.7.tgz", + "integrity": "sha512-ew3qwG/TJRorTz47eW46vZ5oBw5MEYbQZVaEji44j5lAUSQSqIEoul7Kua/BatBW0H0kKQcC9kwUHa1qzaWHSw==", + "requires": { + "commist": "^1.0.0", + "concat-stream": "^2.0.0", + "debug": "^4.1.1", + "duplexify": "^4.1.1", + "help-me": "^3.0.0", + "inherits": "^2.0.3", + "lru-cache": "^6.0.0", + "minimist": "^1.2.5", + "mqtt-packet": "^6.8.0", + "number-allocator": "^1.0.9", + "pump": "^3.0.0", + "readable-stream": "^3.6.0", + "reinterval": "^1.1.0", + "rfdc": "^1.3.0", + "split2": "^3.1.0", + "ws": "^7.5.5", + "xtend": "^4.0.2" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "mqtt-packet": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/mqtt-packet/-/mqtt-packet-6.10.0.tgz", + "integrity": "sha512-ja8+mFKIHdB1Tpl6vac+sktqy3gA8t9Mduom1BA75cI+R9AHnZOiaBQwpGiWnaVJLDGRdNhQmFaAqd7tkKSMGA==", + "requires": { + "bl": "^4.0.2", + "debug": "^4.1.1", + "process-nextick-args": "^2.0.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "nan": { + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.16.0.tgz", + "integrity": "sha512-UdAqHyFngu7TfQKsCBgAA6pWDkT8MAO7d0jyOecVhN5354xbLqdn8mV9Tat9gepAupm0bt2DbeaSC8vS52MuFA==" + }, + "napi-build-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", + "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==" + }, + "node-abi": { + "version": "3.22.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.22.0.tgz", + "integrity": "sha512-u4uAs/4Zzmp/jjsD9cyFYDXeISfUWaAVWshPmDZOFOv4Xl4SbzTXm53I04C2uRueYJ+0t5PEtLH/owbn2Npf/w==", + "requires": { + "semver": "^7.3.5" + } + }, + "nodemailer": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.7.tgz", + "integrity": "sha512-rUtR77ksqex/eZRLmQ21LKVH5nAAsVicAtAYudK7JgwenEDZ0UIQ1adUGqErz7sMkWYxWTTU1aeP2Jga6WQyJw==" + }, + "npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "number-allocator": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/number-allocator/-/number-allocator-1.0.14.tgz", + "integrity": "sha512-OrL44UTVAvkKdOdRQZIJpLkAdjXGTRda052sN4sO77bKEzYYqWKMBjQvrJFzqygI99gL6Z4u2xctPW1tB8ErvA==", + "requires": { + "debug": "^4.3.1", + "js-sdsl": "4.3.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==" + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==" + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==" + }, + "prebuild-install": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.0.tgz", + "integrity": "sha512-CNcMgI1xBypOyGqjp3wOc8AAo1nMhZS3Cwd3iHIxOdAUbb+YxdNuM4Z5iIrZ8RLvOsf3F3bl7b7xGq6DjQoNYA==", + "requires": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^1.0.1", + "node-abi": "^3.3.0", + "npmlog": "^4.0.1", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + } + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + } + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "reinterval": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reinterval/-/reinterval-1.1.0.tgz", + "integrity": "sha1-M2Hs+jymwYKDOA3Qu5VG85D17Oc=" + }, + "rfdc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==" + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "requires": { + "lru-cache": "^6.0.0" + } + }, + "serialport": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/serialport/-/serialport-9.2.8.tgz", + "integrity": "sha512-FsWpMQgSJxi93JgWl5xM1f9/Z8IjRJuaUEoHqLf8FPBLw7gMhInuHOBhI2onQufWIYPGTz3H3oGcu1nCaK1EfA==", + "requires": { + "@serialport/binding-mock": "9.2.4", + "@serialport/bindings": "9.2.8", + "@serialport/parser-byte-length": "9.2.4", + "@serialport/parser-cctalk": "9.2.4", + "@serialport/parser-delimiter": "9.2.4", + "@serialport/parser-inter-byte-timeout": "9.2.4", + "@serialport/parser-readline": "9.2.4", + "@serialport/parser-ready": "9.2.4", + "@serialport/parser-regex": "9.2.4", + "@serialport/stream": "9.2.4", + "debug": "^4.3.2" + } + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==" + }, + "simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "requires": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "split2": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", + "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", + "requires": { + "readable-stream": "^3.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==" + }, + "streamroller": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.1.1.tgz", + "integrity": "sha512-iPhtd9unZ6zKdWgMeYGfSBuqCngyJy1B/GPi/lTpwGpa3bajuX30GjUVd0/Tn/Xhg0mr4DOSENozz9Y06qyonQ==", + "requires": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "fs-extra": "^10.1.0" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" + }, + "tar-fs": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "requires": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "requires": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "total.js": { + "version": "3.4.13", + "resolved": "https://registry.npmjs.org/total.js/-/total.js-3.4.13.tgz", + "integrity": "sha512-lAH4gEixlPFbrE3xfKADAcHfO79IFq2wKa9GTsrgRzIR5MTg3mNH7+4IxvX1pK8faoYb/0oYSJ1YTsAa5hIFFQ==" + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, + "universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==" + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "requires": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "ws": { + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "requires": {} + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } + } +} diff --git a/RVO13/package.json b/RVO13/package.json new file mode 100755 index 0000000..7f7c795 --- /dev/null +++ b/RVO13/package.json @@ -0,0 +1,30 @@ +{ + "name": "emptyproject", + "description": "Total.js empty project.", + "version": "1.0.0", + "main": "debug.js", + "dependencies": { + "bitwise": "^2.1.0", + "easy-crc": "0.0.2", + "jsmodbus": "^4.0.6", + "log4js": "^6.3.0", + "moment": "^2.30.1", + "mqtt": "^4.2.6", + "nodemailer": "^6.9.7", + "serialport": "^9.2.8", + "total.js": "^3.4.13" + }, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "https://github.com/totaljs/emptyproject-flow" + }, + "keywords": [ + "empty", + "project" + ], + "author": "Peter Širka", + "license": "MIT" +} diff --git a/RVO13/release.js b/RVO13/release.js new file mode 100755 index 0000000..02d52ff --- /dev/null +++ b/RVO13/release.js @@ -0,0 +1,15 @@ +// =================================================== +// FOR PRODUCTION +// Total.js - framework for Node.js platform +// https://www.totaljs.com +// =================================================== + +const options = {'ip':'0.0.0.0', 'port':12345}; + +// options.ip = '127.0.0.1'; +// options.port = parseInt(process.argv[2]); +// options.config = { name: 'Total.js' }; +// options.sleep = 3000; + +require('total.js').http('release', options); +// require('total.js').cluster.http(5, 'release', options); diff --git a/RVO13/release.js.json b/RVO13/release.js.json new file mode 100755 index 0000000..ad27057 --- /dev/null +++ b/RVO13/release.js.json @@ -0,0 +1,34 @@ +{ + "pid": 402, + "stats": [ + { + "id": null, + "version": { + "node": "v14.18.1", + "total": "3.4.13", + "app": "1.0.0" + }, + "pid": 402, + "thread": "", + "mode": "release", + "overload": 0, + "date": "2025-10-16T00:22:52.336Z", + "memory": 27.41, + "rm": 0, + "fm": 0, + "wm": 0, + "mm": 0, + "om": 8, + "em": 0, + "dbrm": 0, + "dbwm": 0, + "usage": 0, + "requests": 6, + "pending": 0, + "errors": 0, + "timeouts": 0, + "uptime": 883, + "online": 0 + } + ] +} \ No newline at end of file diff --git a/RVO13/report_data.log b/RVO13/report_data.log new file mode 100755 index 0000000..b584824 --- /dev/null +++ b/RVO13/report_data.log @@ -0,0 +1,210 @@ +{ + "name": "rvo_senica_13_ip123", + "time": "2025-10-15T10:41:07.523Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_13_ip123", + "time": "2025-10-15T11:41:07.522Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_13_ip123", + "time": "2025-10-15T12:41:07.521Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_13_ip123", + "time": "2025-10-15T13:41:07.521Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_13_ip123", + "time": "2025-10-15T14:41:07.521Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_13_ip123", + "time": "2025-10-15T15:41:07.521Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_13_ip123", + "time": "2025-10-15T17:36:09.585Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "13/118_1L_3866_prechod" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_13_ip123", + "time": "2025-10-15T18:36:09.576Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "13/118_1L_3866_prechod" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_13_ip123", + "time": "2025-10-15T19:36:09.582Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "13/118_1L_3866_prechod" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_13_ip123", + "time": "2025-10-15T20:36:09.576Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "13/118_1L_3866_prechod" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_13_ip123", + "time": "2025-10-15T21:36:09.582Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "13/118_1L_3866_prechod" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_13_ip123", + "time": "2025-10-15T22:36:09.577Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "13/118_1L_3866_prechod" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_13_ip123", + "time": "2025-10-15T23:36:09.577Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "13/118_1L_3866_prechod" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +} \ No newline at end of file From 0294b8583eca0c6634b9c168d40d9773759a29d8 Mon Sep 17 00:00:00 2001 From: Jakub Klena Date: Thu, 16 Oct 2025 02:24:04 +0200 Subject: [PATCH 07/30] Backup senica-RVO14 on 16.10.2025 --- RVO14/addSwitch.py | 36 + RVO14/cloud_topic.py | 76 + RVO14/config | 12 + RVO14/createNode.py | 43 + RVO14/databases/accelerometer_db.js | 3055 ++++++++++++++++ RVO14/databases/modbus_config.js | 114 + RVO14/databases/nodes.table | 12 + .../nodes_original/nodes_original.table | 1 + RVO14/databases/notifications.table | 41 + RVO14/databases/pins.table | 14 + RVO14/databases/relays.table | 5 + RVO14/databases/settings.table | 2 + RVO14/databases/tbdata.nosql | 4 + RVO14/databases/tbdatacloud.nosql | 3 + RVO14/databases/total_energy.js | 38 + RVO14/debug.js | 16 + RVO14/err.txt | 33 + RVO14/flow/cloudmqttconnect.js | 357 ++ RVO14/flow/cmd_manager.js | 3071 ++++++++++++++++ RVO14/flow/code.js | 90 + RVO14/flow/comment.js | 11 + RVO14/flow/count.js | 60 + RVO14/flow/db_connector.js | 286 ++ RVO14/flow/db_init.js | 113 + RVO14/flow/debug.js | 100 + RVO14/flow/designer.json | 3102 +++++++++++++++++ RVO14/flow/dido_controller.js | 1486 ++++++++ RVO14/flow/helper/DataToTbHandler.js | 187 + RVO14/flow/helper/ErrorToServiceHandler.js | 91 + RVO14/flow/helper/db_helper.js | 44 + RVO14/flow/helper/logger.js | 30 + RVO14/flow/helper/md5.js | 5 + RVO14/flow/helper/notification_reporter.js | 121 + RVO14/flow/helper/register.js | 144 + RVO14/flow/helper/serialport_helper.js | 99 + RVO14/flow/helper/suncalc.js | 317 ++ RVO14/flow/helper/utils.js | 161 + RVO14/flow/httprequest.js | 137 + RVO14/flow/httpresponse.js | 76 + RVO14/flow/httproute.js | 326 ++ RVO14/flow/infosender.js | 81 + RVO14/flow/modbus_reader.js | 346 ++ RVO14/flow/monitorconsumption.js | 156 + RVO14/flow/monitordisk.js | 96 + RVO14/flow/monitormemory.js | 87 + RVO14/flow/nodesdb_changecheck.js | 77 + RVO14/flow/show_dbdata.js | 243 ++ RVO14/flow/slack_filter.js | 188 + RVO14/flow/thermometer.js | 99 + RVO14/flow/trigger.js | 79 + RVO14/flow/variables.txt | 0 RVO14/flow/virtualwirein.js | 43 + RVO14/flow/virtualwireout.js | 41 + RVO14/flow/wsmqttpublish.js | 448 +++ RVO14/monitor.txt | 195 ++ RVO14/package-lock.json | 2125 +++++++++++ RVO14/package.json | 29 + RVO14/release.js | 15 + RVO14/release.js.json | 34 + RVO14/report_data.log | 181 + 60 files changed, 18482 insertions(+) create mode 100755 RVO14/addSwitch.py create mode 100755 RVO14/cloud_topic.py create mode 100755 RVO14/config create mode 100755 RVO14/createNode.py create mode 100755 RVO14/databases/accelerometer_db.js create mode 100755 RVO14/databases/modbus_config.js create mode 100755 RVO14/databases/nodes.table create mode 100755 RVO14/databases/nodes_original/nodes_original.table create mode 100755 RVO14/databases/notifications.table create mode 100755 RVO14/databases/pins.table create mode 100755 RVO14/databases/relays.table create mode 100755 RVO14/databases/settings.table create mode 100755 RVO14/databases/tbdata.nosql create mode 100755 RVO14/databases/tbdatacloud.nosql create mode 100755 RVO14/databases/total_energy.js create mode 100755 RVO14/debug.js create mode 100755 RVO14/err.txt create mode 100755 RVO14/flow/cloudmqttconnect.js create mode 100755 RVO14/flow/cmd_manager.js create mode 100755 RVO14/flow/code.js create mode 100755 RVO14/flow/comment.js create mode 100755 RVO14/flow/count.js create mode 100755 RVO14/flow/db_connector.js create mode 100755 RVO14/flow/db_init.js create mode 100755 RVO14/flow/debug.js create mode 100755 RVO14/flow/designer.json create mode 100755 RVO14/flow/dido_controller.js create mode 100755 RVO14/flow/helper/DataToTbHandler.js create mode 100755 RVO14/flow/helper/ErrorToServiceHandler.js create mode 100755 RVO14/flow/helper/db_helper.js create mode 100755 RVO14/flow/helper/logger.js create mode 100755 RVO14/flow/helper/md5.js create mode 100755 RVO14/flow/helper/notification_reporter.js create mode 100755 RVO14/flow/helper/register.js create mode 100755 RVO14/flow/helper/serialport_helper.js create mode 100755 RVO14/flow/helper/suncalc.js create mode 100755 RVO14/flow/helper/utils.js create mode 100755 RVO14/flow/httprequest.js create mode 100755 RVO14/flow/httpresponse.js create mode 100755 RVO14/flow/httproute.js create mode 100755 RVO14/flow/infosender.js create mode 100755 RVO14/flow/modbus_reader.js create mode 100755 RVO14/flow/monitorconsumption.js create mode 100755 RVO14/flow/monitordisk.js create mode 100755 RVO14/flow/monitormemory.js create mode 100755 RVO14/flow/nodesdb_changecheck.js create mode 100755 RVO14/flow/show_dbdata.js create mode 100755 RVO14/flow/slack_filter.js create mode 100755 RVO14/flow/thermometer.js create mode 100755 RVO14/flow/trigger.js create mode 100755 RVO14/flow/variables.txt create mode 100755 RVO14/flow/virtualwirein.js create mode 100755 RVO14/flow/virtualwireout.js create mode 100755 RVO14/flow/wsmqttpublish.js create mode 100755 RVO14/monitor.txt create mode 100755 RVO14/package-lock.json create mode 100755 RVO14/package.json create mode 100755 RVO14/release.js create mode 100755 RVO14/release.js.json create mode 100755 RVO14/report_data.log diff --git a/RVO14/addSwitch.py b/RVO14/addSwitch.py new file mode 100755 index 0000000..c35e96b --- /dev/null +++ b/RVO14/addSwitch.py @@ -0,0 +1,36 @@ +import os + +def process_set_file(): + """ + Checks if /root/flowserver exists, reads set.txt, and modifies the second line. + """ + default_folder = "/root/flowserver" if os.path.exists("/root/flowserver") else "/home/unipi/flowserver" + flag = 1 if default_folder == "/root/flowserver" else 0 + + try: + with open("/home/unipi/flowserver/databases/settings.table", "r") as f: + lines = f.readlines() + + if len(lines) >= 2: + lines[0] = lines[0].rstrip('\n') + "|main_switch:boolean\n" + second_line = lines[1].strip() # remove trailing newline + last_pipe_index = second_line.rfind("|") + + if last_pipe_index != -1: + modified_line = second_line[:last_pipe_index + 1] + str(flag) + "|" + second_line[last_pipe_index + 1:] + lines[1] = modified_line + else: + print("Warning: No '|' character found in the second line of set.txt") + + with open("/home/unipi/flowserver/databases/settings.table", "w") as f: + f.writelines(lines) + else: + print("Warning: settings.table has less than two lines.") + + except FileNotFoundError: + print("Error: settings.table not found.") + except Exception as e: + print(e) + +# if __name__ == "__main__": +process_set_file() diff --git a/RVO14/cloud_topic.py b/RVO14/cloud_topic.py new file mode 100755 index 0000000..77c31f1 --- /dev/null +++ b/RVO14/cloud_topic.py @@ -0,0 +1,76 @@ +# import os +# +# def modify_file(file_path): +# """ +# Modifies the given file by: +# 1. Appending "|cloud_topic" to the first line. +# 2. Inserting the text from the third "." to the first "|" on the second line after the last "|" character. +# +# Args: +# file_path (str): The path to the file to be modified. +# """ +# +# with open(file_path, 'r+') as f: +# lines = f.readlines() +# +# # Modify the first line +# lines[0] += "|cloud_topic:string" +# +# # Modify the second line +# second_line = lines[1].strip() # Remove leading/trailing whitespace +# first_pipe_index = second_line.find('|') +# third_dot_index = second_line.find('.', second_line.find('.', second_line.find('.') + 1) + 1) +# text_to_insert = second_line[third_dot_index:first_pipe_index] +# +# last_pipe_index = second_line.rfind('|') +# lines[1] = second_line[:last_pipe_index + 1] + text_to_insert + "|" + second_line[last_pipe_index + 1:] +# +# print(first_pipe_index, third_dot_index, text_to_insert, last_pipe_index) +# # Write the modified lines back to the file +# # f.seek(0) +# # f.writelines(lines) +# # f.truncate() +# +# # Example usage: +# file_path = "settings.table" # Replace with the actual file path +# modify_file(file_path) +# + + +def modify_file(file_path): + """ + Modifies the given file by: + 1. Appending "|cloud_topic" to the first line. + 2. Inserting the text between the third "." and the second "|" on the second line after the last "|" character. + + Args: + file_path (str): The path to the file to be modified. + """ + + with open(file_path, 'r+') as f: + lines = f.readlines() + + first_line = lines[0].strip() + first_line += "|cloud_topic:string\n" + # Modify the first line + lines[0] = first_line + + # Modify the second line + second_line = lines[1].strip() # Remove leading/trailing whitespace + first_pipe_index = second_line.find('|') + second_pipe_index = second_line.find('|', first_pipe_index + 1) + third_dot_index = second_line.find('.', second_line.find('.', second_line.find('.') + 1) + 1) + text_to_insert = "u" + second_line[third_dot_index+1:second_pipe_index] + + last_pipe_index = second_line.rfind('|') + lines[1] = second_line[:last_pipe_index + 1] + text_to_insert + "|" + second_line[last_pipe_index + 1:] + + print(first_pipe_index, third_dot_index, text_to_insert, last_pipe_index) + # Write the modified lines back to the file + f.seek(0) + f.writelines(lines) + f.truncate() + +# Example usage: +file_path = "/home/unipi/flowserver/databases/settings.table" # Replace with the actual file path +modify_file(file_path) diff --git a/RVO14/config b/RVO14/config new file mode 100755 index 0000000..cd0a8a9 --- /dev/null +++ b/RVO14/config @@ -0,0 +1,12 @@ +name : Total.js Flow +default_timezone : Europe/Bratislava + +// Packages settings +package#flow (Object) : { url: '/' } + + +table.relays : line:number|tbname:string|contactor:number|profile:string +table.nodes : node:number|pole_number:string|node_type:string|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|project_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|cloud_topic:string|has_main_switch:boolean|daily_report:boolean|send_changed_node_numbers:boolean +table.pins : pin:string|type:string|line:number +table.notifications : key:string|weight:string|sk:string|en:string diff --git a/RVO14/createNode.py b/RVO14/createNode.py new file mode 100755 index 0000000..a8cea91 --- /dev/null +++ b/RVO14/createNode.py @@ -0,0 +1,43 @@ +print("zaciname") +import re, json + +search_str = '|' +final = [] +counter = 1 +with open("/home/unipi/flowserver/databases/nodes.table", 'r') as file: +# with open("/home/rasta5man/dev/oms/flowserver/databases/nodes.table", 'r') as file: + # Read each line in the file + for line in file: + # Print each line + line = line.strip() + print(line) + if counter != 1: + i = [m.start() for m in re.finditer(re.escape(search_str), line)] + node = line[ i[0] + 1 : i[1] ] + tbname = line[ i[3] + 1 : i[4] ] + final.append({node:tbname}) + counter += 1 +print(json.dumps(final)) +f = open("/home/unipi/flowserver/databases/nodes_original/nodes_original.table", "w") +f.write(json.dumps(final)) +f.close() + + +# +# # ``d`` has to be replaced with a different character +# old_character = "'" +# +# # ``t`` will replace ``d` +# new_character = '"' +# resultant_string = 0; +# with open("/home/unipi/flowserver/databases/nodes_original/nodes_original.table", 'r') as file: +# for line in file: +# resultant_string = re.sub("'", '"', line) +# +# resultant_string = re.sub(" ", "", resultant_string) +# print(resultant_string) +# +# f = open("/home/unipi/flowserver/databases/nodes_original/nodes_original.table", "w") +# f.write(str(resultant_string)) +# f.close() +# diff --git a/RVO14/databases/accelerometer_db.js b/RVO14/databases/accelerometer_db.js new file mode 100755 index 0000000..fdfc7fd --- /dev/null +++ b/RVO14/databases/accelerometer_db.js @@ -0,0 +1,3055 @@ +let naklony = { + "3993": { "label": "1/3A", "naklon": 0 }, + "3989": { "label": "1/3B", "naklon": 15 }, + "3976": { "label": "1/1", "naklon": 0 }, + "4181": { "label": "1/2", "naklon": 0 }, + "4376": { "label": "1/4", "naklon": 15 }, + "3868": { "label": "1/5", "naklon": 15 }, + "3728": { "label": "1/6", "naklon": 15 }, + "3730": { "label": "1/7", "naklon": 0 }, + "4374": { "label": "1/8", "naklon": 0 }, + "3718": { "label": "1/9", "naklon": 15 }, + "4375": { "label": "1/10", "naklon": 15 }, + "4172": { "label": "1/11", "naklon": 15 }, + "4176": { "label": "1/12", "naklon": 15 }, + "3800": { "label": "2/1", "naklon": 5 }, + "3823": { "label": "2/2", "naklon": 5 }, + "3905": { "label": "2/3", "naklon": 5 }, + "3803": { "label": "2/4", "naklon": 5 }, + "3817": { "label": "2/5", "naklon": 5 }, + "3818": { "label": "2/6", "naklon": 5 }, + "3811": { "label": "2/7", "naklon": 5 }, + "3915": { "label": "2/8", "naklon": 5 }, + "3843": { "label": "2/9", "naklon": 10 }, + "3827": { "label": "2/10", "naklon": 10 }, + "4220": { "label": "2/11", "naklon": 10 }, + "3826": { "label": "2/12", "naklon": 10 }, + "3834": { "label": "2/13", "naklon": 10 }, + "3838": { "label": "2/14", "naklon": 10 }, + "2823": { "label": "2/15", "naklon": 10 }, + "3750": { "label": "2/16", "naklon": 10 }, + "3378": { "label": "2/17", "naklon": 0 }, + "3376": { "label": "2/18", "naklon": 0 }, + "3379": { "label": "2/19", "naklon": 0 }, + "3285": { "label": "2/20", "naklon": 0 }, + "3382": { "label": "2/21", "naklon": 0 }, + "3383": { "label": "2/22", "naklon": 0 }, + "3375": { "label": "2/24", "naklon": 0 }, + "3381": { "label": "2/25", "naklon": 0 }, + "3380": { "label": "2/26", "naklon": 0 }, + "3828": { "label": "2/27", "naklon": 10 }, + "3377": { "label": "2/28", "naklon": 0 }, + "3591": { "label": "7/1", "naklon": 0 }, + "3587": { "label": "7/2", "naklon": 0 }, + "3468": { "label": "7/3", "naklon": 0 }, + "3466": { "label": "7/4", "naklon": 0 }, + "3474": { "label": "7/5", "naklon": 0 }, + "3481": { "label": "7/6", "naklon": 0 }, + "3589": { "label": "7/7", "naklon": 0 }, + "3472": { "label": "7/8", "naklon": 0 }, + "3473": { "label": "7/9", "naklon": 0 }, + "3584": { "label": "7/10", "naklon": 0 }, + "3571": { "label": "7/11", "naklon": 0 }, + "3476": { "label": "7/12", "naklon": 0 }, + "3590": { "label": "7/13", "naklon": 0 }, + "3478": { "label": "7/14", "naklon": 0 }, + "3471": { "label": "7/15", "naklon": 0 }, + "3467": { "label": "7/16", "naklon": 0 }, + "3479": { "label": "7/17", "naklon": 0 }, + "3480": { "label": "7/18", "naklon": 0 }, + "3477": { "label": "7/19", "naklon": 0 }, + "3362": { "label": "12/1", "naklon": 0 }, + "3355": { "label": "12/2", "naklon": 0 }, + "3356": { "label": "12/3", "naklon": 0 }, + "3349": { "label": "12/4", "naklon": 0 }, + "3357": { "label": "12/5", "naklon": 0 }, + "3350": { "label": "12/6", "naklon": 0 }, + "3353": { "label": "12/7", "naklon": 0 }, + "3539": { "label": "12/8", "naklon": 0 }, + "3050": { "label": "12/9", "naklon": 0 }, + "3361": { "label": "12/10", "naklon": 0 }, + "3360": { "label": "12/11", "naklon": 0 }, + "3358": { "label": "12/12", "naklon": 0 }, + "3541": { "label": "12/13", "naklon": 0 }, + "3551": { "label": "12/14", "naklon": 0 }, + "3514": { "label": "12/15", "naklon": 0 }, + "3547": { "label": "12/16", "naklon": 0 }, + "3562": { "label": "12/17", "naklon": 0 }, + "3525": { "label": "12/18", "naklon": 0 }, + "3558": { "label": "12/19", "naklon": 0 }, + "3511": { "label": "12/20", "naklon": 0 }, + "3058": { "label": "12/21", "naklon": 0 }, + "3062": { "label": "12/22", "naklon": 0 }, + "3070": { "label": "12/23", "naklon": 0 }, + "3447": { "label": "12/24", "naklon": 0 }, + "3056": { "label": "12/25", "naklon": 0 }, + "3057": { "label": "12/26", "naklon": 0 }, + "3071": { "label": "12/27", "naklon": 0 }, + "3061": { "label": "12/28", "naklon": 0 }, + "3069": { "label": "12/29", "naklon": 0 }, + "3077": { "label": "12/30", "naklon": 0 }, + "3080": { "label": "12/31", "naklon": 0 }, + "3081": { "label": "12/32", "naklon": 0 }, + "3078": { "label": "12/33", "naklon": 0 }, + "4037": { "label": "12/34", "naklon": 0 }, + "3067": { "label": "12/35", "naklon": 0 }, + "3051": { "label": "12/36", "naklon": 0 }, + "2924": { "label": "12/37", "naklon": 0 }, + "3060": { "label": "12/38", "naklon": 0 }, + "3073": { "label": "12/39", "naklon": 0 }, + "3469": { "label": "12/40", "naklon": 0 }, + "2923": { "label": "12/41", "naklon": 0 }, + "2925": { "label": "12/42", "naklon": 0 }, + "3359": { "label": "12/43", "naklon": 0 }, + "3055": { "label": "12/44", "naklon": 0 }, + "2922": { "label": "12/45", "naklon": 0 }, + "3084": { "label": "12/46", "naklon": 0 }, + "3064": { "label": "12/47", "naklon": 0 }, + "3066": { "label": "12/48", "naklon": 0 }, + "3072": { "label": "12/49", "naklon": 0 }, + "3415": { "label": "13/13A", "naklon": 0 }, + "3409": { "label": "13/13B", "naklon": 0 }, + "3399": { "label": "13/13C", "naklon": 0 }, + "3410": { "label": "13/29A", "naklon": 0 }, + "3407": { "label": "13/29B", "naklon": 0 }, + "3405": { "label": "13/34A", "naklon": 0 }, + "3404": { "label": "13/34B", "naklon": 0 }, + "3392": { "label": "13/45A", "naklon": 0 }, + "3386": { "label": "13/45B", "naklon": 0 }, + "3303": { "label": "13/60A", "naklon": 3 }, + "3302": { "label": "13/60B", "naklon": 3 }, + "3319": { "label": "13/70A", "naklon": 6 }, + "3317": { "label": "13/70B", "naklon": 6 }, + "3326": { "label": "13/70C", "naklon": 6 }, + "3351": { "label": "13/73A", "naklon": 6 }, + "3313": { "label": "13/73B", "naklon": 6 }, + "3316": { "label": "13/83A", "naklon": 0 }, + "3320": { "label": "13/83B", "naklon": 0 }, + "3336": { "label": "13/95A", "naklon": 0 }, + "3323": { "label": "13/95B", "naklon": 0 }, + "3339": { "label": "13/98A", "naklon": 0 }, + "3333": { "label": "13/98B", "naklon": 0 }, + "3425": { "label": "13/1", "naklon": 0 }, + "3419": { "label": "13/2", "naklon": 0 }, + "3416": { "label": "13/3", "naklon": 0 }, + "3332": { "label": "13/4", "naklon": 0 }, + "3422": { "label": "13/5", "naklon": 0 }, + "3417": { "label": "13/6", "naklon": 0 }, + "3418": { "label": "13/7", "naklon": 0 }, + "3424": { "label": "13/8", "naklon": 0 }, + "3334": { "label": "13/9", "naklon": 0 }, + "4363": { "label": "13/10", "naklon": 0 }, + "3423": { "label": "13/11", "naklon": 0 }, + "3406": { "label": "13/12", "naklon": 0 }, + "3411": { "label": "13/14", "naklon": 0 }, + "3412": { "label": "13/15", "naklon": 0 }, + "3413": { "label": "13/16", "naklon": 0 }, + "3414": { "label": "13/17", "naklon": 0 }, + "3391": { "label": "13/18", "naklon": 0 }, + "3370": { "label": "13/19", "naklon": 0 }, + "3369": { "label": "13/20", "naklon": 0 }, + "3408": { "label": "13/21", "naklon": 0 }, + "3393": { "label": "13/22", "naklon": 0 }, + "3128": { "label": "13/23", "naklon": 0 }, + "3197": { "label": "13/24", "naklon": 0 }, + "4364": { "label": "13/25", "naklon": 0 }, + "3155": { "label": "13/26", "naklon": 0 }, + "3196": { "label": "13/27", "naklon": 0 }, + "3144": { "label": "13/28", "naklon": 0 }, + "3150": { "label": "13/30", "naklon": 0 }, + "3390": { "label": "13/31", "naklon": 0 }, + "3401": { "label": "13/32", "naklon": 0 }, + "3275": { "label": "13/33", "naklon": 0 }, + "3371": { "label": "13/35", "naklon": 0 }, + "3389": { "label": "13/36", "naklon": 0 }, + "3388": { "label": "13/37", "naklon": 0 }, + "3365": { "label": "13/38", "naklon": 0 }, + "3363": { "label": "13/39", "naklon": 0 }, + "3397": { "label": "13/40", "naklon": 0 }, + "3567": { "label": "13/40/1", "naklon": 0 }, + "3387": { "label": "13/41", "naklon": 0 }, + "3403": { "label": "13/42", "naklon": 0 }, + "3147": { "label": "13/43", "naklon": 0 }, + "3141": { "label": "13/44", "naklon": 0 }, + "3364": { "label": "13/46", "naklon": 0 }, + "3367": { "label": "13/47", "naklon": 0 }, + "3368": { "label": "13/48", "naklon": 0 }, + "3402": { "label": "13/49", "naklon": 0 }, + "3366": { "label": "13/50", "naklon": 0 }, + "3395": { "label": "13/51", "naklon": 0 }, + "3372": { "label": "13/52", "naklon": 0 }, + "3394": { "label": "13/53", "naklon": 0 }, + "3308": { "label": "13/54", "naklon": 0 }, + "3847": { "label": "13/54/1", "naklon": 0 }, + "3312": { "label": "13/55", "naklon": 3 }, + "3309": { "label": "13/56", "naklon": 3 }, + "3311": { "label": "13/57", "naklon": 3 }, + "3310": { "label": "13/58", "naklon": 3 }, + "4365": { "label": "13/59", "naklon": 3 }, + "4093": { "label": "13/60/1", "naklon": 3 }, + "3304": { "label": "13/61", "naklon": 3 }, + "3307": { "label": "13/62", "naklon": 3 }, + "3271": { "label": "13/63", "naklon": 3 }, + "3301": { "label": "13/64", "naklon": 3 }, + "4366": { "label": "13/65", "naklon": 3 }, + "3300": { "label": "13/66", "naklon": 3 }, + "3185": { "label": "13/67", "naklon": 0 }, + "3184": { "label": "13/68", "naklon": 0 }, + "3188": { "label": "13/69", "naklon": 0 }, + "3343": { "label": "13/71", "naklon": 6 }, + "3819": { "label": "13/71/1", "naklon": 6 }, + "3880": { "label": "13/71/2", "naklon": 6 }, + "3348": { "label": "13/72", "naklon": 6 }, + "3344": { "label": "13/74", "naklon": 6 }, + "3346": { "label": "13/75", "naklon": 6 }, + "3597": { "label": "13/75/1", "naklon": 6 }, + "3345": { "label": "13/76", "naklon": 6 }, + "3322": { "label": "13/77", "naklon": 0 }, + "3325": { "label": "13/78", "naklon": 0 }, + "4310": { "label": "13/78/1", "naklon": 0 }, + "3315": { "label": "13/79", "naklon": 0 }, + "3328": { "label": "13/80", "naklon": 0 }, + "3321": { "label": "13/81", "naklon": 0 }, + "3324": { "label": "13/82", "naklon": 0 }, + "3140": { "label": "13/84", "naklon": 0 }, + "3153": { "label": "13/85", "naklon": 0 }, + "3145": { "label": "13/86", "naklon": 0 }, + "3134": { "label": "13/87", "naklon": 0 }, + "3151": { "label": "13/88", "naklon": 0 }, + "3143": { "label": "13/89", "naklon": 0 }, + "3318": { "label": "13/90", "naklon": 0 }, + "3347": { "label": "13/91", "naklon": 0 }, + "3314": { "label": "13/94", "naklon": 0 }, + "3331": { "label": "13/96", "naklon": 0 }, + "3327": { "label": "13/97", "naklon": 0 }, + "3329": { "label": "13/99", "naklon": 0 }, + "3337": { "label": "13/100", "naklon": 0 }, + "3330": { "label": "13/101", "naklon": 0 }, + "3335": { "label": "13/102", "naklon": 0 }, + "3420": { "label": "13/103", "naklon": 0 }, + "3421": { "label": "13/104", "naklon": 0 }, + "4361": { "label": "13/105", "naklon": 0 }, + "4362": { "label": "13/106", "naklon": 0 }, + "3526": { "label": "13/107", "naklon": 0 }, + "4424": { "label": "13/108", "naklon": null }, + "3561": { "label": "13/109", "naklon": null }, + "3527": { "label": "13/110", "naklon": null }, + "3521": { "label": "13/111", "naklon": null }, + "3552": { "label": "13/112", "naklon": null }, + "3544": { "label": "13/113", "naklon": null }, + "3534": { "label": "13/114", "naklon": null }, + "3516": { "label": "13/115", "naklon": null }, + "3513": { "label": "13/116", "naklon": null }, + "3565": { "label": "13/117", "naklon": null }, + "3866": { "label": "13/118", "naklon": null }, + "3136": { "label": "14/1", "naklon": 0 }, + "3137": { "label": "14/2", "naklon": 0 }, + "3135": { "label": "14/3", "naklon": 0 }, + "3149": { "label": "14/4", "naklon": 0 }, + "3142": { "label": "14/5", "naklon": 0 }, + "3342": { "label": "14/6", "naklon": 0 }, + "3340": { "label": "14/7", "naklon": 0 }, + "3152": { "label": "14/8", "naklon": 0 }, + "3886": { "label": "14/9", "naklon": 0 }, + "3341": { "label": "14/10", "naklon": null }, + "3352": { "label": "14/11", "naklon": null }, + "3396": { "label": "15/1", "naklon": 5 }, + "2784": { "label": "15/2", "naklon": 5 }, + "2788": { "label": "15/3", "naklon": 5 }, + "2801": { "label": "15/4", "naklon": 5 }, + "2815": { "label": "15/5", "naklon": 5 }, + "2829": { "label": "15/6", "naklon": 5 }, + "2796": { "label": "15/7", "naklon": 5 }, + "2803": { "label": "15/8", "naklon": 5 }, + "4304": { "label": "15/8/1", "naklon": 5 }, + "4311": { "label": "15/8/2", "naklon": 5 }, + "2821": { "label": "15/9", "naklon": 5 }, + "3400": { "label": "15/10", "naklon": 5 }, + "2799": { "label": "15/11", "naklon": 5 }, + "2804": { "label": "15/12", "naklon": 5 }, + "4303": { "label": "15/12/1", "naklon": 5 }, + "4309": { "label": "15/12/2", "naklon": 5 }, + "2806": { "label": "15/13", "naklon": 5 }, + "2787": { "label": "15/14", "naklon": 5 }, + "2809": { "label": "15/15", "naklon": 5 }, + "2814": { "label": "15/16", "naklon": 0 }, + "3934": { "label": "15/17", "naklon": 0 }, + "3192": { "label": "15/18", "naklon": 0 }, + "2812": { "label": "15/19", "naklon": 0 }, + "4070": { "label": "15/20", "naklon": 0 }, + "2826": { "label": "15/21", "naklon": 0 }, + "2808": { "label": "15/22", "naklon": 3 }, + "2795": { "label": "15/23", "naklon": 3 }, + "2807": { "label": "15/24", "naklon": 3 }, + "2831": { "label": "15/25", "naklon": 0 }, + "2862": { "label": "15/26", "naklon": null }, + "2861": { "label": "15/27", "naklon": 0 }, + "2866": { "label": "15/28", "naklon": 0 }, + "3546": { "label": "15/28/1", "naklon": 0 }, + "4146": { "label": "15/29", "naklon": 0 }, + "3001": { "label": "15/29/1", "naklon": 0 }, + "2835": { "label": "15/30", "naklon": 0 }, + "2874": { "label": "15/31", "naklon": 0 }, + "2852": { "label": "15/32", "naklon": 0 }, + "2851": { "label": "15/33", "naklon": 0 }, + "3560": { "label": "15/33/1", "naklon": 0 }, + "2858": { "label": "15/34", "naklon": 0 }, + "4306": { "label": "15/34/1", "naklon": 0 }, + "2856": { "label": "15/35", "naklon": 0 }, + "2847": { "label": "15/36", "naklon": 0 }, + "3556": { "label": "15/36/1", "naklon": 0 }, + "3950": { "label": "15/37", "naklon": 0 }, + "2848": { "label": "15/38", "naklon": 0 }, + "2863": { "label": "15/39", "naklon": 0 }, + "4313": { "label": "15/39/1", "naklon": 0 }, + "2873": { "label": "15/40", "naklon": 0 }, + "2984": { "label": "15/40/1", "naklon": 0 }, + "2854": { "label": "15/41", "naklon": 0 }, + "2859": { "label": "15/42", "naklon": 0 }, + "2872": { "label": "15/43", "naklon": 0 }, + "2849": { "label": "15/44", "naklon": 0 }, + "2864": { "label": "15/45", "naklon": 0 }, + "3553": { "label": "15/46", "naklon": null }, + "3021": { "label": "15/47", "naklon": null }, + "3008": { "label": "15/47/1", "naklon": null }, + "3017": { "label": "15/48", "naklon": null }, + "3014": { "label": "15/49", "naklon": null }, + "2981": { "label": "15/50", "naklon": null }, + "3020": { "label": "15/51", "naklon": null }, + "3027": { "label": "15/52", "naklon": null }, + "3006": { "label": "15/53", "naklon": null }, + "3012": { "label": "15/54", "naklon": null }, + "2738": { "label": "15/55", "naklon": 0 }, + "2725": { "label": "15/56", "naklon": 0 }, + "3016": { "label": "15/57", "naklon": null }, + "3005": { "label": "15/58", "naklon": null }, + "3009": { "label": "15/58/1", "naklon": null }, + "3010": { "label": "15/59", "naklon": 0 }, + "3538": { "label": "15/59/1", "naklon": 0 }, + "4145": { "label": "15/59/2", "naklon": 0 }, + "2713": { "label": "15/60", "naklon": 0 }, + "2789": { "label": "15/61", "naklon": 0 }, + "2736": { "label": "15/62", "naklon": 0 }, + "2739": { "label": "15/63", "naklon": 0 }, + "4346": { "label": "15/64", "naklon": 0 }, + "2731": { "label": "15/65", "naklon": 0 }, + "2818": { "label": "15/66", "naklon": 0 }, + "3557": { "label": "15/66/1", "naklon": 0 }, + "2822": { "label": "15/67", "naklon": 0 }, + "2833": { "label": "15/68", "naklon": 0 }, + "2834": { "label": "15/69", "naklon": 0 }, + "3097": { "label": "15/70", "naklon": 0 }, + "2824": { "label": "15/71", "naklon": 0 }, + "2828": { "label": "15/72", "naklon": 0 }, + "2600": { "label": "15/73", "naklon": 0 }, + "4314": { "label": "15/73/1", "naklon": 0 }, + "2832": { "label": "15/74", "naklon": 0 }, + "4360": { "label": "15/75", "naklon": 0 }, + "2846": { "label": "15/76", "naklon": 0 }, + "2584": { "label": "15/77", "naklon": 0 }, + "2843": { "label": "15/78", "naklon": 0 }, + "4308": { "label": "15/78/1", "naklon": 0 }, + "4144": { "label": "15/79", "naklon": null }, + "2844": { "label": "15/80", "naklon": 0 }, + "2842": { "label": "15/81", "naklon": 0 }, + "2838": { "label": "15/82", "naklon": 0 }, + "2837": { "label": "15/83", "naklon": null }, + "3555": { "label": "15/83/1", "naklon": null }, + "2839": { "label": "15/84", "naklon": 0 }, + "2830": { "label": "15/85", "naklon": 0 }, + "4066": { "label": "15/86", "naklon": 0 }, + "2836": { "label": "15/87", "naklon": 0 }, + "2911": { "label": "15/88", "naklon": 0 }, + "2825": { "label": "15/89", "naklon": 0 }, + "2811": { "label": "15/90", "naklon": 0 }, + "3740": { "label": "15/94", "naklon": 15 }, + "2734": { "label": "15/95", "naklon": 15 }, + "3105": { "label": "15/96", "naklon": 15 }, + "2732": { "label": "15/97", "naklon": 15 }, + "2727": { "label": "15/98", "naklon": 15 }, + "2735": { "label": "15/99", "naklon": 15 }, + "3926": { "label": "15/100", "naklon": 15 }, + "2918": { "label": "15/101", "naklon": 0 }, + "2705": { "label": "15/102", "naklon": 10 }, + "2708": { "label": "15/103", "naklon": 10 }, + "2721": { "label": "15/104", "naklon": 10 }, + "2719": { "label": "15/105", "naklon": 10 }, + "2919": { "label": "15/106", "naklon": 10 }, + "3101": { "label": "15/107", "naklon": 10 }, + "2853": { "label": "15/108", "naklon": 10 }, + "2715": { "label": "15/109", "naklon": 10 }, + "2712": { "label": "15/110", "naklon": 0 }, + "2711": { "label": "15/111", "naklon": 0 }, + "2709": { "label": "15/112", "naklon": 0 }, + "2710": { "label": "15/113", "naklon": 0 }, + "2907": { "label": "15/114", "naklon": 0 }, + "2906": { "label": "15/115", "naklon": 0 }, + "2908": { "label": "15/116", "naklon": 0 }, + "2901": { "label": "15/117", "naklon": 0 }, + "2913": { "label": "15/118", "naklon": 0 }, + "3656": { "label": "15/119", "naklon": 0 }, + "2781": { "label": "15/120", "naklon": 0 }, + "2802": { "label": "15/121", "naklon": 0 }, + "2791": { "label": "15/122", "naklon": 0 }, + "2783": { "label": "15/123", "naklon": 0 }, + "2794": { "label": "15/124", "naklon": 0 }, + "3139": { "label": "15/125", "naklon": 0 }, + "3229": { "label": "15/126", "naklon": 5 }, + "3239": { "label": "15/127", "naklon": 5 }, + "3230": { "label": "15/128", "naklon": 5 }, + "4016": { "label": "15/129", "naklon": null }, + "3608": { "label": "16/16A", "naklon": 0 }, + "4151": { "label": "16/16B", "naklon": 0 }, + "3710": { "label": "16/1", "naklon": 0 }, + "3726": { "label": "16/2", "naklon": 0 }, + "3743": { "label": "16/3", "naklon": 0 }, + "3724": { "label": "16/4", "naklon": 0 }, + "3712": { "label": "16/5", "naklon": 0 }, + "3739": { "label": "16/6", "naklon": 0 }, + "3742": { "label": "16/7", "naklon": 0 }, + "3731": { "label": "16/8", "naklon": 0 }, + "3727": { "label": "16/9", "naklon": 0 }, + "3729": { "label": "16/10", "naklon": 0 }, + "3736": { "label": "16/11", "naklon": 0 }, + "3713": { "label": "16/12", "naklon": 0 }, + "3715": { "label": "16/13", "naklon": 0 }, + "3733": { "label": "16/14", "naklon": 0 }, + "3732": { "label": "16/15", "naklon": 0 }, + "3634": { "label": "16/17", "naklon": 0 }, + "3610": { "label": "16/18", "naklon": 0 }, + "3626": { "label": "16/19", "naklon": 0 }, + "3618": { "label": "16/20", "naklon": 0 }, + "3619": { "label": "16/21", "naklon": 0 }, + "3628": { "label": "16/22", "naklon": 0 }, + "3615": { "label": "16/23", "naklon": 0 }, + "3609": { "label": "16/24", "naklon": 0 }, + "3606": { "label": "16/25", "naklon": 0 }, + "3624": { "label": "16/26", "naklon": 0 }, + "3627": { "label": "16/27", "naklon": 0 }, + "3607": { "label": "16/28", "naklon": 0 }, + "4370": { "label": "16/29", "naklon": 0 }, + "3692": { "label": "16/30", "naklon": 0 }, + "3614": { "label": "16/31", "naklon": 0 }, + "3623": { "label": "16/32", "naklon": 0 }, + "4373": { "label": "16/33", "naklon": 0 }, + "3620": { "label": "16/34", "naklon": 0 }, + "3685": { "label": "16/35", "naklon": 0 }, + "3616": { "label": "16/36", "naklon": 0 }, + "3686": { "label": "16/37", "naklon": 0 }, + "3688": { "label": "16/38", "naklon": 0 }, + "3684": { "label": "16/39", "naklon": 0 }, + "3825": { "label": "16/40", "naklon": 0 }, + "3865": { "label": "16/41", "naklon": 0 }, + "3824": { "label": "16/42", "naklon": 0 }, + "3871": { "label": "16/43", "naklon": 0 }, + "3801": { "label": "16/44", "naklon": 0 }, + "3862": { "label": "16/45", "naklon": 0 }, + "3876": { "label": "16/46", "naklon": 0 }, + "3861": { "label": "16/47", "naklon": 0 }, + "4215": { "label": "16/48", "naklon": 0 }, + "3605": { "label": "16/49", "naklon": 10 }, + "3603": { "label": "16/50", "naklon": 10 }, + "3592": { "label": "16/51", "naklon": 10 }, + "3598": { "label": "16/52", "naklon": 10 }, + "3594": { "label": "16/53", "naklon": 10 }, + "3593": { "label": "16/54", "naklon": 10 }, + "3630": { "label": "16/55", "naklon": 10 }, + "3763": { "label": "16/56", "naklon": 10 }, + "3746": { "label": "16/57", "naklon": 10 }, + "3699": { "label": "16/58", "naklon": 0 }, + "3698": { "label": "16/59", "naklon": 0 }, + "3709": { "label": "16/60", "naklon": null }, + "3708": { "label": "16/61", "naklon": 0 }, + "3703": { "label": "16/62", "naklon": null }, + "3700": { "label": "16/63", "naklon": 0 }, + "3701": { "label": "16/64", "naklon": null }, + "3704": { "label": "16/65", "naklon": 0 }, + "3707": { "label": "16/66", "naklon": null }, + "3810": { "label": "16/67", "naklon": 0 }, + "4208": { "label": "16/68", "naklon": null }, + "3867": { "label": "16/69", "naklon": 0 }, + "4372": { "label": "16/70", "naklon": null }, + "3881": { "label": "16/71", "naklon": 0 }, + "4204": { "label": "16/72", "naklon": null }, + "3869": { "label": "16/73", "naklon": 0 }, + "4202": { "label": "16/74", "naklon": null }, + "3830": { "label": "16/75", "naklon": 0 }, + "3870": { "label": "16/76", "naklon": null }, + "3964": { "label": "16/77", "naklon": 0 }, + "3849": { "label": "16/78", "naklon": 0 }, + "3694": { "label": "16/79", "naklon": null }, + "3717": { "label": "16/80", "naklon": 0 }, + "3877": { "label": "16/81", "naklon": null }, + "3755": { "label": "16/82", "naklon": 0 }, + "3725": { "label": "16/83", "naklon": null }, + "3716": { "label": "16/84", "naklon": 0 }, + "3696": { "label": "16/85", "naklon": null }, + "3702": { "label": "16/86", "naklon": 0 }, + "3706": { "label": "16/87", "naklon": null }, + "3850": { "label": "16/88", "naklon": 0 }, + "3848": { "label": "16/89", "naklon": null }, + "3737": { "label": "16/90", "naklon": null }, + "3705": { "label": "16/91", "naklon": 0 }, + "3723": { "label": "16/92", "naklon": null }, + "3842": { "label": "16/93", "naklon": 0 }, + "3735": { "label": "16/94", "naklon": null }, + "3719": { "label": "16/95", "naklon": 0 }, + "3697": { "label": "16/96", "naklon": 0 }, + "3711": { "label": "16/97", "naklon": 0 }, + "4107": { "label": "16/98", "naklon": null }, + "4112": { "label": "16/99", "naklon": 5 }, + "4106": { "label": "16/100", "naklon": 5 }, + "4111": { "label": "16/101", "naklon": 5 }, + "4091": { "label": "16/102", "naklon": null }, + "4104": { "label": "16/103", "naklon": 5 }, + "4094": { "label": "16/104", "naklon": null }, + "4089": { "label": "16/105", "naklon": 5 }, + "4095": { "label": "16/106", "naklon": null }, + "4102": { "label": "16/107", "naklon": 5 }, + "4105": { "label": "16/108", "naklon": null }, + "3859": { "label": "16/109", "naklon": null }, + "4090": { "label": "16/110", "naklon": 5 }, + "4110": { "label": "16/111", "naklon": null }, + "4097": { "label": "16/112", "naklon": 5 }, + "4099": { "label": "16/113", "naklon": null }, + "4096": { "label": "16/114", "naklon": null }, + "4101": { "label": "16/115", "naklon": 5 }, + "4109": { "label": "16/116", "naklon": null }, + "4092": { "label": "16/117", "naklon": 5 }, + "3631": { "label": "16/118", "naklon": null }, + "3632": { "label": "16/119", "naklon": 0 }, + "3641": { "label": "16/120", "naklon": null }, + "3638": { "label": "16/121", "naklon": 0 }, + "3637": { "label": "16/122", "naklon": null }, + "4142": { "label": "16/123", "naklon": null }, + "4147": { "label": "16/124", "naklon": 5 }, + "4139": { "label": "16/125", "naklon": 5 }, + "3172": { "label": "20/30A", "naklon": 2 }, + "3164": { "label": "20/30B", "naklon": 2 }, + "3247": { "label": "20/1", "naklon": 10 }, + "3296": { "label": "20/2", "naklon": 10 }, + "3246": { "label": "20/3", "naklon": 10 }, + "3270": { "label": "20/4", "naklon": 10 }, + "3294": { "label": "20/5", "naklon": 10 }, + "3298": { "label": "20/6", "naklon": 10 }, + "3297": { "label": "20/7", "naklon": 10 }, + "3293": { "label": "20/8", "naklon": 10 }, + "3299": { "label": "20/9", "naklon": 10 }, + "3295": { "label": "20/10", "naklon": 10 }, + "3244": { "label": "20/11", "naklon": 10 }, + "3249": { "label": "20/12", "naklon": 10 }, + "3268": { "label": "20/13", "naklon": 10 }, + "3245": { "label": "20/14", "naklon": 10 }, + "3278": { "label": "20/15", "naklon": 10 }, + "3280": { "label": "20/16", "naklon": 10 }, + "3292": { "label": "20/17", "naklon": 10 }, + "3287": { "label": "20/18", "naklon": 10 }, + "3282": { "label": "20/19", "naklon": 10 }, + "3273": { "label": "20/20", "naklon": 0 }, + "3157": { "label": "20/21", "naklon": 0 }, + "3283": { "label": "20/22", "naklon": 0 }, + "3159": { "label": "20/23", "naklon": 0 }, + "3289": { "label": "20/24", "naklon": 0 }, + "3163": { "label": "20/25", "naklon": 0 }, + "3126": { "label": "20/26", "naklon": 0 }, + "3171": { "label": "20/27", "naklon": 0 }, + "3162": { "label": "20/28", "naklon": 0 }, + "3279": { "label": "20/29", "naklon": 10 }, + "3173": { "label": "20/31", "naklon": 0 }, + "3127": { "label": "20/32", "naklon": 0 }, + "3131": { "label": "20/33", "naklon": 0 }, + "3129": { "label": "20/34", "naklon": 0 }, + "3276": { "label": "20/35", "naklon": 2 }, + "3290": { "label": "20/36", "naklon": 2 }, + "3132": { "label": "20/37", "naklon": 0 }, + "3138": { "label": "20/38", "naklon": 0 }, + "3272": { "label": "20/39", "naklon": 0 }, + "3291": { "label": "20/40", "naklon": 0 }, + "3277": { "label": "20/41", "naklon": 10 }, + "3286": { "label": "20/42", "naklon": 10 }, + "3281": { "label": "20/43", "naklon": 10 }, + "3288": { "label": "20/44", "naklon": 10 }, + "3284": { "label": "20/45", "naklon": 10 }, + "3167": { "label": "20/46", "naklon": 10 }, + "3872": { "label": "20/47", "naklon": 0 }, + "3124": { "label": "20/48", "naklon": 0 }, + "3133": { "label": "20/49", "naklon": 0 }, + "3158": { "label": "20/50", "naklon": 0 }, + "3169": { "label": "20/51", "naklon": 0 }, + "3146": { "label": "20/52", "naklon": 0 }, + "3160": { "label": "20/53", "naklon": 0 }, + "3248": { "label": "20/54", "naklon": 0 }, + "3156": { "label": "20/55", "naklon": 0 }, + "3161": { "label": "20/56", "naklon": 0 }, + "3170": { "label": "20/57", "naklon": 0 }, + "3168": { "label": "20/58", "naklon": 0 }, + "3125": { "label": "20/59", "naklon": 0 }, + "3166": { "label": "20/60", "naklon": 0 }, + "3130": { "label": "20/61", "naklon": 0 }, + "3563": { "label": "20/62", "naklon": 0 }, + "3550": { "label": "20/63", "naklon": null }, + "3269": { "label": "20/67", "naklon": 0 }, + "2921": { "label": "21/1", "naklon": 0 }, + "2707": { "label": "21/2", "naklon": 0 }, + "2723": { "label": "21/3", "naklon": 0 }, + "2716": { "label": "21/4", "naklon": 0 }, + "2717": { "label": "21/5", "naklon": 0 }, + "2720": { "label": "21/6", "naklon": 0 }, + "2722": { "label": "21/7", "naklon": 0 }, + "2718": { "label": "21/8", "naklon": 0 }, + "2724": { "label": "21/9", "naklon": 0 }, + "2742": { "label": "21/10", "naklon": 0 }, + "2743": { "label": "21/11", "naklon": 0 }, + "2733": { "label": "21/12", "naklon": 0 }, + "2903": { "label": "21/14", "naklon": 0 }, + "2917": { "label": "21/15", "naklon": 0 }, + "2897": { "label": "21/16", "naklon": 0 }, + "2914": { "label": "21/17", "naklon": 0 }, + "2898": { "label": "21/18", "naklon": 0 }, + "2773": { "label": "21/19", "naklon": 0 }, + "2895": { "label": "21/20", "naklon": 0 }, + "2896": { "label": "21/21", "naklon": 0 }, + "2771": { "label": "21/22", "naklon": 0 }, + "2772": { "label": "21/23", "naklon": 0 }, + "2793": { "label": "21/24", "naklon": 0 }, + "2902": { "label": "21/25", "naklon": 0 }, + "2910": { "label": "21/26", "naklon": 0 }, + "2909": { "label": "21/27", "naklon": 0 }, + "2920": { "label": "21/28", "naklon": 0 }, + "2916": { "label": "21/29", "naklon": 0 }, + "2904": { "label": "21/30", "naklon": 0 }, + "2915": { "label": "21/31", "naklon": 0 }, + "2905": { "label": "21/32", "naklon": 0 }, + "2900": { "label": "21/33", "naklon": 0 }, + "2899": { "label": "21/34", "naklon": 0 }, + "2741": { "label": "21/36", "naklon": 0 }, + "2714": { "label": "21/37", "naklon": 0 }, + "2701": { "label": "21/38", "naklon": 0 }, + "2703": { "label": "21/39", "naklon": 0 }, + "2704": { "label": "21/40", "naklon": 0 }, + "2702": { "label": "21/41", "naklon": 0 }, + "2706": { "label": "21/42", "naklon": 0 }, + "2776": { "label": "21/43", "naklon": 0 }, + "2770": { "label": "21/44", "naklon": 0 }, + "2786": { "label": "21/45", "naklon": 0 }, + "2779": { "label": "21/46", "naklon": 0 }, + "2782": { "label": "21/47", "naklon": 0 }, + "2785": { "label": "21/48", "naklon": 0 }, + "2769": { "label": "21/49", "naklon": 0 }, + "3354": { "label": "21/50", "naklon": 0 }, + "2778": { "label": "21/51", "naklon": 0 }, + "2775": { "label": "21/52", "naklon": 0 }, + "2780": { "label": "21/53", "naklon": 0 }, + "2790": { "label": "21/54", "naklon": 0 }, + "2792": { "label": "21/55", "naklon": 0 }, + "2774": { "label": "21/56", "naklon": 0 }, + "2630": { "label": "22/1", "naklon": 0 }, + "2631": { "label": "22/2", "naklon": 0 }, + "2632": { "label": "22/3", "naklon": 0 }, + "2633": { "label": "22/4", "naklon": 0 }, + "2634": { "label": "22/5", "naklon": 0 }, + "2636": { "label": "22/6", "naklon": 0 }, + "4367": { "label": "22/7", "naklon": 0 }, + "2637": { "label": "22/8", "naklon": 0 }, + "2638": { "label": "22/9", "naklon": 0 }, + "2639": { "label": "22/10", "naklon": 0 }, + "2640": { "label": "22/11", "naklon": 0 }, + "2641": { "label": "22/12", "naklon": 0 }, + "2642": { "label": "22/13", "naklon": 0 }, + "2643": { "label": "22/14", "naklon": 0 }, + "2644": { "label": "22/15", "naklon": 0 }, + "2645": { "label": "22/16", "naklon": 0 }, + "2646": { "label": "22/17", "naklon": 0 }, + "2647": { "label": "22/18", "naklon": 0 }, + "2648": { "label": "22/19", "naklon": 0 }, + "2649": { "label": "22/20", "naklon": 0 }, + "2650": { "label": "22/21", "naklon": 0 }, + "2651": { "label": "22/22", "naklon": 0 }, + "4103": { "label": "22/23", "naklon": 0 }, + "2653": { "label": "22/24", "naklon": 0 }, + "2654": { "label": "22/25", "naklon": 0 }, + "2655": { "label": "22/26", "naklon": 0 }, + "2656": { "label": "22/27", "naklon": 0 }, + "2657": { "label": "22/28", "naklon": 0 }, + "2658": { "label": "22/29", "naklon": 0 }, + "2659": { "label": "22/30", "naklon": 0 }, + "2660": { "label": "22/31", "naklon": 0 }, + "2661": { "label": "22/32", "naklon": 0 }, + "3015": { "label": "22/32/1", "naklon": 0 }, + "2662": { "label": "22/33", "naklon": 0 }, + "2663": { "label": "22/34", "naklon": 0 }, + "2664": { "label": "22/35", "naklon": 0 }, + "2665": { "label": "22/36", "naklon": 0 }, + "2666": { "label": "22/37", "naklon": 0 }, + "2667": { "label": "22/38", "naklon": 0 }, + "2668": { "label": "22/39", "naklon": 0 }, + "2669": { "label": "22/40", "naklon": null }, + "2670": { "label": "22/41", "naklon": null }, + "2671": { "label": "22/42", "naklon": null }, + "3087": { "label": "23/9A", "naklon": 10 }, + "3090": { "label": "23/9B", "naklon": 10 }, + "3075": { "label": "23/1", "naklon": 0 }, + "3089": { "label": "23/2", "naklon": 0 }, + "3088": { "label": "23/3", "naklon": 0 }, + "3228": { "label": "23/4", "naklon": 10 }, + "2751": { "label": "23/5", "naklon": 10 }, + "3243": { "label": "23/6", "naklon": 10 }, + "4349": { "label": "23/7", "naklon": 10 }, + "3102": { "label": "23/8", "naklon": 10 }, + "3099": { "label": "23/10", "naklon": 10 }, + "3103": { "label": "23/11", "naklon": 10 }, + "3093": { "label": "23/12", "naklon": 10 }, + "3098": { "label": "23/13", "naklon": 10 }, + "3092": { "label": "23/14", "naklon": 10 }, + "3233": { "label": "23/15", "naklon": 0 }, + "3095": { "label": "23/16", "naklon": 0 }, + "4074": { "label": "23/17", "naklon": 0 }, + "2729": { "label": "23/18", "naklon": 0 }, + "3234": { "label": "23/19", "naklon": 0 }, + "3094": { "label": "23/20", "naklon": 0 }, + "2817": { "label": "23/21", "naklon": 0 }, + "3226": { "label": "23/22", "naklon": 0 }, + "3225": { "label": "23/23", "naklon": 0 }, + "3237": { "label": "23/24", "naklon": 0 }, + "4250": { "label": "23/25", "naklon": 0 }, + "3059": { "label": "23/26", "naklon": 10 }, + "3238": { "label": "23/27", "naklon": 10 }, + "3242": { "label": "23/28", "naklon": 10 }, + "3236": { "label": "23/29", "naklon": 10 }, + "3112": { "label": "23/30", "naklon": 10 }, + "3224": { "label": "23/31", "naklon": 0 }, + "4298": { "label": "23/32", "naklon": 10 }, + "4150": { "label": "23/33", "naklon": 10 }, + "3091": { "label": "23/34", "naklon": 10 }, + "3771": { "label": "25/1", "naklon": 5 }, + "3777": { "label": "25/2", "naklon": 5 }, + "3749": { "label": "25/3", "naklon": 5 }, + "3769": { "label": "25/4", "naklon": 5 }, + "3765": { "label": "25/5", "naklon": 5 }, + "3785": { "label": "25/6", "naklon": 5 }, + "3761": { "label": "25/7", "naklon": 5 }, + "3758": { "label": "25/8", "naklon": 5 }, + "3766": { "label": "25/9", "naklon": 5 }, + "3779": { "label": "25/10", "naklon": 5 }, + "3899": { "label": "25/11", "naklon": 10 }, + "3922": { "label": "25/12", "naklon": 10 }, + "3912": { "label": "25/13", "naklon": 10 }, + "3933": { "label": "25/14", "naklon": 10 }, + "3921": { "label": "25/15", "naklon": 10 }, + "4300": { "label": "25/16", "naklon": 10 }, + "3927": { "label": "25/17", "naklon": 10 }, + "3212": { "label": "25/18", "naklon": 10 }, + "3208": { "label": "25/19", "naklon": 10 }, + "3207": { "label": "25/20", "naklon": 10 }, + "4294": { "label": "25/21", "naklon": 10 }, + "3209": { "label": "25/22", "naklon": 10 }, + "3745": { "label": "25/23", "naklon": 10 }, + "3762": { "label": "25/24", "naklon": 10 }, + "3215": { "label": "25/25", "naklon": 10 }, + "3210": { "label": "25/26", "naklon": 10 }, + "3211": { "label": "25/27", "naklon": 10 }, + "3206": { "label": "25/28", "naklon": 10 }, + "3918": { "label": "25/29", "naklon": 5 }, + "3928": { "label": "25/30", "naklon": 5 }, + "3917": { "label": "25/31", "naklon": 5 }, + "4029": { "label": "25/32", "naklon": 0 }, + "4038": { "label": "25/33", "naklon": 0 }, + "4022": { "label": "25/34", "naklon": 0 }, + "3937": { "label": "25/35", "naklon": 0 }, + "3190": { "label": "25/36", "naklon": 0 }, + "3835": { "label": "25/37", "naklon": 0 }, + "3201": { "label": "25/38", "naklon": 0 }, + "3193": { "label": "25/39", "naklon": 0 }, + "3191": { "label": "25/40", "naklon": 0 }, + "3203": { "label": "25/41", "naklon": 0 }, + "4301": { "label": "25/42", "naklon": 0 }, + "3223": { "label": "25/43", "naklon": 0 }, + "3202": { "label": "25/44", "naklon": 0 }, + "3205": { "label": "25/45", "naklon": 0 }, + "3194": { "label": "25/46", "naklon": 0 }, + "3198": { "label": "25/47", "naklon": 0 }, + "3204": { "label": "25/48", "naklon": 0 }, + "3200": { "label": "25/49", "naklon": 0 }, + "3216": { "label": "25/50", "naklon": 0 }, + "3932": { "label": "25/51", "naklon": 5 }, + "3923": { "label": "25/52", "naklon": 5 }, + "3913": { "label": "25/53", "naklon": 5 }, + "3900": { "label": "25/54", "naklon": 5 }, + "4189": { "label": "25/55", "naklon": 10 }, + "4191": { "label": "25/56", "naklon": 10 }, + "3790": { "label": "25/57", "naklon": 10 }, + "4190": { "label": "25/58", "naklon": 10 }, + "4302": { "label": "25/59", "naklon": 0 }, + "4351": { "label": "25/60", "naklon": 0 }, + "4075": { "label": "25/61", "naklon": 0 }, + "4071": { "label": "25/62", "naklon": 0 }, + "3784": { "label": "25/63", "naklon": 0 }, + "4065": { "label": "25/64", "naklon": 0 }, + "4297": { "label": "25/65", "naklon": 0 }, + "4295": { "label": "25/66", "naklon": 0 }, + "4299": { "label": "25/67", "naklon": 0 }, + "3772": { "label": "25/68", "naklon": 0 }, + "3941": { "label": "25/69", "naklon": 0 }, + "3782": { "label": "25/70", "naklon": 0 }, + "4068": { "label": "25/71", "naklon": 0 }, + "4073": { "label": "25/72", "naklon": 0 }, + "3901": { "label": "25/73", "naklon": 5 }, + "4296": { "label": "25/74", "naklon": 5 }, + "3910": { "label": "25/75", "naklon": 5 }, + "4293": { "label": "25/76", "naklon": 5 }, + "3919": { "label": "25/77", "naklon": 5 }, + "3924": { "label": "25/78", "naklon": 5 }, + "3909": { "label": "25/79", "naklon": 5 }, + "3896": { "label": "25/80", "naklon": 5 }, + "3911": { "label": "25/81", "naklon": 5 }, + "2819": { "label": "25/82", "naklon": 15 }, + "3776": { "label": "25/83", "naklon": 15 }, + "3752": { "label": "25/84", "naklon": 15 }, + "4353": { "label": "25/85", "naklon": 15 }, + "3791": { "label": "25/86", "naklon": 0 }, + "3770": { "label": "25/87", "naklon": 0 }, + "3760": { "label": "25/88", "naklon": 0 }, + "3115": { "label": "25/89", "naklon": 0 }, + "3738": { "label": "25/90", "naklon": 0 }, + "3748": { "label": "25/91", "naklon": 0 }, + "3753": { "label": "25/92", "naklon": 0 }, + "3775": { "label": "25/93", "naklon": 0 }, + "3778": { "label": "25/94", "naklon": 5 }, + "4078": { "label": "25/95", "naklon": 5 }, + "4088": { "label": "25/96", "naklon": 5 }, + "3856": { "label": "25/97", "naklon": 5 }, + "4084": { "label": "25/98", "naklon": 5 }, + "4069": { "label": "25/99", "naklon": 5 }, + "4188": { "label": "25/100", "naklon": 5 }, + "4064": { "label": "25/101", "naklon": 5 }, + "3792": { "label": "25/102", "naklon": 5 }, + "3780": { "label": "25/103", "naklon": 5 }, + "4034": { "label": "25/104", "naklon": 5 }, + "4072": { "label": "25/105", "naklon": 5 }, + "3884": { "label": "25/106", "naklon": 5 }, + "3793": { "label": "25/107", "naklon": 5 }, + "3863": { "label": "25/108", "naklon": 5 }, + "3855": { "label": "25/109", "naklon": 5 }, + "3846": { "label": "33/1", "naklon": 0 }, + "3943": { "label": "33/2", "naklon": 0 }, + "3903": { "label": "33/3", "naklon": 0 }, + "3982": { "label": "33/4", "naklon": 0 }, + "3879": { "label": "33/5", "naklon": 0 }, + "3887": { "label": "33/6", "naklon": 0 }, + "3920": { "label": "33/7", "naklon": 5 }, + "3942": { "label": "33/8", "naklon": 5 }, + "3829": { "label": "33/9", "naklon": null }, + "3452": { "label": "34/79A", "naklon": 6 }, + "3460": { "label": "34/79B", "naklon": 6 }, + "3443": { "label": "34/90A", "naklon": 6 }, + "3445": { "label": "34/90B", "naklon": 6 }, + "3457": { "label": "34/90C", "naklon": 6 }, + "3461": { "label": "34/97A", "naklon": 6 }, + "3463": { "label": "34/97B", "naklon": 6 }, + "3426": { "label": "34/98A", "naklon": 6 }, + "3444": { "label": "34/98B", "naklon": 6 }, + "3453": { "label": "34/99A", "naklon": 6 }, + "3455": { "label": "34/99B", "naklon": 6 }, + "4009": { "label": "34/1", "naklon": 0 }, + "3602": { "label": "34/2", "naklon": 0 }, + "3441": { "label": "34/3", "naklon": 0 }, + "3464": { "label": "34/4", "naklon": 0 }, + "3883": { "label": "34/5", "naklon": 0 }, + "4098": { "label": "34/6", "naklon": 0 }, + "4003": { "label": "34/7", "naklon": 0 }, + "4004": { "label": "34/8", "naklon": 0 }, + "3888": { "label": "34/9", "naklon": 0 }, + "3997": { "label": "34/10", "naklon": 0 }, + "4006": { "label": "34/11", "naklon": 0 }, + "4000": { "label": "34/12", "naklon": 0 }, + "4011": { "label": "34/13", "naklon": 0 }, + "3999": { "label": "34/14", "naklon": 0 }, + "3981": { "label": "34/15", "naklon": 0 }, + "3988": { "label": "34/16", "naklon": 0 }, + "3986": { "label": "34/17", "naklon": 0 }, + "3998": { "label": "34/18", "naklon": 0 }, + "3983": { "label": "34/19", "naklon": 0 }, + "4005": { "label": "34/20", "naklon": 0 }, + "4001": { "label": "34/21", "naklon": 0 }, + "4008": { "label": "34/22", "naklon": 0 }, + "4002": { "label": "34/23", "naklon": 0 }, + "3996": { "label": "34/24", "naklon": 0 }, + "4007": { "label": "34/25", "naklon": 0 }, + "4113": { "label": "34/26", "naklon": 15 }, + "3595": { "label": "34/27", "naklon": 5 }, + "3599": { "label": "34/28", "naklon": 5 }, + "3601": { "label": "34/29", "naklon": 5 }, + "4205": { "label": "34/30", "naklon": 0 }, + "3987": { "label": "34/31", "naklon": null }, + "4214": { "label": "34/32", "naklon": 0 }, + "4226": { "label": "34/33", "naklon": 0 }, + "4209": { "label": "34/34", "naklon": 0 }, + "4201": { "label": "34/35", "naklon": 0 }, + "3440": { "label": "34/36", "naklon": 0 }, + "3465": { "label": "34/37", "naklon": 0 }, + "3446": { "label": "34/38", "naklon": 0 }, + "4039": { "label": "34/39", "naklon": 5 }, + "4057": { "label": "34/40", "naklon": 5 }, + "3985": { "label": "34/41", "naklon": 0 }, + "3882": { "label": "34/42", "naklon": 0 }, + "4040": { "label": "34/43", "naklon": 5 }, + "3231": { "label": "34/44", "naklon": 0 }, + "3227": { "label": "34/45", "naklon": 0 }, + "3431": { "label": "34/46", "naklon": 0 }, + "4013": { "label": "34/47", "naklon": 0 }, + "4045": { "label": "34/48", "naklon": 0 }, + "3949": { "label": "34/49", "naklon": 0 }, + "3953": { "label": "34/50", "naklon": 0 }, + "3952": { "label": "34/51", "naklon": 0 }, + "3995": { "label": "34/52", "naklon": 0 }, + "3992": { "label": "34/53", "naklon": 0 }, + "4198": { "label": "34/54", "naklon": 0 }, + "3935": { "label": "34/55", "naklon": 0 }, + "4050": { "label": "34/56", "naklon": 0 }, + "4049": { "label": "34/57", "naklon": 0 }, + "4054": { "label": "34/58", "naklon": 0 }, + "3663": { "label": "34/59", "naklon": 6 }, + "3661": { "label": "34/60", "naklon": 6 }, + "3664": { "label": "34/61", "naklon": 6 }, + "3660": { "label": "34/62", "naklon": 6 }, + "3662": { "label": "34/63", "naklon": 6 }, + "3665": { "label": "34/65", "naklon": 6 }, + "3667": { "label": "34/66", "naklon": 6 }, + "3675": { "label": "34/67", "naklon": 6 }, + "3666": { "label": "34/68", "naklon": 6 }, + "3652": { "label": "34/69", "naklon": 6 }, + "3458": { "label": "34/70", "naklon": 6 }, + "4425": { "label": "34/70/1", "naklon": 6 }, + "3459": { "label": "34/71", "naklon": 6 }, + "3435": { "label": "34/72", "naklon": 6 }, + "3448": { "label": "34/73", "naklon": 6 }, + "3451": { "label": "34/74", "naklon": 6 }, + "3442": { "label": "34/75", "naklon": 6 }, + "3449": { "label": "34/76", "naklon": 6 }, + "3450": { "label": "34/77", "naklon": 6 }, + "3433": { "label": "34/78", "naklon": 6 }, + "3432": { "label": "34/80", "naklon": 12 }, + "3470": { "label": "34/81", "naklon": 12 }, + "3438": { "label": "34/82", "naklon": 12 }, + "3439": { "label": "34/83", "naklon": 12 }, + "4028": { "label": "34/84", "naklon": 5 }, + "3596": { "label": "34/85", "naklon": 5 }, + "4021": { "label": "34/86", "naklon": 5 }, + "3437": { "label": "34/87", "naklon": 12 }, + "3428": { "label": "34/88", "naklon": 12 }, + "3430": { "label": "34/89", "naklon": 12 }, + "3454": { "label": "34/91", "naklon": 6 }, + "3492": { "label": "34/92", "naklon": 6 }, + "3462": { "label": "34/93", "naklon": 6 }, + "3427": { "label": "34/94", "naklon": 6 }, + "3434": { "label": "34/95", "naklon": 6 }, + "3456": { "label": "34/96", "naklon": 6 }, + "4307": { "label": "34/98/1", "naklon": 6 }, + "3968": { "label": "35/1", "naklon": 0 }, + "3969": { "label": "35/2", "naklon": 0 }, + "3947": { "label": "35/3", "naklon": 0 }, + "3979": { "label": "35/4", "naklon": 0 }, + "3959": { "label": "35/5", "naklon": 0 }, + "3948": { "label": "35/6", "naklon": 0 }, + "3961": { "label": "35/7", "naklon": 0 }, + "3956": { "label": "35/8", "naklon": 0 }, + "3604": { "label": "35/9", "naklon": 0 }, + "3944": { "label": "35/10", "naklon": 0 }, + "3960": { "label": "35/11", "naklon": 0 }, + "3958": { "label": "35/12", "naklon": 0 }, + "4036": { "label": "35/13", "naklon": 5 }, + "3893": { "label": "35/18", "naklon": 5 }, + "4108": { "label": "35/19", "naklon": 5 }, + "4017": { "label": "35/20", "naklon": 5 }, + "3963": { "label": "35/21", "naklon": 0 }, + "3658": { "label": "35/22", "naklon": 0 }, + "3975": { "label": "35/23", "naklon": 0 }, + "3980": { "label": "35/24", "naklon": 0 }, + "4012": { "label": "35/25", "naklon": 0 }, + "3655": { "label": "35/26", "naklon": 0 }, + "3962": { "label": "35/27", "naklon": 0 }, + "3945": { "label": "35/28", "naklon": 0 }, + "3569": { "label": "35/29", "naklon": 0 }, + "3429": { "label": "35/30", "naklon": 0 }, + "3657": { "label": "35/31", "naklon": 0 }, + "3646": { "label": "35/32", "naklon": 0 }, + "3622": { "label": "35/33", "naklon": 0 }, + "3612": { "label": "35/34", "naklon": 0 }, + "3955": { "label": "35/35", "naklon": 0 }, + "3878": { "label": "35/37", "naklon": 0 }, + "3965": { "label": "35/38", "naklon": 0 }, + "3970": { "label": "35/39", "naklon": 0 }, + "3611": { "label": "35/40", "naklon": 0 }, + "2635": { "label": "35/41", "naklon": 0 }, + "3978": { "label": "35/42", "naklon": 0 }, + "4213": { "label": "35/43", "naklon": 0 }, + "3984": { "label": "35/44", "naklon": 0 }, + "4218": { "label": "35/45", "naklon": 0 }, + "3973": { "label": "35/46", "naklon": 0 }, + "3974": { "label": "35/47", "naklon": 0 }, + "3759": { "label": "35/48", "naklon": 0 }, + "3844": { "label": "35/49", "naklon": 0 }, + "3804": { "label": "35/50", "naklon": 0 }, + "3831": { "label": "35/51", "naklon": 0 }, + "3643": { "label": "35/52", "naklon": 0 }, + "3966": { "label": "35/53", "naklon": 0 }, + "3971": { "label": "35/54", "naklon": 0 }, + "3650": { "label": "35/55", "naklon": 6 }, + "3651": { "label": "35/56", "naklon": 6 }, + "3669": { "label": "35/57", "naklon": 6 }, + "3648": { "label": "35/58", "naklon": 6 }, + "3645": { "label": "35/59", "naklon": 6 }, + "3659": { "label": "35/60", "naklon": 6 }, + "3647": { "label": "35/61", "naklon": 6 }, + "3644": { "label": "35/62", "naklon": 6 }, + "3671": { "label": "35/63", "naklon": 6 }, + "3682": { "label": "35/64", "naklon": 6 }, + "3672": { "label": "35/65", "naklon": 6 }, + "3683": { "label": "35/66", "naklon": 6 }, + "3673": { "label": "35/67", "naklon": 6 }, + "3674": { "label": "35/68", "naklon": 6 }, + "3679": { "label": "35/69", "naklon": 6 }, + "3649": { "label": "35/70", "naklon": 6 }, + "3687": { "label": "35/71", "naklon": 6 }, + "3677": { "label": "35/72", "naklon": 6 }, + "3690": { "label": "35/73", "naklon": 6 }, + "3691": { "label": "35/74", "naklon": 6 }, + "3676": { "label": "35/75", "naklon": 6 }, + "3680": { "label": "35/76", "naklon": 6 }, + "3668": { "label": "35/77", "naklon": 6 }, + "3681": { "label": "35/78", "naklon": 6 }, + "3670": { "label": "35/79", "naklon": 6 }, + "3689": { "label": "35/80", "naklon": 6 }, + "3678": { "label": "35/81", "naklon": 6 }, + "3693": { "label": "35/82", "naklon": 6 }, + "3654": { "label": "35/83", "naklon": null }, + "4086": { "label": "36/1", "naklon": 0 }, + "4085": { "label": "36/2", "naklon": 0 }, + "4083": { "label": "36/3", "naklon": 0 }, + "4087": { "label": "36/4", "naklon": 0 }, + "4077": { "label": "36/5", "naklon": 0 }, + "4082": { "label": "36/6", "naklon": 0 }, + "4186": { "label": "36/7", "naklon": 0 }, + "4206": { "label": "36/8", "naklon": 0 }, + "4080": { "label": "36/9", "naklon": 0 }, + "4081": { "label": "36/10", "naklon": 0 }, + "4210": { "label": "36/11", "naklon": 0 }, + "4079": { "label": "36/12", "naklon": 0 }, + "4076": { "label": "36/13", "naklon": 0 }, + "3852": { "label": "36/14", "naklon": 0 }, + "2813": { "label": "36/15", "naklon": 0 }, + "4219": { "label": "36/16", "naklon": 0 }, + "3104": { "label": "37/1A", "naklon": 15 }, + "3121": { "label": "37/1B", "naklon": 15 }, + "3113": { "label": "37/2", "naklon": 10 }, + "3118": { "label": "37/3", "naklon": 10 }, + "3111": { "label": "37/4", "naklon": 10 }, + "4020": { "label": "37/5", "naklon": 10 }, + "3119": { "label": "37/6", "naklon": 10 }, + "3110": { "label": "37/7", "naklon": 10 }, + "3108": { "label": "37/8", "naklon": 10 }, + "3107": { "label": "37/12", "naklon": 0 }, + "3199": { "label": "37/13", "naklon": 0 }, + "3120": { "label": "37/14", "naklon": 0 }, + "3122": { "label": "37/15", "naklon": 0 }, + "3908": { "label": "37/16", "naklon": 0 }, + "3114": { "label": "37/17", "naklon": 0 }, + "3105": { "label": "37/18", "naklon": 0 }, + "3116": { "label": "37/19", "naklon": 0 }, + "3106": { "label": "37/20", "naklon": 0 }, + "2887": { "label": "37/21", "naklon": 5 }, + "2888": { "label": "37/22", "naklon": 5 }, + "2877": { "label": "37/23", "naklon": 5 }, + "2891": { "label": "37/24", "naklon": 5 }, + "2886": { "label": "37/25", "naklon": 5 }, + "2892": { "label": "37/26", "naklon": 5 }, + "2882": { "label": "37/27", "naklon": 5 }, + "2883": { "label": "37/28", "naklon": 5 }, + "2876": { "label": "37/29", "naklon": 5 }, + "3109": { "label": "37/30", "naklon": 5 }, + "4152": { "label": "37/31", "naklon": 5 }, + "3117": { "label": "37/32", "naklon": 5 }, + "2870": { "label": "37/33", "naklon": 5 }, + "2867": { "label": "37/34", "naklon": 0 }, + "2865": { "label": "37/35", "naklon": 0 }, + "3096": { "label": "37/36", "naklon": 0 }, + "2871": { "label": "37/37", "naklon": 0 }, + "2884": { "label": "37/38", "naklon": 0 }, + "2855": { "label": "37/39", "naklon": 0 }, + "2878": { "label": "37/40", "naklon": 0 }, + "2889": { "label": "37/41", "naklon": 0 }, + "2879": { "label": "37/42", "naklon": 0 }, + "2850": { "label": "37/43", "naklon": 0 }, + "2894": { "label": "37/44", "naklon": 0 }, + "2880": { "label": "37/45", "naklon": 0 }, + "2893": { "label": "37/46", "naklon": 0 }, + "2890": { "label": "37/47", "naklon": 0 }, + "4355": { "label": "37/48", "naklon": 0 }, + "2885": { "label": "37/49", "naklon": 0 }, + "2875": { "label": "37/50", "naklon": 0 }, + "3486": { "label": "38/30A", "naklon": 5 }, + "3714": { "label": "38/30B", "naklon": 0 }, + "3483": { "label": "38/32A", "naklon": 5 }, + "3496": { "label": "38/32B", "naklon": 0 }, + "3487": { "label": "38/35A", "naklon": 5 }, + "3498": { "label": "38/35B", "naklon": 5 }, + "3578": { "label": "38/38A", "naklon": 5 }, + "3508": { "label": "38/38B", "naklon": 5 }, + "3787": { "label": "38/59A", "naklon": 5 }, + "3491": { "label": "38/59B", "naklon": 5 }, + "3568": { "label": "38/1", "naklon": null }, + "3502": { "label": "38/2", "naklon": 0 }, + "3836": { "label": "38/3", "naklon": 0 }, + "3588": { "label": "38/4", "naklon": 0 }, + "3493": { "label": "38/5", "naklon": 0 }, + "3580": { "label": "38/6", "naklon": 0 }, + "3572": { "label": "38/7", "naklon": 0 }, + "3506": { "label": "38/8", "naklon": 0 }, + "3503": { "label": "38/9", "naklon": 0 }, + "3579": { "label": "38/10", "naklon": 0 }, + "3586": { "label": "38/11", "naklon": 0 }, + "3495": { "label": "38/12", "naklon": 5 }, + "3492": { "label": "38/13", "naklon": 5 }, + "3532": { "label": "38/14", "naklon": 5 }, + "3574": { "label": "38/15", "naklon": 5 }, + "4140": { "label": "38/16", "naklon": 5 }, + "3795": { "label": "38/17", "naklon": 5 }, + "3788": { "label": "38/18", "naklon": 5 }, + "3796": { "label": "38/19", "naklon": 5 }, + "3797": { "label": "38/20", "naklon": 5 }, + "3798": { "label": "38/21", "naklon": 5 }, + "3786": { "label": "38/22", "naklon": 5 }, + "4067": { "label": "38/23", "naklon": 5 }, + "3773": { "label": "38/24", "naklon": 5 }, + "3774": { "label": "38/25", "naklon": 5 }, + "3789": { "label": "38/26", "naklon": 5 }, + "3520": { "label": "38/27", "naklon": null }, + "3577": { "label": "38/29", "naklon": 5 }, + "3530": { "label": "38/31", "naklon": null }, + "3488": { "label": "38/33", "naklon": 5 }, + "3505": { "label": "38/34", "naklon": 5 }, + "3497": { "label": "38/36", "naklon": 5 }, + "3490": { "label": "38/37", "naklon": 5 }, + "3585": { "label": "38/39", "naklon": 5 }, + "3582": { "label": "38/40", "naklon": 5 }, + "3507": { "label": "38/41", "naklon": 5 }, + "3484": { "label": "38/42", "naklon": 5 }, + "3501": { "label": "38/43", "naklon": 5 }, + "3581": { "label": "38/44", "naklon": 5 }, + "4192": { "label": "38/45", "naklon": 5 }, + "3576": { "label": "38/46", "naklon": 5 }, + "3489": { "label": "38/47", "naklon": 5 }, + "3573": { "label": "38/48", "naklon": 5 }, + "3504": { "label": "38/49", "naklon": 5 }, + "3794": { "label": "38/50", "naklon": 5 }, + "3485": { "label": "38/51", "naklon": 5 }, + "3482": { "label": "38/52", "naklon": 5 }, + "3575": { "label": "38/53", "naklon": 5 }, + "3499": { "label": "38/54", "naklon": 5 }, + "3494": { "label": "38/55", "naklon": 5 }, + "3583": { "label": "38/56", "naklon": 5 }, + "3570": { "label": "38/57", "naklon": 5 }, + "3500": { "label": "38/58", "naklon": 0 }, + "3510": { "label": "38/63", "naklon": null }, + "3512": { "label": "38/64", "naklon": null }, + "3535": { "label": "38/67", "naklon": null }, + "3531": { "label": "38/68", "naklon": null }, + "3537": { "label": "38/69", "naklon": null }, + "3522": { "label": "39/1", "naklon": 10 }, + "4018": { "label": "39/2", "naklon": 10 }, + "4019": { "label": "39/3", "naklon": 10 }, + "4154": { "label": "39/4", "naklon": 5 }, + "3907": { "label": "39/5", "naklon": 5 }, + "4148": { "label": "39/6", "naklon": 0 }, + "4153": { "label": "39/7", "naklon": 0 }, + "3938": { "label": "39/8", "naklon": 0 }, + "3802": { "label": "39/9", "naklon": 0 }, + "4015": { "label": "39/10", "naklon": 0 }, + "3929": { "label": "39/11", "naklon": 0 }, + "3946": { "label": "39/12", "naklon": 0 }, + "4014": { "label": "39/13", "naklon": 0 }, + "4155": { "label": "39/14", "naklon": 0 }, + "4149": { "label": "39/15", "naklon": 0 }, + "3642": { "label": "39/16", "naklon": 0 }, + "3636": { "label": "39/17", "naklon": 5 }, + "3991": { "label": "39/18", "naklon": 0 }, + "3994": { "label": "39/19", "naklon": 0 }, + "3990": { "label": "39/20", "naklon": 0 }, + "3967": { "label": "39/21", "naklon": 0 }, + "3977": { "label": "39/22", "naklon": 0 }, + "3757": { "label": "39/23", "naklon": 15 }, + "3633": { "label": "39/24", "naklon": 15 }, + "3744": { "label": "39/25", "naklon": 15 }, + "4023": { "label": "39/26", "naklon": 5 }, + "3720": { "label": "39/27", "naklon": 5 }, + "3734": { "label": "39/28", "naklon": 5 }, + "3741": { "label": "39/29", "naklon": 5 }, + "3721": { "label": "39/30", "naklon": 5 }, + "3845": { "label": "39/31", "naklon": 0 }, + "3840": { "label": "39/32", "naklon": 0 }, + "3837": { "label": "39/33", "naklon": null }, + "3839": { "label": "39/34", "naklon": 0 }, + "3542": { "label": "41/1", "naklon": null }, + "3566": { "label": "41/2", "naklon": null }, + "3548": { "label": "41/3", "naklon": null }, + "3515": { "label": "41/4", "naklon": null }, + "3559": { "label": "41/5", "naklon": null }, + "3509": { "label": "41/6", "naklon": null }, + "3524": { "label": "41/7", "naklon": null }, + "3518": { "label": "41/8", "naklon": null }, + "3182": { "label": "41/9", "naklon": null }, + "3187": { "label": "41/10", "naklon": null }, + "3195": { "label": "41/11", "naklon": 0 }, + "3857": { "label": "41/12", "naklon": 0 }, + "3183": { "label": "41/13", "naklon": 0 }, + "3177": { "label": "41/14", "naklon": 0 }, + "3189": { "label": "41/15", "naklon": 0 }, + "3186": { "label": "41/16", "naklon": 0 }, + "3178": { "label": "42/1", "naklon": 0 }, + "3219": { "label": "42/2", "naklon": 0 }, + "3475": { "label": "42/3", "naklon": 0 }, + "3175": { "label": "42/4", "naklon": 0 }, + "3222": { "label": "42/5", "naklon": 0 }, + "3221": { "label": "42/6", "naklon": 0 }, + "3181": { "label": "42/7", "naklon": 0 }, + "3180": { "label": "42/8", "naklon": 0 }, + "3218": { "label": "42/9", "naklon": 0 }, + "3176": { "label": "42/10", "naklon": 0 }, + "3174": { "label": "42/11", "naklon": 0 }, + "3220": { "label": "42/12", "naklon": 0 }, + "3533": { "label": "42/13", "naklon": null }, + "3543": { "label": "42/14", "naklon": null }, + "3554": { "label": "42/15", "naklon": null }, + "3549": { "label": "42/16", "naklon": null }, + "2857": { "label": "43/1", "naklon": 5 }, + "2752": { "label": "43/2", "naklon": 5 }, + "2753": { "label": "43/3", "naklon": 5 }, + "3024": { "label": "43/4", "naklon": 5 }, + "2754": { "label": "43/5", "naklon": 5 }, + "4423": { "label": "43/6", "naklon": 5 }, + "4368": { "label": "43/7", "naklon": 5 }, + "2978": { "label": "43/8", "naklon": 5 }, + "2868": { "label": "43/9", "naklon": 5 }, + "4377": { "label": "43/10", "naklon": 5 }, + "2757": { "label": "43/11", "naklon": 5 }, + "2970": { "label": "43/12", "naklon": 5 }, + "2758": { "label": "43/13", "naklon": 5 }, + "4378": { "label": "43/14", "naklon": 5 }, + "2759": { "label": "43/15", "naklon": 5 }, + "4342": { "label": "43/16", "naklon": 5 }, + "3026": { "label": "43/17", "naklon": null }, + "2986": { "label": "43/18", "naklon": null }, + "4343": { "label": "43/19", "naklon": null }, + "2760": { "label": "43/20", "naklon": null }, + "4379": { "label": "43/21", "naklon": null }, + "2971": { "label": "43/22", "naklon": null }, + "2761": { "label": "43/23", "naklon": null }, + "2762": { "label": "43/24", "naklon": null }, + "4339": { "label": "43/25", "naklon": null }, + "4380": { "label": "43/26", "naklon": null }, + "2975": { "label": "43/27", "naklon": null }, + "3003": { "label": "43/28", "naklon": null }, + "4338": { "label": "43/29", "naklon": null }, + "3002": { "label": "43/30", "naklon": null }, + "4345": { "label": "43/31", "naklon": null }, + "2979": { "label": "43/32", "naklon": null }, + "2989": { "label": "43/33", "naklon": null }, + "2996": { "label": "43/34", "naklon": null }, + "2972": { "label": "43/35", "naklon": null }, + "2988": { "label": "43/36", "naklon": null }, + "4344": { "label": "43/37", "naklon": null }, + "3022": { "label": "43/38", "naklon": null }, + "4341": { "label": "43/39", "naklon": null }, + "2983": { "label": "43/40", "naklon": null }, + "2995": { "label": "43/41", "naklon": null }, + "2763": { "label": "43/42", "naklon": null }, + "2764": { "label": "43/43", "naklon": null }, + "2765": { "label": "43/44", "naklon": null }, + "2766": { "label": "43/45", "naklon": null }, + "2767": { "label": "43/46", "naklon": null }, + "2768": { "label": "43/47", "naklon": null }, + "3018": { "label": "43/48", "naklon": null }, + "2982": { "label": "43/49", "naklon": null }, + "3019": { "label": "43/50", "naklon": 0 }, + "3013": { "label": "43/51", "naklon": null }, + "3007": { "label": "43/52", "naklon": null }, + "2980": { "label": "43/53", "naklon": null }, + "3011": { "label": "43/54", "naklon": null }, + "2672": { "label": "43/55", "naklon": null }, + "2673": { "label": "43/56", "naklon": null }, + "2674": { "label": "43/57", "naklon": null }, + "2675": { "label": "43/58", "naklon": null }, + "2676": { "label": "43/59", "naklon": null }, + "2677": { "label": "43/60", "naklon": null }, + "2678": { "label": "43/61", "naklon": null }, + "2679": { "label": "43/62", "naklon": null }, + "2680": { "label": "43/63", "naklon": null }, + "2840": { "label": "43/64", "naklon": null }, + "2682": { "label": "43/65", "naklon": null }, + "2683": { "label": "43/66", "naklon": null }, + "2684": { "label": "43/67", "naklon": 0 }, + "2685": { "label": "43/68", "naklon": null }, + "2686": { "label": "43/69", "naklon": null }, + "2687": { "label": "43/70", "naklon": null }, + "2688": { "label": "43/71", "naklon": null }, + "2689": { "label": "43/72", "naklon": null }, + "2690": { "label": "43/73", "naklon": null }, + "2691": { "label": "43/74", "naklon": null }, + "2692": { "label": "43/75", "naklon": null }, + "2693": { "label": "43/76", "naklon": 0 }, + "2694": { "label": "43/77", "naklon": null }, + "2695": { "label": "43/78", "naklon": null }, + "2696": { "label": "43/79", "naklon": 0 }, + "2697": { "label": "43/80", "naklon": null }, + "2698": { "label": "43/81", "naklon": 0 }, + "2699": { "label": "43/82", "naklon": null }, + "2700": { "label": "43/83", "naklon": 0 }, + "2744": { "label": "43/84", "naklon": null }, + "2745": { "label": "43/85", "naklon": 0 }, + "2746": { "label": "43/86", "naklon": null }, + "2747": { "label": "43/87", "naklon": 0 }, + "2748": { "label": "43/88", "naklon": null }, + "2749": { "label": "43/89", "naklon": 0 }, + "2841": { "label": "43/90", "naklon": null }, + "4237": { "label": "45/1", "naklon": 5 }, + "4226": { "label": "45/2", "naklon": 5 }, + "4242": { "label": "45/3", "naklon": 5 }, + "4179": { "label": "45/4", "naklon": 5 }, + "4247": { "label": "45/5", "naklon": 5 }, + "4245": { "label": "45/6", "naklon": 5 }, + "3872": { "label": "45/7", "naklon": 5 }, + "4175": { "label": "45/8", "naklon": 5 }, + "4236": { "label": "45/9", "naklon": 5 }, + "4170": { "label": "45/10", "naklon": 5 }, + "4238": { "label": "45/11", "naklon": 5 }, + "4246": { "label": "45/12", "naklon": 5 }, + "4166": { "label": "45/13", "naklon": 5 }, + "4227": { "label": "45/14", "naklon": 5 }, + "4171": { "label": "45/15", "naklon": 5 }, + "4180": { "label": "45/16", "naklon": 5 }, + "4244": { "label": "45/17", "naklon": 5 }, + "4199": { "label": "45/18", "naklon": 5 }, + "4239": { "label": "45/19", "naklon": 5 }, + "4207": { "label": "45/20", "naklon": 5 }, + "4223": { "label": "45/21", "naklon": 5 }, + "4230": { "label": "45/22", "naklon": 5 }, + "4233": { "label": "45/23", "naklon": 5 }, + "4222": { "label": "45/24", "naklon": 5 }, + "4217": { "label": "45/25", "naklon": 5 }, + "4243": { "label": "45/26", "naklon": 5 }, + "4200": { "label": "45/27", "naklon": 5 }, + "4228": { "label": "45/28", "naklon": 5 }, + "4211": { "label": "45/29", "naklon": 5 }, + "4234": { "label": "45/30", "naklon": 5 }, + "4235": { "label": "45/31", "naklon": 5 }, + "4203": { "label": "45/32", "naklon": 5 }, + "4240": { "label": "45/33", "naklon": 5 }, + "4224": { "label": "45/34", "naklon": 5 }, + "4232": { "label": "45/35", "naklon": 5 }, + "4231": { "label": "45/36", "naklon": 5 }, + "4161": { "label": "45/37", "naklon": 5 }, + "4225": { "label": "45/38", "naklon": 5 }, + "4241": { "label": "45/39", "naklon": 5 }, + "4229": { "label": "45/40", "naklon": 5 }, + "4221": { "label": "45/41", "naklon": 5 }, + "4212": { "label": "45/42", "naklon": 5 }, + "4216": { "label": "45/43", "naklon": 5 }, + "3864": { "label": "45/44", "naklon": null }, + "3806": { "label": "46/1", "naklon": 5 }, + "3813": { "label": "46/2", "naklon": 5 }, + "3815": { "label": "46/3", "naklon": 5 }, + "3807": { "label": "46/4", "naklon": 5 }, + "3895": { "label": "46/5", "naklon": 5 }, + "3809": { "label": "46/6", "naklon": 5 }, + "3820": { "label": "46/7", "naklon": 5 }, + "3805": { "label": "46/8", "naklon": 5 }, + "3894": { "label": "46/9", "naklon": 0 }, + "4055": { "label": "46/10", "naklon": 0 }, + "3812": { "label": "46/11", "naklon": 5 }, + "3822": { "label": "46/12", "naklon": 5 }, + "3821": { "label": "46/13", "naklon": 5 }, + "3808": { "label": "46/14", "naklon": 5 }, + "3799": { "label": "46/15", "naklon": 5 }, + "3816": { "label": "46/16", "naklon": 5 }, + "3751": { "label": "46/17", "naklon": 5 }, + "3814": { "label": "46/18", "naklon": 5 }, + "4044": { "label": "46/19", "naklon": 0 }, + "3931": { "label": "46/20", "naklon": 0 }, + "3902": { "label": "46/21", "naklon": 5 }, + "3916": { "label": "46/22", "naklon": 5 }, + "3892": { "label": "46/23", "naklon": 5 }, + "3914": { "label": "46/24", "naklon": 5 }, + "3898": { "label": "46/25", "naklon": 5 }, + "3897": { "label": "46/26", "naklon": 5 }, + "3885": { "label": "46/27", "naklon": 5 }, + "3906": { "label": "46/28", "naklon": 5 }, + "3930": { "label": "46/29", "naklon": 0 }, + "3936": { "label": "46/30", "naklon": 0 }, + "3860": { "label": "46/31", "naklon": 5 }, + "3841": { "label": "46/32", "naklon": 5 }, + "3873": { "label": "46/33", "naklon": 5 }, + "3854": { "label": "46/34", "naklon": 5 }, + "3939": { "label": "46/35", "naklon": 5 }, + "3858": { "label": "46/36", "naklon": 5 }, + "3940": { "label": "46/37", "naklon": 5 }, + "4035": { "label": "46/38", "naklon": 5 }, + "3373": { "label": "47/1", "naklon": 0 }, + "3374": { "label": "47/2", "naklon": 0 }, + "3384": { "label": "47/3", "naklon": 0 }, + "3385": { "label": "47/4", "naklon": 0 }, + "4051": { "label": "48/1", "naklon": 5 }, + "4041": { "label": "48/2", "naklon": 5 }, + "4056": { "label": "48/3", "naklon": 5 }, + "3875": { "label": "48/4", "naklon": 5 }, + "4061": { "label": "48/5", "naklon": 5 }, + "4047": { "label": "48/6", "naklon": 5 }, + "4060": { "label": "48/7", "naklon": 5 }, + "4059": { "label": "48/8", "naklon": 5 }, + "4058": { "label": "48/9", "naklon": 5 }, + "3635": { "label": "48/10", "naklon": 5 }, + "3640": { "label": "48/11", "naklon": 5 }, + "3747": { "label": "48/12", "naklon": 5 }, + "3629": { "label": "48/13", "naklon": 5 }, + "4048": { "label": "48/14", "naklon": 5 }, + "4063": { "label": "48/15", "naklon": 5 }, + "4062": { "label": "48/16", "naklon": 5 }, + "4043": { "label": "48/17", "naklon": 5 }, + "4052": { "label": "48/18", "naklon": 5 }, + "4042": { "label": "48/19", "naklon": 5 }, + "4053": { "label": "48/20", "naklon": 5 }, + "4167": { "label": "50/15A", "naklon": null }, + "4159": { "label": "50/15B", "naklon": null }, + "4183": { "label": "50/1", "naklon": 0 }, + "4157": { "label": "50/2", "naklon": 0 }, + "4160": { "label": "50/3", "naklon": 0 }, + "4173": { "label": "50/4", "naklon": 0 }, + "4177": { "label": "50/5", "naklon": 0 }, + "4174": { "label": "50/6", "naklon": 0 }, + "4178": { "label": "50/7", "naklon": 0 }, + "4195": { "label": "50/8", "naklon": 0 }, + "4169": { "label": "50/9", "naklon": 0 }, + "4162": { "label": "50/10", "naklon": 0 }, + "4158": { "label": "50/11", "naklon": 0 }, + "4182": { "label": "50/12", "naklon": 0 }, + "4194": { "label": "50/13", "naklon": 0 }, + "4184": { "label": "50/14", "naklon": 0 }, + "4197": { "label": "50/16", "naklon": null }, + "4164": { "label": "50/17", "naklon": null }, + "3306": { "label": "50/18", "naklon": null }, + "4168": { "label": "50/19", "naklon": null }, + "4193": { "label": "50/20", "naklon": null }, + "4187": { "label": "50/21", "naklon": null }, + "4163": { "label": "50/22", "naklon": null }, + "4165": { "label": "50/23", "naklon": null }, + "4185": { "label": "50/24", "naklon": null }, + "3904": { "label": "50/25", "naklon": null }, + "2619": { "label": "53/1", "naklon": 0 }, + "2623": { "label": "53/2", "naklon": 0 }, + "2617": { "label": "53/3", "naklon": 0 }, + "2622": { "label": "53/4", "naklon": 0 }, + "2618": { "label": "53/5", "naklon": 0 }, + "2626": { "label": "53/6", "naklon": 0 }, + "2869": { "label": "53/7", "naklon": 0 }, + "2613": { "label": "53/8", "naklon": 0 }, + "2608": { "label": "53/9", "naklon": 0 }, + "2611": { "label": "53/10", "naklon": 0 }, + "2598": { "label": "53/11", "naklon": 0 }, + "3528": { "label": "53/12", "naklon": 0 }, + "3545": { "label": "53/13", "naklon": 0 }, + "2620": { "label": "53/14", "naklon": 0 }, + "2612": { "label": "53/15", "naklon": 0 }, + "2615": { "label": "53/16", "naklon": 0 }, + "3722": { "label": "53/17", "naklon": 0 }, + "2624": { "label": "53/18", "naklon": 0 }, + "2609": { "label": "53/19", "naklon": 0 }, + "2625": { "label": "53/20", "naklon": 0 }, + "2602": { "label": "53/21", "naklon": 0 }, + "2610": { "label": "53/22", "naklon": 0 }, + "2599": { "label": "53/23", "naklon": 0 }, + "2605": { "label": "53/24", "naklon": 0 }, + "2593": { "label": "53/25", "naklon": 0 }, + "3074": { "label": "53/26", "naklon": 0 }, + "2740": { "label": "53/27", "naklon": 0 }, + "2614": { "label": "53/28", "naklon": 0 }, + "2601": { "label": "53/29", "naklon": 0 }, + "4196": { "label": "53/30", "naklon": 0 }, + "2607": { "label": "53/31", "naklon": 0 }, + "2582": { "label": "53/32", "naklon": 0 }, + "2594": { "label": "53/33", "naklon": 0 }, + "2589": { "label": "53/34", "naklon": 0 }, + "2596": { "label": "53/35", "naklon": 0 }, + "2603": { "label": "53/36", "naklon": 0 }, + "2597": { "label": "53/37", "naklon": 0 }, + "2590": { "label": "53/38", "naklon": 0 }, + "2581": { "label": "53/39", "naklon": 0 }, + "2583": { "label": "53/40", "naklon": 0 }, + "2580": { "label": "53/41", "naklon": 0 }, + "2579": { "label": "53/42", "naklon": 0 }, + "2797": { "label": "53/43", "naklon": 0 }, + "2577": { "label": "53/44", "naklon": 0 }, + "2586": { "label": "53/45", "naklon": 0 }, + "2588": { "label": "53/46", "naklon": 0 }, + "2591": { "label": "53/47", "naklon": 0 }, + "2592": { "label": "53/48", "naklon": 0 }, + "2573": { "label": "53/49", "naklon": 0 }, + "2595": { "label": "53/50", "naklon": 0 }, + "2587": { "label": "53/51", "naklon": 0 }, + "2578": { "label": "53/52", "naklon": 0 }, + "2574": { "label": "53/53", "naklon": 0 }, + "2571": { "label": "53/54", "naklon": 0 }, + "2570": { "label": "53/55", "naklon": 0 }, + "2576": { "label": "53/56", "naklon": 0 }, + "2881": { "label": "53/57", "naklon": 0 }, + "2575": { "label": "53/58", "naklon": 0 }, + "2572": { "label": "53/59", "naklon": 0 }, + "2569": { "label": "53/60", "naklon": 0 }, + "4324": { "label": "55/1", "naklon": 0 }, + "4319": { "label": "55/2", "naklon": 0 }, + "4327": { "label": "55/3", "naklon": 0 }, + "4333": { "label": "55/4", "naklon": 0 }, + "4332": { "label": "55/5", "naklon": 0 }, + "4320": { "label": "55/6", "naklon": 0 }, + "4317": { "label": "55/7", "naklon": 0 }, + "4318": { "label": "55/8", "naklon": 0 }, + "4328": { "label": "55/9", "naklon": 0 }, + "4323": { "label": "55/10", "naklon": 0 }, + "4325": { "label": "55/11", "naklon": 0 }, + "4326": { "label": "55/12", "naklon": 0 }, + "4316": { "label": "55/13", "naklon": 0 }, + "4322": { "label": "55/14", "naklon": 0 }, + "4331": { "label": "55/15", "naklon": 0 }, + "4321": { "label": "55/16", "naklon": 0 }, + "4315": { "label": "55/17", "naklon": 0 }, + "4329": { "label": "55/18", "naklon": 0 }, + "4334": { "label": "55/19", "naklon": 0 }, + "4330": { "label": "55/20", "naklon": 0 } +}; + + +let svetlaSorted = [{ "label": "1/3A", "node": 3993, "naklon": 0 }, +{ "label": "1/3B", "node": 3989, "naklon": 15 }, +{ "label": "1/1", "node": 3976, "naklon": 0 }, +{ "label": "1/2", "node": 4181, "naklon": 0 }, +{ "label": "1/4", "node": 4376, "naklon": 15 }, +{ "label": "1/5", "node": 3868, "naklon": 15 }, +{ "label": "1/6", "node": 3728, "naklon": 15 }, +{ "label": "1/7", "node": 3730, "naklon": 0 }, +{ "label": "1/8", "node": 4374, "naklon": 0 }, +{ "label": "1/9", "node": 3718, "naklon": 15 }, +{ "label": "1/10", "node": 4375, "naklon": 15 }, +{ "label": "1/11", "node": 4172, "naklon": 15 }, +{ "label": "1/12", "node": 4176, "naklon": 15 }, +{ "label": "2/1", "node": 3800, "naklon": 5 }, +{ "label": "2/2", "node": 3823, "naklon": 5 }, +{ "label": "2/3", "node": 3905, "naklon": 5 }, +{ "label": "2/4", "node": 3803, "naklon": 5 }, +{ "label": "2/5", "node": 3817, "naklon": 5 }, +{ "label": "2/6", "node": 3818, "naklon": 5 }, +{ "label": "2/7", "node": 3811, "naklon": 5 }, +{ "label": "2/8", "node": 3915, "naklon": 5 }, +{ "label": "2/9", "node": 3843, "naklon": 10 }, +{ "label": "2/10", "node": 3827, "naklon": 10 }, +{ "label": "2/11", "node": 4220, "naklon": 10 }, +{ "label": "2/12", "node": 3826, "naklon": 10 }, +{ "label": "2/13", "node": 3834, "naklon": 10 }, +{ "label": "2/14", "node": 3838, "naklon": 10 }, +{ "label": "2/15", "node": 2823, "naklon": 10 }, +{ "label": "2/16", "node": 3750, "naklon": 10 }, +{ "label": "2/17", "node": 3378, "naklon": 0 }, +{ "label": "2/18", "node": 3376, "naklon": 0 }, +{ "label": "2/19", "node": 3379, "naklon": 0 }, +{ "label": "2/20", "node": 3285, "naklon": 0 }, +{ "label": "2/21", "node": 3382, "naklon": 0 }, +{ "label": "2/22", "node": 3383, "naklon": 0 }, +{ "label": "2/24", "node": 3375, "naklon": 0 }, +{ "label": "2/25", "node": 3381, "naklon": 0 }, +{ "label": "2/26", "node": 3380, "naklon": 0 }, +{ "label": "2/27", "node": 3828, "naklon": 10 }, +{ "label": "2/28", "node": 3377, "naklon": 0 }, +{ "label": "7/1", "node": 3591, "naklon": 0 }, +{ "label": "7/2", "node": 3587, "naklon": 0 }, +{ "label": "7/3", "node": 3468, "naklon": 0 }, +{ "label": "7/4", "node": 3466, "naklon": 0 }, +{ "label": "7/5", "node": 3474, "naklon": 0 }, +{ "label": "7/6", "node": 3481, "naklon": 0 }, +{ "label": "7/7", "node": 3589, "naklon": 0 }, +{ "label": "7/8", "node": 3472, "naklon": 0 }, +{ "label": "7/9", "node": 3473, "naklon": 0 }, +{ "label": "7/10", "node": 3584, "naklon": 0 }, +{ "label": "7/11", "node": 3571, "naklon": 0 }, +{ "label": "7/12", "node": 3476, "naklon": 0 }, +{ "label": "7/13", "node": 3590, "naklon": 0 }, +{ "label": "7/14", "node": 3478, "naklon": 0 }, +{ "label": "7/15", "node": 3471, "naklon": 0 }, +{ "label": "7/16", "node": 3467, "naklon": 0 }, +{ "label": "7/17", "node": 3479, "naklon": 0 }, +{ "label": "7/18", "node": 3480, "naklon": 0 }, +{ "label": "7/19", "node": 3477, "naklon": 0 }, +{ "label": "12/1", "node": 3362, "naklon": 0 }, +{ "label": "12/2", "node": 3355, "naklon": 0 }, +{ "label": "12/3", "node": 3356, "naklon": 0 }, +{ "label": "12/4", "node": 3349, "naklon": 0 }, +{ "label": "12/5", "node": 3357, "naklon": 0 }, +{ "label": "12/6", "node": 3350, "naklon": 0 }, +{ "label": "12/7", "node": 3353, "naklon": 0 }, +{ "label": "12/8", "node": 3539, "naklon": 0 }, +{ "label": "12/9", "node": 3050, "naklon": 0 }, +{ "label": "12/10", "node": 3361, "naklon": 0 }, +{ "label": "12/11", "node": 3360, "naklon": 0 }, +{ "label": "12/12", "node": 3358, "naklon": 0 }, +{ "label": "12/13", "node": 3541, "naklon": 0 }, +{ "label": "12/14", "node": 3551, "naklon": 0 }, +{ "label": "12/15", "node": 3514, "naklon": 0 }, +{ "label": "12/16", "node": 3547, "naklon": 0 }, +{ "label": "12/17", "node": 3562, "naklon": 0 }, +{ "label": "12/18", "node": 3525, "naklon": 0 }, +{ "label": "12/19", "node": 3558, "naklon": 0 }, +{ "label": "12/20", "node": 3511, "naklon": 0 }, +{ "label": "12/21", "node": 3058, "naklon": 0 }, +{ "label": "12/22", "node": 3062, "naklon": 0 }, +{ "label": "12/23", "node": 3070, "naklon": 0 }, +{ "label": "12/24", "node": 3447, "naklon": 0 }, +{ "label": "12/25", "node": 3056, "naklon": 0 }, +{ "label": "12/26", "node": 3057, "naklon": 0 }, +{ "label": "12/27", "node": 3071, "naklon": 0 }, +{ "label": "12/28", "node": 3061, "naklon": 0 }, +{ "label": "12/29", "node": 3069, "naklon": 0 }, +{ "label": "12/30", "node": 3077, "naklon": 0 }, +{ "label": "12/31", "node": 3080, "naklon": 0 }, +{ "label": "12/32", "node": 3081, "naklon": 0 }, +{ "label": "12/33", "node": 3078, "naklon": 0 }, +{ "label": "12/34", "node": 4037, "naklon": 0 }, +{ "label": "12/35", "node": 3067, "naklon": 0 }, +{ "label": "12/36", "node": 3051, "naklon": 0 }, +{ "label": "12/37", "node": 2924, "naklon": 0 }, +{ "label": "12/38", "node": 3060, "naklon": 0 }, +{ "label": "12/39", "node": 3073, "naklon": 0 }, +{ "label": "12/40", "node": 3469, "naklon": 0 }, +{ "label": "12/41", "node": 2923, "naklon": 0 }, +{ "label": "12/42", "node": 2925, "naklon": 0 }, +{ "label": "12/43", "node": 3359, "naklon": 0 }, +{ "label": "12/44", "node": 3055, "naklon": 0 }, +{ "label": "12/45", "node": 2922, "naklon": 0 }, +{ "label": "12/46", "node": 3084, "naklon": 0 }, +{ "label": "12/47", "node": 3064, "naklon": 0 }, +{ "label": "12/48", "node": 3066, "naklon": 0 }, +{ "label": "12/49", "node": 3072, "naklon": 0 }, +{ "label": "13/13A", "node": 3415, "naklon": 0 }, +{ "label": "13/13B", "node": 3409, "naklon": 0 }, +{ "label": "13/13C", "node": 3399, "naklon": 0 }, +{ "label": "13/29A", "node": 3410, "naklon": 0 }, +{ "label": "13/29B", "node": 3407, "naklon": 0 }, +{ "label": "13/34A", "node": 3405, "naklon": 0 }, +{ "label": "13/34B", "node": 3404, "naklon": 0 }, +{ "label": "13/45A", "node": 3392, "naklon": 0 }, +{ "label": "13/45B", "node": 3386, "naklon": 0 }, +{ "label": "13/60A", "node": 3303, "naklon": 3 }, +{ "label": "13/60B", "node": 3302, "naklon": 3 }, +{ "label": "13/70A", "node": 3319, "naklon": 6 }, +{ "label": "13/70B", "node": 3317, "naklon": 6 }, +{ "label": "13/70C", "node": 3326, "naklon": 6 }, +{ "label": "13/73A", "node": 3351, "naklon": 6 }, +{ "label": "13/73B", "node": 3313, "naklon": 6 }, +{ "label": "13/83A", "node": 3316, "naklon": 0 }, +{ "label": "13/83B", "node": 3320, "naklon": 0 }, +{ "label": "13/95A", "node": 3336, "naklon": 0 }, +{ "label": "13/95B", "node": 3323, "naklon": 0 }, +{ "label": "13/98A", "node": 3339, "naklon": 0 }, +{ "label": "13/98B", "node": 3333, "naklon": 0 }, +{ "label": "13/1", "node": 3425, "naklon": 0 }, +{ "label": "13/2", "node": 3419, "naklon": 0 }, +{ "label": "13/3", "node": 3416, "naklon": 0 }, +{ "label": "13/4", "node": 3332, "naklon": 0 }, +{ "label": "13/5", "node": 3422, "naklon": 0 }, +{ "label": "13/6", "node": 3417, "naklon": 0 }, +{ "label": "13/7", "node": 3418, "naklon": 0 }, +{ "label": "13/8", "node": 3424, "naklon": 0 }, +{ "label": "13/9", "node": 3334, "naklon": 0 }, +{ "label": "13/10", "node": 4363, "naklon": 0 }, +{ "label": "13/11", "node": 3423, "naklon": 0 }, +{ "label": "13/12", "node": 3406, "naklon": 0 }, +{ "label": "13/14", "node": 3411, "naklon": 0 }, +{ "label": "13/15", "node": 3412, "naklon": 0 }, +{ "label": "13/16", "node": 3413, "naklon": 0 }, +{ "label": "13/17", "node": 3414, "naklon": 0 }, +{ "label": "13/18", "node": 3391, "naklon": 0 }, +{ "label": "13/19", "node": 3370, "naklon": 0 }, +{ "label": "13/20", "node": 3369, "naklon": 0 }, +{ "label": "13/21", "node": 3408, "naklon": 0 }, +{ "label": "13/22", "node": 3393, "naklon": 0 }, +{ "label": "13/23", "node": 3128, "naklon": 0 }, +{ "label": "13/24", "node": 3197, "naklon": 0 }, +{ "label": "13/25", "node": 4364, "naklon": 0 }, +{ "label": "13/26", "node": 3155, "naklon": 0 }, +{ "label": "13/27", "node": 3196, "naklon": 0 }, +{ "label": "13/28", "node": 3144, "naklon": 0 }, +{ "label": "13/30", "node": 3150, "naklon": 0 }, +{ "label": "13/31", "node": 3390, "naklon": 0 }, +{ "label": "13/32", "node": 3401, "naklon": 0 }, +{ "label": "13/33", "node": 3275, "naklon": 0 }, +{ "label": "13/35", "node": 3371, "naklon": 0 }, +{ "label": "13/36", "node": 3389, "naklon": 0 }, +{ "label": "13/37", "node": 3388, "naklon": 0 }, +{ "label": "13/38", "node": 3365, "naklon": 0 }, +{ "label": "13/39", "node": 3363, "naklon": 0 }, +{ "label": "13/40", "node": 3397, "naklon": 0 }, +{ "label": "13/40/1", "node": 3567, "naklon": 0 }, +{ "label": "13/41", "node": 3387, "naklon": 0 }, +{ "label": "13/42", "node": 3403, "naklon": 0 }, +{ "label": "13/43", "node": 3147, "naklon": 0 }, +{ "label": "13/44", "node": 3141, "naklon": 0 }, +{ "label": "13/46", "node": 3364, "naklon": 0 }, +{ "label": "13/47", "node": 3367, "naklon": 0 }, +{ "label": "13/48", "node": 3368, "naklon": 0 }, +{ "label": "13/49", "node": 3402, "naklon": 0 }, +{ "label": "13/50", "node": 3366, "naklon": 0 }, +{ "label": "13/51", "node": 3395, "naklon": 0 }, +{ "label": "13/52", "node": 3372, "naklon": 0 }, +{ "label": "13/53", "node": 3394, "naklon": 0 }, +{ "label": "13/54", "node": 3308, "naklon": 0 }, +{ "label": "13/54/1", "node": 3847, "naklon": 0 }, +{ "label": "13/55", "node": 3312, "naklon": 3 }, +{ "label": "13/56", "node": 3309, "naklon": 3 }, +{ "label": "13/57", "node": 3311, "naklon": 3 }, +{ "label": "13/58", "node": 3310, "naklon": 3 }, +{ "label": "13/59", "node": 4365, "naklon": 3 }, +{ "label": "13/60/1", "node": 4093, "naklon": 3 }, +{ "label": "13/61", "node": 3304, "naklon": 3 }, +{ "label": "13/62", "node": 3307, "naklon": 3 }, +{ "label": "13/63", "node": 3271, "naklon": 3 }, +{ "label": "13/64", "node": 3301, "naklon": 3 }, +{ "label": "13/65", "node": 4366, "naklon": 3 }, +{ "label": "13/66", "node": 3300, "naklon": 3 }, +{ "label": "13/67", "node": 3185, "naklon": 0 }, +{ "label": "13/68", "node": 3184, "naklon": 0 }, +{ "label": "13/69", "node": 3188, "naklon": 0 }, +{ "label": "13/71", "node": 3343, "naklon": 6 }, +{ "label": "13/71/1", "node": 3819, "naklon": 6 }, +{ "label": "13/71/2", "node": 3880, "naklon": 6 }, +{ "label": "13/72", "node": 3348, "naklon": 6 }, +{ "label": "13/74", "node": 3344, "naklon": 6 }, +{ "label": "13/75", "node": 3346, "naklon": 6 }, +{ "label": "13/75/1", "node": 3597, "naklon": 6 }, +{ "label": "13/76", "node": 3345, "naklon": 6 }, +{ "label": "13/77", "node": 3322, "naklon": 0 }, +{ "label": "13/78", "node": 3325, "naklon": 0 }, +{ "label": "13/78/1", "node": 4310, "naklon": 0 }, +{ "label": "13/79", "node": 3315, "naklon": 0 }, +{ "label": "13/80", "node": 3328, "naklon": 0 }, +{ "label": "13/81", "node": 3321, "naklon": 0 }, +{ "label": "13/82", "node": 3324, "naklon": 0 }, +{ "label": "13/84", "node": 3140, "naklon": 0 }, +{ "label": "13/85", "node": 3153, "naklon": 0 }, +{ "label": "13/86", "node": 3145, "naklon": 0 }, +{ "label": "13/87", "node": 3134, "naklon": 0 }, +{ "label": "13/88", "node": 3151, "naklon": 0 }, +{ "label": "13/89", "node": 3143, "naklon": 0 }, +{ "label": "13/90", "node": 3318, "naklon": 0 }, +{ "label": "13/91", "node": 3347, "naklon": 0 }, +{ "label": "13/94", "node": 3314, "naklon": 0 }, +{ "label": "13/96", "node": 3331, "naklon": 0 }, +{ "label": "13/97", "node": 3327, "naklon": 0 }, +{ "label": "13/99", "node": 3329, "naklon": 0 }, +{ "label": "13/100", "node": 3337, "naklon": 0 }, +{ "label": "13/101", "node": 3330, "naklon": 0 }, +{ "label": "13/102", "node": 3335, "naklon": 0 }, +{ "label": "13/103", "node": 3420, "naklon": 0 }, +{ "label": "13/104", "node": 3421, "naklon": 0 }, +{ "label": "13/105", "node": 4361, "naklon": 0 }, +{ "label": "13/106", "node": 4362, "naklon": 0 }, +{ "label": "13/107", "node": 3526, "naklon": 0 }, +{ "label": "13/108", "node": 4424, "naklon": null }, +{ "label": "13/109", "node": 3561, "naklon": null }, +{ "label": "13/110", "node": 3527, "naklon": null }, +{ "label": "13/111", "node": 3521, "naklon": null }, +{ "label": "13/112", "node": 3552, "naklon": null }, +{ "label": "13/113", "node": 3544, "naklon": null }, +{ "label": "13/114", "node": 3534, "naklon": null }, +{ "label": "13/115", "node": 3516, "naklon": null }, +{ "label": "13/116", "node": 3513, "naklon": null }, +{ "label": "13/117", "node": 3565, "naklon": null }, +{ "label": "13/118", "node": 3866, "naklon": null }, +{ "label": "14/1", "node": 3136, "naklon": 0 }, +{ "label": "14/2", "node": 3137, "naklon": 0 }, +{ "label": "14/3", "node": 3135, "naklon": 0 }, +{ "label": "14/4", "node": 3149, "naklon": 0 }, +{ "label": "14/5", "node": 3142, "naklon": 0 }, +{ "label": "14/6", "node": 3342, "naklon": 0 }, +{ "label": "14/7", "node": 3340, "naklon": 0 }, +{ "label": "14/8", "node": 3152, "naklon": 0 }, +{ "label": "14/9", "node": 3886, "naklon": 0 }, +{ "label": "14/10", "node": 3341, "naklon": null }, +{ "label": "14/11", "node": 3352, "naklon": null }, +{ "label": "15/1", "node": 3396, "naklon": 5 }, +{ "label": "15/2", "node": 2784, "naklon": 5 }, +{ "label": "15/3", "node": 2788, "naklon": 5 }, +{ "label": "15/4", "node": 2801, "naklon": 5 }, +{ "label": "15/5", "node": 2815, "naklon": 5 }, +{ "label": "15/6", "node": 2829, "naklon": 5 }, +{ "label": "15/7", "node": 2796, "naklon": 5 }, +{ "label": "15/8", "node": 2803, "naklon": 5 }, +{ "label": "15/8/1", "node": 4304, "naklon": 5 }, +{ "label": "15/8/2", "node": 4311, "naklon": 5 }, +{ "label": "15/9", "node": 2821, "naklon": 5 }, +{ "label": "15/10", "node": 3400, "naklon": 5 }, +{ "label": "15/11", "node": 2799, "naklon": 5 }, +{ "label": "15/12", "node": 2804, "naklon": 5 }, +{ "label": "15/12/1", "node": 4303, "naklon": 5 }, +{ "label": "15/12/2", "node": 4309, "naklon": 5 }, +{ "label": "15/13", "node": 2806, "naklon": 5 }, +{ "label": "15/14", "node": 2787, "naklon": 5 }, +{ "label": "15/15", "node": 2809, "naklon": 5 }, +{ "label": "15/16", "node": 2814, "naklon": 0 }, +{ "label": "15/17", "node": 3934, "naklon": 0 }, +{ "label": "15/18", "node": 3192, "naklon": 0 }, +{ "label": "15/19", "node": 2812, "naklon": 0 }, +{ "label": "15/20", "node": 4070, "naklon": 0 }, +{ "label": "15/21", "node": 2826, "naklon": 0 }, +{ "label": "15/22", "node": 2808, "naklon": 3 }, +{ "label": "15/23", "node": 2795, "naklon": 3 }, +{ "label": "15/24", "node": 2807, "naklon": 3 }, +{ "label": "15/25", "node": 2831, "naklon": 0 }, +{ "label": "15/26", "node": 2862, "naklon": null }, +{ "label": "15/27", "node": 2861, "naklon": 0 }, +{ "label": "15/28", "node": 2866, "naklon": 0 }, +{ "label": "15/28/1", "node": 3546, "naklon": 0 }, +{ "label": "15/29", "node": 4146, "naklon": 0 }, +{ "label": "15/29/1", "node": 3001, "naklon": 0 }, +{ "label": "15/30", "node": 2835, "naklon": 0 }, +{ "label": "15/31", "node": 2874, "naklon": 0 }, +{ "label": "15/32", "node": 2852, "naklon": 0 }, +{ "label": "15/33", "node": 2851, "naklon": 0 }, +{ "label": "15/33/1", "node": 3560, "naklon": 0 }, +{ "label": "15/34", "node": 2858, "naklon": 0 }, +{ "label": "15/34/1", "node": 4306, "naklon": 0 }, +{ "label": "15/35", "node": 2856, "naklon": 0 }, +{ "label": "15/36", "node": 2847, "naklon": 0 }, +{ "label": "15/36/1", "node": 3556, "naklon": 0 }, +{ "label": "15/37", "node": 3950, "naklon": 0 }, +{ "label": "15/38", "node": 2848, "naklon": 0 }, +{ "label": "15/39", "node": 2863, "naklon": 0 }, +{ "label": "15/39/1", "node": 4313, "naklon": 0 }, +{ "label": "15/40", "node": 2873, "naklon": 0 }, +{ "label": "15/40/1", "node": 2984, "naklon": 0 }, +{ "label": "15/41", "node": 2854, "naklon": 0 }, +{ "label": "15/42", "node": 2859, "naklon": 0 }, +{ "label": "15/43", "node": 2872, "naklon": 0 }, +{ "label": "15/44", "node": 2849, "naklon": 0 }, +{ "label": "15/45", "node": 2864, "naklon": 0 }, +{ "label": "15/46", "node": 3553, "naklon": null }, +{ "label": "15/47", "node": 3021, "naklon": null }, +{ "label": "15/47/1", "node": 3008, "naklon": null }, +{ "label": "15/48", "node": 3017, "naklon": null }, +{ "label": "15/49", "node": 3014, "naklon": null }, +{ "label": "15/50", "node": 2981, "naklon": null }, +{ "label": "15/51", "node": 3020, "naklon": null }, +{ "label": "15/52", "node": 3027, "naklon": null }, +{ "label": "15/53", "node": 3006, "naklon": null }, +{ "label": "15/54", "node": 3012, "naklon": null }, +{ "label": "15/55", "node": 2738, "naklon": 0 }, +{ "label": "15/56", "node": 2725, "naklon": 0 }, +{ "label": "15/57", "node": 3016, "naklon": null }, +{ "label": "15/58", "node": 3005, "naklon": null }, +{ "label": "15/58/1", "node": 3009, "naklon": null }, +{ "label": "15/59", "node": 3010, "naklon": 0 }, +{ "label": "15/59/1", "node": 3538, "naklon": 0 }, +{ "label": "15/59/2", "node": 4145, "naklon": 0 }, +{ "label": "15/60", "node": 2713, "naklon": 0 }, +{ "label": "15/61", "node": 2789, "naklon": 0 }, +{ "label": "15/62", "node": 2736, "naklon": 0 }, +{ "label": "15/63", "node": 2739, "naklon": 0 }, +{ "label": "15/64", "node": 4346, "naklon": 0 }, +{ "label": "15/65", "node": 2731, "naklon": 0 }, +{ "label": "15/66", "node": 2818, "naklon": 0 }, +{ "label": "15/66/1", "node": 3557, "naklon": 0 }, +{ "label": "15/67", "node": 2822, "naklon": 0 }, +{ "label": "15/68", "node": 2833, "naklon": 0 }, +{ "label": "15/69", "node": 2834, "naklon": 0 }, +{ "label": "15/70", "node": 3097, "naklon": 0 }, +{ "label": "15/71", "node": 2824, "naklon": 0 }, +{ "label": "15/72", "node": 2828, "naklon": 0 }, +{ "label": "15/73", "node": 2600, "naklon": 0 }, +{ "label": "15/73/1", "node": 4314, "naklon": 0 }, +{ "label": "15/74", "node": 2832, "naklon": 0 }, +{ "label": "15/75", "node": 4360, "naklon": 0 }, +{ "label": "15/76", "node": 2846, "naklon": 0 }, +{ "label": "15/77", "node": 2584, "naklon": 0 }, +{ "label": "15/78", "node": 2843, "naklon": 0 }, +{ "label": "15/78/1", "node": 4308, "naklon": 0 }, +{ "label": "15/79", "node": 4144, "naklon": null }, +{ "label": "15/80", "node": 2844, "naklon": 0 }, +{ "label": "15/81", "node": 2842, "naklon": 0 }, +{ "label": "15/82", "node": 2838, "naklon": 0 }, +{ "label": "15/83", "node": 2837, "naklon": null }, +{ "label": "15/83/1", "node": 3555, "naklon": null }, +{ "label": "15/84", "node": 2839, "naklon": 0 }, +{ "label": "15/85", "node": 2830, "naklon": 0 }, +{ "label": "15/86", "node": 4066, "naklon": 0 }, +{ "label": "15/87", "node": 2836, "naklon": 0 }, +{ "label": "15/88", "node": 2911, "naklon": 0 }, +{ "label": "15/89", "node": 2825, "naklon": 0 }, +{ "label": "15/90", "node": 2811, "naklon": 0 }, +{ "label": "15/94", "node": 3740, "naklon": 15 }, +{ "label": "15/95", "node": 2734, "naklon": 15 }, +{ "label": "15/96", "node": 3105, "naklon": 15 }, +{ "label": "15/97", "node": 2732, "naklon": 15 }, +{ "label": "15/98", "node": 2727, "naklon": 15 }, +{ "label": "15/99", "node": 2735, "naklon": 15 }, +{ "label": "15/100", "node": 3926, "naklon": 15 }, +{ "label": "15/101", "node": 2918, "naklon": 0 }, +{ "label": "15/102", "node": 2705, "naklon": 10 }, +{ "label": "15/103", "node": 2708, "naklon": 10 }, +{ "label": "15/104", "node": 2721, "naklon": 10 }, +{ "label": "15/105", "node": 2719, "naklon": 10 }, +{ "label": "15/106", "node": 2919, "naklon": 10 }, +{ "label": "15/107", "node": 3101, "naklon": 10 }, +{ "label": "15/108", "node": 2853, "naklon": 10 }, +{ "label": "15/109", "node": 2715, "naklon": 10 }, +{ "label": "15/110", "node": 2712, "naklon": 0 }, +{ "label": "15/111", "node": 2711, "naklon": 0 }, +{ "label": "15/112", "node": 2709, "naklon": 0 }, +{ "label": "15/113", "node": 2710, "naklon": 0 }, +{ "label": "15/114", "node": 2907, "naklon": 0 }, +{ "label": "15/115", "node": 2906, "naklon": 0 }, +{ "label": "15/116", "node": 2908, "naklon": 0 }, +{ "label": "15/117", "node": 2901, "naklon": 0 }, +{ "label": "15/118", "node": 2913, "naklon": 0 }, +{ "label": "15/119", "node": 3656, "naklon": 0 }, +{ "label": "15/120", "node": 2781, "naklon": 0 }, +{ "label": "15/121", "node": 2802, "naklon": 0 }, +{ "label": "15/122", "node": 2791, "naklon": 0 }, +{ "label": "15/123", "node": 2783, "naklon": 0 }, +{ "label": "15/124", "node": 2794, "naklon": 0 }, +{ "label": "15/125", "node": 3139, "naklon": 0 }, +{ "label": "15/126", "node": 3229, "naklon": 5 }, +{ "label": "15/127", "node": 3239, "naklon": 5 }, +{ "label": "15/128", "node": 3230, "naklon": 5 }, +{ "label": "15/129", "node": 4016, "naklon": null }, +{ "label": "16/16A", "node": 3608, "naklon": 0 }, +{ "label": "16/16B", "node": 4151, "naklon": 0 }, +{ "label": "16/1", "node": 3710, "naklon": 0 }, +{ "label": "16/2", "node": 3726, "naklon": 0 }, +{ "label": "16/3", "node": 3743, "naklon": 0 }, +{ "label": "16/4", "node": 3724, "naklon": 0 }, +{ "label": "16/5", "node": 3712, "naklon": 0 }, +{ "label": "16/6", "node": 3739, "naklon": 0 }, +{ "label": "16/7", "node": 3742, "naklon": 0 }, +{ "label": "16/8", "node": 3731, "naklon": 0 }, +{ "label": "16/9", "node": 3727, "naklon": 0 }, +{ "label": "16/10", "node": 3729, "naklon": 0 }, +{ "label": "16/11", "node": 3736, "naklon": 0 }, +{ "label": "16/12", "node": 3713, "naklon": 0 }, +{ "label": "16/13", "node": 3715, "naklon": 0 }, +{ "label": "16/14", "node": 3733, "naklon": 0 }, +{ "label": "16/15", "node": 3732, "naklon": 0 }, +{ "label": "16/17", "node": 3634, "naklon": 0 }, +{ "label": "16/18", "node": 3610, "naklon": 0 }, +{ "label": "16/19", "node": 3626, "naklon": 0 }, +{ "label": "16/20", "node": 3618, "naklon": 0 }, +{ "label": "16/21", "node": 3619, "naklon": 0 }, +{ "label": "16/22", "node": 3628, "naklon": 0 }, +{ "label": "16/23", "node": 3615, "naklon": 0 }, +{ "label": "16/24", "node": 3609, "naklon": 0 }, +{ "label": "16/25", "node": 3606, "naklon": 0 }, +{ "label": "16/26", "node": 3624, "naklon": 0 }, +{ "label": "16/27", "node": 3627, "naklon": 0 }, +{ "label": "16/28", "node": 3607, "naklon": 0 }, +{ "label": "16/29", "node": 4370, "naklon": 0 }, +{ "label": "16/30", "node": 3692, "naklon": 0 }, +{ "label": "16/31", "node": 3614, "naklon": 0 }, +{ "label": "16/32", "node": 3623, "naklon": 0 }, +{ "label": "16/33", "node": 4373, "naklon": 0 }, +{ "label": "16/34", "node": 3620, "naklon": 0 }, +{ "label": "16/35", "node": 3685, "naklon": 0 }, +{ "label": "16/36", "node": 3616, "naklon": 0 }, +{ "label": "16/37", "node": 3686, "naklon": 0 }, +{ "label": "16/38", "node": 3688, "naklon": 0 }, +{ "label": "16/39", "node": 3684, "naklon": 0 }, +{ "label": "16/40", "node": 3825, "naklon": 0 }, +{ "label": "16/41", "node": 3865, "naklon": 0 }, +{ "label": "16/42", "node": 3824, "naklon": 0 }, +{ "label": "16/43", "node": 3871, "naklon": 0 }, +{ "label": "16/44", "node": 3801, "naklon": 0 }, +{ "label": "16/45", "node": 3862, "naklon": 0 }, +{ "label": "16/46", "node": 3876, "naklon": 0 }, +{ "label": "16/47", "node": 3861, "naklon": 0 }, +{ "label": "16/48", "node": 4215, "naklon": 0 }, +{ "label": "16/49", "node": 3605, "naklon": 10 }, +{ "label": "16/50", "node": 3603, "naklon": 10 }, +{ "label": "16/51", "node": 3592, "naklon": 10 }, +{ "label": "16/52", "node": 3598, "naklon": 10 }, +{ "label": "16/53", "node": 3594, "naklon": 10 }, +{ "label": "16/54", "node": 3593, "naklon": 10 }, +{ "label": "16/55", "node": 3630, "naklon": 10 }, +{ "label": "16/56", "node": 3763, "naklon": 10 }, +{ "label": "16/57", "node": 3746, "naklon": 10 }, +{ "label": "16/58", "node": 3699, "naklon": 0 }, +{ "label": "16/59", "node": 3698, "naklon": 0 }, +{ "label": "16/60", "node": 3709, "naklon": null }, +{ "label": "16/61", "node": 3708, "naklon": 0 }, +{ "label": "16/62", "node": 3703, "naklon": null }, +{ "label": "16/63", "node": 3700, "naklon": 0 }, +{ "label": "16/64", "node": 3701, "naklon": null }, +{ "label": "16/65", "node": 3704, "naklon": 0 }, +{ "label": "16/66", "node": 3707, "naklon": null }, +{ "label": "16/67", "node": 3810, "naklon": 0 }, +{ "label": "16/68", "node": 4208, "naklon": null }, +{ "label": "16/69", "node": 3867, "naklon": 0 }, +{ "label": "16/70", "node": 4372, "naklon": null }, +{ "label": "16/71", "node": 3881, "naklon": 0 }, +{ "label": "16/72", "node": 4204, "naklon": null }, +{ "label": "16/73", "node": 3869, "naklon": 0 }, +{ "label": "16/74", "node": 4202, "naklon": null }, +{ "label": "16/75", "node": 3830, "naklon": 0 }, +{ "label": "16/76", "node": 3870, "naklon": null }, +{ "label": "16/77", "node": 3964, "naklon": 0 }, +{ "label": "16/78", "node": 3849, "naklon": 0 }, +{ "label": "16/79", "node": 3694, "naklon": null }, +{ "label": "16/80", "node": 3717, "naklon": 0 }, +{ "label": "16/81", "node": 3877, "naklon": null }, +{ "label": "16/82", "node": 3755, "naklon": 0 }, +{ "label": "16/83", "node": 3725, "naklon": null }, +{ "label": "16/84", "node": 3716, "naklon": 0 }, +{ "label": "16/85", "node": 3696, "naklon": null }, +{ "label": "16/86", "node": 3702, "naklon": 0 }, +{ "label": "16/87", "node": 3706, "naklon": null }, +{ "label": "16/88", "node": 3850, "naklon": 0 }, +{ "label": "16/89", "node": 3848, "naklon": null }, +{ "label": "16/90", "node": 3737, "naklon": null }, +{ "label": "16/91", "node": 3705, "naklon": 0 }, +{ "label": "16/92", "node": 3723, "naklon": null }, +{ "label": "16/93", "node": 3842, "naklon": 0 }, +{ "label": "16/94", "node": 3735, "naklon": null }, +{ "label": "16/95", "node": 3719, "naklon": 0 }, +{ "label": "16/96", "node": 3697, "naklon": 0 }, +{ "label": "16/97", "node": 3711, "naklon": 0 }, +{ "label": "16/98", "node": 4107, "naklon": null }, +{ "label": "16/99", "node": 4112, "naklon": 5 }, +{ "label": "16/100", "node": 4106, "naklon": 5 }, +{ "label": "16/101", "node": 4111, "naklon": 5 }, +{ "label": "16/102", "node": 4091, "naklon": null }, +{ "label": "16/103", "node": 4104, "naklon": 5 }, +{ "label": "16/104", "node": 4094, "naklon": null }, +{ "label": "16/105", "node": 4089, "naklon": 5 }, +{ "label": "16/106", "node": 4095, "naklon": null }, +{ "label": "16/107", "node": 4102, "naklon": 5 }, +{ "label": "16/108", "node": 4105, "naklon": null }, +{ "label": "16/109", "node": 3859, "naklon": null }, +{ "label": "16/110", "node": 4090, "naklon": 5 }, +{ "label": "16/111", "node": 4110, "naklon": null }, +{ "label": "16/112", "node": 4097, "naklon": 5 }, +{ "label": "16/113", "node": 4099, "naklon": null }, +{ "label": "16/114", "node": 4096, "naklon": null }, +{ "label": "16/115", "node": 4101, "naklon": 5 }, +{ "label": "16/116", "node": 4109, "naklon": null }, +{ "label": "16/117", "node": 4092, "naklon": 5 }, +{ "label": "16/118", "node": 3631, "naklon": null }, +{ "label": "16/119", "node": 3632, "naklon": 0 }, +{ "label": "16/120", "node": 3641, "naklon": null }, +{ "label": "16/121", "node": 3638, "naklon": 0 }, +{ "label": "16/122", "node": 3637, "naklon": null }, +{ "label": "16/123", "node": 4142, "naklon": null }, +{ "label": "16/124", "node": 4147, "naklon": 5 }, +{ "label": "16/125", "node": 4139, "naklon": 5 }, +{ "label": "20/30A", "node": 3172, "naklon": 2 }, +{ "label": "20/30B", "node": 3164, "naklon": 2 }, +{ "label": "20/1", "node": 3247, "naklon": 10 }, +{ "label": "20/2", "node": 3296, "naklon": 10 }, +{ "label": "20/3", "node": 3246, "naklon": 10 }, +{ "label": "20/4", "node": 3270, "naklon": 10 }, +{ "label": "20/5", "node": 3294, "naklon": 10 }, +{ "label": "20/6", "node": 3298, "naklon": 10 }, +{ "label": "20/7", "node": 3297, "naklon": 10 }, +{ "label": "20/8", "node": 3293, "naklon": 10 }, +{ "label": "20/9", "node": 3299, "naklon": 10 }, +{ "label": "20/10", "node": 3295, "naklon": 10 }, +{ "label": "20/11", "node": 3244, "naklon": 10 }, +{ "label": "20/12", "node": 3249, "naklon": 10 }, +{ "label": "20/13", "node": 3268, "naklon": 10 }, +{ "label": "20/14", "node": 3245, "naklon": 10 }, +{ "label": "20/15", "node": 3278, "naklon": 10 }, +{ "label": "20/16", "node": 3280, "naklon": 10 }, +{ "label": "20/17", "node": 3292, "naklon": 10 }, +{ "label": "20/18", "node": 3287, "naklon": 10 }, +{ "label": "20/19", "node": 3282, "naklon": 10 }, +{ "label": "20/20", "node": 3273, "naklon": 0 }, +{ "label": "20/21", "node": 3157, "naklon": 0 }, +{ "label": "20/22", "node": 3283, "naklon": 0 }, +{ "label": "20/23", "node": 3159, "naklon": 0 }, +{ "label": "20/24", "node": 3289, "naklon": 0 }, +{ "label": "20/25", "node": 3163, "naklon": 0 }, +{ "label": "20/26", "node": 3126, "naklon": 0 }, +{ "label": "20/27", "node": 3171, "naklon": 0 }, +{ "label": "20/28", "node": 3162, "naklon": 0 }, +{ "label": "20/29", "node": 3279, "naklon": 10 }, +{ "label": "20/31", "node": 3173, "naklon": 0 }, +{ "label": "20/32", "node": 3127, "naklon": 0 }, +{ "label": "20/33", "node": 3131, "naklon": 0 }, +{ "label": "20/34", "node": 3129, "naklon": 0 }, +{ "label": "20/35", "node": 3276, "naklon": 2 }, +{ "label": "20/36", "node": 3290, "naklon": 2 }, +{ "label": "20/37", "node": 3132, "naklon": 0 }, +{ "label": "20/38", "node": 3138, "naklon": 0 }, +{ "label": "20/39", "node": 3272, "naklon": 0 }, +{ "label": "20/40", "node": 3291, "naklon": 0 }, +{ "label": "20/41", "node": 3277, "naklon": 10 }, +{ "label": "20/42", "node": 3286, "naklon": 10 }, +{ "label": "20/43", "node": 3281, "naklon": 10 }, +{ "label": "20/44", "node": 3288, "naklon": 10 }, +{ "label": "20/45", "node": 3284, "naklon": 10 }, +{ "label": "20/46", "node": 3167, "naklon": 10 }, +{ "label": "20/47", "node": 3872, "naklon": 0 }, +{ "label": "20/48", "node": 3124, "naklon": 0 }, +{ "label": "20/49", "node": 3133, "naklon": 0 }, +{ "label": "20/50", "node": 3158, "naklon": 0 }, +{ "label": "20/51", "node": 3169, "naklon": 0 }, +{ "label": "20/52", "node": 3146, "naklon": 0 }, +{ "label": "20/53", "node": 3160, "naklon": 0 }, +{ "label": "20/54", "node": 3248, "naklon": 0 }, +{ "label": "20/55", "node": 3156, "naklon": 0 }, +{ "label": "20/56", "node": 3161, "naklon": 0 }, +{ "label": "20/57", "node": 3170, "naklon": 0 }, +{ "label": "20/58", "node": 3168, "naklon": 0 }, +{ "label": "20/59", "node": 3125, "naklon": 0 }, +{ "label": "20/60", "node": 3166, "naklon": 0 }, +{ "label": "20/61", "node": 3130, "naklon": 0 }, +{ "label": "20/62", "node": 3563, "naklon": 0 }, +{ "label": "20/63", "node": 3550, "naklon": null }, +{ "label": "20/67", "node": 3269, "naklon": 0 }, +{ "label": "21/1", "node": 2921, "naklon": 0 }, +{ "label": "21/2", "node": 2707, "naklon": 0 }, +{ "label": "21/3", "node": 2723, "naklon": 0 }, +{ "label": "21/4", "node": 2716, "naklon": 0 }, +{ "label": "21/5", "node": 2717, "naklon": 0 }, +{ "label": "21/6", "node": 2720, "naklon": 0 }, +{ "label": "21/7", "node": 2722, "naklon": 0 }, +{ "label": "21/8", "node": 2718, "naklon": 0 }, +{ "label": "21/9", "node": 2724, "naklon": 0 }, +{ "label": "21/10", "node": 2742, "naklon": 0 }, +{ "label": "21/11", "node": 2743, "naklon": 0 }, +{ "label": "21/12", "node": 2733, "naklon": 0 }, +{ "label": "21/14", "node": 2903, "naklon": 0 }, +{ "label": "21/15", "node": 2917, "naklon": 0 }, +{ "label": "21/16", "node": 2897, "naklon": 0 }, +{ "label": "21/17", "node": 2914, "naklon": 0 }, +{ "label": "21/18", "node": 2898, "naklon": 0 }, +{ "label": "21/19", "node": 2773, "naklon": 0 }, +{ "label": "21/20", "node": 2895, "naklon": 0 }, +{ "label": "21/21", "node": 2896, "naklon": 0 }, +{ "label": "21/22", "node": 2771, "naklon": 0 }, +{ "label": "21/23", "node": 2772, "naklon": 0 }, +{ "label": "21/24", "node": 2793, "naklon": 0 }, +{ "label": "21/25", "node": 2902, "naklon": 0 }, +{ "label": "21/26", "node": 2910, "naklon": 0 }, +{ "label": "21/27", "node": 2909, "naklon": 0 }, +{ "label": "21/28", "node": 2920, "naklon": 0 }, +{ "label": "21/29", "node": 2916, "naklon": 0 }, +{ "label": "21/30", "node": 2904, "naklon": 0 }, +{ "label": "21/31", "node": 2915, "naklon": 0 }, +{ "label": "21/32", "node": 2905, "naklon": 0 }, +{ "label": "21/33", "node": 2900, "naklon": 0 }, +{ "label": "21/34", "node": 2899, "naklon": 0 }, +{ "label": "21/36", "node": 2741, "naklon": 0 }, +{ "label": "21/37", "node": 2714, "naklon": 0 }, +{ "label": "21/38", "node": 2701, "naklon": 0 }, +{ "label": "21/39", "node": 2703, "naklon": 0 }, +{ "label": "21/40", "node": 2704, "naklon": 0 }, +{ "label": "21/41", "node": 2702, "naklon": 0 }, +{ "label": "21/42", "node": 2706, "naklon": 0 }, +{ "label": "21/43", "node": 2776, "naklon": 0 }, +{ "label": "21/44", "node": 2770, "naklon": 0 }, +{ "label": "21/45", "node": 2786, "naklon": 0 }, +{ "label": "21/46", "node": 2779, "naklon": 0 }, +{ "label": "21/47", "node": 2782, "naklon": 0 }, +{ "label": "21/48", "node": 2785, "naklon": 0 }, +{ "label": "21/49", "node": 2769, "naklon": 0 }, +{ "label": "21/50", "node": 3354, "naklon": 0 }, +{ "label": "21/51", "node": 2778, "naklon": 0 }, +{ "label": "21/52", "node": 2775, "naklon": 0 }, +{ "label": "21/53", "node": 2780, "naklon": 0 }, +{ "label": "21/54", "node": 2790, "naklon": 0 }, +{ "label": "21/55", "node": 2792, "naklon": 0 }, +{ "label": "21/56", "node": 2774, "naklon": 0 }, +{ "label": "22/1", "node": 2630, "naklon": 0 }, +{ "label": "22/2", "node": 2631, "naklon": 0 }, +{ "label": "22/3", "node": 2632, "naklon": 0 }, +{ "label": "22/4", "node": 2633, "naklon": 0 }, +{ "label": "22/5", "node": 2634, "naklon": 0 }, +{ "label": "22/6", "node": 2636, "naklon": 0 }, +{ "label": "22/7", "node": 4367, "naklon": 0 }, +{ "label": "22/8", "node": 2637, "naklon": 0 }, +{ "label": "22/9", "node": 2638, "naklon": 0 }, +{ "label": "22/10", "node": 2639, "naklon": 0 }, +{ "label": "22/11", "node": 2640, "naklon": 0 }, +{ "label": "22/12", "node": 2641, "naklon": 0 }, +{ "label": "22/13", "node": 2642, "naklon": 0 }, +{ "label": "22/14", "node": 2643, "naklon": 0 }, +{ "label": "22/15", "node": 2644, "naklon": 0 }, +{ "label": "22/16", "node": 2645, "naklon": 0 }, +{ "label": "22/17", "node": 2646, "naklon": 0 }, +{ "label": "22/18", "node": 2647, "naklon": 0 }, +{ "label": "22/19", "node": 2648, "naklon": 0 }, +{ "label": "22/20", "node": 2649, "naklon": 0 }, +{ "label": "22/21", "node": 2650, "naklon": 0 }, +{ "label": "22/22", "node": 2651, "naklon": 0 }, +{ "label": "22/23", "node": 4103, "naklon": 0 }, +{ "label": "22/24", "node": 2653, "naklon": 0 }, +{ "label": "22/25", "node": 2654, "naklon": 0 }, +{ "label": "22/26", "node": 2655, "naklon": 0 }, +{ "label": "22/27", "node": 2656, "naklon": 0 }, +{ "label": "22/28", "node": 2657, "naklon": 0 }, +{ "label": "22/29", "node": 2658, "naklon": 0 }, +{ "label": "22/30", "node": 2659, "naklon": 0 }, +{ "label": "22/31", "node": 2660, "naklon": 0 }, +{ "label": "22/32", "node": 2661, "naklon": 0 }, +{ "label": "22/32/1", "node": 3015, "naklon": 0 }, +{ "label": "22/33", "node": 2662, "naklon": 0 }, +{ "label": "22/34", "node": 2663, "naklon": 0 }, +{ "label": "22/35", "node": 2664, "naklon": 0 }, +{ "label": "22/36", "node": 2665, "naklon": 0 }, +{ "label": "22/37", "node": 2666, "naklon": 0 }, +{ "label": "22/38", "node": 2667, "naklon": 0 }, +{ "label": "22/39", "node": 2668, "naklon": 0 }, +{ "label": "22/40", "node": 2669, "naklon": null }, +{ "label": "22/41", "node": 2670, "naklon": null }, +{ "label": "22/42", "node": 2671, "naklon": null }, +{ "label": "23/9A", "node": 3087, "naklon": 10 }, +{ "label": "23/9B", "node": 3090, "naklon": 10 }, +{ "label": "23/1", "node": 3075, "naklon": 0 }, +{ "label": "23/2", "node": 3089, "naklon": 0 }, +{ "label": "23/3", "node": 3088, "naklon": 0 }, +{ "label": "23/4", "node": 3228, "naklon": 10 }, +{ "label": "23/5", "node": 2751, "naklon": 10 }, +{ "label": "23/6", "node": 3243, "naklon": 10 }, +{ "label": "23/7", "node": 4349, "naklon": 10 }, +{ "label": "23/8", "node": 3102, "naklon": 10 }, +{ "label": "23/10", "node": 3099, "naklon": 10 }, +{ "label": "23/11", "node": 3103, "naklon": 10 }, +{ "label": "23/12", "node": 3093, "naklon": 10 }, +{ "label": "23/13", "node": 3098, "naklon": 10 }, +{ "label": "23/14", "node": 3092, "naklon": 10 }, +{ "label": "23/15", "node": 3233, "naklon": 0 }, +{ "label": "23/16", "node": 3095, "naklon": 0 }, +{ "label": "23/17", "node": 4074, "naklon": 0 }, +{ "label": "23/18", "node": 2729, "naklon": 0 }, +{ "label": "23/19", "node": 3234, "naklon": 0 }, +{ "label": "23/20", "node": 3094, "naklon": 0 }, +{ "label": "23/21", "node": 2817, "naklon": 0 }, +{ "label": "23/22", "node": 3226, "naklon": 0 }, +{ "label": "23/23", "node": 3225, "naklon": 0 }, +{ "label": "23/24", "node": 3237, "naklon": 0 }, +{ "label": "23/25", "node": 4250, "naklon": 0 }, +{ "label": "23/26", "node": 3059, "naklon": 10 }, +{ "label": "23/27", "node": 3238, "naklon": 10 }, +{ "label": "23/28", "node": 3242, "naklon": 10 }, +{ "label": "23/29", "node": 3236, "naklon": 10 }, +{ "label": "23/30", "node": 3112, "naklon": 10 }, +{ "label": "23/31", "node": 3224, "naklon": 0 }, +{ "label": "23/32", "node": 4298, "naklon": 10 }, +{ "label": "23/33", "node": 4150, "naklon": 10 }, +{ "label": "23/34", "node": 3091, "naklon": 10 }, +{ "label": "25/1", "node": 3771, "naklon": 5 }, +{ "label": "25/2", "node": 3777, "naklon": 5 }, +{ "label": "25/3", "node": 3749, "naklon": 5 }, +{ "label": "25/4", "node": 3769, "naklon": 5 }, +{ "label": "25/5", "node": 3765, "naklon": 5 }, +{ "label": "25/6", "node": 3785, "naklon": 5 }, +{ "label": "25/7", "node": 3761, "naklon": 5 }, +{ "label": "25/8", "node": 3758, "naklon": 5 }, +{ "label": "25/9", "node": 3766, "naklon": 5 }, +{ "label": "25/10", "node": 3779, "naklon": 5 }, +{ "label": "25/11", "node": 3899, "naklon": 10 }, +{ "label": "25/12", "node": 3922, "naklon": 10 }, +{ "label": "25/13", "node": 3912, "naklon": 10 }, +{ "label": "25/14", "node": 3933, "naklon": 10 }, +{ "label": "25/15", "node": 3921, "naklon": 10 }, +{ "label": "25/16", "node": 4300, "naklon": 10 }, +{ "label": "25/17", "node": 3927, "naklon": 10 }, +{ "label": "25/18", "node": 3212, "naklon": 10 }, +{ "label": "25/19", "node": 3208, "naklon": 10 }, +{ "label": "25/20", "node": 3207, "naklon": 10 }, +{ "label": "25/21", "node": 4294, "naklon": 10 }, +{ "label": "25/22", "node": 3209, "naklon": 10 }, +{ "label": "25/23", "node": 3745, "naklon": 10 }, +{ "label": "25/24", "node": 3762, "naklon": 10 }, +{ "label": "25/25", "node": 3215, "naklon": 10 }, +{ "label": "25/26", "node": 3210, "naklon": 10 }, +{ "label": "25/27", "node": 3211, "naklon": 10 }, +{ "label": "25/28", "node": 3206, "naklon": 10 }, +{ "label": "25/29", "node": 3918, "naklon": 5 }, +{ "label": "25/30", "node": 3928, "naklon": 5 }, +{ "label": "25/31", "node": 3917, "naklon": 5 }, +{ "label": "25/32", "node": 4029, "naklon": 0 }, +{ "label": "25/33", "node": 4038, "naklon": 0 }, +{ "label": "25/34", "node": 4022, "naklon": 0 }, +{ "label": "25/35", "node": 3937, "naklon": 0 }, +{ "label": "25/36", "node": 3190, "naklon": 0 }, +{ "label": "25/37", "node": 3835, "naklon": 0 }, +{ "label": "25/38", "node": 3201, "naklon": 0 }, +{ "label": "25/39", "node": 3193, "naklon": 0 }, +{ "label": "25/40", "node": 3191, "naklon": 0 }, +{ "label": "25/41", "node": 3203, "naklon": 0 }, +{ "label": "25/42", "node": 4301, "naklon": 0 }, +{ "label": "25/43", "node": 3223, "naklon": 0 }, +{ "label": "25/44", "node": 3202, "naklon": 0 }, +{ "label": "25/45", "node": 3205, "naklon": 0 }, +{ "label": "25/46", "node": 3194, "naklon": 0 }, +{ "label": "25/47", "node": 3198, "naklon": 0 }, +{ "label": "25/48", "node": 3204, "naklon": 0 }, +{ "label": "25/49", "node": 3200, "naklon": 0 }, +{ "label": "25/50", "node": 3216, "naklon": 0 }, +{ "label": "25/51", "node": 3932, "naklon": 5 }, +{ "label": "25/52", "node": 3923, "naklon": 5 }, +{ "label": "25/53", "node": 3913, "naklon": 5 }, +{ "label": "25/54", "node": 3900, "naklon": 5 }, +{ "label": "25/55", "node": 4189, "naklon": 10 }, +{ "label": "25/56", "node": 4191, "naklon": 10 }, +{ "label": "25/57", "node": 3790, "naklon": 10 }, +{ "label": "25/58", "node": 4190, "naklon": 10 }, +{ "label": "25/59", "node": 4302, "naklon": 0 }, +{ "label": "25/60", "node": 4351, "naklon": 0 }, +{ "label": "25/61", "node": 4075, "naklon": 0 }, +{ "label": "25/62", "node": 4071, "naklon": 0 }, +{ "label": "25/63", "node": 3784, "naklon": 0 }, +{ "label": "25/64", "node": 4065, "naklon": 0 }, +{ "label": "25/65", "node": 4297, "naklon": 0 }, +{ "label": "25/66", "node": 4295, "naklon": 0 }, +{ "label": "25/67", "node": 4299, "naklon": 0 }, +{ "label": "25/68", "node": 3772, "naklon": 0 }, +{ "label": "25/69", "node": 3941, "naklon": 0 }, +{ "label": "25/70", "node": 3782, "naklon": 0 }, +{ "label": "25/71", "node": 4068, "naklon": 0 }, +{ "label": "25/72", "node": 4073, "naklon": 0 }, +{ "label": "25/73", "node": 3901, "naklon": 5 }, +{ "label": "25/74", "node": 4296, "naklon": 5 }, +{ "label": "25/75", "node": 3910, "naklon": 5 }, +{ "label": "25/76", "node": 4293, "naklon": 5 }, +{ "label": "25/77", "node": 3919, "naklon": 5 }, +{ "label": "25/78", "node": 3924, "naklon": 5 }, +{ "label": "25/79", "node": 3909, "naklon": 5 }, +{ "label": "25/80", "node": 3896, "naklon": 5 }, +{ "label": "25/81", "node": 3911, "naklon": 5 }, +{ "label": "25/82", "node": 2819, "naklon": 15 }, +{ "label": "25/83", "node": 3776, "naklon": 15 }, +{ "label": "25/84", "node": 3752, "naklon": 15 }, +{ "label": "25/85", "node": 4353, "naklon": 15 }, +{ "label": "25/86", "node": 3791, "naklon": 0 }, +{ "label": "25/87", "node": 3770, "naklon": 0 }, +{ "label": "25/88", "node": 3760, "naklon": 0 }, +{ "label": "25/89", "node": 3115, "naklon": 0 }, +{ "label": "25/90", "node": 3738, "naklon": 0 }, +{ "label": "25/91", "node": 3748, "naklon": 0 }, +{ "label": "25/92", "node": 3753, "naklon": 0 }, +{ "label": "25/93", "node": 3775, "naklon": 0 }, +{ "label": "25/94", "node": 3778, "naklon": 5 }, +{ "label": "25/95", "node": 4078, "naklon": 5 }, +{ "label": "25/96", "node": 4088, "naklon": 5 }, +{ "label": "25/97", "node": 3856, "naklon": 5 }, +{ "label": "25/98", "node": 4084, "naklon": 5 }, +{ "label": "25/99", "node": 4069, "naklon": 5 }, +{ "label": "25/100", "node": 4188, "naklon": 5 }, +{ "label": "25/101", "node": 4064, "naklon": 5 }, +{ "label": "25/102", "node": 3792, "naklon": 5 }, +{ "label": "25/103", "node": 3780, "naklon": 5 }, +{ "label": "25/104", "node": 4034, "naklon": 5 }, +{ "label": "25/105", "node": 4072, "naklon": 5 }, +{ "label": "25/106", "node": 3884, "naklon": 5 }, +{ "label": "25/107", "node": 3793, "naklon": 5 }, +{ "label": "25/108", "node": 3863, "naklon": 5 }, +{ "label": "25/109", "node": 3855, "naklon": 5 }, +{ "label": "33/1", "node": 3846, "naklon": 0 }, +{ "label": "33/2", "node": 3943, "naklon": 0 }, +{ "label": "33/3", "node": 3903, "naklon": 0 }, +{ "label": "33/4", "node": 3982, "naklon": 0 }, +{ "label": "33/5", "node": 3879, "naklon": 0 }, +{ "label": "33/6", "node": 3887, "naklon": 0 }, +{ "label": "33/7", "node": 3920, "naklon": 5 }, +{ "label": "33/8", "node": 3942, "naklon": 5 }, +{ "label": "33/9", "node": 3829, "naklon": null }, +{ "label": "34/79A", "node": 3452, "naklon": 6 }, +{ "label": "34/79B", "node": 3460, "naklon": 6 }, +{ "label": "34/90A", "node": 3443, "naklon": 6 }, +{ "label": "34/90B", "node": 3445, "naklon": 6 }, +{ "label": "34/90C", "node": 3457, "naklon": 6 }, +{ "label": "34/97A", "node": 3461, "naklon": 6 }, +{ "label": "34/97B", "node": 3463, "naklon": 6 }, +{ "label": "34/98A", "node": 3426, "naklon": 6 }, +{ "label": "34/98B", "node": 3444, "naklon": 6 }, +{ "label": "34/99A", "node": 3453, "naklon": 6 }, +{ "label": "34/99B", "node": 3455, "naklon": 6 }, +{ "label": "34/1", "node": 4009, "naklon": 0 }, +{ "label": "34/2", "node": 3602, "naklon": 0 }, +{ "label": "34/3", "node": 3441, "naklon": 0 }, +{ "label": "34/4", "node": 3464, "naklon": 0 }, +{ "label": "34/5", "node": 3883, "naklon": 0 }, +{ "label": "34/6", "node": 4098, "naklon": 0 }, +{ "label": "34/7", "node": 4003, "naklon": 0 }, +{ "label": "34/8", "node": 4004, "naklon": 0 }, +{ "label": "34/9", "node": 3888, "naklon": 0 }, +{ "label": "34/10", "node": 3997, "naklon": 0 }, +{ "label": "34/11", "node": 4006, "naklon": 0 }, +{ "label": "34/12", "node": 4000, "naklon": 0 }, +{ "label": "34/13", "node": 4011, "naklon": 0 }, +{ "label": "34/14", "node": 3999, "naklon": 0 }, +{ "label": "34/15", "node": 3981, "naklon": 0 }, +{ "label": "34/16", "node": 3988, "naklon": 0 }, +{ "label": "34/17", "node": 3986, "naklon": 0 }, +{ "label": "34/18", "node": 3998, "naklon": 0 }, +{ "label": "34/19", "node": 3983, "naklon": 0 }, +{ "label": "34/20", "node": 4005, "naklon": 0 }, +{ "label": "34/21", "node": 4001, "naklon": 0 }, +{ "label": "34/22", "node": 4008, "naklon": 0 }, +{ "label": "34/23", "node": 4002, "naklon": 0 }, +{ "label": "34/24", "node": 3996, "naklon": 0 }, +{ "label": "34/25", "node": 4007, "naklon": 0 }, +{ "label": "34/26", "node": 4113, "naklon": 15 }, +{ "label": "34/27", "node": 3595, "naklon": 5 }, +{ "label": "34/28", "node": 3599, "naklon": 5 }, +{ "label": "34/29", "node": 3601, "naklon": 5 }, +{ "label": "34/30", "node": 4205, "naklon": 0 }, +{ "label": "34/31", "node": 3987, "naklon": null }, +{ "label": "34/32", "node": 4214, "naklon": 0 }, +{ "label": "34/33", "node": 4226, "naklon": 0 }, +{ "label": "34/34", "node": 4209, "naklon": 0 }, +{ "label": "34/35", "node": 4201, "naklon": 0 }, +{ "label": "34/36", "node": 3440, "naklon": 0 }, +{ "label": "34/37", "node": 3465, "naklon": 0 }, +{ "label": "34/38", "node": 3446, "naklon": 0 }, +{ "label": "34/39", "node": 4039, "naklon": 5 }, +{ "label": "34/40", "node": 4057, "naklon": 5 }, +{ "label": "34/41", "node": 3985, "naklon": 0 }, +{ "label": "34/42", "node": 3882, "naklon": 0 }, +{ "label": "34/43", "node": 4040, "naklon": 5 }, +{ "label": "34/44", "node": 3231, "naklon": 0 }, +{ "label": "34/45", "node": 3227, "naklon": 0 }, +{ "label": "34/46", "node": 3431, "naklon": 0 }, +{ "label": "34/47", "node": 4013, "naklon": 0 }, +{ "label": "34/48", "node": 4045, "naklon": 0 }, +{ "label": "34/49", "node": 3949, "naklon": 0 }, +{ "label": "34/50", "node": 3953, "naklon": 0 }, +{ "label": "34/51", "node": 3952, "naklon": 0 }, +{ "label": "34/52", "node": 3995, "naklon": 0 }, +{ "label": "34/53", "node": 3992, "naklon": 0 }, +{ "label": "34/54", "node": 4198, "naklon": 0 }, +{ "label": "34/55", "node": 3935, "naklon": 0 }, +{ "label": "34/56", "node": 4050, "naklon": 0 }, +{ "label": "34/57", "node": 4049, "naklon": 0 }, +{ "label": "34/58", "node": 4054, "naklon": 0 }, +{ "label": "34/59", "node": 3663, "naklon": 6 }, +{ "label": "34/60", "node": 3661, "naklon": 6 }, +{ "label": "34/61", "node": 3664, "naklon": 6 }, +{ "label": "34/62", "node": 3660, "naklon": 6 }, +{ "label": "34/63", "node": 3662, "naklon": 6 }, +{ "label": "34/65", "node": 3665, "naklon": 6 }, +{ "label": "34/66", "node": 3667, "naklon": 6 }, +{ "label": "34/67", "node": 3675, "naklon": 6 }, +{ "label": "34/68", "node": 3666, "naklon": 6 }, +{ "label": "34/69", "node": 3652, "naklon": 6 }, +{ "label": "34/70", "node": 3458, "naklon": 6 }, +{ "label": "34/70/1", "node": 4425, "naklon": 6 }, +{ "label": "34/71", "node": 3459, "naklon": 6 }, +{ "label": "34/72", "node": 3435, "naklon": 6 }, +{ "label": "34/73", "node": 3448, "naklon": 6 }, +{ "label": "34/74", "node": 3451, "naklon": 6 }, +{ "label": "34/75", "node": 3442, "naklon": 6 }, +{ "label": "34/76", "node": 3449, "naklon": 6 }, +{ "label": "34/77", "node": 3450, "naklon": 6 }, +{ "label": "34/78", "node": 3433, "naklon": 6 }, +{ "label": "34/80", "node": 3432, "naklon": 12 }, +{ "label": "34/81", "node": 3470, "naklon": 12 }, +{ "label": "34/82", "node": 3438, "naklon": 12 }, +{ "label": "34/83", "node": 3439, "naklon": 12 }, +{ "label": "34/84", "node": 4028, "naklon": 5 }, +{ "label": "34/85", "node": 3596, "naklon": 5 }, +{ "label": "34/86", "node": 4021, "naklon": 5 }, +{ "label": "34/87", "node": 3437, "naklon": 12 }, +{ "label": "34/88", "node": 3428, "naklon": 12 }, +{ "label": "34/89", "node": 3430, "naklon": 12 }, +{ "label": "34/91", "node": 3454, "naklon": 6 }, +{ "label": "34/92", "node": 3492, "naklon": 6 }, +{ "label": "34/93", "node": 3462, "naklon": 6 }, +{ "label": "34/94", "node": 3427, "naklon": 6 }, +{ "label": "34/95", "node": 3434, "naklon": 6 }, +{ "label": "34/96", "node": 3456, "naklon": 6 }, +{ "label": "34/98/1", "node": 4307, "naklon": 6 }, +{ "label": "35/1", "node": 3968, "naklon": 0 }, +{ "label": "35/2", "node": 3969, "naklon": 0 }, +{ "label": "35/3", "node": 3947, "naklon": 0 }, +{ "label": "35/4", "node": 3979, "naklon": 0 }, +{ "label": "35/5", "node": 3959, "naklon": 0 }, +{ "label": "35/6", "node": 3948, "naklon": 0 }, +{ "label": "35/7", "node": 3961, "naklon": 0 }, +{ "label": "35/8", "node": 3956, "naklon": 0 }, +{ "label": "35/9", "node": 3604, "naklon": 0 }, +{ "label": "35/10", "node": 3944, "naklon": 0 }, +{ "label": "35/11", "node": 3960, "naklon": 0 }, +{ "label": "35/12", "node": 3958, "naklon": 0 }, +{ "label": "35/13", "node": 4036, "naklon": 5 }, +{ "label": "35/18", "node": 3893, "naklon": 5 }, +{ "label": "35/19", "node": 4108, "naklon": 5 }, +{ "label": "35/20", "node": 4017, "naklon": 5 }, +{ "label": "35/21", "node": 3963, "naklon": 0 }, +{ "label": "35/22", "node": 3658, "naklon": 0 }, +{ "label": "35/23", "node": 3975, "naklon": 0 }, +{ "label": "35/24", "node": 3980, "naklon": 0 }, +{ "label": "35/25", "node": 4012, "naklon": 0 }, +{ "label": "35/26", "node": 3655, "naklon": 0 }, +{ "label": "35/27", "node": 3962, "naklon": 0 }, +{ "label": "35/28", "node": 3945, "naklon": 0 }, +{ "label": "35/29", "node": 3569, "naklon": 0 }, +{ "label": "35/30", "node": 3429, "naklon": 0 }, +{ "label": "35/31", "node": 3657, "naklon": 0 }, +{ "label": "35/32", "node": 3646, "naklon": 0 }, +{ "label": "35/33", "node": 3622, "naklon": 0 }, +{ "label": "35/34", "node": 3612, "naklon": 0 }, +{ "label": "35/35", "node": 3955, "naklon": 0 }, +{ "label": "35/37", "node": 3878, "naklon": 0 }, +{ "label": "35/38", "node": 3965, "naklon": 0 }, +{ "label": "35/39", "node": 3970, "naklon": 0 }, +{ "label": "35/40", "node": 3611, "naklon": 0 }, +{ "label": "35/41", "node": 2635, "naklon": 0 }, +{ "label": "35/42", "node": 3978, "naklon": 0 }, +{ "label": "35/43", "node": 4213, "naklon": 0 }, +{ "label": "35/44", "node": 3984, "naklon": 0 }, +{ "label": "35/45", "node": 4218, "naklon": 0 }, +{ "label": "35/46", "node": 3973, "naklon": 0 }, +{ "label": "35/47", "node": 3974, "naklon": 0 }, +{ "label": "35/48", "node": 3759, "naklon": 0 }, +{ "label": "35/49", "node": 3844, "naklon": 0 }, +{ "label": "35/50", "node": 3804, "naklon": 0 }, +{ "label": "35/51", "node": 3831, "naklon": 0 }, +{ "label": "35/52", "node": 3643, "naklon": 0 }, +{ "label": "35/53", "node": 3966, "naklon": 0 }, +{ "label": "35/54", "node": 3971, "naklon": 0 }, +{ "label": "35/55", "node": 3650, "naklon": 6 }, +{ "label": "35/56", "node": 3651, "naklon": 6 }, +{ "label": "35/57", "node": 3669, "naklon": 6 }, +{ "label": "35/58", "node": 3648, "naklon": 6 }, +{ "label": "35/59", "node": 3645, "naklon": 6 }, +{ "label": "35/60", "node": 3659, "naklon": 6 }, +{ "label": "35/61", "node": 3647, "naklon": 6 }, +{ "label": "35/62", "node": 3644, "naklon": 6 }, +{ "label": "35/63", "node": 3671, "naklon": 6 }, +{ "label": "35/64", "node": 3682, "naklon": 6 }, +{ "label": "35/65", "node": 3672, "naklon": 6 }, +{ "label": "35/66", "node": 3683, "naklon": 6 }, +{ "label": "35/67", "node": 3673, "naklon": 6 }, +{ "label": "35/68", "node": 3674, "naklon": 6 }, +{ "label": "35/69", "node": 3679, "naklon": 6 }, +{ "label": "35/70", "node": 3649, "naklon": 6 }, +{ "label": "35/71", "node": 3687, "naklon": 6 }, +{ "label": "35/72", "node": 3677, "naklon": 6 }, +{ "label": "35/73", "node": 3690, "naklon": 6 }, +{ "label": "35/74", "node": 3691, "naklon": 6 }, +{ "label": "35/75", "node": 3676, "naklon": 6 }, +{ "label": "35/76", "node": 3680, "naklon": 6 }, +{ "label": "35/77", "node": 3668, "naklon": 6 }, +{ "label": "35/78", "node": 3681, "naklon": 6 }, +{ "label": "35/79", "node": 3670, "naklon": 6 }, +{ "label": "35/80", "node": 3689, "naklon": 6 }, +{ "label": "35/81", "node": 3678, "naklon": 6 }, +{ "label": "35/82", "node": 3693, "naklon": 6 }, +{ "label": "35/83", "node": 3654, "naklon": null }, +{ "label": "36/1", "node": 4086, "naklon": 0 }, +{ "label": "36/2", "node": 4085, "naklon": 0 }, +{ "label": "36/3", "node": 4083, "naklon": 0 }, +{ "label": "36/4", "node": 4087, "naklon": 0 }, +{ "label": "36/5", "node": 4077, "naklon": 0 }, +{ "label": "36/6", "node": 4082, "naklon": 0 }, +{ "label": "36/7", "node": 4186, "naklon": 0 }, +{ "label": "36/8", "node": 4206, "naklon": 0 }, +{ "label": "36/9", "node": 4080, "naklon": 0 }, +{ "label": "36/10", "node": 4081, "naklon": 0 }, +{ "label": "36/11", "node": 4210, "naklon": 0 }, +{ "label": "36/12", "node": 4079, "naklon": 0 }, +{ "label": "36/13", "node": 4076, "naklon": 0 }, +{ "label": "36/14", "node": 3852, "naklon": 0 }, +{ "label": "36/15", "node": 2813, "naklon": 0 }, +{ "label": "36/16", "node": 4219, "naklon": 0 }, +{ "label": "37/1A", "node": 3104, "naklon": 15 }, +{ "label": "37/1B", "node": 3121, "naklon": 15 }, +{ "label": "37/2", "node": 3113, "naklon": 10 }, +{ "label": "37/3", "node": 3118, "naklon": 10 }, +{ "label": "37/4", "node": 3111, "naklon": 10 }, +{ "label": "37/5", "node": 4020, "naklon": 10 }, +{ "label": "37/6", "node": 3119, "naklon": 10 }, +{ "label": "37/7", "node": 3110, "naklon": 10 }, +{ "label": "37/8", "node": 3108, "naklon": 10 }, +{ "label": "37/12", "node": 3107, "naklon": 0 }, +{ "label": "37/13", "node": 3199, "naklon": 0 }, +{ "label": "37/14", "node": 3120, "naklon": 0 }, +{ "label": "37/15", "node": 3122, "naklon": 0 }, +{ "label": "37/16", "node": 3908, "naklon": 0 }, +{ "label": "37/17", "node": 3114, "naklon": 0 }, +{ "label": "37/18", "node": 3105, "naklon": 0 }, +{ "label": "37/19", "node": 3116, "naklon": 0 }, +{ "label": "37/20", "node": 3106, "naklon": 0 }, +{ "label": "37/21", "node": 2887, "naklon": 5 }, +{ "label": "37/22", "node": 2888, "naklon": 5 }, +{ "label": "37/23", "node": 2877, "naklon": 5 }, +{ "label": "37/24", "node": 2891, "naklon": 5 }, +{ "label": "37/25", "node": 2886, "naklon": 5 }, +{ "label": "37/26", "node": 2892, "naklon": 5 }, +{ "label": "37/27", "node": 2882, "naklon": 5 }, +{ "label": "37/28", "node": 2883, "naklon": 5 }, +{ "label": "37/29", "node": 2876, "naklon": 5 }, +{ "label": "37/30", "node": 3109, "naklon": 5 }, +{ "label": "37/31", "node": 4152, "naklon": 5 }, +{ "label": "37/32", "node": 3117, "naklon": 5 }, +{ "label": "37/33", "node": 2870, "naklon": 5 }, +{ "label": "37/34", "node": 2867, "naklon": 0 }, +{ "label": "37/35", "node": 2865, "naklon": 0 }, +{ "label": "37/36", "node": 3096, "naklon": 0 }, +{ "label": "37/37", "node": 2871, "naklon": 0 }, +{ "label": "37/38", "node": 2884, "naklon": 0 }, +{ "label": "37/39", "node": 2855, "naklon": 0 }, +{ "label": "37/40", "node": 2878, "naklon": 0 }, +{ "label": "37/41", "node": 2889, "naklon": 0 }, +{ "label": "37/42", "node": 2879, "naklon": 0 }, +{ "label": "37/43", "node": 2850, "naklon": 0 }, +{ "label": "37/44", "node": 2894, "naklon": 0 }, +{ "label": "37/45", "node": 2880, "naklon": 0 }, +{ "label": "37/46", "node": 2893, "naklon": 0 }, +{ "label": "37/47", "node": 2890, "naklon": 0 }, +{ "label": "37/48", "node": 4355, "naklon": 0 }, +{ "label": "37/49", "node": 2885, "naklon": 0 }, +{ "label": "37/50", "node": 2875, "naklon": 0 }, +{ "label": "38/30A", "node": 3486, "naklon": 5 }, +{ "label": "38/30B", "node": 3714, "naklon": 0 }, +{ "label": "38/32A", "node": 3483, "naklon": 5 }, +{ "label": "38/32B", "node": 3496, "naklon": 0 }, +{ "label": "38/35A", "node": 3487, "naklon": 5 }, +{ "label": "38/35B", "node": 3498, "naklon": 5 }, +{ "label": "38/38A", "node": 3578, "naklon": 5 }, +{ "label": "38/38B", "node": 3508, "naklon": 5 }, +{ "label": "38/59A", "node": 3787, "naklon": 5 }, +{ "label": "38/59B", "node": 3491, "naklon": 5 }, +{ "label": "38/1", "node": 3568, "naklon": null }, +{ "label": "38/2", "node": 3502, "naklon": 0 }, +{ "label": "38/3", "node": 3836, "naklon": 0 }, +{ "label": "38/4", "node": 3588, "naklon": 0 }, +{ "label": "38/5", "node": 3493, "naklon": 0 }, +{ "label": "38/6", "node": 3580, "naklon": 0 }, +{ "label": "38/7", "node": 3572, "naklon": 0 }, +{ "label": "38/8", "node": 3506, "naklon": 0 }, +{ "label": "38/9", "node": 3503, "naklon": 0 }, +{ "label": "38/10", "node": 3579, "naklon": 0 }, +{ "label": "38/11", "node": 3586, "naklon": 0 }, +{ "label": "38/12", "node": 3495, "naklon": 5 }, +{ "label": "38/13", "node": 3492, "naklon": 5 }, +{ "label": "38/14", "node": 3532, "naklon": 5 }, +{ "label": "38/15", "node": 3574, "naklon": 5 }, +{ "label": "38/16", "node": 4140, "naklon": 5 }, +{ "label": "38/17", "node": 3795, "naklon": 5 }, +{ "label": "38/18", "node": 3788, "naklon": 5 }, +{ "label": "38/19", "node": 3796, "naklon": 5 }, +{ "label": "38/20", "node": 3797, "naklon": 5 }, +{ "label": "38/21", "node": 3798, "naklon": 5 }, +{ "label": "38/22", "node": 3786, "naklon": 5 }, +{ "label": "38/23", "node": 4067, "naklon": 5 }, +{ "label": "38/24", "node": 3773, "naklon": 5 }, +{ "label": "38/25", "node": 3774, "naklon": 5 }, +{ "label": "38/26", "node": 3789, "naklon": 5 }, +{ "label": "38/27", "node": 3520, "naklon": null }, +{ "label": "38/29", "node": 3577, "naklon": 5 }, +{ "label": "38/31", "node": 3530, "naklon": null }, +{ "label": "38/33", "node": 3488, "naklon": 5 }, +{ "label": "38/34", "node": 3505, "naklon": 5 }, +{ "label": "38/36", "node": 3497, "naklon": 5 }, +{ "label": "38/37", "node": 3490, "naklon": 5 }, +{ "label": "38/39", "node": 3585, "naklon": 5 }, +{ "label": "38/40", "node": 3582, "naklon": 5 }, +{ "label": "38/41", "node": 3507, "naklon": 5 }, +{ "label": "38/42", "node": 3484, "naklon": 5 }, +{ "label": "38/43", "node": 3501, "naklon": 5 }, +{ "label": "38/44", "node": 3581, "naklon": 5 }, +{ "label": "38/45", "node": 4192, "naklon": 5 }, +{ "label": "38/46", "node": 3576, "naklon": 5 }, +{ "label": "38/47", "node": 3489, "naklon": 5 }, +{ "label": "38/48", "node": 3573, "naklon": 5 }, +{ "label": "38/49", "node": 3504, "naklon": 5 }, +{ "label": "38/50", "node": 3794, "naklon": 5 }, +{ "label": "38/51", "node": 3485, "naklon": 5 }, +{ "label": "38/52", "node": 3482, "naklon": 5 }, +{ "label": "38/53", "node": 3575, "naklon": 5 }, +{ "label": "38/54", "node": 3499, "naklon": 5 }, +{ "label": "38/55", "node": 3494, "naklon": 5 }, +{ "label": "38/56", "node": 3583, "naklon": 5 }, +{ "label": "38/57", "node": 3570, "naklon": 5 }, +{ "label": "38/58", "node": 3500, "naklon": 0 }, +{ "label": "38/63", "node": 3510, "naklon": null }, +{ "label": "38/64", "node": 3512, "naklon": null }, +{ "label": "38/67", "node": 3535, "naklon": null }, +{ "label": "38/68", "node": 3531, "naklon": null }, +{ "label": "38/69", "node": 3537, "naklon": null }, +{ "label": "39/1", "node": 3522, "naklon": 10 }, +{ "label": "39/2", "node": 4018, "naklon": 10 }, +{ "label": "39/3", "node": 4019, "naklon": 10 }, +{ "label": "39/4", "node": 4154, "naklon": 5 }, +{ "label": "39/5", "node": 3907, "naklon": 5 }, +{ "label": "39/6", "node": 4148, "naklon": 0 }, +{ "label": "39/7", "node": 4153, "naklon": 0 }, +{ "label": "39/8", "node": 3938, "naklon": 0 }, +{ "label": "39/9", "node": 3802, "naklon": 0 }, +{ "label": "39/10", "node": 4015, "naklon": 0 }, +{ "label": "39/11", "node": 3929, "naklon": 0 }, +{ "label": "39/12", "node": 3946, "naklon": 0 }, +{ "label": "39/13", "node": 4014, "naklon": 0 }, +{ "label": "39/14", "node": 4155, "naklon": 0 }, +{ "label": "39/15", "node": 4149, "naklon": 0 }, +{ "label": "39/16", "node": 3642, "naklon": 0 }, +{ "label": "39/17", "node": 3636, "naklon": 5 }, +{ "label": "39/18", "node": 3991, "naklon": 0 }, +{ "label": "39/19", "node": 3994, "naklon": 0 }, +{ "label": "39/20", "node": 3990, "naklon": 0 }, +{ "label": "39/21", "node": 3967, "naklon": 0 }, +{ "label": "39/22", "node": 3977, "naklon": 0 }, +{ "label": "39/23", "node": 3757, "naklon": 15 }, +{ "label": "39/24", "node": 3633, "naklon": 15 }, +{ "label": "39/25", "node": 3744, "naklon": 15 }, +{ "label": "39/26", "node": 4023, "naklon": 5 }, +{ "label": "39/27", "node": 3720, "naklon": 5 }, +{ "label": "39/28", "node": 3734, "naklon": 5 }, +{ "label": "39/29", "node": 3741, "naklon": 5 }, +{ "label": "39/30", "node": 3721, "naklon": 5 }, +{ "label": "39/31", "node": 3845, "naklon": 0 }, +{ "label": "39/32", "node": 3840, "naklon": 0 }, +{ "label": "39/33", "node": 3837, "naklon": null }, +{ "label": "39/34", "node": 3839, "naklon": 0 }, +{ "label": "41/1", "node": 3542, "naklon": null }, +{ "label": "41/2", "node": 3566, "naklon": null }, +{ "label": "41/3", "node": 3548, "naklon": null }, +{ "label": "41/4", "node": 3515, "naklon": null }, +{ "label": "41/5", "node": 3559, "naklon": null }, +{ "label": "41/6", "node": 3509, "naklon": null }, +{ "label": "41/7", "node": 3524, "naklon": null }, +{ "label": "41/8", "node": 3518, "naklon": null }, +{ "label": "41/9", "node": 3182, "naklon": null }, +{ "label": "41/10", "node": 3187, "naklon": null }, +{ "label": "41/11", "node": 3195, "naklon": 0 }, +{ "label": "41/12", "node": 3857, "naklon": 0 }, +{ "label": "41/13", "node": 3183, "naklon": 0 }, +{ "label": "41/14", "node": 3177, "naklon": 0 }, +{ "label": "41/15", "node": 3189, "naklon": 0 }, +{ "label": "41/16", "node": 3186, "naklon": 0 }, +{ "label": "42/1", "node": 3178, "naklon": 0 }, +{ "label": "42/2", "node": 3219, "naklon": 0 }, +{ "label": "42/3", "node": 3475, "naklon": 0 }, +{ "label": "42/4", "node": 3175, "naklon": 0 }, +{ "label": "42/5", "node": 3222, "naklon": 0 }, +{ "label": "42/6", "node": 3221, "naklon": 0 }, +{ "label": "42/7", "node": 3181, "naklon": 0 }, +{ "label": "42/8", "node": 3180, "naklon": 0 }, +{ "label": "42/9", "node": 3218, "naklon": 0 }, +{ "label": "42/10", "node": 3176, "naklon": 0 }, +{ "label": "42/11", "node": 3174, "naklon": 0 }, +{ "label": "42/12", "node": 3220, "naklon": 0 }, +{ "label": "42/13", "node": 3533, "naklon": null }, +{ "label": "42/14", "node": 3543, "naklon": null }, +{ "label": "42/15", "node": 3554, "naklon": null }, +{ "label": "42/16", "node": 3549, "naklon": null }, +{ "label": "43/1", "node": 2857, "naklon": 5 }, +{ "label": "43/2", "node": 2752, "naklon": 5 }, +{ "label": "43/3", "node": 2753, "naklon": 5 }, +{ "label": "43/4", "node": 3024, "naklon": 5 }, +{ "label": "43/5", "node": 2754, "naklon": 5 }, +{ "label": "43/6", "node": 4423, "naklon": 5 }, +{ "label": "43/7", "node": 4368, "naklon": 5 }, +{ "label": "43/8", "node": 2978, "naklon": 5 }, +{ "label": "43/9", "node": 2868, "naklon": 5 }, +{ "label": "43/10", "node": 4377, "naklon": 5 }, +{ "label": "43/11", "node": 2757, "naklon": 5 }, +{ "label": "43/12", "node": 2970, "naklon": 5 }, +{ "label": "43/13", "node": 2758, "naklon": 5 }, +{ "label": "43/14", "node": 4378, "naklon": 5 }, +{ "label": "43/15", "node": 2759, "naklon": 5 }, +{ "label": "43/16", "node": 4342, "naklon": 5 }, +{ "label": "43/17", "node": 3026, "naklon": null }, +{ "label": "43/18", "node": 2986, "naklon": null }, +{ "label": "43/19", "node": 4343, "naklon": null }, +{ "label": "43/20", "node": 2760, "naklon": null }, +{ "label": "43/21", "node": 4379, "naklon": null }, +{ "label": "43/22", "node": 2971, "naklon": null }, +{ "label": "43/23", "node": 2761, "naklon": null }, +{ "label": "43/24", "node": 2762, "naklon": null }, +{ "label": "43/25", "node": 4339, "naklon": null }, +{ "label": "43/26", "node": 4380, "naklon": null }, +{ "label": "43/27", "node": 2975, "naklon": null }, +{ "label": "43/28", "node": 3003, "naklon": null }, +{ "label": "43/29", "node": 4338, "naklon": null }, +{ "label": "43/30", "node": 3002, "naklon": null }, +{ "label": "43/31", "node": 4345, "naklon": null }, +{ "label": "43/32", "node": 2979, "naklon": null }, +{ "label": "43/33", "node": 2989, "naklon": null }, +{ "label": "43/34", "node": 2996, "naklon": null }, +{ "label": "43/35", "node": 2972, "naklon": null }, +{ "label": "43/36", "node": 2988, "naklon": null }, +{ "label": "43/37", "node": 4344, "naklon": null }, +{ "label": "43/38", "node": 3022, "naklon": null }, +{ "label": "43/39", "node": 4341, "naklon": null }, +{ "label": "43/40", "node": 2983, "naklon": null }, +{ "label": "43/41", "node": 2995, "naklon": null }, +{ "label": "43/42", "node": 2763, "naklon": null }, +{ "label": "43/43", "node": 2764, "naklon": null }, +{ "label": "43/44", "node": 2765, "naklon": null }, +{ "label": "43/45", "node": 2766, "naklon": null }, +{ "label": "43/46", "node": 2767, "naklon": null }, +{ "label": "43/47", "node": 2768, "naklon": null }, +{ "label": "43/48", "node": 3018, "naklon": null }, +{ "label": "43/49", "node": 2982, "naklon": null }, +{ "label": "43/50", "node": 3019, "naklon": 0 }, +{ "label": "43/51", "node": 3013, "naklon": null }, +{ "label": "43/52", "node": 3007, "naklon": null }, +{ "label": "43/53", "node": 2980, "naklon": null }, +{ "label": "43/54", "node": 3011, "naklon": null }, +{ "label": "43/55", "node": 2672, "naklon": null }, +{ "label": "43/56", "node": 2673, "naklon": null }, +{ "label": "43/57", "node": 2674, "naklon": null }, +{ "label": "43/58", "node": 2675, "naklon": null }, +{ "label": "43/59", "node": 2676, "naklon": null }, +{ "label": "43/60", "node": 2677, "naklon": null }, +{ "label": "43/61", "node": 2678, "naklon": null }, +{ "label": "43/62", "node": 2679, "naklon": null }, +{ "label": "43/63", "node": 2680, "naklon": null }, +{ "label": "43/64", "node": 2840, "naklon": null }, +{ "label": "43/65", "node": 2682, "naklon": null }, +{ "label": "43/66", "node": 2683, "naklon": null }, +{ "label": "43/67", "node": 2684, "naklon": 0 }, +{ "label": "43/68", "node": 2685, "naklon": null }, +{ "label": "43/69", "node": 2686, "naklon": null }, +{ "label": "43/70", "node": 2687, "naklon": null }, +{ "label": "43/71", "node": 2688, "naklon": null }, +{ "label": "43/72", "node": 2689, "naklon": null }, +{ "label": "43/73", "node": 2690, "naklon": null }, +{ "label": "43/74", "node": 2691, "naklon": null }, +{ "label": "43/75", "node": 2692, "naklon": null }, +{ "label": "43/76", "node": 2693, "naklon": 0 }, +{ "label": "43/77", "node": 2694, "naklon": null }, +{ "label": "43/78", "node": 2695, "naklon": null }, +{ "label": "43/79", "node": 2696, "naklon": 0 }, +{ "label": "43/80", "node": 2697, "naklon": null }, +{ "label": "43/81", "node": 2698, "naklon": 0 }, +{ "label": "43/82", "node": 2699, "naklon": null }, +{ "label": "43/83", "node": 2700, "naklon": 0 }, +{ "label": "43/84", "node": 2744, "naklon": null }, +{ "label": "43/85", "node": 2745, "naklon": 0 }, +{ "label": "43/86", "node": 2746, "naklon": null }, +{ "label": "43/87", "node": 2747, "naklon": 0 }, +{ "label": "43/88", "node": 2748, "naklon": null }, +{ "label": "43/89", "node": 2749, "naklon": 0 }, +{ "label": "43/90", "node": 2841, "naklon": null }, +{ "label": "45/1", "node": 4237, "naklon": 5 }, +{ "label": "45/2", "node": 4226, "naklon": 5 }, +{ "label": "45/3", "node": 4242, "naklon": 5 }, +{ "label": "45/4", "node": 4179, "naklon": 5 }, +{ "label": "45/5", "node": 4247, "naklon": 5 }, +{ "label": "45/6", "node": 4245, "naklon": 5 }, +{ "label": "45/7", "node": 3872, "naklon": 5 }, +{ "label": "45/8", "node": 4175, "naklon": 5 }, +{ "label": "45/9", "node": 4236, "naklon": 5 }, +{ "label": "45/10", "node": 4170, "naklon": 5 }, +{ "label": "45/11", "node": 4238, "naklon": 5 }, +{ "label": "45/12", "node": 4246, "naklon": 5 }, +{ "label": "45/13", "node": 4166, "naklon": 5 }, +{ "label": "45/14", "node": 4227, "naklon": 5 }, +{ "label": "45/15", "node": 4171, "naklon": 5 }, +{ "label": "45/16", "node": 4180, "naklon": 5 }, +{ "label": "45/17", "node": 4244, "naklon": 5 }, +{ "label": "45/18", "node": 4199, "naklon": 5 }, +{ "label": "45/19", "node": 4239, "naklon": 5 }, +{ "label": "45/20", "node": 4207, "naklon": 5 }, +{ "label": "45/21", "node": 4223, "naklon": 5 }, +{ "label": "45/22", "node": 4230, "naklon": 5 }, +{ "label": "45/23", "node": 4233, "naklon": 5 }, +{ "label": "45/24", "node": 4222, "naklon": 5 }, +{ "label": "45/25", "node": 4217, "naklon": 5 }, +{ "label": "45/26", "node": 4243, "naklon": 5 }, +{ "label": "45/27", "node": 4200, "naklon": 5 }, +{ "label": "45/28", "node": 4228, "naklon": 5 }, +{ "label": "45/29", "node": 4211, "naklon": 5 }, +{ "label": "45/30", "node": 4234, "naklon": 5 }, +{ "label": "45/31", "node": 4235, "naklon": 5 }, +{ "label": "45/32", "node": 4203, "naklon": 5 }, +{ "label": "45/33", "node": 4240, "naklon": 5 }, +{ "label": "45/34", "node": 4224, "naklon": 5 }, +{ "label": "45/35", "node": 4232, "naklon": 5 }, +{ "label": "45/36", "node": 4231, "naklon": 5 }, +{ "label": "45/37", "node": 4161, "naklon": 5 }, +{ "label": "45/38", "node": 4225, "naklon": 5 }, +{ "label": "45/39", "node": 4241, "naklon": 5 }, +{ "label": "45/40", "node": 4229, "naklon": 5 }, +{ "label": "45/41", "node": 4221, "naklon": 5 }, +{ "label": "45/42", "node": 4212, "naklon": 5 }, +{ "label": "45/43", "node": 4216, "naklon": 5 }, +{ "label": "45/44", "node": 3864, "naklon": null }, +{ "label": "46/1", "node": 3806, "naklon": 5 }, +{ "label": "46/2", "node": 3813, "naklon": 5 }, +{ "label": "46/3", "node": 3815, "naklon": 5 }, +{ "label": "46/4", "node": 3807, "naklon": 5 }, +{ "label": "46/5", "node": 3895, "naklon": 5 }, +{ "label": "46/6", "node": 3809, "naklon": 5 }, +{ "label": "46/7", "node": 3820, "naklon": 5 }, +{ "label": "46/8", "node": 3805, "naklon": 5 }, +{ "label": "46/9", "node": 3894, "naklon": 0 }, +{ "label": "46/10", "node": 4055, "naklon": 0 }, +{ "label": "46/11", "node": 3812, "naklon": 5 }, +{ "label": "46/12", "node": 3822, "naklon": 5 }, +{ "label": "46/13", "node": 3821, "naklon": 5 }, +{ "label": "46/14", "node": 3808, "naklon": 5 }, +{ "label": "46/15", "node": 3799, "naklon": 5 }, +{ "label": "46/16", "node": 3816, "naklon": 5 }, +{ "label": "46/17", "node": 3751, "naklon": 5 }, +{ "label": "46/18", "node": 3814, "naklon": 5 }, +{ "label": "46/19", "node": 4044, "naklon": 0 }, +{ "label": "46/20", "node": 3931, "naklon": 0 }, +{ "label": "46/21", "node": 3902, "naklon": 5 }, +{ "label": "46/22", "node": 3916, "naklon": 5 }, +{ "label": "46/23", "node": 3892, "naklon": 5 }, +{ "label": "46/24", "node": 3914, "naklon": 5 }, +{ "label": "46/25", "node": 3898, "naklon": 5 }, +{ "label": "46/26", "node": 3897, "naklon": 5 }, +{ "label": "46/27", "node": 3885, "naklon": 5 }, +{ "label": "46/28", "node": 3906, "naklon": 5 }, +{ "label": "46/29", "node": 3930, "naklon": 0 }, +{ "label": "46/30", "node": 3936, "naklon": 0 }, +{ "label": "46/31", "node": 3860, "naklon": 5 }, +{ "label": "46/32", "node": 3841, "naklon": 5 }, +{ "label": "46/33", "node": 3873, "naklon": 5 }, +{ "label": "46/34", "node": 3854, "naklon": 5 }, +{ "label": "46/35", "node": 3939, "naklon": 5 }, +{ "label": "46/36", "node": 3858, "naklon": 5 }, +{ "label": "46/37", "node": 3940, "naklon": 5 }, +{ "label": "46/38", "node": 4035, "naklon": 5 }, +{ "label": "47/1", "node": 3373, "naklon": 0 }, +{ "label": "47/2", "node": 3374, "naklon": 0 }, +{ "label": "47/3", "node": 3384, "naklon": 0 }, +{ "label": "47/4", "node": 3385, "naklon": 0 }, +{ "label": "48/1", "node": 4051, "naklon": 5 }, +{ "label": "48/2", "node": 4041, "naklon": 5 }, +{ "label": "48/3", "node": 4056, "naklon": 5 }, +{ "label": "48/4", "node": 3875, "naklon": 5 }, +{ "label": "48/5", "node": 4061, "naklon": 5 }, +{ "label": "48/6", "node": 4047, "naklon": 5 }, +{ "label": "48/7", "node": 4060, "naklon": 5 }, +{ "label": "48/8", "node": 4059, "naklon": 5 }, +{ "label": "48/9", "node": 4058, "naklon": 5 }, +{ "label": "48/10", "node": 3635, "naklon": 5 }, +{ "label": "48/11", "node": 3640, "naklon": 5 }, +{ "label": "48/12", "node": 3747, "naklon": 5 }, +{ "label": "48/13", "node": 3629, "naklon": 5 }, +{ "label": "48/14", "node": 4048, "naklon": 5 }, +{ "label": "48/15", "node": 4063, "naklon": 5 }, +{ "label": "48/16", "node": 4062, "naklon": 5 }, +{ "label": "48/17", "node": 4043, "naklon": 5 }, +{ "label": "48/18", "node": 4052, "naklon": 5 }, +{ "label": "48/19", "node": 4042, "naklon": 5 }, +{ "label": "48/20", "node": 4053, "naklon": 5 }, +{ "label": "50/15A", "node": 4167, "naklon": null }, +{ "label": "50/15B", "node": 4159, "naklon": null }, +{ "label": "50/1", "node": 4183, "naklon": 0 }, +{ "label": "50/2", "node": 4157, "naklon": 0 }, +{ "label": "50/3", "node": 4160, "naklon": 0 }, +{ "label": "50/4", "node": 4173, "naklon": 0 }, +{ "label": "50/5", "node": 4177, "naklon": 0 }, +{ "label": "50/6", "node": 4174, "naklon": 0 }, +{ "label": "50/7", "node": 4178, "naklon": 0 }, +{ "label": "50/8", "node": 4195, "naklon": 0 }, +{ "label": "50/9", "node": 4169, "naklon": 0 }, +{ "label": "50/10", "node": 4162, "naklon": 0 }, +{ "label": "50/11", "node": 4158, "naklon": 0 }, +{ "label": "50/12", "node": 4182, "naklon": 0 }, +{ "label": "50/13", "node": 4194, "naklon": 0 }, +{ "label": "50/14", "node": 4184, "naklon": 0 }, +{ "label": "50/16", "node": 4197, "naklon": null }, +{ "label": "50/17", "node": 4164, "naklon": null }, +{ "label": "50/18", "node": 3306, "naklon": null }, +{ "label": "50/19", "node": 4168, "naklon": null }, +{ "label": "50/20", "node": 4193, "naklon": null }, +{ "label": "50/21", "node": 4187, "naklon": null }, +{ "label": "50/22", "node": 4163, "naklon": null }, +{ "label": "50/23", "node": 4165, "naklon": null }, +{ "label": "50/24", "node": 4185, "naklon": null }, +{ "label": "50/25", "node": 3904, "naklon": null }, +{ "label": "53/1", "node": 2619, "naklon": 0 }, +{ "label": "53/2", "node": 2623, "naklon": 0 }, +{ "label": "53/3", "node": 2617, "naklon": 0 }, +{ "label": "53/4", "node": 2622, "naklon": 0 }, +{ "label": "53/5", "node": 2618, "naklon": 0 }, +{ "label": "53/6", "node": 2626, "naklon": 0 }, +{ "label": "53/7", "node": 2869, "naklon": 0 }, +{ "label": "53/8", "node": 2613, "naklon": 0 }, +{ "label": "53/9", "node": 2608, "naklon": 0 }, +{ "label": "53/10", "node": 2611, "naklon": 0 }, +{ "label": "53/11", "node": 2598, "naklon": 0 }, +{ "label": "53/12", "node": 3528, "naklon": 0 }, +{ "label": "53/13", "node": 3545, "naklon": 0 }, +{ "label": "53/14", "node": 2620, "naklon": 0 }, +{ "label": "53/15", "node": 2612, "naklon": 0 }, +{ "label": "53/16", "node": 2615, "naklon": 0 }, +{ "label": "53/17", "node": 3722, "naklon": 0 }, +{ "label": "53/18", "node": 2624, "naklon": 0 }, +{ "label": "53/19", "node": 2609, "naklon": 0 }, +{ "label": "53/20", "node": 2625, "naklon": 0 }, +{ "label": "53/21", "node": 2602, "naklon": 0 }, +{ "label": "53/22", "node": 2610, "naklon": 0 }, +{ "label": "53/23", "node": 2599, "naklon": 0 }, +{ "label": "53/24", "node": 2605, "naklon": 0 }, +{ "label": "53/25", "node": 2593, "naklon": 0 }, +{ "label": "53/26", "node": 3074, "naklon": 0 }, +{ "label": "53/27", "node": 2740, "naklon": 0 }, +{ "label": "53/28", "node": 2614, "naklon": 0 }, +{ "label": "53/29", "node": 2601, "naklon": 0 }, +{ "label": "53/30", "node": 4196, "naklon": 0 }, +{ "label": "53/31", "node": 2607, "naklon": 0 }, +{ "label": "53/32", "node": 2582, "naklon": 0 }, +{ "label": "53/33", "node": 2594, "naklon": 0 }, +{ "label": "53/34", "node": 2589, "naklon": 0 }, +{ "label": "53/35", "node": 2596, "naklon": 0 }, +{ "label": "53/36", "node": 2603, "naklon": 0 }, +{ "label": "53/37", "node": 2597, "naklon": 0 }, +{ "label": "53/38", "node": 2590, "naklon": 0 }, +{ "label": "53/39", "node": 2581, "naklon": 0 }, +{ "label": "53/40", "node": 2583, "naklon": 0 }, +{ "label": "53/41", "node": 2580, "naklon": 0 }, +{ "label": "53/42", "node": 2579, "naklon": 0 }, +{ "label": "53/43", "node": 2797, "naklon": 0 }, +{ "label": "53/44", "node": 2577, "naklon": 0 }, +{ "label": "53/45", "node": 2586, "naklon": 0 }, +{ "label": "53/46", "node": 2588, "naklon": 0 }, +{ "label": "53/47", "node": 2591, "naklon": 0 }, +{ "label": "53/48", "node": 2592, "naklon": 0 }, +{ "label": "53/49", "node": 2573, "naklon": 0 }, +{ "label": "53/50", "node": 2595, "naklon": 0 }, +{ "label": "53/51", "node": 2587, "naklon": 0 }, +{ "label": "53/52", "node": 2578, "naklon": 0 }, +{ "label": "53/53", "node": 2574, "naklon": 0 }, +{ "label": "53/54", "node": 2571, "naklon": 0 }, +{ "label": "53/55", "node": 2570, "naklon": 0 }, +{ "label": "53/56", "node": 2576, "naklon": 0 }, +{ "label": "53/57", "node": 2881, "naklon": 0 }, +{ "label": "53/58", "node": 2575, "naklon": 0 }, +{ "label": "53/59", "node": 2572, "naklon": 0 }, +{ "label": "53/60", "node": 2569, "naklon": 0 }, +{ "label": "55/1", "node": 4324, "naklon": 0 }, +{ "label": "55/2", "node": 4319, "naklon": 0 }, +{ "label": "55/3", "node": 4327, "naklon": 0 }, +{ "label": "55/4", "node": 4333, "naklon": 0 }, +{ "label": "55/5", "node": 4332, "naklon": 0 }, +{ "label": "55/6", "node": 4320, "naklon": 0 }, +{ "label": "55/7", "node": 4317, "naklon": 0 }, +{ "label": "55/8", "node": 4318, "naklon": 0 }, +{ "label": "55/9", "node": 4328, "naklon": 0 }, +{ "label": "55/10", "node": 4323, "naklon": 0 }, +{ "label": "55/11", "node": 4325, "naklon": 0 }, +{ "label": "55/12", "node": 4326, "naklon": 0 }, +{ "label": "55/13", "node": 4316, "naklon": 0 }, +{ "label": "55/14", "node": 4322, "naklon": 0 }, +{ "label": "55/15", "node": 4331, "naklon": 0 }, +{ "label": "55/16", "node": 4321, "naklon": 0 }, +{ "label": "55/17", "node": 4315, "naklon": 0 }, +{ "label": "55/18", "node": 4329, "naklon": 0 }, +{ "label": "55/19", "node": 4334, "naklon": 0 }, +{ "label": "55/20", "node": 4330, "naklon": 0 } +]; + +module.exports = { naklony }; diff --git a/RVO14/databases/modbus_config.js b/RVO14/databases/modbus_config.js new file mode 100755 index 0000000..b73116a --- /dev/null +++ b/RVO14/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/RVO14/databases/nodes.table b/RVO14/databases/nodes.table new file mode 100755 index 0000000..9ecb93f --- /dev/null +++ b/RVO14/databases/nodes.table @@ -0,0 +1,12 @@ +node:number|pole_number:string|node_type:string|tbname:string|line:number|profile:string|processed:boolean|status:boolean|time_of_last_communication:number ++|3142|5|NEMA|rDbQ84xzwgdqEoPm3kbEDO09anOZY1RXyBv2LVM6|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":8,"dusk_lux_sensor_value":8,"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|1760573784482|........... ++|3340|7|NEMA|roKgWqY95V3mXMRzyAjKqP0bLjexpJPvaGDBw826|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":8,"dusk_lux_sensor_value":8,"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|1760573795109|........... ++|3149|4|NEMA|52dD6ZlV1QaOpRBmbAqGYXkKnGzWMLj4eJq38Pgo|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":8,"dusk_lux_sensor_value":8,"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|1760573784930|........... ++|3342|6|NEMA|E6Kg9oDnLWyzPRMva7v5ZXkJxp4VG58qO2w1lZYe|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":8,"dusk_lux_sensor_value":8,"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|1760573788813|........... ++|3135|3|NEMA|PLBJzmK1r3Gynd6OW0gKX80e5wV4vx9bDEqNgYR8|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":8,"dusk_lux_sensor_value":8,"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|1760573776764|........... ++|3137|2|NEMA|Nzp2OoJlqn6r1ZgvdA3Byr7abBwP5G4eE3RQmyxD|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":8,"dusk_lux_sensor_value":8,"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|1760573782836|........... ++|3136|1|NEMA|wvKJdZML6mXP4DzWBAXxP6AjxNloa5g23Ve9Y1ry|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":8,"dusk_lux_sensor_value":8,"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|1760573777211|........... ++|3152|8|NEMA|nJL5lPMwBx23YpqRe0rpMQ7damXvWVbOrD4gNzy8|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":8,"dusk_lux_sensor_value":8,"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|1760573794310|........... ++|3886|9|NEMA|XMBbew5z4ELrZa2mRAd3VY78vPN6gy3DdVYlpKjq|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":8,"dusk_lux_sensor_value":8,"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|1760573789644|........... ++|3341|10|NEMA|3a5oqJN1bgnx4Ol9dk86vqAByE6jQ8mKDWMpGrLV|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":8,"dusk_lux_sensor_value":8,"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|1760573787886|........... ++|3352|11|NEMA|EjgWGnXaLy9opPOz20n6ZQ086BlYM3w1deVQvbKr|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":8,"dusk_lux_sensor_value":8,"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|1760573806247|........... diff --git a/RVO14/databases/nodes_original/nodes_original.table b/RVO14/databases/nodes_original/nodes_original.table new file mode 100755 index 0000000..30530f7 --- /dev/null +++ b/RVO14/databases/nodes_original/nodes_original.table @@ -0,0 +1 @@ +[{"3142": "rDbQ84xzwgdqEoPm3kbEDO09anOZY1RXyBv2LVM6"}, {"3340": "roKgWqY95V3mXMRzyAjKqP0bLjexpJPvaGDBw826"}, {"3149": "52dD6ZlV1QaOpRBmbAqGYXkKnGzWMLj4eJq38Pgo"}, {"3342": "E6Kg9oDnLWyzPRMva7v5ZXkJxp4VG58qO2w1lZYe"}, {"3135": "PLBJzmK1r3Gynd6OW0gKX80e5wV4vx9bDEqNgYR8"}, {"3137": "Nzp2OoJlqn6r1ZgvdA3Byr7abBwP5G4eE3RQmyxD"}, {"3136": "wvKJdZML6mXP4DzWBAXxP6AjxNloa5g23Ve9Y1ry"}, {"3152": "nJL5lPMwBx23YpqRe0rpMQ7damXvWVbOrD4gNzy8"}, {"3886": "XMBbew5z4ELrZa2mRAd3VY78vPN6gy3DdVYlpKjq"}, {"3341": "3a5oqJN1bgnx4Ol9dk86vqAByE6jQ8mKDWMpGrLV"}, {"3352": "EjgWGnXaLy9opPOz20n6ZQ086BlYM3w1deVQvbKr"}] \ No newline at end of file diff --git a/RVO14/databases/notifications.table b/RVO14/databases/notifications.table new file mode 100755 index 0000000..f7c96cb --- /dev/null +++ b/RVO14/databases/notifications.table @@ -0,0 +1,41 @@ +key:string|weight:string|sk:string|en:string ++|switching_profile_point_applied_to_line|INFORMATIONAL|Aplikovaný bod spínacieho profilu na línií č. ${line} : ${value}|Switching profile point applied to line no. ${line} : ${value}|............... ++|dusk_has_occured|INFORMATIONAL|Nastal súmrak: ${value}|Dusk has occured: ${value}|............... ++|dawn_has_occured|INFORMATIONAL|Nastal úsvit: ${value}|Dawn has occured: ${value}|............... ++|dimming_profile_was_successfully_received_by_node|NOTICE|Stmievací profil bol úspešne prijatý nodom č. ${node}|Dimming profile was successfully received by node no. ${node}|............... ++|master_node_is_responding_again|NOTICE|Master node začal znovu odpovedať|Master node is responding again|............... ++|command_was_sent_from_terminal_interface|DEBUG|Z terminálu bol odoslaný príkaz|A command was sent from terminal interface|............... ++|master_node_is_not_responding|ALERT|Master node neodpovedá|Master node is not responding|............... ++|configuration_of_dimming_profile_to_node_failed|ALERT|Konfigurácia stmievacieho profilu pre node č. ${node} zlyhala|Configuration of dimming profile to node no. ${node} has failed|............... ++|circuit_breaker_was_turned_on_line|NOTICE|Zapnutie ističa na línii č. ${line}|Circuit breaker was turned on - line no. ${line}|............... ++|circuit_breaker_was_turned_off_line|ERROR|Vypnutie ističa na línií č. ${line}|Circuit breaker was turned off - line no. ${line}|............... ++|dimming_profile_was_processed_for_node|INFORMATIONAL|Stmievací profil bol spracovaný pre node č. ${node}|Dimming profile was processed for node no. ${node}|............... ++|switching_profile_was_processed_for_line|INFORMATIONAL|Spínací profil bol spracovaný pre líniu č. ${line}|Switching profile was processed for line no. ${line}|............... ++|thermometer_is_not_responding|WARNING|Teplomer neodpovedá|Thermometer is not responding|............... ++|thermometer_is_responding_again|NOTICE|Teplomer znovu odpovedá|Thermometer is responding again|............... ++|thermometer_sends_invalid_data|WARNING|Teplomer posiela neplatné hodnoty|Thermometer sends invalid data|............... ++|main_switch_has_been_turned_off|CRITICAL|Hlavný vypínač bol vypnutý|Main switch has been turned off|............... ++|main_switch_has_been_turned_on|NOTICE|Hlavný vypínač bol zapnutý|Main switch has been turned on|............... ++|power_supply_has_disconnected_input|ALERT|Napájací zdroj nemá napätie na vstupe|Power supply has disconnected input|............... ++|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_main_open|NOTICE|Hlavné dvere boli otvorené|Main door has been opened|............... ++|door_em_open|NOTICE|Dvere silovej časti boli otvorené|Power door has been opened|............... ++|door_main_open_without_permission|WARNING|Hlavné dvere boli otvorené bez povolenia - zapnutá siréna|Main door has been opened without permission - alarm is on|............... ++|door_em_open_without_permission|WARNING|Dvere silovej časti boli otvorené bez povolenia|Power door has been opened without permission|............... ++|door_main_close|NOTICE|Hlavné dvere boli zatvorené|Main door has been closed|............... ++|door_em_close|NOTICE|Dvere silovej časti boli zatvorené|Power door has been closed|............... ++|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|............... ++|electrometer_ok|NOTICE|Elektromer znovu odpovedá|Electrometer is responding again|............... ++|no_voltage_on_phase|CRITICAL|Na fáze č. ${phase} nie je napätie|No voltage detected on phase no. ${phase}|............... ++|voltage_on_phase_restored|NOTICE|Napätie na fáze č. ${phase} bolo obnovené|Voltage on phase no. ${phase} has been restored|............... ++|flow_start|NOTICE|FLOW bol spustený|FLOW has been started |............... ++|twilight_sensor_nok|ERROR|Sensor súmraku neodpovedá|Twilight sensor is not responding|............... ++|twilight_sensor_ok|NOTICE|Sensor súmraku znovu odpovedá|Twilight sensor is responding again|............... ++|lamps_have_turned_on|NOTICE|Lampy sa zapli|Lamps have turned on|............... ++|lamps_have_turned_off|NOTICE|Lampy sa vypli|Lamps have turned off|............... ++|flow_restart|NOTICE|FLOW bol reštartovaný|FLOW has been restarted|............... ++|nodes_db_changed|NOTICE|Zmena v node databáze|Node db has changed|............... diff --git a/RVO14/databases/pins.table b/RVO14/databases/pins.table new file mode 100755 index 0000000..0eb3d05 --- /dev/null +++ b/RVO14/databases/pins.table @@ -0,0 +1,14 @@ +pin:string|type:string|line:number +*|input1_01|door_condition|0|........... +*|input1_02|rotary_switch_state|0|........... +*|input1_03|rotary_switch_state|0|........... +*|input1_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/RVO14/databases/relays.table b/RVO14/databases/relays.table new file mode 100755 index 0000000..568bbe1 --- /dev/null +++ b/RVO14/databases/relays.table @@ -0,0 +1,5 @@ +line:number|tbname:string|contactor:number|profile:string ++|0|Nzp2OoJlqn6r1ZgvdA3B1j7abBwP5G4eE3RQmyxD|1||........... ++|1|eod9aRWLVl34Gx1Dn7VN5W72rz6qjgmpEXwQJN5Z|9|{"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|3a5oqJN1bgnx4Ol9dk89y37ByE6jQ8mKDWMpGrLV|9|{"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|EjgWGnXaLy9opPOz20n4rZ786BlYM3w1deVQvbKr|9|{"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}|.................................................................................................................. diff --git a/RVO14/databases/settings.table b/RVO14/databases/settings.table new file mode 100755 index 0000000..36e51bd --- /dev/null +++ b/RVO14/databases/settings.table @@ -0,0 +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|project_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|cloud_topic:string|has_main_switch:boolean|daily_report:boolean|send_changed_node_numbers:boolean ++|rvo_senica_14_ip124|en|28.65509C0E0000|48.70826502|17.28455203|192.168.252.1|rvo_senica_14_ip124|0v2DRYFcfX5tAyVE3PBx|1883|0|61|unipi|ttyUSB0|1|20|5|6|3|u124|0|1|1|................................................... diff --git a/RVO14/databases/tbdata.nosql b/RVO14/databases/tbdata.nosql new file mode 100755 index 0000000..d5ed78e --- /dev/null +++ b/RVO14/databases/tbdata.nosql @@ -0,0 +1,4 @@ +-"Nzp2OoJlqn6r1ZgvdA3B1j7abBwP5G4eE3RQmyxD":[{"ts":1760530535409,"values":{"_event":{"type":"notice","status":"new","source":{"func":"modbus_reader","component":"1699965957410","component_name":"Modbus reader","edge":"Nzp2OoJlqn6r1ZgvdA3B1j7abBwP5G4eE3RQmyxD"},"message":{"sk":"rvo_senica_14_ip124: FLOW bol reštartovaný","en":"rvo_senica_14_ip124: FLOW has been restarted"},"message_data":""}}}],"id":"3000315001sl71b"} +-"Nzp2OoJlqn6r1ZgvdA3B1j7abBwP5G4eE3RQmyxD":[{"ts":1760530535484,"values":{"edge_fw_version":"2025-10-08","maintenance_mode":false}}],"id":"3000315002sl70b"} +-"Nzp2OoJlqn6r1ZgvdA3B1j7abBwP5G4eE3RQmyxD":[{"ts":1760530535497,"values":{"statecode":2,"power_mode":"Automatic"}}],"id":"3000315004sl70b"} +-"Nzp2OoJlqn6r1ZgvdA3B1j7abBwP5G4eE3RQmyxD":[{"ts":1760530535520,"values":{"_event":{"type":"notice","status":"new","source":{"func":"rsPort.open()","component":"1699963668903","component_name":"DIDO_Controller","edge":"Nzp2OoJlqn6r1ZgvdA3B1j7abBwP5G4eE3RQmyxD"},"message":{"sk":"rvo_senica_14_ip124: FLOW bol spustený","en":"rvo_senica_14_ip124: FLOW has been started "},"message_data":""}}}],"id":"3000315006sl70b"} diff --git a/RVO14/databases/tbdatacloud.nosql b/RVO14/databases/tbdatacloud.nosql new file mode 100755 index 0000000..f8e0503 --- /dev/null +++ b/RVO14/databases/tbdatacloud.nosql @@ -0,0 +1,3 @@ +-"Nzp2OoJlqn6r1ZgvdA3B1j7abBwP5G4eE3RQmyxD":[{"ts":1760530535484,"values":{"edge_fw_version":"2025-10-08","maintenance_mode":false}}],"id":"3000315003sl71b"} +-"Nzp2OoJlqn6r1ZgvdA3B1j7abBwP5G4eE3RQmyxD":[{"ts":1760530535497,"values":{"statecode":2,"power_mode":"Automatic"}}],"id":"3000315005sl71b"} +-"Nzp2OoJlqn6r1ZgvdA3B1j7abBwP5G4eE3RQmyxD":[{"ts":1760530535520,"values":{"_event":{"type":"notice","status":"new","source":{"func":"rsPort.open()","component":"1699963668903","component_name":"DIDO_Controller","edge":"Nzp2OoJlqn6r1ZgvdA3B1j7abBwP5G4eE3RQmyxD"},"message":{"sk":"rvo_senica_14_ip124: FLOW bol spustený","en":"rvo_senica_14_ip124: FLOW has been started "},"message_data":""}}}],"id":"3000315007sl71b"} diff --git a/RVO14/databases/total_energy.js b/RVO14/databases/total_energy.js new file mode 100755 index 0000000..dde340e --- /dev/null +++ b/RVO14/databases/total_energy.js @@ -0,0 +1,38 @@ +//key is rvo_number, value is max energy when lamps are on +const total_energy = { + 1: 580, + 2: 1100, + 3: 3700, + 4: 4100, + 7: 360, + 12: 1700, + 13: 5400, + 14: 440, + 15: 6100, + 16: 4800, + 20: 1600, + 21: 1000, + 22: 2600, + 23: 1000, + 25: 2600, + 33: 240, + 34: 4000, + 35: 2700, + 36: 820, + 37: 1400, + 35: 3500, + 39: 1170, + 41: 740, + 42: 660, + 43: 4900, + 45: 930, + 46: 700, + 47: 1100, + 48: 1500, + 50: 3200, + 53: 1250, + 55: 1000, + 56: 5500 +} + +module.exports = total_energy; diff --git a/RVO14/debug.js b/RVO14/debug.js new file mode 100755 index 0000000..9818194 --- /dev/null +++ b/RVO14/debug.js @@ -0,0 +1,16 @@ +// =================================================== +// FOR DEVELOPMENT +// Total.js - framework for Node.js platform +// https://www.totaljs.com +// =================================================== + +const options = {}; + +// options.ip = '127.0.0.1'; +// options.port = parseInt(process.argv[2]); +// options.config = { name: 'Total.js' }; +// options.sleep = 3000; +// options.inspector = 9229; +// options.watch = ['private']; + +require('total.js/debug')(options); \ No newline at end of file diff --git a/RVO14/err.txt b/RVO14/err.txt new file mode 100755 index 0000000..1ede1aa --- /dev/null +++ b/RVO14/err.txt @@ -0,0 +1,33 @@ +[2025-09-23T14:01:21.682] [ERROR] errLogs - uncaughtException: Cannot read property 'getHours' of undefined +[2025-09-23T14:01:21.683] [ERROR] errLogs - TypeError: Cannot read property 'getHours' of undefined + at Timeout.emptyReportToSend [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:01:21.684] [ERROR] errLogs - uncaughtException: Cannot read property 'getHours' of undefined +[2025-09-23T14:01:21.684] [ERROR] errLogs - TypeError: Cannot read property 'getHours' of undefined + at Timeout.emptyReportToSend [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:01:21.693] [ERROR] errLogs - uncaughtException: Cannot read property 'getHours' of undefined +[2025-09-23T14:01:21.693] [ERROR] errLogs - TypeError: Cannot read property 'getHours' of undefined + at Timeout.emptyReportToSend [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:01:27.403] [ERROR] errLogs - uncaughtException: date.getHours is not a function +[2025-09-23T14:01:27.404] [ERROR] errLogs - TypeError: date.getHours is not a function + at emptyReportToSend (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at Timeout.dailyReportCheck [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1351:5) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:01:27.404] [ERROR] errLogs - uncaughtException: date.getHours is not a function +[2025-09-23T14:01:27.405] [ERROR] errLogs - TypeError: date.getHours is not a function + at emptyReportToSend (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at Timeout.dailyReportCheck [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1351:5) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:01:27.410] [ERROR] errLogs - uncaughtException: date.getHours is not a function +[2025-09-23T14:01:27.410] [ERROR] errLogs - TypeError: date.getHours is not a function + at emptyReportToSend (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at Timeout.dailyReportCheck [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1351:5) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) diff --git a/RVO14/flow/cloudmqttconnect.js b/RVO14/flow/cloudmqttconnect.js new file mode 100755 index 0000000..b03491f --- /dev/null +++ b/RVO14/flow/cloudmqttconnect.js @@ -0,0 +1,357 @@ +exports.id = 'cloudmqttconnect'; +exports.title = 'Cloud connect mqtt'; +exports.group = 'MQTT'; +exports.color = '#888600'; +exports.version = '1.0.2'; +exports.icon = 'sign-out'; +exports.input = 2; +exports.output = 2; +exports.options = { host: 'tb-stage.worksys.io', port: 1883, clientid: "", username: "" }; + +exports.html = `
+
+
+
Hostname or IP address (if not empty - setting will override db setting)
+
+
+
Port
+
+
+
+
+
@(Client id)
+
+
+
topic
+
+
+
`; + + + +const { promisifyBuilder } = require('./helper/db_helper'); +const fs = require('fs'); +const mqtt = require('mqtt'); +const nosql = NOSQL('tbdatacloud'); + +const SEND_TO = { + debug: 0, + rpcCall: 1, +} + +//CONFIG +let saveTelemetryOnError = true;//backup_on_failure overrides this value +//------------------------ + +const noSqlFileSizeLimit = 4194304;//use 5MB - 4194304 +let insertNoSqlCounter = 0; +let insertBackupNoSqlCounter = 0; +let processingData = false; + +let backup_on_failure = true;//== saveTelemetryOnError - create backup client send failure +let restore_from_backup = 50; //how many rows process at once? +let restore_backup_wait = 3;//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; + + +exports.install = function(instance) { + + var client; + var opts; + var clientReady = false; + + let o = {}; //options + + function main() { + loadSettings(); + } + + //set opts according to db settings + function loadSettings() { + + o = instance.options; + if (!o.topic) o.topic = FLOW.GLOBALS.settings.cloud_topic; + + opts = { + host: o.host, + port: o.port, + clientId: o.clientid, + username: o.username, + rejectUnauthorized: false, + resubscribe: false + }; + + console.log("wsmqttpublich -> loadSettings from instance.options", o); + + if (!o.topic) { + instance.status("Not configured", "white"); + console.log("Cloud mqtt connect: no topic selected"); + return; + } + + connectToTbServer(); + } + + function connectToTbServer() { + var url = "mqtt://" + opts.host + ":" + opts.port; + console.log("MQTT URL: ", url); + + client = mqtt.connect(url, opts); + + client.on('connect', function() { + client.subscribe(`${o.topic}_backward`, (err) => { + if (!err) { + console.log("MQTT subscribed"); + } + }); + instance.status("Connected", "green"); + clientReady = true; + sendClientError = true; + }); + + client.on('reconnect', function() { + instance.status("Reconnecting", "yellow"); + clientReady = false; + }); + + client.on('message', function(topic, message) { + // message is type of buffer + message = message.toString(); + if (message[0] === '{') { + TRY(function() { + + message = JSON.parse(message); + if (message.hasOwnProperty("device") && message.hasOwnProperty("data") && message.data.hasOwnProperty("id")) { + client.publish(`${o.topic}_forward`, `{"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 } }); + } + + }, () => instance.debug('MQTT: Error parsing data', message)); + } + + instance.send(SEND_TO.rpcCall, { "topic": o.topic, "content": message }); + }); + + client.on('close', function() { + clientReady = false; + + instance.status("Disconnected", "red"); + instance.send(SEND_TO.debug, { "message": "Client CLOSE signal received !" }); + }); + + client.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) { + console.log('MQTT client error', err); + sendClientError = false; + } + clientReady = false; + }); + + } + + + instance.on('0', function(data) { + + if (clientReady) { + //do we have some data in backup file? if any, process data from database + if (saveTelemetryOnError) { + //read telemetry data and send back to server + if (!processingData) processDataFromDatabase(); + } + + let stringifiedJson = JSON.stringify(data.data) + client.publish(`${o.topic}_forward`, stringifiedJson, { qos: 1 }); + } + 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 (saveTelemetryOnError && o.topic) { + //create new file from tbdata.nosql, if file size exceeds given limit, and clear tbdata.nosql + makeBackupFromDbFile(); + + //write to tb + data.data.id = UID(); + nosql.insert(data.data); + } + } + }); + + instance.on("1", _ => { + main(); + }) + + instance.close = function(done) { + if (clientReady) { + client.end(); + } + }; + + + function getDbBackupFileCounter(type) { + var files = fs.readdirSync(__dirname + "/../databases"); + + let counter = 0; + for (var i = 0; i < files.length; i++) { + + if (files[i] == "tbdatacloud.nosql") continue; + + if (files[i].endsWith(".nosql")) { + + let pos = files[i].indexOf("."); + if (pos > -1) { + + let fileCounter = counter; + let firstDigit = files[i].slice(0, pos); + + fileCounter = parseInt(firstDigit); + if (isNaN(fileCounter)) fileCounter = 0; + //console.log("getDbBackupFileCounter digit:", files[i], firstDigit, fileCounter, isNaN(fileCounter), type); + + if (type == "max") { + if (fileCounter > counter) { + counter = fileCounter; + } + } + else if (type == "min") { + if (counter == 0) counter = fileCounter; + + if (fileCounter < counter) { + counter = fileCounter; + } + } + } + } + + } + + if (type == "max") counter++; + + return counter; + } + + const makeBackupFromDbFile = async () => { + + if (!saveTelemetryOnError) return; + + //to avoid large file: tbdata.nosql + + //init value is 0! + if (insertNoSqlCounter > 0) { + --insertNoSqlCounter; + return; + } + + insertNoSqlCounter = 100; + + let source = __dirname + "/../databases/tbdatacloud.nosql"; + + var stats = fs.statSync(source); + var fileSizeInBytes = stats.size; + + if (fileSizeInBytes > noSqlFileSizeLimit) { + + let counter = 1; + counter = getDbBackupFileCounter("max"); + + let destination = __dirname + "/../databases/" + counter + "." + "tbdatacloud.nosql"; + + //make backup file + fs.copyFileSync(source, destination); + //fs.renameSync(p, p + "." + counter); + + //clear tbdata.nosql + fs.writeFileSync(source, ""); + fs.truncateSync(source, 0); + + } + } + + const processDataFromDatabase = async () => { + + if (restore_from_backup <= 0) return; + + //calculate diff + const now = new Date(); + let currentTime = now.getTime(); + let diff = currentTime - lastRestoreTime; + + if ((diff / 1000) < restore_backup_wait) { + //console.log("*********restore_backup_wait", diff, restore_backup_wait); + return; + } + + processingData = true; + + //get filename to process + let counter = getDbBackupFileCounter("min"); + + //we have some backup files + let dataBase = 'tbdata'; + + var nosql; + if (counter == 0) dataBase = 'tbdatacloud'; + else dataBase = counter + "." + 'tbdatacloud'; + + nosql = NOSQL(dataBase); + + //select all data - use limit restore_from_backup + let records = await promisifyBuilder(nosql.find().take(restore_from_backup)); + + for (let i = 0; i < records.length; i++) { + if (clientReady) { + + let item = records[i]; + let id = item.id; + + if (id !== undefined) { + //console.log("------------processDataFromDatabase - remove", id, dataBase, i); + + try { + + let message = JSON.parse(JSON.stringify(item)); + delete message.id; + client.publish(`${o.topic}_forward`, JSON.stringify(message), { qos: 1 }); + + //remove from database + await promisifyBuilder(nosql.remove().where("id", id)); + + } catch (error) { + //process error + console.log("processDataFromDatabase", error); + } + + } + + } + else { + processingData = false; + return; + } + } + + if (records.length > 0) { + //clean backup file + if (counter > 0) nosql.clean(); + } + + //no data in db, remove + if (records.length == 0) { + if (counter > 0) nosql.drop(); + } + + const d = new Date(); + lastRestoreTime = d.getTime(); + + processingData = false; + + } + + instance.on('options', main); + +}; diff --git a/RVO14/flow/cmd_manager.js b/RVO14/flow/cmd_manager.js new file mode 100755 index 0000000..25912df --- /dev/null +++ b/RVO14/flow/cmd_manager.js @@ -0,0 +1,3071 @@ +exports.id = 'cmd_manager'; +exports.title = 'CMD Manager'; +exports.group = 'Worksys'; +exports.color = '#5D9CEC'; +exports.version = '0.0.3'; +exports.output = ['red', 'blue', 'yellow', 'blue', 'white', 'green']; +exports.input = 3; +exports.icon = 'cloud-upload'; + +exports.html = ` +
+
+
+
RPC - run RPC calls

+
+
+
@(User)
+
+
+
@(Password)
+
+
+
@(My edge)
+
+
+
+`; +exports.readme = `Manager for CMD calls`; + + +exports.install = function(instance) { + + 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, isEmptyObject, emptyJsObject, writeToFile, addToArrayIfUnique } = require('./helper/utils'); + const bitwise = require('bitwise'); + + var SunCalc = require('./helper/suncalc'); + const DataToTbHandler = require('./helper/DataToTbHandler'); + const errorHandler = require('./helper/ErrorToServiceHandler'); + const { sendNotification } = require('./helper/notification_reporter'); + const process = require('process'); + const { errLogger, logger, monitor } = require('./helper/logger'); + + //for accelerometer purposes + const { naklony } = require("../databases/accelerometer_db"); + + const dbNodes = TABLE("nodes"); + const dbRelays = TABLE("relays"); + + let GLOBALS; + let SETTINGS; + let rsPort; + let tbHandler; + + // runTasks intervals + const SHORT_INTERVAL = 30; + const LONG_INTERVAL = 300; + + //send data to following instances: + const SEND_TO = { + debug: 0, + tb: 1, + http_response: 2, + dido_controller: 3, + infoSender: 4, + dailyReport: 5 + } + + 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 + } + + 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 sendNodeReadout = null; // interval for sending agregate data from node + + 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["1"] = minutes; // dimming + priorities["76"] = minutes; // power + + minutes = 5; + priorities["75"] = minutes; // current + priorities["79"] = minutes; // energy + priorities["87"] = minutes; // aktualny cas + //priorities["84"] = minutes; //accelerometer + + minutes = 10; + priorities["74"] = minutes; // voltage + priorities["77"] = minutes; // power factor + priorities["78"] = minutes; // frequency + + minutes = 60; + priorities["0"] = minutes; // statecode + priorities["6"] = minutes; // dusk + priorities["7"] = minutes; // dawn + priorities["8"] = minutes; // profile + + minutes = 60 * 24; + priorities["89"] = minutes; // verzia fw + priorities["80"] = minutes; // lifetime + + //prikazy kt sa budu spustat na dany node - see config.js in terminal-oms.app. (1 - dimming) + let listOfCommands = [0, 1, 6, 7, 8, 74, 75, 76, 77, 78, 79, 80, 87, 89]; + + 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; + + // holds dusk, dawn (and more) values + let sunCalcResult; + + //helper container for counting resolved group of commands (commands related to set profile) + let cmdCounter = {};//key is node, value is counter + + //TODO: is this set working?? According to previous checks, sets do not work + //if sending of profile to node fails, we send notification and push node into set, so we do not send notification twice + const nodeProfileSendFail = new Set(); + + //we expect to get current temperature in Senica from senica-prod01 + let temperatureInSenica = null; + let accelerometerInterval = null; + + //NOTE: daily reports senica: + //rvo_is_on status, we monitor all nodes - if true, power and dimming should be not 0, if false, 24/7 nodes should be 0, other rvo should not respond + let rvo_is_on; + let previous_rvo_is_on_value; + let handleDailyReport; //setInterval for dailyReportHandler function + let dailyReport = {}; //data needed for daily report + let reportToSend = {}; //final report which we send to cloud + let breakerCounter = null; // status of breakers after flow starts is not in report + let rvoPeriod; // interval of checking dusk dawn and if rvo_is_on + let initialReportStatus = false; + + const DAILY_REPORT_HANDLER_TIME = 3_600_000; + const SET_SUNCALC_RESULT_TIME = 3_600_000; + const SET_RVO_PERIOD_TIME = 300_000; + const ADD_NODE_TO_REPORT_TIME = 3_600_000; + + //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); + + let now = new Date(); + console.log("Cmd-mngr installed", now.toLocaleString("sk-SK")); + + sunCalcResult = calculateDuskDawn(); + + handleRsPort(); + + customTasksInterval = setInterval(reportEdgeDateTimeAndNumberOfLuminaires, 120_000); + setTimeout(reportEdgeDateTimeAndNumberOfLuminaires, 4000); + + //dailyReport related + emptyReportToSend(); + breakerCounter = Object.keys(relaysData).length - 1; // we get number of lines (breakers) except of line 0 + rvoPeriod = setInterval(setRvoPeriod, SET_RVO_PERIOD_TIME); + setTimeout(setRvoPeriod, 3000); + setInterval(setSunCalcResult, SET_SUNCALC_RESULT_TIME); + handleDailyReport = setInterval(dailyReportHandler, DAILY_REPORT_HANDLER_TIME); + + + setCorrectTime = setInterval(setCorrectPlcTimeOnceADay, 60000 * 60); // 1 hour + setCorrectPlcTimeOnceADay(); + + sendNodeReadout = setInterval(sendNodesData, 150_000); + accelerometerInterval = setInterval(accelerometerData, 60000 * 30); //30 min + } + + + 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" + //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 + // if node regular readout does not respond, we repeat request + params.repeatCounter = 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-mngr: 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.byte4 = 96; + params.recipient = 1; + params.register = 8; + params.rw = 1;//write + params.timestamp = timestamp; + 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.byte4 = 96; + params.recipient = 1; + params.register = 8; + params.rw = 1;//write + params.timestamp = timestamp; + 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). + */ + + 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.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.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 + { + + logger.debug("processNodeProfile: Threshold lux level for DUSK/DAWN", node); + + let params = getParams(); + params.type = "set_node_profile"; + params.address = node; + params.register = 96; + params.recipient = 1; + params.rw = 1;//write + params.timestamp = timestamp; + 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(); + params.type = "set_node_profile"; + params.address = node; + params.register = 97; + params.recipient = 1; + params.rw = 1;//write + params.timestamp = timestamp; + 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.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); + + 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); + + console.log("proces profile finished *********************") + } + + + 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; + }); + } + + + 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) { + for (let k in nodesData) { + 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`); + } + } + } + + + function loadRelaysData(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 (value.contactor == 1) processAllNodeProfilesOnLine(value.line); + } + } + + + function reportOnlineNodeStatus(line) { + //Po zapnutí línie broadcastovo aktualizovať predtým čas a o 3 sek neskor - status, brightness + + logger.debug("Cmd-mngr: ----->reportOnlineNodeStatus for line", line); + + const d = new Date(); + + // broadcast actual time + let params = getParams(); + params.address = 0xffffffff;//Broadcast + params.byte1 = d.getHours(); + params.byte2 = d.getMinutes(); + params.recipient = 2;//2 broadcast, address = 0 + params.register = 87;//Actual time + params.rw = 1;//write + params.type = "node-onetime-write"; + params.timestamp = d.getTime() + 30000; + params.info = "run broadcast: Actual time"; + //params.debug = true; + + tasks.push(params); + + let sec = 3; + setTimeout(function() { + //Po zapnutí línie - spraviť hromadný refresh stavu práve zapnutých svietidiel + + let time = Date.now(); + + for (let k in nodesData) { + + //potrebujem nody k danej linii + 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].node_status_before_offline === true || nodesData[k].status === true) { + status = "OK"; + nodesData[k].time_of_last_communication = time; + } + + nodesData[k].readout.status = status; + + updateNodeStatus(k, status === "OK" ? true : false); + if (nodesData[k].hasOwnProperty("node_status_before_offline")) delete nodesData[k].node_status_before_offline; + sendTelemetry({ status: status }, tbname, time); + + //vyreportovanie dimming, current, input power pre liniu pre vsetky nody + //Prud + { + let params = getParams(); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 75;//prud + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = time + 4000; + params.info = 'read current'; + //params.debug = true; + tasks.push(params); + } + + //vykon + { + let params = getParams(); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 76;//výkon + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = time + 4100; + params.info = 'read power'; + //params.debug = true; + + tasks.push(params); + } + //dimming + { + let params = getParams(); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 1;//dimming + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = time + 4200; + params.info = 'read dimming'; + //params.debug = true; + + tasks.push(params); + } + + } + } + + }, sec * 1000); + } + + + function reportOfflineNodeStatus(line) { + + logger.info("Cmd-mngr: ------>reportOffLineNodeStatus for line ", line); + + values = {}; + values["dimming"] = 0;//brightness + values["power"] = 0;//výkon + values["current"] = 0;//prúd + values["status"] = "OFFLINE"; + + const date = Date.now(); + + Object.keys(nodesData).forEach(node => { + + //potrebujem nody k danej linii + if (line == nodesData[node].line || line == undefined) { + + let tbname = nodesData[node].tbname; + let nodeStatus = nodesData[node].status; + + //in case we have reported offline node status, we return (continue with next node) + if (nodeStatus === "OFFLINE") return; + + nodesData[node].node_status_before_offline = nodeStatus; + nodesData[node].status = "OFFLINE"; + nodesData[node].readout = {}; + + sendTelemetry({ ...values }, tbname, date); + } + }); + + } + + + function turnLine(onOrOff, line, info) { + let obj = { + line: line, + command: onOrOff, + info: info + }; + + //to assure, handleDailyReportFunction do not run before rvo_is_on variable changes. So after every line switch we reset the timer + clearInterval(handleDailyReport); + handleDailyReport = setInterval(dailyReportHandler, DAILY_REPORT_HANDLER_TIME); + + //logger.debug("linia", line, obj); + instance.send(SEND_TO.dido_controller, obj); + } + + + 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"; + 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]) { + //CRC_ERROR + message = "NOK"; + error = "CRC_ERROR c1"; + instance.send(SEND_TO.debug, "CRC_ERROR c1"); + } + + 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") { + instance.send(SEND_TO.debug, bytes); + instance.send(SEND_TO.debug, "RESPONSE " + type + " - " + bytes[4]); + + //logger.debug(SEND_TO.debug, "RESPONSE " + type + " - " + bytes[4], bytes); + + error = "type is: " + type; + + message = "NOK"; + } + + return { message, type, error }; + } + + + //BUILD TASKS// + function buildTasks(params) { + + //return; + console.log("buidTAaasks start ****************", params); + monitor.info("buildTasks - params", params); + + let processLine; //defined line + let init = false; + let processLineProfiles = true; + let processBroadcast = true; + let processNodes = true; + + if (params == undefined) { + init = true; + tasks = []; + logger.debug("-->buildTasks clear tasks"); + } + else { + processLineProfiles = params.processLineProfiles; + processBroadcast = false; + processNodes = false; + + processLine = params.line; + } + + let now = new Date(); + + //process line profiles + if (processLineProfiles) { + + let keys = Object.keys(relaysData); + + for (let i = 0; i < keys.length; i++) { + + let line = parseInt(keys[i]); + let profilestr = relaysData[line].profile; + + if (processLine != undefined) { + if (processLine != line) continue; + } + + try { + + /** + * we process line profiles: timepoints, astro clock, lux_sensor, offsets ... + */ + if (profilestr === "") throw ("Profile is not defined"); + let profile = JSON.parse(profilestr); + 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; + + // add name to regular profile timepoint and delete unused end_time key: + time_points.forEach(point => { + point.name = "profileTimepoint" + delete point.end_time; + }); + + //monitor.info("buildTasks: time_points", time_points); + + + /** + * 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 astro clock true, we remove all regular profile points + time_points = []; + + //TODO: when astro clock == true, is offset calculated ??? + //let duskAstroClockOffset = profile.dusk_astro_clock_offset; + //let dawnAstroClockOffset = profile.dawn_astro_clock_offset; + //console.log("line astro clock offsets dusk a dawn: ", duskAstroClockOffset, dawnAstroClockOffset); + // maybe add dusk dawn offset to calculateDuskDawn ?? what dusk dawn will be if dawn_lux_sensor == true?? + //let sunCalcResult = calculateDuskDawn(new Date(), line, duskAstroClockOffset, dawnAstroClockOffset); + + 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 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); + + 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); + + 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(':'); + + let ad = new Date(); + ad.setHours(parseInt(ahours), parseInt(aminutes), 0); + + let bd = new Date(); + bd.setHours(parseInt(bhours), parseInt(bminutes), 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++) { + + let start_time = new Date(); + let [hours, minutes] = time_points[t].start_time.split(':'); + start_time.setHours(parseInt(hours), parseInt(minutes), 0); + + //task is in 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(); + params.type = "relay"; + params.line = parseInt(line); + params.value = time_points[t].value; + params.tbname = relaysData[line].tbname; + params.timestamp = start_time.getTime(); + + // 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; + + //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)) { + 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; + + params.debug = true; + + //turn on/off line + tasks.push(params); + monitor.info("TimePoint params: ", params.info, start_time); + } + + monitor.info("-->time_points final", line, time_points); + + //ensure to turn on/off according to calculated currentValue + let params = getParams(); + params.type = "relay"; + params.line = parseInt(line); + params.tbname = relaysData[line].tbname; + params.value = currentValue; + params.timestamp = i; + params.debug = true; + + //logger.debug(now.toLocaleString("sk-SK")); + 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; + + tasks.push(params); + + } catch (error) { + if (profilestr !== "") { + //errLogger.error(profilestr, error); + console.log(`Cmd_mngr: Unable to process line profile ${line}. Error: `, error); + errorHandler.sendMessageToService(profilestr + "-" + error, 0, "js_error"); + } else { + turnLine("off", line, "No line profile. Switching it off on startup"); + } + } + + } + //logger.debug("tasks:"); + //logger.debug(tasks); + } + + + //NOTE: PROCESS DEFAULT BROADCASTS - Time of dusk, Time of dawn, Actual Time + if (processBroadcast) { + + let d = new Date(); + let time = d.getTime(); + //let sunCalcResult = calculateDuskDawn(); + + { + let params = getParams(); + + params.address = 0xffffffff;//broadcast + params.byte1 = sunCalcResult["dusk_hours"]; + params.byte2 = sunCalcResult["dusk_minutes"]; + params.recipient = 2;//2 broadcast, + params.register = 6;//Time of dusk + params.rw = 1;//write + params.type = "node-regular-write"; + params.timestamp = time + 60000; + params.addMinutesToTimestamp = 60 * 3; //kazde 3 hodiny zisti novy dusk + params.info = "Broadcast-duskTime"; + + tasks.push(params); + } + + { + let params = getParams(); + + params.address = 0xffffffff;//broadcast + params.byte1 = sunCalcResult["dawn_hours"]; + params.byte2 = sunCalcResult["dawn_minutes"]; + params.recipient = 2; //2 broadcast + params.register = 7;//Time of dawn + params.rw = 1;//write + params.type = "node-regular-write"; + params.timestamp = time + 60001; + params.addMinutesToTimestamp = 60 * 3; //kazde 3 hodiny zisti novy dawn + params.info = "Broadcast-dawnTime"; + + tasks.push(params); + } + + { + let params = getParams(); + + params.address = 0xffffffff;//broadcast + params.byte1 = d.getHours(); + params.byte2 = d.getMinutes(); + params.recipient = 2; //2 broadcast + params.register = 87;//Actual time + params.rw = 1;//write + params.type = "node-regular-write"; + params.timestamp = time + 60002; + params.addMinutesToTimestamp = 5; + params.info = "run broadcast: Actual time"; + + tasks.push(params); + } + + } + + //process nodes & tasks - read node's data + if (processNodes) { + + let time = Date.now(); + + for (let k in nodesData) { + let address = parseInt(k); + let tbname = nodesData[k].tbname; + let register = 0; + + for (let i = 0; i < listOfCommands.length; i++) { + + register = listOfCommands[i]; + let addMinutesToTimestamp = priorities[register]; + + let params = getParams(); + + params.address = address; + params.recipient = 1; + params.register = register; + params.type = register == 1 ? "node-dimming-read" : "node-regular-read"; + params.tbname = tbname; + params.timestamp = time + 5000 + i * 500 + addMinutesToTimestamp * 1000; //to make slight time difference + params.addMinutesToTimestamp = addMinutesToTimestamp; + params.info = "Node regular read command"; + + tasks.push(params); + } + + } + } + + + //niektore ulohy sa vygeneruju iba 1x pri starte!!! + if (!init) return; + + + //Master node FW version - modifies SETTINGS.masterNodeIsResponding + { + let params = getParams(); + params.type = "cmd-master"; + params.register = 4; + params.address = 0; + params.timestamp = 0; + params.addMinutesToTimestamp = 5; + params.tbname = SETTINGS.rvoTbName; + params.info = "Master node FW verzia"; + //params.debug = true; + + tasks.push(params); + } + + //kazdu hodinu skontrolovat nastavenie profilov + { + let params = getParams(); + params.type = "process_profiles"; + params.timestamp = Date.now() + 60001; + params.addMinutesToTimestamp = 60;//60 = every hour + params.info = "detekcia nespracovaných profilov linie a nodov"; + //params.debug = true; + + tasks.push(params); + } + + monitor.info("tasks created:", tasks.length); + } + + + /** + * We process line profile, where "astro_clock": true + * example profile: + * + "dawn_lux_sensor": true, + "dusk_lux_sensor": true, + "dawn_lux_sensor_value": 5, + "dusk_lux_sensor_value": 5, + "dawn_astro_clock_offset": 0, + "dusk_astro_clock_offset": 10, + "dawn_lux_sensor_time_window": 30, + "dusk_lux_sensor_time_window": 30, + "dawn_astro_clock_time_window": 60, + "dusk_astro_clock_time_window": 60 + + * if dawn: if currentTimestamp is in timewindow "dawnTime + and - dawn_lux_sensor_time_window" and lux value >= lux_sensor_value, we switch off the line. + * if dusk: we do oposite + * + * dawn: usvit - lux je nad hranicou - vypnem + * dusk: sumrak - lux je pod hranicou - zapnem + */ + 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++) { + + let line = keys[i]; //line is turned off by default + let profilestr = relaysData[line].profile; + const contactor = relaysData[line].contactor; + + try { + + let profile = JSON.parse(profilestr); + if (Object.keys(profile).length === 0) throw ("turnOnOffLinesAccordingToLuxSensor - profile is not defined"); + + 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 (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"); + } + } + } + + //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 (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"); + } + } + } + + } + + } catch (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) { + //MASTER + if (node == 0) return; + + let nodeObj = nodesData[node]; + if (nodeObj == undefined) return; + + let nodeCurrentStatus = nodeObj.status; + const now = Date.now(); + + let data = null; + + if (nodeCurrentStatus === "OFFLINE") { + data = { status: newStatus }; + nodeDbStatusModify(node, data); + return; + } + else 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; + } + + } + + + 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 }; + } + }); + }); + } + + + function processDailyReport() { + + const now = Date.now(); + + for (const [key, value] of Object.entries(dailyReport)) { + + if (["name", "time", "dusk_and_dawn"].includes(key)) continue; + + let poleNumber = nodesData[key]["pole_number"]; + let line = dailyReport[key].line; + let nodeType = nodesData[key]["node_type"]; + let fullNodeName = key // key == nodeNumber + + if (poleNumber && nodeType) { + fullNodeName = SETTINGS.rvo_number + "/" + poleNumber + "_" + line + "L_" + key + "_" + nodeType; + } else { + fullNodeName = key; + } + + if (rvo_is_on) { + + if (value.initialTs) { + if (value.initialTs + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["night_no_data"], fullNodeName); + console.log('report nedostava ziadne data uz hodinu', fullNodeName); + value.initialTs = now; + } + } + if (value.dimmingIsZeroTime) { + if (value.dimmingIsZeroTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["night_dimming=0"], fullNodeName); + console.log("report node dimming je 0 ale ma svietit", fullNodeName); + value.dimmingIsZeroTime = now; + } + } + if (value.powerIsZeroTime) { + if (value.powerIsZeroTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["night_power=0"], fullNodeName); + console.log("report node power je 0 ale ma svietit", fullNodeName); + value.powerIsZeroTime = now; + } + } + + } else { + + let contactorStatus = relaysData[line].contactor; + if (contactorStatus === 1) { + + if (value.initialTs) { + if (value.initialTs + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["day_24/7_no_data"], fullNodeName); + console.log('node je na 24/7 ale nedostava ziadne data uz hodinu', fullNodeName); + value.initialTs = now; + } + } + if (value.dimmingIsOnButShouldBeOffTime) { + if (value.dimmingIsOnButShouldBeOffTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["day_24/7_dimming>0"], fullNodeName); + console.log("report dimming je > 0 ale nema svietit", fullNodeName); + value.dimmingIsOnButShouldBeOffTime = now; + } + } + if (value.powerIsOnButShouldBeOffTime) { + if (value.powerIsOnButShouldBeOffTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["day_24/7_power>0"], fullNodeName); + console.log("report power je > 0 ale nema svietit", fullNodeName); + value.powerIsOnButShouldBeOffTime = now; + } + } + + } + + } + + } + + let report = {}; + report["name"] = SETTINGS.rvo_name; + report["time"] = new Date(); + report["report"] = reportToSend; + + writeToFile(F.path.root("report_data.log"), report, true); + instance.send(SEND_TO.dailyReport, report); + } + + + function dailyReportHandler() { + + if (!SETTINGS.daily_report) return; + + // after dawn we empty reportToSend and start to get data for a new day + const date = new Date(); + const hour = date.getHours(); + const minute = date.getMinutes(); + + console.log("now: ", hour, minute, "suncalc: ", sunCalcResult.dawn_hours, sunCalcResult.dawn_minutes); + + if (hour === sunCalcResult.dawn_hours) { + + //NOTE: ak je este pred usvitom, spracujeme report a posleme na cloud, ak uz je po usvite, resetujeme report plnime data noveho dna + if (minute >= sunCalcResult.dawn_minutes - 2) { + emptyReportToSend(); + emptyDailyReport(); + console.log("Podmienka 1 v dailyReport handler"); + } else { + processDailyReport(); + emptyReportToSend(); + emptyDailyReport(); + console.log("Podmienka 2 v dailyReport handler"); + } + + initialReportStatus = true; + + // ak sa funkcia spusti o hodinu alebo 2 neskor, ako je usvit (moze sa to stat, kedze kazde zapnutie/vypnutie linii odznova spusti casovac. + } else if (hour === sunCalcResult.dawn_hours + 1 || hour === sunCalcResult.dawn_hours + 2) { + if (!initialReportStatus) { + emptyReportToSend(); + emptyDailyReport(); + initialReportStatus = true; + console.log("Podmienka 3 v dailyReport handler"); + } else { + processDailyReport(); + initialReportStatus = true; + console.log("Podmienka 4 v dailyReport handler"); + } + } else { + processDailyReport(); + initialReportStatus = false; + console.log("Podmienka 5 v dailyReport handler"); + } + + console.log("initialReportStatus: ", initialReportStatus); + + } + + function emptyReportToSend() { + emptyJsObject(reportToSend); + reportToSend["contactor"] = { off: [], on: [] }; + reportToSend["night_no_data"] = []; + reportToSend["night_dimming=0"] = []; + reportToSend["night_power=0"] = []; + reportToSend["day_24/7_no_data"] = []; + reportToSend["day_24/7_dimming>0"] = []; + reportToSend["day_24/7_power>0"] = []; + console.log(`resetuje sa reportToSend`); + } + + + //NOTE: ked je initialTs stale rovnaky a zistime ze linie su vypnute (relaysData.line.contactor) - zistim, ci je node na tej linii. Vieme, ze ak je linia vypnuta je to v poriadku lebo nie je na 24/7 linii + //ak je na 24/7 linii, reportujeme, ze neprijima data + function emptyDailyReport() { + const ts = Date.now(); + emptyJsObject(dailyReport); + + //NOTE: do dailyReport dame vsetky nody a pravidelne kontrolujeme ci maju data + //ked nastane sumrak/usvit a svetla maju zacat/prestat svietit, dailyReport spravime nanovo: + for (const [key, value] of Object.entries(nodesData)) { + dailyReport[value.node] = { line: value.line, initialTs: ts }; + } + + console.log("dailyReport: ", dailyReport); + } + + + async function runTasks() { + + clearInterval(interval); + + let currentTimestamp = Date.now(); + + //sort tasks based on timestamp + 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) { + instance.send(SEND_TO.debug, "no tasks created"); + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + if (!rsPort.isOpen) { + instance.send(SEND_TO.debug, "!rsPort.isOpen"); + //await rsPort.open(); + //console.log("Cmd-mngr: !rsPort.isOpen"); + } + + let currentTask = tasks[0]; + + if (currentTask.debug) { + //logger.debug("--->task to process", currentTask); + } + + if (currentTask.timestamp <= currentTimestamp) { + let params = { ...tasks[0] }; + + //allow terminal commands + if (SETTINGS.maintenance_mode && params.type !== "cmd-terminal") { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + let type = params.type; + let tbname = params.tbname; + let node = params.address; + let register = params.register; + let line = null; + let itIsNodeCommand; + + if (nodesData[node] !== undefined) { + line = nodesData[node].line; + itIsNodeCommand = true; + } + + if (params.line !== undefined) line = params.line; + + if (params.addMinutesToTimestamp > 0 || params.timePointName) { + tasks[0].timestamp = currentTimestamp + tasks[0].addMinutesToTimestamp * 60000; + } else { + tasks.shift(); + } + + //kontrola nespracovanych profilov nodov + //TODO: co ked niektore nody neprijimaju profily? kazdu hodinu zahltuju "tasks" array + if (type == "process_profiles") { + //na vsetky zapnutych liniach sa spracuju nespracovane profily nodov + loadRelaysData(); + interval = setInterval(runTasks, SHORT_INTERVAL); + return; + } + + //relay + if (type == "relay") { + + const timePointName = params.timePointName; + const value = params.value; + + let date = new Date(); + date.setDate(date.getDate() + 1);//next day + + let sunCalcResult; + if (timePointName) sunCalcResult = calculateDuskDawn(date, params.line); + + + if (timePointName == "dawn") { + tasks[0].timestamp = sunCalcResult.dawn_time; + } + else if (timePointName == "dusk") { + tasks[0].timestamp = sunCalcResult.dusk_time; + } + else if (timePointName == "luxOn") { + tasks[0].timestamp = sunCalcResult.dusk_time + params.dusk_lux_sensor_time_window * 60000; + } + else if (timePointName == "luxOff") { + tasks[0].timestamp = sunCalcResult.dawn_time + params.dawn_lux_sensor_time_window * 60000; + } + else if (timePointName == "profileTimepoint") { + tasks[0].timestamp = currentTimestamp + tasks[0].addMinutesToTimestamp * 60000; + } + + let info = "aplikovany bod profilu"; + let onOrOff = ""; + value == 1 ? onOrOff = "on" : onOrOff = "off"; + + turnLine(onOrOff, params.line, info); + + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + if (!SETTINGS.masterNodeIsResponding) { + //ak neodpoveda, nebudeme vykonavat ziadne commands, okrem cmd-terminal cmd-master + errorHandler.sendMessageToService("Master node is not responding"); + + let stop = true; + + if (type === "cmd-terminal" || type === "cmd-master") stop = false; + if (stop) { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + } + + let contactorStatus = 1; + if (relaysData[line] != undefined) contactorStatus = relaysData[line].contactor; + + if (line === 0 || contactorStatus === 0 || FLOW.deviceStatus.state_of_breaker[line] === "Off") { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + // TODO: -> status offline for rvo if rotary_switch_state is OFF, this is source of errors + // check if rotary_switch_state == "Off" + // state_of_braker: disconnected = true? + + if (!rsPort.isOpen) { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + //RE-CALCULATE VALUES + //set actual time for broadcast + if (register == 87 && params.recipient === 2) { + var d = new Date(); + params.byte1 = d.getHours();//h + params.byte2 = d.getMinutes();//m + } + + //SET DUSK/DAWN FOR BROADCAST + //Time of dusk + if (register == 6 && params.recipient === 2) { + + if (type != "cmd-terminal") { + params.byte1 = sunCalcResult["dusk_hours"];//h + params.byte2 = sunCalcResult["dusk_minutes"];//m + } + } + + //Time of dawn + if (register == 7 && params.recipient === 2) { + if (type != "cmd-terminal") { + params.byte1 = sunCalcResult["dawn_hours"];//h + params.byte2 = sunCalcResult["dawn_minutes"];//m + } + } + //----------------------- + + instance.send(SEND_TO.debug, "address: " + node + " register:" + register + "type: " + type); + + var startTime, endTime; + startTime = new Date(); + + let saveToTb = true; + if (!tbname) saveToTb = false; + + let resp = com_generic(node, params.recipient, params.rw, register, params.name, params.byte1, params.byte2, params.byte3, params.byte4); + let readBytes = 11; + let timeout = 4000; + + + // await keyword is important, otherwise incorrect data is returned! + await writeData(rsPort, resp, readBytes, timeout).then(function(data) { + + //sometimes happens, that status of node changes to OK, NOK even if line was turned off and should be status OFFLINE. To prevent this, we return if line contactor is 0: + if (itIsNodeCommand && line && relaysData[line].contactor !== 1) return; + + 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); + + //ak sa odpoved zacina 0 - je to v poriadku, inak je NOK + let message = result.message; // OK, NOK + let message_type = result.type; + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + console.log("detected response:", result); + logger.debug("Cmd-mngr: writeData done " + message_type + " duration: " + timeDiff + " type: " + params.debug, params, result); + } + } + + let values = {}; + + //CMD FINISHED + if (message == "OK") { + + updateNodeStatus(node, true); + + //write + if (type == "set_node_profile") { + let result = cmdCounterResolve(node); + if (result == 0) { + dbNodes.modify({ processed: true }).where("node", node).make(function(builder) { + builder.callback(function(err, response) { + + sendNotification("Cmd-mngr: process cmd", SETTINGS.rvoTbName, "dimming_profile_was_successfully_received_by_node", { node: node }, "", SEND_TO.tb, instance); + + logger.debug("--> profil úspešne odoslaný na node č. " + node); + nodesData[node].processed = true; + nodeProfileSendFail.delete(node); + }); + }); + } + } + + //parse read response + if (params.rw == 0) { + values = processResponse(register, dataBytes); //read + } + + if (itIsNodeCommand) { + values.comm_status = "OK"; + values.status = "OK"; + nodesData[node].readout = { ...nodesData[node].readout, ...values }; + + + if (SETTINGS.daily_report) { + //TODO: co ak nedostavame odpovede z nodu ? Musime vyreportovat!! + //v dailyReport teda musi byt kompletny zoznam nodov a neustale kontrolovat, ci maju data, ak nie report node - neodpoveda + if (register === 1) { + + let now = Date.now(); + + if (rvo_is_on === true) { + + if ("dimmingIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].dimmingIsOnButShouldBeOffTime; + + if (values.dimming > 0) { + if ("dimmingIsZeroTime" in dailyReport[node]) delete dailyReport[node].dimmingIsZeroTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if (!("dimmingIsZeroTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], dimmingIsZeroTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } else { + + if ("dimmingIsZeroTime" in dailyReport[node]) delete dailyReport[node].dimmingIsZeroTime; + + if (values.dimming > 0) { + if (!("dimmingIsOnButShouldBeOffTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], dimmingIsOnButShouldBeOffTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if ("dimmingIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].dimmingIsOnButShouldBeOffTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } + } + + if (register === 76) { + + let now = Date.now(); + + if (rvo_is_on === true) { + + if ("powerIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].powerIsOnButShouldBeOffTime; + + if (values.power > 1) { + if ("powerIsZeroTime" in dailyReport[node]) delete dailyReport[node].powerIsZeroTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if (!("powerIsZeroTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], powerIsZeroTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } else { + + if ("powerIsZeroTime" in dailyReport[node]) delete dailyReport[node].powerIsZeroTime; + + if (values.power > 1) { + if (!("powerIsOnButShouldBeOffTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], powerIsOnButShouldBeOffTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if ("powerIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].powerIsOnButShouldBeOffTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } + } + } + + } + + //master node + if (node == 0) { + sendNotification("Cmd-mngr: 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; + } + + if (params.debug) { + //logger.debug("saveToTb", saveToTb, tbname, values); + } + + if (saveToTb && type != "node-regular-read") { + sendTelemetry(values, tbname); + } + else { + if (type == "cmd-terminal") { + terminalCommandResponse(params, "SUCCESS", data); + } + } + + } + else { + terminalCommandResponse(params, "ERROR", data); + handleNokResponseOnRsPort("handleNOK else block", params, itIsNodeCommand, saveToTb); + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + //logger.debug("writeData err: ", error, result, params); + logger.debug("writeData err: ", tbname, node, register, values); + } + } + + //logger.debug(error, result, params); + } + }).catch(function(reason) { + + //console.log("writeData catch exception", reason); + instance.send(SEND_TO.debug, reason); + + terminalCommandResponse(params, "FAILURE", null, reason); + handleNokResponseOnRsPort("handleNOK catch block", params, itIsNodeCommand, saveToTb); + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + logger.debug("-->WRITE FAILED: " + reason, params.debug, params); + } + } + + }); + + } + 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); + } + + + // if node does not respond to request, we repeat request 3 times: + function repeatCommand(params) { + params.repeatCounter++; + if (params.repeatCounter < 4) { + params.timestamp = 0; + params.addMinutesToTimestamp = 0; + tasks.push(params); + } + } + + function handleNokResponseOnRsPort(message, params, itIsNodeCommand, saveToTb) { + + let node = params.address; + let register = params.register; + let type = params.type; + let tbName = params.tbname; + if (!tbName) return; + + let values = {}; + + let updateStatus = updateNodeStatus(node, false); + + if (itIsNodeCommand) { + values.comm_status = "NOK"; + nodesData[node].readout.comm_status = "NOK"; + repeatCommand(params); + } + + if (updateStatus) { + values.status = "NOK"; + nodesData[node].readout.status = "NOK"; + } + + if (type === "node-regular-read") return; + + //master node + if (node == 0) { + sendNotification("Cmd-mngr: 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; + + if (register == 4) values["master_node_version"] = "NOK"; + } + + if (type == "set_node_profile") { + delete cmdCounter[node]; + logger.debug("profil nebol úspešne odoslaný na node č. ", params); + + if (!nodeProfileSendFail.has(node)) { + sendNotification("Cmd-mngr: process cmd", tbName, "configuration_of_dimming_profile_to_node_failed", { node: node }, "", SEND_TO.tb, instance); + nodeProfileSendFail.add(node); + } + } + + // console.log("------",node, register, type, itIsNodeCommand, updateStatus, saveToTb, values); + if (saveToTb) { + sendTelemetry(values, tbName); + } + + } + + + function sendNodesData() { + Object.keys(nodesData).forEach(node => { + if (nodesData[node]["status"] !== "OFFLINE") { + sendTelemetry(nodesData[node].readout, nodesData[node].tbname); + nodesData[node].readout = {}; + } + }) + } + + + /** + * 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; + } + + 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); + + //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 === "OFFLINE") { + nodeObj.node_status_before_offline === true ? number_of_ok_luminaires++ : number_of_nok_luminaires++; + } + else if (nodeObj.status == true) 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 - ts % 60000 //round to full minute + }; + + sendTelemetry(values, SETTINGS.rvoTbName, ts); + } + + + function setSunCalcResult() { + //if next day, we get new dusk and dawn. To make sure, in local timezone 2:00 means 00:00 in utc (it means next day) + if (new Date().getHours() === 2) { + sunCalcResult = calculateDuskDawn(); + console.log("Novy suncalc: ", sunCalcResult); + } + } + + + function setRvoPeriod() { + + if (!SETTINGS.daily_report) return; + + const ts = Date.now(); + + previous_rvo_is_on_value = rvo_is_on; + + if (ts < sunCalcResult.dawn_time - 1_800_000) { // nodes should be on (00:00 -> 06:00 ( - pol hodina, lebo rvo vypina skor) + rvo_is_on = true; + } else if (sunCalcResult.dawn_time - 1_800_000 < ts && ts < sunCalcResult.dusk_time + 1_800_000) { // nodes should be off 06:00 -> 21:00 + rvo_is_on = false; + } else if (sunCalcResult.dusk_time + 1_800_000 < ts) { // nodes should be on 21:00 -> 00:00 + rvo_is_on = true; + } + + if (previous_rvo_is_on_value !== rvo_is_on) { + emptyDailyReport(); + console.log("rvo_is: ", rvo_is_on, previous_rvo_is_on_value); + } + } + + + function handleRsPort() { + + if (rsPort) { + rsPort.removeAllListeners(); + rsPort = null; + } + + //! 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-mngr: rsPort opened success"); + + 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); + + }).catch(function(reason) { + instance.send(SEND_TO.debug, "Cmd-mngr: RPC runSyncExec - promise rejected:" + reason); + }); + }); + + rsPort.on('error', function(err) { + errorHandler.sendMessageToService([exports.title, "unable to open port", SETTINGS.serial_port, err.message], 0); + monitor.info("Cmd-mngr: Error on rsPort", err.message); + }); + + rsPort.on("close", () => { + monitor.info("Cmd-mngr: rsPort closed, reconnecting..."); + setTimeout(handleRsPort, 1000); + }); + + rsPort.open(); + } + + + instance.on("close", () => { + clearInterval(interval); + clearInterval(customTasksInterval); + clearInterval(setCorrectTime); + clearInterval(sendNodeReadout); + clearInterval(accelerometerInterval); + rsPort.close(); + }); + + instance.on("0", _ => { + main(); + }) + + + instance.on("2", _ => { + console.log("dailyReport, reportToSend, rvo_is_on", dailyReport, reportToSend, rvo_is_on, previous_rvo_is_on_value); + }) + + instance.on("1", 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(); + return; + } + else if (flowdata.data == "close") { + rsPort.close(); + return; + } + else if (flowdata.data == "clean") { + tasks = []; + return; + } + else if (flowdata.data == "buildtasks") { + //build & run + return; + } + else if (flowdata.data == "run") { + //durations = []; + + if (tasks.length == 0) { + + buildTasks(); + + if (rsPort.isOpen) { + interval = setInterval(runTasks, 100); + } + else { + instance.send(SEND_TO.debug, "port is not opened!!!"); + } + } + } + else { + //terminal data - object + //logger.debug("flowdata", flowdata.data); + + if (typeof flowdata.data === 'object') { + //logger.debug("dido", flowdata.data); + if (flowdata.data.hasOwnProperty("sender")) { + //data from dido_controller + if (flowdata.data.sender == "dido_controller") { + + if (flowdata.data.hasOwnProperty("cmd")) { + let cmd = flowdata.data.cmd; + + if (cmd == "buildTasks") { + clearInterval(interval); + + logger.debug("-->Cmd-mngr: BUILD TASKS"); + buildTasks(); + + //logger.debug("tasks:"); + //logger.debug(tasks); + + logger.debug("-->Cmd-mngr: RUN TASKS"); + interval = setInterval(runTasks, 5000); + } + else if (cmd == "reload_relays") { + loadRelaysData(flowdata.data.line); + + if (flowdata.data.dataChanged) { + if (!flowdata.data.value) { + reportOfflineNodeStatus(flowdata.data.line); + } + else { + reportOnlineNodeStatus(flowdata.data.line); + } + } + + } + else if (cmd == "rotary_switch_state") { + let value = flowdata.data.value; + + //state was changed + if (rotary_switch_state != value) { + if (value == "Off") { + //vyreportovat vsetky svietdla + reportOfflineNodeStatus(); + } + + rotary_switch_state = value; + } + } + 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) { + + // we send lux_sensor value to all nodes: + let params = getParams(PRIORITY_TYPES.node_broadcast); + + params.recipient = 2;//2 broadcast, address = 0 + params.address = 0xffffffff;//Broadcast + + let ba = longToByteArray(lux_sensor); + + params.byte3 = ba[1];//msb + params.byte4 = ba[0]; + params.timestamp = PRIORITY_TYPES.node_broadcast; + params.info = "run broadcast: Actual Lux level from cabinet"; + params.register = 95;//Actual Lux level from cabinet + params.rw = 1;//write + + tasks.push(params); + + //process profiles + turnOnOffLinesAccordingToLuxSensor(lux_sensor); + } + } + else if (cmd == "state_of_breaker") { + //istic linie + + breakerCounter--; + + let value = flowdata.data.value; + let line = parseInt(flowdata.data.line); + + let dataChanged = false; + if (state_of_breaker[line] != value) dataChanged = true; + + state_of_breaker[line] = value; + + let status = "OK"; + if (value == "Off") status = "NOK"; + + if (dataChanged) { + + if (relaysData.hasOwnProperty(line)) { + let tbname = relaysData[line].tbname; + + if (value == "Off") { + sendNotification("Cmd-mngr: onData", tbname, "circuit_breaker_was_turned_off_line", { line: line }, "", SEND_TO.tb, instance, "circuit_breaker"); + if (breakerCounter < 0) reportToSend["contactor"]["off"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + else { + sendNotification("Cmd-mngr: onData", tbname, "circuit_breaker_was_turned_on_line", { line: line }, "", SEND_TO.tb, instance, "circuit_breaker"); + if (breakerCounter < 0) reportToSend["contactor"]["on"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + + //report status liniu + sendTelemetry({ status: status }, tbname) + + //current value + if (value == "Off") reportOfflineNodeStatus(line); //vyreportovat vsetky svietidla na linii + } + + } + } + else { + logger.debug("undefined cmd", cmd); + } + } + } + + return; + } + + //data from worksys + if (flowdata.data.hasOwnProperty("topic")) { + + let data = getNested(flowdata.data, "content", "data"); + + //if we get temperature in senica from senica-prod01 + let temperature = getNested(flowdata.data, "content", "senica_temperature"); + + if (temperature !== undefined) { + temperatureInSenica = temperature; + return; + } + + if (data === undefined) { + console.log("Invalid rpc command came from platform"); + return; + } + + let command = data.params.command; + let method = data.method; + let profile = data.params.payload; + if (profile == undefined) profile = ""; + let entity = data.params.entities[0]; + let entity_type = entity.entity_type; + let tbname = entity.tb_name; + + instance.send(SEND_TO.debug, flowdata.data); + 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") { + + //let command = data.params.command; + let value = data.params.payload.value; + + if (command == "dimming") { + + let nodeWasFound = false; + let keys = Object.keys(nodesData); + + //logger.debug("-----", keys); + + 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); + + value = parseInt(value); + if (value > 0) value = value + 128; + + params.type = "node-onetime-write"; + params.tbname = tbname; + params.address = node; + params.register = 1; + params.recipient = 1; + params.byte4 = value; + params.rw = 1; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'set dimming from platform'; + //params.debug = true; + + //debug(params); + logger.debug("dimming", params); + + tasks.push(params); + + 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); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 1; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read dimming (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + //pridame aj vyreportovanie - vykon + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 76; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read Input Power (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + //pridame aj vyreportovanie - prud svietidla + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 75; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read Input Current (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + //pridame aj vyreportovanie - power faktor - ucinnik + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 77; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read power factor (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + }, 4000); + + nodeWasFound = true; + break; + } + } + + if (!nodeWasFound) { + logger.debug("set dimming from platform", "unable to find tbname", tbname); + } + } + else { + instance.send(SEND_TO.debug, "undefined command " + command); + logger.debug("undefined command", command); + } + + return; + } + 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++) { + let node = keys[i]; + if (tbname == nodesData[node].tbname) { + + 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"); + + //profil úspešne prijatý pre node č. xx + sendNotification("Cmd-mngr", tbname, "dimming_profile_was_processed_for_node", { node: node }, profile, SEND_TO.tb, instance); + + nodesData[node].processed = false; + nodesData[node].profile = profile; + + processNodeProfile(node); + }); + }); + } + } + } + else { + + instance.send(SEND_TO.debug, "unknown method " + method); + logger.debug("unknown method", method); + + return; + } + } + + //nastav profil linie z platformy + 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") { + + 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++) { + let line = keys[i]; + if (tbname == relaysData[line].tbname) { + //zmazeme tasky + 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) { + + //update profile + logger.debug("worksys - update relay profile done:", profile); + instance.send(SEND_TO.debug, "worksys - update relay profile done"); + + relaysData[line].profile = profile; + + loadRelaysData(line) + logger.debug("loadRelaysData DONE for line", line); + + buildTasks({ processLineProfiles: true, line: line }); + + sendNotification("Cmd-mngr: set profile from worksys", tbname, "switching_profile_was_processed_for_line", { line: line }, profile, SEND_TO.tb, instance); + }); + }); + break; + } + } + } + else if (method == "set_command") { + let value = data.params.payload.value; + + 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; + + 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"); + if (line != 0) reportToSend["contactor"]["off"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + else { + turnLine("on", line, "command received from platform"); + if (line != 0) reportToSend["contactor"]["on"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + } + } + else { + instance.send(SEND_TO.debug, "undefined method " + method); + logger.debug("undefined method", method); + } + + return; + } + else { + instance.send(SEND_TO.debug, "UNKNOW entity_type " + entity_type); + logger.debug("UNKNOW entity_type", entity_type); + } + return; + } + + //terminal + if (!rsPort.isOpen) await rsPort.open(); + + let params = flowdata.data.body; + if (params == undefined) { + //logger.debug("Cmd-mngr: flowdata.data.body is undefined"); + return; + } + + params.priority = PRIORITY_TYPES.terminal; + params.type = "cmd-terminal"; + params.tbname = ""; + params.timestamp = PRIORITY_TYPES.terminal; + params.addMinutesToTimestamp = 0;// do not repeat task!!! + params.debug = true; + + let timestamp = Date.now(); + params.refFlowdataKey = timestamp; + //params.refFlowdata = flowdata; + //refFlowdata = flowdata; + + //console.log("flowdata", flowdata); + + cleanUpRefFlowdataObj(); + + refFlowdataObj[timestamp] = flowdata; + + //fix + //params.address = params.adress; + logger.debug("received from terminal", params); + logger.debug("date/time:", new Date()); + logger.debug("tasks length:", tasks.length); + + //tasks = []; + + //add to tasks + tasks.push(params); + + } + } + }) + + + //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) + } + + + /** + * 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; + + RESTBuilder.make(function(builder) { + + if (!builder) return; + + builder.method('GET'); + builder.url('http://192.168.252.2:8004/gettime?projects_id=1'); + + builder.callback(function(err, response, output) { + + 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); + } + + }); + } + + } 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); + + } else { + //console.log("Read-only", stdout); + + 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]: [ + { + "ts": date, + "values": values + } + ] + } + + tbHandler.sendToTb(dataToTb, instance); + } + + + function calculateDuskDawn(date, line, duskOffset = 0, dawnOffset = 0) { + + if (date === undefined) date = new Date(); + + 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); + } + + //if(profile.dawn_lux_sensor == false) + { + if (profile.hasOwnProperty("dawn_astro_clock_offset")) dawn_astro_clock_offset = parseInt(profile.dawn_astro_clock_offset); + } + + } + + } catch (error) { + if (profilestr != "") { + logger.debug(profilestr); + logger.debug(error); + } + } + + 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; + } + + //Dimming, CCT + else if (register == 1) { + let brightness = 0; + let dimming = byte0; + if (dimming > 128) { + //dimming = -128; + brightness = dimming - 128; + } + + //cct + //Ak Byte3 == 1: CCT = (Byte2*256)+Byte1 + let cct; + if (byte3 == 1) cct = byte2 * 256 + byte1; + else cct = bytesToInt(bytes.slice(0, 3)); + + //cct podla auditu + + values["dimming"] = brightness; + return values; + } + + // + else if (register == 4) { + values["master_node_version"] = bytes[1] + "." + bytes[2]; + //logger.debug("FW Version", register, bytes); + } + + //Napätie + else if (register == 74) { + let voltage = (bytesToInt(bytes) * 0.1).toFixed(1); + values["voltage"] = Number(voltage); + } + + //Prúd + else if (register == 75) { + let current = bytesToInt(bytes); + values["current"] = current; + } + + //výkon + else if (register == 76) { + let power = (bytesToInt(bytes) * 0.1).toFixed(2); + values["power"] = Number(power); + } + + //účinník + else if (register == 77) { + let power_factor = Math.cos(bytesToInt(bytes) * 0.1 * (Math.PI / 180)).toFixed(2); + values["power_factor"] = Number(power_factor); + } + + //frekvencia + else if (register == 78) { + let frequency = (bytesToInt(bytes) * 0.1).toFixed(2); + values["frequency"] = Number(frequency); + } + + //energia + else if (register == 79) { + let energy = bytesToInt(bytes); + values["energy"] = energy / 1000; //energia v kWh -> delit 1000 + } + + //doba života + else if (register == 80) { + let lifetime = (bytesToInt(bytes) / 60).toFixed(2); + values["lifetime"] = Number(lifetime); + } + + //nastavenie profilu + else if (register == 8) { + let time_schedule_settings = bytesToInt(bytes); + values["time_schedule_settings"] = time_schedule_settings; + } + + //naklon - nateraz sa z nodu nevycitava! kvoli problemom s accelerometrom a vracanymi hodnotami, posielame temp a x y z vo funkcii accelerometerData() + else if (register == 84) { + values["temperature"] = byte3 >= 128 ? (byte3 - 128) * (-1) : byte3; + values["inclination_x"] = byte2 >= 128 ? (byte2 - 128) * (-1) : byte2; + values["inclination_y"] = byte1 >= 128 ? (byte1 - 128) * (-1) : byte1; + values["inclination_z"] = byte0 >= 128 ? (byte0 - 128) * (-1) : byte0; + } + + //FW verzia nodu + else if (register == 89) { + //formát: "Byte3: Byte2.Byte1 (Byte0)" + values["fw_version"] = byte3 + ":" + byte2 + "." + byte1 + "(" + byte0 + ")"; + } + + else if (register == 87 || register == 6 || register == 7) { + var d = new Date(); + d.setHours(byte3, byte2, 0, 0); + let timestamp = d.getTime(); + + //aktuálny čas + if (register == 87) values["actual_time"] = timestamp; + //čas súmraku + else if (register == 6) values["dusk_time"] = timestamp; + //čas úsvitu + else if (register == 7) values["dawn_time"] = timestamp; + } + + 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; + + } + + + function getObjectByTbValue(object, tbname) { + return object[Object.keys(object).find(key => object[key].tbname === tbname)]; + } + + + function isObject(item) { + return (typeof item === "object" && !Array.isArray(item) && item !== null); + } + + + // we fake data, that should be received from accelerometer, as they are a bit unreliable. (temperature, x,y,z) + function accelerometerData() { + + if (temperatureInSenica === null) return; + + //clone nodesData and relaysData objects + let nodesData_clone = JSON.parse(JSON.stringify(nodesData)); + let relaysData_clone = JSON.parse(JSON.stringify(relaysData)); + + for (const key in relaysData_clone) { + + const lineData = relaysData_clone[key]; + const lineNumber = lineData.line; + const contactor = lineData.contactor; + + if (lineNumber === 0) continue; + + if (contactor === 1) { + + let date = Date.now(); + + Object.keys(nodesData_clone).forEach((node, index) => { + + setTimeout(function() { + + if (nodesData_clone[node].line === lineNumber) { + + // NOTE: if status of luminaire is NOK or OFFLINE, we do not send data; + let status = nodesData_clone[node].status; + if (status === "OFFLINE" || !status) return; + + let x = null; + if (naklony.hasOwnProperty(node)) x = naklony[node].naklon; + if (x === null) x = 0; + + sendTelemetry({ temperature: Math.round(temperatureInSenica + 10 + Math.floor(Math.random() * 3)), inclination_x: x, inclination_y: 0, inclination_z: 0 }, nodesData_clone[node].tbname, date); + } + + }, (index + 1) * 500); + }) + + } + } + } + + +} // end of instance.export + diff --git a/RVO14/flow/code.js b/RVO14/flow/code.js new file mode 100755 index 0000000..63b31bf --- /dev/null +++ b/RVO14/flow/code.js @@ -0,0 +1,90 @@ +exports.id = 'code'; +exports.title = 'Code'; +exports.group = 'Common'; +exports.color = '#656D78'; +exports.input = true; +exports.output = 1; +exports.author = 'Peter Širka'; +exports.icon = 'code'; +exports.version = '1.2.0'; +exports.options = { outputs: 1, code: 'send(0, value);', keepmessage: true }; + +exports.html = `
+
+
+
@(Number of outputs)
+
@(Minimum is 1)
+
+
+
@(Code)
+
@(Keep message instance)
+
+`; + +exports.readme = `# Code + +This component executes custom JavaScript code as it is and it doesn't contain any secure scope. + +\`\`\`javascript +// value {Object} contains received data +// send(outputIndex, newValue) sends a new value +// error(value) sends an error +// instance {Object} a current component instance +// flowdata {Object} a current flowdata +// repository {Object} a current repository of flowdata +// Example: + +// send() can be execute multiple times +send(0, value); +\`\`\``; + +exports.install = function(instance) { + + var fn; + + instance.on('data', function(response) { + if (fn) { + try { + fn(response.data, instance, response, instance.options, response.repository, require); + } catch (e) { + response.data = e; + instance.throw(response); + } + } + }); + + instance.reconfigure = function() { + try { + if (instance.options.code) { + instance.status(''); + var code = 'var send = function(index, value) { if (options.keepmessage) { flowdata.data = value; instance.send2(index, flowdata); } else instance.send2(index, value);}; var error = function(err) { instance.throw(err); }; ' + instance.options.code; + fn = new Function('value', 'instance', 'flowdata', 'options', 'repository', 'require', code); + } else { + instance.status('Not configured', 'red'); + fn = null; + } + } catch (e) { + fn = null; + instance.error('Code: ' + e.message); + } + }; + + instance.on('options', instance.reconfigure); + instance.reconfigure(); +}; \ No newline at end of file diff --git a/RVO14/flow/comment.js b/RVO14/flow/comment.js new file mode 100755 index 0000000..1e0cd13 --- /dev/null +++ b/RVO14/flow/comment.js @@ -0,0 +1,11 @@ +exports.id = 'comment'; +exports.title = 'Comment'; +exports.group = 'Common'; +exports.color = '#704cff'; +exports.author = 'Martin Smola'; +exports.icon = 'comment'; +exports.traffic = false; +exports.version = '1.0.0'; +exports.readme = '# Comment'; + +exports.install = function() {}; diff --git a/RVO14/flow/count.js b/RVO14/flow/count.js new file mode 100755 index 0000000..fa92ee9 --- /dev/null +++ b/RVO14/flow/count.js @@ -0,0 +1,60 @@ +exports.id = 'count'; +exports.title = 'Count'; +exports.version = '1.0.1'; +exports.author = 'John Graves'; +exports.color = '#656D78'; +exports.icon = 'plus-square'; +exports.input = 2; +exports.output = 1; +exports.options = { increment: 1, initialvalue: 1 }; +exports.readme = `# Counter + +Counter Number of times called.`; + +exports.html = `
+
@(Initial Value)
+
@(Increment)
+

Example Video

+
`; + +exports.readme = `# Count + +This component counts the number of messages received. + +__Response:__ + +Integer value based on the initial value and increment settings. + +__Arguments:__ +- Initial Value: What number should be output on the receipt of the first message. +- Increment: What should the increment be for each following message received.`; + +exports.install = function(instance) { + + var count = 0; + var initialCall = true; + + instance.on('data', function(flowdata) { + var index = flowdata.index; + if (index) { + instance.debug('Reset Count.'); + count = instance.options.initialvalue; + initialCall = true; + } else { + // If this is the first time, set the value to 'initial value' + if(initialCall) { + initialCall = false; + count = instance.options.initialvalue; + } else + count = count+instance.options.increment; + instance.status('Count:' + count); + instance.send2(count); + } + }); + + instance.on('options', function() { + count = instance.options.initialvalue; + initialCall = true; + }); + +}; diff --git a/RVO14/flow/db_connector.js b/RVO14/flow/db_connector.js new file mode 100755 index 0000000..65ee94b --- /dev/null +++ b/RVO14/flow/db_connector.js @@ -0,0 +1,286 @@ +exports.id = 'db_connector'; +exports.title = 'DbConnector'; +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.html = `
+
+
+
DbConnector
+
+
+
`; + +exports.readme = `# read/write data to tables`; + +const instanceSendTo = { + debug: 0, + http_response: 1, +} + +const { promisifyBuilder, makeMapFromDbResult } = require('./helper/db_helper.js'); + +function extractWhereParams(params) +{ + let name = params[0]; + let operator = '='; + let value = params[1]; + + if(params.length == 3) + { + operator = params[1]; + value = params[2]; + } + + return {name: name, operator: operator, value: value}; +} + +exports.install = function(instance) { + + let refFlowdata = null;//holds reference to httprequest flowdata + + instance.on("close", () => { + + }) + + + instance.on("data", async function(flowdata) { + + let params = flowdata.data.body; + console.log("DbConnector", params); + + refFlowdata = flowdata; + + if(refFlowdata != undefined) + { + //make http response + let responseObj = {}; + responseObj["type"] = "SUCESS"; + + try{ + + let table = params.table; + let action = params.action; + + + if(params.data != undefined) + { + let className = params.data.className; + + if(className == "SqlQueryBuilder") + { + let type = params.data.type; + + console.log("SqlQueryBuilder---->", params.data); + + if(type == "SELECT") + { + let table = params.data.queryData.tables[0].table; + + const db = TABLE(table); + var builder = db.find(); + + let result = await promisifyBuilder(builder); + + let response = {}; + response["result"] = result; + response["success"] = true; + + responseObj["data"] = response; + + //console.log(responseObj); + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + } + + return; + } + } + + + console.log("db_connector---->", table, action); + + //actions: read, replace, insert, delete, update... + + if(action == "read") + { + const db = TABLE(params.table); + + //where builder.where('age', '<', 15); + //builder.where('id', 3403); + + var builder = db.find(); + + //https://docs.totaljs.com/latest/en.html#api~DatabaseBuilder~builder.where + if(params.hasOwnProperty("where")) + { + //optionalCan contain "=", "<=", "<", ">=", ">". + //Default value: '=' + + //1.["production_line", 1] + //2. ["or", ["production_line", 1], ["production_line", 2], "end"] + + if (Array.isArray(params.where)) { + + let multipleConditions = false; + + if(params.where[0] == "or") multipleConditions = true; + if (Array.isArray(params.where[0])) multipleConditions = true; + + if(multipleConditions) + { + + for(var i = 0; i < params.where.length; i++) + { + const item = params.where[i]; + + if(item === "or") builder.or(); + + if (Array.isArray(item)) + { + const { name, operator, value } = extractWhereParams(item); + builder.where(name, operator, value); + } + + if(item === "end") builder.end(); + + } + + } + else + { + const { name, operator, value } = extractWhereParams(params.where); + builder.where(name, operator, value); + } + + } + + /* + if(params.where.length >=2 ) + { + let name = params.where[0]; + let operator = '='; + let value = params.where[1]; + + if(params.where.length == 3) + { + operator = params.where[1]; + value = params.where[2]; + } + + builder.where(name, operator, value); + } + */ + } + + if(params.hasOwnProperty("between")) + { + builder.between(params.between[0], params.between[1], params.between[2]); + } + + let response = await promisifyBuilder(builder); + responseObj["data"] = response; + + //console.log(responseObj); + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + + return; + } + + if(action == "delete") + { + + } + + + if(action == "update") + { + //! data receiving from terminal (params) + // { + // hostname: 'localhost', + // table: 'settings', + // action: 'update', + // body: { + // rvo_name: 'terrrr', + // lang: 'en', + // temperature_adress: '28.427B45920702', + // latitude: 48.70826502, + // longitude: 17.28455203, + // mqtt_host: '192.168.252.4', + // mqtt_clientid: 'showroom_test_panel_led', + // mqtt_username: 'xmRd6RJxW53WZe4vMFLU', + // mqtt_port: 1883, + // maintanace_mode: false + // } + // } + const tableToModify = TABLE(params.table); + const newValues = params.body; + + tableToModify.modify(newValues).make(function(builder) { + + builder.callback(function(err, response) { + + if(!err) + { + responseObj["data"] = response; + responseObj["tableUpdated"] = true; + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + } + }); + }); + + } + + if(action == "replace") + { + //truncate table + const db = TABLE(params.table); + var builder = db.remove(); + db.clean(); + + //insert data + let data = params.data; + + for(let i = 0; i < data.length; i++) + { + //console.log(data[i]); + db.insert(data[i]); + } + + console.log("insert done"); + + let responseObj = {}; + responseObj["type"] = "SUCESS"; + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + + + } + + + + } catch (error) { + //console.log(error); + responseObj["type"] = "ERROR"; + responseObj["message"] = error; + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + } + } + }) +} + + diff --git a/RVO14/flow/db_init.js b/RVO14/flow/db_init.js new file mode 100755 index 0000000..b399878 --- /dev/null +++ b/RVO14/flow/db_init.js @@ -0,0 +1,113 @@ +exports.id = 'db_init'; +exports.title = 'DB Initialization'; +exports.group = 'Worksys'; +exports.color = '#888600'; +exports.version = '1.0.2'; +exports.icon = 'sign-out'; +exports.output = 2; + +exports.readme = ` + # DB initialization +`; + +const { promisifyBuilder, makeMapFromDbResult } = require('./helper/db_helper.js'); +const { initNotification } = require('./helper/notification_reporter'); +const errorHandler = require('./helper/ErrorToServiceHandler'); +const total_energy = require('../databases/total_energy'); + +const SEND_TO = { + db_init: 0, + infoSender: 1 +}; + + +exports.install = async function(instance) { + const dbNodes = TABLE("nodes"); + const dbRelays = TABLE("relays"); + const dbSettings = TABLE("settings"); + 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 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.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"]; + Object.keys(dbs.nodesData).forEach(node => dbs.nodesData[node].readout = {}) + + let rvo_number = responseSettings[0]["rvo_name"].match(/\D+(\d{1,2})_/)[1]; + + dbs.settings = { + edge_fw_version: "2025-10-08", //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"], + phases: responseSettings[0]["phases"], + cloud_topic: responseSettings[0]["cloud_topic"], + has_main_switch: responseSettings[0]["has_main_switch"], + daily_report: responseSettings[0]["daily_report"], + send_changed_node_numbers: responseSettings[0]["send_changed_node_numbers"], + rvo_number: rvo_number, + + //dynamic values + masterNodeIsResponding: true, //cmd_manager + maintenance_mode: false, + } + + + dbs.settings.energy_to_switch_lamps = total_energy[rvo_number]; + if (dbs.settings.energy_to_switch_lamps === undefined) console.log('=============== db_init.js: energy_to_switch_lamps is undefined'); + + FLOW.dbLoaded = true; + errorHandler.setProjectId(dbs.settings.project_id); + initNotification(); + + //APP START - send to data services + const toService = { + id: dbs.settings.project_id, + name: dbs.settings.rvo_name, + fw_version: dbs.settings.edge_fw_version, + startdate: new Date().toISOString().slice(0, 19).replace('T', ' '), + js_error: "", + error_message: "" + }; + + instance.send(SEND_TO.infoSender, toService); + console.log("----------------> START - message send to service", toService); + + setTimeout(() => { + console.log("DB_INIT - data loaded"); + instance.send(SEND_TO.db_init, "_") + }, 5000) + +}; + diff --git a/RVO14/flow/debug.js b/RVO14/flow/debug.js new file mode 100755 index 0000000..00cb259 --- /dev/null +++ b/RVO14/flow/debug.js @@ -0,0 +1,100 @@ +exports.id = 'debug'; +exports.title = 'Debug'; +exports.author = 'Peter Širka'; +exports.color = '#967ADC'; +exports.click = true; +exports.input = true; +exports.icon = 'bug'; +exports.version = '2.0.4'; +exports.options = { enabled: true, repository: false, type: 'data' }; +exports.readme = `# Debug + +Prints data to the debug tab.`; + +exports.html = `
+
+
+
@(Output type)
+
@(Path to the property (leave empty to show the whole data object))
+
@(A group name)
+
@(Enabled)
+
+
+
`; + +exports.install = function(instance) { + + instance.on('data', function(response) { + if (instance.options.enabled) { + + var opt = instance.options; + var rep = response.repository; + var val = response.data; + var id = response.id; + + switch (instance.options.type){ + case 'both': + var data = {}; + data.repository = rep; + data.data = val instanceof Error ? { error: val.message, stack: val.stack } : val; + instance.debug(safeparse(opt.property ? U.get(data, opt.property) : data), undefined, opt.group, id); + break; + case 'repository': + instance.debug(safeparse(opt.property ? U.get(rep, opt.property) : rep), undefined, opt.group, id); + break; + case 'data': + default: + if (val instanceof Error) + instance.debug({ error: val.message, stack: val.stack }, undefined, opt.group, id); + else + instance.debug(safeparse(opt.property ? U.get(val, opt.property) : val), undefined, opt.group, id); + break; + } + } + }); + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + instance.save(); + }); + + instance.on('options', function() { + instance.custom.status(); + }); + + instance.custom.status = function() { + instance.status(instance.options.enabled ? 'Enabled' : 'Disabled'); + }; + + instance.custom.status(); + + function safeparse(o) { + + if (o instanceof Buffer) + return o; + + if (o === undefined) + return 'undefined'; + + if (o === null) + return 'null'; + + var cache = []; + var str = JSON.stringify(o, function(key, value) { + if (typeof value === 'object' && value !== null) { + if (cache.indexOf(value) !== -1) { + try { + return JSON.parse(JSON.stringify(value)); + } catch (error) { + return; + } + } + cache.push(value); + } + return value; + }); + cache = null; + return JSON.parse(str); + } +}; diff --git a/RVO14/flow/designer.json b/RVO14/flow/designer.json new file mode 100755 index 0000000..580f5a3 --- /dev/null +++ b/RVO14/flow/designer.json @@ -0,0 +1,3102 @@ +{ + "tabs": [ + { + "name": "MAIN PUSH", + "linker": "main-push", + "id": "1612772287426", + "index": 0 + }, + { + "name": "CMD manager", + "linker": "cmd-manager", + "id": "1615551125555", + "index": 1 + }, + { + "name": "Devices", + "linker": "devices", + "id": "1611921777196", + "index": 2 + } + ], + "components": [ + { + "id": "1611951142547", + "component": "debug", + "tab": "1611921777196", + "name": "ERROR", + "x": 598, + "y": 60, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#DA4453", + "notes": "" + }, + { + "id": "1612776786008", + "component": "wsmqttpublish", + "tab": "1612772287426", + "name": "WS MQTT publish", + "x": 281.75, + "y": 174, + "connections": { + "0": [ + { + "index": "0", + "id": "1615551060773" + } + ], + "1": [ + { + "index": "0", + "id": "1618300858252" + }, + { + "index": "0", + "id": "1618558465485" + } + ], + "2": [ + { + "index": "0", + "id": "1634303685503" + } + ], + "3": [ + { + "index": "0", + "id": "1731068754606" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Connected", + "color": "green" + }, + "options": { + "username": "", + "clientid": "", + "port": "1883", + "host": "" + }, + "color": "#888600", + "notes": "" + }, + { + "id": "1612778461252", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "tb-push", + "x": 72.75, + "y": 328, + "connections": { + "0": [ + { + "index": "0", + "id": "1612783322136" + }, + { + "index": "1", + "id": "1612776786008" + }, + { + "index": "0", + "id": "1731068754606" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1612783322136", + "component": "debug", + "tab": "1612772287426", + "name": "to TB", + "x": 283.75, + "y": 324, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615551060773", + "component": "debug", + "tab": "1612772287426", + "name": "errors from MQTT Broker", + "x": 594, + "y": 57, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#DA4453", + "notes": "" + }, + { + "id": "1615563373927", + "component": "debug", + "tab": "1615551125555", + "name": "Debug", + "x": 755, + "y": 155, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#DA4453", + "notes": "" + }, + { + "id": "1615566865233", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "tb-push", + "x": 755, + "y": 248, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1615798582262", + "component": "debug", + "tab": "1615551125555", + "name": "CMD_debug", + "x": 755, + "y": 346, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615802995322", + "component": "debug", + "tab": "1611921777196", + "name": "Debug", + "x": 596.8833312988281, + "y": 566.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Disabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": false + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615809128443", + "component": "debug", + "tab": "1611921777196", + "name": "tempToTb", + "x": 595.8833312988281, + "y": 658.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615809595184", + "component": "virtualwireout", + "tab": "1611921777196", + "name": "tb-push", + "x": 597.8833312988281, + "y": 377.25, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1616165795916", + "component": "httproute", + "tab": "1615551125555", + "name": "POST /terminal", + "x": 135, + "y": 547, + "connections": { + "0": [ + { + "index": "0", + "id": "1684060205000" + }, + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Listening", + "color": "green" + }, + "options": { + "timeout": 10, + "cachepolicy": 0, + "cacheexpire": "5 minutes", + "size": 5, + "url": "/terminal", + "method": "POST", + "name": "", + "flags": [ + "id:1616165795916", + "post", + 10000 + ], + "emptyresponse": false + }, + "color": "#5D9CEC", + "notes": "### Configuration\n\n- __POST /terminal__\n- flags: \n- maximum request data length: __5 kB__\n- empty response: __false__\n- cache policy: __no cache__\n- cache expire: __5 minutes__", + "cloning": false + }, + { + "id": "1616165824813", + "component": "httpresponse", + "tab": "1615551125555", + "name": "HTTP Response", + "x": 753, + "y": 423, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "json" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1617104731852", + "component": "debug", + "tab": "1615551125555", + "name": "DIDO_Debug", + "x": 669, + "y": 1040, + "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": "turnOff line", + "x": 133, + "y": 1161, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "object", + "data": "{line: 3, command: \"turnOff\", force: true}" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1617115013095", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "tb-push", + "x": 669, + "y": 1150, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1617284749681", + "component": "trigger", + "tab": "1615551125555", + "name": "update profile / node", + "x": 112, + "y": 208, + "connections": { + "0": [ + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "data": "profile_nodes", + "datatype": "string" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1618235171399", + "component": "trigger", + "tab": "1615551125555", + "name": "tun tasks", + "x": 184, + "y": 279, + "connections": { + "0": [ + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "data": "run" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1618300858252", + "component": "debug", + "tab": "1612772287426", + "name": "wsmqtt-exit1", + "x": 597.8833312988281, + "y": 149, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1618393583970", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "to-cmd-manager", + "x": 668.8833312988281, + "y": 1269, + "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": 132.88333129882812, + "y": 367, + "connections": { + "0": [ + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "platform-rpc-call", + "color": "gray" + }, + "options": { + "wirename": "platform-rpc-call" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1618393759854", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "cmd_to_dido", + "x": 119.88333129882812, + "y": 1007, + "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": 752.8833312988281, + "y": 527, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "cmd_to_dido", + "color": "gray" + }, + "options": { + "wirename": "cmd_to_dido" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1618558465485", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "platform-rpc-call", + "x": 597.8833312988281, + "y": 247, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "platform-rpc-call", + "color": "gray" + }, + "options": { + "wirename": "platform-rpc-call" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1618572059773", + "component": "trigger", + "tab": "1615551125555", + "name": "turnOn line", + "x": 132, + "y": 1085, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "data": "{line: 1, command: \"turnOn\", force: true}", + "datatype": "object" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1619515097737", + "component": "cmd_manager", + "tab": "1615551125555", + "name": "CMD Manager", + "x": 452.1091003417969, + "y": 341.05455017089844, + "connections": { + "0": [ + { + "index": "0", + "id": "1615563373927" + } + ], + "1": [ + { + "index": "0", + "id": "1615566865233" + }, + { + "index": "0", + "id": "1615798582262" + } + ], + "2": [ + { + "index": "0", + "id": "1616165824813" + } + ], + "3": [ + { + "index": "0", + "id": "1618393827655" + } + ], + "4": [ + { + "index": "0", + "id": "1635936391935" + } + ], + "5": [ + { + "index": "0", + "id": "1757006030239" + }, + { + "index": "0", + "id": "1757006060377" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1619605019281", + "component": "httproute", + "tab": "1615551125555", + "name": "GET db", + "x": 173, + "y": 653, + "connections": { + "0": [ + { + "index": "0", + "id": "1684060205000" + }, + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Listening", + "color": "green" + }, + "options": { + "timeout": 5, + "cachepolicy": 0, + "cacheexpire": "5 minutes", + "size": 5, + "url": "/db", + "method": "GET", + "name": "", + "flags": [ + "id:1619605019281", + "get", + 5000 + ] + }, + "color": "#5D9CEC", + "notes": "### Configuration\n\n- __GET /db__\n- flags: undefined\n- maximum request data length: __5 kB__\n- empty response: __undefined__\n- cache policy: __no cache__\n- cache expire: __5 minutes__", + "cloning": false + }, + { + "id": "1619784672383", + "component": "trigger", + "tab": "1615551125555", + "name": "turnOnAlarm", + "x": 120, + "y": 1234, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "object", + "data": "{command: \"turnOnAlarm\"}" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1619784812964", + "component": "trigger", + "tab": "1615551125555", + "name": "turnOffAlarm", + "x": 118, + "y": 1307, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "object", + "data": "{command: \"turnOffAlarm\"}" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1621340721628", + "component": "virtualwireout", + "tab": "1611921777196", + "name": "modbus_to_dido", + "x": 599, + "y": 471, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "modbus_to_dido", + "color": "gray" + }, + "options": { + "wirename": "modbus_to_dido" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1622640022885", + "component": "httproute", + "tab": "1615551125555", + "name": "POST /db_connector", + "x": 98, + "y": 1586, + "connections": { + "0": [ + { + "index": "0", + "id": "1622640073521" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Listening", + "color": "green" + }, + "options": { + "timeout": 5, + "cachepolicy": 0, + "cacheexpire": "5 minutes", + "size": 5, + "url": "/db_connector", + "method": "POST", + "flags": [ + "id:1622640022885", + "post", + 5000 + ] + }, + "color": "#5D9CEC", + "notes": "### Configuration\n\n- __POST /db_connector__\n- flags: \n- maximum request data length: __5 kB__\n- empty response: __undefined__\n- cache policy: __no cache__\n- cache expire: __5 minutes__", + "cloning": false + }, + { + "id": "1622640073521", + "component": "db_connector", + "tab": "1615551125555", + "name": "DbConnector", + "x": 372, + "y": 1572, + "connections": { + "1": [ + { + "index": "0", + "id": "1622641420685" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "edge": "undefined" + }, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1622641420685", + "component": "httpresponse", + "tab": "1615551125555", + "name": "HTTP Response", + "x": 596, + "y": 1586, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1634303504177", + "component": "monitormemory", + "tab": "1612772287426", + "name": "RAM", + "x": 69.88333129882812, + "y": 888.5, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465281992" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "858.88 MB / 985.68 MB", + "color": "gray" + }, + "options": { + "enabled": true, + "interval": 30000 + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1634303533779", + "component": "monitordisk", + "tab": "1612772287426", + "name": "disk", + "x": 70.88333129882812, + "y": 982.5, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465821120" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "5.78 GB / 7.26 GB", + "color": "gray" + }, + "options": { + "enabled": true, + "path": "/", + "interval": 30000 + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1634303595494", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "send-to-services", + "x": 51.883331298828125, + "y": 1400.5, + "connections": { + "0": [ + { + "index": "0", + "id": "1634463186563" + }, + { + "index": "1", + "id": "1634488120710" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1634303602169", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "send-to-services", + "x": 426.8833312988281, + "y": 878.5, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1634303685503", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "send-to-services", + "x": 600.8833312988281, + "y": 341.5, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1634303743260", + "component": "httprequest", + "tab": "1612772287426", + "name": "192.168.252.2:8004/sentmessage", + "reference": "", + "x": 506.8833312988281, + "y": 1331.7333374023438, + "connections": { + "0": [ + { + "index": "0", + "id": "1635327431236" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "url": "http://192.168.252.2:8004/sentmessage", + "method": "POST", + "stringify": "json" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1634463186563", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 305.75, + "y": 1442, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634464580289", + "component": "code", + "tab": "1612772287426", + "name": "Code", + "x": 245, + "y": 787, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465243324" + }, + { + "index": "0", + "id": "1634303602169" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "keepmessage": true, + "code": "let response = {};\nresponse.cpu = value.cpu;\nresponse.uptime = value.uptime;\n\nsend(0, response);", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1634465243324", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 428, + "y": 784, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634465281992", + "component": "code", + "tab": "1612772287426", + "name": "Code", + "x": 245, + "y": 884, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465338103" + }, + { + "index": "0", + "id": "1634303602169" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "keepmessage": true, + "code": "value.sender = \"ram\";\n\nlet response = {};\n\nresponse.memory_total = Math.round(value.total / (1024 ** 2));\nresponse.memory_free = Math.round(value.free / (1024 ** 2));\nresponse.memory_used = Math.round(value.used / (1024 ** 2));\n\nsend(0, response);", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1634465338103", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 429, + "y": 976, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634465821120", + "component": "code", + "tab": "1612772287426", + "name": "Code", + "x": 245, + "y": 978, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465892500" + }, + { + "index": "0", + "id": "1634303602169" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "keepmessage": true, + "code": "value.sender = \"hdd\";\n\nlet response = {};\n\nresponse.hdd_total = Math.round(value.total / (1024 ** 2));\nresponse.hdd_free = Math.round(value.free / (1024 ** 2));\nresponse.hdd_used = Math.round(value.used / (1024 ** 2));\n\nsend(0, response);", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1634465892500", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 432, + "y": 1068, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634484067516", + "component": "debug", + "tab": "1612772287426", + "name": "Send info", + "x": 513, + "y": 1441, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634488120710", + "component": "infosender", + "tab": "1612772287426", + "name": "Info sender", + "x": 301, + "y": 1336, + "connections": { + "0": [ + { + "index": "0", + "id": "1634484067516" + }, + { + "index": "0", + "id": "1634303743260" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "edge": "undefined" + }, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1635327431236", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 837.8833312988281, + "y": 1325.5, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1635936391935", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "send-to-services", + "x": 753, + "y": 623, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1637069803394", + "component": "monitorconsumption", + "tab": "1612772287426", + "name": "CPU", + "x": 69, + "y": 791, + "connections": { + "0": [ + { + "index": "0", + "id": "1634464580289" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "49.2% / 69.91 MB", + "color": "gray" + }, + "options": { + "monitorfiles": true, + "monitorconnections": true, + "monitorsize": true, + "monitorconsumption": true, + "enabled": true, + "interval": 30000 + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1683664161036", + "component": "debug", + "tab": "1615551125555", + "name": "CMDtoDIDO", + "x": 392, + "y": 1012, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1683981346282", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "from-dido-controller", + "x": 112, + "y": 459, + "connections": { + "0": [ + { + "index": "0", + "id": "1684055037116" + }, + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "from-dido-controller", + "color": "gray" + }, + "options": { + "wirename": "from-dido-controller" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1684055037116", + "component": "debug", + "tab": "1615551125555", + "name": "from dido to cmd", + "x": 451, + "y": 532, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1684060205000", + "component": "debug", + "tab": "1615551125555", + "name": "HTTP routes", + "x": 450, + "y": 639, + "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": "MDBToDido", + "x": 598, + "y": 147, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1699963668903", + "component": "dido_controller", + "tab": "1615551125555", + "name": "DIDO_Controller", + "x": 397, + "y": 1131, + "connections": { + "0": [ + { + "index": "0", + "id": "1617104731852" + } + ], + "1": [ + { + "index": "0", + "id": "1617104731852" + }, + { + "index": "0", + "id": "1617115013095" + } + ], + "2": [ + { + "index": "0", + "id": "1618393583970" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "edge": "undefined" + }, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1699964678894", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "modbus_to_dido", + "x": 96, + "y": 924, + "connections": { + "0": [ + { + "index": "0", + "id": "1699963668903" + }, + { + "index": "0", + "id": "1699964793925" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "modbus_to_dido", + "color": "gray" + }, + "options": { + "wirename": "modbus_to_dido" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1699964793925", + "component": "debug", + "tab": "1615551125555", + "name": "modbusToDido", + "x": 388, + "y": 920, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1699965957410", + "component": "modbus_reader", + "tab": "1611921777196", + "name": "Modbus reader", + "x": 232, + "y": 175, + "connections": { + "0": [ + { + "index": "0", + "id": "1611951142547" + } + ], + "1": [ + { + "index": "0", + "id": "1621340721628" + }, + { + "index": "0", + "id": "1684179110403" + }, + { + "index": "0", + "id": "1717441414646" + } + ], + "2": [ + { + "index": "0", + "id": "1615809595184" + }, + { + "index": "0", + "id": "1714752862828" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1700411878636", + "component": "thermometer", + "tab": "1611921777196", + "name": "Thermometer", + "x": 234.75, + "y": 444, + "connections": { + "0": [ + { + "index": "0", + "id": "1615802995322" + } + ], + "1": [ + { + "index": "0", + "id": "1615809595184" + }, + { + "index": "0", + "id": "1615809128443" + } + ], + "2": [ + { + "index": "0", + "id": "1621340721628" + }, + { + "index": "0", + "id": "1732889185927" + }, + { + "index": "0", + "id": "1717441414646" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#5CB36D", + "notes": "" + }, + { + "id": "1714752862828", + "component": "debug", + "tab": "1611921777196", + "name": "MDBToTb", + "x": 766, + "y": 324, + "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": 764.0833282470703, + "y": 222, + "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\telse if(value.status === \"NOK-thermometer\")\n\t{\n\t\tsend(0, {\"thermometer\": \"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\telse if(value.values.hasOwnProperty(\"temperature\"))\n\t{\n\t\tsend(0, {\"thermometer\": \"OK\"});\n\t}\n}", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1717442627834", + "component": "debug", + "tab": "1611921777196", + "name": "modbus service", + "x": 966.0833282470703, + "y": 165, + "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": 968.0833282470703, + "y": 268, + "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": 88.75, + "y": 1685, + "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": 296, + "y": 1671, + "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\", \"Flow has been restarted\", \"Node db has changed\"]", + "types": "[\"emergency\", \"critical\", \"error\", \"alert\"]", + "name": "" + }, + "color": "#30E193", + "notes": "" + }, + { + "id": "1718016073501", + "component": "httprequest", + "tab": "1612772287426", + "name": "http://192.168.252.2:8004/slack", + "x": 495, + "y": 1753, + "connections": { + "0": [ + { + "index": "0", + "id": "1718016086212" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "url": "http://192.168.252.2:8004/slack", + "method": "POST", + "stringify": "json" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1718016086212", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 832, + "y": 1664, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "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": 87, + "y": 1591, + "connections": { + "0": [ + { + "index": "0", + "id": "1718016052341" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "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\": \"\" } } } ] }", + "datatype": "object" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1729855334955", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "platform-rpc-call", + "x": 599.9333343505859, + "y": 541.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "platform-rpc-call", + "color": "gray" + }, + "options": { + "wirename": "platform-rpc-call" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1729855371093", + "component": "debug", + "tab": "1612772287426", + "name": "rpc cloud", + "x": 601.9333343505859, + "y": 440.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1731068658334", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 75.75, + "y": 184, + "connections": { + "0": [ + { + "index": "0", + "id": "1612776786008" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731068754606", + "component": "cloudmqttconnect", + "tab": "1612772287426", + "name": "MQTT to senica-prod01", + "x": 284.75, + "y": 452, + "connections": { + "1": [ + { + "index": "0", + "id": "1729855371093" + }, + { + "index": "0", + "id": "1729855334955" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Connected", + "color": "green" + }, + "options": { + "username": "", + "clientid": "", + "port": "2764", + "host": "192.168.252.2", + "topic": "" + }, + "color": "#888600", + "notes": "" + }, + { + "id": "1731069001548", + "component": "db_init", + "tab": "1612772287426", + "name": "DB Initialization", + "x": 1003.75, + "y": 240.25, + "connections": { + "0": [ + { + "index": "0", + "id": "1731069033416" + } + ], + "1": [ + { + "index": "0", + "id": "1747561603739" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#888600", + "notes": "" + }, + { + "id": "1731069033416", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "db-init", + "x": 1244.75, + "y": 233.25, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069059135", + "component": "showdb", + "tab": "1612772287426", + "name": "Show db data", + "x": 1186.75, + "y": 821.25, + "connections": { + "0": [ + { + "index": "0", + "id": "1731069079243" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#888600", + "notes": "" + }, + { + "id": "1731069079243", + "component": "debug", + "tab": "1612772287426", + "name": "dbData", + "x": 1390.75, + "y": 870.25, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1731069116691", + "component": "trigger", + "tab": "1612772287426", + "name": "settings", + "x": 934.75, + "y": 669.75, + "connections": { + "0": [ + { + "index": "0", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069131637", + "component": "trigger", + "tab": "1612772287426", + "name": "relaysData", + "x": 876.75, + "y": 733.75, + "connections": { + "0": [ + { + "index": "1", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069137374", + "component": "trigger", + "tab": "1612772287426", + "name": "nodesData", + "x": 852.75, + "y": 794.75, + "connections": { + "0": [ + { + "index": "2", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069179846", + "component": "trigger", + "tab": "1612772287426", + "name": "pinsData", + "x": 850.75, + "y": 861.75, + "connections": { + "0": [ + { + "index": "3", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069192937", + "component": "trigger", + "tab": "1612772287426", + "name": "sample data", + "x": 857.75, + "y": 928.75, + "connections": { + "0": [ + { + "index": "4", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069264443", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 63.75, + "y": 1279, + "connections": { + "0": [ + { + "index": "0", + "id": "1634488120710" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069334626", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "db-init", + "x": 172.88333129882812, + "y": 129, + "connections": { + "0": [ + { + "index": "0", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069548145", + "component": "virtualwirein", + "tab": "1611921777196", + "name": "db-init", + "x": 46.75, + "y": 192, + "connections": { + "0": [ + { + "index": "0", + "id": "1699965957410" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069567152", + "component": "virtualwirein", + "tab": "1611921777196", + "name": "db-init", + "x": 44.75, + "y": 465, + "connections": { + "0": [ + { + "index": "0", + "id": "1700411878636" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731070156936", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "db-init", + "x": 126.88333129882812, + "y": 1377, + "connections": { + "0": [ + { + "index": "2", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731234189516", + "component": "trigger", + "tab": "1612772287426", + "name": "monitor.txt", + "x": 882.75, + "y": 991.75, + "connections": { + "0": [ + { + "index": "5", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731234189551", + "component": "trigger", + "tab": "1612772287426", + "name": "err.txt", + "x": 904.75, + "y": 1053.75, + "connections": { + "0": [ + { + "index": "6", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1732700042559", + "component": "nodesdb_change_check", + "tab": "1612772287426", + "name": "Nodes DB change check", + "x": 266.8833312988281, + "y": 1980.2333984375, + "connections": { + "0": [ + { + "index": "0", + "id": "1732700071298" + }, + { + "index": "0", + "id": "1732700642917" + } + ], + "1": [ + { + "index": "0", + "id": "1759958914348" + }, + { + "index": "0", + "id": "1759959003114" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#888600", + "notes": "" + }, + { + "id": "1732700057052", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 76.75, + "y": 1988, + "connections": { + "0": [ + { + "index": "0", + "id": "1732700042559" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1732700071298", + "component": "debug", + "tab": "1612772287426", + "name": "nodesChange", + "x": 571.8833312988281, + "y": 2018.2333984375, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1732700642917", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "tb-push", + "x": 567.8833312988281, + "y": 1933, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1732889185927", + "component": "debug", + "tab": "1611921777196", + "name": "tempToDido", + "x": 594.8833312988281, + "y": 753, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1733574412965", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 72.75, + "y": 474, + "connections": { + "0": [ + { + "index": "1", + "id": "1731068754606" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1747561603739", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "send-to-services", + "x": 1243.8833312988281, + "y": 334.5, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1747562867845", + "component": "comment", + "tab": "1612772287426", + "name": "FLOW STARTING POINT", + "x": 1003.5666656494141, + "y": 178, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#704cff", + "notes": "" + }, + { + "id": "1749211698385", + "component": "trigger", + "tab": "1612772287426", + "name": "deviceStatus", + "x": 911.75, + "y": 1116.75, + "connections": { + "0": [ + { + "index": "7", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1757006030239", + "component": "httprequest", + "tab": "1615551125555", + "name": "192.168.252.2:8015/daily_report", + "x": 756.5666656494141, + "y": 715.4499969482422, + "connections": { + "0": [ + { + "index": "0", + "id": "1757006045804" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "stringify": "json", + "method": "POST", + "url": "http://192.168.252.2:8015/daily_report" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1757006045804", + "component": "debug", + "tab": "1615551125555", + "name": "ddd", + "x": 1091.566665649414, + "y": 711.4499969482422, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1757006060377", + "component": "debug", + "tab": "1615551125555", + "name": "reportDebug", + "x": 749.5666656494141, + "y": 799.4499969482422, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1759958914348", + "component": "httprequest", + "tab": "1612772287426", + "name": "http://192.168.252.2:8015/node_numbers", + "x": 571, + "y": 2111, + "connections": { + "0": [ + { + "index": "0", + "id": "1759958927094" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "stringify": "json", + "method": "POST", + "url": "http://192.168.252.2:8015/node_numbers" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1759958927094", + "component": "debug", + "tab": "1612772287426", + "name": "nodesChangeCloud", + "x": 951.8833312988281, + "y": 2109.2333984375, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1759959003114", + "component": "debug", + "tab": "1612772287426", + "name": "nodeChangeCloud1", + "x": 574, + "y": 2218, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1760020290879", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 84.75, + "y": 1787, + "connections": { + "0": [ + { + "index": "1", + "id": "1718016052341" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + } + ], + "version": 615 +} diff --git a/RVO14/flow/dido_controller.js b/RVO14/flow/dido_controller.js new file mode 100755 index 0000000..d16fb19 --- /dev/null +++ b/RVO14/flow/dido_controller.js @@ -0,0 +1,1486 @@ +exports.id = 'dido_controller'; +exports.title = 'DIDO_Controller'; +exports.version = '2.0.0'; +exports.group = 'Worksys'; +exports.color = '#2134B0'; +exports.input = 3; +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 + +state_of_main_switch - reportovat stav hlaveho istica : 0-> off 1-> on +rotary_switch_state - sem by sa mal reportovat stav vstupov manual a auto pola nasledovnej logiky: Manual = 1 a Auto = 0 -> Manu +Manual = 0 a Auto = 0 -> Off, Manual = 0 a Auto = 1 -> Automatic + +door_condition - pin 6, dverový kontakt -> 1 -> vyreportuje Closed, 0 -> vyreportuje Ope +twilight_sensor - hodnotu, ktoru vracia ten analogovy vstup (17) treba poslat sem ako float number. Zrejme tu potom pridame nejaky koeficient prevodu na luxy + +Na kazdu liniu +state_of_breaker - podla indexu istica sa reportuje jeho stav, teda istic na liniu 1: 0-> off, 1-> on +state_of_contactor - podla indexu stkaca sa reportuje jeho stav, teda stykac 1 na liniu 1: 0-> off, 1-> on +*/ + +const { errLogger, logger, monitor } = require('./helper/logger'); +const SerialPort = require('serialport'); +const WebSocket = require('ws'); +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 errorHandler = require('./helper/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 hasMainSwitch; + +let alarmStatus = "OFF"; + +const SEND_TO = { + debug: 0, + tb: 1, + cmd_manager: 2 +} + + +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 = {}; + let rsPortReceivedData = []; + + //to be able to get proper twilight values + let twilight_sensor_interval = 5;//minutes + let twilight_sensor = []; + const twilight_sensor_array = []; + let twilightError = false; + + monitor.info("DIDO_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-we make it global to see it from outside + FLOW.deviceStatus = { //key is device name: temperature,.... + "state_of_main_switch": "Off", //Hlavny istic (alebo druhy dverovy kontakt) + "rotary_switch_state": "Off", //Prevadzkovy + "door_condition": "closed", //Dverový kontakt + "em": "OK", //elektromer rvo + "temperature": "OK", //templomer + "battery": "OK", //Bateria + "power_supply": "OK", //Zdroj + "master_node": "OK", //MN - GLOBALS.settings.masterNodeIsResponding + "no_voltage": "OK", //GLOBALS.settings.no_voltage - vypadok napatia na faze + "state_of_breaker": {}, //"Off",//Istic + "state_of_contactor": {}, //"Off",//Stykac + "twilight_sensor": "OK" //lux sensor + }; + let deviceStatus = FLOW.deviceStatus; + + + function main() { + + GLOBALS = FLOW.GLOBALS; + SETTINGS = FLOW.GLOBALS.settings; + rvoTbName = SETTINGS.rvoTbName; + pinsData = GLOBALS.pinsData; + relaysData = GLOBALS.relaysData; + + tbHandler = new DataToTbHandler(SEND_TO.tb); + tbHandler.setSender(exports.title); + + controller_type = SETTINGS.controller_type; //"lm" or "unipi" + hasMainSwitch = SETTINGS.has_main_switch; + + if (controller_type == "") controller_type = "lm"; + + 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, "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; + } + } + + //report RVO version relaysData[0].tbname; + let values = {}; + values["edge_fw_version"] = SETTINGS.edge_fw_version; + values["maintenance_mode"] = SETTINGS.maintenance_mode; + + sendTelemetry(values, rvoTbName); + + 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); + } + + + function handleRsPort() { + + if (rsPort) { + rsPort.removeAllListeners(); + rsPort = null; + } + + //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('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) { + if (!err) { + monitor.info(exports.title + "--->Digital in_out has been set (runSyncExec was sucessfull)"); + + turnAlarm("off"); + 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('error', err => { + let message = "Dido: rsPort error: " + err.message; + logger.debug(message); + monitor.info(message); + errorHandler.sendMessageToService(message); + }) + + rsPort.on("close", () => { + let message = "Dido: rsPort closed - reconnecting ..."; + logger.debug(message); + monitor.info(message); + setTimeout(handleRsPort, 1000); + }) + + rsPort.open(); + } + + + function handleWebSocket() { + + if (ws) { + ws.removeAllListeners(); + ws = null; + } + + //to keep websocket opened, we send request every 150 seconds + let startRequests = null; + + console.log("handleWebSocket function called"); + ws = new WebSocket('ws:/0.0.0.0:1234/ws'); + + ws.onopen = function open() { + + instance.send(0, exports.title + " running"); + turnAlarm("off"); + + initialSetting(); + + setTimeout(function() { ws.send(JSON.stringify({ cmd: "all" })) }, 5000); + // we request dev info about neuron device from evok to keep websocket connection alive + // for some reason this request returns no data, but connection keeps alive + startRequests = setInterval(() => { + ws.send(JSON.stringify({ "cmd": "filter", "dev": ["neuron"] })); + }, 150000) + }; + + + // 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 = async 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; + + 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 => { + logger.debug('Dido: websocket error', err); + }) + + ws.onclose = function() { + logger.debug('Dido: websocket onclose, reconnecting...') + clearInterval(startRequests); + setTimeout(handleWebSocket, 1000); + } + } + + 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 turnAlarm(onOrOff) { + let value = 0; + if (onOrOff == "on") value = 1; + + if (value == 1 && SETTINGS.maintenance_mode) return; + + alarmStatus = "OFF"; + if (value == 1) alarmStatus = "ON"; + + if (rsPort) { + let arr = [0x55]; + arr.push(13); + arr.push(0); + arr.push(value); + + rsPort.write(Buffer.from(arr), function(err) { + logger.debug(`sirena - ${onOrOff}`); + }); + } + else if (ws) { + let cmd = { "cmd": "set", "dev": "relay", "circuit": "1_01", "value": value }; + ws.send(JSON.stringify(cmd)); + logger.debug(`sirena - ${onOrOff}`); + } + } + + + 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") { + bits.push(0); + } + else bits.push(1); + + if (deviceStatus["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); + } + + + // turn line on or off + function turnLine(onOrOff, line, pin, force, info) { + //onOrOff => "on" or "off" + let value = 0; + if (onOrOff == "on") value = 1; + + if (force == undefined) force = false; + + if (line == 0) { + if (value == 1 && alarmStatus == "ON") turnAlarm("off"); + SETTINGS.maintenance_mode = value ? true : false; + + 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); + return; + } + + if (pin === undefined) pin = getPin(line); + + if (pin === undefined) { + errLogger.error("pin is undefined!", line); + return; + } + + if (!force) { + if (relaysData[line].contactor == value) { + instance.send(SEND_TO.debug, `line is already ${onOrOff} ` + line); + logger.debug(`Dido: turnLine: line is already ${onOrOff} `, line); + return; + } + } + + // if(!rsPort.isOpen && !ws) + if (!rsPort && !ws) { + errLogger.error("Dido - port or websocket is not opened"); + return; + } + + if (rsPort) { + let arr = [0x55]; + arr.push(pin); + arr.push(0); + arr.push(value); + + rsPort.write(Buffer.from(arr), function(err) { + if (err === undefined) { + monitor.info(`Dido: turnLine ${onOrOff} zapisal do rsPort-u`, line, pin, arr, info); + switchLogic(arr); + } + else { + monitor.info(`Dido: turnLine ${onOrOff} WRITE error`, err); + } + }); + + } + else if (ws) { + //pin = "relay1_03" or "input1_01" ... we must make just "1_01" with slice method + monitor.info(`Dido: turnLine ${onOrOff} - (line, pin, force)`, line, pin, force, info); + let cmd = { "cmd": "set", "dev": "relay", "circuit": pin.slice(5), "value": value }; + ws.send(JSON.stringify(cmd)); + } + + //if rvo is 24/7, it has just one switching profile point at 13:00. we do not want to send notification as it repeats every day. + //const d = new Date(); + //if(d.getHours() != 13) sendNotification("Dido_controller: ", SETTINGS.rvoTbName, "switching_profile_point_applied_to_line", { line: line, value: onOrOff }, "", SEND_TO.tb, instance); + } + + + // 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; + + // 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) { + const status = flowdata.data.status; + if (status == "NOK-twilight_sensor") { + deviceStatus["twilight_sensor"] = "NOK"; + } + else if (status == "NOK-em340" || status == "NOK-em111") { + deviceStatus["em"] = "NOK"; + } + else if (status == "NOK-thermometer") { + deviceStatus["temperature"] = "NOK"; + } + } + else if ("values" in flowdata.data) { + 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" + } + else if (values.hasOwnProperty("temperature")) { + deviceStatus["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"; + } + + sendTelemetry(values, rvoTbName); + } + + sendRvoStatus(); + }) + + + + + // we expect array as flowdata.data + instance.on("1", flowdata => { + + //console.log(flowdata.data); + + if (!flowdata.data instanceof Object) return; + + let obj = flowdata.data; + let line = obj.line; + 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"); + }) + + + function calculateStateCode() { + + let bits = []; + + //Hlavny istic - state_of_main_switch => v rvo senica je to druhy door pre silovu cast (EM) + if (deviceStatus["state_of_main_switch"] === "closed" || deviceStatus["state_of_main_switch"] === "Off") { + bits.push(0); + } + else { + bits.push(1); + } + + //Prevadzkovy mod - Manual, Off, Automatic, maintenance_mode = true/false // DAVA 2 BITY + if (!SETTINGS.maintenance_mode) { + if (deviceStatus["rotary_switch_state"] === "Manual") { + bits.push(0); + bits.push(1); + } + + if (deviceStatus["rotary_switch_state"] === "Automatic") { + bits.push(0); + bits.push(0); + } + + if (deviceStatus["rotary_switch_state"] === "Off") { + bits.push(1); + bits.push(0); + } + } + else { + bits.push(1); + bits.push(1); + } + + //Dverovy kontakt + if (deviceStatus["door_condition"] === "closed") { + bits.push(0); + } + else { + bits.push(1); + } + + //EM + if (deviceStatus["em"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //Teplomer + if (deviceStatus["temperature"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //Batéria + if (deviceStatus["battery"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //Zdroj + if (deviceStatus["power_supply"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //MN + if (deviceStatus["master_node"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //výpadok napätia na fáze + if (deviceStatus["no_voltage"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + if (deviceStatus["twilight_sensor"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + // doplnime do 16 bitov (2 byty) + for (let i = bits.length; i < 16; i++) { + bits.push(0); + } + + // console.log("calculateStateCode - deviceStatus", deviceStatus); + // 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; + } + + + async function sendRvoStatus() { + + if (SETTINGS === undefined) return; + SETTINGS.masterNodeIsResponding ? deviceStatus["master_node"] = "OK" : deviceStatus["master_node"] = "NOK"; + + 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 pinsForRvoStatus(controllerType, hasMainSwitch) { + + let pins = []; + + if (controllerType === "lm") { + pins = [1, 4, 6]; + if (hasMainSwitch === 1) { + pins = [4, 6]; + } + } else if (controllerType === "unipi") { + pins = ["input1_01", "input1_04", "input1_05"]; + if (hasMainSwitch === 1) { + pins = ["input1_01", "input1_04"]; + } + } + + return pins; + } + + + function checkRvoStatus() { + + // 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 + //set RVO state + let status = "OK"; + + for (const [key, value] of Object.entries(deviceStatus)) { + if (["em", "twilight_sensor", "temperature", "master_node"].includes(key) && value === "NOK") status = "NOK"; + } + + if (status === "OK") { + + let pinIndexes = pinsForRvoStatus(controller_type, hasMainSwitch); + + for (const pinIndex of pinIndexes) { + if (previousValues[pinIndex] === 0) { + if ((pinIndex === 6 || pinIndex === 'input1_01' || pinIndex === 'input1_05') && SETTINGS.maintenance_mode) continue; + status = "NOK"; + break; + } + } + } + + // battery status. If value is 1 - battery is NOK + if (previousValues[5] === 1) status = "NOK"; + if (SETTINGS.no_voltage.size > 0) status = "NOK"; + + // console.log("rvo status",status) + return status; + } + + + // we pass array to function in case of rsPort ==> switchLogic([55,3,0,1]) ==> [[55,3,0,1]] + // we pass two values in case of websocket ==> switchLogic("relay1_03",1) ==> ["relay1_03",1] + const switchLogic = (...args) => { + + let values = {}; + let pinIndex, newPinValue, twilight; + + //data from rsPort + if (args.length == 1) { + pinIndex = args[0][1] + 1; + if (pinIndex === 17) pinIndex--; + newPinValue = args[0][3]; + twilight = args[0][2]; + } + //data from websocket + else { + pinIndex = args[0]; + newPinValue = args[1]; + } + + 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; + + //default value + let value = "On"; + if (newPinValue === 0) value = "Off"; + + //Hlavny istic + if (type === "state_of_main_switch" && hasMainSwitch) { + if (newPinValue === 0 && newPinValue !== previousValues[pinIndex]) { + sendNotification("switchLogic", rvoTbName, "main_switch_has_been_turned_off", {}, "", SEND_TO.tb, instance, "state_of_main_switch"); + 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"); + deviceStatus["state_of_main_switch"] = "On"; + } + } + + //Prevadzkovy mod + 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"; + + deviceStatus["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, "power_supply_has_disconnected_input", {}, "", SEND_TO.tb, instance, "power_supply"); + + deviceStatus["power_supply"] = "NOK"; + } + else if (newPinValue === 1 && newPinValue !== previousValues[pinIndex]) { + sendNotification("switchLogic", rvoTbName, "power_supply_works_correctly", {}, "", SEND_TO.tb, instance, "power_supply"); + + deviceStatus["power_supply"] = "OK"; + } + } + + //Bateria - 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"); + + deviceStatus["battery"] = "NOK"; + } + else if (newPinValue === 0 && newPinValue !== previousValues[pinIndex]) { + sendNotification("switchLogic", rvoTbName, "battery_level_is_ok", {}, "", SEND_TO.tb, instance, "battery_level"); + + deviceStatus["battery"] = "OK"; + } + } + + //Dverovy kontakt - pin 6 + //! Ak je rvo s dvoma dverovymi kontaktami, ked pride z evoku signal z input1_05, co bol predytm "state_of_main switch" handlujeme ho teraz ako 'door_condition' + else if (type == "door_condition" || type === "state_of_main_switch") { + newPinValue === 0 ? value = "open" : value = "closed"; + + let door = "door_main"; + if (type === "state_of_main_switch") door = "door_em"; + + if (value === "open") { + if (SETTINGS.maintenance_mode) { + sendNotification("switchLogic", rvoTbName, door + "_open", {}, "", SEND_TO.tb, instance, door); + } else { + sendNotification("switchLogic", rvoTbName, door + "_open_without_permission", {}, "", SEND_TO.tb, instance, door); + + // 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 (value === "closed") { + if (alarmStatus == "ON") turnAlarm("off"); + sendNotification("switchLogic", rvoTbName, door + "_close", {}, "", SEND_TO.tb, instance, door); + } + + deviceStatus[type] = value; + } + + //lux sensor + else if (type == "twilight_sensor") { + //! TODO - to show nok status, if lux value is not changing more then 10 times. + //Daylight is far more than 1000. So most of the day, when it is sunshine comes just value 1000. But lux sensor is not NOK. + //This is not the case in LM. If value from LM is the same 10x, there is 99% possibility, that sensor is NOK. + value = newPinValue; + + if (controller_type === 'lm') { + value = parseFloat(newPinValue + (256 * twilight)); + + 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 && !twilightError) { + twilightError = true; + let value = twilight_sensor_array.shift(); + + newPinValue = 0; + } + else if (set.size !== 1 && twilightError) { + //sendNotification("switchLogic", rvoTbName, 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) { + 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); + } + } + + 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); + } + + deviceStatus["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 (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 }); + + //mame iba 3 istice. vyreportujeme a ohandlujeme liniu na tom istom istici ako paralelna linia (napr linia 1, paralelna s nou je linia 4, key je string "4") + // ak je 7 linii, na 1 istici je linia 1,4,7 + + if (line == 1) { + + const lineOnSameBraker = [4, 7]; + + for (var i = 0; i < lineOnSameBraker.length; i++) { + if (!relaysData.hasOwnProperty(lineOnSameBraker[i])) continue; + + 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; + reportLineStatus(lineOnSameBraker[i]); + + values[type] = value; + const tbname = relaysData[lineOnSameBraker[i]].tbname; + sendTelemetry(values, tbname); + + delete values[type]; + } + + } + else { + const lineOnSameBraker = line + 3 + ""; + + if (relaysData.hasOwnProperty(lineOnSameBraker)) { + 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; + reportLineStatus(line + 3); + + values[type] = value; + const tbname = relaysData[lineOnSameBraker].tbname; + sendTelemetry(values, tbname); + + delete values[type]; + } + } + + } + + if (value == "Off") values["status"] = "NOK"; + deviceStatus["state_of_breaker"][line] = value; + + reportLineStatus(line); + } + else return; + + values[type] = value; + + if (type == "rotary_switch_state") { + if (SETTINGS.maintenance_mode) value = "maintenance"; + value = value.toLowerCase(); + values["power_mode"] = value; + } + + if (newPinValue != previousValues[pinIndex]) previousValues[pinIndex] = newPinValue; + if (Object.keys(values).length > 0 && tbname) sendTelemetry(values, tbname); + } + + + function sendTelemetry(values, tbname, date = Date.now()) { + let dataToTb = { + [tbname]: [ + { + "ts": date, + "values": values + } + ] + }; + + tbHandler.sendToTb(dataToTb, instance); + } + + + function isObject(item) { + return (typeof item === "object" && !Array.isArray(item) && item !== null); + } + +} //end of 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 +// *|input1_01|state_of_main_switch|0|........... +// *|input1_02|rotary_switch_state|0|........... +// *|input1_03|rotary_switch_state|0|........... +// *|intut1_04|power_supply|0|........... +// *|input1_05|door_condition|0|........... +// *|input1_06|state_of_breaker|1|........... +// *|input1_07|state_of_breaker|2|........... +// *|input1_08|state_of_breaker|3|........... +// *|relay1_02|state_of_contactor|1|........... +// *|relay1_03|state_of_contactor|2|........... +// *|relay1_04|state_of_contactor|3|........... +// *|287D8776E0013CE9|temperature|0|........... + + +//! pins_data --> from UNIPI +// { +// 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 } +// } + +//! relays_data +// { +// '0': { +// line: 0, +// tbname: 'KjbN4q7JPZmexgdnz2yKQ98YAWwO0Q3BMX6ERLoV', +// contactor: 1, +// profile: '' +// }, +// '1': { +// line: 1, +// tbname: 'RMgnK93rkoAazbqdQ4yBG95Z1YXGx6pmwBeVEP2O', +// contactor: 0, +// profile: '{"intervals":[{"value":0,"end_time":"20:00","start_time":"13:00"},{"value":1,"end_time":"10:00","start_time":"20:00"},{"value":0,"end_time":"10:20","start_time":"10:00"},{"value":1,"end_time":"10:40","start_time":"10:20"},{"value":0,"end_time":"11:00","start_time":"10:40"},{"value":1,"end_time":"11:30","start_time":"11:00"},{"value":0,"end_time":"11:50","start_time":"11:30"},{"value":1,"end_time":"13:00","start_time":"11:50"}],"astro_clock":false,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' +// }, +// '2': { +// line: 2, +// tbname: 'dlE1VQjYrNx9gZRmb38gG08oLBO4qaAk2M6JPnG7', +// contactor: 0, +// profile: '{"intervals":[{"value":0,"end_time":"20:00","start_time":"13:00"},{"value":1,"end_time":"10:00","start_time":"20:00"},{"value":0,"end_time":"10:20","start_time":"10:00"},{"value":1,"end_time":"10:40","start_time":"10:20"},{"value":0,"end_time":"11:00","start_time":"10:40"},{"value":1,"end_time":"11:30","start_time":"11:00"},{"value":0,"end_time":"11:50","start_time":"11:30"},{"value":1,"end_time":"13:00","start_time":"11:50"}],"astro_clock":false,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' +// }, +// '3': { +// line: 3, +// tbname: 'vnmG4kJxaXWNBgMQq0D7Aj5e9oZzOAlr6LdR3w2V', +// contactor: 0, +// profile: '{"intervals":[{"value":0,"end_time":"20:30","start_time":"13:00"},{"value":1,"end_time":"00:10","start_time":"20:30"},{"value":0,"end_time":"13:00","start_time":"05:40"},{"value":1,"end_time":"05:40","start_time":"00:10"}],"astro_clock":true,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' +// } +// } + + + + + +// { +// "jbN4q7JPZmexgdnz2yKbWGDYAWwO0Q3BMX6ERLoV": [ +// { +// "ts": 1700409326353, +// "values": { +// "_event": { +// "type": "notice", +// "status": "new", +// "source": { +// "func": "rsPort.open()", +// "component": "1700343402190", +// "component_name": "DIDO_Controller", +// "edge": "jbN4q7JPZmexgdnz2yKbWGDYAWwO0Q3BMX6ERLoV" +// }, +// "message": "al_shariff_10.0.0.38: FLOW has been started ", +// "message_data": "" +// } +// } +// } +// ] +// } diff --git a/RVO14/flow/helper/DataToTbHandler.js b/RVO14/flow/helper/DataToTbHandler.js new file mode 100755 index 0000000..716ef7b --- /dev/null +++ b/RVO14/flow/helper/DataToTbHandler.js @@ -0,0 +1,187 @@ +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; + this.itIsNodeReadout = false; + this.sender = ""; + + // if attribute change difference is less than limit value, we do not send to tb. + this.attributeChangeLimit = { + temperature: 0.5, + Phase_1_voltage: 2, + Phase_2_voltage: 2, + Phase_3_voltage: 2, + Phase_1_current: 0.1, + Phase_2_current: 0.1, + Phase_3_current: 0.1, + Phase_1_power: 2, + Phase_2_power: 2, + Phase_3_power: 2, + total_power: 2, + total_energy: 1, + Phase_1_pow_factor: 0.1, + Phase_2_pow_factor: 0.1, + Phase_3_pow_factor: 0.1, + power_factor: 0.1, + lifetime: 2, + voltage: 2, + power: 2, + frequency: 3, + energy: 0.1, + current: 2, + inclination_x: 10, + inclination_y: 10, + inclination_z: 10 + }; + + } + + dump() { + console.log("----------------------------"); + console.log("previousValues", this.previousValues); + console.log("----------------------------"); + } + + setSender(sender) { + this.sender = sender; + } + + isEmptyObject(obj) { + for (var _ in obj) { + return false; + } + return true; + } + + + sendToTb(data, instance) { + + //not to modify data object, we do deep copy: + let dataCopy = JSON.parse(JSON.stringify(data)); + + let keys = Object.keys(dataCopy); + + if (keys.length == 0) { + if (this.debug) console.log("sendToTb received empty object", dataCopy); + return; + } + + let tbname = keys[0]; + let ts; + + let arrayOfValues = dataCopy[tbname]; + let arrayOfValuesToSend = []; + + for (let i = 0; i < arrayOfValues.length; i++) { + + ts = arrayOfValues[i].ts; + let values = this.prepareValuesForTb(tbname, ts, arrayOfValues[i].values); + + if (!this.isEmptyObject(values)) { + arrayOfValuesToSend.push({ ts: ts, values: values }); + } + + } + + if (arrayOfValuesToSend.length == 0) { + //if(this.debug) console.log("data not sent - empty array"); + return; + } + + this.messageCounter++; + + let dataToTbModified = { + [tbname]: arrayOfValuesToSend + } + + //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); + instance.send(this.index, dataToTbModified); + } + + + getDiffTimestamp(key) { + //TODO set different value for given key!!! + //if(key == "status") this.timeToHoldTbValue = 2*60*60;//2h + return this.timeToHoldTbValue * 1000; + } + + + prepareValuesForTb(tbname, timestamp, values) { + + let keys = Object.keys(values); + + if (keys.includes("lifetime")) this.itIsNodeReadout = true; + + if (!this.previousValues.hasOwnProperty(tbname)) { + this.previousValues[tbname] = {}; + } + + //if(this.debug) console.log("prepareValuesForTb", tbname, timestamp, values); + + for (let i = 0; i < keys.length; i++) { + + let key = keys[i]; + let value = values[key]; + + if (!this.previousValues[tbname].hasOwnProperty(key)) { + this.previousValues[tbname][key] = { ts: timestamp, value: value }; + continue; + } + + // attributeData ==> {voltage: {ts:333333, value:5}} + let attributeData = this.previousValues[tbname][key]; + let attributeToChange = false; + if (key in this.attributeChangeLimit) attributeToChange = true; + let limit = this.attributeChangeLimit[key]; + let timestampDiffToRemoveKey; + + //this will ensure "node statecode" will be sent just once an hour + if (this.itIsNodeReadout && key === "statecode") { + attributeData.value = value; + this.itIsNodeReadout = false; + timestampDiffToRemoveKey = 1 * 60 * 60 * 1000; // 1 hour + } + + if (key === "twilight_sensor" && value > 100) { + attributeData.value = value; + } + + //if edge, master or node version do not change, send just once a day: + if (["edge_fw_version", "master_node_version", "fw_version"].includes(key)) { + timestampDiffToRemoveKey = 24 * 60 * 60 * 1000; + } + + if (attributeData.value === value || attributeToChange && Math.abs(attributeData.value - value) < limit) { + + let diff = timestamp - attributeData.ts; + if (!timestampDiffToRemoveKey) timestampDiffToRemoveKey = this.getDiffTimestamp(key); + + if (diff > timestampDiffToRemoveKey) { + attributeData.ts = Date.now(); + //if(this.debug) console.log(this.sender + ": update ts for key", key, "diff is", diff, "messageCounter", this.messageCounter); + } + else { + delete values[key]; + //if(this.debug) console.log(this.sender + ": delete key", key, "diff is", diff, "messageCounter", this.messageCounter, timestampDiffToRemoveKey); + } + } + else { + attributeData.value = value; + attributeData.ts = timestamp; + } + + } + + return values; + } +} + +module.exports = DataToTbHandler; + diff --git a/RVO14/flow/helper/ErrorToServiceHandler.js b/RVO14/flow/helper/ErrorToServiceHandler.js new file mode 100755 index 0000000..2b27c32 --- /dev/null +++ b/RVO14/flow/helper/ErrorToServiceHandler.js @@ -0,0 +1,91 @@ +const { MD5 } = require('./md5.js'); +const { networkInterfaces } = require('os'); + +class ErrorToServiceHandler { + constructor() { + this.previousValues = {}; + + this.project_id = undefined; + + const nets = networkInterfaces(); + this.ipAddresses = {}; + + for (const name of Object.keys(nets)) { + for (const net of nets[name]) { + // Skip over non-IPv4 and internal (i.e. 127.0.0.1) addresses + if (net.family === 'IPv4' && !net.internal) { + if (!this.ipAddresses[name]) { + this.ipAddresses[name] = []; + } + this.ipAddresses[name].push(net.address); + } + } + } + } + + setProjectId(project_id) { + this.project_id = project_id; + } + + processMessage(message, seconds) { + if (Array.isArray(message)) message = message.join(', '); + + let key = MD5(message); + let ts = Date.now(); + + //keep in memory - default value is 1h + if (seconds === undefined) seconds = 60 * 60; + + if (!this.previousValues.hasOwnProperty(key)) { + this.previousValues[key] = { ts: ts, duration: seconds }; + } + + let diff = (ts - this.previousValues[key].ts); + if (diff < this.previousValues[key].duration * 1000) return false; + + this.previousValues[key].ts = ts; + + return message; + } + + sendMessageToService(message, seconds, message_type) { + + // if error occures too early FLOW.GLOBALS.settings.project_id is still undefined + if (this.project_id === undefined) { + console.log("ErrorToServiceHandler.js: no project_id"); + return; + } + + let f = this.processMessage(message, seconds); + if (f === false) return; + + if (message_type === undefined) message_type = "error_message"; + + let toService = { + id: this.project_id, + ipAddresses: this.ipAddresses + }; + + //js_error || error_message + toService[message_type] = message; + + console.log("ErrorToServiceHandler------------------------>send to service", toService); + + RESTBuilder.make(function(builder) { + builder.method('POST'); + builder.post(toService); + builder.url('http://192.168.252.2:8004/sentmessage'); + + builder.callback(function(err, response, output) { + console.log("process.on error send", err, response, output, toService); + }); + }); + + } +} + +const errorHandler = new ErrorToServiceHandler(); + + +module.exports = errorHandler; +//module.exports = ErrorToServiceHandler; diff --git a/RVO14/flow/helper/db_helper.js b/RVO14/flow/helper/db_helper.js new file mode 100755 index 0000000..40e796c --- /dev/null +++ b/RVO14/flow/helper/db_helper.js @@ -0,0 +1,44 @@ +function promisifyBuilder(builder) +{ + return new Promise((resolve, reject) => { + + try{ + + builder.callback(function(err, response) { + + if(err != null) reject(err); + resolve(response); + }); + + } catch (error) { + reject(error); + } + }) +} + +function makeMapFromDbResult(response, ...keys) +{ + let s = "-"; + let data = {}; + + for(let i = 0; i < response.length; i++) + { + let record = response[i]; + + let k = []; + for(let j = 0; j < keys.length; j++) + { + k.push( record[keys[j]] ); + } + + let key = k.join(s); + data[ key ] = record; + } + + return data; +} + +module.exports = { + promisifyBuilder, + makeMapFromDbResult + } \ No newline at end of file diff --git a/RVO14/flow/helper/logger.js b/RVO14/flow/helper/logger.js new file mode 100755 index 0000000..2585639 --- /dev/null +++ b/RVO14/flow/helper/logger.js @@ -0,0 +1,30 @@ +//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/RVO14/flow/helper/md5.js b/RVO14/flow/helper/md5.js new file mode 100755 index 0000000..d3b0480 --- /dev/null +++ b/RVO14/flow/helper/md5.js @@ -0,0 +1,5 @@ +function MD5(d){var r = M(V(Y(X(d),8*d.length)));return r.toLowerCase()};function M(d){for(var _,m="0123456789ABCDEF",f="",r=0;r>>4&15)+m.charAt(15&_);return f}function X(d){for(var _=Array(d.length>>2),m=0;m<_.length;m++)_[m]=0;for(m=0;m<8*d.length;m+=8)_[m>>5]|=(255&d.charCodeAt(m/8))<>5]>>>m%32&255);return _}function Y(d,_){d[_>>5]|=128<<_%32,d[14+(_+64>>>9<<4)]=_;for(var m=1732584193,f=-271733879,r=-1732584194,i=271733878,n=0;n>16)+(_>>16)+(m>>16)<<16|65535&m}function bit_rol(d,_){return d<<_|d>>>32-_} + +module.exports = { + MD5 +} \ No newline at end of file diff --git a/RVO14/flow/helper/notification_reporter.js b/RVO14/flow/helper/notification_reporter.js new file mode 100755 index 0000000..839c12c --- /dev/null +++ b/RVO14/flow/helper/notification_reporter.js @@ -0,0 +1,121 @@ +//key is device, value = message {} +let sentValues = {}; +let notificationsData = null; +let rvoName; + +//sendNotification("CMD Manager: process cmd", SETTINGS.rvoTbName, "dimming_profile_was_successfully_received_by_node", { node: node }, "", SEND_TO.tb, instance); + +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 +}; + +function getKey(map, val) { + return Object.keys(map).findItem(key => map[key] === val); +} + +//https://stackoverflow.com/questions/41117799/string-interpolation-on-variable +var template = (tpl, args) => tpl.replace(/\${(\w+)}/g, (_, v) => args[v]); + + +function initNotification() { + notificationsData = FLOW.GLOBALS.notificationsData; + rvoName = FLOW.GLOBALS.settings.rvo_name; +} + + +function sendNotification(func, device, key, params, extra, tb_output, instance, saveKey) { + + let storeToSendValues = true; + if (saveKey == undefined) storeToSendValues = false; + + let weight = ""; + let message = {}; + + let notification = notificationsData[key]; + + if (notification) { + weight = notification.weight.toLowerCase(); + + Object.keys(notification).forEach(item => { + if (["en", "sk", "de", "cz", "it", "es"].includes(item)) { + message[item] = rvoName + ": " + template(notification[item], params); + } + }) + } + else { + //console.error("sendNotification: Notifications: undefined key", key, func, notificationsData); + console.error("sendNotification: Notifications: undefined key", key, func); + return false; + } + + //detect invalid err weight + if (getKey(ERRWEIGHT, weight) == undefined) { + console.error("sendNotification: Notifications: undefined weight", weight, key, func); + return false; + } + + if (sentValues.hasOwnProperty(saveKey)) { + if (JSON.stringify(sentValues[saveKey]) == JSON.stringify(message)) { + return false; + } + } + + if (sentValues[saveKey] == undefined) { + if (storeToSendValues) { + //do not send - flow is was started + sentValues[saveKey] = message; + return false; + } + } + + if (storeToSendValues) sentValues[saveKey] = message; + + let content = { + "type": weight, + "status": "new", + "source": { + "func": func, + "component": instance.id, + "component_name": instance.name, + "edge": device + }, + "message": message, + "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 + + return true; + +} + +module.exports = { + sendNotification, + ERRWEIGHT, + initNotification +} + diff --git a/RVO14/flow/helper/register.js b/RVO14/flow/helper/register.js new file mode 100755 index 0000000..fc1d008 --- /dev/null +++ b/RVO14/flow/helper/register.js @@ -0,0 +1,144 @@ +/* +0 - cislo registra / prikaz +1 - recepient - 0 = master, 1 = slave (slave je automaticky group a broadcast) +2 - r/rw - read/write +3- register name - nazov registra / prikazu (len pre info - zobrazenie v aplikacii) + +4,5,6,7, - jednotlive byte-y - nazov byte-u +4-7 - RES. a prazdny string "" sa nezobrazia!!! +*/ + +//124 zaznamov +const registers = [ + ["0","1","R","Status","","",""], + ["1","1","RW","Dimming","R-Channel ","G-Channel","B-Channel ","W - Channel"], + ["2","1","R","Device types","","",".",""], + ["3","1","RW","Group addresses 1-4","Groups Add. 4","Groups Add. 3","Groups Add. 2","Groups Add. 1"], + ["4","1","RW","Group addresses 5-8","Groups Add. 8","Groups Add. 7","Groups Add. 6","Groups Add. 5"], + ["5","1","RW","Serial number (MAC)","","","",""], + ["6","1","RW","Time of dusk","HH","MM","SS","EXTRA"], + ["7","1","RW","Time of dawn","HH","MM","SS","EXTRA"], + ["8","1","RW","Time Schedule settings","TBD","TBD","Movement sensor","Time Schedule"], + ["9","1","RW","TS1 Time point 1","HH","MM","SS","Ext. Device"], + ["10","1","RW","TS1 Time point 1 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["11","1","RW","TS1 Time point 2","HH","MM","SS","Ext. Device"], + ["12","1","RW","TS1 Time point 2 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["13","1","RW","TS1 Time point 3","HH","MM","SS","Ext. Device"], + ["14","1","RW","TS1 Time point 3 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["15","1","RW","TS1 Time point 4","HH","MM","SS","Ext. Device"], + ["16","1","RW","TS1 Time point 4 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["17","1","RW","TS1 Time point 5","HH","MM","SS","Ext. Device"], + ["18","1","RW","TS1 Time point 5 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["19","1","RW","TS1 Time point 6","HH","MM","SS","Ext. Device"], + ["20","1","RW","TS1 Time point 6 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["21","1","RW","TS1 Time point 7","HH","MM","SS","Ext. Device"], + ["22","1","RW","TS1 Time point 7 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["23","1","RW","TS1 Time point 8","HH","MM","SS","Ext. Device"], + ["24","1","RW","TS1 Time point 8 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["25","1","RW","TS1 Time point 9","HH","MM","SS","Ext. Device"], + ["26","1","RW","TS1 Time point 9 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["27","1","RW","TS1 Time point 10","HH","MM","SS","Ext. Device"], + ["28","1","RW","TS1 Time point 10 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["29","1","RW","TS1 Time point 11","HH","MM","SS","Ext. Device"], + ["30","1","RW","TS1 Time point 11 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["31","1","RW","TS1 Time point 12","HH","MM","SS","Ext. Device"], + ["32","1","RW","TS1 Time point 12 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["33","1","RW","TS1 Time point 13","HH","MM","SS","Ext. Device"], + ["34","1","RW","TS1 Time point 13 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["35","1","RW","TS1 Time point 14","HH","MM","SS","Ext. Device"], + ["36","1","RW","TS1 Time point 14 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["37","1","RW","TS1 Time point 15","HH","MM","SS","Ext. Device"], + ["38","1","RW","TS1 Time point 15 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["39","1","RW","TS1 Time point 16","HH","MM","SS","Ext. Device"], + ["40","1","RW","TS1 Time point 16 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["41","1","RW","TS2 Time point 1","HH","MM","SS","Ext. Device"], + ["42","1","RW","TS2 Time point 1 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["43","1","RW","TS2 Time point 2","HH","MM","SS","Ext. Device"], + ["44","1","RW","TS2 Time point 2 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["45","1","RW","TS2 Time point 3","HH","MM","SS","Ext. Device"], + ["46","1","RW","TS2 Time point 3 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["47","1","RW","TS2 Time point 4","HH","MM","SS","Ext. Device"], + ["48","1","RW","TS2 Time point 4 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["49","1","RW","TS2 Time point 5","HH","MM","SS","Ext. Device"], + ["50","1","RW","TS2 Time point 5 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["51","1","RW","TS2 Time point 6","HH","MM","SS","Ext. Device"], + ["52","1","RW","TS2 Time point 6 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["53","1","RW","TS2 Time point 7","HH","MM","SS","Ext. Device"], + ["54","1","RW","TS2 Time point 7 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["55","1","RW","TS2 Time point 8","HH","MM","SS","Ext. Device"], + ["56","1","RW","TS2 Time point 8 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["57","1","RW","TS2 Time point 9","HH","MM","SS","Ext. Device"], + ["58","1","RW","TS2 Time point 9 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["59","1","RW","TS2 Time point 10","HH","MM","SS","Ext. Device"], + ["60","1","RW","TS2 Time point 10 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["61","1","RW","TS2 Time point 11","HH","MM","SS","Ext. Device"], + ["62","1","RW","TS2 Time point 11 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["63","1","RW","TS2 Time point 12","HH","MM","SS","Ext. Device"], + ["64","1","RW","TS2 Time point 12 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["65","1","RW","TS2 Time point 13","HH","MM","SS","Ext. Device"], + ["66","1","RW","TS2 Time point 13 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["67","1","RW","TS2 Time point 14","HH","MM","SS","Ext. Device"], + ["68","1","RW","TS2 Time point 14 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["69","1","RW","TS2 Time point 15","HH","MM","SS","Ext. Device"], + ["70","1","RW","TS2 Time point 15 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["71","1","RW","TS2 Time point 16","HH","MM","SS","Ext. Device"], + ["72","1","RW","TS2 Time point 16 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["73","1","RW","Power meter status","TBD","","",""], + ["74","1","R","Input Voltage","","","",""], + ["75","1","R","Input Current","","","",""], + ["76","1","R","Input Power","","","",""], + ["77","1","R","Cos phi","","","",""], + ["78","1","R","Frequency","","","",""], + ["79","1","RW","Energy","","","",""], + ["80","1","RW","Lifetime","","","",""], + ["81","1","RW","Power on cycles (input)","","","",""], + ["82","1","RW","Power on cycles (relay)","","","",""], + ["83","1","R","Time since last power on","","","",""], + ["84","1","R","Accelerometer data","","","",""], + ["85","1","RW","GPS latitude","pos/neg","deg","min ","sec"], + ["86","1","RW","GPS longitude","pos/neg","deg","min ","sec"], + ["87","1","RW","Actual time","HH","MM","SS","RES."], + ["88","1","RW","Actual date","Day of week","Day","Month","Year"], + ["89","1","R","Production data 1","","","",""], + ["90","1","R","Production data 2","","","",""], + ["91","1","RW","Network ID","NID3","NID2","NID1","NID0"], + ["95","1","RW","Actual Lux level from cabinet","RES.","RES.","HB","LB"], + ["96","1","RW","Threshold lux level","Dusk HB","Dusk LB","Dawn HB","Dawn LB"], + ["97","1","RW","Adjust period","Dusk HB","Dusk LB","Dawn HB","Dawn LB"], + ["98","1","RW","Offset","RES.","RES.","Dusk","Dawn"], + ["99","1","RW","CCT min/max range","max-H","max-L","min-H","min-L"], + ["100","1","RW","DALI interface","Cmd ID","Add","Cmd","Resp"], + ["101","1","RW","Module FW ver","v1","v2","v3","v4"], + ["102","1","RW","Module MAC-H","unused","unused","M1","M2"], + ["103","1","RW","Module MAC-L","M3","M4","M5","M6"], + ["122","1","R","FW update status/control register","Byte3","Byte2","Byte1","Byte0"], + ["123","1","R","FW update - data index","Byte3","Byte2","Byte1","Byte0"], + ["124","1","R","FW update - data","Byte3","Byte2","Byte1","Byte0"], + ["0","0","R","Status","","","",""], + ["1","0","RW","Control register","RES.","RES.","RES.","init mode enable"], + ["2","0","R","Device types","","","",""], + ["3","0","R","Serial number (MAC)","","","",""], + ["4","0","R","Production data 1","","","",""], + ["5","0","R","Production data 2","","","",""], + ["6","0","RW","Network ID","NID3","NID2","NID1","NID0"], + ["7","0","RW","RS232 settings","param.","param.","Baudrate H","Baudrate L"], + ["8","0","R","Accelerometer data","","","",""], + ["9","0","RW","Module FW ver","v1","v2","v3","v4"], + ["10","0","RW","Module MAC-H","unused","unused","M1","M2"], + ["11","0","RW","Module MAC-L","M3","M4","M5","M6"], + ["32","0","RW","FW update status/control register","Byte3","Byte2","Byte1","Byte0"], + ["33","0","RW","FW update - data index","Byte3","Byte2","Byte1","Byte0"], + ["34","0","RW","FW update - data","Byte3","Byte2","Byte1","Byte0"], + ["125","0","RW","Debug Register","Byte3","Byte2","Byte1","Byte0"], + ["126","0","RW","Network Control Register","Byte3","Byte2","Byte1","Byte0"], + ["127","0","R","Network Status Register","Byte3","Byte2","Byte1","Byte0"], + ["128","0","RW","Node XX Serial Number Register","SER3","SER2","SER1","SER0"], + ["256","0","R","Node XX Network Status Register","","","",""] +]; + +let register = {}; + +module.exports = { + registers, + register +} \ No newline at end of file diff --git a/RVO14/flow/helper/serialport_helper.js b/RVO14/flow/helper/serialport_helper.js new file mode 100755 index 0000000..7f5920d --- /dev/null +++ b/RVO14/flow/helper/serialport_helper.js @@ -0,0 +1,99 @@ +const { exec } = require('child_process'); + +function openPort(port) { + return new Promise((resolve, reject) => { + + var callbackError = function(err) { + port.removeListener('error', callbackError); + port.removeListener('open', callbackError); + + reject(err.message); + }; + + var callbackOpen = function(data) { + port.removeListener('error', callbackError); + port.removeListener('open', callbackOpen); + + resolve("port open: ok"); + }; + + port.on('error', callbackError); + port.on('open', callbackOpen); + + port.open(); + + }) +} + +function runSyncExec(command) { + return new Promise((resolve, reject) => { + + exec(command, (error, stdout, stderr) => { + if (error == null) resolve(stdout); + reject(error); + }); + + }) +} + +async function writeData(port, data, readbytes, timeout) { + return new Promise((resolve, reject) => { + + // 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) { + + port.write(Buffer.from(data), function(err) { + if (err) { + reject(err.message); + } + }); + + 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 +} diff --git a/RVO14/flow/helper/suncalc.js b/RVO14/flow/helper/suncalc.js new file mode 100755 index 0000000..c9ca56d --- /dev/null +++ b/RVO14/flow/helper/suncalc.js @@ -0,0 +1,317 @@ +/* + (c) 2011-2015, Vladimir Agafonkin + SunCalc is a JavaScript library for calculating sun/moon position and light phases. + https://github.com/mourner/suncalc +*/ + +(function () { 'use strict'; + +// shortcuts for easier to read formulas + +var PI = Math.PI, + sin = Math.sin, + cos = Math.cos, + tan = Math.tan, + asin = Math.asin, + atan = Math.atan2, + acos = Math.acos, + rad = PI / 180; + +// sun calculations are based on http://aa.quae.nl/en/reken/zonpositie.html formulas + + +// date/time constants and conversions + +var dayMs = 1000 * 60 * 60 * 24, + J1970 = 2440588, + J2000 = 2451545; + +function toJulian(date) { return date.valueOf() / dayMs - 0.5 + J1970; } +function fromJulian(j) { return new Date((j + 0.5 - J1970) * dayMs); } +function toDays(date) { return toJulian(date) - J2000; } + + +// general calculations for position + +var e = rad * 23.4397; // obliquity of the Earth + +function rightAscension(l, b) { return atan(sin(l) * cos(e) - tan(b) * sin(e), cos(l)); } +function declination(l, b) { return asin(sin(b) * cos(e) + cos(b) * sin(e) * sin(l)); } + +function azimuth(H, phi, dec) { return atan(sin(H), cos(H) * sin(phi) - tan(dec) * cos(phi)); } +function altitude(H, phi, dec) { return asin(sin(phi) * sin(dec) + cos(phi) * cos(dec) * cos(H)); } + +function siderealTime(d, lw) { return rad * (280.16 + 360.9856235 * d) - lw; } + +function astroRefraction(h) { + if (h < 0) // the following formula works for positive altitudes only. + h = 0; // if h = -0.08901179 a div/0 would occur. + + // formula 16.4 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + // 1.02 / tan(h + 10.26 / (h + 5.10)) h in degrees, result in arc minutes -> converted to rad: + return 0.0002967 / Math.tan(h + 0.00312536 / (h + 0.08901179)); +} + +// general sun calculations + +function solarMeanAnomaly(d) { return rad * (357.5291 + 0.98560028 * d); } + +function eclipticLongitude(M) { + + var C = rad * (1.9148 * sin(M) + 0.02 * sin(2 * M) + 0.0003 * sin(3 * M)), // equation of center + P = rad * 102.9372; // perihelion of the Earth + + return M + C + P + PI; +} + +function sunCoords(d) { + + var M = solarMeanAnomaly(d), + L = eclipticLongitude(M); + + return { + dec: declination(L, 0), + ra: rightAscension(L, 0) + }; +} + + +var SunCalc = {}; + + +// calculates sun position for a given date and latitude/longitude + +SunCalc.getPosition = function (date, lat, lng) { + + var lw = rad * -lng, + phi = rad * lat, + d = toDays(date), + + c = sunCoords(d), + H = siderealTime(d, lw) - c.ra; + + return { + azimuth: azimuth(H, phi, c.dec), + altitude: altitude(H, phi, c.dec) + }; +}; + + +// sun times configuration (angle, morning name, evening name) + +var times = SunCalc.times = [ + [-0.833, 'sunrise', 'sunset' ], + [ -0.3, 'sunriseEnd', 'sunsetStart' ], + [ -6, 'dawn', 'dusk' ], + [ -12, 'nauticalDawn', 'nauticalDusk'], + [ -18, 'nightEnd', 'night' ], + [ 6, 'goldenHourEnd', 'goldenHour' ] +]; + +// adds a custom time to the times config + +SunCalc.addTime = function (angle, riseName, setName) { + times.push([angle, riseName, setName]); +}; + + +// calculations for sun times + +var J0 = 0.0009; + +function julianCycle(d, lw) { return Math.round(d - J0 - lw / (2 * PI)); } + +function approxTransit(Ht, lw, n) { return J0 + (Ht + lw) / (2 * PI) + n; } +function solarTransitJ(ds, M, L) { return J2000 + ds + 0.0053 * sin(M) - 0.0069 * sin(2 * L); } + +function hourAngle(h, phi, d) { return acos((sin(h) - sin(phi) * sin(d)) / (cos(phi) * cos(d))); } +function observerAngle(height) { return -2.076 * Math.sqrt(height) / 60; } + +// returns set time for the given sun altitude +function getSetJ(h, lw, phi, dec, n, M, L) { + + var w = hourAngle(h, phi, dec), + a = approxTransit(w, lw, n); + return solarTransitJ(a, M, L); +} + + +// calculates sun times for a given date, latitude/longitude, and, optionally, +// the observer height (in meters) relative to the horizon + +SunCalc.getTimes = function (date, lat, lng, height) { + + height = height || 0; + + var lw = rad * -lng, + phi = rad * lat, + + dh = observerAngle(height), + + d = toDays(date), + n = julianCycle(d, lw), + ds = approxTransit(0, lw, n), + + M = solarMeanAnomaly(ds), + L = eclipticLongitude(M), + dec = declination(L, 0), + + Jnoon = solarTransitJ(ds, M, L), + + i, len, time, h0, Jset, Jrise; + + + var result = { + solarNoon: fromJulian(Jnoon), + nadir: fromJulian(Jnoon - 0.5) + }; + + for (i = 0, len = times.length; i < len; i += 1) { + time = times[i]; + h0 = (time[0] + dh) * rad; + + Jset = getSetJ(h0, lw, phi, dec, n, M, L); + Jrise = Jnoon - (Jset - Jnoon); + + result[time[1]] = fromJulian(Jrise); + result[time[2]] = fromJulian(Jset); + } + + return result; +}; + + +// moon calculations, based on http://aa.quae.nl/en/reken/hemelpositie.html formulas + +function moonCoords(d) { // geocentric ecliptic coordinates of the moon + + var L = rad * (218.316 + 13.176396 * d), // ecliptic longitude + M = rad * (134.963 + 13.064993 * d), // mean anomaly + F = rad * (93.272 + 13.229350 * d), // mean distance + + l = L + rad * 6.289 * sin(M), // longitude + b = rad * 5.128 * sin(F), // latitude + dt = 385001 - 20905 * cos(M); // distance to the moon in km + + return { + ra: rightAscension(l, b), + dec: declination(l, b), + dist: dt + }; +} + +SunCalc.getMoonPosition = function (date, lat, lng) { + + var lw = rad * -lng, + phi = rad * lat, + d = toDays(date), + + c = moonCoords(d), + H = siderealTime(d, lw) - c.ra, + h = altitude(H, phi, c.dec), + // formula 14.1 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + pa = atan(sin(H), tan(phi) * cos(c.dec) - sin(c.dec) * cos(H)); + + h = h + astroRefraction(h); // altitude correction for refraction + + return { + azimuth: azimuth(H, phi, c.dec), + altitude: h, + distance: c.dist, + parallacticAngle: pa + }; +}; + + +// calculations for illumination parameters of the moon, +// based on http://idlastro.gsfc.nasa.gov/ftp/pro/astro/mphase.pro formulas and +// Chapter 48 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + +SunCalc.getMoonIllumination = function (date) { + + var d = toDays(date || new Date()), + s = sunCoords(d), + m = moonCoords(d), + + sdist = 149598000, // distance from Earth to Sun in km + + phi = acos(sin(s.dec) * sin(m.dec) + cos(s.dec) * cos(m.dec) * cos(s.ra - m.ra)), + inc = atan(sdist * sin(phi), m.dist - sdist * cos(phi)), + angle = atan(cos(s.dec) * sin(s.ra - m.ra), sin(s.dec) * cos(m.dec) - + cos(s.dec) * sin(m.dec) * cos(s.ra - m.ra)); + + return { + fraction: (1 + cos(inc)) / 2, + phase: 0.5 + 0.5 * inc * (angle < 0 ? -1 : 1) / Math.PI, + angle: angle + }; +}; + + +function hoursLater(date, h) { + return new Date(date.valueOf() + h * dayMs / 24); +} + +// calculations for moon rise/set times are based on http://www.stargazing.net/kepler/moonrise.html article + +SunCalc.getMoonTimes = function (date, lat, lng, inUTC) { + var t = new Date(date); + if (inUTC) t.setUTCHours(0, 0, 0, 0); + else t.setHours(0, 0, 0, 0); + + var hc = 0.133 * rad, + h0 = SunCalc.getMoonPosition(t, lat, lng).altitude - hc, + h1, h2, rise, set, a, b, xe, ye, d, roots, x1, x2, dx; + + // go in 2-hour chunks, each time seeing if a 3-point quadratic curve crosses zero (which means rise or set) + for (var i = 1; i <= 24; i += 2) { + h1 = SunCalc.getMoonPosition(hoursLater(t, i), lat, lng).altitude - hc; + h2 = SunCalc.getMoonPosition(hoursLater(t, i + 1), lat, lng).altitude - hc; + + a = (h0 + h2) / 2 - h1; + b = (h2 - h0) / 2; + xe = -b / (2 * a); + ye = (a * xe + b) * xe + h1; + d = b * b - 4 * a * h1; + roots = 0; + + if (d >= 0) { + dx = Math.sqrt(d) / (Math.abs(a) * 2); + x1 = xe - dx; + x2 = xe + dx; + if (Math.abs(x1) <= 1) roots++; + if (Math.abs(x2) <= 1) roots++; + if (x1 < -1) x1 = x2; + } + + if (roots === 1) { + if (h0 < 0) rise = i + x1; + else set = i + x1; + + } else if (roots === 2) { + rise = i + (ye < 0 ? x2 : x1); + set = i + (ye < 0 ? x1 : x2); + } + + if (rise && set) break; + + h0 = h2; + } + + var result = {}; + + if (rise) result.rise = hoursLater(t, rise); + if (set) result.set = hoursLater(t, set); + + if (!rise && !set) result[ye > 0 ? 'alwaysUp' : 'alwaysDown'] = true; + + return result; +}; + + +// export as Node module / AMD module / browser variable +if (typeof exports === 'object' && typeof module !== 'undefined') module.exports = SunCalc; +else if (typeof define === 'function' && define.amd) define(SunCalc); +else window.SunCalc = SunCalc; + +}()); diff --git a/RVO14/flow/helper/utils.js b/RVO14/flow/helper/utils.js new file mode 100755 index 0000000..dbffe45 --- /dev/null +++ b/RVO14/flow/helper/utils.js @@ -0,0 +1,161 @@ +const fs = require('fs').promises; + +function bytesToInt(bytes, numberOfBytes) { + let buffer = []; + if (Array.isArray(bytes)) { + buffer = bytes.slice(0); + if (numberOfBytes != undefined) { + buffer = bytes.slice(bytes.length - numberOfBytes); + } + } + else buffer.push(bytes); + + let result = 0; + for (let i = 0; i < buffer.length; i++) { + result = (result << 8) | buffer[i]; + } + + return result >>> 0; //ensure it's an unsigned 32-bit number +} + +function resizeArray(arr, newSize, defaultValue) { + while (newSize > arr.length) + arr.push(defaultValue); + arr.length = newSize; +} + +longToByteArray = function(/*long*/long) { + // we want to represent the input as a 8-bytes array + var byteArray = [0, 0, 0, 0, 0, 0, 0, 0]; + + for (var index = 0; index < byteArray.length; index++) { + var byte = long & 0xff; + byteArray[index] = byte; + long = (long - byte) / 256; + } + + return byteArray; +}; + +function addDays(date, days) { + var result = new Date(date); + result.setDate(result.getDate() + days); + return result; +} + +/* +sleep(2000).then(() => { + // Do something after the sleep! + + +}); +*/ + +function sleep(time) { + return new Promise((resolve) => setTimeout(resolve, time)); +} + +function isEmptyObject(obj) { + for (var name in obj) { + return false; + } + return true; +} + +function emptyJsObject(jsObject) { + Object.keys(jsObject).forEach(key => delete jsObject[key]); +} + +function convertUTCDateToLocalDate(date) { + var newDate = new Date(date); + newDate.setMinutes(date.getMinutes() + date.getTimezoneOffset()); + return newDate; +} + +function addZeroBefore(n) { + return (n < 10 ? '0' : '') + n; +} + + +/** + * Asynchronously writes data to a file. + * + * @param {string} filePath The path to the file. + * @param {string} data The data to write to the file. + * @param {boolean} [append=false] If true, appends the data to the file. If false, it overwrites the file. + */ +async function writeToFile(filePath, data, append = false) { + if (typeof data !== 'string') data = JSON.stringify(data, null, 2); + try { + if (append) { + // Append the data to the end of the file. This is the simplest way to append. + await fs.appendFile(filePath, data, 'utf8'); + console.log(`Successfully appended data to ${filePath} using fs.appendFile.`); + } else { + // Overwrite the file with the new data. + await fs.writeFile(filePath, data, 'utf8'); + console.log(`Successfully wrote (overwrote) data to ${filePath} using fs.writeFile.`); + } + } catch (error) { + console.error(`Error writing to file ${filePath}:`, error); + } +} + + + /** + * Checks if an item is present in an array and adds it if it's not. + * * @param {Array} arr The array to check. + * @param {*} item The item to add. + * @returns {Array} The modified array. + */ +const addToArrayIfUnique = (arr, item) => { + if (!arr.includes(item)) { + arr.push(item); + } + return arr; +}; + + +var convertBase = function() { + + function convertBase(baseFrom, baseTo) { + return function(num) { + return parseInt(num, baseFrom).toString(baseTo); + + }; + } + + // binary to decimal + convertBase.bin2dec = convertBase(2, 10); + + // binary to hexadecimal + convertBase.bin2hex = convertBase(2, 16); + + // decimal to binary + convertBase.dec2bin = convertBase(10, 2); + + // decimal to hexadecimal + convertBase.dec2hex = convertBase(10, 16); + + // hexadecimal to binary + convertBase.hex2bin = convertBase(16, 2); + + // hexadecimal to decimal + convertBase.hex2dec = convertBase(16, 10); + + return convertBase; +}(); + +module.exports = { + bytesToInt, + longToByteArray, + addDays, + addZeroBefore, + resizeArray, + isEmptyObject, + emptyJsObject, + sleep, + convertUTCDateToLocalDate, + writeToFile, + addToArrayIfUnique +} diff --git a/RVO14/flow/httprequest.js b/RVO14/flow/httprequest.js new file mode 100755 index 0000000..469c8cb --- /dev/null +++ b/RVO14/flow/httprequest.js @@ -0,0 +1,137 @@ +exports.id = 'httprequest'; +exports.title = 'HTTP Request'; +exports.group = 'HTTP'; +exports.color = '#5D9CEC'; +exports.input = true; +exports.version = '2.0.1'; +exports.output = 1; +exports.author = 'Peter Širka'; +exports.icon = 'cloud-upload'; + +exports.html = `
+
@(URL address)
+
+
+
@(HTTP method)
+
+
+
@(Serialization)
+
+
+
@(Download the content in chunks)
+
@(Keep persistent cookies)
+
@(Disable DNS cache)
+
@(Keep alive connection)
+
+
+
+
@(Custom headers)
+
@(Cookies)
+
+
+
+ +
+
+
+
@(User)
+
+
+
@(Password)
+
+
+
+
+
`; + +exports.readme = `# Request + +This component creates a request with received data. + +__Response:__ +\`\`\`javascript +{ + data: String, + headers: Object, + status: Number, + host: String +} +\`\`\` + +__Dynamic arguments__: +Are performed via FlowData repository and can be used for URL address or for custom headers/cookies/auth. Use \`repository\` component for creating of dynamic arguments. Dynamic values are replaced in the form \`{key}\`: + +- url address e.g. \`https://.../{key}/\` +- headers values e.g. \`{token}\` +- cookies values e.g. \`{token}\``; + +exports.install = function(instance) { + + var can = false; + var flags = null; + var cookies2 = null; + + instance.on('data', function(response) { + can && instance.custom.send(response); + }); + + instance.custom.send = function(response) { + var options = instance.options; + + var headers = null; + var cookies = null; + + options.headers && Object.keys(options.headers).forEach(function(key) { + !headers && (headers = {}); + headers[key] = response.arg(options.headers[key]); + }); + + if (options.username && options.userpassword) { + !headers && (headers = {}); + headers['Authorization'] = 'Basic ' + U.createBuffer(response.arg(options.username + ':' + options.userpassword)).toString('base64'); + } + + options.cookies && Object.keys(options.cookies).forEach(function(key) { + !cookies && (cookies = {}); + cookies[key] = response.arg(options.cookies[key]); + }); + + if (options.chunks) { + U.download(response.arg(options.url), flags, options.stringify === 'none' ? null : response.data, function(err, response) { + response.on('data', (chunks) => instance.send2(chunks)); + }, cookies || cookies2, headers); + } else { + U.request(response.arg(options.url), flags, options.stringify === 'none' ? null : response.data, 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) + instance.error(err, response); + }, cookies || cookies2, headers); + } + }; + + instance.reconfigure = function() { + var options = instance.options; + can = options.url && options.url && options.method && options.stringify ? true : false; + instance.status(can ? '' : 'Not configured', can ? undefined : 'red'); + + if (!can) + return; + + flags = []; + flags.push(options.method.toLowerCase()); + options.stringify === 'json' && flags.push('json'); + options.stringify === 'raw' && flags.push('raw'); + options.keepalive && flags.push('keepalive'); + !options.nodns && flags.push('dnscache'); + if (options.persistentcookies) { + flags.push('cookies'); + cookies2 = {}; + } else + cookies2 = null; + }; + + instance.on('options', instance.reconfigure); + instance.reconfigure(); +}; \ No newline at end of file diff --git a/RVO14/flow/httpresponse.js b/RVO14/flow/httpresponse.js new file mode 100755 index 0000000..160a3bb --- /dev/null +++ b/RVO14/flow/httpresponse.js @@ -0,0 +1,76 @@ +exports.id = 'httpresponse'; +exports.title = 'HTTP Response'; +exports.group = 'HTTP'; +exports.color = '#5D9CEC'; +exports.icon = 'arrow-right'; +exports.input = true; +exports.output = ['#666D76']; +exports.version = '2.0.0'; +exports.author = 'Martin Smola'; +exports.readme = `# HTTP response + +HTTP response will respond with data recieved using data-type set in Settings form or plain text if not set. Output is the message duration \`Number\` in seconds.`; + +exports.html = `
+
@(Response data-type)
+
JSON is by default.
+
`; + +exports.install = function(instance) { + + var dursum = 0; + var durcount = 0; + + instance.on('data', function(flowdata) { + + var ctrl = flowdata.repository.controller; + var data = flowdata.data; + + if (!ctrl) { + instance.throw('No controller to use for response!'); + return; + } + + durcount++; + dursum += ((new Date() - flowdata.begin) / 1000).floor(2); + setTimeout2(instance.id, instance.custom.duration, 500, 10); + + ctrl.$flowdata = flowdata; + + var datatype = instance.options.datatype || 'json'; + if (datatype === 'emptyresponse') + return ctrl.plain(''); + + if (datatype !== 'json' && typeof(data) !== 'string') { + instance.throw('Incorect type of data, expected string, got ' + typeof(data)); + ctrl.plain(data == null ? '' : data.toString()); + return; + } + + switch(datatype) { + case 'html': + ctrl.content(data, 'text/html'); + break; + case 'plain': + ctrl.plain(data); + break; + case 'xml': + ctrl.content(data, 'text/xml'); + break; + default: + ctrl.json(data); + break; + } + }); + + instance.on('service', function() { + dursum = 0; + durcount = 0; + }); + + instance.custom.duration = function() { + var avg = (dursum / durcount).floor(2); + instance.status(avg + ' sec.'); + instance.send2(0, avg); + }; +}; diff --git a/RVO14/flow/httproute.js b/RVO14/flow/httproute.js new file mode 100755 index 0000000..583a19d --- /dev/null +++ b/RVO14/flow/httproute.js @@ -0,0 +1,326 @@ +exports.id = 'httproute'; +exports.title = 'HTTP Route'; +exports.group = 'HTTP'; +exports.color = '#5D9CEC'; +exports.icon = 'globe'; +exports.input = false; +exports.output = ['#6CAC5A', '#37BC9B']; +exports.version = '1.2.3'; +exports.author = 'Martin Smola'; +exports.cloning = false; +exports.options = { method: 'GET', url: '', size: 5, cacheexpire: '5 minutes', cachepolicy: 0, timeout: 5 }; +exports.dateupdated = '2021-01-21 18:30d'; +exports.readme = `# HTTP route + +__Outputs__: +- first output: raw data (cache is empty or is disabled) +- second output: cached data + +If one of the outputs is disabled then automatic responce with code "503 service unavailable" is sent. + +When a request comes in bellow object is available at \`flowdata.data\`: + +\`\`\`javascript +{ + params: { id: '1' }, // params for dynamic routes, e.g. /test/{id} + query: { msg: 'Hello' }, // parsed query string, e.g. /test/1?msg=Hello + body: { test: 'OK' }, // object if json requests otherwise string + headers: {}, // headers data + session: {}, // session data + user: {}, // user data + files: [], // uploaded files + url: '/users/', // a relative URL address + referrer: '/', // referrer + mobile: false, // determines mobile device + robot: false, // determines search robots/crawlsers + language: 'en' // determines language +} +\`\`\` + +See [documentation for flags](https://docs.totaljs.com/latest/en.html#api~HttpRouteOptionsFlags~unauthorize). These method flags are set automatically e.g. \`get, post, put, patch or delete\` + +--- + +\`id:ROUTE_ID\` flag cannot be used since it's already used by this component internally`; + +exports.html = `
+
+ +
+ +
+
+
@(HTTP method)
+
+
+
@(URL address)
+
+
+
+
+
@(Additional flags)
+
@(Separate flags by comma e.g. json, authorize)
+
+
+
@(Max. request size)
+
@(In kB kilobytes)
+
+
+
@(Timeout)
+
@(In seconds.)
+
+
+
+
+
+
@(Automatically respond with 200 OK?)
+
@(If not checked you need to use HTTP response component to respond to the request.)
+
+
@(Custom headers)
+
@(Cookies)
+
+
+
+
+
+
@(Cache policy)
+
@(User instance must contain id property.)
+
+
+
@(Expiration)
+
@(E.g. 5 minutes)
+
+
+
+`; + +exports.install = function(instance) { + + var route; + + var uninstall = function(id) { + if (F.is4) { + route && route.remove(); + route = null; + } else + UNINSTALL('route', id); + }; + + instance.custom.emptyresponse = function(self) { + self.plain(); + }; + + instance.reconfigure = function() { + + var options = instance.options; + + if (!options.url) { + instance.status('Not configured', 'red'); + return; + } + + if (typeof(options.flags) === 'string') + options.flags = options.flags.split(',').trim(); + + uninstall('id:' + instance.id); + + var flags = options.flags || []; + + flags.push('id:' + instance.id); + + if (!F.is4) + flags.push(options.method.toLowerCase()); + + options.timeout && flags.push(options.timeout * 1000); + + // Make unique values + flags = flags.filter(function(v, i, a) { + if(F.is4 && v.toString().toLowerCase() === options.method.toLowerCase()) + return false; // remove method + return a.indexOf(v) === i; + }); + + options.flags = flags; + var handler = function() { + + if (instance.paused || (instance.isDisabled && (instance.isDisabled('output', 0) || instance.isDisabled('output', 1)))) { + instance.status('503 Service Unavailable'); + this.status = 503; + this.json(); + return; + } + + var key; + var self = this; + + if (instance.options.emptyresponse) { + instance.status('200 OK'); + setTimeout(instance.custom.emptyresponse, 100, self); + + if (instance.hasConnection(0)) { + var data = instance.make({ + query: self.query, + body: self.body, + session: self.session, + user: self.user, + files: self.files, + headers: self.req.headers, + url: self.url, + params: self.params + }); + instance.send2(0, data); + } + + return; + } + + switch (instance.options.cachepolicy) { + case 1: // URL + key = 'rro' + instance.id + self.url.hash(); + break; + case 2: // URL + query + case 3: // URL + query + user + key = self.url; + var keys = Object.keys(self.query); + keys.sort(); + for (var i = 0, length = keys.length; i < length; i++) + key += keys[i] + self.query[keys[i]] + '&'; + if (instance.options.cachepolicy === 3 && self.user) + key += 'iduser' + self.user.id; + key = 'rro' + instance.id + key.hash(); + break; + } + + if (key && F.cache.get2(key)) { + var data = instance.make(F.cache.get2(key)); + data.repository.controller = self; + instance.send2(1, data); + } else { + + var data = instance.make({ + query: self.query, + body: self.body, + session: self.session, + user: self.user, + files: self.files, + headers: self.req.headers, + url: self.url, + params: self.params, + mobile: self.mobile, + robot: self.robot, + referrer: self.referrer, + language: self.language + }); + + data.repository.controller = self; + instance.send2(0, data); + key && FINISHED(self.res, () => F.cache.set(key, self.$flowdata.data, instance.options.cacheexpire)); + } + }; + + if (F.is4) + route = ROUTE(options.method.toUpperCase() + ' ' + options.url, handler, flags, options.size || 5); + else + F.route(options.url, handler, flags, options.size || 5); + + instance.status('Listening', 'green'); + }; + + instance.reconfigure(); + instance.on('options', instance.reconfigure); + instance.on('close', function(){ + uninstall('id:' + instance.id); + }); +}; + +// check url exists +FLOW.trigger('httproutecheckurl', function(next, data) { + var url = data.url; + var method = data.method; + if (url[url.length - 1] !== '/') + url += '/'; + var exists = F.routes.web.findItem(r => r.urlraw === url && r.method === method); + next(exists != null); +}); + +exports.uninstall = function() { + FLOW.trigger('httproutecheckurl', null); +}; diff --git a/RVO14/flow/infosender.js b/RVO14/flow/infosender.js new file mode 100755 index 0000000..587724f --- /dev/null +++ b/RVO14/flow/infosender.js @@ -0,0 +1,81 @@ +exports.id = 'infosender'; +exports.title = 'Info sender'; +exports.version = '1.0.0'; +exports.group = 'Worksys'; +exports.color = '#2134B0'; +exports.input = 2; +exports.output = 1 +exports.icon = 'bolt'; + +const { networkInterfaces } = require('os'); + +exports.html = `
+
+
+
CSV Import
+
+
+
`; + +exports.readme = `# send all data to projects.worksys.io, required to monitor status of controller(unipi)`; + +exports.install = function(instance) { + + let id; + let allValues = {}; + let sendAllValuesInterval; + let configured = false; + + let now = new Date(); + console.log(exports.title, "INSTALLED", now.toLocaleString("sk-SK")); + + const nets = networkInterfaces(); + let ipAddresses = Object.create(null); // Or just '{}', an empty object + + for (const name of Object.keys(nets)) { + for (const net of nets[name]) { + // Skip over non-IPv4 and internal (i.e. 127.0.0.1) addresses + if (net.family === 'IPv4' && !net.internal) { + if (!ipAddresses[name]) { + ipAddresses[name] = []; + } + ipAddresses[name].push(net.address); + } + } + } + + function sendValues() { + if (!configured) return; + + if (Object.keys(allValues).length > 0) { + let dataToSend = { ...allValues }; + dataToSend.id = id; + dataToSend.ipAddresses = ipAddresses; + + instance.send(0, dataToSend); + + allValues = {}; + } + } + + instance.on("close", () => { + clearInterval(sendAllValuesInterval); + }) + + instance.on("0", _ => { + id = FLOW.GLOBALS.settings.project_id; + if (id) configured = true; + else console.log(exports.title, "InfoSender: Unable to send data, no id"); + }) + + instance.on("1", flowdata => { + allValues = { ...allValues, ...flowdata.data }; + //console.log("DATA RECEIVED", flowdata.data); + }) + + sendAllValuesInterval = setInterval(() => { + sendValues(); + }, 60000 * 3); + +} + diff --git a/RVO14/flow/modbus_reader.js b/RVO14/flow/modbus_reader.js new file mode 100755 index 0000000..d6d9dad --- /dev/null +++ b/RVO14/flow/modbus_reader.js @@ -0,0 +1,346 @@ +exports.id = 'modbus_reader'; +exports.title = 'Modbus reader'; +exports.version = '2.0.0'; +exports.group = 'Worksys'; +exports.color = '#2134B0'; +exports.input = 1; +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; +//number of phases inRVO +let phases; +//phases where voltage is 0 (set) +let noVoltage; +let energyToSwitchLamps; + +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.phases = this.buildPhases(); + + this.startSocket(); + } + + buildPhases = () => { + let a = []; + for (let i = 1; i <= phases; i++) { + a.push(`Phase_${i}_voltage`) + } + return a; + } + + startSocket = () => { + + let obj = this; + + if (this.socket) { + this.socket.removeAllListeners(); + this.socket = null; + } + + 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('Modbus_reader: Socket connection error', e); //'ECONNREFUSED' or 'ECONNRESET' ?? + }); + + this.socket.on('close', function() { + console.log('Modbus_reader: Socket connection closed - Waiting 10 seconds before connecting 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 we just start to loop devices from the beginning, or there is just 1 device in config, we wait whole timeoutInterval + if (this.indexInDeviceConfig == 0 || deviceConfig.length === 1) 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 (this.phases.includes(singleValue)) { + let l = singleValue.split("_"); + let phase = parseInt(l[1]); + + // console.log(values[singleValue], tbName); + + if (values[singleValue] == 0) { + noVoltage.add(phase); + sendNotification("modbus_reader: checkNullVoltage", tbName, "no_voltage_on_phase", { phase: phase }, "", SEND_TO.tb, instance, "voltage" + phase); + // console.log('no voltage') + } + else { + noVoltage.delete(phase); + // console.log('voltage detected') + sendNotification("modbus_reader: checkNullVoltage", tbName, "voltage_on_phase_restored", { phase: phase }, "", SEND_TO.tb, instance, "voltage" + phase); + } + } + }) + } + + /** + * function sends notification to slack and to tb, if EM total_power value changes more than numberOfNodes*15. This should show, that RVO lamps has been switched on or off + */ + lampSwitchNotification = (values) => { + + if (!values.hasOwnProperty("total_power")) return; + + const actualTotalPower = values.total_power; + + if (actualTotalPower > energyToSwitchLamps && 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 <= energyToSwitchLamps && 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; + } + + function main() { + + phases = FLOW.GLOBALS.settings.phases; + tbName = FLOW.GLOBALS.settings.rvoTbName; + noVoltage = FLOW.GLOBALS.settings.no_voltage; + energyToSwitchLamps = FLOW.GLOBALS.settings.energy_to_switch_lamps / 2.5; //half value is enought to show if lamps are turned on or off + if (deviceConfig.length) mainSocket = new SocketWithClients(); + else console.log("Modbus_reader: no modbus device in configuration"); + + // this notification is to show, that flow (unipi) has been restarted + sendNotification("modbus_reader", tbName, "flow_restart", {}, "", SEND_TO.slack, instance); + } + + instance.on("0", function(_) { + main(); + }) + +} + diff --git a/RVO14/flow/monitorconsumption.js b/RVO14/flow/monitorconsumption.js new file mode 100755 index 0000000..64cc58e --- /dev/null +++ b/RVO14/flow/monitorconsumption.js @@ -0,0 +1,156 @@ +exports.id = 'monitorconsumption'; +exports.title = 'Consumption'; +exports.version = '1.0.0'; +exports.author = 'Peter Širka'; +exports.group = 'Monitoring'; +exports.color = '#967ADC'; +exports.input = 0; +exports.output = 1; +exports.icon = 'bug'; +exports.options = { interval: 5000, enabled: true, monitorconsumption: true, monitorsize: true, monitorconnections: true, monitorfiles: true }; +exports.click = true; +exports.readme = `# Consumption monitoring + +This component measure CPU and memory consumption, open files and open connections of this application. It uses these Linux commands: \`ps\`, \`lsof\`, \`netstat\` and \`df\`. + +__Data Example__: + +\`\`\`javascript +{ + cpu: 0, // percentage + memory: 4096, // in bytes + size: 34303, // directory size in bytes + files: 34, // count of open files + connections: 343, // count of connections + uptime: '1-12:34:00' +} +\`\`\``; + +exports.html = `
+
+
+
@(Interval in milliseconds)
+
+
+
+
Monitor: Consumption + uptime
+
Monitor: Count of open files
+
Monitor: Count of open connections
+
Monitor: Directory size
+
`; + +exports.install = function(instance) { + + var current = { cpu: 0, memory: 0, files: 0, connections: 0, size: 0, uptime: '', counter: 0 }; + var tproc = null; + var Exec = require('child_process').exec; + var reg_empty = /\s{2,}/g; + var reg_appdisksize = /^[\d.,]+/; + + instance.custom.run = function() { + + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + + var arr = []; + + // Get CPU and Memory consumption + instance.options.monitorconsumption && arr.push(function(next) { + Exec('ps -p {0} -o %cpu,rss,etime'.format(process.pid), function(err, response) { + + if (err) { + instance.throw(err); + } else { + var line = response.split('\n')[1]; + line = line.trim().replace(reg_empty, ' ').split(' '); + var cpu = line[0].parseFloat(); + current.cpu = cpu.floor(1); + current.memory = line[1].parseInt2() * 1024; // kB to bytes + current.uptime = line[2]; + } + + next(); + }); + }); + + // Get count of open files + instance.options.monitorfiles && arr.push(function(next) { + Exec('lsof -a -p {0} | wc -l'.format(process.pid), function(err, response) { + if (err) + instance.throw(err); + else + current.files = response.trim().parseInt2(); + next(); + }); + }); + + // Get count of opened network connections + instance.options.monitorconnections && arr.push(function(next) { + Exec('netstat -an | grep :{0} | wc -l'.format(F.port), function(err, response) { + if (err) { + instance.throw(err); + } else { + current.connections = response.trim().parseInt2() - 1; + if (current.connections < 0) + current.connections = 0; + } + next(); + }); + }); + + // Get directory size + instance.options.monitorsize && current.counter % 5 !== 0 && arr.push(function(next) { + Exec('du -hsb ' + process.cwd(), function(err, response) { + if (err) { + instance.throw(err); + } else { + var match = response.trim().match(reg_appdisksize); + match && (current.size = match.toString().trim().parseInt2()); + } + next(); + }); + }); + + arr.async(function() { + + tproc && clearTimeout(tproc); + + if (instance.options.enabled) { + tproc = setTimeout(instance.custom.run, instance.options.interval); + instance.send2(current); + } + + instance.custom.status(); + current.counter++; + }); + }; + + instance.custom.status = function() { + if (instance.options.enabled) + instance.status('{0}% / {1}'.format(current.cpu, current.memory.filesize())); + else + instance.status('Disabled', 'red'); + }; + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + + if (instance.options.enabled) { + current.counter = 0; + instance.custom.run(); + } + + }); + + instance.on('close', function() { + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + }); + + setTimeout(instance.custom.run, 1000); +}; \ No newline at end of file diff --git a/RVO14/flow/monitordisk.js b/RVO14/flow/monitordisk.js new file mode 100755 index 0000000..f4fdaa0 --- /dev/null +++ b/RVO14/flow/monitordisk.js @@ -0,0 +1,96 @@ +exports.id = 'monitordisk'; +exports.title = 'Disk'; +exports.version = '1.0.0'; +exports.author = 'Peter Širka'; +exports.group = 'Monitoring'; +exports.color = '#F6BB42'; +exports.output = 1; +exports.icon = 'hdd-o'; +exports.click = true; +exports.options = { interval: 8000, path: '/', enabled: true }; +exports.readme = `# Disk monitoring + +This component monitors disk \`bytes\` consumption in Linux systems. It uses \`df\` command. + +__Data Example__: + +\`\`\`javascript +{ + total: 474549649408, + used: 39125245952, + free: 411294994432 +} +\`\`\``; + +exports.html = `
+
+
+
@(Interval in milliseconds)
+
+
+
@(Path)
+
+
+
`; + +exports.install = function(instance) { + + var current = { total: 0, used: 0, free: 0, path: '', type: '', percentUsed: 0 }; + var tproc = null; + + instance.custom.run = function() { + + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + + if (!instance.options.enabled) + return; + + require('child_process').exec('df -hTB1 ' + instance.options.path, function(err, response) { + + tproc = setTimeout(instance.custom.run, instance.options.interval); + + if (err) { + instance.error(err); + return; + } + + response.parseTerminal(function(line) { + if (line[0][0] !== '/') + return; + current.total = line[2].parseInt(); + current.free = line[4].parseInt(); + current.used = line[3].parseInt(); + current.path = instance.options.path || '/'; + current.type = line[1]; + current.percentUsed = line[5]; + instance.custom.status(); + instance.send2(current); + }); + }); + }; + + instance.custom.status = function() { + if (instance.options.enabled) + instance.status(current.free.filesize() + ' / ' + current.total.filesize()); + else + instance.status('Disabled', 'red'); + }; + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + instance.options.enabled && instance.custom.run(); + }); + + instance.on('close', function() { + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + }); + + setTimeout(instance.custom.run, 1000); +}; \ No newline at end of file diff --git a/RVO14/flow/monitormemory.js b/RVO14/flow/monitormemory.js new file mode 100755 index 0000000..2decbc4 --- /dev/null +++ b/RVO14/flow/monitormemory.js @@ -0,0 +1,87 @@ +exports.id = 'monitormemory'; +exports.title = 'Memory'; +exports.version = '1.0.0'; +exports.author = 'Peter Širka'; +exports.group = 'Monitoring'; +exports.color = '#F6BB42'; +exports.output = 1; +exports.click = true; +exports.icon = 'microchip'; +exports.options = { interval: 8000, enabled: true }; +exports.readme = `# Memory monitoring + +This component monitors memory \`bytes\` consumption in Linux systems. It uses \`free\` command. + +__Data Example__: + +\`\`\`javascript +{ + total: 33558769664, + used: 1998868480, + free: 2653708288 +} +\`\`\``; + +exports.html = `
+
+
+
@(Interval in milliseconds)
+
+
+
`; + +exports.install = function(instance) { + + var current = { total: 0, used: 0, free: 0 }; + var tproc = null; + + instance.custom.run = function() { + + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + + if (!instance.options.enabled) + return; + + require('child_process').exec('free -b -t', function(err, response) { + + tproc = setTimeout(instance.custom.run, instance.options.interval); + + if (err) { + instance.error(err); + return; + } + + var memory = response.split('\n')[1].match(/\d+/g); + current.total = memory[0].parseInt(); + current.used = memory[1].parseInt() - memory[3].parseInt(); + current.free = current.total - current.used; + instance.custom.status(); + instance.send2(current); + }); + }; + + instance.custom.status = function() { + if (instance.options.enabled) + instance.status(current.free.filesize() + ' / ' + current.total.filesize()); + else + instance.status('Disabled', 'red'); + }; + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + instance.options.enabled && instance.custom.run(); + }); + + instance.on('close', function() { + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + }); + + setTimeout(instance.custom.run, 1000); +}; \ No newline at end of file diff --git a/RVO14/flow/nodesdb_changecheck.js b/RVO14/flow/nodesdb_changecheck.js new file mode 100755 index 0000000..9adab62 --- /dev/null +++ b/RVO14/flow/nodesdb_changecheck.js @@ -0,0 +1,77 @@ +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 = 2; +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); + } + } + + //kedze do slacku posielame stringy, na cloud musime previest vsetky stringy spat na objekty: + // Funkcia na parsovanie všetkých reťazcov v poli + const parseArray = (arr) => { + return arr.map(jsonString => JSON.parse(jsonString)); + }; + + 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); + if (FLOW.GLOBALS.settings.send_changed_node_numbers) instance.send(1, { aktualneNody: parseArray(zmenene), originalne: parseArray(Array.from(set2)) }); + } + 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/RVO14/flow/show_dbdata.js b/RVO14/flow/show_dbdata.js new file mode 100755 index 0000000..1e23ff7 --- /dev/null +++ b/RVO14/flow/show_dbdata.js @@ -0,0 +1,243 @@ +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 = 8; +exports.output = 1; + +const { exec } = require('child_process'); + +exports.install = 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 }) + }) + instance.on("5", _ => { + exec("sudo tail -n 25 monitor.txt", (err, stdout, stderr) => { + if (err || stderr) instance.send(0, { err, stderr }); + else instance.send(0, stdout); + }) + }) + instance.on("6", _ => { + exec("sudo tail -n 25 err.txt", (err, stdout, stderr) => { + if (err || stderr) instance.send(0, { err, stderr }); + else instance.send(0, stdout); + }) + }) + instance.on("7", _ => { + instance.send(0, FLOW.deviceStatus); + }) +}; + + +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/RVO14/flow/slack_filter.js b/RVO14/flow/slack_filter.js new file mode 100755 index 0000000..6618523 --- /dev/null +++ b/RVO14/flow/slack_filter.js @@ -0,0 +1,188 @@ +exports.id = 'slack_filter'; +exports.title = 'Slack Filter'; +exports.group = 'Citysys'; +exports.color = '#30E193'; +exports.input = 2; +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 = `
+
+
+
@(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('0', 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']['en']; + 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"] = []; + } + + instance.options.name = FLOW.GLOBALS.settings.rvo_name; + if (instance.options.name) { + instance.status('Running'); + running = true; + } else { + instance.status('Please run options again', 'red'); + running = false; + } + } catch (e) { + instance.error('Citysys connector: ' + e.message); + } + }; + + instance.on('options', instance.reconfigure); + + instance.on("1", _ => { + instance.reconfigure(); + }) +}; diff --git a/RVO14/flow/thermometer.js b/RVO14/flow/thermometer.js new file mode 100755 index 0000000..fc7074d --- /dev/null +++ b/RVO14/flow/thermometer.js @@ -0,0 +1,99 @@ +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 = 5;//minutes +let NUMBER_OF_FAILURES_TO_SEND_ERROR = 13; + +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) => { + + 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); + setTimeout(main, 20000); + }) +}; diff --git a/RVO14/flow/trigger.js b/RVO14/flow/trigger.js new file mode 100755 index 0000000..27545a8 --- /dev/null +++ b/RVO14/flow/trigger.js @@ -0,0 +1,79 @@ +exports.id = 'trigger'; +exports.title = 'Trigger'; +exports.group = 'Inputs'; +exports.color = '#F6BB42'; +exports.click = true; +exports.output = 1; +exports.version = '1.1.0'; +exports.author = 'Martin Smola'; +exports.icon = 'play'; + +exports.html = `
+
@(Data type (String by default))
+
@(Data)
+
Trigger 5s after initialization.
+
@(Useful when there's a need to run certain flow when the app restarts, etc.)
+
`; + +exports.readme = `# Trigger + +- Clicking on the component starts the chain +- Settings allows to set a data-type and a value`; + +exports.install = function(instance) { + + var value; + + instance.on('click', () => instance.send2(value)); + + instance.reconfigure = function() { + var options = instance.options; + value = null; + switch (options.datatype) { + case 'integer': + value = options.data.parseInt2('error'); + value = value === 'error' ? NaN : value; + break; + case 'float': + value = options.data.parseFloat2('error'); + value = value === 'error' ? NaN : value; + break; + case 'date': + options.data = options.data.toString(); + var num = options.data.parseInt('error'); + num === 'error' && (num = options.data.parseDate('error')); + num === 'error' && (num = null); + value = num ? new Date(num).toUTCString() : num; + break; + case 'object': + try { + value = (new Function('return ' + options.data))(); + } catch (e) { + instance.error(e); + } + break; + case 'boolean': + value = options.data.parseBoolean(); + break; + case 'buffer': + try { + value = U.createBuffer(options.data); + } catch (e) { + instance.error(e); + } + break; + case 'string': + default: + value = '' + (options.data || ''); + break; + } + }; + + instance.on('options', instance.reconfigure); + instance.reconfigure(); + + if (instance.options.restart) + setTimeout(function(){ + instance.send2(value); + }, 5000); +}; diff --git a/RVO14/flow/variables.txt b/RVO14/flow/variables.txt new file mode 100755 index 0000000..e69de29 diff --git a/RVO14/flow/virtualwirein.js b/RVO14/flow/virtualwirein.js new file mode 100755 index 0000000..38a4e42 --- /dev/null +++ b/RVO14/flow/virtualwirein.js @@ -0,0 +1,43 @@ +exports.id = 'virtualwirein'; +exports.title = 'Virtual wire in'; +exports.version = '1.0.0'; +exports.author = 'Martin Smola'; +exports.color = '#303E4D'; +exports.icon = 'sign-in'; +exports.input = false; +exports.output = 1; +exports.options = {}; +exports.readme = `# Virtual wire in + +When the wires between the components are mess it's time to use Virtual wire.`; + +exports.html = `
+
@(Wire name)
+
+`; + +exports.install = function(instance) { + + instance.custom.reconfigure = function(options){ + if (instance.options.wirename) { + instance.status(instance.options.wirename); + } else + instance.status('Not configured', 'red'); + }; + + ON('virtualwire', function(wirename, flowdata){ + if (instance.options.wirename && instance.options.wirename === wirename) + instance.send(flowdata); + }); + + instance.on('options', instance.custom.reconfigure); + instance.custom.reconfigure(); +}; diff --git a/RVO14/flow/virtualwireout.js b/RVO14/flow/virtualwireout.js new file mode 100755 index 0000000..94a1e4f --- /dev/null +++ b/RVO14/flow/virtualwireout.js @@ -0,0 +1,41 @@ +exports.id = 'virtualwireout'; +exports.title = 'Virtual wire out'; +exports.version = '1.0.0'; +exports.author = 'Martin Smola'; +exports.color = '#303E4D'; +exports.icon = 'sign-out'; +exports.input = true; +exports.options = {}; +exports.readme = `# Virtual wire out + +When the wires between the components are mess it's time to use Virtual wire.`; + +exports.html = `
+
@(Wire name)
+
+`; + +exports.install = function(instance) { + + instance.custom.reconfigure = function(){ + if (instance.options.wirename) { + instance.status(instance.options.wirename); + } else + instance.status('Not configured', 'red'); + }; + + instance.on('data', function(flowdata) { + EMIT('virtualwire', instance.options.wirename, flowdata); + }); + + instance.on('options', instance.custom.reconfigure); + instance.custom.reconfigure(); +}; diff --git a/RVO14/flow/wsmqttpublish.js b/RVO14/flow/wsmqttpublish.js new file mode 100755 index 0000000..0eba804 --- /dev/null +++ b/RVO14/flow/wsmqttpublish.js @@ -0,0 +1,448 @@ +exports.id = 'wsmqttpublish'; +exports.title = 'WS MQTT publish'; +exports.group = 'MQTT'; +exports.color = '#888600'; +exports.version = '1.0.2'; +exports.icon = 'sign-out'; +exports.input = 2; +exports.output = 3; +exports.options = { host: 'tb-stage.worksys.io', port: 1883, clientid: "", username: "" }; + +exports.html = `
+
+
+
Hostname or IP address (if not empty - setting will override db setting)
+
+
+
Port
+
+
+
+
+
@(Client id)
+
+
+
@(Username)
+
+
+
`; + + +exports.readme = ` +# WS MQTT Publish + +Version 1.0.3. + +Added: +- database collections, +- 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 = { + debug: 0, + rpcCall: 1, + services: 2 +} + +//CONFIG +let createTelemetryBackup = true; +let saveTelemetryOnError = true;//backup_on_failure overrides this value +//------------------------ + +let rollers; +if (createTelemetryBackup) rollers = require('streamroller'); + +const noSqlFileSizeLimit = 4194304;//use 5MB - 4194304 +let insertNoSqlCounter = 0; +let insertBackupNoSqlCounter = 0; +let processingData = false; + +let backup_on_failure = false;//== saveTelemetryOnError - create backup client 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; + +process.on('uncaughtException', function(err) { + + errLogger.error('uncaughtException:', err.message) + errLogger.error(err.stack); + + //TODO + //send to service + + //process.exit(1); +}) + +const nosql = NOSQL('tbdata'); +const nosqlBackup = NOSQL('/backup/tbdata'); + + +exports.install = function(instance) { + + var client; + var opts; + var clientReady = false; + + // wsmqtt status for notification purposes on projects.worksys.io database + let wsmqttName = null; + let sendWsStatusVar = null; + let wsmqtt_status = 'disconnected'; + + 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'; + } + + function sendWsStatus() { + instance.send(SEND_TO.services, { [wsmqttName]: wsmqtt_status }); + } + + + function main() { + if (!FLOW.dbLoaded) return; + + loadSettings(); + clearInterval(sendWsStatus); + sendWsStatusVar = setInterval(sendWsStatus, 180000); + } + + //set opts according to db settings + function loadSettings() { + + if (instance.options.host !== "") { + //override settings from database + var o = instance.options; + opts = { + host: o.host, + port: o.port, + clientId: o.clientid, + username: o.username, + rejectUnauthorized: false, + resubscribe: false + }; + + wsmqttName = getWsmqttName(o.host); + + console.log("wsmqttpublich -> loadSettings from instance.options", instance.options); + } + else { + + const SETTINGS = FLOW.GLOBALS.settings; + backup_on_failure = SETTINGS.backup_on_failure; + saveTelemetryOnError = backup_on_failure; + + restore_from_backup = SETTINGS.restore_from_backup; + restore_backup_wait = SETTINGS.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; + + opts = { + host: mqtt_host, + port: mqtt_port, + keepalive: 10, + clientId: mqtt_clientid, + username: mqtt_username, + rejectUnauthorized: false, + resubscribe: false + }; + + wsmqttName = getWsmqttName(mqtt_host); + } + + connectToTbServer(); + } + + function connectToTbServer() { + 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"); + //monitor.info("MQTT client connected"); + + sendClientError = true; + clientReady = true; + wsmqtt_status = 'connected'; + }); + + client.on('reconnect', function() { + instance.status("Reconnecting", "yellow"); + clientReady = false; + }); + + client.on('message', function(topic, message) { + // message is type of buffer + message = message.toString(); + if (message[0] === '{') { + TRY(function() { + + message = JSON.parse(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 } }); + } + + }, () => instance.debug('MQTT: Error parsing data', message)); + } + + instance.send(SEND_TO.rpcCall, { "topic": topic, "content": message }); + }); + + client.on('close', function() { + clientReady = false; + wsmqtt_status = 'disconnected'; + + instance.status("Disconnected", "red"); + instance.send(SEND_TO.debug, { "message": "Client CLOSE signal received !" }); + }); + + client.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; + wsmqtt_status = 'disconnected'; + }); + + } + + + instance.on("0", _ => { + main(); + }) + + + instance.on('1', function(data) { + + if (clientReady) { + //do we have some data in backup file? if any, process data from database + if (saveTelemetryOnError) { + //read telemetry data and send back to server + if (!processingData) processDataFromDatabase(); + } + + let stringifiedJson = JSON.stringify(data.data); + client.publish("v1/gateway/telemetry", stringifiedJson, { qos: 1 }); + + //backup telemetry + if (createTelemetryBackup) { + data.data.id = UID(); + nosqlBackup.insert(data.data); + + insertBackupNoSqlCounter++; + if (insertBackupNoSqlCounter > 150) { + let options = { compress: true }; + let path = __dirname + "/../databases/backup/tbdata.nosql"; + var stream = new rollers.RollingFileStream(path, noSqlFileSizeLimit, 150, options); + stream.write(""); + stream.end(); + + insertBackupNoSqlCounter = 0; + } + } + + } + 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 (saveTelemetryOnError) { + //create new file from tbdata.nosql, if file size exceeds given limit, and clear tbdata.nosql + makeBackupFromDbFile(); + + //write to tb + data.data.id = UID(); + nosql.insert(data.data); + } + } + }); + + + instance.close = function(done) { + if (clientReady) { + client.end(); + clearInterval(sendWsStatusVar); + } + }; + + + function getDbBackupFileCounter(type) { + var files = fs.readdirSync(__dirname + "/../databases"); + + let counter = 0; + for (var i = 0; i < files.length; i++) { + + if (files[i] == "tbdata.nosql") continue; + + if (files[i].endsWith(".nosql")) { + + let pos = files[i].indexOf("."); + if (pos > -1) { + + let fileCounter = counter; + let firstDigit = files[i].slice(0, pos); + + fileCounter = parseInt(firstDigit); + if (isNaN(fileCounter)) fileCounter = 0; + //console.log("getDbBackupFileCounter digit:", files[i], firstDigit, fileCounter, isNaN(fileCounter), type); + + if (type == "max") { + if (fileCounter > counter) { + counter = fileCounter; + } + } + else if (type == "min") { + if (counter == 0) counter = fileCounter; + + if (fileCounter < counter) { + counter = fileCounter; + } + } + } + } + + } + + if (type == "max") counter++; + + return counter; + } + + const makeBackupFromDbFile = async () => { + + if (!saveTelemetryOnError) return; + + //to avoid large file: tbdata.nosql + + //init value is 0! + if (insertNoSqlCounter > 0) { + --insertNoSqlCounter; + return; + } + + insertNoSqlCounter = 100; + + let source = __dirname + "/../databases/tbdata.nosql"; + + var stats = fs.statSync(source); + var fileSizeInBytes = stats.size; + + if (fileSizeInBytes > noSqlFileSizeLimit) { + + let counter = 1; + counter = getDbBackupFileCounter("max"); + + let destination = __dirname + "/../databases/" + counter + "." + "tbdata.nosql"; + + //make backup file + fs.copyFileSync(source, destination); + //fs.renameSync(p, p + "." + counter); + + //clear tbdata.nosql + fs.writeFileSync(source, ""); + fs.truncateSync(source, 0); + + } + } + + const processDataFromDatabase = async () => { + + if (restore_from_backup <= 0) return; + + //calculate diff + const now = new Date(); + let currentTime = now.getTime(); + let diff = currentTime - lastRestoreTime; + + if ((diff / 1000) < restore_backup_wait) { + //console.log("*********restore_backup_wait", diff, restore_backup_wait); + return; + } + + processingData = true; + + //get filename to process + let counter = getDbBackupFileCounter("min"); + + //we have some backup files + let dataBase = 'tbdata'; + + var nosql; + if (counter == 0) dataBase = 'tbdata'; + else dataBase = counter + "." + 'tbdata'; + + nosql = NOSQL(dataBase); + + //select all data - use limit restore_from_backup + let records = await promisifyBuilder(nosql.find().take(restore_from_backup)); + + for (let i = 0; i < records.length; i++) { + if (clientReady) { + + let item = records[i]; + let id = item.id; + + if (id !== undefined) { + //console.log("------------processDataFromDatabase - remove", id, dataBase, i); + + try { + + let message = JSON.parse(JSON.stringify(item)); + delete message.id; + + client.publish("v1/gateway/telemetry", JSON.stringify(message), { qos: 1 }); + + //remove from database + await promisifyBuilder(nosql.remove().where("id", id)); + + } catch (error) { + //process error + console.log("processDataFromDatabase", error); + } + + } + + } + else { + processingData = false; + return; + } + } + + if (records.length > 0) { + //clean backup file + if (counter > 0) nosql.clean(); + } + + //no data in db, remove + if (records.length == 0) { + if (counter > 0) nosql.drop(); + } + + const d = new Date(); + lastRestoreTime = d.getTime(); + + processingData = false; + + } + + instance.on('options', main); + //instance.reconfigure(); +}; diff --git a/RVO14/monitor.txt b/RVO14/monitor.txt new file mode 100755 index 0000000..b7f563b --- /dev/null +++ b/RVO14/monitor.txt @@ -0,0 +1,195 @@ +[2025-10-09T16:47:39.501] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-09T16:47:44.840] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-09T16:47:44.845] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-09T16:47:44.846] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-09T16:47:44.846] [INFO] monitorLogs - 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 +} +[2025-10-09T16:47:44.849] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T16:47:44.851] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-10-10T11:00:00.850Z +[2025-10-09T16:47:44.852] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-09T16:47:44.853] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-10-09T16:47:44.854] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-09T16:47:44.854] [INFO] monitorLogs - 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 +} +[2025-10-09T16:47:44.856] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T16:47:44.856] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-10-10T11:00:00.856Z +[2025-10-09T16:47:44.857] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-09T16:47:44.858] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-10-09T16:47:44.859] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-09T16:47:44.859] [INFO] monitorLogs - 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 +} +[2025-10-09T16:47:44.861] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T16:47:44.862] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-10-10T11:00:00.861Z +[2025-10-09T16:47:44.862] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-09T16:47:44.863] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-10-09T16:47:44.866] [INFO] monitorLogs - tasks created: 165 +[2025-10-09T16:47:44.869] [INFO] monitorLogs - -->FLOW bol spustený Nzp2OoJlqn6r1ZgvdA3B1j7abBwP5G4eE3RQmyxD 2025-08-08 +[2025-10-09T16:47:49.871] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-09T18:59:44.529] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-09T18:59:49.873] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-09T18:59:49.878] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-09T18:59:49.879] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-09T18:59:49.880] [INFO] monitorLogs - 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 +} +[2025-10-09T18:59:49.882] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T18:59:49.884] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-10-10T11:00:00.883Z +[2025-10-09T18:59:49.885] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-09T18:59:49.886] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-10-09T18:59:49.887] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-09T18:59:49.888] [INFO] monitorLogs - 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 +} +[2025-10-09T18:59:49.889] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T18:59:49.890] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-10-10T11:00:00.890Z +[2025-10-09T18:59:49.891] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-09T18:59:49.892] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-10-09T18:59:49.892] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-09T18:59:49.893] [INFO] monitorLogs - 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 +} +[2025-10-09T18:59:49.894] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T18:59:49.895] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-10-10T11:00:00.895Z +[2025-10-09T18:59:49.896] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-09T18:59:49.897] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-10-09T18:59:49.899] [INFO] monitorLogs - tasks created: 165 +[2025-10-09T18:59:49.901] [INFO] monitorLogs - -->FLOW bol spustený Nzp2OoJlqn6r1ZgvdA3B1j7abBwP5G4eE3RQmyxD 2025-08-08 +[2025-10-09T18:59:54.904] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-10T03:59:52.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-10 03:59:52 +[2025-10-11T03:59:53.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-11 03:59:53 +[2025-10-12T03:59:54.015] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-12 03:59:54 +[2025-10-13T03:59:55.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-13 03:59:55 +[2025-10-14T03:59:57.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-14 03:59:57 +[2025-10-15T03:59:58.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-15 03:59:58 +[2025-10-15T14:15:30.155] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-15T14:15:35.494] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-15T14:15:35.498] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-15T14:15:35.500] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-15T14:15:35.500] [INFO] monitorLogs - 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 +} +[2025-10-15T14:15:35.503] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-15T14:15:35.504] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-10-16T11:00:00.503Z +[2025-10-15T14:15:35.506] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-15T14:15:35.507] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-10-15T14:15:35.507] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-15T14:15:35.508] [INFO] monitorLogs - 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 +} +[2025-10-15T14:15:35.510] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-15T14:15:35.510] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-10-16T11:00:00.510Z +[2025-10-15T14:15:35.511] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-15T14:15:35.512] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-10-15T14:15:35.513] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-15T14:15:35.513] [INFO] monitorLogs - 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 +} +[2025-10-15T14:15:35.515] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-15T14:15:35.515] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-10-16T11:00:00.515Z +[2025-10-15T14:15:35.516] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-15T14:15:35.517] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-10-15T14:15:35.519] [INFO] monitorLogs - tasks created: 165 +[2025-10-15T14:15:35.521] [INFO] monitorLogs - -->FLOW bol spustený Nzp2OoJlqn6r1ZgvdA3B1j7abBwP5G4eE3RQmyxD 2025-10-08 +[2025-10-15T14:15:40.530] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu diff --git a/RVO14/package-lock.json b/RVO14/package-lock.json new file mode 100755 index 0000000..cc5cfd9 --- /dev/null +++ b/RVO14/package-lock.json @@ -0,0 +1,2125 @@ +{ + "name": "emptyproject", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "emptyproject", + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "bitwise": "^2.1.0", + "easy-crc": "0.0.2", + "jsmodbus": "^4.0.6", + "log4js": "^6.3.0", + "mqtt": "^4.2.6", + "nodemailer": "^6.9.7", + "serialport": "^9.2.8", + "total.js": "^3.4.13" + } + }, + "node_modules/@serialport/binding-abstract": { + "version": "9.2.3", + "resolved": "https://registry.npmjs.org/@serialport/binding-abstract/-/binding-abstract-9.2.3.tgz", + "integrity": "sha512-cQs9tbIlG3P0IrOWyVirqlhWuJ7Ms2Zh9m2108z6Y5UW/iVj6wEOiW8EmK9QX9jmJXYllE7wgGgvVozP5oCj3w==", + "dependencies": { + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/binding-mock": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/binding-mock/-/binding-mock-9.2.4.tgz", + "integrity": "sha512-dpEhACCs44oQhh6ajJfJdvQdK38Vq0N4W6iD/gdplglDCK7qXRQCMUjJIeKdS/HSEiWkC3bwumUhUufdsOyT4g==", + "dependencies": { + "@serialport/binding-abstract": "9.2.3", + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/bindings": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/@serialport/bindings/-/bindings-9.2.8.tgz", + "integrity": "sha512-hSLxTe0tADZ3LMMGwvEJWOC/TaFQTyPeFalUCsJ1lSQ0k6bPF04JwrtB/C81GetmDBTNRY0GlD0SNtKCc7Dr5g==", + "hasInstallScript": true, + "dependencies": { + "@serialport/binding-abstract": "9.2.3", + "@serialport/parser-readline": "9.2.4", + "bindings": "^1.5.0", + "debug": "^4.3.2", + "nan": "^2.15.0", + "prebuild-install": "^7.0.0" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-byte-length": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-byte-length/-/parser-byte-length-9.2.4.tgz", + "integrity": "sha512-sQD/iw4ZMU3xW9PLi0/GlvU6Y623jGeWecbMkO7izUo/6P7gtfv1c9ikd5h0kwL8AoAOpQA1lxdHIKox+umBUg==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-cctalk": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-cctalk/-/parser-cctalk-9.2.4.tgz", + "integrity": "sha512-T4TU5vQMwmo9AB3gQLFDWbfJXlW5jd9guEsB/nqKjFHTv0FXPdZ7DQ2TpSp8RnHWxU3GX6kYTaDO20BKzc8GPQ==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-delimiter": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-delimiter/-/parser-delimiter-9.2.4.tgz", + "integrity": "sha512-4nvTAoYAgkxFiXrkI+3CA49Yd43CODjeszh89EK+I9c8wOZ+etZduRCzINYPiy26g7zO+GRAb9FoPCsY+sYcbQ==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-inter-byte-timeout": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-inter-byte-timeout/-/parser-inter-byte-timeout-9.2.4.tgz", + "integrity": "sha512-SOAdvr0oBQIOCXX198hiTlxs4JTKg9j5piapw5tNq52fwDOWdbYrFneT/wN04UTMKaDrJuEvXq6T4rv4j7nJ5A==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-readline": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-readline/-/parser-readline-9.2.4.tgz", + "integrity": "sha512-Z1/qrZTQUVhNSJP1hd9YfDvq0o7d87rNwAjjRKbVpa7Qi51tG5BnKt43IV3NFMyBlVcRe0rnIb3tJu57E0SOwg==", + "dependencies": { + "@serialport/parser-delimiter": "9.2.4" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-ready": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-ready/-/parser-ready-9.2.4.tgz", + "integrity": "sha512-Pyi94Itjl6qAURwIZr/gmZpMAyTmKXThm6vL5DoAWGQjcRHWB0gwv2TY2v7N+mQLJYUKU3cMnvnATXxHm7xjxw==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-regex": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-regex/-/parser-regex-9.2.4.tgz", + "integrity": "sha512-sI/cVvPOYz+Dbv4ZdnW16qAwvXiFf/1pGASQdbveRTlgJDdz7sRNlCBifzfTN2xljwvCTZYqiudKvDdC1TepRQ==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/stream": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/stream/-/stream-9.2.4.tgz", + "integrity": "sha512-bLye8Ub4vUFQGmkh8qEqehr7SE7EJs2yDs0h9jzuL5oKi+F34CFmWkEErO8GAOQ8YNn7p6b3GxUgs+0BrHHDZQ==", + "dependencies": { + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "node_modules/are-we-there-yet": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", + "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/base64-js": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", + "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==" + }, + "node_modules/bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "dependencies": { + "file-uri-to-path": "1.0.0" + } + }, + "node_modules/bitwise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/bitwise/-/bitwise-2.1.0.tgz", + "integrity": "sha512-XKgAhMXCh4H/3oNwAHAsAO0iC89s9cOiumgYwSHjSobGWxYjv62YhkL9QEdvGP151xypCtMlAfKK79GEcd2eRQ==" + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/bl/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/buffer": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz", + "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==", + "dependencies": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + }, + "node_modules/buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" + }, + "node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, + "node_modules/code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/commist": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/commist/-/commist-1.1.0.tgz", + "integrity": "sha512-rraC8NXWOEjhADbZe9QBNzLAN5Q3fsTPQtBV+fEVj6xKIgDgNiEVE6ZNfHpZOqfQ21YUzfVNUXLOEZquYvQPPg==", + "dependencies": { + "leven": "^2.1.0", + "minimist": "^1.1.0" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "node_modules/concat-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", + "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", + "engines": [ + "node >= 6.0" + ], + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.0.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/concat-stream/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" + }, + "node_modules/core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "node_modules/crc": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/crc/-/crc-3.4.0.tgz", + "integrity": "sha512-ycVC2+4/DLgXXq7QweYi2znhqDuZz6P5TQXnkQo8v15XY/5p/IWeZwsSE31Ifo8w15b8TWLsqhXOjXyilHuQxw==" + }, + "node_modules/date-format": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.11.tgz", + "integrity": "sha512-VS20KRyorrbMCQmpdl2hg5KaOUsda1RbnsJg461FfrcyCUg+pkd0b40BSW4niQyTheww4DBXQnS7HwSrKkipLw==", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" + }, + "node_modules/detect-libc": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz", + "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==", + "engines": { + "node": ">=8" + } + }, + "node_modules/duplexify": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.2.tgz", + "integrity": "sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw==", + "dependencies": { + "end-of-stream": "^1.4.1", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1", + "stream-shift": "^1.0.0" + } + }, + "node_modules/duplexify/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/easy-crc": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/easy-crc/-/easy-crc-0.0.2.tgz", + "integrity": "sha512-h6eqIdhJRe0p271/xZJbM/0klCi13mW5IB7ZEzEGH11yV4QXWAkD4yPErz0fXdhFrd6sZ4Q1k5Iky2kMsMNePw==" + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" + }, + "node_modules/flatted": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", + "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==" + }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, + "node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "node_modules/gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha512-14x4kjc6lkD3ltw589k0NrPD6cCNTD6CWoVUNpB85+DrtONoZn+Rug6xZU5RvSC4+TZPxA5AnBibQYAvZn41Hg==", + "dependencies": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "node_modules/github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==" + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" + }, + "node_modules/has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" + }, + "node_modules/help-me": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/help-me/-/help-me-3.0.0.tgz", + "integrity": "sha512-hx73jClhyk910sidBB7ERlnhMlFsJJIBqSVMFDwPN8o2v9nmp5KgLq1Xz1Bf1fCMMZ6mPrX159iG0VLy/fPMtQ==", + "dependencies": { + "glob": "^7.1.6", + "readable-stream": "^3.6.0" + } + }, + "node_modules/help-me/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, + "node_modules/is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==", + "dependencies": { + "number-is-nan": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "node_modules/js-sdsl": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz", + "integrity": "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/js-sdsl" + } + }, + "node_modules/jsmodbus": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/jsmodbus/-/jsmodbus-4.0.6.tgz", + "integrity": "sha512-gCmjoaERErK5Rn9Lu/BN07fY13MoWV7JKgGzrnkPlQPdPxYcwDhLtYcmpFFpZ4J9NPZZBSezi1UkLZO/DnNppA==", + "dependencies": { + "crc": "3.4.0", + "debug": "^3.1.0" + }, + "bin": { + "jsmodbus": "bin/jsmodbus.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/jsmodbus/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/leven": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", + "integrity": "sha1-wuep93IJTe6dNCAq6KzORoeHVYA=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/log4js": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.5.2.tgz", + "integrity": "sha512-DXtpNtt+KDOMT7RHUDIur/WsSA3rntlUh9Zg4XCdV42wUuMmbFkl38+LZ92Z5QvQA7mD5kAVkLiBSEH/tvUB8A==", + "dependencies": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "flatted": "^3.2.5", + "rfdc": "^1.3.0", + "streamroller": "^3.1.1" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" + }, + "node_modules/mqtt": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/mqtt/-/mqtt-4.3.7.tgz", + "integrity": "sha512-ew3qwG/TJRorTz47eW46vZ5oBw5MEYbQZVaEji44j5lAUSQSqIEoul7Kua/BatBW0H0kKQcC9kwUHa1qzaWHSw==", + "dependencies": { + "commist": "^1.0.0", + "concat-stream": "^2.0.0", + "debug": "^4.1.1", + "duplexify": "^4.1.1", + "help-me": "^3.0.0", + "inherits": "^2.0.3", + "lru-cache": "^6.0.0", + "minimist": "^1.2.5", + "mqtt-packet": "^6.8.0", + "number-allocator": "^1.0.9", + "pump": "^3.0.0", + "readable-stream": "^3.6.0", + "reinterval": "^1.1.0", + "rfdc": "^1.3.0", + "split2": "^3.1.0", + "ws": "^7.5.5", + "xtend": "^4.0.2" + }, + "bin": { + "mqtt": "bin/mqtt.js", + "mqtt_pub": "bin/pub.js", + "mqtt_sub": "bin/sub.js" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/mqtt-packet": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/mqtt-packet/-/mqtt-packet-6.10.0.tgz", + "integrity": "sha512-ja8+mFKIHdB1Tpl6vac+sktqy3gA8t9Mduom1BA75cI+R9AHnZOiaBQwpGiWnaVJLDGRdNhQmFaAqd7tkKSMGA==", + "dependencies": { + "bl": "^4.0.2", + "debug": "^4.1.1", + "process-nextick-args": "^2.0.1" + } + }, + "node_modules/mqtt/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/nan": { + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.16.0.tgz", + "integrity": "sha512-UdAqHyFngu7TfQKsCBgAA6pWDkT8MAO7d0jyOecVhN5354xbLqdn8mV9Tat9gepAupm0bt2DbeaSC8vS52MuFA==" + }, + "node_modules/napi-build-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", + "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==" + }, + "node_modules/node-abi": { + "version": "3.22.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.22.0.tgz", + "integrity": "sha512-u4uAs/4Zzmp/jjsD9cyFYDXeISfUWaAVWshPmDZOFOv4Xl4SbzTXm53I04C2uRueYJ+0t5PEtLH/owbn2Npf/w==", + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/nodemailer": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.7.tgz", + "integrity": "sha512-rUtR77ksqex/eZRLmQ21LKVH5nAAsVicAtAYudK7JgwenEDZ0UIQ1adUGqErz7sMkWYxWTTU1aeP2Jga6WQyJw==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "dependencies": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "node_modules/number-allocator": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/number-allocator/-/number-allocator-1.0.14.tgz", + "integrity": "sha512-OrL44UTVAvkKdOdRQZIJpLkAdjXGTRda052sN4sO77bKEzYYqWKMBjQvrJFzqygI99gL6Z4u2xctPW1tB8ErvA==", + "dependencies": { + "debug": "^4.3.1", + "js-sdsl": "4.3.0" + } + }, + "node_modules/number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/prebuild-install": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.0.tgz", + "integrity": "sha512-CNcMgI1xBypOyGqjp3wOc8AAo1nMhZS3Cwd3iHIxOdAUbb+YxdNuM4Z5iIrZ8RLvOsf3F3bl7b7xGq6DjQoNYA==", + "dependencies": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^1.0.1", + "node-abi": "^3.3.0", + "npmlog": "^4.0.1", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + }, + "bin": { + "prebuild-install": "bin.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/reinterval": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reinterval/-/reinterval-1.1.0.tgz", + "integrity": "sha1-M2Hs+jymwYKDOA3Qu5VG85D17Oc=" + }, + "node_modules/rfdc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==" + }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/serialport": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/serialport/-/serialport-9.2.8.tgz", + "integrity": "sha512-FsWpMQgSJxi93JgWl5xM1f9/Z8IjRJuaUEoHqLf8FPBLw7gMhInuHOBhI2onQufWIYPGTz3H3oGcu1nCaK1EfA==", + "dependencies": { + "@serialport/binding-mock": "9.2.4", + "@serialport/bindings": "9.2.8", + "@serialport/parser-byte-length": "9.2.4", + "@serialport/parser-cctalk": "9.2.4", + "@serialport/parser-delimiter": "9.2.4", + "@serialport/parser-inter-byte-timeout": "9.2.4", + "@serialport/parser-readline": "9.2.4", + "@serialport/parser-ready": "9.2.4", + "@serialport/parser-regex": "9.2.4", + "@serialport/stream": "9.2.4", + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "node_modules/split2": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", + "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", + "dependencies": { + "readable-stream": "^3.0.0" + } + }, + "node_modules/split2/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==" + }, + "node_modules/streamroller": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.1.1.tgz", + "integrity": "sha512-iPhtd9unZ6zKdWgMeYGfSBuqCngyJy1B/GPi/lTpwGpa3bajuX30GjUVd0/Tn/Xhg0mr4DOSENozz9Y06qyonQ==", + "dependencies": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "fs-extra": "^10.1.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dependencies": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/tar-fs": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "dependencies": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tar-stream/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/total.js": { + "version": "3.4.13", + "resolved": "https://registry.npmjs.org/total.js/-/total.js-3.4.13.tgz", + "integrity": "sha512-lAH4gEixlPFbrE3xfKADAcHfO79IFq2wKa9GTsrgRzIR5MTg3mNH7+4IxvX1pK8faoYb/0oYSJ1YTsAa5hIFFQ==", + "bin": { + "total": "bin/totaljs", + "total.js": "bin/totaljs", + "totaljs": "bin/totaljs", + "totalpackage": "bin/tpm", + "tpm": "bin/tpm" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, + "node_modules/universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "node_modules/wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "node_modules/ws": { + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } + }, + "dependencies": { + "@serialport/binding-abstract": { + "version": "9.2.3", + "resolved": "https://registry.npmjs.org/@serialport/binding-abstract/-/binding-abstract-9.2.3.tgz", + "integrity": "sha512-cQs9tbIlG3P0IrOWyVirqlhWuJ7Ms2Zh9m2108z6Y5UW/iVj6wEOiW8EmK9QX9jmJXYllE7wgGgvVozP5oCj3w==", + "requires": { + "debug": "^4.3.2" + } + }, + "@serialport/binding-mock": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/binding-mock/-/binding-mock-9.2.4.tgz", + "integrity": "sha512-dpEhACCs44oQhh6ajJfJdvQdK38Vq0N4W6iD/gdplglDCK7qXRQCMUjJIeKdS/HSEiWkC3bwumUhUufdsOyT4g==", + "requires": { + "@serialport/binding-abstract": "9.2.3", + "debug": "^4.3.2" + } + }, + "@serialport/bindings": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/@serialport/bindings/-/bindings-9.2.8.tgz", + "integrity": "sha512-hSLxTe0tADZ3LMMGwvEJWOC/TaFQTyPeFalUCsJ1lSQ0k6bPF04JwrtB/C81GetmDBTNRY0GlD0SNtKCc7Dr5g==", + "requires": { + "@serialport/binding-abstract": "9.2.3", + "@serialport/parser-readline": "9.2.4", + "bindings": "^1.5.0", + "debug": "^4.3.2", + "nan": "^2.15.0", + "prebuild-install": "^7.0.0" + } + }, + "@serialport/parser-byte-length": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-byte-length/-/parser-byte-length-9.2.4.tgz", + "integrity": "sha512-sQD/iw4ZMU3xW9PLi0/GlvU6Y623jGeWecbMkO7izUo/6P7gtfv1c9ikd5h0kwL8AoAOpQA1lxdHIKox+umBUg==" + }, + "@serialport/parser-cctalk": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-cctalk/-/parser-cctalk-9.2.4.tgz", + "integrity": "sha512-T4TU5vQMwmo9AB3gQLFDWbfJXlW5jd9guEsB/nqKjFHTv0FXPdZ7DQ2TpSp8RnHWxU3GX6kYTaDO20BKzc8GPQ==" + }, + "@serialport/parser-delimiter": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-delimiter/-/parser-delimiter-9.2.4.tgz", + "integrity": "sha512-4nvTAoYAgkxFiXrkI+3CA49Yd43CODjeszh89EK+I9c8wOZ+etZduRCzINYPiy26g7zO+GRAb9FoPCsY+sYcbQ==" + }, + "@serialport/parser-inter-byte-timeout": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-inter-byte-timeout/-/parser-inter-byte-timeout-9.2.4.tgz", + "integrity": "sha512-SOAdvr0oBQIOCXX198hiTlxs4JTKg9j5piapw5tNq52fwDOWdbYrFneT/wN04UTMKaDrJuEvXq6T4rv4j7nJ5A==" + }, + "@serialport/parser-readline": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-readline/-/parser-readline-9.2.4.tgz", + "integrity": "sha512-Z1/qrZTQUVhNSJP1hd9YfDvq0o7d87rNwAjjRKbVpa7Qi51tG5BnKt43IV3NFMyBlVcRe0rnIb3tJu57E0SOwg==", + "requires": { + "@serialport/parser-delimiter": "9.2.4" + } + }, + "@serialport/parser-ready": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-ready/-/parser-ready-9.2.4.tgz", + "integrity": "sha512-Pyi94Itjl6qAURwIZr/gmZpMAyTmKXThm6vL5DoAWGQjcRHWB0gwv2TY2v7N+mQLJYUKU3cMnvnATXxHm7xjxw==" + }, + "@serialport/parser-regex": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-regex/-/parser-regex-9.2.4.tgz", + "integrity": "sha512-sI/cVvPOYz+Dbv4ZdnW16qAwvXiFf/1pGASQdbveRTlgJDdz7sRNlCBifzfTN2xljwvCTZYqiudKvDdC1TepRQ==" + }, + "@serialport/stream": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/stream/-/stream-9.2.4.tgz", + "integrity": "sha512-bLye8Ub4vUFQGmkh8qEqehr7SE7EJs2yDs0h9jzuL5oKi+F34CFmWkEErO8GAOQ8YNn7p6b3GxUgs+0BrHHDZQ==", + "requires": { + "debug": "^4.3.2" + } + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==" + }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "are-we-there-yet": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", + "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "base64-js": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", + "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==" + }, + "bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "requires": { + "file-uri-to-path": "1.0.0" + } + }, + "bitwise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/bitwise/-/bitwise-2.1.0.tgz", + "integrity": "sha512-XKgAhMXCh4H/3oNwAHAsAO0iC89s9cOiumgYwSHjSobGWxYjv62YhkL9QEdvGP151xypCtMlAfKK79GEcd2eRQ==" + }, + "bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "requires": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "buffer": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz", + "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==", + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" + }, + "chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==" + }, + "commist": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/commist/-/commist-1.1.0.tgz", + "integrity": "sha512-rraC8NXWOEjhADbZe9QBNzLAN5Q3fsTPQtBV+fEVj6xKIgDgNiEVE6ZNfHpZOqfQ21YUzfVNUXLOEZquYvQPPg==", + "requires": { + "leven": "^2.1.0", + "minimist": "^1.1.0" + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "concat-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", + "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.0.2", + "typedarray": "^0.0.6" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "crc": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/crc/-/crc-3.4.0.tgz", + "integrity": "sha512-ycVC2+4/DLgXXq7QweYi2znhqDuZz6P5TQXnkQo8v15XY/5p/IWeZwsSE31Ifo8w15b8TWLsqhXOjXyilHuQxw==" + }, + "date-format": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.11.tgz", + "integrity": "sha512-VS20KRyorrbMCQmpdl2hg5KaOUsda1RbnsJg461FfrcyCUg+pkd0b40BSW4niQyTheww4DBXQnS7HwSrKkipLw==" + }, + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "requires": { + "ms": "2.1.2" + } + }, + "decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "requires": { + "mimic-response": "^3.1.0" + } + }, + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==" + }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" + }, + "detect-libc": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz", + "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==" + }, + "duplexify": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.2.tgz", + "integrity": "sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw==", + "requires": { + "end-of-stream": "^1.4.1", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1", + "stream-shift": "^1.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "easy-crc": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/easy-crc/-/easy-crc-0.0.2.tgz", + "integrity": "sha512-h6eqIdhJRe0p271/xZJbM/0klCi13mW5IB7ZEzEGH11yV4QXWAkD4yPErz0fXdhFrd6sZ4Q1k5Iky2kMsMNePw==" + }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "requires": { + "once": "^1.4.0" + } + }, + "expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==" + }, + "file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" + }, + "flatted": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", + "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==" + }, + "fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, + "fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha512-14x4kjc6lkD3ltw589k0NrPD6cCNTD6CWoVUNpB85+DrtONoZn+Rug6xZU5RvSC4+TZPxA5AnBibQYAvZn41Hg==", + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==" + }, + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" + }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" + }, + "help-me": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/help-me/-/help-me-3.0.0.tgz", + "integrity": "sha512-hx73jClhyk910sidBB7ERlnhMlFsJJIBqSVMFDwPN8o2v9nmp5KgLq1Xz1Bf1fCMMZ6mPrX159iG0VLy/fPMtQ==", + "requires": { + "glob": "^7.1.6", + "readable-stream": "^3.6.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==", + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "js-sdsl": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz", + "integrity": "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==" + }, + "jsmodbus": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/jsmodbus/-/jsmodbus-4.0.6.tgz", + "integrity": "sha512-gCmjoaERErK5Rn9Lu/BN07fY13MoWV7JKgGzrnkPlQPdPxYcwDhLtYcmpFFpZ4J9NPZZBSezi1UkLZO/DnNppA==", + "requires": { + "crc": "3.4.0", + "debug": "^3.1.0" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "requires": { + "ms": "^2.1.1" + } + } + } + }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, + "leven": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", + "integrity": "sha1-wuep93IJTe6dNCAq6KzORoeHVYA=" + }, + "log4js": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.5.2.tgz", + "integrity": "sha512-DXtpNtt+KDOMT7RHUDIur/WsSA3rntlUh9Zg4XCdV42wUuMmbFkl38+LZ92Z5QvQA7mD5kAVkLiBSEH/tvUB8A==", + "requires": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "flatted": "^3.2.5", + "rfdc": "^1.3.0", + "streamroller": "^3.1.1" + } + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "requires": { + "yallist": "^4.0.0" + } + }, + "mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==" + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==" + }, + "mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" + }, + "mqtt": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/mqtt/-/mqtt-4.3.7.tgz", + "integrity": "sha512-ew3qwG/TJRorTz47eW46vZ5oBw5MEYbQZVaEji44j5lAUSQSqIEoul7Kua/BatBW0H0kKQcC9kwUHa1qzaWHSw==", + "requires": { + "commist": "^1.0.0", + "concat-stream": "^2.0.0", + "debug": "^4.1.1", + "duplexify": "^4.1.1", + "help-me": "^3.0.0", + "inherits": "^2.0.3", + "lru-cache": "^6.0.0", + "minimist": "^1.2.5", + "mqtt-packet": "^6.8.0", + "number-allocator": "^1.0.9", + "pump": "^3.0.0", + "readable-stream": "^3.6.0", + "reinterval": "^1.1.0", + "rfdc": "^1.3.0", + "split2": "^3.1.0", + "ws": "^7.5.5", + "xtend": "^4.0.2" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "mqtt-packet": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/mqtt-packet/-/mqtt-packet-6.10.0.tgz", + "integrity": "sha512-ja8+mFKIHdB1Tpl6vac+sktqy3gA8t9Mduom1BA75cI+R9AHnZOiaBQwpGiWnaVJLDGRdNhQmFaAqd7tkKSMGA==", + "requires": { + "bl": "^4.0.2", + "debug": "^4.1.1", + "process-nextick-args": "^2.0.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "nan": { + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.16.0.tgz", + "integrity": "sha512-UdAqHyFngu7TfQKsCBgAA6pWDkT8MAO7d0jyOecVhN5354xbLqdn8mV9Tat9gepAupm0bt2DbeaSC8vS52MuFA==" + }, + "napi-build-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", + "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==" + }, + "node-abi": { + "version": "3.22.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.22.0.tgz", + "integrity": "sha512-u4uAs/4Zzmp/jjsD9cyFYDXeISfUWaAVWshPmDZOFOv4Xl4SbzTXm53I04C2uRueYJ+0t5PEtLH/owbn2Npf/w==", + "requires": { + "semver": "^7.3.5" + } + }, + "nodemailer": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.7.tgz", + "integrity": "sha512-rUtR77ksqex/eZRLmQ21LKVH5nAAsVicAtAYudK7JgwenEDZ0UIQ1adUGqErz7sMkWYxWTTU1aeP2Jga6WQyJw==" + }, + "npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "number-allocator": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/number-allocator/-/number-allocator-1.0.14.tgz", + "integrity": "sha512-OrL44UTVAvkKdOdRQZIJpLkAdjXGTRda052sN4sO77bKEzYYqWKMBjQvrJFzqygI99gL6Z4u2xctPW1tB8ErvA==", + "requires": { + "debug": "^4.3.1", + "js-sdsl": "4.3.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==" + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==" + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==" + }, + "prebuild-install": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.0.tgz", + "integrity": "sha512-CNcMgI1xBypOyGqjp3wOc8AAo1nMhZS3Cwd3iHIxOdAUbb+YxdNuM4Z5iIrZ8RLvOsf3F3bl7b7xGq6DjQoNYA==", + "requires": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^1.0.1", + "node-abi": "^3.3.0", + "npmlog": "^4.0.1", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + } + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + } + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "reinterval": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reinterval/-/reinterval-1.1.0.tgz", + "integrity": "sha1-M2Hs+jymwYKDOA3Qu5VG85D17Oc=" + }, + "rfdc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==" + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "requires": { + "lru-cache": "^6.0.0" + } + }, + "serialport": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/serialport/-/serialport-9.2.8.tgz", + "integrity": "sha512-FsWpMQgSJxi93JgWl5xM1f9/Z8IjRJuaUEoHqLf8FPBLw7gMhInuHOBhI2onQufWIYPGTz3H3oGcu1nCaK1EfA==", + "requires": { + "@serialport/binding-mock": "9.2.4", + "@serialport/bindings": "9.2.8", + "@serialport/parser-byte-length": "9.2.4", + "@serialport/parser-cctalk": "9.2.4", + "@serialport/parser-delimiter": "9.2.4", + "@serialport/parser-inter-byte-timeout": "9.2.4", + "@serialport/parser-readline": "9.2.4", + "@serialport/parser-ready": "9.2.4", + "@serialport/parser-regex": "9.2.4", + "@serialport/stream": "9.2.4", + "debug": "^4.3.2" + } + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==" + }, + "simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "requires": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "split2": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", + "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", + "requires": { + "readable-stream": "^3.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==" + }, + "streamroller": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.1.1.tgz", + "integrity": "sha512-iPhtd9unZ6zKdWgMeYGfSBuqCngyJy1B/GPi/lTpwGpa3bajuX30GjUVd0/Tn/Xhg0mr4DOSENozz9Y06qyonQ==", + "requires": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "fs-extra": "^10.1.0" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" + }, + "tar-fs": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "requires": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "requires": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "total.js": { + "version": "3.4.13", + "resolved": "https://registry.npmjs.org/total.js/-/total.js-3.4.13.tgz", + "integrity": "sha512-lAH4gEixlPFbrE3xfKADAcHfO79IFq2wKa9GTsrgRzIR5MTg3mNH7+4IxvX1pK8faoYb/0oYSJ1YTsAa5hIFFQ==" + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, + "universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==" + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "requires": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "ws": { + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "requires": {} + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } + } +} diff --git a/RVO14/package.json b/RVO14/package.json new file mode 100755 index 0000000..e524d7c --- /dev/null +++ b/RVO14/package.json @@ -0,0 +1,29 @@ +{ + "name": "emptyproject", + "description": "Total.js empty project.", + "version": "1.0.0", + "main": "debug.js", + "dependencies": { + "bitwise": "^2.1.0", + "easy-crc": "0.0.2", + "jsmodbus": "^4.0.6", + "log4js": "^6.3.0", + "mqtt": "^4.2.6", + "nodemailer": "^6.9.7", + "serialport": "^9.2.8", + "total.js": "^3.4.13" + }, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "https://github.com/totaljs/emptyproject-flow" + }, + "keywords": [ + "empty", + "project" + ], + "author": "Peter Širka", + "license": "MIT" +} diff --git a/RVO14/release.js b/RVO14/release.js new file mode 100755 index 0000000..02d52ff --- /dev/null +++ b/RVO14/release.js @@ -0,0 +1,15 @@ +// =================================================== +// FOR PRODUCTION +// Total.js - framework for Node.js platform +// https://www.totaljs.com +// =================================================== + +const options = {'ip':'0.0.0.0', 'port':12345}; + +// options.ip = '127.0.0.1'; +// options.port = parseInt(process.argv[2]); +// options.config = { name: 'Total.js' }; +// options.sleep = 3000; + +require('total.js').http('release', options); +// require('total.js').cluster.http(5, 'release', options); diff --git a/RVO14/release.js.json b/RVO14/release.js.json new file mode 100755 index 0000000..b7d41d9 --- /dev/null +++ b/RVO14/release.js.json @@ -0,0 +1,34 @@ +{ + "pid": 392, + "stats": [ + { + "id": null, + "version": { + "node": "v14.18.1", + "total": "3.4.13", + "app": "1.0.0" + }, + "pid": 392, + "thread": "", + "mode": "release", + "overload": 0, + "date": "2025-10-16T00:23:26.174Z", + "memory": 24.66, + "rm": 0, + "fm": 0, + "wm": 0, + "mm": 0, + "om": 2, + "em": 0, + "dbrm": 0, + "dbwm": 0, + "usage": 0, + "requests": 0, + "pending": 0, + "errors": 0, + "timeouts": 0, + "uptime": 729, + "online": 0 + } + ] +} \ No newline at end of file diff --git a/RVO14/report_data.log b/RVO14/report_data.log new file mode 100755 index 0000000..7464da7 --- /dev/null +++ b/RVO14/report_data.log @@ -0,0 +1,181 @@ +{ + "name": "rvo_senica_14_ip124", + "time": "2025-10-15T13:15:41.139Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_14_ip124", + "time": "2025-10-15T14:15:41.137Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_14_ip124", + "time": "2025-10-15T15:15:41.137Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_14_ip124", + "time": "2025-10-15T16:15:41.138Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_14_ip124", + "time": "2025-10-15T17:15:41.137Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_14_ip124", + "time": "2025-10-15T18:15:41.138Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_14_ip124", + "time": "2025-10-15T19:15:41.139Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_14_ip124", + "time": "2025-10-15T20:15:41.139Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_14_ip124", + "time": "2025-10-15T21:15:41.140Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_14_ip124", + "time": "2025-10-15T22:15:41.140Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_14_ip124", + "time": "2025-10-15T23:15:41.141Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_14_ip124", + "time": "2025-10-16T00:15:41.142Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +} \ No newline at end of file From a1befbc183ccd26ac67384e71143d6239c1bcee6 Mon Sep 17 00:00:00 2001 From: Jakub Klena Date: Thu, 16 Oct 2025 02:24:14 +0200 Subject: [PATCH 08/30] Backup senica-RVO15 on 16.10.2025 --- RVO15/addSwitch.py | 36 + RVO15/cloud_topic.py | 76 + RVO15/config | 12 + RVO15/createNode.py | 43 + RVO15/databases/accelerometer_db.js | 3055 ++++++++++++++++ RVO15/databases/modbus_config.js | 114 + RVO15/databases/nodes.table | 147 + .../nodes_original/nodes_original.table | 1 + RVO15/databases/notifications.table | 41 + RVO15/databases/pins.table | 14 + RVO15/databases/relays.table | 5 + RVO15/databases/settings.table | 2 + RVO15/databases/tbdata.nosql | 4 + RVO15/databases/tbdatacloud.nosql | 3 + RVO15/databases/total_energy.js | 38 + RVO15/debug.js | 16 + RVO15/err.txt | 33 + RVO15/flow/cloudmqttconnect.js | 357 ++ RVO15/flow/cmd_manager.js | 3071 ++++++++++++++++ RVO15/flow/cmd_manager_original.txt | 2800 +++++++++++++++ RVO15/flow/code.js | 90 + RVO15/flow/comment.js | 11 + RVO15/flow/count.js | 60 + RVO15/flow/db_connector.js | 286 ++ RVO15/flow/db_init.js | 113 + RVO15/flow/debug.js | 100 + RVO15/flow/designer.json | 3102 +++++++++++++++++ RVO15/flow/dido_controller.js | 1486 ++++++++ RVO15/flow/helper/DataToTbHandler.js | 187 + RVO15/flow/helper/ErrorToServiceHandler.js | 91 + RVO15/flow/helper/db_helper.js | 44 + RVO15/flow/helper/logger.js | 30 + RVO15/flow/helper/md5.js | 5 + RVO15/flow/helper/notification_reporter.js | 121 + RVO15/flow/helper/register.js | 144 + RVO15/flow/helper/serialport_helper.js | 99 + RVO15/flow/helper/suncalc.js | 317 ++ RVO15/flow/helper/utils.js | 161 + RVO15/flow/httprequest.js | 137 + RVO15/flow/httpresponse.js | 76 + RVO15/flow/httproute.js | 326 ++ RVO15/flow/infosender.js | 81 + RVO15/flow/modbus_reader.js | 346 ++ RVO15/flow/monitorconsumption.js | 156 + RVO15/flow/monitordisk.js | 96 + RVO15/flow/monitormemory.js | 87 + RVO15/flow/nodesdb_changecheck.js | 77 + RVO15/flow/show_dbdata.js | 243 ++ RVO15/flow/slack_filter.js | 188 + RVO15/flow/thermometer.js | 99 + RVO15/flow/trigger.js | 79 + RVO15/flow/variables.txt | 0 RVO15/flow/virtualwirein.js | 43 + RVO15/flow/virtualwireout.js | 41 + RVO15/flow/wsmqttpublish.js | 448 +++ RVO15/monitor.txt | 543 +++ RVO15/package-lock.json | 2125 +++++++++++ RVO15/package.json | 29 + RVO15/release.js | 15 + RVO15/release.js.json | 34 + RVO15/report_data.log | 222 ++ 61 files changed, 21806 insertions(+) create mode 100755 RVO15/addSwitch.py create mode 100755 RVO15/cloud_topic.py create mode 100755 RVO15/config create mode 100755 RVO15/createNode.py create mode 100755 RVO15/databases/accelerometer_db.js create mode 100755 RVO15/databases/modbus_config.js create mode 100755 RVO15/databases/nodes.table create mode 100755 RVO15/databases/nodes_original/nodes_original.table create mode 100755 RVO15/databases/notifications.table create mode 100755 RVO15/databases/pins.table create mode 100755 RVO15/databases/relays.table create mode 100755 RVO15/databases/settings.table create mode 100755 RVO15/databases/tbdata.nosql create mode 100755 RVO15/databases/tbdatacloud.nosql create mode 100755 RVO15/databases/total_energy.js create mode 100755 RVO15/debug.js create mode 100755 RVO15/err.txt create mode 100755 RVO15/flow/cloudmqttconnect.js create mode 100755 RVO15/flow/cmd_manager.js create mode 100755 RVO15/flow/cmd_manager_original.txt create mode 100755 RVO15/flow/code.js create mode 100755 RVO15/flow/comment.js create mode 100755 RVO15/flow/count.js create mode 100755 RVO15/flow/db_connector.js create mode 100755 RVO15/flow/db_init.js create mode 100755 RVO15/flow/debug.js create mode 100755 RVO15/flow/designer.json create mode 100755 RVO15/flow/dido_controller.js create mode 100755 RVO15/flow/helper/DataToTbHandler.js create mode 100755 RVO15/flow/helper/ErrorToServiceHandler.js create mode 100755 RVO15/flow/helper/db_helper.js create mode 100755 RVO15/flow/helper/logger.js create mode 100755 RVO15/flow/helper/md5.js create mode 100755 RVO15/flow/helper/notification_reporter.js create mode 100755 RVO15/flow/helper/register.js create mode 100755 RVO15/flow/helper/serialport_helper.js create mode 100755 RVO15/flow/helper/suncalc.js create mode 100755 RVO15/flow/helper/utils.js create mode 100755 RVO15/flow/httprequest.js create mode 100755 RVO15/flow/httpresponse.js create mode 100755 RVO15/flow/httproute.js create mode 100755 RVO15/flow/infosender.js create mode 100755 RVO15/flow/modbus_reader.js create mode 100755 RVO15/flow/monitorconsumption.js create mode 100755 RVO15/flow/monitordisk.js create mode 100755 RVO15/flow/monitormemory.js create mode 100755 RVO15/flow/nodesdb_changecheck.js create mode 100755 RVO15/flow/show_dbdata.js create mode 100755 RVO15/flow/slack_filter.js create mode 100755 RVO15/flow/thermometer.js create mode 100755 RVO15/flow/trigger.js create mode 100755 RVO15/flow/variables.txt create mode 100755 RVO15/flow/virtualwirein.js create mode 100755 RVO15/flow/virtualwireout.js create mode 100755 RVO15/flow/wsmqttpublish.js create mode 100755 RVO15/monitor.txt create mode 100755 RVO15/package-lock.json create mode 100755 RVO15/package.json create mode 100755 RVO15/release.js create mode 100755 RVO15/release.js.json create mode 100755 RVO15/report_data.log diff --git a/RVO15/addSwitch.py b/RVO15/addSwitch.py new file mode 100755 index 0000000..c35e96b --- /dev/null +++ b/RVO15/addSwitch.py @@ -0,0 +1,36 @@ +import os + +def process_set_file(): + """ + Checks if /root/flowserver exists, reads set.txt, and modifies the second line. + """ + default_folder = "/root/flowserver" if os.path.exists("/root/flowserver") else "/home/unipi/flowserver" + flag = 1 if default_folder == "/root/flowserver" else 0 + + try: + with open("/home/unipi/flowserver/databases/settings.table", "r") as f: + lines = f.readlines() + + if len(lines) >= 2: + lines[0] = lines[0].rstrip('\n') + "|main_switch:boolean\n" + second_line = lines[1].strip() # remove trailing newline + last_pipe_index = second_line.rfind("|") + + if last_pipe_index != -1: + modified_line = second_line[:last_pipe_index + 1] + str(flag) + "|" + second_line[last_pipe_index + 1:] + lines[1] = modified_line + else: + print("Warning: No '|' character found in the second line of set.txt") + + with open("/home/unipi/flowserver/databases/settings.table", "w") as f: + f.writelines(lines) + else: + print("Warning: settings.table has less than two lines.") + + except FileNotFoundError: + print("Error: settings.table not found.") + except Exception as e: + print(e) + +# if __name__ == "__main__": +process_set_file() diff --git a/RVO15/cloud_topic.py b/RVO15/cloud_topic.py new file mode 100755 index 0000000..77c31f1 --- /dev/null +++ b/RVO15/cloud_topic.py @@ -0,0 +1,76 @@ +# import os +# +# def modify_file(file_path): +# """ +# Modifies the given file by: +# 1. Appending "|cloud_topic" to the first line. +# 2. Inserting the text from the third "." to the first "|" on the second line after the last "|" character. +# +# Args: +# file_path (str): The path to the file to be modified. +# """ +# +# with open(file_path, 'r+') as f: +# lines = f.readlines() +# +# # Modify the first line +# lines[0] += "|cloud_topic:string" +# +# # Modify the second line +# second_line = lines[1].strip() # Remove leading/trailing whitespace +# first_pipe_index = second_line.find('|') +# third_dot_index = second_line.find('.', second_line.find('.', second_line.find('.') + 1) + 1) +# text_to_insert = second_line[third_dot_index:first_pipe_index] +# +# last_pipe_index = second_line.rfind('|') +# lines[1] = second_line[:last_pipe_index + 1] + text_to_insert + "|" + second_line[last_pipe_index + 1:] +# +# print(first_pipe_index, third_dot_index, text_to_insert, last_pipe_index) +# # Write the modified lines back to the file +# # f.seek(0) +# # f.writelines(lines) +# # f.truncate() +# +# # Example usage: +# file_path = "settings.table" # Replace with the actual file path +# modify_file(file_path) +# + + +def modify_file(file_path): + """ + Modifies the given file by: + 1. Appending "|cloud_topic" to the first line. + 2. Inserting the text between the third "." and the second "|" on the second line after the last "|" character. + + Args: + file_path (str): The path to the file to be modified. + """ + + with open(file_path, 'r+') as f: + lines = f.readlines() + + first_line = lines[0].strip() + first_line += "|cloud_topic:string\n" + # Modify the first line + lines[0] = first_line + + # Modify the second line + second_line = lines[1].strip() # Remove leading/trailing whitespace + first_pipe_index = second_line.find('|') + second_pipe_index = second_line.find('|', first_pipe_index + 1) + third_dot_index = second_line.find('.', second_line.find('.', second_line.find('.') + 1) + 1) + text_to_insert = "u" + second_line[third_dot_index+1:second_pipe_index] + + last_pipe_index = second_line.rfind('|') + lines[1] = second_line[:last_pipe_index + 1] + text_to_insert + "|" + second_line[last_pipe_index + 1:] + + print(first_pipe_index, third_dot_index, text_to_insert, last_pipe_index) + # Write the modified lines back to the file + f.seek(0) + f.writelines(lines) + f.truncate() + +# Example usage: +file_path = "/home/unipi/flowserver/databases/settings.table" # Replace with the actual file path +modify_file(file_path) diff --git a/RVO15/config b/RVO15/config new file mode 100755 index 0000000..cd0a8a9 --- /dev/null +++ b/RVO15/config @@ -0,0 +1,12 @@ +name : Total.js Flow +default_timezone : Europe/Bratislava + +// Packages settings +package#flow (Object) : { url: '/' } + + +table.relays : line:number|tbname:string|contactor:number|profile:string +table.nodes : node:number|pole_number:string|node_type:string|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|project_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|cloud_topic:string|has_main_switch:boolean|daily_report:boolean|send_changed_node_numbers:boolean +table.pins : pin:string|type:string|line:number +table.notifications : key:string|weight:string|sk:string|en:string diff --git a/RVO15/createNode.py b/RVO15/createNode.py new file mode 100755 index 0000000..a8cea91 --- /dev/null +++ b/RVO15/createNode.py @@ -0,0 +1,43 @@ +print("zaciname") +import re, json + +search_str = '|' +final = [] +counter = 1 +with open("/home/unipi/flowserver/databases/nodes.table", 'r') as file: +# with open("/home/rasta5man/dev/oms/flowserver/databases/nodes.table", 'r') as file: + # Read each line in the file + for line in file: + # Print each line + line = line.strip() + print(line) + if counter != 1: + i = [m.start() for m in re.finditer(re.escape(search_str), line)] + node = line[ i[0] + 1 : i[1] ] + tbname = line[ i[3] + 1 : i[4] ] + final.append({node:tbname}) + counter += 1 +print(json.dumps(final)) +f = open("/home/unipi/flowserver/databases/nodes_original/nodes_original.table", "w") +f.write(json.dumps(final)) +f.close() + + +# +# # ``d`` has to be replaced with a different character +# old_character = "'" +# +# # ``t`` will replace ``d` +# new_character = '"' +# resultant_string = 0; +# with open("/home/unipi/flowserver/databases/nodes_original/nodes_original.table", 'r') as file: +# for line in file: +# resultant_string = re.sub("'", '"', line) +# +# resultant_string = re.sub(" ", "", resultant_string) +# print(resultant_string) +# +# f = open("/home/unipi/flowserver/databases/nodes_original/nodes_original.table", "w") +# f.write(str(resultant_string)) +# f.close() +# diff --git a/RVO15/databases/accelerometer_db.js b/RVO15/databases/accelerometer_db.js new file mode 100755 index 0000000..fdfc7fd --- /dev/null +++ b/RVO15/databases/accelerometer_db.js @@ -0,0 +1,3055 @@ +let naklony = { + "3993": { "label": "1/3A", "naklon": 0 }, + "3989": { "label": "1/3B", "naklon": 15 }, + "3976": { "label": "1/1", "naklon": 0 }, + "4181": { "label": "1/2", "naklon": 0 }, + "4376": { "label": "1/4", "naklon": 15 }, + "3868": { "label": "1/5", "naklon": 15 }, + "3728": { "label": "1/6", "naklon": 15 }, + "3730": { "label": "1/7", "naklon": 0 }, + "4374": { "label": "1/8", "naklon": 0 }, + "3718": { "label": "1/9", "naklon": 15 }, + "4375": { "label": "1/10", "naklon": 15 }, + "4172": { "label": "1/11", "naklon": 15 }, + "4176": { "label": "1/12", "naklon": 15 }, + "3800": { "label": "2/1", "naklon": 5 }, + "3823": { "label": "2/2", "naklon": 5 }, + "3905": { "label": "2/3", "naklon": 5 }, + "3803": { "label": "2/4", "naklon": 5 }, + "3817": { "label": "2/5", "naklon": 5 }, + "3818": { "label": "2/6", "naklon": 5 }, + "3811": { "label": "2/7", "naklon": 5 }, + "3915": { "label": "2/8", "naklon": 5 }, + "3843": { "label": "2/9", "naklon": 10 }, + "3827": { "label": "2/10", "naklon": 10 }, + "4220": { "label": "2/11", "naklon": 10 }, + "3826": { "label": "2/12", "naklon": 10 }, + "3834": { "label": "2/13", "naklon": 10 }, + "3838": { "label": "2/14", "naklon": 10 }, + "2823": { "label": "2/15", "naklon": 10 }, + "3750": { "label": "2/16", "naklon": 10 }, + "3378": { "label": "2/17", "naklon": 0 }, + "3376": { "label": "2/18", "naklon": 0 }, + "3379": { "label": "2/19", "naklon": 0 }, + "3285": { "label": "2/20", "naklon": 0 }, + "3382": { "label": "2/21", "naklon": 0 }, + "3383": { "label": "2/22", "naklon": 0 }, + "3375": { "label": "2/24", "naklon": 0 }, + "3381": { "label": "2/25", "naklon": 0 }, + "3380": { "label": "2/26", "naklon": 0 }, + "3828": { "label": "2/27", "naklon": 10 }, + "3377": { "label": "2/28", "naklon": 0 }, + "3591": { "label": "7/1", "naklon": 0 }, + "3587": { "label": "7/2", "naklon": 0 }, + "3468": { "label": "7/3", "naklon": 0 }, + "3466": { "label": "7/4", "naklon": 0 }, + "3474": { "label": "7/5", "naklon": 0 }, + "3481": { "label": "7/6", "naklon": 0 }, + "3589": { "label": "7/7", "naklon": 0 }, + "3472": { "label": "7/8", "naklon": 0 }, + "3473": { "label": "7/9", "naklon": 0 }, + "3584": { "label": "7/10", "naklon": 0 }, + "3571": { "label": "7/11", "naklon": 0 }, + "3476": { "label": "7/12", "naklon": 0 }, + "3590": { "label": "7/13", "naklon": 0 }, + "3478": { "label": "7/14", "naklon": 0 }, + "3471": { "label": "7/15", "naklon": 0 }, + "3467": { "label": "7/16", "naklon": 0 }, + "3479": { "label": "7/17", "naklon": 0 }, + "3480": { "label": "7/18", "naklon": 0 }, + "3477": { "label": "7/19", "naklon": 0 }, + "3362": { "label": "12/1", "naklon": 0 }, + "3355": { "label": "12/2", "naklon": 0 }, + "3356": { "label": "12/3", "naklon": 0 }, + "3349": { "label": "12/4", "naklon": 0 }, + "3357": { "label": "12/5", "naklon": 0 }, + "3350": { "label": "12/6", "naklon": 0 }, + "3353": { "label": "12/7", "naklon": 0 }, + "3539": { "label": "12/8", "naklon": 0 }, + "3050": { "label": "12/9", "naklon": 0 }, + "3361": { "label": "12/10", "naklon": 0 }, + "3360": { "label": "12/11", "naklon": 0 }, + "3358": { "label": "12/12", "naklon": 0 }, + "3541": { "label": "12/13", "naklon": 0 }, + "3551": { "label": "12/14", "naklon": 0 }, + "3514": { "label": "12/15", "naklon": 0 }, + "3547": { "label": "12/16", "naklon": 0 }, + "3562": { "label": "12/17", "naklon": 0 }, + "3525": { "label": "12/18", "naklon": 0 }, + "3558": { "label": "12/19", "naklon": 0 }, + "3511": { "label": "12/20", "naklon": 0 }, + "3058": { "label": "12/21", "naklon": 0 }, + "3062": { "label": "12/22", "naklon": 0 }, + "3070": { "label": "12/23", "naklon": 0 }, + "3447": { "label": "12/24", "naklon": 0 }, + "3056": { "label": "12/25", "naklon": 0 }, + "3057": { "label": "12/26", "naklon": 0 }, + "3071": { "label": "12/27", "naklon": 0 }, + "3061": { "label": "12/28", "naklon": 0 }, + "3069": { "label": "12/29", "naklon": 0 }, + "3077": { "label": "12/30", "naklon": 0 }, + "3080": { "label": "12/31", "naklon": 0 }, + "3081": { "label": "12/32", "naklon": 0 }, + "3078": { "label": "12/33", "naklon": 0 }, + "4037": { "label": "12/34", "naklon": 0 }, + "3067": { "label": "12/35", "naklon": 0 }, + "3051": { "label": "12/36", "naklon": 0 }, + "2924": { "label": "12/37", "naklon": 0 }, + "3060": { "label": "12/38", "naklon": 0 }, + "3073": { "label": "12/39", "naklon": 0 }, + "3469": { "label": "12/40", "naklon": 0 }, + "2923": { "label": "12/41", "naklon": 0 }, + "2925": { "label": "12/42", "naklon": 0 }, + "3359": { "label": "12/43", "naklon": 0 }, + "3055": { "label": "12/44", "naklon": 0 }, + "2922": { "label": "12/45", "naklon": 0 }, + "3084": { "label": "12/46", "naklon": 0 }, + "3064": { "label": "12/47", "naklon": 0 }, + "3066": { "label": "12/48", "naklon": 0 }, + "3072": { "label": "12/49", "naklon": 0 }, + "3415": { "label": "13/13A", "naklon": 0 }, + "3409": { "label": "13/13B", "naklon": 0 }, + "3399": { "label": "13/13C", "naklon": 0 }, + "3410": { "label": "13/29A", "naklon": 0 }, + "3407": { "label": "13/29B", "naklon": 0 }, + "3405": { "label": "13/34A", "naklon": 0 }, + "3404": { "label": "13/34B", "naklon": 0 }, + "3392": { "label": "13/45A", "naklon": 0 }, + "3386": { "label": "13/45B", "naklon": 0 }, + "3303": { "label": "13/60A", "naklon": 3 }, + "3302": { "label": "13/60B", "naklon": 3 }, + "3319": { "label": "13/70A", "naklon": 6 }, + "3317": { "label": "13/70B", "naklon": 6 }, + "3326": { "label": "13/70C", "naklon": 6 }, + "3351": { "label": "13/73A", "naklon": 6 }, + "3313": { "label": "13/73B", "naklon": 6 }, + "3316": { "label": "13/83A", "naklon": 0 }, + "3320": { "label": "13/83B", "naklon": 0 }, + "3336": { "label": "13/95A", "naklon": 0 }, + "3323": { "label": "13/95B", "naklon": 0 }, + "3339": { "label": "13/98A", "naklon": 0 }, + "3333": { "label": "13/98B", "naklon": 0 }, + "3425": { "label": "13/1", "naklon": 0 }, + "3419": { "label": "13/2", "naklon": 0 }, + "3416": { "label": "13/3", "naklon": 0 }, + "3332": { "label": "13/4", "naklon": 0 }, + "3422": { "label": "13/5", "naklon": 0 }, + "3417": { "label": "13/6", "naklon": 0 }, + "3418": { "label": "13/7", "naklon": 0 }, + "3424": { "label": "13/8", "naklon": 0 }, + "3334": { "label": "13/9", "naklon": 0 }, + "4363": { "label": "13/10", "naklon": 0 }, + "3423": { "label": "13/11", "naklon": 0 }, + "3406": { "label": "13/12", "naklon": 0 }, + "3411": { "label": "13/14", "naklon": 0 }, + "3412": { "label": "13/15", "naklon": 0 }, + "3413": { "label": "13/16", "naklon": 0 }, + "3414": { "label": "13/17", "naklon": 0 }, + "3391": { "label": "13/18", "naklon": 0 }, + "3370": { "label": "13/19", "naklon": 0 }, + "3369": { "label": "13/20", "naklon": 0 }, + "3408": { "label": "13/21", "naklon": 0 }, + "3393": { "label": "13/22", "naklon": 0 }, + "3128": { "label": "13/23", "naklon": 0 }, + "3197": { "label": "13/24", "naklon": 0 }, + "4364": { "label": "13/25", "naklon": 0 }, + "3155": { "label": "13/26", "naklon": 0 }, + "3196": { "label": "13/27", "naklon": 0 }, + "3144": { "label": "13/28", "naklon": 0 }, + "3150": { "label": "13/30", "naklon": 0 }, + "3390": { "label": "13/31", "naklon": 0 }, + "3401": { "label": "13/32", "naklon": 0 }, + "3275": { "label": "13/33", "naklon": 0 }, + "3371": { "label": "13/35", "naklon": 0 }, + "3389": { "label": "13/36", "naklon": 0 }, + "3388": { "label": "13/37", "naklon": 0 }, + "3365": { "label": "13/38", "naklon": 0 }, + "3363": { "label": "13/39", "naklon": 0 }, + "3397": { "label": "13/40", "naklon": 0 }, + "3567": { "label": "13/40/1", "naklon": 0 }, + "3387": { "label": "13/41", "naklon": 0 }, + "3403": { "label": "13/42", "naklon": 0 }, + "3147": { "label": "13/43", "naklon": 0 }, + "3141": { "label": "13/44", "naklon": 0 }, + "3364": { "label": "13/46", "naklon": 0 }, + "3367": { "label": "13/47", "naklon": 0 }, + "3368": { "label": "13/48", "naklon": 0 }, + "3402": { "label": "13/49", "naklon": 0 }, + "3366": { "label": "13/50", "naklon": 0 }, + "3395": { "label": "13/51", "naklon": 0 }, + "3372": { "label": "13/52", "naklon": 0 }, + "3394": { "label": "13/53", "naklon": 0 }, + "3308": { "label": "13/54", "naklon": 0 }, + "3847": { "label": "13/54/1", "naklon": 0 }, + "3312": { "label": "13/55", "naklon": 3 }, + "3309": { "label": "13/56", "naklon": 3 }, + "3311": { "label": "13/57", "naklon": 3 }, + "3310": { "label": "13/58", "naklon": 3 }, + "4365": { "label": "13/59", "naklon": 3 }, + "4093": { "label": "13/60/1", "naklon": 3 }, + "3304": { "label": "13/61", "naklon": 3 }, + "3307": { "label": "13/62", "naklon": 3 }, + "3271": { "label": "13/63", "naklon": 3 }, + "3301": { "label": "13/64", "naklon": 3 }, + "4366": { "label": "13/65", "naklon": 3 }, + "3300": { "label": "13/66", "naklon": 3 }, + "3185": { "label": "13/67", "naklon": 0 }, + "3184": { "label": "13/68", "naklon": 0 }, + "3188": { "label": "13/69", "naklon": 0 }, + "3343": { "label": "13/71", "naklon": 6 }, + "3819": { "label": "13/71/1", "naklon": 6 }, + "3880": { "label": "13/71/2", "naklon": 6 }, + "3348": { "label": "13/72", "naklon": 6 }, + "3344": { "label": "13/74", "naklon": 6 }, + "3346": { "label": "13/75", "naklon": 6 }, + "3597": { "label": "13/75/1", "naklon": 6 }, + "3345": { "label": "13/76", "naklon": 6 }, + "3322": { "label": "13/77", "naklon": 0 }, + "3325": { "label": "13/78", "naklon": 0 }, + "4310": { "label": "13/78/1", "naklon": 0 }, + "3315": { "label": "13/79", "naklon": 0 }, + "3328": { "label": "13/80", "naklon": 0 }, + "3321": { "label": "13/81", "naklon": 0 }, + "3324": { "label": "13/82", "naklon": 0 }, + "3140": { "label": "13/84", "naklon": 0 }, + "3153": { "label": "13/85", "naklon": 0 }, + "3145": { "label": "13/86", "naklon": 0 }, + "3134": { "label": "13/87", "naklon": 0 }, + "3151": { "label": "13/88", "naklon": 0 }, + "3143": { "label": "13/89", "naklon": 0 }, + "3318": { "label": "13/90", "naklon": 0 }, + "3347": { "label": "13/91", "naklon": 0 }, + "3314": { "label": "13/94", "naklon": 0 }, + "3331": { "label": "13/96", "naklon": 0 }, + "3327": { "label": "13/97", "naklon": 0 }, + "3329": { "label": "13/99", "naklon": 0 }, + "3337": { "label": "13/100", "naklon": 0 }, + "3330": { "label": "13/101", "naklon": 0 }, + "3335": { "label": "13/102", "naklon": 0 }, + "3420": { "label": "13/103", "naklon": 0 }, + "3421": { "label": "13/104", "naklon": 0 }, + "4361": { "label": "13/105", "naklon": 0 }, + "4362": { "label": "13/106", "naklon": 0 }, + "3526": { "label": "13/107", "naklon": 0 }, + "4424": { "label": "13/108", "naklon": null }, + "3561": { "label": "13/109", "naklon": null }, + "3527": { "label": "13/110", "naklon": null }, + "3521": { "label": "13/111", "naklon": null }, + "3552": { "label": "13/112", "naklon": null }, + "3544": { "label": "13/113", "naklon": null }, + "3534": { "label": "13/114", "naklon": null }, + "3516": { "label": "13/115", "naklon": null }, + "3513": { "label": "13/116", "naklon": null }, + "3565": { "label": "13/117", "naklon": null }, + "3866": { "label": "13/118", "naklon": null }, + "3136": { "label": "14/1", "naklon": 0 }, + "3137": { "label": "14/2", "naklon": 0 }, + "3135": { "label": "14/3", "naklon": 0 }, + "3149": { "label": "14/4", "naklon": 0 }, + "3142": { "label": "14/5", "naklon": 0 }, + "3342": { "label": "14/6", "naklon": 0 }, + "3340": { "label": "14/7", "naklon": 0 }, + "3152": { "label": "14/8", "naklon": 0 }, + "3886": { "label": "14/9", "naklon": 0 }, + "3341": { "label": "14/10", "naklon": null }, + "3352": { "label": "14/11", "naklon": null }, + "3396": { "label": "15/1", "naklon": 5 }, + "2784": { "label": "15/2", "naklon": 5 }, + "2788": { "label": "15/3", "naklon": 5 }, + "2801": { "label": "15/4", "naklon": 5 }, + "2815": { "label": "15/5", "naklon": 5 }, + "2829": { "label": "15/6", "naklon": 5 }, + "2796": { "label": "15/7", "naklon": 5 }, + "2803": { "label": "15/8", "naklon": 5 }, + "4304": { "label": "15/8/1", "naklon": 5 }, + "4311": { "label": "15/8/2", "naklon": 5 }, + "2821": { "label": "15/9", "naklon": 5 }, + "3400": { "label": "15/10", "naklon": 5 }, + "2799": { "label": "15/11", "naklon": 5 }, + "2804": { "label": "15/12", "naklon": 5 }, + "4303": { "label": "15/12/1", "naklon": 5 }, + "4309": { "label": "15/12/2", "naklon": 5 }, + "2806": { "label": "15/13", "naklon": 5 }, + "2787": { "label": "15/14", "naklon": 5 }, + "2809": { "label": "15/15", "naklon": 5 }, + "2814": { "label": "15/16", "naklon": 0 }, + "3934": { "label": "15/17", "naklon": 0 }, + "3192": { "label": "15/18", "naklon": 0 }, + "2812": { "label": "15/19", "naklon": 0 }, + "4070": { "label": "15/20", "naklon": 0 }, + "2826": { "label": "15/21", "naklon": 0 }, + "2808": { "label": "15/22", "naklon": 3 }, + "2795": { "label": "15/23", "naklon": 3 }, + "2807": { "label": "15/24", "naklon": 3 }, + "2831": { "label": "15/25", "naklon": 0 }, + "2862": { "label": "15/26", "naklon": null }, + "2861": { "label": "15/27", "naklon": 0 }, + "2866": { "label": "15/28", "naklon": 0 }, + "3546": { "label": "15/28/1", "naklon": 0 }, + "4146": { "label": "15/29", "naklon": 0 }, + "3001": { "label": "15/29/1", "naklon": 0 }, + "2835": { "label": "15/30", "naklon": 0 }, + "2874": { "label": "15/31", "naklon": 0 }, + "2852": { "label": "15/32", "naklon": 0 }, + "2851": { "label": "15/33", "naklon": 0 }, + "3560": { "label": "15/33/1", "naklon": 0 }, + "2858": { "label": "15/34", "naklon": 0 }, + "4306": { "label": "15/34/1", "naklon": 0 }, + "2856": { "label": "15/35", "naklon": 0 }, + "2847": { "label": "15/36", "naklon": 0 }, + "3556": { "label": "15/36/1", "naklon": 0 }, + "3950": { "label": "15/37", "naklon": 0 }, + "2848": { "label": "15/38", "naklon": 0 }, + "2863": { "label": "15/39", "naklon": 0 }, + "4313": { "label": "15/39/1", "naklon": 0 }, + "2873": { "label": "15/40", "naklon": 0 }, + "2984": { "label": "15/40/1", "naklon": 0 }, + "2854": { "label": "15/41", "naklon": 0 }, + "2859": { "label": "15/42", "naklon": 0 }, + "2872": { "label": "15/43", "naklon": 0 }, + "2849": { "label": "15/44", "naklon": 0 }, + "2864": { "label": "15/45", "naklon": 0 }, + "3553": { "label": "15/46", "naklon": null }, + "3021": { "label": "15/47", "naklon": null }, + "3008": { "label": "15/47/1", "naklon": null }, + "3017": { "label": "15/48", "naklon": null }, + "3014": { "label": "15/49", "naklon": null }, + "2981": { "label": "15/50", "naklon": null }, + "3020": { "label": "15/51", "naklon": null }, + "3027": { "label": "15/52", "naklon": null }, + "3006": { "label": "15/53", "naklon": null }, + "3012": { "label": "15/54", "naklon": null }, + "2738": { "label": "15/55", "naklon": 0 }, + "2725": { "label": "15/56", "naklon": 0 }, + "3016": { "label": "15/57", "naklon": null }, + "3005": { "label": "15/58", "naklon": null }, + "3009": { "label": "15/58/1", "naklon": null }, + "3010": { "label": "15/59", "naklon": 0 }, + "3538": { "label": "15/59/1", "naklon": 0 }, + "4145": { "label": "15/59/2", "naklon": 0 }, + "2713": { "label": "15/60", "naklon": 0 }, + "2789": { "label": "15/61", "naklon": 0 }, + "2736": { "label": "15/62", "naklon": 0 }, + "2739": { "label": "15/63", "naklon": 0 }, + "4346": { "label": "15/64", "naklon": 0 }, + "2731": { "label": "15/65", "naklon": 0 }, + "2818": { "label": "15/66", "naklon": 0 }, + "3557": { "label": "15/66/1", "naklon": 0 }, + "2822": { "label": "15/67", "naklon": 0 }, + "2833": { "label": "15/68", "naklon": 0 }, + "2834": { "label": "15/69", "naklon": 0 }, + "3097": { "label": "15/70", "naklon": 0 }, + "2824": { "label": "15/71", "naklon": 0 }, + "2828": { "label": "15/72", "naklon": 0 }, + "2600": { "label": "15/73", "naklon": 0 }, + "4314": { "label": "15/73/1", "naklon": 0 }, + "2832": { "label": "15/74", "naklon": 0 }, + "4360": { "label": "15/75", "naklon": 0 }, + "2846": { "label": "15/76", "naklon": 0 }, + "2584": { "label": "15/77", "naklon": 0 }, + "2843": { "label": "15/78", "naklon": 0 }, + "4308": { "label": "15/78/1", "naklon": 0 }, + "4144": { "label": "15/79", "naklon": null }, + "2844": { "label": "15/80", "naklon": 0 }, + "2842": { "label": "15/81", "naklon": 0 }, + "2838": { "label": "15/82", "naklon": 0 }, + "2837": { "label": "15/83", "naklon": null }, + "3555": { "label": "15/83/1", "naklon": null }, + "2839": { "label": "15/84", "naklon": 0 }, + "2830": { "label": "15/85", "naklon": 0 }, + "4066": { "label": "15/86", "naklon": 0 }, + "2836": { "label": "15/87", "naklon": 0 }, + "2911": { "label": "15/88", "naklon": 0 }, + "2825": { "label": "15/89", "naklon": 0 }, + "2811": { "label": "15/90", "naklon": 0 }, + "3740": { "label": "15/94", "naklon": 15 }, + "2734": { "label": "15/95", "naklon": 15 }, + "3105": { "label": "15/96", "naklon": 15 }, + "2732": { "label": "15/97", "naklon": 15 }, + "2727": { "label": "15/98", "naklon": 15 }, + "2735": { "label": "15/99", "naklon": 15 }, + "3926": { "label": "15/100", "naklon": 15 }, + "2918": { "label": "15/101", "naklon": 0 }, + "2705": { "label": "15/102", "naklon": 10 }, + "2708": { "label": "15/103", "naklon": 10 }, + "2721": { "label": "15/104", "naklon": 10 }, + "2719": { "label": "15/105", "naklon": 10 }, + "2919": { "label": "15/106", "naklon": 10 }, + "3101": { "label": "15/107", "naklon": 10 }, + "2853": { "label": "15/108", "naklon": 10 }, + "2715": { "label": "15/109", "naklon": 10 }, + "2712": { "label": "15/110", "naklon": 0 }, + "2711": { "label": "15/111", "naklon": 0 }, + "2709": { "label": "15/112", "naklon": 0 }, + "2710": { "label": "15/113", "naklon": 0 }, + "2907": { "label": "15/114", "naklon": 0 }, + "2906": { "label": "15/115", "naklon": 0 }, + "2908": { "label": "15/116", "naklon": 0 }, + "2901": { "label": "15/117", "naklon": 0 }, + "2913": { "label": "15/118", "naklon": 0 }, + "3656": { "label": "15/119", "naklon": 0 }, + "2781": { "label": "15/120", "naklon": 0 }, + "2802": { "label": "15/121", "naklon": 0 }, + "2791": { "label": "15/122", "naklon": 0 }, + "2783": { "label": "15/123", "naklon": 0 }, + "2794": { "label": "15/124", "naklon": 0 }, + "3139": { "label": "15/125", "naklon": 0 }, + "3229": { "label": "15/126", "naklon": 5 }, + "3239": { "label": "15/127", "naklon": 5 }, + "3230": { "label": "15/128", "naklon": 5 }, + "4016": { "label": "15/129", "naklon": null }, + "3608": { "label": "16/16A", "naklon": 0 }, + "4151": { "label": "16/16B", "naklon": 0 }, + "3710": { "label": "16/1", "naklon": 0 }, + "3726": { "label": "16/2", "naklon": 0 }, + "3743": { "label": "16/3", "naklon": 0 }, + "3724": { "label": "16/4", "naklon": 0 }, + "3712": { "label": "16/5", "naklon": 0 }, + "3739": { "label": "16/6", "naklon": 0 }, + "3742": { "label": "16/7", "naklon": 0 }, + "3731": { "label": "16/8", "naklon": 0 }, + "3727": { "label": "16/9", "naklon": 0 }, + "3729": { "label": "16/10", "naklon": 0 }, + "3736": { "label": "16/11", "naklon": 0 }, + "3713": { "label": "16/12", "naklon": 0 }, + "3715": { "label": "16/13", "naklon": 0 }, + "3733": { "label": "16/14", "naklon": 0 }, + "3732": { "label": "16/15", "naklon": 0 }, + "3634": { "label": "16/17", "naklon": 0 }, + "3610": { "label": "16/18", "naklon": 0 }, + "3626": { "label": "16/19", "naklon": 0 }, + "3618": { "label": "16/20", "naklon": 0 }, + "3619": { "label": "16/21", "naklon": 0 }, + "3628": { "label": "16/22", "naklon": 0 }, + "3615": { "label": "16/23", "naklon": 0 }, + "3609": { "label": "16/24", "naklon": 0 }, + "3606": { "label": "16/25", "naklon": 0 }, + "3624": { "label": "16/26", "naklon": 0 }, + "3627": { "label": "16/27", "naklon": 0 }, + "3607": { "label": "16/28", "naklon": 0 }, + "4370": { "label": "16/29", "naklon": 0 }, + "3692": { "label": "16/30", "naklon": 0 }, + "3614": { "label": "16/31", "naklon": 0 }, + "3623": { "label": "16/32", "naklon": 0 }, + "4373": { "label": "16/33", "naklon": 0 }, + "3620": { "label": "16/34", "naklon": 0 }, + "3685": { "label": "16/35", "naklon": 0 }, + "3616": { "label": "16/36", "naklon": 0 }, + "3686": { "label": "16/37", "naklon": 0 }, + "3688": { "label": "16/38", "naklon": 0 }, + "3684": { "label": "16/39", "naklon": 0 }, + "3825": { "label": "16/40", "naklon": 0 }, + "3865": { "label": "16/41", "naklon": 0 }, + "3824": { "label": "16/42", "naklon": 0 }, + "3871": { "label": "16/43", "naklon": 0 }, + "3801": { "label": "16/44", "naklon": 0 }, + "3862": { "label": "16/45", "naklon": 0 }, + "3876": { "label": "16/46", "naklon": 0 }, + "3861": { "label": "16/47", "naklon": 0 }, + "4215": { "label": "16/48", "naklon": 0 }, + "3605": { "label": "16/49", "naklon": 10 }, + "3603": { "label": "16/50", "naklon": 10 }, + "3592": { "label": "16/51", "naklon": 10 }, + "3598": { "label": "16/52", "naklon": 10 }, + "3594": { "label": "16/53", "naklon": 10 }, + "3593": { "label": "16/54", "naklon": 10 }, + "3630": { "label": "16/55", "naklon": 10 }, + "3763": { "label": "16/56", "naklon": 10 }, + "3746": { "label": "16/57", "naklon": 10 }, + "3699": { "label": "16/58", "naklon": 0 }, + "3698": { "label": "16/59", "naklon": 0 }, + "3709": { "label": "16/60", "naklon": null }, + "3708": { "label": "16/61", "naklon": 0 }, + "3703": { "label": "16/62", "naklon": null }, + "3700": { "label": "16/63", "naklon": 0 }, + "3701": { "label": "16/64", "naklon": null }, + "3704": { "label": "16/65", "naklon": 0 }, + "3707": { "label": "16/66", "naklon": null }, + "3810": { "label": "16/67", "naklon": 0 }, + "4208": { "label": "16/68", "naklon": null }, + "3867": { "label": "16/69", "naklon": 0 }, + "4372": { "label": "16/70", "naklon": null }, + "3881": { "label": "16/71", "naklon": 0 }, + "4204": { "label": "16/72", "naklon": null }, + "3869": { "label": "16/73", "naklon": 0 }, + "4202": { "label": "16/74", "naklon": null }, + "3830": { "label": "16/75", "naklon": 0 }, + "3870": { "label": "16/76", "naklon": null }, + "3964": { "label": "16/77", "naklon": 0 }, + "3849": { "label": "16/78", "naklon": 0 }, + "3694": { "label": "16/79", "naklon": null }, + "3717": { "label": "16/80", "naklon": 0 }, + "3877": { "label": "16/81", "naklon": null }, + "3755": { "label": "16/82", "naklon": 0 }, + "3725": { "label": "16/83", "naklon": null }, + "3716": { "label": "16/84", "naklon": 0 }, + "3696": { "label": "16/85", "naklon": null }, + "3702": { "label": "16/86", "naklon": 0 }, + "3706": { "label": "16/87", "naklon": null }, + "3850": { "label": "16/88", "naklon": 0 }, + "3848": { "label": "16/89", "naklon": null }, + "3737": { "label": "16/90", "naklon": null }, + "3705": { "label": "16/91", "naklon": 0 }, + "3723": { "label": "16/92", "naklon": null }, + "3842": { "label": "16/93", "naklon": 0 }, + "3735": { "label": "16/94", "naklon": null }, + "3719": { "label": "16/95", "naklon": 0 }, + "3697": { "label": "16/96", "naklon": 0 }, + "3711": { "label": "16/97", "naklon": 0 }, + "4107": { "label": "16/98", "naklon": null }, + "4112": { "label": "16/99", "naklon": 5 }, + "4106": { "label": "16/100", "naklon": 5 }, + "4111": { "label": "16/101", "naklon": 5 }, + "4091": { "label": "16/102", "naklon": null }, + "4104": { "label": "16/103", "naklon": 5 }, + "4094": { "label": "16/104", "naklon": null }, + "4089": { "label": "16/105", "naklon": 5 }, + "4095": { "label": "16/106", "naklon": null }, + "4102": { "label": "16/107", "naklon": 5 }, + "4105": { "label": "16/108", "naklon": null }, + "3859": { "label": "16/109", "naklon": null }, + "4090": { "label": "16/110", "naklon": 5 }, + "4110": { "label": "16/111", "naklon": null }, + "4097": { "label": "16/112", "naklon": 5 }, + "4099": { "label": "16/113", "naklon": null }, + "4096": { "label": "16/114", "naklon": null }, + "4101": { "label": "16/115", "naklon": 5 }, + "4109": { "label": "16/116", "naklon": null }, + "4092": { "label": "16/117", "naklon": 5 }, + "3631": { "label": "16/118", "naklon": null }, + "3632": { "label": "16/119", "naklon": 0 }, + "3641": { "label": "16/120", "naklon": null }, + "3638": { "label": "16/121", "naklon": 0 }, + "3637": { "label": "16/122", "naklon": null }, + "4142": { "label": "16/123", "naklon": null }, + "4147": { "label": "16/124", "naklon": 5 }, + "4139": { "label": "16/125", "naklon": 5 }, + "3172": { "label": "20/30A", "naklon": 2 }, + "3164": { "label": "20/30B", "naklon": 2 }, + "3247": { "label": "20/1", "naklon": 10 }, + "3296": { "label": "20/2", "naklon": 10 }, + "3246": { "label": "20/3", "naklon": 10 }, + "3270": { "label": "20/4", "naklon": 10 }, + "3294": { "label": "20/5", "naklon": 10 }, + "3298": { "label": "20/6", "naklon": 10 }, + "3297": { "label": "20/7", "naklon": 10 }, + "3293": { "label": "20/8", "naklon": 10 }, + "3299": { "label": "20/9", "naklon": 10 }, + "3295": { "label": "20/10", "naklon": 10 }, + "3244": { "label": "20/11", "naklon": 10 }, + "3249": { "label": "20/12", "naklon": 10 }, + "3268": { "label": "20/13", "naklon": 10 }, + "3245": { "label": "20/14", "naklon": 10 }, + "3278": { "label": "20/15", "naklon": 10 }, + "3280": { "label": "20/16", "naklon": 10 }, + "3292": { "label": "20/17", "naklon": 10 }, + "3287": { "label": "20/18", "naklon": 10 }, + "3282": { "label": "20/19", "naklon": 10 }, + "3273": { "label": "20/20", "naklon": 0 }, + "3157": { "label": "20/21", "naklon": 0 }, + "3283": { "label": "20/22", "naklon": 0 }, + "3159": { "label": "20/23", "naklon": 0 }, + "3289": { "label": "20/24", "naklon": 0 }, + "3163": { "label": "20/25", "naklon": 0 }, + "3126": { "label": "20/26", "naklon": 0 }, + "3171": { "label": "20/27", "naklon": 0 }, + "3162": { "label": "20/28", "naklon": 0 }, + "3279": { "label": "20/29", "naklon": 10 }, + "3173": { "label": "20/31", "naklon": 0 }, + "3127": { "label": "20/32", "naklon": 0 }, + "3131": { "label": "20/33", "naklon": 0 }, + "3129": { "label": "20/34", "naklon": 0 }, + "3276": { "label": "20/35", "naklon": 2 }, + "3290": { "label": "20/36", "naklon": 2 }, + "3132": { "label": "20/37", "naklon": 0 }, + "3138": { "label": "20/38", "naklon": 0 }, + "3272": { "label": "20/39", "naklon": 0 }, + "3291": { "label": "20/40", "naklon": 0 }, + "3277": { "label": "20/41", "naklon": 10 }, + "3286": { "label": "20/42", "naklon": 10 }, + "3281": { "label": "20/43", "naklon": 10 }, + "3288": { "label": "20/44", "naklon": 10 }, + "3284": { "label": "20/45", "naklon": 10 }, + "3167": { "label": "20/46", "naklon": 10 }, + "3872": { "label": "20/47", "naklon": 0 }, + "3124": { "label": "20/48", "naklon": 0 }, + "3133": { "label": "20/49", "naklon": 0 }, + "3158": { "label": "20/50", "naklon": 0 }, + "3169": { "label": "20/51", "naklon": 0 }, + "3146": { "label": "20/52", "naklon": 0 }, + "3160": { "label": "20/53", "naklon": 0 }, + "3248": { "label": "20/54", "naklon": 0 }, + "3156": { "label": "20/55", "naklon": 0 }, + "3161": { "label": "20/56", "naklon": 0 }, + "3170": { "label": "20/57", "naklon": 0 }, + "3168": { "label": "20/58", "naklon": 0 }, + "3125": { "label": "20/59", "naklon": 0 }, + "3166": { "label": "20/60", "naklon": 0 }, + "3130": { "label": "20/61", "naklon": 0 }, + "3563": { "label": "20/62", "naklon": 0 }, + "3550": { "label": "20/63", "naklon": null }, + "3269": { "label": "20/67", "naklon": 0 }, + "2921": { "label": "21/1", "naklon": 0 }, + "2707": { "label": "21/2", "naklon": 0 }, + "2723": { "label": "21/3", "naklon": 0 }, + "2716": { "label": "21/4", "naklon": 0 }, + "2717": { "label": "21/5", "naklon": 0 }, + "2720": { "label": "21/6", "naklon": 0 }, + "2722": { "label": "21/7", "naklon": 0 }, + "2718": { "label": "21/8", "naklon": 0 }, + "2724": { "label": "21/9", "naklon": 0 }, + "2742": { "label": "21/10", "naklon": 0 }, + "2743": { "label": "21/11", "naklon": 0 }, + "2733": { "label": "21/12", "naklon": 0 }, + "2903": { "label": "21/14", "naklon": 0 }, + "2917": { "label": "21/15", "naklon": 0 }, + "2897": { "label": "21/16", "naklon": 0 }, + "2914": { "label": "21/17", "naklon": 0 }, + "2898": { "label": "21/18", "naklon": 0 }, + "2773": { "label": "21/19", "naklon": 0 }, + "2895": { "label": "21/20", "naklon": 0 }, + "2896": { "label": "21/21", "naklon": 0 }, + "2771": { "label": "21/22", "naklon": 0 }, + "2772": { "label": "21/23", "naklon": 0 }, + "2793": { "label": "21/24", "naklon": 0 }, + "2902": { "label": "21/25", "naklon": 0 }, + "2910": { "label": "21/26", "naklon": 0 }, + "2909": { "label": "21/27", "naklon": 0 }, + "2920": { "label": "21/28", "naklon": 0 }, + "2916": { "label": "21/29", "naklon": 0 }, + "2904": { "label": "21/30", "naklon": 0 }, + "2915": { "label": "21/31", "naklon": 0 }, + "2905": { "label": "21/32", "naklon": 0 }, + "2900": { "label": "21/33", "naklon": 0 }, + "2899": { "label": "21/34", "naklon": 0 }, + "2741": { "label": "21/36", "naklon": 0 }, + "2714": { "label": "21/37", "naklon": 0 }, + "2701": { "label": "21/38", "naklon": 0 }, + "2703": { "label": "21/39", "naklon": 0 }, + "2704": { "label": "21/40", "naklon": 0 }, + "2702": { "label": "21/41", "naklon": 0 }, + "2706": { "label": "21/42", "naklon": 0 }, + "2776": { "label": "21/43", "naklon": 0 }, + "2770": { "label": "21/44", "naklon": 0 }, + "2786": { "label": "21/45", "naklon": 0 }, + "2779": { "label": "21/46", "naklon": 0 }, + "2782": { "label": "21/47", "naklon": 0 }, + "2785": { "label": "21/48", "naklon": 0 }, + "2769": { "label": "21/49", "naklon": 0 }, + "3354": { "label": "21/50", "naklon": 0 }, + "2778": { "label": "21/51", "naklon": 0 }, + "2775": { "label": "21/52", "naklon": 0 }, + "2780": { "label": "21/53", "naklon": 0 }, + "2790": { "label": "21/54", "naklon": 0 }, + "2792": { "label": "21/55", "naklon": 0 }, + "2774": { "label": "21/56", "naklon": 0 }, + "2630": { "label": "22/1", "naklon": 0 }, + "2631": { "label": "22/2", "naklon": 0 }, + "2632": { "label": "22/3", "naklon": 0 }, + "2633": { "label": "22/4", "naklon": 0 }, + "2634": { "label": "22/5", "naklon": 0 }, + "2636": { "label": "22/6", "naklon": 0 }, + "4367": { "label": "22/7", "naklon": 0 }, + "2637": { "label": "22/8", "naklon": 0 }, + "2638": { "label": "22/9", "naklon": 0 }, + "2639": { "label": "22/10", "naklon": 0 }, + "2640": { "label": "22/11", "naklon": 0 }, + "2641": { "label": "22/12", "naklon": 0 }, + "2642": { "label": "22/13", "naklon": 0 }, + "2643": { "label": "22/14", "naklon": 0 }, + "2644": { "label": "22/15", "naklon": 0 }, + "2645": { "label": "22/16", "naklon": 0 }, + "2646": { "label": "22/17", "naklon": 0 }, + "2647": { "label": "22/18", "naklon": 0 }, + "2648": { "label": "22/19", "naklon": 0 }, + "2649": { "label": "22/20", "naklon": 0 }, + "2650": { "label": "22/21", "naklon": 0 }, + "2651": { "label": "22/22", "naklon": 0 }, + "4103": { "label": "22/23", "naklon": 0 }, + "2653": { "label": "22/24", "naklon": 0 }, + "2654": { "label": "22/25", "naklon": 0 }, + "2655": { "label": "22/26", "naklon": 0 }, + "2656": { "label": "22/27", "naklon": 0 }, + "2657": { "label": "22/28", "naklon": 0 }, + "2658": { "label": "22/29", "naklon": 0 }, + "2659": { "label": "22/30", "naklon": 0 }, + "2660": { "label": "22/31", "naklon": 0 }, + "2661": { "label": "22/32", "naklon": 0 }, + "3015": { "label": "22/32/1", "naklon": 0 }, + "2662": { "label": "22/33", "naklon": 0 }, + "2663": { "label": "22/34", "naklon": 0 }, + "2664": { "label": "22/35", "naklon": 0 }, + "2665": { "label": "22/36", "naklon": 0 }, + "2666": { "label": "22/37", "naklon": 0 }, + "2667": { "label": "22/38", "naklon": 0 }, + "2668": { "label": "22/39", "naklon": 0 }, + "2669": { "label": "22/40", "naklon": null }, + "2670": { "label": "22/41", "naklon": null }, + "2671": { "label": "22/42", "naklon": null }, + "3087": { "label": "23/9A", "naklon": 10 }, + "3090": { "label": "23/9B", "naklon": 10 }, + "3075": { "label": "23/1", "naklon": 0 }, + "3089": { "label": "23/2", "naklon": 0 }, + "3088": { "label": "23/3", "naklon": 0 }, + "3228": { "label": "23/4", "naklon": 10 }, + "2751": { "label": "23/5", "naklon": 10 }, + "3243": { "label": "23/6", "naklon": 10 }, + "4349": { "label": "23/7", "naklon": 10 }, + "3102": { "label": "23/8", "naklon": 10 }, + "3099": { "label": "23/10", "naklon": 10 }, + "3103": { "label": "23/11", "naklon": 10 }, + "3093": { "label": "23/12", "naklon": 10 }, + "3098": { "label": "23/13", "naklon": 10 }, + "3092": { "label": "23/14", "naklon": 10 }, + "3233": { "label": "23/15", "naklon": 0 }, + "3095": { "label": "23/16", "naklon": 0 }, + "4074": { "label": "23/17", "naklon": 0 }, + "2729": { "label": "23/18", "naklon": 0 }, + "3234": { "label": "23/19", "naklon": 0 }, + "3094": { "label": "23/20", "naklon": 0 }, + "2817": { "label": "23/21", "naklon": 0 }, + "3226": { "label": "23/22", "naklon": 0 }, + "3225": { "label": "23/23", "naklon": 0 }, + "3237": { "label": "23/24", "naklon": 0 }, + "4250": { "label": "23/25", "naklon": 0 }, + "3059": { "label": "23/26", "naklon": 10 }, + "3238": { "label": "23/27", "naklon": 10 }, + "3242": { "label": "23/28", "naklon": 10 }, + "3236": { "label": "23/29", "naklon": 10 }, + "3112": { "label": "23/30", "naklon": 10 }, + "3224": { "label": "23/31", "naklon": 0 }, + "4298": { "label": "23/32", "naklon": 10 }, + "4150": { "label": "23/33", "naklon": 10 }, + "3091": { "label": "23/34", "naklon": 10 }, + "3771": { "label": "25/1", "naklon": 5 }, + "3777": { "label": "25/2", "naklon": 5 }, + "3749": { "label": "25/3", "naklon": 5 }, + "3769": { "label": "25/4", "naklon": 5 }, + "3765": { "label": "25/5", "naklon": 5 }, + "3785": { "label": "25/6", "naklon": 5 }, + "3761": { "label": "25/7", "naklon": 5 }, + "3758": { "label": "25/8", "naklon": 5 }, + "3766": { "label": "25/9", "naklon": 5 }, + "3779": { "label": "25/10", "naklon": 5 }, + "3899": { "label": "25/11", "naklon": 10 }, + "3922": { "label": "25/12", "naklon": 10 }, + "3912": { "label": "25/13", "naklon": 10 }, + "3933": { "label": "25/14", "naklon": 10 }, + "3921": { "label": "25/15", "naklon": 10 }, + "4300": { "label": "25/16", "naklon": 10 }, + "3927": { "label": "25/17", "naklon": 10 }, + "3212": { "label": "25/18", "naklon": 10 }, + "3208": { "label": "25/19", "naklon": 10 }, + "3207": { "label": "25/20", "naklon": 10 }, + "4294": { "label": "25/21", "naklon": 10 }, + "3209": { "label": "25/22", "naklon": 10 }, + "3745": { "label": "25/23", "naklon": 10 }, + "3762": { "label": "25/24", "naklon": 10 }, + "3215": { "label": "25/25", "naklon": 10 }, + "3210": { "label": "25/26", "naklon": 10 }, + "3211": { "label": "25/27", "naklon": 10 }, + "3206": { "label": "25/28", "naklon": 10 }, + "3918": { "label": "25/29", "naklon": 5 }, + "3928": { "label": "25/30", "naklon": 5 }, + "3917": { "label": "25/31", "naklon": 5 }, + "4029": { "label": "25/32", "naklon": 0 }, + "4038": { "label": "25/33", "naklon": 0 }, + "4022": { "label": "25/34", "naklon": 0 }, + "3937": { "label": "25/35", "naklon": 0 }, + "3190": { "label": "25/36", "naklon": 0 }, + "3835": { "label": "25/37", "naklon": 0 }, + "3201": { "label": "25/38", "naklon": 0 }, + "3193": { "label": "25/39", "naklon": 0 }, + "3191": { "label": "25/40", "naklon": 0 }, + "3203": { "label": "25/41", "naklon": 0 }, + "4301": { "label": "25/42", "naklon": 0 }, + "3223": { "label": "25/43", "naklon": 0 }, + "3202": { "label": "25/44", "naklon": 0 }, + "3205": { "label": "25/45", "naklon": 0 }, + "3194": { "label": "25/46", "naklon": 0 }, + "3198": { "label": "25/47", "naklon": 0 }, + "3204": { "label": "25/48", "naklon": 0 }, + "3200": { "label": "25/49", "naklon": 0 }, + "3216": { "label": "25/50", "naklon": 0 }, + "3932": { "label": "25/51", "naklon": 5 }, + "3923": { "label": "25/52", "naklon": 5 }, + "3913": { "label": "25/53", "naklon": 5 }, + "3900": { "label": "25/54", "naklon": 5 }, + "4189": { "label": "25/55", "naklon": 10 }, + "4191": { "label": "25/56", "naklon": 10 }, + "3790": { "label": "25/57", "naklon": 10 }, + "4190": { "label": "25/58", "naklon": 10 }, + "4302": { "label": "25/59", "naklon": 0 }, + "4351": { "label": "25/60", "naklon": 0 }, + "4075": { "label": "25/61", "naklon": 0 }, + "4071": { "label": "25/62", "naklon": 0 }, + "3784": { "label": "25/63", "naklon": 0 }, + "4065": { "label": "25/64", "naklon": 0 }, + "4297": { "label": "25/65", "naklon": 0 }, + "4295": { "label": "25/66", "naklon": 0 }, + "4299": { "label": "25/67", "naklon": 0 }, + "3772": { "label": "25/68", "naklon": 0 }, + "3941": { "label": "25/69", "naklon": 0 }, + "3782": { "label": "25/70", "naklon": 0 }, + "4068": { "label": "25/71", "naklon": 0 }, + "4073": { "label": "25/72", "naklon": 0 }, + "3901": { "label": "25/73", "naklon": 5 }, + "4296": { "label": "25/74", "naklon": 5 }, + "3910": { "label": "25/75", "naklon": 5 }, + "4293": { "label": "25/76", "naklon": 5 }, + "3919": { "label": "25/77", "naklon": 5 }, + "3924": { "label": "25/78", "naklon": 5 }, + "3909": { "label": "25/79", "naklon": 5 }, + "3896": { "label": "25/80", "naklon": 5 }, + "3911": { "label": "25/81", "naklon": 5 }, + "2819": { "label": "25/82", "naklon": 15 }, + "3776": { "label": "25/83", "naklon": 15 }, + "3752": { "label": "25/84", "naklon": 15 }, + "4353": { "label": "25/85", "naklon": 15 }, + "3791": { "label": "25/86", "naklon": 0 }, + "3770": { "label": "25/87", "naklon": 0 }, + "3760": { "label": "25/88", "naklon": 0 }, + "3115": { "label": "25/89", "naklon": 0 }, + "3738": { "label": "25/90", "naklon": 0 }, + "3748": { "label": "25/91", "naklon": 0 }, + "3753": { "label": "25/92", "naklon": 0 }, + "3775": { "label": "25/93", "naklon": 0 }, + "3778": { "label": "25/94", "naklon": 5 }, + "4078": { "label": "25/95", "naklon": 5 }, + "4088": { "label": "25/96", "naklon": 5 }, + "3856": { "label": "25/97", "naklon": 5 }, + "4084": { "label": "25/98", "naklon": 5 }, + "4069": { "label": "25/99", "naklon": 5 }, + "4188": { "label": "25/100", "naklon": 5 }, + "4064": { "label": "25/101", "naklon": 5 }, + "3792": { "label": "25/102", "naklon": 5 }, + "3780": { "label": "25/103", "naklon": 5 }, + "4034": { "label": "25/104", "naklon": 5 }, + "4072": { "label": "25/105", "naklon": 5 }, + "3884": { "label": "25/106", "naklon": 5 }, + "3793": { "label": "25/107", "naklon": 5 }, + "3863": { "label": "25/108", "naklon": 5 }, + "3855": { "label": "25/109", "naklon": 5 }, + "3846": { "label": "33/1", "naklon": 0 }, + "3943": { "label": "33/2", "naklon": 0 }, + "3903": { "label": "33/3", "naklon": 0 }, + "3982": { "label": "33/4", "naklon": 0 }, + "3879": { "label": "33/5", "naklon": 0 }, + "3887": { "label": "33/6", "naklon": 0 }, + "3920": { "label": "33/7", "naklon": 5 }, + "3942": { "label": "33/8", "naklon": 5 }, + "3829": { "label": "33/9", "naklon": null }, + "3452": { "label": "34/79A", "naklon": 6 }, + "3460": { "label": "34/79B", "naklon": 6 }, + "3443": { "label": "34/90A", "naklon": 6 }, + "3445": { "label": "34/90B", "naklon": 6 }, + "3457": { "label": "34/90C", "naklon": 6 }, + "3461": { "label": "34/97A", "naklon": 6 }, + "3463": { "label": "34/97B", "naklon": 6 }, + "3426": { "label": "34/98A", "naklon": 6 }, + "3444": { "label": "34/98B", "naklon": 6 }, + "3453": { "label": "34/99A", "naklon": 6 }, + "3455": { "label": "34/99B", "naklon": 6 }, + "4009": { "label": "34/1", "naklon": 0 }, + "3602": { "label": "34/2", "naklon": 0 }, + "3441": { "label": "34/3", "naklon": 0 }, + "3464": { "label": "34/4", "naklon": 0 }, + "3883": { "label": "34/5", "naklon": 0 }, + "4098": { "label": "34/6", "naklon": 0 }, + "4003": { "label": "34/7", "naklon": 0 }, + "4004": { "label": "34/8", "naklon": 0 }, + "3888": { "label": "34/9", "naklon": 0 }, + "3997": { "label": "34/10", "naklon": 0 }, + "4006": { "label": "34/11", "naklon": 0 }, + "4000": { "label": "34/12", "naklon": 0 }, + "4011": { "label": "34/13", "naklon": 0 }, + "3999": { "label": "34/14", "naklon": 0 }, + "3981": { "label": "34/15", "naklon": 0 }, + "3988": { "label": "34/16", "naklon": 0 }, + "3986": { "label": "34/17", "naklon": 0 }, + "3998": { "label": "34/18", "naklon": 0 }, + "3983": { "label": "34/19", "naklon": 0 }, + "4005": { "label": "34/20", "naklon": 0 }, + "4001": { "label": "34/21", "naklon": 0 }, + "4008": { "label": "34/22", "naklon": 0 }, + "4002": { "label": "34/23", "naklon": 0 }, + "3996": { "label": "34/24", "naklon": 0 }, + "4007": { "label": "34/25", "naklon": 0 }, + "4113": { "label": "34/26", "naklon": 15 }, + "3595": { "label": "34/27", "naklon": 5 }, + "3599": { "label": "34/28", "naklon": 5 }, + "3601": { "label": "34/29", "naklon": 5 }, + "4205": { "label": "34/30", "naklon": 0 }, + "3987": { "label": "34/31", "naklon": null }, + "4214": { "label": "34/32", "naklon": 0 }, + "4226": { "label": "34/33", "naklon": 0 }, + "4209": { "label": "34/34", "naklon": 0 }, + "4201": { "label": "34/35", "naklon": 0 }, + "3440": { "label": "34/36", "naklon": 0 }, + "3465": { "label": "34/37", "naklon": 0 }, + "3446": { "label": "34/38", "naklon": 0 }, + "4039": { "label": "34/39", "naklon": 5 }, + "4057": { "label": "34/40", "naklon": 5 }, + "3985": { "label": "34/41", "naklon": 0 }, + "3882": { "label": "34/42", "naklon": 0 }, + "4040": { "label": "34/43", "naklon": 5 }, + "3231": { "label": "34/44", "naklon": 0 }, + "3227": { "label": "34/45", "naklon": 0 }, + "3431": { "label": "34/46", "naklon": 0 }, + "4013": { "label": "34/47", "naklon": 0 }, + "4045": { "label": "34/48", "naklon": 0 }, + "3949": { "label": "34/49", "naklon": 0 }, + "3953": { "label": "34/50", "naklon": 0 }, + "3952": { "label": "34/51", "naklon": 0 }, + "3995": { "label": "34/52", "naklon": 0 }, + "3992": { "label": "34/53", "naklon": 0 }, + "4198": { "label": "34/54", "naklon": 0 }, + "3935": { "label": "34/55", "naklon": 0 }, + "4050": { "label": "34/56", "naklon": 0 }, + "4049": { "label": "34/57", "naklon": 0 }, + "4054": { "label": "34/58", "naklon": 0 }, + "3663": { "label": "34/59", "naklon": 6 }, + "3661": { "label": "34/60", "naklon": 6 }, + "3664": { "label": "34/61", "naklon": 6 }, + "3660": { "label": "34/62", "naklon": 6 }, + "3662": { "label": "34/63", "naklon": 6 }, + "3665": { "label": "34/65", "naklon": 6 }, + "3667": { "label": "34/66", "naklon": 6 }, + "3675": { "label": "34/67", "naklon": 6 }, + "3666": { "label": "34/68", "naklon": 6 }, + "3652": { "label": "34/69", "naklon": 6 }, + "3458": { "label": "34/70", "naklon": 6 }, + "4425": { "label": "34/70/1", "naklon": 6 }, + "3459": { "label": "34/71", "naklon": 6 }, + "3435": { "label": "34/72", "naklon": 6 }, + "3448": { "label": "34/73", "naklon": 6 }, + "3451": { "label": "34/74", "naklon": 6 }, + "3442": { "label": "34/75", "naklon": 6 }, + "3449": { "label": "34/76", "naklon": 6 }, + "3450": { "label": "34/77", "naklon": 6 }, + "3433": { "label": "34/78", "naklon": 6 }, + "3432": { "label": "34/80", "naklon": 12 }, + "3470": { "label": "34/81", "naklon": 12 }, + "3438": { "label": "34/82", "naklon": 12 }, + "3439": { "label": "34/83", "naklon": 12 }, + "4028": { "label": "34/84", "naklon": 5 }, + "3596": { "label": "34/85", "naklon": 5 }, + "4021": { "label": "34/86", "naklon": 5 }, + "3437": { "label": "34/87", "naklon": 12 }, + "3428": { "label": "34/88", "naklon": 12 }, + "3430": { "label": "34/89", "naklon": 12 }, + "3454": { "label": "34/91", "naklon": 6 }, + "3492": { "label": "34/92", "naklon": 6 }, + "3462": { "label": "34/93", "naklon": 6 }, + "3427": { "label": "34/94", "naklon": 6 }, + "3434": { "label": "34/95", "naklon": 6 }, + "3456": { "label": "34/96", "naklon": 6 }, + "4307": { "label": "34/98/1", "naklon": 6 }, + "3968": { "label": "35/1", "naklon": 0 }, + "3969": { "label": "35/2", "naklon": 0 }, + "3947": { "label": "35/3", "naklon": 0 }, + "3979": { "label": "35/4", "naklon": 0 }, + "3959": { "label": "35/5", "naklon": 0 }, + "3948": { "label": "35/6", "naklon": 0 }, + "3961": { "label": "35/7", "naklon": 0 }, + "3956": { "label": "35/8", "naklon": 0 }, + "3604": { "label": "35/9", "naklon": 0 }, + "3944": { "label": "35/10", "naklon": 0 }, + "3960": { "label": "35/11", "naklon": 0 }, + "3958": { "label": "35/12", "naklon": 0 }, + "4036": { "label": "35/13", "naklon": 5 }, + "3893": { "label": "35/18", "naklon": 5 }, + "4108": { "label": "35/19", "naklon": 5 }, + "4017": { "label": "35/20", "naklon": 5 }, + "3963": { "label": "35/21", "naklon": 0 }, + "3658": { "label": "35/22", "naklon": 0 }, + "3975": { "label": "35/23", "naklon": 0 }, + "3980": { "label": "35/24", "naklon": 0 }, + "4012": { "label": "35/25", "naklon": 0 }, + "3655": { "label": "35/26", "naklon": 0 }, + "3962": { "label": "35/27", "naklon": 0 }, + "3945": { "label": "35/28", "naklon": 0 }, + "3569": { "label": "35/29", "naklon": 0 }, + "3429": { "label": "35/30", "naklon": 0 }, + "3657": { "label": "35/31", "naklon": 0 }, + "3646": { "label": "35/32", "naklon": 0 }, + "3622": { "label": "35/33", "naklon": 0 }, + "3612": { "label": "35/34", "naklon": 0 }, + "3955": { "label": "35/35", "naklon": 0 }, + "3878": { "label": "35/37", "naklon": 0 }, + "3965": { "label": "35/38", "naklon": 0 }, + "3970": { "label": "35/39", "naklon": 0 }, + "3611": { "label": "35/40", "naklon": 0 }, + "2635": { "label": "35/41", "naklon": 0 }, + "3978": { "label": "35/42", "naklon": 0 }, + "4213": { "label": "35/43", "naklon": 0 }, + "3984": { "label": "35/44", "naklon": 0 }, + "4218": { "label": "35/45", "naklon": 0 }, + "3973": { "label": "35/46", "naklon": 0 }, + "3974": { "label": "35/47", "naklon": 0 }, + "3759": { "label": "35/48", "naklon": 0 }, + "3844": { "label": "35/49", "naklon": 0 }, + "3804": { "label": "35/50", "naklon": 0 }, + "3831": { "label": "35/51", "naklon": 0 }, + "3643": { "label": "35/52", "naklon": 0 }, + "3966": { "label": "35/53", "naklon": 0 }, + "3971": { "label": "35/54", "naklon": 0 }, + "3650": { "label": "35/55", "naklon": 6 }, + "3651": { "label": "35/56", "naklon": 6 }, + "3669": { "label": "35/57", "naklon": 6 }, + "3648": { "label": "35/58", "naklon": 6 }, + "3645": { "label": "35/59", "naklon": 6 }, + "3659": { "label": "35/60", "naklon": 6 }, + "3647": { "label": "35/61", "naklon": 6 }, + "3644": { "label": "35/62", "naklon": 6 }, + "3671": { "label": "35/63", "naklon": 6 }, + "3682": { "label": "35/64", "naklon": 6 }, + "3672": { "label": "35/65", "naklon": 6 }, + "3683": { "label": "35/66", "naklon": 6 }, + "3673": { "label": "35/67", "naklon": 6 }, + "3674": { "label": "35/68", "naklon": 6 }, + "3679": { "label": "35/69", "naklon": 6 }, + "3649": { "label": "35/70", "naklon": 6 }, + "3687": { "label": "35/71", "naklon": 6 }, + "3677": { "label": "35/72", "naklon": 6 }, + "3690": { "label": "35/73", "naklon": 6 }, + "3691": { "label": "35/74", "naklon": 6 }, + "3676": { "label": "35/75", "naklon": 6 }, + "3680": { "label": "35/76", "naklon": 6 }, + "3668": { "label": "35/77", "naklon": 6 }, + "3681": { "label": "35/78", "naklon": 6 }, + "3670": { "label": "35/79", "naklon": 6 }, + "3689": { "label": "35/80", "naklon": 6 }, + "3678": { "label": "35/81", "naklon": 6 }, + "3693": { "label": "35/82", "naklon": 6 }, + "3654": { "label": "35/83", "naklon": null }, + "4086": { "label": "36/1", "naklon": 0 }, + "4085": { "label": "36/2", "naklon": 0 }, + "4083": { "label": "36/3", "naklon": 0 }, + "4087": { "label": "36/4", "naklon": 0 }, + "4077": { "label": "36/5", "naklon": 0 }, + "4082": { "label": "36/6", "naklon": 0 }, + "4186": { "label": "36/7", "naklon": 0 }, + "4206": { "label": "36/8", "naklon": 0 }, + "4080": { "label": "36/9", "naklon": 0 }, + "4081": { "label": "36/10", "naklon": 0 }, + "4210": { "label": "36/11", "naklon": 0 }, + "4079": { "label": "36/12", "naklon": 0 }, + "4076": { "label": "36/13", "naklon": 0 }, + "3852": { "label": "36/14", "naklon": 0 }, + "2813": { "label": "36/15", "naklon": 0 }, + "4219": { "label": "36/16", "naklon": 0 }, + "3104": { "label": "37/1A", "naklon": 15 }, + "3121": { "label": "37/1B", "naklon": 15 }, + "3113": { "label": "37/2", "naklon": 10 }, + "3118": { "label": "37/3", "naklon": 10 }, + "3111": { "label": "37/4", "naklon": 10 }, + "4020": { "label": "37/5", "naklon": 10 }, + "3119": { "label": "37/6", "naklon": 10 }, + "3110": { "label": "37/7", "naklon": 10 }, + "3108": { "label": "37/8", "naklon": 10 }, + "3107": { "label": "37/12", "naklon": 0 }, + "3199": { "label": "37/13", "naklon": 0 }, + "3120": { "label": "37/14", "naklon": 0 }, + "3122": { "label": "37/15", "naklon": 0 }, + "3908": { "label": "37/16", "naklon": 0 }, + "3114": { "label": "37/17", "naklon": 0 }, + "3105": { "label": "37/18", "naklon": 0 }, + "3116": { "label": "37/19", "naklon": 0 }, + "3106": { "label": "37/20", "naklon": 0 }, + "2887": { "label": "37/21", "naklon": 5 }, + "2888": { "label": "37/22", "naklon": 5 }, + "2877": { "label": "37/23", "naklon": 5 }, + "2891": { "label": "37/24", "naklon": 5 }, + "2886": { "label": "37/25", "naklon": 5 }, + "2892": { "label": "37/26", "naklon": 5 }, + "2882": { "label": "37/27", "naklon": 5 }, + "2883": { "label": "37/28", "naklon": 5 }, + "2876": { "label": "37/29", "naklon": 5 }, + "3109": { "label": "37/30", "naklon": 5 }, + "4152": { "label": "37/31", "naklon": 5 }, + "3117": { "label": "37/32", "naklon": 5 }, + "2870": { "label": "37/33", "naklon": 5 }, + "2867": { "label": "37/34", "naklon": 0 }, + "2865": { "label": "37/35", "naklon": 0 }, + "3096": { "label": "37/36", "naklon": 0 }, + "2871": { "label": "37/37", "naklon": 0 }, + "2884": { "label": "37/38", "naklon": 0 }, + "2855": { "label": "37/39", "naklon": 0 }, + "2878": { "label": "37/40", "naklon": 0 }, + "2889": { "label": "37/41", "naklon": 0 }, + "2879": { "label": "37/42", "naklon": 0 }, + "2850": { "label": "37/43", "naklon": 0 }, + "2894": { "label": "37/44", "naklon": 0 }, + "2880": { "label": "37/45", "naklon": 0 }, + "2893": { "label": "37/46", "naklon": 0 }, + "2890": { "label": "37/47", "naklon": 0 }, + "4355": { "label": "37/48", "naklon": 0 }, + "2885": { "label": "37/49", "naklon": 0 }, + "2875": { "label": "37/50", "naklon": 0 }, + "3486": { "label": "38/30A", "naklon": 5 }, + "3714": { "label": "38/30B", "naklon": 0 }, + "3483": { "label": "38/32A", "naklon": 5 }, + "3496": { "label": "38/32B", "naklon": 0 }, + "3487": { "label": "38/35A", "naklon": 5 }, + "3498": { "label": "38/35B", "naklon": 5 }, + "3578": { "label": "38/38A", "naklon": 5 }, + "3508": { "label": "38/38B", "naklon": 5 }, + "3787": { "label": "38/59A", "naklon": 5 }, + "3491": { "label": "38/59B", "naklon": 5 }, + "3568": { "label": "38/1", "naklon": null }, + "3502": { "label": "38/2", "naklon": 0 }, + "3836": { "label": "38/3", "naklon": 0 }, + "3588": { "label": "38/4", "naklon": 0 }, + "3493": { "label": "38/5", "naklon": 0 }, + "3580": { "label": "38/6", "naklon": 0 }, + "3572": { "label": "38/7", "naklon": 0 }, + "3506": { "label": "38/8", "naklon": 0 }, + "3503": { "label": "38/9", "naklon": 0 }, + "3579": { "label": "38/10", "naklon": 0 }, + "3586": { "label": "38/11", "naklon": 0 }, + "3495": { "label": "38/12", "naklon": 5 }, + "3492": { "label": "38/13", "naklon": 5 }, + "3532": { "label": "38/14", "naklon": 5 }, + "3574": { "label": "38/15", "naklon": 5 }, + "4140": { "label": "38/16", "naklon": 5 }, + "3795": { "label": "38/17", "naklon": 5 }, + "3788": { "label": "38/18", "naklon": 5 }, + "3796": { "label": "38/19", "naklon": 5 }, + "3797": { "label": "38/20", "naklon": 5 }, + "3798": { "label": "38/21", "naklon": 5 }, + "3786": { "label": "38/22", "naklon": 5 }, + "4067": { "label": "38/23", "naklon": 5 }, + "3773": { "label": "38/24", "naklon": 5 }, + "3774": { "label": "38/25", "naklon": 5 }, + "3789": { "label": "38/26", "naklon": 5 }, + "3520": { "label": "38/27", "naklon": null }, + "3577": { "label": "38/29", "naklon": 5 }, + "3530": { "label": "38/31", "naklon": null }, + "3488": { "label": "38/33", "naklon": 5 }, + "3505": { "label": "38/34", "naklon": 5 }, + "3497": { "label": "38/36", "naklon": 5 }, + "3490": { "label": "38/37", "naklon": 5 }, + "3585": { "label": "38/39", "naklon": 5 }, + "3582": { "label": "38/40", "naklon": 5 }, + "3507": { "label": "38/41", "naklon": 5 }, + "3484": { "label": "38/42", "naklon": 5 }, + "3501": { "label": "38/43", "naklon": 5 }, + "3581": { "label": "38/44", "naklon": 5 }, + "4192": { "label": "38/45", "naklon": 5 }, + "3576": { "label": "38/46", "naklon": 5 }, + "3489": { "label": "38/47", "naklon": 5 }, + "3573": { "label": "38/48", "naklon": 5 }, + "3504": { "label": "38/49", "naklon": 5 }, + "3794": { "label": "38/50", "naklon": 5 }, + "3485": { "label": "38/51", "naklon": 5 }, + "3482": { "label": "38/52", "naklon": 5 }, + "3575": { "label": "38/53", "naklon": 5 }, + "3499": { "label": "38/54", "naklon": 5 }, + "3494": { "label": "38/55", "naklon": 5 }, + "3583": { "label": "38/56", "naklon": 5 }, + "3570": { "label": "38/57", "naklon": 5 }, + "3500": { "label": "38/58", "naklon": 0 }, + "3510": { "label": "38/63", "naklon": null }, + "3512": { "label": "38/64", "naklon": null }, + "3535": { "label": "38/67", "naklon": null }, + "3531": { "label": "38/68", "naklon": null }, + "3537": { "label": "38/69", "naklon": null }, + "3522": { "label": "39/1", "naklon": 10 }, + "4018": { "label": "39/2", "naklon": 10 }, + "4019": { "label": "39/3", "naklon": 10 }, + "4154": { "label": "39/4", "naklon": 5 }, + "3907": { "label": "39/5", "naklon": 5 }, + "4148": { "label": "39/6", "naklon": 0 }, + "4153": { "label": "39/7", "naklon": 0 }, + "3938": { "label": "39/8", "naklon": 0 }, + "3802": { "label": "39/9", "naklon": 0 }, + "4015": { "label": "39/10", "naklon": 0 }, + "3929": { "label": "39/11", "naklon": 0 }, + "3946": { "label": "39/12", "naklon": 0 }, + "4014": { "label": "39/13", "naklon": 0 }, + "4155": { "label": "39/14", "naklon": 0 }, + "4149": { "label": "39/15", "naklon": 0 }, + "3642": { "label": "39/16", "naklon": 0 }, + "3636": { "label": "39/17", "naklon": 5 }, + "3991": { "label": "39/18", "naklon": 0 }, + "3994": { "label": "39/19", "naklon": 0 }, + "3990": { "label": "39/20", "naklon": 0 }, + "3967": { "label": "39/21", "naklon": 0 }, + "3977": { "label": "39/22", "naklon": 0 }, + "3757": { "label": "39/23", "naklon": 15 }, + "3633": { "label": "39/24", "naklon": 15 }, + "3744": { "label": "39/25", "naklon": 15 }, + "4023": { "label": "39/26", "naklon": 5 }, + "3720": { "label": "39/27", "naklon": 5 }, + "3734": { "label": "39/28", "naklon": 5 }, + "3741": { "label": "39/29", "naklon": 5 }, + "3721": { "label": "39/30", "naklon": 5 }, + "3845": { "label": "39/31", "naklon": 0 }, + "3840": { "label": "39/32", "naklon": 0 }, + "3837": { "label": "39/33", "naklon": null }, + "3839": { "label": "39/34", "naklon": 0 }, + "3542": { "label": "41/1", "naklon": null }, + "3566": { "label": "41/2", "naklon": null }, + "3548": { "label": "41/3", "naklon": null }, + "3515": { "label": "41/4", "naklon": null }, + "3559": { "label": "41/5", "naklon": null }, + "3509": { "label": "41/6", "naklon": null }, + "3524": { "label": "41/7", "naklon": null }, + "3518": { "label": "41/8", "naklon": null }, + "3182": { "label": "41/9", "naklon": null }, + "3187": { "label": "41/10", "naklon": null }, + "3195": { "label": "41/11", "naklon": 0 }, + "3857": { "label": "41/12", "naklon": 0 }, + "3183": { "label": "41/13", "naklon": 0 }, + "3177": { "label": "41/14", "naklon": 0 }, + "3189": { "label": "41/15", "naklon": 0 }, + "3186": { "label": "41/16", "naklon": 0 }, + "3178": { "label": "42/1", "naklon": 0 }, + "3219": { "label": "42/2", "naklon": 0 }, + "3475": { "label": "42/3", "naklon": 0 }, + "3175": { "label": "42/4", "naklon": 0 }, + "3222": { "label": "42/5", "naklon": 0 }, + "3221": { "label": "42/6", "naklon": 0 }, + "3181": { "label": "42/7", "naklon": 0 }, + "3180": { "label": "42/8", "naklon": 0 }, + "3218": { "label": "42/9", "naklon": 0 }, + "3176": { "label": "42/10", "naklon": 0 }, + "3174": { "label": "42/11", "naklon": 0 }, + "3220": { "label": "42/12", "naklon": 0 }, + "3533": { "label": "42/13", "naklon": null }, + "3543": { "label": "42/14", "naklon": null }, + "3554": { "label": "42/15", "naklon": null }, + "3549": { "label": "42/16", "naklon": null }, + "2857": { "label": "43/1", "naklon": 5 }, + "2752": { "label": "43/2", "naklon": 5 }, + "2753": { "label": "43/3", "naklon": 5 }, + "3024": { "label": "43/4", "naklon": 5 }, + "2754": { "label": "43/5", "naklon": 5 }, + "4423": { "label": "43/6", "naklon": 5 }, + "4368": { "label": "43/7", "naklon": 5 }, + "2978": { "label": "43/8", "naklon": 5 }, + "2868": { "label": "43/9", "naklon": 5 }, + "4377": { "label": "43/10", "naklon": 5 }, + "2757": { "label": "43/11", "naklon": 5 }, + "2970": { "label": "43/12", "naklon": 5 }, + "2758": { "label": "43/13", "naklon": 5 }, + "4378": { "label": "43/14", "naklon": 5 }, + "2759": { "label": "43/15", "naklon": 5 }, + "4342": { "label": "43/16", "naklon": 5 }, + "3026": { "label": "43/17", "naklon": null }, + "2986": { "label": "43/18", "naklon": null }, + "4343": { "label": "43/19", "naklon": null }, + "2760": { "label": "43/20", "naklon": null }, + "4379": { "label": "43/21", "naklon": null }, + "2971": { "label": "43/22", "naklon": null }, + "2761": { "label": "43/23", "naklon": null }, + "2762": { "label": "43/24", "naklon": null }, + "4339": { "label": "43/25", "naklon": null }, + "4380": { "label": "43/26", "naklon": null }, + "2975": { "label": "43/27", "naklon": null }, + "3003": { "label": "43/28", "naklon": null }, + "4338": { "label": "43/29", "naklon": null }, + "3002": { "label": "43/30", "naklon": null }, + "4345": { "label": "43/31", "naklon": null }, + "2979": { "label": "43/32", "naklon": null }, + "2989": { "label": "43/33", "naklon": null }, + "2996": { "label": "43/34", "naklon": null }, + "2972": { "label": "43/35", "naklon": null }, + "2988": { "label": "43/36", "naklon": null }, + "4344": { "label": "43/37", "naklon": null }, + "3022": { "label": "43/38", "naklon": null }, + "4341": { "label": "43/39", "naklon": null }, + "2983": { "label": "43/40", "naklon": null }, + "2995": { "label": "43/41", "naklon": null }, + "2763": { "label": "43/42", "naklon": null }, + "2764": { "label": "43/43", "naklon": null }, + "2765": { "label": "43/44", "naklon": null }, + "2766": { "label": "43/45", "naklon": null }, + "2767": { "label": "43/46", "naklon": null }, + "2768": { "label": "43/47", "naklon": null }, + "3018": { "label": "43/48", "naklon": null }, + "2982": { "label": "43/49", "naklon": null }, + "3019": { "label": "43/50", "naklon": 0 }, + "3013": { "label": "43/51", "naklon": null }, + "3007": { "label": "43/52", "naklon": null }, + "2980": { "label": "43/53", "naklon": null }, + "3011": { "label": "43/54", "naklon": null }, + "2672": { "label": "43/55", "naklon": null }, + "2673": { "label": "43/56", "naklon": null }, + "2674": { "label": "43/57", "naklon": null }, + "2675": { "label": "43/58", "naklon": null }, + "2676": { "label": "43/59", "naklon": null }, + "2677": { "label": "43/60", "naklon": null }, + "2678": { "label": "43/61", "naklon": null }, + "2679": { "label": "43/62", "naklon": null }, + "2680": { "label": "43/63", "naklon": null }, + "2840": { "label": "43/64", "naklon": null }, + "2682": { "label": "43/65", "naklon": null }, + "2683": { "label": "43/66", "naklon": null }, + "2684": { "label": "43/67", "naklon": 0 }, + "2685": { "label": "43/68", "naklon": null }, + "2686": { "label": "43/69", "naklon": null }, + "2687": { "label": "43/70", "naklon": null }, + "2688": { "label": "43/71", "naklon": null }, + "2689": { "label": "43/72", "naklon": null }, + "2690": { "label": "43/73", "naklon": null }, + "2691": { "label": "43/74", "naklon": null }, + "2692": { "label": "43/75", "naklon": null }, + "2693": { "label": "43/76", "naklon": 0 }, + "2694": { "label": "43/77", "naklon": null }, + "2695": { "label": "43/78", "naklon": null }, + "2696": { "label": "43/79", "naklon": 0 }, + "2697": { "label": "43/80", "naklon": null }, + "2698": { "label": "43/81", "naklon": 0 }, + "2699": { "label": "43/82", "naklon": null }, + "2700": { "label": "43/83", "naklon": 0 }, + "2744": { "label": "43/84", "naklon": null }, + "2745": { "label": "43/85", "naklon": 0 }, + "2746": { "label": "43/86", "naklon": null }, + "2747": { "label": "43/87", "naklon": 0 }, + "2748": { "label": "43/88", "naklon": null }, + "2749": { "label": "43/89", "naklon": 0 }, + "2841": { "label": "43/90", "naklon": null }, + "4237": { "label": "45/1", "naklon": 5 }, + "4226": { "label": "45/2", "naklon": 5 }, + "4242": { "label": "45/3", "naklon": 5 }, + "4179": { "label": "45/4", "naklon": 5 }, + "4247": { "label": "45/5", "naklon": 5 }, + "4245": { "label": "45/6", "naklon": 5 }, + "3872": { "label": "45/7", "naklon": 5 }, + "4175": { "label": "45/8", "naklon": 5 }, + "4236": { "label": "45/9", "naklon": 5 }, + "4170": { "label": "45/10", "naklon": 5 }, + "4238": { "label": "45/11", "naklon": 5 }, + "4246": { "label": "45/12", "naklon": 5 }, + "4166": { "label": "45/13", "naklon": 5 }, + "4227": { "label": "45/14", "naklon": 5 }, + "4171": { "label": "45/15", "naklon": 5 }, + "4180": { "label": "45/16", "naklon": 5 }, + "4244": { "label": "45/17", "naklon": 5 }, + "4199": { "label": "45/18", "naklon": 5 }, + "4239": { "label": "45/19", "naklon": 5 }, + "4207": { "label": "45/20", "naklon": 5 }, + "4223": { "label": "45/21", "naklon": 5 }, + "4230": { "label": "45/22", "naklon": 5 }, + "4233": { "label": "45/23", "naklon": 5 }, + "4222": { "label": "45/24", "naklon": 5 }, + "4217": { "label": "45/25", "naklon": 5 }, + "4243": { "label": "45/26", "naklon": 5 }, + "4200": { "label": "45/27", "naklon": 5 }, + "4228": { "label": "45/28", "naklon": 5 }, + "4211": { "label": "45/29", "naklon": 5 }, + "4234": { "label": "45/30", "naklon": 5 }, + "4235": { "label": "45/31", "naklon": 5 }, + "4203": { "label": "45/32", "naklon": 5 }, + "4240": { "label": "45/33", "naklon": 5 }, + "4224": { "label": "45/34", "naklon": 5 }, + "4232": { "label": "45/35", "naklon": 5 }, + "4231": { "label": "45/36", "naklon": 5 }, + "4161": { "label": "45/37", "naklon": 5 }, + "4225": { "label": "45/38", "naklon": 5 }, + "4241": { "label": "45/39", "naklon": 5 }, + "4229": { "label": "45/40", "naklon": 5 }, + "4221": { "label": "45/41", "naklon": 5 }, + "4212": { "label": "45/42", "naklon": 5 }, + "4216": { "label": "45/43", "naklon": 5 }, + "3864": { "label": "45/44", "naklon": null }, + "3806": { "label": "46/1", "naklon": 5 }, + "3813": { "label": "46/2", "naklon": 5 }, + "3815": { "label": "46/3", "naklon": 5 }, + "3807": { "label": "46/4", "naklon": 5 }, + "3895": { "label": "46/5", "naklon": 5 }, + "3809": { "label": "46/6", "naklon": 5 }, + "3820": { "label": "46/7", "naklon": 5 }, + "3805": { "label": "46/8", "naklon": 5 }, + "3894": { "label": "46/9", "naklon": 0 }, + "4055": { "label": "46/10", "naklon": 0 }, + "3812": { "label": "46/11", "naklon": 5 }, + "3822": { "label": "46/12", "naklon": 5 }, + "3821": { "label": "46/13", "naklon": 5 }, + "3808": { "label": "46/14", "naklon": 5 }, + "3799": { "label": "46/15", "naklon": 5 }, + "3816": { "label": "46/16", "naklon": 5 }, + "3751": { "label": "46/17", "naklon": 5 }, + "3814": { "label": "46/18", "naklon": 5 }, + "4044": { "label": "46/19", "naklon": 0 }, + "3931": { "label": "46/20", "naklon": 0 }, + "3902": { "label": "46/21", "naklon": 5 }, + "3916": { "label": "46/22", "naklon": 5 }, + "3892": { "label": "46/23", "naklon": 5 }, + "3914": { "label": "46/24", "naklon": 5 }, + "3898": { "label": "46/25", "naklon": 5 }, + "3897": { "label": "46/26", "naklon": 5 }, + "3885": { "label": "46/27", "naklon": 5 }, + "3906": { "label": "46/28", "naklon": 5 }, + "3930": { "label": "46/29", "naklon": 0 }, + "3936": { "label": "46/30", "naklon": 0 }, + "3860": { "label": "46/31", "naklon": 5 }, + "3841": { "label": "46/32", "naklon": 5 }, + "3873": { "label": "46/33", "naklon": 5 }, + "3854": { "label": "46/34", "naklon": 5 }, + "3939": { "label": "46/35", "naklon": 5 }, + "3858": { "label": "46/36", "naklon": 5 }, + "3940": { "label": "46/37", "naklon": 5 }, + "4035": { "label": "46/38", "naklon": 5 }, + "3373": { "label": "47/1", "naklon": 0 }, + "3374": { "label": "47/2", "naklon": 0 }, + "3384": { "label": "47/3", "naklon": 0 }, + "3385": { "label": "47/4", "naklon": 0 }, + "4051": { "label": "48/1", "naklon": 5 }, + "4041": { "label": "48/2", "naklon": 5 }, + "4056": { "label": "48/3", "naklon": 5 }, + "3875": { "label": "48/4", "naklon": 5 }, + "4061": { "label": "48/5", "naklon": 5 }, + "4047": { "label": "48/6", "naklon": 5 }, + "4060": { "label": "48/7", "naklon": 5 }, + "4059": { "label": "48/8", "naklon": 5 }, + "4058": { "label": "48/9", "naklon": 5 }, + "3635": { "label": "48/10", "naklon": 5 }, + "3640": { "label": "48/11", "naklon": 5 }, + "3747": { "label": "48/12", "naklon": 5 }, + "3629": { "label": "48/13", "naklon": 5 }, + "4048": { "label": "48/14", "naklon": 5 }, + "4063": { "label": "48/15", "naklon": 5 }, + "4062": { "label": "48/16", "naklon": 5 }, + "4043": { "label": "48/17", "naklon": 5 }, + "4052": { "label": "48/18", "naklon": 5 }, + "4042": { "label": "48/19", "naklon": 5 }, + "4053": { "label": "48/20", "naklon": 5 }, + "4167": { "label": "50/15A", "naklon": null }, + "4159": { "label": "50/15B", "naklon": null }, + "4183": { "label": "50/1", "naklon": 0 }, + "4157": { "label": "50/2", "naklon": 0 }, + "4160": { "label": "50/3", "naklon": 0 }, + "4173": { "label": "50/4", "naklon": 0 }, + "4177": { "label": "50/5", "naklon": 0 }, + "4174": { "label": "50/6", "naklon": 0 }, + "4178": { "label": "50/7", "naklon": 0 }, + "4195": { "label": "50/8", "naklon": 0 }, + "4169": { "label": "50/9", "naklon": 0 }, + "4162": { "label": "50/10", "naklon": 0 }, + "4158": { "label": "50/11", "naklon": 0 }, + "4182": { "label": "50/12", "naklon": 0 }, + "4194": { "label": "50/13", "naklon": 0 }, + "4184": { "label": "50/14", "naklon": 0 }, + "4197": { "label": "50/16", "naklon": null }, + "4164": { "label": "50/17", "naklon": null }, + "3306": { "label": "50/18", "naklon": null }, + "4168": { "label": "50/19", "naklon": null }, + "4193": { "label": "50/20", "naklon": null }, + "4187": { "label": "50/21", "naklon": null }, + "4163": { "label": "50/22", "naklon": null }, + "4165": { "label": "50/23", "naklon": null }, + "4185": { "label": "50/24", "naklon": null }, + "3904": { "label": "50/25", "naklon": null }, + "2619": { "label": "53/1", "naklon": 0 }, + "2623": { "label": "53/2", "naklon": 0 }, + "2617": { "label": "53/3", "naklon": 0 }, + "2622": { "label": "53/4", "naklon": 0 }, + "2618": { "label": "53/5", "naklon": 0 }, + "2626": { "label": "53/6", "naklon": 0 }, + "2869": { "label": "53/7", "naklon": 0 }, + "2613": { "label": "53/8", "naklon": 0 }, + "2608": { "label": "53/9", "naklon": 0 }, + "2611": { "label": "53/10", "naklon": 0 }, + "2598": { "label": "53/11", "naklon": 0 }, + "3528": { "label": "53/12", "naklon": 0 }, + "3545": { "label": "53/13", "naklon": 0 }, + "2620": { "label": "53/14", "naklon": 0 }, + "2612": { "label": "53/15", "naklon": 0 }, + "2615": { "label": "53/16", "naklon": 0 }, + "3722": { "label": "53/17", "naklon": 0 }, + "2624": { "label": "53/18", "naklon": 0 }, + "2609": { "label": "53/19", "naklon": 0 }, + "2625": { "label": "53/20", "naklon": 0 }, + "2602": { "label": "53/21", "naklon": 0 }, + "2610": { "label": "53/22", "naklon": 0 }, + "2599": { "label": "53/23", "naklon": 0 }, + "2605": { "label": "53/24", "naklon": 0 }, + "2593": { "label": "53/25", "naklon": 0 }, + "3074": { "label": "53/26", "naklon": 0 }, + "2740": { "label": "53/27", "naklon": 0 }, + "2614": { "label": "53/28", "naklon": 0 }, + "2601": { "label": "53/29", "naklon": 0 }, + "4196": { "label": "53/30", "naklon": 0 }, + "2607": { "label": "53/31", "naklon": 0 }, + "2582": { "label": "53/32", "naklon": 0 }, + "2594": { "label": "53/33", "naklon": 0 }, + "2589": { "label": "53/34", "naklon": 0 }, + "2596": { "label": "53/35", "naklon": 0 }, + "2603": { "label": "53/36", "naklon": 0 }, + "2597": { "label": "53/37", "naklon": 0 }, + "2590": { "label": "53/38", "naklon": 0 }, + "2581": { "label": "53/39", "naklon": 0 }, + "2583": { "label": "53/40", "naklon": 0 }, + "2580": { "label": "53/41", "naklon": 0 }, + "2579": { "label": "53/42", "naklon": 0 }, + "2797": { "label": "53/43", "naklon": 0 }, + "2577": { "label": "53/44", "naklon": 0 }, + "2586": { "label": "53/45", "naklon": 0 }, + "2588": { "label": "53/46", "naklon": 0 }, + "2591": { "label": "53/47", "naklon": 0 }, + "2592": { "label": "53/48", "naklon": 0 }, + "2573": { "label": "53/49", "naklon": 0 }, + "2595": { "label": "53/50", "naklon": 0 }, + "2587": { "label": "53/51", "naklon": 0 }, + "2578": { "label": "53/52", "naklon": 0 }, + "2574": { "label": "53/53", "naklon": 0 }, + "2571": { "label": "53/54", "naklon": 0 }, + "2570": { "label": "53/55", "naklon": 0 }, + "2576": { "label": "53/56", "naklon": 0 }, + "2881": { "label": "53/57", "naklon": 0 }, + "2575": { "label": "53/58", "naklon": 0 }, + "2572": { "label": "53/59", "naklon": 0 }, + "2569": { "label": "53/60", "naklon": 0 }, + "4324": { "label": "55/1", "naklon": 0 }, + "4319": { "label": "55/2", "naklon": 0 }, + "4327": { "label": "55/3", "naklon": 0 }, + "4333": { "label": "55/4", "naklon": 0 }, + "4332": { "label": "55/5", "naklon": 0 }, + "4320": { "label": "55/6", "naklon": 0 }, + "4317": { "label": "55/7", "naklon": 0 }, + "4318": { "label": "55/8", "naklon": 0 }, + "4328": { "label": "55/9", "naklon": 0 }, + "4323": { "label": "55/10", "naklon": 0 }, + "4325": { "label": "55/11", "naklon": 0 }, + "4326": { "label": "55/12", "naklon": 0 }, + "4316": { "label": "55/13", "naklon": 0 }, + "4322": { "label": "55/14", "naklon": 0 }, + "4331": { "label": "55/15", "naklon": 0 }, + "4321": { "label": "55/16", "naklon": 0 }, + "4315": { "label": "55/17", "naklon": 0 }, + "4329": { "label": "55/18", "naklon": 0 }, + "4334": { "label": "55/19", "naklon": 0 }, + "4330": { "label": "55/20", "naklon": 0 } +}; + + +let svetlaSorted = [{ "label": "1/3A", "node": 3993, "naklon": 0 }, +{ "label": "1/3B", "node": 3989, "naklon": 15 }, +{ "label": "1/1", "node": 3976, "naklon": 0 }, +{ "label": "1/2", "node": 4181, "naklon": 0 }, +{ "label": "1/4", "node": 4376, "naklon": 15 }, +{ "label": "1/5", "node": 3868, "naklon": 15 }, +{ "label": "1/6", "node": 3728, "naklon": 15 }, +{ "label": "1/7", "node": 3730, "naklon": 0 }, +{ "label": "1/8", "node": 4374, "naklon": 0 }, +{ "label": "1/9", "node": 3718, "naklon": 15 }, +{ "label": "1/10", "node": 4375, "naklon": 15 }, +{ "label": "1/11", "node": 4172, "naklon": 15 }, +{ "label": "1/12", "node": 4176, "naklon": 15 }, +{ "label": "2/1", "node": 3800, "naklon": 5 }, +{ "label": "2/2", "node": 3823, "naklon": 5 }, +{ "label": "2/3", "node": 3905, "naklon": 5 }, +{ "label": "2/4", "node": 3803, "naklon": 5 }, +{ "label": "2/5", "node": 3817, "naklon": 5 }, +{ "label": "2/6", "node": 3818, "naklon": 5 }, +{ "label": "2/7", "node": 3811, "naklon": 5 }, +{ "label": "2/8", "node": 3915, "naklon": 5 }, +{ "label": "2/9", "node": 3843, "naklon": 10 }, +{ "label": "2/10", "node": 3827, "naklon": 10 }, +{ "label": "2/11", "node": 4220, "naklon": 10 }, +{ "label": "2/12", "node": 3826, "naklon": 10 }, +{ "label": "2/13", "node": 3834, "naklon": 10 }, +{ "label": "2/14", "node": 3838, "naklon": 10 }, +{ "label": "2/15", "node": 2823, "naklon": 10 }, +{ "label": "2/16", "node": 3750, "naklon": 10 }, +{ "label": "2/17", "node": 3378, "naklon": 0 }, +{ "label": "2/18", "node": 3376, "naklon": 0 }, +{ "label": "2/19", "node": 3379, "naklon": 0 }, +{ "label": "2/20", "node": 3285, "naklon": 0 }, +{ "label": "2/21", "node": 3382, "naklon": 0 }, +{ "label": "2/22", "node": 3383, "naklon": 0 }, +{ "label": "2/24", "node": 3375, "naklon": 0 }, +{ "label": "2/25", "node": 3381, "naklon": 0 }, +{ "label": "2/26", "node": 3380, "naklon": 0 }, +{ "label": "2/27", "node": 3828, "naklon": 10 }, +{ "label": "2/28", "node": 3377, "naklon": 0 }, +{ "label": "7/1", "node": 3591, "naklon": 0 }, +{ "label": "7/2", "node": 3587, "naklon": 0 }, +{ "label": "7/3", "node": 3468, "naklon": 0 }, +{ "label": "7/4", "node": 3466, "naklon": 0 }, +{ "label": "7/5", "node": 3474, "naklon": 0 }, +{ "label": "7/6", "node": 3481, "naklon": 0 }, +{ "label": "7/7", "node": 3589, "naklon": 0 }, +{ "label": "7/8", "node": 3472, "naklon": 0 }, +{ "label": "7/9", "node": 3473, "naklon": 0 }, +{ "label": "7/10", "node": 3584, "naklon": 0 }, +{ "label": "7/11", "node": 3571, "naklon": 0 }, +{ "label": "7/12", "node": 3476, "naklon": 0 }, +{ "label": "7/13", "node": 3590, "naklon": 0 }, +{ "label": "7/14", "node": 3478, "naklon": 0 }, +{ "label": "7/15", "node": 3471, "naklon": 0 }, +{ "label": "7/16", "node": 3467, "naklon": 0 }, +{ "label": "7/17", "node": 3479, "naklon": 0 }, +{ "label": "7/18", "node": 3480, "naklon": 0 }, +{ "label": "7/19", "node": 3477, "naklon": 0 }, +{ "label": "12/1", "node": 3362, "naklon": 0 }, +{ "label": "12/2", "node": 3355, "naklon": 0 }, +{ "label": "12/3", "node": 3356, "naklon": 0 }, +{ "label": "12/4", "node": 3349, "naklon": 0 }, +{ "label": "12/5", "node": 3357, "naklon": 0 }, +{ "label": "12/6", "node": 3350, "naklon": 0 }, +{ "label": "12/7", "node": 3353, "naklon": 0 }, +{ "label": "12/8", "node": 3539, "naklon": 0 }, +{ "label": "12/9", "node": 3050, "naklon": 0 }, +{ "label": "12/10", "node": 3361, "naklon": 0 }, +{ "label": "12/11", "node": 3360, "naklon": 0 }, +{ "label": "12/12", "node": 3358, "naklon": 0 }, +{ "label": "12/13", "node": 3541, "naklon": 0 }, +{ "label": "12/14", "node": 3551, "naklon": 0 }, +{ "label": "12/15", "node": 3514, "naklon": 0 }, +{ "label": "12/16", "node": 3547, "naklon": 0 }, +{ "label": "12/17", "node": 3562, "naklon": 0 }, +{ "label": "12/18", "node": 3525, "naklon": 0 }, +{ "label": "12/19", "node": 3558, "naklon": 0 }, +{ "label": "12/20", "node": 3511, "naklon": 0 }, +{ "label": "12/21", "node": 3058, "naklon": 0 }, +{ "label": "12/22", "node": 3062, "naklon": 0 }, +{ "label": "12/23", "node": 3070, "naklon": 0 }, +{ "label": "12/24", "node": 3447, "naklon": 0 }, +{ "label": "12/25", "node": 3056, "naklon": 0 }, +{ "label": "12/26", "node": 3057, "naklon": 0 }, +{ "label": "12/27", "node": 3071, "naklon": 0 }, +{ "label": "12/28", "node": 3061, "naklon": 0 }, +{ "label": "12/29", "node": 3069, "naklon": 0 }, +{ "label": "12/30", "node": 3077, "naklon": 0 }, +{ "label": "12/31", "node": 3080, "naklon": 0 }, +{ "label": "12/32", "node": 3081, "naklon": 0 }, +{ "label": "12/33", "node": 3078, "naklon": 0 }, +{ "label": "12/34", "node": 4037, "naklon": 0 }, +{ "label": "12/35", "node": 3067, "naklon": 0 }, +{ "label": "12/36", "node": 3051, "naklon": 0 }, +{ "label": "12/37", "node": 2924, "naklon": 0 }, +{ "label": "12/38", "node": 3060, "naklon": 0 }, +{ "label": "12/39", "node": 3073, "naklon": 0 }, +{ "label": "12/40", "node": 3469, "naklon": 0 }, +{ "label": "12/41", "node": 2923, "naklon": 0 }, +{ "label": "12/42", "node": 2925, "naklon": 0 }, +{ "label": "12/43", "node": 3359, "naklon": 0 }, +{ "label": "12/44", "node": 3055, "naklon": 0 }, +{ "label": "12/45", "node": 2922, "naklon": 0 }, +{ "label": "12/46", "node": 3084, "naklon": 0 }, +{ "label": "12/47", "node": 3064, "naklon": 0 }, +{ "label": "12/48", "node": 3066, "naklon": 0 }, +{ "label": "12/49", "node": 3072, "naklon": 0 }, +{ "label": "13/13A", "node": 3415, "naklon": 0 }, +{ "label": "13/13B", "node": 3409, "naklon": 0 }, +{ "label": "13/13C", "node": 3399, "naklon": 0 }, +{ "label": "13/29A", "node": 3410, "naklon": 0 }, +{ "label": "13/29B", "node": 3407, "naklon": 0 }, +{ "label": "13/34A", "node": 3405, "naklon": 0 }, +{ "label": "13/34B", "node": 3404, "naklon": 0 }, +{ "label": "13/45A", "node": 3392, "naklon": 0 }, +{ "label": "13/45B", "node": 3386, "naklon": 0 }, +{ "label": "13/60A", "node": 3303, "naklon": 3 }, +{ "label": "13/60B", "node": 3302, "naklon": 3 }, +{ "label": "13/70A", "node": 3319, "naklon": 6 }, +{ "label": "13/70B", "node": 3317, "naklon": 6 }, +{ "label": "13/70C", "node": 3326, "naklon": 6 }, +{ "label": "13/73A", "node": 3351, "naklon": 6 }, +{ "label": "13/73B", "node": 3313, "naklon": 6 }, +{ "label": "13/83A", "node": 3316, "naklon": 0 }, +{ "label": "13/83B", "node": 3320, "naklon": 0 }, +{ "label": "13/95A", "node": 3336, "naklon": 0 }, +{ "label": "13/95B", "node": 3323, "naklon": 0 }, +{ "label": "13/98A", "node": 3339, "naklon": 0 }, +{ "label": "13/98B", "node": 3333, "naklon": 0 }, +{ "label": "13/1", "node": 3425, "naklon": 0 }, +{ "label": "13/2", "node": 3419, "naklon": 0 }, +{ "label": "13/3", "node": 3416, "naklon": 0 }, +{ "label": "13/4", "node": 3332, "naklon": 0 }, +{ "label": "13/5", "node": 3422, "naklon": 0 }, +{ "label": "13/6", "node": 3417, "naklon": 0 }, +{ "label": "13/7", "node": 3418, "naklon": 0 }, +{ "label": "13/8", "node": 3424, "naklon": 0 }, +{ "label": "13/9", "node": 3334, "naklon": 0 }, +{ "label": "13/10", "node": 4363, "naklon": 0 }, +{ "label": "13/11", "node": 3423, "naklon": 0 }, +{ "label": "13/12", "node": 3406, "naklon": 0 }, +{ "label": "13/14", "node": 3411, "naklon": 0 }, +{ "label": "13/15", "node": 3412, "naklon": 0 }, +{ "label": "13/16", "node": 3413, "naklon": 0 }, +{ "label": "13/17", "node": 3414, "naklon": 0 }, +{ "label": "13/18", "node": 3391, "naklon": 0 }, +{ "label": "13/19", "node": 3370, "naklon": 0 }, +{ "label": "13/20", "node": 3369, "naklon": 0 }, +{ "label": "13/21", "node": 3408, "naklon": 0 }, +{ "label": "13/22", "node": 3393, "naklon": 0 }, +{ "label": "13/23", "node": 3128, "naklon": 0 }, +{ "label": "13/24", "node": 3197, "naklon": 0 }, +{ "label": "13/25", "node": 4364, "naklon": 0 }, +{ "label": "13/26", "node": 3155, "naklon": 0 }, +{ "label": "13/27", "node": 3196, "naklon": 0 }, +{ "label": "13/28", "node": 3144, "naklon": 0 }, +{ "label": "13/30", "node": 3150, "naklon": 0 }, +{ "label": "13/31", "node": 3390, "naklon": 0 }, +{ "label": "13/32", "node": 3401, "naklon": 0 }, +{ "label": "13/33", "node": 3275, "naklon": 0 }, +{ "label": "13/35", "node": 3371, "naklon": 0 }, +{ "label": "13/36", "node": 3389, "naklon": 0 }, +{ "label": "13/37", "node": 3388, "naklon": 0 }, +{ "label": "13/38", "node": 3365, "naklon": 0 }, +{ "label": "13/39", "node": 3363, "naklon": 0 }, +{ "label": "13/40", "node": 3397, "naklon": 0 }, +{ "label": "13/40/1", "node": 3567, "naklon": 0 }, +{ "label": "13/41", "node": 3387, "naklon": 0 }, +{ "label": "13/42", "node": 3403, "naklon": 0 }, +{ "label": "13/43", "node": 3147, "naklon": 0 }, +{ "label": "13/44", "node": 3141, "naklon": 0 }, +{ "label": "13/46", "node": 3364, "naklon": 0 }, +{ "label": "13/47", "node": 3367, "naklon": 0 }, +{ "label": "13/48", "node": 3368, "naklon": 0 }, +{ "label": "13/49", "node": 3402, "naklon": 0 }, +{ "label": "13/50", "node": 3366, "naklon": 0 }, +{ "label": "13/51", "node": 3395, "naklon": 0 }, +{ "label": "13/52", "node": 3372, "naklon": 0 }, +{ "label": "13/53", "node": 3394, "naklon": 0 }, +{ "label": "13/54", "node": 3308, "naklon": 0 }, +{ "label": "13/54/1", "node": 3847, "naklon": 0 }, +{ "label": "13/55", "node": 3312, "naklon": 3 }, +{ "label": "13/56", "node": 3309, "naklon": 3 }, +{ "label": "13/57", "node": 3311, "naklon": 3 }, +{ "label": "13/58", "node": 3310, "naklon": 3 }, +{ "label": "13/59", "node": 4365, "naklon": 3 }, +{ "label": "13/60/1", "node": 4093, "naklon": 3 }, +{ "label": "13/61", "node": 3304, "naklon": 3 }, +{ "label": "13/62", "node": 3307, "naklon": 3 }, +{ "label": "13/63", "node": 3271, "naklon": 3 }, +{ "label": "13/64", "node": 3301, "naklon": 3 }, +{ "label": "13/65", "node": 4366, "naklon": 3 }, +{ "label": "13/66", "node": 3300, "naklon": 3 }, +{ "label": "13/67", "node": 3185, "naklon": 0 }, +{ "label": "13/68", "node": 3184, "naklon": 0 }, +{ "label": "13/69", "node": 3188, "naklon": 0 }, +{ "label": "13/71", "node": 3343, "naklon": 6 }, +{ "label": "13/71/1", "node": 3819, "naklon": 6 }, +{ "label": "13/71/2", "node": 3880, "naklon": 6 }, +{ "label": "13/72", "node": 3348, "naklon": 6 }, +{ "label": "13/74", "node": 3344, "naklon": 6 }, +{ "label": "13/75", "node": 3346, "naklon": 6 }, +{ "label": "13/75/1", "node": 3597, "naklon": 6 }, +{ "label": "13/76", "node": 3345, "naklon": 6 }, +{ "label": "13/77", "node": 3322, "naklon": 0 }, +{ "label": "13/78", "node": 3325, "naklon": 0 }, +{ "label": "13/78/1", "node": 4310, "naklon": 0 }, +{ "label": "13/79", "node": 3315, "naklon": 0 }, +{ "label": "13/80", "node": 3328, "naklon": 0 }, +{ "label": "13/81", "node": 3321, "naklon": 0 }, +{ "label": "13/82", "node": 3324, "naklon": 0 }, +{ "label": "13/84", "node": 3140, "naklon": 0 }, +{ "label": "13/85", "node": 3153, "naklon": 0 }, +{ "label": "13/86", "node": 3145, "naklon": 0 }, +{ "label": "13/87", "node": 3134, "naklon": 0 }, +{ "label": "13/88", "node": 3151, "naklon": 0 }, +{ "label": "13/89", "node": 3143, "naklon": 0 }, +{ "label": "13/90", "node": 3318, "naklon": 0 }, +{ "label": "13/91", "node": 3347, "naklon": 0 }, +{ "label": "13/94", "node": 3314, "naklon": 0 }, +{ "label": "13/96", "node": 3331, "naklon": 0 }, +{ "label": "13/97", "node": 3327, "naklon": 0 }, +{ "label": "13/99", "node": 3329, "naklon": 0 }, +{ "label": "13/100", "node": 3337, "naklon": 0 }, +{ "label": "13/101", "node": 3330, "naklon": 0 }, +{ "label": "13/102", "node": 3335, "naklon": 0 }, +{ "label": "13/103", "node": 3420, "naklon": 0 }, +{ "label": "13/104", "node": 3421, "naklon": 0 }, +{ "label": "13/105", "node": 4361, "naklon": 0 }, +{ "label": "13/106", "node": 4362, "naklon": 0 }, +{ "label": "13/107", "node": 3526, "naklon": 0 }, +{ "label": "13/108", "node": 4424, "naklon": null }, +{ "label": "13/109", "node": 3561, "naklon": null }, +{ "label": "13/110", "node": 3527, "naklon": null }, +{ "label": "13/111", "node": 3521, "naklon": null }, +{ "label": "13/112", "node": 3552, "naklon": null }, +{ "label": "13/113", "node": 3544, "naklon": null }, +{ "label": "13/114", "node": 3534, "naklon": null }, +{ "label": "13/115", "node": 3516, "naklon": null }, +{ "label": "13/116", "node": 3513, "naklon": null }, +{ "label": "13/117", "node": 3565, "naklon": null }, +{ "label": "13/118", "node": 3866, "naklon": null }, +{ "label": "14/1", "node": 3136, "naklon": 0 }, +{ "label": "14/2", "node": 3137, "naklon": 0 }, +{ "label": "14/3", "node": 3135, "naklon": 0 }, +{ "label": "14/4", "node": 3149, "naklon": 0 }, +{ "label": "14/5", "node": 3142, "naklon": 0 }, +{ "label": "14/6", "node": 3342, "naklon": 0 }, +{ "label": "14/7", "node": 3340, "naklon": 0 }, +{ "label": "14/8", "node": 3152, "naklon": 0 }, +{ "label": "14/9", "node": 3886, "naklon": 0 }, +{ "label": "14/10", "node": 3341, "naklon": null }, +{ "label": "14/11", "node": 3352, "naklon": null }, +{ "label": "15/1", "node": 3396, "naklon": 5 }, +{ "label": "15/2", "node": 2784, "naklon": 5 }, +{ "label": "15/3", "node": 2788, "naklon": 5 }, +{ "label": "15/4", "node": 2801, "naklon": 5 }, +{ "label": "15/5", "node": 2815, "naklon": 5 }, +{ "label": "15/6", "node": 2829, "naklon": 5 }, +{ "label": "15/7", "node": 2796, "naklon": 5 }, +{ "label": "15/8", "node": 2803, "naklon": 5 }, +{ "label": "15/8/1", "node": 4304, "naklon": 5 }, +{ "label": "15/8/2", "node": 4311, "naklon": 5 }, +{ "label": "15/9", "node": 2821, "naklon": 5 }, +{ "label": "15/10", "node": 3400, "naklon": 5 }, +{ "label": "15/11", "node": 2799, "naklon": 5 }, +{ "label": "15/12", "node": 2804, "naklon": 5 }, +{ "label": "15/12/1", "node": 4303, "naklon": 5 }, +{ "label": "15/12/2", "node": 4309, "naklon": 5 }, +{ "label": "15/13", "node": 2806, "naklon": 5 }, +{ "label": "15/14", "node": 2787, "naklon": 5 }, +{ "label": "15/15", "node": 2809, "naklon": 5 }, +{ "label": "15/16", "node": 2814, "naklon": 0 }, +{ "label": "15/17", "node": 3934, "naklon": 0 }, +{ "label": "15/18", "node": 3192, "naklon": 0 }, +{ "label": "15/19", "node": 2812, "naklon": 0 }, +{ "label": "15/20", "node": 4070, "naklon": 0 }, +{ "label": "15/21", "node": 2826, "naklon": 0 }, +{ "label": "15/22", "node": 2808, "naklon": 3 }, +{ "label": "15/23", "node": 2795, "naklon": 3 }, +{ "label": "15/24", "node": 2807, "naklon": 3 }, +{ "label": "15/25", "node": 2831, "naklon": 0 }, +{ "label": "15/26", "node": 2862, "naklon": null }, +{ "label": "15/27", "node": 2861, "naklon": 0 }, +{ "label": "15/28", "node": 2866, "naklon": 0 }, +{ "label": "15/28/1", "node": 3546, "naklon": 0 }, +{ "label": "15/29", "node": 4146, "naklon": 0 }, +{ "label": "15/29/1", "node": 3001, "naklon": 0 }, +{ "label": "15/30", "node": 2835, "naklon": 0 }, +{ "label": "15/31", "node": 2874, "naklon": 0 }, +{ "label": "15/32", "node": 2852, "naklon": 0 }, +{ "label": "15/33", "node": 2851, "naklon": 0 }, +{ "label": "15/33/1", "node": 3560, "naklon": 0 }, +{ "label": "15/34", "node": 2858, "naklon": 0 }, +{ "label": "15/34/1", "node": 4306, "naklon": 0 }, +{ "label": "15/35", "node": 2856, "naklon": 0 }, +{ "label": "15/36", "node": 2847, "naklon": 0 }, +{ "label": "15/36/1", "node": 3556, "naklon": 0 }, +{ "label": "15/37", "node": 3950, "naklon": 0 }, +{ "label": "15/38", "node": 2848, "naklon": 0 }, +{ "label": "15/39", "node": 2863, "naklon": 0 }, +{ "label": "15/39/1", "node": 4313, "naklon": 0 }, +{ "label": "15/40", "node": 2873, "naklon": 0 }, +{ "label": "15/40/1", "node": 2984, "naklon": 0 }, +{ "label": "15/41", "node": 2854, "naklon": 0 }, +{ "label": "15/42", "node": 2859, "naklon": 0 }, +{ "label": "15/43", "node": 2872, "naklon": 0 }, +{ "label": "15/44", "node": 2849, "naklon": 0 }, +{ "label": "15/45", "node": 2864, "naklon": 0 }, +{ "label": "15/46", "node": 3553, "naklon": null }, +{ "label": "15/47", "node": 3021, "naklon": null }, +{ "label": "15/47/1", "node": 3008, "naklon": null }, +{ "label": "15/48", "node": 3017, "naklon": null }, +{ "label": "15/49", "node": 3014, "naklon": null }, +{ "label": "15/50", "node": 2981, "naklon": null }, +{ "label": "15/51", "node": 3020, "naklon": null }, +{ "label": "15/52", "node": 3027, "naklon": null }, +{ "label": "15/53", "node": 3006, "naklon": null }, +{ "label": "15/54", "node": 3012, "naklon": null }, +{ "label": "15/55", "node": 2738, "naklon": 0 }, +{ "label": "15/56", "node": 2725, "naklon": 0 }, +{ "label": "15/57", "node": 3016, "naklon": null }, +{ "label": "15/58", "node": 3005, "naklon": null }, +{ "label": "15/58/1", "node": 3009, "naklon": null }, +{ "label": "15/59", "node": 3010, "naklon": 0 }, +{ "label": "15/59/1", "node": 3538, "naklon": 0 }, +{ "label": "15/59/2", "node": 4145, "naklon": 0 }, +{ "label": "15/60", "node": 2713, "naklon": 0 }, +{ "label": "15/61", "node": 2789, "naklon": 0 }, +{ "label": "15/62", "node": 2736, "naklon": 0 }, +{ "label": "15/63", "node": 2739, "naklon": 0 }, +{ "label": "15/64", "node": 4346, "naklon": 0 }, +{ "label": "15/65", "node": 2731, "naklon": 0 }, +{ "label": "15/66", "node": 2818, "naklon": 0 }, +{ "label": "15/66/1", "node": 3557, "naklon": 0 }, +{ "label": "15/67", "node": 2822, "naklon": 0 }, +{ "label": "15/68", "node": 2833, "naklon": 0 }, +{ "label": "15/69", "node": 2834, "naklon": 0 }, +{ "label": "15/70", "node": 3097, "naklon": 0 }, +{ "label": "15/71", "node": 2824, "naklon": 0 }, +{ "label": "15/72", "node": 2828, "naklon": 0 }, +{ "label": "15/73", "node": 2600, "naklon": 0 }, +{ "label": "15/73/1", "node": 4314, "naklon": 0 }, +{ "label": "15/74", "node": 2832, "naklon": 0 }, +{ "label": "15/75", "node": 4360, "naklon": 0 }, +{ "label": "15/76", "node": 2846, "naklon": 0 }, +{ "label": "15/77", "node": 2584, "naklon": 0 }, +{ "label": "15/78", "node": 2843, "naklon": 0 }, +{ "label": "15/78/1", "node": 4308, "naklon": 0 }, +{ "label": "15/79", "node": 4144, "naklon": null }, +{ "label": "15/80", "node": 2844, "naklon": 0 }, +{ "label": "15/81", "node": 2842, "naklon": 0 }, +{ "label": "15/82", "node": 2838, "naklon": 0 }, +{ "label": "15/83", "node": 2837, "naklon": null }, +{ "label": "15/83/1", "node": 3555, "naklon": null }, +{ "label": "15/84", "node": 2839, "naklon": 0 }, +{ "label": "15/85", "node": 2830, "naklon": 0 }, +{ "label": "15/86", "node": 4066, "naklon": 0 }, +{ "label": "15/87", "node": 2836, "naklon": 0 }, +{ "label": "15/88", "node": 2911, "naklon": 0 }, +{ "label": "15/89", "node": 2825, "naklon": 0 }, +{ "label": "15/90", "node": 2811, "naklon": 0 }, +{ "label": "15/94", "node": 3740, "naklon": 15 }, +{ "label": "15/95", "node": 2734, "naklon": 15 }, +{ "label": "15/96", "node": 3105, "naklon": 15 }, +{ "label": "15/97", "node": 2732, "naklon": 15 }, +{ "label": "15/98", "node": 2727, "naklon": 15 }, +{ "label": "15/99", "node": 2735, "naklon": 15 }, +{ "label": "15/100", "node": 3926, "naklon": 15 }, +{ "label": "15/101", "node": 2918, "naklon": 0 }, +{ "label": "15/102", "node": 2705, "naklon": 10 }, +{ "label": "15/103", "node": 2708, "naklon": 10 }, +{ "label": "15/104", "node": 2721, "naklon": 10 }, +{ "label": "15/105", "node": 2719, "naklon": 10 }, +{ "label": "15/106", "node": 2919, "naklon": 10 }, +{ "label": "15/107", "node": 3101, "naklon": 10 }, +{ "label": "15/108", "node": 2853, "naklon": 10 }, +{ "label": "15/109", "node": 2715, "naklon": 10 }, +{ "label": "15/110", "node": 2712, "naklon": 0 }, +{ "label": "15/111", "node": 2711, "naklon": 0 }, +{ "label": "15/112", "node": 2709, "naklon": 0 }, +{ "label": "15/113", "node": 2710, "naklon": 0 }, +{ "label": "15/114", "node": 2907, "naklon": 0 }, +{ "label": "15/115", "node": 2906, "naklon": 0 }, +{ "label": "15/116", "node": 2908, "naklon": 0 }, +{ "label": "15/117", "node": 2901, "naklon": 0 }, +{ "label": "15/118", "node": 2913, "naklon": 0 }, +{ "label": "15/119", "node": 3656, "naklon": 0 }, +{ "label": "15/120", "node": 2781, "naklon": 0 }, +{ "label": "15/121", "node": 2802, "naklon": 0 }, +{ "label": "15/122", "node": 2791, "naklon": 0 }, +{ "label": "15/123", "node": 2783, "naklon": 0 }, +{ "label": "15/124", "node": 2794, "naklon": 0 }, +{ "label": "15/125", "node": 3139, "naklon": 0 }, +{ "label": "15/126", "node": 3229, "naklon": 5 }, +{ "label": "15/127", "node": 3239, "naklon": 5 }, +{ "label": "15/128", "node": 3230, "naklon": 5 }, +{ "label": "15/129", "node": 4016, "naklon": null }, +{ "label": "16/16A", "node": 3608, "naklon": 0 }, +{ "label": "16/16B", "node": 4151, "naklon": 0 }, +{ "label": "16/1", "node": 3710, "naklon": 0 }, +{ "label": "16/2", "node": 3726, "naklon": 0 }, +{ "label": "16/3", "node": 3743, "naklon": 0 }, +{ "label": "16/4", "node": 3724, "naklon": 0 }, +{ "label": "16/5", "node": 3712, "naklon": 0 }, +{ "label": "16/6", "node": 3739, "naklon": 0 }, +{ "label": "16/7", "node": 3742, "naklon": 0 }, +{ "label": "16/8", "node": 3731, "naklon": 0 }, +{ "label": "16/9", "node": 3727, "naklon": 0 }, +{ "label": "16/10", "node": 3729, "naklon": 0 }, +{ "label": "16/11", "node": 3736, "naklon": 0 }, +{ "label": "16/12", "node": 3713, "naklon": 0 }, +{ "label": "16/13", "node": 3715, "naklon": 0 }, +{ "label": "16/14", "node": 3733, "naklon": 0 }, +{ "label": "16/15", "node": 3732, "naklon": 0 }, +{ "label": "16/17", "node": 3634, "naklon": 0 }, +{ "label": "16/18", "node": 3610, "naklon": 0 }, +{ "label": "16/19", "node": 3626, "naklon": 0 }, +{ "label": "16/20", "node": 3618, "naklon": 0 }, +{ "label": "16/21", "node": 3619, "naklon": 0 }, +{ "label": "16/22", "node": 3628, "naklon": 0 }, +{ "label": "16/23", "node": 3615, "naklon": 0 }, +{ "label": "16/24", "node": 3609, "naklon": 0 }, +{ "label": "16/25", "node": 3606, "naklon": 0 }, +{ "label": "16/26", "node": 3624, "naklon": 0 }, +{ "label": "16/27", "node": 3627, "naklon": 0 }, +{ "label": "16/28", "node": 3607, "naklon": 0 }, +{ "label": "16/29", "node": 4370, "naklon": 0 }, +{ "label": "16/30", "node": 3692, "naklon": 0 }, +{ "label": "16/31", "node": 3614, "naklon": 0 }, +{ "label": "16/32", "node": 3623, "naklon": 0 }, +{ "label": "16/33", "node": 4373, "naklon": 0 }, +{ "label": "16/34", "node": 3620, "naklon": 0 }, +{ "label": "16/35", "node": 3685, "naklon": 0 }, +{ "label": "16/36", "node": 3616, "naklon": 0 }, +{ "label": "16/37", "node": 3686, "naklon": 0 }, +{ "label": "16/38", "node": 3688, "naklon": 0 }, +{ "label": "16/39", "node": 3684, "naklon": 0 }, +{ "label": "16/40", "node": 3825, "naklon": 0 }, +{ "label": "16/41", "node": 3865, "naklon": 0 }, +{ "label": "16/42", "node": 3824, "naklon": 0 }, +{ "label": "16/43", "node": 3871, "naklon": 0 }, +{ "label": "16/44", "node": 3801, "naklon": 0 }, +{ "label": "16/45", "node": 3862, "naklon": 0 }, +{ "label": "16/46", "node": 3876, "naklon": 0 }, +{ "label": "16/47", "node": 3861, "naklon": 0 }, +{ "label": "16/48", "node": 4215, "naklon": 0 }, +{ "label": "16/49", "node": 3605, "naklon": 10 }, +{ "label": "16/50", "node": 3603, "naklon": 10 }, +{ "label": "16/51", "node": 3592, "naklon": 10 }, +{ "label": "16/52", "node": 3598, "naklon": 10 }, +{ "label": "16/53", "node": 3594, "naklon": 10 }, +{ "label": "16/54", "node": 3593, "naklon": 10 }, +{ "label": "16/55", "node": 3630, "naklon": 10 }, +{ "label": "16/56", "node": 3763, "naklon": 10 }, +{ "label": "16/57", "node": 3746, "naklon": 10 }, +{ "label": "16/58", "node": 3699, "naklon": 0 }, +{ "label": "16/59", "node": 3698, "naklon": 0 }, +{ "label": "16/60", "node": 3709, "naklon": null }, +{ "label": "16/61", "node": 3708, "naklon": 0 }, +{ "label": "16/62", "node": 3703, "naklon": null }, +{ "label": "16/63", "node": 3700, "naklon": 0 }, +{ "label": "16/64", "node": 3701, "naklon": null }, +{ "label": "16/65", "node": 3704, "naklon": 0 }, +{ "label": "16/66", "node": 3707, "naklon": null }, +{ "label": "16/67", "node": 3810, "naklon": 0 }, +{ "label": "16/68", "node": 4208, "naklon": null }, +{ "label": "16/69", "node": 3867, "naklon": 0 }, +{ "label": "16/70", "node": 4372, "naklon": null }, +{ "label": "16/71", "node": 3881, "naklon": 0 }, +{ "label": "16/72", "node": 4204, "naklon": null }, +{ "label": "16/73", "node": 3869, "naklon": 0 }, +{ "label": "16/74", "node": 4202, "naklon": null }, +{ "label": "16/75", "node": 3830, "naklon": 0 }, +{ "label": "16/76", "node": 3870, "naklon": null }, +{ "label": "16/77", "node": 3964, "naklon": 0 }, +{ "label": "16/78", "node": 3849, "naklon": 0 }, +{ "label": "16/79", "node": 3694, "naklon": null }, +{ "label": "16/80", "node": 3717, "naklon": 0 }, +{ "label": "16/81", "node": 3877, "naklon": null }, +{ "label": "16/82", "node": 3755, "naklon": 0 }, +{ "label": "16/83", "node": 3725, "naklon": null }, +{ "label": "16/84", "node": 3716, "naklon": 0 }, +{ "label": "16/85", "node": 3696, "naklon": null }, +{ "label": "16/86", "node": 3702, "naklon": 0 }, +{ "label": "16/87", "node": 3706, "naklon": null }, +{ "label": "16/88", "node": 3850, "naklon": 0 }, +{ "label": "16/89", "node": 3848, "naklon": null }, +{ "label": "16/90", "node": 3737, "naklon": null }, +{ "label": "16/91", "node": 3705, "naklon": 0 }, +{ "label": "16/92", "node": 3723, "naklon": null }, +{ "label": "16/93", "node": 3842, "naklon": 0 }, +{ "label": "16/94", "node": 3735, "naklon": null }, +{ "label": "16/95", "node": 3719, "naklon": 0 }, +{ "label": "16/96", "node": 3697, "naklon": 0 }, +{ "label": "16/97", "node": 3711, "naklon": 0 }, +{ "label": "16/98", "node": 4107, "naklon": null }, +{ "label": "16/99", "node": 4112, "naklon": 5 }, +{ "label": "16/100", "node": 4106, "naklon": 5 }, +{ "label": "16/101", "node": 4111, "naklon": 5 }, +{ "label": "16/102", "node": 4091, "naklon": null }, +{ "label": "16/103", "node": 4104, "naklon": 5 }, +{ "label": "16/104", "node": 4094, "naklon": null }, +{ "label": "16/105", "node": 4089, "naklon": 5 }, +{ "label": "16/106", "node": 4095, "naklon": null }, +{ "label": "16/107", "node": 4102, "naklon": 5 }, +{ "label": "16/108", "node": 4105, "naklon": null }, +{ "label": "16/109", "node": 3859, "naklon": null }, +{ "label": "16/110", "node": 4090, "naklon": 5 }, +{ "label": "16/111", "node": 4110, "naklon": null }, +{ "label": "16/112", "node": 4097, "naklon": 5 }, +{ "label": "16/113", "node": 4099, "naklon": null }, +{ "label": "16/114", "node": 4096, "naklon": null }, +{ "label": "16/115", "node": 4101, "naklon": 5 }, +{ "label": "16/116", "node": 4109, "naklon": null }, +{ "label": "16/117", "node": 4092, "naklon": 5 }, +{ "label": "16/118", "node": 3631, "naklon": null }, +{ "label": "16/119", "node": 3632, "naklon": 0 }, +{ "label": "16/120", "node": 3641, "naklon": null }, +{ "label": "16/121", "node": 3638, "naklon": 0 }, +{ "label": "16/122", "node": 3637, "naklon": null }, +{ "label": "16/123", "node": 4142, "naklon": null }, +{ "label": "16/124", "node": 4147, "naklon": 5 }, +{ "label": "16/125", "node": 4139, "naklon": 5 }, +{ "label": "20/30A", "node": 3172, "naklon": 2 }, +{ "label": "20/30B", "node": 3164, "naklon": 2 }, +{ "label": "20/1", "node": 3247, "naklon": 10 }, +{ "label": "20/2", "node": 3296, "naklon": 10 }, +{ "label": "20/3", "node": 3246, "naklon": 10 }, +{ "label": "20/4", "node": 3270, "naklon": 10 }, +{ "label": "20/5", "node": 3294, "naklon": 10 }, +{ "label": "20/6", "node": 3298, "naklon": 10 }, +{ "label": "20/7", "node": 3297, "naklon": 10 }, +{ "label": "20/8", "node": 3293, "naklon": 10 }, +{ "label": "20/9", "node": 3299, "naklon": 10 }, +{ "label": "20/10", "node": 3295, "naklon": 10 }, +{ "label": "20/11", "node": 3244, "naklon": 10 }, +{ "label": "20/12", "node": 3249, "naklon": 10 }, +{ "label": "20/13", "node": 3268, "naklon": 10 }, +{ "label": "20/14", "node": 3245, "naklon": 10 }, +{ "label": "20/15", "node": 3278, "naklon": 10 }, +{ "label": "20/16", "node": 3280, "naklon": 10 }, +{ "label": "20/17", "node": 3292, "naklon": 10 }, +{ "label": "20/18", "node": 3287, "naklon": 10 }, +{ "label": "20/19", "node": 3282, "naklon": 10 }, +{ "label": "20/20", "node": 3273, "naklon": 0 }, +{ "label": "20/21", "node": 3157, "naklon": 0 }, +{ "label": "20/22", "node": 3283, "naklon": 0 }, +{ "label": "20/23", "node": 3159, "naklon": 0 }, +{ "label": "20/24", "node": 3289, "naklon": 0 }, +{ "label": "20/25", "node": 3163, "naklon": 0 }, +{ "label": "20/26", "node": 3126, "naklon": 0 }, +{ "label": "20/27", "node": 3171, "naklon": 0 }, +{ "label": "20/28", "node": 3162, "naklon": 0 }, +{ "label": "20/29", "node": 3279, "naklon": 10 }, +{ "label": "20/31", "node": 3173, "naklon": 0 }, +{ "label": "20/32", "node": 3127, "naklon": 0 }, +{ "label": "20/33", "node": 3131, "naklon": 0 }, +{ "label": "20/34", "node": 3129, "naklon": 0 }, +{ "label": "20/35", "node": 3276, "naklon": 2 }, +{ "label": "20/36", "node": 3290, "naklon": 2 }, +{ "label": "20/37", "node": 3132, "naklon": 0 }, +{ "label": "20/38", "node": 3138, "naklon": 0 }, +{ "label": "20/39", "node": 3272, "naklon": 0 }, +{ "label": "20/40", "node": 3291, "naklon": 0 }, +{ "label": "20/41", "node": 3277, "naklon": 10 }, +{ "label": "20/42", "node": 3286, "naklon": 10 }, +{ "label": "20/43", "node": 3281, "naklon": 10 }, +{ "label": "20/44", "node": 3288, "naklon": 10 }, +{ "label": "20/45", "node": 3284, "naklon": 10 }, +{ "label": "20/46", "node": 3167, "naklon": 10 }, +{ "label": "20/47", "node": 3872, "naklon": 0 }, +{ "label": "20/48", "node": 3124, "naklon": 0 }, +{ "label": "20/49", "node": 3133, "naklon": 0 }, +{ "label": "20/50", "node": 3158, "naklon": 0 }, +{ "label": "20/51", "node": 3169, "naklon": 0 }, +{ "label": "20/52", "node": 3146, "naklon": 0 }, +{ "label": "20/53", "node": 3160, "naklon": 0 }, +{ "label": "20/54", "node": 3248, "naklon": 0 }, +{ "label": "20/55", "node": 3156, "naklon": 0 }, +{ "label": "20/56", "node": 3161, "naklon": 0 }, +{ "label": "20/57", "node": 3170, "naklon": 0 }, +{ "label": "20/58", "node": 3168, "naklon": 0 }, +{ "label": "20/59", "node": 3125, "naklon": 0 }, +{ "label": "20/60", "node": 3166, "naklon": 0 }, +{ "label": "20/61", "node": 3130, "naklon": 0 }, +{ "label": "20/62", "node": 3563, "naklon": 0 }, +{ "label": "20/63", "node": 3550, "naklon": null }, +{ "label": "20/67", "node": 3269, "naklon": 0 }, +{ "label": "21/1", "node": 2921, "naklon": 0 }, +{ "label": "21/2", "node": 2707, "naklon": 0 }, +{ "label": "21/3", "node": 2723, "naklon": 0 }, +{ "label": "21/4", "node": 2716, "naklon": 0 }, +{ "label": "21/5", "node": 2717, "naklon": 0 }, +{ "label": "21/6", "node": 2720, "naklon": 0 }, +{ "label": "21/7", "node": 2722, "naklon": 0 }, +{ "label": "21/8", "node": 2718, "naklon": 0 }, +{ "label": "21/9", "node": 2724, "naklon": 0 }, +{ "label": "21/10", "node": 2742, "naklon": 0 }, +{ "label": "21/11", "node": 2743, "naklon": 0 }, +{ "label": "21/12", "node": 2733, "naklon": 0 }, +{ "label": "21/14", "node": 2903, "naklon": 0 }, +{ "label": "21/15", "node": 2917, "naklon": 0 }, +{ "label": "21/16", "node": 2897, "naklon": 0 }, +{ "label": "21/17", "node": 2914, "naklon": 0 }, +{ "label": "21/18", "node": 2898, "naklon": 0 }, +{ "label": "21/19", "node": 2773, "naklon": 0 }, +{ "label": "21/20", "node": 2895, "naklon": 0 }, +{ "label": "21/21", "node": 2896, "naklon": 0 }, +{ "label": "21/22", "node": 2771, "naklon": 0 }, +{ "label": "21/23", "node": 2772, "naklon": 0 }, +{ "label": "21/24", "node": 2793, "naklon": 0 }, +{ "label": "21/25", "node": 2902, "naklon": 0 }, +{ "label": "21/26", "node": 2910, "naklon": 0 }, +{ "label": "21/27", "node": 2909, "naklon": 0 }, +{ "label": "21/28", "node": 2920, "naklon": 0 }, +{ "label": "21/29", "node": 2916, "naklon": 0 }, +{ "label": "21/30", "node": 2904, "naklon": 0 }, +{ "label": "21/31", "node": 2915, "naklon": 0 }, +{ "label": "21/32", "node": 2905, "naklon": 0 }, +{ "label": "21/33", "node": 2900, "naklon": 0 }, +{ "label": "21/34", "node": 2899, "naklon": 0 }, +{ "label": "21/36", "node": 2741, "naklon": 0 }, +{ "label": "21/37", "node": 2714, "naklon": 0 }, +{ "label": "21/38", "node": 2701, "naklon": 0 }, +{ "label": "21/39", "node": 2703, "naklon": 0 }, +{ "label": "21/40", "node": 2704, "naklon": 0 }, +{ "label": "21/41", "node": 2702, "naklon": 0 }, +{ "label": "21/42", "node": 2706, "naklon": 0 }, +{ "label": "21/43", "node": 2776, "naklon": 0 }, +{ "label": "21/44", "node": 2770, "naklon": 0 }, +{ "label": "21/45", "node": 2786, "naklon": 0 }, +{ "label": "21/46", "node": 2779, "naklon": 0 }, +{ "label": "21/47", "node": 2782, "naklon": 0 }, +{ "label": "21/48", "node": 2785, "naklon": 0 }, +{ "label": "21/49", "node": 2769, "naklon": 0 }, +{ "label": "21/50", "node": 3354, "naklon": 0 }, +{ "label": "21/51", "node": 2778, "naklon": 0 }, +{ "label": "21/52", "node": 2775, "naklon": 0 }, +{ "label": "21/53", "node": 2780, "naklon": 0 }, +{ "label": "21/54", "node": 2790, "naklon": 0 }, +{ "label": "21/55", "node": 2792, "naklon": 0 }, +{ "label": "21/56", "node": 2774, "naklon": 0 }, +{ "label": "22/1", "node": 2630, "naklon": 0 }, +{ "label": "22/2", "node": 2631, "naklon": 0 }, +{ "label": "22/3", "node": 2632, "naklon": 0 }, +{ "label": "22/4", "node": 2633, "naklon": 0 }, +{ "label": "22/5", "node": 2634, "naklon": 0 }, +{ "label": "22/6", "node": 2636, "naklon": 0 }, +{ "label": "22/7", "node": 4367, "naklon": 0 }, +{ "label": "22/8", "node": 2637, "naklon": 0 }, +{ "label": "22/9", "node": 2638, "naklon": 0 }, +{ "label": "22/10", "node": 2639, "naklon": 0 }, +{ "label": "22/11", "node": 2640, "naklon": 0 }, +{ "label": "22/12", "node": 2641, "naklon": 0 }, +{ "label": "22/13", "node": 2642, "naklon": 0 }, +{ "label": "22/14", "node": 2643, "naklon": 0 }, +{ "label": "22/15", "node": 2644, "naklon": 0 }, +{ "label": "22/16", "node": 2645, "naklon": 0 }, +{ "label": "22/17", "node": 2646, "naklon": 0 }, +{ "label": "22/18", "node": 2647, "naklon": 0 }, +{ "label": "22/19", "node": 2648, "naklon": 0 }, +{ "label": "22/20", "node": 2649, "naklon": 0 }, +{ "label": "22/21", "node": 2650, "naklon": 0 }, +{ "label": "22/22", "node": 2651, "naklon": 0 }, +{ "label": "22/23", "node": 4103, "naklon": 0 }, +{ "label": "22/24", "node": 2653, "naklon": 0 }, +{ "label": "22/25", "node": 2654, "naklon": 0 }, +{ "label": "22/26", "node": 2655, "naklon": 0 }, +{ "label": "22/27", "node": 2656, "naklon": 0 }, +{ "label": "22/28", "node": 2657, "naklon": 0 }, +{ "label": "22/29", "node": 2658, "naklon": 0 }, +{ "label": "22/30", "node": 2659, "naklon": 0 }, +{ "label": "22/31", "node": 2660, "naklon": 0 }, +{ "label": "22/32", "node": 2661, "naklon": 0 }, +{ "label": "22/32/1", "node": 3015, "naklon": 0 }, +{ "label": "22/33", "node": 2662, "naklon": 0 }, +{ "label": "22/34", "node": 2663, "naklon": 0 }, +{ "label": "22/35", "node": 2664, "naklon": 0 }, +{ "label": "22/36", "node": 2665, "naklon": 0 }, +{ "label": "22/37", "node": 2666, "naklon": 0 }, +{ "label": "22/38", "node": 2667, "naklon": 0 }, +{ "label": "22/39", "node": 2668, "naklon": 0 }, +{ "label": "22/40", "node": 2669, "naklon": null }, +{ "label": "22/41", "node": 2670, "naklon": null }, +{ "label": "22/42", "node": 2671, "naklon": null }, +{ "label": "23/9A", "node": 3087, "naklon": 10 }, +{ "label": "23/9B", "node": 3090, "naklon": 10 }, +{ "label": "23/1", "node": 3075, "naklon": 0 }, +{ "label": "23/2", "node": 3089, "naklon": 0 }, +{ "label": "23/3", "node": 3088, "naklon": 0 }, +{ "label": "23/4", "node": 3228, "naklon": 10 }, +{ "label": "23/5", "node": 2751, "naklon": 10 }, +{ "label": "23/6", "node": 3243, "naklon": 10 }, +{ "label": "23/7", "node": 4349, "naklon": 10 }, +{ "label": "23/8", "node": 3102, "naklon": 10 }, +{ "label": "23/10", "node": 3099, "naklon": 10 }, +{ "label": "23/11", "node": 3103, "naklon": 10 }, +{ "label": "23/12", "node": 3093, "naklon": 10 }, +{ "label": "23/13", "node": 3098, "naklon": 10 }, +{ "label": "23/14", "node": 3092, "naklon": 10 }, +{ "label": "23/15", "node": 3233, "naklon": 0 }, +{ "label": "23/16", "node": 3095, "naklon": 0 }, +{ "label": "23/17", "node": 4074, "naklon": 0 }, +{ "label": "23/18", "node": 2729, "naklon": 0 }, +{ "label": "23/19", "node": 3234, "naklon": 0 }, +{ "label": "23/20", "node": 3094, "naklon": 0 }, +{ "label": "23/21", "node": 2817, "naklon": 0 }, +{ "label": "23/22", "node": 3226, "naklon": 0 }, +{ "label": "23/23", "node": 3225, "naklon": 0 }, +{ "label": "23/24", "node": 3237, "naklon": 0 }, +{ "label": "23/25", "node": 4250, "naklon": 0 }, +{ "label": "23/26", "node": 3059, "naklon": 10 }, +{ "label": "23/27", "node": 3238, "naklon": 10 }, +{ "label": "23/28", "node": 3242, "naklon": 10 }, +{ "label": "23/29", "node": 3236, "naklon": 10 }, +{ "label": "23/30", "node": 3112, "naklon": 10 }, +{ "label": "23/31", "node": 3224, "naklon": 0 }, +{ "label": "23/32", "node": 4298, "naklon": 10 }, +{ "label": "23/33", "node": 4150, "naklon": 10 }, +{ "label": "23/34", "node": 3091, "naklon": 10 }, +{ "label": "25/1", "node": 3771, "naklon": 5 }, +{ "label": "25/2", "node": 3777, "naklon": 5 }, +{ "label": "25/3", "node": 3749, "naklon": 5 }, +{ "label": "25/4", "node": 3769, "naklon": 5 }, +{ "label": "25/5", "node": 3765, "naklon": 5 }, +{ "label": "25/6", "node": 3785, "naklon": 5 }, +{ "label": "25/7", "node": 3761, "naklon": 5 }, +{ "label": "25/8", "node": 3758, "naklon": 5 }, +{ "label": "25/9", "node": 3766, "naklon": 5 }, +{ "label": "25/10", "node": 3779, "naklon": 5 }, +{ "label": "25/11", "node": 3899, "naklon": 10 }, +{ "label": "25/12", "node": 3922, "naklon": 10 }, +{ "label": "25/13", "node": 3912, "naklon": 10 }, +{ "label": "25/14", "node": 3933, "naklon": 10 }, +{ "label": "25/15", "node": 3921, "naklon": 10 }, +{ "label": "25/16", "node": 4300, "naklon": 10 }, +{ "label": "25/17", "node": 3927, "naklon": 10 }, +{ "label": "25/18", "node": 3212, "naklon": 10 }, +{ "label": "25/19", "node": 3208, "naklon": 10 }, +{ "label": "25/20", "node": 3207, "naklon": 10 }, +{ "label": "25/21", "node": 4294, "naklon": 10 }, +{ "label": "25/22", "node": 3209, "naklon": 10 }, +{ "label": "25/23", "node": 3745, "naklon": 10 }, +{ "label": "25/24", "node": 3762, "naklon": 10 }, +{ "label": "25/25", "node": 3215, "naklon": 10 }, +{ "label": "25/26", "node": 3210, "naklon": 10 }, +{ "label": "25/27", "node": 3211, "naklon": 10 }, +{ "label": "25/28", "node": 3206, "naklon": 10 }, +{ "label": "25/29", "node": 3918, "naklon": 5 }, +{ "label": "25/30", "node": 3928, "naklon": 5 }, +{ "label": "25/31", "node": 3917, "naklon": 5 }, +{ "label": "25/32", "node": 4029, "naklon": 0 }, +{ "label": "25/33", "node": 4038, "naklon": 0 }, +{ "label": "25/34", "node": 4022, "naklon": 0 }, +{ "label": "25/35", "node": 3937, "naklon": 0 }, +{ "label": "25/36", "node": 3190, "naklon": 0 }, +{ "label": "25/37", "node": 3835, "naklon": 0 }, +{ "label": "25/38", "node": 3201, "naklon": 0 }, +{ "label": "25/39", "node": 3193, "naklon": 0 }, +{ "label": "25/40", "node": 3191, "naklon": 0 }, +{ "label": "25/41", "node": 3203, "naklon": 0 }, +{ "label": "25/42", "node": 4301, "naklon": 0 }, +{ "label": "25/43", "node": 3223, "naklon": 0 }, +{ "label": "25/44", "node": 3202, "naklon": 0 }, +{ "label": "25/45", "node": 3205, "naklon": 0 }, +{ "label": "25/46", "node": 3194, "naklon": 0 }, +{ "label": "25/47", "node": 3198, "naklon": 0 }, +{ "label": "25/48", "node": 3204, "naklon": 0 }, +{ "label": "25/49", "node": 3200, "naklon": 0 }, +{ "label": "25/50", "node": 3216, "naklon": 0 }, +{ "label": "25/51", "node": 3932, "naklon": 5 }, +{ "label": "25/52", "node": 3923, "naklon": 5 }, +{ "label": "25/53", "node": 3913, "naklon": 5 }, +{ "label": "25/54", "node": 3900, "naklon": 5 }, +{ "label": "25/55", "node": 4189, "naklon": 10 }, +{ "label": "25/56", "node": 4191, "naklon": 10 }, +{ "label": "25/57", "node": 3790, "naklon": 10 }, +{ "label": "25/58", "node": 4190, "naklon": 10 }, +{ "label": "25/59", "node": 4302, "naklon": 0 }, +{ "label": "25/60", "node": 4351, "naklon": 0 }, +{ "label": "25/61", "node": 4075, "naklon": 0 }, +{ "label": "25/62", "node": 4071, "naklon": 0 }, +{ "label": "25/63", "node": 3784, "naklon": 0 }, +{ "label": "25/64", "node": 4065, "naklon": 0 }, +{ "label": "25/65", "node": 4297, "naklon": 0 }, +{ "label": "25/66", "node": 4295, "naklon": 0 }, +{ "label": "25/67", "node": 4299, "naklon": 0 }, +{ "label": "25/68", "node": 3772, "naklon": 0 }, +{ "label": "25/69", "node": 3941, "naklon": 0 }, +{ "label": "25/70", "node": 3782, "naklon": 0 }, +{ "label": "25/71", "node": 4068, "naklon": 0 }, +{ "label": "25/72", "node": 4073, "naklon": 0 }, +{ "label": "25/73", "node": 3901, "naklon": 5 }, +{ "label": "25/74", "node": 4296, "naklon": 5 }, +{ "label": "25/75", "node": 3910, "naklon": 5 }, +{ "label": "25/76", "node": 4293, "naklon": 5 }, +{ "label": "25/77", "node": 3919, "naklon": 5 }, +{ "label": "25/78", "node": 3924, "naklon": 5 }, +{ "label": "25/79", "node": 3909, "naklon": 5 }, +{ "label": "25/80", "node": 3896, "naklon": 5 }, +{ "label": "25/81", "node": 3911, "naklon": 5 }, +{ "label": "25/82", "node": 2819, "naklon": 15 }, +{ "label": "25/83", "node": 3776, "naklon": 15 }, +{ "label": "25/84", "node": 3752, "naklon": 15 }, +{ "label": "25/85", "node": 4353, "naklon": 15 }, +{ "label": "25/86", "node": 3791, "naklon": 0 }, +{ "label": "25/87", "node": 3770, "naklon": 0 }, +{ "label": "25/88", "node": 3760, "naklon": 0 }, +{ "label": "25/89", "node": 3115, "naklon": 0 }, +{ "label": "25/90", "node": 3738, "naklon": 0 }, +{ "label": "25/91", "node": 3748, "naklon": 0 }, +{ "label": "25/92", "node": 3753, "naklon": 0 }, +{ "label": "25/93", "node": 3775, "naklon": 0 }, +{ "label": "25/94", "node": 3778, "naklon": 5 }, +{ "label": "25/95", "node": 4078, "naklon": 5 }, +{ "label": "25/96", "node": 4088, "naklon": 5 }, +{ "label": "25/97", "node": 3856, "naklon": 5 }, +{ "label": "25/98", "node": 4084, "naklon": 5 }, +{ "label": "25/99", "node": 4069, "naklon": 5 }, +{ "label": "25/100", "node": 4188, "naklon": 5 }, +{ "label": "25/101", "node": 4064, "naklon": 5 }, +{ "label": "25/102", "node": 3792, "naklon": 5 }, +{ "label": "25/103", "node": 3780, "naklon": 5 }, +{ "label": "25/104", "node": 4034, "naklon": 5 }, +{ "label": "25/105", "node": 4072, "naklon": 5 }, +{ "label": "25/106", "node": 3884, "naklon": 5 }, +{ "label": "25/107", "node": 3793, "naklon": 5 }, +{ "label": "25/108", "node": 3863, "naklon": 5 }, +{ "label": "25/109", "node": 3855, "naklon": 5 }, +{ "label": "33/1", "node": 3846, "naklon": 0 }, +{ "label": "33/2", "node": 3943, "naklon": 0 }, +{ "label": "33/3", "node": 3903, "naklon": 0 }, +{ "label": "33/4", "node": 3982, "naklon": 0 }, +{ "label": "33/5", "node": 3879, "naklon": 0 }, +{ "label": "33/6", "node": 3887, "naklon": 0 }, +{ "label": "33/7", "node": 3920, "naklon": 5 }, +{ "label": "33/8", "node": 3942, "naklon": 5 }, +{ "label": "33/9", "node": 3829, "naklon": null }, +{ "label": "34/79A", "node": 3452, "naklon": 6 }, +{ "label": "34/79B", "node": 3460, "naklon": 6 }, +{ "label": "34/90A", "node": 3443, "naklon": 6 }, +{ "label": "34/90B", "node": 3445, "naklon": 6 }, +{ "label": "34/90C", "node": 3457, "naklon": 6 }, +{ "label": "34/97A", "node": 3461, "naklon": 6 }, +{ "label": "34/97B", "node": 3463, "naklon": 6 }, +{ "label": "34/98A", "node": 3426, "naklon": 6 }, +{ "label": "34/98B", "node": 3444, "naklon": 6 }, +{ "label": "34/99A", "node": 3453, "naklon": 6 }, +{ "label": "34/99B", "node": 3455, "naklon": 6 }, +{ "label": "34/1", "node": 4009, "naklon": 0 }, +{ "label": "34/2", "node": 3602, "naklon": 0 }, +{ "label": "34/3", "node": 3441, "naklon": 0 }, +{ "label": "34/4", "node": 3464, "naklon": 0 }, +{ "label": "34/5", "node": 3883, "naklon": 0 }, +{ "label": "34/6", "node": 4098, "naklon": 0 }, +{ "label": "34/7", "node": 4003, "naklon": 0 }, +{ "label": "34/8", "node": 4004, "naklon": 0 }, +{ "label": "34/9", "node": 3888, "naklon": 0 }, +{ "label": "34/10", "node": 3997, "naklon": 0 }, +{ "label": "34/11", "node": 4006, "naklon": 0 }, +{ "label": "34/12", "node": 4000, "naklon": 0 }, +{ "label": "34/13", "node": 4011, "naklon": 0 }, +{ "label": "34/14", "node": 3999, "naklon": 0 }, +{ "label": "34/15", "node": 3981, "naklon": 0 }, +{ "label": "34/16", "node": 3988, "naklon": 0 }, +{ "label": "34/17", "node": 3986, "naklon": 0 }, +{ "label": "34/18", "node": 3998, "naklon": 0 }, +{ "label": "34/19", "node": 3983, "naklon": 0 }, +{ "label": "34/20", "node": 4005, "naklon": 0 }, +{ "label": "34/21", "node": 4001, "naklon": 0 }, +{ "label": "34/22", "node": 4008, "naklon": 0 }, +{ "label": "34/23", "node": 4002, "naklon": 0 }, +{ "label": "34/24", "node": 3996, "naklon": 0 }, +{ "label": "34/25", "node": 4007, "naklon": 0 }, +{ "label": "34/26", "node": 4113, "naklon": 15 }, +{ "label": "34/27", "node": 3595, "naklon": 5 }, +{ "label": "34/28", "node": 3599, "naklon": 5 }, +{ "label": "34/29", "node": 3601, "naklon": 5 }, +{ "label": "34/30", "node": 4205, "naklon": 0 }, +{ "label": "34/31", "node": 3987, "naklon": null }, +{ "label": "34/32", "node": 4214, "naklon": 0 }, +{ "label": "34/33", "node": 4226, "naklon": 0 }, +{ "label": "34/34", "node": 4209, "naklon": 0 }, +{ "label": "34/35", "node": 4201, "naklon": 0 }, +{ "label": "34/36", "node": 3440, "naklon": 0 }, +{ "label": "34/37", "node": 3465, "naklon": 0 }, +{ "label": "34/38", "node": 3446, "naklon": 0 }, +{ "label": "34/39", "node": 4039, "naklon": 5 }, +{ "label": "34/40", "node": 4057, "naklon": 5 }, +{ "label": "34/41", "node": 3985, "naklon": 0 }, +{ "label": "34/42", "node": 3882, "naklon": 0 }, +{ "label": "34/43", "node": 4040, "naklon": 5 }, +{ "label": "34/44", "node": 3231, "naklon": 0 }, +{ "label": "34/45", "node": 3227, "naklon": 0 }, +{ "label": "34/46", "node": 3431, "naklon": 0 }, +{ "label": "34/47", "node": 4013, "naklon": 0 }, +{ "label": "34/48", "node": 4045, "naklon": 0 }, +{ "label": "34/49", "node": 3949, "naklon": 0 }, +{ "label": "34/50", "node": 3953, "naklon": 0 }, +{ "label": "34/51", "node": 3952, "naklon": 0 }, +{ "label": "34/52", "node": 3995, "naklon": 0 }, +{ "label": "34/53", "node": 3992, "naklon": 0 }, +{ "label": "34/54", "node": 4198, "naklon": 0 }, +{ "label": "34/55", "node": 3935, "naklon": 0 }, +{ "label": "34/56", "node": 4050, "naklon": 0 }, +{ "label": "34/57", "node": 4049, "naklon": 0 }, +{ "label": "34/58", "node": 4054, "naklon": 0 }, +{ "label": "34/59", "node": 3663, "naklon": 6 }, +{ "label": "34/60", "node": 3661, "naklon": 6 }, +{ "label": "34/61", "node": 3664, "naklon": 6 }, +{ "label": "34/62", "node": 3660, "naklon": 6 }, +{ "label": "34/63", "node": 3662, "naklon": 6 }, +{ "label": "34/65", "node": 3665, "naklon": 6 }, +{ "label": "34/66", "node": 3667, "naklon": 6 }, +{ "label": "34/67", "node": 3675, "naklon": 6 }, +{ "label": "34/68", "node": 3666, "naklon": 6 }, +{ "label": "34/69", "node": 3652, "naklon": 6 }, +{ "label": "34/70", "node": 3458, "naklon": 6 }, +{ "label": "34/70/1", "node": 4425, "naklon": 6 }, +{ "label": "34/71", "node": 3459, "naklon": 6 }, +{ "label": "34/72", "node": 3435, "naklon": 6 }, +{ "label": "34/73", "node": 3448, "naklon": 6 }, +{ "label": "34/74", "node": 3451, "naklon": 6 }, +{ "label": "34/75", "node": 3442, "naklon": 6 }, +{ "label": "34/76", "node": 3449, "naklon": 6 }, +{ "label": "34/77", "node": 3450, "naklon": 6 }, +{ "label": "34/78", "node": 3433, "naklon": 6 }, +{ "label": "34/80", "node": 3432, "naklon": 12 }, +{ "label": "34/81", "node": 3470, "naklon": 12 }, +{ "label": "34/82", "node": 3438, "naklon": 12 }, +{ "label": "34/83", "node": 3439, "naklon": 12 }, +{ "label": "34/84", "node": 4028, "naklon": 5 }, +{ "label": "34/85", "node": 3596, "naklon": 5 }, +{ "label": "34/86", "node": 4021, "naklon": 5 }, +{ "label": "34/87", "node": 3437, "naklon": 12 }, +{ "label": "34/88", "node": 3428, "naklon": 12 }, +{ "label": "34/89", "node": 3430, "naklon": 12 }, +{ "label": "34/91", "node": 3454, "naklon": 6 }, +{ "label": "34/92", "node": 3492, "naklon": 6 }, +{ "label": "34/93", "node": 3462, "naklon": 6 }, +{ "label": "34/94", "node": 3427, "naklon": 6 }, +{ "label": "34/95", "node": 3434, "naklon": 6 }, +{ "label": "34/96", "node": 3456, "naklon": 6 }, +{ "label": "34/98/1", "node": 4307, "naklon": 6 }, +{ "label": "35/1", "node": 3968, "naklon": 0 }, +{ "label": "35/2", "node": 3969, "naklon": 0 }, +{ "label": "35/3", "node": 3947, "naklon": 0 }, +{ "label": "35/4", "node": 3979, "naklon": 0 }, +{ "label": "35/5", "node": 3959, "naklon": 0 }, +{ "label": "35/6", "node": 3948, "naklon": 0 }, +{ "label": "35/7", "node": 3961, "naklon": 0 }, +{ "label": "35/8", "node": 3956, "naklon": 0 }, +{ "label": "35/9", "node": 3604, "naklon": 0 }, +{ "label": "35/10", "node": 3944, "naklon": 0 }, +{ "label": "35/11", "node": 3960, "naklon": 0 }, +{ "label": "35/12", "node": 3958, "naklon": 0 }, +{ "label": "35/13", "node": 4036, "naklon": 5 }, +{ "label": "35/18", "node": 3893, "naklon": 5 }, +{ "label": "35/19", "node": 4108, "naklon": 5 }, +{ "label": "35/20", "node": 4017, "naklon": 5 }, +{ "label": "35/21", "node": 3963, "naklon": 0 }, +{ "label": "35/22", "node": 3658, "naklon": 0 }, +{ "label": "35/23", "node": 3975, "naklon": 0 }, +{ "label": "35/24", "node": 3980, "naklon": 0 }, +{ "label": "35/25", "node": 4012, "naklon": 0 }, +{ "label": "35/26", "node": 3655, "naklon": 0 }, +{ "label": "35/27", "node": 3962, "naklon": 0 }, +{ "label": "35/28", "node": 3945, "naklon": 0 }, +{ "label": "35/29", "node": 3569, "naklon": 0 }, +{ "label": "35/30", "node": 3429, "naklon": 0 }, +{ "label": "35/31", "node": 3657, "naklon": 0 }, +{ "label": "35/32", "node": 3646, "naklon": 0 }, +{ "label": "35/33", "node": 3622, "naklon": 0 }, +{ "label": "35/34", "node": 3612, "naklon": 0 }, +{ "label": "35/35", "node": 3955, "naklon": 0 }, +{ "label": "35/37", "node": 3878, "naklon": 0 }, +{ "label": "35/38", "node": 3965, "naklon": 0 }, +{ "label": "35/39", "node": 3970, "naklon": 0 }, +{ "label": "35/40", "node": 3611, "naklon": 0 }, +{ "label": "35/41", "node": 2635, "naklon": 0 }, +{ "label": "35/42", "node": 3978, "naklon": 0 }, +{ "label": "35/43", "node": 4213, "naklon": 0 }, +{ "label": "35/44", "node": 3984, "naklon": 0 }, +{ "label": "35/45", "node": 4218, "naklon": 0 }, +{ "label": "35/46", "node": 3973, "naklon": 0 }, +{ "label": "35/47", "node": 3974, "naklon": 0 }, +{ "label": "35/48", "node": 3759, "naklon": 0 }, +{ "label": "35/49", "node": 3844, "naklon": 0 }, +{ "label": "35/50", "node": 3804, "naklon": 0 }, +{ "label": "35/51", "node": 3831, "naklon": 0 }, +{ "label": "35/52", "node": 3643, "naklon": 0 }, +{ "label": "35/53", "node": 3966, "naklon": 0 }, +{ "label": "35/54", "node": 3971, "naklon": 0 }, +{ "label": "35/55", "node": 3650, "naklon": 6 }, +{ "label": "35/56", "node": 3651, "naklon": 6 }, +{ "label": "35/57", "node": 3669, "naklon": 6 }, +{ "label": "35/58", "node": 3648, "naklon": 6 }, +{ "label": "35/59", "node": 3645, "naklon": 6 }, +{ "label": "35/60", "node": 3659, "naklon": 6 }, +{ "label": "35/61", "node": 3647, "naklon": 6 }, +{ "label": "35/62", "node": 3644, "naklon": 6 }, +{ "label": "35/63", "node": 3671, "naklon": 6 }, +{ "label": "35/64", "node": 3682, "naklon": 6 }, +{ "label": "35/65", "node": 3672, "naklon": 6 }, +{ "label": "35/66", "node": 3683, "naklon": 6 }, +{ "label": "35/67", "node": 3673, "naklon": 6 }, +{ "label": "35/68", "node": 3674, "naklon": 6 }, +{ "label": "35/69", "node": 3679, "naklon": 6 }, +{ "label": "35/70", "node": 3649, "naklon": 6 }, +{ "label": "35/71", "node": 3687, "naklon": 6 }, +{ "label": "35/72", "node": 3677, "naklon": 6 }, +{ "label": "35/73", "node": 3690, "naklon": 6 }, +{ "label": "35/74", "node": 3691, "naklon": 6 }, +{ "label": "35/75", "node": 3676, "naklon": 6 }, +{ "label": "35/76", "node": 3680, "naklon": 6 }, +{ "label": "35/77", "node": 3668, "naklon": 6 }, +{ "label": "35/78", "node": 3681, "naklon": 6 }, +{ "label": "35/79", "node": 3670, "naklon": 6 }, +{ "label": "35/80", "node": 3689, "naklon": 6 }, +{ "label": "35/81", "node": 3678, "naklon": 6 }, +{ "label": "35/82", "node": 3693, "naklon": 6 }, +{ "label": "35/83", "node": 3654, "naklon": null }, +{ "label": "36/1", "node": 4086, "naklon": 0 }, +{ "label": "36/2", "node": 4085, "naklon": 0 }, +{ "label": "36/3", "node": 4083, "naklon": 0 }, +{ "label": "36/4", "node": 4087, "naklon": 0 }, +{ "label": "36/5", "node": 4077, "naklon": 0 }, +{ "label": "36/6", "node": 4082, "naklon": 0 }, +{ "label": "36/7", "node": 4186, "naklon": 0 }, +{ "label": "36/8", "node": 4206, "naklon": 0 }, +{ "label": "36/9", "node": 4080, "naklon": 0 }, +{ "label": "36/10", "node": 4081, "naklon": 0 }, +{ "label": "36/11", "node": 4210, "naklon": 0 }, +{ "label": "36/12", "node": 4079, "naklon": 0 }, +{ "label": "36/13", "node": 4076, "naklon": 0 }, +{ "label": "36/14", "node": 3852, "naklon": 0 }, +{ "label": "36/15", "node": 2813, "naklon": 0 }, +{ "label": "36/16", "node": 4219, "naklon": 0 }, +{ "label": "37/1A", "node": 3104, "naklon": 15 }, +{ "label": "37/1B", "node": 3121, "naklon": 15 }, +{ "label": "37/2", "node": 3113, "naklon": 10 }, +{ "label": "37/3", "node": 3118, "naklon": 10 }, +{ "label": "37/4", "node": 3111, "naklon": 10 }, +{ "label": "37/5", "node": 4020, "naklon": 10 }, +{ "label": "37/6", "node": 3119, "naklon": 10 }, +{ "label": "37/7", "node": 3110, "naklon": 10 }, +{ "label": "37/8", "node": 3108, "naklon": 10 }, +{ "label": "37/12", "node": 3107, "naklon": 0 }, +{ "label": "37/13", "node": 3199, "naklon": 0 }, +{ "label": "37/14", "node": 3120, "naklon": 0 }, +{ "label": "37/15", "node": 3122, "naklon": 0 }, +{ "label": "37/16", "node": 3908, "naklon": 0 }, +{ "label": "37/17", "node": 3114, "naklon": 0 }, +{ "label": "37/18", "node": 3105, "naklon": 0 }, +{ "label": "37/19", "node": 3116, "naklon": 0 }, +{ "label": "37/20", "node": 3106, "naklon": 0 }, +{ "label": "37/21", "node": 2887, "naklon": 5 }, +{ "label": "37/22", "node": 2888, "naklon": 5 }, +{ "label": "37/23", "node": 2877, "naklon": 5 }, +{ "label": "37/24", "node": 2891, "naklon": 5 }, +{ "label": "37/25", "node": 2886, "naklon": 5 }, +{ "label": "37/26", "node": 2892, "naklon": 5 }, +{ "label": "37/27", "node": 2882, "naklon": 5 }, +{ "label": "37/28", "node": 2883, "naklon": 5 }, +{ "label": "37/29", "node": 2876, "naklon": 5 }, +{ "label": "37/30", "node": 3109, "naklon": 5 }, +{ "label": "37/31", "node": 4152, "naklon": 5 }, +{ "label": "37/32", "node": 3117, "naklon": 5 }, +{ "label": "37/33", "node": 2870, "naklon": 5 }, +{ "label": "37/34", "node": 2867, "naklon": 0 }, +{ "label": "37/35", "node": 2865, "naklon": 0 }, +{ "label": "37/36", "node": 3096, "naklon": 0 }, +{ "label": "37/37", "node": 2871, "naklon": 0 }, +{ "label": "37/38", "node": 2884, "naklon": 0 }, +{ "label": "37/39", "node": 2855, "naklon": 0 }, +{ "label": "37/40", "node": 2878, "naklon": 0 }, +{ "label": "37/41", "node": 2889, "naklon": 0 }, +{ "label": "37/42", "node": 2879, "naklon": 0 }, +{ "label": "37/43", "node": 2850, "naklon": 0 }, +{ "label": "37/44", "node": 2894, "naklon": 0 }, +{ "label": "37/45", "node": 2880, "naklon": 0 }, +{ "label": "37/46", "node": 2893, "naklon": 0 }, +{ "label": "37/47", "node": 2890, "naklon": 0 }, +{ "label": "37/48", "node": 4355, "naklon": 0 }, +{ "label": "37/49", "node": 2885, "naklon": 0 }, +{ "label": "37/50", "node": 2875, "naklon": 0 }, +{ "label": "38/30A", "node": 3486, "naklon": 5 }, +{ "label": "38/30B", "node": 3714, "naklon": 0 }, +{ "label": "38/32A", "node": 3483, "naklon": 5 }, +{ "label": "38/32B", "node": 3496, "naklon": 0 }, +{ "label": "38/35A", "node": 3487, "naklon": 5 }, +{ "label": "38/35B", "node": 3498, "naklon": 5 }, +{ "label": "38/38A", "node": 3578, "naklon": 5 }, +{ "label": "38/38B", "node": 3508, "naklon": 5 }, +{ "label": "38/59A", "node": 3787, "naklon": 5 }, +{ "label": "38/59B", "node": 3491, "naklon": 5 }, +{ "label": "38/1", "node": 3568, "naklon": null }, +{ "label": "38/2", "node": 3502, "naklon": 0 }, +{ "label": "38/3", "node": 3836, "naklon": 0 }, +{ "label": "38/4", "node": 3588, "naklon": 0 }, +{ "label": "38/5", "node": 3493, "naklon": 0 }, +{ "label": "38/6", "node": 3580, "naklon": 0 }, +{ "label": "38/7", "node": 3572, "naklon": 0 }, +{ "label": "38/8", "node": 3506, "naklon": 0 }, +{ "label": "38/9", "node": 3503, "naklon": 0 }, +{ "label": "38/10", "node": 3579, "naklon": 0 }, +{ "label": "38/11", "node": 3586, "naklon": 0 }, +{ "label": "38/12", "node": 3495, "naklon": 5 }, +{ "label": "38/13", "node": 3492, "naklon": 5 }, +{ "label": "38/14", "node": 3532, "naklon": 5 }, +{ "label": "38/15", "node": 3574, "naklon": 5 }, +{ "label": "38/16", "node": 4140, "naklon": 5 }, +{ "label": "38/17", "node": 3795, "naklon": 5 }, +{ "label": "38/18", "node": 3788, "naklon": 5 }, +{ "label": "38/19", "node": 3796, "naklon": 5 }, +{ "label": "38/20", "node": 3797, "naklon": 5 }, +{ "label": "38/21", "node": 3798, "naklon": 5 }, +{ "label": "38/22", "node": 3786, "naklon": 5 }, +{ "label": "38/23", "node": 4067, "naklon": 5 }, +{ "label": "38/24", "node": 3773, "naklon": 5 }, +{ "label": "38/25", "node": 3774, "naklon": 5 }, +{ "label": "38/26", "node": 3789, "naklon": 5 }, +{ "label": "38/27", "node": 3520, "naklon": null }, +{ "label": "38/29", "node": 3577, "naklon": 5 }, +{ "label": "38/31", "node": 3530, "naklon": null }, +{ "label": "38/33", "node": 3488, "naklon": 5 }, +{ "label": "38/34", "node": 3505, "naklon": 5 }, +{ "label": "38/36", "node": 3497, "naklon": 5 }, +{ "label": "38/37", "node": 3490, "naklon": 5 }, +{ "label": "38/39", "node": 3585, "naklon": 5 }, +{ "label": "38/40", "node": 3582, "naklon": 5 }, +{ "label": "38/41", "node": 3507, "naklon": 5 }, +{ "label": "38/42", "node": 3484, "naklon": 5 }, +{ "label": "38/43", "node": 3501, "naklon": 5 }, +{ "label": "38/44", "node": 3581, "naklon": 5 }, +{ "label": "38/45", "node": 4192, "naklon": 5 }, +{ "label": "38/46", "node": 3576, "naklon": 5 }, +{ "label": "38/47", "node": 3489, "naklon": 5 }, +{ "label": "38/48", "node": 3573, "naklon": 5 }, +{ "label": "38/49", "node": 3504, "naklon": 5 }, +{ "label": "38/50", "node": 3794, "naklon": 5 }, +{ "label": "38/51", "node": 3485, "naklon": 5 }, +{ "label": "38/52", "node": 3482, "naklon": 5 }, +{ "label": "38/53", "node": 3575, "naklon": 5 }, +{ "label": "38/54", "node": 3499, "naklon": 5 }, +{ "label": "38/55", "node": 3494, "naklon": 5 }, +{ "label": "38/56", "node": 3583, "naklon": 5 }, +{ "label": "38/57", "node": 3570, "naklon": 5 }, +{ "label": "38/58", "node": 3500, "naklon": 0 }, +{ "label": "38/63", "node": 3510, "naklon": null }, +{ "label": "38/64", "node": 3512, "naklon": null }, +{ "label": "38/67", "node": 3535, "naklon": null }, +{ "label": "38/68", "node": 3531, "naklon": null }, +{ "label": "38/69", "node": 3537, "naklon": null }, +{ "label": "39/1", "node": 3522, "naklon": 10 }, +{ "label": "39/2", "node": 4018, "naklon": 10 }, +{ "label": "39/3", "node": 4019, "naklon": 10 }, +{ "label": "39/4", "node": 4154, "naklon": 5 }, +{ "label": "39/5", "node": 3907, "naklon": 5 }, +{ "label": "39/6", "node": 4148, "naklon": 0 }, +{ "label": "39/7", "node": 4153, "naklon": 0 }, +{ "label": "39/8", "node": 3938, "naklon": 0 }, +{ "label": "39/9", "node": 3802, "naklon": 0 }, +{ "label": "39/10", "node": 4015, "naklon": 0 }, +{ "label": "39/11", "node": 3929, "naklon": 0 }, +{ "label": "39/12", "node": 3946, "naklon": 0 }, +{ "label": "39/13", "node": 4014, "naklon": 0 }, +{ "label": "39/14", "node": 4155, "naklon": 0 }, +{ "label": "39/15", "node": 4149, "naklon": 0 }, +{ "label": "39/16", "node": 3642, "naklon": 0 }, +{ "label": "39/17", "node": 3636, "naklon": 5 }, +{ "label": "39/18", "node": 3991, "naklon": 0 }, +{ "label": "39/19", "node": 3994, "naklon": 0 }, +{ "label": "39/20", "node": 3990, "naklon": 0 }, +{ "label": "39/21", "node": 3967, "naklon": 0 }, +{ "label": "39/22", "node": 3977, "naklon": 0 }, +{ "label": "39/23", "node": 3757, "naklon": 15 }, +{ "label": "39/24", "node": 3633, "naklon": 15 }, +{ "label": "39/25", "node": 3744, "naklon": 15 }, +{ "label": "39/26", "node": 4023, "naklon": 5 }, +{ "label": "39/27", "node": 3720, "naklon": 5 }, +{ "label": "39/28", "node": 3734, "naklon": 5 }, +{ "label": "39/29", "node": 3741, "naklon": 5 }, +{ "label": "39/30", "node": 3721, "naklon": 5 }, +{ "label": "39/31", "node": 3845, "naklon": 0 }, +{ "label": "39/32", "node": 3840, "naklon": 0 }, +{ "label": "39/33", "node": 3837, "naklon": null }, +{ "label": "39/34", "node": 3839, "naklon": 0 }, +{ "label": "41/1", "node": 3542, "naklon": null }, +{ "label": "41/2", "node": 3566, "naklon": null }, +{ "label": "41/3", "node": 3548, "naklon": null }, +{ "label": "41/4", "node": 3515, "naklon": null }, +{ "label": "41/5", "node": 3559, "naklon": null }, +{ "label": "41/6", "node": 3509, "naklon": null }, +{ "label": "41/7", "node": 3524, "naklon": null }, +{ "label": "41/8", "node": 3518, "naklon": null }, +{ "label": "41/9", "node": 3182, "naklon": null }, +{ "label": "41/10", "node": 3187, "naklon": null }, +{ "label": "41/11", "node": 3195, "naklon": 0 }, +{ "label": "41/12", "node": 3857, "naklon": 0 }, +{ "label": "41/13", "node": 3183, "naklon": 0 }, +{ "label": "41/14", "node": 3177, "naklon": 0 }, +{ "label": "41/15", "node": 3189, "naklon": 0 }, +{ "label": "41/16", "node": 3186, "naklon": 0 }, +{ "label": "42/1", "node": 3178, "naklon": 0 }, +{ "label": "42/2", "node": 3219, "naklon": 0 }, +{ "label": "42/3", "node": 3475, "naklon": 0 }, +{ "label": "42/4", "node": 3175, "naklon": 0 }, +{ "label": "42/5", "node": 3222, "naklon": 0 }, +{ "label": "42/6", "node": 3221, "naklon": 0 }, +{ "label": "42/7", "node": 3181, "naklon": 0 }, +{ "label": "42/8", "node": 3180, "naklon": 0 }, +{ "label": "42/9", "node": 3218, "naklon": 0 }, +{ "label": "42/10", "node": 3176, "naklon": 0 }, +{ "label": "42/11", "node": 3174, "naklon": 0 }, +{ "label": "42/12", "node": 3220, "naklon": 0 }, +{ "label": "42/13", "node": 3533, "naklon": null }, +{ "label": "42/14", "node": 3543, "naklon": null }, +{ "label": "42/15", "node": 3554, "naklon": null }, +{ "label": "42/16", "node": 3549, "naklon": null }, +{ "label": "43/1", "node": 2857, "naklon": 5 }, +{ "label": "43/2", "node": 2752, "naklon": 5 }, +{ "label": "43/3", "node": 2753, "naklon": 5 }, +{ "label": "43/4", "node": 3024, "naklon": 5 }, +{ "label": "43/5", "node": 2754, "naklon": 5 }, +{ "label": "43/6", "node": 4423, "naklon": 5 }, +{ "label": "43/7", "node": 4368, "naklon": 5 }, +{ "label": "43/8", "node": 2978, "naklon": 5 }, +{ "label": "43/9", "node": 2868, "naklon": 5 }, +{ "label": "43/10", "node": 4377, "naklon": 5 }, +{ "label": "43/11", "node": 2757, "naklon": 5 }, +{ "label": "43/12", "node": 2970, "naklon": 5 }, +{ "label": "43/13", "node": 2758, "naklon": 5 }, +{ "label": "43/14", "node": 4378, "naklon": 5 }, +{ "label": "43/15", "node": 2759, "naklon": 5 }, +{ "label": "43/16", "node": 4342, "naklon": 5 }, +{ "label": "43/17", "node": 3026, "naklon": null }, +{ "label": "43/18", "node": 2986, "naklon": null }, +{ "label": "43/19", "node": 4343, "naklon": null }, +{ "label": "43/20", "node": 2760, "naklon": null }, +{ "label": "43/21", "node": 4379, "naklon": null }, +{ "label": "43/22", "node": 2971, "naklon": null }, +{ "label": "43/23", "node": 2761, "naklon": null }, +{ "label": "43/24", "node": 2762, "naklon": null }, +{ "label": "43/25", "node": 4339, "naklon": null }, +{ "label": "43/26", "node": 4380, "naklon": null }, +{ "label": "43/27", "node": 2975, "naklon": null }, +{ "label": "43/28", "node": 3003, "naklon": null }, +{ "label": "43/29", "node": 4338, "naklon": null }, +{ "label": "43/30", "node": 3002, "naklon": null }, +{ "label": "43/31", "node": 4345, "naklon": null }, +{ "label": "43/32", "node": 2979, "naklon": null }, +{ "label": "43/33", "node": 2989, "naklon": null }, +{ "label": "43/34", "node": 2996, "naklon": null }, +{ "label": "43/35", "node": 2972, "naklon": null }, +{ "label": "43/36", "node": 2988, "naklon": null }, +{ "label": "43/37", "node": 4344, "naklon": null }, +{ "label": "43/38", "node": 3022, "naklon": null }, +{ "label": "43/39", "node": 4341, "naklon": null }, +{ "label": "43/40", "node": 2983, "naklon": null }, +{ "label": "43/41", "node": 2995, "naklon": null }, +{ "label": "43/42", "node": 2763, "naklon": null }, +{ "label": "43/43", "node": 2764, "naklon": null }, +{ "label": "43/44", "node": 2765, "naklon": null }, +{ "label": "43/45", "node": 2766, "naklon": null }, +{ "label": "43/46", "node": 2767, "naklon": null }, +{ "label": "43/47", "node": 2768, "naklon": null }, +{ "label": "43/48", "node": 3018, "naklon": null }, +{ "label": "43/49", "node": 2982, "naklon": null }, +{ "label": "43/50", "node": 3019, "naklon": 0 }, +{ "label": "43/51", "node": 3013, "naklon": null }, +{ "label": "43/52", "node": 3007, "naklon": null }, +{ "label": "43/53", "node": 2980, "naklon": null }, +{ "label": "43/54", "node": 3011, "naklon": null }, +{ "label": "43/55", "node": 2672, "naklon": null }, +{ "label": "43/56", "node": 2673, "naklon": null }, +{ "label": "43/57", "node": 2674, "naklon": null }, +{ "label": "43/58", "node": 2675, "naklon": null }, +{ "label": "43/59", "node": 2676, "naklon": null }, +{ "label": "43/60", "node": 2677, "naklon": null }, +{ "label": "43/61", "node": 2678, "naklon": null }, +{ "label": "43/62", "node": 2679, "naklon": null }, +{ "label": "43/63", "node": 2680, "naklon": null }, +{ "label": "43/64", "node": 2840, "naklon": null }, +{ "label": "43/65", "node": 2682, "naklon": null }, +{ "label": "43/66", "node": 2683, "naklon": null }, +{ "label": "43/67", "node": 2684, "naklon": 0 }, +{ "label": "43/68", "node": 2685, "naklon": null }, +{ "label": "43/69", "node": 2686, "naklon": null }, +{ "label": "43/70", "node": 2687, "naklon": null }, +{ "label": "43/71", "node": 2688, "naklon": null }, +{ "label": "43/72", "node": 2689, "naklon": null }, +{ "label": "43/73", "node": 2690, "naklon": null }, +{ "label": "43/74", "node": 2691, "naklon": null }, +{ "label": "43/75", "node": 2692, "naklon": null }, +{ "label": "43/76", "node": 2693, "naklon": 0 }, +{ "label": "43/77", "node": 2694, "naklon": null }, +{ "label": "43/78", "node": 2695, "naklon": null }, +{ "label": "43/79", "node": 2696, "naklon": 0 }, +{ "label": "43/80", "node": 2697, "naklon": null }, +{ "label": "43/81", "node": 2698, "naklon": 0 }, +{ "label": "43/82", "node": 2699, "naklon": null }, +{ "label": "43/83", "node": 2700, "naklon": 0 }, +{ "label": "43/84", "node": 2744, "naklon": null }, +{ "label": "43/85", "node": 2745, "naklon": 0 }, +{ "label": "43/86", "node": 2746, "naklon": null }, +{ "label": "43/87", "node": 2747, "naklon": 0 }, +{ "label": "43/88", "node": 2748, "naklon": null }, +{ "label": "43/89", "node": 2749, "naklon": 0 }, +{ "label": "43/90", "node": 2841, "naklon": null }, +{ "label": "45/1", "node": 4237, "naklon": 5 }, +{ "label": "45/2", "node": 4226, "naklon": 5 }, +{ "label": "45/3", "node": 4242, "naklon": 5 }, +{ "label": "45/4", "node": 4179, "naklon": 5 }, +{ "label": "45/5", "node": 4247, "naklon": 5 }, +{ "label": "45/6", "node": 4245, "naklon": 5 }, +{ "label": "45/7", "node": 3872, "naklon": 5 }, +{ "label": "45/8", "node": 4175, "naklon": 5 }, +{ "label": "45/9", "node": 4236, "naklon": 5 }, +{ "label": "45/10", "node": 4170, "naklon": 5 }, +{ "label": "45/11", "node": 4238, "naklon": 5 }, +{ "label": "45/12", "node": 4246, "naklon": 5 }, +{ "label": "45/13", "node": 4166, "naklon": 5 }, +{ "label": "45/14", "node": 4227, "naklon": 5 }, +{ "label": "45/15", "node": 4171, "naklon": 5 }, +{ "label": "45/16", "node": 4180, "naklon": 5 }, +{ "label": "45/17", "node": 4244, "naklon": 5 }, +{ "label": "45/18", "node": 4199, "naklon": 5 }, +{ "label": "45/19", "node": 4239, "naklon": 5 }, +{ "label": "45/20", "node": 4207, "naklon": 5 }, +{ "label": "45/21", "node": 4223, "naklon": 5 }, +{ "label": "45/22", "node": 4230, "naklon": 5 }, +{ "label": "45/23", "node": 4233, "naklon": 5 }, +{ "label": "45/24", "node": 4222, "naklon": 5 }, +{ "label": "45/25", "node": 4217, "naklon": 5 }, +{ "label": "45/26", "node": 4243, "naklon": 5 }, +{ "label": "45/27", "node": 4200, "naklon": 5 }, +{ "label": "45/28", "node": 4228, "naklon": 5 }, +{ "label": "45/29", "node": 4211, "naklon": 5 }, +{ "label": "45/30", "node": 4234, "naklon": 5 }, +{ "label": "45/31", "node": 4235, "naklon": 5 }, +{ "label": "45/32", "node": 4203, "naklon": 5 }, +{ "label": "45/33", "node": 4240, "naklon": 5 }, +{ "label": "45/34", "node": 4224, "naklon": 5 }, +{ "label": "45/35", "node": 4232, "naklon": 5 }, +{ "label": "45/36", "node": 4231, "naklon": 5 }, +{ "label": "45/37", "node": 4161, "naklon": 5 }, +{ "label": "45/38", "node": 4225, "naklon": 5 }, +{ "label": "45/39", "node": 4241, "naklon": 5 }, +{ "label": "45/40", "node": 4229, "naklon": 5 }, +{ "label": "45/41", "node": 4221, "naklon": 5 }, +{ "label": "45/42", "node": 4212, "naklon": 5 }, +{ "label": "45/43", "node": 4216, "naklon": 5 }, +{ "label": "45/44", "node": 3864, "naklon": null }, +{ "label": "46/1", "node": 3806, "naklon": 5 }, +{ "label": "46/2", "node": 3813, "naklon": 5 }, +{ "label": "46/3", "node": 3815, "naklon": 5 }, +{ "label": "46/4", "node": 3807, "naklon": 5 }, +{ "label": "46/5", "node": 3895, "naklon": 5 }, +{ "label": "46/6", "node": 3809, "naklon": 5 }, +{ "label": "46/7", "node": 3820, "naklon": 5 }, +{ "label": "46/8", "node": 3805, "naklon": 5 }, +{ "label": "46/9", "node": 3894, "naklon": 0 }, +{ "label": "46/10", "node": 4055, "naklon": 0 }, +{ "label": "46/11", "node": 3812, "naklon": 5 }, +{ "label": "46/12", "node": 3822, "naklon": 5 }, +{ "label": "46/13", "node": 3821, "naklon": 5 }, +{ "label": "46/14", "node": 3808, "naklon": 5 }, +{ "label": "46/15", "node": 3799, "naklon": 5 }, +{ "label": "46/16", "node": 3816, "naklon": 5 }, +{ "label": "46/17", "node": 3751, "naklon": 5 }, +{ "label": "46/18", "node": 3814, "naklon": 5 }, +{ "label": "46/19", "node": 4044, "naklon": 0 }, +{ "label": "46/20", "node": 3931, "naklon": 0 }, +{ "label": "46/21", "node": 3902, "naklon": 5 }, +{ "label": "46/22", "node": 3916, "naklon": 5 }, +{ "label": "46/23", "node": 3892, "naklon": 5 }, +{ "label": "46/24", "node": 3914, "naklon": 5 }, +{ "label": "46/25", "node": 3898, "naklon": 5 }, +{ "label": "46/26", "node": 3897, "naklon": 5 }, +{ "label": "46/27", "node": 3885, "naklon": 5 }, +{ "label": "46/28", "node": 3906, "naklon": 5 }, +{ "label": "46/29", "node": 3930, "naklon": 0 }, +{ "label": "46/30", "node": 3936, "naklon": 0 }, +{ "label": "46/31", "node": 3860, "naklon": 5 }, +{ "label": "46/32", "node": 3841, "naklon": 5 }, +{ "label": "46/33", "node": 3873, "naklon": 5 }, +{ "label": "46/34", "node": 3854, "naklon": 5 }, +{ "label": "46/35", "node": 3939, "naklon": 5 }, +{ "label": "46/36", "node": 3858, "naklon": 5 }, +{ "label": "46/37", "node": 3940, "naklon": 5 }, +{ "label": "46/38", "node": 4035, "naklon": 5 }, +{ "label": "47/1", "node": 3373, "naklon": 0 }, +{ "label": "47/2", "node": 3374, "naklon": 0 }, +{ "label": "47/3", "node": 3384, "naklon": 0 }, +{ "label": "47/4", "node": 3385, "naklon": 0 }, +{ "label": "48/1", "node": 4051, "naklon": 5 }, +{ "label": "48/2", "node": 4041, "naklon": 5 }, +{ "label": "48/3", "node": 4056, "naklon": 5 }, +{ "label": "48/4", "node": 3875, "naklon": 5 }, +{ "label": "48/5", "node": 4061, "naklon": 5 }, +{ "label": "48/6", "node": 4047, "naklon": 5 }, +{ "label": "48/7", "node": 4060, "naklon": 5 }, +{ "label": "48/8", "node": 4059, "naklon": 5 }, +{ "label": "48/9", "node": 4058, "naklon": 5 }, +{ "label": "48/10", "node": 3635, "naklon": 5 }, +{ "label": "48/11", "node": 3640, "naklon": 5 }, +{ "label": "48/12", "node": 3747, "naklon": 5 }, +{ "label": "48/13", "node": 3629, "naklon": 5 }, +{ "label": "48/14", "node": 4048, "naklon": 5 }, +{ "label": "48/15", "node": 4063, "naklon": 5 }, +{ "label": "48/16", "node": 4062, "naklon": 5 }, +{ "label": "48/17", "node": 4043, "naklon": 5 }, +{ "label": "48/18", "node": 4052, "naklon": 5 }, +{ "label": "48/19", "node": 4042, "naklon": 5 }, +{ "label": "48/20", "node": 4053, "naklon": 5 }, +{ "label": "50/15A", "node": 4167, "naklon": null }, +{ "label": "50/15B", "node": 4159, "naklon": null }, +{ "label": "50/1", "node": 4183, "naklon": 0 }, +{ "label": "50/2", "node": 4157, "naklon": 0 }, +{ "label": "50/3", "node": 4160, "naklon": 0 }, +{ "label": "50/4", "node": 4173, "naklon": 0 }, +{ "label": "50/5", "node": 4177, "naklon": 0 }, +{ "label": "50/6", "node": 4174, "naklon": 0 }, +{ "label": "50/7", "node": 4178, "naklon": 0 }, +{ "label": "50/8", "node": 4195, "naklon": 0 }, +{ "label": "50/9", "node": 4169, "naklon": 0 }, +{ "label": "50/10", "node": 4162, "naklon": 0 }, +{ "label": "50/11", "node": 4158, "naklon": 0 }, +{ "label": "50/12", "node": 4182, "naklon": 0 }, +{ "label": "50/13", "node": 4194, "naklon": 0 }, +{ "label": "50/14", "node": 4184, "naklon": 0 }, +{ "label": "50/16", "node": 4197, "naklon": null }, +{ "label": "50/17", "node": 4164, "naklon": null }, +{ "label": "50/18", "node": 3306, "naklon": null }, +{ "label": "50/19", "node": 4168, "naklon": null }, +{ "label": "50/20", "node": 4193, "naklon": null }, +{ "label": "50/21", "node": 4187, "naklon": null }, +{ "label": "50/22", "node": 4163, "naklon": null }, +{ "label": "50/23", "node": 4165, "naklon": null }, +{ "label": "50/24", "node": 4185, "naklon": null }, +{ "label": "50/25", "node": 3904, "naklon": null }, +{ "label": "53/1", "node": 2619, "naklon": 0 }, +{ "label": "53/2", "node": 2623, "naklon": 0 }, +{ "label": "53/3", "node": 2617, "naklon": 0 }, +{ "label": "53/4", "node": 2622, "naklon": 0 }, +{ "label": "53/5", "node": 2618, "naklon": 0 }, +{ "label": "53/6", "node": 2626, "naklon": 0 }, +{ "label": "53/7", "node": 2869, "naklon": 0 }, +{ "label": "53/8", "node": 2613, "naklon": 0 }, +{ "label": "53/9", "node": 2608, "naklon": 0 }, +{ "label": "53/10", "node": 2611, "naklon": 0 }, +{ "label": "53/11", "node": 2598, "naklon": 0 }, +{ "label": "53/12", "node": 3528, "naklon": 0 }, +{ "label": "53/13", "node": 3545, "naklon": 0 }, +{ "label": "53/14", "node": 2620, "naklon": 0 }, +{ "label": "53/15", "node": 2612, "naklon": 0 }, +{ "label": "53/16", "node": 2615, "naklon": 0 }, +{ "label": "53/17", "node": 3722, "naklon": 0 }, +{ "label": "53/18", "node": 2624, "naklon": 0 }, +{ "label": "53/19", "node": 2609, "naklon": 0 }, +{ "label": "53/20", "node": 2625, "naklon": 0 }, +{ "label": "53/21", "node": 2602, "naklon": 0 }, +{ "label": "53/22", "node": 2610, "naklon": 0 }, +{ "label": "53/23", "node": 2599, "naklon": 0 }, +{ "label": "53/24", "node": 2605, "naklon": 0 }, +{ "label": "53/25", "node": 2593, "naklon": 0 }, +{ "label": "53/26", "node": 3074, "naklon": 0 }, +{ "label": "53/27", "node": 2740, "naklon": 0 }, +{ "label": "53/28", "node": 2614, "naklon": 0 }, +{ "label": "53/29", "node": 2601, "naklon": 0 }, +{ "label": "53/30", "node": 4196, "naklon": 0 }, +{ "label": "53/31", "node": 2607, "naklon": 0 }, +{ "label": "53/32", "node": 2582, "naklon": 0 }, +{ "label": "53/33", "node": 2594, "naklon": 0 }, +{ "label": "53/34", "node": 2589, "naklon": 0 }, +{ "label": "53/35", "node": 2596, "naklon": 0 }, +{ "label": "53/36", "node": 2603, "naklon": 0 }, +{ "label": "53/37", "node": 2597, "naklon": 0 }, +{ "label": "53/38", "node": 2590, "naklon": 0 }, +{ "label": "53/39", "node": 2581, "naklon": 0 }, +{ "label": "53/40", "node": 2583, "naklon": 0 }, +{ "label": "53/41", "node": 2580, "naklon": 0 }, +{ "label": "53/42", "node": 2579, "naklon": 0 }, +{ "label": "53/43", "node": 2797, "naklon": 0 }, +{ "label": "53/44", "node": 2577, "naklon": 0 }, +{ "label": "53/45", "node": 2586, "naklon": 0 }, +{ "label": "53/46", "node": 2588, "naklon": 0 }, +{ "label": "53/47", "node": 2591, "naklon": 0 }, +{ "label": "53/48", "node": 2592, "naklon": 0 }, +{ "label": "53/49", "node": 2573, "naklon": 0 }, +{ "label": "53/50", "node": 2595, "naklon": 0 }, +{ "label": "53/51", "node": 2587, "naklon": 0 }, +{ "label": "53/52", "node": 2578, "naklon": 0 }, +{ "label": "53/53", "node": 2574, "naklon": 0 }, +{ "label": "53/54", "node": 2571, "naklon": 0 }, +{ "label": "53/55", "node": 2570, "naklon": 0 }, +{ "label": "53/56", "node": 2576, "naklon": 0 }, +{ "label": "53/57", "node": 2881, "naklon": 0 }, +{ "label": "53/58", "node": 2575, "naklon": 0 }, +{ "label": "53/59", "node": 2572, "naklon": 0 }, +{ "label": "53/60", "node": 2569, "naklon": 0 }, +{ "label": "55/1", "node": 4324, "naklon": 0 }, +{ "label": "55/2", "node": 4319, "naklon": 0 }, +{ "label": "55/3", "node": 4327, "naklon": 0 }, +{ "label": "55/4", "node": 4333, "naklon": 0 }, +{ "label": "55/5", "node": 4332, "naklon": 0 }, +{ "label": "55/6", "node": 4320, "naklon": 0 }, +{ "label": "55/7", "node": 4317, "naklon": 0 }, +{ "label": "55/8", "node": 4318, "naklon": 0 }, +{ "label": "55/9", "node": 4328, "naklon": 0 }, +{ "label": "55/10", "node": 4323, "naklon": 0 }, +{ "label": "55/11", "node": 4325, "naklon": 0 }, +{ "label": "55/12", "node": 4326, "naklon": 0 }, +{ "label": "55/13", "node": 4316, "naklon": 0 }, +{ "label": "55/14", "node": 4322, "naklon": 0 }, +{ "label": "55/15", "node": 4331, "naklon": 0 }, +{ "label": "55/16", "node": 4321, "naklon": 0 }, +{ "label": "55/17", "node": 4315, "naklon": 0 }, +{ "label": "55/18", "node": 4329, "naklon": 0 }, +{ "label": "55/19", "node": 4334, "naklon": 0 }, +{ "label": "55/20", "node": 4330, "naklon": 0 } +]; + +module.exports = { naklony }; diff --git a/RVO15/databases/modbus_config.js b/RVO15/databases/modbus_config.js new file mode 100755 index 0000000..b73116a --- /dev/null +++ b/RVO15/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/RVO15/databases/nodes.table b/RVO15/databases/nodes.table new file mode 100755 index 0000000..018b282 --- /dev/null +++ b/RVO15/databases/nodes.table @@ -0,0 +1,147 @@ +node:number|pole_number:string|node_type:string|tbname:string|line:number|profile:string|processed:boolean|status:boolean|time_of_last_communication:number ++|2835|30|NEMA|PLBJzmK1r3Gynd6OW0gKPM0e5wV4vx9bDEqNgYR8|3|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760574169221|............. ++|2836|87|NEMA|eod9aRWLVl34Gx1Dn7VNBa72rz6qjgmpEXwQJN5Z|3|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760574173949|............. ++|2852|32|NEMA|rDbQ84xzwgdqEoPm3kbEG309anOZY1RXyBv2LVM6|3|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573972794|............. ++|2861|27|NEMA|EjgWGnXaLy9opPOz20n4G4786BlYM3w1deVQvbKr|3|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760574202379|............. ++|2862|26|NEMA|3a5oqJN1bgnx4Ol9dk89qB7ByE6jQ8mKDWMpGrLV|3|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760574205286|............. ++|2866|28|NEMA|wvKJdZML6mXP4DzWBAXxGWAjxNloa5g23Ve9Y1ry|3|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573735240|............. ++|2874|31|NEMA|52dD6ZlV1QaOpRBmbAqGPgkKnGzWMLj4eJq38Pgo|3|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573741836|............. ++|3001|29/1|IP65|o9vbeQlLMVg8j5dq4keLNb0NxZpEmnXzwYKO1ar2|3|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573778733|............. ++|3546|28/1|IP65|apKVJBwOyrP35m2lv7KY950YXbeWNd64En9GxRqg|3|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573633784|............. ++|4146|29|IP65|ZmRwd93QL4gaezxEbAx2LOk1prn2XjlPvGyqJ6BO|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573862044|............. ++|2795|23|NEMA|nJL5lPMwBx23YpqRe0rpx27damXvWVbOrD4gNzy8|3|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573681797|............. ++|2796|7|NEMA|gRoJEyXVx4qD9er287L4JQ7wBzGldaPjLWQKm3Mv|3|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573682052|............. ++|2799|11|NEMA|aw4eELG2DlPMdn1JW0BMJaAqQXOZRN3xB5yp8VKr|3|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573683155|............. ++|2801|4|NEMA|PjLblDgRBO6WQqnxmkJ1Jg0Jv3ewZN4p5a89yKdY|3|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573683554|............. ++|2802|121|NEMA|o9vbeQlLMVg8j5dq4keLmX0NxZpEmnXzwYKO1ar2|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":7,"dusk_lux_sensor_value":7,"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|1760573685295|............... ++|2803|8|NEMA|K94XLav1glVRnyQ6r01PKwAme3YJwBxM5oOzdP2j|3|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573686030|............. ++|2804|12|NEMA|ZmRwd93QL4gaezxEbAx2gVk1prn2XjlPvGyqJ6BO|3|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573686285|............. ++|2807|24|NEMA|ZmRwd93QL4gaezxEbAx2B9k1prn2XjlPvGyqJ6BO|3|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573921796|............. ++|2808|22|NEMA|roKgWqY95V3mXMRzyAjKGe0bLjexpJPvaGDBw826|3|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573992105|............. ++|2812|19|NEMA|52dD6ZlV1QaOpRBmbAqG6qkKnGzWMLj4eJq38Pgo|3|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573698233|............. ++|2815|5|NEMA|dz4ojlpP85JMgDLZWkQJDn7aKYqQexEr62GXRV1y|3|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573998030|............. ++|2821|9|NEMA|d9x2V5LGYBzXp4mMRAOmGvkPloaqJwnQj6DgrNe3|3|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573998558|............. ++|2826|21|NEMA|E6Kg9oDnLWyzPRMva7v5XbkJxp4VG58qO2w1lZYe|3|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760574162752|............. ++|2829|6|NEMA|d5xjWYMwEJon6rLlK7yEqN7qgV4DaOeNB9ZX3Gzb|3|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760574008365|............. ++|2831|25|NEMA|eod9aRWLVl34Gx1Dn7VNGa72rz6qjgmpEXwQJN5Z|3|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760574011415|............. ++|2847|36|NEMA|XMBbew5z4ELrZa2mRAd3GO78vPN6gy3DdVYlpKjq|3|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760574024129|............. ++|2848|38|NEMA|zdQO8GwxDqjRgP4137YVGaANyKlpem2nL65rvVJY|3|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760574025439|............. ++|2849|44|NEMA|apKVJBwOyrP35m2lv7KYlv0YXbeWNd64En9GxRqg|3|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760574025694|............. ++|2851|33|05-Repeater|E6Kg9oDnLWyzPRMva7v5PakJxp4VG58qO2w1lZYe|3|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760574025950|............. ++|2854|41|NEMA|zrR51V2ajQ9ZLygPKkEMlJkYDq38xOJolENBXGnv|3|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573695613|............. ++|2856|35|NEMA|nJL5lPMwBx23YpqRe0rpPV7damXvWVbOrD4gNzy8|3|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760574032531|............. ++|2858|34|NEMA|roKgWqY95V3mXMRzyAjKPD0bLjexpJPvaGDBw826|3|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760574158839|............. ++|2859|42|NEMA|BaY3Xpy1EbKGjLq2O7mapp7rx8owgQz9P4dDJRmN|3|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573607430|............. ++|2863|39|NEMA|WlVJBygjDZMeKX3vnAMRlZ08NqdmG2x1Y69LQ4P5|3|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760574205606|............. ++|2864|45|NEMA|o9vbeQlLMVg8j5dq4keLGX0NxZpEmnXzwYKO1ar2|3|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573734266|............. ++|2872|43|NEMA|DbQY6zyveZRwK5drV0Z8Gq7joE4XJM83N9xl2nWq|3|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573737444|............. ++|2873|40|NEMA|5dBNwRp9graYJxZn409Nb3klVov1b2QLPDqGm6XK|3|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573741485|............. ++|2901|117|NEMA|zrR51V2ajQ9ZLygPKkEM3JkYDq38xOJolENBXGnv|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":7,"dusk_lux_sensor_value":7,"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|1760573772024|............... ++|2906|115|NEMA|WlVJBygjDZMeKX3vnAMR2Z08NqdmG2x1Y69LQ4P5|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":7,"dusk_lux_sensor_value":7,"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|1760573772727|............... ++|2907|114|NEMA|zdQO8GwxDqjRgP4137YVBaANyKlpem2nL65rvVJY|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":7,"dusk_lux_sensor_value":7,"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|1760573772871|............... ++|2908|116|NEMA|5dBNwRp9graYJxZn409ND3klVov1b2QLPDqGm6XK|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":7,"dusk_lux_sensor_value":7,"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|1760573773030|............... ++|2853|108|NEMA|52dD6ZlV1QaOpRBmbAqGQgkKnGzWMLj4eJq38Pgo|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":7,"dusk_lux_sensor_value":7,"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|1760574030965|............... ++|2913|118|NEMA|BaY3Xpy1EbKGjLq2O7maQp7rx8owgQz9P4dDJRmN|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":7,"dusk_lux_sensor_value":7,"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|1760573773398|............... ++|2918|101|NEMA|ZmRwd93QL4gaezxEbAx2Q9k1prn2XjlPvGyqJ6BO|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":7,"dusk_lux_sensor_value":7,"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|1760574052368|............... ++|2919|106|NEMA|Nzp2OoJlqn6r1ZgvdA3BDd7abBwP5G4eE3RQmyxD|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":7,"dusk_lux_sensor_value":7,"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|1760573774085|............... ++|2981|50|Kamera|m6EYyZoJ4gWexdjVPAR5lx7RDOq9wv2N5XzKGplr|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":7,"dusk_lux_sensor_value":7,"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|1760574007710|............... ++|2984|40/1|IP65|m6EYyZoJ4gWexdjVPAR5pw7RDOq9wv2N5XzKGplr|3|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760574008572|............. ++|3006|53|IP65|OzNMgZ9n43qPbjXmy7zwPJA2DKdYvW5e6pxGRrVa|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":7,"dusk_lux_sensor_value":7,"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|1760574009994|............... ++|3008|47/1|IP65|3a5oqJN1bgnx4Ol9dk89jZ7ByE6jQ8mKDWMpGrLV|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":7,"dusk_lux_sensor_value":7,"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|1760574010249|............... ++|3012|54|IP65|JX1ObgmqGZ54DMyYL7aDG1kEVdve38WKRzwjNrQ9|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":7,"dusk_lux_sensor_value":7,"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|1760574062702|............... ++|3014|49|IP65|6lQGaY9RDywdVzObj0PaB8kPg4NBn3exEK51LWZq|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":7,"dusk_lux_sensor_value":7,"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|1760574063341|............... ++|3017|48|IP65|pE5X8NQPaow6vlOZxk6a3j0q42ezGBMyWgDVjR3L|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":7,"dusk_lux_sensor_value":7,"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|1760574063916|............... ++|3020|51|IP65|JzwxZXOvDj1bVrN4nkW5GQA8qdyBl3MRKLpGPgaQ|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":7,"dusk_lux_sensor_value":7,"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|1760574068021|............... ++|3021|47|IP65|2O14VBzl8aDmWdNw3A59XlAGyZ5qLJoEMpj6R9ng|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":7,"dusk_lux_sensor_value":7,"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|1760574068452|............... ++|3027|52|IP65|g9OxBZ5KRwNznlY6pAppaxAWXvjdEL4eGQobMDy2|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":7,"dusk_lux_sensor_value":7,"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|1760574072813|............... ++|3105|96|NEMA|52dD6ZlV1QaOpRBmbAqGLgkKnGzWMLj4eJq38Pgo|3|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760574091484|............. ++|3105|18|NEMA|52dD6ZlV1QaOpRBmbAqGLgkKnGzWMLj4eJq38Pgo|3|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760574091484|............. ++|3139|125|Kamera|Z5KyJe9nEg1QNbWlX0w4YDkoDjBLdqzR83VGv624|3|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760574105587|............. ++|3396|1|NEMA|3JjOWdylwgNLzxVab7NaJ8kZ2vG64rq8PEB5QmDo|3|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573631708|............. ++|3400|10|NEMA|B5EoxeMVp4zwr8nqW0GBJYARjvD1PNamOGbLg63Z|3|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573632443|............. ++|3553|46|IP65|eod9aRWLVl34Gx1Dn7VNBM72rz6qjgmpEXwQJN5Z|3|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573839922|............. ++|3556|36/1|IP65|pE5X8NQPaow6vlOZxk6aog0q42ezGBMyWgDVjR3L|3|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760572808228|............. ++|3557|66/1|IP65|OzNMgZ9n43qPbjXmy7zwEaA2DKdYvW5e6pxGRrVa|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573642777|............. ++|3560|33/1|IP65|gP1eOZVj3Q9lv5aDEk45lM7rdpqW8yLm2BbKzJxM|3|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573643192|............. ++|3656|119|NEMA|DbQY6zyveZRwK5drV0Z8qq7joE4XJM83N9xl2nWq|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":7,"dusk_lux_sensor_value":7,"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|1760573643352|............... ++|3859|109|NEMA|rDbQ84xzwgdqEoPm3kbEM309anOZY1RXyBv2LVM6|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":7,"dusk_lux_sensor_value":7,"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|1760573644741|............... ++|3740|94|NEMA|Nzp2OoJlqn6r1ZgvdA3B3d7abBwP5G4eE3RQmyxD|3|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573644102|............. ++|3926|100|NEMA|aw4eELG2DlPMdn1JW0BMEnAqQXOZRN3xB5yp8VKr|3|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573855112|............. ++|3950|37|NEMA|gYbDLqlyZVoRerQpB72MVjkWJnwM5z24POKa8Exj|3|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573856789|............. ++|4216|59/2|Kamera|g9OxBZ5KRwNznlY6pAppqEAWXvjdEL4eGQobMDy2|3|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":7,"dusk_lux_sensor_value":7,"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|1760573659883|............... ++|4303|12/1|IP65|JzwxZXOvDj1bVrN4nkW58QA8qdyBl3MRKLpGPgaQ|3|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573863034|............. ++|4304|8/1|IP65|6lQGaY9RDywdVzObj0Pal8kPg4NBn3exEK51LWZq|3|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573664020|............. ++|4306|34/1|IP65|2O14VBzl8aDmWdNw3A59l9AGyZ5qLJoEMpj6R9ng|3|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573867953|............. ++|4309|12/2|IP65|g9OxBZ5KRwNznlY6pAppvxAWXvjdEL4eGQobMDy2|3|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573670217|............. ++|4311|8/2|IP65|m6EYyZoJ4gWexdjVPAR5Dx7RDOq9wv2N5XzKGplr|3|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573670888|............. ++|4313|39/1|IP65|6lQGaY9RDywdVzObj0PaeOkPg4NBn3exEK51LWZq|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573671447|............. ++|4346|64|NEMA|K94XLav1glVRnyQ6r01PxzAme3YJwBxM5oOzdP2j|3|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":7,"dusk_lux_sensor_value":7,"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|1760573878942|............... ++|2705|102|NEMA|eod9aRWLVl34Gx1Dn7VNna72rz6qjgmpEXwQJN5Z|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":7,"dusk_lux_sensor_value":7,"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|1760574049413|............... ++|2708|103|NEMA|3a5oqJN1bgnx4Ol9dk89DB7ByE6jQ8mKDWMpGrLV|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":7,"dusk_lux_sensor_value":7,"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|1760574050180|............... ++|2709|112|NEMA|XMBbew5z4ELrZa2mRAd3EO78vPN6gy3DdVYlpKjq|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":7,"dusk_lux_sensor_value":7,"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|1760574051410|............... ++|2710|113|NEMA|gYbDLqlyZVoRerQpB72MDjkWJnwM5z24POKa8Exj|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":7,"dusk_lux_sensor_value":7,"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|1760574054013|............... ++|2711|111|NEMA|nJL5lPMwBx23YpqRe0rpQV7damXvWVbOrD4gNzy8|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":7,"dusk_lux_sensor_value":7,"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|1760574061823|............... ++|2712|110|NEMA|roKgWqY95V3mXMRzyAjKOD0bLjexpJPvaGDBw826|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":7,"dusk_lux_sensor_value":7,"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|1760574068676|............... ++|2713|60|NEMA|PjLblDgRBO6WQqnxmkJ1Gr0Jv3ewZN4p5a89yKdY|3|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":7,"dusk_lux_sensor_value":7,"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|1760574068883|............... ++|2719|105|NEMA|wvKJdZML6mXP4DzWBAXx3WAjxNloa5g23Ve9Y1ry|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":7,"dusk_lux_sensor_value":7,"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|1760574072206|............... ++|2721|104|NEMA|EjgWGnXaLy9opPOz20n4Q4786BlYM3w1deVQvbKr|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":7,"dusk_lux_sensor_value":7,"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|1760574076981|............... ++|2725|56|NEMA|RO8rjaBDy21qPQJzW7omP60pK3xmNleVZg9Ed4Gw|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":7,"dusk_lux_sensor_value":7,"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|1760574083290|............... ++|2727|98|NEMA|E6Kg9oDnLWyzPRMva7v5LakJxp4VG58qO2w1lZYe|3|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573964121|............. ++|2732|97|NEMA|rDbQ84xzwgdqEoPm3kbEd309anOZY1RXyBv2LVM6|3|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573964920|............. ++|2734|95|NEMA|PLBJzmK1r3Gynd6OW0gKEM0e5wV4vx9bDEqNgYR8|3|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573968274|............. ++|2735|99|NEMA|roKgWqY95V3mXMRzyAjKLD0bLjexpJPvaGDBw826|3|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573670489|............. ++|2738|55|NEMA|RvmwNz8QPblKp41GD7lKPjkJrLVYoBO92dMegn6W|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":7,"dusk_lux_sensor_value":7,"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|1760573674274|............... ++|2739|63|NEMA|gRoJEyXVx4qD9er287L4Dv7wBzGldaPjLWQKm3Mv|3|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":7,"dusk_lux_sensor_value":7,"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|1760573674418|............... ++|2781|120|NEMA|apKVJBwOyrP35m2lv7KYrv0YXbeWNd64En9GxRqg|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":7,"dusk_lux_sensor_value":7,"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|1760573675344|............... ++|2783|123|NEMA|2O14VBzl8aDmWdNw3A59DlAGyZ5qLJoEMpj6R9ng|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":7,"dusk_lux_sensor_value":7,"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|1760573675967|............... ++|2784|2|NEMA|Z5KyJe9nEg1QNbWlX0w43zkoDjBLdqzR83VGv624|3|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573676191|............. ++|2788|3|NEMA|1JMYvnx2RzKEo4aWQ7DGJvkL8yZV3m9NBePXbrdj|3|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573678427|............. ++|2791|122|NEMA|gP1eOZVj3Q9lv5aDEk45DZ7rdpqW8yLm2BbKzJxM|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":7,"dusk_lux_sensor_value":7,"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|1760573678938|............... ++|2794|124|NEMA|pE5X8NQPaow6vlOZxk6aDj0q42ezGBMyWgDVjR3L|3|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":7,"dusk_lux_sensor_value":7,"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|1760573681510|............... ++|2843|78|06-Repeater|dz4ojlpP85JMgDLZWkQJEG7aKYqQexEr62GXRV1y|2||1|1|1760574021110|............. ++|2844|80|NEMA|d5xjWYMwEJon6rLlK7yEzm7qgV4DaOeNB9ZX3Gzb|2||1|1|1760574241990|............. ++|2697|61|NEMA|dz4ojlpP85JMgDLZWkQJlG7aKYqQexEr62GXRV1y|3|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":7,"dusk_lux_sensor_value":7,"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|1760573633193|............... ++|2814|16|NEMA|wvKJdZML6mXP4DzWBAXxDPAjxNloa5g23Ve9Y1ry|2||1|1|1760573700564|............. ++|2818|66|NEMA|B5EoxeMVp4zwr8nqW0GBlpARjvD1PNamOGbLg63Z|2||1|1|1760573998238|............. ++|2811|90|NEMA|wvKJdZML6mXP4DzWBAXx8WAjxNloa5g23Ve9Y1ry|2||1|1|1760573993958|............. ++|2824|71|NEMA|JX1ObgmqGZ54DMyYL7aDY1kEVdve38WKRzwjNrQ9|2||1|1|1760573999133|............. ++|2825|89|NEMA|EjgWGnXaLy9opPOz20n4L4786BlYM3w1deVQvbKr|2||1|1|1760573999580|............. ++|2806|13|NEMA|eod9aRWLVl34Gx1Dn7VNDr72rz6qjgmpEXwQJN5Z|2||1|1|1760573687914|............. ++|2827|||m6EYyZoJ4gWexdjVPAR5mx7RDOq9wv2N5XzKGplr|2||1|1|1760574001257|............. ++|2828|72|NEMA|RvmwNz8QPblKp41GD7lKQjkJrLVYoBO92dMegn6W|2||1|1|1760574007454|............. ++|2830|85|NEMA|aw4eELG2DlPMdn1JW0BM8nAqQXOZRN3xB5yp8VKr|2||1|1|1760574009818|............. ++|2832|74|NEMA|3JjOWdylwgNLzxVab7NaYnkZ2vG64rq8PEB5QmDo|2||1|1|1760574011655|............. ++|2833|68|NEMA|JzwxZXOvDj1bVrN4nkW5XQA8qdyBl3MRKLpGPgaQ|2||1|1|1760574012134|............. ++|2834|69|NEMA|g9OxBZ5KRwNznlY6pAppQxAWXvjdEL4eGQobMDy2|2||1|1|1760574013667|............. ++|2809|15|NEMA|EjgWGnXaLy9opPOz20n4ea786BlYM3w1deVQvbKr|2||1|1|1760573693217|............. ++|2837|83|NEMA|d9x2V5LGYBzXp4mMRAOmMjkPloaqJwnQj6DgrNe3|2||1|1|1760574018810|............. ++|2838|82|.NEMA|K94XLav1glVRnyQ6r01PDzAme3YJwBxM5oOzdP2j|2||1|1|1760574019146|............. ++|2839|84|NEMA|B5EoxeMVp4zwr8nqW0GBqpARjvD1PNamOGbLg63Z|2||1|1|1760574019545|............. ++|2842|81|NEMA|gRoJEyXVx4qD9er287L4dv7wBzGldaPjLWQKm3Mv|2||1|1|1760574020184|............. ++|2846|76|NEMA|1JMYvnx2RzKEo4aWQ7DGX5kL8yZV3m9NBePXbrdj|2||1|1|1760574022580|............. ++|2911|88|NEMA|3a5oqJN1bgnx4Ol9dk89jB7ByE6jQ8mKDWMpGrLV|2||1|1|1760573773206|............. ++|3005|58|IP65|EjgWGnXaLy9opPOz20n4LV786BlYM3w1deVQvbKr|2||1|1|1760574009419|............. ++|3009|58/1|IP65|Z5KyJe9nEg1QNbWlX0w4PBkoDjBLdqzR83VGv624|2||1|1|1760574010473|............. ++|3010|59|IP65|1JMYvnx2RzKEo4aWQ7DGl5kL8yZV3m9NBePXbrdj|2||1|1|1760574010664|............. ++|3016|57|IP65|3JjOWdylwgNLzxVab7NalnkZ2vG64rq8PEB5QmDo|2||1|1|1760574063517|............. ++|3097|70|NEMA|OzNMgZ9n43qPbjXmy7zw1JA2DKdYvW5e6pxGRrVa|2||1|1|1760574073595|............. ++|3192|18|NEMA|PLBJzmK1r3Gynd6OW0gKDx0e5wV4vx9bDEqNgYR8|2||1|1|1760573820212|............. ++|3229|126|NEMA|gYbDLqlyZVoRerQpB72MXpkWJnwM5z24POKa8Exj|2||1|1|1760573822337|............. ++|3230|128|NEMA|nJL5lPMwBx23YpqRe0rpLv7damXvWVbOrD4gNzy8|2||1|1|1760573628849|............. ++|3239|127|NEMA|XMBbew5z4ELrZa2mRAd3YW78vPN6gy3DdVYlpKjq|2||1|1|1760573629536|............. ++|3538|59/1|IP65|JzwxZXOvDj1bVrN4nkW5RNA8qdyBl3MRKLpGPgaQ|2||1|1|1760573633417|............. ++|3555|83/1|IP65|gP1eOZVj3Q9lv5aDEk4EaR7rdpqW8yLm2BbKzJxM|2||1|1|1760573843404|............. ++|3934|17|NEMA|Nzp2OoJlqn6r1ZgvdA3BKL7abBwP5G4eE3RQmyxD|2||1|1|1760573647153|............. ++|4066|86|NEMA|ZmRwd93QL4gaezxEbAx2L9k1prn2XjlPvGyqJ6BO|2||1|1|1760573964473|............. ++|4144|79|IP65|Nzp2OoJlqn6r1ZgvdA3B3K7abBwP5G4eE3RQmyxD|2||1|1|1760573966773|............. ++|4308|78/1|IP65|OzNMgZ9n43qPbjXmy7zwzJA2DKdYvW5e6pxGRrVa|2||1|1|1760573873176|............. ++|4314|73/1|IP65|m6EYyZoJ4gWexdjVPARNexARDOq9wv2N5XzKGplr|2||1|1|1760573671767|............. ++|4360|75|NEMA|Z5KyJe9nEg1QNbWlX0w4QBkoDjBLdqzR83VGv624|2||1|1|1760573879294|............. ++|2584|77|NEMA|PjLblDgRBO6WQqnxmkJ1jr0Jv3ewZN4p5a89yKdY|2||1|1|1760574020599|............. ++|2600|73|NEMA|RO8rjaBDy21qPQJzW7omQ60pK3xmNleVZg9Ed4Gw|2||1|1|1760573626341|............. ++|2731|65|NEMA|wvKJdZML6mXP4DzWBAXx81AjxNloa5g23Ve9Y1ry|2||1|1|1760573964648|............. ++|3075|62|NEMA|d5xjWYMwEJon6rLlK7yEQm7qgV4DaOeNB9ZX3Gzb|2||1|1|1760574072956|............. ++|2787|14|NEMA|3a5oqJN1bgnx4Ol9dk895Q7ByE6jQ8mKDWMpGrLV|2||1|1|1760573677484|............. ++|3101|107|11-Repeater|PLBJzmK1r3Gynd6OW0gKQM0e5wV4vx9bDEqNgYR8|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":7,"dusk_lux_sensor_value":7,"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|1760574089727|............... ++|4027|20|NEMA|rDbQ84xzwgdqEoPm3kbE4y09anOZY1RXyBv2LVM6|3|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573648303|............. ++|4016|129|NEMA|E6Kg9oDnLWyzPRMva7vrEw7Jxp4VG58qO2w1lZYe|2||1|1|1760573858610|............. diff --git a/RVO15/databases/nodes_original/nodes_original.table b/RVO15/databases/nodes_original/nodes_original.table new file mode 100755 index 0000000..47e0801 --- /dev/null +++ b/RVO15/databases/nodes_original/nodes_original.table @@ -0,0 +1 @@ +[{"2835": "PLBJzmK1r3Gynd6OW0gKPM0e5wV4vx9bDEqNgYR8"}, {"2836": "eod9aRWLVl34Gx1Dn7VNBa72rz6qjgmpEXwQJN5Z"}, {"2852": "rDbQ84xzwgdqEoPm3kbEG309anOZY1RXyBv2LVM6"}, {"2861": "EjgWGnXaLy9opPOz20n4G4786BlYM3w1deVQvbKr"}, {"2862": "3a5oqJN1bgnx4Ol9dk89qB7ByE6jQ8mKDWMpGrLV"}, {"2866": "wvKJdZML6mXP4DzWBAXxGWAjxNloa5g23Ve9Y1ry"}, {"2874": "52dD6ZlV1QaOpRBmbAqGPgkKnGzWMLj4eJq38Pgo"}, {"3001": "o9vbeQlLMVg8j5dq4keLNb0NxZpEmnXzwYKO1ar2"}, {"3546": "apKVJBwOyrP35m2lv7KY950YXbeWNd64En9GxRqg"}, {"4146": "ZmRwd93QL4gaezxEbAx2LOk1prn2XjlPvGyqJ6BO"}, {"2795": "nJL5lPMwBx23YpqRe0rpx27damXvWVbOrD4gNzy8"}, {"2796": "gRoJEyXVx4qD9er287L4JQ7wBzGldaPjLWQKm3Mv"}, {"2799": "aw4eELG2DlPMdn1JW0BMJaAqQXOZRN3xB5yp8VKr"}, {"2801": "PjLblDgRBO6WQqnxmkJ1Jg0Jv3ewZN4p5a89yKdY"}, {"2802": "o9vbeQlLMVg8j5dq4keLmX0NxZpEmnXzwYKO1ar2"}, {"2803": "K94XLav1glVRnyQ6r01PKwAme3YJwBxM5oOzdP2j"}, {"2804": "ZmRwd93QL4gaezxEbAx2gVk1prn2XjlPvGyqJ6BO"}, {"2807": "ZmRwd93QL4gaezxEbAx2B9k1prn2XjlPvGyqJ6BO"}, {"2808": "roKgWqY95V3mXMRzyAjKGe0bLjexpJPvaGDBw826"}, {"2812": "52dD6ZlV1QaOpRBmbAqG6qkKnGzWMLj4eJq38Pgo"}, {"2815": "dz4ojlpP85JMgDLZWkQJDn7aKYqQexEr62GXRV1y"}, {"2821": "d9x2V5LGYBzXp4mMRAOmGvkPloaqJwnQj6DgrNe3"}, {"2826": "E6Kg9oDnLWyzPRMva7v5XbkJxp4VG58qO2w1lZYe"}, {"2829": "d5xjWYMwEJon6rLlK7yEqN7qgV4DaOeNB9ZX3Gzb"}, {"2831": "eod9aRWLVl34Gx1Dn7VNGa72rz6qjgmpEXwQJN5Z"}, {"2847": "XMBbew5z4ELrZa2mRAd3GO78vPN6gy3DdVYlpKjq"}, {"2848": "zdQO8GwxDqjRgP4137YVGaANyKlpem2nL65rvVJY"}, {"2849": "apKVJBwOyrP35m2lv7KYlv0YXbeWNd64En9GxRqg"}, {"2851": "E6Kg9oDnLWyzPRMva7v5PakJxp4VG58qO2w1lZYe"}, {"2854": "zrR51V2ajQ9ZLygPKkEMlJkYDq38xOJolENBXGnv"}, {"2856": "nJL5lPMwBx23YpqRe0rpPV7damXvWVbOrD4gNzy8"}, {"2858": "roKgWqY95V3mXMRzyAjKPD0bLjexpJPvaGDBw826"}, {"2859": "BaY3Xpy1EbKGjLq2O7mapp7rx8owgQz9P4dDJRmN"}, {"2863": "WlVJBygjDZMeKX3vnAMRlZ08NqdmG2x1Y69LQ4P5"}, {"2864": "o9vbeQlLMVg8j5dq4keLGX0NxZpEmnXzwYKO1ar2"}, {"2872": "DbQY6zyveZRwK5drV0Z8Gq7joE4XJM83N9xl2nWq"}, {"2873": "5dBNwRp9graYJxZn409Nb3klVov1b2QLPDqGm6XK"}, {"2901": "zrR51V2ajQ9ZLygPKkEM3JkYDq38xOJolENBXGnv"}, {"2906": "WlVJBygjDZMeKX3vnAMR2Z08NqdmG2x1Y69LQ4P5"}, {"2907": "zdQO8GwxDqjRgP4137YVBaANyKlpem2nL65rvVJY"}, {"2908": "5dBNwRp9graYJxZn409ND3klVov1b2QLPDqGm6XK"}, {"2853": "52dD6ZlV1QaOpRBmbAqGQgkKnGzWMLj4eJq38Pgo"}, {"2913": "BaY3Xpy1EbKGjLq2O7maQp7rx8owgQz9P4dDJRmN"}, {"2918": "ZmRwd93QL4gaezxEbAx2Q9k1prn2XjlPvGyqJ6BO"}, {"2919": "Nzp2OoJlqn6r1ZgvdA3BDd7abBwP5G4eE3RQmyxD"}, {"2981": "m6EYyZoJ4gWexdjVPAR5lx7RDOq9wv2N5XzKGplr"}, {"2984": "m6EYyZoJ4gWexdjVPAR5pw7RDOq9wv2N5XzKGplr"}, {"3006": "OzNMgZ9n43qPbjXmy7zwPJA2DKdYvW5e6pxGRrVa"}, {"3008": "3a5oqJN1bgnx4Ol9dk89jZ7ByE6jQ8mKDWMpGrLV"}, {"3012": "JX1ObgmqGZ54DMyYL7aDG1kEVdve38WKRzwjNrQ9"}, {"3014": "6lQGaY9RDywdVzObj0PaB8kPg4NBn3exEK51LWZq"}, {"3017": "pE5X8NQPaow6vlOZxk6a3j0q42ezGBMyWgDVjR3L"}, {"3020": "JzwxZXOvDj1bVrN4nkW5GQA8qdyBl3MRKLpGPgaQ"}, {"3021": "2O14VBzl8aDmWdNw3A59XlAGyZ5qLJoEMpj6R9ng"}, {"3027": "g9OxBZ5KRwNznlY6pAppaxAWXvjdEL4eGQobMDy2"}, {"3105": "52dD6ZlV1QaOpRBmbAqGLgkKnGzWMLj4eJq38Pgo"}, {"3105": "52dD6ZlV1QaOpRBmbAqGLgkKnGzWMLj4eJq38Pgo"}, {"3139": "Z5KyJe9nEg1QNbWlX0w4YDkoDjBLdqzR83VGv624"}, {"3396": "3JjOWdylwgNLzxVab7NaJ8kZ2vG64rq8PEB5QmDo"}, {"3400": "B5EoxeMVp4zwr8nqW0GBJYARjvD1PNamOGbLg63Z"}, {"3553": "eod9aRWLVl34Gx1Dn7VNBM72rz6qjgmpEXwQJN5Z"}, {"3556": "pE5X8NQPaow6vlOZxk6aog0q42ezGBMyWgDVjR3L"}, {"3557": "OzNMgZ9n43qPbjXmy7zwEaA2DKdYvW5e6pxGRrVa"}, {"3560": "gP1eOZVj3Q9lv5aDEk45lM7rdpqW8yLm2BbKzJxM"}, {"3656": "DbQY6zyveZRwK5drV0Z8qq7joE4XJM83N9xl2nWq"}, {"3859": "rDbQ84xzwgdqEoPm3kbEM309anOZY1RXyBv2LVM6"}, {"3740": "Nzp2OoJlqn6r1ZgvdA3B3d7abBwP5G4eE3RQmyxD"}, {"3926": "aw4eELG2DlPMdn1JW0BMEnAqQXOZRN3xB5yp8VKr"}, {"3950": "gYbDLqlyZVoRerQpB72MVjkWJnwM5z24POKa8Exj"}, {"4216": "g9OxBZ5KRwNznlY6pAppqEAWXvjdEL4eGQobMDy2"}, {"4303": "JzwxZXOvDj1bVrN4nkW58QA8qdyBl3MRKLpGPgaQ"}, {"4304": "6lQGaY9RDywdVzObj0Pal8kPg4NBn3exEK51LWZq"}, {"4306": "2O14VBzl8aDmWdNw3A59l9AGyZ5qLJoEMpj6R9ng"}, {"4309": "g9OxBZ5KRwNznlY6pAppvxAWXvjdEL4eGQobMDy2"}, {"4311": "m6EYyZoJ4gWexdjVPAR5Dx7RDOq9wv2N5XzKGplr"}, {"4313": "6lQGaY9RDywdVzObj0PaeOkPg4NBn3exEK51LWZq"}, {"4346": "K94XLav1glVRnyQ6r01PxzAme3YJwBxM5oOzdP2j"}, {"2705": "eod9aRWLVl34Gx1Dn7VNna72rz6qjgmpEXwQJN5Z"}, {"2708": "3a5oqJN1bgnx4Ol9dk89DB7ByE6jQ8mKDWMpGrLV"}, {"2709": "XMBbew5z4ELrZa2mRAd3EO78vPN6gy3DdVYlpKjq"}, {"2710": "gYbDLqlyZVoRerQpB72MDjkWJnwM5z24POKa8Exj"}, {"2711": "nJL5lPMwBx23YpqRe0rpQV7damXvWVbOrD4gNzy8"}, {"2712": "roKgWqY95V3mXMRzyAjKOD0bLjexpJPvaGDBw826"}, {"2713": "PjLblDgRBO6WQqnxmkJ1Gr0Jv3ewZN4p5a89yKdY"}, {"2719": "wvKJdZML6mXP4DzWBAXx3WAjxNloa5g23Ve9Y1ry"}, {"2721": "EjgWGnXaLy9opPOz20n4Q4786BlYM3w1deVQvbKr"}, {"2725": "RO8rjaBDy21qPQJzW7omP60pK3xmNleVZg9Ed4Gw"}, {"2727": "E6Kg9oDnLWyzPRMva7v5LakJxp4VG58qO2w1lZYe"}, {"2732": "rDbQ84xzwgdqEoPm3kbEd309anOZY1RXyBv2LVM6"}, {"2734": "PLBJzmK1r3Gynd6OW0gKEM0e5wV4vx9bDEqNgYR8"}, {"2735": "roKgWqY95V3mXMRzyAjKLD0bLjexpJPvaGDBw826"}, {"2738": "RvmwNz8QPblKp41GD7lKPjkJrLVYoBO92dMegn6W"}, {"2739": "gRoJEyXVx4qD9er287L4Dv7wBzGldaPjLWQKm3Mv"}, {"2781": "apKVJBwOyrP35m2lv7KYrv0YXbeWNd64En9GxRqg"}, {"2783": "2O14VBzl8aDmWdNw3A59DlAGyZ5qLJoEMpj6R9ng"}, {"2784": "Z5KyJe9nEg1QNbWlX0w43zkoDjBLdqzR83VGv624"}, {"2788": "1JMYvnx2RzKEo4aWQ7DGJvkL8yZV3m9NBePXbrdj"}, {"2791": "gP1eOZVj3Q9lv5aDEk45DZ7rdpqW8yLm2BbKzJxM"}, {"2794": "pE5X8NQPaow6vlOZxk6aDj0q42ezGBMyWgDVjR3L"}, {"2843": "dz4ojlpP85JMgDLZWkQJEG7aKYqQexEr62GXRV1y"}, {"2844": "d5xjWYMwEJon6rLlK7yEzm7qgV4DaOeNB9ZX3Gzb"}, {"2697": "dz4ojlpP85JMgDLZWkQJlG7aKYqQexEr62GXRV1y"}, {"2814": "wvKJdZML6mXP4DzWBAXxDPAjxNloa5g23Ve9Y1ry"}, {"2818": "B5EoxeMVp4zwr8nqW0GBlpARjvD1PNamOGbLg63Z"}, {"2811": "wvKJdZML6mXP4DzWBAXx8WAjxNloa5g23Ve9Y1ry"}, {"2824": "JX1ObgmqGZ54DMyYL7aDY1kEVdve38WKRzwjNrQ9"}, {"2825": "EjgWGnXaLy9opPOz20n4L4786BlYM3w1deVQvbKr"}, {"2806": "eod9aRWLVl34Gx1Dn7VNDr72rz6qjgmpEXwQJN5Z"}, {"2827": "m6EYyZoJ4gWexdjVPAR5mx7RDOq9wv2N5XzKGplr"}, {"2828": "RvmwNz8QPblKp41GD7lKQjkJrLVYoBO92dMegn6W"}, {"2830": "aw4eELG2DlPMdn1JW0BM8nAqQXOZRN3xB5yp8VKr"}, {"2832": "3JjOWdylwgNLzxVab7NaYnkZ2vG64rq8PEB5QmDo"}, {"2833": "JzwxZXOvDj1bVrN4nkW5XQA8qdyBl3MRKLpGPgaQ"}, {"2834": "g9OxBZ5KRwNznlY6pAppQxAWXvjdEL4eGQobMDy2"}, {"2809": "EjgWGnXaLy9opPOz20n4ea786BlYM3w1deVQvbKr"}, {"2837": "d9x2V5LGYBzXp4mMRAOmMjkPloaqJwnQj6DgrNe3"}, {"2838": "K94XLav1glVRnyQ6r01PDzAme3YJwBxM5oOzdP2j"}, {"2839": "B5EoxeMVp4zwr8nqW0GBqpARjvD1PNamOGbLg63Z"}, {"2842": "gRoJEyXVx4qD9er287L4dv7wBzGldaPjLWQKm3Mv"}, {"2846": "1JMYvnx2RzKEo4aWQ7DGX5kL8yZV3m9NBePXbrdj"}, {"2911": "3a5oqJN1bgnx4Ol9dk89jB7ByE6jQ8mKDWMpGrLV"}, {"3005": "EjgWGnXaLy9opPOz20n4LV786BlYM3w1deVQvbKr"}, {"3009": "Z5KyJe9nEg1QNbWlX0w4PBkoDjBLdqzR83VGv624"}, {"3010": "1JMYvnx2RzKEo4aWQ7DGl5kL8yZV3m9NBePXbrdj"}, {"3016": "3JjOWdylwgNLzxVab7NalnkZ2vG64rq8PEB5QmDo"}, {"3097": "OzNMgZ9n43qPbjXmy7zw1JA2DKdYvW5e6pxGRrVa"}, {"3192": "PLBJzmK1r3Gynd6OW0gKDx0e5wV4vx9bDEqNgYR8"}, {"3229": "gYbDLqlyZVoRerQpB72MXpkWJnwM5z24POKa8Exj"}, {"3230": "nJL5lPMwBx23YpqRe0rpLv7damXvWVbOrD4gNzy8"}, {"3239": "XMBbew5z4ELrZa2mRAd3YW78vPN6gy3DdVYlpKjq"}, {"3538": "JzwxZXOvDj1bVrN4nkW5RNA8qdyBl3MRKLpGPgaQ"}, {"3555": "gP1eOZVj3Q9lv5aDEk4EaR7rdpqW8yLm2BbKzJxM"}, {"3934": "Nzp2OoJlqn6r1ZgvdA3BKL7abBwP5G4eE3RQmyxD"}, {"4066": "ZmRwd93QL4gaezxEbAx2L9k1prn2XjlPvGyqJ6BO"}, {"4144": "Nzp2OoJlqn6r1ZgvdA3B3K7abBwP5G4eE3RQmyxD"}, {"4308": "OzNMgZ9n43qPbjXmy7zwzJA2DKdYvW5e6pxGRrVa"}, {"4314": "m6EYyZoJ4gWexdjVPARNexARDOq9wv2N5XzKGplr"}, {"4360": "Z5KyJe9nEg1QNbWlX0w4QBkoDjBLdqzR83VGv624"}, {"2584": "PjLblDgRBO6WQqnxmkJ1jr0Jv3ewZN4p5a89yKdY"}, {"2600": "RO8rjaBDy21qPQJzW7omQ60pK3xmNleVZg9Ed4Gw"}, {"2731": "wvKJdZML6mXP4DzWBAXx81AjxNloa5g23Ve9Y1ry"}, {"3075": "d5xjWYMwEJon6rLlK7yEQm7qgV4DaOeNB9ZX3Gzb"}, {"2787": "3a5oqJN1bgnx4Ol9dk895Q7ByE6jQ8mKDWMpGrLV"}, {"3101": "PLBJzmK1r3Gynd6OW0gKQM0e5wV4vx9bDEqNgYR8"}, {"4027": "rDbQ84xzwgdqEoPm3kbE4y09anOZY1RXyBv2LVM6"}, {"4016": "E6Kg9oDnLWyzPRMva7vrEw7Jxp4VG58qO2w1lZYe"}] \ No newline at end of file diff --git a/RVO15/databases/notifications.table b/RVO15/databases/notifications.table new file mode 100755 index 0000000..f7c96cb --- /dev/null +++ b/RVO15/databases/notifications.table @@ -0,0 +1,41 @@ +key:string|weight:string|sk:string|en:string ++|switching_profile_point_applied_to_line|INFORMATIONAL|Aplikovaný bod spínacieho profilu na línií č. ${line} : ${value}|Switching profile point applied to line no. ${line} : ${value}|............... ++|dusk_has_occured|INFORMATIONAL|Nastal súmrak: ${value}|Dusk has occured: ${value}|............... ++|dawn_has_occured|INFORMATIONAL|Nastal úsvit: ${value}|Dawn has occured: ${value}|............... ++|dimming_profile_was_successfully_received_by_node|NOTICE|Stmievací profil bol úspešne prijatý nodom č. ${node}|Dimming profile was successfully received by node no. ${node}|............... ++|master_node_is_responding_again|NOTICE|Master node začal znovu odpovedať|Master node is responding again|............... ++|command_was_sent_from_terminal_interface|DEBUG|Z terminálu bol odoslaný príkaz|A command was sent from terminal interface|............... ++|master_node_is_not_responding|ALERT|Master node neodpovedá|Master node is not responding|............... ++|configuration_of_dimming_profile_to_node_failed|ALERT|Konfigurácia stmievacieho profilu pre node č. ${node} zlyhala|Configuration of dimming profile to node no. ${node} has failed|............... ++|circuit_breaker_was_turned_on_line|NOTICE|Zapnutie ističa na línii č. ${line}|Circuit breaker was turned on - line no. ${line}|............... ++|circuit_breaker_was_turned_off_line|ERROR|Vypnutie ističa na línií č. ${line}|Circuit breaker was turned off - line no. ${line}|............... ++|dimming_profile_was_processed_for_node|INFORMATIONAL|Stmievací profil bol spracovaný pre node č. ${node}|Dimming profile was processed for node no. ${node}|............... ++|switching_profile_was_processed_for_line|INFORMATIONAL|Spínací profil bol spracovaný pre líniu č. ${line}|Switching profile was processed for line no. ${line}|............... ++|thermometer_is_not_responding|WARNING|Teplomer neodpovedá|Thermometer is not responding|............... ++|thermometer_is_responding_again|NOTICE|Teplomer znovu odpovedá|Thermometer is responding again|............... ++|thermometer_sends_invalid_data|WARNING|Teplomer posiela neplatné hodnoty|Thermometer sends invalid data|............... ++|main_switch_has_been_turned_off|CRITICAL|Hlavný vypínač bol vypnutý|Main switch has been turned off|............... ++|main_switch_has_been_turned_on|NOTICE|Hlavný vypínač bol zapnutý|Main switch has been turned on|............... ++|power_supply_has_disconnected_input|ALERT|Napájací zdroj nemá napätie na vstupe|Power supply has disconnected input|............... ++|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_main_open|NOTICE|Hlavné dvere boli otvorené|Main door has been opened|............... ++|door_em_open|NOTICE|Dvere silovej časti boli otvorené|Power door has been opened|............... ++|door_main_open_without_permission|WARNING|Hlavné dvere boli otvorené bez povolenia - zapnutá siréna|Main door has been opened without permission - alarm is on|............... ++|door_em_open_without_permission|WARNING|Dvere silovej časti boli otvorené bez povolenia|Power door has been opened without permission|............... ++|door_main_close|NOTICE|Hlavné dvere boli zatvorené|Main door has been closed|............... ++|door_em_close|NOTICE|Dvere silovej časti boli zatvorené|Power door has been closed|............... ++|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|............... ++|electrometer_ok|NOTICE|Elektromer znovu odpovedá|Electrometer is responding again|............... ++|no_voltage_on_phase|CRITICAL|Na fáze č. ${phase} nie je napätie|No voltage detected on phase no. ${phase}|............... ++|voltage_on_phase_restored|NOTICE|Napätie na fáze č. ${phase} bolo obnovené|Voltage on phase no. ${phase} has been restored|............... ++|flow_start|NOTICE|FLOW bol spustený|FLOW has been started |............... ++|twilight_sensor_nok|ERROR|Sensor súmraku neodpovedá|Twilight sensor is not responding|............... ++|twilight_sensor_ok|NOTICE|Sensor súmraku znovu odpovedá|Twilight sensor is responding again|............... ++|lamps_have_turned_on|NOTICE|Lampy sa zapli|Lamps have turned on|............... ++|lamps_have_turned_off|NOTICE|Lampy sa vypli|Lamps have turned off|............... ++|flow_restart|NOTICE|FLOW bol reštartovaný|FLOW has been restarted|............... ++|nodes_db_changed|NOTICE|Zmena v node databáze|Node db has changed|............... diff --git a/RVO15/databases/pins.table b/RVO15/databases/pins.table new file mode 100755 index 0000000..0eb3d05 --- /dev/null +++ b/RVO15/databases/pins.table @@ -0,0 +1,14 @@ +pin:string|type:string|line:number +*|input1_01|door_condition|0|........... +*|input1_02|rotary_switch_state|0|........... +*|input1_03|rotary_switch_state|0|........... +*|input1_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/RVO15/databases/relays.table b/RVO15/databases/relays.table new file mode 100755 index 0000000..c0c2cbf --- /dev/null +++ b/RVO15/databases/relays.table @@ -0,0 +1,5 @@ +line:number|tbname:string|contactor:number|profile:string ++|0|zrR51V2ajQ9ZLygPKkEMDakYDq38xOJolENBXGnv|1||........... ++|1|BaY3Xpy1EbKGjLq2O7maOw7rx8owgQz9P4dDJRmN|9|{"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|DbQY6zyveZRwK5drV0Z8wJ7joE4XJM83N9xl2nWq|9|{"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|apKVJBwOyrP35m2lv7KY610YXbeWNd64En9GxRqg|9|{"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}|.................................................................................................................. diff --git a/RVO15/databases/settings.table b/RVO15/databases/settings.table new file mode 100755 index 0000000..8179979 --- /dev/null +++ b/RVO15/databases/settings.table @@ -0,0 +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|project_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|cloud_topic:string|has_main_switch:boolean|daily_report:boolean|send_changed_node_numbers:boolean ++|rvo_senica_15_ip114|en|28.E3829C0E0000|48.70826502|17.28455203|192.168.252.1|rvo_senica_15_ip114|GsmIWDUDcBNX3TRtKVXD|1883|0|51|unipi|ttyUSB0|1|20|5|6|3|u114|0|1|1|................................................... diff --git a/RVO15/databases/tbdata.nosql b/RVO15/databases/tbdata.nosql new file mode 100755 index 0000000..67a5d66 --- /dev/null +++ b/RVO15/databases/tbdata.nosql @@ -0,0 +1,4 @@ +-"zrR51V2ajQ9ZLygPKkEMDakYDq38xOJolENBXGnv":[{"ts":1760521105422,"values":{"_event":{"type":"notice","status":"new","source":{"func":"modbus_reader","component":"1699965957410","component_name":"Modbus reader","edge":"zrR51V2ajQ9ZLygPKkEMDakYDq38xOJolENBXGnv"},"message":{"sk":"rvo_senica_15_ip114: FLOW bol reštartovaný","en":"rvo_senica_15_ip114: FLOW has been restarted"},"message_data":""}}}],"id":"3000158001jn71b"} +-"zrR51V2ajQ9ZLygPKkEMDakYDq38xOJolENBXGnv":[{"ts":1760521105515,"values":{"edge_fw_version":"2025-10-08","maintenance_mode":false}}],"id":"3000158002jn70b"} +-"zrR51V2ajQ9ZLygPKkEMDakYDq38xOJolENBXGnv":[{"ts":1760521105529,"values":{"statecode":2,"power_mode":"Automatic"}}],"id":"3000158004jn70b"} +-"zrR51V2ajQ9ZLygPKkEMDakYDq38xOJolENBXGnv":[{"ts":1760521105581,"values":{"_event":{"type":"notice","status":"new","source":{"func":"rsPort.open()","component":"1699963668903","component_name":"DIDO_Controller","edge":"zrR51V2ajQ9ZLygPKkEMDakYDq38xOJolENBXGnv"},"message":{"sk":"rvo_senica_15_ip114: FLOW bol spustený","en":"rvo_senica_15_ip114: FLOW has been started "},"message_data":""}}}],"id":"3000158006jn70b"} diff --git a/RVO15/databases/tbdatacloud.nosql b/RVO15/databases/tbdatacloud.nosql new file mode 100755 index 0000000..af3eab9 --- /dev/null +++ b/RVO15/databases/tbdatacloud.nosql @@ -0,0 +1,3 @@ +-"zrR51V2ajQ9ZLygPKkEMDakYDq38xOJolENBXGnv":[{"ts":1760521105515,"values":{"edge_fw_version":"2025-10-08","maintenance_mode":false}}],"id":"3000158003jn71b"} +-"zrR51V2ajQ9ZLygPKkEMDakYDq38xOJolENBXGnv":[{"ts":1760521105529,"values":{"statecode":2,"power_mode":"Automatic"}}],"id":"3000158005jn71b"} +-"zrR51V2ajQ9ZLygPKkEMDakYDq38xOJolENBXGnv":[{"ts":1760521105581,"values":{"_event":{"type":"notice","status":"new","source":{"func":"rsPort.open()","component":"1699963668903","component_name":"DIDO_Controller","edge":"zrR51V2ajQ9ZLygPKkEMDakYDq38xOJolENBXGnv"},"message":{"sk":"rvo_senica_15_ip114: FLOW bol spustený","en":"rvo_senica_15_ip114: FLOW has been started "},"message_data":""}}}],"id":"3000158007jn71b"} diff --git a/RVO15/databases/total_energy.js b/RVO15/databases/total_energy.js new file mode 100755 index 0000000..dde340e --- /dev/null +++ b/RVO15/databases/total_energy.js @@ -0,0 +1,38 @@ +//key is rvo_number, value is max energy when lamps are on +const total_energy = { + 1: 580, + 2: 1100, + 3: 3700, + 4: 4100, + 7: 360, + 12: 1700, + 13: 5400, + 14: 440, + 15: 6100, + 16: 4800, + 20: 1600, + 21: 1000, + 22: 2600, + 23: 1000, + 25: 2600, + 33: 240, + 34: 4000, + 35: 2700, + 36: 820, + 37: 1400, + 35: 3500, + 39: 1170, + 41: 740, + 42: 660, + 43: 4900, + 45: 930, + 46: 700, + 47: 1100, + 48: 1500, + 50: 3200, + 53: 1250, + 55: 1000, + 56: 5500 +} + +module.exports = total_energy; diff --git a/RVO15/debug.js b/RVO15/debug.js new file mode 100755 index 0000000..9818194 --- /dev/null +++ b/RVO15/debug.js @@ -0,0 +1,16 @@ +// =================================================== +// FOR DEVELOPMENT +// Total.js - framework for Node.js platform +// https://www.totaljs.com +// =================================================== + +const options = {}; + +// options.ip = '127.0.0.1'; +// options.port = parseInt(process.argv[2]); +// options.config = { name: 'Total.js' }; +// options.sleep = 3000; +// options.inspector = 9229; +// options.watch = ['private']; + +require('total.js/debug')(options); \ No newline at end of file diff --git a/RVO15/err.txt b/RVO15/err.txt new file mode 100755 index 0000000..efb31ff --- /dev/null +++ b/RVO15/err.txt @@ -0,0 +1,33 @@ +[2025-09-23T14:06:08.491] [ERROR] errLogs - uncaughtException: Cannot read property 'getHours' of undefined +[2025-09-23T14:06:08.493] [ERROR] errLogs - TypeError: Cannot read property 'getHours' of undefined + at Timeout.emptyReportToSend [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:06:08.494] [ERROR] errLogs - uncaughtException: Cannot read property 'getHours' of undefined +[2025-09-23T14:06:08.495] [ERROR] errLogs - TypeError: Cannot read property 'getHours' of undefined + at Timeout.emptyReportToSend [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:06:08.503] [ERROR] errLogs - uncaughtException: Cannot read property 'getHours' of undefined +[2025-09-23T14:06:08.504] [ERROR] errLogs - TypeError: Cannot read property 'getHours' of undefined + at Timeout.emptyReportToSend [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:06:14.273] [ERROR] errLogs - uncaughtException: date.getHours is not a function +[2025-09-23T14:06:14.273] [ERROR] errLogs - TypeError: date.getHours is not a function + at emptyReportToSend (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at Timeout.dailyReportCheck [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1351:5) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:06:14.274] [ERROR] errLogs - uncaughtException: date.getHours is not a function +[2025-09-23T14:06:14.275] [ERROR] errLogs - TypeError: date.getHours is not a function + at emptyReportToSend (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at Timeout.dailyReportCheck [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1351:5) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:06:14.280] [ERROR] errLogs - uncaughtException: date.getHours is not a function +[2025-09-23T14:06:14.281] [ERROR] errLogs - TypeError: date.getHours is not a function + at emptyReportToSend (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at Timeout.dailyReportCheck [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1351:5) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) diff --git a/RVO15/flow/cloudmqttconnect.js b/RVO15/flow/cloudmqttconnect.js new file mode 100755 index 0000000..b03491f --- /dev/null +++ b/RVO15/flow/cloudmqttconnect.js @@ -0,0 +1,357 @@ +exports.id = 'cloudmqttconnect'; +exports.title = 'Cloud connect mqtt'; +exports.group = 'MQTT'; +exports.color = '#888600'; +exports.version = '1.0.2'; +exports.icon = 'sign-out'; +exports.input = 2; +exports.output = 2; +exports.options = { host: 'tb-stage.worksys.io', port: 1883, clientid: "", username: "" }; + +exports.html = `
+
+
+
Hostname or IP address (if not empty - setting will override db setting)
+
+
+
Port
+
+
+
+
+
@(Client id)
+
+
+
topic
+
+
+
`; + + + +const { promisifyBuilder } = require('./helper/db_helper'); +const fs = require('fs'); +const mqtt = require('mqtt'); +const nosql = NOSQL('tbdatacloud'); + +const SEND_TO = { + debug: 0, + rpcCall: 1, +} + +//CONFIG +let saveTelemetryOnError = true;//backup_on_failure overrides this value +//------------------------ + +const noSqlFileSizeLimit = 4194304;//use 5MB - 4194304 +let insertNoSqlCounter = 0; +let insertBackupNoSqlCounter = 0; +let processingData = false; + +let backup_on_failure = true;//== saveTelemetryOnError - create backup client send failure +let restore_from_backup = 50; //how many rows process at once? +let restore_backup_wait = 3;//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; + + +exports.install = function(instance) { + + var client; + var opts; + var clientReady = false; + + let o = {}; //options + + function main() { + loadSettings(); + } + + //set opts according to db settings + function loadSettings() { + + o = instance.options; + if (!o.topic) o.topic = FLOW.GLOBALS.settings.cloud_topic; + + opts = { + host: o.host, + port: o.port, + clientId: o.clientid, + username: o.username, + rejectUnauthorized: false, + resubscribe: false + }; + + console.log("wsmqttpublich -> loadSettings from instance.options", o); + + if (!o.topic) { + instance.status("Not configured", "white"); + console.log("Cloud mqtt connect: no topic selected"); + return; + } + + connectToTbServer(); + } + + function connectToTbServer() { + var url = "mqtt://" + opts.host + ":" + opts.port; + console.log("MQTT URL: ", url); + + client = mqtt.connect(url, opts); + + client.on('connect', function() { + client.subscribe(`${o.topic}_backward`, (err) => { + if (!err) { + console.log("MQTT subscribed"); + } + }); + instance.status("Connected", "green"); + clientReady = true; + sendClientError = true; + }); + + client.on('reconnect', function() { + instance.status("Reconnecting", "yellow"); + clientReady = false; + }); + + client.on('message', function(topic, message) { + // message is type of buffer + message = message.toString(); + if (message[0] === '{') { + TRY(function() { + + message = JSON.parse(message); + if (message.hasOwnProperty("device") && message.hasOwnProperty("data") && message.data.hasOwnProperty("id")) { + client.publish(`${o.topic}_forward`, `{"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 } }); + } + + }, () => instance.debug('MQTT: Error parsing data', message)); + } + + instance.send(SEND_TO.rpcCall, { "topic": o.topic, "content": message }); + }); + + client.on('close', function() { + clientReady = false; + + instance.status("Disconnected", "red"); + instance.send(SEND_TO.debug, { "message": "Client CLOSE signal received !" }); + }); + + client.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) { + console.log('MQTT client error', err); + sendClientError = false; + } + clientReady = false; + }); + + } + + + instance.on('0', function(data) { + + if (clientReady) { + //do we have some data in backup file? if any, process data from database + if (saveTelemetryOnError) { + //read telemetry data and send back to server + if (!processingData) processDataFromDatabase(); + } + + let stringifiedJson = JSON.stringify(data.data) + client.publish(`${o.topic}_forward`, stringifiedJson, { qos: 1 }); + } + 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 (saveTelemetryOnError && o.topic) { + //create new file from tbdata.nosql, if file size exceeds given limit, and clear tbdata.nosql + makeBackupFromDbFile(); + + //write to tb + data.data.id = UID(); + nosql.insert(data.data); + } + } + }); + + instance.on("1", _ => { + main(); + }) + + instance.close = function(done) { + if (clientReady) { + client.end(); + } + }; + + + function getDbBackupFileCounter(type) { + var files = fs.readdirSync(__dirname + "/../databases"); + + let counter = 0; + for (var i = 0; i < files.length; i++) { + + if (files[i] == "tbdatacloud.nosql") continue; + + if (files[i].endsWith(".nosql")) { + + let pos = files[i].indexOf("."); + if (pos > -1) { + + let fileCounter = counter; + let firstDigit = files[i].slice(0, pos); + + fileCounter = parseInt(firstDigit); + if (isNaN(fileCounter)) fileCounter = 0; + //console.log("getDbBackupFileCounter digit:", files[i], firstDigit, fileCounter, isNaN(fileCounter), type); + + if (type == "max") { + if (fileCounter > counter) { + counter = fileCounter; + } + } + else if (type == "min") { + if (counter == 0) counter = fileCounter; + + if (fileCounter < counter) { + counter = fileCounter; + } + } + } + } + + } + + if (type == "max") counter++; + + return counter; + } + + const makeBackupFromDbFile = async () => { + + if (!saveTelemetryOnError) return; + + //to avoid large file: tbdata.nosql + + //init value is 0! + if (insertNoSqlCounter > 0) { + --insertNoSqlCounter; + return; + } + + insertNoSqlCounter = 100; + + let source = __dirname + "/../databases/tbdatacloud.nosql"; + + var stats = fs.statSync(source); + var fileSizeInBytes = stats.size; + + if (fileSizeInBytes > noSqlFileSizeLimit) { + + let counter = 1; + counter = getDbBackupFileCounter("max"); + + let destination = __dirname + "/../databases/" + counter + "." + "tbdatacloud.nosql"; + + //make backup file + fs.copyFileSync(source, destination); + //fs.renameSync(p, p + "." + counter); + + //clear tbdata.nosql + fs.writeFileSync(source, ""); + fs.truncateSync(source, 0); + + } + } + + const processDataFromDatabase = async () => { + + if (restore_from_backup <= 0) return; + + //calculate diff + const now = new Date(); + let currentTime = now.getTime(); + let diff = currentTime - lastRestoreTime; + + if ((diff / 1000) < restore_backup_wait) { + //console.log("*********restore_backup_wait", diff, restore_backup_wait); + return; + } + + processingData = true; + + //get filename to process + let counter = getDbBackupFileCounter("min"); + + //we have some backup files + let dataBase = 'tbdata'; + + var nosql; + if (counter == 0) dataBase = 'tbdatacloud'; + else dataBase = counter + "." + 'tbdatacloud'; + + nosql = NOSQL(dataBase); + + //select all data - use limit restore_from_backup + let records = await promisifyBuilder(nosql.find().take(restore_from_backup)); + + for (let i = 0; i < records.length; i++) { + if (clientReady) { + + let item = records[i]; + let id = item.id; + + if (id !== undefined) { + //console.log("------------processDataFromDatabase - remove", id, dataBase, i); + + try { + + let message = JSON.parse(JSON.stringify(item)); + delete message.id; + client.publish(`${o.topic}_forward`, JSON.stringify(message), { qos: 1 }); + + //remove from database + await promisifyBuilder(nosql.remove().where("id", id)); + + } catch (error) { + //process error + console.log("processDataFromDatabase", error); + } + + } + + } + else { + processingData = false; + return; + } + } + + if (records.length > 0) { + //clean backup file + if (counter > 0) nosql.clean(); + } + + //no data in db, remove + if (records.length == 0) { + if (counter > 0) nosql.drop(); + } + + const d = new Date(); + lastRestoreTime = d.getTime(); + + processingData = false; + + } + + instance.on('options', main); + +}; diff --git a/RVO15/flow/cmd_manager.js b/RVO15/flow/cmd_manager.js new file mode 100755 index 0000000..25912df --- /dev/null +++ b/RVO15/flow/cmd_manager.js @@ -0,0 +1,3071 @@ +exports.id = 'cmd_manager'; +exports.title = 'CMD Manager'; +exports.group = 'Worksys'; +exports.color = '#5D9CEC'; +exports.version = '0.0.3'; +exports.output = ['red', 'blue', 'yellow', 'blue', 'white', 'green']; +exports.input = 3; +exports.icon = 'cloud-upload'; + +exports.html = ` +
+
+
+
RPC - run RPC calls

+
+
+
@(User)
+
+
+
@(Password)
+
+
+
@(My edge)
+
+
+
+`; +exports.readme = `Manager for CMD calls`; + + +exports.install = function(instance) { + + 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, isEmptyObject, emptyJsObject, writeToFile, addToArrayIfUnique } = require('./helper/utils'); + const bitwise = require('bitwise'); + + var SunCalc = require('./helper/suncalc'); + const DataToTbHandler = require('./helper/DataToTbHandler'); + const errorHandler = require('./helper/ErrorToServiceHandler'); + const { sendNotification } = require('./helper/notification_reporter'); + const process = require('process'); + const { errLogger, logger, monitor } = require('./helper/logger'); + + //for accelerometer purposes + const { naklony } = require("../databases/accelerometer_db"); + + const dbNodes = TABLE("nodes"); + const dbRelays = TABLE("relays"); + + let GLOBALS; + let SETTINGS; + let rsPort; + let tbHandler; + + // runTasks intervals + const SHORT_INTERVAL = 30; + const LONG_INTERVAL = 300; + + //send data to following instances: + const SEND_TO = { + debug: 0, + tb: 1, + http_response: 2, + dido_controller: 3, + infoSender: 4, + dailyReport: 5 + } + + 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 + } + + 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 sendNodeReadout = null; // interval for sending agregate data from node + + 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["1"] = minutes; // dimming + priorities["76"] = minutes; // power + + minutes = 5; + priorities["75"] = minutes; // current + priorities["79"] = minutes; // energy + priorities["87"] = minutes; // aktualny cas + //priorities["84"] = minutes; //accelerometer + + minutes = 10; + priorities["74"] = minutes; // voltage + priorities["77"] = minutes; // power factor + priorities["78"] = minutes; // frequency + + minutes = 60; + priorities["0"] = minutes; // statecode + priorities["6"] = minutes; // dusk + priorities["7"] = minutes; // dawn + priorities["8"] = minutes; // profile + + minutes = 60 * 24; + priorities["89"] = minutes; // verzia fw + priorities["80"] = minutes; // lifetime + + //prikazy kt sa budu spustat na dany node - see config.js in terminal-oms.app. (1 - dimming) + let listOfCommands = [0, 1, 6, 7, 8, 74, 75, 76, 77, 78, 79, 80, 87, 89]; + + 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; + + // holds dusk, dawn (and more) values + let sunCalcResult; + + //helper container for counting resolved group of commands (commands related to set profile) + let cmdCounter = {};//key is node, value is counter + + //TODO: is this set working?? According to previous checks, sets do not work + //if sending of profile to node fails, we send notification and push node into set, so we do not send notification twice + const nodeProfileSendFail = new Set(); + + //we expect to get current temperature in Senica from senica-prod01 + let temperatureInSenica = null; + let accelerometerInterval = null; + + //NOTE: daily reports senica: + //rvo_is_on status, we monitor all nodes - if true, power and dimming should be not 0, if false, 24/7 nodes should be 0, other rvo should not respond + let rvo_is_on; + let previous_rvo_is_on_value; + let handleDailyReport; //setInterval for dailyReportHandler function + let dailyReport = {}; //data needed for daily report + let reportToSend = {}; //final report which we send to cloud + let breakerCounter = null; // status of breakers after flow starts is not in report + let rvoPeriod; // interval of checking dusk dawn and if rvo_is_on + let initialReportStatus = false; + + const DAILY_REPORT_HANDLER_TIME = 3_600_000; + const SET_SUNCALC_RESULT_TIME = 3_600_000; + const SET_RVO_PERIOD_TIME = 300_000; + const ADD_NODE_TO_REPORT_TIME = 3_600_000; + + //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); + + let now = new Date(); + console.log("Cmd-mngr installed", now.toLocaleString("sk-SK")); + + sunCalcResult = calculateDuskDawn(); + + handleRsPort(); + + customTasksInterval = setInterval(reportEdgeDateTimeAndNumberOfLuminaires, 120_000); + setTimeout(reportEdgeDateTimeAndNumberOfLuminaires, 4000); + + //dailyReport related + emptyReportToSend(); + breakerCounter = Object.keys(relaysData).length - 1; // we get number of lines (breakers) except of line 0 + rvoPeriod = setInterval(setRvoPeriod, SET_RVO_PERIOD_TIME); + setTimeout(setRvoPeriod, 3000); + setInterval(setSunCalcResult, SET_SUNCALC_RESULT_TIME); + handleDailyReport = setInterval(dailyReportHandler, DAILY_REPORT_HANDLER_TIME); + + + setCorrectTime = setInterval(setCorrectPlcTimeOnceADay, 60000 * 60); // 1 hour + setCorrectPlcTimeOnceADay(); + + sendNodeReadout = setInterval(sendNodesData, 150_000); + accelerometerInterval = setInterval(accelerometerData, 60000 * 30); //30 min + } + + + 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" + //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 + // if node regular readout does not respond, we repeat request + params.repeatCounter = 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-mngr: 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.byte4 = 96; + params.recipient = 1; + params.register = 8; + params.rw = 1;//write + params.timestamp = timestamp; + 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.byte4 = 96; + params.recipient = 1; + params.register = 8; + params.rw = 1;//write + params.timestamp = timestamp; + 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). + */ + + 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.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.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 + { + + logger.debug("processNodeProfile: Threshold lux level for DUSK/DAWN", node); + + let params = getParams(); + params.type = "set_node_profile"; + params.address = node; + params.register = 96; + params.recipient = 1; + params.rw = 1;//write + params.timestamp = timestamp; + 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(); + params.type = "set_node_profile"; + params.address = node; + params.register = 97; + params.recipient = 1; + params.rw = 1;//write + params.timestamp = timestamp; + 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.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); + + 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); + + console.log("proces profile finished *********************") + } + + + 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; + }); + } + + + 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) { + for (let k in nodesData) { + 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`); + } + } + } + + + function loadRelaysData(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 (value.contactor == 1) processAllNodeProfilesOnLine(value.line); + } + } + + + function reportOnlineNodeStatus(line) { + //Po zapnutí línie broadcastovo aktualizovať predtým čas a o 3 sek neskor - status, brightness + + logger.debug("Cmd-mngr: ----->reportOnlineNodeStatus for line", line); + + const d = new Date(); + + // broadcast actual time + let params = getParams(); + params.address = 0xffffffff;//Broadcast + params.byte1 = d.getHours(); + params.byte2 = d.getMinutes(); + params.recipient = 2;//2 broadcast, address = 0 + params.register = 87;//Actual time + params.rw = 1;//write + params.type = "node-onetime-write"; + params.timestamp = d.getTime() + 30000; + params.info = "run broadcast: Actual time"; + //params.debug = true; + + tasks.push(params); + + let sec = 3; + setTimeout(function() { + //Po zapnutí línie - spraviť hromadný refresh stavu práve zapnutých svietidiel + + let time = Date.now(); + + for (let k in nodesData) { + + //potrebujem nody k danej linii + 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].node_status_before_offline === true || nodesData[k].status === true) { + status = "OK"; + nodesData[k].time_of_last_communication = time; + } + + nodesData[k].readout.status = status; + + updateNodeStatus(k, status === "OK" ? true : false); + if (nodesData[k].hasOwnProperty("node_status_before_offline")) delete nodesData[k].node_status_before_offline; + sendTelemetry({ status: status }, tbname, time); + + //vyreportovanie dimming, current, input power pre liniu pre vsetky nody + //Prud + { + let params = getParams(); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 75;//prud + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = time + 4000; + params.info = 'read current'; + //params.debug = true; + tasks.push(params); + } + + //vykon + { + let params = getParams(); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 76;//výkon + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = time + 4100; + params.info = 'read power'; + //params.debug = true; + + tasks.push(params); + } + //dimming + { + let params = getParams(); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 1;//dimming + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = time + 4200; + params.info = 'read dimming'; + //params.debug = true; + + tasks.push(params); + } + + } + } + + }, sec * 1000); + } + + + function reportOfflineNodeStatus(line) { + + logger.info("Cmd-mngr: ------>reportOffLineNodeStatus for line ", line); + + values = {}; + values["dimming"] = 0;//brightness + values["power"] = 0;//výkon + values["current"] = 0;//prúd + values["status"] = "OFFLINE"; + + const date = Date.now(); + + Object.keys(nodesData).forEach(node => { + + //potrebujem nody k danej linii + if (line == nodesData[node].line || line == undefined) { + + let tbname = nodesData[node].tbname; + let nodeStatus = nodesData[node].status; + + //in case we have reported offline node status, we return (continue with next node) + if (nodeStatus === "OFFLINE") return; + + nodesData[node].node_status_before_offline = nodeStatus; + nodesData[node].status = "OFFLINE"; + nodesData[node].readout = {}; + + sendTelemetry({ ...values }, tbname, date); + } + }); + + } + + + function turnLine(onOrOff, line, info) { + let obj = { + line: line, + command: onOrOff, + info: info + }; + + //to assure, handleDailyReportFunction do not run before rvo_is_on variable changes. So after every line switch we reset the timer + clearInterval(handleDailyReport); + handleDailyReport = setInterval(dailyReportHandler, DAILY_REPORT_HANDLER_TIME); + + //logger.debug("linia", line, obj); + instance.send(SEND_TO.dido_controller, obj); + } + + + 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"; + 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]) { + //CRC_ERROR + message = "NOK"; + error = "CRC_ERROR c1"; + instance.send(SEND_TO.debug, "CRC_ERROR c1"); + } + + 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") { + instance.send(SEND_TO.debug, bytes); + instance.send(SEND_TO.debug, "RESPONSE " + type + " - " + bytes[4]); + + //logger.debug(SEND_TO.debug, "RESPONSE " + type + " - " + bytes[4], bytes); + + error = "type is: " + type; + + message = "NOK"; + } + + return { message, type, error }; + } + + + //BUILD TASKS// + function buildTasks(params) { + + //return; + console.log("buidTAaasks start ****************", params); + monitor.info("buildTasks - params", params); + + let processLine; //defined line + let init = false; + let processLineProfiles = true; + let processBroadcast = true; + let processNodes = true; + + if (params == undefined) { + init = true; + tasks = []; + logger.debug("-->buildTasks clear tasks"); + } + else { + processLineProfiles = params.processLineProfiles; + processBroadcast = false; + processNodes = false; + + processLine = params.line; + } + + let now = new Date(); + + //process line profiles + if (processLineProfiles) { + + let keys = Object.keys(relaysData); + + for (let i = 0; i < keys.length; i++) { + + let line = parseInt(keys[i]); + let profilestr = relaysData[line].profile; + + if (processLine != undefined) { + if (processLine != line) continue; + } + + try { + + /** + * we process line profiles: timepoints, astro clock, lux_sensor, offsets ... + */ + if (profilestr === "") throw ("Profile is not defined"); + let profile = JSON.parse(profilestr); + 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; + + // add name to regular profile timepoint and delete unused end_time key: + time_points.forEach(point => { + point.name = "profileTimepoint" + delete point.end_time; + }); + + //monitor.info("buildTasks: time_points", time_points); + + + /** + * 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 astro clock true, we remove all regular profile points + time_points = []; + + //TODO: when astro clock == true, is offset calculated ??? + //let duskAstroClockOffset = profile.dusk_astro_clock_offset; + //let dawnAstroClockOffset = profile.dawn_astro_clock_offset; + //console.log("line astro clock offsets dusk a dawn: ", duskAstroClockOffset, dawnAstroClockOffset); + // maybe add dusk dawn offset to calculateDuskDawn ?? what dusk dawn will be if dawn_lux_sensor == true?? + //let sunCalcResult = calculateDuskDawn(new Date(), line, duskAstroClockOffset, dawnAstroClockOffset); + + 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 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); + + 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); + + 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(':'); + + let ad = new Date(); + ad.setHours(parseInt(ahours), parseInt(aminutes), 0); + + let bd = new Date(); + bd.setHours(parseInt(bhours), parseInt(bminutes), 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++) { + + let start_time = new Date(); + let [hours, minutes] = time_points[t].start_time.split(':'); + start_time.setHours(parseInt(hours), parseInt(minutes), 0); + + //task is in 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(); + params.type = "relay"; + params.line = parseInt(line); + params.value = time_points[t].value; + params.tbname = relaysData[line].tbname; + params.timestamp = start_time.getTime(); + + // 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; + + //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)) { + 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; + + params.debug = true; + + //turn on/off line + tasks.push(params); + monitor.info("TimePoint params: ", params.info, start_time); + } + + monitor.info("-->time_points final", line, time_points); + + //ensure to turn on/off according to calculated currentValue + let params = getParams(); + params.type = "relay"; + params.line = parseInt(line); + params.tbname = relaysData[line].tbname; + params.value = currentValue; + params.timestamp = i; + params.debug = true; + + //logger.debug(now.toLocaleString("sk-SK")); + 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; + + tasks.push(params); + + } catch (error) { + if (profilestr !== "") { + //errLogger.error(profilestr, error); + console.log(`Cmd_mngr: Unable to process line profile ${line}. Error: `, error); + errorHandler.sendMessageToService(profilestr + "-" + error, 0, "js_error"); + } else { + turnLine("off", line, "No line profile. Switching it off on startup"); + } + } + + } + //logger.debug("tasks:"); + //logger.debug(tasks); + } + + + //NOTE: PROCESS DEFAULT BROADCASTS - Time of dusk, Time of dawn, Actual Time + if (processBroadcast) { + + let d = new Date(); + let time = d.getTime(); + //let sunCalcResult = calculateDuskDawn(); + + { + let params = getParams(); + + params.address = 0xffffffff;//broadcast + params.byte1 = sunCalcResult["dusk_hours"]; + params.byte2 = sunCalcResult["dusk_minutes"]; + params.recipient = 2;//2 broadcast, + params.register = 6;//Time of dusk + params.rw = 1;//write + params.type = "node-regular-write"; + params.timestamp = time + 60000; + params.addMinutesToTimestamp = 60 * 3; //kazde 3 hodiny zisti novy dusk + params.info = "Broadcast-duskTime"; + + tasks.push(params); + } + + { + let params = getParams(); + + params.address = 0xffffffff;//broadcast + params.byte1 = sunCalcResult["dawn_hours"]; + params.byte2 = sunCalcResult["dawn_minutes"]; + params.recipient = 2; //2 broadcast + params.register = 7;//Time of dawn + params.rw = 1;//write + params.type = "node-regular-write"; + params.timestamp = time + 60001; + params.addMinutesToTimestamp = 60 * 3; //kazde 3 hodiny zisti novy dawn + params.info = "Broadcast-dawnTime"; + + tasks.push(params); + } + + { + let params = getParams(); + + params.address = 0xffffffff;//broadcast + params.byte1 = d.getHours(); + params.byte2 = d.getMinutes(); + params.recipient = 2; //2 broadcast + params.register = 87;//Actual time + params.rw = 1;//write + params.type = "node-regular-write"; + params.timestamp = time + 60002; + params.addMinutesToTimestamp = 5; + params.info = "run broadcast: Actual time"; + + tasks.push(params); + } + + } + + //process nodes & tasks - read node's data + if (processNodes) { + + let time = Date.now(); + + for (let k in nodesData) { + let address = parseInt(k); + let tbname = nodesData[k].tbname; + let register = 0; + + for (let i = 0; i < listOfCommands.length; i++) { + + register = listOfCommands[i]; + let addMinutesToTimestamp = priorities[register]; + + let params = getParams(); + + params.address = address; + params.recipient = 1; + params.register = register; + params.type = register == 1 ? "node-dimming-read" : "node-regular-read"; + params.tbname = tbname; + params.timestamp = time + 5000 + i * 500 + addMinutesToTimestamp * 1000; //to make slight time difference + params.addMinutesToTimestamp = addMinutesToTimestamp; + params.info = "Node regular read command"; + + tasks.push(params); + } + + } + } + + + //niektore ulohy sa vygeneruju iba 1x pri starte!!! + if (!init) return; + + + //Master node FW version - modifies SETTINGS.masterNodeIsResponding + { + let params = getParams(); + params.type = "cmd-master"; + params.register = 4; + params.address = 0; + params.timestamp = 0; + params.addMinutesToTimestamp = 5; + params.tbname = SETTINGS.rvoTbName; + params.info = "Master node FW verzia"; + //params.debug = true; + + tasks.push(params); + } + + //kazdu hodinu skontrolovat nastavenie profilov + { + let params = getParams(); + params.type = "process_profiles"; + params.timestamp = Date.now() + 60001; + params.addMinutesToTimestamp = 60;//60 = every hour + params.info = "detekcia nespracovaných profilov linie a nodov"; + //params.debug = true; + + tasks.push(params); + } + + monitor.info("tasks created:", tasks.length); + } + + + /** + * We process line profile, where "astro_clock": true + * example profile: + * + "dawn_lux_sensor": true, + "dusk_lux_sensor": true, + "dawn_lux_sensor_value": 5, + "dusk_lux_sensor_value": 5, + "dawn_astro_clock_offset": 0, + "dusk_astro_clock_offset": 10, + "dawn_lux_sensor_time_window": 30, + "dusk_lux_sensor_time_window": 30, + "dawn_astro_clock_time_window": 60, + "dusk_astro_clock_time_window": 60 + + * if dawn: if currentTimestamp is in timewindow "dawnTime + and - dawn_lux_sensor_time_window" and lux value >= lux_sensor_value, we switch off the line. + * if dusk: we do oposite + * + * dawn: usvit - lux je nad hranicou - vypnem + * dusk: sumrak - lux je pod hranicou - zapnem + */ + 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++) { + + let line = keys[i]; //line is turned off by default + let profilestr = relaysData[line].profile; + const contactor = relaysData[line].contactor; + + try { + + let profile = JSON.parse(profilestr); + if (Object.keys(profile).length === 0) throw ("turnOnOffLinesAccordingToLuxSensor - profile is not defined"); + + 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 (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"); + } + } + } + + //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 (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"); + } + } + } + + } + + } catch (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) { + //MASTER + if (node == 0) return; + + let nodeObj = nodesData[node]; + if (nodeObj == undefined) return; + + let nodeCurrentStatus = nodeObj.status; + const now = Date.now(); + + let data = null; + + if (nodeCurrentStatus === "OFFLINE") { + data = { status: newStatus }; + nodeDbStatusModify(node, data); + return; + } + else 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; + } + + } + + + 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 }; + } + }); + }); + } + + + function processDailyReport() { + + const now = Date.now(); + + for (const [key, value] of Object.entries(dailyReport)) { + + if (["name", "time", "dusk_and_dawn"].includes(key)) continue; + + let poleNumber = nodesData[key]["pole_number"]; + let line = dailyReport[key].line; + let nodeType = nodesData[key]["node_type"]; + let fullNodeName = key // key == nodeNumber + + if (poleNumber && nodeType) { + fullNodeName = SETTINGS.rvo_number + "/" + poleNumber + "_" + line + "L_" + key + "_" + nodeType; + } else { + fullNodeName = key; + } + + if (rvo_is_on) { + + if (value.initialTs) { + if (value.initialTs + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["night_no_data"], fullNodeName); + console.log('report nedostava ziadne data uz hodinu', fullNodeName); + value.initialTs = now; + } + } + if (value.dimmingIsZeroTime) { + if (value.dimmingIsZeroTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["night_dimming=0"], fullNodeName); + console.log("report node dimming je 0 ale ma svietit", fullNodeName); + value.dimmingIsZeroTime = now; + } + } + if (value.powerIsZeroTime) { + if (value.powerIsZeroTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["night_power=0"], fullNodeName); + console.log("report node power je 0 ale ma svietit", fullNodeName); + value.powerIsZeroTime = now; + } + } + + } else { + + let contactorStatus = relaysData[line].contactor; + if (contactorStatus === 1) { + + if (value.initialTs) { + if (value.initialTs + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["day_24/7_no_data"], fullNodeName); + console.log('node je na 24/7 ale nedostava ziadne data uz hodinu', fullNodeName); + value.initialTs = now; + } + } + if (value.dimmingIsOnButShouldBeOffTime) { + if (value.dimmingIsOnButShouldBeOffTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["day_24/7_dimming>0"], fullNodeName); + console.log("report dimming je > 0 ale nema svietit", fullNodeName); + value.dimmingIsOnButShouldBeOffTime = now; + } + } + if (value.powerIsOnButShouldBeOffTime) { + if (value.powerIsOnButShouldBeOffTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["day_24/7_power>0"], fullNodeName); + console.log("report power je > 0 ale nema svietit", fullNodeName); + value.powerIsOnButShouldBeOffTime = now; + } + } + + } + + } + + } + + let report = {}; + report["name"] = SETTINGS.rvo_name; + report["time"] = new Date(); + report["report"] = reportToSend; + + writeToFile(F.path.root("report_data.log"), report, true); + instance.send(SEND_TO.dailyReport, report); + } + + + function dailyReportHandler() { + + if (!SETTINGS.daily_report) return; + + // after dawn we empty reportToSend and start to get data for a new day + const date = new Date(); + const hour = date.getHours(); + const minute = date.getMinutes(); + + console.log("now: ", hour, minute, "suncalc: ", sunCalcResult.dawn_hours, sunCalcResult.dawn_minutes); + + if (hour === sunCalcResult.dawn_hours) { + + //NOTE: ak je este pred usvitom, spracujeme report a posleme na cloud, ak uz je po usvite, resetujeme report plnime data noveho dna + if (minute >= sunCalcResult.dawn_minutes - 2) { + emptyReportToSend(); + emptyDailyReport(); + console.log("Podmienka 1 v dailyReport handler"); + } else { + processDailyReport(); + emptyReportToSend(); + emptyDailyReport(); + console.log("Podmienka 2 v dailyReport handler"); + } + + initialReportStatus = true; + + // ak sa funkcia spusti o hodinu alebo 2 neskor, ako je usvit (moze sa to stat, kedze kazde zapnutie/vypnutie linii odznova spusti casovac. + } else if (hour === sunCalcResult.dawn_hours + 1 || hour === sunCalcResult.dawn_hours + 2) { + if (!initialReportStatus) { + emptyReportToSend(); + emptyDailyReport(); + initialReportStatus = true; + console.log("Podmienka 3 v dailyReport handler"); + } else { + processDailyReport(); + initialReportStatus = true; + console.log("Podmienka 4 v dailyReport handler"); + } + } else { + processDailyReport(); + initialReportStatus = false; + console.log("Podmienka 5 v dailyReport handler"); + } + + console.log("initialReportStatus: ", initialReportStatus); + + } + + function emptyReportToSend() { + emptyJsObject(reportToSend); + reportToSend["contactor"] = { off: [], on: [] }; + reportToSend["night_no_data"] = []; + reportToSend["night_dimming=0"] = []; + reportToSend["night_power=0"] = []; + reportToSend["day_24/7_no_data"] = []; + reportToSend["day_24/7_dimming>0"] = []; + reportToSend["day_24/7_power>0"] = []; + console.log(`resetuje sa reportToSend`); + } + + + //NOTE: ked je initialTs stale rovnaky a zistime ze linie su vypnute (relaysData.line.contactor) - zistim, ci je node na tej linii. Vieme, ze ak je linia vypnuta je to v poriadku lebo nie je na 24/7 linii + //ak je na 24/7 linii, reportujeme, ze neprijima data + function emptyDailyReport() { + const ts = Date.now(); + emptyJsObject(dailyReport); + + //NOTE: do dailyReport dame vsetky nody a pravidelne kontrolujeme ci maju data + //ked nastane sumrak/usvit a svetla maju zacat/prestat svietit, dailyReport spravime nanovo: + for (const [key, value] of Object.entries(nodesData)) { + dailyReport[value.node] = { line: value.line, initialTs: ts }; + } + + console.log("dailyReport: ", dailyReport); + } + + + async function runTasks() { + + clearInterval(interval); + + let currentTimestamp = Date.now(); + + //sort tasks based on timestamp + 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) { + instance.send(SEND_TO.debug, "no tasks created"); + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + if (!rsPort.isOpen) { + instance.send(SEND_TO.debug, "!rsPort.isOpen"); + //await rsPort.open(); + //console.log("Cmd-mngr: !rsPort.isOpen"); + } + + let currentTask = tasks[0]; + + if (currentTask.debug) { + //logger.debug("--->task to process", currentTask); + } + + if (currentTask.timestamp <= currentTimestamp) { + let params = { ...tasks[0] }; + + //allow terminal commands + if (SETTINGS.maintenance_mode && params.type !== "cmd-terminal") { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + let type = params.type; + let tbname = params.tbname; + let node = params.address; + let register = params.register; + let line = null; + let itIsNodeCommand; + + if (nodesData[node] !== undefined) { + line = nodesData[node].line; + itIsNodeCommand = true; + } + + if (params.line !== undefined) line = params.line; + + if (params.addMinutesToTimestamp > 0 || params.timePointName) { + tasks[0].timestamp = currentTimestamp + tasks[0].addMinutesToTimestamp * 60000; + } else { + tasks.shift(); + } + + //kontrola nespracovanych profilov nodov + //TODO: co ked niektore nody neprijimaju profily? kazdu hodinu zahltuju "tasks" array + if (type == "process_profiles") { + //na vsetky zapnutych liniach sa spracuju nespracovane profily nodov + loadRelaysData(); + interval = setInterval(runTasks, SHORT_INTERVAL); + return; + } + + //relay + if (type == "relay") { + + const timePointName = params.timePointName; + const value = params.value; + + let date = new Date(); + date.setDate(date.getDate() + 1);//next day + + let sunCalcResult; + if (timePointName) sunCalcResult = calculateDuskDawn(date, params.line); + + + if (timePointName == "dawn") { + tasks[0].timestamp = sunCalcResult.dawn_time; + } + else if (timePointName == "dusk") { + tasks[0].timestamp = sunCalcResult.dusk_time; + } + else if (timePointName == "luxOn") { + tasks[0].timestamp = sunCalcResult.dusk_time + params.dusk_lux_sensor_time_window * 60000; + } + else if (timePointName == "luxOff") { + tasks[0].timestamp = sunCalcResult.dawn_time + params.dawn_lux_sensor_time_window * 60000; + } + else if (timePointName == "profileTimepoint") { + tasks[0].timestamp = currentTimestamp + tasks[0].addMinutesToTimestamp * 60000; + } + + let info = "aplikovany bod profilu"; + let onOrOff = ""; + value == 1 ? onOrOff = "on" : onOrOff = "off"; + + turnLine(onOrOff, params.line, info); + + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + if (!SETTINGS.masterNodeIsResponding) { + //ak neodpoveda, nebudeme vykonavat ziadne commands, okrem cmd-terminal cmd-master + errorHandler.sendMessageToService("Master node is not responding"); + + let stop = true; + + if (type === "cmd-terminal" || type === "cmd-master") stop = false; + if (stop) { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + } + + let contactorStatus = 1; + if (relaysData[line] != undefined) contactorStatus = relaysData[line].contactor; + + if (line === 0 || contactorStatus === 0 || FLOW.deviceStatus.state_of_breaker[line] === "Off") { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + // TODO: -> status offline for rvo if rotary_switch_state is OFF, this is source of errors + // check if rotary_switch_state == "Off" + // state_of_braker: disconnected = true? + + if (!rsPort.isOpen) { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + //RE-CALCULATE VALUES + //set actual time for broadcast + if (register == 87 && params.recipient === 2) { + var d = new Date(); + params.byte1 = d.getHours();//h + params.byte2 = d.getMinutes();//m + } + + //SET DUSK/DAWN FOR BROADCAST + //Time of dusk + if (register == 6 && params.recipient === 2) { + + if (type != "cmd-terminal") { + params.byte1 = sunCalcResult["dusk_hours"];//h + params.byte2 = sunCalcResult["dusk_minutes"];//m + } + } + + //Time of dawn + if (register == 7 && params.recipient === 2) { + if (type != "cmd-terminal") { + params.byte1 = sunCalcResult["dawn_hours"];//h + params.byte2 = sunCalcResult["dawn_minutes"];//m + } + } + //----------------------- + + instance.send(SEND_TO.debug, "address: " + node + " register:" + register + "type: " + type); + + var startTime, endTime; + startTime = new Date(); + + let saveToTb = true; + if (!tbname) saveToTb = false; + + let resp = com_generic(node, params.recipient, params.rw, register, params.name, params.byte1, params.byte2, params.byte3, params.byte4); + let readBytes = 11; + let timeout = 4000; + + + // await keyword is important, otherwise incorrect data is returned! + await writeData(rsPort, resp, readBytes, timeout).then(function(data) { + + //sometimes happens, that status of node changes to OK, NOK even if line was turned off and should be status OFFLINE. To prevent this, we return if line contactor is 0: + if (itIsNodeCommand && line && relaysData[line].contactor !== 1) return; + + 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); + + //ak sa odpoved zacina 0 - je to v poriadku, inak je NOK + let message = result.message; // OK, NOK + let message_type = result.type; + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + console.log("detected response:", result); + logger.debug("Cmd-mngr: writeData done " + message_type + " duration: " + timeDiff + " type: " + params.debug, params, result); + } + } + + let values = {}; + + //CMD FINISHED + if (message == "OK") { + + updateNodeStatus(node, true); + + //write + if (type == "set_node_profile") { + let result = cmdCounterResolve(node); + if (result == 0) { + dbNodes.modify({ processed: true }).where("node", node).make(function(builder) { + builder.callback(function(err, response) { + + sendNotification("Cmd-mngr: process cmd", SETTINGS.rvoTbName, "dimming_profile_was_successfully_received_by_node", { node: node }, "", SEND_TO.tb, instance); + + logger.debug("--> profil úspešne odoslaný na node č. " + node); + nodesData[node].processed = true; + nodeProfileSendFail.delete(node); + }); + }); + } + } + + //parse read response + if (params.rw == 0) { + values = processResponse(register, dataBytes); //read + } + + if (itIsNodeCommand) { + values.comm_status = "OK"; + values.status = "OK"; + nodesData[node].readout = { ...nodesData[node].readout, ...values }; + + + if (SETTINGS.daily_report) { + //TODO: co ak nedostavame odpovede z nodu ? Musime vyreportovat!! + //v dailyReport teda musi byt kompletny zoznam nodov a neustale kontrolovat, ci maju data, ak nie report node - neodpoveda + if (register === 1) { + + let now = Date.now(); + + if (rvo_is_on === true) { + + if ("dimmingIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].dimmingIsOnButShouldBeOffTime; + + if (values.dimming > 0) { + if ("dimmingIsZeroTime" in dailyReport[node]) delete dailyReport[node].dimmingIsZeroTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if (!("dimmingIsZeroTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], dimmingIsZeroTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } else { + + if ("dimmingIsZeroTime" in dailyReport[node]) delete dailyReport[node].dimmingIsZeroTime; + + if (values.dimming > 0) { + if (!("dimmingIsOnButShouldBeOffTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], dimmingIsOnButShouldBeOffTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if ("dimmingIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].dimmingIsOnButShouldBeOffTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } + } + + if (register === 76) { + + let now = Date.now(); + + if (rvo_is_on === true) { + + if ("powerIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].powerIsOnButShouldBeOffTime; + + if (values.power > 1) { + if ("powerIsZeroTime" in dailyReport[node]) delete dailyReport[node].powerIsZeroTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if (!("powerIsZeroTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], powerIsZeroTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } else { + + if ("powerIsZeroTime" in dailyReport[node]) delete dailyReport[node].powerIsZeroTime; + + if (values.power > 1) { + if (!("powerIsOnButShouldBeOffTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], powerIsOnButShouldBeOffTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if ("powerIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].powerIsOnButShouldBeOffTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } + } + } + + } + + //master node + if (node == 0) { + sendNotification("Cmd-mngr: 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; + } + + if (params.debug) { + //logger.debug("saveToTb", saveToTb, tbname, values); + } + + if (saveToTb && type != "node-regular-read") { + sendTelemetry(values, tbname); + } + else { + if (type == "cmd-terminal") { + terminalCommandResponse(params, "SUCCESS", data); + } + } + + } + else { + terminalCommandResponse(params, "ERROR", data); + handleNokResponseOnRsPort("handleNOK else block", params, itIsNodeCommand, saveToTb); + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + //logger.debug("writeData err: ", error, result, params); + logger.debug("writeData err: ", tbname, node, register, values); + } + } + + //logger.debug(error, result, params); + } + }).catch(function(reason) { + + //console.log("writeData catch exception", reason); + instance.send(SEND_TO.debug, reason); + + terminalCommandResponse(params, "FAILURE", null, reason); + handleNokResponseOnRsPort("handleNOK catch block", params, itIsNodeCommand, saveToTb); + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + logger.debug("-->WRITE FAILED: " + reason, params.debug, params); + } + } + + }); + + } + 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); + } + + + // if node does not respond to request, we repeat request 3 times: + function repeatCommand(params) { + params.repeatCounter++; + if (params.repeatCounter < 4) { + params.timestamp = 0; + params.addMinutesToTimestamp = 0; + tasks.push(params); + } + } + + function handleNokResponseOnRsPort(message, params, itIsNodeCommand, saveToTb) { + + let node = params.address; + let register = params.register; + let type = params.type; + let tbName = params.tbname; + if (!tbName) return; + + let values = {}; + + let updateStatus = updateNodeStatus(node, false); + + if (itIsNodeCommand) { + values.comm_status = "NOK"; + nodesData[node].readout.comm_status = "NOK"; + repeatCommand(params); + } + + if (updateStatus) { + values.status = "NOK"; + nodesData[node].readout.status = "NOK"; + } + + if (type === "node-regular-read") return; + + //master node + if (node == 0) { + sendNotification("Cmd-mngr: 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; + + if (register == 4) values["master_node_version"] = "NOK"; + } + + if (type == "set_node_profile") { + delete cmdCounter[node]; + logger.debug("profil nebol úspešne odoslaný na node č. ", params); + + if (!nodeProfileSendFail.has(node)) { + sendNotification("Cmd-mngr: process cmd", tbName, "configuration_of_dimming_profile_to_node_failed", { node: node }, "", SEND_TO.tb, instance); + nodeProfileSendFail.add(node); + } + } + + // console.log("------",node, register, type, itIsNodeCommand, updateStatus, saveToTb, values); + if (saveToTb) { + sendTelemetry(values, tbName); + } + + } + + + function sendNodesData() { + Object.keys(nodesData).forEach(node => { + if (nodesData[node]["status"] !== "OFFLINE") { + sendTelemetry(nodesData[node].readout, nodesData[node].tbname); + nodesData[node].readout = {}; + } + }) + } + + + /** + * 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; + } + + 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); + + //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 === "OFFLINE") { + nodeObj.node_status_before_offline === true ? number_of_ok_luminaires++ : number_of_nok_luminaires++; + } + else if (nodeObj.status == true) 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 - ts % 60000 //round to full minute + }; + + sendTelemetry(values, SETTINGS.rvoTbName, ts); + } + + + function setSunCalcResult() { + //if next day, we get new dusk and dawn. To make sure, in local timezone 2:00 means 00:00 in utc (it means next day) + if (new Date().getHours() === 2) { + sunCalcResult = calculateDuskDawn(); + console.log("Novy suncalc: ", sunCalcResult); + } + } + + + function setRvoPeriod() { + + if (!SETTINGS.daily_report) return; + + const ts = Date.now(); + + previous_rvo_is_on_value = rvo_is_on; + + if (ts < sunCalcResult.dawn_time - 1_800_000) { // nodes should be on (00:00 -> 06:00 ( - pol hodina, lebo rvo vypina skor) + rvo_is_on = true; + } else if (sunCalcResult.dawn_time - 1_800_000 < ts && ts < sunCalcResult.dusk_time + 1_800_000) { // nodes should be off 06:00 -> 21:00 + rvo_is_on = false; + } else if (sunCalcResult.dusk_time + 1_800_000 < ts) { // nodes should be on 21:00 -> 00:00 + rvo_is_on = true; + } + + if (previous_rvo_is_on_value !== rvo_is_on) { + emptyDailyReport(); + console.log("rvo_is: ", rvo_is_on, previous_rvo_is_on_value); + } + } + + + function handleRsPort() { + + if (rsPort) { + rsPort.removeAllListeners(); + rsPort = null; + } + + //! 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-mngr: rsPort opened success"); + + 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); + + }).catch(function(reason) { + instance.send(SEND_TO.debug, "Cmd-mngr: RPC runSyncExec - promise rejected:" + reason); + }); + }); + + rsPort.on('error', function(err) { + errorHandler.sendMessageToService([exports.title, "unable to open port", SETTINGS.serial_port, err.message], 0); + monitor.info("Cmd-mngr: Error on rsPort", err.message); + }); + + rsPort.on("close", () => { + monitor.info("Cmd-mngr: rsPort closed, reconnecting..."); + setTimeout(handleRsPort, 1000); + }); + + rsPort.open(); + } + + + instance.on("close", () => { + clearInterval(interval); + clearInterval(customTasksInterval); + clearInterval(setCorrectTime); + clearInterval(sendNodeReadout); + clearInterval(accelerometerInterval); + rsPort.close(); + }); + + instance.on("0", _ => { + main(); + }) + + + instance.on("2", _ => { + console.log("dailyReport, reportToSend, rvo_is_on", dailyReport, reportToSend, rvo_is_on, previous_rvo_is_on_value); + }) + + instance.on("1", 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(); + return; + } + else if (flowdata.data == "close") { + rsPort.close(); + return; + } + else if (flowdata.data == "clean") { + tasks = []; + return; + } + else if (flowdata.data == "buildtasks") { + //build & run + return; + } + else if (flowdata.data == "run") { + //durations = []; + + if (tasks.length == 0) { + + buildTasks(); + + if (rsPort.isOpen) { + interval = setInterval(runTasks, 100); + } + else { + instance.send(SEND_TO.debug, "port is not opened!!!"); + } + } + } + else { + //terminal data - object + //logger.debug("flowdata", flowdata.data); + + if (typeof flowdata.data === 'object') { + //logger.debug("dido", flowdata.data); + if (flowdata.data.hasOwnProperty("sender")) { + //data from dido_controller + if (flowdata.data.sender == "dido_controller") { + + if (flowdata.data.hasOwnProperty("cmd")) { + let cmd = flowdata.data.cmd; + + if (cmd == "buildTasks") { + clearInterval(interval); + + logger.debug("-->Cmd-mngr: BUILD TASKS"); + buildTasks(); + + //logger.debug("tasks:"); + //logger.debug(tasks); + + logger.debug("-->Cmd-mngr: RUN TASKS"); + interval = setInterval(runTasks, 5000); + } + else if (cmd == "reload_relays") { + loadRelaysData(flowdata.data.line); + + if (flowdata.data.dataChanged) { + if (!flowdata.data.value) { + reportOfflineNodeStatus(flowdata.data.line); + } + else { + reportOnlineNodeStatus(flowdata.data.line); + } + } + + } + else if (cmd == "rotary_switch_state") { + let value = flowdata.data.value; + + //state was changed + if (rotary_switch_state != value) { + if (value == "Off") { + //vyreportovat vsetky svietdla + reportOfflineNodeStatus(); + } + + rotary_switch_state = value; + } + } + 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) { + + // we send lux_sensor value to all nodes: + let params = getParams(PRIORITY_TYPES.node_broadcast); + + params.recipient = 2;//2 broadcast, address = 0 + params.address = 0xffffffff;//Broadcast + + let ba = longToByteArray(lux_sensor); + + params.byte3 = ba[1];//msb + params.byte4 = ba[0]; + params.timestamp = PRIORITY_TYPES.node_broadcast; + params.info = "run broadcast: Actual Lux level from cabinet"; + params.register = 95;//Actual Lux level from cabinet + params.rw = 1;//write + + tasks.push(params); + + //process profiles + turnOnOffLinesAccordingToLuxSensor(lux_sensor); + } + } + else if (cmd == "state_of_breaker") { + //istic linie + + breakerCounter--; + + let value = flowdata.data.value; + let line = parseInt(flowdata.data.line); + + let dataChanged = false; + if (state_of_breaker[line] != value) dataChanged = true; + + state_of_breaker[line] = value; + + let status = "OK"; + if (value == "Off") status = "NOK"; + + if (dataChanged) { + + if (relaysData.hasOwnProperty(line)) { + let tbname = relaysData[line].tbname; + + if (value == "Off") { + sendNotification("Cmd-mngr: onData", tbname, "circuit_breaker_was_turned_off_line", { line: line }, "", SEND_TO.tb, instance, "circuit_breaker"); + if (breakerCounter < 0) reportToSend["contactor"]["off"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + else { + sendNotification("Cmd-mngr: onData", tbname, "circuit_breaker_was_turned_on_line", { line: line }, "", SEND_TO.tb, instance, "circuit_breaker"); + if (breakerCounter < 0) reportToSend["contactor"]["on"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + + //report status liniu + sendTelemetry({ status: status }, tbname) + + //current value + if (value == "Off") reportOfflineNodeStatus(line); //vyreportovat vsetky svietidla na linii + } + + } + } + else { + logger.debug("undefined cmd", cmd); + } + } + } + + return; + } + + //data from worksys + if (flowdata.data.hasOwnProperty("topic")) { + + let data = getNested(flowdata.data, "content", "data"); + + //if we get temperature in senica from senica-prod01 + let temperature = getNested(flowdata.data, "content", "senica_temperature"); + + if (temperature !== undefined) { + temperatureInSenica = temperature; + return; + } + + if (data === undefined) { + console.log("Invalid rpc command came from platform"); + return; + } + + let command = data.params.command; + let method = data.method; + let profile = data.params.payload; + if (profile == undefined) profile = ""; + let entity = data.params.entities[0]; + let entity_type = entity.entity_type; + let tbname = entity.tb_name; + + instance.send(SEND_TO.debug, flowdata.data); + 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") { + + //let command = data.params.command; + let value = data.params.payload.value; + + if (command == "dimming") { + + let nodeWasFound = false; + let keys = Object.keys(nodesData); + + //logger.debug("-----", keys); + + 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); + + value = parseInt(value); + if (value > 0) value = value + 128; + + params.type = "node-onetime-write"; + params.tbname = tbname; + params.address = node; + params.register = 1; + params.recipient = 1; + params.byte4 = value; + params.rw = 1; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'set dimming from platform'; + //params.debug = true; + + //debug(params); + logger.debug("dimming", params); + + tasks.push(params); + + 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); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 1; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read dimming (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + //pridame aj vyreportovanie - vykon + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 76; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read Input Power (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + //pridame aj vyreportovanie - prud svietidla + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 75; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read Input Current (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + //pridame aj vyreportovanie - power faktor - ucinnik + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 77; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read power factor (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + }, 4000); + + nodeWasFound = true; + break; + } + } + + if (!nodeWasFound) { + logger.debug("set dimming from platform", "unable to find tbname", tbname); + } + } + else { + instance.send(SEND_TO.debug, "undefined command " + command); + logger.debug("undefined command", command); + } + + return; + } + 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++) { + let node = keys[i]; + if (tbname == nodesData[node].tbname) { + + 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"); + + //profil úspešne prijatý pre node č. xx + sendNotification("Cmd-mngr", tbname, "dimming_profile_was_processed_for_node", { node: node }, profile, SEND_TO.tb, instance); + + nodesData[node].processed = false; + nodesData[node].profile = profile; + + processNodeProfile(node); + }); + }); + } + } + } + else { + + instance.send(SEND_TO.debug, "unknown method " + method); + logger.debug("unknown method", method); + + return; + } + } + + //nastav profil linie z platformy + 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") { + + 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++) { + let line = keys[i]; + if (tbname == relaysData[line].tbname) { + //zmazeme tasky + 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) { + + //update profile + logger.debug("worksys - update relay profile done:", profile); + instance.send(SEND_TO.debug, "worksys - update relay profile done"); + + relaysData[line].profile = profile; + + loadRelaysData(line) + logger.debug("loadRelaysData DONE for line", line); + + buildTasks({ processLineProfiles: true, line: line }); + + sendNotification("Cmd-mngr: set profile from worksys", tbname, "switching_profile_was_processed_for_line", { line: line }, profile, SEND_TO.tb, instance); + }); + }); + break; + } + } + } + else if (method == "set_command") { + let value = data.params.payload.value; + + 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; + + 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"); + if (line != 0) reportToSend["contactor"]["off"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + else { + turnLine("on", line, "command received from platform"); + if (line != 0) reportToSend["contactor"]["on"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + } + } + else { + instance.send(SEND_TO.debug, "undefined method " + method); + logger.debug("undefined method", method); + } + + return; + } + else { + instance.send(SEND_TO.debug, "UNKNOW entity_type " + entity_type); + logger.debug("UNKNOW entity_type", entity_type); + } + return; + } + + //terminal + if (!rsPort.isOpen) await rsPort.open(); + + let params = flowdata.data.body; + if (params == undefined) { + //logger.debug("Cmd-mngr: flowdata.data.body is undefined"); + return; + } + + params.priority = PRIORITY_TYPES.terminal; + params.type = "cmd-terminal"; + params.tbname = ""; + params.timestamp = PRIORITY_TYPES.terminal; + params.addMinutesToTimestamp = 0;// do not repeat task!!! + params.debug = true; + + let timestamp = Date.now(); + params.refFlowdataKey = timestamp; + //params.refFlowdata = flowdata; + //refFlowdata = flowdata; + + //console.log("flowdata", flowdata); + + cleanUpRefFlowdataObj(); + + refFlowdataObj[timestamp] = flowdata; + + //fix + //params.address = params.adress; + logger.debug("received from terminal", params); + logger.debug("date/time:", new Date()); + logger.debug("tasks length:", tasks.length); + + //tasks = []; + + //add to tasks + tasks.push(params); + + } + } + }) + + + //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) + } + + + /** + * 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; + + RESTBuilder.make(function(builder) { + + if (!builder) return; + + builder.method('GET'); + builder.url('http://192.168.252.2:8004/gettime?projects_id=1'); + + builder.callback(function(err, response, output) { + + 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); + } + + }); + } + + } 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); + + } else { + //console.log("Read-only", stdout); + + 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]: [ + { + "ts": date, + "values": values + } + ] + } + + tbHandler.sendToTb(dataToTb, instance); + } + + + function calculateDuskDawn(date, line, duskOffset = 0, dawnOffset = 0) { + + if (date === undefined) date = new Date(); + + 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); + } + + //if(profile.dawn_lux_sensor == false) + { + if (profile.hasOwnProperty("dawn_astro_clock_offset")) dawn_astro_clock_offset = parseInt(profile.dawn_astro_clock_offset); + } + + } + + } catch (error) { + if (profilestr != "") { + logger.debug(profilestr); + logger.debug(error); + } + } + + 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; + } + + //Dimming, CCT + else if (register == 1) { + let brightness = 0; + let dimming = byte0; + if (dimming > 128) { + //dimming = -128; + brightness = dimming - 128; + } + + //cct + //Ak Byte3 == 1: CCT = (Byte2*256)+Byte1 + let cct; + if (byte3 == 1) cct = byte2 * 256 + byte1; + else cct = bytesToInt(bytes.slice(0, 3)); + + //cct podla auditu + + values["dimming"] = brightness; + return values; + } + + // + else if (register == 4) { + values["master_node_version"] = bytes[1] + "." + bytes[2]; + //logger.debug("FW Version", register, bytes); + } + + //Napätie + else if (register == 74) { + let voltage = (bytesToInt(bytes) * 0.1).toFixed(1); + values["voltage"] = Number(voltage); + } + + //Prúd + else if (register == 75) { + let current = bytesToInt(bytes); + values["current"] = current; + } + + //výkon + else if (register == 76) { + let power = (bytesToInt(bytes) * 0.1).toFixed(2); + values["power"] = Number(power); + } + + //účinník + else if (register == 77) { + let power_factor = Math.cos(bytesToInt(bytes) * 0.1 * (Math.PI / 180)).toFixed(2); + values["power_factor"] = Number(power_factor); + } + + //frekvencia + else if (register == 78) { + let frequency = (bytesToInt(bytes) * 0.1).toFixed(2); + values["frequency"] = Number(frequency); + } + + //energia + else if (register == 79) { + let energy = bytesToInt(bytes); + values["energy"] = energy / 1000; //energia v kWh -> delit 1000 + } + + //doba života + else if (register == 80) { + let lifetime = (bytesToInt(bytes) / 60).toFixed(2); + values["lifetime"] = Number(lifetime); + } + + //nastavenie profilu + else if (register == 8) { + let time_schedule_settings = bytesToInt(bytes); + values["time_schedule_settings"] = time_schedule_settings; + } + + //naklon - nateraz sa z nodu nevycitava! kvoli problemom s accelerometrom a vracanymi hodnotami, posielame temp a x y z vo funkcii accelerometerData() + else if (register == 84) { + values["temperature"] = byte3 >= 128 ? (byte3 - 128) * (-1) : byte3; + values["inclination_x"] = byte2 >= 128 ? (byte2 - 128) * (-1) : byte2; + values["inclination_y"] = byte1 >= 128 ? (byte1 - 128) * (-1) : byte1; + values["inclination_z"] = byte0 >= 128 ? (byte0 - 128) * (-1) : byte0; + } + + //FW verzia nodu + else if (register == 89) { + //formát: "Byte3: Byte2.Byte1 (Byte0)" + values["fw_version"] = byte3 + ":" + byte2 + "." + byte1 + "(" + byte0 + ")"; + } + + else if (register == 87 || register == 6 || register == 7) { + var d = new Date(); + d.setHours(byte3, byte2, 0, 0); + let timestamp = d.getTime(); + + //aktuálny čas + if (register == 87) values["actual_time"] = timestamp; + //čas súmraku + else if (register == 6) values["dusk_time"] = timestamp; + //čas úsvitu + else if (register == 7) values["dawn_time"] = timestamp; + } + + 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; + + } + + + function getObjectByTbValue(object, tbname) { + return object[Object.keys(object).find(key => object[key].tbname === tbname)]; + } + + + function isObject(item) { + return (typeof item === "object" && !Array.isArray(item) && item !== null); + } + + + // we fake data, that should be received from accelerometer, as they are a bit unreliable. (temperature, x,y,z) + function accelerometerData() { + + if (temperatureInSenica === null) return; + + //clone nodesData and relaysData objects + let nodesData_clone = JSON.parse(JSON.stringify(nodesData)); + let relaysData_clone = JSON.parse(JSON.stringify(relaysData)); + + for (const key in relaysData_clone) { + + const lineData = relaysData_clone[key]; + const lineNumber = lineData.line; + const contactor = lineData.contactor; + + if (lineNumber === 0) continue; + + if (contactor === 1) { + + let date = Date.now(); + + Object.keys(nodesData_clone).forEach((node, index) => { + + setTimeout(function() { + + if (nodesData_clone[node].line === lineNumber) { + + // NOTE: if status of luminaire is NOK or OFFLINE, we do not send data; + let status = nodesData_clone[node].status; + if (status === "OFFLINE" || !status) return; + + let x = null; + if (naklony.hasOwnProperty(node)) x = naklony[node].naklon; + if (x === null) x = 0; + + sendTelemetry({ temperature: Math.round(temperatureInSenica + 10 + Math.floor(Math.random() * 3)), inclination_x: x, inclination_y: 0, inclination_z: 0 }, nodesData_clone[node].tbname, date); + } + + }, (index + 1) * 500); + }) + + } + } + } + + +} // end of instance.export + diff --git a/RVO15/flow/cmd_manager_original.txt b/RVO15/flow/cmd_manager_original.txt new file mode 100755 index 0000000..e92d48f --- /dev/null +++ b/RVO15/flow/cmd_manager_original.txt @@ -0,0 +1,2800 @@ +exports.id = 'cmd_manager'; +exports.title = 'CMD Manager'; +exports.group = 'Worksys'; +exports.color = '#5D9CEC'; +exports.version = '0.0.3'; +exports.output = ['red', 'blue', 'yellow', 'blue', 'white']; +exports.input = 3; +exports.icon = 'cloud-upload'; + +exports.html = ` +
+
+
+
RPC - run RPC calls

+
+
+
@(User)
+
+
+
@(Password)
+
+
+
@(My edge)
+
+
+
+`; +exports.readme = `Manager for CMD calls`; + + +exports.install = function(instance) { + + 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'); + + var SunCalc = require('./helper/suncalc'); + const DataToTbHandler = require('./helper/DataToTbHandler'); + const errorHandler = require('./helper/ErrorToServiceHandler'); + const { sendNotification } = require('./helper/notification_reporter'); + const process = require('process'); + const { errLogger, logger, monitor } = require('./helper/logger'); + + //for accelerometer purposes + const { naklony } = require("../databases/accelerometer_db"); + + const dbNodes = TABLE("nodes"); + const dbRelays = TABLE("relays"); + + let GLOBALS; + let SETTINGS; + let rsPort; + let tbHandler; + + // runTasks intervals + const SHORT_INTERVAL = 30; + const LONG_INTERVAL = 300; + + //send data to following instances: + const SEND_TO = { + debug: 0, + tb: 1, + http_response: 2, + dido_controller: 3, + infoSender: 4 + } + + 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 + } + + 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 sendNodeReadout = null; // interval for sending agregate data from node + + 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["1"] = minutes; // dimming + priorities["76"] = minutes; // power + + minutes = 5; + priorities["75"] = minutes; // current + priorities["79"] = minutes; // energy + priorities["87"] = minutes; // aktualny cas + //priorities["84"] = minutes; + + minutes = 10; + priorities["74"] = minutes; // voltage + priorities["77"] = minutes; // power factor + priorities["78"] = minutes; // frequency + + minutes = 60; + priorities["0"] = minutes; // statecode + priorities["6"] = minutes; // dusk + priorities["7"] = minutes; // dawn + priorities["8"] = minutes; // profile + + minutes = 60 * 24; + priorities["89"] = minutes; // verzia fw + priorities["80"] = minutes; // lifetime + + //prikazy kt sa budu spustat na dany node - see config.js in terminal-oms.app. (1 - dimming) + let listOfCommands = [0, 1, 6, 7, 8, 74, 75, 76, 77, 78, 79, 80, 87, 89]; + + 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 sunCalcResult; + let reportDuskDawn; + + //helper container for counting resolved group of commands (commands related to set profile) + let cmdCounter = {};//key is node, value is counter + + //if sending of profile to node fails, we send notification and push node into set, so we do not send notification twice + const nodeProfileSendFail = new Set(); + + //we expect to get current temperature in Senica from senica-prod01 + let temperatureInSenica = null; + let accelerometerInterval = null; + + //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); + + let now = new Date(); + console.log("Cmd-mngr 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(); + + customTasksInterval = setInterval(function() { + reportEdgeDateTimeAndNumberOfLuminaires(); + }, 120000); + reportEdgeDateTimeAndNumberOfLuminaires(); + + setCorrectTime = setInterval(setCorrectPlcTimeOnceADay, 60000 * 60); // 1 hour + setCorrectPlcTimeOnceADay(); + + sendNodeReadout = setInterval(sendNodesData, 150000); + accelerometerInterval = setInterval(accelerometerData, 60000 * 30); //30 min + } + + + 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" + //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 + // if node regular readout does not respond, we repeat request + params.repeatCounter = 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-mngr: 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.byte4 = 96; + params.recipient = 1; + params.register = 8; + params.rw = 1;//write + params.timestamp = timestamp; + 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.byte4 = 96; + params.recipient = 1; + params.register = 8; + params.rw = 1;//write + params.timestamp = timestamp; + 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). + */ + + 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.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.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 + { + + logger.debug("processNodeProfile: Threshold lux level for DUSK/DAWN", node); + + let params = getParams(); + params.type = "set_node_profile"; + params.address = node; + params.register = 96; + params.recipient = 1; + params.rw = 1;//write + params.timestamp = timestamp; + 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(); + params.type = "set_node_profile"; + params.address = node; + params.register = 97; + params.recipient = 1; + params.rw = 1;//write + params.timestamp = timestamp; + 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.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); + + 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); + + console.log("proces profile finished *********************") + } + + + 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; + }); + } + + + 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) { + for (let k in nodesData) { + 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`); + } + } + } + + + function loadRelaysData(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 (value.contactor == 1) processAllNodeProfilesOnLine(value.line); + } + } + + + function reportOnlineNodeStatus(line) { + //Po zapnutí línie broadcastovo aktualizovať predtým čas a o 3 sek neskor - status, brightness + + logger.debug("Cmd-mngr: ----->reportOnlineNodeStatus for line", line); + + const d = new Date(); + + // broadcast actual time + let params = getParams(); + params.address = 0xffffffff;//Broadcast + params.byte1 = d.getHours(); + params.byte2 = d.getMinutes(); + params.recipient = 2;//2 broadcast, address = 0 + params.register = 87;//Actual time + params.rw = 1;//write + params.type = "node-onetime-write"; + params.timestamp = d.getTime() + 30000; + params.info = "run broadcast: Actual time"; + //params.debug = true; + + tasks.push(params); + + let sec = 3; + setTimeout(function() { + //Po zapnutí línie - spraviť hromadný refresh stavu práve zapnutých svietidiel + + let time = Date.now(); + + for (let k in nodesData) { + + //potrebujem nody k danej linii + 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].node_status_before_offline === true || nodesData[k].status === true) { + status = "OK"; + nodesData[k].time_of_last_communication = time; + } + + nodesData[k].readout.status = status; + + updateNodeStatus(k, status === "OK" ? true : false); + if (nodesData[k].hasOwnProperty("node_status_before_offline")) delete nodesData[k].node_status_before_offline; + sendTelemetry({ status: status }, tbname, time); + + //vyreportovanie dimming, current, input power pre liniu pre vsetky nody + //Prud + { + let params = getParams(); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 75;//prud + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = time + 4000; + params.info = 'read current'; + //params.debug = true; + tasks.push(params); + } + + //vykon + { + let params = getParams(); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 76;//výkon + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = time + 4100; + params.info = 'read power'; + //params.debug = true; + + tasks.push(params); + } + //dimming + { + let params = getParams(); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 1;//dimming + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = time + 4200; + params.info = 'read dimming'; + //params.debug = true; + + tasks.push(params); + } + + } + } + + }, sec * 1000); + } + + + function reportOfflineNodeStatus(line) { + + logger.info("Cmd-mngr: ------>reportOffLineNodeStatus for line ", line); + + values = {}; + values["dimming"] = 0;//brightness + values["power"] = 0;//výkon + values["current"] = 0;//prúd + values["status"] = "OFFLINE"; + + const date = Date.now(); + + Object.keys(nodesData).forEach(node => { + + //potrebujem nody k danej linii + if (line == nodesData[node].line || line == undefined) { + + let tbname = nodesData[node].tbname; + let nodeStatus = nodesData[node].status; + + //in case we have reported offline node status, we return (continue with next node) + if (nodeStatus === "OFFLINE") return; + + nodesData[node].node_status_before_offline = nodeStatus; + nodesData[node].status = "OFFLINE"; + nodesData[node].readout = {}; + + sendTelemetry({ ...values }, tbname, date); + } + }); + + } + + + function turnLine(onOrOff, line, info) { + let obj = { + line: line, + command: onOrOff, + info: info + }; + + //logger.debug("linia", line, obj); + instance.send(SEND_TO.dido_controller, obj); + } + + + 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"; + 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]) { + //CRC_ERROR + message = "NOK"; + error = "CRC_ERROR c1"; + instance.send(SEND_TO.debug, "CRC_ERROR c1"); + } + + 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") { + instance.send(SEND_TO.debug, bytes); + instance.send(SEND_TO.debug, "RESPONSE " + type + " - " + bytes[4]); + + //logger.debug(SEND_TO.debug, "RESPONSE " + type + " - " + bytes[4], bytes); + + error = "type is: " + type; + + message = "NOK"; + } + + return { message, type, error }; + } + + + //BUILD TASKS// + function buildTasks(params) { + + //return; + console.log("buidTAaasks start ****************", params); + monitor.info("buildTasks - params", params); + + let processLine; //defined line + let init = false; + let processLineProfiles = true; + let processBroadcast = true; + let processNodes = true; + + if (params == undefined) { + init = true; + tasks = []; + logger.debug("-->buildTasks clear tasks"); + } + else { + processLineProfiles = false; + processBroadcast = false; + processNodes = false; + + processLineProfiles = params.processLineProfiles; + processLine = params.line; + } + + let now = new Date(); + + //process line profiles + if (processLineProfiles) { + + let keys = Object.keys(relaysData); + + for (let i = 0; i < keys.length; i++) { + + let line = parseInt(keys[i]); + let profilestr = relaysData[line].profile; + + if (processLine != undefined) { + if (processLine != line) continue; + } + + try { + + /** + * we process line profiles: timepoints, astro clock, lux_sensor, offsets ... + */ + if (profilestr === "") throw ("Profile is not defined"); + let profile = JSON.parse(profilestr); + 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; + + // add name to regular profile timepoint and delete unused end_time key: + time_points.forEach(point => { + point.name = "profileTimepoint" + delete point.end_time; + }); + + //monitor.info("buildTasks: time_points", time_points); + + + /** + * 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 astro clock true, we remove all regular profile points + time_points = []; + + 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 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); + + 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); + + 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(':'); + + let ad = new Date(); + ad.setHours(parseInt(ahours), parseInt(aminutes), 0); + + let bd = new Date(); + bd.setHours(parseInt(bhours), parseInt(bminutes), 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++) { + + let start_time = new Date(); + let [hours, minutes] = time_points[t].start_time.split(':'); + start_time.setHours(parseInt(hours), parseInt(minutes), 0); + + //task is in 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(); + params.type = "relay"; + params.line = parseInt(line); + params.value = time_points[t].value; + params.tbname = relaysData[line].tbname; + params.timestamp = start_time.getTime(); + + // 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; + + //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)) { + 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; + + params.debug = true; + + //turn on/off line + tasks.push(params); + monitor.info("TimePoint params: ", params.info, start_time); + } + + monitor.info("-->time_points final", line, time_points); + + //ensure to turn on/off according to calculated currentValue + let params = getParams(); + params.type = "relay"; + params.line = parseInt(line); + params.tbname = relaysData[line].tbname; + params.value = currentValue; + params.timestamp = i; + params.debug = true; + + //logger.debug(now.toLocaleString("sk-SK")); + 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; + + tasks.push(params); + + } catch (error) { + if (profilestr !== "") { + //errLogger.error(profilestr, error); + console.log(`Cmd_mngr: Unable to process line profile ${line}. Error: `, error); + errorHandler.sendMessageToService(profilestr + "-" + error, 0, "js_error"); + } else { + turnLine("off", line, "No line profile. Switching it off on startup"); + } + } + + } + //logger.debug("tasks:"); + //logger.debug(tasks); + } + + + //NOTE: PROCESS DEFAULT BROADCASTS - Time of dusk, Time of dawn, Actual Time + if (processBroadcast) { + + let d = new Date(); + let time = d.getTime(); + let sunCalcResult = calculateDuskDawn(); + + { + let params = getParams(); + + params.address = 0xffffffff;//broadcast + params.byte1 = sunCalcResult["dusk_hours"]; + params.byte2 = sunCalcResult["dusk_minutes"]; + params.recipient = 2;//2 broadcast, + params.register = 6;//Time of dusk + params.rw = 1;//write + params.type = "node-regular-write"; + params.timestamp = time + 60000; + params.addMinutesToTimestamp = 60 * 3; //kazde 3 hodiny zisti novy dusk + params.info = "Broadcast-duskTime"; + + tasks.push(params); + } + + { + let params = getParams(); + + params.address = 0xffffffff;//broadcast + params.byte1 = sunCalcResult["dawn_hours"]; + params.byte2 = sunCalcResult["dawn_minutes"]; + params.recipient = 2; //2 broadcast + params.register = 7;//Time of dawn + params.rw = 1;//write + params.type = "node-regular-write"; + params.timestamp = time + 60001; + params.addMinutesToTimestamp = 60 * 3; //kazde 3 hodiny zisti novy dawn + params.info = "Broadcast-dawnTime"; + + tasks.push(params); + } + + { + let params = getParams(); + + params.address = 0xffffffff;//broadcast + params.byte1 = d.getHours(); + params.byte2 = d.getMinutes(); + params.recipient = 2; //2 broadcast + params.register = 87;//Actual time + params.rw = 1;//write + params.type = "node-regular-write"; + params.timestamp = time + 60002; + params.addMinutesToTimestamp = 5; + params.info = "run broadcast: Actual time"; + + tasks.push(params); + } + + } + + //process nodes & tasks - read node's data + if (processNodes) { + + let time = Date.now(); + + for (let k in nodesData) { + let address = parseInt(k); + let tbname = nodesData[k].tbname; + let register = 0; + + for (let i = 0; i < listOfCommands.length; i++) { + + register = listOfCommands[i]; + let addMinutesToTimestamp = priorities[register]; + + let params = getParams(); + + params.address = address; + params.recipient = 1; + params.register = register; + params.type = register == 1 ? "node-dimming-read" : "node-regular-read"; + params.tbname = tbname; + params.timestamp = time + 5000 + i * 500 + addMinutesToTimestamp * 1000; //to make slight time difference + params.addMinutesToTimestamp = addMinutesToTimestamp; + params.info = "Node regular read command"; + + tasks.push(params); + } + + } + } + + + //niektore ulohy sa vygeneruju iba 1x pri starte!!! + if (!init) return; + + + //Master node FW version - modifies SETTINGS.masterNodeIsResponding + { + let params = getParams(); + params.type = "cmd-master"; + params.register = 4; + params.address = 0; + params.timestamp = 0; + params.addMinutesToTimestamp = 5; + params.tbname = SETTINGS.rvoTbName; + params.info = "Master node FW verzia"; + //params.debug = true; + + tasks.push(params); + } + + //kazdu hodinu skontrolovat nastavenie profilov + { + let params = getParams(); + params.type = "process_profiles"; + params.timestamp = Date.now() + 60001; + params.addMinutesToTimestamp = 60;//60 = every hour + params.info = "detekcia nespracovaných profilov linie a nodov"; + //params.debug = true; + + tasks.push(params); + } + + monitor.info("tasks created:", tasks.length); + } + + + /** + * We process line profile, where "astro_clock": true + * example profile: + * + "dawn_lux_sensor": true, + "dusk_lux_sensor": true, + "dawn_lux_sensor_value": 5, + "dusk_lux_sensor_value": 5, + "dawn_astro_clock_offset": 0, + "dusk_astro_clock_offset": 10, + "dawn_lux_sensor_time_window": 30, + "dusk_lux_sensor_time_window": 30, + "dawn_astro_clock_time_window": 60, + "dusk_astro_clock_time_window": 60 + + * if dawn: if currentTimestamp is in timewindow "dawnTime + and - dawn_lux_sensor_time_window" and lux value >= lux_sensor_value, we switch off the line. + * if dusk: we do oposite + * + * dawn: usvit - lux je nad hranicou - vypnem + * dusk: sumrak - lux je pod hranicou - zapnem + */ + 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++) { + + let line = keys[i]; //line is turned off by default + let profilestr = relaysData[line].profile; + const contactor = relaysData[line].contactor; + + try { + + let profile = JSON.parse(profilestr); + if (Object.keys(profile).length === 0) throw ("turnOnOffLinesAccordingToLuxSensor - profile is not defined"); + + 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 (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"); + } + } + } + + //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 (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"); + } + } + } + + } + + } catch (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) { + //MASTER + if (node == 0) return; + + let nodeObj = nodesData[node]; + if (nodeObj == undefined) return; + + let nodeCurrentStatus = nodeObj.status; + const now = Date.now(); + + let data = null; + + if (nodeCurrentStatus === "OFFLINE") { + data = { status: newStatus }; + nodeDbStatusModify(node, data); + return; + } + else 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; + } + + } + + + 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 }; + } + }); + }); + } + + + async function runTasks() { + + clearInterval(interval); + + let currentTimestamp = Date.now(); + + //report dusk, dawn--------------------------------- + if (reportDuskDawn.dusk_time < currentTimestamp) { + //vyreportuj iba ak nie je velky rozdiel napr. 60 sekund + if ((currentTimestamp - reportDuskDawn.dusk_time) < 60 * 1000) { + //reportovali sme? + if (reportDuskDawn.dusk_time_reported != sunCalcResult.dusk_time) { + //sendNotification("Cmd-mngr: calculated Time of dusk", SETTINGS.rvoTbName, "dusk_has_occured", { value: sunCalcResult["dusk"] }, "", SEND_TO.tb, instance); + reportDuskDawn.dusk_time_reported = sunCalcResult.dusk_time; + } + } + + var nextDay = new Date(); + nextDay.setDate(nextDay.getDate() + 1); + + sunCalcResult = calculateDuskDawn(nextDay); + reportDuskDawn.dusk_time = sunCalcResult.dusk_time; + } + + if (reportDuskDawn.dawn_time < currentTimestamp) { + //vyreportuj iba ak nie je velky rozdiel napr. 60 sekund + if ((currentTimestamp - reportDuskDawn.dawn_time) < 60 * 1000) { + //reportovali sme? + if (reportDuskDawn.dawn_time_reported != sunCalcResult.dawn_time) { + //sendNotification(": calculated Time of dawn", SETTINGS.rvoTbName, "dawn_has_occured", { value: sunCalcResult["dawn"] }, "", SEND_TO.tb, instance); + reportDuskDawn.dawn_time_reported = sunCalcResult.dawn_time; + } + } + + var nextDay = new Date(); + nextDay.setDate(nextDay.getDate() + 1); + + sunCalcResult = calculateDuskDawn(nextDay); + reportDuskDawn.dawn_time = sunCalcResult.dawn_time; + + } + //-------------------------------------------------------- + + //sort tasks based on timestamp + 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) { + instance.send(SEND_TO.debug, "no tasks created"); + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + if (!rsPort.isOpen) { + instance.send(SEND_TO.debug, "!rsPort.isOpen"); + //await rsPort.open(); + //console.log("Cmd-mngr: !rsPort.isOpen"); + } + + let currentTask = tasks[0]; + + if (currentTask.debug) { + //logger.debug("--->task to process", currentTask); + } + + if (currentTask.timestamp <= currentTimestamp) { + let params = { ...tasks[0] }; + + //allow terminal commands + if (SETTINGS.maintenance_mode && params.type !== "cmd-terminal") { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + let type = params.type; + let tbname = params.tbname; + let node = params.address; + let register = params.register; + let line = null; + let itIsNodeCommand; + + if (nodesData[node] !== undefined) { + line = nodesData[node].line; + itIsNodeCommand = true; + } + + if (params.line !== undefined) line = params.line; + + if (params.addMinutesToTimestamp > 0 || params.timePointName) { + tasks[0].timestamp = currentTimestamp + tasks[0].addMinutesToTimestamp * 60000; + } else { + tasks.shift(); + } + + //kontrola nespracovanych profilov nodov + if (type == "process_profiles") { + //na vsetky zapnutych liniach sa spracuju nespracovane profily nodov + loadRelaysData(); + interval = setInterval(runTasks, SHORT_INTERVAL); + return; + } + + //relay + if (type == "relay") { + + const timePointName = params.timePointName; + const value = params.value; + + let date = new Date(); + date.setDate(date.getDate() + 1);//next day + + let sunCalcResult; + if (timePointName) sunCalcResult = calculateDuskDawn(date, params.line); + + if (timePointName == "dawn") { + tasks[0].timestamp = sunCalcResult.dawn_time; + } + else if (timePointName == "dusk") { + tasks[0].timestamp = sunCalcResult.dusk_time; + } + else if (timePointName == "luxOn") { + tasks[0].timestamp = sunCalcResult.dusk_time + params.dusk_lux_sensor_time_window * 60000; + } + else if (timePointName == "luxOff") { + tasks[0].timestamp = sunCalcResult.dawn_time + params.dawn_lux_sensor_time_window * 60000; + } + else if (timePointName == "profileTimepoint") { + tasks[0].timestamp = currentTimestamp + tasks[0].addMinutesToTimestamp * 60000; + } + + let info = "aplikovany bod profilu"; + let onOrOff = ""; + value == 1 ? onOrOff = "on" : onOrOff = "off"; + + turnLine(onOrOff, params.line, info); + + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + if (!SETTINGS.masterNodeIsResponding) { + //ak neodpoveda, nebudeme vykonavat ziadne commands, okrem cmd-terminal cmd-master + errorHandler.sendMessageToService("Master node is not responding"); + + let stop = true; + + if (type === "cmd-terminal" || type === "cmd-master") stop = false; + if (stop) { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + } + + let contactorStatus = 1; + if (relaysData[line] != undefined) contactorStatus = relaysData[line].contactor; + + if (line === 0 || contactorStatus === 0 || FLOW.deviceStatus.state_of_breaker[line] === "Off") { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + // TODO: -> status offline for rvo if rotary_switch_state is OFF, this is source of errors + // check if rotary_switch_state == "Off" + // state_of_braker: disconnected = true? + + if (!rsPort.isOpen) { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + //RE-CALCULATE VALUES + //set actual time for broadcast + if (register == 87 && params.recipient === 2) { + var d = new Date(); + params.byte1 = d.getHours();//h + params.byte2 = d.getMinutes();//m + } + + //SET DUSK/DAWN FOR BROADCAST + //Time of dusk + if (register == 6 && params.recipient === 2) { + + if (type != "cmd-terminal") { + let sunCalcResult = calculateDuskDawn(); + params.byte1 = sunCalcResult["dusk_hours"];//h + params.byte2 = sunCalcResult["dusk_minutes"];//m + } + } + + //Time of dawn + if (register == 7 && params.recipient === 2) { + if (type != "cmd-terminal") { + let sunCalcResult = calculateDuskDawn(); + params.byte1 = sunCalcResult["dawn_hours"];//h + params.byte2 = sunCalcResult["dawn_minutes"];//m + } + } + //----------------------- + + instance.send(SEND_TO.debug, "address: " + node + " register:" + register + "type: " + type); + + var startTime, endTime; + startTime = new Date(); + + let saveToTb = true; + if (!tbname) saveToTb = false; + + let resp = com_generic(node, params.recipient, params.rw, register, params.name, params.byte1, params.byte2, params.byte3, params.byte4); + let readBytes = 11; + let timeout = 4000; + + + // await keyword is important, otherwise incorrect data is returned! + await writeData(rsPort, resp, readBytes, timeout).then(function(data) { + + //sometimes happens, that status of node changes to OK, NOK even if line was turned off and should be status OFFLINE. To prevent this, we return if line contactor is 0: + if (itIsNodeCommand && line && relaysData[line].contactor !== 1) return; + + 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); + + //ak sa odpoved zacina 0 - je to v poriadku, inak je NOK + let message = result.message; // OK, NOK + let message_type = result.type; + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + console.log("detected response:", result); + logger.debug("Cmd-mngr: writeData done " + message_type + " duration: " + timeDiff + " type: " + params.debug, params, result); + } + } + + let values = {}; + + //CMD FINISHED + if (message == "OK") { + + updateNodeStatus(node, true); + + //write + if (type == "set_node_profile") { + let result = cmdCounterResolve(node); + if (result == 0) { + dbNodes.modify({ processed: true }).where("node", node).make(function(builder) { + builder.callback(function(err, response) { + + sendNotification("Cmd-mngr: process cmd", SETTINGS.rvoTbName, "dimming_profile_was_successfully_received_by_node", { node: node }, "", SEND_TO.tb, instance); + + logger.debug("--> profil úspešne odoslaný na node č. " + node); + nodesData[node].processed = true; + nodeProfileSendFail.delete(node); + }); + }); + } + } + + //parse read response + if (params.rw == 0) { + values = processResponse(register, dataBytes); //read + } + + if (itIsNodeCommand) { + values.comm_status = "OK"; + values.status = "OK"; + nodesData[node].readout = { ...nodesData[node].readout, ...values }; + } + + //master node + if (node == 0) { + sendNotification("Cmd-mngr: 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; + } + + if (params.debug) { + //logger.debug("saveToTb", saveToTb, tbname, values); + } + + if (saveToTb && type != "node-regular-read") { + sendTelemetry(values, tbname); + } + else { + if (type == "cmd-terminal") { + terminalCommandResponse(params, "SUCCESS", data); + } + } + + } + else { + terminalCommandResponse(params, "ERROR", data); + handleNokResponseOnRsPort("handleNOK else block", params, itIsNodeCommand, saveToTb); + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + //logger.debug("writeData err: ", error, result, params); + logger.debug("writeData err: ", tbname, node, register, values); + } + } + + //logger.debug(error, result, params); + } + }).catch(function(reason) { + + //console.log("writeData catch exception", reason); + instance.send(SEND_TO.debug, reason); + + terminalCommandResponse(params, "FAILURE", null, reason); + handleNokResponseOnRsPort("handleNOK catch block", params, itIsNodeCommand, saveToTb); + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + logger.debug("-->WRITE FAILED: " + reason, params.debug, params); + } + } + + }); + + } + 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); + } + + + // if node does not respond to request, we repeat request 3 times: + function repeatCommand(params) { + params.repeatCounter++; + if (params.repeatCounter < 4) { + params.timestamp = 0; + params.addMinutesToTimestamp = 0; + tasks.push(params); + } + } + + function handleNokResponseOnRsPort(message, params, itIsNodeCommand, saveToTb) { + + let node = params.address; + let register = params.register; + let type = params.type; + let tbName = params.tbname; + if (!tbName) return; + + let values = {}; + + let updateStatus = updateNodeStatus(node, false); + + if (itIsNodeCommand) { + values.comm_status = "NOK"; + nodesData[node].readout.comm_status = "NOK"; + repeatCommand(params); + } + + if (updateStatus) { + values.status = "NOK"; + nodesData[node].readout.status = "NOK"; + } + + if (type === "node-regular-read") return; + + //master node + if (node == 0) { + sendNotification("Cmd-mngr: 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; + + if (register == 4) values["master_node_version"] = "NOK"; + } + + if (type == "set_node_profile") { + delete cmdCounter[node]; + logger.debug("profil nebol úspešne odoslaný na node č. ", params); + + if (!nodeProfileSendFail.has(node)) { + sendNotification("Cmd-mngr: process cmd", tbName, "configuration_of_dimming_profile_to_node_failed", { node: node }, "", SEND_TO.tb, instance); + nodeProfileSendFail.add(node); + } + } + + // console.log("------",node, register, type, itIsNodeCommand, updateStatus, saveToTb, values); + if (saveToTb) { + sendTelemetry(values, tbName); + } + + } + + + function sendNodesData() { + Object.keys(nodesData).forEach(node => { + if (nodesData[node]["status"] !== "OFFLINE") { + sendTelemetry(nodesData[node].readout, nodesData[node].tbname); + nodesData[node].readout = {}; + } + }) + } + + + /** + * 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; + } + + 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); + + //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 === "OFFLINE") { + nodeObj.node_status_before_offline === true ? number_of_ok_luminaires++ : number_of_nok_luminaires++; + } + else if (nodeObj.status == true) 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 - ts % 60000 //round to full minute + }; + + sendTelemetry(values, SETTINGS.rvoTbName, ts); + } + + + function handleRsPort() { + + if (rsPort) { + rsPort.removeAllListeners(); + rsPort = null; + } + + //! 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-mngr: rsPort opened success"); + + 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); + + }).catch(function(reason) { + instance.send(SEND_TO.debug, "Cmd-mngr: RPC runSyncExec - promise rejected:" + reason); + }); + }); + + rsPort.on('error', function(err) { + errorHandler.sendMessageToService([exports.title, "unable to open port", SETTINGS.serial_port, err.message], 0); + monitor.info("Cmd-mngr: Error on rsPort", err.message); + }); + + rsPort.on("close", () => { + monitor.info("Cmd-mngr: rsPort closed, reconnecting..."); + setTimeout(handleRsPort, 1000); + }); + + rsPort.open(); + } + + + instance.on("close", () => { + clearInterval(interval); + clearInterval(customTasksInterval); + clearInterval(setCorrectTime); + clearInterval(sendNodeReadout); + clearInterval(accelerometerInterval); + rsPort.close(); + }); + + instance.on("0", _ => { + main(); + }) + + instance.on("1", 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(); + return; + } + else if (flowdata.data == "close") { + rsPort.close(); + return; + } + else if (flowdata.data == "clean") { + tasks = []; + return; + } + else if (flowdata.data == "buildtasks") { + //build & run + return; + } + else if (flowdata.data == "run") { + //durations = []; + + if (tasks.length == 0) { + + buildTasks(); + + if (rsPort.isOpen) { + interval = setInterval(runTasks, 100); + } + else { + instance.send(SEND_TO.debug, "port is not opened!!!"); + } + } + } + else { + //terminal data - object + //logger.debug("flowdata", flowdata.data); + + if (typeof flowdata.data === 'object') { + //logger.debug("dido", flowdata.data); + if (flowdata.data.hasOwnProperty("sender")) { + //data from dido_controller + if (flowdata.data.sender == "dido_controller") { + + if (flowdata.data.hasOwnProperty("cmd")) { + let cmd = flowdata.data.cmd; + + if (cmd == "buildTasks") { + clearInterval(interval); + + logger.debug("-->Cmd-mngr: BUILD TASKS"); + buildTasks(); + + //logger.debug("tasks:"); + //logger.debug(tasks); + + logger.debug("-->Cmd-mngr: RUN TASKS"); + interval = setInterval(runTasks, 5000); + } + else if (cmd == "reload_relays") { + loadRelaysData(flowdata.data.line); + + if (flowdata.data.dataChanged) { + if (!flowdata.data.value) { + reportOfflineNodeStatus(flowdata.data.line); + } + else { + reportOnlineNodeStatus(flowdata.data.line); + } + } + + } + else if (cmd == "rotary_switch_state") { + let value = flowdata.data.value; + + //state was changed + if (rotary_switch_state != value) { + if (value == "Off") { + //vyreportovat vsetky svietdla + reportOfflineNodeStatus(); + } + + rotary_switch_state = value; + } + } + 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) { + + // we send lux_sensor value to all nodes: + let params = getParams(PRIORITY_TYPES.node_broadcast); + + params.recipient = 2;//2 broadcast, address = 0 + params.address = 0xffffffff;//Broadcast + + let ba = longToByteArray(lux_sensor); + + params.byte3 = ba[1];//msb + params.byte4 = ba[0]; + params.timestamp = PRIORITY_TYPES.node_broadcast; + params.info = "run broadcast: Actual Lux level from cabinet"; + params.register = 95;//Actual Lux level from cabinet + params.rw = 1;//write + + tasks.push(params); + + //process profiles + turnOnOffLinesAccordingToLuxSensor(lux_sensor); + } + } + else if (cmd == "state_of_breaker") { + //istic linie + let value = flowdata.data.value; + let line = parseInt(flowdata.data.line); + + let dataChanged = false; + if (state_of_breaker[line] != value) dataChanged = true; + + state_of_breaker[line] = value; + + let status = "OK"; + if (value == "Off") status = "NOK"; + + if (dataChanged) { + + if (relaysData.hasOwnProperty(line)) { + let tbname = relaysData[line].tbname; + + if (value == "Off") sendNotification("Cmd-mngr: onData", tbname, "circuit_breaker_was_turned_off_line", { line: line }, "", SEND_TO.tb, instance, "circuit_breaker"); + else sendNotification("Cmd-mngr: onData", tbname, "circuit_breaker_was_turned_on_line", { line: line }, "", SEND_TO.tb, instance, "circuit_breaker"); + + //report status liniu + sendTelemetry({ status: status }, tbname) + + //current value + if (value == "Off") reportOfflineNodeStatus(line); //vyreportovat vsetky svietidla na linii + } + + } + } + else { + logger.debug("undefined cmd", cmd); + } + } + } + + return; + } + + //data from worksys + if (flowdata.data.hasOwnProperty("topic")) { + + let data = getNested(flowdata.data, "content", "data"); + + //if we get temperature in senica from senica-prod01 + let temperature = getNested(flowdata.data, "content", "senica_temperature"); + + if (temperature !== undefined) { + temperatureInSenica = temperature; + return; + } + + if (data === undefined) { + console.log("Invalid rpc command came from platform"); + return; + } + + let command = data.params.command; + let method = data.method; + let profile = data.params.payload; + if (profile == undefined) profile = ""; + let entity = data.params.entities[0]; + let entity_type = entity.entity_type; + let tbname = entity.tb_name; + + instance.send(SEND_TO.debug, flowdata.data); + 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") { + + //let command = data.params.command; + let value = data.params.payload.value; + + if (command == "dimming") { + + let nodeWasFound = false; + let keys = Object.keys(nodesData); + + //logger.debug("-----", keys); + + 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); + + value = parseInt(value); + if (value > 0) value = value + 128; + + params.type = "node-onetime-write"; + params.tbname = tbname; + params.address = node; + params.register = 1; + params.recipient = 1; + params.byte4 = value; + params.rw = 1; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'set dimming from platform'; + //params.debug = true; + + //debug(params); + logger.debug("dimming", params); + + tasks.push(params); + + 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); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 1; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read dimming (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + //pridame aj vyreportovanie - vykon + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 76; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read Input Power (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + //pridame aj vyreportovanie - prud svietidla + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 75; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read Input Current (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + //pridame aj vyreportovanie - power faktor - ucinnik + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 77; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read power factor (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + }, 4000); + + nodeWasFound = true; + break; + } + } + + if (!nodeWasFound) { + logger.debug("set dimming from platform", "unable to find tbname", tbname); + } + } + else { + instance.send(SEND_TO.debug, "undefined command " + command); + logger.debug("undefined command", command); + } + + return; + } + 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++) { + let node = keys[i]; + if (tbname == nodesData[node].tbname) { + + 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"); + + //profil úspešne prijatý pre node č. xx + sendNotification("Cmd-mngr", tbname, "dimming_profile_was_processed_for_node", { node: node }, profile, SEND_TO.tb, instance); + + nodesData[node].processed = false; + nodesData[node].profile = profile; + + processNodeProfile(node); + }); + }); + } + } + } + else { + + instance.send(SEND_TO.debug, "unknown method " + method); + logger.debug("unknown method", method); + + return; + } + } + + //nastav profil linie z platformy + 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") { + + 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++) { + let line = keys[i]; + if (tbname == relaysData[line].tbname) { + //zmazeme tasky + 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) { + + //update profile + logger.debug("worksys - update relay profile done:", profile); + instance.send(SEND_TO.debug, "worksys - update relay profile done"); + + relaysData[line].profile = profile; + + loadRelaysData(line) + logger.debug("loadRelaysData DONE for line", line); + + buildTasks({ processLineProfiles: true, line: line }); + + sendNotification("Cmd-mngr: set profile from worksys", tbname, "switching_profile_was_processed_for_line", { line: line }, profile, SEND_TO.tb, instance); + }); + }); + break; + } + } + } + else if (method == "set_command") { + let value = data.params.payload.value; + + 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; + + 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"); + } + } + else { + instance.send(SEND_TO.debug, "undefined method " + method); + logger.debug("undefined method", method); + } + + return; + } + else { + instance.send(SEND_TO.debug, "UNKNOW entity_type " + entity_type); + logger.debug("UNKNOW entity_type", entity_type); + } + return; + } + + //terminal + if (!rsPort.isOpen) await rsPort.open(); + + let params = flowdata.data.body; + if (params == undefined) { + //logger.debug("Cmd-mngr: flowdata.data.body is undefined"); + return; + } + + params.priority = PRIORITY_TYPES.terminal; + params.type = "cmd-terminal"; + params.tbname = ""; + params.timestamp = PRIORITY_TYPES.terminal; + params.addMinutesToTimestamp = 0;// do not repeat task!!! + params.debug = true; + + let timestamp = Date.now(); + params.refFlowdataKey = timestamp; + //params.refFlowdata = flowdata; + //refFlowdata = flowdata; + + //console.log("flowdata", flowdata); + + cleanUpRefFlowdataObj(); + + refFlowdataObj[timestamp] = flowdata; + + //fix + //params.address = params.adress; + logger.debug("received from terminal", params); + logger.debug("date/time:", new Date()); + logger.debug("tasks length:", tasks.length); + + //tasks = []; + + //add to tasks + tasks.push(params); + + } + } + }) + + + //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) + } + + + /** + * 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; + + RESTBuilder.make(function(builder) { + + if (!builder) return; + + builder.method('GET'); + builder.url('http://192.168.252.2:8004/gettime?projects_id=1'); + + builder.callback(function(err, response, output) { + + 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); + } + + }); + } + + } 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); + + } else { + //console.log("Read-only", stdout); + + 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]: [ + { + "ts": date, + "values": values + } + ] + } + + 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); + } + + //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); + } + } + + 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; + } + + //Dimming, CCT + else if (register == 1) { + let brightness = 0; + let dimming = byte0; + if (dimming > 128) { + //dimming = -128; + brightness = dimming - 128; + } + + //cct + //Ak Byte3 == 1: CCT = (Byte2*256)+Byte1 + let cct; + if (byte3 == 1) cct = byte2 * 256 + byte1; + else cct = bytesToInt(bytes.slice(0, 3)); + + //cct podla auditu + + values["dimming"] = brightness; + return values; + } + + // + else if (register == 4) { + values["master_node_version"] = bytes[1] + "." + bytes[2]; + //logger.debug("FW Version", register, bytes); + } + + //Napätie + else if (register == 74) { + let voltage = (bytesToInt(bytes) * 0.1).toFixed(1); + values["voltage"] = Number(voltage); + } + + //Prúd + else if (register == 75) { + let current = bytesToInt(bytes); + values["current"] = current; + } + + //výkon + else if (register == 76) { + let power = (bytesToInt(bytes) * 0.1).toFixed(2); + values["power"] = Number(power); + } + + //účinník + else if (register == 77) { + let power_factor = Math.cos(bytesToInt(bytes) * 0.1 * (Math.PI / 180)).toFixed(2); + values["power_factor"] = Number(power_factor); + } + + //frekvencia + else if (register == 78) { + let frequency = (bytesToInt(bytes) * 0.1).toFixed(2); + values["frequency"] = Number(frequency); + } + + //energia + else if (register == 79) { + let energy = bytesToInt(bytes); + values["energy"] = energy / 1000; //energia v kWh -> delit 1000 + } + + //doba života + else if (register == 80) { + let lifetime = (bytesToInt(bytes) / 60).toFixed(2); + values["lifetime"] = Number(lifetime); + } + + //nastavenie profilu + else if (register == 8) { + let time_schedule_settings = bytesToInt(bytes); + values["time_schedule_settings"] = time_schedule_settings; + } + + //naklon - nateraz sa z nodu nevycitava! kvoli problemom s accelerometrom a vracanymi hodnotami, posielame temp a x y z vo funkcii accelerometerData() + else if (register == 84) { + values["temperature"] = byte3 >= 128 ? (byte3 - 128) * (-1) : byte3; + values["inclination_x"] = byte2 >= 128 ? (byte2 - 128) * (-1) : byte2; + values["inclination_y"] = byte1 >= 128 ? (byte1 - 128) * (-1) : byte1; + values["inclination_z"] = byte0 >= 128 ? (byte0 - 128) * (-1) : byte0; + } + + //FW verzia nodu + else if (register == 89) { + //formát: "Byte3: Byte2.Byte1 (Byte0)" + values["fw_version"] = byte3 + ":" + byte2 + "." + byte1 + "(" + byte0 + ")"; + } + + else if (register == 87 || register == 6 || register == 7) { + var d = new Date(); + d.setHours(byte3, byte2, 0, 0); + let timestamp = d.getTime(); + + //aktuálny čas + if (register == 87) values["actual_time"] = timestamp; + //čas súmraku + else if (register == 6) values["dusk_time"] = timestamp; + //čas úsvitu + else if (register == 7) values["dawn_time"] = timestamp; + } + + 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; + + } + + function getObjectByTbValue(object, tbname) { + return object[Object.keys(object).find(key => object[key].tbname === tbname)]; + } + + function isObject(item) { + return (typeof item === "object" && !Array.isArray(item) && item !== null); + } + + + // we fake data, that should be received from accelerometer, as they are a bit unreliable. (temperature, x,y,z) + function accelerometerData() { + + if (temperatureInSenica === null) return; + + //clone nodesData and relaysData objects + let nodesData_clone = JSON.parse(JSON.stringify(nodesData)); + let relaysData_clone = JSON.parse(JSON.stringify(relaysData)); + + for (const key in relaysData_clone) { + + const lineData = relaysData_clone[key]; + const lineNumber = lineData.line; + const contactor = lineData.contactor; + + if (lineNumber === 0) continue; + + if (contactor === 1) { + + let date = Date.now(); + + Object.keys(nodesData_clone).forEach((node, index) => { + + setTimeout(function() { + + if (nodesData_clone[node].line === lineNumber) { + + // NOTE: if status of luminaire is NOK or OFFLINE, we do not send data; + let status = nodesData_clone[node].status; + if (status === "OFFLINE" || !status) return; + + let x = null; + if (naklony.hasOwnProperty(node)) x = naklony[node].naklon; + if (x === null) x = 0; + + sendTelemetry({ temperature: Math.round(temperatureInSenica + 10 + Math.floor(Math.random() * 3)), inclination_x: x, inclination_y: 0, inclination_z: 0 }, nodesData_clone[node].tbname, date); + } + + }, (index + 1) * 500); + }) + + } + } + } + + +} // end of instance.export + diff --git a/RVO15/flow/code.js b/RVO15/flow/code.js new file mode 100755 index 0000000..63b31bf --- /dev/null +++ b/RVO15/flow/code.js @@ -0,0 +1,90 @@ +exports.id = 'code'; +exports.title = 'Code'; +exports.group = 'Common'; +exports.color = '#656D78'; +exports.input = true; +exports.output = 1; +exports.author = 'Peter Širka'; +exports.icon = 'code'; +exports.version = '1.2.0'; +exports.options = { outputs: 1, code: 'send(0, value);', keepmessage: true }; + +exports.html = `
+
+
+
@(Number of outputs)
+
@(Minimum is 1)
+
+
+
@(Code)
+
@(Keep message instance)
+
+`; + +exports.readme = `# Code + +This component executes custom JavaScript code as it is and it doesn't contain any secure scope. + +\`\`\`javascript +// value {Object} contains received data +// send(outputIndex, newValue) sends a new value +// error(value) sends an error +// instance {Object} a current component instance +// flowdata {Object} a current flowdata +// repository {Object} a current repository of flowdata +// Example: + +// send() can be execute multiple times +send(0, value); +\`\`\``; + +exports.install = function(instance) { + + var fn; + + instance.on('data', function(response) { + if (fn) { + try { + fn(response.data, instance, response, instance.options, response.repository, require); + } catch (e) { + response.data = e; + instance.throw(response); + } + } + }); + + instance.reconfigure = function() { + try { + if (instance.options.code) { + instance.status(''); + var code = 'var send = function(index, value) { if (options.keepmessage) { flowdata.data = value; instance.send2(index, flowdata); } else instance.send2(index, value);}; var error = function(err) { instance.throw(err); }; ' + instance.options.code; + fn = new Function('value', 'instance', 'flowdata', 'options', 'repository', 'require', code); + } else { + instance.status('Not configured', 'red'); + fn = null; + } + } catch (e) { + fn = null; + instance.error('Code: ' + e.message); + } + }; + + instance.on('options', instance.reconfigure); + instance.reconfigure(); +}; \ No newline at end of file diff --git a/RVO15/flow/comment.js b/RVO15/flow/comment.js new file mode 100755 index 0000000..1e0cd13 --- /dev/null +++ b/RVO15/flow/comment.js @@ -0,0 +1,11 @@ +exports.id = 'comment'; +exports.title = 'Comment'; +exports.group = 'Common'; +exports.color = '#704cff'; +exports.author = 'Martin Smola'; +exports.icon = 'comment'; +exports.traffic = false; +exports.version = '1.0.0'; +exports.readme = '# Comment'; + +exports.install = function() {}; diff --git a/RVO15/flow/count.js b/RVO15/flow/count.js new file mode 100755 index 0000000..fa92ee9 --- /dev/null +++ b/RVO15/flow/count.js @@ -0,0 +1,60 @@ +exports.id = 'count'; +exports.title = 'Count'; +exports.version = '1.0.1'; +exports.author = 'John Graves'; +exports.color = '#656D78'; +exports.icon = 'plus-square'; +exports.input = 2; +exports.output = 1; +exports.options = { increment: 1, initialvalue: 1 }; +exports.readme = `# Counter + +Counter Number of times called.`; + +exports.html = `
+
@(Initial Value)
+
@(Increment)
+

Example Video

+
`; + +exports.readme = `# Count + +This component counts the number of messages received. + +__Response:__ + +Integer value based on the initial value and increment settings. + +__Arguments:__ +- Initial Value: What number should be output on the receipt of the first message. +- Increment: What should the increment be for each following message received.`; + +exports.install = function(instance) { + + var count = 0; + var initialCall = true; + + instance.on('data', function(flowdata) { + var index = flowdata.index; + if (index) { + instance.debug('Reset Count.'); + count = instance.options.initialvalue; + initialCall = true; + } else { + // If this is the first time, set the value to 'initial value' + if(initialCall) { + initialCall = false; + count = instance.options.initialvalue; + } else + count = count+instance.options.increment; + instance.status('Count:' + count); + instance.send2(count); + } + }); + + instance.on('options', function() { + count = instance.options.initialvalue; + initialCall = true; + }); + +}; diff --git a/RVO15/flow/db_connector.js b/RVO15/flow/db_connector.js new file mode 100755 index 0000000..65ee94b --- /dev/null +++ b/RVO15/flow/db_connector.js @@ -0,0 +1,286 @@ +exports.id = 'db_connector'; +exports.title = 'DbConnector'; +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.html = `
+
+
+
DbConnector
+
+
+
`; + +exports.readme = `# read/write data to tables`; + +const instanceSendTo = { + debug: 0, + http_response: 1, +} + +const { promisifyBuilder, makeMapFromDbResult } = require('./helper/db_helper.js'); + +function extractWhereParams(params) +{ + let name = params[0]; + let operator = '='; + let value = params[1]; + + if(params.length == 3) + { + operator = params[1]; + value = params[2]; + } + + return {name: name, operator: operator, value: value}; +} + +exports.install = function(instance) { + + let refFlowdata = null;//holds reference to httprequest flowdata + + instance.on("close", () => { + + }) + + + instance.on("data", async function(flowdata) { + + let params = flowdata.data.body; + console.log("DbConnector", params); + + refFlowdata = flowdata; + + if(refFlowdata != undefined) + { + //make http response + let responseObj = {}; + responseObj["type"] = "SUCESS"; + + try{ + + let table = params.table; + let action = params.action; + + + if(params.data != undefined) + { + let className = params.data.className; + + if(className == "SqlQueryBuilder") + { + let type = params.data.type; + + console.log("SqlQueryBuilder---->", params.data); + + if(type == "SELECT") + { + let table = params.data.queryData.tables[0].table; + + const db = TABLE(table); + var builder = db.find(); + + let result = await promisifyBuilder(builder); + + let response = {}; + response["result"] = result; + response["success"] = true; + + responseObj["data"] = response; + + //console.log(responseObj); + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + } + + return; + } + } + + + console.log("db_connector---->", table, action); + + //actions: read, replace, insert, delete, update... + + if(action == "read") + { + const db = TABLE(params.table); + + //where builder.where('age', '<', 15); + //builder.where('id', 3403); + + var builder = db.find(); + + //https://docs.totaljs.com/latest/en.html#api~DatabaseBuilder~builder.where + if(params.hasOwnProperty("where")) + { + //optionalCan contain "=", "<=", "<", ">=", ">". + //Default value: '=' + + //1.["production_line", 1] + //2. ["or", ["production_line", 1], ["production_line", 2], "end"] + + if (Array.isArray(params.where)) { + + let multipleConditions = false; + + if(params.where[0] == "or") multipleConditions = true; + if (Array.isArray(params.where[0])) multipleConditions = true; + + if(multipleConditions) + { + + for(var i = 0; i < params.where.length; i++) + { + const item = params.where[i]; + + if(item === "or") builder.or(); + + if (Array.isArray(item)) + { + const { name, operator, value } = extractWhereParams(item); + builder.where(name, operator, value); + } + + if(item === "end") builder.end(); + + } + + } + else + { + const { name, operator, value } = extractWhereParams(params.where); + builder.where(name, operator, value); + } + + } + + /* + if(params.where.length >=2 ) + { + let name = params.where[0]; + let operator = '='; + let value = params.where[1]; + + if(params.where.length == 3) + { + operator = params.where[1]; + value = params.where[2]; + } + + builder.where(name, operator, value); + } + */ + } + + if(params.hasOwnProperty("between")) + { + builder.between(params.between[0], params.between[1], params.between[2]); + } + + let response = await promisifyBuilder(builder); + responseObj["data"] = response; + + //console.log(responseObj); + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + + return; + } + + if(action == "delete") + { + + } + + + if(action == "update") + { + //! data receiving from terminal (params) + // { + // hostname: 'localhost', + // table: 'settings', + // action: 'update', + // body: { + // rvo_name: 'terrrr', + // lang: 'en', + // temperature_adress: '28.427B45920702', + // latitude: 48.70826502, + // longitude: 17.28455203, + // mqtt_host: '192.168.252.4', + // mqtt_clientid: 'showroom_test_panel_led', + // mqtt_username: 'xmRd6RJxW53WZe4vMFLU', + // mqtt_port: 1883, + // maintanace_mode: false + // } + // } + const tableToModify = TABLE(params.table); + const newValues = params.body; + + tableToModify.modify(newValues).make(function(builder) { + + builder.callback(function(err, response) { + + if(!err) + { + responseObj["data"] = response; + responseObj["tableUpdated"] = true; + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + } + }); + }); + + } + + if(action == "replace") + { + //truncate table + const db = TABLE(params.table); + var builder = db.remove(); + db.clean(); + + //insert data + let data = params.data; + + for(let i = 0; i < data.length; i++) + { + //console.log(data[i]); + db.insert(data[i]); + } + + console.log("insert done"); + + let responseObj = {}; + responseObj["type"] = "SUCESS"; + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + + + } + + + + } catch (error) { + //console.log(error); + responseObj["type"] = "ERROR"; + responseObj["message"] = error; + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + } + } + }) +} + + diff --git a/RVO15/flow/db_init.js b/RVO15/flow/db_init.js new file mode 100755 index 0000000..b399878 --- /dev/null +++ b/RVO15/flow/db_init.js @@ -0,0 +1,113 @@ +exports.id = 'db_init'; +exports.title = 'DB Initialization'; +exports.group = 'Worksys'; +exports.color = '#888600'; +exports.version = '1.0.2'; +exports.icon = 'sign-out'; +exports.output = 2; + +exports.readme = ` + # DB initialization +`; + +const { promisifyBuilder, makeMapFromDbResult } = require('./helper/db_helper.js'); +const { initNotification } = require('./helper/notification_reporter'); +const errorHandler = require('./helper/ErrorToServiceHandler'); +const total_energy = require('../databases/total_energy'); + +const SEND_TO = { + db_init: 0, + infoSender: 1 +}; + + +exports.install = async function(instance) { + const dbNodes = TABLE("nodes"); + const dbRelays = TABLE("relays"); + const dbSettings = TABLE("settings"); + 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 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.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"]; + Object.keys(dbs.nodesData).forEach(node => dbs.nodesData[node].readout = {}) + + let rvo_number = responseSettings[0]["rvo_name"].match(/\D+(\d{1,2})_/)[1]; + + dbs.settings = { + edge_fw_version: "2025-10-08", //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"], + phases: responseSettings[0]["phases"], + cloud_topic: responseSettings[0]["cloud_topic"], + has_main_switch: responseSettings[0]["has_main_switch"], + daily_report: responseSettings[0]["daily_report"], + send_changed_node_numbers: responseSettings[0]["send_changed_node_numbers"], + rvo_number: rvo_number, + + //dynamic values + masterNodeIsResponding: true, //cmd_manager + maintenance_mode: false, + } + + + dbs.settings.energy_to_switch_lamps = total_energy[rvo_number]; + if (dbs.settings.energy_to_switch_lamps === undefined) console.log('=============== db_init.js: energy_to_switch_lamps is undefined'); + + FLOW.dbLoaded = true; + errorHandler.setProjectId(dbs.settings.project_id); + initNotification(); + + //APP START - send to data services + const toService = { + id: dbs.settings.project_id, + name: dbs.settings.rvo_name, + fw_version: dbs.settings.edge_fw_version, + startdate: new Date().toISOString().slice(0, 19).replace('T', ' '), + js_error: "", + error_message: "" + }; + + instance.send(SEND_TO.infoSender, toService); + console.log("----------------> START - message send to service", toService); + + setTimeout(() => { + console.log("DB_INIT - data loaded"); + instance.send(SEND_TO.db_init, "_") + }, 5000) + +}; + diff --git a/RVO15/flow/debug.js b/RVO15/flow/debug.js new file mode 100755 index 0000000..00cb259 --- /dev/null +++ b/RVO15/flow/debug.js @@ -0,0 +1,100 @@ +exports.id = 'debug'; +exports.title = 'Debug'; +exports.author = 'Peter Širka'; +exports.color = '#967ADC'; +exports.click = true; +exports.input = true; +exports.icon = 'bug'; +exports.version = '2.0.4'; +exports.options = { enabled: true, repository: false, type: 'data' }; +exports.readme = `# Debug + +Prints data to the debug tab.`; + +exports.html = `
+
+
+
@(Output type)
+
@(Path to the property (leave empty to show the whole data object))
+
@(A group name)
+
@(Enabled)
+
+
+
`; + +exports.install = function(instance) { + + instance.on('data', function(response) { + if (instance.options.enabled) { + + var opt = instance.options; + var rep = response.repository; + var val = response.data; + var id = response.id; + + switch (instance.options.type){ + case 'both': + var data = {}; + data.repository = rep; + data.data = val instanceof Error ? { error: val.message, stack: val.stack } : val; + instance.debug(safeparse(opt.property ? U.get(data, opt.property) : data), undefined, opt.group, id); + break; + case 'repository': + instance.debug(safeparse(opt.property ? U.get(rep, opt.property) : rep), undefined, opt.group, id); + break; + case 'data': + default: + if (val instanceof Error) + instance.debug({ error: val.message, stack: val.stack }, undefined, opt.group, id); + else + instance.debug(safeparse(opt.property ? U.get(val, opt.property) : val), undefined, opt.group, id); + break; + } + } + }); + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + instance.save(); + }); + + instance.on('options', function() { + instance.custom.status(); + }); + + instance.custom.status = function() { + instance.status(instance.options.enabled ? 'Enabled' : 'Disabled'); + }; + + instance.custom.status(); + + function safeparse(o) { + + if (o instanceof Buffer) + return o; + + if (o === undefined) + return 'undefined'; + + if (o === null) + return 'null'; + + var cache = []; + var str = JSON.stringify(o, function(key, value) { + if (typeof value === 'object' && value !== null) { + if (cache.indexOf(value) !== -1) { + try { + return JSON.parse(JSON.stringify(value)); + } catch (error) { + return; + } + } + cache.push(value); + } + return value; + }); + cache = null; + return JSON.parse(str); + } +}; diff --git a/RVO15/flow/designer.json b/RVO15/flow/designer.json new file mode 100755 index 0000000..580f5a3 --- /dev/null +++ b/RVO15/flow/designer.json @@ -0,0 +1,3102 @@ +{ + "tabs": [ + { + "name": "MAIN PUSH", + "linker": "main-push", + "id": "1612772287426", + "index": 0 + }, + { + "name": "CMD manager", + "linker": "cmd-manager", + "id": "1615551125555", + "index": 1 + }, + { + "name": "Devices", + "linker": "devices", + "id": "1611921777196", + "index": 2 + } + ], + "components": [ + { + "id": "1611951142547", + "component": "debug", + "tab": "1611921777196", + "name": "ERROR", + "x": 598, + "y": 60, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#DA4453", + "notes": "" + }, + { + "id": "1612776786008", + "component": "wsmqttpublish", + "tab": "1612772287426", + "name": "WS MQTT publish", + "x": 281.75, + "y": 174, + "connections": { + "0": [ + { + "index": "0", + "id": "1615551060773" + } + ], + "1": [ + { + "index": "0", + "id": "1618300858252" + }, + { + "index": "0", + "id": "1618558465485" + } + ], + "2": [ + { + "index": "0", + "id": "1634303685503" + } + ], + "3": [ + { + "index": "0", + "id": "1731068754606" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Connected", + "color": "green" + }, + "options": { + "username": "", + "clientid": "", + "port": "1883", + "host": "" + }, + "color": "#888600", + "notes": "" + }, + { + "id": "1612778461252", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "tb-push", + "x": 72.75, + "y": 328, + "connections": { + "0": [ + { + "index": "0", + "id": "1612783322136" + }, + { + "index": "1", + "id": "1612776786008" + }, + { + "index": "0", + "id": "1731068754606" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1612783322136", + "component": "debug", + "tab": "1612772287426", + "name": "to TB", + "x": 283.75, + "y": 324, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615551060773", + "component": "debug", + "tab": "1612772287426", + "name": "errors from MQTT Broker", + "x": 594, + "y": 57, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#DA4453", + "notes": "" + }, + { + "id": "1615563373927", + "component": "debug", + "tab": "1615551125555", + "name": "Debug", + "x": 755, + "y": 155, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#DA4453", + "notes": "" + }, + { + "id": "1615566865233", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "tb-push", + "x": 755, + "y": 248, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1615798582262", + "component": "debug", + "tab": "1615551125555", + "name": "CMD_debug", + "x": 755, + "y": 346, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615802995322", + "component": "debug", + "tab": "1611921777196", + "name": "Debug", + "x": 596.8833312988281, + "y": 566.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Disabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": false + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615809128443", + "component": "debug", + "tab": "1611921777196", + "name": "tempToTb", + "x": 595.8833312988281, + "y": 658.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615809595184", + "component": "virtualwireout", + "tab": "1611921777196", + "name": "tb-push", + "x": 597.8833312988281, + "y": 377.25, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1616165795916", + "component": "httproute", + "tab": "1615551125555", + "name": "POST /terminal", + "x": 135, + "y": 547, + "connections": { + "0": [ + { + "index": "0", + "id": "1684060205000" + }, + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Listening", + "color": "green" + }, + "options": { + "timeout": 10, + "cachepolicy": 0, + "cacheexpire": "5 minutes", + "size": 5, + "url": "/terminal", + "method": "POST", + "name": "", + "flags": [ + "id:1616165795916", + "post", + 10000 + ], + "emptyresponse": false + }, + "color": "#5D9CEC", + "notes": "### Configuration\n\n- __POST /terminal__\n- flags: \n- maximum request data length: __5 kB__\n- empty response: __false__\n- cache policy: __no cache__\n- cache expire: __5 minutes__", + "cloning": false + }, + { + "id": "1616165824813", + "component": "httpresponse", + "tab": "1615551125555", + "name": "HTTP Response", + "x": 753, + "y": 423, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "json" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1617104731852", + "component": "debug", + "tab": "1615551125555", + "name": "DIDO_Debug", + "x": 669, + "y": 1040, + "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": "turnOff line", + "x": 133, + "y": 1161, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "object", + "data": "{line: 3, command: \"turnOff\", force: true}" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1617115013095", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "tb-push", + "x": 669, + "y": 1150, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1617284749681", + "component": "trigger", + "tab": "1615551125555", + "name": "update profile / node", + "x": 112, + "y": 208, + "connections": { + "0": [ + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "data": "profile_nodes", + "datatype": "string" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1618235171399", + "component": "trigger", + "tab": "1615551125555", + "name": "tun tasks", + "x": 184, + "y": 279, + "connections": { + "0": [ + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "data": "run" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1618300858252", + "component": "debug", + "tab": "1612772287426", + "name": "wsmqtt-exit1", + "x": 597.8833312988281, + "y": 149, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1618393583970", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "to-cmd-manager", + "x": 668.8833312988281, + "y": 1269, + "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": 132.88333129882812, + "y": 367, + "connections": { + "0": [ + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "platform-rpc-call", + "color": "gray" + }, + "options": { + "wirename": "platform-rpc-call" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1618393759854", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "cmd_to_dido", + "x": 119.88333129882812, + "y": 1007, + "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": 752.8833312988281, + "y": 527, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "cmd_to_dido", + "color": "gray" + }, + "options": { + "wirename": "cmd_to_dido" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1618558465485", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "platform-rpc-call", + "x": 597.8833312988281, + "y": 247, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "platform-rpc-call", + "color": "gray" + }, + "options": { + "wirename": "platform-rpc-call" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1618572059773", + "component": "trigger", + "tab": "1615551125555", + "name": "turnOn line", + "x": 132, + "y": 1085, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "data": "{line: 1, command: \"turnOn\", force: true}", + "datatype": "object" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1619515097737", + "component": "cmd_manager", + "tab": "1615551125555", + "name": "CMD Manager", + "x": 452.1091003417969, + "y": 341.05455017089844, + "connections": { + "0": [ + { + "index": "0", + "id": "1615563373927" + } + ], + "1": [ + { + "index": "0", + "id": "1615566865233" + }, + { + "index": "0", + "id": "1615798582262" + } + ], + "2": [ + { + "index": "0", + "id": "1616165824813" + } + ], + "3": [ + { + "index": "0", + "id": "1618393827655" + } + ], + "4": [ + { + "index": "0", + "id": "1635936391935" + } + ], + "5": [ + { + "index": "0", + "id": "1757006030239" + }, + { + "index": "0", + "id": "1757006060377" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1619605019281", + "component": "httproute", + "tab": "1615551125555", + "name": "GET db", + "x": 173, + "y": 653, + "connections": { + "0": [ + { + "index": "0", + "id": "1684060205000" + }, + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Listening", + "color": "green" + }, + "options": { + "timeout": 5, + "cachepolicy": 0, + "cacheexpire": "5 minutes", + "size": 5, + "url": "/db", + "method": "GET", + "name": "", + "flags": [ + "id:1619605019281", + "get", + 5000 + ] + }, + "color": "#5D9CEC", + "notes": "### Configuration\n\n- __GET /db__\n- flags: undefined\n- maximum request data length: __5 kB__\n- empty response: __undefined__\n- cache policy: __no cache__\n- cache expire: __5 minutes__", + "cloning": false + }, + { + "id": "1619784672383", + "component": "trigger", + "tab": "1615551125555", + "name": "turnOnAlarm", + "x": 120, + "y": 1234, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "object", + "data": "{command: \"turnOnAlarm\"}" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1619784812964", + "component": "trigger", + "tab": "1615551125555", + "name": "turnOffAlarm", + "x": 118, + "y": 1307, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "object", + "data": "{command: \"turnOffAlarm\"}" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1621340721628", + "component": "virtualwireout", + "tab": "1611921777196", + "name": "modbus_to_dido", + "x": 599, + "y": 471, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "modbus_to_dido", + "color": "gray" + }, + "options": { + "wirename": "modbus_to_dido" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1622640022885", + "component": "httproute", + "tab": "1615551125555", + "name": "POST /db_connector", + "x": 98, + "y": 1586, + "connections": { + "0": [ + { + "index": "0", + "id": "1622640073521" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Listening", + "color": "green" + }, + "options": { + "timeout": 5, + "cachepolicy": 0, + "cacheexpire": "5 minutes", + "size": 5, + "url": "/db_connector", + "method": "POST", + "flags": [ + "id:1622640022885", + "post", + 5000 + ] + }, + "color": "#5D9CEC", + "notes": "### Configuration\n\n- __POST /db_connector__\n- flags: \n- maximum request data length: __5 kB__\n- empty response: __undefined__\n- cache policy: __no cache__\n- cache expire: __5 minutes__", + "cloning": false + }, + { + "id": "1622640073521", + "component": "db_connector", + "tab": "1615551125555", + "name": "DbConnector", + "x": 372, + "y": 1572, + "connections": { + "1": [ + { + "index": "0", + "id": "1622641420685" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "edge": "undefined" + }, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1622641420685", + "component": "httpresponse", + "tab": "1615551125555", + "name": "HTTP Response", + "x": 596, + "y": 1586, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1634303504177", + "component": "monitormemory", + "tab": "1612772287426", + "name": "RAM", + "x": 69.88333129882812, + "y": 888.5, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465281992" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "858.88 MB / 985.68 MB", + "color": "gray" + }, + "options": { + "enabled": true, + "interval": 30000 + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1634303533779", + "component": "monitordisk", + "tab": "1612772287426", + "name": "disk", + "x": 70.88333129882812, + "y": 982.5, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465821120" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "5.78 GB / 7.26 GB", + "color": "gray" + }, + "options": { + "enabled": true, + "path": "/", + "interval": 30000 + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1634303595494", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "send-to-services", + "x": 51.883331298828125, + "y": 1400.5, + "connections": { + "0": [ + { + "index": "0", + "id": "1634463186563" + }, + { + "index": "1", + "id": "1634488120710" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1634303602169", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "send-to-services", + "x": 426.8833312988281, + "y": 878.5, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1634303685503", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "send-to-services", + "x": 600.8833312988281, + "y": 341.5, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1634303743260", + "component": "httprequest", + "tab": "1612772287426", + "name": "192.168.252.2:8004/sentmessage", + "reference": "", + "x": 506.8833312988281, + "y": 1331.7333374023438, + "connections": { + "0": [ + { + "index": "0", + "id": "1635327431236" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "url": "http://192.168.252.2:8004/sentmessage", + "method": "POST", + "stringify": "json" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1634463186563", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 305.75, + "y": 1442, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634464580289", + "component": "code", + "tab": "1612772287426", + "name": "Code", + "x": 245, + "y": 787, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465243324" + }, + { + "index": "0", + "id": "1634303602169" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "keepmessage": true, + "code": "let response = {};\nresponse.cpu = value.cpu;\nresponse.uptime = value.uptime;\n\nsend(0, response);", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1634465243324", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 428, + "y": 784, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634465281992", + "component": "code", + "tab": "1612772287426", + "name": "Code", + "x": 245, + "y": 884, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465338103" + }, + { + "index": "0", + "id": "1634303602169" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "keepmessage": true, + "code": "value.sender = \"ram\";\n\nlet response = {};\n\nresponse.memory_total = Math.round(value.total / (1024 ** 2));\nresponse.memory_free = Math.round(value.free / (1024 ** 2));\nresponse.memory_used = Math.round(value.used / (1024 ** 2));\n\nsend(0, response);", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1634465338103", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 429, + "y": 976, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634465821120", + "component": "code", + "tab": "1612772287426", + "name": "Code", + "x": 245, + "y": 978, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465892500" + }, + { + "index": "0", + "id": "1634303602169" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "keepmessage": true, + "code": "value.sender = \"hdd\";\n\nlet response = {};\n\nresponse.hdd_total = Math.round(value.total / (1024 ** 2));\nresponse.hdd_free = Math.round(value.free / (1024 ** 2));\nresponse.hdd_used = Math.round(value.used / (1024 ** 2));\n\nsend(0, response);", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1634465892500", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 432, + "y": 1068, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634484067516", + "component": "debug", + "tab": "1612772287426", + "name": "Send info", + "x": 513, + "y": 1441, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634488120710", + "component": "infosender", + "tab": "1612772287426", + "name": "Info sender", + "x": 301, + "y": 1336, + "connections": { + "0": [ + { + "index": "0", + "id": "1634484067516" + }, + { + "index": "0", + "id": "1634303743260" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "edge": "undefined" + }, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1635327431236", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 837.8833312988281, + "y": 1325.5, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1635936391935", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "send-to-services", + "x": 753, + "y": 623, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1637069803394", + "component": "monitorconsumption", + "tab": "1612772287426", + "name": "CPU", + "x": 69, + "y": 791, + "connections": { + "0": [ + { + "index": "0", + "id": "1634464580289" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "49.2% / 69.91 MB", + "color": "gray" + }, + "options": { + "monitorfiles": true, + "monitorconnections": true, + "monitorsize": true, + "monitorconsumption": true, + "enabled": true, + "interval": 30000 + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1683664161036", + "component": "debug", + "tab": "1615551125555", + "name": "CMDtoDIDO", + "x": 392, + "y": 1012, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1683981346282", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "from-dido-controller", + "x": 112, + "y": 459, + "connections": { + "0": [ + { + "index": "0", + "id": "1684055037116" + }, + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "from-dido-controller", + "color": "gray" + }, + "options": { + "wirename": "from-dido-controller" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1684055037116", + "component": "debug", + "tab": "1615551125555", + "name": "from dido to cmd", + "x": 451, + "y": 532, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1684060205000", + "component": "debug", + "tab": "1615551125555", + "name": "HTTP routes", + "x": 450, + "y": 639, + "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": "MDBToDido", + "x": 598, + "y": 147, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1699963668903", + "component": "dido_controller", + "tab": "1615551125555", + "name": "DIDO_Controller", + "x": 397, + "y": 1131, + "connections": { + "0": [ + { + "index": "0", + "id": "1617104731852" + } + ], + "1": [ + { + "index": "0", + "id": "1617104731852" + }, + { + "index": "0", + "id": "1617115013095" + } + ], + "2": [ + { + "index": "0", + "id": "1618393583970" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "edge": "undefined" + }, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1699964678894", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "modbus_to_dido", + "x": 96, + "y": 924, + "connections": { + "0": [ + { + "index": "0", + "id": "1699963668903" + }, + { + "index": "0", + "id": "1699964793925" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "modbus_to_dido", + "color": "gray" + }, + "options": { + "wirename": "modbus_to_dido" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1699964793925", + "component": "debug", + "tab": "1615551125555", + "name": "modbusToDido", + "x": 388, + "y": 920, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1699965957410", + "component": "modbus_reader", + "tab": "1611921777196", + "name": "Modbus reader", + "x": 232, + "y": 175, + "connections": { + "0": [ + { + "index": "0", + "id": "1611951142547" + } + ], + "1": [ + { + "index": "0", + "id": "1621340721628" + }, + { + "index": "0", + "id": "1684179110403" + }, + { + "index": "0", + "id": "1717441414646" + } + ], + "2": [ + { + "index": "0", + "id": "1615809595184" + }, + { + "index": "0", + "id": "1714752862828" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1700411878636", + "component": "thermometer", + "tab": "1611921777196", + "name": "Thermometer", + "x": 234.75, + "y": 444, + "connections": { + "0": [ + { + "index": "0", + "id": "1615802995322" + } + ], + "1": [ + { + "index": "0", + "id": "1615809595184" + }, + { + "index": "0", + "id": "1615809128443" + } + ], + "2": [ + { + "index": "0", + "id": "1621340721628" + }, + { + "index": "0", + "id": "1732889185927" + }, + { + "index": "0", + "id": "1717441414646" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#5CB36D", + "notes": "" + }, + { + "id": "1714752862828", + "component": "debug", + "tab": "1611921777196", + "name": "MDBToTb", + "x": 766, + "y": 324, + "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": 764.0833282470703, + "y": 222, + "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\telse if(value.status === \"NOK-thermometer\")\n\t{\n\t\tsend(0, {\"thermometer\": \"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\telse if(value.values.hasOwnProperty(\"temperature\"))\n\t{\n\t\tsend(0, {\"thermometer\": \"OK\"});\n\t}\n}", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1717442627834", + "component": "debug", + "tab": "1611921777196", + "name": "modbus service", + "x": 966.0833282470703, + "y": 165, + "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": 968.0833282470703, + "y": 268, + "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": 88.75, + "y": 1685, + "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": 296, + "y": 1671, + "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\", \"Flow has been restarted\", \"Node db has changed\"]", + "types": "[\"emergency\", \"critical\", \"error\", \"alert\"]", + "name": "" + }, + "color": "#30E193", + "notes": "" + }, + { + "id": "1718016073501", + "component": "httprequest", + "tab": "1612772287426", + "name": "http://192.168.252.2:8004/slack", + "x": 495, + "y": 1753, + "connections": { + "0": [ + { + "index": "0", + "id": "1718016086212" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "url": "http://192.168.252.2:8004/slack", + "method": "POST", + "stringify": "json" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1718016086212", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 832, + "y": 1664, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "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": 87, + "y": 1591, + "connections": { + "0": [ + { + "index": "0", + "id": "1718016052341" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "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\": \"\" } } } ] }", + "datatype": "object" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1729855334955", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "platform-rpc-call", + "x": 599.9333343505859, + "y": 541.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "platform-rpc-call", + "color": "gray" + }, + "options": { + "wirename": "platform-rpc-call" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1729855371093", + "component": "debug", + "tab": "1612772287426", + "name": "rpc cloud", + "x": 601.9333343505859, + "y": 440.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1731068658334", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 75.75, + "y": 184, + "connections": { + "0": [ + { + "index": "0", + "id": "1612776786008" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731068754606", + "component": "cloudmqttconnect", + "tab": "1612772287426", + "name": "MQTT to senica-prod01", + "x": 284.75, + "y": 452, + "connections": { + "1": [ + { + "index": "0", + "id": "1729855371093" + }, + { + "index": "0", + "id": "1729855334955" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Connected", + "color": "green" + }, + "options": { + "username": "", + "clientid": "", + "port": "2764", + "host": "192.168.252.2", + "topic": "" + }, + "color": "#888600", + "notes": "" + }, + { + "id": "1731069001548", + "component": "db_init", + "tab": "1612772287426", + "name": "DB Initialization", + "x": 1003.75, + "y": 240.25, + "connections": { + "0": [ + { + "index": "0", + "id": "1731069033416" + } + ], + "1": [ + { + "index": "0", + "id": "1747561603739" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#888600", + "notes": "" + }, + { + "id": "1731069033416", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "db-init", + "x": 1244.75, + "y": 233.25, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069059135", + "component": "showdb", + "tab": "1612772287426", + "name": "Show db data", + "x": 1186.75, + "y": 821.25, + "connections": { + "0": [ + { + "index": "0", + "id": "1731069079243" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#888600", + "notes": "" + }, + { + "id": "1731069079243", + "component": "debug", + "tab": "1612772287426", + "name": "dbData", + "x": 1390.75, + "y": 870.25, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1731069116691", + "component": "trigger", + "tab": "1612772287426", + "name": "settings", + "x": 934.75, + "y": 669.75, + "connections": { + "0": [ + { + "index": "0", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069131637", + "component": "trigger", + "tab": "1612772287426", + "name": "relaysData", + "x": 876.75, + "y": 733.75, + "connections": { + "0": [ + { + "index": "1", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069137374", + "component": "trigger", + "tab": "1612772287426", + "name": "nodesData", + "x": 852.75, + "y": 794.75, + "connections": { + "0": [ + { + "index": "2", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069179846", + "component": "trigger", + "tab": "1612772287426", + "name": "pinsData", + "x": 850.75, + "y": 861.75, + "connections": { + "0": [ + { + "index": "3", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069192937", + "component": "trigger", + "tab": "1612772287426", + "name": "sample data", + "x": 857.75, + "y": 928.75, + "connections": { + "0": [ + { + "index": "4", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069264443", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 63.75, + "y": 1279, + "connections": { + "0": [ + { + "index": "0", + "id": "1634488120710" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069334626", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "db-init", + "x": 172.88333129882812, + "y": 129, + "connections": { + "0": [ + { + "index": "0", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069548145", + "component": "virtualwirein", + "tab": "1611921777196", + "name": "db-init", + "x": 46.75, + "y": 192, + "connections": { + "0": [ + { + "index": "0", + "id": "1699965957410" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069567152", + "component": "virtualwirein", + "tab": "1611921777196", + "name": "db-init", + "x": 44.75, + "y": 465, + "connections": { + "0": [ + { + "index": "0", + "id": "1700411878636" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731070156936", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "db-init", + "x": 126.88333129882812, + "y": 1377, + "connections": { + "0": [ + { + "index": "2", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731234189516", + "component": "trigger", + "tab": "1612772287426", + "name": "monitor.txt", + "x": 882.75, + "y": 991.75, + "connections": { + "0": [ + { + "index": "5", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731234189551", + "component": "trigger", + "tab": "1612772287426", + "name": "err.txt", + "x": 904.75, + "y": 1053.75, + "connections": { + "0": [ + { + "index": "6", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1732700042559", + "component": "nodesdb_change_check", + "tab": "1612772287426", + "name": "Nodes DB change check", + "x": 266.8833312988281, + "y": 1980.2333984375, + "connections": { + "0": [ + { + "index": "0", + "id": "1732700071298" + }, + { + "index": "0", + "id": "1732700642917" + } + ], + "1": [ + { + "index": "0", + "id": "1759958914348" + }, + { + "index": "0", + "id": "1759959003114" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#888600", + "notes": "" + }, + { + "id": "1732700057052", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 76.75, + "y": 1988, + "connections": { + "0": [ + { + "index": "0", + "id": "1732700042559" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1732700071298", + "component": "debug", + "tab": "1612772287426", + "name": "nodesChange", + "x": 571.8833312988281, + "y": 2018.2333984375, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1732700642917", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "tb-push", + "x": 567.8833312988281, + "y": 1933, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1732889185927", + "component": "debug", + "tab": "1611921777196", + "name": "tempToDido", + "x": 594.8833312988281, + "y": 753, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1733574412965", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 72.75, + "y": 474, + "connections": { + "0": [ + { + "index": "1", + "id": "1731068754606" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1747561603739", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "send-to-services", + "x": 1243.8833312988281, + "y": 334.5, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1747562867845", + "component": "comment", + "tab": "1612772287426", + "name": "FLOW STARTING POINT", + "x": 1003.5666656494141, + "y": 178, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#704cff", + "notes": "" + }, + { + "id": "1749211698385", + "component": "trigger", + "tab": "1612772287426", + "name": "deviceStatus", + "x": 911.75, + "y": 1116.75, + "connections": { + "0": [ + { + "index": "7", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1757006030239", + "component": "httprequest", + "tab": "1615551125555", + "name": "192.168.252.2:8015/daily_report", + "x": 756.5666656494141, + "y": 715.4499969482422, + "connections": { + "0": [ + { + "index": "0", + "id": "1757006045804" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "stringify": "json", + "method": "POST", + "url": "http://192.168.252.2:8015/daily_report" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1757006045804", + "component": "debug", + "tab": "1615551125555", + "name": "ddd", + "x": 1091.566665649414, + "y": 711.4499969482422, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1757006060377", + "component": "debug", + "tab": "1615551125555", + "name": "reportDebug", + "x": 749.5666656494141, + "y": 799.4499969482422, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1759958914348", + "component": "httprequest", + "tab": "1612772287426", + "name": "http://192.168.252.2:8015/node_numbers", + "x": 571, + "y": 2111, + "connections": { + "0": [ + { + "index": "0", + "id": "1759958927094" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "stringify": "json", + "method": "POST", + "url": "http://192.168.252.2:8015/node_numbers" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1759958927094", + "component": "debug", + "tab": "1612772287426", + "name": "nodesChangeCloud", + "x": 951.8833312988281, + "y": 2109.2333984375, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1759959003114", + "component": "debug", + "tab": "1612772287426", + "name": "nodeChangeCloud1", + "x": 574, + "y": 2218, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1760020290879", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 84.75, + "y": 1787, + "connections": { + "0": [ + { + "index": "1", + "id": "1718016052341" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + } + ], + "version": 615 +} diff --git a/RVO15/flow/dido_controller.js b/RVO15/flow/dido_controller.js new file mode 100755 index 0000000..d16fb19 --- /dev/null +++ b/RVO15/flow/dido_controller.js @@ -0,0 +1,1486 @@ +exports.id = 'dido_controller'; +exports.title = 'DIDO_Controller'; +exports.version = '2.0.0'; +exports.group = 'Worksys'; +exports.color = '#2134B0'; +exports.input = 3; +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 + +state_of_main_switch - reportovat stav hlaveho istica : 0-> off 1-> on +rotary_switch_state - sem by sa mal reportovat stav vstupov manual a auto pola nasledovnej logiky: Manual = 1 a Auto = 0 -> Manu +Manual = 0 a Auto = 0 -> Off, Manual = 0 a Auto = 1 -> Automatic + +door_condition - pin 6, dverový kontakt -> 1 -> vyreportuje Closed, 0 -> vyreportuje Ope +twilight_sensor - hodnotu, ktoru vracia ten analogovy vstup (17) treba poslat sem ako float number. Zrejme tu potom pridame nejaky koeficient prevodu na luxy + +Na kazdu liniu +state_of_breaker - podla indexu istica sa reportuje jeho stav, teda istic na liniu 1: 0-> off, 1-> on +state_of_contactor - podla indexu stkaca sa reportuje jeho stav, teda stykac 1 na liniu 1: 0-> off, 1-> on +*/ + +const { errLogger, logger, monitor } = require('./helper/logger'); +const SerialPort = require('serialport'); +const WebSocket = require('ws'); +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 errorHandler = require('./helper/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 hasMainSwitch; + +let alarmStatus = "OFF"; + +const SEND_TO = { + debug: 0, + tb: 1, + cmd_manager: 2 +} + + +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 = {}; + let rsPortReceivedData = []; + + //to be able to get proper twilight values + let twilight_sensor_interval = 5;//minutes + let twilight_sensor = []; + const twilight_sensor_array = []; + let twilightError = false; + + monitor.info("DIDO_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-we make it global to see it from outside + FLOW.deviceStatus = { //key is device name: temperature,.... + "state_of_main_switch": "Off", //Hlavny istic (alebo druhy dverovy kontakt) + "rotary_switch_state": "Off", //Prevadzkovy + "door_condition": "closed", //Dverový kontakt + "em": "OK", //elektromer rvo + "temperature": "OK", //templomer + "battery": "OK", //Bateria + "power_supply": "OK", //Zdroj + "master_node": "OK", //MN - GLOBALS.settings.masterNodeIsResponding + "no_voltage": "OK", //GLOBALS.settings.no_voltage - vypadok napatia na faze + "state_of_breaker": {}, //"Off",//Istic + "state_of_contactor": {}, //"Off",//Stykac + "twilight_sensor": "OK" //lux sensor + }; + let deviceStatus = FLOW.deviceStatus; + + + function main() { + + GLOBALS = FLOW.GLOBALS; + SETTINGS = FLOW.GLOBALS.settings; + rvoTbName = SETTINGS.rvoTbName; + pinsData = GLOBALS.pinsData; + relaysData = GLOBALS.relaysData; + + tbHandler = new DataToTbHandler(SEND_TO.tb); + tbHandler.setSender(exports.title); + + controller_type = SETTINGS.controller_type; //"lm" or "unipi" + hasMainSwitch = SETTINGS.has_main_switch; + + if (controller_type == "") controller_type = "lm"; + + 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, "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; + } + } + + //report RVO version relaysData[0].tbname; + let values = {}; + values["edge_fw_version"] = SETTINGS.edge_fw_version; + values["maintenance_mode"] = SETTINGS.maintenance_mode; + + sendTelemetry(values, rvoTbName); + + 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); + } + + + function handleRsPort() { + + if (rsPort) { + rsPort.removeAllListeners(); + rsPort = null; + } + + //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('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) { + if (!err) { + monitor.info(exports.title + "--->Digital in_out has been set (runSyncExec was sucessfull)"); + + turnAlarm("off"); + 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('error', err => { + let message = "Dido: rsPort error: " + err.message; + logger.debug(message); + monitor.info(message); + errorHandler.sendMessageToService(message); + }) + + rsPort.on("close", () => { + let message = "Dido: rsPort closed - reconnecting ..."; + logger.debug(message); + monitor.info(message); + setTimeout(handleRsPort, 1000); + }) + + rsPort.open(); + } + + + function handleWebSocket() { + + if (ws) { + ws.removeAllListeners(); + ws = null; + } + + //to keep websocket opened, we send request every 150 seconds + let startRequests = null; + + console.log("handleWebSocket function called"); + ws = new WebSocket('ws:/0.0.0.0:1234/ws'); + + ws.onopen = function open() { + + instance.send(0, exports.title + " running"); + turnAlarm("off"); + + initialSetting(); + + setTimeout(function() { ws.send(JSON.stringify({ cmd: "all" })) }, 5000); + // we request dev info about neuron device from evok to keep websocket connection alive + // for some reason this request returns no data, but connection keeps alive + startRequests = setInterval(() => { + ws.send(JSON.stringify({ "cmd": "filter", "dev": ["neuron"] })); + }, 150000) + }; + + + // 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 = async 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; + + 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 => { + logger.debug('Dido: websocket error', err); + }) + + ws.onclose = function() { + logger.debug('Dido: websocket onclose, reconnecting...') + clearInterval(startRequests); + setTimeout(handleWebSocket, 1000); + } + } + + 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 turnAlarm(onOrOff) { + let value = 0; + if (onOrOff == "on") value = 1; + + if (value == 1 && SETTINGS.maintenance_mode) return; + + alarmStatus = "OFF"; + if (value == 1) alarmStatus = "ON"; + + if (rsPort) { + let arr = [0x55]; + arr.push(13); + arr.push(0); + arr.push(value); + + rsPort.write(Buffer.from(arr), function(err) { + logger.debug(`sirena - ${onOrOff}`); + }); + } + else if (ws) { + let cmd = { "cmd": "set", "dev": "relay", "circuit": "1_01", "value": value }; + ws.send(JSON.stringify(cmd)); + logger.debug(`sirena - ${onOrOff}`); + } + } + + + 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") { + bits.push(0); + } + else bits.push(1); + + if (deviceStatus["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); + } + + + // turn line on or off + function turnLine(onOrOff, line, pin, force, info) { + //onOrOff => "on" or "off" + let value = 0; + if (onOrOff == "on") value = 1; + + if (force == undefined) force = false; + + if (line == 0) { + if (value == 1 && alarmStatus == "ON") turnAlarm("off"); + SETTINGS.maintenance_mode = value ? true : false; + + 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); + return; + } + + if (pin === undefined) pin = getPin(line); + + if (pin === undefined) { + errLogger.error("pin is undefined!", line); + return; + } + + if (!force) { + if (relaysData[line].contactor == value) { + instance.send(SEND_TO.debug, `line is already ${onOrOff} ` + line); + logger.debug(`Dido: turnLine: line is already ${onOrOff} `, line); + return; + } + } + + // if(!rsPort.isOpen && !ws) + if (!rsPort && !ws) { + errLogger.error("Dido - port or websocket is not opened"); + return; + } + + if (rsPort) { + let arr = [0x55]; + arr.push(pin); + arr.push(0); + arr.push(value); + + rsPort.write(Buffer.from(arr), function(err) { + if (err === undefined) { + monitor.info(`Dido: turnLine ${onOrOff} zapisal do rsPort-u`, line, pin, arr, info); + switchLogic(arr); + } + else { + monitor.info(`Dido: turnLine ${onOrOff} WRITE error`, err); + } + }); + + } + else if (ws) { + //pin = "relay1_03" or "input1_01" ... we must make just "1_01" with slice method + monitor.info(`Dido: turnLine ${onOrOff} - (line, pin, force)`, line, pin, force, info); + let cmd = { "cmd": "set", "dev": "relay", "circuit": pin.slice(5), "value": value }; + ws.send(JSON.stringify(cmd)); + } + + //if rvo is 24/7, it has just one switching profile point at 13:00. we do not want to send notification as it repeats every day. + //const d = new Date(); + //if(d.getHours() != 13) sendNotification("Dido_controller: ", SETTINGS.rvoTbName, "switching_profile_point_applied_to_line", { line: line, value: onOrOff }, "", SEND_TO.tb, instance); + } + + + // 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; + + // 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) { + const status = flowdata.data.status; + if (status == "NOK-twilight_sensor") { + deviceStatus["twilight_sensor"] = "NOK"; + } + else if (status == "NOK-em340" || status == "NOK-em111") { + deviceStatus["em"] = "NOK"; + } + else if (status == "NOK-thermometer") { + deviceStatus["temperature"] = "NOK"; + } + } + else if ("values" in flowdata.data) { + 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" + } + else if (values.hasOwnProperty("temperature")) { + deviceStatus["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"; + } + + sendTelemetry(values, rvoTbName); + } + + sendRvoStatus(); + }) + + + + + // we expect array as flowdata.data + instance.on("1", flowdata => { + + //console.log(flowdata.data); + + if (!flowdata.data instanceof Object) return; + + let obj = flowdata.data; + let line = obj.line; + 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"); + }) + + + function calculateStateCode() { + + let bits = []; + + //Hlavny istic - state_of_main_switch => v rvo senica je to druhy door pre silovu cast (EM) + if (deviceStatus["state_of_main_switch"] === "closed" || deviceStatus["state_of_main_switch"] === "Off") { + bits.push(0); + } + else { + bits.push(1); + } + + //Prevadzkovy mod - Manual, Off, Automatic, maintenance_mode = true/false // DAVA 2 BITY + if (!SETTINGS.maintenance_mode) { + if (deviceStatus["rotary_switch_state"] === "Manual") { + bits.push(0); + bits.push(1); + } + + if (deviceStatus["rotary_switch_state"] === "Automatic") { + bits.push(0); + bits.push(0); + } + + if (deviceStatus["rotary_switch_state"] === "Off") { + bits.push(1); + bits.push(0); + } + } + else { + bits.push(1); + bits.push(1); + } + + //Dverovy kontakt + if (deviceStatus["door_condition"] === "closed") { + bits.push(0); + } + else { + bits.push(1); + } + + //EM + if (deviceStatus["em"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //Teplomer + if (deviceStatus["temperature"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //Batéria + if (deviceStatus["battery"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //Zdroj + if (deviceStatus["power_supply"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //MN + if (deviceStatus["master_node"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //výpadok napätia na fáze + if (deviceStatus["no_voltage"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + if (deviceStatus["twilight_sensor"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + // doplnime do 16 bitov (2 byty) + for (let i = bits.length; i < 16; i++) { + bits.push(0); + } + + // console.log("calculateStateCode - deviceStatus", deviceStatus); + // 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; + } + + + async function sendRvoStatus() { + + if (SETTINGS === undefined) return; + SETTINGS.masterNodeIsResponding ? deviceStatus["master_node"] = "OK" : deviceStatus["master_node"] = "NOK"; + + 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 pinsForRvoStatus(controllerType, hasMainSwitch) { + + let pins = []; + + if (controllerType === "lm") { + pins = [1, 4, 6]; + if (hasMainSwitch === 1) { + pins = [4, 6]; + } + } else if (controllerType === "unipi") { + pins = ["input1_01", "input1_04", "input1_05"]; + if (hasMainSwitch === 1) { + pins = ["input1_01", "input1_04"]; + } + } + + return pins; + } + + + function checkRvoStatus() { + + // 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 + //set RVO state + let status = "OK"; + + for (const [key, value] of Object.entries(deviceStatus)) { + if (["em", "twilight_sensor", "temperature", "master_node"].includes(key) && value === "NOK") status = "NOK"; + } + + if (status === "OK") { + + let pinIndexes = pinsForRvoStatus(controller_type, hasMainSwitch); + + for (const pinIndex of pinIndexes) { + if (previousValues[pinIndex] === 0) { + if ((pinIndex === 6 || pinIndex === 'input1_01' || pinIndex === 'input1_05') && SETTINGS.maintenance_mode) continue; + status = "NOK"; + break; + } + } + } + + // battery status. If value is 1 - battery is NOK + if (previousValues[5] === 1) status = "NOK"; + if (SETTINGS.no_voltage.size > 0) status = "NOK"; + + // console.log("rvo status",status) + return status; + } + + + // we pass array to function in case of rsPort ==> switchLogic([55,3,0,1]) ==> [[55,3,0,1]] + // we pass two values in case of websocket ==> switchLogic("relay1_03",1) ==> ["relay1_03",1] + const switchLogic = (...args) => { + + let values = {}; + let pinIndex, newPinValue, twilight; + + //data from rsPort + if (args.length == 1) { + pinIndex = args[0][1] + 1; + if (pinIndex === 17) pinIndex--; + newPinValue = args[0][3]; + twilight = args[0][2]; + } + //data from websocket + else { + pinIndex = args[0]; + newPinValue = args[1]; + } + + 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; + + //default value + let value = "On"; + if (newPinValue === 0) value = "Off"; + + //Hlavny istic + if (type === "state_of_main_switch" && hasMainSwitch) { + if (newPinValue === 0 && newPinValue !== previousValues[pinIndex]) { + sendNotification("switchLogic", rvoTbName, "main_switch_has_been_turned_off", {}, "", SEND_TO.tb, instance, "state_of_main_switch"); + 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"); + deviceStatus["state_of_main_switch"] = "On"; + } + } + + //Prevadzkovy mod + 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"; + + deviceStatus["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, "power_supply_has_disconnected_input", {}, "", SEND_TO.tb, instance, "power_supply"); + + deviceStatus["power_supply"] = "NOK"; + } + else if (newPinValue === 1 && newPinValue !== previousValues[pinIndex]) { + sendNotification("switchLogic", rvoTbName, "power_supply_works_correctly", {}, "", SEND_TO.tb, instance, "power_supply"); + + deviceStatus["power_supply"] = "OK"; + } + } + + //Bateria - 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"); + + deviceStatus["battery"] = "NOK"; + } + else if (newPinValue === 0 && newPinValue !== previousValues[pinIndex]) { + sendNotification("switchLogic", rvoTbName, "battery_level_is_ok", {}, "", SEND_TO.tb, instance, "battery_level"); + + deviceStatus["battery"] = "OK"; + } + } + + //Dverovy kontakt - pin 6 + //! Ak je rvo s dvoma dverovymi kontaktami, ked pride z evoku signal z input1_05, co bol predytm "state_of_main switch" handlujeme ho teraz ako 'door_condition' + else if (type == "door_condition" || type === "state_of_main_switch") { + newPinValue === 0 ? value = "open" : value = "closed"; + + let door = "door_main"; + if (type === "state_of_main_switch") door = "door_em"; + + if (value === "open") { + if (SETTINGS.maintenance_mode) { + sendNotification("switchLogic", rvoTbName, door + "_open", {}, "", SEND_TO.tb, instance, door); + } else { + sendNotification("switchLogic", rvoTbName, door + "_open_without_permission", {}, "", SEND_TO.tb, instance, door); + + // 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 (value === "closed") { + if (alarmStatus == "ON") turnAlarm("off"); + sendNotification("switchLogic", rvoTbName, door + "_close", {}, "", SEND_TO.tb, instance, door); + } + + deviceStatus[type] = value; + } + + //lux sensor + else if (type == "twilight_sensor") { + //! TODO - to show nok status, if lux value is not changing more then 10 times. + //Daylight is far more than 1000. So most of the day, when it is sunshine comes just value 1000. But lux sensor is not NOK. + //This is not the case in LM. If value from LM is the same 10x, there is 99% possibility, that sensor is NOK. + value = newPinValue; + + if (controller_type === 'lm') { + value = parseFloat(newPinValue + (256 * twilight)); + + 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 && !twilightError) { + twilightError = true; + let value = twilight_sensor_array.shift(); + + newPinValue = 0; + } + else if (set.size !== 1 && twilightError) { + //sendNotification("switchLogic", rvoTbName, 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) { + 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); + } + } + + 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); + } + + deviceStatus["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 (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 }); + + //mame iba 3 istice. vyreportujeme a ohandlujeme liniu na tom istom istici ako paralelna linia (napr linia 1, paralelna s nou je linia 4, key je string "4") + // ak je 7 linii, na 1 istici je linia 1,4,7 + + if (line == 1) { + + const lineOnSameBraker = [4, 7]; + + for (var i = 0; i < lineOnSameBraker.length; i++) { + if (!relaysData.hasOwnProperty(lineOnSameBraker[i])) continue; + + 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; + reportLineStatus(lineOnSameBraker[i]); + + values[type] = value; + const tbname = relaysData[lineOnSameBraker[i]].tbname; + sendTelemetry(values, tbname); + + delete values[type]; + } + + } + else { + const lineOnSameBraker = line + 3 + ""; + + if (relaysData.hasOwnProperty(lineOnSameBraker)) { + 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; + reportLineStatus(line + 3); + + values[type] = value; + const tbname = relaysData[lineOnSameBraker].tbname; + sendTelemetry(values, tbname); + + delete values[type]; + } + } + + } + + if (value == "Off") values["status"] = "NOK"; + deviceStatus["state_of_breaker"][line] = value; + + reportLineStatus(line); + } + else return; + + values[type] = value; + + if (type == "rotary_switch_state") { + if (SETTINGS.maintenance_mode) value = "maintenance"; + value = value.toLowerCase(); + values["power_mode"] = value; + } + + if (newPinValue != previousValues[pinIndex]) previousValues[pinIndex] = newPinValue; + if (Object.keys(values).length > 0 && tbname) sendTelemetry(values, tbname); + } + + + function sendTelemetry(values, tbname, date = Date.now()) { + let dataToTb = { + [tbname]: [ + { + "ts": date, + "values": values + } + ] + }; + + tbHandler.sendToTb(dataToTb, instance); + } + + + function isObject(item) { + return (typeof item === "object" && !Array.isArray(item) && item !== null); + } + +} //end of 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 +// *|input1_01|state_of_main_switch|0|........... +// *|input1_02|rotary_switch_state|0|........... +// *|input1_03|rotary_switch_state|0|........... +// *|intut1_04|power_supply|0|........... +// *|input1_05|door_condition|0|........... +// *|input1_06|state_of_breaker|1|........... +// *|input1_07|state_of_breaker|2|........... +// *|input1_08|state_of_breaker|3|........... +// *|relay1_02|state_of_contactor|1|........... +// *|relay1_03|state_of_contactor|2|........... +// *|relay1_04|state_of_contactor|3|........... +// *|287D8776E0013CE9|temperature|0|........... + + +//! pins_data --> from UNIPI +// { +// 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 } +// } + +//! relays_data +// { +// '0': { +// line: 0, +// tbname: 'KjbN4q7JPZmexgdnz2yKQ98YAWwO0Q3BMX6ERLoV', +// contactor: 1, +// profile: '' +// }, +// '1': { +// line: 1, +// tbname: 'RMgnK93rkoAazbqdQ4yBG95Z1YXGx6pmwBeVEP2O', +// contactor: 0, +// profile: '{"intervals":[{"value":0,"end_time":"20:00","start_time":"13:00"},{"value":1,"end_time":"10:00","start_time":"20:00"},{"value":0,"end_time":"10:20","start_time":"10:00"},{"value":1,"end_time":"10:40","start_time":"10:20"},{"value":0,"end_time":"11:00","start_time":"10:40"},{"value":1,"end_time":"11:30","start_time":"11:00"},{"value":0,"end_time":"11:50","start_time":"11:30"},{"value":1,"end_time":"13:00","start_time":"11:50"}],"astro_clock":false,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' +// }, +// '2': { +// line: 2, +// tbname: 'dlE1VQjYrNx9gZRmb38gG08oLBO4qaAk2M6JPnG7', +// contactor: 0, +// profile: '{"intervals":[{"value":0,"end_time":"20:00","start_time":"13:00"},{"value":1,"end_time":"10:00","start_time":"20:00"},{"value":0,"end_time":"10:20","start_time":"10:00"},{"value":1,"end_time":"10:40","start_time":"10:20"},{"value":0,"end_time":"11:00","start_time":"10:40"},{"value":1,"end_time":"11:30","start_time":"11:00"},{"value":0,"end_time":"11:50","start_time":"11:30"},{"value":1,"end_time":"13:00","start_time":"11:50"}],"astro_clock":false,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' +// }, +// '3': { +// line: 3, +// tbname: 'vnmG4kJxaXWNBgMQq0D7Aj5e9oZzOAlr6LdR3w2V', +// contactor: 0, +// profile: '{"intervals":[{"value":0,"end_time":"20:30","start_time":"13:00"},{"value":1,"end_time":"00:10","start_time":"20:30"},{"value":0,"end_time":"13:00","start_time":"05:40"},{"value":1,"end_time":"05:40","start_time":"00:10"}],"astro_clock":true,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' +// } +// } + + + + + +// { +// "jbN4q7JPZmexgdnz2yKbWGDYAWwO0Q3BMX6ERLoV": [ +// { +// "ts": 1700409326353, +// "values": { +// "_event": { +// "type": "notice", +// "status": "new", +// "source": { +// "func": "rsPort.open()", +// "component": "1700343402190", +// "component_name": "DIDO_Controller", +// "edge": "jbN4q7JPZmexgdnz2yKbWGDYAWwO0Q3BMX6ERLoV" +// }, +// "message": "al_shariff_10.0.0.38: FLOW has been started ", +// "message_data": "" +// } +// } +// } +// ] +// } diff --git a/RVO15/flow/helper/DataToTbHandler.js b/RVO15/flow/helper/DataToTbHandler.js new file mode 100755 index 0000000..716ef7b --- /dev/null +++ b/RVO15/flow/helper/DataToTbHandler.js @@ -0,0 +1,187 @@ +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; + this.itIsNodeReadout = false; + this.sender = ""; + + // if attribute change difference is less than limit value, we do not send to tb. + this.attributeChangeLimit = { + temperature: 0.5, + Phase_1_voltage: 2, + Phase_2_voltage: 2, + Phase_3_voltage: 2, + Phase_1_current: 0.1, + Phase_2_current: 0.1, + Phase_3_current: 0.1, + Phase_1_power: 2, + Phase_2_power: 2, + Phase_3_power: 2, + total_power: 2, + total_energy: 1, + Phase_1_pow_factor: 0.1, + Phase_2_pow_factor: 0.1, + Phase_3_pow_factor: 0.1, + power_factor: 0.1, + lifetime: 2, + voltage: 2, + power: 2, + frequency: 3, + energy: 0.1, + current: 2, + inclination_x: 10, + inclination_y: 10, + inclination_z: 10 + }; + + } + + dump() { + console.log("----------------------------"); + console.log("previousValues", this.previousValues); + console.log("----------------------------"); + } + + setSender(sender) { + this.sender = sender; + } + + isEmptyObject(obj) { + for (var _ in obj) { + return false; + } + return true; + } + + + sendToTb(data, instance) { + + //not to modify data object, we do deep copy: + let dataCopy = JSON.parse(JSON.stringify(data)); + + let keys = Object.keys(dataCopy); + + if (keys.length == 0) { + if (this.debug) console.log("sendToTb received empty object", dataCopy); + return; + } + + let tbname = keys[0]; + let ts; + + let arrayOfValues = dataCopy[tbname]; + let arrayOfValuesToSend = []; + + for (let i = 0; i < arrayOfValues.length; i++) { + + ts = arrayOfValues[i].ts; + let values = this.prepareValuesForTb(tbname, ts, arrayOfValues[i].values); + + if (!this.isEmptyObject(values)) { + arrayOfValuesToSend.push({ ts: ts, values: values }); + } + + } + + if (arrayOfValuesToSend.length == 0) { + //if(this.debug) console.log("data not sent - empty array"); + return; + } + + this.messageCounter++; + + let dataToTbModified = { + [tbname]: arrayOfValuesToSend + } + + //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); + instance.send(this.index, dataToTbModified); + } + + + getDiffTimestamp(key) { + //TODO set different value for given key!!! + //if(key == "status") this.timeToHoldTbValue = 2*60*60;//2h + return this.timeToHoldTbValue * 1000; + } + + + prepareValuesForTb(tbname, timestamp, values) { + + let keys = Object.keys(values); + + if (keys.includes("lifetime")) this.itIsNodeReadout = true; + + if (!this.previousValues.hasOwnProperty(tbname)) { + this.previousValues[tbname] = {}; + } + + //if(this.debug) console.log("prepareValuesForTb", tbname, timestamp, values); + + for (let i = 0; i < keys.length; i++) { + + let key = keys[i]; + let value = values[key]; + + if (!this.previousValues[tbname].hasOwnProperty(key)) { + this.previousValues[tbname][key] = { ts: timestamp, value: value }; + continue; + } + + // attributeData ==> {voltage: {ts:333333, value:5}} + let attributeData = this.previousValues[tbname][key]; + let attributeToChange = false; + if (key in this.attributeChangeLimit) attributeToChange = true; + let limit = this.attributeChangeLimit[key]; + let timestampDiffToRemoveKey; + + //this will ensure "node statecode" will be sent just once an hour + if (this.itIsNodeReadout && key === "statecode") { + attributeData.value = value; + this.itIsNodeReadout = false; + timestampDiffToRemoveKey = 1 * 60 * 60 * 1000; // 1 hour + } + + if (key === "twilight_sensor" && value > 100) { + attributeData.value = value; + } + + //if edge, master or node version do not change, send just once a day: + if (["edge_fw_version", "master_node_version", "fw_version"].includes(key)) { + timestampDiffToRemoveKey = 24 * 60 * 60 * 1000; + } + + if (attributeData.value === value || attributeToChange && Math.abs(attributeData.value - value) < limit) { + + let diff = timestamp - attributeData.ts; + if (!timestampDiffToRemoveKey) timestampDiffToRemoveKey = this.getDiffTimestamp(key); + + if (diff > timestampDiffToRemoveKey) { + attributeData.ts = Date.now(); + //if(this.debug) console.log(this.sender + ": update ts for key", key, "diff is", diff, "messageCounter", this.messageCounter); + } + else { + delete values[key]; + //if(this.debug) console.log(this.sender + ": delete key", key, "diff is", diff, "messageCounter", this.messageCounter, timestampDiffToRemoveKey); + } + } + else { + attributeData.value = value; + attributeData.ts = timestamp; + } + + } + + return values; + } +} + +module.exports = DataToTbHandler; + diff --git a/RVO15/flow/helper/ErrorToServiceHandler.js b/RVO15/flow/helper/ErrorToServiceHandler.js new file mode 100755 index 0000000..2b27c32 --- /dev/null +++ b/RVO15/flow/helper/ErrorToServiceHandler.js @@ -0,0 +1,91 @@ +const { MD5 } = require('./md5.js'); +const { networkInterfaces } = require('os'); + +class ErrorToServiceHandler { + constructor() { + this.previousValues = {}; + + this.project_id = undefined; + + const nets = networkInterfaces(); + this.ipAddresses = {}; + + for (const name of Object.keys(nets)) { + for (const net of nets[name]) { + // Skip over non-IPv4 and internal (i.e. 127.0.0.1) addresses + if (net.family === 'IPv4' && !net.internal) { + if (!this.ipAddresses[name]) { + this.ipAddresses[name] = []; + } + this.ipAddresses[name].push(net.address); + } + } + } + } + + setProjectId(project_id) { + this.project_id = project_id; + } + + processMessage(message, seconds) { + if (Array.isArray(message)) message = message.join(', '); + + let key = MD5(message); + let ts = Date.now(); + + //keep in memory - default value is 1h + if (seconds === undefined) seconds = 60 * 60; + + if (!this.previousValues.hasOwnProperty(key)) { + this.previousValues[key] = { ts: ts, duration: seconds }; + } + + let diff = (ts - this.previousValues[key].ts); + if (diff < this.previousValues[key].duration * 1000) return false; + + this.previousValues[key].ts = ts; + + return message; + } + + sendMessageToService(message, seconds, message_type) { + + // if error occures too early FLOW.GLOBALS.settings.project_id is still undefined + if (this.project_id === undefined) { + console.log("ErrorToServiceHandler.js: no project_id"); + return; + } + + let f = this.processMessage(message, seconds); + if (f === false) return; + + if (message_type === undefined) message_type = "error_message"; + + let toService = { + id: this.project_id, + ipAddresses: this.ipAddresses + }; + + //js_error || error_message + toService[message_type] = message; + + console.log("ErrorToServiceHandler------------------------>send to service", toService); + + RESTBuilder.make(function(builder) { + builder.method('POST'); + builder.post(toService); + builder.url('http://192.168.252.2:8004/sentmessage'); + + builder.callback(function(err, response, output) { + console.log("process.on error send", err, response, output, toService); + }); + }); + + } +} + +const errorHandler = new ErrorToServiceHandler(); + + +module.exports = errorHandler; +//module.exports = ErrorToServiceHandler; diff --git a/RVO15/flow/helper/db_helper.js b/RVO15/flow/helper/db_helper.js new file mode 100755 index 0000000..40e796c --- /dev/null +++ b/RVO15/flow/helper/db_helper.js @@ -0,0 +1,44 @@ +function promisifyBuilder(builder) +{ + return new Promise((resolve, reject) => { + + try{ + + builder.callback(function(err, response) { + + if(err != null) reject(err); + resolve(response); + }); + + } catch (error) { + reject(error); + } + }) +} + +function makeMapFromDbResult(response, ...keys) +{ + let s = "-"; + let data = {}; + + for(let i = 0; i < response.length; i++) + { + let record = response[i]; + + let k = []; + for(let j = 0; j < keys.length; j++) + { + k.push( record[keys[j]] ); + } + + let key = k.join(s); + data[ key ] = record; + } + + return data; +} + +module.exports = { + promisifyBuilder, + makeMapFromDbResult + } \ No newline at end of file diff --git a/RVO15/flow/helper/logger.js b/RVO15/flow/helper/logger.js new file mode 100755 index 0000000..2585639 --- /dev/null +++ b/RVO15/flow/helper/logger.js @@ -0,0 +1,30 @@ +//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/RVO15/flow/helper/md5.js b/RVO15/flow/helper/md5.js new file mode 100755 index 0000000..d3b0480 --- /dev/null +++ b/RVO15/flow/helper/md5.js @@ -0,0 +1,5 @@ +function MD5(d){var r = M(V(Y(X(d),8*d.length)));return r.toLowerCase()};function M(d){for(var _,m="0123456789ABCDEF",f="",r=0;r>>4&15)+m.charAt(15&_);return f}function X(d){for(var _=Array(d.length>>2),m=0;m<_.length;m++)_[m]=0;for(m=0;m<8*d.length;m+=8)_[m>>5]|=(255&d.charCodeAt(m/8))<>5]>>>m%32&255);return _}function Y(d,_){d[_>>5]|=128<<_%32,d[14+(_+64>>>9<<4)]=_;for(var m=1732584193,f=-271733879,r=-1732584194,i=271733878,n=0;n>16)+(_>>16)+(m>>16)<<16|65535&m}function bit_rol(d,_){return d<<_|d>>>32-_} + +module.exports = { + MD5 +} \ No newline at end of file diff --git a/RVO15/flow/helper/notification_reporter.js b/RVO15/flow/helper/notification_reporter.js new file mode 100755 index 0000000..839c12c --- /dev/null +++ b/RVO15/flow/helper/notification_reporter.js @@ -0,0 +1,121 @@ +//key is device, value = message {} +let sentValues = {}; +let notificationsData = null; +let rvoName; + +//sendNotification("CMD Manager: process cmd", SETTINGS.rvoTbName, "dimming_profile_was_successfully_received_by_node", { node: node }, "", SEND_TO.tb, instance); + +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 +}; + +function getKey(map, val) { + return Object.keys(map).findItem(key => map[key] === val); +} + +//https://stackoverflow.com/questions/41117799/string-interpolation-on-variable +var template = (tpl, args) => tpl.replace(/\${(\w+)}/g, (_, v) => args[v]); + + +function initNotification() { + notificationsData = FLOW.GLOBALS.notificationsData; + rvoName = FLOW.GLOBALS.settings.rvo_name; +} + + +function sendNotification(func, device, key, params, extra, tb_output, instance, saveKey) { + + let storeToSendValues = true; + if (saveKey == undefined) storeToSendValues = false; + + let weight = ""; + let message = {}; + + let notification = notificationsData[key]; + + if (notification) { + weight = notification.weight.toLowerCase(); + + Object.keys(notification).forEach(item => { + if (["en", "sk", "de", "cz", "it", "es"].includes(item)) { + message[item] = rvoName + ": " + template(notification[item], params); + } + }) + } + else { + //console.error("sendNotification: Notifications: undefined key", key, func, notificationsData); + console.error("sendNotification: Notifications: undefined key", key, func); + return false; + } + + //detect invalid err weight + if (getKey(ERRWEIGHT, weight) == undefined) { + console.error("sendNotification: Notifications: undefined weight", weight, key, func); + return false; + } + + if (sentValues.hasOwnProperty(saveKey)) { + if (JSON.stringify(sentValues[saveKey]) == JSON.stringify(message)) { + return false; + } + } + + if (sentValues[saveKey] == undefined) { + if (storeToSendValues) { + //do not send - flow is was started + sentValues[saveKey] = message; + return false; + } + } + + if (storeToSendValues) sentValues[saveKey] = message; + + let content = { + "type": weight, + "status": "new", + "source": { + "func": func, + "component": instance.id, + "component_name": instance.name, + "edge": device + }, + "message": message, + "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 + + return true; + +} + +module.exports = { + sendNotification, + ERRWEIGHT, + initNotification +} + diff --git a/RVO15/flow/helper/register.js b/RVO15/flow/helper/register.js new file mode 100755 index 0000000..fc1d008 --- /dev/null +++ b/RVO15/flow/helper/register.js @@ -0,0 +1,144 @@ +/* +0 - cislo registra / prikaz +1 - recepient - 0 = master, 1 = slave (slave je automaticky group a broadcast) +2 - r/rw - read/write +3- register name - nazov registra / prikazu (len pre info - zobrazenie v aplikacii) + +4,5,6,7, - jednotlive byte-y - nazov byte-u +4-7 - RES. a prazdny string "" sa nezobrazia!!! +*/ + +//124 zaznamov +const registers = [ + ["0","1","R","Status","","",""], + ["1","1","RW","Dimming","R-Channel ","G-Channel","B-Channel ","W - Channel"], + ["2","1","R","Device types","","",".",""], + ["3","1","RW","Group addresses 1-4","Groups Add. 4","Groups Add. 3","Groups Add. 2","Groups Add. 1"], + ["4","1","RW","Group addresses 5-8","Groups Add. 8","Groups Add. 7","Groups Add. 6","Groups Add. 5"], + ["5","1","RW","Serial number (MAC)","","","",""], + ["6","1","RW","Time of dusk","HH","MM","SS","EXTRA"], + ["7","1","RW","Time of dawn","HH","MM","SS","EXTRA"], + ["8","1","RW","Time Schedule settings","TBD","TBD","Movement sensor","Time Schedule"], + ["9","1","RW","TS1 Time point 1","HH","MM","SS","Ext. Device"], + ["10","1","RW","TS1 Time point 1 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["11","1","RW","TS1 Time point 2","HH","MM","SS","Ext. Device"], + ["12","1","RW","TS1 Time point 2 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["13","1","RW","TS1 Time point 3","HH","MM","SS","Ext. Device"], + ["14","1","RW","TS1 Time point 3 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["15","1","RW","TS1 Time point 4","HH","MM","SS","Ext. Device"], + ["16","1","RW","TS1 Time point 4 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["17","1","RW","TS1 Time point 5","HH","MM","SS","Ext. Device"], + ["18","1","RW","TS1 Time point 5 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["19","1","RW","TS1 Time point 6","HH","MM","SS","Ext. Device"], + ["20","1","RW","TS1 Time point 6 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["21","1","RW","TS1 Time point 7","HH","MM","SS","Ext. Device"], + ["22","1","RW","TS1 Time point 7 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["23","1","RW","TS1 Time point 8","HH","MM","SS","Ext. Device"], + ["24","1","RW","TS1 Time point 8 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["25","1","RW","TS1 Time point 9","HH","MM","SS","Ext. Device"], + ["26","1","RW","TS1 Time point 9 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["27","1","RW","TS1 Time point 10","HH","MM","SS","Ext. Device"], + ["28","1","RW","TS1 Time point 10 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["29","1","RW","TS1 Time point 11","HH","MM","SS","Ext. Device"], + ["30","1","RW","TS1 Time point 11 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["31","1","RW","TS1 Time point 12","HH","MM","SS","Ext. Device"], + ["32","1","RW","TS1 Time point 12 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["33","1","RW","TS1 Time point 13","HH","MM","SS","Ext. Device"], + ["34","1","RW","TS1 Time point 13 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["35","1","RW","TS1 Time point 14","HH","MM","SS","Ext. Device"], + ["36","1","RW","TS1 Time point 14 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["37","1","RW","TS1 Time point 15","HH","MM","SS","Ext. Device"], + ["38","1","RW","TS1 Time point 15 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["39","1","RW","TS1 Time point 16","HH","MM","SS","Ext. Device"], + ["40","1","RW","TS1 Time point 16 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["41","1","RW","TS2 Time point 1","HH","MM","SS","Ext. Device"], + ["42","1","RW","TS2 Time point 1 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["43","1","RW","TS2 Time point 2","HH","MM","SS","Ext. Device"], + ["44","1","RW","TS2 Time point 2 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["45","1","RW","TS2 Time point 3","HH","MM","SS","Ext. Device"], + ["46","1","RW","TS2 Time point 3 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["47","1","RW","TS2 Time point 4","HH","MM","SS","Ext. Device"], + ["48","1","RW","TS2 Time point 4 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["49","1","RW","TS2 Time point 5","HH","MM","SS","Ext. Device"], + ["50","1","RW","TS2 Time point 5 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["51","1","RW","TS2 Time point 6","HH","MM","SS","Ext. Device"], + ["52","1","RW","TS2 Time point 6 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["53","1","RW","TS2 Time point 7","HH","MM","SS","Ext. Device"], + ["54","1","RW","TS2 Time point 7 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["55","1","RW","TS2 Time point 8","HH","MM","SS","Ext. Device"], + ["56","1","RW","TS2 Time point 8 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["57","1","RW","TS2 Time point 9","HH","MM","SS","Ext. Device"], + ["58","1","RW","TS2 Time point 9 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["59","1","RW","TS2 Time point 10","HH","MM","SS","Ext. Device"], + ["60","1","RW","TS2 Time point 10 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["61","1","RW","TS2 Time point 11","HH","MM","SS","Ext. Device"], + ["62","1","RW","TS2 Time point 11 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["63","1","RW","TS2 Time point 12","HH","MM","SS","Ext. Device"], + ["64","1","RW","TS2 Time point 12 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["65","1","RW","TS2 Time point 13","HH","MM","SS","Ext. Device"], + ["66","1","RW","TS2 Time point 13 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["67","1","RW","TS2 Time point 14","HH","MM","SS","Ext. Device"], + ["68","1","RW","TS2 Time point 14 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["69","1","RW","TS2 Time point 15","HH","MM","SS","Ext. Device"], + ["70","1","RW","TS2 Time point 15 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["71","1","RW","TS2 Time point 16","HH","MM","SS","Ext. Device"], + ["72","1","RW","TS2 Time point 16 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["73","1","RW","Power meter status","TBD","","",""], + ["74","1","R","Input Voltage","","","",""], + ["75","1","R","Input Current","","","",""], + ["76","1","R","Input Power","","","",""], + ["77","1","R","Cos phi","","","",""], + ["78","1","R","Frequency","","","",""], + ["79","1","RW","Energy","","","",""], + ["80","1","RW","Lifetime","","","",""], + ["81","1","RW","Power on cycles (input)","","","",""], + ["82","1","RW","Power on cycles (relay)","","","",""], + ["83","1","R","Time since last power on","","","",""], + ["84","1","R","Accelerometer data","","","",""], + ["85","1","RW","GPS latitude","pos/neg","deg","min ","sec"], + ["86","1","RW","GPS longitude","pos/neg","deg","min ","sec"], + ["87","1","RW","Actual time","HH","MM","SS","RES."], + ["88","1","RW","Actual date","Day of week","Day","Month","Year"], + ["89","1","R","Production data 1","","","",""], + ["90","1","R","Production data 2","","","",""], + ["91","1","RW","Network ID","NID3","NID2","NID1","NID0"], + ["95","1","RW","Actual Lux level from cabinet","RES.","RES.","HB","LB"], + ["96","1","RW","Threshold lux level","Dusk HB","Dusk LB","Dawn HB","Dawn LB"], + ["97","1","RW","Adjust period","Dusk HB","Dusk LB","Dawn HB","Dawn LB"], + ["98","1","RW","Offset","RES.","RES.","Dusk","Dawn"], + ["99","1","RW","CCT min/max range","max-H","max-L","min-H","min-L"], + ["100","1","RW","DALI interface","Cmd ID","Add","Cmd","Resp"], + ["101","1","RW","Module FW ver","v1","v2","v3","v4"], + ["102","1","RW","Module MAC-H","unused","unused","M1","M2"], + ["103","1","RW","Module MAC-L","M3","M4","M5","M6"], + ["122","1","R","FW update status/control register","Byte3","Byte2","Byte1","Byte0"], + ["123","1","R","FW update - data index","Byte3","Byte2","Byte1","Byte0"], + ["124","1","R","FW update - data","Byte3","Byte2","Byte1","Byte0"], + ["0","0","R","Status","","","",""], + ["1","0","RW","Control register","RES.","RES.","RES.","init mode enable"], + ["2","0","R","Device types","","","",""], + ["3","0","R","Serial number (MAC)","","","",""], + ["4","0","R","Production data 1","","","",""], + ["5","0","R","Production data 2","","","",""], + ["6","0","RW","Network ID","NID3","NID2","NID1","NID0"], + ["7","0","RW","RS232 settings","param.","param.","Baudrate H","Baudrate L"], + ["8","0","R","Accelerometer data","","","",""], + ["9","0","RW","Module FW ver","v1","v2","v3","v4"], + ["10","0","RW","Module MAC-H","unused","unused","M1","M2"], + ["11","0","RW","Module MAC-L","M3","M4","M5","M6"], + ["32","0","RW","FW update status/control register","Byte3","Byte2","Byte1","Byte0"], + ["33","0","RW","FW update - data index","Byte3","Byte2","Byte1","Byte0"], + ["34","0","RW","FW update - data","Byte3","Byte2","Byte1","Byte0"], + ["125","0","RW","Debug Register","Byte3","Byte2","Byte1","Byte0"], + ["126","0","RW","Network Control Register","Byte3","Byte2","Byte1","Byte0"], + ["127","0","R","Network Status Register","Byte3","Byte2","Byte1","Byte0"], + ["128","0","RW","Node XX Serial Number Register","SER3","SER2","SER1","SER0"], + ["256","0","R","Node XX Network Status Register","","","",""] +]; + +let register = {}; + +module.exports = { + registers, + register +} \ No newline at end of file diff --git a/RVO15/flow/helper/serialport_helper.js b/RVO15/flow/helper/serialport_helper.js new file mode 100755 index 0000000..7f5920d --- /dev/null +++ b/RVO15/flow/helper/serialport_helper.js @@ -0,0 +1,99 @@ +const { exec } = require('child_process'); + +function openPort(port) { + return new Promise((resolve, reject) => { + + var callbackError = function(err) { + port.removeListener('error', callbackError); + port.removeListener('open', callbackError); + + reject(err.message); + }; + + var callbackOpen = function(data) { + port.removeListener('error', callbackError); + port.removeListener('open', callbackOpen); + + resolve("port open: ok"); + }; + + port.on('error', callbackError); + port.on('open', callbackOpen); + + port.open(); + + }) +} + +function runSyncExec(command) { + return new Promise((resolve, reject) => { + + exec(command, (error, stdout, stderr) => { + if (error == null) resolve(stdout); + reject(error); + }); + + }) +} + +async function writeData(port, data, readbytes, timeout) { + return new Promise((resolve, reject) => { + + // 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) { + + port.write(Buffer.from(data), function(err) { + if (err) { + reject(err.message); + } + }); + + 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 +} diff --git a/RVO15/flow/helper/suncalc.js b/RVO15/flow/helper/suncalc.js new file mode 100755 index 0000000..c9ca56d --- /dev/null +++ b/RVO15/flow/helper/suncalc.js @@ -0,0 +1,317 @@ +/* + (c) 2011-2015, Vladimir Agafonkin + SunCalc is a JavaScript library for calculating sun/moon position and light phases. + https://github.com/mourner/suncalc +*/ + +(function () { 'use strict'; + +// shortcuts for easier to read formulas + +var PI = Math.PI, + sin = Math.sin, + cos = Math.cos, + tan = Math.tan, + asin = Math.asin, + atan = Math.atan2, + acos = Math.acos, + rad = PI / 180; + +// sun calculations are based on http://aa.quae.nl/en/reken/zonpositie.html formulas + + +// date/time constants and conversions + +var dayMs = 1000 * 60 * 60 * 24, + J1970 = 2440588, + J2000 = 2451545; + +function toJulian(date) { return date.valueOf() / dayMs - 0.5 + J1970; } +function fromJulian(j) { return new Date((j + 0.5 - J1970) * dayMs); } +function toDays(date) { return toJulian(date) - J2000; } + + +// general calculations for position + +var e = rad * 23.4397; // obliquity of the Earth + +function rightAscension(l, b) { return atan(sin(l) * cos(e) - tan(b) * sin(e), cos(l)); } +function declination(l, b) { return asin(sin(b) * cos(e) + cos(b) * sin(e) * sin(l)); } + +function azimuth(H, phi, dec) { return atan(sin(H), cos(H) * sin(phi) - tan(dec) * cos(phi)); } +function altitude(H, phi, dec) { return asin(sin(phi) * sin(dec) + cos(phi) * cos(dec) * cos(H)); } + +function siderealTime(d, lw) { return rad * (280.16 + 360.9856235 * d) - lw; } + +function astroRefraction(h) { + if (h < 0) // the following formula works for positive altitudes only. + h = 0; // if h = -0.08901179 a div/0 would occur. + + // formula 16.4 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + // 1.02 / tan(h + 10.26 / (h + 5.10)) h in degrees, result in arc minutes -> converted to rad: + return 0.0002967 / Math.tan(h + 0.00312536 / (h + 0.08901179)); +} + +// general sun calculations + +function solarMeanAnomaly(d) { return rad * (357.5291 + 0.98560028 * d); } + +function eclipticLongitude(M) { + + var C = rad * (1.9148 * sin(M) + 0.02 * sin(2 * M) + 0.0003 * sin(3 * M)), // equation of center + P = rad * 102.9372; // perihelion of the Earth + + return M + C + P + PI; +} + +function sunCoords(d) { + + var M = solarMeanAnomaly(d), + L = eclipticLongitude(M); + + return { + dec: declination(L, 0), + ra: rightAscension(L, 0) + }; +} + + +var SunCalc = {}; + + +// calculates sun position for a given date and latitude/longitude + +SunCalc.getPosition = function (date, lat, lng) { + + var lw = rad * -lng, + phi = rad * lat, + d = toDays(date), + + c = sunCoords(d), + H = siderealTime(d, lw) - c.ra; + + return { + azimuth: azimuth(H, phi, c.dec), + altitude: altitude(H, phi, c.dec) + }; +}; + + +// sun times configuration (angle, morning name, evening name) + +var times = SunCalc.times = [ + [-0.833, 'sunrise', 'sunset' ], + [ -0.3, 'sunriseEnd', 'sunsetStart' ], + [ -6, 'dawn', 'dusk' ], + [ -12, 'nauticalDawn', 'nauticalDusk'], + [ -18, 'nightEnd', 'night' ], + [ 6, 'goldenHourEnd', 'goldenHour' ] +]; + +// adds a custom time to the times config + +SunCalc.addTime = function (angle, riseName, setName) { + times.push([angle, riseName, setName]); +}; + + +// calculations for sun times + +var J0 = 0.0009; + +function julianCycle(d, lw) { return Math.round(d - J0 - lw / (2 * PI)); } + +function approxTransit(Ht, lw, n) { return J0 + (Ht + lw) / (2 * PI) + n; } +function solarTransitJ(ds, M, L) { return J2000 + ds + 0.0053 * sin(M) - 0.0069 * sin(2 * L); } + +function hourAngle(h, phi, d) { return acos((sin(h) - sin(phi) * sin(d)) / (cos(phi) * cos(d))); } +function observerAngle(height) { return -2.076 * Math.sqrt(height) / 60; } + +// returns set time for the given sun altitude +function getSetJ(h, lw, phi, dec, n, M, L) { + + var w = hourAngle(h, phi, dec), + a = approxTransit(w, lw, n); + return solarTransitJ(a, M, L); +} + + +// calculates sun times for a given date, latitude/longitude, and, optionally, +// the observer height (in meters) relative to the horizon + +SunCalc.getTimes = function (date, lat, lng, height) { + + height = height || 0; + + var lw = rad * -lng, + phi = rad * lat, + + dh = observerAngle(height), + + d = toDays(date), + n = julianCycle(d, lw), + ds = approxTransit(0, lw, n), + + M = solarMeanAnomaly(ds), + L = eclipticLongitude(M), + dec = declination(L, 0), + + Jnoon = solarTransitJ(ds, M, L), + + i, len, time, h0, Jset, Jrise; + + + var result = { + solarNoon: fromJulian(Jnoon), + nadir: fromJulian(Jnoon - 0.5) + }; + + for (i = 0, len = times.length; i < len; i += 1) { + time = times[i]; + h0 = (time[0] + dh) * rad; + + Jset = getSetJ(h0, lw, phi, dec, n, M, L); + Jrise = Jnoon - (Jset - Jnoon); + + result[time[1]] = fromJulian(Jrise); + result[time[2]] = fromJulian(Jset); + } + + return result; +}; + + +// moon calculations, based on http://aa.quae.nl/en/reken/hemelpositie.html formulas + +function moonCoords(d) { // geocentric ecliptic coordinates of the moon + + var L = rad * (218.316 + 13.176396 * d), // ecliptic longitude + M = rad * (134.963 + 13.064993 * d), // mean anomaly + F = rad * (93.272 + 13.229350 * d), // mean distance + + l = L + rad * 6.289 * sin(M), // longitude + b = rad * 5.128 * sin(F), // latitude + dt = 385001 - 20905 * cos(M); // distance to the moon in km + + return { + ra: rightAscension(l, b), + dec: declination(l, b), + dist: dt + }; +} + +SunCalc.getMoonPosition = function (date, lat, lng) { + + var lw = rad * -lng, + phi = rad * lat, + d = toDays(date), + + c = moonCoords(d), + H = siderealTime(d, lw) - c.ra, + h = altitude(H, phi, c.dec), + // formula 14.1 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + pa = atan(sin(H), tan(phi) * cos(c.dec) - sin(c.dec) * cos(H)); + + h = h + astroRefraction(h); // altitude correction for refraction + + return { + azimuth: azimuth(H, phi, c.dec), + altitude: h, + distance: c.dist, + parallacticAngle: pa + }; +}; + + +// calculations for illumination parameters of the moon, +// based on http://idlastro.gsfc.nasa.gov/ftp/pro/astro/mphase.pro formulas and +// Chapter 48 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + +SunCalc.getMoonIllumination = function (date) { + + var d = toDays(date || new Date()), + s = sunCoords(d), + m = moonCoords(d), + + sdist = 149598000, // distance from Earth to Sun in km + + phi = acos(sin(s.dec) * sin(m.dec) + cos(s.dec) * cos(m.dec) * cos(s.ra - m.ra)), + inc = atan(sdist * sin(phi), m.dist - sdist * cos(phi)), + angle = atan(cos(s.dec) * sin(s.ra - m.ra), sin(s.dec) * cos(m.dec) - + cos(s.dec) * sin(m.dec) * cos(s.ra - m.ra)); + + return { + fraction: (1 + cos(inc)) / 2, + phase: 0.5 + 0.5 * inc * (angle < 0 ? -1 : 1) / Math.PI, + angle: angle + }; +}; + + +function hoursLater(date, h) { + return new Date(date.valueOf() + h * dayMs / 24); +} + +// calculations for moon rise/set times are based on http://www.stargazing.net/kepler/moonrise.html article + +SunCalc.getMoonTimes = function (date, lat, lng, inUTC) { + var t = new Date(date); + if (inUTC) t.setUTCHours(0, 0, 0, 0); + else t.setHours(0, 0, 0, 0); + + var hc = 0.133 * rad, + h0 = SunCalc.getMoonPosition(t, lat, lng).altitude - hc, + h1, h2, rise, set, a, b, xe, ye, d, roots, x1, x2, dx; + + // go in 2-hour chunks, each time seeing if a 3-point quadratic curve crosses zero (which means rise or set) + for (var i = 1; i <= 24; i += 2) { + h1 = SunCalc.getMoonPosition(hoursLater(t, i), lat, lng).altitude - hc; + h2 = SunCalc.getMoonPosition(hoursLater(t, i + 1), lat, lng).altitude - hc; + + a = (h0 + h2) / 2 - h1; + b = (h2 - h0) / 2; + xe = -b / (2 * a); + ye = (a * xe + b) * xe + h1; + d = b * b - 4 * a * h1; + roots = 0; + + if (d >= 0) { + dx = Math.sqrt(d) / (Math.abs(a) * 2); + x1 = xe - dx; + x2 = xe + dx; + if (Math.abs(x1) <= 1) roots++; + if (Math.abs(x2) <= 1) roots++; + if (x1 < -1) x1 = x2; + } + + if (roots === 1) { + if (h0 < 0) rise = i + x1; + else set = i + x1; + + } else if (roots === 2) { + rise = i + (ye < 0 ? x2 : x1); + set = i + (ye < 0 ? x1 : x2); + } + + if (rise && set) break; + + h0 = h2; + } + + var result = {}; + + if (rise) result.rise = hoursLater(t, rise); + if (set) result.set = hoursLater(t, set); + + if (!rise && !set) result[ye > 0 ? 'alwaysUp' : 'alwaysDown'] = true; + + return result; +}; + + +// export as Node module / AMD module / browser variable +if (typeof exports === 'object' && typeof module !== 'undefined') module.exports = SunCalc; +else if (typeof define === 'function' && define.amd) define(SunCalc); +else window.SunCalc = SunCalc; + +}()); diff --git a/RVO15/flow/helper/utils.js b/RVO15/flow/helper/utils.js new file mode 100755 index 0000000..dbffe45 --- /dev/null +++ b/RVO15/flow/helper/utils.js @@ -0,0 +1,161 @@ +const fs = require('fs').promises; + +function bytesToInt(bytes, numberOfBytes) { + let buffer = []; + if (Array.isArray(bytes)) { + buffer = bytes.slice(0); + if (numberOfBytes != undefined) { + buffer = bytes.slice(bytes.length - numberOfBytes); + } + } + else buffer.push(bytes); + + let result = 0; + for (let i = 0; i < buffer.length; i++) { + result = (result << 8) | buffer[i]; + } + + return result >>> 0; //ensure it's an unsigned 32-bit number +} + +function resizeArray(arr, newSize, defaultValue) { + while (newSize > arr.length) + arr.push(defaultValue); + arr.length = newSize; +} + +longToByteArray = function(/*long*/long) { + // we want to represent the input as a 8-bytes array + var byteArray = [0, 0, 0, 0, 0, 0, 0, 0]; + + for (var index = 0; index < byteArray.length; index++) { + var byte = long & 0xff; + byteArray[index] = byte; + long = (long - byte) / 256; + } + + return byteArray; +}; + +function addDays(date, days) { + var result = new Date(date); + result.setDate(result.getDate() + days); + return result; +} + +/* +sleep(2000).then(() => { + // Do something after the sleep! + + +}); +*/ + +function sleep(time) { + return new Promise((resolve) => setTimeout(resolve, time)); +} + +function isEmptyObject(obj) { + for (var name in obj) { + return false; + } + return true; +} + +function emptyJsObject(jsObject) { + Object.keys(jsObject).forEach(key => delete jsObject[key]); +} + +function convertUTCDateToLocalDate(date) { + var newDate = new Date(date); + newDate.setMinutes(date.getMinutes() + date.getTimezoneOffset()); + return newDate; +} + +function addZeroBefore(n) { + return (n < 10 ? '0' : '') + n; +} + + +/** + * Asynchronously writes data to a file. + * + * @param {string} filePath The path to the file. + * @param {string} data The data to write to the file. + * @param {boolean} [append=false] If true, appends the data to the file. If false, it overwrites the file. + */ +async function writeToFile(filePath, data, append = false) { + if (typeof data !== 'string') data = JSON.stringify(data, null, 2); + try { + if (append) { + // Append the data to the end of the file. This is the simplest way to append. + await fs.appendFile(filePath, data, 'utf8'); + console.log(`Successfully appended data to ${filePath} using fs.appendFile.`); + } else { + // Overwrite the file with the new data. + await fs.writeFile(filePath, data, 'utf8'); + console.log(`Successfully wrote (overwrote) data to ${filePath} using fs.writeFile.`); + } + } catch (error) { + console.error(`Error writing to file ${filePath}:`, error); + } +} + + + /** + * Checks if an item is present in an array and adds it if it's not. + * * @param {Array} arr The array to check. + * @param {*} item The item to add. + * @returns {Array} The modified array. + */ +const addToArrayIfUnique = (arr, item) => { + if (!arr.includes(item)) { + arr.push(item); + } + return arr; +}; + + +var convertBase = function() { + + function convertBase(baseFrom, baseTo) { + return function(num) { + return parseInt(num, baseFrom).toString(baseTo); + + }; + } + + // binary to decimal + convertBase.bin2dec = convertBase(2, 10); + + // binary to hexadecimal + convertBase.bin2hex = convertBase(2, 16); + + // decimal to binary + convertBase.dec2bin = convertBase(10, 2); + + // decimal to hexadecimal + convertBase.dec2hex = convertBase(10, 16); + + // hexadecimal to binary + convertBase.hex2bin = convertBase(16, 2); + + // hexadecimal to decimal + convertBase.hex2dec = convertBase(16, 10); + + return convertBase; +}(); + +module.exports = { + bytesToInt, + longToByteArray, + addDays, + addZeroBefore, + resizeArray, + isEmptyObject, + emptyJsObject, + sleep, + convertUTCDateToLocalDate, + writeToFile, + addToArrayIfUnique +} diff --git a/RVO15/flow/httprequest.js b/RVO15/flow/httprequest.js new file mode 100755 index 0000000..469c8cb --- /dev/null +++ b/RVO15/flow/httprequest.js @@ -0,0 +1,137 @@ +exports.id = 'httprequest'; +exports.title = 'HTTP Request'; +exports.group = 'HTTP'; +exports.color = '#5D9CEC'; +exports.input = true; +exports.version = '2.0.1'; +exports.output = 1; +exports.author = 'Peter Širka'; +exports.icon = 'cloud-upload'; + +exports.html = `
+
@(URL address)
+
+
+
@(HTTP method)
+
+
+
@(Serialization)
+
+
+
@(Download the content in chunks)
+
@(Keep persistent cookies)
+
@(Disable DNS cache)
+
@(Keep alive connection)
+
+
+
+
@(Custom headers)
+
@(Cookies)
+
+
+
+ +
+
+
+
@(User)
+
+
+
@(Password)
+
+
+
+
+
`; + +exports.readme = `# Request + +This component creates a request with received data. + +__Response:__ +\`\`\`javascript +{ + data: String, + headers: Object, + status: Number, + host: String +} +\`\`\` + +__Dynamic arguments__: +Are performed via FlowData repository and can be used for URL address or for custom headers/cookies/auth. Use \`repository\` component for creating of dynamic arguments. Dynamic values are replaced in the form \`{key}\`: + +- url address e.g. \`https://.../{key}/\` +- headers values e.g. \`{token}\` +- cookies values e.g. \`{token}\``; + +exports.install = function(instance) { + + var can = false; + var flags = null; + var cookies2 = null; + + instance.on('data', function(response) { + can && instance.custom.send(response); + }); + + instance.custom.send = function(response) { + var options = instance.options; + + var headers = null; + var cookies = null; + + options.headers && Object.keys(options.headers).forEach(function(key) { + !headers && (headers = {}); + headers[key] = response.arg(options.headers[key]); + }); + + if (options.username && options.userpassword) { + !headers && (headers = {}); + headers['Authorization'] = 'Basic ' + U.createBuffer(response.arg(options.username + ':' + options.userpassword)).toString('base64'); + } + + options.cookies && Object.keys(options.cookies).forEach(function(key) { + !cookies && (cookies = {}); + cookies[key] = response.arg(options.cookies[key]); + }); + + if (options.chunks) { + U.download(response.arg(options.url), flags, options.stringify === 'none' ? null : response.data, function(err, response) { + response.on('data', (chunks) => instance.send2(chunks)); + }, cookies || cookies2, headers); + } else { + U.request(response.arg(options.url), flags, options.stringify === 'none' ? null : response.data, 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) + instance.error(err, response); + }, cookies || cookies2, headers); + } + }; + + instance.reconfigure = function() { + var options = instance.options; + can = options.url && options.url && options.method && options.stringify ? true : false; + instance.status(can ? '' : 'Not configured', can ? undefined : 'red'); + + if (!can) + return; + + flags = []; + flags.push(options.method.toLowerCase()); + options.stringify === 'json' && flags.push('json'); + options.stringify === 'raw' && flags.push('raw'); + options.keepalive && flags.push('keepalive'); + !options.nodns && flags.push('dnscache'); + if (options.persistentcookies) { + flags.push('cookies'); + cookies2 = {}; + } else + cookies2 = null; + }; + + instance.on('options', instance.reconfigure); + instance.reconfigure(); +}; \ No newline at end of file diff --git a/RVO15/flow/httpresponse.js b/RVO15/flow/httpresponse.js new file mode 100755 index 0000000..160a3bb --- /dev/null +++ b/RVO15/flow/httpresponse.js @@ -0,0 +1,76 @@ +exports.id = 'httpresponse'; +exports.title = 'HTTP Response'; +exports.group = 'HTTP'; +exports.color = '#5D9CEC'; +exports.icon = 'arrow-right'; +exports.input = true; +exports.output = ['#666D76']; +exports.version = '2.0.0'; +exports.author = 'Martin Smola'; +exports.readme = `# HTTP response + +HTTP response will respond with data recieved using data-type set in Settings form or plain text if not set. Output is the message duration \`Number\` in seconds.`; + +exports.html = `
+
@(Response data-type)
+
JSON is by default.
+
`; + +exports.install = function(instance) { + + var dursum = 0; + var durcount = 0; + + instance.on('data', function(flowdata) { + + var ctrl = flowdata.repository.controller; + var data = flowdata.data; + + if (!ctrl) { + instance.throw('No controller to use for response!'); + return; + } + + durcount++; + dursum += ((new Date() - flowdata.begin) / 1000).floor(2); + setTimeout2(instance.id, instance.custom.duration, 500, 10); + + ctrl.$flowdata = flowdata; + + var datatype = instance.options.datatype || 'json'; + if (datatype === 'emptyresponse') + return ctrl.plain(''); + + if (datatype !== 'json' && typeof(data) !== 'string') { + instance.throw('Incorect type of data, expected string, got ' + typeof(data)); + ctrl.plain(data == null ? '' : data.toString()); + return; + } + + switch(datatype) { + case 'html': + ctrl.content(data, 'text/html'); + break; + case 'plain': + ctrl.plain(data); + break; + case 'xml': + ctrl.content(data, 'text/xml'); + break; + default: + ctrl.json(data); + break; + } + }); + + instance.on('service', function() { + dursum = 0; + durcount = 0; + }); + + instance.custom.duration = function() { + var avg = (dursum / durcount).floor(2); + instance.status(avg + ' sec.'); + instance.send2(0, avg); + }; +}; diff --git a/RVO15/flow/httproute.js b/RVO15/flow/httproute.js new file mode 100755 index 0000000..583a19d --- /dev/null +++ b/RVO15/flow/httproute.js @@ -0,0 +1,326 @@ +exports.id = 'httproute'; +exports.title = 'HTTP Route'; +exports.group = 'HTTP'; +exports.color = '#5D9CEC'; +exports.icon = 'globe'; +exports.input = false; +exports.output = ['#6CAC5A', '#37BC9B']; +exports.version = '1.2.3'; +exports.author = 'Martin Smola'; +exports.cloning = false; +exports.options = { method: 'GET', url: '', size: 5, cacheexpire: '5 minutes', cachepolicy: 0, timeout: 5 }; +exports.dateupdated = '2021-01-21 18:30d'; +exports.readme = `# HTTP route + +__Outputs__: +- first output: raw data (cache is empty or is disabled) +- second output: cached data + +If one of the outputs is disabled then automatic responce with code "503 service unavailable" is sent. + +When a request comes in bellow object is available at \`flowdata.data\`: + +\`\`\`javascript +{ + params: { id: '1' }, // params for dynamic routes, e.g. /test/{id} + query: { msg: 'Hello' }, // parsed query string, e.g. /test/1?msg=Hello + body: { test: 'OK' }, // object if json requests otherwise string + headers: {}, // headers data + session: {}, // session data + user: {}, // user data + files: [], // uploaded files + url: '/users/', // a relative URL address + referrer: '/', // referrer + mobile: false, // determines mobile device + robot: false, // determines search robots/crawlsers + language: 'en' // determines language +} +\`\`\` + +See [documentation for flags](https://docs.totaljs.com/latest/en.html#api~HttpRouteOptionsFlags~unauthorize). These method flags are set automatically e.g. \`get, post, put, patch or delete\` + +--- + +\`id:ROUTE_ID\` flag cannot be used since it's already used by this component internally`; + +exports.html = `
+
+ +
+ +
+
+
@(HTTP method)
+
+
+
@(URL address)
+
+
+
+
+
@(Additional flags)
+
@(Separate flags by comma e.g. json, authorize)
+
+
+
@(Max. request size)
+
@(In kB kilobytes)
+
+
+
@(Timeout)
+
@(In seconds.)
+
+
+
+
+
+
@(Automatically respond with 200 OK?)
+
@(If not checked you need to use HTTP response component to respond to the request.)
+
+
@(Custom headers)
+
@(Cookies)
+
+
+
+
+
+
@(Cache policy)
+
@(User instance must contain id property.)
+
+
+
@(Expiration)
+
@(E.g. 5 minutes)
+
+
+
+`; + +exports.install = function(instance) { + + var route; + + var uninstall = function(id) { + if (F.is4) { + route && route.remove(); + route = null; + } else + UNINSTALL('route', id); + }; + + instance.custom.emptyresponse = function(self) { + self.plain(); + }; + + instance.reconfigure = function() { + + var options = instance.options; + + if (!options.url) { + instance.status('Not configured', 'red'); + return; + } + + if (typeof(options.flags) === 'string') + options.flags = options.flags.split(',').trim(); + + uninstall('id:' + instance.id); + + var flags = options.flags || []; + + flags.push('id:' + instance.id); + + if (!F.is4) + flags.push(options.method.toLowerCase()); + + options.timeout && flags.push(options.timeout * 1000); + + // Make unique values + flags = flags.filter(function(v, i, a) { + if(F.is4 && v.toString().toLowerCase() === options.method.toLowerCase()) + return false; // remove method + return a.indexOf(v) === i; + }); + + options.flags = flags; + var handler = function() { + + if (instance.paused || (instance.isDisabled && (instance.isDisabled('output', 0) || instance.isDisabled('output', 1)))) { + instance.status('503 Service Unavailable'); + this.status = 503; + this.json(); + return; + } + + var key; + var self = this; + + if (instance.options.emptyresponse) { + instance.status('200 OK'); + setTimeout(instance.custom.emptyresponse, 100, self); + + if (instance.hasConnection(0)) { + var data = instance.make({ + query: self.query, + body: self.body, + session: self.session, + user: self.user, + files: self.files, + headers: self.req.headers, + url: self.url, + params: self.params + }); + instance.send2(0, data); + } + + return; + } + + switch (instance.options.cachepolicy) { + case 1: // URL + key = 'rro' + instance.id + self.url.hash(); + break; + case 2: // URL + query + case 3: // URL + query + user + key = self.url; + var keys = Object.keys(self.query); + keys.sort(); + for (var i = 0, length = keys.length; i < length; i++) + key += keys[i] + self.query[keys[i]] + '&'; + if (instance.options.cachepolicy === 3 && self.user) + key += 'iduser' + self.user.id; + key = 'rro' + instance.id + key.hash(); + break; + } + + if (key && F.cache.get2(key)) { + var data = instance.make(F.cache.get2(key)); + data.repository.controller = self; + instance.send2(1, data); + } else { + + var data = instance.make({ + query: self.query, + body: self.body, + session: self.session, + user: self.user, + files: self.files, + headers: self.req.headers, + url: self.url, + params: self.params, + mobile: self.mobile, + robot: self.robot, + referrer: self.referrer, + language: self.language + }); + + data.repository.controller = self; + instance.send2(0, data); + key && FINISHED(self.res, () => F.cache.set(key, self.$flowdata.data, instance.options.cacheexpire)); + } + }; + + if (F.is4) + route = ROUTE(options.method.toUpperCase() + ' ' + options.url, handler, flags, options.size || 5); + else + F.route(options.url, handler, flags, options.size || 5); + + instance.status('Listening', 'green'); + }; + + instance.reconfigure(); + instance.on('options', instance.reconfigure); + instance.on('close', function(){ + uninstall('id:' + instance.id); + }); +}; + +// check url exists +FLOW.trigger('httproutecheckurl', function(next, data) { + var url = data.url; + var method = data.method; + if (url[url.length - 1] !== '/') + url += '/'; + var exists = F.routes.web.findItem(r => r.urlraw === url && r.method === method); + next(exists != null); +}); + +exports.uninstall = function() { + FLOW.trigger('httproutecheckurl', null); +}; diff --git a/RVO15/flow/infosender.js b/RVO15/flow/infosender.js new file mode 100755 index 0000000..587724f --- /dev/null +++ b/RVO15/flow/infosender.js @@ -0,0 +1,81 @@ +exports.id = 'infosender'; +exports.title = 'Info sender'; +exports.version = '1.0.0'; +exports.group = 'Worksys'; +exports.color = '#2134B0'; +exports.input = 2; +exports.output = 1 +exports.icon = 'bolt'; + +const { networkInterfaces } = require('os'); + +exports.html = `
+
+
+
CSV Import
+
+
+
`; + +exports.readme = `# send all data to projects.worksys.io, required to monitor status of controller(unipi)`; + +exports.install = function(instance) { + + let id; + let allValues = {}; + let sendAllValuesInterval; + let configured = false; + + let now = new Date(); + console.log(exports.title, "INSTALLED", now.toLocaleString("sk-SK")); + + const nets = networkInterfaces(); + let ipAddresses = Object.create(null); // Or just '{}', an empty object + + for (const name of Object.keys(nets)) { + for (const net of nets[name]) { + // Skip over non-IPv4 and internal (i.e. 127.0.0.1) addresses + if (net.family === 'IPv4' && !net.internal) { + if (!ipAddresses[name]) { + ipAddresses[name] = []; + } + ipAddresses[name].push(net.address); + } + } + } + + function sendValues() { + if (!configured) return; + + if (Object.keys(allValues).length > 0) { + let dataToSend = { ...allValues }; + dataToSend.id = id; + dataToSend.ipAddresses = ipAddresses; + + instance.send(0, dataToSend); + + allValues = {}; + } + } + + instance.on("close", () => { + clearInterval(sendAllValuesInterval); + }) + + instance.on("0", _ => { + id = FLOW.GLOBALS.settings.project_id; + if (id) configured = true; + else console.log(exports.title, "InfoSender: Unable to send data, no id"); + }) + + instance.on("1", flowdata => { + allValues = { ...allValues, ...flowdata.data }; + //console.log("DATA RECEIVED", flowdata.data); + }) + + sendAllValuesInterval = setInterval(() => { + sendValues(); + }, 60000 * 3); + +} + diff --git a/RVO15/flow/modbus_reader.js b/RVO15/flow/modbus_reader.js new file mode 100755 index 0000000..d6d9dad --- /dev/null +++ b/RVO15/flow/modbus_reader.js @@ -0,0 +1,346 @@ +exports.id = 'modbus_reader'; +exports.title = 'Modbus reader'; +exports.version = '2.0.0'; +exports.group = 'Worksys'; +exports.color = '#2134B0'; +exports.input = 1; +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; +//number of phases inRVO +let phases; +//phases where voltage is 0 (set) +let noVoltage; +let energyToSwitchLamps; + +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.phases = this.buildPhases(); + + this.startSocket(); + } + + buildPhases = () => { + let a = []; + for (let i = 1; i <= phases; i++) { + a.push(`Phase_${i}_voltage`) + } + return a; + } + + startSocket = () => { + + let obj = this; + + if (this.socket) { + this.socket.removeAllListeners(); + this.socket = null; + } + + 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('Modbus_reader: Socket connection error', e); //'ECONNREFUSED' or 'ECONNRESET' ?? + }); + + this.socket.on('close', function() { + console.log('Modbus_reader: Socket connection closed - Waiting 10 seconds before connecting 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 we just start to loop devices from the beginning, or there is just 1 device in config, we wait whole timeoutInterval + if (this.indexInDeviceConfig == 0 || deviceConfig.length === 1) 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 (this.phases.includes(singleValue)) { + let l = singleValue.split("_"); + let phase = parseInt(l[1]); + + // console.log(values[singleValue], tbName); + + if (values[singleValue] == 0) { + noVoltage.add(phase); + sendNotification("modbus_reader: checkNullVoltage", tbName, "no_voltage_on_phase", { phase: phase }, "", SEND_TO.tb, instance, "voltage" + phase); + // console.log('no voltage') + } + else { + noVoltage.delete(phase); + // console.log('voltage detected') + sendNotification("modbus_reader: checkNullVoltage", tbName, "voltage_on_phase_restored", { phase: phase }, "", SEND_TO.tb, instance, "voltage" + phase); + } + } + }) + } + + /** + * function sends notification to slack and to tb, if EM total_power value changes more than numberOfNodes*15. This should show, that RVO lamps has been switched on or off + */ + lampSwitchNotification = (values) => { + + if (!values.hasOwnProperty("total_power")) return; + + const actualTotalPower = values.total_power; + + if (actualTotalPower > energyToSwitchLamps && 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 <= energyToSwitchLamps && 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; + } + + function main() { + + phases = FLOW.GLOBALS.settings.phases; + tbName = FLOW.GLOBALS.settings.rvoTbName; + noVoltage = FLOW.GLOBALS.settings.no_voltage; + energyToSwitchLamps = FLOW.GLOBALS.settings.energy_to_switch_lamps / 2.5; //half value is enought to show if lamps are turned on or off + if (deviceConfig.length) mainSocket = new SocketWithClients(); + else console.log("Modbus_reader: no modbus device in configuration"); + + // this notification is to show, that flow (unipi) has been restarted + sendNotification("modbus_reader", tbName, "flow_restart", {}, "", SEND_TO.slack, instance); + } + + instance.on("0", function(_) { + main(); + }) + +} + diff --git a/RVO15/flow/monitorconsumption.js b/RVO15/flow/monitorconsumption.js new file mode 100755 index 0000000..64cc58e --- /dev/null +++ b/RVO15/flow/monitorconsumption.js @@ -0,0 +1,156 @@ +exports.id = 'monitorconsumption'; +exports.title = 'Consumption'; +exports.version = '1.0.0'; +exports.author = 'Peter Širka'; +exports.group = 'Monitoring'; +exports.color = '#967ADC'; +exports.input = 0; +exports.output = 1; +exports.icon = 'bug'; +exports.options = { interval: 5000, enabled: true, monitorconsumption: true, monitorsize: true, monitorconnections: true, monitorfiles: true }; +exports.click = true; +exports.readme = `# Consumption monitoring + +This component measure CPU and memory consumption, open files and open connections of this application. It uses these Linux commands: \`ps\`, \`lsof\`, \`netstat\` and \`df\`. + +__Data Example__: + +\`\`\`javascript +{ + cpu: 0, // percentage + memory: 4096, // in bytes + size: 34303, // directory size in bytes + files: 34, // count of open files + connections: 343, // count of connections + uptime: '1-12:34:00' +} +\`\`\``; + +exports.html = `
+
+
+
@(Interval in milliseconds)
+
+
+
+
Monitor: Consumption + uptime
+
Monitor: Count of open files
+
Monitor: Count of open connections
+
Monitor: Directory size
+
`; + +exports.install = function(instance) { + + var current = { cpu: 0, memory: 0, files: 0, connections: 0, size: 0, uptime: '', counter: 0 }; + var tproc = null; + var Exec = require('child_process').exec; + var reg_empty = /\s{2,}/g; + var reg_appdisksize = /^[\d.,]+/; + + instance.custom.run = function() { + + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + + var arr = []; + + // Get CPU and Memory consumption + instance.options.monitorconsumption && arr.push(function(next) { + Exec('ps -p {0} -o %cpu,rss,etime'.format(process.pid), function(err, response) { + + if (err) { + instance.throw(err); + } else { + var line = response.split('\n')[1]; + line = line.trim().replace(reg_empty, ' ').split(' '); + var cpu = line[0].parseFloat(); + current.cpu = cpu.floor(1); + current.memory = line[1].parseInt2() * 1024; // kB to bytes + current.uptime = line[2]; + } + + next(); + }); + }); + + // Get count of open files + instance.options.monitorfiles && arr.push(function(next) { + Exec('lsof -a -p {0} | wc -l'.format(process.pid), function(err, response) { + if (err) + instance.throw(err); + else + current.files = response.trim().parseInt2(); + next(); + }); + }); + + // Get count of opened network connections + instance.options.monitorconnections && arr.push(function(next) { + Exec('netstat -an | grep :{0} | wc -l'.format(F.port), function(err, response) { + if (err) { + instance.throw(err); + } else { + current.connections = response.trim().parseInt2() - 1; + if (current.connections < 0) + current.connections = 0; + } + next(); + }); + }); + + // Get directory size + instance.options.monitorsize && current.counter % 5 !== 0 && arr.push(function(next) { + Exec('du -hsb ' + process.cwd(), function(err, response) { + if (err) { + instance.throw(err); + } else { + var match = response.trim().match(reg_appdisksize); + match && (current.size = match.toString().trim().parseInt2()); + } + next(); + }); + }); + + arr.async(function() { + + tproc && clearTimeout(tproc); + + if (instance.options.enabled) { + tproc = setTimeout(instance.custom.run, instance.options.interval); + instance.send2(current); + } + + instance.custom.status(); + current.counter++; + }); + }; + + instance.custom.status = function() { + if (instance.options.enabled) + instance.status('{0}% / {1}'.format(current.cpu, current.memory.filesize())); + else + instance.status('Disabled', 'red'); + }; + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + + if (instance.options.enabled) { + current.counter = 0; + instance.custom.run(); + } + + }); + + instance.on('close', function() { + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + }); + + setTimeout(instance.custom.run, 1000); +}; \ No newline at end of file diff --git a/RVO15/flow/monitordisk.js b/RVO15/flow/monitordisk.js new file mode 100755 index 0000000..f4fdaa0 --- /dev/null +++ b/RVO15/flow/monitordisk.js @@ -0,0 +1,96 @@ +exports.id = 'monitordisk'; +exports.title = 'Disk'; +exports.version = '1.0.0'; +exports.author = 'Peter Širka'; +exports.group = 'Monitoring'; +exports.color = '#F6BB42'; +exports.output = 1; +exports.icon = 'hdd-o'; +exports.click = true; +exports.options = { interval: 8000, path: '/', enabled: true }; +exports.readme = `# Disk monitoring + +This component monitors disk \`bytes\` consumption in Linux systems. It uses \`df\` command. + +__Data Example__: + +\`\`\`javascript +{ + total: 474549649408, + used: 39125245952, + free: 411294994432 +} +\`\`\``; + +exports.html = `
+
+
+
@(Interval in milliseconds)
+
+
+
@(Path)
+
+
+
`; + +exports.install = function(instance) { + + var current = { total: 0, used: 0, free: 0, path: '', type: '', percentUsed: 0 }; + var tproc = null; + + instance.custom.run = function() { + + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + + if (!instance.options.enabled) + return; + + require('child_process').exec('df -hTB1 ' + instance.options.path, function(err, response) { + + tproc = setTimeout(instance.custom.run, instance.options.interval); + + if (err) { + instance.error(err); + return; + } + + response.parseTerminal(function(line) { + if (line[0][0] !== '/') + return; + current.total = line[2].parseInt(); + current.free = line[4].parseInt(); + current.used = line[3].parseInt(); + current.path = instance.options.path || '/'; + current.type = line[1]; + current.percentUsed = line[5]; + instance.custom.status(); + instance.send2(current); + }); + }); + }; + + instance.custom.status = function() { + if (instance.options.enabled) + instance.status(current.free.filesize() + ' / ' + current.total.filesize()); + else + instance.status('Disabled', 'red'); + }; + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + instance.options.enabled && instance.custom.run(); + }); + + instance.on('close', function() { + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + }); + + setTimeout(instance.custom.run, 1000); +}; \ No newline at end of file diff --git a/RVO15/flow/monitormemory.js b/RVO15/flow/monitormemory.js new file mode 100755 index 0000000..2decbc4 --- /dev/null +++ b/RVO15/flow/monitormemory.js @@ -0,0 +1,87 @@ +exports.id = 'monitormemory'; +exports.title = 'Memory'; +exports.version = '1.0.0'; +exports.author = 'Peter Širka'; +exports.group = 'Monitoring'; +exports.color = '#F6BB42'; +exports.output = 1; +exports.click = true; +exports.icon = 'microchip'; +exports.options = { interval: 8000, enabled: true }; +exports.readme = `# Memory monitoring + +This component monitors memory \`bytes\` consumption in Linux systems. It uses \`free\` command. + +__Data Example__: + +\`\`\`javascript +{ + total: 33558769664, + used: 1998868480, + free: 2653708288 +} +\`\`\``; + +exports.html = `
+
+
+
@(Interval in milliseconds)
+
+
+
`; + +exports.install = function(instance) { + + var current = { total: 0, used: 0, free: 0 }; + var tproc = null; + + instance.custom.run = function() { + + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + + if (!instance.options.enabled) + return; + + require('child_process').exec('free -b -t', function(err, response) { + + tproc = setTimeout(instance.custom.run, instance.options.interval); + + if (err) { + instance.error(err); + return; + } + + var memory = response.split('\n')[1].match(/\d+/g); + current.total = memory[0].parseInt(); + current.used = memory[1].parseInt() - memory[3].parseInt(); + current.free = current.total - current.used; + instance.custom.status(); + instance.send2(current); + }); + }; + + instance.custom.status = function() { + if (instance.options.enabled) + instance.status(current.free.filesize() + ' / ' + current.total.filesize()); + else + instance.status('Disabled', 'red'); + }; + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + instance.options.enabled && instance.custom.run(); + }); + + instance.on('close', function() { + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + }); + + setTimeout(instance.custom.run, 1000); +}; \ No newline at end of file diff --git a/RVO15/flow/nodesdb_changecheck.js b/RVO15/flow/nodesdb_changecheck.js new file mode 100755 index 0000000..9adab62 --- /dev/null +++ b/RVO15/flow/nodesdb_changecheck.js @@ -0,0 +1,77 @@ +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 = 2; +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); + } + } + + //kedze do slacku posielame stringy, na cloud musime previest vsetky stringy spat na objekty: + // Funkcia na parsovanie všetkých reťazcov v poli + const parseArray = (arr) => { + return arr.map(jsonString => JSON.parse(jsonString)); + }; + + 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); + if (FLOW.GLOBALS.settings.send_changed_node_numbers) instance.send(1, { aktualneNody: parseArray(zmenene), originalne: parseArray(Array.from(set2)) }); + } + 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/RVO15/flow/show_dbdata.js b/RVO15/flow/show_dbdata.js new file mode 100755 index 0000000..1e23ff7 --- /dev/null +++ b/RVO15/flow/show_dbdata.js @@ -0,0 +1,243 @@ +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 = 8; +exports.output = 1; + +const { exec } = require('child_process'); + +exports.install = 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 }) + }) + instance.on("5", _ => { + exec("sudo tail -n 25 monitor.txt", (err, stdout, stderr) => { + if (err || stderr) instance.send(0, { err, stderr }); + else instance.send(0, stdout); + }) + }) + instance.on("6", _ => { + exec("sudo tail -n 25 err.txt", (err, stdout, stderr) => { + if (err || stderr) instance.send(0, { err, stderr }); + else instance.send(0, stdout); + }) + }) + instance.on("7", _ => { + instance.send(0, FLOW.deviceStatus); + }) +}; + + +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/RVO15/flow/slack_filter.js b/RVO15/flow/slack_filter.js new file mode 100755 index 0000000..6618523 --- /dev/null +++ b/RVO15/flow/slack_filter.js @@ -0,0 +1,188 @@ +exports.id = 'slack_filter'; +exports.title = 'Slack Filter'; +exports.group = 'Citysys'; +exports.color = '#30E193'; +exports.input = 2; +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 = `
+
+
+
@(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('0', 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']['en']; + 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"] = []; + } + + instance.options.name = FLOW.GLOBALS.settings.rvo_name; + if (instance.options.name) { + instance.status('Running'); + running = true; + } else { + instance.status('Please run options again', 'red'); + running = false; + } + } catch (e) { + instance.error('Citysys connector: ' + e.message); + } + }; + + instance.on('options', instance.reconfigure); + + instance.on("1", _ => { + instance.reconfigure(); + }) +}; diff --git a/RVO15/flow/thermometer.js b/RVO15/flow/thermometer.js new file mode 100755 index 0000000..fc7074d --- /dev/null +++ b/RVO15/flow/thermometer.js @@ -0,0 +1,99 @@ +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 = 5;//minutes +let NUMBER_OF_FAILURES_TO_SEND_ERROR = 13; + +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) => { + + 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); + setTimeout(main, 20000); + }) +}; diff --git a/RVO15/flow/trigger.js b/RVO15/flow/trigger.js new file mode 100755 index 0000000..27545a8 --- /dev/null +++ b/RVO15/flow/trigger.js @@ -0,0 +1,79 @@ +exports.id = 'trigger'; +exports.title = 'Trigger'; +exports.group = 'Inputs'; +exports.color = '#F6BB42'; +exports.click = true; +exports.output = 1; +exports.version = '1.1.0'; +exports.author = 'Martin Smola'; +exports.icon = 'play'; + +exports.html = `
+
@(Data type (String by default))
+
@(Data)
+
Trigger 5s after initialization.
+
@(Useful when there's a need to run certain flow when the app restarts, etc.)
+
`; + +exports.readme = `# Trigger + +- Clicking on the component starts the chain +- Settings allows to set a data-type and a value`; + +exports.install = function(instance) { + + var value; + + instance.on('click', () => instance.send2(value)); + + instance.reconfigure = function() { + var options = instance.options; + value = null; + switch (options.datatype) { + case 'integer': + value = options.data.parseInt2('error'); + value = value === 'error' ? NaN : value; + break; + case 'float': + value = options.data.parseFloat2('error'); + value = value === 'error' ? NaN : value; + break; + case 'date': + options.data = options.data.toString(); + var num = options.data.parseInt('error'); + num === 'error' && (num = options.data.parseDate('error')); + num === 'error' && (num = null); + value = num ? new Date(num).toUTCString() : num; + break; + case 'object': + try { + value = (new Function('return ' + options.data))(); + } catch (e) { + instance.error(e); + } + break; + case 'boolean': + value = options.data.parseBoolean(); + break; + case 'buffer': + try { + value = U.createBuffer(options.data); + } catch (e) { + instance.error(e); + } + break; + case 'string': + default: + value = '' + (options.data || ''); + break; + } + }; + + instance.on('options', instance.reconfigure); + instance.reconfigure(); + + if (instance.options.restart) + setTimeout(function(){ + instance.send2(value); + }, 5000); +}; diff --git a/RVO15/flow/variables.txt b/RVO15/flow/variables.txt new file mode 100755 index 0000000..e69de29 diff --git a/RVO15/flow/virtualwirein.js b/RVO15/flow/virtualwirein.js new file mode 100755 index 0000000..38a4e42 --- /dev/null +++ b/RVO15/flow/virtualwirein.js @@ -0,0 +1,43 @@ +exports.id = 'virtualwirein'; +exports.title = 'Virtual wire in'; +exports.version = '1.0.0'; +exports.author = 'Martin Smola'; +exports.color = '#303E4D'; +exports.icon = 'sign-in'; +exports.input = false; +exports.output = 1; +exports.options = {}; +exports.readme = `# Virtual wire in + +When the wires between the components are mess it's time to use Virtual wire.`; + +exports.html = `
+
@(Wire name)
+
+`; + +exports.install = function(instance) { + + instance.custom.reconfigure = function(options){ + if (instance.options.wirename) { + instance.status(instance.options.wirename); + } else + instance.status('Not configured', 'red'); + }; + + ON('virtualwire', function(wirename, flowdata){ + if (instance.options.wirename && instance.options.wirename === wirename) + instance.send(flowdata); + }); + + instance.on('options', instance.custom.reconfigure); + instance.custom.reconfigure(); +}; diff --git a/RVO15/flow/virtualwireout.js b/RVO15/flow/virtualwireout.js new file mode 100755 index 0000000..94a1e4f --- /dev/null +++ b/RVO15/flow/virtualwireout.js @@ -0,0 +1,41 @@ +exports.id = 'virtualwireout'; +exports.title = 'Virtual wire out'; +exports.version = '1.0.0'; +exports.author = 'Martin Smola'; +exports.color = '#303E4D'; +exports.icon = 'sign-out'; +exports.input = true; +exports.options = {}; +exports.readme = `# Virtual wire out + +When the wires between the components are mess it's time to use Virtual wire.`; + +exports.html = `
+
@(Wire name)
+
+`; + +exports.install = function(instance) { + + instance.custom.reconfigure = function(){ + if (instance.options.wirename) { + instance.status(instance.options.wirename); + } else + instance.status('Not configured', 'red'); + }; + + instance.on('data', function(flowdata) { + EMIT('virtualwire', instance.options.wirename, flowdata); + }); + + instance.on('options', instance.custom.reconfigure); + instance.custom.reconfigure(); +}; diff --git a/RVO15/flow/wsmqttpublish.js b/RVO15/flow/wsmqttpublish.js new file mode 100755 index 0000000..0eba804 --- /dev/null +++ b/RVO15/flow/wsmqttpublish.js @@ -0,0 +1,448 @@ +exports.id = 'wsmqttpublish'; +exports.title = 'WS MQTT publish'; +exports.group = 'MQTT'; +exports.color = '#888600'; +exports.version = '1.0.2'; +exports.icon = 'sign-out'; +exports.input = 2; +exports.output = 3; +exports.options = { host: 'tb-stage.worksys.io', port: 1883, clientid: "", username: "" }; + +exports.html = `
+
+
+
Hostname or IP address (if not empty - setting will override db setting)
+
+
+
Port
+
+
+
+
+
@(Client id)
+
+
+
@(Username)
+
+
+
`; + + +exports.readme = ` +# WS MQTT Publish + +Version 1.0.3. + +Added: +- database collections, +- 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 = { + debug: 0, + rpcCall: 1, + services: 2 +} + +//CONFIG +let createTelemetryBackup = true; +let saveTelemetryOnError = true;//backup_on_failure overrides this value +//------------------------ + +let rollers; +if (createTelemetryBackup) rollers = require('streamroller'); + +const noSqlFileSizeLimit = 4194304;//use 5MB - 4194304 +let insertNoSqlCounter = 0; +let insertBackupNoSqlCounter = 0; +let processingData = false; + +let backup_on_failure = false;//== saveTelemetryOnError - create backup client 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; + +process.on('uncaughtException', function(err) { + + errLogger.error('uncaughtException:', err.message) + errLogger.error(err.stack); + + //TODO + //send to service + + //process.exit(1); +}) + +const nosql = NOSQL('tbdata'); +const nosqlBackup = NOSQL('/backup/tbdata'); + + +exports.install = function(instance) { + + var client; + var opts; + var clientReady = false; + + // wsmqtt status for notification purposes on projects.worksys.io database + let wsmqttName = null; + let sendWsStatusVar = null; + let wsmqtt_status = 'disconnected'; + + 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'; + } + + function sendWsStatus() { + instance.send(SEND_TO.services, { [wsmqttName]: wsmqtt_status }); + } + + + function main() { + if (!FLOW.dbLoaded) return; + + loadSettings(); + clearInterval(sendWsStatus); + sendWsStatusVar = setInterval(sendWsStatus, 180000); + } + + //set opts according to db settings + function loadSettings() { + + if (instance.options.host !== "") { + //override settings from database + var o = instance.options; + opts = { + host: o.host, + port: o.port, + clientId: o.clientid, + username: o.username, + rejectUnauthorized: false, + resubscribe: false + }; + + wsmqttName = getWsmqttName(o.host); + + console.log("wsmqttpublich -> loadSettings from instance.options", instance.options); + } + else { + + const SETTINGS = FLOW.GLOBALS.settings; + backup_on_failure = SETTINGS.backup_on_failure; + saveTelemetryOnError = backup_on_failure; + + restore_from_backup = SETTINGS.restore_from_backup; + restore_backup_wait = SETTINGS.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; + + opts = { + host: mqtt_host, + port: mqtt_port, + keepalive: 10, + clientId: mqtt_clientid, + username: mqtt_username, + rejectUnauthorized: false, + resubscribe: false + }; + + wsmqttName = getWsmqttName(mqtt_host); + } + + connectToTbServer(); + } + + function connectToTbServer() { + 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"); + //monitor.info("MQTT client connected"); + + sendClientError = true; + clientReady = true; + wsmqtt_status = 'connected'; + }); + + client.on('reconnect', function() { + instance.status("Reconnecting", "yellow"); + clientReady = false; + }); + + client.on('message', function(topic, message) { + // message is type of buffer + message = message.toString(); + if (message[0] === '{') { + TRY(function() { + + message = JSON.parse(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 } }); + } + + }, () => instance.debug('MQTT: Error parsing data', message)); + } + + instance.send(SEND_TO.rpcCall, { "topic": topic, "content": message }); + }); + + client.on('close', function() { + clientReady = false; + wsmqtt_status = 'disconnected'; + + instance.status("Disconnected", "red"); + instance.send(SEND_TO.debug, { "message": "Client CLOSE signal received !" }); + }); + + client.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; + wsmqtt_status = 'disconnected'; + }); + + } + + + instance.on("0", _ => { + main(); + }) + + + instance.on('1', function(data) { + + if (clientReady) { + //do we have some data in backup file? if any, process data from database + if (saveTelemetryOnError) { + //read telemetry data and send back to server + if (!processingData) processDataFromDatabase(); + } + + let stringifiedJson = JSON.stringify(data.data); + client.publish("v1/gateway/telemetry", stringifiedJson, { qos: 1 }); + + //backup telemetry + if (createTelemetryBackup) { + data.data.id = UID(); + nosqlBackup.insert(data.data); + + insertBackupNoSqlCounter++; + if (insertBackupNoSqlCounter > 150) { + let options = { compress: true }; + let path = __dirname + "/../databases/backup/tbdata.nosql"; + var stream = new rollers.RollingFileStream(path, noSqlFileSizeLimit, 150, options); + stream.write(""); + stream.end(); + + insertBackupNoSqlCounter = 0; + } + } + + } + 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 (saveTelemetryOnError) { + //create new file from tbdata.nosql, if file size exceeds given limit, and clear tbdata.nosql + makeBackupFromDbFile(); + + //write to tb + data.data.id = UID(); + nosql.insert(data.data); + } + } + }); + + + instance.close = function(done) { + if (clientReady) { + client.end(); + clearInterval(sendWsStatusVar); + } + }; + + + function getDbBackupFileCounter(type) { + var files = fs.readdirSync(__dirname + "/../databases"); + + let counter = 0; + for (var i = 0; i < files.length; i++) { + + if (files[i] == "tbdata.nosql") continue; + + if (files[i].endsWith(".nosql")) { + + let pos = files[i].indexOf("."); + if (pos > -1) { + + let fileCounter = counter; + let firstDigit = files[i].slice(0, pos); + + fileCounter = parseInt(firstDigit); + if (isNaN(fileCounter)) fileCounter = 0; + //console.log("getDbBackupFileCounter digit:", files[i], firstDigit, fileCounter, isNaN(fileCounter), type); + + if (type == "max") { + if (fileCounter > counter) { + counter = fileCounter; + } + } + else if (type == "min") { + if (counter == 0) counter = fileCounter; + + if (fileCounter < counter) { + counter = fileCounter; + } + } + } + } + + } + + if (type == "max") counter++; + + return counter; + } + + const makeBackupFromDbFile = async () => { + + if (!saveTelemetryOnError) return; + + //to avoid large file: tbdata.nosql + + //init value is 0! + if (insertNoSqlCounter > 0) { + --insertNoSqlCounter; + return; + } + + insertNoSqlCounter = 100; + + let source = __dirname + "/../databases/tbdata.nosql"; + + var stats = fs.statSync(source); + var fileSizeInBytes = stats.size; + + if (fileSizeInBytes > noSqlFileSizeLimit) { + + let counter = 1; + counter = getDbBackupFileCounter("max"); + + let destination = __dirname + "/../databases/" + counter + "." + "tbdata.nosql"; + + //make backup file + fs.copyFileSync(source, destination); + //fs.renameSync(p, p + "." + counter); + + //clear tbdata.nosql + fs.writeFileSync(source, ""); + fs.truncateSync(source, 0); + + } + } + + const processDataFromDatabase = async () => { + + if (restore_from_backup <= 0) return; + + //calculate diff + const now = new Date(); + let currentTime = now.getTime(); + let diff = currentTime - lastRestoreTime; + + if ((diff / 1000) < restore_backup_wait) { + //console.log("*********restore_backup_wait", diff, restore_backup_wait); + return; + } + + processingData = true; + + //get filename to process + let counter = getDbBackupFileCounter("min"); + + //we have some backup files + let dataBase = 'tbdata'; + + var nosql; + if (counter == 0) dataBase = 'tbdata'; + else dataBase = counter + "." + 'tbdata'; + + nosql = NOSQL(dataBase); + + //select all data - use limit restore_from_backup + let records = await promisifyBuilder(nosql.find().take(restore_from_backup)); + + for (let i = 0; i < records.length; i++) { + if (clientReady) { + + let item = records[i]; + let id = item.id; + + if (id !== undefined) { + //console.log("------------processDataFromDatabase - remove", id, dataBase, i); + + try { + + let message = JSON.parse(JSON.stringify(item)); + delete message.id; + + client.publish("v1/gateway/telemetry", JSON.stringify(message), { qos: 1 }); + + //remove from database + await promisifyBuilder(nosql.remove().where("id", id)); + + } catch (error) { + //process error + console.log("processDataFromDatabase", error); + } + + } + + } + else { + processingData = false; + return; + } + } + + if (records.length > 0) { + //clean backup file + if (counter > 0) nosql.clean(); + } + + //no data in db, remove + if (records.length == 0) { + if (counter > 0) nosql.drop(); + } + + const d = new Date(); + lastRestoreTime = d.getTime(); + + processingData = false; + + } + + instance.on('options', main); + //instance.reconfigure(); +}; diff --git a/RVO15/monitor.txt b/RVO15/monitor.txt new file mode 100755 index 0000000..76b8525 --- /dev/null +++ b/RVO15/monitor.txt @@ -0,0 +1,543 @@ +[2025-09-30T09:28:38.187] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-09-30T09:28:43.546] [INFO] monitorLogs - buildTasks - params undefined +[2025-09-30T09:28:43.551] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-09-30T09:28:43.552] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-09-30T09:28:43.553] [INFO] monitorLogs - 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 +} +[2025-09-30T09:28:43.556] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-30T09:28:43.557] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-09-30T11:00:00.556Z +[2025-09-30T09:28:43.558] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-09-30T09:28:43.560] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-09-30T09:28:43.560] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-09-30T09:28:43.561] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-30T09:28:43.564] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-30T09:28:43.565] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-10-01T05:19:00.565Z +[2025-09-30T09:28:43.566] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-09-30T17:04:00.566Z +[2025-09-30T09:28:43.566] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:19', name: 'luxOff' }, + { value: 1, start_time: '19:4', name: 'luxOn' } +] +[2025-09-30T09:28:43.567] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-09-30T09:28:43.568] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-09-30T09:28:43.569] [INFO] monitorLogs - 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 +} +[2025-09-30T09:28:43.570] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-30T09:28:43.571] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-09-30T11:00:00.571Z +[2025-09-30T09:28:43.572] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-09-30T09:28:43.573] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-09-30T09:28:43.600] [INFO] monitorLogs - tasks created: 2042 +[2025-09-30T09:28:43.602] [INFO] monitorLogs - -->FLOW bol spustený zrR51V2ajQ9ZLygPKkEMDakYDq38xOJolENBXGnv 2025-08-08 +[2025-09-30T09:28:48.618] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-30T18:45:52.856] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-01T03:28:45.013] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-01 03:28:45 +[2025-10-01T06:40:49.122] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-01T18:45:46.307] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-02T03:28:46.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-02 03:28:46 +[2025-10-02T06:35:41.006] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-02T18:43:08.841] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-03T03:28:47.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-03 03:28:47 +[2025-10-03T06:38:04.989] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-03T14:47:56.128] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-03T14:48:01.488] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-03T14:48:01.493] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-03T14:48:01.494] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-03T14:48:01.495] [INFO] monitorLogs - 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 +} +[2025-10-03T14:48:01.497] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-03T14:48:01.499] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-10-04T11:00:00.498Z +[2025-10-03T14:48:01.500] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-03T14:48:01.501] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-10-03T14:48:01.502] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-03T14:48:01.503] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-03T14:48:01.506] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-03T14:48:01.507] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-10-04T05:24:00.506Z +[2025-10-03T14:48:01.507] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-10-03T16:58:00.507Z +[2025-10-03T14:48:01.508] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:24', name: 'luxOff' }, + { value: 1, start_time: '18:58', name: 'luxOn' } +] +[2025-10-03T14:48:01.509] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-10-03T14:48:01.510] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-03T14:48:01.510] [INFO] monitorLogs - 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 +} +[2025-10-03T14:48:01.512] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-03T14:48:01.513] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-10-04T11:00:00.512Z +[2025-10-03T14:48:01.513] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-03T14:48:01.514] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-10-03T14:48:01.542] [INFO] monitorLogs - tasks created: 2042 +[2025-10-03T14:48:01.545] [INFO] monitorLogs - -->FLOW bol spustený zrR51V2ajQ9ZLygPKkEMDakYDq38xOJolENBXGnv 2025-08-08 +[2025-10-03T14:48:06.561] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-03T18:39:04.378] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-04T03:48:03.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-04 03:48:03 +[2025-10-04T06:39:02.239] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-04T18:28:56.000] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-05T03:48:04.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-05 03:48:04 +[2025-10-05T06:41:25.148] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-05T18:33:49.740] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-06T03:48:05.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-06 03:48:05 +[2025-10-06T06:51:19.338] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-06T18:26:09.926] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-07T03:48:06.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-07 03:48:06 +[2025-10-07T06:46:10.731] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-07T18:31:03.648] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-08T03:48:07.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-08 03:48:07 +[2025-10-08T06:46:05.379] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-08T18:28:27.929] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-08T23:28:24.721] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-08T23:28:30.081] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-08T23:28:30.086] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-08T23:28:30.087] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-08T23:28:30.087] [INFO] monitorLogs - 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 +} +[2025-10-08T23:28:30.090] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-08T23:28:30.092] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-10-09T11:00:00.091Z +[2025-10-08T23:28:30.093] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-08T23:28:30.094] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-10-08T23:28:30.095] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-08T23:28:30.095] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-08T23:28:30.099] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-08T23:28:30.099] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-10-09T05:31:00.099Z +[2025-10-08T23:28:30.100] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-10-09T16:47:00.100Z +[2025-10-08T23:28:30.101] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:31', name: 'luxOff' }, + { value: 1, start_time: '18:47', name: 'luxOn' } +] +[2025-10-08T23:28:30.102] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-10-08T23:28:30.103] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-08T23:28:30.103] [INFO] monitorLogs - 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 +} +[2025-10-08T23:28:30.105] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-08T23:28:30.105] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-10-09T11:00:00.105Z +[2025-10-08T23:28:30.106] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-08T23:28:30.107] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-10-08T23:28:30.135] [INFO] monitorLogs - tasks created: 2042 +[2025-10-08T23:28:30.138] [INFO] monitorLogs - -->FLOW bol spustený zrR51V2ajQ9ZLygPKkEMDakYDq38xOJolENBXGnv 2025-08-08 +[2025-10-08T23:28:35.153] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-08T23:31:26.435] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-08T23:31:31.798] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-08T23:31:31.803] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-08T23:31:31.804] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-08T23:31:31.805] [INFO] monitorLogs - 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 +} +[2025-10-08T23:31:31.808] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-08T23:31:31.809] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-10-09T11:00:00.808Z +[2025-10-08T23:31:31.810] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-08T23:31:31.812] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-10-08T23:31:31.812] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-08T23:31:31.813] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-08T23:31:31.816] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-08T23:31:31.817] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-10-09T05:31:00.817Z +[2025-10-08T23:31:31.818] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-10-09T16:47:00.818Z +[2025-10-08T23:31:31.818] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:31', name: 'luxOff' }, + { value: 1, start_time: '18:47', name: 'luxOn' } +] +[2025-10-08T23:31:31.819] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-10-08T23:31:31.820] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-08T23:31:31.821] [INFO] monitorLogs - 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 +} +[2025-10-08T23:31:31.822] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-08T23:31:31.823] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-10-09T11:00:00.823Z +[2025-10-08T23:31:31.824] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-08T23:31:31.824] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-10-08T23:31:31.852] [INFO] monitorLogs - tasks created: 2042 +[2025-10-08T23:31:31.855] [INFO] monitorLogs - -->FLOW bol spustený zrR51V2ajQ9ZLygPKkEMDakYDq38xOJolENBXGnv 2025-08-08 +[2025-10-08T23:31:36.872] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-09T03:31:33.013] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-09 03:31:33 +[2025-10-09T06:58:19.746] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-09T16:53:04.351] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-09T16:53:09.708] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-09T16:53:09.713] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-09T16:53:09.714] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-09T16:53:09.715] [INFO] monitorLogs - 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 +} +[2025-10-09T16:53:09.717] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T16:53:09.719] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-10-10T11:00:00.718Z +[2025-10-09T16:53:09.720] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-09T16:53:09.721] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-10-09T16:53:09.722] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-09T16:53:09.722] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-09T16:53:09.726] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T16:53:09.727] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-10-10T05:32:00.726Z +[2025-10-09T16:53:09.727] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-10-09T16:45:00.727Z +[2025-10-09T16:53:09.728] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T16:53:09.729] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-10-09T16:53:09.730] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-09T16:53:09.730] [INFO] monitorLogs - 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 +} +[2025-10-09T16:53:09.732] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T16:53:09.733] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-10-10T11:00:00.732Z +[2025-10-09T16:53:09.733] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-09T16:53:09.734] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-10-09T16:53:09.761] [INFO] monitorLogs - tasks created: 2042 +[2025-10-09T16:53:09.763] [INFO] monitorLogs - -->FLOW bol spustený zrR51V2ajQ9ZLygPKkEMDakYDq38xOJolENBXGnv 2025-08-08 +[2025-10-09T16:53:14.780] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-09T18:23:43.918] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-09T19:05:36.938] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-09T19:05:42.288] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-09T19:05:42.293] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-09T19:05:42.294] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-09T19:05:42.295] [INFO] monitorLogs - 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 +} +[2025-10-09T19:05:42.298] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T19:05:42.299] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-10-10T11:00:00.299Z +[2025-10-09T19:05:42.301] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-09T19:05:42.302] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-10-09T19:05:42.303] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-09T19:05:42.303] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-09T19:05:42.306] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T19:05:42.307] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-10-10T05:32:00.307Z +[2025-10-09T19:05:42.308] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-10-10T16:45:00.308Z +[2025-10-09T19:05:42.309] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T19:05:42.310] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-10-09T19:05:42.310] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-09T19:05:42.311] [INFO] monitorLogs - 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 +} +[2025-10-09T19:05:42.312] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T19:05:42.313] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-10-10T11:00:00.313Z +[2025-10-09T19:05:42.314] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-09T19:05:42.315] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-10-09T19:05:42.343] [INFO] monitorLogs - tasks created: 2042 +[2025-10-09T19:05:42.346] [INFO] monitorLogs - -->FLOW bol spustený zrR51V2ajQ9ZLygPKkEMDakYDq38xOJolENBXGnv 2025-08-08 +[2025-10-09T19:05:47.361] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-10T03:05:44.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-10 03:05:44 +[2025-10-10T06:55:54.096] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-10T18:18:12.108] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-11T03:05:45.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-11 03:05:45 +[2025-10-11T06:58:17.232] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-11T18:23:05.972] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-12T03:05:46.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-12 03:05:46 +[2025-10-12T06:58:09.618] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-12T18:20:27.629] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-13T03:05:47.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-13 03:05:47 +[2025-10-13T06:53:01.284] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-13T18:22:51.465] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-14T03:05:48.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-14 03:05:48 +[2025-10-14T06:55:25.694] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-14T18:15:12.545] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-15T03:05:49.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-15 03:05:49 +[2025-10-15T07:02:50.224] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-15T11:38:20.163] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-15T11:38:25.525] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-15T11:38:25.530] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-15T11:38:25.531] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-15T11:38:25.532] [INFO] monitorLogs - 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 +} +[2025-10-15T11:38:25.535] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-15T11:38:25.536] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-10-15T11:00:00.535Z +[2025-10-15T11:38:25.537] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-15T11:38:25.539] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-10-15T11:38:25.539] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-15T11:38:25.540] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-15T11:38:25.543] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-15T11:38:25.544] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-10-16T05:41:00.544Z +[2025-10-15T11:38:25.545] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-10-15T16:33:00.545Z +[2025-10-15T11:38:25.546] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:41', name: 'luxOff' }, + { value: 1, start_time: '18:33', name: 'luxOn' } +] +[2025-10-15T11:38:25.547] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-10-15T11:38:25.547] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-15T11:38:25.548] [INFO] monitorLogs - 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 +} +[2025-10-15T11:38:25.549] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-15T11:38:25.550] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-10-15T11:00:00.550Z +[2025-10-15T11:38:25.551] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-15T11:38:25.552] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-10-15T11:38:25.579] [INFO] monitorLogs - tasks created: 2042 +[2025-10-15T11:38:25.582] [INFO] monitorLogs - -->FLOW bol spustený zrR51V2ajQ9ZLygPKkEMDakYDq38xOJolENBXGnv 2025-10-08 +[2025-10-15T11:38:30.598] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-15T18:15:02.068] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor diff --git a/RVO15/package-lock.json b/RVO15/package-lock.json new file mode 100755 index 0000000..cc5cfd9 --- /dev/null +++ b/RVO15/package-lock.json @@ -0,0 +1,2125 @@ +{ + "name": "emptyproject", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "emptyproject", + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "bitwise": "^2.1.0", + "easy-crc": "0.0.2", + "jsmodbus": "^4.0.6", + "log4js": "^6.3.0", + "mqtt": "^4.2.6", + "nodemailer": "^6.9.7", + "serialport": "^9.2.8", + "total.js": "^3.4.13" + } + }, + "node_modules/@serialport/binding-abstract": { + "version": "9.2.3", + "resolved": "https://registry.npmjs.org/@serialport/binding-abstract/-/binding-abstract-9.2.3.tgz", + "integrity": "sha512-cQs9tbIlG3P0IrOWyVirqlhWuJ7Ms2Zh9m2108z6Y5UW/iVj6wEOiW8EmK9QX9jmJXYllE7wgGgvVozP5oCj3w==", + "dependencies": { + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/binding-mock": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/binding-mock/-/binding-mock-9.2.4.tgz", + "integrity": "sha512-dpEhACCs44oQhh6ajJfJdvQdK38Vq0N4W6iD/gdplglDCK7qXRQCMUjJIeKdS/HSEiWkC3bwumUhUufdsOyT4g==", + "dependencies": { + "@serialport/binding-abstract": "9.2.3", + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/bindings": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/@serialport/bindings/-/bindings-9.2.8.tgz", + "integrity": "sha512-hSLxTe0tADZ3LMMGwvEJWOC/TaFQTyPeFalUCsJ1lSQ0k6bPF04JwrtB/C81GetmDBTNRY0GlD0SNtKCc7Dr5g==", + "hasInstallScript": true, + "dependencies": { + "@serialport/binding-abstract": "9.2.3", + "@serialport/parser-readline": "9.2.4", + "bindings": "^1.5.0", + "debug": "^4.3.2", + "nan": "^2.15.0", + "prebuild-install": "^7.0.0" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-byte-length": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-byte-length/-/parser-byte-length-9.2.4.tgz", + "integrity": "sha512-sQD/iw4ZMU3xW9PLi0/GlvU6Y623jGeWecbMkO7izUo/6P7gtfv1c9ikd5h0kwL8AoAOpQA1lxdHIKox+umBUg==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-cctalk": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-cctalk/-/parser-cctalk-9.2.4.tgz", + "integrity": "sha512-T4TU5vQMwmo9AB3gQLFDWbfJXlW5jd9guEsB/nqKjFHTv0FXPdZ7DQ2TpSp8RnHWxU3GX6kYTaDO20BKzc8GPQ==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-delimiter": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-delimiter/-/parser-delimiter-9.2.4.tgz", + "integrity": "sha512-4nvTAoYAgkxFiXrkI+3CA49Yd43CODjeszh89EK+I9c8wOZ+etZduRCzINYPiy26g7zO+GRAb9FoPCsY+sYcbQ==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-inter-byte-timeout": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-inter-byte-timeout/-/parser-inter-byte-timeout-9.2.4.tgz", + "integrity": "sha512-SOAdvr0oBQIOCXX198hiTlxs4JTKg9j5piapw5tNq52fwDOWdbYrFneT/wN04UTMKaDrJuEvXq6T4rv4j7nJ5A==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-readline": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-readline/-/parser-readline-9.2.4.tgz", + "integrity": "sha512-Z1/qrZTQUVhNSJP1hd9YfDvq0o7d87rNwAjjRKbVpa7Qi51tG5BnKt43IV3NFMyBlVcRe0rnIb3tJu57E0SOwg==", + "dependencies": { + "@serialport/parser-delimiter": "9.2.4" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-ready": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-ready/-/parser-ready-9.2.4.tgz", + "integrity": "sha512-Pyi94Itjl6qAURwIZr/gmZpMAyTmKXThm6vL5DoAWGQjcRHWB0gwv2TY2v7N+mQLJYUKU3cMnvnATXxHm7xjxw==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-regex": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-regex/-/parser-regex-9.2.4.tgz", + "integrity": "sha512-sI/cVvPOYz+Dbv4ZdnW16qAwvXiFf/1pGASQdbveRTlgJDdz7sRNlCBifzfTN2xljwvCTZYqiudKvDdC1TepRQ==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/stream": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/stream/-/stream-9.2.4.tgz", + "integrity": "sha512-bLye8Ub4vUFQGmkh8qEqehr7SE7EJs2yDs0h9jzuL5oKi+F34CFmWkEErO8GAOQ8YNn7p6b3GxUgs+0BrHHDZQ==", + "dependencies": { + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "node_modules/are-we-there-yet": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", + "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/base64-js": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", + "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==" + }, + "node_modules/bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "dependencies": { + "file-uri-to-path": "1.0.0" + } + }, + "node_modules/bitwise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/bitwise/-/bitwise-2.1.0.tgz", + "integrity": "sha512-XKgAhMXCh4H/3oNwAHAsAO0iC89s9cOiumgYwSHjSobGWxYjv62YhkL9QEdvGP151xypCtMlAfKK79GEcd2eRQ==" + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/bl/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/buffer": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz", + "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==", + "dependencies": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + }, + "node_modules/buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" + }, + "node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, + "node_modules/code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/commist": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/commist/-/commist-1.1.0.tgz", + "integrity": "sha512-rraC8NXWOEjhADbZe9QBNzLAN5Q3fsTPQtBV+fEVj6xKIgDgNiEVE6ZNfHpZOqfQ21YUzfVNUXLOEZquYvQPPg==", + "dependencies": { + "leven": "^2.1.0", + "minimist": "^1.1.0" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "node_modules/concat-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", + "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", + "engines": [ + "node >= 6.0" + ], + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.0.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/concat-stream/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" + }, + "node_modules/core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "node_modules/crc": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/crc/-/crc-3.4.0.tgz", + "integrity": "sha512-ycVC2+4/DLgXXq7QweYi2znhqDuZz6P5TQXnkQo8v15XY/5p/IWeZwsSE31Ifo8w15b8TWLsqhXOjXyilHuQxw==" + }, + "node_modules/date-format": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.11.tgz", + "integrity": "sha512-VS20KRyorrbMCQmpdl2hg5KaOUsda1RbnsJg461FfrcyCUg+pkd0b40BSW4niQyTheww4DBXQnS7HwSrKkipLw==", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" + }, + "node_modules/detect-libc": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz", + "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==", + "engines": { + "node": ">=8" + } + }, + "node_modules/duplexify": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.2.tgz", + "integrity": "sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw==", + "dependencies": { + "end-of-stream": "^1.4.1", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1", + "stream-shift": "^1.0.0" + } + }, + "node_modules/duplexify/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/easy-crc": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/easy-crc/-/easy-crc-0.0.2.tgz", + "integrity": "sha512-h6eqIdhJRe0p271/xZJbM/0klCi13mW5IB7ZEzEGH11yV4QXWAkD4yPErz0fXdhFrd6sZ4Q1k5Iky2kMsMNePw==" + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" + }, + "node_modules/flatted": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", + "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==" + }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, + "node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "node_modules/gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha512-14x4kjc6lkD3ltw589k0NrPD6cCNTD6CWoVUNpB85+DrtONoZn+Rug6xZU5RvSC4+TZPxA5AnBibQYAvZn41Hg==", + "dependencies": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "node_modules/github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==" + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" + }, + "node_modules/has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" + }, + "node_modules/help-me": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/help-me/-/help-me-3.0.0.tgz", + "integrity": "sha512-hx73jClhyk910sidBB7ERlnhMlFsJJIBqSVMFDwPN8o2v9nmp5KgLq1Xz1Bf1fCMMZ6mPrX159iG0VLy/fPMtQ==", + "dependencies": { + "glob": "^7.1.6", + "readable-stream": "^3.6.0" + } + }, + "node_modules/help-me/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, + "node_modules/is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==", + "dependencies": { + "number-is-nan": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "node_modules/js-sdsl": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz", + "integrity": "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/js-sdsl" + } + }, + "node_modules/jsmodbus": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/jsmodbus/-/jsmodbus-4.0.6.tgz", + "integrity": "sha512-gCmjoaERErK5Rn9Lu/BN07fY13MoWV7JKgGzrnkPlQPdPxYcwDhLtYcmpFFpZ4J9NPZZBSezi1UkLZO/DnNppA==", + "dependencies": { + "crc": "3.4.0", + "debug": "^3.1.0" + }, + "bin": { + "jsmodbus": "bin/jsmodbus.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/jsmodbus/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/leven": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", + "integrity": "sha1-wuep93IJTe6dNCAq6KzORoeHVYA=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/log4js": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.5.2.tgz", + "integrity": "sha512-DXtpNtt+KDOMT7RHUDIur/WsSA3rntlUh9Zg4XCdV42wUuMmbFkl38+LZ92Z5QvQA7mD5kAVkLiBSEH/tvUB8A==", + "dependencies": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "flatted": "^3.2.5", + "rfdc": "^1.3.0", + "streamroller": "^3.1.1" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" + }, + "node_modules/mqtt": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/mqtt/-/mqtt-4.3.7.tgz", + "integrity": "sha512-ew3qwG/TJRorTz47eW46vZ5oBw5MEYbQZVaEji44j5lAUSQSqIEoul7Kua/BatBW0H0kKQcC9kwUHa1qzaWHSw==", + "dependencies": { + "commist": "^1.0.0", + "concat-stream": "^2.0.0", + "debug": "^4.1.1", + "duplexify": "^4.1.1", + "help-me": "^3.0.0", + "inherits": "^2.0.3", + "lru-cache": "^6.0.0", + "minimist": "^1.2.5", + "mqtt-packet": "^6.8.0", + "number-allocator": "^1.0.9", + "pump": "^3.0.0", + "readable-stream": "^3.6.0", + "reinterval": "^1.1.0", + "rfdc": "^1.3.0", + "split2": "^3.1.0", + "ws": "^7.5.5", + "xtend": "^4.0.2" + }, + "bin": { + "mqtt": "bin/mqtt.js", + "mqtt_pub": "bin/pub.js", + "mqtt_sub": "bin/sub.js" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/mqtt-packet": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/mqtt-packet/-/mqtt-packet-6.10.0.tgz", + "integrity": "sha512-ja8+mFKIHdB1Tpl6vac+sktqy3gA8t9Mduom1BA75cI+R9AHnZOiaBQwpGiWnaVJLDGRdNhQmFaAqd7tkKSMGA==", + "dependencies": { + "bl": "^4.0.2", + "debug": "^4.1.1", + "process-nextick-args": "^2.0.1" + } + }, + "node_modules/mqtt/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/nan": { + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.16.0.tgz", + "integrity": "sha512-UdAqHyFngu7TfQKsCBgAA6pWDkT8MAO7d0jyOecVhN5354xbLqdn8mV9Tat9gepAupm0bt2DbeaSC8vS52MuFA==" + }, + "node_modules/napi-build-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", + "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==" + }, + "node_modules/node-abi": { + "version": "3.22.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.22.0.tgz", + "integrity": "sha512-u4uAs/4Zzmp/jjsD9cyFYDXeISfUWaAVWshPmDZOFOv4Xl4SbzTXm53I04C2uRueYJ+0t5PEtLH/owbn2Npf/w==", + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/nodemailer": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.7.tgz", + "integrity": "sha512-rUtR77ksqex/eZRLmQ21LKVH5nAAsVicAtAYudK7JgwenEDZ0UIQ1adUGqErz7sMkWYxWTTU1aeP2Jga6WQyJw==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "dependencies": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "node_modules/number-allocator": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/number-allocator/-/number-allocator-1.0.14.tgz", + "integrity": "sha512-OrL44UTVAvkKdOdRQZIJpLkAdjXGTRda052sN4sO77bKEzYYqWKMBjQvrJFzqygI99gL6Z4u2xctPW1tB8ErvA==", + "dependencies": { + "debug": "^4.3.1", + "js-sdsl": "4.3.0" + } + }, + "node_modules/number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/prebuild-install": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.0.tgz", + "integrity": "sha512-CNcMgI1xBypOyGqjp3wOc8AAo1nMhZS3Cwd3iHIxOdAUbb+YxdNuM4Z5iIrZ8RLvOsf3F3bl7b7xGq6DjQoNYA==", + "dependencies": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^1.0.1", + "node-abi": "^3.3.0", + "npmlog": "^4.0.1", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + }, + "bin": { + "prebuild-install": "bin.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/reinterval": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reinterval/-/reinterval-1.1.0.tgz", + "integrity": "sha1-M2Hs+jymwYKDOA3Qu5VG85D17Oc=" + }, + "node_modules/rfdc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==" + }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/serialport": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/serialport/-/serialport-9.2.8.tgz", + "integrity": "sha512-FsWpMQgSJxi93JgWl5xM1f9/Z8IjRJuaUEoHqLf8FPBLw7gMhInuHOBhI2onQufWIYPGTz3H3oGcu1nCaK1EfA==", + "dependencies": { + "@serialport/binding-mock": "9.2.4", + "@serialport/bindings": "9.2.8", + "@serialport/parser-byte-length": "9.2.4", + "@serialport/parser-cctalk": "9.2.4", + "@serialport/parser-delimiter": "9.2.4", + "@serialport/parser-inter-byte-timeout": "9.2.4", + "@serialport/parser-readline": "9.2.4", + "@serialport/parser-ready": "9.2.4", + "@serialport/parser-regex": "9.2.4", + "@serialport/stream": "9.2.4", + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "node_modules/split2": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", + "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", + "dependencies": { + "readable-stream": "^3.0.0" + } + }, + "node_modules/split2/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==" + }, + "node_modules/streamroller": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.1.1.tgz", + "integrity": "sha512-iPhtd9unZ6zKdWgMeYGfSBuqCngyJy1B/GPi/lTpwGpa3bajuX30GjUVd0/Tn/Xhg0mr4DOSENozz9Y06qyonQ==", + "dependencies": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "fs-extra": "^10.1.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dependencies": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/tar-fs": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "dependencies": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tar-stream/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/total.js": { + "version": "3.4.13", + "resolved": "https://registry.npmjs.org/total.js/-/total.js-3.4.13.tgz", + "integrity": "sha512-lAH4gEixlPFbrE3xfKADAcHfO79IFq2wKa9GTsrgRzIR5MTg3mNH7+4IxvX1pK8faoYb/0oYSJ1YTsAa5hIFFQ==", + "bin": { + "total": "bin/totaljs", + "total.js": "bin/totaljs", + "totaljs": "bin/totaljs", + "totalpackage": "bin/tpm", + "tpm": "bin/tpm" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, + "node_modules/universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "node_modules/wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "node_modules/ws": { + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } + }, + "dependencies": { + "@serialport/binding-abstract": { + "version": "9.2.3", + "resolved": "https://registry.npmjs.org/@serialport/binding-abstract/-/binding-abstract-9.2.3.tgz", + "integrity": "sha512-cQs9tbIlG3P0IrOWyVirqlhWuJ7Ms2Zh9m2108z6Y5UW/iVj6wEOiW8EmK9QX9jmJXYllE7wgGgvVozP5oCj3w==", + "requires": { + "debug": "^4.3.2" + } + }, + "@serialport/binding-mock": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/binding-mock/-/binding-mock-9.2.4.tgz", + "integrity": "sha512-dpEhACCs44oQhh6ajJfJdvQdK38Vq0N4W6iD/gdplglDCK7qXRQCMUjJIeKdS/HSEiWkC3bwumUhUufdsOyT4g==", + "requires": { + "@serialport/binding-abstract": "9.2.3", + "debug": "^4.3.2" + } + }, + "@serialport/bindings": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/@serialport/bindings/-/bindings-9.2.8.tgz", + "integrity": "sha512-hSLxTe0tADZ3LMMGwvEJWOC/TaFQTyPeFalUCsJ1lSQ0k6bPF04JwrtB/C81GetmDBTNRY0GlD0SNtKCc7Dr5g==", + "requires": { + "@serialport/binding-abstract": "9.2.3", + "@serialport/parser-readline": "9.2.4", + "bindings": "^1.5.0", + "debug": "^4.3.2", + "nan": "^2.15.0", + "prebuild-install": "^7.0.0" + } + }, + "@serialport/parser-byte-length": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-byte-length/-/parser-byte-length-9.2.4.tgz", + "integrity": "sha512-sQD/iw4ZMU3xW9PLi0/GlvU6Y623jGeWecbMkO7izUo/6P7gtfv1c9ikd5h0kwL8AoAOpQA1lxdHIKox+umBUg==" + }, + "@serialport/parser-cctalk": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-cctalk/-/parser-cctalk-9.2.4.tgz", + "integrity": "sha512-T4TU5vQMwmo9AB3gQLFDWbfJXlW5jd9guEsB/nqKjFHTv0FXPdZ7DQ2TpSp8RnHWxU3GX6kYTaDO20BKzc8GPQ==" + }, + "@serialport/parser-delimiter": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-delimiter/-/parser-delimiter-9.2.4.tgz", + "integrity": "sha512-4nvTAoYAgkxFiXrkI+3CA49Yd43CODjeszh89EK+I9c8wOZ+etZduRCzINYPiy26g7zO+GRAb9FoPCsY+sYcbQ==" + }, + "@serialport/parser-inter-byte-timeout": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-inter-byte-timeout/-/parser-inter-byte-timeout-9.2.4.tgz", + "integrity": "sha512-SOAdvr0oBQIOCXX198hiTlxs4JTKg9j5piapw5tNq52fwDOWdbYrFneT/wN04UTMKaDrJuEvXq6T4rv4j7nJ5A==" + }, + "@serialport/parser-readline": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-readline/-/parser-readline-9.2.4.tgz", + "integrity": "sha512-Z1/qrZTQUVhNSJP1hd9YfDvq0o7d87rNwAjjRKbVpa7Qi51tG5BnKt43IV3NFMyBlVcRe0rnIb3tJu57E0SOwg==", + "requires": { + "@serialport/parser-delimiter": "9.2.4" + } + }, + "@serialport/parser-ready": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-ready/-/parser-ready-9.2.4.tgz", + "integrity": "sha512-Pyi94Itjl6qAURwIZr/gmZpMAyTmKXThm6vL5DoAWGQjcRHWB0gwv2TY2v7N+mQLJYUKU3cMnvnATXxHm7xjxw==" + }, + "@serialport/parser-regex": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-regex/-/parser-regex-9.2.4.tgz", + "integrity": "sha512-sI/cVvPOYz+Dbv4ZdnW16qAwvXiFf/1pGASQdbveRTlgJDdz7sRNlCBifzfTN2xljwvCTZYqiudKvDdC1TepRQ==" + }, + "@serialport/stream": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/stream/-/stream-9.2.4.tgz", + "integrity": "sha512-bLye8Ub4vUFQGmkh8qEqehr7SE7EJs2yDs0h9jzuL5oKi+F34CFmWkEErO8GAOQ8YNn7p6b3GxUgs+0BrHHDZQ==", + "requires": { + "debug": "^4.3.2" + } + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==" + }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "are-we-there-yet": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", + "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "base64-js": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", + "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==" + }, + "bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "requires": { + "file-uri-to-path": "1.0.0" + } + }, + "bitwise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/bitwise/-/bitwise-2.1.0.tgz", + "integrity": "sha512-XKgAhMXCh4H/3oNwAHAsAO0iC89s9cOiumgYwSHjSobGWxYjv62YhkL9QEdvGP151xypCtMlAfKK79GEcd2eRQ==" + }, + "bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "requires": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "buffer": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz", + "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==", + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" + }, + "chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==" + }, + "commist": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/commist/-/commist-1.1.0.tgz", + "integrity": "sha512-rraC8NXWOEjhADbZe9QBNzLAN5Q3fsTPQtBV+fEVj6xKIgDgNiEVE6ZNfHpZOqfQ21YUzfVNUXLOEZquYvQPPg==", + "requires": { + "leven": "^2.1.0", + "minimist": "^1.1.0" + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "concat-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", + "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.0.2", + "typedarray": "^0.0.6" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "crc": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/crc/-/crc-3.4.0.tgz", + "integrity": "sha512-ycVC2+4/DLgXXq7QweYi2znhqDuZz6P5TQXnkQo8v15XY/5p/IWeZwsSE31Ifo8w15b8TWLsqhXOjXyilHuQxw==" + }, + "date-format": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.11.tgz", + "integrity": "sha512-VS20KRyorrbMCQmpdl2hg5KaOUsda1RbnsJg461FfrcyCUg+pkd0b40BSW4niQyTheww4DBXQnS7HwSrKkipLw==" + }, + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "requires": { + "ms": "2.1.2" + } + }, + "decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "requires": { + "mimic-response": "^3.1.0" + } + }, + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==" + }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" + }, + "detect-libc": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz", + "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==" + }, + "duplexify": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.2.tgz", + "integrity": "sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw==", + "requires": { + "end-of-stream": "^1.4.1", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1", + "stream-shift": "^1.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "easy-crc": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/easy-crc/-/easy-crc-0.0.2.tgz", + "integrity": "sha512-h6eqIdhJRe0p271/xZJbM/0klCi13mW5IB7ZEzEGH11yV4QXWAkD4yPErz0fXdhFrd6sZ4Q1k5Iky2kMsMNePw==" + }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "requires": { + "once": "^1.4.0" + } + }, + "expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==" + }, + "file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" + }, + "flatted": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", + "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==" + }, + "fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, + "fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha512-14x4kjc6lkD3ltw589k0NrPD6cCNTD6CWoVUNpB85+DrtONoZn+Rug6xZU5RvSC4+TZPxA5AnBibQYAvZn41Hg==", + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==" + }, + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" + }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" + }, + "help-me": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/help-me/-/help-me-3.0.0.tgz", + "integrity": "sha512-hx73jClhyk910sidBB7ERlnhMlFsJJIBqSVMFDwPN8o2v9nmp5KgLq1Xz1Bf1fCMMZ6mPrX159iG0VLy/fPMtQ==", + "requires": { + "glob": "^7.1.6", + "readable-stream": "^3.6.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==", + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "js-sdsl": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz", + "integrity": "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==" + }, + "jsmodbus": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/jsmodbus/-/jsmodbus-4.0.6.tgz", + "integrity": "sha512-gCmjoaERErK5Rn9Lu/BN07fY13MoWV7JKgGzrnkPlQPdPxYcwDhLtYcmpFFpZ4J9NPZZBSezi1UkLZO/DnNppA==", + "requires": { + "crc": "3.4.0", + "debug": "^3.1.0" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "requires": { + "ms": "^2.1.1" + } + } + } + }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, + "leven": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", + "integrity": "sha1-wuep93IJTe6dNCAq6KzORoeHVYA=" + }, + "log4js": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.5.2.tgz", + "integrity": "sha512-DXtpNtt+KDOMT7RHUDIur/WsSA3rntlUh9Zg4XCdV42wUuMmbFkl38+LZ92Z5QvQA7mD5kAVkLiBSEH/tvUB8A==", + "requires": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "flatted": "^3.2.5", + "rfdc": "^1.3.0", + "streamroller": "^3.1.1" + } + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "requires": { + "yallist": "^4.0.0" + } + }, + "mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==" + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==" + }, + "mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" + }, + "mqtt": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/mqtt/-/mqtt-4.3.7.tgz", + "integrity": "sha512-ew3qwG/TJRorTz47eW46vZ5oBw5MEYbQZVaEji44j5lAUSQSqIEoul7Kua/BatBW0H0kKQcC9kwUHa1qzaWHSw==", + "requires": { + "commist": "^1.0.0", + "concat-stream": "^2.0.0", + "debug": "^4.1.1", + "duplexify": "^4.1.1", + "help-me": "^3.0.0", + "inherits": "^2.0.3", + "lru-cache": "^6.0.0", + "minimist": "^1.2.5", + "mqtt-packet": "^6.8.0", + "number-allocator": "^1.0.9", + "pump": "^3.0.0", + "readable-stream": "^3.6.0", + "reinterval": "^1.1.0", + "rfdc": "^1.3.0", + "split2": "^3.1.0", + "ws": "^7.5.5", + "xtend": "^4.0.2" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "mqtt-packet": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/mqtt-packet/-/mqtt-packet-6.10.0.tgz", + "integrity": "sha512-ja8+mFKIHdB1Tpl6vac+sktqy3gA8t9Mduom1BA75cI+R9AHnZOiaBQwpGiWnaVJLDGRdNhQmFaAqd7tkKSMGA==", + "requires": { + "bl": "^4.0.2", + "debug": "^4.1.1", + "process-nextick-args": "^2.0.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "nan": { + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.16.0.tgz", + "integrity": "sha512-UdAqHyFngu7TfQKsCBgAA6pWDkT8MAO7d0jyOecVhN5354xbLqdn8mV9Tat9gepAupm0bt2DbeaSC8vS52MuFA==" + }, + "napi-build-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", + "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==" + }, + "node-abi": { + "version": "3.22.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.22.0.tgz", + "integrity": "sha512-u4uAs/4Zzmp/jjsD9cyFYDXeISfUWaAVWshPmDZOFOv4Xl4SbzTXm53I04C2uRueYJ+0t5PEtLH/owbn2Npf/w==", + "requires": { + "semver": "^7.3.5" + } + }, + "nodemailer": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.7.tgz", + "integrity": "sha512-rUtR77ksqex/eZRLmQ21LKVH5nAAsVicAtAYudK7JgwenEDZ0UIQ1adUGqErz7sMkWYxWTTU1aeP2Jga6WQyJw==" + }, + "npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "number-allocator": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/number-allocator/-/number-allocator-1.0.14.tgz", + "integrity": "sha512-OrL44UTVAvkKdOdRQZIJpLkAdjXGTRda052sN4sO77bKEzYYqWKMBjQvrJFzqygI99gL6Z4u2xctPW1tB8ErvA==", + "requires": { + "debug": "^4.3.1", + "js-sdsl": "4.3.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==" + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==" + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==" + }, + "prebuild-install": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.0.tgz", + "integrity": "sha512-CNcMgI1xBypOyGqjp3wOc8AAo1nMhZS3Cwd3iHIxOdAUbb+YxdNuM4Z5iIrZ8RLvOsf3F3bl7b7xGq6DjQoNYA==", + "requires": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^1.0.1", + "node-abi": "^3.3.0", + "npmlog": "^4.0.1", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + } + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + } + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "reinterval": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reinterval/-/reinterval-1.1.0.tgz", + "integrity": "sha1-M2Hs+jymwYKDOA3Qu5VG85D17Oc=" + }, + "rfdc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==" + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "requires": { + "lru-cache": "^6.0.0" + } + }, + "serialport": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/serialport/-/serialport-9.2.8.tgz", + "integrity": "sha512-FsWpMQgSJxi93JgWl5xM1f9/Z8IjRJuaUEoHqLf8FPBLw7gMhInuHOBhI2onQufWIYPGTz3H3oGcu1nCaK1EfA==", + "requires": { + "@serialport/binding-mock": "9.2.4", + "@serialport/bindings": "9.2.8", + "@serialport/parser-byte-length": "9.2.4", + "@serialport/parser-cctalk": "9.2.4", + "@serialport/parser-delimiter": "9.2.4", + "@serialport/parser-inter-byte-timeout": "9.2.4", + "@serialport/parser-readline": "9.2.4", + "@serialport/parser-ready": "9.2.4", + "@serialport/parser-regex": "9.2.4", + "@serialport/stream": "9.2.4", + "debug": "^4.3.2" + } + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==" + }, + "simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "requires": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "split2": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", + "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", + "requires": { + "readable-stream": "^3.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==" + }, + "streamroller": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.1.1.tgz", + "integrity": "sha512-iPhtd9unZ6zKdWgMeYGfSBuqCngyJy1B/GPi/lTpwGpa3bajuX30GjUVd0/Tn/Xhg0mr4DOSENozz9Y06qyonQ==", + "requires": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "fs-extra": "^10.1.0" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" + }, + "tar-fs": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "requires": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "requires": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "total.js": { + "version": "3.4.13", + "resolved": "https://registry.npmjs.org/total.js/-/total.js-3.4.13.tgz", + "integrity": "sha512-lAH4gEixlPFbrE3xfKADAcHfO79IFq2wKa9GTsrgRzIR5MTg3mNH7+4IxvX1pK8faoYb/0oYSJ1YTsAa5hIFFQ==" + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, + "universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==" + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "requires": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "ws": { + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "requires": {} + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } + } +} diff --git a/RVO15/package.json b/RVO15/package.json new file mode 100755 index 0000000..e524d7c --- /dev/null +++ b/RVO15/package.json @@ -0,0 +1,29 @@ +{ + "name": "emptyproject", + "description": "Total.js empty project.", + "version": "1.0.0", + "main": "debug.js", + "dependencies": { + "bitwise": "^2.1.0", + "easy-crc": "0.0.2", + "jsmodbus": "^4.0.6", + "log4js": "^6.3.0", + "mqtt": "^4.2.6", + "nodemailer": "^6.9.7", + "serialport": "^9.2.8", + "total.js": "^3.4.13" + }, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "https://github.com/totaljs/emptyproject-flow" + }, + "keywords": [ + "empty", + "project" + ], + "author": "Peter Širka", + "license": "MIT" +} diff --git a/RVO15/release.js b/RVO15/release.js new file mode 100755 index 0000000..02d52ff --- /dev/null +++ b/RVO15/release.js @@ -0,0 +1,15 @@ +// =================================================== +// FOR PRODUCTION +// Total.js - framework for Node.js platform +// https://www.totaljs.com +// =================================================== + +const options = {'ip':'0.0.0.0', 'port':12345}; + +// options.ip = '127.0.0.1'; +// options.port = parseInt(process.argv[2]); +// options.config = { name: 'Total.js' }; +// options.sleep = 3000; + +require('total.js').http('release', options); +// require('total.js').cluster.http(5, 'release', options); diff --git a/RVO15/release.js.json b/RVO15/release.js.json new file mode 100755 index 0000000..dbbae46 --- /dev/null +++ b/RVO15/release.js.json @@ -0,0 +1,34 @@ +{ + "pid": 395, + "stats": [ + { + "id": null, + "version": { + "node": "v14.18.1", + "total": "3.4.13", + "app": "1.0.0" + }, + "pid": 395, + "thread": "", + "mode": "release", + "overload": 0, + "date": "2025-10-16T00:23:16.398Z", + "memory": 29.43, + "rm": 0, + "fm": 0, + "wm": 0, + "mm": 0, + "om": 12, + "em": 0, + "dbrm": 0, + "dbwm": 0, + "usage": 0, + "requests": 7, + "pending": 0, + "errors": 0, + "timeouts": 0, + "uptime": 886, + "online": 0 + } + ] +} \ No newline at end of file diff --git a/RVO15/report_data.log b/RVO15/report_data.log new file mode 100755 index 0000000..7ab8289 --- /dev/null +++ b/RVO15/report_data.log @@ -0,0 +1,222 @@ +{ + "name": "rvo_senica_15_ip114", + "time": "2025-10-15T10:38:31.217Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [ + "15/61_3L_2697_NEMA" + ], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_15_ip114", + "time": "2025-10-15T12:07:07.647Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [ + "15/61_3L_2697_NEMA" + ], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_15_ip114", + "time": "2025-10-15T13:07:07.647Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [ + "15/61_3L_2697_NEMA" + ], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_15_ip114", + "time": "2025-10-15T14:07:07.649Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [ + "15/61_3L_2697_NEMA" + ], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_15_ip114", + "time": "2025-10-15T15:07:07.649Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [ + "15/61_3L_2697_NEMA" + ], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_15_ip114", + "time": "2025-10-15T16:07:07.649Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [ + "15/61_3L_2697_NEMA" + ], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_15_ip114", + "time": "2025-10-15T17:41:57.692Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [ + "15/61_3L_2697_NEMA" + ], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_15_ip114", + "time": "2025-10-15T18:41:57.692Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [ + "15/61_3L_2697_NEMA" + ], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_15_ip114", + "time": "2025-10-15T19:41:57.689Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [ + "15/61_3L_2697_NEMA" + ], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_15_ip114", + "time": "2025-10-15T20:41:57.694Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [ + "15/61_3L_2697_NEMA" + ], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_15_ip114", + "time": "2025-10-15T21:41:57.690Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [ + "15/61_3L_2697_NEMA" + ], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_15_ip114", + "time": "2025-10-15T22:41:57.690Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [ + "15/61_3L_2697_NEMA" + ], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_15_ip114", + "time": "2025-10-15T23:41:57.689Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [ + "15/61_3L_2697_NEMA" + ], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +} \ No newline at end of file From 7c6669ddba11c527e83b3f7f7b6472c69075678f Mon Sep 17 00:00:00 2001 From: Jakub Klena Date: Thu, 16 Oct 2025 02:24:24 +0200 Subject: [PATCH 09/30] Backup senica-RVO16 on 16.10.2025 --- RVO16/addSwitch.py | 36 + RVO16/cloud_topic.py | 76 + RVO16/config | 12 + RVO16/createNode.py | 43 + RVO16/databases/accelerometer_db.js | 3055 +++++++ RVO16/databases/modbus_config.js | 114 + RVO16/databases/nodes.table | 128 + .../nodes_original/nodes_original.table | 1 + RVO16/databases/notifications.table | 41 + RVO16/databases/pins.table | 14 + RVO16/databases/relays.table | 5 + RVO16/databases/settings.table | 2 + RVO16/databases/tbdata.nosql | 0 RVO16/databases/tbdatacloud.nosql | 0 RVO16/databases/total_energy.js | 38 + RVO16/debug.js | 16 + RVO16/err.txt | 33 + RVO16/flow/cloudmqttconnect.js | 357 + RVO16/flow/cmd_manager.js | 3071 +++++++ RVO16/flow/cmd_manager_orig.txt | 2800 ++++++ RVO16/flow/code.js | 90 + RVO16/flow/comment.js | 11 + RVO16/flow/count.js | 60 + RVO16/flow/db_connector.js | 286 + RVO16/flow/db_init.js | 113 + RVO16/flow/debug.js | 100 + RVO16/flow/designer.json | 3102 +++++++ RVO16/flow/dido_controller.js | 1486 +++ RVO16/flow/dido_controller_orig.txt | 1473 +++ RVO16/flow/helper/DataToTbHandler.js | 187 + RVO16/flow/helper/ErrorToServiceHandler.js | 91 + RVO16/flow/helper/db_helper.js | 44 + RVO16/flow/helper/logger.js | 30 + RVO16/flow/helper/md5.js | 5 + RVO16/flow/helper/notification_reporter.js | 121 + RVO16/flow/helper/register.js | 144 + RVO16/flow/helper/serialport_helper.js | 99 + RVO16/flow/helper/suncalc.js | 317 + RVO16/flow/helper/utils.js | 161 + RVO16/flow/httprequest.js | 137 + RVO16/flow/httpresponse.js | 76 + RVO16/flow/httproute.js | 326 + RVO16/flow/infosender.js | 81 + RVO16/flow/modbus_reader.js | 346 + RVO16/flow/monitorconsumption.js | 156 + RVO16/flow/monitordisk.js | 96 + RVO16/flow/monitormemory.js | 87 + RVO16/flow/nodesdb_changecheck.js | 77 + RVO16/flow/show_dbdata.js | 243 + RVO16/flow/slack_filter.js | 188 + RVO16/flow/thermometer.js | 99 + RVO16/flow/trigger.js | 79 + RVO16/flow/variables.txt | 0 RVO16/flow/virtualwirein.js | 43 + RVO16/flow/virtualwireout.js | 41 + RVO16/flow/wsmqttpublish.js | 448 + RVO16/monitor.txt | 7953 +++++++++++++++++ RVO16/package-lock.json | 2139 +++++ RVO16/package.json | 30 + RVO16/release.js | 15 + RVO16/release.js.json | 34 + RVO16/report_data.log | 2191 +++++ 62 files changed, 32647 insertions(+) create mode 100755 RVO16/addSwitch.py create mode 100755 RVO16/cloud_topic.py create mode 100755 RVO16/config create mode 100755 RVO16/createNode.py create mode 100755 RVO16/databases/accelerometer_db.js create mode 100755 RVO16/databases/modbus_config.js create mode 100755 RVO16/databases/nodes.table create mode 100755 RVO16/databases/nodes_original/nodes_original.table create mode 100755 RVO16/databases/notifications.table create mode 100755 RVO16/databases/pins.table create mode 100755 RVO16/databases/relays.table create mode 100755 RVO16/databases/settings.table create mode 100755 RVO16/databases/tbdata.nosql create mode 100755 RVO16/databases/tbdatacloud.nosql create mode 100755 RVO16/databases/total_energy.js create mode 100755 RVO16/debug.js create mode 100755 RVO16/err.txt create mode 100755 RVO16/flow/cloudmqttconnect.js create mode 100755 RVO16/flow/cmd_manager.js create mode 100755 RVO16/flow/cmd_manager_orig.txt create mode 100755 RVO16/flow/code.js create mode 100755 RVO16/flow/comment.js create mode 100755 RVO16/flow/count.js create mode 100755 RVO16/flow/db_connector.js create mode 100755 RVO16/flow/db_init.js create mode 100755 RVO16/flow/debug.js create mode 100755 RVO16/flow/designer.json create mode 100755 RVO16/flow/dido_controller.js create mode 100755 RVO16/flow/dido_controller_orig.txt create mode 100755 RVO16/flow/helper/DataToTbHandler.js create mode 100755 RVO16/flow/helper/ErrorToServiceHandler.js create mode 100755 RVO16/flow/helper/db_helper.js create mode 100755 RVO16/flow/helper/logger.js create mode 100755 RVO16/flow/helper/md5.js create mode 100755 RVO16/flow/helper/notification_reporter.js create mode 100755 RVO16/flow/helper/register.js create mode 100755 RVO16/flow/helper/serialport_helper.js create mode 100755 RVO16/flow/helper/suncalc.js create mode 100755 RVO16/flow/helper/utils.js create mode 100755 RVO16/flow/httprequest.js create mode 100755 RVO16/flow/httpresponse.js create mode 100755 RVO16/flow/httproute.js create mode 100755 RVO16/flow/infosender.js create mode 100755 RVO16/flow/modbus_reader.js create mode 100755 RVO16/flow/monitorconsumption.js create mode 100755 RVO16/flow/monitordisk.js create mode 100755 RVO16/flow/monitormemory.js create mode 100755 RVO16/flow/nodesdb_changecheck.js create mode 100755 RVO16/flow/show_dbdata.js create mode 100755 RVO16/flow/slack_filter.js create mode 100755 RVO16/flow/thermometer.js create mode 100755 RVO16/flow/trigger.js create mode 100755 RVO16/flow/variables.txt create mode 100755 RVO16/flow/virtualwirein.js create mode 100755 RVO16/flow/virtualwireout.js create mode 100755 RVO16/flow/wsmqttpublish.js create mode 100755 RVO16/monitor.txt create mode 100755 RVO16/package-lock.json create mode 100755 RVO16/package.json create mode 100755 RVO16/release.js create mode 100755 RVO16/release.js.json create mode 100755 RVO16/report_data.log diff --git a/RVO16/addSwitch.py b/RVO16/addSwitch.py new file mode 100755 index 0000000..c35e96b --- /dev/null +++ b/RVO16/addSwitch.py @@ -0,0 +1,36 @@ +import os + +def process_set_file(): + """ + Checks if /root/flowserver exists, reads set.txt, and modifies the second line. + """ + default_folder = "/root/flowserver" if os.path.exists("/root/flowserver") else "/home/unipi/flowserver" + flag = 1 if default_folder == "/root/flowserver" else 0 + + try: + with open("/home/unipi/flowserver/databases/settings.table", "r") as f: + lines = f.readlines() + + if len(lines) >= 2: + lines[0] = lines[0].rstrip('\n') + "|main_switch:boolean\n" + second_line = lines[1].strip() # remove trailing newline + last_pipe_index = second_line.rfind("|") + + if last_pipe_index != -1: + modified_line = second_line[:last_pipe_index + 1] + str(flag) + "|" + second_line[last_pipe_index + 1:] + lines[1] = modified_line + else: + print("Warning: No '|' character found in the second line of set.txt") + + with open("/home/unipi/flowserver/databases/settings.table", "w") as f: + f.writelines(lines) + else: + print("Warning: settings.table has less than two lines.") + + except FileNotFoundError: + print("Error: settings.table not found.") + except Exception as e: + print(e) + +# if __name__ == "__main__": +process_set_file() diff --git a/RVO16/cloud_topic.py b/RVO16/cloud_topic.py new file mode 100755 index 0000000..77c31f1 --- /dev/null +++ b/RVO16/cloud_topic.py @@ -0,0 +1,76 @@ +# import os +# +# def modify_file(file_path): +# """ +# Modifies the given file by: +# 1. Appending "|cloud_topic" to the first line. +# 2. Inserting the text from the third "." to the first "|" on the second line after the last "|" character. +# +# Args: +# file_path (str): The path to the file to be modified. +# """ +# +# with open(file_path, 'r+') as f: +# lines = f.readlines() +# +# # Modify the first line +# lines[0] += "|cloud_topic:string" +# +# # Modify the second line +# second_line = lines[1].strip() # Remove leading/trailing whitespace +# first_pipe_index = second_line.find('|') +# third_dot_index = second_line.find('.', second_line.find('.', second_line.find('.') + 1) + 1) +# text_to_insert = second_line[third_dot_index:first_pipe_index] +# +# last_pipe_index = second_line.rfind('|') +# lines[1] = second_line[:last_pipe_index + 1] + text_to_insert + "|" + second_line[last_pipe_index + 1:] +# +# print(first_pipe_index, third_dot_index, text_to_insert, last_pipe_index) +# # Write the modified lines back to the file +# # f.seek(0) +# # f.writelines(lines) +# # f.truncate() +# +# # Example usage: +# file_path = "settings.table" # Replace with the actual file path +# modify_file(file_path) +# + + +def modify_file(file_path): + """ + Modifies the given file by: + 1. Appending "|cloud_topic" to the first line. + 2. Inserting the text between the third "." and the second "|" on the second line after the last "|" character. + + Args: + file_path (str): The path to the file to be modified. + """ + + with open(file_path, 'r+') as f: + lines = f.readlines() + + first_line = lines[0].strip() + first_line += "|cloud_topic:string\n" + # Modify the first line + lines[0] = first_line + + # Modify the second line + second_line = lines[1].strip() # Remove leading/trailing whitespace + first_pipe_index = second_line.find('|') + second_pipe_index = second_line.find('|', first_pipe_index + 1) + third_dot_index = second_line.find('.', second_line.find('.', second_line.find('.') + 1) + 1) + text_to_insert = "u" + second_line[third_dot_index+1:second_pipe_index] + + last_pipe_index = second_line.rfind('|') + lines[1] = second_line[:last_pipe_index + 1] + text_to_insert + "|" + second_line[last_pipe_index + 1:] + + print(first_pipe_index, third_dot_index, text_to_insert, last_pipe_index) + # Write the modified lines back to the file + f.seek(0) + f.writelines(lines) + f.truncate() + +# Example usage: +file_path = "/home/unipi/flowserver/databases/settings.table" # Replace with the actual file path +modify_file(file_path) diff --git a/RVO16/config b/RVO16/config new file mode 100755 index 0000000..cd0a8a9 --- /dev/null +++ b/RVO16/config @@ -0,0 +1,12 @@ +name : Total.js Flow +default_timezone : Europe/Bratislava + +// Packages settings +package#flow (Object) : { url: '/' } + + +table.relays : line:number|tbname:string|contactor:number|profile:string +table.nodes : node:number|pole_number:string|node_type:string|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|project_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|cloud_topic:string|has_main_switch:boolean|daily_report:boolean|send_changed_node_numbers:boolean +table.pins : pin:string|type:string|line:number +table.notifications : key:string|weight:string|sk:string|en:string diff --git a/RVO16/createNode.py b/RVO16/createNode.py new file mode 100755 index 0000000..21406cc --- /dev/null +++ b/RVO16/createNode.py @@ -0,0 +1,43 @@ +print("zaciname") +import re, json + +search_str = '|' +final = [] +counter = 1 +with open("/home/unipi/flowserver/databases/nodes.table", 'r') as file: +# with open("/home/rasta5man/dev/oms/flowserver/databases/nodes.table", 'r') as file: + # Read each line in the file + for line in file: + # Print each line + line = line.strip() + print(line) + if counter != 1: + i = [m.start() for m in re.finditer(re.escape(search_str), line)] + node = line[ i[0] + 1 : i[1] ] + tbname = line[ i[1] + 1 : i[2] ] + final.append({node:tbname}) + counter += 1 +print(json.dumps(final)) +f = open("/home/unipi/flowserver/databases/nodes_original/nodes_original.table", "w") +f.write(json.dumps(final)) +f.close() + + +# +# # ``d`` has to be replaced with a different character +# old_character = "'" +# +# # ``t`` will replace ``d` +# new_character = '"' +# resultant_string = 0; +# with open("/home/unipi/flowserver/databases/nodes_original/nodes_original.table", 'r') as file: +# for line in file: +# resultant_string = re.sub("'", '"', line) +# +# resultant_string = re.sub(" ", "", resultant_string) +# print(resultant_string) +# +# f = open("/home/unipi/flowserver/databases/nodes_original/nodes_original.table", "w") +# f.write(str(resultant_string)) +# f.close() +# diff --git a/RVO16/databases/accelerometer_db.js b/RVO16/databases/accelerometer_db.js new file mode 100755 index 0000000..fdfc7fd --- /dev/null +++ b/RVO16/databases/accelerometer_db.js @@ -0,0 +1,3055 @@ +let naklony = { + "3993": { "label": "1/3A", "naklon": 0 }, + "3989": { "label": "1/3B", "naklon": 15 }, + "3976": { "label": "1/1", "naklon": 0 }, + "4181": { "label": "1/2", "naklon": 0 }, + "4376": { "label": "1/4", "naklon": 15 }, + "3868": { "label": "1/5", "naklon": 15 }, + "3728": { "label": "1/6", "naklon": 15 }, + "3730": { "label": "1/7", "naklon": 0 }, + "4374": { "label": "1/8", "naklon": 0 }, + "3718": { "label": "1/9", "naklon": 15 }, + "4375": { "label": "1/10", "naklon": 15 }, + "4172": { "label": "1/11", "naklon": 15 }, + "4176": { "label": "1/12", "naklon": 15 }, + "3800": { "label": "2/1", "naklon": 5 }, + "3823": { "label": "2/2", "naklon": 5 }, + "3905": { "label": "2/3", "naklon": 5 }, + "3803": { "label": "2/4", "naklon": 5 }, + "3817": { "label": "2/5", "naklon": 5 }, + "3818": { "label": "2/6", "naklon": 5 }, + "3811": { "label": "2/7", "naklon": 5 }, + "3915": { "label": "2/8", "naklon": 5 }, + "3843": { "label": "2/9", "naklon": 10 }, + "3827": { "label": "2/10", "naklon": 10 }, + "4220": { "label": "2/11", "naklon": 10 }, + "3826": { "label": "2/12", "naklon": 10 }, + "3834": { "label": "2/13", "naklon": 10 }, + "3838": { "label": "2/14", "naklon": 10 }, + "2823": { "label": "2/15", "naklon": 10 }, + "3750": { "label": "2/16", "naklon": 10 }, + "3378": { "label": "2/17", "naklon": 0 }, + "3376": { "label": "2/18", "naklon": 0 }, + "3379": { "label": "2/19", "naklon": 0 }, + "3285": { "label": "2/20", "naklon": 0 }, + "3382": { "label": "2/21", "naklon": 0 }, + "3383": { "label": "2/22", "naklon": 0 }, + "3375": { "label": "2/24", "naklon": 0 }, + "3381": { "label": "2/25", "naklon": 0 }, + "3380": { "label": "2/26", "naklon": 0 }, + "3828": { "label": "2/27", "naklon": 10 }, + "3377": { "label": "2/28", "naklon": 0 }, + "3591": { "label": "7/1", "naklon": 0 }, + "3587": { "label": "7/2", "naklon": 0 }, + "3468": { "label": "7/3", "naklon": 0 }, + "3466": { "label": "7/4", "naklon": 0 }, + "3474": { "label": "7/5", "naklon": 0 }, + "3481": { "label": "7/6", "naklon": 0 }, + "3589": { "label": "7/7", "naklon": 0 }, + "3472": { "label": "7/8", "naklon": 0 }, + "3473": { "label": "7/9", "naklon": 0 }, + "3584": { "label": "7/10", "naklon": 0 }, + "3571": { "label": "7/11", "naklon": 0 }, + "3476": { "label": "7/12", "naklon": 0 }, + "3590": { "label": "7/13", "naklon": 0 }, + "3478": { "label": "7/14", "naklon": 0 }, + "3471": { "label": "7/15", "naklon": 0 }, + "3467": { "label": "7/16", "naklon": 0 }, + "3479": { "label": "7/17", "naklon": 0 }, + "3480": { "label": "7/18", "naklon": 0 }, + "3477": { "label": "7/19", "naklon": 0 }, + "3362": { "label": "12/1", "naklon": 0 }, + "3355": { "label": "12/2", "naklon": 0 }, + "3356": { "label": "12/3", "naklon": 0 }, + "3349": { "label": "12/4", "naklon": 0 }, + "3357": { "label": "12/5", "naklon": 0 }, + "3350": { "label": "12/6", "naklon": 0 }, + "3353": { "label": "12/7", "naklon": 0 }, + "3539": { "label": "12/8", "naklon": 0 }, + "3050": { "label": "12/9", "naklon": 0 }, + "3361": { "label": "12/10", "naklon": 0 }, + "3360": { "label": "12/11", "naklon": 0 }, + "3358": { "label": "12/12", "naklon": 0 }, + "3541": { "label": "12/13", "naklon": 0 }, + "3551": { "label": "12/14", "naklon": 0 }, + "3514": { "label": "12/15", "naklon": 0 }, + "3547": { "label": "12/16", "naklon": 0 }, + "3562": { "label": "12/17", "naklon": 0 }, + "3525": { "label": "12/18", "naklon": 0 }, + "3558": { "label": "12/19", "naklon": 0 }, + "3511": { "label": "12/20", "naklon": 0 }, + "3058": { "label": "12/21", "naklon": 0 }, + "3062": { "label": "12/22", "naklon": 0 }, + "3070": { "label": "12/23", "naklon": 0 }, + "3447": { "label": "12/24", "naklon": 0 }, + "3056": { "label": "12/25", "naklon": 0 }, + "3057": { "label": "12/26", "naklon": 0 }, + "3071": { "label": "12/27", "naklon": 0 }, + "3061": { "label": "12/28", "naklon": 0 }, + "3069": { "label": "12/29", "naklon": 0 }, + "3077": { "label": "12/30", "naklon": 0 }, + "3080": { "label": "12/31", "naklon": 0 }, + "3081": { "label": "12/32", "naklon": 0 }, + "3078": { "label": "12/33", "naklon": 0 }, + "4037": { "label": "12/34", "naklon": 0 }, + "3067": { "label": "12/35", "naklon": 0 }, + "3051": { "label": "12/36", "naklon": 0 }, + "2924": { "label": "12/37", "naklon": 0 }, + "3060": { "label": "12/38", "naklon": 0 }, + "3073": { "label": "12/39", "naklon": 0 }, + "3469": { "label": "12/40", "naklon": 0 }, + "2923": { "label": "12/41", "naklon": 0 }, + "2925": { "label": "12/42", "naklon": 0 }, + "3359": { "label": "12/43", "naklon": 0 }, + "3055": { "label": "12/44", "naklon": 0 }, + "2922": { "label": "12/45", "naklon": 0 }, + "3084": { "label": "12/46", "naklon": 0 }, + "3064": { "label": "12/47", "naklon": 0 }, + "3066": { "label": "12/48", "naklon": 0 }, + "3072": { "label": "12/49", "naklon": 0 }, + "3415": { "label": "13/13A", "naklon": 0 }, + "3409": { "label": "13/13B", "naklon": 0 }, + "3399": { "label": "13/13C", "naklon": 0 }, + "3410": { "label": "13/29A", "naklon": 0 }, + "3407": { "label": "13/29B", "naklon": 0 }, + "3405": { "label": "13/34A", "naklon": 0 }, + "3404": { "label": "13/34B", "naklon": 0 }, + "3392": { "label": "13/45A", "naklon": 0 }, + "3386": { "label": "13/45B", "naklon": 0 }, + "3303": { "label": "13/60A", "naklon": 3 }, + "3302": { "label": "13/60B", "naklon": 3 }, + "3319": { "label": "13/70A", "naklon": 6 }, + "3317": { "label": "13/70B", "naklon": 6 }, + "3326": { "label": "13/70C", "naklon": 6 }, + "3351": { "label": "13/73A", "naklon": 6 }, + "3313": { "label": "13/73B", "naklon": 6 }, + "3316": { "label": "13/83A", "naklon": 0 }, + "3320": { "label": "13/83B", "naklon": 0 }, + "3336": { "label": "13/95A", "naklon": 0 }, + "3323": { "label": "13/95B", "naklon": 0 }, + "3339": { "label": "13/98A", "naklon": 0 }, + "3333": { "label": "13/98B", "naklon": 0 }, + "3425": { "label": "13/1", "naklon": 0 }, + "3419": { "label": "13/2", "naklon": 0 }, + "3416": { "label": "13/3", "naklon": 0 }, + "3332": { "label": "13/4", "naklon": 0 }, + "3422": { "label": "13/5", "naklon": 0 }, + "3417": { "label": "13/6", "naklon": 0 }, + "3418": { "label": "13/7", "naklon": 0 }, + "3424": { "label": "13/8", "naklon": 0 }, + "3334": { "label": "13/9", "naklon": 0 }, + "4363": { "label": "13/10", "naklon": 0 }, + "3423": { "label": "13/11", "naklon": 0 }, + "3406": { "label": "13/12", "naklon": 0 }, + "3411": { "label": "13/14", "naklon": 0 }, + "3412": { "label": "13/15", "naklon": 0 }, + "3413": { "label": "13/16", "naklon": 0 }, + "3414": { "label": "13/17", "naklon": 0 }, + "3391": { "label": "13/18", "naklon": 0 }, + "3370": { "label": "13/19", "naklon": 0 }, + "3369": { "label": "13/20", "naklon": 0 }, + "3408": { "label": "13/21", "naklon": 0 }, + "3393": { "label": "13/22", "naklon": 0 }, + "3128": { "label": "13/23", "naklon": 0 }, + "3197": { "label": "13/24", "naklon": 0 }, + "4364": { "label": "13/25", "naklon": 0 }, + "3155": { "label": "13/26", "naklon": 0 }, + "3196": { "label": "13/27", "naklon": 0 }, + "3144": { "label": "13/28", "naklon": 0 }, + "3150": { "label": "13/30", "naklon": 0 }, + "3390": { "label": "13/31", "naklon": 0 }, + "3401": { "label": "13/32", "naklon": 0 }, + "3275": { "label": "13/33", "naklon": 0 }, + "3371": { "label": "13/35", "naklon": 0 }, + "3389": { "label": "13/36", "naklon": 0 }, + "3388": { "label": "13/37", "naklon": 0 }, + "3365": { "label": "13/38", "naklon": 0 }, + "3363": { "label": "13/39", "naklon": 0 }, + "3397": { "label": "13/40", "naklon": 0 }, + "3567": { "label": "13/40/1", "naklon": 0 }, + "3387": { "label": "13/41", "naklon": 0 }, + "3403": { "label": "13/42", "naklon": 0 }, + "3147": { "label": "13/43", "naklon": 0 }, + "3141": { "label": "13/44", "naklon": 0 }, + "3364": { "label": "13/46", "naklon": 0 }, + "3367": { "label": "13/47", "naklon": 0 }, + "3368": { "label": "13/48", "naklon": 0 }, + "3402": { "label": "13/49", "naklon": 0 }, + "3366": { "label": "13/50", "naklon": 0 }, + "3395": { "label": "13/51", "naklon": 0 }, + "3372": { "label": "13/52", "naklon": 0 }, + "3394": { "label": "13/53", "naklon": 0 }, + "3308": { "label": "13/54", "naklon": 0 }, + "3847": { "label": "13/54/1", "naklon": 0 }, + "3312": { "label": "13/55", "naklon": 3 }, + "3309": { "label": "13/56", "naklon": 3 }, + "3311": { "label": "13/57", "naklon": 3 }, + "3310": { "label": "13/58", "naklon": 3 }, + "4365": { "label": "13/59", "naklon": 3 }, + "4093": { "label": "13/60/1", "naklon": 3 }, + "3304": { "label": "13/61", "naklon": 3 }, + "3307": { "label": "13/62", "naklon": 3 }, + "3271": { "label": "13/63", "naklon": 3 }, + "3301": { "label": "13/64", "naklon": 3 }, + "4366": { "label": "13/65", "naklon": 3 }, + "3300": { "label": "13/66", "naklon": 3 }, + "3185": { "label": "13/67", "naklon": 0 }, + "3184": { "label": "13/68", "naklon": 0 }, + "3188": { "label": "13/69", "naklon": 0 }, + "3343": { "label": "13/71", "naklon": 6 }, + "3819": { "label": "13/71/1", "naklon": 6 }, + "3880": { "label": "13/71/2", "naklon": 6 }, + "3348": { "label": "13/72", "naklon": 6 }, + "3344": { "label": "13/74", "naklon": 6 }, + "3346": { "label": "13/75", "naklon": 6 }, + "3597": { "label": "13/75/1", "naklon": 6 }, + "3345": { "label": "13/76", "naklon": 6 }, + "3322": { "label": "13/77", "naklon": 0 }, + "3325": { "label": "13/78", "naklon": 0 }, + "4310": { "label": "13/78/1", "naklon": 0 }, + "3315": { "label": "13/79", "naklon": 0 }, + "3328": { "label": "13/80", "naklon": 0 }, + "3321": { "label": "13/81", "naklon": 0 }, + "3324": { "label": "13/82", "naklon": 0 }, + "3140": { "label": "13/84", "naklon": 0 }, + "3153": { "label": "13/85", "naklon": 0 }, + "3145": { "label": "13/86", "naklon": 0 }, + "3134": { "label": "13/87", "naklon": 0 }, + "3151": { "label": "13/88", "naklon": 0 }, + "3143": { "label": "13/89", "naklon": 0 }, + "3318": { "label": "13/90", "naklon": 0 }, + "3347": { "label": "13/91", "naklon": 0 }, + "3314": { "label": "13/94", "naklon": 0 }, + "3331": { "label": "13/96", "naklon": 0 }, + "3327": { "label": "13/97", "naklon": 0 }, + "3329": { "label": "13/99", "naklon": 0 }, + "3337": { "label": "13/100", "naklon": 0 }, + "3330": { "label": "13/101", "naklon": 0 }, + "3335": { "label": "13/102", "naklon": 0 }, + "3420": { "label": "13/103", "naklon": 0 }, + "3421": { "label": "13/104", "naklon": 0 }, + "4361": { "label": "13/105", "naklon": 0 }, + "4362": { "label": "13/106", "naklon": 0 }, + "3526": { "label": "13/107", "naklon": 0 }, + "4424": { "label": "13/108", "naklon": null }, + "3561": { "label": "13/109", "naklon": null }, + "3527": { "label": "13/110", "naklon": null }, + "3521": { "label": "13/111", "naklon": null }, + "3552": { "label": "13/112", "naklon": null }, + "3544": { "label": "13/113", "naklon": null }, + "3534": { "label": "13/114", "naklon": null }, + "3516": { "label": "13/115", "naklon": null }, + "3513": { "label": "13/116", "naklon": null }, + "3565": { "label": "13/117", "naklon": null }, + "3866": { "label": "13/118", "naklon": null }, + "3136": { "label": "14/1", "naklon": 0 }, + "3137": { "label": "14/2", "naklon": 0 }, + "3135": { "label": "14/3", "naklon": 0 }, + "3149": { "label": "14/4", "naklon": 0 }, + "3142": { "label": "14/5", "naklon": 0 }, + "3342": { "label": "14/6", "naklon": 0 }, + "3340": { "label": "14/7", "naklon": 0 }, + "3152": { "label": "14/8", "naklon": 0 }, + "3886": { "label": "14/9", "naklon": 0 }, + "3341": { "label": "14/10", "naklon": null }, + "3352": { "label": "14/11", "naklon": null }, + "3396": { "label": "15/1", "naklon": 5 }, + "2784": { "label": "15/2", "naklon": 5 }, + "2788": { "label": "15/3", "naklon": 5 }, + "2801": { "label": "15/4", "naklon": 5 }, + "2815": { "label": "15/5", "naklon": 5 }, + "2829": { "label": "15/6", "naklon": 5 }, + "2796": { "label": "15/7", "naklon": 5 }, + "2803": { "label": "15/8", "naklon": 5 }, + "4304": { "label": "15/8/1", "naklon": 5 }, + "4311": { "label": "15/8/2", "naklon": 5 }, + "2821": { "label": "15/9", "naklon": 5 }, + "3400": { "label": "15/10", "naklon": 5 }, + "2799": { "label": "15/11", "naklon": 5 }, + "2804": { "label": "15/12", "naklon": 5 }, + "4303": { "label": "15/12/1", "naklon": 5 }, + "4309": { "label": "15/12/2", "naklon": 5 }, + "2806": { "label": "15/13", "naklon": 5 }, + "2787": { "label": "15/14", "naklon": 5 }, + "2809": { "label": "15/15", "naklon": 5 }, + "2814": { "label": "15/16", "naklon": 0 }, + "3934": { "label": "15/17", "naklon": 0 }, + "3192": { "label": "15/18", "naklon": 0 }, + "2812": { "label": "15/19", "naklon": 0 }, + "4070": { "label": "15/20", "naklon": 0 }, + "2826": { "label": "15/21", "naklon": 0 }, + "2808": { "label": "15/22", "naklon": 3 }, + "2795": { "label": "15/23", "naklon": 3 }, + "2807": { "label": "15/24", "naklon": 3 }, + "2831": { "label": "15/25", "naklon": 0 }, + "2862": { "label": "15/26", "naklon": null }, + "2861": { "label": "15/27", "naklon": 0 }, + "2866": { "label": "15/28", "naklon": 0 }, + "3546": { "label": "15/28/1", "naklon": 0 }, + "4146": { "label": "15/29", "naklon": 0 }, + "3001": { "label": "15/29/1", "naklon": 0 }, + "2835": { "label": "15/30", "naklon": 0 }, + "2874": { "label": "15/31", "naklon": 0 }, + "2852": { "label": "15/32", "naklon": 0 }, + "2851": { "label": "15/33", "naklon": 0 }, + "3560": { "label": "15/33/1", "naklon": 0 }, + "2858": { "label": "15/34", "naklon": 0 }, + "4306": { "label": "15/34/1", "naklon": 0 }, + "2856": { "label": "15/35", "naklon": 0 }, + "2847": { "label": "15/36", "naklon": 0 }, + "3556": { "label": "15/36/1", "naklon": 0 }, + "3950": { "label": "15/37", "naklon": 0 }, + "2848": { "label": "15/38", "naklon": 0 }, + "2863": { "label": "15/39", "naklon": 0 }, + "4313": { "label": "15/39/1", "naklon": 0 }, + "2873": { "label": "15/40", "naklon": 0 }, + "2984": { "label": "15/40/1", "naklon": 0 }, + "2854": { "label": "15/41", "naklon": 0 }, + "2859": { "label": "15/42", "naklon": 0 }, + "2872": { "label": "15/43", "naklon": 0 }, + "2849": { "label": "15/44", "naklon": 0 }, + "2864": { "label": "15/45", "naklon": 0 }, + "3553": { "label": "15/46", "naklon": null }, + "3021": { "label": "15/47", "naklon": null }, + "3008": { "label": "15/47/1", "naklon": null }, + "3017": { "label": "15/48", "naklon": null }, + "3014": { "label": "15/49", "naklon": null }, + "2981": { "label": "15/50", "naklon": null }, + "3020": { "label": "15/51", "naklon": null }, + "3027": { "label": "15/52", "naklon": null }, + "3006": { "label": "15/53", "naklon": null }, + "3012": { "label": "15/54", "naklon": null }, + "2738": { "label": "15/55", "naklon": 0 }, + "2725": { "label": "15/56", "naklon": 0 }, + "3016": { "label": "15/57", "naklon": null }, + "3005": { "label": "15/58", "naklon": null }, + "3009": { "label": "15/58/1", "naklon": null }, + "3010": { "label": "15/59", "naklon": 0 }, + "3538": { "label": "15/59/1", "naklon": 0 }, + "4145": { "label": "15/59/2", "naklon": 0 }, + "2713": { "label": "15/60", "naklon": 0 }, + "2789": { "label": "15/61", "naklon": 0 }, + "2736": { "label": "15/62", "naklon": 0 }, + "2739": { "label": "15/63", "naklon": 0 }, + "4346": { "label": "15/64", "naklon": 0 }, + "2731": { "label": "15/65", "naklon": 0 }, + "2818": { "label": "15/66", "naklon": 0 }, + "3557": { "label": "15/66/1", "naklon": 0 }, + "2822": { "label": "15/67", "naklon": 0 }, + "2833": { "label": "15/68", "naklon": 0 }, + "2834": { "label": "15/69", "naklon": 0 }, + "3097": { "label": "15/70", "naklon": 0 }, + "2824": { "label": "15/71", "naklon": 0 }, + "2828": { "label": "15/72", "naklon": 0 }, + "2600": { "label": "15/73", "naklon": 0 }, + "4314": { "label": "15/73/1", "naklon": 0 }, + "2832": { "label": "15/74", "naklon": 0 }, + "4360": { "label": "15/75", "naklon": 0 }, + "2846": { "label": "15/76", "naklon": 0 }, + "2584": { "label": "15/77", "naklon": 0 }, + "2843": { "label": "15/78", "naklon": 0 }, + "4308": { "label": "15/78/1", "naklon": 0 }, + "4144": { "label": "15/79", "naklon": null }, + "2844": { "label": "15/80", "naklon": 0 }, + "2842": { "label": "15/81", "naklon": 0 }, + "2838": { "label": "15/82", "naklon": 0 }, + "2837": { "label": "15/83", "naklon": null }, + "3555": { "label": "15/83/1", "naklon": null }, + "2839": { "label": "15/84", "naklon": 0 }, + "2830": { "label": "15/85", "naklon": 0 }, + "4066": { "label": "15/86", "naklon": 0 }, + "2836": { "label": "15/87", "naklon": 0 }, + "2911": { "label": "15/88", "naklon": 0 }, + "2825": { "label": "15/89", "naklon": 0 }, + "2811": { "label": "15/90", "naklon": 0 }, + "3740": { "label": "15/94", "naklon": 15 }, + "2734": { "label": "15/95", "naklon": 15 }, + "3105": { "label": "15/96", "naklon": 15 }, + "2732": { "label": "15/97", "naklon": 15 }, + "2727": { "label": "15/98", "naklon": 15 }, + "2735": { "label": "15/99", "naklon": 15 }, + "3926": { "label": "15/100", "naklon": 15 }, + "2918": { "label": "15/101", "naklon": 0 }, + "2705": { "label": "15/102", "naklon": 10 }, + "2708": { "label": "15/103", "naklon": 10 }, + "2721": { "label": "15/104", "naklon": 10 }, + "2719": { "label": "15/105", "naklon": 10 }, + "2919": { "label": "15/106", "naklon": 10 }, + "3101": { "label": "15/107", "naklon": 10 }, + "2853": { "label": "15/108", "naklon": 10 }, + "2715": { "label": "15/109", "naklon": 10 }, + "2712": { "label": "15/110", "naklon": 0 }, + "2711": { "label": "15/111", "naklon": 0 }, + "2709": { "label": "15/112", "naklon": 0 }, + "2710": { "label": "15/113", "naklon": 0 }, + "2907": { "label": "15/114", "naklon": 0 }, + "2906": { "label": "15/115", "naklon": 0 }, + "2908": { "label": "15/116", "naklon": 0 }, + "2901": { "label": "15/117", "naklon": 0 }, + "2913": { "label": "15/118", "naklon": 0 }, + "3656": { "label": "15/119", "naklon": 0 }, + "2781": { "label": "15/120", "naklon": 0 }, + "2802": { "label": "15/121", "naklon": 0 }, + "2791": { "label": "15/122", "naklon": 0 }, + "2783": { "label": "15/123", "naklon": 0 }, + "2794": { "label": "15/124", "naklon": 0 }, + "3139": { "label": "15/125", "naklon": 0 }, + "3229": { "label": "15/126", "naklon": 5 }, + "3239": { "label": "15/127", "naklon": 5 }, + "3230": { "label": "15/128", "naklon": 5 }, + "4016": { "label": "15/129", "naklon": null }, + "3608": { "label": "16/16A", "naklon": 0 }, + "4151": { "label": "16/16B", "naklon": 0 }, + "3710": { "label": "16/1", "naklon": 0 }, + "3726": { "label": "16/2", "naklon": 0 }, + "3743": { "label": "16/3", "naklon": 0 }, + "3724": { "label": "16/4", "naklon": 0 }, + "3712": { "label": "16/5", "naklon": 0 }, + "3739": { "label": "16/6", "naklon": 0 }, + "3742": { "label": "16/7", "naklon": 0 }, + "3731": { "label": "16/8", "naklon": 0 }, + "3727": { "label": "16/9", "naklon": 0 }, + "3729": { "label": "16/10", "naklon": 0 }, + "3736": { "label": "16/11", "naklon": 0 }, + "3713": { "label": "16/12", "naklon": 0 }, + "3715": { "label": "16/13", "naklon": 0 }, + "3733": { "label": "16/14", "naklon": 0 }, + "3732": { "label": "16/15", "naklon": 0 }, + "3634": { "label": "16/17", "naklon": 0 }, + "3610": { "label": "16/18", "naklon": 0 }, + "3626": { "label": "16/19", "naklon": 0 }, + "3618": { "label": "16/20", "naklon": 0 }, + "3619": { "label": "16/21", "naklon": 0 }, + "3628": { "label": "16/22", "naklon": 0 }, + "3615": { "label": "16/23", "naklon": 0 }, + "3609": { "label": "16/24", "naklon": 0 }, + "3606": { "label": "16/25", "naklon": 0 }, + "3624": { "label": "16/26", "naklon": 0 }, + "3627": { "label": "16/27", "naklon": 0 }, + "3607": { "label": "16/28", "naklon": 0 }, + "4370": { "label": "16/29", "naklon": 0 }, + "3692": { "label": "16/30", "naklon": 0 }, + "3614": { "label": "16/31", "naklon": 0 }, + "3623": { "label": "16/32", "naklon": 0 }, + "4373": { "label": "16/33", "naklon": 0 }, + "3620": { "label": "16/34", "naklon": 0 }, + "3685": { "label": "16/35", "naklon": 0 }, + "3616": { "label": "16/36", "naklon": 0 }, + "3686": { "label": "16/37", "naklon": 0 }, + "3688": { "label": "16/38", "naklon": 0 }, + "3684": { "label": "16/39", "naklon": 0 }, + "3825": { "label": "16/40", "naklon": 0 }, + "3865": { "label": "16/41", "naklon": 0 }, + "3824": { "label": "16/42", "naklon": 0 }, + "3871": { "label": "16/43", "naklon": 0 }, + "3801": { "label": "16/44", "naklon": 0 }, + "3862": { "label": "16/45", "naklon": 0 }, + "3876": { "label": "16/46", "naklon": 0 }, + "3861": { "label": "16/47", "naklon": 0 }, + "4215": { "label": "16/48", "naklon": 0 }, + "3605": { "label": "16/49", "naklon": 10 }, + "3603": { "label": "16/50", "naklon": 10 }, + "3592": { "label": "16/51", "naklon": 10 }, + "3598": { "label": "16/52", "naklon": 10 }, + "3594": { "label": "16/53", "naklon": 10 }, + "3593": { "label": "16/54", "naklon": 10 }, + "3630": { "label": "16/55", "naklon": 10 }, + "3763": { "label": "16/56", "naklon": 10 }, + "3746": { "label": "16/57", "naklon": 10 }, + "3699": { "label": "16/58", "naklon": 0 }, + "3698": { "label": "16/59", "naklon": 0 }, + "3709": { "label": "16/60", "naklon": null }, + "3708": { "label": "16/61", "naklon": 0 }, + "3703": { "label": "16/62", "naklon": null }, + "3700": { "label": "16/63", "naklon": 0 }, + "3701": { "label": "16/64", "naklon": null }, + "3704": { "label": "16/65", "naklon": 0 }, + "3707": { "label": "16/66", "naklon": null }, + "3810": { "label": "16/67", "naklon": 0 }, + "4208": { "label": "16/68", "naklon": null }, + "3867": { "label": "16/69", "naklon": 0 }, + "4372": { "label": "16/70", "naklon": null }, + "3881": { "label": "16/71", "naklon": 0 }, + "4204": { "label": "16/72", "naklon": null }, + "3869": { "label": "16/73", "naklon": 0 }, + "4202": { "label": "16/74", "naklon": null }, + "3830": { "label": "16/75", "naklon": 0 }, + "3870": { "label": "16/76", "naklon": null }, + "3964": { "label": "16/77", "naklon": 0 }, + "3849": { "label": "16/78", "naklon": 0 }, + "3694": { "label": "16/79", "naklon": null }, + "3717": { "label": "16/80", "naklon": 0 }, + "3877": { "label": "16/81", "naklon": null }, + "3755": { "label": "16/82", "naklon": 0 }, + "3725": { "label": "16/83", "naklon": null }, + "3716": { "label": "16/84", "naklon": 0 }, + "3696": { "label": "16/85", "naklon": null }, + "3702": { "label": "16/86", "naklon": 0 }, + "3706": { "label": "16/87", "naklon": null }, + "3850": { "label": "16/88", "naklon": 0 }, + "3848": { "label": "16/89", "naklon": null }, + "3737": { "label": "16/90", "naklon": null }, + "3705": { "label": "16/91", "naklon": 0 }, + "3723": { "label": "16/92", "naklon": null }, + "3842": { "label": "16/93", "naklon": 0 }, + "3735": { "label": "16/94", "naklon": null }, + "3719": { "label": "16/95", "naklon": 0 }, + "3697": { "label": "16/96", "naklon": 0 }, + "3711": { "label": "16/97", "naklon": 0 }, + "4107": { "label": "16/98", "naklon": null }, + "4112": { "label": "16/99", "naklon": 5 }, + "4106": { "label": "16/100", "naklon": 5 }, + "4111": { "label": "16/101", "naklon": 5 }, + "4091": { "label": "16/102", "naklon": null }, + "4104": { "label": "16/103", "naklon": 5 }, + "4094": { "label": "16/104", "naklon": null }, + "4089": { "label": "16/105", "naklon": 5 }, + "4095": { "label": "16/106", "naklon": null }, + "4102": { "label": "16/107", "naklon": 5 }, + "4105": { "label": "16/108", "naklon": null }, + "3859": { "label": "16/109", "naklon": null }, + "4090": { "label": "16/110", "naklon": 5 }, + "4110": { "label": "16/111", "naklon": null }, + "4097": { "label": "16/112", "naklon": 5 }, + "4099": { "label": "16/113", "naklon": null }, + "4096": { "label": "16/114", "naklon": null }, + "4101": { "label": "16/115", "naklon": 5 }, + "4109": { "label": "16/116", "naklon": null }, + "4092": { "label": "16/117", "naklon": 5 }, + "3631": { "label": "16/118", "naklon": null }, + "3632": { "label": "16/119", "naklon": 0 }, + "3641": { "label": "16/120", "naklon": null }, + "3638": { "label": "16/121", "naklon": 0 }, + "3637": { "label": "16/122", "naklon": null }, + "4142": { "label": "16/123", "naklon": null }, + "4147": { "label": "16/124", "naklon": 5 }, + "4139": { "label": "16/125", "naklon": 5 }, + "3172": { "label": "20/30A", "naklon": 2 }, + "3164": { "label": "20/30B", "naklon": 2 }, + "3247": { "label": "20/1", "naklon": 10 }, + "3296": { "label": "20/2", "naklon": 10 }, + "3246": { "label": "20/3", "naklon": 10 }, + "3270": { "label": "20/4", "naklon": 10 }, + "3294": { "label": "20/5", "naklon": 10 }, + "3298": { "label": "20/6", "naklon": 10 }, + "3297": { "label": "20/7", "naklon": 10 }, + "3293": { "label": "20/8", "naklon": 10 }, + "3299": { "label": "20/9", "naklon": 10 }, + "3295": { "label": "20/10", "naklon": 10 }, + "3244": { "label": "20/11", "naklon": 10 }, + "3249": { "label": "20/12", "naklon": 10 }, + "3268": { "label": "20/13", "naklon": 10 }, + "3245": { "label": "20/14", "naklon": 10 }, + "3278": { "label": "20/15", "naklon": 10 }, + "3280": { "label": "20/16", "naklon": 10 }, + "3292": { "label": "20/17", "naklon": 10 }, + "3287": { "label": "20/18", "naklon": 10 }, + "3282": { "label": "20/19", "naklon": 10 }, + "3273": { "label": "20/20", "naklon": 0 }, + "3157": { "label": "20/21", "naklon": 0 }, + "3283": { "label": "20/22", "naklon": 0 }, + "3159": { "label": "20/23", "naklon": 0 }, + "3289": { "label": "20/24", "naklon": 0 }, + "3163": { "label": "20/25", "naklon": 0 }, + "3126": { "label": "20/26", "naklon": 0 }, + "3171": { "label": "20/27", "naklon": 0 }, + "3162": { "label": "20/28", "naklon": 0 }, + "3279": { "label": "20/29", "naklon": 10 }, + "3173": { "label": "20/31", "naklon": 0 }, + "3127": { "label": "20/32", "naklon": 0 }, + "3131": { "label": "20/33", "naklon": 0 }, + "3129": { "label": "20/34", "naklon": 0 }, + "3276": { "label": "20/35", "naklon": 2 }, + "3290": { "label": "20/36", "naklon": 2 }, + "3132": { "label": "20/37", "naklon": 0 }, + "3138": { "label": "20/38", "naklon": 0 }, + "3272": { "label": "20/39", "naklon": 0 }, + "3291": { "label": "20/40", "naklon": 0 }, + "3277": { "label": "20/41", "naklon": 10 }, + "3286": { "label": "20/42", "naklon": 10 }, + "3281": { "label": "20/43", "naklon": 10 }, + "3288": { "label": "20/44", "naklon": 10 }, + "3284": { "label": "20/45", "naklon": 10 }, + "3167": { "label": "20/46", "naklon": 10 }, + "3872": { "label": "20/47", "naklon": 0 }, + "3124": { "label": "20/48", "naklon": 0 }, + "3133": { "label": "20/49", "naklon": 0 }, + "3158": { "label": "20/50", "naklon": 0 }, + "3169": { "label": "20/51", "naklon": 0 }, + "3146": { "label": "20/52", "naklon": 0 }, + "3160": { "label": "20/53", "naklon": 0 }, + "3248": { "label": "20/54", "naklon": 0 }, + "3156": { "label": "20/55", "naklon": 0 }, + "3161": { "label": "20/56", "naklon": 0 }, + "3170": { "label": "20/57", "naklon": 0 }, + "3168": { "label": "20/58", "naklon": 0 }, + "3125": { "label": "20/59", "naklon": 0 }, + "3166": { "label": "20/60", "naklon": 0 }, + "3130": { "label": "20/61", "naklon": 0 }, + "3563": { "label": "20/62", "naklon": 0 }, + "3550": { "label": "20/63", "naklon": null }, + "3269": { "label": "20/67", "naklon": 0 }, + "2921": { "label": "21/1", "naklon": 0 }, + "2707": { "label": "21/2", "naklon": 0 }, + "2723": { "label": "21/3", "naklon": 0 }, + "2716": { "label": "21/4", "naklon": 0 }, + "2717": { "label": "21/5", "naklon": 0 }, + "2720": { "label": "21/6", "naklon": 0 }, + "2722": { "label": "21/7", "naklon": 0 }, + "2718": { "label": "21/8", "naklon": 0 }, + "2724": { "label": "21/9", "naklon": 0 }, + "2742": { "label": "21/10", "naklon": 0 }, + "2743": { "label": "21/11", "naklon": 0 }, + "2733": { "label": "21/12", "naklon": 0 }, + "2903": { "label": "21/14", "naklon": 0 }, + "2917": { "label": "21/15", "naklon": 0 }, + "2897": { "label": "21/16", "naklon": 0 }, + "2914": { "label": "21/17", "naklon": 0 }, + "2898": { "label": "21/18", "naklon": 0 }, + "2773": { "label": "21/19", "naklon": 0 }, + "2895": { "label": "21/20", "naklon": 0 }, + "2896": { "label": "21/21", "naklon": 0 }, + "2771": { "label": "21/22", "naklon": 0 }, + "2772": { "label": "21/23", "naklon": 0 }, + "2793": { "label": "21/24", "naklon": 0 }, + "2902": { "label": "21/25", "naklon": 0 }, + "2910": { "label": "21/26", "naklon": 0 }, + "2909": { "label": "21/27", "naklon": 0 }, + "2920": { "label": "21/28", "naklon": 0 }, + "2916": { "label": "21/29", "naklon": 0 }, + "2904": { "label": "21/30", "naklon": 0 }, + "2915": { "label": "21/31", "naklon": 0 }, + "2905": { "label": "21/32", "naklon": 0 }, + "2900": { "label": "21/33", "naklon": 0 }, + "2899": { "label": "21/34", "naklon": 0 }, + "2741": { "label": "21/36", "naklon": 0 }, + "2714": { "label": "21/37", "naklon": 0 }, + "2701": { "label": "21/38", "naklon": 0 }, + "2703": { "label": "21/39", "naklon": 0 }, + "2704": { "label": "21/40", "naklon": 0 }, + "2702": { "label": "21/41", "naklon": 0 }, + "2706": { "label": "21/42", "naklon": 0 }, + "2776": { "label": "21/43", "naklon": 0 }, + "2770": { "label": "21/44", "naklon": 0 }, + "2786": { "label": "21/45", "naklon": 0 }, + "2779": { "label": "21/46", "naklon": 0 }, + "2782": { "label": "21/47", "naklon": 0 }, + "2785": { "label": "21/48", "naklon": 0 }, + "2769": { "label": "21/49", "naklon": 0 }, + "3354": { "label": "21/50", "naklon": 0 }, + "2778": { "label": "21/51", "naklon": 0 }, + "2775": { "label": "21/52", "naklon": 0 }, + "2780": { "label": "21/53", "naklon": 0 }, + "2790": { "label": "21/54", "naklon": 0 }, + "2792": { "label": "21/55", "naklon": 0 }, + "2774": { "label": "21/56", "naklon": 0 }, + "2630": { "label": "22/1", "naklon": 0 }, + "2631": { "label": "22/2", "naklon": 0 }, + "2632": { "label": "22/3", "naklon": 0 }, + "2633": { "label": "22/4", "naklon": 0 }, + "2634": { "label": "22/5", "naklon": 0 }, + "2636": { "label": "22/6", "naklon": 0 }, + "4367": { "label": "22/7", "naklon": 0 }, + "2637": { "label": "22/8", "naklon": 0 }, + "2638": { "label": "22/9", "naklon": 0 }, + "2639": { "label": "22/10", "naklon": 0 }, + "2640": { "label": "22/11", "naklon": 0 }, + "2641": { "label": "22/12", "naklon": 0 }, + "2642": { "label": "22/13", "naklon": 0 }, + "2643": { "label": "22/14", "naklon": 0 }, + "2644": { "label": "22/15", "naklon": 0 }, + "2645": { "label": "22/16", "naklon": 0 }, + "2646": { "label": "22/17", "naklon": 0 }, + "2647": { "label": "22/18", "naklon": 0 }, + "2648": { "label": "22/19", "naklon": 0 }, + "2649": { "label": "22/20", "naklon": 0 }, + "2650": { "label": "22/21", "naklon": 0 }, + "2651": { "label": "22/22", "naklon": 0 }, + "4103": { "label": "22/23", "naklon": 0 }, + "2653": { "label": "22/24", "naklon": 0 }, + "2654": { "label": "22/25", "naklon": 0 }, + "2655": { "label": "22/26", "naklon": 0 }, + "2656": { "label": "22/27", "naklon": 0 }, + "2657": { "label": "22/28", "naklon": 0 }, + "2658": { "label": "22/29", "naklon": 0 }, + "2659": { "label": "22/30", "naklon": 0 }, + "2660": { "label": "22/31", "naklon": 0 }, + "2661": { "label": "22/32", "naklon": 0 }, + "3015": { "label": "22/32/1", "naklon": 0 }, + "2662": { "label": "22/33", "naklon": 0 }, + "2663": { "label": "22/34", "naklon": 0 }, + "2664": { "label": "22/35", "naklon": 0 }, + "2665": { "label": "22/36", "naklon": 0 }, + "2666": { "label": "22/37", "naklon": 0 }, + "2667": { "label": "22/38", "naklon": 0 }, + "2668": { "label": "22/39", "naklon": 0 }, + "2669": { "label": "22/40", "naklon": null }, + "2670": { "label": "22/41", "naklon": null }, + "2671": { "label": "22/42", "naklon": null }, + "3087": { "label": "23/9A", "naklon": 10 }, + "3090": { "label": "23/9B", "naklon": 10 }, + "3075": { "label": "23/1", "naklon": 0 }, + "3089": { "label": "23/2", "naklon": 0 }, + "3088": { "label": "23/3", "naklon": 0 }, + "3228": { "label": "23/4", "naklon": 10 }, + "2751": { "label": "23/5", "naklon": 10 }, + "3243": { "label": "23/6", "naklon": 10 }, + "4349": { "label": "23/7", "naklon": 10 }, + "3102": { "label": "23/8", "naklon": 10 }, + "3099": { "label": "23/10", "naklon": 10 }, + "3103": { "label": "23/11", "naklon": 10 }, + "3093": { "label": "23/12", "naklon": 10 }, + "3098": { "label": "23/13", "naklon": 10 }, + "3092": { "label": "23/14", "naklon": 10 }, + "3233": { "label": "23/15", "naklon": 0 }, + "3095": { "label": "23/16", "naklon": 0 }, + "4074": { "label": "23/17", "naklon": 0 }, + "2729": { "label": "23/18", "naklon": 0 }, + "3234": { "label": "23/19", "naklon": 0 }, + "3094": { "label": "23/20", "naklon": 0 }, + "2817": { "label": "23/21", "naklon": 0 }, + "3226": { "label": "23/22", "naklon": 0 }, + "3225": { "label": "23/23", "naklon": 0 }, + "3237": { "label": "23/24", "naklon": 0 }, + "4250": { "label": "23/25", "naklon": 0 }, + "3059": { "label": "23/26", "naklon": 10 }, + "3238": { "label": "23/27", "naklon": 10 }, + "3242": { "label": "23/28", "naklon": 10 }, + "3236": { "label": "23/29", "naklon": 10 }, + "3112": { "label": "23/30", "naklon": 10 }, + "3224": { "label": "23/31", "naklon": 0 }, + "4298": { "label": "23/32", "naklon": 10 }, + "4150": { "label": "23/33", "naklon": 10 }, + "3091": { "label": "23/34", "naklon": 10 }, + "3771": { "label": "25/1", "naklon": 5 }, + "3777": { "label": "25/2", "naklon": 5 }, + "3749": { "label": "25/3", "naklon": 5 }, + "3769": { "label": "25/4", "naklon": 5 }, + "3765": { "label": "25/5", "naklon": 5 }, + "3785": { "label": "25/6", "naklon": 5 }, + "3761": { "label": "25/7", "naklon": 5 }, + "3758": { "label": "25/8", "naklon": 5 }, + "3766": { "label": "25/9", "naklon": 5 }, + "3779": { "label": "25/10", "naklon": 5 }, + "3899": { "label": "25/11", "naklon": 10 }, + "3922": { "label": "25/12", "naklon": 10 }, + "3912": { "label": "25/13", "naklon": 10 }, + "3933": { "label": "25/14", "naklon": 10 }, + "3921": { "label": "25/15", "naklon": 10 }, + "4300": { "label": "25/16", "naklon": 10 }, + "3927": { "label": "25/17", "naklon": 10 }, + "3212": { "label": "25/18", "naklon": 10 }, + "3208": { "label": "25/19", "naklon": 10 }, + "3207": { "label": "25/20", "naklon": 10 }, + "4294": { "label": "25/21", "naklon": 10 }, + "3209": { "label": "25/22", "naklon": 10 }, + "3745": { "label": "25/23", "naklon": 10 }, + "3762": { "label": "25/24", "naklon": 10 }, + "3215": { "label": "25/25", "naklon": 10 }, + "3210": { "label": "25/26", "naklon": 10 }, + "3211": { "label": "25/27", "naklon": 10 }, + "3206": { "label": "25/28", "naklon": 10 }, + "3918": { "label": "25/29", "naklon": 5 }, + "3928": { "label": "25/30", "naklon": 5 }, + "3917": { "label": "25/31", "naklon": 5 }, + "4029": { "label": "25/32", "naklon": 0 }, + "4038": { "label": "25/33", "naklon": 0 }, + "4022": { "label": "25/34", "naklon": 0 }, + "3937": { "label": "25/35", "naklon": 0 }, + "3190": { "label": "25/36", "naklon": 0 }, + "3835": { "label": "25/37", "naklon": 0 }, + "3201": { "label": "25/38", "naklon": 0 }, + "3193": { "label": "25/39", "naklon": 0 }, + "3191": { "label": "25/40", "naklon": 0 }, + "3203": { "label": "25/41", "naklon": 0 }, + "4301": { "label": "25/42", "naklon": 0 }, + "3223": { "label": "25/43", "naklon": 0 }, + "3202": { "label": "25/44", "naklon": 0 }, + "3205": { "label": "25/45", "naklon": 0 }, + "3194": { "label": "25/46", "naklon": 0 }, + "3198": { "label": "25/47", "naklon": 0 }, + "3204": { "label": "25/48", "naklon": 0 }, + "3200": { "label": "25/49", "naklon": 0 }, + "3216": { "label": "25/50", "naklon": 0 }, + "3932": { "label": "25/51", "naklon": 5 }, + "3923": { "label": "25/52", "naklon": 5 }, + "3913": { "label": "25/53", "naklon": 5 }, + "3900": { "label": "25/54", "naklon": 5 }, + "4189": { "label": "25/55", "naklon": 10 }, + "4191": { "label": "25/56", "naklon": 10 }, + "3790": { "label": "25/57", "naklon": 10 }, + "4190": { "label": "25/58", "naklon": 10 }, + "4302": { "label": "25/59", "naklon": 0 }, + "4351": { "label": "25/60", "naklon": 0 }, + "4075": { "label": "25/61", "naklon": 0 }, + "4071": { "label": "25/62", "naklon": 0 }, + "3784": { "label": "25/63", "naklon": 0 }, + "4065": { "label": "25/64", "naklon": 0 }, + "4297": { "label": "25/65", "naklon": 0 }, + "4295": { "label": "25/66", "naklon": 0 }, + "4299": { "label": "25/67", "naklon": 0 }, + "3772": { "label": "25/68", "naklon": 0 }, + "3941": { "label": "25/69", "naklon": 0 }, + "3782": { "label": "25/70", "naklon": 0 }, + "4068": { "label": "25/71", "naklon": 0 }, + "4073": { "label": "25/72", "naklon": 0 }, + "3901": { "label": "25/73", "naklon": 5 }, + "4296": { "label": "25/74", "naklon": 5 }, + "3910": { "label": "25/75", "naklon": 5 }, + "4293": { "label": "25/76", "naklon": 5 }, + "3919": { "label": "25/77", "naklon": 5 }, + "3924": { "label": "25/78", "naklon": 5 }, + "3909": { "label": "25/79", "naklon": 5 }, + "3896": { "label": "25/80", "naklon": 5 }, + "3911": { "label": "25/81", "naklon": 5 }, + "2819": { "label": "25/82", "naklon": 15 }, + "3776": { "label": "25/83", "naklon": 15 }, + "3752": { "label": "25/84", "naklon": 15 }, + "4353": { "label": "25/85", "naklon": 15 }, + "3791": { "label": "25/86", "naklon": 0 }, + "3770": { "label": "25/87", "naklon": 0 }, + "3760": { "label": "25/88", "naklon": 0 }, + "3115": { "label": "25/89", "naklon": 0 }, + "3738": { "label": "25/90", "naklon": 0 }, + "3748": { "label": "25/91", "naklon": 0 }, + "3753": { "label": "25/92", "naklon": 0 }, + "3775": { "label": "25/93", "naklon": 0 }, + "3778": { "label": "25/94", "naklon": 5 }, + "4078": { "label": "25/95", "naklon": 5 }, + "4088": { "label": "25/96", "naklon": 5 }, + "3856": { "label": "25/97", "naklon": 5 }, + "4084": { "label": "25/98", "naklon": 5 }, + "4069": { "label": "25/99", "naklon": 5 }, + "4188": { "label": "25/100", "naklon": 5 }, + "4064": { "label": "25/101", "naklon": 5 }, + "3792": { "label": "25/102", "naklon": 5 }, + "3780": { "label": "25/103", "naklon": 5 }, + "4034": { "label": "25/104", "naklon": 5 }, + "4072": { "label": "25/105", "naklon": 5 }, + "3884": { "label": "25/106", "naklon": 5 }, + "3793": { "label": "25/107", "naklon": 5 }, + "3863": { "label": "25/108", "naklon": 5 }, + "3855": { "label": "25/109", "naklon": 5 }, + "3846": { "label": "33/1", "naklon": 0 }, + "3943": { "label": "33/2", "naklon": 0 }, + "3903": { "label": "33/3", "naklon": 0 }, + "3982": { "label": "33/4", "naklon": 0 }, + "3879": { "label": "33/5", "naklon": 0 }, + "3887": { "label": "33/6", "naklon": 0 }, + "3920": { "label": "33/7", "naklon": 5 }, + "3942": { "label": "33/8", "naklon": 5 }, + "3829": { "label": "33/9", "naklon": null }, + "3452": { "label": "34/79A", "naklon": 6 }, + "3460": { "label": "34/79B", "naklon": 6 }, + "3443": { "label": "34/90A", "naklon": 6 }, + "3445": { "label": "34/90B", "naklon": 6 }, + "3457": { "label": "34/90C", "naklon": 6 }, + "3461": { "label": "34/97A", "naklon": 6 }, + "3463": { "label": "34/97B", "naklon": 6 }, + "3426": { "label": "34/98A", "naklon": 6 }, + "3444": { "label": "34/98B", "naklon": 6 }, + "3453": { "label": "34/99A", "naklon": 6 }, + "3455": { "label": "34/99B", "naklon": 6 }, + "4009": { "label": "34/1", "naklon": 0 }, + "3602": { "label": "34/2", "naklon": 0 }, + "3441": { "label": "34/3", "naklon": 0 }, + "3464": { "label": "34/4", "naklon": 0 }, + "3883": { "label": "34/5", "naklon": 0 }, + "4098": { "label": "34/6", "naklon": 0 }, + "4003": { "label": "34/7", "naklon": 0 }, + "4004": { "label": "34/8", "naklon": 0 }, + "3888": { "label": "34/9", "naklon": 0 }, + "3997": { "label": "34/10", "naklon": 0 }, + "4006": { "label": "34/11", "naklon": 0 }, + "4000": { "label": "34/12", "naklon": 0 }, + "4011": { "label": "34/13", "naklon": 0 }, + "3999": { "label": "34/14", "naklon": 0 }, + "3981": { "label": "34/15", "naklon": 0 }, + "3988": { "label": "34/16", "naklon": 0 }, + "3986": { "label": "34/17", "naklon": 0 }, + "3998": { "label": "34/18", "naklon": 0 }, + "3983": { "label": "34/19", "naklon": 0 }, + "4005": { "label": "34/20", "naklon": 0 }, + "4001": { "label": "34/21", "naklon": 0 }, + "4008": { "label": "34/22", "naklon": 0 }, + "4002": { "label": "34/23", "naklon": 0 }, + "3996": { "label": "34/24", "naklon": 0 }, + "4007": { "label": "34/25", "naklon": 0 }, + "4113": { "label": "34/26", "naklon": 15 }, + "3595": { "label": "34/27", "naklon": 5 }, + "3599": { "label": "34/28", "naklon": 5 }, + "3601": { "label": "34/29", "naklon": 5 }, + "4205": { "label": "34/30", "naklon": 0 }, + "3987": { "label": "34/31", "naklon": null }, + "4214": { "label": "34/32", "naklon": 0 }, + "4226": { "label": "34/33", "naklon": 0 }, + "4209": { "label": "34/34", "naklon": 0 }, + "4201": { "label": "34/35", "naklon": 0 }, + "3440": { "label": "34/36", "naklon": 0 }, + "3465": { "label": "34/37", "naklon": 0 }, + "3446": { "label": "34/38", "naklon": 0 }, + "4039": { "label": "34/39", "naklon": 5 }, + "4057": { "label": "34/40", "naklon": 5 }, + "3985": { "label": "34/41", "naklon": 0 }, + "3882": { "label": "34/42", "naklon": 0 }, + "4040": { "label": "34/43", "naklon": 5 }, + "3231": { "label": "34/44", "naklon": 0 }, + "3227": { "label": "34/45", "naklon": 0 }, + "3431": { "label": "34/46", "naklon": 0 }, + "4013": { "label": "34/47", "naklon": 0 }, + "4045": { "label": "34/48", "naklon": 0 }, + "3949": { "label": "34/49", "naklon": 0 }, + "3953": { "label": "34/50", "naklon": 0 }, + "3952": { "label": "34/51", "naklon": 0 }, + "3995": { "label": "34/52", "naklon": 0 }, + "3992": { "label": "34/53", "naklon": 0 }, + "4198": { "label": "34/54", "naklon": 0 }, + "3935": { "label": "34/55", "naklon": 0 }, + "4050": { "label": "34/56", "naklon": 0 }, + "4049": { "label": "34/57", "naklon": 0 }, + "4054": { "label": "34/58", "naklon": 0 }, + "3663": { "label": "34/59", "naklon": 6 }, + "3661": { "label": "34/60", "naklon": 6 }, + "3664": { "label": "34/61", "naklon": 6 }, + "3660": { "label": "34/62", "naklon": 6 }, + "3662": { "label": "34/63", "naklon": 6 }, + "3665": { "label": "34/65", "naklon": 6 }, + "3667": { "label": "34/66", "naklon": 6 }, + "3675": { "label": "34/67", "naklon": 6 }, + "3666": { "label": "34/68", "naklon": 6 }, + "3652": { "label": "34/69", "naklon": 6 }, + "3458": { "label": "34/70", "naklon": 6 }, + "4425": { "label": "34/70/1", "naklon": 6 }, + "3459": { "label": "34/71", "naklon": 6 }, + "3435": { "label": "34/72", "naklon": 6 }, + "3448": { "label": "34/73", "naklon": 6 }, + "3451": { "label": "34/74", "naklon": 6 }, + "3442": { "label": "34/75", "naklon": 6 }, + "3449": { "label": "34/76", "naklon": 6 }, + "3450": { "label": "34/77", "naklon": 6 }, + "3433": { "label": "34/78", "naklon": 6 }, + "3432": { "label": "34/80", "naklon": 12 }, + "3470": { "label": "34/81", "naklon": 12 }, + "3438": { "label": "34/82", "naklon": 12 }, + "3439": { "label": "34/83", "naklon": 12 }, + "4028": { "label": "34/84", "naklon": 5 }, + "3596": { "label": "34/85", "naklon": 5 }, + "4021": { "label": "34/86", "naklon": 5 }, + "3437": { "label": "34/87", "naklon": 12 }, + "3428": { "label": "34/88", "naklon": 12 }, + "3430": { "label": "34/89", "naklon": 12 }, + "3454": { "label": "34/91", "naklon": 6 }, + "3492": { "label": "34/92", "naklon": 6 }, + "3462": { "label": "34/93", "naklon": 6 }, + "3427": { "label": "34/94", "naklon": 6 }, + "3434": { "label": "34/95", "naklon": 6 }, + "3456": { "label": "34/96", "naklon": 6 }, + "4307": { "label": "34/98/1", "naklon": 6 }, + "3968": { "label": "35/1", "naklon": 0 }, + "3969": { "label": "35/2", "naklon": 0 }, + "3947": { "label": "35/3", "naklon": 0 }, + "3979": { "label": "35/4", "naklon": 0 }, + "3959": { "label": "35/5", "naklon": 0 }, + "3948": { "label": "35/6", "naklon": 0 }, + "3961": { "label": "35/7", "naklon": 0 }, + "3956": { "label": "35/8", "naklon": 0 }, + "3604": { "label": "35/9", "naklon": 0 }, + "3944": { "label": "35/10", "naklon": 0 }, + "3960": { "label": "35/11", "naklon": 0 }, + "3958": { "label": "35/12", "naklon": 0 }, + "4036": { "label": "35/13", "naklon": 5 }, + "3893": { "label": "35/18", "naklon": 5 }, + "4108": { "label": "35/19", "naklon": 5 }, + "4017": { "label": "35/20", "naklon": 5 }, + "3963": { "label": "35/21", "naklon": 0 }, + "3658": { "label": "35/22", "naklon": 0 }, + "3975": { "label": "35/23", "naklon": 0 }, + "3980": { "label": "35/24", "naklon": 0 }, + "4012": { "label": "35/25", "naklon": 0 }, + "3655": { "label": "35/26", "naklon": 0 }, + "3962": { "label": "35/27", "naklon": 0 }, + "3945": { "label": "35/28", "naklon": 0 }, + "3569": { "label": "35/29", "naklon": 0 }, + "3429": { "label": "35/30", "naklon": 0 }, + "3657": { "label": "35/31", "naklon": 0 }, + "3646": { "label": "35/32", "naklon": 0 }, + "3622": { "label": "35/33", "naklon": 0 }, + "3612": { "label": "35/34", "naklon": 0 }, + "3955": { "label": "35/35", "naklon": 0 }, + "3878": { "label": "35/37", "naklon": 0 }, + "3965": { "label": "35/38", "naklon": 0 }, + "3970": { "label": "35/39", "naklon": 0 }, + "3611": { "label": "35/40", "naklon": 0 }, + "2635": { "label": "35/41", "naklon": 0 }, + "3978": { "label": "35/42", "naklon": 0 }, + "4213": { "label": "35/43", "naklon": 0 }, + "3984": { "label": "35/44", "naklon": 0 }, + "4218": { "label": "35/45", "naklon": 0 }, + "3973": { "label": "35/46", "naklon": 0 }, + "3974": { "label": "35/47", "naklon": 0 }, + "3759": { "label": "35/48", "naklon": 0 }, + "3844": { "label": "35/49", "naklon": 0 }, + "3804": { "label": "35/50", "naklon": 0 }, + "3831": { "label": "35/51", "naklon": 0 }, + "3643": { "label": "35/52", "naklon": 0 }, + "3966": { "label": "35/53", "naklon": 0 }, + "3971": { "label": "35/54", "naklon": 0 }, + "3650": { "label": "35/55", "naklon": 6 }, + "3651": { "label": "35/56", "naklon": 6 }, + "3669": { "label": "35/57", "naklon": 6 }, + "3648": { "label": "35/58", "naklon": 6 }, + "3645": { "label": "35/59", "naklon": 6 }, + "3659": { "label": "35/60", "naklon": 6 }, + "3647": { "label": "35/61", "naklon": 6 }, + "3644": { "label": "35/62", "naklon": 6 }, + "3671": { "label": "35/63", "naklon": 6 }, + "3682": { "label": "35/64", "naklon": 6 }, + "3672": { "label": "35/65", "naklon": 6 }, + "3683": { "label": "35/66", "naklon": 6 }, + "3673": { "label": "35/67", "naklon": 6 }, + "3674": { "label": "35/68", "naklon": 6 }, + "3679": { "label": "35/69", "naklon": 6 }, + "3649": { "label": "35/70", "naklon": 6 }, + "3687": { "label": "35/71", "naklon": 6 }, + "3677": { "label": "35/72", "naklon": 6 }, + "3690": { "label": "35/73", "naklon": 6 }, + "3691": { "label": "35/74", "naklon": 6 }, + "3676": { "label": "35/75", "naklon": 6 }, + "3680": { "label": "35/76", "naklon": 6 }, + "3668": { "label": "35/77", "naklon": 6 }, + "3681": { "label": "35/78", "naklon": 6 }, + "3670": { "label": "35/79", "naklon": 6 }, + "3689": { "label": "35/80", "naklon": 6 }, + "3678": { "label": "35/81", "naklon": 6 }, + "3693": { "label": "35/82", "naklon": 6 }, + "3654": { "label": "35/83", "naklon": null }, + "4086": { "label": "36/1", "naklon": 0 }, + "4085": { "label": "36/2", "naklon": 0 }, + "4083": { "label": "36/3", "naklon": 0 }, + "4087": { "label": "36/4", "naklon": 0 }, + "4077": { "label": "36/5", "naklon": 0 }, + "4082": { "label": "36/6", "naklon": 0 }, + "4186": { "label": "36/7", "naklon": 0 }, + "4206": { "label": "36/8", "naklon": 0 }, + "4080": { "label": "36/9", "naklon": 0 }, + "4081": { "label": "36/10", "naklon": 0 }, + "4210": { "label": "36/11", "naklon": 0 }, + "4079": { "label": "36/12", "naklon": 0 }, + "4076": { "label": "36/13", "naklon": 0 }, + "3852": { "label": "36/14", "naklon": 0 }, + "2813": { "label": "36/15", "naklon": 0 }, + "4219": { "label": "36/16", "naklon": 0 }, + "3104": { "label": "37/1A", "naklon": 15 }, + "3121": { "label": "37/1B", "naklon": 15 }, + "3113": { "label": "37/2", "naklon": 10 }, + "3118": { "label": "37/3", "naklon": 10 }, + "3111": { "label": "37/4", "naklon": 10 }, + "4020": { "label": "37/5", "naklon": 10 }, + "3119": { "label": "37/6", "naklon": 10 }, + "3110": { "label": "37/7", "naklon": 10 }, + "3108": { "label": "37/8", "naklon": 10 }, + "3107": { "label": "37/12", "naklon": 0 }, + "3199": { "label": "37/13", "naklon": 0 }, + "3120": { "label": "37/14", "naklon": 0 }, + "3122": { "label": "37/15", "naklon": 0 }, + "3908": { "label": "37/16", "naklon": 0 }, + "3114": { "label": "37/17", "naklon": 0 }, + "3105": { "label": "37/18", "naklon": 0 }, + "3116": { "label": "37/19", "naklon": 0 }, + "3106": { "label": "37/20", "naklon": 0 }, + "2887": { "label": "37/21", "naklon": 5 }, + "2888": { "label": "37/22", "naklon": 5 }, + "2877": { "label": "37/23", "naklon": 5 }, + "2891": { "label": "37/24", "naklon": 5 }, + "2886": { "label": "37/25", "naklon": 5 }, + "2892": { "label": "37/26", "naklon": 5 }, + "2882": { "label": "37/27", "naklon": 5 }, + "2883": { "label": "37/28", "naklon": 5 }, + "2876": { "label": "37/29", "naklon": 5 }, + "3109": { "label": "37/30", "naklon": 5 }, + "4152": { "label": "37/31", "naklon": 5 }, + "3117": { "label": "37/32", "naklon": 5 }, + "2870": { "label": "37/33", "naklon": 5 }, + "2867": { "label": "37/34", "naklon": 0 }, + "2865": { "label": "37/35", "naklon": 0 }, + "3096": { "label": "37/36", "naklon": 0 }, + "2871": { "label": "37/37", "naklon": 0 }, + "2884": { "label": "37/38", "naklon": 0 }, + "2855": { "label": "37/39", "naklon": 0 }, + "2878": { "label": "37/40", "naklon": 0 }, + "2889": { "label": "37/41", "naklon": 0 }, + "2879": { "label": "37/42", "naklon": 0 }, + "2850": { "label": "37/43", "naklon": 0 }, + "2894": { "label": "37/44", "naklon": 0 }, + "2880": { "label": "37/45", "naklon": 0 }, + "2893": { "label": "37/46", "naklon": 0 }, + "2890": { "label": "37/47", "naklon": 0 }, + "4355": { "label": "37/48", "naklon": 0 }, + "2885": { "label": "37/49", "naklon": 0 }, + "2875": { "label": "37/50", "naklon": 0 }, + "3486": { "label": "38/30A", "naklon": 5 }, + "3714": { "label": "38/30B", "naklon": 0 }, + "3483": { "label": "38/32A", "naklon": 5 }, + "3496": { "label": "38/32B", "naklon": 0 }, + "3487": { "label": "38/35A", "naklon": 5 }, + "3498": { "label": "38/35B", "naklon": 5 }, + "3578": { "label": "38/38A", "naklon": 5 }, + "3508": { "label": "38/38B", "naklon": 5 }, + "3787": { "label": "38/59A", "naklon": 5 }, + "3491": { "label": "38/59B", "naklon": 5 }, + "3568": { "label": "38/1", "naklon": null }, + "3502": { "label": "38/2", "naklon": 0 }, + "3836": { "label": "38/3", "naklon": 0 }, + "3588": { "label": "38/4", "naklon": 0 }, + "3493": { "label": "38/5", "naklon": 0 }, + "3580": { "label": "38/6", "naklon": 0 }, + "3572": { "label": "38/7", "naklon": 0 }, + "3506": { "label": "38/8", "naklon": 0 }, + "3503": { "label": "38/9", "naklon": 0 }, + "3579": { "label": "38/10", "naklon": 0 }, + "3586": { "label": "38/11", "naklon": 0 }, + "3495": { "label": "38/12", "naklon": 5 }, + "3492": { "label": "38/13", "naklon": 5 }, + "3532": { "label": "38/14", "naklon": 5 }, + "3574": { "label": "38/15", "naklon": 5 }, + "4140": { "label": "38/16", "naklon": 5 }, + "3795": { "label": "38/17", "naklon": 5 }, + "3788": { "label": "38/18", "naklon": 5 }, + "3796": { "label": "38/19", "naklon": 5 }, + "3797": { "label": "38/20", "naklon": 5 }, + "3798": { "label": "38/21", "naklon": 5 }, + "3786": { "label": "38/22", "naklon": 5 }, + "4067": { "label": "38/23", "naklon": 5 }, + "3773": { "label": "38/24", "naklon": 5 }, + "3774": { "label": "38/25", "naklon": 5 }, + "3789": { "label": "38/26", "naklon": 5 }, + "3520": { "label": "38/27", "naklon": null }, + "3577": { "label": "38/29", "naklon": 5 }, + "3530": { "label": "38/31", "naklon": null }, + "3488": { "label": "38/33", "naklon": 5 }, + "3505": { "label": "38/34", "naklon": 5 }, + "3497": { "label": "38/36", "naklon": 5 }, + "3490": { "label": "38/37", "naklon": 5 }, + "3585": { "label": "38/39", "naklon": 5 }, + "3582": { "label": "38/40", "naklon": 5 }, + "3507": { "label": "38/41", "naklon": 5 }, + "3484": { "label": "38/42", "naklon": 5 }, + "3501": { "label": "38/43", "naklon": 5 }, + "3581": { "label": "38/44", "naklon": 5 }, + "4192": { "label": "38/45", "naklon": 5 }, + "3576": { "label": "38/46", "naklon": 5 }, + "3489": { "label": "38/47", "naklon": 5 }, + "3573": { "label": "38/48", "naklon": 5 }, + "3504": { "label": "38/49", "naklon": 5 }, + "3794": { "label": "38/50", "naklon": 5 }, + "3485": { "label": "38/51", "naklon": 5 }, + "3482": { "label": "38/52", "naklon": 5 }, + "3575": { "label": "38/53", "naklon": 5 }, + "3499": { "label": "38/54", "naklon": 5 }, + "3494": { "label": "38/55", "naklon": 5 }, + "3583": { "label": "38/56", "naklon": 5 }, + "3570": { "label": "38/57", "naklon": 5 }, + "3500": { "label": "38/58", "naklon": 0 }, + "3510": { "label": "38/63", "naklon": null }, + "3512": { "label": "38/64", "naklon": null }, + "3535": { "label": "38/67", "naklon": null }, + "3531": { "label": "38/68", "naklon": null }, + "3537": { "label": "38/69", "naklon": null }, + "3522": { "label": "39/1", "naklon": 10 }, + "4018": { "label": "39/2", "naklon": 10 }, + "4019": { "label": "39/3", "naklon": 10 }, + "4154": { "label": "39/4", "naklon": 5 }, + "3907": { "label": "39/5", "naklon": 5 }, + "4148": { "label": "39/6", "naklon": 0 }, + "4153": { "label": "39/7", "naklon": 0 }, + "3938": { "label": "39/8", "naklon": 0 }, + "3802": { "label": "39/9", "naklon": 0 }, + "4015": { "label": "39/10", "naklon": 0 }, + "3929": { "label": "39/11", "naklon": 0 }, + "3946": { "label": "39/12", "naklon": 0 }, + "4014": { "label": "39/13", "naklon": 0 }, + "4155": { "label": "39/14", "naklon": 0 }, + "4149": { "label": "39/15", "naklon": 0 }, + "3642": { "label": "39/16", "naklon": 0 }, + "3636": { "label": "39/17", "naklon": 5 }, + "3991": { "label": "39/18", "naklon": 0 }, + "3994": { "label": "39/19", "naklon": 0 }, + "3990": { "label": "39/20", "naklon": 0 }, + "3967": { "label": "39/21", "naklon": 0 }, + "3977": { "label": "39/22", "naklon": 0 }, + "3757": { "label": "39/23", "naklon": 15 }, + "3633": { "label": "39/24", "naklon": 15 }, + "3744": { "label": "39/25", "naklon": 15 }, + "4023": { "label": "39/26", "naklon": 5 }, + "3720": { "label": "39/27", "naklon": 5 }, + "3734": { "label": "39/28", "naklon": 5 }, + "3741": { "label": "39/29", "naklon": 5 }, + "3721": { "label": "39/30", "naklon": 5 }, + "3845": { "label": "39/31", "naklon": 0 }, + "3840": { "label": "39/32", "naklon": 0 }, + "3837": { "label": "39/33", "naklon": null }, + "3839": { "label": "39/34", "naklon": 0 }, + "3542": { "label": "41/1", "naklon": null }, + "3566": { "label": "41/2", "naklon": null }, + "3548": { "label": "41/3", "naklon": null }, + "3515": { "label": "41/4", "naklon": null }, + "3559": { "label": "41/5", "naklon": null }, + "3509": { "label": "41/6", "naklon": null }, + "3524": { "label": "41/7", "naklon": null }, + "3518": { "label": "41/8", "naklon": null }, + "3182": { "label": "41/9", "naklon": null }, + "3187": { "label": "41/10", "naklon": null }, + "3195": { "label": "41/11", "naklon": 0 }, + "3857": { "label": "41/12", "naklon": 0 }, + "3183": { "label": "41/13", "naklon": 0 }, + "3177": { "label": "41/14", "naklon": 0 }, + "3189": { "label": "41/15", "naklon": 0 }, + "3186": { "label": "41/16", "naklon": 0 }, + "3178": { "label": "42/1", "naklon": 0 }, + "3219": { "label": "42/2", "naklon": 0 }, + "3475": { "label": "42/3", "naklon": 0 }, + "3175": { "label": "42/4", "naklon": 0 }, + "3222": { "label": "42/5", "naklon": 0 }, + "3221": { "label": "42/6", "naklon": 0 }, + "3181": { "label": "42/7", "naklon": 0 }, + "3180": { "label": "42/8", "naklon": 0 }, + "3218": { "label": "42/9", "naklon": 0 }, + "3176": { "label": "42/10", "naklon": 0 }, + "3174": { "label": "42/11", "naklon": 0 }, + "3220": { "label": "42/12", "naklon": 0 }, + "3533": { "label": "42/13", "naklon": null }, + "3543": { "label": "42/14", "naklon": null }, + "3554": { "label": "42/15", "naklon": null }, + "3549": { "label": "42/16", "naklon": null }, + "2857": { "label": "43/1", "naklon": 5 }, + "2752": { "label": "43/2", "naklon": 5 }, + "2753": { "label": "43/3", "naklon": 5 }, + "3024": { "label": "43/4", "naklon": 5 }, + "2754": { "label": "43/5", "naklon": 5 }, + "4423": { "label": "43/6", "naklon": 5 }, + "4368": { "label": "43/7", "naklon": 5 }, + "2978": { "label": "43/8", "naklon": 5 }, + "2868": { "label": "43/9", "naklon": 5 }, + "4377": { "label": "43/10", "naklon": 5 }, + "2757": { "label": "43/11", "naklon": 5 }, + "2970": { "label": "43/12", "naklon": 5 }, + "2758": { "label": "43/13", "naklon": 5 }, + "4378": { "label": "43/14", "naklon": 5 }, + "2759": { "label": "43/15", "naklon": 5 }, + "4342": { "label": "43/16", "naklon": 5 }, + "3026": { "label": "43/17", "naklon": null }, + "2986": { "label": "43/18", "naklon": null }, + "4343": { "label": "43/19", "naklon": null }, + "2760": { "label": "43/20", "naklon": null }, + "4379": { "label": "43/21", "naklon": null }, + "2971": { "label": "43/22", "naklon": null }, + "2761": { "label": "43/23", "naklon": null }, + "2762": { "label": "43/24", "naklon": null }, + "4339": { "label": "43/25", "naklon": null }, + "4380": { "label": "43/26", "naklon": null }, + "2975": { "label": "43/27", "naklon": null }, + "3003": { "label": "43/28", "naklon": null }, + "4338": { "label": "43/29", "naklon": null }, + "3002": { "label": "43/30", "naklon": null }, + "4345": { "label": "43/31", "naklon": null }, + "2979": { "label": "43/32", "naklon": null }, + "2989": { "label": "43/33", "naklon": null }, + "2996": { "label": "43/34", "naklon": null }, + "2972": { "label": "43/35", "naklon": null }, + "2988": { "label": "43/36", "naklon": null }, + "4344": { "label": "43/37", "naklon": null }, + "3022": { "label": "43/38", "naklon": null }, + "4341": { "label": "43/39", "naklon": null }, + "2983": { "label": "43/40", "naklon": null }, + "2995": { "label": "43/41", "naklon": null }, + "2763": { "label": "43/42", "naklon": null }, + "2764": { "label": "43/43", "naklon": null }, + "2765": { "label": "43/44", "naklon": null }, + "2766": { "label": "43/45", "naklon": null }, + "2767": { "label": "43/46", "naklon": null }, + "2768": { "label": "43/47", "naklon": null }, + "3018": { "label": "43/48", "naklon": null }, + "2982": { "label": "43/49", "naklon": null }, + "3019": { "label": "43/50", "naklon": 0 }, + "3013": { "label": "43/51", "naklon": null }, + "3007": { "label": "43/52", "naklon": null }, + "2980": { "label": "43/53", "naklon": null }, + "3011": { "label": "43/54", "naklon": null }, + "2672": { "label": "43/55", "naklon": null }, + "2673": { "label": "43/56", "naklon": null }, + "2674": { "label": "43/57", "naklon": null }, + "2675": { "label": "43/58", "naklon": null }, + "2676": { "label": "43/59", "naklon": null }, + "2677": { "label": "43/60", "naklon": null }, + "2678": { "label": "43/61", "naklon": null }, + "2679": { "label": "43/62", "naklon": null }, + "2680": { "label": "43/63", "naklon": null }, + "2840": { "label": "43/64", "naklon": null }, + "2682": { "label": "43/65", "naklon": null }, + "2683": { "label": "43/66", "naklon": null }, + "2684": { "label": "43/67", "naklon": 0 }, + "2685": { "label": "43/68", "naklon": null }, + "2686": { "label": "43/69", "naklon": null }, + "2687": { "label": "43/70", "naklon": null }, + "2688": { "label": "43/71", "naklon": null }, + "2689": { "label": "43/72", "naklon": null }, + "2690": { "label": "43/73", "naklon": null }, + "2691": { "label": "43/74", "naklon": null }, + "2692": { "label": "43/75", "naklon": null }, + "2693": { "label": "43/76", "naklon": 0 }, + "2694": { "label": "43/77", "naklon": null }, + "2695": { "label": "43/78", "naklon": null }, + "2696": { "label": "43/79", "naklon": 0 }, + "2697": { "label": "43/80", "naklon": null }, + "2698": { "label": "43/81", "naklon": 0 }, + "2699": { "label": "43/82", "naklon": null }, + "2700": { "label": "43/83", "naklon": 0 }, + "2744": { "label": "43/84", "naklon": null }, + "2745": { "label": "43/85", "naklon": 0 }, + "2746": { "label": "43/86", "naklon": null }, + "2747": { "label": "43/87", "naklon": 0 }, + "2748": { "label": "43/88", "naklon": null }, + "2749": { "label": "43/89", "naklon": 0 }, + "2841": { "label": "43/90", "naklon": null }, + "4237": { "label": "45/1", "naklon": 5 }, + "4226": { "label": "45/2", "naklon": 5 }, + "4242": { "label": "45/3", "naklon": 5 }, + "4179": { "label": "45/4", "naklon": 5 }, + "4247": { "label": "45/5", "naklon": 5 }, + "4245": { "label": "45/6", "naklon": 5 }, + "3872": { "label": "45/7", "naklon": 5 }, + "4175": { "label": "45/8", "naklon": 5 }, + "4236": { "label": "45/9", "naklon": 5 }, + "4170": { "label": "45/10", "naklon": 5 }, + "4238": { "label": "45/11", "naklon": 5 }, + "4246": { "label": "45/12", "naklon": 5 }, + "4166": { "label": "45/13", "naklon": 5 }, + "4227": { "label": "45/14", "naklon": 5 }, + "4171": { "label": "45/15", "naklon": 5 }, + "4180": { "label": "45/16", "naklon": 5 }, + "4244": { "label": "45/17", "naklon": 5 }, + "4199": { "label": "45/18", "naklon": 5 }, + "4239": { "label": "45/19", "naklon": 5 }, + "4207": { "label": "45/20", "naklon": 5 }, + "4223": { "label": "45/21", "naklon": 5 }, + "4230": { "label": "45/22", "naklon": 5 }, + "4233": { "label": "45/23", "naklon": 5 }, + "4222": { "label": "45/24", "naklon": 5 }, + "4217": { "label": "45/25", "naklon": 5 }, + "4243": { "label": "45/26", "naklon": 5 }, + "4200": { "label": "45/27", "naklon": 5 }, + "4228": { "label": "45/28", "naklon": 5 }, + "4211": { "label": "45/29", "naklon": 5 }, + "4234": { "label": "45/30", "naklon": 5 }, + "4235": { "label": "45/31", "naklon": 5 }, + "4203": { "label": "45/32", "naklon": 5 }, + "4240": { "label": "45/33", "naklon": 5 }, + "4224": { "label": "45/34", "naklon": 5 }, + "4232": { "label": "45/35", "naklon": 5 }, + "4231": { "label": "45/36", "naklon": 5 }, + "4161": { "label": "45/37", "naklon": 5 }, + "4225": { "label": "45/38", "naklon": 5 }, + "4241": { "label": "45/39", "naklon": 5 }, + "4229": { "label": "45/40", "naklon": 5 }, + "4221": { "label": "45/41", "naklon": 5 }, + "4212": { "label": "45/42", "naklon": 5 }, + "4216": { "label": "45/43", "naklon": 5 }, + "3864": { "label": "45/44", "naklon": null }, + "3806": { "label": "46/1", "naklon": 5 }, + "3813": { "label": "46/2", "naklon": 5 }, + "3815": { "label": "46/3", "naklon": 5 }, + "3807": { "label": "46/4", "naklon": 5 }, + "3895": { "label": "46/5", "naklon": 5 }, + "3809": { "label": "46/6", "naklon": 5 }, + "3820": { "label": "46/7", "naklon": 5 }, + "3805": { "label": "46/8", "naklon": 5 }, + "3894": { "label": "46/9", "naklon": 0 }, + "4055": { "label": "46/10", "naklon": 0 }, + "3812": { "label": "46/11", "naklon": 5 }, + "3822": { "label": "46/12", "naklon": 5 }, + "3821": { "label": "46/13", "naklon": 5 }, + "3808": { "label": "46/14", "naklon": 5 }, + "3799": { "label": "46/15", "naklon": 5 }, + "3816": { "label": "46/16", "naklon": 5 }, + "3751": { "label": "46/17", "naklon": 5 }, + "3814": { "label": "46/18", "naklon": 5 }, + "4044": { "label": "46/19", "naklon": 0 }, + "3931": { "label": "46/20", "naklon": 0 }, + "3902": { "label": "46/21", "naklon": 5 }, + "3916": { "label": "46/22", "naklon": 5 }, + "3892": { "label": "46/23", "naklon": 5 }, + "3914": { "label": "46/24", "naklon": 5 }, + "3898": { "label": "46/25", "naklon": 5 }, + "3897": { "label": "46/26", "naklon": 5 }, + "3885": { "label": "46/27", "naklon": 5 }, + "3906": { "label": "46/28", "naklon": 5 }, + "3930": { "label": "46/29", "naklon": 0 }, + "3936": { "label": "46/30", "naklon": 0 }, + "3860": { "label": "46/31", "naklon": 5 }, + "3841": { "label": "46/32", "naklon": 5 }, + "3873": { "label": "46/33", "naklon": 5 }, + "3854": { "label": "46/34", "naklon": 5 }, + "3939": { "label": "46/35", "naklon": 5 }, + "3858": { "label": "46/36", "naklon": 5 }, + "3940": { "label": "46/37", "naklon": 5 }, + "4035": { "label": "46/38", "naklon": 5 }, + "3373": { "label": "47/1", "naklon": 0 }, + "3374": { "label": "47/2", "naklon": 0 }, + "3384": { "label": "47/3", "naklon": 0 }, + "3385": { "label": "47/4", "naklon": 0 }, + "4051": { "label": "48/1", "naklon": 5 }, + "4041": { "label": "48/2", "naklon": 5 }, + "4056": { "label": "48/3", "naklon": 5 }, + "3875": { "label": "48/4", "naklon": 5 }, + "4061": { "label": "48/5", "naklon": 5 }, + "4047": { "label": "48/6", "naklon": 5 }, + "4060": { "label": "48/7", "naklon": 5 }, + "4059": { "label": "48/8", "naklon": 5 }, + "4058": { "label": "48/9", "naklon": 5 }, + "3635": { "label": "48/10", "naklon": 5 }, + "3640": { "label": "48/11", "naklon": 5 }, + "3747": { "label": "48/12", "naklon": 5 }, + "3629": { "label": "48/13", "naklon": 5 }, + "4048": { "label": "48/14", "naklon": 5 }, + "4063": { "label": "48/15", "naklon": 5 }, + "4062": { "label": "48/16", "naklon": 5 }, + "4043": { "label": "48/17", "naklon": 5 }, + "4052": { "label": "48/18", "naklon": 5 }, + "4042": { "label": "48/19", "naklon": 5 }, + "4053": { "label": "48/20", "naklon": 5 }, + "4167": { "label": "50/15A", "naklon": null }, + "4159": { "label": "50/15B", "naklon": null }, + "4183": { "label": "50/1", "naklon": 0 }, + "4157": { "label": "50/2", "naklon": 0 }, + "4160": { "label": "50/3", "naklon": 0 }, + "4173": { "label": "50/4", "naklon": 0 }, + "4177": { "label": "50/5", "naklon": 0 }, + "4174": { "label": "50/6", "naklon": 0 }, + "4178": { "label": "50/7", "naklon": 0 }, + "4195": { "label": "50/8", "naklon": 0 }, + "4169": { "label": "50/9", "naklon": 0 }, + "4162": { "label": "50/10", "naklon": 0 }, + "4158": { "label": "50/11", "naklon": 0 }, + "4182": { "label": "50/12", "naklon": 0 }, + "4194": { "label": "50/13", "naklon": 0 }, + "4184": { "label": "50/14", "naklon": 0 }, + "4197": { "label": "50/16", "naklon": null }, + "4164": { "label": "50/17", "naklon": null }, + "3306": { "label": "50/18", "naklon": null }, + "4168": { "label": "50/19", "naklon": null }, + "4193": { "label": "50/20", "naklon": null }, + "4187": { "label": "50/21", "naklon": null }, + "4163": { "label": "50/22", "naklon": null }, + "4165": { "label": "50/23", "naklon": null }, + "4185": { "label": "50/24", "naklon": null }, + "3904": { "label": "50/25", "naklon": null }, + "2619": { "label": "53/1", "naklon": 0 }, + "2623": { "label": "53/2", "naklon": 0 }, + "2617": { "label": "53/3", "naklon": 0 }, + "2622": { "label": "53/4", "naklon": 0 }, + "2618": { "label": "53/5", "naklon": 0 }, + "2626": { "label": "53/6", "naklon": 0 }, + "2869": { "label": "53/7", "naklon": 0 }, + "2613": { "label": "53/8", "naklon": 0 }, + "2608": { "label": "53/9", "naklon": 0 }, + "2611": { "label": "53/10", "naklon": 0 }, + "2598": { "label": "53/11", "naklon": 0 }, + "3528": { "label": "53/12", "naklon": 0 }, + "3545": { "label": "53/13", "naklon": 0 }, + "2620": { "label": "53/14", "naklon": 0 }, + "2612": { "label": "53/15", "naklon": 0 }, + "2615": { "label": "53/16", "naklon": 0 }, + "3722": { "label": "53/17", "naklon": 0 }, + "2624": { "label": "53/18", "naklon": 0 }, + "2609": { "label": "53/19", "naklon": 0 }, + "2625": { "label": "53/20", "naklon": 0 }, + "2602": { "label": "53/21", "naklon": 0 }, + "2610": { "label": "53/22", "naklon": 0 }, + "2599": { "label": "53/23", "naklon": 0 }, + "2605": { "label": "53/24", "naklon": 0 }, + "2593": { "label": "53/25", "naklon": 0 }, + "3074": { "label": "53/26", "naklon": 0 }, + "2740": { "label": "53/27", "naklon": 0 }, + "2614": { "label": "53/28", "naklon": 0 }, + "2601": { "label": "53/29", "naklon": 0 }, + "4196": { "label": "53/30", "naklon": 0 }, + "2607": { "label": "53/31", "naklon": 0 }, + "2582": { "label": "53/32", "naklon": 0 }, + "2594": { "label": "53/33", "naklon": 0 }, + "2589": { "label": "53/34", "naklon": 0 }, + "2596": { "label": "53/35", "naklon": 0 }, + "2603": { "label": "53/36", "naklon": 0 }, + "2597": { "label": "53/37", "naklon": 0 }, + "2590": { "label": "53/38", "naklon": 0 }, + "2581": { "label": "53/39", "naklon": 0 }, + "2583": { "label": "53/40", "naklon": 0 }, + "2580": { "label": "53/41", "naklon": 0 }, + "2579": { "label": "53/42", "naklon": 0 }, + "2797": { "label": "53/43", "naklon": 0 }, + "2577": { "label": "53/44", "naklon": 0 }, + "2586": { "label": "53/45", "naklon": 0 }, + "2588": { "label": "53/46", "naklon": 0 }, + "2591": { "label": "53/47", "naklon": 0 }, + "2592": { "label": "53/48", "naklon": 0 }, + "2573": { "label": "53/49", "naklon": 0 }, + "2595": { "label": "53/50", "naklon": 0 }, + "2587": { "label": "53/51", "naklon": 0 }, + "2578": { "label": "53/52", "naklon": 0 }, + "2574": { "label": "53/53", "naklon": 0 }, + "2571": { "label": "53/54", "naklon": 0 }, + "2570": { "label": "53/55", "naklon": 0 }, + "2576": { "label": "53/56", "naklon": 0 }, + "2881": { "label": "53/57", "naklon": 0 }, + "2575": { "label": "53/58", "naklon": 0 }, + "2572": { "label": "53/59", "naklon": 0 }, + "2569": { "label": "53/60", "naklon": 0 }, + "4324": { "label": "55/1", "naklon": 0 }, + "4319": { "label": "55/2", "naklon": 0 }, + "4327": { "label": "55/3", "naklon": 0 }, + "4333": { "label": "55/4", "naklon": 0 }, + "4332": { "label": "55/5", "naklon": 0 }, + "4320": { "label": "55/6", "naklon": 0 }, + "4317": { "label": "55/7", "naklon": 0 }, + "4318": { "label": "55/8", "naklon": 0 }, + "4328": { "label": "55/9", "naklon": 0 }, + "4323": { "label": "55/10", "naklon": 0 }, + "4325": { "label": "55/11", "naklon": 0 }, + "4326": { "label": "55/12", "naklon": 0 }, + "4316": { "label": "55/13", "naklon": 0 }, + "4322": { "label": "55/14", "naklon": 0 }, + "4331": { "label": "55/15", "naklon": 0 }, + "4321": { "label": "55/16", "naklon": 0 }, + "4315": { "label": "55/17", "naklon": 0 }, + "4329": { "label": "55/18", "naklon": 0 }, + "4334": { "label": "55/19", "naklon": 0 }, + "4330": { "label": "55/20", "naklon": 0 } +}; + + +let svetlaSorted = [{ "label": "1/3A", "node": 3993, "naklon": 0 }, +{ "label": "1/3B", "node": 3989, "naklon": 15 }, +{ "label": "1/1", "node": 3976, "naklon": 0 }, +{ "label": "1/2", "node": 4181, "naklon": 0 }, +{ "label": "1/4", "node": 4376, "naklon": 15 }, +{ "label": "1/5", "node": 3868, "naklon": 15 }, +{ "label": "1/6", "node": 3728, "naklon": 15 }, +{ "label": "1/7", "node": 3730, "naklon": 0 }, +{ "label": "1/8", "node": 4374, "naklon": 0 }, +{ "label": "1/9", "node": 3718, "naklon": 15 }, +{ "label": "1/10", "node": 4375, "naklon": 15 }, +{ "label": "1/11", "node": 4172, "naklon": 15 }, +{ "label": "1/12", "node": 4176, "naklon": 15 }, +{ "label": "2/1", "node": 3800, "naklon": 5 }, +{ "label": "2/2", "node": 3823, "naklon": 5 }, +{ "label": "2/3", "node": 3905, "naklon": 5 }, +{ "label": "2/4", "node": 3803, "naklon": 5 }, +{ "label": "2/5", "node": 3817, "naklon": 5 }, +{ "label": "2/6", "node": 3818, "naklon": 5 }, +{ "label": "2/7", "node": 3811, "naklon": 5 }, +{ "label": "2/8", "node": 3915, "naklon": 5 }, +{ "label": "2/9", "node": 3843, "naklon": 10 }, +{ "label": "2/10", "node": 3827, "naklon": 10 }, +{ "label": "2/11", "node": 4220, "naklon": 10 }, +{ "label": "2/12", "node": 3826, "naklon": 10 }, +{ "label": "2/13", "node": 3834, "naklon": 10 }, +{ "label": "2/14", "node": 3838, "naklon": 10 }, +{ "label": "2/15", "node": 2823, "naklon": 10 }, +{ "label": "2/16", "node": 3750, "naklon": 10 }, +{ "label": "2/17", "node": 3378, "naklon": 0 }, +{ "label": "2/18", "node": 3376, "naklon": 0 }, +{ "label": "2/19", "node": 3379, "naklon": 0 }, +{ "label": "2/20", "node": 3285, "naklon": 0 }, +{ "label": "2/21", "node": 3382, "naklon": 0 }, +{ "label": "2/22", "node": 3383, "naklon": 0 }, +{ "label": "2/24", "node": 3375, "naklon": 0 }, +{ "label": "2/25", "node": 3381, "naklon": 0 }, +{ "label": "2/26", "node": 3380, "naklon": 0 }, +{ "label": "2/27", "node": 3828, "naklon": 10 }, +{ "label": "2/28", "node": 3377, "naklon": 0 }, +{ "label": "7/1", "node": 3591, "naklon": 0 }, +{ "label": "7/2", "node": 3587, "naklon": 0 }, +{ "label": "7/3", "node": 3468, "naklon": 0 }, +{ "label": "7/4", "node": 3466, "naklon": 0 }, +{ "label": "7/5", "node": 3474, "naklon": 0 }, +{ "label": "7/6", "node": 3481, "naklon": 0 }, +{ "label": "7/7", "node": 3589, "naklon": 0 }, +{ "label": "7/8", "node": 3472, "naklon": 0 }, +{ "label": "7/9", "node": 3473, "naklon": 0 }, +{ "label": "7/10", "node": 3584, "naklon": 0 }, +{ "label": "7/11", "node": 3571, "naklon": 0 }, +{ "label": "7/12", "node": 3476, "naklon": 0 }, +{ "label": "7/13", "node": 3590, "naklon": 0 }, +{ "label": "7/14", "node": 3478, "naklon": 0 }, +{ "label": "7/15", "node": 3471, "naklon": 0 }, +{ "label": "7/16", "node": 3467, "naklon": 0 }, +{ "label": "7/17", "node": 3479, "naklon": 0 }, +{ "label": "7/18", "node": 3480, "naklon": 0 }, +{ "label": "7/19", "node": 3477, "naklon": 0 }, +{ "label": "12/1", "node": 3362, "naklon": 0 }, +{ "label": "12/2", "node": 3355, "naklon": 0 }, +{ "label": "12/3", "node": 3356, "naklon": 0 }, +{ "label": "12/4", "node": 3349, "naklon": 0 }, +{ "label": "12/5", "node": 3357, "naklon": 0 }, +{ "label": "12/6", "node": 3350, "naklon": 0 }, +{ "label": "12/7", "node": 3353, "naklon": 0 }, +{ "label": "12/8", "node": 3539, "naklon": 0 }, +{ "label": "12/9", "node": 3050, "naklon": 0 }, +{ "label": "12/10", "node": 3361, "naklon": 0 }, +{ "label": "12/11", "node": 3360, "naklon": 0 }, +{ "label": "12/12", "node": 3358, "naklon": 0 }, +{ "label": "12/13", "node": 3541, "naklon": 0 }, +{ "label": "12/14", "node": 3551, "naklon": 0 }, +{ "label": "12/15", "node": 3514, "naklon": 0 }, +{ "label": "12/16", "node": 3547, "naklon": 0 }, +{ "label": "12/17", "node": 3562, "naklon": 0 }, +{ "label": "12/18", "node": 3525, "naklon": 0 }, +{ "label": "12/19", "node": 3558, "naklon": 0 }, +{ "label": "12/20", "node": 3511, "naklon": 0 }, +{ "label": "12/21", "node": 3058, "naklon": 0 }, +{ "label": "12/22", "node": 3062, "naklon": 0 }, +{ "label": "12/23", "node": 3070, "naklon": 0 }, +{ "label": "12/24", "node": 3447, "naklon": 0 }, +{ "label": "12/25", "node": 3056, "naklon": 0 }, +{ "label": "12/26", "node": 3057, "naklon": 0 }, +{ "label": "12/27", "node": 3071, "naklon": 0 }, +{ "label": "12/28", "node": 3061, "naklon": 0 }, +{ "label": "12/29", "node": 3069, "naklon": 0 }, +{ "label": "12/30", "node": 3077, "naklon": 0 }, +{ "label": "12/31", "node": 3080, "naklon": 0 }, +{ "label": "12/32", "node": 3081, "naklon": 0 }, +{ "label": "12/33", "node": 3078, "naklon": 0 }, +{ "label": "12/34", "node": 4037, "naklon": 0 }, +{ "label": "12/35", "node": 3067, "naklon": 0 }, +{ "label": "12/36", "node": 3051, "naklon": 0 }, +{ "label": "12/37", "node": 2924, "naklon": 0 }, +{ "label": "12/38", "node": 3060, "naklon": 0 }, +{ "label": "12/39", "node": 3073, "naklon": 0 }, +{ "label": "12/40", "node": 3469, "naklon": 0 }, +{ "label": "12/41", "node": 2923, "naklon": 0 }, +{ "label": "12/42", "node": 2925, "naklon": 0 }, +{ "label": "12/43", "node": 3359, "naklon": 0 }, +{ "label": "12/44", "node": 3055, "naklon": 0 }, +{ "label": "12/45", "node": 2922, "naklon": 0 }, +{ "label": "12/46", "node": 3084, "naklon": 0 }, +{ "label": "12/47", "node": 3064, "naklon": 0 }, +{ "label": "12/48", "node": 3066, "naklon": 0 }, +{ "label": "12/49", "node": 3072, "naklon": 0 }, +{ "label": "13/13A", "node": 3415, "naklon": 0 }, +{ "label": "13/13B", "node": 3409, "naklon": 0 }, +{ "label": "13/13C", "node": 3399, "naklon": 0 }, +{ "label": "13/29A", "node": 3410, "naklon": 0 }, +{ "label": "13/29B", "node": 3407, "naklon": 0 }, +{ "label": "13/34A", "node": 3405, "naklon": 0 }, +{ "label": "13/34B", "node": 3404, "naklon": 0 }, +{ "label": "13/45A", "node": 3392, "naklon": 0 }, +{ "label": "13/45B", "node": 3386, "naklon": 0 }, +{ "label": "13/60A", "node": 3303, "naklon": 3 }, +{ "label": "13/60B", "node": 3302, "naklon": 3 }, +{ "label": "13/70A", "node": 3319, "naklon": 6 }, +{ "label": "13/70B", "node": 3317, "naklon": 6 }, +{ "label": "13/70C", "node": 3326, "naklon": 6 }, +{ "label": "13/73A", "node": 3351, "naklon": 6 }, +{ "label": "13/73B", "node": 3313, "naklon": 6 }, +{ "label": "13/83A", "node": 3316, "naklon": 0 }, +{ "label": "13/83B", "node": 3320, "naklon": 0 }, +{ "label": "13/95A", "node": 3336, "naklon": 0 }, +{ "label": "13/95B", "node": 3323, "naklon": 0 }, +{ "label": "13/98A", "node": 3339, "naklon": 0 }, +{ "label": "13/98B", "node": 3333, "naklon": 0 }, +{ "label": "13/1", "node": 3425, "naklon": 0 }, +{ "label": "13/2", "node": 3419, "naklon": 0 }, +{ "label": "13/3", "node": 3416, "naklon": 0 }, +{ "label": "13/4", "node": 3332, "naklon": 0 }, +{ "label": "13/5", "node": 3422, "naklon": 0 }, +{ "label": "13/6", "node": 3417, "naklon": 0 }, +{ "label": "13/7", "node": 3418, "naklon": 0 }, +{ "label": "13/8", "node": 3424, "naklon": 0 }, +{ "label": "13/9", "node": 3334, "naklon": 0 }, +{ "label": "13/10", "node": 4363, "naklon": 0 }, +{ "label": "13/11", "node": 3423, "naklon": 0 }, +{ "label": "13/12", "node": 3406, "naklon": 0 }, +{ "label": "13/14", "node": 3411, "naklon": 0 }, +{ "label": "13/15", "node": 3412, "naklon": 0 }, +{ "label": "13/16", "node": 3413, "naklon": 0 }, +{ "label": "13/17", "node": 3414, "naklon": 0 }, +{ "label": "13/18", "node": 3391, "naklon": 0 }, +{ "label": "13/19", "node": 3370, "naklon": 0 }, +{ "label": "13/20", "node": 3369, "naklon": 0 }, +{ "label": "13/21", "node": 3408, "naklon": 0 }, +{ "label": "13/22", "node": 3393, "naklon": 0 }, +{ "label": "13/23", "node": 3128, "naklon": 0 }, +{ "label": "13/24", "node": 3197, "naklon": 0 }, +{ "label": "13/25", "node": 4364, "naklon": 0 }, +{ "label": "13/26", "node": 3155, "naklon": 0 }, +{ "label": "13/27", "node": 3196, "naklon": 0 }, +{ "label": "13/28", "node": 3144, "naklon": 0 }, +{ "label": "13/30", "node": 3150, "naklon": 0 }, +{ "label": "13/31", "node": 3390, "naklon": 0 }, +{ "label": "13/32", "node": 3401, "naklon": 0 }, +{ "label": "13/33", "node": 3275, "naklon": 0 }, +{ "label": "13/35", "node": 3371, "naklon": 0 }, +{ "label": "13/36", "node": 3389, "naklon": 0 }, +{ "label": "13/37", "node": 3388, "naklon": 0 }, +{ "label": "13/38", "node": 3365, "naklon": 0 }, +{ "label": "13/39", "node": 3363, "naklon": 0 }, +{ "label": "13/40", "node": 3397, "naklon": 0 }, +{ "label": "13/40/1", "node": 3567, "naklon": 0 }, +{ "label": "13/41", "node": 3387, "naklon": 0 }, +{ "label": "13/42", "node": 3403, "naklon": 0 }, +{ "label": "13/43", "node": 3147, "naklon": 0 }, +{ "label": "13/44", "node": 3141, "naklon": 0 }, +{ "label": "13/46", "node": 3364, "naklon": 0 }, +{ "label": "13/47", "node": 3367, "naklon": 0 }, +{ "label": "13/48", "node": 3368, "naklon": 0 }, +{ "label": "13/49", "node": 3402, "naklon": 0 }, +{ "label": "13/50", "node": 3366, "naklon": 0 }, +{ "label": "13/51", "node": 3395, "naklon": 0 }, +{ "label": "13/52", "node": 3372, "naklon": 0 }, +{ "label": "13/53", "node": 3394, "naklon": 0 }, +{ "label": "13/54", "node": 3308, "naklon": 0 }, +{ "label": "13/54/1", "node": 3847, "naklon": 0 }, +{ "label": "13/55", "node": 3312, "naklon": 3 }, +{ "label": "13/56", "node": 3309, "naklon": 3 }, +{ "label": "13/57", "node": 3311, "naklon": 3 }, +{ "label": "13/58", "node": 3310, "naklon": 3 }, +{ "label": "13/59", "node": 4365, "naklon": 3 }, +{ "label": "13/60/1", "node": 4093, "naklon": 3 }, +{ "label": "13/61", "node": 3304, "naklon": 3 }, +{ "label": "13/62", "node": 3307, "naklon": 3 }, +{ "label": "13/63", "node": 3271, "naklon": 3 }, +{ "label": "13/64", "node": 3301, "naklon": 3 }, +{ "label": "13/65", "node": 4366, "naklon": 3 }, +{ "label": "13/66", "node": 3300, "naklon": 3 }, +{ "label": "13/67", "node": 3185, "naklon": 0 }, +{ "label": "13/68", "node": 3184, "naklon": 0 }, +{ "label": "13/69", "node": 3188, "naklon": 0 }, +{ "label": "13/71", "node": 3343, "naklon": 6 }, +{ "label": "13/71/1", "node": 3819, "naklon": 6 }, +{ "label": "13/71/2", "node": 3880, "naklon": 6 }, +{ "label": "13/72", "node": 3348, "naklon": 6 }, +{ "label": "13/74", "node": 3344, "naklon": 6 }, +{ "label": "13/75", "node": 3346, "naklon": 6 }, +{ "label": "13/75/1", "node": 3597, "naklon": 6 }, +{ "label": "13/76", "node": 3345, "naklon": 6 }, +{ "label": "13/77", "node": 3322, "naklon": 0 }, +{ "label": "13/78", "node": 3325, "naklon": 0 }, +{ "label": "13/78/1", "node": 4310, "naklon": 0 }, +{ "label": "13/79", "node": 3315, "naklon": 0 }, +{ "label": "13/80", "node": 3328, "naklon": 0 }, +{ "label": "13/81", "node": 3321, "naklon": 0 }, +{ "label": "13/82", "node": 3324, "naklon": 0 }, +{ "label": "13/84", "node": 3140, "naklon": 0 }, +{ "label": "13/85", "node": 3153, "naklon": 0 }, +{ "label": "13/86", "node": 3145, "naklon": 0 }, +{ "label": "13/87", "node": 3134, "naklon": 0 }, +{ "label": "13/88", "node": 3151, "naklon": 0 }, +{ "label": "13/89", "node": 3143, "naklon": 0 }, +{ "label": "13/90", "node": 3318, "naklon": 0 }, +{ "label": "13/91", "node": 3347, "naklon": 0 }, +{ "label": "13/94", "node": 3314, "naklon": 0 }, +{ "label": "13/96", "node": 3331, "naklon": 0 }, +{ "label": "13/97", "node": 3327, "naklon": 0 }, +{ "label": "13/99", "node": 3329, "naklon": 0 }, +{ "label": "13/100", "node": 3337, "naklon": 0 }, +{ "label": "13/101", "node": 3330, "naklon": 0 }, +{ "label": "13/102", "node": 3335, "naklon": 0 }, +{ "label": "13/103", "node": 3420, "naklon": 0 }, +{ "label": "13/104", "node": 3421, "naklon": 0 }, +{ "label": "13/105", "node": 4361, "naklon": 0 }, +{ "label": "13/106", "node": 4362, "naklon": 0 }, +{ "label": "13/107", "node": 3526, "naklon": 0 }, +{ "label": "13/108", "node": 4424, "naklon": null }, +{ "label": "13/109", "node": 3561, "naklon": null }, +{ "label": "13/110", "node": 3527, "naklon": null }, +{ "label": "13/111", "node": 3521, "naklon": null }, +{ "label": "13/112", "node": 3552, "naklon": null }, +{ "label": "13/113", "node": 3544, "naklon": null }, +{ "label": "13/114", "node": 3534, "naklon": null }, +{ "label": "13/115", "node": 3516, "naklon": null }, +{ "label": "13/116", "node": 3513, "naklon": null }, +{ "label": "13/117", "node": 3565, "naklon": null }, +{ "label": "13/118", "node": 3866, "naklon": null }, +{ "label": "14/1", "node": 3136, "naklon": 0 }, +{ "label": "14/2", "node": 3137, "naklon": 0 }, +{ "label": "14/3", "node": 3135, "naklon": 0 }, +{ "label": "14/4", "node": 3149, "naklon": 0 }, +{ "label": "14/5", "node": 3142, "naklon": 0 }, +{ "label": "14/6", "node": 3342, "naklon": 0 }, +{ "label": "14/7", "node": 3340, "naklon": 0 }, +{ "label": "14/8", "node": 3152, "naklon": 0 }, +{ "label": "14/9", "node": 3886, "naklon": 0 }, +{ "label": "14/10", "node": 3341, "naklon": null }, +{ "label": "14/11", "node": 3352, "naklon": null }, +{ "label": "15/1", "node": 3396, "naklon": 5 }, +{ "label": "15/2", "node": 2784, "naklon": 5 }, +{ "label": "15/3", "node": 2788, "naklon": 5 }, +{ "label": "15/4", "node": 2801, "naklon": 5 }, +{ "label": "15/5", "node": 2815, "naklon": 5 }, +{ "label": "15/6", "node": 2829, "naklon": 5 }, +{ "label": "15/7", "node": 2796, "naklon": 5 }, +{ "label": "15/8", "node": 2803, "naklon": 5 }, +{ "label": "15/8/1", "node": 4304, "naklon": 5 }, +{ "label": "15/8/2", "node": 4311, "naklon": 5 }, +{ "label": "15/9", "node": 2821, "naklon": 5 }, +{ "label": "15/10", "node": 3400, "naklon": 5 }, +{ "label": "15/11", "node": 2799, "naklon": 5 }, +{ "label": "15/12", "node": 2804, "naklon": 5 }, +{ "label": "15/12/1", "node": 4303, "naklon": 5 }, +{ "label": "15/12/2", "node": 4309, "naklon": 5 }, +{ "label": "15/13", "node": 2806, "naklon": 5 }, +{ "label": "15/14", "node": 2787, "naklon": 5 }, +{ "label": "15/15", "node": 2809, "naklon": 5 }, +{ "label": "15/16", "node": 2814, "naklon": 0 }, +{ "label": "15/17", "node": 3934, "naklon": 0 }, +{ "label": "15/18", "node": 3192, "naklon": 0 }, +{ "label": "15/19", "node": 2812, "naklon": 0 }, +{ "label": "15/20", "node": 4070, "naklon": 0 }, +{ "label": "15/21", "node": 2826, "naklon": 0 }, +{ "label": "15/22", "node": 2808, "naklon": 3 }, +{ "label": "15/23", "node": 2795, "naklon": 3 }, +{ "label": "15/24", "node": 2807, "naklon": 3 }, +{ "label": "15/25", "node": 2831, "naklon": 0 }, +{ "label": "15/26", "node": 2862, "naklon": null }, +{ "label": "15/27", "node": 2861, "naklon": 0 }, +{ "label": "15/28", "node": 2866, "naklon": 0 }, +{ "label": "15/28/1", "node": 3546, "naklon": 0 }, +{ "label": "15/29", "node": 4146, "naklon": 0 }, +{ "label": "15/29/1", "node": 3001, "naklon": 0 }, +{ "label": "15/30", "node": 2835, "naklon": 0 }, +{ "label": "15/31", "node": 2874, "naklon": 0 }, +{ "label": "15/32", "node": 2852, "naklon": 0 }, +{ "label": "15/33", "node": 2851, "naklon": 0 }, +{ "label": "15/33/1", "node": 3560, "naklon": 0 }, +{ "label": "15/34", "node": 2858, "naklon": 0 }, +{ "label": "15/34/1", "node": 4306, "naklon": 0 }, +{ "label": "15/35", "node": 2856, "naklon": 0 }, +{ "label": "15/36", "node": 2847, "naklon": 0 }, +{ "label": "15/36/1", "node": 3556, "naklon": 0 }, +{ "label": "15/37", "node": 3950, "naklon": 0 }, +{ "label": "15/38", "node": 2848, "naklon": 0 }, +{ "label": "15/39", "node": 2863, "naklon": 0 }, +{ "label": "15/39/1", "node": 4313, "naklon": 0 }, +{ "label": "15/40", "node": 2873, "naklon": 0 }, +{ "label": "15/40/1", "node": 2984, "naklon": 0 }, +{ "label": "15/41", "node": 2854, "naklon": 0 }, +{ "label": "15/42", "node": 2859, "naklon": 0 }, +{ "label": "15/43", "node": 2872, "naklon": 0 }, +{ "label": "15/44", "node": 2849, "naklon": 0 }, +{ "label": "15/45", "node": 2864, "naklon": 0 }, +{ "label": "15/46", "node": 3553, "naklon": null }, +{ "label": "15/47", "node": 3021, "naklon": null }, +{ "label": "15/47/1", "node": 3008, "naklon": null }, +{ "label": "15/48", "node": 3017, "naklon": null }, +{ "label": "15/49", "node": 3014, "naklon": null }, +{ "label": "15/50", "node": 2981, "naklon": null }, +{ "label": "15/51", "node": 3020, "naklon": null }, +{ "label": "15/52", "node": 3027, "naklon": null }, +{ "label": "15/53", "node": 3006, "naklon": null }, +{ "label": "15/54", "node": 3012, "naklon": null }, +{ "label": "15/55", "node": 2738, "naklon": 0 }, +{ "label": "15/56", "node": 2725, "naklon": 0 }, +{ "label": "15/57", "node": 3016, "naklon": null }, +{ "label": "15/58", "node": 3005, "naklon": null }, +{ "label": "15/58/1", "node": 3009, "naklon": null }, +{ "label": "15/59", "node": 3010, "naklon": 0 }, +{ "label": "15/59/1", "node": 3538, "naklon": 0 }, +{ "label": "15/59/2", "node": 4145, "naklon": 0 }, +{ "label": "15/60", "node": 2713, "naklon": 0 }, +{ "label": "15/61", "node": 2789, "naklon": 0 }, +{ "label": "15/62", "node": 2736, "naklon": 0 }, +{ "label": "15/63", "node": 2739, "naklon": 0 }, +{ "label": "15/64", "node": 4346, "naklon": 0 }, +{ "label": "15/65", "node": 2731, "naklon": 0 }, +{ "label": "15/66", "node": 2818, "naklon": 0 }, +{ "label": "15/66/1", "node": 3557, "naklon": 0 }, +{ "label": "15/67", "node": 2822, "naklon": 0 }, +{ "label": "15/68", "node": 2833, "naklon": 0 }, +{ "label": "15/69", "node": 2834, "naklon": 0 }, +{ "label": "15/70", "node": 3097, "naklon": 0 }, +{ "label": "15/71", "node": 2824, "naklon": 0 }, +{ "label": "15/72", "node": 2828, "naklon": 0 }, +{ "label": "15/73", "node": 2600, "naklon": 0 }, +{ "label": "15/73/1", "node": 4314, "naklon": 0 }, +{ "label": "15/74", "node": 2832, "naklon": 0 }, +{ "label": "15/75", "node": 4360, "naklon": 0 }, +{ "label": "15/76", "node": 2846, "naklon": 0 }, +{ "label": "15/77", "node": 2584, "naklon": 0 }, +{ "label": "15/78", "node": 2843, "naklon": 0 }, +{ "label": "15/78/1", "node": 4308, "naklon": 0 }, +{ "label": "15/79", "node": 4144, "naklon": null }, +{ "label": "15/80", "node": 2844, "naklon": 0 }, +{ "label": "15/81", "node": 2842, "naklon": 0 }, +{ "label": "15/82", "node": 2838, "naklon": 0 }, +{ "label": "15/83", "node": 2837, "naklon": null }, +{ "label": "15/83/1", "node": 3555, "naklon": null }, +{ "label": "15/84", "node": 2839, "naklon": 0 }, +{ "label": "15/85", "node": 2830, "naklon": 0 }, +{ "label": "15/86", "node": 4066, "naklon": 0 }, +{ "label": "15/87", "node": 2836, "naklon": 0 }, +{ "label": "15/88", "node": 2911, "naklon": 0 }, +{ "label": "15/89", "node": 2825, "naklon": 0 }, +{ "label": "15/90", "node": 2811, "naklon": 0 }, +{ "label": "15/94", "node": 3740, "naklon": 15 }, +{ "label": "15/95", "node": 2734, "naklon": 15 }, +{ "label": "15/96", "node": 3105, "naklon": 15 }, +{ "label": "15/97", "node": 2732, "naklon": 15 }, +{ "label": "15/98", "node": 2727, "naklon": 15 }, +{ "label": "15/99", "node": 2735, "naklon": 15 }, +{ "label": "15/100", "node": 3926, "naklon": 15 }, +{ "label": "15/101", "node": 2918, "naklon": 0 }, +{ "label": "15/102", "node": 2705, "naklon": 10 }, +{ "label": "15/103", "node": 2708, "naklon": 10 }, +{ "label": "15/104", "node": 2721, "naklon": 10 }, +{ "label": "15/105", "node": 2719, "naklon": 10 }, +{ "label": "15/106", "node": 2919, "naklon": 10 }, +{ "label": "15/107", "node": 3101, "naklon": 10 }, +{ "label": "15/108", "node": 2853, "naklon": 10 }, +{ "label": "15/109", "node": 2715, "naklon": 10 }, +{ "label": "15/110", "node": 2712, "naklon": 0 }, +{ "label": "15/111", "node": 2711, "naklon": 0 }, +{ "label": "15/112", "node": 2709, "naklon": 0 }, +{ "label": "15/113", "node": 2710, "naklon": 0 }, +{ "label": "15/114", "node": 2907, "naklon": 0 }, +{ "label": "15/115", "node": 2906, "naklon": 0 }, +{ "label": "15/116", "node": 2908, "naklon": 0 }, +{ "label": "15/117", "node": 2901, "naklon": 0 }, +{ "label": "15/118", "node": 2913, "naklon": 0 }, +{ "label": "15/119", "node": 3656, "naklon": 0 }, +{ "label": "15/120", "node": 2781, "naklon": 0 }, +{ "label": "15/121", "node": 2802, "naklon": 0 }, +{ "label": "15/122", "node": 2791, "naklon": 0 }, +{ "label": "15/123", "node": 2783, "naklon": 0 }, +{ "label": "15/124", "node": 2794, "naklon": 0 }, +{ "label": "15/125", "node": 3139, "naklon": 0 }, +{ "label": "15/126", "node": 3229, "naklon": 5 }, +{ "label": "15/127", "node": 3239, "naklon": 5 }, +{ "label": "15/128", "node": 3230, "naklon": 5 }, +{ "label": "15/129", "node": 4016, "naklon": null }, +{ "label": "16/16A", "node": 3608, "naklon": 0 }, +{ "label": "16/16B", "node": 4151, "naklon": 0 }, +{ "label": "16/1", "node": 3710, "naklon": 0 }, +{ "label": "16/2", "node": 3726, "naklon": 0 }, +{ "label": "16/3", "node": 3743, "naklon": 0 }, +{ "label": "16/4", "node": 3724, "naklon": 0 }, +{ "label": "16/5", "node": 3712, "naklon": 0 }, +{ "label": "16/6", "node": 3739, "naklon": 0 }, +{ "label": "16/7", "node": 3742, "naklon": 0 }, +{ "label": "16/8", "node": 3731, "naklon": 0 }, +{ "label": "16/9", "node": 3727, "naklon": 0 }, +{ "label": "16/10", "node": 3729, "naklon": 0 }, +{ "label": "16/11", "node": 3736, "naklon": 0 }, +{ "label": "16/12", "node": 3713, "naklon": 0 }, +{ "label": "16/13", "node": 3715, "naklon": 0 }, +{ "label": "16/14", "node": 3733, "naklon": 0 }, +{ "label": "16/15", "node": 3732, "naklon": 0 }, +{ "label": "16/17", "node": 3634, "naklon": 0 }, +{ "label": "16/18", "node": 3610, "naklon": 0 }, +{ "label": "16/19", "node": 3626, "naklon": 0 }, +{ "label": "16/20", "node": 3618, "naklon": 0 }, +{ "label": "16/21", "node": 3619, "naklon": 0 }, +{ "label": "16/22", "node": 3628, "naklon": 0 }, +{ "label": "16/23", "node": 3615, "naklon": 0 }, +{ "label": "16/24", "node": 3609, "naklon": 0 }, +{ "label": "16/25", "node": 3606, "naklon": 0 }, +{ "label": "16/26", "node": 3624, "naklon": 0 }, +{ "label": "16/27", "node": 3627, "naklon": 0 }, +{ "label": "16/28", "node": 3607, "naklon": 0 }, +{ "label": "16/29", "node": 4370, "naklon": 0 }, +{ "label": "16/30", "node": 3692, "naklon": 0 }, +{ "label": "16/31", "node": 3614, "naklon": 0 }, +{ "label": "16/32", "node": 3623, "naklon": 0 }, +{ "label": "16/33", "node": 4373, "naklon": 0 }, +{ "label": "16/34", "node": 3620, "naklon": 0 }, +{ "label": "16/35", "node": 3685, "naklon": 0 }, +{ "label": "16/36", "node": 3616, "naklon": 0 }, +{ "label": "16/37", "node": 3686, "naklon": 0 }, +{ "label": "16/38", "node": 3688, "naklon": 0 }, +{ "label": "16/39", "node": 3684, "naklon": 0 }, +{ "label": "16/40", "node": 3825, "naklon": 0 }, +{ "label": "16/41", "node": 3865, "naklon": 0 }, +{ "label": "16/42", "node": 3824, "naklon": 0 }, +{ "label": "16/43", "node": 3871, "naklon": 0 }, +{ "label": "16/44", "node": 3801, "naklon": 0 }, +{ "label": "16/45", "node": 3862, "naklon": 0 }, +{ "label": "16/46", "node": 3876, "naklon": 0 }, +{ "label": "16/47", "node": 3861, "naklon": 0 }, +{ "label": "16/48", "node": 4215, "naklon": 0 }, +{ "label": "16/49", "node": 3605, "naklon": 10 }, +{ "label": "16/50", "node": 3603, "naklon": 10 }, +{ "label": "16/51", "node": 3592, "naklon": 10 }, +{ "label": "16/52", "node": 3598, "naklon": 10 }, +{ "label": "16/53", "node": 3594, "naklon": 10 }, +{ "label": "16/54", "node": 3593, "naklon": 10 }, +{ "label": "16/55", "node": 3630, "naklon": 10 }, +{ "label": "16/56", "node": 3763, "naklon": 10 }, +{ "label": "16/57", "node": 3746, "naklon": 10 }, +{ "label": "16/58", "node": 3699, "naklon": 0 }, +{ "label": "16/59", "node": 3698, "naklon": 0 }, +{ "label": "16/60", "node": 3709, "naklon": null }, +{ "label": "16/61", "node": 3708, "naklon": 0 }, +{ "label": "16/62", "node": 3703, "naklon": null }, +{ "label": "16/63", "node": 3700, "naklon": 0 }, +{ "label": "16/64", "node": 3701, "naklon": null }, +{ "label": "16/65", "node": 3704, "naklon": 0 }, +{ "label": "16/66", "node": 3707, "naklon": null }, +{ "label": "16/67", "node": 3810, "naklon": 0 }, +{ "label": "16/68", "node": 4208, "naklon": null }, +{ "label": "16/69", "node": 3867, "naklon": 0 }, +{ "label": "16/70", "node": 4372, "naklon": null }, +{ "label": "16/71", "node": 3881, "naklon": 0 }, +{ "label": "16/72", "node": 4204, "naklon": null }, +{ "label": "16/73", "node": 3869, "naklon": 0 }, +{ "label": "16/74", "node": 4202, "naklon": null }, +{ "label": "16/75", "node": 3830, "naklon": 0 }, +{ "label": "16/76", "node": 3870, "naklon": null }, +{ "label": "16/77", "node": 3964, "naklon": 0 }, +{ "label": "16/78", "node": 3849, "naklon": 0 }, +{ "label": "16/79", "node": 3694, "naklon": null }, +{ "label": "16/80", "node": 3717, "naklon": 0 }, +{ "label": "16/81", "node": 3877, "naklon": null }, +{ "label": "16/82", "node": 3755, "naklon": 0 }, +{ "label": "16/83", "node": 3725, "naklon": null }, +{ "label": "16/84", "node": 3716, "naklon": 0 }, +{ "label": "16/85", "node": 3696, "naklon": null }, +{ "label": "16/86", "node": 3702, "naklon": 0 }, +{ "label": "16/87", "node": 3706, "naklon": null }, +{ "label": "16/88", "node": 3850, "naklon": 0 }, +{ "label": "16/89", "node": 3848, "naklon": null }, +{ "label": "16/90", "node": 3737, "naklon": null }, +{ "label": "16/91", "node": 3705, "naklon": 0 }, +{ "label": "16/92", "node": 3723, "naklon": null }, +{ "label": "16/93", "node": 3842, "naklon": 0 }, +{ "label": "16/94", "node": 3735, "naklon": null }, +{ "label": "16/95", "node": 3719, "naklon": 0 }, +{ "label": "16/96", "node": 3697, "naklon": 0 }, +{ "label": "16/97", "node": 3711, "naklon": 0 }, +{ "label": "16/98", "node": 4107, "naklon": null }, +{ "label": "16/99", "node": 4112, "naklon": 5 }, +{ "label": "16/100", "node": 4106, "naklon": 5 }, +{ "label": "16/101", "node": 4111, "naklon": 5 }, +{ "label": "16/102", "node": 4091, "naklon": null }, +{ "label": "16/103", "node": 4104, "naklon": 5 }, +{ "label": "16/104", "node": 4094, "naklon": null }, +{ "label": "16/105", "node": 4089, "naklon": 5 }, +{ "label": "16/106", "node": 4095, "naklon": null }, +{ "label": "16/107", "node": 4102, "naklon": 5 }, +{ "label": "16/108", "node": 4105, "naklon": null }, +{ "label": "16/109", "node": 3859, "naklon": null }, +{ "label": "16/110", "node": 4090, "naklon": 5 }, +{ "label": "16/111", "node": 4110, "naklon": null }, +{ "label": "16/112", "node": 4097, "naklon": 5 }, +{ "label": "16/113", "node": 4099, "naklon": null }, +{ "label": "16/114", "node": 4096, "naklon": null }, +{ "label": "16/115", "node": 4101, "naklon": 5 }, +{ "label": "16/116", "node": 4109, "naklon": null }, +{ "label": "16/117", "node": 4092, "naklon": 5 }, +{ "label": "16/118", "node": 3631, "naklon": null }, +{ "label": "16/119", "node": 3632, "naklon": 0 }, +{ "label": "16/120", "node": 3641, "naklon": null }, +{ "label": "16/121", "node": 3638, "naklon": 0 }, +{ "label": "16/122", "node": 3637, "naklon": null }, +{ "label": "16/123", "node": 4142, "naklon": null }, +{ "label": "16/124", "node": 4147, "naklon": 5 }, +{ "label": "16/125", "node": 4139, "naklon": 5 }, +{ "label": "20/30A", "node": 3172, "naklon": 2 }, +{ "label": "20/30B", "node": 3164, "naklon": 2 }, +{ "label": "20/1", "node": 3247, "naklon": 10 }, +{ "label": "20/2", "node": 3296, "naklon": 10 }, +{ "label": "20/3", "node": 3246, "naklon": 10 }, +{ "label": "20/4", "node": 3270, "naklon": 10 }, +{ "label": "20/5", "node": 3294, "naklon": 10 }, +{ "label": "20/6", "node": 3298, "naklon": 10 }, +{ "label": "20/7", "node": 3297, "naklon": 10 }, +{ "label": "20/8", "node": 3293, "naklon": 10 }, +{ "label": "20/9", "node": 3299, "naklon": 10 }, +{ "label": "20/10", "node": 3295, "naklon": 10 }, +{ "label": "20/11", "node": 3244, "naklon": 10 }, +{ "label": "20/12", "node": 3249, "naklon": 10 }, +{ "label": "20/13", "node": 3268, "naklon": 10 }, +{ "label": "20/14", "node": 3245, "naklon": 10 }, +{ "label": "20/15", "node": 3278, "naklon": 10 }, +{ "label": "20/16", "node": 3280, "naklon": 10 }, +{ "label": "20/17", "node": 3292, "naklon": 10 }, +{ "label": "20/18", "node": 3287, "naklon": 10 }, +{ "label": "20/19", "node": 3282, "naklon": 10 }, +{ "label": "20/20", "node": 3273, "naklon": 0 }, +{ "label": "20/21", "node": 3157, "naklon": 0 }, +{ "label": "20/22", "node": 3283, "naklon": 0 }, +{ "label": "20/23", "node": 3159, "naklon": 0 }, +{ "label": "20/24", "node": 3289, "naklon": 0 }, +{ "label": "20/25", "node": 3163, "naklon": 0 }, +{ "label": "20/26", "node": 3126, "naklon": 0 }, +{ "label": "20/27", "node": 3171, "naklon": 0 }, +{ "label": "20/28", "node": 3162, "naklon": 0 }, +{ "label": "20/29", "node": 3279, "naklon": 10 }, +{ "label": "20/31", "node": 3173, "naklon": 0 }, +{ "label": "20/32", "node": 3127, "naklon": 0 }, +{ "label": "20/33", "node": 3131, "naklon": 0 }, +{ "label": "20/34", "node": 3129, "naklon": 0 }, +{ "label": "20/35", "node": 3276, "naklon": 2 }, +{ "label": "20/36", "node": 3290, "naklon": 2 }, +{ "label": "20/37", "node": 3132, "naklon": 0 }, +{ "label": "20/38", "node": 3138, "naklon": 0 }, +{ "label": "20/39", "node": 3272, "naklon": 0 }, +{ "label": "20/40", "node": 3291, "naklon": 0 }, +{ "label": "20/41", "node": 3277, "naklon": 10 }, +{ "label": "20/42", "node": 3286, "naklon": 10 }, +{ "label": "20/43", "node": 3281, "naklon": 10 }, +{ "label": "20/44", "node": 3288, "naklon": 10 }, +{ "label": "20/45", "node": 3284, "naklon": 10 }, +{ "label": "20/46", "node": 3167, "naklon": 10 }, +{ "label": "20/47", "node": 3872, "naklon": 0 }, +{ "label": "20/48", "node": 3124, "naklon": 0 }, +{ "label": "20/49", "node": 3133, "naklon": 0 }, +{ "label": "20/50", "node": 3158, "naklon": 0 }, +{ "label": "20/51", "node": 3169, "naklon": 0 }, +{ "label": "20/52", "node": 3146, "naklon": 0 }, +{ "label": "20/53", "node": 3160, "naklon": 0 }, +{ "label": "20/54", "node": 3248, "naklon": 0 }, +{ "label": "20/55", "node": 3156, "naklon": 0 }, +{ "label": "20/56", "node": 3161, "naklon": 0 }, +{ "label": "20/57", "node": 3170, "naklon": 0 }, +{ "label": "20/58", "node": 3168, "naklon": 0 }, +{ "label": "20/59", "node": 3125, "naklon": 0 }, +{ "label": "20/60", "node": 3166, "naklon": 0 }, +{ "label": "20/61", "node": 3130, "naklon": 0 }, +{ "label": "20/62", "node": 3563, "naklon": 0 }, +{ "label": "20/63", "node": 3550, "naklon": null }, +{ "label": "20/67", "node": 3269, "naklon": 0 }, +{ "label": "21/1", "node": 2921, "naklon": 0 }, +{ "label": "21/2", "node": 2707, "naklon": 0 }, +{ "label": "21/3", "node": 2723, "naklon": 0 }, +{ "label": "21/4", "node": 2716, "naklon": 0 }, +{ "label": "21/5", "node": 2717, "naklon": 0 }, +{ "label": "21/6", "node": 2720, "naklon": 0 }, +{ "label": "21/7", "node": 2722, "naklon": 0 }, +{ "label": "21/8", "node": 2718, "naklon": 0 }, +{ "label": "21/9", "node": 2724, "naklon": 0 }, +{ "label": "21/10", "node": 2742, "naklon": 0 }, +{ "label": "21/11", "node": 2743, "naklon": 0 }, +{ "label": "21/12", "node": 2733, "naklon": 0 }, +{ "label": "21/14", "node": 2903, "naklon": 0 }, +{ "label": "21/15", "node": 2917, "naklon": 0 }, +{ "label": "21/16", "node": 2897, "naklon": 0 }, +{ "label": "21/17", "node": 2914, "naklon": 0 }, +{ "label": "21/18", "node": 2898, "naklon": 0 }, +{ "label": "21/19", "node": 2773, "naklon": 0 }, +{ "label": "21/20", "node": 2895, "naklon": 0 }, +{ "label": "21/21", "node": 2896, "naklon": 0 }, +{ "label": "21/22", "node": 2771, "naklon": 0 }, +{ "label": "21/23", "node": 2772, "naklon": 0 }, +{ "label": "21/24", "node": 2793, "naklon": 0 }, +{ "label": "21/25", "node": 2902, "naklon": 0 }, +{ "label": "21/26", "node": 2910, "naklon": 0 }, +{ "label": "21/27", "node": 2909, "naklon": 0 }, +{ "label": "21/28", "node": 2920, "naklon": 0 }, +{ "label": "21/29", "node": 2916, "naklon": 0 }, +{ "label": "21/30", "node": 2904, "naklon": 0 }, +{ "label": "21/31", "node": 2915, "naklon": 0 }, +{ "label": "21/32", "node": 2905, "naklon": 0 }, +{ "label": "21/33", "node": 2900, "naklon": 0 }, +{ "label": "21/34", "node": 2899, "naklon": 0 }, +{ "label": "21/36", "node": 2741, "naklon": 0 }, +{ "label": "21/37", "node": 2714, "naklon": 0 }, +{ "label": "21/38", "node": 2701, "naklon": 0 }, +{ "label": "21/39", "node": 2703, "naklon": 0 }, +{ "label": "21/40", "node": 2704, "naklon": 0 }, +{ "label": "21/41", "node": 2702, "naklon": 0 }, +{ "label": "21/42", "node": 2706, "naklon": 0 }, +{ "label": "21/43", "node": 2776, "naklon": 0 }, +{ "label": "21/44", "node": 2770, "naklon": 0 }, +{ "label": "21/45", "node": 2786, "naklon": 0 }, +{ "label": "21/46", "node": 2779, "naklon": 0 }, +{ "label": "21/47", "node": 2782, "naklon": 0 }, +{ "label": "21/48", "node": 2785, "naklon": 0 }, +{ "label": "21/49", "node": 2769, "naklon": 0 }, +{ "label": "21/50", "node": 3354, "naklon": 0 }, +{ "label": "21/51", "node": 2778, "naklon": 0 }, +{ "label": "21/52", "node": 2775, "naklon": 0 }, +{ "label": "21/53", "node": 2780, "naklon": 0 }, +{ "label": "21/54", "node": 2790, "naklon": 0 }, +{ "label": "21/55", "node": 2792, "naklon": 0 }, +{ "label": "21/56", "node": 2774, "naklon": 0 }, +{ "label": "22/1", "node": 2630, "naklon": 0 }, +{ "label": "22/2", "node": 2631, "naklon": 0 }, +{ "label": "22/3", "node": 2632, "naklon": 0 }, +{ "label": "22/4", "node": 2633, "naklon": 0 }, +{ "label": "22/5", "node": 2634, "naklon": 0 }, +{ "label": "22/6", "node": 2636, "naklon": 0 }, +{ "label": "22/7", "node": 4367, "naklon": 0 }, +{ "label": "22/8", "node": 2637, "naklon": 0 }, +{ "label": "22/9", "node": 2638, "naklon": 0 }, +{ "label": "22/10", "node": 2639, "naklon": 0 }, +{ "label": "22/11", "node": 2640, "naklon": 0 }, +{ "label": "22/12", "node": 2641, "naklon": 0 }, +{ "label": "22/13", "node": 2642, "naklon": 0 }, +{ "label": "22/14", "node": 2643, "naklon": 0 }, +{ "label": "22/15", "node": 2644, "naklon": 0 }, +{ "label": "22/16", "node": 2645, "naklon": 0 }, +{ "label": "22/17", "node": 2646, "naklon": 0 }, +{ "label": "22/18", "node": 2647, "naklon": 0 }, +{ "label": "22/19", "node": 2648, "naklon": 0 }, +{ "label": "22/20", "node": 2649, "naklon": 0 }, +{ "label": "22/21", "node": 2650, "naklon": 0 }, +{ "label": "22/22", "node": 2651, "naklon": 0 }, +{ "label": "22/23", "node": 4103, "naklon": 0 }, +{ "label": "22/24", "node": 2653, "naklon": 0 }, +{ "label": "22/25", "node": 2654, "naklon": 0 }, +{ "label": "22/26", "node": 2655, "naklon": 0 }, +{ "label": "22/27", "node": 2656, "naklon": 0 }, +{ "label": "22/28", "node": 2657, "naklon": 0 }, +{ "label": "22/29", "node": 2658, "naklon": 0 }, +{ "label": "22/30", "node": 2659, "naklon": 0 }, +{ "label": "22/31", "node": 2660, "naklon": 0 }, +{ "label": "22/32", "node": 2661, "naklon": 0 }, +{ "label": "22/32/1", "node": 3015, "naklon": 0 }, +{ "label": "22/33", "node": 2662, "naklon": 0 }, +{ "label": "22/34", "node": 2663, "naklon": 0 }, +{ "label": "22/35", "node": 2664, "naklon": 0 }, +{ "label": "22/36", "node": 2665, "naklon": 0 }, +{ "label": "22/37", "node": 2666, "naklon": 0 }, +{ "label": "22/38", "node": 2667, "naklon": 0 }, +{ "label": "22/39", "node": 2668, "naklon": 0 }, +{ "label": "22/40", "node": 2669, "naklon": null }, +{ "label": "22/41", "node": 2670, "naklon": null }, +{ "label": "22/42", "node": 2671, "naklon": null }, +{ "label": "23/9A", "node": 3087, "naklon": 10 }, +{ "label": "23/9B", "node": 3090, "naklon": 10 }, +{ "label": "23/1", "node": 3075, "naklon": 0 }, +{ "label": "23/2", "node": 3089, "naklon": 0 }, +{ "label": "23/3", "node": 3088, "naklon": 0 }, +{ "label": "23/4", "node": 3228, "naklon": 10 }, +{ "label": "23/5", "node": 2751, "naklon": 10 }, +{ "label": "23/6", "node": 3243, "naklon": 10 }, +{ "label": "23/7", "node": 4349, "naklon": 10 }, +{ "label": "23/8", "node": 3102, "naklon": 10 }, +{ "label": "23/10", "node": 3099, "naklon": 10 }, +{ "label": "23/11", "node": 3103, "naklon": 10 }, +{ "label": "23/12", "node": 3093, "naklon": 10 }, +{ "label": "23/13", "node": 3098, "naklon": 10 }, +{ "label": "23/14", "node": 3092, "naklon": 10 }, +{ "label": "23/15", "node": 3233, "naklon": 0 }, +{ "label": "23/16", "node": 3095, "naklon": 0 }, +{ "label": "23/17", "node": 4074, "naklon": 0 }, +{ "label": "23/18", "node": 2729, "naklon": 0 }, +{ "label": "23/19", "node": 3234, "naklon": 0 }, +{ "label": "23/20", "node": 3094, "naklon": 0 }, +{ "label": "23/21", "node": 2817, "naklon": 0 }, +{ "label": "23/22", "node": 3226, "naklon": 0 }, +{ "label": "23/23", "node": 3225, "naklon": 0 }, +{ "label": "23/24", "node": 3237, "naklon": 0 }, +{ "label": "23/25", "node": 4250, "naklon": 0 }, +{ "label": "23/26", "node": 3059, "naklon": 10 }, +{ "label": "23/27", "node": 3238, "naklon": 10 }, +{ "label": "23/28", "node": 3242, "naklon": 10 }, +{ "label": "23/29", "node": 3236, "naklon": 10 }, +{ "label": "23/30", "node": 3112, "naklon": 10 }, +{ "label": "23/31", "node": 3224, "naklon": 0 }, +{ "label": "23/32", "node": 4298, "naklon": 10 }, +{ "label": "23/33", "node": 4150, "naklon": 10 }, +{ "label": "23/34", "node": 3091, "naklon": 10 }, +{ "label": "25/1", "node": 3771, "naklon": 5 }, +{ "label": "25/2", "node": 3777, "naklon": 5 }, +{ "label": "25/3", "node": 3749, "naklon": 5 }, +{ "label": "25/4", "node": 3769, "naklon": 5 }, +{ "label": "25/5", "node": 3765, "naklon": 5 }, +{ "label": "25/6", "node": 3785, "naklon": 5 }, +{ "label": "25/7", "node": 3761, "naklon": 5 }, +{ "label": "25/8", "node": 3758, "naklon": 5 }, +{ "label": "25/9", "node": 3766, "naklon": 5 }, +{ "label": "25/10", "node": 3779, "naklon": 5 }, +{ "label": "25/11", "node": 3899, "naklon": 10 }, +{ "label": "25/12", "node": 3922, "naklon": 10 }, +{ "label": "25/13", "node": 3912, "naklon": 10 }, +{ "label": "25/14", "node": 3933, "naklon": 10 }, +{ "label": "25/15", "node": 3921, "naklon": 10 }, +{ "label": "25/16", "node": 4300, "naklon": 10 }, +{ "label": "25/17", "node": 3927, "naklon": 10 }, +{ "label": "25/18", "node": 3212, "naklon": 10 }, +{ "label": "25/19", "node": 3208, "naklon": 10 }, +{ "label": "25/20", "node": 3207, "naklon": 10 }, +{ "label": "25/21", "node": 4294, "naklon": 10 }, +{ "label": "25/22", "node": 3209, "naklon": 10 }, +{ "label": "25/23", "node": 3745, "naklon": 10 }, +{ "label": "25/24", "node": 3762, "naklon": 10 }, +{ "label": "25/25", "node": 3215, "naklon": 10 }, +{ "label": "25/26", "node": 3210, "naklon": 10 }, +{ "label": "25/27", "node": 3211, "naklon": 10 }, +{ "label": "25/28", "node": 3206, "naklon": 10 }, +{ "label": "25/29", "node": 3918, "naklon": 5 }, +{ "label": "25/30", "node": 3928, "naklon": 5 }, +{ "label": "25/31", "node": 3917, "naklon": 5 }, +{ "label": "25/32", "node": 4029, "naklon": 0 }, +{ "label": "25/33", "node": 4038, "naklon": 0 }, +{ "label": "25/34", "node": 4022, "naklon": 0 }, +{ "label": "25/35", "node": 3937, "naklon": 0 }, +{ "label": "25/36", "node": 3190, "naklon": 0 }, +{ "label": "25/37", "node": 3835, "naklon": 0 }, +{ "label": "25/38", "node": 3201, "naklon": 0 }, +{ "label": "25/39", "node": 3193, "naklon": 0 }, +{ "label": "25/40", "node": 3191, "naklon": 0 }, +{ "label": "25/41", "node": 3203, "naklon": 0 }, +{ "label": "25/42", "node": 4301, "naklon": 0 }, +{ "label": "25/43", "node": 3223, "naklon": 0 }, +{ "label": "25/44", "node": 3202, "naklon": 0 }, +{ "label": "25/45", "node": 3205, "naklon": 0 }, +{ "label": "25/46", "node": 3194, "naklon": 0 }, +{ "label": "25/47", "node": 3198, "naklon": 0 }, +{ "label": "25/48", "node": 3204, "naklon": 0 }, +{ "label": "25/49", "node": 3200, "naklon": 0 }, +{ "label": "25/50", "node": 3216, "naklon": 0 }, +{ "label": "25/51", "node": 3932, "naklon": 5 }, +{ "label": "25/52", "node": 3923, "naklon": 5 }, +{ "label": "25/53", "node": 3913, "naklon": 5 }, +{ "label": "25/54", "node": 3900, "naklon": 5 }, +{ "label": "25/55", "node": 4189, "naklon": 10 }, +{ "label": "25/56", "node": 4191, "naklon": 10 }, +{ "label": "25/57", "node": 3790, "naklon": 10 }, +{ "label": "25/58", "node": 4190, "naklon": 10 }, +{ "label": "25/59", "node": 4302, "naklon": 0 }, +{ "label": "25/60", "node": 4351, "naklon": 0 }, +{ "label": "25/61", "node": 4075, "naklon": 0 }, +{ "label": "25/62", "node": 4071, "naklon": 0 }, +{ "label": "25/63", "node": 3784, "naklon": 0 }, +{ "label": "25/64", "node": 4065, "naklon": 0 }, +{ "label": "25/65", "node": 4297, "naklon": 0 }, +{ "label": "25/66", "node": 4295, "naklon": 0 }, +{ "label": "25/67", "node": 4299, "naklon": 0 }, +{ "label": "25/68", "node": 3772, "naklon": 0 }, +{ "label": "25/69", "node": 3941, "naklon": 0 }, +{ "label": "25/70", "node": 3782, "naklon": 0 }, +{ "label": "25/71", "node": 4068, "naklon": 0 }, +{ "label": "25/72", "node": 4073, "naklon": 0 }, +{ "label": "25/73", "node": 3901, "naklon": 5 }, +{ "label": "25/74", "node": 4296, "naklon": 5 }, +{ "label": "25/75", "node": 3910, "naklon": 5 }, +{ "label": "25/76", "node": 4293, "naklon": 5 }, +{ "label": "25/77", "node": 3919, "naklon": 5 }, +{ "label": "25/78", "node": 3924, "naklon": 5 }, +{ "label": "25/79", "node": 3909, "naklon": 5 }, +{ "label": "25/80", "node": 3896, "naklon": 5 }, +{ "label": "25/81", "node": 3911, "naklon": 5 }, +{ "label": "25/82", "node": 2819, "naklon": 15 }, +{ "label": "25/83", "node": 3776, "naklon": 15 }, +{ "label": "25/84", "node": 3752, "naklon": 15 }, +{ "label": "25/85", "node": 4353, "naklon": 15 }, +{ "label": "25/86", "node": 3791, "naklon": 0 }, +{ "label": "25/87", "node": 3770, "naklon": 0 }, +{ "label": "25/88", "node": 3760, "naklon": 0 }, +{ "label": "25/89", "node": 3115, "naklon": 0 }, +{ "label": "25/90", "node": 3738, "naklon": 0 }, +{ "label": "25/91", "node": 3748, "naklon": 0 }, +{ "label": "25/92", "node": 3753, "naklon": 0 }, +{ "label": "25/93", "node": 3775, "naklon": 0 }, +{ "label": "25/94", "node": 3778, "naklon": 5 }, +{ "label": "25/95", "node": 4078, "naklon": 5 }, +{ "label": "25/96", "node": 4088, "naklon": 5 }, +{ "label": "25/97", "node": 3856, "naklon": 5 }, +{ "label": "25/98", "node": 4084, "naklon": 5 }, +{ "label": "25/99", "node": 4069, "naklon": 5 }, +{ "label": "25/100", "node": 4188, "naklon": 5 }, +{ "label": "25/101", "node": 4064, "naklon": 5 }, +{ "label": "25/102", "node": 3792, "naklon": 5 }, +{ "label": "25/103", "node": 3780, "naklon": 5 }, +{ "label": "25/104", "node": 4034, "naklon": 5 }, +{ "label": "25/105", "node": 4072, "naklon": 5 }, +{ "label": "25/106", "node": 3884, "naklon": 5 }, +{ "label": "25/107", "node": 3793, "naklon": 5 }, +{ "label": "25/108", "node": 3863, "naklon": 5 }, +{ "label": "25/109", "node": 3855, "naklon": 5 }, +{ "label": "33/1", "node": 3846, "naklon": 0 }, +{ "label": "33/2", "node": 3943, "naklon": 0 }, +{ "label": "33/3", "node": 3903, "naklon": 0 }, +{ "label": "33/4", "node": 3982, "naklon": 0 }, +{ "label": "33/5", "node": 3879, "naklon": 0 }, +{ "label": "33/6", "node": 3887, "naklon": 0 }, +{ "label": "33/7", "node": 3920, "naklon": 5 }, +{ "label": "33/8", "node": 3942, "naklon": 5 }, +{ "label": "33/9", "node": 3829, "naklon": null }, +{ "label": "34/79A", "node": 3452, "naklon": 6 }, +{ "label": "34/79B", "node": 3460, "naklon": 6 }, +{ "label": "34/90A", "node": 3443, "naklon": 6 }, +{ "label": "34/90B", "node": 3445, "naklon": 6 }, +{ "label": "34/90C", "node": 3457, "naklon": 6 }, +{ "label": "34/97A", "node": 3461, "naklon": 6 }, +{ "label": "34/97B", "node": 3463, "naklon": 6 }, +{ "label": "34/98A", "node": 3426, "naklon": 6 }, +{ "label": "34/98B", "node": 3444, "naklon": 6 }, +{ "label": "34/99A", "node": 3453, "naklon": 6 }, +{ "label": "34/99B", "node": 3455, "naklon": 6 }, +{ "label": "34/1", "node": 4009, "naklon": 0 }, +{ "label": "34/2", "node": 3602, "naklon": 0 }, +{ "label": "34/3", "node": 3441, "naklon": 0 }, +{ "label": "34/4", "node": 3464, "naklon": 0 }, +{ "label": "34/5", "node": 3883, "naklon": 0 }, +{ "label": "34/6", "node": 4098, "naklon": 0 }, +{ "label": "34/7", "node": 4003, "naklon": 0 }, +{ "label": "34/8", "node": 4004, "naklon": 0 }, +{ "label": "34/9", "node": 3888, "naklon": 0 }, +{ "label": "34/10", "node": 3997, "naklon": 0 }, +{ "label": "34/11", "node": 4006, "naklon": 0 }, +{ "label": "34/12", "node": 4000, "naklon": 0 }, +{ "label": "34/13", "node": 4011, "naklon": 0 }, +{ "label": "34/14", "node": 3999, "naklon": 0 }, +{ "label": "34/15", "node": 3981, "naklon": 0 }, +{ "label": "34/16", "node": 3988, "naklon": 0 }, +{ "label": "34/17", "node": 3986, "naklon": 0 }, +{ "label": "34/18", "node": 3998, "naklon": 0 }, +{ "label": "34/19", "node": 3983, "naklon": 0 }, +{ "label": "34/20", "node": 4005, "naklon": 0 }, +{ "label": "34/21", "node": 4001, "naklon": 0 }, +{ "label": "34/22", "node": 4008, "naklon": 0 }, +{ "label": "34/23", "node": 4002, "naklon": 0 }, +{ "label": "34/24", "node": 3996, "naklon": 0 }, +{ "label": "34/25", "node": 4007, "naklon": 0 }, +{ "label": "34/26", "node": 4113, "naklon": 15 }, +{ "label": "34/27", "node": 3595, "naklon": 5 }, +{ "label": "34/28", "node": 3599, "naklon": 5 }, +{ "label": "34/29", "node": 3601, "naklon": 5 }, +{ "label": "34/30", "node": 4205, "naklon": 0 }, +{ "label": "34/31", "node": 3987, "naklon": null }, +{ "label": "34/32", "node": 4214, "naklon": 0 }, +{ "label": "34/33", "node": 4226, "naklon": 0 }, +{ "label": "34/34", "node": 4209, "naklon": 0 }, +{ "label": "34/35", "node": 4201, "naklon": 0 }, +{ "label": "34/36", "node": 3440, "naklon": 0 }, +{ "label": "34/37", "node": 3465, "naklon": 0 }, +{ "label": "34/38", "node": 3446, "naklon": 0 }, +{ "label": "34/39", "node": 4039, "naklon": 5 }, +{ "label": "34/40", "node": 4057, "naklon": 5 }, +{ "label": "34/41", "node": 3985, "naklon": 0 }, +{ "label": "34/42", "node": 3882, "naklon": 0 }, +{ "label": "34/43", "node": 4040, "naklon": 5 }, +{ "label": "34/44", "node": 3231, "naklon": 0 }, +{ "label": "34/45", "node": 3227, "naklon": 0 }, +{ "label": "34/46", "node": 3431, "naklon": 0 }, +{ "label": "34/47", "node": 4013, "naklon": 0 }, +{ "label": "34/48", "node": 4045, "naklon": 0 }, +{ "label": "34/49", "node": 3949, "naklon": 0 }, +{ "label": "34/50", "node": 3953, "naklon": 0 }, +{ "label": "34/51", "node": 3952, "naklon": 0 }, +{ "label": "34/52", "node": 3995, "naklon": 0 }, +{ "label": "34/53", "node": 3992, "naklon": 0 }, +{ "label": "34/54", "node": 4198, "naklon": 0 }, +{ "label": "34/55", "node": 3935, "naklon": 0 }, +{ "label": "34/56", "node": 4050, "naklon": 0 }, +{ "label": "34/57", "node": 4049, "naklon": 0 }, +{ "label": "34/58", "node": 4054, "naklon": 0 }, +{ "label": "34/59", "node": 3663, "naklon": 6 }, +{ "label": "34/60", "node": 3661, "naklon": 6 }, +{ "label": "34/61", "node": 3664, "naklon": 6 }, +{ "label": "34/62", "node": 3660, "naklon": 6 }, +{ "label": "34/63", "node": 3662, "naklon": 6 }, +{ "label": "34/65", "node": 3665, "naklon": 6 }, +{ "label": "34/66", "node": 3667, "naklon": 6 }, +{ "label": "34/67", "node": 3675, "naklon": 6 }, +{ "label": "34/68", "node": 3666, "naklon": 6 }, +{ "label": "34/69", "node": 3652, "naklon": 6 }, +{ "label": "34/70", "node": 3458, "naklon": 6 }, +{ "label": "34/70/1", "node": 4425, "naklon": 6 }, +{ "label": "34/71", "node": 3459, "naklon": 6 }, +{ "label": "34/72", "node": 3435, "naklon": 6 }, +{ "label": "34/73", "node": 3448, "naklon": 6 }, +{ "label": "34/74", "node": 3451, "naklon": 6 }, +{ "label": "34/75", "node": 3442, "naklon": 6 }, +{ "label": "34/76", "node": 3449, "naklon": 6 }, +{ "label": "34/77", "node": 3450, "naklon": 6 }, +{ "label": "34/78", "node": 3433, "naklon": 6 }, +{ "label": "34/80", "node": 3432, "naklon": 12 }, +{ "label": "34/81", "node": 3470, "naklon": 12 }, +{ "label": "34/82", "node": 3438, "naklon": 12 }, +{ "label": "34/83", "node": 3439, "naklon": 12 }, +{ "label": "34/84", "node": 4028, "naklon": 5 }, +{ "label": "34/85", "node": 3596, "naklon": 5 }, +{ "label": "34/86", "node": 4021, "naklon": 5 }, +{ "label": "34/87", "node": 3437, "naklon": 12 }, +{ "label": "34/88", "node": 3428, "naklon": 12 }, +{ "label": "34/89", "node": 3430, "naklon": 12 }, +{ "label": "34/91", "node": 3454, "naklon": 6 }, +{ "label": "34/92", "node": 3492, "naklon": 6 }, +{ "label": "34/93", "node": 3462, "naklon": 6 }, +{ "label": "34/94", "node": 3427, "naklon": 6 }, +{ "label": "34/95", "node": 3434, "naklon": 6 }, +{ "label": "34/96", "node": 3456, "naklon": 6 }, +{ "label": "34/98/1", "node": 4307, "naklon": 6 }, +{ "label": "35/1", "node": 3968, "naklon": 0 }, +{ "label": "35/2", "node": 3969, "naklon": 0 }, +{ "label": "35/3", "node": 3947, "naklon": 0 }, +{ "label": "35/4", "node": 3979, "naklon": 0 }, +{ "label": "35/5", "node": 3959, "naklon": 0 }, +{ "label": "35/6", "node": 3948, "naklon": 0 }, +{ "label": "35/7", "node": 3961, "naklon": 0 }, +{ "label": "35/8", "node": 3956, "naklon": 0 }, +{ "label": "35/9", "node": 3604, "naklon": 0 }, +{ "label": "35/10", "node": 3944, "naklon": 0 }, +{ "label": "35/11", "node": 3960, "naklon": 0 }, +{ "label": "35/12", "node": 3958, "naklon": 0 }, +{ "label": "35/13", "node": 4036, "naklon": 5 }, +{ "label": "35/18", "node": 3893, "naklon": 5 }, +{ "label": "35/19", "node": 4108, "naklon": 5 }, +{ "label": "35/20", "node": 4017, "naklon": 5 }, +{ "label": "35/21", "node": 3963, "naklon": 0 }, +{ "label": "35/22", "node": 3658, "naklon": 0 }, +{ "label": "35/23", "node": 3975, "naklon": 0 }, +{ "label": "35/24", "node": 3980, "naklon": 0 }, +{ "label": "35/25", "node": 4012, "naklon": 0 }, +{ "label": "35/26", "node": 3655, "naklon": 0 }, +{ "label": "35/27", "node": 3962, "naklon": 0 }, +{ "label": "35/28", "node": 3945, "naklon": 0 }, +{ "label": "35/29", "node": 3569, "naklon": 0 }, +{ "label": "35/30", "node": 3429, "naklon": 0 }, +{ "label": "35/31", "node": 3657, "naklon": 0 }, +{ "label": "35/32", "node": 3646, "naklon": 0 }, +{ "label": "35/33", "node": 3622, "naklon": 0 }, +{ "label": "35/34", "node": 3612, "naklon": 0 }, +{ "label": "35/35", "node": 3955, "naklon": 0 }, +{ "label": "35/37", "node": 3878, "naklon": 0 }, +{ "label": "35/38", "node": 3965, "naklon": 0 }, +{ "label": "35/39", "node": 3970, "naklon": 0 }, +{ "label": "35/40", "node": 3611, "naklon": 0 }, +{ "label": "35/41", "node": 2635, "naklon": 0 }, +{ "label": "35/42", "node": 3978, "naklon": 0 }, +{ "label": "35/43", "node": 4213, "naklon": 0 }, +{ "label": "35/44", "node": 3984, "naklon": 0 }, +{ "label": "35/45", "node": 4218, "naklon": 0 }, +{ "label": "35/46", "node": 3973, "naklon": 0 }, +{ "label": "35/47", "node": 3974, "naklon": 0 }, +{ "label": "35/48", "node": 3759, "naklon": 0 }, +{ "label": "35/49", "node": 3844, "naklon": 0 }, +{ "label": "35/50", "node": 3804, "naklon": 0 }, +{ "label": "35/51", "node": 3831, "naklon": 0 }, +{ "label": "35/52", "node": 3643, "naklon": 0 }, +{ "label": "35/53", "node": 3966, "naklon": 0 }, +{ "label": "35/54", "node": 3971, "naklon": 0 }, +{ "label": "35/55", "node": 3650, "naklon": 6 }, +{ "label": "35/56", "node": 3651, "naklon": 6 }, +{ "label": "35/57", "node": 3669, "naklon": 6 }, +{ "label": "35/58", "node": 3648, "naklon": 6 }, +{ "label": "35/59", "node": 3645, "naklon": 6 }, +{ "label": "35/60", "node": 3659, "naklon": 6 }, +{ "label": "35/61", "node": 3647, "naklon": 6 }, +{ "label": "35/62", "node": 3644, "naklon": 6 }, +{ "label": "35/63", "node": 3671, "naklon": 6 }, +{ "label": "35/64", "node": 3682, "naklon": 6 }, +{ "label": "35/65", "node": 3672, "naklon": 6 }, +{ "label": "35/66", "node": 3683, "naklon": 6 }, +{ "label": "35/67", "node": 3673, "naklon": 6 }, +{ "label": "35/68", "node": 3674, "naklon": 6 }, +{ "label": "35/69", "node": 3679, "naklon": 6 }, +{ "label": "35/70", "node": 3649, "naklon": 6 }, +{ "label": "35/71", "node": 3687, "naklon": 6 }, +{ "label": "35/72", "node": 3677, "naklon": 6 }, +{ "label": "35/73", "node": 3690, "naklon": 6 }, +{ "label": "35/74", "node": 3691, "naklon": 6 }, +{ "label": "35/75", "node": 3676, "naklon": 6 }, +{ "label": "35/76", "node": 3680, "naklon": 6 }, +{ "label": "35/77", "node": 3668, "naklon": 6 }, +{ "label": "35/78", "node": 3681, "naklon": 6 }, +{ "label": "35/79", "node": 3670, "naklon": 6 }, +{ "label": "35/80", "node": 3689, "naklon": 6 }, +{ "label": "35/81", "node": 3678, "naklon": 6 }, +{ "label": "35/82", "node": 3693, "naklon": 6 }, +{ "label": "35/83", "node": 3654, "naklon": null }, +{ "label": "36/1", "node": 4086, "naklon": 0 }, +{ "label": "36/2", "node": 4085, "naklon": 0 }, +{ "label": "36/3", "node": 4083, "naklon": 0 }, +{ "label": "36/4", "node": 4087, "naklon": 0 }, +{ "label": "36/5", "node": 4077, "naklon": 0 }, +{ "label": "36/6", "node": 4082, "naklon": 0 }, +{ "label": "36/7", "node": 4186, "naklon": 0 }, +{ "label": "36/8", "node": 4206, "naklon": 0 }, +{ "label": "36/9", "node": 4080, "naklon": 0 }, +{ "label": "36/10", "node": 4081, "naklon": 0 }, +{ "label": "36/11", "node": 4210, "naklon": 0 }, +{ "label": "36/12", "node": 4079, "naklon": 0 }, +{ "label": "36/13", "node": 4076, "naklon": 0 }, +{ "label": "36/14", "node": 3852, "naklon": 0 }, +{ "label": "36/15", "node": 2813, "naklon": 0 }, +{ "label": "36/16", "node": 4219, "naklon": 0 }, +{ "label": "37/1A", "node": 3104, "naklon": 15 }, +{ "label": "37/1B", "node": 3121, "naklon": 15 }, +{ "label": "37/2", "node": 3113, "naklon": 10 }, +{ "label": "37/3", "node": 3118, "naklon": 10 }, +{ "label": "37/4", "node": 3111, "naklon": 10 }, +{ "label": "37/5", "node": 4020, "naklon": 10 }, +{ "label": "37/6", "node": 3119, "naklon": 10 }, +{ "label": "37/7", "node": 3110, "naklon": 10 }, +{ "label": "37/8", "node": 3108, "naklon": 10 }, +{ "label": "37/12", "node": 3107, "naklon": 0 }, +{ "label": "37/13", "node": 3199, "naklon": 0 }, +{ "label": "37/14", "node": 3120, "naklon": 0 }, +{ "label": "37/15", "node": 3122, "naklon": 0 }, +{ "label": "37/16", "node": 3908, "naklon": 0 }, +{ "label": "37/17", "node": 3114, "naklon": 0 }, +{ "label": "37/18", "node": 3105, "naklon": 0 }, +{ "label": "37/19", "node": 3116, "naklon": 0 }, +{ "label": "37/20", "node": 3106, "naklon": 0 }, +{ "label": "37/21", "node": 2887, "naklon": 5 }, +{ "label": "37/22", "node": 2888, "naklon": 5 }, +{ "label": "37/23", "node": 2877, "naklon": 5 }, +{ "label": "37/24", "node": 2891, "naklon": 5 }, +{ "label": "37/25", "node": 2886, "naklon": 5 }, +{ "label": "37/26", "node": 2892, "naklon": 5 }, +{ "label": "37/27", "node": 2882, "naklon": 5 }, +{ "label": "37/28", "node": 2883, "naklon": 5 }, +{ "label": "37/29", "node": 2876, "naklon": 5 }, +{ "label": "37/30", "node": 3109, "naklon": 5 }, +{ "label": "37/31", "node": 4152, "naklon": 5 }, +{ "label": "37/32", "node": 3117, "naklon": 5 }, +{ "label": "37/33", "node": 2870, "naklon": 5 }, +{ "label": "37/34", "node": 2867, "naklon": 0 }, +{ "label": "37/35", "node": 2865, "naklon": 0 }, +{ "label": "37/36", "node": 3096, "naklon": 0 }, +{ "label": "37/37", "node": 2871, "naklon": 0 }, +{ "label": "37/38", "node": 2884, "naklon": 0 }, +{ "label": "37/39", "node": 2855, "naklon": 0 }, +{ "label": "37/40", "node": 2878, "naklon": 0 }, +{ "label": "37/41", "node": 2889, "naklon": 0 }, +{ "label": "37/42", "node": 2879, "naklon": 0 }, +{ "label": "37/43", "node": 2850, "naklon": 0 }, +{ "label": "37/44", "node": 2894, "naklon": 0 }, +{ "label": "37/45", "node": 2880, "naklon": 0 }, +{ "label": "37/46", "node": 2893, "naklon": 0 }, +{ "label": "37/47", "node": 2890, "naklon": 0 }, +{ "label": "37/48", "node": 4355, "naklon": 0 }, +{ "label": "37/49", "node": 2885, "naklon": 0 }, +{ "label": "37/50", "node": 2875, "naklon": 0 }, +{ "label": "38/30A", "node": 3486, "naklon": 5 }, +{ "label": "38/30B", "node": 3714, "naklon": 0 }, +{ "label": "38/32A", "node": 3483, "naklon": 5 }, +{ "label": "38/32B", "node": 3496, "naklon": 0 }, +{ "label": "38/35A", "node": 3487, "naklon": 5 }, +{ "label": "38/35B", "node": 3498, "naklon": 5 }, +{ "label": "38/38A", "node": 3578, "naklon": 5 }, +{ "label": "38/38B", "node": 3508, "naklon": 5 }, +{ "label": "38/59A", "node": 3787, "naklon": 5 }, +{ "label": "38/59B", "node": 3491, "naklon": 5 }, +{ "label": "38/1", "node": 3568, "naklon": null }, +{ "label": "38/2", "node": 3502, "naklon": 0 }, +{ "label": "38/3", "node": 3836, "naklon": 0 }, +{ "label": "38/4", "node": 3588, "naklon": 0 }, +{ "label": "38/5", "node": 3493, "naklon": 0 }, +{ "label": "38/6", "node": 3580, "naklon": 0 }, +{ "label": "38/7", "node": 3572, "naklon": 0 }, +{ "label": "38/8", "node": 3506, "naklon": 0 }, +{ "label": "38/9", "node": 3503, "naklon": 0 }, +{ "label": "38/10", "node": 3579, "naklon": 0 }, +{ "label": "38/11", "node": 3586, "naklon": 0 }, +{ "label": "38/12", "node": 3495, "naklon": 5 }, +{ "label": "38/13", "node": 3492, "naklon": 5 }, +{ "label": "38/14", "node": 3532, "naklon": 5 }, +{ "label": "38/15", "node": 3574, "naklon": 5 }, +{ "label": "38/16", "node": 4140, "naklon": 5 }, +{ "label": "38/17", "node": 3795, "naklon": 5 }, +{ "label": "38/18", "node": 3788, "naklon": 5 }, +{ "label": "38/19", "node": 3796, "naklon": 5 }, +{ "label": "38/20", "node": 3797, "naklon": 5 }, +{ "label": "38/21", "node": 3798, "naklon": 5 }, +{ "label": "38/22", "node": 3786, "naklon": 5 }, +{ "label": "38/23", "node": 4067, "naklon": 5 }, +{ "label": "38/24", "node": 3773, "naklon": 5 }, +{ "label": "38/25", "node": 3774, "naklon": 5 }, +{ "label": "38/26", "node": 3789, "naklon": 5 }, +{ "label": "38/27", "node": 3520, "naklon": null }, +{ "label": "38/29", "node": 3577, "naklon": 5 }, +{ "label": "38/31", "node": 3530, "naklon": null }, +{ "label": "38/33", "node": 3488, "naklon": 5 }, +{ "label": "38/34", "node": 3505, "naklon": 5 }, +{ "label": "38/36", "node": 3497, "naklon": 5 }, +{ "label": "38/37", "node": 3490, "naklon": 5 }, +{ "label": "38/39", "node": 3585, "naklon": 5 }, +{ "label": "38/40", "node": 3582, "naklon": 5 }, +{ "label": "38/41", "node": 3507, "naklon": 5 }, +{ "label": "38/42", "node": 3484, "naklon": 5 }, +{ "label": "38/43", "node": 3501, "naklon": 5 }, +{ "label": "38/44", "node": 3581, "naklon": 5 }, +{ "label": "38/45", "node": 4192, "naklon": 5 }, +{ "label": "38/46", "node": 3576, "naklon": 5 }, +{ "label": "38/47", "node": 3489, "naklon": 5 }, +{ "label": "38/48", "node": 3573, "naklon": 5 }, +{ "label": "38/49", "node": 3504, "naklon": 5 }, +{ "label": "38/50", "node": 3794, "naklon": 5 }, +{ "label": "38/51", "node": 3485, "naklon": 5 }, +{ "label": "38/52", "node": 3482, "naklon": 5 }, +{ "label": "38/53", "node": 3575, "naklon": 5 }, +{ "label": "38/54", "node": 3499, "naklon": 5 }, +{ "label": "38/55", "node": 3494, "naklon": 5 }, +{ "label": "38/56", "node": 3583, "naklon": 5 }, +{ "label": "38/57", "node": 3570, "naklon": 5 }, +{ "label": "38/58", "node": 3500, "naklon": 0 }, +{ "label": "38/63", "node": 3510, "naklon": null }, +{ "label": "38/64", "node": 3512, "naklon": null }, +{ "label": "38/67", "node": 3535, "naklon": null }, +{ "label": "38/68", "node": 3531, "naklon": null }, +{ "label": "38/69", "node": 3537, "naklon": null }, +{ "label": "39/1", "node": 3522, "naklon": 10 }, +{ "label": "39/2", "node": 4018, "naklon": 10 }, +{ "label": "39/3", "node": 4019, "naklon": 10 }, +{ "label": "39/4", "node": 4154, "naklon": 5 }, +{ "label": "39/5", "node": 3907, "naklon": 5 }, +{ "label": "39/6", "node": 4148, "naklon": 0 }, +{ "label": "39/7", "node": 4153, "naklon": 0 }, +{ "label": "39/8", "node": 3938, "naklon": 0 }, +{ "label": "39/9", "node": 3802, "naklon": 0 }, +{ "label": "39/10", "node": 4015, "naklon": 0 }, +{ "label": "39/11", "node": 3929, "naklon": 0 }, +{ "label": "39/12", "node": 3946, "naklon": 0 }, +{ "label": "39/13", "node": 4014, "naklon": 0 }, +{ "label": "39/14", "node": 4155, "naklon": 0 }, +{ "label": "39/15", "node": 4149, "naklon": 0 }, +{ "label": "39/16", "node": 3642, "naklon": 0 }, +{ "label": "39/17", "node": 3636, "naklon": 5 }, +{ "label": "39/18", "node": 3991, "naklon": 0 }, +{ "label": "39/19", "node": 3994, "naklon": 0 }, +{ "label": "39/20", "node": 3990, "naklon": 0 }, +{ "label": "39/21", "node": 3967, "naklon": 0 }, +{ "label": "39/22", "node": 3977, "naklon": 0 }, +{ "label": "39/23", "node": 3757, "naklon": 15 }, +{ "label": "39/24", "node": 3633, "naklon": 15 }, +{ "label": "39/25", "node": 3744, "naklon": 15 }, +{ "label": "39/26", "node": 4023, "naklon": 5 }, +{ "label": "39/27", "node": 3720, "naklon": 5 }, +{ "label": "39/28", "node": 3734, "naklon": 5 }, +{ "label": "39/29", "node": 3741, "naklon": 5 }, +{ "label": "39/30", "node": 3721, "naklon": 5 }, +{ "label": "39/31", "node": 3845, "naklon": 0 }, +{ "label": "39/32", "node": 3840, "naklon": 0 }, +{ "label": "39/33", "node": 3837, "naklon": null }, +{ "label": "39/34", "node": 3839, "naklon": 0 }, +{ "label": "41/1", "node": 3542, "naklon": null }, +{ "label": "41/2", "node": 3566, "naklon": null }, +{ "label": "41/3", "node": 3548, "naklon": null }, +{ "label": "41/4", "node": 3515, "naklon": null }, +{ "label": "41/5", "node": 3559, "naklon": null }, +{ "label": "41/6", "node": 3509, "naklon": null }, +{ "label": "41/7", "node": 3524, "naklon": null }, +{ "label": "41/8", "node": 3518, "naklon": null }, +{ "label": "41/9", "node": 3182, "naklon": null }, +{ "label": "41/10", "node": 3187, "naklon": null }, +{ "label": "41/11", "node": 3195, "naklon": 0 }, +{ "label": "41/12", "node": 3857, "naklon": 0 }, +{ "label": "41/13", "node": 3183, "naklon": 0 }, +{ "label": "41/14", "node": 3177, "naklon": 0 }, +{ "label": "41/15", "node": 3189, "naklon": 0 }, +{ "label": "41/16", "node": 3186, "naklon": 0 }, +{ "label": "42/1", "node": 3178, "naklon": 0 }, +{ "label": "42/2", "node": 3219, "naklon": 0 }, +{ "label": "42/3", "node": 3475, "naklon": 0 }, +{ "label": "42/4", "node": 3175, "naklon": 0 }, +{ "label": "42/5", "node": 3222, "naklon": 0 }, +{ "label": "42/6", "node": 3221, "naklon": 0 }, +{ "label": "42/7", "node": 3181, "naklon": 0 }, +{ "label": "42/8", "node": 3180, "naklon": 0 }, +{ "label": "42/9", "node": 3218, "naklon": 0 }, +{ "label": "42/10", "node": 3176, "naklon": 0 }, +{ "label": "42/11", "node": 3174, "naklon": 0 }, +{ "label": "42/12", "node": 3220, "naklon": 0 }, +{ "label": "42/13", "node": 3533, "naklon": null }, +{ "label": "42/14", "node": 3543, "naklon": null }, +{ "label": "42/15", "node": 3554, "naklon": null }, +{ "label": "42/16", "node": 3549, "naklon": null }, +{ "label": "43/1", "node": 2857, "naklon": 5 }, +{ "label": "43/2", "node": 2752, "naklon": 5 }, +{ "label": "43/3", "node": 2753, "naklon": 5 }, +{ "label": "43/4", "node": 3024, "naklon": 5 }, +{ "label": "43/5", "node": 2754, "naklon": 5 }, +{ "label": "43/6", "node": 4423, "naklon": 5 }, +{ "label": "43/7", "node": 4368, "naklon": 5 }, +{ "label": "43/8", "node": 2978, "naklon": 5 }, +{ "label": "43/9", "node": 2868, "naklon": 5 }, +{ "label": "43/10", "node": 4377, "naklon": 5 }, +{ "label": "43/11", "node": 2757, "naklon": 5 }, +{ "label": "43/12", "node": 2970, "naklon": 5 }, +{ "label": "43/13", "node": 2758, "naklon": 5 }, +{ "label": "43/14", "node": 4378, "naklon": 5 }, +{ "label": "43/15", "node": 2759, "naklon": 5 }, +{ "label": "43/16", "node": 4342, "naklon": 5 }, +{ "label": "43/17", "node": 3026, "naklon": null }, +{ "label": "43/18", "node": 2986, "naklon": null }, +{ "label": "43/19", "node": 4343, "naklon": null }, +{ "label": "43/20", "node": 2760, "naklon": null }, +{ "label": "43/21", "node": 4379, "naklon": null }, +{ "label": "43/22", "node": 2971, "naklon": null }, +{ "label": "43/23", "node": 2761, "naklon": null }, +{ "label": "43/24", "node": 2762, "naklon": null }, +{ "label": "43/25", "node": 4339, "naklon": null }, +{ "label": "43/26", "node": 4380, "naklon": null }, +{ "label": "43/27", "node": 2975, "naklon": null }, +{ "label": "43/28", "node": 3003, "naklon": null }, +{ "label": "43/29", "node": 4338, "naklon": null }, +{ "label": "43/30", "node": 3002, "naklon": null }, +{ "label": "43/31", "node": 4345, "naklon": null }, +{ "label": "43/32", "node": 2979, "naklon": null }, +{ "label": "43/33", "node": 2989, "naklon": null }, +{ "label": "43/34", "node": 2996, "naklon": null }, +{ "label": "43/35", "node": 2972, "naklon": null }, +{ "label": "43/36", "node": 2988, "naklon": null }, +{ "label": "43/37", "node": 4344, "naklon": null }, +{ "label": "43/38", "node": 3022, "naklon": null }, +{ "label": "43/39", "node": 4341, "naklon": null }, +{ "label": "43/40", "node": 2983, "naklon": null }, +{ "label": "43/41", "node": 2995, "naklon": null }, +{ "label": "43/42", "node": 2763, "naklon": null }, +{ "label": "43/43", "node": 2764, "naklon": null }, +{ "label": "43/44", "node": 2765, "naklon": null }, +{ "label": "43/45", "node": 2766, "naklon": null }, +{ "label": "43/46", "node": 2767, "naklon": null }, +{ "label": "43/47", "node": 2768, "naklon": null }, +{ "label": "43/48", "node": 3018, "naklon": null }, +{ "label": "43/49", "node": 2982, "naklon": null }, +{ "label": "43/50", "node": 3019, "naklon": 0 }, +{ "label": "43/51", "node": 3013, "naklon": null }, +{ "label": "43/52", "node": 3007, "naklon": null }, +{ "label": "43/53", "node": 2980, "naklon": null }, +{ "label": "43/54", "node": 3011, "naklon": null }, +{ "label": "43/55", "node": 2672, "naklon": null }, +{ "label": "43/56", "node": 2673, "naklon": null }, +{ "label": "43/57", "node": 2674, "naklon": null }, +{ "label": "43/58", "node": 2675, "naklon": null }, +{ "label": "43/59", "node": 2676, "naklon": null }, +{ "label": "43/60", "node": 2677, "naklon": null }, +{ "label": "43/61", "node": 2678, "naklon": null }, +{ "label": "43/62", "node": 2679, "naklon": null }, +{ "label": "43/63", "node": 2680, "naklon": null }, +{ "label": "43/64", "node": 2840, "naklon": null }, +{ "label": "43/65", "node": 2682, "naklon": null }, +{ "label": "43/66", "node": 2683, "naklon": null }, +{ "label": "43/67", "node": 2684, "naklon": 0 }, +{ "label": "43/68", "node": 2685, "naklon": null }, +{ "label": "43/69", "node": 2686, "naklon": null }, +{ "label": "43/70", "node": 2687, "naklon": null }, +{ "label": "43/71", "node": 2688, "naklon": null }, +{ "label": "43/72", "node": 2689, "naklon": null }, +{ "label": "43/73", "node": 2690, "naklon": null }, +{ "label": "43/74", "node": 2691, "naklon": null }, +{ "label": "43/75", "node": 2692, "naklon": null }, +{ "label": "43/76", "node": 2693, "naklon": 0 }, +{ "label": "43/77", "node": 2694, "naklon": null }, +{ "label": "43/78", "node": 2695, "naklon": null }, +{ "label": "43/79", "node": 2696, "naklon": 0 }, +{ "label": "43/80", "node": 2697, "naklon": null }, +{ "label": "43/81", "node": 2698, "naklon": 0 }, +{ "label": "43/82", "node": 2699, "naklon": null }, +{ "label": "43/83", "node": 2700, "naklon": 0 }, +{ "label": "43/84", "node": 2744, "naklon": null }, +{ "label": "43/85", "node": 2745, "naklon": 0 }, +{ "label": "43/86", "node": 2746, "naklon": null }, +{ "label": "43/87", "node": 2747, "naklon": 0 }, +{ "label": "43/88", "node": 2748, "naklon": null }, +{ "label": "43/89", "node": 2749, "naklon": 0 }, +{ "label": "43/90", "node": 2841, "naklon": null }, +{ "label": "45/1", "node": 4237, "naklon": 5 }, +{ "label": "45/2", "node": 4226, "naklon": 5 }, +{ "label": "45/3", "node": 4242, "naklon": 5 }, +{ "label": "45/4", "node": 4179, "naklon": 5 }, +{ "label": "45/5", "node": 4247, "naklon": 5 }, +{ "label": "45/6", "node": 4245, "naklon": 5 }, +{ "label": "45/7", "node": 3872, "naklon": 5 }, +{ "label": "45/8", "node": 4175, "naklon": 5 }, +{ "label": "45/9", "node": 4236, "naklon": 5 }, +{ "label": "45/10", "node": 4170, "naklon": 5 }, +{ "label": "45/11", "node": 4238, "naklon": 5 }, +{ "label": "45/12", "node": 4246, "naklon": 5 }, +{ "label": "45/13", "node": 4166, "naklon": 5 }, +{ "label": "45/14", "node": 4227, "naklon": 5 }, +{ "label": "45/15", "node": 4171, "naklon": 5 }, +{ "label": "45/16", "node": 4180, "naklon": 5 }, +{ "label": "45/17", "node": 4244, "naklon": 5 }, +{ "label": "45/18", "node": 4199, "naklon": 5 }, +{ "label": "45/19", "node": 4239, "naklon": 5 }, +{ "label": "45/20", "node": 4207, "naklon": 5 }, +{ "label": "45/21", "node": 4223, "naklon": 5 }, +{ "label": "45/22", "node": 4230, "naklon": 5 }, +{ "label": "45/23", "node": 4233, "naklon": 5 }, +{ "label": "45/24", "node": 4222, "naklon": 5 }, +{ "label": "45/25", "node": 4217, "naklon": 5 }, +{ "label": "45/26", "node": 4243, "naklon": 5 }, +{ "label": "45/27", "node": 4200, "naklon": 5 }, +{ "label": "45/28", "node": 4228, "naklon": 5 }, +{ "label": "45/29", "node": 4211, "naklon": 5 }, +{ "label": "45/30", "node": 4234, "naklon": 5 }, +{ "label": "45/31", "node": 4235, "naklon": 5 }, +{ "label": "45/32", "node": 4203, "naklon": 5 }, +{ "label": "45/33", "node": 4240, "naklon": 5 }, +{ "label": "45/34", "node": 4224, "naklon": 5 }, +{ "label": "45/35", "node": 4232, "naklon": 5 }, +{ "label": "45/36", "node": 4231, "naklon": 5 }, +{ "label": "45/37", "node": 4161, "naklon": 5 }, +{ "label": "45/38", "node": 4225, "naklon": 5 }, +{ "label": "45/39", "node": 4241, "naklon": 5 }, +{ "label": "45/40", "node": 4229, "naklon": 5 }, +{ "label": "45/41", "node": 4221, "naklon": 5 }, +{ "label": "45/42", "node": 4212, "naklon": 5 }, +{ "label": "45/43", "node": 4216, "naklon": 5 }, +{ "label": "45/44", "node": 3864, "naklon": null }, +{ "label": "46/1", "node": 3806, "naklon": 5 }, +{ "label": "46/2", "node": 3813, "naklon": 5 }, +{ "label": "46/3", "node": 3815, "naklon": 5 }, +{ "label": "46/4", "node": 3807, "naklon": 5 }, +{ "label": "46/5", "node": 3895, "naklon": 5 }, +{ "label": "46/6", "node": 3809, "naklon": 5 }, +{ "label": "46/7", "node": 3820, "naklon": 5 }, +{ "label": "46/8", "node": 3805, "naklon": 5 }, +{ "label": "46/9", "node": 3894, "naklon": 0 }, +{ "label": "46/10", "node": 4055, "naklon": 0 }, +{ "label": "46/11", "node": 3812, "naklon": 5 }, +{ "label": "46/12", "node": 3822, "naklon": 5 }, +{ "label": "46/13", "node": 3821, "naklon": 5 }, +{ "label": "46/14", "node": 3808, "naklon": 5 }, +{ "label": "46/15", "node": 3799, "naklon": 5 }, +{ "label": "46/16", "node": 3816, "naklon": 5 }, +{ "label": "46/17", "node": 3751, "naklon": 5 }, +{ "label": "46/18", "node": 3814, "naklon": 5 }, +{ "label": "46/19", "node": 4044, "naklon": 0 }, +{ "label": "46/20", "node": 3931, "naklon": 0 }, +{ "label": "46/21", "node": 3902, "naklon": 5 }, +{ "label": "46/22", "node": 3916, "naklon": 5 }, +{ "label": "46/23", "node": 3892, "naklon": 5 }, +{ "label": "46/24", "node": 3914, "naklon": 5 }, +{ "label": "46/25", "node": 3898, "naklon": 5 }, +{ "label": "46/26", "node": 3897, "naklon": 5 }, +{ "label": "46/27", "node": 3885, "naklon": 5 }, +{ "label": "46/28", "node": 3906, "naklon": 5 }, +{ "label": "46/29", "node": 3930, "naklon": 0 }, +{ "label": "46/30", "node": 3936, "naklon": 0 }, +{ "label": "46/31", "node": 3860, "naklon": 5 }, +{ "label": "46/32", "node": 3841, "naklon": 5 }, +{ "label": "46/33", "node": 3873, "naklon": 5 }, +{ "label": "46/34", "node": 3854, "naklon": 5 }, +{ "label": "46/35", "node": 3939, "naklon": 5 }, +{ "label": "46/36", "node": 3858, "naklon": 5 }, +{ "label": "46/37", "node": 3940, "naklon": 5 }, +{ "label": "46/38", "node": 4035, "naklon": 5 }, +{ "label": "47/1", "node": 3373, "naklon": 0 }, +{ "label": "47/2", "node": 3374, "naklon": 0 }, +{ "label": "47/3", "node": 3384, "naklon": 0 }, +{ "label": "47/4", "node": 3385, "naklon": 0 }, +{ "label": "48/1", "node": 4051, "naklon": 5 }, +{ "label": "48/2", "node": 4041, "naklon": 5 }, +{ "label": "48/3", "node": 4056, "naklon": 5 }, +{ "label": "48/4", "node": 3875, "naklon": 5 }, +{ "label": "48/5", "node": 4061, "naklon": 5 }, +{ "label": "48/6", "node": 4047, "naklon": 5 }, +{ "label": "48/7", "node": 4060, "naklon": 5 }, +{ "label": "48/8", "node": 4059, "naklon": 5 }, +{ "label": "48/9", "node": 4058, "naklon": 5 }, +{ "label": "48/10", "node": 3635, "naklon": 5 }, +{ "label": "48/11", "node": 3640, "naklon": 5 }, +{ "label": "48/12", "node": 3747, "naklon": 5 }, +{ "label": "48/13", "node": 3629, "naklon": 5 }, +{ "label": "48/14", "node": 4048, "naklon": 5 }, +{ "label": "48/15", "node": 4063, "naklon": 5 }, +{ "label": "48/16", "node": 4062, "naklon": 5 }, +{ "label": "48/17", "node": 4043, "naklon": 5 }, +{ "label": "48/18", "node": 4052, "naklon": 5 }, +{ "label": "48/19", "node": 4042, "naklon": 5 }, +{ "label": "48/20", "node": 4053, "naklon": 5 }, +{ "label": "50/15A", "node": 4167, "naklon": null }, +{ "label": "50/15B", "node": 4159, "naklon": null }, +{ "label": "50/1", "node": 4183, "naklon": 0 }, +{ "label": "50/2", "node": 4157, "naklon": 0 }, +{ "label": "50/3", "node": 4160, "naklon": 0 }, +{ "label": "50/4", "node": 4173, "naklon": 0 }, +{ "label": "50/5", "node": 4177, "naklon": 0 }, +{ "label": "50/6", "node": 4174, "naklon": 0 }, +{ "label": "50/7", "node": 4178, "naklon": 0 }, +{ "label": "50/8", "node": 4195, "naklon": 0 }, +{ "label": "50/9", "node": 4169, "naklon": 0 }, +{ "label": "50/10", "node": 4162, "naklon": 0 }, +{ "label": "50/11", "node": 4158, "naklon": 0 }, +{ "label": "50/12", "node": 4182, "naklon": 0 }, +{ "label": "50/13", "node": 4194, "naklon": 0 }, +{ "label": "50/14", "node": 4184, "naklon": 0 }, +{ "label": "50/16", "node": 4197, "naklon": null }, +{ "label": "50/17", "node": 4164, "naklon": null }, +{ "label": "50/18", "node": 3306, "naklon": null }, +{ "label": "50/19", "node": 4168, "naklon": null }, +{ "label": "50/20", "node": 4193, "naklon": null }, +{ "label": "50/21", "node": 4187, "naklon": null }, +{ "label": "50/22", "node": 4163, "naklon": null }, +{ "label": "50/23", "node": 4165, "naklon": null }, +{ "label": "50/24", "node": 4185, "naklon": null }, +{ "label": "50/25", "node": 3904, "naklon": null }, +{ "label": "53/1", "node": 2619, "naklon": 0 }, +{ "label": "53/2", "node": 2623, "naklon": 0 }, +{ "label": "53/3", "node": 2617, "naklon": 0 }, +{ "label": "53/4", "node": 2622, "naklon": 0 }, +{ "label": "53/5", "node": 2618, "naklon": 0 }, +{ "label": "53/6", "node": 2626, "naklon": 0 }, +{ "label": "53/7", "node": 2869, "naklon": 0 }, +{ "label": "53/8", "node": 2613, "naklon": 0 }, +{ "label": "53/9", "node": 2608, "naklon": 0 }, +{ "label": "53/10", "node": 2611, "naklon": 0 }, +{ "label": "53/11", "node": 2598, "naklon": 0 }, +{ "label": "53/12", "node": 3528, "naklon": 0 }, +{ "label": "53/13", "node": 3545, "naklon": 0 }, +{ "label": "53/14", "node": 2620, "naklon": 0 }, +{ "label": "53/15", "node": 2612, "naklon": 0 }, +{ "label": "53/16", "node": 2615, "naklon": 0 }, +{ "label": "53/17", "node": 3722, "naklon": 0 }, +{ "label": "53/18", "node": 2624, "naklon": 0 }, +{ "label": "53/19", "node": 2609, "naklon": 0 }, +{ "label": "53/20", "node": 2625, "naklon": 0 }, +{ "label": "53/21", "node": 2602, "naklon": 0 }, +{ "label": "53/22", "node": 2610, "naklon": 0 }, +{ "label": "53/23", "node": 2599, "naklon": 0 }, +{ "label": "53/24", "node": 2605, "naklon": 0 }, +{ "label": "53/25", "node": 2593, "naklon": 0 }, +{ "label": "53/26", "node": 3074, "naklon": 0 }, +{ "label": "53/27", "node": 2740, "naklon": 0 }, +{ "label": "53/28", "node": 2614, "naklon": 0 }, +{ "label": "53/29", "node": 2601, "naklon": 0 }, +{ "label": "53/30", "node": 4196, "naklon": 0 }, +{ "label": "53/31", "node": 2607, "naklon": 0 }, +{ "label": "53/32", "node": 2582, "naklon": 0 }, +{ "label": "53/33", "node": 2594, "naklon": 0 }, +{ "label": "53/34", "node": 2589, "naklon": 0 }, +{ "label": "53/35", "node": 2596, "naklon": 0 }, +{ "label": "53/36", "node": 2603, "naklon": 0 }, +{ "label": "53/37", "node": 2597, "naklon": 0 }, +{ "label": "53/38", "node": 2590, "naklon": 0 }, +{ "label": "53/39", "node": 2581, "naklon": 0 }, +{ "label": "53/40", "node": 2583, "naklon": 0 }, +{ "label": "53/41", "node": 2580, "naklon": 0 }, +{ "label": "53/42", "node": 2579, "naklon": 0 }, +{ "label": "53/43", "node": 2797, "naklon": 0 }, +{ "label": "53/44", "node": 2577, "naklon": 0 }, +{ "label": "53/45", "node": 2586, "naklon": 0 }, +{ "label": "53/46", "node": 2588, "naklon": 0 }, +{ "label": "53/47", "node": 2591, "naklon": 0 }, +{ "label": "53/48", "node": 2592, "naklon": 0 }, +{ "label": "53/49", "node": 2573, "naklon": 0 }, +{ "label": "53/50", "node": 2595, "naklon": 0 }, +{ "label": "53/51", "node": 2587, "naklon": 0 }, +{ "label": "53/52", "node": 2578, "naklon": 0 }, +{ "label": "53/53", "node": 2574, "naklon": 0 }, +{ "label": "53/54", "node": 2571, "naklon": 0 }, +{ "label": "53/55", "node": 2570, "naklon": 0 }, +{ "label": "53/56", "node": 2576, "naklon": 0 }, +{ "label": "53/57", "node": 2881, "naklon": 0 }, +{ "label": "53/58", "node": 2575, "naklon": 0 }, +{ "label": "53/59", "node": 2572, "naklon": 0 }, +{ "label": "53/60", "node": 2569, "naklon": 0 }, +{ "label": "55/1", "node": 4324, "naklon": 0 }, +{ "label": "55/2", "node": 4319, "naklon": 0 }, +{ "label": "55/3", "node": 4327, "naklon": 0 }, +{ "label": "55/4", "node": 4333, "naklon": 0 }, +{ "label": "55/5", "node": 4332, "naklon": 0 }, +{ "label": "55/6", "node": 4320, "naklon": 0 }, +{ "label": "55/7", "node": 4317, "naklon": 0 }, +{ "label": "55/8", "node": 4318, "naklon": 0 }, +{ "label": "55/9", "node": 4328, "naklon": 0 }, +{ "label": "55/10", "node": 4323, "naklon": 0 }, +{ "label": "55/11", "node": 4325, "naklon": 0 }, +{ "label": "55/12", "node": 4326, "naklon": 0 }, +{ "label": "55/13", "node": 4316, "naklon": 0 }, +{ "label": "55/14", "node": 4322, "naklon": 0 }, +{ "label": "55/15", "node": 4331, "naklon": 0 }, +{ "label": "55/16", "node": 4321, "naklon": 0 }, +{ "label": "55/17", "node": 4315, "naklon": 0 }, +{ "label": "55/18", "node": 4329, "naklon": 0 }, +{ "label": "55/19", "node": 4334, "naklon": 0 }, +{ "label": "55/20", "node": 4330, "naklon": 0 } +]; + +module.exports = { naklony }; diff --git a/RVO16/databases/modbus_config.js b/RVO16/databases/modbus_config.js new file mode 100755 index 0000000..b73116a --- /dev/null +++ b/RVO16/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/RVO16/databases/nodes.table b/RVO16/databases/nodes.table new file mode 100755 index 0000000..3df00ab --- /dev/null +++ b/RVO16/databases/nodes.table @@ -0,0 +1,128 @@ +node:number|pole_number:string|node_type:string|tbname:string|line:number|profile:string|processed:boolean|status:boolean|time_of_last_communication:number ++|3831|17|NEMA|JzwxZXOvDj1bVrN4nkWwJKk8qdyBl3MRKLpGPgaQ|1||1|1|1760574248582|............. ++|3739|6|NEMA|5dBNwRp9graYJxZn409wGV7lVov1b2QLPDqGm6XK|1||1|1|1760573832281|............. ++|3801|44|NEMA|roKgWqY95V3mXMRzyAjmrz7bLjexpJPvaGDBw826|1||1|1|1760574246856|............. ++|3659|60|NEMA|ZmRwd93QL4gaezxEbAxW2O71prn2XjlPvGyqJ6BO|1||1|1|1760573713804|............. ++|3659|78|NEMA|ZmRwd93QL4gaezxEbAxW2O71prn2XjlPvGyqJ6BO|1||1|1|1760573713804|............. ++|3861|47|NEMA|gYbDLqlyZVoRerQpB72rGp7WJnwM5z24POKa8Exj|1||1|1|1760573552771|............. ++|3870|76|NEMA|B5EoxeMVp4zwr8nqW0GjBxARjvD1PNamOGbLg63Z|1||1|0|1760244554423|............. ++|4107|98|NEMA|rDbQ84xzwgdqEoPm3kbJErk9anOZY1RXyBv2LVM6|1||1|1|1760573931758|............. ++|4766|51|NEMA|zrR51V2ajQ9ZLygPKkEmPpkYDq38xOJolENBXGnv|1||1|1|1760573654852|............. ++|3593|54|NEMA|apKVJBwOyrP35m2lv7KzEKkYXbeWNd64En9GxRqg|1||1|1|1760574049100|............. ++|3755|82|NEMA|wvKJdZML6mXP4DzWBAXWx17jxNloa5g23Ve9Y1ry|1||1|1|1760573915778|............. ++|3697|96|NEMA|PLBJzmK1r3Gynd6OW0gGKo0e5wV4vx9bDEqNgYR8|1||1|1|1760573736032|............. ++|3712|5|NEMA|WlVJBygjDZMeKX3vnAMzGQ08NqdmG2x1Y69LQ4P5|1||1|1|1760573762576|............. ++|3724|4|NEMA|zdQO8GwxDqjRgP4137Y1xq7NyKlpem2nL65rvVJY|1||1|1|1760573913125|............. ++|4370|29|NEMA|gRoJEyXVx4qD9er287LPwm7wBzGldaPjLWQKm3Mv|1||1|1|1760573974777|............. ++|4372|70|NEMA|PjLblDgRBO6WQqnxmkJ5150Jv3ewZN4p5a89yKdY|1||1|1|1760573638552|............. ++|4373|33|NEMA|aw4eELG2DlPMdn1JW0B1zbAqQXOZRN3xB5yp8VKr|1||1|1|1760573638696|............. ++|3594|53|NEMA|DbQY6zyveZRwK5drV0Z9lLAjoE4XJM83N9xl2nWq|1||1|1|1760574093302|............. ++|3603|50|NEMA|5dBNwRp9graYJxZn409wRV7lVov1b2QLPDqGm6XK|1||1|1|1760574097105|............. ++|3605|49|NEMA|WlVJBygjDZMeKX3vnAMzWQ08NqdmG2x1Y69LQ4P5|1||1|1|1760573706900|............. ++|3963|25|NEMA|1JMYvnx2RzKEo4aWQ7Dm9GAL8yZV3m9NBePXbrdj|1||1|1|1760573588007|............. ++|3608|16A|NEMA|m6EYyZoJ4gWexdjVPARNzEARDOq9wv2N5XzKGplr|1||1|1|1760574106821|............. ++|3609|24|NEMA|Z5KyJe9nEg1QNbWlX0wWmm0oDjBLdqzR83VGv624|1||1|1|1760573708275|............. ++|3610|18|NEMA|g9OxBZ5KRwNznlY6pAp64dkWXvjdEL4eGQobMDy2|1||1|1|1760574107380|............. ++|3614|31|NEMA|d9x2V5LGYBzXp4mMRAOBPq7PloaqJwnQj6DgrNe3|1||1|1|1760574129401|............. ++|4768|23|NEMA|3JjOWdylwgNLzxVab7NEPBkZ2vG64rq8PEB5QmDo|1||1|1|1760573661963|............. ++|3618|20|NEMA|JX1ObgmqGZ54DMyYL7a95d7EVdve38WKRzwjNrQ9|1||1|1|1760574136560|............. ++|2736|21|NEMA|RvmwNz8QPblKp41GD7lDmV7JrLVYoBO92dMegn6W|1||1|1|1760574193434|............. ++|3620|34|NEMA|ZmRwd93QL4gaezxEbAxW1O71prn2XjlPvGyqJ6BO|1||1|1|1760574136720|............. ++|3623|32|NEMA|B5EoxeMVp4zwr8nqW0GjexARjvD1PNamOGbLg63Z|1||1|1|1760574113964|............. ++|3624|26|NEMA|PjLblDgRBO6WQqnxmkJ5w50Jv3ewZN4p5a89yKdY|1||1|1|1760574116313|............. ++|3626|19|NEMA|OzNMgZ9n43qPbjXmy7zWGdA2DKdYvW5e6pxGRrVa|1||1|1|1760574116489|............. ++|3627|27|NEMA|dz4ojlpP85JMgDLZWkQO1zAaKYqQexEr62GXRV1y|1||1|1|1760574119286|............. ++|3732|22|NEMA|RO8rjaBDy21qPQJzW7oDK9ApK3xmNleVZg9Ed4Gw|1||1|1|1760573632480|............. ++|3631|118|NEMA|g9OxBZ5KRwNznlY6pAp66EkWXvjdEL4eGQobMDy2|1||1|1|1760574120900|............. ++|3637|122|NEMA|RO8rjaBDy21qPQJzW7oDDOApK3xmNleVZg9Ed4Gw|1||1|1|1760574121251|............. ++|3638|121|NEMA|RvmwNz8QPblKp41GD7lDDZ7JrLVYoBO92dMegn6W|1||1|1|1760573706692|............. ++|4117|120|NEMA|JX1ObgmqGZ54DMyYL7a99m7EVdve38WKRzwjNrQ9|1||1|1|1760573759587|............. ++|3685|35|NEMA|eod9aRWLVl34Gx1Dn7VoYMA2rz6qjgmpEXwQJN5Z|1||1|1|1760574134003|............. ++|3686|37|NEMA|EjgWGnXaLy9opPOz20n6gV086BlYM3w1deVQvbKr|1||1|1|1760573851554|............. ++|3688|38|NEMA|wvKJdZML6mXP4DzWBAXWO17jxNloa5g23Ve9Y1ry|1||1|1|1760574134323|............. ++|3692|30|NEMA|K94XLav1glVRnyQ6r01BVakme3YJwBxM5oOzdP2j|1||1|1|1760574134483|............. ++|3694|79|NEMA|eod9aRWLVl34Gx1Dn7VoNMA2rz6qjgmpEXwQJN5Z|1||1|1|1760573856587|............. ++|3696|85|NEMA|52dD6ZlV1QaOpRBmbAqKGQkKnGzWMLj4eJq38Pgo|1||1|1|1760573856763|............. ++|3698|59|NEMA|6lQGaY9RDywdVzObj0P1ZykPg4NBn3exEK51LWZq|1||1|1|1760573863475|............. ++|3699|58|NEMA|pE5X8NQPaow6vlOZxk6gYy7q42ezGBMyWgDVjR3L|1||1|1|1760574138941|............. ++|3700|63|NEMA|OzNMgZ9n43qPbjXmy7zWOdA2DKdYvW5e6pxGRrVa|1||1|1|1760573866735|............. ++|3701|64|NEMA|JX1ObgmqGZ54DMyYL7a9Jd7EVdve38WKRzwjNrQ9|1||1|1|1760573868940|............. ++|2647|86|NEMA|rDbQ84xzwgdqEoPm3kbJEdk9anOZY1RXyBv2LVM6|1||1|1|1760574072000|............. ++|3703|62|NEMA|g9OxBZ5KRwNznlY6pAp6bdkWXvjdEL4eGQobMDy2|1||1|1|1760573872455|............. ++|2613|65|NEMA|RvmwNz8QPblKp41GD7lD4V7JrLVYoBO92dMegn6W|1||1|1|1760574079990|............. ++|3706|87|NEMA|E6Kg9oDnLWyzPRMva7vr5x7Jxp4VG58qO2w1lZYe|1||1|1|1760573880525|............. ++|3707|66|NEMA|RO8rjaBDy21qPQJzW7oDm9ApK3xmNleVZg9Ed4Gw|1||1|1|1760573880717|............. ++|3708|61|NEMA|JzwxZXOvDj1bVrN4nkWweKk8qdyBl3MRKLpGPgaQ|1||1|1|1760573759987|............. ++|3709|60|NEMA|m6EYyZoJ4gWexdjVPARNaEARDOq9wv2N5XzKGplr|1||1|1|1760574157351|............. ++|3713|12|NEMA|gP1eOZVj3Q9lv5aDEk4E1Q7rdpqW8yLm2BbKzJxM|1||1|1|1760573902514|............. ++|3716|84|NEMA|PLBJzmK1r3Gynd6OW0gGKP0e5wV4vx9bDEqNgYR8|1||1|1|1760573907500|............. ++|3719|95|NEMA|Nzp2OoJlqn6r1ZgvdA3GBjAabBwP5G4eE3RQmyxD|1||1|1|1760573908347|............. ++|3723|92|NEMA|3a5oqJN1bgnx4Ol9dk869wAByE6jQ8mKDWMpGrLV|1||1|1|1760573912550|............. ++|3725|83|NEMA|Nzp2OoJlqn6r1ZgvdA3GBKAabBwP5G4eE3RQmyxD|1||1|1|1760574201249|............. ++|3727|9|NEMA|DbQY6zyveZRwK5drV0Z9ZLAjoE4XJM83N9xl2nWq|1||1|1|1760574222870|............. ++|3729|10|NEMA|apKVJBwOyrP35m2lv7KzWKkYXbeWNd64En9GxRqg|1||1|1|1760572741778|............. ++|3731|8|NEMA|BaY3Xpy1EbKGjLq2O7mGKo0rx8owgQz9P4dDJRmN|1||1|1|1760574222118|............. ++|3880|15|NEMA|6lQGaY9RDywdVzObj0P1oykPg4NBn3exEK51LWZq|1||1|1|1760573584220|............. ++|3219|14|NEMA|pE5X8NQPaow6vlOZxk6gMy7q42ezGBMyWgDVjR3L|1||1|1|1760574097712|............. ++|3735|94|NEMA|wvKJdZML6mXP4DzWBAXWxB7jxNloa5g23Ve9Y1ry|1||1|1|1760573638137|............. ++|3736|11|NEMA|o9vbeQlLMVg8j5dq4kegbRANxZpEmnXzwYKO1ar2|1||1|1|1760574229166|............. ++|3737|90|NEMA|ZmRwd93QL4gaezxEbAxW2X71prn2XjlPvGyqJ6BO|1||1|1|1760573882603|............. ++|3743|3|NEMA|gYbDLqlyZVoRerQpB72r8p7WJnwM5z24POKa8Exj|1||1|1|1760573901987|............. ++|3746|57|NEMA|2O14VBzl8aDmWdNw3A513bAGyZ5qLJoEMpj6R9ng|1||1|1|1760573907692|............. ++|3763|56|NEMA|gP1eOZVj3Q9lv5aDEk4EMQ7rdpqW8yLm2BbKzJxM|1||1|1|1760574243772|............. ++|3490|67|NEMA|3JjOWdylwgNLzxVab7NEaBkZ2vG64rq8PEB5QmDo|1||1|1|1760574044114|............. ++|3824|42|NEMA|rDbQ84xzwgdqEoPm3kbJPdk9anOZY1RXyBv2LVM6|1||1|1|1760574248038|............. ++|3825|40|NEMA|PLBJzmK1r3Gynd6OW0gG2P0e5wV4vx9bDEqNgYR8|1||1|1|1760574248230|............. ++|3830|75|NEMA|d9x2V5LGYBzXp4mMRAOBmq7PloaqJwnQj6DgrNe3|1||1|1|1760573952276|............. ++|3842|93|NEMA|EjgWGnXaLy9opPOz20n64m086BlYM3w1deVQvbKr|1||1|1|1760573953044|............. ++|3848|89|NEMA|nJL5lPMwBx23YpqRe0rlpv7damXvWVbOrD4gNzy8|1||1|1|1760573953251|............. ++|3850|88|NEMA|roKgWqY95V3mXMRzyAjmKz7bLjexpJPvaGDBw826|1||1|1|1760573953683|............. ++|3964|77|NEMA|aw4eELG2DlPMdn1JW0B1MbAqQXOZRN3xB5yp8VKr|1||1|1|1760573998763|............. ++|3862|45|NEMA|nJL5lPMwBx23YpqRe0rlqv7damXvWVbOrD4gNzy8|1||1|1|1760573553074|............. ++|3867|69|NEMA|1JMYvnx2RzKEo4aWQ7DmGGAL8yZV3m9NBePXbrdj|1||1|1|1760573559978|............. ++|3869|73|NEMA|gRoJEyXVx4qD9er287LP4m7wBzGldaPjLWQKm3Mv|1||1|1|1760573561560|............. ++|3871|43|NEMA|E6Kg9oDnLWyzPRMva7vrWx7Jxp4VG58qO2w1lZYe|1||1|1|1760573578435|............. ++|3876|46|NEMA|XMBbew5z4ELrZa2mRAd5ZW08vPN6gy3DdVYlpKjq|1||1|1|1760573578962|............. ++|3722|105|NEMA|WlVJBygjDZMeKX3vnAMzRj08NqdmG2x1Y69LQ4P5|1||1|1|1760573912374|............. ++|4090|110|NEMA|apKVJBwOyrP35m2lv7Kzz5kYXbeWNd64En9GxRqg|1||1|1|1760573588902|............. ++|4091|102|NEMA|XMBbew5z4ELrZa2mRAd53V08vPN6gy3DdVYlpKjq|1||1|1|1760574011691|............. ++|4092|117|NEMA|JzwxZXOvDj1bVrN4nkWwwNk8qdyBl3MRKLpGPgaQ|1||1|1|1760573592641|............. ++|4095|106|NEMA|5dBNwRp9graYJxZn409wNQ7lVov1b2QLPDqGm6XK|1||1|1|1760573597787|............. ++|4097|112|NEMA|gP1eOZVj3Q9lv5aDEk4EEM7rdpqW8yLm2BbKzJxM|1||1|1|1760574017667|............. ++|4099|113|NEMA|2O14VBzl8aDmWdNw3A5119AGyZ5qLJoEMpj6R9ng|1||1|1|1760573929265|............. ++|4102|107|NEMA|zrR51V2ajQ9ZLygPKkEmMxkYDq38xOJolENBXGnv|1||1|1|1760573609037|............. ++|4104|103|NEMA|gYbDLqlyZVoRerQpB72rML7WJnwM5z24POKa8Exj|1||1|1|1760573609261|............. ++|3115|108|NEMA|BaY3Xpy1EbKGjLq2O7mGa60rx8owgQz9P4dDJRmN|1||1|1|1760574074381|............. ++|4106|100|NEMA|roKgWqY95V3mXMRzyAjmKj7bLjexpJPvaGDBw826|1||1|1|1760573930336|............. ++|4110|111|NEMA|o9vbeQlLMVg8j5dq4keggbANxZpEmnXzwYKO1ar2|1||1|1|1760573755129|............. ++|4767|101|NEMA|nJL5lPMwBx23YpqRe0rlpw7damXvWVbOrD4gNzy8|1||1|1|1760573661772|............. ++|3702|99|NEMA|E6Kg9oDnLWyzPRMva7vr5j7Jxp4VG58qO2w1lZYe|1||1|1|1760573738525|............. ++|4139|125|NEMA|1JMYvnx2RzKEo4aWQ7DmmZAL8yZV3m9NBePXbrdj|1||1|1|1760573661372|............. ++|4142|123|NEMA|3JjOWdylwgNLzxVab7NEEKkZ2vG64rq8PEB5QmDo|1||1|1|1760573958972|............. ++|4147|124|NEMA|Z5KyJe9nEg1QNbWlX0wWWD0oDjBLdqzR83VGv624|1||1|1|1760573959532|............. ++|4151|16B|NEMA|PjLblDgRBO6WQqnxmkJ5560Jv3ewZN4p5a89yKdY|1||1|1|1760574072383|............. ++|4202|74|NEMA|K94XLav1glVRnyQ6r01BPakme3YJwBxM5oOzdP2j|1||1|1|1760574151726|............. ++|4204|72|NEMA|d5xjWYMwEJon6rLlK7yBEKAqgV4DaOeNB9ZX3Gzb|1||1|1|1760574157590|............. ++|4208|68|NEMA|Z5KyJe9nEg1QNbWlX0wW4m0oDjBLdqzR83VGv624|1||1|1|1760574157798|............. ++|4215|48|NEMA|zdQO8GwxDqjRgP4137Y15q7NyKlpem2nL65rvVJY|1||1|1|1760573631122|............. ++|3710|1|NEMA|nJL5lPMwBx23YpqRe0rlKv7damXvWVbOrD4gNzy8|1||1|1|1760573884153|............. ++|3711|97|NEMA|52dD6ZlV1QaOpRBmbAqKGMkKnGzWMLj4eJq38Pgo|1||1|1|1760573761425|............. ++|3726|2|NEMA|XMBbew5z4ELrZa2mRAd5dW08vPN6gy3DdVYlpKjq|1||1|1|1760573806537|............. ++|4094|104|NEMA|zdQO8GwxDqjRgP4137Y1V67NyKlpem2nL65rvVJY|1||1|1|1760573592913|............. ++|4765|81|NEMA|EjgWGnXaLy9opPOz20n64V086BlYM3w1deVQvbKr|1||1|1|1760573653766|............. ++|3607|28|NEMA|d5xjWYMwEJon6rLlK7yBlKAqgV4DaOeNB9ZX3Gzb|1||1|1|1760574104424|............. ++|4758|109|NEMA|DbQY6zyveZRwK5drV0Z98bAjoE4XJM83N9xl2nWq|1||1|1|1760573642819|............. ++|2715|52|NEMA|BaY3Xpy1EbKGjLq2O7mG9o0rx8owgQz9P4dDJRmN|1||1|1|1760574035453|............. ++|3881|71|NEMA|dz4ojlpP85JMgDLZWkQOJzAaKYqQexEr62GXRV1y|1||1|1|1760573584379|............. ++|3715|13|NEMA|2O14VBzl8aDmWdNw3A516bAGyZ5qLJoEMpj6R9ng|1||1|1|1760573902786|............. ++|3616|36|NEMA|3a5oqJN1bgnx4Ol9dk86BZAByE6jQ8mKDWMpGrLV|1||1|1|1760574129561|............. ++|3742|7|NEMA|zrR51V2ajQ9ZLygPKkEm1pkYDq38xOJolENBXGnv|1||1|1|1760573834071|............. ++|3717|80|NEMA|3a5oqJN1bgnx4Ol9dk869ZAByE6jQ8mKDWMpGrLV|1||1|1|1760573907867|............. ++|3705|91|NEMA|eod9aRWLVl34Gx1Dn7VoNbA2rz6qjgmpEXwQJN5Z|1||1|1|1760573742313|............. ++|3630|55|NEMA|o9vbeQlLMVg8j5dq4kegdRANxZpEmnXzwYKO1ar2|1||1|1|1760574119477|............. ++|3865|41|NEMA|52dD6ZlV1QaOpRBmbAqKvQkKnGzWMLj4eJq38Pgo|1||1|1|1760573559802|............. ++|3632|119|NEMA|OzNMgZ9n43qPbjXmy7zWWaA2DKdYvW5e6pxGRrVa|1||1|1|1760574121075|............. ++|3684|39|NEMA|Nzp2OoJlqn6r1ZgvdA3GRKAabBwP5G4eE3RQmyxD|1||1|1|1760574128250|............. ++|4096|114|NEMA|pE5X8NQPaow6vlOZxk6ggg7q42ezGBMyWgDVjR3L|1|{"intervals":[{"cct":3000,"value":0,"end_time":"20:00","start_time":"13:00"},{"cct":3000,"value":10,"end_time":"05:30","start_time":"20:00"},{"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|1760573922713|............. ++|4764|116|NEMA|m6EYyZoJ4gWexdjVPARNNwARDOq9wv2N5XzKGplr|1|{"intervals":[{"cct":3000,"value":0,"end_time":"20:00","start_time":"13:00"},{"cct":3000,"value":10,"end_time":"05:30","start_time":"20:00"},{"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|1760573653574|............. ++|4101|115|NEMA|6lQGaY9RDywdVzObj0P11OkPg4NBn3exEK51LWZq|1|{"intervals":[{"cct":3000,"value":0,"end_time":"16:20","start_time":"13:00"},{"cct":3000,"value":10,"end_time":"06:50","start_time":"16:20"},{"cct":3000,"value":0,"end_time":"13:00","start_time":"06: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}|1|1|1760573929473|............. diff --git a/RVO16/databases/nodes_original/nodes_original.table b/RVO16/databases/nodes_original/nodes_original.table new file mode 100755 index 0000000..33435e9 --- /dev/null +++ b/RVO16/databases/nodes_original/nodes_original.table @@ -0,0 +1 @@ +[{"3831": "JzwxZXOvDj1bVrN4nkWwJKk8qdyBl3MRKLpGPgaQ"}, {"3739": "5dBNwRp9graYJxZn409wGV7lVov1b2QLPDqGm6XK"}, {"3801": "roKgWqY95V3mXMRzyAjmrz7bLjexpJPvaGDBw826"}, {"3659": "ZmRwd93QL4gaezxEbAxW2O71prn2XjlPvGyqJ6BO"}, {"3861": "gYbDLqlyZVoRerQpB72rGp7WJnwM5z24POKa8Exj"}, {"3870": "B5EoxeMVp4zwr8nqW0GjBxARjvD1PNamOGbLg63Z"}, {"4107": "rDbQ84xzwgdqEoPm3kbJErk9anOZY1RXyBv2LVM6"}, {"4766": "zrR51V2ajQ9ZLygPKkEmPpkYDq38xOJolENBXGnv"}, {"3593": "apKVJBwOyrP35m2lv7KzEKkYXbeWNd64En9GxRqg"}, {"3755": "wvKJdZML6mXP4DzWBAXWx17jxNloa5g23Ve9Y1ry"}, {"3697": "PLBJzmK1r3Gynd6OW0gGKo0e5wV4vx9bDEqNgYR8"}, {"3712": "WlVJBygjDZMeKX3vnAMzGQ08NqdmG2x1Y69LQ4P5"}, {"3724": "zdQO8GwxDqjRgP4137Y1xq7NyKlpem2nL65rvVJY"}, {"4370": "gRoJEyXVx4qD9er287LPwm7wBzGldaPjLWQKm3Mv"}, {"4372": "PjLblDgRBO6WQqnxmkJ5150Jv3ewZN4p5a89yKdY"}, {"4373": "aw4eELG2DlPMdn1JW0B1zbAqQXOZRN3xB5yp8VKr"}, {"3594": "DbQY6zyveZRwK5drV0Z9lLAjoE4XJM83N9xl2nWq"}, {"3603": "5dBNwRp9graYJxZn409wRV7lVov1b2QLPDqGm6XK"}, {"3605": "WlVJBygjDZMeKX3vnAMzWQ08NqdmG2x1Y69LQ4P5"}, {"3963": "1JMYvnx2RzKEo4aWQ7Dm9GAL8yZV3m9NBePXbrdj"}, {"3608": "m6EYyZoJ4gWexdjVPARNzEARDOq9wv2N5XzKGplr"}, {"3609": "Z5KyJe9nEg1QNbWlX0wWmm0oDjBLdqzR83VGv624"}, {"3610": "g9OxBZ5KRwNznlY6pAp64dkWXvjdEL4eGQobMDy2"}, {"3614": "d9x2V5LGYBzXp4mMRAOBPq7PloaqJwnQj6DgrNe3"}, {"4768": "3JjOWdylwgNLzxVab7NEPBkZ2vG64rq8PEB5QmDo"}, {"3618": "JX1ObgmqGZ54DMyYL7a95d7EVdve38WKRzwjNrQ9"}, {"2736": "RvmwNz8QPblKp41GD7lDmV7JrLVYoBO92dMegn6W"}, {"3620": "ZmRwd93QL4gaezxEbAxW1O71prn2XjlPvGyqJ6BO"}, {"3623": "B5EoxeMVp4zwr8nqW0GjexARjvD1PNamOGbLg63Z"}, {"3624": "PjLblDgRBO6WQqnxmkJ5w50Jv3ewZN4p5a89yKdY"}, {"3626": "OzNMgZ9n43qPbjXmy7zWGdA2DKdYvW5e6pxGRrVa"}, {"3627": "dz4ojlpP85JMgDLZWkQO1zAaKYqQexEr62GXRV1y"}, {"3732": "RO8rjaBDy21qPQJzW7oDK9ApK3xmNleVZg9Ed4Gw"}, {"3631": "g9OxBZ5KRwNznlY6pAp66EkWXvjdEL4eGQobMDy2"}, {"3637": "RO8rjaBDy21qPQJzW7oDDOApK3xmNleVZg9Ed4Gw"}, {"3638": "RvmwNz8QPblKp41GD7lDDZ7JrLVYoBO92dMegn6W"}, {"4117": "JX1ObgmqGZ54DMyYL7a99m7EVdve38WKRzwjNrQ9"}, {"3685": "eod9aRWLVl34Gx1Dn7VoYMA2rz6qjgmpEXwQJN5Z"}, {"3686": "EjgWGnXaLy9opPOz20n6gV086BlYM3w1deVQvbKr"}, {"3688": "wvKJdZML6mXP4DzWBAXWO17jxNloa5g23Ve9Y1ry"}, {"3692": "K94XLav1glVRnyQ6r01BVakme3YJwBxM5oOzdP2j"}, {"3694": "eod9aRWLVl34Gx1Dn7VoNMA2rz6qjgmpEXwQJN5Z"}, {"3696": "52dD6ZlV1QaOpRBmbAqKGQkKnGzWMLj4eJq38Pgo"}, {"3698": "6lQGaY9RDywdVzObj0P1ZykPg4NBn3exEK51LWZq"}, {"3699": "pE5X8NQPaow6vlOZxk6gYy7q42ezGBMyWgDVjR3L"}, {"3700": "OzNMgZ9n43qPbjXmy7zWOdA2DKdYvW5e6pxGRrVa"}, {"3701": "JX1ObgmqGZ54DMyYL7a9Jd7EVdve38WKRzwjNrQ9"}, {"2647": "rDbQ84xzwgdqEoPm3kbJEdk9anOZY1RXyBv2LVM6"}, {"3703": "g9OxBZ5KRwNznlY6pAp6bdkWXvjdEL4eGQobMDy2"}, {"2613": "RvmwNz8QPblKp41GD7lD4V7JrLVYoBO92dMegn6W"}, {"3706": "E6Kg9oDnLWyzPRMva7vr5x7Jxp4VG58qO2w1lZYe"}, {"3707": "RO8rjaBDy21qPQJzW7oDm9ApK3xmNleVZg9Ed4Gw"}, {"3708": "JzwxZXOvDj1bVrN4nkWweKk8qdyBl3MRKLpGPgaQ"}, {"3709": "m6EYyZoJ4gWexdjVPARNaEARDOq9wv2N5XzKGplr"}, {"3713": "gP1eOZVj3Q9lv5aDEk4E1Q7rdpqW8yLm2BbKzJxM"}, {"3716": "PLBJzmK1r3Gynd6OW0gGKP0e5wV4vx9bDEqNgYR8"}, {"3719": "Nzp2OoJlqn6r1ZgvdA3GBjAabBwP5G4eE3RQmyxD"}, {"3723": "3a5oqJN1bgnx4Ol9dk869wAByE6jQ8mKDWMpGrLV"}, {"3725": "Nzp2OoJlqn6r1ZgvdA3GBKAabBwP5G4eE3RQmyxD"}, {"3727": "DbQY6zyveZRwK5drV0Z9ZLAjoE4XJM83N9xl2nWq"}, {"3729": "apKVJBwOyrP35m2lv7KzWKkYXbeWNd64En9GxRqg"}, {"3731": "BaY3Xpy1EbKGjLq2O7mGKo0rx8owgQz9P4dDJRmN"}, {"3880": "6lQGaY9RDywdVzObj0P1oykPg4NBn3exEK51LWZq"}, {"3219": "pE5X8NQPaow6vlOZxk6gMy7q42ezGBMyWgDVjR3L"}, {"3735": "wvKJdZML6mXP4DzWBAXWxB7jxNloa5g23Ve9Y1ry"}, {"3736": "o9vbeQlLMVg8j5dq4kegbRANxZpEmnXzwYKO1ar2"}, {"3737": "ZmRwd93QL4gaezxEbAxW2X71prn2XjlPvGyqJ6BO"}, {"3743": "gYbDLqlyZVoRerQpB72r8p7WJnwM5z24POKa8Exj"}, {"3746": "2O14VBzl8aDmWdNw3A513bAGyZ5qLJoEMpj6R9ng"}, {"3763": "gP1eOZVj3Q9lv5aDEk4EMQ7rdpqW8yLm2BbKzJxM"}, {"3490": "3JjOWdylwgNLzxVab7NEaBkZ2vG64rq8PEB5QmDo"}, {"3824": "rDbQ84xzwgdqEoPm3kbJPdk9anOZY1RXyBv2LVM6"}, {"3825": "PLBJzmK1r3Gynd6OW0gG2P0e5wV4vx9bDEqNgYR8"}, {"3830": "d9x2V5LGYBzXp4mMRAOBmq7PloaqJwnQj6DgrNe3"}, {"3842": "EjgWGnXaLy9opPOz20n64m086BlYM3w1deVQvbKr"}, {"3848": "nJL5lPMwBx23YpqRe0rlpv7damXvWVbOrD4gNzy8"}, {"3850": "roKgWqY95V3mXMRzyAjmKz7bLjexpJPvaGDBw826"}, {"3964": "aw4eELG2DlPMdn1JW0B1MbAqQXOZRN3xB5yp8VKr"}, {"3862": "nJL5lPMwBx23YpqRe0rlqv7damXvWVbOrD4gNzy8"}, {"3867": "1JMYvnx2RzKEo4aWQ7DmGGAL8yZV3m9NBePXbrdj"}, {"3869": "gRoJEyXVx4qD9er287LP4m7wBzGldaPjLWQKm3Mv"}, {"3871": "E6Kg9oDnLWyzPRMva7vrWx7Jxp4VG58qO2w1lZYe"}, {"3876": "XMBbew5z4ELrZa2mRAd5ZW08vPN6gy3DdVYlpKjq"}, {"3722": "WlVJBygjDZMeKX3vnAMzRj08NqdmG2x1Y69LQ4P5"}, {"4090": "apKVJBwOyrP35m2lv7Kzz5kYXbeWNd64En9GxRqg"}, {"4091": "XMBbew5z4ELrZa2mRAd53V08vPN6gy3DdVYlpKjq"}, {"4092": "JzwxZXOvDj1bVrN4nkWwwNk8qdyBl3MRKLpGPgaQ"}, {"4095": "5dBNwRp9graYJxZn409wNQ7lVov1b2QLPDqGm6XK"}, {"4097": "gP1eOZVj3Q9lv5aDEk4EEM7rdpqW8yLm2BbKzJxM"}, {"4099": "2O14VBzl8aDmWdNw3A5119AGyZ5qLJoEMpj6R9ng"}, {"4102": "zrR51V2ajQ9ZLygPKkEmMxkYDq38xOJolENBXGnv"}, {"4104": "gYbDLqlyZVoRerQpB72rML7WJnwM5z24POKa8Exj"}, {"3115": "BaY3Xpy1EbKGjLq2O7mGa60rx8owgQz9P4dDJRmN"}, {"4106": "roKgWqY95V3mXMRzyAjmKj7bLjexpJPvaGDBw826"}, {"4110": "o9vbeQlLMVg8j5dq4keggbANxZpEmnXzwYKO1ar2"}, {"4767": "nJL5lPMwBx23YpqRe0rlpw7damXvWVbOrD4gNzy8"}, {"3702": "E6Kg9oDnLWyzPRMva7vr5j7Jxp4VG58qO2w1lZYe"}, {"4139": "1JMYvnx2RzKEo4aWQ7DmmZAL8yZV3m9NBePXbrdj"}, {"4142": "3JjOWdylwgNLzxVab7NEEKkZ2vG64rq8PEB5QmDo"}, {"4147": "Z5KyJe9nEg1QNbWlX0wWWD0oDjBLdqzR83VGv624"}, {"4151": "PjLblDgRBO6WQqnxmkJ5560Jv3ewZN4p5a89yKdY"}, {"4202": "K94XLav1glVRnyQ6r01BPakme3YJwBxM5oOzdP2j"}, {"4204": "d5xjWYMwEJon6rLlK7yBEKAqgV4DaOeNB9ZX3Gzb"}, {"4208": "Z5KyJe9nEg1QNbWlX0wW4m0oDjBLdqzR83VGv624"}, {"4215": "zdQO8GwxDqjRgP4137Y15q7NyKlpem2nL65rvVJY"}, {"3710": "nJL5lPMwBx23YpqRe0rlKv7damXvWVbOrD4gNzy8"}, {"3711": "52dD6ZlV1QaOpRBmbAqKGMkKnGzWMLj4eJq38Pgo"}, {"3726": "XMBbew5z4ELrZa2mRAd5dW08vPN6gy3DdVYlpKjq"}, {"4094": "zdQO8GwxDqjRgP4137Y1V67NyKlpem2nL65rvVJY"}, {"4765": "EjgWGnXaLy9opPOz20n64V086BlYM3w1deVQvbKr"}, {"3607": "d5xjWYMwEJon6rLlK7yBlKAqgV4DaOeNB9ZX3Gzb"}, {"4758": "DbQY6zyveZRwK5drV0Z98bAjoE4XJM83N9xl2nWq"}, {"2715": "BaY3Xpy1EbKGjLq2O7mG9o0rx8owgQz9P4dDJRmN"}, {"3881": "dz4ojlpP85JMgDLZWkQOJzAaKYqQexEr62GXRV1y"}, {"3715": "2O14VBzl8aDmWdNw3A516bAGyZ5qLJoEMpj6R9ng"}, {"3616": "3a5oqJN1bgnx4Ol9dk86BZAByE6jQ8mKDWMpGrLV"}, {"3742": "zrR51V2ajQ9ZLygPKkEm1pkYDq38xOJolENBXGnv"}, {"3717": "3a5oqJN1bgnx4Ol9dk869ZAByE6jQ8mKDWMpGrLV"}, {"3705": "eod9aRWLVl34Gx1Dn7VoNbA2rz6qjgmpEXwQJN5Z"}, {"3630": "o9vbeQlLMVg8j5dq4kegdRANxZpEmnXzwYKO1ar2"}, {"3865": "52dD6ZlV1QaOpRBmbAqKvQkKnGzWMLj4eJq38Pgo"}, {"3632": "OzNMgZ9n43qPbjXmy7zWWaA2DKdYvW5e6pxGRrVa"}, {"3684": "Nzp2OoJlqn6r1ZgvdA3GRKAabBwP5G4eE3RQmyxD"}, {"4096": "pE5X8NQPaow6vlOZxk6ggg7q42ezGBMyWgDVjR3L"}, {"4764": "m6EYyZoJ4gWexdjVPARNNwARDOq9wv2N5XzKGplr"}, {"4101": "6lQGaY9RDywdVzObj0P11OkPg4NBn3exEK51LWZq"}] \ No newline at end of file diff --git a/RVO16/databases/notifications.table b/RVO16/databases/notifications.table new file mode 100755 index 0000000..f7c96cb --- /dev/null +++ b/RVO16/databases/notifications.table @@ -0,0 +1,41 @@ +key:string|weight:string|sk:string|en:string ++|switching_profile_point_applied_to_line|INFORMATIONAL|Aplikovaný bod spínacieho profilu na línií č. ${line} : ${value}|Switching profile point applied to line no. ${line} : ${value}|............... ++|dusk_has_occured|INFORMATIONAL|Nastal súmrak: ${value}|Dusk has occured: ${value}|............... ++|dawn_has_occured|INFORMATIONAL|Nastal úsvit: ${value}|Dawn has occured: ${value}|............... ++|dimming_profile_was_successfully_received_by_node|NOTICE|Stmievací profil bol úspešne prijatý nodom č. ${node}|Dimming profile was successfully received by node no. ${node}|............... ++|master_node_is_responding_again|NOTICE|Master node začal znovu odpovedať|Master node is responding again|............... ++|command_was_sent_from_terminal_interface|DEBUG|Z terminálu bol odoslaný príkaz|A command was sent from terminal interface|............... ++|master_node_is_not_responding|ALERT|Master node neodpovedá|Master node is not responding|............... ++|configuration_of_dimming_profile_to_node_failed|ALERT|Konfigurácia stmievacieho profilu pre node č. ${node} zlyhala|Configuration of dimming profile to node no. ${node} has failed|............... ++|circuit_breaker_was_turned_on_line|NOTICE|Zapnutie ističa na línii č. ${line}|Circuit breaker was turned on - line no. ${line}|............... ++|circuit_breaker_was_turned_off_line|ERROR|Vypnutie ističa na línií č. ${line}|Circuit breaker was turned off - line no. ${line}|............... ++|dimming_profile_was_processed_for_node|INFORMATIONAL|Stmievací profil bol spracovaný pre node č. ${node}|Dimming profile was processed for node no. ${node}|............... ++|switching_profile_was_processed_for_line|INFORMATIONAL|Spínací profil bol spracovaný pre líniu č. ${line}|Switching profile was processed for line no. ${line}|............... ++|thermometer_is_not_responding|WARNING|Teplomer neodpovedá|Thermometer is not responding|............... ++|thermometer_is_responding_again|NOTICE|Teplomer znovu odpovedá|Thermometer is responding again|............... ++|thermometer_sends_invalid_data|WARNING|Teplomer posiela neplatné hodnoty|Thermometer sends invalid data|............... ++|main_switch_has_been_turned_off|CRITICAL|Hlavný vypínač bol vypnutý|Main switch has been turned off|............... ++|main_switch_has_been_turned_on|NOTICE|Hlavný vypínač bol zapnutý|Main switch has been turned on|............... ++|power_supply_has_disconnected_input|ALERT|Napájací zdroj nemá napätie na vstupe|Power supply has disconnected input|............... ++|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_main_open|NOTICE|Hlavné dvere boli otvorené|Main door has been opened|............... ++|door_em_open|NOTICE|Dvere silovej časti boli otvorené|Power door has been opened|............... ++|door_main_open_without_permission|WARNING|Hlavné dvere boli otvorené bez povolenia - zapnutá siréna|Main door has been opened without permission - alarm is on|............... ++|door_em_open_without_permission|WARNING|Dvere silovej časti boli otvorené bez povolenia|Power door has been opened without permission|............... ++|door_main_close|NOTICE|Hlavné dvere boli zatvorené|Main door has been closed|............... ++|door_em_close|NOTICE|Dvere silovej časti boli zatvorené|Power door has been closed|............... ++|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|............... ++|electrometer_ok|NOTICE|Elektromer znovu odpovedá|Electrometer is responding again|............... ++|no_voltage_on_phase|CRITICAL|Na fáze č. ${phase} nie je napätie|No voltage detected on phase no. ${phase}|............... ++|voltage_on_phase_restored|NOTICE|Napätie na fáze č. ${phase} bolo obnovené|Voltage on phase no. ${phase} has been restored|............... ++|flow_start|NOTICE|FLOW bol spustený|FLOW has been started |............... ++|twilight_sensor_nok|ERROR|Sensor súmraku neodpovedá|Twilight sensor is not responding|............... ++|twilight_sensor_ok|NOTICE|Sensor súmraku znovu odpovedá|Twilight sensor is responding again|............... ++|lamps_have_turned_on|NOTICE|Lampy sa zapli|Lamps have turned on|............... ++|lamps_have_turned_off|NOTICE|Lampy sa vypli|Lamps have turned off|............... ++|flow_restart|NOTICE|FLOW bol reštartovaný|FLOW has been restarted|............... ++|nodes_db_changed|NOTICE|Zmena v node databáze|Node db has changed|............... diff --git a/RVO16/databases/pins.table b/RVO16/databases/pins.table new file mode 100755 index 0000000..0eb3d05 --- /dev/null +++ b/RVO16/databases/pins.table @@ -0,0 +1,14 @@ +pin:string|type:string|line:number +*|input1_01|door_condition|0|........... +*|input1_02|rotary_switch_state|0|........... +*|input1_03|rotary_switch_state|0|........... +*|input1_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/RVO16/databases/relays.table b/RVO16/databases/relays.table new file mode 100755 index 0000000..8e8acf1 --- /dev/null +++ b/RVO16/databases/relays.table @@ -0,0 +1,5 @@ +line:number|tbname:string|contactor:number|profile:string ++|0|PLBJzmK1r3Gynd6OW0gKRo0e5wV4vx9bDEqNgYR8|1||........... ++|1|5dBNwRp9graYJxZn409wv37lVov1b2QLPDqGm6XK|9|{"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|zrR51V2ajQ9ZLygPKkEmGJkYDq38xOJolENBXGnv|9|{"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|BaY3Xpy1EbKGjLq2O7mG3p0rx8owgQz9P4dDJRmN|9|{"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/RVO16/databases/settings.table b/RVO16/databases/settings.table new file mode 100755 index 0000000..0c03756 --- /dev/null +++ b/RVO16/databases/settings.table @@ -0,0 +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|project_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|cloud_topic:string|has_main_switch:boolean|daily_report:boolean|send_changed_node_numbers:boolean ++|rvo_senica_16_10.0.0.131|en|28.569E9C0E0000|48.70826502|17.28455203|192.168.252.1|rvo_senica_16_10.0.0.131|6EANzPOaNVolqCTE4iXN|1883|0|67|unipi|ttyUSB0|1|20|5|6|3|u131|0|1|1|................................................... diff --git a/RVO16/databases/tbdata.nosql b/RVO16/databases/tbdata.nosql new file mode 100755 index 0000000..e69de29 diff --git a/RVO16/databases/tbdatacloud.nosql b/RVO16/databases/tbdatacloud.nosql new file mode 100755 index 0000000..e69de29 diff --git a/RVO16/databases/total_energy.js b/RVO16/databases/total_energy.js new file mode 100755 index 0000000..dde340e --- /dev/null +++ b/RVO16/databases/total_energy.js @@ -0,0 +1,38 @@ +//key is rvo_number, value is max energy when lamps are on +const total_energy = { + 1: 580, + 2: 1100, + 3: 3700, + 4: 4100, + 7: 360, + 12: 1700, + 13: 5400, + 14: 440, + 15: 6100, + 16: 4800, + 20: 1600, + 21: 1000, + 22: 2600, + 23: 1000, + 25: 2600, + 33: 240, + 34: 4000, + 35: 2700, + 36: 820, + 37: 1400, + 35: 3500, + 39: 1170, + 41: 740, + 42: 660, + 43: 4900, + 45: 930, + 46: 700, + 47: 1100, + 48: 1500, + 50: 3200, + 53: 1250, + 55: 1000, + 56: 5500 +} + +module.exports = total_energy; diff --git a/RVO16/debug.js b/RVO16/debug.js new file mode 100755 index 0000000..9818194 --- /dev/null +++ b/RVO16/debug.js @@ -0,0 +1,16 @@ +// =================================================== +// FOR DEVELOPMENT +// Total.js - framework for Node.js platform +// https://www.totaljs.com +// =================================================== + +const options = {}; + +// options.ip = '127.0.0.1'; +// options.port = parseInt(process.argv[2]); +// options.config = { name: 'Total.js' }; +// options.sleep = 3000; +// options.inspector = 9229; +// options.watch = ['private']; + +require('total.js/debug')(options); \ No newline at end of file diff --git a/RVO16/err.txt b/RVO16/err.txt new file mode 100755 index 0000000..1e36701 --- /dev/null +++ b/RVO16/err.txt @@ -0,0 +1,33 @@ +[2025-09-23T13:44:13.406] [ERROR] errLogs - uncaughtException: Cannot read property 'getHours' of undefined +[2025-09-23T13:44:13.407] [ERROR] errLogs - TypeError: Cannot read property 'getHours' of undefined + at Timeout.emptyReportToSend [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T13:44:13.408] [ERROR] errLogs - uncaughtException: Cannot read property 'getHours' of undefined +[2025-09-23T13:44:13.408] [ERROR] errLogs - TypeError: Cannot read property 'getHours' of undefined + at Timeout.emptyReportToSend [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T13:44:13.418] [ERROR] errLogs - uncaughtException: Cannot read property 'getHours' of undefined +[2025-09-23T13:44:13.418] [ERROR] errLogs - TypeError: Cannot read property 'getHours' of undefined + at Timeout.emptyReportToSend [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T13:44:19.196] [ERROR] errLogs - uncaughtException: date.getHours is not a function +[2025-09-23T13:44:19.197] [ERROR] errLogs - TypeError: date.getHours is not a function + at emptyReportToSend (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at Timeout.dailyReportCheck [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1351:5) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T13:44:19.197] [ERROR] errLogs - uncaughtException: date.getHours is not a function +[2025-09-23T13:44:19.198] [ERROR] errLogs - TypeError: date.getHours is not a function + at emptyReportToSend (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at Timeout.dailyReportCheck [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1351:5) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T13:44:19.201] [ERROR] errLogs - uncaughtException: date.getHours is not a function +[2025-09-23T13:44:19.202] [ERROR] errLogs - TypeError: date.getHours is not a function + at emptyReportToSend (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at Timeout.dailyReportCheck [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1351:5) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) diff --git a/RVO16/flow/cloudmqttconnect.js b/RVO16/flow/cloudmqttconnect.js new file mode 100755 index 0000000..b03491f --- /dev/null +++ b/RVO16/flow/cloudmqttconnect.js @@ -0,0 +1,357 @@ +exports.id = 'cloudmqttconnect'; +exports.title = 'Cloud connect mqtt'; +exports.group = 'MQTT'; +exports.color = '#888600'; +exports.version = '1.0.2'; +exports.icon = 'sign-out'; +exports.input = 2; +exports.output = 2; +exports.options = { host: 'tb-stage.worksys.io', port: 1883, clientid: "", username: "" }; + +exports.html = `
+
+
+
Hostname or IP address (if not empty - setting will override db setting)
+
+
+
Port
+
+
+
+
+
@(Client id)
+
+
+
topic
+
+
+
`; + + + +const { promisifyBuilder } = require('./helper/db_helper'); +const fs = require('fs'); +const mqtt = require('mqtt'); +const nosql = NOSQL('tbdatacloud'); + +const SEND_TO = { + debug: 0, + rpcCall: 1, +} + +//CONFIG +let saveTelemetryOnError = true;//backup_on_failure overrides this value +//------------------------ + +const noSqlFileSizeLimit = 4194304;//use 5MB - 4194304 +let insertNoSqlCounter = 0; +let insertBackupNoSqlCounter = 0; +let processingData = false; + +let backup_on_failure = true;//== saveTelemetryOnError - create backup client send failure +let restore_from_backup = 50; //how many rows process at once? +let restore_backup_wait = 3;//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; + + +exports.install = function(instance) { + + var client; + var opts; + var clientReady = false; + + let o = {}; //options + + function main() { + loadSettings(); + } + + //set opts according to db settings + function loadSettings() { + + o = instance.options; + if (!o.topic) o.topic = FLOW.GLOBALS.settings.cloud_topic; + + opts = { + host: o.host, + port: o.port, + clientId: o.clientid, + username: o.username, + rejectUnauthorized: false, + resubscribe: false + }; + + console.log("wsmqttpublich -> loadSettings from instance.options", o); + + if (!o.topic) { + instance.status("Not configured", "white"); + console.log("Cloud mqtt connect: no topic selected"); + return; + } + + connectToTbServer(); + } + + function connectToTbServer() { + var url = "mqtt://" + opts.host + ":" + opts.port; + console.log("MQTT URL: ", url); + + client = mqtt.connect(url, opts); + + client.on('connect', function() { + client.subscribe(`${o.topic}_backward`, (err) => { + if (!err) { + console.log("MQTT subscribed"); + } + }); + instance.status("Connected", "green"); + clientReady = true; + sendClientError = true; + }); + + client.on('reconnect', function() { + instance.status("Reconnecting", "yellow"); + clientReady = false; + }); + + client.on('message', function(topic, message) { + // message is type of buffer + message = message.toString(); + if (message[0] === '{') { + TRY(function() { + + message = JSON.parse(message); + if (message.hasOwnProperty("device") && message.hasOwnProperty("data") && message.data.hasOwnProperty("id")) { + client.publish(`${o.topic}_forward`, `{"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 } }); + } + + }, () => instance.debug('MQTT: Error parsing data', message)); + } + + instance.send(SEND_TO.rpcCall, { "topic": o.topic, "content": message }); + }); + + client.on('close', function() { + clientReady = false; + + instance.status("Disconnected", "red"); + instance.send(SEND_TO.debug, { "message": "Client CLOSE signal received !" }); + }); + + client.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) { + console.log('MQTT client error', err); + sendClientError = false; + } + clientReady = false; + }); + + } + + + instance.on('0', function(data) { + + if (clientReady) { + //do we have some data in backup file? if any, process data from database + if (saveTelemetryOnError) { + //read telemetry data and send back to server + if (!processingData) processDataFromDatabase(); + } + + let stringifiedJson = JSON.stringify(data.data) + client.publish(`${o.topic}_forward`, stringifiedJson, { qos: 1 }); + } + 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 (saveTelemetryOnError && o.topic) { + //create new file from tbdata.nosql, if file size exceeds given limit, and clear tbdata.nosql + makeBackupFromDbFile(); + + //write to tb + data.data.id = UID(); + nosql.insert(data.data); + } + } + }); + + instance.on("1", _ => { + main(); + }) + + instance.close = function(done) { + if (clientReady) { + client.end(); + } + }; + + + function getDbBackupFileCounter(type) { + var files = fs.readdirSync(__dirname + "/../databases"); + + let counter = 0; + for (var i = 0; i < files.length; i++) { + + if (files[i] == "tbdatacloud.nosql") continue; + + if (files[i].endsWith(".nosql")) { + + let pos = files[i].indexOf("."); + if (pos > -1) { + + let fileCounter = counter; + let firstDigit = files[i].slice(0, pos); + + fileCounter = parseInt(firstDigit); + if (isNaN(fileCounter)) fileCounter = 0; + //console.log("getDbBackupFileCounter digit:", files[i], firstDigit, fileCounter, isNaN(fileCounter), type); + + if (type == "max") { + if (fileCounter > counter) { + counter = fileCounter; + } + } + else if (type == "min") { + if (counter == 0) counter = fileCounter; + + if (fileCounter < counter) { + counter = fileCounter; + } + } + } + } + + } + + if (type == "max") counter++; + + return counter; + } + + const makeBackupFromDbFile = async () => { + + if (!saveTelemetryOnError) return; + + //to avoid large file: tbdata.nosql + + //init value is 0! + if (insertNoSqlCounter > 0) { + --insertNoSqlCounter; + return; + } + + insertNoSqlCounter = 100; + + let source = __dirname + "/../databases/tbdatacloud.nosql"; + + var stats = fs.statSync(source); + var fileSizeInBytes = stats.size; + + if (fileSizeInBytes > noSqlFileSizeLimit) { + + let counter = 1; + counter = getDbBackupFileCounter("max"); + + let destination = __dirname + "/../databases/" + counter + "." + "tbdatacloud.nosql"; + + //make backup file + fs.copyFileSync(source, destination); + //fs.renameSync(p, p + "." + counter); + + //clear tbdata.nosql + fs.writeFileSync(source, ""); + fs.truncateSync(source, 0); + + } + } + + const processDataFromDatabase = async () => { + + if (restore_from_backup <= 0) return; + + //calculate diff + const now = new Date(); + let currentTime = now.getTime(); + let diff = currentTime - lastRestoreTime; + + if ((diff / 1000) < restore_backup_wait) { + //console.log("*********restore_backup_wait", diff, restore_backup_wait); + return; + } + + processingData = true; + + //get filename to process + let counter = getDbBackupFileCounter("min"); + + //we have some backup files + let dataBase = 'tbdata'; + + var nosql; + if (counter == 0) dataBase = 'tbdatacloud'; + else dataBase = counter + "." + 'tbdatacloud'; + + nosql = NOSQL(dataBase); + + //select all data - use limit restore_from_backup + let records = await promisifyBuilder(nosql.find().take(restore_from_backup)); + + for (let i = 0; i < records.length; i++) { + if (clientReady) { + + let item = records[i]; + let id = item.id; + + if (id !== undefined) { + //console.log("------------processDataFromDatabase - remove", id, dataBase, i); + + try { + + let message = JSON.parse(JSON.stringify(item)); + delete message.id; + client.publish(`${o.topic}_forward`, JSON.stringify(message), { qos: 1 }); + + //remove from database + await promisifyBuilder(nosql.remove().where("id", id)); + + } catch (error) { + //process error + console.log("processDataFromDatabase", error); + } + + } + + } + else { + processingData = false; + return; + } + } + + if (records.length > 0) { + //clean backup file + if (counter > 0) nosql.clean(); + } + + //no data in db, remove + if (records.length == 0) { + if (counter > 0) nosql.drop(); + } + + const d = new Date(); + lastRestoreTime = d.getTime(); + + processingData = false; + + } + + instance.on('options', main); + +}; diff --git a/RVO16/flow/cmd_manager.js b/RVO16/flow/cmd_manager.js new file mode 100755 index 0000000..ba4fc47 --- /dev/null +++ b/RVO16/flow/cmd_manager.js @@ -0,0 +1,3071 @@ +exports.id = 'cmd_manager'; +exports.title = 'CMD Manager'; +exports.group = 'Worksys'; +exports.color = '#5D9CEC'; +exports.version = '0.0.3'; +exports.output = ['red', 'blue', 'yellow', 'blue', 'white', 'green']; +exports.input = 3; +exports.icon = 'cloud-upload'; + +exports.html = ` +
+
+
+
RPC - run RPC calls

+
+
+
@(User)
+
+
+
@(Password)
+
+
+
@(My edge)
+
+
+
+`; +exports.readme = `Manager for CMD calls`; + + +exports.install = function(instance) { + + 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, isEmptyObject, emptyJsObject, writeToFile, addToArrayIfUnique } = require('./helper/utils'); + const bitwise = require('bitwise'); + + var SunCalc = require('./helper/suncalc'); + const DataToTbHandler = require('./helper/DataToTbHandler'); + const errorHandler = require('./helper/ErrorToServiceHandler'); + const { sendNotification } = require('./helper/notification_reporter'); + const process = require('process'); + const { errLogger, logger, monitor } = require('./helper/logger'); + + //for accelerometer purposes + const { naklony } = require("../databases/accelerometer_db"); + + const dbNodes = TABLE("nodes"); + const dbRelays = TABLE("relays"); + + let GLOBALS; + let SETTINGS; + let rsPort; + let tbHandler; + + // runTasks intervals + const SHORT_INTERVAL = 30; + const LONG_INTERVAL = 300; + + //send data to following instances: + const SEND_TO = { + debug: 0, + tb: 1, + http_response: 2, + dido_controller: 3, + infoSender: 4, + dailyReport: 5 + } + + 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 + } + + 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 sendNodeReadout = null; // interval for sending agregate data from node + + 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["1"] = minutes; // dimming + priorities["76"] = minutes; // power + + minutes = 5; + priorities["75"] = minutes; // current + priorities["79"] = minutes; // energy + priorities["87"] = minutes; // aktualny cas + //priorities["84"] = minutes; //accelerometer + + minutes = 10; + priorities["74"] = minutes; // voltage + priorities["77"] = minutes; // power factor + priorities["78"] = minutes; // frequency + + minutes = 60; + priorities["0"] = minutes; // statecode + priorities["6"] = minutes; // dusk + priorities["7"] = minutes; // dawn + priorities["8"] = minutes; // profile + + minutes = 60 * 24; + priorities["89"] = minutes; // verzia fw + priorities["80"] = minutes; // lifetime + + //prikazy kt sa budu spustat na dany node - see config.js in terminal-oms.app. (1 - dimming) + let listOfCommands = [0, 1, 6, 7, 8, 74, 75, 76, 77, 78, 79, 80, 87, 89]; + + 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; + + // holds dusk, dawn (and more) values + let sunCalcResult; + + //helper container for counting resolved group of commands (commands related to set profile) + let cmdCounter = {};//key is node, value is counter + + //TODO: is this set working?? According to previous checks, sets do not work + //if sending of profile to node fails, we send notification and push node into set, so we do not send notification twice + const nodeProfileSendFail = new Set(); + + //we expect to get current temperature in Senica from senica-prod01 + let temperatureInSenica = null; + let accelerometerInterval = null; + + //NOTE: daily reports senica: + //rvo_is_on status, we monitor all nodes - if true, power and dimming should be not 0, if false, 24/7 nodes should be 0, other rvo should not respond + let rvo_is_on; + let previous_rvo_is_on_value; + let handleDailyReport; //setInterval for dailyReportHandler function + let dailyReport = {}; //data needed for daily report + let reportToSend = {}; //final report which we send to cloud + let breakerCounter = null; // status of breakers after flow starts is not in report + let rvoPeriod; // interval of checking dusk dawn and if rvo_is_on + let initialReportStatus = false; + + const DAILY_REPORT_HANDLER_TIME = 3_600_000; + const SET_SUNCALC_RESULT_TIME = 3_600_000; + const SET_RVO_PERIOD_TIME = 300_000; + const ADD_NODE_TO_REPORT_TIME = 3_600_000; + + //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); + + let now = new Date(); + console.log("Cmd-mngr installed", now.toLocaleString("sk-SK")); + + sunCalcResult = calculateDuskDawn(); + + handleRsPort(); + + customTasksInterval = setInterval(reportEdgeDateTimeAndNumberOfLuminaires, 120_000); + setTimeout(reportEdgeDateTimeAndNumberOfLuminaires, 4000); + + //dailyReport related + emptyReportToSend(); + breakerCounter = Object.keys(relaysData).length - 1; // we get number of lines (breakers) except of line 0 + rvoPeriod = setInterval(setRvoPeriod, SET_RVO_PERIOD_TIME); + setTimeout(setRvoPeriod, 3000); + setInterval(setSunCalcResult, SET_SUNCALC_RESULT_TIME); + handleDailyReport = setInterval(dailyReportHandler, DAILY_REPORT_HANDLER_TIME); + + + setCorrectTime = setInterval(setCorrectPlcTimeOnceADay, 60000 * 60); // 1 hour + setCorrectPlcTimeOnceADay(); + + sendNodeReadout = setInterval(sendNodesData, 150_000); + accelerometerInterval = setInterval(accelerometerData, 60000 * 30); //30 min + } + + + 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" + //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 + // if node regular readout does not respond, we repeat request + params.repeatCounter = 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-mngr: 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.byte4 = 96; + params.recipient = 1; + params.register = 8; + params.rw = 1;//write + params.timestamp = timestamp; + 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.byte4 = 96; + params.recipient = 1; + params.register = 8; + params.rw = 1;//write + params.timestamp = timestamp; + 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). + */ + + 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.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.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 + { + + logger.debug("processNodeProfile: Threshold lux level for DUSK/DAWN", node); + + let params = getParams(); + params.type = "set_node_profile"; + params.address = node; + params.register = 96; + params.recipient = 1; + params.rw = 1;//write + params.timestamp = timestamp; + 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(); + params.type = "set_node_profile"; + params.address = node; + params.register = 97; + params.recipient = 1; + params.rw = 1;//write + params.timestamp = timestamp; + 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.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); + + 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); + + console.log("proces profile finished *********************") + } + + + 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; + }); + } + + + 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) { + for (let k in nodesData) { + 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`); + } + } + } + + + function loadRelaysData(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 (value.contactor == 1) processAllNodeProfilesOnLine(value.line); + } + } + + + function reportOnlineNodeStatus(line) { + //Po zapnutí línie broadcastovo aktualizovať predtým čas a o 3 sek neskor - status, brightness + + logger.debug("Cmd-mngr: ----->reportOnlineNodeStatus for line", line); + + const d = new Date(); + + // broadcast actual time + let params = getParams(); + params.address = 0xffffffff;//Broadcast + params.byte1 = d.getHours(); + params.byte2 = d.getMinutes(); + params.recipient = 2;//2 broadcast, address = 0 + params.register = 87;//Actual time + params.rw = 1;//write + params.type = "node-onetime-write"; + params.timestamp = d.getTime() + 30000; + params.info = "run broadcast: Actual time"; + //params.debug = true; + + tasks.push(params); + + let sec = 3; + setTimeout(function() { + //Po zapnutí línie - spraviť hromadný refresh stavu práve zapnutých svietidiel + + let time = Date.now(); + + for (let k in nodesData) { + + //potrebujem nody k danej linii + 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].node_status_before_offline === true || nodesData[k].status === true) { + status = "OK"; + nodesData[k].time_of_last_communication = time; + } + + nodesData[k].readout.status = status; + + updateNodeStatus(k, status === "OK" ? true : false); + if (nodesData[k].hasOwnProperty("node_status_before_offline")) delete nodesData[k].node_status_before_offline; + sendTelemetry({ status: status }, tbname, time); + + //vyreportovanie dimming, current, input power pre liniu pre vsetky nody + //Prud + { + let params = getParams(); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 75;//prud + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = time + 4000; + params.info = 'read current'; + //params.debug = true; + tasks.push(params); + } + + //vykon + { + let params = getParams(); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 76;//výkon + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = time + 4100; + params.info = 'read power'; + //params.debug = true; + + tasks.push(params); + } + //dimming + { + let params = getParams(); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 1;//dimming + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = time + 4200; + params.info = 'read dimming'; + //params.debug = true; + + tasks.push(params); + } + + } + } + + }, sec * 1000); + } + + + function reportOfflineNodeStatus(line) { + + logger.info("Cmd-mngr: ------>reportOffLineNodeStatus for line ", line); + + values = {}; + values["dimming"] = 0;//brightness + values["power"] = 0;//výkon + values["current"] = 0;//prúd + values["status"] = "OFFLINE"; + + const date = Date.now(); + + Object.keys(nodesData).forEach(node => { + + //potrebujem nody k danej linii + if (line == nodesData[node].line || line == undefined) { + + let tbname = nodesData[node].tbname; + let nodeStatus = nodesData[node].status; + + //in case we have reported offline node status, we return (continue with next node) + if (nodeStatus === "OFFLINE") return; + + nodesData[node].node_status_before_offline = nodeStatus; + nodesData[node].status = "OFFLINE"; + nodesData[node].readout = {}; + + sendTelemetry({ ...values }, tbname, date); + } + }); + + } + + + function turnLine(onOrOff, line, info) { + let obj = { + line: line, + command: onOrOff, + info: info + }; + + //to assure, handleDailyReportFunction do not run before rvo_is_on variable changes. So after every line switch we reset the timer + clearInterval(handleDailyReport); + handleDailyReport = setInterval(dailyReportHandler, DAILY_REPORT_HANDLER_TIME); + + //logger.debug("linia", line, obj); + instance.send(SEND_TO.dido_controller, obj); + } + + + 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"; + 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]) { + //CRC_ERROR + message = "NOK"; + error = "CRC_ERROR c1"; + instance.send(SEND_TO.debug, "CRC_ERROR c1"); + } + + 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") { + instance.send(SEND_TO.debug, bytes); + instance.send(SEND_TO.debug, "RESPONSE " + type + " - " + bytes[4]); + + //logger.debug(SEND_TO.debug, "RESPONSE " + type + " - " + bytes[4], bytes); + + error = "type is: " + type; + + message = "NOK"; + } + + return { message, type, error }; + } + + + //BUILD TASKS// + function buildTasks(params) { + + //return; + console.log("buidTAaasks start ****************", params); + monitor.info("buildTasks - params", params); + + let processLine; //defined line + let init = false; + let processLineProfiles = true; + let processBroadcast = true; + let processNodes = true; + + if (params == undefined) { + init = true; + tasks = []; + logger.debug("-->buildTasks clear tasks"); + } + else { + processLineProfiles = params.processLineProfiles; + processBroadcast = false; + processNodes = false; + + processLine = params.line; + } + + let now = new Date(); + + //process line profiles + if (processLineProfiles) { + + let keys = Object.keys(relaysData); + + for (let i = 0; i < keys.length; i++) { + + let line = parseInt(keys[i]); + let profilestr = relaysData[line].profile; + + if (processLine != undefined) { + if (processLine != line) continue; + } + + try { + + /** + * we process line profiles: timepoints, astro clock, lux_sensor, offsets ... + */ + if (profilestr === "") throw ("Profile is not defined"); + let profile = JSON.parse(profilestr); + 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; + + // add name to regular profile timepoint and delete unused end_time key: + time_points.forEach(point => { + point.name = "profileTimepoint" + delete point.end_time; + }); + + //monitor.info("buildTasks: time_points", time_points); + + + /** + * 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 astro clock true, we remove all regular profile points + time_points = []; + + //TODO: when astro clock == true, is offset calculated ??? + //let duskAstroClockOffset = profile.dusk_astro_clock_offset; + //let dawnAstroClockOffset = profile.dawn_astro_clock_offset; + //console.log("line astro clock offsets dusk a dawn: ", duskAstroClockOffset, dawnAstroClockOffset); + // maybe add dusk dawn offset to calculateDuskDawn ?? what dusk dawn will be if dawn_lux_sensor == true?? + //let sunCalcResult = calculateDuskDawn(new Date(), line, duskAstroClockOffset, dawnAstroClockOffset); + + 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 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); + + 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); + + 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(':'); + + let ad = new Date(); + ad.setHours(parseInt(ahours), parseInt(aminutes), 0); + + let bd = new Date(); + bd.setHours(parseInt(bhours), parseInt(bminutes), 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++) { + + let start_time = new Date(); + let [hours, minutes] = time_points[t].start_time.split(':'); + start_time.setHours(parseInt(hours), parseInt(minutes), 0); + + //task is in 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(); + params.type = "relay"; + params.line = parseInt(line); + params.value = time_points[t].value; + params.tbname = relaysData[line].tbname; + params.timestamp = start_time.getTime(); + + // 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; + + //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)) { + 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; + + params.debug = true; + + //turn on/off line + tasks.push(params); + monitor.info("TimePoint params: ", params.info, start_time); + } + + monitor.info("-->time_points final", line, time_points); + + //ensure to turn on/off according to calculated currentValue + let params = getParams(); + params.type = "relay"; + params.line = parseInt(line); + params.tbname = relaysData[line].tbname; + params.value = currentValue; + params.timestamp = i; + params.debug = true; + + //logger.debug(now.toLocaleString("sk-SK")); + 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; + + tasks.push(params); + + } catch (error) { + if (profilestr !== "") { + //errLogger.error(profilestr, error); + console.log(`Cmd_mngr: Unable to process line profile ${line}. Error: `, error); + errorHandler.sendMessageToService(profilestr + "-" + error, 0, "js_error"); + } else { + turnLine("off", line, "No line profile. Switching it off on startup"); + } + } + + } + //logger.debug("tasks:"); + //logger.debug(tasks); + } + + + //NOTE: PROCESS DEFAULT BROADCASTS - Time of dusk, Time of dawn, Actual Time + if (processBroadcast) { + + let d = new Date(); + let time = d.getTime(); + //let sunCalcResult = calculateDuskDawn(); + + { + let params = getParams(); + + params.address = 0xffffffff;//broadcast + params.byte1 = sunCalcResult["dusk_hours"]; + params.byte2 = sunCalcResult["dusk_minutes"]; + params.recipient = 2;//2 broadcast, + params.register = 6;//Time of dusk + params.rw = 1;//write + params.type = "node-regular-write"; + params.timestamp = time + 60000; + params.addMinutesToTimestamp = 60 * 3; //kazde 3 hodiny zisti novy dusk + params.info = "Broadcast-duskTime"; + + tasks.push(params); + } + + { + let params = getParams(); + + params.address = 0xffffffff;//broadcast + params.byte1 = sunCalcResult["dawn_hours"]; + params.byte2 = sunCalcResult["dawn_minutes"]; + params.recipient = 2; //2 broadcast + params.register = 7;//Time of dawn + params.rw = 1;//write + params.type = "node-regular-write"; + params.timestamp = time + 60001; + params.addMinutesToTimestamp = 60 * 3; //kazde 3 hodiny zisti novy dawn + params.info = "Broadcast-dawnTime"; + + tasks.push(params); + } + + { + let params = getParams(); + + params.address = 0xffffffff;//broadcast + params.byte1 = d.getHours(); + params.byte2 = d.getMinutes(); + params.recipient = 2; //2 broadcast + params.register = 87;//Actual time + params.rw = 1;//write + params.type = "node-regular-write"; + params.timestamp = time + 60002; + params.addMinutesToTimestamp = 5; + params.info = "run broadcast: Actual time"; + + tasks.push(params); + } + + } + + //process nodes & tasks - read node's data + if (processNodes) { + + let time = Date.now(); + + for (let k in nodesData) { + let address = parseInt(k); + let tbname = nodesData[k].tbname; + let register = 0; + + for (let i = 0; i < listOfCommands.length; i++) { + + register = listOfCommands[i]; + let addMinutesToTimestamp = priorities[register]; + + let params = getParams(); + + params.address = address; + params.recipient = 1; + params.register = register; + params.type = register == 1 ? "node-dimming-read" : "node-regular-read"; + params.tbname = tbname; + params.timestamp = time + 5000 + i * 500 + addMinutesToTimestamp * 1000; //to make slight time difference + params.addMinutesToTimestamp = addMinutesToTimestamp; + params.info = "Node regular read command"; + + tasks.push(params); + } + + } + } + + + //niektore ulohy sa vygeneruju iba 1x pri starte!!! + if (!init) return; + + + //Master node FW version - modifies SETTINGS.masterNodeIsResponding + { + let params = getParams(); + params.type = "cmd-master"; + params.register = 4; + params.address = 0; + params.timestamp = 0; + params.addMinutesToTimestamp = 5; + params.tbname = SETTINGS.rvoTbName; + params.info = "Master node FW verzia"; + //params.debug = true; + + tasks.push(params); + } + + //kazdu hodinu skontrolovat nastavenie profilov + { + let params = getParams(); + params.type = "process_profiles"; + params.timestamp = Date.now() + 60001; + params.addMinutesToTimestamp = 60;//60 = every hour + params.info = "detekcia nespracovaných profilov linie a nodov"; + //params.debug = true; + + tasks.push(params); + } + + monitor.info("tasks created:", tasks.length); + } + + + /** + * We process line profile, where "astro_clock": true + * example profile: + * + "dawn_lux_sensor": true, + "dusk_lux_sensor": true, + "dawn_lux_sensor_value": 5, + "dusk_lux_sensor_value": 5, + "dawn_astro_clock_offset": 0, + "dusk_astro_clock_offset": 10, + "dawn_lux_sensor_time_window": 30, + "dusk_lux_sensor_time_window": 30, + "dawn_astro_clock_time_window": 60, + "dusk_astro_clock_time_window": 60 + + * if dawn: if currentTimestamp is in timewindow "dawnTime + and - dawn_lux_sensor_time_window" and lux value >= lux_sensor_value, we switch off the line. + * if dusk: we do oposite + * + * dawn: usvit - lux je nad hranicou - vypnem + * dusk: sumrak - lux je pod hranicou - zapnem + */ + 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++) { + + let line = keys[i]; //line is turned off by default + let profilestr = relaysData[line].profile; + const contactor = relaysData[line].contactor; + + try { + + let profile = JSON.parse(profilestr); + if (Object.keys(profile).length === 0) throw ("turnOnOffLinesAccordingToLuxSensor - profile is not defined"); + + 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 (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"); + } + } + } + + //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 (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"); + } + } + } + + } + + } catch (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) { + //MASTER + if (node == 0) return; + + let nodeObj = nodesData[node]; + if (nodeObj == undefined) return; + + let nodeCurrentStatus = nodeObj.status; + const now = Date.now(); + + let data = null; + + if (nodeCurrentStatus === "OFFLINE") { + data = { status: newStatus }; + nodeDbStatusModify(node, data); + return; + } + else 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; + } + + } + + + 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 }; + } + }); + }); + } + + + function processDailyReport() { + + const now = Date.now(); + + for (const [key, value] of Object.entries(dailyReport)) { + + if (["name", "time", "dusk_and_dawn"].includes(key)) continue; + + let poleNumber = nodesData[key]["pole_number"]; + let line = dailyReport[key].line; + let nodeType = nodesData[key]["node_type"]; + let fullNodeName = key + + if (poleNumber && nodeType && line) { + fullNodeName = SETTINGS.rvo_number + "/" + poleNumber + "_" + line + "L_" + key + "_" + nodeType; + } else { + fullNodeName = key; + } + + if (rvo_is_on) { + + if (value.initialTs) { + if (value.initialTs + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["night_no_data"], fullNodeName); + console.log('report nedostava ziadne data uz hodinu', fullNodeName); + value.initialTs = now; + } + } + if (value.dimmingIsZeroTime) { + if (value.dimmingIsZeroTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["night_dimming=0"], fullNodeName); + console.log("report node dimming je 0 ale ma svietit", fullNodeName); + value.dimmingIsZeroTime = now; + } + } + if (value.powerIsZeroTime) { + if (value.powerIsZeroTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["night_power=0"], fullNodeName); + console.log("report node power je 0 ale ma svietit", fullNodeName); + value.powerIsZeroTime = now; + } + } + + } else { + + let contactorStatus = relaysData[line].contactor; + if (contactorStatus === 1) { + + if (value.initialTs) { + if (value.initialTs + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["day_24/7_no_data"], fullNodeName); + console.log('node je na 24/7 ale nedostava ziadne data uz hodinu', fullNodeName); + value.initialTs = now; + } + } + if (value.dimmingIsOnButShouldBeOffTime) { + if (value.dimmingIsOnButShouldBeOffTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["day_24/7_dimming>0"], fullNodeName); + console.log("report dimming je > 0 ale nema svietit", fullNodeName); + value.dimmingIsOnButShouldBeOffTime = now; + } + } + if (value.powerIsOnButShouldBeOffTime) { + if (value.powerIsOnButShouldBeOffTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["day_24/7_power>0"], fullNodeName); + console.log("report power je > 0 ale nema svietit", fullNodeName); + value.powerIsOnButShouldBeOffTime = now; + } + } + + } + + } + + } + + let report = {}; + report["name"] = SETTINGS.rvo_name; + report["time"] = new Date(); + report["report"] = reportToSend; + + writeToFile(F.path.root("report_data.log"), report, true); + instance.send(SEND_TO.dailyReport, report); + } + + + function dailyReportHandler() { + + if (!SETTINGS.daily_report) return; + + // after dawn we empty reportToSend and start to get data for a new day + const date = new Date(); + const hour = date.getHours(); + const minute = date.getMinutes(); + + console.log("now: ", hour, minute, "suncalc: ", sunCalcResult.dawn_hours, sunCalcResult.dawn_minutes); + + if (hour === sunCalcResult.dawn_hours) { + + //NOTE: ak je este pred usvitom, spracujeme report a posleme na cloud, ak uz je po usvite, resetujeme report plnime data noveho dna + if (minute >= sunCalcResult.dawn_minutes - 2) { + emptyReportToSend(); + emptyDailyReport(); + console.log("Podmienka 1 v dailyReport handler"); + } else { + processDailyReport(); + emptyReportToSend(); + emptyDailyReport(); + console.log("Podmienka 2 v dailyReport handler"); + } + + initialReportStatus = true; + + // ak sa funkcia spusti o hodinu alebo 2 neskor, ako je usvit (moze sa to stat, kedze kazde zapnutie/vypnutie linii odznova spusti casovac. + } else if (hour === sunCalcResult.dawn_hours + 1 || hour === sunCalcResult.dawn_hours + 2) { + if (!initialReportStatus) { + emptyReportToSend(); + emptyDailyReport(); + initialReportStatus = true; + console.log("Podmienka 3 v dailyReport handler"); + } else { + processDailyReport(); + initialReportStatus = true; + console.log("Podmienka 4 v dailyReport handler"); + } + } else { + processDailyReport(); + initialReportStatus = false; + console.log("Podmienka 5 v dailyReport handler"); + } + + console.log("initialReportStatus: ", initialReportStatus); + + } + + function emptyReportToSend() { + emptyJsObject(reportToSend); + reportToSend["contactor"] = { off: [], on: [] }; + reportToSend["night_no_data"] = []; + reportToSend["night_dimming=0"] = []; + reportToSend["night_power=0"] = []; + reportToSend["day_24/7_no_data"] = []; + reportToSend["day_24/7_dimming>0"] = []; + reportToSend["day_24/7_power>0"] = []; + console.log(`resetuje sa reportToSend`); + } + + + //NOTE: ked je initialTs stale rovnaky a zistime ze linie su vypnute (relaysData.line.contactor) - zistim, ci je node na tej linii. Vieme, ze ak je linia vypnuta je to v poriadku lebo nie je na 24/7 linii + //ak je na 24/7 linii, reportujeme, ze neprijima data + function emptyDailyReport() { + const ts = Date.now(); + emptyJsObject(dailyReport); + + //NOTE: do dailyReport dame vsetky nody a pravidelne kontrolujeme ci maju data + //ked nastane sumrak/usvit a svetla maju zacat/prestat svietit, dailyReport spravime nanovo: + for (const [key, value] of Object.entries(nodesData)) { + dailyReport[value.node] = { line: value.line, initialTs: ts }; + } + + console.log("dailyReport: ", dailyReport); + } + + + async function runTasks() { + + clearInterval(interval); + + let currentTimestamp = Date.now(); + + //sort tasks based on timestamp + 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) { + instance.send(SEND_TO.debug, "no tasks created"); + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + if (!rsPort.isOpen) { + instance.send(SEND_TO.debug, "!rsPort.isOpen"); + //await rsPort.open(); + //console.log("Cmd-mngr: !rsPort.isOpen"); + } + + let currentTask = tasks[0]; + + if (currentTask.debug) { + //logger.debug("--->task to process", currentTask); + } + + if (currentTask.timestamp <= currentTimestamp) { + let params = { ...tasks[0] }; + + //allow terminal commands + if (SETTINGS.maintenance_mode && params.type !== "cmd-terminal") { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + let type = params.type; + let tbname = params.tbname; + let node = params.address; + let register = params.register; + let line = null; + let itIsNodeCommand; + + if (nodesData[node] !== undefined) { + line = nodesData[node].line; + itIsNodeCommand = true; + } + + if (params.line !== undefined) line = params.line; + + if (params.addMinutesToTimestamp > 0 || params.timePointName) { + tasks[0].timestamp = currentTimestamp + tasks[0].addMinutesToTimestamp * 60000; + } else { + tasks.shift(); + } + + //kontrola nespracovanych profilov nodov + //TODO: co ked niektore nody neprijimaju profily? kazdu hodinu zahltuju "tasks" array + if (type == "process_profiles") { + //na vsetky zapnutych liniach sa spracuju nespracovane profily nodov + loadRelaysData(); + interval = setInterval(runTasks, SHORT_INTERVAL); + return; + } + + //relay + if (type == "relay") { + + const timePointName = params.timePointName; + const value = params.value; + + let date = new Date(); + date.setDate(date.getDate() + 1);//next day + + let sunCalcResult; + if (timePointName) sunCalcResult = calculateDuskDawn(date, params.line); + + + if (timePointName == "dawn") { + tasks[0].timestamp = sunCalcResult.dawn_time; + } + else if (timePointName == "dusk") { + tasks[0].timestamp = sunCalcResult.dusk_time; + } + else if (timePointName == "luxOn") { + tasks[0].timestamp = sunCalcResult.dusk_time + params.dusk_lux_sensor_time_window * 60000; + } + else if (timePointName == "luxOff") { + tasks[0].timestamp = sunCalcResult.dawn_time + params.dawn_lux_sensor_time_window * 60000; + } + else if (timePointName == "profileTimepoint") { + tasks[0].timestamp = currentTimestamp + tasks[0].addMinutesToTimestamp * 60000; + } + + let info = "aplikovany bod profilu"; + let onOrOff = ""; + value == 1 ? onOrOff = "on" : onOrOff = "off"; + + turnLine(onOrOff, params.line, info); + + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + if (!SETTINGS.masterNodeIsResponding) { + //ak neodpoveda, nebudeme vykonavat ziadne commands, okrem cmd-terminal cmd-master + errorHandler.sendMessageToService("Master node is not responding"); + + let stop = true; + + if (type === "cmd-terminal" || type === "cmd-master") stop = false; + if (stop) { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + } + + let contactorStatus = 1; + if (relaysData[line] != undefined) contactorStatus = relaysData[line].contactor; + + if (line === 0 || contactorStatus === 0 || FLOW.deviceStatus.state_of_breaker[line] === "Off") { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + // TODO: -> status offline for rvo if rotary_switch_state is OFF, this is source of errors + // check if rotary_switch_state == "Off" + // state_of_braker: disconnected = true? + + if (!rsPort.isOpen) { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + //RE-CALCULATE VALUES + //set actual time for broadcast + if (register == 87 && params.recipient === 2) { + var d = new Date(); + params.byte1 = d.getHours();//h + params.byte2 = d.getMinutes();//m + } + + //SET DUSK/DAWN FOR BROADCAST + //Time of dusk + if (register == 6 && params.recipient === 2) { + + if (type != "cmd-terminal") { + params.byte1 = sunCalcResult["dusk_hours"];//h + params.byte2 = sunCalcResult["dusk_minutes"];//m + } + } + + //Time of dawn + if (register == 7 && params.recipient === 2) { + if (type != "cmd-terminal") { + params.byte1 = sunCalcResult["dawn_hours"];//h + params.byte2 = sunCalcResult["dawn_minutes"];//m + } + } + //----------------------- + + instance.send(SEND_TO.debug, "address: " + node + " register:" + register + "type: " + type); + + var startTime, endTime; + startTime = new Date(); + + let saveToTb = true; + if (!tbname) saveToTb = false; + + let resp = com_generic(node, params.recipient, params.rw, register, params.name, params.byte1, params.byte2, params.byte3, params.byte4); + let readBytes = 11; + let timeout = 4000; + + + // await keyword is important, otherwise incorrect data is returned! + await writeData(rsPort, resp, readBytes, timeout).then(function(data) { + + //sometimes happens, that status of node changes to OK, NOK even if line was turned off and should be status OFFLINE. To prevent this, we return if line contactor is 0: + if (itIsNodeCommand && line && relaysData[line].contactor !== 1) return; + + 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); + + //ak sa odpoved zacina 0 - je to v poriadku, inak je NOK + let message = result.message; // OK, NOK + let message_type = result.type; + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + console.log("detected response:", result); + logger.debug("Cmd-mngr: writeData done " + message_type + " duration: " + timeDiff + " type: " + params.debug, params, result); + } + } + + let values = {}; + + //CMD FINISHED + if (message == "OK") { + + updateNodeStatus(node, true); + + //write + if (type == "set_node_profile") { + let result = cmdCounterResolve(node); + if (result == 0) { + dbNodes.modify({ processed: true }).where("node", node).make(function(builder) { + builder.callback(function(err, response) { + + sendNotification("Cmd-mngr: process cmd", SETTINGS.rvoTbName, "dimming_profile_was_successfully_received_by_node", { node: node }, "", SEND_TO.tb, instance); + + logger.debug("--> profil úspešne odoslaný na node č. " + node); + nodesData[node].processed = true; + nodeProfileSendFail.delete(node); + }); + }); + } + } + + //parse read response + if (params.rw == 0) { + values = processResponse(register, dataBytes); //read + } + + if (itIsNodeCommand) { + values.comm_status = "OK"; + values.status = "OK"; + nodesData[node].readout = { ...nodesData[node].readout, ...values }; + + + if (SETTINGS.daily_report) { + //TODO: co ak nedostavame odpovede z nodu ? Musime vyreportovat!! + //v dailyReport teda musi byt kompletny zoznam nodov a neustale kontrolovat, ci maju data, ak nie report node - neodpoveda + if (register === 1) { + + let now = Date.now(); + + if (rvo_is_on === true) { + + if ("dimmingIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].dimmingIsOnButShouldBeOffTime; + + if (values.dimming > 0) { + if ("dimmingIsZeroTime" in dailyReport[node]) delete dailyReport[node].dimmingIsZeroTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if (!("dimmingIsZeroTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], dimmingIsZeroTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } else { + + if ("dimmingIsZeroTime" in dailyReport[node]) delete dailyReport[node].dimmingIsZeroTime; + + if (values.dimming > 0) { + if (!("dimmingIsOnButShouldBeOffTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], dimmingIsOnButShouldBeOffTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if ("dimmingIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].dimmingIsOnButShouldBeOffTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } + } + + if (register === 76) { + + let now = Date.now(); + + if (rvo_is_on === true) { + + if ("powerIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].powerIsOnButShouldBeOffTime; + + if (values.power > 1) { + if ("powerIsZeroTime" in dailyReport[node]) delete dailyReport[node].powerIsZeroTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if (!("powerIsZeroTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], powerIsZeroTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } else { + + if ("powerIsZeroTime" in dailyReport[node]) delete dailyReport[node].powerIsZeroTime; + + if (values.power > 1) { + if (!("powerIsOnButShouldBeOffTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], powerIsOnButShouldBeOffTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if ("powerIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].powerIsOnButShouldBeOffTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } + } + } + + } + + //master node + if (node == 0) { + sendNotification("Cmd-mngr: 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; + } + + if (params.debug) { + //logger.debug("saveToTb", saveToTb, tbname, values); + } + + if (saveToTb && type != "node-regular-read") { + sendTelemetry(values, tbname); + } + else { + if (type == "cmd-terminal") { + terminalCommandResponse(params, "SUCCESS", data); + } + } + + } + else { + terminalCommandResponse(params, "ERROR", data); + handleNokResponseOnRsPort("handleNOK else block", params, itIsNodeCommand, saveToTb); + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + //logger.debug("writeData err: ", error, result, params); + logger.debug("writeData err: ", tbname, node, register, values); + } + } + + //logger.debug(error, result, params); + } + }).catch(function(reason) { + + //console.log("writeData catch exception", reason); + instance.send(SEND_TO.debug, reason); + + terminalCommandResponse(params, "FAILURE", null, reason); + handleNokResponseOnRsPort("handleNOK catch block", params, itIsNodeCommand, saveToTb); + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + logger.debug("-->WRITE FAILED: " + reason, params.debug, params); + } + } + + }); + + } + 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); + } + + + // if node does not respond to request, we repeat request 3 times: + function repeatCommand(params) { + params.repeatCounter++; + if (params.repeatCounter < 4) { + params.timestamp = 0; + params.addMinutesToTimestamp = 0; + tasks.push(params); + } + } + + function handleNokResponseOnRsPort(message, params, itIsNodeCommand, saveToTb) { + + let node = params.address; + let register = params.register; + let type = params.type; + let tbName = params.tbname; + if (!tbName) return; + + let values = {}; + + let updateStatus = updateNodeStatus(node, false); + + if (itIsNodeCommand) { + values.comm_status = "NOK"; + nodesData[node].readout.comm_status = "NOK"; + repeatCommand(params); + } + + if (updateStatus) { + values.status = "NOK"; + nodesData[node].readout.status = "NOK"; + } + + if (type === "node-regular-read") return; + + //master node + if (node == 0) { + sendNotification("Cmd-mngr: 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; + + if (register == 4) values["master_node_version"] = "NOK"; + } + + if (type == "set_node_profile") { + delete cmdCounter[node]; + logger.debug("profil nebol úspešne odoslaný na node č. ", params); + + if (!nodeProfileSendFail.has(node)) { + sendNotification("Cmd-mngr: process cmd", tbName, "configuration_of_dimming_profile_to_node_failed", { node: node }, "", SEND_TO.tb, instance); + nodeProfileSendFail.add(node); + } + } + + // console.log("------",node, register, type, itIsNodeCommand, updateStatus, saveToTb, values); + if (saveToTb) { + sendTelemetry(values, tbName); + } + + } + + + function sendNodesData() { + Object.keys(nodesData).forEach(node => { + if (nodesData[node]["status"] !== "OFFLINE") { + sendTelemetry(nodesData[node].readout, nodesData[node].tbname); + nodesData[node].readout = {}; + } + }) + } + + + /** + * 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; + } + + 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); + + //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 === "OFFLINE") { + nodeObj.node_status_before_offline === true ? number_of_ok_luminaires++ : number_of_nok_luminaires++; + } + else if (nodeObj.status == true) 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 - ts % 60000 //round to full minute + }; + + sendTelemetry(values, SETTINGS.rvoTbName, ts); + } + + + function setSunCalcResult() { + //if next day, we get new dusk and dawn. To make sure, in local timezone 2:00 means 00:00 in utc (it means next day) + if (new Date().getHours() === 2) { + sunCalcResult = calculateDuskDawn(); + console.log("Novy suncalc: ", sunCalcResult); + } + } + + + function setRvoPeriod() { + + if (!SETTINGS.daily_report) return; + + const ts = Date.now(); + + previous_rvo_is_on_value = rvo_is_on; + + if (ts < sunCalcResult.dawn_time - 1_800_000) { // nodes should be on (00:00 -> 06:00 ( - pol hodina, lebo rvo vypina skor) + rvo_is_on = true; + } else if (sunCalcResult.dawn_time - 1_800_000 < ts && ts < sunCalcResult.dusk_time + 1_800_000) { // nodes should be off 06:00 -> 21:00 + rvo_is_on = false; + } else if (sunCalcResult.dusk_time + 1_800_000 < ts) { // nodes should be on 21:00 -> 00:00 + rvo_is_on = true; + } + + if (previous_rvo_is_on_value !== rvo_is_on) { + emptyDailyReport(); + console.log("rvo_is: ", rvo_is_on, previous_rvo_is_on_value); + } + } + + + function handleRsPort() { + + if (rsPort) { + rsPort.removeAllListeners(); + rsPort = null; + } + + //! 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-mngr: rsPort opened success"); + + 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); + + }).catch(function(reason) { + instance.send(SEND_TO.debug, "Cmd-mngr: RPC runSyncExec - promise rejected:" + reason); + }); + }); + + rsPort.on('error', function(err) { + errorHandler.sendMessageToService([exports.title, "unable to open port", SETTINGS.serial_port, err.message], 0); + monitor.info("Cmd-mngr: Error on rsPort", err.message); + }); + + rsPort.on("close", () => { + monitor.info("Cmd-mngr: rsPort closed, reconnecting..."); + setTimeout(handleRsPort, 1000); + }); + + rsPort.open(); + } + + + instance.on("close", () => { + clearInterval(interval); + clearInterval(customTasksInterval); + clearInterval(setCorrectTime); + clearInterval(sendNodeReadout); + clearInterval(accelerometerInterval); + rsPort.close(); + }); + + instance.on("0", _ => { + main(); + }) + + + instance.on("2", _ => { + console.log("dailyReport, reportToSend, rvo_is_on", dailyReport, reportToSend, rvo_is_on, previous_rvo_is_on_value); + }) + + instance.on("1", 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(); + return; + } + else if (flowdata.data == "close") { + rsPort.close(); + return; + } + else if (flowdata.data == "clean") { + tasks = []; + return; + } + else if (flowdata.data == "buildtasks") { + //build & run + return; + } + else if (flowdata.data == "run") { + //durations = []; + + if (tasks.length == 0) { + + buildTasks(); + + if (rsPort.isOpen) { + interval = setInterval(runTasks, 100); + } + else { + instance.send(SEND_TO.debug, "port is not opened!!!"); + } + } + } + else { + //terminal data - object + //logger.debug("flowdata", flowdata.data); + + if (typeof flowdata.data === 'object') { + //logger.debug("dido", flowdata.data); + if (flowdata.data.hasOwnProperty("sender")) { + //data from dido_controller + if (flowdata.data.sender == "dido_controller") { + + if (flowdata.data.hasOwnProperty("cmd")) { + let cmd = flowdata.data.cmd; + + if (cmd == "buildTasks") { + clearInterval(interval); + + logger.debug("-->Cmd-mngr: BUILD TASKS"); + buildTasks(); + + //logger.debug("tasks:"); + //logger.debug(tasks); + + logger.debug("-->Cmd-mngr: RUN TASKS"); + interval = setInterval(runTasks, 5000); + } + else if (cmd == "reload_relays") { + loadRelaysData(flowdata.data.line); + + if (flowdata.data.dataChanged) { + if (!flowdata.data.value) { + reportOfflineNodeStatus(flowdata.data.line); + } + else { + reportOnlineNodeStatus(flowdata.data.line); + } + } + + } + else if (cmd == "rotary_switch_state") { + let value = flowdata.data.value; + + //state was changed + if (rotary_switch_state != value) { + if (value == "Off") { + //vyreportovat vsetky svietdla + reportOfflineNodeStatus(); + } + + rotary_switch_state = value; + } + } + 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) { + + // we send lux_sensor value to all nodes: + let params = getParams(PRIORITY_TYPES.node_broadcast); + + params.recipient = 2;//2 broadcast, address = 0 + params.address = 0xffffffff;//Broadcast + + let ba = longToByteArray(lux_sensor); + + params.byte3 = ba[1];//msb + params.byte4 = ba[0]; + params.timestamp = PRIORITY_TYPES.node_broadcast; + params.info = "run broadcast: Actual Lux level from cabinet"; + params.register = 95;//Actual Lux level from cabinet + params.rw = 1;//write + + tasks.push(params); + + //process profiles + turnOnOffLinesAccordingToLuxSensor(lux_sensor); + } + } + else if (cmd == "state_of_breaker") { + //istic linie + + breakerCounter--; + + let value = flowdata.data.value; + let line = parseInt(flowdata.data.line); + + let dataChanged = false; + if (state_of_breaker[line] != value) dataChanged = true; + + state_of_breaker[line] = value; + + let status = "OK"; + if (value == "Off") status = "NOK"; + + if (dataChanged) { + + if (relaysData.hasOwnProperty(line)) { + let tbname = relaysData[line].tbname; + + if (value == "Off") { + sendNotification("Cmd-mngr: onData", tbname, "circuit_breaker_was_turned_off_line", { line: line }, "", SEND_TO.tb, instance, "circuit_breaker"); + if (breakerCounter < 0) reportToSend["contactor"]["off"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + else { + sendNotification("Cmd-mngr: onData", tbname, "circuit_breaker_was_turned_on_line", { line: line }, "", SEND_TO.tb, instance, "circuit_breaker"); + if (breakerCounter < 0) reportToSend["contactor"]["on"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + + //report status liniu + sendTelemetry({ status: status }, tbname) + + //current value + if (value == "Off") reportOfflineNodeStatus(line); //vyreportovat vsetky svietidla na linii + } + + } + } + else { + logger.debug("undefined cmd", cmd); + } + } + } + + return; + } + + //data from worksys + if (flowdata.data.hasOwnProperty("topic")) { + + let data = getNested(flowdata.data, "content", "data"); + + //if we get temperature in senica from senica-prod01 + let temperature = getNested(flowdata.data, "content", "senica_temperature"); + + if (temperature !== undefined) { + temperatureInSenica = temperature; + return; + } + + if (data === undefined) { + console.log("Invalid rpc command came from platform"); + return; + } + + let command = data.params.command; + let method = data.method; + let profile = data.params.payload; + if (profile == undefined) profile = ""; + let entity = data.params.entities[0]; + let entity_type = entity.entity_type; + let tbname = entity.tb_name; + + instance.send(SEND_TO.debug, flowdata.data); + 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") { + + //let command = data.params.command; + let value = data.params.payload.value; + + if (command == "dimming") { + + let nodeWasFound = false; + let keys = Object.keys(nodesData); + + //logger.debug("-----", keys); + + 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); + + value = parseInt(value); + if (value > 0) value = value + 128; + + params.type = "node-onetime-write"; + params.tbname = tbname; + params.address = node; + params.register = 1; + params.recipient = 1; + params.byte4 = value; + params.rw = 1; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'set dimming from platform'; + //params.debug = true; + + //debug(params); + logger.debug("dimming", params); + + tasks.push(params); + + 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); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 1; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read dimming (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + //pridame aj vyreportovanie - vykon + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 76; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read Input Power (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + //pridame aj vyreportovanie - prud svietidla + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 75; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read Input Current (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + //pridame aj vyreportovanie - power faktor - ucinnik + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 77; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read power factor (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + }, 4000); + + nodeWasFound = true; + break; + } + } + + if (!nodeWasFound) { + logger.debug("set dimming from platform", "unable to find tbname", tbname); + } + } + else { + instance.send(SEND_TO.debug, "undefined command " + command); + logger.debug("undefined command", command); + } + + return; + } + 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++) { + let node = keys[i]; + if (tbname == nodesData[node].tbname) { + + 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"); + + //profil úspešne prijatý pre node č. xx + sendNotification("Cmd-mngr", tbname, "dimming_profile_was_processed_for_node", { node: node }, profile, SEND_TO.tb, instance); + + nodesData[node].processed = false; + nodesData[node].profile = profile; + + processNodeProfile(node); + }); + }); + } + } + } + else { + + instance.send(SEND_TO.debug, "unknown method " + method); + logger.debug("unknown method", method); + + return; + } + } + + //nastav profil linie z platformy + 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") { + + 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++) { + let line = keys[i]; + if (tbname == relaysData[line].tbname) { + //zmazeme tasky + 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) { + + //update profile + logger.debug("worksys - update relay profile done:", profile); + instance.send(SEND_TO.debug, "worksys - update relay profile done"); + + relaysData[line].profile = profile; + + loadRelaysData(line) + logger.debug("loadRelaysData DONE for line", line); + + buildTasks({ processLineProfiles: true, line: line }); + + sendNotification("Cmd-mngr: set profile from worksys", tbname, "switching_profile_was_processed_for_line", { line: line }, profile, SEND_TO.tb, instance); + }); + }); + break; + } + } + } + else if (method == "set_command") { + let value = data.params.payload.value; + + 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; + + 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"); + if(line !== 0) reportToSend["contactor"]["off"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + else { + turnLine("on", line, "command received from platform"); + if(line !== 0) reportToSend["contactor"]["on"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + } + } + else { + instance.send(SEND_TO.debug, "undefined method " + method); + logger.debug("undefined method", method); + } + + return; + } + else { + instance.send(SEND_TO.debug, "UNKNOW entity_type " + entity_type); + logger.debug("UNKNOW entity_type", entity_type); + } + return; + } + + //terminal + if (!rsPort.isOpen) await rsPort.open(); + + let params = flowdata.data.body; + if (params == undefined) { + //logger.debug("Cmd-mngr: flowdata.data.body is undefined"); + return; + } + + params.priority = PRIORITY_TYPES.terminal; + params.type = "cmd-terminal"; + params.tbname = ""; + params.timestamp = PRIORITY_TYPES.terminal; + params.addMinutesToTimestamp = 0;// do not repeat task!!! + params.debug = true; + + let timestamp = Date.now(); + params.refFlowdataKey = timestamp; + //params.refFlowdata = flowdata; + //refFlowdata = flowdata; + + //console.log("flowdata", flowdata); + + cleanUpRefFlowdataObj(); + + refFlowdataObj[timestamp] = flowdata; + + //fix + //params.address = params.adress; + logger.debug("received from terminal", params); + logger.debug("date/time:", new Date()); + logger.debug("tasks length:", tasks.length); + + //tasks = []; + + //add to tasks + tasks.push(params); + + } + } + }) + + + //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) + } + + + /** + * 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; + + RESTBuilder.make(function(builder) { + + if (!builder) return; + + builder.method('GET'); + builder.url('http://192.168.252.2:8004/gettime?projects_id=1'); + + builder.callback(function(err, response, output) { + + 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); + } + + }); + } + + } 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); + + } else { + //console.log("Read-only", stdout); + + 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]: [ + { + "ts": date, + "values": values + } + ] + } + + tbHandler.sendToTb(dataToTb, instance); + } + + + function calculateDuskDawn(date, line, duskOffset = 0, dawnOffset = 0) { + + if (date === undefined) date = new Date(); + + 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); + } + + //if(profile.dawn_lux_sensor == false) + { + if (profile.hasOwnProperty("dawn_astro_clock_offset")) dawn_astro_clock_offset = parseInt(profile.dawn_astro_clock_offset); + } + + } + + } catch (error) { + if (profilestr != "") { + logger.debug(profilestr); + logger.debug(error); + } + } + + 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; + } + + //Dimming, CCT + else if (register == 1) { + let brightness = 0; + let dimming = byte0; + if (dimming > 128) { + //dimming = -128; + brightness = dimming - 128; + } + + //cct + //Ak Byte3 == 1: CCT = (Byte2*256)+Byte1 + let cct; + if (byte3 == 1) cct = byte2 * 256 + byte1; + else cct = bytesToInt(bytes.slice(0, 3)); + + //cct podla auditu + + values["dimming"] = brightness; + return values; + } + + // + else if (register == 4) { + values["master_node_version"] = bytes[1] + "." + bytes[2]; + //logger.debug("FW Version", register, bytes); + } + + //Napätie + else if (register == 74) { + let voltage = (bytesToInt(bytes) * 0.1).toFixed(1); + values["voltage"] = Number(voltage); + } + + //Prúd + else if (register == 75) { + let current = bytesToInt(bytes); + values["current"] = current; + } + + //výkon + else if (register == 76) { + let power = (bytesToInt(bytes) * 0.1).toFixed(2); + values["power"] = Number(power); + } + + //účinník + else if (register == 77) { + let power_factor = Math.cos(bytesToInt(bytes) * 0.1 * (Math.PI / 180)).toFixed(2); + values["power_factor"] = Number(power_factor); + } + + //frekvencia + else if (register == 78) { + let frequency = (bytesToInt(bytes) * 0.1).toFixed(2); + values["frequency"] = Number(frequency); + } + + //energia + else if (register == 79) { + let energy = bytesToInt(bytes); + values["energy"] = energy / 1000; //energia v kWh -> delit 1000 + } + + //doba života + else if (register == 80) { + let lifetime = (bytesToInt(bytes) / 60).toFixed(2); + values["lifetime"] = Number(lifetime); + } + + //nastavenie profilu + else if (register == 8) { + let time_schedule_settings = bytesToInt(bytes); + values["time_schedule_settings"] = time_schedule_settings; + } + + //naklon - nateraz sa z nodu nevycitava! kvoli problemom s accelerometrom a vracanymi hodnotami, posielame temp a x y z vo funkcii accelerometerData() + else if (register == 84) { + values["temperature"] = byte3 >= 128 ? (byte3 - 128) * (-1) : byte3; + values["inclination_x"] = byte2 >= 128 ? (byte2 - 128) * (-1) : byte2; + values["inclination_y"] = byte1 >= 128 ? (byte1 - 128) * (-1) : byte1; + values["inclination_z"] = byte0 >= 128 ? (byte0 - 128) * (-1) : byte0; + } + + //FW verzia nodu + else if (register == 89) { + //formát: "Byte3: Byte2.Byte1 (Byte0)" + values["fw_version"] = byte3 + ":" + byte2 + "." + byte1 + "(" + byte0 + ")"; + } + + else if (register == 87 || register == 6 || register == 7) { + var d = new Date(); + d.setHours(byte3, byte2, 0, 0); + let timestamp = d.getTime(); + + //aktuálny čas + if (register == 87) values["actual_time"] = timestamp; + //čas súmraku + else if (register == 6) values["dusk_time"] = timestamp; + //čas úsvitu + else if (register == 7) values["dawn_time"] = timestamp; + } + + 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; + + } + + + function getObjectByTbValue(object, tbname) { + return object[Object.keys(object).find(key => object[key].tbname === tbname)]; + } + + + function isObject(item) { + return (typeof item === "object" && !Array.isArray(item) && item !== null); + } + + + // we fake data, that should be received from accelerometer, as they are a bit unreliable. (temperature, x,y,z) + function accelerometerData() { + + if (temperatureInSenica === null) return; + + //clone nodesData and relaysData objects + let nodesData_clone = JSON.parse(JSON.stringify(nodesData)); + let relaysData_clone = JSON.parse(JSON.stringify(relaysData)); + + for (const key in relaysData_clone) { + + const lineData = relaysData_clone[key]; + const lineNumber = lineData.line; + const contactor = lineData.contactor; + + if (lineNumber === 0) continue; + + if (contactor === 1) { + + let date = Date.now(); + + Object.keys(nodesData_clone).forEach((node, index) => { + + setTimeout(function() { + + if (nodesData_clone[node].line === lineNumber) { + + // NOTE: if status of luminaire is NOK or OFFLINE, we do not send data; + let status = nodesData_clone[node].status; + if (status === "OFFLINE" || !status) return; + + let x = null; + if (naklony.hasOwnProperty(node)) x = naklony[node].naklon; + if (x === null) x = 0; + + sendTelemetry({ temperature: Math.round(temperatureInSenica + 10 + Math.floor(Math.random() * 3)), inclination_x: x, inclination_y: 0, inclination_z: 0 }, nodesData_clone[node].tbname, date); + } + + }, (index + 1) * 500); + }) + + } + } + } + + +} // end of instance.export + diff --git a/RVO16/flow/cmd_manager_orig.txt b/RVO16/flow/cmd_manager_orig.txt new file mode 100755 index 0000000..e92d48f --- /dev/null +++ b/RVO16/flow/cmd_manager_orig.txt @@ -0,0 +1,2800 @@ +exports.id = 'cmd_manager'; +exports.title = 'CMD Manager'; +exports.group = 'Worksys'; +exports.color = '#5D9CEC'; +exports.version = '0.0.3'; +exports.output = ['red', 'blue', 'yellow', 'blue', 'white']; +exports.input = 3; +exports.icon = 'cloud-upload'; + +exports.html = ` +
+
+
+
RPC - run RPC calls

+
+
+
@(User)
+
+
+
@(Password)
+
+
+
@(My edge)
+
+
+
+`; +exports.readme = `Manager for CMD calls`; + + +exports.install = function(instance) { + + 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'); + + var SunCalc = require('./helper/suncalc'); + const DataToTbHandler = require('./helper/DataToTbHandler'); + const errorHandler = require('./helper/ErrorToServiceHandler'); + const { sendNotification } = require('./helper/notification_reporter'); + const process = require('process'); + const { errLogger, logger, monitor } = require('./helper/logger'); + + //for accelerometer purposes + const { naklony } = require("../databases/accelerometer_db"); + + const dbNodes = TABLE("nodes"); + const dbRelays = TABLE("relays"); + + let GLOBALS; + let SETTINGS; + let rsPort; + let tbHandler; + + // runTasks intervals + const SHORT_INTERVAL = 30; + const LONG_INTERVAL = 300; + + //send data to following instances: + const SEND_TO = { + debug: 0, + tb: 1, + http_response: 2, + dido_controller: 3, + infoSender: 4 + } + + 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 + } + + 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 sendNodeReadout = null; // interval for sending agregate data from node + + 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["1"] = minutes; // dimming + priorities["76"] = minutes; // power + + minutes = 5; + priorities["75"] = minutes; // current + priorities["79"] = minutes; // energy + priorities["87"] = minutes; // aktualny cas + //priorities["84"] = minutes; + + minutes = 10; + priorities["74"] = minutes; // voltage + priorities["77"] = minutes; // power factor + priorities["78"] = minutes; // frequency + + minutes = 60; + priorities["0"] = minutes; // statecode + priorities["6"] = minutes; // dusk + priorities["7"] = minutes; // dawn + priorities["8"] = minutes; // profile + + minutes = 60 * 24; + priorities["89"] = minutes; // verzia fw + priorities["80"] = minutes; // lifetime + + //prikazy kt sa budu spustat na dany node - see config.js in terminal-oms.app. (1 - dimming) + let listOfCommands = [0, 1, 6, 7, 8, 74, 75, 76, 77, 78, 79, 80, 87, 89]; + + 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 sunCalcResult; + let reportDuskDawn; + + //helper container for counting resolved group of commands (commands related to set profile) + let cmdCounter = {};//key is node, value is counter + + //if sending of profile to node fails, we send notification and push node into set, so we do not send notification twice + const nodeProfileSendFail = new Set(); + + //we expect to get current temperature in Senica from senica-prod01 + let temperatureInSenica = null; + let accelerometerInterval = null; + + //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); + + let now = new Date(); + console.log("Cmd-mngr 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(); + + customTasksInterval = setInterval(function() { + reportEdgeDateTimeAndNumberOfLuminaires(); + }, 120000); + reportEdgeDateTimeAndNumberOfLuminaires(); + + setCorrectTime = setInterval(setCorrectPlcTimeOnceADay, 60000 * 60); // 1 hour + setCorrectPlcTimeOnceADay(); + + sendNodeReadout = setInterval(sendNodesData, 150000); + accelerometerInterval = setInterval(accelerometerData, 60000 * 30); //30 min + } + + + 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" + //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 + // if node regular readout does not respond, we repeat request + params.repeatCounter = 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-mngr: 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.byte4 = 96; + params.recipient = 1; + params.register = 8; + params.rw = 1;//write + params.timestamp = timestamp; + 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.byte4 = 96; + params.recipient = 1; + params.register = 8; + params.rw = 1;//write + params.timestamp = timestamp; + 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). + */ + + 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.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.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 + { + + logger.debug("processNodeProfile: Threshold lux level for DUSK/DAWN", node); + + let params = getParams(); + params.type = "set_node_profile"; + params.address = node; + params.register = 96; + params.recipient = 1; + params.rw = 1;//write + params.timestamp = timestamp; + 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(); + params.type = "set_node_profile"; + params.address = node; + params.register = 97; + params.recipient = 1; + params.rw = 1;//write + params.timestamp = timestamp; + 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.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); + + 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); + + console.log("proces profile finished *********************") + } + + + 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; + }); + } + + + 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) { + for (let k in nodesData) { + 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`); + } + } + } + + + function loadRelaysData(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 (value.contactor == 1) processAllNodeProfilesOnLine(value.line); + } + } + + + function reportOnlineNodeStatus(line) { + //Po zapnutí línie broadcastovo aktualizovať predtým čas a o 3 sek neskor - status, brightness + + logger.debug("Cmd-mngr: ----->reportOnlineNodeStatus for line", line); + + const d = new Date(); + + // broadcast actual time + let params = getParams(); + params.address = 0xffffffff;//Broadcast + params.byte1 = d.getHours(); + params.byte2 = d.getMinutes(); + params.recipient = 2;//2 broadcast, address = 0 + params.register = 87;//Actual time + params.rw = 1;//write + params.type = "node-onetime-write"; + params.timestamp = d.getTime() + 30000; + params.info = "run broadcast: Actual time"; + //params.debug = true; + + tasks.push(params); + + let sec = 3; + setTimeout(function() { + //Po zapnutí línie - spraviť hromadný refresh stavu práve zapnutých svietidiel + + let time = Date.now(); + + for (let k in nodesData) { + + //potrebujem nody k danej linii + 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].node_status_before_offline === true || nodesData[k].status === true) { + status = "OK"; + nodesData[k].time_of_last_communication = time; + } + + nodesData[k].readout.status = status; + + updateNodeStatus(k, status === "OK" ? true : false); + if (nodesData[k].hasOwnProperty("node_status_before_offline")) delete nodesData[k].node_status_before_offline; + sendTelemetry({ status: status }, tbname, time); + + //vyreportovanie dimming, current, input power pre liniu pre vsetky nody + //Prud + { + let params = getParams(); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 75;//prud + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = time + 4000; + params.info = 'read current'; + //params.debug = true; + tasks.push(params); + } + + //vykon + { + let params = getParams(); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 76;//výkon + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = time + 4100; + params.info = 'read power'; + //params.debug = true; + + tasks.push(params); + } + //dimming + { + let params = getParams(); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 1;//dimming + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = time + 4200; + params.info = 'read dimming'; + //params.debug = true; + + tasks.push(params); + } + + } + } + + }, sec * 1000); + } + + + function reportOfflineNodeStatus(line) { + + logger.info("Cmd-mngr: ------>reportOffLineNodeStatus for line ", line); + + values = {}; + values["dimming"] = 0;//brightness + values["power"] = 0;//výkon + values["current"] = 0;//prúd + values["status"] = "OFFLINE"; + + const date = Date.now(); + + Object.keys(nodesData).forEach(node => { + + //potrebujem nody k danej linii + if (line == nodesData[node].line || line == undefined) { + + let tbname = nodesData[node].tbname; + let nodeStatus = nodesData[node].status; + + //in case we have reported offline node status, we return (continue with next node) + if (nodeStatus === "OFFLINE") return; + + nodesData[node].node_status_before_offline = nodeStatus; + nodesData[node].status = "OFFLINE"; + nodesData[node].readout = {}; + + sendTelemetry({ ...values }, tbname, date); + } + }); + + } + + + function turnLine(onOrOff, line, info) { + let obj = { + line: line, + command: onOrOff, + info: info + }; + + //logger.debug("linia", line, obj); + instance.send(SEND_TO.dido_controller, obj); + } + + + 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"; + 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]) { + //CRC_ERROR + message = "NOK"; + error = "CRC_ERROR c1"; + instance.send(SEND_TO.debug, "CRC_ERROR c1"); + } + + 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") { + instance.send(SEND_TO.debug, bytes); + instance.send(SEND_TO.debug, "RESPONSE " + type + " - " + bytes[4]); + + //logger.debug(SEND_TO.debug, "RESPONSE " + type + " - " + bytes[4], bytes); + + error = "type is: " + type; + + message = "NOK"; + } + + return { message, type, error }; + } + + + //BUILD TASKS// + function buildTasks(params) { + + //return; + console.log("buidTAaasks start ****************", params); + monitor.info("buildTasks - params", params); + + let processLine; //defined line + let init = false; + let processLineProfiles = true; + let processBroadcast = true; + let processNodes = true; + + if (params == undefined) { + init = true; + tasks = []; + logger.debug("-->buildTasks clear tasks"); + } + else { + processLineProfiles = false; + processBroadcast = false; + processNodes = false; + + processLineProfiles = params.processLineProfiles; + processLine = params.line; + } + + let now = new Date(); + + //process line profiles + if (processLineProfiles) { + + let keys = Object.keys(relaysData); + + for (let i = 0; i < keys.length; i++) { + + let line = parseInt(keys[i]); + let profilestr = relaysData[line].profile; + + if (processLine != undefined) { + if (processLine != line) continue; + } + + try { + + /** + * we process line profiles: timepoints, astro clock, lux_sensor, offsets ... + */ + if (profilestr === "") throw ("Profile is not defined"); + let profile = JSON.parse(profilestr); + 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; + + // add name to regular profile timepoint and delete unused end_time key: + time_points.forEach(point => { + point.name = "profileTimepoint" + delete point.end_time; + }); + + //monitor.info("buildTasks: time_points", time_points); + + + /** + * 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 astro clock true, we remove all regular profile points + time_points = []; + + 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 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); + + 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); + + 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(':'); + + let ad = new Date(); + ad.setHours(parseInt(ahours), parseInt(aminutes), 0); + + let bd = new Date(); + bd.setHours(parseInt(bhours), parseInt(bminutes), 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++) { + + let start_time = new Date(); + let [hours, minutes] = time_points[t].start_time.split(':'); + start_time.setHours(parseInt(hours), parseInt(minutes), 0); + + //task is in 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(); + params.type = "relay"; + params.line = parseInt(line); + params.value = time_points[t].value; + params.tbname = relaysData[line].tbname; + params.timestamp = start_time.getTime(); + + // 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; + + //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)) { + 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; + + params.debug = true; + + //turn on/off line + tasks.push(params); + monitor.info("TimePoint params: ", params.info, start_time); + } + + monitor.info("-->time_points final", line, time_points); + + //ensure to turn on/off according to calculated currentValue + let params = getParams(); + params.type = "relay"; + params.line = parseInt(line); + params.tbname = relaysData[line].tbname; + params.value = currentValue; + params.timestamp = i; + params.debug = true; + + //logger.debug(now.toLocaleString("sk-SK")); + 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; + + tasks.push(params); + + } catch (error) { + if (profilestr !== "") { + //errLogger.error(profilestr, error); + console.log(`Cmd_mngr: Unable to process line profile ${line}. Error: `, error); + errorHandler.sendMessageToService(profilestr + "-" + error, 0, "js_error"); + } else { + turnLine("off", line, "No line profile. Switching it off on startup"); + } + } + + } + //logger.debug("tasks:"); + //logger.debug(tasks); + } + + + //NOTE: PROCESS DEFAULT BROADCASTS - Time of dusk, Time of dawn, Actual Time + if (processBroadcast) { + + let d = new Date(); + let time = d.getTime(); + let sunCalcResult = calculateDuskDawn(); + + { + let params = getParams(); + + params.address = 0xffffffff;//broadcast + params.byte1 = sunCalcResult["dusk_hours"]; + params.byte2 = sunCalcResult["dusk_minutes"]; + params.recipient = 2;//2 broadcast, + params.register = 6;//Time of dusk + params.rw = 1;//write + params.type = "node-regular-write"; + params.timestamp = time + 60000; + params.addMinutesToTimestamp = 60 * 3; //kazde 3 hodiny zisti novy dusk + params.info = "Broadcast-duskTime"; + + tasks.push(params); + } + + { + let params = getParams(); + + params.address = 0xffffffff;//broadcast + params.byte1 = sunCalcResult["dawn_hours"]; + params.byte2 = sunCalcResult["dawn_minutes"]; + params.recipient = 2; //2 broadcast + params.register = 7;//Time of dawn + params.rw = 1;//write + params.type = "node-regular-write"; + params.timestamp = time + 60001; + params.addMinutesToTimestamp = 60 * 3; //kazde 3 hodiny zisti novy dawn + params.info = "Broadcast-dawnTime"; + + tasks.push(params); + } + + { + let params = getParams(); + + params.address = 0xffffffff;//broadcast + params.byte1 = d.getHours(); + params.byte2 = d.getMinutes(); + params.recipient = 2; //2 broadcast + params.register = 87;//Actual time + params.rw = 1;//write + params.type = "node-regular-write"; + params.timestamp = time + 60002; + params.addMinutesToTimestamp = 5; + params.info = "run broadcast: Actual time"; + + tasks.push(params); + } + + } + + //process nodes & tasks - read node's data + if (processNodes) { + + let time = Date.now(); + + for (let k in nodesData) { + let address = parseInt(k); + let tbname = nodesData[k].tbname; + let register = 0; + + for (let i = 0; i < listOfCommands.length; i++) { + + register = listOfCommands[i]; + let addMinutesToTimestamp = priorities[register]; + + let params = getParams(); + + params.address = address; + params.recipient = 1; + params.register = register; + params.type = register == 1 ? "node-dimming-read" : "node-regular-read"; + params.tbname = tbname; + params.timestamp = time + 5000 + i * 500 + addMinutesToTimestamp * 1000; //to make slight time difference + params.addMinutesToTimestamp = addMinutesToTimestamp; + params.info = "Node regular read command"; + + tasks.push(params); + } + + } + } + + + //niektore ulohy sa vygeneruju iba 1x pri starte!!! + if (!init) return; + + + //Master node FW version - modifies SETTINGS.masterNodeIsResponding + { + let params = getParams(); + params.type = "cmd-master"; + params.register = 4; + params.address = 0; + params.timestamp = 0; + params.addMinutesToTimestamp = 5; + params.tbname = SETTINGS.rvoTbName; + params.info = "Master node FW verzia"; + //params.debug = true; + + tasks.push(params); + } + + //kazdu hodinu skontrolovat nastavenie profilov + { + let params = getParams(); + params.type = "process_profiles"; + params.timestamp = Date.now() + 60001; + params.addMinutesToTimestamp = 60;//60 = every hour + params.info = "detekcia nespracovaných profilov linie a nodov"; + //params.debug = true; + + tasks.push(params); + } + + monitor.info("tasks created:", tasks.length); + } + + + /** + * We process line profile, where "astro_clock": true + * example profile: + * + "dawn_lux_sensor": true, + "dusk_lux_sensor": true, + "dawn_lux_sensor_value": 5, + "dusk_lux_sensor_value": 5, + "dawn_astro_clock_offset": 0, + "dusk_astro_clock_offset": 10, + "dawn_lux_sensor_time_window": 30, + "dusk_lux_sensor_time_window": 30, + "dawn_astro_clock_time_window": 60, + "dusk_astro_clock_time_window": 60 + + * if dawn: if currentTimestamp is in timewindow "dawnTime + and - dawn_lux_sensor_time_window" and lux value >= lux_sensor_value, we switch off the line. + * if dusk: we do oposite + * + * dawn: usvit - lux je nad hranicou - vypnem + * dusk: sumrak - lux je pod hranicou - zapnem + */ + 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++) { + + let line = keys[i]; //line is turned off by default + let profilestr = relaysData[line].profile; + const contactor = relaysData[line].contactor; + + try { + + let profile = JSON.parse(profilestr); + if (Object.keys(profile).length === 0) throw ("turnOnOffLinesAccordingToLuxSensor - profile is not defined"); + + 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 (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"); + } + } + } + + //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 (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"); + } + } + } + + } + + } catch (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) { + //MASTER + if (node == 0) return; + + let nodeObj = nodesData[node]; + if (nodeObj == undefined) return; + + let nodeCurrentStatus = nodeObj.status; + const now = Date.now(); + + let data = null; + + if (nodeCurrentStatus === "OFFLINE") { + data = { status: newStatus }; + nodeDbStatusModify(node, data); + return; + } + else 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; + } + + } + + + 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 }; + } + }); + }); + } + + + async function runTasks() { + + clearInterval(interval); + + let currentTimestamp = Date.now(); + + //report dusk, dawn--------------------------------- + if (reportDuskDawn.dusk_time < currentTimestamp) { + //vyreportuj iba ak nie je velky rozdiel napr. 60 sekund + if ((currentTimestamp - reportDuskDawn.dusk_time) < 60 * 1000) { + //reportovali sme? + if (reportDuskDawn.dusk_time_reported != sunCalcResult.dusk_time) { + //sendNotification("Cmd-mngr: calculated Time of dusk", SETTINGS.rvoTbName, "dusk_has_occured", { value: sunCalcResult["dusk"] }, "", SEND_TO.tb, instance); + reportDuskDawn.dusk_time_reported = sunCalcResult.dusk_time; + } + } + + var nextDay = new Date(); + nextDay.setDate(nextDay.getDate() + 1); + + sunCalcResult = calculateDuskDawn(nextDay); + reportDuskDawn.dusk_time = sunCalcResult.dusk_time; + } + + if (reportDuskDawn.dawn_time < currentTimestamp) { + //vyreportuj iba ak nie je velky rozdiel napr. 60 sekund + if ((currentTimestamp - reportDuskDawn.dawn_time) < 60 * 1000) { + //reportovali sme? + if (reportDuskDawn.dawn_time_reported != sunCalcResult.dawn_time) { + //sendNotification(": calculated Time of dawn", SETTINGS.rvoTbName, "dawn_has_occured", { value: sunCalcResult["dawn"] }, "", SEND_TO.tb, instance); + reportDuskDawn.dawn_time_reported = sunCalcResult.dawn_time; + } + } + + var nextDay = new Date(); + nextDay.setDate(nextDay.getDate() + 1); + + sunCalcResult = calculateDuskDawn(nextDay); + reportDuskDawn.dawn_time = sunCalcResult.dawn_time; + + } + //-------------------------------------------------------- + + //sort tasks based on timestamp + 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) { + instance.send(SEND_TO.debug, "no tasks created"); + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + if (!rsPort.isOpen) { + instance.send(SEND_TO.debug, "!rsPort.isOpen"); + //await rsPort.open(); + //console.log("Cmd-mngr: !rsPort.isOpen"); + } + + let currentTask = tasks[0]; + + if (currentTask.debug) { + //logger.debug("--->task to process", currentTask); + } + + if (currentTask.timestamp <= currentTimestamp) { + let params = { ...tasks[0] }; + + //allow terminal commands + if (SETTINGS.maintenance_mode && params.type !== "cmd-terminal") { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + let type = params.type; + let tbname = params.tbname; + let node = params.address; + let register = params.register; + let line = null; + let itIsNodeCommand; + + if (nodesData[node] !== undefined) { + line = nodesData[node].line; + itIsNodeCommand = true; + } + + if (params.line !== undefined) line = params.line; + + if (params.addMinutesToTimestamp > 0 || params.timePointName) { + tasks[0].timestamp = currentTimestamp + tasks[0].addMinutesToTimestamp * 60000; + } else { + tasks.shift(); + } + + //kontrola nespracovanych profilov nodov + if (type == "process_profiles") { + //na vsetky zapnutych liniach sa spracuju nespracovane profily nodov + loadRelaysData(); + interval = setInterval(runTasks, SHORT_INTERVAL); + return; + } + + //relay + if (type == "relay") { + + const timePointName = params.timePointName; + const value = params.value; + + let date = new Date(); + date.setDate(date.getDate() + 1);//next day + + let sunCalcResult; + if (timePointName) sunCalcResult = calculateDuskDawn(date, params.line); + + if (timePointName == "dawn") { + tasks[0].timestamp = sunCalcResult.dawn_time; + } + else if (timePointName == "dusk") { + tasks[0].timestamp = sunCalcResult.dusk_time; + } + else if (timePointName == "luxOn") { + tasks[0].timestamp = sunCalcResult.dusk_time + params.dusk_lux_sensor_time_window * 60000; + } + else if (timePointName == "luxOff") { + tasks[0].timestamp = sunCalcResult.dawn_time + params.dawn_lux_sensor_time_window * 60000; + } + else if (timePointName == "profileTimepoint") { + tasks[0].timestamp = currentTimestamp + tasks[0].addMinutesToTimestamp * 60000; + } + + let info = "aplikovany bod profilu"; + let onOrOff = ""; + value == 1 ? onOrOff = "on" : onOrOff = "off"; + + turnLine(onOrOff, params.line, info); + + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + if (!SETTINGS.masterNodeIsResponding) { + //ak neodpoveda, nebudeme vykonavat ziadne commands, okrem cmd-terminal cmd-master + errorHandler.sendMessageToService("Master node is not responding"); + + let stop = true; + + if (type === "cmd-terminal" || type === "cmd-master") stop = false; + if (stop) { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + } + + let contactorStatus = 1; + if (relaysData[line] != undefined) contactorStatus = relaysData[line].contactor; + + if (line === 0 || contactorStatus === 0 || FLOW.deviceStatus.state_of_breaker[line] === "Off") { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + // TODO: -> status offline for rvo if rotary_switch_state is OFF, this is source of errors + // check if rotary_switch_state == "Off" + // state_of_braker: disconnected = true? + + if (!rsPort.isOpen) { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + //RE-CALCULATE VALUES + //set actual time for broadcast + if (register == 87 && params.recipient === 2) { + var d = new Date(); + params.byte1 = d.getHours();//h + params.byte2 = d.getMinutes();//m + } + + //SET DUSK/DAWN FOR BROADCAST + //Time of dusk + if (register == 6 && params.recipient === 2) { + + if (type != "cmd-terminal") { + let sunCalcResult = calculateDuskDawn(); + params.byte1 = sunCalcResult["dusk_hours"];//h + params.byte2 = sunCalcResult["dusk_minutes"];//m + } + } + + //Time of dawn + if (register == 7 && params.recipient === 2) { + if (type != "cmd-terminal") { + let sunCalcResult = calculateDuskDawn(); + params.byte1 = sunCalcResult["dawn_hours"];//h + params.byte2 = sunCalcResult["dawn_minutes"];//m + } + } + //----------------------- + + instance.send(SEND_TO.debug, "address: " + node + " register:" + register + "type: " + type); + + var startTime, endTime; + startTime = new Date(); + + let saveToTb = true; + if (!tbname) saveToTb = false; + + let resp = com_generic(node, params.recipient, params.rw, register, params.name, params.byte1, params.byte2, params.byte3, params.byte4); + let readBytes = 11; + let timeout = 4000; + + + // await keyword is important, otherwise incorrect data is returned! + await writeData(rsPort, resp, readBytes, timeout).then(function(data) { + + //sometimes happens, that status of node changes to OK, NOK even if line was turned off and should be status OFFLINE. To prevent this, we return if line contactor is 0: + if (itIsNodeCommand && line && relaysData[line].contactor !== 1) return; + + 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); + + //ak sa odpoved zacina 0 - je to v poriadku, inak je NOK + let message = result.message; // OK, NOK + let message_type = result.type; + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + console.log("detected response:", result); + logger.debug("Cmd-mngr: writeData done " + message_type + " duration: " + timeDiff + " type: " + params.debug, params, result); + } + } + + let values = {}; + + //CMD FINISHED + if (message == "OK") { + + updateNodeStatus(node, true); + + //write + if (type == "set_node_profile") { + let result = cmdCounterResolve(node); + if (result == 0) { + dbNodes.modify({ processed: true }).where("node", node).make(function(builder) { + builder.callback(function(err, response) { + + sendNotification("Cmd-mngr: process cmd", SETTINGS.rvoTbName, "dimming_profile_was_successfully_received_by_node", { node: node }, "", SEND_TO.tb, instance); + + logger.debug("--> profil úspešne odoslaný na node č. " + node); + nodesData[node].processed = true; + nodeProfileSendFail.delete(node); + }); + }); + } + } + + //parse read response + if (params.rw == 0) { + values = processResponse(register, dataBytes); //read + } + + if (itIsNodeCommand) { + values.comm_status = "OK"; + values.status = "OK"; + nodesData[node].readout = { ...nodesData[node].readout, ...values }; + } + + //master node + if (node == 0) { + sendNotification("Cmd-mngr: 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; + } + + if (params.debug) { + //logger.debug("saveToTb", saveToTb, tbname, values); + } + + if (saveToTb && type != "node-regular-read") { + sendTelemetry(values, tbname); + } + else { + if (type == "cmd-terminal") { + terminalCommandResponse(params, "SUCCESS", data); + } + } + + } + else { + terminalCommandResponse(params, "ERROR", data); + handleNokResponseOnRsPort("handleNOK else block", params, itIsNodeCommand, saveToTb); + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + //logger.debug("writeData err: ", error, result, params); + logger.debug("writeData err: ", tbname, node, register, values); + } + } + + //logger.debug(error, result, params); + } + }).catch(function(reason) { + + //console.log("writeData catch exception", reason); + instance.send(SEND_TO.debug, reason); + + terminalCommandResponse(params, "FAILURE", null, reason); + handleNokResponseOnRsPort("handleNOK catch block", params, itIsNodeCommand, saveToTb); + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + logger.debug("-->WRITE FAILED: " + reason, params.debug, params); + } + } + + }); + + } + 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); + } + + + // if node does not respond to request, we repeat request 3 times: + function repeatCommand(params) { + params.repeatCounter++; + if (params.repeatCounter < 4) { + params.timestamp = 0; + params.addMinutesToTimestamp = 0; + tasks.push(params); + } + } + + function handleNokResponseOnRsPort(message, params, itIsNodeCommand, saveToTb) { + + let node = params.address; + let register = params.register; + let type = params.type; + let tbName = params.tbname; + if (!tbName) return; + + let values = {}; + + let updateStatus = updateNodeStatus(node, false); + + if (itIsNodeCommand) { + values.comm_status = "NOK"; + nodesData[node].readout.comm_status = "NOK"; + repeatCommand(params); + } + + if (updateStatus) { + values.status = "NOK"; + nodesData[node].readout.status = "NOK"; + } + + if (type === "node-regular-read") return; + + //master node + if (node == 0) { + sendNotification("Cmd-mngr: 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; + + if (register == 4) values["master_node_version"] = "NOK"; + } + + if (type == "set_node_profile") { + delete cmdCounter[node]; + logger.debug("profil nebol úspešne odoslaný na node č. ", params); + + if (!nodeProfileSendFail.has(node)) { + sendNotification("Cmd-mngr: process cmd", tbName, "configuration_of_dimming_profile_to_node_failed", { node: node }, "", SEND_TO.tb, instance); + nodeProfileSendFail.add(node); + } + } + + // console.log("------",node, register, type, itIsNodeCommand, updateStatus, saveToTb, values); + if (saveToTb) { + sendTelemetry(values, tbName); + } + + } + + + function sendNodesData() { + Object.keys(nodesData).forEach(node => { + if (nodesData[node]["status"] !== "OFFLINE") { + sendTelemetry(nodesData[node].readout, nodesData[node].tbname); + nodesData[node].readout = {}; + } + }) + } + + + /** + * 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; + } + + 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); + + //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 === "OFFLINE") { + nodeObj.node_status_before_offline === true ? number_of_ok_luminaires++ : number_of_nok_luminaires++; + } + else if (nodeObj.status == true) 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 - ts % 60000 //round to full minute + }; + + sendTelemetry(values, SETTINGS.rvoTbName, ts); + } + + + function handleRsPort() { + + if (rsPort) { + rsPort.removeAllListeners(); + rsPort = null; + } + + //! 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-mngr: rsPort opened success"); + + 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); + + }).catch(function(reason) { + instance.send(SEND_TO.debug, "Cmd-mngr: RPC runSyncExec - promise rejected:" + reason); + }); + }); + + rsPort.on('error', function(err) { + errorHandler.sendMessageToService([exports.title, "unable to open port", SETTINGS.serial_port, err.message], 0); + monitor.info("Cmd-mngr: Error on rsPort", err.message); + }); + + rsPort.on("close", () => { + monitor.info("Cmd-mngr: rsPort closed, reconnecting..."); + setTimeout(handleRsPort, 1000); + }); + + rsPort.open(); + } + + + instance.on("close", () => { + clearInterval(interval); + clearInterval(customTasksInterval); + clearInterval(setCorrectTime); + clearInterval(sendNodeReadout); + clearInterval(accelerometerInterval); + rsPort.close(); + }); + + instance.on("0", _ => { + main(); + }) + + instance.on("1", 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(); + return; + } + else if (flowdata.data == "close") { + rsPort.close(); + return; + } + else if (flowdata.data == "clean") { + tasks = []; + return; + } + else if (flowdata.data == "buildtasks") { + //build & run + return; + } + else if (flowdata.data == "run") { + //durations = []; + + if (tasks.length == 0) { + + buildTasks(); + + if (rsPort.isOpen) { + interval = setInterval(runTasks, 100); + } + else { + instance.send(SEND_TO.debug, "port is not opened!!!"); + } + } + } + else { + //terminal data - object + //logger.debug("flowdata", flowdata.data); + + if (typeof flowdata.data === 'object') { + //logger.debug("dido", flowdata.data); + if (flowdata.data.hasOwnProperty("sender")) { + //data from dido_controller + if (flowdata.data.sender == "dido_controller") { + + if (flowdata.data.hasOwnProperty("cmd")) { + let cmd = flowdata.data.cmd; + + if (cmd == "buildTasks") { + clearInterval(interval); + + logger.debug("-->Cmd-mngr: BUILD TASKS"); + buildTasks(); + + //logger.debug("tasks:"); + //logger.debug(tasks); + + logger.debug("-->Cmd-mngr: RUN TASKS"); + interval = setInterval(runTasks, 5000); + } + else if (cmd == "reload_relays") { + loadRelaysData(flowdata.data.line); + + if (flowdata.data.dataChanged) { + if (!flowdata.data.value) { + reportOfflineNodeStatus(flowdata.data.line); + } + else { + reportOnlineNodeStatus(flowdata.data.line); + } + } + + } + else if (cmd == "rotary_switch_state") { + let value = flowdata.data.value; + + //state was changed + if (rotary_switch_state != value) { + if (value == "Off") { + //vyreportovat vsetky svietdla + reportOfflineNodeStatus(); + } + + rotary_switch_state = value; + } + } + 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) { + + // we send lux_sensor value to all nodes: + let params = getParams(PRIORITY_TYPES.node_broadcast); + + params.recipient = 2;//2 broadcast, address = 0 + params.address = 0xffffffff;//Broadcast + + let ba = longToByteArray(lux_sensor); + + params.byte3 = ba[1];//msb + params.byte4 = ba[0]; + params.timestamp = PRIORITY_TYPES.node_broadcast; + params.info = "run broadcast: Actual Lux level from cabinet"; + params.register = 95;//Actual Lux level from cabinet + params.rw = 1;//write + + tasks.push(params); + + //process profiles + turnOnOffLinesAccordingToLuxSensor(lux_sensor); + } + } + else if (cmd == "state_of_breaker") { + //istic linie + let value = flowdata.data.value; + let line = parseInt(flowdata.data.line); + + let dataChanged = false; + if (state_of_breaker[line] != value) dataChanged = true; + + state_of_breaker[line] = value; + + let status = "OK"; + if (value == "Off") status = "NOK"; + + if (dataChanged) { + + if (relaysData.hasOwnProperty(line)) { + let tbname = relaysData[line].tbname; + + if (value == "Off") sendNotification("Cmd-mngr: onData", tbname, "circuit_breaker_was_turned_off_line", { line: line }, "", SEND_TO.tb, instance, "circuit_breaker"); + else sendNotification("Cmd-mngr: onData", tbname, "circuit_breaker_was_turned_on_line", { line: line }, "", SEND_TO.tb, instance, "circuit_breaker"); + + //report status liniu + sendTelemetry({ status: status }, tbname) + + //current value + if (value == "Off") reportOfflineNodeStatus(line); //vyreportovat vsetky svietidla na linii + } + + } + } + else { + logger.debug("undefined cmd", cmd); + } + } + } + + return; + } + + //data from worksys + if (flowdata.data.hasOwnProperty("topic")) { + + let data = getNested(flowdata.data, "content", "data"); + + //if we get temperature in senica from senica-prod01 + let temperature = getNested(flowdata.data, "content", "senica_temperature"); + + if (temperature !== undefined) { + temperatureInSenica = temperature; + return; + } + + if (data === undefined) { + console.log("Invalid rpc command came from platform"); + return; + } + + let command = data.params.command; + let method = data.method; + let profile = data.params.payload; + if (profile == undefined) profile = ""; + let entity = data.params.entities[0]; + let entity_type = entity.entity_type; + let tbname = entity.tb_name; + + instance.send(SEND_TO.debug, flowdata.data); + 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") { + + //let command = data.params.command; + let value = data.params.payload.value; + + if (command == "dimming") { + + let nodeWasFound = false; + let keys = Object.keys(nodesData); + + //logger.debug("-----", keys); + + 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); + + value = parseInt(value); + if (value > 0) value = value + 128; + + params.type = "node-onetime-write"; + params.tbname = tbname; + params.address = node; + params.register = 1; + params.recipient = 1; + params.byte4 = value; + params.rw = 1; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'set dimming from platform'; + //params.debug = true; + + //debug(params); + logger.debug("dimming", params); + + tasks.push(params); + + 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); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 1; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read dimming (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + //pridame aj vyreportovanie - vykon + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 76; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read Input Power (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + //pridame aj vyreportovanie - prud svietidla + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 75; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read Input Current (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + //pridame aj vyreportovanie - power faktor - ucinnik + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 77; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read power factor (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + }, 4000); + + nodeWasFound = true; + break; + } + } + + if (!nodeWasFound) { + logger.debug("set dimming from platform", "unable to find tbname", tbname); + } + } + else { + instance.send(SEND_TO.debug, "undefined command " + command); + logger.debug("undefined command", command); + } + + return; + } + 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++) { + let node = keys[i]; + if (tbname == nodesData[node].tbname) { + + 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"); + + //profil úspešne prijatý pre node č. xx + sendNotification("Cmd-mngr", tbname, "dimming_profile_was_processed_for_node", { node: node }, profile, SEND_TO.tb, instance); + + nodesData[node].processed = false; + nodesData[node].profile = profile; + + processNodeProfile(node); + }); + }); + } + } + } + else { + + instance.send(SEND_TO.debug, "unknown method " + method); + logger.debug("unknown method", method); + + return; + } + } + + //nastav profil linie z platformy + 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") { + + 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++) { + let line = keys[i]; + if (tbname == relaysData[line].tbname) { + //zmazeme tasky + 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) { + + //update profile + logger.debug("worksys - update relay profile done:", profile); + instance.send(SEND_TO.debug, "worksys - update relay profile done"); + + relaysData[line].profile = profile; + + loadRelaysData(line) + logger.debug("loadRelaysData DONE for line", line); + + buildTasks({ processLineProfiles: true, line: line }); + + sendNotification("Cmd-mngr: set profile from worksys", tbname, "switching_profile_was_processed_for_line", { line: line }, profile, SEND_TO.tb, instance); + }); + }); + break; + } + } + } + else if (method == "set_command") { + let value = data.params.payload.value; + + 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; + + 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"); + } + } + else { + instance.send(SEND_TO.debug, "undefined method " + method); + logger.debug("undefined method", method); + } + + return; + } + else { + instance.send(SEND_TO.debug, "UNKNOW entity_type " + entity_type); + logger.debug("UNKNOW entity_type", entity_type); + } + return; + } + + //terminal + if (!rsPort.isOpen) await rsPort.open(); + + let params = flowdata.data.body; + if (params == undefined) { + //logger.debug("Cmd-mngr: flowdata.data.body is undefined"); + return; + } + + params.priority = PRIORITY_TYPES.terminal; + params.type = "cmd-terminal"; + params.tbname = ""; + params.timestamp = PRIORITY_TYPES.terminal; + params.addMinutesToTimestamp = 0;// do not repeat task!!! + params.debug = true; + + let timestamp = Date.now(); + params.refFlowdataKey = timestamp; + //params.refFlowdata = flowdata; + //refFlowdata = flowdata; + + //console.log("flowdata", flowdata); + + cleanUpRefFlowdataObj(); + + refFlowdataObj[timestamp] = flowdata; + + //fix + //params.address = params.adress; + logger.debug("received from terminal", params); + logger.debug("date/time:", new Date()); + logger.debug("tasks length:", tasks.length); + + //tasks = []; + + //add to tasks + tasks.push(params); + + } + } + }) + + + //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) + } + + + /** + * 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; + + RESTBuilder.make(function(builder) { + + if (!builder) return; + + builder.method('GET'); + builder.url('http://192.168.252.2:8004/gettime?projects_id=1'); + + builder.callback(function(err, response, output) { + + 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); + } + + }); + } + + } 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); + + } else { + //console.log("Read-only", stdout); + + 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]: [ + { + "ts": date, + "values": values + } + ] + } + + 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); + } + + //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); + } + } + + 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; + } + + //Dimming, CCT + else if (register == 1) { + let brightness = 0; + let dimming = byte0; + if (dimming > 128) { + //dimming = -128; + brightness = dimming - 128; + } + + //cct + //Ak Byte3 == 1: CCT = (Byte2*256)+Byte1 + let cct; + if (byte3 == 1) cct = byte2 * 256 + byte1; + else cct = bytesToInt(bytes.slice(0, 3)); + + //cct podla auditu + + values["dimming"] = brightness; + return values; + } + + // + else if (register == 4) { + values["master_node_version"] = bytes[1] + "." + bytes[2]; + //logger.debug("FW Version", register, bytes); + } + + //Napätie + else if (register == 74) { + let voltage = (bytesToInt(bytes) * 0.1).toFixed(1); + values["voltage"] = Number(voltage); + } + + //Prúd + else if (register == 75) { + let current = bytesToInt(bytes); + values["current"] = current; + } + + //výkon + else if (register == 76) { + let power = (bytesToInt(bytes) * 0.1).toFixed(2); + values["power"] = Number(power); + } + + //účinník + else if (register == 77) { + let power_factor = Math.cos(bytesToInt(bytes) * 0.1 * (Math.PI / 180)).toFixed(2); + values["power_factor"] = Number(power_factor); + } + + //frekvencia + else if (register == 78) { + let frequency = (bytesToInt(bytes) * 0.1).toFixed(2); + values["frequency"] = Number(frequency); + } + + //energia + else if (register == 79) { + let energy = bytesToInt(bytes); + values["energy"] = energy / 1000; //energia v kWh -> delit 1000 + } + + //doba života + else if (register == 80) { + let lifetime = (bytesToInt(bytes) / 60).toFixed(2); + values["lifetime"] = Number(lifetime); + } + + //nastavenie profilu + else if (register == 8) { + let time_schedule_settings = bytesToInt(bytes); + values["time_schedule_settings"] = time_schedule_settings; + } + + //naklon - nateraz sa z nodu nevycitava! kvoli problemom s accelerometrom a vracanymi hodnotami, posielame temp a x y z vo funkcii accelerometerData() + else if (register == 84) { + values["temperature"] = byte3 >= 128 ? (byte3 - 128) * (-1) : byte3; + values["inclination_x"] = byte2 >= 128 ? (byte2 - 128) * (-1) : byte2; + values["inclination_y"] = byte1 >= 128 ? (byte1 - 128) * (-1) : byte1; + values["inclination_z"] = byte0 >= 128 ? (byte0 - 128) * (-1) : byte0; + } + + //FW verzia nodu + else if (register == 89) { + //formát: "Byte3: Byte2.Byte1 (Byte0)" + values["fw_version"] = byte3 + ":" + byte2 + "." + byte1 + "(" + byte0 + ")"; + } + + else if (register == 87 || register == 6 || register == 7) { + var d = new Date(); + d.setHours(byte3, byte2, 0, 0); + let timestamp = d.getTime(); + + //aktuálny čas + if (register == 87) values["actual_time"] = timestamp; + //čas súmraku + else if (register == 6) values["dusk_time"] = timestamp; + //čas úsvitu + else if (register == 7) values["dawn_time"] = timestamp; + } + + 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; + + } + + function getObjectByTbValue(object, tbname) { + return object[Object.keys(object).find(key => object[key].tbname === tbname)]; + } + + function isObject(item) { + return (typeof item === "object" && !Array.isArray(item) && item !== null); + } + + + // we fake data, that should be received from accelerometer, as they are a bit unreliable. (temperature, x,y,z) + function accelerometerData() { + + if (temperatureInSenica === null) return; + + //clone nodesData and relaysData objects + let nodesData_clone = JSON.parse(JSON.stringify(nodesData)); + let relaysData_clone = JSON.parse(JSON.stringify(relaysData)); + + for (const key in relaysData_clone) { + + const lineData = relaysData_clone[key]; + const lineNumber = lineData.line; + const contactor = lineData.contactor; + + if (lineNumber === 0) continue; + + if (contactor === 1) { + + let date = Date.now(); + + Object.keys(nodesData_clone).forEach((node, index) => { + + setTimeout(function() { + + if (nodesData_clone[node].line === lineNumber) { + + // NOTE: if status of luminaire is NOK or OFFLINE, we do not send data; + let status = nodesData_clone[node].status; + if (status === "OFFLINE" || !status) return; + + let x = null; + if (naklony.hasOwnProperty(node)) x = naklony[node].naklon; + if (x === null) x = 0; + + sendTelemetry({ temperature: Math.round(temperatureInSenica + 10 + Math.floor(Math.random() * 3)), inclination_x: x, inclination_y: 0, inclination_z: 0 }, nodesData_clone[node].tbname, date); + } + + }, (index + 1) * 500); + }) + + } + } + } + + +} // end of instance.export + diff --git a/RVO16/flow/code.js b/RVO16/flow/code.js new file mode 100755 index 0000000..63b31bf --- /dev/null +++ b/RVO16/flow/code.js @@ -0,0 +1,90 @@ +exports.id = 'code'; +exports.title = 'Code'; +exports.group = 'Common'; +exports.color = '#656D78'; +exports.input = true; +exports.output = 1; +exports.author = 'Peter Širka'; +exports.icon = 'code'; +exports.version = '1.2.0'; +exports.options = { outputs: 1, code: 'send(0, value);', keepmessage: true }; + +exports.html = `
+
+
+
@(Number of outputs)
+
@(Minimum is 1)
+
+
+
@(Code)
+
@(Keep message instance)
+
+`; + +exports.readme = `# Code + +This component executes custom JavaScript code as it is and it doesn't contain any secure scope. + +\`\`\`javascript +// value {Object} contains received data +// send(outputIndex, newValue) sends a new value +// error(value) sends an error +// instance {Object} a current component instance +// flowdata {Object} a current flowdata +// repository {Object} a current repository of flowdata +// Example: + +// send() can be execute multiple times +send(0, value); +\`\`\``; + +exports.install = function(instance) { + + var fn; + + instance.on('data', function(response) { + if (fn) { + try { + fn(response.data, instance, response, instance.options, response.repository, require); + } catch (e) { + response.data = e; + instance.throw(response); + } + } + }); + + instance.reconfigure = function() { + try { + if (instance.options.code) { + instance.status(''); + var code = 'var send = function(index, value) { if (options.keepmessage) { flowdata.data = value; instance.send2(index, flowdata); } else instance.send2(index, value);}; var error = function(err) { instance.throw(err); }; ' + instance.options.code; + fn = new Function('value', 'instance', 'flowdata', 'options', 'repository', 'require', code); + } else { + instance.status('Not configured', 'red'); + fn = null; + } + } catch (e) { + fn = null; + instance.error('Code: ' + e.message); + } + }; + + instance.on('options', instance.reconfigure); + instance.reconfigure(); +}; \ No newline at end of file diff --git a/RVO16/flow/comment.js b/RVO16/flow/comment.js new file mode 100755 index 0000000..1e0cd13 --- /dev/null +++ b/RVO16/flow/comment.js @@ -0,0 +1,11 @@ +exports.id = 'comment'; +exports.title = 'Comment'; +exports.group = 'Common'; +exports.color = '#704cff'; +exports.author = 'Martin Smola'; +exports.icon = 'comment'; +exports.traffic = false; +exports.version = '1.0.0'; +exports.readme = '# Comment'; + +exports.install = function() {}; diff --git a/RVO16/flow/count.js b/RVO16/flow/count.js new file mode 100755 index 0000000..fa92ee9 --- /dev/null +++ b/RVO16/flow/count.js @@ -0,0 +1,60 @@ +exports.id = 'count'; +exports.title = 'Count'; +exports.version = '1.0.1'; +exports.author = 'John Graves'; +exports.color = '#656D78'; +exports.icon = 'plus-square'; +exports.input = 2; +exports.output = 1; +exports.options = { increment: 1, initialvalue: 1 }; +exports.readme = `# Counter + +Counter Number of times called.`; + +exports.html = `
+
@(Initial Value)
+
@(Increment)
+

Example Video

+
`; + +exports.readme = `# Count + +This component counts the number of messages received. + +__Response:__ + +Integer value based on the initial value and increment settings. + +__Arguments:__ +- Initial Value: What number should be output on the receipt of the first message. +- Increment: What should the increment be for each following message received.`; + +exports.install = function(instance) { + + var count = 0; + var initialCall = true; + + instance.on('data', function(flowdata) { + var index = flowdata.index; + if (index) { + instance.debug('Reset Count.'); + count = instance.options.initialvalue; + initialCall = true; + } else { + // If this is the first time, set the value to 'initial value' + if(initialCall) { + initialCall = false; + count = instance.options.initialvalue; + } else + count = count+instance.options.increment; + instance.status('Count:' + count); + instance.send2(count); + } + }); + + instance.on('options', function() { + count = instance.options.initialvalue; + initialCall = true; + }); + +}; diff --git a/RVO16/flow/db_connector.js b/RVO16/flow/db_connector.js new file mode 100755 index 0000000..65ee94b --- /dev/null +++ b/RVO16/flow/db_connector.js @@ -0,0 +1,286 @@ +exports.id = 'db_connector'; +exports.title = 'DbConnector'; +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.html = `
+
+
+
DbConnector
+
+
+
`; + +exports.readme = `# read/write data to tables`; + +const instanceSendTo = { + debug: 0, + http_response: 1, +} + +const { promisifyBuilder, makeMapFromDbResult } = require('./helper/db_helper.js'); + +function extractWhereParams(params) +{ + let name = params[0]; + let operator = '='; + let value = params[1]; + + if(params.length == 3) + { + operator = params[1]; + value = params[2]; + } + + return {name: name, operator: operator, value: value}; +} + +exports.install = function(instance) { + + let refFlowdata = null;//holds reference to httprequest flowdata + + instance.on("close", () => { + + }) + + + instance.on("data", async function(flowdata) { + + let params = flowdata.data.body; + console.log("DbConnector", params); + + refFlowdata = flowdata; + + if(refFlowdata != undefined) + { + //make http response + let responseObj = {}; + responseObj["type"] = "SUCESS"; + + try{ + + let table = params.table; + let action = params.action; + + + if(params.data != undefined) + { + let className = params.data.className; + + if(className == "SqlQueryBuilder") + { + let type = params.data.type; + + console.log("SqlQueryBuilder---->", params.data); + + if(type == "SELECT") + { + let table = params.data.queryData.tables[0].table; + + const db = TABLE(table); + var builder = db.find(); + + let result = await promisifyBuilder(builder); + + let response = {}; + response["result"] = result; + response["success"] = true; + + responseObj["data"] = response; + + //console.log(responseObj); + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + } + + return; + } + } + + + console.log("db_connector---->", table, action); + + //actions: read, replace, insert, delete, update... + + if(action == "read") + { + const db = TABLE(params.table); + + //where builder.where('age', '<', 15); + //builder.where('id', 3403); + + var builder = db.find(); + + //https://docs.totaljs.com/latest/en.html#api~DatabaseBuilder~builder.where + if(params.hasOwnProperty("where")) + { + //optionalCan contain "=", "<=", "<", ">=", ">". + //Default value: '=' + + //1.["production_line", 1] + //2. ["or", ["production_line", 1], ["production_line", 2], "end"] + + if (Array.isArray(params.where)) { + + let multipleConditions = false; + + if(params.where[0] == "or") multipleConditions = true; + if (Array.isArray(params.where[0])) multipleConditions = true; + + if(multipleConditions) + { + + for(var i = 0; i < params.where.length; i++) + { + const item = params.where[i]; + + if(item === "or") builder.or(); + + if (Array.isArray(item)) + { + const { name, operator, value } = extractWhereParams(item); + builder.where(name, operator, value); + } + + if(item === "end") builder.end(); + + } + + } + else + { + const { name, operator, value } = extractWhereParams(params.where); + builder.where(name, operator, value); + } + + } + + /* + if(params.where.length >=2 ) + { + let name = params.where[0]; + let operator = '='; + let value = params.where[1]; + + if(params.where.length == 3) + { + operator = params.where[1]; + value = params.where[2]; + } + + builder.where(name, operator, value); + } + */ + } + + if(params.hasOwnProperty("between")) + { + builder.between(params.between[0], params.between[1], params.between[2]); + } + + let response = await promisifyBuilder(builder); + responseObj["data"] = response; + + //console.log(responseObj); + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + + return; + } + + if(action == "delete") + { + + } + + + if(action == "update") + { + //! data receiving from terminal (params) + // { + // hostname: 'localhost', + // table: 'settings', + // action: 'update', + // body: { + // rvo_name: 'terrrr', + // lang: 'en', + // temperature_adress: '28.427B45920702', + // latitude: 48.70826502, + // longitude: 17.28455203, + // mqtt_host: '192.168.252.4', + // mqtt_clientid: 'showroom_test_panel_led', + // mqtt_username: 'xmRd6RJxW53WZe4vMFLU', + // mqtt_port: 1883, + // maintanace_mode: false + // } + // } + const tableToModify = TABLE(params.table); + const newValues = params.body; + + tableToModify.modify(newValues).make(function(builder) { + + builder.callback(function(err, response) { + + if(!err) + { + responseObj["data"] = response; + responseObj["tableUpdated"] = true; + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + } + }); + }); + + } + + if(action == "replace") + { + //truncate table + const db = TABLE(params.table); + var builder = db.remove(); + db.clean(); + + //insert data + let data = params.data; + + for(let i = 0; i < data.length; i++) + { + //console.log(data[i]); + db.insert(data[i]); + } + + console.log("insert done"); + + let responseObj = {}; + responseObj["type"] = "SUCESS"; + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + + + } + + + + } catch (error) { + //console.log(error); + responseObj["type"] = "ERROR"; + responseObj["message"] = error; + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + } + } + }) +} + + diff --git a/RVO16/flow/db_init.js b/RVO16/flow/db_init.js new file mode 100755 index 0000000..b399878 --- /dev/null +++ b/RVO16/flow/db_init.js @@ -0,0 +1,113 @@ +exports.id = 'db_init'; +exports.title = 'DB Initialization'; +exports.group = 'Worksys'; +exports.color = '#888600'; +exports.version = '1.0.2'; +exports.icon = 'sign-out'; +exports.output = 2; + +exports.readme = ` + # DB initialization +`; + +const { promisifyBuilder, makeMapFromDbResult } = require('./helper/db_helper.js'); +const { initNotification } = require('./helper/notification_reporter'); +const errorHandler = require('./helper/ErrorToServiceHandler'); +const total_energy = require('../databases/total_energy'); + +const SEND_TO = { + db_init: 0, + infoSender: 1 +}; + + +exports.install = async function(instance) { + const dbNodes = TABLE("nodes"); + const dbRelays = TABLE("relays"); + const dbSettings = TABLE("settings"); + 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 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.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"]; + Object.keys(dbs.nodesData).forEach(node => dbs.nodesData[node].readout = {}) + + let rvo_number = responseSettings[0]["rvo_name"].match(/\D+(\d{1,2})_/)[1]; + + dbs.settings = { + edge_fw_version: "2025-10-08", //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"], + phases: responseSettings[0]["phases"], + cloud_topic: responseSettings[0]["cloud_topic"], + has_main_switch: responseSettings[0]["has_main_switch"], + daily_report: responseSettings[0]["daily_report"], + send_changed_node_numbers: responseSettings[0]["send_changed_node_numbers"], + rvo_number: rvo_number, + + //dynamic values + masterNodeIsResponding: true, //cmd_manager + maintenance_mode: false, + } + + + dbs.settings.energy_to_switch_lamps = total_energy[rvo_number]; + if (dbs.settings.energy_to_switch_lamps === undefined) console.log('=============== db_init.js: energy_to_switch_lamps is undefined'); + + FLOW.dbLoaded = true; + errorHandler.setProjectId(dbs.settings.project_id); + initNotification(); + + //APP START - send to data services + const toService = { + id: dbs.settings.project_id, + name: dbs.settings.rvo_name, + fw_version: dbs.settings.edge_fw_version, + startdate: new Date().toISOString().slice(0, 19).replace('T', ' '), + js_error: "", + error_message: "" + }; + + instance.send(SEND_TO.infoSender, toService); + console.log("----------------> START - message send to service", toService); + + setTimeout(() => { + console.log("DB_INIT - data loaded"); + instance.send(SEND_TO.db_init, "_") + }, 5000) + +}; + diff --git a/RVO16/flow/debug.js b/RVO16/flow/debug.js new file mode 100755 index 0000000..00cb259 --- /dev/null +++ b/RVO16/flow/debug.js @@ -0,0 +1,100 @@ +exports.id = 'debug'; +exports.title = 'Debug'; +exports.author = 'Peter Širka'; +exports.color = '#967ADC'; +exports.click = true; +exports.input = true; +exports.icon = 'bug'; +exports.version = '2.0.4'; +exports.options = { enabled: true, repository: false, type: 'data' }; +exports.readme = `# Debug + +Prints data to the debug tab.`; + +exports.html = `
+
+
+
@(Output type)
+
@(Path to the property (leave empty to show the whole data object))
+
@(A group name)
+
@(Enabled)
+
+
+
`; + +exports.install = function(instance) { + + instance.on('data', function(response) { + if (instance.options.enabled) { + + var opt = instance.options; + var rep = response.repository; + var val = response.data; + var id = response.id; + + switch (instance.options.type){ + case 'both': + var data = {}; + data.repository = rep; + data.data = val instanceof Error ? { error: val.message, stack: val.stack } : val; + instance.debug(safeparse(opt.property ? U.get(data, opt.property) : data), undefined, opt.group, id); + break; + case 'repository': + instance.debug(safeparse(opt.property ? U.get(rep, opt.property) : rep), undefined, opt.group, id); + break; + case 'data': + default: + if (val instanceof Error) + instance.debug({ error: val.message, stack: val.stack }, undefined, opt.group, id); + else + instance.debug(safeparse(opt.property ? U.get(val, opt.property) : val), undefined, opt.group, id); + break; + } + } + }); + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + instance.save(); + }); + + instance.on('options', function() { + instance.custom.status(); + }); + + instance.custom.status = function() { + instance.status(instance.options.enabled ? 'Enabled' : 'Disabled'); + }; + + instance.custom.status(); + + function safeparse(o) { + + if (o instanceof Buffer) + return o; + + if (o === undefined) + return 'undefined'; + + if (o === null) + return 'null'; + + var cache = []; + var str = JSON.stringify(o, function(key, value) { + if (typeof value === 'object' && value !== null) { + if (cache.indexOf(value) !== -1) { + try { + return JSON.parse(JSON.stringify(value)); + } catch (error) { + return; + } + } + cache.push(value); + } + return value; + }); + cache = null; + return JSON.parse(str); + } +}; diff --git a/RVO16/flow/designer.json b/RVO16/flow/designer.json new file mode 100755 index 0000000..4a54399 --- /dev/null +++ b/RVO16/flow/designer.json @@ -0,0 +1,3102 @@ +{ + "tabs": [ + { + "name": "MAIN PUSH", + "linker": "main-push", + "id": "1612772287426", + "index": 0 + }, + { + "name": "CMD manager", + "linker": "cmd-manager", + "id": "1615551125555", + "index": 1 + }, + { + "name": "Devices", + "linker": "devices", + "id": "1611921777196", + "index": 2 + } + ], + "components": [ + { + "id": "1611951142547", + "component": "debug", + "tab": "1611921777196", + "name": "ERROR", + "x": 598, + "y": 60, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#DA4453", + "notes": "" + }, + { + "id": "1612776786008", + "component": "wsmqttpublish", + "tab": "1612772287426", + "name": "WS MQTT publish", + "x": 281.75, + "y": 174, + "connections": { + "0": [ + { + "index": "0", + "id": "1615551060773" + } + ], + "1": [ + { + "index": "0", + "id": "1618300858252" + }, + { + "index": "0", + "id": "1618558465485" + } + ], + "2": [ + { + "index": "0", + "id": "1634303685503" + } + ], + "3": [ + { + "index": "0", + "id": "1731068754606" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Connected", + "color": "green" + }, + "options": { + "username": "", + "clientid": "", + "port": "1883", + "host": "" + }, + "color": "#888600", + "notes": "" + }, + { + "id": "1612778461252", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "tb-push", + "x": 72.75, + "y": 328, + "connections": { + "0": [ + { + "index": "0", + "id": "1612783322136" + }, + { + "index": "1", + "id": "1612776786008" + }, + { + "index": "0", + "id": "1731068754606" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1612783322136", + "component": "debug", + "tab": "1612772287426", + "name": "to TB", + "x": 283.75, + "y": 324, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615551060773", + "component": "debug", + "tab": "1612772287426", + "name": "errors from MQTT Broker", + "x": 594, + "y": 57, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#DA4453", + "notes": "" + }, + { + "id": "1615563373927", + "component": "debug", + "tab": "1615551125555", + "name": "Debug", + "x": 755, + "y": 155, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#DA4453", + "notes": "" + }, + { + "id": "1615566865233", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "tb-push", + "x": 755, + "y": 248, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1615798582262", + "component": "debug", + "tab": "1615551125555", + "name": "CMD_debug", + "x": 755, + "y": 346, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615802995322", + "component": "debug", + "tab": "1611921777196", + "name": "Debug", + "x": 596.8833312988281, + "y": 566.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Disabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": false + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615809128443", + "component": "debug", + "tab": "1611921777196", + "name": "tempToTb", + "x": 595.8833312988281, + "y": 658.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615809595184", + "component": "virtualwireout", + "tab": "1611921777196", + "name": "tb-push", + "x": 597.8833312988281, + "y": 377.25, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1616165795916", + "component": "httproute", + "tab": "1615551125555", + "name": "POST /terminal", + "x": 135, + "y": 547, + "connections": { + "0": [ + { + "index": "0", + "id": "1684060205000" + }, + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Listening", + "color": "green" + }, + "options": { + "timeout": 10, + "cachepolicy": 0, + "cacheexpire": "5 minutes", + "size": 5, + "url": "/terminal", + "method": "POST", + "name": "", + "flags": [ + "id:1616165795916", + "post", + 10000 + ], + "emptyresponse": false + }, + "color": "#5D9CEC", + "notes": "### Configuration\n\n- __POST /terminal__\n- flags: \n- maximum request data length: __5 kB__\n- empty response: __false__\n- cache policy: __no cache__\n- cache expire: __5 minutes__", + "cloning": false + }, + { + "id": "1616165824813", + "component": "httpresponse", + "tab": "1615551125555", + "name": "HTTP Response", + "x": 753, + "y": 423, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "json" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1617104731852", + "component": "debug", + "tab": "1615551125555", + "name": "DIDO_Debug", + "x": 669, + "y": 1040, + "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": "turnOff line", + "x": 133, + "y": 1161, + "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": 669, + "y": 1150, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1617284749681", + "component": "trigger", + "tab": "1615551125555", + "name": "update profile / node", + "x": 112, + "y": 208, + "connections": { + "0": [ + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "string", + "data": "profile_nodes" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1618235171399", + "component": "trigger", + "tab": "1615551125555", + "name": "tun tasks", + "x": 184, + "y": 279, + "connections": { + "0": [ + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "data": "run" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1618300858252", + "component": "debug", + "tab": "1612772287426", + "name": "wsmqtt-exit1", + "x": 597.8833312988281, + "y": 149, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1618393583970", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "to-cmd-manager", + "x": 668.8833312988281, + "y": 1269, + "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": 132.88333129882812, + "y": 367, + "connections": { + "0": [ + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "platform-rpc-call", + "color": "gray" + }, + "options": { + "wirename": "platform-rpc-call" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1618393759854", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "cmd_to_dido", + "x": 119.88333129882812, + "y": 1007, + "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": 752.8833312988281, + "y": 527, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "cmd_to_dido", + "color": "gray" + }, + "options": { + "wirename": "cmd_to_dido" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1618558465485", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "platform-rpc-call", + "x": 597.8833312988281, + "y": 247, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "platform-rpc-call", + "color": "gray" + }, + "options": { + "wirename": "platform-rpc-call" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1618572059773", + "component": "trigger", + "tab": "1615551125555", + "name": "turnOn line", + "x": 132, + "y": 1085, + "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": 452.1091003417969, + "y": 341.05455017089844, + "connections": { + "0": [ + { + "index": "0", + "id": "1615563373927" + } + ], + "1": [ + { + "index": "0", + "id": "1615566865233" + }, + { + "index": "0", + "id": "1615798582262" + } + ], + "2": [ + { + "index": "0", + "id": "1616165824813" + } + ], + "3": [ + { + "index": "0", + "id": "1618393827655" + } + ], + "4": [ + { + "index": "0", + "id": "1635936391935" + } + ], + "5": [ + { + "index": "0", + "id": "1757006030239" + }, + { + "index": "0", + "id": "1757006060377" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1619605019281", + "component": "httproute", + "tab": "1615551125555", + "name": "GET db", + "x": 173, + "y": 653, + "connections": { + "0": [ + { + "index": "0", + "id": "1684060205000" + }, + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Listening", + "color": "green" + }, + "options": { + "timeout": 5, + "cachepolicy": 0, + "cacheexpire": "5 minutes", + "size": 5, + "url": "/db", + "method": "GET", + "name": "", + "flags": [ + "id:1619605019281", + "get", + 5000 + ] + }, + "color": "#5D9CEC", + "notes": "### Configuration\n\n- __GET /db__\n- flags: undefined\n- maximum request data length: __5 kB__\n- empty response: __undefined__\n- cache policy: __no cache__\n- cache expire: __5 minutes__", + "cloning": false + }, + { + "id": "1619784672383", + "component": "trigger", + "tab": "1615551125555", + "name": "turnOnAlarm", + "x": 120, + "y": 1234, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "data": "{command: \"turnOnAlarm\"}", + "datatype": "object" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1619784812964", + "component": "trigger", + "tab": "1615551125555", + "name": "turnOffAlarm", + "x": 118, + "y": 1307, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "data": "{command: \"turnOffAlarm\"}", + "datatype": "object" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1621340721628", + "component": "virtualwireout", + "tab": "1611921777196", + "name": "modbus_to_dido", + "x": 599, + "y": 471, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "modbus_to_dido", + "color": "gray" + }, + "options": { + "wirename": "modbus_to_dido" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1622640022885", + "component": "httproute", + "tab": "1615551125555", + "name": "POST /db_connector", + "x": 98, + "y": 1586, + "connections": { + "0": [ + { + "index": "0", + "id": "1622640073521" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Listening", + "color": "green" + }, + "options": { + "timeout": 5, + "cachepolicy": 0, + "cacheexpire": "5 minutes", + "size": 5, + "url": "/db_connector", + "method": "POST", + "flags": [ + "id:1622640022885", + "post", + 5000 + ] + }, + "color": "#5D9CEC", + "notes": "### Configuration\n\n- __POST /db_connector__\n- flags: \n- maximum request data length: __5 kB__\n- empty response: __undefined__\n- cache policy: __no cache__\n- cache expire: __5 minutes__", + "cloning": false + }, + { + "id": "1622640073521", + "component": "db_connector", + "tab": "1615551125555", + "name": "DbConnector", + "x": 372, + "y": 1572, + "connections": { + "1": [ + { + "index": "0", + "id": "1622641420685" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "edge": "undefined" + }, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1622641420685", + "component": "httpresponse", + "tab": "1615551125555", + "name": "HTTP Response", + "x": 596, + "y": 1586, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1634303504177", + "component": "monitormemory", + "tab": "1612772287426", + "name": "RAM", + "x": 69.88333129882812, + "y": 888.5, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465281992" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "825.84 MB / 985.68 MB", + "color": "gray" + }, + "options": { + "enabled": true, + "interval": 30000 + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1634303533779", + "component": "monitordisk", + "tab": "1612772287426", + "name": "disk", + "x": 70.88333129882812, + "y": 982.5, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465821120" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "5.78 GB / 7.26 GB", + "color": "gray" + }, + "options": { + "enabled": true, + "path": "/", + "interval": 30000 + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1634303595494", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "send-to-services", + "x": 51.883331298828125, + "y": 1400.5, + "connections": { + "0": [ + { + "index": "0", + "id": "1634463186563" + }, + { + "index": "1", + "id": "1634488120710" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1634303602169", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "send-to-services", + "x": 426.8833312988281, + "y": 878.5, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1634303685503", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "send-to-services", + "x": 600.8833312988281, + "y": 341.5, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1634303743260", + "component": "httprequest", + "tab": "1612772287426", + "name": "192.168.252.2:8004/sentmessage", + "reference": "", + "x": 506.8833312988281, + "y": 1331.7333374023438, + "connections": { + "0": [ + { + "index": "0", + "id": "1635327431236" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "stringify": "json", + "method": "POST", + "url": "http://192.168.252.2:8004/sentmessage" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1634463186563", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 305.75, + "y": 1442, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634464580289", + "component": "code", + "tab": "1612772287426", + "name": "Code", + "x": 245, + "y": 787, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465243324" + }, + { + "index": "0", + "id": "1634303602169" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "keepmessage": true, + "code": "let response = {};\nresponse.cpu = value.cpu;\nresponse.uptime = value.uptime;\n\nsend(0, response);", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1634465243324", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 428, + "y": 784, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634465281992", + "component": "code", + "tab": "1612772287426", + "name": "Code", + "x": 245, + "y": 884, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465338103" + }, + { + "index": "0", + "id": "1634303602169" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "keepmessage": true, + "code": "value.sender = \"ram\";\n\nlet response = {};\n\nresponse.memory_total = Math.round(value.total / (1024 ** 2));\nresponse.memory_free = Math.round(value.free / (1024 ** 2));\nresponse.memory_used = Math.round(value.used / (1024 ** 2));\n\nsend(0, response);", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1634465338103", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 429, + "y": 976, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634465821120", + "component": "code", + "tab": "1612772287426", + "name": "Code", + "x": 245, + "y": 978, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465892500" + }, + { + "index": "0", + "id": "1634303602169" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "keepmessage": true, + "code": "value.sender = \"hdd\";\n\nlet response = {};\n\nresponse.hdd_total = Math.round(value.total / (1024 ** 2));\nresponse.hdd_free = Math.round(value.free / (1024 ** 2));\nresponse.hdd_used = Math.round(value.used / (1024 ** 2));\n\nsend(0, response);", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1634465892500", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 432, + "y": 1068, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634484067516", + "component": "debug", + "tab": "1612772287426", + "name": "Send info", + "x": 513, + "y": 1441, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634488120710", + "component": "infosender", + "tab": "1612772287426", + "name": "Info sender", + "x": 301, + "y": 1336, + "connections": { + "0": [ + { + "index": "0", + "id": "1634484067516" + }, + { + "index": "0", + "id": "1634303743260" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "edge": "undefined" + }, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1635327431236", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 837.8833312988281, + "y": 1325.5, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1635936391935", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "send-to-services", + "x": 753, + "y": 623, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1637069803394", + "component": "monitorconsumption", + "tab": "1612772287426", + "name": "CPU", + "x": 69, + "y": 791, + "connections": { + "0": [ + { + "index": "0", + "id": "1634464580289" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "1.1% / 88.25 MB", + "color": "gray" + }, + "options": { + "monitorfiles": true, + "monitorconnections": true, + "monitorsize": true, + "monitorconsumption": true, + "enabled": true, + "interval": 30000 + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1683664161036", + "component": "debug", + "tab": "1615551125555", + "name": "CMDtoDIDO", + "x": 392, + "y": 1012, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1683981346282", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "from-dido-controller", + "x": 112, + "y": 459, + "connections": { + "0": [ + { + "index": "0", + "id": "1684055037116" + }, + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "from-dido-controller", + "color": "gray" + }, + "options": { + "wirename": "from-dido-controller" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1684055037116", + "component": "debug", + "tab": "1615551125555", + "name": "from dido to cmd", + "x": 451, + "y": 532, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1684060205000", + "component": "debug", + "tab": "1615551125555", + "name": "HTTP routes", + "x": 450, + "y": 639, + "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": "MDBToDido", + "x": 598, + "y": 147, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1699963668903", + "component": "dido_controller", + "tab": "1615551125555", + "name": "DIDO_Controller", + "x": 397, + "y": 1131, + "connections": { + "0": [ + { + "index": "0", + "id": "1617104731852" + } + ], + "1": [ + { + "index": "0", + "id": "1617104731852" + }, + { + "index": "0", + "id": "1617115013095" + } + ], + "2": [ + { + "index": "0", + "id": "1618393583970" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "edge": "undefined" + }, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1699964678894", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "modbus_to_dido", + "x": 96, + "y": 924, + "connections": { + "0": [ + { + "index": "0", + "id": "1699963668903" + }, + { + "index": "0", + "id": "1699964793925" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "modbus_to_dido", + "color": "gray" + }, + "options": { + "wirename": "modbus_to_dido" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1699964793925", + "component": "debug", + "tab": "1615551125555", + "name": "modbusToDido", + "x": 388, + "y": 920, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1699965957410", + "component": "modbus_reader", + "tab": "1611921777196", + "name": "Modbus reader", + "x": 232, + "y": 175, + "connections": { + "0": [ + { + "index": "0", + "id": "1611951142547" + } + ], + "1": [ + { + "index": "0", + "id": "1621340721628" + }, + { + "index": "0", + "id": "1684179110403" + }, + { + "index": "0", + "id": "1717441414646" + } + ], + "2": [ + { + "index": "0", + "id": "1615809595184" + }, + { + "index": "0", + "id": "1714752862828" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1700411878636", + "component": "thermometer", + "tab": "1611921777196", + "name": "Thermometer", + "x": 234.75, + "y": 444, + "connections": { + "0": [ + { + "index": "0", + "id": "1615802995322" + } + ], + "1": [ + { + "index": "0", + "id": "1615809595184" + }, + { + "index": "0", + "id": "1615809128443" + } + ], + "2": [ + { + "index": "0", + "id": "1621340721628" + }, + { + "index": "0", + "id": "1732889185927" + }, + { + "index": "0", + "id": "1717441414646" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#5CB36D", + "notes": "" + }, + { + "id": "1714752862828", + "component": "debug", + "tab": "1611921777196", + "name": "MDBToTb", + "x": 766, + "y": 324, + "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": 764.0833282470703, + "y": 222, + "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\telse if(value.status === \"NOK-thermometer\")\n\t{\n\t\tsend(0, {\"thermometer\": \"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\telse if(value.values.hasOwnProperty(\"temperature\"))\n\t{\n\t\tsend(0, {\"thermometer\": \"OK\"});\n\t}\n}", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1717442627834", + "component": "debug", + "tab": "1611921777196", + "name": "modbus service", + "x": 966.0833282470703, + "y": 165, + "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": 968.0833282470703, + "y": 268, + "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": 88.75, + "y": 1685, + "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": 296, + "y": 1671, + "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\", \"Flow has been restarted\", \"Node db has changed\"]", + "types": "[\"emergency\", \"critical\", \"error\", \"alert\"]", + "name": "rvo_senica_16_10.0.0.131" + }, + "color": "#30E193", + "notes": "" + }, + { + "id": "1718016073501", + "component": "httprequest", + "tab": "1612772287426", + "name": "http://192.168.252.2:8004/slack", + "x": 495, + "y": 1753, + "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": 832, + "y": 1664, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "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": 87, + "y": 1591, + "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": "" + }, + { + "id": "1729855334955", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "platform-rpc-call", + "x": 599.9333343505859, + "y": 541.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "platform-rpc-call", + "color": "gray" + }, + "options": { + "wirename": "platform-rpc-call" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1729855371093", + "component": "debug", + "tab": "1612772287426", + "name": "rpc cloud", + "x": 601.9333343505859, + "y": 440.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1731068658334", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 75.75, + "y": 184, + "connections": { + "0": [ + { + "index": "0", + "id": "1612776786008" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731068754606", + "component": "cloudmqttconnect", + "tab": "1612772287426", + "name": "MQTT to senica-prod01", + "x": 284.75, + "y": 452, + "connections": { + "1": [ + { + "index": "0", + "id": "1729855371093" + }, + { + "index": "0", + "id": "1729855334955" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Connected", + "color": "green" + }, + "options": { + "username": "", + "clientid": "", + "port": "2764", + "host": "192.168.252.2", + "topic": "u131" + }, + "color": "#888600", + "notes": "" + }, + { + "id": "1731069001548", + "component": "db_init", + "tab": "1612772287426", + "name": "DB Initialization", + "x": 1003.75, + "y": 240.25, + "connections": { + "0": [ + { + "index": "0", + "id": "1731069033416" + } + ], + "1": [ + { + "index": "0", + "id": "1747561603739" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#888600", + "notes": "" + }, + { + "id": "1731069033416", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "db-init", + "x": 1244.75, + "y": 233.25, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069059135", + "component": "showdb", + "tab": "1612772287426", + "name": "Show db data", + "x": 1186.75, + "y": 821.25, + "connections": { + "0": [ + { + "index": "0", + "id": "1731069079243" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#888600", + "notes": "" + }, + { + "id": "1731069079243", + "component": "debug", + "tab": "1612772287426", + "name": "dbData", + "x": 1390.75, + "y": 870.25, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1731069116691", + "component": "trigger", + "tab": "1612772287426", + "name": "settings", + "x": 934.75, + "y": 669.75, + "connections": { + "0": [ + { + "index": "0", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069131637", + "component": "trigger", + "tab": "1612772287426", + "name": "relaysData", + "x": 876.75, + "y": 733.75, + "connections": { + "0": [ + { + "index": "1", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069137374", + "component": "trigger", + "tab": "1612772287426", + "name": "nodesData", + "x": 852.75, + "y": 794.75, + "connections": { + "0": [ + { + "index": "2", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069179846", + "component": "trigger", + "tab": "1612772287426", + "name": "pinsData", + "x": 850.75, + "y": 861.75, + "connections": { + "0": [ + { + "index": "3", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069192937", + "component": "trigger", + "tab": "1612772287426", + "name": "sample data", + "x": 857.75, + "y": 928.75, + "connections": { + "0": [ + { + "index": "4", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069264443", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 63.75, + "y": 1279, + "connections": { + "0": [ + { + "index": "0", + "id": "1634488120710" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069334626", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "db-init", + "x": 172.88333129882812, + "y": 129, + "connections": { + "0": [ + { + "index": "0", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069548145", + "component": "virtualwirein", + "tab": "1611921777196", + "name": "db-init", + "x": 46.75, + "y": 192, + "connections": { + "0": [ + { + "index": "0", + "id": "1699965957410" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069567152", + "component": "virtualwirein", + "tab": "1611921777196", + "name": "db-init", + "x": 44.75, + "y": 465, + "connections": { + "0": [ + { + "index": "0", + "id": "1700411878636" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731070156936", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "db-init", + "x": 126.88333129882812, + "y": 1377, + "connections": { + "0": [ + { + "index": "2", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731234189516", + "component": "trigger", + "tab": "1612772287426", + "name": "monitor.txt", + "x": 882.75, + "y": 991.75, + "connections": { + "0": [ + { + "index": "5", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731234189551", + "component": "trigger", + "tab": "1612772287426", + "name": "err.txt", + "x": 904.75, + "y": 1053.75, + "connections": { + "0": [ + { + "index": "6", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1732700042559", + "component": "nodesdb_change_check", + "tab": "1612772287426", + "name": "Nodes DB change check", + "x": 266.8833312988281, + "y": 1980.2333984375, + "connections": { + "0": [ + { + "index": "0", + "id": "1732700071298" + }, + { + "index": "0", + "id": "1732700642917" + } + ], + "1": [ + { + "index": "0", + "id": "1759958914348" + }, + { + "index": "0", + "id": "1759959003114" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#888600", + "notes": "" + }, + { + "id": "1732700057052", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 76.75, + "y": 1988, + "connections": { + "0": [ + { + "index": "0", + "id": "1732700042559" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1732700071298", + "component": "debug", + "tab": "1612772287426", + "name": "nodesChange", + "x": 571.8833312988281, + "y": 2018.2333984375, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1732700642917", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "tb-push", + "x": 567.8833312988281, + "y": 1933, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1732889185927", + "component": "debug", + "tab": "1611921777196", + "name": "tempToDido", + "x": 594.8833312988281, + "y": 753, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1733574412965", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 72.75, + "y": 474, + "connections": { + "0": [ + { + "index": "1", + "id": "1731068754606" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1747561603739", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "send-to-services", + "x": 1243.8833312988281, + "y": 334.5, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1747562867845", + "component": "comment", + "tab": "1612772287426", + "name": "FLOW STARTING POINT", + "x": 1003.5666656494141, + "y": 178, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#704cff", + "notes": "" + }, + { + "id": "1749211698385", + "component": "trigger", + "tab": "1612772287426", + "name": "deviceStatus", + "x": 911.75, + "y": 1116.75, + "connections": { + "0": [ + { + "index": "7", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1757006030239", + "component": "httprequest", + "tab": "1615551125555", + "name": "192.168.252.2:8015/daily_report", + "x": 756.5666656494141, + "y": 715.4499969482422, + "connections": { + "0": [ + { + "index": "0", + "id": "1757006045804" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "url": "http://192.168.252.2:8015/daily_report", + "method": "POST", + "stringify": "json" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1757006045804", + "component": "debug", + "tab": "1615551125555", + "name": "ddd", + "x": 1091.566665649414, + "y": 711.4499969482422, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1757006060377", + "component": "debug", + "tab": "1615551125555", + "name": "reportDebug", + "x": 749.5666656494141, + "y": 799.4499969482422, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1759958914348", + "component": "httprequest", + "tab": "1612772287426", + "name": "http://192.168.252.2:8015/node_numbers", + "x": 571, + "y": 2111, + "connections": { + "0": [ + { + "index": "0", + "id": "1759958927094" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "url": "http://192.168.252.2:8015/node_numbers", + "method": "POST", + "stringify": "json" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1759958927094", + "component": "debug", + "tab": "1612772287426", + "name": "nodesChangeCloud", + "x": 951.8833312988281, + "y": 2109.2333984375, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1759959003114", + "component": "debug", + "tab": "1612772287426", + "name": "nodeChangeCloud1", + "x": 574, + "y": 2218, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1760020290879", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 84.75, + "y": 1787, + "connections": { + "0": [ + { + "index": "1", + "id": "1718016052341" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + } + ], + "version": 615 +} \ No newline at end of file diff --git a/RVO16/flow/dido_controller.js b/RVO16/flow/dido_controller.js new file mode 100755 index 0000000..d16fb19 --- /dev/null +++ b/RVO16/flow/dido_controller.js @@ -0,0 +1,1486 @@ +exports.id = 'dido_controller'; +exports.title = 'DIDO_Controller'; +exports.version = '2.0.0'; +exports.group = 'Worksys'; +exports.color = '#2134B0'; +exports.input = 3; +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 + +state_of_main_switch - reportovat stav hlaveho istica : 0-> off 1-> on +rotary_switch_state - sem by sa mal reportovat stav vstupov manual a auto pola nasledovnej logiky: Manual = 1 a Auto = 0 -> Manu +Manual = 0 a Auto = 0 -> Off, Manual = 0 a Auto = 1 -> Automatic + +door_condition - pin 6, dverový kontakt -> 1 -> vyreportuje Closed, 0 -> vyreportuje Ope +twilight_sensor - hodnotu, ktoru vracia ten analogovy vstup (17) treba poslat sem ako float number. Zrejme tu potom pridame nejaky koeficient prevodu na luxy + +Na kazdu liniu +state_of_breaker - podla indexu istica sa reportuje jeho stav, teda istic na liniu 1: 0-> off, 1-> on +state_of_contactor - podla indexu stkaca sa reportuje jeho stav, teda stykac 1 na liniu 1: 0-> off, 1-> on +*/ + +const { errLogger, logger, monitor } = require('./helper/logger'); +const SerialPort = require('serialport'); +const WebSocket = require('ws'); +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 errorHandler = require('./helper/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 hasMainSwitch; + +let alarmStatus = "OFF"; + +const SEND_TO = { + debug: 0, + tb: 1, + cmd_manager: 2 +} + + +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 = {}; + let rsPortReceivedData = []; + + //to be able to get proper twilight values + let twilight_sensor_interval = 5;//minutes + let twilight_sensor = []; + const twilight_sensor_array = []; + let twilightError = false; + + monitor.info("DIDO_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-we make it global to see it from outside + FLOW.deviceStatus = { //key is device name: temperature,.... + "state_of_main_switch": "Off", //Hlavny istic (alebo druhy dverovy kontakt) + "rotary_switch_state": "Off", //Prevadzkovy + "door_condition": "closed", //Dverový kontakt + "em": "OK", //elektromer rvo + "temperature": "OK", //templomer + "battery": "OK", //Bateria + "power_supply": "OK", //Zdroj + "master_node": "OK", //MN - GLOBALS.settings.masterNodeIsResponding + "no_voltage": "OK", //GLOBALS.settings.no_voltage - vypadok napatia na faze + "state_of_breaker": {}, //"Off",//Istic + "state_of_contactor": {}, //"Off",//Stykac + "twilight_sensor": "OK" //lux sensor + }; + let deviceStatus = FLOW.deviceStatus; + + + function main() { + + GLOBALS = FLOW.GLOBALS; + SETTINGS = FLOW.GLOBALS.settings; + rvoTbName = SETTINGS.rvoTbName; + pinsData = GLOBALS.pinsData; + relaysData = GLOBALS.relaysData; + + tbHandler = new DataToTbHandler(SEND_TO.tb); + tbHandler.setSender(exports.title); + + controller_type = SETTINGS.controller_type; //"lm" or "unipi" + hasMainSwitch = SETTINGS.has_main_switch; + + if (controller_type == "") controller_type = "lm"; + + 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, "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; + } + } + + //report RVO version relaysData[0].tbname; + let values = {}; + values["edge_fw_version"] = SETTINGS.edge_fw_version; + values["maintenance_mode"] = SETTINGS.maintenance_mode; + + sendTelemetry(values, rvoTbName); + + 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); + } + + + function handleRsPort() { + + if (rsPort) { + rsPort.removeAllListeners(); + rsPort = null; + } + + //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('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) { + if (!err) { + monitor.info(exports.title + "--->Digital in_out has been set (runSyncExec was sucessfull)"); + + turnAlarm("off"); + 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('error', err => { + let message = "Dido: rsPort error: " + err.message; + logger.debug(message); + monitor.info(message); + errorHandler.sendMessageToService(message); + }) + + rsPort.on("close", () => { + let message = "Dido: rsPort closed - reconnecting ..."; + logger.debug(message); + monitor.info(message); + setTimeout(handleRsPort, 1000); + }) + + rsPort.open(); + } + + + function handleWebSocket() { + + if (ws) { + ws.removeAllListeners(); + ws = null; + } + + //to keep websocket opened, we send request every 150 seconds + let startRequests = null; + + console.log("handleWebSocket function called"); + ws = new WebSocket('ws:/0.0.0.0:1234/ws'); + + ws.onopen = function open() { + + instance.send(0, exports.title + " running"); + turnAlarm("off"); + + initialSetting(); + + setTimeout(function() { ws.send(JSON.stringify({ cmd: "all" })) }, 5000); + // we request dev info about neuron device from evok to keep websocket connection alive + // for some reason this request returns no data, but connection keeps alive + startRequests = setInterval(() => { + ws.send(JSON.stringify({ "cmd": "filter", "dev": ["neuron"] })); + }, 150000) + }; + + + // 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 = async 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; + + 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 => { + logger.debug('Dido: websocket error', err); + }) + + ws.onclose = function() { + logger.debug('Dido: websocket onclose, reconnecting...') + clearInterval(startRequests); + setTimeout(handleWebSocket, 1000); + } + } + + 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 turnAlarm(onOrOff) { + let value = 0; + if (onOrOff == "on") value = 1; + + if (value == 1 && SETTINGS.maintenance_mode) return; + + alarmStatus = "OFF"; + if (value == 1) alarmStatus = "ON"; + + if (rsPort) { + let arr = [0x55]; + arr.push(13); + arr.push(0); + arr.push(value); + + rsPort.write(Buffer.from(arr), function(err) { + logger.debug(`sirena - ${onOrOff}`); + }); + } + else if (ws) { + let cmd = { "cmd": "set", "dev": "relay", "circuit": "1_01", "value": value }; + ws.send(JSON.stringify(cmd)); + logger.debug(`sirena - ${onOrOff}`); + } + } + + + 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") { + bits.push(0); + } + else bits.push(1); + + if (deviceStatus["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); + } + + + // turn line on or off + function turnLine(onOrOff, line, pin, force, info) { + //onOrOff => "on" or "off" + let value = 0; + if (onOrOff == "on") value = 1; + + if (force == undefined) force = false; + + if (line == 0) { + if (value == 1 && alarmStatus == "ON") turnAlarm("off"); + SETTINGS.maintenance_mode = value ? true : false; + + 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); + return; + } + + if (pin === undefined) pin = getPin(line); + + if (pin === undefined) { + errLogger.error("pin is undefined!", line); + return; + } + + if (!force) { + if (relaysData[line].contactor == value) { + instance.send(SEND_TO.debug, `line is already ${onOrOff} ` + line); + logger.debug(`Dido: turnLine: line is already ${onOrOff} `, line); + return; + } + } + + // if(!rsPort.isOpen && !ws) + if (!rsPort && !ws) { + errLogger.error("Dido - port or websocket is not opened"); + return; + } + + if (rsPort) { + let arr = [0x55]; + arr.push(pin); + arr.push(0); + arr.push(value); + + rsPort.write(Buffer.from(arr), function(err) { + if (err === undefined) { + monitor.info(`Dido: turnLine ${onOrOff} zapisal do rsPort-u`, line, pin, arr, info); + switchLogic(arr); + } + else { + monitor.info(`Dido: turnLine ${onOrOff} WRITE error`, err); + } + }); + + } + else if (ws) { + //pin = "relay1_03" or "input1_01" ... we must make just "1_01" with slice method + monitor.info(`Dido: turnLine ${onOrOff} - (line, pin, force)`, line, pin, force, info); + let cmd = { "cmd": "set", "dev": "relay", "circuit": pin.slice(5), "value": value }; + ws.send(JSON.stringify(cmd)); + } + + //if rvo is 24/7, it has just one switching profile point at 13:00. we do not want to send notification as it repeats every day. + //const d = new Date(); + //if(d.getHours() != 13) sendNotification("Dido_controller: ", SETTINGS.rvoTbName, "switching_profile_point_applied_to_line", { line: line, value: onOrOff }, "", SEND_TO.tb, instance); + } + + + // 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; + + // 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) { + const status = flowdata.data.status; + if (status == "NOK-twilight_sensor") { + deviceStatus["twilight_sensor"] = "NOK"; + } + else if (status == "NOK-em340" || status == "NOK-em111") { + deviceStatus["em"] = "NOK"; + } + else if (status == "NOK-thermometer") { + deviceStatus["temperature"] = "NOK"; + } + } + else if ("values" in flowdata.data) { + 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" + } + else if (values.hasOwnProperty("temperature")) { + deviceStatus["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"; + } + + sendTelemetry(values, rvoTbName); + } + + sendRvoStatus(); + }) + + + + + // we expect array as flowdata.data + instance.on("1", flowdata => { + + //console.log(flowdata.data); + + if (!flowdata.data instanceof Object) return; + + let obj = flowdata.data; + let line = obj.line; + 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"); + }) + + + function calculateStateCode() { + + let bits = []; + + //Hlavny istic - state_of_main_switch => v rvo senica je to druhy door pre silovu cast (EM) + if (deviceStatus["state_of_main_switch"] === "closed" || deviceStatus["state_of_main_switch"] === "Off") { + bits.push(0); + } + else { + bits.push(1); + } + + //Prevadzkovy mod - Manual, Off, Automatic, maintenance_mode = true/false // DAVA 2 BITY + if (!SETTINGS.maintenance_mode) { + if (deviceStatus["rotary_switch_state"] === "Manual") { + bits.push(0); + bits.push(1); + } + + if (deviceStatus["rotary_switch_state"] === "Automatic") { + bits.push(0); + bits.push(0); + } + + if (deviceStatus["rotary_switch_state"] === "Off") { + bits.push(1); + bits.push(0); + } + } + else { + bits.push(1); + bits.push(1); + } + + //Dverovy kontakt + if (deviceStatus["door_condition"] === "closed") { + bits.push(0); + } + else { + bits.push(1); + } + + //EM + if (deviceStatus["em"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //Teplomer + if (deviceStatus["temperature"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //Batéria + if (deviceStatus["battery"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //Zdroj + if (deviceStatus["power_supply"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //MN + if (deviceStatus["master_node"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //výpadok napätia na fáze + if (deviceStatus["no_voltage"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + if (deviceStatus["twilight_sensor"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + // doplnime do 16 bitov (2 byty) + for (let i = bits.length; i < 16; i++) { + bits.push(0); + } + + // console.log("calculateStateCode - deviceStatus", deviceStatus); + // 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; + } + + + async function sendRvoStatus() { + + if (SETTINGS === undefined) return; + SETTINGS.masterNodeIsResponding ? deviceStatus["master_node"] = "OK" : deviceStatus["master_node"] = "NOK"; + + 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 pinsForRvoStatus(controllerType, hasMainSwitch) { + + let pins = []; + + if (controllerType === "lm") { + pins = [1, 4, 6]; + if (hasMainSwitch === 1) { + pins = [4, 6]; + } + } else if (controllerType === "unipi") { + pins = ["input1_01", "input1_04", "input1_05"]; + if (hasMainSwitch === 1) { + pins = ["input1_01", "input1_04"]; + } + } + + return pins; + } + + + function checkRvoStatus() { + + // 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 + //set RVO state + let status = "OK"; + + for (const [key, value] of Object.entries(deviceStatus)) { + if (["em", "twilight_sensor", "temperature", "master_node"].includes(key) && value === "NOK") status = "NOK"; + } + + if (status === "OK") { + + let pinIndexes = pinsForRvoStatus(controller_type, hasMainSwitch); + + for (const pinIndex of pinIndexes) { + if (previousValues[pinIndex] === 0) { + if ((pinIndex === 6 || pinIndex === 'input1_01' || pinIndex === 'input1_05') && SETTINGS.maintenance_mode) continue; + status = "NOK"; + break; + } + } + } + + // battery status. If value is 1 - battery is NOK + if (previousValues[5] === 1) status = "NOK"; + if (SETTINGS.no_voltage.size > 0) status = "NOK"; + + // console.log("rvo status",status) + return status; + } + + + // we pass array to function in case of rsPort ==> switchLogic([55,3,0,1]) ==> [[55,3,0,1]] + // we pass two values in case of websocket ==> switchLogic("relay1_03",1) ==> ["relay1_03",1] + const switchLogic = (...args) => { + + let values = {}; + let pinIndex, newPinValue, twilight; + + //data from rsPort + if (args.length == 1) { + pinIndex = args[0][1] + 1; + if (pinIndex === 17) pinIndex--; + newPinValue = args[0][3]; + twilight = args[0][2]; + } + //data from websocket + else { + pinIndex = args[0]; + newPinValue = args[1]; + } + + 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; + + //default value + let value = "On"; + if (newPinValue === 0) value = "Off"; + + //Hlavny istic + if (type === "state_of_main_switch" && hasMainSwitch) { + if (newPinValue === 0 && newPinValue !== previousValues[pinIndex]) { + sendNotification("switchLogic", rvoTbName, "main_switch_has_been_turned_off", {}, "", SEND_TO.tb, instance, "state_of_main_switch"); + 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"); + deviceStatus["state_of_main_switch"] = "On"; + } + } + + //Prevadzkovy mod + 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"; + + deviceStatus["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, "power_supply_has_disconnected_input", {}, "", SEND_TO.tb, instance, "power_supply"); + + deviceStatus["power_supply"] = "NOK"; + } + else if (newPinValue === 1 && newPinValue !== previousValues[pinIndex]) { + sendNotification("switchLogic", rvoTbName, "power_supply_works_correctly", {}, "", SEND_TO.tb, instance, "power_supply"); + + deviceStatus["power_supply"] = "OK"; + } + } + + //Bateria - 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"); + + deviceStatus["battery"] = "NOK"; + } + else if (newPinValue === 0 && newPinValue !== previousValues[pinIndex]) { + sendNotification("switchLogic", rvoTbName, "battery_level_is_ok", {}, "", SEND_TO.tb, instance, "battery_level"); + + deviceStatus["battery"] = "OK"; + } + } + + //Dverovy kontakt - pin 6 + //! Ak je rvo s dvoma dverovymi kontaktami, ked pride z evoku signal z input1_05, co bol predytm "state_of_main switch" handlujeme ho teraz ako 'door_condition' + else if (type == "door_condition" || type === "state_of_main_switch") { + newPinValue === 0 ? value = "open" : value = "closed"; + + let door = "door_main"; + if (type === "state_of_main_switch") door = "door_em"; + + if (value === "open") { + if (SETTINGS.maintenance_mode) { + sendNotification("switchLogic", rvoTbName, door + "_open", {}, "", SEND_TO.tb, instance, door); + } else { + sendNotification("switchLogic", rvoTbName, door + "_open_without_permission", {}, "", SEND_TO.tb, instance, door); + + // 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 (value === "closed") { + if (alarmStatus == "ON") turnAlarm("off"); + sendNotification("switchLogic", rvoTbName, door + "_close", {}, "", SEND_TO.tb, instance, door); + } + + deviceStatus[type] = value; + } + + //lux sensor + else if (type == "twilight_sensor") { + //! TODO - to show nok status, if lux value is not changing more then 10 times. + //Daylight is far more than 1000. So most of the day, when it is sunshine comes just value 1000. But lux sensor is not NOK. + //This is not the case in LM. If value from LM is the same 10x, there is 99% possibility, that sensor is NOK. + value = newPinValue; + + if (controller_type === 'lm') { + value = parseFloat(newPinValue + (256 * twilight)); + + 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 && !twilightError) { + twilightError = true; + let value = twilight_sensor_array.shift(); + + newPinValue = 0; + } + else if (set.size !== 1 && twilightError) { + //sendNotification("switchLogic", rvoTbName, 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) { + 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); + } + } + + 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); + } + + deviceStatus["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 (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 }); + + //mame iba 3 istice. vyreportujeme a ohandlujeme liniu na tom istom istici ako paralelna linia (napr linia 1, paralelna s nou je linia 4, key je string "4") + // ak je 7 linii, na 1 istici je linia 1,4,7 + + if (line == 1) { + + const lineOnSameBraker = [4, 7]; + + for (var i = 0; i < lineOnSameBraker.length; i++) { + if (!relaysData.hasOwnProperty(lineOnSameBraker[i])) continue; + + 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; + reportLineStatus(lineOnSameBraker[i]); + + values[type] = value; + const tbname = relaysData[lineOnSameBraker[i]].tbname; + sendTelemetry(values, tbname); + + delete values[type]; + } + + } + else { + const lineOnSameBraker = line + 3 + ""; + + if (relaysData.hasOwnProperty(lineOnSameBraker)) { + 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; + reportLineStatus(line + 3); + + values[type] = value; + const tbname = relaysData[lineOnSameBraker].tbname; + sendTelemetry(values, tbname); + + delete values[type]; + } + } + + } + + if (value == "Off") values["status"] = "NOK"; + deviceStatus["state_of_breaker"][line] = value; + + reportLineStatus(line); + } + else return; + + values[type] = value; + + if (type == "rotary_switch_state") { + if (SETTINGS.maintenance_mode) value = "maintenance"; + value = value.toLowerCase(); + values["power_mode"] = value; + } + + if (newPinValue != previousValues[pinIndex]) previousValues[pinIndex] = newPinValue; + if (Object.keys(values).length > 0 && tbname) sendTelemetry(values, tbname); + } + + + function sendTelemetry(values, tbname, date = Date.now()) { + let dataToTb = { + [tbname]: [ + { + "ts": date, + "values": values + } + ] + }; + + tbHandler.sendToTb(dataToTb, instance); + } + + + function isObject(item) { + return (typeof item === "object" && !Array.isArray(item) && item !== null); + } + +} //end of 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 +// *|input1_01|state_of_main_switch|0|........... +// *|input1_02|rotary_switch_state|0|........... +// *|input1_03|rotary_switch_state|0|........... +// *|intut1_04|power_supply|0|........... +// *|input1_05|door_condition|0|........... +// *|input1_06|state_of_breaker|1|........... +// *|input1_07|state_of_breaker|2|........... +// *|input1_08|state_of_breaker|3|........... +// *|relay1_02|state_of_contactor|1|........... +// *|relay1_03|state_of_contactor|2|........... +// *|relay1_04|state_of_contactor|3|........... +// *|287D8776E0013CE9|temperature|0|........... + + +//! pins_data --> from UNIPI +// { +// 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 } +// } + +//! relays_data +// { +// '0': { +// line: 0, +// tbname: 'KjbN4q7JPZmexgdnz2yKQ98YAWwO0Q3BMX6ERLoV', +// contactor: 1, +// profile: '' +// }, +// '1': { +// line: 1, +// tbname: 'RMgnK93rkoAazbqdQ4yBG95Z1YXGx6pmwBeVEP2O', +// contactor: 0, +// profile: '{"intervals":[{"value":0,"end_time":"20:00","start_time":"13:00"},{"value":1,"end_time":"10:00","start_time":"20:00"},{"value":0,"end_time":"10:20","start_time":"10:00"},{"value":1,"end_time":"10:40","start_time":"10:20"},{"value":0,"end_time":"11:00","start_time":"10:40"},{"value":1,"end_time":"11:30","start_time":"11:00"},{"value":0,"end_time":"11:50","start_time":"11:30"},{"value":1,"end_time":"13:00","start_time":"11:50"}],"astro_clock":false,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' +// }, +// '2': { +// line: 2, +// tbname: 'dlE1VQjYrNx9gZRmb38gG08oLBO4qaAk2M6JPnG7', +// contactor: 0, +// profile: '{"intervals":[{"value":0,"end_time":"20:00","start_time":"13:00"},{"value":1,"end_time":"10:00","start_time":"20:00"},{"value":0,"end_time":"10:20","start_time":"10:00"},{"value":1,"end_time":"10:40","start_time":"10:20"},{"value":0,"end_time":"11:00","start_time":"10:40"},{"value":1,"end_time":"11:30","start_time":"11:00"},{"value":0,"end_time":"11:50","start_time":"11:30"},{"value":1,"end_time":"13:00","start_time":"11:50"}],"astro_clock":false,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' +// }, +// '3': { +// line: 3, +// tbname: 'vnmG4kJxaXWNBgMQq0D7Aj5e9oZzOAlr6LdR3w2V', +// contactor: 0, +// profile: '{"intervals":[{"value":0,"end_time":"20:30","start_time":"13:00"},{"value":1,"end_time":"00:10","start_time":"20:30"},{"value":0,"end_time":"13:00","start_time":"05:40"},{"value":1,"end_time":"05:40","start_time":"00:10"}],"astro_clock":true,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' +// } +// } + + + + + +// { +// "jbN4q7JPZmexgdnz2yKbWGDYAWwO0Q3BMX6ERLoV": [ +// { +// "ts": 1700409326353, +// "values": { +// "_event": { +// "type": "notice", +// "status": "new", +// "source": { +// "func": "rsPort.open()", +// "component": "1700343402190", +// "component_name": "DIDO_Controller", +// "edge": "jbN4q7JPZmexgdnz2yKbWGDYAWwO0Q3BMX6ERLoV" +// }, +// "message": "al_shariff_10.0.0.38: FLOW has been started ", +// "message_data": "" +// } +// } +// } +// ] +// } diff --git a/RVO16/flow/dido_controller_orig.txt b/RVO16/flow/dido_controller_orig.txt new file mode 100755 index 0000000..523d39b --- /dev/null +++ b/RVO16/flow/dido_controller_orig.txt @@ -0,0 +1,1473 @@ +exports.id = 'dido_controller'; +exports.title = 'DIDO_Controller'; +exports.version = '2.0.0'; +exports.group = 'Worksys'; +exports.color = '#2134B0'; +exports.input = 3; +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 + +state_of_main_switch - reportovať stav hlavného ističa : 0-> off 1-> on +rotary_switch_state - sem by sa mal reportovať stav vstupov manual a auto podľa nasledovnej logiky: Manual = 1 a Auto = 0 -> Manual, +Manual = 0 a Auto = 0 -> Off, Manual = 0 a Auto = 1 -> Automatic + +door_condition - 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 + +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 +*/ + +const { errLogger, logger, monitor } = require('./helper/logger'); +const SerialPort = require('serialport'); +const WebSocket = require('ws'); +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 +} + + +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 = {}; + let rsPortReceivedData = []; + + //to be able to get proper twilight values + let twilight_sensor_interval = 5;//minutes + let twilight_sensor = []; + const twilight_sensor_array = []; + let twilightError = false; + + monitor.info("DIDO_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 deviceStatus = { //key is device name: temperature,.... + "state_of_main_switch": "Off", //Hlavný istič (po novom druhy dverovy kontakt) + "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 + }; + + + function main() { + + GLOBALS = FLOW.GLOBALS; + SETTINGS = FLOW.GLOBALS.settings; + rvoTbName = SETTINGS.rvoTbName; + pinsData = GLOBALS.pinsData; + relaysData = GLOBALS.relaysData; + + 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"; + + 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, "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; + } + } + + //report RVO version relaysData[0].tbname; + let values = {}; + values["edge_fw_version"] = SETTINGS.edge_fw_version; + values["maintenance_mode"] = SETTINGS.maintenance_mode; + + sendTelemetry(values, rvoTbName); + + 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); + } + + + 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) { + if (!err) { + monitor.info(exports.title + "--->Digital in_out has been set (runSyncExec was sucessfull)"); + + turnAlarm("off"); + 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() { + + //to keep websocket opened, we send request every 150 seconds + let startRequests = null; + + console.log("handleWebSocket function called"); + ws = new WebSocket('ws:/0.0.0.0:1234/ws'); + + ws.onopen = function open() { + + instance.send(0, exports.title + " running"); + turnAlarm("off"); + + initialSetting(); + + setTimeout(function() { ws.send(JSON.stringify({ cmd: "all" })) }, 5000); + // we request dev info about neuron device from evok to keep websocket connection alive + // for some reason this request returns no data, but connection keeps alive + startRequests = setInterval(() => { + ws.send(JSON.stringify({ "cmd": "filter", "dev": ["neuron"] })); + }, 150000) + }; + + + // 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 = async 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; + + 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) => { + monitor.info('websocket error, reconnect') + instance.send(SEND_TO.debug, err.message); + clearInterval(startRequests); + ws = null; + setTimeout(handleWebSocket, 1000); + }) + + + ws.onclose = function() { + // connection closed, discard old websocket and create a new one in 5s + // stopRequests(); + monitor.info('websocket onclose, reconnect') + clearInterval(startRequests); + ws = null; + console.log("ws is null now, reconnecting..."); + setTimeout(handleWebSocket, 1000); + } + } + + 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 turnAlarm(onOrOff) { + let value = 0; + if (onOrOff == "on") value = 1; + + if (value == 1 && SETTINGS.maintenance_mode) return; + + alarmStatus = "OFF"; + if (value == 1) alarmStatus = "ON"; + + if (rsPort) { + let arr = [0x55]; + arr.push(13); + arr.push(0); + arr.push(value); + + rsPort.write(Buffer.from(arr), function(err) { + logger.debug(`sirena - ${onOrOff}`); + }); + } + else if (ws) { + let cmd = { "cmd": "set", "dev": "relay", "circuit": "1_01", "value": value }; + ws.send(JSON.stringify(cmd)); + logger.debug(`sirena - ${onOrOff}`); + } + } + + + 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") { + bits.push(0); + } + else bits.push(1); + + if (deviceStatus["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); + } + + + // turn line on or off + function turnLine(onOrOff, line, pin, force, info) { + //onOrOff => "on" or "off" + let value = 0; + if (onOrOff == "on") value = 1; + + if (force == undefined) force = false; + + if (line == 0) { + if (value == 1 && alarmStatus == "ON") turnAlarm("off"); + SETTINGS.maintenance_mode = value ? true : false; + + 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); + return; + } + + if (pin === undefined) pin = getPin(line); + + if (pin === undefined) { + errLogger.error("pin is undefined!", line); + return; + } + + if (!force) { + if (relaysData[line].contactor == value) { + instance.send(SEND_TO.debug, `line is already ${onOrOff} ` + line); + logger.debug(`turnLine: line is already ${onOrOff} `, 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(value); + + rsPort.write(Buffer.from(arr), function(err) { + if (err === undefined) { + monitor.info(`turnLine ${onOrOff} zapisal do rsPort-u`, line, pin, arr, info); + switchLogic(arr); + } + else { + monitor.info(`turnLine ${onOrOff} 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 }; + ws.send(JSON.stringify(cmd)); + } + + //if rvo is 24/7, it has just one switching profile point at 13:00. we do not want to send notification as it repeats every day. + //const d = new Date(); + //if(d.getHours() != 13) sendNotification("Dido_controller: ", SETTINGS.rvoTbName, "switching_profile_point_applied_to_line", { line: line, value: onOrOff }, "", SEND_TO.tb, instance); + } + + + // 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; + + // 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) { + const status = flowdata.data.status; + if (status == "NOK-twilight_sensor") { + deviceStatus["twilight_sensor"] = "NOK"; + } + else if (status == "NOK-em340" || status == "NOK-em111") { + deviceStatus["em"] = "NOK"; + } + else if (status == "NOK-thermometer") { + deviceStatus["temperature"] = "NOK"; + } + } + else if ("values" in flowdata.data) { + 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" + } + else if (values.hasOwnProperty("temperature")) { + deviceStatus["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"; + } + + sendTelemetry(values, rvoTbName); + } + + sendRvoStatus(); + }) + + + + + // we expect array as flowdata.data + instance.on("1", flowdata => { + + //console.log(flowdata.data); + + if (!flowdata.data instanceof Object) return; + + let obj = flowdata.data; + let line = obj.line; + 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"); + }) + + + function calculateStateCode() { + + 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") { + bits.push(0); + } + else { + bits.push(1); + } + + //Prevádzkový mód - Manual, Off, Automatic, maintenance_mode = true/false // DAVA 2 BITY + if (!SETTINGS.maintenance_mode) { + if (deviceStatus["rotary_switch_state"] == "Manual") { + bits.push(0); + bits.push(1); + } + + if (deviceStatus["rotary_switch_state"] == "Automatic") { + bits.push(0); + bits.push(0); + } + + if (deviceStatus["rotary_switch_state"] == "Off") { + bits.push(1); + bits.push(0); + } + } + else { + bits.push(1); + bits.push(1); + } + + //Dverový kontakt + if (deviceStatus["door_condition"] == "closed") { + bits.push(0); + } + else { + bits.push(1); + } + + //EM + if (deviceStatus["em"] == "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //Teplomer + if (deviceStatus["temperature"] == "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //Batéria + if (deviceStatus["battery"] == "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //Zdroj + if (deviceStatus["power_supply"] == "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //MN + if (deviceStatus["master_node"] == "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //výpadok napätia na fáze + if (deviceStatus["no_voltage"] == "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + if (deviceStatus["twilight_sensor"] == "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + // doplnime do 16 bitov (2 byty) + for (let i = bits.length; i < 16; i++) { + bits.push(0); + } + + // console.log("calculateStateCode - deviceStatus", deviceStatus); + // 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; + } + + + async function sendRvoStatus() { + + if (SETTINGS === undefined) return; + SETTINGS.masterNodeIsResponding ? deviceStatus["master_node"] = "OK" : deviceStatus["master_node"] = "NOK"; + + 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() { + + // 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 + //set RVO state + let status = "OK"; + + for (const [key, value] of Object.entries(deviceStatus)) { + if (["em", "twilight_sensor", "temperature", "master_node"].includes(key) && value == "NOK") status = "NOK"; + } + + if (status == "OK") { + let pinIndexes = [1, 4, 6]; + if (controller_type == 'unipi') pinIndexes = ['input1_01', 'input1_04', 'input1_05']; + + for (const pinIndex of pinIndexes) { + if (previousValues[pinIndex] === 0) { + if ((pinIndex === 6 || pinIndex === 'input1_01' || pinIndex === 'input1_05') && SETTINGS.maintenance_mode) continue; + status = "NOK"; + break; + } + } + } + + // battery status. If value is 1 - battery is NOK + if (previousValues[5] === 1) status = "NOK"; + if (SETTINGS.no_voltage.size > 0) status = "NOK"; + + // console.log("rvo status",status) + return status; + } + + + // we pass array to function in case of rsPort ==> switchLogic([55,3,0,1]) ==> [[55,3,0,1]] + // we pass two values in case of websocket ==> switchLogic("relay1_03",1) ==> ["relay1_03",1] + const switchLogic = (...args) => { + + let values = {}; + let pinIndex, newPinValue, twilight; + + //data from rsPort + if (args.length == 1) { + pinIndex = args[0][1] + 1; + if (pinIndex === 17) pinIndex--; + newPinValue = args[0][3]; + twilight = args[0][2]; + } + //data from websocket + else { + pinIndex = args[0]; + newPinValue = args[1]; + } + + 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; + + //default value + let value = "On"; + if (newPinValue === 0) value = "Off"; + + //Prevádzkový mód + 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"; + + deviceStatus["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, "power_supply_has_disconnected_input", {}, "", SEND_TO.tb, instance, "power_supply"); + + deviceStatus["power_supply"] = "NOK"; + } + else if (newPinValue === 1 && newPinValue !== previousValues[pinIndex]) { + sendNotification("switchLogic", rvoTbName, "power_supply_works_correctly", {}, "", SEND_TO.tb, instance, "power_supply"); + + deviceStatus["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"); + + deviceStatus["battery"] = "NOK"; + } + else if (newPinValue === 0 && newPinValue !== previousValues[pinIndex]) { + sendNotification("switchLogic", rvoTbName, "battery_level_is_ok", {}, "", SEND_TO.tb, instance, "battery_level"); + + deviceStatus["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' + else if (type == "door_condition" || type === "state_of_main_switch") { + newPinValue === 0 ? value = "open" : value = "closed"; + + 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, "door_opened_without_permission", {}, "", SEND_TO.tb, instance, "rvo_door"); + + // 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 (value === "closed") { + if (alarmStatus == "ON") turnAlarm("off"); + sendNotification("switchLogic", rvoTbName, "door_closed", {}, "", SEND_TO.tb, instance, "rvo_door"); + } + + deviceStatus[type] = value; + } + + //lux sensor + else if (type == "twilight_sensor") { + //! TODO - to show nok status, if lux value is not changing more then 10 times. + //Daylight is far more than 1000. So most of the day, when it is sunshine comes just value 1000. But lux sensor is not NOK. + //This is not the case in LM. If value from LM is the same 10x, there is 99% possibility, that sensor is NOK. + value = newPinValue; + + if (controller_type === 'lm') { + value = parseFloat(newPinValue + (256 * twilight)); + + 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 && !twilightError) { + twilightError = true; + let value = twilight_sensor_array.shift(); + + newPinValue = 0; + } + else if (set.size !== 1 && twilightError) { + //sendNotification("switchLogic", rvoTbName, 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) { + 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); + } + } + + 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); + } + + deviceStatus["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) + // { + // let time = 0; + // if(value) time = 1000 * 10;//10 sekund + + // let dataChanged = false; + // if(relaysData[line].contactor != newPinValue) dataChanged = true; + // relaysData[line].contactor = newPinValue; // 0,1 + + // //ak bola predchadzajuci stav off a novy stav je on, budu sa nastavovat nespracovane node profiles + // //a budu sa odosielat commandy, tie vsak mozu zlyhat, a preto potrebujeme ich spusti trochu neskor + // setTimeout(function(){ + // instance.send(SEND_TO.cmd_manager, {sender: "dido_controller", cmd: "reload_relays", line: line, time: time, value: value, dataChanged: dataChanged}); + // }, time); + + // reportLineStatus(line); + // } + // else + // { + // errLogger.error("modify table relays failed", err); + // } + + // }); + // }); + } + + 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 }); + + //mame iba 3 istice. vyreportujeme a ohandlujeme liniu na tom istom istici ako paralelna linia (napr linia 1, paralelna s nou je linia 4, key je string "4") + // ak je 7 linii, na 1 istici je linia 1,4,7 + + if (line == 1) { + + const lineOnSameBraker = [4, 7]; + + for (var i = 0; i < lineOnSameBraker.length; i++) { + if (!relaysData.hasOwnProperty(lineOnSameBraker[i])) continue; + + 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; + reportLineStatus(lineOnSameBraker[i]); + + values[type] = value; + const tbname = relaysData[lineOnSameBraker[i]].tbname; + sendTelemetry(values, tbname); + + delete values[type]; + } + + } + else { + const lineOnSameBraker = line + 3 + ""; + + if (relaysData.hasOwnProperty(lineOnSameBraker)) { + 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; + reportLineStatus(line + 3); + + values[type] = value; + const tbname = relaysData[lineOnSameBraker].tbname; + sendTelemetry(values, tbname); + + delete values[type]; + } + } + + } + + if (value == "Off") values["status"] = "NOK"; + deviceStatus["state_of_breaker"][line] = value; + + reportLineStatus(line); + } + else return; + + values[type] = value; + + if (type == "rotary_switch_state") { + if (SETTINGS.maintenance_mode) value = "maintenance"; + value = value.toLowerCase(); + values["power_mode"] = value; + } + + if (newPinValue != previousValues[pinIndex]) previousValues[pinIndex] = newPinValue; + if (Object.keys(values).length > 0 && tbname) sendTelemetry(values, tbname); + } + + + function sendTelemetry(values, tbname, date = Date.now()) { + let dataToTb = { + [tbname]: [ + { + "ts": date, + "values": values + } + ] + }; + + tbHandler.sendToTb(dataToTb, instance); + } + + + function isObject(item) { + return (typeof item === "object" && !Array.isArray(item) && item !== null); + } + +} //end of 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 +// *|input1_01|state_of_main_switch|0|........... +// *|input1_02|rotary_switch_state|0|........... +// *|input1_03|rotary_switch_state|0|........... +// *|intut1_04|power_supply|0|........... +// *|input1_05|door_condition|0|........... +// *|input1_06|state_of_breaker|1|........... +// *|input1_07|state_of_breaker|2|........... +// *|input1_08|state_of_breaker|3|........... +// *|relay1_02|state_of_contactor|1|........... +// *|relay1_03|state_of_contactor|2|........... +// *|relay1_04|state_of_contactor|3|........... +// *|287D8776E0013CE9|temperature|0|........... + + +//! pins_data --> from UNIPI +// { +// 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 } +// } + +//! relays_data +// { +// '0': { +// line: 0, +// tbname: 'KjbN4q7JPZmexgdnz2yKQ98YAWwO0Q3BMX6ERLoV', +// contactor: 1, +// profile: '' +// }, +// '1': { +// line: 1, +// tbname: 'RMgnK93rkoAazbqdQ4yBG95Z1YXGx6pmwBeVEP2O', +// contactor: 0, +// profile: '{"intervals":[{"value":0,"end_time":"20:00","start_time":"13:00"},{"value":1,"end_time":"10:00","start_time":"20:00"},{"value":0,"end_time":"10:20","start_time":"10:00"},{"value":1,"end_time":"10:40","start_time":"10:20"},{"value":0,"end_time":"11:00","start_time":"10:40"},{"value":1,"end_time":"11:30","start_time":"11:00"},{"value":0,"end_time":"11:50","start_time":"11:30"},{"value":1,"end_time":"13:00","start_time":"11:50"}],"astro_clock":false,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' +// }, +// '2': { +// line: 2, +// tbname: 'dlE1VQjYrNx9gZRmb38gG08oLBO4qaAk2M6JPnG7', +// contactor: 0, +// profile: '{"intervals":[{"value":0,"end_time":"20:00","start_time":"13:00"},{"value":1,"end_time":"10:00","start_time":"20:00"},{"value":0,"end_time":"10:20","start_time":"10:00"},{"value":1,"end_time":"10:40","start_time":"10:20"},{"value":0,"end_time":"11:00","start_time":"10:40"},{"value":1,"end_time":"11:30","start_time":"11:00"},{"value":0,"end_time":"11:50","start_time":"11:30"},{"value":1,"end_time":"13:00","start_time":"11:50"}],"astro_clock":false,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' +// }, +// '3': { +// line: 3, +// tbname: 'vnmG4kJxaXWNBgMQq0D7Aj5e9oZzOAlr6LdR3w2V', +// contactor: 0, +// profile: '{"intervals":[{"value":0,"end_time":"20:30","start_time":"13:00"},{"value":1,"end_time":"00:10","start_time":"20:30"},{"value":0,"end_time":"13:00","start_time":"05:40"},{"value":1,"end_time":"05:40","start_time":"00:10"}],"astro_clock":true,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' +// } +// } + + + + + +// { +// "jbN4q7JPZmexgdnz2yKbWGDYAWwO0Q3BMX6ERLoV": [ +// { +// "ts": 1700409326353, +// "values": { +// "_event": { +// "type": "notice", +// "status": "new", +// "source": { +// "func": "rsPort.open()", +// "component": "1700343402190", +// "component_name": "DIDO_Controller", +// "edge": "jbN4q7JPZmexgdnz2yKbWGDYAWwO0Q3BMX6ERLoV" +// }, +// "message": "al_shariff_10.0.0.38: FLOW has been started ", +// "message_data": "" +// } +// } +// } +// ] +// } diff --git a/RVO16/flow/helper/DataToTbHandler.js b/RVO16/flow/helper/DataToTbHandler.js new file mode 100755 index 0000000..716ef7b --- /dev/null +++ b/RVO16/flow/helper/DataToTbHandler.js @@ -0,0 +1,187 @@ +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; + this.itIsNodeReadout = false; + this.sender = ""; + + // if attribute change difference is less than limit value, we do not send to tb. + this.attributeChangeLimit = { + temperature: 0.5, + Phase_1_voltage: 2, + Phase_2_voltage: 2, + Phase_3_voltage: 2, + Phase_1_current: 0.1, + Phase_2_current: 0.1, + Phase_3_current: 0.1, + Phase_1_power: 2, + Phase_2_power: 2, + Phase_3_power: 2, + total_power: 2, + total_energy: 1, + Phase_1_pow_factor: 0.1, + Phase_2_pow_factor: 0.1, + Phase_3_pow_factor: 0.1, + power_factor: 0.1, + lifetime: 2, + voltage: 2, + power: 2, + frequency: 3, + energy: 0.1, + current: 2, + inclination_x: 10, + inclination_y: 10, + inclination_z: 10 + }; + + } + + dump() { + console.log("----------------------------"); + console.log("previousValues", this.previousValues); + console.log("----------------------------"); + } + + setSender(sender) { + this.sender = sender; + } + + isEmptyObject(obj) { + for (var _ in obj) { + return false; + } + return true; + } + + + sendToTb(data, instance) { + + //not to modify data object, we do deep copy: + let dataCopy = JSON.parse(JSON.stringify(data)); + + let keys = Object.keys(dataCopy); + + if (keys.length == 0) { + if (this.debug) console.log("sendToTb received empty object", dataCopy); + return; + } + + let tbname = keys[0]; + let ts; + + let arrayOfValues = dataCopy[tbname]; + let arrayOfValuesToSend = []; + + for (let i = 0; i < arrayOfValues.length; i++) { + + ts = arrayOfValues[i].ts; + let values = this.prepareValuesForTb(tbname, ts, arrayOfValues[i].values); + + if (!this.isEmptyObject(values)) { + arrayOfValuesToSend.push({ ts: ts, values: values }); + } + + } + + if (arrayOfValuesToSend.length == 0) { + //if(this.debug) console.log("data not sent - empty array"); + return; + } + + this.messageCounter++; + + let dataToTbModified = { + [tbname]: arrayOfValuesToSend + } + + //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); + instance.send(this.index, dataToTbModified); + } + + + getDiffTimestamp(key) { + //TODO set different value for given key!!! + //if(key == "status") this.timeToHoldTbValue = 2*60*60;//2h + return this.timeToHoldTbValue * 1000; + } + + + prepareValuesForTb(tbname, timestamp, values) { + + let keys = Object.keys(values); + + if (keys.includes("lifetime")) this.itIsNodeReadout = true; + + if (!this.previousValues.hasOwnProperty(tbname)) { + this.previousValues[tbname] = {}; + } + + //if(this.debug) console.log("prepareValuesForTb", tbname, timestamp, values); + + for (let i = 0; i < keys.length; i++) { + + let key = keys[i]; + let value = values[key]; + + if (!this.previousValues[tbname].hasOwnProperty(key)) { + this.previousValues[tbname][key] = { ts: timestamp, value: value }; + continue; + } + + // attributeData ==> {voltage: {ts:333333, value:5}} + let attributeData = this.previousValues[tbname][key]; + let attributeToChange = false; + if (key in this.attributeChangeLimit) attributeToChange = true; + let limit = this.attributeChangeLimit[key]; + let timestampDiffToRemoveKey; + + //this will ensure "node statecode" will be sent just once an hour + if (this.itIsNodeReadout && key === "statecode") { + attributeData.value = value; + this.itIsNodeReadout = false; + timestampDiffToRemoveKey = 1 * 60 * 60 * 1000; // 1 hour + } + + if (key === "twilight_sensor" && value > 100) { + attributeData.value = value; + } + + //if edge, master or node version do not change, send just once a day: + if (["edge_fw_version", "master_node_version", "fw_version"].includes(key)) { + timestampDiffToRemoveKey = 24 * 60 * 60 * 1000; + } + + if (attributeData.value === value || attributeToChange && Math.abs(attributeData.value - value) < limit) { + + let diff = timestamp - attributeData.ts; + if (!timestampDiffToRemoveKey) timestampDiffToRemoveKey = this.getDiffTimestamp(key); + + if (diff > timestampDiffToRemoveKey) { + attributeData.ts = Date.now(); + //if(this.debug) console.log(this.sender + ": update ts for key", key, "diff is", diff, "messageCounter", this.messageCounter); + } + else { + delete values[key]; + //if(this.debug) console.log(this.sender + ": delete key", key, "diff is", diff, "messageCounter", this.messageCounter, timestampDiffToRemoveKey); + } + } + else { + attributeData.value = value; + attributeData.ts = timestamp; + } + + } + + return values; + } +} + +module.exports = DataToTbHandler; + diff --git a/RVO16/flow/helper/ErrorToServiceHandler.js b/RVO16/flow/helper/ErrorToServiceHandler.js new file mode 100755 index 0000000..2b27c32 --- /dev/null +++ b/RVO16/flow/helper/ErrorToServiceHandler.js @@ -0,0 +1,91 @@ +const { MD5 } = require('./md5.js'); +const { networkInterfaces } = require('os'); + +class ErrorToServiceHandler { + constructor() { + this.previousValues = {}; + + this.project_id = undefined; + + const nets = networkInterfaces(); + this.ipAddresses = {}; + + for (const name of Object.keys(nets)) { + for (const net of nets[name]) { + // Skip over non-IPv4 and internal (i.e. 127.0.0.1) addresses + if (net.family === 'IPv4' && !net.internal) { + if (!this.ipAddresses[name]) { + this.ipAddresses[name] = []; + } + this.ipAddresses[name].push(net.address); + } + } + } + } + + setProjectId(project_id) { + this.project_id = project_id; + } + + processMessage(message, seconds) { + if (Array.isArray(message)) message = message.join(', '); + + let key = MD5(message); + let ts = Date.now(); + + //keep in memory - default value is 1h + if (seconds === undefined) seconds = 60 * 60; + + if (!this.previousValues.hasOwnProperty(key)) { + this.previousValues[key] = { ts: ts, duration: seconds }; + } + + let diff = (ts - this.previousValues[key].ts); + if (diff < this.previousValues[key].duration * 1000) return false; + + this.previousValues[key].ts = ts; + + return message; + } + + sendMessageToService(message, seconds, message_type) { + + // if error occures too early FLOW.GLOBALS.settings.project_id is still undefined + if (this.project_id === undefined) { + console.log("ErrorToServiceHandler.js: no project_id"); + return; + } + + let f = this.processMessage(message, seconds); + if (f === false) return; + + if (message_type === undefined) message_type = "error_message"; + + let toService = { + id: this.project_id, + ipAddresses: this.ipAddresses + }; + + //js_error || error_message + toService[message_type] = message; + + console.log("ErrorToServiceHandler------------------------>send to service", toService); + + RESTBuilder.make(function(builder) { + builder.method('POST'); + builder.post(toService); + builder.url('http://192.168.252.2:8004/sentmessage'); + + builder.callback(function(err, response, output) { + console.log("process.on error send", err, response, output, toService); + }); + }); + + } +} + +const errorHandler = new ErrorToServiceHandler(); + + +module.exports = errorHandler; +//module.exports = ErrorToServiceHandler; diff --git a/RVO16/flow/helper/db_helper.js b/RVO16/flow/helper/db_helper.js new file mode 100755 index 0000000..40e796c --- /dev/null +++ b/RVO16/flow/helper/db_helper.js @@ -0,0 +1,44 @@ +function promisifyBuilder(builder) +{ + return new Promise((resolve, reject) => { + + try{ + + builder.callback(function(err, response) { + + if(err != null) reject(err); + resolve(response); + }); + + } catch (error) { + reject(error); + } + }) +} + +function makeMapFromDbResult(response, ...keys) +{ + let s = "-"; + let data = {}; + + for(let i = 0; i < response.length; i++) + { + let record = response[i]; + + let k = []; + for(let j = 0; j < keys.length; j++) + { + k.push( record[keys[j]] ); + } + + let key = k.join(s); + data[ key ] = record; + } + + return data; +} + +module.exports = { + promisifyBuilder, + makeMapFromDbResult + } \ No newline at end of file diff --git a/RVO16/flow/helper/logger.js b/RVO16/flow/helper/logger.js new file mode 100755 index 0000000..2585639 --- /dev/null +++ b/RVO16/flow/helper/logger.js @@ -0,0 +1,30 @@ +//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/RVO16/flow/helper/md5.js b/RVO16/flow/helper/md5.js new file mode 100755 index 0000000..d3b0480 --- /dev/null +++ b/RVO16/flow/helper/md5.js @@ -0,0 +1,5 @@ +function MD5(d){var r = M(V(Y(X(d),8*d.length)));return r.toLowerCase()};function M(d){for(var _,m="0123456789ABCDEF",f="",r=0;r>>4&15)+m.charAt(15&_);return f}function X(d){for(var _=Array(d.length>>2),m=0;m<_.length;m++)_[m]=0;for(m=0;m<8*d.length;m+=8)_[m>>5]|=(255&d.charCodeAt(m/8))<>5]>>>m%32&255);return _}function Y(d,_){d[_>>5]|=128<<_%32,d[14+(_+64>>>9<<4)]=_;for(var m=1732584193,f=-271733879,r=-1732584194,i=271733878,n=0;n>16)+(_>>16)+(m>>16)<<16|65535&m}function bit_rol(d,_){return d<<_|d>>>32-_} + +module.exports = { + MD5 +} \ No newline at end of file diff --git a/RVO16/flow/helper/notification_reporter.js b/RVO16/flow/helper/notification_reporter.js new file mode 100755 index 0000000..839c12c --- /dev/null +++ b/RVO16/flow/helper/notification_reporter.js @@ -0,0 +1,121 @@ +//key is device, value = message {} +let sentValues = {}; +let notificationsData = null; +let rvoName; + +//sendNotification("CMD Manager: process cmd", SETTINGS.rvoTbName, "dimming_profile_was_successfully_received_by_node", { node: node }, "", SEND_TO.tb, instance); + +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 +}; + +function getKey(map, val) { + return Object.keys(map).findItem(key => map[key] === val); +} + +//https://stackoverflow.com/questions/41117799/string-interpolation-on-variable +var template = (tpl, args) => tpl.replace(/\${(\w+)}/g, (_, v) => args[v]); + + +function initNotification() { + notificationsData = FLOW.GLOBALS.notificationsData; + rvoName = FLOW.GLOBALS.settings.rvo_name; +} + + +function sendNotification(func, device, key, params, extra, tb_output, instance, saveKey) { + + let storeToSendValues = true; + if (saveKey == undefined) storeToSendValues = false; + + let weight = ""; + let message = {}; + + let notification = notificationsData[key]; + + if (notification) { + weight = notification.weight.toLowerCase(); + + Object.keys(notification).forEach(item => { + if (["en", "sk", "de", "cz", "it", "es"].includes(item)) { + message[item] = rvoName + ": " + template(notification[item], params); + } + }) + } + else { + //console.error("sendNotification: Notifications: undefined key", key, func, notificationsData); + console.error("sendNotification: Notifications: undefined key", key, func); + return false; + } + + //detect invalid err weight + if (getKey(ERRWEIGHT, weight) == undefined) { + console.error("sendNotification: Notifications: undefined weight", weight, key, func); + return false; + } + + if (sentValues.hasOwnProperty(saveKey)) { + if (JSON.stringify(sentValues[saveKey]) == JSON.stringify(message)) { + return false; + } + } + + if (sentValues[saveKey] == undefined) { + if (storeToSendValues) { + //do not send - flow is was started + sentValues[saveKey] = message; + return false; + } + } + + if (storeToSendValues) sentValues[saveKey] = message; + + let content = { + "type": weight, + "status": "new", + "source": { + "func": func, + "component": instance.id, + "component_name": instance.name, + "edge": device + }, + "message": message, + "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 + + return true; + +} + +module.exports = { + sendNotification, + ERRWEIGHT, + initNotification +} + diff --git a/RVO16/flow/helper/register.js b/RVO16/flow/helper/register.js new file mode 100755 index 0000000..fc1d008 --- /dev/null +++ b/RVO16/flow/helper/register.js @@ -0,0 +1,144 @@ +/* +0 - cislo registra / prikaz +1 - recepient - 0 = master, 1 = slave (slave je automaticky group a broadcast) +2 - r/rw - read/write +3- register name - nazov registra / prikazu (len pre info - zobrazenie v aplikacii) + +4,5,6,7, - jednotlive byte-y - nazov byte-u +4-7 - RES. a prazdny string "" sa nezobrazia!!! +*/ + +//124 zaznamov +const registers = [ + ["0","1","R","Status","","",""], + ["1","1","RW","Dimming","R-Channel ","G-Channel","B-Channel ","W - Channel"], + ["2","1","R","Device types","","",".",""], + ["3","1","RW","Group addresses 1-4","Groups Add. 4","Groups Add. 3","Groups Add. 2","Groups Add. 1"], + ["4","1","RW","Group addresses 5-8","Groups Add. 8","Groups Add. 7","Groups Add. 6","Groups Add. 5"], + ["5","1","RW","Serial number (MAC)","","","",""], + ["6","1","RW","Time of dusk","HH","MM","SS","EXTRA"], + ["7","1","RW","Time of dawn","HH","MM","SS","EXTRA"], + ["8","1","RW","Time Schedule settings","TBD","TBD","Movement sensor","Time Schedule"], + ["9","1","RW","TS1 Time point 1","HH","MM","SS","Ext. Device"], + ["10","1","RW","TS1 Time point 1 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["11","1","RW","TS1 Time point 2","HH","MM","SS","Ext. Device"], + ["12","1","RW","TS1 Time point 2 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["13","1","RW","TS1 Time point 3","HH","MM","SS","Ext. Device"], + ["14","1","RW","TS1 Time point 3 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["15","1","RW","TS1 Time point 4","HH","MM","SS","Ext. Device"], + ["16","1","RW","TS1 Time point 4 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["17","1","RW","TS1 Time point 5","HH","MM","SS","Ext. Device"], + ["18","1","RW","TS1 Time point 5 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["19","1","RW","TS1 Time point 6","HH","MM","SS","Ext. Device"], + ["20","1","RW","TS1 Time point 6 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["21","1","RW","TS1 Time point 7","HH","MM","SS","Ext. Device"], + ["22","1","RW","TS1 Time point 7 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["23","1","RW","TS1 Time point 8","HH","MM","SS","Ext. Device"], + ["24","1","RW","TS1 Time point 8 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["25","1","RW","TS1 Time point 9","HH","MM","SS","Ext. Device"], + ["26","1","RW","TS1 Time point 9 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["27","1","RW","TS1 Time point 10","HH","MM","SS","Ext. Device"], + ["28","1","RW","TS1 Time point 10 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["29","1","RW","TS1 Time point 11","HH","MM","SS","Ext. Device"], + ["30","1","RW","TS1 Time point 11 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["31","1","RW","TS1 Time point 12","HH","MM","SS","Ext. Device"], + ["32","1","RW","TS1 Time point 12 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["33","1","RW","TS1 Time point 13","HH","MM","SS","Ext. Device"], + ["34","1","RW","TS1 Time point 13 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["35","1","RW","TS1 Time point 14","HH","MM","SS","Ext. Device"], + ["36","1","RW","TS1 Time point 14 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["37","1","RW","TS1 Time point 15","HH","MM","SS","Ext. Device"], + ["38","1","RW","TS1 Time point 15 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["39","1","RW","TS1 Time point 16","HH","MM","SS","Ext. Device"], + ["40","1","RW","TS1 Time point 16 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["41","1","RW","TS2 Time point 1","HH","MM","SS","Ext. Device"], + ["42","1","RW","TS2 Time point 1 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["43","1","RW","TS2 Time point 2","HH","MM","SS","Ext. Device"], + ["44","1","RW","TS2 Time point 2 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["45","1","RW","TS2 Time point 3","HH","MM","SS","Ext. Device"], + ["46","1","RW","TS2 Time point 3 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["47","1","RW","TS2 Time point 4","HH","MM","SS","Ext. Device"], + ["48","1","RW","TS2 Time point 4 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["49","1","RW","TS2 Time point 5","HH","MM","SS","Ext. Device"], + ["50","1","RW","TS2 Time point 5 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["51","1","RW","TS2 Time point 6","HH","MM","SS","Ext. Device"], + ["52","1","RW","TS2 Time point 6 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["53","1","RW","TS2 Time point 7","HH","MM","SS","Ext. Device"], + ["54","1","RW","TS2 Time point 7 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["55","1","RW","TS2 Time point 8","HH","MM","SS","Ext. Device"], + ["56","1","RW","TS2 Time point 8 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["57","1","RW","TS2 Time point 9","HH","MM","SS","Ext. Device"], + ["58","1","RW","TS2 Time point 9 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["59","1","RW","TS2 Time point 10","HH","MM","SS","Ext. Device"], + ["60","1","RW","TS2 Time point 10 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["61","1","RW","TS2 Time point 11","HH","MM","SS","Ext. Device"], + ["62","1","RW","TS2 Time point 11 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["63","1","RW","TS2 Time point 12","HH","MM","SS","Ext. Device"], + ["64","1","RW","TS2 Time point 12 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["65","1","RW","TS2 Time point 13","HH","MM","SS","Ext. Device"], + ["66","1","RW","TS2 Time point 13 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["67","1","RW","TS2 Time point 14","HH","MM","SS","Ext. Device"], + ["68","1","RW","TS2 Time point 14 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["69","1","RW","TS2 Time point 15","HH","MM","SS","Ext. Device"], + ["70","1","RW","TS2 Time point 15 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["71","1","RW","TS2 Time point 16","HH","MM","SS","Ext. Device"], + ["72","1","RW","TS2 Time point 16 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["73","1","RW","Power meter status","TBD","","",""], + ["74","1","R","Input Voltage","","","",""], + ["75","1","R","Input Current","","","",""], + ["76","1","R","Input Power","","","",""], + ["77","1","R","Cos phi","","","",""], + ["78","1","R","Frequency","","","",""], + ["79","1","RW","Energy","","","",""], + ["80","1","RW","Lifetime","","","",""], + ["81","1","RW","Power on cycles (input)","","","",""], + ["82","1","RW","Power on cycles (relay)","","","",""], + ["83","1","R","Time since last power on","","","",""], + ["84","1","R","Accelerometer data","","","",""], + ["85","1","RW","GPS latitude","pos/neg","deg","min ","sec"], + ["86","1","RW","GPS longitude","pos/neg","deg","min ","sec"], + ["87","1","RW","Actual time","HH","MM","SS","RES."], + ["88","1","RW","Actual date","Day of week","Day","Month","Year"], + ["89","1","R","Production data 1","","","",""], + ["90","1","R","Production data 2","","","",""], + ["91","1","RW","Network ID","NID3","NID2","NID1","NID0"], + ["95","1","RW","Actual Lux level from cabinet","RES.","RES.","HB","LB"], + ["96","1","RW","Threshold lux level","Dusk HB","Dusk LB","Dawn HB","Dawn LB"], + ["97","1","RW","Adjust period","Dusk HB","Dusk LB","Dawn HB","Dawn LB"], + ["98","1","RW","Offset","RES.","RES.","Dusk","Dawn"], + ["99","1","RW","CCT min/max range","max-H","max-L","min-H","min-L"], + ["100","1","RW","DALI interface","Cmd ID","Add","Cmd","Resp"], + ["101","1","RW","Module FW ver","v1","v2","v3","v4"], + ["102","1","RW","Module MAC-H","unused","unused","M1","M2"], + ["103","1","RW","Module MAC-L","M3","M4","M5","M6"], + ["122","1","R","FW update status/control register","Byte3","Byte2","Byte1","Byte0"], + ["123","1","R","FW update - data index","Byte3","Byte2","Byte1","Byte0"], + ["124","1","R","FW update - data","Byte3","Byte2","Byte1","Byte0"], + ["0","0","R","Status","","","",""], + ["1","0","RW","Control register","RES.","RES.","RES.","init mode enable"], + ["2","0","R","Device types","","","",""], + ["3","0","R","Serial number (MAC)","","","",""], + ["4","0","R","Production data 1","","","",""], + ["5","0","R","Production data 2","","","",""], + ["6","0","RW","Network ID","NID3","NID2","NID1","NID0"], + ["7","0","RW","RS232 settings","param.","param.","Baudrate H","Baudrate L"], + ["8","0","R","Accelerometer data","","","",""], + ["9","0","RW","Module FW ver","v1","v2","v3","v4"], + ["10","0","RW","Module MAC-H","unused","unused","M1","M2"], + ["11","0","RW","Module MAC-L","M3","M4","M5","M6"], + ["32","0","RW","FW update status/control register","Byte3","Byte2","Byte1","Byte0"], + ["33","0","RW","FW update - data index","Byte3","Byte2","Byte1","Byte0"], + ["34","0","RW","FW update - data","Byte3","Byte2","Byte1","Byte0"], + ["125","0","RW","Debug Register","Byte3","Byte2","Byte1","Byte0"], + ["126","0","RW","Network Control Register","Byte3","Byte2","Byte1","Byte0"], + ["127","0","R","Network Status Register","Byte3","Byte2","Byte1","Byte0"], + ["128","0","RW","Node XX Serial Number Register","SER3","SER2","SER1","SER0"], + ["256","0","R","Node XX Network Status Register","","","",""] +]; + +let register = {}; + +module.exports = { + registers, + register +} \ No newline at end of file diff --git a/RVO16/flow/helper/serialport_helper.js b/RVO16/flow/helper/serialport_helper.js new file mode 100755 index 0000000..7f5920d --- /dev/null +++ b/RVO16/flow/helper/serialport_helper.js @@ -0,0 +1,99 @@ +const { exec } = require('child_process'); + +function openPort(port) { + return new Promise((resolve, reject) => { + + var callbackError = function(err) { + port.removeListener('error', callbackError); + port.removeListener('open', callbackError); + + reject(err.message); + }; + + var callbackOpen = function(data) { + port.removeListener('error', callbackError); + port.removeListener('open', callbackOpen); + + resolve("port open: ok"); + }; + + port.on('error', callbackError); + port.on('open', callbackOpen); + + port.open(); + + }) +} + +function runSyncExec(command) { + return new Promise((resolve, reject) => { + + exec(command, (error, stdout, stderr) => { + if (error == null) resolve(stdout); + reject(error); + }); + + }) +} + +async function writeData(port, data, readbytes, timeout) { + return new Promise((resolve, reject) => { + + // 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) { + + port.write(Buffer.from(data), function(err) { + if (err) { + reject(err.message); + } + }); + + 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 +} diff --git a/RVO16/flow/helper/suncalc.js b/RVO16/flow/helper/suncalc.js new file mode 100755 index 0000000..c9ca56d --- /dev/null +++ b/RVO16/flow/helper/suncalc.js @@ -0,0 +1,317 @@ +/* + (c) 2011-2015, Vladimir Agafonkin + SunCalc is a JavaScript library for calculating sun/moon position and light phases. + https://github.com/mourner/suncalc +*/ + +(function () { 'use strict'; + +// shortcuts for easier to read formulas + +var PI = Math.PI, + sin = Math.sin, + cos = Math.cos, + tan = Math.tan, + asin = Math.asin, + atan = Math.atan2, + acos = Math.acos, + rad = PI / 180; + +// sun calculations are based on http://aa.quae.nl/en/reken/zonpositie.html formulas + + +// date/time constants and conversions + +var dayMs = 1000 * 60 * 60 * 24, + J1970 = 2440588, + J2000 = 2451545; + +function toJulian(date) { return date.valueOf() / dayMs - 0.5 + J1970; } +function fromJulian(j) { return new Date((j + 0.5 - J1970) * dayMs); } +function toDays(date) { return toJulian(date) - J2000; } + + +// general calculations for position + +var e = rad * 23.4397; // obliquity of the Earth + +function rightAscension(l, b) { return atan(sin(l) * cos(e) - tan(b) * sin(e), cos(l)); } +function declination(l, b) { return asin(sin(b) * cos(e) + cos(b) * sin(e) * sin(l)); } + +function azimuth(H, phi, dec) { return atan(sin(H), cos(H) * sin(phi) - tan(dec) * cos(phi)); } +function altitude(H, phi, dec) { return asin(sin(phi) * sin(dec) + cos(phi) * cos(dec) * cos(H)); } + +function siderealTime(d, lw) { return rad * (280.16 + 360.9856235 * d) - lw; } + +function astroRefraction(h) { + if (h < 0) // the following formula works for positive altitudes only. + h = 0; // if h = -0.08901179 a div/0 would occur. + + // formula 16.4 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + // 1.02 / tan(h + 10.26 / (h + 5.10)) h in degrees, result in arc minutes -> converted to rad: + return 0.0002967 / Math.tan(h + 0.00312536 / (h + 0.08901179)); +} + +// general sun calculations + +function solarMeanAnomaly(d) { return rad * (357.5291 + 0.98560028 * d); } + +function eclipticLongitude(M) { + + var C = rad * (1.9148 * sin(M) + 0.02 * sin(2 * M) + 0.0003 * sin(3 * M)), // equation of center + P = rad * 102.9372; // perihelion of the Earth + + return M + C + P + PI; +} + +function sunCoords(d) { + + var M = solarMeanAnomaly(d), + L = eclipticLongitude(M); + + return { + dec: declination(L, 0), + ra: rightAscension(L, 0) + }; +} + + +var SunCalc = {}; + + +// calculates sun position for a given date and latitude/longitude + +SunCalc.getPosition = function (date, lat, lng) { + + var lw = rad * -lng, + phi = rad * lat, + d = toDays(date), + + c = sunCoords(d), + H = siderealTime(d, lw) - c.ra; + + return { + azimuth: azimuth(H, phi, c.dec), + altitude: altitude(H, phi, c.dec) + }; +}; + + +// sun times configuration (angle, morning name, evening name) + +var times = SunCalc.times = [ + [-0.833, 'sunrise', 'sunset' ], + [ -0.3, 'sunriseEnd', 'sunsetStart' ], + [ -6, 'dawn', 'dusk' ], + [ -12, 'nauticalDawn', 'nauticalDusk'], + [ -18, 'nightEnd', 'night' ], + [ 6, 'goldenHourEnd', 'goldenHour' ] +]; + +// adds a custom time to the times config + +SunCalc.addTime = function (angle, riseName, setName) { + times.push([angle, riseName, setName]); +}; + + +// calculations for sun times + +var J0 = 0.0009; + +function julianCycle(d, lw) { return Math.round(d - J0 - lw / (2 * PI)); } + +function approxTransit(Ht, lw, n) { return J0 + (Ht + lw) / (2 * PI) + n; } +function solarTransitJ(ds, M, L) { return J2000 + ds + 0.0053 * sin(M) - 0.0069 * sin(2 * L); } + +function hourAngle(h, phi, d) { return acos((sin(h) - sin(phi) * sin(d)) / (cos(phi) * cos(d))); } +function observerAngle(height) { return -2.076 * Math.sqrt(height) / 60; } + +// returns set time for the given sun altitude +function getSetJ(h, lw, phi, dec, n, M, L) { + + var w = hourAngle(h, phi, dec), + a = approxTransit(w, lw, n); + return solarTransitJ(a, M, L); +} + + +// calculates sun times for a given date, latitude/longitude, and, optionally, +// the observer height (in meters) relative to the horizon + +SunCalc.getTimes = function (date, lat, lng, height) { + + height = height || 0; + + var lw = rad * -lng, + phi = rad * lat, + + dh = observerAngle(height), + + d = toDays(date), + n = julianCycle(d, lw), + ds = approxTransit(0, lw, n), + + M = solarMeanAnomaly(ds), + L = eclipticLongitude(M), + dec = declination(L, 0), + + Jnoon = solarTransitJ(ds, M, L), + + i, len, time, h0, Jset, Jrise; + + + var result = { + solarNoon: fromJulian(Jnoon), + nadir: fromJulian(Jnoon - 0.5) + }; + + for (i = 0, len = times.length; i < len; i += 1) { + time = times[i]; + h0 = (time[0] + dh) * rad; + + Jset = getSetJ(h0, lw, phi, dec, n, M, L); + Jrise = Jnoon - (Jset - Jnoon); + + result[time[1]] = fromJulian(Jrise); + result[time[2]] = fromJulian(Jset); + } + + return result; +}; + + +// moon calculations, based on http://aa.quae.nl/en/reken/hemelpositie.html formulas + +function moonCoords(d) { // geocentric ecliptic coordinates of the moon + + var L = rad * (218.316 + 13.176396 * d), // ecliptic longitude + M = rad * (134.963 + 13.064993 * d), // mean anomaly + F = rad * (93.272 + 13.229350 * d), // mean distance + + l = L + rad * 6.289 * sin(M), // longitude + b = rad * 5.128 * sin(F), // latitude + dt = 385001 - 20905 * cos(M); // distance to the moon in km + + return { + ra: rightAscension(l, b), + dec: declination(l, b), + dist: dt + }; +} + +SunCalc.getMoonPosition = function (date, lat, lng) { + + var lw = rad * -lng, + phi = rad * lat, + d = toDays(date), + + c = moonCoords(d), + H = siderealTime(d, lw) - c.ra, + h = altitude(H, phi, c.dec), + // formula 14.1 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + pa = atan(sin(H), tan(phi) * cos(c.dec) - sin(c.dec) * cos(H)); + + h = h + astroRefraction(h); // altitude correction for refraction + + return { + azimuth: azimuth(H, phi, c.dec), + altitude: h, + distance: c.dist, + parallacticAngle: pa + }; +}; + + +// calculations for illumination parameters of the moon, +// based on http://idlastro.gsfc.nasa.gov/ftp/pro/astro/mphase.pro formulas and +// Chapter 48 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + +SunCalc.getMoonIllumination = function (date) { + + var d = toDays(date || new Date()), + s = sunCoords(d), + m = moonCoords(d), + + sdist = 149598000, // distance from Earth to Sun in km + + phi = acos(sin(s.dec) * sin(m.dec) + cos(s.dec) * cos(m.dec) * cos(s.ra - m.ra)), + inc = atan(sdist * sin(phi), m.dist - sdist * cos(phi)), + angle = atan(cos(s.dec) * sin(s.ra - m.ra), sin(s.dec) * cos(m.dec) - + cos(s.dec) * sin(m.dec) * cos(s.ra - m.ra)); + + return { + fraction: (1 + cos(inc)) / 2, + phase: 0.5 + 0.5 * inc * (angle < 0 ? -1 : 1) / Math.PI, + angle: angle + }; +}; + + +function hoursLater(date, h) { + return new Date(date.valueOf() + h * dayMs / 24); +} + +// calculations for moon rise/set times are based on http://www.stargazing.net/kepler/moonrise.html article + +SunCalc.getMoonTimes = function (date, lat, lng, inUTC) { + var t = new Date(date); + if (inUTC) t.setUTCHours(0, 0, 0, 0); + else t.setHours(0, 0, 0, 0); + + var hc = 0.133 * rad, + h0 = SunCalc.getMoonPosition(t, lat, lng).altitude - hc, + h1, h2, rise, set, a, b, xe, ye, d, roots, x1, x2, dx; + + // go in 2-hour chunks, each time seeing if a 3-point quadratic curve crosses zero (which means rise or set) + for (var i = 1; i <= 24; i += 2) { + h1 = SunCalc.getMoonPosition(hoursLater(t, i), lat, lng).altitude - hc; + h2 = SunCalc.getMoonPosition(hoursLater(t, i + 1), lat, lng).altitude - hc; + + a = (h0 + h2) / 2 - h1; + b = (h2 - h0) / 2; + xe = -b / (2 * a); + ye = (a * xe + b) * xe + h1; + d = b * b - 4 * a * h1; + roots = 0; + + if (d >= 0) { + dx = Math.sqrt(d) / (Math.abs(a) * 2); + x1 = xe - dx; + x2 = xe + dx; + if (Math.abs(x1) <= 1) roots++; + if (Math.abs(x2) <= 1) roots++; + if (x1 < -1) x1 = x2; + } + + if (roots === 1) { + if (h0 < 0) rise = i + x1; + else set = i + x1; + + } else if (roots === 2) { + rise = i + (ye < 0 ? x2 : x1); + set = i + (ye < 0 ? x1 : x2); + } + + if (rise && set) break; + + h0 = h2; + } + + var result = {}; + + if (rise) result.rise = hoursLater(t, rise); + if (set) result.set = hoursLater(t, set); + + if (!rise && !set) result[ye > 0 ? 'alwaysUp' : 'alwaysDown'] = true; + + return result; +}; + + +// export as Node module / AMD module / browser variable +if (typeof exports === 'object' && typeof module !== 'undefined') module.exports = SunCalc; +else if (typeof define === 'function' && define.amd) define(SunCalc); +else window.SunCalc = SunCalc; + +}()); diff --git a/RVO16/flow/helper/utils.js b/RVO16/flow/helper/utils.js new file mode 100755 index 0000000..dbffe45 --- /dev/null +++ b/RVO16/flow/helper/utils.js @@ -0,0 +1,161 @@ +const fs = require('fs').promises; + +function bytesToInt(bytes, numberOfBytes) { + let buffer = []; + if (Array.isArray(bytes)) { + buffer = bytes.slice(0); + if (numberOfBytes != undefined) { + buffer = bytes.slice(bytes.length - numberOfBytes); + } + } + else buffer.push(bytes); + + let result = 0; + for (let i = 0; i < buffer.length; i++) { + result = (result << 8) | buffer[i]; + } + + return result >>> 0; //ensure it's an unsigned 32-bit number +} + +function resizeArray(arr, newSize, defaultValue) { + while (newSize > arr.length) + arr.push(defaultValue); + arr.length = newSize; +} + +longToByteArray = function(/*long*/long) { + // we want to represent the input as a 8-bytes array + var byteArray = [0, 0, 0, 0, 0, 0, 0, 0]; + + for (var index = 0; index < byteArray.length; index++) { + var byte = long & 0xff; + byteArray[index] = byte; + long = (long - byte) / 256; + } + + return byteArray; +}; + +function addDays(date, days) { + var result = new Date(date); + result.setDate(result.getDate() + days); + return result; +} + +/* +sleep(2000).then(() => { + // Do something after the sleep! + + +}); +*/ + +function sleep(time) { + return new Promise((resolve) => setTimeout(resolve, time)); +} + +function isEmptyObject(obj) { + for (var name in obj) { + return false; + } + return true; +} + +function emptyJsObject(jsObject) { + Object.keys(jsObject).forEach(key => delete jsObject[key]); +} + +function convertUTCDateToLocalDate(date) { + var newDate = new Date(date); + newDate.setMinutes(date.getMinutes() + date.getTimezoneOffset()); + return newDate; +} + +function addZeroBefore(n) { + return (n < 10 ? '0' : '') + n; +} + + +/** + * Asynchronously writes data to a file. + * + * @param {string} filePath The path to the file. + * @param {string} data The data to write to the file. + * @param {boolean} [append=false] If true, appends the data to the file. If false, it overwrites the file. + */ +async function writeToFile(filePath, data, append = false) { + if (typeof data !== 'string') data = JSON.stringify(data, null, 2); + try { + if (append) { + // Append the data to the end of the file. This is the simplest way to append. + await fs.appendFile(filePath, data, 'utf8'); + console.log(`Successfully appended data to ${filePath} using fs.appendFile.`); + } else { + // Overwrite the file with the new data. + await fs.writeFile(filePath, data, 'utf8'); + console.log(`Successfully wrote (overwrote) data to ${filePath} using fs.writeFile.`); + } + } catch (error) { + console.error(`Error writing to file ${filePath}:`, error); + } +} + + + /** + * Checks if an item is present in an array and adds it if it's not. + * * @param {Array} arr The array to check. + * @param {*} item The item to add. + * @returns {Array} The modified array. + */ +const addToArrayIfUnique = (arr, item) => { + if (!arr.includes(item)) { + arr.push(item); + } + return arr; +}; + + +var convertBase = function() { + + function convertBase(baseFrom, baseTo) { + return function(num) { + return parseInt(num, baseFrom).toString(baseTo); + + }; + } + + // binary to decimal + convertBase.bin2dec = convertBase(2, 10); + + // binary to hexadecimal + convertBase.bin2hex = convertBase(2, 16); + + // decimal to binary + convertBase.dec2bin = convertBase(10, 2); + + // decimal to hexadecimal + convertBase.dec2hex = convertBase(10, 16); + + // hexadecimal to binary + convertBase.hex2bin = convertBase(16, 2); + + // hexadecimal to decimal + convertBase.hex2dec = convertBase(16, 10); + + return convertBase; +}(); + +module.exports = { + bytesToInt, + longToByteArray, + addDays, + addZeroBefore, + resizeArray, + isEmptyObject, + emptyJsObject, + sleep, + convertUTCDateToLocalDate, + writeToFile, + addToArrayIfUnique +} diff --git a/RVO16/flow/httprequest.js b/RVO16/flow/httprequest.js new file mode 100755 index 0000000..469c8cb --- /dev/null +++ b/RVO16/flow/httprequest.js @@ -0,0 +1,137 @@ +exports.id = 'httprequest'; +exports.title = 'HTTP Request'; +exports.group = 'HTTP'; +exports.color = '#5D9CEC'; +exports.input = true; +exports.version = '2.0.1'; +exports.output = 1; +exports.author = 'Peter Širka'; +exports.icon = 'cloud-upload'; + +exports.html = `
+
@(URL address)
+
+
+
@(HTTP method)
+
+
+
@(Serialization)
+
+
+
@(Download the content in chunks)
+
@(Keep persistent cookies)
+
@(Disable DNS cache)
+
@(Keep alive connection)
+
+
+
+
@(Custom headers)
+
@(Cookies)
+
+
+
+ +
+
+
+
@(User)
+
+
+
@(Password)
+
+
+
+
+
`; + +exports.readme = `# Request + +This component creates a request with received data. + +__Response:__ +\`\`\`javascript +{ + data: String, + headers: Object, + status: Number, + host: String +} +\`\`\` + +__Dynamic arguments__: +Are performed via FlowData repository and can be used for URL address or for custom headers/cookies/auth. Use \`repository\` component for creating of dynamic arguments. Dynamic values are replaced in the form \`{key}\`: + +- url address e.g. \`https://.../{key}/\` +- headers values e.g. \`{token}\` +- cookies values e.g. \`{token}\``; + +exports.install = function(instance) { + + var can = false; + var flags = null; + var cookies2 = null; + + instance.on('data', function(response) { + can && instance.custom.send(response); + }); + + instance.custom.send = function(response) { + var options = instance.options; + + var headers = null; + var cookies = null; + + options.headers && Object.keys(options.headers).forEach(function(key) { + !headers && (headers = {}); + headers[key] = response.arg(options.headers[key]); + }); + + if (options.username && options.userpassword) { + !headers && (headers = {}); + headers['Authorization'] = 'Basic ' + U.createBuffer(response.arg(options.username + ':' + options.userpassword)).toString('base64'); + } + + options.cookies && Object.keys(options.cookies).forEach(function(key) { + !cookies && (cookies = {}); + cookies[key] = response.arg(options.cookies[key]); + }); + + if (options.chunks) { + U.download(response.arg(options.url), flags, options.stringify === 'none' ? null : response.data, function(err, response) { + response.on('data', (chunks) => instance.send2(chunks)); + }, cookies || cookies2, headers); + } else { + U.request(response.arg(options.url), flags, options.stringify === 'none' ? null : response.data, 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) + instance.error(err, response); + }, cookies || cookies2, headers); + } + }; + + instance.reconfigure = function() { + var options = instance.options; + can = options.url && options.url && options.method && options.stringify ? true : false; + instance.status(can ? '' : 'Not configured', can ? undefined : 'red'); + + if (!can) + return; + + flags = []; + flags.push(options.method.toLowerCase()); + options.stringify === 'json' && flags.push('json'); + options.stringify === 'raw' && flags.push('raw'); + options.keepalive && flags.push('keepalive'); + !options.nodns && flags.push('dnscache'); + if (options.persistentcookies) { + flags.push('cookies'); + cookies2 = {}; + } else + cookies2 = null; + }; + + instance.on('options', instance.reconfigure); + instance.reconfigure(); +}; \ No newline at end of file diff --git a/RVO16/flow/httpresponse.js b/RVO16/flow/httpresponse.js new file mode 100755 index 0000000..160a3bb --- /dev/null +++ b/RVO16/flow/httpresponse.js @@ -0,0 +1,76 @@ +exports.id = 'httpresponse'; +exports.title = 'HTTP Response'; +exports.group = 'HTTP'; +exports.color = '#5D9CEC'; +exports.icon = 'arrow-right'; +exports.input = true; +exports.output = ['#666D76']; +exports.version = '2.0.0'; +exports.author = 'Martin Smola'; +exports.readme = `# HTTP response + +HTTP response will respond with data recieved using data-type set in Settings form or plain text if not set. Output is the message duration \`Number\` in seconds.`; + +exports.html = `
+
@(Response data-type)
+
JSON is by default.
+
`; + +exports.install = function(instance) { + + var dursum = 0; + var durcount = 0; + + instance.on('data', function(flowdata) { + + var ctrl = flowdata.repository.controller; + var data = flowdata.data; + + if (!ctrl) { + instance.throw('No controller to use for response!'); + return; + } + + durcount++; + dursum += ((new Date() - flowdata.begin) / 1000).floor(2); + setTimeout2(instance.id, instance.custom.duration, 500, 10); + + ctrl.$flowdata = flowdata; + + var datatype = instance.options.datatype || 'json'; + if (datatype === 'emptyresponse') + return ctrl.plain(''); + + if (datatype !== 'json' && typeof(data) !== 'string') { + instance.throw('Incorect type of data, expected string, got ' + typeof(data)); + ctrl.plain(data == null ? '' : data.toString()); + return; + } + + switch(datatype) { + case 'html': + ctrl.content(data, 'text/html'); + break; + case 'plain': + ctrl.plain(data); + break; + case 'xml': + ctrl.content(data, 'text/xml'); + break; + default: + ctrl.json(data); + break; + } + }); + + instance.on('service', function() { + dursum = 0; + durcount = 0; + }); + + instance.custom.duration = function() { + var avg = (dursum / durcount).floor(2); + instance.status(avg + ' sec.'); + instance.send2(0, avg); + }; +}; diff --git a/RVO16/flow/httproute.js b/RVO16/flow/httproute.js new file mode 100755 index 0000000..583a19d --- /dev/null +++ b/RVO16/flow/httproute.js @@ -0,0 +1,326 @@ +exports.id = 'httproute'; +exports.title = 'HTTP Route'; +exports.group = 'HTTP'; +exports.color = '#5D9CEC'; +exports.icon = 'globe'; +exports.input = false; +exports.output = ['#6CAC5A', '#37BC9B']; +exports.version = '1.2.3'; +exports.author = 'Martin Smola'; +exports.cloning = false; +exports.options = { method: 'GET', url: '', size: 5, cacheexpire: '5 minutes', cachepolicy: 0, timeout: 5 }; +exports.dateupdated = '2021-01-21 18:30d'; +exports.readme = `# HTTP route + +__Outputs__: +- first output: raw data (cache is empty or is disabled) +- second output: cached data + +If one of the outputs is disabled then automatic responce with code "503 service unavailable" is sent. + +When a request comes in bellow object is available at \`flowdata.data\`: + +\`\`\`javascript +{ + params: { id: '1' }, // params for dynamic routes, e.g. /test/{id} + query: { msg: 'Hello' }, // parsed query string, e.g. /test/1?msg=Hello + body: { test: 'OK' }, // object if json requests otherwise string + headers: {}, // headers data + session: {}, // session data + user: {}, // user data + files: [], // uploaded files + url: '/users/', // a relative URL address + referrer: '/', // referrer + mobile: false, // determines mobile device + robot: false, // determines search robots/crawlsers + language: 'en' // determines language +} +\`\`\` + +See [documentation for flags](https://docs.totaljs.com/latest/en.html#api~HttpRouteOptionsFlags~unauthorize). These method flags are set automatically e.g. \`get, post, put, patch or delete\` + +--- + +\`id:ROUTE_ID\` flag cannot be used since it's already used by this component internally`; + +exports.html = `
+
+ +
+ +
+
+
@(HTTP method)
+
+
+
@(URL address)
+
+
+
+
+
@(Additional flags)
+
@(Separate flags by comma e.g. json, authorize)
+
+
+
@(Max. request size)
+
@(In kB kilobytes)
+
+
+
@(Timeout)
+
@(In seconds.)
+
+
+
+
+
+
@(Automatically respond with 200 OK?)
+
@(If not checked you need to use HTTP response component to respond to the request.)
+
+
@(Custom headers)
+
@(Cookies)
+
+
+
+
+
+
@(Cache policy)
+
@(User instance must contain id property.)
+
+
+
@(Expiration)
+
@(E.g. 5 minutes)
+
+
+
+`; + +exports.install = function(instance) { + + var route; + + var uninstall = function(id) { + if (F.is4) { + route && route.remove(); + route = null; + } else + UNINSTALL('route', id); + }; + + instance.custom.emptyresponse = function(self) { + self.plain(); + }; + + instance.reconfigure = function() { + + var options = instance.options; + + if (!options.url) { + instance.status('Not configured', 'red'); + return; + } + + if (typeof(options.flags) === 'string') + options.flags = options.flags.split(',').trim(); + + uninstall('id:' + instance.id); + + var flags = options.flags || []; + + flags.push('id:' + instance.id); + + if (!F.is4) + flags.push(options.method.toLowerCase()); + + options.timeout && flags.push(options.timeout * 1000); + + // Make unique values + flags = flags.filter(function(v, i, a) { + if(F.is4 && v.toString().toLowerCase() === options.method.toLowerCase()) + return false; // remove method + return a.indexOf(v) === i; + }); + + options.flags = flags; + var handler = function() { + + if (instance.paused || (instance.isDisabled && (instance.isDisabled('output', 0) || instance.isDisabled('output', 1)))) { + instance.status('503 Service Unavailable'); + this.status = 503; + this.json(); + return; + } + + var key; + var self = this; + + if (instance.options.emptyresponse) { + instance.status('200 OK'); + setTimeout(instance.custom.emptyresponse, 100, self); + + if (instance.hasConnection(0)) { + var data = instance.make({ + query: self.query, + body: self.body, + session: self.session, + user: self.user, + files: self.files, + headers: self.req.headers, + url: self.url, + params: self.params + }); + instance.send2(0, data); + } + + return; + } + + switch (instance.options.cachepolicy) { + case 1: // URL + key = 'rro' + instance.id + self.url.hash(); + break; + case 2: // URL + query + case 3: // URL + query + user + key = self.url; + var keys = Object.keys(self.query); + keys.sort(); + for (var i = 0, length = keys.length; i < length; i++) + key += keys[i] + self.query[keys[i]] + '&'; + if (instance.options.cachepolicy === 3 && self.user) + key += 'iduser' + self.user.id; + key = 'rro' + instance.id + key.hash(); + break; + } + + if (key && F.cache.get2(key)) { + var data = instance.make(F.cache.get2(key)); + data.repository.controller = self; + instance.send2(1, data); + } else { + + var data = instance.make({ + query: self.query, + body: self.body, + session: self.session, + user: self.user, + files: self.files, + headers: self.req.headers, + url: self.url, + params: self.params, + mobile: self.mobile, + robot: self.robot, + referrer: self.referrer, + language: self.language + }); + + data.repository.controller = self; + instance.send2(0, data); + key && FINISHED(self.res, () => F.cache.set(key, self.$flowdata.data, instance.options.cacheexpire)); + } + }; + + if (F.is4) + route = ROUTE(options.method.toUpperCase() + ' ' + options.url, handler, flags, options.size || 5); + else + F.route(options.url, handler, flags, options.size || 5); + + instance.status('Listening', 'green'); + }; + + instance.reconfigure(); + instance.on('options', instance.reconfigure); + instance.on('close', function(){ + uninstall('id:' + instance.id); + }); +}; + +// check url exists +FLOW.trigger('httproutecheckurl', function(next, data) { + var url = data.url; + var method = data.method; + if (url[url.length - 1] !== '/') + url += '/'; + var exists = F.routes.web.findItem(r => r.urlraw === url && r.method === method); + next(exists != null); +}); + +exports.uninstall = function() { + FLOW.trigger('httproutecheckurl', null); +}; diff --git a/RVO16/flow/infosender.js b/RVO16/flow/infosender.js new file mode 100755 index 0000000..587724f --- /dev/null +++ b/RVO16/flow/infosender.js @@ -0,0 +1,81 @@ +exports.id = 'infosender'; +exports.title = 'Info sender'; +exports.version = '1.0.0'; +exports.group = 'Worksys'; +exports.color = '#2134B0'; +exports.input = 2; +exports.output = 1 +exports.icon = 'bolt'; + +const { networkInterfaces } = require('os'); + +exports.html = `
+
+
+
CSV Import
+
+
+
`; + +exports.readme = `# send all data to projects.worksys.io, required to monitor status of controller(unipi)`; + +exports.install = function(instance) { + + let id; + let allValues = {}; + let sendAllValuesInterval; + let configured = false; + + let now = new Date(); + console.log(exports.title, "INSTALLED", now.toLocaleString("sk-SK")); + + const nets = networkInterfaces(); + let ipAddresses = Object.create(null); // Or just '{}', an empty object + + for (const name of Object.keys(nets)) { + for (const net of nets[name]) { + // Skip over non-IPv4 and internal (i.e. 127.0.0.1) addresses + if (net.family === 'IPv4' && !net.internal) { + if (!ipAddresses[name]) { + ipAddresses[name] = []; + } + ipAddresses[name].push(net.address); + } + } + } + + function sendValues() { + if (!configured) return; + + if (Object.keys(allValues).length > 0) { + let dataToSend = { ...allValues }; + dataToSend.id = id; + dataToSend.ipAddresses = ipAddresses; + + instance.send(0, dataToSend); + + allValues = {}; + } + } + + instance.on("close", () => { + clearInterval(sendAllValuesInterval); + }) + + instance.on("0", _ => { + id = FLOW.GLOBALS.settings.project_id; + if (id) configured = true; + else console.log(exports.title, "InfoSender: Unable to send data, no id"); + }) + + instance.on("1", flowdata => { + allValues = { ...allValues, ...flowdata.data }; + //console.log("DATA RECEIVED", flowdata.data); + }) + + sendAllValuesInterval = setInterval(() => { + sendValues(); + }, 60000 * 3); + +} + diff --git a/RVO16/flow/modbus_reader.js b/RVO16/flow/modbus_reader.js new file mode 100755 index 0000000..d6d9dad --- /dev/null +++ b/RVO16/flow/modbus_reader.js @@ -0,0 +1,346 @@ +exports.id = 'modbus_reader'; +exports.title = 'Modbus reader'; +exports.version = '2.0.0'; +exports.group = 'Worksys'; +exports.color = '#2134B0'; +exports.input = 1; +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; +//number of phases inRVO +let phases; +//phases where voltage is 0 (set) +let noVoltage; +let energyToSwitchLamps; + +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.phases = this.buildPhases(); + + this.startSocket(); + } + + buildPhases = () => { + let a = []; + for (let i = 1; i <= phases; i++) { + a.push(`Phase_${i}_voltage`) + } + return a; + } + + startSocket = () => { + + let obj = this; + + if (this.socket) { + this.socket.removeAllListeners(); + this.socket = null; + } + + 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('Modbus_reader: Socket connection error', e); //'ECONNREFUSED' or 'ECONNRESET' ?? + }); + + this.socket.on('close', function() { + console.log('Modbus_reader: Socket connection closed - Waiting 10 seconds before connecting 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 we just start to loop devices from the beginning, or there is just 1 device in config, we wait whole timeoutInterval + if (this.indexInDeviceConfig == 0 || deviceConfig.length === 1) 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 (this.phases.includes(singleValue)) { + let l = singleValue.split("_"); + let phase = parseInt(l[1]); + + // console.log(values[singleValue], tbName); + + if (values[singleValue] == 0) { + noVoltage.add(phase); + sendNotification("modbus_reader: checkNullVoltage", tbName, "no_voltage_on_phase", { phase: phase }, "", SEND_TO.tb, instance, "voltage" + phase); + // console.log('no voltage') + } + else { + noVoltage.delete(phase); + // console.log('voltage detected') + sendNotification("modbus_reader: checkNullVoltage", tbName, "voltage_on_phase_restored", { phase: phase }, "", SEND_TO.tb, instance, "voltage" + phase); + } + } + }) + } + + /** + * function sends notification to slack and to tb, if EM total_power value changes more than numberOfNodes*15. This should show, that RVO lamps has been switched on or off + */ + lampSwitchNotification = (values) => { + + if (!values.hasOwnProperty("total_power")) return; + + const actualTotalPower = values.total_power; + + if (actualTotalPower > energyToSwitchLamps && 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 <= energyToSwitchLamps && 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; + } + + function main() { + + phases = FLOW.GLOBALS.settings.phases; + tbName = FLOW.GLOBALS.settings.rvoTbName; + noVoltage = FLOW.GLOBALS.settings.no_voltage; + energyToSwitchLamps = FLOW.GLOBALS.settings.energy_to_switch_lamps / 2.5; //half value is enought to show if lamps are turned on or off + if (deviceConfig.length) mainSocket = new SocketWithClients(); + else console.log("Modbus_reader: no modbus device in configuration"); + + // this notification is to show, that flow (unipi) has been restarted + sendNotification("modbus_reader", tbName, "flow_restart", {}, "", SEND_TO.slack, instance); + } + + instance.on("0", function(_) { + main(); + }) + +} + diff --git a/RVO16/flow/monitorconsumption.js b/RVO16/flow/monitorconsumption.js new file mode 100755 index 0000000..64cc58e --- /dev/null +++ b/RVO16/flow/monitorconsumption.js @@ -0,0 +1,156 @@ +exports.id = 'monitorconsumption'; +exports.title = 'Consumption'; +exports.version = '1.0.0'; +exports.author = 'Peter Širka'; +exports.group = 'Monitoring'; +exports.color = '#967ADC'; +exports.input = 0; +exports.output = 1; +exports.icon = 'bug'; +exports.options = { interval: 5000, enabled: true, monitorconsumption: true, monitorsize: true, monitorconnections: true, monitorfiles: true }; +exports.click = true; +exports.readme = `# Consumption monitoring + +This component measure CPU and memory consumption, open files and open connections of this application. It uses these Linux commands: \`ps\`, \`lsof\`, \`netstat\` and \`df\`. + +__Data Example__: + +\`\`\`javascript +{ + cpu: 0, // percentage + memory: 4096, // in bytes + size: 34303, // directory size in bytes + files: 34, // count of open files + connections: 343, // count of connections + uptime: '1-12:34:00' +} +\`\`\``; + +exports.html = `
+
+
+
@(Interval in milliseconds)
+
+
+
+
Monitor: Consumption + uptime
+
Monitor: Count of open files
+
Monitor: Count of open connections
+
Monitor: Directory size
+
`; + +exports.install = function(instance) { + + var current = { cpu: 0, memory: 0, files: 0, connections: 0, size: 0, uptime: '', counter: 0 }; + var tproc = null; + var Exec = require('child_process').exec; + var reg_empty = /\s{2,}/g; + var reg_appdisksize = /^[\d.,]+/; + + instance.custom.run = function() { + + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + + var arr = []; + + // Get CPU and Memory consumption + instance.options.monitorconsumption && arr.push(function(next) { + Exec('ps -p {0} -o %cpu,rss,etime'.format(process.pid), function(err, response) { + + if (err) { + instance.throw(err); + } else { + var line = response.split('\n')[1]; + line = line.trim().replace(reg_empty, ' ').split(' '); + var cpu = line[0].parseFloat(); + current.cpu = cpu.floor(1); + current.memory = line[1].parseInt2() * 1024; // kB to bytes + current.uptime = line[2]; + } + + next(); + }); + }); + + // Get count of open files + instance.options.monitorfiles && arr.push(function(next) { + Exec('lsof -a -p {0} | wc -l'.format(process.pid), function(err, response) { + if (err) + instance.throw(err); + else + current.files = response.trim().parseInt2(); + next(); + }); + }); + + // Get count of opened network connections + instance.options.monitorconnections && arr.push(function(next) { + Exec('netstat -an | grep :{0} | wc -l'.format(F.port), function(err, response) { + if (err) { + instance.throw(err); + } else { + current.connections = response.trim().parseInt2() - 1; + if (current.connections < 0) + current.connections = 0; + } + next(); + }); + }); + + // Get directory size + instance.options.monitorsize && current.counter % 5 !== 0 && arr.push(function(next) { + Exec('du -hsb ' + process.cwd(), function(err, response) { + if (err) { + instance.throw(err); + } else { + var match = response.trim().match(reg_appdisksize); + match && (current.size = match.toString().trim().parseInt2()); + } + next(); + }); + }); + + arr.async(function() { + + tproc && clearTimeout(tproc); + + if (instance.options.enabled) { + tproc = setTimeout(instance.custom.run, instance.options.interval); + instance.send2(current); + } + + instance.custom.status(); + current.counter++; + }); + }; + + instance.custom.status = function() { + if (instance.options.enabled) + instance.status('{0}% / {1}'.format(current.cpu, current.memory.filesize())); + else + instance.status('Disabled', 'red'); + }; + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + + if (instance.options.enabled) { + current.counter = 0; + instance.custom.run(); + } + + }); + + instance.on('close', function() { + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + }); + + setTimeout(instance.custom.run, 1000); +}; \ No newline at end of file diff --git a/RVO16/flow/monitordisk.js b/RVO16/flow/monitordisk.js new file mode 100755 index 0000000..f4fdaa0 --- /dev/null +++ b/RVO16/flow/monitordisk.js @@ -0,0 +1,96 @@ +exports.id = 'monitordisk'; +exports.title = 'Disk'; +exports.version = '1.0.0'; +exports.author = 'Peter Širka'; +exports.group = 'Monitoring'; +exports.color = '#F6BB42'; +exports.output = 1; +exports.icon = 'hdd-o'; +exports.click = true; +exports.options = { interval: 8000, path: '/', enabled: true }; +exports.readme = `# Disk monitoring + +This component monitors disk \`bytes\` consumption in Linux systems. It uses \`df\` command. + +__Data Example__: + +\`\`\`javascript +{ + total: 474549649408, + used: 39125245952, + free: 411294994432 +} +\`\`\``; + +exports.html = `
+
+
+
@(Interval in milliseconds)
+
+
+
@(Path)
+
+
+
`; + +exports.install = function(instance) { + + var current = { total: 0, used: 0, free: 0, path: '', type: '', percentUsed: 0 }; + var tproc = null; + + instance.custom.run = function() { + + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + + if (!instance.options.enabled) + return; + + require('child_process').exec('df -hTB1 ' + instance.options.path, function(err, response) { + + tproc = setTimeout(instance.custom.run, instance.options.interval); + + if (err) { + instance.error(err); + return; + } + + response.parseTerminal(function(line) { + if (line[0][0] !== '/') + return; + current.total = line[2].parseInt(); + current.free = line[4].parseInt(); + current.used = line[3].parseInt(); + current.path = instance.options.path || '/'; + current.type = line[1]; + current.percentUsed = line[5]; + instance.custom.status(); + instance.send2(current); + }); + }); + }; + + instance.custom.status = function() { + if (instance.options.enabled) + instance.status(current.free.filesize() + ' / ' + current.total.filesize()); + else + instance.status('Disabled', 'red'); + }; + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + instance.options.enabled && instance.custom.run(); + }); + + instance.on('close', function() { + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + }); + + setTimeout(instance.custom.run, 1000); +}; \ No newline at end of file diff --git a/RVO16/flow/monitormemory.js b/RVO16/flow/monitormemory.js new file mode 100755 index 0000000..2decbc4 --- /dev/null +++ b/RVO16/flow/monitormemory.js @@ -0,0 +1,87 @@ +exports.id = 'monitormemory'; +exports.title = 'Memory'; +exports.version = '1.0.0'; +exports.author = 'Peter Širka'; +exports.group = 'Monitoring'; +exports.color = '#F6BB42'; +exports.output = 1; +exports.click = true; +exports.icon = 'microchip'; +exports.options = { interval: 8000, enabled: true }; +exports.readme = `# Memory monitoring + +This component monitors memory \`bytes\` consumption in Linux systems. It uses \`free\` command. + +__Data Example__: + +\`\`\`javascript +{ + total: 33558769664, + used: 1998868480, + free: 2653708288 +} +\`\`\``; + +exports.html = `
+
+
+
@(Interval in milliseconds)
+
+
+
`; + +exports.install = function(instance) { + + var current = { total: 0, used: 0, free: 0 }; + var tproc = null; + + instance.custom.run = function() { + + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + + if (!instance.options.enabled) + return; + + require('child_process').exec('free -b -t', function(err, response) { + + tproc = setTimeout(instance.custom.run, instance.options.interval); + + if (err) { + instance.error(err); + return; + } + + var memory = response.split('\n')[1].match(/\d+/g); + current.total = memory[0].parseInt(); + current.used = memory[1].parseInt() - memory[3].parseInt(); + current.free = current.total - current.used; + instance.custom.status(); + instance.send2(current); + }); + }; + + instance.custom.status = function() { + if (instance.options.enabled) + instance.status(current.free.filesize() + ' / ' + current.total.filesize()); + else + instance.status('Disabled', 'red'); + }; + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + instance.options.enabled && instance.custom.run(); + }); + + instance.on('close', function() { + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + }); + + setTimeout(instance.custom.run, 1000); +}; \ No newline at end of file diff --git a/RVO16/flow/nodesdb_changecheck.js b/RVO16/flow/nodesdb_changecheck.js new file mode 100755 index 0000000..9adab62 --- /dev/null +++ b/RVO16/flow/nodesdb_changecheck.js @@ -0,0 +1,77 @@ +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 = 2; +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); + } + } + + //kedze do slacku posielame stringy, na cloud musime previest vsetky stringy spat na objekty: + // Funkcia na parsovanie všetkých reťazcov v poli + const parseArray = (arr) => { + return arr.map(jsonString => JSON.parse(jsonString)); + }; + + 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); + if (FLOW.GLOBALS.settings.send_changed_node_numbers) instance.send(1, { aktualneNody: parseArray(zmenene), originalne: parseArray(Array.from(set2)) }); + } + 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/RVO16/flow/show_dbdata.js b/RVO16/flow/show_dbdata.js new file mode 100755 index 0000000..1e23ff7 --- /dev/null +++ b/RVO16/flow/show_dbdata.js @@ -0,0 +1,243 @@ +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 = 8; +exports.output = 1; + +const { exec } = require('child_process'); + +exports.install = 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 }) + }) + instance.on("5", _ => { + exec("sudo tail -n 25 monitor.txt", (err, stdout, stderr) => { + if (err || stderr) instance.send(0, { err, stderr }); + else instance.send(0, stdout); + }) + }) + instance.on("6", _ => { + exec("sudo tail -n 25 err.txt", (err, stdout, stderr) => { + if (err || stderr) instance.send(0, { err, stderr }); + else instance.send(0, stdout); + }) + }) + instance.on("7", _ => { + instance.send(0, FLOW.deviceStatus); + }) +}; + + +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/RVO16/flow/slack_filter.js b/RVO16/flow/slack_filter.js new file mode 100755 index 0000000..6618523 --- /dev/null +++ b/RVO16/flow/slack_filter.js @@ -0,0 +1,188 @@ +exports.id = 'slack_filter'; +exports.title = 'Slack Filter'; +exports.group = 'Citysys'; +exports.color = '#30E193'; +exports.input = 2; +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 = `
+
+
+
@(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('0', 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']['en']; + 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"] = []; + } + + instance.options.name = FLOW.GLOBALS.settings.rvo_name; + if (instance.options.name) { + instance.status('Running'); + running = true; + } else { + instance.status('Please run options again', 'red'); + running = false; + } + } catch (e) { + instance.error('Citysys connector: ' + e.message); + } + }; + + instance.on('options', instance.reconfigure); + + instance.on("1", _ => { + instance.reconfigure(); + }) +}; diff --git a/RVO16/flow/thermometer.js b/RVO16/flow/thermometer.js new file mode 100755 index 0000000..fc7074d --- /dev/null +++ b/RVO16/flow/thermometer.js @@ -0,0 +1,99 @@ +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 = 5;//minutes +let NUMBER_OF_FAILURES_TO_SEND_ERROR = 13; + +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) => { + + 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); + setTimeout(main, 20000); + }) +}; diff --git a/RVO16/flow/trigger.js b/RVO16/flow/trigger.js new file mode 100755 index 0000000..27545a8 --- /dev/null +++ b/RVO16/flow/trigger.js @@ -0,0 +1,79 @@ +exports.id = 'trigger'; +exports.title = 'Trigger'; +exports.group = 'Inputs'; +exports.color = '#F6BB42'; +exports.click = true; +exports.output = 1; +exports.version = '1.1.0'; +exports.author = 'Martin Smola'; +exports.icon = 'play'; + +exports.html = `
+
@(Data type (String by default))
+
@(Data)
+
Trigger 5s after initialization.
+
@(Useful when there's a need to run certain flow when the app restarts, etc.)
+
`; + +exports.readme = `# Trigger + +- Clicking on the component starts the chain +- Settings allows to set a data-type and a value`; + +exports.install = function(instance) { + + var value; + + instance.on('click', () => instance.send2(value)); + + instance.reconfigure = function() { + var options = instance.options; + value = null; + switch (options.datatype) { + case 'integer': + value = options.data.parseInt2('error'); + value = value === 'error' ? NaN : value; + break; + case 'float': + value = options.data.parseFloat2('error'); + value = value === 'error' ? NaN : value; + break; + case 'date': + options.data = options.data.toString(); + var num = options.data.parseInt('error'); + num === 'error' && (num = options.data.parseDate('error')); + num === 'error' && (num = null); + value = num ? new Date(num).toUTCString() : num; + break; + case 'object': + try { + value = (new Function('return ' + options.data))(); + } catch (e) { + instance.error(e); + } + break; + case 'boolean': + value = options.data.parseBoolean(); + break; + case 'buffer': + try { + value = U.createBuffer(options.data); + } catch (e) { + instance.error(e); + } + break; + case 'string': + default: + value = '' + (options.data || ''); + break; + } + }; + + instance.on('options', instance.reconfigure); + instance.reconfigure(); + + if (instance.options.restart) + setTimeout(function(){ + instance.send2(value); + }, 5000); +}; diff --git a/RVO16/flow/variables.txt b/RVO16/flow/variables.txt new file mode 100755 index 0000000..e69de29 diff --git a/RVO16/flow/virtualwirein.js b/RVO16/flow/virtualwirein.js new file mode 100755 index 0000000..38a4e42 --- /dev/null +++ b/RVO16/flow/virtualwirein.js @@ -0,0 +1,43 @@ +exports.id = 'virtualwirein'; +exports.title = 'Virtual wire in'; +exports.version = '1.0.0'; +exports.author = 'Martin Smola'; +exports.color = '#303E4D'; +exports.icon = 'sign-in'; +exports.input = false; +exports.output = 1; +exports.options = {}; +exports.readme = `# Virtual wire in + +When the wires between the components are mess it's time to use Virtual wire.`; + +exports.html = `
+
@(Wire name)
+
+`; + +exports.install = function(instance) { + + instance.custom.reconfigure = function(options){ + if (instance.options.wirename) { + instance.status(instance.options.wirename); + } else + instance.status('Not configured', 'red'); + }; + + ON('virtualwire', function(wirename, flowdata){ + if (instance.options.wirename && instance.options.wirename === wirename) + instance.send(flowdata); + }); + + instance.on('options', instance.custom.reconfigure); + instance.custom.reconfigure(); +}; diff --git a/RVO16/flow/virtualwireout.js b/RVO16/flow/virtualwireout.js new file mode 100755 index 0000000..94a1e4f --- /dev/null +++ b/RVO16/flow/virtualwireout.js @@ -0,0 +1,41 @@ +exports.id = 'virtualwireout'; +exports.title = 'Virtual wire out'; +exports.version = '1.0.0'; +exports.author = 'Martin Smola'; +exports.color = '#303E4D'; +exports.icon = 'sign-out'; +exports.input = true; +exports.options = {}; +exports.readme = `# Virtual wire out + +When the wires between the components are mess it's time to use Virtual wire.`; + +exports.html = `
+
@(Wire name)
+
+`; + +exports.install = function(instance) { + + instance.custom.reconfigure = function(){ + if (instance.options.wirename) { + instance.status(instance.options.wirename); + } else + instance.status('Not configured', 'red'); + }; + + instance.on('data', function(flowdata) { + EMIT('virtualwire', instance.options.wirename, flowdata); + }); + + instance.on('options', instance.custom.reconfigure); + instance.custom.reconfigure(); +}; diff --git a/RVO16/flow/wsmqttpublish.js b/RVO16/flow/wsmqttpublish.js new file mode 100755 index 0000000..0eba804 --- /dev/null +++ b/RVO16/flow/wsmqttpublish.js @@ -0,0 +1,448 @@ +exports.id = 'wsmqttpublish'; +exports.title = 'WS MQTT publish'; +exports.group = 'MQTT'; +exports.color = '#888600'; +exports.version = '1.0.2'; +exports.icon = 'sign-out'; +exports.input = 2; +exports.output = 3; +exports.options = { host: 'tb-stage.worksys.io', port: 1883, clientid: "", username: "" }; + +exports.html = `
+
+
+
Hostname or IP address (if not empty - setting will override db setting)
+
+
+
Port
+
+
+
+
+
@(Client id)
+
+
+
@(Username)
+
+
+
`; + + +exports.readme = ` +# WS MQTT Publish + +Version 1.0.3. + +Added: +- database collections, +- 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 = { + debug: 0, + rpcCall: 1, + services: 2 +} + +//CONFIG +let createTelemetryBackup = true; +let saveTelemetryOnError = true;//backup_on_failure overrides this value +//------------------------ + +let rollers; +if (createTelemetryBackup) rollers = require('streamroller'); + +const noSqlFileSizeLimit = 4194304;//use 5MB - 4194304 +let insertNoSqlCounter = 0; +let insertBackupNoSqlCounter = 0; +let processingData = false; + +let backup_on_failure = false;//== saveTelemetryOnError - create backup client 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; + +process.on('uncaughtException', function(err) { + + errLogger.error('uncaughtException:', err.message) + errLogger.error(err.stack); + + //TODO + //send to service + + //process.exit(1); +}) + +const nosql = NOSQL('tbdata'); +const nosqlBackup = NOSQL('/backup/tbdata'); + + +exports.install = function(instance) { + + var client; + var opts; + var clientReady = false; + + // wsmqtt status for notification purposes on projects.worksys.io database + let wsmqttName = null; + let sendWsStatusVar = null; + let wsmqtt_status = 'disconnected'; + + 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'; + } + + function sendWsStatus() { + instance.send(SEND_TO.services, { [wsmqttName]: wsmqtt_status }); + } + + + function main() { + if (!FLOW.dbLoaded) return; + + loadSettings(); + clearInterval(sendWsStatus); + sendWsStatusVar = setInterval(sendWsStatus, 180000); + } + + //set opts according to db settings + function loadSettings() { + + if (instance.options.host !== "") { + //override settings from database + var o = instance.options; + opts = { + host: o.host, + port: o.port, + clientId: o.clientid, + username: o.username, + rejectUnauthorized: false, + resubscribe: false + }; + + wsmqttName = getWsmqttName(o.host); + + console.log("wsmqttpublich -> loadSettings from instance.options", instance.options); + } + else { + + const SETTINGS = FLOW.GLOBALS.settings; + backup_on_failure = SETTINGS.backup_on_failure; + saveTelemetryOnError = backup_on_failure; + + restore_from_backup = SETTINGS.restore_from_backup; + restore_backup_wait = SETTINGS.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; + + opts = { + host: mqtt_host, + port: mqtt_port, + keepalive: 10, + clientId: mqtt_clientid, + username: mqtt_username, + rejectUnauthorized: false, + resubscribe: false + }; + + wsmqttName = getWsmqttName(mqtt_host); + } + + connectToTbServer(); + } + + function connectToTbServer() { + 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"); + //monitor.info("MQTT client connected"); + + sendClientError = true; + clientReady = true; + wsmqtt_status = 'connected'; + }); + + client.on('reconnect', function() { + instance.status("Reconnecting", "yellow"); + clientReady = false; + }); + + client.on('message', function(topic, message) { + // message is type of buffer + message = message.toString(); + if (message[0] === '{') { + TRY(function() { + + message = JSON.parse(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 } }); + } + + }, () => instance.debug('MQTT: Error parsing data', message)); + } + + instance.send(SEND_TO.rpcCall, { "topic": topic, "content": message }); + }); + + client.on('close', function() { + clientReady = false; + wsmqtt_status = 'disconnected'; + + instance.status("Disconnected", "red"); + instance.send(SEND_TO.debug, { "message": "Client CLOSE signal received !" }); + }); + + client.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; + wsmqtt_status = 'disconnected'; + }); + + } + + + instance.on("0", _ => { + main(); + }) + + + instance.on('1', function(data) { + + if (clientReady) { + //do we have some data in backup file? if any, process data from database + if (saveTelemetryOnError) { + //read telemetry data and send back to server + if (!processingData) processDataFromDatabase(); + } + + let stringifiedJson = JSON.stringify(data.data); + client.publish("v1/gateway/telemetry", stringifiedJson, { qos: 1 }); + + //backup telemetry + if (createTelemetryBackup) { + data.data.id = UID(); + nosqlBackup.insert(data.data); + + insertBackupNoSqlCounter++; + if (insertBackupNoSqlCounter > 150) { + let options = { compress: true }; + let path = __dirname + "/../databases/backup/tbdata.nosql"; + var stream = new rollers.RollingFileStream(path, noSqlFileSizeLimit, 150, options); + stream.write(""); + stream.end(); + + insertBackupNoSqlCounter = 0; + } + } + + } + 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 (saveTelemetryOnError) { + //create new file from tbdata.nosql, if file size exceeds given limit, and clear tbdata.nosql + makeBackupFromDbFile(); + + //write to tb + data.data.id = UID(); + nosql.insert(data.data); + } + } + }); + + + instance.close = function(done) { + if (clientReady) { + client.end(); + clearInterval(sendWsStatusVar); + } + }; + + + function getDbBackupFileCounter(type) { + var files = fs.readdirSync(__dirname + "/../databases"); + + let counter = 0; + for (var i = 0; i < files.length; i++) { + + if (files[i] == "tbdata.nosql") continue; + + if (files[i].endsWith(".nosql")) { + + let pos = files[i].indexOf("."); + if (pos > -1) { + + let fileCounter = counter; + let firstDigit = files[i].slice(0, pos); + + fileCounter = parseInt(firstDigit); + if (isNaN(fileCounter)) fileCounter = 0; + //console.log("getDbBackupFileCounter digit:", files[i], firstDigit, fileCounter, isNaN(fileCounter), type); + + if (type == "max") { + if (fileCounter > counter) { + counter = fileCounter; + } + } + else if (type == "min") { + if (counter == 0) counter = fileCounter; + + if (fileCounter < counter) { + counter = fileCounter; + } + } + } + } + + } + + if (type == "max") counter++; + + return counter; + } + + const makeBackupFromDbFile = async () => { + + if (!saveTelemetryOnError) return; + + //to avoid large file: tbdata.nosql + + //init value is 0! + if (insertNoSqlCounter > 0) { + --insertNoSqlCounter; + return; + } + + insertNoSqlCounter = 100; + + let source = __dirname + "/../databases/tbdata.nosql"; + + var stats = fs.statSync(source); + var fileSizeInBytes = stats.size; + + if (fileSizeInBytes > noSqlFileSizeLimit) { + + let counter = 1; + counter = getDbBackupFileCounter("max"); + + let destination = __dirname + "/../databases/" + counter + "." + "tbdata.nosql"; + + //make backup file + fs.copyFileSync(source, destination); + //fs.renameSync(p, p + "." + counter); + + //clear tbdata.nosql + fs.writeFileSync(source, ""); + fs.truncateSync(source, 0); + + } + } + + const processDataFromDatabase = async () => { + + if (restore_from_backup <= 0) return; + + //calculate diff + const now = new Date(); + let currentTime = now.getTime(); + let diff = currentTime - lastRestoreTime; + + if ((diff / 1000) < restore_backup_wait) { + //console.log("*********restore_backup_wait", diff, restore_backup_wait); + return; + } + + processingData = true; + + //get filename to process + let counter = getDbBackupFileCounter("min"); + + //we have some backup files + let dataBase = 'tbdata'; + + var nosql; + if (counter == 0) dataBase = 'tbdata'; + else dataBase = counter + "." + 'tbdata'; + + nosql = NOSQL(dataBase); + + //select all data - use limit restore_from_backup + let records = await promisifyBuilder(nosql.find().take(restore_from_backup)); + + for (let i = 0; i < records.length; i++) { + if (clientReady) { + + let item = records[i]; + let id = item.id; + + if (id !== undefined) { + //console.log("------------processDataFromDatabase - remove", id, dataBase, i); + + try { + + let message = JSON.parse(JSON.stringify(item)); + delete message.id; + + client.publish("v1/gateway/telemetry", JSON.stringify(message), { qos: 1 }); + + //remove from database + await promisifyBuilder(nosql.remove().where("id", id)); + + } catch (error) { + //process error + console.log("processDataFromDatabase", error); + } + + } + + } + else { + processingData = false; + return; + } + } + + if (records.length > 0) { + //clean backup file + if (counter > 0) nosql.clean(); + } + + //no data in db, remove + if (records.length == 0) { + if (counter > 0) nosql.drop(); + } + + const d = new Date(); + lastRestoreTime = d.getTime(); + + processingData = false; + + } + + instance.on('options', main); + //instance.reconfigure(); +}; diff --git a/RVO16/monitor.txt b/RVO16/monitor.txt new file mode 100755 index 0000000..576d0a8 --- /dev/null +++ b/RVO16/monitor.txt @@ -0,0 +1,7953 @@ +[2025-01-02T09:49:40.344] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-01-02T09:49:45.683] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 true turn off on startup +[2025-01-02T09:49:45.699] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 true turn off on startup +[2025-01-02T09:49:45.706] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 true turn off on startup +[2025-01-02T09:49:45.749] [INFO] monitorLogs - MQTT client error Error: connect ECONNREFUSED 192.168.252.1:1883 + at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1159:16) { + errno: -111, + code: 'ECONNREFUSED', + syscall: 'connect', + address: '192.168.252.1', + port: 1883 +} +[2025-01-02T09:49:50.717] [INFO] monitorLogs - buildTasks - params undefined +[2025-01-02T09:49:50.719] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-01-02T09:49:50.720] [INFO] monitorLogs - profile: { + 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 +} +[2025-01-02T09:49:50.725] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-02T09:49:50.727] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-01-03T07:14:00.726Z +[2025-01-02T09:49:50.728] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-01-02T15:37:00.728Z +[2025-01-02T09:49:50.729] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '8:14', name: 'luxOff' }, + { value: 1, start_time: '16:37', name: 'luxOn' } +] +[2025-01-02T09:49:50.730] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-01-02T09:49:50.731] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-01-02T09:49:50.731] [INFO] monitorLogs - profile: { + 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 +} +[2025-01-02T09:49:50.734] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-02T09:49:50.734] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-01-03T07:14:00.734Z +[2025-01-02T09:49:50.735] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-01-02T15:37:00.735Z +[2025-01-02T09:49:50.736] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '8:14', name: 'luxOff' }, + { value: 1, start_time: '16:37', name: 'luxOn' } +] +[2025-01-02T09:49:50.737] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-01-02T09:49:50.738] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-01-02T09:49:50.738] [INFO] monitorLogs - profile: { + 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 +} +[2025-01-02T09:49:50.740] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-02T09:49:50.741] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-01-03T07:14:00.741Z +[2025-01-02T09:49:50.742] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-01-02T15:37:00.742Z +[2025-01-02T09:49:50.742] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '8:14', name: 'luxOff' }, + { value: 1, start_time: '16:37', name: 'luxOn' } +] +[2025-01-02T09:49:50.743] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-01-02T09:49:50.762] [INFO] monitorLogs - tasks created: 2030 +[2025-01-02T09:49:50.765] [INFO] monitorLogs - -->FLOW bol spustený PLBJzmK1r3Gynd6OW0gKRo0e5wV4vx9bDEqNgYR8 2024-11-04 +[2025-01-02T16:17:43.742] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-01-02T16:17:43.770] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-01-02T16:17:43.777] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-01-03T03:49:46.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-03 03:49:46 +[2025-01-03T07:24:51.322] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-01-03T07:24:51.334] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-01-03T07:24:51.341] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-01-03T10:20:07.943] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-01-03T10:20:13.284] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 true turn off on startup +[2025-01-03T10:20:13.301] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 true turn off on startup +[2025-01-03T10:20:13.308] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 true turn off on startup +[2025-01-03T10:20:13.324] [INFO] monitorLogs - MQTT client error Error: connect ECONNREFUSED 192.168.252.1:1883 + at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1159:16) { + errno: -111, + code: 'ECONNREFUSED', + syscall: 'connect', + address: '192.168.252.1', + port: 1883 +} +[2025-01-03T10:20:18.322] [INFO] monitorLogs - buildTasks - params undefined +[2025-01-03T10:20:18.323] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-01-03T10:20:18.324] [INFO] monitorLogs - profile: { + 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 +} +[2025-01-03T10:20:18.330] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-03T10:20:18.332] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-01-04T07:14:00.331Z +[2025-01-03T10:20:18.333] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-01-03T15:38:00.332Z +[2025-01-03T10:20:18.333] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '8:14', name: 'luxOff' }, + { value: 1, start_time: '16:38', name: 'luxOn' } +] +[2025-01-03T10:20:18.334] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-01-03T10:20:18.335] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-01-03T10:20:18.336] [INFO] monitorLogs - profile: { + 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 +} +[2025-01-03T10:20:18.338] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-03T10:20:18.339] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-01-04T07:14:00.339Z +[2025-01-03T10:20:18.340] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-01-03T15:38:00.340Z +[2025-01-03T10:20:18.340] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '8:14', name: 'luxOff' }, + { value: 1, start_time: '16:38', name: 'luxOn' } +] +[2025-01-03T10:20:18.342] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-01-03T10:20:18.342] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-01-03T10:20:18.343] [INFO] monitorLogs - profile: { + 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 +} +[2025-01-03T10:20:18.345] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-03T10:20:18.346] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-01-04T07:14:00.346Z +[2025-01-03T10:20:18.346] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-01-03T15:38:00.346Z +[2025-01-03T10:20:18.347] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '8:14', name: 'luxOff' }, + { value: 1, start_time: '16:38', name: 'luxOn' } +] +[2025-01-03T10:20:18.348] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-01-03T10:20:18.361] [INFO] monitorLogs - tasks created: 2030 +[2025-01-03T10:20:18.364] [INFO] monitorLogs - -->FLOW bol spustený PLBJzmK1r3Gynd6OW0gKRo0e5wV4vx9bDEqNgYR8 2025-01-02 +[2025-01-03T16:29:50.515] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-01-03T16:29:50.540] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-01-03T16:29:50.547] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-01-04T03:20:15.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-04 03:20:15 +[2025-01-04T07:20:11.122] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-01-04T07:20:11.133] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-01-04T07:20:11.140] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-01-04T16:26:41.750] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-01-04T16:26:41.777] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-01-04T16:26:41.784] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-01-05T03:20:16.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-05 03:20:16 +[2025-01-05T07:33:01.652] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-01-05T07:33:01.664] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-01-05T07:33:01.670] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-01-05T16:16:00.709] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-01-05T16:16:00.730] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-01-05T16:16:00.736] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-01-06T03:20:17.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-06 03:20:17 +[2025-01-06T07:29:12.640] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-01-06T07:29:12.652] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-01-06T07:29:12.660] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-01-06T16:28:47.560] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-01-06T16:28:47.584] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-01-06T16:28:47.590] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-01-07T03:20:18.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-07 03:20:18 +[2025-01-07T07:31:09.630] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-01-07T07:31:09.642] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-01-07T07:31:09.648] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-01-07T16:21:57.879] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-01-07T16:21:57.900] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-01-07T16:21:57.907] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-01-08T03:20:19.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-08 03:20:19 +[2025-01-08T07:26:18.933] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-01-08T07:26:18.945] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-01-08T07:26:18.954] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-01-08T16:31:11.891] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-01-08T16:31:11.916] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-01-08T16:31:11.924] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-01-09T03:20:20.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-09 03:20:20 +[2025-01-09T07:28:09.711] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-01-09T07:28:09.723] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-01-09T07:28:09.730] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-01-09T12:43:19.676] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-01-09T12:43:25.017] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 true turn off on startup +[2025-01-09T12:43:25.033] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 true turn off on startup +[2025-01-09T12:43:25.041] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 true turn off on startup +[2025-01-09T12:43:25.057] [INFO] monitorLogs - MQTT client error Error: connect ECONNREFUSED 192.168.252.1:1883 + at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1159:16) { + errno: -111, + code: 'ECONNREFUSED', + syscall: 'connect', + address: '192.168.252.1', + port: 1883 +} +[2025-01-09T12:43:30.053] [INFO] monitorLogs - buildTasks - params undefined +[2025-01-09T12:43:30.055] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-01-09T12:43:30.056] [INFO] monitorLogs - profile: { + 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 +} +[2025-01-09T12:43:30.061] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-09T12:43:30.063] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-01-10T07:13:00.062Z +[2025-01-09T12:43:30.064] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-01-09T15:45:00.064Z +[2025-01-09T12:43:30.064] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '8:13', name: 'luxOff' }, + { value: 1, start_time: '16:45', name: 'luxOn' } +] +[2025-01-09T12:43:30.066] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-01-09T12:43:30.067] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-01-09T12:43:30.067] [INFO] monitorLogs - profile: { + 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 +} +[2025-01-09T12:43:30.070] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-09T12:43:30.070] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-01-10T07:13:00.070Z +[2025-01-09T12:43:30.071] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-01-09T15:45:00.071Z +[2025-01-09T12:43:30.072] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '8:13', name: 'luxOff' }, + { value: 1, start_time: '16:45', name: 'luxOn' } +] +[2025-01-09T12:43:30.073] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-01-09T12:43:30.074] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-01-09T12:43:30.074] [INFO] monitorLogs - profile: { + 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 +} +[2025-01-09T12:43:30.076] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-09T12:43:30.077] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-01-10T07:13:00.077Z +[2025-01-09T12:43:30.078] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-01-09T15:45:00.078Z +[2025-01-09T12:43:30.078] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '8:13', name: 'luxOff' }, + { value: 1, start_time: '16:45', name: 'luxOn' } +] +[2025-01-09T12:43:30.079] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-01-09T12:43:30.093] [INFO] monitorLogs - tasks created: 2030 +[2025-01-09T12:43:30.096] [INFO] monitorLogs - -->FLOW bol spustený PLBJzmK1r3Gynd6OW0gKRo0e5wV4vx9bDEqNgYR8 2025-01-02 +[2025-01-09T15:32:37.697] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-01-09T15:32:43.031] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 true turn off on startup +[2025-01-09T15:32:43.046] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 true turn off on startup +[2025-01-09T15:32:43.053] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 true turn off on startup +[2025-01-09T15:32:43.068] [INFO] monitorLogs - MQTT client error Error: connect ECONNREFUSED 192.168.252.1:1883 + at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1159:16) { + errno: -111, + code: 'ECONNREFUSED', + syscall: 'connect', + address: '192.168.252.1', + port: 1883 +} +[2025-01-09T15:32:48.066] [INFO] monitorLogs - buildTasks - params undefined +[2025-01-09T15:32:48.067] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-01-09T15:32:48.068] [INFO] monitorLogs - profile: { + 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 +} +[2025-01-09T15:32:48.074] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-09T15:32:48.075] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-01-10T07:13:00.074Z +[2025-01-09T15:32:48.076] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-01-09T15:45:00.076Z +[2025-01-09T15:32:48.077] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '8:13', name: 'luxOff' }, + { value: 1, start_time: '16:45', name: 'luxOn' } +] +[2025-01-09T15:32:48.078] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-01-09T15:32:48.079] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-01-09T15:32:48.080] [INFO] monitorLogs - profile: { + 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 +} +[2025-01-09T15:32:48.083] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-09T15:32:48.084] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-01-10T07:13:00.084Z +[2025-01-09T15:32:48.084] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-01-09T15:45:00.084Z +[2025-01-09T15:32:48.085] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '8:13', name: 'luxOff' }, + { value: 1, start_time: '16:45', name: 'luxOn' } +] +[2025-01-09T15:32:48.086] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-01-09T15:32:48.087] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-01-09T15:32:48.087] [INFO] monitorLogs - profile: { + 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 +} +[2025-01-09T15:32:48.089] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-09T15:32:48.090] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-01-10T07:13:00.090Z +[2025-01-09T15:32:48.091] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-01-09T15:45:00.091Z +[2025-01-09T15:32:48.092] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '8:13', name: 'luxOff' }, + { value: 1, start_time: '16:45', name: 'luxOn' } +] +[2025-01-09T15:32:48.093] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-01-09T15:32:48.106] [INFO] monitorLogs - tasks created: 2030 +[2025-01-09T15:32:48.109] [INFO] monitorLogs - -->FLOW bol spustený PLBJzmK1r3Gynd6OW0gKRo0e5wV4vx9bDEqNgYR8 2025-01-02 +[2025-01-09T16:31:42.046] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-01-09T16:31:42.070] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-01-09T16:31:42.078] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-01-10T03:32:44.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-10 03:32:44 +[2025-01-10T07:30:45.954] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-01-10T07:30:45.964] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-01-10T07:30:45.971] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-01-10T14:13:51.879] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-01-10T14:13:57.209] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 true turn off on startup +[2025-01-10T14:13:57.224] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 true turn off on startup +[2025-01-10T14:13:57.231] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 true turn off on startup +[2025-01-10T14:13:57.262] [INFO] monitorLogs - MQTT client error Error: connect ECONNREFUSED 192.168.252.1:1883 + at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1159:16) { + errno: -111, + code: 'ECONNREFUSED', + syscall: 'connect', + address: '192.168.252.1', + port: 1883 +} +[2025-01-10T14:14:02.244] [INFO] monitorLogs - buildTasks - params undefined +[2025-01-10T14:14:02.246] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-01-10T14:14:02.247] [INFO] monitorLogs - profile: { + 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 +} +[2025-01-10T14:14:02.252] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-10T14:14:02.253] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-01-11T07:12:00.252Z +[2025-01-10T14:14:02.254] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-01-10T15:46:00.254Z +[2025-01-10T14:14:02.255] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '8:12', name: 'luxOff' }, + { value: 1, start_time: '16:46', name: 'luxOn' } +] +[2025-01-10T14:14:02.256] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-01-10T14:14:02.257] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-01-10T14:14:02.257] [INFO] monitorLogs - profile: { + 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 +} +[2025-01-10T14:14:02.260] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-10T14:14:02.260] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-01-11T07:12:00.260Z +[2025-01-10T14:14:02.261] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-01-10T15:46:00.261Z +[2025-01-10T14:14:02.262] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '8:12', name: 'luxOff' }, + { value: 1, start_time: '16:46', name: 'luxOn' } +] +[2025-01-10T14:14:02.263] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-01-10T14:14:02.264] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-01-10T14:14:02.264] [INFO] monitorLogs - profile: { + 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 +} +[2025-01-10T14:14:02.266] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-10T14:14:02.267] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-01-11T07:12:00.267Z +[2025-01-10T14:14:02.268] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-01-10T15:46:00.267Z +[2025-01-10T14:14:02.268] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '8:12', name: 'luxOff' }, + { value: 1, start_time: '16:46', name: 'luxOn' } +] +[2025-01-10T14:14:02.269] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-01-10T14:14:02.282] [INFO] monitorLogs - tasks created: 2030 +[2025-01-10T14:14:02.285] [INFO] monitorLogs - -->FLOW bol spustený PLBJzmK1r3Gynd6OW0gKRo0e5wV4vx9bDEqNgYR8 2025-01-02 +[2025-01-10T14:18:50.293] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-01-10T14:18:55.636] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 true turn off on startup +[2025-01-10T14:18:55.651] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 true turn off on startup +[2025-01-10T14:18:55.658] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 true turn off on startup +[2025-01-10T14:18:55.674] [INFO] monitorLogs - MQTT client error Error: connect ECONNREFUSED 192.168.252.1:1883 + at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1159:16) { + errno: -111, + code: 'ECONNREFUSED', + syscall: 'connect', + address: '192.168.252.1', + port: 1883 +} +[2025-01-10T14:19:00.671] [INFO] monitorLogs - buildTasks - params undefined +[2025-01-10T14:19:00.673] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-01-10T14:19:00.674] [INFO] monitorLogs - profile: { + 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 +} +[2025-01-10T14:19:00.679] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-10T14:19:00.681] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-01-11T07:12:00.680Z +[2025-01-10T14:19:00.682] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-01-10T15:46:00.681Z +[2025-01-10T14:19:00.682] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '8:12', name: 'luxOff' }, + { value: 1, start_time: '16:46', name: 'luxOn' } +] +[2025-01-10T14:19:00.683] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-01-10T14:19:00.684] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-01-10T14:19:00.685] [INFO] monitorLogs - profile: { + 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 +} +[2025-01-10T14:19:00.687] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-10T14:19:00.688] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-01-11T07:12:00.688Z +[2025-01-10T14:19:00.689] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-01-10T15:46:00.689Z +[2025-01-10T14:19:00.689] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '8:12', name: 'luxOff' }, + { value: 1, start_time: '16:46', name: 'luxOn' } +] +[2025-01-10T14:19:00.690] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-01-10T14:19:00.691] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-01-10T14:19:00.692] [INFO] monitorLogs - profile: { + 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 +} +[2025-01-10T14:19:00.694] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-10T14:19:00.694] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-01-11T07:12:00.694Z +[2025-01-10T14:19:00.695] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-01-10T15:46:00.695Z +[2025-01-10T14:19:00.696] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '8:12', name: 'luxOff' }, + { value: 1, start_time: '16:46', name: 'luxOn' } +] +[2025-01-10T14:19:00.697] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-01-10T14:19:00.715] [INFO] monitorLogs - tasks created: 2030 +[2025-01-10T14:19:00.718] [INFO] monitorLogs - -->FLOW bol spustený PLBJzmK1r3Gynd6OW0gKRo0e5wV4vx9bDEqNgYR8 2025-01-02 +[2025-01-10T15:58:15.666] [INFO] monitorLogs - MQTT client connected +[2025-01-10T16:29:47.541] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-01-10T16:29:47.568] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-01-10T16:29:47.576] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-01-11T03:18:57.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-11 03:18:57 +[2025-01-11T07:22:50.322] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-01-11T07:22:50.334] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-01-11T07:22:50.342] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-01-11T16:31:56.369] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-01-11T16:31:56.396] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-01-11T16:31:56.403] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-01-12T03:18:57.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-12 03:18:57 +[2025-01-12T07:31:15.743] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-01-12T07:31:15.754] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-01-12T07:31:15.761] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-01-12T16:29:48.435] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-01-12T16:29:48.461] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-01-12T16:29:48.468] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-01-13T03:18:58.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-13 03:18:58 +[2025-01-13T07:36:54.697] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-01-13T07:36:54.709] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-01-13T07:36:54.716] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-01-13T16:35:21.903] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-01-13T16:35:21.930] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-01-13T16:35:21.937] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-01-14T03:18:59.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-14 03:18:59 +[2025-01-14T07:16:05.078] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-01-14T07:16:05.089] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-01-14T07:16:05.095] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-01-14T16:37:53.848] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-01-14T16:37:53.874] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-01-14T16:37:53.881] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-01-15T03:19:00.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-15 03:19:00 +[2025-01-15T07:23:37.382] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-01-15T07:23:37.394] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-01-15T07:23:37.401] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-01-15T16:37:20.028] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-01-15T16:37:20.054] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-01-15T16:37:20.061] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-01-16T03:19:02.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-16 03:19:02 +[2025-01-16T07:20:56.732] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-01-16T07:20:56.744] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-01-16T07:20:56.750] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-01-16T16:36:01.013] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-01-16T16:36:01.039] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-01-16T16:36:01.045] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-01-17T03:19:02.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-17 03:19:02 +[2025-01-17T07:23:33.087] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-01-17T07:23:33.099] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-01-17T07:23:33.105] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-01-17T16:40:37.327] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-01-17T16:40:37.352] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-01-17T16:40:37.359] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-01-18T03:19:03.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-18 03:19:03 +[2025-01-18T07:22:07.787] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-01-18T07:22:07.799] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-01-18T07:22:07.805] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-01-18T16:44:38.616] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-01-18T16:44:38.643] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-01-18T16:44:38.649] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-01-19T03:19:04.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-19 03:19:04 +[2025-01-19T07:19:58.151] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-01-19T07:19:58.163] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-01-19T07:19:58.170] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-01-19T16:41:59.826] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-01-19T16:41:59.851] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-01-19T16:41:59.858] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-01-20T03:19:05.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-20 03:19:05 +[2025-01-20T07:23:50.045] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-01-20T07:23:50.059] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-01-20T07:23:50.065] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-01-20T16:42:15.130] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-01-20T16:42:15.156] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-01-20T16:42:15.163] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-01-21T03:19:06.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-21 03:19:06 +[2025-01-21T06:22:13.309] [INFO] monitorLogs - MQTT client connected +[2025-01-21T07:27:44.319] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-01-21T07:27:44.330] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-01-21T07:27:44.337] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-01-21T16:42:13.928] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-01-21T16:42:13.955] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-01-21T16:42:13.962] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-01-22T03:19:07.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-22 03:19:07 +[2025-01-22T07:23:31.774] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-01-22T07:23:31.787] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-01-22T07:23:31.793] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-01-22T13:28:32.479] [INFO] monitorLogs - MQTT client connected +[2025-01-22T13:30:34.046] [INFO] monitorLogs - MQTT client connected +[2025-01-22T13:32:01.658] [INFO] monitorLogs - MQTT client connected +[2025-01-22T13:33:45.426] [INFO] monitorLogs - MQTT client connected +[2025-01-22T16:39:56.664] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-01-22T16:39:56.690] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-01-22T16:39:56.696] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-01-23T03:19:08.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-23 03:19:08 +[2025-01-23T07:20:31.446] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-01-23T07:20:31.459] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-01-23T07:20:31.465] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-01-23T16:45:46.632] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-01-23T16:45:46.658] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-01-23T16:45:46.665] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-01-24T03:19:09.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-24 03:19:09 +[2025-01-24T07:07:22.197] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-01-24T07:07:22.211] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-01-24T07:07:22.218] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-01-24T16:56:55.684] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-01-24T16:56:55.710] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-01-24T16:56:55.717] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-01-25T03:19:10.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-25 03:19:10 +[2025-01-25T07:16:47.378] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-01-25T07:16:47.390] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-01-25T07:16:47.396] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-01-25T12:45:07.874] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-01-25T12:45:13.220] [INFO] monitorLogs - buildTasks - params undefined +[2025-01-25T12:45:13.225] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-01-25T12:45:13.227] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-01-25T12:45:13.227] [INFO] monitorLogs - profile: { + 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 +} +[2025-01-25T12:45:13.232] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-25T12:45:13.233] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-01-26T07:00:00.232Z +[2025-01-25T12:45:13.235] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-01-25T16:08:00.234Z +[2025-01-25T12:45:13.235] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '8:0', name: 'luxOff' }, + { value: 1, start_time: '17:8', name: 'luxOn' } +] +[2025-01-25T12:45:13.236] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-01-25T12:45:13.237] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-01-25T12:45:13.238] [INFO] monitorLogs - profile: { + 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 +} +[2025-01-25T12:45:13.240] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-25T12:45:13.241] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-01-26T07:00:00.241Z +[2025-01-25T12:45:13.242] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-01-25T16:08:00.242Z +[2025-01-25T12:45:13.243] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '8:0', name: 'luxOff' }, + { value: 1, start_time: '17:8', name: 'luxOn' } +] +[2025-01-25T12:45:13.244] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-01-25T12:45:13.244] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-01-25T12:45:13.245] [INFO] monitorLogs - profile: { + 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 +} +[2025-01-25T12:45:13.247] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-25T12:45:13.248] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-01-26T07:00:00.248Z +[2025-01-25T12:45:13.249] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-01-25T16:08:00.249Z +[2025-01-25T12:45:13.249] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '8:0', name: 'luxOff' }, + { value: 1, start_time: '17:8', name: 'luxOn' } +] +[2025-01-25T12:45:13.251] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-01-25T12:45:13.260] [INFO] monitorLogs - tasks created: 1904 +[2025-01-25T12:45:13.263] [INFO] monitorLogs - -->FLOW bol spustený PLBJzmK1r3Gynd6OW0gKRo0e5wV4vx9bDEqNgYR8 2025-01-21 +[2025-01-25T12:45:13.369] [INFO] monitorLogs - MQTT client connected +[2025-01-25T12:45:13.578] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-25T12:45:13.884] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-25T12:45:14.190] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-25T16:51:24.984] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-01-25T16:51:24.987] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-01-25T16:51:24.990] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-01-26T03:45:15.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-26 03:45:15 +[2025-01-26T07:13:17.958] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-01-26T07:13:17.961] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-01-26T07:13:17.963] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-01-26T16:55:21.050] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-01-26T16:55:21.053] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-01-26T16:55:21.055] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-01-27T03:45:16.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-27 03:45:16 +[2025-01-27T07:05:42.631] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-01-27T07:05:42.634] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-01-27T07:05:42.636] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-01-27T17:03:03.056] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-01-27T17:03:03.058] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-01-27T17:03:03.060] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-01-28T03:45:21.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-28 03:45:21 +[2025-01-28T07:14:55.495] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-01-28T07:14:55.497] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-01-28T07:14:55.499] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-01-28T16:53:11.921] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-01-28T16:53:11.923] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-01-28T16:53:11.925] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-01-29T03:45:21.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-29 03:45:21 +[2025-01-29T07:04:39.421] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-01-29T07:04:39.423] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-01-29T07:04:39.425] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-01-29T17:06:24.859] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-01-29T17:06:24.861] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-01-29T17:06:24.863] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-01-30T03:45:19.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-30 03:45:19 +[2025-01-30T06:59:42.515] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-01-30T06:59:42.518] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-01-30T06:59:42.520] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-01-30T17:07:43.847] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-01-30T17:07:43.853] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-01-30T17:07:43.855] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-01-31T03:45:20.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-31 03:45:20 +[2025-01-31T07:00:29.432] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-01-31T07:00:29.435] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-01-31T07:00:29.437] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-01-31T10:50:42.610] [INFO] monitorLogs - MQTT client connected +[2025-01-31T17:07:05.523] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-01-31T17:07:05.528] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-01-31T17:07:05.531] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-02-01T03:45:24.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-01 03:45:24 +[2025-02-01T06:58:05.622] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-02-01T06:58:05.624] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-02-01T06:58:05.626] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-02-01T17:05:38.791] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-02-01T17:05:38.793] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-02-01T17:05:38.795] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-02-02T03:45:22.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-02 03:45:22 +[2025-02-02T07:09:05.551] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-02-02T07:09:05.553] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-02-02T07:09:05.555] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-02-02T17:10:15.975] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-02-02T17:10:15.978] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-02-02T17:10:15.979] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-02-03T03:45:23.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-03 03:45:23 +[2025-02-03T06:53:29.946] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-02-03T06:53:29.948] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-02-03T06:53:29.950] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-02-03T07:01:04.812] [INFO] monitorLogs - MQTT client connected +[2025-02-03T07:02:54.184] [INFO] monitorLogs - MQTT client connected +[2025-02-03T07:04:01.185] [INFO] monitorLogs - MQTT client connected +[2025-02-03T07:04:42.483] [INFO] monitorLogs - MQTT client connected +[2025-02-03T07:05:26.182] [INFO] monitorLogs - MQTT client connected +[2025-02-03T17:13:34.211] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-02-03T17:13:34.213] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-02-03T17:13:34.216] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-02-04T03:45:24.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-04 03:45:24 +[2025-02-04T06:53:26.519] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-02-04T06:53:26.522] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-02-04T06:53:26.524] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-02-04T17:16:01.747] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-02-04T17:16:01.749] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-02-04T17:16:01.752] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-02-05T03:45:25.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-05 03:45:25 +[2025-02-05T06:52:26.905] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-02-05T06:52:26.908] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-02-05T06:52:26.910] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-02-05T17:16:39.088] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-02-05T17:16:39.090] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-02-05T17:16:39.092] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-02-06T03:45:26.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-06 03:45:26 +[2025-02-06T06:52:19.434] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-02-06T06:52:19.436] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-02-06T06:52:19.439] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-02-06T17:12:56.967] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-02-06T17:12:56.969] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-02-06T17:12:56.971] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-02-07T03:45:27.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-07 03:45:27 +[2025-02-07T06:53:18.818] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-02-07T06:53:18.820] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-02-07T06:53:18.822] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-02-07T08:41:46.222] [INFO] monitorLogs - MQTT client connected +[2025-02-07T08:43:45.497] [INFO] monitorLogs - MQTT client connected +[2025-02-07T08:44:27.513] [INFO] monitorLogs - MQTT client connected +[2025-02-07T08:44:49.111] [INFO] monitorLogs - MQTT client connected +[2025-02-07T08:46:39.351] [INFO] monitorLogs - MQTT client connected +[2025-02-07T08:49:02.142] [INFO] monitorLogs - MQTT client connected +[2025-02-07T17:10:07.474] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-02-07T17:10:07.476] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-02-07T17:10:07.478] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-02-08T02:40:40.126] [INFO] monitorLogs - MQTT client connected +[2025-02-08T03:45:28.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-08 03:45:28 +[2025-02-08T06:48:54.039] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-02-08T06:48:54.041] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-02-08T06:48:54.043] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-02-08T17:19:59.791] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-02-08T17:19:59.793] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-02-08T17:19:59.795] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-02-09T03:45:29.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-09 03:45:29 +[2025-02-09T06:54:39.633] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-02-09T06:54:39.635] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-02-09T06:54:39.637] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-02-09T13:28:08.128] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-02-09T13:28:13.509] [INFO] monitorLogs - buildTasks - params undefined +[2025-02-09T13:28:13.513] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-02-09T13:28:13.515] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-02-09T13:28:13.515] [INFO] monitorLogs - profile: { + 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 +} +[2025-02-09T13:28:13.520] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-02-09T13:28:13.521] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-02-10T06:40:00.520Z +[2025-02-09T13:28:13.522] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-02-09T16:32:00.522Z +[2025-02-09T13:28:13.523] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:40', name: 'luxOff' }, + { value: 1, start_time: '17:32', name: 'luxOn' } +] +[2025-02-09T13:28:13.524] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-02-09T13:28:13.525] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-02-09T13:28:13.526] [INFO] monitorLogs - profile: { + 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 +} +[2025-02-09T13:28:13.528] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-02-09T13:28:13.529] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-02-10T06:40:00.529Z +[2025-02-09T13:28:13.530] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-02-09T16:32:00.530Z +[2025-02-09T13:28:13.530] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:40', name: 'luxOff' }, + { value: 1, start_time: '17:32', name: 'luxOn' } +] +[2025-02-09T13:28:13.531] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-02-09T13:28:13.532] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-02-09T13:28:13.533] [INFO] monitorLogs - profile: { + 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 +} +[2025-02-09T13:28:13.535] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-02-09T13:28:13.536] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-02-10T06:40:00.535Z +[2025-02-09T13:28:13.536] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-02-09T16:32:00.536Z +[2025-02-09T13:28:13.537] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:40', name: 'luxOff' }, + { value: 1, start_time: '17:32', name: 'luxOn' } +] +[2025-02-09T13:28:13.538] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-02-09T13:28:13.548] [INFO] monitorLogs - tasks created: 1904 +[2025-02-09T13:28:13.550] [INFO] monitorLogs - -->FLOW bol spustený PLBJzmK1r3Gynd6OW0gKRo0e5wV4vx9bDEqNgYR8 2025-01-30 +[2025-02-09T13:28:13.677] [INFO] monitorLogs - MQTT client connected +[2025-02-09T13:28:13.867] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-02-09T13:28:14.172] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-02-09T13:28:14.478] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-02-09T17:10:50.197] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-02-09T17:10:50.200] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-02-09T17:10:50.203] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-02-10T03:28:15.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-10 03:28:15 +[2025-02-10T06:46:02.434] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-02-10T06:46:02.437] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-02-10T06:46:02.440] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-02-10T17:24:26.690] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-02-10T17:24:26.692] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-02-10T17:24:26.694] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-02-11T03:28:16.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-11 03:28:16 +[2025-02-11T06:43:09.871] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-02-11T06:43:09.874] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-02-11T06:43:09.876] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-02-11T17:21:25.854] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-02-11T17:21:25.857] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-02-11T17:21:25.859] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-02-12T03:28:17.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-12 03:28:17 +[2025-02-12T06:51:25.862] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-02-12T06:51:25.865] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-02-12T06:51:25.867] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-02-12T17:14:00.486] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-02-12T17:14:00.488] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-02-12T17:14:00.490] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-02-13T03:28:17.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-13 03:28:17 +[2025-02-13T06:55:17.296] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-02-13T06:55:17.299] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-02-13T06:55:17.301] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-02-13T13:18:10.312] [INFO] monitorLogs - MQTT client connected +[2025-02-13T13:19:08.602] [INFO] monitorLogs - MQTT client connected +[2025-02-13T13:20:53.466] [INFO] monitorLogs - MQTT client connected +[2025-02-13T13:21:27.062] [INFO] monitorLogs - MQTT client connected +[2025-02-13T13:23:21.563] [INFO] monitorLogs - MQTT client connected +[2025-02-13T13:24:29.106] [INFO] monitorLogs - MQTT client connected +[2025-02-13T13:26:01.619] [INFO] monitorLogs - MQTT client connected +[2025-02-13T15:22:54.343] [INFO] monitorLogs - MQTT client connected +[2025-02-13T17:16:05.428] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-02-13T17:16:05.431] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-02-13T17:16:05.433] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-02-14T03:28:18.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-14 03:28:18 +[2025-02-14T06:40:06.721] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-02-14T06:40:06.724] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-02-14T06:40:06.727] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-02-14T17:19:28.288] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-02-14T17:19:28.291] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-02-14T17:19:28.293] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-02-15T03:28:19.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-15 03:28:19 +[2025-02-15T06:44:42.086] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-02-15T06:44:42.090] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-02-15T06:44:42.092] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-02-15T17:26:18.817] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-02-15T17:26:18.819] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-02-15T17:26:18.821] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-02-16T03:28:20.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-16 03:28:20 +[2025-02-16T06:37:15.005] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-02-16T06:37:15.008] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-02-16T06:37:15.010] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-02-16T17:27:23.513] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-02-16T17:27:23.515] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-02-16T17:27:23.517] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-02-17T03:28:21.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-17 03:28:21 +[2025-02-17T06:36:54.550] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-02-17T06:36:54.554] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-02-17T06:36:54.556] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-02-17T07:03:54.119] [INFO] monitorLogs - MQTT client connected +[2025-02-17T07:04:16.364] [INFO] monitorLogs - MQTT client connected +[2025-02-17T08:02:50.228] [INFO] monitorLogs - MQTT client connected +[2025-02-17T08:04:10.887] [INFO] monitorLogs - MQTT client connected +[2025-02-17T08:56:46.155] [INFO] monitorLogs - MQTT client connected +[2025-02-17T17:26:42.936] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-02-17T17:26:42.939] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-02-17T17:26:42.941] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-02-18T03:28:22.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-18 03:28:22 +[2025-02-18T06:40:26.764] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-02-18T06:40:26.767] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-02-18T06:40:26.769] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-02-18T06:54:10.682] [INFO] monitorLogs - MQTT client connected +[2025-02-18T17:38:01.692] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-02-18T17:38:01.694] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-02-18T17:38:01.696] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-02-19T03:28:23.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-19 03:28:23 +[2025-02-19T06:29:19.006] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-02-19T06:29:19.008] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-02-19T06:29:19.010] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-02-19T15:06:42.845] [INFO] monitorLogs - MQTT client connected +[2025-02-19T15:09:58.579] [INFO] monitorLogs - MQTT client connected +[2025-02-19T15:12:55.370] [INFO] monitorLogs - MQTT client connected +[2025-02-19T17:36:54.182] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-02-19T17:36:54.184] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-02-19T17:36:54.186] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-02-20T03:28:24.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-20 03:28:24 +[2025-02-20T06:29:32.802] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-02-20T06:29:32.805] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-02-20T06:29:32.807] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-02-20T09:20:06.979] [INFO] monitorLogs - MQTT client connected +[2025-02-20T17:40:04.430] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-02-20T17:40:04.432] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-02-20T17:40:04.434] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-02-21T03:28:25.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-21 03:28:25 +[2025-02-21T06:25:58.764] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-02-21T06:25:58.766] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-02-21T06:25:58.768] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-02-21T17:40:32.048] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-02-21T17:40:32.052] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-02-21T17:40:32.053] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-02-22T03:28:26.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-22 03:28:26 +[2025-02-22T06:24:37.194] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-02-22T06:24:37.196] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-02-22T06:24:37.198] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-02-22T17:42:24.229] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-02-22T17:42:24.231] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-02-22T17:42:24.233] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-02-23T03:28:27.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-23 03:28:27 +[2025-02-23T06:22:53.722] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-02-23T06:22:53.725] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-02-23T06:22:53.727] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-02-23T17:31:20.116] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-02-23T17:31:20.119] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-02-23T17:31:20.121] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-02-24T03:28:28.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-24 03:28:28 +[2025-02-24T06:24:43.435] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-02-24T06:24:43.438] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-02-24T06:24:43.439] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-02-24T09:09:43.037] [INFO] monitorLogs - MQTT client connected +[2025-02-24T14:01:09.593] [INFO] monitorLogs - MQTT client connected +[2025-02-24T14:02:07.127] [INFO] monitorLogs - MQTT client connected +[2025-02-24T17:44:35.141] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-02-24T17:44:35.144] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-02-24T17:44:35.146] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-02-25T03:28:29.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-25 03:28:29 +[2025-02-25T06:25:03.623] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-02-25T06:25:03.625] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-02-25T06:25:03.627] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-02-25T06:51:14.538] [INFO] monitorLogs - MQTT client connected +[2025-02-25T06:52:29.080] [INFO] monitorLogs - MQTT client connected +[2025-02-25T06:55:26.687] [INFO] monitorLogs - MQTT client connected +[2025-02-25T06:57:16.396] [INFO] monitorLogs - MQTT client connected +[2025-02-25T06:57:45.010] [INFO] monitorLogs - MQTT client connected +[2025-02-25T06:58:12.446] [INFO] monitorLogs - MQTT client connected +[2025-02-25T07:10:57.227] [INFO] monitorLogs - MQTT client connected +[2025-02-25T07:11:29.540] [INFO] monitorLogs - MQTT client connected +[2025-02-25T07:12:32.955] [INFO] monitorLogs - MQTT client connected +[2025-02-25T07:14:26.513] [INFO] monitorLogs - MQTT client connected +[2025-02-25T07:14:56.234] [INFO] monitorLogs - MQTT client connected +[2025-02-25T07:16:54.393] [INFO] monitorLogs - MQTT client connected +[2025-02-25T12:37:28.692] [INFO] monitorLogs - MQTT client connected +[2025-02-25T12:37:50.041] [INFO] monitorLogs - MQTT client connected +[2025-02-25T12:39:00.851] [INFO] monitorLogs - MQTT client connected +[2025-02-25T14:05:34.234] [INFO] monitorLogs - MQTT client connected +[2025-02-25T14:07:41.904] [INFO] monitorLogs - MQTT client connected +[2025-02-25T14:08:17.909] [INFO] monitorLogs - MQTT client connected +[2025-02-25T14:08:54.277] [INFO] monitorLogs - MQTT client connected +[2025-02-25T14:09:34.675] [INFO] monitorLogs - MQTT client connected +[2025-02-25T14:10:30.558] [INFO] monitorLogs - MQTT client connected +[2025-02-25T14:11:39.827] [INFO] monitorLogs - MQTT client connected +[2025-02-25T14:12:02.785] [INFO] monitorLogs - MQTT client connected +[2025-02-25T14:12:55.309] [INFO] monitorLogs - MQTT client connected +[2025-02-25T14:14:08.593] [INFO] monitorLogs - MQTT client connected +[2025-02-25T14:15:05.584] [INFO] monitorLogs - MQTT client connected +[2025-02-25T14:15:51.325] [INFO] monitorLogs - MQTT client connected +[2025-02-25T14:20:51.100] [INFO] monitorLogs - MQTT client connected +[2025-02-25T17:41:56.690] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-02-25T17:41:56.692] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-02-25T17:41:56.694] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-02-26T03:28:30.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-26 03:28:30 +[2025-02-26T06:35:33.866] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-02-26T06:35:33.869] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-02-26T06:35:33.871] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-02-26T17:40:00.289] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-02-26T17:40:00.296] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-02-26T17:40:00.298] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-02-26T18:43:05.176] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-02-26T18:43:10.512] [INFO] monitorLogs - buildTasks - params undefined +[2025-02-26T18:43:10.517] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-02-26T18:43:10.518] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-02-26T18:43:10.519] [INFO] monitorLogs - profile: { + 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 +} +[2025-02-26T18:43:10.523] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-02-26T18:43:10.525] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-02-27T06:10:00.524Z +[2025-02-26T18:43:10.526] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-02-27T17:00:00.526Z +[2025-02-26T18:43:10.527] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:10', name: 'luxOff' }, + { value: 1, start_time: '18:0', name: 'luxOn' } +] +[2025-02-26T18:43:10.528] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-02-26T18:43:10.529] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-02-26T18:43:10.530] [INFO] monitorLogs - profile: { + 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 +} +[2025-02-26T18:43:10.532] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-02-26T18:43:10.533] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-02-27T06:10:00.533Z +[2025-02-26T18:43:10.534] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-02-27T17:00:00.534Z +[2025-02-26T18:43:10.534] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:10', name: 'luxOff' }, + { value: 1, start_time: '18:0', name: 'luxOn' } +] +[2025-02-26T18:43:10.535] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-02-26T18:43:10.536] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-02-26T18:43:10.537] [INFO] monitorLogs - profile: { + 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 +} +[2025-02-26T18:43:10.539] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-02-26T18:43:10.539] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-02-27T06:10:00.539Z +[2025-02-26T18:43:10.540] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-02-27T17:00:00.540Z +[2025-02-26T18:43:10.541] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:10', name: 'luxOff' }, + { value: 1, start_time: '18:0', name: 'luxOn' } +] +[2025-02-26T18:43:10.542] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-02-26T18:43:10.552] [INFO] monitorLogs - tasks created: 1904 +[2025-02-26T18:43:10.555] [INFO] monitorLogs - -->FLOW bol spustený PLBJzmK1r3Gynd6OW0gKRo0e5wV4vx9bDEqNgYR8 2025-01-30 +[2025-02-26T18:43:10.669] [INFO] monitorLogs - MQTT client connected +[2025-02-26T18:43:10.872] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-02-26T18:43:11.178] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-02-26T18:43:11.498] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-02-27T03:43:12.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-27 03:43:12 +[2025-02-27T06:26:15.391] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-02-27T06:26:15.396] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-02-27T06:26:15.398] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-02-27T17:41:26.438] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-02-27T17:41:26.446] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-02-27T17:41:26.449] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-02-28T03:43:13.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-28 03:43:13 +[2025-02-28T06:15:30.073] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-02-28T06:15:30.077] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-02-28T06:15:30.080] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-02-28T12:20:03.232] [INFO] monitorLogs - MQTT client connected +[2025-02-28T12:26:51.668] [INFO] monitorLogs - MQTT client connected +[2025-02-28T17:50:58.647] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-02-28T17:50:58.649] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-02-28T17:50:58.652] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-03-01T03:43:14.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-01 03:43:14 +[2025-03-01T06:14:46.087] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-03-01T06:14:46.090] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-03-01T06:14:46.092] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-03-01T17:52:21.750] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-03-01T17:52:21.752] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-03-01T17:52:21.754] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-03-02T03:43:15.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-02 03:43:15 +[2025-03-02T06:13:10.845] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-03-02T06:13:10.848] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-03-02T06:13:10.850] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-03-02T17:57:02.546] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-03-02T17:57:02.549] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-03-02T17:57:02.551] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-03-03T03:43:16.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-03 03:43:16 +[2025-03-03T06:08:55.866] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-03-03T06:08:55.869] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-03-03T06:08:55.871] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-03-03T17:56:12.631] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-03-03T17:56:12.639] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-03-03T17:56:12.641] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-03-04T03:43:17.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-04 03:43:17 +[2025-03-04T06:06:09.411] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-03-04T06:06:09.414] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-03-04T06:06:09.416] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-03-04T07:04:55.030] [INFO] monitorLogs - MQTT client connected +[2025-03-04T07:07:50.013] [INFO] monitorLogs - MQTT client connected +[2025-03-04T07:09:53.828] [INFO] monitorLogs - MQTT client connected +[2025-03-04T07:10:40.306] [INFO] monitorLogs - MQTT client connected +[2025-03-04T07:12:20.706] [INFO] monitorLogs - MQTT client connected +[2025-03-04T07:13:50.813] [INFO] monitorLogs - MQTT client connected +[2025-03-04T07:16:18.189] [INFO] monitorLogs - MQTT client connected +[2025-03-04T07:22:11.021] [INFO] monitorLogs - MQTT client connected +[2025-03-04T17:58:35.601] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-03-04T17:58:35.603] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-03-04T17:58:35.605] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-03-05T03:43:18.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-05 03:43:18 +[2025-03-05T06:05:23.350] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-03-05T06:05:23.353] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-03-05T06:05:23.355] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-03-05T17:58:36.860] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-03-05T17:58:36.868] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-03-05T17:58:36.871] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-03-06T03:43:19.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-06 03:43:19 +[2025-03-06T06:02:31.171] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-03-06T06:02:31.174] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-03-06T06:02:31.176] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-03-06T18:00:48.544] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-03-06T18:00:48.552] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-03-06T18:00:48.554] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-03-07T03:43:20.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-07 03:43:20 +[2025-03-07T06:01:50.493] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-03-07T06:01:50.495] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-03-07T06:01:50.497] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-03-07T18:03:44.779] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-03-07T18:03:44.787] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-03-07T18:03:44.789] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-03-08T03:43:21.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-08 03:43:21 +[2025-03-08T05:59:20.905] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-03-08T05:59:20.907] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-03-08T05:59:20.909] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-03-08T18:02:42.022] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-03-08T18:02:42.030] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-03-08T18:02:42.032] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-03-09T03:43:23.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-09 03:43:23 +[2025-03-09T06:01:30.927] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-03-09T06:01:30.929] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-03-09T06:01:30.931] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-03-09T18:04:09.731] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-03-09T18:04:09.740] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-03-09T18:04:09.742] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-03-10T03:43:24.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-10 03:43:24 +[2025-03-10T05:59:32.431] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-03-10T05:59:32.433] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-03-10T05:59:32.435] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-03-10T06:43:00.141] [INFO] monitorLogs - MQTT client connected +[2025-03-10T06:43:22.388] [INFO] monitorLogs - MQTT client connected +[2025-03-10T17:48:05.298] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-03-10T17:48:05.305] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-03-10T17:48:05.307] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-03-11T03:43:25.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-11 03:43:25 +[2025-03-11T05:54:32.495] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-03-11T05:54:32.498] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-03-11T05:54:32.500] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-03-11T08:22:20.605] [INFO] monitorLogs - MQTT client connected +[2025-03-11T08:23:27.392] [INFO] monitorLogs - MQTT client connected +[2025-03-11T08:24:03.794] [INFO] monitorLogs - MQTT client connected +[2025-03-11T08:25:00.081] [INFO] monitorLogs - MQTT client connected +[2025-03-11T17:59:43.780] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-03-11T17:59:43.783] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-03-11T17:59:43.785] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-03-12T03:43:26.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-12 03:43:26 +[2025-03-12T05:55:00.505] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-03-12T05:55:00.507] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-03-12T05:55:00.509] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-03-12T16:14:59.965] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-03-12T16:15:05.329] [INFO] monitorLogs - buildTasks - params undefined +[2025-03-12T16:15:05.334] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-03-12T16:15:05.335] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-03-12T16:15:05.336] [INFO] monitorLogs - profile: { + 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 +} +[2025-03-12T16:15:05.340] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-03-12T16:15:05.342] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-03-13T05:41:00.341Z +[2025-03-12T16:15:05.343] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-03-12T17:22:00.343Z +[2025-03-12T16:15:05.344] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '6:41', name: 'luxOff' }, + { value: 1, start_time: '18:22', name: 'luxOn' } +] +[2025-03-12T16:15:05.345] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-03-12T16:15:05.346] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-03-12T16:15:05.346] [INFO] monitorLogs - profile: { + 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 +} +[2025-03-12T16:15:05.349] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-03-12T16:15:05.349] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-03-13T05:41:00.349Z +[2025-03-12T16:15:05.350] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-03-12T17:22:00.350Z +[2025-03-12T16:15:05.351] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '6:41', name: 'luxOff' }, + { value: 1, start_time: '18:22', name: 'luxOn' } +] +[2025-03-12T16:15:05.352] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-03-12T16:15:05.353] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-03-12T16:15:05.354] [INFO] monitorLogs - profile: { + 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 +} +[2025-03-12T16:15:05.356] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-03-12T16:15:05.356] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-03-13T05:41:00.356Z +[2025-03-12T16:15:05.357] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-03-12T17:22:00.357Z +[2025-03-12T16:15:05.358] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '6:41', name: 'luxOff' }, + { value: 1, start_time: '18:22', name: 'luxOn' } +] +[2025-03-12T16:15:05.359] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-03-12T16:15:05.369] [INFO] monitorLogs - tasks created: 1904 +[2025-03-12T16:15:05.371] [INFO] monitorLogs - -->FLOW bol spustený PLBJzmK1r3Gynd6OW0gKRo0e5wV4vx9bDEqNgYR8 2025-01-30 +[2025-03-12T16:15:05.448] [INFO] monitorLogs - MQTT client connected +[2025-03-12T16:15:05.687] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-03-12T16:15:05.993] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-03-12T16:15:06.298] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-03-12T18:08:27.978] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-03-12T18:08:27.981] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-03-12T18:08:27.984] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-03-13T03:15:06.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-13 03:15:06 +[2025-03-13T06:07:18.438] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-03-13T06:07:18.440] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-03-13T06:07:18.442] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-03-13T08:15:40.662] [INFO] monitorLogs - MQTT client connected +[2025-03-13T09:44:38.128] [INFO] monitorLogs - MQTT client connected +[2025-03-13T09:45:33.229] [INFO] monitorLogs - MQTT client connected +[2025-03-13T09:47:04.827] [INFO] monitorLogs - MQTT client connected +[2025-03-13T09:48:55.580] [INFO] monitorLogs - MQTT client connected +[2025-03-13T09:49:51.665] [INFO] monitorLogs - MQTT client connected +[2025-03-13T09:50:23.005] [INFO] monitorLogs - MQTT client connected +[2025-03-13T10:13:29.418] [INFO] monitorLogs - MQTT client connected +[2025-03-13T18:08:52.924] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-03-13T18:08:52.928] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-03-13T18:08:52.931] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-03-14T03:15:08.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-14 03:15:08 +[2025-03-14T06:00:36.361] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-03-14T06:00:36.365] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-03-14T06:00:36.367] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-03-14T18:04:38.077] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-03-14T18:04:38.080] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-03-14T18:04:38.082] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-03-15T03:15:09.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-15 03:15:09 +[2025-03-15T05:59:54.872] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-03-15T05:59:54.880] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-03-15T05:59:54.882] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-03-15T18:11:54.667] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-03-15T18:11:54.674] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-03-15T18:11:54.676] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-03-16T03:15:10.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-16 03:15:10 +[2025-03-16T05:50:15.059] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-03-16T05:50:15.061] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-03-16T05:50:15.063] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-03-16T18:16:10.540] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-03-16T18:16:10.543] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-03-16T18:16:10.545] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-03-17T03:15:11.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-17 03:15:11 +[2025-03-17T05:51:20.900] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-03-17T05:51:20.902] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-03-17T05:51:20.904] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-03-17T06:45:36.589] [INFO] monitorLogs - MQTT client connected +[2025-03-17T07:05:05.147] [INFO] monitorLogs - MQTT client connected +[2025-03-17T07:22:23.404] [INFO] monitorLogs - MQTT client connected +[2025-03-17T08:12:52.847] [INFO] monitorLogs - MQTT client connected +[2025-03-17T18:14:27.405] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-03-17T18:14:27.407] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-03-17T18:14:27.409] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-03-18T03:15:12.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-18 03:15:12 +[2025-03-18T05:38:29.204] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-03-18T05:38:29.206] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-03-18T05:38:29.208] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-03-18T18:19:58.971] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-03-18T18:19:58.975] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-03-18T18:19:58.976] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-03-19T03:15:13.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-19 03:15:13 +[2025-03-19T05:36:53.886] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-03-19T05:36:53.890] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-03-19T05:36:53.892] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-03-19T14:06:26.068] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-03-19T14:06:31.429] [INFO] monitorLogs - buildTasks - params undefined +[2025-03-19T14:06:31.434] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-03-19T14:06:31.436] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-03-19T14:06:31.436] [INFO] monitorLogs - profile: { + 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 +} +[2025-03-19T14:06:31.441] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-03-19T14:06:31.442] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-03-20T05:27:00.441Z +[2025-03-19T14:06:31.444] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-03-19T17:32:00.443Z +[2025-03-19T14:06:31.444] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '6:27', name: 'luxOff' }, + { value: 1, start_time: '18:32', name: 'luxOn' } +] +[2025-03-19T14:06:31.446] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-03-19T14:06:31.446] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-03-19T14:06:31.447] [INFO] monitorLogs - profile: { + 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 +} +[2025-03-19T14:06:31.449] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-03-19T14:06:31.450] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-03-20T05:27:00.450Z +[2025-03-19T14:06:31.451] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-03-19T17:32:00.451Z +[2025-03-19T14:06:31.452] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '6:27', name: 'luxOff' }, + { value: 1, start_time: '18:32', name: 'luxOn' } +] +[2025-03-19T14:06:31.453] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-03-19T14:06:31.454] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-03-19T14:06:31.454] [INFO] monitorLogs - profile: { + 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 +} +[2025-03-19T14:06:31.456] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-03-19T14:06:31.457] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-03-20T05:27:00.457Z +[2025-03-19T14:06:31.458] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-03-19T17:32:00.458Z +[2025-03-19T14:06:31.458] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '6:27', name: 'luxOff' }, + { value: 1, start_time: '18:32', name: 'luxOn' } +] +[2025-03-19T14:06:31.459] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-03-19T14:06:31.469] [INFO] monitorLogs - tasks created: 1904 +[2025-03-19T14:06:31.472] [INFO] monitorLogs - -->FLOW bol spustený PLBJzmK1r3Gynd6OW0gKRo0e5wV4vx9bDEqNgYR8 2025-01-30 +[2025-03-19T14:06:31.789] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-03-19T14:06:31.835] [INFO] monitorLogs - MQTT client connected +[2025-03-19T14:06:32.094] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-03-19T14:06:32.400] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-03-19T14:09:24.053] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-03-19T14:09:29.424] [INFO] monitorLogs - buildTasks - params undefined +[2025-03-19T14:09:29.428] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-03-19T14:09:29.430] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-03-19T14:09:29.430] [INFO] monitorLogs - profile: { + 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 +} +[2025-03-19T14:09:29.435] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-03-19T14:09:29.436] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-03-20T05:27:00.435Z +[2025-03-19T14:09:29.438] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-03-19T17:32:00.437Z +[2025-03-19T14:09:29.438] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '6:27', name: 'luxOff' }, + { value: 1, start_time: '18:32', name: 'luxOn' } +] +[2025-03-19T14:09:29.439] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-03-19T14:09:29.440] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-03-19T14:09:29.441] [INFO] monitorLogs - profile: { + 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 +} +[2025-03-19T14:09:29.443] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-03-19T14:09:29.444] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-03-20T05:27:00.444Z +[2025-03-19T14:09:29.445] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-03-19T17:32:00.445Z +[2025-03-19T14:09:29.446] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '6:27', name: 'luxOff' }, + { value: 1, start_time: '18:32', name: 'luxOn' } +] +[2025-03-19T14:09:29.447] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-03-19T14:09:29.447] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-03-19T14:09:29.448] [INFO] monitorLogs - profile: { + 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 +} +[2025-03-19T14:09:29.450] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-03-19T14:09:29.451] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-03-20T05:27:00.451Z +[2025-03-19T14:09:29.452] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-03-19T17:32:00.452Z +[2025-03-19T14:09:29.452] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '6:27', name: 'luxOff' }, + { value: 1, start_time: '18:32', name: 'luxOn' } +] +[2025-03-19T14:09:29.453] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-03-19T14:09:29.463] [INFO] monitorLogs - tasks created: 1904 +[2025-03-19T14:09:29.466] [INFO] monitorLogs - -->FLOW bol spustený PLBJzmK1r3Gynd6OW0gKRo0e5wV4vx9bDEqNgYR8 2025-01-30 +[2025-03-19T14:09:29.686] [INFO] monitorLogs - MQTT client connected +[2025-03-19T14:09:29.780] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-03-19T14:09:30.086] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-03-19T14:09:30.392] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-03-19T14:11:27.992] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false command received from platform +[2025-03-19T14:12:16.314] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false command received from platform +[2025-03-19T14:12:23.705] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false command received from platform +[2025-03-19T14:19:39.059] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false command received from platform +[2025-03-19T14:19:45.533] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false command received from platform +[2025-03-19T14:19:51.021] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false command received from platform +[2025-03-19T18:22:37.609] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-03-19T18:22:37.612] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-03-19T18:22:37.614] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-03-20T03:09:31.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-20 03:09:31 +[2025-03-20T05:34:25.797] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-03-20T05:34:25.800] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-03-20T05:34:25.802] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-03-20T18:21:58.894] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-03-20T18:21:58.902] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-03-20T18:21:58.904] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-03-21T03:09:32.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-21 03:09:32 +[2025-03-21T05:32:41.111] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-03-21T05:32:41.114] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-03-21T05:32:41.119] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-03-21T18:21:45.033] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-03-21T18:21:45.040] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-03-21T18:21:45.043] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-03-22T03:09:33.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-22 03:09:33 +[2025-03-22T05:31:07.163] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-03-22T05:31:07.165] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-03-22T05:31:07.167] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-03-22T18:17:03.174] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-03-22T18:17:03.176] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-03-22T18:17:03.178] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-03-23T03:09:34.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-23 03:09:34 +[2025-03-23T05:34:21.431] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-03-23T05:34:21.433] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-03-23T05:34:21.435] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-03-23T18:25:11.667] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-03-23T18:25:11.670] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-03-23T18:25:11.672] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-03-24T03:09:35.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-24 03:09:35 +[2025-03-24T05:33:18.450] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-03-24T05:33:18.452] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-03-24T05:33:18.454] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-03-24T08:09:06.036] [INFO] monitorLogs - MQTT client connected +[2025-03-24T10:16:39.719] [INFO] monitorLogs - MQTT client connected +[2025-03-24T10:17:10.884] [INFO] monitorLogs - MQTT client connected +[2025-03-24T10:48:28.299] [INFO] monitorLogs - MQTT client connected +[2025-03-24T12:01:37.244] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-03-24T12:01:42.591] [INFO] monitorLogs - buildTasks - params undefined +[2025-03-24T12:01:42.596] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-03-24T12:01:42.597] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-03-24T12:01:42.598] [INFO] monitorLogs - profile: { + 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 +} +[2025-03-24T12:01:42.602] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-03-24T12:01:42.604] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-03-25T05:16:00.603Z +[2025-03-24T12:01:42.605] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-03-24T17:40:00.605Z +[2025-03-24T12:01:42.606] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '6:16', name: 'luxOff' }, + { value: 1, start_time: '18:40', name: 'luxOn' } +] +[2025-03-24T12:01:42.607] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-03-24T12:01:42.608] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-03-24T12:01:42.609] [INFO] monitorLogs - profile: { + 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 +} +[2025-03-24T12:01:42.611] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-03-24T12:01:42.612] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-03-25T05:16:00.612Z +[2025-03-24T12:01:42.613] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-03-24T17:40:00.613Z +[2025-03-24T12:01:42.614] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '6:16', name: 'luxOff' }, + { value: 1, start_time: '18:40', name: 'luxOn' } +] +[2025-03-24T12:01:42.615] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-03-24T12:01:42.616] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-03-24T12:01:42.616] [INFO] monitorLogs - profile: { + 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 +} +[2025-03-24T12:01:42.618] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-03-24T12:01:42.619] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-03-25T05:16:00.619Z +[2025-03-24T12:01:42.620] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-03-24T17:40:00.620Z +[2025-03-24T12:01:42.620] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '6:16', name: 'luxOff' }, + { value: 1, start_time: '18:40', name: 'luxOn' } +] +[2025-03-24T12:01:42.621] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-03-24T12:01:42.631] [INFO] monitorLogs - tasks created: 1904 +[2025-03-24T12:01:42.634] [INFO] monitorLogs - -->FLOW bol spustený PLBJzmK1r3Gynd6OW0gKRo0e5wV4vx9bDEqNgYR8 2025-01-30 +[2025-03-24T12:01:42.710] [INFO] monitorLogs - MQTT client connected +[2025-03-24T12:01:42.949] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-03-24T12:01:43.255] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-03-24T12:01:43.560] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-03-24T18:26:44.089] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-03-24T18:26:44.097] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-03-24T18:26:44.100] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-03-25T03:01:44.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-25 03:01:44 +[2025-03-25T05:28:21.205] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-03-25T05:28:21.208] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-03-25T05:28:21.210] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-03-25T18:28:17.918] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-03-25T18:28:17.926] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-03-25T18:28:17.928] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-03-26T03:01:45.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-26 03:01:45 +[2025-03-26T05:23:19.717] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-03-26T05:23:19.720] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-03-26T05:23:19.723] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-03-26T18:27:47.309] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-03-26T18:27:47.317] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-03-26T18:27:47.319] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-03-27T03:01:46.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-27 03:01:46 +[2025-03-27T05:22:05.745] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-03-27T05:22:05.748] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-03-27T05:22:05.751] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-03-27T18:33:14.159] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-03-27T18:33:14.168] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-03-27T18:33:14.170] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-03-28T03:01:47.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-28 03:01:47 +[2025-03-28T05:19:34.823] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-03-28T05:19:34.826] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-03-28T05:19:34.828] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-03-28T07:34:53.063] [INFO] monitorLogs - MQTT client connected +[2025-03-28T07:38:11.495] [INFO] monitorLogs - MQTT client connected +[2025-03-28T09:16:08.976] [INFO] monitorLogs - MQTT client connected +[2025-03-28T18:23:46.730] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-03-28T18:23:46.738] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-03-28T18:23:46.741] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-03-29T03:01:48.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-29 03:01:48 +[2025-03-29T05:26:32.506] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-03-29T05:26:32.509] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-03-29T05:26:32.511] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-03-29T18:19:05.517] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-03-29T18:19:05.525] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-03-29T18:19:05.528] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-03-30T03:01:50.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-30 03:01:50 +[2025-03-30T06:23:58.749] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-03-30T06:23:58.752] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-03-30T06:23:58.755] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-03-30T19:24:11.054] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-03-30T19:24:11.063] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-03-30T19:24:11.065] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-03-31T03:01:50.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-31 03:01:50 +[2025-03-31T06:12:28.635] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-03-31T06:12:28.638] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-03-31T06:12:28.641] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-03-31T06:50:17.686] [INFO] monitorLogs - MQTT client connected +[2025-03-31T06:57:37.435] [INFO] monitorLogs - MQTT client connected +[2025-03-31T19:37:32.769] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-03-31T19:37:32.778] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-03-31T19:37:32.780] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-04-01T03:01:52.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-01 03:01:52 +[2025-04-01T06:14:19.203] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-04-01T06:14:19.206] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-04-01T06:14:19.208] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-04-01T07:40:45.867] [INFO] monitorLogs - MQTT client connected +[2025-04-01T07:56:54.445] [INFO] monitorLogs - MQTT client connected +[2025-04-01T19:37:06.382] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-04-01T19:37:06.389] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-04-01T19:37:06.392] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-04-02T02:17:52.578] [INFO] monitorLogs - MQTT client connected +[2025-04-02T03:01:53.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-02 03:01:53 +[2025-04-02T03:23:53.869] [INFO] monitorLogs - MQTT client connected +[2025-04-02T06:09:15.113] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-04-02T06:09:15.116] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-04-02T06:09:15.119] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-04-02T19:38:06.308] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-04-02T19:38:06.316] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-04-02T19:38:06.318] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-04-03T03:01:54.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-03 03:01:54 +[2025-04-03T06:04:25.156] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-04-03T06:04:25.160] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-04-03T06:04:25.162] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-04-03T19:43:04.644] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-04-03T19:43:04.653] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-04-03T19:43:04.655] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-04-04T03:01:55.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-04 03:01:55 +[2025-04-04T06:04:09.575] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-04-04T06:04:09.578] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-04-04T06:04:09.581] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-04-04T19:44:38.005] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-04-04T19:44:38.014] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-04-04T19:44:38.017] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-04-05T03:01:56.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-05 03:01:56 +[2025-04-05T06:02:27.264] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-04-05T06:02:27.267] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-04-05T06:02:27.269] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-04-05T19:44:35.902] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-04-05T19:44:35.911] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-04-05T19:44:35.913] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-04-06T03:01:57.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-06 03:01:57 +[2025-04-06T05:59:19.044] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-04-06T05:59:19.047] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-04-06T05:59:19.049] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-04-06T19:45:37.860] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-04-06T19:45:37.867] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-04-06T19:45:37.870] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-04-07T03:01:58.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-07 03:01:58 +[2025-04-07T06:06:10.727] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-04-07T06:06:10.730] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-04-07T06:06:10.732] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-04-07T12:04:53.964] [INFO] monitorLogs - MQTT client connected +[2025-04-07T19:36:27.600] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-04-07T19:36:27.607] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-04-07T19:36:27.610] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-04-08T03:01:59.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-08 03:01:59 +[2025-04-08T06:07:14.726] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-04-08T06:07:14.729] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-04-08T06:07:14.731] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-04-08T19:49:32.038] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-04-08T19:49:32.047] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-04-08T19:49:32.049] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-04-09T03:02:00.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-09 03:02:00 +[2025-04-09T05:53:45.395] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-04-09T05:53:45.398] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-04-09T05:53:45.400] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-04-09T19:51:10.876] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-04-09T19:51:10.884] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-04-09T19:51:10.886] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-04-10T03:02:01.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-10 03:02:01 +[2025-04-10T06:01:00.171] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-04-10T06:01:00.175] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-04-10T06:01:00.177] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-04-10T10:37:48.534] [INFO] monitorLogs - MQTT client connected +[2025-04-10T19:50:45.405] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-04-10T19:50:45.414] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-04-10T19:50:45.416] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-04-11T00:29:21.749] [INFO] monitorLogs - MQTT client connected +[2025-04-11T03:02:02.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-11 03:02:02 +[2025-04-11T05:50:13.394] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-04-11T05:50:13.397] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-04-11T05:50:13.399] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-04-11T19:48:45.124] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-04-11T19:48:45.132] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-04-11T19:48:45.135] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-04-12T05:48:54.627] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-04-12T05:48:54.631] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-04-12T05:48:54.633] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-04-12T19:55:19.126] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-04-12T19:55:19.133] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-04-12T19:55:19.135] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-04-13T03:02:05.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-13 03:02:05 +[2025-04-13T05:43:54.665] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-04-13T05:43:54.668] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-04-13T05:43:54.669] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-04-13T19:49:35.967] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-04-13T19:49:35.974] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-04-13T19:49:35.977] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-04-14T03:02:06.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-14 03:02:06 +[2025-04-14T05:44:17.588] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-04-14T05:44:17.591] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-04-14T05:44:17.593] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-04-14T16:19:27.234] [INFO] monitorLogs - MQTT client connected +[2025-04-14T19:57:07.460] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-04-14T19:57:07.466] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-04-14T19:57:07.468] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-04-15T03:02:07.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-15 03:02:07 +[2025-04-15T05:57:12.737] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-04-15T05:57:12.741] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-04-15T05:57:12.744] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-04-15T11:19:31.123] [INFO] monitorLogs - MQTT client connected +[2025-04-15T14:15:29.621] [INFO] monitorLogs - MQTT client connected +[2025-04-15T19:56:44.571] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-04-15T19:56:44.575] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-04-15T19:56:44.577] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-04-16T03:02:08.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-16 03:02:08 +[2025-04-16T05:38:08.481] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-04-16T05:38:08.483] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-04-16T05:38:08.486] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-04-16T20:00:15.671] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-04-16T20:00:15.679] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-04-16T20:00:15.681] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-04-17T03:02:09.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-17 03:02:09 +[2025-04-17T05:38:59.299] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-04-17T05:38:59.302] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-04-17T05:38:59.304] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-04-17T19:53:37.583] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-04-17T19:53:37.589] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-04-17T19:53:37.591] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-04-18T03:02:10.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-18 03:02:10 +[2025-04-18T05:50:00.533] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-04-18T05:50:00.536] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-04-18T05:50:00.538] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-04-18T19:47:47.542] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-04-18T19:47:47.550] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-04-18T19:47:47.552] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-04-19T03:02:11.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-19 03:02:11 +[2025-04-19T05:34:17.177] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-04-19T05:34:17.179] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-04-19T05:34:17.181] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-04-19T20:05:52.749] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-04-19T20:05:52.751] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-04-19T20:05:52.753] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-04-20T03:02:18.582] [INFO] monitorLogs - setCorrectPlcTimeOnceADay - function error SyntaxError: Unexpected token < in JSON at position 0 + at JSON.parse () + at /home/unipi/flowserver/flow/cmd_manager.js:2413:28 + at Object.exec_callback [as callback] (/home/unipi/flowserver/node_modules/total.js/builders.js:5803:3) + at IncomingMessage.request_process_end (/home/unipi/flowserver/node_modules/total.js/utils.js:1184:11) + at IncomingMessage.emit (events.js:412:35) + at endReadableNT (internal/streams/readable.js:1334:12) + at processTicksAndRejections (internal/process/task_queues.js:82:21) 503: Service Unavailable
503
Service Unavailable
+[2025-04-20T05:30:16.003] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-04-20T05:30:16.006] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-04-20T05:30:16.009] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-04-20T20:06:23.561] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-04-20T20:06:23.568] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-04-20T20:06:23.570] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-04-21T03:02:14.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-21 03:02:14 +[2025-04-21T05:30:55.669] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-04-21T05:30:55.673] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-04-21T05:30:55.675] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-04-21T20:09:44.028] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-04-21T20:09:44.035] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-04-21T20:09:44.038] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-04-22T03:02:15.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-22 03:02:15 +[2025-04-22T05:29:04.620] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-04-22T05:29:04.624] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-04-22T05:29:04.627] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-04-22T20:10:41.631] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-04-22T20:10:41.639] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-04-22T20:10:41.641] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-04-23T03:02:16.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-23 03:02:16 +[2025-04-23T05:31:38.881] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-04-23T05:31:38.885] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-04-23T05:31:38.887] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-04-23T11:55:39.590] [INFO] monitorLogs - MQTT client connected +[2025-04-23T20:09:27.628] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-04-23T20:09:27.632] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-04-23T20:09:27.634] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-04-24T03:02:17.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-24 03:02:17 +[2025-04-24T05:28:34.641] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-04-24T05:28:34.643] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-04-24T05:28:34.645] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-04-24T17:05:27.630] [INFO] monitorLogs - MQTT client connected +[2025-04-24T17:06:40.707] [INFO] monitorLogs - MQTT client connected +[2025-04-24T17:07:19.183] [INFO] monitorLogs - MQTT client connected +[2025-04-24T18:03:11.711] [INFO] monitorLogs - MQTT client connected +[2025-04-24T20:08:19.243] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-04-24T20:08:19.247] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-04-24T20:08:19.249] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-04-25T03:02:18.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-25 03:02:18 +[2025-04-25T05:37:24.191] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-04-25T05:37:24.194] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-04-25T05:37:24.196] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-04-25T10:31:50.888] [INFO] monitorLogs - MQTT client connected +[2025-04-25T12:15:18.281] [INFO] monitorLogs - MQTT client connected +[2025-04-25T20:11:40.302] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-04-25T20:11:40.307] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-04-25T20:11:40.309] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-04-26T03:02:19.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-26 03:02:19 +[2025-04-26T05:25:23.484] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-04-26T05:25:23.486] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-04-26T05:25:23.489] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-04-26T20:17:42.248] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-04-26T20:17:42.251] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-04-26T20:17:42.253] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-04-27T03:02:20.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-27 03:02:20 +[2025-04-27T05:18:21.223] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-04-27T05:18:21.225] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-04-27T05:18:21.227] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-04-27T20:19:51.785] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-04-27T20:19:51.789] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-04-27T20:19:51.790] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-04-28T03:02:21.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-28 03:02:21 +[2025-04-28T05:16:42.760] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-04-28T05:16:42.763] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-04-28T05:16:42.765] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-04-28T20:19:56.090] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-04-28T20:19:56.098] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-04-28T20:19:56.100] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-04-29T03:02:23.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-29 03:02:23 +[2025-04-29T05:14:55.736] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-04-29T05:14:55.739] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-04-29T05:14:55.741] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-04-29T06:46:22.547] [INFO] monitorLogs - MQTT client connected +[2025-04-29T06:53:15.787] [INFO] monitorLogs - MQTT client connected +[2025-04-29T06:54:53.183] [INFO] monitorLogs - MQTT client connected +[2025-04-29T06:56:16.503] [INFO] monitorLogs - MQTT client connected +[2025-04-29T07:48:12.417] [INFO] monitorLogs - MQTT client connected +[2025-04-29T07:49:21.794] [INFO] monitorLogs - MQTT client connected +[2025-04-29T07:51:58.675] [INFO] monitorLogs - MQTT client connected +[2025-04-29T07:53:07.773] [INFO] monitorLogs - MQTT client connected +[2025-04-29T07:54:11.811] [INFO] monitorLogs - MQTT client connected +[2025-04-29T09:11:45.442] [INFO] monitorLogs - MQTT client connected +[2025-04-29T09:12:08.744] [INFO] monitorLogs - MQTT client connected +[2025-04-29T20:21:23.390] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-04-29T20:21:23.394] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-04-29T20:21:23.397] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-04-29T22:22:32.226] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-04-29T22:22:37.584] [INFO] monitorLogs - buildTasks - params undefined +[2025-04-29T22:22:37.590] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-04-29T22:22:37.592] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-04-29T22:22:37.592] [INFO] monitorLogs - profile: { + 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 +} +[2025-04-29T22:22:37.597] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-04-29T22:22:37.599] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-04-30T04:05:00.598Z +[2025-04-29T22:22:37.600] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-04-30T18:33:00.600Z +[2025-04-29T22:22:37.601] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '6:5', name: 'luxOff' }, + { value: 1, start_time: '20:33', name: 'luxOn' } +] +[2025-04-29T22:22:37.602] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-04-29T22:22:37.603] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-04-29T22:22:37.604] [INFO] monitorLogs - profile: { + 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 +} +[2025-04-29T22:22:37.607] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-04-29T22:22:37.607] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-04-30T04:05:00.607Z +[2025-04-29T22:22:37.608] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-04-30T18:33:00.608Z +[2025-04-29T22:22:37.609] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '6:5', name: 'luxOff' }, + { value: 1, start_time: '20:33', name: 'luxOn' } +] +[2025-04-29T22:22:37.610] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-04-29T22:22:37.611] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-04-29T22:22:37.612] [INFO] monitorLogs - profile: { + 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 +} +[2025-04-29T22:22:37.614] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-04-29T22:22:37.615] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-04-30T04:05:00.615Z +[2025-04-29T22:22:37.616] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-04-30T18:33:00.615Z +[2025-04-29T22:22:37.616] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '6:5', name: 'luxOff' }, + { value: 1, start_time: '20:33', name: 'luxOn' } +] +[2025-04-29T22:22:37.618] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-04-29T22:22:37.633] [INFO] monitorLogs - tasks created: 1778 +[2025-04-29T22:22:37.636] [INFO] monitorLogs - -->FLOW bol spustený PLBJzmK1r3Gynd6OW0gKRo0e5wV4vx9bDEqNgYR8 2025-04-28 +[2025-04-29T22:22:37.771] [INFO] monitorLogs - MQTT client connected +[2025-04-29T22:22:37.950] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-04-29T22:22:38.257] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-04-29T22:22:38.562] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-04-30T03:22:39.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-30 03:22:39 +[2025-04-30T05:16:09.625] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-04-30T05:16:09.628] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-04-30T05:16:09.630] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-04-30T17:04:25.127] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-04-30T17:04:30.491] [INFO] monitorLogs - buildTasks - params undefined +[2025-04-30T17:04:30.496] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-04-30T17:04:30.497] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-04-30T17:04:30.498] [INFO] monitorLogs - profile: { + 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 +} +[2025-04-30T17:04:30.502] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-04-30T17:04:30.504] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-05-01T04:03:00.503Z +[2025-04-30T17:04:30.505] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-04-30T18:34:00.505Z +[2025-04-30T17:04:30.506] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '6:3', name: 'luxOff' }, + { value: 1, start_time: '20:34', name: 'luxOn' } +] +[2025-04-30T17:04:30.507] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-04-30T17:04:30.508] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-04-30T17:04:30.509] [INFO] monitorLogs - profile: { + 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 +} +[2025-04-30T17:04:30.511] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-04-30T17:04:30.512] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-05-01T04:03:00.512Z +[2025-04-30T17:04:30.513] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-04-30T18:34:00.513Z +[2025-04-30T17:04:30.513] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '6:3', name: 'luxOff' }, + { value: 1, start_time: '20:34', name: 'luxOn' } +] +[2025-04-30T17:04:30.514] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-04-30T17:04:30.515] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-04-30T17:04:30.516] [INFO] monitorLogs - profile: { + 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 +} +[2025-04-30T17:04:30.518] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-04-30T17:04:30.519] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-05-01T04:03:00.518Z +[2025-04-30T17:04:30.519] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-04-30T18:34:00.519Z +[2025-04-30T17:04:30.520] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '6:3', name: 'luxOff' }, + { value: 1, start_time: '20:34', name: 'luxOn' } +] +[2025-04-30T17:04:30.521] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-04-30T17:04:30.547] [INFO] monitorLogs - tasks created: 1778 +[2025-04-30T17:04:30.550] [INFO] monitorLogs - -->FLOW bol spustený PLBJzmK1r3Gynd6OW0gKRo0e5wV4vx9bDEqNgYR8 2025-04-24 +[2025-04-30T17:04:30.666] [INFO] monitorLogs - MQTT client connected +[2025-04-30T17:04:30.865] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-04-30T17:04:31.170] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-04-30T17:04:31.475] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-04-30T20:22:38.875] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-04-30T20:22:38.879] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-04-30T20:22:38.881] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-05-01T03:04:32.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-01 03:04:32 +[2025-05-01T05:11:52.096] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-05-01T05:11:52.100] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-05-01T05:11:52.101] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-05-01T20:24:27.372] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-05-01T20:24:27.378] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-05-01T20:24:27.381] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-05-02T03:04:33.016] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-02 03:04:33 +[2025-05-02T05:10:11.006] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-05-02T05:10:11.009] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-05-02T05:10:11.011] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-05-02T20:24:50.647] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-05-02T20:24:50.654] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-05-02T20:24:50.656] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-05-03T03:04:34.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-03 03:04:34 +[2025-05-03T05:09:08.847] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-05-03T05:09:08.850] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-05-03T05:09:08.852] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-05-03T20:17:17.058] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-05-03T20:17:17.064] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-05-03T20:17:17.067] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-05-04T03:04:35.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-04 03:04:35 +[2025-05-04T05:16:36.743] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-05-04T05:16:36.745] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-05-04T05:16:36.747] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-05-04T20:25:54.298] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-05-04T20:25:54.305] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-05-04T20:25:54.308] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-05-05T03:04:36.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-05 03:04:36 +[2025-05-05T05:15:25.849] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-05-05T05:15:25.852] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-05-05T05:15:25.854] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-05-05T06:40:19.085] [INFO] monitorLogs - MQTT client connected +[2025-05-05T20:12:40.479] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-05-05T20:12:40.486] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-05-05T20:12:40.488] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-05-06T03:04:38.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-06 03:04:38 +[2025-05-06T05:10:26.815] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-05-06T05:10:26.817] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-05-06T05:10:26.819] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-05-06T20:26:50.844] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-05-06T20:26:50.847] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-05-06T20:26:50.849] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-05-07T03:04:39.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-07 03:04:39 +[2025-05-07T05:09:54.829] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-05-07T05:09:54.832] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-05-07T05:09:54.834] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-05-07T11:58:18.980] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-05-07T11:58:24.336] [INFO] monitorLogs - buildTasks - params undefined +[2025-05-07T11:58:24.340] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-05-07T11:58:24.342] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-05-07T11:58:24.343] [INFO] monitorLogs - profile: { + 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 +} +[2025-05-07T11:58:24.347] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-05-07T11:58:24.348] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-05-08T03:52:00.347Z +[2025-05-07T11:58:24.350] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-05-07T18:44:00.349Z +[2025-05-07T11:58:24.350] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '5:52', name: 'luxOff' }, + { value: 1, start_time: '20:44', name: 'luxOn' } +] +[2025-05-07T11:58:24.351] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-05-07T11:58:24.352] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-05-07T11:58:24.353] [INFO] monitorLogs - profile: { + 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 +} +[2025-05-07T11:58:24.355] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-05-07T11:58:24.356] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-05-08T03:52:00.356Z +[2025-05-07T11:58:24.357] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-05-07T18:44:00.356Z +[2025-05-07T11:58:24.357] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '5:52', name: 'luxOff' }, + { value: 1, start_time: '20:44', name: 'luxOn' } +] +[2025-05-07T11:58:24.358] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-05-07T11:58:24.359] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-05-07T11:58:24.359] [INFO] monitorLogs - profile: { + 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 +} +[2025-05-07T11:58:24.362] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-05-07T11:58:24.362] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-05-08T03:52:00.362Z +[2025-05-07T11:58:24.363] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-05-07T18:44:00.363Z +[2025-05-07T11:58:24.363] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '5:52', name: 'luxOff' }, + { value: 1, start_time: '20:44', name: 'luxOn' } +] +[2025-05-07T11:58:24.364] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-05-07T11:58:24.393] [INFO] monitorLogs - tasks created: 1778 +[2025-05-07T11:58:24.396] [INFO] monitorLogs - -->FLOW bol spustený PLBJzmK1r3Gynd6OW0gKRo0e5wV4vx9bDEqNgYR8 2025-04-24 +[2025-05-07T11:58:24.497] [INFO] monitorLogs - MQTT client connected +[2025-05-07T11:58:24.710] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-05-07T11:58:25.015] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-05-07T11:58:25.322] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-05-07T12:53:22.743] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-05-07T12:53:28.092] [INFO] monitorLogs - buildTasks - params undefined +[2025-05-07T12:53:28.097] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-05-07T12:53:28.099] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-05-07T12:53:28.099] [INFO] monitorLogs - profile: { + 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 +} +[2025-05-07T12:53:28.103] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-05-07T12:53:28.105] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-05-08T03:52:00.104Z +[2025-05-07T12:53:28.107] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-05-07T18:44:00.106Z +[2025-05-07T12:53:28.107] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '5:52', name: 'luxOff' }, + { value: 1, start_time: '20:44', name: 'luxOn' } +] +[2025-05-07T12:53:28.109] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-05-07T12:53:28.110] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-05-07T12:53:28.110] [INFO] monitorLogs - profile: { + 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 +} +[2025-05-07T12:53:28.113] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-05-07T12:53:28.113] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-05-08T03:52:00.113Z +[2025-05-07T12:53:28.114] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-05-07T18:44:00.114Z +[2025-05-07T12:53:28.115] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '5:52', name: 'luxOff' }, + { value: 1, start_time: '20:44', name: 'luxOn' } +] +[2025-05-07T12:53:28.116] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-05-07T12:53:28.117] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-05-07T12:53:28.117] [INFO] monitorLogs - profile: { + 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 +} +[2025-05-07T12:53:28.119] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-05-07T12:53:28.120] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-05-08T03:52:00.120Z +[2025-05-07T12:53:28.121] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-05-07T18:44:00.121Z +[2025-05-07T12:53:28.122] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '5:52', name: 'luxOff' }, + { value: 1, start_time: '20:44', name: 'luxOn' } +] +[2025-05-07T12:53:28.123] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-05-07T12:53:28.149] [INFO] monitorLogs - tasks created: 1778 +[2025-05-07T12:53:28.151] [INFO] monitorLogs - -->FLOW bol spustený PLBJzmK1r3Gynd6OW0gKRo0e5wV4vx9bDEqNgYR8 2025-04-24 +[2025-05-07T12:53:28.286] [INFO] monitorLogs - MQTT client connected +[2025-05-07T12:53:28.468] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-05-07T12:53:28.774] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-05-07T12:53:29.079] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-05-07T13:28:34.797] [INFO] monitorLogs - MQTT client connected +[2025-05-07T13:28:56.326] [INFO] monitorLogs - MQTT client connected +[2025-05-07T20:26:02.918] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-05-07T20:26:02.926] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-05-07T20:26:02.929] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-05-08T03:53:29.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-08 03:53:29 +[2025-05-08T05:10:22.731] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-05-08T05:10:22.733] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-05-08T05:10:22.736] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-05-08T20:33:04.462] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-05-08T20:33:04.471] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-05-08T20:33:04.473] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-05-09T03:53:30.075] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-09 03:53:30 +[2025-05-09T04:58:49.632] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-05-09T04:58:49.635] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-05-09T04:58:49.637] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-05-09T20:37:18.184] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-05-09T20:37:18.193] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-05-09T20:37:18.195] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-05-10T03:53:31.017] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-10 03:53:31 +[2025-05-10T04:56:27.936] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-05-10T04:56:27.939] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-05-10T04:56:27.941] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-05-10T20:34:39.638] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-05-10T20:34:39.646] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-05-10T20:34:39.649] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-05-11T03:53:33.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-11 03:53:33 +[2025-05-11T05:00:25.425] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-05-11T05:00:25.428] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-05-11T05:00:25.431] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-05-11T20:39:44.416] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-05-11T20:39:44.424] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-05-11T20:39:44.427] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-05-12T03:53:34.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-12 03:53:34 +[2025-05-12T04:54:35.482] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-05-12T04:54:35.484] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-05-12T04:54:35.487] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-05-12T09:50:56.691] [INFO] monitorLogs - MQTT client connected +[2025-05-12T09:51:58.129] [INFO] monitorLogs - MQTT client connected +[2025-05-12T10:52:27.381] [INFO] monitorLogs - MQTT client connected +[2025-05-12T20:41:41.197] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-05-12T20:41:41.205] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-05-12T20:41:41.208] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-05-13T03:53:35.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-13 03:53:35 +[2025-05-13T04:53:27.789] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-05-13T04:53:27.792] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-05-13T04:53:27.795] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-05-13T20:41:24.537] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-05-13T20:41:24.546] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-05-13T20:41:24.548] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-05-14T03:53:36.019] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-14 03:53:36 +[2025-05-14T04:52:37.976] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-05-14T04:52:37.978] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-05-14T04:52:37.980] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-05-14T07:44:39.494] [INFO] monitorLogs - MQTT client connected +[2025-05-14T08:32:11.183] [INFO] monitorLogs - MQTT client connected +[2025-05-14T09:41:29.565] [INFO] monitorLogs - MQTT client connected +[2025-05-14T10:08:29.602] [INFO] monitorLogs - MQTT client connected +[2025-05-14T10:46:15.864] [INFO] monitorLogs - MQTT client connected +[2025-05-14T10:47:22.623] [INFO] monitorLogs - MQTT client connected +[2025-05-14T10:48:04.342] [INFO] monitorLogs - MQTT client connected +[2025-05-14T10:48:23.951] [INFO] monitorLogs - MQTT client connected +[2025-05-14T10:52:48.828] [INFO] monitorLogs - MQTT client connected +[2025-05-14T10:55:08.575] [INFO] monitorLogs - MQTT client connected +[2025-05-14T20:40:38.069] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-05-14T20:40:38.077] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-05-14T20:40:38.080] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-05-15T03:53:37.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-15 03:53:37 +[2025-05-15T05:00:53.762] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-05-15T05:00:53.765] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-05-15T05:00:53.768] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-05-15T15:53:51.114] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-05-15T15:53:56.517] [INFO] monitorLogs - buildTasks - params undefined +[2025-05-15T15:53:56.521] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-05-15T15:53:56.523] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-05-15T15:53:56.523] [INFO] monitorLogs - profile: { + 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 +} +[2025-05-15T15:53:56.528] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-05-15T15:53:56.529] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-05-16T03:41:00.528Z +[2025-05-15T15:53:56.530] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-05-15T18:56:00.530Z +[2025-05-15T15:53:56.531] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '5:41', name: 'luxOff' }, + { value: 1, start_time: '20:56', name: 'luxOn' } +] +[2025-05-15T15:53:56.532] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-05-15T15:53:56.533] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-05-15T15:53:56.534] [INFO] monitorLogs - profile: { + 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 +} +[2025-05-15T15:53:56.536] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-05-15T15:53:56.537] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-05-16T03:41:00.537Z +[2025-05-15T15:53:56.538] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-05-15T18:56:00.538Z +[2025-05-15T15:53:56.538] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '5:41', name: 'luxOff' }, + { value: 1, start_time: '20:56', name: 'luxOn' } +] +[2025-05-15T15:53:56.539] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-05-15T15:53:56.540] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-05-15T15:53:56.541] [INFO] monitorLogs - profile: { + 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 +} +[2025-05-15T15:53:56.543] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-05-15T15:53:56.544] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-05-16T03:41:00.544Z +[2025-05-15T15:53:56.545] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-05-15T18:56:00.544Z +[2025-05-15T15:53:56.545] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '5:41', name: 'luxOff' }, + { value: 1, start_time: '20:56', name: 'luxOn' } +] +[2025-05-15T15:53:56.546] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-05-15T15:53:56.555] [INFO] monitorLogs - tasks created: 1778 +[2025-05-15T15:53:56.558] [INFO] monitorLogs - -->FLOW bol spustený PLBJzmK1r3Gynd6OW0gKRo0e5wV4vx9bDEqNgYR8 2025-04-24 +[2025-05-15T15:53:56.644] [INFO] monitorLogs - MQTT client connected +[2025-05-15T15:53:56.872] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-05-15T15:53:57.177] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-05-15T15:53:57.482] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-05-15T20:36:39.883] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-05-15T20:36:39.886] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-05-15T20:36:39.889] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-05-16T03:53:58.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-16 03:53:58 +[2025-05-16T04:48:46.793] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-05-16T04:48:46.796] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-05-16T04:48:46.798] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-05-16T20:46:05.442] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-05-16T20:46:05.449] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-05-16T20:46:05.452] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-05-17T03:53:59.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-17 03:53:59 +[2025-05-17T04:57:42.164] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-05-17T04:57:42.167] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-05-17T04:57:42.169] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-05-17T20:44:43.240] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-05-17T20:44:43.243] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-05-17T20:44:43.245] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-05-18T03:54:00.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-18 03:54:00 +[2025-05-18T05:05:09.120] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-05-18T05:05:09.123] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-05-18T05:05:09.125] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-05-18T13:25:19.144] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-05-18T13:25:24.509] [INFO] monitorLogs - buildTasks - params undefined +[2025-05-18T13:25:24.513] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-05-18T13:25:24.514] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-05-18T13:25:24.515] [INFO] monitorLogs - profile: { + 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 +} +[2025-05-18T13:25:24.519] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-05-18T13:25:24.521] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-05-19T03:37:00.520Z +[2025-05-18T13:25:24.522] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-05-18T19:00:00.522Z +[2025-05-18T13:25:24.523] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '5:37', name: 'luxOff' }, + { value: 1, start_time: '21:0', name: 'luxOn' } +] +[2025-05-18T13:25:24.524] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-05-18T13:25:24.525] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-05-18T13:25:24.525] [INFO] monitorLogs - profile: { + 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 +} +[2025-05-18T13:25:24.528] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-05-18T13:25:24.529] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-05-19T03:37:00.528Z +[2025-05-18T13:25:24.529] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-05-18T19:00:00.529Z +[2025-05-18T13:25:24.530] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '5:37', name: 'luxOff' }, + { value: 1, start_time: '21:0', name: 'luxOn' } +] +[2025-05-18T13:25:24.531] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-05-18T13:25:24.532] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-05-18T13:25:24.532] [INFO] monitorLogs - profile: { + 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 +} +[2025-05-18T13:25:24.535] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-05-18T13:25:24.535] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-05-19T03:37:00.535Z +[2025-05-18T13:25:24.536] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-05-18T19:00:00.536Z +[2025-05-18T13:25:24.537] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '5:37', name: 'luxOff' }, + { value: 1, start_time: '21:0', name: 'luxOn' } +] +[2025-05-18T13:25:24.538] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-05-18T13:25:24.563] [INFO] monitorLogs - tasks created: 1778 +[2025-05-18T13:25:24.565] [INFO] monitorLogs - -->FLOW bol spustený PLBJzmK1r3Gynd6OW0gKRo0e5wV4vx9bDEqNgYR8 2025-04-24 +[2025-05-18T13:25:29.579] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-05-18T20:43:51.557] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-05-18T20:43:51.565] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-05-18T20:43:51.568] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-05-19T03:25:25.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-19 03:25:25 +[2025-05-19T05:04:16.775] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-05-19T05:04:16.779] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-05-19T05:04:16.781] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-05-19T20:32:52.829] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-05-19T20:32:52.837] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-05-19T20:32:52.840] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-05-20T03:25:26.022] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-20 03:25:26 +[2025-05-20T04:55:02.542] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-05-20T04:55:02.545] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-05-20T04:55:02.547] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-05-20T20:50:39.287] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-05-20T20:50:39.290] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-05-20T20:50:39.292] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-05-21T03:25:27.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-21 03:25:27 +[2025-05-21T04:44:33.859] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-05-21T04:44:33.861] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-05-21T04:44:33.864] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-05-21T20:50:32.448] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-05-21T20:50:32.454] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-05-21T20:50:32.457] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-05-22T03:25:28.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-22 03:25:28 +[2025-05-22T04:46:38.151] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-05-22T04:46:38.153] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-05-22T04:46:38.156] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-05-22T20:44:22.363] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-05-22T20:44:22.365] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-05-22T20:44:22.367] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-05-23T03:25:30.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-23 03:25:30 +[2025-05-23T04:48:16.055] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-05-23T04:48:16.059] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-05-23T04:48:16.061] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-05-23T20:55:09.911] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-05-23T20:55:09.918] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-05-23T20:55:09.921] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-05-24T03:25:31.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-24 03:25:31 +[2025-05-24T04:41:07.749] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-05-24T04:41:07.751] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-05-24T04:41:07.754] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-05-24T20:55:57.526] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-05-24T20:55:57.529] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-05-24T20:55:57.532] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-05-25T03:25:32.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-25 03:25:32 +[2025-05-25T04:39:03.575] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-05-25T04:39:03.579] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-05-25T04:39:03.581] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-05-25T20:58:15.430] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-05-25T20:58:15.437] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-05-25T20:58:15.440] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-05-26T03:25:33.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-26 03:25:33 +[2025-05-26T04:49:52.322] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-05-26T04:49:52.324] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-05-26T04:49:52.327] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-05-26T20:58:00.177] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-05-26T20:58:00.185] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-05-26T20:58:00.187] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-05-27T03:25:34.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-27 03:25:34 +[2025-05-27T04:36:36.990] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-05-27T04:36:36.993] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-05-27T04:36:36.995] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-05-27T20:59:54.661] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-05-27T20:59:54.668] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-05-27T20:59:54.671] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-05-28T03:25:35.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-28 03:25:35 +[2025-05-28T04:35:10.052] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-05-28T04:35:10.055] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-05-28T04:35:10.057] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-05-28T20:58:37.111] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-05-28T20:58:37.119] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-05-28T20:58:37.122] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-05-29T03:25:37.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-29 03:25:37 +[2025-05-29T04:41:22.387] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-05-29T04:41:22.389] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-05-29T04:41:22.391] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-05-29T21:01:19.937] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-05-29T21:01:19.945] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-05-29T21:01:19.948] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-05-30T03:25:38.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-30 03:25:38 +[2025-05-30T04:34:59.014] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-05-30T04:34:59.017] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-05-30T04:34:59.019] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-05-30T16:04:38.115] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-05-30T16:04:43.484] [INFO] monitorLogs - buildTasks - params undefined +[2025-05-30T16:04:43.489] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-05-30T16:04:43.490] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-05-30T16:04:43.491] [INFO] monitorLogs - profile: { + 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 +} +[2025-05-30T16:04:43.495] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-05-30T16:04:43.496] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-05-31T03:25:00.495Z +[2025-05-30T16:04:43.498] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-05-30T19:14:00.497Z +[2025-05-30T16:04:43.498] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '5:25', name: 'luxOff' }, + { value: 1, start_time: '21:14', name: 'luxOn' } +] +[2025-05-30T16:04:43.500] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-05-30T16:04:43.500] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-05-30T16:04:43.501] [INFO] monitorLogs - profile: { + 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 +} +[2025-05-30T16:04:43.503] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-05-30T16:04:43.504] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-05-31T03:25:00.504Z +[2025-05-30T16:04:43.505] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-05-30T19:14:00.505Z +[2025-05-30T16:04:43.506] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '5:25', name: 'luxOff' }, + { value: 1, start_time: '21:14', name: 'luxOn' } +] +[2025-05-30T16:04:43.507] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-05-30T16:04:43.508] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-05-30T16:04:43.508] [INFO] monitorLogs - profile: { + 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 +} +[2025-05-30T16:04:43.510] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-05-30T16:04:43.511] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-05-31T03:25:00.511Z +[2025-05-30T16:04:43.512] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-05-30T19:14:00.512Z +[2025-05-30T16:04:43.512] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '5:25', name: 'luxOff' }, + { value: 1, start_time: '21:14', name: 'luxOn' } +] +[2025-05-30T16:04:43.514] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-05-30T16:04:43.540] [INFO] monitorLogs - tasks created: 1778 +[2025-05-30T16:04:43.543] [INFO] monitorLogs - -->FLOW bol spustený PLBJzmK1r3Gynd6OW0gKRo0e5wV4vx9bDEqNgYR8 2025-04-24 +[2025-05-30T16:04:48.557] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-05-30T16:12:27.181] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-05-30T16:12:32.539] [INFO] monitorLogs - buildTasks - params undefined +[2025-05-30T16:12:32.544] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-05-30T16:12:32.545] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-05-30T16:12:32.545] [INFO] monitorLogs - profile: { + 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 +} +[2025-05-30T16:12:32.550] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-05-30T16:12:32.551] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-05-31T03:25:00.550Z +[2025-05-30T16:12:32.553] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-05-30T19:14:00.552Z +[2025-05-30T16:12:32.553] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '5:25', name: 'luxOff' }, + { value: 1, start_time: '21:14', name: 'luxOn' } +] +[2025-05-30T16:12:32.555] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-05-30T16:12:32.555] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-05-30T16:12:32.556] [INFO] monitorLogs - profile: { + 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 +} +[2025-05-30T16:12:32.558] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-05-30T16:12:32.559] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-05-31T03:25:00.559Z +[2025-05-30T16:12:32.560] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-05-30T19:14:00.560Z +[2025-05-30T16:12:32.561] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '5:25', name: 'luxOff' }, + { value: 1, start_time: '21:14', name: 'luxOn' } +] +[2025-05-30T16:12:32.562] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-05-30T16:12:32.562] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-05-30T16:12:32.563] [INFO] monitorLogs - profile: { + 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 +} +[2025-05-30T16:12:32.565] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-05-30T16:12:32.566] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-05-31T03:25:00.566Z +[2025-05-30T16:12:32.568] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-05-30T19:14:00.567Z +[2025-05-30T16:12:32.569] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '5:25', name: 'luxOff' }, + { value: 1, start_time: '21:14', name: 'luxOn' } +] +[2025-05-30T16:12:32.570] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-05-30T16:12:32.596] [INFO] monitorLogs - tasks created: 1778 +[2025-05-30T16:12:32.598] [INFO] monitorLogs - -->FLOW bol spustený PLBJzmK1r3Gynd6OW0gKRo0e5wV4vx9bDEqNgYR8 2025-04-24 +[2025-05-30T16:12:37.613] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-05-30T21:04:55.003] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-05-30T21:04:55.011] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-05-30T21:04:55.014] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-05-31T03:12:34.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-31 03:12:34 +[2025-05-31T04:32:07.276] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-05-31T04:32:07.280] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-05-31T04:32:07.282] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-05-31T20:54:47.061] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-05-31T20:54:47.068] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-05-31T20:54:47.071] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-06-01T03:12:35.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-01 03:12:35 +[2025-06-01T04:36:01.145] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-06-01T04:36:01.149] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-06-01T04:36:01.151] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-06-01T20:59:08.074] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-06-01T20:59:08.081] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-06-01T20:59:08.084] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-06-02T03:12:36.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-02 03:12:36 +[2025-06-02T04:32:39.227] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-06-02T04:32:39.230] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-06-02T04:32:39.232] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-06-02T20:39:11.808] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-06-02T20:39:11.815] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-06-02T20:39:11.817] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-06-03T03:12:38.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-03 03:12:38 +[2025-06-03T04:41:57.994] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-06-03T04:41:57.997] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-06-03T04:41:57.999] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-06-03T21:04:21.764] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-06-03T21:04:21.772] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-06-03T21:04:21.774] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-06-04T03:12:39.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-04 03:12:39 +[2025-06-04T04:32:04.375] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-06-04T04:32:04.378] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-06-04T04:32:04.380] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-06-04T17:02:33.116] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-06-04T17:02:38.482] [INFO] monitorLogs - buildTasks - params undefined +[2025-06-04T17:02:38.486] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-06-04T17:02:38.487] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-06-04T17:02:38.488] [INFO] monitorLogs - profile: { + 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 +} +[2025-06-04T17:02:38.492] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-06-04T17:02:38.493] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-06-05T03:22:00.493Z +[2025-06-04T17:02:38.495] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-06-04T19:19:00.495Z +[2025-06-04T17:02:38.496] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '5:22', name: 'luxOff' }, + { value: 1, start_time: '21:19', name: 'luxOn' } +] +[2025-06-04T17:02:38.497] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-06-04T17:02:38.498] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-06-04T17:02:38.498] [INFO] monitorLogs - profile: { + 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 +} +[2025-06-04T17:02:38.501] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-06-04T17:02:38.501] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-06-05T03:22:00.501Z +[2025-06-04T17:02:38.502] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-06-04T19:19:00.502Z +[2025-06-04T17:02:38.503] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '5:22', name: 'luxOff' }, + { value: 1, start_time: '21:19', name: 'luxOn' } +] +[2025-06-04T17:02:38.504] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-06-04T17:02:38.505] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-06-04T17:02:38.505] [INFO] monitorLogs - profile: { + 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 +} +[2025-06-04T17:02:38.507] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-06-04T17:02:38.508] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-06-05T03:22:00.508Z +[2025-06-04T17:02:38.509] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-06-04T19:19:00.509Z +[2025-06-04T17:02:38.510] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '5:22', name: 'luxOff' }, + { value: 1, start_time: '21:19', name: 'luxOn' } +] +[2025-06-04T17:02:38.511] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-06-04T17:02:38.537] [INFO] monitorLogs - tasks created: 1778 +[2025-06-04T17:02:38.540] [INFO] monitorLogs - -->FLOW bol spustený PLBJzmK1r3Gynd6OW0gKRo0e5wV4vx9bDEqNgYR8 2025-04-24 +[2025-06-04T17:02:43.555] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-04T21:06:23.959] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-06-04T21:06:23.966] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-06-04T21:06:23.969] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-06-05T03:02:40.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-05 03:02:40 +[2025-06-05T04:31:11.597] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-06-05T04:31:11.600] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-06-05T04:31:11.602] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-06-05T21:04:51.648] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-06-05T21:04:51.656] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-06-05T21:04:51.658] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-06-06T03:02:42.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-06 03:02:42 +[2025-06-06T04:31:21.975] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-06-06T04:31:21.977] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-06-06T04:31:21.980] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-06-06T21:07:18.796] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-06-06T21:07:18.804] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-06-06T21:07:18.806] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-06-07T03:02:43.070] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-07 03:02:43 +[2025-06-07T04:33:30.818] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-06-07T04:33:30.821] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-06-07T04:33:30.824] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-06-07T20:53:01.052] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-06-07T20:53:01.060] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-06-07T20:53:01.063] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-06-08T03:02:44.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-08 03:02:44 +[2025-06-08T04:28:53.896] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-06-08T04:28:53.898] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-06-08T04:28:53.900] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-06-08T21:11:07.022] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-06-08T21:11:07.029] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-06-08T21:11:07.032] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-06-09T03:02:45.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-09 03:02:45 +[2025-06-09T04:28:04.814] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-06-09T04:28:04.817] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-06-09T04:28:04.819] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-06-09T21:11:01.018] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-06-09T21:11:01.020] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-06-09T21:11:01.022] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-06-10T03:02:47.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-10 03:02:47 +[2025-06-10T04:30:44.303] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-06-10T04:30:44.306] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-06-10T04:30:44.307] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-06-10T21:09:35.042] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-06-10T21:09:35.050] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-06-10T21:09:35.052] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-06-11T03:02:48.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-11 03:02:48 +[2025-06-11T04:31:01.939] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-06-11T04:31:01.942] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-06-11T04:31:01.944] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-06-11T21:12:52.675] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-06-11T21:12:52.678] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-06-11T21:12:52.680] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-06-12T03:02:49.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-12 03:02:49 +[2025-06-12T04:26:50.328] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-06-12T04:26:50.330] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-06-12T04:26:50.334] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-06-12T21:14:29.506] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-06-12T21:14:29.514] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-06-12T21:14:29.516] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-06-13T03:02:50.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-13 03:02:50 +[2025-06-13T04:27:58.208] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-06-13T04:27:58.211] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-06-13T04:27:58.213] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-06-13T15:04:47.192] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-06-13T15:04:52.557] [INFO] monitorLogs - buildTasks - params undefined +[2025-06-13T15:04:52.561] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-06-13T15:04:52.562] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-06-13T15:04:52.563] [INFO] monitorLogs - profile: { + 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 +} +[2025-06-13T15:04:52.567] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-06-13T15:04:52.568] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-06-14T03:19:00.568Z +[2025-06-13T15:04:52.570] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-06-13T19:25:00.570Z +[2025-06-13T15:04:52.571] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '5:19', name: 'luxOff' }, + { value: 1, start_time: '21:25', name: 'luxOn' } +] +[2025-06-13T15:04:52.572] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-06-13T15:04:52.573] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-06-13T15:04:52.573] [INFO] monitorLogs - profile: { + 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 +} +[2025-06-13T15:04:52.576] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-06-13T15:04:52.576] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-06-14T03:19:00.576Z +[2025-06-13T15:04:52.577] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-06-13T19:25:00.577Z +[2025-06-13T15:04:52.578] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '5:19', name: 'luxOff' }, + { value: 1, start_time: '21:25', name: 'luxOn' } +] +[2025-06-13T15:04:52.579] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-06-13T15:04:52.580] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-06-13T15:04:52.580] [INFO] monitorLogs - profile: { + 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 +} +[2025-06-13T15:04:52.582] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-06-13T15:04:52.583] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-06-14T03:19:00.583Z +[2025-06-13T15:04:52.584] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-06-13T19:25:00.584Z +[2025-06-13T15:04:52.584] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '5:19', name: 'luxOff' }, + { value: 1, start_time: '21:25', name: 'luxOn' } +] +[2025-06-13T15:04:52.585] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-06-13T15:04:52.612] [INFO] monitorLogs - tasks created: 1778 +[2025-06-13T15:04:52.614] [INFO] monitorLogs - -->FLOW bol spustený PLBJzmK1r3Gynd6OW0gKRo0e5wV4vx9bDEqNgYR8 2025-04-24 +[2025-06-13T15:04:57.630] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-13T21:14:23.641] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-06-13T21:14:23.649] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-06-13T21:14:23.652] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-06-14T03:04:54.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-14 03:04:54 +[2025-06-14T04:26:20.346] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-06-14T04:26:20.349] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-06-14T04:26:20.351] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-06-14T21:15:41.402] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-06-14T21:15:41.409] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-06-14T21:15:41.411] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-06-15T03:04:55.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-15 03:04:55 +[2025-06-15T04:27:47.150] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-06-15T04:27:47.153] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-06-15T04:27:47.155] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-06-15T21:15:06.005] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-06-15T21:15:06.011] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-06-15T21:15:06.014] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-06-16T03:04:57.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-16 03:04:57 +[2025-06-16T04:25:45.748] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-06-16T04:25:45.751] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-06-16T04:25:45.753] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-06-16T20:52:06.910] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-06-16T20:52:06.918] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-06-16T20:52:06.920] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-06-17T03:04:58.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-17 03:04:58 +[2025-06-17T04:33:53.485] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-06-17T04:33:53.488] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-06-17T04:33:53.490] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-06-17T21:15:57.201] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-06-17T21:15:57.207] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-06-17T21:15:57.210] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-06-18T03:04:59.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-18 03:04:59 +[2025-06-18T04:27:28.269] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-06-18T04:27:28.271] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-06-18T04:27:28.274] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-06-18T21:16:34.965] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-06-18T21:16:34.973] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-06-18T21:16:34.975] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-06-19T03:05:00.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-19 03:05:00 +[2025-06-19T04:28:36.990] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-06-19T04:28:36.993] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-06-19T04:28:36.995] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-06-19T10:59:19.954] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false command received from platform +[2025-06-19T10:59:27.938] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false command received from platform +[2025-06-19T10:59:35.306] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false command received from platform +[2025-06-19T21:19:33.062] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-06-19T21:19:33.065] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-06-19T21:19:33.067] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-06-20T03:05:02.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-20 03:05:02 +[2025-06-20T04:26:59.508] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-06-20T04:26:59.510] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-06-20T04:26:59.513] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-06-20T14:36:27.082] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-06-20T14:36:32.455] [INFO] monitorLogs - buildTasks - params undefined +[2025-06-20T14:36:32.459] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-06-20T14:36:32.460] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-06-20T14:36:32.461] [INFO] monitorLogs - profile: { + 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 +} +[2025-06-20T14:36:32.465] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-06-20T14:36:32.466] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-06-21T03:19:00.466Z +[2025-06-20T14:36:32.468] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-06-20T19:28:00.468Z +[2025-06-20T14:36:32.468] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '5:19', name: 'luxOff' }, + { value: 1, start_time: '21:28', name: 'luxOn' } +] +[2025-06-20T14:36:32.470] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-06-20T14:36:32.471] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-06-20T14:36:32.471] [INFO] monitorLogs - profile: { + 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 +} +[2025-06-20T14:36:32.474] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-06-20T14:36:32.474] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-06-21T03:19:00.474Z +[2025-06-20T14:36:32.475] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-06-20T19:28:00.475Z +[2025-06-20T14:36:32.476] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '5:19', name: 'luxOff' }, + { value: 1, start_time: '21:28', name: 'luxOn' } +] +[2025-06-20T14:36:32.477] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-06-20T14:36:32.478] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-06-20T14:36:32.478] [INFO] monitorLogs - profile: { + 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 +} +[2025-06-20T14:36:32.480] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-06-20T14:36:32.481] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-06-21T03:19:00.481Z +[2025-06-20T14:36:32.482] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-06-20T19:28:00.482Z +[2025-06-20T14:36:32.482] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '5:19', name: 'luxOff' }, + { value: 1, start_time: '21:28', name: 'luxOn' } +] +[2025-06-20T14:36:32.483] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-06-20T14:36:32.509] [INFO] monitorLogs - tasks created: 1778 +[2025-06-20T14:36:32.512] [INFO] monitorLogs - -->FLOW bol spustený PLBJzmK1r3Gynd6OW0gKRo0e5wV4vx9bDEqNgYR8 2025-04-24 +[2025-06-20T14:36:37.525] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-20T14:44:05.105] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-06-20T14:44:10.466] [INFO] monitorLogs - buildTasks - params undefined +[2025-06-20T14:44:10.471] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-06-20T14:44:10.472] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-06-20T14:44:10.473] [INFO] monitorLogs - profile: { + 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 +} +[2025-06-20T14:44:10.477] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-06-20T14:44:10.478] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-06-21T03:19:00.477Z +[2025-06-20T14:44:10.480] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-06-20T19:28:00.479Z +[2025-06-20T14:44:10.480] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '5:19', name: 'luxOff' }, + { value: 1, start_time: '21:28', name: 'luxOn' } +] +[2025-06-20T14:44:10.482] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-06-20T14:44:10.482] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-06-20T14:44:10.483] [INFO] monitorLogs - profile: { + 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 +} +[2025-06-20T14:44:10.485] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-06-20T14:44:10.486] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-06-21T03:19:00.486Z +[2025-06-20T14:44:10.487] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-06-20T19:28:00.487Z +[2025-06-20T14:44:10.488] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '5:19', name: 'luxOff' }, + { value: 1, start_time: '21:28', name: 'luxOn' } +] +[2025-06-20T14:44:10.489] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-06-20T14:44:10.489] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-06-20T14:44:10.490] [INFO] monitorLogs - profile: { + 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 +} +[2025-06-20T14:44:10.492] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-06-20T14:44:10.493] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-06-21T03:19:00.493Z +[2025-06-20T14:44:10.494] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-06-20T19:28:00.494Z +[2025-06-20T14:44:10.494] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '5:19', name: 'luxOff' }, + { value: 1, start_time: '21:28', name: 'luxOn' } +] +[2025-06-20T14:44:10.495] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-06-20T14:44:10.522] [INFO] monitorLogs - tasks created: 1778 +[2025-06-20T14:44:10.525] [INFO] monitorLogs - -->FLOW bol spustený PLBJzmK1r3Gynd6OW0gKRo0e5wV4vx9bDEqNgYR8 2025-04-24 +[2025-06-20T14:44:15.539] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-20T21:18:39.843] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-06-20T21:18:39.852] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-06-20T21:18:39.854] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-06-21T03:44:11.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-21 03:44:11 +[2025-06-21T04:29:04.628] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-06-21T04:29:04.631] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-06-21T04:29:04.633] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-06-21T21:16:58.431] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-06-21T21:16:58.439] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-06-21T21:16:58.441] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-06-22T03:44:12.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-22 03:44:12 +[2025-06-22T04:28:35.090] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-06-22T04:28:35.092] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-06-22T04:28:35.095] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-06-22T21:18:11.294] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-06-22T21:18:11.302] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-06-22T21:18:11.305] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-06-23T03:44:14.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-23 03:44:14 +[2025-06-23T04:28:47.590] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-06-23T04:28:47.592] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-06-23T04:28:47.594] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-06-23T21:06:58.604] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-06-23T21:06:58.612] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-06-23T21:06:58.614] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-06-24T03:44:15.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-24 03:44:15 +[2025-06-24T04:29:26.531] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-06-24T04:29:26.534] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-06-24T04:29:26.537] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-06-24T21:16:51.296] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-06-24T21:16:51.304] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-06-24T21:16:51.306] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-06-25T03:44:16.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-25 03:44:16 +[2025-06-25T04:29:07.218] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-06-25T04:29:07.221] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-06-25T04:29:07.223] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-06-25T21:19:24.152] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-06-25T21:19:24.160] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-06-25T21:19:24.162] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-06-26T03:44:18.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-26 03:44:18 +[2025-06-26T04:30:37.302] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-06-26T04:30:37.304] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-06-26T04:30:37.307] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-06-26T20:43:40.217] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-06-26T20:43:40.224] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-06-26T20:43:40.227] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-06-27T03:44:19.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-27 03:44:19 +[2025-06-27T04:34:16.464] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-06-27T04:34:16.467] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-06-27T04:34:16.469] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-06-27T21:10:45.071] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-06-27T21:10:45.079] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-06-27T21:10:45.081] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-06-28T03:44:21.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-28 03:44:21 +[2025-06-28T04:41:19.779] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-06-28T04:41:19.781] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-06-28T04:41:19.783] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-06-28T21:19:09.482] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-06-28T21:19:09.490] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-06-28T21:19:09.492] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-06-29T03:44:22.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-29 03:44:22 +[2025-06-29T04:30:00.433] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-06-29T04:30:00.435] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-06-29T04:30:00.437] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-06-29T21:17:35.001] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-06-29T21:17:35.009] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-06-29T21:17:35.012] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-06-30T03:44:23.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-30 03:44:23 +[2025-06-30T04:31:29.727] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-06-30T04:31:29.730] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-06-30T04:31:29.732] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-06-30T21:19:28.808] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-06-30T21:19:28.814] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-06-30T21:19:28.816] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-01T03:44:25.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-01 03:44:25 +[2025-07-01T04:29:31.812] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-01T04:29:31.815] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-01T04:29:31.817] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-01T21:20:32.873] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-01T21:20:32.881] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-01T21:20:32.883] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-02T03:44:26.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-02 03:44:26 +[2025-07-02T04:29:31.383] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-02T04:29:31.385] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-02T04:29:31.387] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-02T07:28:57.798] [INFO] monitorLogs - turnLine on - (line, SETTINGS.maintenance_mode) 0 true command received from platform +[2025-07-02T07:29:17.991] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false command received from platform +[2025-07-02T07:35:48.027] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false command received from platform +[2025-07-02T07:36:49.913] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false command received from platform +[2025-07-02T07:39:23.064] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false command received from platform +[2025-07-02T07:39:35.061] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false command received from platform +[2025-07-02T15:03:55.086] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false command received from platform +[2025-07-02T21:00:02.146] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-07-02T21:00:07.516] [INFO] monitorLogs - buildTasks - params undefined +[2025-07-02T21:00:07.521] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-07-02T21:00:07.522] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-07-02T21:00:07.522] [INFO] monitorLogs - profile: { + 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 +} +[2025-07-02T21:00:07.527] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-07-02T21:00:07.528] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-07-03T03:23:00.527Z +[2025-07-02T21:00:07.529] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-07-02T19:28:00.529Z +[2025-07-02T21:00:07.530] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '5:23', name: 'luxOff' }, + { value: 1, start_time: '21:28', name: 'luxOn' } +] +[2025-07-02T21:00:07.531] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-07-02T21:00:07.532] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-07-02T21:00:07.533] [INFO] monitorLogs - profile: { + 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 +} +[2025-07-02T21:00:07.535] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-07-02T21:00:07.536] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-07-03T03:23:00.536Z +[2025-07-02T21:00:07.537] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-07-02T19:28:00.537Z +[2025-07-02T21:00:07.538] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '5:23', name: 'luxOff' }, + { value: 1, start_time: '21:28', name: 'luxOn' } +] +[2025-07-02T21:00:07.539] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-07-02T21:00:07.539] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-07-02T21:00:07.540] [INFO] monitorLogs - profile: { + 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 +} +[2025-07-02T21:00:07.542] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-07-02T21:00:07.543] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-07-03T03:23:00.543Z +[2025-07-02T21:00:07.544] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-07-02T19:28:00.543Z +[2025-07-02T21:00:07.544] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '5:23', name: 'luxOff' }, + { value: 1, start_time: '21:28', name: 'luxOn' } +] +[2025-07-02T21:00:07.545] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-07-02T21:00:07.571] [INFO] monitorLogs - tasks created: 1778 +[2025-07-02T21:00:07.574] [INFO] monitorLogs - -->FLOW bol spustený PLBJzmK1r3Gynd6OW0gKRo0e5wV4vx9bDEqNgYR8 2025-04-24 +[2025-07-02T21:00:12.589] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-02T21:18:29.561] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-02T21:18:29.564] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-02T21:18:29.567] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-03T03:00:09.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-03 03:00:09 +[2025-07-03T04:32:36.686] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-03T04:32:36.690] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-03T04:32:36.692] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-03T09:04:36.456] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-07-03T09:04:41.816] [INFO] monitorLogs - buildTasks - params undefined +[2025-07-03T09:04:41.821] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-07-03T09:04:41.822] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-07-03T09:04:41.823] [INFO] monitorLogs - profile: { + 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 +} +[2025-07-03T09:04:41.827] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-07-03T09:04:41.828] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-07-04T03:24:00.828Z +[2025-07-03T09:04:41.830] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-07-03T19:27:00.830Z +[2025-07-03T09:04:41.831] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '5:24', name: 'luxOff' }, + { value: 1, start_time: '21:27', name: 'luxOn' } +] +[2025-07-03T09:04:41.832] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-07-03T09:04:41.833] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-07-03T09:04:41.833] [INFO] monitorLogs - profile: { + 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 +} +[2025-07-03T09:04:41.836] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-07-03T09:04:41.836] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-07-04T03:24:00.836Z +[2025-07-03T09:04:41.837] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-07-03T19:27:00.837Z +[2025-07-03T09:04:41.838] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '5:24', name: 'luxOff' }, + { value: 1, start_time: '21:27', name: 'luxOn' } +] +[2025-07-03T09:04:41.839] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-07-03T09:04:41.840] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-07-03T09:04:41.840] [INFO] monitorLogs - profile: { + 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 +} +[2025-07-03T09:04:41.842] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-07-03T09:04:41.843] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-07-04T03:24:00.843Z +[2025-07-03T09:04:41.844] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-07-03T19:27:00.844Z +[2025-07-03T09:04:41.844] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '5:24', name: 'luxOff' }, + { value: 1, start_time: '21:27', name: 'luxOn' } +] +[2025-07-03T09:04:41.846] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-07-03T09:04:41.873] [INFO] monitorLogs - tasks created: 1778 +[2025-07-03T09:04:41.875] [INFO] monitorLogs - -->FLOW bol spustený PLBJzmK1r3Gynd6OW0gKRo0e5wV4vx9bDEqNgYR8 2025-04-24 +[2025-07-03T09:04:46.890] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-03T21:09:15.892] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-03T21:09:15.901] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-03T21:09:15.903] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-04T03:04:43.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-04 03:04:43 +[2025-07-04T04:47:21.475] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-04T04:47:21.479] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-04T04:47:21.482] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-04T21:16:19.103] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-04T21:16:19.111] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-04T21:16:19.113] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-05T03:04:44.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-05 03:04:44 +[2025-07-05T04:33:57.978] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-05T04:33:57.982] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-05T04:33:57.985] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-05T15:07:42.110] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-07-05T15:07:47.473] [INFO] monitorLogs - buildTasks - params undefined +[2025-07-05T15:07:47.477] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-07-05T15:07:47.478] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-07-05T15:07:47.479] [INFO] monitorLogs - profile: { + 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 +} +[2025-07-05T15:07:47.483] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-07-05T15:07:47.485] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-07-06T03:26:00.484Z +[2025-07-05T15:07:47.486] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-07-05T19:27:00.486Z +[2025-07-05T15:07:47.487] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '5:26', name: 'luxOff' }, + { value: 1, start_time: '21:27', name: 'luxOn' } +] +[2025-07-05T15:07:47.488] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-07-05T15:07:47.489] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-07-05T15:07:47.489] [INFO] monitorLogs - profile: { + 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 +} +[2025-07-05T15:07:47.492] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-07-05T15:07:47.492] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-07-06T03:26:00.492Z +[2025-07-05T15:07:47.493] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-07-05T19:27:00.493Z +[2025-07-05T15:07:47.494] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '5:26', name: 'luxOff' }, + { value: 1, start_time: '21:27', name: 'luxOn' } +] +[2025-07-05T15:07:47.495] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-07-05T15:07:47.495] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-07-05T15:07:47.496] [INFO] monitorLogs - profile: { + 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 +} +[2025-07-05T15:07:47.498] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-07-05T15:07:47.499] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-07-06T03:26:00.499Z +[2025-07-05T15:07:47.500] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-07-05T19:27:00.500Z +[2025-07-05T15:07:47.500] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '5:26', name: 'luxOff' }, + { value: 1, start_time: '21:27', name: 'luxOn' } +] +[2025-07-05T15:07:47.501] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-07-05T15:07:47.527] [INFO] monitorLogs - tasks created: 1778 +[2025-07-05T15:07:47.529] [INFO] monitorLogs - -->FLOW bol spustený PLBJzmK1r3Gynd6OW0gKRo0e5wV4vx9bDEqNgYR8 2025-04-24 +[2025-07-05T15:07:52.544] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-05T16:09:34.868] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-07-05T16:09:40.227] [INFO] monitorLogs - buildTasks - params undefined +[2025-07-05T16:09:40.232] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-07-05T16:09:40.233] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-07-05T16:09:40.233] [INFO] monitorLogs - profile: { + 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 +} +[2025-07-05T16:09:40.238] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-07-05T16:09:40.239] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-07-06T03:26:00.238Z +[2025-07-05T16:09:40.240] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-07-05T19:27:00.240Z +[2025-07-05T16:09:40.241] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '5:26', name: 'luxOff' }, + { value: 1, start_time: '21:27', name: 'luxOn' } +] +[2025-07-05T16:09:40.242] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-07-05T16:09:40.243] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-07-05T16:09:40.244] [INFO] monitorLogs - profile: { + 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 +} +[2025-07-05T16:09:40.246] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-07-05T16:09:40.247] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-07-06T03:26:00.247Z +[2025-07-05T16:09:40.248] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-07-05T19:27:00.247Z +[2025-07-05T16:09:40.248] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '5:26', name: 'luxOff' }, + { value: 1, start_time: '21:27', name: 'luxOn' } +] +[2025-07-05T16:09:40.249] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-07-05T16:09:40.250] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-07-05T16:09:40.250] [INFO] monitorLogs - profile: { + 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 +} +[2025-07-05T16:09:40.252] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-07-05T16:09:40.253] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-07-06T03:26:00.253Z +[2025-07-05T16:09:40.254] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-07-05T19:27:00.254Z +[2025-07-05T16:09:40.254] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '5:26', name: 'luxOff' }, + { value: 1, start_time: '21:27', name: 'luxOn' } +] +[2025-07-05T16:09:40.255] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-07-05T16:09:40.281] [INFO] monitorLogs - tasks created: 1778 +[2025-07-05T16:09:40.283] [INFO] monitorLogs - -->FLOW bol spustený PLBJzmK1r3Gynd6OW0gKRo0e5wV4vx9bDEqNgYR8 2025-04-24 +[2025-07-05T16:09:45.298] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-05T16:17:32.291] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-07-05T16:17:37.650] [INFO] monitorLogs - buildTasks - params undefined +[2025-07-05T16:17:37.654] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-07-05T16:17:37.655] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-07-05T16:17:37.656] [INFO] monitorLogs - profile: { + 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 +} +[2025-07-05T16:17:37.660] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-07-05T16:17:37.661] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-07-06T03:26:00.661Z +[2025-07-05T16:17:37.663] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-07-05T19:27:00.663Z +[2025-07-05T16:17:37.664] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '5:26', name: 'luxOff' }, + { value: 1, start_time: '21:27', name: 'luxOn' } +] +[2025-07-05T16:17:37.665] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-07-05T16:17:37.665] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-07-05T16:17:37.666] [INFO] monitorLogs - profile: { + 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 +} +[2025-07-05T16:17:37.668] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-07-05T16:17:37.669] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-07-06T03:26:00.669Z +[2025-07-05T16:17:37.670] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-07-05T19:27:00.670Z +[2025-07-05T16:17:37.670] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '5:26', name: 'luxOff' }, + { value: 1, start_time: '21:27', name: 'luxOn' } +] +[2025-07-05T16:17:37.672] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-07-05T16:17:37.672] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-07-05T16:17:37.673] [INFO] monitorLogs - profile: { + 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 +} +[2025-07-05T16:17:37.675] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-07-05T16:17:37.676] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-07-06T03:26:00.676Z +[2025-07-05T16:17:37.676] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-07-05T19:27:00.676Z +[2025-07-05T16:17:37.677] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '5:26', name: 'luxOff' }, + { value: 1, start_time: '21:27', name: 'luxOn' } +] +[2025-07-05T16:17:37.678] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-07-05T16:17:37.703] [INFO] monitorLogs - tasks created: 1778 +[2025-07-05T16:17:37.706] [INFO] monitorLogs - -->FLOW bol spustený PLBJzmK1r3Gynd6OW0gKRo0e5wV4vx9bDEqNgYR8 2025-04-24 +[2025-07-05T16:17:42.721] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-05T16:19:23.028] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-07-05T16:19:28.388] [INFO] monitorLogs - buildTasks - params undefined +[2025-07-05T16:19:28.393] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-07-05T16:19:28.394] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-07-05T16:19:28.394] [INFO] monitorLogs - profile: { + 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 +} +[2025-07-05T16:19:28.399] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-07-05T16:19:28.400] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-07-06T03:26:00.399Z +[2025-07-05T16:19:28.401] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-07-05T19:27:00.401Z +[2025-07-05T16:19:28.402] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '5:26', name: 'luxOff' }, + { value: 1, start_time: '21:27', name: 'luxOn' } +] +[2025-07-05T16:19:28.403] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-07-05T16:19:28.404] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-07-05T16:19:28.405] [INFO] monitorLogs - profile: { + 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 +} +[2025-07-05T16:19:28.407] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-07-05T16:19:28.408] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-07-06T03:26:00.408Z +[2025-07-05T16:19:28.409] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-07-05T19:27:00.409Z +[2025-07-05T16:19:28.409] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '5:26', name: 'luxOff' }, + { value: 1, start_time: '21:27', name: 'luxOn' } +] +[2025-07-05T16:19:28.410] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-07-05T16:19:28.411] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-07-05T16:19:28.412] [INFO] monitorLogs - profile: { + 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 +} +[2025-07-05T16:19:28.414] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-07-05T16:19:28.415] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-07-06T03:26:00.415Z +[2025-07-05T16:19:28.416] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-07-05T19:27:00.416Z +[2025-07-05T16:19:28.417] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '5:26', name: 'luxOff' }, + { value: 1, start_time: '21:27', name: 'luxOn' } +] +[2025-07-05T16:19:28.418] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-07-05T16:19:28.445] [INFO] monitorLogs - tasks created: 1778 +[2025-07-05T16:19:28.448] [INFO] monitorLogs - -->FLOW bol spustený PLBJzmK1r3Gynd6OW0gKRo0e5wV4vx9bDEqNgYR8 2025-04-24 +[2025-07-05T16:19:33.463] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-05T21:14:29.961] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-05T21:14:29.970] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-05T21:14:29.972] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-06T03:19:30.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-06 03:19:30 +[2025-07-06T04:36:25.737] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-06T04:36:25.741] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-06T04:36:25.748] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-06T20:32:32.651] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-06T20:32:32.658] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-06T20:32:32.663] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-06T22:24:29.192] [INFO] monitorLogs - turnLine on - (line, SETTINGS.maintenance_mode) 0 true command received from platform +[2025-07-06T22:25:59.428] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false command received from platform +[2025-07-07T03:19:32.037] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-07 03:19:32 +[2025-07-07T04:51:14.660] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-07T04:51:14.664] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-07T04:51:14.667] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-07T13:50:46.448] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-07-07T13:50:51.820] [INFO] monitorLogs - buildTasks - params undefined +[2025-07-07T13:50:51.824] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-07-07T13:50:51.825] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-07-07T13:50:51.826] [INFO] monitorLogs - profile: { + 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 +} +[2025-07-07T13:50:51.830] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-07-07T13:50:51.832] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-07-08T03:27:00.831Z +[2025-07-07T13:50:51.833] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-07-07T19:26:00.833Z +[2025-07-07T13:50:51.834] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '5:27', name: 'luxOff' }, + { value: 1, start_time: '21:26', name: 'luxOn' } +] +[2025-07-07T13:50:51.835] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-07-07T13:50:51.836] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-07-07T13:50:51.836] [INFO] monitorLogs - profile: { + 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 +} +[2025-07-07T13:50:51.839] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-07-07T13:50:51.840] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-07-08T03:27:00.839Z +[2025-07-07T13:50:51.841] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-07-07T19:26:00.840Z +[2025-07-07T13:50:51.841] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '5:27', name: 'luxOff' }, + { value: 1, start_time: '21:26', name: 'luxOn' } +] +[2025-07-07T13:50:51.842] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-07-07T13:50:51.843] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-07-07T13:50:51.844] [INFO] monitorLogs - profile: { + 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 +} +[2025-07-07T13:50:51.846] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-07-07T13:50:51.847] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-07-08T03:27:00.846Z +[2025-07-07T13:50:51.847] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-07-07T19:26:00.847Z +[2025-07-07T13:50:51.848] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '5:27', name: 'luxOff' }, + { value: 1, start_time: '21:26', name: 'luxOn' } +] +[2025-07-07T13:50:51.849] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-07-07T13:50:51.876] [INFO] monitorLogs - tasks created: 1778 +[2025-07-07T13:50:51.879] [INFO] monitorLogs - -->FLOW bol spustený PLBJzmK1r3Gynd6OW0gKRo0e5wV4vx9bDEqNgYR8 2025-07-08 +[2025-07-07T13:50:56.894] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-07T21:14:19.235] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-07T21:14:19.244] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-07T21:14:19.247] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-08T03:50:53.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-08 03:50:53 +[2025-07-08T04:53:20.122] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-08T04:53:20.124] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-08T04:53:20.127] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-08T20:52:31.425] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-08T20:52:31.432] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-08T20:52:31.434] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-09T03:50:54.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-09 03:50:54 +[2025-07-09T05:02:41.637] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-09T05:02:41.639] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-09T05:02:41.641] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-09T21:10:12.776] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-09T21:10:12.783] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-09T21:10:12.786] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-10T02:24:05.055] [INFO] monitorLogs - MQTT client error Error: connect ECONNREFUSED 192.168.252.1:1883 + at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1159:16) { + errno: -111, + code: 'ECONNREFUSED', + syscall: 'connect', + address: '192.168.252.1', + port: 1883 +} +[2025-07-10T03:50:55.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-10 03:50:55 +[2025-07-10T04:40:43.968] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-10T04:40:43.970] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-10T04:40:43.972] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-10T16:12:11.178] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-07-10T16:12:16.534] [INFO] monitorLogs - buildTasks - params undefined +[2025-07-10T16:12:16.539] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-07-10T16:12:16.540] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-07-10T16:12:16.541] [INFO] monitorLogs - profile: { + 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 +} +[2025-07-10T16:12:16.545] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-07-10T16:12:16.546] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-07-11T03:30:00.545Z +[2025-07-10T16:12:16.548] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-07-10T19:24:00.547Z +[2025-07-10T16:12:16.548] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '5:30', name: 'luxOff' }, + { value: 1, start_time: '21:24', name: 'luxOn' } +] +[2025-07-10T16:12:16.550] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-07-10T16:12:16.550] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-07-10T16:12:16.551] [INFO] monitorLogs - profile: { + 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 +} +[2025-07-10T16:12:16.553] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-07-10T16:12:16.554] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-07-11T03:30:00.554Z +[2025-07-10T16:12:16.555] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-07-10T19:24:00.555Z +[2025-07-10T16:12:16.556] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '5:30', name: 'luxOff' }, + { value: 1, start_time: '21:24', name: 'luxOn' } +] +[2025-07-10T16:12:16.557] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-07-10T16:12:16.557] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-07-10T16:12:16.558] [INFO] monitorLogs - profile: { + 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 +} +[2025-07-10T16:12:16.560] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-07-10T16:12:16.561] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-07-11T03:30:00.561Z +[2025-07-10T16:12:16.562] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-07-10T19:24:00.561Z +[2025-07-10T16:12:16.562] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '5:30', name: 'luxOff' }, + { value: 1, start_time: '21:24', name: 'luxOn' } +] +[2025-07-10T16:12:16.563] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-07-10T16:12:16.589] [INFO] monitorLogs - tasks created: 1778 +[2025-07-10T16:12:16.592] [INFO] monitorLogs - -->FLOW bol spustený PLBJzmK1r3Gynd6OW0gKRo0e5wV4vx9bDEqNgYR8 2025-07-08 +[2025-07-10T16:12:21.605] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-10T21:08:56.917] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-10T21:08:56.925] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-10T21:08:56.928] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-11T03:12:18.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-11 03:12:18 +[2025-07-11T04:42:38.531] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-11T04:42:38.534] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-11T04:42:38.536] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-11T21:10:47.440] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-11T21:10:47.446] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-11T21:10:47.450] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-12T03:12:19.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-12 03:12:19 +[2025-07-12T04:44:36.485] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-12T04:44:36.488] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-12T04:44:36.490] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-12T21:06:20.299] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-12T21:06:20.306] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-12T21:06:20.308] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-13T03:12:20.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-13 03:12:20 +[2025-07-13T04:44:30.533] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-13T04:44:30.537] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-13T04:44:30.539] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-13T21:08:45.908] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-13T21:08:45.915] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-13T21:08:45.917] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-14T03:12:21.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-14 03:12:21 +[2025-07-14T04:43:38.886] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-14T04:43:38.889] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-14T04:43:38.891] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-14T21:06:39.560] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-14T21:06:39.566] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-14T21:06:39.569] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-15T03:12:23.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-15 03:12:23 +[2025-07-15T04:45:53.030] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-15T04:45:53.033] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-15T04:45:53.035] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-15T15:05:52.102] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-07-15T15:05:57.473] [INFO] monitorLogs - buildTasks - params undefined +[2025-07-15T15:05:57.478] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-07-15T15:05:57.479] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-07-15T15:05:57.480] [INFO] monitorLogs - profile: { + 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 +} +[2025-07-15T15:05:57.484] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-07-15T15:05:57.485] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-07-16T03:35:00.484Z +[2025-07-15T15:05:57.487] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-07-15T19:20:00.487Z +[2025-07-15T15:05:57.487] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '5:35', name: 'luxOff' }, + { value: 1, start_time: '21:20', name: 'luxOn' } +] +[2025-07-15T15:05:57.489] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-07-15T15:05:57.490] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-07-15T15:05:57.490] [INFO] monitorLogs - profile: { + 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 +} +[2025-07-15T15:05:57.492] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-07-15T15:05:57.493] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-07-16T03:35:00.493Z +[2025-07-15T15:05:57.494] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-07-15T19:20:00.494Z +[2025-07-15T15:05:57.495] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '5:35', name: 'luxOff' }, + { value: 1, start_time: '21:20', name: 'luxOn' } +] +[2025-07-15T15:05:57.496] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-07-15T15:05:57.496] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-07-15T15:05:57.497] [INFO] monitorLogs - profile: { + 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 +} +[2025-07-15T15:05:57.499] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-07-15T15:05:57.500] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-07-16T03:35:00.500Z +[2025-07-15T15:05:57.501] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-07-15T19:20:00.500Z +[2025-07-15T15:05:57.501] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '5:35', name: 'luxOff' }, + { value: 1, start_time: '21:20', name: 'luxOn' } +] +[2025-07-15T15:05:57.502] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-07-15T15:05:57.529] [INFO] monitorLogs - tasks created: 1778 +[2025-07-15T15:05:57.532] [INFO] monitorLogs - -->FLOW bol spustený PLBJzmK1r3Gynd6OW0gKRo0e5wV4vx9bDEqNgYR8 2025-07-08 +[2025-07-15T15:06:02.546] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-15T21:01:03.664] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-15T21:01:03.673] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-15T21:01:03.676] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-16T03:05:59.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-16 03:05:59 +[2025-07-16T04:46:39.821] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-16T04:46:39.824] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-16T04:46:39.826] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-16T11:25:26.087] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-07-16T11:25:31.454] [INFO] monitorLogs - buildTasks - params undefined +[2025-07-16T11:25:31.458] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-07-16T11:25:31.459] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-07-16T11:25:31.460] [INFO] monitorLogs - profile: { + 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 +} +[2025-07-16T11:25:31.464] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-07-16T11:25:31.465] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-07-17T03:36:00.464Z +[2025-07-16T11:25:31.467] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-07-16T19:19:00.467Z +[2025-07-16T11:25:31.468] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '5:36', name: 'luxOff' }, + { value: 1, start_time: '21:19', name: 'luxOn' } +] +[2025-07-16T11:25:31.469] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-07-16T11:25:31.470] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-07-16T11:25:31.470] [INFO] monitorLogs - profile: { + 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 +} +[2025-07-16T11:25:31.473] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-07-16T11:25:31.473] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-07-17T03:36:00.473Z +[2025-07-16T11:25:31.474] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-07-16T19:19:00.474Z +[2025-07-16T11:25:31.475] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '5:36', name: 'luxOff' }, + { value: 1, start_time: '21:19', name: 'luxOn' } +] +[2025-07-16T11:25:31.476] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-07-16T11:25:31.477] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-07-16T11:25:31.477] [INFO] monitorLogs - profile: { + 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 +} +[2025-07-16T11:25:31.479] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-07-16T11:25:31.480] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-07-17T03:36:00.480Z +[2025-07-16T11:25:31.481] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-07-16T19:19:00.481Z +[2025-07-16T11:25:31.481] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '5:36', name: 'luxOff' }, + { value: 1, start_time: '21:19', name: 'luxOn' } +] +[2025-07-16T11:25:31.482] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-07-16T11:25:31.509] [INFO] monitorLogs - tasks created: 1778 +[2025-07-16T11:25:31.512] [INFO] monitorLogs - -->FLOW bol spustený PLBJzmK1r3Gynd6OW0gKRo0e5wV4vx9bDEqNgYR8 2025-07-08 +[2025-07-16T11:25:36.527] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-16T20:56:58.863] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-16T20:56:58.872] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-16T20:56:58.875] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-17T03:25:33.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-17 03:25:33 +[2025-07-17T04:54:09.827] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-17T04:54:09.830] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-17T04:54:09.832] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-17T09:05:28.193] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-07-17T09:05:33.550] [INFO] monitorLogs - buildTasks - params undefined +[2025-07-17T09:05:33.555] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-07-17T09:05:33.556] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-07-17T09:05:33.556] [INFO] monitorLogs - profile: { + 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 +} +[2025-07-17T09:05:33.561] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-07-17T09:05:33.562] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-07-18T03:37:00.561Z +[2025-07-17T09:05:33.564] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-07-17T19:18:00.563Z +[2025-07-17T09:05:33.564] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '5:37', name: 'luxOff' }, + { value: 1, start_time: '21:18', name: 'luxOn' } +] +[2025-07-17T09:05:33.565] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-07-17T09:05:33.566] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-07-17T09:05:33.567] [INFO] monitorLogs - profile: { + 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 +} +[2025-07-17T09:05:33.569] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-07-17T09:05:33.570] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-07-18T03:37:00.570Z +[2025-07-17T09:05:33.571] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-07-17T19:18:00.571Z +[2025-07-17T09:05:33.572] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '5:37', name: 'luxOff' }, + { value: 1, start_time: '21:18', name: 'luxOn' } +] +[2025-07-17T09:05:33.573] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-07-17T09:05:33.573] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-07-17T09:05:33.574] [INFO] monitorLogs - profile: { + 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 +} +[2025-07-17T09:05:33.576] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-07-17T09:05:33.577] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-07-18T03:37:00.577Z +[2025-07-17T09:05:33.577] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-07-17T19:18:00.577Z +[2025-07-17T09:05:33.578] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '5:37', name: 'luxOff' }, + { value: 1, start_time: '21:18', name: 'luxOn' } +] +[2025-07-17T09:05:33.579] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-07-17T09:05:33.605] [INFO] monitorLogs - tasks created: 1778 +[2025-07-17T09:05:33.608] [INFO] monitorLogs - -->FLOW bol spustený PLBJzmK1r3Gynd6OW0gKRo0e5wV4vx9bDEqNgYR8 2025-07-08 +[2025-07-17T09:05:38.623] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-17T20:59:41.501] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-17T20:59:41.510] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-17T20:59:41.513] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-18T03:05:35.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-18 03:05:35 +[2025-07-18T05:04:44.432] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-18T05:04:44.436] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-18T05:04:44.439] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-18T21:04:47.461] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-18T21:04:47.470] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-18T21:04:47.472] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-19T03:05:36.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-19 03:05:36 +[2025-07-19T04:55:28.571] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-19T04:55:28.580] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-19T04:55:28.582] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-19T21:03:39.654] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-19T21:03:39.663] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-19T21:03:39.665] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-20T03:05:37.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-20 03:05:37 +[2025-07-20T04:51:05.295] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-20T04:51:05.304] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-20T04:51:05.306] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-20T21:02:06.453] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-20T21:02:06.462] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-20T21:02:06.464] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-21T03:05:39.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-21 03:05:39 +[2025-07-21T04:51:30.019] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-21T04:51:30.026] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-21T04:51:30.029] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-21T20:31:24.915] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-21T20:31:24.922] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-21T20:31:24.925] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-22T03:05:40.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-22 03:05:40 +[2025-07-22T04:52:25.823] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-22T04:52:25.833] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-22T04:52:25.835] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-22T21:02:11.593] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-22T21:02:11.602] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-22T21:02:11.604] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-23T03:05:41.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-23 03:05:41 +[2025-07-23T04:52:56.721] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-23T04:52:56.731] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-23T04:52:56.733] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-23T08:17:31.117] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-07-23T08:17:36.477] [INFO] monitorLogs - buildTasks - params undefined +[2025-07-23T08:17:36.482] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-07-23T08:17:36.483] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-07-23T08:17:36.484] [INFO] monitorLogs - profile: { + 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 +} +[2025-07-23T08:17:36.488] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-07-23T08:17:36.489] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-07-24T03:44:00.488Z +[2025-07-23T08:17:36.491] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-07-23T19:12:00.490Z +[2025-07-23T08:17:36.491] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '5:44', name: 'luxOff' }, + { value: 1, start_time: '21:12', name: 'luxOn' } +] +[2025-07-23T08:17:36.493] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-07-23T08:17:36.493] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-07-23T08:17:36.494] [INFO] monitorLogs - profile: { + 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 +} +[2025-07-23T08:17:36.496] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-07-23T08:17:36.497] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-07-24T03:44:00.497Z +[2025-07-23T08:17:36.498] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-07-23T19:12:00.498Z +[2025-07-23T08:17:36.499] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '5:44', name: 'luxOff' }, + { value: 1, start_time: '21:12', name: 'luxOn' } +] +[2025-07-23T08:17:36.500] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-07-23T08:17:36.500] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-07-23T08:17:36.501] [INFO] monitorLogs - profile: { + 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 +} +[2025-07-23T08:17:36.503] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-07-23T08:17:36.504] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-07-24T03:44:00.504Z +[2025-07-23T08:17:36.505] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-07-23T19:12:00.504Z +[2025-07-23T08:17:36.505] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '5:44', name: 'luxOff' }, + { value: 1, start_time: '21:12', name: 'luxOn' } +] +[2025-07-23T08:17:36.506] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-07-23T08:17:36.532] [INFO] monitorLogs - tasks created: 1778 +[2025-07-23T08:17:36.535] [INFO] monitorLogs - -->FLOW bol spustený PLBJzmK1r3Gynd6OW0gKRo0e5wV4vx9bDEqNgYR8 2025-07-08 +[2025-07-23T08:17:41.550] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-23T21:00:26.588] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-23T21:00:26.597] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-23T21:00:26.600] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-24T03:17:38.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-24 03:17:38 +[2025-07-24T04:59:32.038] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-24T04:59:32.042] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-24T04:59:32.045] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-24T20:47:56.020] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-24T20:47:56.029] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-24T20:47:56.031] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-25T03:17:39.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-25 03:17:39 +[2025-07-25T05:01:28.221] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-25T05:01:28.230] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-25T05:01:28.232] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-25T20:47:35.356] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-25T20:47:35.364] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-25T20:47:35.366] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-26T03:17:41.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-26 03:17:41 +[2025-07-26T05:02:28.072] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-26T05:02:28.080] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-26T05:02:28.083] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-26T20:50:42.509] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-26T20:50:42.517] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-26T20:50:42.520] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-27T03:17:42.014] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-27 03:17:42 +[2025-07-27T05:03:52.922] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-27T05:03:52.926] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-27T05:03:52.928] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-27T20:40:08.386] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-27T20:40:08.395] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-27T20:40:08.397] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-28T03:17:43.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-28 03:17:43 +[2025-07-28T05:06:00.942] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-28T05:06:00.950] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-28T05:06:00.952] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-28T20:44:54.253] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-28T20:44:54.262] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-28T20:44:54.265] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-29T03:17:45.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-29 03:17:45 +[2025-07-29T05:05:15.586] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-29T05:05:15.594] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-29T05:05:15.596] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-29T12:19:39.074] [INFO] monitorLogs - MQTT client error Error: connect ECONNREFUSED 192.168.252.1:1883 + at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1159:16) { + errno: -111, + code: 'ECONNREFUSED', + syscall: 'connect', + address: '192.168.252.1', + port: 1883 +} +[2025-07-29T20:48:16.834] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-29T20:48:16.842] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-29T20:48:16.844] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-30T03:17:46.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-30 03:17:46 +[2025-07-30T05:03:38.141] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-30T05:03:38.150] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-30T05:03:38.152] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-30T20:44:15.998] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-30T20:44:16.006] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-30T20:44:16.008] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-31T03:17:47.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-31 03:17:47 +[2025-07-31T05:05:24.539] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-31T05:05:24.546] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-31T05:05:24.549] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-31T20:46:53.052] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-31T20:46:53.065] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-31T20:46:53.068] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-01T03:17:48.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-01 03:17:48 +[2025-08-01T05:05:28.714] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-01T05:05:28.718] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-01T05:05:28.721] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-01T11:22:03.289] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-08-01T11:22:08.662] [INFO] monitorLogs - buildTasks - params undefined +[2025-08-01T11:22:08.666] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-08-01T11:22:08.667] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-08-01T11:22:08.668] [INFO] monitorLogs - profile: { + 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 +} +[2025-08-01T11:22:08.672] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-08-01T11:22:08.673] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-08-02T03:55:00.673Z +[2025-08-01T11:22:08.675] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-08-01T19:01:00.674Z +[2025-08-01T11:22:08.675] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '5:55', name: 'luxOff' }, + { value: 1, start_time: '21:1', name: 'luxOn' } +] +[2025-08-01T11:22:08.677] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-08-01T11:22:08.677] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-08-01T11:22:08.678] [INFO] monitorLogs - profile: { + 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 +} +[2025-08-01T11:22:08.680] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-08-01T11:22:08.681] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-08-02T03:55:00.681Z +[2025-08-01T11:22:08.682] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-08-01T19:01:00.682Z +[2025-08-01T11:22:08.683] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '5:55', name: 'luxOff' }, + { value: 1, start_time: '21:1', name: 'luxOn' } +] +[2025-08-01T11:22:08.684] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-08-01T11:22:08.684] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-08-01T11:22:08.685] [INFO] monitorLogs - profile: { + 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 +} +[2025-08-01T11:22:08.687] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-08-01T11:22:08.688] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-08-02T03:55:00.688Z +[2025-08-01T11:22:08.688] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-08-01T19:01:00.688Z +[2025-08-01T11:22:08.689] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '5:55', name: 'luxOff' }, + { value: 1, start_time: '21:1', name: 'luxOn' } +] +[2025-08-01T11:22:08.690] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-08-01T11:22:08.716] [INFO] monitorLogs - tasks created: 1778 +[2025-08-01T11:22:08.719] [INFO] monitorLogs - -->FLOW bol spustený PLBJzmK1r3Gynd6OW0gKRo0e5wV4vx9bDEqNgYR8 2025-07-08 +[2025-08-01T11:22:13.734] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-01T20:34:28.212] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-01T20:34:28.221] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-01T20:34:28.223] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-02T03:22:10.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-02 03:22:10 +[2025-08-02T05:06:33.520] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-02T05:06:33.524] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-02T05:06:33.527] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-02T20:37:11.333] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-02T20:37:11.341] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-02T20:37:11.345] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-03T03:22:12.023] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-03 03:22:12 +[2025-08-03T05:19:26.911] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-03T05:19:26.914] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-03T05:19:26.917] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-03T20:43:09.991] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-03T20:43:09.999] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-03T20:43:10.002] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-04T03:22:13.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-04 03:22:13 +[2025-08-04T05:11:47.511] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-04T05:11:47.519] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-04T05:11:47.522] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-04T20:41:05.778] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-04T20:41:05.786] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-04T20:41:05.789] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-05T03:22:14.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-05 03:22:14 +[2025-08-05T05:15:56.361] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-05T05:15:56.365] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-05T05:15:56.367] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-05T16:12:43.107] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-08-05T16:12:48.458] [INFO] monitorLogs - buildTasks - params undefined +[2025-08-05T16:12:48.462] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-08-05T16:12:48.463] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-08-05T16:12:48.464] [INFO] monitorLogs - profile: { + 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 +} +[2025-08-05T16:12:48.468] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-08-05T16:12:48.469] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-08-06T04:01:00.468Z +[2025-08-05T16:12:48.471] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-08-05T18:55:00.471Z +[2025-08-05T16:12:48.472] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '6:1', name: 'luxOff' }, + { value: 1, start_time: '20:55', name: 'luxOn' } +] +[2025-08-05T16:12:48.474] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-08-05T16:12:48.474] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-08-05T16:12:48.475] [INFO] monitorLogs - profile: { + 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 +} +[2025-08-05T16:12:48.477] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-08-05T16:12:48.478] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-08-06T04:01:00.478Z +[2025-08-05T16:12:48.479] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-08-05T18:55:00.479Z +[2025-08-05T16:12:48.480] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '6:1', name: 'luxOff' }, + { value: 1, start_time: '20:55', name: 'luxOn' } +] +[2025-08-05T16:12:48.481] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-08-05T16:12:48.481] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-08-05T16:12:48.482] [INFO] monitorLogs - profile: { + 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 +} +[2025-08-05T16:12:48.484] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-08-05T16:12:48.485] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-08-06T04:01:00.485Z +[2025-08-05T16:12:48.485] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-08-05T18:55:00.485Z +[2025-08-05T16:12:48.486] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '6:1', name: 'luxOff' }, + { value: 1, start_time: '20:55', name: 'luxOn' } +] +[2025-08-05T16:12:48.487] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-08-05T16:12:48.515] [INFO] monitorLogs - tasks created: 1778 +[2025-08-05T16:12:48.517] [INFO] monitorLogs - -->FLOW bol spustený PLBJzmK1r3Gynd6OW0gKRo0e5wV4vx9bDEqNgYR8 2025-07-08 +[2025-08-05T16:12:53.532] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-05T20:37:46.089] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-05T20:37:46.097] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-05T20:37:46.099] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-06T03:12:50.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-06 03:12:50 +[2025-08-06T05:14:09.326] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-06T05:14:09.335] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-06T05:14:09.337] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-06T12:53:22.054] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-08-06T12:53:27.410] [INFO] monitorLogs - buildTasks - params undefined +[2025-08-06T12:53:27.415] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-08-06T12:53:27.416] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-08-06T12:53:27.417] [INFO] monitorLogs - profile: { + 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 +} +[2025-08-06T12:53:27.422] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-08-06T12:53:27.424] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-08-07T04:02:00.423Z +[2025-08-06T12:53:27.425] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-08-06T18:53:00.425Z +[2025-08-06T12:53:27.426] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '6:2', name: 'luxOff' }, + { value: 1, start_time: '20:53', name: 'luxOn' } +] +[2025-08-06T12:53:27.427] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-08-06T12:53:27.428] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-08-06T12:53:27.428] [INFO] monitorLogs - profile: { + 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 +} +[2025-08-06T12:53:27.431] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-08-06T12:53:27.431] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-08-07T04:02:00.431Z +[2025-08-06T12:53:27.432] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-08-06T18:53:00.432Z +[2025-08-06T12:53:27.433] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '6:2', name: 'luxOff' }, + { value: 1, start_time: '20:53', name: 'luxOn' } +] +[2025-08-06T12:53:27.434] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-08-06T12:53:27.435] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-08-06T12:53:27.435] [INFO] monitorLogs - profile: { + 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 +} +[2025-08-06T12:53:27.437] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-08-06T12:53:27.438] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-08-07T04:02:00.438Z +[2025-08-06T12:53:27.439] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-08-06T18:53:00.439Z +[2025-08-06T12:53:27.440] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '6:2', name: 'luxOff' }, + { value: 1, start_time: '20:53', name: 'luxOn' } +] +[2025-08-06T12:53:27.441] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-08-06T12:53:27.468] [INFO] monitorLogs - tasks created: 1778 +[2025-08-06T12:53:27.471] [INFO] monitorLogs - -->FLOW bol spustený PLBJzmK1r3Gynd6OW0gKRo0e5wV4vx9bDEqNgYR8 2025-08-08 +[2025-08-06T12:53:32.486] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-06T20:36:18.729] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-06T20:36:18.738] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-06T20:36:18.741] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-07T03:53:29.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-07 03:53:29 +[2025-08-07T05:16:35.634] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-07T05:16:35.638] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-07T05:16:35.640] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-07T20:37:38.948] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-07T20:37:38.956] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-07T20:37:38.959] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-08T03:53:30.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-08 03:53:30 +[2025-08-08T05:17:14.744] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-08T05:17:14.753] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-08T05:17:14.756] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-08T20:34:07.800] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-08T20:34:07.807] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-08T20:34:07.809] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-09T03:53:32.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-09 03:53:32 +[2025-08-09T05:16:06.489] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-09T05:16:06.493] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-09T05:16:06.496] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-09T20:34:57.194] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-09T20:34:57.202] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-09T20:34:57.204] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-10T03:53:33.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-10 03:53:33 +[2025-08-10T05:17:06.447] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-10T05:17:06.455] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-10T05:17:06.458] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-10T20:32:18.552] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-10T20:32:18.560] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-10T20:32:18.563] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-11T03:53:35.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-11 03:53:35 +[2025-08-11T05:19:48.118] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-11T05:19:48.122] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-11T05:19:48.125] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-11T20:31:55.141] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-11T20:31:55.149] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-11T20:31:55.151] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-12T03:53:36.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-12 03:53:36 +[2025-08-12T05:19:30.994] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-12T05:19:30.998] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-12T05:19:31.000] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-12T20:28:56.784] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-12T20:28:56.792] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-12T20:28:56.794] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-13T03:53:37.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-13 03:53:37 +[2025-08-13T05:22:19.368] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-13T05:22:19.372] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-13T05:22:19.374] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-13T20:28:12.153] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-13T20:28:12.161] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-13T20:28:12.163] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-14T03:53:39.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-14 03:53:39 +[2025-08-14T05:23:06.542] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-14T05:23:06.546] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-14T05:23:06.548] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-14T20:24:37.643] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-14T20:24:37.651] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-14T20:24:37.653] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-15T03:53:40.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-15 03:53:40 +[2025-08-15T05:25:27.207] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-15T05:25:27.211] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-15T05:25:27.213] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-15T20:21:27.262] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-15T20:21:27.268] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-15T20:21:27.270] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-16T03:53:42.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-16 03:53:42 +[2025-08-16T05:27:45.036] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-16T05:27:45.040] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-16T05:27:45.042] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-16T20:19:25.709] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-16T20:19:25.717] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-16T20:19:25.719] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-17T03:53:43.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-17 03:53:43 +[2025-08-17T05:30:20.017] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-17T05:30:20.021] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-17T05:30:20.024] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-17T20:18:55.461] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-17T20:18:55.469] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-17T20:18:55.472] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-18T03:53:44.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-18 03:53:44 +[2025-08-18T05:28:33.513] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-18T05:28:33.517] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-18T05:28:33.519] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-18T20:17:24.064] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-18T20:17:24.072] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-18T20:17:24.074] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-19T03:53:46.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-19 03:53:46 +[2025-08-19T05:30:06.286] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-19T05:30:06.289] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-19T05:30:06.292] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-19T20:17:51.497] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-19T20:17:51.506] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-19T20:17:51.508] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-20T03:53:47.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-20 03:53:47 +[2025-08-20T05:31:33.466] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-20T05:31:33.470] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-20T05:31:33.472] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-20T20:11:07.338] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-20T20:11:07.345] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-20T20:11:07.347] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-21T03:53:48.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-21 03:53:48 +[2025-08-21T05:39:45.307] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-21T05:39:45.311] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-21T05:39:45.313] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-21T19:54:38.800] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-21T19:54:38.808] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-21T19:54:38.811] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-22T03:53:50.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-22 03:53:50 +[2025-08-22T05:45:07.988] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-22T05:45:07.992] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-22T05:45:07.995] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-22T20:09:13.799] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-22T20:09:13.807] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-22T20:09:13.809] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-23T03:53:51.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-23 03:53:51 +[2025-08-23T05:41:47.170] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-23T05:41:47.174] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-23T05:41:47.177] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-23T20:08:10.515] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-23T20:08:10.523] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-23T20:08:10.525] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-24T03:53:52.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-24 03:53:52 +[2025-08-24T05:40:07.444] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-24T05:40:07.448] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-24T05:40:07.451] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-24T20:07:48.318] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-24T20:07:48.325] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-24T20:07:48.328] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-25T03:53:53.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-25 03:53:53 +[2025-08-25T05:43:40.059] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-25T05:43:40.067] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-25T05:43:40.070] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-25T20:02:11.762] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-25T20:02:11.769] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-25T20:02:11.772] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-26T03:53:55.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-26 03:53:55 +[2025-08-26T05:41:23.378] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-26T05:41:23.382] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-26T05:41:23.385] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-26T20:00:49.091] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-26T20:00:49.099] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-26T20:00:49.101] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-27T03:53:56.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-27 03:53:56 +[2025-08-27T05:43:46.707] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-27T05:43:46.711] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-27T05:43:46.714] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-27T19:58:33.645] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-27T19:58:33.653] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-27T19:58:33.655] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-28T03:53:57.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-28 03:53:57 +[2025-08-28T05:44:15.741] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-28T05:44:15.750] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-28T05:44:15.752] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-28T19:57:06.735] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-28T19:57:06.743] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-28T19:57:06.745] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-29T03:53:59.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-29 03:53:59 +[2025-08-29T05:47:48.709] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-29T05:47:48.713] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-29T05:47:48.715] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-29T19:45:08.324] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-29T19:45:08.332] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-29T19:45:08.334] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-30T03:54:00.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-30 03:54:00 +[2025-08-30T05:47:29.175] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-30T05:47:29.178] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-30T05:47:29.181] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-30T19:39:48.997] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-30T19:39:49.005] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-30T19:39:49.007] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-31T03:54:01.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-31 03:54:01 +[2025-08-31T06:02:44.979] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-31T06:02:44.987] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-31T06:02:44.990] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-31T19:52:56.185] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-31T19:52:56.193] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-31T19:52:56.195] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-01T03:54:03.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-01 03:54:03 +[2025-09-01T05:53:13.718] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-01T05:53:13.721] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-01T05:53:13.724] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-01T19:48:33.112] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-01T19:48:33.119] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-01T19:48:33.122] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-02T03:54:04.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-02 03:54:04 +[2025-09-02T05:49:49.935] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-02T05:49:49.943] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-02T05:49:49.945] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-02T19:40:05.866] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-02T19:40:05.873] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-02T19:40:05.876] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-03T03:54:05.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-03 03:54:05 +[2025-09-03T05:58:26.872] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-03T05:58:26.876] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-03T05:58:26.878] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-03T17:33:44.229] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-09-03T17:33:49.599] [INFO] monitorLogs - buildTasks - params undefined +[2025-09-03T17:33:49.603] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-09-03T17:33:49.605] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-09-03T17:33:49.605] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-03T17:33:49.612] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-03T17:33:49.613] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-09-04T04:41:00.612Z +[2025-09-03T17:33:49.614] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-09-03T18:01:00.614Z +[2025-09-03T17:33:49.615] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '6:41', name: 'luxOff' }, + { value: 1, start_time: '20:1', name: 'luxOn' } +] +[2025-09-03T17:33:49.616] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-09-03T17:33:49.617] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-09-03T17:33:49.618] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-03T17:33:49.621] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-03T17:33:49.622] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-09-04T04:41:00.621Z +[2025-09-03T17:33:49.622] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-09-03T18:01:00.622Z +[2025-09-03T17:33:49.623] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '6:41', name: 'luxOff' }, + { value: 1, start_time: '20:1', name: 'luxOn' } +] +[2025-09-03T17:33:49.624] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-09-03T17:33:49.625] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-09-03T17:33:49.625] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-03T17:33:49.628] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-03T17:33:49.629] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-09-04T04:41:00.629Z +[2025-09-03T17:33:49.630] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-09-03T18:01:00.630Z +[2025-09-03T17:33:49.631] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '6:41', name: 'luxOff' }, + { value: 1, start_time: '20:1', name: 'luxOn' } +] +[2025-09-03T17:33:49.633] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-09-03T17:33:49.654] [INFO] monitorLogs - tasks created: 267 +[2025-09-03T17:33:49.657] [INFO] monitorLogs - -->FLOW bol spustený PLBJzmK1r3Gynd6OW0gKRo0e5wV4vx9bDEqNgYR8 2025-08-08 +[2025-09-03T17:33:54.660] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-03T17:43:59.189] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-09-03T17:44:04.546] [INFO] monitorLogs - buildTasks - params undefined +[2025-09-03T17:44:04.551] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-09-03T17:44:04.552] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-09-03T17:44:04.553] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-03T17:44:04.559] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-03T17:44:04.560] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-09-04T04:41:00.560Z +[2025-09-03T17:44:04.562] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-09-03T18:01:00.562Z +[2025-09-03T17:44:04.563] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '6:41', name: 'luxOff' }, + { value: 1, start_time: '20:1', name: 'luxOn' } +] +[2025-09-03T17:44:04.564] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-09-03T17:44:04.565] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-09-03T17:44:04.566] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-03T17:44:04.569] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-03T17:44:04.570] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-09-04T04:41:00.570Z +[2025-09-03T17:44:04.571] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-09-03T18:01:00.571Z +[2025-09-03T17:44:04.572] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '6:41', name: 'luxOff' }, + { value: 1, start_time: '20:1', name: 'luxOn' } +] +[2025-09-03T17:44:04.573] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-09-03T17:44:04.573] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-09-03T17:44:04.574] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-03T17:44:04.577] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-03T17:44:04.577] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-09-04T04:41:00.577Z +[2025-09-03T17:44:04.578] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-09-03T18:01:00.578Z +[2025-09-03T17:44:04.579] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '6:41', name: 'luxOff' }, + { value: 1, start_time: '20:1', name: 'luxOn' } +] +[2025-09-03T17:44:04.580] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-09-03T17:44:04.606] [INFO] monitorLogs - tasks created: 1779 +[2025-09-03T17:44:04.609] [INFO] monitorLogs - -->FLOW bol spustený PLBJzmK1r3Gynd6OW0gKRo0e5wV4vx9bDEqNgYR8 2025-08-08 +[2025-09-03T17:44:09.621] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-03T19:44:50.973] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-03T19:44:50.979] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-03T19:44:50.982] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-04T03:44:06.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-04 03:44:06 +[2025-09-04T05:54:36.003] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-04T05:54:36.009] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-04T05:54:36.012] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-04T19:45:02.126] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-04T19:45:02.132] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-04T19:45:02.135] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-05T03:44:08.066] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-05 03:44:08 +[2025-09-05T05:56:53.646] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-05T05:56:53.652] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-05T05:56:53.655] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-05T19:41:03.379] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-05T19:41:03.385] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-05T19:41:03.388] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-06T03:44:09.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-06 03:44:09 +[2025-09-06T06:09:48.370] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-06T06:09:48.376] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-06T06:09:48.378] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-06T18:06:11.099] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-09-06T18:06:16.495] [INFO] monitorLogs - buildTasks - params undefined +[2025-09-06T18:06:16.501] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-09-06T18:06:16.502] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-09-06T18:06:16.502] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-06T18:06:16.507] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-06T18:06:16.508] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-09-07T04:46:00.507Z +[2025-09-06T18:06:16.510] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-09-06T17:55:00.510Z +[2025-09-06T18:06:16.511] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '6:46', name: 'luxOff' }, + { value: 1, start_time: '19:55', name: 'luxOn' } +] +[2025-09-06T18:06:16.512] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-09-06T18:06:16.513] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-09-06T18:06:16.514] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-06T18:06:16.516] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-06T18:06:16.517] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-09-07T04:46:00.517Z +[2025-09-06T18:06:16.518] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-09-06T17:55:00.518Z +[2025-09-06T18:06:16.519] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '6:46', name: 'luxOff' }, + { value: 1, start_time: '19:55', name: 'luxOn' } +] +[2025-09-06T18:06:16.520] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-09-06T18:06:16.521] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-09-06T18:06:16.521] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-06T18:06:16.524] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-06T18:06:16.524] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-09-07T04:46:00.524Z +[2025-09-06T18:06:16.526] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-09-06T17:55:00.525Z +[2025-09-06T18:06:16.526] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '6:46', name: 'luxOff' }, + { value: 1, start_time: '19:55', name: 'luxOn' } +] +[2025-09-06T18:06:16.527] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-09-06T18:06:16.531] [INFO] monitorLogs - tasks created: 266 +[2025-09-06T18:06:16.533] [INFO] monitorLogs - -->FLOW bol spustený PLBJzmK1r3Gynd6OW0gKRo0e5wV4vx9bDEqNgYR8 2025-08-08 +[2025-09-06T18:06:21.537] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-06T19:39:21.843] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-06T19:39:21.846] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-06T19:39:21.848] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-07T03:06:17.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-07 03:06:17 +[2025-09-07T05:57:11.580] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-07T05:57:11.587] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-07T05:57:11.590] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-07T19:35:07.757] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-07T19:35:07.765] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-07T19:35:07.768] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-07T23:19:51.334] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-09-07T23:19:56.717] [INFO] monitorLogs - buildTasks - params undefined +[2025-09-07T23:19:56.724] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-09-07T23:19:56.725] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-09-07T23:19:56.726] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-07T23:19:56.731] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-07T23:19:56.732] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-09-08T04:47:00.731Z +[2025-09-07T23:19:56.734] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-09-08T17:53:00.734Z +[2025-09-07T23:19:56.735] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '6:47', name: 'luxOff' }, + { value: 1, start_time: '19:53', name: 'luxOn' } +] +[2025-09-07T23:19:56.737] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-09-07T23:19:56.738] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-09-07T23:19:56.738] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-07T23:19:56.741] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-07T23:19:56.742] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-09-08T04:47:00.742Z +[2025-09-07T23:19:56.743] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-09-08T17:53:00.743Z +[2025-09-07T23:19:56.743] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '6:47', name: 'luxOff' }, + { value: 1, start_time: '19:53', name: 'luxOn' } +] +[2025-09-07T23:19:56.745] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-09-07T23:19:56.746] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-09-07T23:19:56.746] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-07T23:19:56.749] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-07T23:19:56.750] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-09-08T04:47:00.750Z +[2025-09-07T23:19:56.751] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-09-08T17:53:00.751Z +[2025-09-07T23:19:56.751] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '6:47', name: 'luxOff' }, + { value: 1, start_time: '19:53', name: 'luxOn' } +] +[2025-09-07T23:19:56.752] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-09-07T23:19:56.756] [INFO] monitorLogs - tasks created: 266 +[2025-09-07T23:19:56.759] [INFO] monitorLogs - -->FLOW bol spustený PLBJzmK1r3Gynd6OW0gKRo0e5wV4vx9bDEqNgYR8 2025-08-08 +[2025-09-07T23:20:01.763] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-08T03:19:59.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-08 03:19:59 +[2025-09-08T05:59:23.774] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-08T05:59:23.779] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-08T05:59:23.782] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-08T15:34:15.256] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-09-08T15:34:20.624] [INFO] monitorLogs - buildTasks - params undefined +[2025-09-08T15:34:20.628] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-09-08T15:34:20.629] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-09-08T15:34:20.630] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-08T15:34:20.634] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-08T15:34:20.636] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-09-09T04:48:00.635Z +[2025-09-08T15:34:20.637] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-09-08T17:51:00.637Z +[2025-09-08T15:34:20.638] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '6:48', name: 'luxOff' }, + { value: 1, start_time: '19:51', name: 'luxOn' } +] +[2025-09-08T15:34:20.639] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-09-08T15:34:20.640] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-09-08T15:34:20.640] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-08T15:34:20.643] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-08T15:34:20.644] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-09-09T04:48:00.643Z +[2025-09-08T15:34:20.644] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-09-08T17:51:00.644Z +[2025-09-08T15:34:20.645] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '6:48', name: 'luxOff' }, + { value: 1, start_time: '19:51', name: 'luxOn' } +] +[2025-09-08T15:34:20.646] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-09-08T15:34:20.647] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-09-08T15:34:20.647] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-08T15:34:20.650] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-08T15:34:20.650] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-09-09T04:48:00.650Z +[2025-09-08T15:34:20.651] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-09-08T17:51:00.651Z +[2025-09-08T15:34:20.652] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '6:48', name: 'luxOff' }, + { value: 1, start_time: '19:51', name: 'luxOn' } +] +[2025-09-08T15:34:20.653] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-09-08T15:34:20.679] [INFO] monitorLogs - tasks created: 1778 +[2025-09-08T15:34:20.681] [INFO] monitorLogs - -->FLOW bol spustený PLBJzmK1r3Gynd6OW0gKRo0e5wV4vx9bDEqNgYR8 2025-08-08 +[2025-09-08T15:34:25.695] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-08T19:36:11.981] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-08T19:36:11.987] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-08T19:36:11.990] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-09T03:34:22.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-09 03:34:22 +[2025-09-09T06:01:04.305] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-09T06:01:04.312] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-09T06:01:04.314] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-09T19:29:00.440] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-09T19:29:00.446] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-09T19:29:00.448] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-10T03:34:23.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-10 03:34:23 +[2025-09-10T06:05:06.389] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-10T06:05:06.396] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-10T06:05:06.398] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-10T09:14:57.896] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-09-10T09:15:03.256] [INFO] monitorLogs - buildTasks - params undefined +[2025-09-10T09:15:03.261] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-09-10T09:15:03.262] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-09-10T09:15:03.262] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-10T09:15:03.267] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-10T09:15:03.268] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-09-11T04:51:00.267Z +[2025-09-10T09:15:03.269] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-09-10T17:46:00.269Z +[2025-09-10T09:15:03.270] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '6:51', name: 'luxOff' }, + { value: 1, start_time: '19:46', name: 'luxOn' } +] +[2025-09-10T09:15:03.271] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-09-10T09:15:03.272] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-09-10T09:15:03.273] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-10T09:15:03.275] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-10T09:15:03.276] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-09-11T04:51:00.276Z +[2025-09-10T09:15:03.277] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-09-10T17:46:00.276Z +[2025-09-10T09:15:03.277] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '6:51', name: 'luxOff' }, + { value: 1, start_time: '19:46', name: 'luxOn' } +] +[2025-09-10T09:15:03.278] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-09-10T09:15:03.279] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-09-10T09:15:03.279] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-10T09:15:03.282] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-10T09:15:03.282] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-09-11T04:51:00.282Z +[2025-09-10T09:15:03.283] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-09-10T17:46:00.283Z +[2025-09-10T09:15:03.284] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '6:51', name: 'luxOff' }, + { value: 1, start_time: '19:46', name: 'luxOn' } +] +[2025-09-10T09:15:03.285] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-09-10T09:15:03.311] [INFO] monitorLogs - tasks created: 1778 +[2025-09-10T09:15:03.314] [INFO] monitorLogs - -->FLOW bol spustený PLBJzmK1r3Gynd6OW0gKRo0e5wV4vx9bDEqNgYR8 2025-08-08 +[2025-09-10T09:15:08.328] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-10T16:27:37.332] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-09-10T16:27:42.695] [INFO] monitorLogs - buildTasks - params undefined +[2025-09-10T16:27:42.700] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-09-10T16:27:42.701] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-09-10T16:27:42.701] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-10T16:27:42.706] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-10T16:27:42.707] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-09-11T04:51:00.706Z +[2025-09-10T16:27:42.709] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-09-10T17:46:00.708Z +[2025-09-10T16:27:42.709] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '6:51', name: 'luxOff' }, + { value: 1, start_time: '19:46', name: 'luxOn' } +] +[2025-09-10T16:27:42.711] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-09-10T16:27:42.711] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-09-10T16:27:42.712] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-10T16:27:42.715] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-10T16:27:42.715] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-09-11T04:51:00.715Z +[2025-09-10T16:27:42.716] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-09-10T17:46:00.716Z +[2025-09-10T16:27:42.717] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '6:51', name: 'luxOff' }, + { value: 1, start_time: '19:46', name: 'luxOn' } +] +[2025-09-10T16:27:42.718] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-09-10T16:27:42.718] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-09-10T16:27:42.719] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-10T16:27:42.721] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-10T16:27:42.722] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-09-11T04:51:00.722Z +[2025-09-10T16:27:42.723] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-09-10T17:46:00.723Z +[2025-09-10T16:27:42.723] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '6:51', name: 'luxOff' }, + { value: 1, start_time: '19:46', name: 'luxOn' } +] +[2025-09-10T16:27:42.724] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-09-10T16:27:42.752] [INFO] monitorLogs - tasks created: 1778 +[2025-09-10T16:27:42.754] [INFO] monitorLogs - -->FLOW bol spustený PLBJzmK1r3Gynd6OW0gKRo0e5wV4vx9bDEqNgYR8 2025-08-08 +[2025-09-10T16:27:47.769] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-10T19:18:09.819] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-10T19:18:09.825] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-10T19:18:09.828] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-11T03:27:44.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-11 03:27:44 +[2025-09-11T06:12:12.223] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-11T06:12:12.229] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-11T06:12:12.231] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-11T19:29:46.430] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-11T19:29:46.436] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-11T19:29:46.438] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-12T03:27:45.062] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-12 03:27:45 +[2025-09-12T06:07:25.063] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-12T06:07:25.069] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-12T06:07:25.071] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-12T19:16:24.474] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-12T19:16:24.479] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-12T19:16:24.481] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-13T03:27:46.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-13 03:27:46 +[2025-09-13T06:25:18.729] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-13T06:25:18.734] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-13T06:25:18.736] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-13T19:19:08.147] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-13T19:19:08.153] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-13T19:19:08.155] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-14T03:27:48.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-14 03:27:48 +[2025-09-14T06:21:56.079] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-14T06:21:56.086] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-14T06:21:56.088] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-14T19:22:36.196] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-14T19:22:36.202] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-14T19:22:36.204] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-14T22:41:57.355] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-09-14T22:42:02.711] [INFO] monitorLogs - buildTasks - params undefined +[2025-09-14T22:42:02.716] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-09-14T22:42:02.717] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-09-14T22:42:02.718] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-14T22:42:02.722] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-14T22:42:02.723] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-09-15T04:57:00.723Z +[2025-09-14T22:42:02.725] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-09-15T17:38:00.725Z +[2025-09-14T22:42:02.726] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '6:57', name: 'luxOff' }, + { value: 1, start_time: '19:38', name: 'luxOn' } +] +[2025-09-14T22:42:02.727] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-09-14T22:42:02.728] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-09-14T22:42:02.728] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-14T22:42:02.731] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-14T22:42:02.732] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-09-15T04:57:00.732Z +[2025-09-14T22:42:02.733] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-09-15T17:38:00.733Z +[2025-09-14T22:42:02.733] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '6:57', name: 'luxOff' }, + { value: 1, start_time: '19:38', name: 'luxOn' } +] +[2025-09-14T22:42:02.734] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-09-14T22:42:02.735] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-09-14T22:42:02.736] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-14T22:42:02.738] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-14T22:42:02.738] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-09-15T04:57:00.738Z +[2025-09-14T22:42:02.739] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-09-15T17:38:00.739Z +[2025-09-14T22:42:02.740] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '6:57', name: 'luxOff' }, + { value: 1, start_time: '19:38', name: 'luxOn' } +] +[2025-09-14T22:42:02.741] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-09-14T22:42:02.766] [INFO] monitorLogs - tasks created: 1778 +[2025-09-14T22:42:02.769] [INFO] monitorLogs - -->FLOW bol spustený PLBJzmK1r3Gynd6OW0gKRo0e5wV4vx9bDEqNgYR8 2025-08-08 +[2025-09-14T22:42:07.780] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-15T03:42:04.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-15 03:42:04 +[2025-09-15T06:08:46.320] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-15T06:08:46.325] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-15T06:08:46.328] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-15T19:21:07.121] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-15T19:21:07.127] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-15T19:21:07.129] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-16T03:42:05.042] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-16 03:42:05 +[2025-09-16T06:27:52.328] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-16T06:27:52.335] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-16T06:27:52.337] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-16T19:15:32.430] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-16T19:15:32.436] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-16T19:15:32.438] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-17T03:42:06.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-17 03:42:06 +[2025-09-17T06:17:01.491] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-17T06:17:01.497] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-17T06:17:01.499] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-17T19:16:31.396] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-17T19:16:31.402] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-17T19:16:31.404] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-17T19:37:12.787] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-09-17T19:37:18.141] [INFO] monitorLogs - buildTasks - params undefined +[2025-09-17T19:37:18.146] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-09-17T19:37:18.147] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-09-17T19:37:18.148] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-17T19:37:18.152] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-17T19:37:18.153] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-09-18T05:01:00.152Z +[2025-09-17T19:37:18.155] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-09-18T17:32:00.154Z +[2025-09-17T19:37:18.155] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:1', name: 'luxOff' }, + { value: 1, start_time: '19:32', name: 'luxOn' } +] +[2025-09-17T19:37:18.156] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-09-17T19:37:18.157] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-09-17T19:37:18.158] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-17T19:37:18.160] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-17T19:37:18.161] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-09-18T05:01:00.161Z +[2025-09-17T19:37:18.162] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-09-18T17:32:00.162Z +[2025-09-17T19:37:18.163] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:1', name: 'luxOff' }, + { value: 1, start_time: '19:32', name: 'luxOn' } +] +[2025-09-17T19:37:18.164] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-09-17T19:37:18.164] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-09-17T19:37:18.165] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-17T19:37:18.167] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-17T19:37:18.168] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-09-18T05:01:00.168Z +[2025-09-17T19:37:18.169] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-09-18T17:32:00.169Z +[2025-09-17T19:37:18.169] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:1', name: 'luxOff' }, + { value: 1, start_time: '19:32', name: 'luxOn' } +] +[2025-09-17T19:37:18.170] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-09-17T19:37:18.197] [INFO] monitorLogs - tasks created: 1778 +[2025-09-17T19:37:18.199] [INFO] monitorLogs - -->FLOW bol spustený PLBJzmK1r3Gynd6OW0gKRo0e5wV4vx9bDEqNgYR8 2025-08-08 +[2025-09-17T19:37:23.213] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-18T03:37:20.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-18 03:37:20 +[2025-09-18T06:20:06.081] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-18T06:20:06.086] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-18T06:20:06.088] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-18T19:15:55.598] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-18T19:15:55.604] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-18T19:15:55.606] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-19T03:37:21.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-19 03:37:21 +[2025-09-19T06:14:12.838] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-19T06:14:12.843] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-19T06:14:12.846] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-19T11:03:15.178] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-09-19T11:03:20.530] [INFO] monitorLogs - buildTasks - params undefined +[2025-09-19T11:03:20.534] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-09-19T11:03:20.535] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-09-19T11:03:20.536] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-19T11:03:20.540] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-19T11:03:20.541] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-09-20T05:04:00.540Z +[2025-09-19T11:03:20.543] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-09-19T17:27:00.542Z +[2025-09-19T11:03:20.543] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:4', name: 'luxOff' }, + { value: 1, start_time: '19:27', name: 'luxOn' } +] +[2025-09-19T11:03:20.544] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-09-19T11:03:20.545] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-09-19T11:03:20.546] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-19T11:03:20.548] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-19T11:03:20.549] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-09-20T05:04:00.549Z +[2025-09-19T11:03:20.550] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-09-19T17:27:00.550Z +[2025-09-19T11:03:20.551] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:4', name: 'luxOff' }, + { value: 1, start_time: '19:27', name: 'luxOn' } +] +[2025-09-19T11:03:20.552] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-09-19T11:03:20.552] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-09-19T11:03:20.553] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-19T11:03:20.555] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-19T11:03:20.556] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-09-20T05:04:00.556Z +[2025-09-19T11:03:20.557] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-09-19T17:27:00.556Z +[2025-09-19T11:03:20.557] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:4', name: 'luxOff' }, + { value: 1, start_time: '19:27', name: 'luxOn' } +] +[2025-09-19T11:03:20.558] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-09-19T11:03:20.585] [INFO] monitorLogs - tasks created: 1778 +[2025-09-19T11:03:20.588] [INFO] monitorLogs - -->FLOW bol spustený PLBJzmK1r3Gynd6OW0gKRo0e5wV4vx9bDEqNgYR8 2025-08-08 +[2025-09-19T11:03:25.602] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-19T19:12:06.485] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-19T19:12:06.491] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-19T19:12:06.493] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-20T03:03:22.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-20 03:03:22 +[2025-09-20T06:14:18.733] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-20T06:14:18.740] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-20T06:14:18.742] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-20T19:11:24.245] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-20T19:11:24.251] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-20T19:11:24.253] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-21T01:29:28.145] [INFO] monitorLogs - MQTT client error Error: connect ECONNREFUSED 192.168.252.1:1883 + at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1159:16) { + errno: -111, + code: 'ECONNREFUSED', + syscall: 'connect', + address: '192.168.252.1', + port: 1883 +} +[2025-09-21T03:03:23.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-21 03:03:23 +[2025-09-21T06:16:44.066] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-21T06:16:44.073] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-21T06:16:44.078] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-21T17:55:48.117] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-09-21T17:55:53.503] [INFO] monitorLogs - buildTasks - params undefined +[2025-09-21T17:55:53.508] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-09-21T17:55:53.509] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-09-21T17:55:53.510] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-21T17:55:53.515] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-21T17:55:53.516] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-09-22T05:07:00.515Z +[2025-09-21T17:55:53.518] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-09-21T17:23:00.517Z +[2025-09-21T17:55:53.519] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:7', name: 'luxOff' }, + { value: 1, start_time: '19:23', name: 'luxOn' } +] +[2025-09-21T17:55:53.520] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-09-21T17:55:53.521] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-09-21T17:55:53.522] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-21T17:55:53.524] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-21T17:55:53.525] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-09-22T05:07:00.525Z +[2025-09-21T17:55:53.526] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-09-21T17:23:00.526Z +[2025-09-21T17:55:53.527] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:7', name: 'luxOff' }, + { value: 1, start_time: '19:23', name: 'luxOn' } +] +[2025-09-21T17:55:53.528] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-09-21T17:55:53.529] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-09-21T17:55:53.529] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-21T17:55:53.532] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-21T17:55:53.533] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-09-22T05:07:00.533Z +[2025-09-21T17:55:53.534] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-09-21T17:23:00.533Z +[2025-09-21T17:55:53.534] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:7', name: 'luxOff' }, + { value: 1, start_time: '19:23', name: 'luxOn' } +] +[2025-09-21T17:55:53.535] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-09-21T17:55:53.551] [INFO] monitorLogs - tasks created: 1778 +[2025-09-21T17:55:53.554] [INFO] monitorLogs - -->FLOW bol spustený PLBJzmK1r3Gynd6OW0gKRo0e5wV4vx9bDEqNgYR8 2025-08-08 +[2025-09-21T17:55:58.568] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-21T19:07:22.082] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-21T19:07:22.090] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-21T19:07:22.093] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-22T03:55:56.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-22 03:55:56 +[2025-09-22T06:19:14.857] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-22T06:19:14.865] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-22T06:19:14.867] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-22T19:02:03.317] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-22T19:02:03.325] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-22T19:02:03.327] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-23T03:55:57.059] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-23 03:55:57 +[2025-09-23T06:25:40.429] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-23T06:25:40.435] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-23T06:25:40.437] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-23T12:44:08.124] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-09-23T12:44:13.511] [INFO] monitorLogs - buildTasks - params undefined +[2025-09-23T12:44:13.516] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-09-23T12:44:13.517] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-09-23T12:44:13.517] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-23T12:44:13.521] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-23T12:44:13.523] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-09-24T05:09:00.522Z +[2025-09-23T12:44:13.524] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-09-23T17:19:00.524Z +[2025-09-23T12:44:13.525] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:9', name: 'luxOff' }, + { value: 1, start_time: '19:19', name: 'luxOn' } +] +[2025-09-23T12:44:13.526] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-09-23T12:44:13.527] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-09-23T12:44:13.528] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-23T12:44:13.530] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-23T12:44:13.531] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-09-24T05:09:00.531Z +[2025-09-23T12:44:13.532] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-09-23T17:19:00.532Z +[2025-09-23T12:44:13.532] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:9', name: 'luxOff' }, + { value: 1, start_time: '19:19', name: 'luxOn' } +] +[2025-09-23T12:44:13.533] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-09-23T12:44:13.534] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-09-23T12:44:13.535] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-23T12:44:13.537] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-23T12:44:13.537] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-09-24T05:09:00.537Z +[2025-09-23T12:44:13.538] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-09-23T17:19:00.538Z +[2025-09-23T12:44:13.539] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:9', name: 'luxOff' }, + { value: 1, start_time: '19:19', name: 'luxOn' } +] +[2025-09-23T12:44:13.540] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-09-23T12:44:13.567] [INFO] monitorLogs - tasks created: 1778 +[2025-09-23T12:44:13.569] [INFO] monitorLogs - -->FLOW bol spustený PLBJzmK1r3Gynd6OW0gKRo0e5wV4vx9bDEqNgYR8 2025-08-08 +[2025-09-23T12:44:18.583] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-23T14:36:14.271] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-09-23T14:36:19.626] [INFO] monitorLogs - buildTasks - params undefined +[2025-09-23T14:36:19.631] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-09-23T14:36:19.632] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-09-23T14:36:19.633] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-23T14:36:19.637] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-23T14:36:19.639] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-09-24T05:09:00.638Z +[2025-09-23T14:36:19.640] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-09-23T17:19:00.640Z +[2025-09-23T14:36:19.641] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:9', name: 'luxOff' }, + { value: 1, start_time: '19:19', name: 'luxOn' } +] +[2025-09-23T14:36:19.642] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-09-23T14:36:19.643] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-09-23T14:36:19.643] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-23T14:36:19.646] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-23T14:36:19.646] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-09-24T05:09:00.646Z +[2025-09-23T14:36:19.647] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-09-23T17:19:00.647Z +[2025-09-23T14:36:19.648] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:9', name: 'luxOff' }, + { value: 1, start_time: '19:19', name: 'luxOn' } +] +[2025-09-23T14:36:19.649] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-09-23T14:36:19.650] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-09-23T14:36:19.650] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-23T14:36:19.652] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-23T14:36:19.653] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-09-24T05:09:00.653Z +[2025-09-23T14:36:19.654] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-09-23T17:19:00.654Z +[2025-09-23T14:36:19.654] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:9', name: 'luxOff' }, + { value: 1, start_time: '19:19', name: 'luxOn' } +] +[2025-09-23T14:36:19.655] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-09-23T14:36:19.682] [INFO] monitorLogs - tasks created: 1778 +[2025-09-23T14:36:19.684] [INFO] monitorLogs - -->FLOW bol spustený PLBJzmK1r3Gynd6OW0gKRo0e5wV4vx9bDEqNgYR8 2025-08-08 +[2025-09-23T14:36:24.698] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-23T18:52:24.280] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-23T18:52:24.289] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-23T18:52:24.291] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-24T03:36:20.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-24 03:36:20 +[2025-09-24T06:39:53.147] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-24T06:39:53.153] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-24T06:39:53.155] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-24T18:50:34.258] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-24T18:50:34.266] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-24T18:50:34.269] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-25T03:36:21.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-25 03:36:21 +[2025-09-25T06:40:34.626] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-25T06:40:34.632] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-25T06:40:34.635] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-25T11:37:54.253] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-09-25T11:37:59.655] [INFO] monitorLogs - buildTasks - params undefined +[2025-09-25T11:37:59.660] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-09-25T11:37:59.661] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-09-25T11:37:59.662] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-25T11:37:59.666] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-25T11:37:59.668] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-09-26T05:12:00.667Z +[2025-09-25T11:37:59.670] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-09-25T17:14:00.669Z +[2025-09-25T11:37:59.670] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:12', name: 'luxOff' }, + { value: 1, start_time: '19:14', name: 'luxOn' } +] +[2025-09-25T11:37:59.672] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-09-25T11:37:59.673] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-09-25T11:37:59.673] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-25T11:37:59.676] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-25T11:37:59.677] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-09-26T05:12:00.677Z +[2025-09-25T11:37:59.678] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-09-25T17:14:00.678Z +[2025-09-25T11:37:59.678] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:12', name: 'luxOff' }, + { value: 1, start_time: '19:14', name: 'luxOn' } +] +[2025-09-25T11:37:59.680] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-09-25T11:37:59.681] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-09-25T11:37:59.681] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-25T11:37:59.684] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-25T11:37:59.685] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-09-26T05:12:00.684Z +[2025-09-25T11:37:59.685] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-09-25T17:14:00.685Z +[2025-09-25T11:37:59.686] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:12', name: 'luxOff' }, + { value: 1, start_time: '19:14', name: 'luxOn' } +] +[2025-09-25T11:37:59.687] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-09-25T11:37:59.703] [INFO] monitorLogs - tasks created: 1778 +[2025-09-25T11:37:59.705] [INFO] monitorLogs - -->FLOW bol spustený PLBJzmK1r3Gynd6OW0gKRo0e5wV4vx9bDEqNgYR8 2025-08-08 +[2025-09-25T11:38:04.720] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-25T15:17:16.534] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-09-25T15:17:21.879] [INFO] monitorLogs - buildTasks - params undefined +[2025-09-25T15:17:21.884] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-09-25T15:17:21.885] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-09-25T15:17:21.885] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-25T15:17:21.890] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-25T15:17:21.891] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-09-26T05:12:00.890Z +[2025-09-25T15:17:21.892] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-09-25T17:14:00.892Z +[2025-09-25T15:17:21.893] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:12', name: 'luxOff' }, + { value: 1, start_time: '19:14', name: 'luxOn' } +] +[2025-09-25T15:17:21.894] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-09-25T15:17:21.895] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-09-25T15:17:21.896] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-25T15:17:21.898] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-25T15:17:21.899] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-09-26T05:12:00.899Z +[2025-09-25T15:17:21.900] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-09-25T17:14:00.900Z +[2025-09-25T15:17:21.900] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:12', name: 'luxOff' }, + { value: 1, start_time: '19:14', name: 'luxOn' } +] +[2025-09-25T15:17:21.901] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-09-25T15:17:21.902] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-09-25T15:17:21.903] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-25T15:17:21.905] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-25T15:17:21.906] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-09-26T05:12:00.905Z +[2025-09-25T15:17:21.906] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-09-25T17:14:00.906Z +[2025-09-25T15:17:21.907] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:12', name: 'luxOff' }, + { value: 1, start_time: '19:14', name: 'luxOn' } +] +[2025-09-25T15:17:21.908] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-09-25T15:17:21.935] [INFO] monitorLogs - tasks created: 1778 +[2025-09-25T15:17:21.938] [INFO] monitorLogs - -->FLOW bol spustený PLBJzmK1r3Gynd6OW0gKRo0e5wV4vx9bDEqNgYR8 2025-08-08 +[2025-09-25T15:17:26.952] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-25T18:40:02.834] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-25T18:40:02.840] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-25T18:40:02.843] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-26T03:17:24.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-26 03:17:24 +[2025-09-26T06:38:35.022] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-26T06:38:35.028] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-26T06:38:35.031] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-26T18:55:06.023] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-26T18:55:06.030] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-26T18:55:06.032] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-27T03:17:25.059] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-27 03:17:25 +[2025-09-27T06:35:33.380] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-27T06:35:33.386] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-27T06:35:33.388] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-27T18:55:04.633] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-27T18:55:04.639] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-27T18:55:04.641] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-28T03:17:26.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-28 03:17:26 +[2025-09-28T06:34:23.717] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-28T06:34:23.723] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-28T06:34:23.726] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-28T18:54:33.807] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-28T18:54:33.813] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-28T18:54:33.815] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-29T03:17:27.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-29 03:17:27 +[2025-09-29T06:29:05.978] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-29T06:29:05.982] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-29T06:29:05.984] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-29T18:51:00.139] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-29T18:51:00.142] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-29T18:51:00.144] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-30T03:17:28.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-30 03:17:28 +[2025-09-30T06:30:09.070] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-30T06:30:09.076] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-30T06:30:09.078] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-30T18:49:36.463] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-30T18:49:36.469] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-30T18:49:36.471] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-01T03:17:30.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-01 03:17:30 +[2025-10-01T06:37:03.837] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-01T06:37:03.844] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-01T06:37:03.846] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-01T18:46:54.426] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-01T18:46:54.432] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-01T18:46:54.434] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-02T03:17:31.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-02 03:17:31 +[2025-10-02T06:32:34.084] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-02T06:32:34.090] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-02T06:32:34.092] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-02T18:46:06.611] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-02T18:46:06.617] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-02T18:46:06.619] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-03T03:17:32.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-03 03:17:32 +[2025-10-03T06:34:47.922] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-03T06:34:47.927] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-03T06:34:47.929] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-03T14:35:40.728] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-03T14:35:46.094] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-03T14:35:46.099] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-03T14:35:46.100] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-03T14:35:46.101] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-03T14:35:46.105] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-03T14:35:46.106] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-10-04T05:24:00.105Z +[2025-10-03T14:35:46.108] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-10-03T16:58:00.107Z +[2025-10-03T14:35:46.109] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:24', name: 'luxOff' }, + { value: 1, start_time: '18:58', name: 'luxOn' } +] +[2025-10-03T14:35:46.111] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-10-03T14:35:46.112] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-03T14:35:46.112] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-03T14:35:46.115] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-03T14:35:46.115] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-10-04T05:24:00.115Z +[2025-10-03T14:35:46.116] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-10-03T16:58:00.116Z +[2025-10-03T14:35:46.117] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:24', name: 'luxOff' }, + { value: 1, start_time: '18:58', name: 'luxOn' } +] +[2025-10-03T14:35:46.118] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-10-03T14:35:46.118] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-03T14:35:46.119] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-03T14:35:46.121] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-03T14:35:46.122] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-10-04T05:24:00.122Z +[2025-10-03T14:35:46.122] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-10-03T16:58:00.122Z +[2025-10-03T14:35:46.123] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:24', name: 'luxOff' }, + { value: 1, start_time: '18:58', name: 'luxOn' } +] +[2025-10-03T14:35:46.124] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-10-03T14:35:46.149] [INFO] monitorLogs - tasks created: 1778 +[2025-10-03T14:35:46.152] [INFO] monitorLogs - -->FLOW bol spustený PLBJzmK1r3Gynd6OW0gKRo0e5wV4vx9bDEqNgYR8 2025-08-08 +[2025-10-03T14:35:51.166] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-03T15:42:11.623] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-03T15:42:16.970] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-03T15:42:16.975] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-03T15:42:16.976] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-03T15:42:16.977] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-03T15:42:16.981] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-03T15:42:16.983] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-10-04T05:24:00.982Z +[2025-10-03T15:42:16.984] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-10-03T16:58:00.984Z +[2025-10-03T15:42:16.985] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:24', name: 'luxOff' }, + { value: 1, start_time: '18:58', name: 'luxOn' } +] +[2025-10-03T15:42:16.986] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-10-03T15:42:16.987] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-03T15:42:16.987] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-03T15:42:16.990] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-03T15:42:16.991] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-10-04T05:24:00.990Z +[2025-10-03T15:42:16.991] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-10-03T16:58:00.991Z +[2025-10-03T15:42:16.992] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:24', name: 'luxOff' }, + { value: 1, start_time: '18:58', name: 'luxOn' } +] +[2025-10-03T15:42:16.993] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-10-03T15:42:16.994] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-03T15:42:16.994] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-03T15:42:16.997] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-03T15:42:16.997] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-10-04T05:24:00.997Z +[2025-10-03T15:42:16.998] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-10-03T16:58:00.998Z +[2025-10-03T15:42:16.999] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:24', name: 'luxOff' }, + { value: 1, start_time: '18:58', name: 'luxOn' } +] +[2025-10-03T15:42:17.000] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-10-03T15:42:17.027] [INFO] monitorLogs - tasks created: 1778 +[2025-10-03T15:42:17.030] [INFO] monitorLogs - -->FLOW bol spustený PLBJzmK1r3Gynd6OW0gKRo0e5wV4vx9bDEqNgYR8 2025-08-08 +[2025-10-03T15:42:22.042] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-03T18:42:36.289] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-03T18:42:36.296] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-03T18:42:36.299] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-04T03:42:19.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-04 03:42:19 +[2025-10-04T06:36:50.215] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-04T06:36:50.218] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-04T06:36:50.221] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-04T18:31:20.710] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-04T18:31:20.716] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-04T18:31:20.718] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-05T03:42:20.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-05 03:42:20 +[2025-10-05T06:39:53.596] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-05T06:39:53.602] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-05T06:39:53.604] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-05T18:35:05.060] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-05T18:35:05.062] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-05T18:35:05.064] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-06T03:42:21.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-06 03:42:21 +[2025-10-06T06:51:14.163] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-06T06:51:14.167] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-06T06:51:14.169] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-06T18:25:36.908] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-06T18:25:36.912] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-06T18:25:36.914] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-07T03:42:22.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-07 03:42:22 +[2025-10-07T06:45:18.947] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-07T06:45:18.953] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-07T06:45:18.955] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-07T18:33:46.558] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-07T18:33:46.564] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-07T18:33:46.566] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-08T03:42:24.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-08 03:42:24 +[2025-10-08T06:42:20.332] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-08T06:42:20.338] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-08T06:42:20.340] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-08T18:30:16.462] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-08T18:30:16.468] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-08T18:30:16.470] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-09T03:42:25.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-09 03:42:25 +[2025-10-09T06:58:08.565] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-09T06:58:08.572] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-09T06:58:08.574] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-09T12:07:01.184] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-09T12:07:06.541] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-09T12:07:06.546] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-09T12:07:06.547] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-09T12:07:06.548] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-09T12:07:06.552] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T12:07:06.553] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-10-10T05:32:00.553Z +[2025-10-09T12:07:06.555] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-10-09T16:45:00.555Z +[2025-10-09T12:07:06.555] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T12:07:06.557] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-10-09T12:07:06.558] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-09T12:07:06.558] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-09T12:07:06.561] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T12:07:06.561] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-10-10T05:32:00.561Z +[2025-10-09T12:07:06.562] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-10-09T16:45:00.562Z +[2025-10-09T12:07:06.563] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T12:07:06.564] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-10-09T12:07:06.565] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-09T12:07:06.565] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-09T12:07:06.567] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T12:07:06.568] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-10-10T05:32:00.568Z +[2025-10-09T12:07:06.569] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-10-09T16:45:00.569Z +[2025-10-09T12:07:06.569] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T12:07:06.570] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-10-09T12:07:06.597] [INFO] monitorLogs - tasks created: 1778 +[2025-10-09T12:07:06.600] [INFO] monitorLogs - -->FLOW bol spustený PLBJzmK1r3Gynd6OW0gKRo0e5wV4vx9bDEqNgYR8 2025-08-08 +[2025-10-09T12:07:11.612] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-09T16:30:16.782] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-09T16:30:22.167] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-09T16:30:22.172] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-09T16:30:22.173] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-09T16:30:22.174] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-09T16:30:22.178] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T16:30:22.180] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-10-10T05:32:00.179Z +[2025-10-09T16:30:22.181] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-10-09T16:45:00.181Z +[2025-10-09T16:30:22.182] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T16:30:22.183] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-10-09T16:30:22.184] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-09T16:30:22.185] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-09T16:30:22.188] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T16:30:22.189] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-10-10T05:32:00.189Z +[2025-10-09T16:30:22.190] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-10-09T16:45:00.190Z +[2025-10-09T16:30:22.190] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T16:30:22.191] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-10-09T16:30:22.192] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-09T16:30:22.192] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-09T16:30:22.195] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T16:30:22.195] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-10-10T05:32:00.195Z +[2025-10-09T16:30:22.196] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-10-09T16:45:00.196Z +[2025-10-09T16:30:22.196] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T16:30:22.198] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-10-09T16:30:22.224] [INFO] monitorLogs - tasks created: 1778 +[2025-10-09T16:30:22.227] [INFO] monitorLogs - -->FLOW bol spustený PLBJzmK1r3Gynd6OW0gKRo0e5wV4vx9bDEqNgYR8 2025-08-08 +[2025-10-09T16:30:27.241] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-09T16:31:03.822] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-09T16:31:09.173] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-09T16:31:09.178] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-09T16:31:09.179] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-09T16:31:09.180] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-09T16:31:09.184] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T16:31:09.186] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-10-10T05:32:00.185Z +[2025-10-09T16:31:09.187] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-10-09T16:45:00.187Z +[2025-10-09T16:31:09.188] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T16:31:09.189] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-10-09T16:31:09.190] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-09T16:31:09.190] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-09T16:31:09.193] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T16:31:09.193] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-10-10T05:32:00.193Z +[2025-10-09T16:31:09.194] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-10-09T16:45:00.194Z +[2025-10-09T16:31:09.195] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T16:31:09.196] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-10-09T16:31:09.196] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-09T16:31:09.197] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-09T16:31:09.199] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T16:31:09.200] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-10-10T05:32:00.200Z +[2025-10-09T16:31:09.200] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-10-09T16:45:00.200Z +[2025-10-09T16:31:09.201] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T16:31:09.202] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-10-09T16:31:09.229] [INFO] monitorLogs - tasks created: 1778 +[2025-10-09T16:31:09.232] [INFO] monitorLogs - -->FLOW bol spustený PLBJzmK1r3Gynd6OW0gKRo0e5wV4vx9bDEqNgYR8 2025-08-08 +[2025-10-09T16:31:14.245] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-09T16:32:03.153] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-09T16:32:08.540] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-09T16:32:08.546] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-09T16:32:08.548] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-09T16:32:08.548] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-09T16:32:08.553] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T16:32:08.555] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-10-10T05:32:00.554Z +[2025-10-09T16:32:08.557] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-10-09T16:45:00.556Z +[2025-10-09T16:32:08.557] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T16:32:08.559] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-10-09T16:32:08.559] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-09T16:32:08.560] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-09T16:32:08.563] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T16:32:08.564] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-10-10T05:32:00.564Z +[2025-10-09T16:32:08.565] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-10-09T16:45:00.564Z +[2025-10-09T16:32:08.565] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T16:32:08.567] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-10-09T16:32:08.567] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-09T16:32:08.568] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-09T16:32:08.571] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T16:32:08.571] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-10-10T05:32:00.571Z +[2025-10-09T16:32:08.572] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-10-09T16:45:00.572Z +[2025-10-09T16:32:08.572] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T16:32:08.573] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-10-09T16:32:08.589] [INFO] monitorLogs - tasks created: 1778 +[2025-10-09T16:32:08.592] [INFO] monitorLogs - -->FLOW bol spustený PLBJzmK1r3Gynd6OW0gKRo0e5wV4vx9bDEqNgYR8 2025-08-08 +[2025-10-09T16:32:13.606] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-09T16:32:54.727] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-09T16:33:00.098] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-09T16:33:00.103] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-09T16:33:00.104] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-09T16:33:00.104] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-09T16:33:00.108] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T16:33:00.110] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-10-10T05:32:00.109Z +[2025-10-09T16:33:00.111] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-10-09T16:45:00.111Z +[2025-10-09T16:33:00.112] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T16:33:00.113] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-10-09T16:33:00.114] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-09T16:33:00.115] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-09T16:33:00.117] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T16:33:00.118] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-10-10T05:32:00.118Z +[2025-10-09T16:33:00.119] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-10-09T16:45:00.119Z +[2025-10-09T16:33:00.119] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T16:33:00.120] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-10-09T16:33:00.121] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-09T16:33:00.122] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-09T16:33:00.124] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T16:33:00.124] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-10-10T05:32:00.124Z +[2025-10-09T16:33:00.125] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-10-09T16:45:00.125Z +[2025-10-09T16:33:00.126] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T16:33:00.127] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-10-09T16:33:00.153] [INFO] monitorLogs - tasks created: 1778 +[2025-10-09T16:33:00.156] [INFO] monitorLogs - -->FLOW bol spustený PLBJzmK1r3Gynd6OW0gKRo0e5wV4vx9bDEqNgYR8 2025-08-08 +[2025-10-09T16:33:05.167] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-09T18:26:48.166] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-09T18:26:48.173] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-09T18:26:48.175] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-09T19:10:07.344] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-09T19:10:12.728] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-09T19:10:12.733] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-09T19:10:12.734] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-09T19:10:12.735] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-09T19:10:12.739] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T19:10:12.741] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-10-10T05:32:00.740Z +[2025-10-09T19:10:12.742] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-10-10T16:45:00.742Z +[2025-10-09T19:10:12.744] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T19:10:12.745] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-10-09T19:10:12.746] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-09T19:10:12.746] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-09T19:10:12.749] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T19:10:12.750] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-10-10T05:32:00.750Z +[2025-10-09T19:10:12.751] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-10-10T16:45:00.751Z +[2025-10-09T19:10:12.752] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T19:10:12.753] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-10-09T19:10:12.754] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-09T19:10:12.754] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-09T19:10:12.757] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T19:10:12.758] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-10-10T05:32:00.757Z +[2025-10-09T19:10:12.758] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-10-10T16:45:00.758Z +[2025-10-09T19:10:12.759] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T19:10:12.760] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-10-09T19:10:12.776] [INFO] monitorLogs - tasks created: 1778 +[2025-10-09T19:10:12.779] [INFO] monitorLogs - -->FLOW bol spustený PLBJzmK1r3Gynd6OW0gKRo0e5wV4vx9bDEqNgYR8 2025-08-08 +[2025-10-09T19:10:17.794] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-10T03:10:14.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-10 03:10:14 +[2025-10-10T06:56:15.568] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-10T06:56:15.573] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-10T06:56:15.575] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-10T18:21:46.656] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-10T18:21:46.661] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-10T18:21:46.664] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-11T03:10:15.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-11 03:10:15 +[2025-10-11T06:56:44.513] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-11T06:56:44.519] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-11T06:56:44.521] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-11T18:22:16.173] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-11T18:22:16.180] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-11T18:22:16.182] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-12T03:10:17.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-12 03:10:17 +[2025-10-12T06:55:44.136] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-12T06:55:44.141] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-12T06:55:44.143] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-12T18:21:28.990] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-12T18:21:28.997] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-12T18:21:28.999] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-13T03:10:18.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-13 03:10:18 +[2025-10-13T06:49:52.597] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-13T06:49:52.603] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-13T06:49:52.605] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-13T18:25:08.194] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-13T18:25:08.201] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-13T18:25:08.203] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-14T03:10:19.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-14 03:10:19 +[2025-10-14T06:50:50.847] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-14T06:50:50.853] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-14T06:50:50.856] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-14T18:15:04.153] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-14T18:15:04.160] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-14T18:15:04.162] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-14T23:55:44.750] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-14T23:55:50.112] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-14T23:55:50.117] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-14T23:55:50.118] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-14T23:55:50.118] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-14T23:55:50.123] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-14T23:55:50.124] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-10-15T05:40:00.123Z +[2025-10-14T23:55:50.126] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-10-15T16:35:00.125Z +[2025-10-14T23:55:50.126] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:40', name: 'luxOff' }, + { value: 1, start_time: '18:35', name: 'luxOn' } +] +[2025-10-14T23:55:50.128] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-10-14T23:55:50.128] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-14T23:55:50.129] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-14T23:55:50.132] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-14T23:55:50.132] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-10-15T05:40:00.132Z +[2025-10-14T23:55:50.133] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-10-15T16:35:00.133Z +[2025-10-14T23:55:50.134] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:40', name: 'luxOff' }, + { value: 1, start_time: '18:35', name: 'luxOn' } +] +[2025-10-14T23:55:50.135] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-10-14T23:55:50.136] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-14T23:55:50.136] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-14T23:55:50.138] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-14T23:55:50.139] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-10-15T05:40:00.139Z +[2025-10-14T23:55:50.140] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-10-15T16:35:00.140Z +[2025-10-14T23:55:50.141] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:40', name: 'luxOff' }, + { value: 1, start_time: '18:35', name: 'luxOn' } +] +[2025-10-14T23:55:50.143] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-10-14T23:55:50.169] [INFO] monitorLogs - tasks created: 1778 +[2025-10-14T23:55:50.172] [INFO] monitorLogs - -->FLOW bol spustený PLBJzmK1r3Gynd6OW0gKRo0e5wV4vx9bDEqNgYR8 2025-10-08 +[2025-10-14T23:55:55.186] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-14T23:56:44.744] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-14T23:56:50.098] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-14T23:56:50.103] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-14T23:56:50.104] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-14T23:56:50.105] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-14T23:56:50.109] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-14T23:56:50.111] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-10-15T05:40:00.110Z +[2025-10-14T23:56:50.112] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-10-15T16:35:00.112Z +[2025-10-14T23:56:50.113] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:40', name: 'luxOff' }, + { value: 1, start_time: '18:35', name: 'luxOn' } +] +[2025-10-14T23:56:50.114] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-10-14T23:56:50.115] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-14T23:56:50.116] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-14T23:56:50.118] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-14T23:56:50.119] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-10-15T05:40:00.118Z +[2025-10-14T23:56:50.120] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-10-15T16:35:00.119Z +[2025-10-14T23:56:50.120] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:40', name: 'luxOff' }, + { value: 1, start_time: '18:35', name: 'luxOn' } +] +[2025-10-14T23:56:50.121] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-10-14T23:56:50.122] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-14T23:56:50.122] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-14T23:56:50.125] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-14T23:56:50.125] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-10-15T05:40:00.125Z +[2025-10-14T23:56:50.126] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-10-15T16:35:00.126Z +[2025-10-14T23:56:50.127] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:40', name: 'luxOff' }, + { value: 1, start_time: '18:35', name: 'luxOn' } +] +[2025-10-14T23:56:50.128] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-10-14T23:56:50.155] [INFO] monitorLogs - tasks created: 1778 +[2025-10-14T23:56:50.157] [INFO] monitorLogs - -->FLOW bol spustený PLBJzmK1r3Gynd6OW0gKRo0e5wV4vx9bDEqNgYR8 2025-10-08 +[2025-10-14T23:56:55.170] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-15T03:56:52.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-15 03:56:52 +[2025-10-15T06:58:28.540] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-15T06:58:28.547] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-15T06:58:28.549] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-15T08:29:25.067] [INFO] monitorLogs - turnLine on - (line, SETTINGS.maintenance_mode) 0 true command received from platform +[2025-10-15T08:29:32.101] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false command received from platform +[2025-10-15T08:29:41.061] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false command received from platform +[2025-10-15T08:29:51.286] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false command received from platform +[2025-10-15T08:29:56.100] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false command received from platform +[2025-10-15T08:30:11.790] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false command received from platform +[2025-10-15T18:13:32.743] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-15T18:13:32.749] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-15T18:13:32.751] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor diff --git a/RVO16/package-lock.json b/RVO16/package-lock.json new file mode 100755 index 0000000..3c5c1ba --- /dev/null +++ b/RVO16/package-lock.json @@ -0,0 +1,2139 @@ +{ + "name": "emptyproject", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "emptyproject", + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "bitwise": "^2.1.0", + "easy-crc": "0.0.2", + "jsmodbus": "^4.0.6", + "log4js": "^6.3.0", + "moment": "^2.30.1", + "mqtt": "^4.2.6", + "nodemailer": "^6.9.7", + "serialport": "^9.2.8", + "total.js": "^3.4.13" + } + }, + "node_modules/@serialport/binding-abstract": { + "version": "9.2.3", + "resolved": "https://registry.npmjs.org/@serialport/binding-abstract/-/binding-abstract-9.2.3.tgz", + "integrity": "sha512-cQs9tbIlG3P0IrOWyVirqlhWuJ7Ms2Zh9m2108z6Y5UW/iVj6wEOiW8EmK9QX9jmJXYllE7wgGgvVozP5oCj3w==", + "dependencies": { + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/binding-mock": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/binding-mock/-/binding-mock-9.2.4.tgz", + "integrity": "sha512-dpEhACCs44oQhh6ajJfJdvQdK38Vq0N4W6iD/gdplglDCK7qXRQCMUjJIeKdS/HSEiWkC3bwumUhUufdsOyT4g==", + "dependencies": { + "@serialport/binding-abstract": "9.2.3", + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/bindings": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/@serialport/bindings/-/bindings-9.2.8.tgz", + "integrity": "sha512-hSLxTe0tADZ3LMMGwvEJWOC/TaFQTyPeFalUCsJ1lSQ0k6bPF04JwrtB/C81GetmDBTNRY0GlD0SNtKCc7Dr5g==", + "hasInstallScript": true, + "dependencies": { + "@serialport/binding-abstract": "9.2.3", + "@serialport/parser-readline": "9.2.4", + "bindings": "^1.5.0", + "debug": "^4.3.2", + "nan": "^2.15.0", + "prebuild-install": "^7.0.0" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-byte-length": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-byte-length/-/parser-byte-length-9.2.4.tgz", + "integrity": "sha512-sQD/iw4ZMU3xW9PLi0/GlvU6Y623jGeWecbMkO7izUo/6P7gtfv1c9ikd5h0kwL8AoAOpQA1lxdHIKox+umBUg==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-cctalk": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-cctalk/-/parser-cctalk-9.2.4.tgz", + "integrity": "sha512-T4TU5vQMwmo9AB3gQLFDWbfJXlW5jd9guEsB/nqKjFHTv0FXPdZ7DQ2TpSp8RnHWxU3GX6kYTaDO20BKzc8GPQ==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-delimiter": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-delimiter/-/parser-delimiter-9.2.4.tgz", + "integrity": "sha512-4nvTAoYAgkxFiXrkI+3CA49Yd43CODjeszh89EK+I9c8wOZ+etZduRCzINYPiy26g7zO+GRAb9FoPCsY+sYcbQ==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-inter-byte-timeout": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-inter-byte-timeout/-/parser-inter-byte-timeout-9.2.4.tgz", + "integrity": "sha512-SOAdvr0oBQIOCXX198hiTlxs4JTKg9j5piapw5tNq52fwDOWdbYrFneT/wN04UTMKaDrJuEvXq6T4rv4j7nJ5A==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-readline": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-readline/-/parser-readline-9.2.4.tgz", + "integrity": "sha512-Z1/qrZTQUVhNSJP1hd9YfDvq0o7d87rNwAjjRKbVpa7Qi51tG5BnKt43IV3NFMyBlVcRe0rnIb3tJu57E0SOwg==", + "dependencies": { + "@serialport/parser-delimiter": "9.2.4" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-ready": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-ready/-/parser-ready-9.2.4.tgz", + "integrity": "sha512-Pyi94Itjl6qAURwIZr/gmZpMAyTmKXThm6vL5DoAWGQjcRHWB0gwv2TY2v7N+mQLJYUKU3cMnvnATXxHm7xjxw==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-regex": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-regex/-/parser-regex-9.2.4.tgz", + "integrity": "sha512-sI/cVvPOYz+Dbv4ZdnW16qAwvXiFf/1pGASQdbveRTlgJDdz7sRNlCBifzfTN2xljwvCTZYqiudKvDdC1TepRQ==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/stream": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/stream/-/stream-9.2.4.tgz", + "integrity": "sha512-bLye8Ub4vUFQGmkh8qEqehr7SE7EJs2yDs0h9jzuL5oKi+F34CFmWkEErO8GAOQ8YNn7p6b3GxUgs+0BrHHDZQ==", + "dependencies": { + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "node_modules/are-we-there-yet": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", + "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/base64-js": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", + "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==" + }, + "node_modules/bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "dependencies": { + "file-uri-to-path": "1.0.0" + } + }, + "node_modules/bitwise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/bitwise/-/bitwise-2.1.0.tgz", + "integrity": "sha512-XKgAhMXCh4H/3oNwAHAsAO0iC89s9cOiumgYwSHjSobGWxYjv62YhkL9QEdvGP151xypCtMlAfKK79GEcd2eRQ==" + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/bl/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/buffer": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz", + "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==", + "dependencies": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + }, + "node_modules/buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" + }, + "node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, + "node_modules/code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/commist": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/commist/-/commist-1.1.0.tgz", + "integrity": "sha512-rraC8NXWOEjhADbZe9QBNzLAN5Q3fsTPQtBV+fEVj6xKIgDgNiEVE6ZNfHpZOqfQ21YUzfVNUXLOEZquYvQPPg==", + "dependencies": { + "leven": "^2.1.0", + "minimist": "^1.1.0" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "node_modules/concat-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", + "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", + "engines": [ + "node >= 6.0" + ], + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.0.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/concat-stream/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" + }, + "node_modules/core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "node_modules/crc": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/crc/-/crc-3.4.0.tgz", + "integrity": "sha512-ycVC2+4/DLgXXq7QweYi2znhqDuZz6P5TQXnkQo8v15XY/5p/IWeZwsSE31Ifo8w15b8TWLsqhXOjXyilHuQxw==" + }, + "node_modules/date-format": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.11.tgz", + "integrity": "sha512-VS20KRyorrbMCQmpdl2hg5KaOUsda1RbnsJg461FfrcyCUg+pkd0b40BSW4niQyTheww4DBXQnS7HwSrKkipLw==", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" + }, + "node_modules/detect-libc": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz", + "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==", + "engines": { + "node": ">=8" + } + }, + "node_modules/duplexify": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.2.tgz", + "integrity": "sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw==", + "dependencies": { + "end-of-stream": "^1.4.1", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1", + "stream-shift": "^1.0.0" + } + }, + "node_modules/duplexify/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/easy-crc": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/easy-crc/-/easy-crc-0.0.2.tgz", + "integrity": "sha512-h6eqIdhJRe0p271/xZJbM/0klCi13mW5IB7ZEzEGH11yV4QXWAkD4yPErz0fXdhFrd6sZ4Q1k5Iky2kMsMNePw==" + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" + }, + "node_modules/flatted": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", + "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==" + }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, + "node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "node_modules/gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha512-14x4kjc6lkD3ltw589k0NrPD6cCNTD6CWoVUNpB85+DrtONoZn+Rug6xZU5RvSC4+TZPxA5AnBibQYAvZn41Hg==", + "dependencies": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "node_modules/github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==" + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" + }, + "node_modules/has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" + }, + "node_modules/help-me": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/help-me/-/help-me-3.0.0.tgz", + "integrity": "sha512-hx73jClhyk910sidBB7ERlnhMlFsJJIBqSVMFDwPN8o2v9nmp5KgLq1Xz1Bf1fCMMZ6mPrX159iG0VLy/fPMtQ==", + "dependencies": { + "glob": "^7.1.6", + "readable-stream": "^3.6.0" + } + }, + "node_modules/help-me/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, + "node_modules/is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==", + "dependencies": { + "number-is-nan": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "node_modules/js-sdsl": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz", + "integrity": "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/js-sdsl" + } + }, + "node_modules/jsmodbus": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/jsmodbus/-/jsmodbus-4.0.6.tgz", + "integrity": "sha512-gCmjoaERErK5Rn9Lu/BN07fY13MoWV7JKgGzrnkPlQPdPxYcwDhLtYcmpFFpZ4J9NPZZBSezi1UkLZO/DnNppA==", + "dependencies": { + "crc": "3.4.0", + "debug": "^3.1.0" + }, + "bin": { + "jsmodbus": "bin/jsmodbus.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/jsmodbus/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/leven": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", + "integrity": "sha1-wuep93IJTe6dNCAq6KzORoeHVYA=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/log4js": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.5.2.tgz", + "integrity": "sha512-DXtpNtt+KDOMT7RHUDIur/WsSA3rntlUh9Zg4XCdV42wUuMmbFkl38+LZ92Z5QvQA7mD5kAVkLiBSEH/tvUB8A==", + "dependencies": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "flatted": "^3.2.5", + "rfdc": "^1.3.0", + "streamroller": "^3.1.1" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" + }, + "node_modules/moment": { + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", + "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==", + "engines": { + "node": "*" + } + }, + "node_modules/mqtt": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/mqtt/-/mqtt-4.3.7.tgz", + "integrity": "sha512-ew3qwG/TJRorTz47eW46vZ5oBw5MEYbQZVaEji44j5lAUSQSqIEoul7Kua/BatBW0H0kKQcC9kwUHa1qzaWHSw==", + "dependencies": { + "commist": "^1.0.0", + "concat-stream": "^2.0.0", + "debug": "^4.1.1", + "duplexify": "^4.1.1", + "help-me": "^3.0.0", + "inherits": "^2.0.3", + "lru-cache": "^6.0.0", + "minimist": "^1.2.5", + "mqtt-packet": "^6.8.0", + "number-allocator": "^1.0.9", + "pump": "^3.0.0", + "readable-stream": "^3.6.0", + "reinterval": "^1.1.0", + "rfdc": "^1.3.0", + "split2": "^3.1.0", + "ws": "^7.5.5", + "xtend": "^4.0.2" + }, + "bin": { + "mqtt": "bin/mqtt.js", + "mqtt_pub": "bin/pub.js", + "mqtt_sub": "bin/sub.js" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/mqtt-packet": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/mqtt-packet/-/mqtt-packet-6.10.0.tgz", + "integrity": "sha512-ja8+mFKIHdB1Tpl6vac+sktqy3gA8t9Mduom1BA75cI+R9AHnZOiaBQwpGiWnaVJLDGRdNhQmFaAqd7tkKSMGA==", + "dependencies": { + "bl": "^4.0.2", + "debug": "^4.1.1", + "process-nextick-args": "^2.0.1" + } + }, + "node_modules/mqtt/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/nan": { + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.16.0.tgz", + "integrity": "sha512-UdAqHyFngu7TfQKsCBgAA6pWDkT8MAO7d0jyOecVhN5354xbLqdn8mV9Tat9gepAupm0bt2DbeaSC8vS52MuFA==" + }, + "node_modules/napi-build-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", + "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==" + }, + "node_modules/node-abi": { + "version": "3.22.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.22.0.tgz", + "integrity": "sha512-u4uAs/4Zzmp/jjsD9cyFYDXeISfUWaAVWshPmDZOFOv4Xl4SbzTXm53I04C2uRueYJ+0t5PEtLH/owbn2Npf/w==", + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/nodemailer": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.7.tgz", + "integrity": "sha512-rUtR77ksqex/eZRLmQ21LKVH5nAAsVicAtAYudK7JgwenEDZ0UIQ1adUGqErz7sMkWYxWTTU1aeP2Jga6WQyJw==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "dependencies": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "node_modules/number-allocator": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/number-allocator/-/number-allocator-1.0.14.tgz", + "integrity": "sha512-OrL44UTVAvkKdOdRQZIJpLkAdjXGTRda052sN4sO77bKEzYYqWKMBjQvrJFzqygI99gL6Z4u2xctPW1tB8ErvA==", + "dependencies": { + "debug": "^4.3.1", + "js-sdsl": "4.3.0" + } + }, + "node_modules/number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/prebuild-install": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.0.tgz", + "integrity": "sha512-CNcMgI1xBypOyGqjp3wOc8AAo1nMhZS3Cwd3iHIxOdAUbb+YxdNuM4Z5iIrZ8RLvOsf3F3bl7b7xGq6DjQoNYA==", + "dependencies": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^1.0.1", + "node-abi": "^3.3.0", + "npmlog": "^4.0.1", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + }, + "bin": { + "prebuild-install": "bin.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/reinterval": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reinterval/-/reinterval-1.1.0.tgz", + "integrity": "sha1-M2Hs+jymwYKDOA3Qu5VG85D17Oc=" + }, + "node_modules/rfdc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==" + }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/serialport": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/serialport/-/serialport-9.2.8.tgz", + "integrity": "sha512-FsWpMQgSJxi93JgWl5xM1f9/Z8IjRJuaUEoHqLf8FPBLw7gMhInuHOBhI2onQufWIYPGTz3H3oGcu1nCaK1EfA==", + "dependencies": { + "@serialport/binding-mock": "9.2.4", + "@serialport/bindings": "9.2.8", + "@serialport/parser-byte-length": "9.2.4", + "@serialport/parser-cctalk": "9.2.4", + "@serialport/parser-delimiter": "9.2.4", + "@serialport/parser-inter-byte-timeout": "9.2.4", + "@serialport/parser-readline": "9.2.4", + "@serialport/parser-ready": "9.2.4", + "@serialport/parser-regex": "9.2.4", + "@serialport/stream": "9.2.4", + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "node_modules/split2": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", + "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", + "dependencies": { + "readable-stream": "^3.0.0" + } + }, + "node_modules/split2/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==" + }, + "node_modules/streamroller": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.1.1.tgz", + "integrity": "sha512-iPhtd9unZ6zKdWgMeYGfSBuqCngyJy1B/GPi/lTpwGpa3bajuX30GjUVd0/Tn/Xhg0mr4DOSENozz9Y06qyonQ==", + "dependencies": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "fs-extra": "^10.1.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dependencies": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/tar-fs": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "dependencies": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tar-stream/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/total.js": { + "version": "3.4.13", + "resolved": "https://registry.npmjs.org/total.js/-/total.js-3.4.13.tgz", + "integrity": "sha512-lAH4gEixlPFbrE3xfKADAcHfO79IFq2wKa9GTsrgRzIR5MTg3mNH7+4IxvX1pK8faoYb/0oYSJ1YTsAa5hIFFQ==", + "bin": { + "total": "bin/totaljs", + "total.js": "bin/totaljs", + "totaljs": "bin/totaljs", + "totalpackage": "bin/tpm", + "tpm": "bin/tpm" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, + "node_modules/universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "node_modules/wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "node_modules/ws": { + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } + }, + "dependencies": { + "@serialport/binding-abstract": { + "version": "9.2.3", + "resolved": "https://registry.npmjs.org/@serialport/binding-abstract/-/binding-abstract-9.2.3.tgz", + "integrity": "sha512-cQs9tbIlG3P0IrOWyVirqlhWuJ7Ms2Zh9m2108z6Y5UW/iVj6wEOiW8EmK9QX9jmJXYllE7wgGgvVozP5oCj3w==", + "requires": { + "debug": "^4.3.2" + } + }, + "@serialport/binding-mock": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/binding-mock/-/binding-mock-9.2.4.tgz", + "integrity": "sha512-dpEhACCs44oQhh6ajJfJdvQdK38Vq0N4W6iD/gdplglDCK7qXRQCMUjJIeKdS/HSEiWkC3bwumUhUufdsOyT4g==", + "requires": { + "@serialport/binding-abstract": "9.2.3", + "debug": "^4.3.2" + } + }, + "@serialport/bindings": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/@serialport/bindings/-/bindings-9.2.8.tgz", + "integrity": "sha512-hSLxTe0tADZ3LMMGwvEJWOC/TaFQTyPeFalUCsJ1lSQ0k6bPF04JwrtB/C81GetmDBTNRY0GlD0SNtKCc7Dr5g==", + "requires": { + "@serialport/binding-abstract": "9.2.3", + "@serialport/parser-readline": "9.2.4", + "bindings": "^1.5.0", + "debug": "^4.3.2", + "nan": "^2.15.0", + "prebuild-install": "^7.0.0" + } + }, + "@serialport/parser-byte-length": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-byte-length/-/parser-byte-length-9.2.4.tgz", + "integrity": "sha512-sQD/iw4ZMU3xW9PLi0/GlvU6Y623jGeWecbMkO7izUo/6P7gtfv1c9ikd5h0kwL8AoAOpQA1lxdHIKox+umBUg==" + }, + "@serialport/parser-cctalk": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-cctalk/-/parser-cctalk-9.2.4.tgz", + "integrity": "sha512-T4TU5vQMwmo9AB3gQLFDWbfJXlW5jd9guEsB/nqKjFHTv0FXPdZ7DQ2TpSp8RnHWxU3GX6kYTaDO20BKzc8GPQ==" + }, + "@serialport/parser-delimiter": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-delimiter/-/parser-delimiter-9.2.4.tgz", + "integrity": "sha512-4nvTAoYAgkxFiXrkI+3CA49Yd43CODjeszh89EK+I9c8wOZ+etZduRCzINYPiy26g7zO+GRAb9FoPCsY+sYcbQ==" + }, + "@serialport/parser-inter-byte-timeout": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-inter-byte-timeout/-/parser-inter-byte-timeout-9.2.4.tgz", + "integrity": "sha512-SOAdvr0oBQIOCXX198hiTlxs4JTKg9j5piapw5tNq52fwDOWdbYrFneT/wN04UTMKaDrJuEvXq6T4rv4j7nJ5A==" + }, + "@serialport/parser-readline": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-readline/-/parser-readline-9.2.4.tgz", + "integrity": "sha512-Z1/qrZTQUVhNSJP1hd9YfDvq0o7d87rNwAjjRKbVpa7Qi51tG5BnKt43IV3NFMyBlVcRe0rnIb3tJu57E0SOwg==", + "requires": { + "@serialport/parser-delimiter": "9.2.4" + } + }, + "@serialport/parser-ready": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-ready/-/parser-ready-9.2.4.tgz", + "integrity": "sha512-Pyi94Itjl6qAURwIZr/gmZpMAyTmKXThm6vL5DoAWGQjcRHWB0gwv2TY2v7N+mQLJYUKU3cMnvnATXxHm7xjxw==" + }, + "@serialport/parser-regex": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-regex/-/parser-regex-9.2.4.tgz", + "integrity": "sha512-sI/cVvPOYz+Dbv4ZdnW16qAwvXiFf/1pGASQdbveRTlgJDdz7sRNlCBifzfTN2xljwvCTZYqiudKvDdC1TepRQ==" + }, + "@serialport/stream": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/stream/-/stream-9.2.4.tgz", + "integrity": "sha512-bLye8Ub4vUFQGmkh8qEqehr7SE7EJs2yDs0h9jzuL5oKi+F34CFmWkEErO8GAOQ8YNn7p6b3GxUgs+0BrHHDZQ==", + "requires": { + "debug": "^4.3.2" + } + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==" + }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "are-we-there-yet": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", + "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "base64-js": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", + "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==" + }, + "bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "requires": { + "file-uri-to-path": "1.0.0" + } + }, + "bitwise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/bitwise/-/bitwise-2.1.0.tgz", + "integrity": "sha512-XKgAhMXCh4H/3oNwAHAsAO0iC89s9cOiumgYwSHjSobGWxYjv62YhkL9QEdvGP151xypCtMlAfKK79GEcd2eRQ==" + }, + "bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "requires": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "buffer": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz", + "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==", + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" + }, + "chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==" + }, + "commist": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/commist/-/commist-1.1.0.tgz", + "integrity": "sha512-rraC8NXWOEjhADbZe9QBNzLAN5Q3fsTPQtBV+fEVj6xKIgDgNiEVE6ZNfHpZOqfQ21YUzfVNUXLOEZquYvQPPg==", + "requires": { + "leven": "^2.1.0", + "minimist": "^1.1.0" + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "concat-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", + "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.0.2", + "typedarray": "^0.0.6" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "crc": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/crc/-/crc-3.4.0.tgz", + "integrity": "sha512-ycVC2+4/DLgXXq7QweYi2znhqDuZz6P5TQXnkQo8v15XY/5p/IWeZwsSE31Ifo8w15b8TWLsqhXOjXyilHuQxw==" + }, + "date-format": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.11.tgz", + "integrity": "sha512-VS20KRyorrbMCQmpdl2hg5KaOUsda1RbnsJg461FfrcyCUg+pkd0b40BSW4niQyTheww4DBXQnS7HwSrKkipLw==" + }, + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "requires": { + "ms": "2.1.2" + } + }, + "decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "requires": { + "mimic-response": "^3.1.0" + } + }, + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==" + }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" + }, + "detect-libc": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz", + "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==" + }, + "duplexify": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.2.tgz", + "integrity": "sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw==", + "requires": { + "end-of-stream": "^1.4.1", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1", + "stream-shift": "^1.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "easy-crc": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/easy-crc/-/easy-crc-0.0.2.tgz", + "integrity": "sha512-h6eqIdhJRe0p271/xZJbM/0klCi13mW5IB7ZEzEGH11yV4QXWAkD4yPErz0fXdhFrd6sZ4Q1k5Iky2kMsMNePw==" + }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "requires": { + "once": "^1.4.0" + } + }, + "expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==" + }, + "file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" + }, + "flatted": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", + "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==" + }, + "fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, + "fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha512-14x4kjc6lkD3ltw589k0NrPD6cCNTD6CWoVUNpB85+DrtONoZn+Rug6xZU5RvSC4+TZPxA5AnBibQYAvZn41Hg==", + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==" + }, + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" + }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" + }, + "help-me": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/help-me/-/help-me-3.0.0.tgz", + "integrity": "sha512-hx73jClhyk910sidBB7ERlnhMlFsJJIBqSVMFDwPN8o2v9nmp5KgLq1Xz1Bf1fCMMZ6mPrX159iG0VLy/fPMtQ==", + "requires": { + "glob": "^7.1.6", + "readable-stream": "^3.6.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==", + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "js-sdsl": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz", + "integrity": "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==" + }, + "jsmodbus": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/jsmodbus/-/jsmodbus-4.0.6.tgz", + "integrity": "sha512-gCmjoaERErK5Rn9Lu/BN07fY13MoWV7JKgGzrnkPlQPdPxYcwDhLtYcmpFFpZ4J9NPZZBSezi1UkLZO/DnNppA==", + "requires": { + "crc": "3.4.0", + "debug": "^3.1.0" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "requires": { + "ms": "^2.1.1" + } + } + } + }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, + "leven": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", + "integrity": "sha1-wuep93IJTe6dNCAq6KzORoeHVYA=" + }, + "log4js": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.5.2.tgz", + "integrity": "sha512-DXtpNtt+KDOMT7RHUDIur/WsSA3rntlUh9Zg4XCdV42wUuMmbFkl38+LZ92Z5QvQA7mD5kAVkLiBSEH/tvUB8A==", + "requires": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "flatted": "^3.2.5", + "rfdc": "^1.3.0", + "streamroller": "^3.1.1" + } + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "requires": { + "yallist": "^4.0.0" + } + }, + "mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==" + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==" + }, + "mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" + }, + "moment": { + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", + "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==" + }, + "mqtt": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/mqtt/-/mqtt-4.3.7.tgz", + "integrity": "sha512-ew3qwG/TJRorTz47eW46vZ5oBw5MEYbQZVaEji44j5lAUSQSqIEoul7Kua/BatBW0H0kKQcC9kwUHa1qzaWHSw==", + "requires": { + "commist": "^1.0.0", + "concat-stream": "^2.0.0", + "debug": "^4.1.1", + "duplexify": "^4.1.1", + "help-me": "^3.0.0", + "inherits": "^2.0.3", + "lru-cache": "^6.0.0", + "minimist": "^1.2.5", + "mqtt-packet": "^6.8.0", + "number-allocator": "^1.0.9", + "pump": "^3.0.0", + "readable-stream": "^3.6.0", + "reinterval": "^1.1.0", + "rfdc": "^1.3.0", + "split2": "^3.1.0", + "ws": "^7.5.5", + "xtend": "^4.0.2" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "mqtt-packet": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/mqtt-packet/-/mqtt-packet-6.10.0.tgz", + "integrity": "sha512-ja8+mFKIHdB1Tpl6vac+sktqy3gA8t9Mduom1BA75cI+R9AHnZOiaBQwpGiWnaVJLDGRdNhQmFaAqd7tkKSMGA==", + "requires": { + "bl": "^4.0.2", + "debug": "^4.1.1", + "process-nextick-args": "^2.0.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "nan": { + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.16.0.tgz", + "integrity": "sha512-UdAqHyFngu7TfQKsCBgAA6pWDkT8MAO7d0jyOecVhN5354xbLqdn8mV9Tat9gepAupm0bt2DbeaSC8vS52MuFA==" + }, + "napi-build-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", + "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==" + }, + "node-abi": { + "version": "3.22.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.22.0.tgz", + "integrity": "sha512-u4uAs/4Zzmp/jjsD9cyFYDXeISfUWaAVWshPmDZOFOv4Xl4SbzTXm53I04C2uRueYJ+0t5PEtLH/owbn2Npf/w==", + "requires": { + "semver": "^7.3.5" + } + }, + "nodemailer": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.7.tgz", + "integrity": "sha512-rUtR77ksqex/eZRLmQ21LKVH5nAAsVicAtAYudK7JgwenEDZ0UIQ1adUGqErz7sMkWYxWTTU1aeP2Jga6WQyJw==" + }, + "npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "number-allocator": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/number-allocator/-/number-allocator-1.0.14.tgz", + "integrity": "sha512-OrL44UTVAvkKdOdRQZIJpLkAdjXGTRda052sN4sO77bKEzYYqWKMBjQvrJFzqygI99gL6Z4u2xctPW1tB8ErvA==", + "requires": { + "debug": "^4.3.1", + "js-sdsl": "4.3.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==" + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==" + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==" + }, + "prebuild-install": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.0.tgz", + "integrity": "sha512-CNcMgI1xBypOyGqjp3wOc8AAo1nMhZS3Cwd3iHIxOdAUbb+YxdNuM4Z5iIrZ8RLvOsf3F3bl7b7xGq6DjQoNYA==", + "requires": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^1.0.1", + "node-abi": "^3.3.0", + "npmlog": "^4.0.1", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + } + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + } + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "reinterval": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reinterval/-/reinterval-1.1.0.tgz", + "integrity": "sha1-M2Hs+jymwYKDOA3Qu5VG85D17Oc=" + }, + "rfdc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==" + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "requires": { + "lru-cache": "^6.0.0" + } + }, + "serialport": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/serialport/-/serialport-9.2.8.tgz", + "integrity": "sha512-FsWpMQgSJxi93JgWl5xM1f9/Z8IjRJuaUEoHqLf8FPBLw7gMhInuHOBhI2onQufWIYPGTz3H3oGcu1nCaK1EfA==", + "requires": { + "@serialport/binding-mock": "9.2.4", + "@serialport/bindings": "9.2.8", + "@serialport/parser-byte-length": "9.2.4", + "@serialport/parser-cctalk": "9.2.4", + "@serialport/parser-delimiter": "9.2.4", + "@serialport/parser-inter-byte-timeout": "9.2.4", + "@serialport/parser-readline": "9.2.4", + "@serialport/parser-ready": "9.2.4", + "@serialport/parser-regex": "9.2.4", + "@serialport/stream": "9.2.4", + "debug": "^4.3.2" + } + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==" + }, + "simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "requires": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "split2": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", + "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", + "requires": { + "readable-stream": "^3.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==" + }, + "streamroller": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.1.1.tgz", + "integrity": "sha512-iPhtd9unZ6zKdWgMeYGfSBuqCngyJy1B/GPi/lTpwGpa3bajuX30GjUVd0/Tn/Xhg0mr4DOSENozz9Y06qyonQ==", + "requires": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "fs-extra": "^10.1.0" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" + }, + "tar-fs": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "requires": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "requires": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "total.js": { + "version": "3.4.13", + "resolved": "https://registry.npmjs.org/total.js/-/total.js-3.4.13.tgz", + "integrity": "sha512-lAH4gEixlPFbrE3xfKADAcHfO79IFq2wKa9GTsrgRzIR5MTg3mNH7+4IxvX1pK8faoYb/0oYSJ1YTsAa5hIFFQ==" + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, + "universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==" + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "requires": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "ws": { + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "requires": {} + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } + } +} diff --git a/RVO16/package.json b/RVO16/package.json new file mode 100755 index 0000000..7f7c795 --- /dev/null +++ b/RVO16/package.json @@ -0,0 +1,30 @@ +{ + "name": "emptyproject", + "description": "Total.js empty project.", + "version": "1.0.0", + "main": "debug.js", + "dependencies": { + "bitwise": "^2.1.0", + "easy-crc": "0.0.2", + "jsmodbus": "^4.0.6", + "log4js": "^6.3.0", + "moment": "^2.30.1", + "mqtt": "^4.2.6", + "nodemailer": "^6.9.7", + "serialport": "^9.2.8", + "total.js": "^3.4.13" + }, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "https://github.com/totaljs/emptyproject-flow" + }, + "keywords": [ + "empty", + "project" + ], + "author": "Peter Širka", + "license": "MIT" +} diff --git a/RVO16/release.js b/RVO16/release.js new file mode 100755 index 0000000..02d52ff --- /dev/null +++ b/RVO16/release.js @@ -0,0 +1,15 @@ +// =================================================== +// FOR PRODUCTION +// Total.js - framework for Node.js platform +// https://www.totaljs.com +// =================================================== + +const options = {'ip':'0.0.0.0', 'port':12345}; + +// options.ip = '127.0.0.1'; +// options.port = parseInt(process.argv[2]); +// options.config = { name: 'Total.js' }; +// options.sleep = 3000; + +require('total.js').http('release', options); +// require('total.js').cluster.http(5, 'release', options); diff --git a/RVO16/release.js.json b/RVO16/release.js.json new file mode 100755 index 0000000..87cf245 --- /dev/null +++ b/RVO16/release.js.json @@ -0,0 +1,34 @@ +{ + "pid": 17794, + "stats": [ + { + "id": null, + "version": { + "node": "v14.18.1", + "total": "3.4.13", + "app": "1.0.0" + }, + "pid": 17794, + "thread": "", + "mode": "release", + "overload": 0, + "date": "2025-10-16T00:23:43.622Z", + "memory": 25.99, + "rm": 0, + "fm": 0, + "wm": 0, + "mm": 0, + "om": 6, + "em": 0, + "dbrm": 0, + "dbwm": 0, + "usage": 0, + "requests": 5, + "pending": 0, + "errors": 0, + "timeouts": 0, + "uptime": 1588, + "online": 0 + } + ] +} \ No newline at end of file diff --git a/RVO16/report_data.log b/RVO16/report_data.log new file mode 100755 index 0000000..f227606 --- /dev/null +++ b/RVO16/report_data.log @@ -0,0 +1,2191 @@ +{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-09T18:10:18.411Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-09T19:10:18.406Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-09T20:10:18.406Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-09T21:10:18.407Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-09T22:10:18.407Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-09T23:10:18.407Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-10T00:10:18.409Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-10T01:10:19.412Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-10T02:10:19.413Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-10T03:10:19.413Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-10T04:10:19.413Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-10T07:33:36.911Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-10T08:33:36.911Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-10T09:33:36.911Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-10T10:33:36.912Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-10T11:33:36.912Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-10T12:33:36.912Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-10T13:33:36.912Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-10T14:33:36.912Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-10T15:33:36.913Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-10T17:53:33.407Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [ + "4096", + "4764" + ], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-10T18:53:33.406Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [ + "4096", + "4764" + ], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-10T19:53:33.407Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [ + "4096", + "4764" + ], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-10T20:53:33.406Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [ + "4096", + "4764" + ], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-10T21:53:33.406Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [ + "4096", + "4764" + ], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-10T22:53:33.406Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [ + "4096", + "4764" + ], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-10T23:53:33.406Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [ + "4096", + "4764" + ], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-11T00:53:33.406Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [ + "4096", + "4764" + ], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-11T01:53:34.452Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [ + "4096", + "4764" + ], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-11T02:53:34.452Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [ + "4096", + "4764" + ], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-11T03:53:34.452Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [ + "4096", + "4764" + ], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-11T04:53:34.453Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [ + "4096", + "4764" + ], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-11T07:37:54.032Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-11T08:37:54.032Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-11T09:37:54.033Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-11T10:37:54.034Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-11T11:37:54.034Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-11T12:37:54.034Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-11T13:37:54.035Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-11T14:37:54.036Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-11T15:37:54.036Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-11T17:46:59.301Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-11T18:46:59.300Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-11T19:46:59.299Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-11T20:46:59.300Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-11T21:46:59.301Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-11T22:46:59.301Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-11T23:46:59.301Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-12T00:46:59.301Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-12T01:47:01.307Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-12T02:47:01.309Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-12T03:47:01.309Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-12T04:47:01.310Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-12T07:38:54.619Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-12T08:38:54.620Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-12T09:38:54.620Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-12T10:38:54.621Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-12T11:38:54.621Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-12T12:38:54.622Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-12T13:38:54.623Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-12T14:38:54.624Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-12T15:38:54.624Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-12T17:44:59.085Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "3870" + ], + "night_dimming=0": [ + "4764" + ], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-12T18:44:59.083Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "3870" + ], + "night_dimming=0": [ + "4764" + ], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-12T19:44:59.084Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "3870" + ], + "night_dimming=0": [ + "4764" + ], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-12T20:44:59.085Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "3870" + ], + "night_dimming=0": [ + "4764" + ], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-12T21:44:59.085Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "3870" + ], + "night_dimming=0": [ + "4764" + ], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-12T22:44:59.084Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "3870" + ], + "night_dimming=0": [ + "4764" + ], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-12T23:44:59.085Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "3870" + ], + "night_dimming=0": [ + "4764" + ], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-13T00:44:59.086Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "3870" + ], + "night_dimming=0": [ + "4764" + ], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-13T01:45:00.080Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "3870" + ], + "night_dimming=0": [ + "4764" + ], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-13T02:45:00.080Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "3870" + ], + "night_dimming=0": [ + "4764" + ], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-13T03:45:00.081Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "3870" + ], + "night_dimming=0": [ + "4764" + ], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-13T04:45:00.082Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "3870" + ], + "night_dimming=0": [ + "4764" + ], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-13T07:40:21.933Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-13T08:40:21.932Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-13T09:40:21.932Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-13T10:40:21.934Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-13T11:40:21.932Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-13T12:40:21.933Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-13T13:40:21.934Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-13T14:40:21.934Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-13T15:40:21.934Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-13T17:44:40.288Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "3870" + ], + "night_dimming=0": [ + "4096", + "4764" + ], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-13T18:44:40.293Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "3870", + "3710", + "3726" + ], + "night_dimming=0": [ + "4096", + "4764" + ], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-13T19:44:40.288Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "3870", + "3710", + "3726" + ], + "night_dimming=0": [ + "4096", + "4764" + ], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-13T20:44:40.293Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "3870", + "3710", + "3726" + ], + "night_dimming=0": [ + "4096", + "4764" + ], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-13T21:44:40.287Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "3870", + "3710", + "3726" + ], + "night_dimming=0": [ + "4096", + "4764" + ], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-13T22:44:40.289Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "3870", + "3710", + "3726" + ], + "night_dimming=0": [ + "4096", + "4764" + ], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-13T23:44:40.288Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "3870", + "3710", + "3726" + ], + "night_dimming=0": [ + "4096", + "4764" + ], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-14T00:44:40.288Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "3870", + "3710", + "3726" + ], + "night_dimming=0": [ + "4096", + "4764" + ], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-14T01:44:41.253Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "3870", + "3710", + "3726" + ], + "night_dimming=0": [ + "4096", + "4764" + ], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-14T02:44:41.254Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "3870", + "3710", + "3726" + ], + "night_dimming=0": [ + "4096", + "4764" + ], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-14T03:44:41.255Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "3870", + "3710", + "3726" + ], + "night_dimming=0": [ + "4096", + "4764" + ], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-14T04:44:41.255Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "3870", + "3710", + "3726" + ], + "night_dimming=0": [ + "4096", + "4764" + ], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-14T07:42:06.909Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-14T08:42:06.909Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-14T09:42:06.909Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-14T10:42:06.910Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-14T11:42:06.910Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-14T12:42:06.911Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-14T13:42:06.911Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-14T14:42:06.911Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-14T15:42:06.912Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-14T17:41:02.972Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "3870" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-14T18:41:02.971Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "3870" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-14T19:41:02.972Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "3870" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-14T20:41:02.972Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "3870" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-14T21:41:02.971Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "3870" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-14T22:56:55.788Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "16/76_1L_3870_NEMA" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-14T23:56:55.789Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "16/76_1L_3870_NEMA" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-15T00:56:55.785Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "16/76_1L_3870_NEMA" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-15T01:56:57.426Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "16/76_1L_3870_NEMA" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-15T02:56:57.424Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "16/76_1L_3870_NEMA" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-15T03:56:57.425Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "16/76_1L_3870_NEMA" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-15T04:56:57.424Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "16/76_1L_3870_NEMA" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-15T08:30:11.791Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-15T09:30:11.791Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-15T10:30:11.791Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-15T11:30:11.790Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-15T12:30:11.791Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-15T13:30:11.791Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-15T14:30:11.792Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-15T15:30:11.792Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-15T17:40:38.689Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "16/76_1L_3870_NEMA" + ], + "night_dimming=0": [], + "night_power=0": [ + "16/114_1L_4096_NEMA", + "16/116_1L_4764_NEMA" + ], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-15T18:40:38.689Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "16/76_1L_3870_NEMA" + ], + "night_dimming=0": [], + "night_power=0": [ + "16/114_1L_4096_NEMA", + "16/116_1L_4764_NEMA" + ], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-15T19:40:38.685Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "16/76_1L_3870_NEMA" + ], + "night_dimming=0": [], + "night_power=0": [ + "16/114_1L_4096_NEMA", + "16/116_1L_4764_NEMA" + ], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-15T20:40:38.687Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "16/76_1L_3870_NEMA" + ], + "night_dimming=0": [], + "night_power=0": [ + "16/114_1L_4096_NEMA", + "16/116_1L_4764_NEMA" + ], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-15T21:40:38.693Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "16/76_1L_3870_NEMA" + ], + "night_dimming=0": [], + "night_power=0": [ + "16/114_1L_4096_NEMA", + "16/116_1L_4764_NEMA" + ], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-15T22:40:38.688Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "16/76_1L_3870_NEMA" + ], + "night_dimming=0": [], + "night_power=0": [ + "16/114_1L_4096_NEMA", + "16/116_1L_4764_NEMA" + ], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_16_10.0.0.131", + "time": "2025-10-15T23:40:38.689Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "16/76_1L_3870_NEMA" + ], + "night_dimming=0": [], + "night_power=0": [ + "16/114_1L_4096_NEMA", + "16/116_1L_4764_NEMA" + ], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +} \ No newline at end of file From aae6807bcb15a981b75e890c3b84d72c8e353793 Mon Sep 17 00:00:00 2001 From: Jakub Klena Date: Thu, 16 Oct 2025 02:24:33 +0200 Subject: [PATCH 10/30] Backup senica-RVO20 on 16.10.2025 --- RVO20/addSwitch.py | 36 + RVO20/cloud_topic.py | 76 + RVO20/config | 12 + RVO20/createNode.py | 43 + RVO20/databases/accelerometer_db.js | 3055 ++++++++++++++++ RVO20/databases/modbus_config.js | 114 + RVO20/databases/nodes.table | 66 + .../nodes_original/nodes_original.table | 1 + RVO20/databases/notifications.table | 41 + RVO20/databases/pins.table | 14 + RVO20/databases/relays.table | 5 + RVO20/databases/settings.table | 2 + RVO20/databases/tbdata.nosql | 4 + RVO20/databases/tbdatacloud.nosql | 3 + RVO20/databases/total_energy.js | 38 + RVO20/debug.js | 16 + RVO20/err.txt | 43 + RVO20/flow/cloudmqttconnect.js | 357 ++ RVO20/flow/cmd_manager.js | 3071 ++++++++++++++++ RVO20/flow/code.js | 90 + RVO20/flow/comment.js | 11 + RVO20/flow/count.js | 60 + RVO20/flow/db_connector.js | 286 ++ RVO20/flow/db_init.js | 113 + RVO20/flow/debug.js | 100 + RVO20/flow/designer.json | 3102 ++++++++++++++++ RVO20/flow/dido_controller.js | 1486 ++++++++ RVO20/flow/helper/DataToTbHandler.js | 187 + RVO20/flow/helper/ErrorToServiceHandler.js | 91 + RVO20/flow/helper/db_helper.js | 44 + RVO20/flow/helper/logger.js | 30 + RVO20/flow/helper/md5.js | 5 + RVO20/flow/helper/notification_reporter.js | 121 + RVO20/flow/helper/register.js | 144 + RVO20/flow/helper/serialport_helper.js | 99 + RVO20/flow/helper/suncalc.js | 317 ++ RVO20/flow/helper/utils.js | 161 + RVO20/flow/httprequest.js | 137 + RVO20/flow/httpresponse.js | 76 + RVO20/flow/httproute.js | 326 ++ RVO20/flow/infosender.js | 81 + RVO20/flow/modbus_reader.js | 346 ++ RVO20/flow/monitorconsumption.js | 156 + RVO20/flow/monitordisk.js | 96 + RVO20/flow/monitormemory.js | 87 + RVO20/flow/nodesdb_changecheck.js | 77 + RVO20/flow/show_dbdata.js | 243 ++ RVO20/flow/slack_filter.js | 188 + RVO20/flow/thermometer.js | 99 + RVO20/flow/trigger.js | 79 + RVO20/flow/variables.txt | 0 RVO20/flow/virtualwirein.js | 43 + RVO20/flow/virtualwireout.js | 41 + RVO20/flow/wsmqttpublish.js | 448 +++ RVO20/monitor.txt | 3207 +++++++++++++++++ RVO20/package-lock.json | 2139 +++++++++++ RVO20/package.json | 30 + RVO20/release.js | 15 + RVO20/release.js.json | 34 + RVO20/report_data.log | 151 + 60 files changed, 21543 insertions(+) create mode 100755 RVO20/addSwitch.py create mode 100755 RVO20/cloud_topic.py create mode 100755 RVO20/config create mode 100755 RVO20/createNode.py create mode 100755 RVO20/databases/accelerometer_db.js create mode 100755 RVO20/databases/modbus_config.js create mode 100755 RVO20/databases/nodes.table create mode 100755 RVO20/databases/nodes_original/nodes_original.table create mode 100755 RVO20/databases/notifications.table create mode 100755 RVO20/databases/pins.table create mode 100755 RVO20/databases/relays.table create mode 100755 RVO20/databases/settings.table create mode 100755 RVO20/databases/tbdata.nosql create mode 100755 RVO20/databases/tbdatacloud.nosql create mode 100755 RVO20/databases/total_energy.js create mode 100755 RVO20/debug.js create mode 100755 RVO20/err.txt create mode 100755 RVO20/flow/cloudmqttconnect.js create mode 100755 RVO20/flow/cmd_manager.js create mode 100755 RVO20/flow/code.js create mode 100755 RVO20/flow/comment.js create mode 100755 RVO20/flow/count.js create mode 100755 RVO20/flow/db_connector.js create mode 100755 RVO20/flow/db_init.js create mode 100755 RVO20/flow/debug.js create mode 100755 RVO20/flow/designer.json create mode 100755 RVO20/flow/dido_controller.js create mode 100755 RVO20/flow/helper/DataToTbHandler.js create mode 100755 RVO20/flow/helper/ErrorToServiceHandler.js create mode 100755 RVO20/flow/helper/db_helper.js create mode 100755 RVO20/flow/helper/logger.js create mode 100755 RVO20/flow/helper/md5.js create mode 100755 RVO20/flow/helper/notification_reporter.js create mode 100755 RVO20/flow/helper/register.js create mode 100755 RVO20/flow/helper/serialport_helper.js create mode 100755 RVO20/flow/helper/suncalc.js create mode 100755 RVO20/flow/helper/utils.js create mode 100755 RVO20/flow/httprequest.js create mode 100755 RVO20/flow/httpresponse.js create mode 100755 RVO20/flow/httproute.js create mode 100755 RVO20/flow/infosender.js create mode 100755 RVO20/flow/modbus_reader.js create mode 100755 RVO20/flow/monitorconsumption.js create mode 100755 RVO20/flow/monitordisk.js create mode 100755 RVO20/flow/monitormemory.js create mode 100755 RVO20/flow/nodesdb_changecheck.js create mode 100755 RVO20/flow/show_dbdata.js create mode 100755 RVO20/flow/slack_filter.js create mode 100755 RVO20/flow/thermometer.js create mode 100755 RVO20/flow/trigger.js create mode 100755 RVO20/flow/variables.txt create mode 100755 RVO20/flow/virtualwirein.js create mode 100755 RVO20/flow/virtualwireout.js create mode 100755 RVO20/flow/wsmqttpublish.js create mode 100755 RVO20/monitor.txt create mode 100755 RVO20/package-lock.json create mode 100755 RVO20/package.json create mode 100755 RVO20/release.js create mode 100755 RVO20/release.js.json create mode 100755 RVO20/report_data.log diff --git a/RVO20/addSwitch.py b/RVO20/addSwitch.py new file mode 100755 index 0000000..c35e96b --- /dev/null +++ b/RVO20/addSwitch.py @@ -0,0 +1,36 @@ +import os + +def process_set_file(): + """ + Checks if /root/flowserver exists, reads set.txt, and modifies the second line. + """ + default_folder = "/root/flowserver" if os.path.exists("/root/flowserver") else "/home/unipi/flowserver" + flag = 1 if default_folder == "/root/flowserver" else 0 + + try: + with open("/home/unipi/flowserver/databases/settings.table", "r") as f: + lines = f.readlines() + + if len(lines) >= 2: + lines[0] = lines[0].rstrip('\n') + "|main_switch:boolean\n" + second_line = lines[1].strip() # remove trailing newline + last_pipe_index = second_line.rfind("|") + + if last_pipe_index != -1: + modified_line = second_line[:last_pipe_index + 1] + str(flag) + "|" + second_line[last_pipe_index + 1:] + lines[1] = modified_line + else: + print("Warning: No '|' character found in the second line of set.txt") + + with open("/home/unipi/flowserver/databases/settings.table", "w") as f: + f.writelines(lines) + else: + print("Warning: settings.table has less than two lines.") + + except FileNotFoundError: + print("Error: settings.table not found.") + except Exception as e: + print(e) + +# if __name__ == "__main__": +process_set_file() diff --git a/RVO20/cloud_topic.py b/RVO20/cloud_topic.py new file mode 100755 index 0000000..77c31f1 --- /dev/null +++ b/RVO20/cloud_topic.py @@ -0,0 +1,76 @@ +# import os +# +# def modify_file(file_path): +# """ +# Modifies the given file by: +# 1. Appending "|cloud_topic" to the first line. +# 2. Inserting the text from the third "." to the first "|" on the second line after the last "|" character. +# +# Args: +# file_path (str): The path to the file to be modified. +# """ +# +# with open(file_path, 'r+') as f: +# lines = f.readlines() +# +# # Modify the first line +# lines[0] += "|cloud_topic:string" +# +# # Modify the second line +# second_line = lines[1].strip() # Remove leading/trailing whitespace +# first_pipe_index = second_line.find('|') +# third_dot_index = second_line.find('.', second_line.find('.', second_line.find('.') + 1) + 1) +# text_to_insert = second_line[third_dot_index:first_pipe_index] +# +# last_pipe_index = second_line.rfind('|') +# lines[1] = second_line[:last_pipe_index + 1] + text_to_insert + "|" + second_line[last_pipe_index + 1:] +# +# print(first_pipe_index, third_dot_index, text_to_insert, last_pipe_index) +# # Write the modified lines back to the file +# # f.seek(0) +# # f.writelines(lines) +# # f.truncate() +# +# # Example usage: +# file_path = "settings.table" # Replace with the actual file path +# modify_file(file_path) +# + + +def modify_file(file_path): + """ + Modifies the given file by: + 1. Appending "|cloud_topic" to the first line. + 2. Inserting the text between the third "." and the second "|" on the second line after the last "|" character. + + Args: + file_path (str): The path to the file to be modified. + """ + + with open(file_path, 'r+') as f: + lines = f.readlines() + + first_line = lines[0].strip() + first_line += "|cloud_topic:string\n" + # Modify the first line + lines[0] = first_line + + # Modify the second line + second_line = lines[1].strip() # Remove leading/trailing whitespace + first_pipe_index = second_line.find('|') + second_pipe_index = second_line.find('|', first_pipe_index + 1) + third_dot_index = second_line.find('.', second_line.find('.', second_line.find('.') + 1) + 1) + text_to_insert = "u" + second_line[third_dot_index+1:second_pipe_index] + + last_pipe_index = second_line.rfind('|') + lines[1] = second_line[:last_pipe_index + 1] + text_to_insert + "|" + second_line[last_pipe_index + 1:] + + print(first_pipe_index, third_dot_index, text_to_insert, last_pipe_index) + # Write the modified lines back to the file + f.seek(0) + f.writelines(lines) + f.truncate() + +# Example usage: +file_path = "/home/unipi/flowserver/databases/settings.table" # Replace with the actual file path +modify_file(file_path) diff --git a/RVO20/config b/RVO20/config new file mode 100755 index 0000000..cd0a8a9 --- /dev/null +++ b/RVO20/config @@ -0,0 +1,12 @@ +name : Total.js Flow +default_timezone : Europe/Bratislava + +// Packages settings +package#flow (Object) : { url: '/' } + + +table.relays : line:number|tbname:string|contactor:number|profile:string +table.nodes : node:number|pole_number:string|node_type:string|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|project_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|cloud_topic:string|has_main_switch:boolean|daily_report:boolean|send_changed_node_numbers:boolean +table.pins : pin:string|type:string|line:number +table.notifications : key:string|weight:string|sk:string|en:string diff --git a/RVO20/createNode.py b/RVO20/createNode.py new file mode 100755 index 0000000..a8cea91 --- /dev/null +++ b/RVO20/createNode.py @@ -0,0 +1,43 @@ +print("zaciname") +import re, json + +search_str = '|' +final = [] +counter = 1 +with open("/home/unipi/flowserver/databases/nodes.table", 'r') as file: +# with open("/home/rasta5man/dev/oms/flowserver/databases/nodes.table", 'r') as file: + # Read each line in the file + for line in file: + # Print each line + line = line.strip() + print(line) + if counter != 1: + i = [m.start() for m in re.finditer(re.escape(search_str), line)] + node = line[ i[0] + 1 : i[1] ] + tbname = line[ i[3] + 1 : i[4] ] + final.append({node:tbname}) + counter += 1 +print(json.dumps(final)) +f = open("/home/unipi/flowserver/databases/nodes_original/nodes_original.table", "w") +f.write(json.dumps(final)) +f.close() + + +# +# # ``d`` has to be replaced with a different character +# old_character = "'" +# +# # ``t`` will replace ``d` +# new_character = '"' +# resultant_string = 0; +# with open("/home/unipi/flowserver/databases/nodes_original/nodes_original.table", 'r') as file: +# for line in file: +# resultant_string = re.sub("'", '"', line) +# +# resultant_string = re.sub(" ", "", resultant_string) +# print(resultant_string) +# +# f = open("/home/unipi/flowserver/databases/nodes_original/nodes_original.table", "w") +# f.write(str(resultant_string)) +# f.close() +# diff --git a/RVO20/databases/accelerometer_db.js b/RVO20/databases/accelerometer_db.js new file mode 100755 index 0000000..fdfc7fd --- /dev/null +++ b/RVO20/databases/accelerometer_db.js @@ -0,0 +1,3055 @@ +let naklony = { + "3993": { "label": "1/3A", "naklon": 0 }, + "3989": { "label": "1/3B", "naklon": 15 }, + "3976": { "label": "1/1", "naklon": 0 }, + "4181": { "label": "1/2", "naklon": 0 }, + "4376": { "label": "1/4", "naklon": 15 }, + "3868": { "label": "1/5", "naklon": 15 }, + "3728": { "label": "1/6", "naklon": 15 }, + "3730": { "label": "1/7", "naklon": 0 }, + "4374": { "label": "1/8", "naklon": 0 }, + "3718": { "label": "1/9", "naklon": 15 }, + "4375": { "label": "1/10", "naklon": 15 }, + "4172": { "label": "1/11", "naklon": 15 }, + "4176": { "label": "1/12", "naklon": 15 }, + "3800": { "label": "2/1", "naklon": 5 }, + "3823": { "label": "2/2", "naklon": 5 }, + "3905": { "label": "2/3", "naklon": 5 }, + "3803": { "label": "2/4", "naklon": 5 }, + "3817": { "label": "2/5", "naklon": 5 }, + "3818": { "label": "2/6", "naklon": 5 }, + "3811": { "label": "2/7", "naklon": 5 }, + "3915": { "label": "2/8", "naklon": 5 }, + "3843": { "label": "2/9", "naklon": 10 }, + "3827": { "label": "2/10", "naklon": 10 }, + "4220": { "label": "2/11", "naklon": 10 }, + "3826": { "label": "2/12", "naklon": 10 }, + "3834": { "label": "2/13", "naklon": 10 }, + "3838": { "label": "2/14", "naklon": 10 }, + "2823": { "label": "2/15", "naklon": 10 }, + "3750": { "label": "2/16", "naklon": 10 }, + "3378": { "label": "2/17", "naklon": 0 }, + "3376": { "label": "2/18", "naklon": 0 }, + "3379": { "label": "2/19", "naklon": 0 }, + "3285": { "label": "2/20", "naklon": 0 }, + "3382": { "label": "2/21", "naklon": 0 }, + "3383": { "label": "2/22", "naklon": 0 }, + "3375": { "label": "2/24", "naklon": 0 }, + "3381": { "label": "2/25", "naklon": 0 }, + "3380": { "label": "2/26", "naklon": 0 }, + "3828": { "label": "2/27", "naklon": 10 }, + "3377": { "label": "2/28", "naklon": 0 }, + "3591": { "label": "7/1", "naklon": 0 }, + "3587": { "label": "7/2", "naklon": 0 }, + "3468": { "label": "7/3", "naklon": 0 }, + "3466": { "label": "7/4", "naklon": 0 }, + "3474": { "label": "7/5", "naklon": 0 }, + "3481": { "label": "7/6", "naklon": 0 }, + "3589": { "label": "7/7", "naklon": 0 }, + "3472": { "label": "7/8", "naklon": 0 }, + "3473": { "label": "7/9", "naklon": 0 }, + "3584": { "label": "7/10", "naklon": 0 }, + "3571": { "label": "7/11", "naklon": 0 }, + "3476": { "label": "7/12", "naklon": 0 }, + "3590": { "label": "7/13", "naklon": 0 }, + "3478": { "label": "7/14", "naklon": 0 }, + "3471": { "label": "7/15", "naklon": 0 }, + "3467": { "label": "7/16", "naklon": 0 }, + "3479": { "label": "7/17", "naklon": 0 }, + "3480": { "label": "7/18", "naklon": 0 }, + "3477": { "label": "7/19", "naklon": 0 }, + "3362": { "label": "12/1", "naklon": 0 }, + "3355": { "label": "12/2", "naklon": 0 }, + "3356": { "label": "12/3", "naklon": 0 }, + "3349": { "label": "12/4", "naklon": 0 }, + "3357": { "label": "12/5", "naklon": 0 }, + "3350": { "label": "12/6", "naklon": 0 }, + "3353": { "label": "12/7", "naklon": 0 }, + "3539": { "label": "12/8", "naklon": 0 }, + "3050": { "label": "12/9", "naklon": 0 }, + "3361": { "label": "12/10", "naklon": 0 }, + "3360": { "label": "12/11", "naklon": 0 }, + "3358": { "label": "12/12", "naklon": 0 }, + "3541": { "label": "12/13", "naklon": 0 }, + "3551": { "label": "12/14", "naklon": 0 }, + "3514": { "label": "12/15", "naklon": 0 }, + "3547": { "label": "12/16", "naklon": 0 }, + "3562": { "label": "12/17", "naklon": 0 }, + "3525": { "label": "12/18", "naklon": 0 }, + "3558": { "label": "12/19", "naklon": 0 }, + "3511": { "label": "12/20", "naklon": 0 }, + "3058": { "label": "12/21", "naklon": 0 }, + "3062": { "label": "12/22", "naklon": 0 }, + "3070": { "label": "12/23", "naklon": 0 }, + "3447": { "label": "12/24", "naklon": 0 }, + "3056": { "label": "12/25", "naklon": 0 }, + "3057": { "label": "12/26", "naklon": 0 }, + "3071": { "label": "12/27", "naklon": 0 }, + "3061": { "label": "12/28", "naklon": 0 }, + "3069": { "label": "12/29", "naklon": 0 }, + "3077": { "label": "12/30", "naklon": 0 }, + "3080": { "label": "12/31", "naklon": 0 }, + "3081": { "label": "12/32", "naklon": 0 }, + "3078": { "label": "12/33", "naklon": 0 }, + "4037": { "label": "12/34", "naklon": 0 }, + "3067": { "label": "12/35", "naklon": 0 }, + "3051": { "label": "12/36", "naklon": 0 }, + "2924": { "label": "12/37", "naklon": 0 }, + "3060": { "label": "12/38", "naklon": 0 }, + "3073": { "label": "12/39", "naklon": 0 }, + "3469": { "label": "12/40", "naklon": 0 }, + "2923": { "label": "12/41", "naklon": 0 }, + "2925": { "label": "12/42", "naklon": 0 }, + "3359": { "label": "12/43", "naklon": 0 }, + "3055": { "label": "12/44", "naklon": 0 }, + "2922": { "label": "12/45", "naklon": 0 }, + "3084": { "label": "12/46", "naklon": 0 }, + "3064": { "label": "12/47", "naklon": 0 }, + "3066": { "label": "12/48", "naklon": 0 }, + "3072": { "label": "12/49", "naklon": 0 }, + "3415": { "label": "13/13A", "naklon": 0 }, + "3409": { "label": "13/13B", "naklon": 0 }, + "3399": { "label": "13/13C", "naklon": 0 }, + "3410": { "label": "13/29A", "naklon": 0 }, + "3407": { "label": "13/29B", "naklon": 0 }, + "3405": { "label": "13/34A", "naklon": 0 }, + "3404": { "label": "13/34B", "naklon": 0 }, + "3392": { "label": "13/45A", "naklon": 0 }, + "3386": { "label": "13/45B", "naklon": 0 }, + "3303": { "label": "13/60A", "naklon": 3 }, + "3302": { "label": "13/60B", "naklon": 3 }, + "3319": { "label": "13/70A", "naklon": 6 }, + "3317": { "label": "13/70B", "naklon": 6 }, + "3326": { "label": "13/70C", "naklon": 6 }, + "3351": { "label": "13/73A", "naklon": 6 }, + "3313": { "label": "13/73B", "naklon": 6 }, + "3316": { "label": "13/83A", "naklon": 0 }, + "3320": { "label": "13/83B", "naklon": 0 }, + "3336": { "label": "13/95A", "naklon": 0 }, + "3323": { "label": "13/95B", "naklon": 0 }, + "3339": { "label": "13/98A", "naklon": 0 }, + "3333": { "label": "13/98B", "naklon": 0 }, + "3425": { "label": "13/1", "naklon": 0 }, + "3419": { "label": "13/2", "naklon": 0 }, + "3416": { "label": "13/3", "naklon": 0 }, + "3332": { "label": "13/4", "naklon": 0 }, + "3422": { "label": "13/5", "naklon": 0 }, + "3417": { "label": "13/6", "naklon": 0 }, + "3418": { "label": "13/7", "naklon": 0 }, + "3424": { "label": "13/8", "naklon": 0 }, + "3334": { "label": "13/9", "naklon": 0 }, + "4363": { "label": "13/10", "naklon": 0 }, + "3423": { "label": "13/11", "naklon": 0 }, + "3406": { "label": "13/12", "naklon": 0 }, + "3411": { "label": "13/14", "naklon": 0 }, + "3412": { "label": "13/15", "naklon": 0 }, + "3413": { "label": "13/16", "naklon": 0 }, + "3414": { "label": "13/17", "naklon": 0 }, + "3391": { "label": "13/18", "naklon": 0 }, + "3370": { "label": "13/19", "naklon": 0 }, + "3369": { "label": "13/20", "naklon": 0 }, + "3408": { "label": "13/21", "naklon": 0 }, + "3393": { "label": "13/22", "naklon": 0 }, + "3128": { "label": "13/23", "naklon": 0 }, + "3197": { "label": "13/24", "naklon": 0 }, + "4364": { "label": "13/25", "naklon": 0 }, + "3155": { "label": "13/26", "naklon": 0 }, + "3196": { "label": "13/27", "naklon": 0 }, + "3144": { "label": "13/28", "naklon": 0 }, + "3150": { "label": "13/30", "naklon": 0 }, + "3390": { "label": "13/31", "naklon": 0 }, + "3401": { "label": "13/32", "naklon": 0 }, + "3275": { "label": "13/33", "naklon": 0 }, + "3371": { "label": "13/35", "naklon": 0 }, + "3389": { "label": "13/36", "naklon": 0 }, + "3388": { "label": "13/37", "naklon": 0 }, + "3365": { "label": "13/38", "naklon": 0 }, + "3363": { "label": "13/39", "naklon": 0 }, + "3397": { "label": "13/40", "naklon": 0 }, + "3567": { "label": "13/40/1", "naklon": 0 }, + "3387": { "label": "13/41", "naklon": 0 }, + "3403": { "label": "13/42", "naklon": 0 }, + "3147": { "label": "13/43", "naklon": 0 }, + "3141": { "label": "13/44", "naklon": 0 }, + "3364": { "label": "13/46", "naklon": 0 }, + "3367": { "label": "13/47", "naklon": 0 }, + "3368": { "label": "13/48", "naklon": 0 }, + "3402": { "label": "13/49", "naklon": 0 }, + "3366": { "label": "13/50", "naklon": 0 }, + "3395": { "label": "13/51", "naklon": 0 }, + "3372": { "label": "13/52", "naklon": 0 }, + "3394": { "label": "13/53", "naklon": 0 }, + "3308": { "label": "13/54", "naklon": 0 }, + "3847": { "label": "13/54/1", "naklon": 0 }, + "3312": { "label": "13/55", "naklon": 3 }, + "3309": { "label": "13/56", "naklon": 3 }, + "3311": { "label": "13/57", "naklon": 3 }, + "3310": { "label": "13/58", "naklon": 3 }, + "4365": { "label": "13/59", "naklon": 3 }, + "4093": { "label": "13/60/1", "naklon": 3 }, + "3304": { "label": "13/61", "naklon": 3 }, + "3307": { "label": "13/62", "naklon": 3 }, + "3271": { "label": "13/63", "naklon": 3 }, + "3301": { "label": "13/64", "naklon": 3 }, + "4366": { "label": "13/65", "naklon": 3 }, + "3300": { "label": "13/66", "naklon": 3 }, + "3185": { "label": "13/67", "naklon": 0 }, + "3184": { "label": "13/68", "naklon": 0 }, + "3188": { "label": "13/69", "naklon": 0 }, + "3343": { "label": "13/71", "naklon": 6 }, + "3819": { "label": "13/71/1", "naklon": 6 }, + "3880": { "label": "13/71/2", "naklon": 6 }, + "3348": { "label": "13/72", "naklon": 6 }, + "3344": { "label": "13/74", "naklon": 6 }, + "3346": { "label": "13/75", "naklon": 6 }, + "3597": { "label": "13/75/1", "naklon": 6 }, + "3345": { "label": "13/76", "naklon": 6 }, + "3322": { "label": "13/77", "naklon": 0 }, + "3325": { "label": "13/78", "naklon": 0 }, + "4310": { "label": "13/78/1", "naklon": 0 }, + "3315": { "label": "13/79", "naklon": 0 }, + "3328": { "label": "13/80", "naklon": 0 }, + "3321": { "label": "13/81", "naklon": 0 }, + "3324": { "label": "13/82", "naklon": 0 }, + "3140": { "label": "13/84", "naklon": 0 }, + "3153": { "label": "13/85", "naklon": 0 }, + "3145": { "label": "13/86", "naklon": 0 }, + "3134": { "label": "13/87", "naklon": 0 }, + "3151": { "label": "13/88", "naklon": 0 }, + "3143": { "label": "13/89", "naklon": 0 }, + "3318": { "label": "13/90", "naklon": 0 }, + "3347": { "label": "13/91", "naklon": 0 }, + "3314": { "label": "13/94", "naklon": 0 }, + "3331": { "label": "13/96", "naklon": 0 }, + "3327": { "label": "13/97", "naklon": 0 }, + "3329": { "label": "13/99", "naklon": 0 }, + "3337": { "label": "13/100", "naklon": 0 }, + "3330": { "label": "13/101", "naklon": 0 }, + "3335": { "label": "13/102", "naklon": 0 }, + "3420": { "label": "13/103", "naklon": 0 }, + "3421": { "label": "13/104", "naklon": 0 }, + "4361": { "label": "13/105", "naklon": 0 }, + "4362": { "label": "13/106", "naklon": 0 }, + "3526": { "label": "13/107", "naklon": 0 }, + "4424": { "label": "13/108", "naklon": null }, + "3561": { "label": "13/109", "naklon": null }, + "3527": { "label": "13/110", "naklon": null }, + "3521": { "label": "13/111", "naklon": null }, + "3552": { "label": "13/112", "naklon": null }, + "3544": { "label": "13/113", "naklon": null }, + "3534": { "label": "13/114", "naklon": null }, + "3516": { "label": "13/115", "naklon": null }, + "3513": { "label": "13/116", "naklon": null }, + "3565": { "label": "13/117", "naklon": null }, + "3866": { "label": "13/118", "naklon": null }, + "3136": { "label": "14/1", "naklon": 0 }, + "3137": { "label": "14/2", "naklon": 0 }, + "3135": { "label": "14/3", "naklon": 0 }, + "3149": { "label": "14/4", "naklon": 0 }, + "3142": { "label": "14/5", "naklon": 0 }, + "3342": { "label": "14/6", "naklon": 0 }, + "3340": { "label": "14/7", "naklon": 0 }, + "3152": { "label": "14/8", "naklon": 0 }, + "3886": { "label": "14/9", "naklon": 0 }, + "3341": { "label": "14/10", "naklon": null }, + "3352": { "label": "14/11", "naklon": null }, + "3396": { "label": "15/1", "naklon": 5 }, + "2784": { "label": "15/2", "naklon": 5 }, + "2788": { "label": "15/3", "naklon": 5 }, + "2801": { "label": "15/4", "naklon": 5 }, + "2815": { "label": "15/5", "naklon": 5 }, + "2829": { "label": "15/6", "naklon": 5 }, + "2796": { "label": "15/7", "naklon": 5 }, + "2803": { "label": "15/8", "naklon": 5 }, + "4304": { "label": "15/8/1", "naklon": 5 }, + "4311": { "label": "15/8/2", "naklon": 5 }, + "2821": { "label": "15/9", "naklon": 5 }, + "3400": { "label": "15/10", "naklon": 5 }, + "2799": { "label": "15/11", "naklon": 5 }, + "2804": { "label": "15/12", "naklon": 5 }, + "4303": { "label": "15/12/1", "naklon": 5 }, + "4309": { "label": "15/12/2", "naklon": 5 }, + "2806": { "label": "15/13", "naklon": 5 }, + "2787": { "label": "15/14", "naklon": 5 }, + "2809": { "label": "15/15", "naklon": 5 }, + "2814": { "label": "15/16", "naklon": 0 }, + "3934": { "label": "15/17", "naklon": 0 }, + "3192": { "label": "15/18", "naklon": 0 }, + "2812": { "label": "15/19", "naklon": 0 }, + "4070": { "label": "15/20", "naklon": 0 }, + "2826": { "label": "15/21", "naklon": 0 }, + "2808": { "label": "15/22", "naklon": 3 }, + "2795": { "label": "15/23", "naklon": 3 }, + "2807": { "label": "15/24", "naklon": 3 }, + "2831": { "label": "15/25", "naklon": 0 }, + "2862": { "label": "15/26", "naklon": null }, + "2861": { "label": "15/27", "naklon": 0 }, + "2866": { "label": "15/28", "naklon": 0 }, + "3546": { "label": "15/28/1", "naklon": 0 }, + "4146": { "label": "15/29", "naklon": 0 }, + "3001": { "label": "15/29/1", "naklon": 0 }, + "2835": { "label": "15/30", "naklon": 0 }, + "2874": { "label": "15/31", "naklon": 0 }, + "2852": { "label": "15/32", "naklon": 0 }, + "2851": { "label": "15/33", "naklon": 0 }, + "3560": { "label": "15/33/1", "naklon": 0 }, + "2858": { "label": "15/34", "naklon": 0 }, + "4306": { "label": "15/34/1", "naklon": 0 }, + "2856": { "label": "15/35", "naklon": 0 }, + "2847": { "label": "15/36", "naklon": 0 }, + "3556": { "label": "15/36/1", "naklon": 0 }, + "3950": { "label": "15/37", "naklon": 0 }, + "2848": { "label": "15/38", "naklon": 0 }, + "2863": { "label": "15/39", "naklon": 0 }, + "4313": { "label": "15/39/1", "naklon": 0 }, + "2873": { "label": "15/40", "naklon": 0 }, + "2984": { "label": "15/40/1", "naklon": 0 }, + "2854": { "label": "15/41", "naklon": 0 }, + "2859": { "label": "15/42", "naklon": 0 }, + "2872": { "label": "15/43", "naklon": 0 }, + "2849": { "label": "15/44", "naklon": 0 }, + "2864": { "label": "15/45", "naklon": 0 }, + "3553": { "label": "15/46", "naklon": null }, + "3021": { "label": "15/47", "naklon": null }, + "3008": { "label": "15/47/1", "naklon": null }, + "3017": { "label": "15/48", "naklon": null }, + "3014": { "label": "15/49", "naklon": null }, + "2981": { "label": "15/50", "naklon": null }, + "3020": { "label": "15/51", "naklon": null }, + "3027": { "label": "15/52", "naklon": null }, + "3006": { "label": "15/53", "naklon": null }, + "3012": { "label": "15/54", "naklon": null }, + "2738": { "label": "15/55", "naklon": 0 }, + "2725": { "label": "15/56", "naklon": 0 }, + "3016": { "label": "15/57", "naklon": null }, + "3005": { "label": "15/58", "naklon": null }, + "3009": { "label": "15/58/1", "naklon": null }, + "3010": { "label": "15/59", "naklon": 0 }, + "3538": { "label": "15/59/1", "naklon": 0 }, + "4145": { "label": "15/59/2", "naklon": 0 }, + "2713": { "label": "15/60", "naklon": 0 }, + "2789": { "label": "15/61", "naklon": 0 }, + "2736": { "label": "15/62", "naklon": 0 }, + "2739": { "label": "15/63", "naklon": 0 }, + "4346": { "label": "15/64", "naklon": 0 }, + "2731": { "label": "15/65", "naklon": 0 }, + "2818": { "label": "15/66", "naklon": 0 }, + "3557": { "label": "15/66/1", "naklon": 0 }, + "2822": { "label": "15/67", "naklon": 0 }, + "2833": { "label": "15/68", "naklon": 0 }, + "2834": { "label": "15/69", "naklon": 0 }, + "3097": { "label": "15/70", "naklon": 0 }, + "2824": { "label": "15/71", "naklon": 0 }, + "2828": { "label": "15/72", "naklon": 0 }, + "2600": { "label": "15/73", "naklon": 0 }, + "4314": { "label": "15/73/1", "naklon": 0 }, + "2832": { "label": "15/74", "naklon": 0 }, + "4360": { "label": "15/75", "naklon": 0 }, + "2846": { "label": "15/76", "naklon": 0 }, + "2584": { "label": "15/77", "naklon": 0 }, + "2843": { "label": "15/78", "naklon": 0 }, + "4308": { "label": "15/78/1", "naklon": 0 }, + "4144": { "label": "15/79", "naklon": null }, + "2844": { "label": "15/80", "naklon": 0 }, + "2842": { "label": "15/81", "naklon": 0 }, + "2838": { "label": "15/82", "naklon": 0 }, + "2837": { "label": "15/83", "naklon": null }, + "3555": { "label": "15/83/1", "naklon": null }, + "2839": { "label": "15/84", "naklon": 0 }, + "2830": { "label": "15/85", "naklon": 0 }, + "4066": { "label": "15/86", "naklon": 0 }, + "2836": { "label": "15/87", "naklon": 0 }, + "2911": { "label": "15/88", "naklon": 0 }, + "2825": { "label": "15/89", "naklon": 0 }, + "2811": { "label": "15/90", "naklon": 0 }, + "3740": { "label": "15/94", "naklon": 15 }, + "2734": { "label": "15/95", "naklon": 15 }, + "3105": { "label": "15/96", "naklon": 15 }, + "2732": { "label": "15/97", "naklon": 15 }, + "2727": { "label": "15/98", "naklon": 15 }, + "2735": { "label": "15/99", "naklon": 15 }, + "3926": { "label": "15/100", "naklon": 15 }, + "2918": { "label": "15/101", "naklon": 0 }, + "2705": { "label": "15/102", "naklon": 10 }, + "2708": { "label": "15/103", "naklon": 10 }, + "2721": { "label": "15/104", "naklon": 10 }, + "2719": { "label": "15/105", "naklon": 10 }, + "2919": { "label": "15/106", "naklon": 10 }, + "3101": { "label": "15/107", "naklon": 10 }, + "2853": { "label": "15/108", "naklon": 10 }, + "2715": { "label": "15/109", "naklon": 10 }, + "2712": { "label": "15/110", "naklon": 0 }, + "2711": { "label": "15/111", "naklon": 0 }, + "2709": { "label": "15/112", "naklon": 0 }, + "2710": { "label": "15/113", "naklon": 0 }, + "2907": { "label": "15/114", "naklon": 0 }, + "2906": { "label": "15/115", "naklon": 0 }, + "2908": { "label": "15/116", "naklon": 0 }, + "2901": { "label": "15/117", "naklon": 0 }, + "2913": { "label": "15/118", "naklon": 0 }, + "3656": { "label": "15/119", "naklon": 0 }, + "2781": { "label": "15/120", "naklon": 0 }, + "2802": { "label": "15/121", "naklon": 0 }, + "2791": { "label": "15/122", "naklon": 0 }, + "2783": { "label": "15/123", "naklon": 0 }, + "2794": { "label": "15/124", "naklon": 0 }, + "3139": { "label": "15/125", "naklon": 0 }, + "3229": { "label": "15/126", "naklon": 5 }, + "3239": { "label": "15/127", "naklon": 5 }, + "3230": { "label": "15/128", "naklon": 5 }, + "4016": { "label": "15/129", "naklon": null }, + "3608": { "label": "16/16A", "naklon": 0 }, + "4151": { "label": "16/16B", "naklon": 0 }, + "3710": { "label": "16/1", "naklon": 0 }, + "3726": { "label": "16/2", "naklon": 0 }, + "3743": { "label": "16/3", "naklon": 0 }, + "3724": { "label": "16/4", "naklon": 0 }, + "3712": { "label": "16/5", "naklon": 0 }, + "3739": { "label": "16/6", "naklon": 0 }, + "3742": { "label": "16/7", "naklon": 0 }, + "3731": { "label": "16/8", "naklon": 0 }, + "3727": { "label": "16/9", "naklon": 0 }, + "3729": { "label": "16/10", "naklon": 0 }, + "3736": { "label": "16/11", "naklon": 0 }, + "3713": { "label": "16/12", "naklon": 0 }, + "3715": { "label": "16/13", "naklon": 0 }, + "3733": { "label": "16/14", "naklon": 0 }, + "3732": { "label": "16/15", "naklon": 0 }, + "3634": { "label": "16/17", "naklon": 0 }, + "3610": { "label": "16/18", "naklon": 0 }, + "3626": { "label": "16/19", "naklon": 0 }, + "3618": { "label": "16/20", "naklon": 0 }, + "3619": { "label": "16/21", "naklon": 0 }, + "3628": { "label": "16/22", "naklon": 0 }, + "3615": { "label": "16/23", "naklon": 0 }, + "3609": { "label": "16/24", "naklon": 0 }, + "3606": { "label": "16/25", "naklon": 0 }, + "3624": { "label": "16/26", "naklon": 0 }, + "3627": { "label": "16/27", "naklon": 0 }, + "3607": { "label": "16/28", "naklon": 0 }, + "4370": { "label": "16/29", "naklon": 0 }, + "3692": { "label": "16/30", "naklon": 0 }, + "3614": { "label": "16/31", "naklon": 0 }, + "3623": { "label": "16/32", "naklon": 0 }, + "4373": { "label": "16/33", "naklon": 0 }, + "3620": { "label": "16/34", "naklon": 0 }, + "3685": { "label": "16/35", "naklon": 0 }, + "3616": { "label": "16/36", "naklon": 0 }, + "3686": { "label": "16/37", "naklon": 0 }, + "3688": { "label": "16/38", "naklon": 0 }, + "3684": { "label": "16/39", "naklon": 0 }, + "3825": { "label": "16/40", "naklon": 0 }, + "3865": { "label": "16/41", "naklon": 0 }, + "3824": { "label": "16/42", "naklon": 0 }, + "3871": { "label": "16/43", "naklon": 0 }, + "3801": { "label": "16/44", "naklon": 0 }, + "3862": { "label": "16/45", "naklon": 0 }, + "3876": { "label": "16/46", "naklon": 0 }, + "3861": { "label": "16/47", "naklon": 0 }, + "4215": { "label": "16/48", "naklon": 0 }, + "3605": { "label": "16/49", "naklon": 10 }, + "3603": { "label": "16/50", "naklon": 10 }, + "3592": { "label": "16/51", "naklon": 10 }, + "3598": { "label": "16/52", "naklon": 10 }, + "3594": { "label": "16/53", "naklon": 10 }, + "3593": { "label": "16/54", "naklon": 10 }, + "3630": { "label": "16/55", "naklon": 10 }, + "3763": { "label": "16/56", "naklon": 10 }, + "3746": { "label": "16/57", "naklon": 10 }, + "3699": { "label": "16/58", "naklon": 0 }, + "3698": { "label": "16/59", "naklon": 0 }, + "3709": { "label": "16/60", "naklon": null }, + "3708": { "label": "16/61", "naklon": 0 }, + "3703": { "label": "16/62", "naklon": null }, + "3700": { "label": "16/63", "naklon": 0 }, + "3701": { "label": "16/64", "naklon": null }, + "3704": { "label": "16/65", "naklon": 0 }, + "3707": { "label": "16/66", "naklon": null }, + "3810": { "label": "16/67", "naklon": 0 }, + "4208": { "label": "16/68", "naklon": null }, + "3867": { "label": "16/69", "naklon": 0 }, + "4372": { "label": "16/70", "naklon": null }, + "3881": { "label": "16/71", "naklon": 0 }, + "4204": { "label": "16/72", "naklon": null }, + "3869": { "label": "16/73", "naklon": 0 }, + "4202": { "label": "16/74", "naklon": null }, + "3830": { "label": "16/75", "naklon": 0 }, + "3870": { "label": "16/76", "naklon": null }, + "3964": { "label": "16/77", "naklon": 0 }, + "3849": { "label": "16/78", "naklon": 0 }, + "3694": { "label": "16/79", "naklon": null }, + "3717": { "label": "16/80", "naklon": 0 }, + "3877": { "label": "16/81", "naklon": null }, + "3755": { "label": "16/82", "naklon": 0 }, + "3725": { "label": "16/83", "naklon": null }, + "3716": { "label": "16/84", "naklon": 0 }, + "3696": { "label": "16/85", "naklon": null }, + "3702": { "label": "16/86", "naklon": 0 }, + "3706": { "label": "16/87", "naklon": null }, + "3850": { "label": "16/88", "naklon": 0 }, + "3848": { "label": "16/89", "naklon": null }, + "3737": { "label": "16/90", "naklon": null }, + "3705": { "label": "16/91", "naklon": 0 }, + "3723": { "label": "16/92", "naklon": null }, + "3842": { "label": "16/93", "naklon": 0 }, + "3735": { "label": "16/94", "naklon": null }, + "3719": { "label": "16/95", "naklon": 0 }, + "3697": { "label": "16/96", "naklon": 0 }, + "3711": { "label": "16/97", "naklon": 0 }, + "4107": { "label": "16/98", "naklon": null }, + "4112": { "label": "16/99", "naklon": 5 }, + "4106": { "label": "16/100", "naklon": 5 }, + "4111": { "label": "16/101", "naklon": 5 }, + "4091": { "label": "16/102", "naklon": null }, + "4104": { "label": "16/103", "naklon": 5 }, + "4094": { "label": "16/104", "naklon": null }, + "4089": { "label": "16/105", "naklon": 5 }, + "4095": { "label": "16/106", "naklon": null }, + "4102": { "label": "16/107", "naklon": 5 }, + "4105": { "label": "16/108", "naklon": null }, + "3859": { "label": "16/109", "naklon": null }, + "4090": { "label": "16/110", "naklon": 5 }, + "4110": { "label": "16/111", "naklon": null }, + "4097": { "label": "16/112", "naklon": 5 }, + "4099": { "label": "16/113", "naklon": null }, + "4096": { "label": "16/114", "naklon": null }, + "4101": { "label": "16/115", "naklon": 5 }, + "4109": { "label": "16/116", "naklon": null }, + "4092": { "label": "16/117", "naklon": 5 }, + "3631": { "label": "16/118", "naklon": null }, + "3632": { "label": "16/119", "naklon": 0 }, + "3641": { "label": "16/120", "naklon": null }, + "3638": { "label": "16/121", "naklon": 0 }, + "3637": { "label": "16/122", "naklon": null }, + "4142": { "label": "16/123", "naklon": null }, + "4147": { "label": "16/124", "naklon": 5 }, + "4139": { "label": "16/125", "naklon": 5 }, + "3172": { "label": "20/30A", "naklon": 2 }, + "3164": { "label": "20/30B", "naklon": 2 }, + "3247": { "label": "20/1", "naklon": 10 }, + "3296": { "label": "20/2", "naklon": 10 }, + "3246": { "label": "20/3", "naklon": 10 }, + "3270": { "label": "20/4", "naklon": 10 }, + "3294": { "label": "20/5", "naklon": 10 }, + "3298": { "label": "20/6", "naklon": 10 }, + "3297": { "label": "20/7", "naklon": 10 }, + "3293": { "label": "20/8", "naklon": 10 }, + "3299": { "label": "20/9", "naklon": 10 }, + "3295": { "label": "20/10", "naklon": 10 }, + "3244": { "label": "20/11", "naklon": 10 }, + "3249": { "label": "20/12", "naklon": 10 }, + "3268": { "label": "20/13", "naklon": 10 }, + "3245": { "label": "20/14", "naklon": 10 }, + "3278": { "label": "20/15", "naklon": 10 }, + "3280": { "label": "20/16", "naklon": 10 }, + "3292": { "label": "20/17", "naklon": 10 }, + "3287": { "label": "20/18", "naklon": 10 }, + "3282": { "label": "20/19", "naklon": 10 }, + "3273": { "label": "20/20", "naklon": 0 }, + "3157": { "label": "20/21", "naklon": 0 }, + "3283": { "label": "20/22", "naklon": 0 }, + "3159": { "label": "20/23", "naklon": 0 }, + "3289": { "label": "20/24", "naklon": 0 }, + "3163": { "label": "20/25", "naklon": 0 }, + "3126": { "label": "20/26", "naklon": 0 }, + "3171": { "label": "20/27", "naklon": 0 }, + "3162": { "label": "20/28", "naklon": 0 }, + "3279": { "label": "20/29", "naklon": 10 }, + "3173": { "label": "20/31", "naklon": 0 }, + "3127": { "label": "20/32", "naklon": 0 }, + "3131": { "label": "20/33", "naklon": 0 }, + "3129": { "label": "20/34", "naklon": 0 }, + "3276": { "label": "20/35", "naklon": 2 }, + "3290": { "label": "20/36", "naklon": 2 }, + "3132": { "label": "20/37", "naklon": 0 }, + "3138": { "label": "20/38", "naklon": 0 }, + "3272": { "label": "20/39", "naklon": 0 }, + "3291": { "label": "20/40", "naklon": 0 }, + "3277": { "label": "20/41", "naklon": 10 }, + "3286": { "label": "20/42", "naklon": 10 }, + "3281": { "label": "20/43", "naklon": 10 }, + "3288": { "label": "20/44", "naklon": 10 }, + "3284": { "label": "20/45", "naklon": 10 }, + "3167": { "label": "20/46", "naklon": 10 }, + "3872": { "label": "20/47", "naklon": 0 }, + "3124": { "label": "20/48", "naklon": 0 }, + "3133": { "label": "20/49", "naklon": 0 }, + "3158": { "label": "20/50", "naklon": 0 }, + "3169": { "label": "20/51", "naklon": 0 }, + "3146": { "label": "20/52", "naklon": 0 }, + "3160": { "label": "20/53", "naklon": 0 }, + "3248": { "label": "20/54", "naklon": 0 }, + "3156": { "label": "20/55", "naklon": 0 }, + "3161": { "label": "20/56", "naklon": 0 }, + "3170": { "label": "20/57", "naklon": 0 }, + "3168": { "label": "20/58", "naklon": 0 }, + "3125": { "label": "20/59", "naklon": 0 }, + "3166": { "label": "20/60", "naklon": 0 }, + "3130": { "label": "20/61", "naklon": 0 }, + "3563": { "label": "20/62", "naklon": 0 }, + "3550": { "label": "20/63", "naklon": null }, + "3269": { "label": "20/67", "naklon": 0 }, + "2921": { "label": "21/1", "naklon": 0 }, + "2707": { "label": "21/2", "naklon": 0 }, + "2723": { "label": "21/3", "naklon": 0 }, + "2716": { "label": "21/4", "naklon": 0 }, + "2717": { "label": "21/5", "naklon": 0 }, + "2720": { "label": "21/6", "naklon": 0 }, + "2722": { "label": "21/7", "naklon": 0 }, + "2718": { "label": "21/8", "naklon": 0 }, + "2724": { "label": "21/9", "naklon": 0 }, + "2742": { "label": "21/10", "naklon": 0 }, + "2743": { "label": "21/11", "naklon": 0 }, + "2733": { "label": "21/12", "naklon": 0 }, + "2903": { "label": "21/14", "naklon": 0 }, + "2917": { "label": "21/15", "naklon": 0 }, + "2897": { "label": "21/16", "naklon": 0 }, + "2914": { "label": "21/17", "naklon": 0 }, + "2898": { "label": "21/18", "naklon": 0 }, + "2773": { "label": "21/19", "naklon": 0 }, + "2895": { "label": "21/20", "naklon": 0 }, + "2896": { "label": "21/21", "naklon": 0 }, + "2771": { "label": "21/22", "naklon": 0 }, + "2772": { "label": "21/23", "naklon": 0 }, + "2793": { "label": "21/24", "naklon": 0 }, + "2902": { "label": "21/25", "naklon": 0 }, + "2910": { "label": "21/26", "naklon": 0 }, + "2909": { "label": "21/27", "naklon": 0 }, + "2920": { "label": "21/28", "naklon": 0 }, + "2916": { "label": "21/29", "naklon": 0 }, + "2904": { "label": "21/30", "naklon": 0 }, + "2915": { "label": "21/31", "naklon": 0 }, + "2905": { "label": "21/32", "naklon": 0 }, + "2900": { "label": "21/33", "naklon": 0 }, + "2899": { "label": "21/34", "naklon": 0 }, + "2741": { "label": "21/36", "naklon": 0 }, + "2714": { "label": "21/37", "naklon": 0 }, + "2701": { "label": "21/38", "naklon": 0 }, + "2703": { "label": "21/39", "naklon": 0 }, + "2704": { "label": "21/40", "naklon": 0 }, + "2702": { "label": "21/41", "naklon": 0 }, + "2706": { "label": "21/42", "naklon": 0 }, + "2776": { "label": "21/43", "naklon": 0 }, + "2770": { "label": "21/44", "naklon": 0 }, + "2786": { "label": "21/45", "naklon": 0 }, + "2779": { "label": "21/46", "naklon": 0 }, + "2782": { "label": "21/47", "naklon": 0 }, + "2785": { "label": "21/48", "naklon": 0 }, + "2769": { "label": "21/49", "naklon": 0 }, + "3354": { "label": "21/50", "naklon": 0 }, + "2778": { "label": "21/51", "naklon": 0 }, + "2775": { "label": "21/52", "naklon": 0 }, + "2780": { "label": "21/53", "naklon": 0 }, + "2790": { "label": "21/54", "naklon": 0 }, + "2792": { "label": "21/55", "naklon": 0 }, + "2774": { "label": "21/56", "naklon": 0 }, + "2630": { "label": "22/1", "naklon": 0 }, + "2631": { "label": "22/2", "naklon": 0 }, + "2632": { "label": "22/3", "naklon": 0 }, + "2633": { "label": "22/4", "naklon": 0 }, + "2634": { "label": "22/5", "naklon": 0 }, + "2636": { "label": "22/6", "naklon": 0 }, + "4367": { "label": "22/7", "naklon": 0 }, + "2637": { "label": "22/8", "naklon": 0 }, + "2638": { "label": "22/9", "naklon": 0 }, + "2639": { "label": "22/10", "naklon": 0 }, + "2640": { "label": "22/11", "naklon": 0 }, + "2641": { "label": "22/12", "naklon": 0 }, + "2642": { "label": "22/13", "naklon": 0 }, + "2643": { "label": "22/14", "naklon": 0 }, + "2644": { "label": "22/15", "naklon": 0 }, + "2645": { "label": "22/16", "naklon": 0 }, + "2646": { "label": "22/17", "naklon": 0 }, + "2647": { "label": "22/18", "naklon": 0 }, + "2648": { "label": "22/19", "naklon": 0 }, + "2649": { "label": "22/20", "naklon": 0 }, + "2650": { "label": "22/21", "naklon": 0 }, + "2651": { "label": "22/22", "naklon": 0 }, + "4103": { "label": "22/23", "naklon": 0 }, + "2653": { "label": "22/24", "naklon": 0 }, + "2654": { "label": "22/25", "naklon": 0 }, + "2655": { "label": "22/26", "naklon": 0 }, + "2656": { "label": "22/27", "naklon": 0 }, + "2657": { "label": "22/28", "naklon": 0 }, + "2658": { "label": "22/29", "naklon": 0 }, + "2659": { "label": "22/30", "naklon": 0 }, + "2660": { "label": "22/31", "naklon": 0 }, + "2661": { "label": "22/32", "naklon": 0 }, + "3015": { "label": "22/32/1", "naklon": 0 }, + "2662": { "label": "22/33", "naklon": 0 }, + "2663": { "label": "22/34", "naklon": 0 }, + "2664": { "label": "22/35", "naklon": 0 }, + "2665": { "label": "22/36", "naklon": 0 }, + "2666": { "label": "22/37", "naklon": 0 }, + "2667": { "label": "22/38", "naklon": 0 }, + "2668": { "label": "22/39", "naklon": 0 }, + "2669": { "label": "22/40", "naklon": null }, + "2670": { "label": "22/41", "naklon": null }, + "2671": { "label": "22/42", "naklon": null }, + "3087": { "label": "23/9A", "naklon": 10 }, + "3090": { "label": "23/9B", "naklon": 10 }, + "3075": { "label": "23/1", "naklon": 0 }, + "3089": { "label": "23/2", "naklon": 0 }, + "3088": { "label": "23/3", "naklon": 0 }, + "3228": { "label": "23/4", "naklon": 10 }, + "2751": { "label": "23/5", "naklon": 10 }, + "3243": { "label": "23/6", "naklon": 10 }, + "4349": { "label": "23/7", "naklon": 10 }, + "3102": { "label": "23/8", "naklon": 10 }, + "3099": { "label": "23/10", "naklon": 10 }, + "3103": { "label": "23/11", "naklon": 10 }, + "3093": { "label": "23/12", "naklon": 10 }, + "3098": { "label": "23/13", "naklon": 10 }, + "3092": { "label": "23/14", "naklon": 10 }, + "3233": { "label": "23/15", "naklon": 0 }, + "3095": { "label": "23/16", "naklon": 0 }, + "4074": { "label": "23/17", "naklon": 0 }, + "2729": { "label": "23/18", "naklon": 0 }, + "3234": { "label": "23/19", "naklon": 0 }, + "3094": { "label": "23/20", "naklon": 0 }, + "2817": { "label": "23/21", "naklon": 0 }, + "3226": { "label": "23/22", "naklon": 0 }, + "3225": { "label": "23/23", "naklon": 0 }, + "3237": { "label": "23/24", "naklon": 0 }, + "4250": { "label": "23/25", "naklon": 0 }, + "3059": { "label": "23/26", "naklon": 10 }, + "3238": { "label": "23/27", "naklon": 10 }, + "3242": { "label": "23/28", "naklon": 10 }, + "3236": { "label": "23/29", "naklon": 10 }, + "3112": { "label": "23/30", "naklon": 10 }, + "3224": { "label": "23/31", "naklon": 0 }, + "4298": { "label": "23/32", "naklon": 10 }, + "4150": { "label": "23/33", "naklon": 10 }, + "3091": { "label": "23/34", "naklon": 10 }, + "3771": { "label": "25/1", "naklon": 5 }, + "3777": { "label": "25/2", "naklon": 5 }, + "3749": { "label": "25/3", "naklon": 5 }, + "3769": { "label": "25/4", "naklon": 5 }, + "3765": { "label": "25/5", "naklon": 5 }, + "3785": { "label": "25/6", "naklon": 5 }, + "3761": { "label": "25/7", "naklon": 5 }, + "3758": { "label": "25/8", "naklon": 5 }, + "3766": { "label": "25/9", "naklon": 5 }, + "3779": { "label": "25/10", "naklon": 5 }, + "3899": { "label": "25/11", "naklon": 10 }, + "3922": { "label": "25/12", "naklon": 10 }, + "3912": { "label": "25/13", "naklon": 10 }, + "3933": { "label": "25/14", "naklon": 10 }, + "3921": { "label": "25/15", "naklon": 10 }, + "4300": { "label": "25/16", "naklon": 10 }, + "3927": { "label": "25/17", "naklon": 10 }, + "3212": { "label": "25/18", "naklon": 10 }, + "3208": { "label": "25/19", "naklon": 10 }, + "3207": { "label": "25/20", "naklon": 10 }, + "4294": { "label": "25/21", "naklon": 10 }, + "3209": { "label": "25/22", "naklon": 10 }, + "3745": { "label": "25/23", "naklon": 10 }, + "3762": { "label": "25/24", "naklon": 10 }, + "3215": { "label": "25/25", "naklon": 10 }, + "3210": { "label": "25/26", "naklon": 10 }, + "3211": { "label": "25/27", "naklon": 10 }, + "3206": { "label": "25/28", "naklon": 10 }, + "3918": { "label": "25/29", "naklon": 5 }, + "3928": { "label": "25/30", "naklon": 5 }, + "3917": { "label": "25/31", "naklon": 5 }, + "4029": { "label": "25/32", "naklon": 0 }, + "4038": { "label": "25/33", "naklon": 0 }, + "4022": { "label": "25/34", "naklon": 0 }, + "3937": { "label": "25/35", "naklon": 0 }, + "3190": { "label": "25/36", "naklon": 0 }, + "3835": { "label": "25/37", "naklon": 0 }, + "3201": { "label": "25/38", "naklon": 0 }, + "3193": { "label": "25/39", "naklon": 0 }, + "3191": { "label": "25/40", "naklon": 0 }, + "3203": { "label": "25/41", "naklon": 0 }, + "4301": { "label": "25/42", "naklon": 0 }, + "3223": { "label": "25/43", "naklon": 0 }, + "3202": { "label": "25/44", "naklon": 0 }, + "3205": { "label": "25/45", "naklon": 0 }, + "3194": { "label": "25/46", "naklon": 0 }, + "3198": { "label": "25/47", "naklon": 0 }, + "3204": { "label": "25/48", "naklon": 0 }, + "3200": { "label": "25/49", "naklon": 0 }, + "3216": { "label": "25/50", "naklon": 0 }, + "3932": { "label": "25/51", "naklon": 5 }, + "3923": { "label": "25/52", "naklon": 5 }, + "3913": { "label": "25/53", "naklon": 5 }, + "3900": { "label": "25/54", "naklon": 5 }, + "4189": { "label": "25/55", "naklon": 10 }, + "4191": { "label": "25/56", "naklon": 10 }, + "3790": { "label": "25/57", "naklon": 10 }, + "4190": { "label": "25/58", "naklon": 10 }, + "4302": { "label": "25/59", "naklon": 0 }, + "4351": { "label": "25/60", "naklon": 0 }, + "4075": { "label": "25/61", "naklon": 0 }, + "4071": { "label": "25/62", "naklon": 0 }, + "3784": { "label": "25/63", "naklon": 0 }, + "4065": { "label": "25/64", "naklon": 0 }, + "4297": { "label": "25/65", "naklon": 0 }, + "4295": { "label": "25/66", "naklon": 0 }, + "4299": { "label": "25/67", "naklon": 0 }, + "3772": { "label": "25/68", "naklon": 0 }, + "3941": { "label": "25/69", "naklon": 0 }, + "3782": { "label": "25/70", "naklon": 0 }, + "4068": { "label": "25/71", "naklon": 0 }, + "4073": { "label": "25/72", "naklon": 0 }, + "3901": { "label": "25/73", "naklon": 5 }, + "4296": { "label": "25/74", "naklon": 5 }, + "3910": { "label": "25/75", "naklon": 5 }, + "4293": { "label": "25/76", "naklon": 5 }, + "3919": { "label": "25/77", "naklon": 5 }, + "3924": { "label": "25/78", "naklon": 5 }, + "3909": { "label": "25/79", "naklon": 5 }, + "3896": { "label": "25/80", "naklon": 5 }, + "3911": { "label": "25/81", "naklon": 5 }, + "2819": { "label": "25/82", "naklon": 15 }, + "3776": { "label": "25/83", "naklon": 15 }, + "3752": { "label": "25/84", "naklon": 15 }, + "4353": { "label": "25/85", "naklon": 15 }, + "3791": { "label": "25/86", "naklon": 0 }, + "3770": { "label": "25/87", "naklon": 0 }, + "3760": { "label": "25/88", "naklon": 0 }, + "3115": { "label": "25/89", "naklon": 0 }, + "3738": { "label": "25/90", "naklon": 0 }, + "3748": { "label": "25/91", "naklon": 0 }, + "3753": { "label": "25/92", "naklon": 0 }, + "3775": { "label": "25/93", "naklon": 0 }, + "3778": { "label": "25/94", "naklon": 5 }, + "4078": { "label": "25/95", "naklon": 5 }, + "4088": { "label": "25/96", "naklon": 5 }, + "3856": { "label": "25/97", "naklon": 5 }, + "4084": { "label": "25/98", "naklon": 5 }, + "4069": { "label": "25/99", "naklon": 5 }, + "4188": { "label": "25/100", "naklon": 5 }, + "4064": { "label": "25/101", "naklon": 5 }, + "3792": { "label": "25/102", "naklon": 5 }, + "3780": { "label": "25/103", "naklon": 5 }, + "4034": { "label": "25/104", "naklon": 5 }, + "4072": { "label": "25/105", "naklon": 5 }, + "3884": { "label": "25/106", "naklon": 5 }, + "3793": { "label": "25/107", "naklon": 5 }, + "3863": { "label": "25/108", "naklon": 5 }, + "3855": { "label": "25/109", "naklon": 5 }, + "3846": { "label": "33/1", "naklon": 0 }, + "3943": { "label": "33/2", "naklon": 0 }, + "3903": { "label": "33/3", "naklon": 0 }, + "3982": { "label": "33/4", "naklon": 0 }, + "3879": { "label": "33/5", "naklon": 0 }, + "3887": { "label": "33/6", "naklon": 0 }, + "3920": { "label": "33/7", "naklon": 5 }, + "3942": { "label": "33/8", "naklon": 5 }, + "3829": { "label": "33/9", "naklon": null }, + "3452": { "label": "34/79A", "naklon": 6 }, + "3460": { "label": "34/79B", "naklon": 6 }, + "3443": { "label": "34/90A", "naklon": 6 }, + "3445": { "label": "34/90B", "naklon": 6 }, + "3457": { "label": "34/90C", "naklon": 6 }, + "3461": { "label": "34/97A", "naklon": 6 }, + "3463": { "label": "34/97B", "naklon": 6 }, + "3426": { "label": "34/98A", "naklon": 6 }, + "3444": { "label": "34/98B", "naklon": 6 }, + "3453": { "label": "34/99A", "naklon": 6 }, + "3455": { "label": "34/99B", "naklon": 6 }, + "4009": { "label": "34/1", "naklon": 0 }, + "3602": { "label": "34/2", "naklon": 0 }, + "3441": { "label": "34/3", "naklon": 0 }, + "3464": { "label": "34/4", "naklon": 0 }, + "3883": { "label": "34/5", "naklon": 0 }, + "4098": { "label": "34/6", "naklon": 0 }, + "4003": { "label": "34/7", "naklon": 0 }, + "4004": { "label": "34/8", "naklon": 0 }, + "3888": { "label": "34/9", "naklon": 0 }, + "3997": { "label": "34/10", "naklon": 0 }, + "4006": { "label": "34/11", "naklon": 0 }, + "4000": { "label": "34/12", "naklon": 0 }, + "4011": { "label": "34/13", "naklon": 0 }, + "3999": { "label": "34/14", "naklon": 0 }, + "3981": { "label": "34/15", "naklon": 0 }, + "3988": { "label": "34/16", "naklon": 0 }, + "3986": { "label": "34/17", "naklon": 0 }, + "3998": { "label": "34/18", "naklon": 0 }, + "3983": { "label": "34/19", "naklon": 0 }, + "4005": { "label": "34/20", "naklon": 0 }, + "4001": { "label": "34/21", "naklon": 0 }, + "4008": { "label": "34/22", "naklon": 0 }, + "4002": { "label": "34/23", "naklon": 0 }, + "3996": { "label": "34/24", "naklon": 0 }, + "4007": { "label": "34/25", "naklon": 0 }, + "4113": { "label": "34/26", "naklon": 15 }, + "3595": { "label": "34/27", "naklon": 5 }, + "3599": { "label": "34/28", "naklon": 5 }, + "3601": { "label": "34/29", "naklon": 5 }, + "4205": { "label": "34/30", "naklon": 0 }, + "3987": { "label": "34/31", "naklon": null }, + "4214": { "label": "34/32", "naklon": 0 }, + "4226": { "label": "34/33", "naklon": 0 }, + "4209": { "label": "34/34", "naklon": 0 }, + "4201": { "label": "34/35", "naklon": 0 }, + "3440": { "label": "34/36", "naklon": 0 }, + "3465": { "label": "34/37", "naklon": 0 }, + "3446": { "label": "34/38", "naklon": 0 }, + "4039": { "label": "34/39", "naklon": 5 }, + "4057": { "label": "34/40", "naklon": 5 }, + "3985": { "label": "34/41", "naklon": 0 }, + "3882": { "label": "34/42", "naklon": 0 }, + "4040": { "label": "34/43", "naklon": 5 }, + "3231": { "label": "34/44", "naklon": 0 }, + "3227": { "label": "34/45", "naklon": 0 }, + "3431": { "label": "34/46", "naklon": 0 }, + "4013": { "label": "34/47", "naklon": 0 }, + "4045": { "label": "34/48", "naklon": 0 }, + "3949": { "label": "34/49", "naklon": 0 }, + "3953": { "label": "34/50", "naklon": 0 }, + "3952": { "label": "34/51", "naklon": 0 }, + "3995": { "label": "34/52", "naklon": 0 }, + "3992": { "label": "34/53", "naklon": 0 }, + "4198": { "label": "34/54", "naklon": 0 }, + "3935": { "label": "34/55", "naklon": 0 }, + "4050": { "label": "34/56", "naklon": 0 }, + "4049": { "label": "34/57", "naklon": 0 }, + "4054": { "label": "34/58", "naklon": 0 }, + "3663": { "label": "34/59", "naklon": 6 }, + "3661": { "label": "34/60", "naklon": 6 }, + "3664": { "label": "34/61", "naklon": 6 }, + "3660": { "label": "34/62", "naklon": 6 }, + "3662": { "label": "34/63", "naklon": 6 }, + "3665": { "label": "34/65", "naklon": 6 }, + "3667": { "label": "34/66", "naklon": 6 }, + "3675": { "label": "34/67", "naklon": 6 }, + "3666": { "label": "34/68", "naklon": 6 }, + "3652": { "label": "34/69", "naklon": 6 }, + "3458": { "label": "34/70", "naklon": 6 }, + "4425": { "label": "34/70/1", "naklon": 6 }, + "3459": { "label": "34/71", "naklon": 6 }, + "3435": { "label": "34/72", "naklon": 6 }, + "3448": { "label": "34/73", "naklon": 6 }, + "3451": { "label": "34/74", "naklon": 6 }, + "3442": { "label": "34/75", "naklon": 6 }, + "3449": { "label": "34/76", "naklon": 6 }, + "3450": { "label": "34/77", "naklon": 6 }, + "3433": { "label": "34/78", "naklon": 6 }, + "3432": { "label": "34/80", "naklon": 12 }, + "3470": { "label": "34/81", "naklon": 12 }, + "3438": { "label": "34/82", "naklon": 12 }, + "3439": { "label": "34/83", "naklon": 12 }, + "4028": { "label": "34/84", "naklon": 5 }, + "3596": { "label": "34/85", "naklon": 5 }, + "4021": { "label": "34/86", "naklon": 5 }, + "3437": { "label": "34/87", "naklon": 12 }, + "3428": { "label": "34/88", "naklon": 12 }, + "3430": { "label": "34/89", "naklon": 12 }, + "3454": { "label": "34/91", "naklon": 6 }, + "3492": { "label": "34/92", "naklon": 6 }, + "3462": { "label": "34/93", "naklon": 6 }, + "3427": { "label": "34/94", "naklon": 6 }, + "3434": { "label": "34/95", "naklon": 6 }, + "3456": { "label": "34/96", "naklon": 6 }, + "4307": { "label": "34/98/1", "naklon": 6 }, + "3968": { "label": "35/1", "naklon": 0 }, + "3969": { "label": "35/2", "naklon": 0 }, + "3947": { "label": "35/3", "naklon": 0 }, + "3979": { "label": "35/4", "naklon": 0 }, + "3959": { "label": "35/5", "naklon": 0 }, + "3948": { "label": "35/6", "naklon": 0 }, + "3961": { "label": "35/7", "naklon": 0 }, + "3956": { "label": "35/8", "naklon": 0 }, + "3604": { "label": "35/9", "naklon": 0 }, + "3944": { "label": "35/10", "naklon": 0 }, + "3960": { "label": "35/11", "naklon": 0 }, + "3958": { "label": "35/12", "naklon": 0 }, + "4036": { "label": "35/13", "naklon": 5 }, + "3893": { "label": "35/18", "naklon": 5 }, + "4108": { "label": "35/19", "naklon": 5 }, + "4017": { "label": "35/20", "naklon": 5 }, + "3963": { "label": "35/21", "naklon": 0 }, + "3658": { "label": "35/22", "naklon": 0 }, + "3975": { "label": "35/23", "naklon": 0 }, + "3980": { "label": "35/24", "naklon": 0 }, + "4012": { "label": "35/25", "naklon": 0 }, + "3655": { "label": "35/26", "naklon": 0 }, + "3962": { "label": "35/27", "naklon": 0 }, + "3945": { "label": "35/28", "naklon": 0 }, + "3569": { "label": "35/29", "naklon": 0 }, + "3429": { "label": "35/30", "naklon": 0 }, + "3657": { "label": "35/31", "naklon": 0 }, + "3646": { "label": "35/32", "naklon": 0 }, + "3622": { "label": "35/33", "naklon": 0 }, + "3612": { "label": "35/34", "naklon": 0 }, + "3955": { "label": "35/35", "naklon": 0 }, + "3878": { "label": "35/37", "naklon": 0 }, + "3965": { "label": "35/38", "naklon": 0 }, + "3970": { "label": "35/39", "naklon": 0 }, + "3611": { "label": "35/40", "naklon": 0 }, + "2635": { "label": "35/41", "naklon": 0 }, + "3978": { "label": "35/42", "naklon": 0 }, + "4213": { "label": "35/43", "naklon": 0 }, + "3984": { "label": "35/44", "naklon": 0 }, + "4218": { "label": "35/45", "naklon": 0 }, + "3973": { "label": "35/46", "naklon": 0 }, + "3974": { "label": "35/47", "naklon": 0 }, + "3759": { "label": "35/48", "naklon": 0 }, + "3844": { "label": "35/49", "naklon": 0 }, + "3804": { "label": "35/50", "naklon": 0 }, + "3831": { "label": "35/51", "naklon": 0 }, + "3643": { "label": "35/52", "naklon": 0 }, + "3966": { "label": "35/53", "naklon": 0 }, + "3971": { "label": "35/54", "naklon": 0 }, + "3650": { "label": "35/55", "naklon": 6 }, + "3651": { "label": "35/56", "naklon": 6 }, + "3669": { "label": "35/57", "naklon": 6 }, + "3648": { "label": "35/58", "naklon": 6 }, + "3645": { "label": "35/59", "naklon": 6 }, + "3659": { "label": "35/60", "naklon": 6 }, + "3647": { "label": "35/61", "naklon": 6 }, + "3644": { "label": "35/62", "naklon": 6 }, + "3671": { "label": "35/63", "naklon": 6 }, + "3682": { "label": "35/64", "naklon": 6 }, + "3672": { "label": "35/65", "naklon": 6 }, + "3683": { "label": "35/66", "naklon": 6 }, + "3673": { "label": "35/67", "naklon": 6 }, + "3674": { "label": "35/68", "naklon": 6 }, + "3679": { "label": "35/69", "naklon": 6 }, + "3649": { "label": "35/70", "naklon": 6 }, + "3687": { "label": "35/71", "naklon": 6 }, + "3677": { "label": "35/72", "naklon": 6 }, + "3690": { "label": "35/73", "naklon": 6 }, + "3691": { "label": "35/74", "naklon": 6 }, + "3676": { "label": "35/75", "naklon": 6 }, + "3680": { "label": "35/76", "naklon": 6 }, + "3668": { "label": "35/77", "naklon": 6 }, + "3681": { "label": "35/78", "naklon": 6 }, + "3670": { "label": "35/79", "naklon": 6 }, + "3689": { "label": "35/80", "naklon": 6 }, + "3678": { "label": "35/81", "naklon": 6 }, + "3693": { "label": "35/82", "naklon": 6 }, + "3654": { "label": "35/83", "naklon": null }, + "4086": { "label": "36/1", "naklon": 0 }, + "4085": { "label": "36/2", "naklon": 0 }, + "4083": { "label": "36/3", "naklon": 0 }, + "4087": { "label": "36/4", "naklon": 0 }, + "4077": { "label": "36/5", "naklon": 0 }, + "4082": { "label": "36/6", "naklon": 0 }, + "4186": { "label": "36/7", "naklon": 0 }, + "4206": { "label": "36/8", "naklon": 0 }, + "4080": { "label": "36/9", "naklon": 0 }, + "4081": { "label": "36/10", "naklon": 0 }, + "4210": { "label": "36/11", "naklon": 0 }, + "4079": { "label": "36/12", "naklon": 0 }, + "4076": { "label": "36/13", "naklon": 0 }, + "3852": { "label": "36/14", "naklon": 0 }, + "2813": { "label": "36/15", "naklon": 0 }, + "4219": { "label": "36/16", "naklon": 0 }, + "3104": { "label": "37/1A", "naklon": 15 }, + "3121": { "label": "37/1B", "naklon": 15 }, + "3113": { "label": "37/2", "naklon": 10 }, + "3118": { "label": "37/3", "naklon": 10 }, + "3111": { "label": "37/4", "naklon": 10 }, + "4020": { "label": "37/5", "naklon": 10 }, + "3119": { "label": "37/6", "naklon": 10 }, + "3110": { "label": "37/7", "naklon": 10 }, + "3108": { "label": "37/8", "naklon": 10 }, + "3107": { "label": "37/12", "naklon": 0 }, + "3199": { "label": "37/13", "naklon": 0 }, + "3120": { "label": "37/14", "naklon": 0 }, + "3122": { "label": "37/15", "naklon": 0 }, + "3908": { "label": "37/16", "naklon": 0 }, + "3114": { "label": "37/17", "naklon": 0 }, + "3105": { "label": "37/18", "naklon": 0 }, + "3116": { "label": "37/19", "naklon": 0 }, + "3106": { "label": "37/20", "naklon": 0 }, + "2887": { "label": "37/21", "naklon": 5 }, + "2888": { "label": "37/22", "naklon": 5 }, + "2877": { "label": "37/23", "naklon": 5 }, + "2891": { "label": "37/24", "naklon": 5 }, + "2886": { "label": "37/25", "naklon": 5 }, + "2892": { "label": "37/26", "naklon": 5 }, + "2882": { "label": "37/27", "naklon": 5 }, + "2883": { "label": "37/28", "naklon": 5 }, + "2876": { "label": "37/29", "naklon": 5 }, + "3109": { "label": "37/30", "naklon": 5 }, + "4152": { "label": "37/31", "naklon": 5 }, + "3117": { "label": "37/32", "naklon": 5 }, + "2870": { "label": "37/33", "naklon": 5 }, + "2867": { "label": "37/34", "naklon": 0 }, + "2865": { "label": "37/35", "naklon": 0 }, + "3096": { "label": "37/36", "naklon": 0 }, + "2871": { "label": "37/37", "naklon": 0 }, + "2884": { "label": "37/38", "naklon": 0 }, + "2855": { "label": "37/39", "naklon": 0 }, + "2878": { "label": "37/40", "naklon": 0 }, + "2889": { "label": "37/41", "naklon": 0 }, + "2879": { "label": "37/42", "naklon": 0 }, + "2850": { "label": "37/43", "naklon": 0 }, + "2894": { "label": "37/44", "naklon": 0 }, + "2880": { "label": "37/45", "naklon": 0 }, + "2893": { "label": "37/46", "naklon": 0 }, + "2890": { "label": "37/47", "naklon": 0 }, + "4355": { "label": "37/48", "naklon": 0 }, + "2885": { "label": "37/49", "naklon": 0 }, + "2875": { "label": "37/50", "naklon": 0 }, + "3486": { "label": "38/30A", "naklon": 5 }, + "3714": { "label": "38/30B", "naklon": 0 }, + "3483": { "label": "38/32A", "naklon": 5 }, + "3496": { "label": "38/32B", "naklon": 0 }, + "3487": { "label": "38/35A", "naklon": 5 }, + "3498": { "label": "38/35B", "naklon": 5 }, + "3578": { "label": "38/38A", "naklon": 5 }, + "3508": { "label": "38/38B", "naklon": 5 }, + "3787": { "label": "38/59A", "naklon": 5 }, + "3491": { "label": "38/59B", "naklon": 5 }, + "3568": { "label": "38/1", "naklon": null }, + "3502": { "label": "38/2", "naklon": 0 }, + "3836": { "label": "38/3", "naklon": 0 }, + "3588": { "label": "38/4", "naklon": 0 }, + "3493": { "label": "38/5", "naklon": 0 }, + "3580": { "label": "38/6", "naklon": 0 }, + "3572": { "label": "38/7", "naklon": 0 }, + "3506": { "label": "38/8", "naklon": 0 }, + "3503": { "label": "38/9", "naklon": 0 }, + "3579": { "label": "38/10", "naklon": 0 }, + "3586": { "label": "38/11", "naklon": 0 }, + "3495": { "label": "38/12", "naklon": 5 }, + "3492": { "label": "38/13", "naklon": 5 }, + "3532": { "label": "38/14", "naklon": 5 }, + "3574": { "label": "38/15", "naklon": 5 }, + "4140": { "label": "38/16", "naklon": 5 }, + "3795": { "label": "38/17", "naklon": 5 }, + "3788": { "label": "38/18", "naklon": 5 }, + "3796": { "label": "38/19", "naklon": 5 }, + "3797": { "label": "38/20", "naklon": 5 }, + "3798": { "label": "38/21", "naklon": 5 }, + "3786": { "label": "38/22", "naklon": 5 }, + "4067": { "label": "38/23", "naklon": 5 }, + "3773": { "label": "38/24", "naklon": 5 }, + "3774": { "label": "38/25", "naklon": 5 }, + "3789": { "label": "38/26", "naklon": 5 }, + "3520": { "label": "38/27", "naklon": null }, + "3577": { "label": "38/29", "naklon": 5 }, + "3530": { "label": "38/31", "naklon": null }, + "3488": { "label": "38/33", "naklon": 5 }, + "3505": { "label": "38/34", "naklon": 5 }, + "3497": { "label": "38/36", "naklon": 5 }, + "3490": { "label": "38/37", "naklon": 5 }, + "3585": { "label": "38/39", "naklon": 5 }, + "3582": { "label": "38/40", "naklon": 5 }, + "3507": { "label": "38/41", "naklon": 5 }, + "3484": { "label": "38/42", "naklon": 5 }, + "3501": { "label": "38/43", "naklon": 5 }, + "3581": { "label": "38/44", "naklon": 5 }, + "4192": { "label": "38/45", "naklon": 5 }, + "3576": { "label": "38/46", "naklon": 5 }, + "3489": { "label": "38/47", "naklon": 5 }, + "3573": { "label": "38/48", "naklon": 5 }, + "3504": { "label": "38/49", "naklon": 5 }, + "3794": { "label": "38/50", "naklon": 5 }, + "3485": { "label": "38/51", "naklon": 5 }, + "3482": { "label": "38/52", "naklon": 5 }, + "3575": { "label": "38/53", "naklon": 5 }, + "3499": { "label": "38/54", "naklon": 5 }, + "3494": { "label": "38/55", "naklon": 5 }, + "3583": { "label": "38/56", "naklon": 5 }, + "3570": { "label": "38/57", "naklon": 5 }, + "3500": { "label": "38/58", "naklon": 0 }, + "3510": { "label": "38/63", "naklon": null }, + "3512": { "label": "38/64", "naklon": null }, + "3535": { "label": "38/67", "naklon": null }, + "3531": { "label": "38/68", "naklon": null }, + "3537": { "label": "38/69", "naklon": null }, + "3522": { "label": "39/1", "naklon": 10 }, + "4018": { "label": "39/2", "naklon": 10 }, + "4019": { "label": "39/3", "naklon": 10 }, + "4154": { "label": "39/4", "naklon": 5 }, + "3907": { "label": "39/5", "naklon": 5 }, + "4148": { "label": "39/6", "naklon": 0 }, + "4153": { "label": "39/7", "naklon": 0 }, + "3938": { "label": "39/8", "naklon": 0 }, + "3802": { "label": "39/9", "naklon": 0 }, + "4015": { "label": "39/10", "naklon": 0 }, + "3929": { "label": "39/11", "naklon": 0 }, + "3946": { "label": "39/12", "naklon": 0 }, + "4014": { "label": "39/13", "naklon": 0 }, + "4155": { "label": "39/14", "naklon": 0 }, + "4149": { "label": "39/15", "naklon": 0 }, + "3642": { "label": "39/16", "naklon": 0 }, + "3636": { "label": "39/17", "naklon": 5 }, + "3991": { "label": "39/18", "naklon": 0 }, + "3994": { "label": "39/19", "naklon": 0 }, + "3990": { "label": "39/20", "naklon": 0 }, + "3967": { "label": "39/21", "naklon": 0 }, + "3977": { "label": "39/22", "naklon": 0 }, + "3757": { "label": "39/23", "naklon": 15 }, + "3633": { "label": "39/24", "naklon": 15 }, + "3744": { "label": "39/25", "naklon": 15 }, + "4023": { "label": "39/26", "naklon": 5 }, + "3720": { "label": "39/27", "naklon": 5 }, + "3734": { "label": "39/28", "naklon": 5 }, + "3741": { "label": "39/29", "naklon": 5 }, + "3721": { "label": "39/30", "naklon": 5 }, + "3845": { "label": "39/31", "naklon": 0 }, + "3840": { "label": "39/32", "naklon": 0 }, + "3837": { "label": "39/33", "naklon": null }, + "3839": { "label": "39/34", "naklon": 0 }, + "3542": { "label": "41/1", "naklon": null }, + "3566": { "label": "41/2", "naklon": null }, + "3548": { "label": "41/3", "naklon": null }, + "3515": { "label": "41/4", "naklon": null }, + "3559": { "label": "41/5", "naklon": null }, + "3509": { "label": "41/6", "naklon": null }, + "3524": { "label": "41/7", "naklon": null }, + "3518": { "label": "41/8", "naklon": null }, + "3182": { "label": "41/9", "naklon": null }, + "3187": { "label": "41/10", "naklon": null }, + "3195": { "label": "41/11", "naklon": 0 }, + "3857": { "label": "41/12", "naklon": 0 }, + "3183": { "label": "41/13", "naklon": 0 }, + "3177": { "label": "41/14", "naklon": 0 }, + "3189": { "label": "41/15", "naklon": 0 }, + "3186": { "label": "41/16", "naklon": 0 }, + "3178": { "label": "42/1", "naklon": 0 }, + "3219": { "label": "42/2", "naklon": 0 }, + "3475": { "label": "42/3", "naklon": 0 }, + "3175": { "label": "42/4", "naklon": 0 }, + "3222": { "label": "42/5", "naklon": 0 }, + "3221": { "label": "42/6", "naklon": 0 }, + "3181": { "label": "42/7", "naklon": 0 }, + "3180": { "label": "42/8", "naklon": 0 }, + "3218": { "label": "42/9", "naklon": 0 }, + "3176": { "label": "42/10", "naklon": 0 }, + "3174": { "label": "42/11", "naklon": 0 }, + "3220": { "label": "42/12", "naklon": 0 }, + "3533": { "label": "42/13", "naklon": null }, + "3543": { "label": "42/14", "naklon": null }, + "3554": { "label": "42/15", "naklon": null }, + "3549": { "label": "42/16", "naklon": null }, + "2857": { "label": "43/1", "naklon": 5 }, + "2752": { "label": "43/2", "naklon": 5 }, + "2753": { "label": "43/3", "naklon": 5 }, + "3024": { "label": "43/4", "naklon": 5 }, + "2754": { "label": "43/5", "naklon": 5 }, + "4423": { "label": "43/6", "naklon": 5 }, + "4368": { "label": "43/7", "naklon": 5 }, + "2978": { "label": "43/8", "naklon": 5 }, + "2868": { "label": "43/9", "naklon": 5 }, + "4377": { "label": "43/10", "naklon": 5 }, + "2757": { "label": "43/11", "naklon": 5 }, + "2970": { "label": "43/12", "naklon": 5 }, + "2758": { "label": "43/13", "naklon": 5 }, + "4378": { "label": "43/14", "naklon": 5 }, + "2759": { "label": "43/15", "naklon": 5 }, + "4342": { "label": "43/16", "naklon": 5 }, + "3026": { "label": "43/17", "naklon": null }, + "2986": { "label": "43/18", "naklon": null }, + "4343": { "label": "43/19", "naklon": null }, + "2760": { "label": "43/20", "naklon": null }, + "4379": { "label": "43/21", "naklon": null }, + "2971": { "label": "43/22", "naklon": null }, + "2761": { "label": "43/23", "naklon": null }, + "2762": { "label": "43/24", "naklon": null }, + "4339": { "label": "43/25", "naklon": null }, + "4380": { "label": "43/26", "naklon": null }, + "2975": { "label": "43/27", "naklon": null }, + "3003": { "label": "43/28", "naklon": null }, + "4338": { "label": "43/29", "naklon": null }, + "3002": { "label": "43/30", "naklon": null }, + "4345": { "label": "43/31", "naklon": null }, + "2979": { "label": "43/32", "naklon": null }, + "2989": { "label": "43/33", "naklon": null }, + "2996": { "label": "43/34", "naklon": null }, + "2972": { "label": "43/35", "naklon": null }, + "2988": { "label": "43/36", "naklon": null }, + "4344": { "label": "43/37", "naklon": null }, + "3022": { "label": "43/38", "naklon": null }, + "4341": { "label": "43/39", "naklon": null }, + "2983": { "label": "43/40", "naklon": null }, + "2995": { "label": "43/41", "naklon": null }, + "2763": { "label": "43/42", "naklon": null }, + "2764": { "label": "43/43", "naklon": null }, + "2765": { "label": "43/44", "naklon": null }, + "2766": { "label": "43/45", "naklon": null }, + "2767": { "label": "43/46", "naklon": null }, + "2768": { "label": "43/47", "naklon": null }, + "3018": { "label": "43/48", "naklon": null }, + "2982": { "label": "43/49", "naklon": null }, + "3019": { "label": "43/50", "naklon": 0 }, + "3013": { "label": "43/51", "naklon": null }, + "3007": { "label": "43/52", "naklon": null }, + "2980": { "label": "43/53", "naklon": null }, + "3011": { "label": "43/54", "naklon": null }, + "2672": { "label": "43/55", "naklon": null }, + "2673": { "label": "43/56", "naklon": null }, + "2674": { "label": "43/57", "naklon": null }, + "2675": { "label": "43/58", "naklon": null }, + "2676": { "label": "43/59", "naklon": null }, + "2677": { "label": "43/60", "naklon": null }, + "2678": { "label": "43/61", "naklon": null }, + "2679": { "label": "43/62", "naklon": null }, + "2680": { "label": "43/63", "naklon": null }, + "2840": { "label": "43/64", "naklon": null }, + "2682": { "label": "43/65", "naklon": null }, + "2683": { "label": "43/66", "naklon": null }, + "2684": { "label": "43/67", "naklon": 0 }, + "2685": { "label": "43/68", "naklon": null }, + "2686": { "label": "43/69", "naklon": null }, + "2687": { "label": "43/70", "naklon": null }, + "2688": { "label": "43/71", "naklon": null }, + "2689": { "label": "43/72", "naklon": null }, + "2690": { "label": "43/73", "naklon": null }, + "2691": { "label": "43/74", "naklon": null }, + "2692": { "label": "43/75", "naklon": null }, + "2693": { "label": "43/76", "naklon": 0 }, + "2694": { "label": "43/77", "naklon": null }, + "2695": { "label": "43/78", "naklon": null }, + "2696": { "label": "43/79", "naklon": 0 }, + "2697": { "label": "43/80", "naklon": null }, + "2698": { "label": "43/81", "naklon": 0 }, + "2699": { "label": "43/82", "naklon": null }, + "2700": { "label": "43/83", "naklon": 0 }, + "2744": { "label": "43/84", "naklon": null }, + "2745": { "label": "43/85", "naklon": 0 }, + "2746": { "label": "43/86", "naklon": null }, + "2747": { "label": "43/87", "naklon": 0 }, + "2748": { "label": "43/88", "naklon": null }, + "2749": { "label": "43/89", "naklon": 0 }, + "2841": { "label": "43/90", "naklon": null }, + "4237": { "label": "45/1", "naklon": 5 }, + "4226": { "label": "45/2", "naklon": 5 }, + "4242": { "label": "45/3", "naklon": 5 }, + "4179": { "label": "45/4", "naklon": 5 }, + "4247": { "label": "45/5", "naklon": 5 }, + "4245": { "label": "45/6", "naklon": 5 }, + "3872": { "label": "45/7", "naklon": 5 }, + "4175": { "label": "45/8", "naklon": 5 }, + "4236": { "label": "45/9", "naklon": 5 }, + "4170": { "label": "45/10", "naklon": 5 }, + "4238": { "label": "45/11", "naklon": 5 }, + "4246": { "label": "45/12", "naklon": 5 }, + "4166": { "label": "45/13", "naklon": 5 }, + "4227": { "label": "45/14", "naklon": 5 }, + "4171": { "label": "45/15", "naklon": 5 }, + "4180": { "label": "45/16", "naklon": 5 }, + "4244": { "label": "45/17", "naklon": 5 }, + "4199": { "label": "45/18", "naklon": 5 }, + "4239": { "label": "45/19", "naklon": 5 }, + "4207": { "label": "45/20", "naklon": 5 }, + "4223": { "label": "45/21", "naklon": 5 }, + "4230": { "label": "45/22", "naklon": 5 }, + "4233": { "label": "45/23", "naklon": 5 }, + "4222": { "label": "45/24", "naklon": 5 }, + "4217": { "label": "45/25", "naklon": 5 }, + "4243": { "label": "45/26", "naklon": 5 }, + "4200": { "label": "45/27", "naklon": 5 }, + "4228": { "label": "45/28", "naklon": 5 }, + "4211": { "label": "45/29", "naklon": 5 }, + "4234": { "label": "45/30", "naklon": 5 }, + "4235": { "label": "45/31", "naklon": 5 }, + "4203": { "label": "45/32", "naklon": 5 }, + "4240": { "label": "45/33", "naklon": 5 }, + "4224": { "label": "45/34", "naklon": 5 }, + "4232": { "label": "45/35", "naklon": 5 }, + "4231": { "label": "45/36", "naklon": 5 }, + "4161": { "label": "45/37", "naklon": 5 }, + "4225": { "label": "45/38", "naklon": 5 }, + "4241": { "label": "45/39", "naklon": 5 }, + "4229": { "label": "45/40", "naklon": 5 }, + "4221": { "label": "45/41", "naklon": 5 }, + "4212": { "label": "45/42", "naklon": 5 }, + "4216": { "label": "45/43", "naklon": 5 }, + "3864": { "label": "45/44", "naklon": null }, + "3806": { "label": "46/1", "naklon": 5 }, + "3813": { "label": "46/2", "naklon": 5 }, + "3815": { "label": "46/3", "naklon": 5 }, + "3807": { "label": "46/4", "naklon": 5 }, + "3895": { "label": "46/5", "naklon": 5 }, + "3809": { "label": "46/6", "naklon": 5 }, + "3820": { "label": "46/7", "naklon": 5 }, + "3805": { "label": "46/8", "naklon": 5 }, + "3894": { "label": "46/9", "naklon": 0 }, + "4055": { "label": "46/10", "naklon": 0 }, + "3812": { "label": "46/11", "naklon": 5 }, + "3822": { "label": "46/12", "naklon": 5 }, + "3821": { "label": "46/13", "naklon": 5 }, + "3808": { "label": "46/14", "naklon": 5 }, + "3799": { "label": "46/15", "naklon": 5 }, + "3816": { "label": "46/16", "naklon": 5 }, + "3751": { "label": "46/17", "naklon": 5 }, + "3814": { "label": "46/18", "naklon": 5 }, + "4044": { "label": "46/19", "naklon": 0 }, + "3931": { "label": "46/20", "naklon": 0 }, + "3902": { "label": "46/21", "naklon": 5 }, + "3916": { "label": "46/22", "naklon": 5 }, + "3892": { "label": "46/23", "naklon": 5 }, + "3914": { "label": "46/24", "naklon": 5 }, + "3898": { "label": "46/25", "naklon": 5 }, + "3897": { "label": "46/26", "naklon": 5 }, + "3885": { "label": "46/27", "naklon": 5 }, + "3906": { "label": "46/28", "naklon": 5 }, + "3930": { "label": "46/29", "naklon": 0 }, + "3936": { "label": "46/30", "naklon": 0 }, + "3860": { "label": "46/31", "naklon": 5 }, + "3841": { "label": "46/32", "naklon": 5 }, + "3873": { "label": "46/33", "naklon": 5 }, + "3854": { "label": "46/34", "naklon": 5 }, + "3939": { "label": "46/35", "naklon": 5 }, + "3858": { "label": "46/36", "naklon": 5 }, + "3940": { "label": "46/37", "naklon": 5 }, + "4035": { "label": "46/38", "naklon": 5 }, + "3373": { "label": "47/1", "naklon": 0 }, + "3374": { "label": "47/2", "naklon": 0 }, + "3384": { "label": "47/3", "naklon": 0 }, + "3385": { "label": "47/4", "naklon": 0 }, + "4051": { "label": "48/1", "naklon": 5 }, + "4041": { "label": "48/2", "naklon": 5 }, + "4056": { "label": "48/3", "naklon": 5 }, + "3875": { "label": "48/4", "naklon": 5 }, + "4061": { "label": "48/5", "naklon": 5 }, + "4047": { "label": "48/6", "naklon": 5 }, + "4060": { "label": "48/7", "naklon": 5 }, + "4059": { "label": "48/8", "naklon": 5 }, + "4058": { "label": "48/9", "naklon": 5 }, + "3635": { "label": "48/10", "naklon": 5 }, + "3640": { "label": "48/11", "naklon": 5 }, + "3747": { "label": "48/12", "naklon": 5 }, + "3629": { "label": "48/13", "naklon": 5 }, + "4048": { "label": "48/14", "naklon": 5 }, + "4063": { "label": "48/15", "naklon": 5 }, + "4062": { "label": "48/16", "naklon": 5 }, + "4043": { "label": "48/17", "naklon": 5 }, + "4052": { "label": "48/18", "naklon": 5 }, + "4042": { "label": "48/19", "naklon": 5 }, + "4053": { "label": "48/20", "naklon": 5 }, + "4167": { "label": "50/15A", "naklon": null }, + "4159": { "label": "50/15B", "naklon": null }, + "4183": { "label": "50/1", "naklon": 0 }, + "4157": { "label": "50/2", "naklon": 0 }, + "4160": { "label": "50/3", "naklon": 0 }, + "4173": { "label": "50/4", "naklon": 0 }, + "4177": { "label": "50/5", "naklon": 0 }, + "4174": { "label": "50/6", "naklon": 0 }, + "4178": { "label": "50/7", "naklon": 0 }, + "4195": { "label": "50/8", "naklon": 0 }, + "4169": { "label": "50/9", "naklon": 0 }, + "4162": { "label": "50/10", "naklon": 0 }, + "4158": { "label": "50/11", "naklon": 0 }, + "4182": { "label": "50/12", "naklon": 0 }, + "4194": { "label": "50/13", "naklon": 0 }, + "4184": { "label": "50/14", "naklon": 0 }, + "4197": { "label": "50/16", "naklon": null }, + "4164": { "label": "50/17", "naklon": null }, + "3306": { "label": "50/18", "naklon": null }, + "4168": { "label": "50/19", "naklon": null }, + "4193": { "label": "50/20", "naklon": null }, + "4187": { "label": "50/21", "naklon": null }, + "4163": { "label": "50/22", "naklon": null }, + "4165": { "label": "50/23", "naklon": null }, + "4185": { "label": "50/24", "naklon": null }, + "3904": { "label": "50/25", "naklon": null }, + "2619": { "label": "53/1", "naklon": 0 }, + "2623": { "label": "53/2", "naklon": 0 }, + "2617": { "label": "53/3", "naklon": 0 }, + "2622": { "label": "53/4", "naklon": 0 }, + "2618": { "label": "53/5", "naklon": 0 }, + "2626": { "label": "53/6", "naklon": 0 }, + "2869": { "label": "53/7", "naklon": 0 }, + "2613": { "label": "53/8", "naklon": 0 }, + "2608": { "label": "53/9", "naklon": 0 }, + "2611": { "label": "53/10", "naklon": 0 }, + "2598": { "label": "53/11", "naklon": 0 }, + "3528": { "label": "53/12", "naklon": 0 }, + "3545": { "label": "53/13", "naklon": 0 }, + "2620": { "label": "53/14", "naklon": 0 }, + "2612": { "label": "53/15", "naklon": 0 }, + "2615": { "label": "53/16", "naklon": 0 }, + "3722": { "label": "53/17", "naklon": 0 }, + "2624": { "label": "53/18", "naklon": 0 }, + "2609": { "label": "53/19", "naklon": 0 }, + "2625": { "label": "53/20", "naklon": 0 }, + "2602": { "label": "53/21", "naklon": 0 }, + "2610": { "label": "53/22", "naklon": 0 }, + "2599": { "label": "53/23", "naklon": 0 }, + "2605": { "label": "53/24", "naklon": 0 }, + "2593": { "label": "53/25", "naklon": 0 }, + "3074": { "label": "53/26", "naklon": 0 }, + "2740": { "label": "53/27", "naklon": 0 }, + "2614": { "label": "53/28", "naklon": 0 }, + "2601": { "label": "53/29", "naklon": 0 }, + "4196": { "label": "53/30", "naklon": 0 }, + "2607": { "label": "53/31", "naklon": 0 }, + "2582": { "label": "53/32", "naklon": 0 }, + "2594": { "label": "53/33", "naklon": 0 }, + "2589": { "label": "53/34", "naklon": 0 }, + "2596": { "label": "53/35", "naklon": 0 }, + "2603": { "label": "53/36", "naklon": 0 }, + "2597": { "label": "53/37", "naklon": 0 }, + "2590": { "label": "53/38", "naklon": 0 }, + "2581": { "label": "53/39", "naklon": 0 }, + "2583": { "label": "53/40", "naklon": 0 }, + "2580": { "label": "53/41", "naklon": 0 }, + "2579": { "label": "53/42", "naklon": 0 }, + "2797": { "label": "53/43", "naklon": 0 }, + "2577": { "label": "53/44", "naklon": 0 }, + "2586": { "label": "53/45", "naklon": 0 }, + "2588": { "label": "53/46", "naklon": 0 }, + "2591": { "label": "53/47", "naklon": 0 }, + "2592": { "label": "53/48", "naklon": 0 }, + "2573": { "label": "53/49", "naklon": 0 }, + "2595": { "label": "53/50", "naklon": 0 }, + "2587": { "label": "53/51", "naklon": 0 }, + "2578": { "label": "53/52", "naklon": 0 }, + "2574": { "label": "53/53", "naklon": 0 }, + "2571": { "label": "53/54", "naklon": 0 }, + "2570": { "label": "53/55", "naklon": 0 }, + "2576": { "label": "53/56", "naklon": 0 }, + "2881": { "label": "53/57", "naklon": 0 }, + "2575": { "label": "53/58", "naklon": 0 }, + "2572": { "label": "53/59", "naklon": 0 }, + "2569": { "label": "53/60", "naklon": 0 }, + "4324": { "label": "55/1", "naklon": 0 }, + "4319": { "label": "55/2", "naklon": 0 }, + "4327": { "label": "55/3", "naklon": 0 }, + "4333": { "label": "55/4", "naklon": 0 }, + "4332": { "label": "55/5", "naklon": 0 }, + "4320": { "label": "55/6", "naklon": 0 }, + "4317": { "label": "55/7", "naklon": 0 }, + "4318": { "label": "55/8", "naklon": 0 }, + "4328": { "label": "55/9", "naklon": 0 }, + "4323": { "label": "55/10", "naklon": 0 }, + "4325": { "label": "55/11", "naklon": 0 }, + "4326": { "label": "55/12", "naklon": 0 }, + "4316": { "label": "55/13", "naklon": 0 }, + "4322": { "label": "55/14", "naklon": 0 }, + "4331": { "label": "55/15", "naklon": 0 }, + "4321": { "label": "55/16", "naklon": 0 }, + "4315": { "label": "55/17", "naklon": 0 }, + "4329": { "label": "55/18", "naklon": 0 }, + "4334": { "label": "55/19", "naklon": 0 }, + "4330": { "label": "55/20", "naklon": 0 } +}; + + +let svetlaSorted = [{ "label": "1/3A", "node": 3993, "naklon": 0 }, +{ "label": "1/3B", "node": 3989, "naklon": 15 }, +{ "label": "1/1", "node": 3976, "naklon": 0 }, +{ "label": "1/2", "node": 4181, "naklon": 0 }, +{ "label": "1/4", "node": 4376, "naklon": 15 }, +{ "label": "1/5", "node": 3868, "naklon": 15 }, +{ "label": "1/6", "node": 3728, "naklon": 15 }, +{ "label": "1/7", "node": 3730, "naklon": 0 }, +{ "label": "1/8", "node": 4374, "naklon": 0 }, +{ "label": "1/9", "node": 3718, "naklon": 15 }, +{ "label": "1/10", "node": 4375, "naklon": 15 }, +{ "label": "1/11", "node": 4172, "naklon": 15 }, +{ "label": "1/12", "node": 4176, "naklon": 15 }, +{ "label": "2/1", "node": 3800, "naklon": 5 }, +{ "label": "2/2", "node": 3823, "naklon": 5 }, +{ "label": "2/3", "node": 3905, "naklon": 5 }, +{ "label": "2/4", "node": 3803, "naklon": 5 }, +{ "label": "2/5", "node": 3817, "naklon": 5 }, +{ "label": "2/6", "node": 3818, "naklon": 5 }, +{ "label": "2/7", "node": 3811, "naklon": 5 }, +{ "label": "2/8", "node": 3915, "naklon": 5 }, +{ "label": "2/9", "node": 3843, "naklon": 10 }, +{ "label": "2/10", "node": 3827, "naklon": 10 }, +{ "label": "2/11", "node": 4220, "naklon": 10 }, +{ "label": "2/12", "node": 3826, "naklon": 10 }, +{ "label": "2/13", "node": 3834, "naklon": 10 }, +{ "label": "2/14", "node": 3838, "naklon": 10 }, +{ "label": "2/15", "node": 2823, "naklon": 10 }, +{ "label": "2/16", "node": 3750, "naklon": 10 }, +{ "label": "2/17", "node": 3378, "naklon": 0 }, +{ "label": "2/18", "node": 3376, "naklon": 0 }, +{ "label": "2/19", "node": 3379, "naklon": 0 }, +{ "label": "2/20", "node": 3285, "naklon": 0 }, +{ "label": "2/21", "node": 3382, "naklon": 0 }, +{ "label": "2/22", "node": 3383, "naklon": 0 }, +{ "label": "2/24", "node": 3375, "naklon": 0 }, +{ "label": "2/25", "node": 3381, "naklon": 0 }, +{ "label": "2/26", "node": 3380, "naklon": 0 }, +{ "label": "2/27", "node": 3828, "naklon": 10 }, +{ "label": "2/28", "node": 3377, "naklon": 0 }, +{ "label": "7/1", "node": 3591, "naklon": 0 }, +{ "label": "7/2", "node": 3587, "naklon": 0 }, +{ "label": "7/3", "node": 3468, "naklon": 0 }, +{ "label": "7/4", "node": 3466, "naklon": 0 }, +{ "label": "7/5", "node": 3474, "naklon": 0 }, +{ "label": "7/6", "node": 3481, "naklon": 0 }, +{ "label": "7/7", "node": 3589, "naklon": 0 }, +{ "label": "7/8", "node": 3472, "naklon": 0 }, +{ "label": "7/9", "node": 3473, "naklon": 0 }, +{ "label": "7/10", "node": 3584, "naklon": 0 }, +{ "label": "7/11", "node": 3571, "naklon": 0 }, +{ "label": "7/12", "node": 3476, "naklon": 0 }, +{ "label": "7/13", "node": 3590, "naklon": 0 }, +{ "label": "7/14", "node": 3478, "naklon": 0 }, +{ "label": "7/15", "node": 3471, "naklon": 0 }, +{ "label": "7/16", "node": 3467, "naklon": 0 }, +{ "label": "7/17", "node": 3479, "naklon": 0 }, +{ "label": "7/18", "node": 3480, "naklon": 0 }, +{ "label": "7/19", "node": 3477, "naklon": 0 }, +{ "label": "12/1", "node": 3362, "naklon": 0 }, +{ "label": "12/2", "node": 3355, "naklon": 0 }, +{ "label": "12/3", "node": 3356, "naklon": 0 }, +{ "label": "12/4", "node": 3349, "naklon": 0 }, +{ "label": "12/5", "node": 3357, "naklon": 0 }, +{ "label": "12/6", "node": 3350, "naklon": 0 }, +{ "label": "12/7", "node": 3353, "naklon": 0 }, +{ "label": "12/8", "node": 3539, "naklon": 0 }, +{ "label": "12/9", "node": 3050, "naklon": 0 }, +{ "label": "12/10", "node": 3361, "naklon": 0 }, +{ "label": "12/11", "node": 3360, "naklon": 0 }, +{ "label": "12/12", "node": 3358, "naklon": 0 }, +{ "label": "12/13", "node": 3541, "naklon": 0 }, +{ "label": "12/14", "node": 3551, "naklon": 0 }, +{ "label": "12/15", "node": 3514, "naklon": 0 }, +{ "label": "12/16", "node": 3547, "naklon": 0 }, +{ "label": "12/17", "node": 3562, "naklon": 0 }, +{ "label": "12/18", "node": 3525, "naklon": 0 }, +{ "label": "12/19", "node": 3558, "naklon": 0 }, +{ "label": "12/20", "node": 3511, "naklon": 0 }, +{ "label": "12/21", "node": 3058, "naklon": 0 }, +{ "label": "12/22", "node": 3062, "naklon": 0 }, +{ "label": "12/23", "node": 3070, "naklon": 0 }, +{ "label": "12/24", "node": 3447, "naklon": 0 }, +{ "label": "12/25", "node": 3056, "naklon": 0 }, +{ "label": "12/26", "node": 3057, "naklon": 0 }, +{ "label": "12/27", "node": 3071, "naklon": 0 }, +{ "label": "12/28", "node": 3061, "naklon": 0 }, +{ "label": "12/29", "node": 3069, "naklon": 0 }, +{ "label": "12/30", "node": 3077, "naklon": 0 }, +{ "label": "12/31", "node": 3080, "naklon": 0 }, +{ "label": "12/32", "node": 3081, "naklon": 0 }, +{ "label": "12/33", "node": 3078, "naklon": 0 }, +{ "label": "12/34", "node": 4037, "naklon": 0 }, +{ "label": "12/35", "node": 3067, "naklon": 0 }, +{ "label": "12/36", "node": 3051, "naklon": 0 }, +{ "label": "12/37", "node": 2924, "naklon": 0 }, +{ "label": "12/38", "node": 3060, "naklon": 0 }, +{ "label": "12/39", "node": 3073, "naklon": 0 }, +{ "label": "12/40", "node": 3469, "naklon": 0 }, +{ "label": "12/41", "node": 2923, "naklon": 0 }, +{ "label": "12/42", "node": 2925, "naklon": 0 }, +{ "label": "12/43", "node": 3359, "naklon": 0 }, +{ "label": "12/44", "node": 3055, "naklon": 0 }, +{ "label": "12/45", "node": 2922, "naklon": 0 }, +{ "label": "12/46", "node": 3084, "naklon": 0 }, +{ "label": "12/47", "node": 3064, "naklon": 0 }, +{ "label": "12/48", "node": 3066, "naklon": 0 }, +{ "label": "12/49", "node": 3072, "naklon": 0 }, +{ "label": "13/13A", "node": 3415, "naklon": 0 }, +{ "label": "13/13B", "node": 3409, "naklon": 0 }, +{ "label": "13/13C", "node": 3399, "naklon": 0 }, +{ "label": "13/29A", "node": 3410, "naklon": 0 }, +{ "label": "13/29B", "node": 3407, "naklon": 0 }, +{ "label": "13/34A", "node": 3405, "naklon": 0 }, +{ "label": "13/34B", "node": 3404, "naklon": 0 }, +{ "label": "13/45A", "node": 3392, "naklon": 0 }, +{ "label": "13/45B", "node": 3386, "naklon": 0 }, +{ "label": "13/60A", "node": 3303, "naklon": 3 }, +{ "label": "13/60B", "node": 3302, "naklon": 3 }, +{ "label": "13/70A", "node": 3319, "naklon": 6 }, +{ "label": "13/70B", "node": 3317, "naklon": 6 }, +{ "label": "13/70C", "node": 3326, "naklon": 6 }, +{ "label": "13/73A", "node": 3351, "naklon": 6 }, +{ "label": "13/73B", "node": 3313, "naklon": 6 }, +{ "label": "13/83A", "node": 3316, "naklon": 0 }, +{ "label": "13/83B", "node": 3320, "naklon": 0 }, +{ "label": "13/95A", "node": 3336, "naklon": 0 }, +{ "label": "13/95B", "node": 3323, "naklon": 0 }, +{ "label": "13/98A", "node": 3339, "naklon": 0 }, +{ "label": "13/98B", "node": 3333, "naklon": 0 }, +{ "label": "13/1", "node": 3425, "naklon": 0 }, +{ "label": "13/2", "node": 3419, "naklon": 0 }, +{ "label": "13/3", "node": 3416, "naklon": 0 }, +{ "label": "13/4", "node": 3332, "naklon": 0 }, +{ "label": "13/5", "node": 3422, "naklon": 0 }, +{ "label": "13/6", "node": 3417, "naklon": 0 }, +{ "label": "13/7", "node": 3418, "naklon": 0 }, +{ "label": "13/8", "node": 3424, "naklon": 0 }, +{ "label": "13/9", "node": 3334, "naklon": 0 }, +{ "label": "13/10", "node": 4363, "naklon": 0 }, +{ "label": "13/11", "node": 3423, "naklon": 0 }, +{ "label": "13/12", "node": 3406, "naklon": 0 }, +{ "label": "13/14", "node": 3411, "naklon": 0 }, +{ "label": "13/15", "node": 3412, "naklon": 0 }, +{ "label": "13/16", "node": 3413, "naklon": 0 }, +{ "label": "13/17", "node": 3414, "naklon": 0 }, +{ "label": "13/18", "node": 3391, "naklon": 0 }, +{ "label": "13/19", "node": 3370, "naklon": 0 }, +{ "label": "13/20", "node": 3369, "naklon": 0 }, +{ "label": "13/21", "node": 3408, "naklon": 0 }, +{ "label": "13/22", "node": 3393, "naklon": 0 }, +{ "label": "13/23", "node": 3128, "naklon": 0 }, +{ "label": "13/24", "node": 3197, "naklon": 0 }, +{ "label": "13/25", "node": 4364, "naklon": 0 }, +{ "label": "13/26", "node": 3155, "naklon": 0 }, +{ "label": "13/27", "node": 3196, "naklon": 0 }, +{ "label": "13/28", "node": 3144, "naklon": 0 }, +{ "label": "13/30", "node": 3150, "naklon": 0 }, +{ "label": "13/31", "node": 3390, "naklon": 0 }, +{ "label": "13/32", "node": 3401, "naklon": 0 }, +{ "label": "13/33", "node": 3275, "naklon": 0 }, +{ "label": "13/35", "node": 3371, "naklon": 0 }, +{ "label": "13/36", "node": 3389, "naklon": 0 }, +{ "label": "13/37", "node": 3388, "naklon": 0 }, +{ "label": "13/38", "node": 3365, "naklon": 0 }, +{ "label": "13/39", "node": 3363, "naklon": 0 }, +{ "label": "13/40", "node": 3397, "naklon": 0 }, +{ "label": "13/40/1", "node": 3567, "naklon": 0 }, +{ "label": "13/41", "node": 3387, "naklon": 0 }, +{ "label": "13/42", "node": 3403, "naklon": 0 }, +{ "label": "13/43", "node": 3147, "naklon": 0 }, +{ "label": "13/44", "node": 3141, "naklon": 0 }, +{ "label": "13/46", "node": 3364, "naklon": 0 }, +{ "label": "13/47", "node": 3367, "naklon": 0 }, +{ "label": "13/48", "node": 3368, "naklon": 0 }, +{ "label": "13/49", "node": 3402, "naklon": 0 }, +{ "label": "13/50", "node": 3366, "naklon": 0 }, +{ "label": "13/51", "node": 3395, "naklon": 0 }, +{ "label": "13/52", "node": 3372, "naklon": 0 }, +{ "label": "13/53", "node": 3394, "naklon": 0 }, +{ "label": "13/54", "node": 3308, "naklon": 0 }, +{ "label": "13/54/1", "node": 3847, "naklon": 0 }, +{ "label": "13/55", "node": 3312, "naklon": 3 }, +{ "label": "13/56", "node": 3309, "naklon": 3 }, +{ "label": "13/57", "node": 3311, "naklon": 3 }, +{ "label": "13/58", "node": 3310, "naklon": 3 }, +{ "label": "13/59", "node": 4365, "naklon": 3 }, +{ "label": "13/60/1", "node": 4093, "naklon": 3 }, +{ "label": "13/61", "node": 3304, "naklon": 3 }, +{ "label": "13/62", "node": 3307, "naklon": 3 }, +{ "label": "13/63", "node": 3271, "naklon": 3 }, +{ "label": "13/64", "node": 3301, "naklon": 3 }, +{ "label": "13/65", "node": 4366, "naklon": 3 }, +{ "label": "13/66", "node": 3300, "naklon": 3 }, +{ "label": "13/67", "node": 3185, "naklon": 0 }, +{ "label": "13/68", "node": 3184, "naklon": 0 }, +{ "label": "13/69", "node": 3188, "naklon": 0 }, +{ "label": "13/71", "node": 3343, "naklon": 6 }, +{ "label": "13/71/1", "node": 3819, "naklon": 6 }, +{ "label": "13/71/2", "node": 3880, "naklon": 6 }, +{ "label": "13/72", "node": 3348, "naklon": 6 }, +{ "label": "13/74", "node": 3344, "naklon": 6 }, +{ "label": "13/75", "node": 3346, "naklon": 6 }, +{ "label": "13/75/1", "node": 3597, "naklon": 6 }, +{ "label": "13/76", "node": 3345, "naklon": 6 }, +{ "label": "13/77", "node": 3322, "naklon": 0 }, +{ "label": "13/78", "node": 3325, "naklon": 0 }, +{ "label": "13/78/1", "node": 4310, "naklon": 0 }, +{ "label": "13/79", "node": 3315, "naklon": 0 }, +{ "label": "13/80", "node": 3328, "naklon": 0 }, +{ "label": "13/81", "node": 3321, "naklon": 0 }, +{ "label": "13/82", "node": 3324, "naklon": 0 }, +{ "label": "13/84", "node": 3140, "naklon": 0 }, +{ "label": "13/85", "node": 3153, "naklon": 0 }, +{ "label": "13/86", "node": 3145, "naklon": 0 }, +{ "label": "13/87", "node": 3134, "naklon": 0 }, +{ "label": "13/88", "node": 3151, "naklon": 0 }, +{ "label": "13/89", "node": 3143, "naklon": 0 }, +{ "label": "13/90", "node": 3318, "naklon": 0 }, +{ "label": "13/91", "node": 3347, "naklon": 0 }, +{ "label": "13/94", "node": 3314, "naklon": 0 }, +{ "label": "13/96", "node": 3331, "naklon": 0 }, +{ "label": "13/97", "node": 3327, "naklon": 0 }, +{ "label": "13/99", "node": 3329, "naklon": 0 }, +{ "label": "13/100", "node": 3337, "naklon": 0 }, +{ "label": "13/101", "node": 3330, "naklon": 0 }, +{ "label": "13/102", "node": 3335, "naklon": 0 }, +{ "label": "13/103", "node": 3420, "naklon": 0 }, +{ "label": "13/104", "node": 3421, "naklon": 0 }, +{ "label": "13/105", "node": 4361, "naklon": 0 }, +{ "label": "13/106", "node": 4362, "naklon": 0 }, +{ "label": "13/107", "node": 3526, "naklon": 0 }, +{ "label": "13/108", "node": 4424, "naklon": null }, +{ "label": "13/109", "node": 3561, "naklon": null }, +{ "label": "13/110", "node": 3527, "naklon": null }, +{ "label": "13/111", "node": 3521, "naklon": null }, +{ "label": "13/112", "node": 3552, "naklon": null }, +{ "label": "13/113", "node": 3544, "naklon": null }, +{ "label": "13/114", "node": 3534, "naklon": null }, +{ "label": "13/115", "node": 3516, "naklon": null }, +{ "label": "13/116", "node": 3513, "naklon": null }, +{ "label": "13/117", "node": 3565, "naklon": null }, +{ "label": "13/118", "node": 3866, "naklon": null }, +{ "label": "14/1", "node": 3136, "naklon": 0 }, +{ "label": "14/2", "node": 3137, "naklon": 0 }, +{ "label": "14/3", "node": 3135, "naklon": 0 }, +{ "label": "14/4", "node": 3149, "naklon": 0 }, +{ "label": "14/5", "node": 3142, "naklon": 0 }, +{ "label": "14/6", "node": 3342, "naklon": 0 }, +{ "label": "14/7", "node": 3340, "naklon": 0 }, +{ "label": "14/8", "node": 3152, "naklon": 0 }, +{ "label": "14/9", "node": 3886, "naklon": 0 }, +{ "label": "14/10", "node": 3341, "naklon": null }, +{ "label": "14/11", "node": 3352, "naklon": null }, +{ "label": "15/1", "node": 3396, "naklon": 5 }, +{ "label": "15/2", "node": 2784, "naklon": 5 }, +{ "label": "15/3", "node": 2788, "naklon": 5 }, +{ "label": "15/4", "node": 2801, "naklon": 5 }, +{ "label": "15/5", "node": 2815, "naklon": 5 }, +{ "label": "15/6", "node": 2829, "naklon": 5 }, +{ "label": "15/7", "node": 2796, "naklon": 5 }, +{ "label": "15/8", "node": 2803, "naklon": 5 }, +{ "label": "15/8/1", "node": 4304, "naklon": 5 }, +{ "label": "15/8/2", "node": 4311, "naklon": 5 }, +{ "label": "15/9", "node": 2821, "naklon": 5 }, +{ "label": "15/10", "node": 3400, "naklon": 5 }, +{ "label": "15/11", "node": 2799, "naklon": 5 }, +{ "label": "15/12", "node": 2804, "naklon": 5 }, +{ "label": "15/12/1", "node": 4303, "naklon": 5 }, +{ "label": "15/12/2", "node": 4309, "naklon": 5 }, +{ "label": "15/13", "node": 2806, "naklon": 5 }, +{ "label": "15/14", "node": 2787, "naklon": 5 }, +{ "label": "15/15", "node": 2809, "naklon": 5 }, +{ "label": "15/16", "node": 2814, "naklon": 0 }, +{ "label": "15/17", "node": 3934, "naklon": 0 }, +{ "label": "15/18", "node": 3192, "naklon": 0 }, +{ "label": "15/19", "node": 2812, "naklon": 0 }, +{ "label": "15/20", "node": 4070, "naklon": 0 }, +{ "label": "15/21", "node": 2826, "naklon": 0 }, +{ "label": "15/22", "node": 2808, "naklon": 3 }, +{ "label": "15/23", "node": 2795, "naklon": 3 }, +{ "label": "15/24", "node": 2807, "naklon": 3 }, +{ "label": "15/25", "node": 2831, "naklon": 0 }, +{ "label": "15/26", "node": 2862, "naklon": null }, +{ "label": "15/27", "node": 2861, "naklon": 0 }, +{ "label": "15/28", "node": 2866, "naklon": 0 }, +{ "label": "15/28/1", "node": 3546, "naklon": 0 }, +{ "label": "15/29", "node": 4146, "naklon": 0 }, +{ "label": "15/29/1", "node": 3001, "naklon": 0 }, +{ "label": "15/30", "node": 2835, "naklon": 0 }, +{ "label": "15/31", "node": 2874, "naklon": 0 }, +{ "label": "15/32", "node": 2852, "naklon": 0 }, +{ "label": "15/33", "node": 2851, "naklon": 0 }, +{ "label": "15/33/1", "node": 3560, "naklon": 0 }, +{ "label": "15/34", "node": 2858, "naklon": 0 }, +{ "label": "15/34/1", "node": 4306, "naklon": 0 }, +{ "label": "15/35", "node": 2856, "naklon": 0 }, +{ "label": "15/36", "node": 2847, "naklon": 0 }, +{ "label": "15/36/1", "node": 3556, "naklon": 0 }, +{ "label": "15/37", "node": 3950, "naklon": 0 }, +{ "label": "15/38", "node": 2848, "naklon": 0 }, +{ "label": "15/39", "node": 2863, "naklon": 0 }, +{ "label": "15/39/1", "node": 4313, "naklon": 0 }, +{ "label": "15/40", "node": 2873, "naklon": 0 }, +{ "label": "15/40/1", "node": 2984, "naklon": 0 }, +{ "label": "15/41", "node": 2854, "naklon": 0 }, +{ "label": "15/42", "node": 2859, "naklon": 0 }, +{ "label": "15/43", "node": 2872, "naklon": 0 }, +{ "label": "15/44", "node": 2849, "naklon": 0 }, +{ "label": "15/45", "node": 2864, "naklon": 0 }, +{ "label": "15/46", "node": 3553, "naklon": null }, +{ "label": "15/47", "node": 3021, "naklon": null }, +{ "label": "15/47/1", "node": 3008, "naklon": null }, +{ "label": "15/48", "node": 3017, "naklon": null }, +{ "label": "15/49", "node": 3014, "naklon": null }, +{ "label": "15/50", "node": 2981, "naklon": null }, +{ "label": "15/51", "node": 3020, "naklon": null }, +{ "label": "15/52", "node": 3027, "naklon": null }, +{ "label": "15/53", "node": 3006, "naklon": null }, +{ "label": "15/54", "node": 3012, "naklon": null }, +{ "label": "15/55", "node": 2738, "naklon": 0 }, +{ "label": "15/56", "node": 2725, "naklon": 0 }, +{ "label": "15/57", "node": 3016, "naklon": null }, +{ "label": "15/58", "node": 3005, "naklon": null }, +{ "label": "15/58/1", "node": 3009, "naklon": null }, +{ "label": "15/59", "node": 3010, "naklon": 0 }, +{ "label": "15/59/1", "node": 3538, "naklon": 0 }, +{ "label": "15/59/2", "node": 4145, "naklon": 0 }, +{ "label": "15/60", "node": 2713, "naklon": 0 }, +{ "label": "15/61", "node": 2789, "naklon": 0 }, +{ "label": "15/62", "node": 2736, "naklon": 0 }, +{ "label": "15/63", "node": 2739, "naklon": 0 }, +{ "label": "15/64", "node": 4346, "naklon": 0 }, +{ "label": "15/65", "node": 2731, "naklon": 0 }, +{ "label": "15/66", "node": 2818, "naklon": 0 }, +{ "label": "15/66/1", "node": 3557, "naklon": 0 }, +{ "label": "15/67", "node": 2822, "naklon": 0 }, +{ "label": "15/68", "node": 2833, "naklon": 0 }, +{ "label": "15/69", "node": 2834, "naklon": 0 }, +{ "label": "15/70", "node": 3097, "naklon": 0 }, +{ "label": "15/71", "node": 2824, "naklon": 0 }, +{ "label": "15/72", "node": 2828, "naklon": 0 }, +{ "label": "15/73", "node": 2600, "naklon": 0 }, +{ "label": "15/73/1", "node": 4314, "naklon": 0 }, +{ "label": "15/74", "node": 2832, "naklon": 0 }, +{ "label": "15/75", "node": 4360, "naklon": 0 }, +{ "label": "15/76", "node": 2846, "naklon": 0 }, +{ "label": "15/77", "node": 2584, "naklon": 0 }, +{ "label": "15/78", "node": 2843, "naklon": 0 }, +{ "label": "15/78/1", "node": 4308, "naklon": 0 }, +{ "label": "15/79", "node": 4144, "naklon": null }, +{ "label": "15/80", "node": 2844, "naklon": 0 }, +{ "label": "15/81", "node": 2842, "naklon": 0 }, +{ "label": "15/82", "node": 2838, "naklon": 0 }, +{ "label": "15/83", "node": 2837, "naklon": null }, +{ "label": "15/83/1", "node": 3555, "naklon": null }, +{ "label": "15/84", "node": 2839, "naklon": 0 }, +{ "label": "15/85", "node": 2830, "naklon": 0 }, +{ "label": "15/86", "node": 4066, "naklon": 0 }, +{ "label": "15/87", "node": 2836, "naklon": 0 }, +{ "label": "15/88", "node": 2911, "naklon": 0 }, +{ "label": "15/89", "node": 2825, "naklon": 0 }, +{ "label": "15/90", "node": 2811, "naklon": 0 }, +{ "label": "15/94", "node": 3740, "naklon": 15 }, +{ "label": "15/95", "node": 2734, "naklon": 15 }, +{ "label": "15/96", "node": 3105, "naklon": 15 }, +{ "label": "15/97", "node": 2732, "naklon": 15 }, +{ "label": "15/98", "node": 2727, "naklon": 15 }, +{ "label": "15/99", "node": 2735, "naklon": 15 }, +{ "label": "15/100", "node": 3926, "naklon": 15 }, +{ "label": "15/101", "node": 2918, "naklon": 0 }, +{ "label": "15/102", "node": 2705, "naklon": 10 }, +{ "label": "15/103", "node": 2708, "naklon": 10 }, +{ "label": "15/104", "node": 2721, "naklon": 10 }, +{ "label": "15/105", "node": 2719, "naklon": 10 }, +{ "label": "15/106", "node": 2919, "naklon": 10 }, +{ "label": "15/107", "node": 3101, "naklon": 10 }, +{ "label": "15/108", "node": 2853, "naklon": 10 }, +{ "label": "15/109", "node": 2715, "naklon": 10 }, +{ "label": "15/110", "node": 2712, "naklon": 0 }, +{ "label": "15/111", "node": 2711, "naklon": 0 }, +{ "label": "15/112", "node": 2709, "naklon": 0 }, +{ "label": "15/113", "node": 2710, "naklon": 0 }, +{ "label": "15/114", "node": 2907, "naklon": 0 }, +{ "label": "15/115", "node": 2906, "naklon": 0 }, +{ "label": "15/116", "node": 2908, "naklon": 0 }, +{ "label": "15/117", "node": 2901, "naklon": 0 }, +{ "label": "15/118", "node": 2913, "naklon": 0 }, +{ "label": "15/119", "node": 3656, "naklon": 0 }, +{ "label": "15/120", "node": 2781, "naklon": 0 }, +{ "label": "15/121", "node": 2802, "naklon": 0 }, +{ "label": "15/122", "node": 2791, "naklon": 0 }, +{ "label": "15/123", "node": 2783, "naklon": 0 }, +{ "label": "15/124", "node": 2794, "naklon": 0 }, +{ "label": "15/125", "node": 3139, "naklon": 0 }, +{ "label": "15/126", "node": 3229, "naklon": 5 }, +{ "label": "15/127", "node": 3239, "naklon": 5 }, +{ "label": "15/128", "node": 3230, "naklon": 5 }, +{ "label": "15/129", "node": 4016, "naklon": null }, +{ "label": "16/16A", "node": 3608, "naklon": 0 }, +{ "label": "16/16B", "node": 4151, "naklon": 0 }, +{ "label": "16/1", "node": 3710, "naklon": 0 }, +{ "label": "16/2", "node": 3726, "naklon": 0 }, +{ "label": "16/3", "node": 3743, "naklon": 0 }, +{ "label": "16/4", "node": 3724, "naklon": 0 }, +{ "label": "16/5", "node": 3712, "naklon": 0 }, +{ "label": "16/6", "node": 3739, "naklon": 0 }, +{ "label": "16/7", "node": 3742, "naklon": 0 }, +{ "label": "16/8", "node": 3731, "naklon": 0 }, +{ "label": "16/9", "node": 3727, "naklon": 0 }, +{ "label": "16/10", "node": 3729, "naklon": 0 }, +{ "label": "16/11", "node": 3736, "naklon": 0 }, +{ "label": "16/12", "node": 3713, "naklon": 0 }, +{ "label": "16/13", "node": 3715, "naklon": 0 }, +{ "label": "16/14", "node": 3733, "naklon": 0 }, +{ "label": "16/15", "node": 3732, "naklon": 0 }, +{ "label": "16/17", "node": 3634, "naklon": 0 }, +{ "label": "16/18", "node": 3610, "naklon": 0 }, +{ "label": "16/19", "node": 3626, "naklon": 0 }, +{ "label": "16/20", "node": 3618, "naklon": 0 }, +{ "label": "16/21", "node": 3619, "naklon": 0 }, +{ "label": "16/22", "node": 3628, "naklon": 0 }, +{ "label": "16/23", "node": 3615, "naklon": 0 }, +{ "label": "16/24", "node": 3609, "naklon": 0 }, +{ "label": "16/25", "node": 3606, "naklon": 0 }, +{ "label": "16/26", "node": 3624, "naklon": 0 }, +{ "label": "16/27", "node": 3627, "naklon": 0 }, +{ "label": "16/28", "node": 3607, "naklon": 0 }, +{ "label": "16/29", "node": 4370, "naklon": 0 }, +{ "label": "16/30", "node": 3692, "naklon": 0 }, +{ "label": "16/31", "node": 3614, "naklon": 0 }, +{ "label": "16/32", "node": 3623, "naklon": 0 }, +{ "label": "16/33", "node": 4373, "naklon": 0 }, +{ "label": "16/34", "node": 3620, "naklon": 0 }, +{ "label": "16/35", "node": 3685, "naklon": 0 }, +{ "label": "16/36", "node": 3616, "naklon": 0 }, +{ "label": "16/37", "node": 3686, "naklon": 0 }, +{ "label": "16/38", "node": 3688, "naklon": 0 }, +{ "label": "16/39", "node": 3684, "naklon": 0 }, +{ "label": "16/40", "node": 3825, "naklon": 0 }, +{ "label": "16/41", "node": 3865, "naklon": 0 }, +{ "label": "16/42", "node": 3824, "naklon": 0 }, +{ "label": "16/43", "node": 3871, "naklon": 0 }, +{ "label": "16/44", "node": 3801, "naklon": 0 }, +{ "label": "16/45", "node": 3862, "naklon": 0 }, +{ "label": "16/46", "node": 3876, "naklon": 0 }, +{ "label": "16/47", "node": 3861, "naklon": 0 }, +{ "label": "16/48", "node": 4215, "naklon": 0 }, +{ "label": "16/49", "node": 3605, "naklon": 10 }, +{ "label": "16/50", "node": 3603, "naklon": 10 }, +{ "label": "16/51", "node": 3592, "naklon": 10 }, +{ "label": "16/52", "node": 3598, "naklon": 10 }, +{ "label": "16/53", "node": 3594, "naklon": 10 }, +{ "label": "16/54", "node": 3593, "naklon": 10 }, +{ "label": "16/55", "node": 3630, "naklon": 10 }, +{ "label": "16/56", "node": 3763, "naklon": 10 }, +{ "label": "16/57", "node": 3746, "naklon": 10 }, +{ "label": "16/58", "node": 3699, "naklon": 0 }, +{ "label": "16/59", "node": 3698, "naklon": 0 }, +{ "label": "16/60", "node": 3709, "naklon": null }, +{ "label": "16/61", "node": 3708, "naklon": 0 }, +{ "label": "16/62", "node": 3703, "naklon": null }, +{ "label": "16/63", "node": 3700, "naklon": 0 }, +{ "label": "16/64", "node": 3701, "naklon": null }, +{ "label": "16/65", "node": 3704, "naklon": 0 }, +{ "label": "16/66", "node": 3707, "naklon": null }, +{ "label": "16/67", "node": 3810, "naklon": 0 }, +{ "label": "16/68", "node": 4208, "naklon": null }, +{ "label": "16/69", "node": 3867, "naklon": 0 }, +{ "label": "16/70", "node": 4372, "naklon": null }, +{ "label": "16/71", "node": 3881, "naklon": 0 }, +{ "label": "16/72", "node": 4204, "naklon": null }, +{ "label": "16/73", "node": 3869, "naklon": 0 }, +{ "label": "16/74", "node": 4202, "naklon": null }, +{ "label": "16/75", "node": 3830, "naklon": 0 }, +{ "label": "16/76", "node": 3870, "naklon": null }, +{ "label": "16/77", "node": 3964, "naklon": 0 }, +{ "label": "16/78", "node": 3849, "naklon": 0 }, +{ "label": "16/79", "node": 3694, "naklon": null }, +{ "label": "16/80", "node": 3717, "naklon": 0 }, +{ "label": "16/81", "node": 3877, "naklon": null }, +{ "label": "16/82", "node": 3755, "naklon": 0 }, +{ "label": "16/83", "node": 3725, "naklon": null }, +{ "label": "16/84", "node": 3716, "naklon": 0 }, +{ "label": "16/85", "node": 3696, "naklon": null }, +{ "label": "16/86", "node": 3702, "naklon": 0 }, +{ "label": "16/87", "node": 3706, "naklon": null }, +{ "label": "16/88", "node": 3850, "naklon": 0 }, +{ "label": "16/89", "node": 3848, "naklon": null }, +{ "label": "16/90", "node": 3737, "naklon": null }, +{ "label": "16/91", "node": 3705, "naklon": 0 }, +{ "label": "16/92", "node": 3723, "naklon": null }, +{ "label": "16/93", "node": 3842, "naklon": 0 }, +{ "label": "16/94", "node": 3735, "naklon": null }, +{ "label": "16/95", "node": 3719, "naklon": 0 }, +{ "label": "16/96", "node": 3697, "naklon": 0 }, +{ "label": "16/97", "node": 3711, "naklon": 0 }, +{ "label": "16/98", "node": 4107, "naklon": null }, +{ "label": "16/99", "node": 4112, "naklon": 5 }, +{ "label": "16/100", "node": 4106, "naklon": 5 }, +{ "label": "16/101", "node": 4111, "naklon": 5 }, +{ "label": "16/102", "node": 4091, "naklon": null }, +{ "label": "16/103", "node": 4104, "naklon": 5 }, +{ "label": "16/104", "node": 4094, "naklon": null }, +{ "label": "16/105", "node": 4089, "naklon": 5 }, +{ "label": "16/106", "node": 4095, "naklon": null }, +{ "label": "16/107", "node": 4102, "naklon": 5 }, +{ "label": "16/108", "node": 4105, "naklon": null }, +{ "label": "16/109", "node": 3859, "naklon": null }, +{ "label": "16/110", "node": 4090, "naklon": 5 }, +{ "label": "16/111", "node": 4110, "naklon": null }, +{ "label": "16/112", "node": 4097, "naklon": 5 }, +{ "label": "16/113", "node": 4099, "naklon": null }, +{ "label": "16/114", "node": 4096, "naklon": null }, +{ "label": "16/115", "node": 4101, "naklon": 5 }, +{ "label": "16/116", "node": 4109, "naklon": null }, +{ "label": "16/117", "node": 4092, "naklon": 5 }, +{ "label": "16/118", "node": 3631, "naklon": null }, +{ "label": "16/119", "node": 3632, "naklon": 0 }, +{ "label": "16/120", "node": 3641, "naklon": null }, +{ "label": "16/121", "node": 3638, "naklon": 0 }, +{ "label": "16/122", "node": 3637, "naklon": null }, +{ "label": "16/123", "node": 4142, "naklon": null }, +{ "label": "16/124", "node": 4147, "naklon": 5 }, +{ "label": "16/125", "node": 4139, "naklon": 5 }, +{ "label": "20/30A", "node": 3172, "naklon": 2 }, +{ "label": "20/30B", "node": 3164, "naklon": 2 }, +{ "label": "20/1", "node": 3247, "naklon": 10 }, +{ "label": "20/2", "node": 3296, "naklon": 10 }, +{ "label": "20/3", "node": 3246, "naklon": 10 }, +{ "label": "20/4", "node": 3270, "naklon": 10 }, +{ "label": "20/5", "node": 3294, "naklon": 10 }, +{ "label": "20/6", "node": 3298, "naklon": 10 }, +{ "label": "20/7", "node": 3297, "naklon": 10 }, +{ "label": "20/8", "node": 3293, "naklon": 10 }, +{ "label": "20/9", "node": 3299, "naklon": 10 }, +{ "label": "20/10", "node": 3295, "naklon": 10 }, +{ "label": "20/11", "node": 3244, "naklon": 10 }, +{ "label": "20/12", "node": 3249, "naklon": 10 }, +{ "label": "20/13", "node": 3268, "naklon": 10 }, +{ "label": "20/14", "node": 3245, "naklon": 10 }, +{ "label": "20/15", "node": 3278, "naklon": 10 }, +{ "label": "20/16", "node": 3280, "naklon": 10 }, +{ "label": "20/17", "node": 3292, "naklon": 10 }, +{ "label": "20/18", "node": 3287, "naklon": 10 }, +{ "label": "20/19", "node": 3282, "naklon": 10 }, +{ "label": "20/20", "node": 3273, "naklon": 0 }, +{ "label": "20/21", "node": 3157, "naklon": 0 }, +{ "label": "20/22", "node": 3283, "naklon": 0 }, +{ "label": "20/23", "node": 3159, "naklon": 0 }, +{ "label": "20/24", "node": 3289, "naklon": 0 }, +{ "label": "20/25", "node": 3163, "naklon": 0 }, +{ "label": "20/26", "node": 3126, "naklon": 0 }, +{ "label": "20/27", "node": 3171, "naklon": 0 }, +{ "label": "20/28", "node": 3162, "naklon": 0 }, +{ "label": "20/29", "node": 3279, "naklon": 10 }, +{ "label": "20/31", "node": 3173, "naklon": 0 }, +{ "label": "20/32", "node": 3127, "naklon": 0 }, +{ "label": "20/33", "node": 3131, "naklon": 0 }, +{ "label": "20/34", "node": 3129, "naklon": 0 }, +{ "label": "20/35", "node": 3276, "naklon": 2 }, +{ "label": "20/36", "node": 3290, "naklon": 2 }, +{ "label": "20/37", "node": 3132, "naklon": 0 }, +{ "label": "20/38", "node": 3138, "naklon": 0 }, +{ "label": "20/39", "node": 3272, "naklon": 0 }, +{ "label": "20/40", "node": 3291, "naklon": 0 }, +{ "label": "20/41", "node": 3277, "naklon": 10 }, +{ "label": "20/42", "node": 3286, "naklon": 10 }, +{ "label": "20/43", "node": 3281, "naklon": 10 }, +{ "label": "20/44", "node": 3288, "naklon": 10 }, +{ "label": "20/45", "node": 3284, "naklon": 10 }, +{ "label": "20/46", "node": 3167, "naklon": 10 }, +{ "label": "20/47", "node": 3872, "naklon": 0 }, +{ "label": "20/48", "node": 3124, "naklon": 0 }, +{ "label": "20/49", "node": 3133, "naklon": 0 }, +{ "label": "20/50", "node": 3158, "naklon": 0 }, +{ "label": "20/51", "node": 3169, "naklon": 0 }, +{ "label": "20/52", "node": 3146, "naklon": 0 }, +{ "label": "20/53", "node": 3160, "naklon": 0 }, +{ "label": "20/54", "node": 3248, "naklon": 0 }, +{ "label": "20/55", "node": 3156, "naklon": 0 }, +{ "label": "20/56", "node": 3161, "naklon": 0 }, +{ "label": "20/57", "node": 3170, "naklon": 0 }, +{ "label": "20/58", "node": 3168, "naklon": 0 }, +{ "label": "20/59", "node": 3125, "naklon": 0 }, +{ "label": "20/60", "node": 3166, "naklon": 0 }, +{ "label": "20/61", "node": 3130, "naklon": 0 }, +{ "label": "20/62", "node": 3563, "naklon": 0 }, +{ "label": "20/63", "node": 3550, "naklon": null }, +{ "label": "20/67", "node": 3269, "naklon": 0 }, +{ "label": "21/1", "node": 2921, "naklon": 0 }, +{ "label": "21/2", "node": 2707, "naklon": 0 }, +{ "label": "21/3", "node": 2723, "naklon": 0 }, +{ "label": "21/4", "node": 2716, "naklon": 0 }, +{ "label": "21/5", "node": 2717, "naklon": 0 }, +{ "label": "21/6", "node": 2720, "naklon": 0 }, +{ "label": "21/7", "node": 2722, "naklon": 0 }, +{ "label": "21/8", "node": 2718, "naklon": 0 }, +{ "label": "21/9", "node": 2724, "naklon": 0 }, +{ "label": "21/10", "node": 2742, "naklon": 0 }, +{ "label": "21/11", "node": 2743, "naklon": 0 }, +{ "label": "21/12", "node": 2733, "naklon": 0 }, +{ "label": "21/14", "node": 2903, "naklon": 0 }, +{ "label": "21/15", "node": 2917, "naklon": 0 }, +{ "label": "21/16", "node": 2897, "naklon": 0 }, +{ "label": "21/17", "node": 2914, "naklon": 0 }, +{ "label": "21/18", "node": 2898, "naklon": 0 }, +{ "label": "21/19", "node": 2773, "naklon": 0 }, +{ "label": "21/20", "node": 2895, "naklon": 0 }, +{ "label": "21/21", "node": 2896, "naklon": 0 }, +{ "label": "21/22", "node": 2771, "naklon": 0 }, +{ "label": "21/23", "node": 2772, "naklon": 0 }, +{ "label": "21/24", "node": 2793, "naklon": 0 }, +{ "label": "21/25", "node": 2902, "naklon": 0 }, +{ "label": "21/26", "node": 2910, "naklon": 0 }, +{ "label": "21/27", "node": 2909, "naklon": 0 }, +{ "label": "21/28", "node": 2920, "naklon": 0 }, +{ "label": "21/29", "node": 2916, "naklon": 0 }, +{ "label": "21/30", "node": 2904, "naklon": 0 }, +{ "label": "21/31", "node": 2915, "naklon": 0 }, +{ "label": "21/32", "node": 2905, "naklon": 0 }, +{ "label": "21/33", "node": 2900, "naklon": 0 }, +{ "label": "21/34", "node": 2899, "naklon": 0 }, +{ "label": "21/36", "node": 2741, "naklon": 0 }, +{ "label": "21/37", "node": 2714, "naklon": 0 }, +{ "label": "21/38", "node": 2701, "naklon": 0 }, +{ "label": "21/39", "node": 2703, "naklon": 0 }, +{ "label": "21/40", "node": 2704, "naklon": 0 }, +{ "label": "21/41", "node": 2702, "naklon": 0 }, +{ "label": "21/42", "node": 2706, "naklon": 0 }, +{ "label": "21/43", "node": 2776, "naklon": 0 }, +{ "label": "21/44", "node": 2770, "naklon": 0 }, +{ "label": "21/45", "node": 2786, "naklon": 0 }, +{ "label": "21/46", "node": 2779, "naklon": 0 }, +{ "label": "21/47", "node": 2782, "naklon": 0 }, +{ "label": "21/48", "node": 2785, "naklon": 0 }, +{ "label": "21/49", "node": 2769, "naklon": 0 }, +{ "label": "21/50", "node": 3354, "naklon": 0 }, +{ "label": "21/51", "node": 2778, "naklon": 0 }, +{ "label": "21/52", "node": 2775, "naklon": 0 }, +{ "label": "21/53", "node": 2780, "naklon": 0 }, +{ "label": "21/54", "node": 2790, "naklon": 0 }, +{ "label": "21/55", "node": 2792, "naklon": 0 }, +{ "label": "21/56", "node": 2774, "naklon": 0 }, +{ "label": "22/1", "node": 2630, "naklon": 0 }, +{ "label": "22/2", "node": 2631, "naklon": 0 }, +{ "label": "22/3", "node": 2632, "naklon": 0 }, +{ "label": "22/4", "node": 2633, "naklon": 0 }, +{ "label": "22/5", "node": 2634, "naklon": 0 }, +{ "label": "22/6", "node": 2636, "naklon": 0 }, +{ "label": "22/7", "node": 4367, "naklon": 0 }, +{ "label": "22/8", "node": 2637, "naklon": 0 }, +{ "label": "22/9", "node": 2638, "naklon": 0 }, +{ "label": "22/10", "node": 2639, "naklon": 0 }, +{ "label": "22/11", "node": 2640, "naklon": 0 }, +{ "label": "22/12", "node": 2641, "naklon": 0 }, +{ "label": "22/13", "node": 2642, "naklon": 0 }, +{ "label": "22/14", "node": 2643, "naklon": 0 }, +{ "label": "22/15", "node": 2644, "naklon": 0 }, +{ "label": "22/16", "node": 2645, "naklon": 0 }, +{ "label": "22/17", "node": 2646, "naklon": 0 }, +{ "label": "22/18", "node": 2647, "naklon": 0 }, +{ "label": "22/19", "node": 2648, "naklon": 0 }, +{ "label": "22/20", "node": 2649, "naklon": 0 }, +{ "label": "22/21", "node": 2650, "naklon": 0 }, +{ "label": "22/22", "node": 2651, "naklon": 0 }, +{ "label": "22/23", "node": 4103, "naklon": 0 }, +{ "label": "22/24", "node": 2653, "naklon": 0 }, +{ "label": "22/25", "node": 2654, "naklon": 0 }, +{ "label": "22/26", "node": 2655, "naklon": 0 }, +{ "label": "22/27", "node": 2656, "naklon": 0 }, +{ "label": "22/28", "node": 2657, "naklon": 0 }, +{ "label": "22/29", "node": 2658, "naklon": 0 }, +{ "label": "22/30", "node": 2659, "naklon": 0 }, +{ "label": "22/31", "node": 2660, "naklon": 0 }, +{ "label": "22/32", "node": 2661, "naklon": 0 }, +{ "label": "22/32/1", "node": 3015, "naklon": 0 }, +{ "label": "22/33", "node": 2662, "naklon": 0 }, +{ "label": "22/34", "node": 2663, "naklon": 0 }, +{ "label": "22/35", "node": 2664, "naklon": 0 }, +{ "label": "22/36", "node": 2665, "naklon": 0 }, +{ "label": "22/37", "node": 2666, "naklon": 0 }, +{ "label": "22/38", "node": 2667, "naklon": 0 }, +{ "label": "22/39", "node": 2668, "naklon": 0 }, +{ "label": "22/40", "node": 2669, "naklon": null }, +{ "label": "22/41", "node": 2670, "naklon": null }, +{ "label": "22/42", "node": 2671, "naklon": null }, +{ "label": "23/9A", "node": 3087, "naklon": 10 }, +{ "label": "23/9B", "node": 3090, "naklon": 10 }, +{ "label": "23/1", "node": 3075, "naklon": 0 }, +{ "label": "23/2", "node": 3089, "naklon": 0 }, +{ "label": "23/3", "node": 3088, "naklon": 0 }, +{ "label": "23/4", "node": 3228, "naklon": 10 }, +{ "label": "23/5", "node": 2751, "naklon": 10 }, +{ "label": "23/6", "node": 3243, "naklon": 10 }, +{ "label": "23/7", "node": 4349, "naklon": 10 }, +{ "label": "23/8", "node": 3102, "naklon": 10 }, +{ "label": "23/10", "node": 3099, "naklon": 10 }, +{ "label": "23/11", "node": 3103, "naklon": 10 }, +{ "label": "23/12", "node": 3093, "naklon": 10 }, +{ "label": "23/13", "node": 3098, "naklon": 10 }, +{ "label": "23/14", "node": 3092, "naklon": 10 }, +{ "label": "23/15", "node": 3233, "naklon": 0 }, +{ "label": "23/16", "node": 3095, "naklon": 0 }, +{ "label": "23/17", "node": 4074, "naklon": 0 }, +{ "label": "23/18", "node": 2729, "naklon": 0 }, +{ "label": "23/19", "node": 3234, "naklon": 0 }, +{ "label": "23/20", "node": 3094, "naklon": 0 }, +{ "label": "23/21", "node": 2817, "naklon": 0 }, +{ "label": "23/22", "node": 3226, "naklon": 0 }, +{ "label": "23/23", "node": 3225, "naklon": 0 }, +{ "label": "23/24", "node": 3237, "naklon": 0 }, +{ "label": "23/25", "node": 4250, "naklon": 0 }, +{ "label": "23/26", "node": 3059, "naklon": 10 }, +{ "label": "23/27", "node": 3238, "naklon": 10 }, +{ "label": "23/28", "node": 3242, "naklon": 10 }, +{ "label": "23/29", "node": 3236, "naklon": 10 }, +{ "label": "23/30", "node": 3112, "naklon": 10 }, +{ "label": "23/31", "node": 3224, "naklon": 0 }, +{ "label": "23/32", "node": 4298, "naklon": 10 }, +{ "label": "23/33", "node": 4150, "naklon": 10 }, +{ "label": "23/34", "node": 3091, "naklon": 10 }, +{ "label": "25/1", "node": 3771, "naklon": 5 }, +{ "label": "25/2", "node": 3777, "naklon": 5 }, +{ "label": "25/3", "node": 3749, "naklon": 5 }, +{ "label": "25/4", "node": 3769, "naklon": 5 }, +{ "label": "25/5", "node": 3765, "naklon": 5 }, +{ "label": "25/6", "node": 3785, "naklon": 5 }, +{ "label": "25/7", "node": 3761, "naklon": 5 }, +{ "label": "25/8", "node": 3758, "naklon": 5 }, +{ "label": "25/9", "node": 3766, "naklon": 5 }, +{ "label": "25/10", "node": 3779, "naklon": 5 }, +{ "label": "25/11", "node": 3899, "naklon": 10 }, +{ "label": "25/12", "node": 3922, "naklon": 10 }, +{ "label": "25/13", "node": 3912, "naklon": 10 }, +{ "label": "25/14", "node": 3933, "naklon": 10 }, +{ "label": "25/15", "node": 3921, "naklon": 10 }, +{ "label": "25/16", "node": 4300, "naklon": 10 }, +{ "label": "25/17", "node": 3927, "naklon": 10 }, +{ "label": "25/18", "node": 3212, "naklon": 10 }, +{ "label": "25/19", "node": 3208, "naklon": 10 }, +{ "label": "25/20", "node": 3207, "naklon": 10 }, +{ "label": "25/21", "node": 4294, "naklon": 10 }, +{ "label": "25/22", "node": 3209, "naklon": 10 }, +{ "label": "25/23", "node": 3745, "naklon": 10 }, +{ "label": "25/24", "node": 3762, "naklon": 10 }, +{ "label": "25/25", "node": 3215, "naklon": 10 }, +{ "label": "25/26", "node": 3210, "naklon": 10 }, +{ "label": "25/27", "node": 3211, "naklon": 10 }, +{ "label": "25/28", "node": 3206, "naklon": 10 }, +{ "label": "25/29", "node": 3918, "naklon": 5 }, +{ "label": "25/30", "node": 3928, "naklon": 5 }, +{ "label": "25/31", "node": 3917, "naklon": 5 }, +{ "label": "25/32", "node": 4029, "naklon": 0 }, +{ "label": "25/33", "node": 4038, "naklon": 0 }, +{ "label": "25/34", "node": 4022, "naklon": 0 }, +{ "label": "25/35", "node": 3937, "naklon": 0 }, +{ "label": "25/36", "node": 3190, "naklon": 0 }, +{ "label": "25/37", "node": 3835, "naklon": 0 }, +{ "label": "25/38", "node": 3201, "naklon": 0 }, +{ "label": "25/39", "node": 3193, "naklon": 0 }, +{ "label": "25/40", "node": 3191, "naklon": 0 }, +{ "label": "25/41", "node": 3203, "naklon": 0 }, +{ "label": "25/42", "node": 4301, "naklon": 0 }, +{ "label": "25/43", "node": 3223, "naklon": 0 }, +{ "label": "25/44", "node": 3202, "naklon": 0 }, +{ "label": "25/45", "node": 3205, "naklon": 0 }, +{ "label": "25/46", "node": 3194, "naklon": 0 }, +{ "label": "25/47", "node": 3198, "naklon": 0 }, +{ "label": "25/48", "node": 3204, "naklon": 0 }, +{ "label": "25/49", "node": 3200, "naklon": 0 }, +{ "label": "25/50", "node": 3216, "naklon": 0 }, +{ "label": "25/51", "node": 3932, "naklon": 5 }, +{ "label": "25/52", "node": 3923, "naklon": 5 }, +{ "label": "25/53", "node": 3913, "naklon": 5 }, +{ "label": "25/54", "node": 3900, "naklon": 5 }, +{ "label": "25/55", "node": 4189, "naklon": 10 }, +{ "label": "25/56", "node": 4191, "naklon": 10 }, +{ "label": "25/57", "node": 3790, "naklon": 10 }, +{ "label": "25/58", "node": 4190, "naklon": 10 }, +{ "label": "25/59", "node": 4302, "naklon": 0 }, +{ "label": "25/60", "node": 4351, "naklon": 0 }, +{ "label": "25/61", "node": 4075, "naklon": 0 }, +{ "label": "25/62", "node": 4071, "naklon": 0 }, +{ "label": "25/63", "node": 3784, "naklon": 0 }, +{ "label": "25/64", "node": 4065, "naklon": 0 }, +{ "label": "25/65", "node": 4297, "naklon": 0 }, +{ "label": "25/66", "node": 4295, "naklon": 0 }, +{ "label": "25/67", "node": 4299, "naklon": 0 }, +{ "label": "25/68", "node": 3772, "naklon": 0 }, +{ "label": "25/69", "node": 3941, "naklon": 0 }, +{ "label": "25/70", "node": 3782, "naklon": 0 }, +{ "label": "25/71", "node": 4068, "naklon": 0 }, +{ "label": "25/72", "node": 4073, "naklon": 0 }, +{ "label": "25/73", "node": 3901, "naklon": 5 }, +{ "label": "25/74", "node": 4296, "naklon": 5 }, +{ "label": "25/75", "node": 3910, "naklon": 5 }, +{ "label": "25/76", "node": 4293, "naklon": 5 }, +{ "label": "25/77", "node": 3919, "naklon": 5 }, +{ "label": "25/78", "node": 3924, "naklon": 5 }, +{ "label": "25/79", "node": 3909, "naklon": 5 }, +{ "label": "25/80", "node": 3896, "naklon": 5 }, +{ "label": "25/81", "node": 3911, "naklon": 5 }, +{ "label": "25/82", "node": 2819, "naklon": 15 }, +{ "label": "25/83", "node": 3776, "naklon": 15 }, +{ "label": "25/84", "node": 3752, "naklon": 15 }, +{ "label": "25/85", "node": 4353, "naklon": 15 }, +{ "label": "25/86", "node": 3791, "naklon": 0 }, +{ "label": "25/87", "node": 3770, "naklon": 0 }, +{ "label": "25/88", "node": 3760, "naklon": 0 }, +{ "label": "25/89", "node": 3115, "naklon": 0 }, +{ "label": "25/90", "node": 3738, "naklon": 0 }, +{ "label": "25/91", "node": 3748, "naklon": 0 }, +{ "label": "25/92", "node": 3753, "naklon": 0 }, +{ "label": "25/93", "node": 3775, "naklon": 0 }, +{ "label": "25/94", "node": 3778, "naklon": 5 }, +{ "label": "25/95", "node": 4078, "naklon": 5 }, +{ "label": "25/96", "node": 4088, "naklon": 5 }, +{ "label": "25/97", "node": 3856, "naklon": 5 }, +{ "label": "25/98", "node": 4084, "naklon": 5 }, +{ "label": "25/99", "node": 4069, "naklon": 5 }, +{ "label": "25/100", "node": 4188, "naklon": 5 }, +{ "label": "25/101", "node": 4064, "naklon": 5 }, +{ "label": "25/102", "node": 3792, "naklon": 5 }, +{ "label": "25/103", "node": 3780, "naklon": 5 }, +{ "label": "25/104", "node": 4034, "naklon": 5 }, +{ "label": "25/105", "node": 4072, "naklon": 5 }, +{ "label": "25/106", "node": 3884, "naklon": 5 }, +{ "label": "25/107", "node": 3793, "naklon": 5 }, +{ "label": "25/108", "node": 3863, "naklon": 5 }, +{ "label": "25/109", "node": 3855, "naklon": 5 }, +{ "label": "33/1", "node": 3846, "naklon": 0 }, +{ "label": "33/2", "node": 3943, "naklon": 0 }, +{ "label": "33/3", "node": 3903, "naklon": 0 }, +{ "label": "33/4", "node": 3982, "naklon": 0 }, +{ "label": "33/5", "node": 3879, "naklon": 0 }, +{ "label": "33/6", "node": 3887, "naklon": 0 }, +{ "label": "33/7", "node": 3920, "naklon": 5 }, +{ "label": "33/8", "node": 3942, "naklon": 5 }, +{ "label": "33/9", "node": 3829, "naklon": null }, +{ "label": "34/79A", "node": 3452, "naklon": 6 }, +{ "label": "34/79B", "node": 3460, "naklon": 6 }, +{ "label": "34/90A", "node": 3443, "naklon": 6 }, +{ "label": "34/90B", "node": 3445, "naklon": 6 }, +{ "label": "34/90C", "node": 3457, "naklon": 6 }, +{ "label": "34/97A", "node": 3461, "naklon": 6 }, +{ "label": "34/97B", "node": 3463, "naklon": 6 }, +{ "label": "34/98A", "node": 3426, "naklon": 6 }, +{ "label": "34/98B", "node": 3444, "naklon": 6 }, +{ "label": "34/99A", "node": 3453, "naklon": 6 }, +{ "label": "34/99B", "node": 3455, "naklon": 6 }, +{ "label": "34/1", "node": 4009, "naklon": 0 }, +{ "label": "34/2", "node": 3602, "naklon": 0 }, +{ "label": "34/3", "node": 3441, "naklon": 0 }, +{ "label": "34/4", "node": 3464, "naklon": 0 }, +{ "label": "34/5", "node": 3883, "naklon": 0 }, +{ "label": "34/6", "node": 4098, "naklon": 0 }, +{ "label": "34/7", "node": 4003, "naklon": 0 }, +{ "label": "34/8", "node": 4004, "naklon": 0 }, +{ "label": "34/9", "node": 3888, "naklon": 0 }, +{ "label": "34/10", "node": 3997, "naklon": 0 }, +{ "label": "34/11", "node": 4006, "naklon": 0 }, +{ "label": "34/12", "node": 4000, "naklon": 0 }, +{ "label": "34/13", "node": 4011, "naklon": 0 }, +{ "label": "34/14", "node": 3999, "naklon": 0 }, +{ "label": "34/15", "node": 3981, "naklon": 0 }, +{ "label": "34/16", "node": 3988, "naklon": 0 }, +{ "label": "34/17", "node": 3986, "naklon": 0 }, +{ "label": "34/18", "node": 3998, "naklon": 0 }, +{ "label": "34/19", "node": 3983, "naklon": 0 }, +{ "label": "34/20", "node": 4005, "naklon": 0 }, +{ "label": "34/21", "node": 4001, "naklon": 0 }, +{ "label": "34/22", "node": 4008, "naklon": 0 }, +{ "label": "34/23", "node": 4002, "naklon": 0 }, +{ "label": "34/24", "node": 3996, "naklon": 0 }, +{ "label": "34/25", "node": 4007, "naklon": 0 }, +{ "label": "34/26", "node": 4113, "naklon": 15 }, +{ "label": "34/27", "node": 3595, "naklon": 5 }, +{ "label": "34/28", "node": 3599, "naklon": 5 }, +{ "label": "34/29", "node": 3601, "naklon": 5 }, +{ "label": "34/30", "node": 4205, "naklon": 0 }, +{ "label": "34/31", "node": 3987, "naklon": null }, +{ "label": "34/32", "node": 4214, "naklon": 0 }, +{ "label": "34/33", "node": 4226, "naklon": 0 }, +{ "label": "34/34", "node": 4209, "naklon": 0 }, +{ "label": "34/35", "node": 4201, "naklon": 0 }, +{ "label": "34/36", "node": 3440, "naklon": 0 }, +{ "label": "34/37", "node": 3465, "naklon": 0 }, +{ "label": "34/38", "node": 3446, "naklon": 0 }, +{ "label": "34/39", "node": 4039, "naklon": 5 }, +{ "label": "34/40", "node": 4057, "naklon": 5 }, +{ "label": "34/41", "node": 3985, "naklon": 0 }, +{ "label": "34/42", "node": 3882, "naklon": 0 }, +{ "label": "34/43", "node": 4040, "naklon": 5 }, +{ "label": "34/44", "node": 3231, "naklon": 0 }, +{ "label": "34/45", "node": 3227, "naklon": 0 }, +{ "label": "34/46", "node": 3431, "naklon": 0 }, +{ "label": "34/47", "node": 4013, "naklon": 0 }, +{ "label": "34/48", "node": 4045, "naklon": 0 }, +{ "label": "34/49", "node": 3949, "naklon": 0 }, +{ "label": "34/50", "node": 3953, "naklon": 0 }, +{ "label": "34/51", "node": 3952, "naklon": 0 }, +{ "label": "34/52", "node": 3995, "naklon": 0 }, +{ "label": "34/53", "node": 3992, "naklon": 0 }, +{ "label": "34/54", "node": 4198, "naklon": 0 }, +{ "label": "34/55", "node": 3935, "naklon": 0 }, +{ "label": "34/56", "node": 4050, "naklon": 0 }, +{ "label": "34/57", "node": 4049, "naklon": 0 }, +{ "label": "34/58", "node": 4054, "naklon": 0 }, +{ "label": "34/59", "node": 3663, "naklon": 6 }, +{ "label": "34/60", "node": 3661, "naklon": 6 }, +{ "label": "34/61", "node": 3664, "naklon": 6 }, +{ "label": "34/62", "node": 3660, "naklon": 6 }, +{ "label": "34/63", "node": 3662, "naklon": 6 }, +{ "label": "34/65", "node": 3665, "naklon": 6 }, +{ "label": "34/66", "node": 3667, "naklon": 6 }, +{ "label": "34/67", "node": 3675, "naklon": 6 }, +{ "label": "34/68", "node": 3666, "naklon": 6 }, +{ "label": "34/69", "node": 3652, "naklon": 6 }, +{ "label": "34/70", "node": 3458, "naklon": 6 }, +{ "label": "34/70/1", "node": 4425, "naklon": 6 }, +{ "label": "34/71", "node": 3459, "naklon": 6 }, +{ "label": "34/72", "node": 3435, "naklon": 6 }, +{ "label": "34/73", "node": 3448, "naklon": 6 }, +{ "label": "34/74", "node": 3451, "naklon": 6 }, +{ "label": "34/75", "node": 3442, "naklon": 6 }, +{ "label": "34/76", "node": 3449, "naklon": 6 }, +{ "label": "34/77", "node": 3450, "naklon": 6 }, +{ "label": "34/78", "node": 3433, "naklon": 6 }, +{ "label": "34/80", "node": 3432, "naklon": 12 }, +{ "label": "34/81", "node": 3470, "naklon": 12 }, +{ "label": "34/82", "node": 3438, "naklon": 12 }, +{ "label": "34/83", "node": 3439, "naklon": 12 }, +{ "label": "34/84", "node": 4028, "naklon": 5 }, +{ "label": "34/85", "node": 3596, "naklon": 5 }, +{ "label": "34/86", "node": 4021, "naklon": 5 }, +{ "label": "34/87", "node": 3437, "naklon": 12 }, +{ "label": "34/88", "node": 3428, "naklon": 12 }, +{ "label": "34/89", "node": 3430, "naklon": 12 }, +{ "label": "34/91", "node": 3454, "naklon": 6 }, +{ "label": "34/92", "node": 3492, "naklon": 6 }, +{ "label": "34/93", "node": 3462, "naklon": 6 }, +{ "label": "34/94", "node": 3427, "naklon": 6 }, +{ "label": "34/95", "node": 3434, "naklon": 6 }, +{ "label": "34/96", "node": 3456, "naklon": 6 }, +{ "label": "34/98/1", "node": 4307, "naklon": 6 }, +{ "label": "35/1", "node": 3968, "naklon": 0 }, +{ "label": "35/2", "node": 3969, "naklon": 0 }, +{ "label": "35/3", "node": 3947, "naklon": 0 }, +{ "label": "35/4", "node": 3979, "naklon": 0 }, +{ "label": "35/5", "node": 3959, "naklon": 0 }, +{ "label": "35/6", "node": 3948, "naklon": 0 }, +{ "label": "35/7", "node": 3961, "naklon": 0 }, +{ "label": "35/8", "node": 3956, "naklon": 0 }, +{ "label": "35/9", "node": 3604, "naklon": 0 }, +{ "label": "35/10", "node": 3944, "naklon": 0 }, +{ "label": "35/11", "node": 3960, "naklon": 0 }, +{ "label": "35/12", "node": 3958, "naklon": 0 }, +{ "label": "35/13", "node": 4036, "naklon": 5 }, +{ "label": "35/18", "node": 3893, "naklon": 5 }, +{ "label": "35/19", "node": 4108, "naklon": 5 }, +{ "label": "35/20", "node": 4017, "naklon": 5 }, +{ "label": "35/21", "node": 3963, "naklon": 0 }, +{ "label": "35/22", "node": 3658, "naklon": 0 }, +{ "label": "35/23", "node": 3975, "naklon": 0 }, +{ "label": "35/24", "node": 3980, "naklon": 0 }, +{ "label": "35/25", "node": 4012, "naklon": 0 }, +{ "label": "35/26", "node": 3655, "naklon": 0 }, +{ "label": "35/27", "node": 3962, "naklon": 0 }, +{ "label": "35/28", "node": 3945, "naklon": 0 }, +{ "label": "35/29", "node": 3569, "naklon": 0 }, +{ "label": "35/30", "node": 3429, "naklon": 0 }, +{ "label": "35/31", "node": 3657, "naklon": 0 }, +{ "label": "35/32", "node": 3646, "naklon": 0 }, +{ "label": "35/33", "node": 3622, "naklon": 0 }, +{ "label": "35/34", "node": 3612, "naklon": 0 }, +{ "label": "35/35", "node": 3955, "naklon": 0 }, +{ "label": "35/37", "node": 3878, "naklon": 0 }, +{ "label": "35/38", "node": 3965, "naklon": 0 }, +{ "label": "35/39", "node": 3970, "naklon": 0 }, +{ "label": "35/40", "node": 3611, "naklon": 0 }, +{ "label": "35/41", "node": 2635, "naklon": 0 }, +{ "label": "35/42", "node": 3978, "naklon": 0 }, +{ "label": "35/43", "node": 4213, "naklon": 0 }, +{ "label": "35/44", "node": 3984, "naklon": 0 }, +{ "label": "35/45", "node": 4218, "naklon": 0 }, +{ "label": "35/46", "node": 3973, "naklon": 0 }, +{ "label": "35/47", "node": 3974, "naklon": 0 }, +{ "label": "35/48", "node": 3759, "naklon": 0 }, +{ "label": "35/49", "node": 3844, "naklon": 0 }, +{ "label": "35/50", "node": 3804, "naklon": 0 }, +{ "label": "35/51", "node": 3831, "naklon": 0 }, +{ "label": "35/52", "node": 3643, "naklon": 0 }, +{ "label": "35/53", "node": 3966, "naklon": 0 }, +{ "label": "35/54", "node": 3971, "naklon": 0 }, +{ "label": "35/55", "node": 3650, "naklon": 6 }, +{ "label": "35/56", "node": 3651, "naklon": 6 }, +{ "label": "35/57", "node": 3669, "naklon": 6 }, +{ "label": "35/58", "node": 3648, "naklon": 6 }, +{ "label": "35/59", "node": 3645, "naklon": 6 }, +{ "label": "35/60", "node": 3659, "naklon": 6 }, +{ "label": "35/61", "node": 3647, "naklon": 6 }, +{ "label": "35/62", "node": 3644, "naklon": 6 }, +{ "label": "35/63", "node": 3671, "naklon": 6 }, +{ "label": "35/64", "node": 3682, "naklon": 6 }, +{ "label": "35/65", "node": 3672, "naklon": 6 }, +{ "label": "35/66", "node": 3683, "naklon": 6 }, +{ "label": "35/67", "node": 3673, "naklon": 6 }, +{ "label": "35/68", "node": 3674, "naklon": 6 }, +{ "label": "35/69", "node": 3679, "naklon": 6 }, +{ "label": "35/70", "node": 3649, "naklon": 6 }, +{ "label": "35/71", "node": 3687, "naklon": 6 }, +{ "label": "35/72", "node": 3677, "naklon": 6 }, +{ "label": "35/73", "node": 3690, "naklon": 6 }, +{ "label": "35/74", "node": 3691, "naklon": 6 }, +{ "label": "35/75", "node": 3676, "naklon": 6 }, +{ "label": "35/76", "node": 3680, "naklon": 6 }, +{ "label": "35/77", "node": 3668, "naklon": 6 }, +{ "label": "35/78", "node": 3681, "naklon": 6 }, +{ "label": "35/79", "node": 3670, "naklon": 6 }, +{ "label": "35/80", "node": 3689, "naklon": 6 }, +{ "label": "35/81", "node": 3678, "naklon": 6 }, +{ "label": "35/82", "node": 3693, "naklon": 6 }, +{ "label": "35/83", "node": 3654, "naklon": null }, +{ "label": "36/1", "node": 4086, "naklon": 0 }, +{ "label": "36/2", "node": 4085, "naklon": 0 }, +{ "label": "36/3", "node": 4083, "naklon": 0 }, +{ "label": "36/4", "node": 4087, "naklon": 0 }, +{ "label": "36/5", "node": 4077, "naklon": 0 }, +{ "label": "36/6", "node": 4082, "naklon": 0 }, +{ "label": "36/7", "node": 4186, "naklon": 0 }, +{ "label": "36/8", "node": 4206, "naklon": 0 }, +{ "label": "36/9", "node": 4080, "naklon": 0 }, +{ "label": "36/10", "node": 4081, "naklon": 0 }, +{ "label": "36/11", "node": 4210, "naklon": 0 }, +{ "label": "36/12", "node": 4079, "naklon": 0 }, +{ "label": "36/13", "node": 4076, "naklon": 0 }, +{ "label": "36/14", "node": 3852, "naklon": 0 }, +{ "label": "36/15", "node": 2813, "naklon": 0 }, +{ "label": "36/16", "node": 4219, "naklon": 0 }, +{ "label": "37/1A", "node": 3104, "naklon": 15 }, +{ "label": "37/1B", "node": 3121, "naklon": 15 }, +{ "label": "37/2", "node": 3113, "naklon": 10 }, +{ "label": "37/3", "node": 3118, "naklon": 10 }, +{ "label": "37/4", "node": 3111, "naklon": 10 }, +{ "label": "37/5", "node": 4020, "naklon": 10 }, +{ "label": "37/6", "node": 3119, "naklon": 10 }, +{ "label": "37/7", "node": 3110, "naklon": 10 }, +{ "label": "37/8", "node": 3108, "naklon": 10 }, +{ "label": "37/12", "node": 3107, "naklon": 0 }, +{ "label": "37/13", "node": 3199, "naklon": 0 }, +{ "label": "37/14", "node": 3120, "naklon": 0 }, +{ "label": "37/15", "node": 3122, "naklon": 0 }, +{ "label": "37/16", "node": 3908, "naklon": 0 }, +{ "label": "37/17", "node": 3114, "naklon": 0 }, +{ "label": "37/18", "node": 3105, "naklon": 0 }, +{ "label": "37/19", "node": 3116, "naklon": 0 }, +{ "label": "37/20", "node": 3106, "naklon": 0 }, +{ "label": "37/21", "node": 2887, "naklon": 5 }, +{ "label": "37/22", "node": 2888, "naklon": 5 }, +{ "label": "37/23", "node": 2877, "naklon": 5 }, +{ "label": "37/24", "node": 2891, "naklon": 5 }, +{ "label": "37/25", "node": 2886, "naklon": 5 }, +{ "label": "37/26", "node": 2892, "naklon": 5 }, +{ "label": "37/27", "node": 2882, "naklon": 5 }, +{ "label": "37/28", "node": 2883, "naklon": 5 }, +{ "label": "37/29", "node": 2876, "naklon": 5 }, +{ "label": "37/30", "node": 3109, "naklon": 5 }, +{ "label": "37/31", "node": 4152, "naklon": 5 }, +{ "label": "37/32", "node": 3117, "naklon": 5 }, +{ "label": "37/33", "node": 2870, "naklon": 5 }, +{ "label": "37/34", "node": 2867, "naklon": 0 }, +{ "label": "37/35", "node": 2865, "naklon": 0 }, +{ "label": "37/36", "node": 3096, "naklon": 0 }, +{ "label": "37/37", "node": 2871, "naklon": 0 }, +{ "label": "37/38", "node": 2884, "naklon": 0 }, +{ "label": "37/39", "node": 2855, "naklon": 0 }, +{ "label": "37/40", "node": 2878, "naklon": 0 }, +{ "label": "37/41", "node": 2889, "naklon": 0 }, +{ "label": "37/42", "node": 2879, "naklon": 0 }, +{ "label": "37/43", "node": 2850, "naklon": 0 }, +{ "label": "37/44", "node": 2894, "naklon": 0 }, +{ "label": "37/45", "node": 2880, "naklon": 0 }, +{ "label": "37/46", "node": 2893, "naklon": 0 }, +{ "label": "37/47", "node": 2890, "naklon": 0 }, +{ "label": "37/48", "node": 4355, "naklon": 0 }, +{ "label": "37/49", "node": 2885, "naklon": 0 }, +{ "label": "37/50", "node": 2875, "naklon": 0 }, +{ "label": "38/30A", "node": 3486, "naklon": 5 }, +{ "label": "38/30B", "node": 3714, "naklon": 0 }, +{ "label": "38/32A", "node": 3483, "naklon": 5 }, +{ "label": "38/32B", "node": 3496, "naklon": 0 }, +{ "label": "38/35A", "node": 3487, "naklon": 5 }, +{ "label": "38/35B", "node": 3498, "naklon": 5 }, +{ "label": "38/38A", "node": 3578, "naklon": 5 }, +{ "label": "38/38B", "node": 3508, "naklon": 5 }, +{ "label": "38/59A", "node": 3787, "naklon": 5 }, +{ "label": "38/59B", "node": 3491, "naklon": 5 }, +{ "label": "38/1", "node": 3568, "naklon": null }, +{ "label": "38/2", "node": 3502, "naklon": 0 }, +{ "label": "38/3", "node": 3836, "naklon": 0 }, +{ "label": "38/4", "node": 3588, "naklon": 0 }, +{ "label": "38/5", "node": 3493, "naklon": 0 }, +{ "label": "38/6", "node": 3580, "naklon": 0 }, +{ "label": "38/7", "node": 3572, "naklon": 0 }, +{ "label": "38/8", "node": 3506, "naklon": 0 }, +{ "label": "38/9", "node": 3503, "naklon": 0 }, +{ "label": "38/10", "node": 3579, "naklon": 0 }, +{ "label": "38/11", "node": 3586, "naklon": 0 }, +{ "label": "38/12", "node": 3495, "naklon": 5 }, +{ "label": "38/13", "node": 3492, "naklon": 5 }, +{ "label": "38/14", "node": 3532, "naklon": 5 }, +{ "label": "38/15", "node": 3574, "naklon": 5 }, +{ "label": "38/16", "node": 4140, "naklon": 5 }, +{ "label": "38/17", "node": 3795, "naklon": 5 }, +{ "label": "38/18", "node": 3788, "naklon": 5 }, +{ "label": "38/19", "node": 3796, "naklon": 5 }, +{ "label": "38/20", "node": 3797, "naklon": 5 }, +{ "label": "38/21", "node": 3798, "naklon": 5 }, +{ "label": "38/22", "node": 3786, "naklon": 5 }, +{ "label": "38/23", "node": 4067, "naklon": 5 }, +{ "label": "38/24", "node": 3773, "naklon": 5 }, +{ "label": "38/25", "node": 3774, "naklon": 5 }, +{ "label": "38/26", "node": 3789, "naklon": 5 }, +{ "label": "38/27", "node": 3520, "naklon": null }, +{ "label": "38/29", "node": 3577, "naklon": 5 }, +{ "label": "38/31", "node": 3530, "naklon": null }, +{ "label": "38/33", "node": 3488, "naklon": 5 }, +{ "label": "38/34", "node": 3505, "naklon": 5 }, +{ "label": "38/36", "node": 3497, "naklon": 5 }, +{ "label": "38/37", "node": 3490, "naklon": 5 }, +{ "label": "38/39", "node": 3585, "naklon": 5 }, +{ "label": "38/40", "node": 3582, "naklon": 5 }, +{ "label": "38/41", "node": 3507, "naklon": 5 }, +{ "label": "38/42", "node": 3484, "naklon": 5 }, +{ "label": "38/43", "node": 3501, "naklon": 5 }, +{ "label": "38/44", "node": 3581, "naklon": 5 }, +{ "label": "38/45", "node": 4192, "naklon": 5 }, +{ "label": "38/46", "node": 3576, "naklon": 5 }, +{ "label": "38/47", "node": 3489, "naklon": 5 }, +{ "label": "38/48", "node": 3573, "naklon": 5 }, +{ "label": "38/49", "node": 3504, "naklon": 5 }, +{ "label": "38/50", "node": 3794, "naklon": 5 }, +{ "label": "38/51", "node": 3485, "naklon": 5 }, +{ "label": "38/52", "node": 3482, "naklon": 5 }, +{ "label": "38/53", "node": 3575, "naklon": 5 }, +{ "label": "38/54", "node": 3499, "naklon": 5 }, +{ "label": "38/55", "node": 3494, "naklon": 5 }, +{ "label": "38/56", "node": 3583, "naklon": 5 }, +{ "label": "38/57", "node": 3570, "naklon": 5 }, +{ "label": "38/58", "node": 3500, "naklon": 0 }, +{ "label": "38/63", "node": 3510, "naklon": null }, +{ "label": "38/64", "node": 3512, "naklon": null }, +{ "label": "38/67", "node": 3535, "naklon": null }, +{ "label": "38/68", "node": 3531, "naklon": null }, +{ "label": "38/69", "node": 3537, "naklon": null }, +{ "label": "39/1", "node": 3522, "naklon": 10 }, +{ "label": "39/2", "node": 4018, "naklon": 10 }, +{ "label": "39/3", "node": 4019, "naklon": 10 }, +{ "label": "39/4", "node": 4154, "naklon": 5 }, +{ "label": "39/5", "node": 3907, "naklon": 5 }, +{ "label": "39/6", "node": 4148, "naklon": 0 }, +{ "label": "39/7", "node": 4153, "naklon": 0 }, +{ "label": "39/8", "node": 3938, "naklon": 0 }, +{ "label": "39/9", "node": 3802, "naklon": 0 }, +{ "label": "39/10", "node": 4015, "naklon": 0 }, +{ "label": "39/11", "node": 3929, "naklon": 0 }, +{ "label": "39/12", "node": 3946, "naklon": 0 }, +{ "label": "39/13", "node": 4014, "naklon": 0 }, +{ "label": "39/14", "node": 4155, "naklon": 0 }, +{ "label": "39/15", "node": 4149, "naklon": 0 }, +{ "label": "39/16", "node": 3642, "naklon": 0 }, +{ "label": "39/17", "node": 3636, "naklon": 5 }, +{ "label": "39/18", "node": 3991, "naklon": 0 }, +{ "label": "39/19", "node": 3994, "naklon": 0 }, +{ "label": "39/20", "node": 3990, "naklon": 0 }, +{ "label": "39/21", "node": 3967, "naklon": 0 }, +{ "label": "39/22", "node": 3977, "naklon": 0 }, +{ "label": "39/23", "node": 3757, "naklon": 15 }, +{ "label": "39/24", "node": 3633, "naklon": 15 }, +{ "label": "39/25", "node": 3744, "naklon": 15 }, +{ "label": "39/26", "node": 4023, "naklon": 5 }, +{ "label": "39/27", "node": 3720, "naklon": 5 }, +{ "label": "39/28", "node": 3734, "naklon": 5 }, +{ "label": "39/29", "node": 3741, "naklon": 5 }, +{ "label": "39/30", "node": 3721, "naklon": 5 }, +{ "label": "39/31", "node": 3845, "naklon": 0 }, +{ "label": "39/32", "node": 3840, "naklon": 0 }, +{ "label": "39/33", "node": 3837, "naklon": null }, +{ "label": "39/34", "node": 3839, "naklon": 0 }, +{ "label": "41/1", "node": 3542, "naklon": null }, +{ "label": "41/2", "node": 3566, "naklon": null }, +{ "label": "41/3", "node": 3548, "naklon": null }, +{ "label": "41/4", "node": 3515, "naklon": null }, +{ "label": "41/5", "node": 3559, "naklon": null }, +{ "label": "41/6", "node": 3509, "naklon": null }, +{ "label": "41/7", "node": 3524, "naklon": null }, +{ "label": "41/8", "node": 3518, "naklon": null }, +{ "label": "41/9", "node": 3182, "naklon": null }, +{ "label": "41/10", "node": 3187, "naklon": null }, +{ "label": "41/11", "node": 3195, "naklon": 0 }, +{ "label": "41/12", "node": 3857, "naklon": 0 }, +{ "label": "41/13", "node": 3183, "naklon": 0 }, +{ "label": "41/14", "node": 3177, "naklon": 0 }, +{ "label": "41/15", "node": 3189, "naklon": 0 }, +{ "label": "41/16", "node": 3186, "naklon": 0 }, +{ "label": "42/1", "node": 3178, "naklon": 0 }, +{ "label": "42/2", "node": 3219, "naklon": 0 }, +{ "label": "42/3", "node": 3475, "naklon": 0 }, +{ "label": "42/4", "node": 3175, "naklon": 0 }, +{ "label": "42/5", "node": 3222, "naklon": 0 }, +{ "label": "42/6", "node": 3221, "naklon": 0 }, +{ "label": "42/7", "node": 3181, "naklon": 0 }, +{ "label": "42/8", "node": 3180, "naklon": 0 }, +{ "label": "42/9", "node": 3218, "naklon": 0 }, +{ "label": "42/10", "node": 3176, "naklon": 0 }, +{ "label": "42/11", "node": 3174, "naklon": 0 }, +{ "label": "42/12", "node": 3220, "naklon": 0 }, +{ "label": "42/13", "node": 3533, "naklon": null }, +{ "label": "42/14", "node": 3543, "naklon": null }, +{ "label": "42/15", "node": 3554, "naklon": null }, +{ "label": "42/16", "node": 3549, "naklon": null }, +{ "label": "43/1", "node": 2857, "naklon": 5 }, +{ "label": "43/2", "node": 2752, "naklon": 5 }, +{ "label": "43/3", "node": 2753, "naklon": 5 }, +{ "label": "43/4", "node": 3024, "naklon": 5 }, +{ "label": "43/5", "node": 2754, "naklon": 5 }, +{ "label": "43/6", "node": 4423, "naklon": 5 }, +{ "label": "43/7", "node": 4368, "naklon": 5 }, +{ "label": "43/8", "node": 2978, "naklon": 5 }, +{ "label": "43/9", "node": 2868, "naklon": 5 }, +{ "label": "43/10", "node": 4377, "naklon": 5 }, +{ "label": "43/11", "node": 2757, "naklon": 5 }, +{ "label": "43/12", "node": 2970, "naklon": 5 }, +{ "label": "43/13", "node": 2758, "naklon": 5 }, +{ "label": "43/14", "node": 4378, "naklon": 5 }, +{ "label": "43/15", "node": 2759, "naklon": 5 }, +{ "label": "43/16", "node": 4342, "naklon": 5 }, +{ "label": "43/17", "node": 3026, "naklon": null }, +{ "label": "43/18", "node": 2986, "naklon": null }, +{ "label": "43/19", "node": 4343, "naklon": null }, +{ "label": "43/20", "node": 2760, "naklon": null }, +{ "label": "43/21", "node": 4379, "naklon": null }, +{ "label": "43/22", "node": 2971, "naklon": null }, +{ "label": "43/23", "node": 2761, "naklon": null }, +{ "label": "43/24", "node": 2762, "naklon": null }, +{ "label": "43/25", "node": 4339, "naklon": null }, +{ "label": "43/26", "node": 4380, "naklon": null }, +{ "label": "43/27", "node": 2975, "naklon": null }, +{ "label": "43/28", "node": 3003, "naklon": null }, +{ "label": "43/29", "node": 4338, "naklon": null }, +{ "label": "43/30", "node": 3002, "naklon": null }, +{ "label": "43/31", "node": 4345, "naklon": null }, +{ "label": "43/32", "node": 2979, "naklon": null }, +{ "label": "43/33", "node": 2989, "naklon": null }, +{ "label": "43/34", "node": 2996, "naklon": null }, +{ "label": "43/35", "node": 2972, "naklon": null }, +{ "label": "43/36", "node": 2988, "naklon": null }, +{ "label": "43/37", "node": 4344, "naklon": null }, +{ "label": "43/38", "node": 3022, "naklon": null }, +{ "label": "43/39", "node": 4341, "naklon": null }, +{ "label": "43/40", "node": 2983, "naklon": null }, +{ "label": "43/41", "node": 2995, "naklon": null }, +{ "label": "43/42", "node": 2763, "naklon": null }, +{ "label": "43/43", "node": 2764, "naklon": null }, +{ "label": "43/44", "node": 2765, "naklon": null }, +{ "label": "43/45", "node": 2766, "naklon": null }, +{ "label": "43/46", "node": 2767, "naklon": null }, +{ "label": "43/47", "node": 2768, "naklon": null }, +{ "label": "43/48", "node": 3018, "naklon": null }, +{ "label": "43/49", "node": 2982, "naklon": null }, +{ "label": "43/50", "node": 3019, "naklon": 0 }, +{ "label": "43/51", "node": 3013, "naklon": null }, +{ "label": "43/52", "node": 3007, "naklon": null }, +{ "label": "43/53", "node": 2980, "naklon": null }, +{ "label": "43/54", "node": 3011, "naklon": null }, +{ "label": "43/55", "node": 2672, "naklon": null }, +{ "label": "43/56", "node": 2673, "naklon": null }, +{ "label": "43/57", "node": 2674, "naklon": null }, +{ "label": "43/58", "node": 2675, "naklon": null }, +{ "label": "43/59", "node": 2676, "naklon": null }, +{ "label": "43/60", "node": 2677, "naklon": null }, +{ "label": "43/61", "node": 2678, "naklon": null }, +{ "label": "43/62", "node": 2679, "naklon": null }, +{ "label": "43/63", "node": 2680, "naklon": null }, +{ "label": "43/64", "node": 2840, "naklon": null }, +{ "label": "43/65", "node": 2682, "naklon": null }, +{ "label": "43/66", "node": 2683, "naklon": null }, +{ "label": "43/67", "node": 2684, "naklon": 0 }, +{ "label": "43/68", "node": 2685, "naklon": null }, +{ "label": "43/69", "node": 2686, "naklon": null }, +{ "label": "43/70", "node": 2687, "naklon": null }, +{ "label": "43/71", "node": 2688, "naklon": null }, +{ "label": "43/72", "node": 2689, "naklon": null }, +{ "label": "43/73", "node": 2690, "naklon": null }, +{ "label": "43/74", "node": 2691, "naklon": null }, +{ "label": "43/75", "node": 2692, "naklon": null }, +{ "label": "43/76", "node": 2693, "naklon": 0 }, +{ "label": "43/77", "node": 2694, "naklon": null }, +{ "label": "43/78", "node": 2695, "naklon": null }, +{ "label": "43/79", "node": 2696, "naklon": 0 }, +{ "label": "43/80", "node": 2697, "naklon": null }, +{ "label": "43/81", "node": 2698, "naklon": 0 }, +{ "label": "43/82", "node": 2699, "naklon": null }, +{ "label": "43/83", "node": 2700, "naklon": 0 }, +{ "label": "43/84", "node": 2744, "naklon": null }, +{ "label": "43/85", "node": 2745, "naklon": 0 }, +{ "label": "43/86", "node": 2746, "naklon": null }, +{ "label": "43/87", "node": 2747, "naklon": 0 }, +{ "label": "43/88", "node": 2748, "naklon": null }, +{ "label": "43/89", "node": 2749, "naklon": 0 }, +{ "label": "43/90", "node": 2841, "naklon": null }, +{ "label": "45/1", "node": 4237, "naklon": 5 }, +{ "label": "45/2", "node": 4226, "naklon": 5 }, +{ "label": "45/3", "node": 4242, "naklon": 5 }, +{ "label": "45/4", "node": 4179, "naklon": 5 }, +{ "label": "45/5", "node": 4247, "naklon": 5 }, +{ "label": "45/6", "node": 4245, "naklon": 5 }, +{ "label": "45/7", "node": 3872, "naklon": 5 }, +{ "label": "45/8", "node": 4175, "naklon": 5 }, +{ "label": "45/9", "node": 4236, "naklon": 5 }, +{ "label": "45/10", "node": 4170, "naklon": 5 }, +{ "label": "45/11", "node": 4238, "naklon": 5 }, +{ "label": "45/12", "node": 4246, "naklon": 5 }, +{ "label": "45/13", "node": 4166, "naklon": 5 }, +{ "label": "45/14", "node": 4227, "naklon": 5 }, +{ "label": "45/15", "node": 4171, "naklon": 5 }, +{ "label": "45/16", "node": 4180, "naklon": 5 }, +{ "label": "45/17", "node": 4244, "naklon": 5 }, +{ "label": "45/18", "node": 4199, "naklon": 5 }, +{ "label": "45/19", "node": 4239, "naklon": 5 }, +{ "label": "45/20", "node": 4207, "naklon": 5 }, +{ "label": "45/21", "node": 4223, "naklon": 5 }, +{ "label": "45/22", "node": 4230, "naklon": 5 }, +{ "label": "45/23", "node": 4233, "naklon": 5 }, +{ "label": "45/24", "node": 4222, "naklon": 5 }, +{ "label": "45/25", "node": 4217, "naklon": 5 }, +{ "label": "45/26", "node": 4243, "naklon": 5 }, +{ "label": "45/27", "node": 4200, "naklon": 5 }, +{ "label": "45/28", "node": 4228, "naklon": 5 }, +{ "label": "45/29", "node": 4211, "naklon": 5 }, +{ "label": "45/30", "node": 4234, "naklon": 5 }, +{ "label": "45/31", "node": 4235, "naklon": 5 }, +{ "label": "45/32", "node": 4203, "naklon": 5 }, +{ "label": "45/33", "node": 4240, "naklon": 5 }, +{ "label": "45/34", "node": 4224, "naklon": 5 }, +{ "label": "45/35", "node": 4232, "naklon": 5 }, +{ "label": "45/36", "node": 4231, "naklon": 5 }, +{ "label": "45/37", "node": 4161, "naklon": 5 }, +{ "label": "45/38", "node": 4225, "naklon": 5 }, +{ "label": "45/39", "node": 4241, "naklon": 5 }, +{ "label": "45/40", "node": 4229, "naklon": 5 }, +{ "label": "45/41", "node": 4221, "naklon": 5 }, +{ "label": "45/42", "node": 4212, "naklon": 5 }, +{ "label": "45/43", "node": 4216, "naklon": 5 }, +{ "label": "45/44", "node": 3864, "naklon": null }, +{ "label": "46/1", "node": 3806, "naklon": 5 }, +{ "label": "46/2", "node": 3813, "naklon": 5 }, +{ "label": "46/3", "node": 3815, "naklon": 5 }, +{ "label": "46/4", "node": 3807, "naklon": 5 }, +{ "label": "46/5", "node": 3895, "naklon": 5 }, +{ "label": "46/6", "node": 3809, "naklon": 5 }, +{ "label": "46/7", "node": 3820, "naklon": 5 }, +{ "label": "46/8", "node": 3805, "naklon": 5 }, +{ "label": "46/9", "node": 3894, "naklon": 0 }, +{ "label": "46/10", "node": 4055, "naklon": 0 }, +{ "label": "46/11", "node": 3812, "naklon": 5 }, +{ "label": "46/12", "node": 3822, "naklon": 5 }, +{ "label": "46/13", "node": 3821, "naklon": 5 }, +{ "label": "46/14", "node": 3808, "naklon": 5 }, +{ "label": "46/15", "node": 3799, "naklon": 5 }, +{ "label": "46/16", "node": 3816, "naklon": 5 }, +{ "label": "46/17", "node": 3751, "naklon": 5 }, +{ "label": "46/18", "node": 3814, "naklon": 5 }, +{ "label": "46/19", "node": 4044, "naklon": 0 }, +{ "label": "46/20", "node": 3931, "naklon": 0 }, +{ "label": "46/21", "node": 3902, "naklon": 5 }, +{ "label": "46/22", "node": 3916, "naklon": 5 }, +{ "label": "46/23", "node": 3892, "naklon": 5 }, +{ "label": "46/24", "node": 3914, "naklon": 5 }, +{ "label": "46/25", "node": 3898, "naklon": 5 }, +{ "label": "46/26", "node": 3897, "naklon": 5 }, +{ "label": "46/27", "node": 3885, "naklon": 5 }, +{ "label": "46/28", "node": 3906, "naklon": 5 }, +{ "label": "46/29", "node": 3930, "naklon": 0 }, +{ "label": "46/30", "node": 3936, "naklon": 0 }, +{ "label": "46/31", "node": 3860, "naklon": 5 }, +{ "label": "46/32", "node": 3841, "naklon": 5 }, +{ "label": "46/33", "node": 3873, "naklon": 5 }, +{ "label": "46/34", "node": 3854, "naklon": 5 }, +{ "label": "46/35", "node": 3939, "naklon": 5 }, +{ "label": "46/36", "node": 3858, "naklon": 5 }, +{ "label": "46/37", "node": 3940, "naklon": 5 }, +{ "label": "46/38", "node": 4035, "naklon": 5 }, +{ "label": "47/1", "node": 3373, "naklon": 0 }, +{ "label": "47/2", "node": 3374, "naklon": 0 }, +{ "label": "47/3", "node": 3384, "naklon": 0 }, +{ "label": "47/4", "node": 3385, "naklon": 0 }, +{ "label": "48/1", "node": 4051, "naklon": 5 }, +{ "label": "48/2", "node": 4041, "naklon": 5 }, +{ "label": "48/3", "node": 4056, "naklon": 5 }, +{ "label": "48/4", "node": 3875, "naklon": 5 }, +{ "label": "48/5", "node": 4061, "naklon": 5 }, +{ "label": "48/6", "node": 4047, "naklon": 5 }, +{ "label": "48/7", "node": 4060, "naklon": 5 }, +{ "label": "48/8", "node": 4059, "naklon": 5 }, +{ "label": "48/9", "node": 4058, "naklon": 5 }, +{ "label": "48/10", "node": 3635, "naklon": 5 }, +{ "label": "48/11", "node": 3640, "naklon": 5 }, +{ "label": "48/12", "node": 3747, "naklon": 5 }, +{ "label": "48/13", "node": 3629, "naklon": 5 }, +{ "label": "48/14", "node": 4048, "naklon": 5 }, +{ "label": "48/15", "node": 4063, "naklon": 5 }, +{ "label": "48/16", "node": 4062, "naklon": 5 }, +{ "label": "48/17", "node": 4043, "naklon": 5 }, +{ "label": "48/18", "node": 4052, "naklon": 5 }, +{ "label": "48/19", "node": 4042, "naklon": 5 }, +{ "label": "48/20", "node": 4053, "naklon": 5 }, +{ "label": "50/15A", "node": 4167, "naklon": null }, +{ "label": "50/15B", "node": 4159, "naklon": null }, +{ "label": "50/1", "node": 4183, "naklon": 0 }, +{ "label": "50/2", "node": 4157, "naklon": 0 }, +{ "label": "50/3", "node": 4160, "naklon": 0 }, +{ "label": "50/4", "node": 4173, "naklon": 0 }, +{ "label": "50/5", "node": 4177, "naklon": 0 }, +{ "label": "50/6", "node": 4174, "naklon": 0 }, +{ "label": "50/7", "node": 4178, "naklon": 0 }, +{ "label": "50/8", "node": 4195, "naklon": 0 }, +{ "label": "50/9", "node": 4169, "naklon": 0 }, +{ "label": "50/10", "node": 4162, "naklon": 0 }, +{ "label": "50/11", "node": 4158, "naklon": 0 }, +{ "label": "50/12", "node": 4182, "naklon": 0 }, +{ "label": "50/13", "node": 4194, "naklon": 0 }, +{ "label": "50/14", "node": 4184, "naklon": 0 }, +{ "label": "50/16", "node": 4197, "naklon": null }, +{ "label": "50/17", "node": 4164, "naklon": null }, +{ "label": "50/18", "node": 3306, "naklon": null }, +{ "label": "50/19", "node": 4168, "naklon": null }, +{ "label": "50/20", "node": 4193, "naklon": null }, +{ "label": "50/21", "node": 4187, "naklon": null }, +{ "label": "50/22", "node": 4163, "naklon": null }, +{ "label": "50/23", "node": 4165, "naklon": null }, +{ "label": "50/24", "node": 4185, "naklon": null }, +{ "label": "50/25", "node": 3904, "naklon": null }, +{ "label": "53/1", "node": 2619, "naklon": 0 }, +{ "label": "53/2", "node": 2623, "naklon": 0 }, +{ "label": "53/3", "node": 2617, "naklon": 0 }, +{ "label": "53/4", "node": 2622, "naklon": 0 }, +{ "label": "53/5", "node": 2618, "naklon": 0 }, +{ "label": "53/6", "node": 2626, "naklon": 0 }, +{ "label": "53/7", "node": 2869, "naklon": 0 }, +{ "label": "53/8", "node": 2613, "naklon": 0 }, +{ "label": "53/9", "node": 2608, "naklon": 0 }, +{ "label": "53/10", "node": 2611, "naklon": 0 }, +{ "label": "53/11", "node": 2598, "naklon": 0 }, +{ "label": "53/12", "node": 3528, "naklon": 0 }, +{ "label": "53/13", "node": 3545, "naklon": 0 }, +{ "label": "53/14", "node": 2620, "naklon": 0 }, +{ "label": "53/15", "node": 2612, "naklon": 0 }, +{ "label": "53/16", "node": 2615, "naklon": 0 }, +{ "label": "53/17", "node": 3722, "naklon": 0 }, +{ "label": "53/18", "node": 2624, "naklon": 0 }, +{ "label": "53/19", "node": 2609, "naklon": 0 }, +{ "label": "53/20", "node": 2625, "naklon": 0 }, +{ "label": "53/21", "node": 2602, "naklon": 0 }, +{ "label": "53/22", "node": 2610, "naklon": 0 }, +{ "label": "53/23", "node": 2599, "naklon": 0 }, +{ "label": "53/24", "node": 2605, "naklon": 0 }, +{ "label": "53/25", "node": 2593, "naklon": 0 }, +{ "label": "53/26", "node": 3074, "naklon": 0 }, +{ "label": "53/27", "node": 2740, "naklon": 0 }, +{ "label": "53/28", "node": 2614, "naklon": 0 }, +{ "label": "53/29", "node": 2601, "naklon": 0 }, +{ "label": "53/30", "node": 4196, "naklon": 0 }, +{ "label": "53/31", "node": 2607, "naklon": 0 }, +{ "label": "53/32", "node": 2582, "naklon": 0 }, +{ "label": "53/33", "node": 2594, "naklon": 0 }, +{ "label": "53/34", "node": 2589, "naklon": 0 }, +{ "label": "53/35", "node": 2596, "naklon": 0 }, +{ "label": "53/36", "node": 2603, "naklon": 0 }, +{ "label": "53/37", "node": 2597, "naklon": 0 }, +{ "label": "53/38", "node": 2590, "naklon": 0 }, +{ "label": "53/39", "node": 2581, "naklon": 0 }, +{ "label": "53/40", "node": 2583, "naklon": 0 }, +{ "label": "53/41", "node": 2580, "naklon": 0 }, +{ "label": "53/42", "node": 2579, "naklon": 0 }, +{ "label": "53/43", "node": 2797, "naklon": 0 }, +{ "label": "53/44", "node": 2577, "naklon": 0 }, +{ "label": "53/45", "node": 2586, "naklon": 0 }, +{ "label": "53/46", "node": 2588, "naklon": 0 }, +{ "label": "53/47", "node": 2591, "naklon": 0 }, +{ "label": "53/48", "node": 2592, "naklon": 0 }, +{ "label": "53/49", "node": 2573, "naklon": 0 }, +{ "label": "53/50", "node": 2595, "naklon": 0 }, +{ "label": "53/51", "node": 2587, "naklon": 0 }, +{ "label": "53/52", "node": 2578, "naklon": 0 }, +{ "label": "53/53", "node": 2574, "naklon": 0 }, +{ "label": "53/54", "node": 2571, "naklon": 0 }, +{ "label": "53/55", "node": 2570, "naklon": 0 }, +{ "label": "53/56", "node": 2576, "naklon": 0 }, +{ "label": "53/57", "node": 2881, "naklon": 0 }, +{ "label": "53/58", "node": 2575, "naklon": 0 }, +{ "label": "53/59", "node": 2572, "naklon": 0 }, +{ "label": "53/60", "node": 2569, "naklon": 0 }, +{ "label": "55/1", "node": 4324, "naklon": 0 }, +{ "label": "55/2", "node": 4319, "naklon": 0 }, +{ "label": "55/3", "node": 4327, "naklon": 0 }, +{ "label": "55/4", "node": 4333, "naklon": 0 }, +{ "label": "55/5", "node": 4332, "naklon": 0 }, +{ "label": "55/6", "node": 4320, "naklon": 0 }, +{ "label": "55/7", "node": 4317, "naklon": 0 }, +{ "label": "55/8", "node": 4318, "naklon": 0 }, +{ "label": "55/9", "node": 4328, "naklon": 0 }, +{ "label": "55/10", "node": 4323, "naklon": 0 }, +{ "label": "55/11", "node": 4325, "naklon": 0 }, +{ "label": "55/12", "node": 4326, "naklon": 0 }, +{ "label": "55/13", "node": 4316, "naklon": 0 }, +{ "label": "55/14", "node": 4322, "naklon": 0 }, +{ "label": "55/15", "node": 4331, "naklon": 0 }, +{ "label": "55/16", "node": 4321, "naklon": 0 }, +{ "label": "55/17", "node": 4315, "naklon": 0 }, +{ "label": "55/18", "node": 4329, "naklon": 0 }, +{ "label": "55/19", "node": 4334, "naklon": 0 }, +{ "label": "55/20", "node": 4330, "naklon": 0 } +]; + +module.exports = { naklony }; diff --git a/RVO20/databases/modbus_config.js b/RVO20/databases/modbus_config.js new file mode 100755 index 0000000..b73116a --- /dev/null +++ b/RVO20/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/RVO20/databases/nodes.table b/RVO20/databases/nodes.table new file mode 100755 index 0000000..0500aa5 --- /dev/null +++ b/RVO20/databases/nodes.table @@ -0,0 +1,66 @@ +node:number|pole_number:string|node_type:string|tbname:string|line:number|profile:string|processed:boolean|status:boolean|time_of_last_communication:number ++|3129|34|NEMA|g9OxBZ5KRwNznlY6pApp9GAWXvjdEL4eGQobMDy2|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760574224291|............. ++|3130|61|NEMA|roKgWqY95V3mXMRzyAjK6r0bLjexpJPvaGDBw826|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573924055|............. ++|3172|30A|NEMA|o9vbeQlLMVg8j5dq4keL560NxZpEmnXzwYKO1ar2|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573959528|............. ++|3131|33|NEMA|6lQGaY9RDywdVzObj0Pa8DkPg4NBn3exEK51LWZq|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573712406|............. ++|3132|37|NEMA|JX1ObgmqGZ54DMyYL7aDZKkEVdve38WKRzwjNrQ9|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573930287|............. ++|3133|49|NEMA|B5EoxeMVp4zwr8nqW0GBmvARjvD1PNamOGbLg63Z|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573932652|............. ++|3138|38|NEMA|RvmwNz8QPblKp41GD7lKynkJrLVYoBO92dMegn6W|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573933307|............. ++|3173|31|NEMA|2O14VBzl8aDmWdNw3A59xmAGyZ5qLJoEMpj6R9ng|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573962532|............. ++|3163|25|NEMA|WlVJBygjDZMeKX3vnAMR6908NqdmG2x1Y69LQ4P5|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573687783|............. ++|3164|30B|NEMA|gP1eOZVj3Q9lv5aDEk45pR7rdpqW8yLm2BbKzJxM|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573712805|............. ++|3395|47|NEMA|K94XLav1glVRnyQ6r01PpRAme3YJwBxM5oOzdP2j|1|{"intervals":[{"cct":3000,"value":70,"end_time":"13:00","start_time":"13:00"}],"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|1760573907246|............. ++|3166|60|NEMA|E6Kg9oDnLWyzPRMva7v5GwkJxp4VG58qO2w1lZYe|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573951107|............. ++|3167|46|NEMA|gRoJEyXVx4qD9er287L4BL7wBzGldaPjLWQKm3Mv|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573869345|............. ++|3168|58|NEMA|52dD6ZlV1QaOpRBmbAqGyrkKnGzWMLj4eJq38Pgo|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573870064|............. ++|3244|11|NEMA|eod9aRWLVl34Gx1Dn7VNmy72rz6qjgmpEXwQJN5Z|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573861292|............. ++|3169|51|NEMA|ZmRwd93QL4gaezxEbAx2yek1prn2XjlPvGyqJ6BO|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573872700|............. ++|3170|57|NEMA|PLBJzmK1r3Gynd6OW0gKym0e5wV4vx9bDEqNgYR8|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573874474|............. ++|3171|27|NEMA|BaY3Xpy1EbKGjLq2O7mayY7rx8owgQz9P4dDJRmN|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573956875|............. ++|3245|14|NEMA|wvKJdZML6mXP4DzWBAXxKpAjxNloa5g23Ve9Y1ry|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573962979|............. ++|3246|3|NEMA|Nzp2OoJlqn6r1ZgvdA3Bqj7abBwP5G4eE3RQmyxD|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573887097|............. ++|3247|1|NEMA|EjgWGnXaLy9opPOz20n4Wm786BlYM3w1deVQvbKr|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573873356|............. ++|3248|54|NEMA|EjgWGnXaLy9opPOz20n4yX786BlYM3w1deVQvbKr|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573885419|............. ++|3249|12|NEMA|3a5oqJN1bgnx4Ol9dk89dz7ByE6jQ8mKDWMpGrLV|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573891635|............. ++|3268|13|NEMA|EjgWGnXaLy9opPOz20n4WX786BlYM3w1deVQvbKr|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573966318|............. ++|3269|67|NEMA|5dBNwRp9graYJxZn409NB6klVov1b2QLPDqGm6XK|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573966702|............. ++|3270|4|NEMA|PLBJzmK1r3Gynd6OW0gKWo0e5wV4vx9bDEqNgYR8|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573912599|............. ++|3272|39|NEMA|RO8rjaBDy21qPQJzW7omyp0pK3xmNleVZg9Ed4Gw|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573913078|............. ++|3273|20|NEMA|roKgWqY95V3mXMRzyAjKyr0bLjexpJPvaGDBw826|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573968811|............. ++|3276|35|NEMA|JzwxZXOvDj1bVrN4nkW5vXA8qdyBl3MRKLpGPgaQ|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573969450|............. ++|3277|41|NEMA|Z5KyJe9nEg1QNbWlX0w4yNkoDjBLdqzR83VGv624|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573921291|............. ++|3278|15|NEMA|Nzp2OoJlqn6r1ZgvdA3Bq57abBwP5G4eE3RQmyxD|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573922649|............. ++|3279|29|NEMA|apKVJBwOyrP35m2lv7KY4V0YXbeWNd64En9GxRqg|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573925989|............. ++|3280|16|NEMA|PLBJzmK1r3Gynd6OW0gKWm0e5wV4vx9bDEqNgYR8|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573931933|............. ++|3281|43|NEMA|PjLblDgRBO6WQqnxmkJ1em0Jv3ewZN4p5a89yKdY|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573932476|............. ++|3282|19|Kamera|E6Kg9oDnLWyzPRMva7v5ywkJxp4VG58qO2w1lZYe|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573974867|............. ++|3283|22|NEMA|XMBbew5z4ELrZa2mRAd34578vPN6gy3DdVYlpKjq|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573945738|............. ++|3284|45|NEMA|d5xjWYMwEJon6rLlK7yEyX7qgV4DaOeNB9ZX3Gzb|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573946058|............. ++|3286|42|NEMA|1JMYvnx2RzKEo4aWQ7DGMQkL8yZV3m9NBePXbrdj|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573894447|............. ++|3287|18|NEMA|rDbQ84xzwgdqEoPm3kbEKZ09anOZY1RXyBv2LVM6|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573894591|............. ++|3288|44|NEMA|dz4ojlpP85JMgDLZWkQJnr7aKYqQexEr62GXRV1y|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573900423|............. ++|3289|24|NEMA|zdQO8GwxDqjRgP4137YVrNANyKlpem2nL65rvVJY|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573953999|............. ++|3290|36|NEMA|OzNMgZ9n43qPbjXmy7zwyXA2DKdYvW5e6pxGRrVa|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573902437|............. ++|3291|40|NEMA|3JjOWdylwgNLzxVab7NaxxkZ2vG64rq8PEB5QmDo|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573902612|............. ++|3292|17|NEMA|52dD6ZlV1QaOpRBmbAqGWrkKnGzWMLj4eJq38Pgo|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573902788|............. ++|3293|8|NEMA|roKgWqY95V3mXMRzyAjKWj0bLjexpJPvaGDBw826|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573904162|............. ++|3294|5|NEMA|52dD6ZlV1QaOpRBmbAqGWMkKnGzWMLj4eJq38Pgo|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573967533|............. ++|3295|10|NEMA|ZmRwd93QL4gaezxEbAx2Xek1prn2XjlPvGyqJ6BO|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573905553|............. ++|3296|2|NEMA|OzNMgZ9n43qPbjXmy7zwRyA2DKdYvW5e6pxGRrVa|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573974500|............. ++|3297|7|NEMA|E6Kg9oDnLWyzPRMva7v58jkJxp4VG58qO2w1lZYe|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573906208|............. ++|3298|6|NEMA|rDbQ84xzwgdqEoPm3kbEWr09anOZY1RXyBv2LVM6|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573906351|............. ++|3299|9|NEMA|nJL5lPMwBx23YpqRe0rpaw7damXvWVbOrD4gNzy8|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573906671|............. ++|3550|63|IP65|XMBbew5z4ELrZa2mRAd3m578vPN6gy3DdVYlpKjq|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573907438|............. ++|3563|62|IP65|nJL5lPMwBx23YpqRe0rpNp7damXvWVbOrD4gNzy8|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573907630|............. ++|3124|48|NEMA|d9x2V5LGYBzXp4mMRAOmVXkPloaqJwnQj6DgrNe3|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573808739|............. ++|3125|59|NEMA|rDbQ84xzwgdqEoPm3kbE9Z09anOZY1RXyBv2LVM6|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573694046|............. ++|3126|26|NEMA|zrR51V2ajQ9ZLygPKkEM9EkYDq38xOJolENBXGnv|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573694238|............. ++|3127|32|NEMA|pE5X8NQPaow6vlOZxk6aV80q42ezGBMyWgDVjR3L|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760574223923|............. ++|3146|52|NEMA|eod9aRWLVl34Gx1Dn7VNby72rz6qjgmpEXwQJN5Z|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573933818|............. ++|3156|55|NEMA|wvKJdZML6mXP4DzWBAXxjpAjxNloa5g23Ve9Y1ry|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760574015165|............. ++|3157|21|NEMA|nJL5lPMwBx23YpqRe0rpyp7damXvWVbOrD4gNzy8|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573936247|............. ++|3158|50|NEMA|aw4eELG2DlPMdn1JW0BM2eAqQXOZRN3xB5yp8VKr|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573938788|............. ++|3159|23|NEMA|gYbDLqlyZVoRerQpB72MpokWJnwM5z24POKa8Exj|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573840600|............. ++|3160|53|NEMA|3a5oqJN1bgnx4Ol9dk89nz7ByE6jQ8mKDWMpGrLV|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573727649|............. ++|3161|56|NEMA|Nzp2OoJlqn6r1ZgvdA3Bo57abBwP5G4eE3RQmyxD|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573941903|............. ++|3162|28|NEMA|DbQY6zyveZRwK5drV0Z8dE7joE4XJM83N9xl2nWq|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573943709|............. diff --git a/RVO20/databases/nodes_original/nodes_original.table b/RVO20/databases/nodes_original/nodes_original.table new file mode 100755 index 0000000..b98e96a --- /dev/null +++ b/RVO20/databases/nodes_original/nodes_original.table @@ -0,0 +1 @@ +[{"3129": "g9OxBZ5KRwNznlY6pApp9GAWXvjdEL4eGQobMDy2"}, {"3130": "roKgWqY95V3mXMRzyAjK6r0bLjexpJPvaGDBw826"}, {"3172": "o9vbeQlLMVg8j5dq4keL560NxZpEmnXzwYKO1ar2"}, {"3131": "6lQGaY9RDywdVzObj0Pa8DkPg4NBn3exEK51LWZq"}, {"3132": "JX1ObgmqGZ54DMyYL7aDZKkEVdve38WKRzwjNrQ9"}, {"3133": "B5EoxeMVp4zwr8nqW0GBmvARjvD1PNamOGbLg63Z"}, {"3138": "RvmwNz8QPblKp41GD7lKynkJrLVYoBO92dMegn6W"}, {"3173": "2O14VBzl8aDmWdNw3A59xmAGyZ5qLJoEMpj6R9ng"}, {"3163": "WlVJBygjDZMeKX3vnAMR6908NqdmG2x1Y69LQ4P5"}, {"3164": "gP1eOZVj3Q9lv5aDEk45pR7rdpqW8yLm2BbKzJxM"}, {"3395": "K94XLav1glVRnyQ6r01PpRAme3YJwBxM5oOzdP2j"}, {"3166": "E6Kg9oDnLWyzPRMva7v5GwkJxp4VG58qO2w1lZYe"}, {"3167": "gRoJEyXVx4qD9er287L4BL7wBzGldaPjLWQKm3Mv"}, {"3168": "52dD6ZlV1QaOpRBmbAqGyrkKnGzWMLj4eJq38Pgo"}, {"3244": "eod9aRWLVl34Gx1Dn7VNmy72rz6qjgmpEXwQJN5Z"}, {"3169": "ZmRwd93QL4gaezxEbAx2yek1prn2XjlPvGyqJ6BO"}, {"3170": "PLBJzmK1r3Gynd6OW0gKym0e5wV4vx9bDEqNgYR8"}, {"3171": "BaY3Xpy1EbKGjLq2O7mayY7rx8owgQz9P4dDJRmN"}, {"3245": "wvKJdZML6mXP4DzWBAXxKpAjxNloa5g23Ve9Y1ry"}, {"3246": "Nzp2OoJlqn6r1ZgvdA3Bqj7abBwP5G4eE3RQmyxD"}, {"3247": "EjgWGnXaLy9opPOz20n4Wm786BlYM3w1deVQvbKr"}, {"3248": "EjgWGnXaLy9opPOz20n4yX786BlYM3w1deVQvbKr"}, {"3249": "3a5oqJN1bgnx4Ol9dk89dz7ByE6jQ8mKDWMpGrLV"}, {"3268": "EjgWGnXaLy9opPOz20n4WX786BlYM3w1deVQvbKr"}, {"3269": "5dBNwRp9graYJxZn409NB6klVov1b2QLPDqGm6XK"}, {"3270": "PLBJzmK1r3Gynd6OW0gKWo0e5wV4vx9bDEqNgYR8"}, {"3272": "RO8rjaBDy21qPQJzW7omyp0pK3xmNleVZg9Ed4Gw"}, {"3273": "roKgWqY95V3mXMRzyAjKyr0bLjexpJPvaGDBw826"}, {"3276": "JzwxZXOvDj1bVrN4nkW5vXA8qdyBl3MRKLpGPgaQ"}, {"3277": "Z5KyJe9nEg1QNbWlX0w4yNkoDjBLdqzR83VGv624"}, {"3278": "Nzp2OoJlqn6r1ZgvdA3Bq57abBwP5G4eE3RQmyxD"}, {"3279": "apKVJBwOyrP35m2lv7KY4V0YXbeWNd64En9GxRqg"}, {"3280": "PLBJzmK1r3Gynd6OW0gKWm0e5wV4vx9bDEqNgYR8"}, {"3281": "PjLblDgRBO6WQqnxmkJ1em0Jv3ewZN4p5a89yKdY"}, {"3282": "E6Kg9oDnLWyzPRMva7v5ywkJxp4VG58qO2w1lZYe"}, {"3283": "XMBbew5z4ELrZa2mRAd34578vPN6gy3DdVYlpKjq"}, {"3284": "d5xjWYMwEJon6rLlK7yEyX7qgV4DaOeNB9ZX3Gzb"}, {"3286": "1JMYvnx2RzKEo4aWQ7DGMQkL8yZV3m9NBePXbrdj"}, {"3287": "rDbQ84xzwgdqEoPm3kbEKZ09anOZY1RXyBv2LVM6"}, {"3288": "dz4ojlpP85JMgDLZWkQJnr7aKYqQexEr62GXRV1y"}, {"3289": "zdQO8GwxDqjRgP4137YVrNANyKlpem2nL65rvVJY"}, {"3290": "OzNMgZ9n43qPbjXmy7zwyXA2DKdYvW5e6pxGRrVa"}, {"3291": "3JjOWdylwgNLzxVab7NaxxkZ2vG64rq8PEB5QmDo"}, {"3292": "52dD6ZlV1QaOpRBmbAqGWrkKnGzWMLj4eJq38Pgo"}, {"3293": "roKgWqY95V3mXMRzyAjKWj0bLjexpJPvaGDBw826"}, {"3294": "52dD6ZlV1QaOpRBmbAqGWMkKnGzWMLj4eJq38Pgo"}, {"3295": "ZmRwd93QL4gaezxEbAx2Xek1prn2XjlPvGyqJ6BO"}, {"3296": "OzNMgZ9n43qPbjXmy7zwRyA2DKdYvW5e6pxGRrVa"}, {"3297": "E6Kg9oDnLWyzPRMva7v58jkJxp4VG58qO2w1lZYe"}, {"3298": "rDbQ84xzwgdqEoPm3kbEWr09anOZY1RXyBv2LVM6"}, {"3299": "nJL5lPMwBx23YpqRe0rpaw7damXvWVbOrD4gNzy8"}, {"3550": "XMBbew5z4ELrZa2mRAd3m578vPN6gy3DdVYlpKjq"}, {"3563": "nJL5lPMwBx23YpqRe0rpNp7damXvWVbOrD4gNzy8"}, {"3124": "d9x2V5LGYBzXp4mMRAOmVXkPloaqJwnQj6DgrNe3"}, {"3125": "rDbQ84xzwgdqEoPm3kbE9Z09anOZY1RXyBv2LVM6"}, {"3126": "zrR51V2ajQ9ZLygPKkEM9EkYDq38xOJolENBXGnv"}, {"3127": "pE5X8NQPaow6vlOZxk6aV80q42ezGBMyWgDVjR3L"}, {"3146": "eod9aRWLVl34Gx1Dn7VNby72rz6qjgmpEXwQJN5Z"}, {"3156": "wvKJdZML6mXP4DzWBAXxjpAjxNloa5g23Ve9Y1ry"}, {"3157": "nJL5lPMwBx23YpqRe0rpyp7damXvWVbOrD4gNzy8"}, {"3158": "aw4eELG2DlPMdn1JW0BM2eAqQXOZRN3xB5yp8VKr"}, {"3159": "gYbDLqlyZVoRerQpB72MpokWJnwM5z24POKa8Exj"}, {"3160": "3a5oqJN1bgnx4Ol9dk89nz7ByE6jQ8mKDWMpGrLV"}, {"3161": "Nzp2OoJlqn6r1ZgvdA3Bo57abBwP5G4eE3RQmyxD"}, {"3162": "DbQY6zyveZRwK5drV0Z8dE7joE4XJM83N9xl2nWq"}] \ No newline at end of file diff --git a/RVO20/databases/notifications.table b/RVO20/databases/notifications.table new file mode 100755 index 0000000..f7c96cb --- /dev/null +++ b/RVO20/databases/notifications.table @@ -0,0 +1,41 @@ +key:string|weight:string|sk:string|en:string ++|switching_profile_point_applied_to_line|INFORMATIONAL|Aplikovaný bod spínacieho profilu na línií č. ${line} : ${value}|Switching profile point applied to line no. ${line} : ${value}|............... ++|dusk_has_occured|INFORMATIONAL|Nastal súmrak: ${value}|Dusk has occured: ${value}|............... ++|dawn_has_occured|INFORMATIONAL|Nastal úsvit: ${value}|Dawn has occured: ${value}|............... ++|dimming_profile_was_successfully_received_by_node|NOTICE|Stmievací profil bol úspešne prijatý nodom č. ${node}|Dimming profile was successfully received by node no. ${node}|............... ++|master_node_is_responding_again|NOTICE|Master node začal znovu odpovedať|Master node is responding again|............... ++|command_was_sent_from_terminal_interface|DEBUG|Z terminálu bol odoslaný príkaz|A command was sent from terminal interface|............... ++|master_node_is_not_responding|ALERT|Master node neodpovedá|Master node is not responding|............... ++|configuration_of_dimming_profile_to_node_failed|ALERT|Konfigurácia stmievacieho profilu pre node č. ${node} zlyhala|Configuration of dimming profile to node no. ${node} has failed|............... ++|circuit_breaker_was_turned_on_line|NOTICE|Zapnutie ističa na línii č. ${line}|Circuit breaker was turned on - line no. ${line}|............... ++|circuit_breaker_was_turned_off_line|ERROR|Vypnutie ističa na línií č. ${line}|Circuit breaker was turned off - line no. ${line}|............... ++|dimming_profile_was_processed_for_node|INFORMATIONAL|Stmievací profil bol spracovaný pre node č. ${node}|Dimming profile was processed for node no. ${node}|............... ++|switching_profile_was_processed_for_line|INFORMATIONAL|Spínací profil bol spracovaný pre líniu č. ${line}|Switching profile was processed for line no. ${line}|............... ++|thermometer_is_not_responding|WARNING|Teplomer neodpovedá|Thermometer is not responding|............... ++|thermometer_is_responding_again|NOTICE|Teplomer znovu odpovedá|Thermometer is responding again|............... ++|thermometer_sends_invalid_data|WARNING|Teplomer posiela neplatné hodnoty|Thermometer sends invalid data|............... ++|main_switch_has_been_turned_off|CRITICAL|Hlavný vypínač bol vypnutý|Main switch has been turned off|............... ++|main_switch_has_been_turned_on|NOTICE|Hlavný vypínač bol zapnutý|Main switch has been turned on|............... ++|power_supply_has_disconnected_input|ALERT|Napájací zdroj nemá napätie na vstupe|Power supply has disconnected input|............... ++|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_main_open|NOTICE|Hlavné dvere boli otvorené|Main door has been opened|............... ++|door_em_open|NOTICE|Dvere silovej časti boli otvorené|Power door has been opened|............... ++|door_main_open_without_permission|WARNING|Hlavné dvere boli otvorené bez povolenia - zapnutá siréna|Main door has been opened without permission - alarm is on|............... ++|door_em_open_without_permission|WARNING|Dvere silovej časti boli otvorené bez povolenia|Power door has been opened without permission|............... ++|door_main_close|NOTICE|Hlavné dvere boli zatvorené|Main door has been closed|............... ++|door_em_close|NOTICE|Dvere silovej časti boli zatvorené|Power door has been closed|............... ++|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|............... ++|electrometer_ok|NOTICE|Elektromer znovu odpovedá|Electrometer is responding again|............... ++|no_voltage_on_phase|CRITICAL|Na fáze č. ${phase} nie je napätie|No voltage detected on phase no. ${phase}|............... ++|voltage_on_phase_restored|NOTICE|Napätie na fáze č. ${phase} bolo obnovené|Voltage on phase no. ${phase} has been restored|............... ++|flow_start|NOTICE|FLOW bol spustený|FLOW has been started |............... ++|twilight_sensor_nok|ERROR|Sensor súmraku neodpovedá|Twilight sensor is not responding|............... ++|twilight_sensor_ok|NOTICE|Sensor súmraku znovu odpovedá|Twilight sensor is responding again|............... ++|lamps_have_turned_on|NOTICE|Lampy sa zapli|Lamps have turned on|............... ++|lamps_have_turned_off|NOTICE|Lampy sa vypli|Lamps have turned off|............... ++|flow_restart|NOTICE|FLOW bol reštartovaný|FLOW has been restarted|............... ++|nodes_db_changed|NOTICE|Zmena v node databáze|Node db has changed|............... diff --git a/RVO20/databases/pins.table b/RVO20/databases/pins.table new file mode 100755 index 0000000..0eb3d05 --- /dev/null +++ b/RVO20/databases/pins.table @@ -0,0 +1,14 @@ +pin:string|type:string|line:number +*|input1_01|door_condition|0|........... +*|input1_02|rotary_switch_state|0|........... +*|input1_03|rotary_switch_state|0|........... +*|input1_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/RVO20/databases/relays.table b/RVO20/databases/relays.table new file mode 100755 index 0000000..ff32e00 --- /dev/null +++ b/RVO20/databases/relays.table @@ -0,0 +1,5 @@ +line:number|tbname:string|contactor:number|profile:string ++|0|JX1ObgmqGZ54DMyYL7aDRmkEVdve38WKRzwjNrQ9|1||........... ++|3|3JjOWdylwgNLzxVab7NaZKkZ2vG64rq8PEB5QmDo|9|{"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}|.......................................................................................................................................................................................................................................................................................................................................................................................................................................... ++|1|RvmwNz8QPblKp41GD7lKnZkJrLVYoBO92dMegn6W|9|{"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|RO8rjaBDy21qPQJzW7omgO0pK3xmNleVZg9Ed4Gw|9|{"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}|....................................................................................................................................................................................................................................................................................................................................................................................... diff --git a/RVO20/databases/settings.table b/RVO20/databases/settings.table new file mode 100755 index 0000000..4b602d8 --- /dev/null +++ b/RVO20/databases/settings.table @@ -0,0 +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|project_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|cloud_topic:string|has_main_switch:boolean|daily_report:boolean|send_changed_node_numbers:boolean ++|rvo_senica_20_ip113|en|28.52309C0E0000|48.70826502|17.28455203|192.168.252.1|rvo_senica_20_ip113|LRNIDo9JxKXbm5ANY9tS|1883|0|55|unipi|ttyUSB0|1|20|5|6|3|u113|0|1|1|................................................... diff --git a/RVO20/databases/tbdata.nosql b/RVO20/databases/tbdata.nosql new file mode 100755 index 0000000..e7ed6bd --- /dev/null +++ b/RVO20/databases/tbdata.nosql @@ -0,0 +1,4 @@ +-"JX1ObgmqGZ54DMyYL7aDRmkEVdve38WKRzwjNrQ9":[{"ts":1760534853428,"values":{"_event":{"type":"notice","status":"new","source":{"func":"modbus_reader","component":"1699965957410","component_name":"Modbus reader","edge":"JX1ObgmqGZ54DMyYL7aDRmkEVdve38WKRzwjNrQ9"},"message":{"sk":"rvo_senica_20_ip113: FLOW bol reštartovaný","en":"rvo_senica_20_ip113: FLOW has been restarted"},"message_data":""}}}],"id":"3000387001uh71b"} +-"JX1ObgmqGZ54DMyYL7aDRmkEVdve38WKRzwjNrQ9":[{"ts":1760534853523,"values":{"edge_fw_version":"2025-10-08","maintenance_mode":false}}],"id":"3000387002uh70b"} +-"JX1ObgmqGZ54DMyYL7aDRmkEVdve38WKRzwjNrQ9":[{"ts":1760534853538,"values":{"statecode":2,"power_mode":"Automatic"}}],"id":"3000387004uh70b"} +-"JX1ObgmqGZ54DMyYL7aDRmkEVdve38WKRzwjNrQ9":[{"ts":1760534853581,"values":{"_event":{"type":"notice","status":"new","source":{"func":"rsPort.open()","component":"1699963668903","component_name":"DIDO_Controller","edge":"JX1ObgmqGZ54DMyYL7aDRmkEVdve38WKRzwjNrQ9"},"message":{"sk":"rvo_senica_20_ip113: FLOW bol spustený","en":"rvo_senica_20_ip113: FLOW has been started "},"message_data":""}}}],"id":"3000387006uh70b"} diff --git a/RVO20/databases/tbdatacloud.nosql b/RVO20/databases/tbdatacloud.nosql new file mode 100755 index 0000000..b04520e --- /dev/null +++ b/RVO20/databases/tbdatacloud.nosql @@ -0,0 +1,3 @@ +-"JX1ObgmqGZ54DMyYL7aDRmkEVdve38WKRzwjNrQ9":[{"ts":1760534853523,"values":{"edge_fw_version":"2025-10-08","maintenance_mode":false}}],"id":"3000387003uh71b"} +-"JX1ObgmqGZ54DMyYL7aDRmkEVdve38WKRzwjNrQ9":[{"ts":1760534853538,"values":{"statecode":2,"power_mode":"Automatic"}}],"id":"3000387005uh71b"} +-"JX1ObgmqGZ54DMyYL7aDRmkEVdve38WKRzwjNrQ9":[{"ts":1760534853581,"values":{"_event":{"type":"notice","status":"new","source":{"func":"rsPort.open()","component":"1699963668903","component_name":"DIDO_Controller","edge":"JX1ObgmqGZ54DMyYL7aDRmkEVdve38WKRzwjNrQ9"},"message":{"sk":"rvo_senica_20_ip113: FLOW bol spustený","en":"rvo_senica_20_ip113: FLOW has been started "},"message_data":""}}}],"id":"3000387007uh71b"} diff --git a/RVO20/databases/total_energy.js b/RVO20/databases/total_energy.js new file mode 100755 index 0000000..dde340e --- /dev/null +++ b/RVO20/databases/total_energy.js @@ -0,0 +1,38 @@ +//key is rvo_number, value is max energy when lamps are on +const total_energy = { + 1: 580, + 2: 1100, + 3: 3700, + 4: 4100, + 7: 360, + 12: 1700, + 13: 5400, + 14: 440, + 15: 6100, + 16: 4800, + 20: 1600, + 21: 1000, + 22: 2600, + 23: 1000, + 25: 2600, + 33: 240, + 34: 4000, + 35: 2700, + 36: 820, + 37: 1400, + 35: 3500, + 39: 1170, + 41: 740, + 42: 660, + 43: 4900, + 45: 930, + 46: 700, + 47: 1100, + 48: 1500, + 50: 3200, + 53: 1250, + 55: 1000, + 56: 5500 +} + +module.exports = total_energy; diff --git a/RVO20/debug.js b/RVO20/debug.js new file mode 100755 index 0000000..9818194 --- /dev/null +++ b/RVO20/debug.js @@ -0,0 +1,16 @@ +// =================================================== +// FOR DEVELOPMENT +// Total.js - framework for Node.js platform +// https://www.totaljs.com +// =================================================== + +const options = {}; + +// options.ip = '127.0.0.1'; +// options.port = parseInt(process.argv[2]); +// options.config = { name: 'Total.js' }; +// options.sleep = 3000; +// options.inspector = 9229; +// options.watch = ['private']; + +require('total.js/debug')(options); \ No newline at end of file diff --git a/RVO20/err.txt b/RVO20/err.txt new file mode 100755 index 0000000..23f9f4f --- /dev/null +++ b/RVO20/err.txt @@ -0,0 +1,43 @@ +[2024-10-27T10:59:31.474] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T11:29:37.671] [ERROR] errLogs - checkFinalRVOStatus: value is 0 door_condition +[2024-10-27T11:59:43.889] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T12:29:50.084] [ERROR] errLogs - checkFinalRVOStatus: value is 0 door_condition +[2024-10-27T12:59:56.348] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T13:30:02.563] [ERROR] errLogs - checkFinalRVOStatus: value is 0 door_condition +[2024-10-27T14:05:09.807] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T14:30:14.935] [ERROR] errLogs - checkFinalRVOStatus: value is 0 door_condition +[2024-10-27T15:05:22.193] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T15:32:57.904] [ERROR] errLogs - checkFinalRVOStatus: value is 0 door_condition +[2025-09-23T14:07:13.453] [ERROR] errLogs - uncaughtException: Cannot read property 'getHours' of undefined +[2025-09-23T14:07:13.457] [ERROR] errLogs - TypeError: Cannot read property 'getHours' of undefined + at Timeout.emptyReportToSend [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:07:13.458] [ERROR] errLogs - uncaughtException: Cannot read property 'getHours' of undefined +[2025-09-23T14:07:13.459] [ERROR] errLogs - TypeError: Cannot read property 'getHours' of undefined + at Timeout.emptyReportToSend [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:07:13.472] [ERROR] errLogs - uncaughtException: Cannot read property 'getHours' of undefined +[2025-09-23T14:07:13.472] [ERROR] errLogs - TypeError: Cannot read property 'getHours' of undefined + at Timeout.emptyReportToSend [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:07:19.212] [ERROR] errLogs - uncaughtException: date.getHours is not a function +[2025-09-23T14:07:19.213] [ERROR] errLogs - TypeError: date.getHours is not a function + at emptyReportToSend (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at Timeout.dailyReportCheck [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1351:5) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:07:19.214] [ERROR] errLogs - uncaughtException: date.getHours is not a function +[2025-09-23T14:07:19.214] [ERROR] errLogs - TypeError: date.getHours is not a function + at emptyReportToSend (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at Timeout.dailyReportCheck [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1351:5) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:07:19.220] [ERROR] errLogs - uncaughtException: date.getHours is not a function +[2025-09-23T14:07:19.221] [ERROR] errLogs - TypeError: date.getHours is not a function + at emptyReportToSend (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at Timeout.dailyReportCheck [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1351:5) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) diff --git a/RVO20/flow/cloudmqttconnect.js b/RVO20/flow/cloudmqttconnect.js new file mode 100755 index 0000000..b03491f --- /dev/null +++ b/RVO20/flow/cloudmqttconnect.js @@ -0,0 +1,357 @@ +exports.id = 'cloudmqttconnect'; +exports.title = 'Cloud connect mqtt'; +exports.group = 'MQTT'; +exports.color = '#888600'; +exports.version = '1.0.2'; +exports.icon = 'sign-out'; +exports.input = 2; +exports.output = 2; +exports.options = { host: 'tb-stage.worksys.io', port: 1883, clientid: "", username: "" }; + +exports.html = `
+
+
+
Hostname or IP address (if not empty - setting will override db setting)
+
+
+
Port
+
+
+
+
+
@(Client id)
+
+
+
topic
+
+
+
`; + + + +const { promisifyBuilder } = require('./helper/db_helper'); +const fs = require('fs'); +const mqtt = require('mqtt'); +const nosql = NOSQL('tbdatacloud'); + +const SEND_TO = { + debug: 0, + rpcCall: 1, +} + +//CONFIG +let saveTelemetryOnError = true;//backup_on_failure overrides this value +//------------------------ + +const noSqlFileSizeLimit = 4194304;//use 5MB - 4194304 +let insertNoSqlCounter = 0; +let insertBackupNoSqlCounter = 0; +let processingData = false; + +let backup_on_failure = true;//== saveTelemetryOnError - create backup client send failure +let restore_from_backup = 50; //how many rows process at once? +let restore_backup_wait = 3;//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; + + +exports.install = function(instance) { + + var client; + var opts; + var clientReady = false; + + let o = {}; //options + + function main() { + loadSettings(); + } + + //set opts according to db settings + function loadSettings() { + + o = instance.options; + if (!o.topic) o.topic = FLOW.GLOBALS.settings.cloud_topic; + + opts = { + host: o.host, + port: o.port, + clientId: o.clientid, + username: o.username, + rejectUnauthorized: false, + resubscribe: false + }; + + console.log("wsmqttpublich -> loadSettings from instance.options", o); + + if (!o.topic) { + instance.status("Not configured", "white"); + console.log("Cloud mqtt connect: no topic selected"); + return; + } + + connectToTbServer(); + } + + function connectToTbServer() { + var url = "mqtt://" + opts.host + ":" + opts.port; + console.log("MQTT URL: ", url); + + client = mqtt.connect(url, opts); + + client.on('connect', function() { + client.subscribe(`${o.topic}_backward`, (err) => { + if (!err) { + console.log("MQTT subscribed"); + } + }); + instance.status("Connected", "green"); + clientReady = true; + sendClientError = true; + }); + + client.on('reconnect', function() { + instance.status("Reconnecting", "yellow"); + clientReady = false; + }); + + client.on('message', function(topic, message) { + // message is type of buffer + message = message.toString(); + if (message[0] === '{') { + TRY(function() { + + message = JSON.parse(message); + if (message.hasOwnProperty("device") && message.hasOwnProperty("data") && message.data.hasOwnProperty("id")) { + client.publish(`${o.topic}_forward`, `{"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 } }); + } + + }, () => instance.debug('MQTT: Error parsing data', message)); + } + + instance.send(SEND_TO.rpcCall, { "topic": o.topic, "content": message }); + }); + + client.on('close', function() { + clientReady = false; + + instance.status("Disconnected", "red"); + instance.send(SEND_TO.debug, { "message": "Client CLOSE signal received !" }); + }); + + client.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) { + console.log('MQTT client error', err); + sendClientError = false; + } + clientReady = false; + }); + + } + + + instance.on('0', function(data) { + + if (clientReady) { + //do we have some data in backup file? if any, process data from database + if (saveTelemetryOnError) { + //read telemetry data and send back to server + if (!processingData) processDataFromDatabase(); + } + + let stringifiedJson = JSON.stringify(data.data) + client.publish(`${o.topic}_forward`, stringifiedJson, { qos: 1 }); + } + 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 (saveTelemetryOnError && o.topic) { + //create new file from tbdata.nosql, if file size exceeds given limit, and clear tbdata.nosql + makeBackupFromDbFile(); + + //write to tb + data.data.id = UID(); + nosql.insert(data.data); + } + } + }); + + instance.on("1", _ => { + main(); + }) + + instance.close = function(done) { + if (clientReady) { + client.end(); + } + }; + + + function getDbBackupFileCounter(type) { + var files = fs.readdirSync(__dirname + "/../databases"); + + let counter = 0; + for (var i = 0; i < files.length; i++) { + + if (files[i] == "tbdatacloud.nosql") continue; + + if (files[i].endsWith(".nosql")) { + + let pos = files[i].indexOf("."); + if (pos > -1) { + + let fileCounter = counter; + let firstDigit = files[i].slice(0, pos); + + fileCounter = parseInt(firstDigit); + if (isNaN(fileCounter)) fileCounter = 0; + //console.log("getDbBackupFileCounter digit:", files[i], firstDigit, fileCounter, isNaN(fileCounter), type); + + if (type == "max") { + if (fileCounter > counter) { + counter = fileCounter; + } + } + else if (type == "min") { + if (counter == 0) counter = fileCounter; + + if (fileCounter < counter) { + counter = fileCounter; + } + } + } + } + + } + + if (type == "max") counter++; + + return counter; + } + + const makeBackupFromDbFile = async () => { + + if (!saveTelemetryOnError) return; + + //to avoid large file: tbdata.nosql + + //init value is 0! + if (insertNoSqlCounter > 0) { + --insertNoSqlCounter; + return; + } + + insertNoSqlCounter = 100; + + let source = __dirname + "/../databases/tbdatacloud.nosql"; + + var stats = fs.statSync(source); + var fileSizeInBytes = stats.size; + + if (fileSizeInBytes > noSqlFileSizeLimit) { + + let counter = 1; + counter = getDbBackupFileCounter("max"); + + let destination = __dirname + "/../databases/" + counter + "." + "tbdatacloud.nosql"; + + //make backup file + fs.copyFileSync(source, destination); + //fs.renameSync(p, p + "." + counter); + + //clear tbdata.nosql + fs.writeFileSync(source, ""); + fs.truncateSync(source, 0); + + } + } + + const processDataFromDatabase = async () => { + + if (restore_from_backup <= 0) return; + + //calculate diff + const now = new Date(); + let currentTime = now.getTime(); + let diff = currentTime - lastRestoreTime; + + if ((diff / 1000) < restore_backup_wait) { + //console.log("*********restore_backup_wait", diff, restore_backup_wait); + return; + } + + processingData = true; + + //get filename to process + let counter = getDbBackupFileCounter("min"); + + //we have some backup files + let dataBase = 'tbdata'; + + var nosql; + if (counter == 0) dataBase = 'tbdatacloud'; + else dataBase = counter + "." + 'tbdatacloud'; + + nosql = NOSQL(dataBase); + + //select all data - use limit restore_from_backup + let records = await promisifyBuilder(nosql.find().take(restore_from_backup)); + + for (let i = 0; i < records.length; i++) { + if (clientReady) { + + let item = records[i]; + let id = item.id; + + if (id !== undefined) { + //console.log("------------processDataFromDatabase - remove", id, dataBase, i); + + try { + + let message = JSON.parse(JSON.stringify(item)); + delete message.id; + client.publish(`${o.topic}_forward`, JSON.stringify(message), { qos: 1 }); + + //remove from database + await promisifyBuilder(nosql.remove().where("id", id)); + + } catch (error) { + //process error + console.log("processDataFromDatabase", error); + } + + } + + } + else { + processingData = false; + return; + } + } + + if (records.length > 0) { + //clean backup file + if (counter > 0) nosql.clean(); + } + + //no data in db, remove + if (records.length == 0) { + if (counter > 0) nosql.drop(); + } + + const d = new Date(); + lastRestoreTime = d.getTime(); + + processingData = false; + + } + + instance.on('options', main); + +}; diff --git a/RVO20/flow/cmd_manager.js b/RVO20/flow/cmd_manager.js new file mode 100755 index 0000000..25912df --- /dev/null +++ b/RVO20/flow/cmd_manager.js @@ -0,0 +1,3071 @@ +exports.id = 'cmd_manager'; +exports.title = 'CMD Manager'; +exports.group = 'Worksys'; +exports.color = '#5D9CEC'; +exports.version = '0.0.3'; +exports.output = ['red', 'blue', 'yellow', 'blue', 'white', 'green']; +exports.input = 3; +exports.icon = 'cloud-upload'; + +exports.html = ` +
+
+
+
RPC - run RPC calls

+
+
+
@(User)
+
+
+
@(Password)
+
+
+
@(My edge)
+
+
+
+`; +exports.readme = `Manager for CMD calls`; + + +exports.install = function(instance) { + + 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, isEmptyObject, emptyJsObject, writeToFile, addToArrayIfUnique } = require('./helper/utils'); + const bitwise = require('bitwise'); + + var SunCalc = require('./helper/suncalc'); + const DataToTbHandler = require('./helper/DataToTbHandler'); + const errorHandler = require('./helper/ErrorToServiceHandler'); + const { sendNotification } = require('./helper/notification_reporter'); + const process = require('process'); + const { errLogger, logger, monitor } = require('./helper/logger'); + + //for accelerometer purposes + const { naklony } = require("../databases/accelerometer_db"); + + const dbNodes = TABLE("nodes"); + const dbRelays = TABLE("relays"); + + let GLOBALS; + let SETTINGS; + let rsPort; + let tbHandler; + + // runTasks intervals + const SHORT_INTERVAL = 30; + const LONG_INTERVAL = 300; + + //send data to following instances: + const SEND_TO = { + debug: 0, + tb: 1, + http_response: 2, + dido_controller: 3, + infoSender: 4, + dailyReport: 5 + } + + 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 + } + + 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 sendNodeReadout = null; // interval for sending agregate data from node + + 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["1"] = minutes; // dimming + priorities["76"] = minutes; // power + + minutes = 5; + priorities["75"] = minutes; // current + priorities["79"] = minutes; // energy + priorities["87"] = minutes; // aktualny cas + //priorities["84"] = minutes; //accelerometer + + minutes = 10; + priorities["74"] = minutes; // voltage + priorities["77"] = minutes; // power factor + priorities["78"] = minutes; // frequency + + minutes = 60; + priorities["0"] = minutes; // statecode + priorities["6"] = minutes; // dusk + priorities["7"] = minutes; // dawn + priorities["8"] = minutes; // profile + + minutes = 60 * 24; + priorities["89"] = minutes; // verzia fw + priorities["80"] = minutes; // lifetime + + //prikazy kt sa budu spustat na dany node - see config.js in terminal-oms.app. (1 - dimming) + let listOfCommands = [0, 1, 6, 7, 8, 74, 75, 76, 77, 78, 79, 80, 87, 89]; + + 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; + + // holds dusk, dawn (and more) values + let sunCalcResult; + + //helper container for counting resolved group of commands (commands related to set profile) + let cmdCounter = {};//key is node, value is counter + + //TODO: is this set working?? According to previous checks, sets do not work + //if sending of profile to node fails, we send notification and push node into set, so we do not send notification twice + const nodeProfileSendFail = new Set(); + + //we expect to get current temperature in Senica from senica-prod01 + let temperatureInSenica = null; + let accelerometerInterval = null; + + //NOTE: daily reports senica: + //rvo_is_on status, we monitor all nodes - if true, power and dimming should be not 0, if false, 24/7 nodes should be 0, other rvo should not respond + let rvo_is_on; + let previous_rvo_is_on_value; + let handleDailyReport; //setInterval for dailyReportHandler function + let dailyReport = {}; //data needed for daily report + let reportToSend = {}; //final report which we send to cloud + let breakerCounter = null; // status of breakers after flow starts is not in report + let rvoPeriod; // interval of checking dusk dawn and if rvo_is_on + let initialReportStatus = false; + + const DAILY_REPORT_HANDLER_TIME = 3_600_000; + const SET_SUNCALC_RESULT_TIME = 3_600_000; + const SET_RVO_PERIOD_TIME = 300_000; + const ADD_NODE_TO_REPORT_TIME = 3_600_000; + + //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); + + let now = new Date(); + console.log("Cmd-mngr installed", now.toLocaleString("sk-SK")); + + sunCalcResult = calculateDuskDawn(); + + handleRsPort(); + + customTasksInterval = setInterval(reportEdgeDateTimeAndNumberOfLuminaires, 120_000); + setTimeout(reportEdgeDateTimeAndNumberOfLuminaires, 4000); + + //dailyReport related + emptyReportToSend(); + breakerCounter = Object.keys(relaysData).length - 1; // we get number of lines (breakers) except of line 0 + rvoPeriod = setInterval(setRvoPeriod, SET_RVO_PERIOD_TIME); + setTimeout(setRvoPeriod, 3000); + setInterval(setSunCalcResult, SET_SUNCALC_RESULT_TIME); + handleDailyReport = setInterval(dailyReportHandler, DAILY_REPORT_HANDLER_TIME); + + + setCorrectTime = setInterval(setCorrectPlcTimeOnceADay, 60000 * 60); // 1 hour + setCorrectPlcTimeOnceADay(); + + sendNodeReadout = setInterval(sendNodesData, 150_000); + accelerometerInterval = setInterval(accelerometerData, 60000 * 30); //30 min + } + + + 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" + //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 + // if node regular readout does not respond, we repeat request + params.repeatCounter = 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-mngr: 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.byte4 = 96; + params.recipient = 1; + params.register = 8; + params.rw = 1;//write + params.timestamp = timestamp; + 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.byte4 = 96; + params.recipient = 1; + params.register = 8; + params.rw = 1;//write + params.timestamp = timestamp; + 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). + */ + + 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.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.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 + { + + logger.debug("processNodeProfile: Threshold lux level for DUSK/DAWN", node); + + let params = getParams(); + params.type = "set_node_profile"; + params.address = node; + params.register = 96; + params.recipient = 1; + params.rw = 1;//write + params.timestamp = timestamp; + 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(); + params.type = "set_node_profile"; + params.address = node; + params.register = 97; + params.recipient = 1; + params.rw = 1;//write + params.timestamp = timestamp; + 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.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); + + 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); + + console.log("proces profile finished *********************") + } + + + 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; + }); + } + + + 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) { + for (let k in nodesData) { + 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`); + } + } + } + + + function loadRelaysData(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 (value.contactor == 1) processAllNodeProfilesOnLine(value.line); + } + } + + + function reportOnlineNodeStatus(line) { + //Po zapnutí línie broadcastovo aktualizovať predtým čas a o 3 sek neskor - status, brightness + + logger.debug("Cmd-mngr: ----->reportOnlineNodeStatus for line", line); + + const d = new Date(); + + // broadcast actual time + let params = getParams(); + params.address = 0xffffffff;//Broadcast + params.byte1 = d.getHours(); + params.byte2 = d.getMinutes(); + params.recipient = 2;//2 broadcast, address = 0 + params.register = 87;//Actual time + params.rw = 1;//write + params.type = "node-onetime-write"; + params.timestamp = d.getTime() + 30000; + params.info = "run broadcast: Actual time"; + //params.debug = true; + + tasks.push(params); + + let sec = 3; + setTimeout(function() { + //Po zapnutí línie - spraviť hromadný refresh stavu práve zapnutých svietidiel + + let time = Date.now(); + + for (let k in nodesData) { + + //potrebujem nody k danej linii + 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].node_status_before_offline === true || nodesData[k].status === true) { + status = "OK"; + nodesData[k].time_of_last_communication = time; + } + + nodesData[k].readout.status = status; + + updateNodeStatus(k, status === "OK" ? true : false); + if (nodesData[k].hasOwnProperty("node_status_before_offline")) delete nodesData[k].node_status_before_offline; + sendTelemetry({ status: status }, tbname, time); + + //vyreportovanie dimming, current, input power pre liniu pre vsetky nody + //Prud + { + let params = getParams(); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 75;//prud + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = time + 4000; + params.info = 'read current'; + //params.debug = true; + tasks.push(params); + } + + //vykon + { + let params = getParams(); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 76;//výkon + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = time + 4100; + params.info = 'read power'; + //params.debug = true; + + tasks.push(params); + } + //dimming + { + let params = getParams(); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 1;//dimming + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = time + 4200; + params.info = 'read dimming'; + //params.debug = true; + + tasks.push(params); + } + + } + } + + }, sec * 1000); + } + + + function reportOfflineNodeStatus(line) { + + logger.info("Cmd-mngr: ------>reportOffLineNodeStatus for line ", line); + + values = {}; + values["dimming"] = 0;//brightness + values["power"] = 0;//výkon + values["current"] = 0;//prúd + values["status"] = "OFFLINE"; + + const date = Date.now(); + + Object.keys(nodesData).forEach(node => { + + //potrebujem nody k danej linii + if (line == nodesData[node].line || line == undefined) { + + let tbname = nodesData[node].tbname; + let nodeStatus = nodesData[node].status; + + //in case we have reported offline node status, we return (continue with next node) + if (nodeStatus === "OFFLINE") return; + + nodesData[node].node_status_before_offline = nodeStatus; + nodesData[node].status = "OFFLINE"; + nodesData[node].readout = {}; + + sendTelemetry({ ...values }, tbname, date); + } + }); + + } + + + function turnLine(onOrOff, line, info) { + let obj = { + line: line, + command: onOrOff, + info: info + }; + + //to assure, handleDailyReportFunction do not run before rvo_is_on variable changes. So after every line switch we reset the timer + clearInterval(handleDailyReport); + handleDailyReport = setInterval(dailyReportHandler, DAILY_REPORT_HANDLER_TIME); + + //logger.debug("linia", line, obj); + instance.send(SEND_TO.dido_controller, obj); + } + + + 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"; + 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]) { + //CRC_ERROR + message = "NOK"; + error = "CRC_ERROR c1"; + instance.send(SEND_TO.debug, "CRC_ERROR c1"); + } + + 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") { + instance.send(SEND_TO.debug, bytes); + instance.send(SEND_TO.debug, "RESPONSE " + type + " - " + bytes[4]); + + //logger.debug(SEND_TO.debug, "RESPONSE " + type + " - " + bytes[4], bytes); + + error = "type is: " + type; + + message = "NOK"; + } + + return { message, type, error }; + } + + + //BUILD TASKS// + function buildTasks(params) { + + //return; + console.log("buidTAaasks start ****************", params); + monitor.info("buildTasks - params", params); + + let processLine; //defined line + let init = false; + let processLineProfiles = true; + let processBroadcast = true; + let processNodes = true; + + if (params == undefined) { + init = true; + tasks = []; + logger.debug("-->buildTasks clear tasks"); + } + else { + processLineProfiles = params.processLineProfiles; + processBroadcast = false; + processNodes = false; + + processLine = params.line; + } + + let now = new Date(); + + //process line profiles + if (processLineProfiles) { + + let keys = Object.keys(relaysData); + + for (let i = 0; i < keys.length; i++) { + + let line = parseInt(keys[i]); + let profilestr = relaysData[line].profile; + + if (processLine != undefined) { + if (processLine != line) continue; + } + + try { + + /** + * we process line profiles: timepoints, astro clock, lux_sensor, offsets ... + */ + if (profilestr === "") throw ("Profile is not defined"); + let profile = JSON.parse(profilestr); + 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; + + // add name to regular profile timepoint and delete unused end_time key: + time_points.forEach(point => { + point.name = "profileTimepoint" + delete point.end_time; + }); + + //monitor.info("buildTasks: time_points", time_points); + + + /** + * 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 astro clock true, we remove all regular profile points + time_points = []; + + //TODO: when astro clock == true, is offset calculated ??? + //let duskAstroClockOffset = profile.dusk_astro_clock_offset; + //let dawnAstroClockOffset = profile.dawn_astro_clock_offset; + //console.log("line astro clock offsets dusk a dawn: ", duskAstroClockOffset, dawnAstroClockOffset); + // maybe add dusk dawn offset to calculateDuskDawn ?? what dusk dawn will be if dawn_lux_sensor == true?? + //let sunCalcResult = calculateDuskDawn(new Date(), line, duskAstroClockOffset, dawnAstroClockOffset); + + 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 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); + + 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); + + 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(':'); + + let ad = new Date(); + ad.setHours(parseInt(ahours), parseInt(aminutes), 0); + + let bd = new Date(); + bd.setHours(parseInt(bhours), parseInt(bminutes), 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++) { + + let start_time = new Date(); + let [hours, minutes] = time_points[t].start_time.split(':'); + start_time.setHours(parseInt(hours), parseInt(minutes), 0); + + //task is in 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(); + params.type = "relay"; + params.line = parseInt(line); + params.value = time_points[t].value; + params.tbname = relaysData[line].tbname; + params.timestamp = start_time.getTime(); + + // 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; + + //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)) { + 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; + + params.debug = true; + + //turn on/off line + tasks.push(params); + monitor.info("TimePoint params: ", params.info, start_time); + } + + monitor.info("-->time_points final", line, time_points); + + //ensure to turn on/off according to calculated currentValue + let params = getParams(); + params.type = "relay"; + params.line = parseInt(line); + params.tbname = relaysData[line].tbname; + params.value = currentValue; + params.timestamp = i; + params.debug = true; + + //logger.debug(now.toLocaleString("sk-SK")); + 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; + + tasks.push(params); + + } catch (error) { + if (profilestr !== "") { + //errLogger.error(profilestr, error); + console.log(`Cmd_mngr: Unable to process line profile ${line}. Error: `, error); + errorHandler.sendMessageToService(profilestr + "-" + error, 0, "js_error"); + } else { + turnLine("off", line, "No line profile. Switching it off on startup"); + } + } + + } + //logger.debug("tasks:"); + //logger.debug(tasks); + } + + + //NOTE: PROCESS DEFAULT BROADCASTS - Time of dusk, Time of dawn, Actual Time + if (processBroadcast) { + + let d = new Date(); + let time = d.getTime(); + //let sunCalcResult = calculateDuskDawn(); + + { + let params = getParams(); + + params.address = 0xffffffff;//broadcast + params.byte1 = sunCalcResult["dusk_hours"]; + params.byte2 = sunCalcResult["dusk_minutes"]; + params.recipient = 2;//2 broadcast, + params.register = 6;//Time of dusk + params.rw = 1;//write + params.type = "node-regular-write"; + params.timestamp = time + 60000; + params.addMinutesToTimestamp = 60 * 3; //kazde 3 hodiny zisti novy dusk + params.info = "Broadcast-duskTime"; + + tasks.push(params); + } + + { + let params = getParams(); + + params.address = 0xffffffff;//broadcast + params.byte1 = sunCalcResult["dawn_hours"]; + params.byte2 = sunCalcResult["dawn_minutes"]; + params.recipient = 2; //2 broadcast + params.register = 7;//Time of dawn + params.rw = 1;//write + params.type = "node-regular-write"; + params.timestamp = time + 60001; + params.addMinutesToTimestamp = 60 * 3; //kazde 3 hodiny zisti novy dawn + params.info = "Broadcast-dawnTime"; + + tasks.push(params); + } + + { + let params = getParams(); + + params.address = 0xffffffff;//broadcast + params.byte1 = d.getHours(); + params.byte2 = d.getMinutes(); + params.recipient = 2; //2 broadcast + params.register = 87;//Actual time + params.rw = 1;//write + params.type = "node-regular-write"; + params.timestamp = time + 60002; + params.addMinutesToTimestamp = 5; + params.info = "run broadcast: Actual time"; + + tasks.push(params); + } + + } + + //process nodes & tasks - read node's data + if (processNodes) { + + let time = Date.now(); + + for (let k in nodesData) { + let address = parseInt(k); + let tbname = nodesData[k].tbname; + let register = 0; + + for (let i = 0; i < listOfCommands.length; i++) { + + register = listOfCommands[i]; + let addMinutesToTimestamp = priorities[register]; + + let params = getParams(); + + params.address = address; + params.recipient = 1; + params.register = register; + params.type = register == 1 ? "node-dimming-read" : "node-regular-read"; + params.tbname = tbname; + params.timestamp = time + 5000 + i * 500 + addMinutesToTimestamp * 1000; //to make slight time difference + params.addMinutesToTimestamp = addMinutesToTimestamp; + params.info = "Node regular read command"; + + tasks.push(params); + } + + } + } + + + //niektore ulohy sa vygeneruju iba 1x pri starte!!! + if (!init) return; + + + //Master node FW version - modifies SETTINGS.masterNodeIsResponding + { + let params = getParams(); + params.type = "cmd-master"; + params.register = 4; + params.address = 0; + params.timestamp = 0; + params.addMinutesToTimestamp = 5; + params.tbname = SETTINGS.rvoTbName; + params.info = "Master node FW verzia"; + //params.debug = true; + + tasks.push(params); + } + + //kazdu hodinu skontrolovat nastavenie profilov + { + let params = getParams(); + params.type = "process_profiles"; + params.timestamp = Date.now() + 60001; + params.addMinutesToTimestamp = 60;//60 = every hour + params.info = "detekcia nespracovaných profilov linie a nodov"; + //params.debug = true; + + tasks.push(params); + } + + monitor.info("tasks created:", tasks.length); + } + + + /** + * We process line profile, where "astro_clock": true + * example profile: + * + "dawn_lux_sensor": true, + "dusk_lux_sensor": true, + "dawn_lux_sensor_value": 5, + "dusk_lux_sensor_value": 5, + "dawn_astro_clock_offset": 0, + "dusk_astro_clock_offset": 10, + "dawn_lux_sensor_time_window": 30, + "dusk_lux_sensor_time_window": 30, + "dawn_astro_clock_time_window": 60, + "dusk_astro_clock_time_window": 60 + + * if dawn: if currentTimestamp is in timewindow "dawnTime + and - dawn_lux_sensor_time_window" and lux value >= lux_sensor_value, we switch off the line. + * if dusk: we do oposite + * + * dawn: usvit - lux je nad hranicou - vypnem + * dusk: sumrak - lux je pod hranicou - zapnem + */ + 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++) { + + let line = keys[i]; //line is turned off by default + let profilestr = relaysData[line].profile; + const contactor = relaysData[line].contactor; + + try { + + let profile = JSON.parse(profilestr); + if (Object.keys(profile).length === 0) throw ("turnOnOffLinesAccordingToLuxSensor - profile is not defined"); + + 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 (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"); + } + } + } + + //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 (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"); + } + } + } + + } + + } catch (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) { + //MASTER + if (node == 0) return; + + let nodeObj = nodesData[node]; + if (nodeObj == undefined) return; + + let nodeCurrentStatus = nodeObj.status; + const now = Date.now(); + + let data = null; + + if (nodeCurrentStatus === "OFFLINE") { + data = { status: newStatus }; + nodeDbStatusModify(node, data); + return; + } + else 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; + } + + } + + + 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 }; + } + }); + }); + } + + + function processDailyReport() { + + const now = Date.now(); + + for (const [key, value] of Object.entries(dailyReport)) { + + if (["name", "time", "dusk_and_dawn"].includes(key)) continue; + + let poleNumber = nodesData[key]["pole_number"]; + let line = dailyReport[key].line; + let nodeType = nodesData[key]["node_type"]; + let fullNodeName = key // key == nodeNumber + + if (poleNumber && nodeType) { + fullNodeName = SETTINGS.rvo_number + "/" + poleNumber + "_" + line + "L_" + key + "_" + nodeType; + } else { + fullNodeName = key; + } + + if (rvo_is_on) { + + if (value.initialTs) { + if (value.initialTs + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["night_no_data"], fullNodeName); + console.log('report nedostava ziadne data uz hodinu', fullNodeName); + value.initialTs = now; + } + } + if (value.dimmingIsZeroTime) { + if (value.dimmingIsZeroTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["night_dimming=0"], fullNodeName); + console.log("report node dimming je 0 ale ma svietit", fullNodeName); + value.dimmingIsZeroTime = now; + } + } + if (value.powerIsZeroTime) { + if (value.powerIsZeroTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["night_power=0"], fullNodeName); + console.log("report node power je 0 ale ma svietit", fullNodeName); + value.powerIsZeroTime = now; + } + } + + } else { + + let contactorStatus = relaysData[line].contactor; + if (contactorStatus === 1) { + + if (value.initialTs) { + if (value.initialTs + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["day_24/7_no_data"], fullNodeName); + console.log('node je na 24/7 ale nedostava ziadne data uz hodinu', fullNodeName); + value.initialTs = now; + } + } + if (value.dimmingIsOnButShouldBeOffTime) { + if (value.dimmingIsOnButShouldBeOffTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["day_24/7_dimming>0"], fullNodeName); + console.log("report dimming je > 0 ale nema svietit", fullNodeName); + value.dimmingIsOnButShouldBeOffTime = now; + } + } + if (value.powerIsOnButShouldBeOffTime) { + if (value.powerIsOnButShouldBeOffTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["day_24/7_power>0"], fullNodeName); + console.log("report power je > 0 ale nema svietit", fullNodeName); + value.powerIsOnButShouldBeOffTime = now; + } + } + + } + + } + + } + + let report = {}; + report["name"] = SETTINGS.rvo_name; + report["time"] = new Date(); + report["report"] = reportToSend; + + writeToFile(F.path.root("report_data.log"), report, true); + instance.send(SEND_TO.dailyReport, report); + } + + + function dailyReportHandler() { + + if (!SETTINGS.daily_report) return; + + // after dawn we empty reportToSend and start to get data for a new day + const date = new Date(); + const hour = date.getHours(); + const minute = date.getMinutes(); + + console.log("now: ", hour, minute, "suncalc: ", sunCalcResult.dawn_hours, sunCalcResult.dawn_minutes); + + if (hour === sunCalcResult.dawn_hours) { + + //NOTE: ak je este pred usvitom, spracujeme report a posleme na cloud, ak uz je po usvite, resetujeme report plnime data noveho dna + if (minute >= sunCalcResult.dawn_minutes - 2) { + emptyReportToSend(); + emptyDailyReport(); + console.log("Podmienka 1 v dailyReport handler"); + } else { + processDailyReport(); + emptyReportToSend(); + emptyDailyReport(); + console.log("Podmienka 2 v dailyReport handler"); + } + + initialReportStatus = true; + + // ak sa funkcia spusti o hodinu alebo 2 neskor, ako je usvit (moze sa to stat, kedze kazde zapnutie/vypnutie linii odznova spusti casovac. + } else if (hour === sunCalcResult.dawn_hours + 1 || hour === sunCalcResult.dawn_hours + 2) { + if (!initialReportStatus) { + emptyReportToSend(); + emptyDailyReport(); + initialReportStatus = true; + console.log("Podmienka 3 v dailyReport handler"); + } else { + processDailyReport(); + initialReportStatus = true; + console.log("Podmienka 4 v dailyReport handler"); + } + } else { + processDailyReport(); + initialReportStatus = false; + console.log("Podmienka 5 v dailyReport handler"); + } + + console.log("initialReportStatus: ", initialReportStatus); + + } + + function emptyReportToSend() { + emptyJsObject(reportToSend); + reportToSend["contactor"] = { off: [], on: [] }; + reportToSend["night_no_data"] = []; + reportToSend["night_dimming=0"] = []; + reportToSend["night_power=0"] = []; + reportToSend["day_24/7_no_data"] = []; + reportToSend["day_24/7_dimming>0"] = []; + reportToSend["day_24/7_power>0"] = []; + console.log(`resetuje sa reportToSend`); + } + + + //NOTE: ked je initialTs stale rovnaky a zistime ze linie su vypnute (relaysData.line.contactor) - zistim, ci je node na tej linii. Vieme, ze ak je linia vypnuta je to v poriadku lebo nie je na 24/7 linii + //ak je na 24/7 linii, reportujeme, ze neprijima data + function emptyDailyReport() { + const ts = Date.now(); + emptyJsObject(dailyReport); + + //NOTE: do dailyReport dame vsetky nody a pravidelne kontrolujeme ci maju data + //ked nastane sumrak/usvit a svetla maju zacat/prestat svietit, dailyReport spravime nanovo: + for (const [key, value] of Object.entries(nodesData)) { + dailyReport[value.node] = { line: value.line, initialTs: ts }; + } + + console.log("dailyReport: ", dailyReport); + } + + + async function runTasks() { + + clearInterval(interval); + + let currentTimestamp = Date.now(); + + //sort tasks based on timestamp + 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) { + instance.send(SEND_TO.debug, "no tasks created"); + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + if (!rsPort.isOpen) { + instance.send(SEND_TO.debug, "!rsPort.isOpen"); + //await rsPort.open(); + //console.log("Cmd-mngr: !rsPort.isOpen"); + } + + let currentTask = tasks[0]; + + if (currentTask.debug) { + //logger.debug("--->task to process", currentTask); + } + + if (currentTask.timestamp <= currentTimestamp) { + let params = { ...tasks[0] }; + + //allow terminal commands + if (SETTINGS.maintenance_mode && params.type !== "cmd-terminal") { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + let type = params.type; + let tbname = params.tbname; + let node = params.address; + let register = params.register; + let line = null; + let itIsNodeCommand; + + if (nodesData[node] !== undefined) { + line = nodesData[node].line; + itIsNodeCommand = true; + } + + if (params.line !== undefined) line = params.line; + + if (params.addMinutesToTimestamp > 0 || params.timePointName) { + tasks[0].timestamp = currentTimestamp + tasks[0].addMinutesToTimestamp * 60000; + } else { + tasks.shift(); + } + + //kontrola nespracovanych profilov nodov + //TODO: co ked niektore nody neprijimaju profily? kazdu hodinu zahltuju "tasks" array + if (type == "process_profiles") { + //na vsetky zapnutych liniach sa spracuju nespracovane profily nodov + loadRelaysData(); + interval = setInterval(runTasks, SHORT_INTERVAL); + return; + } + + //relay + if (type == "relay") { + + const timePointName = params.timePointName; + const value = params.value; + + let date = new Date(); + date.setDate(date.getDate() + 1);//next day + + let sunCalcResult; + if (timePointName) sunCalcResult = calculateDuskDawn(date, params.line); + + + if (timePointName == "dawn") { + tasks[0].timestamp = sunCalcResult.dawn_time; + } + else if (timePointName == "dusk") { + tasks[0].timestamp = sunCalcResult.dusk_time; + } + else if (timePointName == "luxOn") { + tasks[0].timestamp = sunCalcResult.dusk_time + params.dusk_lux_sensor_time_window * 60000; + } + else if (timePointName == "luxOff") { + tasks[0].timestamp = sunCalcResult.dawn_time + params.dawn_lux_sensor_time_window * 60000; + } + else if (timePointName == "profileTimepoint") { + tasks[0].timestamp = currentTimestamp + tasks[0].addMinutesToTimestamp * 60000; + } + + let info = "aplikovany bod profilu"; + let onOrOff = ""; + value == 1 ? onOrOff = "on" : onOrOff = "off"; + + turnLine(onOrOff, params.line, info); + + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + if (!SETTINGS.masterNodeIsResponding) { + //ak neodpoveda, nebudeme vykonavat ziadne commands, okrem cmd-terminal cmd-master + errorHandler.sendMessageToService("Master node is not responding"); + + let stop = true; + + if (type === "cmd-terminal" || type === "cmd-master") stop = false; + if (stop) { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + } + + let contactorStatus = 1; + if (relaysData[line] != undefined) contactorStatus = relaysData[line].contactor; + + if (line === 0 || contactorStatus === 0 || FLOW.deviceStatus.state_of_breaker[line] === "Off") { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + // TODO: -> status offline for rvo if rotary_switch_state is OFF, this is source of errors + // check if rotary_switch_state == "Off" + // state_of_braker: disconnected = true? + + if (!rsPort.isOpen) { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + //RE-CALCULATE VALUES + //set actual time for broadcast + if (register == 87 && params.recipient === 2) { + var d = new Date(); + params.byte1 = d.getHours();//h + params.byte2 = d.getMinutes();//m + } + + //SET DUSK/DAWN FOR BROADCAST + //Time of dusk + if (register == 6 && params.recipient === 2) { + + if (type != "cmd-terminal") { + params.byte1 = sunCalcResult["dusk_hours"];//h + params.byte2 = sunCalcResult["dusk_minutes"];//m + } + } + + //Time of dawn + if (register == 7 && params.recipient === 2) { + if (type != "cmd-terminal") { + params.byte1 = sunCalcResult["dawn_hours"];//h + params.byte2 = sunCalcResult["dawn_minutes"];//m + } + } + //----------------------- + + instance.send(SEND_TO.debug, "address: " + node + " register:" + register + "type: " + type); + + var startTime, endTime; + startTime = new Date(); + + let saveToTb = true; + if (!tbname) saveToTb = false; + + let resp = com_generic(node, params.recipient, params.rw, register, params.name, params.byte1, params.byte2, params.byte3, params.byte4); + let readBytes = 11; + let timeout = 4000; + + + // await keyword is important, otherwise incorrect data is returned! + await writeData(rsPort, resp, readBytes, timeout).then(function(data) { + + //sometimes happens, that status of node changes to OK, NOK even if line was turned off and should be status OFFLINE. To prevent this, we return if line contactor is 0: + if (itIsNodeCommand && line && relaysData[line].contactor !== 1) return; + + 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); + + //ak sa odpoved zacina 0 - je to v poriadku, inak je NOK + let message = result.message; // OK, NOK + let message_type = result.type; + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + console.log("detected response:", result); + logger.debug("Cmd-mngr: writeData done " + message_type + " duration: " + timeDiff + " type: " + params.debug, params, result); + } + } + + let values = {}; + + //CMD FINISHED + if (message == "OK") { + + updateNodeStatus(node, true); + + //write + if (type == "set_node_profile") { + let result = cmdCounterResolve(node); + if (result == 0) { + dbNodes.modify({ processed: true }).where("node", node).make(function(builder) { + builder.callback(function(err, response) { + + sendNotification("Cmd-mngr: process cmd", SETTINGS.rvoTbName, "dimming_profile_was_successfully_received_by_node", { node: node }, "", SEND_TO.tb, instance); + + logger.debug("--> profil úspešne odoslaný na node č. " + node); + nodesData[node].processed = true; + nodeProfileSendFail.delete(node); + }); + }); + } + } + + //parse read response + if (params.rw == 0) { + values = processResponse(register, dataBytes); //read + } + + if (itIsNodeCommand) { + values.comm_status = "OK"; + values.status = "OK"; + nodesData[node].readout = { ...nodesData[node].readout, ...values }; + + + if (SETTINGS.daily_report) { + //TODO: co ak nedostavame odpovede z nodu ? Musime vyreportovat!! + //v dailyReport teda musi byt kompletny zoznam nodov a neustale kontrolovat, ci maju data, ak nie report node - neodpoveda + if (register === 1) { + + let now = Date.now(); + + if (rvo_is_on === true) { + + if ("dimmingIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].dimmingIsOnButShouldBeOffTime; + + if (values.dimming > 0) { + if ("dimmingIsZeroTime" in dailyReport[node]) delete dailyReport[node].dimmingIsZeroTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if (!("dimmingIsZeroTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], dimmingIsZeroTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } else { + + if ("dimmingIsZeroTime" in dailyReport[node]) delete dailyReport[node].dimmingIsZeroTime; + + if (values.dimming > 0) { + if (!("dimmingIsOnButShouldBeOffTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], dimmingIsOnButShouldBeOffTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if ("dimmingIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].dimmingIsOnButShouldBeOffTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } + } + + if (register === 76) { + + let now = Date.now(); + + if (rvo_is_on === true) { + + if ("powerIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].powerIsOnButShouldBeOffTime; + + if (values.power > 1) { + if ("powerIsZeroTime" in dailyReport[node]) delete dailyReport[node].powerIsZeroTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if (!("powerIsZeroTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], powerIsZeroTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } else { + + if ("powerIsZeroTime" in dailyReport[node]) delete dailyReport[node].powerIsZeroTime; + + if (values.power > 1) { + if (!("powerIsOnButShouldBeOffTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], powerIsOnButShouldBeOffTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if ("powerIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].powerIsOnButShouldBeOffTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } + } + } + + } + + //master node + if (node == 0) { + sendNotification("Cmd-mngr: 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; + } + + if (params.debug) { + //logger.debug("saveToTb", saveToTb, tbname, values); + } + + if (saveToTb && type != "node-regular-read") { + sendTelemetry(values, tbname); + } + else { + if (type == "cmd-terminal") { + terminalCommandResponse(params, "SUCCESS", data); + } + } + + } + else { + terminalCommandResponse(params, "ERROR", data); + handleNokResponseOnRsPort("handleNOK else block", params, itIsNodeCommand, saveToTb); + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + //logger.debug("writeData err: ", error, result, params); + logger.debug("writeData err: ", tbname, node, register, values); + } + } + + //logger.debug(error, result, params); + } + }).catch(function(reason) { + + //console.log("writeData catch exception", reason); + instance.send(SEND_TO.debug, reason); + + terminalCommandResponse(params, "FAILURE", null, reason); + handleNokResponseOnRsPort("handleNOK catch block", params, itIsNodeCommand, saveToTb); + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + logger.debug("-->WRITE FAILED: " + reason, params.debug, params); + } + } + + }); + + } + 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); + } + + + // if node does not respond to request, we repeat request 3 times: + function repeatCommand(params) { + params.repeatCounter++; + if (params.repeatCounter < 4) { + params.timestamp = 0; + params.addMinutesToTimestamp = 0; + tasks.push(params); + } + } + + function handleNokResponseOnRsPort(message, params, itIsNodeCommand, saveToTb) { + + let node = params.address; + let register = params.register; + let type = params.type; + let tbName = params.tbname; + if (!tbName) return; + + let values = {}; + + let updateStatus = updateNodeStatus(node, false); + + if (itIsNodeCommand) { + values.comm_status = "NOK"; + nodesData[node].readout.comm_status = "NOK"; + repeatCommand(params); + } + + if (updateStatus) { + values.status = "NOK"; + nodesData[node].readout.status = "NOK"; + } + + if (type === "node-regular-read") return; + + //master node + if (node == 0) { + sendNotification("Cmd-mngr: 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; + + if (register == 4) values["master_node_version"] = "NOK"; + } + + if (type == "set_node_profile") { + delete cmdCounter[node]; + logger.debug("profil nebol úspešne odoslaný na node č. ", params); + + if (!nodeProfileSendFail.has(node)) { + sendNotification("Cmd-mngr: process cmd", tbName, "configuration_of_dimming_profile_to_node_failed", { node: node }, "", SEND_TO.tb, instance); + nodeProfileSendFail.add(node); + } + } + + // console.log("------",node, register, type, itIsNodeCommand, updateStatus, saveToTb, values); + if (saveToTb) { + sendTelemetry(values, tbName); + } + + } + + + function sendNodesData() { + Object.keys(nodesData).forEach(node => { + if (nodesData[node]["status"] !== "OFFLINE") { + sendTelemetry(nodesData[node].readout, nodesData[node].tbname); + nodesData[node].readout = {}; + } + }) + } + + + /** + * 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; + } + + 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); + + //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 === "OFFLINE") { + nodeObj.node_status_before_offline === true ? number_of_ok_luminaires++ : number_of_nok_luminaires++; + } + else if (nodeObj.status == true) 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 - ts % 60000 //round to full minute + }; + + sendTelemetry(values, SETTINGS.rvoTbName, ts); + } + + + function setSunCalcResult() { + //if next day, we get new dusk and dawn. To make sure, in local timezone 2:00 means 00:00 in utc (it means next day) + if (new Date().getHours() === 2) { + sunCalcResult = calculateDuskDawn(); + console.log("Novy suncalc: ", sunCalcResult); + } + } + + + function setRvoPeriod() { + + if (!SETTINGS.daily_report) return; + + const ts = Date.now(); + + previous_rvo_is_on_value = rvo_is_on; + + if (ts < sunCalcResult.dawn_time - 1_800_000) { // nodes should be on (00:00 -> 06:00 ( - pol hodina, lebo rvo vypina skor) + rvo_is_on = true; + } else if (sunCalcResult.dawn_time - 1_800_000 < ts && ts < sunCalcResult.dusk_time + 1_800_000) { // nodes should be off 06:00 -> 21:00 + rvo_is_on = false; + } else if (sunCalcResult.dusk_time + 1_800_000 < ts) { // nodes should be on 21:00 -> 00:00 + rvo_is_on = true; + } + + if (previous_rvo_is_on_value !== rvo_is_on) { + emptyDailyReport(); + console.log("rvo_is: ", rvo_is_on, previous_rvo_is_on_value); + } + } + + + function handleRsPort() { + + if (rsPort) { + rsPort.removeAllListeners(); + rsPort = null; + } + + //! 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-mngr: rsPort opened success"); + + 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); + + }).catch(function(reason) { + instance.send(SEND_TO.debug, "Cmd-mngr: RPC runSyncExec - promise rejected:" + reason); + }); + }); + + rsPort.on('error', function(err) { + errorHandler.sendMessageToService([exports.title, "unable to open port", SETTINGS.serial_port, err.message], 0); + monitor.info("Cmd-mngr: Error on rsPort", err.message); + }); + + rsPort.on("close", () => { + monitor.info("Cmd-mngr: rsPort closed, reconnecting..."); + setTimeout(handleRsPort, 1000); + }); + + rsPort.open(); + } + + + instance.on("close", () => { + clearInterval(interval); + clearInterval(customTasksInterval); + clearInterval(setCorrectTime); + clearInterval(sendNodeReadout); + clearInterval(accelerometerInterval); + rsPort.close(); + }); + + instance.on("0", _ => { + main(); + }) + + + instance.on("2", _ => { + console.log("dailyReport, reportToSend, rvo_is_on", dailyReport, reportToSend, rvo_is_on, previous_rvo_is_on_value); + }) + + instance.on("1", 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(); + return; + } + else if (flowdata.data == "close") { + rsPort.close(); + return; + } + else if (flowdata.data == "clean") { + tasks = []; + return; + } + else if (flowdata.data == "buildtasks") { + //build & run + return; + } + else if (flowdata.data == "run") { + //durations = []; + + if (tasks.length == 0) { + + buildTasks(); + + if (rsPort.isOpen) { + interval = setInterval(runTasks, 100); + } + else { + instance.send(SEND_TO.debug, "port is not opened!!!"); + } + } + } + else { + //terminal data - object + //logger.debug("flowdata", flowdata.data); + + if (typeof flowdata.data === 'object') { + //logger.debug("dido", flowdata.data); + if (flowdata.data.hasOwnProperty("sender")) { + //data from dido_controller + if (flowdata.data.sender == "dido_controller") { + + if (flowdata.data.hasOwnProperty("cmd")) { + let cmd = flowdata.data.cmd; + + if (cmd == "buildTasks") { + clearInterval(interval); + + logger.debug("-->Cmd-mngr: BUILD TASKS"); + buildTasks(); + + //logger.debug("tasks:"); + //logger.debug(tasks); + + logger.debug("-->Cmd-mngr: RUN TASKS"); + interval = setInterval(runTasks, 5000); + } + else if (cmd == "reload_relays") { + loadRelaysData(flowdata.data.line); + + if (flowdata.data.dataChanged) { + if (!flowdata.data.value) { + reportOfflineNodeStatus(flowdata.data.line); + } + else { + reportOnlineNodeStatus(flowdata.data.line); + } + } + + } + else if (cmd == "rotary_switch_state") { + let value = flowdata.data.value; + + //state was changed + if (rotary_switch_state != value) { + if (value == "Off") { + //vyreportovat vsetky svietdla + reportOfflineNodeStatus(); + } + + rotary_switch_state = value; + } + } + 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) { + + // we send lux_sensor value to all nodes: + let params = getParams(PRIORITY_TYPES.node_broadcast); + + params.recipient = 2;//2 broadcast, address = 0 + params.address = 0xffffffff;//Broadcast + + let ba = longToByteArray(lux_sensor); + + params.byte3 = ba[1];//msb + params.byte4 = ba[0]; + params.timestamp = PRIORITY_TYPES.node_broadcast; + params.info = "run broadcast: Actual Lux level from cabinet"; + params.register = 95;//Actual Lux level from cabinet + params.rw = 1;//write + + tasks.push(params); + + //process profiles + turnOnOffLinesAccordingToLuxSensor(lux_sensor); + } + } + else if (cmd == "state_of_breaker") { + //istic linie + + breakerCounter--; + + let value = flowdata.data.value; + let line = parseInt(flowdata.data.line); + + let dataChanged = false; + if (state_of_breaker[line] != value) dataChanged = true; + + state_of_breaker[line] = value; + + let status = "OK"; + if (value == "Off") status = "NOK"; + + if (dataChanged) { + + if (relaysData.hasOwnProperty(line)) { + let tbname = relaysData[line].tbname; + + if (value == "Off") { + sendNotification("Cmd-mngr: onData", tbname, "circuit_breaker_was_turned_off_line", { line: line }, "", SEND_TO.tb, instance, "circuit_breaker"); + if (breakerCounter < 0) reportToSend["contactor"]["off"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + else { + sendNotification("Cmd-mngr: onData", tbname, "circuit_breaker_was_turned_on_line", { line: line }, "", SEND_TO.tb, instance, "circuit_breaker"); + if (breakerCounter < 0) reportToSend["contactor"]["on"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + + //report status liniu + sendTelemetry({ status: status }, tbname) + + //current value + if (value == "Off") reportOfflineNodeStatus(line); //vyreportovat vsetky svietidla na linii + } + + } + } + else { + logger.debug("undefined cmd", cmd); + } + } + } + + return; + } + + //data from worksys + if (flowdata.data.hasOwnProperty("topic")) { + + let data = getNested(flowdata.data, "content", "data"); + + //if we get temperature in senica from senica-prod01 + let temperature = getNested(flowdata.data, "content", "senica_temperature"); + + if (temperature !== undefined) { + temperatureInSenica = temperature; + return; + } + + if (data === undefined) { + console.log("Invalid rpc command came from platform"); + return; + } + + let command = data.params.command; + let method = data.method; + let profile = data.params.payload; + if (profile == undefined) profile = ""; + let entity = data.params.entities[0]; + let entity_type = entity.entity_type; + let tbname = entity.tb_name; + + instance.send(SEND_TO.debug, flowdata.data); + 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") { + + //let command = data.params.command; + let value = data.params.payload.value; + + if (command == "dimming") { + + let nodeWasFound = false; + let keys = Object.keys(nodesData); + + //logger.debug("-----", keys); + + 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); + + value = parseInt(value); + if (value > 0) value = value + 128; + + params.type = "node-onetime-write"; + params.tbname = tbname; + params.address = node; + params.register = 1; + params.recipient = 1; + params.byte4 = value; + params.rw = 1; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'set dimming from platform'; + //params.debug = true; + + //debug(params); + logger.debug("dimming", params); + + tasks.push(params); + + 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); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 1; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read dimming (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + //pridame aj vyreportovanie - vykon + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 76; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read Input Power (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + //pridame aj vyreportovanie - prud svietidla + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 75; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read Input Current (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + //pridame aj vyreportovanie - power faktor - ucinnik + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 77; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read power factor (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + }, 4000); + + nodeWasFound = true; + break; + } + } + + if (!nodeWasFound) { + logger.debug("set dimming from platform", "unable to find tbname", tbname); + } + } + else { + instance.send(SEND_TO.debug, "undefined command " + command); + logger.debug("undefined command", command); + } + + return; + } + 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++) { + let node = keys[i]; + if (tbname == nodesData[node].tbname) { + + 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"); + + //profil úspešne prijatý pre node č. xx + sendNotification("Cmd-mngr", tbname, "dimming_profile_was_processed_for_node", { node: node }, profile, SEND_TO.tb, instance); + + nodesData[node].processed = false; + nodesData[node].profile = profile; + + processNodeProfile(node); + }); + }); + } + } + } + else { + + instance.send(SEND_TO.debug, "unknown method " + method); + logger.debug("unknown method", method); + + return; + } + } + + //nastav profil linie z platformy + 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") { + + 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++) { + let line = keys[i]; + if (tbname == relaysData[line].tbname) { + //zmazeme tasky + 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) { + + //update profile + logger.debug("worksys - update relay profile done:", profile); + instance.send(SEND_TO.debug, "worksys - update relay profile done"); + + relaysData[line].profile = profile; + + loadRelaysData(line) + logger.debug("loadRelaysData DONE for line", line); + + buildTasks({ processLineProfiles: true, line: line }); + + sendNotification("Cmd-mngr: set profile from worksys", tbname, "switching_profile_was_processed_for_line", { line: line }, profile, SEND_TO.tb, instance); + }); + }); + break; + } + } + } + else if (method == "set_command") { + let value = data.params.payload.value; + + 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; + + 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"); + if (line != 0) reportToSend["contactor"]["off"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + else { + turnLine("on", line, "command received from platform"); + if (line != 0) reportToSend["contactor"]["on"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + } + } + else { + instance.send(SEND_TO.debug, "undefined method " + method); + logger.debug("undefined method", method); + } + + return; + } + else { + instance.send(SEND_TO.debug, "UNKNOW entity_type " + entity_type); + logger.debug("UNKNOW entity_type", entity_type); + } + return; + } + + //terminal + if (!rsPort.isOpen) await rsPort.open(); + + let params = flowdata.data.body; + if (params == undefined) { + //logger.debug("Cmd-mngr: flowdata.data.body is undefined"); + return; + } + + params.priority = PRIORITY_TYPES.terminal; + params.type = "cmd-terminal"; + params.tbname = ""; + params.timestamp = PRIORITY_TYPES.terminal; + params.addMinutesToTimestamp = 0;// do not repeat task!!! + params.debug = true; + + let timestamp = Date.now(); + params.refFlowdataKey = timestamp; + //params.refFlowdata = flowdata; + //refFlowdata = flowdata; + + //console.log("flowdata", flowdata); + + cleanUpRefFlowdataObj(); + + refFlowdataObj[timestamp] = flowdata; + + //fix + //params.address = params.adress; + logger.debug("received from terminal", params); + logger.debug("date/time:", new Date()); + logger.debug("tasks length:", tasks.length); + + //tasks = []; + + //add to tasks + tasks.push(params); + + } + } + }) + + + //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) + } + + + /** + * 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; + + RESTBuilder.make(function(builder) { + + if (!builder) return; + + builder.method('GET'); + builder.url('http://192.168.252.2:8004/gettime?projects_id=1'); + + builder.callback(function(err, response, output) { + + 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); + } + + }); + } + + } 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); + + } else { + //console.log("Read-only", stdout); + + 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]: [ + { + "ts": date, + "values": values + } + ] + } + + tbHandler.sendToTb(dataToTb, instance); + } + + + function calculateDuskDawn(date, line, duskOffset = 0, dawnOffset = 0) { + + if (date === undefined) date = new Date(); + + 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); + } + + //if(profile.dawn_lux_sensor == false) + { + if (profile.hasOwnProperty("dawn_astro_clock_offset")) dawn_astro_clock_offset = parseInt(profile.dawn_astro_clock_offset); + } + + } + + } catch (error) { + if (profilestr != "") { + logger.debug(profilestr); + logger.debug(error); + } + } + + 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; + } + + //Dimming, CCT + else if (register == 1) { + let brightness = 0; + let dimming = byte0; + if (dimming > 128) { + //dimming = -128; + brightness = dimming - 128; + } + + //cct + //Ak Byte3 == 1: CCT = (Byte2*256)+Byte1 + let cct; + if (byte3 == 1) cct = byte2 * 256 + byte1; + else cct = bytesToInt(bytes.slice(0, 3)); + + //cct podla auditu + + values["dimming"] = brightness; + return values; + } + + // + else if (register == 4) { + values["master_node_version"] = bytes[1] + "." + bytes[2]; + //logger.debug("FW Version", register, bytes); + } + + //Napätie + else if (register == 74) { + let voltage = (bytesToInt(bytes) * 0.1).toFixed(1); + values["voltage"] = Number(voltage); + } + + //Prúd + else if (register == 75) { + let current = bytesToInt(bytes); + values["current"] = current; + } + + //výkon + else if (register == 76) { + let power = (bytesToInt(bytes) * 0.1).toFixed(2); + values["power"] = Number(power); + } + + //účinník + else if (register == 77) { + let power_factor = Math.cos(bytesToInt(bytes) * 0.1 * (Math.PI / 180)).toFixed(2); + values["power_factor"] = Number(power_factor); + } + + //frekvencia + else if (register == 78) { + let frequency = (bytesToInt(bytes) * 0.1).toFixed(2); + values["frequency"] = Number(frequency); + } + + //energia + else if (register == 79) { + let energy = bytesToInt(bytes); + values["energy"] = energy / 1000; //energia v kWh -> delit 1000 + } + + //doba života + else if (register == 80) { + let lifetime = (bytesToInt(bytes) / 60).toFixed(2); + values["lifetime"] = Number(lifetime); + } + + //nastavenie profilu + else if (register == 8) { + let time_schedule_settings = bytesToInt(bytes); + values["time_schedule_settings"] = time_schedule_settings; + } + + //naklon - nateraz sa z nodu nevycitava! kvoli problemom s accelerometrom a vracanymi hodnotami, posielame temp a x y z vo funkcii accelerometerData() + else if (register == 84) { + values["temperature"] = byte3 >= 128 ? (byte3 - 128) * (-1) : byte3; + values["inclination_x"] = byte2 >= 128 ? (byte2 - 128) * (-1) : byte2; + values["inclination_y"] = byte1 >= 128 ? (byte1 - 128) * (-1) : byte1; + values["inclination_z"] = byte0 >= 128 ? (byte0 - 128) * (-1) : byte0; + } + + //FW verzia nodu + else if (register == 89) { + //formát: "Byte3: Byte2.Byte1 (Byte0)" + values["fw_version"] = byte3 + ":" + byte2 + "." + byte1 + "(" + byte0 + ")"; + } + + else if (register == 87 || register == 6 || register == 7) { + var d = new Date(); + d.setHours(byte3, byte2, 0, 0); + let timestamp = d.getTime(); + + //aktuálny čas + if (register == 87) values["actual_time"] = timestamp; + //čas súmraku + else if (register == 6) values["dusk_time"] = timestamp; + //čas úsvitu + else if (register == 7) values["dawn_time"] = timestamp; + } + + 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; + + } + + + function getObjectByTbValue(object, tbname) { + return object[Object.keys(object).find(key => object[key].tbname === tbname)]; + } + + + function isObject(item) { + return (typeof item === "object" && !Array.isArray(item) && item !== null); + } + + + // we fake data, that should be received from accelerometer, as they are a bit unreliable. (temperature, x,y,z) + function accelerometerData() { + + if (temperatureInSenica === null) return; + + //clone nodesData and relaysData objects + let nodesData_clone = JSON.parse(JSON.stringify(nodesData)); + let relaysData_clone = JSON.parse(JSON.stringify(relaysData)); + + for (const key in relaysData_clone) { + + const lineData = relaysData_clone[key]; + const lineNumber = lineData.line; + const contactor = lineData.contactor; + + if (lineNumber === 0) continue; + + if (contactor === 1) { + + let date = Date.now(); + + Object.keys(nodesData_clone).forEach((node, index) => { + + setTimeout(function() { + + if (nodesData_clone[node].line === lineNumber) { + + // NOTE: if status of luminaire is NOK or OFFLINE, we do not send data; + let status = nodesData_clone[node].status; + if (status === "OFFLINE" || !status) return; + + let x = null; + if (naklony.hasOwnProperty(node)) x = naklony[node].naklon; + if (x === null) x = 0; + + sendTelemetry({ temperature: Math.round(temperatureInSenica + 10 + Math.floor(Math.random() * 3)), inclination_x: x, inclination_y: 0, inclination_z: 0 }, nodesData_clone[node].tbname, date); + } + + }, (index + 1) * 500); + }) + + } + } + } + + +} // end of instance.export + diff --git a/RVO20/flow/code.js b/RVO20/flow/code.js new file mode 100755 index 0000000..63b31bf --- /dev/null +++ b/RVO20/flow/code.js @@ -0,0 +1,90 @@ +exports.id = 'code'; +exports.title = 'Code'; +exports.group = 'Common'; +exports.color = '#656D78'; +exports.input = true; +exports.output = 1; +exports.author = 'Peter Širka'; +exports.icon = 'code'; +exports.version = '1.2.0'; +exports.options = { outputs: 1, code: 'send(0, value);', keepmessage: true }; + +exports.html = `
+
+
+
@(Number of outputs)
+
@(Minimum is 1)
+
+
+
@(Code)
+
@(Keep message instance)
+
+`; + +exports.readme = `# Code + +This component executes custom JavaScript code as it is and it doesn't contain any secure scope. + +\`\`\`javascript +// value {Object} contains received data +// send(outputIndex, newValue) sends a new value +// error(value) sends an error +// instance {Object} a current component instance +// flowdata {Object} a current flowdata +// repository {Object} a current repository of flowdata +// Example: + +// send() can be execute multiple times +send(0, value); +\`\`\``; + +exports.install = function(instance) { + + var fn; + + instance.on('data', function(response) { + if (fn) { + try { + fn(response.data, instance, response, instance.options, response.repository, require); + } catch (e) { + response.data = e; + instance.throw(response); + } + } + }); + + instance.reconfigure = function() { + try { + if (instance.options.code) { + instance.status(''); + var code = 'var send = function(index, value) { if (options.keepmessage) { flowdata.data = value; instance.send2(index, flowdata); } else instance.send2(index, value);}; var error = function(err) { instance.throw(err); }; ' + instance.options.code; + fn = new Function('value', 'instance', 'flowdata', 'options', 'repository', 'require', code); + } else { + instance.status('Not configured', 'red'); + fn = null; + } + } catch (e) { + fn = null; + instance.error('Code: ' + e.message); + } + }; + + instance.on('options', instance.reconfigure); + instance.reconfigure(); +}; \ No newline at end of file diff --git a/RVO20/flow/comment.js b/RVO20/flow/comment.js new file mode 100755 index 0000000..1e0cd13 --- /dev/null +++ b/RVO20/flow/comment.js @@ -0,0 +1,11 @@ +exports.id = 'comment'; +exports.title = 'Comment'; +exports.group = 'Common'; +exports.color = '#704cff'; +exports.author = 'Martin Smola'; +exports.icon = 'comment'; +exports.traffic = false; +exports.version = '1.0.0'; +exports.readme = '# Comment'; + +exports.install = function() {}; diff --git a/RVO20/flow/count.js b/RVO20/flow/count.js new file mode 100755 index 0000000..fa92ee9 --- /dev/null +++ b/RVO20/flow/count.js @@ -0,0 +1,60 @@ +exports.id = 'count'; +exports.title = 'Count'; +exports.version = '1.0.1'; +exports.author = 'John Graves'; +exports.color = '#656D78'; +exports.icon = 'plus-square'; +exports.input = 2; +exports.output = 1; +exports.options = { increment: 1, initialvalue: 1 }; +exports.readme = `# Counter + +Counter Number of times called.`; + +exports.html = `
+
@(Initial Value)
+
@(Increment)
+

Example Video

+
`; + +exports.readme = `# Count + +This component counts the number of messages received. + +__Response:__ + +Integer value based on the initial value and increment settings. + +__Arguments:__ +- Initial Value: What number should be output on the receipt of the first message. +- Increment: What should the increment be for each following message received.`; + +exports.install = function(instance) { + + var count = 0; + var initialCall = true; + + instance.on('data', function(flowdata) { + var index = flowdata.index; + if (index) { + instance.debug('Reset Count.'); + count = instance.options.initialvalue; + initialCall = true; + } else { + // If this is the first time, set the value to 'initial value' + if(initialCall) { + initialCall = false; + count = instance.options.initialvalue; + } else + count = count+instance.options.increment; + instance.status('Count:' + count); + instance.send2(count); + } + }); + + instance.on('options', function() { + count = instance.options.initialvalue; + initialCall = true; + }); + +}; diff --git a/RVO20/flow/db_connector.js b/RVO20/flow/db_connector.js new file mode 100755 index 0000000..65ee94b --- /dev/null +++ b/RVO20/flow/db_connector.js @@ -0,0 +1,286 @@ +exports.id = 'db_connector'; +exports.title = 'DbConnector'; +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.html = `
+
+
+
DbConnector
+
+
+
`; + +exports.readme = `# read/write data to tables`; + +const instanceSendTo = { + debug: 0, + http_response: 1, +} + +const { promisifyBuilder, makeMapFromDbResult } = require('./helper/db_helper.js'); + +function extractWhereParams(params) +{ + let name = params[0]; + let operator = '='; + let value = params[1]; + + if(params.length == 3) + { + operator = params[1]; + value = params[2]; + } + + return {name: name, operator: operator, value: value}; +} + +exports.install = function(instance) { + + let refFlowdata = null;//holds reference to httprequest flowdata + + instance.on("close", () => { + + }) + + + instance.on("data", async function(flowdata) { + + let params = flowdata.data.body; + console.log("DbConnector", params); + + refFlowdata = flowdata; + + if(refFlowdata != undefined) + { + //make http response + let responseObj = {}; + responseObj["type"] = "SUCESS"; + + try{ + + let table = params.table; + let action = params.action; + + + if(params.data != undefined) + { + let className = params.data.className; + + if(className == "SqlQueryBuilder") + { + let type = params.data.type; + + console.log("SqlQueryBuilder---->", params.data); + + if(type == "SELECT") + { + let table = params.data.queryData.tables[0].table; + + const db = TABLE(table); + var builder = db.find(); + + let result = await promisifyBuilder(builder); + + let response = {}; + response["result"] = result; + response["success"] = true; + + responseObj["data"] = response; + + //console.log(responseObj); + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + } + + return; + } + } + + + console.log("db_connector---->", table, action); + + //actions: read, replace, insert, delete, update... + + if(action == "read") + { + const db = TABLE(params.table); + + //where builder.where('age', '<', 15); + //builder.where('id', 3403); + + var builder = db.find(); + + //https://docs.totaljs.com/latest/en.html#api~DatabaseBuilder~builder.where + if(params.hasOwnProperty("where")) + { + //optionalCan contain "=", "<=", "<", ">=", ">". + //Default value: '=' + + //1.["production_line", 1] + //2. ["or", ["production_line", 1], ["production_line", 2], "end"] + + if (Array.isArray(params.where)) { + + let multipleConditions = false; + + if(params.where[0] == "or") multipleConditions = true; + if (Array.isArray(params.where[0])) multipleConditions = true; + + if(multipleConditions) + { + + for(var i = 0; i < params.where.length; i++) + { + const item = params.where[i]; + + if(item === "or") builder.or(); + + if (Array.isArray(item)) + { + const { name, operator, value } = extractWhereParams(item); + builder.where(name, operator, value); + } + + if(item === "end") builder.end(); + + } + + } + else + { + const { name, operator, value } = extractWhereParams(params.where); + builder.where(name, operator, value); + } + + } + + /* + if(params.where.length >=2 ) + { + let name = params.where[0]; + let operator = '='; + let value = params.where[1]; + + if(params.where.length == 3) + { + operator = params.where[1]; + value = params.where[2]; + } + + builder.where(name, operator, value); + } + */ + } + + if(params.hasOwnProperty("between")) + { + builder.between(params.between[0], params.between[1], params.between[2]); + } + + let response = await promisifyBuilder(builder); + responseObj["data"] = response; + + //console.log(responseObj); + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + + return; + } + + if(action == "delete") + { + + } + + + if(action == "update") + { + //! data receiving from terminal (params) + // { + // hostname: 'localhost', + // table: 'settings', + // action: 'update', + // body: { + // rvo_name: 'terrrr', + // lang: 'en', + // temperature_adress: '28.427B45920702', + // latitude: 48.70826502, + // longitude: 17.28455203, + // mqtt_host: '192.168.252.4', + // mqtt_clientid: 'showroom_test_panel_led', + // mqtt_username: 'xmRd6RJxW53WZe4vMFLU', + // mqtt_port: 1883, + // maintanace_mode: false + // } + // } + const tableToModify = TABLE(params.table); + const newValues = params.body; + + tableToModify.modify(newValues).make(function(builder) { + + builder.callback(function(err, response) { + + if(!err) + { + responseObj["data"] = response; + responseObj["tableUpdated"] = true; + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + } + }); + }); + + } + + if(action == "replace") + { + //truncate table + const db = TABLE(params.table); + var builder = db.remove(); + db.clean(); + + //insert data + let data = params.data; + + for(let i = 0; i < data.length; i++) + { + //console.log(data[i]); + db.insert(data[i]); + } + + console.log("insert done"); + + let responseObj = {}; + responseObj["type"] = "SUCESS"; + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + + + } + + + + } catch (error) { + //console.log(error); + responseObj["type"] = "ERROR"; + responseObj["message"] = error; + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + } + } + }) +} + + diff --git a/RVO20/flow/db_init.js b/RVO20/flow/db_init.js new file mode 100755 index 0000000..b399878 --- /dev/null +++ b/RVO20/flow/db_init.js @@ -0,0 +1,113 @@ +exports.id = 'db_init'; +exports.title = 'DB Initialization'; +exports.group = 'Worksys'; +exports.color = '#888600'; +exports.version = '1.0.2'; +exports.icon = 'sign-out'; +exports.output = 2; + +exports.readme = ` + # DB initialization +`; + +const { promisifyBuilder, makeMapFromDbResult } = require('./helper/db_helper.js'); +const { initNotification } = require('./helper/notification_reporter'); +const errorHandler = require('./helper/ErrorToServiceHandler'); +const total_energy = require('../databases/total_energy'); + +const SEND_TO = { + db_init: 0, + infoSender: 1 +}; + + +exports.install = async function(instance) { + const dbNodes = TABLE("nodes"); + const dbRelays = TABLE("relays"); + const dbSettings = TABLE("settings"); + 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 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.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"]; + Object.keys(dbs.nodesData).forEach(node => dbs.nodesData[node].readout = {}) + + let rvo_number = responseSettings[0]["rvo_name"].match(/\D+(\d{1,2})_/)[1]; + + dbs.settings = { + edge_fw_version: "2025-10-08", //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"], + phases: responseSettings[0]["phases"], + cloud_topic: responseSettings[0]["cloud_topic"], + has_main_switch: responseSettings[0]["has_main_switch"], + daily_report: responseSettings[0]["daily_report"], + send_changed_node_numbers: responseSettings[0]["send_changed_node_numbers"], + rvo_number: rvo_number, + + //dynamic values + masterNodeIsResponding: true, //cmd_manager + maintenance_mode: false, + } + + + dbs.settings.energy_to_switch_lamps = total_energy[rvo_number]; + if (dbs.settings.energy_to_switch_lamps === undefined) console.log('=============== db_init.js: energy_to_switch_lamps is undefined'); + + FLOW.dbLoaded = true; + errorHandler.setProjectId(dbs.settings.project_id); + initNotification(); + + //APP START - send to data services + const toService = { + id: dbs.settings.project_id, + name: dbs.settings.rvo_name, + fw_version: dbs.settings.edge_fw_version, + startdate: new Date().toISOString().slice(0, 19).replace('T', ' '), + js_error: "", + error_message: "" + }; + + instance.send(SEND_TO.infoSender, toService); + console.log("----------------> START - message send to service", toService); + + setTimeout(() => { + console.log("DB_INIT - data loaded"); + instance.send(SEND_TO.db_init, "_") + }, 5000) + +}; + diff --git a/RVO20/flow/debug.js b/RVO20/flow/debug.js new file mode 100755 index 0000000..00cb259 --- /dev/null +++ b/RVO20/flow/debug.js @@ -0,0 +1,100 @@ +exports.id = 'debug'; +exports.title = 'Debug'; +exports.author = 'Peter Širka'; +exports.color = '#967ADC'; +exports.click = true; +exports.input = true; +exports.icon = 'bug'; +exports.version = '2.0.4'; +exports.options = { enabled: true, repository: false, type: 'data' }; +exports.readme = `# Debug + +Prints data to the debug tab.`; + +exports.html = `
+
+
+
@(Output type)
+
@(Path to the property (leave empty to show the whole data object))
+
@(A group name)
+
@(Enabled)
+
+
+
`; + +exports.install = function(instance) { + + instance.on('data', function(response) { + if (instance.options.enabled) { + + var opt = instance.options; + var rep = response.repository; + var val = response.data; + var id = response.id; + + switch (instance.options.type){ + case 'both': + var data = {}; + data.repository = rep; + data.data = val instanceof Error ? { error: val.message, stack: val.stack } : val; + instance.debug(safeparse(opt.property ? U.get(data, opt.property) : data), undefined, opt.group, id); + break; + case 'repository': + instance.debug(safeparse(opt.property ? U.get(rep, opt.property) : rep), undefined, opt.group, id); + break; + case 'data': + default: + if (val instanceof Error) + instance.debug({ error: val.message, stack: val.stack }, undefined, opt.group, id); + else + instance.debug(safeparse(opt.property ? U.get(val, opt.property) : val), undefined, opt.group, id); + break; + } + } + }); + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + instance.save(); + }); + + instance.on('options', function() { + instance.custom.status(); + }); + + instance.custom.status = function() { + instance.status(instance.options.enabled ? 'Enabled' : 'Disabled'); + }; + + instance.custom.status(); + + function safeparse(o) { + + if (o instanceof Buffer) + return o; + + if (o === undefined) + return 'undefined'; + + if (o === null) + return 'null'; + + var cache = []; + var str = JSON.stringify(o, function(key, value) { + if (typeof value === 'object' && value !== null) { + if (cache.indexOf(value) !== -1) { + try { + return JSON.parse(JSON.stringify(value)); + } catch (error) { + return; + } + } + cache.push(value); + } + return value; + }); + cache = null; + return JSON.parse(str); + } +}; diff --git a/RVO20/flow/designer.json b/RVO20/flow/designer.json new file mode 100755 index 0000000..580f5a3 --- /dev/null +++ b/RVO20/flow/designer.json @@ -0,0 +1,3102 @@ +{ + "tabs": [ + { + "name": "MAIN PUSH", + "linker": "main-push", + "id": "1612772287426", + "index": 0 + }, + { + "name": "CMD manager", + "linker": "cmd-manager", + "id": "1615551125555", + "index": 1 + }, + { + "name": "Devices", + "linker": "devices", + "id": "1611921777196", + "index": 2 + } + ], + "components": [ + { + "id": "1611951142547", + "component": "debug", + "tab": "1611921777196", + "name": "ERROR", + "x": 598, + "y": 60, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#DA4453", + "notes": "" + }, + { + "id": "1612776786008", + "component": "wsmqttpublish", + "tab": "1612772287426", + "name": "WS MQTT publish", + "x": 281.75, + "y": 174, + "connections": { + "0": [ + { + "index": "0", + "id": "1615551060773" + } + ], + "1": [ + { + "index": "0", + "id": "1618300858252" + }, + { + "index": "0", + "id": "1618558465485" + } + ], + "2": [ + { + "index": "0", + "id": "1634303685503" + } + ], + "3": [ + { + "index": "0", + "id": "1731068754606" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Connected", + "color": "green" + }, + "options": { + "username": "", + "clientid": "", + "port": "1883", + "host": "" + }, + "color": "#888600", + "notes": "" + }, + { + "id": "1612778461252", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "tb-push", + "x": 72.75, + "y": 328, + "connections": { + "0": [ + { + "index": "0", + "id": "1612783322136" + }, + { + "index": "1", + "id": "1612776786008" + }, + { + "index": "0", + "id": "1731068754606" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1612783322136", + "component": "debug", + "tab": "1612772287426", + "name": "to TB", + "x": 283.75, + "y": 324, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615551060773", + "component": "debug", + "tab": "1612772287426", + "name": "errors from MQTT Broker", + "x": 594, + "y": 57, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#DA4453", + "notes": "" + }, + { + "id": "1615563373927", + "component": "debug", + "tab": "1615551125555", + "name": "Debug", + "x": 755, + "y": 155, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#DA4453", + "notes": "" + }, + { + "id": "1615566865233", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "tb-push", + "x": 755, + "y": 248, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1615798582262", + "component": "debug", + "tab": "1615551125555", + "name": "CMD_debug", + "x": 755, + "y": 346, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615802995322", + "component": "debug", + "tab": "1611921777196", + "name": "Debug", + "x": 596.8833312988281, + "y": 566.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Disabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": false + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615809128443", + "component": "debug", + "tab": "1611921777196", + "name": "tempToTb", + "x": 595.8833312988281, + "y": 658.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615809595184", + "component": "virtualwireout", + "tab": "1611921777196", + "name": "tb-push", + "x": 597.8833312988281, + "y": 377.25, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1616165795916", + "component": "httproute", + "tab": "1615551125555", + "name": "POST /terminal", + "x": 135, + "y": 547, + "connections": { + "0": [ + { + "index": "0", + "id": "1684060205000" + }, + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Listening", + "color": "green" + }, + "options": { + "timeout": 10, + "cachepolicy": 0, + "cacheexpire": "5 minutes", + "size": 5, + "url": "/terminal", + "method": "POST", + "name": "", + "flags": [ + "id:1616165795916", + "post", + 10000 + ], + "emptyresponse": false + }, + "color": "#5D9CEC", + "notes": "### Configuration\n\n- __POST /terminal__\n- flags: \n- maximum request data length: __5 kB__\n- empty response: __false__\n- cache policy: __no cache__\n- cache expire: __5 minutes__", + "cloning": false + }, + { + "id": "1616165824813", + "component": "httpresponse", + "tab": "1615551125555", + "name": "HTTP Response", + "x": 753, + "y": 423, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "json" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1617104731852", + "component": "debug", + "tab": "1615551125555", + "name": "DIDO_Debug", + "x": 669, + "y": 1040, + "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": "turnOff line", + "x": 133, + "y": 1161, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "object", + "data": "{line: 3, command: \"turnOff\", force: true}" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1617115013095", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "tb-push", + "x": 669, + "y": 1150, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1617284749681", + "component": "trigger", + "tab": "1615551125555", + "name": "update profile / node", + "x": 112, + "y": 208, + "connections": { + "0": [ + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "data": "profile_nodes", + "datatype": "string" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1618235171399", + "component": "trigger", + "tab": "1615551125555", + "name": "tun tasks", + "x": 184, + "y": 279, + "connections": { + "0": [ + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "data": "run" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1618300858252", + "component": "debug", + "tab": "1612772287426", + "name": "wsmqtt-exit1", + "x": 597.8833312988281, + "y": 149, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1618393583970", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "to-cmd-manager", + "x": 668.8833312988281, + "y": 1269, + "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": 132.88333129882812, + "y": 367, + "connections": { + "0": [ + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "platform-rpc-call", + "color": "gray" + }, + "options": { + "wirename": "platform-rpc-call" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1618393759854", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "cmd_to_dido", + "x": 119.88333129882812, + "y": 1007, + "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": 752.8833312988281, + "y": 527, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "cmd_to_dido", + "color": "gray" + }, + "options": { + "wirename": "cmd_to_dido" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1618558465485", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "platform-rpc-call", + "x": 597.8833312988281, + "y": 247, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "platform-rpc-call", + "color": "gray" + }, + "options": { + "wirename": "platform-rpc-call" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1618572059773", + "component": "trigger", + "tab": "1615551125555", + "name": "turnOn line", + "x": 132, + "y": 1085, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "data": "{line: 1, command: \"turnOn\", force: true}", + "datatype": "object" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1619515097737", + "component": "cmd_manager", + "tab": "1615551125555", + "name": "CMD Manager", + "x": 452.1091003417969, + "y": 341.05455017089844, + "connections": { + "0": [ + { + "index": "0", + "id": "1615563373927" + } + ], + "1": [ + { + "index": "0", + "id": "1615566865233" + }, + { + "index": "0", + "id": "1615798582262" + } + ], + "2": [ + { + "index": "0", + "id": "1616165824813" + } + ], + "3": [ + { + "index": "0", + "id": "1618393827655" + } + ], + "4": [ + { + "index": "0", + "id": "1635936391935" + } + ], + "5": [ + { + "index": "0", + "id": "1757006030239" + }, + { + "index": "0", + "id": "1757006060377" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1619605019281", + "component": "httproute", + "tab": "1615551125555", + "name": "GET db", + "x": 173, + "y": 653, + "connections": { + "0": [ + { + "index": "0", + "id": "1684060205000" + }, + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Listening", + "color": "green" + }, + "options": { + "timeout": 5, + "cachepolicy": 0, + "cacheexpire": "5 minutes", + "size": 5, + "url": "/db", + "method": "GET", + "name": "", + "flags": [ + "id:1619605019281", + "get", + 5000 + ] + }, + "color": "#5D9CEC", + "notes": "### Configuration\n\n- __GET /db__\n- flags: undefined\n- maximum request data length: __5 kB__\n- empty response: __undefined__\n- cache policy: __no cache__\n- cache expire: __5 minutes__", + "cloning": false + }, + { + "id": "1619784672383", + "component": "trigger", + "tab": "1615551125555", + "name": "turnOnAlarm", + "x": 120, + "y": 1234, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "object", + "data": "{command: \"turnOnAlarm\"}" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1619784812964", + "component": "trigger", + "tab": "1615551125555", + "name": "turnOffAlarm", + "x": 118, + "y": 1307, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "object", + "data": "{command: \"turnOffAlarm\"}" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1621340721628", + "component": "virtualwireout", + "tab": "1611921777196", + "name": "modbus_to_dido", + "x": 599, + "y": 471, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "modbus_to_dido", + "color": "gray" + }, + "options": { + "wirename": "modbus_to_dido" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1622640022885", + "component": "httproute", + "tab": "1615551125555", + "name": "POST /db_connector", + "x": 98, + "y": 1586, + "connections": { + "0": [ + { + "index": "0", + "id": "1622640073521" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Listening", + "color": "green" + }, + "options": { + "timeout": 5, + "cachepolicy": 0, + "cacheexpire": "5 minutes", + "size": 5, + "url": "/db_connector", + "method": "POST", + "flags": [ + "id:1622640022885", + "post", + 5000 + ] + }, + "color": "#5D9CEC", + "notes": "### Configuration\n\n- __POST /db_connector__\n- flags: \n- maximum request data length: __5 kB__\n- empty response: __undefined__\n- cache policy: __no cache__\n- cache expire: __5 minutes__", + "cloning": false + }, + { + "id": "1622640073521", + "component": "db_connector", + "tab": "1615551125555", + "name": "DbConnector", + "x": 372, + "y": 1572, + "connections": { + "1": [ + { + "index": "0", + "id": "1622641420685" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "edge": "undefined" + }, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1622641420685", + "component": "httpresponse", + "tab": "1615551125555", + "name": "HTTP Response", + "x": 596, + "y": 1586, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1634303504177", + "component": "monitormemory", + "tab": "1612772287426", + "name": "RAM", + "x": 69.88333129882812, + "y": 888.5, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465281992" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "858.88 MB / 985.68 MB", + "color": "gray" + }, + "options": { + "enabled": true, + "interval": 30000 + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1634303533779", + "component": "monitordisk", + "tab": "1612772287426", + "name": "disk", + "x": 70.88333129882812, + "y": 982.5, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465821120" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "5.78 GB / 7.26 GB", + "color": "gray" + }, + "options": { + "enabled": true, + "path": "/", + "interval": 30000 + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1634303595494", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "send-to-services", + "x": 51.883331298828125, + "y": 1400.5, + "connections": { + "0": [ + { + "index": "0", + "id": "1634463186563" + }, + { + "index": "1", + "id": "1634488120710" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1634303602169", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "send-to-services", + "x": 426.8833312988281, + "y": 878.5, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1634303685503", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "send-to-services", + "x": 600.8833312988281, + "y": 341.5, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1634303743260", + "component": "httprequest", + "tab": "1612772287426", + "name": "192.168.252.2:8004/sentmessage", + "reference": "", + "x": 506.8833312988281, + "y": 1331.7333374023438, + "connections": { + "0": [ + { + "index": "0", + "id": "1635327431236" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "url": "http://192.168.252.2:8004/sentmessage", + "method": "POST", + "stringify": "json" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1634463186563", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 305.75, + "y": 1442, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634464580289", + "component": "code", + "tab": "1612772287426", + "name": "Code", + "x": 245, + "y": 787, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465243324" + }, + { + "index": "0", + "id": "1634303602169" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "keepmessage": true, + "code": "let response = {};\nresponse.cpu = value.cpu;\nresponse.uptime = value.uptime;\n\nsend(0, response);", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1634465243324", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 428, + "y": 784, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634465281992", + "component": "code", + "tab": "1612772287426", + "name": "Code", + "x": 245, + "y": 884, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465338103" + }, + { + "index": "0", + "id": "1634303602169" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "keepmessage": true, + "code": "value.sender = \"ram\";\n\nlet response = {};\n\nresponse.memory_total = Math.round(value.total / (1024 ** 2));\nresponse.memory_free = Math.round(value.free / (1024 ** 2));\nresponse.memory_used = Math.round(value.used / (1024 ** 2));\n\nsend(0, response);", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1634465338103", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 429, + "y": 976, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634465821120", + "component": "code", + "tab": "1612772287426", + "name": "Code", + "x": 245, + "y": 978, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465892500" + }, + { + "index": "0", + "id": "1634303602169" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "keepmessage": true, + "code": "value.sender = \"hdd\";\n\nlet response = {};\n\nresponse.hdd_total = Math.round(value.total / (1024 ** 2));\nresponse.hdd_free = Math.round(value.free / (1024 ** 2));\nresponse.hdd_used = Math.round(value.used / (1024 ** 2));\n\nsend(0, response);", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1634465892500", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 432, + "y": 1068, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634484067516", + "component": "debug", + "tab": "1612772287426", + "name": "Send info", + "x": 513, + "y": 1441, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634488120710", + "component": "infosender", + "tab": "1612772287426", + "name": "Info sender", + "x": 301, + "y": 1336, + "connections": { + "0": [ + { + "index": "0", + "id": "1634484067516" + }, + { + "index": "0", + "id": "1634303743260" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "edge": "undefined" + }, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1635327431236", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 837.8833312988281, + "y": 1325.5, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1635936391935", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "send-to-services", + "x": 753, + "y": 623, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1637069803394", + "component": "monitorconsumption", + "tab": "1612772287426", + "name": "CPU", + "x": 69, + "y": 791, + "connections": { + "0": [ + { + "index": "0", + "id": "1634464580289" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "49.2% / 69.91 MB", + "color": "gray" + }, + "options": { + "monitorfiles": true, + "monitorconnections": true, + "monitorsize": true, + "monitorconsumption": true, + "enabled": true, + "interval": 30000 + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1683664161036", + "component": "debug", + "tab": "1615551125555", + "name": "CMDtoDIDO", + "x": 392, + "y": 1012, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1683981346282", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "from-dido-controller", + "x": 112, + "y": 459, + "connections": { + "0": [ + { + "index": "0", + "id": "1684055037116" + }, + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "from-dido-controller", + "color": "gray" + }, + "options": { + "wirename": "from-dido-controller" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1684055037116", + "component": "debug", + "tab": "1615551125555", + "name": "from dido to cmd", + "x": 451, + "y": 532, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1684060205000", + "component": "debug", + "tab": "1615551125555", + "name": "HTTP routes", + "x": 450, + "y": 639, + "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": "MDBToDido", + "x": 598, + "y": 147, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1699963668903", + "component": "dido_controller", + "tab": "1615551125555", + "name": "DIDO_Controller", + "x": 397, + "y": 1131, + "connections": { + "0": [ + { + "index": "0", + "id": "1617104731852" + } + ], + "1": [ + { + "index": "0", + "id": "1617104731852" + }, + { + "index": "0", + "id": "1617115013095" + } + ], + "2": [ + { + "index": "0", + "id": "1618393583970" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "edge": "undefined" + }, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1699964678894", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "modbus_to_dido", + "x": 96, + "y": 924, + "connections": { + "0": [ + { + "index": "0", + "id": "1699963668903" + }, + { + "index": "0", + "id": "1699964793925" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "modbus_to_dido", + "color": "gray" + }, + "options": { + "wirename": "modbus_to_dido" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1699964793925", + "component": "debug", + "tab": "1615551125555", + "name": "modbusToDido", + "x": 388, + "y": 920, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1699965957410", + "component": "modbus_reader", + "tab": "1611921777196", + "name": "Modbus reader", + "x": 232, + "y": 175, + "connections": { + "0": [ + { + "index": "0", + "id": "1611951142547" + } + ], + "1": [ + { + "index": "0", + "id": "1621340721628" + }, + { + "index": "0", + "id": "1684179110403" + }, + { + "index": "0", + "id": "1717441414646" + } + ], + "2": [ + { + "index": "0", + "id": "1615809595184" + }, + { + "index": "0", + "id": "1714752862828" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1700411878636", + "component": "thermometer", + "tab": "1611921777196", + "name": "Thermometer", + "x": 234.75, + "y": 444, + "connections": { + "0": [ + { + "index": "0", + "id": "1615802995322" + } + ], + "1": [ + { + "index": "0", + "id": "1615809595184" + }, + { + "index": "0", + "id": "1615809128443" + } + ], + "2": [ + { + "index": "0", + "id": "1621340721628" + }, + { + "index": "0", + "id": "1732889185927" + }, + { + "index": "0", + "id": "1717441414646" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#5CB36D", + "notes": "" + }, + { + "id": "1714752862828", + "component": "debug", + "tab": "1611921777196", + "name": "MDBToTb", + "x": 766, + "y": 324, + "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": 764.0833282470703, + "y": 222, + "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\telse if(value.status === \"NOK-thermometer\")\n\t{\n\t\tsend(0, {\"thermometer\": \"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\telse if(value.values.hasOwnProperty(\"temperature\"))\n\t{\n\t\tsend(0, {\"thermometer\": \"OK\"});\n\t}\n}", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1717442627834", + "component": "debug", + "tab": "1611921777196", + "name": "modbus service", + "x": 966.0833282470703, + "y": 165, + "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": 968.0833282470703, + "y": 268, + "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": 88.75, + "y": 1685, + "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": 296, + "y": 1671, + "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\", \"Flow has been restarted\", \"Node db has changed\"]", + "types": "[\"emergency\", \"critical\", \"error\", \"alert\"]", + "name": "" + }, + "color": "#30E193", + "notes": "" + }, + { + "id": "1718016073501", + "component": "httprequest", + "tab": "1612772287426", + "name": "http://192.168.252.2:8004/slack", + "x": 495, + "y": 1753, + "connections": { + "0": [ + { + "index": "0", + "id": "1718016086212" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "url": "http://192.168.252.2:8004/slack", + "method": "POST", + "stringify": "json" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1718016086212", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 832, + "y": 1664, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "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": 87, + "y": 1591, + "connections": { + "0": [ + { + "index": "0", + "id": "1718016052341" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "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\": \"\" } } } ] }", + "datatype": "object" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1729855334955", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "platform-rpc-call", + "x": 599.9333343505859, + "y": 541.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "platform-rpc-call", + "color": "gray" + }, + "options": { + "wirename": "platform-rpc-call" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1729855371093", + "component": "debug", + "tab": "1612772287426", + "name": "rpc cloud", + "x": 601.9333343505859, + "y": 440.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1731068658334", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 75.75, + "y": 184, + "connections": { + "0": [ + { + "index": "0", + "id": "1612776786008" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731068754606", + "component": "cloudmqttconnect", + "tab": "1612772287426", + "name": "MQTT to senica-prod01", + "x": 284.75, + "y": 452, + "connections": { + "1": [ + { + "index": "0", + "id": "1729855371093" + }, + { + "index": "0", + "id": "1729855334955" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Connected", + "color": "green" + }, + "options": { + "username": "", + "clientid": "", + "port": "2764", + "host": "192.168.252.2", + "topic": "" + }, + "color": "#888600", + "notes": "" + }, + { + "id": "1731069001548", + "component": "db_init", + "tab": "1612772287426", + "name": "DB Initialization", + "x": 1003.75, + "y": 240.25, + "connections": { + "0": [ + { + "index": "0", + "id": "1731069033416" + } + ], + "1": [ + { + "index": "0", + "id": "1747561603739" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#888600", + "notes": "" + }, + { + "id": "1731069033416", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "db-init", + "x": 1244.75, + "y": 233.25, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069059135", + "component": "showdb", + "tab": "1612772287426", + "name": "Show db data", + "x": 1186.75, + "y": 821.25, + "connections": { + "0": [ + { + "index": "0", + "id": "1731069079243" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#888600", + "notes": "" + }, + { + "id": "1731069079243", + "component": "debug", + "tab": "1612772287426", + "name": "dbData", + "x": 1390.75, + "y": 870.25, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1731069116691", + "component": "trigger", + "tab": "1612772287426", + "name": "settings", + "x": 934.75, + "y": 669.75, + "connections": { + "0": [ + { + "index": "0", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069131637", + "component": "trigger", + "tab": "1612772287426", + "name": "relaysData", + "x": 876.75, + "y": 733.75, + "connections": { + "0": [ + { + "index": "1", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069137374", + "component": "trigger", + "tab": "1612772287426", + "name": "nodesData", + "x": 852.75, + "y": 794.75, + "connections": { + "0": [ + { + "index": "2", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069179846", + "component": "trigger", + "tab": "1612772287426", + "name": "pinsData", + "x": 850.75, + "y": 861.75, + "connections": { + "0": [ + { + "index": "3", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069192937", + "component": "trigger", + "tab": "1612772287426", + "name": "sample data", + "x": 857.75, + "y": 928.75, + "connections": { + "0": [ + { + "index": "4", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069264443", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 63.75, + "y": 1279, + "connections": { + "0": [ + { + "index": "0", + "id": "1634488120710" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069334626", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "db-init", + "x": 172.88333129882812, + "y": 129, + "connections": { + "0": [ + { + "index": "0", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069548145", + "component": "virtualwirein", + "tab": "1611921777196", + "name": "db-init", + "x": 46.75, + "y": 192, + "connections": { + "0": [ + { + "index": "0", + "id": "1699965957410" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069567152", + "component": "virtualwirein", + "tab": "1611921777196", + "name": "db-init", + "x": 44.75, + "y": 465, + "connections": { + "0": [ + { + "index": "0", + "id": "1700411878636" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731070156936", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "db-init", + "x": 126.88333129882812, + "y": 1377, + "connections": { + "0": [ + { + "index": "2", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731234189516", + "component": "trigger", + "tab": "1612772287426", + "name": "monitor.txt", + "x": 882.75, + "y": 991.75, + "connections": { + "0": [ + { + "index": "5", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731234189551", + "component": "trigger", + "tab": "1612772287426", + "name": "err.txt", + "x": 904.75, + "y": 1053.75, + "connections": { + "0": [ + { + "index": "6", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1732700042559", + "component": "nodesdb_change_check", + "tab": "1612772287426", + "name": "Nodes DB change check", + "x": 266.8833312988281, + "y": 1980.2333984375, + "connections": { + "0": [ + { + "index": "0", + "id": "1732700071298" + }, + { + "index": "0", + "id": "1732700642917" + } + ], + "1": [ + { + "index": "0", + "id": "1759958914348" + }, + { + "index": "0", + "id": "1759959003114" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#888600", + "notes": "" + }, + { + "id": "1732700057052", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 76.75, + "y": 1988, + "connections": { + "0": [ + { + "index": "0", + "id": "1732700042559" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1732700071298", + "component": "debug", + "tab": "1612772287426", + "name": "nodesChange", + "x": 571.8833312988281, + "y": 2018.2333984375, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1732700642917", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "tb-push", + "x": 567.8833312988281, + "y": 1933, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1732889185927", + "component": "debug", + "tab": "1611921777196", + "name": "tempToDido", + "x": 594.8833312988281, + "y": 753, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1733574412965", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 72.75, + "y": 474, + "connections": { + "0": [ + { + "index": "1", + "id": "1731068754606" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1747561603739", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "send-to-services", + "x": 1243.8833312988281, + "y": 334.5, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1747562867845", + "component": "comment", + "tab": "1612772287426", + "name": "FLOW STARTING POINT", + "x": 1003.5666656494141, + "y": 178, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#704cff", + "notes": "" + }, + { + "id": "1749211698385", + "component": "trigger", + "tab": "1612772287426", + "name": "deviceStatus", + "x": 911.75, + "y": 1116.75, + "connections": { + "0": [ + { + "index": "7", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1757006030239", + "component": "httprequest", + "tab": "1615551125555", + "name": "192.168.252.2:8015/daily_report", + "x": 756.5666656494141, + "y": 715.4499969482422, + "connections": { + "0": [ + { + "index": "0", + "id": "1757006045804" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "stringify": "json", + "method": "POST", + "url": "http://192.168.252.2:8015/daily_report" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1757006045804", + "component": "debug", + "tab": "1615551125555", + "name": "ddd", + "x": 1091.566665649414, + "y": 711.4499969482422, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1757006060377", + "component": "debug", + "tab": "1615551125555", + "name": "reportDebug", + "x": 749.5666656494141, + "y": 799.4499969482422, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1759958914348", + "component": "httprequest", + "tab": "1612772287426", + "name": "http://192.168.252.2:8015/node_numbers", + "x": 571, + "y": 2111, + "connections": { + "0": [ + { + "index": "0", + "id": "1759958927094" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "stringify": "json", + "method": "POST", + "url": "http://192.168.252.2:8015/node_numbers" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1759958927094", + "component": "debug", + "tab": "1612772287426", + "name": "nodesChangeCloud", + "x": 951.8833312988281, + "y": 2109.2333984375, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1759959003114", + "component": "debug", + "tab": "1612772287426", + "name": "nodeChangeCloud1", + "x": 574, + "y": 2218, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1760020290879", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 84.75, + "y": 1787, + "connections": { + "0": [ + { + "index": "1", + "id": "1718016052341" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + } + ], + "version": 615 +} diff --git a/RVO20/flow/dido_controller.js b/RVO20/flow/dido_controller.js new file mode 100755 index 0000000..d16fb19 --- /dev/null +++ b/RVO20/flow/dido_controller.js @@ -0,0 +1,1486 @@ +exports.id = 'dido_controller'; +exports.title = 'DIDO_Controller'; +exports.version = '2.0.0'; +exports.group = 'Worksys'; +exports.color = '#2134B0'; +exports.input = 3; +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 + +state_of_main_switch - reportovat stav hlaveho istica : 0-> off 1-> on +rotary_switch_state - sem by sa mal reportovat stav vstupov manual a auto pola nasledovnej logiky: Manual = 1 a Auto = 0 -> Manu +Manual = 0 a Auto = 0 -> Off, Manual = 0 a Auto = 1 -> Automatic + +door_condition - pin 6, dverový kontakt -> 1 -> vyreportuje Closed, 0 -> vyreportuje Ope +twilight_sensor - hodnotu, ktoru vracia ten analogovy vstup (17) treba poslat sem ako float number. Zrejme tu potom pridame nejaky koeficient prevodu na luxy + +Na kazdu liniu +state_of_breaker - podla indexu istica sa reportuje jeho stav, teda istic na liniu 1: 0-> off, 1-> on +state_of_contactor - podla indexu stkaca sa reportuje jeho stav, teda stykac 1 na liniu 1: 0-> off, 1-> on +*/ + +const { errLogger, logger, monitor } = require('./helper/logger'); +const SerialPort = require('serialport'); +const WebSocket = require('ws'); +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 errorHandler = require('./helper/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 hasMainSwitch; + +let alarmStatus = "OFF"; + +const SEND_TO = { + debug: 0, + tb: 1, + cmd_manager: 2 +} + + +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 = {}; + let rsPortReceivedData = []; + + //to be able to get proper twilight values + let twilight_sensor_interval = 5;//minutes + let twilight_sensor = []; + const twilight_sensor_array = []; + let twilightError = false; + + monitor.info("DIDO_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-we make it global to see it from outside + FLOW.deviceStatus = { //key is device name: temperature,.... + "state_of_main_switch": "Off", //Hlavny istic (alebo druhy dverovy kontakt) + "rotary_switch_state": "Off", //Prevadzkovy + "door_condition": "closed", //Dverový kontakt + "em": "OK", //elektromer rvo + "temperature": "OK", //templomer + "battery": "OK", //Bateria + "power_supply": "OK", //Zdroj + "master_node": "OK", //MN - GLOBALS.settings.masterNodeIsResponding + "no_voltage": "OK", //GLOBALS.settings.no_voltage - vypadok napatia na faze + "state_of_breaker": {}, //"Off",//Istic + "state_of_contactor": {}, //"Off",//Stykac + "twilight_sensor": "OK" //lux sensor + }; + let deviceStatus = FLOW.deviceStatus; + + + function main() { + + GLOBALS = FLOW.GLOBALS; + SETTINGS = FLOW.GLOBALS.settings; + rvoTbName = SETTINGS.rvoTbName; + pinsData = GLOBALS.pinsData; + relaysData = GLOBALS.relaysData; + + tbHandler = new DataToTbHandler(SEND_TO.tb); + tbHandler.setSender(exports.title); + + controller_type = SETTINGS.controller_type; //"lm" or "unipi" + hasMainSwitch = SETTINGS.has_main_switch; + + if (controller_type == "") controller_type = "lm"; + + 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, "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; + } + } + + //report RVO version relaysData[0].tbname; + let values = {}; + values["edge_fw_version"] = SETTINGS.edge_fw_version; + values["maintenance_mode"] = SETTINGS.maintenance_mode; + + sendTelemetry(values, rvoTbName); + + 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); + } + + + function handleRsPort() { + + if (rsPort) { + rsPort.removeAllListeners(); + rsPort = null; + } + + //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('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) { + if (!err) { + monitor.info(exports.title + "--->Digital in_out has been set (runSyncExec was sucessfull)"); + + turnAlarm("off"); + 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('error', err => { + let message = "Dido: rsPort error: " + err.message; + logger.debug(message); + monitor.info(message); + errorHandler.sendMessageToService(message); + }) + + rsPort.on("close", () => { + let message = "Dido: rsPort closed - reconnecting ..."; + logger.debug(message); + monitor.info(message); + setTimeout(handleRsPort, 1000); + }) + + rsPort.open(); + } + + + function handleWebSocket() { + + if (ws) { + ws.removeAllListeners(); + ws = null; + } + + //to keep websocket opened, we send request every 150 seconds + let startRequests = null; + + console.log("handleWebSocket function called"); + ws = new WebSocket('ws:/0.0.0.0:1234/ws'); + + ws.onopen = function open() { + + instance.send(0, exports.title + " running"); + turnAlarm("off"); + + initialSetting(); + + setTimeout(function() { ws.send(JSON.stringify({ cmd: "all" })) }, 5000); + // we request dev info about neuron device from evok to keep websocket connection alive + // for some reason this request returns no data, but connection keeps alive + startRequests = setInterval(() => { + ws.send(JSON.stringify({ "cmd": "filter", "dev": ["neuron"] })); + }, 150000) + }; + + + // 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 = async 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; + + 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 => { + logger.debug('Dido: websocket error', err); + }) + + ws.onclose = function() { + logger.debug('Dido: websocket onclose, reconnecting...') + clearInterval(startRequests); + setTimeout(handleWebSocket, 1000); + } + } + + 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 turnAlarm(onOrOff) { + let value = 0; + if (onOrOff == "on") value = 1; + + if (value == 1 && SETTINGS.maintenance_mode) return; + + alarmStatus = "OFF"; + if (value == 1) alarmStatus = "ON"; + + if (rsPort) { + let arr = [0x55]; + arr.push(13); + arr.push(0); + arr.push(value); + + rsPort.write(Buffer.from(arr), function(err) { + logger.debug(`sirena - ${onOrOff}`); + }); + } + else if (ws) { + let cmd = { "cmd": "set", "dev": "relay", "circuit": "1_01", "value": value }; + ws.send(JSON.stringify(cmd)); + logger.debug(`sirena - ${onOrOff}`); + } + } + + + 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") { + bits.push(0); + } + else bits.push(1); + + if (deviceStatus["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); + } + + + // turn line on or off + function turnLine(onOrOff, line, pin, force, info) { + //onOrOff => "on" or "off" + let value = 0; + if (onOrOff == "on") value = 1; + + if (force == undefined) force = false; + + if (line == 0) { + if (value == 1 && alarmStatus == "ON") turnAlarm("off"); + SETTINGS.maintenance_mode = value ? true : false; + + 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); + return; + } + + if (pin === undefined) pin = getPin(line); + + if (pin === undefined) { + errLogger.error("pin is undefined!", line); + return; + } + + if (!force) { + if (relaysData[line].contactor == value) { + instance.send(SEND_TO.debug, `line is already ${onOrOff} ` + line); + logger.debug(`Dido: turnLine: line is already ${onOrOff} `, line); + return; + } + } + + // if(!rsPort.isOpen && !ws) + if (!rsPort && !ws) { + errLogger.error("Dido - port or websocket is not opened"); + return; + } + + if (rsPort) { + let arr = [0x55]; + arr.push(pin); + arr.push(0); + arr.push(value); + + rsPort.write(Buffer.from(arr), function(err) { + if (err === undefined) { + monitor.info(`Dido: turnLine ${onOrOff} zapisal do rsPort-u`, line, pin, arr, info); + switchLogic(arr); + } + else { + monitor.info(`Dido: turnLine ${onOrOff} WRITE error`, err); + } + }); + + } + else if (ws) { + //pin = "relay1_03" or "input1_01" ... we must make just "1_01" with slice method + monitor.info(`Dido: turnLine ${onOrOff} - (line, pin, force)`, line, pin, force, info); + let cmd = { "cmd": "set", "dev": "relay", "circuit": pin.slice(5), "value": value }; + ws.send(JSON.stringify(cmd)); + } + + //if rvo is 24/7, it has just one switching profile point at 13:00. we do not want to send notification as it repeats every day. + //const d = new Date(); + //if(d.getHours() != 13) sendNotification("Dido_controller: ", SETTINGS.rvoTbName, "switching_profile_point_applied_to_line", { line: line, value: onOrOff }, "", SEND_TO.tb, instance); + } + + + // 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; + + // 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) { + const status = flowdata.data.status; + if (status == "NOK-twilight_sensor") { + deviceStatus["twilight_sensor"] = "NOK"; + } + else if (status == "NOK-em340" || status == "NOK-em111") { + deviceStatus["em"] = "NOK"; + } + else if (status == "NOK-thermometer") { + deviceStatus["temperature"] = "NOK"; + } + } + else if ("values" in flowdata.data) { + 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" + } + else if (values.hasOwnProperty("temperature")) { + deviceStatus["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"; + } + + sendTelemetry(values, rvoTbName); + } + + sendRvoStatus(); + }) + + + + + // we expect array as flowdata.data + instance.on("1", flowdata => { + + //console.log(flowdata.data); + + if (!flowdata.data instanceof Object) return; + + let obj = flowdata.data; + let line = obj.line; + 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"); + }) + + + function calculateStateCode() { + + let bits = []; + + //Hlavny istic - state_of_main_switch => v rvo senica je to druhy door pre silovu cast (EM) + if (deviceStatus["state_of_main_switch"] === "closed" || deviceStatus["state_of_main_switch"] === "Off") { + bits.push(0); + } + else { + bits.push(1); + } + + //Prevadzkovy mod - Manual, Off, Automatic, maintenance_mode = true/false // DAVA 2 BITY + if (!SETTINGS.maintenance_mode) { + if (deviceStatus["rotary_switch_state"] === "Manual") { + bits.push(0); + bits.push(1); + } + + if (deviceStatus["rotary_switch_state"] === "Automatic") { + bits.push(0); + bits.push(0); + } + + if (deviceStatus["rotary_switch_state"] === "Off") { + bits.push(1); + bits.push(0); + } + } + else { + bits.push(1); + bits.push(1); + } + + //Dverovy kontakt + if (deviceStatus["door_condition"] === "closed") { + bits.push(0); + } + else { + bits.push(1); + } + + //EM + if (deviceStatus["em"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //Teplomer + if (deviceStatus["temperature"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //Batéria + if (deviceStatus["battery"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //Zdroj + if (deviceStatus["power_supply"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //MN + if (deviceStatus["master_node"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //výpadok napätia na fáze + if (deviceStatus["no_voltage"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + if (deviceStatus["twilight_sensor"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + // doplnime do 16 bitov (2 byty) + for (let i = bits.length; i < 16; i++) { + bits.push(0); + } + + // console.log("calculateStateCode - deviceStatus", deviceStatus); + // 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; + } + + + async function sendRvoStatus() { + + if (SETTINGS === undefined) return; + SETTINGS.masterNodeIsResponding ? deviceStatus["master_node"] = "OK" : deviceStatus["master_node"] = "NOK"; + + 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 pinsForRvoStatus(controllerType, hasMainSwitch) { + + let pins = []; + + if (controllerType === "lm") { + pins = [1, 4, 6]; + if (hasMainSwitch === 1) { + pins = [4, 6]; + } + } else if (controllerType === "unipi") { + pins = ["input1_01", "input1_04", "input1_05"]; + if (hasMainSwitch === 1) { + pins = ["input1_01", "input1_04"]; + } + } + + return pins; + } + + + function checkRvoStatus() { + + // 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 + //set RVO state + let status = "OK"; + + for (const [key, value] of Object.entries(deviceStatus)) { + if (["em", "twilight_sensor", "temperature", "master_node"].includes(key) && value === "NOK") status = "NOK"; + } + + if (status === "OK") { + + let pinIndexes = pinsForRvoStatus(controller_type, hasMainSwitch); + + for (const pinIndex of pinIndexes) { + if (previousValues[pinIndex] === 0) { + if ((pinIndex === 6 || pinIndex === 'input1_01' || pinIndex === 'input1_05') && SETTINGS.maintenance_mode) continue; + status = "NOK"; + break; + } + } + } + + // battery status. If value is 1 - battery is NOK + if (previousValues[5] === 1) status = "NOK"; + if (SETTINGS.no_voltage.size > 0) status = "NOK"; + + // console.log("rvo status",status) + return status; + } + + + // we pass array to function in case of rsPort ==> switchLogic([55,3,0,1]) ==> [[55,3,0,1]] + // we pass two values in case of websocket ==> switchLogic("relay1_03",1) ==> ["relay1_03",1] + const switchLogic = (...args) => { + + let values = {}; + let pinIndex, newPinValue, twilight; + + //data from rsPort + if (args.length == 1) { + pinIndex = args[0][1] + 1; + if (pinIndex === 17) pinIndex--; + newPinValue = args[0][3]; + twilight = args[0][2]; + } + //data from websocket + else { + pinIndex = args[0]; + newPinValue = args[1]; + } + + 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; + + //default value + let value = "On"; + if (newPinValue === 0) value = "Off"; + + //Hlavny istic + if (type === "state_of_main_switch" && hasMainSwitch) { + if (newPinValue === 0 && newPinValue !== previousValues[pinIndex]) { + sendNotification("switchLogic", rvoTbName, "main_switch_has_been_turned_off", {}, "", SEND_TO.tb, instance, "state_of_main_switch"); + 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"); + deviceStatus["state_of_main_switch"] = "On"; + } + } + + //Prevadzkovy mod + 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"; + + deviceStatus["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, "power_supply_has_disconnected_input", {}, "", SEND_TO.tb, instance, "power_supply"); + + deviceStatus["power_supply"] = "NOK"; + } + else if (newPinValue === 1 && newPinValue !== previousValues[pinIndex]) { + sendNotification("switchLogic", rvoTbName, "power_supply_works_correctly", {}, "", SEND_TO.tb, instance, "power_supply"); + + deviceStatus["power_supply"] = "OK"; + } + } + + //Bateria - 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"); + + deviceStatus["battery"] = "NOK"; + } + else if (newPinValue === 0 && newPinValue !== previousValues[pinIndex]) { + sendNotification("switchLogic", rvoTbName, "battery_level_is_ok", {}, "", SEND_TO.tb, instance, "battery_level"); + + deviceStatus["battery"] = "OK"; + } + } + + //Dverovy kontakt - pin 6 + //! Ak je rvo s dvoma dverovymi kontaktami, ked pride z evoku signal z input1_05, co bol predytm "state_of_main switch" handlujeme ho teraz ako 'door_condition' + else if (type == "door_condition" || type === "state_of_main_switch") { + newPinValue === 0 ? value = "open" : value = "closed"; + + let door = "door_main"; + if (type === "state_of_main_switch") door = "door_em"; + + if (value === "open") { + if (SETTINGS.maintenance_mode) { + sendNotification("switchLogic", rvoTbName, door + "_open", {}, "", SEND_TO.tb, instance, door); + } else { + sendNotification("switchLogic", rvoTbName, door + "_open_without_permission", {}, "", SEND_TO.tb, instance, door); + + // 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 (value === "closed") { + if (alarmStatus == "ON") turnAlarm("off"); + sendNotification("switchLogic", rvoTbName, door + "_close", {}, "", SEND_TO.tb, instance, door); + } + + deviceStatus[type] = value; + } + + //lux sensor + else if (type == "twilight_sensor") { + //! TODO - to show nok status, if lux value is not changing more then 10 times. + //Daylight is far more than 1000. So most of the day, when it is sunshine comes just value 1000. But lux sensor is not NOK. + //This is not the case in LM. If value from LM is the same 10x, there is 99% possibility, that sensor is NOK. + value = newPinValue; + + if (controller_type === 'lm') { + value = parseFloat(newPinValue + (256 * twilight)); + + 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 && !twilightError) { + twilightError = true; + let value = twilight_sensor_array.shift(); + + newPinValue = 0; + } + else if (set.size !== 1 && twilightError) { + //sendNotification("switchLogic", rvoTbName, 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) { + 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); + } + } + + 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); + } + + deviceStatus["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 (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 }); + + //mame iba 3 istice. vyreportujeme a ohandlujeme liniu na tom istom istici ako paralelna linia (napr linia 1, paralelna s nou je linia 4, key je string "4") + // ak je 7 linii, na 1 istici je linia 1,4,7 + + if (line == 1) { + + const lineOnSameBraker = [4, 7]; + + for (var i = 0; i < lineOnSameBraker.length; i++) { + if (!relaysData.hasOwnProperty(lineOnSameBraker[i])) continue; + + 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; + reportLineStatus(lineOnSameBraker[i]); + + values[type] = value; + const tbname = relaysData[lineOnSameBraker[i]].tbname; + sendTelemetry(values, tbname); + + delete values[type]; + } + + } + else { + const lineOnSameBraker = line + 3 + ""; + + if (relaysData.hasOwnProperty(lineOnSameBraker)) { + 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; + reportLineStatus(line + 3); + + values[type] = value; + const tbname = relaysData[lineOnSameBraker].tbname; + sendTelemetry(values, tbname); + + delete values[type]; + } + } + + } + + if (value == "Off") values["status"] = "NOK"; + deviceStatus["state_of_breaker"][line] = value; + + reportLineStatus(line); + } + else return; + + values[type] = value; + + if (type == "rotary_switch_state") { + if (SETTINGS.maintenance_mode) value = "maintenance"; + value = value.toLowerCase(); + values["power_mode"] = value; + } + + if (newPinValue != previousValues[pinIndex]) previousValues[pinIndex] = newPinValue; + if (Object.keys(values).length > 0 && tbname) sendTelemetry(values, tbname); + } + + + function sendTelemetry(values, tbname, date = Date.now()) { + let dataToTb = { + [tbname]: [ + { + "ts": date, + "values": values + } + ] + }; + + tbHandler.sendToTb(dataToTb, instance); + } + + + function isObject(item) { + return (typeof item === "object" && !Array.isArray(item) && item !== null); + } + +} //end of 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 +// *|input1_01|state_of_main_switch|0|........... +// *|input1_02|rotary_switch_state|0|........... +// *|input1_03|rotary_switch_state|0|........... +// *|intut1_04|power_supply|0|........... +// *|input1_05|door_condition|0|........... +// *|input1_06|state_of_breaker|1|........... +// *|input1_07|state_of_breaker|2|........... +// *|input1_08|state_of_breaker|3|........... +// *|relay1_02|state_of_contactor|1|........... +// *|relay1_03|state_of_contactor|2|........... +// *|relay1_04|state_of_contactor|3|........... +// *|287D8776E0013CE9|temperature|0|........... + + +//! pins_data --> from UNIPI +// { +// 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 } +// } + +//! relays_data +// { +// '0': { +// line: 0, +// tbname: 'KjbN4q7JPZmexgdnz2yKQ98YAWwO0Q3BMX6ERLoV', +// contactor: 1, +// profile: '' +// }, +// '1': { +// line: 1, +// tbname: 'RMgnK93rkoAazbqdQ4yBG95Z1YXGx6pmwBeVEP2O', +// contactor: 0, +// profile: '{"intervals":[{"value":0,"end_time":"20:00","start_time":"13:00"},{"value":1,"end_time":"10:00","start_time":"20:00"},{"value":0,"end_time":"10:20","start_time":"10:00"},{"value":1,"end_time":"10:40","start_time":"10:20"},{"value":0,"end_time":"11:00","start_time":"10:40"},{"value":1,"end_time":"11:30","start_time":"11:00"},{"value":0,"end_time":"11:50","start_time":"11:30"},{"value":1,"end_time":"13:00","start_time":"11:50"}],"astro_clock":false,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' +// }, +// '2': { +// line: 2, +// tbname: 'dlE1VQjYrNx9gZRmb38gG08oLBO4qaAk2M6JPnG7', +// contactor: 0, +// profile: '{"intervals":[{"value":0,"end_time":"20:00","start_time":"13:00"},{"value":1,"end_time":"10:00","start_time":"20:00"},{"value":0,"end_time":"10:20","start_time":"10:00"},{"value":1,"end_time":"10:40","start_time":"10:20"},{"value":0,"end_time":"11:00","start_time":"10:40"},{"value":1,"end_time":"11:30","start_time":"11:00"},{"value":0,"end_time":"11:50","start_time":"11:30"},{"value":1,"end_time":"13:00","start_time":"11:50"}],"astro_clock":false,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' +// }, +// '3': { +// line: 3, +// tbname: 'vnmG4kJxaXWNBgMQq0D7Aj5e9oZzOAlr6LdR3w2V', +// contactor: 0, +// profile: '{"intervals":[{"value":0,"end_time":"20:30","start_time":"13:00"},{"value":1,"end_time":"00:10","start_time":"20:30"},{"value":0,"end_time":"13:00","start_time":"05:40"},{"value":1,"end_time":"05:40","start_time":"00:10"}],"astro_clock":true,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' +// } +// } + + + + + +// { +// "jbN4q7JPZmexgdnz2yKbWGDYAWwO0Q3BMX6ERLoV": [ +// { +// "ts": 1700409326353, +// "values": { +// "_event": { +// "type": "notice", +// "status": "new", +// "source": { +// "func": "rsPort.open()", +// "component": "1700343402190", +// "component_name": "DIDO_Controller", +// "edge": "jbN4q7JPZmexgdnz2yKbWGDYAWwO0Q3BMX6ERLoV" +// }, +// "message": "al_shariff_10.0.0.38: FLOW has been started ", +// "message_data": "" +// } +// } +// } +// ] +// } diff --git a/RVO20/flow/helper/DataToTbHandler.js b/RVO20/flow/helper/DataToTbHandler.js new file mode 100755 index 0000000..716ef7b --- /dev/null +++ b/RVO20/flow/helper/DataToTbHandler.js @@ -0,0 +1,187 @@ +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; + this.itIsNodeReadout = false; + this.sender = ""; + + // if attribute change difference is less than limit value, we do not send to tb. + this.attributeChangeLimit = { + temperature: 0.5, + Phase_1_voltage: 2, + Phase_2_voltage: 2, + Phase_3_voltage: 2, + Phase_1_current: 0.1, + Phase_2_current: 0.1, + Phase_3_current: 0.1, + Phase_1_power: 2, + Phase_2_power: 2, + Phase_3_power: 2, + total_power: 2, + total_energy: 1, + Phase_1_pow_factor: 0.1, + Phase_2_pow_factor: 0.1, + Phase_3_pow_factor: 0.1, + power_factor: 0.1, + lifetime: 2, + voltage: 2, + power: 2, + frequency: 3, + energy: 0.1, + current: 2, + inclination_x: 10, + inclination_y: 10, + inclination_z: 10 + }; + + } + + dump() { + console.log("----------------------------"); + console.log("previousValues", this.previousValues); + console.log("----------------------------"); + } + + setSender(sender) { + this.sender = sender; + } + + isEmptyObject(obj) { + for (var _ in obj) { + return false; + } + return true; + } + + + sendToTb(data, instance) { + + //not to modify data object, we do deep copy: + let dataCopy = JSON.parse(JSON.stringify(data)); + + let keys = Object.keys(dataCopy); + + if (keys.length == 0) { + if (this.debug) console.log("sendToTb received empty object", dataCopy); + return; + } + + let tbname = keys[0]; + let ts; + + let arrayOfValues = dataCopy[tbname]; + let arrayOfValuesToSend = []; + + for (let i = 0; i < arrayOfValues.length; i++) { + + ts = arrayOfValues[i].ts; + let values = this.prepareValuesForTb(tbname, ts, arrayOfValues[i].values); + + if (!this.isEmptyObject(values)) { + arrayOfValuesToSend.push({ ts: ts, values: values }); + } + + } + + if (arrayOfValuesToSend.length == 0) { + //if(this.debug) console.log("data not sent - empty array"); + return; + } + + this.messageCounter++; + + let dataToTbModified = { + [tbname]: arrayOfValuesToSend + } + + //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); + instance.send(this.index, dataToTbModified); + } + + + getDiffTimestamp(key) { + //TODO set different value for given key!!! + //if(key == "status") this.timeToHoldTbValue = 2*60*60;//2h + return this.timeToHoldTbValue * 1000; + } + + + prepareValuesForTb(tbname, timestamp, values) { + + let keys = Object.keys(values); + + if (keys.includes("lifetime")) this.itIsNodeReadout = true; + + if (!this.previousValues.hasOwnProperty(tbname)) { + this.previousValues[tbname] = {}; + } + + //if(this.debug) console.log("prepareValuesForTb", tbname, timestamp, values); + + for (let i = 0; i < keys.length; i++) { + + let key = keys[i]; + let value = values[key]; + + if (!this.previousValues[tbname].hasOwnProperty(key)) { + this.previousValues[tbname][key] = { ts: timestamp, value: value }; + continue; + } + + // attributeData ==> {voltage: {ts:333333, value:5}} + let attributeData = this.previousValues[tbname][key]; + let attributeToChange = false; + if (key in this.attributeChangeLimit) attributeToChange = true; + let limit = this.attributeChangeLimit[key]; + let timestampDiffToRemoveKey; + + //this will ensure "node statecode" will be sent just once an hour + if (this.itIsNodeReadout && key === "statecode") { + attributeData.value = value; + this.itIsNodeReadout = false; + timestampDiffToRemoveKey = 1 * 60 * 60 * 1000; // 1 hour + } + + if (key === "twilight_sensor" && value > 100) { + attributeData.value = value; + } + + //if edge, master or node version do not change, send just once a day: + if (["edge_fw_version", "master_node_version", "fw_version"].includes(key)) { + timestampDiffToRemoveKey = 24 * 60 * 60 * 1000; + } + + if (attributeData.value === value || attributeToChange && Math.abs(attributeData.value - value) < limit) { + + let diff = timestamp - attributeData.ts; + if (!timestampDiffToRemoveKey) timestampDiffToRemoveKey = this.getDiffTimestamp(key); + + if (diff > timestampDiffToRemoveKey) { + attributeData.ts = Date.now(); + //if(this.debug) console.log(this.sender + ": update ts for key", key, "diff is", diff, "messageCounter", this.messageCounter); + } + else { + delete values[key]; + //if(this.debug) console.log(this.sender + ": delete key", key, "diff is", diff, "messageCounter", this.messageCounter, timestampDiffToRemoveKey); + } + } + else { + attributeData.value = value; + attributeData.ts = timestamp; + } + + } + + return values; + } +} + +module.exports = DataToTbHandler; + diff --git a/RVO20/flow/helper/ErrorToServiceHandler.js b/RVO20/flow/helper/ErrorToServiceHandler.js new file mode 100755 index 0000000..2b27c32 --- /dev/null +++ b/RVO20/flow/helper/ErrorToServiceHandler.js @@ -0,0 +1,91 @@ +const { MD5 } = require('./md5.js'); +const { networkInterfaces } = require('os'); + +class ErrorToServiceHandler { + constructor() { + this.previousValues = {}; + + this.project_id = undefined; + + const nets = networkInterfaces(); + this.ipAddresses = {}; + + for (const name of Object.keys(nets)) { + for (const net of nets[name]) { + // Skip over non-IPv4 and internal (i.e. 127.0.0.1) addresses + if (net.family === 'IPv4' && !net.internal) { + if (!this.ipAddresses[name]) { + this.ipAddresses[name] = []; + } + this.ipAddresses[name].push(net.address); + } + } + } + } + + setProjectId(project_id) { + this.project_id = project_id; + } + + processMessage(message, seconds) { + if (Array.isArray(message)) message = message.join(', '); + + let key = MD5(message); + let ts = Date.now(); + + //keep in memory - default value is 1h + if (seconds === undefined) seconds = 60 * 60; + + if (!this.previousValues.hasOwnProperty(key)) { + this.previousValues[key] = { ts: ts, duration: seconds }; + } + + let diff = (ts - this.previousValues[key].ts); + if (diff < this.previousValues[key].duration * 1000) return false; + + this.previousValues[key].ts = ts; + + return message; + } + + sendMessageToService(message, seconds, message_type) { + + // if error occures too early FLOW.GLOBALS.settings.project_id is still undefined + if (this.project_id === undefined) { + console.log("ErrorToServiceHandler.js: no project_id"); + return; + } + + let f = this.processMessage(message, seconds); + if (f === false) return; + + if (message_type === undefined) message_type = "error_message"; + + let toService = { + id: this.project_id, + ipAddresses: this.ipAddresses + }; + + //js_error || error_message + toService[message_type] = message; + + console.log("ErrorToServiceHandler------------------------>send to service", toService); + + RESTBuilder.make(function(builder) { + builder.method('POST'); + builder.post(toService); + builder.url('http://192.168.252.2:8004/sentmessage'); + + builder.callback(function(err, response, output) { + console.log("process.on error send", err, response, output, toService); + }); + }); + + } +} + +const errorHandler = new ErrorToServiceHandler(); + + +module.exports = errorHandler; +//module.exports = ErrorToServiceHandler; diff --git a/RVO20/flow/helper/db_helper.js b/RVO20/flow/helper/db_helper.js new file mode 100755 index 0000000..40e796c --- /dev/null +++ b/RVO20/flow/helper/db_helper.js @@ -0,0 +1,44 @@ +function promisifyBuilder(builder) +{ + return new Promise((resolve, reject) => { + + try{ + + builder.callback(function(err, response) { + + if(err != null) reject(err); + resolve(response); + }); + + } catch (error) { + reject(error); + } + }) +} + +function makeMapFromDbResult(response, ...keys) +{ + let s = "-"; + let data = {}; + + for(let i = 0; i < response.length; i++) + { + let record = response[i]; + + let k = []; + for(let j = 0; j < keys.length; j++) + { + k.push( record[keys[j]] ); + } + + let key = k.join(s); + data[ key ] = record; + } + + return data; +} + +module.exports = { + promisifyBuilder, + makeMapFromDbResult + } \ No newline at end of file diff --git a/RVO20/flow/helper/logger.js b/RVO20/flow/helper/logger.js new file mode 100755 index 0000000..2585639 --- /dev/null +++ b/RVO20/flow/helper/logger.js @@ -0,0 +1,30 @@ +//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/RVO20/flow/helper/md5.js b/RVO20/flow/helper/md5.js new file mode 100755 index 0000000..d3b0480 --- /dev/null +++ b/RVO20/flow/helper/md5.js @@ -0,0 +1,5 @@ +function MD5(d){var r = M(V(Y(X(d),8*d.length)));return r.toLowerCase()};function M(d){for(var _,m="0123456789ABCDEF",f="",r=0;r>>4&15)+m.charAt(15&_);return f}function X(d){for(var _=Array(d.length>>2),m=0;m<_.length;m++)_[m]=0;for(m=0;m<8*d.length;m+=8)_[m>>5]|=(255&d.charCodeAt(m/8))<>5]>>>m%32&255);return _}function Y(d,_){d[_>>5]|=128<<_%32,d[14+(_+64>>>9<<4)]=_;for(var m=1732584193,f=-271733879,r=-1732584194,i=271733878,n=0;n>16)+(_>>16)+(m>>16)<<16|65535&m}function bit_rol(d,_){return d<<_|d>>>32-_} + +module.exports = { + MD5 +} \ No newline at end of file diff --git a/RVO20/flow/helper/notification_reporter.js b/RVO20/flow/helper/notification_reporter.js new file mode 100755 index 0000000..839c12c --- /dev/null +++ b/RVO20/flow/helper/notification_reporter.js @@ -0,0 +1,121 @@ +//key is device, value = message {} +let sentValues = {}; +let notificationsData = null; +let rvoName; + +//sendNotification("CMD Manager: process cmd", SETTINGS.rvoTbName, "dimming_profile_was_successfully_received_by_node", { node: node }, "", SEND_TO.tb, instance); + +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 +}; + +function getKey(map, val) { + return Object.keys(map).findItem(key => map[key] === val); +} + +//https://stackoverflow.com/questions/41117799/string-interpolation-on-variable +var template = (tpl, args) => tpl.replace(/\${(\w+)}/g, (_, v) => args[v]); + + +function initNotification() { + notificationsData = FLOW.GLOBALS.notificationsData; + rvoName = FLOW.GLOBALS.settings.rvo_name; +} + + +function sendNotification(func, device, key, params, extra, tb_output, instance, saveKey) { + + let storeToSendValues = true; + if (saveKey == undefined) storeToSendValues = false; + + let weight = ""; + let message = {}; + + let notification = notificationsData[key]; + + if (notification) { + weight = notification.weight.toLowerCase(); + + Object.keys(notification).forEach(item => { + if (["en", "sk", "de", "cz", "it", "es"].includes(item)) { + message[item] = rvoName + ": " + template(notification[item], params); + } + }) + } + else { + //console.error("sendNotification: Notifications: undefined key", key, func, notificationsData); + console.error("sendNotification: Notifications: undefined key", key, func); + return false; + } + + //detect invalid err weight + if (getKey(ERRWEIGHT, weight) == undefined) { + console.error("sendNotification: Notifications: undefined weight", weight, key, func); + return false; + } + + if (sentValues.hasOwnProperty(saveKey)) { + if (JSON.stringify(sentValues[saveKey]) == JSON.stringify(message)) { + return false; + } + } + + if (sentValues[saveKey] == undefined) { + if (storeToSendValues) { + //do not send - flow is was started + sentValues[saveKey] = message; + return false; + } + } + + if (storeToSendValues) sentValues[saveKey] = message; + + let content = { + "type": weight, + "status": "new", + "source": { + "func": func, + "component": instance.id, + "component_name": instance.name, + "edge": device + }, + "message": message, + "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 + + return true; + +} + +module.exports = { + sendNotification, + ERRWEIGHT, + initNotification +} + diff --git a/RVO20/flow/helper/register.js b/RVO20/flow/helper/register.js new file mode 100755 index 0000000..fc1d008 --- /dev/null +++ b/RVO20/flow/helper/register.js @@ -0,0 +1,144 @@ +/* +0 - cislo registra / prikaz +1 - recepient - 0 = master, 1 = slave (slave je automaticky group a broadcast) +2 - r/rw - read/write +3- register name - nazov registra / prikazu (len pre info - zobrazenie v aplikacii) + +4,5,6,7, - jednotlive byte-y - nazov byte-u +4-7 - RES. a prazdny string "" sa nezobrazia!!! +*/ + +//124 zaznamov +const registers = [ + ["0","1","R","Status","","",""], + ["1","1","RW","Dimming","R-Channel ","G-Channel","B-Channel ","W - Channel"], + ["2","1","R","Device types","","",".",""], + ["3","1","RW","Group addresses 1-4","Groups Add. 4","Groups Add. 3","Groups Add. 2","Groups Add. 1"], + ["4","1","RW","Group addresses 5-8","Groups Add. 8","Groups Add. 7","Groups Add. 6","Groups Add. 5"], + ["5","1","RW","Serial number (MAC)","","","",""], + ["6","1","RW","Time of dusk","HH","MM","SS","EXTRA"], + ["7","1","RW","Time of dawn","HH","MM","SS","EXTRA"], + ["8","1","RW","Time Schedule settings","TBD","TBD","Movement sensor","Time Schedule"], + ["9","1","RW","TS1 Time point 1","HH","MM","SS","Ext. Device"], + ["10","1","RW","TS1 Time point 1 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["11","1","RW","TS1 Time point 2","HH","MM","SS","Ext. Device"], + ["12","1","RW","TS1 Time point 2 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["13","1","RW","TS1 Time point 3","HH","MM","SS","Ext. Device"], + ["14","1","RW","TS1 Time point 3 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["15","1","RW","TS1 Time point 4","HH","MM","SS","Ext. Device"], + ["16","1","RW","TS1 Time point 4 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["17","1","RW","TS1 Time point 5","HH","MM","SS","Ext. Device"], + ["18","1","RW","TS1 Time point 5 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["19","1","RW","TS1 Time point 6","HH","MM","SS","Ext. Device"], + ["20","1","RW","TS1 Time point 6 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["21","1","RW","TS1 Time point 7","HH","MM","SS","Ext. Device"], + ["22","1","RW","TS1 Time point 7 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["23","1","RW","TS1 Time point 8","HH","MM","SS","Ext. Device"], + ["24","1","RW","TS1 Time point 8 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["25","1","RW","TS1 Time point 9","HH","MM","SS","Ext. Device"], + ["26","1","RW","TS1 Time point 9 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["27","1","RW","TS1 Time point 10","HH","MM","SS","Ext. Device"], + ["28","1","RW","TS1 Time point 10 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["29","1","RW","TS1 Time point 11","HH","MM","SS","Ext. Device"], + ["30","1","RW","TS1 Time point 11 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["31","1","RW","TS1 Time point 12","HH","MM","SS","Ext. Device"], + ["32","1","RW","TS1 Time point 12 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["33","1","RW","TS1 Time point 13","HH","MM","SS","Ext. Device"], + ["34","1","RW","TS1 Time point 13 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["35","1","RW","TS1 Time point 14","HH","MM","SS","Ext. Device"], + ["36","1","RW","TS1 Time point 14 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["37","1","RW","TS1 Time point 15","HH","MM","SS","Ext. Device"], + ["38","1","RW","TS1 Time point 15 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["39","1","RW","TS1 Time point 16","HH","MM","SS","Ext. Device"], + ["40","1","RW","TS1 Time point 16 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["41","1","RW","TS2 Time point 1","HH","MM","SS","Ext. Device"], + ["42","1","RW","TS2 Time point 1 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["43","1","RW","TS2 Time point 2","HH","MM","SS","Ext. Device"], + ["44","1","RW","TS2 Time point 2 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["45","1","RW","TS2 Time point 3","HH","MM","SS","Ext. Device"], + ["46","1","RW","TS2 Time point 3 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["47","1","RW","TS2 Time point 4","HH","MM","SS","Ext. Device"], + ["48","1","RW","TS2 Time point 4 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["49","1","RW","TS2 Time point 5","HH","MM","SS","Ext. Device"], + ["50","1","RW","TS2 Time point 5 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["51","1","RW","TS2 Time point 6","HH","MM","SS","Ext. Device"], + ["52","1","RW","TS2 Time point 6 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["53","1","RW","TS2 Time point 7","HH","MM","SS","Ext. Device"], + ["54","1","RW","TS2 Time point 7 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["55","1","RW","TS2 Time point 8","HH","MM","SS","Ext. Device"], + ["56","1","RW","TS2 Time point 8 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["57","1","RW","TS2 Time point 9","HH","MM","SS","Ext. Device"], + ["58","1","RW","TS2 Time point 9 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["59","1","RW","TS2 Time point 10","HH","MM","SS","Ext. Device"], + ["60","1","RW","TS2 Time point 10 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["61","1","RW","TS2 Time point 11","HH","MM","SS","Ext. Device"], + ["62","1","RW","TS2 Time point 11 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["63","1","RW","TS2 Time point 12","HH","MM","SS","Ext. Device"], + ["64","1","RW","TS2 Time point 12 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["65","1","RW","TS2 Time point 13","HH","MM","SS","Ext. Device"], + ["66","1","RW","TS2 Time point 13 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["67","1","RW","TS2 Time point 14","HH","MM","SS","Ext. Device"], + ["68","1","RW","TS2 Time point 14 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["69","1","RW","TS2 Time point 15","HH","MM","SS","Ext. Device"], + ["70","1","RW","TS2 Time point 15 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["71","1","RW","TS2 Time point 16","HH","MM","SS","Ext. Device"], + ["72","1","RW","TS2 Time point 16 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["73","1","RW","Power meter status","TBD","","",""], + ["74","1","R","Input Voltage","","","",""], + ["75","1","R","Input Current","","","",""], + ["76","1","R","Input Power","","","",""], + ["77","1","R","Cos phi","","","",""], + ["78","1","R","Frequency","","","",""], + ["79","1","RW","Energy","","","",""], + ["80","1","RW","Lifetime","","","",""], + ["81","1","RW","Power on cycles (input)","","","",""], + ["82","1","RW","Power on cycles (relay)","","","",""], + ["83","1","R","Time since last power on","","","",""], + ["84","1","R","Accelerometer data","","","",""], + ["85","1","RW","GPS latitude","pos/neg","deg","min ","sec"], + ["86","1","RW","GPS longitude","pos/neg","deg","min ","sec"], + ["87","1","RW","Actual time","HH","MM","SS","RES."], + ["88","1","RW","Actual date","Day of week","Day","Month","Year"], + ["89","1","R","Production data 1","","","",""], + ["90","1","R","Production data 2","","","",""], + ["91","1","RW","Network ID","NID3","NID2","NID1","NID0"], + ["95","1","RW","Actual Lux level from cabinet","RES.","RES.","HB","LB"], + ["96","1","RW","Threshold lux level","Dusk HB","Dusk LB","Dawn HB","Dawn LB"], + ["97","1","RW","Adjust period","Dusk HB","Dusk LB","Dawn HB","Dawn LB"], + ["98","1","RW","Offset","RES.","RES.","Dusk","Dawn"], + ["99","1","RW","CCT min/max range","max-H","max-L","min-H","min-L"], + ["100","1","RW","DALI interface","Cmd ID","Add","Cmd","Resp"], + ["101","1","RW","Module FW ver","v1","v2","v3","v4"], + ["102","1","RW","Module MAC-H","unused","unused","M1","M2"], + ["103","1","RW","Module MAC-L","M3","M4","M5","M6"], + ["122","1","R","FW update status/control register","Byte3","Byte2","Byte1","Byte0"], + ["123","1","R","FW update - data index","Byte3","Byte2","Byte1","Byte0"], + ["124","1","R","FW update - data","Byte3","Byte2","Byte1","Byte0"], + ["0","0","R","Status","","","",""], + ["1","0","RW","Control register","RES.","RES.","RES.","init mode enable"], + ["2","0","R","Device types","","","",""], + ["3","0","R","Serial number (MAC)","","","",""], + ["4","0","R","Production data 1","","","",""], + ["5","0","R","Production data 2","","","",""], + ["6","0","RW","Network ID","NID3","NID2","NID1","NID0"], + ["7","0","RW","RS232 settings","param.","param.","Baudrate H","Baudrate L"], + ["8","0","R","Accelerometer data","","","",""], + ["9","0","RW","Module FW ver","v1","v2","v3","v4"], + ["10","0","RW","Module MAC-H","unused","unused","M1","M2"], + ["11","0","RW","Module MAC-L","M3","M4","M5","M6"], + ["32","0","RW","FW update status/control register","Byte3","Byte2","Byte1","Byte0"], + ["33","0","RW","FW update - data index","Byte3","Byte2","Byte1","Byte0"], + ["34","0","RW","FW update - data","Byte3","Byte2","Byte1","Byte0"], + ["125","0","RW","Debug Register","Byte3","Byte2","Byte1","Byte0"], + ["126","0","RW","Network Control Register","Byte3","Byte2","Byte1","Byte0"], + ["127","0","R","Network Status Register","Byte3","Byte2","Byte1","Byte0"], + ["128","0","RW","Node XX Serial Number Register","SER3","SER2","SER1","SER0"], + ["256","0","R","Node XX Network Status Register","","","",""] +]; + +let register = {}; + +module.exports = { + registers, + register +} \ No newline at end of file diff --git a/RVO20/flow/helper/serialport_helper.js b/RVO20/flow/helper/serialport_helper.js new file mode 100755 index 0000000..7f5920d --- /dev/null +++ b/RVO20/flow/helper/serialport_helper.js @@ -0,0 +1,99 @@ +const { exec } = require('child_process'); + +function openPort(port) { + return new Promise((resolve, reject) => { + + var callbackError = function(err) { + port.removeListener('error', callbackError); + port.removeListener('open', callbackError); + + reject(err.message); + }; + + var callbackOpen = function(data) { + port.removeListener('error', callbackError); + port.removeListener('open', callbackOpen); + + resolve("port open: ok"); + }; + + port.on('error', callbackError); + port.on('open', callbackOpen); + + port.open(); + + }) +} + +function runSyncExec(command) { + return new Promise((resolve, reject) => { + + exec(command, (error, stdout, stderr) => { + if (error == null) resolve(stdout); + reject(error); + }); + + }) +} + +async function writeData(port, data, readbytes, timeout) { + return new Promise((resolve, reject) => { + + // 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) { + + port.write(Buffer.from(data), function(err) { + if (err) { + reject(err.message); + } + }); + + 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 +} diff --git a/RVO20/flow/helper/suncalc.js b/RVO20/flow/helper/suncalc.js new file mode 100755 index 0000000..c9ca56d --- /dev/null +++ b/RVO20/flow/helper/suncalc.js @@ -0,0 +1,317 @@ +/* + (c) 2011-2015, Vladimir Agafonkin + SunCalc is a JavaScript library for calculating sun/moon position and light phases. + https://github.com/mourner/suncalc +*/ + +(function () { 'use strict'; + +// shortcuts for easier to read formulas + +var PI = Math.PI, + sin = Math.sin, + cos = Math.cos, + tan = Math.tan, + asin = Math.asin, + atan = Math.atan2, + acos = Math.acos, + rad = PI / 180; + +// sun calculations are based on http://aa.quae.nl/en/reken/zonpositie.html formulas + + +// date/time constants and conversions + +var dayMs = 1000 * 60 * 60 * 24, + J1970 = 2440588, + J2000 = 2451545; + +function toJulian(date) { return date.valueOf() / dayMs - 0.5 + J1970; } +function fromJulian(j) { return new Date((j + 0.5 - J1970) * dayMs); } +function toDays(date) { return toJulian(date) - J2000; } + + +// general calculations for position + +var e = rad * 23.4397; // obliquity of the Earth + +function rightAscension(l, b) { return atan(sin(l) * cos(e) - tan(b) * sin(e), cos(l)); } +function declination(l, b) { return asin(sin(b) * cos(e) + cos(b) * sin(e) * sin(l)); } + +function azimuth(H, phi, dec) { return atan(sin(H), cos(H) * sin(phi) - tan(dec) * cos(phi)); } +function altitude(H, phi, dec) { return asin(sin(phi) * sin(dec) + cos(phi) * cos(dec) * cos(H)); } + +function siderealTime(d, lw) { return rad * (280.16 + 360.9856235 * d) - lw; } + +function astroRefraction(h) { + if (h < 0) // the following formula works for positive altitudes only. + h = 0; // if h = -0.08901179 a div/0 would occur. + + // formula 16.4 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + // 1.02 / tan(h + 10.26 / (h + 5.10)) h in degrees, result in arc minutes -> converted to rad: + return 0.0002967 / Math.tan(h + 0.00312536 / (h + 0.08901179)); +} + +// general sun calculations + +function solarMeanAnomaly(d) { return rad * (357.5291 + 0.98560028 * d); } + +function eclipticLongitude(M) { + + var C = rad * (1.9148 * sin(M) + 0.02 * sin(2 * M) + 0.0003 * sin(3 * M)), // equation of center + P = rad * 102.9372; // perihelion of the Earth + + return M + C + P + PI; +} + +function sunCoords(d) { + + var M = solarMeanAnomaly(d), + L = eclipticLongitude(M); + + return { + dec: declination(L, 0), + ra: rightAscension(L, 0) + }; +} + + +var SunCalc = {}; + + +// calculates sun position for a given date and latitude/longitude + +SunCalc.getPosition = function (date, lat, lng) { + + var lw = rad * -lng, + phi = rad * lat, + d = toDays(date), + + c = sunCoords(d), + H = siderealTime(d, lw) - c.ra; + + return { + azimuth: azimuth(H, phi, c.dec), + altitude: altitude(H, phi, c.dec) + }; +}; + + +// sun times configuration (angle, morning name, evening name) + +var times = SunCalc.times = [ + [-0.833, 'sunrise', 'sunset' ], + [ -0.3, 'sunriseEnd', 'sunsetStart' ], + [ -6, 'dawn', 'dusk' ], + [ -12, 'nauticalDawn', 'nauticalDusk'], + [ -18, 'nightEnd', 'night' ], + [ 6, 'goldenHourEnd', 'goldenHour' ] +]; + +// adds a custom time to the times config + +SunCalc.addTime = function (angle, riseName, setName) { + times.push([angle, riseName, setName]); +}; + + +// calculations for sun times + +var J0 = 0.0009; + +function julianCycle(d, lw) { return Math.round(d - J0 - lw / (2 * PI)); } + +function approxTransit(Ht, lw, n) { return J0 + (Ht + lw) / (2 * PI) + n; } +function solarTransitJ(ds, M, L) { return J2000 + ds + 0.0053 * sin(M) - 0.0069 * sin(2 * L); } + +function hourAngle(h, phi, d) { return acos((sin(h) - sin(phi) * sin(d)) / (cos(phi) * cos(d))); } +function observerAngle(height) { return -2.076 * Math.sqrt(height) / 60; } + +// returns set time for the given sun altitude +function getSetJ(h, lw, phi, dec, n, M, L) { + + var w = hourAngle(h, phi, dec), + a = approxTransit(w, lw, n); + return solarTransitJ(a, M, L); +} + + +// calculates sun times for a given date, latitude/longitude, and, optionally, +// the observer height (in meters) relative to the horizon + +SunCalc.getTimes = function (date, lat, lng, height) { + + height = height || 0; + + var lw = rad * -lng, + phi = rad * lat, + + dh = observerAngle(height), + + d = toDays(date), + n = julianCycle(d, lw), + ds = approxTransit(0, lw, n), + + M = solarMeanAnomaly(ds), + L = eclipticLongitude(M), + dec = declination(L, 0), + + Jnoon = solarTransitJ(ds, M, L), + + i, len, time, h0, Jset, Jrise; + + + var result = { + solarNoon: fromJulian(Jnoon), + nadir: fromJulian(Jnoon - 0.5) + }; + + for (i = 0, len = times.length; i < len; i += 1) { + time = times[i]; + h0 = (time[0] + dh) * rad; + + Jset = getSetJ(h0, lw, phi, dec, n, M, L); + Jrise = Jnoon - (Jset - Jnoon); + + result[time[1]] = fromJulian(Jrise); + result[time[2]] = fromJulian(Jset); + } + + return result; +}; + + +// moon calculations, based on http://aa.quae.nl/en/reken/hemelpositie.html formulas + +function moonCoords(d) { // geocentric ecliptic coordinates of the moon + + var L = rad * (218.316 + 13.176396 * d), // ecliptic longitude + M = rad * (134.963 + 13.064993 * d), // mean anomaly + F = rad * (93.272 + 13.229350 * d), // mean distance + + l = L + rad * 6.289 * sin(M), // longitude + b = rad * 5.128 * sin(F), // latitude + dt = 385001 - 20905 * cos(M); // distance to the moon in km + + return { + ra: rightAscension(l, b), + dec: declination(l, b), + dist: dt + }; +} + +SunCalc.getMoonPosition = function (date, lat, lng) { + + var lw = rad * -lng, + phi = rad * lat, + d = toDays(date), + + c = moonCoords(d), + H = siderealTime(d, lw) - c.ra, + h = altitude(H, phi, c.dec), + // formula 14.1 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + pa = atan(sin(H), tan(phi) * cos(c.dec) - sin(c.dec) * cos(H)); + + h = h + astroRefraction(h); // altitude correction for refraction + + return { + azimuth: azimuth(H, phi, c.dec), + altitude: h, + distance: c.dist, + parallacticAngle: pa + }; +}; + + +// calculations for illumination parameters of the moon, +// based on http://idlastro.gsfc.nasa.gov/ftp/pro/astro/mphase.pro formulas and +// Chapter 48 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + +SunCalc.getMoonIllumination = function (date) { + + var d = toDays(date || new Date()), + s = sunCoords(d), + m = moonCoords(d), + + sdist = 149598000, // distance from Earth to Sun in km + + phi = acos(sin(s.dec) * sin(m.dec) + cos(s.dec) * cos(m.dec) * cos(s.ra - m.ra)), + inc = atan(sdist * sin(phi), m.dist - sdist * cos(phi)), + angle = atan(cos(s.dec) * sin(s.ra - m.ra), sin(s.dec) * cos(m.dec) - + cos(s.dec) * sin(m.dec) * cos(s.ra - m.ra)); + + return { + fraction: (1 + cos(inc)) / 2, + phase: 0.5 + 0.5 * inc * (angle < 0 ? -1 : 1) / Math.PI, + angle: angle + }; +}; + + +function hoursLater(date, h) { + return new Date(date.valueOf() + h * dayMs / 24); +} + +// calculations for moon rise/set times are based on http://www.stargazing.net/kepler/moonrise.html article + +SunCalc.getMoonTimes = function (date, lat, lng, inUTC) { + var t = new Date(date); + if (inUTC) t.setUTCHours(0, 0, 0, 0); + else t.setHours(0, 0, 0, 0); + + var hc = 0.133 * rad, + h0 = SunCalc.getMoonPosition(t, lat, lng).altitude - hc, + h1, h2, rise, set, a, b, xe, ye, d, roots, x1, x2, dx; + + // go in 2-hour chunks, each time seeing if a 3-point quadratic curve crosses zero (which means rise or set) + for (var i = 1; i <= 24; i += 2) { + h1 = SunCalc.getMoonPosition(hoursLater(t, i), lat, lng).altitude - hc; + h2 = SunCalc.getMoonPosition(hoursLater(t, i + 1), lat, lng).altitude - hc; + + a = (h0 + h2) / 2 - h1; + b = (h2 - h0) / 2; + xe = -b / (2 * a); + ye = (a * xe + b) * xe + h1; + d = b * b - 4 * a * h1; + roots = 0; + + if (d >= 0) { + dx = Math.sqrt(d) / (Math.abs(a) * 2); + x1 = xe - dx; + x2 = xe + dx; + if (Math.abs(x1) <= 1) roots++; + if (Math.abs(x2) <= 1) roots++; + if (x1 < -1) x1 = x2; + } + + if (roots === 1) { + if (h0 < 0) rise = i + x1; + else set = i + x1; + + } else if (roots === 2) { + rise = i + (ye < 0 ? x2 : x1); + set = i + (ye < 0 ? x1 : x2); + } + + if (rise && set) break; + + h0 = h2; + } + + var result = {}; + + if (rise) result.rise = hoursLater(t, rise); + if (set) result.set = hoursLater(t, set); + + if (!rise && !set) result[ye > 0 ? 'alwaysUp' : 'alwaysDown'] = true; + + return result; +}; + + +// export as Node module / AMD module / browser variable +if (typeof exports === 'object' && typeof module !== 'undefined') module.exports = SunCalc; +else if (typeof define === 'function' && define.amd) define(SunCalc); +else window.SunCalc = SunCalc; + +}()); diff --git a/RVO20/flow/helper/utils.js b/RVO20/flow/helper/utils.js new file mode 100755 index 0000000..dbffe45 --- /dev/null +++ b/RVO20/flow/helper/utils.js @@ -0,0 +1,161 @@ +const fs = require('fs').promises; + +function bytesToInt(bytes, numberOfBytes) { + let buffer = []; + if (Array.isArray(bytes)) { + buffer = bytes.slice(0); + if (numberOfBytes != undefined) { + buffer = bytes.slice(bytes.length - numberOfBytes); + } + } + else buffer.push(bytes); + + let result = 0; + for (let i = 0; i < buffer.length; i++) { + result = (result << 8) | buffer[i]; + } + + return result >>> 0; //ensure it's an unsigned 32-bit number +} + +function resizeArray(arr, newSize, defaultValue) { + while (newSize > arr.length) + arr.push(defaultValue); + arr.length = newSize; +} + +longToByteArray = function(/*long*/long) { + // we want to represent the input as a 8-bytes array + var byteArray = [0, 0, 0, 0, 0, 0, 0, 0]; + + for (var index = 0; index < byteArray.length; index++) { + var byte = long & 0xff; + byteArray[index] = byte; + long = (long - byte) / 256; + } + + return byteArray; +}; + +function addDays(date, days) { + var result = new Date(date); + result.setDate(result.getDate() + days); + return result; +} + +/* +sleep(2000).then(() => { + // Do something after the sleep! + + +}); +*/ + +function sleep(time) { + return new Promise((resolve) => setTimeout(resolve, time)); +} + +function isEmptyObject(obj) { + for (var name in obj) { + return false; + } + return true; +} + +function emptyJsObject(jsObject) { + Object.keys(jsObject).forEach(key => delete jsObject[key]); +} + +function convertUTCDateToLocalDate(date) { + var newDate = new Date(date); + newDate.setMinutes(date.getMinutes() + date.getTimezoneOffset()); + return newDate; +} + +function addZeroBefore(n) { + return (n < 10 ? '0' : '') + n; +} + + +/** + * Asynchronously writes data to a file. + * + * @param {string} filePath The path to the file. + * @param {string} data The data to write to the file. + * @param {boolean} [append=false] If true, appends the data to the file. If false, it overwrites the file. + */ +async function writeToFile(filePath, data, append = false) { + if (typeof data !== 'string') data = JSON.stringify(data, null, 2); + try { + if (append) { + // Append the data to the end of the file. This is the simplest way to append. + await fs.appendFile(filePath, data, 'utf8'); + console.log(`Successfully appended data to ${filePath} using fs.appendFile.`); + } else { + // Overwrite the file with the new data. + await fs.writeFile(filePath, data, 'utf8'); + console.log(`Successfully wrote (overwrote) data to ${filePath} using fs.writeFile.`); + } + } catch (error) { + console.error(`Error writing to file ${filePath}:`, error); + } +} + + + /** + * Checks if an item is present in an array and adds it if it's not. + * * @param {Array} arr The array to check. + * @param {*} item The item to add. + * @returns {Array} The modified array. + */ +const addToArrayIfUnique = (arr, item) => { + if (!arr.includes(item)) { + arr.push(item); + } + return arr; +}; + + +var convertBase = function() { + + function convertBase(baseFrom, baseTo) { + return function(num) { + return parseInt(num, baseFrom).toString(baseTo); + + }; + } + + // binary to decimal + convertBase.bin2dec = convertBase(2, 10); + + // binary to hexadecimal + convertBase.bin2hex = convertBase(2, 16); + + // decimal to binary + convertBase.dec2bin = convertBase(10, 2); + + // decimal to hexadecimal + convertBase.dec2hex = convertBase(10, 16); + + // hexadecimal to binary + convertBase.hex2bin = convertBase(16, 2); + + // hexadecimal to decimal + convertBase.hex2dec = convertBase(16, 10); + + return convertBase; +}(); + +module.exports = { + bytesToInt, + longToByteArray, + addDays, + addZeroBefore, + resizeArray, + isEmptyObject, + emptyJsObject, + sleep, + convertUTCDateToLocalDate, + writeToFile, + addToArrayIfUnique +} diff --git a/RVO20/flow/httprequest.js b/RVO20/flow/httprequest.js new file mode 100755 index 0000000..469c8cb --- /dev/null +++ b/RVO20/flow/httprequest.js @@ -0,0 +1,137 @@ +exports.id = 'httprequest'; +exports.title = 'HTTP Request'; +exports.group = 'HTTP'; +exports.color = '#5D9CEC'; +exports.input = true; +exports.version = '2.0.1'; +exports.output = 1; +exports.author = 'Peter Širka'; +exports.icon = 'cloud-upload'; + +exports.html = `
+
@(URL address)
+
+
+
@(HTTP method)
+
+
+
@(Serialization)
+
+
+
@(Download the content in chunks)
+
@(Keep persistent cookies)
+
@(Disable DNS cache)
+
@(Keep alive connection)
+
+
+
+
@(Custom headers)
+
@(Cookies)
+
+
+
+ +
+
+
+
@(User)
+
+
+
@(Password)
+
+
+
+
+
`; + +exports.readme = `# Request + +This component creates a request with received data. + +__Response:__ +\`\`\`javascript +{ + data: String, + headers: Object, + status: Number, + host: String +} +\`\`\` + +__Dynamic arguments__: +Are performed via FlowData repository and can be used for URL address or for custom headers/cookies/auth. Use \`repository\` component for creating of dynamic arguments. Dynamic values are replaced in the form \`{key}\`: + +- url address e.g. \`https://.../{key}/\` +- headers values e.g. \`{token}\` +- cookies values e.g. \`{token}\``; + +exports.install = function(instance) { + + var can = false; + var flags = null; + var cookies2 = null; + + instance.on('data', function(response) { + can && instance.custom.send(response); + }); + + instance.custom.send = function(response) { + var options = instance.options; + + var headers = null; + var cookies = null; + + options.headers && Object.keys(options.headers).forEach(function(key) { + !headers && (headers = {}); + headers[key] = response.arg(options.headers[key]); + }); + + if (options.username && options.userpassword) { + !headers && (headers = {}); + headers['Authorization'] = 'Basic ' + U.createBuffer(response.arg(options.username + ':' + options.userpassword)).toString('base64'); + } + + options.cookies && Object.keys(options.cookies).forEach(function(key) { + !cookies && (cookies = {}); + cookies[key] = response.arg(options.cookies[key]); + }); + + if (options.chunks) { + U.download(response.arg(options.url), flags, options.stringify === 'none' ? null : response.data, function(err, response) { + response.on('data', (chunks) => instance.send2(chunks)); + }, cookies || cookies2, headers); + } else { + U.request(response.arg(options.url), flags, options.stringify === 'none' ? null : response.data, 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) + instance.error(err, response); + }, cookies || cookies2, headers); + } + }; + + instance.reconfigure = function() { + var options = instance.options; + can = options.url && options.url && options.method && options.stringify ? true : false; + instance.status(can ? '' : 'Not configured', can ? undefined : 'red'); + + if (!can) + return; + + flags = []; + flags.push(options.method.toLowerCase()); + options.stringify === 'json' && flags.push('json'); + options.stringify === 'raw' && flags.push('raw'); + options.keepalive && flags.push('keepalive'); + !options.nodns && flags.push('dnscache'); + if (options.persistentcookies) { + flags.push('cookies'); + cookies2 = {}; + } else + cookies2 = null; + }; + + instance.on('options', instance.reconfigure); + instance.reconfigure(); +}; \ No newline at end of file diff --git a/RVO20/flow/httpresponse.js b/RVO20/flow/httpresponse.js new file mode 100755 index 0000000..160a3bb --- /dev/null +++ b/RVO20/flow/httpresponse.js @@ -0,0 +1,76 @@ +exports.id = 'httpresponse'; +exports.title = 'HTTP Response'; +exports.group = 'HTTP'; +exports.color = '#5D9CEC'; +exports.icon = 'arrow-right'; +exports.input = true; +exports.output = ['#666D76']; +exports.version = '2.0.0'; +exports.author = 'Martin Smola'; +exports.readme = `# HTTP response + +HTTP response will respond with data recieved using data-type set in Settings form or plain text if not set. Output is the message duration \`Number\` in seconds.`; + +exports.html = `
+
@(Response data-type)
+
JSON is by default.
+
`; + +exports.install = function(instance) { + + var dursum = 0; + var durcount = 0; + + instance.on('data', function(flowdata) { + + var ctrl = flowdata.repository.controller; + var data = flowdata.data; + + if (!ctrl) { + instance.throw('No controller to use for response!'); + return; + } + + durcount++; + dursum += ((new Date() - flowdata.begin) / 1000).floor(2); + setTimeout2(instance.id, instance.custom.duration, 500, 10); + + ctrl.$flowdata = flowdata; + + var datatype = instance.options.datatype || 'json'; + if (datatype === 'emptyresponse') + return ctrl.plain(''); + + if (datatype !== 'json' && typeof(data) !== 'string') { + instance.throw('Incorect type of data, expected string, got ' + typeof(data)); + ctrl.plain(data == null ? '' : data.toString()); + return; + } + + switch(datatype) { + case 'html': + ctrl.content(data, 'text/html'); + break; + case 'plain': + ctrl.plain(data); + break; + case 'xml': + ctrl.content(data, 'text/xml'); + break; + default: + ctrl.json(data); + break; + } + }); + + instance.on('service', function() { + dursum = 0; + durcount = 0; + }); + + instance.custom.duration = function() { + var avg = (dursum / durcount).floor(2); + instance.status(avg + ' sec.'); + instance.send2(0, avg); + }; +}; diff --git a/RVO20/flow/httproute.js b/RVO20/flow/httproute.js new file mode 100755 index 0000000..583a19d --- /dev/null +++ b/RVO20/flow/httproute.js @@ -0,0 +1,326 @@ +exports.id = 'httproute'; +exports.title = 'HTTP Route'; +exports.group = 'HTTP'; +exports.color = '#5D9CEC'; +exports.icon = 'globe'; +exports.input = false; +exports.output = ['#6CAC5A', '#37BC9B']; +exports.version = '1.2.3'; +exports.author = 'Martin Smola'; +exports.cloning = false; +exports.options = { method: 'GET', url: '', size: 5, cacheexpire: '5 minutes', cachepolicy: 0, timeout: 5 }; +exports.dateupdated = '2021-01-21 18:30d'; +exports.readme = `# HTTP route + +__Outputs__: +- first output: raw data (cache is empty or is disabled) +- second output: cached data + +If one of the outputs is disabled then automatic responce with code "503 service unavailable" is sent. + +When a request comes in bellow object is available at \`flowdata.data\`: + +\`\`\`javascript +{ + params: { id: '1' }, // params for dynamic routes, e.g. /test/{id} + query: { msg: 'Hello' }, // parsed query string, e.g. /test/1?msg=Hello + body: { test: 'OK' }, // object if json requests otherwise string + headers: {}, // headers data + session: {}, // session data + user: {}, // user data + files: [], // uploaded files + url: '/users/', // a relative URL address + referrer: '/', // referrer + mobile: false, // determines mobile device + robot: false, // determines search robots/crawlsers + language: 'en' // determines language +} +\`\`\` + +See [documentation for flags](https://docs.totaljs.com/latest/en.html#api~HttpRouteOptionsFlags~unauthorize). These method flags are set automatically e.g. \`get, post, put, patch or delete\` + +--- + +\`id:ROUTE_ID\` flag cannot be used since it's already used by this component internally`; + +exports.html = `
+
+ +
+ +
+
+
@(HTTP method)
+
+
+
@(URL address)
+
+
+
+
+
@(Additional flags)
+
@(Separate flags by comma e.g. json, authorize)
+
+
+
@(Max. request size)
+
@(In kB kilobytes)
+
+
+
@(Timeout)
+
@(In seconds.)
+
+
+
+
+
+
@(Automatically respond with 200 OK?)
+
@(If not checked you need to use HTTP response component to respond to the request.)
+
+
@(Custom headers)
+
@(Cookies)
+
+
+
+
+
+
@(Cache policy)
+
@(User instance must contain id property.)
+
+
+
@(Expiration)
+
@(E.g. 5 minutes)
+
+
+
+`; + +exports.install = function(instance) { + + var route; + + var uninstall = function(id) { + if (F.is4) { + route && route.remove(); + route = null; + } else + UNINSTALL('route', id); + }; + + instance.custom.emptyresponse = function(self) { + self.plain(); + }; + + instance.reconfigure = function() { + + var options = instance.options; + + if (!options.url) { + instance.status('Not configured', 'red'); + return; + } + + if (typeof(options.flags) === 'string') + options.flags = options.flags.split(',').trim(); + + uninstall('id:' + instance.id); + + var flags = options.flags || []; + + flags.push('id:' + instance.id); + + if (!F.is4) + flags.push(options.method.toLowerCase()); + + options.timeout && flags.push(options.timeout * 1000); + + // Make unique values + flags = flags.filter(function(v, i, a) { + if(F.is4 && v.toString().toLowerCase() === options.method.toLowerCase()) + return false; // remove method + return a.indexOf(v) === i; + }); + + options.flags = flags; + var handler = function() { + + if (instance.paused || (instance.isDisabled && (instance.isDisabled('output', 0) || instance.isDisabled('output', 1)))) { + instance.status('503 Service Unavailable'); + this.status = 503; + this.json(); + return; + } + + var key; + var self = this; + + if (instance.options.emptyresponse) { + instance.status('200 OK'); + setTimeout(instance.custom.emptyresponse, 100, self); + + if (instance.hasConnection(0)) { + var data = instance.make({ + query: self.query, + body: self.body, + session: self.session, + user: self.user, + files: self.files, + headers: self.req.headers, + url: self.url, + params: self.params + }); + instance.send2(0, data); + } + + return; + } + + switch (instance.options.cachepolicy) { + case 1: // URL + key = 'rro' + instance.id + self.url.hash(); + break; + case 2: // URL + query + case 3: // URL + query + user + key = self.url; + var keys = Object.keys(self.query); + keys.sort(); + for (var i = 0, length = keys.length; i < length; i++) + key += keys[i] + self.query[keys[i]] + '&'; + if (instance.options.cachepolicy === 3 && self.user) + key += 'iduser' + self.user.id; + key = 'rro' + instance.id + key.hash(); + break; + } + + if (key && F.cache.get2(key)) { + var data = instance.make(F.cache.get2(key)); + data.repository.controller = self; + instance.send2(1, data); + } else { + + var data = instance.make({ + query: self.query, + body: self.body, + session: self.session, + user: self.user, + files: self.files, + headers: self.req.headers, + url: self.url, + params: self.params, + mobile: self.mobile, + robot: self.robot, + referrer: self.referrer, + language: self.language + }); + + data.repository.controller = self; + instance.send2(0, data); + key && FINISHED(self.res, () => F.cache.set(key, self.$flowdata.data, instance.options.cacheexpire)); + } + }; + + if (F.is4) + route = ROUTE(options.method.toUpperCase() + ' ' + options.url, handler, flags, options.size || 5); + else + F.route(options.url, handler, flags, options.size || 5); + + instance.status('Listening', 'green'); + }; + + instance.reconfigure(); + instance.on('options', instance.reconfigure); + instance.on('close', function(){ + uninstall('id:' + instance.id); + }); +}; + +// check url exists +FLOW.trigger('httproutecheckurl', function(next, data) { + var url = data.url; + var method = data.method; + if (url[url.length - 1] !== '/') + url += '/'; + var exists = F.routes.web.findItem(r => r.urlraw === url && r.method === method); + next(exists != null); +}); + +exports.uninstall = function() { + FLOW.trigger('httproutecheckurl', null); +}; diff --git a/RVO20/flow/infosender.js b/RVO20/flow/infosender.js new file mode 100755 index 0000000..587724f --- /dev/null +++ b/RVO20/flow/infosender.js @@ -0,0 +1,81 @@ +exports.id = 'infosender'; +exports.title = 'Info sender'; +exports.version = '1.0.0'; +exports.group = 'Worksys'; +exports.color = '#2134B0'; +exports.input = 2; +exports.output = 1 +exports.icon = 'bolt'; + +const { networkInterfaces } = require('os'); + +exports.html = `
+
+
+
CSV Import
+
+
+
`; + +exports.readme = `# send all data to projects.worksys.io, required to monitor status of controller(unipi)`; + +exports.install = function(instance) { + + let id; + let allValues = {}; + let sendAllValuesInterval; + let configured = false; + + let now = new Date(); + console.log(exports.title, "INSTALLED", now.toLocaleString("sk-SK")); + + const nets = networkInterfaces(); + let ipAddresses = Object.create(null); // Or just '{}', an empty object + + for (const name of Object.keys(nets)) { + for (const net of nets[name]) { + // Skip over non-IPv4 and internal (i.e. 127.0.0.1) addresses + if (net.family === 'IPv4' && !net.internal) { + if (!ipAddresses[name]) { + ipAddresses[name] = []; + } + ipAddresses[name].push(net.address); + } + } + } + + function sendValues() { + if (!configured) return; + + if (Object.keys(allValues).length > 0) { + let dataToSend = { ...allValues }; + dataToSend.id = id; + dataToSend.ipAddresses = ipAddresses; + + instance.send(0, dataToSend); + + allValues = {}; + } + } + + instance.on("close", () => { + clearInterval(sendAllValuesInterval); + }) + + instance.on("0", _ => { + id = FLOW.GLOBALS.settings.project_id; + if (id) configured = true; + else console.log(exports.title, "InfoSender: Unable to send data, no id"); + }) + + instance.on("1", flowdata => { + allValues = { ...allValues, ...flowdata.data }; + //console.log("DATA RECEIVED", flowdata.data); + }) + + sendAllValuesInterval = setInterval(() => { + sendValues(); + }, 60000 * 3); + +} + diff --git a/RVO20/flow/modbus_reader.js b/RVO20/flow/modbus_reader.js new file mode 100755 index 0000000..d6d9dad --- /dev/null +++ b/RVO20/flow/modbus_reader.js @@ -0,0 +1,346 @@ +exports.id = 'modbus_reader'; +exports.title = 'Modbus reader'; +exports.version = '2.0.0'; +exports.group = 'Worksys'; +exports.color = '#2134B0'; +exports.input = 1; +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; +//number of phases inRVO +let phases; +//phases where voltage is 0 (set) +let noVoltage; +let energyToSwitchLamps; + +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.phases = this.buildPhases(); + + this.startSocket(); + } + + buildPhases = () => { + let a = []; + for (let i = 1; i <= phases; i++) { + a.push(`Phase_${i}_voltage`) + } + return a; + } + + startSocket = () => { + + let obj = this; + + if (this.socket) { + this.socket.removeAllListeners(); + this.socket = null; + } + + 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('Modbus_reader: Socket connection error', e); //'ECONNREFUSED' or 'ECONNRESET' ?? + }); + + this.socket.on('close', function() { + console.log('Modbus_reader: Socket connection closed - Waiting 10 seconds before connecting 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 we just start to loop devices from the beginning, or there is just 1 device in config, we wait whole timeoutInterval + if (this.indexInDeviceConfig == 0 || deviceConfig.length === 1) 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 (this.phases.includes(singleValue)) { + let l = singleValue.split("_"); + let phase = parseInt(l[1]); + + // console.log(values[singleValue], tbName); + + if (values[singleValue] == 0) { + noVoltage.add(phase); + sendNotification("modbus_reader: checkNullVoltage", tbName, "no_voltage_on_phase", { phase: phase }, "", SEND_TO.tb, instance, "voltage" + phase); + // console.log('no voltage') + } + else { + noVoltage.delete(phase); + // console.log('voltage detected') + sendNotification("modbus_reader: checkNullVoltage", tbName, "voltage_on_phase_restored", { phase: phase }, "", SEND_TO.tb, instance, "voltage" + phase); + } + } + }) + } + + /** + * function sends notification to slack and to tb, if EM total_power value changes more than numberOfNodes*15. This should show, that RVO lamps has been switched on or off + */ + lampSwitchNotification = (values) => { + + if (!values.hasOwnProperty("total_power")) return; + + const actualTotalPower = values.total_power; + + if (actualTotalPower > energyToSwitchLamps && 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 <= energyToSwitchLamps && 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; + } + + function main() { + + phases = FLOW.GLOBALS.settings.phases; + tbName = FLOW.GLOBALS.settings.rvoTbName; + noVoltage = FLOW.GLOBALS.settings.no_voltage; + energyToSwitchLamps = FLOW.GLOBALS.settings.energy_to_switch_lamps / 2.5; //half value is enought to show if lamps are turned on or off + if (deviceConfig.length) mainSocket = new SocketWithClients(); + else console.log("Modbus_reader: no modbus device in configuration"); + + // this notification is to show, that flow (unipi) has been restarted + sendNotification("modbus_reader", tbName, "flow_restart", {}, "", SEND_TO.slack, instance); + } + + instance.on("0", function(_) { + main(); + }) + +} + diff --git a/RVO20/flow/monitorconsumption.js b/RVO20/flow/monitorconsumption.js new file mode 100755 index 0000000..64cc58e --- /dev/null +++ b/RVO20/flow/monitorconsumption.js @@ -0,0 +1,156 @@ +exports.id = 'monitorconsumption'; +exports.title = 'Consumption'; +exports.version = '1.0.0'; +exports.author = 'Peter Širka'; +exports.group = 'Monitoring'; +exports.color = '#967ADC'; +exports.input = 0; +exports.output = 1; +exports.icon = 'bug'; +exports.options = { interval: 5000, enabled: true, monitorconsumption: true, monitorsize: true, monitorconnections: true, monitorfiles: true }; +exports.click = true; +exports.readme = `# Consumption monitoring + +This component measure CPU and memory consumption, open files and open connections of this application. It uses these Linux commands: \`ps\`, \`lsof\`, \`netstat\` and \`df\`. + +__Data Example__: + +\`\`\`javascript +{ + cpu: 0, // percentage + memory: 4096, // in bytes + size: 34303, // directory size in bytes + files: 34, // count of open files + connections: 343, // count of connections + uptime: '1-12:34:00' +} +\`\`\``; + +exports.html = `
+
+
+
@(Interval in milliseconds)
+
+
+
+
Monitor: Consumption + uptime
+
Monitor: Count of open files
+
Monitor: Count of open connections
+
Monitor: Directory size
+
`; + +exports.install = function(instance) { + + var current = { cpu: 0, memory: 0, files: 0, connections: 0, size: 0, uptime: '', counter: 0 }; + var tproc = null; + var Exec = require('child_process').exec; + var reg_empty = /\s{2,}/g; + var reg_appdisksize = /^[\d.,]+/; + + instance.custom.run = function() { + + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + + var arr = []; + + // Get CPU and Memory consumption + instance.options.monitorconsumption && arr.push(function(next) { + Exec('ps -p {0} -o %cpu,rss,etime'.format(process.pid), function(err, response) { + + if (err) { + instance.throw(err); + } else { + var line = response.split('\n')[1]; + line = line.trim().replace(reg_empty, ' ').split(' '); + var cpu = line[0].parseFloat(); + current.cpu = cpu.floor(1); + current.memory = line[1].parseInt2() * 1024; // kB to bytes + current.uptime = line[2]; + } + + next(); + }); + }); + + // Get count of open files + instance.options.monitorfiles && arr.push(function(next) { + Exec('lsof -a -p {0} | wc -l'.format(process.pid), function(err, response) { + if (err) + instance.throw(err); + else + current.files = response.trim().parseInt2(); + next(); + }); + }); + + // Get count of opened network connections + instance.options.monitorconnections && arr.push(function(next) { + Exec('netstat -an | grep :{0} | wc -l'.format(F.port), function(err, response) { + if (err) { + instance.throw(err); + } else { + current.connections = response.trim().parseInt2() - 1; + if (current.connections < 0) + current.connections = 0; + } + next(); + }); + }); + + // Get directory size + instance.options.monitorsize && current.counter % 5 !== 0 && arr.push(function(next) { + Exec('du -hsb ' + process.cwd(), function(err, response) { + if (err) { + instance.throw(err); + } else { + var match = response.trim().match(reg_appdisksize); + match && (current.size = match.toString().trim().parseInt2()); + } + next(); + }); + }); + + arr.async(function() { + + tproc && clearTimeout(tproc); + + if (instance.options.enabled) { + tproc = setTimeout(instance.custom.run, instance.options.interval); + instance.send2(current); + } + + instance.custom.status(); + current.counter++; + }); + }; + + instance.custom.status = function() { + if (instance.options.enabled) + instance.status('{0}% / {1}'.format(current.cpu, current.memory.filesize())); + else + instance.status('Disabled', 'red'); + }; + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + + if (instance.options.enabled) { + current.counter = 0; + instance.custom.run(); + } + + }); + + instance.on('close', function() { + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + }); + + setTimeout(instance.custom.run, 1000); +}; \ No newline at end of file diff --git a/RVO20/flow/monitordisk.js b/RVO20/flow/monitordisk.js new file mode 100755 index 0000000..f4fdaa0 --- /dev/null +++ b/RVO20/flow/monitordisk.js @@ -0,0 +1,96 @@ +exports.id = 'monitordisk'; +exports.title = 'Disk'; +exports.version = '1.0.0'; +exports.author = 'Peter Širka'; +exports.group = 'Monitoring'; +exports.color = '#F6BB42'; +exports.output = 1; +exports.icon = 'hdd-o'; +exports.click = true; +exports.options = { interval: 8000, path: '/', enabled: true }; +exports.readme = `# Disk monitoring + +This component monitors disk \`bytes\` consumption in Linux systems. It uses \`df\` command. + +__Data Example__: + +\`\`\`javascript +{ + total: 474549649408, + used: 39125245952, + free: 411294994432 +} +\`\`\``; + +exports.html = `
+
+
+
@(Interval in milliseconds)
+
+
+
@(Path)
+
+
+
`; + +exports.install = function(instance) { + + var current = { total: 0, used: 0, free: 0, path: '', type: '', percentUsed: 0 }; + var tproc = null; + + instance.custom.run = function() { + + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + + if (!instance.options.enabled) + return; + + require('child_process').exec('df -hTB1 ' + instance.options.path, function(err, response) { + + tproc = setTimeout(instance.custom.run, instance.options.interval); + + if (err) { + instance.error(err); + return; + } + + response.parseTerminal(function(line) { + if (line[0][0] !== '/') + return; + current.total = line[2].parseInt(); + current.free = line[4].parseInt(); + current.used = line[3].parseInt(); + current.path = instance.options.path || '/'; + current.type = line[1]; + current.percentUsed = line[5]; + instance.custom.status(); + instance.send2(current); + }); + }); + }; + + instance.custom.status = function() { + if (instance.options.enabled) + instance.status(current.free.filesize() + ' / ' + current.total.filesize()); + else + instance.status('Disabled', 'red'); + }; + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + instance.options.enabled && instance.custom.run(); + }); + + instance.on('close', function() { + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + }); + + setTimeout(instance.custom.run, 1000); +}; \ No newline at end of file diff --git a/RVO20/flow/monitormemory.js b/RVO20/flow/monitormemory.js new file mode 100755 index 0000000..2decbc4 --- /dev/null +++ b/RVO20/flow/monitormemory.js @@ -0,0 +1,87 @@ +exports.id = 'monitormemory'; +exports.title = 'Memory'; +exports.version = '1.0.0'; +exports.author = 'Peter Širka'; +exports.group = 'Monitoring'; +exports.color = '#F6BB42'; +exports.output = 1; +exports.click = true; +exports.icon = 'microchip'; +exports.options = { interval: 8000, enabled: true }; +exports.readme = `# Memory monitoring + +This component monitors memory \`bytes\` consumption in Linux systems. It uses \`free\` command. + +__Data Example__: + +\`\`\`javascript +{ + total: 33558769664, + used: 1998868480, + free: 2653708288 +} +\`\`\``; + +exports.html = `
+
+
+
@(Interval in milliseconds)
+
+
+
`; + +exports.install = function(instance) { + + var current = { total: 0, used: 0, free: 0 }; + var tproc = null; + + instance.custom.run = function() { + + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + + if (!instance.options.enabled) + return; + + require('child_process').exec('free -b -t', function(err, response) { + + tproc = setTimeout(instance.custom.run, instance.options.interval); + + if (err) { + instance.error(err); + return; + } + + var memory = response.split('\n')[1].match(/\d+/g); + current.total = memory[0].parseInt(); + current.used = memory[1].parseInt() - memory[3].parseInt(); + current.free = current.total - current.used; + instance.custom.status(); + instance.send2(current); + }); + }; + + instance.custom.status = function() { + if (instance.options.enabled) + instance.status(current.free.filesize() + ' / ' + current.total.filesize()); + else + instance.status('Disabled', 'red'); + }; + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + instance.options.enabled && instance.custom.run(); + }); + + instance.on('close', function() { + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + }); + + setTimeout(instance.custom.run, 1000); +}; \ No newline at end of file diff --git a/RVO20/flow/nodesdb_changecheck.js b/RVO20/flow/nodesdb_changecheck.js new file mode 100755 index 0000000..9adab62 --- /dev/null +++ b/RVO20/flow/nodesdb_changecheck.js @@ -0,0 +1,77 @@ +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 = 2; +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); + } + } + + //kedze do slacku posielame stringy, na cloud musime previest vsetky stringy spat na objekty: + // Funkcia na parsovanie všetkých reťazcov v poli + const parseArray = (arr) => { + return arr.map(jsonString => JSON.parse(jsonString)); + }; + + 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); + if (FLOW.GLOBALS.settings.send_changed_node_numbers) instance.send(1, { aktualneNody: parseArray(zmenene), originalne: parseArray(Array.from(set2)) }); + } + 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/RVO20/flow/show_dbdata.js b/RVO20/flow/show_dbdata.js new file mode 100755 index 0000000..1e23ff7 --- /dev/null +++ b/RVO20/flow/show_dbdata.js @@ -0,0 +1,243 @@ +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 = 8; +exports.output = 1; + +const { exec } = require('child_process'); + +exports.install = 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 }) + }) + instance.on("5", _ => { + exec("sudo tail -n 25 monitor.txt", (err, stdout, stderr) => { + if (err || stderr) instance.send(0, { err, stderr }); + else instance.send(0, stdout); + }) + }) + instance.on("6", _ => { + exec("sudo tail -n 25 err.txt", (err, stdout, stderr) => { + if (err || stderr) instance.send(0, { err, stderr }); + else instance.send(0, stdout); + }) + }) + instance.on("7", _ => { + instance.send(0, FLOW.deviceStatus); + }) +}; + + +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/RVO20/flow/slack_filter.js b/RVO20/flow/slack_filter.js new file mode 100755 index 0000000..6618523 --- /dev/null +++ b/RVO20/flow/slack_filter.js @@ -0,0 +1,188 @@ +exports.id = 'slack_filter'; +exports.title = 'Slack Filter'; +exports.group = 'Citysys'; +exports.color = '#30E193'; +exports.input = 2; +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 = `
+
+
+
@(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('0', 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']['en']; + 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"] = []; + } + + instance.options.name = FLOW.GLOBALS.settings.rvo_name; + if (instance.options.name) { + instance.status('Running'); + running = true; + } else { + instance.status('Please run options again', 'red'); + running = false; + } + } catch (e) { + instance.error('Citysys connector: ' + e.message); + } + }; + + instance.on('options', instance.reconfigure); + + instance.on("1", _ => { + instance.reconfigure(); + }) +}; diff --git a/RVO20/flow/thermometer.js b/RVO20/flow/thermometer.js new file mode 100755 index 0000000..fc7074d --- /dev/null +++ b/RVO20/flow/thermometer.js @@ -0,0 +1,99 @@ +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 = 5;//minutes +let NUMBER_OF_FAILURES_TO_SEND_ERROR = 13; + +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) => { + + 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); + setTimeout(main, 20000); + }) +}; diff --git a/RVO20/flow/trigger.js b/RVO20/flow/trigger.js new file mode 100755 index 0000000..27545a8 --- /dev/null +++ b/RVO20/flow/trigger.js @@ -0,0 +1,79 @@ +exports.id = 'trigger'; +exports.title = 'Trigger'; +exports.group = 'Inputs'; +exports.color = '#F6BB42'; +exports.click = true; +exports.output = 1; +exports.version = '1.1.0'; +exports.author = 'Martin Smola'; +exports.icon = 'play'; + +exports.html = `
+
@(Data type (String by default))
+
@(Data)
+
Trigger 5s after initialization.
+
@(Useful when there's a need to run certain flow when the app restarts, etc.)
+
`; + +exports.readme = `# Trigger + +- Clicking on the component starts the chain +- Settings allows to set a data-type and a value`; + +exports.install = function(instance) { + + var value; + + instance.on('click', () => instance.send2(value)); + + instance.reconfigure = function() { + var options = instance.options; + value = null; + switch (options.datatype) { + case 'integer': + value = options.data.parseInt2('error'); + value = value === 'error' ? NaN : value; + break; + case 'float': + value = options.data.parseFloat2('error'); + value = value === 'error' ? NaN : value; + break; + case 'date': + options.data = options.data.toString(); + var num = options.data.parseInt('error'); + num === 'error' && (num = options.data.parseDate('error')); + num === 'error' && (num = null); + value = num ? new Date(num).toUTCString() : num; + break; + case 'object': + try { + value = (new Function('return ' + options.data))(); + } catch (e) { + instance.error(e); + } + break; + case 'boolean': + value = options.data.parseBoolean(); + break; + case 'buffer': + try { + value = U.createBuffer(options.data); + } catch (e) { + instance.error(e); + } + break; + case 'string': + default: + value = '' + (options.data || ''); + break; + } + }; + + instance.on('options', instance.reconfigure); + instance.reconfigure(); + + if (instance.options.restart) + setTimeout(function(){ + instance.send2(value); + }, 5000); +}; diff --git a/RVO20/flow/variables.txt b/RVO20/flow/variables.txt new file mode 100755 index 0000000..e69de29 diff --git a/RVO20/flow/virtualwirein.js b/RVO20/flow/virtualwirein.js new file mode 100755 index 0000000..38a4e42 --- /dev/null +++ b/RVO20/flow/virtualwirein.js @@ -0,0 +1,43 @@ +exports.id = 'virtualwirein'; +exports.title = 'Virtual wire in'; +exports.version = '1.0.0'; +exports.author = 'Martin Smola'; +exports.color = '#303E4D'; +exports.icon = 'sign-in'; +exports.input = false; +exports.output = 1; +exports.options = {}; +exports.readme = `# Virtual wire in + +When the wires between the components are mess it's time to use Virtual wire.`; + +exports.html = `
+
@(Wire name)
+
+`; + +exports.install = function(instance) { + + instance.custom.reconfigure = function(options){ + if (instance.options.wirename) { + instance.status(instance.options.wirename); + } else + instance.status('Not configured', 'red'); + }; + + ON('virtualwire', function(wirename, flowdata){ + if (instance.options.wirename && instance.options.wirename === wirename) + instance.send(flowdata); + }); + + instance.on('options', instance.custom.reconfigure); + instance.custom.reconfigure(); +}; diff --git a/RVO20/flow/virtualwireout.js b/RVO20/flow/virtualwireout.js new file mode 100755 index 0000000..94a1e4f --- /dev/null +++ b/RVO20/flow/virtualwireout.js @@ -0,0 +1,41 @@ +exports.id = 'virtualwireout'; +exports.title = 'Virtual wire out'; +exports.version = '1.0.0'; +exports.author = 'Martin Smola'; +exports.color = '#303E4D'; +exports.icon = 'sign-out'; +exports.input = true; +exports.options = {}; +exports.readme = `# Virtual wire out + +When the wires between the components are mess it's time to use Virtual wire.`; + +exports.html = `
+
@(Wire name)
+
+`; + +exports.install = function(instance) { + + instance.custom.reconfigure = function(){ + if (instance.options.wirename) { + instance.status(instance.options.wirename); + } else + instance.status('Not configured', 'red'); + }; + + instance.on('data', function(flowdata) { + EMIT('virtualwire', instance.options.wirename, flowdata); + }); + + instance.on('options', instance.custom.reconfigure); + instance.custom.reconfigure(); +}; diff --git a/RVO20/flow/wsmqttpublish.js b/RVO20/flow/wsmqttpublish.js new file mode 100755 index 0000000..0eba804 --- /dev/null +++ b/RVO20/flow/wsmqttpublish.js @@ -0,0 +1,448 @@ +exports.id = 'wsmqttpublish'; +exports.title = 'WS MQTT publish'; +exports.group = 'MQTT'; +exports.color = '#888600'; +exports.version = '1.0.2'; +exports.icon = 'sign-out'; +exports.input = 2; +exports.output = 3; +exports.options = { host: 'tb-stage.worksys.io', port: 1883, clientid: "", username: "" }; + +exports.html = `
+
+
+
Hostname or IP address (if not empty - setting will override db setting)
+
+
+
Port
+
+
+
+
+
@(Client id)
+
+
+
@(Username)
+
+
+
`; + + +exports.readme = ` +# WS MQTT Publish + +Version 1.0.3. + +Added: +- database collections, +- 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 = { + debug: 0, + rpcCall: 1, + services: 2 +} + +//CONFIG +let createTelemetryBackup = true; +let saveTelemetryOnError = true;//backup_on_failure overrides this value +//------------------------ + +let rollers; +if (createTelemetryBackup) rollers = require('streamroller'); + +const noSqlFileSizeLimit = 4194304;//use 5MB - 4194304 +let insertNoSqlCounter = 0; +let insertBackupNoSqlCounter = 0; +let processingData = false; + +let backup_on_failure = false;//== saveTelemetryOnError - create backup client 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; + +process.on('uncaughtException', function(err) { + + errLogger.error('uncaughtException:', err.message) + errLogger.error(err.stack); + + //TODO + //send to service + + //process.exit(1); +}) + +const nosql = NOSQL('tbdata'); +const nosqlBackup = NOSQL('/backup/tbdata'); + + +exports.install = function(instance) { + + var client; + var opts; + var clientReady = false; + + // wsmqtt status for notification purposes on projects.worksys.io database + let wsmqttName = null; + let sendWsStatusVar = null; + let wsmqtt_status = 'disconnected'; + + 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'; + } + + function sendWsStatus() { + instance.send(SEND_TO.services, { [wsmqttName]: wsmqtt_status }); + } + + + function main() { + if (!FLOW.dbLoaded) return; + + loadSettings(); + clearInterval(sendWsStatus); + sendWsStatusVar = setInterval(sendWsStatus, 180000); + } + + //set opts according to db settings + function loadSettings() { + + if (instance.options.host !== "") { + //override settings from database + var o = instance.options; + opts = { + host: o.host, + port: o.port, + clientId: o.clientid, + username: o.username, + rejectUnauthorized: false, + resubscribe: false + }; + + wsmqttName = getWsmqttName(o.host); + + console.log("wsmqttpublich -> loadSettings from instance.options", instance.options); + } + else { + + const SETTINGS = FLOW.GLOBALS.settings; + backup_on_failure = SETTINGS.backup_on_failure; + saveTelemetryOnError = backup_on_failure; + + restore_from_backup = SETTINGS.restore_from_backup; + restore_backup_wait = SETTINGS.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; + + opts = { + host: mqtt_host, + port: mqtt_port, + keepalive: 10, + clientId: mqtt_clientid, + username: mqtt_username, + rejectUnauthorized: false, + resubscribe: false + }; + + wsmqttName = getWsmqttName(mqtt_host); + } + + connectToTbServer(); + } + + function connectToTbServer() { + 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"); + //monitor.info("MQTT client connected"); + + sendClientError = true; + clientReady = true; + wsmqtt_status = 'connected'; + }); + + client.on('reconnect', function() { + instance.status("Reconnecting", "yellow"); + clientReady = false; + }); + + client.on('message', function(topic, message) { + // message is type of buffer + message = message.toString(); + if (message[0] === '{') { + TRY(function() { + + message = JSON.parse(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 } }); + } + + }, () => instance.debug('MQTT: Error parsing data', message)); + } + + instance.send(SEND_TO.rpcCall, { "topic": topic, "content": message }); + }); + + client.on('close', function() { + clientReady = false; + wsmqtt_status = 'disconnected'; + + instance.status("Disconnected", "red"); + instance.send(SEND_TO.debug, { "message": "Client CLOSE signal received !" }); + }); + + client.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; + wsmqtt_status = 'disconnected'; + }); + + } + + + instance.on("0", _ => { + main(); + }) + + + instance.on('1', function(data) { + + if (clientReady) { + //do we have some data in backup file? if any, process data from database + if (saveTelemetryOnError) { + //read telemetry data and send back to server + if (!processingData) processDataFromDatabase(); + } + + let stringifiedJson = JSON.stringify(data.data); + client.publish("v1/gateway/telemetry", stringifiedJson, { qos: 1 }); + + //backup telemetry + if (createTelemetryBackup) { + data.data.id = UID(); + nosqlBackup.insert(data.data); + + insertBackupNoSqlCounter++; + if (insertBackupNoSqlCounter > 150) { + let options = { compress: true }; + let path = __dirname + "/../databases/backup/tbdata.nosql"; + var stream = new rollers.RollingFileStream(path, noSqlFileSizeLimit, 150, options); + stream.write(""); + stream.end(); + + insertBackupNoSqlCounter = 0; + } + } + + } + 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 (saveTelemetryOnError) { + //create new file from tbdata.nosql, if file size exceeds given limit, and clear tbdata.nosql + makeBackupFromDbFile(); + + //write to tb + data.data.id = UID(); + nosql.insert(data.data); + } + } + }); + + + instance.close = function(done) { + if (clientReady) { + client.end(); + clearInterval(sendWsStatusVar); + } + }; + + + function getDbBackupFileCounter(type) { + var files = fs.readdirSync(__dirname + "/../databases"); + + let counter = 0; + for (var i = 0; i < files.length; i++) { + + if (files[i] == "tbdata.nosql") continue; + + if (files[i].endsWith(".nosql")) { + + let pos = files[i].indexOf("."); + if (pos > -1) { + + let fileCounter = counter; + let firstDigit = files[i].slice(0, pos); + + fileCounter = parseInt(firstDigit); + if (isNaN(fileCounter)) fileCounter = 0; + //console.log("getDbBackupFileCounter digit:", files[i], firstDigit, fileCounter, isNaN(fileCounter), type); + + if (type == "max") { + if (fileCounter > counter) { + counter = fileCounter; + } + } + else if (type == "min") { + if (counter == 0) counter = fileCounter; + + if (fileCounter < counter) { + counter = fileCounter; + } + } + } + } + + } + + if (type == "max") counter++; + + return counter; + } + + const makeBackupFromDbFile = async () => { + + if (!saveTelemetryOnError) return; + + //to avoid large file: tbdata.nosql + + //init value is 0! + if (insertNoSqlCounter > 0) { + --insertNoSqlCounter; + return; + } + + insertNoSqlCounter = 100; + + let source = __dirname + "/../databases/tbdata.nosql"; + + var stats = fs.statSync(source); + var fileSizeInBytes = stats.size; + + if (fileSizeInBytes > noSqlFileSizeLimit) { + + let counter = 1; + counter = getDbBackupFileCounter("max"); + + let destination = __dirname + "/../databases/" + counter + "." + "tbdata.nosql"; + + //make backup file + fs.copyFileSync(source, destination); + //fs.renameSync(p, p + "." + counter); + + //clear tbdata.nosql + fs.writeFileSync(source, ""); + fs.truncateSync(source, 0); + + } + } + + const processDataFromDatabase = async () => { + + if (restore_from_backup <= 0) return; + + //calculate diff + const now = new Date(); + let currentTime = now.getTime(); + let diff = currentTime - lastRestoreTime; + + if ((diff / 1000) < restore_backup_wait) { + //console.log("*********restore_backup_wait", diff, restore_backup_wait); + return; + } + + processingData = true; + + //get filename to process + let counter = getDbBackupFileCounter("min"); + + //we have some backup files + let dataBase = 'tbdata'; + + var nosql; + if (counter == 0) dataBase = 'tbdata'; + else dataBase = counter + "." + 'tbdata'; + + nosql = NOSQL(dataBase); + + //select all data - use limit restore_from_backup + let records = await promisifyBuilder(nosql.find().take(restore_from_backup)); + + for (let i = 0; i < records.length; i++) { + if (clientReady) { + + let item = records[i]; + let id = item.id; + + if (id !== undefined) { + //console.log("------------processDataFromDatabase - remove", id, dataBase, i); + + try { + + let message = JSON.parse(JSON.stringify(item)); + delete message.id; + + client.publish("v1/gateway/telemetry", JSON.stringify(message), { qos: 1 }); + + //remove from database + await promisifyBuilder(nosql.remove().where("id", id)); + + } catch (error) { + //process error + console.log("processDataFromDatabase", error); + } + + } + + } + else { + processingData = false; + return; + } + } + + if (records.length > 0) { + //clean backup file + if (counter > 0) nosql.clean(); + } + + //no data in db, remove + if (records.length == 0) { + if (counter > 0) nosql.drop(); + } + + const d = new Date(); + lastRestoreTime = d.getTime(); + + processingData = false; + + } + + instance.on('options', main); + //instance.reconfigure(); +}; diff --git a/RVO20/monitor.txt b/RVO20/monitor.txt new file mode 100755 index 0000000..002980c --- /dev/null +++ b/RVO20/monitor.txt @@ -0,0 +1,3207 @@ +[2024-10-11T13:29:55.042] [INFO] monitorLogs - MQTT broker error Error: connect ECONNREFUSED 192.168.252.1:1883 + at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1159:16) { + errno: -111, + code: 'ECONNREFUSED', + syscall: 'connect', + address: '192.168.252.1', + port: 1883 +} +[2024-10-11T13:30:04.909] [INFO] monitorLogs - MQTT broker connected +[2024-10-12T03:32:50.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-12 03:32:50 +[2024-10-12T13:00:22.449] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-12T13:00:22.484] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-12T13:00:22.519] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-13T03:32:51.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-13 03:32:51 +[2024-10-13T13:00:22.493] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-13T13:00:22.528] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-13T13:00:22.563] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-14T03:32:52.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-14 03:32:52 +[2024-10-14T13:00:22.649] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-14T13:00:22.683] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-14T13:00:22.718] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-15T03:32:53.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-15 03:32:53 +[2024-10-15T13:00:22.654] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-15T13:00:22.687] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-15T13:00:22.732] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-16T03:32:54.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-16 03:32:54 +[2024-10-16T13:00:22.828] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-16T13:00:22.864] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-16T13:00:22.899] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-17T03:32:55.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-17 03:32:55 +[2024-10-17T08:38:55.714] [INFO] monitorLogs - MQTT broker connected +[2024-10-17T13:00:22.898] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-17T13:00:22.933] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-17T13:00:22.968] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-18T03:32:56.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-18 03:32:56 +[2024-10-18T13:00:23.126] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-18T13:00:23.162] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-18T13:00:23.197] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-18T17:20:13.261] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T17:20:13.844] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T17:40:46.860] [INFO] monitorLogs - MQTT broker error Error: read ECONNRESET + at TCP.onStreamRead (internal/stream_base_commons.js:209:20) { + errno: -104, + code: 'ECONNRESET', + syscall: 'read' +} +[2024-10-18T17:40:47.430] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T17:54:23.259] [INFO] monitorLogs - MQTT broker error Error: read ECONNRESET + at TCP.onStreamRead (internal/stream_base_commons.js:209:20) { + errno: -104, + code: 'ECONNRESET', + syscall: 'read' +} +[2024-10-18T17:54:26.780] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T18:14:50.643] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T18:15:35.438] [INFO] monitorLogs - MQTT broker error Error: Connection refused: Server unavailable + at MqttClient._handleConnack (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:1388:17) + at MqttClient._handlePacket (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:549:12) + at work (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:438:12) + at Writable.writable._write (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:452:5) + at doWrite (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:409:139) + at writeOrBuffer (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:398:5) + at Writable.write (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:307:11) + at Socket.ondata (internal/streams/readable.js:731:22) + at Socket.emit (events.js:400:28) + at addChunk (internal/streams/readable.js:293:12) { + code: 3 +} +[2024-10-18T18:15:35.577] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T18:20:08.076] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T18:20:08.225] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T18:36:52.175] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T20:30:06.235] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T20:30:06.570] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T20:44:03.504] [INFO] monitorLogs - MQTT broker error Error: Connection refused: Server unavailable + at MqttClient._handleConnack (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:1388:17) + at MqttClient._handlePacket (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:549:12) + at work (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:438:12) + at Writable.writable._write (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:452:5) + at doWrite (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:409:139) + at writeOrBuffer (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:398:5) + at Writable.write (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:307:11) + at Socket.ondata (internal/streams/readable.js:731:22) + at Socket.emit (events.js:400:28) + at addChunk (internal/streams/readable.js:293:12) { + code: 3 +} +[2024-10-18T20:44:06.816] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T20:44:09.153] [INFO] monitorLogs - MQTT broker error Error: read ECONNRESET + at TCP.onStreamRead (internal/stream_base_commons.js:209:20) { + errno: -104, + code: 'ECONNRESET', + syscall: 'read' +} +[2024-10-18T20:44:09.292] [INFO] monitorLogs - MQTT broker connected +[2024-10-19T03:32:57.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-19 03:32:57 +[2024-10-19T13:00:23.373] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-19T13:00:23.409] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-19T13:00:23.444] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-20T03:32:58.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-20 03:32:58 +[2024-10-20T13:00:23.376] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-20T13:00:23.411] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-20T13:00:23.446] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-21T03:32:59.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-21 03:32:59 +[2024-10-21T03:51:33.779] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T04:10:09.631] [INFO] monitorLogs - MQTT broker error Error: read ECONNRESET + at TCP.onStreamRead (internal/stream_base_commons.js:209:20) { + errno: -104, + code: 'ECONNRESET', + syscall: 'read' +} +[2024-10-21T04:10:17.675] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T04:37:27.359] [INFO] monitorLogs - MQTT broker error Error: read ECONNRESET + at TCP.onStreamRead (internal/stream_base_commons.js:209:20) { + errno: -104, + code: 'ECONNRESET', + syscall: 'read' +} +[2024-10-21T04:37:31.896] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T09:11:12.519] [INFO] monitorLogs - MQTT broker error Error: read ECONNRESET + at TCP.onStreamRead (internal/stream_base_commons.js:209:20) { + errno: -104, + code: 'ECONNRESET', + syscall: 'read' +} +[2024-10-21T09:11:24.400] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T09:55:21.806] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T09:55:22.158] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T09:55:22.510] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T10:23:08.141] [INFO] monitorLogs - MQTT broker error Error: read ECONNRESET + at TCP.onStreamRead (internal/stream_base_commons.js:209:20) { + errno: -104, + code: 'ECONNRESET', + syscall: 'read' +} +[2024-10-21T10:23:10.087] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T10:44:27.064] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T13:00:23.496] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-21T13:00:23.532] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-21T13:00:23.568] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-22T03:33:00.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-22 03:33:00 +[2024-10-22T13:00:23.873] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-22T13:00:23.910] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-22T13:00:23.945] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-23T03:33:01.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-23 03:33:01 +[2024-10-23T13:00:24.207] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-23T13:00:24.242] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-23T13:00:24.278] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-24T03:33:02.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-24 03:33:02 +[2024-10-24T13:00:24.947] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-24T13:00:24.983] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-24T13:00:25.018] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-25T03:33:03.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-25 03:33:03 +[2024-10-25T09:15:14.148] [INFO] monitorLogs - DI_DO_Relay_Controller installed +[2024-10-25T09:15:14.501] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 true turn off on startup +[2024-10-25T09:15:14.503] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 true turn off on startup +[2024-10-25T09:15:14.504] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 true turn off on startup +[2024-10-25T09:15:16.263] [INFO] monitorLogs - MQTT broker connected +[2024-10-25T09:15:17.520] [INFO] monitorLogs - buildTasks - params undefined +[2024-10-25T09:15:17.522] [INFO] monitorLogs - buildTasks: profile for line 1 +[2024-10-25T09:15:17.522] [INFO] monitorLogs - 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 +} +[2024-10-25T09:15:17.525] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-10-25T09:15:17.526] [INFO] monitorLogs - profileTimepoint: turn on line: 1 2024-10-25T11:00:00.525Z +[2024-10-25T09:15:17.527] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2024-10-25T09:15:17.529] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2024-10-25T09:15:17.530] [INFO] monitorLogs - buildTasks: profile for line 2 +[2024-10-25T09:15:17.531] [INFO] monitorLogs - 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 +} +[2024-10-25T09:15:17.532] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-10-25T09:15:17.533] [INFO] monitorLogs - profileTimepoint: turn on line: 2 2024-10-25T11:00:00.533Z +[2024-10-25T09:15:17.534] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2024-10-25T09:15:17.535] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2024-10-25T09:15:17.535] [INFO] monitorLogs - buildTasks: profile for line 3 +[2024-10-25T09:15:17.536] [INFO] monitorLogs - 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 +} +[2024-10-25T09:15:17.537] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-10-25T09:15:17.538] [INFO] monitorLogs - profileTimepoint: turn on line: 3 2024-10-25T11:00:00.537Z +[2024-10-25T09:15:17.538] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2024-10-25T09:15:17.539] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2024-10-25T09:15:17.541] [INFO] monitorLogs - tasks created: 45 +[2024-10-25T09:15:17.548] [INFO] monitorLogs - -->FLOW bol spustený JX1ObgmqGZ54DMyYL7aDRmkEVdve38WKRzwjNrQ9 2024-07-08 +[2024-10-25T09:15:17.850] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-25T09:15:17.887] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-25T09:15:17.922] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-25T09:28:43.449] [INFO] monitorLogs - DI_DO_Relay_Controller installed +[2024-10-25T09:28:43.802] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 true turn off on startup +[2024-10-25T09:28:43.804] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 true turn off on startup +[2024-10-25T09:28:43.806] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 true turn off on startup +[2024-10-25T09:28:44.483] [INFO] monitorLogs - MQTT broker connected +[2024-10-25T09:28:46.822] [INFO] monitorLogs - buildTasks - params undefined +[2024-10-25T09:28:46.824] [INFO] monitorLogs - buildTasks: profile for line 1 +[2024-10-25T09:28:46.824] [INFO] monitorLogs - 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 +} +[2024-10-25T09:28:46.827] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-10-25T09:28:46.829] [INFO] monitorLogs - profileTimepoint: turn on line: 1 2024-10-25T11:00:00.827Z +[2024-10-25T09:28:46.830] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2024-10-25T09:28:46.831] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2024-10-25T09:28:46.831] [INFO] monitorLogs - buildTasks: profile for line 2 +[2024-10-25T09:28:46.832] [INFO] monitorLogs - 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 +} +[2024-10-25T09:28:46.833] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-10-25T09:28:46.834] [INFO] monitorLogs - profileTimepoint: turn on line: 2 2024-10-25T11:00:00.834Z +[2024-10-25T09:28:46.835] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2024-10-25T09:28:46.836] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2024-10-25T09:28:46.836] [INFO] monitorLogs - buildTasks: profile for line 3 +[2024-10-25T09:28:46.837] [INFO] monitorLogs - 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 +} +[2024-10-25T09:28:46.838] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-10-25T09:28:46.839] [INFO] monitorLogs - profileTimepoint: turn on line: 3 2024-10-25T11:00:00.839Z +[2024-10-25T09:28:46.840] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2024-10-25T09:28:46.841] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2024-10-25T09:28:46.847] [INFO] monitorLogs - tasks created: 1053 +[2024-10-25T09:28:46.855] [INFO] monitorLogs - -->FLOW bol spustený JX1ObgmqGZ54DMyYL7aDRmkEVdve38WKRzwjNrQ9 2024-07-08 +[2024-10-25T09:28:47.160] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-25T09:28:47.198] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-25T09:28:47.237] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-25T13:00:00.955] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-25T13:00:00.994] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-25T13:00:01.031] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-26T03:28:43.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-26 03:28:43 +[2024-10-26T13:00:01.070] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-26T13:00:01.106] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-26T13:00:01.142] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-27T03:28:44.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-27 03:28:44 +[2024-10-27T12:00:01.613] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-27T12:00:01.649] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-27T12:00:01.685] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-27T16:04:10.264] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2024-10-27T16:04:10.597] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 true turn off on startup +[2024-10-27T16:04:10.612] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 true turn off on startup +[2024-10-27T16:04:10.618] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 true turn off on startup +[2024-10-27T16:04:10.789] [INFO] monitorLogs - MQTT broker connected +[2024-10-27T16:04:15.630] [INFO] monitorLogs - buildTasks - params undefined +[2024-10-27T16:04:15.632] [INFO] monitorLogs - buildTasks: profile for line 1 +[2024-10-27T16:04:15.633] [INFO] monitorLogs - 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 +} +[2024-10-27T16:04:15.636] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-10-27T16:04:15.638] [INFO] monitorLogs - profileTimepoint: turn on line: 1 2024-10-28T12:00:00.637Z +[2024-10-27T16:04:15.641] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2024-10-27T16:04:15.642] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2024-10-27T16:04:15.643] [INFO] monitorLogs - buildTasks: profile for line 2 +[2024-10-27T16:04:15.643] [INFO] monitorLogs - 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 +} +[2024-10-27T16:04:15.645] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-10-27T16:04:15.645] [INFO] monitorLogs - profileTimepoint: turn on line: 2 2024-10-28T12:00:00.645Z +[2024-10-27T16:04:15.646] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2024-10-27T16:04:15.647] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2024-10-27T16:04:15.648] [INFO] monitorLogs - buildTasks: profile for line 3 +[2024-10-27T16:04:15.648] [INFO] monitorLogs - 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 +} +[2024-10-27T16:04:15.650] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-10-27T16:04:15.650] [INFO] monitorLogs - profileTimepoint: turn on line: 3 2024-10-28T12:00:00.650Z +[2024-10-27T16:04:15.651] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2024-10-27T16:04:15.652] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2024-10-27T16:04:15.659] [INFO] monitorLogs - tasks created: 1051 +[2024-10-27T16:04:15.662] [INFO] monitorLogs - -->FLOW bol spustený JX1ObgmqGZ54DMyYL7aDRmkEVdve38WKRzwjNrQ9 2024-09-23 +[2024-10-27T16:04:15.970] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-27T16:04:16.011] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-27T16:04:16.051] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-28T03:04:11.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-28 03:04:11 +[2024-10-28T13:00:03.130] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-28T13:00:03.168] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-28T13:00:03.204] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-29T03:04:12.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-29 03:04:12 +[2024-10-29T13:00:03.286] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-29T13:00:03.323] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-29T13:00:03.359] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-30T03:04:13.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-30 03:04:13 +[2024-10-30T13:00:04.014] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-30T13:00:04.051] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-30T13:00:04.087] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-31T03:04:14.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-31 03:04:14 +[2024-10-31T13:00:04.368] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-31T13:00:04.404] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-31T13:00:04.439] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-31T16:41:51.169] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2024-10-31T16:41:51.595] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 true turn off on startup +[2024-10-31T16:41:51.610] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 true turn off on startup +[2024-10-31T16:41:51.615] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 true turn off on startup +[2024-10-31T16:41:52.780] [INFO] monitorLogs - MQTT broker connected +[2024-10-31T16:41:56.629] [INFO] monitorLogs - buildTasks - params undefined +[2024-10-31T16:41:56.630] [INFO] monitorLogs - buildTasks: profile for line 1 +[2024-10-31T16:41:56.631] [INFO] monitorLogs - 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 +} +[2024-10-31T16:41:56.634] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-10-31T16:41:56.636] [INFO] monitorLogs - profileTimepoint: turn on line: 1 2024-11-01T12:00:00.635Z +[2024-10-31T16:41:56.637] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2024-10-31T16:41:56.638] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2024-10-31T16:41:56.639] [INFO] monitorLogs - buildTasks: profile for line 2 +[2024-10-31T16:41:56.639] [INFO] monitorLogs - 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 +} +[2024-10-31T16:41:56.641] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-10-31T16:41:56.642] [INFO] monitorLogs - profileTimepoint: turn on line: 2 2024-11-01T12:00:00.642Z +[2024-10-31T16:41:56.642] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2024-10-31T16:41:56.643] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2024-10-31T16:41:56.644] [INFO] monitorLogs - buildTasks: profile for line 3 +[2024-10-31T16:41:56.645] [INFO] monitorLogs - 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 +} +[2024-10-31T16:41:56.646] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-10-31T16:41:56.646] [INFO] monitorLogs - profileTimepoint: turn on line: 3 2024-11-01T12:00:00.646Z +[2024-10-31T16:41:56.647] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2024-10-31T16:41:56.648] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2024-10-31T16:41:56.655] [INFO] monitorLogs - tasks created: 1051 +[2024-10-31T16:41:56.662] [INFO] monitorLogs - -->FLOW bol spustený JX1ObgmqGZ54DMyYL7aDRmkEVdve38WKRzwjNrQ9 2024-09-23 +[2024-10-31T16:41:56.966] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-31T16:41:57.007] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-31T16:41:57.047] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-01T03:41:52.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-01 03:41:52 +[2024-11-01T13:00:01.812] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-01T13:00:01.850] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-01T13:00:01.886] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-02T03:41:53.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-02 03:41:53 +[2024-11-02T13:00:01.796] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-02T13:00:02.020] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-02T13:00:02.055] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-03T03:41:54.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-03 03:41:54 +[2024-11-03T13:00:01.862] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-03T13:00:02.056] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-03T13:00:02.092] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-04T03:41:55.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-04 03:41:55 +[2024-11-04T13:00:02.714] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-04T13:00:02.750] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-04T13:00:02.785] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-04T14:13:25.310] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2024-11-04T14:13:25.625] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 true turn off on startup +[2024-11-04T14:13:25.640] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 true turn off on startup +[2024-11-04T14:13:25.646] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 true turn off on startup +[2024-11-04T14:13:25.966] [INFO] monitorLogs - MQTT broker connected +[2024-11-04T14:13:30.658] [INFO] monitorLogs - buildTasks - params undefined +[2024-11-04T14:13:30.660] [INFO] monitorLogs - buildTasks: profile for line 1 +[2024-11-04T14:13:30.661] [INFO] monitorLogs - 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 +} +[2024-11-04T14:13:30.665] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-04T14:13:30.667] [INFO] monitorLogs - profileTimepoint: turn on line: 1 2024-11-05T12:00:00.666Z +[2024-11-04T14:13:30.668] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2024-11-04T14:13:30.669] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2024-11-04T14:13:30.670] [INFO] monitorLogs - buildTasks: profile for line 2 +[2024-11-04T14:13:30.670] [INFO] monitorLogs - 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 +} +[2024-11-04T14:13:30.672] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-04T14:13:30.673] [INFO] monitorLogs - profileTimepoint: turn on line: 2 2024-11-05T12:00:00.673Z +[2024-11-04T14:13:30.674] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2024-11-04T14:13:30.674] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2024-11-04T14:13:30.675] [INFO] monitorLogs - buildTasks: profile for line 3 +[2024-11-04T14:13:30.676] [INFO] monitorLogs - 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 +} +[2024-11-04T14:13:30.677] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-04T14:13:30.678] [INFO] monitorLogs - profileTimepoint: turn on line: 3 2024-11-05T12:00:00.678Z +[2024-11-04T14:13:30.678] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2024-11-04T14:13:30.679] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2024-11-04T14:13:30.686] [INFO] monitorLogs - tasks created: 1051 +[2024-11-04T14:13:30.689] [INFO] monitorLogs - -->FLOW bol spustený JX1ObgmqGZ54DMyYL7aDRmkEVdve38WKRzwjNrQ9 2024-09-23 +[2024-11-04T14:13:30.997] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-04T14:13:31.041] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-04T14:13:31.082] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-05T03:13:26.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-05 03:13:26 +[2024-11-05T13:00:00.901] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-05T13:00:00.938] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-05T13:00:00.975] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-05T23:03:58.056] [INFO] monitorLogs - MQTT broker connected +[2024-11-06T03:13:27.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-06 03:13:27 +[2024-11-06T13:00:01.117] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-06T13:00:01.154] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-06T13:00:01.191] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-07T03:13:34.671] [INFO] monitorLogs - setCorrectPlcTimeOnceADay - function error SyntaxError: Unexpected token < in JSON at position 0 + at JSON.parse () + at /home/unipi/flowserver/flow/cmd_manager.js:2898:26 + at Object.exec_callback [as callback] (/home/unipi/flowserver/node_modules/total.js/builders.js:5803:3) + at IncomingMessage.request_process_end (/home/unipi/flowserver/node_modules/total.js/utils.js:1184:11) + at IncomingMessage.emit (events.js:412:35) + at endReadableNT (internal/streams/readable.js:1334:12) + at processTicksAndRejections (internal/process/task_queues.js:82:21) 503: Service Unavailable
503
Service Unavailable
+[2024-11-07T13:00:01.107] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-07T13:00:01.358] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-07T13:00:01.394] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-08T03:13:29.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-08 03:13:29 +[2024-11-08T13:00:01.394] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-08T13:00:01.430] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-08T13:00:01.466] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-09T03:13:30.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-09 03:13:30 +[2024-11-09T13:00:01.479] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-09T13:00:01.515] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-09T13:00:01.550] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-10T03:13:36.608] [INFO] monitorLogs - setCorrectPlcTimeOnceADay - function error SyntaxError: Unexpected token < in JSON at position 0 + at JSON.parse () + at /home/unipi/flowserver/flow/cmd_manager.js:2898:26 + at Object.exec_callback [as callback] (/home/unipi/flowserver/node_modules/total.js/builders.js:5803:3) + at IncomingMessage.request_process_end (/home/unipi/flowserver/node_modules/total.js/utils.js:1184:11) + at IncomingMessage.emit (events.js:412:35) + at endReadableNT (internal/streams/readable.js:1334:12) + at processTicksAndRejections (internal/process/task_queues.js:82:21) 503: Service Unavailable
503
Service Unavailable
+[2024-11-10T13:00:01.701] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-10T13:00:01.737] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-10T13:00:01.772] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-10T15:25:43.131] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2024-11-10T15:25:48.531] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 true turn off on startup +[2024-11-10T15:25:48.533] [INFO] monitorLogs - turnLine: off pin (relay) relay1_02 +[2024-11-10T15:25:48.546] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 true turn off on startup +[2024-11-10T15:25:48.547] [INFO] monitorLogs - turnLine: off pin (relay) relay1_03 +[2024-11-10T15:25:48.552] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 true turn off on startup +[2024-11-10T15:25:48.553] [INFO] monitorLogs - turnLine: off pin (relay) relay1_04 +[2024-11-10T15:25:48.637] [INFO] monitorLogs - MQTT client connected +[2024-11-10T15:25:53.564] [INFO] monitorLogs - buildTasks - params undefined +[2024-11-10T15:25:53.566] [INFO] monitorLogs - buildTasks: profile for line 1 +[2024-11-10T15:25:53.567] [INFO] monitorLogs - 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 +} +[2024-11-10T15:25:53.570] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-10T15:25:53.571] [INFO] monitorLogs - profileTimepoint: turn on line: 1 2024-11-11T12:00:00.570Z +[2024-11-10T15:25:53.573] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2024-11-10T15:25:53.574] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2024-11-10T15:25:53.575] [INFO] monitorLogs - buildTasks: profile for line 2 +[2024-11-10T15:25:53.575] [INFO] monitorLogs - 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 +} +[2024-11-10T15:25:53.577] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-10T15:25:53.577] [INFO] monitorLogs - profileTimepoint: turn on line: 2 2024-11-11T12:00:00.577Z +[2024-11-10T15:25:53.578] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2024-11-10T15:25:53.579] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2024-11-10T15:25:53.580] [INFO] monitorLogs - buildTasks: profile for line 3 +[2024-11-10T15:25:53.580] [INFO] monitorLogs - 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 +} +[2024-11-10T15:25:53.581] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-10T15:25:53.582] [INFO] monitorLogs - profileTimepoint: turn on line: 3 2024-11-11T12:00:00.582Z +[2024-11-10T15:25:53.583] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2024-11-10T15:25:53.584] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2024-11-10T15:25:53.590] [INFO] monitorLogs - tasks created: 1051 +[2024-11-10T15:25:53.593] [INFO] monitorLogs - -->FLOW bol spustený JX1ObgmqGZ54DMyYL7aDRmkEVdve38WKRzwjNrQ9 2024-11-04 +[2024-11-10T15:25:53.900] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-10T15:25:53.901] [INFO] monitorLogs - turnLine: on pin (relay) relay1_02 +[2024-11-10T15:25:53.944] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-10T15:25:53.945] [INFO] monitorLogs - turnLine: on pin (relay) relay1_03 +[2024-11-10T15:25:53.989] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-10T15:25:53.990] [INFO] monitorLogs - turnLine: on pin (relay) relay1_04 +[2024-11-11T03:25:53.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-11 03:25:53 +[2024-11-11T13:00:01.624] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-11T13:00:01.662] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-11T13:00:01.698] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-11T23:21:55.029] [INFO] monitorLogs - MQTT client connected +[2024-11-12T03:25:54.014] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-12 03:25:54 +[2024-11-12T13:00:01.725] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-12T13:00:01.763] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-12T13:00:01.800] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-13T03:25:55.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-13 03:25:55 +[2024-11-13T10:23:18.141] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2024-11-13T10:23:23.472] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 true turn off on startup +[2024-11-13T10:23:23.486] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 true turn off on startup +[2024-11-13T10:23:23.492] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 true turn off on startup +[2024-11-13T10:23:23.582] [INFO] monitorLogs - MQTT client connected +[2024-11-13T10:23:28.505] [INFO] monitorLogs - buildTasks - params undefined +[2024-11-13T10:23:28.506] [INFO] monitorLogs - buildTasks: profile for line 1 +[2024-11-13T10:23:28.507] [INFO] monitorLogs - 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 +} +[2024-11-13T10:23:28.511] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-13T10:23:28.512] [INFO] monitorLogs - profileTimepoint: turn on line: 1 2024-11-13T12:00:00.511Z +[2024-11-13T10:23:28.513] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2024-11-13T10:23:28.514] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2024-11-13T10:23:28.515] [INFO] monitorLogs - buildTasks: profile for line 2 +[2024-11-13T10:23:28.516] [INFO] monitorLogs - 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 +} +[2024-11-13T10:23:28.517] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-13T10:23:28.518] [INFO] monitorLogs - profileTimepoint: turn on line: 2 2024-11-13T12:00:00.518Z +[2024-11-13T10:23:28.519] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2024-11-13T10:23:28.520] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2024-11-13T10:23:28.521] [INFO] monitorLogs - buildTasks: profile for line 3 +[2024-11-13T10:23:28.522] [INFO] monitorLogs - 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 +} +[2024-11-13T10:23:28.523] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-13T10:23:28.524] [INFO] monitorLogs - profileTimepoint: turn on line: 3 2024-11-13T12:00:00.524Z +[2024-11-13T10:23:28.524] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2024-11-13T10:23:28.525] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2024-11-13T10:23:28.532] [INFO] monitorLogs - tasks created: 1051 +[2024-11-13T10:23:28.536] [INFO] monitorLogs - -->FLOW bol spustený JX1ObgmqGZ54DMyYL7aDRmkEVdve38WKRzwjNrQ9 2024-11-04 +[2024-11-13T10:23:28.842] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-13T10:23:28.885] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-13T10:23:28.929] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-14T03:23:25.013] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-14 03:23:25 +[2024-11-15T03:23:26.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-15 03:23:26 +[2024-11-16T03:23:27.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-16 03:23:27 +[2024-11-17T03:23:28.013] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-17 03:23:28 +[2024-11-18T03:23:29.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-18 03:23:29 +[2024-11-19T03:23:30.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-19 03:23:30 +[2024-11-20T03:23:34.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-20 03:23:34 +[2024-11-21T03:23:36.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-21 03:23:36 +[2024-11-22T03:23:33.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-22 03:23:33 +[2024-11-23T03:23:34.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-23 03:23:34 +[2024-11-24T03:23:36.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-24 03:23:36 +[2024-11-25T03:23:36.013] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-25 03:23:36 +[2024-11-26T03:23:37.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-26 03:23:37 +[2024-11-27T03:23:38.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-27 03:23:38 +[2024-11-28T03:23:39.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-28 03:23:39 +[2024-11-29T03:23:40.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-29 03:23:40 +[2024-11-30T03:23:41.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-30 03:23:41 +[2024-11-30T15:44:55.721] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2024-11-30T15:45:01.054] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 true turn off on startup +[2024-11-30T15:45:01.068] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 true turn off on startup +[2024-11-30T15:45:01.074] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 true turn off on startup +[2024-11-30T15:45:01.321] [INFO] monitorLogs - MQTT client connected +[2024-11-30T15:45:06.085] [INFO] monitorLogs - buildTasks - params undefined +[2024-11-30T15:45:06.087] [INFO] monitorLogs - buildTasks: profile for line 1 +[2024-11-30T15:45:06.088] [INFO] monitorLogs - 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 +} +[2024-11-30T15:45:06.091] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-30T15:45:06.092] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2024-12-01T12:00:00.092Z +[2024-11-30T15:45:06.093] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2024-11-30T15:45:06.095] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2024-11-30T15:45:06.095] [INFO] monitorLogs - buildTasks: profile for line 2 +[2024-11-30T15:45:06.096] [INFO] monitorLogs - 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 +} +[2024-11-30T15:45:06.098] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-30T15:45:06.099] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2024-12-01T12:00:00.098Z +[2024-11-30T15:45:06.099] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2024-11-30T15:45:06.101] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2024-11-30T15:45:06.101] [INFO] monitorLogs - buildTasks: profile for line 3 +[2024-11-30T15:45:06.102] [INFO] monitorLogs - 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 +} +[2024-11-30T15:45:06.103] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-30T15:45:06.104] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2024-12-01T12:00:00.104Z +[2024-11-30T15:45:06.105] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2024-11-30T15:45:06.106] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2024-11-30T15:45:06.113] [INFO] monitorLogs - tasks created: 1051 +[2024-11-30T15:45:06.116] [INFO] monitorLogs - -->FLOW bol spustený JX1ObgmqGZ54DMyYL7aDRmkEVdve38WKRzwjNrQ9 2024-11-04 +[2024-11-30T15:45:06.423] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-30T15:45:06.466] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-30T15:45:06.510] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-01T03:45:03.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-01 03:45:03 +[2024-12-02T03:45:04.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-02 03:45:04 +[2024-12-03T03:45:05.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-03 03:45:05 +[2024-12-04T03:45:06.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-04 03:45:06 +[2024-12-04T11:23:44.068] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2024-12-04T11:23:49.465] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 true turn off on startup +[2024-12-04T11:23:49.478] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 true turn off on startup +[2024-12-04T11:23:49.483] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 true turn off on startup +[2024-12-04T11:23:54.495] [INFO] monitorLogs - buildTasks - params undefined +[2024-12-04T11:23:54.497] [INFO] monitorLogs - buildTasks: profile for line 1 +[2024-12-04T11:23:54.497] [INFO] monitorLogs - 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 +} +[2024-12-04T11:23:54.500] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-12-04T11:23:54.502] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2024-12-04T12:00:00.501Z +[2024-12-04T11:23:54.503] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2024-12-04T11:23:54.504] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2024-12-04T11:23:54.505] [INFO] monitorLogs - buildTasks: profile for line 2 +[2024-12-04T11:23:54.506] [INFO] monitorLogs - 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 +} +[2024-12-04T11:23:54.507] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-12-04T11:23:54.508] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2024-12-04T12:00:00.508Z +[2024-12-04T11:23:54.509] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2024-12-04T11:23:54.510] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2024-12-04T11:23:54.510] [INFO] monitorLogs - buildTasks: profile for line 3 +[2024-12-04T11:23:54.511] [INFO] monitorLogs - 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 +} +[2024-12-04T11:23:54.512] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-12-04T11:23:54.513] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2024-12-04T12:00:00.513Z +[2024-12-04T11:23:54.513] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2024-12-04T11:23:54.514] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2024-12-04T11:23:54.521] [INFO] monitorLogs - tasks created: 1051 +[2024-12-04T11:23:54.523] [INFO] monitorLogs - -->FLOW bol spustený JX1ObgmqGZ54DMyYL7aDRmkEVdve38WKRzwjNrQ9 2024-11-04 +[2024-12-04T11:23:54.831] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-04T11:23:54.872] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-04T11:23:54.913] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-04T11:31:39.127] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2024-12-04T11:31:44.525] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 true turn off on startup +[2024-12-04T11:31:44.539] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 true turn off on startup +[2024-12-04T11:31:44.545] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 true turn off on startup +[2024-12-04T11:31:44.671] [INFO] monitorLogs - MQTT client connected +[2024-12-04T11:31:49.556] [INFO] monitorLogs - buildTasks - params undefined +[2024-12-04T11:31:49.557] [INFO] monitorLogs - buildTasks: profile for line 1 +[2024-12-04T11:31:49.558] [INFO] monitorLogs - 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 +} +[2024-12-04T11:31:49.561] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-12-04T11:31:49.563] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2024-12-04T12:00:00.562Z +[2024-12-04T11:31:49.564] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2024-12-04T11:31:49.565] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2024-12-04T11:31:49.566] [INFO] monitorLogs - buildTasks: profile for line 2 +[2024-12-04T11:31:49.567] [INFO] monitorLogs - 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 +} +[2024-12-04T11:31:49.568] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-12-04T11:31:49.569] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2024-12-04T12:00:00.569Z +[2024-12-04T11:31:49.570] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2024-12-04T11:31:49.571] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2024-12-04T11:31:49.571] [INFO] monitorLogs - buildTasks: profile for line 3 +[2024-12-04T11:31:49.572] [INFO] monitorLogs - 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 +} +[2024-12-04T11:31:49.573] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-12-04T11:31:49.574] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2024-12-04T12:00:00.574Z +[2024-12-04T11:31:49.574] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2024-12-04T11:31:49.575] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2024-12-04T11:31:49.582] [INFO] monitorLogs - tasks created: 1051 +[2024-12-04T11:31:49.588] [INFO] monitorLogs - -->FLOW bol spustený JX1ObgmqGZ54DMyYL7aDRmkEVdve38WKRzwjNrQ9 2024-11-04 +[2024-12-04T11:31:49.894] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-04T11:31:49.938] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-04T11:31:49.981] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-05T03:31:47.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-05 03:31:47 +[2024-12-06T03:31:48.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-06 03:31:48 +[2024-12-07T03:31:49.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-07 03:31:49 +[2024-12-08T03:31:50.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-08 03:31:50 +[2024-12-09T03:31:51.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-09 03:31:51 +[2024-12-09T09:15:35.355] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-09T09:15:36.463] [INFO] monitorLogs - websocket error, reconnect +[2024-12-09T09:15:36.466] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-09T09:24:00.171] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2024-12-09T09:24:05.506] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 true turn off on startup +[2024-12-09T09:24:05.520] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 true turn off on startup +[2024-12-09T09:24:05.526] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 true turn off on startup +[2024-12-09T09:24:05.736] [INFO] monitorLogs - MQTT client connected +[2024-12-09T09:24:10.537] [INFO] monitorLogs - buildTasks - params undefined +[2024-12-09T09:24:10.538] [INFO] monitorLogs - buildTasks: profile for line 1 +[2024-12-09T09:24:10.539] [INFO] monitorLogs - 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 +} +[2024-12-09T09:24:10.543] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-12-09T09:24:10.544] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2024-12-09T12:00:00.543Z +[2024-12-09T09:24:10.545] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2024-12-09T09:24:10.546] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2024-12-09T09:24:10.547] [INFO] monitorLogs - buildTasks: profile for line 2 +[2024-12-09T09:24:10.548] [INFO] monitorLogs - 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 +} +[2024-12-09T09:24:10.549] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-12-09T09:24:10.550] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2024-12-09T12:00:00.550Z +[2024-12-09T09:24:10.551] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2024-12-09T09:24:10.552] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2024-12-09T09:24:10.553] [INFO] monitorLogs - buildTasks: profile for line 3 +[2024-12-09T09:24:10.553] [INFO] monitorLogs - 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 +} +[2024-12-09T09:24:10.555] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-12-09T09:24:10.555] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2024-12-09T12:00:00.555Z +[2024-12-09T09:24:10.556] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2024-12-09T09:24:10.557] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2024-12-09T09:24:10.564] [INFO] monitorLogs - tasks created: 1051 +[2024-12-09T09:24:10.567] [INFO] monitorLogs - -->FLOW bol spustený JX1ObgmqGZ54DMyYL7aDRmkEVdve38WKRzwjNrQ9 2024-11-04 +[2024-12-09T09:24:10.873] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-09T09:24:10.915] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-09T09:24:10.959] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-10T03:24:07.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-10 03:24:07 +[2024-12-10T06:41:02.583] [INFO] monitorLogs - MQTT client connected +[2024-12-11T03:24:08.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-11 03:24:08 +[2024-12-12T03:24:09.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-12 03:24:09 +[2024-12-13T03:24:11.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-13 03:24:11 +[2024-12-14T03:24:12.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-14 03:24:12 +[2024-12-15T03:24:12.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-15 03:24:12 +[2024-12-16T03:24:14.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-16 03:24:14 +[2024-12-17T03:24:14.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-17 03:24:14 +[2024-12-18T03:24:15.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-18 03:24:15 +[2024-12-19T03:24:16.013] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-19 03:24:16 +[2024-12-20T03:24:17.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-20 03:24:17 +[2024-12-21T03:24:18.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-21 03:24:18 +[2024-12-22T03:24:19.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-22 03:24:19 +[2024-12-23T03:24:20.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-23 03:24:20 +[2024-12-24T03:24:21.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-24 03:24:21 +[2024-12-25T03:24:22.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-25 03:24:22 +[2024-12-26T03:24:23.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-26 03:24:23 +[2024-12-27T03:24:24.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-27 03:24:24 +[2024-12-28T03:24:25.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-28 03:24:25 +[2024-12-29T03:24:26.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-29 03:24:26 +[2024-12-30T03:24:27.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-30 03:24:27 +[2024-12-31T03:24:28.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-31 03:24:28 +[2025-01-01T03:24:29.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-01 03:24:29 +[2025-01-02T03:24:30.015] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-02 03:24:30 +[2025-01-02T08:47:39.004] [INFO] monitorLogs - MQTT client error Error: read ECONNRESET + at TCP.onStreamRead (internal/stream_base_commons.js:209:20) { + errno: -104, + code: 'ECONNRESET', + syscall: 'read' +} +[2025-01-02T11:45:06.138] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-01-02T11:45:11.512] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 true turn off on startup +[2025-01-02T11:45:11.527] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 true turn off on startup +[2025-01-02T11:45:11.533] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 true turn off on startup +[2025-01-02T11:45:11.604] [INFO] monitorLogs - MQTT client error Error: connect ECONNREFUSED 192.168.252.1:1883 + at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1159:16) { + errno: -111, + code: 'ECONNREFUSED', + syscall: 'connect', + address: '192.168.252.1', + port: 1883 +} +[2025-01-02T11:45:16.547] [INFO] monitorLogs - buildTasks - params undefined +[2025-01-02T11:45:16.548] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-01-02T11:45:16.549] [INFO] monitorLogs - 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 +} +[2025-01-02T11:45:16.552] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-02T11:45:16.553] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-01-02T12:00:00.552Z +[2025-01-02T11:45:16.554] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-01-02T11:45:16.555] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-01-02T11:45:16.556] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-01-02T11:45:16.557] [INFO] monitorLogs - 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 +} +[2025-01-02T11:45:16.559] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-02T11:45:16.559] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-01-02T12:00:00.559Z +[2025-01-02T11:45:16.560] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-01-02T11:45:16.561] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-01-02T11:45:16.562] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-01-02T11:45:16.562] [INFO] monitorLogs - 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 +} +[2025-01-02T11:45:16.564] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-02T11:45:16.564] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-01-02T12:00:00.564Z +[2025-01-02T11:45:16.565] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-01-02T11:45:16.566] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-01-02T11:45:16.573] [INFO] monitorLogs - tasks created: 1051 +[2025-01-02T11:45:16.575] [INFO] monitorLogs - -->FLOW bol spustený JX1ObgmqGZ54DMyYL7aDRmkEVdve38WKRzwjNrQ9 2025-01-02 +[2025-01-02T11:45:16.882] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-02T11:45:16.923] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-02T11:45:16.963] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-03T03:45:12.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-03 03:45:12 +[2025-01-03T10:17:24.447] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-01-03T10:17:29.796] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 true turn off on startup +[2025-01-03T10:17:29.812] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 true turn off on startup +[2025-01-03T10:17:29.819] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 true turn off on startup +[2025-01-03T10:17:29.838] [INFO] monitorLogs - MQTT client error Error: connect ECONNREFUSED 192.168.252.1:1883 + at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1159:16) { + errno: -111, + code: 'ECONNREFUSED', + syscall: 'connect', + address: '192.168.252.1', + port: 1883 +} +[2025-01-03T10:17:34.831] [INFO] monitorLogs - buildTasks - params undefined +[2025-01-03T10:17:34.833] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-01-03T10:17:34.833] [INFO] monitorLogs - 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 +} +[2025-01-03T10:17:34.837] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-03T10:17:34.838] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-01-03T12:00:00.837Z +[2025-01-03T10:17:34.839] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-01-03T10:17:34.840] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-01-03T10:17:34.841] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-01-03T10:17:34.842] [INFO] monitorLogs - 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 +} +[2025-01-03T10:17:34.843] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-03T10:17:34.844] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-01-03T12:00:00.844Z +[2025-01-03T10:17:34.845] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-01-03T10:17:34.846] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-01-03T10:17:34.846] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-01-03T10:17:34.847] [INFO] monitorLogs - 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 +} +[2025-01-03T10:17:34.848] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-03T10:17:34.849] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-01-03T12:00:00.849Z +[2025-01-03T10:17:34.850] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-01-03T10:17:34.852] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-01-03T10:17:34.862] [INFO] monitorLogs - tasks created: 1051 +[2025-01-03T10:17:34.864] [INFO] monitorLogs - -->FLOW bol spustený JX1ObgmqGZ54DMyYL7aDRmkEVdve38WKRzwjNrQ9 2025-01-02 +[2025-01-03T10:17:35.172] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-03T10:17:35.214] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-03T10:17:35.255] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-04T03:17:31.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-04 03:17:31 +[2025-01-05T03:17:32.017] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-05 03:17:32 +[2025-01-06T03:17:33.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-06 03:17:33 +[2025-01-07T03:17:34.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-07 03:17:34 +[2025-01-08T03:17:35.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-08 03:17:35 +[2025-01-09T03:17:36.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-09 03:17:36 +[2025-01-09T15:28:55.809] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-01-09T15:29:01.164] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 true turn off on startup +[2025-01-09T15:29:01.178] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 true turn off on startup +[2025-01-09T15:29:01.185] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 true turn off on startup +[2025-01-09T15:29:01.199] [INFO] monitorLogs - MQTT client error Error: connect ECONNREFUSED 192.168.252.1:1883 + at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1159:16) { + errno: -111, + code: 'ECONNREFUSED', + syscall: 'connect', + address: '192.168.252.1', + port: 1883 +} +[2025-01-09T15:29:06.196] [INFO] monitorLogs - buildTasks - params undefined +[2025-01-09T15:29:06.198] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-01-09T15:29:06.199] [INFO] monitorLogs - 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 +} +[2025-01-09T15:29:06.202] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-09T15:29:06.203] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-01-10T12:00:00.203Z +[2025-01-09T15:29:06.204] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-01-09T15:29:06.206] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-01-09T15:29:06.206] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-01-09T15:29:06.207] [INFO] monitorLogs - 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 +} +[2025-01-09T15:29:06.209] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-09T15:29:06.209] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-01-10T12:00:00.209Z +[2025-01-09T15:29:06.210] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-01-09T15:29:06.212] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-01-09T15:29:06.212] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-01-09T15:29:06.213] [INFO] monitorLogs - 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 +} +[2025-01-09T15:29:06.214] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-09T15:29:06.215] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-01-10T12:00:00.215Z +[2025-01-09T15:29:06.215] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-01-09T15:29:06.216] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-01-09T15:29:06.224] [INFO] monitorLogs - tasks created: 1051 +[2025-01-09T15:29:06.226] [INFO] monitorLogs - -->FLOW bol spustený JX1ObgmqGZ54DMyYL7aDRmkEVdve38WKRzwjNrQ9 2025-01-02 +[2025-01-09T15:29:06.533] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-09T15:29:06.573] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-09T15:29:06.615] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-10T03:29:03.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-10 03:29:03 +[2025-01-10T14:43:52.048] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-01-10T14:43:57.394] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 true turn off on startup +[2025-01-10T14:43:57.409] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 true turn off on startup +[2025-01-10T14:43:57.416] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 true turn off on startup +[2025-01-10T14:43:57.574] [INFO] monitorLogs - MQTT client error Error: connect ECONNREFUSED 192.168.252.1:1883 + at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1159:16) { + errno: -111, + code: 'ECONNREFUSED', + syscall: 'connect', + address: '192.168.252.1', + port: 1883 +} +[2025-01-10T14:44:02.428] [INFO] monitorLogs - buildTasks - params undefined +[2025-01-10T14:44:02.430] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-01-10T14:44:02.430] [INFO] monitorLogs - 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 +} +[2025-01-10T14:44:02.433] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-10T14:44:02.435] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-01-11T12:00:00.434Z +[2025-01-10T14:44:02.435] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-01-10T14:44:02.437] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-01-10T14:44:02.437] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-01-10T14:44:02.438] [INFO] monitorLogs - 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 +} +[2025-01-10T14:44:02.440] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-10T14:44:02.441] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-01-11T12:00:00.440Z +[2025-01-10T14:44:02.441] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-01-10T14:44:02.442] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-01-10T14:44:02.443] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-01-10T14:44:02.443] [INFO] monitorLogs - 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 +} +[2025-01-10T14:44:02.445] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-10T14:44:02.446] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-01-11T12:00:00.445Z +[2025-01-10T14:44:02.446] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-01-10T14:44:02.447] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-01-10T14:44:02.454] [INFO] monitorLogs - tasks created: 1051 +[2025-01-10T14:44:02.457] [INFO] monitorLogs - -->FLOW bol spustený JX1ObgmqGZ54DMyYL7aDRmkEVdve38WKRzwjNrQ9 2025-01-09 +[2025-01-10T14:44:02.764] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-10T14:44:02.805] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-10T14:44:02.846] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-10T15:58:15.649] [INFO] monitorLogs - MQTT client connected +[2025-01-11T03:43:59.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-11 03:43:59 +[2025-01-12T03:44:00.013] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-12 03:44:00 +[2025-01-13T03:44:01.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-13 03:44:01 +[2025-01-14T03:44:02.014] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-14 03:44:02 +[2025-01-15T03:44:03.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-15 03:44:03 +[2025-01-16T03:44:04.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-16 03:44:04 +[2025-01-17T03:44:05.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-17 03:44:05 +[2025-01-18T03:44:06.015] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-18 03:44:06 +[2025-01-19T03:44:07.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-19 03:44:07 +[2025-01-20T03:44:08.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-20 03:44:08 +[2025-01-21T03:44:09.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-21 03:44:09 +[2025-01-22T03:44:09.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-22 03:44:09 +[2025-01-23T03:44:10.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-23 03:44:10 +[2025-01-24T01:27:31.276] [INFO] monitorLogs - MQTT client connected +[2025-01-24T03:44:11.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-24 03:44:11 +[2025-01-25T03:44:12.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-25 03:44:12 +[2025-01-26T03:44:13.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-26 03:44:13 +[2025-01-27T03:44:14.013] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-27 03:44:14 +[2025-01-28T03:44:15.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-28 03:44:15 +[2025-01-29T03:44:16.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-29 03:44:16 +[2025-01-30T03:44:17.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-30 03:44:17 +[2025-01-31T03:44:18.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-31 03:44:18 +[2025-02-01T03:44:19.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-01 03:44:19 +[2025-02-02T03:44:20.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-02 03:44:20 +[2025-02-03T03:44:21.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-03 03:44:21 +[2025-02-04T03:44:22.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-04 03:44:22 +[2025-02-05T03:44:23.013] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-05 03:44:23 +[2025-02-06T03:44:24.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-06 03:44:24 +[2025-02-07T03:44:25.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-07 03:44:25 +[2025-02-08T03:44:26.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-08 03:44:26 +[2025-02-09T03:44:27.013] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-09 03:44:27 +[2025-02-09T13:23:12.115] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-02-09T13:23:17.474] [INFO] monitorLogs - buildTasks - params undefined +[2025-02-09T13:23:17.479] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-02-09T13:23:17.480] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-02-09T13:23:17.481] [INFO] monitorLogs - 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 +} +[2025-02-09T13:23:17.484] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-02-09T13:23:17.486] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-02-10T12:00:00.485Z +[2025-02-09T13:23:17.487] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-02-09T13:23:17.488] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-02-09T13:23:17.489] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-02-09T13:23:17.489] [INFO] monitorLogs - 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 +} +[2025-02-09T13:23:17.491] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-02-09T13:23:17.491] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-02-10T12:00:00.491Z +[2025-02-09T13:23:17.492] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-02-09T13:23:17.493] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-02-09T13:23:17.494] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-02-09T13:23:17.495] [INFO] monitorLogs - 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 +} +[2025-02-09T13:23:17.496] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-02-09T13:23:17.497] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-02-10T12:00:00.496Z +[2025-02-09T13:23:17.497] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-02-09T13:23:17.498] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-02-09T13:23:17.504] [INFO] monitorLogs - tasks created: 986 +[2025-02-09T13:23:17.506] [INFO] monitorLogs - -->FLOW bol spustený JX1ObgmqGZ54DMyYL7aDRmkEVdve38WKRzwjNrQ9 2025-01-30 +[2025-02-09T13:23:17.669] [INFO] monitorLogs - MQTT client connected +[2025-02-09T13:23:17.816] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-02-09T13:23:18.120] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-02-09T13:23:18.424] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-02-10T03:23:19.013] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-10 03:23:19 +[2025-02-11T03:23:20.019] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-11 03:23:20 +[2025-02-11T13:33:51.259] [INFO] monitorLogs - MQTT client connected +[2025-02-12T03:23:21.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-12 03:23:21 +[2025-02-13T03:23:22.013] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-13 03:23:22 +[2025-02-13T09:49:18.658] [INFO] monitorLogs - MQTT client connected +[2025-02-13T13:18:36.029] [INFO] monitorLogs - MQTT client connected +[2025-02-13T13:21:28.277] [INFO] monitorLogs - MQTT client connected +[2025-02-13T13:21:46.769] [INFO] monitorLogs - MQTT client connected +[2025-02-13T13:31:35.142] [INFO] monitorLogs - MQTT client connected +[2025-02-13T15:22:54.768] [INFO] monitorLogs - MQTT client connected +[2025-02-14T03:23:23.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-14 03:23:23 +[2025-02-15T03:23:24.018] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-15 03:23:24 +[2025-02-16T03:23:25.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-16 03:23:25 +[2025-02-17T03:23:25.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-17 03:23:25 +[2025-02-17T07:02:43.228] [INFO] monitorLogs - MQTT client connected +[2025-02-17T07:03:15.774] [INFO] monitorLogs - MQTT client connected +[2025-02-17T08:02:37.713] [INFO] monitorLogs - MQTT client connected +[2025-02-17T08:04:53.421] [INFO] monitorLogs - MQTT client connected +[2025-02-17T08:56:02.723] [INFO] monitorLogs - MQTT client connected +[2025-02-17T08:56:37.231] [INFO] monitorLogs - MQTT client connected +[2025-02-18T03:23:26.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-18 03:23:26 +[2025-02-19T03:23:27.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-19 03:23:27 +[2025-02-19T15:06:48.190] [INFO] monitorLogs - MQTT client connected +[2025-02-19T15:09:52.585] [INFO] monitorLogs - MQTT client connected +[2025-02-19T15:12:57.800] [INFO] monitorLogs - MQTT client connected +[2025-02-20T03:23:28.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-20 03:23:28 +[2025-02-20T09:19:55.182] [INFO] monitorLogs - MQTT client connected +[2025-02-20T09:20:36.577] [INFO] monitorLogs - MQTT client connected +[2025-02-21T03:23:35.560] [INFO] monitorLogs - setCorrectPlcTimeOnceADay - function error SyntaxError: Unexpected token < in JSON at position 0 + at JSON.parse () + at /home/unipi/flowserver/flow/cmd_manager.js:2409:28 + at Object.exec_callback [as callback] (/home/unipi/flowserver/node_modules/total.js/builders.js:5803:3) + at IncomingMessage.request_process_end (/home/unipi/flowserver/node_modules/total.js/utils.js:1184:11) + at IncomingMessage.emit (events.js:412:35) + at endReadableNT (internal/streams/readable.js:1334:12) + at processTicksAndRejections (internal/process/task_queues.js:82:21) 503: Service Unavailable
503
Service Unavailable
+[2025-02-22T03:23:30.014] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-22 03:23:30 +[2025-02-23T03:23:31.015] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-23 03:23:31 +[2025-02-24T03:23:32.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-24 03:23:32 +[2025-02-24T09:10:07.898] [INFO] monitorLogs - MQTT client connected +[2025-02-24T14:02:24.048] [INFO] monitorLogs - MQTT client connected +[2025-02-25T03:23:33.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-25 03:23:33 +[2025-02-25T06:51:04.974] [INFO] monitorLogs - MQTT client connected +[2025-02-25T06:51:44.097] [INFO] monitorLogs - MQTT client connected +[2025-02-25T06:52:23.273] [INFO] monitorLogs - MQTT client connected +[2025-02-25T06:52:50.195] [INFO] monitorLogs - MQTT client connected +[2025-02-25T06:55:39.390] [INFO] monitorLogs - MQTT client connected +[2025-02-25T06:56:21.674] [INFO] monitorLogs - MQTT client connected +[2025-02-25T06:58:02.468] [INFO] monitorLogs - MQTT client connected +[2025-02-25T06:59:47.108] [INFO] monitorLogs - MQTT client connected +[2025-02-25T07:00:28.413] [INFO] monitorLogs - MQTT client connected +[2025-02-25T07:11:58.140] [INFO] monitorLogs - MQTT client connected +[2025-02-25T07:18:29.218] [INFO] monitorLogs - MQTT client connected +[2025-02-25T12:39:22.974] [INFO] monitorLogs - MQTT client connected +[2025-02-25T14:05:37.492] [INFO] monitorLogs - MQTT client connected +[2025-02-25T14:07:13.559] [INFO] monitorLogs - MQTT client connected +[2025-02-25T14:07:48.479] [INFO] monitorLogs - MQTT client connected +[2025-02-25T14:13:09.350] [INFO] monitorLogs - MQTT client connected +[2025-02-25T14:15:35.146] [INFO] monitorLogs - MQTT client connected +[2025-02-25T14:20:55.280] [INFO] monitorLogs - MQTT client connected +[2025-02-26T03:23:34.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-26 03:23:34 +[2025-02-27T03:23:35.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-27 03:23:35 +[2025-02-28T03:23:36.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-28 03:23:36 +[2025-02-28T12:20:56.325] [INFO] monitorLogs - MQTT client connected +[2025-02-28T12:26:52.476] [INFO] monitorLogs - MQTT client connected +[2025-03-01T03:23:37.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-01 03:23:37 +[2025-03-02T03:23:39.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-02 03:23:39 +[2025-03-03T03:23:39.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-03 03:23:39 +[2025-03-04T03:23:40.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-04 03:23:40 +[2025-03-04T07:19:47.779] [INFO] monitorLogs - MQTT client connected +[2025-03-05T03:23:41.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-05 03:23:41 +[2025-03-06T03:23:42.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-06 03:23:42 +[2025-03-07T03:23:43.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-07 03:23:43 +[2025-03-08T03:23:44.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-08 03:23:44 +[2025-03-09T03:23:45.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-09 03:23:45 +[2025-03-10T03:23:46.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-10 03:23:46 +[2025-03-10T06:45:29.505] [INFO] monitorLogs - MQTT client connected +[2025-03-10T20:31:55.176] [INFO] monitorLogs - MQTT client connected +[2025-03-11T03:23:47.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-11 03:23:47 +[2025-03-11T08:19:17.149] [INFO] monitorLogs - MQTT client connected +[2025-03-11T08:24:23.375] [INFO] monitorLogs - MQTT client connected +[2025-03-11T08:25:31.539] [INFO] monitorLogs - MQTT client connected +[2025-03-12T03:23:48.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-12 03:23:48 +[2025-03-12T16:09:31.947] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-03-12T16:09:37.332] [INFO] monitorLogs - buildTasks - params undefined +[2025-03-12T16:09:37.337] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-03-12T16:09:37.338] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-03-12T16:09:37.339] [INFO] monitorLogs - 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 +} +[2025-03-12T16:09:37.341] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-03-12T16:09:37.343] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-03-13T12:00:00.342Z +[2025-03-12T16:09:37.344] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-03-12T16:09:37.345] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-03-12T16:09:37.346] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-03-12T16:09:37.347] [INFO] monitorLogs - 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 +} +[2025-03-12T16:09:37.348] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-03-12T16:09:37.349] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-03-13T12:00:00.349Z +[2025-03-12T16:09:37.350] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-03-12T16:09:37.351] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-03-12T16:09:37.351] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-03-12T16:09:37.352] [INFO] monitorLogs - 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 +} +[2025-03-12T16:09:37.353] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-03-12T16:09:37.354] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-03-13T12:00:00.354Z +[2025-03-12T16:09:37.354] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-03-12T16:09:37.355] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-03-12T16:09:37.361] [INFO] monitorLogs - tasks created: 986 +[2025-03-12T16:09:37.363] [INFO] monitorLogs - -->FLOW bol spustený JX1ObgmqGZ54DMyYL7aDRmkEVdve38WKRzwjNrQ9 2025-01-30 +[2025-03-12T16:09:37.437] [INFO] monitorLogs - MQTT client connected +[2025-03-12T16:09:37.672] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-03-12T16:09:37.976] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-03-12T16:09:38.280] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-03-13T03:09:39.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-13 03:09:39 +[2025-03-13T06:36:31.269] [INFO] monitorLogs - MQTT client connected +[2025-03-13T09:45:11.370] [INFO] monitorLogs - MQTT client connected +[2025-03-13T09:46:31.125] [INFO] monitorLogs - MQTT client connected +[2025-03-13T09:46:52.689] [INFO] monitorLogs - MQTT client connected +[2025-03-13T09:47:56.688] [INFO] monitorLogs - MQTT client connected +[2025-03-13T09:49:41.327] [INFO] monitorLogs - MQTT client connected +[2025-03-13T09:50:27.714] [INFO] monitorLogs - MQTT client connected +[2025-03-14T03:09:40.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-14 03:09:40 +[2025-03-15T03:09:41.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-15 03:09:41 +[2025-03-16T03:09:42.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-16 03:09:42 +[2025-03-17T03:09:43.015] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-17 03:09:43 +[2025-03-17T07:05:54.508] [INFO] monitorLogs - MQTT client connected +[2025-03-18T03:09:44.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-18 03:09:44 +[2025-03-19T03:09:45.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-19 03:09:45 +[2025-03-20T03:09:46.013] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-20 03:09:46 +[2025-03-21T03:09:47.014] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-21 03:09:47 +[2025-03-22T03:09:48.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-22 03:09:48 +[2025-03-23T03:09:49.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-23 03:09:49 +[2025-03-24T03:09:50.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-24 03:09:50 +[2025-03-24T07:07:11.972] [INFO] monitorLogs - MQTT client connected +[2025-03-24T09:29:45.029] [INFO] monitorLogs - MQTT client connected +[2025-03-24T10:08:17.303] [INFO] monitorLogs - MQTT client connected +[2025-03-24T10:23:04.519] [INFO] monitorLogs - MQTT client connected +[2025-03-24T12:32:32.592] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-03-24T12:32:37.988] [INFO] monitorLogs - buildTasks - params undefined +[2025-03-24T12:32:37.992] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-03-24T12:32:37.994] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-03-24T12:32:37.994] [INFO] monitorLogs - 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 +} +[2025-03-24T12:32:37.997] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-03-24T12:32:37.999] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-03-24T12:00:00.998Z +[2025-03-24T12:32:38.000] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-03-24T12:32:38.001] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-03-24T12:32:38.002] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-03-24T12:32:38.002] [INFO] monitorLogs - 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 +} +[2025-03-24T12:32:38.004] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-03-24T12:32:38.005] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-03-24T12:00:00.004Z +[2025-03-24T12:32:38.005] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-03-24T12:32:38.006] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-03-24T12:32:38.007] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-03-24T12:32:38.008] [INFO] monitorLogs - 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 +} +[2025-03-24T12:32:38.009] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-03-24T12:32:38.010] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-03-24T12:00:00.010Z +[2025-03-24T12:32:38.010] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-03-24T12:32:38.011] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-03-24T12:32:38.017] [INFO] monitorLogs - tasks created: 986 +[2025-03-24T12:32:38.020] [INFO] monitorLogs - -->FLOW bol spustený JX1ObgmqGZ54DMyYL7aDRmkEVdve38WKRzwjNrQ9 2025-01-30 +[2025-03-24T12:32:38.100] [INFO] monitorLogs - MQTT client connected +[2025-03-24T12:32:38.329] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-03-24T12:32:38.633] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-03-24T12:32:38.938] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-03-25T03:32:39.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-25 03:32:39 +[2025-03-25T12:59:21.790] [INFO] monitorLogs - MQTT client connected +[2025-03-25T13:39:23.207] [INFO] monitorLogs - MQTT client connected +[2025-03-26T03:32:40.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-26 03:32:40 +[2025-03-27T03:32:42.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-27 03:32:42 +[2025-03-28T03:32:43.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-28 03:32:43 +[2025-03-28T07:34:54.364] [INFO] monitorLogs - MQTT client connected +[2025-03-28T07:37:24.070] [INFO] monitorLogs - MQTT client connected +[2025-03-28T07:38:14.910] [INFO] monitorLogs - MQTT client connected +[2025-03-28T18:28:38.402] [INFO] monitorLogs - MQTT client connected +[2025-03-29T03:32:44.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-29 03:32:44 +[2025-03-30T03:32:45.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-30 03:32:45 +[2025-03-31T03:32:46.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-31 03:32:46 +[2025-03-31T06:48:45.070] [INFO] monitorLogs - MQTT client connected +[2025-03-31T06:49:42.079] [INFO] monitorLogs - MQTT client connected +[2025-04-01T03:32:47.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-01 03:32:47 +[2025-04-01T07:56:54.359] [INFO] monitorLogs - MQTT client connected +[2025-04-02T02:18:02.864] [INFO] monitorLogs - MQTT client connected +[2025-04-02T03:24:22.171] [INFO] monitorLogs - MQTT client connected +[2025-04-02T03:32:48.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-02 03:32:48 +[2025-04-03T03:32:49.016] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-03 03:32:49 +[2025-04-04T03:32:50.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-04 03:32:50 +[2025-04-05T03:32:51.013] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-05 03:32:51 +[2025-04-06T03:32:52.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-06 03:32:52 +[2025-04-07T03:32:53.013] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-07 03:32:53 +[2025-04-07T08:37:23.630] [INFO] monitorLogs - MQTT client connected +[2025-04-07T08:41:46.850] [INFO] monitorLogs - MQTT client connected +[2025-04-08T03:32:54.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-08 03:32:54 +[2025-04-09T03:32:55.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-09 03:32:55 +[2025-04-10T03:32:56.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-10 03:32:56 +[2025-04-11T03:32:57.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-11 03:32:57 +[2025-04-12T03:32:58.014] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-12 03:32:58 +[2025-04-13T03:32:59.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-13 03:32:59 +[2025-04-14T03:33:00.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-14 03:33:00 +[2025-04-14T16:19:37.180] [INFO] monitorLogs - MQTT client connected +[2025-04-15T03:33:02.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-15 03:33:02 +[2025-04-15T11:19:24.469] [INFO] monitorLogs - MQTT client connected +[2025-04-16T03:33:03.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-16 03:33:03 +[2025-04-17T03:33:04.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-17 03:33:04 +[2025-04-18T03:33:05.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-18 03:33:05 +[2025-04-19T03:33:06.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-19 03:33:06 +[2025-04-20T03:33:07.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-20 03:33:07 +[2025-04-21T03:33:08.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-21 03:33:08 +[2025-04-22T03:33:09.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-22 03:33:09 +[2025-04-22T12:13:59.202] [INFO] monitorLogs - MQTT client connected +[2025-04-23T03:33:11.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-23 03:33:11 +[2025-04-23T06:54:32.476] [INFO] monitorLogs - MQTT client connected +[2025-04-24T03:33:12.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-24 03:33:12 +[2025-04-24T08:32:23.226] [INFO] monitorLogs - MQTT client connected +[2025-04-24T18:03:27.589] [INFO] monitorLogs - MQTT client connected +[2025-04-24T18:05:04.433] [INFO] monitorLogs - MQTT client connected +[2025-04-25T03:33:13.016] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-25 03:33:13 +[2025-04-25T10:31:39.662] [INFO] monitorLogs - MQTT client connected +[2025-04-26T03:33:14.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-26 03:33:14 +[2025-04-27T03:33:15.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-27 03:33:15 +[2025-04-28T03:33:16.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-28 03:33:16 +[2025-04-28T08:58:23.279] [INFO] monitorLogs - Thermometer is not responding Error: Command failed: owread -C 28.52309C0E0000/temperature +ServerRead: Data error on 28.52309C0E0000/temperature + + at ChildProcess.exithandler (child_process.js:383:12) + at ChildProcess.emit (events.js:400:28) + at maybeClose (internal/child_process.js:1058:16) + at Socket. (internal/child_process.js:443:11) + at Socket.emit (events.js:400:28) + at Pipe. (net.js:686:12) { + killed: false, + code: 1, + signal: null, + cmd: 'owread -C 28.52309C0E0000/temperature' +} +[2025-04-29T03:33:18.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-29 03:33:18 +[2025-04-29T06:56:32.782] [INFO] monitorLogs - MQTT client connected +[2025-04-29T07:54:32.598] [INFO] monitorLogs - MQTT client connected +[2025-04-29T07:54:41.031] [INFO] monitorLogs - MQTT client connected +[2025-04-30T03:33:19.013] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-30 03:33:19 +[2025-04-30T17:00:52.214] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-04-30T17:00:57.598] [INFO] monitorLogs - buildTasks - params undefined +[2025-04-30T17:00:57.602] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-04-30T17:00:57.604] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-04-30T17:00:57.604] [INFO] monitorLogs - 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 +} +[2025-04-30T17:00:57.607] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-04-30T17:00:57.609] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-05-01T11:00:00.608Z +[2025-04-30T17:00:57.610] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-04-30T17:00:57.611] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-04-30T17:00:57.612] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-04-30T17:00:57.612] [INFO] monitorLogs - 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 +} +[2025-04-30T17:00:57.614] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-04-30T17:00:57.615] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-05-01T11:00:00.614Z +[2025-04-30T17:00:57.615] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-04-30T17:00:57.616] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-04-30T17:00:57.617] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-04-30T17:00:57.617] [INFO] monitorLogs - 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 +} +[2025-04-30T17:00:57.619] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-04-30T17:00:57.619] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-05-01T11:00:00.619Z +[2025-04-30T17:00:57.620] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-04-30T17:00:57.621] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-04-30T17:00:57.627] [INFO] monitorLogs - tasks created: 921 +[2025-04-30T17:00:57.629] [INFO] monitorLogs - -->FLOW bol spustený JX1ObgmqGZ54DMyYL7aDRmkEVdve38WKRzwjNrQ9 2025-04-24 +[2025-04-30T17:00:57.755] [INFO] monitorLogs - MQTT client connected +[2025-04-30T17:00:57.938] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-04-30T17:00:58.243] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-04-30T17:00:58.548] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-05-01T03:01:01.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-01 03:01:01 +[2025-05-02T03:01:02.013] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-02 03:01:02 +[2025-05-03T03:01:03.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-03 03:01:03 +[2025-05-04T03:01:12.564] [INFO] monitorLogs - setCorrectPlcTimeOnceADay - function error SyntaxError: Unexpected token < in JSON at position 0 + at JSON.parse () + at /home/unipi/flowserver/flow/cmd_manager.js:2431:28 + at Object.exec_callback [as callback] (/home/unipi/flowserver/node_modules/total.js/builders.js:5803:3) + at IncomingMessage.request_process_end (/home/unipi/flowserver/node_modules/total.js/utils.js:1184:11) + at IncomingMessage.emit (events.js:412:35) + at endReadableNT (internal/streams/readable.js:1334:12) + at processTicksAndRejections (internal/process/task_queues.js:82:21) 503: Service Unavailable
503
Service Unavailable
+[2025-05-05T03:01:05.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-05 03:01:05 +[2025-05-05T07:42:02.092] [INFO] monitorLogs - MQTT client connected +[2025-05-06T03:01:06.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-06 03:01:06 +[2025-05-06T08:19:38.820] [INFO] monitorLogs - MQTT client connected +[2025-05-07T03:01:07.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-07 03:01:07 +[2025-05-07T13:29:00.341] [INFO] monitorLogs - MQTT client connected +[2025-05-07T19:30:44.179] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-05-07T19:30:49.538] [INFO] monitorLogs - buildTasks - params undefined +[2025-05-07T19:30:49.542] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-05-07T19:30:49.544] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-05-07T19:30:49.544] [INFO] monitorLogs - 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 +} +[2025-05-07T19:30:49.547] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-05-07T19:30:49.549] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-05-08T11:00:00.548Z +[2025-05-07T19:30:49.550] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-05-07T19:30:49.552] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-05-07T19:30:49.552] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-05-07T19:30:49.553] [INFO] monitorLogs - 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 +} +[2025-05-07T19:30:49.554] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-05-07T19:30:49.555] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-05-08T11:00:00.555Z +[2025-05-07T19:30:49.556] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-05-07T19:30:49.557] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-05-07T19:30:49.558] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-05-07T19:30:49.558] [INFO] monitorLogs - 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 +} +[2025-05-07T19:30:49.559] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-05-07T19:30:49.560] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-05-08T11:00:00.560Z +[2025-05-07T19:30:49.561] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-05-07T19:30:49.562] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-05-07T19:30:49.583] [INFO] monitorLogs - tasks created: 921 +[2025-05-07T19:30:49.586] [INFO] monitorLogs - -->FLOW bol spustený JX1ObgmqGZ54DMyYL7aDRmkEVdve38WKRzwjNrQ9 2025-04-24 +[2025-05-07T19:30:49.694] [INFO] monitorLogs - MQTT client connected +[2025-05-07T19:30:49.895] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-05-07T19:30:50.198] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-05-07T19:30:50.502] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-05-08T03:30:52.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-08 03:30:52 +[2025-05-09T03:30:53.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-09 03:30:53 +[2025-05-10T03:30:55.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-10 03:30:55 +[2025-05-11T03:30:56.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-11 03:30:56 +[2025-05-12T03:30:57.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-12 03:30:57 +[2025-05-12T09:52:09.576] [INFO] monitorLogs - MQTT client connected +[2025-05-13T03:30:58.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-13 03:30:58 +[2025-05-13T08:22:05.023] [INFO] monitorLogs - MQTT client connected +[2025-05-13T09:59:11.835] [INFO] monitorLogs - MQTT client connected +[2025-05-14T03:30:59.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-14 03:30:59 +[2025-05-14T07:43:26.123] [INFO] monitorLogs - MQTT client connected +[2025-05-14T07:44:04.568] [INFO] monitorLogs - MQTT client connected +[2025-05-14T08:30:21.414] [INFO] monitorLogs - MQTT client connected +[2025-05-14T09:42:06.700] [INFO] monitorLogs - MQTT client connected +[2025-05-14T10:08:58.646] [INFO] monitorLogs - MQTT client connected +[2025-05-14T10:48:40.447] [INFO] monitorLogs - MQTT client connected +[2025-05-14T10:50:48.466] [INFO] monitorLogs - MQTT client connected +[2025-05-14T10:52:35.644] [INFO] monitorLogs - MQTT client connected +[2025-05-14T10:53:14.081] [INFO] monitorLogs - MQTT client connected +[2025-05-14T10:55:31.396] [INFO] monitorLogs - MQTT client connected +[2025-05-14T10:57:28.711] [INFO] monitorLogs - MQTT client connected +[2025-05-15T03:31:00.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-15 03:31:00 +[2025-05-16T03:31:02.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-16 03:31:02 +[2025-05-16T10:05:55.896] [INFO] monitorLogs - MQTT client connected +[2025-05-17T03:31:03.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-17 03:31:03 +[2025-05-18T03:31:04.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-18 03:31:04 +[2025-05-19T03:31:05.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-19 03:31:05 +[2025-05-19T06:53:55.817] [INFO] monitorLogs - MQTT client connected +[2025-05-20T03:31:06.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-20 03:31:06 +[2025-05-20T08:28:49.164] [INFO] monitorLogs - MQTT client connected +[2025-05-20T08:32:18.759] [INFO] monitorLogs - MQTT client connected +[2025-05-21T03:31:07.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-21 03:31:07 +[2025-05-22T03:31:08.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-22 03:31:08 +[2025-05-23T03:31:09.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-23 03:31:09 +[2025-05-23T10:57:03.014] [INFO] monitorLogs - MQTT client connected +[2025-05-24T03:31:10.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-24 03:31:10 +[2025-05-25T03:31:11.013] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-25 03:31:11 +[2025-05-26T03:31:13.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-26 03:31:13 +[2025-05-26T07:08:21.004] [INFO] monitorLogs - MQTT client connected +[2025-05-27T03:31:14.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-27 03:31:14 +[2025-05-27T11:00:25.104] [INFO] monitorLogs - MQTT client connected +[2025-05-27T12:50:26.581] [INFO] monitorLogs - MQTT client connected +[2025-05-28T03:31:15.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-28 03:31:15 +[2025-05-28T10:12:20.632] [INFO] monitorLogs - MQTT client connected +[2025-05-29T03:31:16.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-29 03:31:16 +[2025-05-30T03:31:17.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-30 03:31:17 +[2025-05-31T03:31:18.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-31 03:31:18 +[2025-05-31T13:45:56.533] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-05-31T13:46:01.990] [INFO] monitorLogs - buildTasks - params undefined +[2025-05-31T13:46:01.994] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-05-31T13:46:01.995] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-05-31T13:46:01.996] [INFO] monitorLogs - 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 +} +[2025-05-31T13:46:01.999] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-05-31T13:46:02.000] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-06-01T11:00:00.999Z +[2025-05-31T13:46:02.001] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-05-31T13:46:02.002] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-05-31T13:46:02.003] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-05-31T13:46:02.004] [INFO] monitorLogs - 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 +} +[2025-05-31T13:46:02.006] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-05-31T13:46:02.007] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-06-01T11:00:00.006Z +[2025-05-31T13:46:02.008] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-05-31T13:46:02.009] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-05-31T13:46:02.010] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-05-31T13:46:02.010] [INFO] monitorLogs - 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 +} +[2025-05-31T13:46:02.012] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-05-31T13:46:02.012] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-06-01T11:00:00.012Z +[2025-05-31T13:46:02.013] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-05-31T13:46:02.014] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-05-31T13:46:02.038] [INFO] monitorLogs - tasks created: 921 +[2025-05-31T13:46:02.040] [INFO] monitorLogs - -->FLOW bol spustený JX1ObgmqGZ54DMyYL7aDRmkEVdve38WKRzwjNrQ9 2025-04-24 +[2025-05-31T13:46:07.049] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-01T03:46:05.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-01 03:46:05 +[2025-06-02T03:46:06.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-02 03:46:06 +[2025-06-03T03:46:08.029] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-03 03:46:08 +[2025-06-04T03:46:09.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-04 03:46:09 +[2025-06-05T03:46:11.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-05 03:46:11 +[2025-06-06T03:46:12.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-06 03:46:12 +[2025-06-07T03:46:13.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-07 03:46:13 +[2025-06-08T03:46:15.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-08 03:46:15 +[2025-06-09T03:46:16.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-09 03:46:16 +[2025-06-10T03:46:17.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-10 03:46:17 +[2025-06-11T03:46:18.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-11 03:46:18 +[2025-06-12T03:46:19.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-12 03:46:19 +[2025-06-13T03:46:21.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-13 03:46:21 +[2025-06-13T15:28:58.102] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-06-13T15:29:03.462] [INFO] monitorLogs - buildTasks - params undefined +[2025-06-13T15:29:03.467] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-06-13T15:29:03.468] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-06-13T15:29:03.468] [INFO] monitorLogs - 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 +} +[2025-06-13T15:29:03.471] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-06-13T15:29:03.473] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-06-14T11:00:00.472Z +[2025-06-13T15:29:03.474] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-06-13T15:29:03.475] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-06-13T15:29:03.476] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-06-13T15:29:03.476] [INFO] monitorLogs - 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 +} +[2025-06-13T15:29:03.478] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-06-13T15:29:03.478] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-06-14T11:00:00.478Z +[2025-06-13T15:29:03.479] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-06-13T15:29:03.480] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-06-13T15:29:03.481] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-06-13T15:29:03.481] [INFO] monitorLogs - 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 +} +[2025-06-13T15:29:03.483] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-06-13T15:29:03.483] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-06-14T11:00:00.483Z +[2025-06-13T15:29:03.484] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-06-13T15:29:03.485] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-06-13T15:29:03.507] [INFO] monitorLogs - tasks created: 921 +[2025-06-13T15:29:03.510] [INFO] monitorLogs - -->FLOW bol spustený JX1ObgmqGZ54DMyYL7aDRmkEVdve38WKRzwjNrQ9 2025-04-24 +[2025-06-13T15:29:08.519] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-14T03:29:06.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-14 03:29:06 +[2025-06-15T03:29:07.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-15 03:29:07 +[2025-06-16T03:29:08.028] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-16 03:29:08 +[2025-06-17T03:29:10.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-17 03:29:10 +[2025-06-17T16:09:21.185] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-06-17T16:09:26.553] [INFO] monitorLogs - buildTasks - params undefined +[2025-06-17T16:09:26.559] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-06-17T16:09:26.560] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-06-17T16:09:26.561] [INFO] monitorLogs - 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 +} +[2025-06-17T16:09:26.565] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-06-17T16:09:26.566] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-06-18T11:00:00.565Z +[2025-06-17T16:09:26.568] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-06-17T16:09:26.569] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-06-17T16:09:26.570] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-06-17T16:09:26.571] [INFO] monitorLogs - 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 +} +[2025-06-17T16:09:26.573] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-06-17T16:09:26.574] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-06-18T11:00:00.574Z +[2025-06-17T16:09:26.575] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-06-17T16:09:26.576] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-06-17T16:09:26.577] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-06-17T16:09:26.578] [INFO] monitorLogs - 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 +} +[2025-06-17T16:09:26.579] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-06-17T16:09:26.580] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-06-18T11:00:00.580Z +[2025-06-17T16:09:26.581] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-06-17T16:09:26.582] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-06-17T16:09:26.604] [INFO] monitorLogs - tasks created: 921 +[2025-06-17T16:09:26.606] [INFO] monitorLogs - -->FLOW bol spustený JX1ObgmqGZ54DMyYL7aDRmkEVdve38WKRzwjNrQ9 2025-04-24 +[2025-06-17T16:09:31.615] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-17T16:10:45.216] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-06-17T16:10:50.584] [INFO] monitorLogs - buildTasks - params undefined +[2025-06-17T16:10:50.588] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-06-17T16:10:50.589] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-06-17T16:10:50.590] [INFO] monitorLogs - 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 +} +[2025-06-17T16:10:50.593] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-06-17T16:10:50.594] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-06-18T11:00:00.593Z +[2025-06-17T16:10:50.595] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-06-17T16:10:50.597] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-06-17T16:10:50.597] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-06-17T16:10:50.598] [INFO] monitorLogs - 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 +} +[2025-06-17T16:10:50.599] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-06-17T16:10:50.600] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-06-18T11:00:00.600Z +[2025-06-17T16:10:50.601] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-06-17T16:10:50.602] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-06-17T16:10:50.603] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-06-17T16:10:50.603] [INFO] monitorLogs - 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 +} +[2025-06-17T16:10:50.605] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-06-17T16:10:50.605] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-06-18T11:00:00.605Z +[2025-06-17T16:10:50.606] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-06-17T16:10:50.607] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-06-17T16:10:50.630] [INFO] monitorLogs - tasks created: 921 +[2025-06-17T16:10:50.633] [INFO] monitorLogs - -->FLOW bol spustený JX1ObgmqGZ54DMyYL7aDRmkEVdve38WKRzwjNrQ9 2025-04-24 +[2025-06-17T16:10:55.642] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-18T03:10:52.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-18 03:10:52 +[2025-06-19T03:10:54.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-19 03:10:54 +[2025-06-20T03:10:55.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-20 03:10:55 +[2025-06-21T03:10:56.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-21 03:10:56 +[2025-06-22T03:10:58.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-22 03:10:58 +[2025-06-23T03:10:59.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-23 03:10:59 +[2025-06-24T03:11:00.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-24 03:11:00 +[2025-06-25T03:11:02.014] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-25 03:11:02 +[2025-06-26T03:11:03.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-26 03:11:03 +[2025-06-27T03:11:05.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-27 03:11:05 +[2025-06-28T03:11:06.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-28 03:11:06 +[2025-06-29T03:11:08.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-29 03:11:08 +[2025-06-30T03:11:09.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-30 03:11:09 +[2025-07-01T03:11:10.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-01 03:11:10 +[2025-07-02T03:11:12.014] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-02 03:11:12 +[2025-07-03T03:11:13.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-03 03:11:13 +[2025-07-04T03:11:15.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-04 03:11:15 +[2025-07-05T03:11:16.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-05 03:11:16 +[2025-07-06T03:11:18.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-06 03:11:18 +[2025-07-07T03:11:19.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-07 03:11:19 +[2025-07-07T13:46:56.145] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-07-07T13:47:01.510] [INFO] monitorLogs - buildTasks - params undefined +[2025-07-07T13:47:01.515] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-07-07T13:47:01.516] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-07-07T13:47:01.517] [INFO] monitorLogs - 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 +} +[2025-07-07T13:47:01.519] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-07-07T13:47:01.521] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-07-08T11:00:00.520Z +[2025-07-07T13:47:01.522] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-07-07T13:47:01.523] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-07-07T13:47:01.524] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-07-07T13:47:01.524] [INFO] monitorLogs - 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 +} +[2025-07-07T13:47:01.526] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-07-07T13:47:01.527] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-07-08T11:00:00.526Z +[2025-07-07T13:47:01.527] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-07-07T13:47:01.528] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-07-07T13:47:01.529] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-07-07T13:47:01.530] [INFO] monitorLogs - 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 +} +[2025-07-07T13:47:01.531] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-07-07T13:47:01.532] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-07-08T11:00:00.531Z +[2025-07-07T13:47:01.532] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-07-07T13:47:01.533] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-07-07T13:47:01.558] [INFO] monitorLogs - tasks created: 921 +[2025-07-07T13:47:01.561] [INFO] monitorLogs - -->FLOW bol spustený JX1ObgmqGZ54DMyYL7aDRmkEVdve38WKRzwjNrQ9 2025-07-08 +[2025-07-07T13:47:06.569] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-08T03:47:04.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-08 03:47:04 +[2025-07-09T03:47:05.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-09 03:47:05 +[2025-07-10T02:24:04.615] [INFO] monitorLogs - MQTT client error Error: connect ECONNREFUSED 192.168.252.1:1883 + at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1159:16) { + errno: -111, + code: 'ECONNREFUSED', + syscall: 'connect', + address: '192.168.252.1', + port: 1883 +} +[2025-07-10T03:47:07.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-10 03:47:07 +[2025-07-11T03:47:08.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-11 03:47:08 +[2025-07-12T03:47:09.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-12 03:47:09 +[2025-07-13T03:47:10.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-13 03:47:10 +[2025-07-14T03:47:12.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-14 03:47:12 +[2025-07-15T03:47:13.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-15 03:47:13 +[2025-07-16T03:47:15.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-16 03:47:15 +[2025-07-17T03:47:16.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-17 03:47:16 +[2025-07-18T03:47:17.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-18 03:47:17 +[2025-07-19T03:47:19.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-19 03:47:19 +[2025-07-20T03:47:20.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-20 03:47:20 +[2025-07-21T03:47:21.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-21 03:47:21 +[2025-07-22T03:47:23.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-22 03:47:23 +[2025-07-23T03:47:24.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-23 03:47:24 +[2025-07-24T03:47:26.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-24 03:47:26 +[2025-07-25T03:47:27.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-25 03:47:27 +[2025-07-26T03:47:28.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-26 03:47:28 +[2025-07-27T03:47:30.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-27 03:47:30 +[2025-07-28T03:47:31.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-28 03:47:31 +[2025-07-29T03:47:32.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-29 03:47:32 +[2025-07-29T12:19:35.168] [INFO] monitorLogs - MQTT client error Error: connect ECONNREFUSED 192.168.252.1:1883 + at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1159:16) { + errno: -111, + code: 'ECONNREFUSED', + syscall: 'connect', + address: '192.168.252.1', + port: 1883 +} +[2025-07-30T03:47:34.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-30 03:47:34 +[2025-07-31T03:47:35.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-31 03:47:35 +[2025-08-01T03:47:36.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-01 03:47:36 +[2025-08-02T03:47:38.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-02 03:47:38 +[2025-08-03T03:47:39.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-03 03:47:39 +[2025-08-04T03:47:40.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-04 03:47:40 +[2025-08-05T03:47:41.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-05 03:47:41 +[2025-08-06T03:47:43.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-06 03:47:43 +[2025-08-06T13:43:35.138] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-08-06T13:43:40.517] [INFO] monitorLogs - buildTasks - params undefined +[2025-08-06T13:43:40.522] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-08-06T13:43:40.523] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-08-06T13:43:40.524] [INFO] monitorLogs - 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 +} +[2025-08-06T13:43:40.527] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-08-06T13:43:40.528] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-08-07T11:00:00.527Z +[2025-08-06T13:43:40.530] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-08-06T13:43:40.531] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-08-06T13:43:40.532] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-08-06T13:43:40.532] [INFO] monitorLogs - 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 +} +[2025-08-06T13:43:40.534] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-08-06T13:43:40.534] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-08-07T11:00:00.534Z +[2025-08-06T13:43:40.535] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-08-06T13:43:40.536] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-08-06T13:43:40.537] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-08-06T13:43:40.537] [INFO] monitorLogs - 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 +} +[2025-08-06T13:43:40.539] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-08-06T13:43:40.539] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-08-07T11:00:00.539Z +[2025-08-06T13:43:40.540] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-08-06T13:43:40.541] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-08-06T13:43:40.562] [INFO] monitorLogs - tasks created: 921 +[2025-08-06T13:43:40.565] [INFO] monitorLogs - -->FLOW bol spustený JX1ObgmqGZ54DMyYL7aDRmkEVdve38WKRzwjNrQ9 2025-08-08 +[2025-08-06T13:43:45.575] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-07T03:43:42.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-07 03:43:42 +[2025-08-08T03:43:43.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-08 03:43:43 +[2025-08-09T03:43:45.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-09 03:43:45 +[2025-08-10T03:43:46.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-10 03:43:46 +[2025-08-11T03:43:47.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-11 03:43:47 +[2025-08-12T03:43:49.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-12 03:43:49 +[2025-08-13T03:43:50.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-13 03:43:50 +[2025-08-14T03:43:52.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-14 03:43:52 +[2025-08-15T03:43:53.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-15 03:43:53 +[2025-08-16T03:43:55.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-16 03:43:55 +[2025-08-17T03:43:56.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-17 03:43:56 +[2025-08-18T03:43:57.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-18 03:43:57 +[2025-08-19T03:43:59.014] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-19 03:43:59 +[2025-08-20T03:44:00.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-20 03:44:00 +[2025-08-21T03:44:01.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-21 03:44:01 +[2025-08-22T03:44:03.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-22 03:44:03 +[2025-08-23T03:44:04.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-23 03:44:04 +[2025-08-24T03:44:05.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-24 03:44:05 +[2025-08-25T03:44:06.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-25 03:44:06 +[2025-08-26T03:44:08.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-26 03:44:08 +[2025-08-27T03:44:09.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-27 03:44:09 +[2025-08-28T03:44:10.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-28 03:44:10 +[2025-08-29T03:44:12.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-29 03:44:12 +[2025-08-30T03:44:13.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-30 03:44:13 +[2025-08-31T03:44:14.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-31 03:44:14 +[2025-09-01T03:44:16.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-01 03:44:16 +[2025-09-02T03:44:17.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-02 03:44:17 +[2025-09-03T03:44:18.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-03 03:44:18 +[2025-09-04T03:44:20.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-04 03:44:20 +[2025-09-05T03:44:21.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-05 03:44:21 +[2025-09-06T03:44:23.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-06 03:44:23 +[2025-09-07T03:44:24.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-07 03:44:24 +[2025-09-08T03:44:25.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-08 03:44:25 +[2025-09-09T03:44:26.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-09 03:44:26 +[2025-09-10T03:44:28.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-10 03:44:28 +[2025-09-11T03:44:29.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-11 03:44:29 +[2025-09-12T03:44:30.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-12 03:44:30 +[2025-09-13T03:44:31.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-13 03:44:31 +[2025-09-14T03:44:33.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-14 03:44:33 +[2025-09-15T03:44:34.016] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-15 03:44:34 +[2025-09-16T03:44:35.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-16 03:44:35 +[2025-09-16T15:45:12.980] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-09-16T15:45:18.366] [INFO] monitorLogs - buildTasks - params undefined +[2025-09-16T15:45:18.370] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-09-16T15:45:18.371] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-09-16T15:45:18.372] [INFO] monitorLogs - 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 +} +[2025-09-16T15:45:18.374] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-16T15:45:18.376] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-09-17T11:00:00.375Z +[2025-09-16T15:45:18.377] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-09-16T15:45:18.379] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-09-16T15:45:18.380] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-09-16T15:45:18.381] [INFO] monitorLogs - 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 +} +[2025-09-16T15:45:18.382] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-16T15:45:18.383] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-09-17T11:00:00.383Z +[2025-09-16T15:45:18.384] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-09-16T15:45:18.385] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-09-16T15:45:18.385] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-09-16T15:45:18.386] [INFO] monitorLogs - 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 +} +[2025-09-16T15:45:18.387] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-16T15:45:18.388] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-09-17T11:00:00.388Z +[2025-09-16T15:45:18.389] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-09-16T15:45:18.390] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-09-16T15:45:18.413] [INFO] monitorLogs - tasks created: 921 +[2025-09-16T15:45:18.415] [INFO] monitorLogs - -->FLOW bol spustený JX1ObgmqGZ54DMyYL7aDRmkEVdve38WKRzwjNrQ9 2025-08-08 +[2025-09-16T15:45:23.423] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-17T03:45:20.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-17 03:45:20 +[2025-09-17T20:41:33.137] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-09-17T20:41:38.523] [INFO] monitorLogs - buildTasks - params undefined +[2025-09-17T20:41:38.527] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-09-17T20:41:38.528] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-09-17T20:41:38.529] [INFO] monitorLogs - 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 +} +[2025-09-17T20:41:38.532] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-17T20:41:38.533] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-09-18T11:00:00.533Z +[2025-09-17T20:41:38.535] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-09-17T20:41:38.536] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-09-17T20:41:38.537] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-09-17T20:41:38.537] [INFO] monitorLogs - 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 +} +[2025-09-17T20:41:38.538] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-17T20:41:38.539] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-09-18T11:00:00.539Z +[2025-09-17T20:41:38.540] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-09-17T20:41:38.541] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-09-17T20:41:38.542] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-09-17T20:41:38.543] [INFO] monitorLogs - 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 +} +[2025-09-17T20:41:38.545] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-17T20:41:38.545] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-09-18T11:00:00.545Z +[2025-09-17T20:41:38.546] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-09-17T20:41:38.547] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-09-17T20:41:38.569] [INFO] monitorLogs - tasks created: 921 +[2025-09-17T20:41:38.572] [INFO] monitorLogs - -->FLOW bol spustený JX1ObgmqGZ54DMyYL7aDRmkEVdve38WKRzwjNrQ9 2025-08-08 +[2025-09-17T20:41:43.580] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-18T03:41:40.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-18 03:41:40 +[2025-09-19T03:41:41.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-19 03:41:41 +[2025-09-19T11:21:07.476] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-09-19T11:21:12.846] [INFO] monitorLogs - buildTasks - params undefined +[2025-09-19T11:21:12.850] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-09-19T11:21:12.851] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-09-19T11:21:12.852] [INFO] monitorLogs - 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 +} +[2025-09-19T11:21:12.855] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-19T11:21:12.856] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-09-19T11:00:00.855Z +[2025-09-19T11:21:12.857] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-09-19T11:21:12.858] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-09-19T11:21:12.859] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-09-19T11:21:12.860] [INFO] monitorLogs - 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 +} +[2025-09-19T11:21:12.861] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-19T11:21:12.862] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-09-19T11:00:00.862Z +[2025-09-19T11:21:12.863] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-09-19T11:21:12.864] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-09-19T11:21:12.864] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-09-19T11:21:12.865] [INFO] monitorLogs - 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 +} +[2025-09-19T11:21:12.866] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-19T11:21:12.867] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-09-19T11:00:00.867Z +[2025-09-19T11:21:12.867] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-09-19T11:21:12.869] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-09-19T11:21:12.891] [INFO] monitorLogs - tasks created: 921 +[2025-09-19T11:21:12.894] [INFO] monitorLogs - -->FLOW bol spustený JX1ObgmqGZ54DMyYL7aDRmkEVdve38WKRzwjNrQ9 2025-08-08 +[2025-09-19T11:21:17.902] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-20T03:21:15.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-20 03:21:15 +[2025-09-21T01:29:23.307] [INFO] monitorLogs - MQTT client error Error: connect ECONNREFUSED 192.168.252.1:1883 + at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1159:16) { + errno: -111, + code: 'ECONNREFUSED', + syscall: 'connect', + address: '192.168.252.1', + port: 1883 +} +[2025-09-21T03:21:16.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-21 03:21:16 +[2025-09-21T18:12:01.683] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-09-21T18:12:07.042] [INFO] monitorLogs - buildTasks - params undefined +[2025-09-21T18:12:07.047] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-09-21T18:12:07.048] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-09-21T18:12:07.049] [INFO] monitorLogs - 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 +} +[2025-09-21T18:12:07.052] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-21T18:12:07.053] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-09-22T11:00:00.052Z +[2025-09-21T18:12:07.054] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-09-21T18:12:07.055] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-09-21T18:12:07.056] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-09-21T18:12:07.057] [INFO] monitorLogs - 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 +} +[2025-09-21T18:12:07.058] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-21T18:12:07.059] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-09-22T11:00:00.059Z +[2025-09-21T18:12:07.060] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-09-21T18:12:07.061] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-09-21T18:12:07.061] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-09-21T18:12:07.062] [INFO] monitorLogs - 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 +} +[2025-09-21T18:12:07.063] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-21T18:12:07.064] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-09-22T11:00:00.064Z +[2025-09-21T18:12:07.065] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-09-21T18:12:07.066] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-09-21T18:12:07.071] [INFO] monitorLogs - tasks created: 921 +[2025-09-21T18:12:07.091] [INFO] monitorLogs - -->FLOW bol spustený JX1ObgmqGZ54DMyYL7aDRmkEVdve38WKRzwjNrQ9 2025-08-08 +[2025-09-21T18:12:12.082] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-22T03:12:09.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-22 03:12:09 +[2025-09-23T03:12:10.014] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-23 03:12:10 +[2025-09-23T13:07:08.188] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-09-23T13:07:13.545] [INFO] monitorLogs - buildTasks - params undefined +[2025-09-23T13:07:13.550] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-09-23T13:07:13.551] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-09-23T13:07:13.551] [INFO] monitorLogs - 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 +} +[2025-09-23T13:07:13.554] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-23T13:07:13.555] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-09-24T11:00:00.555Z +[2025-09-23T13:07:13.557] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-09-23T13:07:13.558] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-09-23T13:07:13.559] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-09-23T13:07:13.559] [INFO] monitorLogs - 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 +} +[2025-09-23T13:07:13.561] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-23T13:07:13.561] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-09-24T11:00:00.561Z +[2025-09-23T13:07:13.562] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-09-23T13:07:13.563] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-09-23T13:07:13.564] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-09-23T13:07:13.564] [INFO] monitorLogs - 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 +} +[2025-09-23T13:07:13.567] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-23T13:07:13.567] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-09-24T11:00:00.567Z +[2025-09-23T13:07:13.568] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-09-23T13:07:13.569] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-09-23T13:07:13.591] [INFO] monitorLogs - tasks created: 921 +[2025-09-23T13:07:13.594] [INFO] monitorLogs - -->FLOW bol spustený JX1ObgmqGZ54DMyYL7aDRmkEVdve38WKRzwjNrQ9 2025-08-08 +[2025-09-23T13:07:18.602] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-23T14:33:39.768] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-09-23T14:33:45.110] [INFO] monitorLogs - buildTasks - params undefined +[2025-09-23T14:33:45.115] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-09-23T14:33:45.116] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-09-23T14:33:45.117] [INFO] monitorLogs - 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 +} +[2025-09-23T14:33:45.120] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-23T14:33:45.122] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-09-24T11:00:00.121Z +[2025-09-23T14:33:45.123] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-09-23T14:33:45.124] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-09-23T14:33:45.125] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-09-23T14:33:45.126] [INFO] monitorLogs - 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 +} +[2025-09-23T14:33:45.127] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-23T14:33:45.128] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-09-24T11:00:00.128Z +[2025-09-23T14:33:45.129] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-09-23T14:33:45.130] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-09-23T14:33:45.130] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-09-23T14:33:45.131] [INFO] monitorLogs - 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 +} +[2025-09-23T14:33:45.132] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-23T14:33:45.133] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-09-24T11:00:00.133Z +[2025-09-23T14:33:45.134] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-09-23T14:33:45.135] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-09-23T14:33:45.157] [INFO] monitorLogs - tasks created: 921 +[2025-09-23T14:33:45.159] [INFO] monitorLogs - -->FLOW bol spustený JX1ObgmqGZ54DMyYL7aDRmkEVdve38WKRzwjNrQ9 2025-08-08 +[2025-09-23T14:33:50.168] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-24T03:33:48.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-24 03:33:48 +[2025-09-25T03:33:49.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-25 03:33:49 +[2025-09-25T16:33:34.820] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-09-25T16:33:40.171] [INFO] monitorLogs - buildTasks - params undefined +[2025-09-25T16:33:40.177] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-09-25T16:33:40.178] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-09-25T16:33:40.178] [INFO] monitorLogs - 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 +} +[2025-09-25T16:33:40.181] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-25T16:33:40.183] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-09-26T11:00:00.182Z +[2025-09-25T16:33:40.184] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-09-25T16:33:40.185] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-09-25T16:33:40.186] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-09-25T16:33:40.186] [INFO] monitorLogs - 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 +} +[2025-09-25T16:33:40.188] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-25T16:33:40.188] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-09-26T11:00:00.188Z +[2025-09-25T16:33:40.189] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-09-25T16:33:40.190] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-09-25T16:33:40.191] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-09-25T16:33:40.192] [INFO] monitorLogs - 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 +} +[2025-09-25T16:33:40.193] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-25T16:33:40.194] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-09-26T11:00:00.194Z +[2025-09-25T16:33:40.194] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-09-25T16:33:40.195] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-09-25T16:33:40.217] [INFO] monitorLogs - tasks created: 921 +[2025-09-25T16:33:40.219] [INFO] monitorLogs - -->FLOW bol spustený JX1ObgmqGZ54DMyYL7aDRmkEVdve38WKRzwjNrQ9 2025-08-08 +[2025-09-25T16:33:45.227] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-26T03:33:41.014] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-26 03:33:41 +[2025-09-27T03:33:42.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-27 03:33:42 +[2025-09-28T03:33:44.022] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-28 03:33:44 +[2025-09-29T03:33:45.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-29 03:33:45 +[2025-09-30T03:33:46.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-30 03:33:46 +[2025-10-01T03:33:47.013] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-01 03:33:47 +[2025-10-02T03:33:48.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-02 03:33:48 +[2025-10-03T03:33:49.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-03 03:33:49 +[2025-10-03T14:49:17.403] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-03T14:49:22.768] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-03T14:49:22.773] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-03T14:49:22.774] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-03T14:49:22.775] [INFO] monitorLogs - 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 +} +[2025-10-03T14:49:22.778] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-03T14:49:22.779] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-10-04T11:00:00.778Z +[2025-10-03T14:49:22.780] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-03T14:49:22.782] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-10-03T14:49:22.782] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-03T14:49:22.783] [INFO] monitorLogs - 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 +} +[2025-10-03T14:49:22.784] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-03T14:49:22.785] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-10-04T11:00:00.785Z +[2025-10-03T14:49:22.786] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-03T14:49:22.787] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-10-03T14:49:22.788] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-03T14:49:22.788] [INFO] monitorLogs - 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 +} +[2025-10-03T14:49:22.790] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-03T14:49:22.790] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-10-04T11:00:00.790Z +[2025-10-03T14:49:22.791] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-03T14:49:22.792] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-10-03T14:49:22.814] [INFO] monitorLogs - tasks created: 921 +[2025-10-03T14:49:22.816] [INFO] monitorLogs - -->FLOW bol spustený JX1ObgmqGZ54DMyYL7aDRmkEVdve38WKRzwjNrQ9 2025-08-08 +[2025-10-03T14:49:27.823] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-04T03:49:25.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-04 03:49:25 +[2025-10-05T03:49:26.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-05 03:49:26 +[2025-10-06T03:49:27.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-06 03:49:27 +[2025-10-07T03:49:28.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-07 03:49:28 +[2025-10-08T03:49:29.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-08 03:49:29 +[2025-10-09T03:49:30.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-09 03:49:30 +[2025-10-09T16:54:26.460] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-09T16:54:31.825] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-09T16:54:31.830] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-09T16:54:31.831] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-09T16:54:31.832] [INFO] monitorLogs - 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 +} +[2025-10-09T16:54:31.834] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T16:54:31.836] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-10-10T11:00:00.835Z +[2025-10-09T16:54:31.837] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-09T16:54:31.838] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-10-09T16:54:31.839] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-09T16:54:31.840] [INFO] monitorLogs - 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 +} +[2025-10-09T16:54:31.841] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T16:54:31.842] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-10-10T11:00:00.842Z +[2025-10-09T16:54:31.842] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-09T16:54:31.844] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-10-09T16:54:31.844] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-09T16:54:31.845] [INFO] monitorLogs - 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 +} +[2025-10-09T16:54:31.846] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T16:54:31.847] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-10-10T11:00:00.847Z +[2025-10-09T16:54:31.848] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-09T16:54:31.848] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-10-09T16:54:31.871] [INFO] monitorLogs - tasks created: 921 +[2025-10-09T16:54:31.874] [INFO] monitorLogs - -->FLOW bol spustený JX1ObgmqGZ54DMyYL7aDRmkEVdve38WKRzwjNrQ9 2025-08-08 +[2025-10-09T16:54:36.881] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-09T19:06:59.224] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-09T19:07:04.579] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-09T19:07:04.584] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-09T19:07:04.585] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-09T19:07:04.586] [INFO] monitorLogs - 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 +} +[2025-10-09T19:07:04.589] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T19:07:04.590] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-10-10T11:00:00.589Z +[2025-10-09T19:07:04.591] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-09T19:07:04.593] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-10-09T19:07:04.593] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-09T19:07:04.594] [INFO] monitorLogs - 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 +} +[2025-10-09T19:07:04.595] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T19:07:04.596] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-10-10T11:00:00.596Z +[2025-10-09T19:07:04.597] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-09T19:07:04.598] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-10-09T19:07:04.599] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-09T19:07:04.599] [INFO] monitorLogs - 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 +} +[2025-10-09T19:07:04.601] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T19:07:04.601] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-10-10T11:00:00.601Z +[2025-10-09T19:07:04.602] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-09T19:07:04.603] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-10-09T19:07:04.626] [INFO] monitorLogs - tasks created: 921 +[2025-10-09T19:07:04.629] [INFO] monitorLogs - -->FLOW bol spustený JX1ObgmqGZ54DMyYL7aDRmkEVdve38WKRzwjNrQ9 2025-08-08 +[2025-10-09T19:07:09.636] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-10T03:07:06.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-10 03:07:06 +[2025-10-11T03:07:07.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-11 03:07:07 +[2025-10-12T03:07:08.013] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-12 03:07:08 +[2025-10-13T03:07:09.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-13 03:07:09 +[2025-10-14T03:07:10.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-14 03:07:10 +[2025-10-15T03:07:11.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-15 03:07:11 +[2025-10-15T15:27:28.165] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-15T15:27:33.534] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-15T15:27:33.539] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-15T15:27:33.540] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-15T15:27:33.541] [INFO] monitorLogs - 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 +} +[2025-10-15T15:27:33.543] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-15T15:27:33.545] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-10-16T11:00:00.544Z +[2025-10-15T15:27:33.547] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-15T15:27:33.548] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-10-15T15:27:33.549] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-15T15:27:33.549] [INFO] monitorLogs - 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 +} +[2025-10-15T15:27:33.551] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-15T15:27:33.551] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-10-16T11:00:00.551Z +[2025-10-15T15:27:33.552] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-15T15:27:33.553] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-10-15T15:27:33.554] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-15T15:27:33.554] [INFO] monitorLogs - 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 +} +[2025-10-15T15:27:33.556] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-15T15:27:33.556] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-10-16T11:00:00.556Z +[2025-10-15T15:27:33.557] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-15T15:27:33.558] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-10-15T15:27:33.580] [INFO] monitorLogs - tasks created: 921 +[2025-10-15T15:27:33.582] [INFO] monitorLogs - -->FLOW bol spustený JX1ObgmqGZ54DMyYL7aDRmkEVdve38WKRzwjNrQ9 2025-10-08 +[2025-10-15T15:27:38.590] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu diff --git a/RVO20/package-lock.json b/RVO20/package-lock.json new file mode 100755 index 0000000..3c5c1ba --- /dev/null +++ b/RVO20/package-lock.json @@ -0,0 +1,2139 @@ +{ + "name": "emptyproject", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "emptyproject", + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "bitwise": "^2.1.0", + "easy-crc": "0.0.2", + "jsmodbus": "^4.0.6", + "log4js": "^6.3.0", + "moment": "^2.30.1", + "mqtt": "^4.2.6", + "nodemailer": "^6.9.7", + "serialport": "^9.2.8", + "total.js": "^3.4.13" + } + }, + "node_modules/@serialport/binding-abstract": { + "version": "9.2.3", + "resolved": "https://registry.npmjs.org/@serialport/binding-abstract/-/binding-abstract-9.2.3.tgz", + "integrity": "sha512-cQs9tbIlG3P0IrOWyVirqlhWuJ7Ms2Zh9m2108z6Y5UW/iVj6wEOiW8EmK9QX9jmJXYllE7wgGgvVozP5oCj3w==", + "dependencies": { + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/binding-mock": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/binding-mock/-/binding-mock-9.2.4.tgz", + "integrity": "sha512-dpEhACCs44oQhh6ajJfJdvQdK38Vq0N4W6iD/gdplglDCK7qXRQCMUjJIeKdS/HSEiWkC3bwumUhUufdsOyT4g==", + "dependencies": { + "@serialport/binding-abstract": "9.2.3", + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/bindings": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/@serialport/bindings/-/bindings-9.2.8.tgz", + "integrity": "sha512-hSLxTe0tADZ3LMMGwvEJWOC/TaFQTyPeFalUCsJ1lSQ0k6bPF04JwrtB/C81GetmDBTNRY0GlD0SNtKCc7Dr5g==", + "hasInstallScript": true, + "dependencies": { + "@serialport/binding-abstract": "9.2.3", + "@serialport/parser-readline": "9.2.4", + "bindings": "^1.5.0", + "debug": "^4.3.2", + "nan": "^2.15.0", + "prebuild-install": "^7.0.0" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-byte-length": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-byte-length/-/parser-byte-length-9.2.4.tgz", + "integrity": "sha512-sQD/iw4ZMU3xW9PLi0/GlvU6Y623jGeWecbMkO7izUo/6P7gtfv1c9ikd5h0kwL8AoAOpQA1lxdHIKox+umBUg==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-cctalk": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-cctalk/-/parser-cctalk-9.2.4.tgz", + "integrity": "sha512-T4TU5vQMwmo9AB3gQLFDWbfJXlW5jd9guEsB/nqKjFHTv0FXPdZ7DQ2TpSp8RnHWxU3GX6kYTaDO20BKzc8GPQ==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-delimiter": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-delimiter/-/parser-delimiter-9.2.4.tgz", + "integrity": "sha512-4nvTAoYAgkxFiXrkI+3CA49Yd43CODjeszh89EK+I9c8wOZ+etZduRCzINYPiy26g7zO+GRAb9FoPCsY+sYcbQ==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-inter-byte-timeout": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-inter-byte-timeout/-/parser-inter-byte-timeout-9.2.4.tgz", + "integrity": "sha512-SOAdvr0oBQIOCXX198hiTlxs4JTKg9j5piapw5tNq52fwDOWdbYrFneT/wN04UTMKaDrJuEvXq6T4rv4j7nJ5A==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-readline": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-readline/-/parser-readline-9.2.4.tgz", + "integrity": "sha512-Z1/qrZTQUVhNSJP1hd9YfDvq0o7d87rNwAjjRKbVpa7Qi51tG5BnKt43IV3NFMyBlVcRe0rnIb3tJu57E0SOwg==", + "dependencies": { + "@serialport/parser-delimiter": "9.2.4" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-ready": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-ready/-/parser-ready-9.2.4.tgz", + "integrity": "sha512-Pyi94Itjl6qAURwIZr/gmZpMAyTmKXThm6vL5DoAWGQjcRHWB0gwv2TY2v7N+mQLJYUKU3cMnvnATXxHm7xjxw==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-regex": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-regex/-/parser-regex-9.2.4.tgz", + "integrity": "sha512-sI/cVvPOYz+Dbv4ZdnW16qAwvXiFf/1pGASQdbveRTlgJDdz7sRNlCBifzfTN2xljwvCTZYqiudKvDdC1TepRQ==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/stream": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/stream/-/stream-9.2.4.tgz", + "integrity": "sha512-bLye8Ub4vUFQGmkh8qEqehr7SE7EJs2yDs0h9jzuL5oKi+F34CFmWkEErO8GAOQ8YNn7p6b3GxUgs+0BrHHDZQ==", + "dependencies": { + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "node_modules/are-we-there-yet": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", + "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/base64-js": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", + "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==" + }, + "node_modules/bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "dependencies": { + "file-uri-to-path": "1.0.0" + } + }, + "node_modules/bitwise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/bitwise/-/bitwise-2.1.0.tgz", + "integrity": "sha512-XKgAhMXCh4H/3oNwAHAsAO0iC89s9cOiumgYwSHjSobGWxYjv62YhkL9QEdvGP151xypCtMlAfKK79GEcd2eRQ==" + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/bl/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/buffer": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz", + "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==", + "dependencies": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + }, + "node_modules/buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" + }, + "node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, + "node_modules/code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/commist": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/commist/-/commist-1.1.0.tgz", + "integrity": "sha512-rraC8NXWOEjhADbZe9QBNzLAN5Q3fsTPQtBV+fEVj6xKIgDgNiEVE6ZNfHpZOqfQ21YUzfVNUXLOEZquYvQPPg==", + "dependencies": { + "leven": "^2.1.0", + "minimist": "^1.1.0" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "node_modules/concat-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", + "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", + "engines": [ + "node >= 6.0" + ], + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.0.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/concat-stream/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" + }, + "node_modules/core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "node_modules/crc": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/crc/-/crc-3.4.0.tgz", + "integrity": "sha512-ycVC2+4/DLgXXq7QweYi2znhqDuZz6P5TQXnkQo8v15XY/5p/IWeZwsSE31Ifo8w15b8TWLsqhXOjXyilHuQxw==" + }, + "node_modules/date-format": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.11.tgz", + "integrity": "sha512-VS20KRyorrbMCQmpdl2hg5KaOUsda1RbnsJg461FfrcyCUg+pkd0b40BSW4niQyTheww4DBXQnS7HwSrKkipLw==", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" + }, + "node_modules/detect-libc": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz", + "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==", + "engines": { + "node": ">=8" + } + }, + "node_modules/duplexify": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.2.tgz", + "integrity": "sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw==", + "dependencies": { + "end-of-stream": "^1.4.1", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1", + "stream-shift": "^1.0.0" + } + }, + "node_modules/duplexify/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/easy-crc": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/easy-crc/-/easy-crc-0.0.2.tgz", + "integrity": "sha512-h6eqIdhJRe0p271/xZJbM/0klCi13mW5IB7ZEzEGH11yV4QXWAkD4yPErz0fXdhFrd6sZ4Q1k5Iky2kMsMNePw==" + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" + }, + "node_modules/flatted": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", + "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==" + }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, + "node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "node_modules/gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha512-14x4kjc6lkD3ltw589k0NrPD6cCNTD6CWoVUNpB85+DrtONoZn+Rug6xZU5RvSC4+TZPxA5AnBibQYAvZn41Hg==", + "dependencies": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "node_modules/github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==" + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" + }, + "node_modules/has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" + }, + "node_modules/help-me": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/help-me/-/help-me-3.0.0.tgz", + "integrity": "sha512-hx73jClhyk910sidBB7ERlnhMlFsJJIBqSVMFDwPN8o2v9nmp5KgLq1Xz1Bf1fCMMZ6mPrX159iG0VLy/fPMtQ==", + "dependencies": { + "glob": "^7.1.6", + "readable-stream": "^3.6.0" + } + }, + "node_modules/help-me/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, + "node_modules/is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==", + "dependencies": { + "number-is-nan": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "node_modules/js-sdsl": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz", + "integrity": "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/js-sdsl" + } + }, + "node_modules/jsmodbus": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/jsmodbus/-/jsmodbus-4.0.6.tgz", + "integrity": "sha512-gCmjoaERErK5Rn9Lu/BN07fY13MoWV7JKgGzrnkPlQPdPxYcwDhLtYcmpFFpZ4J9NPZZBSezi1UkLZO/DnNppA==", + "dependencies": { + "crc": "3.4.0", + "debug": "^3.1.0" + }, + "bin": { + "jsmodbus": "bin/jsmodbus.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/jsmodbus/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/leven": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", + "integrity": "sha1-wuep93IJTe6dNCAq6KzORoeHVYA=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/log4js": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.5.2.tgz", + "integrity": "sha512-DXtpNtt+KDOMT7RHUDIur/WsSA3rntlUh9Zg4XCdV42wUuMmbFkl38+LZ92Z5QvQA7mD5kAVkLiBSEH/tvUB8A==", + "dependencies": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "flatted": "^3.2.5", + "rfdc": "^1.3.0", + "streamroller": "^3.1.1" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" + }, + "node_modules/moment": { + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", + "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==", + "engines": { + "node": "*" + } + }, + "node_modules/mqtt": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/mqtt/-/mqtt-4.3.7.tgz", + "integrity": "sha512-ew3qwG/TJRorTz47eW46vZ5oBw5MEYbQZVaEji44j5lAUSQSqIEoul7Kua/BatBW0H0kKQcC9kwUHa1qzaWHSw==", + "dependencies": { + "commist": "^1.0.0", + "concat-stream": "^2.0.0", + "debug": "^4.1.1", + "duplexify": "^4.1.1", + "help-me": "^3.0.0", + "inherits": "^2.0.3", + "lru-cache": "^6.0.0", + "minimist": "^1.2.5", + "mqtt-packet": "^6.8.0", + "number-allocator": "^1.0.9", + "pump": "^3.0.0", + "readable-stream": "^3.6.0", + "reinterval": "^1.1.0", + "rfdc": "^1.3.0", + "split2": "^3.1.0", + "ws": "^7.5.5", + "xtend": "^4.0.2" + }, + "bin": { + "mqtt": "bin/mqtt.js", + "mqtt_pub": "bin/pub.js", + "mqtt_sub": "bin/sub.js" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/mqtt-packet": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/mqtt-packet/-/mqtt-packet-6.10.0.tgz", + "integrity": "sha512-ja8+mFKIHdB1Tpl6vac+sktqy3gA8t9Mduom1BA75cI+R9AHnZOiaBQwpGiWnaVJLDGRdNhQmFaAqd7tkKSMGA==", + "dependencies": { + "bl": "^4.0.2", + "debug": "^4.1.1", + "process-nextick-args": "^2.0.1" + } + }, + "node_modules/mqtt/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/nan": { + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.16.0.tgz", + "integrity": "sha512-UdAqHyFngu7TfQKsCBgAA6pWDkT8MAO7d0jyOecVhN5354xbLqdn8mV9Tat9gepAupm0bt2DbeaSC8vS52MuFA==" + }, + "node_modules/napi-build-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", + "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==" + }, + "node_modules/node-abi": { + "version": "3.22.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.22.0.tgz", + "integrity": "sha512-u4uAs/4Zzmp/jjsD9cyFYDXeISfUWaAVWshPmDZOFOv4Xl4SbzTXm53I04C2uRueYJ+0t5PEtLH/owbn2Npf/w==", + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/nodemailer": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.7.tgz", + "integrity": "sha512-rUtR77ksqex/eZRLmQ21LKVH5nAAsVicAtAYudK7JgwenEDZ0UIQ1adUGqErz7sMkWYxWTTU1aeP2Jga6WQyJw==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "dependencies": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "node_modules/number-allocator": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/number-allocator/-/number-allocator-1.0.14.tgz", + "integrity": "sha512-OrL44UTVAvkKdOdRQZIJpLkAdjXGTRda052sN4sO77bKEzYYqWKMBjQvrJFzqygI99gL6Z4u2xctPW1tB8ErvA==", + "dependencies": { + "debug": "^4.3.1", + "js-sdsl": "4.3.0" + } + }, + "node_modules/number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/prebuild-install": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.0.tgz", + "integrity": "sha512-CNcMgI1xBypOyGqjp3wOc8AAo1nMhZS3Cwd3iHIxOdAUbb+YxdNuM4Z5iIrZ8RLvOsf3F3bl7b7xGq6DjQoNYA==", + "dependencies": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^1.0.1", + "node-abi": "^3.3.0", + "npmlog": "^4.0.1", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + }, + "bin": { + "prebuild-install": "bin.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/reinterval": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reinterval/-/reinterval-1.1.0.tgz", + "integrity": "sha1-M2Hs+jymwYKDOA3Qu5VG85D17Oc=" + }, + "node_modules/rfdc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==" + }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/serialport": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/serialport/-/serialport-9.2.8.tgz", + "integrity": "sha512-FsWpMQgSJxi93JgWl5xM1f9/Z8IjRJuaUEoHqLf8FPBLw7gMhInuHOBhI2onQufWIYPGTz3H3oGcu1nCaK1EfA==", + "dependencies": { + "@serialport/binding-mock": "9.2.4", + "@serialport/bindings": "9.2.8", + "@serialport/parser-byte-length": "9.2.4", + "@serialport/parser-cctalk": "9.2.4", + "@serialport/parser-delimiter": "9.2.4", + "@serialport/parser-inter-byte-timeout": "9.2.4", + "@serialport/parser-readline": "9.2.4", + "@serialport/parser-ready": "9.2.4", + "@serialport/parser-regex": "9.2.4", + "@serialport/stream": "9.2.4", + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "node_modules/split2": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", + "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", + "dependencies": { + "readable-stream": "^3.0.0" + } + }, + "node_modules/split2/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==" + }, + "node_modules/streamroller": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.1.1.tgz", + "integrity": "sha512-iPhtd9unZ6zKdWgMeYGfSBuqCngyJy1B/GPi/lTpwGpa3bajuX30GjUVd0/Tn/Xhg0mr4DOSENozz9Y06qyonQ==", + "dependencies": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "fs-extra": "^10.1.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dependencies": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/tar-fs": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "dependencies": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tar-stream/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/total.js": { + "version": "3.4.13", + "resolved": "https://registry.npmjs.org/total.js/-/total.js-3.4.13.tgz", + "integrity": "sha512-lAH4gEixlPFbrE3xfKADAcHfO79IFq2wKa9GTsrgRzIR5MTg3mNH7+4IxvX1pK8faoYb/0oYSJ1YTsAa5hIFFQ==", + "bin": { + "total": "bin/totaljs", + "total.js": "bin/totaljs", + "totaljs": "bin/totaljs", + "totalpackage": "bin/tpm", + "tpm": "bin/tpm" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, + "node_modules/universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "node_modules/wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "node_modules/ws": { + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } + }, + "dependencies": { + "@serialport/binding-abstract": { + "version": "9.2.3", + "resolved": "https://registry.npmjs.org/@serialport/binding-abstract/-/binding-abstract-9.2.3.tgz", + "integrity": "sha512-cQs9tbIlG3P0IrOWyVirqlhWuJ7Ms2Zh9m2108z6Y5UW/iVj6wEOiW8EmK9QX9jmJXYllE7wgGgvVozP5oCj3w==", + "requires": { + "debug": "^4.3.2" + } + }, + "@serialport/binding-mock": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/binding-mock/-/binding-mock-9.2.4.tgz", + "integrity": "sha512-dpEhACCs44oQhh6ajJfJdvQdK38Vq0N4W6iD/gdplglDCK7qXRQCMUjJIeKdS/HSEiWkC3bwumUhUufdsOyT4g==", + "requires": { + "@serialport/binding-abstract": "9.2.3", + "debug": "^4.3.2" + } + }, + "@serialport/bindings": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/@serialport/bindings/-/bindings-9.2.8.tgz", + "integrity": "sha512-hSLxTe0tADZ3LMMGwvEJWOC/TaFQTyPeFalUCsJ1lSQ0k6bPF04JwrtB/C81GetmDBTNRY0GlD0SNtKCc7Dr5g==", + "requires": { + "@serialport/binding-abstract": "9.2.3", + "@serialport/parser-readline": "9.2.4", + "bindings": "^1.5.0", + "debug": "^4.3.2", + "nan": "^2.15.0", + "prebuild-install": "^7.0.0" + } + }, + "@serialport/parser-byte-length": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-byte-length/-/parser-byte-length-9.2.4.tgz", + "integrity": "sha512-sQD/iw4ZMU3xW9PLi0/GlvU6Y623jGeWecbMkO7izUo/6P7gtfv1c9ikd5h0kwL8AoAOpQA1lxdHIKox+umBUg==" + }, + "@serialport/parser-cctalk": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-cctalk/-/parser-cctalk-9.2.4.tgz", + "integrity": "sha512-T4TU5vQMwmo9AB3gQLFDWbfJXlW5jd9guEsB/nqKjFHTv0FXPdZ7DQ2TpSp8RnHWxU3GX6kYTaDO20BKzc8GPQ==" + }, + "@serialport/parser-delimiter": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-delimiter/-/parser-delimiter-9.2.4.tgz", + "integrity": "sha512-4nvTAoYAgkxFiXrkI+3CA49Yd43CODjeszh89EK+I9c8wOZ+etZduRCzINYPiy26g7zO+GRAb9FoPCsY+sYcbQ==" + }, + "@serialport/parser-inter-byte-timeout": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-inter-byte-timeout/-/parser-inter-byte-timeout-9.2.4.tgz", + "integrity": "sha512-SOAdvr0oBQIOCXX198hiTlxs4JTKg9j5piapw5tNq52fwDOWdbYrFneT/wN04UTMKaDrJuEvXq6T4rv4j7nJ5A==" + }, + "@serialport/parser-readline": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-readline/-/parser-readline-9.2.4.tgz", + "integrity": "sha512-Z1/qrZTQUVhNSJP1hd9YfDvq0o7d87rNwAjjRKbVpa7Qi51tG5BnKt43IV3NFMyBlVcRe0rnIb3tJu57E0SOwg==", + "requires": { + "@serialport/parser-delimiter": "9.2.4" + } + }, + "@serialport/parser-ready": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-ready/-/parser-ready-9.2.4.tgz", + "integrity": "sha512-Pyi94Itjl6qAURwIZr/gmZpMAyTmKXThm6vL5DoAWGQjcRHWB0gwv2TY2v7N+mQLJYUKU3cMnvnATXxHm7xjxw==" + }, + "@serialport/parser-regex": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-regex/-/parser-regex-9.2.4.tgz", + "integrity": "sha512-sI/cVvPOYz+Dbv4ZdnW16qAwvXiFf/1pGASQdbveRTlgJDdz7sRNlCBifzfTN2xljwvCTZYqiudKvDdC1TepRQ==" + }, + "@serialport/stream": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/stream/-/stream-9.2.4.tgz", + "integrity": "sha512-bLye8Ub4vUFQGmkh8qEqehr7SE7EJs2yDs0h9jzuL5oKi+F34CFmWkEErO8GAOQ8YNn7p6b3GxUgs+0BrHHDZQ==", + "requires": { + "debug": "^4.3.2" + } + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==" + }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "are-we-there-yet": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", + "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "base64-js": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", + "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==" + }, + "bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "requires": { + "file-uri-to-path": "1.0.0" + } + }, + "bitwise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/bitwise/-/bitwise-2.1.0.tgz", + "integrity": "sha512-XKgAhMXCh4H/3oNwAHAsAO0iC89s9cOiumgYwSHjSobGWxYjv62YhkL9QEdvGP151xypCtMlAfKK79GEcd2eRQ==" + }, + "bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "requires": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "buffer": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz", + "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==", + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" + }, + "chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==" + }, + "commist": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/commist/-/commist-1.1.0.tgz", + "integrity": "sha512-rraC8NXWOEjhADbZe9QBNzLAN5Q3fsTPQtBV+fEVj6xKIgDgNiEVE6ZNfHpZOqfQ21YUzfVNUXLOEZquYvQPPg==", + "requires": { + "leven": "^2.1.0", + "minimist": "^1.1.0" + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "concat-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", + "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.0.2", + "typedarray": "^0.0.6" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "crc": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/crc/-/crc-3.4.0.tgz", + "integrity": "sha512-ycVC2+4/DLgXXq7QweYi2znhqDuZz6P5TQXnkQo8v15XY/5p/IWeZwsSE31Ifo8w15b8TWLsqhXOjXyilHuQxw==" + }, + "date-format": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.11.tgz", + "integrity": "sha512-VS20KRyorrbMCQmpdl2hg5KaOUsda1RbnsJg461FfrcyCUg+pkd0b40BSW4niQyTheww4DBXQnS7HwSrKkipLw==" + }, + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "requires": { + "ms": "2.1.2" + } + }, + "decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "requires": { + "mimic-response": "^3.1.0" + } + }, + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==" + }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" + }, + "detect-libc": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz", + "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==" + }, + "duplexify": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.2.tgz", + "integrity": "sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw==", + "requires": { + "end-of-stream": "^1.4.1", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1", + "stream-shift": "^1.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "easy-crc": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/easy-crc/-/easy-crc-0.0.2.tgz", + "integrity": "sha512-h6eqIdhJRe0p271/xZJbM/0klCi13mW5IB7ZEzEGH11yV4QXWAkD4yPErz0fXdhFrd6sZ4Q1k5Iky2kMsMNePw==" + }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "requires": { + "once": "^1.4.0" + } + }, + "expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==" + }, + "file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" + }, + "flatted": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", + "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==" + }, + "fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, + "fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha512-14x4kjc6lkD3ltw589k0NrPD6cCNTD6CWoVUNpB85+DrtONoZn+Rug6xZU5RvSC4+TZPxA5AnBibQYAvZn41Hg==", + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==" + }, + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" + }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" + }, + "help-me": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/help-me/-/help-me-3.0.0.tgz", + "integrity": "sha512-hx73jClhyk910sidBB7ERlnhMlFsJJIBqSVMFDwPN8o2v9nmp5KgLq1Xz1Bf1fCMMZ6mPrX159iG0VLy/fPMtQ==", + "requires": { + "glob": "^7.1.6", + "readable-stream": "^3.6.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==", + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "js-sdsl": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz", + "integrity": "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==" + }, + "jsmodbus": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/jsmodbus/-/jsmodbus-4.0.6.tgz", + "integrity": "sha512-gCmjoaERErK5Rn9Lu/BN07fY13MoWV7JKgGzrnkPlQPdPxYcwDhLtYcmpFFpZ4J9NPZZBSezi1UkLZO/DnNppA==", + "requires": { + "crc": "3.4.0", + "debug": "^3.1.0" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "requires": { + "ms": "^2.1.1" + } + } + } + }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, + "leven": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", + "integrity": "sha1-wuep93IJTe6dNCAq6KzORoeHVYA=" + }, + "log4js": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.5.2.tgz", + "integrity": "sha512-DXtpNtt+KDOMT7RHUDIur/WsSA3rntlUh9Zg4XCdV42wUuMmbFkl38+LZ92Z5QvQA7mD5kAVkLiBSEH/tvUB8A==", + "requires": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "flatted": "^3.2.5", + "rfdc": "^1.3.0", + "streamroller": "^3.1.1" + } + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "requires": { + "yallist": "^4.0.0" + } + }, + "mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==" + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==" + }, + "mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" + }, + "moment": { + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", + "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==" + }, + "mqtt": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/mqtt/-/mqtt-4.3.7.tgz", + "integrity": "sha512-ew3qwG/TJRorTz47eW46vZ5oBw5MEYbQZVaEji44j5lAUSQSqIEoul7Kua/BatBW0H0kKQcC9kwUHa1qzaWHSw==", + "requires": { + "commist": "^1.0.0", + "concat-stream": "^2.0.0", + "debug": "^4.1.1", + "duplexify": "^4.1.1", + "help-me": "^3.0.0", + "inherits": "^2.0.3", + "lru-cache": "^6.0.0", + "minimist": "^1.2.5", + "mqtt-packet": "^6.8.0", + "number-allocator": "^1.0.9", + "pump": "^3.0.0", + "readable-stream": "^3.6.0", + "reinterval": "^1.1.0", + "rfdc": "^1.3.0", + "split2": "^3.1.0", + "ws": "^7.5.5", + "xtend": "^4.0.2" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "mqtt-packet": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/mqtt-packet/-/mqtt-packet-6.10.0.tgz", + "integrity": "sha512-ja8+mFKIHdB1Tpl6vac+sktqy3gA8t9Mduom1BA75cI+R9AHnZOiaBQwpGiWnaVJLDGRdNhQmFaAqd7tkKSMGA==", + "requires": { + "bl": "^4.0.2", + "debug": "^4.1.1", + "process-nextick-args": "^2.0.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "nan": { + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.16.0.tgz", + "integrity": "sha512-UdAqHyFngu7TfQKsCBgAA6pWDkT8MAO7d0jyOecVhN5354xbLqdn8mV9Tat9gepAupm0bt2DbeaSC8vS52MuFA==" + }, + "napi-build-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", + "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==" + }, + "node-abi": { + "version": "3.22.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.22.0.tgz", + "integrity": "sha512-u4uAs/4Zzmp/jjsD9cyFYDXeISfUWaAVWshPmDZOFOv4Xl4SbzTXm53I04C2uRueYJ+0t5PEtLH/owbn2Npf/w==", + "requires": { + "semver": "^7.3.5" + } + }, + "nodemailer": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.7.tgz", + "integrity": "sha512-rUtR77ksqex/eZRLmQ21LKVH5nAAsVicAtAYudK7JgwenEDZ0UIQ1adUGqErz7sMkWYxWTTU1aeP2Jga6WQyJw==" + }, + "npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "number-allocator": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/number-allocator/-/number-allocator-1.0.14.tgz", + "integrity": "sha512-OrL44UTVAvkKdOdRQZIJpLkAdjXGTRda052sN4sO77bKEzYYqWKMBjQvrJFzqygI99gL6Z4u2xctPW1tB8ErvA==", + "requires": { + "debug": "^4.3.1", + "js-sdsl": "4.3.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==" + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==" + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==" + }, + "prebuild-install": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.0.tgz", + "integrity": "sha512-CNcMgI1xBypOyGqjp3wOc8AAo1nMhZS3Cwd3iHIxOdAUbb+YxdNuM4Z5iIrZ8RLvOsf3F3bl7b7xGq6DjQoNYA==", + "requires": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^1.0.1", + "node-abi": "^3.3.0", + "npmlog": "^4.0.1", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + } + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + } + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "reinterval": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reinterval/-/reinterval-1.1.0.tgz", + "integrity": "sha1-M2Hs+jymwYKDOA3Qu5VG85D17Oc=" + }, + "rfdc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==" + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "requires": { + "lru-cache": "^6.0.0" + } + }, + "serialport": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/serialport/-/serialport-9.2.8.tgz", + "integrity": "sha512-FsWpMQgSJxi93JgWl5xM1f9/Z8IjRJuaUEoHqLf8FPBLw7gMhInuHOBhI2onQufWIYPGTz3H3oGcu1nCaK1EfA==", + "requires": { + "@serialport/binding-mock": "9.2.4", + "@serialport/bindings": "9.2.8", + "@serialport/parser-byte-length": "9.2.4", + "@serialport/parser-cctalk": "9.2.4", + "@serialport/parser-delimiter": "9.2.4", + "@serialport/parser-inter-byte-timeout": "9.2.4", + "@serialport/parser-readline": "9.2.4", + "@serialport/parser-ready": "9.2.4", + "@serialport/parser-regex": "9.2.4", + "@serialport/stream": "9.2.4", + "debug": "^4.3.2" + } + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==" + }, + "simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "requires": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "split2": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", + "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", + "requires": { + "readable-stream": "^3.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==" + }, + "streamroller": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.1.1.tgz", + "integrity": "sha512-iPhtd9unZ6zKdWgMeYGfSBuqCngyJy1B/GPi/lTpwGpa3bajuX30GjUVd0/Tn/Xhg0mr4DOSENozz9Y06qyonQ==", + "requires": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "fs-extra": "^10.1.0" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" + }, + "tar-fs": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "requires": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "requires": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "total.js": { + "version": "3.4.13", + "resolved": "https://registry.npmjs.org/total.js/-/total.js-3.4.13.tgz", + "integrity": "sha512-lAH4gEixlPFbrE3xfKADAcHfO79IFq2wKa9GTsrgRzIR5MTg3mNH7+4IxvX1pK8faoYb/0oYSJ1YTsAa5hIFFQ==" + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, + "universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==" + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "requires": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "ws": { + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "requires": {} + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } + } +} diff --git a/RVO20/package.json b/RVO20/package.json new file mode 100755 index 0000000..7f7c795 --- /dev/null +++ b/RVO20/package.json @@ -0,0 +1,30 @@ +{ + "name": "emptyproject", + "description": "Total.js empty project.", + "version": "1.0.0", + "main": "debug.js", + "dependencies": { + "bitwise": "^2.1.0", + "easy-crc": "0.0.2", + "jsmodbus": "^4.0.6", + "log4js": "^6.3.0", + "moment": "^2.30.1", + "mqtt": "^4.2.6", + "nodemailer": "^6.9.7", + "serialport": "^9.2.8", + "total.js": "^3.4.13" + }, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "https://github.com/totaljs/emptyproject-flow" + }, + "keywords": [ + "empty", + "project" + ], + "author": "Peter Širka", + "license": "MIT" +} diff --git a/RVO20/release.js b/RVO20/release.js new file mode 100755 index 0000000..02d52ff --- /dev/null +++ b/RVO20/release.js @@ -0,0 +1,15 @@ +// =================================================== +// FOR PRODUCTION +// Total.js - framework for Node.js platform +// https://www.totaljs.com +// =================================================== + +const options = {'ip':'0.0.0.0', 'port':12345}; + +// options.ip = '127.0.0.1'; +// options.port = parseInt(process.argv[2]); +// options.config = { name: 'Total.js' }; +// options.sleep = 3000; + +require('total.js').http('release', options); +// require('total.js').cluster.http(5, 'release', options); diff --git a/RVO20/release.js.json b/RVO20/release.js.json new file mode 100755 index 0000000..e15b421 --- /dev/null +++ b/RVO20/release.js.json @@ -0,0 +1,34 @@ +{ + "pid": 416, + "stats": [ + { + "id": null, + "version": { + "node": "v14.18.1", + "total": "3.4.13", + "app": "1.0.0" + }, + "pid": 416, + "thread": "", + "mode": "release", + "overload": 0, + "date": "2025-10-16T00:23:24.253Z", + "memory": 21.64, + "rm": 0, + "fm": 0, + "wm": 0, + "mm": 0, + "om": 2, + "em": 0, + "dbrm": 0, + "dbwm": 0, + "usage": 0, + "requests": 0, + "pending": 0, + "errors": 0, + "timeouts": 0, + "uptime": 657, + "online": 0 + } + ] +} \ No newline at end of file diff --git a/RVO20/report_data.log b/RVO20/report_data.log new file mode 100755 index 0000000..14fdbbd --- /dev/null +++ b/RVO20/report_data.log @@ -0,0 +1,151 @@ +{ + "name": "rvo_senica_20_ip113", + "time": "2025-10-15T14:27:39.204Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_20_ip113", + "time": "2025-10-15T15:27:39.199Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_20_ip113", + "time": "2025-10-15T16:27:39.200Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_20_ip113", + "time": "2025-10-15T17:27:39.200Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_20_ip113", + "time": "2025-10-15T18:27:39.204Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_20_ip113", + "time": "2025-10-15T19:27:39.201Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_20_ip113", + "time": "2025-10-15T20:27:39.200Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_20_ip113", + "time": "2025-10-15T21:27:39.201Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_20_ip113", + "time": "2025-10-15T22:27:39.200Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_20_ip113", + "time": "2025-10-15T23:27:39.201Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +} \ No newline at end of file From 5582b767d75080a27c1923b0add408479c6a4514 Mon Sep 17 00:00:00 2001 From: Jakub Klena Date: Thu, 16 Oct 2025 02:24:42 +0200 Subject: [PATCH 11/30] Backup senica-RVO21 on 16.10.2025 --- RVO21/addSwitch.py | 36 + RVO21/cloud_topic.py | 76 + RVO21/config | 12 + RVO21/createNode.py | 43 + RVO21/databases/accelerometer_db.js | 3055 ++++++++++++ RVO21/databases/modbus_config.js | 114 + RVO21/databases/nodes.table | 55 + .../nodes_original/nodes_original.table | 1 + RVO21/databases/notifications.table | 41 + RVO21/databases/pins.table | 14 + RVO21/databases/relays.table | 5 + RVO21/databases/settings.table | 2 + RVO21/databases/tbdata.nosql | 4 + RVO21/databases/tbdatacloud.nosql | 3 + RVO21/databases/total_energy.js | 38 + RVO21/debug.js | 16 + RVO21/err.txt | 33 + RVO21/flow/cloudmqttconnect.js | 357 ++ RVO21/flow/cmd_manager.js | 3071 ++++++++++++ RVO21/flow/code.js | 90 + RVO21/flow/comment.js | 11 + RVO21/flow/count.js | 60 + RVO21/flow/db_connector.js | 286 ++ RVO21/flow/db_init.js | 113 + RVO21/flow/debug.js | 100 + RVO21/flow/designer.json | 3102 ++++++++++++ RVO21/flow/dido_controller.js | 1486 ++++++ RVO21/flow/helper/DataToTbHandler.js | 187 + RVO21/flow/helper/ErrorToServiceHandler.js | 91 + RVO21/flow/helper/db_helper.js | 44 + RVO21/flow/helper/logger.js | 30 + RVO21/flow/helper/md5.js | 5 + RVO21/flow/helper/notification_reporter.js | 121 + RVO21/flow/helper/register.js | 144 + RVO21/flow/helper/serialport_helper.js | 99 + RVO21/flow/helper/suncalc.js | 317 ++ RVO21/flow/helper/utils.js | 161 + RVO21/flow/httprequest.js | 137 + RVO21/flow/httpresponse.js | 76 + RVO21/flow/httproute.js | 326 ++ RVO21/flow/infosender.js | 81 + RVO21/flow/modbus_reader.js | 346 ++ RVO21/flow/monitorconsumption.js | 156 + RVO21/flow/monitordisk.js | 96 + RVO21/flow/monitormemory.js | 87 + RVO21/flow/nodesdb_changecheck.js | 77 + RVO21/flow/show_dbdata.js | 243 + RVO21/flow/slack_filter.js | 188 + RVO21/flow/thermometer.js | 99 + RVO21/flow/trigger.js | 79 + RVO21/flow/variables.txt | 0 RVO21/flow/virtualwirein.js | 43 + RVO21/flow/virtualwireout.js | 41 + RVO21/flow/wsmqttpublish.js | 448 ++ RVO21/monitor.txt | 4218 +++++++++++++++++ RVO21/package-lock.json | 2139 +++++++++ RVO21/package.json | 30 + RVO21/release.js | 15 + RVO21/release.js.json | 34 + RVO21/report_data.log | 151 + 60 files changed, 22533 insertions(+) create mode 100755 RVO21/addSwitch.py create mode 100755 RVO21/cloud_topic.py create mode 100755 RVO21/config create mode 100755 RVO21/createNode.py create mode 100755 RVO21/databases/accelerometer_db.js create mode 100755 RVO21/databases/modbus_config.js create mode 100755 RVO21/databases/nodes.table create mode 100755 RVO21/databases/nodes_original/nodes_original.table create mode 100755 RVO21/databases/notifications.table create mode 100755 RVO21/databases/pins.table create mode 100755 RVO21/databases/relays.table create mode 100755 RVO21/databases/settings.table create mode 100755 RVO21/databases/tbdata.nosql create mode 100755 RVO21/databases/tbdatacloud.nosql create mode 100755 RVO21/databases/total_energy.js create mode 100755 RVO21/debug.js create mode 100755 RVO21/err.txt create mode 100755 RVO21/flow/cloudmqttconnect.js create mode 100755 RVO21/flow/cmd_manager.js create mode 100755 RVO21/flow/code.js create mode 100755 RVO21/flow/comment.js create mode 100755 RVO21/flow/count.js create mode 100755 RVO21/flow/db_connector.js create mode 100755 RVO21/flow/db_init.js create mode 100755 RVO21/flow/debug.js create mode 100755 RVO21/flow/designer.json create mode 100755 RVO21/flow/dido_controller.js create mode 100755 RVO21/flow/helper/DataToTbHandler.js create mode 100755 RVO21/flow/helper/ErrorToServiceHandler.js create mode 100755 RVO21/flow/helper/db_helper.js create mode 100755 RVO21/flow/helper/logger.js create mode 100755 RVO21/flow/helper/md5.js create mode 100755 RVO21/flow/helper/notification_reporter.js create mode 100755 RVO21/flow/helper/register.js create mode 100755 RVO21/flow/helper/serialport_helper.js create mode 100755 RVO21/flow/helper/suncalc.js create mode 100755 RVO21/flow/helper/utils.js create mode 100755 RVO21/flow/httprequest.js create mode 100755 RVO21/flow/httpresponse.js create mode 100755 RVO21/flow/httproute.js create mode 100755 RVO21/flow/infosender.js create mode 100755 RVO21/flow/modbus_reader.js create mode 100755 RVO21/flow/monitorconsumption.js create mode 100755 RVO21/flow/monitordisk.js create mode 100755 RVO21/flow/monitormemory.js create mode 100755 RVO21/flow/nodesdb_changecheck.js create mode 100755 RVO21/flow/show_dbdata.js create mode 100755 RVO21/flow/slack_filter.js create mode 100755 RVO21/flow/thermometer.js create mode 100755 RVO21/flow/trigger.js create mode 100755 RVO21/flow/variables.txt create mode 100755 RVO21/flow/virtualwirein.js create mode 100755 RVO21/flow/virtualwireout.js create mode 100755 RVO21/flow/wsmqttpublish.js create mode 100755 RVO21/monitor.txt create mode 100755 RVO21/package-lock.json create mode 100755 RVO21/package.json create mode 100755 RVO21/release.js create mode 100755 RVO21/release.js.json create mode 100755 RVO21/report_data.log diff --git a/RVO21/addSwitch.py b/RVO21/addSwitch.py new file mode 100755 index 0000000..c35e96b --- /dev/null +++ b/RVO21/addSwitch.py @@ -0,0 +1,36 @@ +import os + +def process_set_file(): + """ + Checks if /root/flowserver exists, reads set.txt, and modifies the second line. + """ + default_folder = "/root/flowserver" if os.path.exists("/root/flowserver") else "/home/unipi/flowserver" + flag = 1 if default_folder == "/root/flowserver" else 0 + + try: + with open("/home/unipi/flowserver/databases/settings.table", "r") as f: + lines = f.readlines() + + if len(lines) >= 2: + lines[0] = lines[0].rstrip('\n') + "|main_switch:boolean\n" + second_line = lines[1].strip() # remove trailing newline + last_pipe_index = second_line.rfind("|") + + if last_pipe_index != -1: + modified_line = second_line[:last_pipe_index + 1] + str(flag) + "|" + second_line[last_pipe_index + 1:] + lines[1] = modified_line + else: + print("Warning: No '|' character found in the second line of set.txt") + + with open("/home/unipi/flowserver/databases/settings.table", "w") as f: + f.writelines(lines) + else: + print("Warning: settings.table has less than two lines.") + + except FileNotFoundError: + print("Error: settings.table not found.") + except Exception as e: + print(e) + +# if __name__ == "__main__": +process_set_file() diff --git a/RVO21/cloud_topic.py b/RVO21/cloud_topic.py new file mode 100755 index 0000000..77c31f1 --- /dev/null +++ b/RVO21/cloud_topic.py @@ -0,0 +1,76 @@ +# import os +# +# def modify_file(file_path): +# """ +# Modifies the given file by: +# 1. Appending "|cloud_topic" to the first line. +# 2. Inserting the text from the third "." to the first "|" on the second line after the last "|" character. +# +# Args: +# file_path (str): The path to the file to be modified. +# """ +# +# with open(file_path, 'r+') as f: +# lines = f.readlines() +# +# # Modify the first line +# lines[0] += "|cloud_topic:string" +# +# # Modify the second line +# second_line = lines[1].strip() # Remove leading/trailing whitespace +# first_pipe_index = second_line.find('|') +# third_dot_index = second_line.find('.', second_line.find('.', second_line.find('.') + 1) + 1) +# text_to_insert = second_line[third_dot_index:first_pipe_index] +# +# last_pipe_index = second_line.rfind('|') +# lines[1] = second_line[:last_pipe_index + 1] + text_to_insert + "|" + second_line[last_pipe_index + 1:] +# +# print(first_pipe_index, third_dot_index, text_to_insert, last_pipe_index) +# # Write the modified lines back to the file +# # f.seek(0) +# # f.writelines(lines) +# # f.truncate() +# +# # Example usage: +# file_path = "settings.table" # Replace with the actual file path +# modify_file(file_path) +# + + +def modify_file(file_path): + """ + Modifies the given file by: + 1. Appending "|cloud_topic" to the first line. + 2. Inserting the text between the third "." and the second "|" on the second line after the last "|" character. + + Args: + file_path (str): The path to the file to be modified. + """ + + with open(file_path, 'r+') as f: + lines = f.readlines() + + first_line = lines[0].strip() + first_line += "|cloud_topic:string\n" + # Modify the first line + lines[0] = first_line + + # Modify the second line + second_line = lines[1].strip() # Remove leading/trailing whitespace + first_pipe_index = second_line.find('|') + second_pipe_index = second_line.find('|', first_pipe_index + 1) + third_dot_index = second_line.find('.', second_line.find('.', second_line.find('.') + 1) + 1) + text_to_insert = "u" + second_line[third_dot_index+1:second_pipe_index] + + last_pipe_index = second_line.rfind('|') + lines[1] = second_line[:last_pipe_index + 1] + text_to_insert + "|" + second_line[last_pipe_index + 1:] + + print(first_pipe_index, third_dot_index, text_to_insert, last_pipe_index) + # Write the modified lines back to the file + f.seek(0) + f.writelines(lines) + f.truncate() + +# Example usage: +file_path = "/home/unipi/flowserver/databases/settings.table" # Replace with the actual file path +modify_file(file_path) diff --git a/RVO21/config b/RVO21/config new file mode 100755 index 0000000..cd0a8a9 --- /dev/null +++ b/RVO21/config @@ -0,0 +1,12 @@ +name : Total.js Flow +default_timezone : Europe/Bratislava + +// Packages settings +package#flow (Object) : { url: '/' } + + +table.relays : line:number|tbname:string|contactor:number|profile:string +table.nodes : node:number|pole_number:string|node_type:string|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|project_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|cloud_topic:string|has_main_switch:boolean|daily_report:boolean|send_changed_node_numbers:boolean +table.pins : pin:string|type:string|line:number +table.notifications : key:string|weight:string|sk:string|en:string diff --git a/RVO21/createNode.py b/RVO21/createNode.py new file mode 100755 index 0000000..a8cea91 --- /dev/null +++ b/RVO21/createNode.py @@ -0,0 +1,43 @@ +print("zaciname") +import re, json + +search_str = '|' +final = [] +counter = 1 +with open("/home/unipi/flowserver/databases/nodes.table", 'r') as file: +# with open("/home/rasta5man/dev/oms/flowserver/databases/nodes.table", 'r') as file: + # Read each line in the file + for line in file: + # Print each line + line = line.strip() + print(line) + if counter != 1: + i = [m.start() for m in re.finditer(re.escape(search_str), line)] + node = line[ i[0] + 1 : i[1] ] + tbname = line[ i[3] + 1 : i[4] ] + final.append({node:tbname}) + counter += 1 +print(json.dumps(final)) +f = open("/home/unipi/flowserver/databases/nodes_original/nodes_original.table", "w") +f.write(json.dumps(final)) +f.close() + + +# +# # ``d`` has to be replaced with a different character +# old_character = "'" +# +# # ``t`` will replace ``d` +# new_character = '"' +# resultant_string = 0; +# with open("/home/unipi/flowserver/databases/nodes_original/nodes_original.table", 'r') as file: +# for line in file: +# resultant_string = re.sub("'", '"', line) +# +# resultant_string = re.sub(" ", "", resultant_string) +# print(resultant_string) +# +# f = open("/home/unipi/flowserver/databases/nodes_original/nodes_original.table", "w") +# f.write(str(resultant_string)) +# f.close() +# diff --git a/RVO21/databases/accelerometer_db.js b/RVO21/databases/accelerometer_db.js new file mode 100755 index 0000000..fdfc7fd --- /dev/null +++ b/RVO21/databases/accelerometer_db.js @@ -0,0 +1,3055 @@ +let naklony = { + "3993": { "label": "1/3A", "naklon": 0 }, + "3989": { "label": "1/3B", "naklon": 15 }, + "3976": { "label": "1/1", "naklon": 0 }, + "4181": { "label": "1/2", "naklon": 0 }, + "4376": { "label": "1/4", "naklon": 15 }, + "3868": { "label": "1/5", "naklon": 15 }, + "3728": { "label": "1/6", "naklon": 15 }, + "3730": { "label": "1/7", "naklon": 0 }, + "4374": { "label": "1/8", "naklon": 0 }, + "3718": { "label": "1/9", "naklon": 15 }, + "4375": { "label": "1/10", "naklon": 15 }, + "4172": { "label": "1/11", "naklon": 15 }, + "4176": { "label": "1/12", "naklon": 15 }, + "3800": { "label": "2/1", "naklon": 5 }, + "3823": { "label": "2/2", "naklon": 5 }, + "3905": { "label": "2/3", "naklon": 5 }, + "3803": { "label": "2/4", "naklon": 5 }, + "3817": { "label": "2/5", "naklon": 5 }, + "3818": { "label": "2/6", "naklon": 5 }, + "3811": { "label": "2/7", "naklon": 5 }, + "3915": { "label": "2/8", "naklon": 5 }, + "3843": { "label": "2/9", "naklon": 10 }, + "3827": { "label": "2/10", "naklon": 10 }, + "4220": { "label": "2/11", "naklon": 10 }, + "3826": { "label": "2/12", "naklon": 10 }, + "3834": { "label": "2/13", "naklon": 10 }, + "3838": { "label": "2/14", "naklon": 10 }, + "2823": { "label": "2/15", "naklon": 10 }, + "3750": { "label": "2/16", "naklon": 10 }, + "3378": { "label": "2/17", "naklon": 0 }, + "3376": { "label": "2/18", "naklon": 0 }, + "3379": { "label": "2/19", "naklon": 0 }, + "3285": { "label": "2/20", "naklon": 0 }, + "3382": { "label": "2/21", "naklon": 0 }, + "3383": { "label": "2/22", "naklon": 0 }, + "3375": { "label": "2/24", "naklon": 0 }, + "3381": { "label": "2/25", "naklon": 0 }, + "3380": { "label": "2/26", "naklon": 0 }, + "3828": { "label": "2/27", "naklon": 10 }, + "3377": { "label": "2/28", "naklon": 0 }, + "3591": { "label": "7/1", "naklon": 0 }, + "3587": { "label": "7/2", "naklon": 0 }, + "3468": { "label": "7/3", "naklon": 0 }, + "3466": { "label": "7/4", "naklon": 0 }, + "3474": { "label": "7/5", "naklon": 0 }, + "3481": { "label": "7/6", "naklon": 0 }, + "3589": { "label": "7/7", "naklon": 0 }, + "3472": { "label": "7/8", "naklon": 0 }, + "3473": { "label": "7/9", "naklon": 0 }, + "3584": { "label": "7/10", "naklon": 0 }, + "3571": { "label": "7/11", "naklon": 0 }, + "3476": { "label": "7/12", "naklon": 0 }, + "3590": { "label": "7/13", "naklon": 0 }, + "3478": { "label": "7/14", "naklon": 0 }, + "3471": { "label": "7/15", "naklon": 0 }, + "3467": { "label": "7/16", "naklon": 0 }, + "3479": { "label": "7/17", "naklon": 0 }, + "3480": { "label": "7/18", "naklon": 0 }, + "3477": { "label": "7/19", "naklon": 0 }, + "3362": { "label": "12/1", "naklon": 0 }, + "3355": { "label": "12/2", "naklon": 0 }, + "3356": { "label": "12/3", "naklon": 0 }, + "3349": { "label": "12/4", "naklon": 0 }, + "3357": { "label": "12/5", "naklon": 0 }, + "3350": { "label": "12/6", "naklon": 0 }, + "3353": { "label": "12/7", "naklon": 0 }, + "3539": { "label": "12/8", "naklon": 0 }, + "3050": { "label": "12/9", "naklon": 0 }, + "3361": { "label": "12/10", "naklon": 0 }, + "3360": { "label": "12/11", "naklon": 0 }, + "3358": { "label": "12/12", "naklon": 0 }, + "3541": { "label": "12/13", "naklon": 0 }, + "3551": { "label": "12/14", "naklon": 0 }, + "3514": { "label": "12/15", "naklon": 0 }, + "3547": { "label": "12/16", "naklon": 0 }, + "3562": { "label": "12/17", "naklon": 0 }, + "3525": { "label": "12/18", "naklon": 0 }, + "3558": { "label": "12/19", "naklon": 0 }, + "3511": { "label": "12/20", "naklon": 0 }, + "3058": { "label": "12/21", "naklon": 0 }, + "3062": { "label": "12/22", "naklon": 0 }, + "3070": { "label": "12/23", "naklon": 0 }, + "3447": { "label": "12/24", "naklon": 0 }, + "3056": { "label": "12/25", "naklon": 0 }, + "3057": { "label": "12/26", "naklon": 0 }, + "3071": { "label": "12/27", "naklon": 0 }, + "3061": { "label": "12/28", "naklon": 0 }, + "3069": { "label": "12/29", "naklon": 0 }, + "3077": { "label": "12/30", "naklon": 0 }, + "3080": { "label": "12/31", "naklon": 0 }, + "3081": { "label": "12/32", "naklon": 0 }, + "3078": { "label": "12/33", "naklon": 0 }, + "4037": { "label": "12/34", "naklon": 0 }, + "3067": { "label": "12/35", "naklon": 0 }, + "3051": { "label": "12/36", "naklon": 0 }, + "2924": { "label": "12/37", "naklon": 0 }, + "3060": { "label": "12/38", "naklon": 0 }, + "3073": { "label": "12/39", "naklon": 0 }, + "3469": { "label": "12/40", "naklon": 0 }, + "2923": { "label": "12/41", "naklon": 0 }, + "2925": { "label": "12/42", "naklon": 0 }, + "3359": { "label": "12/43", "naklon": 0 }, + "3055": { "label": "12/44", "naklon": 0 }, + "2922": { "label": "12/45", "naklon": 0 }, + "3084": { "label": "12/46", "naklon": 0 }, + "3064": { "label": "12/47", "naklon": 0 }, + "3066": { "label": "12/48", "naklon": 0 }, + "3072": { "label": "12/49", "naklon": 0 }, + "3415": { "label": "13/13A", "naklon": 0 }, + "3409": { "label": "13/13B", "naklon": 0 }, + "3399": { "label": "13/13C", "naklon": 0 }, + "3410": { "label": "13/29A", "naklon": 0 }, + "3407": { "label": "13/29B", "naklon": 0 }, + "3405": { "label": "13/34A", "naklon": 0 }, + "3404": { "label": "13/34B", "naklon": 0 }, + "3392": { "label": "13/45A", "naklon": 0 }, + "3386": { "label": "13/45B", "naklon": 0 }, + "3303": { "label": "13/60A", "naklon": 3 }, + "3302": { "label": "13/60B", "naklon": 3 }, + "3319": { "label": "13/70A", "naklon": 6 }, + "3317": { "label": "13/70B", "naklon": 6 }, + "3326": { "label": "13/70C", "naklon": 6 }, + "3351": { "label": "13/73A", "naklon": 6 }, + "3313": { "label": "13/73B", "naklon": 6 }, + "3316": { "label": "13/83A", "naklon": 0 }, + "3320": { "label": "13/83B", "naklon": 0 }, + "3336": { "label": "13/95A", "naklon": 0 }, + "3323": { "label": "13/95B", "naklon": 0 }, + "3339": { "label": "13/98A", "naklon": 0 }, + "3333": { "label": "13/98B", "naklon": 0 }, + "3425": { "label": "13/1", "naklon": 0 }, + "3419": { "label": "13/2", "naklon": 0 }, + "3416": { "label": "13/3", "naklon": 0 }, + "3332": { "label": "13/4", "naklon": 0 }, + "3422": { "label": "13/5", "naklon": 0 }, + "3417": { "label": "13/6", "naklon": 0 }, + "3418": { "label": "13/7", "naklon": 0 }, + "3424": { "label": "13/8", "naklon": 0 }, + "3334": { "label": "13/9", "naklon": 0 }, + "4363": { "label": "13/10", "naklon": 0 }, + "3423": { "label": "13/11", "naklon": 0 }, + "3406": { "label": "13/12", "naklon": 0 }, + "3411": { "label": "13/14", "naklon": 0 }, + "3412": { "label": "13/15", "naklon": 0 }, + "3413": { "label": "13/16", "naklon": 0 }, + "3414": { "label": "13/17", "naklon": 0 }, + "3391": { "label": "13/18", "naklon": 0 }, + "3370": { "label": "13/19", "naklon": 0 }, + "3369": { "label": "13/20", "naklon": 0 }, + "3408": { "label": "13/21", "naklon": 0 }, + "3393": { "label": "13/22", "naklon": 0 }, + "3128": { "label": "13/23", "naklon": 0 }, + "3197": { "label": "13/24", "naklon": 0 }, + "4364": { "label": "13/25", "naklon": 0 }, + "3155": { "label": "13/26", "naklon": 0 }, + "3196": { "label": "13/27", "naklon": 0 }, + "3144": { "label": "13/28", "naklon": 0 }, + "3150": { "label": "13/30", "naklon": 0 }, + "3390": { "label": "13/31", "naklon": 0 }, + "3401": { "label": "13/32", "naklon": 0 }, + "3275": { "label": "13/33", "naklon": 0 }, + "3371": { "label": "13/35", "naklon": 0 }, + "3389": { "label": "13/36", "naklon": 0 }, + "3388": { "label": "13/37", "naklon": 0 }, + "3365": { "label": "13/38", "naklon": 0 }, + "3363": { "label": "13/39", "naklon": 0 }, + "3397": { "label": "13/40", "naklon": 0 }, + "3567": { "label": "13/40/1", "naklon": 0 }, + "3387": { "label": "13/41", "naklon": 0 }, + "3403": { "label": "13/42", "naklon": 0 }, + "3147": { "label": "13/43", "naklon": 0 }, + "3141": { "label": "13/44", "naklon": 0 }, + "3364": { "label": "13/46", "naklon": 0 }, + "3367": { "label": "13/47", "naklon": 0 }, + "3368": { "label": "13/48", "naklon": 0 }, + "3402": { "label": "13/49", "naklon": 0 }, + "3366": { "label": "13/50", "naklon": 0 }, + "3395": { "label": "13/51", "naklon": 0 }, + "3372": { "label": "13/52", "naklon": 0 }, + "3394": { "label": "13/53", "naklon": 0 }, + "3308": { "label": "13/54", "naklon": 0 }, + "3847": { "label": "13/54/1", "naklon": 0 }, + "3312": { "label": "13/55", "naklon": 3 }, + "3309": { "label": "13/56", "naklon": 3 }, + "3311": { "label": "13/57", "naklon": 3 }, + "3310": { "label": "13/58", "naklon": 3 }, + "4365": { "label": "13/59", "naklon": 3 }, + "4093": { "label": "13/60/1", "naklon": 3 }, + "3304": { "label": "13/61", "naklon": 3 }, + "3307": { "label": "13/62", "naklon": 3 }, + "3271": { "label": "13/63", "naklon": 3 }, + "3301": { "label": "13/64", "naklon": 3 }, + "4366": { "label": "13/65", "naklon": 3 }, + "3300": { "label": "13/66", "naklon": 3 }, + "3185": { "label": "13/67", "naklon": 0 }, + "3184": { "label": "13/68", "naklon": 0 }, + "3188": { "label": "13/69", "naklon": 0 }, + "3343": { "label": "13/71", "naklon": 6 }, + "3819": { "label": "13/71/1", "naklon": 6 }, + "3880": { "label": "13/71/2", "naklon": 6 }, + "3348": { "label": "13/72", "naklon": 6 }, + "3344": { "label": "13/74", "naklon": 6 }, + "3346": { "label": "13/75", "naklon": 6 }, + "3597": { "label": "13/75/1", "naklon": 6 }, + "3345": { "label": "13/76", "naklon": 6 }, + "3322": { "label": "13/77", "naklon": 0 }, + "3325": { "label": "13/78", "naklon": 0 }, + "4310": { "label": "13/78/1", "naklon": 0 }, + "3315": { "label": "13/79", "naklon": 0 }, + "3328": { "label": "13/80", "naklon": 0 }, + "3321": { "label": "13/81", "naklon": 0 }, + "3324": { "label": "13/82", "naklon": 0 }, + "3140": { "label": "13/84", "naklon": 0 }, + "3153": { "label": "13/85", "naklon": 0 }, + "3145": { "label": "13/86", "naklon": 0 }, + "3134": { "label": "13/87", "naklon": 0 }, + "3151": { "label": "13/88", "naklon": 0 }, + "3143": { "label": "13/89", "naklon": 0 }, + "3318": { "label": "13/90", "naklon": 0 }, + "3347": { "label": "13/91", "naklon": 0 }, + "3314": { "label": "13/94", "naklon": 0 }, + "3331": { "label": "13/96", "naklon": 0 }, + "3327": { "label": "13/97", "naklon": 0 }, + "3329": { "label": "13/99", "naklon": 0 }, + "3337": { "label": "13/100", "naklon": 0 }, + "3330": { "label": "13/101", "naklon": 0 }, + "3335": { "label": "13/102", "naklon": 0 }, + "3420": { "label": "13/103", "naklon": 0 }, + "3421": { "label": "13/104", "naklon": 0 }, + "4361": { "label": "13/105", "naklon": 0 }, + "4362": { "label": "13/106", "naklon": 0 }, + "3526": { "label": "13/107", "naklon": 0 }, + "4424": { "label": "13/108", "naklon": null }, + "3561": { "label": "13/109", "naklon": null }, + "3527": { "label": "13/110", "naklon": null }, + "3521": { "label": "13/111", "naklon": null }, + "3552": { "label": "13/112", "naklon": null }, + "3544": { "label": "13/113", "naklon": null }, + "3534": { "label": "13/114", "naklon": null }, + "3516": { "label": "13/115", "naklon": null }, + "3513": { "label": "13/116", "naklon": null }, + "3565": { "label": "13/117", "naklon": null }, + "3866": { "label": "13/118", "naklon": null }, + "3136": { "label": "14/1", "naklon": 0 }, + "3137": { "label": "14/2", "naklon": 0 }, + "3135": { "label": "14/3", "naklon": 0 }, + "3149": { "label": "14/4", "naklon": 0 }, + "3142": { "label": "14/5", "naklon": 0 }, + "3342": { "label": "14/6", "naklon": 0 }, + "3340": { "label": "14/7", "naklon": 0 }, + "3152": { "label": "14/8", "naklon": 0 }, + "3886": { "label": "14/9", "naklon": 0 }, + "3341": { "label": "14/10", "naklon": null }, + "3352": { "label": "14/11", "naklon": null }, + "3396": { "label": "15/1", "naklon": 5 }, + "2784": { "label": "15/2", "naklon": 5 }, + "2788": { "label": "15/3", "naklon": 5 }, + "2801": { "label": "15/4", "naklon": 5 }, + "2815": { "label": "15/5", "naklon": 5 }, + "2829": { "label": "15/6", "naklon": 5 }, + "2796": { "label": "15/7", "naklon": 5 }, + "2803": { "label": "15/8", "naklon": 5 }, + "4304": { "label": "15/8/1", "naklon": 5 }, + "4311": { "label": "15/8/2", "naklon": 5 }, + "2821": { "label": "15/9", "naklon": 5 }, + "3400": { "label": "15/10", "naklon": 5 }, + "2799": { "label": "15/11", "naklon": 5 }, + "2804": { "label": "15/12", "naklon": 5 }, + "4303": { "label": "15/12/1", "naklon": 5 }, + "4309": { "label": "15/12/2", "naklon": 5 }, + "2806": { "label": "15/13", "naklon": 5 }, + "2787": { "label": "15/14", "naklon": 5 }, + "2809": { "label": "15/15", "naklon": 5 }, + "2814": { "label": "15/16", "naklon": 0 }, + "3934": { "label": "15/17", "naklon": 0 }, + "3192": { "label": "15/18", "naklon": 0 }, + "2812": { "label": "15/19", "naklon": 0 }, + "4070": { "label": "15/20", "naklon": 0 }, + "2826": { "label": "15/21", "naklon": 0 }, + "2808": { "label": "15/22", "naklon": 3 }, + "2795": { "label": "15/23", "naklon": 3 }, + "2807": { "label": "15/24", "naklon": 3 }, + "2831": { "label": "15/25", "naklon": 0 }, + "2862": { "label": "15/26", "naklon": null }, + "2861": { "label": "15/27", "naklon": 0 }, + "2866": { "label": "15/28", "naklon": 0 }, + "3546": { "label": "15/28/1", "naklon": 0 }, + "4146": { "label": "15/29", "naklon": 0 }, + "3001": { "label": "15/29/1", "naklon": 0 }, + "2835": { "label": "15/30", "naklon": 0 }, + "2874": { "label": "15/31", "naklon": 0 }, + "2852": { "label": "15/32", "naklon": 0 }, + "2851": { "label": "15/33", "naklon": 0 }, + "3560": { "label": "15/33/1", "naklon": 0 }, + "2858": { "label": "15/34", "naklon": 0 }, + "4306": { "label": "15/34/1", "naklon": 0 }, + "2856": { "label": "15/35", "naklon": 0 }, + "2847": { "label": "15/36", "naklon": 0 }, + "3556": { "label": "15/36/1", "naklon": 0 }, + "3950": { "label": "15/37", "naklon": 0 }, + "2848": { "label": "15/38", "naklon": 0 }, + "2863": { "label": "15/39", "naklon": 0 }, + "4313": { "label": "15/39/1", "naklon": 0 }, + "2873": { "label": "15/40", "naklon": 0 }, + "2984": { "label": "15/40/1", "naklon": 0 }, + "2854": { "label": "15/41", "naklon": 0 }, + "2859": { "label": "15/42", "naklon": 0 }, + "2872": { "label": "15/43", "naklon": 0 }, + "2849": { "label": "15/44", "naklon": 0 }, + "2864": { "label": "15/45", "naklon": 0 }, + "3553": { "label": "15/46", "naklon": null }, + "3021": { "label": "15/47", "naklon": null }, + "3008": { "label": "15/47/1", "naklon": null }, + "3017": { "label": "15/48", "naklon": null }, + "3014": { "label": "15/49", "naklon": null }, + "2981": { "label": "15/50", "naklon": null }, + "3020": { "label": "15/51", "naklon": null }, + "3027": { "label": "15/52", "naklon": null }, + "3006": { "label": "15/53", "naklon": null }, + "3012": { "label": "15/54", "naklon": null }, + "2738": { "label": "15/55", "naklon": 0 }, + "2725": { "label": "15/56", "naklon": 0 }, + "3016": { "label": "15/57", "naklon": null }, + "3005": { "label": "15/58", "naklon": null }, + "3009": { "label": "15/58/1", "naklon": null }, + "3010": { "label": "15/59", "naklon": 0 }, + "3538": { "label": "15/59/1", "naklon": 0 }, + "4145": { "label": "15/59/2", "naklon": 0 }, + "2713": { "label": "15/60", "naklon": 0 }, + "2789": { "label": "15/61", "naklon": 0 }, + "2736": { "label": "15/62", "naklon": 0 }, + "2739": { "label": "15/63", "naklon": 0 }, + "4346": { "label": "15/64", "naklon": 0 }, + "2731": { "label": "15/65", "naklon": 0 }, + "2818": { "label": "15/66", "naklon": 0 }, + "3557": { "label": "15/66/1", "naklon": 0 }, + "2822": { "label": "15/67", "naklon": 0 }, + "2833": { "label": "15/68", "naklon": 0 }, + "2834": { "label": "15/69", "naklon": 0 }, + "3097": { "label": "15/70", "naklon": 0 }, + "2824": { "label": "15/71", "naklon": 0 }, + "2828": { "label": "15/72", "naklon": 0 }, + "2600": { "label": "15/73", "naklon": 0 }, + "4314": { "label": "15/73/1", "naklon": 0 }, + "2832": { "label": "15/74", "naklon": 0 }, + "4360": { "label": "15/75", "naklon": 0 }, + "2846": { "label": "15/76", "naklon": 0 }, + "2584": { "label": "15/77", "naklon": 0 }, + "2843": { "label": "15/78", "naklon": 0 }, + "4308": { "label": "15/78/1", "naklon": 0 }, + "4144": { "label": "15/79", "naklon": null }, + "2844": { "label": "15/80", "naklon": 0 }, + "2842": { "label": "15/81", "naklon": 0 }, + "2838": { "label": "15/82", "naklon": 0 }, + "2837": { "label": "15/83", "naklon": null }, + "3555": { "label": "15/83/1", "naklon": null }, + "2839": { "label": "15/84", "naklon": 0 }, + "2830": { "label": "15/85", "naklon": 0 }, + "4066": { "label": "15/86", "naklon": 0 }, + "2836": { "label": "15/87", "naklon": 0 }, + "2911": { "label": "15/88", "naklon": 0 }, + "2825": { "label": "15/89", "naklon": 0 }, + "2811": { "label": "15/90", "naklon": 0 }, + "3740": { "label": "15/94", "naklon": 15 }, + "2734": { "label": "15/95", "naklon": 15 }, + "3105": { "label": "15/96", "naklon": 15 }, + "2732": { "label": "15/97", "naklon": 15 }, + "2727": { "label": "15/98", "naklon": 15 }, + "2735": { "label": "15/99", "naklon": 15 }, + "3926": { "label": "15/100", "naklon": 15 }, + "2918": { "label": "15/101", "naklon": 0 }, + "2705": { "label": "15/102", "naklon": 10 }, + "2708": { "label": "15/103", "naklon": 10 }, + "2721": { "label": "15/104", "naklon": 10 }, + "2719": { "label": "15/105", "naklon": 10 }, + "2919": { "label": "15/106", "naklon": 10 }, + "3101": { "label": "15/107", "naklon": 10 }, + "2853": { "label": "15/108", "naklon": 10 }, + "2715": { "label": "15/109", "naklon": 10 }, + "2712": { "label": "15/110", "naklon": 0 }, + "2711": { "label": "15/111", "naklon": 0 }, + "2709": { "label": "15/112", "naklon": 0 }, + "2710": { "label": "15/113", "naklon": 0 }, + "2907": { "label": "15/114", "naklon": 0 }, + "2906": { "label": "15/115", "naklon": 0 }, + "2908": { "label": "15/116", "naklon": 0 }, + "2901": { "label": "15/117", "naklon": 0 }, + "2913": { "label": "15/118", "naklon": 0 }, + "3656": { "label": "15/119", "naklon": 0 }, + "2781": { "label": "15/120", "naklon": 0 }, + "2802": { "label": "15/121", "naklon": 0 }, + "2791": { "label": "15/122", "naklon": 0 }, + "2783": { "label": "15/123", "naklon": 0 }, + "2794": { "label": "15/124", "naklon": 0 }, + "3139": { "label": "15/125", "naklon": 0 }, + "3229": { "label": "15/126", "naklon": 5 }, + "3239": { "label": "15/127", "naklon": 5 }, + "3230": { "label": "15/128", "naklon": 5 }, + "4016": { "label": "15/129", "naklon": null }, + "3608": { "label": "16/16A", "naklon": 0 }, + "4151": { "label": "16/16B", "naklon": 0 }, + "3710": { "label": "16/1", "naklon": 0 }, + "3726": { "label": "16/2", "naklon": 0 }, + "3743": { "label": "16/3", "naklon": 0 }, + "3724": { "label": "16/4", "naklon": 0 }, + "3712": { "label": "16/5", "naklon": 0 }, + "3739": { "label": "16/6", "naklon": 0 }, + "3742": { "label": "16/7", "naklon": 0 }, + "3731": { "label": "16/8", "naklon": 0 }, + "3727": { "label": "16/9", "naklon": 0 }, + "3729": { "label": "16/10", "naklon": 0 }, + "3736": { "label": "16/11", "naklon": 0 }, + "3713": { "label": "16/12", "naklon": 0 }, + "3715": { "label": "16/13", "naklon": 0 }, + "3733": { "label": "16/14", "naklon": 0 }, + "3732": { "label": "16/15", "naklon": 0 }, + "3634": { "label": "16/17", "naklon": 0 }, + "3610": { "label": "16/18", "naklon": 0 }, + "3626": { "label": "16/19", "naklon": 0 }, + "3618": { "label": "16/20", "naklon": 0 }, + "3619": { "label": "16/21", "naklon": 0 }, + "3628": { "label": "16/22", "naklon": 0 }, + "3615": { "label": "16/23", "naklon": 0 }, + "3609": { "label": "16/24", "naklon": 0 }, + "3606": { "label": "16/25", "naklon": 0 }, + "3624": { "label": "16/26", "naklon": 0 }, + "3627": { "label": "16/27", "naklon": 0 }, + "3607": { "label": "16/28", "naklon": 0 }, + "4370": { "label": "16/29", "naklon": 0 }, + "3692": { "label": "16/30", "naklon": 0 }, + "3614": { "label": "16/31", "naklon": 0 }, + "3623": { "label": "16/32", "naklon": 0 }, + "4373": { "label": "16/33", "naklon": 0 }, + "3620": { "label": "16/34", "naklon": 0 }, + "3685": { "label": "16/35", "naklon": 0 }, + "3616": { "label": "16/36", "naklon": 0 }, + "3686": { "label": "16/37", "naklon": 0 }, + "3688": { "label": "16/38", "naklon": 0 }, + "3684": { "label": "16/39", "naklon": 0 }, + "3825": { "label": "16/40", "naklon": 0 }, + "3865": { "label": "16/41", "naklon": 0 }, + "3824": { "label": "16/42", "naklon": 0 }, + "3871": { "label": "16/43", "naklon": 0 }, + "3801": { "label": "16/44", "naklon": 0 }, + "3862": { "label": "16/45", "naklon": 0 }, + "3876": { "label": "16/46", "naklon": 0 }, + "3861": { "label": "16/47", "naklon": 0 }, + "4215": { "label": "16/48", "naklon": 0 }, + "3605": { "label": "16/49", "naklon": 10 }, + "3603": { "label": "16/50", "naklon": 10 }, + "3592": { "label": "16/51", "naklon": 10 }, + "3598": { "label": "16/52", "naklon": 10 }, + "3594": { "label": "16/53", "naklon": 10 }, + "3593": { "label": "16/54", "naklon": 10 }, + "3630": { "label": "16/55", "naklon": 10 }, + "3763": { "label": "16/56", "naklon": 10 }, + "3746": { "label": "16/57", "naklon": 10 }, + "3699": { "label": "16/58", "naklon": 0 }, + "3698": { "label": "16/59", "naklon": 0 }, + "3709": { "label": "16/60", "naklon": null }, + "3708": { "label": "16/61", "naklon": 0 }, + "3703": { "label": "16/62", "naklon": null }, + "3700": { "label": "16/63", "naklon": 0 }, + "3701": { "label": "16/64", "naklon": null }, + "3704": { "label": "16/65", "naklon": 0 }, + "3707": { "label": "16/66", "naklon": null }, + "3810": { "label": "16/67", "naklon": 0 }, + "4208": { "label": "16/68", "naklon": null }, + "3867": { "label": "16/69", "naklon": 0 }, + "4372": { "label": "16/70", "naklon": null }, + "3881": { "label": "16/71", "naklon": 0 }, + "4204": { "label": "16/72", "naklon": null }, + "3869": { "label": "16/73", "naklon": 0 }, + "4202": { "label": "16/74", "naklon": null }, + "3830": { "label": "16/75", "naklon": 0 }, + "3870": { "label": "16/76", "naklon": null }, + "3964": { "label": "16/77", "naklon": 0 }, + "3849": { "label": "16/78", "naklon": 0 }, + "3694": { "label": "16/79", "naklon": null }, + "3717": { "label": "16/80", "naklon": 0 }, + "3877": { "label": "16/81", "naklon": null }, + "3755": { "label": "16/82", "naklon": 0 }, + "3725": { "label": "16/83", "naklon": null }, + "3716": { "label": "16/84", "naklon": 0 }, + "3696": { "label": "16/85", "naklon": null }, + "3702": { "label": "16/86", "naklon": 0 }, + "3706": { "label": "16/87", "naklon": null }, + "3850": { "label": "16/88", "naklon": 0 }, + "3848": { "label": "16/89", "naklon": null }, + "3737": { "label": "16/90", "naklon": null }, + "3705": { "label": "16/91", "naklon": 0 }, + "3723": { "label": "16/92", "naklon": null }, + "3842": { "label": "16/93", "naklon": 0 }, + "3735": { "label": "16/94", "naklon": null }, + "3719": { "label": "16/95", "naklon": 0 }, + "3697": { "label": "16/96", "naklon": 0 }, + "3711": { "label": "16/97", "naklon": 0 }, + "4107": { "label": "16/98", "naklon": null }, + "4112": { "label": "16/99", "naklon": 5 }, + "4106": { "label": "16/100", "naklon": 5 }, + "4111": { "label": "16/101", "naklon": 5 }, + "4091": { "label": "16/102", "naklon": null }, + "4104": { "label": "16/103", "naklon": 5 }, + "4094": { "label": "16/104", "naklon": null }, + "4089": { "label": "16/105", "naklon": 5 }, + "4095": { "label": "16/106", "naklon": null }, + "4102": { "label": "16/107", "naklon": 5 }, + "4105": { "label": "16/108", "naklon": null }, + "3859": { "label": "16/109", "naklon": null }, + "4090": { "label": "16/110", "naklon": 5 }, + "4110": { "label": "16/111", "naklon": null }, + "4097": { "label": "16/112", "naklon": 5 }, + "4099": { "label": "16/113", "naklon": null }, + "4096": { "label": "16/114", "naklon": null }, + "4101": { "label": "16/115", "naklon": 5 }, + "4109": { "label": "16/116", "naklon": null }, + "4092": { "label": "16/117", "naklon": 5 }, + "3631": { "label": "16/118", "naklon": null }, + "3632": { "label": "16/119", "naklon": 0 }, + "3641": { "label": "16/120", "naklon": null }, + "3638": { "label": "16/121", "naklon": 0 }, + "3637": { "label": "16/122", "naklon": null }, + "4142": { "label": "16/123", "naklon": null }, + "4147": { "label": "16/124", "naklon": 5 }, + "4139": { "label": "16/125", "naklon": 5 }, + "3172": { "label": "20/30A", "naklon": 2 }, + "3164": { "label": "20/30B", "naklon": 2 }, + "3247": { "label": "20/1", "naklon": 10 }, + "3296": { "label": "20/2", "naklon": 10 }, + "3246": { "label": "20/3", "naklon": 10 }, + "3270": { "label": "20/4", "naklon": 10 }, + "3294": { "label": "20/5", "naklon": 10 }, + "3298": { "label": "20/6", "naklon": 10 }, + "3297": { "label": "20/7", "naklon": 10 }, + "3293": { "label": "20/8", "naklon": 10 }, + "3299": { "label": "20/9", "naklon": 10 }, + "3295": { "label": "20/10", "naklon": 10 }, + "3244": { "label": "20/11", "naklon": 10 }, + "3249": { "label": "20/12", "naklon": 10 }, + "3268": { "label": "20/13", "naklon": 10 }, + "3245": { "label": "20/14", "naklon": 10 }, + "3278": { "label": "20/15", "naklon": 10 }, + "3280": { "label": "20/16", "naklon": 10 }, + "3292": { "label": "20/17", "naklon": 10 }, + "3287": { "label": "20/18", "naklon": 10 }, + "3282": { "label": "20/19", "naklon": 10 }, + "3273": { "label": "20/20", "naklon": 0 }, + "3157": { "label": "20/21", "naklon": 0 }, + "3283": { "label": "20/22", "naklon": 0 }, + "3159": { "label": "20/23", "naklon": 0 }, + "3289": { "label": "20/24", "naklon": 0 }, + "3163": { "label": "20/25", "naklon": 0 }, + "3126": { "label": "20/26", "naklon": 0 }, + "3171": { "label": "20/27", "naklon": 0 }, + "3162": { "label": "20/28", "naklon": 0 }, + "3279": { "label": "20/29", "naklon": 10 }, + "3173": { "label": "20/31", "naklon": 0 }, + "3127": { "label": "20/32", "naklon": 0 }, + "3131": { "label": "20/33", "naklon": 0 }, + "3129": { "label": "20/34", "naklon": 0 }, + "3276": { "label": "20/35", "naklon": 2 }, + "3290": { "label": "20/36", "naklon": 2 }, + "3132": { "label": "20/37", "naklon": 0 }, + "3138": { "label": "20/38", "naklon": 0 }, + "3272": { "label": "20/39", "naklon": 0 }, + "3291": { "label": "20/40", "naklon": 0 }, + "3277": { "label": "20/41", "naklon": 10 }, + "3286": { "label": "20/42", "naklon": 10 }, + "3281": { "label": "20/43", "naklon": 10 }, + "3288": { "label": "20/44", "naklon": 10 }, + "3284": { "label": "20/45", "naklon": 10 }, + "3167": { "label": "20/46", "naklon": 10 }, + "3872": { "label": "20/47", "naklon": 0 }, + "3124": { "label": "20/48", "naklon": 0 }, + "3133": { "label": "20/49", "naklon": 0 }, + "3158": { "label": "20/50", "naklon": 0 }, + "3169": { "label": "20/51", "naklon": 0 }, + "3146": { "label": "20/52", "naklon": 0 }, + "3160": { "label": "20/53", "naklon": 0 }, + "3248": { "label": "20/54", "naklon": 0 }, + "3156": { "label": "20/55", "naklon": 0 }, + "3161": { "label": "20/56", "naklon": 0 }, + "3170": { "label": "20/57", "naklon": 0 }, + "3168": { "label": "20/58", "naklon": 0 }, + "3125": { "label": "20/59", "naklon": 0 }, + "3166": { "label": "20/60", "naklon": 0 }, + "3130": { "label": "20/61", "naklon": 0 }, + "3563": { "label": "20/62", "naklon": 0 }, + "3550": { "label": "20/63", "naklon": null }, + "3269": { "label": "20/67", "naklon": 0 }, + "2921": { "label": "21/1", "naklon": 0 }, + "2707": { "label": "21/2", "naklon": 0 }, + "2723": { "label": "21/3", "naklon": 0 }, + "2716": { "label": "21/4", "naklon": 0 }, + "2717": { "label": "21/5", "naklon": 0 }, + "2720": { "label": "21/6", "naklon": 0 }, + "2722": { "label": "21/7", "naklon": 0 }, + "2718": { "label": "21/8", "naklon": 0 }, + "2724": { "label": "21/9", "naklon": 0 }, + "2742": { "label": "21/10", "naklon": 0 }, + "2743": { "label": "21/11", "naklon": 0 }, + "2733": { "label": "21/12", "naklon": 0 }, + "2903": { "label": "21/14", "naklon": 0 }, + "2917": { "label": "21/15", "naklon": 0 }, + "2897": { "label": "21/16", "naklon": 0 }, + "2914": { "label": "21/17", "naklon": 0 }, + "2898": { "label": "21/18", "naklon": 0 }, + "2773": { "label": "21/19", "naklon": 0 }, + "2895": { "label": "21/20", "naklon": 0 }, + "2896": { "label": "21/21", "naklon": 0 }, + "2771": { "label": "21/22", "naklon": 0 }, + "2772": { "label": "21/23", "naklon": 0 }, + "2793": { "label": "21/24", "naklon": 0 }, + "2902": { "label": "21/25", "naklon": 0 }, + "2910": { "label": "21/26", "naklon": 0 }, + "2909": { "label": "21/27", "naklon": 0 }, + "2920": { "label": "21/28", "naklon": 0 }, + "2916": { "label": "21/29", "naklon": 0 }, + "2904": { "label": "21/30", "naklon": 0 }, + "2915": { "label": "21/31", "naklon": 0 }, + "2905": { "label": "21/32", "naklon": 0 }, + "2900": { "label": "21/33", "naklon": 0 }, + "2899": { "label": "21/34", "naklon": 0 }, + "2741": { "label": "21/36", "naklon": 0 }, + "2714": { "label": "21/37", "naklon": 0 }, + "2701": { "label": "21/38", "naklon": 0 }, + "2703": { "label": "21/39", "naklon": 0 }, + "2704": { "label": "21/40", "naklon": 0 }, + "2702": { "label": "21/41", "naklon": 0 }, + "2706": { "label": "21/42", "naklon": 0 }, + "2776": { "label": "21/43", "naklon": 0 }, + "2770": { "label": "21/44", "naklon": 0 }, + "2786": { "label": "21/45", "naklon": 0 }, + "2779": { "label": "21/46", "naklon": 0 }, + "2782": { "label": "21/47", "naklon": 0 }, + "2785": { "label": "21/48", "naklon": 0 }, + "2769": { "label": "21/49", "naklon": 0 }, + "3354": { "label": "21/50", "naklon": 0 }, + "2778": { "label": "21/51", "naklon": 0 }, + "2775": { "label": "21/52", "naklon": 0 }, + "2780": { "label": "21/53", "naklon": 0 }, + "2790": { "label": "21/54", "naklon": 0 }, + "2792": { "label": "21/55", "naklon": 0 }, + "2774": { "label": "21/56", "naklon": 0 }, + "2630": { "label": "22/1", "naklon": 0 }, + "2631": { "label": "22/2", "naklon": 0 }, + "2632": { "label": "22/3", "naklon": 0 }, + "2633": { "label": "22/4", "naklon": 0 }, + "2634": { "label": "22/5", "naklon": 0 }, + "2636": { "label": "22/6", "naklon": 0 }, + "4367": { "label": "22/7", "naklon": 0 }, + "2637": { "label": "22/8", "naklon": 0 }, + "2638": { "label": "22/9", "naklon": 0 }, + "2639": { "label": "22/10", "naklon": 0 }, + "2640": { "label": "22/11", "naklon": 0 }, + "2641": { "label": "22/12", "naklon": 0 }, + "2642": { "label": "22/13", "naklon": 0 }, + "2643": { "label": "22/14", "naklon": 0 }, + "2644": { "label": "22/15", "naklon": 0 }, + "2645": { "label": "22/16", "naklon": 0 }, + "2646": { "label": "22/17", "naklon": 0 }, + "2647": { "label": "22/18", "naklon": 0 }, + "2648": { "label": "22/19", "naklon": 0 }, + "2649": { "label": "22/20", "naklon": 0 }, + "2650": { "label": "22/21", "naklon": 0 }, + "2651": { "label": "22/22", "naklon": 0 }, + "4103": { "label": "22/23", "naklon": 0 }, + "2653": { "label": "22/24", "naklon": 0 }, + "2654": { "label": "22/25", "naklon": 0 }, + "2655": { "label": "22/26", "naklon": 0 }, + "2656": { "label": "22/27", "naklon": 0 }, + "2657": { "label": "22/28", "naklon": 0 }, + "2658": { "label": "22/29", "naklon": 0 }, + "2659": { "label": "22/30", "naklon": 0 }, + "2660": { "label": "22/31", "naklon": 0 }, + "2661": { "label": "22/32", "naklon": 0 }, + "3015": { "label": "22/32/1", "naklon": 0 }, + "2662": { "label": "22/33", "naklon": 0 }, + "2663": { "label": "22/34", "naklon": 0 }, + "2664": { "label": "22/35", "naklon": 0 }, + "2665": { "label": "22/36", "naklon": 0 }, + "2666": { "label": "22/37", "naklon": 0 }, + "2667": { "label": "22/38", "naklon": 0 }, + "2668": { "label": "22/39", "naklon": 0 }, + "2669": { "label": "22/40", "naklon": null }, + "2670": { "label": "22/41", "naklon": null }, + "2671": { "label": "22/42", "naklon": null }, + "3087": { "label": "23/9A", "naklon": 10 }, + "3090": { "label": "23/9B", "naklon": 10 }, + "3075": { "label": "23/1", "naklon": 0 }, + "3089": { "label": "23/2", "naklon": 0 }, + "3088": { "label": "23/3", "naklon": 0 }, + "3228": { "label": "23/4", "naklon": 10 }, + "2751": { "label": "23/5", "naklon": 10 }, + "3243": { "label": "23/6", "naklon": 10 }, + "4349": { "label": "23/7", "naklon": 10 }, + "3102": { "label": "23/8", "naklon": 10 }, + "3099": { "label": "23/10", "naklon": 10 }, + "3103": { "label": "23/11", "naklon": 10 }, + "3093": { "label": "23/12", "naklon": 10 }, + "3098": { "label": "23/13", "naklon": 10 }, + "3092": { "label": "23/14", "naklon": 10 }, + "3233": { "label": "23/15", "naklon": 0 }, + "3095": { "label": "23/16", "naklon": 0 }, + "4074": { "label": "23/17", "naklon": 0 }, + "2729": { "label": "23/18", "naklon": 0 }, + "3234": { "label": "23/19", "naklon": 0 }, + "3094": { "label": "23/20", "naklon": 0 }, + "2817": { "label": "23/21", "naklon": 0 }, + "3226": { "label": "23/22", "naklon": 0 }, + "3225": { "label": "23/23", "naklon": 0 }, + "3237": { "label": "23/24", "naklon": 0 }, + "4250": { "label": "23/25", "naklon": 0 }, + "3059": { "label": "23/26", "naklon": 10 }, + "3238": { "label": "23/27", "naklon": 10 }, + "3242": { "label": "23/28", "naklon": 10 }, + "3236": { "label": "23/29", "naklon": 10 }, + "3112": { "label": "23/30", "naklon": 10 }, + "3224": { "label": "23/31", "naklon": 0 }, + "4298": { "label": "23/32", "naklon": 10 }, + "4150": { "label": "23/33", "naklon": 10 }, + "3091": { "label": "23/34", "naklon": 10 }, + "3771": { "label": "25/1", "naklon": 5 }, + "3777": { "label": "25/2", "naklon": 5 }, + "3749": { "label": "25/3", "naklon": 5 }, + "3769": { "label": "25/4", "naklon": 5 }, + "3765": { "label": "25/5", "naklon": 5 }, + "3785": { "label": "25/6", "naklon": 5 }, + "3761": { "label": "25/7", "naklon": 5 }, + "3758": { "label": "25/8", "naklon": 5 }, + "3766": { "label": "25/9", "naklon": 5 }, + "3779": { "label": "25/10", "naklon": 5 }, + "3899": { "label": "25/11", "naklon": 10 }, + "3922": { "label": "25/12", "naklon": 10 }, + "3912": { "label": "25/13", "naklon": 10 }, + "3933": { "label": "25/14", "naklon": 10 }, + "3921": { "label": "25/15", "naklon": 10 }, + "4300": { "label": "25/16", "naklon": 10 }, + "3927": { "label": "25/17", "naklon": 10 }, + "3212": { "label": "25/18", "naklon": 10 }, + "3208": { "label": "25/19", "naklon": 10 }, + "3207": { "label": "25/20", "naklon": 10 }, + "4294": { "label": "25/21", "naklon": 10 }, + "3209": { "label": "25/22", "naklon": 10 }, + "3745": { "label": "25/23", "naklon": 10 }, + "3762": { "label": "25/24", "naklon": 10 }, + "3215": { "label": "25/25", "naklon": 10 }, + "3210": { "label": "25/26", "naklon": 10 }, + "3211": { "label": "25/27", "naklon": 10 }, + "3206": { "label": "25/28", "naklon": 10 }, + "3918": { "label": "25/29", "naklon": 5 }, + "3928": { "label": "25/30", "naklon": 5 }, + "3917": { "label": "25/31", "naklon": 5 }, + "4029": { "label": "25/32", "naklon": 0 }, + "4038": { "label": "25/33", "naklon": 0 }, + "4022": { "label": "25/34", "naklon": 0 }, + "3937": { "label": "25/35", "naklon": 0 }, + "3190": { "label": "25/36", "naklon": 0 }, + "3835": { "label": "25/37", "naklon": 0 }, + "3201": { "label": "25/38", "naklon": 0 }, + "3193": { "label": "25/39", "naklon": 0 }, + "3191": { "label": "25/40", "naklon": 0 }, + "3203": { "label": "25/41", "naklon": 0 }, + "4301": { "label": "25/42", "naklon": 0 }, + "3223": { "label": "25/43", "naklon": 0 }, + "3202": { "label": "25/44", "naklon": 0 }, + "3205": { "label": "25/45", "naklon": 0 }, + "3194": { "label": "25/46", "naklon": 0 }, + "3198": { "label": "25/47", "naklon": 0 }, + "3204": { "label": "25/48", "naklon": 0 }, + "3200": { "label": "25/49", "naklon": 0 }, + "3216": { "label": "25/50", "naklon": 0 }, + "3932": { "label": "25/51", "naklon": 5 }, + "3923": { "label": "25/52", "naklon": 5 }, + "3913": { "label": "25/53", "naklon": 5 }, + "3900": { "label": "25/54", "naklon": 5 }, + "4189": { "label": "25/55", "naklon": 10 }, + "4191": { "label": "25/56", "naklon": 10 }, + "3790": { "label": "25/57", "naklon": 10 }, + "4190": { "label": "25/58", "naklon": 10 }, + "4302": { "label": "25/59", "naklon": 0 }, + "4351": { "label": "25/60", "naklon": 0 }, + "4075": { "label": "25/61", "naklon": 0 }, + "4071": { "label": "25/62", "naklon": 0 }, + "3784": { "label": "25/63", "naklon": 0 }, + "4065": { "label": "25/64", "naklon": 0 }, + "4297": { "label": "25/65", "naklon": 0 }, + "4295": { "label": "25/66", "naklon": 0 }, + "4299": { "label": "25/67", "naklon": 0 }, + "3772": { "label": "25/68", "naklon": 0 }, + "3941": { "label": "25/69", "naklon": 0 }, + "3782": { "label": "25/70", "naklon": 0 }, + "4068": { "label": "25/71", "naklon": 0 }, + "4073": { "label": "25/72", "naklon": 0 }, + "3901": { "label": "25/73", "naklon": 5 }, + "4296": { "label": "25/74", "naklon": 5 }, + "3910": { "label": "25/75", "naklon": 5 }, + "4293": { "label": "25/76", "naklon": 5 }, + "3919": { "label": "25/77", "naklon": 5 }, + "3924": { "label": "25/78", "naklon": 5 }, + "3909": { "label": "25/79", "naklon": 5 }, + "3896": { "label": "25/80", "naklon": 5 }, + "3911": { "label": "25/81", "naklon": 5 }, + "2819": { "label": "25/82", "naklon": 15 }, + "3776": { "label": "25/83", "naklon": 15 }, + "3752": { "label": "25/84", "naklon": 15 }, + "4353": { "label": "25/85", "naklon": 15 }, + "3791": { "label": "25/86", "naklon": 0 }, + "3770": { "label": "25/87", "naklon": 0 }, + "3760": { "label": "25/88", "naklon": 0 }, + "3115": { "label": "25/89", "naklon": 0 }, + "3738": { "label": "25/90", "naklon": 0 }, + "3748": { "label": "25/91", "naklon": 0 }, + "3753": { "label": "25/92", "naklon": 0 }, + "3775": { "label": "25/93", "naklon": 0 }, + "3778": { "label": "25/94", "naklon": 5 }, + "4078": { "label": "25/95", "naklon": 5 }, + "4088": { "label": "25/96", "naklon": 5 }, + "3856": { "label": "25/97", "naklon": 5 }, + "4084": { "label": "25/98", "naklon": 5 }, + "4069": { "label": "25/99", "naklon": 5 }, + "4188": { "label": "25/100", "naklon": 5 }, + "4064": { "label": "25/101", "naklon": 5 }, + "3792": { "label": "25/102", "naklon": 5 }, + "3780": { "label": "25/103", "naklon": 5 }, + "4034": { "label": "25/104", "naklon": 5 }, + "4072": { "label": "25/105", "naklon": 5 }, + "3884": { "label": "25/106", "naklon": 5 }, + "3793": { "label": "25/107", "naklon": 5 }, + "3863": { "label": "25/108", "naklon": 5 }, + "3855": { "label": "25/109", "naklon": 5 }, + "3846": { "label": "33/1", "naklon": 0 }, + "3943": { "label": "33/2", "naklon": 0 }, + "3903": { "label": "33/3", "naklon": 0 }, + "3982": { "label": "33/4", "naklon": 0 }, + "3879": { "label": "33/5", "naklon": 0 }, + "3887": { "label": "33/6", "naklon": 0 }, + "3920": { "label": "33/7", "naklon": 5 }, + "3942": { "label": "33/8", "naklon": 5 }, + "3829": { "label": "33/9", "naklon": null }, + "3452": { "label": "34/79A", "naklon": 6 }, + "3460": { "label": "34/79B", "naklon": 6 }, + "3443": { "label": "34/90A", "naklon": 6 }, + "3445": { "label": "34/90B", "naklon": 6 }, + "3457": { "label": "34/90C", "naklon": 6 }, + "3461": { "label": "34/97A", "naklon": 6 }, + "3463": { "label": "34/97B", "naklon": 6 }, + "3426": { "label": "34/98A", "naklon": 6 }, + "3444": { "label": "34/98B", "naklon": 6 }, + "3453": { "label": "34/99A", "naklon": 6 }, + "3455": { "label": "34/99B", "naklon": 6 }, + "4009": { "label": "34/1", "naklon": 0 }, + "3602": { "label": "34/2", "naklon": 0 }, + "3441": { "label": "34/3", "naklon": 0 }, + "3464": { "label": "34/4", "naklon": 0 }, + "3883": { "label": "34/5", "naklon": 0 }, + "4098": { "label": "34/6", "naklon": 0 }, + "4003": { "label": "34/7", "naklon": 0 }, + "4004": { "label": "34/8", "naklon": 0 }, + "3888": { "label": "34/9", "naklon": 0 }, + "3997": { "label": "34/10", "naklon": 0 }, + "4006": { "label": "34/11", "naklon": 0 }, + "4000": { "label": "34/12", "naklon": 0 }, + "4011": { "label": "34/13", "naklon": 0 }, + "3999": { "label": "34/14", "naklon": 0 }, + "3981": { "label": "34/15", "naklon": 0 }, + "3988": { "label": "34/16", "naklon": 0 }, + "3986": { "label": "34/17", "naklon": 0 }, + "3998": { "label": "34/18", "naklon": 0 }, + "3983": { "label": "34/19", "naklon": 0 }, + "4005": { "label": "34/20", "naklon": 0 }, + "4001": { "label": "34/21", "naklon": 0 }, + "4008": { "label": "34/22", "naklon": 0 }, + "4002": { "label": "34/23", "naklon": 0 }, + "3996": { "label": "34/24", "naklon": 0 }, + "4007": { "label": "34/25", "naklon": 0 }, + "4113": { "label": "34/26", "naklon": 15 }, + "3595": { "label": "34/27", "naklon": 5 }, + "3599": { "label": "34/28", "naklon": 5 }, + "3601": { "label": "34/29", "naklon": 5 }, + "4205": { "label": "34/30", "naklon": 0 }, + "3987": { "label": "34/31", "naklon": null }, + "4214": { "label": "34/32", "naklon": 0 }, + "4226": { "label": "34/33", "naklon": 0 }, + "4209": { "label": "34/34", "naklon": 0 }, + "4201": { "label": "34/35", "naklon": 0 }, + "3440": { "label": "34/36", "naklon": 0 }, + "3465": { "label": "34/37", "naklon": 0 }, + "3446": { "label": "34/38", "naklon": 0 }, + "4039": { "label": "34/39", "naklon": 5 }, + "4057": { "label": "34/40", "naklon": 5 }, + "3985": { "label": "34/41", "naklon": 0 }, + "3882": { "label": "34/42", "naklon": 0 }, + "4040": { "label": "34/43", "naklon": 5 }, + "3231": { "label": "34/44", "naklon": 0 }, + "3227": { "label": "34/45", "naklon": 0 }, + "3431": { "label": "34/46", "naklon": 0 }, + "4013": { "label": "34/47", "naklon": 0 }, + "4045": { "label": "34/48", "naklon": 0 }, + "3949": { "label": "34/49", "naklon": 0 }, + "3953": { "label": "34/50", "naklon": 0 }, + "3952": { "label": "34/51", "naklon": 0 }, + "3995": { "label": "34/52", "naklon": 0 }, + "3992": { "label": "34/53", "naklon": 0 }, + "4198": { "label": "34/54", "naklon": 0 }, + "3935": { "label": "34/55", "naklon": 0 }, + "4050": { "label": "34/56", "naklon": 0 }, + "4049": { "label": "34/57", "naklon": 0 }, + "4054": { "label": "34/58", "naklon": 0 }, + "3663": { "label": "34/59", "naklon": 6 }, + "3661": { "label": "34/60", "naklon": 6 }, + "3664": { "label": "34/61", "naklon": 6 }, + "3660": { "label": "34/62", "naklon": 6 }, + "3662": { "label": "34/63", "naklon": 6 }, + "3665": { "label": "34/65", "naklon": 6 }, + "3667": { "label": "34/66", "naklon": 6 }, + "3675": { "label": "34/67", "naklon": 6 }, + "3666": { "label": "34/68", "naklon": 6 }, + "3652": { "label": "34/69", "naklon": 6 }, + "3458": { "label": "34/70", "naklon": 6 }, + "4425": { "label": "34/70/1", "naklon": 6 }, + "3459": { "label": "34/71", "naklon": 6 }, + "3435": { "label": "34/72", "naklon": 6 }, + "3448": { "label": "34/73", "naklon": 6 }, + "3451": { "label": "34/74", "naklon": 6 }, + "3442": { "label": "34/75", "naklon": 6 }, + "3449": { "label": "34/76", "naklon": 6 }, + "3450": { "label": "34/77", "naklon": 6 }, + "3433": { "label": "34/78", "naklon": 6 }, + "3432": { "label": "34/80", "naklon": 12 }, + "3470": { "label": "34/81", "naklon": 12 }, + "3438": { "label": "34/82", "naklon": 12 }, + "3439": { "label": "34/83", "naklon": 12 }, + "4028": { "label": "34/84", "naklon": 5 }, + "3596": { "label": "34/85", "naklon": 5 }, + "4021": { "label": "34/86", "naklon": 5 }, + "3437": { "label": "34/87", "naklon": 12 }, + "3428": { "label": "34/88", "naklon": 12 }, + "3430": { "label": "34/89", "naklon": 12 }, + "3454": { "label": "34/91", "naklon": 6 }, + "3492": { "label": "34/92", "naklon": 6 }, + "3462": { "label": "34/93", "naklon": 6 }, + "3427": { "label": "34/94", "naklon": 6 }, + "3434": { "label": "34/95", "naklon": 6 }, + "3456": { "label": "34/96", "naklon": 6 }, + "4307": { "label": "34/98/1", "naklon": 6 }, + "3968": { "label": "35/1", "naklon": 0 }, + "3969": { "label": "35/2", "naklon": 0 }, + "3947": { "label": "35/3", "naklon": 0 }, + "3979": { "label": "35/4", "naklon": 0 }, + "3959": { "label": "35/5", "naklon": 0 }, + "3948": { "label": "35/6", "naklon": 0 }, + "3961": { "label": "35/7", "naklon": 0 }, + "3956": { "label": "35/8", "naklon": 0 }, + "3604": { "label": "35/9", "naklon": 0 }, + "3944": { "label": "35/10", "naklon": 0 }, + "3960": { "label": "35/11", "naklon": 0 }, + "3958": { "label": "35/12", "naklon": 0 }, + "4036": { "label": "35/13", "naklon": 5 }, + "3893": { "label": "35/18", "naklon": 5 }, + "4108": { "label": "35/19", "naklon": 5 }, + "4017": { "label": "35/20", "naklon": 5 }, + "3963": { "label": "35/21", "naklon": 0 }, + "3658": { "label": "35/22", "naklon": 0 }, + "3975": { "label": "35/23", "naklon": 0 }, + "3980": { "label": "35/24", "naklon": 0 }, + "4012": { "label": "35/25", "naklon": 0 }, + "3655": { "label": "35/26", "naklon": 0 }, + "3962": { "label": "35/27", "naklon": 0 }, + "3945": { "label": "35/28", "naklon": 0 }, + "3569": { "label": "35/29", "naklon": 0 }, + "3429": { "label": "35/30", "naklon": 0 }, + "3657": { "label": "35/31", "naklon": 0 }, + "3646": { "label": "35/32", "naklon": 0 }, + "3622": { "label": "35/33", "naklon": 0 }, + "3612": { "label": "35/34", "naklon": 0 }, + "3955": { "label": "35/35", "naklon": 0 }, + "3878": { "label": "35/37", "naklon": 0 }, + "3965": { "label": "35/38", "naklon": 0 }, + "3970": { "label": "35/39", "naklon": 0 }, + "3611": { "label": "35/40", "naklon": 0 }, + "2635": { "label": "35/41", "naklon": 0 }, + "3978": { "label": "35/42", "naklon": 0 }, + "4213": { "label": "35/43", "naklon": 0 }, + "3984": { "label": "35/44", "naklon": 0 }, + "4218": { "label": "35/45", "naklon": 0 }, + "3973": { "label": "35/46", "naklon": 0 }, + "3974": { "label": "35/47", "naklon": 0 }, + "3759": { "label": "35/48", "naklon": 0 }, + "3844": { "label": "35/49", "naklon": 0 }, + "3804": { "label": "35/50", "naklon": 0 }, + "3831": { "label": "35/51", "naklon": 0 }, + "3643": { "label": "35/52", "naklon": 0 }, + "3966": { "label": "35/53", "naklon": 0 }, + "3971": { "label": "35/54", "naklon": 0 }, + "3650": { "label": "35/55", "naklon": 6 }, + "3651": { "label": "35/56", "naklon": 6 }, + "3669": { "label": "35/57", "naklon": 6 }, + "3648": { "label": "35/58", "naklon": 6 }, + "3645": { "label": "35/59", "naklon": 6 }, + "3659": { "label": "35/60", "naklon": 6 }, + "3647": { "label": "35/61", "naklon": 6 }, + "3644": { "label": "35/62", "naklon": 6 }, + "3671": { "label": "35/63", "naklon": 6 }, + "3682": { "label": "35/64", "naklon": 6 }, + "3672": { "label": "35/65", "naklon": 6 }, + "3683": { "label": "35/66", "naklon": 6 }, + "3673": { "label": "35/67", "naklon": 6 }, + "3674": { "label": "35/68", "naklon": 6 }, + "3679": { "label": "35/69", "naklon": 6 }, + "3649": { "label": "35/70", "naklon": 6 }, + "3687": { "label": "35/71", "naklon": 6 }, + "3677": { "label": "35/72", "naklon": 6 }, + "3690": { "label": "35/73", "naklon": 6 }, + "3691": { "label": "35/74", "naklon": 6 }, + "3676": { "label": "35/75", "naklon": 6 }, + "3680": { "label": "35/76", "naklon": 6 }, + "3668": { "label": "35/77", "naklon": 6 }, + "3681": { "label": "35/78", "naklon": 6 }, + "3670": { "label": "35/79", "naklon": 6 }, + "3689": { "label": "35/80", "naklon": 6 }, + "3678": { "label": "35/81", "naklon": 6 }, + "3693": { "label": "35/82", "naklon": 6 }, + "3654": { "label": "35/83", "naklon": null }, + "4086": { "label": "36/1", "naklon": 0 }, + "4085": { "label": "36/2", "naklon": 0 }, + "4083": { "label": "36/3", "naklon": 0 }, + "4087": { "label": "36/4", "naklon": 0 }, + "4077": { "label": "36/5", "naklon": 0 }, + "4082": { "label": "36/6", "naklon": 0 }, + "4186": { "label": "36/7", "naklon": 0 }, + "4206": { "label": "36/8", "naklon": 0 }, + "4080": { "label": "36/9", "naklon": 0 }, + "4081": { "label": "36/10", "naklon": 0 }, + "4210": { "label": "36/11", "naklon": 0 }, + "4079": { "label": "36/12", "naklon": 0 }, + "4076": { "label": "36/13", "naklon": 0 }, + "3852": { "label": "36/14", "naklon": 0 }, + "2813": { "label": "36/15", "naklon": 0 }, + "4219": { "label": "36/16", "naklon": 0 }, + "3104": { "label": "37/1A", "naklon": 15 }, + "3121": { "label": "37/1B", "naklon": 15 }, + "3113": { "label": "37/2", "naklon": 10 }, + "3118": { "label": "37/3", "naklon": 10 }, + "3111": { "label": "37/4", "naklon": 10 }, + "4020": { "label": "37/5", "naklon": 10 }, + "3119": { "label": "37/6", "naklon": 10 }, + "3110": { "label": "37/7", "naklon": 10 }, + "3108": { "label": "37/8", "naklon": 10 }, + "3107": { "label": "37/12", "naklon": 0 }, + "3199": { "label": "37/13", "naklon": 0 }, + "3120": { "label": "37/14", "naklon": 0 }, + "3122": { "label": "37/15", "naklon": 0 }, + "3908": { "label": "37/16", "naklon": 0 }, + "3114": { "label": "37/17", "naklon": 0 }, + "3105": { "label": "37/18", "naklon": 0 }, + "3116": { "label": "37/19", "naklon": 0 }, + "3106": { "label": "37/20", "naklon": 0 }, + "2887": { "label": "37/21", "naklon": 5 }, + "2888": { "label": "37/22", "naklon": 5 }, + "2877": { "label": "37/23", "naklon": 5 }, + "2891": { "label": "37/24", "naklon": 5 }, + "2886": { "label": "37/25", "naklon": 5 }, + "2892": { "label": "37/26", "naklon": 5 }, + "2882": { "label": "37/27", "naklon": 5 }, + "2883": { "label": "37/28", "naklon": 5 }, + "2876": { "label": "37/29", "naklon": 5 }, + "3109": { "label": "37/30", "naklon": 5 }, + "4152": { "label": "37/31", "naklon": 5 }, + "3117": { "label": "37/32", "naklon": 5 }, + "2870": { "label": "37/33", "naklon": 5 }, + "2867": { "label": "37/34", "naklon": 0 }, + "2865": { "label": "37/35", "naklon": 0 }, + "3096": { "label": "37/36", "naklon": 0 }, + "2871": { "label": "37/37", "naklon": 0 }, + "2884": { "label": "37/38", "naklon": 0 }, + "2855": { "label": "37/39", "naklon": 0 }, + "2878": { "label": "37/40", "naklon": 0 }, + "2889": { "label": "37/41", "naklon": 0 }, + "2879": { "label": "37/42", "naklon": 0 }, + "2850": { "label": "37/43", "naklon": 0 }, + "2894": { "label": "37/44", "naklon": 0 }, + "2880": { "label": "37/45", "naklon": 0 }, + "2893": { "label": "37/46", "naklon": 0 }, + "2890": { "label": "37/47", "naklon": 0 }, + "4355": { "label": "37/48", "naklon": 0 }, + "2885": { "label": "37/49", "naklon": 0 }, + "2875": { "label": "37/50", "naklon": 0 }, + "3486": { "label": "38/30A", "naklon": 5 }, + "3714": { "label": "38/30B", "naklon": 0 }, + "3483": { "label": "38/32A", "naklon": 5 }, + "3496": { "label": "38/32B", "naklon": 0 }, + "3487": { "label": "38/35A", "naklon": 5 }, + "3498": { "label": "38/35B", "naklon": 5 }, + "3578": { "label": "38/38A", "naklon": 5 }, + "3508": { "label": "38/38B", "naklon": 5 }, + "3787": { "label": "38/59A", "naklon": 5 }, + "3491": { "label": "38/59B", "naklon": 5 }, + "3568": { "label": "38/1", "naklon": null }, + "3502": { "label": "38/2", "naklon": 0 }, + "3836": { "label": "38/3", "naklon": 0 }, + "3588": { "label": "38/4", "naklon": 0 }, + "3493": { "label": "38/5", "naklon": 0 }, + "3580": { "label": "38/6", "naklon": 0 }, + "3572": { "label": "38/7", "naklon": 0 }, + "3506": { "label": "38/8", "naklon": 0 }, + "3503": { "label": "38/9", "naklon": 0 }, + "3579": { "label": "38/10", "naklon": 0 }, + "3586": { "label": "38/11", "naklon": 0 }, + "3495": { "label": "38/12", "naklon": 5 }, + "3492": { "label": "38/13", "naklon": 5 }, + "3532": { "label": "38/14", "naklon": 5 }, + "3574": { "label": "38/15", "naklon": 5 }, + "4140": { "label": "38/16", "naklon": 5 }, + "3795": { "label": "38/17", "naklon": 5 }, + "3788": { "label": "38/18", "naklon": 5 }, + "3796": { "label": "38/19", "naklon": 5 }, + "3797": { "label": "38/20", "naklon": 5 }, + "3798": { "label": "38/21", "naklon": 5 }, + "3786": { "label": "38/22", "naklon": 5 }, + "4067": { "label": "38/23", "naklon": 5 }, + "3773": { "label": "38/24", "naklon": 5 }, + "3774": { "label": "38/25", "naklon": 5 }, + "3789": { "label": "38/26", "naklon": 5 }, + "3520": { "label": "38/27", "naklon": null }, + "3577": { "label": "38/29", "naklon": 5 }, + "3530": { "label": "38/31", "naklon": null }, + "3488": { "label": "38/33", "naklon": 5 }, + "3505": { "label": "38/34", "naklon": 5 }, + "3497": { "label": "38/36", "naklon": 5 }, + "3490": { "label": "38/37", "naklon": 5 }, + "3585": { "label": "38/39", "naklon": 5 }, + "3582": { "label": "38/40", "naklon": 5 }, + "3507": { "label": "38/41", "naklon": 5 }, + "3484": { "label": "38/42", "naklon": 5 }, + "3501": { "label": "38/43", "naklon": 5 }, + "3581": { "label": "38/44", "naklon": 5 }, + "4192": { "label": "38/45", "naklon": 5 }, + "3576": { "label": "38/46", "naklon": 5 }, + "3489": { "label": "38/47", "naklon": 5 }, + "3573": { "label": "38/48", "naklon": 5 }, + "3504": { "label": "38/49", "naklon": 5 }, + "3794": { "label": "38/50", "naklon": 5 }, + "3485": { "label": "38/51", "naklon": 5 }, + "3482": { "label": "38/52", "naklon": 5 }, + "3575": { "label": "38/53", "naklon": 5 }, + "3499": { "label": "38/54", "naklon": 5 }, + "3494": { "label": "38/55", "naklon": 5 }, + "3583": { "label": "38/56", "naklon": 5 }, + "3570": { "label": "38/57", "naklon": 5 }, + "3500": { "label": "38/58", "naklon": 0 }, + "3510": { "label": "38/63", "naklon": null }, + "3512": { "label": "38/64", "naklon": null }, + "3535": { "label": "38/67", "naklon": null }, + "3531": { "label": "38/68", "naklon": null }, + "3537": { "label": "38/69", "naklon": null }, + "3522": { "label": "39/1", "naklon": 10 }, + "4018": { "label": "39/2", "naklon": 10 }, + "4019": { "label": "39/3", "naklon": 10 }, + "4154": { "label": "39/4", "naklon": 5 }, + "3907": { "label": "39/5", "naklon": 5 }, + "4148": { "label": "39/6", "naklon": 0 }, + "4153": { "label": "39/7", "naklon": 0 }, + "3938": { "label": "39/8", "naklon": 0 }, + "3802": { "label": "39/9", "naklon": 0 }, + "4015": { "label": "39/10", "naklon": 0 }, + "3929": { "label": "39/11", "naklon": 0 }, + "3946": { "label": "39/12", "naklon": 0 }, + "4014": { "label": "39/13", "naklon": 0 }, + "4155": { "label": "39/14", "naklon": 0 }, + "4149": { "label": "39/15", "naklon": 0 }, + "3642": { "label": "39/16", "naklon": 0 }, + "3636": { "label": "39/17", "naklon": 5 }, + "3991": { "label": "39/18", "naklon": 0 }, + "3994": { "label": "39/19", "naklon": 0 }, + "3990": { "label": "39/20", "naklon": 0 }, + "3967": { "label": "39/21", "naklon": 0 }, + "3977": { "label": "39/22", "naklon": 0 }, + "3757": { "label": "39/23", "naklon": 15 }, + "3633": { "label": "39/24", "naklon": 15 }, + "3744": { "label": "39/25", "naklon": 15 }, + "4023": { "label": "39/26", "naklon": 5 }, + "3720": { "label": "39/27", "naklon": 5 }, + "3734": { "label": "39/28", "naklon": 5 }, + "3741": { "label": "39/29", "naklon": 5 }, + "3721": { "label": "39/30", "naklon": 5 }, + "3845": { "label": "39/31", "naklon": 0 }, + "3840": { "label": "39/32", "naklon": 0 }, + "3837": { "label": "39/33", "naklon": null }, + "3839": { "label": "39/34", "naklon": 0 }, + "3542": { "label": "41/1", "naklon": null }, + "3566": { "label": "41/2", "naklon": null }, + "3548": { "label": "41/3", "naklon": null }, + "3515": { "label": "41/4", "naklon": null }, + "3559": { "label": "41/5", "naklon": null }, + "3509": { "label": "41/6", "naklon": null }, + "3524": { "label": "41/7", "naklon": null }, + "3518": { "label": "41/8", "naklon": null }, + "3182": { "label": "41/9", "naklon": null }, + "3187": { "label": "41/10", "naklon": null }, + "3195": { "label": "41/11", "naklon": 0 }, + "3857": { "label": "41/12", "naklon": 0 }, + "3183": { "label": "41/13", "naklon": 0 }, + "3177": { "label": "41/14", "naklon": 0 }, + "3189": { "label": "41/15", "naklon": 0 }, + "3186": { "label": "41/16", "naklon": 0 }, + "3178": { "label": "42/1", "naklon": 0 }, + "3219": { "label": "42/2", "naklon": 0 }, + "3475": { "label": "42/3", "naklon": 0 }, + "3175": { "label": "42/4", "naklon": 0 }, + "3222": { "label": "42/5", "naklon": 0 }, + "3221": { "label": "42/6", "naklon": 0 }, + "3181": { "label": "42/7", "naklon": 0 }, + "3180": { "label": "42/8", "naklon": 0 }, + "3218": { "label": "42/9", "naklon": 0 }, + "3176": { "label": "42/10", "naklon": 0 }, + "3174": { "label": "42/11", "naklon": 0 }, + "3220": { "label": "42/12", "naklon": 0 }, + "3533": { "label": "42/13", "naklon": null }, + "3543": { "label": "42/14", "naklon": null }, + "3554": { "label": "42/15", "naklon": null }, + "3549": { "label": "42/16", "naklon": null }, + "2857": { "label": "43/1", "naklon": 5 }, + "2752": { "label": "43/2", "naklon": 5 }, + "2753": { "label": "43/3", "naklon": 5 }, + "3024": { "label": "43/4", "naklon": 5 }, + "2754": { "label": "43/5", "naklon": 5 }, + "4423": { "label": "43/6", "naklon": 5 }, + "4368": { "label": "43/7", "naklon": 5 }, + "2978": { "label": "43/8", "naklon": 5 }, + "2868": { "label": "43/9", "naklon": 5 }, + "4377": { "label": "43/10", "naklon": 5 }, + "2757": { "label": "43/11", "naklon": 5 }, + "2970": { "label": "43/12", "naklon": 5 }, + "2758": { "label": "43/13", "naklon": 5 }, + "4378": { "label": "43/14", "naklon": 5 }, + "2759": { "label": "43/15", "naklon": 5 }, + "4342": { "label": "43/16", "naklon": 5 }, + "3026": { "label": "43/17", "naklon": null }, + "2986": { "label": "43/18", "naklon": null }, + "4343": { "label": "43/19", "naklon": null }, + "2760": { "label": "43/20", "naklon": null }, + "4379": { "label": "43/21", "naklon": null }, + "2971": { "label": "43/22", "naklon": null }, + "2761": { "label": "43/23", "naklon": null }, + "2762": { "label": "43/24", "naklon": null }, + "4339": { "label": "43/25", "naklon": null }, + "4380": { "label": "43/26", "naklon": null }, + "2975": { "label": "43/27", "naklon": null }, + "3003": { "label": "43/28", "naklon": null }, + "4338": { "label": "43/29", "naklon": null }, + "3002": { "label": "43/30", "naklon": null }, + "4345": { "label": "43/31", "naklon": null }, + "2979": { "label": "43/32", "naklon": null }, + "2989": { "label": "43/33", "naklon": null }, + "2996": { "label": "43/34", "naklon": null }, + "2972": { "label": "43/35", "naklon": null }, + "2988": { "label": "43/36", "naklon": null }, + "4344": { "label": "43/37", "naklon": null }, + "3022": { "label": "43/38", "naklon": null }, + "4341": { "label": "43/39", "naklon": null }, + "2983": { "label": "43/40", "naklon": null }, + "2995": { "label": "43/41", "naklon": null }, + "2763": { "label": "43/42", "naklon": null }, + "2764": { "label": "43/43", "naklon": null }, + "2765": { "label": "43/44", "naklon": null }, + "2766": { "label": "43/45", "naklon": null }, + "2767": { "label": "43/46", "naklon": null }, + "2768": { "label": "43/47", "naklon": null }, + "3018": { "label": "43/48", "naklon": null }, + "2982": { "label": "43/49", "naklon": null }, + "3019": { "label": "43/50", "naklon": 0 }, + "3013": { "label": "43/51", "naklon": null }, + "3007": { "label": "43/52", "naklon": null }, + "2980": { "label": "43/53", "naklon": null }, + "3011": { "label": "43/54", "naklon": null }, + "2672": { "label": "43/55", "naklon": null }, + "2673": { "label": "43/56", "naklon": null }, + "2674": { "label": "43/57", "naklon": null }, + "2675": { "label": "43/58", "naklon": null }, + "2676": { "label": "43/59", "naklon": null }, + "2677": { "label": "43/60", "naklon": null }, + "2678": { "label": "43/61", "naklon": null }, + "2679": { "label": "43/62", "naklon": null }, + "2680": { "label": "43/63", "naklon": null }, + "2840": { "label": "43/64", "naklon": null }, + "2682": { "label": "43/65", "naklon": null }, + "2683": { "label": "43/66", "naklon": null }, + "2684": { "label": "43/67", "naklon": 0 }, + "2685": { "label": "43/68", "naklon": null }, + "2686": { "label": "43/69", "naklon": null }, + "2687": { "label": "43/70", "naklon": null }, + "2688": { "label": "43/71", "naklon": null }, + "2689": { "label": "43/72", "naklon": null }, + "2690": { "label": "43/73", "naklon": null }, + "2691": { "label": "43/74", "naklon": null }, + "2692": { "label": "43/75", "naklon": null }, + "2693": { "label": "43/76", "naklon": 0 }, + "2694": { "label": "43/77", "naklon": null }, + "2695": { "label": "43/78", "naklon": null }, + "2696": { "label": "43/79", "naklon": 0 }, + "2697": { "label": "43/80", "naklon": null }, + "2698": { "label": "43/81", "naklon": 0 }, + "2699": { "label": "43/82", "naklon": null }, + "2700": { "label": "43/83", "naklon": 0 }, + "2744": { "label": "43/84", "naklon": null }, + "2745": { "label": "43/85", "naklon": 0 }, + "2746": { "label": "43/86", "naklon": null }, + "2747": { "label": "43/87", "naklon": 0 }, + "2748": { "label": "43/88", "naklon": null }, + "2749": { "label": "43/89", "naklon": 0 }, + "2841": { "label": "43/90", "naklon": null }, + "4237": { "label": "45/1", "naklon": 5 }, + "4226": { "label": "45/2", "naklon": 5 }, + "4242": { "label": "45/3", "naklon": 5 }, + "4179": { "label": "45/4", "naklon": 5 }, + "4247": { "label": "45/5", "naklon": 5 }, + "4245": { "label": "45/6", "naklon": 5 }, + "3872": { "label": "45/7", "naklon": 5 }, + "4175": { "label": "45/8", "naklon": 5 }, + "4236": { "label": "45/9", "naklon": 5 }, + "4170": { "label": "45/10", "naklon": 5 }, + "4238": { "label": "45/11", "naklon": 5 }, + "4246": { "label": "45/12", "naklon": 5 }, + "4166": { "label": "45/13", "naklon": 5 }, + "4227": { "label": "45/14", "naklon": 5 }, + "4171": { "label": "45/15", "naklon": 5 }, + "4180": { "label": "45/16", "naklon": 5 }, + "4244": { "label": "45/17", "naklon": 5 }, + "4199": { "label": "45/18", "naklon": 5 }, + "4239": { "label": "45/19", "naklon": 5 }, + "4207": { "label": "45/20", "naklon": 5 }, + "4223": { "label": "45/21", "naklon": 5 }, + "4230": { "label": "45/22", "naklon": 5 }, + "4233": { "label": "45/23", "naklon": 5 }, + "4222": { "label": "45/24", "naklon": 5 }, + "4217": { "label": "45/25", "naklon": 5 }, + "4243": { "label": "45/26", "naklon": 5 }, + "4200": { "label": "45/27", "naklon": 5 }, + "4228": { "label": "45/28", "naklon": 5 }, + "4211": { "label": "45/29", "naklon": 5 }, + "4234": { "label": "45/30", "naklon": 5 }, + "4235": { "label": "45/31", "naklon": 5 }, + "4203": { "label": "45/32", "naklon": 5 }, + "4240": { "label": "45/33", "naklon": 5 }, + "4224": { "label": "45/34", "naklon": 5 }, + "4232": { "label": "45/35", "naklon": 5 }, + "4231": { "label": "45/36", "naklon": 5 }, + "4161": { "label": "45/37", "naklon": 5 }, + "4225": { "label": "45/38", "naklon": 5 }, + "4241": { "label": "45/39", "naklon": 5 }, + "4229": { "label": "45/40", "naklon": 5 }, + "4221": { "label": "45/41", "naklon": 5 }, + "4212": { "label": "45/42", "naklon": 5 }, + "4216": { "label": "45/43", "naklon": 5 }, + "3864": { "label": "45/44", "naklon": null }, + "3806": { "label": "46/1", "naklon": 5 }, + "3813": { "label": "46/2", "naklon": 5 }, + "3815": { "label": "46/3", "naklon": 5 }, + "3807": { "label": "46/4", "naklon": 5 }, + "3895": { "label": "46/5", "naklon": 5 }, + "3809": { "label": "46/6", "naklon": 5 }, + "3820": { "label": "46/7", "naklon": 5 }, + "3805": { "label": "46/8", "naklon": 5 }, + "3894": { "label": "46/9", "naklon": 0 }, + "4055": { "label": "46/10", "naklon": 0 }, + "3812": { "label": "46/11", "naklon": 5 }, + "3822": { "label": "46/12", "naklon": 5 }, + "3821": { "label": "46/13", "naklon": 5 }, + "3808": { "label": "46/14", "naklon": 5 }, + "3799": { "label": "46/15", "naklon": 5 }, + "3816": { "label": "46/16", "naklon": 5 }, + "3751": { "label": "46/17", "naklon": 5 }, + "3814": { "label": "46/18", "naklon": 5 }, + "4044": { "label": "46/19", "naklon": 0 }, + "3931": { "label": "46/20", "naklon": 0 }, + "3902": { "label": "46/21", "naklon": 5 }, + "3916": { "label": "46/22", "naklon": 5 }, + "3892": { "label": "46/23", "naklon": 5 }, + "3914": { "label": "46/24", "naklon": 5 }, + "3898": { "label": "46/25", "naklon": 5 }, + "3897": { "label": "46/26", "naklon": 5 }, + "3885": { "label": "46/27", "naklon": 5 }, + "3906": { "label": "46/28", "naklon": 5 }, + "3930": { "label": "46/29", "naklon": 0 }, + "3936": { "label": "46/30", "naklon": 0 }, + "3860": { "label": "46/31", "naklon": 5 }, + "3841": { "label": "46/32", "naklon": 5 }, + "3873": { "label": "46/33", "naklon": 5 }, + "3854": { "label": "46/34", "naklon": 5 }, + "3939": { "label": "46/35", "naklon": 5 }, + "3858": { "label": "46/36", "naklon": 5 }, + "3940": { "label": "46/37", "naklon": 5 }, + "4035": { "label": "46/38", "naklon": 5 }, + "3373": { "label": "47/1", "naklon": 0 }, + "3374": { "label": "47/2", "naklon": 0 }, + "3384": { "label": "47/3", "naklon": 0 }, + "3385": { "label": "47/4", "naklon": 0 }, + "4051": { "label": "48/1", "naklon": 5 }, + "4041": { "label": "48/2", "naklon": 5 }, + "4056": { "label": "48/3", "naklon": 5 }, + "3875": { "label": "48/4", "naklon": 5 }, + "4061": { "label": "48/5", "naklon": 5 }, + "4047": { "label": "48/6", "naklon": 5 }, + "4060": { "label": "48/7", "naklon": 5 }, + "4059": { "label": "48/8", "naklon": 5 }, + "4058": { "label": "48/9", "naklon": 5 }, + "3635": { "label": "48/10", "naklon": 5 }, + "3640": { "label": "48/11", "naklon": 5 }, + "3747": { "label": "48/12", "naklon": 5 }, + "3629": { "label": "48/13", "naklon": 5 }, + "4048": { "label": "48/14", "naklon": 5 }, + "4063": { "label": "48/15", "naklon": 5 }, + "4062": { "label": "48/16", "naklon": 5 }, + "4043": { "label": "48/17", "naklon": 5 }, + "4052": { "label": "48/18", "naklon": 5 }, + "4042": { "label": "48/19", "naklon": 5 }, + "4053": { "label": "48/20", "naklon": 5 }, + "4167": { "label": "50/15A", "naklon": null }, + "4159": { "label": "50/15B", "naklon": null }, + "4183": { "label": "50/1", "naklon": 0 }, + "4157": { "label": "50/2", "naklon": 0 }, + "4160": { "label": "50/3", "naklon": 0 }, + "4173": { "label": "50/4", "naklon": 0 }, + "4177": { "label": "50/5", "naklon": 0 }, + "4174": { "label": "50/6", "naklon": 0 }, + "4178": { "label": "50/7", "naklon": 0 }, + "4195": { "label": "50/8", "naklon": 0 }, + "4169": { "label": "50/9", "naklon": 0 }, + "4162": { "label": "50/10", "naklon": 0 }, + "4158": { "label": "50/11", "naklon": 0 }, + "4182": { "label": "50/12", "naklon": 0 }, + "4194": { "label": "50/13", "naklon": 0 }, + "4184": { "label": "50/14", "naklon": 0 }, + "4197": { "label": "50/16", "naklon": null }, + "4164": { "label": "50/17", "naklon": null }, + "3306": { "label": "50/18", "naklon": null }, + "4168": { "label": "50/19", "naklon": null }, + "4193": { "label": "50/20", "naklon": null }, + "4187": { "label": "50/21", "naklon": null }, + "4163": { "label": "50/22", "naklon": null }, + "4165": { "label": "50/23", "naklon": null }, + "4185": { "label": "50/24", "naklon": null }, + "3904": { "label": "50/25", "naklon": null }, + "2619": { "label": "53/1", "naklon": 0 }, + "2623": { "label": "53/2", "naklon": 0 }, + "2617": { "label": "53/3", "naklon": 0 }, + "2622": { "label": "53/4", "naklon": 0 }, + "2618": { "label": "53/5", "naklon": 0 }, + "2626": { "label": "53/6", "naklon": 0 }, + "2869": { "label": "53/7", "naklon": 0 }, + "2613": { "label": "53/8", "naklon": 0 }, + "2608": { "label": "53/9", "naklon": 0 }, + "2611": { "label": "53/10", "naklon": 0 }, + "2598": { "label": "53/11", "naklon": 0 }, + "3528": { "label": "53/12", "naklon": 0 }, + "3545": { "label": "53/13", "naklon": 0 }, + "2620": { "label": "53/14", "naklon": 0 }, + "2612": { "label": "53/15", "naklon": 0 }, + "2615": { "label": "53/16", "naklon": 0 }, + "3722": { "label": "53/17", "naklon": 0 }, + "2624": { "label": "53/18", "naklon": 0 }, + "2609": { "label": "53/19", "naklon": 0 }, + "2625": { "label": "53/20", "naklon": 0 }, + "2602": { "label": "53/21", "naklon": 0 }, + "2610": { "label": "53/22", "naklon": 0 }, + "2599": { "label": "53/23", "naklon": 0 }, + "2605": { "label": "53/24", "naklon": 0 }, + "2593": { "label": "53/25", "naklon": 0 }, + "3074": { "label": "53/26", "naklon": 0 }, + "2740": { "label": "53/27", "naklon": 0 }, + "2614": { "label": "53/28", "naklon": 0 }, + "2601": { "label": "53/29", "naklon": 0 }, + "4196": { "label": "53/30", "naklon": 0 }, + "2607": { "label": "53/31", "naklon": 0 }, + "2582": { "label": "53/32", "naklon": 0 }, + "2594": { "label": "53/33", "naklon": 0 }, + "2589": { "label": "53/34", "naklon": 0 }, + "2596": { "label": "53/35", "naklon": 0 }, + "2603": { "label": "53/36", "naklon": 0 }, + "2597": { "label": "53/37", "naklon": 0 }, + "2590": { "label": "53/38", "naklon": 0 }, + "2581": { "label": "53/39", "naklon": 0 }, + "2583": { "label": "53/40", "naklon": 0 }, + "2580": { "label": "53/41", "naklon": 0 }, + "2579": { "label": "53/42", "naklon": 0 }, + "2797": { "label": "53/43", "naklon": 0 }, + "2577": { "label": "53/44", "naklon": 0 }, + "2586": { "label": "53/45", "naklon": 0 }, + "2588": { "label": "53/46", "naklon": 0 }, + "2591": { "label": "53/47", "naklon": 0 }, + "2592": { "label": "53/48", "naklon": 0 }, + "2573": { "label": "53/49", "naklon": 0 }, + "2595": { "label": "53/50", "naklon": 0 }, + "2587": { "label": "53/51", "naklon": 0 }, + "2578": { "label": "53/52", "naklon": 0 }, + "2574": { "label": "53/53", "naklon": 0 }, + "2571": { "label": "53/54", "naklon": 0 }, + "2570": { "label": "53/55", "naklon": 0 }, + "2576": { "label": "53/56", "naklon": 0 }, + "2881": { "label": "53/57", "naklon": 0 }, + "2575": { "label": "53/58", "naklon": 0 }, + "2572": { "label": "53/59", "naklon": 0 }, + "2569": { "label": "53/60", "naklon": 0 }, + "4324": { "label": "55/1", "naklon": 0 }, + "4319": { "label": "55/2", "naklon": 0 }, + "4327": { "label": "55/3", "naklon": 0 }, + "4333": { "label": "55/4", "naklon": 0 }, + "4332": { "label": "55/5", "naklon": 0 }, + "4320": { "label": "55/6", "naklon": 0 }, + "4317": { "label": "55/7", "naklon": 0 }, + "4318": { "label": "55/8", "naklon": 0 }, + "4328": { "label": "55/9", "naklon": 0 }, + "4323": { "label": "55/10", "naklon": 0 }, + "4325": { "label": "55/11", "naklon": 0 }, + "4326": { "label": "55/12", "naklon": 0 }, + "4316": { "label": "55/13", "naklon": 0 }, + "4322": { "label": "55/14", "naklon": 0 }, + "4331": { "label": "55/15", "naklon": 0 }, + "4321": { "label": "55/16", "naklon": 0 }, + "4315": { "label": "55/17", "naklon": 0 }, + "4329": { "label": "55/18", "naklon": 0 }, + "4334": { "label": "55/19", "naklon": 0 }, + "4330": { "label": "55/20", "naklon": 0 } +}; + + +let svetlaSorted = [{ "label": "1/3A", "node": 3993, "naklon": 0 }, +{ "label": "1/3B", "node": 3989, "naklon": 15 }, +{ "label": "1/1", "node": 3976, "naklon": 0 }, +{ "label": "1/2", "node": 4181, "naklon": 0 }, +{ "label": "1/4", "node": 4376, "naklon": 15 }, +{ "label": "1/5", "node": 3868, "naklon": 15 }, +{ "label": "1/6", "node": 3728, "naklon": 15 }, +{ "label": "1/7", "node": 3730, "naklon": 0 }, +{ "label": "1/8", "node": 4374, "naklon": 0 }, +{ "label": "1/9", "node": 3718, "naklon": 15 }, +{ "label": "1/10", "node": 4375, "naklon": 15 }, +{ "label": "1/11", "node": 4172, "naklon": 15 }, +{ "label": "1/12", "node": 4176, "naklon": 15 }, +{ "label": "2/1", "node": 3800, "naklon": 5 }, +{ "label": "2/2", "node": 3823, "naklon": 5 }, +{ "label": "2/3", "node": 3905, "naklon": 5 }, +{ "label": "2/4", "node": 3803, "naklon": 5 }, +{ "label": "2/5", "node": 3817, "naklon": 5 }, +{ "label": "2/6", "node": 3818, "naklon": 5 }, +{ "label": "2/7", "node": 3811, "naklon": 5 }, +{ "label": "2/8", "node": 3915, "naklon": 5 }, +{ "label": "2/9", "node": 3843, "naklon": 10 }, +{ "label": "2/10", "node": 3827, "naklon": 10 }, +{ "label": "2/11", "node": 4220, "naklon": 10 }, +{ "label": "2/12", "node": 3826, "naklon": 10 }, +{ "label": "2/13", "node": 3834, "naklon": 10 }, +{ "label": "2/14", "node": 3838, "naklon": 10 }, +{ "label": "2/15", "node": 2823, "naklon": 10 }, +{ "label": "2/16", "node": 3750, "naklon": 10 }, +{ "label": "2/17", "node": 3378, "naklon": 0 }, +{ "label": "2/18", "node": 3376, "naklon": 0 }, +{ "label": "2/19", "node": 3379, "naklon": 0 }, +{ "label": "2/20", "node": 3285, "naklon": 0 }, +{ "label": "2/21", "node": 3382, "naklon": 0 }, +{ "label": "2/22", "node": 3383, "naklon": 0 }, +{ "label": "2/24", "node": 3375, "naklon": 0 }, +{ "label": "2/25", "node": 3381, "naklon": 0 }, +{ "label": "2/26", "node": 3380, "naklon": 0 }, +{ "label": "2/27", "node": 3828, "naklon": 10 }, +{ "label": "2/28", "node": 3377, "naklon": 0 }, +{ "label": "7/1", "node": 3591, "naklon": 0 }, +{ "label": "7/2", "node": 3587, "naklon": 0 }, +{ "label": "7/3", "node": 3468, "naklon": 0 }, +{ "label": "7/4", "node": 3466, "naklon": 0 }, +{ "label": "7/5", "node": 3474, "naklon": 0 }, +{ "label": "7/6", "node": 3481, "naklon": 0 }, +{ "label": "7/7", "node": 3589, "naklon": 0 }, +{ "label": "7/8", "node": 3472, "naklon": 0 }, +{ "label": "7/9", "node": 3473, "naklon": 0 }, +{ "label": "7/10", "node": 3584, "naklon": 0 }, +{ "label": "7/11", "node": 3571, "naklon": 0 }, +{ "label": "7/12", "node": 3476, "naklon": 0 }, +{ "label": "7/13", "node": 3590, "naklon": 0 }, +{ "label": "7/14", "node": 3478, "naklon": 0 }, +{ "label": "7/15", "node": 3471, "naklon": 0 }, +{ "label": "7/16", "node": 3467, "naklon": 0 }, +{ "label": "7/17", "node": 3479, "naklon": 0 }, +{ "label": "7/18", "node": 3480, "naklon": 0 }, +{ "label": "7/19", "node": 3477, "naklon": 0 }, +{ "label": "12/1", "node": 3362, "naklon": 0 }, +{ "label": "12/2", "node": 3355, "naklon": 0 }, +{ "label": "12/3", "node": 3356, "naklon": 0 }, +{ "label": "12/4", "node": 3349, "naklon": 0 }, +{ "label": "12/5", "node": 3357, "naklon": 0 }, +{ "label": "12/6", "node": 3350, "naklon": 0 }, +{ "label": "12/7", "node": 3353, "naklon": 0 }, +{ "label": "12/8", "node": 3539, "naklon": 0 }, +{ "label": "12/9", "node": 3050, "naklon": 0 }, +{ "label": "12/10", "node": 3361, "naklon": 0 }, +{ "label": "12/11", "node": 3360, "naklon": 0 }, +{ "label": "12/12", "node": 3358, "naklon": 0 }, +{ "label": "12/13", "node": 3541, "naklon": 0 }, +{ "label": "12/14", "node": 3551, "naklon": 0 }, +{ "label": "12/15", "node": 3514, "naklon": 0 }, +{ "label": "12/16", "node": 3547, "naklon": 0 }, +{ "label": "12/17", "node": 3562, "naklon": 0 }, +{ "label": "12/18", "node": 3525, "naklon": 0 }, +{ "label": "12/19", "node": 3558, "naklon": 0 }, +{ "label": "12/20", "node": 3511, "naklon": 0 }, +{ "label": "12/21", "node": 3058, "naklon": 0 }, +{ "label": "12/22", "node": 3062, "naklon": 0 }, +{ "label": "12/23", "node": 3070, "naklon": 0 }, +{ "label": "12/24", "node": 3447, "naklon": 0 }, +{ "label": "12/25", "node": 3056, "naklon": 0 }, +{ "label": "12/26", "node": 3057, "naklon": 0 }, +{ "label": "12/27", "node": 3071, "naklon": 0 }, +{ "label": "12/28", "node": 3061, "naklon": 0 }, +{ "label": "12/29", "node": 3069, "naklon": 0 }, +{ "label": "12/30", "node": 3077, "naklon": 0 }, +{ "label": "12/31", "node": 3080, "naklon": 0 }, +{ "label": "12/32", "node": 3081, "naklon": 0 }, +{ "label": "12/33", "node": 3078, "naklon": 0 }, +{ "label": "12/34", "node": 4037, "naklon": 0 }, +{ "label": "12/35", "node": 3067, "naklon": 0 }, +{ "label": "12/36", "node": 3051, "naklon": 0 }, +{ "label": "12/37", "node": 2924, "naklon": 0 }, +{ "label": "12/38", "node": 3060, "naklon": 0 }, +{ "label": "12/39", "node": 3073, "naklon": 0 }, +{ "label": "12/40", "node": 3469, "naklon": 0 }, +{ "label": "12/41", "node": 2923, "naklon": 0 }, +{ "label": "12/42", "node": 2925, "naklon": 0 }, +{ "label": "12/43", "node": 3359, "naklon": 0 }, +{ "label": "12/44", "node": 3055, "naklon": 0 }, +{ "label": "12/45", "node": 2922, "naklon": 0 }, +{ "label": "12/46", "node": 3084, "naklon": 0 }, +{ "label": "12/47", "node": 3064, "naklon": 0 }, +{ "label": "12/48", "node": 3066, "naklon": 0 }, +{ "label": "12/49", "node": 3072, "naklon": 0 }, +{ "label": "13/13A", "node": 3415, "naklon": 0 }, +{ "label": "13/13B", "node": 3409, "naklon": 0 }, +{ "label": "13/13C", "node": 3399, "naklon": 0 }, +{ "label": "13/29A", "node": 3410, "naklon": 0 }, +{ "label": "13/29B", "node": 3407, "naklon": 0 }, +{ "label": "13/34A", "node": 3405, "naklon": 0 }, +{ "label": "13/34B", "node": 3404, "naklon": 0 }, +{ "label": "13/45A", "node": 3392, "naklon": 0 }, +{ "label": "13/45B", "node": 3386, "naklon": 0 }, +{ "label": "13/60A", "node": 3303, "naklon": 3 }, +{ "label": "13/60B", "node": 3302, "naklon": 3 }, +{ "label": "13/70A", "node": 3319, "naklon": 6 }, +{ "label": "13/70B", "node": 3317, "naklon": 6 }, +{ "label": "13/70C", "node": 3326, "naklon": 6 }, +{ "label": "13/73A", "node": 3351, "naklon": 6 }, +{ "label": "13/73B", "node": 3313, "naklon": 6 }, +{ "label": "13/83A", "node": 3316, "naklon": 0 }, +{ "label": "13/83B", "node": 3320, "naklon": 0 }, +{ "label": "13/95A", "node": 3336, "naklon": 0 }, +{ "label": "13/95B", "node": 3323, "naklon": 0 }, +{ "label": "13/98A", "node": 3339, "naklon": 0 }, +{ "label": "13/98B", "node": 3333, "naklon": 0 }, +{ "label": "13/1", "node": 3425, "naklon": 0 }, +{ "label": "13/2", "node": 3419, "naklon": 0 }, +{ "label": "13/3", "node": 3416, "naklon": 0 }, +{ "label": "13/4", "node": 3332, "naklon": 0 }, +{ "label": "13/5", "node": 3422, "naklon": 0 }, +{ "label": "13/6", "node": 3417, "naklon": 0 }, +{ "label": "13/7", "node": 3418, "naklon": 0 }, +{ "label": "13/8", "node": 3424, "naklon": 0 }, +{ "label": "13/9", "node": 3334, "naklon": 0 }, +{ "label": "13/10", "node": 4363, "naklon": 0 }, +{ "label": "13/11", "node": 3423, "naklon": 0 }, +{ "label": "13/12", "node": 3406, "naklon": 0 }, +{ "label": "13/14", "node": 3411, "naklon": 0 }, +{ "label": "13/15", "node": 3412, "naklon": 0 }, +{ "label": "13/16", "node": 3413, "naklon": 0 }, +{ "label": "13/17", "node": 3414, "naklon": 0 }, +{ "label": "13/18", "node": 3391, "naklon": 0 }, +{ "label": "13/19", "node": 3370, "naklon": 0 }, +{ "label": "13/20", "node": 3369, "naklon": 0 }, +{ "label": "13/21", "node": 3408, "naklon": 0 }, +{ "label": "13/22", "node": 3393, "naklon": 0 }, +{ "label": "13/23", "node": 3128, "naklon": 0 }, +{ "label": "13/24", "node": 3197, "naklon": 0 }, +{ "label": "13/25", "node": 4364, "naklon": 0 }, +{ "label": "13/26", "node": 3155, "naklon": 0 }, +{ "label": "13/27", "node": 3196, "naklon": 0 }, +{ "label": "13/28", "node": 3144, "naklon": 0 }, +{ "label": "13/30", "node": 3150, "naklon": 0 }, +{ "label": "13/31", "node": 3390, "naklon": 0 }, +{ "label": "13/32", "node": 3401, "naklon": 0 }, +{ "label": "13/33", "node": 3275, "naklon": 0 }, +{ "label": "13/35", "node": 3371, "naklon": 0 }, +{ "label": "13/36", "node": 3389, "naklon": 0 }, +{ "label": "13/37", "node": 3388, "naklon": 0 }, +{ "label": "13/38", "node": 3365, "naklon": 0 }, +{ "label": "13/39", "node": 3363, "naklon": 0 }, +{ "label": "13/40", "node": 3397, "naklon": 0 }, +{ "label": "13/40/1", "node": 3567, "naklon": 0 }, +{ "label": "13/41", "node": 3387, "naklon": 0 }, +{ "label": "13/42", "node": 3403, "naklon": 0 }, +{ "label": "13/43", "node": 3147, "naklon": 0 }, +{ "label": "13/44", "node": 3141, "naklon": 0 }, +{ "label": "13/46", "node": 3364, "naklon": 0 }, +{ "label": "13/47", "node": 3367, "naklon": 0 }, +{ "label": "13/48", "node": 3368, "naklon": 0 }, +{ "label": "13/49", "node": 3402, "naklon": 0 }, +{ "label": "13/50", "node": 3366, "naklon": 0 }, +{ "label": "13/51", "node": 3395, "naklon": 0 }, +{ "label": "13/52", "node": 3372, "naklon": 0 }, +{ "label": "13/53", "node": 3394, "naklon": 0 }, +{ "label": "13/54", "node": 3308, "naklon": 0 }, +{ "label": "13/54/1", "node": 3847, "naklon": 0 }, +{ "label": "13/55", "node": 3312, "naklon": 3 }, +{ "label": "13/56", "node": 3309, "naklon": 3 }, +{ "label": "13/57", "node": 3311, "naklon": 3 }, +{ "label": "13/58", "node": 3310, "naklon": 3 }, +{ "label": "13/59", "node": 4365, "naklon": 3 }, +{ "label": "13/60/1", "node": 4093, "naklon": 3 }, +{ "label": "13/61", "node": 3304, "naklon": 3 }, +{ "label": "13/62", "node": 3307, "naklon": 3 }, +{ "label": "13/63", "node": 3271, "naklon": 3 }, +{ "label": "13/64", "node": 3301, "naklon": 3 }, +{ "label": "13/65", "node": 4366, "naklon": 3 }, +{ "label": "13/66", "node": 3300, "naklon": 3 }, +{ "label": "13/67", "node": 3185, "naklon": 0 }, +{ "label": "13/68", "node": 3184, "naklon": 0 }, +{ "label": "13/69", "node": 3188, "naklon": 0 }, +{ "label": "13/71", "node": 3343, "naklon": 6 }, +{ "label": "13/71/1", "node": 3819, "naklon": 6 }, +{ "label": "13/71/2", "node": 3880, "naklon": 6 }, +{ "label": "13/72", "node": 3348, "naklon": 6 }, +{ "label": "13/74", "node": 3344, "naklon": 6 }, +{ "label": "13/75", "node": 3346, "naklon": 6 }, +{ "label": "13/75/1", "node": 3597, "naklon": 6 }, +{ "label": "13/76", "node": 3345, "naklon": 6 }, +{ "label": "13/77", "node": 3322, "naklon": 0 }, +{ "label": "13/78", "node": 3325, "naklon": 0 }, +{ "label": "13/78/1", "node": 4310, "naklon": 0 }, +{ "label": "13/79", "node": 3315, "naklon": 0 }, +{ "label": "13/80", "node": 3328, "naklon": 0 }, +{ "label": "13/81", "node": 3321, "naklon": 0 }, +{ "label": "13/82", "node": 3324, "naklon": 0 }, +{ "label": "13/84", "node": 3140, "naklon": 0 }, +{ "label": "13/85", "node": 3153, "naklon": 0 }, +{ "label": "13/86", "node": 3145, "naklon": 0 }, +{ "label": "13/87", "node": 3134, "naklon": 0 }, +{ "label": "13/88", "node": 3151, "naklon": 0 }, +{ "label": "13/89", "node": 3143, "naklon": 0 }, +{ "label": "13/90", "node": 3318, "naklon": 0 }, +{ "label": "13/91", "node": 3347, "naklon": 0 }, +{ "label": "13/94", "node": 3314, "naklon": 0 }, +{ "label": "13/96", "node": 3331, "naklon": 0 }, +{ "label": "13/97", "node": 3327, "naklon": 0 }, +{ "label": "13/99", "node": 3329, "naklon": 0 }, +{ "label": "13/100", "node": 3337, "naklon": 0 }, +{ "label": "13/101", "node": 3330, "naklon": 0 }, +{ "label": "13/102", "node": 3335, "naklon": 0 }, +{ "label": "13/103", "node": 3420, "naklon": 0 }, +{ "label": "13/104", "node": 3421, "naklon": 0 }, +{ "label": "13/105", "node": 4361, "naklon": 0 }, +{ "label": "13/106", "node": 4362, "naklon": 0 }, +{ "label": "13/107", "node": 3526, "naklon": 0 }, +{ "label": "13/108", "node": 4424, "naklon": null }, +{ "label": "13/109", "node": 3561, "naklon": null }, +{ "label": "13/110", "node": 3527, "naklon": null }, +{ "label": "13/111", "node": 3521, "naklon": null }, +{ "label": "13/112", "node": 3552, "naklon": null }, +{ "label": "13/113", "node": 3544, "naklon": null }, +{ "label": "13/114", "node": 3534, "naklon": null }, +{ "label": "13/115", "node": 3516, "naklon": null }, +{ "label": "13/116", "node": 3513, "naklon": null }, +{ "label": "13/117", "node": 3565, "naklon": null }, +{ "label": "13/118", "node": 3866, "naklon": null }, +{ "label": "14/1", "node": 3136, "naklon": 0 }, +{ "label": "14/2", "node": 3137, "naklon": 0 }, +{ "label": "14/3", "node": 3135, "naklon": 0 }, +{ "label": "14/4", "node": 3149, "naklon": 0 }, +{ "label": "14/5", "node": 3142, "naklon": 0 }, +{ "label": "14/6", "node": 3342, "naklon": 0 }, +{ "label": "14/7", "node": 3340, "naklon": 0 }, +{ "label": "14/8", "node": 3152, "naklon": 0 }, +{ "label": "14/9", "node": 3886, "naklon": 0 }, +{ "label": "14/10", "node": 3341, "naklon": null }, +{ "label": "14/11", "node": 3352, "naklon": null }, +{ "label": "15/1", "node": 3396, "naklon": 5 }, +{ "label": "15/2", "node": 2784, "naklon": 5 }, +{ "label": "15/3", "node": 2788, "naklon": 5 }, +{ "label": "15/4", "node": 2801, "naklon": 5 }, +{ "label": "15/5", "node": 2815, "naklon": 5 }, +{ "label": "15/6", "node": 2829, "naklon": 5 }, +{ "label": "15/7", "node": 2796, "naklon": 5 }, +{ "label": "15/8", "node": 2803, "naklon": 5 }, +{ "label": "15/8/1", "node": 4304, "naklon": 5 }, +{ "label": "15/8/2", "node": 4311, "naklon": 5 }, +{ "label": "15/9", "node": 2821, "naklon": 5 }, +{ "label": "15/10", "node": 3400, "naklon": 5 }, +{ "label": "15/11", "node": 2799, "naklon": 5 }, +{ "label": "15/12", "node": 2804, "naklon": 5 }, +{ "label": "15/12/1", "node": 4303, "naklon": 5 }, +{ "label": "15/12/2", "node": 4309, "naklon": 5 }, +{ "label": "15/13", "node": 2806, "naklon": 5 }, +{ "label": "15/14", "node": 2787, "naklon": 5 }, +{ "label": "15/15", "node": 2809, "naklon": 5 }, +{ "label": "15/16", "node": 2814, "naklon": 0 }, +{ "label": "15/17", "node": 3934, "naklon": 0 }, +{ "label": "15/18", "node": 3192, "naklon": 0 }, +{ "label": "15/19", "node": 2812, "naklon": 0 }, +{ "label": "15/20", "node": 4070, "naklon": 0 }, +{ "label": "15/21", "node": 2826, "naklon": 0 }, +{ "label": "15/22", "node": 2808, "naklon": 3 }, +{ "label": "15/23", "node": 2795, "naklon": 3 }, +{ "label": "15/24", "node": 2807, "naklon": 3 }, +{ "label": "15/25", "node": 2831, "naklon": 0 }, +{ "label": "15/26", "node": 2862, "naklon": null }, +{ "label": "15/27", "node": 2861, "naklon": 0 }, +{ "label": "15/28", "node": 2866, "naklon": 0 }, +{ "label": "15/28/1", "node": 3546, "naklon": 0 }, +{ "label": "15/29", "node": 4146, "naklon": 0 }, +{ "label": "15/29/1", "node": 3001, "naklon": 0 }, +{ "label": "15/30", "node": 2835, "naklon": 0 }, +{ "label": "15/31", "node": 2874, "naklon": 0 }, +{ "label": "15/32", "node": 2852, "naklon": 0 }, +{ "label": "15/33", "node": 2851, "naklon": 0 }, +{ "label": "15/33/1", "node": 3560, "naklon": 0 }, +{ "label": "15/34", "node": 2858, "naklon": 0 }, +{ "label": "15/34/1", "node": 4306, "naklon": 0 }, +{ "label": "15/35", "node": 2856, "naklon": 0 }, +{ "label": "15/36", "node": 2847, "naklon": 0 }, +{ "label": "15/36/1", "node": 3556, "naklon": 0 }, +{ "label": "15/37", "node": 3950, "naklon": 0 }, +{ "label": "15/38", "node": 2848, "naklon": 0 }, +{ "label": "15/39", "node": 2863, "naklon": 0 }, +{ "label": "15/39/1", "node": 4313, "naklon": 0 }, +{ "label": "15/40", "node": 2873, "naklon": 0 }, +{ "label": "15/40/1", "node": 2984, "naklon": 0 }, +{ "label": "15/41", "node": 2854, "naklon": 0 }, +{ "label": "15/42", "node": 2859, "naklon": 0 }, +{ "label": "15/43", "node": 2872, "naklon": 0 }, +{ "label": "15/44", "node": 2849, "naklon": 0 }, +{ "label": "15/45", "node": 2864, "naklon": 0 }, +{ "label": "15/46", "node": 3553, "naklon": null }, +{ "label": "15/47", "node": 3021, "naklon": null }, +{ "label": "15/47/1", "node": 3008, "naklon": null }, +{ "label": "15/48", "node": 3017, "naklon": null }, +{ "label": "15/49", "node": 3014, "naklon": null }, +{ "label": "15/50", "node": 2981, "naklon": null }, +{ "label": "15/51", "node": 3020, "naklon": null }, +{ "label": "15/52", "node": 3027, "naklon": null }, +{ "label": "15/53", "node": 3006, "naklon": null }, +{ "label": "15/54", "node": 3012, "naklon": null }, +{ "label": "15/55", "node": 2738, "naklon": 0 }, +{ "label": "15/56", "node": 2725, "naklon": 0 }, +{ "label": "15/57", "node": 3016, "naklon": null }, +{ "label": "15/58", "node": 3005, "naklon": null }, +{ "label": "15/58/1", "node": 3009, "naklon": null }, +{ "label": "15/59", "node": 3010, "naklon": 0 }, +{ "label": "15/59/1", "node": 3538, "naklon": 0 }, +{ "label": "15/59/2", "node": 4145, "naklon": 0 }, +{ "label": "15/60", "node": 2713, "naklon": 0 }, +{ "label": "15/61", "node": 2789, "naklon": 0 }, +{ "label": "15/62", "node": 2736, "naklon": 0 }, +{ "label": "15/63", "node": 2739, "naklon": 0 }, +{ "label": "15/64", "node": 4346, "naklon": 0 }, +{ "label": "15/65", "node": 2731, "naklon": 0 }, +{ "label": "15/66", "node": 2818, "naklon": 0 }, +{ "label": "15/66/1", "node": 3557, "naklon": 0 }, +{ "label": "15/67", "node": 2822, "naklon": 0 }, +{ "label": "15/68", "node": 2833, "naklon": 0 }, +{ "label": "15/69", "node": 2834, "naklon": 0 }, +{ "label": "15/70", "node": 3097, "naklon": 0 }, +{ "label": "15/71", "node": 2824, "naklon": 0 }, +{ "label": "15/72", "node": 2828, "naklon": 0 }, +{ "label": "15/73", "node": 2600, "naklon": 0 }, +{ "label": "15/73/1", "node": 4314, "naklon": 0 }, +{ "label": "15/74", "node": 2832, "naklon": 0 }, +{ "label": "15/75", "node": 4360, "naklon": 0 }, +{ "label": "15/76", "node": 2846, "naklon": 0 }, +{ "label": "15/77", "node": 2584, "naklon": 0 }, +{ "label": "15/78", "node": 2843, "naklon": 0 }, +{ "label": "15/78/1", "node": 4308, "naklon": 0 }, +{ "label": "15/79", "node": 4144, "naklon": null }, +{ "label": "15/80", "node": 2844, "naklon": 0 }, +{ "label": "15/81", "node": 2842, "naklon": 0 }, +{ "label": "15/82", "node": 2838, "naklon": 0 }, +{ "label": "15/83", "node": 2837, "naklon": null }, +{ "label": "15/83/1", "node": 3555, "naklon": null }, +{ "label": "15/84", "node": 2839, "naklon": 0 }, +{ "label": "15/85", "node": 2830, "naklon": 0 }, +{ "label": "15/86", "node": 4066, "naklon": 0 }, +{ "label": "15/87", "node": 2836, "naklon": 0 }, +{ "label": "15/88", "node": 2911, "naklon": 0 }, +{ "label": "15/89", "node": 2825, "naklon": 0 }, +{ "label": "15/90", "node": 2811, "naklon": 0 }, +{ "label": "15/94", "node": 3740, "naklon": 15 }, +{ "label": "15/95", "node": 2734, "naklon": 15 }, +{ "label": "15/96", "node": 3105, "naklon": 15 }, +{ "label": "15/97", "node": 2732, "naklon": 15 }, +{ "label": "15/98", "node": 2727, "naklon": 15 }, +{ "label": "15/99", "node": 2735, "naklon": 15 }, +{ "label": "15/100", "node": 3926, "naklon": 15 }, +{ "label": "15/101", "node": 2918, "naklon": 0 }, +{ "label": "15/102", "node": 2705, "naklon": 10 }, +{ "label": "15/103", "node": 2708, "naklon": 10 }, +{ "label": "15/104", "node": 2721, "naklon": 10 }, +{ "label": "15/105", "node": 2719, "naklon": 10 }, +{ "label": "15/106", "node": 2919, "naklon": 10 }, +{ "label": "15/107", "node": 3101, "naklon": 10 }, +{ "label": "15/108", "node": 2853, "naklon": 10 }, +{ "label": "15/109", "node": 2715, "naklon": 10 }, +{ "label": "15/110", "node": 2712, "naklon": 0 }, +{ "label": "15/111", "node": 2711, "naklon": 0 }, +{ "label": "15/112", "node": 2709, "naklon": 0 }, +{ "label": "15/113", "node": 2710, "naklon": 0 }, +{ "label": "15/114", "node": 2907, "naklon": 0 }, +{ "label": "15/115", "node": 2906, "naklon": 0 }, +{ "label": "15/116", "node": 2908, "naklon": 0 }, +{ "label": "15/117", "node": 2901, "naklon": 0 }, +{ "label": "15/118", "node": 2913, "naklon": 0 }, +{ "label": "15/119", "node": 3656, "naklon": 0 }, +{ "label": "15/120", "node": 2781, "naklon": 0 }, +{ "label": "15/121", "node": 2802, "naklon": 0 }, +{ "label": "15/122", "node": 2791, "naklon": 0 }, +{ "label": "15/123", "node": 2783, "naklon": 0 }, +{ "label": "15/124", "node": 2794, "naklon": 0 }, +{ "label": "15/125", "node": 3139, "naklon": 0 }, +{ "label": "15/126", "node": 3229, "naklon": 5 }, +{ "label": "15/127", "node": 3239, "naklon": 5 }, +{ "label": "15/128", "node": 3230, "naklon": 5 }, +{ "label": "15/129", "node": 4016, "naklon": null }, +{ "label": "16/16A", "node": 3608, "naklon": 0 }, +{ "label": "16/16B", "node": 4151, "naklon": 0 }, +{ "label": "16/1", "node": 3710, "naklon": 0 }, +{ "label": "16/2", "node": 3726, "naklon": 0 }, +{ "label": "16/3", "node": 3743, "naklon": 0 }, +{ "label": "16/4", "node": 3724, "naklon": 0 }, +{ "label": "16/5", "node": 3712, "naklon": 0 }, +{ "label": "16/6", "node": 3739, "naklon": 0 }, +{ "label": "16/7", "node": 3742, "naklon": 0 }, +{ "label": "16/8", "node": 3731, "naklon": 0 }, +{ "label": "16/9", "node": 3727, "naklon": 0 }, +{ "label": "16/10", "node": 3729, "naklon": 0 }, +{ "label": "16/11", "node": 3736, "naklon": 0 }, +{ "label": "16/12", "node": 3713, "naklon": 0 }, +{ "label": "16/13", "node": 3715, "naklon": 0 }, +{ "label": "16/14", "node": 3733, "naklon": 0 }, +{ "label": "16/15", "node": 3732, "naklon": 0 }, +{ "label": "16/17", "node": 3634, "naklon": 0 }, +{ "label": "16/18", "node": 3610, "naklon": 0 }, +{ "label": "16/19", "node": 3626, "naklon": 0 }, +{ "label": "16/20", "node": 3618, "naklon": 0 }, +{ "label": "16/21", "node": 3619, "naklon": 0 }, +{ "label": "16/22", "node": 3628, "naklon": 0 }, +{ "label": "16/23", "node": 3615, "naklon": 0 }, +{ "label": "16/24", "node": 3609, "naklon": 0 }, +{ "label": "16/25", "node": 3606, "naklon": 0 }, +{ "label": "16/26", "node": 3624, "naklon": 0 }, +{ "label": "16/27", "node": 3627, "naklon": 0 }, +{ "label": "16/28", "node": 3607, "naklon": 0 }, +{ "label": "16/29", "node": 4370, "naklon": 0 }, +{ "label": "16/30", "node": 3692, "naklon": 0 }, +{ "label": "16/31", "node": 3614, "naklon": 0 }, +{ "label": "16/32", "node": 3623, "naklon": 0 }, +{ "label": "16/33", "node": 4373, "naklon": 0 }, +{ "label": "16/34", "node": 3620, "naklon": 0 }, +{ "label": "16/35", "node": 3685, "naklon": 0 }, +{ "label": "16/36", "node": 3616, "naklon": 0 }, +{ "label": "16/37", "node": 3686, "naklon": 0 }, +{ "label": "16/38", "node": 3688, "naklon": 0 }, +{ "label": "16/39", "node": 3684, "naklon": 0 }, +{ "label": "16/40", "node": 3825, "naklon": 0 }, +{ "label": "16/41", "node": 3865, "naklon": 0 }, +{ "label": "16/42", "node": 3824, "naklon": 0 }, +{ "label": "16/43", "node": 3871, "naklon": 0 }, +{ "label": "16/44", "node": 3801, "naklon": 0 }, +{ "label": "16/45", "node": 3862, "naklon": 0 }, +{ "label": "16/46", "node": 3876, "naklon": 0 }, +{ "label": "16/47", "node": 3861, "naklon": 0 }, +{ "label": "16/48", "node": 4215, "naklon": 0 }, +{ "label": "16/49", "node": 3605, "naklon": 10 }, +{ "label": "16/50", "node": 3603, "naklon": 10 }, +{ "label": "16/51", "node": 3592, "naklon": 10 }, +{ "label": "16/52", "node": 3598, "naklon": 10 }, +{ "label": "16/53", "node": 3594, "naklon": 10 }, +{ "label": "16/54", "node": 3593, "naklon": 10 }, +{ "label": "16/55", "node": 3630, "naklon": 10 }, +{ "label": "16/56", "node": 3763, "naklon": 10 }, +{ "label": "16/57", "node": 3746, "naklon": 10 }, +{ "label": "16/58", "node": 3699, "naklon": 0 }, +{ "label": "16/59", "node": 3698, "naklon": 0 }, +{ "label": "16/60", "node": 3709, "naklon": null }, +{ "label": "16/61", "node": 3708, "naklon": 0 }, +{ "label": "16/62", "node": 3703, "naklon": null }, +{ "label": "16/63", "node": 3700, "naklon": 0 }, +{ "label": "16/64", "node": 3701, "naklon": null }, +{ "label": "16/65", "node": 3704, "naklon": 0 }, +{ "label": "16/66", "node": 3707, "naklon": null }, +{ "label": "16/67", "node": 3810, "naklon": 0 }, +{ "label": "16/68", "node": 4208, "naklon": null }, +{ "label": "16/69", "node": 3867, "naklon": 0 }, +{ "label": "16/70", "node": 4372, "naklon": null }, +{ "label": "16/71", "node": 3881, "naklon": 0 }, +{ "label": "16/72", "node": 4204, "naklon": null }, +{ "label": "16/73", "node": 3869, "naklon": 0 }, +{ "label": "16/74", "node": 4202, "naklon": null }, +{ "label": "16/75", "node": 3830, "naklon": 0 }, +{ "label": "16/76", "node": 3870, "naklon": null }, +{ "label": "16/77", "node": 3964, "naklon": 0 }, +{ "label": "16/78", "node": 3849, "naklon": 0 }, +{ "label": "16/79", "node": 3694, "naklon": null }, +{ "label": "16/80", "node": 3717, "naklon": 0 }, +{ "label": "16/81", "node": 3877, "naklon": null }, +{ "label": "16/82", "node": 3755, "naklon": 0 }, +{ "label": "16/83", "node": 3725, "naklon": null }, +{ "label": "16/84", "node": 3716, "naklon": 0 }, +{ "label": "16/85", "node": 3696, "naklon": null }, +{ "label": "16/86", "node": 3702, "naklon": 0 }, +{ "label": "16/87", "node": 3706, "naklon": null }, +{ "label": "16/88", "node": 3850, "naklon": 0 }, +{ "label": "16/89", "node": 3848, "naklon": null }, +{ "label": "16/90", "node": 3737, "naklon": null }, +{ "label": "16/91", "node": 3705, "naklon": 0 }, +{ "label": "16/92", "node": 3723, "naklon": null }, +{ "label": "16/93", "node": 3842, "naklon": 0 }, +{ "label": "16/94", "node": 3735, "naklon": null }, +{ "label": "16/95", "node": 3719, "naklon": 0 }, +{ "label": "16/96", "node": 3697, "naklon": 0 }, +{ "label": "16/97", "node": 3711, "naklon": 0 }, +{ "label": "16/98", "node": 4107, "naklon": null }, +{ "label": "16/99", "node": 4112, "naklon": 5 }, +{ "label": "16/100", "node": 4106, "naklon": 5 }, +{ "label": "16/101", "node": 4111, "naklon": 5 }, +{ "label": "16/102", "node": 4091, "naklon": null }, +{ "label": "16/103", "node": 4104, "naklon": 5 }, +{ "label": "16/104", "node": 4094, "naklon": null }, +{ "label": "16/105", "node": 4089, "naklon": 5 }, +{ "label": "16/106", "node": 4095, "naklon": null }, +{ "label": "16/107", "node": 4102, "naklon": 5 }, +{ "label": "16/108", "node": 4105, "naklon": null }, +{ "label": "16/109", "node": 3859, "naklon": null }, +{ "label": "16/110", "node": 4090, "naklon": 5 }, +{ "label": "16/111", "node": 4110, "naklon": null }, +{ "label": "16/112", "node": 4097, "naklon": 5 }, +{ "label": "16/113", "node": 4099, "naklon": null }, +{ "label": "16/114", "node": 4096, "naklon": null }, +{ "label": "16/115", "node": 4101, "naklon": 5 }, +{ "label": "16/116", "node": 4109, "naklon": null }, +{ "label": "16/117", "node": 4092, "naklon": 5 }, +{ "label": "16/118", "node": 3631, "naklon": null }, +{ "label": "16/119", "node": 3632, "naklon": 0 }, +{ "label": "16/120", "node": 3641, "naklon": null }, +{ "label": "16/121", "node": 3638, "naklon": 0 }, +{ "label": "16/122", "node": 3637, "naklon": null }, +{ "label": "16/123", "node": 4142, "naklon": null }, +{ "label": "16/124", "node": 4147, "naklon": 5 }, +{ "label": "16/125", "node": 4139, "naklon": 5 }, +{ "label": "20/30A", "node": 3172, "naklon": 2 }, +{ "label": "20/30B", "node": 3164, "naklon": 2 }, +{ "label": "20/1", "node": 3247, "naklon": 10 }, +{ "label": "20/2", "node": 3296, "naklon": 10 }, +{ "label": "20/3", "node": 3246, "naklon": 10 }, +{ "label": "20/4", "node": 3270, "naklon": 10 }, +{ "label": "20/5", "node": 3294, "naklon": 10 }, +{ "label": "20/6", "node": 3298, "naklon": 10 }, +{ "label": "20/7", "node": 3297, "naklon": 10 }, +{ "label": "20/8", "node": 3293, "naklon": 10 }, +{ "label": "20/9", "node": 3299, "naklon": 10 }, +{ "label": "20/10", "node": 3295, "naklon": 10 }, +{ "label": "20/11", "node": 3244, "naklon": 10 }, +{ "label": "20/12", "node": 3249, "naklon": 10 }, +{ "label": "20/13", "node": 3268, "naklon": 10 }, +{ "label": "20/14", "node": 3245, "naklon": 10 }, +{ "label": "20/15", "node": 3278, "naklon": 10 }, +{ "label": "20/16", "node": 3280, "naklon": 10 }, +{ "label": "20/17", "node": 3292, "naklon": 10 }, +{ "label": "20/18", "node": 3287, "naklon": 10 }, +{ "label": "20/19", "node": 3282, "naklon": 10 }, +{ "label": "20/20", "node": 3273, "naklon": 0 }, +{ "label": "20/21", "node": 3157, "naklon": 0 }, +{ "label": "20/22", "node": 3283, "naklon": 0 }, +{ "label": "20/23", "node": 3159, "naklon": 0 }, +{ "label": "20/24", "node": 3289, "naklon": 0 }, +{ "label": "20/25", "node": 3163, "naklon": 0 }, +{ "label": "20/26", "node": 3126, "naklon": 0 }, +{ "label": "20/27", "node": 3171, "naklon": 0 }, +{ "label": "20/28", "node": 3162, "naklon": 0 }, +{ "label": "20/29", "node": 3279, "naklon": 10 }, +{ "label": "20/31", "node": 3173, "naklon": 0 }, +{ "label": "20/32", "node": 3127, "naklon": 0 }, +{ "label": "20/33", "node": 3131, "naklon": 0 }, +{ "label": "20/34", "node": 3129, "naklon": 0 }, +{ "label": "20/35", "node": 3276, "naklon": 2 }, +{ "label": "20/36", "node": 3290, "naklon": 2 }, +{ "label": "20/37", "node": 3132, "naklon": 0 }, +{ "label": "20/38", "node": 3138, "naklon": 0 }, +{ "label": "20/39", "node": 3272, "naklon": 0 }, +{ "label": "20/40", "node": 3291, "naklon": 0 }, +{ "label": "20/41", "node": 3277, "naklon": 10 }, +{ "label": "20/42", "node": 3286, "naklon": 10 }, +{ "label": "20/43", "node": 3281, "naklon": 10 }, +{ "label": "20/44", "node": 3288, "naklon": 10 }, +{ "label": "20/45", "node": 3284, "naklon": 10 }, +{ "label": "20/46", "node": 3167, "naklon": 10 }, +{ "label": "20/47", "node": 3872, "naklon": 0 }, +{ "label": "20/48", "node": 3124, "naklon": 0 }, +{ "label": "20/49", "node": 3133, "naklon": 0 }, +{ "label": "20/50", "node": 3158, "naklon": 0 }, +{ "label": "20/51", "node": 3169, "naklon": 0 }, +{ "label": "20/52", "node": 3146, "naklon": 0 }, +{ "label": "20/53", "node": 3160, "naklon": 0 }, +{ "label": "20/54", "node": 3248, "naklon": 0 }, +{ "label": "20/55", "node": 3156, "naklon": 0 }, +{ "label": "20/56", "node": 3161, "naklon": 0 }, +{ "label": "20/57", "node": 3170, "naklon": 0 }, +{ "label": "20/58", "node": 3168, "naklon": 0 }, +{ "label": "20/59", "node": 3125, "naklon": 0 }, +{ "label": "20/60", "node": 3166, "naklon": 0 }, +{ "label": "20/61", "node": 3130, "naklon": 0 }, +{ "label": "20/62", "node": 3563, "naklon": 0 }, +{ "label": "20/63", "node": 3550, "naklon": null }, +{ "label": "20/67", "node": 3269, "naklon": 0 }, +{ "label": "21/1", "node": 2921, "naklon": 0 }, +{ "label": "21/2", "node": 2707, "naklon": 0 }, +{ "label": "21/3", "node": 2723, "naklon": 0 }, +{ "label": "21/4", "node": 2716, "naklon": 0 }, +{ "label": "21/5", "node": 2717, "naklon": 0 }, +{ "label": "21/6", "node": 2720, "naklon": 0 }, +{ "label": "21/7", "node": 2722, "naklon": 0 }, +{ "label": "21/8", "node": 2718, "naklon": 0 }, +{ "label": "21/9", "node": 2724, "naklon": 0 }, +{ "label": "21/10", "node": 2742, "naklon": 0 }, +{ "label": "21/11", "node": 2743, "naklon": 0 }, +{ "label": "21/12", "node": 2733, "naklon": 0 }, +{ "label": "21/14", "node": 2903, "naklon": 0 }, +{ "label": "21/15", "node": 2917, "naklon": 0 }, +{ "label": "21/16", "node": 2897, "naklon": 0 }, +{ "label": "21/17", "node": 2914, "naklon": 0 }, +{ "label": "21/18", "node": 2898, "naklon": 0 }, +{ "label": "21/19", "node": 2773, "naklon": 0 }, +{ "label": "21/20", "node": 2895, "naklon": 0 }, +{ "label": "21/21", "node": 2896, "naklon": 0 }, +{ "label": "21/22", "node": 2771, "naklon": 0 }, +{ "label": "21/23", "node": 2772, "naklon": 0 }, +{ "label": "21/24", "node": 2793, "naklon": 0 }, +{ "label": "21/25", "node": 2902, "naklon": 0 }, +{ "label": "21/26", "node": 2910, "naklon": 0 }, +{ "label": "21/27", "node": 2909, "naklon": 0 }, +{ "label": "21/28", "node": 2920, "naklon": 0 }, +{ "label": "21/29", "node": 2916, "naklon": 0 }, +{ "label": "21/30", "node": 2904, "naklon": 0 }, +{ "label": "21/31", "node": 2915, "naklon": 0 }, +{ "label": "21/32", "node": 2905, "naklon": 0 }, +{ "label": "21/33", "node": 2900, "naklon": 0 }, +{ "label": "21/34", "node": 2899, "naklon": 0 }, +{ "label": "21/36", "node": 2741, "naklon": 0 }, +{ "label": "21/37", "node": 2714, "naklon": 0 }, +{ "label": "21/38", "node": 2701, "naklon": 0 }, +{ "label": "21/39", "node": 2703, "naklon": 0 }, +{ "label": "21/40", "node": 2704, "naklon": 0 }, +{ "label": "21/41", "node": 2702, "naklon": 0 }, +{ "label": "21/42", "node": 2706, "naklon": 0 }, +{ "label": "21/43", "node": 2776, "naklon": 0 }, +{ "label": "21/44", "node": 2770, "naklon": 0 }, +{ "label": "21/45", "node": 2786, "naklon": 0 }, +{ "label": "21/46", "node": 2779, "naklon": 0 }, +{ "label": "21/47", "node": 2782, "naklon": 0 }, +{ "label": "21/48", "node": 2785, "naklon": 0 }, +{ "label": "21/49", "node": 2769, "naklon": 0 }, +{ "label": "21/50", "node": 3354, "naklon": 0 }, +{ "label": "21/51", "node": 2778, "naklon": 0 }, +{ "label": "21/52", "node": 2775, "naklon": 0 }, +{ "label": "21/53", "node": 2780, "naklon": 0 }, +{ "label": "21/54", "node": 2790, "naklon": 0 }, +{ "label": "21/55", "node": 2792, "naklon": 0 }, +{ "label": "21/56", "node": 2774, "naklon": 0 }, +{ "label": "22/1", "node": 2630, "naklon": 0 }, +{ "label": "22/2", "node": 2631, "naklon": 0 }, +{ "label": "22/3", "node": 2632, "naklon": 0 }, +{ "label": "22/4", "node": 2633, "naklon": 0 }, +{ "label": "22/5", "node": 2634, "naklon": 0 }, +{ "label": "22/6", "node": 2636, "naklon": 0 }, +{ "label": "22/7", "node": 4367, "naklon": 0 }, +{ "label": "22/8", "node": 2637, "naklon": 0 }, +{ "label": "22/9", "node": 2638, "naklon": 0 }, +{ "label": "22/10", "node": 2639, "naklon": 0 }, +{ "label": "22/11", "node": 2640, "naklon": 0 }, +{ "label": "22/12", "node": 2641, "naklon": 0 }, +{ "label": "22/13", "node": 2642, "naklon": 0 }, +{ "label": "22/14", "node": 2643, "naklon": 0 }, +{ "label": "22/15", "node": 2644, "naklon": 0 }, +{ "label": "22/16", "node": 2645, "naklon": 0 }, +{ "label": "22/17", "node": 2646, "naklon": 0 }, +{ "label": "22/18", "node": 2647, "naklon": 0 }, +{ "label": "22/19", "node": 2648, "naklon": 0 }, +{ "label": "22/20", "node": 2649, "naklon": 0 }, +{ "label": "22/21", "node": 2650, "naklon": 0 }, +{ "label": "22/22", "node": 2651, "naklon": 0 }, +{ "label": "22/23", "node": 4103, "naklon": 0 }, +{ "label": "22/24", "node": 2653, "naklon": 0 }, +{ "label": "22/25", "node": 2654, "naklon": 0 }, +{ "label": "22/26", "node": 2655, "naklon": 0 }, +{ "label": "22/27", "node": 2656, "naklon": 0 }, +{ "label": "22/28", "node": 2657, "naklon": 0 }, +{ "label": "22/29", "node": 2658, "naklon": 0 }, +{ "label": "22/30", "node": 2659, "naklon": 0 }, +{ "label": "22/31", "node": 2660, "naklon": 0 }, +{ "label": "22/32", "node": 2661, "naklon": 0 }, +{ "label": "22/32/1", "node": 3015, "naklon": 0 }, +{ "label": "22/33", "node": 2662, "naklon": 0 }, +{ "label": "22/34", "node": 2663, "naklon": 0 }, +{ "label": "22/35", "node": 2664, "naklon": 0 }, +{ "label": "22/36", "node": 2665, "naklon": 0 }, +{ "label": "22/37", "node": 2666, "naklon": 0 }, +{ "label": "22/38", "node": 2667, "naklon": 0 }, +{ "label": "22/39", "node": 2668, "naklon": 0 }, +{ "label": "22/40", "node": 2669, "naklon": null }, +{ "label": "22/41", "node": 2670, "naklon": null }, +{ "label": "22/42", "node": 2671, "naklon": null }, +{ "label": "23/9A", "node": 3087, "naklon": 10 }, +{ "label": "23/9B", "node": 3090, "naklon": 10 }, +{ "label": "23/1", "node": 3075, "naklon": 0 }, +{ "label": "23/2", "node": 3089, "naklon": 0 }, +{ "label": "23/3", "node": 3088, "naklon": 0 }, +{ "label": "23/4", "node": 3228, "naklon": 10 }, +{ "label": "23/5", "node": 2751, "naklon": 10 }, +{ "label": "23/6", "node": 3243, "naklon": 10 }, +{ "label": "23/7", "node": 4349, "naklon": 10 }, +{ "label": "23/8", "node": 3102, "naklon": 10 }, +{ "label": "23/10", "node": 3099, "naklon": 10 }, +{ "label": "23/11", "node": 3103, "naklon": 10 }, +{ "label": "23/12", "node": 3093, "naklon": 10 }, +{ "label": "23/13", "node": 3098, "naklon": 10 }, +{ "label": "23/14", "node": 3092, "naklon": 10 }, +{ "label": "23/15", "node": 3233, "naklon": 0 }, +{ "label": "23/16", "node": 3095, "naklon": 0 }, +{ "label": "23/17", "node": 4074, "naklon": 0 }, +{ "label": "23/18", "node": 2729, "naklon": 0 }, +{ "label": "23/19", "node": 3234, "naklon": 0 }, +{ "label": "23/20", "node": 3094, "naklon": 0 }, +{ "label": "23/21", "node": 2817, "naklon": 0 }, +{ "label": "23/22", "node": 3226, "naklon": 0 }, +{ "label": "23/23", "node": 3225, "naklon": 0 }, +{ "label": "23/24", "node": 3237, "naklon": 0 }, +{ "label": "23/25", "node": 4250, "naklon": 0 }, +{ "label": "23/26", "node": 3059, "naklon": 10 }, +{ "label": "23/27", "node": 3238, "naklon": 10 }, +{ "label": "23/28", "node": 3242, "naklon": 10 }, +{ "label": "23/29", "node": 3236, "naklon": 10 }, +{ "label": "23/30", "node": 3112, "naklon": 10 }, +{ "label": "23/31", "node": 3224, "naklon": 0 }, +{ "label": "23/32", "node": 4298, "naklon": 10 }, +{ "label": "23/33", "node": 4150, "naklon": 10 }, +{ "label": "23/34", "node": 3091, "naklon": 10 }, +{ "label": "25/1", "node": 3771, "naklon": 5 }, +{ "label": "25/2", "node": 3777, "naklon": 5 }, +{ "label": "25/3", "node": 3749, "naklon": 5 }, +{ "label": "25/4", "node": 3769, "naklon": 5 }, +{ "label": "25/5", "node": 3765, "naklon": 5 }, +{ "label": "25/6", "node": 3785, "naklon": 5 }, +{ "label": "25/7", "node": 3761, "naklon": 5 }, +{ "label": "25/8", "node": 3758, "naklon": 5 }, +{ "label": "25/9", "node": 3766, "naklon": 5 }, +{ "label": "25/10", "node": 3779, "naklon": 5 }, +{ "label": "25/11", "node": 3899, "naklon": 10 }, +{ "label": "25/12", "node": 3922, "naklon": 10 }, +{ "label": "25/13", "node": 3912, "naklon": 10 }, +{ "label": "25/14", "node": 3933, "naklon": 10 }, +{ "label": "25/15", "node": 3921, "naklon": 10 }, +{ "label": "25/16", "node": 4300, "naklon": 10 }, +{ "label": "25/17", "node": 3927, "naklon": 10 }, +{ "label": "25/18", "node": 3212, "naklon": 10 }, +{ "label": "25/19", "node": 3208, "naklon": 10 }, +{ "label": "25/20", "node": 3207, "naklon": 10 }, +{ "label": "25/21", "node": 4294, "naklon": 10 }, +{ "label": "25/22", "node": 3209, "naklon": 10 }, +{ "label": "25/23", "node": 3745, "naklon": 10 }, +{ "label": "25/24", "node": 3762, "naklon": 10 }, +{ "label": "25/25", "node": 3215, "naklon": 10 }, +{ "label": "25/26", "node": 3210, "naklon": 10 }, +{ "label": "25/27", "node": 3211, "naklon": 10 }, +{ "label": "25/28", "node": 3206, "naklon": 10 }, +{ "label": "25/29", "node": 3918, "naklon": 5 }, +{ "label": "25/30", "node": 3928, "naklon": 5 }, +{ "label": "25/31", "node": 3917, "naklon": 5 }, +{ "label": "25/32", "node": 4029, "naklon": 0 }, +{ "label": "25/33", "node": 4038, "naklon": 0 }, +{ "label": "25/34", "node": 4022, "naklon": 0 }, +{ "label": "25/35", "node": 3937, "naklon": 0 }, +{ "label": "25/36", "node": 3190, "naklon": 0 }, +{ "label": "25/37", "node": 3835, "naklon": 0 }, +{ "label": "25/38", "node": 3201, "naklon": 0 }, +{ "label": "25/39", "node": 3193, "naklon": 0 }, +{ "label": "25/40", "node": 3191, "naklon": 0 }, +{ "label": "25/41", "node": 3203, "naklon": 0 }, +{ "label": "25/42", "node": 4301, "naklon": 0 }, +{ "label": "25/43", "node": 3223, "naklon": 0 }, +{ "label": "25/44", "node": 3202, "naklon": 0 }, +{ "label": "25/45", "node": 3205, "naklon": 0 }, +{ "label": "25/46", "node": 3194, "naklon": 0 }, +{ "label": "25/47", "node": 3198, "naklon": 0 }, +{ "label": "25/48", "node": 3204, "naklon": 0 }, +{ "label": "25/49", "node": 3200, "naklon": 0 }, +{ "label": "25/50", "node": 3216, "naklon": 0 }, +{ "label": "25/51", "node": 3932, "naklon": 5 }, +{ "label": "25/52", "node": 3923, "naklon": 5 }, +{ "label": "25/53", "node": 3913, "naklon": 5 }, +{ "label": "25/54", "node": 3900, "naklon": 5 }, +{ "label": "25/55", "node": 4189, "naklon": 10 }, +{ "label": "25/56", "node": 4191, "naklon": 10 }, +{ "label": "25/57", "node": 3790, "naklon": 10 }, +{ "label": "25/58", "node": 4190, "naklon": 10 }, +{ "label": "25/59", "node": 4302, "naklon": 0 }, +{ "label": "25/60", "node": 4351, "naklon": 0 }, +{ "label": "25/61", "node": 4075, "naklon": 0 }, +{ "label": "25/62", "node": 4071, "naklon": 0 }, +{ "label": "25/63", "node": 3784, "naklon": 0 }, +{ "label": "25/64", "node": 4065, "naklon": 0 }, +{ "label": "25/65", "node": 4297, "naklon": 0 }, +{ "label": "25/66", "node": 4295, "naklon": 0 }, +{ "label": "25/67", "node": 4299, "naklon": 0 }, +{ "label": "25/68", "node": 3772, "naklon": 0 }, +{ "label": "25/69", "node": 3941, "naklon": 0 }, +{ "label": "25/70", "node": 3782, "naklon": 0 }, +{ "label": "25/71", "node": 4068, "naklon": 0 }, +{ "label": "25/72", "node": 4073, "naklon": 0 }, +{ "label": "25/73", "node": 3901, "naklon": 5 }, +{ "label": "25/74", "node": 4296, "naklon": 5 }, +{ "label": "25/75", "node": 3910, "naklon": 5 }, +{ "label": "25/76", "node": 4293, "naklon": 5 }, +{ "label": "25/77", "node": 3919, "naklon": 5 }, +{ "label": "25/78", "node": 3924, "naklon": 5 }, +{ "label": "25/79", "node": 3909, "naklon": 5 }, +{ "label": "25/80", "node": 3896, "naklon": 5 }, +{ "label": "25/81", "node": 3911, "naklon": 5 }, +{ "label": "25/82", "node": 2819, "naklon": 15 }, +{ "label": "25/83", "node": 3776, "naklon": 15 }, +{ "label": "25/84", "node": 3752, "naklon": 15 }, +{ "label": "25/85", "node": 4353, "naklon": 15 }, +{ "label": "25/86", "node": 3791, "naklon": 0 }, +{ "label": "25/87", "node": 3770, "naklon": 0 }, +{ "label": "25/88", "node": 3760, "naklon": 0 }, +{ "label": "25/89", "node": 3115, "naklon": 0 }, +{ "label": "25/90", "node": 3738, "naklon": 0 }, +{ "label": "25/91", "node": 3748, "naklon": 0 }, +{ "label": "25/92", "node": 3753, "naklon": 0 }, +{ "label": "25/93", "node": 3775, "naklon": 0 }, +{ "label": "25/94", "node": 3778, "naklon": 5 }, +{ "label": "25/95", "node": 4078, "naklon": 5 }, +{ "label": "25/96", "node": 4088, "naklon": 5 }, +{ "label": "25/97", "node": 3856, "naklon": 5 }, +{ "label": "25/98", "node": 4084, "naklon": 5 }, +{ "label": "25/99", "node": 4069, "naklon": 5 }, +{ "label": "25/100", "node": 4188, "naklon": 5 }, +{ "label": "25/101", "node": 4064, "naklon": 5 }, +{ "label": "25/102", "node": 3792, "naklon": 5 }, +{ "label": "25/103", "node": 3780, "naklon": 5 }, +{ "label": "25/104", "node": 4034, "naklon": 5 }, +{ "label": "25/105", "node": 4072, "naklon": 5 }, +{ "label": "25/106", "node": 3884, "naklon": 5 }, +{ "label": "25/107", "node": 3793, "naklon": 5 }, +{ "label": "25/108", "node": 3863, "naklon": 5 }, +{ "label": "25/109", "node": 3855, "naklon": 5 }, +{ "label": "33/1", "node": 3846, "naklon": 0 }, +{ "label": "33/2", "node": 3943, "naklon": 0 }, +{ "label": "33/3", "node": 3903, "naklon": 0 }, +{ "label": "33/4", "node": 3982, "naklon": 0 }, +{ "label": "33/5", "node": 3879, "naklon": 0 }, +{ "label": "33/6", "node": 3887, "naklon": 0 }, +{ "label": "33/7", "node": 3920, "naklon": 5 }, +{ "label": "33/8", "node": 3942, "naklon": 5 }, +{ "label": "33/9", "node": 3829, "naklon": null }, +{ "label": "34/79A", "node": 3452, "naklon": 6 }, +{ "label": "34/79B", "node": 3460, "naklon": 6 }, +{ "label": "34/90A", "node": 3443, "naklon": 6 }, +{ "label": "34/90B", "node": 3445, "naklon": 6 }, +{ "label": "34/90C", "node": 3457, "naklon": 6 }, +{ "label": "34/97A", "node": 3461, "naklon": 6 }, +{ "label": "34/97B", "node": 3463, "naklon": 6 }, +{ "label": "34/98A", "node": 3426, "naklon": 6 }, +{ "label": "34/98B", "node": 3444, "naklon": 6 }, +{ "label": "34/99A", "node": 3453, "naklon": 6 }, +{ "label": "34/99B", "node": 3455, "naklon": 6 }, +{ "label": "34/1", "node": 4009, "naklon": 0 }, +{ "label": "34/2", "node": 3602, "naklon": 0 }, +{ "label": "34/3", "node": 3441, "naklon": 0 }, +{ "label": "34/4", "node": 3464, "naklon": 0 }, +{ "label": "34/5", "node": 3883, "naklon": 0 }, +{ "label": "34/6", "node": 4098, "naklon": 0 }, +{ "label": "34/7", "node": 4003, "naklon": 0 }, +{ "label": "34/8", "node": 4004, "naklon": 0 }, +{ "label": "34/9", "node": 3888, "naklon": 0 }, +{ "label": "34/10", "node": 3997, "naklon": 0 }, +{ "label": "34/11", "node": 4006, "naklon": 0 }, +{ "label": "34/12", "node": 4000, "naklon": 0 }, +{ "label": "34/13", "node": 4011, "naklon": 0 }, +{ "label": "34/14", "node": 3999, "naklon": 0 }, +{ "label": "34/15", "node": 3981, "naklon": 0 }, +{ "label": "34/16", "node": 3988, "naklon": 0 }, +{ "label": "34/17", "node": 3986, "naklon": 0 }, +{ "label": "34/18", "node": 3998, "naklon": 0 }, +{ "label": "34/19", "node": 3983, "naklon": 0 }, +{ "label": "34/20", "node": 4005, "naklon": 0 }, +{ "label": "34/21", "node": 4001, "naklon": 0 }, +{ "label": "34/22", "node": 4008, "naklon": 0 }, +{ "label": "34/23", "node": 4002, "naklon": 0 }, +{ "label": "34/24", "node": 3996, "naklon": 0 }, +{ "label": "34/25", "node": 4007, "naklon": 0 }, +{ "label": "34/26", "node": 4113, "naklon": 15 }, +{ "label": "34/27", "node": 3595, "naklon": 5 }, +{ "label": "34/28", "node": 3599, "naklon": 5 }, +{ "label": "34/29", "node": 3601, "naklon": 5 }, +{ "label": "34/30", "node": 4205, "naklon": 0 }, +{ "label": "34/31", "node": 3987, "naklon": null }, +{ "label": "34/32", "node": 4214, "naklon": 0 }, +{ "label": "34/33", "node": 4226, "naklon": 0 }, +{ "label": "34/34", "node": 4209, "naklon": 0 }, +{ "label": "34/35", "node": 4201, "naklon": 0 }, +{ "label": "34/36", "node": 3440, "naklon": 0 }, +{ "label": "34/37", "node": 3465, "naklon": 0 }, +{ "label": "34/38", "node": 3446, "naklon": 0 }, +{ "label": "34/39", "node": 4039, "naklon": 5 }, +{ "label": "34/40", "node": 4057, "naklon": 5 }, +{ "label": "34/41", "node": 3985, "naklon": 0 }, +{ "label": "34/42", "node": 3882, "naklon": 0 }, +{ "label": "34/43", "node": 4040, "naklon": 5 }, +{ "label": "34/44", "node": 3231, "naklon": 0 }, +{ "label": "34/45", "node": 3227, "naklon": 0 }, +{ "label": "34/46", "node": 3431, "naklon": 0 }, +{ "label": "34/47", "node": 4013, "naklon": 0 }, +{ "label": "34/48", "node": 4045, "naklon": 0 }, +{ "label": "34/49", "node": 3949, "naklon": 0 }, +{ "label": "34/50", "node": 3953, "naklon": 0 }, +{ "label": "34/51", "node": 3952, "naklon": 0 }, +{ "label": "34/52", "node": 3995, "naklon": 0 }, +{ "label": "34/53", "node": 3992, "naklon": 0 }, +{ "label": "34/54", "node": 4198, "naklon": 0 }, +{ "label": "34/55", "node": 3935, "naklon": 0 }, +{ "label": "34/56", "node": 4050, "naklon": 0 }, +{ "label": "34/57", "node": 4049, "naklon": 0 }, +{ "label": "34/58", "node": 4054, "naklon": 0 }, +{ "label": "34/59", "node": 3663, "naklon": 6 }, +{ "label": "34/60", "node": 3661, "naklon": 6 }, +{ "label": "34/61", "node": 3664, "naklon": 6 }, +{ "label": "34/62", "node": 3660, "naklon": 6 }, +{ "label": "34/63", "node": 3662, "naklon": 6 }, +{ "label": "34/65", "node": 3665, "naklon": 6 }, +{ "label": "34/66", "node": 3667, "naklon": 6 }, +{ "label": "34/67", "node": 3675, "naklon": 6 }, +{ "label": "34/68", "node": 3666, "naklon": 6 }, +{ "label": "34/69", "node": 3652, "naklon": 6 }, +{ "label": "34/70", "node": 3458, "naklon": 6 }, +{ "label": "34/70/1", "node": 4425, "naklon": 6 }, +{ "label": "34/71", "node": 3459, "naklon": 6 }, +{ "label": "34/72", "node": 3435, "naklon": 6 }, +{ "label": "34/73", "node": 3448, "naklon": 6 }, +{ "label": "34/74", "node": 3451, "naklon": 6 }, +{ "label": "34/75", "node": 3442, "naklon": 6 }, +{ "label": "34/76", "node": 3449, "naklon": 6 }, +{ "label": "34/77", "node": 3450, "naklon": 6 }, +{ "label": "34/78", "node": 3433, "naklon": 6 }, +{ "label": "34/80", "node": 3432, "naklon": 12 }, +{ "label": "34/81", "node": 3470, "naklon": 12 }, +{ "label": "34/82", "node": 3438, "naklon": 12 }, +{ "label": "34/83", "node": 3439, "naklon": 12 }, +{ "label": "34/84", "node": 4028, "naklon": 5 }, +{ "label": "34/85", "node": 3596, "naklon": 5 }, +{ "label": "34/86", "node": 4021, "naklon": 5 }, +{ "label": "34/87", "node": 3437, "naklon": 12 }, +{ "label": "34/88", "node": 3428, "naklon": 12 }, +{ "label": "34/89", "node": 3430, "naklon": 12 }, +{ "label": "34/91", "node": 3454, "naklon": 6 }, +{ "label": "34/92", "node": 3492, "naklon": 6 }, +{ "label": "34/93", "node": 3462, "naklon": 6 }, +{ "label": "34/94", "node": 3427, "naklon": 6 }, +{ "label": "34/95", "node": 3434, "naklon": 6 }, +{ "label": "34/96", "node": 3456, "naklon": 6 }, +{ "label": "34/98/1", "node": 4307, "naklon": 6 }, +{ "label": "35/1", "node": 3968, "naklon": 0 }, +{ "label": "35/2", "node": 3969, "naklon": 0 }, +{ "label": "35/3", "node": 3947, "naklon": 0 }, +{ "label": "35/4", "node": 3979, "naklon": 0 }, +{ "label": "35/5", "node": 3959, "naklon": 0 }, +{ "label": "35/6", "node": 3948, "naklon": 0 }, +{ "label": "35/7", "node": 3961, "naklon": 0 }, +{ "label": "35/8", "node": 3956, "naklon": 0 }, +{ "label": "35/9", "node": 3604, "naklon": 0 }, +{ "label": "35/10", "node": 3944, "naklon": 0 }, +{ "label": "35/11", "node": 3960, "naklon": 0 }, +{ "label": "35/12", "node": 3958, "naklon": 0 }, +{ "label": "35/13", "node": 4036, "naklon": 5 }, +{ "label": "35/18", "node": 3893, "naklon": 5 }, +{ "label": "35/19", "node": 4108, "naklon": 5 }, +{ "label": "35/20", "node": 4017, "naklon": 5 }, +{ "label": "35/21", "node": 3963, "naklon": 0 }, +{ "label": "35/22", "node": 3658, "naklon": 0 }, +{ "label": "35/23", "node": 3975, "naklon": 0 }, +{ "label": "35/24", "node": 3980, "naklon": 0 }, +{ "label": "35/25", "node": 4012, "naklon": 0 }, +{ "label": "35/26", "node": 3655, "naklon": 0 }, +{ "label": "35/27", "node": 3962, "naklon": 0 }, +{ "label": "35/28", "node": 3945, "naklon": 0 }, +{ "label": "35/29", "node": 3569, "naklon": 0 }, +{ "label": "35/30", "node": 3429, "naklon": 0 }, +{ "label": "35/31", "node": 3657, "naklon": 0 }, +{ "label": "35/32", "node": 3646, "naklon": 0 }, +{ "label": "35/33", "node": 3622, "naklon": 0 }, +{ "label": "35/34", "node": 3612, "naklon": 0 }, +{ "label": "35/35", "node": 3955, "naklon": 0 }, +{ "label": "35/37", "node": 3878, "naklon": 0 }, +{ "label": "35/38", "node": 3965, "naklon": 0 }, +{ "label": "35/39", "node": 3970, "naklon": 0 }, +{ "label": "35/40", "node": 3611, "naklon": 0 }, +{ "label": "35/41", "node": 2635, "naklon": 0 }, +{ "label": "35/42", "node": 3978, "naklon": 0 }, +{ "label": "35/43", "node": 4213, "naklon": 0 }, +{ "label": "35/44", "node": 3984, "naklon": 0 }, +{ "label": "35/45", "node": 4218, "naklon": 0 }, +{ "label": "35/46", "node": 3973, "naklon": 0 }, +{ "label": "35/47", "node": 3974, "naklon": 0 }, +{ "label": "35/48", "node": 3759, "naklon": 0 }, +{ "label": "35/49", "node": 3844, "naklon": 0 }, +{ "label": "35/50", "node": 3804, "naklon": 0 }, +{ "label": "35/51", "node": 3831, "naklon": 0 }, +{ "label": "35/52", "node": 3643, "naklon": 0 }, +{ "label": "35/53", "node": 3966, "naklon": 0 }, +{ "label": "35/54", "node": 3971, "naklon": 0 }, +{ "label": "35/55", "node": 3650, "naklon": 6 }, +{ "label": "35/56", "node": 3651, "naklon": 6 }, +{ "label": "35/57", "node": 3669, "naklon": 6 }, +{ "label": "35/58", "node": 3648, "naklon": 6 }, +{ "label": "35/59", "node": 3645, "naklon": 6 }, +{ "label": "35/60", "node": 3659, "naklon": 6 }, +{ "label": "35/61", "node": 3647, "naklon": 6 }, +{ "label": "35/62", "node": 3644, "naklon": 6 }, +{ "label": "35/63", "node": 3671, "naklon": 6 }, +{ "label": "35/64", "node": 3682, "naklon": 6 }, +{ "label": "35/65", "node": 3672, "naklon": 6 }, +{ "label": "35/66", "node": 3683, "naklon": 6 }, +{ "label": "35/67", "node": 3673, "naklon": 6 }, +{ "label": "35/68", "node": 3674, "naklon": 6 }, +{ "label": "35/69", "node": 3679, "naklon": 6 }, +{ "label": "35/70", "node": 3649, "naklon": 6 }, +{ "label": "35/71", "node": 3687, "naklon": 6 }, +{ "label": "35/72", "node": 3677, "naklon": 6 }, +{ "label": "35/73", "node": 3690, "naklon": 6 }, +{ "label": "35/74", "node": 3691, "naklon": 6 }, +{ "label": "35/75", "node": 3676, "naklon": 6 }, +{ "label": "35/76", "node": 3680, "naklon": 6 }, +{ "label": "35/77", "node": 3668, "naklon": 6 }, +{ "label": "35/78", "node": 3681, "naklon": 6 }, +{ "label": "35/79", "node": 3670, "naklon": 6 }, +{ "label": "35/80", "node": 3689, "naklon": 6 }, +{ "label": "35/81", "node": 3678, "naklon": 6 }, +{ "label": "35/82", "node": 3693, "naklon": 6 }, +{ "label": "35/83", "node": 3654, "naklon": null }, +{ "label": "36/1", "node": 4086, "naklon": 0 }, +{ "label": "36/2", "node": 4085, "naklon": 0 }, +{ "label": "36/3", "node": 4083, "naklon": 0 }, +{ "label": "36/4", "node": 4087, "naklon": 0 }, +{ "label": "36/5", "node": 4077, "naklon": 0 }, +{ "label": "36/6", "node": 4082, "naklon": 0 }, +{ "label": "36/7", "node": 4186, "naklon": 0 }, +{ "label": "36/8", "node": 4206, "naklon": 0 }, +{ "label": "36/9", "node": 4080, "naklon": 0 }, +{ "label": "36/10", "node": 4081, "naklon": 0 }, +{ "label": "36/11", "node": 4210, "naklon": 0 }, +{ "label": "36/12", "node": 4079, "naklon": 0 }, +{ "label": "36/13", "node": 4076, "naklon": 0 }, +{ "label": "36/14", "node": 3852, "naklon": 0 }, +{ "label": "36/15", "node": 2813, "naklon": 0 }, +{ "label": "36/16", "node": 4219, "naklon": 0 }, +{ "label": "37/1A", "node": 3104, "naklon": 15 }, +{ "label": "37/1B", "node": 3121, "naklon": 15 }, +{ "label": "37/2", "node": 3113, "naklon": 10 }, +{ "label": "37/3", "node": 3118, "naklon": 10 }, +{ "label": "37/4", "node": 3111, "naklon": 10 }, +{ "label": "37/5", "node": 4020, "naklon": 10 }, +{ "label": "37/6", "node": 3119, "naklon": 10 }, +{ "label": "37/7", "node": 3110, "naklon": 10 }, +{ "label": "37/8", "node": 3108, "naklon": 10 }, +{ "label": "37/12", "node": 3107, "naklon": 0 }, +{ "label": "37/13", "node": 3199, "naklon": 0 }, +{ "label": "37/14", "node": 3120, "naklon": 0 }, +{ "label": "37/15", "node": 3122, "naklon": 0 }, +{ "label": "37/16", "node": 3908, "naklon": 0 }, +{ "label": "37/17", "node": 3114, "naklon": 0 }, +{ "label": "37/18", "node": 3105, "naklon": 0 }, +{ "label": "37/19", "node": 3116, "naklon": 0 }, +{ "label": "37/20", "node": 3106, "naklon": 0 }, +{ "label": "37/21", "node": 2887, "naklon": 5 }, +{ "label": "37/22", "node": 2888, "naklon": 5 }, +{ "label": "37/23", "node": 2877, "naklon": 5 }, +{ "label": "37/24", "node": 2891, "naklon": 5 }, +{ "label": "37/25", "node": 2886, "naklon": 5 }, +{ "label": "37/26", "node": 2892, "naklon": 5 }, +{ "label": "37/27", "node": 2882, "naklon": 5 }, +{ "label": "37/28", "node": 2883, "naklon": 5 }, +{ "label": "37/29", "node": 2876, "naklon": 5 }, +{ "label": "37/30", "node": 3109, "naklon": 5 }, +{ "label": "37/31", "node": 4152, "naklon": 5 }, +{ "label": "37/32", "node": 3117, "naklon": 5 }, +{ "label": "37/33", "node": 2870, "naklon": 5 }, +{ "label": "37/34", "node": 2867, "naklon": 0 }, +{ "label": "37/35", "node": 2865, "naklon": 0 }, +{ "label": "37/36", "node": 3096, "naklon": 0 }, +{ "label": "37/37", "node": 2871, "naklon": 0 }, +{ "label": "37/38", "node": 2884, "naklon": 0 }, +{ "label": "37/39", "node": 2855, "naklon": 0 }, +{ "label": "37/40", "node": 2878, "naklon": 0 }, +{ "label": "37/41", "node": 2889, "naklon": 0 }, +{ "label": "37/42", "node": 2879, "naklon": 0 }, +{ "label": "37/43", "node": 2850, "naklon": 0 }, +{ "label": "37/44", "node": 2894, "naklon": 0 }, +{ "label": "37/45", "node": 2880, "naklon": 0 }, +{ "label": "37/46", "node": 2893, "naklon": 0 }, +{ "label": "37/47", "node": 2890, "naklon": 0 }, +{ "label": "37/48", "node": 4355, "naklon": 0 }, +{ "label": "37/49", "node": 2885, "naklon": 0 }, +{ "label": "37/50", "node": 2875, "naklon": 0 }, +{ "label": "38/30A", "node": 3486, "naklon": 5 }, +{ "label": "38/30B", "node": 3714, "naklon": 0 }, +{ "label": "38/32A", "node": 3483, "naklon": 5 }, +{ "label": "38/32B", "node": 3496, "naklon": 0 }, +{ "label": "38/35A", "node": 3487, "naklon": 5 }, +{ "label": "38/35B", "node": 3498, "naklon": 5 }, +{ "label": "38/38A", "node": 3578, "naklon": 5 }, +{ "label": "38/38B", "node": 3508, "naklon": 5 }, +{ "label": "38/59A", "node": 3787, "naklon": 5 }, +{ "label": "38/59B", "node": 3491, "naklon": 5 }, +{ "label": "38/1", "node": 3568, "naklon": null }, +{ "label": "38/2", "node": 3502, "naklon": 0 }, +{ "label": "38/3", "node": 3836, "naklon": 0 }, +{ "label": "38/4", "node": 3588, "naklon": 0 }, +{ "label": "38/5", "node": 3493, "naklon": 0 }, +{ "label": "38/6", "node": 3580, "naklon": 0 }, +{ "label": "38/7", "node": 3572, "naklon": 0 }, +{ "label": "38/8", "node": 3506, "naklon": 0 }, +{ "label": "38/9", "node": 3503, "naklon": 0 }, +{ "label": "38/10", "node": 3579, "naklon": 0 }, +{ "label": "38/11", "node": 3586, "naklon": 0 }, +{ "label": "38/12", "node": 3495, "naklon": 5 }, +{ "label": "38/13", "node": 3492, "naklon": 5 }, +{ "label": "38/14", "node": 3532, "naklon": 5 }, +{ "label": "38/15", "node": 3574, "naklon": 5 }, +{ "label": "38/16", "node": 4140, "naklon": 5 }, +{ "label": "38/17", "node": 3795, "naklon": 5 }, +{ "label": "38/18", "node": 3788, "naklon": 5 }, +{ "label": "38/19", "node": 3796, "naklon": 5 }, +{ "label": "38/20", "node": 3797, "naklon": 5 }, +{ "label": "38/21", "node": 3798, "naklon": 5 }, +{ "label": "38/22", "node": 3786, "naklon": 5 }, +{ "label": "38/23", "node": 4067, "naklon": 5 }, +{ "label": "38/24", "node": 3773, "naklon": 5 }, +{ "label": "38/25", "node": 3774, "naklon": 5 }, +{ "label": "38/26", "node": 3789, "naklon": 5 }, +{ "label": "38/27", "node": 3520, "naklon": null }, +{ "label": "38/29", "node": 3577, "naklon": 5 }, +{ "label": "38/31", "node": 3530, "naklon": null }, +{ "label": "38/33", "node": 3488, "naklon": 5 }, +{ "label": "38/34", "node": 3505, "naklon": 5 }, +{ "label": "38/36", "node": 3497, "naklon": 5 }, +{ "label": "38/37", "node": 3490, "naklon": 5 }, +{ "label": "38/39", "node": 3585, "naklon": 5 }, +{ "label": "38/40", "node": 3582, "naklon": 5 }, +{ "label": "38/41", "node": 3507, "naklon": 5 }, +{ "label": "38/42", "node": 3484, "naklon": 5 }, +{ "label": "38/43", "node": 3501, "naklon": 5 }, +{ "label": "38/44", "node": 3581, "naklon": 5 }, +{ "label": "38/45", "node": 4192, "naklon": 5 }, +{ "label": "38/46", "node": 3576, "naklon": 5 }, +{ "label": "38/47", "node": 3489, "naklon": 5 }, +{ "label": "38/48", "node": 3573, "naklon": 5 }, +{ "label": "38/49", "node": 3504, "naklon": 5 }, +{ "label": "38/50", "node": 3794, "naklon": 5 }, +{ "label": "38/51", "node": 3485, "naklon": 5 }, +{ "label": "38/52", "node": 3482, "naklon": 5 }, +{ "label": "38/53", "node": 3575, "naklon": 5 }, +{ "label": "38/54", "node": 3499, "naklon": 5 }, +{ "label": "38/55", "node": 3494, "naklon": 5 }, +{ "label": "38/56", "node": 3583, "naklon": 5 }, +{ "label": "38/57", "node": 3570, "naklon": 5 }, +{ "label": "38/58", "node": 3500, "naklon": 0 }, +{ "label": "38/63", "node": 3510, "naklon": null }, +{ "label": "38/64", "node": 3512, "naklon": null }, +{ "label": "38/67", "node": 3535, "naklon": null }, +{ "label": "38/68", "node": 3531, "naklon": null }, +{ "label": "38/69", "node": 3537, "naklon": null }, +{ "label": "39/1", "node": 3522, "naklon": 10 }, +{ "label": "39/2", "node": 4018, "naklon": 10 }, +{ "label": "39/3", "node": 4019, "naklon": 10 }, +{ "label": "39/4", "node": 4154, "naklon": 5 }, +{ "label": "39/5", "node": 3907, "naklon": 5 }, +{ "label": "39/6", "node": 4148, "naklon": 0 }, +{ "label": "39/7", "node": 4153, "naklon": 0 }, +{ "label": "39/8", "node": 3938, "naklon": 0 }, +{ "label": "39/9", "node": 3802, "naklon": 0 }, +{ "label": "39/10", "node": 4015, "naklon": 0 }, +{ "label": "39/11", "node": 3929, "naklon": 0 }, +{ "label": "39/12", "node": 3946, "naklon": 0 }, +{ "label": "39/13", "node": 4014, "naklon": 0 }, +{ "label": "39/14", "node": 4155, "naklon": 0 }, +{ "label": "39/15", "node": 4149, "naklon": 0 }, +{ "label": "39/16", "node": 3642, "naklon": 0 }, +{ "label": "39/17", "node": 3636, "naklon": 5 }, +{ "label": "39/18", "node": 3991, "naklon": 0 }, +{ "label": "39/19", "node": 3994, "naklon": 0 }, +{ "label": "39/20", "node": 3990, "naklon": 0 }, +{ "label": "39/21", "node": 3967, "naklon": 0 }, +{ "label": "39/22", "node": 3977, "naklon": 0 }, +{ "label": "39/23", "node": 3757, "naklon": 15 }, +{ "label": "39/24", "node": 3633, "naklon": 15 }, +{ "label": "39/25", "node": 3744, "naklon": 15 }, +{ "label": "39/26", "node": 4023, "naklon": 5 }, +{ "label": "39/27", "node": 3720, "naklon": 5 }, +{ "label": "39/28", "node": 3734, "naklon": 5 }, +{ "label": "39/29", "node": 3741, "naklon": 5 }, +{ "label": "39/30", "node": 3721, "naklon": 5 }, +{ "label": "39/31", "node": 3845, "naklon": 0 }, +{ "label": "39/32", "node": 3840, "naklon": 0 }, +{ "label": "39/33", "node": 3837, "naklon": null }, +{ "label": "39/34", "node": 3839, "naklon": 0 }, +{ "label": "41/1", "node": 3542, "naklon": null }, +{ "label": "41/2", "node": 3566, "naklon": null }, +{ "label": "41/3", "node": 3548, "naklon": null }, +{ "label": "41/4", "node": 3515, "naklon": null }, +{ "label": "41/5", "node": 3559, "naklon": null }, +{ "label": "41/6", "node": 3509, "naklon": null }, +{ "label": "41/7", "node": 3524, "naklon": null }, +{ "label": "41/8", "node": 3518, "naklon": null }, +{ "label": "41/9", "node": 3182, "naklon": null }, +{ "label": "41/10", "node": 3187, "naklon": null }, +{ "label": "41/11", "node": 3195, "naklon": 0 }, +{ "label": "41/12", "node": 3857, "naklon": 0 }, +{ "label": "41/13", "node": 3183, "naklon": 0 }, +{ "label": "41/14", "node": 3177, "naklon": 0 }, +{ "label": "41/15", "node": 3189, "naklon": 0 }, +{ "label": "41/16", "node": 3186, "naklon": 0 }, +{ "label": "42/1", "node": 3178, "naklon": 0 }, +{ "label": "42/2", "node": 3219, "naklon": 0 }, +{ "label": "42/3", "node": 3475, "naklon": 0 }, +{ "label": "42/4", "node": 3175, "naklon": 0 }, +{ "label": "42/5", "node": 3222, "naklon": 0 }, +{ "label": "42/6", "node": 3221, "naklon": 0 }, +{ "label": "42/7", "node": 3181, "naklon": 0 }, +{ "label": "42/8", "node": 3180, "naklon": 0 }, +{ "label": "42/9", "node": 3218, "naklon": 0 }, +{ "label": "42/10", "node": 3176, "naklon": 0 }, +{ "label": "42/11", "node": 3174, "naklon": 0 }, +{ "label": "42/12", "node": 3220, "naklon": 0 }, +{ "label": "42/13", "node": 3533, "naklon": null }, +{ "label": "42/14", "node": 3543, "naklon": null }, +{ "label": "42/15", "node": 3554, "naklon": null }, +{ "label": "42/16", "node": 3549, "naklon": null }, +{ "label": "43/1", "node": 2857, "naklon": 5 }, +{ "label": "43/2", "node": 2752, "naklon": 5 }, +{ "label": "43/3", "node": 2753, "naklon": 5 }, +{ "label": "43/4", "node": 3024, "naklon": 5 }, +{ "label": "43/5", "node": 2754, "naklon": 5 }, +{ "label": "43/6", "node": 4423, "naklon": 5 }, +{ "label": "43/7", "node": 4368, "naklon": 5 }, +{ "label": "43/8", "node": 2978, "naklon": 5 }, +{ "label": "43/9", "node": 2868, "naklon": 5 }, +{ "label": "43/10", "node": 4377, "naklon": 5 }, +{ "label": "43/11", "node": 2757, "naklon": 5 }, +{ "label": "43/12", "node": 2970, "naklon": 5 }, +{ "label": "43/13", "node": 2758, "naklon": 5 }, +{ "label": "43/14", "node": 4378, "naklon": 5 }, +{ "label": "43/15", "node": 2759, "naklon": 5 }, +{ "label": "43/16", "node": 4342, "naklon": 5 }, +{ "label": "43/17", "node": 3026, "naklon": null }, +{ "label": "43/18", "node": 2986, "naklon": null }, +{ "label": "43/19", "node": 4343, "naklon": null }, +{ "label": "43/20", "node": 2760, "naklon": null }, +{ "label": "43/21", "node": 4379, "naklon": null }, +{ "label": "43/22", "node": 2971, "naklon": null }, +{ "label": "43/23", "node": 2761, "naklon": null }, +{ "label": "43/24", "node": 2762, "naklon": null }, +{ "label": "43/25", "node": 4339, "naklon": null }, +{ "label": "43/26", "node": 4380, "naklon": null }, +{ "label": "43/27", "node": 2975, "naklon": null }, +{ "label": "43/28", "node": 3003, "naklon": null }, +{ "label": "43/29", "node": 4338, "naklon": null }, +{ "label": "43/30", "node": 3002, "naklon": null }, +{ "label": "43/31", "node": 4345, "naklon": null }, +{ "label": "43/32", "node": 2979, "naklon": null }, +{ "label": "43/33", "node": 2989, "naklon": null }, +{ "label": "43/34", "node": 2996, "naklon": null }, +{ "label": "43/35", "node": 2972, "naklon": null }, +{ "label": "43/36", "node": 2988, "naklon": null }, +{ "label": "43/37", "node": 4344, "naklon": null }, +{ "label": "43/38", "node": 3022, "naklon": null }, +{ "label": "43/39", "node": 4341, "naklon": null }, +{ "label": "43/40", "node": 2983, "naklon": null }, +{ "label": "43/41", "node": 2995, "naklon": null }, +{ "label": "43/42", "node": 2763, "naklon": null }, +{ "label": "43/43", "node": 2764, "naklon": null }, +{ "label": "43/44", "node": 2765, "naklon": null }, +{ "label": "43/45", "node": 2766, "naklon": null }, +{ "label": "43/46", "node": 2767, "naklon": null }, +{ "label": "43/47", "node": 2768, "naklon": null }, +{ "label": "43/48", "node": 3018, "naklon": null }, +{ "label": "43/49", "node": 2982, "naklon": null }, +{ "label": "43/50", "node": 3019, "naklon": 0 }, +{ "label": "43/51", "node": 3013, "naklon": null }, +{ "label": "43/52", "node": 3007, "naklon": null }, +{ "label": "43/53", "node": 2980, "naklon": null }, +{ "label": "43/54", "node": 3011, "naklon": null }, +{ "label": "43/55", "node": 2672, "naklon": null }, +{ "label": "43/56", "node": 2673, "naklon": null }, +{ "label": "43/57", "node": 2674, "naklon": null }, +{ "label": "43/58", "node": 2675, "naklon": null }, +{ "label": "43/59", "node": 2676, "naklon": null }, +{ "label": "43/60", "node": 2677, "naklon": null }, +{ "label": "43/61", "node": 2678, "naklon": null }, +{ "label": "43/62", "node": 2679, "naklon": null }, +{ "label": "43/63", "node": 2680, "naklon": null }, +{ "label": "43/64", "node": 2840, "naklon": null }, +{ "label": "43/65", "node": 2682, "naklon": null }, +{ "label": "43/66", "node": 2683, "naklon": null }, +{ "label": "43/67", "node": 2684, "naklon": 0 }, +{ "label": "43/68", "node": 2685, "naklon": null }, +{ "label": "43/69", "node": 2686, "naklon": null }, +{ "label": "43/70", "node": 2687, "naklon": null }, +{ "label": "43/71", "node": 2688, "naklon": null }, +{ "label": "43/72", "node": 2689, "naklon": null }, +{ "label": "43/73", "node": 2690, "naklon": null }, +{ "label": "43/74", "node": 2691, "naklon": null }, +{ "label": "43/75", "node": 2692, "naklon": null }, +{ "label": "43/76", "node": 2693, "naklon": 0 }, +{ "label": "43/77", "node": 2694, "naklon": null }, +{ "label": "43/78", "node": 2695, "naklon": null }, +{ "label": "43/79", "node": 2696, "naklon": 0 }, +{ "label": "43/80", "node": 2697, "naklon": null }, +{ "label": "43/81", "node": 2698, "naklon": 0 }, +{ "label": "43/82", "node": 2699, "naklon": null }, +{ "label": "43/83", "node": 2700, "naklon": 0 }, +{ "label": "43/84", "node": 2744, "naklon": null }, +{ "label": "43/85", "node": 2745, "naklon": 0 }, +{ "label": "43/86", "node": 2746, "naklon": null }, +{ "label": "43/87", "node": 2747, "naklon": 0 }, +{ "label": "43/88", "node": 2748, "naklon": null }, +{ "label": "43/89", "node": 2749, "naklon": 0 }, +{ "label": "43/90", "node": 2841, "naklon": null }, +{ "label": "45/1", "node": 4237, "naklon": 5 }, +{ "label": "45/2", "node": 4226, "naklon": 5 }, +{ "label": "45/3", "node": 4242, "naklon": 5 }, +{ "label": "45/4", "node": 4179, "naklon": 5 }, +{ "label": "45/5", "node": 4247, "naklon": 5 }, +{ "label": "45/6", "node": 4245, "naklon": 5 }, +{ "label": "45/7", "node": 3872, "naklon": 5 }, +{ "label": "45/8", "node": 4175, "naklon": 5 }, +{ "label": "45/9", "node": 4236, "naklon": 5 }, +{ "label": "45/10", "node": 4170, "naklon": 5 }, +{ "label": "45/11", "node": 4238, "naklon": 5 }, +{ "label": "45/12", "node": 4246, "naklon": 5 }, +{ "label": "45/13", "node": 4166, "naklon": 5 }, +{ "label": "45/14", "node": 4227, "naklon": 5 }, +{ "label": "45/15", "node": 4171, "naklon": 5 }, +{ "label": "45/16", "node": 4180, "naklon": 5 }, +{ "label": "45/17", "node": 4244, "naklon": 5 }, +{ "label": "45/18", "node": 4199, "naklon": 5 }, +{ "label": "45/19", "node": 4239, "naklon": 5 }, +{ "label": "45/20", "node": 4207, "naklon": 5 }, +{ "label": "45/21", "node": 4223, "naklon": 5 }, +{ "label": "45/22", "node": 4230, "naklon": 5 }, +{ "label": "45/23", "node": 4233, "naklon": 5 }, +{ "label": "45/24", "node": 4222, "naklon": 5 }, +{ "label": "45/25", "node": 4217, "naklon": 5 }, +{ "label": "45/26", "node": 4243, "naklon": 5 }, +{ "label": "45/27", "node": 4200, "naklon": 5 }, +{ "label": "45/28", "node": 4228, "naklon": 5 }, +{ "label": "45/29", "node": 4211, "naklon": 5 }, +{ "label": "45/30", "node": 4234, "naklon": 5 }, +{ "label": "45/31", "node": 4235, "naklon": 5 }, +{ "label": "45/32", "node": 4203, "naklon": 5 }, +{ "label": "45/33", "node": 4240, "naklon": 5 }, +{ "label": "45/34", "node": 4224, "naklon": 5 }, +{ "label": "45/35", "node": 4232, "naklon": 5 }, +{ "label": "45/36", "node": 4231, "naklon": 5 }, +{ "label": "45/37", "node": 4161, "naklon": 5 }, +{ "label": "45/38", "node": 4225, "naklon": 5 }, +{ "label": "45/39", "node": 4241, "naklon": 5 }, +{ "label": "45/40", "node": 4229, "naklon": 5 }, +{ "label": "45/41", "node": 4221, "naklon": 5 }, +{ "label": "45/42", "node": 4212, "naklon": 5 }, +{ "label": "45/43", "node": 4216, "naklon": 5 }, +{ "label": "45/44", "node": 3864, "naklon": null }, +{ "label": "46/1", "node": 3806, "naklon": 5 }, +{ "label": "46/2", "node": 3813, "naklon": 5 }, +{ "label": "46/3", "node": 3815, "naklon": 5 }, +{ "label": "46/4", "node": 3807, "naklon": 5 }, +{ "label": "46/5", "node": 3895, "naklon": 5 }, +{ "label": "46/6", "node": 3809, "naklon": 5 }, +{ "label": "46/7", "node": 3820, "naklon": 5 }, +{ "label": "46/8", "node": 3805, "naklon": 5 }, +{ "label": "46/9", "node": 3894, "naklon": 0 }, +{ "label": "46/10", "node": 4055, "naklon": 0 }, +{ "label": "46/11", "node": 3812, "naklon": 5 }, +{ "label": "46/12", "node": 3822, "naklon": 5 }, +{ "label": "46/13", "node": 3821, "naklon": 5 }, +{ "label": "46/14", "node": 3808, "naklon": 5 }, +{ "label": "46/15", "node": 3799, "naklon": 5 }, +{ "label": "46/16", "node": 3816, "naklon": 5 }, +{ "label": "46/17", "node": 3751, "naklon": 5 }, +{ "label": "46/18", "node": 3814, "naklon": 5 }, +{ "label": "46/19", "node": 4044, "naklon": 0 }, +{ "label": "46/20", "node": 3931, "naklon": 0 }, +{ "label": "46/21", "node": 3902, "naklon": 5 }, +{ "label": "46/22", "node": 3916, "naklon": 5 }, +{ "label": "46/23", "node": 3892, "naklon": 5 }, +{ "label": "46/24", "node": 3914, "naklon": 5 }, +{ "label": "46/25", "node": 3898, "naklon": 5 }, +{ "label": "46/26", "node": 3897, "naklon": 5 }, +{ "label": "46/27", "node": 3885, "naklon": 5 }, +{ "label": "46/28", "node": 3906, "naklon": 5 }, +{ "label": "46/29", "node": 3930, "naklon": 0 }, +{ "label": "46/30", "node": 3936, "naklon": 0 }, +{ "label": "46/31", "node": 3860, "naklon": 5 }, +{ "label": "46/32", "node": 3841, "naklon": 5 }, +{ "label": "46/33", "node": 3873, "naklon": 5 }, +{ "label": "46/34", "node": 3854, "naklon": 5 }, +{ "label": "46/35", "node": 3939, "naklon": 5 }, +{ "label": "46/36", "node": 3858, "naklon": 5 }, +{ "label": "46/37", "node": 3940, "naklon": 5 }, +{ "label": "46/38", "node": 4035, "naklon": 5 }, +{ "label": "47/1", "node": 3373, "naklon": 0 }, +{ "label": "47/2", "node": 3374, "naklon": 0 }, +{ "label": "47/3", "node": 3384, "naklon": 0 }, +{ "label": "47/4", "node": 3385, "naklon": 0 }, +{ "label": "48/1", "node": 4051, "naklon": 5 }, +{ "label": "48/2", "node": 4041, "naklon": 5 }, +{ "label": "48/3", "node": 4056, "naklon": 5 }, +{ "label": "48/4", "node": 3875, "naklon": 5 }, +{ "label": "48/5", "node": 4061, "naklon": 5 }, +{ "label": "48/6", "node": 4047, "naklon": 5 }, +{ "label": "48/7", "node": 4060, "naklon": 5 }, +{ "label": "48/8", "node": 4059, "naklon": 5 }, +{ "label": "48/9", "node": 4058, "naklon": 5 }, +{ "label": "48/10", "node": 3635, "naklon": 5 }, +{ "label": "48/11", "node": 3640, "naklon": 5 }, +{ "label": "48/12", "node": 3747, "naklon": 5 }, +{ "label": "48/13", "node": 3629, "naklon": 5 }, +{ "label": "48/14", "node": 4048, "naklon": 5 }, +{ "label": "48/15", "node": 4063, "naklon": 5 }, +{ "label": "48/16", "node": 4062, "naklon": 5 }, +{ "label": "48/17", "node": 4043, "naklon": 5 }, +{ "label": "48/18", "node": 4052, "naklon": 5 }, +{ "label": "48/19", "node": 4042, "naklon": 5 }, +{ "label": "48/20", "node": 4053, "naklon": 5 }, +{ "label": "50/15A", "node": 4167, "naklon": null }, +{ "label": "50/15B", "node": 4159, "naklon": null }, +{ "label": "50/1", "node": 4183, "naklon": 0 }, +{ "label": "50/2", "node": 4157, "naklon": 0 }, +{ "label": "50/3", "node": 4160, "naklon": 0 }, +{ "label": "50/4", "node": 4173, "naklon": 0 }, +{ "label": "50/5", "node": 4177, "naklon": 0 }, +{ "label": "50/6", "node": 4174, "naklon": 0 }, +{ "label": "50/7", "node": 4178, "naklon": 0 }, +{ "label": "50/8", "node": 4195, "naklon": 0 }, +{ "label": "50/9", "node": 4169, "naklon": 0 }, +{ "label": "50/10", "node": 4162, "naklon": 0 }, +{ "label": "50/11", "node": 4158, "naklon": 0 }, +{ "label": "50/12", "node": 4182, "naklon": 0 }, +{ "label": "50/13", "node": 4194, "naklon": 0 }, +{ "label": "50/14", "node": 4184, "naklon": 0 }, +{ "label": "50/16", "node": 4197, "naklon": null }, +{ "label": "50/17", "node": 4164, "naklon": null }, +{ "label": "50/18", "node": 3306, "naklon": null }, +{ "label": "50/19", "node": 4168, "naklon": null }, +{ "label": "50/20", "node": 4193, "naklon": null }, +{ "label": "50/21", "node": 4187, "naklon": null }, +{ "label": "50/22", "node": 4163, "naklon": null }, +{ "label": "50/23", "node": 4165, "naklon": null }, +{ "label": "50/24", "node": 4185, "naklon": null }, +{ "label": "50/25", "node": 3904, "naklon": null }, +{ "label": "53/1", "node": 2619, "naklon": 0 }, +{ "label": "53/2", "node": 2623, "naklon": 0 }, +{ "label": "53/3", "node": 2617, "naklon": 0 }, +{ "label": "53/4", "node": 2622, "naklon": 0 }, +{ "label": "53/5", "node": 2618, "naklon": 0 }, +{ "label": "53/6", "node": 2626, "naklon": 0 }, +{ "label": "53/7", "node": 2869, "naklon": 0 }, +{ "label": "53/8", "node": 2613, "naklon": 0 }, +{ "label": "53/9", "node": 2608, "naklon": 0 }, +{ "label": "53/10", "node": 2611, "naklon": 0 }, +{ "label": "53/11", "node": 2598, "naklon": 0 }, +{ "label": "53/12", "node": 3528, "naklon": 0 }, +{ "label": "53/13", "node": 3545, "naklon": 0 }, +{ "label": "53/14", "node": 2620, "naklon": 0 }, +{ "label": "53/15", "node": 2612, "naklon": 0 }, +{ "label": "53/16", "node": 2615, "naklon": 0 }, +{ "label": "53/17", "node": 3722, "naklon": 0 }, +{ "label": "53/18", "node": 2624, "naklon": 0 }, +{ "label": "53/19", "node": 2609, "naklon": 0 }, +{ "label": "53/20", "node": 2625, "naklon": 0 }, +{ "label": "53/21", "node": 2602, "naklon": 0 }, +{ "label": "53/22", "node": 2610, "naklon": 0 }, +{ "label": "53/23", "node": 2599, "naklon": 0 }, +{ "label": "53/24", "node": 2605, "naklon": 0 }, +{ "label": "53/25", "node": 2593, "naklon": 0 }, +{ "label": "53/26", "node": 3074, "naklon": 0 }, +{ "label": "53/27", "node": 2740, "naklon": 0 }, +{ "label": "53/28", "node": 2614, "naklon": 0 }, +{ "label": "53/29", "node": 2601, "naklon": 0 }, +{ "label": "53/30", "node": 4196, "naklon": 0 }, +{ "label": "53/31", "node": 2607, "naklon": 0 }, +{ "label": "53/32", "node": 2582, "naklon": 0 }, +{ "label": "53/33", "node": 2594, "naklon": 0 }, +{ "label": "53/34", "node": 2589, "naklon": 0 }, +{ "label": "53/35", "node": 2596, "naklon": 0 }, +{ "label": "53/36", "node": 2603, "naklon": 0 }, +{ "label": "53/37", "node": 2597, "naklon": 0 }, +{ "label": "53/38", "node": 2590, "naklon": 0 }, +{ "label": "53/39", "node": 2581, "naklon": 0 }, +{ "label": "53/40", "node": 2583, "naklon": 0 }, +{ "label": "53/41", "node": 2580, "naklon": 0 }, +{ "label": "53/42", "node": 2579, "naklon": 0 }, +{ "label": "53/43", "node": 2797, "naklon": 0 }, +{ "label": "53/44", "node": 2577, "naklon": 0 }, +{ "label": "53/45", "node": 2586, "naklon": 0 }, +{ "label": "53/46", "node": 2588, "naklon": 0 }, +{ "label": "53/47", "node": 2591, "naklon": 0 }, +{ "label": "53/48", "node": 2592, "naklon": 0 }, +{ "label": "53/49", "node": 2573, "naklon": 0 }, +{ "label": "53/50", "node": 2595, "naklon": 0 }, +{ "label": "53/51", "node": 2587, "naklon": 0 }, +{ "label": "53/52", "node": 2578, "naklon": 0 }, +{ "label": "53/53", "node": 2574, "naklon": 0 }, +{ "label": "53/54", "node": 2571, "naklon": 0 }, +{ "label": "53/55", "node": 2570, "naklon": 0 }, +{ "label": "53/56", "node": 2576, "naklon": 0 }, +{ "label": "53/57", "node": 2881, "naklon": 0 }, +{ "label": "53/58", "node": 2575, "naklon": 0 }, +{ "label": "53/59", "node": 2572, "naklon": 0 }, +{ "label": "53/60", "node": 2569, "naklon": 0 }, +{ "label": "55/1", "node": 4324, "naklon": 0 }, +{ "label": "55/2", "node": 4319, "naklon": 0 }, +{ "label": "55/3", "node": 4327, "naklon": 0 }, +{ "label": "55/4", "node": 4333, "naklon": 0 }, +{ "label": "55/5", "node": 4332, "naklon": 0 }, +{ "label": "55/6", "node": 4320, "naklon": 0 }, +{ "label": "55/7", "node": 4317, "naklon": 0 }, +{ "label": "55/8", "node": 4318, "naklon": 0 }, +{ "label": "55/9", "node": 4328, "naklon": 0 }, +{ "label": "55/10", "node": 4323, "naklon": 0 }, +{ "label": "55/11", "node": 4325, "naklon": 0 }, +{ "label": "55/12", "node": 4326, "naklon": 0 }, +{ "label": "55/13", "node": 4316, "naklon": 0 }, +{ "label": "55/14", "node": 4322, "naklon": 0 }, +{ "label": "55/15", "node": 4331, "naklon": 0 }, +{ "label": "55/16", "node": 4321, "naklon": 0 }, +{ "label": "55/17", "node": 4315, "naklon": 0 }, +{ "label": "55/18", "node": 4329, "naklon": 0 }, +{ "label": "55/19", "node": 4334, "naklon": 0 }, +{ "label": "55/20", "node": 4330, "naklon": 0 } +]; + +module.exports = { naklony }; diff --git a/RVO21/databases/modbus_config.js b/RVO21/databases/modbus_config.js new file mode 100755 index 0000000..b73116a --- /dev/null +++ b/RVO21/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/RVO21/databases/nodes.table b/RVO21/databases/nodes.table new file mode 100755 index 0000000..32fe719 --- /dev/null +++ b/RVO21/databases/nodes.table @@ -0,0 +1,55 @@ +node:number|pole_number:string|node_type:string|tbname:string|line:number|profile:string|processed:boolean|status:boolean|time_of_last_communication:number ++|2718|8|NEMA|g9OxBZ5KRwNznlY6pApp11AWXvjdEL4eGQobMDy2|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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":-10,"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|1760573848734|............. ++|2770|44|NEMA|apKVJBwOyrP35m2lv7KYJ10YXbeWNd64En9GxRqg|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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":-10,"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|1760573854086|............. ++|2706|42|NEMA|BaY3Xpy1EbKGjLq2O7maew7rx8owgQz9P4dDJRmN|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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":-10,"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|1760573976769|............. ++|2920|28|NEMA|wvKJdZML6mXP4DzWBAXx1PAjxNloa5g23Ve9Y1ry|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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":-10,"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|1760573877447|............. ++|2793|24|NEMA|ZmRwd93QL4gaezxEbAx2wVk1prn2XjlPvGyqJ6BO|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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":-10,"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|1760573919327|............. ++|2895|20|NEMA|K94XLav1glVRnyQ6r01P5wAme3YJwBxM5oOzdP2j|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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":-10,"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|1760573867572|............. ++|2707|2|NEMA|gP1eOZVj3Q9lv5aDEk45xV7rdpqW8yLm2BbKzJxM|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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":-10,"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|1760573846625|............. ++|3423|21|NEMA|d9x2V5LGYBzXp4mMRAOmovkPloaqJwnQj6DgrNe3|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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":-10,"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|1760573879061|............. ++|2714|37|NEMA|gYbDLqlyZVoRerQpB72MR8kWJnwM5z24POKa8Exj|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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":-10,"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|1760573884909|............. ++|2897|16|NEMA|PjLblDgRBO6WQqnxmkJ16g0Jv3ewZN4p5a89yKdY|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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":-10,"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|1760573867732|............. ++|2898|18|NEMA|d5xjWYMwEJon6rLlK7yE6N7qgV4DaOeNB9ZX3Gzb|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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":-10,"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|1760573921628|............. ++|2716|4|NEMA|pE5X8NQPaow6vlOZxk6a8X0q42ezGBMyWgDVjR3L|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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":-10,"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|1760573847056|............. ++|2899|34|NEMA|roKgWqY95V3mXMRzyAjKBe0bLjexpJPvaGDBw826|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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":-10,"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|1760573868036|............. ++|2717|5|NEMA|6lQGaY9RDywdVzObj0PaRWkPg4NBn3exEK51LWZq|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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":-10,"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|1760573848398|............. ++|2921|1|NEMA|o9vbeQlLMVg8j5dq4keL140NxZpEmnXzwYKO1ar2|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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":-10,"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|1760573878086|............. ++|2900|33|NEMA|E6Kg9oDnLWyzPRMva7v56bkJxp4VG58qO2w1lZYe|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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":-10,"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|1760573872062|............. ++|2902|25|NEMA|eod9aRWLVl34Gx1Dn7VNpr72rz6qjgmpEXwQJN5Z|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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":-10,"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|1760573872525|............. ++|2903|14|NEMA|Z5KyJe9nEg1QNbWlX0w46zkoDjBLdqzR83VGv624|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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":-10,"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|1760573872669|............. ++|2904|30|NEMA|PLBJzmK1r3Gynd6OW0gK1x0e5wV4vx9bDEqNgYR8|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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":-10,"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|1760573873708|............. ++|2905|32|NEMA|rDbQ84xzwgdqEoPm3kbEOy09anOZY1RXyBv2LVM6|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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":-10,"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|1760573874155|............. ++|2909|27|Kamera|EjgWGnXaLy9opPOz20n41a786BlYM3w1deVQvbKr|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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":-10,"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|1760573874954|............. ++|2910|26|NEMA|3a5oqJN1bgnx4Ol9dk89XQ7ByE6jQ8mKDWMpGrLV|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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":-10,"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|1760573875114|............. ++|2914|17|NEMA|dz4ojlpP85JMgDLZWkQJan7aKYqQexEr62GXRV1y|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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":-10,"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|1760573875897|............. ++|2915|31|NEMA|52dD6ZlV1QaOpRBmbAqG1qkKnGzWMLj4eJq38Pgo|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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":-10,"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|1760573876057|............. ++|2916|29|NEMA|Nzp2OoJlqn6r1ZgvdA3BPL7abBwP5G4eE3RQmyxD|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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":-10,"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|1760573876185|............. ++|2917|15|NEMA|1JMYvnx2RzKEo4aWQ7DG6vkL8yZV3m9NBePXbrdj|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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":-10,"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|1760573877000|............. ++|2701|38|NEMA|zdQO8GwxDqjRgP4137YVD5ANyKlpem2nL65rvVJY|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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":-10,"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|1760573973605|............. ++|2702|41|NEMA|zrR51V2ajQ9ZLygPKkEMJakYDq38xOJolENBXGnv|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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":-10,"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|1760573881154|............. ++|2703|39|NEMA|WlVJBygjDZMeKX3vnAMRJR08NqdmG2x1Y69LQ4P5|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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":-10,"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|1760574000337|............. ++|2704|40|NEMA|5dBNwRp9graYJxZn409NKwklVov1b2QLPDqGm6XK|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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":-10,"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|1760574000848|............. ++|2720|6|NEMA|m6EYyZoJ4gWexdjVPAR56v7RDOq9wv2N5XzKGplr|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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":-10,"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|1760573892035|............. ++|2722|7|NEMA|JzwxZXOvDj1bVrN4nkW5pbA8qdyBl3MRKLpGPgaQ|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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":-10,"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|1760573924152|............. ++|2723|3|NEMA|2O14VBzl8aDmWdNw3A59VgAGyZ5qLJoEMpj6R9ng|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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":-10,"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|1760573894640|............. ++|2724|9|NEMA|OzNMgZ9n43qPbjXmy7zwlbA2DKdYvW5e6pxGRrVa|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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":-10,"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|1760573895007|............. ++|2733|12|NEMA|RO8rjaBDy21qPQJzW7om1L0pK3xmNleVZg9Ed4Gw|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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":-10,"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|1760573849724|............. ++|2741|36|NEMA|XMBbew5z4ELrZa2mRAd3ew78vPN6gy3DdVYlpKjq|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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":-10,"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|1760573897436|............. ++|2742|10|NEMA|JX1ObgmqGZ54DMyYL7aDOGkEVdve38WKRzwjNrQ9|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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":-10,"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|1760573850523|............. ++|2743|11|NEMA|RvmwNz8QPblKp41GD7lK1QkJrLVYoBO92dMegn6W|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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":-10,"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|1760573850843|............. ++|2769|49|NEMA|6lQGaY9RDywdVzObj0PaDWkPg4NBn3exEK51LWZq|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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":-10,"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|1760573896400|............. ++|2771|22|NEMA|B5EoxeMVp4zwr8nqW0GB6YARjvD1PNamOGbLg63Z|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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":-10,"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|1760573854438|............. ++|2772|23|NEMA|aw4eELG2DlPMdn1JW0BMYaAqQXOZRN3xB5yp8VKr|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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":-10,"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|1760573854614|............. ++|2773|19|NEMA|gRoJEyXVx4qD9er287L46Q7wBzGldaPjLWQKm3Mv|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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":-10,"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|1760573854774|............. ++|2774|56|NEMA|RO8rjaBDy21qPQJzW7omeL0pK3xmNleVZg9Ed4Gw|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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":-10,"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|1760573855605|............. ++|2775|52|NEMA|g9OxBZ5KRwNznlY6pAppe1AWXvjdEL4eGQobMDy2|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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":-10,"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|1760573856228|............. ++|2776|43|NEMA|DbQY6zyveZRwK5drV0Z8DJ7joE4XJM83N9xl2nWq|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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":-10,"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|1760573857826|............. ++|3354|50|NEMA|m6EYyZoJ4gWexdjVPAR5Bv7RDOq9wv2N5XzKGplr|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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":-10,"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|1760573878741|............. ++|2778|51|NEMA|JzwxZXOvDj1bVrN4nkW5DbA8qdyBl3MRKLpGPgaQ|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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":-10,"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|1760573911561|............. ++|2779|46|NEMA|gP1eOZVj3Q9lv5aDEk45KV7rdpqW8yLm2BbKzJxM|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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":-10,"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|1760573859711|............. ++|2780|53|NEMA|OzNMgZ9n43qPbjXmy7zwbbA2DKdYvW5e6pxGRrVa|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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":-10,"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|1760573860382|............. ++|2782|47|NEMA|2O14VBzl8aDmWdNw3A594gAGyZ5qLJoEMpj6R9ng|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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":-10,"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|1760573860781|............. ++|2785|48|NEMA|pE5X8NQPaow6vlOZxk6aBX0q42ezGBMyWgDVjR3L|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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":-10,"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|1760573861549|............. ++|2786|45|NEMA|o9vbeQlLMVg8j5dq4keLD40NxZpEmnXzwYKO1ar2|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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":-10,"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|1760573901543|............. ++|2790|54|NEMA|JX1ObgmqGZ54DMyYL7aDeGkEVdve38WKRzwjNrQ9|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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":-10,"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|1760573917122|............. ++|2792|55|NEMA|RvmwNz8QPblKp41GD7lKaQkJrLVYoBO92dMegn6W|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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":-10,"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|1760573865511|............. diff --git a/RVO21/databases/nodes_original/nodes_original.table b/RVO21/databases/nodes_original/nodes_original.table new file mode 100755 index 0000000..58a3335 --- /dev/null +++ b/RVO21/databases/nodes_original/nodes_original.table @@ -0,0 +1 @@ +[{"2718": "g9OxBZ5KRwNznlY6pApp11AWXvjdEL4eGQobMDy2"}, {"2770": "apKVJBwOyrP35m2lv7KYJ10YXbeWNd64En9GxRqg"}, {"2706": "BaY3Xpy1EbKGjLq2O7maew7rx8owgQz9P4dDJRmN"}, {"2920": "wvKJdZML6mXP4DzWBAXx1PAjxNloa5g23Ve9Y1ry"}, {"2793": "ZmRwd93QL4gaezxEbAx2wVk1prn2XjlPvGyqJ6BO"}, {"2895": "K94XLav1glVRnyQ6r01P5wAme3YJwBxM5oOzdP2j"}, {"2707": "gP1eOZVj3Q9lv5aDEk45xV7rdpqW8yLm2BbKzJxM"}, {"3423": "d9x2V5LGYBzXp4mMRAOmovkPloaqJwnQj6DgrNe3"}, {"2714": "gYbDLqlyZVoRerQpB72MR8kWJnwM5z24POKa8Exj"}, {"2897": "PjLblDgRBO6WQqnxmkJ16g0Jv3ewZN4p5a89yKdY"}, {"2898": "d5xjWYMwEJon6rLlK7yE6N7qgV4DaOeNB9ZX3Gzb"}, {"2716": "pE5X8NQPaow6vlOZxk6a8X0q42ezGBMyWgDVjR3L"}, {"2899": "roKgWqY95V3mXMRzyAjKBe0bLjexpJPvaGDBw826"}, {"2717": "6lQGaY9RDywdVzObj0PaRWkPg4NBn3exEK51LWZq"}, {"2921": "o9vbeQlLMVg8j5dq4keL140NxZpEmnXzwYKO1ar2"}, {"2900": "E6Kg9oDnLWyzPRMva7v56bkJxp4VG58qO2w1lZYe"}, {"2902": "eod9aRWLVl34Gx1Dn7VNpr72rz6qjgmpEXwQJN5Z"}, {"2903": "Z5KyJe9nEg1QNbWlX0w46zkoDjBLdqzR83VGv624"}, {"2904": "PLBJzmK1r3Gynd6OW0gK1x0e5wV4vx9bDEqNgYR8"}, {"2905": "rDbQ84xzwgdqEoPm3kbEOy09anOZY1RXyBv2LVM6"}, {"2909": "EjgWGnXaLy9opPOz20n41a786BlYM3w1deVQvbKr"}, {"2910": "3a5oqJN1bgnx4Ol9dk89XQ7ByE6jQ8mKDWMpGrLV"}, {"2914": "dz4ojlpP85JMgDLZWkQJan7aKYqQexEr62GXRV1y"}, {"2915": "52dD6ZlV1QaOpRBmbAqG1qkKnGzWMLj4eJq38Pgo"}, {"2916": "Nzp2OoJlqn6r1ZgvdA3BPL7abBwP5G4eE3RQmyxD"}, {"2917": "1JMYvnx2RzKEo4aWQ7DG6vkL8yZV3m9NBePXbrdj"}, {"2701": "zdQO8GwxDqjRgP4137YVD5ANyKlpem2nL65rvVJY"}, {"2702": "zrR51V2ajQ9ZLygPKkEMJakYDq38xOJolENBXGnv"}, {"2703": "WlVJBygjDZMeKX3vnAMRJR08NqdmG2x1Y69LQ4P5"}, {"2704": "5dBNwRp9graYJxZn409NKwklVov1b2QLPDqGm6XK"}, {"2720": "m6EYyZoJ4gWexdjVPAR56v7RDOq9wv2N5XzKGplr"}, {"2722": "JzwxZXOvDj1bVrN4nkW5pbA8qdyBl3MRKLpGPgaQ"}, {"2723": "2O14VBzl8aDmWdNw3A59VgAGyZ5qLJoEMpj6R9ng"}, {"2724": "OzNMgZ9n43qPbjXmy7zwlbA2DKdYvW5e6pxGRrVa"}, {"2733": "RO8rjaBDy21qPQJzW7om1L0pK3xmNleVZg9Ed4Gw"}, {"2741": "XMBbew5z4ELrZa2mRAd3ew78vPN6gy3DdVYlpKjq"}, {"2742": "JX1ObgmqGZ54DMyYL7aDOGkEVdve38WKRzwjNrQ9"}, {"2743": "RvmwNz8QPblKp41GD7lK1QkJrLVYoBO92dMegn6W"}, {"2769": "6lQGaY9RDywdVzObj0PaDWkPg4NBn3exEK51LWZq"}, {"2771": "B5EoxeMVp4zwr8nqW0GB6YARjvD1PNamOGbLg63Z"}, {"2772": "aw4eELG2DlPMdn1JW0BMYaAqQXOZRN3xB5yp8VKr"}, {"2773": "gRoJEyXVx4qD9er287L46Q7wBzGldaPjLWQKm3Mv"}, {"2774": "RO8rjaBDy21qPQJzW7omeL0pK3xmNleVZg9Ed4Gw"}, {"2775": "g9OxBZ5KRwNznlY6pAppe1AWXvjdEL4eGQobMDy2"}, {"2776": "DbQY6zyveZRwK5drV0Z8DJ7joE4XJM83N9xl2nWq"}, {"3354": "m6EYyZoJ4gWexdjVPAR5Bv7RDOq9wv2N5XzKGplr"}, {"2778": "JzwxZXOvDj1bVrN4nkW5DbA8qdyBl3MRKLpGPgaQ"}, {"2779": "gP1eOZVj3Q9lv5aDEk45KV7rdpqW8yLm2BbKzJxM"}, {"2780": "OzNMgZ9n43qPbjXmy7zwbbA2DKdYvW5e6pxGRrVa"}, {"2782": "2O14VBzl8aDmWdNw3A594gAGyZ5qLJoEMpj6R9ng"}, {"2785": "pE5X8NQPaow6vlOZxk6aBX0q42ezGBMyWgDVjR3L"}, {"2786": "o9vbeQlLMVg8j5dq4keLD40NxZpEmnXzwYKO1ar2"}, {"2790": "JX1ObgmqGZ54DMyYL7aDeGkEVdve38WKRzwjNrQ9"}, {"2792": "RvmwNz8QPblKp41GD7lKaQkJrLVYoBO92dMegn6W"}] \ No newline at end of file diff --git a/RVO21/databases/notifications.table b/RVO21/databases/notifications.table new file mode 100755 index 0000000..f7c96cb --- /dev/null +++ b/RVO21/databases/notifications.table @@ -0,0 +1,41 @@ +key:string|weight:string|sk:string|en:string ++|switching_profile_point_applied_to_line|INFORMATIONAL|Aplikovaný bod spínacieho profilu na línií č. ${line} : ${value}|Switching profile point applied to line no. ${line} : ${value}|............... ++|dusk_has_occured|INFORMATIONAL|Nastal súmrak: ${value}|Dusk has occured: ${value}|............... ++|dawn_has_occured|INFORMATIONAL|Nastal úsvit: ${value}|Dawn has occured: ${value}|............... ++|dimming_profile_was_successfully_received_by_node|NOTICE|Stmievací profil bol úspešne prijatý nodom č. ${node}|Dimming profile was successfully received by node no. ${node}|............... ++|master_node_is_responding_again|NOTICE|Master node začal znovu odpovedať|Master node is responding again|............... ++|command_was_sent_from_terminal_interface|DEBUG|Z terminálu bol odoslaný príkaz|A command was sent from terminal interface|............... ++|master_node_is_not_responding|ALERT|Master node neodpovedá|Master node is not responding|............... ++|configuration_of_dimming_profile_to_node_failed|ALERT|Konfigurácia stmievacieho profilu pre node č. ${node} zlyhala|Configuration of dimming profile to node no. ${node} has failed|............... ++|circuit_breaker_was_turned_on_line|NOTICE|Zapnutie ističa na línii č. ${line}|Circuit breaker was turned on - line no. ${line}|............... ++|circuit_breaker_was_turned_off_line|ERROR|Vypnutie ističa na línií č. ${line}|Circuit breaker was turned off - line no. ${line}|............... ++|dimming_profile_was_processed_for_node|INFORMATIONAL|Stmievací profil bol spracovaný pre node č. ${node}|Dimming profile was processed for node no. ${node}|............... ++|switching_profile_was_processed_for_line|INFORMATIONAL|Spínací profil bol spracovaný pre líniu č. ${line}|Switching profile was processed for line no. ${line}|............... ++|thermometer_is_not_responding|WARNING|Teplomer neodpovedá|Thermometer is not responding|............... ++|thermometer_is_responding_again|NOTICE|Teplomer znovu odpovedá|Thermometer is responding again|............... ++|thermometer_sends_invalid_data|WARNING|Teplomer posiela neplatné hodnoty|Thermometer sends invalid data|............... ++|main_switch_has_been_turned_off|CRITICAL|Hlavný vypínač bol vypnutý|Main switch has been turned off|............... ++|main_switch_has_been_turned_on|NOTICE|Hlavný vypínač bol zapnutý|Main switch has been turned on|............... ++|power_supply_has_disconnected_input|ALERT|Napájací zdroj nemá napätie na vstupe|Power supply has disconnected input|............... ++|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_main_open|NOTICE|Hlavné dvere boli otvorené|Main door has been opened|............... ++|door_em_open|NOTICE|Dvere silovej časti boli otvorené|Power door has been opened|............... ++|door_main_open_without_permission|WARNING|Hlavné dvere boli otvorené bez povolenia - zapnutá siréna|Main door has been opened without permission - alarm is on|............... ++|door_em_open_without_permission|WARNING|Dvere silovej časti boli otvorené bez povolenia|Power door has been opened without permission|............... ++|door_main_close|NOTICE|Hlavné dvere boli zatvorené|Main door has been closed|............... ++|door_em_close|NOTICE|Dvere silovej časti boli zatvorené|Power door has been closed|............... ++|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|............... ++|electrometer_ok|NOTICE|Elektromer znovu odpovedá|Electrometer is responding again|............... ++|no_voltage_on_phase|CRITICAL|Na fáze č. ${phase} nie je napätie|No voltage detected on phase no. ${phase}|............... ++|voltage_on_phase_restored|NOTICE|Napätie na fáze č. ${phase} bolo obnovené|Voltage on phase no. ${phase} has been restored|............... ++|flow_start|NOTICE|FLOW bol spustený|FLOW has been started |............... ++|twilight_sensor_nok|ERROR|Sensor súmraku neodpovedá|Twilight sensor is not responding|............... ++|twilight_sensor_ok|NOTICE|Sensor súmraku znovu odpovedá|Twilight sensor is responding again|............... ++|lamps_have_turned_on|NOTICE|Lampy sa zapli|Lamps have turned on|............... ++|lamps_have_turned_off|NOTICE|Lampy sa vypli|Lamps have turned off|............... ++|flow_restart|NOTICE|FLOW bol reštartovaný|FLOW has been restarted|............... ++|nodes_db_changed|NOTICE|Zmena v node databáze|Node db has changed|............... diff --git a/RVO21/databases/pins.table b/RVO21/databases/pins.table new file mode 100755 index 0000000..0eb3d05 --- /dev/null +++ b/RVO21/databases/pins.table @@ -0,0 +1,14 @@ +pin:string|type:string|line:number +*|input1_01|door_condition|0|........... +*|input1_02|rotary_switch_state|0|........... +*|input1_03|rotary_switch_state|0|........... +*|input1_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/RVO21/databases/relays.table b/RVO21/databases/relays.table new file mode 100755 index 0000000..f6c34a0 --- /dev/null +++ b/RVO21/databases/relays.table @@ -0,0 +1,5 @@ +line:number|tbname:string|contactor:number|profile:string ++|0|ZmRwd93QL4gaezxEbAxWvw71prn2XjlPvGyqJ6BO|1||........... ++|3|5dBNwRp9graYJxZn409N3wklVov1b2QLPDqGm6XK|9|{"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}|.......................................................................................................................................................................................................................................................................................................................................................................................................................................... ++|1|gYbDLqlyZVoRerQpB72M18kWJnwM5z24POKa8Exj|9|{"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|zdQO8GwxDqjRgP4137YVp5ANyKlpem2nL65rvVJY|9|{"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}|....................................................................................................................................................................................................................................................................................................................................................................................... diff --git a/RVO21/databases/settings.table b/RVO21/databases/settings.table new file mode 100755 index 0000000..576e6f9 --- /dev/null +++ b/RVO21/databases/settings.table @@ -0,0 +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|project_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|cloud_topic:string|has_main_switch:boolean|daily_report:boolean|send_changed_node_numbers:boolean ++|rvo_senica_21_ip115|en|28.7F6E9C0E0000|48.70826502|17.28455203|192.168.252.1|rvo_senica_21_ip115|Io3I1Fo1RdqGHaLGtRwJ|1883|0|56|unipi|ttyUSB0|1|20|5|6|3|u115|0|1|1|................................................... diff --git a/RVO21/databases/tbdata.nosql b/RVO21/databases/tbdata.nosql new file mode 100755 index 0000000..824c608 --- /dev/null +++ b/RVO21/databases/tbdata.nosql @@ -0,0 +1,4 @@ +-"ZmRwd93QL4gaezxEbAxWvw71prn2XjlPvGyqJ6BO":[{"ts":1760535295415,"values":{"_event":{"type":"notice","status":"new","source":{"func":"modbus_reader","component":"1699965957410","component_name":"Modbus reader","edge":"ZmRwd93QL4gaezxEbAxWvw71prn2XjlPvGyqJ6BO"},"message":{"sk":"rvo_senica_21_ip115: FLOW bol reštartovaný","en":"rvo_senica_21_ip115: FLOW has been restarted"},"message_data":""}}}],"id":"3000395001sc71b"} +-"ZmRwd93QL4gaezxEbAxWvw71prn2XjlPvGyqJ6BO":[{"ts":1760535295514,"values":{"edge_fw_version":"2025-10-08","maintenance_mode":false}}],"id":"3000395002sc70b"} +-"ZmRwd93QL4gaezxEbAxWvw71prn2XjlPvGyqJ6BO":[{"ts":1760535295526,"values":{"statecode":2,"power_mode":"Automatic"}}],"id":"3000395004sc70b"} +-"ZmRwd93QL4gaezxEbAxWvw71prn2XjlPvGyqJ6BO":[{"ts":1760535295569,"values":{"_event":{"type":"notice","status":"new","source":{"func":"rsPort.open()","component":"1699963668903","component_name":"DIDO_Controller","edge":"ZmRwd93QL4gaezxEbAxWvw71prn2XjlPvGyqJ6BO"},"message":{"sk":"rvo_senica_21_ip115: FLOW bol spustený","en":"rvo_senica_21_ip115: FLOW has been started "},"message_data":""}}}],"id":"3000395006sc70b"} diff --git a/RVO21/databases/tbdatacloud.nosql b/RVO21/databases/tbdatacloud.nosql new file mode 100755 index 0000000..817dba6 --- /dev/null +++ b/RVO21/databases/tbdatacloud.nosql @@ -0,0 +1,3 @@ +-"ZmRwd93QL4gaezxEbAxWvw71prn2XjlPvGyqJ6BO":[{"ts":1760535295514,"values":{"edge_fw_version":"2025-10-08","maintenance_mode":false}}],"id":"3000395003sc71b"} +-"ZmRwd93QL4gaezxEbAxWvw71prn2XjlPvGyqJ6BO":[{"ts":1760535295526,"values":{"statecode":2,"power_mode":"Automatic"}}],"id":"3000395005sc71b"} +-"ZmRwd93QL4gaezxEbAxWvw71prn2XjlPvGyqJ6BO":[{"ts":1760535295569,"values":{"_event":{"type":"notice","status":"new","source":{"func":"rsPort.open()","component":"1699963668903","component_name":"DIDO_Controller","edge":"ZmRwd93QL4gaezxEbAxWvw71prn2XjlPvGyqJ6BO"},"message":{"sk":"rvo_senica_21_ip115: FLOW bol spustený","en":"rvo_senica_21_ip115: FLOW has been started "},"message_data":""}}}],"id":"3000395007sc71b"} diff --git a/RVO21/databases/total_energy.js b/RVO21/databases/total_energy.js new file mode 100755 index 0000000..dde340e --- /dev/null +++ b/RVO21/databases/total_energy.js @@ -0,0 +1,38 @@ +//key is rvo_number, value is max energy when lamps are on +const total_energy = { + 1: 580, + 2: 1100, + 3: 3700, + 4: 4100, + 7: 360, + 12: 1700, + 13: 5400, + 14: 440, + 15: 6100, + 16: 4800, + 20: 1600, + 21: 1000, + 22: 2600, + 23: 1000, + 25: 2600, + 33: 240, + 34: 4000, + 35: 2700, + 36: 820, + 37: 1400, + 35: 3500, + 39: 1170, + 41: 740, + 42: 660, + 43: 4900, + 45: 930, + 46: 700, + 47: 1100, + 48: 1500, + 50: 3200, + 53: 1250, + 55: 1000, + 56: 5500 +} + +module.exports = total_energy; diff --git a/RVO21/debug.js b/RVO21/debug.js new file mode 100755 index 0000000..9818194 --- /dev/null +++ b/RVO21/debug.js @@ -0,0 +1,16 @@ +// =================================================== +// FOR DEVELOPMENT +// Total.js - framework for Node.js platform +// https://www.totaljs.com +// =================================================== + +const options = {}; + +// options.ip = '127.0.0.1'; +// options.port = parseInt(process.argv[2]); +// options.config = { name: 'Total.js' }; +// options.sleep = 3000; +// options.inspector = 9229; +// options.watch = ['private']; + +require('total.js/debug')(options); \ No newline at end of file diff --git a/RVO21/err.txt b/RVO21/err.txt new file mode 100755 index 0000000..1d7ef39 --- /dev/null +++ b/RVO21/err.txt @@ -0,0 +1,33 @@ +[2025-09-23T14:08:42.426] [ERROR] errLogs - uncaughtException: Cannot read property 'getHours' of undefined +[2025-09-23T14:08:42.429] [ERROR] errLogs - TypeError: Cannot read property 'getHours' of undefined + at Timeout.emptyReportToSend [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:08:42.430] [ERROR] errLogs - uncaughtException: Cannot read property 'getHours' of undefined +[2025-09-23T14:08:42.431] [ERROR] errLogs - TypeError: Cannot read property 'getHours' of undefined + at Timeout.emptyReportToSend [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:08:42.445] [ERROR] errLogs - uncaughtException: Cannot read property 'getHours' of undefined +[2025-09-23T14:08:42.445] [ERROR] errLogs - TypeError: Cannot read property 'getHours' of undefined + at Timeout.emptyReportToSend [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:08:48.170] [ERROR] errLogs - uncaughtException: date.getHours is not a function +[2025-09-23T14:08:48.171] [ERROR] errLogs - TypeError: date.getHours is not a function + at emptyReportToSend (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at Timeout.dailyReportCheck [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1351:5) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:08:48.172] [ERROR] errLogs - uncaughtException: date.getHours is not a function +[2025-09-23T14:08:48.172] [ERROR] errLogs - TypeError: date.getHours is not a function + at emptyReportToSend (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at Timeout.dailyReportCheck [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1351:5) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:08:48.177] [ERROR] errLogs - uncaughtException: date.getHours is not a function +[2025-09-23T14:08:48.177] [ERROR] errLogs - TypeError: date.getHours is not a function + at emptyReportToSend (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at Timeout.dailyReportCheck [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1351:5) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) diff --git a/RVO21/flow/cloudmqttconnect.js b/RVO21/flow/cloudmqttconnect.js new file mode 100755 index 0000000..b03491f --- /dev/null +++ b/RVO21/flow/cloudmqttconnect.js @@ -0,0 +1,357 @@ +exports.id = 'cloudmqttconnect'; +exports.title = 'Cloud connect mqtt'; +exports.group = 'MQTT'; +exports.color = '#888600'; +exports.version = '1.0.2'; +exports.icon = 'sign-out'; +exports.input = 2; +exports.output = 2; +exports.options = { host: 'tb-stage.worksys.io', port: 1883, clientid: "", username: "" }; + +exports.html = `
+
+
+
Hostname or IP address (if not empty - setting will override db setting)
+
+
+
Port
+
+
+
+
+
@(Client id)
+
+
+
topic
+
+
+
`; + + + +const { promisifyBuilder } = require('./helper/db_helper'); +const fs = require('fs'); +const mqtt = require('mqtt'); +const nosql = NOSQL('tbdatacloud'); + +const SEND_TO = { + debug: 0, + rpcCall: 1, +} + +//CONFIG +let saveTelemetryOnError = true;//backup_on_failure overrides this value +//------------------------ + +const noSqlFileSizeLimit = 4194304;//use 5MB - 4194304 +let insertNoSqlCounter = 0; +let insertBackupNoSqlCounter = 0; +let processingData = false; + +let backup_on_failure = true;//== saveTelemetryOnError - create backup client send failure +let restore_from_backup = 50; //how many rows process at once? +let restore_backup_wait = 3;//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; + + +exports.install = function(instance) { + + var client; + var opts; + var clientReady = false; + + let o = {}; //options + + function main() { + loadSettings(); + } + + //set opts according to db settings + function loadSettings() { + + o = instance.options; + if (!o.topic) o.topic = FLOW.GLOBALS.settings.cloud_topic; + + opts = { + host: o.host, + port: o.port, + clientId: o.clientid, + username: o.username, + rejectUnauthorized: false, + resubscribe: false + }; + + console.log("wsmqttpublich -> loadSettings from instance.options", o); + + if (!o.topic) { + instance.status("Not configured", "white"); + console.log("Cloud mqtt connect: no topic selected"); + return; + } + + connectToTbServer(); + } + + function connectToTbServer() { + var url = "mqtt://" + opts.host + ":" + opts.port; + console.log("MQTT URL: ", url); + + client = mqtt.connect(url, opts); + + client.on('connect', function() { + client.subscribe(`${o.topic}_backward`, (err) => { + if (!err) { + console.log("MQTT subscribed"); + } + }); + instance.status("Connected", "green"); + clientReady = true; + sendClientError = true; + }); + + client.on('reconnect', function() { + instance.status("Reconnecting", "yellow"); + clientReady = false; + }); + + client.on('message', function(topic, message) { + // message is type of buffer + message = message.toString(); + if (message[0] === '{') { + TRY(function() { + + message = JSON.parse(message); + if (message.hasOwnProperty("device") && message.hasOwnProperty("data") && message.data.hasOwnProperty("id")) { + client.publish(`${o.topic}_forward`, `{"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 } }); + } + + }, () => instance.debug('MQTT: Error parsing data', message)); + } + + instance.send(SEND_TO.rpcCall, { "topic": o.topic, "content": message }); + }); + + client.on('close', function() { + clientReady = false; + + instance.status("Disconnected", "red"); + instance.send(SEND_TO.debug, { "message": "Client CLOSE signal received !" }); + }); + + client.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) { + console.log('MQTT client error', err); + sendClientError = false; + } + clientReady = false; + }); + + } + + + instance.on('0', function(data) { + + if (clientReady) { + //do we have some data in backup file? if any, process data from database + if (saveTelemetryOnError) { + //read telemetry data and send back to server + if (!processingData) processDataFromDatabase(); + } + + let stringifiedJson = JSON.stringify(data.data) + client.publish(`${o.topic}_forward`, stringifiedJson, { qos: 1 }); + } + 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 (saveTelemetryOnError && o.topic) { + //create new file from tbdata.nosql, if file size exceeds given limit, and clear tbdata.nosql + makeBackupFromDbFile(); + + //write to tb + data.data.id = UID(); + nosql.insert(data.data); + } + } + }); + + instance.on("1", _ => { + main(); + }) + + instance.close = function(done) { + if (clientReady) { + client.end(); + } + }; + + + function getDbBackupFileCounter(type) { + var files = fs.readdirSync(__dirname + "/../databases"); + + let counter = 0; + for (var i = 0; i < files.length; i++) { + + if (files[i] == "tbdatacloud.nosql") continue; + + if (files[i].endsWith(".nosql")) { + + let pos = files[i].indexOf("."); + if (pos > -1) { + + let fileCounter = counter; + let firstDigit = files[i].slice(0, pos); + + fileCounter = parseInt(firstDigit); + if (isNaN(fileCounter)) fileCounter = 0; + //console.log("getDbBackupFileCounter digit:", files[i], firstDigit, fileCounter, isNaN(fileCounter), type); + + if (type == "max") { + if (fileCounter > counter) { + counter = fileCounter; + } + } + else if (type == "min") { + if (counter == 0) counter = fileCounter; + + if (fileCounter < counter) { + counter = fileCounter; + } + } + } + } + + } + + if (type == "max") counter++; + + return counter; + } + + const makeBackupFromDbFile = async () => { + + if (!saveTelemetryOnError) return; + + //to avoid large file: tbdata.nosql + + //init value is 0! + if (insertNoSqlCounter > 0) { + --insertNoSqlCounter; + return; + } + + insertNoSqlCounter = 100; + + let source = __dirname + "/../databases/tbdatacloud.nosql"; + + var stats = fs.statSync(source); + var fileSizeInBytes = stats.size; + + if (fileSizeInBytes > noSqlFileSizeLimit) { + + let counter = 1; + counter = getDbBackupFileCounter("max"); + + let destination = __dirname + "/../databases/" + counter + "." + "tbdatacloud.nosql"; + + //make backup file + fs.copyFileSync(source, destination); + //fs.renameSync(p, p + "." + counter); + + //clear tbdata.nosql + fs.writeFileSync(source, ""); + fs.truncateSync(source, 0); + + } + } + + const processDataFromDatabase = async () => { + + if (restore_from_backup <= 0) return; + + //calculate diff + const now = new Date(); + let currentTime = now.getTime(); + let diff = currentTime - lastRestoreTime; + + if ((diff / 1000) < restore_backup_wait) { + //console.log("*********restore_backup_wait", diff, restore_backup_wait); + return; + } + + processingData = true; + + //get filename to process + let counter = getDbBackupFileCounter("min"); + + //we have some backup files + let dataBase = 'tbdata'; + + var nosql; + if (counter == 0) dataBase = 'tbdatacloud'; + else dataBase = counter + "." + 'tbdatacloud'; + + nosql = NOSQL(dataBase); + + //select all data - use limit restore_from_backup + let records = await promisifyBuilder(nosql.find().take(restore_from_backup)); + + for (let i = 0; i < records.length; i++) { + if (clientReady) { + + let item = records[i]; + let id = item.id; + + if (id !== undefined) { + //console.log("------------processDataFromDatabase - remove", id, dataBase, i); + + try { + + let message = JSON.parse(JSON.stringify(item)); + delete message.id; + client.publish(`${o.topic}_forward`, JSON.stringify(message), { qos: 1 }); + + //remove from database + await promisifyBuilder(nosql.remove().where("id", id)); + + } catch (error) { + //process error + console.log("processDataFromDatabase", error); + } + + } + + } + else { + processingData = false; + return; + } + } + + if (records.length > 0) { + //clean backup file + if (counter > 0) nosql.clean(); + } + + //no data in db, remove + if (records.length == 0) { + if (counter > 0) nosql.drop(); + } + + const d = new Date(); + lastRestoreTime = d.getTime(); + + processingData = false; + + } + + instance.on('options', main); + +}; diff --git a/RVO21/flow/cmd_manager.js b/RVO21/flow/cmd_manager.js new file mode 100755 index 0000000..25912df --- /dev/null +++ b/RVO21/flow/cmd_manager.js @@ -0,0 +1,3071 @@ +exports.id = 'cmd_manager'; +exports.title = 'CMD Manager'; +exports.group = 'Worksys'; +exports.color = '#5D9CEC'; +exports.version = '0.0.3'; +exports.output = ['red', 'blue', 'yellow', 'blue', 'white', 'green']; +exports.input = 3; +exports.icon = 'cloud-upload'; + +exports.html = ` +
+
+
+
RPC - run RPC calls

+
+
+
@(User)
+
+
+
@(Password)
+
+
+
@(My edge)
+
+
+
+`; +exports.readme = `Manager for CMD calls`; + + +exports.install = function(instance) { + + 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, isEmptyObject, emptyJsObject, writeToFile, addToArrayIfUnique } = require('./helper/utils'); + const bitwise = require('bitwise'); + + var SunCalc = require('./helper/suncalc'); + const DataToTbHandler = require('./helper/DataToTbHandler'); + const errorHandler = require('./helper/ErrorToServiceHandler'); + const { sendNotification } = require('./helper/notification_reporter'); + const process = require('process'); + const { errLogger, logger, monitor } = require('./helper/logger'); + + //for accelerometer purposes + const { naklony } = require("../databases/accelerometer_db"); + + const dbNodes = TABLE("nodes"); + const dbRelays = TABLE("relays"); + + let GLOBALS; + let SETTINGS; + let rsPort; + let tbHandler; + + // runTasks intervals + const SHORT_INTERVAL = 30; + const LONG_INTERVAL = 300; + + //send data to following instances: + const SEND_TO = { + debug: 0, + tb: 1, + http_response: 2, + dido_controller: 3, + infoSender: 4, + dailyReport: 5 + } + + 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 + } + + 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 sendNodeReadout = null; // interval for sending agregate data from node + + 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["1"] = minutes; // dimming + priorities["76"] = minutes; // power + + minutes = 5; + priorities["75"] = minutes; // current + priorities["79"] = minutes; // energy + priorities["87"] = minutes; // aktualny cas + //priorities["84"] = minutes; //accelerometer + + minutes = 10; + priorities["74"] = minutes; // voltage + priorities["77"] = minutes; // power factor + priorities["78"] = minutes; // frequency + + minutes = 60; + priorities["0"] = minutes; // statecode + priorities["6"] = minutes; // dusk + priorities["7"] = minutes; // dawn + priorities["8"] = minutes; // profile + + minutes = 60 * 24; + priorities["89"] = minutes; // verzia fw + priorities["80"] = minutes; // lifetime + + //prikazy kt sa budu spustat na dany node - see config.js in terminal-oms.app. (1 - dimming) + let listOfCommands = [0, 1, 6, 7, 8, 74, 75, 76, 77, 78, 79, 80, 87, 89]; + + 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; + + // holds dusk, dawn (and more) values + let sunCalcResult; + + //helper container for counting resolved group of commands (commands related to set profile) + let cmdCounter = {};//key is node, value is counter + + //TODO: is this set working?? According to previous checks, sets do not work + //if sending of profile to node fails, we send notification and push node into set, so we do not send notification twice + const nodeProfileSendFail = new Set(); + + //we expect to get current temperature in Senica from senica-prod01 + let temperatureInSenica = null; + let accelerometerInterval = null; + + //NOTE: daily reports senica: + //rvo_is_on status, we monitor all nodes - if true, power and dimming should be not 0, if false, 24/7 nodes should be 0, other rvo should not respond + let rvo_is_on; + let previous_rvo_is_on_value; + let handleDailyReport; //setInterval for dailyReportHandler function + let dailyReport = {}; //data needed for daily report + let reportToSend = {}; //final report which we send to cloud + let breakerCounter = null; // status of breakers after flow starts is not in report + let rvoPeriod; // interval of checking dusk dawn and if rvo_is_on + let initialReportStatus = false; + + const DAILY_REPORT_HANDLER_TIME = 3_600_000; + const SET_SUNCALC_RESULT_TIME = 3_600_000; + const SET_RVO_PERIOD_TIME = 300_000; + const ADD_NODE_TO_REPORT_TIME = 3_600_000; + + //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); + + let now = new Date(); + console.log("Cmd-mngr installed", now.toLocaleString("sk-SK")); + + sunCalcResult = calculateDuskDawn(); + + handleRsPort(); + + customTasksInterval = setInterval(reportEdgeDateTimeAndNumberOfLuminaires, 120_000); + setTimeout(reportEdgeDateTimeAndNumberOfLuminaires, 4000); + + //dailyReport related + emptyReportToSend(); + breakerCounter = Object.keys(relaysData).length - 1; // we get number of lines (breakers) except of line 0 + rvoPeriod = setInterval(setRvoPeriod, SET_RVO_PERIOD_TIME); + setTimeout(setRvoPeriod, 3000); + setInterval(setSunCalcResult, SET_SUNCALC_RESULT_TIME); + handleDailyReport = setInterval(dailyReportHandler, DAILY_REPORT_HANDLER_TIME); + + + setCorrectTime = setInterval(setCorrectPlcTimeOnceADay, 60000 * 60); // 1 hour + setCorrectPlcTimeOnceADay(); + + sendNodeReadout = setInterval(sendNodesData, 150_000); + accelerometerInterval = setInterval(accelerometerData, 60000 * 30); //30 min + } + + + 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" + //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 + // if node regular readout does not respond, we repeat request + params.repeatCounter = 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-mngr: 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.byte4 = 96; + params.recipient = 1; + params.register = 8; + params.rw = 1;//write + params.timestamp = timestamp; + 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.byte4 = 96; + params.recipient = 1; + params.register = 8; + params.rw = 1;//write + params.timestamp = timestamp; + 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). + */ + + 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.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.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 + { + + logger.debug("processNodeProfile: Threshold lux level for DUSK/DAWN", node); + + let params = getParams(); + params.type = "set_node_profile"; + params.address = node; + params.register = 96; + params.recipient = 1; + params.rw = 1;//write + params.timestamp = timestamp; + 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(); + params.type = "set_node_profile"; + params.address = node; + params.register = 97; + params.recipient = 1; + params.rw = 1;//write + params.timestamp = timestamp; + 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.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); + + 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); + + console.log("proces profile finished *********************") + } + + + 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; + }); + } + + + 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) { + for (let k in nodesData) { + 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`); + } + } + } + + + function loadRelaysData(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 (value.contactor == 1) processAllNodeProfilesOnLine(value.line); + } + } + + + function reportOnlineNodeStatus(line) { + //Po zapnutí línie broadcastovo aktualizovať predtým čas a o 3 sek neskor - status, brightness + + logger.debug("Cmd-mngr: ----->reportOnlineNodeStatus for line", line); + + const d = new Date(); + + // broadcast actual time + let params = getParams(); + params.address = 0xffffffff;//Broadcast + params.byte1 = d.getHours(); + params.byte2 = d.getMinutes(); + params.recipient = 2;//2 broadcast, address = 0 + params.register = 87;//Actual time + params.rw = 1;//write + params.type = "node-onetime-write"; + params.timestamp = d.getTime() + 30000; + params.info = "run broadcast: Actual time"; + //params.debug = true; + + tasks.push(params); + + let sec = 3; + setTimeout(function() { + //Po zapnutí línie - spraviť hromadný refresh stavu práve zapnutých svietidiel + + let time = Date.now(); + + for (let k in nodesData) { + + //potrebujem nody k danej linii + 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].node_status_before_offline === true || nodesData[k].status === true) { + status = "OK"; + nodesData[k].time_of_last_communication = time; + } + + nodesData[k].readout.status = status; + + updateNodeStatus(k, status === "OK" ? true : false); + if (nodesData[k].hasOwnProperty("node_status_before_offline")) delete nodesData[k].node_status_before_offline; + sendTelemetry({ status: status }, tbname, time); + + //vyreportovanie dimming, current, input power pre liniu pre vsetky nody + //Prud + { + let params = getParams(); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 75;//prud + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = time + 4000; + params.info = 'read current'; + //params.debug = true; + tasks.push(params); + } + + //vykon + { + let params = getParams(); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 76;//výkon + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = time + 4100; + params.info = 'read power'; + //params.debug = true; + + tasks.push(params); + } + //dimming + { + let params = getParams(); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 1;//dimming + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = time + 4200; + params.info = 'read dimming'; + //params.debug = true; + + tasks.push(params); + } + + } + } + + }, sec * 1000); + } + + + function reportOfflineNodeStatus(line) { + + logger.info("Cmd-mngr: ------>reportOffLineNodeStatus for line ", line); + + values = {}; + values["dimming"] = 0;//brightness + values["power"] = 0;//výkon + values["current"] = 0;//prúd + values["status"] = "OFFLINE"; + + const date = Date.now(); + + Object.keys(nodesData).forEach(node => { + + //potrebujem nody k danej linii + if (line == nodesData[node].line || line == undefined) { + + let tbname = nodesData[node].tbname; + let nodeStatus = nodesData[node].status; + + //in case we have reported offline node status, we return (continue with next node) + if (nodeStatus === "OFFLINE") return; + + nodesData[node].node_status_before_offline = nodeStatus; + nodesData[node].status = "OFFLINE"; + nodesData[node].readout = {}; + + sendTelemetry({ ...values }, tbname, date); + } + }); + + } + + + function turnLine(onOrOff, line, info) { + let obj = { + line: line, + command: onOrOff, + info: info + }; + + //to assure, handleDailyReportFunction do not run before rvo_is_on variable changes. So after every line switch we reset the timer + clearInterval(handleDailyReport); + handleDailyReport = setInterval(dailyReportHandler, DAILY_REPORT_HANDLER_TIME); + + //logger.debug("linia", line, obj); + instance.send(SEND_TO.dido_controller, obj); + } + + + 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"; + 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]) { + //CRC_ERROR + message = "NOK"; + error = "CRC_ERROR c1"; + instance.send(SEND_TO.debug, "CRC_ERROR c1"); + } + + 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") { + instance.send(SEND_TO.debug, bytes); + instance.send(SEND_TO.debug, "RESPONSE " + type + " - " + bytes[4]); + + //logger.debug(SEND_TO.debug, "RESPONSE " + type + " - " + bytes[4], bytes); + + error = "type is: " + type; + + message = "NOK"; + } + + return { message, type, error }; + } + + + //BUILD TASKS// + function buildTasks(params) { + + //return; + console.log("buidTAaasks start ****************", params); + monitor.info("buildTasks - params", params); + + let processLine; //defined line + let init = false; + let processLineProfiles = true; + let processBroadcast = true; + let processNodes = true; + + if (params == undefined) { + init = true; + tasks = []; + logger.debug("-->buildTasks clear tasks"); + } + else { + processLineProfiles = params.processLineProfiles; + processBroadcast = false; + processNodes = false; + + processLine = params.line; + } + + let now = new Date(); + + //process line profiles + if (processLineProfiles) { + + let keys = Object.keys(relaysData); + + for (let i = 0; i < keys.length; i++) { + + let line = parseInt(keys[i]); + let profilestr = relaysData[line].profile; + + if (processLine != undefined) { + if (processLine != line) continue; + } + + try { + + /** + * we process line profiles: timepoints, astro clock, lux_sensor, offsets ... + */ + if (profilestr === "") throw ("Profile is not defined"); + let profile = JSON.parse(profilestr); + 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; + + // add name to regular profile timepoint and delete unused end_time key: + time_points.forEach(point => { + point.name = "profileTimepoint" + delete point.end_time; + }); + + //monitor.info("buildTasks: time_points", time_points); + + + /** + * 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 astro clock true, we remove all regular profile points + time_points = []; + + //TODO: when astro clock == true, is offset calculated ??? + //let duskAstroClockOffset = profile.dusk_astro_clock_offset; + //let dawnAstroClockOffset = profile.dawn_astro_clock_offset; + //console.log("line astro clock offsets dusk a dawn: ", duskAstroClockOffset, dawnAstroClockOffset); + // maybe add dusk dawn offset to calculateDuskDawn ?? what dusk dawn will be if dawn_lux_sensor == true?? + //let sunCalcResult = calculateDuskDawn(new Date(), line, duskAstroClockOffset, dawnAstroClockOffset); + + 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 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); + + 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); + + 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(':'); + + let ad = new Date(); + ad.setHours(parseInt(ahours), parseInt(aminutes), 0); + + let bd = new Date(); + bd.setHours(parseInt(bhours), parseInt(bminutes), 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++) { + + let start_time = new Date(); + let [hours, minutes] = time_points[t].start_time.split(':'); + start_time.setHours(parseInt(hours), parseInt(minutes), 0); + + //task is in 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(); + params.type = "relay"; + params.line = parseInt(line); + params.value = time_points[t].value; + params.tbname = relaysData[line].tbname; + params.timestamp = start_time.getTime(); + + // 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; + + //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)) { + 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; + + params.debug = true; + + //turn on/off line + tasks.push(params); + monitor.info("TimePoint params: ", params.info, start_time); + } + + monitor.info("-->time_points final", line, time_points); + + //ensure to turn on/off according to calculated currentValue + let params = getParams(); + params.type = "relay"; + params.line = parseInt(line); + params.tbname = relaysData[line].tbname; + params.value = currentValue; + params.timestamp = i; + params.debug = true; + + //logger.debug(now.toLocaleString("sk-SK")); + 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; + + tasks.push(params); + + } catch (error) { + if (profilestr !== "") { + //errLogger.error(profilestr, error); + console.log(`Cmd_mngr: Unable to process line profile ${line}. Error: `, error); + errorHandler.sendMessageToService(profilestr + "-" + error, 0, "js_error"); + } else { + turnLine("off", line, "No line profile. Switching it off on startup"); + } + } + + } + //logger.debug("tasks:"); + //logger.debug(tasks); + } + + + //NOTE: PROCESS DEFAULT BROADCASTS - Time of dusk, Time of dawn, Actual Time + if (processBroadcast) { + + let d = new Date(); + let time = d.getTime(); + //let sunCalcResult = calculateDuskDawn(); + + { + let params = getParams(); + + params.address = 0xffffffff;//broadcast + params.byte1 = sunCalcResult["dusk_hours"]; + params.byte2 = sunCalcResult["dusk_minutes"]; + params.recipient = 2;//2 broadcast, + params.register = 6;//Time of dusk + params.rw = 1;//write + params.type = "node-regular-write"; + params.timestamp = time + 60000; + params.addMinutesToTimestamp = 60 * 3; //kazde 3 hodiny zisti novy dusk + params.info = "Broadcast-duskTime"; + + tasks.push(params); + } + + { + let params = getParams(); + + params.address = 0xffffffff;//broadcast + params.byte1 = sunCalcResult["dawn_hours"]; + params.byte2 = sunCalcResult["dawn_minutes"]; + params.recipient = 2; //2 broadcast + params.register = 7;//Time of dawn + params.rw = 1;//write + params.type = "node-regular-write"; + params.timestamp = time + 60001; + params.addMinutesToTimestamp = 60 * 3; //kazde 3 hodiny zisti novy dawn + params.info = "Broadcast-dawnTime"; + + tasks.push(params); + } + + { + let params = getParams(); + + params.address = 0xffffffff;//broadcast + params.byte1 = d.getHours(); + params.byte2 = d.getMinutes(); + params.recipient = 2; //2 broadcast + params.register = 87;//Actual time + params.rw = 1;//write + params.type = "node-regular-write"; + params.timestamp = time + 60002; + params.addMinutesToTimestamp = 5; + params.info = "run broadcast: Actual time"; + + tasks.push(params); + } + + } + + //process nodes & tasks - read node's data + if (processNodes) { + + let time = Date.now(); + + for (let k in nodesData) { + let address = parseInt(k); + let tbname = nodesData[k].tbname; + let register = 0; + + for (let i = 0; i < listOfCommands.length; i++) { + + register = listOfCommands[i]; + let addMinutesToTimestamp = priorities[register]; + + let params = getParams(); + + params.address = address; + params.recipient = 1; + params.register = register; + params.type = register == 1 ? "node-dimming-read" : "node-regular-read"; + params.tbname = tbname; + params.timestamp = time + 5000 + i * 500 + addMinutesToTimestamp * 1000; //to make slight time difference + params.addMinutesToTimestamp = addMinutesToTimestamp; + params.info = "Node regular read command"; + + tasks.push(params); + } + + } + } + + + //niektore ulohy sa vygeneruju iba 1x pri starte!!! + if (!init) return; + + + //Master node FW version - modifies SETTINGS.masterNodeIsResponding + { + let params = getParams(); + params.type = "cmd-master"; + params.register = 4; + params.address = 0; + params.timestamp = 0; + params.addMinutesToTimestamp = 5; + params.tbname = SETTINGS.rvoTbName; + params.info = "Master node FW verzia"; + //params.debug = true; + + tasks.push(params); + } + + //kazdu hodinu skontrolovat nastavenie profilov + { + let params = getParams(); + params.type = "process_profiles"; + params.timestamp = Date.now() + 60001; + params.addMinutesToTimestamp = 60;//60 = every hour + params.info = "detekcia nespracovaných profilov linie a nodov"; + //params.debug = true; + + tasks.push(params); + } + + monitor.info("tasks created:", tasks.length); + } + + + /** + * We process line profile, where "astro_clock": true + * example profile: + * + "dawn_lux_sensor": true, + "dusk_lux_sensor": true, + "dawn_lux_sensor_value": 5, + "dusk_lux_sensor_value": 5, + "dawn_astro_clock_offset": 0, + "dusk_astro_clock_offset": 10, + "dawn_lux_sensor_time_window": 30, + "dusk_lux_sensor_time_window": 30, + "dawn_astro_clock_time_window": 60, + "dusk_astro_clock_time_window": 60 + + * if dawn: if currentTimestamp is in timewindow "dawnTime + and - dawn_lux_sensor_time_window" and lux value >= lux_sensor_value, we switch off the line. + * if dusk: we do oposite + * + * dawn: usvit - lux je nad hranicou - vypnem + * dusk: sumrak - lux je pod hranicou - zapnem + */ + 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++) { + + let line = keys[i]; //line is turned off by default + let profilestr = relaysData[line].profile; + const contactor = relaysData[line].contactor; + + try { + + let profile = JSON.parse(profilestr); + if (Object.keys(profile).length === 0) throw ("turnOnOffLinesAccordingToLuxSensor - profile is not defined"); + + 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 (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"); + } + } + } + + //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 (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"); + } + } + } + + } + + } catch (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) { + //MASTER + if (node == 0) return; + + let nodeObj = nodesData[node]; + if (nodeObj == undefined) return; + + let nodeCurrentStatus = nodeObj.status; + const now = Date.now(); + + let data = null; + + if (nodeCurrentStatus === "OFFLINE") { + data = { status: newStatus }; + nodeDbStatusModify(node, data); + return; + } + else 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; + } + + } + + + 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 }; + } + }); + }); + } + + + function processDailyReport() { + + const now = Date.now(); + + for (const [key, value] of Object.entries(dailyReport)) { + + if (["name", "time", "dusk_and_dawn"].includes(key)) continue; + + let poleNumber = nodesData[key]["pole_number"]; + let line = dailyReport[key].line; + let nodeType = nodesData[key]["node_type"]; + let fullNodeName = key // key == nodeNumber + + if (poleNumber && nodeType) { + fullNodeName = SETTINGS.rvo_number + "/" + poleNumber + "_" + line + "L_" + key + "_" + nodeType; + } else { + fullNodeName = key; + } + + if (rvo_is_on) { + + if (value.initialTs) { + if (value.initialTs + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["night_no_data"], fullNodeName); + console.log('report nedostava ziadne data uz hodinu', fullNodeName); + value.initialTs = now; + } + } + if (value.dimmingIsZeroTime) { + if (value.dimmingIsZeroTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["night_dimming=0"], fullNodeName); + console.log("report node dimming je 0 ale ma svietit", fullNodeName); + value.dimmingIsZeroTime = now; + } + } + if (value.powerIsZeroTime) { + if (value.powerIsZeroTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["night_power=0"], fullNodeName); + console.log("report node power je 0 ale ma svietit", fullNodeName); + value.powerIsZeroTime = now; + } + } + + } else { + + let contactorStatus = relaysData[line].contactor; + if (contactorStatus === 1) { + + if (value.initialTs) { + if (value.initialTs + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["day_24/7_no_data"], fullNodeName); + console.log('node je na 24/7 ale nedostava ziadne data uz hodinu', fullNodeName); + value.initialTs = now; + } + } + if (value.dimmingIsOnButShouldBeOffTime) { + if (value.dimmingIsOnButShouldBeOffTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["day_24/7_dimming>0"], fullNodeName); + console.log("report dimming je > 0 ale nema svietit", fullNodeName); + value.dimmingIsOnButShouldBeOffTime = now; + } + } + if (value.powerIsOnButShouldBeOffTime) { + if (value.powerIsOnButShouldBeOffTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["day_24/7_power>0"], fullNodeName); + console.log("report power je > 0 ale nema svietit", fullNodeName); + value.powerIsOnButShouldBeOffTime = now; + } + } + + } + + } + + } + + let report = {}; + report["name"] = SETTINGS.rvo_name; + report["time"] = new Date(); + report["report"] = reportToSend; + + writeToFile(F.path.root("report_data.log"), report, true); + instance.send(SEND_TO.dailyReport, report); + } + + + function dailyReportHandler() { + + if (!SETTINGS.daily_report) return; + + // after dawn we empty reportToSend and start to get data for a new day + const date = new Date(); + const hour = date.getHours(); + const minute = date.getMinutes(); + + console.log("now: ", hour, minute, "suncalc: ", sunCalcResult.dawn_hours, sunCalcResult.dawn_minutes); + + if (hour === sunCalcResult.dawn_hours) { + + //NOTE: ak je este pred usvitom, spracujeme report a posleme na cloud, ak uz je po usvite, resetujeme report plnime data noveho dna + if (minute >= sunCalcResult.dawn_minutes - 2) { + emptyReportToSend(); + emptyDailyReport(); + console.log("Podmienka 1 v dailyReport handler"); + } else { + processDailyReport(); + emptyReportToSend(); + emptyDailyReport(); + console.log("Podmienka 2 v dailyReport handler"); + } + + initialReportStatus = true; + + // ak sa funkcia spusti o hodinu alebo 2 neskor, ako je usvit (moze sa to stat, kedze kazde zapnutie/vypnutie linii odznova spusti casovac. + } else if (hour === sunCalcResult.dawn_hours + 1 || hour === sunCalcResult.dawn_hours + 2) { + if (!initialReportStatus) { + emptyReportToSend(); + emptyDailyReport(); + initialReportStatus = true; + console.log("Podmienka 3 v dailyReport handler"); + } else { + processDailyReport(); + initialReportStatus = true; + console.log("Podmienka 4 v dailyReport handler"); + } + } else { + processDailyReport(); + initialReportStatus = false; + console.log("Podmienka 5 v dailyReport handler"); + } + + console.log("initialReportStatus: ", initialReportStatus); + + } + + function emptyReportToSend() { + emptyJsObject(reportToSend); + reportToSend["contactor"] = { off: [], on: [] }; + reportToSend["night_no_data"] = []; + reportToSend["night_dimming=0"] = []; + reportToSend["night_power=0"] = []; + reportToSend["day_24/7_no_data"] = []; + reportToSend["day_24/7_dimming>0"] = []; + reportToSend["day_24/7_power>0"] = []; + console.log(`resetuje sa reportToSend`); + } + + + //NOTE: ked je initialTs stale rovnaky a zistime ze linie su vypnute (relaysData.line.contactor) - zistim, ci je node na tej linii. Vieme, ze ak je linia vypnuta je to v poriadku lebo nie je na 24/7 linii + //ak je na 24/7 linii, reportujeme, ze neprijima data + function emptyDailyReport() { + const ts = Date.now(); + emptyJsObject(dailyReport); + + //NOTE: do dailyReport dame vsetky nody a pravidelne kontrolujeme ci maju data + //ked nastane sumrak/usvit a svetla maju zacat/prestat svietit, dailyReport spravime nanovo: + for (const [key, value] of Object.entries(nodesData)) { + dailyReport[value.node] = { line: value.line, initialTs: ts }; + } + + console.log("dailyReport: ", dailyReport); + } + + + async function runTasks() { + + clearInterval(interval); + + let currentTimestamp = Date.now(); + + //sort tasks based on timestamp + 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) { + instance.send(SEND_TO.debug, "no tasks created"); + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + if (!rsPort.isOpen) { + instance.send(SEND_TO.debug, "!rsPort.isOpen"); + //await rsPort.open(); + //console.log("Cmd-mngr: !rsPort.isOpen"); + } + + let currentTask = tasks[0]; + + if (currentTask.debug) { + //logger.debug("--->task to process", currentTask); + } + + if (currentTask.timestamp <= currentTimestamp) { + let params = { ...tasks[0] }; + + //allow terminal commands + if (SETTINGS.maintenance_mode && params.type !== "cmd-terminal") { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + let type = params.type; + let tbname = params.tbname; + let node = params.address; + let register = params.register; + let line = null; + let itIsNodeCommand; + + if (nodesData[node] !== undefined) { + line = nodesData[node].line; + itIsNodeCommand = true; + } + + if (params.line !== undefined) line = params.line; + + if (params.addMinutesToTimestamp > 0 || params.timePointName) { + tasks[0].timestamp = currentTimestamp + tasks[0].addMinutesToTimestamp * 60000; + } else { + tasks.shift(); + } + + //kontrola nespracovanych profilov nodov + //TODO: co ked niektore nody neprijimaju profily? kazdu hodinu zahltuju "tasks" array + if (type == "process_profiles") { + //na vsetky zapnutych liniach sa spracuju nespracovane profily nodov + loadRelaysData(); + interval = setInterval(runTasks, SHORT_INTERVAL); + return; + } + + //relay + if (type == "relay") { + + const timePointName = params.timePointName; + const value = params.value; + + let date = new Date(); + date.setDate(date.getDate() + 1);//next day + + let sunCalcResult; + if (timePointName) sunCalcResult = calculateDuskDawn(date, params.line); + + + if (timePointName == "dawn") { + tasks[0].timestamp = sunCalcResult.dawn_time; + } + else if (timePointName == "dusk") { + tasks[0].timestamp = sunCalcResult.dusk_time; + } + else if (timePointName == "luxOn") { + tasks[0].timestamp = sunCalcResult.dusk_time + params.dusk_lux_sensor_time_window * 60000; + } + else if (timePointName == "luxOff") { + tasks[0].timestamp = sunCalcResult.dawn_time + params.dawn_lux_sensor_time_window * 60000; + } + else if (timePointName == "profileTimepoint") { + tasks[0].timestamp = currentTimestamp + tasks[0].addMinutesToTimestamp * 60000; + } + + let info = "aplikovany bod profilu"; + let onOrOff = ""; + value == 1 ? onOrOff = "on" : onOrOff = "off"; + + turnLine(onOrOff, params.line, info); + + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + if (!SETTINGS.masterNodeIsResponding) { + //ak neodpoveda, nebudeme vykonavat ziadne commands, okrem cmd-terminal cmd-master + errorHandler.sendMessageToService("Master node is not responding"); + + let stop = true; + + if (type === "cmd-terminal" || type === "cmd-master") stop = false; + if (stop) { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + } + + let contactorStatus = 1; + if (relaysData[line] != undefined) contactorStatus = relaysData[line].contactor; + + if (line === 0 || contactorStatus === 0 || FLOW.deviceStatus.state_of_breaker[line] === "Off") { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + // TODO: -> status offline for rvo if rotary_switch_state is OFF, this is source of errors + // check if rotary_switch_state == "Off" + // state_of_braker: disconnected = true? + + if (!rsPort.isOpen) { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + //RE-CALCULATE VALUES + //set actual time for broadcast + if (register == 87 && params.recipient === 2) { + var d = new Date(); + params.byte1 = d.getHours();//h + params.byte2 = d.getMinutes();//m + } + + //SET DUSK/DAWN FOR BROADCAST + //Time of dusk + if (register == 6 && params.recipient === 2) { + + if (type != "cmd-terminal") { + params.byte1 = sunCalcResult["dusk_hours"];//h + params.byte2 = sunCalcResult["dusk_minutes"];//m + } + } + + //Time of dawn + if (register == 7 && params.recipient === 2) { + if (type != "cmd-terminal") { + params.byte1 = sunCalcResult["dawn_hours"];//h + params.byte2 = sunCalcResult["dawn_minutes"];//m + } + } + //----------------------- + + instance.send(SEND_TO.debug, "address: " + node + " register:" + register + "type: " + type); + + var startTime, endTime; + startTime = new Date(); + + let saveToTb = true; + if (!tbname) saveToTb = false; + + let resp = com_generic(node, params.recipient, params.rw, register, params.name, params.byte1, params.byte2, params.byte3, params.byte4); + let readBytes = 11; + let timeout = 4000; + + + // await keyword is important, otherwise incorrect data is returned! + await writeData(rsPort, resp, readBytes, timeout).then(function(data) { + + //sometimes happens, that status of node changes to OK, NOK even if line was turned off and should be status OFFLINE. To prevent this, we return if line contactor is 0: + if (itIsNodeCommand && line && relaysData[line].contactor !== 1) return; + + 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); + + //ak sa odpoved zacina 0 - je to v poriadku, inak je NOK + let message = result.message; // OK, NOK + let message_type = result.type; + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + console.log("detected response:", result); + logger.debug("Cmd-mngr: writeData done " + message_type + " duration: " + timeDiff + " type: " + params.debug, params, result); + } + } + + let values = {}; + + //CMD FINISHED + if (message == "OK") { + + updateNodeStatus(node, true); + + //write + if (type == "set_node_profile") { + let result = cmdCounterResolve(node); + if (result == 0) { + dbNodes.modify({ processed: true }).where("node", node).make(function(builder) { + builder.callback(function(err, response) { + + sendNotification("Cmd-mngr: process cmd", SETTINGS.rvoTbName, "dimming_profile_was_successfully_received_by_node", { node: node }, "", SEND_TO.tb, instance); + + logger.debug("--> profil úspešne odoslaný na node č. " + node); + nodesData[node].processed = true; + nodeProfileSendFail.delete(node); + }); + }); + } + } + + //parse read response + if (params.rw == 0) { + values = processResponse(register, dataBytes); //read + } + + if (itIsNodeCommand) { + values.comm_status = "OK"; + values.status = "OK"; + nodesData[node].readout = { ...nodesData[node].readout, ...values }; + + + if (SETTINGS.daily_report) { + //TODO: co ak nedostavame odpovede z nodu ? Musime vyreportovat!! + //v dailyReport teda musi byt kompletny zoznam nodov a neustale kontrolovat, ci maju data, ak nie report node - neodpoveda + if (register === 1) { + + let now = Date.now(); + + if (rvo_is_on === true) { + + if ("dimmingIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].dimmingIsOnButShouldBeOffTime; + + if (values.dimming > 0) { + if ("dimmingIsZeroTime" in dailyReport[node]) delete dailyReport[node].dimmingIsZeroTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if (!("dimmingIsZeroTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], dimmingIsZeroTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } else { + + if ("dimmingIsZeroTime" in dailyReport[node]) delete dailyReport[node].dimmingIsZeroTime; + + if (values.dimming > 0) { + if (!("dimmingIsOnButShouldBeOffTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], dimmingIsOnButShouldBeOffTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if ("dimmingIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].dimmingIsOnButShouldBeOffTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } + } + + if (register === 76) { + + let now = Date.now(); + + if (rvo_is_on === true) { + + if ("powerIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].powerIsOnButShouldBeOffTime; + + if (values.power > 1) { + if ("powerIsZeroTime" in dailyReport[node]) delete dailyReport[node].powerIsZeroTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if (!("powerIsZeroTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], powerIsZeroTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } else { + + if ("powerIsZeroTime" in dailyReport[node]) delete dailyReport[node].powerIsZeroTime; + + if (values.power > 1) { + if (!("powerIsOnButShouldBeOffTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], powerIsOnButShouldBeOffTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if ("powerIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].powerIsOnButShouldBeOffTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } + } + } + + } + + //master node + if (node == 0) { + sendNotification("Cmd-mngr: 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; + } + + if (params.debug) { + //logger.debug("saveToTb", saveToTb, tbname, values); + } + + if (saveToTb && type != "node-regular-read") { + sendTelemetry(values, tbname); + } + else { + if (type == "cmd-terminal") { + terminalCommandResponse(params, "SUCCESS", data); + } + } + + } + else { + terminalCommandResponse(params, "ERROR", data); + handleNokResponseOnRsPort("handleNOK else block", params, itIsNodeCommand, saveToTb); + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + //logger.debug("writeData err: ", error, result, params); + logger.debug("writeData err: ", tbname, node, register, values); + } + } + + //logger.debug(error, result, params); + } + }).catch(function(reason) { + + //console.log("writeData catch exception", reason); + instance.send(SEND_TO.debug, reason); + + terminalCommandResponse(params, "FAILURE", null, reason); + handleNokResponseOnRsPort("handleNOK catch block", params, itIsNodeCommand, saveToTb); + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + logger.debug("-->WRITE FAILED: " + reason, params.debug, params); + } + } + + }); + + } + 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); + } + + + // if node does not respond to request, we repeat request 3 times: + function repeatCommand(params) { + params.repeatCounter++; + if (params.repeatCounter < 4) { + params.timestamp = 0; + params.addMinutesToTimestamp = 0; + tasks.push(params); + } + } + + function handleNokResponseOnRsPort(message, params, itIsNodeCommand, saveToTb) { + + let node = params.address; + let register = params.register; + let type = params.type; + let tbName = params.tbname; + if (!tbName) return; + + let values = {}; + + let updateStatus = updateNodeStatus(node, false); + + if (itIsNodeCommand) { + values.comm_status = "NOK"; + nodesData[node].readout.comm_status = "NOK"; + repeatCommand(params); + } + + if (updateStatus) { + values.status = "NOK"; + nodesData[node].readout.status = "NOK"; + } + + if (type === "node-regular-read") return; + + //master node + if (node == 0) { + sendNotification("Cmd-mngr: 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; + + if (register == 4) values["master_node_version"] = "NOK"; + } + + if (type == "set_node_profile") { + delete cmdCounter[node]; + logger.debug("profil nebol úspešne odoslaný na node č. ", params); + + if (!nodeProfileSendFail.has(node)) { + sendNotification("Cmd-mngr: process cmd", tbName, "configuration_of_dimming_profile_to_node_failed", { node: node }, "", SEND_TO.tb, instance); + nodeProfileSendFail.add(node); + } + } + + // console.log("------",node, register, type, itIsNodeCommand, updateStatus, saveToTb, values); + if (saveToTb) { + sendTelemetry(values, tbName); + } + + } + + + function sendNodesData() { + Object.keys(nodesData).forEach(node => { + if (nodesData[node]["status"] !== "OFFLINE") { + sendTelemetry(nodesData[node].readout, nodesData[node].tbname); + nodesData[node].readout = {}; + } + }) + } + + + /** + * 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; + } + + 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); + + //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 === "OFFLINE") { + nodeObj.node_status_before_offline === true ? number_of_ok_luminaires++ : number_of_nok_luminaires++; + } + else if (nodeObj.status == true) 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 - ts % 60000 //round to full minute + }; + + sendTelemetry(values, SETTINGS.rvoTbName, ts); + } + + + function setSunCalcResult() { + //if next day, we get new dusk and dawn. To make sure, in local timezone 2:00 means 00:00 in utc (it means next day) + if (new Date().getHours() === 2) { + sunCalcResult = calculateDuskDawn(); + console.log("Novy suncalc: ", sunCalcResult); + } + } + + + function setRvoPeriod() { + + if (!SETTINGS.daily_report) return; + + const ts = Date.now(); + + previous_rvo_is_on_value = rvo_is_on; + + if (ts < sunCalcResult.dawn_time - 1_800_000) { // nodes should be on (00:00 -> 06:00 ( - pol hodina, lebo rvo vypina skor) + rvo_is_on = true; + } else if (sunCalcResult.dawn_time - 1_800_000 < ts && ts < sunCalcResult.dusk_time + 1_800_000) { // nodes should be off 06:00 -> 21:00 + rvo_is_on = false; + } else if (sunCalcResult.dusk_time + 1_800_000 < ts) { // nodes should be on 21:00 -> 00:00 + rvo_is_on = true; + } + + if (previous_rvo_is_on_value !== rvo_is_on) { + emptyDailyReport(); + console.log("rvo_is: ", rvo_is_on, previous_rvo_is_on_value); + } + } + + + function handleRsPort() { + + if (rsPort) { + rsPort.removeAllListeners(); + rsPort = null; + } + + //! 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-mngr: rsPort opened success"); + + 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); + + }).catch(function(reason) { + instance.send(SEND_TO.debug, "Cmd-mngr: RPC runSyncExec - promise rejected:" + reason); + }); + }); + + rsPort.on('error', function(err) { + errorHandler.sendMessageToService([exports.title, "unable to open port", SETTINGS.serial_port, err.message], 0); + monitor.info("Cmd-mngr: Error on rsPort", err.message); + }); + + rsPort.on("close", () => { + monitor.info("Cmd-mngr: rsPort closed, reconnecting..."); + setTimeout(handleRsPort, 1000); + }); + + rsPort.open(); + } + + + instance.on("close", () => { + clearInterval(interval); + clearInterval(customTasksInterval); + clearInterval(setCorrectTime); + clearInterval(sendNodeReadout); + clearInterval(accelerometerInterval); + rsPort.close(); + }); + + instance.on("0", _ => { + main(); + }) + + + instance.on("2", _ => { + console.log("dailyReport, reportToSend, rvo_is_on", dailyReport, reportToSend, rvo_is_on, previous_rvo_is_on_value); + }) + + instance.on("1", 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(); + return; + } + else if (flowdata.data == "close") { + rsPort.close(); + return; + } + else if (flowdata.data == "clean") { + tasks = []; + return; + } + else if (flowdata.data == "buildtasks") { + //build & run + return; + } + else if (flowdata.data == "run") { + //durations = []; + + if (tasks.length == 0) { + + buildTasks(); + + if (rsPort.isOpen) { + interval = setInterval(runTasks, 100); + } + else { + instance.send(SEND_TO.debug, "port is not opened!!!"); + } + } + } + else { + //terminal data - object + //logger.debug("flowdata", flowdata.data); + + if (typeof flowdata.data === 'object') { + //logger.debug("dido", flowdata.data); + if (flowdata.data.hasOwnProperty("sender")) { + //data from dido_controller + if (flowdata.data.sender == "dido_controller") { + + if (flowdata.data.hasOwnProperty("cmd")) { + let cmd = flowdata.data.cmd; + + if (cmd == "buildTasks") { + clearInterval(interval); + + logger.debug("-->Cmd-mngr: BUILD TASKS"); + buildTasks(); + + //logger.debug("tasks:"); + //logger.debug(tasks); + + logger.debug("-->Cmd-mngr: RUN TASKS"); + interval = setInterval(runTasks, 5000); + } + else if (cmd == "reload_relays") { + loadRelaysData(flowdata.data.line); + + if (flowdata.data.dataChanged) { + if (!flowdata.data.value) { + reportOfflineNodeStatus(flowdata.data.line); + } + else { + reportOnlineNodeStatus(flowdata.data.line); + } + } + + } + else if (cmd == "rotary_switch_state") { + let value = flowdata.data.value; + + //state was changed + if (rotary_switch_state != value) { + if (value == "Off") { + //vyreportovat vsetky svietdla + reportOfflineNodeStatus(); + } + + rotary_switch_state = value; + } + } + 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) { + + // we send lux_sensor value to all nodes: + let params = getParams(PRIORITY_TYPES.node_broadcast); + + params.recipient = 2;//2 broadcast, address = 0 + params.address = 0xffffffff;//Broadcast + + let ba = longToByteArray(lux_sensor); + + params.byte3 = ba[1];//msb + params.byte4 = ba[0]; + params.timestamp = PRIORITY_TYPES.node_broadcast; + params.info = "run broadcast: Actual Lux level from cabinet"; + params.register = 95;//Actual Lux level from cabinet + params.rw = 1;//write + + tasks.push(params); + + //process profiles + turnOnOffLinesAccordingToLuxSensor(lux_sensor); + } + } + else if (cmd == "state_of_breaker") { + //istic linie + + breakerCounter--; + + let value = flowdata.data.value; + let line = parseInt(flowdata.data.line); + + let dataChanged = false; + if (state_of_breaker[line] != value) dataChanged = true; + + state_of_breaker[line] = value; + + let status = "OK"; + if (value == "Off") status = "NOK"; + + if (dataChanged) { + + if (relaysData.hasOwnProperty(line)) { + let tbname = relaysData[line].tbname; + + if (value == "Off") { + sendNotification("Cmd-mngr: onData", tbname, "circuit_breaker_was_turned_off_line", { line: line }, "", SEND_TO.tb, instance, "circuit_breaker"); + if (breakerCounter < 0) reportToSend["contactor"]["off"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + else { + sendNotification("Cmd-mngr: onData", tbname, "circuit_breaker_was_turned_on_line", { line: line }, "", SEND_TO.tb, instance, "circuit_breaker"); + if (breakerCounter < 0) reportToSend["contactor"]["on"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + + //report status liniu + sendTelemetry({ status: status }, tbname) + + //current value + if (value == "Off") reportOfflineNodeStatus(line); //vyreportovat vsetky svietidla na linii + } + + } + } + else { + logger.debug("undefined cmd", cmd); + } + } + } + + return; + } + + //data from worksys + if (flowdata.data.hasOwnProperty("topic")) { + + let data = getNested(flowdata.data, "content", "data"); + + //if we get temperature in senica from senica-prod01 + let temperature = getNested(flowdata.data, "content", "senica_temperature"); + + if (temperature !== undefined) { + temperatureInSenica = temperature; + return; + } + + if (data === undefined) { + console.log("Invalid rpc command came from platform"); + return; + } + + let command = data.params.command; + let method = data.method; + let profile = data.params.payload; + if (profile == undefined) profile = ""; + let entity = data.params.entities[0]; + let entity_type = entity.entity_type; + let tbname = entity.tb_name; + + instance.send(SEND_TO.debug, flowdata.data); + 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") { + + //let command = data.params.command; + let value = data.params.payload.value; + + if (command == "dimming") { + + let nodeWasFound = false; + let keys = Object.keys(nodesData); + + //logger.debug("-----", keys); + + 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); + + value = parseInt(value); + if (value > 0) value = value + 128; + + params.type = "node-onetime-write"; + params.tbname = tbname; + params.address = node; + params.register = 1; + params.recipient = 1; + params.byte4 = value; + params.rw = 1; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'set dimming from platform'; + //params.debug = true; + + //debug(params); + logger.debug("dimming", params); + + tasks.push(params); + + 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); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 1; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read dimming (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + //pridame aj vyreportovanie - vykon + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 76; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read Input Power (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + //pridame aj vyreportovanie - prud svietidla + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 75; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read Input Current (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + //pridame aj vyreportovanie - power faktor - ucinnik + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 77; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read power factor (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + }, 4000); + + nodeWasFound = true; + break; + } + } + + if (!nodeWasFound) { + logger.debug("set dimming from platform", "unable to find tbname", tbname); + } + } + else { + instance.send(SEND_TO.debug, "undefined command " + command); + logger.debug("undefined command", command); + } + + return; + } + 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++) { + let node = keys[i]; + if (tbname == nodesData[node].tbname) { + + 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"); + + //profil úspešne prijatý pre node č. xx + sendNotification("Cmd-mngr", tbname, "dimming_profile_was_processed_for_node", { node: node }, profile, SEND_TO.tb, instance); + + nodesData[node].processed = false; + nodesData[node].profile = profile; + + processNodeProfile(node); + }); + }); + } + } + } + else { + + instance.send(SEND_TO.debug, "unknown method " + method); + logger.debug("unknown method", method); + + return; + } + } + + //nastav profil linie z platformy + 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") { + + 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++) { + let line = keys[i]; + if (tbname == relaysData[line].tbname) { + //zmazeme tasky + 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) { + + //update profile + logger.debug("worksys - update relay profile done:", profile); + instance.send(SEND_TO.debug, "worksys - update relay profile done"); + + relaysData[line].profile = profile; + + loadRelaysData(line) + logger.debug("loadRelaysData DONE for line", line); + + buildTasks({ processLineProfiles: true, line: line }); + + sendNotification("Cmd-mngr: set profile from worksys", tbname, "switching_profile_was_processed_for_line", { line: line }, profile, SEND_TO.tb, instance); + }); + }); + break; + } + } + } + else if (method == "set_command") { + let value = data.params.payload.value; + + 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; + + 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"); + if (line != 0) reportToSend["contactor"]["off"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + else { + turnLine("on", line, "command received from platform"); + if (line != 0) reportToSend["contactor"]["on"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + } + } + else { + instance.send(SEND_TO.debug, "undefined method " + method); + logger.debug("undefined method", method); + } + + return; + } + else { + instance.send(SEND_TO.debug, "UNKNOW entity_type " + entity_type); + logger.debug("UNKNOW entity_type", entity_type); + } + return; + } + + //terminal + if (!rsPort.isOpen) await rsPort.open(); + + let params = flowdata.data.body; + if (params == undefined) { + //logger.debug("Cmd-mngr: flowdata.data.body is undefined"); + return; + } + + params.priority = PRIORITY_TYPES.terminal; + params.type = "cmd-terminal"; + params.tbname = ""; + params.timestamp = PRIORITY_TYPES.terminal; + params.addMinutesToTimestamp = 0;// do not repeat task!!! + params.debug = true; + + let timestamp = Date.now(); + params.refFlowdataKey = timestamp; + //params.refFlowdata = flowdata; + //refFlowdata = flowdata; + + //console.log("flowdata", flowdata); + + cleanUpRefFlowdataObj(); + + refFlowdataObj[timestamp] = flowdata; + + //fix + //params.address = params.adress; + logger.debug("received from terminal", params); + logger.debug("date/time:", new Date()); + logger.debug("tasks length:", tasks.length); + + //tasks = []; + + //add to tasks + tasks.push(params); + + } + } + }) + + + //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) + } + + + /** + * 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; + + RESTBuilder.make(function(builder) { + + if (!builder) return; + + builder.method('GET'); + builder.url('http://192.168.252.2:8004/gettime?projects_id=1'); + + builder.callback(function(err, response, output) { + + 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); + } + + }); + } + + } 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); + + } else { + //console.log("Read-only", stdout); + + 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]: [ + { + "ts": date, + "values": values + } + ] + } + + tbHandler.sendToTb(dataToTb, instance); + } + + + function calculateDuskDawn(date, line, duskOffset = 0, dawnOffset = 0) { + + if (date === undefined) date = new Date(); + + 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); + } + + //if(profile.dawn_lux_sensor == false) + { + if (profile.hasOwnProperty("dawn_astro_clock_offset")) dawn_astro_clock_offset = parseInt(profile.dawn_astro_clock_offset); + } + + } + + } catch (error) { + if (profilestr != "") { + logger.debug(profilestr); + logger.debug(error); + } + } + + 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; + } + + //Dimming, CCT + else if (register == 1) { + let brightness = 0; + let dimming = byte0; + if (dimming > 128) { + //dimming = -128; + brightness = dimming - 128; + } + + //cct + //Ak Byte3 == 1: CCT = (Byte2*256)+Byte1 + let cct; + if (byte3 == 1) cct = byte2 * 256 + byte1; + else cct = bytesToInt(bytes.slice(0, 3)); + + //cct podla auditu + + values["dimming"] = brightness; + return values; + } + + // + else if (register == 4) { + values["master_node_version"] = bytes[1] + "." + bytes[2]; + //logger.debug("FW Version", register, bytes); + } + + //Napätie + else if (register == 74) { + let voltage = (bytesToInt(bytes) * 0.1).toFixed(1); + values["voltage"] = Number(voltage); + } + + //Prúd + else if (register == 75) { + let current = bytesToInt(bytes); + values["current"] = current; + } + + //výkon + else if (register == 76) { + let power = (bytesToInt(bytes) * 0.1).toFixed(2); + values["power"] = Number(power); + } + + //účinník + else if (register == 77) { + let power_factor = Math.cos(bytesToInt(bytes) * 0.1 * (Math.PI / 180)).toFixed(2); + values["power_factor"] = Number(power_factor); + } + + //frekvencia + else if (register == 78) { + let frequency = (bytesToInt(bytes) * 0.1).toFixed(2); + values["frequency"] = Number(frequency); + } + + //energia + else if (register == 79) { + let energy = bytesToInt(bytes); + values["energy"] = energy / 1000; //energia v kWh -> delit 1000 + } + + //doba života + else if (register == 80) { + let lifetime = (bytesToInt(bytes) / 60).toFixed(2); + values["lifetime"] = Number(lifetime); + } + + //nastavenie profilu + else if (register == 8) { + let time_schedule_settings = bytesToInt(bytes); + values["time_schedule_settings"] = time_schedule_settings; + } + + //naklon - nateraz sa z nodu nevycitava! kvoli problemom s accelerometrom a vracanymi hodnotami, posielame temp a x y z vo funkcii accelerometerData() + else if (register == 84) { + values["temperature"] = byte3 >= 128 ? (byte3 - 128) * (-1) : byte3; + values["inclination_x"] = byte2 >= 128 ? (byte2 - 128) * (-1) : byte2; + values["inclination_y"] = byte1 >= 128 ? (byte1 - 128) * (-1) : byte1; + values["inclination_z"] = byte0 >= 128 ? (byte0 - 128) * (-1) : byte0; + } + + //FW verzia nodu + else if (register == 89) { + //formát: "Byte3: Byte2.Byte1 (Byte0)" + values["fw_version"] = byte3 + ":" + byte2 + "." + byte1 + "(" + byte0 + ")"; + } + + else if (register == 87 || register == 6 || register == 7) { + var d = new Date(); + d.setHours(byte3, byte2, 0, 0); + let timestamp = d.getTime(); + + //aktuálny čas + if (register == 87) values["actual_time"] = timestamp; + //čas súmraku + else if (register == 6) values["dusk_time"] = timestamp; + //čas úsvitu + else if (register == 7) values["dawn_time"] = timestamp; + } + + 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; + + } + + + function getObjectByTbValue(object, tbname) { + return object[Object.keys(object).find(key => object[key].tbname === tbname)]; + } + + + function isObject(item) { + return (typeof item === "object" && !Array.isArray(item) && item !== null); + } + + + // we fake data, that should be received from accelerometer, as they are a bit unreliable. (temperature, x,y,z) + function accelerometerData() { + + if (temperatureInSenica === null) return; + + //clone nodesData and relaysData objects + let nodesData_clone = JSON.parse(JSON.stringify(nodesData)); + let relaysData_clone = JSON.parse(JSON.stringify(relaysData)); + + for (const key in relaysData_clone) { + + const lineData = relaysData_clone[key]; + const lineNumber = lineData.line; + const contactor = lineData.contactor; + + if (lineNumber === 0) continue; + + if (contactor === 1) { + + let date = Date.now(); + + Object.keys(nodesData_clone).forEach((node, index) => { + + setTimeout(function() { + + if (nodesData_clone[node].line === lineNumber) { + + // NOTE: if status of luminaire is NOK or OFFLINE, we do not send data; + let status = nodesData_clone[node].status; + if (status === "OFFLINE" || !status) return; + + let x = null; + if (naklony.hasOwnProperty(node)) x = naklony[node].naklon; + if (x === null) x = 0; + + sendTelemetry({ temperature: Math.round(temperatureInSenica + 10 + Math.floor(Math.random() * 3)), inclination_x: x, inclination_y: 0, inclination_z: 0 }, nodesData_clone[node].tbname, date); + } + + }, (index + 1) * 500); + }) + + } + } + } + + +} // end of instance.export + diff --git a/RVO21/flow/code.js b/RVO21/flow/code.js new file mode 100755 index 0000000..63b31bf --- /dev/null +++ b/RVO21/flow/code.js @@ -0,0 +1,90 @@ +exports.id = 'code'; +exports.title = 'Code'; +exports.group = 'Common'; +exports.color = '#656D78'; +exports.input = true; +exports.output = 1; +exports.author = 'Peter Širka'; +exports.icon = 'code'; +exports.version = '1.2.0'; +exports.options = { outputs: 1, code: 'send(0, value);', keepmessage: true }; + +exports.html = `
+
+
+
@(Number of outputs)
+
@(Minimum is 1)
+
+
+
@(Code)
+
@(Keep message instance)
+
+`; + +exports.readme = `# Code + +This component executes custom JavaScript code as it is and it doesn't contain any secure scope. + +\`\`\`javascript +// value {Object} contains received data +// send(outputIndex, newValue) sends a new value +// error(value) sends an error +// instance {Object} a current component instance +// flowdata {Object} a current flowdata +// repository {Object} a current repository of flowdata +// Example: + +// send() can be execute multiple times +send(0, value); +\`\`\``; + +exports.install = function(instance) { + + var fn; + + instance.on('data', function(response) { + if (fn) { + try { + fn(response.data, instance, response, instance.options, response.repository, require); + } catch (e) { + response.data = e; + instance.throw(response); + } + } + }); + + instance.reconfigure = function() { + try { + if (instance.options.code) { + instance.status(''); + var code = 'var send = function(index, value) { if (options.keepmessage) { flowdata.data = value; instance.send2(index, flowdata); } else instance.send2(index, value);}; var error = function(err) { instance.throw(err); }; ' + instance.options.code; + fn = new Function('value', 'instance', 'flowdata', 'options', 'repository', 'require', code); + } else { + instance.status('Not configured', 'red'); + fn = null; + } + } catch (e) { + fn = null; + instance.error('Code: ' + e.message); + } + }; + + instance.on('options', instance.reconfigure); + instance.reconfigure(); +}; \ No newline at end of file diff --git a/RVO21/flow/comment.js b/RVO21/flow/comment.js new file mode 100755 index 0000000..1e0cd13 --- /dev/null +++ b/RVO21/flow/comment.js @@ -0,0 +1,11 @@ +exports.id = 'comment'; +exports.title = 'Comment'; +exports.group = 'Common'; +exports.color = '#704cff'; +exports.author = 'Martin Smola'; +exports.icon = 'comment'; +exports.traffic = false; +exports.version = '1.0.0'; +exports.readme = '# Comment'; + +exports.install = function() {}; diff --git a/RVO21/flow/count.js b/RVO21/flow/count.js new file mode 100755 index 0000000..fa92ee9 --- /dev/null +++ b/RVO21/flow/count.js @@ -0,0 +1,60 @@ +exports.id = 'count'; +exports.title = 'Count'; +exports.version = '1.0.1'; +exports.author = 'John Graves'; +exports.color = '#656D78'; +exports.icon = 'plus-square'; +exports.input = 2; +exports.output = 1; +exports.options = { increment: 1, initialvalue: 1 }; +exports.readme = `# Counter + +Counter Number of times called.`; + +exports.html = `
+
@(Initial Value)
+
@(Increment)
+

Example Video

+
`; + +exports.readme = `# Count + +This component counts the number of messages received. + +__Response:__ + +Integer value based on the initial value and increment settings. + +__Arguments:__ +- Initial Value: What number should be output on the receipt of the first message. +- Increment: What should the increment be for each following message received.`; + +exports.install = function(instance) { + + var count = 0; + var initialCall = true; + + instance.on('data', function(flowdata) { + var index = flowdata.index; + if (index) { + instance.debug('Reset Count.'); + count = instance.options.initialvalue; + initialCall = true; + } else { + // If this is the first time, set the value to 'initial value' + if(initialCall) { + initialCall = false; + count = instance.options.initialvalue; + } else + count = count+instance.options.increment; + instance.status('Count:' + count); + instance.send2(count); + } + }); + + instance.on('options', function() { + count = instance.options.initialvalue; + initialCall = true; + }); + +}; diff --git a/RVO21/flow/db_connector.js b/RVO21/flow/db_connector.js new file mode 100755 index 0000000..65ee94b --- /dev/null +++ b/RVO21/flow/db_connector.js @@ -0,0 +1,286 @@ +exports.id = 'db_connector'; +exports.title = 'DbConnector'; +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.html = `
+
+
+
DbConnector
+
+
+
`; + +exports.readme = `# read/write data to tables`; + +const instanceSendTo = { + debug: 0, + http_response: 1, +} + +const { promisifyBuilder, makeMapFromDbResult } = require('./helper/db_helper.js'); + +function extractWhereParams(params) +{ + let name = params[0]; + let operator = '='; + let value = params[1]; + + if(params.length == 3) + { + operator = params[1]; + value = params[2]; + } + + return {name: name, operator: operator, value: value}; +} + +exports.install = function(instance) { + + let refFlowdata = null;//holds reference to httprequest flowdata + + instance.on("close", () => { + + }) + + + instance.on("data", async function(flowdata) { + + let params = flowdata.data.body; + console.log("DbConnector", params); + + refFlowdata = flowdata; + + if(refFlowdata != undefined) + { + //make http response + let responseObj = {}; + responseObj["type"] = "SUCESS"; + + try{ + + let table = params.table; + let action = params.action; + + + if(params.data != undefined) + { + let className = params.data.className; + + if(className == "SqlQueryBuilder") + { + let type = params.data.type; + + console.log("SqlQueryBuilder---->", params.data); + + if(type == "SELECT") + { + let table = params.data.queryData.tables[0].table; + + const db = TABLE(table); + var builder = db.find(); + + let result = await promisifyBuilder(builder); + + let response = {}; + response["result"] = result; + response["success"] = true; + + responseObj["data"] = response; + + //console.log(responseObj); + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + } + + return; + } + } + + + console.log("db_connector---->", table, action); + + //actions: read, replace, insert, delete, update... + + if(action == "read") + { + const db = TABLE(params.table); + + //where builder.where('age', '<', 15); + //builder.where('id', 3403); + + var builder = db.find(); + + //https://docs.totaljs.com/latest/en.html#api~DatabaseBuilder~builder.where + if(params.hasOwnProperty("where")) + { + //optionalCan contain "=", "<=", "<", ">=", ">". + //Default value: '=' + + //1.["production_line", 1] + //2. ["or", ["production_line", 1], ["production_line", 2], "end"] + + if (Array.isArray(params.where)) { + + let multipleConditions = false; + + if(params.where[0] == "or") multipleConditions = true; + if (Array.isArray(params.where[0])) multipleConditions = true; + + if(multipleConditions) + { + + for(var i = 0; i < params.where.length; i++) + { + const item = params.where[i]; + + if(item === "or") builder.or(); + + if (Array.isArray(item)) + { + const { name, operator, value } = extractWhereParams(item); + builder.where(name, operator, value); + } + + if(item === "end") builder.end(); + + } + + } + else + { + const { name, operator, value } = extractWhereParams(params.where); + builder.where(name, operator, value); + } + + } + + /* + if(params.where.length >=2 ) + { + let name = params.where[0]; + let operator = '='; + let value = params.where[1]; + + if(params.where.length == 3) + { + operator = params.where[1]; + value = params.where[2]; + } + + builder.where(name, operator, value); + } + */ + } + + if(params.hasOwnProperty("between")) + { + builder.between(params.between[0], params.between[1], params.between[2]); + } + + let response = await promisifyBuilder(builder); + responseObj["data"] = response; + + //console.log(responseObj); + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + + return; + } + + if(action == "delete") + { + + } + + + if(action == "update") + { + //! data receiving from terminal (params) + // { + // hostname: 'localhost', + // table: 'settings', + // action: 'update', + // body: { + // rvo_name: 'terrrr', + // lang: 'en', + // temperature_adress: '28.427B45920702', + // latitude: 48.70826502, + // longitude: 17.28455203, + // mqtt_host: '192.168.252.4', + // mqtt_clientid: 'showroom_test_panel_led', + // mqtt_username: 'xmRd6RJxW53WZe4vMFLU', + // mqtt_port: 1883, + // maintanace_mode: false + // } + // } + const tableToModify = TABLE(params.table); + const newValues = params.body; + + tableToModify.modify(newValues).make(function(builder) { + + builder.callback(function(err, response) { + + if(!err) + { + responseObj["data"] = response; + responseObj["tableUpdated"] = true; + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + } + }); + }); + + } + + if(action == "replace") + { + //truncate table + const db = TABLE(params.table); + var builder = db.remove(); + db.clean(); + + //insert data + let data = params.data; + + for(let i = 0; i < data.length; i++) + { + //console.log(data[i]); + db.insert(data[i]); + } + + console.log("insert done"); + + let responseObj = {}; + responseObj["type"] = "SUCESS"; + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + + + } + + + + } catch (error) { + //console.log(error); + responseObj["type"] = "ERROR"; + responseObj["message"] = error; + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + } + } + }) +} + + diff --git a/RVO21/flow/db_init.js b/RVO21/flow/db_init.js new file mode 100755 index 0000000..b399878 --- /dev/null +++ b/RVO21/flow/db_init.js @@ -0,0 +1,113 @@ +exports.id = 'db_init'; +exports.title = 'DB Initialization'; +exports.group = 'Worksys'; +exports.color = '#888600'; +exports.version = '1.0.2'; +exports.icon = 'sign-out'; +exports.output = 2; + +exports.readme = ` + # DB initialization +`; + +const { promisifyBuilder, makeMapFromDbResult } = require('./helper/db_helper.js'); +const { initNotification } = require('./helper/notification_reporter'); +const errorHandler = require('./helper/ErrorToServiceHandler'); +const total_energy = require('../databases/total_energy'); + +const SEND_TO = { + db_init: 0, + infoSender: 1 +}; + + +exports.install = async function(instance) { + const dbNodes = TABLE("nodes"); + const dbRelays = TABLE("relays"); + const dbSettings = TABLE("settings"); + 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 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.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"]; + Object.keys(dbs.nodesData).forEach(node => dbs.nodesData[node].readout = {}) + + let rvo_number = responseSettings[0]["rvo_name"].match(/\D+(\d{1,2})_/)[1]; + + dbs.settings = { + edge_fw_version: "2025-10-08", //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"], + phases: responseSettings[0]["phases"], + cloud_topic: responseSettings[0]["cloud_topic"], + has_main_switch: responseSettings[0]["has_main_switch"], + daily_report: responseSettings[0]["daily_report"], + send_changed_node_numbers: responseSettings[0]["send_changed_node_numbers"], + rvo_number: rvo_number, + + //dynamic values + masterNodeIsResponding: true, //cmd_manager + maintenance_mode: false, + } + + + dbs.settings.energy_to_switch_lamps = total_energy[rvo_number]; + if (dbs.settings.energy_to_switch_lamps === undefined) console.log('=============== db_init.js: energy_to_switch_lamps is undefined'); + + FLOW.dbLoaded = true; + errorHandler.setProjectId(dbs.settings.project_id); + initNotification(); + + //APP START - send to data services + const toService = { + id: dbs.settings.project_id, + name: dbs.settings.rvo_name, + fw_version: dbs.settings.edge_fw_version, + startdate: new Date().toISOString().slice(0, 19).replace('T', ' '), + js_error: "", + error_message: "" + }; + + instance.send(SEND_TO.infoSender, toService); + console.log("----------------> START - message send to service", toService); + + setTimeout(() => { + console.log("DB_INIT - data loaded"); + instance.send(SEND_TO.db_init, "_") + }, 5000) + +}; + diff --git a/RVO21/flow/debug.js b/RVO21/flow/debug.js new file mode 100755 index 0000000..00cb259 --- /dev/null +++ b/RVO21/flow/debug.js @@ -0,0 +1,100 @@ +exports.id = 'debug'; +exports.title = 'Debug'; +exports.author = 'Peter Širka'; +exports.color = '#967ADC'; +exports.click = true; +exports.input = true; +exports.icon = 'bug'; +exports.version = '2.0.4'; +exports.options = { enabled: true, repository: false, type: 'data' }; +exports.readme = `# Debug + +Prints data to the debug tab.`; + +exports.html = `
+
+
+
@(Output type)
+
@(Path to the property (leave empty to show the whole data object))
+
@(A group name)
+
@(Enabled)
+
+
+
`; + +exports.install = function(instance) { + + instance.on('data', function(response) { + if (instance.options.enabled) { + + var opt = instance.options; + var rep = response.repository; + var val = response.data; + var id = response.id; + + switch (instance.options.type){ + case 'both': + var data = {}; + data.repository = rep; + data.data = val instanceof Error ? { error: val.message, stack: val.stack } : val; + instance.debug(safeparse(opt.property ? U.get(data, opt.property) : data), undefined, opt.group, id); + break; + case 'repository': + instance.debug(safeparse(opt.property ? U.get(rep, opt.property) : rep), undefined, opt.group, id); + break; + case 'data': + default: + if (val instanceof Error) + instance.debug({ error: val.message, stack: val.stack }, undefined, opt.group, id); + else + instance.debug(safeparse(opt.property ? U.get(val, opt.property) : val), undefined, opt.group, id); + break; + } + } + }); + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + instance.save(); + }); + + instance.on('options', function() { + instance.custom.status(); + }); + + instance.custom.status = function() { + instance.status(instance.options.enabled ? 'Enabled' : 'Disabled'); + }; + + instance.custom.status(); + + function safeparse(o) { + + if (o instanceof Buffer) + return o; + + if (o === undefined) + return 'undefined'; + + if (o === null) + return 'null'; + + var cache = []; + var str = JSON.stringify(o, function(key, value) { + if (typeof value === 'object' && value !== null) { + if (cache.indexOf(value) !== -1) { + try { + return JSON.parse(JSON.stringify(value)); + } catch (error) { + return; + } + } + cache.push(value); + } + return value; + }); + cache = null; + return JSON.parse(str); + } +}; diff --git a/RVO21/flow/designer.json b/RVO21/flow/designer.json new file mode 100755 index 0000000..580f5a3 --- /dev/null +++ b/RVO21/flow/designer.json @@ -0,0 +1,3102 @@ +{ + "tabs": [ + { + "name": "MAIN PUSH", + "linker": "main-push", + "id": "1612772287426", + "index": 0 + }, + { + "name": "CMD manager", + "linker": "cmd-manager", + "id": "1615551125555", + "index": 1 + }, + { + "name": "Devices", + "linker": "devices", + "id": "1611921777196", + "index": 2 + } + ], + "components": [ + { + "id": "1611951142547", + "component": "debug", + "tab": "1611921777196", + "name": "ERROR", + "x": 598, + "y": 60, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#DA4453", + "notes": "" + }, + { + "id": "1612776786008", + "component": "wsmqttpublish", + "tab": "1612772287426", + "name": "WS MQTT publish", + "x": 281.75, + "y": 174, + "connections": { + "0": [ + { + "index": "0", + "id": "1615551060773" + } + ], + "1": [ + { + "index": "0", + "id": "1618300858252" + }, + { + "index": "0", + "id": "1618558465485" + } + ], + "2": [ + { + "index": "0", + "id": "1634303685503" + } + ], + "3": [ + { + "index": "0", + "id": "1731068754606" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Connected", + "color": "green" + }, + "options": { + "username": "", + "clientid": "", + "port": "1883", + "host": "" + }, + "color": "#888600", + "notes": "" + }, + { + "id": "1612778461252", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "tb-push", + "x": 72.75, + "y": 328, + "connections": { + "0": [ + { + "index": "0", + "id": "1612783322136" + }, + { + "index": "1", + "id": "1612776786008" + }, + { + "index": "0", + "id": "1731068754606" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1612783322136", + "component": "debug", + "tab": "1612772287426", + "name": "to TB", + "x": 283.75, + "y": 324, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615551060773", + "component": "debug", + "tab": "1612772287426", + "name": "errors from MQTT Broker", + "x": 594, + "y": 57, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#DA4453", + "notes": "" + }, + { + "id": "1615563373927", + "component": "debug", + "tab": "1615551125555", + "name": "Debug", + "x": 755, + "y": 155, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#DA4453", + "notes": "" + }, + { + "id": "1615566865233", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "tb-push", + "x": 755, + "y": 248, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1615798582262", + "component": "debug", + "tab": "1615551125555", + "name": "CMD_debug", + "x": 755, + "y": 346, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615802995322", + "component": "debug", + "tab": "1611921777196", + "name": "Debug", + "x": 596.8833312988281, + "y": 566.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Disabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": false + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615809128443", + "component": "debug", + "tab": "1611921777196", + "name": "tempToTb", + "x": 595.8833312988281, + "y": 658.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615809595184", + "component": "virtualwireout", + "tab": "1611921777196", + "name": "tb-push", + "x": 597.8833312988281, + "y": 377.25, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1616165795916", + "component": "httproute", + "tab": "1615551125555", + "name": "POST /terminal", + "x": 135, + "y": 547, + "connections": { + "0": [ + { + "index": "0", + "id": "1684060205000" + }, + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Listening", + "color": "green" + }, + "options": { + "timeout": 10, + "cachepolicy": 0, + "cacheexpire": "5 minutes", + "size": 5, + "url": "/terminal", + "method": "POST", + "name": "", + "flags": [ + "id:1616165795916", + "post", + 10000 + ], + "emptyresponse": false + }, + "color": "#5D9CEC", + "notes": "### Configuration\n\n- __POST /terminal__\n- flags: \n- maximum request data length: __5 kB__\n- empty response: __false__\n- cache policy: __no cache__\n- cache expire: __5 minutes__", + "cloning": false + }, + { + "id": "1616165824813", + "component": "httpresponse", + "tab": "1615551125555", + "name": "HTTP Response", + "x": 753, + "y": 423, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "json" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1617104731852", + "component": "debug", + "tab": "1615551125555", + "name": "DIDO_Debug", + "x": 669, + "y": 1040, + "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": "turnOff line", + "x": 133, + "y": 1161, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "object", + "data": "{line: 3, command: \"turnOff\", force: true}" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1617115013095", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "tb-push", + "x": 669, + "y": 1150, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1617284749681", + "component": "trigger", + "tab": "1615551125555", + "name": "update profile / node", + "x": 112, + "y": 208, + "connections": { + "0": [ + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "data": "profile_nodes", + "datatype": "string" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1618235171399", + "component": "trigger", + "tab": "1615551125555", + "name": "tun tasks", + "x": 184, + "y": 279, + "connections": { + "0": [ + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "data": "run" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1618300858252", + "component": "debug", + "tab": "1612772287426", + "name": "wsmqtt-exit1", + "x": 597.8833312988281, + "y": 149, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1618393583970", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "to-cmd-manager", + "x": 668.8833312988281, + "y": 1269, + "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": 132.88333129882812, + "y": 367, + "connections": { + "0": [ + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "platform-rpc-call", + "color": "gray" + }, + "options": { + "wirename": "platform-rpc-call" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1618393759854", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "cmd_to_dido", + "x": 119.88333129882812, + "y": 1007, + "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": 752.8833312988281, + "y": 527, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "cmd_to_dido", + "color": "gray" + }, + "options": { + "wirename": "cmd_to_dido" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1618558465485", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "platform-rpc-call", + "x": 597.8833312988281, + "y": 247, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "platform-rpc-call", + "color": "gray" + }, + "options": { + "wirename": "platform-rpc-call" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1618572059773", + "component": "trigger", + "tab": "1615551125555", + "name": "turnOn line", + "x": 132, + "y": 1085, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "data": "{line: 1, command: \"turnOn\", force: true}", + "datatype": "object" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1619515097737", + "component": "cmd_manager", + "tab": "1615551125555", + "name": "CMD Manager", + "x": 452.1091003417969, + "y": 341.05455017089844, + "connections": { + "0": [ + { + "index": "0", + "id": "1615563373927" + } + ], + "1": [ + { + "index": "0", + "id": "1615566865233" + }, + { + "index": "0", + "id": "1615798582262" + } + ], + "2": [ + { + "index": "0", + "id": "1616165824813" + } + ], + "3": [ + { + "index": "0", + "id": "1618393827655" + } + ], + "4": [ + { + "index": "0", + "id": "1635936391935" + } + ], + "5": [ + { + "index": "0", + "id": "1757006030239" + }, + { + "index": "0", + "id": "1757006060377" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1619605019281", + "component": "httproute", + "tab": "1615551125555", + "name": "GET db", + "x": 173, + "y": 653, + "connections": { + "0": [ + { + "index": "0", + "id": "1684060205000" + }, + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Listening", + "color": "green" + }, + "options": { + "timeout": 5, + "cachepolicy": 0, + "cacheexpire": "5 minutes", + "size": 5, + "url": "/db", + "method": "GET", + "name": "", + "flags": [ + "id:1619605019281", + "get", + 5000 + ] + }, + "color": "#5D9CEC", + "notes": "### Configuration\n\n- __GET /db__\n- flags: undefined\n- maximum request data length: __5 kB__\n- empty response: __undefined__\n- cache policy: __no cache__\n- cache expire: __5 minutes__", + "cloning": false + }, + { + "id": "1619784672383", + "component": "trigger", + "tab": "1615551125555", + "name": "turnOnAlarm", + "x": 120, + "y": 1234, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "object", + "data": "{command: \"turnOnAlarm\"}" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1619784812964", + "component": "trigger", + "tab": "1615551125555", + "name": "turnOffAlarm", + "x": 118, + "y": 1307, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "object", + "data": "{command: \"turnOffAlarm\"}" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1621340721628", + "component": "virtualwireout", + "tab": "1611921777196", + "name": "modbus_to_dido", + "x": 599, + "y": 471, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "modbus_to_dido", + "color": "gray" + }, + "options": { + "wirename": "modbus_to_dido" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1622640022885", + "component": "httproute", + "tab": "1615551125555", + "name": "POST /db_connector", + "x": 98, + "y": 1586, + "connections": { + "0": [ + { + "index": "0", + "id": "1622640073521" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Listening", + "color": "green" + }, + "options": { + "timeout": 5, + "cachepolicy": 0, + "cacheexpire": "5 minutes", + "size": 5, + "url": "/db_connector", + "method": "POST", + "flags": [ + "id:1622640022885", + "post", + 5000 + ] + }, + "color": "#5D9CEC", + "notes": "### Configuration\n\n- __POST /db_connector__\n- flags: \n- maximum request data length: __5 kB__\n- empty response: __undefined__\n- cache policy: __no cache__\n- cache expire: __5 minutes__", + "cloning": false + }, + { + "id": "1622640073521", + "component": "db_connector", + "tab": "1615551125555", + "name": "DbConnector", + "x": 372, + "y": 1572, + "connections": { + "1": [ + { + "index": "0", + "id": "1622641420685" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "edge": "undefined" + }, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1622641420685", + "component": "httpresponse", + "tab": "1615551125555", + "name": "HTTP Response", + "x": 596, + "y": 1586, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1634303504177", + "component": "monitormemory", + "tab": "1612772287426", + "name": "RAM", + "x": 69.88333129882812, + "y": 888.5, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465281992" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "858.88 MB / 985.68 MB", + "color": "gray" + }, + "options": { + "enabled": true, + "interval": 30000 + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1634303533779", + "component": "monitordisk", + "tab": "1612772287426", + "name": "disk", + "x": 70.88333129882812, + "y": 982.5, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465821120" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "5.78 GB / 7.26 GB", + "color": "gray" + }, + "options": { + "enabled": true, + "path": "/", + "interval": 30000 + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1634303595494", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "send-to-services", + "x": 51.883331298828125, + "y": 1400.5, + "connections": { + "0": [ + { + "index": "0", + "id": "1634463186563" + }, + { + "index": "1", + "id": "1634488120710" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1634303602169", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "send-to-services", + "x": 426.8833312988281, + "y": 878.5, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1634303685503", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "send-to-services", + "x": 600.8833312988281, + "y": 341.5, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1634303743260", + "component": "httprequest", + "tab": "1612772287426", + "name": "192.168.252.2:8004/sentmessage", + "reference": "", + "x": 506.8833312988281, + "y": 1331.7333374023438, + "connections": { + "0": [ + { + "index": "0", + "id": "1635327431236" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "url": "http://192.168.252.2:8004/sentmessage", + "method": "POST", + "stringify": "json" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1634463186563", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 305.75, + "y": 1442, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634464580289", + "component": "code", + "tab": "1612772287426", + "name": "Code", + "x": 245, + "y": 787, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465243324" + }, + { + "index": "0", + "id": "1634303602169" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "keepmessage": true, + "code": "let response = {};\nresponse.cpu = value.cpu;\nresponse.uptime = value.uptime;\n\nsend(0, response);", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1634465243324", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 428, + "y": 784, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634465281992", + "component": "code", + "tab": "1612772287426", + "name": "Code", + "x": 245, + "y": 884, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465338103" + }, + { + "index": "0", + "id": "1634303602169" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "keepmessage": true, + "code": "value.sender = \"ram\";\n\nlet response = {};\n\nresponse.memory_total = Math.round(value.total / (1024 ** 2));\nresponse.memory_free = Math.round(value.free / (1024 ** 2));\nresponse.memory_used = Math.round(value.used / (1024 ** 2));\n\nsend(0, response);", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1634465338103", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 429, + "y": 976, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634465821120", + "component": "code", + "tab": "1612772287426", + "name": "Code", + "x": 245, + "y": 978, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465892500" + }, + { + "index": "0", + "id": "1634303602169" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "keepmessage": true, + "code": "value.sender = \"hdd\";\n\nlet response = {};\n\nresponse.hdd_total = Math.round(value.total / (1024 ** 2));\nresponse.hdd_free = Math.round(value.free / (1024 ** 2));\nresponse.hdd_used = Math.round(value.used / (1024 ** 2));\n\nsend(0, response);", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1634465892500", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 432, + "y": 1068, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634484067516", + "component": "debug", + "tab": "1612772287426", + "name": "Send info", + "x": 513, + "y": 1441, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634488120710", + "component": "infosender", + "tab": "1612772287426", + "name": "Info sender", + "x": 301, + "y": 1336, + "connections": { + "0": [ + { + "index": "0", + "id": "1634484067516" + }, + { + "index": "0", + "id": "1634303743260" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "edge": "undefined" + }, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1635327431236", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 837.8833312988281, + "y": 1325.5, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1635936391935", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "send-to-services", + "x": 753, + "y": 623, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1637069803394", + "component": "monitorconsumption", + "tab": "1612772287426", + "name": "CPU", + "x": 69, + "y": 791, + "connections": { + "0": [ + { + "index": "0", + "id": "1634464580289" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "49.2% / 69.91 MB", + "color": "gray" + }, + "options": { + "monitorfiles": true, + "monitorconnections": true, + "monitorsize": true, + "monitorconsumption": true, + "enabled": true, + "interval": 30000 + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1683664161036", + "component": "debug", + "tab": "1615551125555", + "name": "CMDtoDIDO", + "x": 392, + "y": 1012, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1683981346282", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "from-dido-controller", + "x": 112, + "y": 459, + "connections": { + "0": [ + { + "index": "0", + "id": "1684055037116" + }, + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "from-dido-controller", + "color": "gray" + }, + "options": { + "wirename": "from-dido-controller" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1684055037116", + "component": "debug", + "tab": "1615551125555", + "name": "from dido to cmd", + "x": 451, + "y": 532, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1684060205000", + "component": "debug", + "tab": "1615551125555", + "name": "HTTP routes", + "x": 450, + "y": 639, + "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": "MDBToDido", + "x": 598, + "y": 147, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1699963668903", + "component": "dido_controller", + "tab": "1615551125555", + "name": "DIDO_Controller", + "x": 397, + "y": 1131, + "connections": { + "0": [ + { + "index": "0", + "id": "1617104731852" + } + ], + "1": [ + { + "index": "0", + "id": "1617104731852" + }, + { + "index": "0", + "id": "1617115013095" + } + ], + "2": [ + { + "index": "0", + "id": "1618393583970" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "edge": "undefined" + }, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1699964678894", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "modbus_to_dido", + "x": 96, + "y": 924, + "connections": { + "0": [ + { + "index": "0", + "id": "1699963668903" + }, + { + "index": "0", + "id": "1699964793925" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "modbus_to_dido", + "color": "gray" + }, + "options": { + "wirename": "modbus_to_dido" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1699964793925", + "component": "debug", + "tab": "1615551125555", + "name": "modbusToDido", + "x": 388, + "y": 920, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1699965957410", + "component": "modbus_reader", + "tab": "1611921777196", + "name": "Modbus reader", + "x": 232, + "y": 175, + "connections": { + "0": [ + { + "index": "0", + "id": "1611951142547" + } + ], + "1": [ + { + "index": "0", + "id": "1621340721628" + }, + { + "index": "0", + "id": "1684179110403" + }, + { + "index": "0", + "id": "1717441414646" + } + ], + "2": [ + { + "index": "0", + "id": "1615809595184" + }, + { + "index": "0", + "id": "1714752862828" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1700411878636", + "component": "thermometer", + "tab": "1611921777196", + "name": "Thermometer", + "x": 234.75, + "y": 444, + "connections": { + "0": [ + { + "index": "0", + "id": "1615802995322" + } + ], + "1": [ + { + "index": "0", + "id": "1615809595184" + }, + { + "index": "0", + "id": "1615809128443" + } + ], + "2": [ + { + "index": "0", + "id": "1621340721628" + }, + { + "index": "0", + "id": "1732889185927" + }, + { + "index": "0", + "id": "1717441414646" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#5CB36D", + "notes": "" + }, + { + "id": "1714752862828", + "component": "debug", + "tab": "1611921777196", + "name": "MDBToTb", + "x": 766, + "y": 324, + "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": 764.0833282470703, + "y": 222, + "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\telse if(value.status === \"NOK-thermometer\")\n\t{\n\t\tsend(0, {\"thermometer\": \"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\telse if(value.values.hasOwnProperty(\"temperature\"))\n\t{\n\t\tsend(0, {\"thermometer\": \"OK\"});\n\t}\n}", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1717442627834", + "component": "debug", + "tab": "1611921777196", + "name": "modbus service", + "x": 966.0833282470703, + "y": 165, + "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": 968.0833282470703, + "y": 268, + "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": 88.75, + "y": 1685, + "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": 296, + "y": 1671, + "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\", \"Flow has been restarted\", \"Node db has changed\"]", + "types": "[\"emergency\", \"critical\", \"error\", \"alert\"]", + "name": "" + }, + "color": "#30E193", + "notes": "" + }, + { + "id": "1718016073501", + "component": "httprequest", + "tab": "1612772287426", + "name": "http://192.168.252.2:8004/slack", + "x": 495, + "y": 1753, + "connections": { + "0": [ + { + "index": "0", + "id": "1718016086212" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "url": "http://192.168.252.2:8004/slack", + "method": "POST", + "stringify": "json" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1718016086212", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 832, + "y": 1664, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "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": 87, + "y": 1591, + "connections": { + "0": [ + { + "index": "0", + "id": "1718016052341" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "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\": \"\" } } } ] }", + "datatype": "object" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1729855334955", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "platform-rpc-call", + "x": 599.9333343505859, + "y": 541.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "platform-rpc-call", + "color": "gray" + }, + "options": { + "wirename": "platform-rpc-call" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1729855371093", + "component": "debug", + "tab": "1612772287426", + "name": "rpc cloud", + "x": 601.9333343505859, + "y": 440.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1731068658334", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 75.75, + "y": 184, + "connections": { + "0": [ + { + "index": "0", + "id": "1612776786008" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731068754606", + "component": "cloudmqttconnect", + "tab": "1612772287426", + "name": "MQTT to senica-prod01", + "x": 284.75, + "y": 452, + "connections": { + "1": [ + { + "index": "0", + "id": "1729855371093" + }, + { + "index": "0", + "id": "1729855334955" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Connected", + "color": "green" + }, + "options": { + "username": "", + "clientid": "", + "port": "2764", + "host": "192.168.252.2", + "topic": "" + }, + "color": "#888600", + "notes": "" + }, + { + "id": "1731069001548", + "component": "db_init", + "tab": "1612772287426", + "name": "DB Initialization", + "x": 1003.75, + "y": 240.25, + "connections": { + "0": [ + { + "index": "0", + "id": "1731069033416" + } + ], + "1": [ + { + "index": "0", + "id": "1747561603739" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#888600", + "notes": "" + }, + { + "id": "1731069033416", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "db-init", + "x": 1244.75, + "y": 233.25, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069059135", + "component": "showdb", + "tab": "1612772287426", + "name": "Show db data", + "x": 1186.75, + "y": 821.25, + "connections": { + "0": [ + { + "index": "0", + "id": "1731069079243" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#888600", + "notes": "" + }, + { + "id": "1731069079243", + "component": "debug", + "tab": "1612772287426", + "name": "dbData", + "x": 1390.75, + "y": 870.25, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1731069116691", + "component": "trigger", + "tab": "1612772287426", + "name": "settings", + "x": 934.75, + "y": 669.75, + "connections": { + "0": [ + { + "index": "0", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069131637", + "component": "trigger", + "tab": "1612772287426", + "name": "relaysData", + "x": 876.75, + "y": 733.75, + "connections": { + "0": [ + { + "index": "1", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069137374", + "component": "trigger", + "tab": "1612772287426", + "name": "nodesData", + "x": 852.75, + "y": 794.75, + "connections": { + "0": [ + { + "index": "2", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069179846", + "component": "trigger", + "tab": "1612772287426", + "name": "pinsData", + "x": 850.75, + "y": 861.75, + "connections": { + "0": [ + { + "index": "3", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069192937", + "component": "trigger", + "tab": "1612772287426", + "name": "sample data", + "x": 857.75, + "y": 928.75, + "connections": { + "0": [ + { + "index": "4", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069264443", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 63.75, + "y": 1279, + "connections": { + "0": [ + { + "index": "0", + "id": "1634488120710" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069334626", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "db-init", + "x": 172.88333129882812, + "y": 129, + "connections": { + "0": [ + { + "index": "0", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069548145", + "component": "virtualwirein", + "tab": "1611921777196", + "name": "db-init", + "x": 46.75, + "y": 192, + "connections": { + "0": [ + { + "index": "0", + "id": "1699965957410" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069567152", + "component": "virtualwirein", + "tab": "1611921777196", + "name": "db-init", + "x": 44.75, + "y": 465, + "connections": { + "0": [ + { + "index": "0", + "id": "1700411878636" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731070156936", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "db-init", + "x": 126.88333129882812, + "y": 1377, + "connections": { + "0": [ + { + "index": "2", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731234189516", + "component": "trigger", + "tab": "1612772287426", + "name": "monitor.txt", + "x": 882.75, + "y": 991.75, + "connections": { + "0": [ + { + "index": "5", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731234189551", + "component": "trigger", + "tab": "1612772287426", + "name": "err.txt", + "x": 904.75, + "y": 1053.75, + "connections": { + "0": [ + { + "index": "6", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1732700042559", + "component": "nodesdb_change_check", + "tab": "1612772287426", + "name": "Nodes DB change check", + "x": 266.8833312988281, + "y": 1980.2333984375, + "connections": { + "0": [ + { + "index": "0", + "id": "1732700071298" + }, + { + "index": "0", + "id": "1732700642917" + } + ], + "1": [ + { + "index": "0", + "id": "1759958914348" + }, + { + "index": "0", + "id": "1759959003114" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#888600", + "notes": "" + }, + { + "id": "1732700057052", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 76.75, + "y": 1988, + "connections": { + "0": [ + { + "index": "0", + "id": "1732700042559" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1732700071298", + "component": "debug", + "tab": "1612772287426", + "name": "nodesChange", + "x": 571.8833312988281, + "y": 2018.2333984375, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1732700642917", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "tb-push", + "x": 567.8833312988281, + "y": 1933, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1732889185927", + "component": "debug", + "tab": "1611921777196", + "name": "tempToDido", + "x": 594.8833312988281, + "y": 753, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1733574412965", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 72.75, + "y": 474, + "connections": { + "0": [ + { + "index": "1", + "id": "1731068754606" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1747561603739", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "send-to-services", + "x": 1243.8833312988281, + "y": 334.5, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1747562867845", + "component": "comment", + "tab": "1612772287426", + "name": "FLOW STARTING POINT", + "x": 1003.5666656494141, + "y": 178, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#704cff", + "notes": "" + }, + { + "id": "1749211698385", + "component": "trigger", + "tab": "1612772287426", + "name": "deviceStatus", + "x": 911.75, + "y": 1116.75, + "connections": { + "0": [ + { + "index": "7", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1757006030239", + "component": "httprequest", + "tab": "1615551125555", + "name": "192.168.252.2:8015/daily_report", + "x": 756.5666656494141, + "y": 715.4499969482422, + "connections": { + "0": [ + { + "index": "0", + "id": "1757006045804" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "stringify": "json", + "method": "POST", + "url": "http://192.168.252.2:8015/daily_report" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1757006045804", + "component": "debug", + "tab": "1615551125555", + "name": "ddd", + "x": 1091.566665649414, + "y": 711.4499969482422, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1757006060377", + "component": "debug", + "tab": "1615551125555", + "name": "reportDebug", + "x": 749.5666656494141, + "y": 799.4499969482422, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1759958914348", + "component": "httprequest", + "tab": "1612772287426", + "name": "http://192.168.252.2:8015/node_numbers", + "x": 571, + "y": 2111, + "connections": { + "0": [ + { + "index": "0", + "id": "1759958927094" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "stringify": "json", + "method": "POST", + "url": "http://192.168.252.2:8015/node_numbers" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1759958927094", + "component": "debug", + "tab": "1612772287426", + "name": "nodesChangeCloud", + "x": 951.8833312988281, + "y": 2109.2333984375, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1759959003114", + "component": "debug", + "tab": "1612772287426", + "name": "nodeChangeCloud1", + "x": 574, + "y": 2218, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1760020290879", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 84.75, + "y": 1787, + "connections": { + "0": [ + { + "index": "1", + "id": "1718016052341" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + } + ], + "version": 615 +} diff --git a/RVO21/flow/dido_controller.js b/RVO21/flow/dido_controller.js new file mode 100755 index 0000000..d16fb19 --- /dev/null +++ b/RVO21/flow/dido_controller.js @@ -0,0 +1,1486 @@ +exports.id = 'dido_controller'; +exports.title = 'DIDO_Controller'; +exports.version = '2.0.0'; +exports.group = 'Worksys'; +exports.color = '#2134B0'; +exports.input = 3; +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 + +state_of_main_switch - reportovat stav hlaveho istica : 0-> off 1-> on +rotary_switch_state - sem by sa mal reportovat stav vstupov manual a auto pola nasledovnej logiky: Manual = 1 a Auto = 0 -> Manu +Manual = 0 a Auto = 0 -> Off, Manual = 0 a Auto = 1 -> Automatic + +door_condition - pin 6, dverový kontakt -> 1 -> vyreportuje Closed, 0 -> vyreportuje Ope +twilight_sensor - hodnotu, ktoru vracia ten analogovy vstup (17) treba poslat sem ako float number. Zrejme tu potom pridame nejaky koeficient prevodu na luxy + +Na kazdu liniu +state_of_breaker - podla indexu istica sa reportuje jeho stav, teda istic na liniu 1: 0-> off, 1-> on +state_of_contactor - podla indexu stkaca sa reportuje jeho stav, teda stykac 1 na liniu 1: 0-> off, 1-> on +*/ + +const { errLogger, logger, monitor } = require('./helper/logger'); +const SerialPort = require('serialport'); +const WebSocket = require('ws'); +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 errorHandler = require('./helper/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 hasMainSwitch; + +let alarmStatus = "OFF"; + +const SEND_TO = { + debug: 0, + tb: 1, + cmd_manager: 2 +} + + +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 = {}; + let rsPortReceivedData = []; + + //to be able to get proper twilight values + let twilight_sensor_interval = 5;//minutes + let twilight_sensor = []; + const twilight_sensor_array = []; + let twilightError = false; + + monitor.info("DIDO_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-we make it global to see it from outside + FLOW.deviceStatus = { //key is device name: temperature,.... + "state_of_main_switch": "Off", //Hlavny istic (alebo druhy dverovy kontakt) + "rotary_switch_state": "Off", //Prevadzkovy + "door_condition": "closed", //Dverový kontakt + "em": "OK", //elektromer rvo + "temperature": "OK", //templomer + "battery": "OK", //Bateria + "power_supply": "OK", //Zdroj + "master_node": "OK", //MN - GLOBALS.settings.masterNodeIsResponding + "no_voltage": "OK", //GLOBALS.settings.no_voltage - vypadok napatia na faze + "state_of_breaker": {}, //"Off",//Istic + "state_of_contactor": {}, //"Off",//Stykac + "twilight_sensor": "OK" //lux sensor + }; + let deviceStatus = FLOW.deviceStatus; + + + function main() { + + GLOBALS = FLOW.GLOBALS; + SETTINGS = FLOW.GLOBALS.settings; + rvoTbName = SETTINGS.rvoTbName; + pinsData = GLOBALS.pinsData; + relaysData = GLOBALS.relaysData; + + tbHandler = new DataToTbHandler(SEND_TO.tb); + tbHandler.setSender(exports.title); + + controller_type = SETTINGS.controller_type; //"lm" or "unipi" + hasMainSwitch = SETTINGS.has_main_switch; + + if (controller_type == "") controller_type = "lm"; + + 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, "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; + } + } + + //report RVO version relaysData[0].tbname; + let values = {}; + values["edge_fw_version"] = SETTINGS.edge_fw_version; + values["maintenance_mode"] = SETTINGS.maintenance_mode; + + sendTelemetry(values, rvoTbName); + + 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); + } + + + function handleRsPort() { + + if (rsPort) { + rsPort.removeAllListeners(); + rsPort = null; + } + + //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('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) { + if (!err) { + monitor.info(exports.title + "--->Digital in_out has been set (runSyncExec was sucessfull)"); + + turnAlarm("off"); + 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('error', err => { + let message = "Dido: rsPort error: " + err.message; + logger.debug(message); + monitor.info(message); + errorHandler.sendMessageToService(message); + }) + + rsPort.on("close", () => { + let message = "Dido: rsPort closed - reconnecting ..."; + logger.debug(message); + monitor.info(message); + setTimeout(handleRsPort, 1000); + }) + + rsPort.open(); + } + + + function handleWebSocket() { + + if (ws) { + ws.removeAllListeners(); + ws = null; + } + + //to keep websocket opened, we send request every 150 seconds + let startRequests = null; + + console.log("handleWebSocket function called"); + ws = new WebSocket('ws:/0.0.0.0:1234/ws'); + + ws.onopen = function open() { + + instance.send(0, exports.title + " running"); + turnAlarm("off"); + + initialSetting(); + + setTimeout(function() { ws.send(JSON.stringify({ cmd: "all" })) }, 5000); + // we request dev info about neuron device from evok to keep websocket connection alive + // for some reason this request returns no data, but connection keeps alive + startRequests = setInterval(() => { + ws.send(JSON.stringify({ "cmd": "filter", "dev": ["neuron"] })); + }, 150000) + }; + + + // 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 = async 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; + + 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 => { + logger.debug('Dido: websocket error', err); + }) + + ws.onclose = function() { + logger.debug('Dido: websocket onclose, reconnecting...') + clearInterval(startRequests); + setTimeout(handleWebSocket, 1000); + } + } + + 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 turnAlarm(onOrOff) { + let value = 0; + if (onOrOff == "on") value = 1; + + if (value == 1 && SETTINGS.maintenance_mode) return; + + alarmStatus = "OFF"; + if (value == 1) alarmStatus = "ON"; + + if (rsPort) { + let arr = [0x55]; + arr.push(13); + arr.push(0); + arr.push(value); + + rsPort.write(Buffer.from(arr), function(err) { + logger.debug(`sirena - ${onOrOff}`); + }); + } + else if (ws) { + let cmd = { "cmd": "set", "dev": "relay", "circuit": "1_01", "value": value }; + ws.send(JSON.stringify(cmd)); + logger.debug(`sirena - ${onOrOff}`); + } + } + + + 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") { + bits.push(0); + } + else bits.push(1); + + if (deviceStatus["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); + } + + + // turn line on or off + function turnLine(onOrOff, line, pin, force, info) { + //onOrOff => "on" or "off" + let value = 0; + if (onOrOff == "on") value = 1; + + if (force == undefined) force = false; + + if (line == 0) { + if (value == 1 && alarmStatus == "ON") turnAlarm("off"); + SETTINGS.maintenance_mode = value ? true : false; + + 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); + return; + } + + if (pin === undefined) pin = getPin(line); + + if (pin === undefined) { + errLogger.error("pin is undefined!", line); + return; + } + + if (!force) { + if (relaysData[line].contactor == value) { + instance.send(SEND_TO.debug, `line is already ${onOrOff} ` + line); + logger.debug(`Dido: turnLine: line is already ${onOrOff} `, line); + return; + } + } + + // if(!rsPort.isOpen && !ws) + if (!rsPort && !ws) { + errLogger.error("Dido - port or websocket is not opened"); + return; + } + + if (rsPort) { + let arr = [0x55]; + arr.push(pin); + arr.push(0); + arr.push(value); + + rsPort.write(Buffer.from(arr), function(err) { + if (err === undefined) { + monitor.info(`Dido: turnLine ${onOrOff} zapisal do rsPort-u`, line, pin, arr, info); + switchLogic(arr); + } + else { + monitor.info(`Dido: turnLine ${onOrOff} WRITE error`, err); + } + }); + + } + else if (ws) { + //pin = "relay1_03" or "input1_01" ... we must make just "1_01" with slice method + monitor.info(`Dido: turnLine ${onOrOff} - (line, pin, force)`, line, pin, force, info); + let cmd = { "cmd": "set", "dev": "relay", "circuit": pin.slice(5), "value": value }; + ws.send(JSON.stringify(cmd)); + } + + //if rvo is 24/7, it has just one switching profile point at 13:00. we do not want to send notification as it repeats every day. + //const d = new Date(); + //if(d.getHours() != 13) sendNotification("Dido_controller: ", SETTINGS.rvoTbName, "switching_profile_point_applied_to_line", { line: line, value: onOrOff }, "", SEND_TO.tb, instance); + } + + + // 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; + + // 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) { + const status = flowdata.data.status; + if (status == "NOK-twilight_sensor") { + deviceStatus["twilight_sensor"] = "NOK"; + } + else if (status == "NOK-em340" || status == "NOK-em111") { + deviceStatus["em"] = "NOK"; + } + else if (status == "NOK-thermometer") { + deviceStatus["temperature"] = "NOK"; + } + } + else if ("values" in flowdata.data) { + 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" + } + else if (values.hasOwnProperty("temperature")) { + deviceStatus["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"; + } + + sendTelemetry(values, rvoTbName); + } + + sendRvoStatus(); + }) + + + + + // we expect array as flowdata.data + instance.on("1", flowdata => { + + //console.log(flowdata.data); + + if (!flowdata.data instanceof Object) return; + + let obj = flowdata.data; + let line = obj.line; + 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"); + }) + + + function calculateStateCode() { + + let bits = []; + + //Hlavny istic - state_of_main_switch => v rvo senica je to druhy door pre silovu cast (EM) + if (deviceStatus["state_of_main_switch"] === "closed" || deviceStatus["state_of_main_switch"] === "Off") { + bits.push(0); + } + else { + bits.push(1); + } + + //Prevadzkovy mod - Manual, Off, Automatic, maintenance_mode = true/false // DAVA 2 BITY + if (!SETTINGS.maintenance_mode) { + if (deviceStatus["rotary_switch_state"] === "Manual") { + bits.push(0); + bits.push(1); + } + + if (deviceStatus["rotary_switch_state"] === "Automatic") { + bits.push(0); + bits.push(0); + } + + if (deviceStatus["rotary_switch_state"] === "Off") { + bits.push(1); + bits.push(0); + } + } + else { + bits.push(1); + bits.push(1); + } + + //Dverovy kontakt + if (deviceStatus["door_condition"] === "closed") { + bits.push(0); + } + else { + bits.push(1); + } + + //EM + if (deviceStatus["em"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //Teplomer + if (deviceStatus["temperature"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //Batéria + if (deviceStatus["battery"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //Zdroj + if (deviceStatus["power_supply"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //MN + if (deviceStatus["master_node"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //výpadok napätia na fáze + if (deviceStatus["no_voltage"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + if (deviceStatus["twilight_sensor"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + // doplnime do 16 bitov (2 byty) + for (let i = bits.length; i < 16; i++) { + bits.push(0); + } + + // console.log("calculateStateCode - deviceStatus", deviceStatus); + // 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; + } + + + async function sendRvoStatus() { + + if (SETTINGS === undefined) return; + SETTINGS.masterNodeIsResponding ? deviceStatus["master_node"] = "OK" : deviceStatus["master_node"] = "NOK"; + + 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 pinsForRvoStatus(controllerType, hasMainSwitch) { + + let pins = []; + + if (controllerType === "lm") { + pins = [1, 4, 6]; + if (hasMainSwitch === 1) { + pins = [4, 6]; + } + } else if (controllerType === "unipi") { + pins = ["input1_01", "input1_04", "input1_05"]; + if (hasMainSwitch === 1) { + pins = ["input1_01", "input1_04"]; + } + } + + return pins; + } + + + function checkRvoStatus() { + + // 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 + //set RVO state + let status = "OK"; + + for (const [key, value] of Object.entries(deviceStatus)) { + if (["em", "twilight_sensor", "temperature", "master_node"].includes(key) && value === "NOK") status = "NOK"; + } + + if (status === "OK") { + + let pinIndexes = pinsForRvoStatus(controller_type, hasMainSwitch); + + for (const pinIndex of pinIndexes) { + if (previousValues[pinIndex] === 0) { + if ((pinIndex === 6 || pinIndex === 'input1_01' || pinIndex === 'input1_05') && SETTINGS.maintenance_mode) continue; + status = "NOK"; + break; + } + } + } + + // battery status. If value is 1 - battery is NOK + if (previousValues[5] === 1) status = "NOK"; + if (SETTINGS.no_voltage.size > 0) status = "NOK"; + + // console.log("rvo status",status) + return status; + } + + + // we pass array to function in case of rsPort ==> switchLogic([55,3,0,1]) ==> [[55,3,0,1]] + // we pass two values in case of websocket ==> switchLogic("relay1_03",1) ==> ["relay1_03",1] + const switchLogic = (...args) => { + + let values = {}; + let pinIndex, newPinValue, twilight; + + //data from rsPort + if (args.length == 1) { + pinIndex = args[0][1] + 1; + if (pinIndex === 17) pinIndex--; + newPinValue = args[0][3]; + twilight = args[0][2]; + } + //data from websocket + else { + pinIndex = args[0]; + newPinValue = args[1]; + } + + 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; + + //default value + let value = "On"; + if (newPinValue === 0) value = "Off"; + + //Hlavny istic + if (type === "state_of_main_switch" && hasMainSwitch) { + if (newPinValue === 0 && newPinValue !== previousValues[pinIndex]) { + sendNotification("switchLogic", rvoTbName, "main_switch_has_been_turned_off", {}, "", SEND_TO.tb, instance, "state_of_main_switch"); + 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"); + deviceStatus["state_of_main_switch"] = "On"; + } + } + + //Prevadzkovy mod + 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"; + + deviceStatus["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, "power_supply_has_disconnected_input", {}, "", SEND_TO.tb, instance, "power_supply"); + + deviceStatus["power_supply"] = "NOK"; + } + else if (newPinValue === 1 && newPinValue !== previousValues[pinIndex]) { + sendNotification("switchLogic", rvoTbName, "power_supply_works_correctly", {}, "", SEND_TO.tb, instance, "power_supply"); + + deviceStatus["power_supply"] = "OK"; + } + } + + //Bateria - 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"); + + deviceStatus["battery"] = "NOK"; + } + else if (newPinValue === 0 && newPinValue !== previousValues[pinIndex]) { + sendNotification("switchLogic", rvoTbName, "battery_level_is_ok", {}, "", SEND_TO.tb, instance, "battery_level"); + + deviceStatus["battery"] = "OK"; + } + } + + //Dverovy kontakt - pin 6 + //! Ak je rvo s dvoma dverovymi kontaktami, ked pride z evoku signal z input1_05, co bol predytm "state_of_main switch" handlujeme ho teraz ako 'door_condition' + else if (type == "door_condition" || type === "state_of_main_switch") { + newPinValue === 0 ? value = "open" : value = "closed"; + + let door = "door_main"; + if (type === "state_of_main_switch") door = "door_em"; + + if (value === "open") { + if (SETTINGS.maintenance_mode) { + sendNotification("switchLogic", rvoTbName, door + "_open", {}, "", SEND_TO.tb, instance, door); + } else { + sendNotification("switchLogic", rvoTbName, door + "_open_without_permission", {}, "", SEND_TO.tb, instance, door); + + // 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 (value === "closed") { + if (alarmStatus == "ON") turnAlarm("off"); + sendNotification("switchLogic", rvoTbName, door + "_close", {}, "", SEND_TO.tb, instance, door); + } + + deviceStatus[type] = value; + } + + //lux sensor + else if (type == "twilight_sensor") { + //! TODO - to show nok status, if lux value is not changing more then 10 times. + //Daylight is far more than 1000. So most of the day, when it is sunshine comes just value 1000. But lux sensor is not NOK. + //This is not the case in LM. If value from LM is the same 10x, there is 99% possibility, that sensor is NOK. + value = newPinValue; + + if (controller_type === 'lm') { + value = parseFloat(newPinValue + (256 * twilight)); + + 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 && !twilightError) { + twilightError = true; + let value = twilight_sensor_array.shift(); + + newPinValue = 0; + } + else if (set.size !== 1 && twilightError) { + //sendNotification("switchLogic", rvoTbName, 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) { + 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); + } + } + + 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); + } + + deviceStatus["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 (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 }); + + //mame iba 3 istice. vyreportujeme a ohandlujeme liniu na tom istom istici ako paralelna linia (napr linia 1, paralelna s nou je linia 4, key je string "4") + // ak je 7 linii, na 1 istici je linia 1,4,7 + + if (line == 1) { + + const lineOnSameBraker = [4, 7]; + + for (var i = 0; i < lineOnSameBraker.length; i++) { + if (!relaysData.hasOwnProperty(lineOnSameBraker[i])) continue; + + 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; + reportLineStatus(lineOnSameBraker[i]); + + values[type] = value; + const tbname = relaysData[lineOnSameBraker[i]].tbname; + sendTelemetry(values, tbname); + + delete values[type]; + } + + } + else { + const lineOnSameBraker = line + 3 + ""; + + if (relaysData.hasOwnProperty(lineOnSameBraker)) { + 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; + reportLineStatus(line + 3); + + values[type] = value; + const tbname = relaysData[lineOnSameBraker].tbname; + sendTelemetry(values, tbname); + + delete values[type]; + } + } + + } + + if (value == "Off") values["status"] = "NOK"; + deviceStatus["state_of_breaker"][line] = value; + + reportLineStatus(line); + } + else return; + + values[type] = value; + + if (type == "rotary_switch_state") { + if (SETTINGS.maintenance_mode) value = "maintenance"; + value = value.toLowerCase(); + values["power_mode"] = value; + } + + if (newPinValue != previousValues[pinIndex]) previousValues[pinIndex] = newPinValue; + if (Object.keys(values).length > 0 && tbname) sendTelemetry(values, tbname); + } + + + function sendTelemetry(values, tbname, date = Date.now()) { + let dataToTb = { + [tbname]: [ + { + "ts": date, + "values": values + } + ] + }; + + tbHandler.sendToTb(dataToTb, instance); + } + + + function isObject(item) { + return (typeof item === "object" && !Array.isArray(item) && item !== null); + } + +} //end of 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 +// *|input1_01|state_of_main_switch|0|........... +// *|input1_02|rotary_switch_state|0|........... +// *|input1_03|rotary_switch_state|0|........... +// *|intut1_04|power_supply|0|........... +// *|input1_05|door_condition|0|........... +// *|input1_06|state_of_breaker|1|........... +// *|input1_07|state_of_breaker|2|........... +// *|input1_08|state_of_breaker|3|........... +// *|relay1_02|state_of_contactor|1|........... +// *|relay1_03|state_of_contactor|2|........... +// *|relay1_04|state_of_contactor|3|........... +// *|287D8776E0013CE9|temperature|0|........... + + +//! pins_data --> from UNIPI +// { +// 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 } +// } + +//! relays_data +// { +// '0': { +// line: 0, +// tbname: 'KjbN4q7JPZmexgdnz2yKQ98YAWwO0Q3BMX6ERLoV', +// contactor: 1, +// profile: '' +// }, +// '1': { +// line: 1, +// tbname: 'RMgnK93rkoAazbqdQ4yBG95Z1YXGx6pmwBeVEP2O', +// contactor: 0, +// profile: '{"intervals":[{"value":0,"end_time":"20:00","start_time":"13:00"},{"value":1,"end_time":"10:00","start_time":"20:00"},{"value":0,"end_time":"10:20","start_time":"10:00"},{"value":1,"end_time":"10:40","start_time":"10:20"},{"value":0,"end_time":"11:00","start_time":"10:40"},{"value":1,"end_time":"11:30","start_time":"11:00"},{"value":0,"end_time":"11:50","start_time":"11:30"},{"value":1,"end_time":"13:00","start_time":"11:50"}],"astro_clock":false,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' +// }, +// '2': { +// line: 2, +// tbname: 'dlE1VQjYrNx9gZRmb38gG08oLBO4qaAk2M6JPnG7', +// contactor: 0, +// profile: '{"intervals":[{"value":0,"end_time":"20:00","start_time":"13:00"},{"value":1,"end_time":"10:00","start_time":"20:00"},{"value":0,"end_time":"10:20","start_time":"10:00"},{"value":1,"end_time":"10:40","start_time":"10:20"},{"value":0,"end_time":"11:00","start_time":"10:40"},{"value":1,"end_time":"11:30","start_time":"11:00"},{"value":0,"end_time":"11:50","start_time":"11:30"},{"value":1,"end_time":"13:00","start_time":"11:50"}],"astro_clock":false,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' +// }, +// '3': { +// line: 3, +// tbname: 'vnmG4kJxaXWNBgMQq0D7Aj5e9oZzOAlr6LdR3w2V', +// contactor: 0, +// profile: '{"intervals":[{"value":0,"end_time":"20:30","start_time":"13:00"},{"value":1,"end_time":"00:10","start_time":"20:30"},{"value":0,"end_time":"13:00","start_time":"05:40"},{"value":1,"end_time":"05:40","start_time":"00:10"}],"astro_clock":true,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' +// } +// } + + + + + +// { +// "jbN4q7JPZmexgdnz2yKbWGDYAWwO0Q3BMX6ERLoV": [ +// { +// "ts": 1700409326353, +// "values": { +// "_event": { +// "type": "notice", +// "status": "new", +// "source": { +// "func": "rsPort.open()", +// "component": "1700343402190", +// "component_name": "DIDO_Controller", +// "edge": "jbN4q7JPZmexgdnz2yKbWGDYAWwO0Q3BMX6ERLoV" +// }, +// "message": "al_shariff_10.0.0.38: FLOW has been started ", +// "message_data": "" +// } +// } +// } +// ] +// } diff --git a/RVO21/flow/helper/DataToTbHandler.js b/RVO21/flow/helper/DataToTbHandler.js new file mode 100755 index 0000000..716ef7b --- /dev/null +++ b/RVO21/flow/helper/DataToTbHandler.js @@ -0,0 +1,187 @@ +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; + this.itIsNodeReadout = false; + this.sender = ""; + + // if attribute change difference is less than limit value, we do not send to tb. + this.attributeChangeLimit = { + temperature: 0.5, + Phase_1_voltage: 2, + Phase_2_voltage: 2, + Phase_3_voltage: 2, + Phase_1_current: 0.1, + Phase_2_current: 0.1, + Phase_3_current: 0.1, + Phase_1_power: 2, + Phase_2_power: 2, + Phase_3_power: 2, + total_power: 2, + total_energy: 1, + Phase_1_pow_factor: 0.1, + Phase_2_pow_factor: 0.1, + Phase_3_pow_factor: 0.1, + power_factor: 0.1, + lifetime: 2, + voltage: 2, + power: 2, + frequency: 3, + energy: 0.1, + current: 2, + inclination_x: 10, + inclination_y: 10, + inclination_z: 10 + }; + + } + + dump() { + console.log("----------------------------"); + console.log("previousValues", this.previousValues); + console.log("----------------------------"); + } + + setSender(sender) { + this.sender = sender; + } + + isEmptyObject(obj) { + for (var _ in obj) { + return false; + } + return true; + } + + + sendToTb(data, instance) { + + //not to modify data object, we do deep copy: + let dataCopy = JSON.parse(JSON.stringify(data)); + + let keys = Object.keys(dataCopy); + + if (keys.length == 0) { + if (this.debug) console.log("sendToTb received empty object", dataCopy); + return; + } + + let tbname = keys[0]; + let ts; + + let arrayOfValues = dataCopy[tbname]; + let arrayOfValuesToSend = []; + + for (let i = 0; i < arrayOfValues.length; i++) { + + ts = arrayOfValues[i].ts; + let values = this.prepareValuesForTb(tbname, ts, arrayOfValues[i].values); + + if (!this.isEmptyObject(values)) { + arrayOfValuesToSend.push({ ts: ts, values: values }); + } + + } + + if (arrayOfValuesToSend.length == 0) { + //if(this.debug) console.log("data not sent - empty array"); + return; + } + + this.messageCounter++; + + let dataToTbModified = { + [tbname]: arrayOfValuesToSend + } + + //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); + instance.send(this.index, dataToTbModified); + } + + + getDiffTimestamp(key) { + //TODO set different value for given key!!! + //if(key == "status") this.timeToHoldTbValue = 2*60*60;//2h + return this.timeToHoldTbValue * 1000; + } + + + prepareValuesForTb(tbname, timestamp, values) { + + let keys = Object.keys(values); + + if (keys.includes("lifetime")) this.itIsNodeReadout = true; + + if (!this.previousValues.hasOwnProperty(tbname)) { + this.previousValues[tbname] = {}; + } + + //if(this.debug) console.log("prepareValuesForTb", tbname, timestamp, values); + + for (let i = 0; i < keys.length; i++) { + + let key = keys[i]; + let value = values[key]; + + if (!this.previousValues[tbname].hasOwnProperty(key)) { + this.previousValues[tbname][key] = { ts: timestamp, value: value }; + continue; + } + + // attributeData ==> {voltage: {ts:333333, value:5}} + let attributeData = this.previousValues[tbname][key]; + let attributeToChange = false; + if (key in this.attributeChangeLimit) attributeToChange = true; + let limit = this.attributeChangeLimit[key]; + let timestampDiffToRemoveKey; + + //this will ensure "node statecode" will be sent just once an hour + if (this.itIsNodeReadout && key === "statecode") { + attributeData.value = value; + this.itIsNodeReadout = false; + timestampDiffToRemoveKey = 1 * 60 * 60 * 1000; // 1 hour + } + + if (key === "twilight_sensor" && value > 100) { + attributeData.value = value; + } + + //if edge, master or node version do not change, send just once a day: + if (["edge_fw_version", "master_node_version", "fw_version"].includes(key)) { + timestampDiffToRemoveKey = 24 * 60 * 60 * 1000; + } + + if (attributeData.value === value || attributeToChange && Math.abs(attributeData.value - value) < limit) { + + let diff = timestamp - attributeData.ts; + if (!timestampDiffToRemoveKey) timestampDiffToRemoveKey = this.getDiffTimestamp(key); + + if (diff > timestampDiffToRemoveKey) { + attributeData.ts = Date.now(); + //if(this.debug) console.log(this.sender + ": update ts for key", key, "diff is", diff, "messageCounter", this.messageCounter); + } + else { + delete values[key]; + //if(this.debug) console.log(this.sender + ": delete key", key, "diff is", diff, "messageCounter", this.messageCounter, timestampDiffToRemoveKey); + } + } + else { + attributeData.value = value; + attributeData.ts = timestamp; + } + + } + + return values; + } +} + +module.exports = DataToTbHandler; + diff --git a/RVO21/flow/helper/ErrorToServiceHandler.js b/RVO21/flow/helper/ErrorToServiceHandler.js new file mode 100755 index 0000000..2b27c32 --- /dev/null +++ b/RVO21/flow/helper/ErrorToServiceHandler.js @@ -0,0 +1,91 @@ +const { MD5 } = require('./md5.js'); +const { networkInterfaces } = require('os'); + +class ErrorToServiceHandler { + constructor() { + this.previousValues = {}; + + this.project_id = undefined; + + const nets = networkInterfaces(); + this.ipAddresses = {}; + + for (const name of Object.keys(nets)) { + for (const net of nets[name]) { + // Skip over non-IPv4 and internal (i.e. 127.0.0.1) addresses + if (net.family === 'IPv4' && !net.internal) { + if (!this.ipAddresses[name]) { + this.ipAddresses[name] = []; + } + this.ipAddresses[name].push(net.address); + } + } + } + } + + setProjectId(project_id) { + this.project_id = project_id; + } + + processMessage(message, seconds) { + if (Array.isArray(message)) message = message.join(', '); + + let key = MD5(message); + let ts = Date.now(); + + //keep in memory - default value is 1h + if (seconds === undefined) seconds = 60 * 60; + + if (!this.previousValues.hasOwnProperty(key)) { + this.previousValues[key] = { ts: ts, duration: seconds }; + } + + let diff = (ts - this.previousValues[key].ts); + if (diff < this.previousValues[key].duration * 1000) return false; + + this.previousValues[key].ts = ts; + + return message; + } + + sendMessageToService(message, seconds, message_type) { + + // if error occures too early FLOW.GLOBALS.settings.project_id is still undefined + if (this.project_id === undefined) { + console.log("ErrorToServiceHandler.js: no project_id"); + return; + } + + let f = this.processMessage(message, seconds); + if (f === false) return; + + if (message_type === undefined) message_type = "error_message"; + + let toService = { + id: this.project_id, + ipAddresses: this.ipAddresses + }; + + //js_error || error_message + toService[message_type] = message; + + console.log("ErrorToServiceHandler------------------------>send to service", toService); + + RESTBuilder.make(function(builder) { + builder.method('POST'); + builder.post(toService); + builder.url('http://192.168.252.2:8004/sentmessage'); + + builder.callback(function(err, response, output) { + console.log("process.on error send", err, response, output, toService); + }); + }); + + } +} + +const errorHandler = new ErrorToServiceHandler(); + + +module.exports = errorHandler; +//module.exports = ErrorToServiceHandler; diff --git a/RVO21/flow/helper/db_helper.js b/RVO21/flow/helper/db_helper.js new file mode 100755 index 0000000..40e796c --- /dev/null +++ b/RVO21/flow/helper/db_helper.js @@ -0,0 +1,44 @@ +function promisifyBuilder(builder) +{ + return new Promise((resolve, reject) => { + + try{ + + builder.callback(function(err, response) { + + if(err != null) reject(err); + resolve(response); + }); + + } catch (error) { + reject(error); + } + }) +} + +function makeMapFromDbResult(response, ...keys) +{ + let s = "-"; + let data = {}; + + for(let i = 0; i < response.length; i++) + { + let record = response[i]; + + let k = []; + for(let j = 0; j < keys.length; j++) + { + k.push( record[keys[j]] ); + } + + let key = k.join(s); + data[ key ] = record; + } + + return data; +} + +module.exports = { + promisifyBuilder, + makeMapFromDbResult + } \ No newline at end of file diff --git a/RVO21/flow/helper/logger.js b/RVO21/flow/helper/logger.js new file mode 100755 index 0000000..2585639 --- /dev/null +++ b/RVO21/flow/helper/logger.js @@ -0,0 +1,30 @@ +//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/RVO21/flow/helper/md5.js b/RVO21/flow/helper/md5.js new file mode 100755 index 0000000..d3b0480 --- /dev/null +++ b/RVO21/flow/helper/md5.js @@ -0,0 +1,5 @@ +function MD5(d){var r = M(V(Y(X(d),8*d.length)));return r.toLowerCase()};function M(d){for(var _,m="0123456789ABCDEF",f="",r=0;r>>4&15)+m.charAt(15&_);return f}function X(d){for(var _=Array(d.length>>2),m=0;m<_.length;m++)_[m]=0;for(m=0;m<8*d.length;m+=8)_[m>>5]|=(255&d.charCodeAt(m/8))<>5]>>>m%32&255);return _}function Y(d,_){d[_>>5]|=128<<_%32,d[14+(_+64>>>9<<4)]=_;for(var m=1732584193,f=-271733879,r=-1732584194,i=271733878,n=0;n>16)+(_>>16)+(m>>16)<<16|65535&m}function bit_rol(d,_){return d<<_|d>>>32-_} + +module.exports = { + MD5 +} \ No newline at end of file diff --git a/RVO21/flow/helper/notification_reporter.js b/RVO21/flow/helper/notification_reporter.js new file mode 100755 index 0000000..839c12c --- /dev/null +++ b/RVO21/flow/helper/notification_reporter.js @@ -0,0 +1,121 @@ +//key is device, value = message {} +let sentValues = {}; +let notificationsData = null; +let rvoName; + +//sendNotification("CMD Manager: process cmd", SETTINGS.rvoTbName, "dimming_profile_was_successfully_received_by_node", { node: node }, "", SEND_TO.tb, instance); + +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 +}; + +function getKey(map, val) { + return Object.keys(map).findItem(key => map[key] === val); +} + +//https://stackoverflow.com/questions/41117799/string-interpolation-on-variable +var template = (tpl, args) => tpl.replace(/\${(\w+)}/g, (_, v) => args[v]); + + +function initNotification() { + notificationsData = FLOW.GLOBALS.notificationsData; + rvoName = FLOW.GLOBALS.settings.rvo_name; +} + + +function sendNotification(func, device, key, params, extra, tb_output, instance, saveKey) { + + let storeToSendValues = true; + if (saveKey == undefined) storeToSendValues = false; + + let weight = ""; + let message = {}; + + let notification = notificationsData[key]; + + if (notification) { + weight = notification.weight.toLowerCase(); + + Object.keys(notification).forEach(item => { + if (["en", "sk", "de", "cz", "it", "es"].includes(item)) { + message[item] = rvoName + ": " + template(notification[item], params); + } + }) + } + else { + //console.error("sendNotification: Notifications: undefined key", key, func, notificationsData); + console.error("sendNotification: Notifications: undefined key", key, func); + return false; + } + + //detect invalid err weight + if (getKey(ERRWEIGHT, weight) == undefined) { + console.error("sendNotification: Notifications: undefined weight", weight, key, func); + return false; + } + + if (sentValues.hasOwnProperty(saveKey)) { + if (JSON.stringify(sentValues[saveKey]) == JSON.stringify(message)) { + return false; + } + } + + if (sentValues[saveKey] == undefined) { + if (storeToSendValues) { + //do not send - flow is was started + sentValues[saveKey] = message; + return false; + } + } + + if (storeToSendValues) sentValues[saveKey] = message; + + let content = { + "type": weight, + "status": "new", + "source": { + "func": func, + "component": instance.id, + "component_name": instance.name, + "edge": device + }, + "message": message, + "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 + + return true; + +} + +module.exports = { + sendNotification, + ERRWEIGHT, + initNotification +} + diff --git a/RVO21/flow/helper/register.js b/RVO21/flow/helper/register.js new file mode 100755 index 0000000..fc1d008 --- /dev/null +++ b/RVO21/flow/helper/register.js @@ -0,0 +1,144 @@ +/* +0 - cislo registra / prikaz +1 - recepient - 0 = master, 1 = slave (slave je automaticky group a broadcast) +2 - r/rw - read/write +3- register name - nazov registra / prikazu (len pre info - zobrazenie v aplikacii) + +4,5,6,7, - jednotlive byte-y - nazov byte-u +4-7 - RES. a prazdny string "" sa nezobrazia!!! +*/ + +//124 zaznamov +const registers = [ + ["0","1","R","Status","","",""], + ["1","1","RW","Dimming","R-Channel ","G-Channel","B-Channel ","W - Channel"], + ["2","1","R","Device types","","",".",""], + ["3","1","RW","Group addresses 1-4","Groups Add. 4","Groups Add. 3","Groups Add. 2","Groups Add. 1"], + ["4","1","RW","Group addresses 5-8","Groups Add. 8","Groups Add. 7","Groups Add. 6","Groups Add. 5"], + ["5","1","RW","Serial number (MAC)","","","",""], + ["6","1","RW","Time of dusk","HH","MM","SS","EXTRA"], + ["7","1","RW","Time of dawn","HH","MM","SS","EXTRA"], + ["8","1","RW","Time Schedule settings","TBD","TBD","Movement sensor","Time Schedule"], + ["9","1","RW","TS1 Time point 1","HH","MM","SS","Ext. Device"], + ["10","1","RW","TS1 Time point 1 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["11","1","RW","TS1 Time point 2","HH","MM","SS","Ext. Device"], + ["12","1","RW","TS1 Time point 2 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["13","1","RW","TS1 Time point 3","HH","MM","SS","Ext. Device"], + ["14","1","RW","TS1 Time point 3 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["15","1","RW","TS1 Time point 4","HH","MM","SS","Ext. Device"], + ["16","1","RW","TS1 Time point 4 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["17","1","RW","TS1 Time point 5","HH","MM","SS","Ext. Device"], + ["18","1","RW","TS1 Time point 5 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["19","1","RW","TS1 Time point 6","HH","MM","SS","Ext. Device"], + ["20","1","RW","TS1 Time point 6 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["21","1","RW","TS1 Time point 7","HH","MM","SS","Ext. Device"], + ["22","1","RW","TS1 Time point 7 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["23","1","RW","TS1 Time point 8","HH","MM","SS","Ext. Device"], + ["24","1","RW","TS1 Time point 8 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["25","1","RW","TS1 Time point 9","HH","MM","SS","Ext. Device"], + ["26","1","RW","TS1 Time point 9 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["27","1","RW","TS1 Time point 10","HH","MM","SS","Ext. Device"], + ["28","1","RW","TS1 Time point 10 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["29","1","RW","TS1 Time point 11","HH","MM","SS","Ext. Device"], + ["30","1","RW","TS1 Time point 11 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["31","1","RW","TS1 Time point 12","HH","MM","SS","Ext. Device"], + ["32","1","RW","TS1 Time point 12 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["33","1","RW","TS1 Time point 13","HH","MM","SS","Ext. Device"], + ["34","1","RW","TS1 Time point 13 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["35","1","RW","TS1 Time point 14","HH","MM","SS","Ext. Device"], + ["36","1","RW","TS1 Time point 14 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["37","1","RW","TS1 Time point 15","HH","MM","SS","Ext. Device"], + ["38","1","RW","TS1 Time point 15 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["39","1","RW","TS1 Time point 16","HH","MM","SS","Ext. Device"], + ["40","1","RW","TS1 Time point 16 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["41","1","RW","TS2 Time point 1","HH","MM","SS","Ext. Device"], + ["42","1","RW","TS2 Time point 1 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["43","1","RW","TS2 Time point 2","HH","MM","SS","Ext. Device"], + ["44","1","RW","TS2 Time point 2 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["45","1","RW","TS2 Time point 3","HH","MM","SS","Ext. Device"], + ["46","1","RW","TS2 Time point 3 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["47","1","RW","TS2 Time point 4","HH","MM","SS","Ext. Device"], + ["48","1","RW","TS2 Time point 4 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["49","1","RW","TS2 Time point 5","HH","MM","SS","Ext. Device"], + ["50","1","RW","TS2 Time point 5 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["51","1","RW","TS2 Time point 6","HH","MM","SS","Ext. Device"], + ["52","1","RW","TS2 Time point 6 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["53","1","RW","TS2 Time point 7","HH","MM","SS","Ext. Device"], + ["54","1","RW","TS2 Time point 7 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["55","1","RW","TS2 Time point 8","HH","MM","SS","Ext. Device"], + ["56","1","RW","TS2 Time point 8 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["57","1","RW","TS2 Time point 9","HH","MM","SS","Ext. Device"], + ["58","1","RW","TS2 Time point 9 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["59","1","RW","TS2 Time point 10","HH","MM","SS","Ext. Device"], + ["60","1","RW","TS2 Time point 10 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["61","1","RW","TS2 Time point 11","HH","MM","SS","Ext. Device"], + ["62","1","RW","TS2 Time point 11 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["63","1","RW","TS2 Time point 12","HH","MM","SS","Ext. Device"], + ["64","1","RW","TS2 Time point 12 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["65","1","RW","TS2 Time point 13","HH","MM","SS","Ext. Device"], + ["66","1","RW","TS2 Time point 13 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["67","1","RW","TS2 Time point 14","HH","MM","SS","Ext. Device"], + ["68","1","RW","TS2 Time point 14 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["69","1","RW","TS2 Time point 15","HH","MM","SS","Ext. Device"], + ["70","1","RW","TS2 Time point 15 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["71","1","RW","TS2 Time point 16","HH","MM","SS","Ext. Device"], + ["72","1","RW","TS2 Time point 16 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["73","1","RW","Power meter status","TBD","","",""], + ["74","1","R","Input Voltage","","","",""], + ["75","1","R","Input Current","","","",""], + ["76","1","R","Input Power","","","",""], + ["77","1","R","Cos phi","","","",""], + ["78","1","R","Frequency","","","",""], + ["79","1","RW","Energy","","","",""], + ["80","1","RW","Lifetime","","","",""], + ["81","1","RW","Power on cycles (input)","","","",""], + ["82","1","RW","Power on cycles (relay)","","","",""], + ["83","1","R","Time since last power on","","","",""], + ["84","1","R","Accelerometer data","","","",""], + ["85","1","RW","GPS latitude","pos/neg","deg","min ","sec"], + ["86","1","RW","GPS longitude","pos/neg","deg","min ","sec"], + ["87","1","RW","Actual time","HH","MM","SS","RES."], + ["88","1","RW","Actual date","Day of week","Day","Month","Year"], + ["89","1","R","Production data 1","","","",""], + ["90","1","R","Production data 2","","","",""], + ["91","1","RW","Network ID","NID3","NID2","NID1","NID0"], + ["95","1","RW","Actual Lux level from cabinet","RES.","RES.","HB","LB"], + ["96","1","RW","Threshold lux level","Dusk HB","Dusk LB","Dawn HB","Dawn LB"], + ["97","1","RW","Adjust period","Dusk HB","Dusk LB","Dawn HB","Dawn LB"], + ["98","1","RW","Offset","RES.","RES.","Dusk","Dawn"], + ["99","1","RW","CCT min/max range","max-H","max-L","min-H","min-L"], + ["100","1","RW","DALI interface","Cmd ID","Add","Cmd","Resp"], + ["101","1","RW","Module FW ver","v1","v2","v3","v4"], + ["102","1","RW","Module MAC-H","unused","unused","M1","M2"], + ["103","1","RW","Module MAC-L","M3","M4","M5","M6"], + ["122","1","R","FW update status/control register","Byte3","Byte2","Byte1","Byte0"], + ["123","1","R","FW update - data index","Byte3","Byte2","Byte1","Byte0"], + ["124","1","R","FW update - data","Byte3","Byte2","Byte1","Byte0"], + ["0","0","R","Status","","","",""], + ["1","0","RW","Control register","RES.","RES.","RES.","init mode enable"], + ["2","0","R","Device types","","","",""], + ["3","0","R","Serial number (MAC)","","","",""], + ["4","0","R","Production data 1","","","",""], + ["5","0","R","Production data 2","","","",""], + ["6","0","RW","Network ID","NID3","NID2","NID1","NID0"], + ["7","0","RW","RS232 settings","param.","param.","Baudrate H","Baudrate L"], + ["8","0","R","Accelerometer data","","","",""], + ["9","0","RW","Module FW ver","v1","v2","v3","v4"], + ["10","0","RW","Module MAC-H","unused","unused","M1","M2"], + ["11","0","RW","Module MAC-L","M3","M4","M5","M6"], + ["32","0","RW","FW update status/control register","Byte3","Byte2","Byte1","Byte0"], + ["33","0","RW","FW update - data index","Byte3","Byte2","Byte1","Byte0"], + ["34","0","RW","FW update - data","Byte3","Byte2","Byte1","Byte0"], + ["125","0","RW","Debug Register","Byte3","Byte2","Byte1","Byte0"], + ["126","0","RW","Network Control Register","Byte3","Byte2","Byte1","Byte0"], + ["127","0","R","Network Status Register","Byte3","Byte2","Byte1","Byte0"], + ["128","0","RW","Node XX Serial Number Register","SER3","SER2","SER1","SER0"], + ["256","0","R","Node XX Network Status Register","","","",""] +]; + +let register = {}; + +module.exports = { + registers, + register +} \ No newline at end of file diff --git a/RVO21/flow/helper/serialport_helper.js b/RVO21/flow/helper/serialport_helper.js new file mode 100755 index 0000000..7f5920d --- /dev/null +++ b/RVO21/flow/helper/serialport_helper.js @@ -0,0 +1,99 @@ +const { exec } = require('child_process'); + +function openPort(port) { + return new Promise((resolve, reject) => { + + var callbackError = function(err) { + port.removeListener('error', callbackError); + port.removeListener('open', callbackError); + + reject(err.message); + }; + + var callbackOpen = function(data) { + port.removeListener('error', callbackError); + port.removeListener('open', callbackOpen); + + resolve("port open: ok"); + }; + + port.on('error', callbackError); + port.on('open', callbackOpen); + + port.open(); + + }) +} + +function runSyncExec(command) { + return new Promise((resolve, reject) => { + + exec(command, (error, stdout, stderr) => { + if (error == null) resolve(stdout); + reject(error); + }); + + }) +} + +async function writeData(port, data, readbytes, timeout) { + return new Promise((resolve, reject) => { + + // 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) { + + port.write(Buffer.from(data), function(err) { + if (err) { + reject(err.message); + } + }); + + 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 +} diff --git a/RVO21/flow/helper/suncalc.js b/RVO21/flow/helper/suncalc.js new file mode 100755 index 0000000..c9ca56d --- /dev/null +++ b/RVO21/flow/helper/suncalc.js @@ -0,0 +1,317 @@ +/* + (c) 2011-2015, Vladimir Agafonkin + SunCalc is a JavaScript library for calculating sun/moon position and light phases. + https://github.com/mourner/suncalc +*/ + +(function () { 'use strict'; + +// shortcuts for easier to read formulas + +var PI = Math.PI, + sin = Math.sin, + cos = Math.cos, + tan = Math.tan, + asin = Math.asin, + atan = Math.atan2, + acos = Math.acos, + rad = PI / 180; + +// sun calculations are based on http://aa.quae.nl/en/reken/zonpositie.html formulas + + +// date/time constants and conversions + +var dayMs = 1000 * 60 * 60 * 24, + J1970 = 2440588, + J2000 = 2451545; + +function toJulian(date) { return date.valueOf() / dayMs - 0.5 + J1970; } +function fromJulian(j) { return new Date((j + 0.5 - J1970) * dayMs); } +function toDays(date) { return toJulian(date) - J2000; } + + +// general calculations for position + +var e = rad * 23.4397; // obliquity of the Earth + +function rightAscension(l, b) { return atan(sin(l) * cos(e) - tan(b) * sin(e), cos(l)); } +function declination(l, b) { return asin(sin(b) * cos(e) + cos(b) * sin(e) * sin(l)); } + +function azimuth(H, phi, dec) { return atan(sin(H), cos(H) * sin(phi) - tan(dec) * cos(phi)); } +function altitude(H, phi, dec) { return asin(sin(phi) * sin(dec) + cos(phi) * cos(dec) * cos(H)); } + +function siderealTime(d, lw) { return rad * (280.16 + 360.9856235 * d) - lw; } + +function astroRefraction(h) { + if (h < 0) // the following formula works for positive altitudes only. + h = 0; // if h = -0.08901179 a div/0 would occur. + + // formula 16.4 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + // 1.02 / tan(h + 10.26 / (h + 5.10)) h in degrees, result in arc minutes -> converted to rad: + return 0.0002967 / Math.tan(h + 0.00312536 / (h + 0.08901179)); +} + +// general sun calculations + +function solarMeanAnomaly(d) { return rad * (357.5291 + 0.98560028 * d); } + +function eclipticLongitude(M) { + + var C = rad * (1.9148 * sin(M) + 0.02 * sin(2 * M) + 0.0003 * sin(3 * M)), // equation of center + P = rad * 102.9372; // perihelion of the Earth + + return M + C + P + PI; +} + +function sunCoords(d) { + + var M = solarMeanAnomaly(d), + L = eclipticLongitude(M); + + return { + dec: declination(L, 0), + ra: rightAscension(L, 0) + }; +} + + +var SunCalc = {}; + + +// calculates sun position for a given date and latitude/longitude + +SunCalc.getPosition = function (date, lat, lng) { + + var lw = rad * -lng, + phi = rad * lat, + d = toDays(date), + + c = sunCoords(d), + H = siderealTime(d, lw) - c.ra; + + return { + azimuth: azimuth(H, phi, c.dec), + altitude: altitude(H, phi, c.dec) + }; +}; + + +// sun times configuration (angle, morning name, evening name) + +var times = SunCalc.times = [ + [-0.833, 'sunrise', 'sunset' ], + [ -0.3, 'sunriseEnd', 'sunsetStart' ], + [ -6, 'dawn', 'dusk' ], + [ -12, 'nauticalDawn', 'nauticalDusk'], + [ -18, 'nightEnd', 'night' ], + [ 6, 'goldenHourEnd', 'goldenHour' ] +]; + +// adds a custom time to the times config + +SunCalc.addTime = function (angle, riseName, setName) { + times.push([angle, riseName, setName]); +}; + + +// calculations for sun times + +var J0 = 0.0009; + +function julianCycle(d, lw) { return Math.round(d - J0 - lw / (2 * PI)); } + +function approxTransit(Ht, lw, n) { return J0 + (Ht + lw) / (2 * PI) + n; } +function solarTransitJ(ds, M, L) { return J2000 + ds + 0.0053 * sin(M) - 0.0069 * sin(2 * L); } + +function hourAngle(h, phi, d) { return acos((sin(h) - sin(phi) * sin(d)) / (cos(phi) * cos(d))); } +function observerAngle(height) { return -2.076 * Math.sqrt(height) / 60; } + +// returns set time for the given sun altitude +function getSetJ(h, lw, phi, dec, n, M, L) { + + var w = hourAngle(h, phi, dec), + a = approxTransit(w, lw, n); + return solarTransitJ(a, M, L); +} + + +// calculates sun times for a given date, latitude/longitude, and, optionally, +// the observer height (in meters) relative to the horizon + +SunCalc.getTimes = function (date, lat, lng, height) { + + height = height || 0; + + var lw = rad * -lng, + phi = rad * lat, + + dh = observerAngle(height), + + d = toDays(date), + n = julianCycle(d, lw), + ds = approxTransit(0, lw, n), + + M = solarMeanAnomaly(ds), + L = eclipticLongitude(M), + dec = declination(L, 0), + + Jnoon = solarTransitJ(ds, M, L), + + i, len, time, h0, Jset, Jrise; + + + var result = { + solarNoon: fromJulian(Jnoon), + nadir: fromJulian(Jnoon - 0.5) + }; + + for (i = 0, len = times.length; i < len; i += 1) { + time = times[i]; + h0 = (time[0] + dh) * rad; + + Jset = getSetJ(h0, lw, phi, dec, n, M, L); + Jrise = Jnoon - (Jset - Jnoon); + + result[time[1]] = fromJulian(Jrise); + result[time[2]] = fromJulian(Jset); + } + + return result; +}; + + +// moon calculations, based on http://aa.quae.nl/en/reken/hemelpositie.html formulas + +function moonCoords(d) { // geocentric ecliptic coordinates of the moon + + var L = rad * (218.316 + 13.176396 * d), // ecliptic longitude + M = rad * (134.963 + 13.064993 * d), // mean anomaly + F = rad * (93.272 + 13.229350 * d), // mean distance + + l = L + rad * 6.289 * sin(M), // longitude + b = rad * 5.128 * sin(F), // latitude + dt = 385001 - 20905 * cos(M); // distance to the moon in km + + return { + ra: rightAscension(l, b), + dec: declination(l, b), + dist: dt + }; +} + +SunCalc.getMoonPosition = function (date, lat, lng) { + + var lw = rad * -lng, + phi = rad * lat, + d = toDays(date), + + c = moonCoords(d), + H = siderealTime(d, lw) - c.ra, + h = altitude(H, phi, c.dec), + // formula 14.1 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + pa = atan(sin(H), tan(phi) * cos(c.dec) - sin(c.dec) * cos(H)); + + h = h + astroRefraction(h); // altitude correction for refraction + + return { + azimuth: azimuth(H, phi, c.dec), + altitude: h, + distance: c.dist, + parallacticAngle: pa + }; +}; + + +// calculations for illumination parameters of the moon, +// based on http://idlastro.gsfc.nasa.gov/ftp/pro/astro/mphase.pro formulas and +// Chapter 48 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + +SunCalc.getMoonIllumination = function (date) { + + var d = toDays(date || new Date()), + s = sunCoords(d), + m = moonCoords(d), + + sdist = 149598000, // distance from Earth to Sun in km + + phi = acos(sin(s.dec) * sin(m.dec) + cos(s.dec) * cos(m.dec) * cos(s.ra - m.ra)), + inc = atan(sdist * sin(phi), m.dist - sdist * cos(phi)), + angle = atan(cos(s.dec) * sin(s.ra - m.ra), sin(s.dec) * cos(m.dec) - + cos(s.dec) * sin(m.dec) * cos(s.ra - m.ra)); + + return { + fraction: (1 + cos(inc)) / 2, + phase: 0.5 + 0.5 * inc * (angle < 0 ? -1 : 1) / Math.PI, + angle: angle + }; +}; + + +function hoursLater(date, h) { + return new Date(date.valueOf() + h * dayMs / 24); +} + +// calculations for moon rise/set times are based on http://www.stargazing.net/kepler/moonrise.html article + +SunCalc.getMoonTimes = function (date, lat, lng, inUTC) { + var t = new Date(date); + if (inUTC) t.setUTCHours(0, 0, 0, 0); + else t.setHours(0, 0, 0, 0); + + var hc = 0.133 * rad, + h0 = SunCalc.getMoonPosition(t, lat, lng).altitude - hc, + h1, h2, rise, set, a, b, xe, ye, d, roots, x1, x2, dx; + + // go in 2-hour chunks, each time seeing if a 3-point quadratic curve crosses zero (which means rise or set) + for (var i = 1; i <= 24; i += 2) { + h1 = SunCalc.getMoonPosition(hoursLater(t, i), lat, lng).altitude - hc; + h2 = SunCalc.getMoonPosition(hoursLater(t, i + 1), lat, lng).altitude - hc; + + a = (h0 + h2) / 2 - h1; + b = (h2 - h0) / 2; + xe = -b / (2 * a); + ye = (a * xe + b) * xe + h1; + d = b * b - 4 * a * h1; + roots = 0; + + if (d >= 0) { + dx = Math.sqrt(d) / (Math.abs(a) * 2); + x1 = xe - dx; + x2 = xe + dx; + if (Math.abs(x1) <= 1) roots++; + if (Math.abs(x2) <= 1) roots++; + if (x1 < -1) x1 = x2; + } + + if (roots === 1) { + if (h0 < 0) rise = i + x1; + else set = i + x1; + + } else if (roots === 2) { + rise = i + (ye < 0 ? x2 : x1); + set = i + (ye < 0 ? x1 : x2); + } + + if (rise && set) break; + + h0 = h2; + } + + var result = {}; + + if (rise) result.rise = hoursLater(t, rise); + if (set) result.set = hoursLater(t, set); + + if (!rise && !set) result[ye > 0 ? 'alwaysUp' : 'alwaysDown'] = true; + + return result; +}; + + +// export as Node module / AMD module / browser variable +if (typeof exports === 'object' && typeof module !== 'undefined') module.exports = SunCalc; +else if (typeof define === 'function' && define.amd) define(SunCalc); +else window.SunCalc = SunCalc; + +}()); diff --git a/RVO21/flow/helper/utils.js b/RVO21/flow/helper/utils.js new file mode 100755 index 0000000..dbffe45 --- /dev/null +++ b/RVO21/flow/helper/utils.js @@ -0,0 +1,161 @@ +const fs = require('fs').promises; + +function bytesToInt(bytes, numberOfBytes) { + let buffer = []; + if (Array.isArray(bytes)) { + buffer = bytes.slice(0); + if (numberOfBytes != undefined) { + buffer = bytes.slice(bytes.length - numberOfBytes); + } + } + else buffer.push(bytes); + + let result = 0; + for (let i = 0; i < buffer.length; i++) { + result = (result << 8) | buffer[i]; + } + + return result >>> 0; //ensure it's an unsigned 32-bit number +} + +function resizeArray(arr, newSize, defaultValue) { + while (newSize > arr.length) + arr.push(defaultValue); + arr.length = newSize; +} + +longToByteArray = function(/*long*/long) { + // we want to represent the input as a 8-bytes array + var byteArray = [0, 0, 0, 0, 0, 0, 0, 0]; + + for (var index = 0; index < byteArray.length; index++) { + var byte = long & 0xff; + byteArray[index] = byte; + long = (long - byte) / 256; + } + + return byteArray; +}; + +function addDays(date, days) { + var result = new Date(date); + result.setDate(result.getDate() + days); + return result; +} + +/* +sleep(2000).then(() => { + // Do something after the sleep! + + +}); +*/ + +function sleep(time) { + return new Promise((resolve) => setTimeout(resolve, time)); +} + +function isEmptyObject(obj) { + for (var name in obj) { + return false; + } + return true; +} + +function emptyJsObject(jsObject) { + Object.keys(jsObject).forEach(key => delete jsObject[key]); +} + +function convertUTCDateToLocalDate(date) { + var newDate = new Date(date); + newDate.setMinutes(date.getMinutes() + date.getTimezoneOffset()); + return newDate; +} + +function addZeroBefore(n) { + return (n < 10 ? '0' : '') + n; +} + + +/** + * Asynchronously writes data to a file. + * + * @param {string} filePath The path to the file. + * @param {string} data The data to write to the file. + * @param {boolean} [append=false] If true, appends the data to the file. If false, it overwrites the file. + */ +async function writeToFile(filePath, data, append = false) { + if (typeof data !== 'string') data = JSON.stringify(data, null, 2); + try { + if (append) { + // Append the data to the end of the file. This is the simplest way to append. + await fs.appendFile(filePath, data, 'utf8'); + console.log(`Successfully appended data to ${filePath} using fs.appendFile.`); + } else { + // Overwrite the file with the new data. + await fs.writeFile(filePath, data, 'utf8'); + console.log(`Successfully wrote (overwrote) data to ${filePath} using fs.writeFile.`); + } + } catch (error) { + console.error(`Error writing to file ${filePath}:`, error); + } +} + + + /** + * Checks if an item is present in an array and adds it if it's not. + * * @param {Array} arr The array to check. + * @param {*} item The item to add. + * @returns {Array} The modified array. + */ +const addToArrayIfUnique = (arr, item) => { + if (!arr.includes(item)) { + arr.push(item); + } + return arr; +}; + + +var convertBase = function() { + + function convertBase(baseFrom, baseTo) { + return function(num) { + return parseInt(num, baseFrom).toString(baseTo); + + }; + } + + // binary to decimal + convertBase.bin2dec = convertBase(2, 10); + + // binary to hexadecimal + convertBase.bin2hex = convertBase(2, 16); + + // decimal to binary + convertBase.dec2bin = convertBase(10, 2); + + // decimal to hexadecimal + convertBase.dec2hex = convertBase(10, 16); + + // hexadecimal to binary + convertBase.hex2bin = convertBase(16, 2); + + // hexadecimal to decimal + convertBase.hex2dec = convertBase(16, 10); + + return convertBase; +}(); + +module.exports = { + bytesToInt, + longToByteArray, + addDays, + addZeroBefore, + resizeArray, + isEmptyObject, + emptyJsObject, + sleep, + convertUTCDateToLocalDate, + writeToFile, + addToArrayIfUnique +} diff --git a/RVO21/flow/httprequest.js b/RVO21/flow/httprequest.js new file mode 100755 index 0000000..469c8cb --- /dev/null +++ b/RVO21/flow/httprequest.js @@ -0,0 +1,137 @@ +exports.id = 'httprequest'; +exports.title = 'HTTP Request'; +exports.group = 'HTTP'; +exports.color = '#5D9CEC'; +exports.input = true; +exports.version = '2.0.1'; +exports.output = 1; +exports.author = 'Peter Širka'; +exports.icon = 'cloud-upload'; + +exports.html = `
+
@(URL address)
+
+
+
@(HTTP method)
+
+
+
@(Serialization)
+
+
+
@(Download the content in chunks)
+
@(Keep persistent cookies)
+
@(Disable DNS cache)
+
@(Keep alive connection)
+
+
+
+
@(Custom headers)
+
@(Cookies)
+
+
+
+ +
+
+
+
@(User)
+
+
+
@(Password)
+
+
+
+
+
`; + +exports.readme = `# Request + +This component creates a request with received data. + +__Response:__ +\`\`\`javascript +{ + data: String, + headers: Object, + status: Number, + host: String +} +\`\`\` + +__Dynamic arguments__: +Are performed via FlowData repository and can be used for URL address or for custom headers/cookies/auth. Use \`repository\` component for creating of dynamic arguments. Dynamic values are replaced in the form \`{key}\`: + +- url address e.g. \`https://.../{key}/\` +- headers values e.g. \`{token}\` +- cookies values e.g. \`{token}\``; + +exports.install = function(instance) { + + var can = false; + var flags = null; + var cookies2 = null; + + instance.on('data', function(response) { + can && instance.custom.send(response); + }); + + instance.custom.send = function(response) { + var options = instance.options; + + var headers = null; + var cookies = null; + + options.headers && Object.keys(options.headers).forEach(function(key) { + !headers && (headers = {}); + headers[key] = response.arg(options.headers[key]); + }); + + if (options.username && options.userpassword) { + !headers && (headers = {}); + headers['Authorization'] = 'Basic ' + U.createBuffer(response.arg(options.username + ':' + options.userpassword)).toString('base64'); + } + + options.cookies && Object.keys(options.cookies).forEach(function(key) { + !cookies && (cookies = {}); + cookies[key] = response.arg(options.cookies[key]); + }); + + if (options.chunks) { + U.download(response.arg(options.url), flags, options.stringify === 'none' ? null : response.data, function(err, response) { + response.on('data', (chunks) => instance.send2(chunks)); + }, cookies || cookies2, headers); + } else { + U.request(response.arg(options.url), flags, options.stringify === 'none' ? null : response.data, 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) + instance.error(err, response); + }, cookies || cookies2, headers); + } + }; + + instance.reconfigure = function() { + var options = instance.options; + can = options.url && options.url && options.method && options.stringify ? true : false; + instance.status(can ? '' : 'Not configured', can ? undefined : 'red'); + + if (!can) + return; + + flags = []; + flags.push(options.method.toLowerCase()); + options.stringify === 'json' && flags.push('json'); + options.stringify === 'raw' && flags.push('raw'); + options.keepalive && flags.push('keepalive'); + !options.nodns && flags.push('dnscache'); + if (options.persistentcookies) { + flags.push('cookies'); + cookies2 = {}; + } else + cookies2 = null; + }; + + instance.on('options', instance.reconfigure); + instance.reconfigure(); +}; \ No newline at end of file diff --git a/RVO21/flow/httpresponse.js b/RVO21/flow/httpresponse.js new file mode 100755 index 0000000..160a3bb --- /dev/null +++ b/RVO21/flow/httpresponse.js @@ -0,0 +1,76 @@ +exports.id = 'httpresponse'; +exports.title = 'HTTP Response'; +exports.group = 'HTTP'; +exports.color = '#5D9CEC'; +exports.icon = 'arrow-right'; +exports.input = true; +exports.output = ['#666D76']; +exports.version = '2.0.0'; +exports.author = 'Martin Smola'; +exports.readme = `# HTTP response + +HTTP response will respond with data recieved using data-type set in Settings form or plain text if not set. Output is the message duration \`Number\` in seconds.`; + +exports.html = `
+
@(Response data-type)
+
JSON is by default.
+
`; + +exports.install = function(instance) { + + var dursum = 0; + var durcount = 0; + + instance.on('data', function(flowdata) { + + var ctrl = flowdata.repository.controller; + var data = flowdata.data; + + if (!ctrl) { + instance.throw('No controller to use for response!'); + return; + } + + durcount++; + dursum += ((new Date() - flowdata.begin) / 1000).floor(2); + setTimeout2(instance.id, instance.custom.duration, 500, 10); + + ctrl.$flowdata = flowdata; + + var datatype = instance.options.datatype || 'json'; + if (datatype === 'emptyresponse') + return ctrl.plain(''); + + if (datatype !== 'json' && typeof(data) !== 'string') { + instance.throw('Incorect type of data, expected string, got ' + typeof(data)); + ctrl.plain(data == null ? '' : data.toString()); + return; + } + + switch(datatype) { + case 'html': + ctrl.content(data, 'text/html'); + break; + case 'plain': + ctrl.plain(data); + break; + case 'xml': + ctrl.content(data, 'text/xml'); + break; + default: + ctrl.json(data); + break; + } + }); + + instance.on('service', function() { + dursum = 0; + durcount = 0; + }); + + instance.custom.duration = function() { + var avg = (dursum / durcount).floor(2); + instance.status(avg + ' sec.'); + instance.send2(0, avg); + }; +}; diff --git a/RVO21/flow/httproute.js b/RVO21/flow/httproute.js new file mode 100755 index 0000000..583a19d --- /dev/null +++ b/RVO21/flow/httproute.js @@ -0,0 +1,326 @@ +exports.id = 'httproute'; +exports.title = 'HTTP Route'; +exports.group = 'HTTP'; +exports.color = '#5D9CEC'; +exports.icon = 'globe'; +exports.input = false; +exports.output = ['#6CAC5A', '#37BC9B']; +exports.version = '1.2.3'; +exports.author = 'Martin Smola'; +exports.cloning = false; +exports.options = { method: 'GET', url: '', size: 5, cacheexpire: '5 minutes', cachepolicy: 0, timeout: 5 }; +exports.dateupdated = '2021-01-21 18:30d'; +exports.readme = `# HTTP route + +__Outputs__: +- first output: raw data (cache is empty or is disabled) +- second output: cached data + +If one of the outputs is disabled then automatic responce with code "503 service unavailable" is sent. + +When a request comes in bellow object is available at \`flowdata.data\`: + +\`\`\`javascript +{ + params: { id: '1' }, // params for dynamic routes, e.g. /test/{id} + query: { msg: 'Hello' }, // parsed query string, e.g. /test/1?msg=Hello + body: { test: 'OK' }, // object if json requests otherwise string + headers: {}, // headers data + session: {}, // session data + user: {}, // user data + files: [], // uploaded files + url: '/users/', // a relative URL address + referrer: '/', // referrer + mobile: false, // determines mobile device + robot: false, // determines search robots/crawlsers + language: 'en' // determines language +} +\`\`\` + +See [documentation for flags](https://docs.totaljs.com/latest/en.html#api~HttpRouteOptionsFlags~unauthorize). These method flags are set automatically e.g. \`get, post, put, patch or delete\` + +--- + +\`id:ROUTE_ID\` flag cannot be used since it's already used by this component internally`; + +exports.html = `
+
+ +
+ +
+
+
@(HTTP method)
+
+
+
@(URL address)
+
+
+
+
+
@(Additional flags)
+
@(Separate flags by comma e.g. json, authorize)
+
+
+
@(Max. request size)
+
@(In kB kilobytes)
+
+
+
@(Timeout)
+
@(In seconds.)
+
+
+
+
+
+
@(Automatically respond with 200 OK?)
+
@(If not checked you need to use HTTP response component to respond to the request.)
+
+
@(Custom headers)
+
@(Cookies)
+
+
+
+
+
+
@(Cache policy)
+
@(User instance must contain id property.)
+
+
+
@(Expiration)
+
@(E.g. 5 minutes)
+
+
+
+`; + +exports.install = function(instance) { + + var route; + + var uninstall = function(id) { + if (F.is4) { + route && route.remove(); + route = null; + } else + UNINSTALL('route', id); + }; + + instance.custom.emptyresponse = function(self) { + self.plain(); + }; + + instance.reconfigure = function() { + + var options = instance.options; + + if (!options.url) { + instance.status('Not configured', 'red'); + return; + } + + if (typeof(options.flags) === 'string') + options.flags = options.flags.split(',').trim(); + + uninstall('id:' + instance.id); + + var flags = options.flags || []; + + flags.push('id:' + instance.id); + + if (!F.is4) + flags.push(options.method.toLowerCase()); + + options.timeout && flags.push(options.timeout * 1000); + + // Make unique values + flags = flags.filter(function(v, i, a) { + if(F.is4 && v.toString().toLowerCase() === options.method.toLowerCase()) + return false; // remove method + return a.indexOf(v) === i; + }); + + options.flags = flags; + var handler = function() { + + if (instance.paused || (instance.isDisabled && (instance.isDisabled('output', 0) || instance.isDisabled('output', 1)))) { + instance.status('503 Service Unavailable'); + this.status = 503; + this.json(); + return; + } + + var key; + var self = this; + + if (instance.options.emptyresponse) { + instance.status('200 OK'); + setTimeout(instance.custom.emptyresponse, 100, self); + + if (instance.hasConnection(0)) { + var data = instance.make({ + query: self.query, + body: self.body, + session: self.session, + user: self.user, + files: self.files, + headers: self.req.headers, + url: self.url, + params: self.params + }); + instance.send2(0, data); + } + + return; + } + + switch (instance.options.cachepolicy) { + case 1: // URL + key = 'rro' + instance.id + self.url.hash(); + break; + case 2: // URL + query + case 3: // URL + query + user + key = self.url; + var keys = Object.keys(self.query); + keys.sort(); + for (var i = 0, length = keys.length; i < length; i++) + key += keys[i] + self.query[keys[i]] + '&'; + if (instance.options.cachepolicy === 3 && self.user) + key += 'iduser' + self.user.id; + key = 'rro' + instance.id + key.hash(); + break; + } + + if (key && F.cache.get2(key)) { + var data = instance.make(F.cache.get2(key)); + data.repository.controller = self; + instance.send2(1, data); + } else { + + var data = instance.make({ + query: self.query, + body: self.body, + session: self.session, + user: self.user, + files: self.files, + headers: self.req.headers, + url: self.url, + params: self.params, + mobile: self.mobile, + robot: self.robot, + referrer: self.referrer, + language: self.language + }); + + data.repository.controller = self; + instance.send2(0, data); + key && FINISHED(self.res, () => F.cache.set(key, self.$flowdata.data, instance.options.cacheexpire)); + } + }; + + if (F.is4) + route = ROUTE(options.method.toUpperCase() + ' ' + options.url, handler, flags, options.size || 5); + else + F.route(options.url, handler, flags, options.size || 5); + + instance.status('Listening', 'green'); + }; + + instance.reconfigure(); + instance.on('options', instance.reconfigure); + instance.on('close', function(){ + uninstall('id:' + instance.id); + }); +}; + +// check url exists +FLOW.trigger('httproutecheckurl', function(next, data) { + var url = data.url; + var method = data.method; + if (url[url.length - 1] !== '/') + url += '/'; + var exists = F.routes.web.findItem(r => r.urlraw === url && r.method === method); + next(exists != null); +}); + +exports.uninstall = function() { + FLOW.trigger('httproutecheckurl', null); +}; diff --git a/RVO21/flow/infosender.js b/RVO21/flow/infosender.js new file mode 100755 index 0000000..587724f --- /dev/null +++ b/RVO21/flow/infosender.js @@ -0,0 +1,81 @@ +exports.id = 'infosender'; +exports.title = 'Info sender'; +exports.version = '1.0.0'; +exports.group = 'Worksys'; +exports.color = '#2134B0'; +exports.input = 2; +exports.output = 1 +exports.icon = 'bolt'; + +const { networkInterfaces } = require('os'); + +exports.html = `
+
+
+
CSV Import
+
+
+
`; + +exports.readme = `# send all data to projects.worksys.io, required to monitor status of controller(unipi)`; + +exports.install = function(instance) { + + let id; + let allValues = {}; + let sendAllValuesInterval; + let configured = false; + + let now = new Date(); + console.log(exports.title, "INSTALLED", now.toLocaleString("sk-SK")); + + const nets = networkInterfaces(); + let ipAddresses = Object.create(null); // Or just '{}', an empty object + + for (const name of Object.keys(nets)) { + for (const net of nets[name]) { + // Skip over non-IPv4 and internal (i.e. 127.0.0.1) addresses + if (net.family === 'IPv4' && !net.internal) { + if (!ipAddresses[name]) { + ipAddresses[name] = []; + } + ipAddresses[name].push(net.address); + } + } + } + + function sendValues() { + if (!configured) return; + + if (Object.keys(allValues).length > 0) { + let dataToSend = { ...allValues }; + dataToSend.id = id; + dataToSend.ipAddresses = ipAddresses; + + instance.send(0, dataToSend); + + allValues = {}; + } + } + + instance.on("close", () => { + clearInterval(sendAllValuesInterval); + }) + + instance.on("0", _ => { + id = FLOW.GLOBALS.settings.project_id; + if (id) configured = true; + else console.log(exports.title, "InfoSender: Unable to send data, no id"); + }) + + instance.on("1", flowdata => { + allValues = { ...allValues, ...flowdata.data }; + //console.log("DATA RECEIVED", flowdata.data); + }) + + sendAllValuesInterval = setInterval(() => { + sendValues(); + }, 60000 * 3); + +} + diff --git a/RVO21/flow/modbus_reader.js b/RVO21/flow/modbus_reader.js new file mode 100755 index 0000000..d6d9dad --- /dev/null +++ b/RVO21/flow/modbus_reader.js @@ -0,0 +1,346 @@ +exports.id = 'modbus_reader'; +exports.title = 'Modbus reader'; +exports.version = '2.0.0'; +exports.group = 'Worksys'; +exports.color = '#2134B0'; +exports.input = 1; +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; +//number of phases inRVO +let phases; +//phases where voltage is 0 (set) +let noVoltage; +let energyToSwitchLamps; + +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.phases = this.buildPhases(); + + this.startSocket(); + } + + buildPhases = () => { + let a = []; + for (let i = 1; i <= phases; i++) { + a.push(`Phase_${i}_voltage`) + } + return a; + } + + startSocket = () => { + + let obj = this; + + if (this.socket) { + this.socket.removeAllListeners(); + this.socket = null; + } + + 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('Modbus_reader: Socket connection error', e); //'ECONNREFUSED' or 'ECONNRESET' ?? + }); + + this.socket.on('close', function() { + console.log('Modbus_reader: Socket connection closed - Waiting 10 seconds before connecting 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 we just start to loop devices from the beginning, or there is just 1 device in config, we wait whole timeoutInterval + if (this.indexInDeviceConfig == 0 || deviceConfig.length === 1) 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 (this.phases.includes(singleValue)) { + let l = singleValue.split("_"); + let phase = parseInt(l[1]); + + // console.log(values[singleValue], tbName); + + if (values[singleValue] == 0) { + noVoltage.add(phase); + sendNotification("modbus_reader: checkNullVoltage", tbName, "no_voltage_on_phase", { phase: phase }, "", SEND_TO.tb, instance, "voltage" + phase); + // console.log('no voltage') + } + else { + noVoltage.delete(phase); + // console.log('voltage detected') + sendNotification("modbus_reader: checkNullVoltage", tbName, "voltage_on_phase_restored", { phase: phase }, "", SEND_TO.tb, instance, "voltage" + phase); + } + } + }) + } + + /** + * function sends notification to slack and to tb, if EM total_power value changes more than numberOfNodes*15. This should show, that RVO lamps has been switched on or off + */ + lampSwitchNotification = (values) => { + + if (!values.hasOwnProperty("total_power")) return; + + const actualTotalPower = values.total_power; + + if (actualTotalPower > energyToSwitchLamps && 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 <= energyToSwitchLamps && 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; + } + + function main() { + + phases = FLOW.GLOBALS.settings.phases; + tbName = FLOW.GLOBALS.settings.rvoTbName; + noVoltage = FLOW.GLOBALS.settings.no_voltage; + energyToSwitchLamps = FLOW.GLOBALS.settings.energy_to_switch_lamps / 2.5; //half value is enought to show if lamps are turned on or off + if (deviceConfig.length) mainSocket = new SocketWithClients(); + else console.log("Modbus_reader: no modbus device in configuration"); + + // this notification is to show, that flow (unipi) has been restarted + sendNotification("modbus_reader", tbName, "flow_restart", {}, "", SEND_TO.slack, instance); + } + + instance.on("0", function(_) { + main(); + }) + +} + diff --git a/RVO21/flow/monitorconsumption.js b/RVO21/flow/monitorconsumption.js new file mode 100755 index 0000000..64cc58e --- /dev/null +++ b/RVO21/flow/monitorconsumption.js @@ -0,0 +1,156 @@ +exports.id = 'monitorconsumption'; +exports.title = 'Consumption'; +exports.version = '1.0.0'; +exports.author = 'Peter Širka'; +exports.group = 'Monitoring'; +exports.color = '#967ADC'; +exports.input = 0; +exports.output = 1; +exports.icon = 'bug'; +exports.options = { interval: 5000, enabled: true, monitorconsumption: true, monitorsize: true, monitorconnections: true, monitorfiles: true }; +exports.click = true; +exports.readme = `# Consumption monitoring + +This component measure CPU and memory consumption, open files and open connections of this application. It uses these Linux commands: \`ps\`, \`lsof\`, \`netstat\` and \`df\`. + +__Data Example__: + +\`\`\`javascript +{ + cpu: 0, // percentage + memory: 4096, // in bytes + size: 34303, // directory size in bytes + files: 34, // count of open files + connections: 343, // count of connections + uptime: '1-12:34:00' +} +\`\`\``; + +exports.html = `
+
+
+
@(Interval in milliseconds)
+
+
+
+
Monitor: Consumption + uptime
+
Monitor: Count of open files
+
Monitor: Count of open connections
+
Monitor: Directory size
+
`; + +exports.install = function(instance) { + + var current = { cpu: 0, memory: 0, files: 0, connections: 0, size: 0, uptime: '', counter: 0 }; + var tproc = null; + var Exec = require('child_process').exec; + var reg_empty = /\s{2,}/g; + var reg_appdisksize = /^[\d.,]+/; + + instance.custom.run = function() { + + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + + var arr = []; + + // Get CPU and Memory consumption + instance.options.monitorconsumption && arr.push(function(next) { + Exec('ps -p {0} -o %cpu,rss,etime'.format(process.pid), function(err, response) { + + if (err) { + instance.throw(err); + } else { + var line = response.split('\n')[1]; + line = line.trim().replace(reg_empty, ' ').split(' '); + var cpu = line[0].parseFloat(); + current.cpu = cpu.floor(1); + current.memory = line[1].parseInt2() * 1024; // kB to bytes + current.uptime = line[2]; + } + + next(); + }); + }); + + // Get count of open files + instance.options.monitorfiles && arr.push(function(next) { + Exec('lsof -a -p {0} | wc -l'.format(process.pid), function(err, response) { + if (err) + instance.throw(err); + else + current.files = response.trim().parseInt2(); + next(); + }); + }); + + // Get count of opened network connections + instance.options.monitorconnections && arr.push(function(next) { + Exec('netstat -an | grep :{0} | wc -l'.format(F.port), function(err, response) { + if (err) { + instance.throw(err); + } else { + current.connections = response.trim().parseInt2() - 1; + if (current.connections < 0) + current.connections = 0; + } + next(); + }); + }); + + // Get directory size + instance.options.monitorsize && current.counter % 5 !== 0 && arr.push(function(next) { + Exec('du -hsb ' + process.cwd(), function(err, response) { + if (err) { + instance.throw(err); + } else { + var match = response.trim().match(reg_appdisksize); + match && (current.size = match.toString().trim().parseInt2()); + } + next(); + }); + }); + + arr.async(function() { + + tproc && clearTimeout(tproc); + + if (instance.options.enabled) { + tproc = setTimeout(instance.custom.run, instance.options.interval); + instance.send2(current); + } + + instance.custom.status(); + current.counter++; + }); + }; + + instance.custom.status = function() { + if (instance.options.enabled) + instance.status('{0}% / {1}'.format(current.cpu, current.memory.filesize())); + else + instance.status('Disabled', 'red'); + }; + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + + if (instance.options.enabled) { + current.counter = 0; + instance.custom.run(); + } + + }); + + instance.on('close', function() { + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + }); + + setTimeout(instance.custom.run, 1000); +}; \ No newline at end of file diff --git a/RVO21/flow/monitordisk.js b/RVO21/flow/monitordisk.js new file mode 100755 index 0000000..f4fdaa0 --- /dev/null +++ b/RVO21/flow/monitordisk.js @@ -0,0 +1,96 @@ +exports.id = 'monitordisk'; +exports.title = 'Disk'; +exports.version = '1.0.0'; +exports.author = 'Peter Širka'; +exports.group = 'Monitoring'; +exports.color = '#F6BB42'; +exports.output = 1; +exports.icon = 'hdd-o'; +exports.click = true; +exports.options = { interval: 8000, path: '/', enabled: true }; +exports.readme = `# Disk monitoring + +This component monitors disk \`bytes\` consumption in Linux systems. It uses \`df\` command. + +__Data Example__: + +\`\`\`javascript +{ + total: 474549649408, + used: 39125245952, + free: 411294994432 +} +\`\`\``; + +exports.html = `
+
+
+
@(Interval in milliseconds)
+
+
+
@(Path)
+
+
+
`; + +exports.install = function(instance) { + + var current = { total: 0, used: 0, free: 0, path: '', type: '', percentUsed: 0 }; + var tproc = null; + + instance.custom.run = function() { + + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + + if (!instance.options.enabled) + return; + + require('child_process').exec('df -hTB1 ' + instance.options.path, function(err, response) { + + tproc = setTimeout(instance.custom.run, instance.options.interval); + + if (err) { + instance.error(err); + return; + } + + response.parseTerminal(function(line) { + if (line[0][0] !== '/') + return; + current.total = line[2].parseInt(); + current.free = line[4].parseInt(); + current.used = line[3].parseInt(); + current.path = instance.options.path || '/'; + current.type = line[1]; + current.percentUsed = line[5]; + instance.custom.status(); + instance.send2(current); + }); + }); + }; + + instance.custom.status = function() { + if (instance.options.enabled) + instance.status(current.free.filesize() + ' / ' + current.total.filesize()); + else + instance.status('Disabled', 'red'); + }; + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + instance.options.enabled && instance.custom.run(); + }); + + instance.on('close', function() { + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + }); + + setTimeout(instance.custom.run, 1000); +}; \ No newline at end of file diff --git a/RVO21/flow/monitormemory.js b/RVO21/flow/monitormemory.js new file mode 100755 index 0000000..2decbc4 --- /dev/null +++ b/RVO21/flow/monitormemory.js @@ -0,0 +1,87 @@ +exports.id = 'monitormemory'; +exports.title = 'Memory'; +exports.version = '1.0.0'; +exports.author = 'Peter Širka'; +exports.group = 'Monitoring'; +exports.color = '#F6BB42'; +exports.output = 1; +exports.click = true; +exports.icon = 'microchip'; +exports.options = { interval: 8000, enabled: true }; +exports.readme = `# Memory monitoring + +This component monitors memory \`bytes\` consumption in Linux systems. It uses \`free\` command. + +__Data Example__: + +\`\`\`javascript +{ + total: 33558769664, + used: 1998868480, + free: 2653708288 +} +\`\`\``; + +exports.html = `
+
+
+
@(Interval in milliseconds)
+
+
+
`; + +exports.install = function(instance) { + + var current = { total: 0, used: 0, free: 0 }; + var tproc = null; + + instance.custom.run = function() { + + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + + if (!instance.options.enabled) + return; + + require('child_process').exec('free -b -t', function(err, response) { + + tproc = setTimeout(instance.custom.run, instance.options.interval); + + if (err) { + instance.error(err); + return; + } + + var memory = response.split('\n')[1].match(/\d+/g); + current.total = memory[0].parseInt(); + current.used = memory[1].parseInt() - memory[3].parseInt(); + current.free = current.total - current.used; + instance.custom.status(); + instance.send2(current); + }); + }; + + instance.custom.status = function() { + if (instance.options.enabled) + instance.status(current.free.filesize() + ' / ' + current.total.filesize()); + else + instance.status('Disabled', 'red'); + }; + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + instance.options.enabled && instance.custom.run(); + }); + + instance.on('close', function() { + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + }); + + setTimeout(instance.custom.run, 1000); +}; \ No newline at end of file diff --git a/RVO21/flow/nodesdb_changecheck.js b/RVO21/flow/nodesdb_changecheck.js new file mode 100755 index 0000000..9adab62 --- /dev/null +++ b/RVO21/flow/nodesdb_changecheck.js @@ -0,0 +1,77 @@ +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 = 2; +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); + } + } + + //kedze do slacku posielame stringy, na cloud musime previest vsetky stringy spat na objekty: + // Funkcia na parsovanie všetkých reťazcov v poli + const parseArray = (arr) => { + return arr.map(jsonString => JSON.parse(jsonString)); + }; + + 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); + if (FLOW.GLOBALS.settings.send_changed_node_numbers) instance.send(1, { aktualneNody: parseArray(zmenene), originalne: parseArray(Array.from(set2)) }); + } + 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/RVO21/flow/show_dbdata.js b/RVO21/flow/show_dbdata.js new file mode 100755 index 0000000..1e23ff7 --- /dev/null +++ b/RVO21/flow/show_dbdata.js @@ -0,0 +1,243 @@ +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 = 8; +exports.output = 1; + +const { exec } = require('child_process'); + +exports.install = 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 }) + }) + instance.on("5", _ => { + exec("sudo tail -n 25 monitor.txt", (err, stdout, stderr) => { + if (err || stderr) instance.send(0, { err, stderr }); + else instance.send(0, stdout); + }) + }) + instance.on("6", _ => { + exec("sudo tail -n 25 err.txt", (err, stdout, stderr) => { + if (err || stderr) instance.send(0, { err, stderr }); + else instance.send(0, stdout); + }) + }) + instance.on("7", _ => { + instance.send(0, FLOW.deviceStatus); + }) +}; + + +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/RVO21/flow/slack_filter.js b/RVO21/flow/slack_filter.js new file mode 100755 index 0000000..6618523 --- /dev/null +++ b/RVO21/flow/slack_filter.js @@ -0,0 +1,188 @@ +exports.id = 'slack_filter'; +exports.title = 'Slack Filter'; +exports.group = 'Citysys'; +exports.color = '#30E193'; +exports.input = 2; +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 = `
+
+
+
@(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('0', 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']['en']; + 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"] = []; + } + + instance.options.name = FLOW.GLOBALS.settings.rvo_name; + if (instance.options.name) { + instance.status('Running'); + running = true; + } else { + instance.status('Please run options again', 'red'); + running = false; + } + } catch (e) { + instance.error('Citysys connector: ' + e.message); + } + }; + + instance.on('options', instance.reconfigure); + + instance.on("1", _ => { + instance.reconfigure(); + }) +}; diff --git a/RVO21/flow/thermometer.js b/RVO21/flow/thermometer.js new file mode 100755 index 0000000..fc7074d --- /dev/null +++ b/RVO21/flow/thermometer.js @@ -0,0 +1,99 @@ +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 = 5;//minutes +let NUMBER_OF_FAILURES_TO_SEND_ERROR = 13; + +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) => { + + 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); + setTimeout(main, 20000); + }) +}; diff --git a/RVO21/flow/trigger.js b/RVO21/flow/trigger.js new file mode 100755 index 0000000..27545a8 --- /dev/null +++ b/RVO21/flow/trigger.js @@ -0,0 +1,79 @@ +exports.id = 'trigger'; +exports.title = 'Trigger'; +exports.group = 'Inputs'; +exports.color = '#F6BB42'; +exports.click = true; +exports.output = 1; +exports.version = '1.1.0'; +exports.author = 'Martin Smola'; +exports.icon = 'play'; + +exports.html = `
+
@(Data type (String by default))
+
@(Data)
+
Trigger 5s after initialization.
+
@(Useful when there's a need to run certain flow when the app restarts, etc.)
+
`; + +exports.readme = `# Trigger + +- Clicking on the component starts the chain +- Settings allows to set a data-type and a value`; + +exports.install = function(instance) { + + var value; + + instance.on('click', () => instance.send2(value)); + + instance.reconfigure = function() { + var options = instance.options; + value = null; + switch (options.datatype) { + case 'integer': + value = options.data.parseInt2('error'); + value = value === 'error' ? NaN : value; + break; + case 'float': + value = options.data.parseFloat2('error'); + value = value === 'error' ? NaN : value; + break; + case 'date': + options.data = options.data.toString(); + var num = options.data.parseInt('error'); + num === 'error' && (num = options.data.parseDate('error')); + num === 'error' && (num = null); + value = num ? new Date(num).toUTCString() : num; + break; + case 'object': + try { + value = (new Function('return ' + options.data))(); + } catch (e) { + instance.error(e); + } + break; + case 'boolean': + value = options.data.parseBoolean(); + break; + case 'buffer': + try { + value = U.createBuffer(options.data); + } catch (e) { + instance.error(e); + } + break; + case 'string': + default: + value = '' + (options.data || ''); + break; + } + }; + + instance.on('options', instance.reconfigure); + instance.reconfigure(); + + if (instance.options.restart) + setTimeout(function(){ + instance.send2(value); + }, 5000); +}; diff --git a/RVO21/flow/variables.txt b/RVO21/flow/variables.txt new file mode 100755 index 0000000..e69de29 diff --git a/RVO21/flow/virtualwirein.js b/RVO21/flow/virtualwirein.js new file mode 100755 index 0000000..38a4e42 --- /dev/null +++ b/RVO21/flow/virtualwirein.js @@ -0,0 +1,43 @@ +exports.id = 'virtualwirein'; +exports.title = 'Virtual wire in'; +exports.version = '1.0.0'; +exports.author = 'Martin Smola'; +exports.color = '#303E4D'; +exports.icon = 'sign-in'; +exports.input = false; +exports.output = 1; +exports.options = {}; +exports.readme = `# Virtual wire in + +When the wires between the components are mess it's time to use Virtual wire.`; + +exports.html = `
+
@(Wire name)
+
+`; + +exports.install = function(instance) { + + instance.custom.reconfigure = function(options){ + if (instance.options.wirename) { + instance.status(instance.options.wirename); + } else + instance.status('Not configured', 'red'); + }; + + ON('virtualwire', function(wirename, flowdata){ + if (instance.options.wirename && instance.options.wirename === wirename) + instance.send(flowdata); + }); + + instance.on('options', instance.custom.reconfigure); + instance.custom.reconfigure(); +}; diff --git a/RVO21/flow/virtualwireout.js b/RVO21/flow/virtualwireout.js new file mode 100755 index 0000000..94a1e4f --- /dev/null +++ b/RVO21/flow/virtualwireout.js @@ -0,0 +1,41 @@ +exports.id = 'virtualwireout'; +exports.title = 'Virtual wire out'; +exports.version = '1.0.0'; +exports.author = 'Martin Smola'; +exports.color = '#303E4D'; +exports.icon = 'sign-out'; +exports.input = true; +exports.options = {}; +exports.readme = `# Virtual wire out + +When the wires between the components are mess it's time to use Virtual wire.`; + +exports.html = `
+
@(Wire name)
+
+`; + +exports.install = function(instance) { + + instance.custom.reconfigure = function(){ + if (instance.options.wirename) { + instance.status(instance.options.wirename); + } else + instance.status('Not configured', 'red'); + }; + + instance.on('data', function(flowdata) { + EMIT('virtualwire', instance.options.wirename, flowdata); + }); + + instance.on('options', instance.custom.reconfigure); + instance.custom.reconfigure(); +}; diff --git a/RVO21/flow/wsmqttpublish.js b/RVO21/flow/wsmqttpublish.js new file mode 100755 index 0000000..0eba804 --- /dev/null +++ b/RVO21/flow/wsmqttpublish.js @@ -0,0 +1,448 @@ +exports.id = 'wsmqttpublish'; +exports.title = 'WS MQTT publish'; +exports.group = 'MQTT'; +exports.color = '#888600'; +exports.version = '1.0.2'; +exports.icon = 'sign-out'; +exports.input = 2; +exports.output = 3; +exports.options = { host: 'tb-stage.worksys.io', port: 1883, clientid: "", username: "" }; + +exports.html = `
+
+
+
Hostname or IP address (if not empty - setting will override db setting)
+
+
+
Port
+
+
+
+
+
@(Client id)
+
+
+
@(Username)
+
+
+
`; + + +exports.readme = ` +# WS MQTT Publish + +Version 1.0.3. + +Added: +- database collections, +- 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 = { + debug: 0, + rpcCall: 1, + services: 2 +} + +//CONFIG +let createTelemetryBackup = true; +let saveTelemetryOnError = true;//backup_on_failure overrides this value +//------------------------ + +let rollers; +if (createTelemetryBackup) rollers = require('streamroller'); + +const noSqlFileSizeLimit = 4194304;//use 5MB - 4194304 +let insertNoSqlCounter = 0; +let insertBackupNoSqlCounter = 0; +let processingData = false; + +let backup_on_failure = false;//== saveTelemetryOnError - create backup client 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; + +process.on('uncaughtException', function(err) { + + errLogger.error('uncaughtException:', err.message) + errLogger.error(err.stack); + + //TODO + //send to service + + //process.exit(1); +}) + +const nosql = NOSQL('tbdata'); +const nosqlBackup = NOSQL('/backup/tbdata'); + + +exports.install = function(instance) { + + var client; + var opts; + var clientReady = false; + + // wsmqtt status for notification purposes on projects.worksys.io database + let wsmqttName = null; + let sendWsStatusVar = null; + let wsmqtt_status = 'disconnected'; + + 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'; + } + + function sendWsStatus() { + instance.send(SEND_TO.services, { [wsmqttName]: wsmqtt_status }); + } + + + function main() { + if (!FLOW.dbLoaded) return; + + loadSettings(); + clearInterval(sendWsStatus); + sendWsStatusVar = setInterval(sendWsStatus, 180000); + } + + //set opts according to db settings + function loadSettings() { + + if (instance.options.host !== "") { + //override settings from database + var o = instance.options; + opts = { + host: o.host, + port: o.port, + clientId: o.clientid, + username: o.username, + rejectUnauthorized: false, + resubscribe: false + }; + + wsmqttName = getWsmqttName(o.host); + + console.log("wsmqttpublich -> loadSettings from instance.options", instance.options); + } + else { + + const SETTINGS = FLOW.GLOBALS.settings; + backup_on_failure = SETTINGS.backup_on_failure; + saveTelemetryOnError = backup_on_failure; + + restore_from_backup = SETTINGS.restore_from_backup; + restore_backup_wait = SETTINGS.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; + + opts = { + host: mqtt_host, + port: mqtt_port, + keepalive: 10, + clientId: mqtt_clientid, + username: mqtt_username, + rejectUnauthorized: false, + resubscribe: false + }; + + wsmqttName = getWsmqttName(mqtt_host); + } + + connectToTbServer(); + } + + function connectToTbServer() { + 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"); + //monitor.info("MQTT client connected"); + + sendClientError = true; + clientReady = true; + wsmqtt_status = 'connected'; + }); + + client.on('reconnect', function() { + instance.status("Reconnecting", "yellow"); + clientReady = false; + }); + + client.on('message', function(topic, message) { + // message is type of buffer + message = message.toString(); + if (message[0] === '{') { + TRY(function() { + + message = JSON.parse(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 } }); + } + + }, () => instance.debug('MQTT: Error parsing data', message)); + } + + instance.send(SEND_TO.rpcCall, { "topic": topic, "content": message }); + }); + + client.on('close', function() { + clientReady = false; + wsmqtt_status = 'disconnected'; + + instance.status("Disconnected", "red"); + instance.send(SEND_TO.debug, { "message": "Client CLOSE signal received !" }); + }); + + client.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; + wsmqtt_status = 'disconnected'; + }); + + } + + + instance.on("0", _ => { + main(); + }) + + + instance.on('1', function(data) { + + if (clientReady) { + //do we have some data in backup file? if any, process data from database + if (saveTelemetryOnError) { + //read telemetry data and send back to server + if (!processingData) processDataFromDatabase(); + } + + let stringifiedJson = JSON.stringify(data.data); + client.publish("v1/gateway/telemetry", stringifiedJson, { qos: 1 }); + + //backup telemetry + if (createTelemetryBackup) { + data.data.id = UID(); + nosqlBackup.insert(data.data); + + insertBackupNoSqlCounter++; + if (insertBackupNoSqlCounter > 150) { + let options = { compress: true }; + let path = __dirname + "/../databases/backup/tbdata.nosql"; + var stream = new rollers.RollingFileStream(path, noSqlFileSizeLimit, 150, options); + stream.write(""); + stream.end(); + + insertBackupNoSqlCounter = 0; + } + } + + } + 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 (saveTelemetryOnError) { + //create new file from tbdata.nosql, if file size exceeds given limit, and clear tbdata.nosql + makeBackupFromDbFile(); + + //write to tb + data.data.id = UID(); + nosql.insert(data.data); + } + } + }); + + + instance.close = function(done) { + if (clientReady) { + client.end(); + clearInterval(sendWsStatusVar); + } + }; + + + function getDbBackupFileCounter(type) { + var files = fs.readdirSync(__dirname + "/../databases"); + + let counter = 0; + for (var i = 0; i < files.length; i++) { + + if (files[i] == "tbdata.nosql") continue; + + if (files[i].endsWith(".nosql")) { + + let pos = files[i].indexOf("."); + if (pos > -1) { + + let fileCounter = counter; + let firstDigit = files[i].slice(0, pos); + + fileCounter = parseInt(firstDigit); + if (isNaN(fileCounter)) fileCounter = 0; + //console.log("getDbBackupFileCounter digit:", files[i], firstDigit, fileCounter, isNaN(fileCounter), type); + + if (type == "max") { + if (fileCounter > counter) { + counter = fileCounter; + } + } + else if (type == "min") { + if (counter == 0) counter = fileCounter; + + if (fileCounter < counter) { + counter = fileCounter; + } + } + } + } + + } + + if (type == "max") counter++; + + return counter; + } + + const makeBackupFromDbFile = async () => { + + if (!saveTelemetryOnError) return; + + //to avoid large file: tbdata.nosql + + //init value is 0! + if (insertNoSqlCounter > 0) { + --insertNoSqlCounter; + return; + } + + insertNoSqlCounter = 100; + + let source = __dirname + "/../databases/tbdata.nosql"; + + var stats = fs.statSync(source); + var fileSizeInBytes = stats.size; + + if (fileSizeInBytes > noSqlFileSizeLimit) { + + let counter = 1; + counter = getDbBackupFileCounter("max"); + + let destination = __dirname + "/../databases/" + counter + "." + "tbdata.nosql"; + + //make backup file + fs.copyFileSync(source, destination); + //fs.renameSync(p, p + "." + counter); + + //clear tbdata.nosql + fs.writeFileSync(source, ""); + fs.truncateSync(source, 0); + + } + } + + const processDataFromDatabase = async () => { + + if (restore_from_backup <= 0) return; + + //calculate diff + const now = new Date(); + let currentTime = now.getTime(); + let diff = currentTime - lastRestoreTime; + + if ((diff / 1000) < restore_backup_wait) { + //console.log("*********restore_backup_wait", diff, restore_backup_wait); + return; + } + + processingData = true; + + //get filename to process + let counter = getDbBackupFileCounter("min"); + + //we have some backup files + let dataBase = 'tbdata'; + + var nosql; + if (counter == 0) dataBase = 'tbdata'; + else dataBase = counter + "." + 'tbdata'; + + nosql = NOSQL(dataBase); + + //select all data - use limit restore_from_backup + let records = await promisifyBuilder(nosql.find().take(restore_from_backup)); + + for (let i = 0; i < records.length; i++) { + if (clientReady) { + + let item = records[i]; + let id = item.id; + + if (id !== undefined) { + //console.log("------------processDataFromDatabase - remove", id, dataBase, i); + + try { + + let message = JSON.parse(JSON.stringify(item)); + delete message.id; + + client.publish("v1/gateway/telemetry", JSON.stringify(message), { qos: 1 }); + + //remove from database + await promisifyBuilder(nosql.remove().where("id", id)); + + } catch (error) { + //process error + console.log("processDataFromDatabase", error); + } + + } + + } + else { + processingData = false; + return; + } + } + + if (records.length > 0) { + //clean backup file + if (counter > 0) nosql.clean(); + } + + //no data in db, remove + if (records.length == 0) { + if (counter > 0) nosql.drop(); + } + + const d = new Date(); + lastRestoreTime = d.getTime(); + + processingData = false; + + } + + instance.on('options', main); + //instance.reconfigure(); +}; diff --git a/RVO21/monitor.txt b/RVO21/monitor.txt new file mode 100755 index 0000000..1b5c4b8 --- /dev/null +++ b/RVO21/monitor.txt @@ -0,0 +1,4218 @@ +[2024-10-11T13:30:05.428] [INFO] monitorLogs - MQTT broker connected +[2024-10-12T03:39:11.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-12 03:39:11 +[2024-10-12T13:00:13.169] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-12T13:00:13.205] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-12T13:00:13.240] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-13T03:39:12.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-13 03:39:12 +[2024-10-13T13:00:13.447] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-13T13:00:13.487] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-13T13:00:13.522] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-14T03:39:14.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-14 03:39:14 +[2024-10-14T13:00:13.533] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-14T13:00:13.572] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-14T13:00:13.607] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-15T03:39:14.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-15 03:39:14 +[2024-10-15T13:00:13.597] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-15T13:00:13.633] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-15T13:00:13.667] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-16T03:39:14.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-16 03:39:14 +[2024-10-16T09:57:26.004] [INFO] monitorLogs - MQTT broker connected +[2024-10-16T10:04:44.308] [INFO] monitorLogs - MQTT broker connected +[2024-10-16T10:55:13.571] [INFO] monitorLogs - MQTT broker connected +[2024-10-16T13:00:13.712] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-16T13:00:13.747] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-16T13:00:13.782] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-17T03:39:15.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-17 03:39:15 +[2024-10-17T13:00:13.766] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-17T13:00:13.801] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-17T13:00:13.835] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-17T13:39:08.705] [INFO] monitorLogs - MQTT broker connected +[2024-10-17T15:02:10.947] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2024-10-17T15:02:11.269] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 true turn off on startup +[2024-10-17T15:02:11.284] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 true turn off on startup +[2024-10-17T15:02:11.290] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 true turn off on startup +[2024-10-17T15:02:11.375] [INFO] monitorLogs - MQTT broker connected +[2024-10-17T15:02:16.301] [INFO] monitorLogs - buildTasks - params undefined +[2024-10-17T15:02:16.303] [INFO] monitorLogs - buildTasks: profile for line 1 +[2024-10-17T15:02:16.304] [INFO] monitorLogs - 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 +} +[2024-10-17T15:02:16.308] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-10-17T15:02:16.309] [INFO] monitorLogs - profileTimepoint: turn on line: 1 2024-10-18T11:00:00.308Z +[2024-10-17T15:02:16.311] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2024-10-17T15:02:16.312] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2024-10-17T15:02:16.313] [INFO] monitorLogs - buildTasks: profile for line 2 +[2024-10-17T15:02:16.313] [INFO] monitorLogs - 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 +} +[2024-10-17T15:02:16.315] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-10-17T15:02:16.315] [INFO] monitorLogs - profileTimepoint: turn on line: 2 2024-10-18T11:00:00.315Z +[2024-10-17T15:02:16.316] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2024-10-17T15:02:16.317] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2024-10-17T15:02:16.318] [INFO] monitorLogs - buildTasks: profile for line 3 +[2024-10-17T15:02:16.318] [INFO] monitorLogs - 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 +} +[2024-10-17T15:02:16.320] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-10-17T15:02:16.320] [INFO] monitorLogs - profileTimepoint: turn on line: 3 2024-10-18T11:00:00.320Z +[2024-10-17T15:02:16.321] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2024-10-17T15:02:16.322] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2024-10-17T15:02:16.328] [INFO] monitorLogs - tasks created: 859 +[2024-10-17T15:02:16.331] [INFO] monitorLogs - -->FLOW bol spustený ZmRwd93QL4gaezxEbAxWvw71prn2XjlPvGyqJ6BO 2024-09-23 +[2024-10-17T15:02:16.639] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-17T15:02:16.679] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-17T15:02:16.721] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-17T15:05:45.165] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2024-10-17T15:05:45.528] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 true turn off on startup +[2024-10-17T15:05:45.543] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 true turn off on startup +[2024-10-17T15:05:45.549] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 true turn off on startup +[2024-10-17T15:05:47.093] [INFO] monitorLogs - MQTT broker connected +[2024-10-17T15:05:50.561] [INFO] monitorLogs - buildTasks - params undefined +[2024-10-17T15:05:50.563] [INFO] monitorLogs - buildTasks: profile for line 1 +[2024-10-17T15:05:50.563] [INFO] monitorLogs - 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 +} +[2024-10-17T15:05:50.566] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-10-17T15:05:50.568] [INFO] monitorLogs - profileTimepoint: turn on line: 1 2024-10-18T11:00:00.567Z +[2024-10-17T15:05:50.569] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2024-10-17T15:05:50.571] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2024-10-17T15:05:50.572] [INFO] monitorLogs - buildTasks: profile for line 2 +[2024-10-17T15:05:50.573] [INFO] monitorLogs - 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 +} +[2024-10-17T15:05:50.574] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-10-17T15:05:50.575] [INFO] monitorLogs - profileTimepoint: turn on line: 2 2024-10-18T11:00:00.574Z +[2024-10-17T15:05:50.575] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2024-10-17T15:05:50.576] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2024-10-17T15:05:50.577] [INFO] monitorLogs - buildTasks: profile for line 3 +[2024-10-17T15:05:50.577] [INFO] monitorLogs - 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 +} +[2024-10-17T15:05:50.579] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-10-17T15:05:50.579] [INFO] monitorLogs - profileTimepoint: turn on line: 3 2024-10-18T11:00:00.579Z +[2024-10-17T15:05:50.580] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2024-10-17T15:05:50.581] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2024-10-17T15:05:50.587] [INFO] monitorLogs - tasks created: 859 +[2024-10-17T15:05:50.589] [INFO] monitorLogs - -->FLOW bol spustený ZmRwd93QL4gaezxEbAxWvw71prn2XjlPvGyqJ6BO 2024-09-23 +[2024-10-17T15:05:50.898] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-17T15:05:50.938] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-17T15:05:50.978] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-17T15:14:50.441] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2024-10-17T15:14:50.756] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 true turn off on startup +[2024-10-17T15:14:50.771] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 true turn off on startup +[2024-10-17T15:14:50.776] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 true turn off on startup +[2024-10-17T15:14:50.919] [INFO] monitorLogs - MQTT broker connected +[2024-10-17T15:14:55.788] [INFO] monitorLogs - buildTasks - params undefined +[2024-10-17T15:14:55.790] [INFO] monitorLogs - buildTasks: profile for line 1 +[2024-10-17T15:14:55.791] [INFO] monitorLogs - 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 +} +[2024-10-17T15:14:55.794] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-10-17T15:14:55.796] [INFO] monitorLogs - profileTimepoint: turn on line: 1 2024-10-18T11:00:00.795Z +[2024-10-17T15:14:55.797] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2024-10-17T15:14:55.799] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2024-10-17T15:14:55.800] [INFO] monitorLogs - buildTasks: profile for line 2 +[2024-10-17T15:14:55.801] [INFO] monitorLogs - 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 +} +[2024-10-17T15:14:55.803] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-10-17T15:14:55.803] [INFO] monitorLogs - profileTimepoint: turn on line: 2 2024-10-18T11:00:00.803Z +[2024-10-17T15:14:55.804] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2024-10-17T15:14:55.805] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2024-10-17T15:14:55.806] [INFO] monitorLogs - buildTasks: profile for line 3 +[2024-10-17T15:14:55.806] [INFO] monitorLogs - 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 +} +[2024-10-17T15:14:55.808] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-10-17T15:14:55.809] [INFO] monitorLogs - profileTimepoint: turn on line: 3 2024-10-18T11:00:00.809Z +[2024-10-17T15:14:55.810] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2024-10-17T15:14:55.811] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2024-10-17T15:14:55.817] [INFO] monitorLogs - tasks created: 875 +[2024-10-17T15:14:55.819] [INFO] monitorLogs - -->FLOW bol spustený ZmRwd93QL4gaezxEbAxWvw71prn2XjlPvGyqJ6BO 2024-09-23 +[2024-10-17T15:14:56.128] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-17T15:14:56.167] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-17T15:14:56.208] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-17T18:24:48.351] [INFO] monitorLogs - MQTT broker error Error: Connection refused: Server unavailable + at MqttClient._handleConnack (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:1388:17) + at MqttClient._handlePacket (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:549:12) + at work (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:438:12) + at Writable.writable._write (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:452:5) + at doWrite (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:409:139) + at writeOrBuffer (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:398:5) + at Writable.write (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:307:11) + at Socket.ondata (internal/streams/readable.js:731:22) + at Socket.emit (events.js:400:28) + at addChunk (internal/streams/readable.js:293:12) { + code: 3 +} +[2024-10-17T18:24:51.687] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T03:14:53.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-18 03:14:53 +[2024-10-18T13:00:00.936] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-18T13:00:00.976] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-18T13:00:01.012] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-18T17:20:13.638] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T17:20:14.651] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T17:40:50.955] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T17:50:03.943] [INFO] monitorLogs - MQTT broker error Error: read ECONNRESET + at TCP.onStreamRead (internal/stream_base_commons.js:209:20) { + errno: -104, + code: 'ECONNRESET', + syscall: 'read' +} +[2024-10-18T17:50:05.545] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T17:54:31.976] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T18:03:32.867] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T18:03:34.445] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T18:14:51.316] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T18:15:39.255] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T18:36:51.667] [INFO] monitorLogs - MQTT broker error Error: read ECONNRESET + at TCP.onStreamRead (internal/stream_base_commons.js:209:20) { + errno: -104, + code: 'ECONNRESET', + syscall: 'read' +} +[2024-10-18T18:36:52.948] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T20:30:06.646] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T20:30:06.807] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T20:30:07.177] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T20:44:07.271] [INFO] monitorLogs - MQTT broker connected +[2024-10-19T03:14:54.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-19 03:14:54 +[2024-10-19T13:00:00.980] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-19T13:00:01.017] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-19T13:00:01.052] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-20T03:14:54.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-20 03:14:54 +[2024-10-20T13:00:01.414] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-20T13:00:01.452] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-20T13:00:01.488] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-21T03:14:55.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-21 03:14:55 +[2024-10-21T03:51:33.597] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T03:51:33.795] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T04:10:15.321] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T04:10:17.611] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T04:37:31.790] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T09:11:24.627] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T09:55:21.341] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T09:55:22.020] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T09:55:22.175] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T10:23:09.544] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T10:23:10.673] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T13:00:01.360] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-21T13:00:01.535] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-21T13:00:01.570] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-22T03:14:56.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-22 03:14:56 +[2024-10-22T13:00:01.519] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-22T13:00:01.556] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-22T13:00:01.592] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-23T03:14:57.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-23 03:14:57 +[2024-10-23T13:00:01.922] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-23T13:00:01.959] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-23T13:00:01.994] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-24T03:14:58.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-24 03:14:58 +[2024-10-24T12:31:37.120] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2024-10-24T12:31:37.493] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 true turn off on startup +[2024-10-24T12:31:37.507] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 true turn off on startup +[2024-10-24T12:31:37.513] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 true turn off on startup +[2024-10-24T12:31:38.900] [INFO] monitorLogs - MQTT broker connected +[2024-10-24T12:31:42.526] [INFO] monitorLogs - buildTasks - params undefined +[2024-10-24T12:31:42.528] [INFO] monitorLogs - buildTasks: profile for line 1 +[2024-10-24T12:31:42.529] [INFO] monitorLogs - 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 +} +[2024-10-24T12:31:42.531] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-10-24T12:31:42.533] [INFO] monitorLogs - profileTimepoint: turn on line: 1 2024-10-24T11:00:00.532Z +[2024-10-24T12:31:42.534] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2024-10-24T12:31:42.535] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2024-10-24T12:31:42.536] [INFO] monitorLogs - buildTasks: profile for line 2 +[2024-10-24T12:31:42.536] [INFO] monitorLogs - 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 +} +[2024-10-24T12:31:42.539] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-10-24T12:31:42.539] [INFO] monitorLogs - profileTimepoint: turn on line: 2 2024-10-24T11:00:00.539Z +[2024-10-24T12:31:42.540] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2024-10-24T12:31:42.541] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2024-10-24T12:31:42.542] [INFO] monitorLogs - buildTasks: profile for line 3 +[2024-10-24T12:31:42.542] [INFO] monitorLogs - 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 +} +[2024-10-24T12:31:42.543] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-10-24T12:31:42.544] [INFO] monitorLogs - profileTimepoint: turn on line: 3 2024-10-24T11:00:00.544Z +[2024-10-24T12:31:42.545] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2024-10-24T12:31:42.546] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2024-10-24T12:31:42.552] [INFO] monitorLogs - tasks created: 875 +[2024-10-24T12:31:42.554] [INFO] monitorLogs - -->FLOW bol spustený ZmRwd93QL4gaezxEbAxWvw71prn2XjlPvGyqJ6BO 2024-09-23 +[2024-10-24T12:31:42.862] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-24T12:31:42.901] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-24T12:31:42.941] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-24T13:00:00.605] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-24T13:00:00.643] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-24T13:00:00.681] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-25T03:31:38.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-25 03:31:38 +[2024-10-25T13:00:00.730] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-25T13:00:00.767] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-25T13:00:00.803] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-26T03:31:39.013] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-26 03:31:39 +[2024-10-26T13:00:00.898] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-26T13:00:00.942] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-26T13:00:00.977] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-27T03:31:40.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-27 03:31:40 +[2024-10-27T12:00:01.074] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-27T12:00:01.116] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-27T12:00:01.152] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-28T03:31:41.013] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-28 03:31:41 +[2024-10-28T12:00:01.184] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-28T12:00:01.221] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-28T12:00:01.256] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-29T03:31:42.014] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-29 03:31:42 +[2024-10-29T12:00:01.241] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-29T12:00:01.279] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-29T12:00:01.315] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-30T03:31:43.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-30 03:31:43 +[2024-10-30T09:26:02.186] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2024-10-30T09:26:02.591] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 true turn off on startup +[2024-10-30T09:26:02.605] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 true turn off on startup +[2024-10-30T09:26:02.611] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 true turn off on startup +[2024-10-30T09:26:04.059] [INFO] monitorLogs - MQTT broker connected +[2024-10-30T09:26:07.623] [INFO] monitorLogs - buildTasks - params undefined +[2024-10-30T09:26:07.625] [INFO] monitorLogs - buildTasks: profile for line 1 +[2024-10-30T09:26:07.626] [INFO] monitorLogs - 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 +} +[2024-10-30T09:26:07.628] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-10-30T09:26:07.630] [INFO] monitorLogs - profileTimepoint: turn on line: 1 2024-10-30T12:00:00.629Z +[2024-10-30T09:26:07.631] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2024-10-30T09:26:07.632] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2024-10-30T09:26:07.633] [INFO] monitorLogs - buildTasks: profile for line 2 +[2024-10-30T09:26:07.633] [INFO] monitorLogs - 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 +} +[2024-10-30T09:26:07.635] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-10-30T09:26:07.636] [INFO] monitorLogs - profileTimepoint: turn on line: 2 2024-10-30T12:00:00.636Z +[2024-10-30T09:26:07.637] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2024-10-30T09:26:07.638] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2024-10-30T09:26:07.638] [INFO] monitorLogs - buildTasks: profile for line 3 +[2024-10-30T09:26:07.639] [INFO] monitorLogs - 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 +} +[2024-10-30T09:26:07.640] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-10-30T09:26:07.641] [INFO] monitorLogs - profileTimepoint: turn on line: 3 2024-10-30T12:00:00.641Z +[2024-10-30T09:26:07.641] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2024-10-30T09:26:07.642] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2024-10-30T09:26:07.653] [INFO] monitorLogs - tasks created: 875 +[2024-10-30T09:26:07.659] [INFO] monitorLogs - -->FLOW bol spustený ZmRwd93QL4gaezxEbAxWvw71prn2XjlPvGyqJ6BO 2024-09-23 +[2024-10-30T09:26:07.963] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-30T09:26:08.003] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-30T09:26:08.043] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-30T13:00:00.899] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-30T13:00:00.936] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-30T13:00:00.972] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-31T03:26:02.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-31 03:26:02 +[2024-10-31T13:00:01.005] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-31T13:00:01.040] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-31T13:00:01.075] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-01T03:26:03.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-01 03:26:03 +[2024-11-01T13:00:01.287] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-01T13:00:01.322] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-01T13:00:01.356] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-02T03:26:04.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-02 03:26:04 +[2024-11-02T13:00:01.350] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-02T13:00:01.388] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-02T13:00:01.423] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-03T03:26:05.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-03 03:26:05 +[2024-11-03T13:00:01.593] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-03T13:00:01.630] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-03T13:00:01.665] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-04T03:26:06.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-04 03:26:06 +[2024-11-04T13:00:03.414] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-04T13:00:03.449] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-04T13:00:03.484] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-04T14:13:38.694] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2024-11-04T14:13:39.022] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 true turn off on startup +[2024-11-04T14:13:39.037] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 true turn off on startup +[2024-11-04T14:13:39.043] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 true turn off on startup +[2024-11-04T14:13:39.247] [INFO] monitorLogs - MQTT broker connected +[2024-11-04T14:13:44.055] [INFO] monitorLogs - buildTasks - params undefined +[2024-11-04T14:13:44.057] [INFO] monitorLogs - buildTasks: profile for line 1 +[2024-11-04T14:13:44.058] [INFO] monitorLogs - 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 +} +[2024-11-04T14:13:44.061] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-04T14:13:44.063] [INFO] monitorLogs - profileTimepoint: turn on line: 1 2024-11-05T12:00:00.062Z +[2024-11-04T14:13:44.065] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2024-11-04T14:13:44.066] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2024-11-04T14:13:44.067] [INFO] monitorLogs - buildTasks: profile for line 2 +[2024-11-04T14:13:44.067] [INFO] monitorLogs - 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 +} +[2024-11-04T14:13:44.069] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-04T14:13:44.070] [INFO] monitorLogs - profileTimepoint: turn on line: 2 2024-11-05T12:00:00.069Z +[2024-11-04T14:13:44.071] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2024-11-04T14:13:44.072] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2024-11-04T14:13:44.072] [INFO] monitorLogs - buildTasks: profile for line 3 +[2024-11-04T14:13:44.073] [INFO] monitorLogs - 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 +} +[2024-11-04T14:13:44.074] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-04T14:13:44.075] [INFO] monitorLogs - profileTimepoint: turn on line: 3 2024-11-05T12:00:00.075Z +[2024-11-04T14:13:44.075] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2024-11-04T14:13:44.076] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2024-11-04T14:13:44.083] [INFO] monitorLogs - tasks created: 875 +[2024-11-04T14:13:44.085] [INFO] monitorLogs - -->FLOW bol spustený ZmRwd93QL4gaezxEbAxWvw71prn2XjlPvGyqJ6BO 2024-09-23 +[2024-11-04T14:13:44.394] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-04T14:13:44.435] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-04T14:13:44.476] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-05T03:13:39.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-05 03:13:39 +[2024-11-05T13:00:00.108] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-05T13:00:00.145] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-05T13:00:00.182] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-05T22:55:57.282] [INFO] monitorLogs - MQTT broker connected +[2024-11-06T03:13:40.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-06 03:13:40 +[2024-11-06T13:00:00.220] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-06T13:00:00.257] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-06T13:00:00.293] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-07T01:40:58.801] [INFO] monitorLogs - MQTT broker connected +[2024-11-07T03:13:45.418] [INFO] monitorLogs - setCorrectPlcTimeOnceADay - function error SyntaxError: Unexpected token < in JSON at position 0 + at JSON.parse () + at /home/unipi/flowserver/flow/cmd_manager.js:2898:26 + at Object.exec_callback [as callback] (/home/unipi/flowserver/node_modules/total.js/builders.js:5803:3) + at IncomingMessage.request_process_end (/home/unipi/flowserver/node_modules/total.js/utils.js:1184:11) + at IncomingMessage.emit (events.js:412:35) + at endReadableNT (internal/streams/readable.js:1334:12) + at processTicksAndRejections (internal/process/task_queues.js:82:21) 503: Service Unavailable
503
Service Unavailable
+[2024-11-07T13:00:00.379] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-07T13:00:00.415] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-07T13:00:00.451] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-07T15:55:50.474] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2024-11-07T15:55:50.887] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 true turn off on startup +[2024-11-07T15:55:50.902] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 true turn off on startup +[2024-11-07T15:55:50.907] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 true turn off on startup +[2024-11-07T15:55:52.161] [INFO] monitorLogs - MQTT broker connected +[2024-11-07T15:55:55.920] [INFO] monitorLogs - buildTasks - params undefined +[2024-11-07T15:55:55.921] [INFO] monitorLogs - buildTasks: profile for line 1 +[2024-11-07T15:55:55.922] [INFO] monitorLogs - 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 +} +[2024-11-07T15:55:55.925] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-07T15:55:55.927] [INFO] monitorLogs - profileTimepoint: turn on line: 1 2024-11-08T12:00:00.926Z +[2024-11-07T15:55:55.928] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2024-11-07T15:55:55.930] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2024-11-07T15:55:55.931] [INFO] monitorLogs - buildTasks: profile for line 2 +[2024-11-07T15:55:55.931] [INFO] monitorLogs - 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 +} +[2024-11-07T15:55:55.933] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-07T15:55:55.934] [INFO] monitorLogs - profileTimepoint: turn on line: 2 2024-11-08T12:00:00.933Z +[2024-11-07T15:55:55.934] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2024-11-07T15:55:55.935] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2024-11-07T15:55:55.936] [INFO] monitorLogs - buildTasks: profile for line 3 +[2024-11-07T15:55:55.936] [INFO] monitorLogs - 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 +} +[2024-11-07T15:55:55.938] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-07T15:55:55.938] [INFO] monitorLogs - profileTimepoint: turn on line: 3 2024-11-08T12:00:00.938Z +[2024-11-07T15:55:55.939] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2024-11-07T15:55:55.940] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2024-11-07T15:55:55.946] [INFO] monitorLogs - tasks created: 875 +[2024-11-07T15:55:55.953] [INFO] monitorLogs - -->FLOW bol spustený ZmRwd93QL4gaezxEbAxWvw71prn2XjlPvGyqJ6BO 2024-09-23 +[2024-11-07T15:55:56.257] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-07T15:55:56.298] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-07T15:55:56.339] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-08T03:55:54.024] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-08 03:55:54 +[2024-11-08T13:00:01.135] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-08T13:00:01.171] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-08T13:00:01.207] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-09T03:55:55.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-09 03:55:55 +[2024-11-09T12:36:17.093] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2024-11-09T12:36:22.592] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 true turn off on startup +[2024-11-09T12:36:22.593] [INFO] monitorLogs - turnLine: off pin (relay) relay1_02 +[2024-11-09T12:36:22.604] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 true turn off on startup +[2024-11-09T12:36:22.605] [INFO] monitorLogs - turnLine: off pin (relay) relay1_03 +[2024-11-09T12:36:22.610] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 true turn off on startup +[2024-11-09T12:36:22.611] [INFO] monitorLogs - turnLine: off pin (relay) relay1_04 +[2024-11-09T12:36:22.763] [INFO] monitorLogs - MQTT client connected +[2024-11-09T12:36:27.621] [INFO] monitorLogs - buildTasks - params undefined +[2024-11-09T12:36:27.622] [INFO] monitorLogs - buildTasks: profile for line 1 +[2024-11-09T12:36:27.623] [INFO] monitorLogs - 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 +} +[2024-11-09T12:36:27.625] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-09T12:36:27.626] [INFO] monitorLogs - profileTimepoint: turn on line: 1 2024-11-09T12:00:00.626Z +[2024-11-09T12:36:27.628] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2024-11-09T12:36:27.629] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2024-11-09T12:36:27.630] [INFO] monitorLogs - buildTasks: profile for line 2 +[2024-11-09T12:36:27.630] [INFO] monitorLogs - 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 +} +[2024-11-09T12:36:27.632] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-09T12:36:27.633] [INFO] monitorLogs - profileTimepoint: turn on line: 2 2024-11-09T12:00:00.633Z +[2024-11-09T12:36:27.634] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2024-11-09T12:36:27.635] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2024-11-09T12:36:27.635] [INFO] monitorLogs - buildTasks: profile for line 3 +[2024-11-09T12:36:27.636] [INFO] monitorLogs - 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 +} +[2024-11-09T12:36:27.637] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-09T12:36:27.638] [INFO] monitorLogs - profileTimepoint: turn on line: 3 2024-11-09T12:00:00.638Z +[2024-11-09T12:36:27.638] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2024-11-09T12:36:27.639] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2024-11-09T12:36:27.645] [INFO] monitorLogs - tasks created: 875 +[2024-11-09T12:36:27.649] [INFO] monitorLogs - -->FLOW bol spustený ZmRwd93QL4gaezxEbAxWvw71prn2XjlPvGyqJ6BO 2024-11-04 +[2024-11-09T12:36:27.955] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-09T12:36:27.955] [INFO] monitorLogs - turnLine: on pin (relay) relay1_02 +[2024-11-09T12:36:27.998] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-09T12:36:27.999] [INFO] monitorLogs - turnLine: on pin (relay) relay1_03 +[2024-11-09T12:36:28.042] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-09T12:36:28.043] [INFO] monitorLogs - turnLine: on pin (relay) relay1_04 +[2024-11-09T12:42:22.966] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2024-11-09T12:42:28.451] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 true turn off on startup +[2024-11-09T12:42:28.453] [INFO] monitorLogs - turnLine: off pin (relay) relay1_02 +[2024-11-09T12:42:28.464] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 true turn off on startup +[2024-11-09T12:42:28.464] [INFO] monitorLogs - turnLine: off pin (relay) relay1_03 +[2024-11-09T12:42:28.470] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 true turn off on startup +[2024-11-09T12:42:28.470] [INFO] monitorLogs - turnLine: off pin (relay) relay1_04 +[2024-11-09T12:42:28.602] [INFO] monitorLogs - MQTT client connected +[2024-11-09T12:42:33.482] [INFO] monitorLogs - buildTasks - params undefined +[2024-11-09T12:42:33.483] [INFO] monitorLogs - buildTasks: profile for line 1 +[2024-11-09T12:42:33.484] [INFO] monitorLogs - 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 +} +[2024-11-09T12:42:33.487] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-09T12:42:33.489] [INFO] monitorLogs - profileTimepoint: turn on line: 1 2024-11-09T12:00:00.488Z +[2024-11-09T12:42:33.490] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2024-11-09T12:42:33.491] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2024-11-09T12:42:33.492] [INFO] monitorLogs - buildTasks: profile for line 2 +[2024-11-09T12:42:33.492] [INFO] monitorLogs - 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 +} +[2024-11-09T12:42:33.494] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-09T12:42:33.494] [INFO] monitorLogs - profileTimepoint: turn on line: 2 2024-11-09T12:00:00.494Z +[2024-11-09T12:42:33.495] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2024-11-09T12:42:33.496] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2024-11-09T12:42:33.497] [INFO] monitorLogs - buildTasks: profile for line 3 +[2024-11-09T12:42:33.497] [INFO] monitorLogs - 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 +} +[2024-11-09T12:42:33.498] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-09T12:42:33.499] [INFO] monitorLogs - profileTimepoint: turn on line: 3 2024-11-09T12:00:00.499Z +[2024-11-09T12:42:33.500] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2024-11-09T12:42:33.501] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2024-11-09T12:42:33.506] [INFO] monitorLogs - tasks created: 875 +[2024-11-09T12:42:33.510] [INFO] monitorLogs - -->FLOW bol spustený ZmRwd93QL4gaezxEbAxWvw71prn2XjlPvGyqJ6BO 2024-11-04 +[2024-11-09T12:42:33.815] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-09T12:42:33.815] [INFO] monitorLogs - turnLine: on pin (relay) relay1_02 +[2024-11-09T12:42:33.867] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-09T12:42:33.868] [INFO] monitorLogs - turnLine: on pin (relay) relay1_03 +[2024-11-09T12:42:33.912] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-09T12:42:33.913] [INFO] monitorLogs - turnLine: on pin (relay) relay1_04 +[2024-11-09T13:00:00.854] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-09T13:00:00.892] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-09T13:00:00.930] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-09T13:10:59.156] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2024-11-09T13:11:04.527] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 true turn off on startup +[2024-11-09T13:11:04.529] [INFO] monitorLogs - turnLine: off pin (relay) relay1_02 +[2024-11-09T13:11:04.543] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 true turn off on startup +[2024-11-09T13:11:04.544] [INFO] monitorLogs - turnLine: off pin (relay) relay1_03 +[2024-11-09T13:11:04.550] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 true turn off on startup +[2024-11-09T13:11:04.551] [INFO] monitorLogs - turnLine: off pin (relay) relay1_04 +[2024-11-09T13:11:04.646] [INFO] monitorLogs - MQTT client connected +[2024-11-09T13:11:09.564] [INFO] monitorLogs - buildTasks - params undefined +[2024-11-09T13:11:09.565] [INFO] monitorLogs - buildTasks: profile for line 1 +[2024-11-09T13:11:09.566] [INFO] monitorLogs - 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 +} +[2024-11-09T13:11:09.569] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-09T13:11:09.570] [INFO] monitorLogs - profileTimepoint: turn on line: 1 2024-11-10T12:00:00.570Z +[2024-11-09T13:11:09.572] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2024-11-09T13:11:09.573] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2024-11-09T13:11:09.574] [INFO] monitorLogs - buildTasks: profile for line 2 +[2024-11-09T13:11:09.574] [INFO] monitorLogs - 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 +} +[2024-11-09T13:11:09.576] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-09T13:11:09.577] [INFO] monitorLogs - profileTimepoint: turn on line: 2 2024-11-10T12:00:00.577Z +[2024-11-09T13:11:09.578] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2024-11-09T13:11:09.578] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2024-11-09T13:11:09.579] [INFO] monitorLogs - buildTasks: profile for line 3 +[2024-11-09T13:11:09.579] [INFO] monitorLogs - 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 +} +[2024-11-09T13:11:09.581] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-09T13:11:09.582] [INFO] monitorLogs - profileTimepoint: turn on line: 3 2024-11-10T12:00:00.581Z +[2024-11-09T13:11:09.582] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2024-11-09T13:11:09.583] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2024-11-09T13:11:09.589] [INFO] monitorLogs - tasks created: 875 +[2024-11-09T13:11:09.592] [INFO] monitorLogs - -->FLOW bol spustený ZmRwd93QL4gaezxEbAxWvw71prn2XjlPvGyqJ6BO 2024-11-04 +[2024-11-09T13:11:09.898] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-09T13:11:09.899] [INFO] monitorLogs - turnLine: on pin (relay) relay1_02 +[2024-11-09T13:11:09.943] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-09T13:11:09.944] [INFO] monitorLogs - turnLine: on pin (relay) relay1_03 +[2024-11-09T13:11:09.987] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-09T13:11:09.988] [INFO] monitorLogs - turnLine: on pin (relay) relay1_04 +[2024-11-09T13:22:17.304] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2024-11-09T13:22:22.698] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 true turn off on startup +[2024-11-09T13:22:22.700] [INFO] monitorLogs - turnLine: off pin (relay) relay1_02 +[2024-11-09T13:22:22.714] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 true turn off on startup +[2024-11-09T13:22:22.715] [INFO] monitorLogs - turnLine: off pin (relay) relay1_03 +[2024-11-09T13:22:22.721] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 true turn off on startup +[2024-11-09T13:22:22.722] [INFO] monitorLogs - turnLine: off pin (relay) relay1_04 +[2024-11-09T13:22:22.825] [INFO] monitorLogs - MQTT client connected +[2024-11-09T13:22:27.734] [INFO] monitorLogs - buildTasks - params undefined +[2024-11-09T13:22:27.735] [INFO] monitorLogs - buildTasks: profile for line 1 +[2024-11-09T13:22:27.736] [INFO] monitorLogs - 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 +} +[2024-11-09T13:22:27.738] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-09T13:22:27.739] [INFO] monitorLogs - profileTimepoint: turn on line: 1 2024-11-10T12:00:00.739Z +[2024-11-09T13:22:27.741] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2024-11-09T13:22:27.742] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2024-11-09T13:22:27.743] [INFO] monitorLogs - buildTasks: profile for line 2 +[2024-11-09T13:22:27.743] [INFO] monitorLogs - 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 +} +[2024-11-09T13:22:27.745] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-09T13:22:27.746] [INFO] monitorLogs - profileTimepoint: turn on line: 2 2024-11-10T12:00:00.745Z +[2024-11-09T13:22:27.746] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2024-11-09T13:22:27.747] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2024-11-09T13:22:27.748] [INFO] monitorLogs - buildTasks: profile for line 3 +[2024-11-09T13:22:27.748] [INFO] monitorLogs - 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 +} +[2024-11-09T13:22:27.750] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-09T13:22:27.750] [INFO] monitorLogs - profileTimepoint: turn on line: 3 2024-11-10T12:00:00.750Z +[2024-11-09T13:22:27.751] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2024-11-09T13:22:27.752] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2024-11-09T13:22:27.758] [INFO] monitorLogs - tasks created: 875 +[2024-11-09T13:22:27.761] [INFO] monitorLogs - -->FLOW bol spustený ZmRwd93QL4gaezxEbAxWvw71prn2XjlPvGyqJ6BO 2024-11-04 +[2024-11-09T13:22:28.067] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-09T13:22:28.067] [INFO] monitorLogs - turnLine: on pin (relay) relay1_02 +[2024-11-09T13:22:28.109] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-09T13:22:28.110] [INFO] monitorLogs - turnLine: on pin (relay) relay1_03 +[2024-11-09T13:22:28.153] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-09T13:22:28.154] [INFO] monitorLogs - turnLine: on pin (relay) relay1_04 +[2024-11-09T13:25:08.419] [INFO] monitorLogs - turnLine on - (line, SETTINGS.maintenance_mode) 0 true command received from platform +[2024-11-09T13:25:21.750] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false command received from platform +[2024-11-10T03:22:25.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-10 03:22:25 +[2024-11-10T13:00:00.800] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-10T13:00:00.837] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-10T13:00:00.873] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-11T03:22:26.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-11 03:22:26 +[2024-11-11T13:00:00.980] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-11T13:00:01.017] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-11T13:00:01.055] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-11T23:08:40.615] [INFO] monitorLogs - MQTT client connected +[2024-11-12T03:22:27.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-12 03:22:27 +[2024-11-12T13:00:01.859] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-12T13:00:01.896] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-12T13:00:01.931] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-13T03:22:28.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-13 03:22:28 +[2024-11-13T10:22:13.116] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2024-11-13T10:22:18.435] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 true turn off on startup +[2024-11-13T10:22:18.450] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 true turn off on startup +[2024-11-13T10:22:18.456] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 true turn off on startup +[2024-11-13T10:22:18.919] [INFO] monitorLogs - MQTT client connected +[2024-11-13T10:22:23.467] [INFO] monitorLogs - buildTasks - params undefined +[2024-11-13T10:22:23.469] [INFO] monitorLogs - buildTasks: profile for line 1 +[2024-11-13T10:22:23.470] [INFO] monitorLogs - 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 +} +[2024-11-13T10:22:23.472] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-13T10:22:23.473] [INFO] monitorLogs - profileTimepoint: turn on line: 1 2024-11-13T12:00:00.473Z +[2024-11-13T10:22:23.475] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2024-11-13T10:22:23.476] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2024-11-13T10:22:23.477] [INFO] monitorLogs - buildTasks: profile for line 2 +[2024-11-13T10:22:23.477] [INFO] monitorLogs - 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 +} +[2024-11-13T10:22:23.479] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-13T10:22:23.480] [INFO] monitorLogs - profileTimepoint: turn on line: 2 2024-11-13T12:00:00.480Z +[2024-11-13T10:22:23.481] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2024-11-13T10:22:23.482] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2024-11-13T10:22:23.483] [INFO] monitorLogs - buildTasks: profile for line 3 +[2024-11-13T10:22:23.483] [INFO] monitorLogs - 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 +} +[2024-11-13T10:22:23.485] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-13T10:22:23.485] [INFO] monitorLogs - profileTimepoint: turn on line: 3 2024-11-13T12:00:00.485Z +[2024-11-13T10:22:23.486] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2024-11-13T10:22:23.487] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2024-11-13T10:22:23.495] [INFO] monitorLogs - tasks created: 875 +[2024-11-13T10:22:23.498] [INFO] monitorLogs - -->FLOW bol spustený ZmRwd93QL4gaezxEbAxWvw71prn2XjlPvGyqJ6BO 2024-11-04 +[2024-11-13T10:22:23.804] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-13T10:22:23.848] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-13T10:22:23.896] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-14T03:22:19.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-14 03:22:19 +[2024-11-15T03:22:20.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-15 03:22:20 +[2024-11-16T03:22:21.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-16 03:22:21 +[2024-11-17T03:22:22.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-17 03:22:22 +[2024-11-18T03:22:23.013] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-18 03:22:23 +[2024-11-19T03:22:25.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-19 03:22:25 +[2024-11-20T03:22:25.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-20 03:22:25 +[2024-11-21T03:22:26.015] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-21 03:22:26 +[2024-11-22T03:22:27.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-22 03:22:27 +[2024-11-23T03:22:27.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-23 03:22:27 +[2024-11-24T03:22:28.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-24 03:22:28 +[2024-11-25T03:22:29.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-25 03:22:29 +[2024-11-25T06:11:59.544] [INFO] monitorLogs - MQTT client connected +[2024-11-25T07:12:32.997] [INFO] monitorLogs - MQTT client connected +[2024-11-26T03:22:30.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-26 03:22:30 +[2024-11-27T03:22:31.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-27 03:22:31 +[2024-11-28T03:22:32.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-28 03:22:32 +[2024-11-29T03:22:32.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-29 03:22:32 +[2024-11-30T03:22:33.014] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-30 03:22:33 +[2024-11-30T15:41:49.009] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2024-11-30T15:41:54.335] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 true turn off on startup +[2024-11-30T15:41:54.350] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 true turn off on startup +[2024-11-30T15:41:54.356] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 true turn off on startup +[2024-11-30T15:41:54.469] [INFO] monitorLogs - MQTT client connected +[2024-11-30T15:41:59.368] [INFO] monitorLogs - buildTasks - params undefined +[2024-11-30T15:41:59.370] [INFO] monitorLogs - buildTasks: profile for line 1 +[2024-11-30T15:41:59.371] [INFO] monitorLogs - 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 +} +[2024-11-30T15:41:59.374] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-30T15:41:59.376] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2024-12-01T12:00:00.375Z +[2024-11-30T15:41:59.377] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2024-11-30T15:41:59.378] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2024-11-30T15:41:59.379] [INFO] monitorLogs - buildTasks: profile for line 2 +[2024-11-30T15:41:59.379] [INFO] monitorLogs - 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 +} +[2024-11-30T15:41:59.381] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-30T15:41:59.382] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2024-12-01T12:00:00.382Z +[2024-11-30T15:41:59.384] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2024-11-30T15:41:59.385] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2024-11-30T15:41:59.386] [INFO] monitorLogs - buildTasks: profile for line 3 +[2024-11-30T15:41:59.386] [INFO] monitorLogs - 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 +} +[2024-11-30T15:41:59.387] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-30T15:41:59.388] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2024-12-01T12:00:00.388Z +[2024-11-30T15:41:59.389] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2024-11-30T15:41:59.390] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2024-11-30T15:41:59.396] [INFO] monitorLogs - tasks created: 875 +[2024-11-30T15:41:59.398] [INFO] monitorLogs - -->FLOW bol spustený ZmRwd93QL4gaezxEbAxWvw71prn2XjlPvGyqJ6BO 2024-11-04 +[2024-11-30T15:41:59.705] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-30T15:41:59.748] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-30T15:41:59.791] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-01T03:41:56.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-01 03:41:56 +[2024-12-02T03:41:57.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-02 03:41:57 +[2024-12-03T03:41:58.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-03 03:41:58 +[2024-12-04T00:19:07.624] [INFO] monitorLogs - MQTT client connected +[2024-12-04T03:41:59.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-04 03:41:59 +[2024-12-05T03:42:00.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-05 03:42:00 +[2024-12-05T10:59:33.851] [INFO] monitorLogs - MQTT client connected +[2024-12-06T03:42:01.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-06 03:42:01 +[2024-12-07T03:42:01.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-07 03:42:01 +[2024-12-08T03:42:02.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-08 03:42:02 +[2024-12-09T03:42:03.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-09 03:42:03 +[2024-12-09T08:31:52.606] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-09T08:31:53.628] [INFO] monitorLogs - websocket error, reconnect +[2024-12-09T08:31:53.630] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-09T08:45:22.116] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2024-12-09T08:45:27.467] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 true turn off on startup +[2024-12-09T08:45:27.481] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 true turn off on startup +[2024-12-09T08:45:27.487] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 true turn off on startup +[2024-12-09T08:45:27.644] [INFO] monitorLogs - MQTT client connected +[2024-12-09T08:45:32.499] [INFO] monitorLogs - buildTasks - params undefined +[2024-12-09T08:45:32.501] [INFO] monitorLogs - buildTasks: profile for line 1 +[2024-12-09T08:45:32.501] [INFO] monitorLogs - 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 +} +[2024-12-09T08:45:32.505] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-12-09T08:45:32.506] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2024-12-09T12:00:00.506Z +[2024-12-09T08:45:32.507] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2024-12-09T08:45:32.509] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2024-12-09T08:45:32.510] [INFO] monitorLogs - buildTasks: profile for line 2 +[2024-12-09T08:45:32.510] [INFO] monitorLogs - 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 +} +[2024-12-09T08:45:32.512] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-12-09T08:45:32.513] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2024-12-09T12:00:00.512Z +[2024-12-09T08:45:32.514] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2024-12-09T08:45:32.515] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2024-12-09T08:45:32.516] [INFO] monitorLogs - buildTasks: profile for line 3 +[2024-12-09T08:45:32.516] [INFO] monitorLogs - 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 +} +[2024-12-09T08:45:32.518] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-12-09T08:45:32.518] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2024-12-09T12:00:00.518Z +[2024-12-09T08:45:32.519] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2024-12-09T08:45:32.520] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2024-12-09T08:45:32.526] [INFO] monitorLogs - tasks created: 875 +[2024-12-09T08:45:32.529] [INFO] monitorLogs - -->FLOW bol spustený ZmRwd93QL4gaezxEbAxWvw71prn2XjlPvGyqJ6BO 2024-11-04 +[2024-12-09T08:45:32.835] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-09T08:45:32.879] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-09T08:45:32.923] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-09T08:47:26.034] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2024-12-09T08:47:31.408] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 true turn off on startup +[2024-12-09T08:47:31.422] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 true turn off on startup +[2024-12-09T08:47:31.428] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 true turn off on startup +[2024-12-09T08:47:31.829] [INFO] monitorLogs - MQTT client connected +[2024-12-09T08:47:36.439] [INFO] monitorLogs - buildTasks - params undefined +[2024-12-09T08:47:36.441] [INFO] monitorLogs - buildTasks: profile for line 1 +[2024-12-09T08:47:36.442] [INFO] monitorLogs - 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 +} +[2024-12-09T08:47:36.445] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-12-09T08:47:36.446] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2024-12-09T12:00:00.446Z +[2024-12-09T08:47:36.447] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2024-12-09T08:47:36.449] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2024-12-09T08:47:36.449] [INFO] monitorLogs - buildTasks: profile for line 2 +[2024-12-09T08:47:36.450] [INFO] monitorLogs - 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 +} +[2024-12-09T08:47:36.452] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-12-09T08:47:36.452] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2024-12-09T12:00:00.452Z +[2024-12-09T08:47:36.453] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2024-12-09T08:47:36.454] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2024-12-09T08:47:36.455] [INFO] monitorLogs - buildTasks: profile for line 3 +[2024-12-09T08:47:36.455] [INFO] monitorLogs - 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 +} +[2024-12-09T08:47:36.457] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-12-09T08:47:36.457] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2024-12-09T12:00:00.457Z +[2024-12-09T08:47:36.458] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2024-12-09T08:47:36.459] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2024-12-09T08:47:36.465] [INFO] monitorLogs - tasks created: 875 +[2024-12-09T08:47:36.468] [INFO] monitorLogs - -->FLOW bol spustený ZmRwd93QL4gaezxEbAxWvw71prn2XjlPvGyqJ6BO 2024-11-04 +[2024-12-09T08:47:36.774] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-09T08:47:36.818] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-09T08:47:36.863] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-09T10:07:11.389] [INFO] monitorLogs - MQTT client connected +[2024-12-09T10:47:43.424] [INFO] monitorLogs - MQTT client connected +[2024-12-10T03:47:34.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-10 03:47:34 +[2024-12-10T06:40:56.474] [INFO] monitorLogs - MQTT client connected +[2024-12-11T03:47:35.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-11 03:47:35 +[2024-12-12T03:47:35.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-12 03:47:35 +[2024-12-13T03:47:36.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-13 03:47:36 +[2024-12-14T03:47:37.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-14 03:47:37 +[2024-12-15T03:47:45.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-15 03:47:45 +[2024-12-16T03:47:39.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-16 03:47:39 +[2024-12-17T03:47:40.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-17 03:47:40 +[2024-12-18T03:47:41.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-18 03:47:41 +[2024-12-19T03:47:42.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-19 03:47:42 +[2024-12-20T03:47:43.014] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-20 03:47:43 +[2024-12-21T03:47:44.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-21 03:47:44 +[2024-12-22T03:47:44.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-22 03:47:44 +[2024-12-23T03:47:45.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-23 03:47:45 +[2024-12-24T03:47:46.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-24 03:47:46 +[2024-12-25T03:47:47.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-25 03:47:47 +[2024-12-26T03:47:48.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-26 03:47:48 +[2024-12-27T03:47:49.015] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-27 03:47:49 +[2024-12-28T03:47:49.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-28 03:47:49 +[2024-12-29T03:47:50.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-29 03:47:50 +[2024-12-30T03:47:51.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-30 03:47:51 +[2024-12-31T03:47:52.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-31 03:47:52 +[2025-01-01T03:47:53.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-01 03:47:53 +[2025-01-02T03:47:54.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-02 03:47:54 +[2025-01-02T08:47:38.978] [INFO] monitorLogs - MQTT client error Error: read ECONNRESET + at TCP.onStreamRead (internal/stream_base_commons.js:209:20) { + errno: -104, + code: 'ECONNRESET', + syscall: 'read' +} +[2025-01-02T11:45:08.064] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-01-02T11:45:13.426] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 true turn off on startup +[2025-01-02T11:45:13.440] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 true turn off on startup +[2025-01-02T11:45:13.447] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 true turn off on startup +[2025-01-02T11:45:13.510] [INFO] monitorLogs - MQTT client error Error: connect ECONNREFUSED 192.168.252.1:1883 + at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1159:16) { + errno: -111, + code: 'ECONNREFUSED', + syscall: 'connect', + address: '192.168.252.1', + port: 1883 +} +[2025-01-02T11:45:18.459] [INFO] monitorLogs - buildTasks - params undefined +[2025-01-02T11:45:18.461] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-01-02T11:45:18.462] [INFO] monitorLogs - 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 +} +[2025-01-02T11:45:18.465] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-02T11:45:18.466] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-01-02T12:00:00.465Z +[2025-01-02T11:45:18.467] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-01-02T11:45:18.468] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-01-02T11:45:18.469] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-01-02T11:45:18.470] [INFO] monitorLogs - 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 +} +[2025-01-02T11:45:18.471] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-02T11:45:18.472] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-01-02T12:00:00.472Z +[2025-01-02T11:45:18.473] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-01-02T11:45:18.474] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-01-02T11:45:18.474] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-01-02T11:45:18.475] [INFO] monitorLogs - 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 +} +[2025-01-02T11:45:18.476] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-02T11:45:18.477] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-01-02T12:00:00.477Z +[2025-01-02T11:45:18.477] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-01-02T11:45:18.478] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-01-02T11:45:18.489] [INFO] monitorLogs - tasks created: 875 +[2025-01-02T11:45:18.492] [INFO] monitorLogs - -->FLOW bol spustený ZmRwd93QL4gaezxEbAxWvw71prn2XjlPvGyqJ6BO 2025-01-02 +[2025-01-02T11:45:18.798] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-02T11:45:18.839] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-02T11:45:18.879] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-03T03:45:16.013] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-03 03:45:16 +[2025-01-03T10:19:00.048] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-01-03T10:19:05.382] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 true turn off on startup +[2025-01-03T10:19:05.398] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 true turn off on startup +[2025-01-03T10:19:05.405] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 true turn off on startup +[2025-01-03T10:19:05.423] [INFO] monitorLogs - MQTT client error Error: connect ECONNREFUSED 192.168.252.1:1883 + at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1159:16) { + errno: -111, + code: 'ECONNREFUSED', + syscall: 'connect', + address: '192.168.252.1', + port: 1883 +} +[2025-01-03T10:19:10.417] [INFO] monitorLogs - buildTasks - params undefined +[2025-01-03T10:19:10.418] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-01-03T10:19:10.419] [INFO] monitorLogs - 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 +} +[2025-01-03T10:19:10.421] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-03T10:19:10.423] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-01-03T12:00:00.422Z +[2025-01-03T10:19:10.424] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-01-03T10:19:10.425] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-01-03T10:19:10.426] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-01-03T10:19:10.427] [INFO] monitorLogs - 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 +} +[2025-01-03T10:19:10.429] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-03T10:19:10.430] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-01-03T12:00:00.430Z +[2025-01-03T10:19:10.431] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-01-03T10:19:10.432] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-01-03T10:19:10.432] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-01-03T10:19:10.433] [INFO] monitorLogs - 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 +} +[2025-01-03T10:19:10.434] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-03T10:19:10.435] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-01-03T12:00:00.435Z +[2025-01-03T10:19:10.435] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-01-03T10:19:10.436] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-01-03T10:19:10.445] [INFO] monitorLogs - tasks created: 875 +[2025-01-03T10:19:10.448] [INFO] monitorLogs - -->FLOW bol spustený ZmRwd93QL4gaezxEbAxWvw71prn2XjlPvGyqJ6BO 2025-01-02 +[2025-01-03T10:19:10.754] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-03T10:19:10.796] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-03T10:19:10.838] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-04T03:19:06.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-04 03:19:06 +[2025-01-05T03:19:07.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-05 03:19:07 +[2025-01-06T03:19:08.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-06 03:19:08 +[2025-01-07T03:19:09.013] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-07 03:19:09 +[2025-01-08T03:19:10.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-08 03:19:10 +[2025-01-09T03:19:11.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-09 03:19:11 +[2025-01-09T15:31:02.944] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-01-09T15:31:08.286] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 true turn off on startup +[2025-01-09T15:31:08.301] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 true turn off on startup +[2025-01-09T15:31:08.307] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 true turn off on startup +[2025-01-09T15:31:08.326] [INFO] monitorLogs - MQTT client error Error: connect ECONNREFUSED 192.168.252.1:1883 + at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1159:16) { + errno: -111, + code: 'ECONNREFUSED', + syscall: 'connect', + address: '192.168.252.1', + port: 1883 +} +[2025-01-09T15:31:13.319] [INFO] monitorLogs - buildTasks - params undefined +[2025-01-09T15:31:13.320] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-01-09T15:31:13.321] [INFO] monitorLogs - 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 +} +[2025-01-09T15:31:13.325] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-09T15:31:13.326] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-01-10T12:00:00.325Z +[2025-01-09T15:31:13.327] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-01-09T15:31:13.328] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-01-09T15:31:13.329] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-01-09T15:31:13.329] [INFO] monitorLogs - 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 +} +[2025-01-09T15:31:13.331] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-09T15:31:13.332] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-01-10T12:00:00.331Z +[2025-01-09T15:31:13.332] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-01-09T15:31:13.333] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-01-09T15:31:13.334] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-01-09T15:31:13.334] [INFO] monitorLogs - 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 +} +[2025-01-09T15:31:13.336] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-09T15:31:13.337] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-01-10T12:00:00.336Z +[2025-01-09T15:31:13.338] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-01-09T15:31:13.339] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-01-09T15:31:13.345] [INFO] monitorLogs - tasks created: 875 +[2025-01-09T15:31:13.348] [INFO] monitorLogs - -->FLOW bol spustený ZmRwd93QL4gaezxEbAxWvw71prn2XjlPvGyqJ6BO 2025-01-02 +[2025-01-09T15:31:13.654] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-09T15:31:13.694] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-09T15:31:13.739] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-10T03:31:09.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-10 03:31:09 +[2025-01-10T14:46:40.040] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-01-10T14:46:45.402] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 true turn off on startup +[2025-01-10T14:46:45.416] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 true turn off on startup +[2025-01-10T14:46:45.422] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 true turn off on startup +[2025-01-10T14:46:45.487] [INFO] monitorLogs - MQTT client error Error: connect ECONNREFUSED 192.168.252.1:1883 + at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1159:16) { + errno: -111, + code: 'ECONNREFUSED', + syscall: 'connect', + address: '192.168.252.1', + port: 1883 +} +[2025-01-10T14:46:50.435] [INFO] monitorLogs - buildTasks - params undefined +[2025-01-10T14:46:50.437] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-01-10T14:46:50.438] [INFO] monitorLogs - 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 +} +[2025-01-10T14:46:50.441] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-10T14:46:50.442] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-01-11T12:00:00.442Z +[2025-01-10T14:46:50.443] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-01-10T14:46:50.444] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-01-10T14:46:50.445] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-01-10T14:46:50.446] [INFO] monitorLogs - 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 +} +[2025-01-10T14:46:50.447] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-10T14:46:50.448] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-01-11T12:00:00.448Z +[2025-01-10T14:46:50.449] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-01-10T14:46:50.450] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-01-10T14:46:50.451] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-01-10T14:46:50.451] [INFO] monitorLogs - 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 +} +[2025-01-10T14:46:50.453] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-10T14:46:50.453] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-01-11T12:00:00.453Z +[2025-01-10T14:46:50.454] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-01-10T14:46:50.455] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-01-10T14:46:50.461] [INFO] monitorLogs - tasks created: 875 +[2025-01-10T14:46:50.464] [INFO] monitorLogs - -->FLOW bol spustený ZmRwd93QL4gaezxEbAxWvw71prn2XjlPvGyqJ6BO 2025-01-09 +[2025-01-10T14:46:50.771] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-10T14:46:50.815] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-10T14:46:50.855] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-10T15:58:14.788] [INFO] monitorLogs - MQTT client connected +[2025-01-10T17:20:20.155] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-01-10T17:20:25.500] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 true turn off on startup +[2025-01-10T17:20:25.515] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 true turn off on startup +[2025-01-10T17:20:25.521] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 true turn off on startup +[2025-01-10T17:20:25.944] [INFO] monitorLogs - MQTT client connected +[2025-01-10T17:20:30.533] [INFO] monitorLogs - buildTasks - params undefined +[2025-01-10T17:20:30.534] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-01-10T17:20:30.535] [INFO] monitorLogs - 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 +} +[2025-01-10T17:20:30.539] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-10T17:20:30.540] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-01-11T12:00:00.539Z +[2025-01-10T17:20:30.542] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-01-10T17:20:30.543] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-01-10T17:20:30.543] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-01-10T17:20:30.544] [INFO] monitorLogs - 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 +} +[2025-01-10T17:20:30.547] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-10T17:20:30.547] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-01-11T12:00:00.547Z +[2025-01-10T17:20:30.548] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-01-10T17:20:30.549] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-01-10T17:20:30.550] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-01-10T17:20:30.550] [INFO] monitorLogs - 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 +} +[2025-01-10T17:20:30.552] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-10T17:20:30.553] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-01-11T12:00:00.552Z +[2025-01-10T17:20:30.553] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-01-10T17:20:30.554] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-01-10T17:20:30.560] [INFO] monitorLogs - tasks created: 875 +[2025-01-10T17:20:30.563] [INFO] monitorLogs - -->FLOW bol spustený ZmRwd93QL4gaezxEbAxWvw71prn2XjlPvGyqJ6BO 2025-01-09 +[2025-01-10T17:20:30.870] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-10T17:20:30.911] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-10T17:20:30.954] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-11T03:20:28.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-11 03:20:28 +[2025-01-12T03:20:29.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-12 03:20:29 +[2025-01-13T03:20:30.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-13 03:20:30 +[2025-01-14T03:20:31.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-14 03:20:31 +[2025-01-15T03:20:32.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-15 03:20:32 +[2025-01-16T03:20:33.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-16 03:20:33 +[2025-01-17T03:20:34.015] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-17 03:20:34 +[2025-01-18T03:20:35.013] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-18 03:20:35 +[2025-01-19T03:20:35.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-19 03:20:35 +[2025-01-20T01:32:59.267] [INFO] monitorLogs - MQTT client connected +[2025-01-20T03:20:36.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-20 03:20:36 +[2025-01-21T03:20:37.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-21 03:20:37 +[2025-01-22T03:20:38.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-22 03:20:38 +[2025-01-23T03:20:39.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-23 03:20:39 +[2025-01-24T03:20:40.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-24 03:20:40 +[2025-01-25T03:20:41.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-25 03:20:41 +[2025-01-25T12:44:25.844] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-01-25T12:44:31.191] [INFO] monitorLogs - buildTasks - params undefined +[2025-01-25T12:44:31.195] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-01-25T12:44:31.196] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-01-25T12:44:31.197] [INFO] monitorLogs - 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 +} +[2025-01-25T12:44:31.200] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-25T12:44:31.201] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-01-25T12:00:00.200Z +[2025-01-25T12:44:31.202] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-01-25T12:44:31.204] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-01-25T12:44:31.204] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-01-25T12:44:31.205] [INFO] monitorLogs - 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 +} +[2025-01-25T12:44:31.206] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-25T12:44:31.207] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-01-25T12:00:00.207Z +[2025-01-25T12:44:31.208] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-01-25T12:44:31.209] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-01-25T12:44:31.210] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-01-25T12:44:31.210] [INFO] monitorLogs - 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 +} +[2025-01-25T12:44:31.212] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-25T12:44:31.212] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-01-25T12:00:00.212Z +[2025-01-25T12:44:31.213] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-01-25T12:44:31.214] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-01-25T12:44:31.219] [INFO] monitorLogs - tasks created: 821 +[2025-01-25T12:44:31.221] [INFO] monitorLogs - -->FLOW bol spustený ZmRwd93QL4gaezxEbAxWvw71prn2XjlPvGyqJ6BO 2025-01-21 +[2025-01-25T12:44:31.304] [INFO] monitorLogs - MQTT client connected +[2025-01-25T12:44:31.530] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-25T12:44:31.834] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-25T12:44:32.138] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-26T03:44:32.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-26 03:44:32 +[2025-01-27T03:44:33.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-27 03:44:33 +[2025-01-28T03:44:34.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-28 03:44:34 +[2025-01-29T03:44:35.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-29 03:44:35 +[2025-01-29T18:06:07.494] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-01-29T18:06:12.898] [INFO] monitorLogs - buildTasks - params undefined +[2025-01-29T18:06:12.902] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-01-29T18:06:12.904] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-01-29T18:06:12.904] [INFO] monitorLogs - 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 +} +[2025-01-29T18:06:12.907] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-29T18:06:12.909] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-01-30T12:00:00.908Z +[2025-01-29T18:06:12.910] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-01-29T18:06:12.911] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-01-29T18:06:12.912] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-01-29T18:06:12.912] [INFO] monitorLogs - 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 +} +[2025-01-29T18:06:12.914] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-29T18:06:12.914] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-01-30T12:00:00.914Z +[2025-01-29T18:06:12.915] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-01-29T18:06:12.916] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-01-29T18:06:12.917] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-01-29T18:06:12.918] [INFO] monitorLogs - 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 +} +[2025-01-29T18:06:12.919] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-29T18:06:12.920] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-01-30T12:00:00.919Z +[2025-01-29T18:06:12.920] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-01-29T18:06:12.921] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-01-29T18:06:12.926] [INFO] monitorLogs - tasks created: 821 +[2025-01-29T18:06:12.929] [INFO] monitorLogs - -->FLOW bol spustený ZmRwd93QL4gaezxEbAxWvw71prn2XjlPvGyqJ6BO 2025-01-21 +[2025-01-29T18:06:13.238] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-29T18:06:13.543] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-29T18:06:13.847] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-29T18:06:31.178] [INFO] monitorLogs - MQTT client connected +[2025-01-30T03:06:15.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-30 03:06:15 +[2025-01-31T03:06:16.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-31 03:06:16 +[2025-02-01T03:06:17.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-01 03:06:17 +[2025-02-02T03:06:18.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-02 03:06:18 +[2025-02-03T03:06:19.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-03 03:06:19 +[2025-02-03T06:59:41.880] [INFO] monitorLogs - MQTT client connected +[2025-02-04T03:06:20.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-04 03:06:20 +[2025-02-05T03:06:20.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-05 03:06:20 +[2025-02-06T03:06:21.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-06 03:06:21 +[2025-02-07T03:06:22.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-07 03:06:22 +[2025-02-07T08:42:46.776] [INFO] monitorLogs - MQTT client connected +[2025-02-07T08:44:43.250] [INFO] monitorLogs - MQTT client connected +[2025-02-08T02:40:49.407] [INFO] monitorLogs - MQTT client connected +[2025-02-08T03:06:23.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-08 03:06:23 +[2025-02-09T03:06:24.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-09 03:06:24 +[2025-02-09T13:26:00.158] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-02-09T13:26:05.512] [INFO] monitorLogs - buildTasks - params undefined +[2025-02-09T13:26:05.517] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-02-09T13:26:05.518] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-02-09T13:26:05.519] [INFO] monitorLogs - 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 +} +[2025-02-09T13:26:05.521] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-02-09T13:26:05.523] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-02-10T12:00:00.522Z +[2025-02-09T13:26:05.524] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-02-09T13:26:05.525] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-02-09T13:26:05.526] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-02-09T13:26:05.526] [INFO] monitorLogs - 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 +} +[2025-02-09T13:26:05.528] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-02-09T13:26:05.529] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-02-10T12:00:00.528Z +[2025-02-09T13:26:05.529] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-02-09T13:26:05.530] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-02-09T13:26:05.531] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-02-09T13:26:05.532] [INFO] monitorLogs - 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 +} +[2025-02-09T13:26:05.533] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-02-09T13:26:05.534] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-02-10T12:00:00.533Z +[2025-02-09T13:26:05.534] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-02-09T13:26:05.536] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-02-09T13:26:05.541] [INFO] monitorLogs - tasks created: 821 +[2025-02-09T13:26:05.543] [INFO] monitorLogs - -->FLOW bol spustený ZmRwd93QL4gaezxEbAxWvw71prn2XjlPvGyqJ6BO 2025-01-30 +[2025-02-09T13:26:05.854] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-02-09T13:26:05.955] [INFO] monitorLogs - MQTT client connected +[2025-02-09T13:26:06.157] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-02-09T13:26:06.461] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-02-10T03:26:08.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-10 03:26:08 +[2025-02-10T15:17:31.102] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-02-10T15:17:36.473] [INFO] monitorLogs - buildTasks - params undefined +[2025-02-10T15:17:36.478] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-02-10T15:17:36.479] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-02-10T15:17:36.480] [INFO] monitorLogs - 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 +} +[2025-02-10T15:17:36.483] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-02-10T15:17:36.484] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-02-11T12:00:00.483Z +[2025-02-10T15:17:36.485] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-02-10T15:17:36.486] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-02-10T15:17:36.487] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-02-10T15:17:36.488] [INFO] monitorLogs - 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 +} +[2025-02-10T15:17:36.489] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-02-10T15:17:36.490] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-02-11T12:00:00.490Z +[2025-02-10T15:17:36.491] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-02-10T15:17:36.492] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-02-10T15:17:36.492] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-02-10T15:17:36.493] [INFO] monitorLogs - 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 +} +[2025-02-10T15:17:36.494] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-02-10T15:17:36.495] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-02-11T12:00:00.495Z +[2025-02-10T15:17:36.496] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-02-10T15:17:36.497] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-02-10T15:17:36.502] [INFO] monitorLogs - tasks created: 821 +[2025-02-10T15:17:36.504] [INFO] monitorLogs - -->FLOW bol spustený ZmRwd93QL4gaezxEbAxWvw71prn2XjlPvGyqJ6BO 2025-01-30 +[2025-02-10T15:17:36.611] [INFO] monitorLogs - MQTT client connected +[2025-02-10T15:17:36.813] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-02-10T15:17:37.117] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-02-10T15:17:37.421] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-02-11T03:17:39.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-11 03:17:39 +[2025-02-11T13:34:31.236] [INFO] monitorLogs - MQTT client connected +[2025-02-11T13:39:25.591] [INFO] monitorLogs - MQTT client connected +[2025-02-12T03:17:40.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-12 03:17:40 +[2025-02-12T14:57:23.511] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-02-12T14:57:28.917] [INFO] monitorLogs - buildTasks - params undefined +[2025-02-12T14:57:28.922] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-02-12T14:57:28.923] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-02-12T14:57:28.924] [INFO] monitorLogs - 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 +} +[2025-02-12T14:57:28.927] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-02-12T14:57:28.930] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-02-13T12:00:00.927Z +[2025-02-12T14:57:28.931] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-02-12T14:57:28.933] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-02-12T14:57:28.934] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-02-12T14:57:28.934] [INFO] monitorLogs - 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 +} +[2025-02-12T14:57:28.936] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-02-12T14:57:28.937] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-02-13T12:00:00.936Z +[2025-02-12T14:57:28.937] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-02-12T14:57:28.938] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-02-12T14:57:28.939] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-02-12T14:57:28.939] [INFO] monitorLogs - 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 +} +[2025-02-12T14:57:28.941] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-02-12T14:57:28.941] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-02-13T12:00:00.941Z +[2025-02-12T14:57:28.942] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-02-12T14:57:28.943] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-02-12T14:57:28.948] [INFO] monitorLogs - tasks created: 821 +[2025-02-12T14:57:28.950] [INFO] monitorLogs - -->FLOW bol spustený ZmRwd93QL4gaezxEbAxWvw71prn2XjlPvGyqJ6BO 2025-01-30 +[2025-02-12T14:57:29.076] [INFO] monitorLogs - MQTT client connected +[2025-02-12T14:57:29.259] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-02-12T14:57:29.563] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-02-12T14:57:29.867] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-02-13T03:57:31.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-13 03:57:31 +[2025-02-13T13:17:54.506] [INFO] monitorLogs - MQTT client connected +[2025-02-13T13:19:00.093] [INFO] monitorLogs - MQTT client connected +[2025-02-13T13:20:44.385] [INFO] monitorLogs - MQTT client connected +[2025-02-13T13:22:00.938] [INFO] monitorLogs - MQTT client connected +[2025-02-13T13:22:53.073] [INFO] monitorLogs - MQTT client connected +[2025-02-13T13:29:20.769] [INFO] monitorLogs - MQTT client connected +[2025-02-13T15:23:00.934] [INFO] monitorLogs - MQTT client connected +[2025-02-14T03:57:32.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-14 03:57:32 +[2025-02-15T03:57:32.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-15 03:57:32 +[2025-02-16T03:57:33.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-16 03:57:33 +[2025-02-17T03:57:34.013] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-17 03:57:34 +[2025-02-17T07:02:30.243] [INFO] monitorLogs - MQTT client connected +[2025-02-17T07:03:02.553] [INFO] monitorLogs - MQTT client connected +[2025-02-17T07:03:35.760] [INFO] monitorLogs - MQTT client connected +[2025-02-17T08:02:30.358] [INFO] monitorLogs - MQTT client connected +[2025-02-17T08:04:02.735] [INFO] monitorLogs - MQTT client connected +[2025-02-17T08:04:10.028] [INFO] monitorLogs - MQTT client connected +[2025-02-17T08:56:23.314] [INFO] monitorLogs - MQTT client connected +[2025-02-18T03:57:35.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-18 03:57:35 +[2025-02-18T06:54:10.212] [INFO] monitorLogs - MQTT client connected +[2025-02-19T03:57:36.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-19 03:57:36 +[2025-02-19T14:18:29.718] [INFO] monitorLogs - MQTT client connected +[2025-02-19T15:06:41.226] [INFO] monitorLogs - MQTT client connected +[2025-02-19T15:09:54.653] [INFO] monitorLogs - MQTT client connected +[2025-02-19T15:12:58.852] [INFO] monitorLogs - MQTT client connected +[2025-02-20T03:57:37.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-20 03:57:37 +[2025-02-20T09:20:01.461] [INFO] monitorLogs - MQTT client connected +[2025-02-21T03:57:37.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-21 03:57:37 +[2025-02-22T03:57:38.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-22 03:57:38 +[2025-02-23T03:57:39.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-23 03:57:39 +[2025-02-24T03:57:40.013] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-24 03:57:40 +[2025-02-24T09:09:56.818] [INFO] monitorLogs - MQTT client connected +[2025-02-24T14:00:50.073] [INFO] monitorLogs - MQTT client connected +[2025-02-24T14:01:11.672] [INFO] monitorLogs - MQTT client connected +[2025-02-24T14:02:30.140] [INFO] monitorLogs - MQTT client connected +[2025-02-25T03:57:41.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-25 03:57:41 +[2025-02-25T06:50:05.731] [INFO] monitorLogs - MQTT client connected +[2025-02-25T06:52:16.629] [INFO] monitorLogs - MQTT client connected +[2025-02-25T06:53:55.443] [INFO] monitorLogs - MQTT client connected +[2025-02-25T06:54:37.504] [INFO] monitorLogs - MQTT client connected +[2025-02-25T06:55:14.431] [INFO] monitorLogs - MQTT client connected +[2025-02-25T06:55:36.989] [INFO] monitorLogs - MQTT client connected +[2025-02-25T06:56:32.955] [INFO] monitorLogs - MQTT client connected +[2025-02-25T06:57:37.753] [INFO] monitorLogs - MQTT client connected +[2025-02-25T06:59:11.048] [INFO] monitorLogs - MQTT client connected +[2025-02-25T07:11:00.395] [INFO] monitorLogs - MQTT client connected +[2025-02-25T07:11:25.995] [INFO] monitorLogs - MQTT client connected +[2025-02-25T07:12:14.297] [INFO] monitorLogs - MQTT client connected +[2025-02-25T07:12:44.751] [INFO] monitorLogs - MQTT client connected +[2025-02-25T07:15:57.607] [INFO] monitorLogs - MQTT client connected +[2025-02-25T07:17:19.206] [INFO] monitorLogs - MQTT client connected +[2025-02-25T07:18:42.880] [INFO] monitorLogs - MQTT client connected +[2025-02-25T12:36:48.945] [INFO] monitorLogs - MQTT client connected +[2025-02-25T12:37:25.669] [INFO] monitorLogs - MQTT client connected +[2025-02-25T12:39:22.505] [INFO] monitorLogs - MQTT client connected +[2025-02-25T14:06:10.593] [INFO] monitorLogs - MQTT client connected +[2025-02-25T14:11:23.887] [INFO] monitorLogs - MQTT client connected +[2025-02-25T14:12:44.337] [INFO] monitorLogs - MQTT client connected +[2025-02-25T14:13:08.907] [INFO] monitorLogs - MQTT client connected +[2025-02-25T14:15:15.550] [INFO] monitorLogs - MQTT client connected +[2025-02-25T14:20:50.836] [INFO] monitorLogs - MQTT client connected +[2025-02-26T03:57:42.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-26 03:57:42 +[2025-02-27T03:57:43.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-27 03:57:43 +[2025-02-28T03:57:44.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-28 03:57:44 +[2025-02-28T12:20:45.767] [INFO] monitorLogs - MQTT client connected +[2025-02-28T12:26:53.091] [INFO] monitorLogs - MQTT client connected +[2025-03-01T03:57:44.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-01 03:57:44 +[2025-03-02T03:57:45.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-02 03:57:45 +[2025-03-03T03:57:46.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-03 03:57:46 +[2025-03-03T12:34:15.372] [INFO] monitorLogs - MQTT client connected +[2025-03-04T03:57:47.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-04 03:57:47 +[2025-03-04T07:03:51.190] [INFO] monitorLogs - MQTT client connected +[2025-03-04T07:04:41.509] [INFO] monitorLogs - MQTT client connected +[2025-03-04T07:09:13.555] [INFO] monitorLogs - MQTT client connected +[2025-03-04T07:09:51.906] [INFO] monitorLogs - MQTT client connected +[2025-03-04T07:12:10.931] [INFO] monitorLogs - MQTT client connected +[2025-03-04T07:14:24.856] [INFO] monitorLogs - MQTT client connected +[2025-03-04T07:14:59.142] [INFO] monitorLogs - MQTT client connected +[2025-03-04T07:18:01.282] [INFO] monitorLogs - MQTT client connected +[2025-03-04T07:19:03.949] [INFO] monitorLogs - MQTT client connected +[2025-03-05T03:57:48.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-05 03:57:48 +[2025-03-06T03:57:49.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-06 03:57:49 +[2025-03-07T03:57:50.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-07 03:57:50 +[2025-03-08T03:57:51.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-08 03:57:51 +[2025-03-09T03:57:52.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-09 03:57:52 +[2025-03-10T03:57:52.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-10 03:57:52 +[2025-03-10T06:44:10.356] [INFO] monitorLogs - MQTT client connected +[2025-03-11T03:57:53.013] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-11 03:57:53 +[2025-03-11T08:23:46.639] [INFO] monitorLogs - MQTT client connected +[2025-03-12T03:57:54.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-12 03:57:54 +[2025-03-12T16:12:39.642] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-03-12T16:12:45.015] [INFO] monitorLogs - buildTasks - params undefined +[2025-03-12T16:12:45.020] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-03-12T16:12:45.021] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-03-12T16:12:45.022] [INFO] monitorLogs - 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 +} +[2025-03-12T16:12:45.025] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-03-12T16:12:45.026] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-03-13T12:00:00.025Z +[2025-03-12T16:12:45.027] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-03-12T16:12:45.029] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-03-12T16:12:45.029] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-03-12T16:12:45.030] [INFO] monitorLogs - 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 +} +[2025-03-12T16:12:45.031] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-03-12T16:12:45.032] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-03-13T12:00:00.032Z +[2025-03-12T16:12:45.033] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-03-12T16:12:45.034] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-03-12T16:12:45.035] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-03-12T16:12:45.035] [INFO] monitorLogs - 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 +} +[2025-03-12T16:12:45.037] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-03-12T16:12:45.037] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-03-13T12:00:00.037Z +[2025-03-12T16:12:45.038] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-03-12T16:12:45.039] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-03-12T16:12:45.044] [INFO] monitorLogs - tasks created: 821 +[2025-03-12T16:12:45.046] [INFO] monitorLogs - -->FLOW bol spustený ZmRwd93QL4gaezxEbAxWvw71prn2XjlPvGyqJ6BO 2025-01-30 +[2025-03-12T16:12:45.132] [INFO] monitorLogs - MQTT client connected +[2025-03-12T16:12:45.355] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-03-12T16:12:45.659] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-03-12T16:12:45.963] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-03-13T03:12:46.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-13 03:12:46 +[2025-03-13T08:12:57.539] [INFO] monitorLogs - MQTT client connected +[2025-03-13T09:47:57.620] [INFO] monitorLogs - MQTT client connected +[2025-03-13T10:13:32.626] [INFO] monitorLogs - MQTT client connected +[2025-03-14T03:12:47.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-14 03:12:47 +[2025-03-15T03:12:48.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-15 03:12:48 +[2025-03-16T03:12:49.016] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-16 03:12:49 +[2025-03-17T03:12:50.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-17 03:12:50 +[2025-03-17T07:07:09.809] [INFO] monitorLogs - MQTT client connected +[2025-03-18T03:12:51.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-18 03:12:51 +[2025-03-19T03:12:52.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-19 03:12:52 +[2025-03-20T03:12:53.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-20 03:12:53 +[2025-03-21T03:12:53.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-21 03:12:53 +[2025-03-22T03:12:54.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-22 03:12:54 +[2025-03-23T03:12:55.013] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-23 03:12:55 +[2025-03-24T03:12:56.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-24 03:12:56 +[2025-03-24T07:47:36.350] [INFO] monitorLogs - MQTT client connected +[2025-03-24T08:09:28.778] [INFO] monitorLogs - MQTT client connected +[2025-03-24T08:39:38.617] [INFO] monitorLogs - MQTT client connected +[2025-03-24T09:38:49.256] [INFO] monitorLogs - MQTT client connected +[2025-03-24T10:08:00.271] [INFO] monitorLogs - MQTT client connected +[2025-03-24T12:35:46.426] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-03-24T12:35:51.774] [INFO] monitorLogs - buildTasks - params undefined +[2025-03-24T12:35:51.778] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-03-24T12:35:51.780] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-03-24T12:35:51.780] [INFO] monitorLogs - 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 +} +[2025-03-24T12:35:51.783] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-03-24T12:35:51.785] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-03-24T12:00:00.784Z +[2025-03-24T12:35:51.786] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-03-24T12:35:51.787] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-03-24T12:35:51.788] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-03-24T12:35:51.788] [INFO] monitorLogs - 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 +} +[2025-03-24T12:35:51.790] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-03-24T12:35:51.790] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-03-24T12:00:00.790Z +[2025-03-24T12:35:51.791] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-03-24T12:35:51.792] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-03-24T12:35:51.793] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-03-24T12:35:51.793] [INFO] monitorLogs - 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 +} +[2025-03-24T12:35:51.795] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-03-24T12:35:51.795] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-03-24T12:00:00.795Z +[2025-03-24T12:35:51.796] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-03-24T12:35:51.797] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-03-24T12:35:51.802] [INFO] monitorLogs - tasks created: 821 +[2025-03-24T12:35:51.805] [INFO] monitorLogs - -->FLOW bol spustený ZmRwd93QL4gaezxEbAxWvw71prn2XjlPvGyqJ6BO 2025-01-30 +[2025-03-24T12:35:51.890] [INFO] monitorLogs - MQTT client connected +[2025-03-24T12:35:52.113] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-03-24T12:35:52.419] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-03-24T12:35:52.723] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-03-25T03:35:53.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-25 03:35:53 +[2025-03-26T03:35:54.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-26 03:35:54 +[2025-03-26T09:05:35.658] [INFO] monitorLogs - MQTT client connected +[2025-03-27T03:35:55.021] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-27 03:35:55 +[2025-03-28T03:35:56.018] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-28 03:35:56 +[2025-03-28T07:34:56.147] [INFO] monitorLogs - MQTT client connected +[2025-03-28T07:38:01.507] [INFO] monitorLogs - MQTT client connected +[2025-03-28T09:16:18.107] [INFO] monitorLogs - MQTT client connected +[2025-03-29T03:35:57.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-29 03:35:57 +[2025-03-30T03:35:58.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-30 03:35:58 +[2025-03-31T03:35:58.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-31 03:35:58 +[2025-03-31T06:50:25.878] [INFO] monitorLogs - MQTT client connected +[2025-04-01T03:35:59.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-01 03:35:59 +[2025-04-01T07:40:41.507] [INFO] monitorLogs - MQTT client connected +[2025-04-01T07:54:32.250] [INFO] monitorLogs - MQTT client connected +[2025-04-01T07:55:30.675] [INFO] monitorLogs - MQTT client connected +[2025-04-01T07:55:55.467] [INFO] monitorLogs - MQTT client connected +[2025-04-01T07:56:58.913] [INFO] monitorLogs - MQTT client connected +[2025-04-02T02:17:34.306] [INFO] monitorLogs - MQTT client connected +[2025-04-02T03:24:07.818] [INFO] monitorLogs - MQTT client connected +[2025-04-02T03:36:00.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-02 03:36:00 +[2025-04-03T03:36:01.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-03 03:36:01 +[2025-04-04T03:36:02.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-04 03:36:02 +[2025-04-04T09:46:33.508] [INFO] monitorLogs - MQTT client connected +[2025-04-05T03:36:03.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-05 03:36:03 +[2025-04-06T03:36:04.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-06 03:36:04 +[2025-04-07T03:36:05.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-07 03:36:05 +[2025-04-07T08:32:43.527] [INFO] monitorLogs - MQTT client connected +[2025-04-07T08:33:09.916] [INFO] monitorLogs - MQTT client connected +[2025-04-07T08:37:46.033] [INFO] monitorLogs - MQTT client connected +[2025-04-07T08:41:54.107] [INFO] monitorLogs - MQTT client connected +[2025-04-07T08:49:07.530] [INFO] monitorLogs - MQTT client connected +[2025-04-08T03:36:06.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-08 03:36:06 +[2025-04-09T03:36:07.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-09 03:36:07 +[2025-04-10T03:36:07.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-10 03:36:07 +[2025-04-10T06:47:02.188] [INFO] monitorLogs - MQTT client connected +[2025-04-10T07:06:34.287] [INFO] monitorLogs - MQTT client connected +[2025-04-11T00:29:19.941] [INFO] monitorLogs - MQTT client connected +[2025-04-11T03:36:08.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-11 03:36:08 +[2025-04-12T00:54:07.928] [INFO] monitorLogs - MQTT client connected +[2025-04-12T03:36:09.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-12 03:36:09 +[2025-04-13T03:36:10.015] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-13 03:36:10 +[2025-04-14T03:36:11.013] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-14 03:36:11 +[2025-04-14T16:19:23.523] [INFO] monitorLogs - MQTT client connected +[2025-04-15T03:36:12.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-15 03:36:12 +[2025-04-15T11:19:24.121] [INFO] monitorLogs - MQTT client connected +[2025-04-16T03:36:13.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-16 03:36:13 +[2025-04-17T03:36:14.016] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-17 03:36:14 +[2025-04-18T03:36:15.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-18 03:36:15 +[2025-04-19T03:36:16.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-19 03:36:16 +[2025-04-20T03:36:17.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-20 03:36:17 +[2025-04-21T03:36:17.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-21 03:36:17 +[2025-04-22T03:36:18.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-22 03:36:18 +[2025-04-22T13:38:09.715] [INFO] monitorLogs - MQTT client connected +[2025-04-23T03:36:19.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-23 03:36:19 +[2025-04-23T06:53:54.666] [INFO] monitorLogs - MQTT client connected +[2025-04-24T03:36:20.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-24 03:36:20 +[2025-04-24T17:05:12.775] [INFO] monitorLogs - MQTT client connected +[2025-04-24T17:05:33.877] [INFO] monitorLogs - MQTT client connected +[2025-04-24T17:07:01.178] [INFO] monitorLogs - MQTT client connected +[2025-04-24T18:02:17.011] [INFO] monitorLogs - MQTT client connected +[2025-04-24T18:04:11.278] [INFO] monitorLogs - MQTT client connected +[2025-04-25T03:36:21.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-25 03:36:21 +[2025-04-25T10:31:50.122] [INFO] monitorLogs - MQTT client connected +[2025-04-25T12:14:37.281] [INFO] monitorLogs - MQTT client connected +[2025-04-26T03:36:22.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-26 03:36:22 +[2025-04-27T03:36:23.015] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-27 03:36:23 +[2025-04-28T03:36:24.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-28 03:36:24 +[2025-04-29T03:36:25.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-29 03:36:25 +[2025-04-29T06:56:21.171] [INFO] monitorLogs - MQTT client connected +[2025-04-29T07:48:54.509] [INFO] monitorLogs - MQTT client connected +[2025-04-29T07:50:54.780] [INFO] monitorLogs - MQTT client connected +[2025-04-29T07:54:40.726] [INFO] monitorLogs - MQTT client connected +[2025-04-29T09:12:15.604] [INFO] monitorLogs - MQTT client connected +[2025-04-30T03:36:26.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-30 03:36:26 +[2025-04-30T17:02:59.090] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-04-30T17:03:04.470] [INFO] monitorLogs - buildTasks - params undefined +[2025-04-30T17:03:04.475] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-04-30T17:03:04.476] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-04-30T17:03:04.477] [INFO] monitorLogs - 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 +} +[2025-04-30T17:03:04.480] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-04-30T17:03:04.481] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-05-01T11:00:00.480Z +[2025-04-30T17:03:04.482] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-04-30T17:03:04.483] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-04-30T17:03:04.484] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-04-30T17:03:04.485] [INFO] monitorLogs - 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 +} +[2025-04-30T17:03:04.486] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-04-30T17:03:04.487] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-05-01T11:00:00.487Z +[2025-04-30T17:03:04.488] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-04-30T17:03:04.489] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-04-30T17:03:04.490] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-04-30T17:03:04.490] [INFO] monitorLogs - 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 +} +[2025-04-30T17:03:04.491] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-04-30T17:03:04.492] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-05-01T11:00:00.492Z +[2025-04-30T17:03:04.493] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-04-30T17:03:04.494] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-04-30T17:03:04.514] [INFO] monitorLogs - tasks created: 767 +[2025-04-30T17:03:04.517] [INFO] monitorLogs - -->FLOW bol spustený ZmRwd93QL4gaezxEbAxWvw71prn2XjlPvGyqJ6BO 2025-04-24 +[2025-04-30T17:03:04.621] [INFO] monitorLogs - MQTT client connected +[2025-04-30T17:03:04.824] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-04-30T17:03:05.129] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-04-30T17:03:05.433] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-05-01T03:03:07.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-01 03:03:07 +[2025-05-02T03:03:08.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-02 03:03:08 +[2025-05-03T03:03:09.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-03 03:03:09 +[2025-05-04T03:03:10.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-04 03:03:10 +[2025-05-05T03:03:11.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-05 03:03:11 +[2025-05-05T08:04:51.517] [INFO] monitorLogs - MQTT client connected +[2025-05-05T08:35:05.694] [INFO] monitorLogs - MQTT client connected +[2025-05-05T08:59:32.884] [INFO] monitorLogs - MQTT client connected +[2025-05-06T03:03:12.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-06 03:03:12 +[2025-05-06T08:22:46.446] [INFO] monitorLogs - MQTT client connected +[2025-05-07T03:03:13.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-07 03:03:13 +[2025-05-07T19:32:53.490] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-05-07T19:32:58.855] [INFO] monitorLogs - buildTasks - params undefined +[2025-05-07T19:32:58.860] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-05-07T19:32:58.861] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-05-07T19:32:58.862] [INFO] monitorLogs - 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 +} +[2025-05-07T19:32:58.865] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-05-07T19:32:58.866] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-05-08T11:00:00.865Z +[2025-05-07T19:32:58.867] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-05-07T19:32:58.868] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-05-07T19:32:58.869] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-05-07T19:32:58.870] [INFO] monitorLogs - 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 +} +[2025-05-07T19:32:58.871] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-05-07T19:32:58.872] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-05-08T11:00:00.872Z +[2025-05-07T19:32:58.873] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-05-07T19:32:58.874] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-05-07T19:32:58.874] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-05-07T19:32:58.875] [INFO] monitorLogs - 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 +} +[2025-05-07T19:32:58.876] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-05-07T19:32:58.877] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-05-08T11:00:00.877Z +[2025-05-07T19:32:58.878] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-05-07T19:32:58.879] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-05-07T19:32:58.883] [INFO] monitorLogs - tasks created: 767 +[2025-05-07T19:32:58.886] [INFO] monitorLogs - -->FLOW bol spustený ZmRwd93QL4gaezxEbAxWvw71prn2XjlPvGyqJ6BO 2025-04-24 +[2025-05-07T19:32:59.059] [INFO] monitorLogs - MQTT client connected +[2025-05-07T19:32:59.194] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-05-07T19:32:59.498] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-05-07T19:32:59.801] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-05-08T03:33:01.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-08 03:33:01 +[2025-05-09T03:33:02.015] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-09 03:33:02 +[2025-05-10T03:33:03.024] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-10 03:33:03 +[2025-05-11T03:33:04.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-11 03:33:04 +[2025-05-12T03:33:05.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-12 03:33:05 +[2025-05-12T04:10:11.256] [INFO] monitorLogs - MQTT client connected +[2025-05-12T09:50:57.872] [INFO] monitorLogs - MQTT client connected +[2025-05-12T10:53:34.446] [INFO] monitorLogs - MQTT client connected +[2025-05-12T13:41:17.406] [INFO] monitorLogs - MQTT client connected +[2025-05-13T03:33:06.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-13 03:33:06 +[2025-05-14T03:33:07.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-14 03:33:07 +[2025-05-14T07:44:39.013] [INFO] monitorLogs - MQTT client connected +[2025-05-14T08:31:39.154] [INFO] monitorLogs - MQTT client connected +[2025-05-14T09:10:58.970] [INFO] monitorLogs - MQTT client connected +[2025-05-14T09:41:52.253] [INFO] monitorLogs - MQTT client connected +[2025-05-14T10:08:09.786] [INFO] monitorLogs - MQTT client connected +[2025-05-14T10:45:22.544] [INFO] monitorLogs - MQTT client connected +[2025-05-14T10:47:56.281] [INFO] monitorLogs - MQTT client connected +[2025-05-14T10:49:42.152] [INFO] monitorLogs - MQTT client connected +[2025-05-14T10:50:35.638] [INFO] monitorLogs - MQTT client connected +[2025-05-14T10:51:32.964] [INFO] monitorLogs - MQTT client connected +[2025-05-14T10:52:45.970] [INFO] monitorLogs - MQTT client connected +[2025-05-14T10:53:30.171] [INFO] monitorLogs - MQTT client connected +[2025-05-14T10:54:32.810] [INFO] monitorLogs - MQTT client connected +[2025-05-15T03:33:08.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-15 03:33:08 +[2025-05-16T03:33:09.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-16 03:33:09 +[2025-05-17T03:33:09.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-17 03:33:09 +[2025-05-18T03:33:10.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-18 03:33:10 +[2025-05-19T03:33:11.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-19 03:33:11 +[2025-05-20T03:33:12.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-20 03:33:12 +[2025-05-20T08:28:11.039] [INFO] monitorLogs - MQTT client connected +[2025-05-20T08:31:25.109] [INFO] monitorLogs - MQTT client connected +[2025-05-21T03:33:13.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-21 03:33:13 +[2025-05-22T03:33:14.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-22 03:33:14 +[2025-05-23T03:33:15.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-23 03:33:15 +[2025-05-23T10:56:43.416] [INFO] monitorLogs - MQTT client connected +[2025-05-24T03:33:16.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-24 03:33:16 +[2025-05-25T03:33:17.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-25 03:33:17 +[2025-05-26T03:33:18.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-26 03:33:18 +[2025-05-26T07:25:59.537] [INFO] monitorLogs - MQTT client connected +[2025-05-26T08:40:31.414] [INFO] monitorLogs - MQTT client connected +[2025-05-26T14:13:20.335] [INFO] monitorLogs - Thermometer is not responding Error: Command failed: owread -C 28.7F6E9C0E0000/temperature +ServerRead: Data error on 28.7F6E9C0E0000/temperature + + at ChildProcess.exithandler (child_process.js:383:12) + at ChildProcess.emit (events.js:400:28) + at maybeClose (internal/child_process.js:1058:16) + at Socket. (internal/child_process.js:443:11) + at Socket.emit (events.js:400:28) + at Pipe. (net.js:686:12) { + killed: false, + code: 1, + signal: null, + cmd: 'owread -C 28.7F6E9C0E0000/temperature' +} +[2025-05-27T03:33:19.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-27 03:33:19 +[2025-05-27T12:47:14.619] [INFO] monitorLogs - MQTT client connected +[2025-05-27T12:48:37.547] [INFO] monitorLogs - MQTT client connected +[2025-05-27T12:50:15.778] [INFO] monitorLogs - MQTT client connected +[2025-05-28T03:33:20.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-28 03:33:20 +[2025-05-28T10:12:22.531] [INFO] monitorLogs - MQTT client connected +[2025-05-29T03:33:21.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-29 03:33:21 +[2025-05-29T13:04:53.679] [INFO] monitorLogs - MQTT client connected +[2025-05-30T03:33:21.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-30 03:33:21 +[2025-05-31T03:33:22.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-31 03:33:22 +[2025-05-31T13:48:05.136] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-05-31T13:48:10.508] [INFO] monitorLogs - buildTasks - params undefined +[2025-05-31T13:48:10.513] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-05-31T13:48:10.514] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-05-31T13:48:10.515] [INFO] monitorLogs - 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 +} +[2025-05-31T13:48:10.518] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-05-31T13:48:10.519] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-06-01T11:00:00.519Z +[2025-05-31T13:48:10.521] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-05-31T13:48:10.522] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-05-31T13:48:10.522] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-05-31T13:48:10.523] [INFO] monitorLogs - 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 +} +[2025-05-31T13:48:10.525] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-05-31T13:48:10.525] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-06-01T11:00:00.525Z +[2025-05-31T13:48:10.526] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-05-31T13:48:10.527] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-05-31T13:48:10.528] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-05-31T13:48:10.528] [INFO] monitorLogs - 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 +} +[2025-05-31T13:48:10.530] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-05-31T13:48:10.530] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-06-01T11:00:00.530Z +[2025-05-31T13:48:10.531] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-05-31T13:48:10.532] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-05-31T13:48:10.537] [INFO] monitorLogs - tasks created: 767 +[2025-05-31T13:48:10.557] [INFO] monitorLogs - -->FLOW bol spustený ZmRwd93QL4gaezxEbAxWvw71prn2XjlPvGyqJ6BO 2025-04-24 +[2025-05-31T13:48:15.547] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-01T03:48:13.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-01 03:48:13 +[2025-06-02T03:48:14.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-02 03:48:14 +[2025-06-03T07:51:28.645] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-06-03T07:51:34.062] [INFO] monitorLogs - buildTasks - params undefined +[2025-06-03T07:51:34.067] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-06-03T07:51:34.068] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-06-03T07:51:34.069] [INFO] monitorLogs - 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 +} +[2025-06-03T07:51:34.071] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-06-03T07:51:34.073] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-06-03T11:00:00.072Z +[2025-06-03T07:51:34.074] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-06-03T07:51:34.075] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-06-03T07:51:34.076] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-06-03T07:51:34.076] [INFO] monitorLogs - 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 +} +[2025-06-03T07:51:34.078] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-06-03T07:51:34.079] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-06-03T11:00:00.078Z +[2025-06-03T07:51:34.079] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-06-03T07:51:34.080] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-06-03T07:51:34.081] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-06-03T07:51:34.082] [INFO] monitorLogs - 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 +} +[2025-06-03T07:51:34.083] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-06-03T07:51:34.084] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-06-03T11:00:00.084Z +[2025-06-03T07:51:34.085] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-06-03T07:51:34.085] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-06-03T07:51:34.108] [INFO] monitorLogs - tasks created: 767 +[2025-06-03T07:51:34.110] [INFO] monitorLogs - -->FLOW bol spustený ZmRwd93QL4gaezxEbAxWvw71prn2XjlPvGyqJ6BO 2025-04-24 +[2025-06-03T07:51:39.118] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-03T07:51:39.422] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-03T07:51:39.726] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-04T03:51:38.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-04 03:51:38 +[2025-06-05T03:51:39.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-05 03:51:39 +[2025-06-06T03:51:40.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-06 03:51:40 +[2025-06-06T15:46:01.529] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-06-06T15:46:06.944] [INFO] monitorLogs - buildTasks - params undefined +[2025-06-06T15:46:06.948] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-06-06T15:46:06.949] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-06-06T15:46:06.950] [INFO] monitorLogs - 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 +} +[2025-06-06T15:46:06.953] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-06-06T15:46:06.954] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-06-07T11:00:00.953Z +[2025-06-06T15:46:06.955] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-06-06T15:46:06.956] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-06-06T15:46:06.957] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-06-06T15:46:06.958] [INFO] monitorLogs - 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 +} +[2025-06-06T15:46:06.959] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-06-06T15:46:06.960] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-06-07T11:00:00.960Z +[2025-06-06T15:46:06.961] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-06-06T15:46:06.962] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-06-06T15:46:06.963] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-06-06T15:46:06.963] [INFO] monitorLogs - 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 +} +[2025-06-06T15:46:06.965] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-06-06T15:46:06.965] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-06-07T11:00:00.965Z +[2025-06-06T15:46:06.966] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-06-06T15:46:06.967] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-06-06T15:46:06.971] [INFO] monitorLogs - tasks created: 767 +[2025-06-06T15:46:06.974] [INFO] monitorLogs - -->FLOW bol spustený ZmRwd93QL4gaezxEbAxWvw71prn2XjlPvGyqJ6BO 2025-04-24 +[2025-06-06T15:46:11.990] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-06T15:46:12.293] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-06T15:46:12.597] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-06T16:05:32.068] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-06-06T16:05:37.423] [INFO] monitorLogs - buildTasks - params undefined +[2025-06-06T16:05:37.428] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-06-06T16:05:37.429] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-06-06T16:05:37.429] [INFO] monitorLogs - 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 +} +[2025-06-06T16:05:37.432] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-06-06T16:05:37.434] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-06-07T11:00:00.433Z +[2025-06-06T16:05:37.435] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-06-06T16:05:37.436] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-06-06T16:05:37.437] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-06-06T16:05:37.437] [INFO] monitorLogs - 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 +} +[2025-06-06T16:05:37.439] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-06-06T16:05:37.439] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-06-07T11:00:00.439Z +[2025-06-06T16:05:37.440] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-06-06T16:05:37.441] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-06-06T16:05:37.441] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-06-06T16:05:37.442] [INFO] monitorLogs - 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 +} +[2025-06-06T16:05:37.443] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-06-06T16:05:37.444] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-06-07T11:00:00.444Z +[2025-06-06T16:05:37.445] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-06-06T16:05:37.446] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-06-06T16:05:37.468] [INFO] monitorLogs - tasks created: 767 +[2025-06-06T16:05:37.471] [INFO] monitorLogs - -->FLOW bol spustený ZmRwd93QL4gaezxEbAxWvw71prn2XjlPvGyqJ6BO 2025-04-24 +[2025-06-06T16:05:42.480] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-06T16:44:39.415] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-06-06T16:44:44.766] [INFO] monitorLogs - buildTasks - params undefined +[2025-06-06T16:44:44.771] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-06-06T16:44:44.772] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-06-06T16:44:44.772] [INFO] monitorLogs - 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 +} +[2025-06-06T16:44:44.775] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-06-06T16:44:44.776] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-06-07T11:00:00.776Z +[2025-06-06T16:44:44.778] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-06-06T16:44:44.779] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-06-06T16:44:44.779] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-06-06T16:44:44.780] [INFO] monitorLogs - 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 +} +[2025-06-06T16:44:44.782] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-06-06T16:44:44.782] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-06-07T11:00:00.782Z +[2025-06-06T16:44:44.783] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-06-06T16:44:44.784] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-06-06T16:44:44.785] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-06-06T16:44:44.785] [INFO] monitorLogs - 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 +} +[2025-06-06T16:44:44.787] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-06-06T16:44:44.787] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-06-07T11:00:00.787Z +[2025-06-06T16:44:44.788] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-06-06T16:44:44.789] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-06-06T16:44:44.794] [INFO] monitorLogs - tasks created: 767 +[2025-06-06T16:44:44.815] [INFO] monitorLogs - -->FLOW bol spustený ZmRwd93QL4gaezxEbAxWvw71prn2XjlPvGyqJ6BO 2025-04-24 +[2025-06-06T16:44:49.805] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-07T03:44:47.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-07 03:44:47 +[2025-06-07T08:34:04.335] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-06-07T08:34:09.702] [INFO] monitorLogs - buildTasks - params undefined +[2025-06-07T08:34:09.706] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-06-07T08:34:09.708] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-06-07T08:34:09.708] [INFO] monitorLogs - 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 +} +[2025-06-07T08:34:09.711] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-06-07T08:34:09.712] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-06-07T11:00:00.711Z +[2025-06-07T08:34:09.714] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-06-07T08:34:09.715] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-06-07T08:34:09.715] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-06-07T08:34:09.716] [INFO] monitorLogs - 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 +} +[2025-06-07T08:34:09.718] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-06-07T08:34:09.718] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-06-07T11:00:00.718Z +[2025-06-07T08:34:09.719] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-06-07T08:34:09.720] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-06-07T08:34:09.721] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-06-07T08:34:09.721] [INFO] monitorLogs - 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 +} +[2025-06-07T08:34:09.723] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-06-07T08:34:09.723] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-06-07T11:00:00.723Z +[2025-06-07T08:34:09.724] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-06-07T08:34:09.725] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-06-07T08:34:09.730] [INFO] monitorLogs - tasks created: 767 +[2025-06-07T08:34:09.732] [INFO] monitorLogs - -->FLOW bol spustený ZmRwd93QL4gaezxEbAxWvw71prn2XjlPvGyqJ6BO 2025-04-24 +[2025-06-07T08:34:14.799] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-07T08:36:47.122] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-06-07T08:36:52.483] [INFO] monitorLogs - buildTasks - params undefined +[2025-06-07T08:36:52.487] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-06-07T08:36:52.488] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-06-07T08:36:52.489] [INFO] monitorLogs - 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 +} +[2025-06-07T08:36:52.492] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-06-07T08:36:52.493] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-06-07T11:00:00.492Z +[2025-06-07T08:36:52.494] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-06-07T08:36:52.495] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-06-07T08:36:52.496] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-06-07T08:36:52.497] [INFO] monitorLogs - 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 +} +[2025-06-07T08:36:52.498] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-06-07T08:36:52.499] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-06-07T11:00:00.499Z +[2025-06-07T08:36:52.500] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-06-07T08:36:52.501] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-06-07T08:36:52.502] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-06-07T08:36:52.502] [INFO] monitorLogs - 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 +} +[2025-06-07T08:36:52.503] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-06-07T08:36:52.504] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-06-07T11:00:00.504Z +[2025-06-07T08:36:52.505] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-06-07T08:36:52.506] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-06-07T08:36:52.511] [INFO] monitorLogs - tasks created: 767 +[2025-06-07T08:36:52.513] [INFO] monitorLogs - -->FLOW bol spustený ZmRwd93QL4gaezxEbAxWvw71prn2XjlPvGyqJ6BO 2025-04-24 +[2025-06-07T08:36:57.521] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-08T03:36:54.024] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-08 03:36:54 +[2025-06-09T03:36:55.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-09 03:36:55 +[2025-06-10T03:36:56.013] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-10 03:36:56 +[2025-06-11T03:36:57.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-11 03:36:57 +[2025-06-12T03:36:58.014] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-12 03:36:58 +[2025-06-13T03:36:59.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-13 03:36:59 +[2025-06-13T15:31:08.145] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-06-13T15:31:13.504] [INFO] monitorLogs - buildTasks - params undefined +[2025-06-13T15:31:13.508] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-06-13T15:31:13.509] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-06-13T15:31:13.510] [INFO] monitorLogs - 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 +} +[2025-06-13T15:31:13.513] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-06-13T15:31:13.514] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-06-14T11:00:00.513Z +[2025-06-13T15:31:13.515] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-06-13T15:31:13.516] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-06-13T15:31:13.517] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-06-13T15:31:13.518] [INFO] monitorLogs - 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 +} +[2025-06-13T15:31:13.519] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-06-13T15:31:13.520] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-06-14T11:00:00.520Z +[2025-06-13T15:31:13.521] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-06-13T15:31:13.522] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-06-13T15:31:13.522] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-06-13T15:31:13.523] [INFO] monitorLogs - 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 +} +[2025-06-13T15:31:13.524] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-06-13T15:31:13.525] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-06-14T11:00:00.525Z +[2025-06-13T15:31:13.526] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-06-13T15:31:13.526] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-06-13T15:31:13.548] [INFO] monitorLogs - tasks created: 767 +[2025-06-13T15:31:13.550] [INFO] monitorLogs - -->FLOW bol spustený ZmRwd93QL4gaezxEbAxWvw71prn2XjlPvGyqJ6BO 2025-04-24 +[2025-06-13T15:31:18.559] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-14T03:31:16.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-14 03:31:16 +[2025-06-15T03:31:17.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-15 03:31:17 +[2025-06-16T03:31:18.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-16 03:31:18 +[2025-06-16T12:16:52.112] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-06-16T12:16:57.476] [INFO] monitorLogs - buildTasks - params undefined +[2025-06-16T12:16:57.481] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-06-16T12:16:57.482] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-06-16T12:16:57.482] [INFO] monitorLogs - 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 +} +[2025-06-16T12:16:57.485] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-06-16T12:16:57.486] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-06-16T11:00:00.486Z +[2025-06-16T12:16:57.488] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-06-16T12:16:57.489] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-06-16T12:16:57.490] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-06-16T12:16:57.490] [INFO] monitorLogs - 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 +} +[2025-06-16T12:16:57.492] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-06-16T12:16:57.492] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-06-16T11:00:00.492Z +[2025-06-16T12:16:57.493] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-06-16T12:16:57.494] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-06-16T12:16:57.495] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-06-16T12:16:57.495] [INFO] monitorLogs - 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 +} +[2025-06-16T12:16:57.497] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-06-16T12:16:57.497] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-06-16T11:00:00.497Z +[2025-06-16T12:16:57.498] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-06-16T12:16:57.499] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-06-16T12:16:57.504] [INFO] monitorLogs - tasks created: 767 +[2025-06-16T12:16:57.523] [INFO] monitorLogs - -->FLOW bol spustený ZmRwd93QL4gaezxEbAxWvw71prn2XjlPvGyqJ6BO 2025-04-24 +[2025-06-16T12:17:02.531] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-17T03:17:00.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-17 03:17:00 +[2025-06-18T03:17:01.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-18 03:17:01 +[2025-06-19T03:17:02.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-19 03:17:02 +[2025-06-20T03:17:03.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-20 03:17:03 +[2025-06-21T03:17:04.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-21 03:17:04 +[2025-06-22T03:17:05.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-22 03:17:05 +[2025-06-23T03:17:06.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-23 03:17:06 +[2025-06-24T03:17:07.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-24 03:17:07 +[2025-06-24T16:02:07.764] [INFO] monitorLogs - Thermometer is not responding Error: Command failed: owread -C 28.7F6E9C0E0000/temperature +ServerRead: Data error on 28.7F6E9C0E0000/temperature + + at ChildProcess.exithandler (child_process.js:383:12) + at ChildProcess.emit (events.js:400:28) + at maybeClose (internal/child_process.js:1058:16) + at Socket. (internal/child_process.js:443:11) + at Socket.emit (events.js:400:28) + at Pipe. (net.js:686:12) { + killed: false, + code: 1, + signal: null, + cmd: 'owread -C 28.7F6E9C0E0000/temperature' +} +[2025-06-25T03:17:08.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-25 03:17:08 +[2025-06-26T03:17:09.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-26 03:17:09 +[2025-06-27T03:17:10.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-27 03:17:10 +[2025-06-28T03:17:11.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-28 03:17:11 +[2025-06-29T03:17:12.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-29 03:17:12 +[2025-06-30T03:17:13.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-30 03:17:13 +[2025-07-01T03:17:14.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-01 03:17:14 +[2025-07-02T03:17:15.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-02 03:17:15 +[2025-07-03T03:17:16.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-03 03:17:16 +[2025-07-04T03:17:17.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-04 03:17:17 +[2025-07-05T03:17:18.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-05 03:17:18 +[2025-07-06T03:17:19.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-06 03:17:19 +[2025-07-07T03:17:20.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-07 03:17:20 +[2025-07-07T13:49:06.085] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-07-07T13:49:11.442] [INFO] monitorLogs - buildTasks - params undefined +[2025-07-07T13:49:11.446] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-07-07T13:49:11.447] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-07-07T13:49:11.448] [INFO] monitorLogs - 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 +} +[2025-07-07T13:49:11.451] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-07-07T13:49:11.452] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-07-08T11:00:00.451Z +[2025-07-07T13:49:11.453] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-07-07T13:49:11.454] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-07-07T13:49:11.455] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-07-07T13:49:11.456] [INFO] monitorLogs - 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 +} +[2025-07-07T13:49:11.457] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-07-07T13:49:11.458] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-07-08T11:00:00.458Z +[2025-07-07T13:49:11.459] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-07-07T13:49:11.460] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-07-07T13:49:11.460] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-07-07T13:49:11.461] [INFO] monitorLogs - 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 +} +[2025-07-07T13:49:11.462] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-07-07T13:49:11.463] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-07-08T11:00:00.463Z +[2025-07-07T13:49:11.464] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-07-07T13:49:11.465] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-07-07T13:49:11.487] [INFO] monitorLogs - tasks created: 767 +[2025-07-07T13:49:11.489] [INFO] monitorLogs - -->FLOW bol spustený ZmRwd93QL4gaezxEbAxWvw71prn2XjlPvGyqJ6BO 2025-07-08 +[2025-07-07T13:49:16.496] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-08T03:49:14.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-08 03:49:14 +[2025-07-09T03:49:15.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-09 03:49:15 +[2025-07-10T02:24:18.670] [INFO] monitorLogs - MQTT client error Error: connect ECONNREFUSED 192.168.252.1:1883 + at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1159:16) { + errno: -111, + code: 'ECONNREFUSED', + syscall: 'connect', + address: '192.168.252.1', + port: 1883 +} +[2025-07-10T03:49:16.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-10 03:49:16 +[2025-07-10T13:18:07.806] [INFO] monitorLogs - turnLine on - (line, SETTINGS.maintenance_mode) 0 true command received from platform +[2025-07-10T13:27:28.983] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false command received from platform +[2025-07-10T13:33:06.721] [INFO] monitorLogs - turnLine on - (line, SETTINGS.maintenance_mode) 0 true command received from platform +[2025-07-10T13:39:16.107] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false command received from platform +[2025-07-10T13:40:09.968] [INFO] monitorLogs - turnLine on - (line, SETTINGS.maintenance_mode) 0 true command received from platform +[2025-07-10T13:41:13.648] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false command received from platform +[2025-07-11T03:49:17.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-11 03:49:17 +[2025-07-12T03:49:18.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-12 03:49:18 +[2025-07-13T03:49:19.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-13 03:49:19 +[2025-07-14T03:49:20.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-14 03:49:20 +[2025-07-15T03:49:21.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-15 03:49:21 +[2025-07-16T03:49:22.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-16 03:49:22 +[2025-07-17T03:49:23.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-17 03:49:23 +[2025-07-18T03:49:24.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-18 03:49:24 +[2025-07-19T03:49:25.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-19 03:49:25 +[2025-07-20T03:49:26.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-20 03:49:26 +[2025-07-21T03:49:27.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-21 03:49:27 +[2025-07-22T03:49:28.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-22 03:49:28 +[2025-07-23T03:49:29.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-23 03:49:29 +[2025-07-24T03:49:30.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-24 03:49:30 +[2025-07-25T03:49:31.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-25 03:49:31 +[2025-07-26T03:49:32.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-26 03:49:32 +[2025-07-27T03:49:33.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-27 03:49:33 +[2025-07-28T03:49:34.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-28 03:49:34 +[2025-07-29T03:49:35.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-29 03:49:35 +[2025-07-29T12:19:39.014] [INFO] monitorLogs - MQTT client error Error: connect ECONNREFUSED 192.168.252.1:1883 + at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1159:16) { + errno: -111, + code: 'ECONNREFUSED', + syscall: 'connect', + address: '192.168.252.1', + port: 1883 +} +[2025-07-30T03:49:36.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-30 03:49:36 +[2025-07-31T03:49:37.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-31 03:49:37 +[2025-08-01T03:49:38.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-01 03:49:38 +[2025-08-02T03:49:39.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-02 03:49:39 +[2025-08-03T03:49:40.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-03 03:49:40 +[2025-08-04T03:49:41.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-04 03:49:41 +[2025-08-05T03:49:42.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-05 03:49:42 +[2025-08-06T03:49:42.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-06 03:49:42 +[2025-08-06T13:45:45.139] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-08-06T13:45:50.492] [INFO] monitorLogs - buildTasks - params undefined +[2025-08-06T13:45:50.496] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-08-06T13:45:50.497] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-08-06T13:45:50.498] [INFO] monitorLogs - 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 +} +[2025-08-06T13:45:50.500] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-08-06T13:45:50.502] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-08-07T11:00:00.501Z +[2025-08-06T13:45:50.503] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-08-06T13:45:50.504] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-08-06T13:45:50.505] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-08-06T13:45:50.505] [INFO] monitorLogs - 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 +} +[2025-08-06T13:45:50.507] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-08-06T13:45:50.508] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-08-07T11:00:00.507Z +[2025-08-06T13:45:50.508] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-08-06T13:45:50.509] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-08-06T13:45:50.510] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-08-06T13:45:50.511] [INFO] monitorLogs - 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 +} +[2025-08-06T13:45:50.512] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-08-06T13:45:50.513] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-08-07T11:00:00.513Z +[2025-08-06T13:45:50.513] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-08-06T13:45:50.514] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-08-06T13:45:50.537] [INFO] monitorLogs - tasks created: 767 +[2025-08-06T13:45:50.539] [INFO] monitorLogs - -->FLOW bol spustený ZmRwd93QL4gaezxEbAxWvw71prn2XjlPvGyqJ6BO 2025-08-08 +[2025-08-06T13:45:55.547] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-07T03:45:53.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-07 03:45:53 +[2025-08-08T03:45:54.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-08 03:45:54 +[2025-08-09T03:45:55.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-09 03:45:55 +[2025-08-10T03:45:56.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-10 03:45:56 +[2025-08-11T03:45:57.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-11 03:45:57 +[2025-08-12T03:45:58.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-12 03:45:58 +[2025-08-13T03:45:59.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-13 03:45:59 +[2025-08-14T03:46:00.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-14 03:46:00 +[2025-08-15T03:46:01.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-15 03:46:01 +[2025-08-16T03:46:02.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-16 03:46:02 +[2025-08-17T03:46:03.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-17 03:46:03 +[2025-08-18T03:46:04.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-18 03:46:04 +[2025-08-19T03:46:05.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-19 03:46:05 +[2025-08-20T03:46:06.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-20 03:46:06 +[2025-08-21T03:46:07.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-21 03:46:07 +[2025-08-22T03:46:08.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-22 03:46:08 +[2025-08-23T03:46:09.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-23 03:46:09 +[2025-08-24T03:46:10.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-24 03:46:10 +[2025-08-25T03:46:11.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-25 03:46:11 +[2025-08-26T03:46:12.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-26 03:46:12 +[2025-08-27T03:46:13.018] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-27 03:46:13 +[2025-08-28T03:46:14.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-28 03:46:14 +[2025-08-29T03:46:15.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-29 03:46:15 +[2025-08-30T03:46:16.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-30 03:46:16 +[2025-08-31T03:46:17.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-31 03:46:17 +[2025-09-01T03:46:18.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-01 03:46:18 +[2025-09-02T03:46:19.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-02 03:46:19 +[2025-09-03T03:46:20.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-03 03:46:20 +[2025-09-04T03:46:21.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-04 03:46:21 +[2025-09-05T03:46:22.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-05 03:46:22 +[2025-09-06T03:46:23.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-06 03:46:23 +[2025-09-07T03:46:24.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-07 03:46:24 +[2025-09-07T22:05:41.527] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-09-07T22:05:46.895] [INFO] monitorLogs - buildTasks - params undefined +[2025-09-07T22:05:46.899] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-09-07T22:05:46.900] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-09-07T22:05:46.901] [INFO] monitorLogs - 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 +} +[2025-09-07T22:05:46.904] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-07T22:05:46.905] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-09-08T11:00:00.904Z +[2025-09-07T22:05:46.906] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-09-07T22:05:46.908] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-09-07T22:05:46.908] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-09-07T22:05:46.909] [INFO] monitorLogs - 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 +} +[2025-09-07T22:05:46.910] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-07T22:05:46.911] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-09-08T11:00:00.911Z +[2025-09-07T22:05:46.912] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-09-07T22:05:46.913] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-09-07T22:05:46.914] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-09-07T22:05:46.914] [INFO] monitorLogs - 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 +} +[2025-09-07T22:05:46.915] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-07T22:05:46.916] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-09-08T11:00:00.916Z +[2025-09-07T22:05:46.917] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-09-07T22:05:46.918] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-09-07T22:05:46.940] [INFO] monitorLogs - tasks created: 767 +[2025-09-07T22:05:46.943] [INFO] monitorLogs - -->FLOW bol spustený ZmRwd93QL4gaezxEbAxWvw71prn2XjlPvGyqJ6BO 2025-08-08 +[2025-09-07T22:05:51.951] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-07T22:05:52.254] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-07T22:05:52.559] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-08T03:05:50.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-08 03:05:50 +[2025-09-08T08:34:20.527] [INFO] monitorLogs - turnLine on - (line, SETTINGS.maintenance_mode) 0 true command received from platform +[2025-09-08T08:35:40.468] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false command received from platform +[2025-09-09T03:05:51.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-09 03:05:51 +[2025-09-10T03:05:52.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-10 03:05:52 +[2025-09-11T03:05:53.029] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-11 03:05:53 +[2025-09-12T03:05:54.013] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-12 03:05:54 +[2025-09-13T03:05:55.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-13 03:05:55 +[2025-09-14T03:05:56.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-14 03:05:56 +[2025-09-15T03:05:57.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-15 03:05:57 +[2025-09-16T03:05:57.013] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-16 03:05:57 +[2025-09-16T15:47:26.166] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-09-16T15:47:31.513] [INFO] monitorLogs - buildTasks - params undefined +[2025-09-16T15:47:31.517] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-09-16T15:47:31.518] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-09-16T15:47:31.519] [INFO] monitorLogs - 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 +} +[2025-09-16T15:47:31.522] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-16T15:47:31.523] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-09-17T11:00:00.522Z +[2025-09-16T15:47:31.524] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-09-16T15:47:31.525] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-09-16T15:47:31.526] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-09-16T15:47:31.527] [INFO] monitorLogs - 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 +} +[2025-09-16T15:47:31.528] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-16T15:47:31.529] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-09-17T11:00:00.529Z +[2025-09-16T15:47:31.530] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-09-16T15:47:31.531] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-09-16T15:47:31.532] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-09-16T15:47:31.532] [INFO] monitorLogs - 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 +} +[2025-09-16T15:47:31.533] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-16T15:47:31.534] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-09-17T11:00:00.534Z +[2025-09-16T15:47:31.535] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-09-16T15:47:31.536] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-09-16T15:47:31.540] [INFO] monitorLogs - tasks created: 767 +[2025-09-16T15:47:31.543] [INFO] monitorLogs - -->FLOW bol spustený ZmRwd93QL4gaezxEbAxWvw71prn2XjlPvGyqJ6BO 2025-08-08 +[2025-09-16T15:47:36.550] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-17T03:47:33.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-17 03:47:33 +[2025-09-17T20:43:41.399] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-09-17T20:43:46.760] [INFO] monitorLogs - buildTasks - params undefined +[2025-09-17T20:43:46.764] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-09-17T20:43:46.765] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-09-17T20:43:46.766] [INFO] monitorLogs - 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 +} +[2025-09-17T20:43:46.769] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-17T20:43:46.770] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-09-18T11:00:00.769Z +[2025-09-17T20:43:46.771] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-09-17T20:43:46.772] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-09-17T20:43:46.773] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-09-17T20:43:46.774] [INFO] monitorLogs - 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 +} +[2025-09-17T20:43:46.775] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-17T20:43:46.776] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-09-18T11:00:00.776Z +[2025-09-17T20:43:46.777] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-09-17T20:43:46.778] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-09-17T20:43:46.779] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-09-17T20:43:46.779] [INFO] monitorLogs - 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 +} +[2025-09-17T20:43:46.781] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-17T20:43:46.781] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-09-18T11:00:00.781Z +[2025-09-17T20:43:46.782] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-09-17T20:43:46.783] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-09-17T20:43:46.787] [INFO] monitorLogs - tasks created: 767 +[2025-09-17T20:43:46.790] [INFO] monitorLogs - -->FLOW bol spustený ZmRwd93QL4gaezxEbAxWvw71prn2XjlPvGyqJ6BO 2025-08-08 +[2025-09-17T20:43:51.796] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-18T03:43:48.013] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-18 03:43:48 +[2025-09-19T03:43:49.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-19 03:43:49 +[2025-09-19T11:23:17.951] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-09-19T11:23:23.307] [INFO] monitorLogs - buildTasks - params undefined +[2025-09-19T11:23:23.311] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-09-19T11:23:23.312] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-09-19T11:23:23.313] [INFO] monitorLogs - 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 +} +[2025-09-19T11:23:23.316] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-19T11:23:23.317] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-09-19T11:00:00.316Z +[2025-09-19T11:23:23.318] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-09-19T11:23:23.319] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-09-19T11:23:23.320] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-09-19T11:23:23.321] [INFO] monitorLogs - 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 +} +[2025-09-19T11:23:23.322] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-19T11:23:23.323] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-09-19T11:00:00.323Z +[2025-09-19T11:23:23.324] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-09-19T11:23:23.325] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-09-19T11:23:23.325] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-09-19T11:23:23.326] [INFO] monitorLogs - 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 +} +[2025-09-19T11:23:23.328] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-19T11:23:23.329] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-09-19T11:00:00.329Z +[2025-09-19T11:23:23.330] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-09-19T11:23:23.331] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-09-19T11:23:23.335] [INFO] monitorLogs - tasks created: 767 +[2025-09-19T11:23:23.354] [INFO] monitorLogs - -->FLOW bol spustený ZmRwd93QL4gaezxEbAxWvw71prn2XjlPvGyqJ6BO 2025-08-08 +[2025-09-19T11:23:28.361] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-20T03:23:25.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-20 03:23:25 +[2025-09-21T01:29:20.919] [INFO] monitorLogs - MQTT client error Error: connect ECONNREFUSED 192.168.252.1:1883 + at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1159:16) { + errno: -111, + code: 'ECONNREFUSED', + syscall: 'connect', + address: '192.168.252.1', + port: 1883 +} +[2025-09-21T03:23:26.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-21 03:23:26 +[2025-09-21T18:13:29.939] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-09-21T18:13:35.289] [INFO] monitorLogs - buildTasks - params undefined +[2025-09-21T18:13:35.294] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-09-21T18:13:35.295] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-09-21T18:13:35.295] [INFO] monitorLogs - 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 +} +[2025-09-21T18:13:35.298] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-21T18:13:35.300] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-09-22T11:00:00.299Z +[2025-09-21T18:13:35.301] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-09-21T18:13:35.302] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-09-21T18:13:35.303] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-09-21T18:13:35.303] [INFO] monitorLogs - 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 +} +[2025-09-21T18:13:35.305] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-21T18:13:35.305] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-09-22T11:00:00.305Z +[2025-09-21T18:13:35.306] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-09-21T18:13:35.307] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-09-21T18:13:35.308] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-09-21T18:13:35.309] [INFO] monitorLogs - 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 +} +[2025-09-21T18:13:35.310] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-21T18:13:35.311] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-09-22T11:00:00.311Z +[2025-09-21T18:13:35.311] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-09-21T18:13:35.312] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-09-21T18:13:35.334] [INFO] monitorLogs - tasks created: 767 +[2025-09-21T18:13:35.337] [INFO] monitorLogs - -->FLOW bol spustený ZmRwd93QL4gaezxEbAxWvw71prn2XjlPvGyqJ6BO 2025-08-08 +[2025-09-21T18:13:40.344] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-22T03:13:37.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-22 03:13:37 +[2025-09-23T03:13:38.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-23 03:13:38 +[2025-09-23T13:08:37.170] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-09-23T13:08:42.522] [INFO] monitorLogs - buildTasks - params undefined +[2025-09-23T13:08:42.527] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-09-23T13:08:42.528] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-09-23T13:08:42.529] [INFO] monitorLogs - 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 +} +[2025-09-23T13:08:42.531] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-23T13:08:42.533] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-09-24T11:00:00.532Z +[2025-09-23T13:08:42.534] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-09-23T13:08:42.535] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-09-23T13:08:42.536] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-09-23T13:08:42.536] [INFO] monitorLogs - 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 +} +[2025-09-23T13:08:42.538] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-23T13:08:42.538] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-09-24T11:00:00.538Z +[2025-09-23T13:08:42.539] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-09-23T13:08:42.540] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-09-23T13:08:42.541] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-09-23T13:08:42.541] [INFO] monitorLogs - 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 +} +[2025-09-23T13:08:42.543] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-23T13:08:42.543] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-09-24T11:00:00.543Z +[2025-09-23T13:08:42.544] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-09-23T13:08:42.545] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-09-23T13:08:42.550] [INFO] monitorLogs - tasks created: 767 +[2025-09-23T13:08:42.552] [INFO] monitorLogs - -->FLOW bol spustený ZmRwd93QL4gaezxEbAxWvw71prn2XjlPvGyqJ6BO 2025-08-08 +[2025-09-23T13:08:47.560] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-23T14:35:08.184] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-09-23T14:35:13.547] [INFO] monitorLogs - buildTasks - params undefined +[2025-09-23T14:35:13.551] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-09-23T14:35:13.552] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-09-23T14:35:13.553] [INFO] monitorLogs - 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 +} +[2025-09-23T14:35:13.556] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-23T14:35:13.557] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-09-24T11:00:00.556Z +[2025-09-23T14:35:13.558] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-09-23T14:35:13.560] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-09-23T14:35:13.561] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-09-23T14:35:13.562] [INFO] monitorLogs - 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 +} +[2025-09-23T14:35:13.563] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-23T14:35:13.564] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-09-24T11:00:00.564Z +[2025-09-23T14:35:13.565] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-09-23T14:35:13.566] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-09-23T14:35:13.566] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-09-23T14:35:13.567] [INFO] monitorLogs - 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 +} +[2025-09-23T14:35:13.568] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-23T14:35:13.569] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-09-24T11:00:00.569Z +[2025-09-23T14:35:13.570] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-09-23T14:35:13.571] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-09-23T14:35:13.593] [INFO] monitorLogs - tasks created: 767 +[2025-09-23T14:35:13.595] [INFO] monitorLogs - -->FLOW bol spustený ZmRwd93QL4gaezxEbAxWvw71prn2XjlPvGyqJ6BO 2025-08-08 +[2025-09-23T14:35:18.602] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-24T03:35:15.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-24 03:35:15 +[2025-09-25T03:35:16.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-25 03:35:16 +[2025-09-25T16:35:22.862] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-09-25T16:35:28.212] [INFO] monitorLogs - buildTasks - params undefined +[2025-09-25T16:35:28.217] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-09-25T16:35:28.218] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-09-25T16:35:28.218] [INFO] monitorLogs - 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 +} +[2025-09-25T16:35:28.221] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-25T16:35:28.223] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-09-26T11:00:00.222Z +[2025-09-25T16:35:28.224] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-09-25T16:35:28.225] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-09-25T16:35:28.226] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-09-25T16:35:28.226] [INFO] monitorLogs - 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 +} +[2025-09-25T16:35:28.228] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-25T16:35:28.229] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-09-26T11:00:00.228Z +[2025-09-25T16:35:28.230] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-09-25T16:35:28.231] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-09-25T16:35:28.232] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-09-25T16:35:28.233] [INFO] monitorLogs - 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 +} +[2025-09-25T16:35:28.234] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-25T16:35:28.235] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-09-26T11:00:00.235Z +[2025-09-25T16:35:28.235] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-09-25T16:35:28.236] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-09-25T16:35:28.257] [INFO] monitorLogs - tasks created: 767 +[2025-09-25T16:35:28.259] [INFO] monitorLogs - -->FLOW bol spustený ZmRwd93QL4gaezxEbAxWvw71prn2XjlPvGyqJ6BO 2025-08-08 +[2025-09-25T16:35:33.266] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-26T03:35:30.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-26 03:35:30 +[2025-09-27T03:35:31.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-27 03:35:31 +[2025-09-28T03:35:32.013] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-28 03:35:32 +[2025-09-29T03:35:33.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-29 03:35:33 +[2025-09-30T03:35:33.014] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-30 03:35:33 +[2025-10-01T03:35:34.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-01 03:35:34 +[2025-10-02T03:35:35.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-02 03:35:35 +[2025-10-03T03:35:36.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-03 03:35:36 +[2025-10-03T14:51:06.077] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-03T14:51:11.447] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-03T14:51:11.452] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-03T14:51:11.453] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-03T14:51:11.454] [INFO] monitorLogs - 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 +} +[2025-10-03T14:51:11.457] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-03T14:51:11.458] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-10-04T11:00:00.457Z +[2025-10-03T14:51:11.459] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-03T14:51:11.460] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-10-03T14:51:11.461] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-03T14:51:11.462] [INFO] monitorLogs - 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 +} +[2025-10-03T14:51:11.463] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-03T14:51:11.464] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-10-04T11:00:00.464Z +[2025-10-03T14:51:11.465] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-03T14:51:11.466] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-10-03T14:51:11.467] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-03T14:51:11.467] [INFO] monitorLogs - 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 +} +[2025-10-03T14:51:11.469] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-03T14:51:11.469] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-10-04T11:00:00.469Z +[2025-10-03T14:51:11.470] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-03T14:51:11.471] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-10-03T14:51:11.475] [INFO] monitorLogs - tasks created: 767 +[2025-10-03T14:51:11.495] [INFO] monitorLogs - -->FLOW bol spustený ZmRwd93QL4gaezxEbAxWvw71prn2XjlPvGyqJ6BO 2025-08-08 +[2025-10-03T14:51:16.502] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-04T03:51:13.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-04 03:51:13 +[2025-10-05T03:51:14.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-05 03:51:14 +[2025-10-06T03:51:15.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-06 03:51:15 +[2025-10-07T03:51:16.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-07 03:51:16 +[2025-10-08T03:51:17.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-08 03:51:17 +[2025-10-09T03:51:18.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-09 03:51:18 +[2025-10-09T16:56:15.451] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-09T16:56:20.805] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-09T16:56:20.810] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-09T16:56:20.811] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-09T16:56:20.811] [INFO] monitorLogs - 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 +} +[2025-10-09T16:56:20.814] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T16:56:20.816] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-10-10T11:00:00.815Z +[2025-10-09T16:56:20.817] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-09T16:56:20.818] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-10-09T16:56:20.819] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-09T16:56:20.819] [INFO] monitorLogs - 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 +} +[2025-10-09T16:56:20.821] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T16:56:20.821] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-10-10T11:00:00.821Z +[2025-10-09T16:56:20.822] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-09T16:56:20.823] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-10-09T16:56:20.824] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-09T16:56:20.824] [INFO] monitorLogs - 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 +} +[2025-10-09T16:56:20.826] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T16:56:20.826] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-10-10T11:00:00.826Z +[2025-10-09T16:56:20.827] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-09T16:56:20.828] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-10-09T16:56:20.849] [INFO] monitorLogs - tasks created: 767 +[2025-10-09T16:56:20.852] [INFO] monitorLogs - -->FLOW bol spustený ZmRwd93QL4gaezxEbAxWvw71prn2XjlPvGyqJ6BO 2025-08-08 +[2025-10-09T16:56:25.856] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-09T19:08:47.472] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-09T19:08:52.837] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-09T19:08:52.843] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-09T19:08:52.844] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-09T19:08:52.844] [INFO] monitorLogs - 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 +} +[2025-10-09T19:08:52.847] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T19:08:52.849] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-10-10T11:00:00.848Z +[2025-10-09T19:08:52.850] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-09T19:08:52.851] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-10-09T19:08:52.852] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-09T19:08:52.852] [INFO] monitorLogs - 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 +} +[2025-10-09T19:08:52.854] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T19:08:52.854] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-10-10T11:00:00.854Z +[2025-10-09T19:08:52.855] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-09T19:08:52.856] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-10-09T19:08:52.857] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-09T19:08:52.857] [INFO] monitorLogs - 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 +} +[2025-10-09T19:08:52.859] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T19:08:52.859] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-10-10T11:00:00.859Z +[2025-10-09T19:08:52.860] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-09T19:08:52.861] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-10-09T19:08:52.865] [INFO] monitorLogs - tasks created: 767 +[2025-10-09T19:08:52.868] [INFO] monitorLogs - -->FLOW bol spustený ZmRwd93QL4gaezxEbAxWvw71prn2XjlPvGyqJ6BO 2025-08-08 +[2025-10-09T19:08:57.875] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-10T03:08:54.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-10 03:08:54 +[2025-10-11T03:08:55.013] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-11 03:08:55 +[2025-10-12T03:08:56.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-12 03:08:56 +[2025-10-13T03:08:57.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-13 03:08:57 +[2025-10-14T03:08:57.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-14 03:08:57 +[2025-10-15T03:08:58.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-15 03:08:58 +[2025-10-15T15:34:50.152] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-15T15:34:55.522] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-15T15:34:55.527] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-15T15:34:55.528] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-15T15:34:55.529] [INFO] monitorLogs - 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 +} +[2025-10-15T15:34:55.532] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-15T15:34:55.533] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-10-16T11:00:00.532Z +[2025-10-15T15:34:55.534] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-15T15:34:55.535] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-10-15T15:34:55.536] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-15T15:34:55.537] [INFO] monitorLogs - 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 +} +[2025-10-15T15:34:55.538] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-15T15:34:55.539] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-10-16T11:00:00.539Z +[2025-10-15T15:34:55.540] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-15T15:34:55.541] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-10-15T15:34:55.541] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-15T15:34:55.542] [INFO] monitorLogs - 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 +} +[2025-10-15T15:34:55.543] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-15T15:34:55.544] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-10-16T11:00:00.544Z +[2025-10-15T15:34:55.545] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-15T15:34:55.546] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-10-15T15:34:55.567] [INFO] monitorLogs - tasks created: 767 +[2025-10-15T15:34:55.570] [INFO] monitorLogs - -->FLOW bol spustený ZmRwd93QL4gaezxEbAxWvw71prn2XjlPvGyqJ6BO 2025-10-08 +[2025-10-15T15:35:00.577] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu diff --git a/RVO21/package-lock.json b/RVO21/package-lock.json new file mode 100755 index 0000000..3c5c1ba --- /dev/null +++ b/RVO21/package-lock.json @@ -0,0 +1,2139 @@ +{ + "name": "emptyproject", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "emptyproject", + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "bitwise": "^2.1.0", + "easy-crc": "0.0.2", + "jsmodbus": "^4.0.6", + "log4js": "^6.3.0", + "moment": "^2.30.1", + "mqtt": "^4.2.6", + "nodemailer": "^6.9.7", + "serialport": "^9.2.8", + "total.js": "^3.4.13" + } + }, + "node_modules/@serialport/binding-abstract": { + "version": "9.2.3", + "resolved": "https://registry.npmjs.org/@serialport/binding-abstract/-/binding-abstract-9.2.3.tgz", + "integrity": "sha512-cQs9tbIlG3P0IrOWyVirqlhWuJ7Ms2Zh9m2108z6Y5UW/iVj6wEOiW8EmK9QX9jmJXYllE7wgGgvVozP5oCj3w==", + "dependencies": { + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/binding-mock": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/binding-mock/-/binding-mock-9.2.4.tgz", + "integrity": "sha512-dpEhACCs44oQhh6ajJfJdvQdK38Vq0N4W6iD/gdplglDCK7qXRQCMUjJIeKdS/HSEiWkC3bwumUhUufdsOyT4g==", + "dependencies": { + "@serialport/binding-abstract": "9.2.3", + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/bindings": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/@serialport/bindings/-/bindings-9.2.8.tgz", + "integrity": "sha512-hSLxTe0tADZ3LMMGwvEJWOC/TaFQTyPeFalUCsJ1lSQ0k6bPF04JwrtB/C81GetmDBTNRY0GlD0SNtKCc7Dr5g==", + "hasInstallScript": true, + "dependencies": { + "@serialport/binding-abstract": "9.2.3", + "@serialport/parser-readline": "9.2.4", + "bindings": "^1.5.0", + "debug": "^4.3.2", + "nan": "^2.15.0", + "prebuild-install": "^7.0.0" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-byte-length": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-byte-length/-/parser-byte-length-9.2.4.tgz", + "integrity": "sha512-sQD/iw4ZMU3xW9PLi0/GlvU6Y623jGeWecbMkO7izUo/6P7gtfv1c9ikd5h0kwL8AoAOpQA1lxdHIKox+umBUg==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-cctalk": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-cctalk/-/parser-cctalk-9.2.4.tgz", + "integrity": "sha512-T4TU5vQMwmo9AB3gQLFDWbfJXlW5jd9guEsB/nqKjFHTv0FXPdZ7DQ2TpSp8RnHWxU3GX6kYTaDO20BKzc8GPQ==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-delimiter": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-delimiter/-/parser-delimiter-9.2.4.tgz", + "integrity": "sha512-4nvTAoYAgkxFiXrkI+3CA49Yd43CODjeszh89EK+I9c8wOZ+etZduRCzINYPiy26g7zO+GRAb9FoPCsY+sYcbQ==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-inter-byte-timeout": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-inter-byte-timeout/-/parser-inter-byte-timeout-9.2.4.tgz", + "integrity": "sha512-SOAdvr0oBQIOCXX198hiTlxs4JTKg9j5piapw5tNq52fwDOWdbYrFneT/wN04UTMKaDrJuEvXq6T4rv4j7nJ5A==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-readline": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-readline/-/parser-readline-9.2.4.tgz", + "integrity": "sha512-Z1/qrZTQUVhNSJP1hd9YfDvq0o7d87rNwAjjRKbVpa7Qi51tG5BnKt43IV3NFMyBlVcRe0rnIb3tJu57E0SOwg==", + "dependencies": { + "@serialport/parser-delimiter": "9.2.4" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-ready": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-ready/-/parser-ready-9.2.4.tgz", + "integrity": "sha512-Pyi94Itjl6qAURwIZr/gmZpMAyTmKXThm6vL5DoAWGQjcRHWB0gwv2TY2v7N+mQLJYUKU3cMnvnATXxHm7xjxw==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-regex": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-regex/-/parser-regex-9.2.4.tgz", + "integrity": "sha512-sI/cVvPOYz+Dbv4ZdnW16qAwvXiFf/1pGASQdbveRTlgJDdz7sRNlCBifzfTN2xljwvCTZYqiudKvDdC1TepRQ==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/stream": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/stream/-/stream-9.2.4.tgz", + "integrity": "sha512-bLye8Ub4vUFQGmkh8qEqehr7SE7EJs2yDs0h9jzuL5oKi+F34CFmWkEErO8GAOQ8YNn7p6b3GxUgs+0BrHHDZQ==", + "dependencies": { + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "node_modules/are-we-there-yet": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", + "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/base64-js": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", + "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==" + }, + "node_modules/bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "dependencies": { + "file-uri-to-path": "1.0.0" + } + }, + "node_modules/bitwise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/bitwise/-/bitwise-2.1.0.tgz", + "integrity": "sha512-XKgAhMXCh4H/3oNwAHAsAO0iC89s9cOiumgYwSHjSobGWxYjv62YhkL9QEdvGP151xypCtMlAfKK79GEcd2eRQ==" + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/bl/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/buffer": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz", + "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==", + "dependencies": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + }, + "node_modules/buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" + }, + "node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, + "node_modules/code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/commist": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/commist/-/commist-1.1.0.tgz", + "integrity": "sha512-rraC8NXWOEjhADbZe9QBNzLAN5Q3fsTPQtBV+fEVj6xKIgDgNiEVE6ZNfHpZOqfQ21YUzfVNUXLOEZquYvQPPg==", + "dependencies": { + "leven": "^2.1.0", + "minimist": "^1.1.0" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "node_modules/concat-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", + "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", + "engines": [ + "node >= 6.0" + ], + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.0.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/concat-stream/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" + }, + "node_modules/core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "node_modules/crc": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/crc/-/crc-3.4.0.tgz", + "integrity": "sha512-ycVC2+4/DLgXXq7QweYi2znhqDuZz6P5TQXnkQo8v15XY/5p/IWeZwsSE31Ifo8w15b8TWLsqhXOjXyilHuQxw==" + }, + "node_modules/date-format": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.11.tgz", + "integrity": "sha512-VS20KRyorrbMCQmpdl2hg5KaOUsda1RbnsJg461FfrcyCUg+pkd0b40BSW4niQyTheww4DBXQnS7HwSrKkipLw==", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" + }, + "node_modules/detect-libc": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz", + "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==", + "engines": { + "node": ">=8" + } + }, + "node_modules/duplexify": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.2.tgz", + "integrity": "sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw==", + "dependencies": { + "end-of-stream": "^1.4.1", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1", + "stream-shift": "^1.0.0" + } + }, + "node_modules/duplexify/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/easy-crc": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/easy-crc/-/easy-crc-0.0.2.tgz", + "integrity": "sha512-h6eqIdhJRe0p271/xZJbM/0klCi13mW5IB7ZEzEGH11yV4QXWAkD4yPErz0fXdhFrd6sZ4Q1k5Iky2kMsMNePw==" + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" + }, + "node_modules/flatted": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", + "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==" + }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, + "node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "node_modules/gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha512-14x4kjc6lkD3ltw589k0NrPD6cCNTD6CWoVUNpB85+DrtONoZn+Rug6xZU5RvSC4+TZPxA5AnBibQYAvZn41Hg==", + "dependencies": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "node_modules/github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==" + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" + }, + "node_modules/has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" + }, + "node_modules/help-me": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/help-me/-/help-me-3.0.0.tgz", + "integrity": "sha512-hx73jClhyk910sidBB7ERlnhMlFsJJIBqSVMFDwPN8o2v9nmp5KgLq1Xz1Bf1fCMMZ6mPrX159iG0VLy/fPMtQ==", + "dependencies": { + "glob": "^7.1.6", + "readable-stream": "^3.6.0" + } + }, + "node_modules/help-me/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, + "node_modules/is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==", + "dependencies": { + "number-is-nan": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "node_modules/js-sdsl": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz", + "integrity": "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/js-sdsl" + } + }, + "node_modules/jsmodbus": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/jsmodbus/-/jsmodbus-4.0.6.tgz", + "integrity": "sha512-gCmjoaERErK5Rn9Lu/BN07fY13MoWV7JKgGzrnkPlQPdPxYcwDhLtYcmpFFpZ4J9NPZZBSezi1UkLZO/DnNppA==", + "dependencies": { + "crc": "3.4.0", + "debug": "^3.1.0" + }, + "bin": { + "jsmodbus": "bin/jsmodbus.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/jsmodbus/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/leven": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", + "integrity": "sha1-wuep93IJTe6dNCAq6KzORoeHVYA=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/log4js": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.5.2.tgz", + "integrity": "sha512-DXtpNtt+KDOMT7RHUDIur/WsSA3rntlUh9Zg4XCdV42wUuMmbFkl38+LZ92Z5QvQA7mD5kAVkLiBSEH/tvUB8A==", + "dependencies": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "flatted": "^3.2.5", + "rfdc": "^1.3.0", + "streamroller": "^3.1.1" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" + }, + "node_modules/moment": { + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", + "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==", + "engines": { + "node": "*" + } + }, + "node_modules/mqtt": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/mqtt/-/mqtt-4.3.7.tgz", + "integrity": "sha512-ew3qwG/TJRorTz47eW46vZ5oBw5MEYbQZVaEji44j5lAUSQSqIEoul7Kua/BatBW0H0kKQcC9kwUHa1qzaWHSw==", + "dependencies": { + "commist": "^1.0.0", + "concat-stream": "^2.0.0", + "debug": "^4.1.1", + "duplexify": "^4.1.1", + "help-me": "^3.0.0", + "inherits": "^2.0.3", + "lru-cache": "^6.0.0", + "minimist": "^1.2.5", + "mqtt-packet": "^6.8.0", + "number-allocator": "^1.0.9", + "pump": "^3.0.0", + "readable-stream": "^3.6.0", + "reinterval": "^1.1.0", + "rfdc": "^1.3.0", + "split2": "^3.1.0", + "ws": "^7.5.5", + "xtend": "^4.0.2" + }, + "bin": { + "mqtt": "bin/mqtt.js", + "mqtt_pub": "bin/pub.js", + "mqtt_sub": "bin/sub.js" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/mqtt-packet": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/mqtt-packet/-/mqtt-packet-6.10.0.tgz", + "integrity": "sha512-ja8+mFKIHdB1Tpl6vac+sktqy3gA8t9Mduom1BA75cI+R9AHnZOiaBQwpGiWnaVJLDGRdNhQmFaAqd7tkKSMGA==", + "dependencies": { + "bl": "^4.0.2", + "debug": "^4.1.1", + "process-nextick-args": "^2.0.1" + } + }, + "node_modules/mqtt/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/nan": { + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.16.0.tgz", + "integrity": "sha512-UdAqHyFngu7TfQKsCBgAA6pWDkT8MAO7d0jyOecVhN5354xbLqdn8mV9Tat9gepAupm0bt2DbeaSC8vS52MuFA==" + }, + "node_modules/napi-build-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", + "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==" + }, + "node_modules/node-abi": { + "version": "3.22.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.22.0.tgz", + "integrity": "sha512-u4uAs/4Zzmp/jjsD9cyFYDXeISfUWaAVWshPmDZOFOv4Xl4SbzTXm53I04C2uRueYJ+0t5PEtLH/owbn2Npf/w==", + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/nodemailer": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.7.tgz", + "integrity": "sha512-rUtR77ksqex/eZRLmQ21LKVH5nAAsVicAtAYudK7JgwenEDZ0UIQ1adUGqErz7sMkWYxWTTU1aeP2Jga6WQyJw==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "dependencies": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "node_modules/number-allocator": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/number-allocator/-/number-allocator-1.0.14.tgz", + "integrity": "sha512-OrL44UTVAvkKdOdRQZIJpLkAdjXGTRda052sN4sO77bKEzYYqWKMBjQvrJFzqygI99gL6Z4u2xctPW1tB8ErvA==", + "dependencies": { + "debug": "^4.3.1", + "js-sdsl": "4.3.0" + } + }, + "node_modules/number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/prebuild-install": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.0.tgz", + "integrity": "sha512-CNcMgI1xBypOyGqjp3wOc8AAo1nMhZS3Cwd3iHIxOdAUbb+YxdNuM4Z5iIrZ8RLvOsf3F3bl7b7xGq6DjQoNYA==", + "dependencies": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^1.0.1", + "node-abi": "^3.3.0", + "npmlog": "^4.0.1", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + }, + "bin": { + "prebuild-install": "bin.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/reinterval": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reinterval/-/reinterval-1.1.0.tgz", + "integrity": "sha1-M2Hs+jymwYKDOA3Qu5VG85D17Oc=" + }, + "node_modules/rfdc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==" + }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/serialport": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/serialport/-/serialport-9.2.8.tgz", + "integrity": "sha512-FsWpMQgSJxi93JgWl5xM1f9/Z8IjRJuaUEoHqLf8FPBLw7gMhInuHOBhI2onQufWIYPGTz3H3oGcu1nCaK1EfA==", + "dependencies": { + "@serialport/binding-mock": "9.2.4", + "@serialport/bindings": "9.2.8", + "@serialport/parser-byte-length": "9.2.4", + "@serialport/parser-cctalk": "9.2.4", + "@serialport/parser-delimiter": "9.2.4", + "@serialport/parser-inter-byte-timeout": "9.2.4", + "@serialport/parser-readline": "9.2.4", + "@serialport/parser-ready": "9.2.4", + "@serialport/parser-regex": "9.2.4", + "@serialport/stream": "9.2.4", + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "node_modules/split2": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", + "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", + "dependencies": { + "readable-stream": "^3.0.0" + } + }, + "node_modules/split2/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==" + }, + "node_modules/streamroller": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.1.1.tgz", + "integrity": "sha512-iPhtd9unZ6zKdWgMeYGfSBuqCngyJy1B/GPi/lTpwGpa3bajuX30GjUVd0/Tn/Xhg0mr4DOSENozz9Y06qyonQ==", + "dependencies": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "fs-extra": "^10.1.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dependencies": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/tar-fs": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "dependencies": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tar-stream/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/total.js": { + "version": "3.4.13", + "resolved": "https://registry.npmjs.org/total.js/-/total.js-3.4.13.tgz", + "integrity": "sha512-lAH4gEixlPFbrE3xfKADAcHfO79IFq2wKa9GTsrgRzIR5MTg3mNH7+4IxvX1pK8faoYb/0oYSJ1YTsAa5hIFFQ==", + "bin": { + "total": "bin/totaljs", + "total.js": "bin/totaljs", + "totaljs": "bin/totaljs", + "totalpackage": "bin/tpm", + "tpm": "bin/tpm" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, + "node_modules/universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "node_modules/wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "node_modules/ws": { + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } + }, + "dependencies": { + "@serialport/binding-abstract": { + "version": "9.2.3", + "resolved": "https://registry.npmjs.org/@serialport/binding-abstract/-/binding-abstract-9.2.3.tgz", + "integrity": "sha512-cQs9tbIlG3P0IrOWyVirqlhWuJ7Ms2Zh9m2108z6Y5UW/iVj6wEOiW8EmK9QX9jmJXYllE7wgGgvVozP5oCj3w==", + "requires": { + "debug": "^4.3.2" + } + }, + "@serialport/binding-mock": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/binding-mock/-/binding-mock-9.2.4.tgz", + "integrity": "sha512-dpEhACCs44oQhh6ajJfJdvQdK38Vq0N4W6iD/gdplglDCK7qXRQCMUjJIeKdS/HSEiWkC3bwumUhUufdsOyT4g==", + "requires": { + "@serialport/binding-abstract": "9.2.3", + "debug": "^4.3.2" + } + }, + "@serialport/bindings": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/@serialport/bindings/-/bindings-9.2.8.tgz", + "integrity": "sha512-hSLxTe0tADZ3LMMGwvEJWOC/TaFQTyPeFalUCsJ1lSQ0k6bPF04JwrtB/C81GetmDBTNRY0GlD0SNtKCc7Dr5g==", + "requires": { + "@serialport/binding-abstract": "9.2.3", + "@serialport/parser-readline": "9.2.4", + "bindings": "^1.5.0", + "debug": "^4.3.2", + "nan": "^2.15.0", + "prebuild-install": "^7.0.0" + } + }, + "@serialport/parser-byte-length": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-byte-length/-/parser-byte-length-9.2.4.tgz", + "integrity": "sha512-sQD/iw4ZMU3xW9PLi0/GlvU6Y623jGeWecbMkO7izUo/6P7gtfv1c9ikd5h0kwL8AoAOpQA1lxdHIKox+umBUg==" + }, + "@serialport/parser-cctalk": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-cctalk/-/parser-cctalk-9.2.4.tgz", + "integrity": "sha512-T4TU5vQMwmo9AB3gQLFDWbfJXlW5jd9guEsB/nqKjFHTv0FXPdZ7DQ2TpSp8RnHWxU3GX6kYTaDO20BKzc8GPQ==" + }, + "@serialport/parser-delimiter": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-delimiter/-/parser-delimiter-9.2.4.tgz", + "integrity": "sha512-4nvTAoYAgkxFiXrkI+3CA49Yd43CODjeszh89EK+I9c8wOZ+etZduRCzINYPiy26g7zO+GRAb9FoPCsY+sYcbQ==" + }, + "@serialport/parser-inter-byte-timeout": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-inter-byte-timeout/-/parser-inter-byte-timeout-9.2.4.tgz", + "integrity": "sha512-SOAdvr0oBQIOCXX198hiTlxs4JTKg9j5piapw5tNq52fwDOWdbYrFneT/wN04UTMKaDrJuEvXq6T4rv4j7nJ5A==" + }, + "@serialport/parser-readline": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-readline/-/parser-readline-9.2.4.tgz", + "integrity": "sha512-Z1/qrZTQUVhNSJP1hd9YfDvq0o7d87rNwAjjRKbVpa7Qi51tG5BnKt43IV3NFMyBlVcRe0rnIb3tJu57E0SOwg==", + "requires": { + "@serialport/parser-delimiter": "9.2.4" + } + }, + "@serialport/parser-ready": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-ready/-/parser-ready-9.2.4.tgz", + "integrity": "sha512-Pyi94Itjl6qAURwIZr/gmZpMAyTmKXThm6vL5DoAWGQjcRHWB0gwv2TY2v7N+mQLJYUKU3cMnvnATXxHm7xjxw==" + }, + "@serialport/parser-regex": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-regex/-/parser-regex-9.2.4.tgz", + "integrity": "sha512-sI/cVvPOYz+Dbv4ZdnW16qAwvXiFf/1pGASQdbveRTlgJDdz7sRNlCBifzfTN2xljwvCTZYqiudKvDdC1TepRQ==" + }, + "@serialport/stream": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/stream/-/stream-9.2.4.tgz", + "integrity": "sha512-bLye8Ub4vUFQGmkh8qEqehr7SE7EJs2yDs0h9jzuL5oKi+F34CFmWkEErO8GAOQ8YNn7p6b3GxUgs+0BrHHDZQ==", + "requires": { + "debug": "^4.3.2" + } + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==" + }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "are-we-there-yet": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", + "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "base64-js": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", + "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==" + }, + "bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "requires": { + "file-uri-to-path": "1.0.0" + } + }, + "bitwise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/bitwise/-/bitwise-2.1.0.tgz", + "integrity": "sha512-XKgAhMXCh4H/3oNwAHAsAO0iC89s9cOiumgYwSHjSobGWxYjv62YhkL9QEdvGP151xypCtMlAfKK79GEcd2eRQ==" + }, + "bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "requires": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "buffer": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz", + "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==", + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" + }, + "chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==" + }, + "commist": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/commist/-/commist-1.1.0.tgz", + "integrity": "sha512-rraC8NXWOEjhADbZe9QBNzLAN5Q3fsTPQtBV+fEVj6xKIgDgNiEVE6ZNfHpZOqfQ21YUzfVNUXLOEZquYvQPPg==", + "requires": { + "leven": "^2.1.0", + "minimist": "^1.1.0" + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "concat-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", + "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.0.2", + "typedarray": "^0.0.6" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "crc": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/crc/-/crc-3.4.0.tgz", + "integrity": "sha512-ycVC2+4/DLgXXq7QweYi2znhqDuZz6P5TQXnkQo8v15XY/5p/IWeZwsSE31Ifo8w15b8TWLsqhXOjXyilHuQxw==" + }, + "date-format": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.11.tgz", + "integrity": "sha512-VS20KRyorrbMCQmpdl2hg5KaOUsda1RbnsJg461FfrcyCUg+pkd0b40BSW4niQyTheww4DBXQnS7HwSrKkipLw==" + }, + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "requires": { + "ms": "2.1.2" + } + }, + "decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "requires": { + "mimic-response": "^3.1.0" + } + }, + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==" + }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" + }, + "detect-libc": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz", + "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==" + }, + "duplexify": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.2.tgz", + "integrity": "sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw==", + "requires": { + "end-of-stream": "^1.4.1", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1", + "stream-shift": "^1.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "easy-crc": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/easy-crc/-/easy-crc-0.0.2.tgz", + "integrity": "sha512-h6eqIdhJRe0p271/xZJbM/0klCi13mW5IB7ZEzEGH11yV4QXWAkD4yPErz0fXdhFrd6sZ4Q1k5Iky2kMsMNePw==" + }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "requires": { + "once": "^1.4.0" + } + }, + "expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==" + }, + "file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" + }, + "flatted": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", + "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==" + }, + "fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, + "fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha512-14x4kjc6lkD3ltw589k0NrPD6cCNTD6CWoVUNpB85+DrtONoZn+Rug6xZU5RvSC4+TZPxA5AnBibQYAvZn41Hg==", + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==" + }, + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" + }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" + }, + "help-me": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/help-me/-/help-me-3.0.0.tgz", + "integrity": "sha512-hx73jClhyk910sidBB7ERlnhMlFsJJIBqSVMFDwPN8o2v9nmp5KgLq1Xz1Bf1fCMMZ6mPrX159iG0VLy/fPMtQ==", + "requires": { + "glob": "^7.1.6", + "readable-stream": "^3.6.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==", + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "js-sdsl": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz", + "integrity": "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==" + }, + "jsmodbus": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/jsmodbus/-/jsmodbus-4.0.6.tgz", + "integrity": "sha512-gCmjoaERErK5Rn9Lu/BN07fY13MoWV7JKgGzrnkPlQPdPxYcwDhLtYcmpFFpZ4J9NPZZBSezi1UkLZO/DnNppA==", + "requires": { + "crc": "3.4.0", + "debug": "^3.1.0" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "requires": { + "ms": "^2.1.1" + } + } + } + }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, + "leven": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", + "integrity": "sha1-wuep93IJTe6dNCAq6KzORoeHVYA=" + }, + "log4js": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.5.2.tgz", + "integrity": "sha512-DXtpNtt+KDOMT7RHUDIur/WsSA3rntlUh9Zg4XCdV42wUuMmbFkl38+LZ92Z5QvQA7mD5kAVkLiBSEH/tvUB8A==", + "requires": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "flatted": "^3.2.5", + "rfdc": "^1.3.0", + "streamroller": "^3.1.1" + } + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "requires": { + "yallist": "^4.0.0" + } + }, + "mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==" + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==" + }, + "mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" + }, + "moment": { + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", + "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==" + }, + "mqtt": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/mqtt/-/mqtt-4.3.7.tgz", + "integrity": "sha512-ew3qwG/TJRorTz47eW46vZ5oBw5MEYbQZVaEji44j5lAUSQSqIEoul7Kua/BatBW0H0kKQcC9kwUHa1qzaWHSw==", + "requires": { + "commist": "^1.0.0", + "concat-stream": "^2.0.0", + "debug": "^4.1.1", + "duplexify": "^4.1.1", + "help-me": "^3.0.0", + "inherits": "^2.0.3", + "lru-cache": "^6.0.0", + "minimist": "^1.2.5", + "mqtt-packet": "^6.8.0", + "number-allocator": "^1.0.9", + "pump": "^3.0.0", + "readable-stream": "^3.6.0", + "reinterval": "^1.1.0", + "rfdc": "^1.3.0", + "split2": "^3.1.0", + "ws": "^7.5.5", + "xtend": "^4.0.2" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "mqtt-packet": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/mqtt-packet/-/mqtt-packet-6.10.0.tgz", + "integrity": "sha512-ja8+mFKIHdB1Tpl6vac+sktqy3gA8t9Mduom1BA75cI+R9AHnZOiaBQwpGiWnaVJLDGRdNhQmFaAqd7tkKSMGA==", + "requires": { + "bl": "^4.0.2", + "debug": "^4.1.1", + "process-nextick-args": "^2.0.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "nan": { + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.16.0.tgz", + "integrity": "sha512-UdAqHyFngu7TfQKsCBgAA6pWDkT8MAO7d0jyOecVhN5354xbLqdn8mV9Tat9gepAupm0bt2DbeaSC8vS52MuFA==" + }, + "napi-build-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", + "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==" + }, + "node-abi": { + "version": "3.22.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.22.0.tgz", + "integrity": "sha512-u4uAs/4Zzmp/jjsD9cyFYDXeISfUWaAVWshPmDZOFOv4Xl4SbzTXm53I04C2uRueYJ+0t5PEtLH/owbn2Npf/w==", + "requires": { + "semver": "^7.3.5" + } + }, + "nodemailer": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.7.tgz", + "integrity": "sha512-rUtR77ksqex/eZRLmQ21LKVH5nAAsVicAtAYudK7JgwenEDZ0UIQ1adUGqErz7sMkWYxWTTU1aeP2Jga6WQyJw==" + }, + "npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "number-allocator": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/number-allocator/-/number-allocator-1.0.14.tgz", + "integrity": "sha512-OrL44UTVAvkKdOdRQZIJpLkAdjXGTRda052sN4sO77bKEzYYqWKMBjQvrJFzqygI99gL6Z4u2xctPW1tB8ErvA==", + "requires": { + "debug": "^4.3.1", + "js-sdsl": "4.3.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==" + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==" + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==" + }, + "prebuild-install": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.0.tgz", + "integrity": "sha512-CNcMgI1xBypOyGqjp3wOc8AAo1nMhZS3Cwd3iHIxOdAUbb+YxdNuM4Z5iIrZ8RLvOsf3F3bl7b7xGq6DjQoNYA==", + "requires": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^1.0.1", + "node-abi": "^3.3.0", + "npmlog": "^4.0.1", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + } + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + } + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "reinterval": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reinterval/-/reinterval-1.1.0.tgz", + "integrity": "sha1-M2Hs+jymwYKDOA3Qu5VG85D17Oc=" + }, + "rfdc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==" + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "requires": { + "lru-cache": "^6.0.0" + } + }, + "serialport": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/serialport/-/serialport-9.2.8.tgz", + "integrity": "sha512-FsWpMQgSJxi93JgWl5xM1f9/Z8IjRJuaUEoHqLf8FPBLw7gMhInuHOBhI2onQufWIYPGTz3H3oGcu1nCaK1EfA==", + "requires": { + "@serialport/binding-mock": "9.2.4", + "@serialport/bindings": "9.2.8", + "@serialport/parser-byte-length": "9.2.4", + "@serialport/parser-cctalk": "9.2.4", + "@serialport/parser-delimiter": "9.2.4", + "@serialport/parser-inter-byte-timeout": "9.2.4", + "@serialport/parser-readline": "9.2.4", + "@serialport/parser-ready": "9.2.4", + "@serialport/parser-regex": "9.2.4", + "@serialport/stream": "9.2.4", + "debug": "^4.3.2" + } + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==" + }, + "simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "requires": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "split2": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", + "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", + "requires": { + "readable-stream": "^3.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==" + }, + "streamroller": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.1.1.tgz", + "integrity": "sha512-iPhtd9unZ6zKdWgMeYGfSBuqCngyJy1B/GPi/lTpwGpa3bajuX30GjUVd0/Tn/Xhg0mr4DOSENozz9Y06qyonQ==", + "requires": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "fs-extra": "^10.1.0" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" + }, + "tar-fs": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "requires": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "requires": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "total.js": { + "version": "3.4.13", + "resolved": "https://registry.npmjs.org/total.js/-/total.js-3.4.13.tgz", + "integrity": "sha512-lAH4gEixlPFbrE3xfKADAcHfO79IFq2wKa9GTsrgRzIR5MTg3mNH7+4IxvX1pK8faoYb/0oYSJ1YTsAa5hIFFQ==" + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, + "universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==" + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "requires": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "ws": { + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "requires": {} + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } + } +} diff --git a/RVO21/package.json b/RVO21/package.json new file mode 100755 index 0000000..7f7c795 --- /dev/null +++ b/RVO21/package.json @@ -0,0 +1,30 @@ +{ + "name": "emptyproject", + "description": "Total.js empty project.", + "version": "1.0.0", + "main": "debug.js", + "dependencies": { + "bitwise": "^2.1.0", + "easy-crc": "0.0.2", + "jsmodbus": "^4.0.6", + "log4js": "^6.3.0", + "moment": "^2.30.1", + "mqtt": "^4.2.6", + "nodemailer": "^6.9.7", + "serialport": "^9.2.8", + "total.js": "^3.4.13" + }, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "https://github.com/totaljs/emptyproject-flow" + }, + "keywords": [ + "empty", + "project" + ], + "author": "Peter Širka", + "license": "MIT" +} diff --git a/RVO21/release.js b/RVO21/release.js new file mode 100755 index 0000000..02d52ff --- /dev/null +++ b/RVO21/release.js @@ -0,0 +1,15 @@ +// =================================================== +// FOR PRODUCTION +// Total.js - framework for Node.js platform +// https://www.totaljs.com +// =================================================== + +const options = {'ip':'0.0.0.0', 'port':12345}; + +// options.ip = '127.0.0.1'; +// options.port = parseInt(process.argv[2]); +// options.config = { name: 'Total.js' }; +// options.sleep = 3000; + +require('total.js').http('release', options); +// require('total.js').cluster.http(5, 'release', options); diff --git a/RVO21/release.js.json b/RVO21/release.js.json new file mode 100755 index 0000000..e0587b3 --- /dev/null +++ b/RVO21/release.js.json @@ -0,0 +1,34 @@ +{ + "pid": 405, + "stats": [ + { + "id": null, + "version": { + "node": "v14.18.1", + "total": "3.4.13", + "app": "1.0.0" + }, + "pid": 405, + "thread": "", + "mode": "release", + "overload": 0, + "date": "2025-10-16T00:23:46.213Z", + "memory": 21.78, + "rm": 0, + "fm": 0, + "wm": 0, + "mm": 0, + "om": 4, + "em": 1, + "dbrm": 0, + "dbwm": 0, + "usage": 0, + "requests": 0, + "pending": 0, + "errors": 0, + "timeouts": 0, + "uptime": 650, + "online": 0 + } + ] +} \ No newline at end of file diff --git a/RVO21/report_data.log b/RVO21/report_data.log new file mode 100755 index 0000000..e2b3d82 --- /dev/null +++ b/RVO21/report_data.log @@ -0,0 +1,151 @@ +{ + "name": "rvo_senica_21_ip115", + "time": "2025-10-15T14:35:01.190Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_21_ip115", + "time": "2025-10-15T15:35:01.185Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_21_ip115", + "time": "2025-10-15T16:35:01.186Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_21_ip115", + "time": "2025-10-15T17:35:01.187Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_21_ip115", + "time": "2025-10-15T18:35:01.187Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_21_ip115", + "time": "2025-10-15T19:35:01.187Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_21_ip115", + "time": "2025-10-15T20:35:01.188Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_21_ip115", + "time": "2025-10-15T21:35:01.188Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_21_ip115", + "time": "2025-10-15T22:35:01.196Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_21_ip115", + "time": "2025-10-15T23:35:01.190Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +} \ No newline at end of file From f07e260dba181a8b04df9ab6ea0f26d066fd8098 Mon Sep 17 00:00:00 2001 From: Jakub Klena Date: Thu, 16 Oct 2025 02:24:51 +0200 Subject: [PATCH 12/30] Backup senica-RVO22 on 16.10.2025 --- RVO22/addSwitch.py | 36 + RVO22/cloud_topic.py | 76 + RVO22/config | 12 + RVO22/createNode.py | 43 + RVO22/databases/accelerometer_db.js | 3055 ++++++++++++++++ RVO22/databases/modbus_config.js | 114 + RVO22/databases/nodes.table | 43 + .../nodes_original/nodes_original.table | 1 + RVO22/databases/notifications.table | 41 + RVO22/databases/pins.table | 14 + RVO22/databases/relays.table | 5 + RVO22/databases/settings.table | 2 + RVO22/databases/tbdata.nosql | 4 + RVO22/databases/tbdatacloud.nosql | 3 + RVO22/databases/total_energy.js | 38 + RVO22/debug.js | 16 + RVO22/err.txt | 74 + RVO22/flow/cloudmqttconnect.js | 357 ++ RVO22/flow/cmd_manager.js | 3071 ++++++++++++++++ RVO22/flow/code.js | 90 + RVO22/flow/comment.js | 11 + RVO22/flow/count.js | 60 + RVO22/flow/db_connector.js | 286 ++ RVO22/flow/db_init.js | 113 + RVO22/flow/debug.js | 100 + RVO22/flow/designer.json | 3102 +++++++++++++++++ RVO22/flow/dido_controller.js | 1486 ++++++++ RVO22/flow/helper/DataToTbHandler.js | 187 + RVO22/flow/helper/ErrorToServiceHandler.js | 91 + RVO22/flow/helper/db_helper.js | 44 + RVO22/flow/helper/logger.js | 30 + RVO22/flow/helper/md5.js | 5 + RVO22/flow/helper/notification_reporter.js | 121 + RVO22/flow/helper/register.js | 144 + RVO22/flow/helper/serialport_helper.js | 99 + RVO22/flow/helper/suncalc.js | 317 ++ RVO22/flow/helper/utils.js | 161 + RVO22/flow/httprequest.js | 137 + RVO22/flow/httpresponse.js | 76 + RVO22/flow/httproute.js | 326 ++ RVO22/flow/infosender.js | 81 + RVO22/flow/modbus_reader.js | 346 ++ RVO22/flow/monitorconsumption.js | 156 + RVO22/flow/monitordisk.js | 96 + RVO22/flow/monitormemory.js | 87 + RVO22/flow/nodesdb_changecheck.js | 77 + RVO22/flow/show_dbdata.js | 243 ++ RVO22/flow/slack_filter.js | 188 + RVO22/flow/thermometer.js | 99 + RVO22/flow/trigger.js | 79 + RVO22/flow/variables.txt | 0 RVO22/flow/virtualwirein.js | 43 + RVO22/flow/virtualwireout.js | 41 + RVO22/flow/wsmqttpublish.js | 448 +++ RVO22/monitor.txt | 314 ++ RVO22/package-lock.json | 2139 ++++++++++++ RVO22/package.json | 30 + RVO22/release.js | 15 + RVO22/release.js.json | 34 + RVO22/report_data.log | 178 + 60 files changed, 18685 insertions(+) create mode 100755 RVO22/addSwitch.py create mode 100755 RVO22/cloud_topic.py create mode 100755 RVO22/config create mode 100755 RVO22/createNode.py create mode 100755 RVO22/databases/accelerometer_db.js create mode 100755 RVO22/databases/modbus_config.js create mode 100755 RVO22/databases/nodes.table create mode 100755 RVO22/databases/nodes_original/nodes_original.table create mode 100755 RVO22/databases/notifications.table create mode 100755 RVO22/databases/pins.table create mode 100755 RVO22/databases/relays.table create mode 100755 RVO22/databases/settings.table create mode 100755 RVO22/databases/tbdata.nosql create mode 100755 RVO22/databases/tbdatacloud.nosql create mode 100755 RVO22/databases/total_energy.js create mode 100755 RVO22/debug.js create mode 100755 RVO22/err.txt create mode 100755 RVO22/flow/cloudmqttconnect.js create mode 100755 RVO22/flow/cmd_manager.js create mode 100755 RVO22/flow/code.js create mode 100755 RVO22/flow/comment.js create mode 100755 RVO22/flow/count.js create mode 100755 RVO22/flow/db_connector.js create mode 100755 RVO22/flow/db_init.js create mode 100755 RVO22/flow/debug.js create mode 100755 RVO22/flow/designer.json create mode 100755 RVO22/flow/dido_controller.js create mode 100755 RVO22/flow/helper/DataToTbHandler.js create mode 100755 RVO22/flow/helper/ErrorToServiceHandler.js create mode 100755 RVO22/flow/helper/db_helper.js create mode 100755 RVO22/flow/helper/logger.js create mode 100755 RVO22/flow/helper/md5.js create mode 100755 RVO22/flow/helper/notification_reporter.js create mode 100755 RVO22/flow/helper/register.js create mode 100755 RVO22/flow/helper/serialport_helper.js create mode 100755 RVO22/flow/helper/suncalc.js create mode 100755 RVO22/flow/helper/utils.js create mode 100755 RVO22/flow/httprequest.js create mode 100755 RVO22/flow/httpresponse.js create mode 100755 RVO22/flow/httproute.js create mode 100755 RVO22/flow/infosender.js create mode 100755 RVO22/flow/modbus_reader.js create mode 100755 RVO22/flow/monitorconsumption.js create mode 100755 RVO22/flow/monitordisk.js create mode 100755 RVO22/flow/monitormemory.js create mode 100755 RVO22/flow/nodesdb_changecheck.js create mode 100755 RVO22/flow/show_dbdata.js create mode 100755 RVO22/flow/slack_filter.js create mode 100755 RVO22/flow/thermometer.js create mode 100755 RVO22/flow/trigger.js create mode 100755 RVO22/flow/variables.txt create mode 100755 RVO22/flow/virtualwirein.js create mode 100755 RVO22/flow/virtualwireout.js create mode 100755 RVO22/flow/wsmqttpublish.js create mode 100755 RVO22/monitor.txt create mode 100755 RVO22/package-lock.json create mode 100755 RVO22/package.json create mode 100755 RVO22/release.js create mode 100755 RVO22/release.js.json create mode 100755 RVO22/report_data.log diff --git a/RVO22/addSwitch.py b/RVO22/addSwitch.py new file mode 100755 index 0000000..c35e96b --- /dev/null +++ b/RVO22/addSwitch.py @@ -0,0 +1,36 @@ +import os + +def process_set_file(): + """ + Checks if /root/flowserver exists, reads set.txt, and modifies the second line. + """ + default_folder = "/root/flowserver" if os.path.exists("/root/flowserver") else "/home/unipi/flowserver" + flag = 1 if default_folder == "/root/flowserver" else 0 + + try: + with open("/home/unipi/flowserver/databases/settings.table", "r") as f: + lines = f.readlines() + + if len(lines) >= 2: + lines[0] = lines[0].rstrip('\n') + "|main_switch:boolean\n" + second_line = lines[1].strip() # remove trailing newline + last_pipe_index = second_line.rfind("|") + + if last_pipe_index != -1: + modified_line = second_line[:last_pipe_index + 1] + str(flag) + "|" + second_line[last_pipe_index + 1:] + lines[1] = modified_line + else: + print("Warning: No '|' character found in the second line of set.txt") + + with open("/home/unipi/flowserver/databases/settings.table", "w") as f: + f.writelines(lines) + else: + print("Warning: settings.table has less than two lines.") + + except FileNotFoundError: + print("Error: settings.table not found.") + except Exception as e: + print(e) + +# if __name__ == "__main__": +process_set_file() diff --git a/RVO22/cloud_topic.py b/RVO22/cloud_topic.py new file mode 100755 index 0000000..77c31f1 --- /dev/null +++ b/RVO22/cloud_topic.py @@ -0,0 +1,76 @@ +# import os +# +# def modify_file(file_path): +# """ +# Modifies the given file by: +# 1. Appending "|cloud_topic" to the first line. +# 2. Inserting the text from the third "." to the first "|" on the second line after the last "|" character. +# +# Args: +# file_path (str): The path to the file to be modified. +# """ +# +# with open(file_path, 'r+') as f: +# lines = f.readlines() +# +# # Modify the first line +# lines[0] += "|cloud_topic:string" +# +# # Modify the second line +# second_line = lines[1].strip() # Remove leading/trailing whitespace +# first_pipe_index = second_line.find('|') +# third_dot_index = second_line.find('.', second_line.find('.', second_line.find('.') + 1) + 1) +# text_to_insert = second_line[third_dot_index:first_pipe_index] +# +# last_pipe_index = second_line.rfind('|') +# lines[1] = second_line[:last_pipe_index + 1] + text_to_insert + "|" + second_line[last_pipe_index + 1:] +# +# print(first_pipe_index, third_dot_index, text_to_insert, last_pipe_index) +# # Write the modified lines back to the file +# # f.seek(0) +# # f.writelines(lines) +# # f.truncate() +# +# # Example usage: +# file_path = "settings.table" # Replace with the actual file path +# modify_file(file_path) +# + + +def modify_file(file_path): + """ + Modifies the given file by: + 1. Appending "|cloud_topic" to the first line. + 2. Inserting the text between the third "." and the second "|" on the second line after the last "|" character. + + Args: + file_path (str): The path to the file to be modified. + """ + + with open(file_path, 'r+') as f: + lines = f.readlines() + + first_line = lines[0].strip() + first_line += "|cloud_topic:string\n" + # Modify the first line + lines[0] = first_line + + # Modify the second line + second_line = lines[1].strip() # Remove leading/trailing whitespace + first_pipe_index = second_line.find('|') + second_pipe_index = second_line.find('|', first_pipe_index + 1) + third_dot_index = second_line.find('.', second_line.find('.', second_line.find('.') + 1) + 1) + text_to_insert = "u" + second_line[third_dot_index+1:second_pipe_index] + + last_pipe_index = second_line.rfind('|') + lines[1] = second_line[:last_pipe_index + 1] + text_to_insert + "|" + second_line[last_pipe_index + 1:] + + print(first_pipe_index, third_dot_index, text_to_insert, last_pipe_index) + # Write the modified lines back to the file + f.seek(0) + f.writelines(lines) + f.truncate() + +# Example usage: +file_path = "/home/unipi/flowserver/databases/settings.table" # Replace with the actual file path +modify_file(file_path) diff --git a/RVO22/config b/RVO22/config new file mode 100755 index 0000000..cd0a8a9 --- /dev/null +++ b/RVO22/config @@ -0,0 +1,12 @@ +name : Total.js Flow +default_timezone : Europe/Bratislava + +// Packages settings +package#flow (Object) : { url: '/' } + + +table.relays : line:number|tbname:string|contactor:number|profile:string +table.nodes : node:number|pole_number:string|node_type:string|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|project_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|cloud_topic:string|has_main_switch:boolean|daily_report:boolean|send_changed_node_numbers:boolean +table.pins : pin:string|type:string|line:number +table.notifications : key:string|weight:string|sk:string|en:string diff --git a/RVO22/createNode.py b/RVO22/createNode.py new file mode 100755 index 0000000..a8cea91 --- /dev/null +++ b/RVO22/createNode.py @@ -0,0 +1,43 @@ +print("zaciname") +import re, json + +search_str = '|' +final = [] +counter = 1 +with open("/home/unipi/flowserver/databases/nodes.table", 'r') as file: +# with open("/home/rasta5man/dev/oms/flowserver/databases/nodes.table", 'r') as file: + # Read each line in the file + for line in file: + # Print each line + line = line.strip() + print(line) + if counter != 1: + i = [m.start() for m in re.finditer(re.escape(search_str), line)] + node = line[ i[0] + 1 : i[1] ] + tbname = line[ i[3] + 1 : i[4] ] + final.append({node:tbname}) + counter += 1 +print(json.dumps(final)) +f = open("/home/unipi/flowserver/databases/nodes_original/nodes_original.table", "w") +f.write(json.dumps(final)) +f.close() + + +# +# # ``d`` has to be replaced with a different character +# old_character = "'" +# +# # ``t`` will replace ``d` +# new_character = '"' +# resultant_string = 0; +# with open("/home/unipi/flowserver/databases/nodes_original/nodes_original.table", 'r') as file: +# for line in file: +# resultant_string = re.sub("'", '"', line) +# +# resultant_string = re.sub(" ", "", resultant_string) +# print(resultant_string) +# +# f = open("/home/unipi/flowserver/databases/nodes_original/nodes_original.table", "w") +# f.write(str(resultant_string)) +# f.close() +# diff --git a/RVO22/databases/accelerometer_db.js b/RVO22/databases/accelerometer_db.js new file mode 100755 index 0000000..fdfc7fd --- /dev/null +++ b/RVO22/databases/accelerometer_db.js @@ -0,0 +1,3055 @@ +let naklony = { + "3993": { "label": "1/3A", "naklon": 0 }, + "3989": { "label": "1/3B", "naklon": 15 }, + "3976": { "label": "1/1", "naklon": 0 }, + "4181": { "label": "1/2", "naklon": 0 }, + "4376": { "label": "1/4", "naklon": 15 }, + "3868": { "label": "1/5", "naklon": 15 }, + "3728": { "label": "1/6", "naklon": 15 }, + "3730": { "label": "1/7", "naklon": 0 }, + "4374": { "label": "1/8", "naklon": 0 }, + "3718": { "label": "1/9", "naklon": 15 }, + "4375": { "label": "1/10", "naklon": 15 }, + "4172": { "label": "1/11", "naklon": 15 }, + "4176": { "label": "1/12", "naklon": 15 }, + "3800": { "label": "2/1", "naklon": 5 }, + "3823": { "label": "2/2", "naklon": 5 }, + "3905": { "label": "2/3", "naklon": 5 }, + "3803": { "label": "2/4", "naklon": 5 }, + "3817": { "label": "2/5", "naklon": 5 }, + "3818": { "label": "2/6", "naklon": 5 }, + "3811": { "label": "2/7", "naklon": 5 }, + "3915": { "label": "2/8", "naklon": 5 }, + "3843": { "label": "2/9", "naklon": 10 }, + "3827": { "label": "2/10", "naklon": 10 }, + "4220": { "label": "2/11", "naklon": 10 }, + "3826": { "label": "2/12", "naklon": 10 }, + "3834": { "label": "2/13", "naklon": 10 }, + "3838": { "label": "2/14", "naklon": 10 }, + "2823": { "label": "2/15", "naklon": 10 }, + "3750": { "label": "2/16", "naklon": 10 }, + "3378": { "label": "2/17", "naklon": 0 }, + "3376": { "label": "2/18", "naklon": 0 }, + "3379": { "label": "2/19", "naklon": 0 }, + "3285": { "label": "2/20", "naklon": 0 }, + "3382": { "label": "2/21", "naklon": 0 }, + "3383": { "label": "2/22", "naklon": 0 }, + "3375": { "label": "2/24", "naklon": 0 }, + "3381": { "label": "2/25", "naklon": 0 }, + "3380": { "label": "2/26", "naklon": 0 }, + "3828": { "label": "2/27", "naklon": 10 }, + "3377": { "label": "2/28", "naklon": 0 }, + "3591": { "label": "7/1", "naklon": 0 }, + "3587": { "label": "7/2", "naklon": 0 }, + "3468": { "label": "7/3", "naklon": 0 }, + "3466": { "label": "7/4", "naklon": 0 }, + "3474": { "label": "7/5", "naklon": 0 }, + "3481": { "label": "7/6", "naklon": 0 }, + "3589": { "label": "7/7", "naklon": 0 }, + "3472": { "label": "7/8", "naklon": 0 }, + "3473": { "label": "7/9", "naklon": 0 }, + "3584": { "label": "7/10", "naklon": 0 }, + "3571": { "label": "7/11", "naklon": 0 }, + "3476": { "label": "7/12", "naklon": 0 }, + "3590": { "label": "7/13", "naklon": 0 }, + "3478": { "label": "7/14", "naklon": 0 }, + "3471": { "label": "7/15", "naklon": 0 }, + "3467": { "label": "7/16", "naklon": 0 }, + "3479": { "label": "7/17", "naklon": 0 }, + "3480": { "label": "7/18", "naklon": 0 }, + "3477": { "label": "7/19", "naklon": 0 }, + "3362": { "label": "12/1", "naklon": 0 }, + "3355": { "label": "12/2", "naklon": 0 }, + "3356": { "label": "12/3", "naklon": 0 }, + "3349": { "label": "12/4", "naklon": 0 }, + "3357": { "label": "12/5", "naklon": 0 }, + "3350": { "label": "12/6", "naklon": 0 }, + "3353": { "label": "12/7", "naklon": 0 }, + "3539": { "label": "12/8", "naklon": 0 }, + "3050": { "label": "12/9", "naklon": 0 }, + "3361": { "label": "12/10", "naklon": 0 }, + "3360": { "label": "12/11", "naklon": 0 }, + "3358": { "label": "12/12", "naklon": 0 }, + "3541": { "label": "12/13", "naklon": 0 }, + "3551": { "label": "12/14", "naklon": 0 }, + "3514": { "label": "12/15", "naklon": 0 }, + "3547": { "label": "12/16", "naklon": 0 }, + "3562": { "label": "12/17", "naklon": 0 }, + "3525": { "label": "12/18", "naklon": 0 }, + "3558": { "label": "12/19", "naklon": 0 }, + "3511": { "label": "12/20", "naklon": 0 }, + "3058": { "label": "12/21", "naklon": 0 }, + "3062": { "label": "12/22", "naklon": 0 }, + "3070": { "label": "12/23", "naklon": 0 }, + "3447": { "label": "12/24", "naklon": 0 }, + "3056": { "label": "12/25", "naklon": 0 }, + "3057": { "label": "12/26", "naklon": 0 }, + "3071": { "label": "12/27", "naklon": 0 }, + "3061": { "label": "12/28", "naklon": 0 }, + "3069": { "label": "12/29", "naklon": 0 }, + "3077": { "label": "12/30", "naklon": 0 }, + "3080": { "label": "12/31", "naklon": 0 }, + "3081": { "label": "12/32", "naklon": 0 }, + "3078": { "label": "12/33", "naklon": 0 }, + "4037": { "label": "12/34", "naklon": 0 }, + "3067": { "label": "12/35", "naklon": 0 }, + "3051": { "label": "12/36", "naklon": 0 }, + "2924": { "label": "12/37", "naklon": 0 }, + "3060": { "label": "12/38", "naklon": 0 }, + "3073": { "label": "12/39", "naklon": 0 }, + "3469": { "label": "12/40", "naklon": 0 }, + "2923": { "label": "12/41", "naklon": 0 }, + "2925": { "label": "12/42", "naklon": 0 }, + "3359": { "label": "12/43", "naklon": 0 }, + "3055": { "label": "12/44", "naklon": 0 }, + "2922": { "label": "12/45", "naklon": 0 }, + "3084": { "label": "12/46", "naklon": 0 }, + "3064": { "label": "12/47", "naklon": 0 }, + "3066": { "label": "12/48", "naklon": 0 }, + "3072": { "label": "12/49", "naklon": 0 }, + "3415": { "label": "13/13A", "naklon": 0 }, + "3409": { "label": "13/13B", "naklon": 0 }, + "3399": { "label": "13/13C", "naklon": 0 }, + "3410": { "label": "13/29A", "naklon": 0 }, + "3407": { "label": "13/29B", "naklon": 0 }, + "3405": { "label": "13/34A", "naklon": 0 }, + "3404": { "label": "13/34B", "naklon": 0 }, + "3392": { "label": "13/45A", "naklon": 0 }, + "3386": { "label": "13/45B", "naklon": 0 }, + "3303": { "label": "13/60A", "naklon": 3 }, + "3302": { "label": "13/60B", "naklon": 3 }, + "3319": { "label": "13/70A", "naklon": 6 }, + "3317": { "label": "13/70B", "naklon": 6 }, + "3326": { "label": "13/70C", "naklon": 6 }, + "3351": { "label": "13/73A", "naklon": 6 }, + "3313": { "label": "13/73B", "naklon": 6 }, + "3316": { "label": "13/83A", "naklon": 0 }, + "3320": { "label": "13/83B", "naklon": 0 }, + "3336": { "label": "13/95A", "naklon": 0 }, + "3323": { "label": "13/95B", "naklon": 0 }, + "3339": { "label": "13/98A", "naklon": 0 }, + "3333": { "label": "13/98B", "naklon": 0 }, + "3425": { "label": "13/1", "naklon": 0 }, + "3419": { "label": "13/2", "naklon": 0 }, + "3416": { "label": "13/3", "naklon": 0 }, + "3332": { "label": "13/4", "naklon": 0 }, + "3422": { "label": "13/5", "naklon": 0 }, + "3417": { "label": "13/6", "naklon": 0 }, + "3418": { "label": "13/7", "naklon": 0 }, + "3424": { "label": "13/8", "naklon": 0 }, + "3334": { "label": "13/9", "naklon": 0 }, + "4363": { "label": "13/10", "naklon": 0 }, + "3423": { "label": "13/11", "naklon": 0 }, + "3406": { "label": "13/12", "naklon": 0 }, + "3411": { "label": "13/14", "naklon": 0 }, + "3412": { "label": "13/15", "naklon": 0 }, + "3413": { "label": "13/16", "naklon": 0 }, + "3414": { "label": "13/17", "naklon": 0 }, + "3391": { "label": "13/18", "naklon": 0 }, + "3370": { "label": "13/19", "naklon": 0 }, + "3369": { "label": "13/20", "naklon": 0 }, + "3408": { "label": "13/21", "naklon": 0 }, + "3393": { "label": "13/22", "naklon": 0 }, + "3128": { "label": "13/23", "naklon": 0 }, + "3197": { "label": "13/24", "naklon": 0 }, + "4364": { "label": "13/25", "naklon": 0 }, + "3155": { "label": "13/26", "naklon": 0 }, + "3196": { "label": "13/27", "naklon": 0 }, + "3144": { "label": "13/28", "naklon": 0 }, + "3150": { "label": "13/30", "naklon": 0 }, + "3390": { "label": "13/31", "naklon": 0 }, + "3401": { "label": "13/32", "naklon": 0 }, + "3275": { "label": "13/33", "naklon": 0 }, + "3371": { "label": "13/35", "naklon": 0 }, + "3389": { "label": "13/36", "naklon": 0 }, + "3388": { "label": "13/37", "naklon": 0 }, + "3365": { "label": "13/38", "naklon": 0 }, + "3363": { "label": "13/39", "naklon": 0 }, + "3397": { "label": "13/40", "naklon": 0 }, + "3567": { "label": "13/40/1", "naklon": 0 }, + "3387": { "label": "13/41", "naklon": 0 }, + "3403": { "label": "13/42", "naklon": 0 }, + "3147": { "label": "13/43", "naklon": 0 }, + "3141": { "label": "13/44", "naklon": 0 }, + "3364": { "label": "13/46", "naklon": 0 }, + "3367": { "label": "13/47", "naklon": 0 }, + "3368": { "label": "13/48", "naklon": 0 }, + "3402": { "label": "13/49", "naklon": 0 }, + "3366": { "label": "13/50", "naklon": 0 }, + "3395": { "label": "13/51", "naklon": 0 }, + "3372": { "label": "13/52", "naklon": 0 }, + "3394": { "label": "13/53", "naklon": 0 }, + "3308": { "label": "13/54", "naklon": 0 }, + "3847": { "label": "13/54/1", "naklon": 0 }, + "3312": { "label": "13/55", "naklon": 3 }, + "3309": { "label": "13/56", "naklon": 3 }, + "3311": { "label": "13/57", "naklon": 3 }, + "3310": { "label": "13/58", "naklon": 3 }, + "4365": { "label": "13/59", "naklon": 3 }, + "4093": { "label": "13/60/1", "naklon": 3 }, + "3304": { "label": "13/61", "naklon": 3 }, + "3307": { "label": "13/62", "naklon": 3 }, + "3271": { "label": "13/63", "naklon": 3 }, + "3301": { "label": "13/64", "naklon": 3 }, + "4366": { "label": "13/65", "naklon": 3 }, + "3300": { "label": "13/66", "naklon": 3 }, + "3185": { "label": "13/67", "naklon": 0 }, + "3184": { "label": "13/68", "naklon": 0 }, + "3188": { "label": "13/69", "naklon": 0 }, + "3343": { "label": "13/71", "naklon": 6 }, + "3819": { "label": "13/71/1", "naklon": 6 }, + "3880": { "label": "13/71/2", "naklon": 6 }, + "3348": { "label": "13/72", "naklon": 6 }, + "3344": { "label": "13/74", "naklon": 6 }, + "3346": { "label": "13/75", "naklon": 6 }, + "3597": { "label": "13/75/1", "naklon": 6 }, + "3345": { "label": "13/76", "naklon": 6 }, + "3322": { "label": "13/77", "naklon": 0 }, + "3325": { "label": "13/78", "naklon": 0 }, + "4310": { "label": "13/78/1", "naklon": 0 }, + "3315": { "label": "13/79", "naklon": 0 }, + "3328": { "label": "13/80", "naklon": 0 }, + "3321": { "label": "13/81", "naklon": 0 }, + "3324": { "label": "13/82", "naklon": 0 }, + "3140": { "label": "13/84", "naklon": 0 }, + "3153": { "label": "13/85", "naklon": 0 }, + "3145": { "label": "13/86", "naklon": 0 }, + "3134": { "label": "13/87", "naklon": 0 }, + "3151": { "label": "13/88", "naklon": 0 }, + "3143": { "label": "13/89", "naklon": 0 }, + "3318": { "label": "13/90", "naklon": 0 }, + "3347": { "label": "13/91", "naklon": 0 }, + "3314": { "label": "13/94", "naklon": 0 }, + "3331": { "label": "13/96", "naklon": 0 }, + "3327": { "label": "13/97", "naklon": 0 }, + "3329": { "label": "13/99", "naklon": 0 }, + "3337": { "label": "13/100", "naklon": 0 }, + "3330": { "label": "13/101", "naklon": 0 }, + "3335": { "label": "13/102", "naklon": 0 }, + "3420": { "label": "13/103", "naklon": 0 }, + "3421": { "label": "13/104", "naklon": 0 }, + "4361": { "label": "13/105", "naklon": 0 }, + "4362": { "label": "13/106", "naklon": 0 }, + "3526": { "label": "13/107", "naklon": 0 }, + "4424": { "label": "13/108", "naklon": null }, + "3561": { "label": "13/109", "naklon": null }, + "3527": { "label": "13/110", "naklon": null }, + "3521": { "label": "13/111", "naklon": null }, + "3552": { "label": "13/112", "naklon": null }, + "3544": { "label": "13/113", "naklon": null }, + "3534": { "label": "13/114", "naklon": null }, + "3516": { "label": "13/115", "naklon": null }, + "3513": { "label": "13/116", "naklon": null }, + "3565": { "label": "13/117", "naklon": null }, + "3866": { "label": "13/118", "naklon": null }, + "3136": { "label": "14/1", "naklon": 0 }, + "3137": { "label": "14/2", "naklon": 0 }, + "3135": { "label": "14/3", "naklon": 0 }, + "3149": { "label": "14/4", "naklon": 0 }, + "3142": { "label": "14/5", "naklon": 0 }, + "3342": { "label": "14/6", "naklon": 0 }, + "3340": { "label": "14/7", "naklon": 0 }, + "3152": { "label": "14/8", "naklon": 0 }, + "3886": { "label": "14/9", "naklon": 0 }, + "3341": { "label": "14/10", "naklon": null }, + "3352": { "label": "14/11", "naklon": null }, + "3396": { "label": "15/1", "naklon": 5 }, + "2784": { "label": "15/2", "naklon": 5 }, + "2788": { "label": "15/3", "naklon": 5 }, + "2801": { "label": "15/4", "naklon": 5 }, + "2815": { "label": "15/5", "naklon": 5 }, + "2829": { "label": "15/6", "naklon": 5 }, + "2796": { "label": "15/7", "naklon": 5 }, + "2803": { "label": "15/8", "naklon": 5 }, + "4304": { "label": "15/8/1", "naklon": 5 }, + "4311": { "label": "15/8/2", "naklon": 5 }, + "2821": { "label": "15/9", "naklon": 5 }, + "3400": { "label": "15/10", "naklon": 5 }, + "2799": { "label": "15/11", "naklon": 5 }, + "2804": { "label": "15/12", "naklon": 5 }, + "4303": { "label": "15/12/1", "naklon": 5 }, + "4309": { "label": "15/12/2", "naklon": 5 }, + "2806": { "label": "15/13", "naklon": 5 }, + "2787": { "label": "15/14", "naklon": 5 }, + "2809": { "label": "15/15", "naklon": 5 }, + "2814": { "label": "15/16", "naklon": 0 }, + "3934": { "label": "15/17", "naklon": 0 }, + "3192": { "label": "15/18", "naklon": 0 }, + "2812": { "label": "15/19", "naklon": 0 }, + "4070": { "label": "15/20", "naklon": 0 }, + "2826": { "label": "15/21", "naklon": 0 }, + "2808": { "label": "15/22", "naklon": 3 }, + "2795": { "label": "15/23", "naklon": 3 }, + "2807": { "label": "15/24", "naklon": 3 }, + "2831": { "label": "15/25", "naklon": 0 }, + "2862": { "label": "15/26", "naklon": null }, + "2861": { "label": "15/27", "naklon": 0 }, + "2866": { "label": "15/28", "naklon": 0 }, + "3546": { "label": "15/28/1", "naklon": 0 }, + "4146": { "label": "15/29", "naklon": 0 }, + "3001": { "label": "15/29/1", "naklon": 0 }, + "2835": { "label": "15/30", "naklon": 0 }, + "2874": { "label": "15/31", "naklon": 0 }, + "2852": { "label": "15/32", "naklon": 0 }, + "2851": { "label": "15/33", "naklon": 0 }, + "3560": { "label": "15/33/1", "naklon": 0 }, + "2858": { "label": "15/34", "naklon": 0 }, + "4306": { "label": "15/34/1", "naklon": 0 }, + "2856": { "label": "15/35", "naklon": 0 }, + "2847": { "label": "15/36", "naklon": 0 }, + "3556": { "label": "15/36/1", "naklon": 0 }, + "3950": { "label": "15/37", "naklon": 0 }, + "2848": { "label": "15/38", "naklon": 0 }, + "2863": { "label": "15/39", "naklon": 0 }, + "4313": { "label": "15/39/1", "naklon": 0 }, + "2873": { "label": "15/40", "naklon": 0 }, + "2984": { "label": "15/40/1", "naklon": 0 }, + "2854": { "label": "15/41", "naklon": 0 }, + "2859": { "label": "15/42", "naklon": 0 }, + "2872": { "label": "15/43", "naklon": 0 }, + "2849": { "label": "15/44", "naklon": 0 }, + "2864": { "label": "15/45", "naklon": 0 }, + "3553": { "label": "15/46", "naklon": null }, + "3021": { "label": "15/47", "naklon": null }, + "3008": { "label": "15/47/1", "naklon": null }, + "3017": { "label": "15/48", "naklon": null }, + "3014": { "label": "15/49", "naklon": null }, + "2981": { "label": "15/50", "naklon": null }, + "3020": { "label": "15/51", "naklon": null }, + "3027": { "label": "15/52", "naklon": null }, + "3006": { "label": "15/53", "naklon": null }, + "3012": { "label": "15/54", "naklon": null }, + "2738": { "label": "15/55", "naklon": 0 }, + "2725": { "label": "15/56", "naklon": 0 }, + "3016": { "label": "15/57", "naklon": null }, + "3005": { "label": "15/58", "naklon": null }, + "3009": { "label": "15/58/1", "naklon": null }, + "3010": { "label": "15/59", "naklon": 0 }, + "3538": { "label": "15/59/1", "naklon": 0 }, + "4145": { "label": "15/59/2", "naklon": 0 }, + "2713": { "label": "15/60", "naklon": 0 }, + "2789": { "label": "15/61", "naklon": 0 }, + "2736": { "label": "15/62", "naklon": 0 }, + "2739": { "label": "15/63", "naklon": 0 }, + "4346": { "label": "15/64", "naklon": 0 }, + "2731": { "label": "15/65", "naklon": 0 }, + "2818": { "label": "15/66", "naklon": 0 }, + "3557": { "label": "15/66/1", "naklon": 0 }, + "2822": { "label": "15/67", "naklon": 0 }, + "2833": { "label": "15/68", "naklon": 0 }, + "2834": { "label": "15/69", "naklon": 0 }, + "3097": { "label": "15/70", "naklon": 0 }, + "2824": { "label": "15/71", "naklon": 0 }, + "2828": { "label": "15/72", "naklon": 0 }, + "2600": { "label": "15/73", "naklon": 0 }, + "4314": { "label": "15/73/1", "naklon": 0 }, + "2832": { "label": "15/74", "naklon": 0 }, + "4360": { "label": "15/75", "naklon": 0 }, + "2846": { "label": "15/76", "naklon": 0 }, + "2584": { "label": "15/77", "naklon": 0 }, + "2843": { "label": "15/78", "naklon": 0 }, + "4308": { "label": "15/78/1", "naklon": 0 }, + "4144": { "label": "15/79", "naklon": null }, + "2844": { "label": "15/80", "naklon": 0 }, + "2842": { "label": "15/81", "naklon": 0 }, + "2838": { "label": "15/82", "naklon": 0 }, + "2837": { "label": "15/83", "naklon": null }, + "3555": { "label": "15/83/1", "naklon": null }, + "2839": { "label": "15/84", "naklon": 0 }, + "2830": { "label": "15/85", "naklon": 0 }, + "4066": { "label": "15/86", "naklon": 0 }, + "2836": { "label": "15/87", "naklon": 0 }, + "2911": { "label": "15/88", "naklon": 0 }, + "2825": { "label": "15/89", "naklon": 0 }, + "2811": { "label": "15/90", "naklon": 0 }, + "3740": { "label": "15/94", "naklon": 15 }, + "2734": { "label": "15/95", "naklon": 15 }, + "3105": { "label": "15/96", "naklon": 15 }, + "2732": { "label": "15/97", "naklon": 15 }, + "2727": { "label": "15/98", "naklon": 15 }, + "2735": { "label": "15/99", "naklon": 15 }, + "3926": { "label": "15/100", "naklon": 15 }, + "2918": { "label": "15/101", "naklon": 0 }, + "2705": { "label": "15/102", "naklon": 10 }, + "2708": { "label": "15/103", "naklon": 10 }, + "2721": { "label": "15/104", "naklon": 10 }, + "2719": { "label": "15/105", "naklon": 10 }, + "2919": { "label": "15/106", "naklon": 10 }, + "3101": { "label": "15/107", "naklon": 10 }, + "2853": { "label": "15/108", "naklon": 10 }, + "2715": { "label": "15/109", "naklon": 10 }, + "2712": { "label": "15/110", "naklon": 0 }, + "2711": { "label": "15/111", "naklon": 0 }, + "2709": { "label": "15/112", "naklon": 0 }, + "2710": { "label": "15/113", "naklon": 0 }, + "2907": { "label": "15/114", "naklon": 0 }, + "2906": { "label": "15/115", "naklon": 0 }, + "2908": { "label": "15/116", "naklon": 0 }, + "2901": { "label": "15/117", "naklon": 0 }, + "2913": { "label": "15/118", "naklon": 0 }, + "3656": { "label": "15/119", "naklon": 0 }, + "2781": { "label": "15/120", "naklon": 0 }, + "2802": { "label": "15/121", "naklon": 0 }, + "2791": { "label": "15/122", "naklon": 0 }, + "2783": { "label": "15/123", "naklon": 0 }, + "2794": { "label": "15/124", "naklon": 0 }, + "3139": { "label": "15/125", "naklon": 0 }, + "3229": { "label": "15/126", "naklon": 5 }, + "3239": { "label": "15/127", "naklon": 5 }, + "3230": { "label": "15/128", "naklon": 5 }, + "4016": { "label": "15/129", "naklon": null }, + "3608": { "label": "16/16A", "naklon": 0 }, + "4151": { "label": "16/16B", "naklon": 0 }, + "3710": { "label": "16/1", "naklon": 0 }, + "3726": { "label": "16/2", "naklon": 0 }, + "3743": { "label": "16/3", "naklon": 0 }, + "3724": { "label": "16/4", "naklon": 0 }, + "3712": { "label": "16/5", "naklon": 0 }, + "3739": { "label": "16/6", "naklon": 0 }, + "3742": { "label": "16/7", "naklon": 0 }, + "3731": { "label": "16/8", "naklon": 0 }, + "3727": { "label": "16/9", "naklon": 0 }, + "3729": { "label": "16/10", "naklon": 0 }, + "3736": { "label": "16/11", "naklon": 0 }, + "3713": { "label": "16/12", "naklon": 0 }, + "3715": { "label": "16/13", "naklon": 0 }, + "3733": { "label": "16/14", "naklon": 0 }, + "3732": { "label": "16/15", "naklon": 0 }, + "3634": { "label": "16/17", "naklon": 0 }, + "3610": { "label": "16/18", "naklon": 0 }, + "3626": { "label": "16/19", "naklon": 0 }, + "3618": { "label": "16/20", "naklon": 0 }, + "3619": { "label": "16/21", "naklon": 0 }, + "3628": { "label": "16/22", "naklon": 0 }, + "3615": { "label": "16/23", "naklon": 0 }, + "3609": { "label": "16/24", "naklon": 0 }, + "3606": { "label": "16/25", "naklon": 0 }, + "3624": { "label": "16/26", "naklon": 0 }, + "3627": { "label": "16/27", "naklon": 0 }, + "3607": { "label": "16/28", "naklon": 0 }, + "4370": { "label": "16/29", "naklon": 0 }, + "3692": { "label": "16/30", "naklon": 0 }, + "3614": { "label": "16/31", "naklon": 0 }, + "3623": { "label": "16/32", "naklon": 0 }, + "4373": { "label": "16/33", "naklon": 0 }, + "3620": { "label": "16/34", "naklon": 0 }, + "3685": { "label": "16/35", "naklon": 0 }, + "3616": { "label": "16/36", "naklon": 0 }, + "3686": { "label": "16/37", "naklon": 0 }, + "3688": { "label": "16/38", "naklon": 0 }, + "3684": { "label": "16/39", "naklon": 0 }, + "3825": { "label": "16/40", "naklon": 0 }, + "3865": { "label": "16/41", "naklon": 0 }, + "3824": { "label": "16/42", "naklon": 0 }, + "3871": { "label": "16/43", "naklon": 0 }, + "3801": { "label": "16/44", "naklon": 0 }, + "3862": { "label": "16/45", "naklon": 0 }, + "3876": { "label": "16/46", "naklon": 0 }, + "3861": { "label": "16/47", "naklon": 0 }, + "4215": { "label": "16/48", "naklon": 0 }, + "3605": { "label": "16/49", "naklon": 10 }, + "3603": { "label": "16/50", "naklon": 10 }, + "3592": { "label": "16/51", "naklon": 10 }, + "3598": { "label": "16/52", "naklon": 10 }, + "3594": { "label": "16/53", "naklon": 10 }, + "3593": { "label": "16/54", "naklon": 10 }, + "3630": { "label": "16/55", "naklon": 10 }, + "3763": { "label": "16/56", "naklon": 10 }, + "3746": { "label": "16/57", "naklon": 10 }, + "3699": { "label": "16/58", "naklon": 0 }, + "3698": { "label": "16/59", "naklon": 0 }, + "3709": { "label": "16/60", "naklon": null }, + "3708": { "label": "16/61", "naklon": 0 }, + "3703": { "label": "16/62", "naklon": null }, + "3700": { "label": "16/63", "naklon": 0 }, + "3701": { "label": "16/64", "naklon": null }, + "3704": { "label": "16/65", "naklon": 0 }, + "3707": { "label": "16/66", "naklon": null }, + "3810": { "label": "16/67", "naklon": 0 }, + "4208": { "label": "16/68", "naklon": null }, + "3867": { "label": "16/69", "naklon": 0 }, + "4372": { "label": "16/70", "naklon": null }, + "3881": { "label": "16/71", "naklon": 0 }, + "4204": { "label": "16/72", "naklon": null }, + "3869": { "label": "16/73", "naklon": 0 }, + "4202": { "label": "16/74", "naklon": null }, + "3830": { "label": "16/75", "naklon": 0 }, + "3870": { "label": "16/76", "naklon": null }, + "3964": { "label": "16/77", "naklon": 0 }, + "3849": { "label": "16/78", "naklon": 0 }, + "3694": { "label": "16/79", "naklon": null }, + "3717": { "label": "16/80", "naklon": 0 }, + "3877": { "label": "16/81", "naklon": null }, + "3755": { "label": "16/82", "naklon": 0 }, + "3725": { "label": "16/83", "naklon": null }, + "3716": { "label": "16/84", "naklon": 0 }, + "3696": { "label": "16/85", "naklon": null }, + "3702": { "label": "16/86", "naklon": 0 }, + "3706": { "label": "16/87", "naklon": null }, + "3850": { "label": "16/88", "naklon": 0 }, + "3848": { "label": "16/89", "naklon": null }, + "3737": { "label": "16/90", "naklon": null }, + "3705": { "label": "16/91", "naklon": 0 }, + "3723": { "label": "16/92", "naklon": null }, + "3842": { "label": "16/93", "naklon": 0 }, + "3735": { "label": "16/94", "naklon": null }, + "3719": { "label": "16/95", "naklon": 0 }, + "3697": { "label": "16/96", "naklon": 0 }, + "3711": { "label": "16/97", "naklon": 0 }, + "4107": { "label": "16/98", "naklon": null }, + "4112": { "label": "16/99", "naklon": 5 }, + "4106": { "label": "16/100", "naklon": 5 }, + "4111": { "label": "16/101", "naklon": 5 }, + "4091": { "label": "16/102", "naklon": null }, + "4104": { "label": "16/103", "naklon": 5 }, + "4094": { "label": "16/104", "naklon": null }, + "4089": { "label": "16/105", "naklon": 5 }, + "4095": { "label": "16/106", "naklon": null }, + "4102": { "label": "16/107", "naklon": 5 }, + "4105": { "label": "16/108", "naklon": null }, + "3859": { "label": "16/109", "naklon": null }, + "4090": { "label": "16/110", "naklon": 5 }, + "4110": { "label": "16/111", "naklon": null }, + "4097": { "label": "16/112", "naklon": 5 }, + "4099": { "label": "16/113", "naklon": null }, + "4096": { "label": "16/114", "naklon": null }, + "4101": { "label": "16/115", "naklon": 5 }, + "4109": { "label": "16/116", "naklon": null }, + "4092": { "label": "16/117", "naklon": 5 }, + "3631": { "label": "16/118", "naklon": null }, + "3632": { "label": "16/119", "naklon": 0 }, + "3641": { "label": "16/120", "naklon": null }, + "3638": { "label": "16/121", "naklon": 0 }, + "3637": { "label": "16/122", "naklon": null }, + "4142": { "label": "16/123", "naklon": null }, + "4147": { "label": "16/124", "naklon": 5 }, + "4139": { "label": "16/125", "naklon": 5 }, + "3172": { "label": "20/30A", "naklon": 2 }, + "3164": { "label": "20/30B", "naklon": 2 }, + "3247": { "label": "20/1", "naklon": 10 }, + "3296": { "label": "20/2", "naklon": 10 }, + "3246": { "label": "20/3", "naklon": 10 }, + "3270": { "label": "20/4", "naklon": 10 }, + "3294": { "label": "20/5", "naklon": 10 }, + "3298": { "label": "20/6", "naklon": 10 }, + "3297": { "label": "20/7", "naklon": 10 }, + "3293": { "label": "20/8", "naklon": 10 }, + "3299": { "label": "20/9", "naklon": 10 }, + "3295": { "label": "20/10", "naklon": 10 }, + "3244": { "label": "20/11", "naklon": 10 }, + "3249": { "label": "20/12", "naklon": 10 }, + "3268": { "label": "20/13", "naklon": 10 }, + "3245": { "label": "20/14", "naklon": 10 }, + "3278": { "label": "20/15", "naklon": 10 }, + "3280": { "label": "20/16", "naklon": 10 }, + "3292": { "label": "20/17", "naklon": 10 }, + "3287": { "label": "20/18", "naklon": 10 }, + "3282": { "label": "20/19", "naklon": 10 }, + "3273": { "label": "20/20", "naklon": 0 }, + "3157": { "label": "20/21", "naklon": 0 }, + "3283": { "label": "20/22", "naklon": 0 }, + "3159": { "label": "20/23", "naklon": 0 }, + "3289": { "label": "20/24", "naklon": 0 }, + "3163": { "label": "20/25", "naklon": 0 }, + "3126": { "label": "20/26", "naklon": 0 }, + "3171": { "label": "20/27", "naklon": 0 }, + "3162": { "label": "20/28", "naklon": 0 }, + "3279": { "label": "20/29", "naklon": 10 }, + "3173": { "label": "20/31", "naklon": 0 }, + "3127": { "label": "20/32", "naklon": 0 }, + "3131": { "label": "20/33", "naklon": 0 }, + "3129": { "label": "20/34", "naklon": 0 }, + "3276": { "label": "20/35", "naklon": 2 }, + "3290": { "label": "20/36", "naklon": 2 }, + "3132": { "label": "20/37", "naklon": 0 }, + "3138": { "label": "20/38", "naklon": 0 }, + "3272": { "label": "20/39", "naklon": 0 }, + "3291": { "label": "20/40", "naklon": 0 }, + "3277": { "label": "20/41", "naklon": 10 }, + "3286": { "label": "20/42", "naklon": 10 }, + "3281": { "label": "20/43", "naklon": 10 }, + "3288": { "label": "20/44", "naklon": 10 }, + "3284": { "label": "20/45", "naklon": 10 }, + "3167": { "label": "20/46", "naklon": 10 }, + "3872": { "label": "20/47", "naklon": 0 }, + "3124": { "label": "20/48", "naklon": 0 }, + "3133": { "label": "20/49", "naklon": 0 }, + "3158": { "label": "20/50", "naklon": 0 }, + "3169": { "label": "20/51", "naklon": 0 }, + "3146": { "label": "20/52", "naklon": 0 }, + "3160": { "label": "20/53", "naklon": 0 }, + "3248": { "label": "20/54", "naklon": 0 }, + "3156": { "label": "20/55", "naklon": 0 }, + "3161": { "label": "20/56", "naklon": 0 }, + "3170": { "label": "20/57", "naklon": 0 }, + "3168": { "label": "20/58", "naklon": 0 }, + "3125": { "label": "20/59", "naklon": 0 }, + "3166": { "label": "20/60", "naklon": 0 }, + "3130": { "label": "20/61", "naklon": 0 }, + "3563": { "label": "20/62", "naklon": 0 }, + "3550": { "label": "20/63", "naklon": null }, + "3269": { "label": "20/67", "naklon": 0 }, + "2921": { "label": "21/1", "naklon": 0 }, + "2707": { "label": "21/2", "naklon": 0 }, + "2723": { "label": "21/3", "naklon": 0 }, + "2716": { "label": "21/4", "naklon": 0 }, + "2717": { "label": "21/5", "naklon": 0 }, + "2720": { "label": "21/6", "naklon": 0 }, + "2722": { "label": "21/7", "naklon": 0 }, + "2718": { "label": "21/8", "naklon": 0 }, + "2724": { "label": "21/9", "naklon": 0 }, + "2742": { "label": "21/10", "naklon": 0 }, + "2743": { "label": "21/11", "naklon": 0 }, + "2733": { "label": "21/12", "naklon": 0 }, + "2903": { "label": "21/14", "naklon": 0 }, + "2917": { "label": "21/15", "naklon": 0 }, + "2897": { "label": "21/16", "naklon": 0 }, + "2914": { "label": "21/17", "naklon": 0 }, + "2898": { "label": "21/18", "naklon": 0 }, + "2773": { "label": "21/19", "naklon": 0 }, + "2895": { "label": "21/20", "naklon": 0 }, + "2896": { "label": "21/21", "naklon": 0 }, + "2771": { "label": "21/22", "naklon": 0 }, + "2772": { "label": "21/23", "naklon": 0 }, + "2793": { "label": "21/24", "naklon": 0 }, + "2902": { "label": "21/25", "naklon": 0 }, + "2910": { "label": "21/26", "naklon": 0 }, + "2909": { "label": "21/27", "naklon": 0 }, + "2920": { "label": "21/28", "naklon": 0 }, + "2916": { "label": "21/29", "naklon": 0 }, + "2904": { "label": "21/30", "naklon": 0 }, + "2915": { "label": "21/31", "naklon": 0 }, + "2905": { "label": "21/32", "naklon": 0 }, + "2900": { "label": "21/33", "naklon": 0 }, + "2899": { "label": "21/34", "naklon": 0 }, + "2741": { "label": "21/36", "naklon": 0 }, + "2714": { "label": "21/37", "naklon": 0 }, + "2701": { "label": "21/38", "naklon": 0 }, + "2703": { "label": "21/39", "naklon": 0 }, + "2704": { "label": "21/40", "naklon": 0 }, + "2702": { "label": "21/41", "naklon": 0 }, + "2706": { "label": "21/42", "naklon": 0 }, + "2776": { "label": "21/43", "naklon": 0 }, + "2770": { "label": "21/44", "naklon": 0 }, + "2786": { "label": "21/45", "naklon": 0 }, + "2779": { "label": "21/46", "naklon": 0 }, + "2782": { "label": "21/47", "naklon": 0 }, + "2785": { "label": "21/48", "naklon": 0 }, + "2769": { "label": "21/49", "naklon": 0 }, + "3354": { "label": "21/50", "naklon": 0 }, + "2778": { "label": "21/51", "naklon": 0 }, + "2775": { "label": "21/52", "naklon": 0 }, + "2780": { "label": "21/53", "naklon": 0 }, + "2790": { "label": "21/54", "naklon": 0 }, + "2792": { "label": "21/55", "naklon": 0 }, + "2774": { "label": "21/56", "naklon": 0 }, + "2630": { "label": "22/1", "naklon": 0 }, + "2631": { "label": "22/2", "naklon": 0 }, + "2632": { "label": "22/3", "naklon": 0 }, + "2633": { "label": "22/4", "naklon": 0 }, + "2634": { "label": "22/5", "naklon": 0 }, + "2636": { "label": "22/6", "naklon": 0 }, + "4367": { "label": "22/7", "naklon": 0 }, + "2637": { "label": "22/8", "naklon": 0 }, + "2638": { "label": "22/9", "naklon": 0 }, + "2639": { "label": "22/10", "naklon": 0 }, + "2640": { "label": "22/11", "naklon": 0 }, + "2641": { "label": "22/12", "naklon": 0 }, + "2642": { "label": "22/13", "naklon": 0 }, + "2643": { "label": "22/14", "naklon": 0 }, + "2644": { "label": "22/15", "naklon": 0 }, + "2645": { "label": "22/16", "naklon": 0 }, + "2646": { "label": "22/17", "naklon": 0 }, + "2647": { "label": "22/18", "naklon": 0 }, + "2648": { "label": "22/19", "naklon": 0 }, + "2649": { "label": "22/20", "naklon": 0 }, + "2650": { "label": "22/21", "naklon": 0 }, + "2651": { "label": "22/22", "naklon": 0 }, + "4103": { "label": "22/23", "naklon": 0 }, + "2653": { "label": "22/24", "naklon": 0 }, + "2654": { "label": "22/25", "naklon": 0 }, + "2655": { "label": "22/26", "naklon": 0 }, + "2656": { "label": "22/27", "naklon": 0 }, + "2657": { "label": "22/28", "naklon": 0 }, + "2658": { "label": "22/29", "naklon": 0 }, + "2659": { "label": "22/30", "naklon": 0 }, + "2660": { "label": "22/31", "naklon": 0 }, + "2661": { "label": "22/32", "naklon": 0 }, + "3015": { "label": "22/32/1", "naklon": 0 }, + "2662": { "label": "22/33", "naklon": 0 }, + "2663": { "label": "22/34", "naklon": 0 }, + "2664": { "label": "22/35", "naklon": 0 }, + "2665": { "label": "22/36", "naklon": 0 }, + "2666": { "label": "22/37", "naklon": 0 }, + "2667": { "label": "22/38", "naklon": 0 }, + "2668": { "label": "22/39", "naklon": 0 }, + "2669": { "label": "22/40", "naklon": null }, + "2670": { "label": "22/41", "naklon": null }, + "2671": { "label": "22/42", "naklon": null }, + "3087": { "label": "23/9A", "naklon": 10 }, + "3090": { "label": "23/9B", "naklon": 10 }, + "3075": { "label": "23/1", "naklon": 0 }, + "3089": { "label": "23/2", "naklon": 0 }, + "3088": { "label": "23/3", "naklon": 0 }, + "3228": { "label": "23/4", "naklon": 10 }, + "2751": { "label": "23/5", "naklon": 10 }, + "3243": { "label": "23/6", "naklon": 10 }, + "4349": { "label": "23/7", "naklon": 10 }, + "3102": { "label": "23/8", "naklon": 10 }, + "3099": { "label": "23/10", "naklon": 10 }, + "3103": { "label": "23/11", "naklon": 10 }, + "3093": { "label": "23/12", "naklon": 10 }, + "3098": { "label": "23/13", "naklon": 10 }, + "3092": { "label": "23/14", "naklon": 10 }, + "3233": { "label": "23/15", "naklon": 0 }, + "3095": { "label": "23/16", "naklon": 0 }, + "4074": { "label": "23/17", "naklon": 0 }, + "2729": { "label": "23/18", "naklon": 0 }, + "3234": { "label": "23/19", "naklon": 0 }, + "3094": { "label": "23/20", "naklon": 0 }, + "2817": { "label": "23/21", "naklon": 0 }, + "3226": { "label": "23/22", "naklon": 0 }, + "3225": { "label": "23/23", "naklon": 0 }, + "3237": { "label": "23/24", "naklon": 0 }, + "4250": { "label": "23/25", "naklon": 0 }, + "3059": { "label": "23/26", "naklon": 10 }, + "3238": { "label": "23/27", "naklon": 10 }, + "3242": { "label": "23/28", "naklon": 10 }, + "3236": { "label": "23/29", "naklon": 10 }, + "3112": { "label": "23/30", "naklon": 10 }, + "3224": { "label": "23/31", "naklon": 0 }, + "4298": { "label": "23/32", "naklon": 10 }, + "4150": { "label": "23/33", "naklon": 10 }, + "3091": { "label": "23/34", "naklon": 10 }, + "3771": { "label": "25/1", "naklon": 5 }, + "3777": { "label": "25/2", "naklon": 5 }, + "3749": { "label": "25/3", "naklon": 5 }, + "3769": { "label": "25/4", "naklon": 5 }, + "3765": { "label": "25/5", "naklon": 5 }, + "3785": { "label": "25/6", "naklon": 5 }, + "3761": { "label": "25/7", "naklon": 5 }, + "3758": { "label": "25/8", "naklon": 5 }, + "3766": { "label": "25/9", "naklon": 5 }, + "3779": { "label": "25/10", "naklon": 5 }, + "3899": { "label": "25/11", "naklon": 10 }, + "3922": { "label": "25/12", "naklon": 10 }, + "3912": { "label": "25/13", "naklon": 10 }, + "3933": { "label": "25/14", "naklon": 10 }, + "3921": { "label": "25/15", "naklon": 10 }, + "4300": { "label": "25/16", "naklon": 10 }, + "3927": { "label": "25/17", "naklon": 10 }, + "3212": { "label": "25/18", "naklon": 10 }, + "3208": { "label": "25/19", "naklon": 10 }, + "3207": { "label": "25/20", "naklon": 10 }, + "4294": { "label": "25/21", "naklon": 10 }, + "3209": { "label": "25/22", "naklon": 10 }, + "3745": { "label": "25/23", "naklon": 10 }, + "3762": { "label": "25/24", "naklon": 10 }, + "3215": { "label": "25/25", "naklon": 10 }, + "3210": { "label": "25/26", "naklon": 10 }, + "3211": { "label": "25/27", "naklon": 10 }, + "3206": { "label": "25/28", "naklon": 10 }, + "3918": { "label": "25/29", "naklon": 5 }, + "3928": { "label": "25/30", "naklon": 5 }, + "3917": { "label": "25/31", "naklon": 5 }, + "4029": { "label": "25/32", "naklon": 0 }, + "4038": { "label": "25/33", "naklon": 0 }, + "4022": { "label": "25/34", "naklon": 0 }, + "3937": { "label": "25/35", "naklon": 0 }, + "3190": { "label": "25/36", "naklon": 0 }, + "3835": { "label": "25/37", "naklon": 0 }, + "3201": { "label": "25/38", "naklon": 0 }, + "3193": { "label": "25/39", "naklon": 0 }, + "3191": { "label": "25/40", "naklon": 0 }, + "3203": { "label": "25/41", "naklon": 0 }, + "4301": { "label": "25/42", "naklon": 0 }, + "3223": { "label": "25/43", "naklon": 0 }, + "3202": { "label": "25/44", "naklon": 0 }, + "3205": { "label": "25/45", "naklon": 0 }, + "3194": { "label": "25/46", "naklon": 0 }, + "3198": { "label": "25/47", "naklon": 0 }, + "3204": { "label": "25/48", "naklon": 0 }, + "3200": { "label": "25/49", "naklon": 0 }, + "3216": { "label": "25/50", "naklon": 0 }, + "3932": { "label": "25/51", "naklon": 5 }, + "3923": { "label": "25/52", "naklon": 5 }, + "3913": { "label": "25/53", "naklon": 5 }, + "3900": { "label": "25/54", "naklon": 5 }, + "4189": { "label": "25/55", "naklon": 10 }, + "4191": { "label": "25/56", "naklon": 10 }, + "3790": { "label": "25/57", "naklon": 10 }, + "4190": { "label": "25/58", "naklon": 10 }, + "4302": { "label": "25/59", "naklon": 0 }, + "4351": { "label": "25/60", "naklon": 0 }, + "4075": { "label": "25/61", "naklon": 0 }, + "4071": { "label": "25/62", "naklon": 0 }, + "3784": { "label": "25/63", "naklon": 0 }, + "4065": { "label": "25/64", "naklon": 0 }, + "4297": { "label": "25/65", "naklon": 0 }, + "4295": { "label": "25/66", "naklon": 0 }, + "4299": { "label": "25/67", "naklon": 0 }, + "3772": { "label": "25/68", "naklon": 0 }, + "3941": { "label": "25/69", "naklon": 0 }, + "3782": { "label": "25/70", "naklon": 0 }, + "4068": { "label": "25/71", "naklon": 0 }, + "4073": { "label": "25/72", "naklon": 0 }, + "3901": { "label": "25/73", "naklon": 5 }, + "4296": { "label": "25/74", "naklon": 5 }, + "3910": { "label": "25/75", "naklon": 5 }, + "4293": { "label": "25/76", "naklon": 5 }, + "3919": { "label": "25/77", "naklon": 5 }, + "3924": { "label": "25/78", "naklon": 5 }, + "3909": { "label": "25/79", "naklon": 5 }, + "3896": { "label": "25/80", "naklon": 5 }, + "3911": { "label": "25/81", "naklon": 5 }, + "2819": { "label": "25/82", "naklon": 15 }, + "3776": { "label": "25/83", "naklon": 15 }, + "3752": { "label": "25/84", "naklon": 15 }, + "4353": { "label": "25/85", "naklon": 15 }, + "3791": { "label": "25/86", "naklon": 0 }, + "3770": { "label": "25/87", "naklon": 0 }, + "3760": { "label": "25/88", "naklon": 0 }, + "3115": { "label": "25/89", "naklon": 0 }, + "3738": { "label": "25/90", "naklon": 0 }, + "3748": { "label": "25/91", "naklon": 0 }, + "3753": { "label": "25/92", "naklon": 0 }, + "3775": { "label": "25/93", "naklon": 0 }, + "3778": { "label": "25/94", "naklon": 5 }, + "4078": { "label": "25/95", "naklon": 5 }, + "4088": { "label": "25/96", "naklon": 5 }, + "3856": { "label": "25/97", "naklon": 5 }, + "4084": { "label": "25/98", "naklon": 5 }, + "4069": { "label": "25/99", "naklon": 5 }, + "4188": { "label": "25/100", "naklon": 5 }, + "4064": { "label": "25/101", "naklon": 5 }, + "3792": { "label": "25/102", "naklon": 5 }, + "3780": { "label": "25/103", "naklon": 5 }, + "4034": { "label": "25/104", "naklon": 5 }, + "4072": { "label": "25/105", "naklon": 5 }, + "3884": { "label": "25/106", "naklon": 5 }, + "3793": { "label": "25/107", "naklon": 5 }, + "3863": { "label": "25/108", "naklon": 5 }, + "3855": { "label": "25/109", "naklon": 5 }, + "3846": { "label": "33/1", "naklon": 0 }, + "3943": { "label": "33/2", "naklon": 0 }, + "3903": { "label": "33/3", "naklon": 0 }, + "3982": { "label": "33/4", "naklon": 0 }, + "3879": { "label": "33/5", "naklon": 0 }, + "3887": { "label": "33/6", "naklon": 0 }, + "3920": { "label": "33/7", "naklon": 5 }, + "3942": { "label": "33/8", "naklon": 5 }, + "3829": { "label": "33/9", "naklon": null }, + "3452": { "label": "34/79A", "naklon": 6 }, + "3460": { "label": "34/79B", "naklon": 6 }, + "3443": { "label": "34/90A", "naklon": 6 }, + "3445": { "label": "34/90B", "naklon": 6 }, + "3457": { "label": "34/90C", "naklon": 6 }, + "3461": { "label": "34/97A", "naklon": 6 }, + "3463": { "label": "34/97B", "naklon": 6 }, + "3426": { "label": "34/98A", "naklon": 6 }, + "3444": { "label": "34/98B", "naklon": 6 }, + "3453": { "label": "34/99A", "naklon": 6 }, + "3455": { "label": "34/99B", "naklon": 6 }, + "4009": { "label": "34/1", "naklon": 0 }, + "3602": { "label": "34/2", "naklon": 0 }, + "3441": { "label": "34/3", "naklon": 0 }, + "3464": { "label": "34/4", "naklon": 0 }, + "3883": { "label": "34/5", "naklon": 0 }, + "4098": { "label": "34/6", "naklon": 0 }, + "4003": { "label": "34/7", "naklon": 0 }, + "4004": { "label": "34/8", "naklon": 0 }, + "3888": { "label": "34/9", "naklon": 0 }, + "3997": { "label": "34/10", "naklon": 0 }, + "4006": { "label": "34/11", "naklon": 0 }, + "4000": { "label": "34/12", "naklon": 0 }, + "4011": { "label": "34/13", "naklon": 0 }, + "3999": { "label": "34/14", "naklon": 0 }, + "3981": { "label": "34/15", "naklon": 0 }, + "3988": { "label": "34/16", "naklon": 0 }, + "3986": { "label": "34/17", "naklon": 0 }, + "3998": { "label": "34/18", "naklon": 0 }, + "3983": { "label": "34/19", "naklon": 0 }, + "4005": { "label": "34/20", "naklon": 0 }, + "4001": { "label": "34/21", "naklon": 0 }, + "4008": { "label": "34/22", "naklon": 0 }, + "4002": { "label": "34/23", "naklon": 0 }, + "3996": { "label": "34/24", "naklon": 0 }, + "4007": { "label": "34/25", "naklon": 0 }, + "4113": { "label": "34/26", "naklon": 15 }, + "3595": { "label": "34/27", "naklon": 5 }, + "3599": { "label": "34/28", "naklon": 5 }, + "3601": { "label": "34/29", "naklon": 5 }, + "4205": { "label": "34/30", "naklon": 0 }, + "3987": { "label": "34/31", "naklon": null }, + "4214": { "label": "34/32", "naklon": 0 }, + "4226": { "label": "34/33", "naklon": 0 }, + "4209": { "label": "34/34", "naklon": 0 }, + "4201": { "label": "34/35", "naklon": 0 }, + "3440": { "label": "34/36", "naklon": 0 }, + "3465": { "label": "34/37", "naklon": 0 }, + "3446": { "label": "34/38", "naklon": 0 }, + "4039": { "label": "34/39", "naklon": 5 }, + "4057": { "label": "34/40", "naklon": 5 }, + "3985": { "label": "34/41", "naklon": 0 }, + "3882": { "label": "34/42", "naklon": 0 }, + "4040": { "label": "34/43", "naklon": 5 }, + "3231": { "label": "34/44", "naklon": 0 }, + "3227": { "label": "34/45", "naklon": 0 }, + "3431": { "label": "34/46", "naklon": 0 }, + "4013": { "label": "34/47", "naklon": 0 }, + "4045": { "label": "34/48", "naklon": 0 }, + "3949": { "label": "34/49", "naklon": 0 }, + "3953": { "label": "34/50", "naklon": 0 }, + "3952": { "label": "34/51", "naklon": 0 }, + "3995": { "label": "34/52", "naklon": 0 }, + "3992": { "label": "34/53", "naklon": 0 }, + "4198": { "label": "34/54", "naklon": 0 }, + "3935": { "label": "34/55", "naklon": 0 }, + "4050": { "label": "34/56", "naklon": 0 }, + "4049": { "label": "34/57", "naklon": 0 }, + "4054": { "label": "34/58", "naklon": 0 }, + "3663": { "label": "34/59", "naklon": 6 }, + "3661": { "label": "34/60", "naklon": 6 }, + "3664": { "label": "34/61", "naklon": 6 }, + "3660": { "label": "34/62", "naklon": 6 }, + "3662": { "label": "34/63", "naklon": 6 }, + "3665": { "label": "34/65", "naklon": 6 }, + "3667": { "label": "34/66", "naklon": 6 }, + "3675": { "label": "34/67", "naklon": 6 }, + "3666": { "label": "34/68", "naklon": 6 }, + "3652": { "label": "34/69", "naklon": 6 }, + "3458": { "label": "34/70", "naklon": 6 }, + "4425": { "label": "34/70/1", "naklon": 6 }, + "3459": { "label": "34/71", "naklon": 6 }, + "3435": { "label": "34/72", "naklon": 6 }, + "3448": { "label": "34/73", "naklon": 6 }, + "3451": { "label": "34/74", "naklon": 6 }, + "3442": { "label": "34/75", "naklon": 6 }, + "3449": { "label": "34/76", "naklon": 6 }, + "3450": { "label": "34/77", "naklon": 6 }, + "3433": { "label": "34/78", "naklon": 6 }, + "3432": { "label": "34/80", "naklon": 12 }, + "3470": { "label": "34/81", "naklon": 12 }, + "3438": { "label": "34/82", "naklon": 12 }, + "3439": { "label": "34/83", "naklon": 12 }, + "4028": { "label": "34/84", "naklon": 5 }, + "3596": { "label": "34/85", "naklon": 5 }, + "4021": { "label": "34/86", "naklon": 5 }, + "3437": { "label": "34/87", "naklon": 12 }, + "3428": { "label": "34/88", "naklon": 12 }, + "3430": { "label": "34/89", "naklon": 12 }, + "3454": { "label": "34/91", "naklon": 6 }, + "3492": { "label": "34/92", "naklon": 6 }, + "3462": { "label": "34/93", "naklon": 6 }, + "3427": { "label": "34/94", "naklon": 6 }, + "3434": { "label": "34/95", "naklon": 6 }, + "3456": { "label": "34/96", "naklon": 6 }, + "4307": { "label": "34/98/1", "naklon": 6 }, + "3968": { "label": "35/1", "naklon": 0 }, + "3969": { "label": "35/2", "naklon": 0 }, + "3947": { "label": "35/3", "naklon": 0 }, + "3979": { "label": "35/4", "naklon": 0 }, + "3959": { "label": "35/5", "naklon": 0 }, + "3948": { "label": "35/6", "naklon": 0 }, + "3961": { "label": "35/7", "naklon": 0 }, + "3956": { "label": "35/8", "naklon": 0 }, + "3604": { "label": "35/9", "naklon": 0 }, + "3944": { "label": "35/10", "naklon": 0 }, + "3960": { "label": "35/11", "naklon": 0 }, + "3958": { "label": "35/12", "naklon": 0 }, + "4036": { "label": "35/13", "naklon": 5 }, + "3893": { "label": "35/18", "naklon": 5 }, + "4108": { "label": "35/19", "naklon": 5 }, + "4017": { "label": "35/20", "naklon": 5 }, + "3963": { "label": "35/21", "naklon": 0 }, + "3658": { "label": "35/22", "naklon": 0 }, + "3975": { "label": "35/23", "naklon": 0 }, + "3980": { "label": "35/24", "naklon": 0 }, + "4012": { "label": "35/25", "naklon": 0 }, + "3655": { "label": "35/26", "naklon": 0 }, + "3962": { "label": "35/27", "naklon": 0 }, + "3945": { "label": "35/28", "naklon": 0 }, + "3569": { "label": "35/29", "naklon": 0 }, + "3429": { "label": "35/30", "naklon": 0 }, + "3657": { "label": "35/31", "naklon": 0 }, + "3646": { "label": "35/32", "naklon": 0 }, + "3622": { "label": "35/33", "naklon": 0 }, + "3612": { "label": "35/34", "naklon": 0 }, + "3955": { "label": "35/35", "naklon": 0 }, + "3878": { "label": "35/37", "naklon": 0 }, + "3965": { "label": "35/38", "naklon": 0 }, + "3970": { "label": "35/39", "naklon": 0 }, + "3611": { "label": "35/40", "naklon": 0 }, + "2635": { "label": "35/41", "naklon": 0 }, + "3978": { "label": "35/42", "naklon": 0 }, + "4213": { "label": "35/43", "naklon": 0 }, + "3984": { "label": "35/44", "naklon": 0 }, + "4218": { "label": "35/45", "naklon": 0 }, + "3973": { "label": "35/46", "naklon": 0 }, + "3974": { "label": "35/47", "naklon": 0 }, + "3759": { "label": "35/48", "naklon": 0 }, + "3844": { "label": "35/49", "naklon": 0 }, + "3804": { "label": "35/50", "naklon": 0 }, + "3831": { "label": "35/51", "naklon": 0 }, + "3643": { "label": "35/52", "naklon": 0 }, + "3966": { "label": "35/53", "naklon": 0 }, + "3971": { "label": "35/54", "naklon": 0 }, + "3650": { "label": "35/55", "naklon": 6 }, + "3651": { "label": "35/56", "naklon": 6 }, + "3669": { "label": "35/57", "naklon": 6 }, + "3648": { "label": "35/58", "naklon": 6 }, + "3645": { "label": "35/59", "naklon": 6 }, + "3659": { "label": "35/60", "naklon": 6 }, + "3647": { "label": "35/61", "naklon": 6 }, + "3644": { "label": "35/62", "naklon": 6 }, + "3671": { "label": "35/63", "naklon": 6 }, + "3682": { "label": "35/64", "naklon": 6 }, + "3672": { "label": "35/65", "naklon": 6 }, + "3683": { "label": "35/66", "naklon": 6 }, + "3673": { "label": "35/67", "naklon": 6 }, + "3674": { "label": "35/68", "naklon": 6 }, + "3679": { "label": "35/69", "naklon": 6 }, + "3649": { "label": "35/70", "naklon": 6 }, + "3687": { "label": "35/71", "naklon": 6 }, + "3677": { "label": "35/72", "naklon": 6 }, + "3690": { "label": "35/73", "naklon": 6 }, + "3691": { "label": "35/74", "naklon": 6 }, + "3676": { "label": "35/75", "naklon": 6 }, + "3680": { "label": "35/76", "naklon": 6 }, + "3668": { "label": "35/77", "naklon": 6 }, + "3681": { "label": "35/78", "naklon": 6 }, + "3670": { "label": "35/79", "naklon": 6 }, + "3689": { "label": "35/80", "naklon": 6 }, + "3678": { "label": "35/81", "naklon": 6 }, + "3693": { "label": "35/82", "naklon": 6 }, + "3654": { "label": "35/83", "naklon": null }, + "4086": { "label": "36/1", "naklon": 0 }, + "4085": { "label": "36/2", "naklon": 0 }, + "4083": { "label": "36/3", "naklon": 0 }, + "4087": { "label": "36/4", "naklon": 0 }, + "4077": { "label": "36/5", "naklon": 0 }, + "4082": { "label": "36/6", "naklon": 0 }, + "4186": { "label": "36/7", "naklon": 0 }, + "4206": { "label": "36/8", "naklon": 0 }, + "4080": { "label": "36/9", "naklon": 0 }, + "4081": { "label": "36/10", "naklon": 0 }, + "4210": { "label": "36/11", "naklon": 0 }, + "4079": { "label": "36/12", "naklon": 0 }, + "4076": { "label": "36/13", "naklon": 0 }, + "3852": { "label": "36/14", "naklon": 0 }, + "2813": { "label": "36/15", "naklon": 0 }, + "4219": { "label": "36/16", "naklon": 0 }, + "3104": { "label": "37/1A", "naklon": 15 }, + "3121": { "label": "37/1B", "naklon": 15 }, + "3113": { "label": "37/2", "naklon": 10 }, + "3118": { "label": "37/3", "naklon": 10 }, + "3111": { "label": "37/4", "naklon": 10 }, + "4020": { "label": "37/5", "naklon": 10 }, + "3119": { "label": "37/6", "naklon": 10 }, + "3110": { "label": "37/7", "naklon": 10 }, + "3108": { "label": "37/8", "naklon": 10 }, + "3107": { "label": "37/12", "naklon": 0 }, + "3199": { "label": "37/13", "naklon": 0 }, + "3120": { "label": "37/14", "naklon": 0 }, + "3122": { "label": "37/15", "naklon": 0 }, + "3908": { "label": "37/16", "naklon": 0 }, + "3114": { "label": "37/17", "naklon": 0 }, + "3105": { "label": "37/18", "naklon": 0 }, + "3116": { "label": "37/19", "naklon": 0 }, + "3106": { "label": "37/20", "naklon": 0 }, + "2887": { "label": "37/21", "naklon": 5 }, + "2888": { "label": "37/22", "naklon": 5 }, + "2877": { "label": "37/23", "naklon": 5 }, + "2891": { "label": "37/24", "naklon": 5 }, + "2886": { "label": "37/25", "naklon": 5 }, + "2892": { "label": "37/26", "naklon": 5 }, + "2882": { "label": "37/27", "naklon": 5 }, + "2883": { "label": "37/28", "naklon": 5 }, + "2876": { "label": "37/29", "naklon": 5 }, + "3109": { "label": "37/30", "naklon": 5 }, + "4152": { "label": "37/31", "naklon": 5 }, + "3117": { "label": "37/32", "naklon": 5 }, + "2870": { "label": "37/33", "naklon": 5 }, + "2867": { "label": "37/34", "naklon": 0 }, + "2865": { "label": "37/35", "naklon": 0 }, + "3096": { "label": "37/36", "naklon": 0 }, + "2871": { "label": "37/37", "naklon": 0 }, + "2884": { "label": "37/38", "naklon": 0 }, + "2855": { "label": "37/39", "naklon": 0 }, + "2878": { "label": "37/40", "naklon": 0 }, + "2889": { "label": "37/41", "naklon": 0 }, + "2879": { "label": "37/42", "naklon": 0 }, + "2850": { "label": "37/43", "naklon": 0 }, + "2894": { "label": "37/44", "naklon": 0 }, + "2880": { "label": "37/45", "naklon": 0 }, + "2893": { "label": "37/46", "naklon": 0 }, + "2890": { "label": "37/47", "naklon": 0 }, + "4355": { "label": "37/48", "naklon": 0 }, + "2885": { "label": "37/49", "naklon": 0 }, + "2875": { "label": "37/50", "naklon": 0 }, + "3486": { "label": "38/30A", "naklon": 5 }, + "3714": { "label": "38/30B", "naklon": 0 }, + "3483": { "label": "38/32A", "naklon": 5 }, + "3496": { "label": "38/32B", "naklon": 0 }, + "3487": { "label": "38/35A", "naklon": 5 }, + "3498": { "label": "38/35B", "naklon": 5 }, + "3578": { "label": "38/38A", "naklon": 5 }, + "3508": { "label": "38/38B", "naklon": 5 }, + "3787": { "label": "38/59A", "naklon": 5 }, + "3491": { "label": "38/59B", "naklon": 5 }, + "3568": { "label": "38/1", "naklon": null }, + "3502": { "label": "38/2", "naklon": 0 }, + "3836": { "label": "38/3", "naklon": 0 }, + "3588": { "label": "38/4", "naklon": 0 }, + "3493": { "label": "38/5", "naklon": 0 }, + "3580": { "label": "38/6", "naklon": 0 }, + "3572": { "label": "38/7", "naklon": 0 }, + "3506": { "label": "38/8", "naklon": 0 }, + "3503": { "label": "38/9", "naklon": 0 }, + "3579": { "label": "38/10", "naklon": 0 }, + "3586": { "label": "38/11", "naklon": 0 }, + "3495": { "label": "38/12", "naklon": 5 }, + "3492": { "label": "38/13", "naklon": 5 }, + "3532": { "label": "38/14", "naklon": 5 }, + "3574": { "label": "38/15", "naklon": 5 }, + "4140": { "label": "38/16", "naklon": 5 }, + "3795": { "label": "38/17", "naklon": 5 }, + "3788": { "label": "38/18", "naklon": 5 }, + "3796": { "label": "38/19", "naklon": 5 }, + "3797": { "label": "38/20", "naklon": 5 }, + "3798": { "label": "38/21", "naklon": 5 }, + "3786": { "label": "38/22", "naklon": 5 }, + "4067": { "label": "38/23", "naklon": 5 }, + "3773": { "label": "38/24", "naklon": 5 }, + "3774": { "label": "38/25", "naklon": 5 }, + "3789": { "label": "38/26", "naklon": 5 }, + "3520": { "label": "38/27", "naklon": null }, + "3577": { "label": "38/29", "naklon": 5 }, + "3530": { "label": "38/31", "naklon": null }, + "3488": { "label": "38/33", "naklon": 5 }, + "3505": { "label": "38/34", "naklon": 5 }, + "3497": { "label": "38/36", "naklon": 5 }, + "3490": { "label": "38/37", "naklon": 5 }, + "3585": { "label": "38/39", "naklon": 5 }, + "3582": { "label": "38/40", "naklon": 5 }, + "3507": { "label": "38/41", "naklon": 5 }, + "3484": { "label": "38/42", "naklon": 5 }, + "3501": { "label": "38/43", "naklon": 5 }, + "3581": { "label": "38/44", "naklon": 5 }, + "4192": { "label": "38/45", "naklon": 5 }, + "3576": { "label": "38/46", "naklon": 5 }, + "3489": { "label": "38/47", "naklon": 5 }, + "3573": { "label": "38/48", "naklon": 5 }, + "3504": { "label": "38/49", "naklon": 5 }, + "3794": { "label": "38/50", "naklon": 5 }, + "3485": { "label": "38/51", "naklon": 5 }, + "3482": { "label": "38/52", "naklon": 5 }, + "3575": { "label": "38/53", "naklon": 5 }, + "3499": { "label": "38/54", "naklon": 5 }, + "3494": { "label": "38/55", "naklon": 5 }, + "3583": { "label": "38/56", "naklon": 5 }, + "3570": { "label": "38/57", "naklon": 5 }, + "3500": { "label": "38/58", "naklon": 0 }, + "3510": { "label": "38/63", "naklon": null }, + "3512": { "label": "38/64", "naklon": null }, + "3535": { "label": "38/67", "naklon": null }, + "3531": { "label": "38/68", "naklon": null }, + "3537": { "label": "38/69", "naklon": null }, + "3522": { "label": "39/1", "naklon": 10 }, + "4018": { "label": "39/2", "naklon": 10 }, + "4019": { "label": "39/3", "naklon": 10 }, + "4154": { "label": "39/4", "naklon": 5 }, + "3907": { "label": "39/5", "naklon": 5 }, + "4148": { "label": "39/6", "naklon": 0 }, + "4153": { "label": "39/7", "naklon": 0 }, + "3938": { "label": "39/8", "naklon": 0 }, + "3802": { "label": "39/9", "naklon": 0 }, + "4015": { "label": "39/10", "naklon": 0 }, + "3929": { "label": "39/11", "naklon": 0 }, + "3946": { "label": "39/12", "naklon": 0 }, + "4014": { "label": "39/13", "naklon": 0 }, + "4155": { "label": "39/14", "naklon": 0 }, + "4149": { "label": "39/15", "naklon": 0 }, + "3642": { "label": "39/16", "naklon": 0 }, + "3636": { "label": "39/17", "naklon": 5 }, + "3991": { "label": "39/18", "naklon": 0 }, + "3994": { "label": "39/19", "naklon": 0 }, + "3990": { "label": "39/20", "naklon": 0 }, + "3967": { "label": "39/21", "naklon": 0 }, + "3977": { "label": "39/22", "naklon": 0 }, + "3757": { "label": "39/23", "naklon": 15 }, + "3633": { "label": "39/24", "naklon": 15 }, + "3744": { "label": "39/25", "naklon": 15 }, + "4023": { "label": "39/26", "naklon": 5 }, + "3720": { "label": "39/27", "naklon": 5 }, + "3734": { "label": "39/28", "naklon": 5 }, + "3741": { "label": "39/29", "naklon": 5 }, + "3721": { "label": "39/30", "naklon": 5 }, + "3845": { "label": "39/31", "naklon": 0 }, + "3840": { "label": "39/32", "naklon": 0 }, + "3837": { "label": "39/33", "naklon": null }, + "3839": { "label": "39/34", "naklon": 0 }, + "3542": { "label": "41/1", "naklon": null }, + "3566": { "label": "41/2", "naklon": null }, + "3548": { "label": "41/3", "naklon": null }, + "3515": { "label": "41/4", "naklon": null }, + "3559": { "label": "41/5", "naklon": null }, + "3509": { "label": "41/6", "naklon": null }, + "3524": { "label": "41/7", "naklon": null }, + "3518": { "label": "41/8", "naklon": null }, + "3182": { "label": "41/9", "naklon": null }, + "3187": { "label": "41/10", "naklon": null }, + "3195": { "label": "41/11", "naklon": 0 }, + "3857": { "label": "41/12", "naklon": 0 }, + "3183": { "label": "41/13", "naklon": 0 }, + "3177": { "label": "41/14", "naklon": 0 }, + "3189": { "label": "41/15", "naklon": 0 }, + "3186": { "label": "41/16", "naklon": 0 }, + "3178": { "label": "42/1", "naklon": 0 }, + "3219": { "label": "42/2", "naklon": 0 }, + "3475": { "label": "42/3", "naklon": 0 }, + "3175": { "label": "42/4", "naklon": 0 }, + "3222": { "label": "42/5", "naklon": 0 }, + "3221": { "label": "42/6", "naklon": 0 }, + "3181": { "label": "42/7", "naklon": 0 }, + "3180": { "label": "42/8", "naklon": 0 }, + "3218": { "label": "42/9", "naklon": 0 }, + "3176": { "label": "42/10", "naklon": 0 }, + "3174": { "label": "42/11", "naklon": 0 }, + "3220": { "label": "42/12", "naklon": 0 }, + "3533": { "label": "42/13", "naklon": null }, + "3543": { "label": "42/14", "naklon": null }, + "3554": { "label": "42/15", "naklon": null }, + "3549": { "label": "42/16", "naklon": null }, + "2857": { "label": "43/1", "naklon": 5 }, + "2752": { "label": "43/2", "naklon": 5 }, + "2753": { "label": "43/3", "naklon": 5 }, + "3024": { "label": "43/4", "naklon": 5 }, + "2754": { "label": "43/5", "naklon": 5 }, + "4423": { "label": "43/6", "naklon": 5 }, + "4368": { "label": "43/7", "naklon": 5 }, + "2978": { "label": "43/8", "naklon": 5 }, + "2868": { "label": "43/9", "naklon": 5 }, + "4377": { "label": "43/10", "naklon": 5 }, + "2757": { "label": "43/11", "naklon": 5 }, + "2970": { "label": "43/12", "naklon": 5 }, + "2758": { "label": "43/13", "naklon": 5 }, + "4378": { "label": "43/14", "naklon": 5 }, + "2759": { "label": "43/15", "naklon": 5 }, + "4342": { "label": "43/16", "naklon": 5 }, + "3026": { "label": "43/17", "naklon": null }, + "2986": { "label": "43/18", "naklon": null }, + "4343": { "label": "43/19", "naklon": null }, + "2760": { "label": "43/20", "naklon": null }, + "4379": { "label": "43/21", "naklon": null }, + "2971": { "label": "43/22", "naklon": null }, + "2761": { "label": "43/23", "naklon": null }, + "2762": { "label": "43/24", "naklon": null }, + "4339": { "label": "43/25", "naklon": null }, + "4380": { "label": "43/26", "naklon": null }, + "2975": { "label": "43/27", "naklon": null }, + "3003": { "label": "43/28", "naklon": null }, + "4338": { "label": "43/29", "naklon": null }, + "3002": { "label": "43/30", "naklon": null }, + "4345": { "label": "43/31", "naklon": null }, + "2979": { "label": "43/32", "naklon": null }, + "2989": { "label": "43/33", "naklon": null }, + "2996": { "label": "43/34", "naklon": null }, + "2972": { "label": "43/35", "naklon": null }, + "2988": { "label": "43/36", "naklon": null }, + "4344": { "label": "43/37", "naklon": null }, + "3022": { "label": "43/38", "naklon": null }, + "4341": { "label": "43/39", "naklon": null }, + "2983": { "label": "43/40", "naklon": null }, + "2995": { "label": "43/41", "naklon": null }, + "2763": { "label": "43/42", "naklon": null }, + "2764": { "label": "43/43", "naklon": null }, + "2765": { "label": "43/44", "naklon": null }, + "2766": { "label": "43/45", "naklon": null }, + "2767": { "label": "43/46", "naklon": null }, + "2768": { "label": "43/47", "naklon": null }, + "3018": { "label": "43/48", "naklon": null }, + "2982": { "label": "43/49", "naklon": null }, + "3019": { "label": "43/50", "naklon": 0 }, + "3013": { "label": "43/51", "naklon": null }, + "3007": { "label": "43/52", "naklon": null }, + "2980": { "label": "43/53", "naklon": null }, + "3011": { "label": "43/54", "naklon": null }, + "2672": { "label": "43/55", "naklon": null }, + "2673": { "label": "43/56", "naklon": null }, + "2674": { "label": "43/57", "naklon": null }, + "2675": { "label": "43/58", "naklon": null }, + "2676": { "label": "43/59", "naklon": null }, + "2677": { "label": "43/60", "naklon": null }, + "2678": { "label": "43/61", "naklon": null }, + "2679": { "label": "43/62", "naklon": null }, + "2680": { "label": "43/63", "naklon": null }, + "2840": { "label": "43/64", "naklon": null }, + "2682": { "label": "43/65", "naklon": null }, + "2683": { "label": "43/66", "naklon": null }, + "2684": { "label": "43/67", "naklon": 0 }, + "2685": { "label": "43/68", "naklon": null }, + "2686": { "label": "43/69", "naklon": null }, + "2687": { "label": "43/70", "naklon": null }, + "2688": { "label": "43/71", "naklon": null }, + "2689": { "label": "43/72", "naklon": null }, + "2690": { "label": "43/73", "naklon": null }, + "2691": { "label": "43/74", "naklon": null }, + "2692": { "label": "43/75", "naklon": null }, + "2693": { "label": "43/76", "naklon": 0 }, + "2694": { "label": "43/77", "naklon": null }, + "2695": { "label": "43/78", "naklon": null }, + "2696": { "label": "43/79", "naklon": 0 }, + "2697": { "label": "43/80", "naklon": null }, + "2698": { "label": "43/81", "naklon": 0 }, + "2699": { "label": "43/82", "naklon": null }, + "2700": { "label": "43/83", "naklon": 0 }, + "2744": { "label": "43/84", "naklon": null }, + "2745": { "label": "43/85", "naklon": 0 }, + "2746": { "label": "43/86", "naklon": null }, + "2747": { "label": "43/87", "naklon": 0 }, + "2748": { "label": "43/88", "naklon": null }, + "2749": { "label": "43/89", "naklon": 0 }, + "2841": { "label": "43/90", "naklon": null }, + "4237": { "label": "45/1", "naklon": 5 }, + "4226": { "label": "45/2", "naklon": 5 }, + "4242": { "label": "45/3", "naklon": 5 }, + "4179": { "label": "45/4", "naklon": 5 }, + "4247": { "label": "45/5", "naklon": 5 }, + "4245": { "label": "45/6", "naklon": 5 }, + "3872": { "label": "45/7", "naklon": 5 }, + "4175": { "label": "45/8", "naklon": 5 }, + "4236": { "label": "45/9", "naklon": 5 }, + "4170": { "label": "45/10", "naklon": 5 }, + "4238": { "label": "45/11", "naklon": 5 }, + "4246": { "label": "45/12", "naklon": 5 }, + "4166": { "label": "45/13", "naklon": 5 }, + "4227": { "label": "45/14", "naklon": 5 }, + "4171": { "label": "45/15", "naklon": 5 }, + "4180": { "label": "45/16", "naklon": 5 }, + "4244": { "label": "45/17", "naklon": 5 }, + "4199": { "label": "45/18", "naklon": 5 }, + "4239": { "label": "45/19", "naklon": 5 }, + "4207": { "label": "45/20", "naklon": 5 }, + "4223": { "label": "45/21", "naklon": 5 }, + "4230": { "label": "45/22", "naklon": 5 }, + "4233": { "label": "45/23", "naklon": 5 }, + "4222": { "label": "45/24", "naklon": 5 }, + "4217": { "label": "45/25", "naklon": 5 }, + "4243": { "label": "45/26", "naklon": 5 }, + "4200": { "label": "45/27", "naklon": 5 }, + "4228": { "label": "45/28", "naklon": 5 }, + "4211": { "label": "45/29", "naklon": 5 }, + "4234": { "label": "45/30", "naklon": 5 }, + "4235": { "label": "45/31", "naklon": 5 }, + "4203": { "label": "45/32", "naklon": 5 }, + "4240": { "label": "45/33", "naklon": 5 }, + "4224": { "label": "45/34", "naklon": 5 }, + "4232": { "label": "45/35", "naklon": 5 }, + "4231": { "label": "45/36", "naklon": 5 }, + "4161": { "label": "45/37", "naklon": 5 }, + "4225": { "label": "45/38", "naklon": 5 }, + "4241": { "label": "45/39", "naklon": 5 }, + "4229": { "label": "45/40", "naklon": 5 }, + "4221": { "label": "45/41", "naklon": 5 }, + "4212": { "label": "45/42", "naklon": 5 }, + "4216": { "label": "45/43", "naklon": 5 }, + "3864": { "label": "45/44", "naklon": null }, + "3806": { "label": "46/1", "naklon": 5 }, + "3813": { "label": "46/2", "naklon": 5 }, + "3815": { "label": "46/3", "naklon": 5 }, + "3807": { "label": "46/4", "naklon": 5 }, + "3895": { "label": "46/5", "naklon": 5 }, + "3809": { "label": "46/6", "naklon": 5 }, + "3820": { "label": "46/7", "naklon": 5 }, + "3805": { "label": "46/8", "naklon": 5 }, + "3894": { "label": "46/9", "naklon": 0 }, + "4055": { "label": "46/10", "naklon": 0 }, + "3812": { "label": "46/11", "naklon": 5 }, + "3822": { "label": "46/12", "naklon": 5 }, + "3821": { "label": "46/13", "naklon": 5 }, + "3808": { "label": "46/14", "naklon": 5 }, + "3799": { "label": "46/15", "naklon": 5 }, + "3816": { "label": "46/16", "naklon": 5 }, + "3751": { "label": "46/17", "naklon": 5 }, + "3814": { "label": "46/18", "naklon": 5 }, + "4044": { "label": "46/19", "naklon": 0 }, + "3931": { "label": "46/20", "naklon": 0 }, + "3902": { "label": "46/21", "naklon": 5 }, + "3916": { "label": "46/22", "naklon": 5 }, + "3892": { "label": "46/23", "naklon": 5 }, + "3914": { "label": "46/24", "naklon": 5 }, + "3898": { "label": "46/25", "naklon": 5 }, + "3897": { "label": "46/26", "naklon": 5 }, + "3885": { "label": "46/27", "naklon": 5 }, + "3906": { "label": "46/28", "naklon": 5 }, + "3930": { "label": "46/29", "naklon": 0 }, + "3936": { "label": "46/30", "naklon": 0 }, + "3860": { "label": "46/31", "naklon": 5 }, + "3841": { "label": "46/32", "naklon": 5 }, + "3873": { "label": "46/33", "naklon": 5 }, + "3854": { "label": "46/34", "naklon": 5 }, + "3939": { "label": "46/35", "naklon": 5 }, + "3858": { "label": "46/36", "naklon": 5 }, + "3940": { "label": "46/37", "naklon": 5 }, + "4035": { "label": "46/38", "naklon": 5 }, + "3373": { "label": "47/1", "naklon": 0 }, + "3374": { "label": "47/2", "naklon": 0 }, + "3384": { "label": "47/3", "naklon": 0 }, + "3385": { "label": "47/4", "naklon": 0 }, + "4051": { "label": "48/1", "naklon": 5 }, + "4041": { "label": "48/2", "naklon": 5 }, + "4056": { "label": "48/3", "naklon": 5 }, + "3875": { "label": "48/4", "naklon": 5 }, + "4061": { "label": "48/5", "naklon": 5 }, + "4047": { "label": "48/6", "naklon": 5 }, + "4060": { "label": "48/7", "naklon": 5 }, + "4059": { "label": "48/8", "naklon": 5 }, + "4058": { "label": "48/9", "naklon": 5 }, + "3635": { "label": "48/10", "naklon": 5 }, + "3640": { "label": "48/11", "naklon": 5 }, + "3747": { "label": "48/12", "naklon": 5 }, + "3629": { "label": "48/13", "naklon": 5 }, + "4048": { "label": "48/14", "naklon": 5 }, + "4063": { "label": "48/15", "naklon": 5 }, + "4062": { "label": "48/16", "naklon": 5 }, + "4043": { "label": "48/17", "naklon": 5 }, + "4052": { "label": "48/18", "naklon": 5 }, + "4042": { "label": "48/19", "naklon": 5 }, + "4053": { "label": "48/20", "naklon": 5 }, + "4167": { "label": "50/15A", "naklon": null }, + "4159": { "label": "50/15B", "naklon": null }, + "4183": { "label": "50/1", "naklon": 0 }, + "4157": { "label": "50/2", "naklon": 0 }, + "4160": { "label": "50/3", "naklon": 0 }, + "4173": { "label": "50/4", "naklon": 0 }, + "4177": { "label": "50/5", "naklon": 0 }, + "4174": { "label": "50/6", "naklon": 0 }, + "4178": { "label": "50/7", "naklon": 0 }, + "4195": { "label": "50/8", "naklon": 0 }, + "4169": { "label": "50/9", "naklon": 0 }, + "4162": { "label": "50/10", "naklon": 0 }, + "4158": { "label": "50/11", "naklon": 0 }, + "4182": { "label": "50/12", "naklon": 0 }, + "4194": { "label": "50/13", "naklon": 0 }, + "4184": { "label": "50/14", "naklon": 0 }, + "4197": { "label": "50/16", "naklon": null }, + "4164": { "label": "50/17", "naklon": null }, + "3306": { "label": "50/18", "naklon": null }, + "4168": { "label": "50/19", "naklon": null }, + "4193": { "label": "50/20", "naklon": null }, + "4187": { "label": "50/21", "naklon": null }, + "4163": { "label": "50/22", "naklon": null }, + "4165": { "label": "50/23", "naklon": null }, + "4185": { "label": "50/24", "naklon": null }, + "3904": { "label": "50/25", "naklon": null }, + "2619": { "label": "53/1", "naklon": 0 }, + "2623": { "label": "53/2", "naklon": 0 }, + "2617": { "label": "53/3", "naklon": 0 }, + "2622": { "label": "53/4", "naklon": 0 }, + "2618": { "label": "53/5", "naklon": 0 }, + "2626": { "label": "53/6", "naklon": 0 }, + "2869": { "label": "53/7", "naklon": 0 }, + "2613": { "label": "53/8", "naklon": 0 }, + "2608": { "label": "53/9", "naklon": 0 }, + "2611": { "label": "53/10", "naklon": 0 }, + "2598": { "label": "53/11", "naklon": 0 }, + "3528": { "label": "53/12", "naklon": 0 }, + "3545": { "label": "53/13", "naklon": 0 }, + "2620": { "label": "53/14", "naklon": 0 }, + "2612": { "label": "53/15", "naklon": 0 }, + "2615": { "label": "53/16", "naklon": 0 }, + "3722": { "label": "53/17", "naklon": 0 }, + "2624": { "label": "53/18", "naklon": 0 }, + "2609": { "label": "53/19", "naklon": 0 }, + "2625": { "label": "53/20", "naklon": 0 }, + "2602": { "label": "53/21", "naklon": 0 }, + "2610": { "label": "53/22", "naklon": 0 }, + "2599": { "label": "53/23", "naklon": 0 }, + "2605": { "label": "53/24", "naklon": 0 }, + "2593": { "label": "53/25", "naklon": 0 }, + "3074": { "label": "53/26", "naklon": 0 }, + "2740": { "label": "53/27", "naklon": 0 }, + "2614": { "label": "53/28", "naklon": 0 }, + "2601": { "label": "53/29", "naklon": 0 }, + "4196": { "label": "53/30", "naklon": 0 }, + "2607": { "label": "53/31", "naklon": 0 }, + "2582": { "label": "53/32", "naklon": 0 }, + "2594": { "label": "53/33", "naklon": 0 }, + "2589": { "label": "53/34", "naklon": 0 }, + "2596": { "label": "53/35", "naklon": 0 }, + "2603": { "label": "53/36", "naklon": 0 }, + "2597": { "label": "53/37", "naklon": 0 }, + "2590": { "label": "53/38", "naklon": 0 }, + "2581": { "label": "53/39", "naklon": 0 }, + "2583": { "label": "53/40", "naklon": 0 }, + "2580": { "label": "53/41", "naklon": 0 }, + "2579": { "label": "53/42", "naklon": 0 }, + "2797": { "label": "53/43", "naklon": 0 }, + "2577": { "label": "53/44", "naklon": 0 }, + "2586": { "label": "53/45", "naklon": 0 }, + "2588": { "label": "53/46", "naklon": 0 }, + "2591": { "label": "53/47", "naklon": 0 }, + "2592": { "label": "53/48", "naklon": 0 }, + "2573": { "label": "53/49", "naklon": 0 }, + "2595": { "label": "53/50", "naklon": 0 }, + "2587": { "label": "53/51", "naklon": 0 }, + "2578": { "label": "53/52", "naklon": 0 }, + "2574": { "label": "53/53", "naklon": 0 }, + "2571": { "label": "53/54", "naklon": 0 }, + "2570": { "label": "53/55", "naklon": 0 }, + "2576": { "label": "53/56", "naklon": 0 }, + "2881": { "label": "53/57", "naklon": 0 }, + "2575": { "label": "53/58", "naklon": 0 }, + "2572": { "label": "53/59", "naklon": 0 }, + "2569": { "label": "53/60", "naklon": 0 }, + "4324": { "label": "55/1", "naklon": 0 }, + "4319": { "label": "55/2", "naklon": 0 }, + "4327": { "label": "55/3", "naklon": 0 }, + "4333": { "label": "55/4", "naklon": 0 }, + "4332": { "label": "55/5", "naklon": 0 }, + "4320": { "label": "55/6", "naklon": 0 }, + "4317": { "label": "55/7", "naklon": 0 }, + "4318": { "label": "55/8", "naklon": 0 }, + "4328": { "label": "55/9", "naklon": 0 }, + "4323": { "label": "55/10", "naklon": 0 }, + "4325": { "label": "55/11", "naklon": 0 }, + "4326": { "label": "55/12", "naklon": 0 }, + "4316": { "label": "55/13", "naklon": 0 }, + "4322": { "label": "55/14", "naklon": 0 }, + "4331": { "label": "55/15", "naklon": 0 }, + "4321": { "label": "55/16", "naklon": 0 }, + "4315": { "label": "55/17", "naklon": 0 }, + "4329": { "label": "55/18", "naklon": 0 }, + "4334": { "label": "55/19", "naklon": 0 }, + "4330": { "label": "55/20", "naklon": 0 } +}; + + +let svetlaSorted = [{ "label": "1/3A", "node": 3993, "naklon": 0 }, +{ "label": "1/3B", "node": 3989, "naklon": 15 }, +{ "label": "1/1", "node": 3976, "naklon": 0 }, +{ "label": "1/2", "node": 4181, "naklon": 0 }, +{ "label": "1/4", "node": 4376, "naklon": 15 }, +{ "label": "1/5", "node": 3868, "naklon": 15 }, +{ "label": "1/6", "node": 3728, "naklon": 15 }, +{ "label": "1/7", "node": 3730, "naklon": 0 }, +{ "label": "1/8", "node": 4374, "naklon": 0 }, +{ "label": "1/9", "node": 3718, "naklon": 15 }, +{ "label": "1/10", "node": 4375, "naklon": 15 }, +{ "label": "1/11", "node": 4172, "naklon": 15 }, +{ "label": "1/12", "node": 4176, "naklon": 15 }, +{ "label": "2/1", "node": 3800, "naklon": 5 }, +{ "label": "2/2", "node": 3823, "naklon": 5 }, +{ "label": "2/3", "node": 3905, "naklon": 5 }, +{ "label": "2/4", "node": 3803, "naklon": 5 }, +{ "label": "2/5", "node": 3817, "naklon": 5 }, +{ "label": "2/6", "node": 3818, "naklon": 5 }, +{ "label": "2/7", "node": 3811, "naklon": 5 }, +{ "label": "2/8", "node": 3915, "naklon": 5 }, +{ "label": "2/9", "node": 3843, "naklon": 10 }, +{ "label": "2/10", "node": 3827, "naklon": 10 }, +{ "label": "2/11", "node": 4220, "naklon": 10 }, +{ "label": "2/12", "node": 3826, "naklon": 10 }, +{ "label": "2/13", "node": 3834, "naklon": 10 }, +{ "label": "2/14", "node": 3838, "naklon": 10 }, +{ "label": "2/15", "node": 2823, "naklon": 10 }, +{ "label": "2/16", "node": 3750, "naklon": 10 }, +{ "label": "2/17", "node": 3378, "naklon": 0 }, +{ "label": "2/18", "node": 3376, "naklon": 0 }, +{ "label": "2/19", "node": 3379, "naklon": 0 }, +{ "label": "2/20", "node": 3285, "naklon": 0 }, +{ "label": "2/21", "node": 3382, "naklon": 0 }, +{ "label": "2/22", "node": 3383, "naklon": 0 }, +{ "label": "2/24", "node": 3375, "naklon": 0 }, +{ "label": "2/25", "node": 3381, "naklon": 0 }, +{ "label": "2/26", "node": 3380, "naklon": 0 }, +{ "label": "2/27", "node": 3828, "naklon": 10 }, +{ "label": "2/28", "node": 3377, "naklon": 0 }, +{ "label": "7/1", "node": 3591, "naklon": 0 }, +{ "label": "7/2", "node": 3587, "naklon": 0 }, +{ "label": "7/3", "node": 3468, "naklon": 0 }, +{ "label": "7/4", "node": 3466, "naklon": 0 }, +{ "label": "7/5", "node": 3474, "naklon": 0 }, +{ "label": "7/6", "node": 3481, "naklon": 0 }, +{ "label": "7/7", "node": 3589, "naklon": 0 }, +{ "label": "7/8", "node": 3472, "naklon": 0 }, +{ "label": "7/9", "node": 3473, "naklon": 0 }, +{ "label": "7/10", "node": 3584, "naklon": 0 }, +{ "label": "7/11", "node": 3571, "naklon": 0 }, +{ "label": "7/12", "node": 3476, "naklon": 0 }, +{ "label": "7/13", "node": 3590, "naklon": 0 }, +{ "label": "7/14", "node": 3478, "naklon": 0 }, +{ "label": "7/15", "node": 3471, "naklon": 0 }, +{ "label": "7/16", "node": 3467, "naklon": 0 }, +{ "label": "7/17", "node": 3479, "naklon": 0 }, +{ "label": "7/18", "node": 3480, "naklon": 0 }, +{ "label": "7/19", "node": 3477, "naklon": 0 }, +{ "label": "12/1", "node": 3362, "naklon": 0 }, +{ "label": "12/2", "node": 3355, "naklon": 0 }, +{ "label": "12/3", "node": 3356, "naklon": 0 }, +{ "label": "12/4", "node": 3349, "naklon": 0 }, +{ "label": "12/5", "node": 3357, "naklon": 0 }, +{ "label": "12/6", "node": 3350, "naklon": 0 }, +{ "label": "12/7", "node": 3353, "naklon": 0 }, +{ "label": "12/8", "node": 3539, "naklon": 0 }, +{ "label": "12/9", "node": 3050, "naklon": 0 }, +{ "label": "12/10", "node": 3361, "naklon": 0 }, +{ "label": "12/11", "node": 3360, "naklon": 0 }, +{ "label": "12/12", "node": 3358, "naklon": 0 }, +{ "label": "12/13", "node": 3541, "naklon": 0 }, +{ "label": "12/14", "node": 3551, "naklon": 0 }, +{ "label": "12/15", "node": 3514, "naklon": 0 }, +{ "label": "12/16", "node": 3547, "naklon": 0 }, +{ "label": "12/17", "node": 3562, "naklon": 0 }, +{ "label": "12/18", "node": 3525, "naklon": 0 }, +{ "label": "12/19", "node": 3558, "naklon": 0 }, +{ "label": "12/20", "node": 3511, "naklon": 0 }, +{ "label": "12/21", "node": 3058, "naklon": 0 }, +{ "label": "12/22", "node": 3062, "naklon": 0 }, +{ "label": "12/23", "node": 3070, "naklon": 0 }, +{ "label": "12/24", "node": 3447, "naklon": 0 }, +{ "label": "12/25", "node": 3056, "naklon": 0 }, +{ "label": "12/26", "node": 3057, "naklon": 0 }, +{ "label": "12/27", "node": 3071, "naklon": 0 }, +{ "label": "12/28", "node": 3061, "naklon": 0 }, +{ "label": "12/29", "node": 3069, "naklon": 0 }, +{ "label": "12/30", "node": 3077, "naklon": 0 }, +{ "label": "12/31", "node": 3080, "naklon": 0 }, +{ "label": "12/32", "node": 3081, "naklon": 0 }, +{ "label": "12/33", "node": 3078, "naklon": 0 }, +{ "label": "12/34", "node": 4037, "naklon": 0 }, +{ "label": "12/35", "node": 3067, "naklon": 0 }, +{ "label": "12/36", "node": 3051, "naklon": 0 }, +{ "label": "12/37", "node": 2924, "naklon": 0 }, +{ "label": "12/38", "node": 3060, "naklon": 0 }, +{ "label": "12/39", "node": 3073, "naklon": 0 }, +{ "label": "12/40", "node": 3469, "naklon": 0 }, +{ "label": "12/41", "node": 2923, "naklon": 0 }, +{ "label": "12/42", "node": 2925, "naklon": 0 }, +{ "label": "12/43", "node": 3359, "naklon": 0 }, +{ "label": "12/44", "node": 3055, "naklon": 0 }, +{ "label": "12/45", "node": 2922, "naklon": 0 }, +{ "label": "12/46", "node": 3084, "naklon": 0 }, +{ "label": "12/47", "node": 3064, "naklon": 0 }, +{ "label": "12/48", "node": 3066, "naklon": 0 }, +{ "label": "12/49", "node": 3072, "naklon": 0 }, +{ "label": "13/13A", "node": 3415, "naklon": 0 }, +{ "label": "13/13B", "node": 3409, "naklon": 0 }, +{ "label": "13/13C", "node": 3399, "naklon": 0 }, +{ "label": "13/29A", "node": 3410, "naklon": 0 }, +{ "label": "13/29B", "node": 3407, "naklon": 0 }, +{ "label": "13/34A", "node": 3405, "naklon": 0 }, +{ "label": "13/34B", "node": 3404, "naklon": 0 }, +{ "label": "13/45A", "node": 3392, "naklon": 0 }, +{ "label": "13/45B", "node": 3386, "naklon": 0 }, +{ "label": "13/60A", "node": 3303, "naklon": 3 }, +{ "label": "13/60B", "node": 3302, "naklon": 3 }, +{ "label": "13/70A", "node": 3319, "naklon": 6 }, +{ "label": "13/70B", "node": 3317, "naklon": 6 }, +{ "label": "13/70C", "node": 3326, "naklon": 6 }, +{ "label": "13/73A", "node": 3351, "naklon": 6 }, +{ "label": "13/73B", "node": 3313, "naklon": 6 }, +{ "label": "13/83A", "node": 3316, "naklon": 0 }, +{ "label": "13/83B", "node": 3320, "naklon": 0 }, +{ "label": "13/95A", "node": 3336, "naklon": 0 }, +{ "label": "13/95B", "node": 3323, "naklon": 0 }, +{ "label": "13/98A", "node": 3339, "naklon": 0 }, +{ "label": "13/98B", "node": 3333, "naklon": 0 }, +{ "label": "13/1", "node": 3425, "naklon": 0 }, +{ "label": "13/2", "node": 3419, "naklon": 0 }, +{ "label": "13/3", "node": 3416, "naklon": 0 }, +{ "label": "13/4", "node": 3332, "naklon": 0 }, +{ "label": "13/5", "node": 3422, "naklon": 0 }, +{ "label": "13/6", "node": 3417, "naklon": 0 }, +{ "label": "13/7", "node": 3418, "naklon": 0 }, +{ "label": "13/8", "node": 3424, "naklon": 0 }, +{ "label": "13/9", "node": 3334, "naklon": 0 }, +{ "label": "13/10", "node": 4363, "naklon": 0 }, +{ "label": "13/11", "node": 3423, "naklon": 0 }, +{ "label": "13/12", "node": 3406, "naklon": 0 }, +{ "label": "13/14", "node": 3411, "naklon": 0 }, +{ "label": "13/15", "node": 3412, "naklon": 0 }, +{ "label": "13/16", "node": 3413, "naklon": 0 }, +{ "label": "13/17", "node": 3414, "naklon": 0 }, +{ "label": "13/18", "node": 3391, "naklon": 0 }, +{ "label": "13/19", "node": 3370, "naklon": 0 }, +{ "label": "13/20", "node": 3369, "naklon": 0 }, +{ "label": "13/21", "node": 3408, "naklon": 0 }, +{ "label": "13/22", "node": 3393, "naklon": 0 }, +{ "label": "13/23", "node": 3128, "naklon": 0 }, +{ "label": "13/24", "node": 3197, "naklon": 0 }, +{ "label": "13/25", "node": 4364, "naklon": 0 }, +{ "label": "13/26", "node": 3155, "naklon": 0 }, +{ "label": "13/27", "node": 3196, "naklon": 0 }, +{ "label": "13/28", "node": 3144, "naklon": 0 }, +{ "label": "13/30", "node": 3150, "naklon": 0 }, +{ "label": "13/31", "node": 3390, "naklon": 0 }, +{ "label": "13/32", "node": 3401, "naklon": 0 }, +{ "label": "13/33", "node": 3275, "naklon": 0 }, +{ "label": "13/35", "node": 3371, "naklon": 0 }, +{ "label": "13/36", "node": 3389, "naklon": 0 }, +{ "label": "13/37", "node": 3388, "naklon": 0 }, +{ "label": "13/38", "node": 3365, "naklon": 0 }, +{ "label": "13/39", "node": 3363, "naklon": 0 }, +{ "label": "13/40", "node": 3397, "naklon": 0 }, +{ "label": "13/40/1", "node": 3567, "naklon": 0 }, +{ "label": "13/41", "node": 3387, "naklon": 0 }, +{ "label": "13/42", "node": 3403, "naklon": 0 }, +{ "label": "13/43", "node": 3147, "naklon": 0 }, +{ "label": "13/44", "node": 3141, "naklon": 0 }, +{ "label": "13/46", "node": 3364, "naklon": 0 }, +{ "label": "13/47", "node": 3367, "naklon": 0 }, +{ "label": "13/48", "node": 3368, "naklon": 0 }, +{ "label": "13/49", "node": 3402, "naklon": 0 }, +{ "label": "13/50", "node": 3366, "naklon": 0 }, +{ "label": "13/51", "node": 3395, "naklon": 0 }, +{ "label": "13/52", "node": 3372, "naklon": 0 }, +{ "label": "13/53", "node": 3394, "naklon": 0 }, +{ "label": "13/54", "node": 3308, "naklon": 0 }, +{ "label": "13/54/1", "node": 3847, "naklon": 0 }, +{ "label": "13/55", "node": 3312, "naklon": 3 }, +{ "label": "13/56", "node": 3309, "naklon": 3 }, +{ "label": "13/57", "node": 3311, "naklon": 3 }, +{ "label": "13/58", "node": 3310, "naklon": 3 }, +{ "label": "13/59", "node": 4365, "naklon": 3 }, +{ "label": "13/60/1", "node": 4093, "naklon": 3 }, +{ "label": "13/61", "node": 3304, "naklon": 3 }, +{ "label": "13/62", "node": 3307, "naklon": 3 }, +{ "label": "13/63", "node": 3271, "naklon": 3 }, +{ "label": "13/64", "node": 3301, "naklon": 3 }, +{ "label": "13/65", "node": 4366, "naklon": 3 }, +{ "label": "13/66", "node": 3300, "naklon": 3 }, +{ "label": "13/67", "node": 3185, "naklon": 0 }, +{ "label": "13/68", "node": 3184, "naklon": 0 }, +{ "label": "13/69", "node": 3188, "naklon": 0 }, +{ "label": "13/71", "node": 3343, "naklon": 6 }, +{ "label": "13/71/1", "node": 3819, "naklon": 6 }, +{ "label": "13/71/2", "node": 3880, "naklon": 6 }, +{ "label": "13/72", "node": 3348, "naklon": 6 }, +{ "label": "13/74", "node": 3344, "naklon": 6 }, +{ "label": "13/75", "node": 3346, "naklon": 6 }, +{ "label": "13/75/1", "node": 3597, "naklon": 6 }, +{ "label": "13/76", "node": 3345, "naklon": 6 }, +{ "label": "13/77", "node": 3322, "naklon": 0 }, +{ "label": "13/78", "node": 3325, "naklon": 0 }, +{ "label": "13/78/1", "node": 4310, "naklon": 0 }, +{ "label": "13/79", "node": 3315, "naklon": 0 }, +{ "label": "13/80", "node": 3328, "naklon": 0 }, +{ "label": "13/81", "node": 3321, "naklon": 0 }, +{ "label": "13/82", "node": 3324, "naklon": 0 }, +{ "label": "13/84", "node": 3140, "naklon": 0 }, +{ "label": "13/85", "node": 3153, "naklon": 0 }, +{ "label": "13/86", "node": 3145, "naklon": 0 }, +{ "label": "13/87", "node": 3134, "naklon": 0 }, +{ "label": "13/88", "node": 3151, "naklon": 0 }, +{ "label": "13/89", "node": 3143, "naklon": 0 }, +{ "label": "13/90", "node": 3318, "naklon": 0 }, +{ "label": "13/91", "node": 3347, "naklon": 0 }, +{ "label": "13/94", "node": 3314, "naklon": 0 }, +{ "label": "13/96", "node": 3331, "naklon": 0 }, +{ "label": "13/97", "node": 3327, "naklon": 0 }, +{ "label": "13/99", "node": 3329, "naklon": 0 }, +{ "label": "13/100", "node": 3337, "naklon": 0 }, +{ "label": "13/101", "node": 3330, "naklon": 0 }, +{ "label": "13/102", "node": 3335, "naklon": 0 }, +{ "label": "13/103", "node": 3420, "naklon": 0 }, +{ "label": "13/104", "node": 3421, "naklon": 0 }, +{ "label": "13/105", "node": 4361, "naklon": 0 }, +{ "label": "13/106", "node": 4362, "naklon": 0 }, +{ "label": "13/107", "node": 3526, "naklon": 0 }, +{ "label": "13/108", "node": 4424, "naklon": null }, +{ "label": "13/109", "node": 3561, "naklon": null }, +{ "label": "13/110", "node": 3527, "naklon": null }, +{ "label": "13/111", "node": 3521, "naklon": null }, +{ "label": "13/112", "node": 3552, "naklon": null }, +{ "label": "13/113", "node": 3544, "naklon": null }, +{ "label": "13/114", "node": 3534, "naklon": null }, +{ "label": "13/115", "node": 3516, "naklon": null }, +{ "label": "13/116", "node": 3513, "naklon": null }, +{ "label": "13/117", "node": 3565, "naklon": null }, +{ "label": "13/118", "node": 3866, "naklon": null }, +{ "label": "14/1", "node": 3136, "naklon": 0 }, +{ "label": "14/2", "node": 3137, "naklon": 0 }, +{ "label": "14/3", "node": 3135, "naklon": 0 }, +{ "label": "14/4", "node": 3149, "naklon": 0 }, +{ "label": "14/5", "node": 3142, "naklon": 0 }, +{ "label": "14/6", "node": 3342, "naklon": 0 }, +{ "label": "14/7", "node": 3340, "naklon": 0 }, +{ "label": "14/8", "node": 3152, "naklon": 0 }, +{ "label": "14/9", "node": 3886, "naklon": 0 }, +{ "label": "14/10", "node": 3341, "naklon": null }, +{ "label": "14/11", "node": 3352, "naklon": null }, +{ "label": "15/1", "node": 3396, "naklon": 5 }, +{ "label": "15/2", "node": 2784, "naklon": 5 }, +{ "label": "15/3", "node": 2788, "naklon": 5 }, +{ "label": "15/4", "node": 2801, "naklon": 5 }, +{ "label": "15/5", "node": 2815, "naklon": 5 }, +{ "label": "15/6", "node": 2829, "naklon": 5 }, +{ "label": "15/7", "node": 2796, "naklon": 5 }, +{ "label": "15/8", "node": 2803, "naklon": 5 }, +{ "label": "15/8/1", "node": 4304, "naklon": 5 }, +{ "label": "15/8/2", "node": 4311, "naklon": 5 }, +{ "label": "15/9", "node": 2821, "naklon": 5 }, +{ "label": "15/10", "node": 3400, "naklon": 5 }, +{ "label": "15/11", "node": 2799, "naklon": 5 }, +{ "label": "15/12", "node": 2804, "naklon": 5 }, +{ "label": "15/12/1", "node": 4303, "naklon": 5 }, +{ "label": "15/12/2", "node": 4309, "naklon": 5 }, +{ "label": "15/13", "node": 2806, "naklon": 5 }, +{ "label": "15/14", "node": 2787, "naklon": 5 }, +{ "label": "15/15", "node": 2809, "naklon": 5 }, +{ "label": "15/16", "node": 2814, "naklon": 0 }, +{ "label": "15/17", "node": 3934, "naklon": 0 }, +{ "label": "15/18", "node": 3192, "naklon": 0 }, +{ "label": "15/19", "node": 2812, "naklon": 0 }, +{ "label": "15/20", "node": 4070, "naklon": 0 }, +{ "label": "15/21", "node": 2826, "naklon": 0 }, +{ "label": "15/22", "node": 2808, "naklon": 3 }, +{ "label": "15/23", "node": 2795, "naklon": 3 }, +{ "label": "15/24", "node": 2807, "naklon": 3 }, +{ "label": "15/25", "node": 2831, "naklon": 0 }, +{ "label": "15/26", "node": 2862, "naklon": null }, +{ "label": "15/27", "node": 2861, "naklon": 0 }, +{ "label": "15/28", "node": 2866, "naklon": 0 }, +{ "label": "15/28/1", "node": 3546, "naklon": 0 }, +{ "label": "15/29", "node": 4146, "naklon": 0 }, +{ "label": "15/29/1", "node": 3001, "naklon": 0 }, +{ "label": "15/30", "node": 2835, "naklon": 0 }, +{ "label": "15/31", "node": 2874, "naklon": 0 }, +{ "label": "15/32", "node": 2852, "naklon": 0 }, +{ "label": "15/33", "node": 2851, "naklon": 0 }, +{ "label": "15/33/1", "node": 3560, "naklon": 0 }, +{ "label": "15/34", "node": 2858, "naklon": 0 }, +{ "label": "15/34/1", "node": 4306, "naklon": 0 }, +{ "label": "15/35", "node": 2856, "naklon": 0 }, +{ "label": "15/36", "node": 2847, "naklon": 0 }, +{ "label": "15/36/1", "node": 3556, "naklon": 0 }, +{ "label": "15/37", "node": 3950, "naklon": 0 }, +{ "label": "15/38", "node": 2848, "naklon": 0 }, +{ "label": "15/39", "node": 2863, "naklon": 0 }, +{ "label": "15/39/1", "node": 4313, "naklon": 0 }, +{ "label": "15/40", "node": 2873, "naklon": 0 }, +{ "label": "15/40/1", "node": 2984, "naklon": 0 }, +{ "label": "15/41", "node": 2854, "naklon": 0 }, +{ "label": "15/42", "node": 2859, "naklon": 0 }, +{ "label": "15/43", "node": 2872, "naklon": 0 }, +{ "label": "15/44", "node": 2849, "naklon": 0 }, +{ "label": "15/45", "node": 2864, "naklon": 0 }, +{ "label": "15/46", "node": 3553, "naklon": null }, +{ "label": "15/47", "node": 3021, "naklon": null }, +{ "label": "15/47/1", "node": 3008, "naklon": null }, +{ "label": "15/48", "node": 3017, "naklon": null }, +{ "label": "15/49", "node": 3014, "naklon": null }, +{ "label": "15/50", "node": 2981, "naklon": null }, +{ "label": "15/51", "node": 3020, "naklon": null }, +{ "label": "15/52", "node": 3027, "naklon": null }, +{ "label": "15/53", "node": 3006, "naklon": null }, +{ "label": "15/54", "node": 3012, "naklon": null }, +{ "label": "15/55", "node": 2738, "naklon": 0 }, +{ "label": "15/56", "node": 2725, "naklon": 0 }, +{ "label": "15/57", "node": 3016, "naklon": null }, +{ "label": "15/58", "node": 3005, "naklon": null }, +{ "label": "15/58/1", "node": 3009, "naklon": null }, +{ "label": "15/59", "node": 3010, "naklon": 0 }, +{ "label": "15/59/1", "node": 3538, "naklon": 0 }, +{ "label": "15/59/2", "node": 4145, "naklon": 0 }, +{ "label": "15/60", "node": 2713, "naklon": 0 }, +{ "label": "15/61", "node": 2789, "naklon": 0 }, +{ "label": "15/62", "node": 2736, "naklon": 0 }, +{ "label": "15/63", "node": 2739, "naklon": 0 }, +{ "label": "15/64", "node": 4346, "naklon": 0 }, +{ "label": "15/65", "node": 2731, "naklon": 0 }, +{ "label": "15/66", "node": 2818, "naklon": 0 }, +{ "label": "15/66/1", "node": 3557, "naklon": 0 }, +{ "label": "15/67", "node": 2822, "naklon": 0 }, +{ "label": "15/68", "node": 2833, "naklon": 0 }, +{ "label": "15/69", "node": 2834, "naklon": 0 }, +{ "label": "15/70", "node": 3097, "naklon": 0 }, +{ "label": "15/71", "node": 2824, "naklon": 0 }, +{ "label": "15/72", "node": 2828, "naklon": 0 }, +{ "label": "15/73", "node": 2600, "naklon": 0 }, +{ "label": "15/73/1", "node": 4314, "naklon": 0 }, +{ "label": "15/74", "node": 2832, "naklon": 0 }, +{ "label": "15/75", "node": 4360, "naklon": 0 }, +{ "label": "15/76", "node": 2846, "naklon": 0 }, +{ "label": "15/77", "node": 2584, "naklon": 0 }, +{ "label": "15/78", "node": 2843, "naklon": 0 }, +{ "label": "15/78/1", "node": 4308, "naklon": 0 }, +{ "label": "15/79", "node": 4144, "naklon": null }, +{ "label": "15/80", "node": 2844, "naklon": 0 }, +{ "label": "15/81", "node": 2842, "naklon": 0 }, +{ "label": "15/82", "node": 2838, "naklon": 0 }, +{ "label": "15/83", "node": 2837, "naklon": null }, +{ "label": "15/83/1", "node": 3555, "naklon": null }, +{ "label": "15/84", "node": 2839, "naklon": 0 }, +{ "label": "15/85", "node": 2830, "naklon": 0 }, +{ "label": "15/86", "node": 4066, "naklon": 0 }, +{ "label": "15/87", "node": 2836, "naklon": 0 }, +{ "label": "15/88", "node": 2911, "naklon": 0 }, +{ "label": "15/89", "node": 2825, "naklon": 0 }, +{ "label": "15/90", "node": 2811, "naklon": 0 }, +{ "label": "15/94", "node": 3740, "naklon": 15 }, +{ "label": "15/95", "node": 2734, "naklon": 15 }, +{ "label": "15/96", "node": 3105, "naklon": 15 }, +{ "label": "15/97", "node": 2732, "naklon": 15 }, +{ "label": "15/98", "node": 2727, "naklon": 15 }, +{ "label": "15/99", "node": 2735, "naklon": 15 }, +{ "label": "15/100", "node": 3926, "naklon": 15 }, +{ "label": "15/101", "node": 2918, "naklon": 0 }, +{ "label": "15/102", "node": 2705, "naklon": 10 }, +{ "label": "15/103", "node": 2708, "naklon": 10 }, +{ "label": "15/104", "node": 2721, "naklon": 10 }, +{ "label": "15/105", "node": 2719, "naklon": 10 }, +{ "label": "15/106", "node": 2919, "naklon": 10 }, +{ "label": "15/107", "node": 3101, "naklon": 10 }, +{ "label": "15/108", "node": 2853, "naklon": 10 }, +{ "label": "15/109", "node": 2715, "naklon": 10 }, +{ "label": "15/110", "node": 2712, "naklon": 0 }, +{ "label": "15/111", "node": 2711, "naklon": 0 }, +{ "label": "15/112", "node": 2709, "naklon": 0 }, +{ "label": "15/113", "node": 2710, "naklon": 0 }, +{ "label": "15/114", "node": 2907, "naklon": 0 }, +{ "label": "15/115", "node": 2906, "naklon": 0 }, +{ "label": "15/116", "node": 2908, "naklon": 0 }, +{ "label": "15/117", "node": 2901, "naklon": 0 }, +{ "label": "15/118", "node": 2913, "naklon": 0 }, +{ "label": "15/119", "node": 3656, "naklon": 0 }, +{ "label": "15/120", "node": 2781, "naklon": 0 }, +{ "label": "15/121", "node": 2802, "naklon": 0 }, +{ "label": "15/122", "node": 2791, "naklon": 0 }, +{ "label": "15/123", "node": 2783, "naklon": 0 }, +{ "label": "15/124", "node": 2794, "naklon": 0 }, +{ "label": "15/125", "node": 3139, "naklon": 0 }, +{ "label": "15/126", "node": 3229, "naklon": 5 }, +{ "label": "15/127", "node": 3239, "naklon": 5 }, +{ "label": "15/128", "node": 3230, "naklon": 5 }, +{ "label": "15/129", "node": 4016, "naklon": null }, +{ "label": "16/16A", "node": 3608, "naklon": 0 }, +{ "label": "16/16B", "node": 4151, "naklon": 0 }, +{ "label": "16/1", "node": 3710, "naklon": 0 }, +{ "label": "16/2", "node": 3726, "naklon": 0 }, +{ "label": "16/3", "node": 3743, "naklon": 0 }, +{ "label": "16/4", "node": 3724, "naklon": 0 }, +{ "label": "16/5", "node": 3712, "naklon": 0 }, +{ "label": "16/6", "node": 3739, "naklon": 0 }, +{ "label": "16/7", "node": 3742, "naklon": 0 }, +{ "label": "16/8", "node": 3731, "naklon": 0 }, +{ "label": "16/9", "node": 3727, "naklon": 0 }, +{ "label": "16/10", "node": 3729, "naklon": 0 }, +{ "label": "16/11", "node": 3736, "naklon": 0 }, +{ "label": "16/12", "node": 3713, "naklon": 0 }, +{ "label": "16/13", "node": 3715, "naklon": 0 }, +{ "label": "16/14", "node": 3733, "naklon": 0 }, +{ "label": "16/15", "node": 3732, "naklon": 0 }, +{ "label": "16/17", "node": 3634, "naklon": 0 }, +{ "label": "16/18", "node": 3610, "naklon": 0 }, +{ "label": "16/19", "node": 3626, "naklon": 0 }, +{ "label": "16/20", "node": 3618, "naklon": 0 }, +{ "label": "16/21", "node": 3619, "naklon": 0 }, +{ "label": "16/22", "node": 3628, "naklon": 0 }, +{ "label": "16/23", "node": 3615, "naklon": 0 }, +{ "label": "16/24", "node": 3609, "naklon": 0 }, +{ "label": "16/25", "node": 3606, "naklon": 0 }, +{ "label": "16/26", "node": 3624, "naklon": 0 }, +{ "label": "16/27", "node": 3627, "naklon": 0 }, +{ "label": "16/28", "node": 3607, "naklon": 0 }, +{ "label": "16/29", "node": 4370, "naklon": 0 }, +{ "label": "16/30", "node": 3692, "naklon": 0 }, +{ "label": "16/31", "node": 3614, "naklon": 0 }, +{ "label": "16/32", "node": 3623, "naklon": 0 }, +{ "label": "16/33", "node": 4373, "naklon": 0 }, +{ "label": "16/34", "node": 3620, "naklon": 0 }, +{ "label": "16/35", "node": 3685, "naklon": 0 }, +{ "label": "16/36", "node": 3616, "naklon": 0 }, +{ "label": "16/37", "node": 3686, "naklon": 0 }, +{ "label": "16/38", "node": 3688, "naklon": 0 }, +{ "label": "16/39", "node": 3684, "naklon": 0 }, +{ "label": "16/40", "node": 3825, "naklon": 0 }, +{ "label": "16/41", "node": 3865, "naklon": 0 }, +{ "label": "16/42", "node": 3824, "naklon": 0 }, +{ "label": "16/43", "node": 3871, "naklon": 0 }, +{ "label": "16/44", "node": 3801, "naklon": 0 }, +{ "label": "16/45", "node": 3862, "naklon": 0 }, +{ "label": "16/46", "node": 3876, "naklon": 0 }, +{ "label": "16/47", "node": 3861, "naklon": 0 }, +{ "label": "16/48", "node": 4215, "naklon": 0 }, +{ "label": "16/49", "node": 3605, "naklon": 10 }, +{ "label": "16/50", "node": 3603, "naklon": 10 }, +{ "label": "16/51", "node": 3592, "naklon": 10 }, +{ "label": "16/52", "node": 3598, "naklon": 10 }, +{ "label": "16/53", "node": 3594, "naklon": 10 }, +{ "label": "16/54", "node": 3593, "naklon": 10 }, +{ "label": "16/55", "node": 3630, "naklon": 10 }, +{ "label": "16/56", "node": 3763, "naklon": 10 }, +{ "label": "16/57", "node": 3746, "naklon": 10 }, +{ "label": "16/58", "node": 3699, "naklon": 0 }, +{ "label": "16/59", "node": 3698, "naklon": 0 }, +{ "label": "16/60", "node": 3709, "naklon": null }, +{ "label": "16/61", "node": 3708, "naklon": 0 }, +{ "label": "16/62", "node": 3703, "naklon": null }, +{ "label": "16/63", "node": 3700, "naklon": 0 }, +{ "label": "16/64", "node": 3701, "naklon": null }, +{ "label": "16/65", "node": 3704, "naklon": 0 }, +{ "label": "16/66", "node": 3707, "naklon": null }, +{ "label": "16/67", "node": 3810, "naklon": 0 }, +{ "label": "16/68", "node": 4208, "naklon": null }, +{ "label": "16/69", "node": 3867, "naklon": 0 }, +{ "label": "16/70", "node": 4372, "naklon": null }, +{ "label": "16/71", "node": 3881, "naklon": 0 }, +{ "label": "16/72", "node": 4204, "naklon": null }, +{ "label": "16/73", "node": 3869, "naklon": 0 }, +{ "label": "16/74", "node": 4202, "naklon": null }, +{ "label": "16/75", "node": 3830, "naklon": 0 }, +{ "label": "16/76", "node": 3870, "naklon": null }, +{ "label": "16/77", "node": 3964, "naklon": 0 }, +{ "label": "16/78", "node": 3849, "naklon": 0 }, +{ "label": "16/79", "node": 3694, "naklon": null }, +{ "label": "16/80", "node": 3717, "naklon": 0 }, +{ "label": "16/81", "node": 3877, "naklon": null }, +{ "label": "16/82", "node": 3755, "naklon": 0 }, +{ "label": "16/83", "node": 3725, "naklon": null }, +{ "label": "16/84", "node": 3716, "naklon": 0 }, +{ "label": "16/85", "node": 3696, "naklon": null }, +{ "label": "16/86", "node": 3702, "naklon": 0 }, +{ "label": "16/87", "node": 3706, "naklon": null }, +{ "label": "16/88", "node": 3850, "naklon": 0 }, +{ "label": "16/89", "node": 3848, "naklon": null }, +{ "label": "16/90", "node": 3737, "naklon": null }, +{ "label": "16/91", "node": 3705, "naklon": 0 }, +{ "label": "16/92", "node": 3723, "naklon": null }, +{ "label": "16/93", "node": 3842, "naklon": 0 }, +{ "label": "16/94", "node": 3735, "naklon": null }, +{ "label": "16/95", "node": 3719, "naklon": 0 }, +{ "label": "16/96", "node": 3697, "naklon": 0 }, +{ "label": "16/97", "node": 3711, "naklon": 0 }, +{ "label": "16/98", "node": 4107, "naklon": null }, +{ "label": "16/99", "node": 4112, "naklon": 5 }, +{ "label": "16/100", "node": 4106, "naklon": 5 }, +{ "label": "16/101", "node": 4111, "naklon": 5 }, +{ "label": "16/102", "node": 4091, "naklon": null }, +{ "label": "16/103", "node": 4104, "naklon": 5 }, +{ "label": "16/104", "node": 4094, "naklon": null }, +{ "label": "16/105", "node": 4089, "naklon": 5 }, +{ "label": "16/106", "node": 4095, "naklon": null }, +{ "label": "16/107", "node": 4102, "naklon": 5 }, +{ "label": "16/108", "node": 4105, "naklon": null }, +{ "label": "16/109", "node": 3859, "naklon": null }, +{ "label": "16/110", "node": 4090, "naklon": 5 }, +{ "label": "16/111", "node": 4110, "naklon": null }, +{ "label": "16/112", "node": 4097, "naklon": 5 }, +{ "label": "16/113", "node": 4099, "naklon": null }, +{ "label": "16/114", "node": 4096, "naklon": null }, +{ "label": "16/115", "node": 4101, "naklon": 5 }, +{ "label": "16/116", "node": 4109, "naklon": null }, +{ "label": "16/117", "node": 4092, "naklon": 5 }, +{ "label": "16/118", "node": 3631, "naklon": null }, +{ "label": "16/119", "node": 3632, "naklon": 0 }, +{ "label": "16/120", "node": 3641, "naklon": null }, +{ "label": "16/121", "node": 3638, "naklon": 0 }, +{ "label": "16/122", "node": 3637, "naklon": null }, +{ "label": "16/123", "node": 4142, "naklon": null }, +{ "label": "16/124", "node": 4147, "naklon": 5 }, +{ "label": "16/125", "node": 4139, "naklon": 5 }, +{ "label": "20/30A", "node": 3172, "naklon": 2 }, +{ "label": "20/30B", "node": 3164, "naklon": 2 }, +{ "label": "20/1", "node": 3247, "naklon": 10 }, +{ "label": "20/2", "node": 3296, "naklon": 10 }, +{ "label": "20/3", "node": 3246, "naklon": 10 }, +{ "label": "20/4", "node": 3270, "naklon": 10 }, +{ "label": "20/5", "node": 3294, "naklon": 10 }, +{ "label": "20/6", "node": 3298, "naklon": 10 }, +{ "label": "20/7", "node": 3297, "naklon": 10 }, +{ "label": "20/8", "node": 3293, "naklon": 10 }, +{ "label": "20/9", "node": 3299, "naklon": 10 }, +{ "label": "20/10", "node": 3295, "naklon": 10 }, +{ "label": "20/11", "node": 3244, "naklon": 10 }, +{ "label": "20/12", "node": 3249, "naklon": 10 }, +{ "label": "20/13", "node": 3268, "naklon": 10 }, +{ "label": "20/14", "node": 3245, "naklon": 10 }, +{ "label": "20/15", "node": 3278, "naklon": 10 }, +{ "label": "20/16", "node": 3280, "naklon": 10 }, +{ "label": "20/17", "node": 3292, "naklon": 10 }, +{ "label": "20/18", "node": 3287, "naklon": 10 }, +{ "label": "20/19", "node": 3282, "naklon": 10 }, +{ "label": "20/20", "node": 3273, "naklon": 0 }, +{ "label": "20/21", "node": 3157, "naklon": 0 }, +{ "label": "20/22", "node": 3283, "naklon": 0 }, +{ "label": "20/23", "node": 3159, "naklon": 0 }, +{ "label": "20/24", "node": 3289, "naklon": 0 }, +{ "label": "20/25", "node": 3163, "naklon": 0 }, +{ "label": "20/26", "node": 3126, "naklon": 0 }, +{ "label": "20/27", "node": 3171, "naklon": 0 }, +{ "label": "20/28", "node": 3162, "naklon": 0 }, +{ "label": "20/29", "node": 3279, "naklon": 10 }, +{ "label": "20/31", "node": 3173, "naklon": 0 }, +{ "label": "20/32", "node": 3127, "naklon": 0 }, +{ "label": "20/33", "node": 3131, "naklon": 0 }, +{ "label": "20/34", "node": 3129, "naklon": 0 }, +{ "label": "20/35", "node": 3276, "naklon": 2 }, +{ "label": "20/36", "node": 3290, "naklon": 2 }, +{ "label": "20/37", "node": 3132, "naklon": 0 }, +{ "label": "20/38", "node": 3138, "naklon": 0 }, +{ "label": "20/39", "node": 3272, "naklon": 0 }, +{ "label": "20/40", "node": 3291, "naklon": 0 }, +{ "label": "20/41", "node": 3277, "naklon": 10 }, +{ "label": "20/42", "node": 3286, "naklon": 10 }, +{ "label": "20/43", "node": 3281, "naklon": 10 }, +{ "label": "20/44", "node": 3288, "naklon": 10 }, +{ "label": "20/45", "node": 3284, "naklon": 10 }, +{ "label": "20/46", "node": 3167, "naklon": 10 }, +{ "label": "20/47", "node": 3872, "naklon": 0 }, +{ "label": "20/48", "node": 3124, "naklon": 0 }, +{ "label": "20/49", "node": 3133, "naklon": 0 }, +{ "label": "20/50", "node": 3158, "naklon": 0 }, +{ "label": "20/51", "node": 3169, "naklon": 0 }, +{ "label": "20/52", "node": 3146, "naklon": 0 }, +{ "label": "20/53", "node": 3160, "naklon": 0 }, +{ "label": "20/54", "node": 3248, "naklon": 0 }, +{ "label": "20/55", "node": 3156, "naklon": 0 }, +{ "label": "20/56", "node": 3161, "naklon": 0 }, +{ "label": "20/57", "node": 3170, "naklon": 0 }, +{ "label": "20/58", "node": 3168, "naklon": 0 }, +{ "label": "20/59", "node": 3125, "naklon": 0 }, +{ "label": "20/60", "node": 3166, "naklon": 0 }, +{ "label": "20/61", "node": 3130, "naklon": 0 }, +{ "label": "20/62", "node": 3563, "naklon": 0 }, +{ "label": "20/63", "node": 3550, "naklon": null }, +{ "label": "20/67", "node": 3269, "naklon": 0 }, +{ "label": "21/1", "node": 2921, "naklon": 0 }, +{ "label": "21/2", "node": 2707, "naklon": 0 }, +{ "label": "21/3", "node": 2723, "naklon": 0 }, +{ "label": "21/4", "node": 2716, "naklon": 0 }, +{ "label": "21/5", "node": 2717, "naklon": 0 }, +{ "label": "21/6", "node": 2720, "naklon": 0 }, +{ "label": "21/7", "node": 2722, "naklon": 0 }, +{ "label": "21/8", "node": 2718, "naklon": 0 }, +{ "label": "21/9", "node": 2724, "naklon": 0 }, +{ "label": "21/10", "node": 2742, "naklon": 0 }, +{ "label": "21/11", "node": 2743, "naklon": 0 }, +{ "label": "21/12", "node": 2733, "naklon": 0 }, +{ "label": "21/14", "node": 2903, "naklon": 0 }, +{ "label": "21/15", "node": 2917, "naklon": 0 }, +{ "label": "21/16", "node": 2897, "naklon": 0 }, +{ "label": "21/17", "node": 2914, "naklon": 0 }, +{ "label": "21/18", "node": 2898, "naklon": 0 }, +{ "label": "21/19", "node": 2773, "naklon": 0 }, +{ "label": "21/20", "node": 2895, "naklon": 0 }, +{ "label": "21/21", "node": 2896, "naklon": 0 }, +{ "label": "21/22", "node": 2771, "naklon": 0 }, +{ "label": "21/23", "node": 2772, "naklon": 0 }, +{ "label": "21/24", "node": 2793, "naklon": 0 }, +{ "label": "21/25", "node": 2902, "naklon": 0 }, +{ "label": "21/26", "node": 2910, "naklon": 0 }, +{ "label": "21/27", "node": 2909, "naklon": 0 }, +{ "label": "21/28", "node": 2920, "naklon": 0 }, +{ "label": "21/29", "node": 2916, "naklon": 0 }, +{ "label": "21/30", "node": 2904, "naklon": 0 }, +{ "label": "21/31", "node": 2915, "naklon": 0 }, +{ "label": "21/32", "node": 2905, "naklon": 0 }, +{ "label": "21/33", "node": 2900, "naklon": 0 }, +{ "label": "21/34", "node": 2899, "naklon": 0 }, +{ "label": "21/36", "node": 2741, "naklon": 0 }, +{ "label": "21/37", "node": 2714, "naklon": 0 }, +{ "label": "21/38", "node": 2701, "naklon": 0 }, +{ "label": "21/39", "node": 2703, "naklon": 0 }, +{ "label": "21/40", "node": 2704, "naklon": 0 }, +{ "label": "21/41", "node": 2702, "naklon": 0 }, +{ "label": "21/42", "node": 2706, "naklon": 0 }, +{ "label": "21/43", "node": 2776, "naklon": 0 }, +{ "label": "21/44", "node": 2770, "naklon": 0 }, +{ "label": "21/45", "node": 2786, "naklon": 0 }, +{ "label": "21/46", "node": 2779, "naklon": 0 }, +{ "label": "21/47", "node": 2782, "naklon": 0 }, +{ "label": "21/48", "node": 2785, "naklon": 0 }, +{ "label": "21/49", "node": 2769, "naklon": 0 }, +{ "label": "21/50", "node": 3354, "naklon": 0 }, +{ "label": "21/51", "node": 2778, "naklon": 0 }, +{ "label": "21/52", "node": 2775, "naklon": 0 }, +{ "label": "21/53", "node": 2780, "naklon": 0 }, +{ "label": "21/54", "node": 2790, "naklon": 0 }, +{ "label": "21/55", "node": 2792, "naklon": 0 }, +{ "label": "21/56", "node": 2774, "naklon": 0 }, +{ "label": "22/1", "node": 2630, "naklon": 0 }, +{ "label": "22/2", "node": 2631, "naklon": 0 }, +{ "label": "22/3", "node": 2632, "naklon": 0 }, +{ "label": "22/4", "node": 2633, "naklon": 0 }, +{ "label": "22/5", "node": 2634, "naklon": 0 }, +{ "label": "22/6", "node": 2636, "naklon": 0 }, +{ "label": "22/7", "node": 4367, "naklon": 0 }, +{ "label": "22/8", "node": 2637, "naklon": 0 }, +{ "label": "22/9", "node": 2638, "naklon": 0 }, +{ "label": "22/10", "node": 2639, "naklon": 0 }, +{ "label": "22/11", "node": 2640, "naklon": 0 }, +{ "label": "22/12", "node": 2641, "naklon": 0 }, +{ "label": "22/13", "node": 2642, "naklon": 0 }, +{ "label": "22/14", "node": 2643, "naklon": 0 }, +{ "label": "22/15", "node": 2644, "naklon": 0 }, +{ "label": "22/16", "node": 2645, "naklon": 0 }, +{ "label": "22/17", "node": 2646, "naklon": 0 }, +{ "label": "22/18", "node": 2647, "naklon": 0 }, +{ "label": "22/19", "node": 2648, "naklon": 0 }, +{ "label": "22/20", "node": 2649, "naklon": 0 }, +{ "label": "22/21", "node": 2650, "naklon": 0 }, +{ "label": "22/22", "node": 2651, "naklon": 0 }, +{ "label": "22/23", "node": 4103, "naklon": 0 }, +{ "label": "22/24", "node": 2653, "naklon": 0 }, +{ "label": "22/25", "node": 2654, "naklon": 0 }, +{ "label": "22/26", "node": 2655, "naklon": 0 }, +{ "label": "22/27", "node": 2656, "naklon": 0 }, +{ "label": "22/28", "node": 2657, "naklon": 0 }, +{ "label": "22/29", "node": 2658, "naklon": 0 }, +{ "label": "22/30", "node": 2659, "naklon": 0 }, +{ "label": "22/31", "node": 2660, "naklon": 0 }, +{ "label": "22/32", "node": 2661, "naklon": 0 }, +{ "label": "22/32/1", "node": 3015, "naklon": 0 }, +{ "label": "22/33", "node": 2662, "naklon": 0 }, +{ "label": "22/34", "node": 2663, "naklon": 0 }, +{ "label": "22/35", "node": 2664, "naklon": 0 }, +{ "label": "22/36", "node": 2665, "naklon": 0 }, +{ "label": "22/37", "node": 2666, "naklon": 0 }, +{ "label": "22/38", "node": 2667, "naklon": 0 }, +{ "label": "22/39", "node": 2668, "naklon": 0 }, +{ "label": "22/40", "node": 2669, "naklon": null }, +{ "label": "22/41", "node": 2670, "naklon": null }, +{ "label": "22/42", "node": 2671, "naklon": null }, +{ "label": "23/9A", "node": 3087, "naklon": 10 }, +{ "label": "23/9B", "node": 3090, "naklon": 10 }, +{ "label": "23/1", "node": 3075, "naklon": 0 }, +{ "label": "23/2", "node": 3089, "naklon": 0 }, +{ "label": "23/3", "node": 3088, "naklon": 0 }, +{ "label": "23/4", "node": 3228, "naklon": 10 }, +{ "label": "23/5", "node": 2751, "naklon": 10 }, +{ "label": "23/6", "node": 3243, "naklon": 10 }, +{ "label": "23/7", "node": 4349, "naklon": 10 }, +{ "label": "23/8", "node": 3102, "naklon": 10 }, +{ "label": "23/10", "node": 3099, "naklon": 10 }, +{ "label": "23/11", "node": 3103, "naklon": 10 }, +{ "label": "23/12", "node": 3093, "naklon": 10 }, +{ "label": "23/13", "node": 3098, "naklon": 10 }, +{ "label": "23/14", "node": 3092, "naklon": 10 }, +{ "label": "23/15", "node": 3233, "naklon": 0 }, +{ "label": "23/16", "node": 3095, "naklon": 0 }, +{ "label": "23/17", "node": 4074, "naklon": 0 }, +{ "label": "23/18", "node": 2729, "naklon": 0 }, +{ "label": "23/19", "node": 3234, "naklon": 0 }, +{ "label": "23/20", "node": 3094, "naklon": 0 }, +{ "label": "23/21", "node": 2817, "naklon": 0 }, +{ "label": "23/22", "node": 3226, "naklon": 0 }, +{ "label": "23/23", "node": 3225, "naklon": 0 }, +{ "label": "23/24", "node": 3237, "naklon": 0 }, +{ "label": "23/25", "node": 4250, "naklon": 0 }, +{ "label": "23/26", "node": 3059, "naklon": 10 }, +{ "label": "23/27", "node": 3238, "naklon": 10 }, +{ "label": "23/28", "node": 3242, "naklon": 10 }, +{ "label": "23/29", "node": 3236, "naklon": 10 }, +{ "label": "23/30", "node": 3112, "naklon": 10 }, +{ "label": "23/31", "node": 3224, "naklon": 0 }, +{ "label": "23/32", "node": 4298, "naklon": 10 }, +{ "label": "23/33", "node": 4150, "naklon": 10 }, +{ "label": "23/34", "node": 3091, "naklon": 10 }, +{ "label": "25/1", "node": 3771, "naklon": 5 }, +{ "label": "25/2", "node": 3777, "naklon": 5 }, +{ "label": "25/3", "node": 3749, "naklon": 5 }, +{ "label": "25/4", "node": 3769, "naklon": 5 }, +{ "label": "25/5", "node": 3765, "naklon": 5 }, +{ "label": "25/6", "node": 3785, "naklon": 5 }, +{ "label": "25/7", "node": 3761, "naklon": 5 }, +{ "label": "25/8", "node": 3758, "naklon": 5 }, +{ "label": "25/9", "node": 3766, "naklon": 5 }, +{ "label": "25/10", "node": 3779, "naklon": 5 }, +{ "label": "25/11", "node": 3899, "naklon": 10 }, +{ "label": "25/12", "node": 3922, "naklon": 10 }, +{ "label": "25/13", "node": 3912, "naklon": 10 }, +{ "label": "25/14", "node": 3933, "naklon": 10 }, +{ "label": "25/15", "node": 3921, "naklon": 10 }, +{ "label": "25/16", "node": 4300, "naklon": 10 }, +{ "label": "25/17", "node": 3927, "naklon": 10 }, +{ "label": "25/18", "node": 3212, "naklon": 10 }, +{ "label": "25/19", "node": 3208, "naklon": 10 }, +{ "label": "25/20", "node": 3207, "naklon": 10 }, +{ "label": "25/21", "node": 4294, "naklon": 10 }, +{ "label": "25/22", "node": 3209, "naklon": 10 }, +{ "label": "25/23", "node": 3745, "naklon": 10 }, +{ "label": "25/24", "node": 3762, "naklon": 10 }, +{ "label": "25/25", "node": 3215, "naklon": 10 }, +{ "label": "25/26", "node": 3210, "naklon": 10 }, +{ "label": "25/27", "node": 3211, "naklon": 10 }, +{ "label": "25/28", "node": 3206, "naklon": 10 }, +{ "label": "25/29", "node": 3918, "naklon": 5 }, +{ "label": "25/30", "node": 3928, "naklon": 5 }, +{ "label": "25/31", "node": 3917, "naklon": 5 }, +{ "label": "25/32", "node": 4029, "naklon": 0 }, +{ "label": "25/33", "node": 4038, "naklon": 0 }, +{ "label": "25/34", "node": 4022, "naklon": 0 }, +{ "label": "25/35", "node": 3937, "naklon": 0 }, +{ "label": "25/36", "node": 3190, "naklon": 0 }, +{ "label": "25/37", "node": 3835, "naklon": 0 }, +{ "label": "25/38", "node": 3201, "naklon": 0 }, +{ "label": "25/39", "node": 3193, "naklon": 0 }, +{ "label": "25/40", "node": 3191, "naklon": 0 }, +{ "label": "25/41", "node": 3203, "naklon": 0 }, +{ "label": "25/42", "node": 4301, "naklon": 0 }, +{ "label": "25/43", "node": 3223, "naklon": 0 }, +{ "label": "25/44", "node": 3202, "naklon": 0 }, +{ "label": "25/45", "node": 3205, "naklon": 0 }, +{ "label": "25/46", "node": 3194, "naklon": 0 }, +{ "label": "25/47", "node": 3198, "naklon": 0 }, +{ "label": "25/48", "node": 3204, "naklon": 0 }, +{ "label": "25/49", "node": 3200, "naklon": 0 }, +{ "label": "25/50", "node": 3216, "naklon": 0 }, +{ "label": "25/51", "node": 3932, "naklon": 5 }, +{ "label": "25/52", "node": 3923, "naklon": 5 }, +{ "label": "25/53", "node": 3913, "naklon": 5 }, +{ "label": "25/54", "node": 3900, "naklon": 5 }, +{ "label": "25/55", "node": 4189, "naklon": 10 }, +{ "label": "25/56", "node": 4191, "naklon": 10 }, +{ "label": "25/57", "node": 3790, "naklon": 10 }, +{ "label": "25/58", "node": 4190, "naklon": 10 }, +{ "label": "25/59", "node": 4302, "naklon": 0 }, +{ "label": "25/60", "node": 4351, "naklon": 0 }, +{ "label": "25/61", "node": 4075, "naklon": 0 }, +{ "label": "25/62", "node": 4071, "naklon": 0 }, +{ "label": "25/63", "node": 3784, "naklon": 0 }, +{ "label": "25/64", "node": 4065, "naklon": 0 }, +{ "label": "25/65", "node": 4297, "naklon": 0 }, +{ "label": "25/66", "node": 4295, "naklon": 0 }, +{ "label": "25/67", "node": 4299, "naklon": 0 }, +{ "label": "25/68", "node": 3772, "naklon": 0 }, +{ "label": "25/69", "node": 3941, "naklon": 0 }, +{ "label": "25/70", "node": 3782, "naklon": 0 }, +{ "label": "25/71", "node": 4068, "naklon": 0 }, +{ "label": "25/72", "node": 4073, "naklon": 0 }, +{ "label": "25/73", "node": 3901, "naklon": 5 }, +{ "label": "25/74", "node": 4296, "naklon": 5 }, +{ "label": "25/75", "node": 3910, "naklon": 5 }, +{ "label": "25/76", "node": 4293, "naklon": 5 }, +{ "label": "25/77", "node": 3919, "naklon": 5 }, +{ "label": "25/78", "node": 3924, "naklon": 5 }, +{ "label": "25/79", "node": 3909, "naklon": 5 }, +{ "label": "25/80", "node": 3896, "naklon": 5 }, +{ "label": "25/81", "node": 3911, "naklon": 5 }, +{ "label": "25/82", "node": 2819, "naklon": 15 }, +{ "label": "25/83", "node": 3776, "naklon": 15 }, +{ "label": "25/84", "node": 3752, "naklon": 15 }, +{ "label": "25/85", "node": 4353, "naklon": 15 }, +{ "label": "25/86", "node": 3791, "naklon": 0 }, +{ "label": "25/87", "node": 3770, "naklon": 0 }, +{ "label": "25/88", "node": 3760, "naklon": 0 }, +{ "label": "25/89", "node": 3115, "naklon": 0 }, +{ "label": "25/90", "node": 3738, "naklon": 0 }, +{ "label": "25/91", "node": 3748, "naklon": 0 }, +{ "label": "25/92", "node": 3753, "naklon": 0 }, +{ "label": "25/93", "node": 3775, "naklon": 0 }, +{ "label": "25/94", "node": 3778, "naklon": 5 }, +{ "label": "25/95", "node": 4078, "naklon": 5 }, +{ "label": "25/96", "node": 4088, "naklon": 5 }, +{ "label": "25/97", "node": 3856, "naklon": 5 }, +{ "label": "25/98", "node": 4084, "naklon": 5 }, +{ "label": "25/99", "node": 4069, "naklon": 5 }, +{ "label": "25/100", "node": 4188, "naklon": 5 }, +{ "label": "25/101", "node": 4064, "naklon": 5 }, +{ "label": "25/102", "node": 3792, "naklon": 5 }, +{ "label": "25/103", "node": 3780, "naklon": 5 }, +{ "label": "25/104", "node": 4034, "naklon": 5 }, +{ "label": "25/105", "node": 4072, "naklon": 5 }, +{ "label": "25/106", "node": 3884, "naklon": 5 }, +{ "label": "25/107", "node": 3793, "naklon": 5 }, +{ "label": "25/108", "node": 3863, "naklon": 5 }, +{ "label": "25/109", "node": 3855, "naklon": 5 }, +{ "label": "33/1", "node": 3846, "naklon": 0 }, +{ "label": "33/2", "node": 3943, "naklon": 0 }, +{ "label": "33/3", "node": 3903, "naklon": 0 }, +{ "label": "33/4", "node": 3982, "naklon": 0 }, +{ "label": "33/5", "node": 3879, "naklon": 0 }, +{ "label": "33/6", "node": 3887, "naklon": 0 }, +{ "label": "33/7", "node": 3920, "naklon": 5 }, +{ "label": "33/8", "node": 3942, "naklon": 5 }, +{ "label": "33/9", "node": 3829, "naklon": null }, +{ "label": "34/79A", "node": 3452, "naklon": 6 }, +{ "label": "34/79B", "node": 3460, "naklon": 6 }, +{ "label": "34/90A", "node": 3443, "naklon": 6 }, +{ "label": "34/90B", "node": 3445, "naklon": 6 }, +{ "label": "34/90C", "node": 3457, "naklon": 6 }, +{ "label": "34/97A", "node": 3461, "naklon": 6 }, +{ "label": "34/97B", "node": 3463, "naklon": 6 }, +{ "label": "34/98A", "node": 3426, "naklon": 6 }, +{ "label": "34/98B", "node": 3444, "naklon": 6 }, +{ "label": "34/99A", "node": 3453, "naklon": 6 }, +{ "label": "34/99B", "node": 3455, "naklon": 6 }, +{ "label": "34/1", "node": 4009, "naklon": 0 }, +{ "label": "34/2", "node": 3602, "naklon": 0 }, +{ "label": "34/3", "node": 3441, "naklon": 0 }, +{ "label": "34/4", "node": 3464, "naklon": 0 }, +{ "label": "34/5", "node": 3883, "naklon": 0 }, +{ "label": "34/6", "node": 4098, "naklon": 0 }, +{ "label": "34/7", "node": 4003, "naklon": 0 }, +{ "label": "34/8", "node": 4004, "naklon": 0 }, +{ "label": "34/9", "node": 3888, "naklon": 0 }, +{ "label": "34/10", "node": 3997, "naklon": 0 }, +{ "label": "34/11", "node": 4006, "naklon": 0 }, +{ "label": "34/12", "node": 4000, "naklon": 0 }, +{ "label": "34/13", "node": 4011, "naklon": 0 }, +{ "label": "34/14", "node": 3999, "naklon": 0 }, +{ "label": "34/15", "node": 3981, "naklon": 0 }, +{ "label": "34/16", "node": 3988, "naklon": 0 }, +{ "label": "34/17", "node": 3986, "naklon": 0 }, +{ "label": "34/18", "node": 3998, "naklon": 0 }, +{ "label": "34/19", "node": 3983, "naklon": 0 }, +{ "label": "34/20", "node": 4005, "naklon": 0 }, +{ "label": "34/21", "node": 4001, "naklon": 0 }, +{ "label": "34/22", "node": 4008, "naklon": 0 }, +{ "label": "34/23", "node": 4002, "naklon": 0 }, +{ "label": "34/24", "node": 3996, "naklon": 0 }, +{ "label": "34/25", "node": 4007, "naklon": 0 }, +{ "label": "34/26", "node": 4113, "naklon": 15 }, +{ "label": "34/27", "node": 3595, "naklon": 5 }, +{ "label": "34/28", "node": 3599, "naklon": 5 }, +{ "label": "34/29", "node": 3601, "naklon": 5 }, +{ "label": "34/30", "node": 4205, "naklon": 0 }, +{ "label": "34/31", "node": 3987, "naklon": null }, +{ "label": "34/32", "node": 4214, "naklon": 0 }, +{ "label": "34/33", "node": 4226, "naklon": 0 }, +{ "label": "34/34", "node": 4209, "naklon": 0 }, +{ "label": "34/35", "node": 4201, "naklon": 0 }, +{ "label": "34/36", "node": 3440, "naklon": 0 }, +{ "label": "34/37", "node": 3465, "naklon": 0 }, +{ "label": "34/38", "node": 3446, "naklon": 0 }, +{ "label": "34/39", "node": 4039, "naklon": 5 }, +{ "label": "34/40", "node": 4057, "naklon": 5 }, +{ "label": "34/41", "node": 3985, "naklon": 0 }, +{ "label": "34/42", "node": 3882, "naklon": 0 }, +{ "label": "34/43", "node": 4040, "naklon": 5 }, +{ "label": "34/44", "node": 3231, "naklon": 0 }, +{ "label": "34/45", "node": 3227, "naklon": 0 }, +{ "label": "34/46", "node": 3431, "naklon": 0 }, +{ "label": "34/47", "node": 4013, "naklon": 0 }, +{ "label": "34/48", "node": 4045, "naklon": 0 }, +{ "label": "34/49", "node": 3949, "naklon": 0 }, +{ "label": "34/50", "node": 3953, "naklon": 0 }, +{ "label": "34/51", "node": 3952, "naklon": 0 }, +{ "label": "34/52", "node": 3995, "naklon": 0 }, +{ "label": "34/53", "node": 3992, "naklon": 0 }, +{ "label": "34/54", "node": 4198, "naklon": 0 }, +{ "label": "34/55", "node": 3935, "naklon": 0 }, +{ "label": "34/56", "node": 4050, "naklon": 0 }, +{ "label": "34/57", "node": 4049, "naklon": 0 }, +{ "label": "34/58", "node": 4054, "naklon": 0 }, +{ "label": "34/59", "node": 3663, "naklon": 6 }, +{ "label": "34/60", "node": 3661, "naklon": 6 }, +{ "label": "34/61", "node": 3664, "naklon": 6 }, +{ "label": "34/62", "node": 3660, "naklon": 6 }, +{ "label": "34/63", "node": 3662, "naklon": 6 }, +{ "label": "34/65", "node": 3665, "naklon": 6 }, +{ "label": "34/66", "node": 3667, "naklon": 6 }, +{ "label": "34/67", "node": 3675, "naklon": 6 }, +{ "label": "34/68", "node": 3666, "naklon": 6 }, +{ "label": "34/69", "node": 3652, "naklon": 6 }, +{ "label": "34/70", "node": 3458, "naklon": 6 }, +{ "label": "34/70/1", "node": 4425, "naklon": 6 }, +{ "label": "34/71", "node": 3459, "naklon": 6 }, +{ "label": "34/72", "node": 3435, "naklon": 6 }, +{ "label": "34/73", "node": 3448, "naklon": 6 }, +{ "label": "34/74", "node": 3451, "naklon": 6 }, +{ "label": "34/75", "node": 3442, "naklon": 6 }, +{ "label": "34/76", "node": 3449, "naklon": 6 }, +{ "label": "34/77", "node": 3450, "naklon": 6 }, +{ "label": "34/78", "node": 3433, "naklon": 6 }, +{ "label": "34/80", "node": 3432, "naklon": 12 }, +{ "label": "34/81", "node": 3470, "naklon": 12 }, +{ "label": "34/82", "node": 3438, "naklon": 12 }, +{ "label": "34/83", "node": 3439, "naklon": 12 }, +{ "label": "34/84", "node": 4028, "naklon": 5 }, +{ "label": "34/85", "node": 3596, "naklon": 5 }, +{ "label": "34/86", "node": 4021, "naklon": 5 }, +{ "label": "34/87", "node": 3437, "naklon": 12 }, +{ "label": "34/88", "node": 3428, "naklon": 12 }, +{ "label": "34/89", "node": 3430, "naklon": 12 }, +{ "label": "34/91", "node": 3454, "naklon": 6 }, +{ "label": "34/92", "node": 3492, "naklon": 6 }, +{ "label": "34/93", "node": 3462, "naklon": 6 }, +{ "label": "34/94", "node": 3427, "naklon": 6 }, +{ "label": "34/95", "node": 3434, "naklon": 6 }, +{ "label": "34/96", "node": 3456, "naklon": 6 }, +{ "label": "34/98/1", "node": 4307, "naklon": 6 }, +{ "label": "35/1", "node": 3968, "naklon": 0 }, +{ "label": "35/2", "node": 3969, "naklon": 0 }, +{ "label": "35/3", "node": 3947, "naklon": 0 }, +{ "label": "35/4", "node": 3979, "naklon": 0 }, +{ "label": "35/5", "node": 3959, "naklon": 0 }, +{ "label": "35/6", "node": 3948, "naklon": 0 }, +{ "label": "35/7", "node": 3961, "naklon": 0 }, +{ "label": "35/8", "node": 3956, "naklon": 0 }, +{ "label": "35/9", "node": 3604, "naklon": 0 }, +{ "label": "35/10", "node": 3944, "naklon": 0 }, +{ "label": "35/11", "node": 3960, "naklon": 0 }, +{ "label": "35/12", "node": 3958, "naklon": 0 }, +{ "label": "35/13", "node": 4036, "naklon": 5 }, +{ "label": "35/18", "node": 3893, "naklon": 5 }, +{ "label": "35/19", "node": 4108, "naklon": 5 }, +{ "label": "35/20", "node": 4017, "naklon": 5 }, +{ "label": "35/21", "node": 3963, "naklon": 0 }, +{ "label": "35/22", "node": 3658, "naklon": 0 }, +{ "label": "35/23", "node": 3975, "naklon": 0 }, +{ "label": "35/24", "node": 3980, "naklon": 0 }, +{ "label": "35/25", "node": 4012, "naklon": 0 }, +{ "label": "35/26", "node": 3655, "naklon": 0 }, +{ "label": "35/27", "node": 3962, "naklon": 0 }, +{ "label": "35/28", "node": 3945, "naklon": 0 }, +{ "label": "35/29", "node": 3569, "naklon": 0 }, +{ "label": "35/30", "node": 3429, "naklon": 0 }, +{ "label": "35/31", "node": 3657, "naklon": 0 }, +{ "label": "35/32", "node": 3646, "naklon": 0 }, +{ "label": "35/33", "node": 3622, "naklon": 0 }, +{ "label": "35/34", "node": 3612, "naklon": 0 }, +{ "label": "35/35", "node": 3955, "naklon": 0 }, +{ "label": "35/37", "node": 3878, "naklon": 0 }, +{ "label": "35/38", "node": 3965, "naklon": 0 }, +{ "label": "35/39", "node": 3970, "naklon": 0 }, +{ "label": "35/40", "node": 3611, "naklon": 0 }, +{ "label": "35/41", "node": 2635, "naklon": 0 }, +{ "label": "35/42", "node": 3978, "naklon": 0 }, +{ "label": "35/43", "node": 4213, "naklon": 0 }, +{ "label": "35/44", "node": 3984, "naklon": 0 }, +{ "label": "35/45", "node": 4218, "naklon": 0 }, +{ "label": "35/46", "node": 3973, "naklon": 0 }, +{ "label": "35/47", "node": 3974, "naklon": 0 }, +{ "label": "35/48", "node": 3759, "naklon": 0 }, +{ "label": "35/49", "node": 3844, "naklon": 0 }, +{ "label": "35/50", "node": 3804, "naklon": 0 }, +{ "label": "35/51", "node": 3831, "naklon": 0 }, +{ "label": "35/52", "node": 3643, "naklon": 0 }, +{ "label": "35/53", "node": 3966, "naklon": 0 }, +{ "label": "35/54", "node": 3971, "naklon": 0 }, +{ "label": "35/55", "node": 3650, "naklon": 6 }, +{ "label": "35/56", "node": 3651, "naklon": 6 }, +{ "label": "35/57", "node": 3669, "naklon": 6 }, +{ "label": "35/58", "node": 3648, "naklon": 6 }, +{ "label": "35/59", "node": 3645, "naklon": 6 }, +{ "label": "35/60", "node": 3659, "naklon": 6 }, +{ "label": "35/61", "node": 3647, "naklon": 6 }, +{ "label": "35/62", "node": 3644, "naklon": 6 }, +{ "label": "35/63", "node": 3671, "naklon": 6 }, +{ "label": "35/64", "node": 3682, "naklon": 6 }, +{ "label": "35/65", "node": 3672, "naklon": 6 }, +{ "label": "35/66", "node": 3683, "naklon": 6 }, +{ "label": "35/67", "node": 3673, "naklon": 6 }, +{ "label": "35/68", "node": 3674, "naklon": 6 }, +{ "label": "35/69", "node": 3679, "naklon": 6 }, +{ "label": "35/70", "node": 3649, "naklon": 6 }, +{ "label": "35/71", "node": 3687, "naklon": 6 }, +{ "label": "35/72", "node": 3677, "naklon": 6 }, +{ "label": "35/73", "node": 3690, "naklon": 6 }, +{ "label": "35/74", "node": 3691, "naklon": 6 }, +{ "label": "35/75", "node": 3676, "naklon": 6 }, +{ "label": "35/76", "node": 3680, "naklon": 6 }, +{ "label": "35/77", "node": 3668, "naklon": 6 }, +{ "label": "35/78", "node": 3681, "naklon": 6 }, +{ "label": "35/79", "node": 3670, "naklon": 6 }, +{ "label": "35/80", "node": 3689, "naklon": 6 }, +{ "label": "35/81", "node": 3678, "naklon": 6 }, +{ "label": "35/82", "node": 3693, "naklon": 6 }, +{ "label": "35/83", "node": 3654, "naklon": null }, +{ "label": "36/1", "node": 4086, "naklon": 0 }, +{ "label": "36/2", "node": 4085, "naklon": 0 }, +{ "label": "36/3", "node": 4083, "naklon": 0 }, +{ "label": "36/4", "node": 4087, "naklon": 0 }, +{ "label": "36/5", "node": 4077, "naklon": 0 }, +{ "label": "36/6", "node": 4082, "naklon": 0 }, +{ "label": "36/7", "node": 4186, "naklon": 0 }, +{ "label": "36/8", "node": 4206, "naklon": 0 }, +{ "label": "36/9", "node": 4080, "naklon": 0 }, +{ "label": "36/10", "node": 4081, "naklon": 0 }, +{ "label": "36/11", "node": 4210, "naklon": 0 }, +{ "label": "36/12", "node": 4079, "naklon": 0 }, +{ "label": "36/13", "node": 4076, "naklon": 0 }, +{ "label": "36/14", "node": 3852, "naklon": 0 }, +{ "label": "36/15", "node": 2813, "naklon": 0 }, +{ "label": "36/16", "node": 4219, "naklon": 0 }, +{ "label": "37/1A", "node": 3104, "naklon": 15 }, +{ "label": "37/1B", "node": 3121, "naklon": 15 }, +{ "label": "37/2", "node": 3113, "naklon": 10 }, +{ "label": "37/3", "node": 3118, "naklon": 10 }, +{ "label": "37/4", "node": 3111, "naklon": 10 }, +{ "label": "37/5", "node": 4020, "naklon": 10 }, +{ "label": "37/6", "node": 3119, "naklon": 10 }, +{ "label": "37/7", "node": 3110, "naklon": 10 }, +{ "label": "37/8", "node": 3108, "naklon": 10 }, +{ "label": "37/12", "node": 3107, "naklon": 0 }, +{ "label": "37/13", "node": 3199, "naklon": 0 }, +{ "label": "37/14", "node": 3120, "naklon": 0 }, +{ "label": "37/15", "node": 3122, "naklon": 0 }, +{ "label": "37/16", "node": 3908, "naklon": 0 }, +{ "label": "37/17", "node": 3114, "naklon": 0 }, +{ "label": "37/18", "node": 3105, "naklon": 0 }, +{ "label": "37/19", "node": 3116, "naklon": 0 }, +{ "label": "37/20", "node": 3106, "naklon": 0 }, +{ "label": "37/21", "node": 2887, "naklon": 5 }, +{ "label": "37/22", "node": 2888, "naklon": 5 }, +{ "label": "37/23", "node": 2877, "naklon": 5 }, +{ "label": "37/24", "node": 2891, "naklon": 5 }, +{ "label": "37/25", "node": 2886, "naklon": 5 }, +{ "label": "37/26", "node": 2892, "naklon": 5 }, +{ "label": "37/27", "node": 2882, "naklon": 5 }, +{ "label": "37/28", "node": 2883, "naklon": 5 }, +{ "label": "37/29", "node": 2876, "naklon": 5 }, +{ "label": "37/30", "node": 3109, "naklon": 5 }, +{ "label": "37/31", "node": 4152, "naklon": 5 }, +{ "label": "37/32", "node": 3117, "naklon": 5 }, +{ "label": "37/33", "node": 2870, "naklon": 5 }, +{ "label": "37/34", "node": 2867, "naklon": 0 }, +{ "label": "37/35", "node": 2865, "naklon": 0 }, +{ "label": "37/36", "node": 3096, "naklon": 0 }, +{ "label": "37/37", "node": 2871, "naklon": 0 }, +{ "label": "37/38", "node": 2884, "naklon": 0 }, +{ "label": "37/39", "node": 2855, "naklon": 0 }, +{ "label": "37/40", "node": 2878, "naklon": 0 }, +{ "label": "37/41", "node": 2889, "naklon": 0 }, +{ "label": "37/42", "node": 2879, "naklon": 0 }, +{ "label": "37/43", "node": 2850, "naklon": 0 }, +{ "label": "37/44", "node": 2894, "naklon": 0 }, +{ "label": "37/45", "node": 2880, "naklon": 0 }, +{ "label": "37/46", "node": 2893, "naklon": 0 }, +{ "label": "37/47", "node": 2890, "naklon": 0 }, +{ "label": "37/48", "node": 4355, "naklon": 0 }, +{ "label": "37/49", "node": 2885, "naklon": 0 }, +{ "label": "37/50", "node": 2875, "naklon": 0 }, +{ "label": "38/30A", "node": 3486, "naklon": 5 }, +{ "label": "38/30B", "node": 3714, "naklon": 0 }, +{ "label": "38/32A", "node": 3483, "naklon": 5 }, +{ "label": "38/32B", "node": 3496, "naklon": 0 }, +{ "label": "38/35A", "node": 3487, "naklon": 5 }, +{ "label": "38/35B", "node": 3498, "naklon": 5 }, +{ "label": "38/38A", "node": 3578, "naklon": 5 }, +{ "label": "38/38B", "node": 3508, "naklon": 5 }, +{ "label": "38/59A", "node": 3787, "naklon": 5 }, +{ "label": "38/59B", "node": 3491, "naklon": 5 }, +{ "label": "38/1", "node": 3568, "naklon": null }, +{ "label": "38/2", "node": 3502, "naklon": 0 }, +{ "label": "38/3", "node": 3836, "naklon": 0 }, +{ "label": "38/4", "node": 3588, "naklon": 0 }, +{ "label": "38/5", "node": 3493, "naklon": 0 }, +{ "label": "38/6", "node": 3580, "naklon": 0 }, +{ "label": "38/7", "node": 3572, "naklon": 0 }, +{ "label": "38/8", "node": 3506, "naklon": 0 }, +{ "label": "38/9", "node": 3503, "naklon": 0 }, +{ "label": "38/10", "node": 3579, "naklon": 0 }, +{ "label": "38/11", "node": 3586, "naklon": 0 }, +{ "label": "38/12", "node": 3495, "naklon": 5 }, +{ "label": "38/13", "node": 3492, "naklon": 5 }, +{ "label": "38/14", "node": 3532, "naklon": 5 }, +{ "label": "38/15", "node": 3574, "naklon": 5 }, +{ "label": "38/16", "node": 4140, "naklon": 5 }, +{ "label": "38/17", "node": 3795, "naklon": 5 }, +{ "label": "38/18", "node": 3788, "naklon": 5 }, +{ "label": "38/19", "node": 3796, "naklon": 5 }, +{ "label": "38/20", "node": 3797, "naklon": 5 }, +{ "label": "38/21", "node": 3798, "naklon": 5 }, +{ "label": "38/22", "node": 3786, "naklon": 5 }, +{ "label": "38/23", "node": 4067, "naklon": 5 }, +{ "label": "38/24", "node": 3773, "naklon": 5 }, +{ "label": "38/25", "node": 3774, "naklon": 5 }, +{ "label": "38/26", "node": 3789, "naklon": 5 }, +{ "label": "38/27", "node": 3520, "naklon": null }, +{ "label": "38/29", "node": 3577, "naklon": 5 }, +{ "label": "38/31", "node": 3530, "naklon": null }, +{ "label": "38/33", "node": 3488, "naklon": 5 }, +{ "label": "38/34", "node": 3505, "naklon": 5 }, +{ "label": "38/36", "node": 3497, "naklon": 5 }, +{ "label": "38/37", "node": 3490, "naklon": 5 }, +{ "label": "38/39", "node": 3585, "naklon": 5 }, +{ "label": "38/40", "node": 3582, "naklon": 5 }, +{ "label": "38/41", "node": 3507, "naklon": 5 }, +{ "label": "38/42", "node": 3484, "naklon": 5 }, +{ "label": "38/43", "node": 3501, "naklon": 5 }, +{ "label": "38/44", "node": 3581, "naklon": 5 }, +{ "label": "38/45", "node": 4192, "naklon": 5 }, +{ "label": "38/46", "node": 3576, "naklon": 5 }, +{ "label": "38/47", "node": 3489, "naklon": 5 }, +{ "label": "38/48", "node": 3573, "naklon": 5 }, +{ "label": "38/49", "node": 3504, "naklon": 5 }, +{ "label": "38/50", "node": 3794, "naklon": 5 }, +{ "label": "38/51", "node": 3485, "naklon": 5 }, +{ "label": "38/52", "node": 3482, "naklon": 5 }, +{ "label": "38/53", "node": 3575, "naklon": 5 }, +{ "label": "38/54", "node": 3499, "naklon": 5 }, +{ "label": "38/55", "node": 3494, "naklon": 5 }, +{ "label": "38/56", "node": 3583, "naklon": 5 }, +{ "label": "38/57", "node": 3570, "naklon": 5 }, +{ "label": "38/58", "node": 3500, "naklon": 0 }, +{ "label": "38/63", "node": 3510, "naklon": null }, +{ "label": "38/64", "node": 3512, "naklon": null }, +{ "label": "38/67", "node": 3535, "naklon": null }, +{ "label": "38/68", "node": 3531, "naklon": null }, +{ "label": "38/69", "node": 3537, "naklon": null }, +{ "label": "39/1", "node": 3522, "naklon": 10 }, +{ "label": "39/2", "node": 4018, "naklon": 10 }, +{ "label": "39/3", "node": 4019, "naklon": 10 }, +{ "label": "39/4", "node": 4154, "naklon": 5 }, +{ "label": "39/5", "node": 3907, "naklon": 5 }, +{ "label": "39/6", "node": 4148, "naklon": 0 }, +{ "label": "39/7", "node": 4153, "naklon": 0 }, +{ "label": "39/8", "node": 3938, "naklon": 0 }, +{ "label": "39/9", "node": 3802, "naklon": 0 }, +{ "label": "39/10", "node": 4015, "naklon": 0 }, +{ "label": "39/11", "node": 3929, "naklon": 0 }, +{ "label": "39/12", "node": 3946, "naklon": 0 }, +{ "label": "39/13", "node": 4014, "naklon": 0 }, +{ "label": "39/14", "node": 4155, "naklon": 0 }, +{ "label": "39/15", "node": 4149, "naklon": 0 }, +{ "label": "39/16", "node": 3642, "naklon": 0 }, +{ "label": "39/17", "node": 3636, "naklon": 5 }, +{ "label": "39/18", "node": 3991, "naklon": 0 }, +{ "label": "39/19", "node": 3994, "naklon": 0 }, +{ "label": "39/20", "node": 3990, "naklon": 0 }, +{ "label": "39/21", "node": 3967, "naklon": 0 }, +{ "label": "39/22", "node": 3977, "naklon": 0 }, +{ "label": "39/23", "node": 3757, "naklon": 15 }, +{ "label": "39/24", "node": 3633, "naklon": 15 }, +{ "label": "39/25", "node": 3744, "naklon": 15 }, +{ "label": "39/26", "node": 4023, "naklon": 5 }, +{ "label": "39/27", "node": 3720, "naklon": 5 }, +{ "label": "39/28", "node": 3734, "naklon": 5 }, +{ "label": "39/29", "node": 3741, "naklon": 5 }, +{ "label": "39/30", "node": 3721, "naklon": 5 }, +{ "label": "39/31", "node": 3845, "naklon": 0 }, +{ "label": "39/32", "node": 3840, "naklon": 0 }, +{ "label": "39/33", "node": 3837, "naklon": null }, +{ "label": "39/34", "node": 3839, "naklon": 0 }, +{ "label": "41/1", "node": 3542, "naklon": null }, +{ "label": "41/2", "node": 3566, "naklon": null }, +{ "label": "41/3", "node": 3548, "naklon": null }, +{ "label": "41/4", "node": 3515, "naklon": null }, +{ "label": "41/5", "node": 3559, "naklon": null }, +{ "label": "41/6", "node": 3509, "naklon": null }, +{ "label": "41/7", "node": 3524, "naklon": null }, +{ "label": "41/8", "node": 3518, "naklon": null }, +{ "label": "41/9", "node": 3182, "naklon": null }, +{ "label": "41/10", "node": 3187, "naklon": null }, +{ "label": "41/11", "node": 3195, "naklon": 0 }, +{ "label": "41/12", "node": 3857, "naklon": 0 }, +{ "label": "41/13", "node": 3183, "naklon": 0 }, +{ "label": "41/14", "node": 3177, "naklon": 0 }, +{ "label": "41/15", "node": 3189, "naklon": 0 }, +{ "label": "41/16", "node": 3186, "naklon": 0 }, +{ "label": "42/1", "node": 3178, "naklon": 0 }, +{ "label": "42/2", "node": 3219, "naklon": 0 }, +{ "label": "42/3", "node": 3475, "naklon": 0 }, +{ "label": "42/4", "node": 3175, "naklon": 0 }, +{ "label": "42/5", "node": 3222, "naklon": 0 }, +{ "label": "42/6", "node": 3221, "naklon": 0 }, +{ "label": "42/7", "node": 3181, "naklon": 0 }, +{ "label": "42/8", "node": 3180, "naklon": 0 }, +{ "label": "42/9", "node": 3218, "naklon": 0 }, +{ "label": "42/10", "node": 3176, "naklon": 0 }, +{ "label": "42/11", "node": 3174, "naklon": 0 }, +{ "label": "42/12", "node": 3220, "naklon": 0 }, +{ "label": "42/13", "node": 3533, "naklon": null }, +{ "label": "42/14", "node": 3543, "naklon": null }, +{ "label": "42/15", "node": 3554, "naklon": null }, +{ "label": "42/16", "node": 3549, "naklon": null }, +{ "label": "43/1", "node": 2857, "naklon": 5 }, +{ "label": "43/2", "node": 2752, "naklon": 5 }, +{ "label": "43/3", "node": 2753, "naklon": 5 }, +{ "label": "43/4", "node": 3024, "naklon": 5 }, +{ "label": "43/5", "node": 2754, "naklon": 5 }, +{ "label": "43/6", "node": 4423, "naklon": 5 }, +{ "label": "43/7", "node": 4368, "naklon": 5 }, +{ "label": "43/8", "node": 2978, "naklon": 5 }, +{ "label": "43/9", "node": 2868, "naklon": 5 }, +{ "label": "43/10", "node": 4377, "naklon": 5 }, +{ "label": "43/11", "node": 2757, "naklon": 5 }, +{ "label": "43/12", "node": 2970, "naklon": 5 }, +{ "label": "43/13", "node": 2758, "naklon": 5 }, +{ "label": "43/14", "node": 4378, "naklon": 5 }, +{ "label": "43/15", "node": 2759, "naklon": 5 }, +{ "label": "43/16", "node": 4342, "naklon": 5 }, +{ "label": "43/17", "node": 3026, "naklon": null }, +{ "label": "43/18", "node": 2986, "naklon": null }, +{ "label": "43/19", "node": 4343, "naklon": null }, +{ "label": "43/20", "node": 2760, "naklon": null }, +{ "label": "43/21", "node": 4379, "naklon": null }, +{ "label": "43/22", "node": 2971, "naklon": null }, +{ "label": "43/23", "node": 2761, "naklon": null }, +{ "label": "43/24", "node": 2762, "naklon": null }, +{ "label": "43/25", "node": 4339, "naklon": null }, +{ "label": "43/26", "node": 4380, "naklon": null }, +{ "label": "43/27", "node": 2975, "naklon": null }, +{ "label": "43/28", "node": 3003, "naklon": null }, +{ "label": "43/29", "node": 4338, "naklon": null }, +{ "label": "43/30", "node": 3002, "naklon": null }, +{ "label": "43/31", "node": 4345, "naklon": null }, +{ "label": "43/32", "node": 2979, "naklon": null }, +{ "label": "43/33", "node": 2989, "naklon": null }, +{ "label": "43/34", "node": 2996, "naklon": null }, +{ "label": "43/35", "node": 2972, "naklon": null }, +{ "label": "43/36", "node": 2988, "naklon": null }, +{ "label": "43/37", "node": 4344, "naklon": null }, +{ "label": "43/38", "node": 3022, "naklon": null }, +{ "label": "43/39", "node": 4341, "naklon": null }, +{ "label": "43/40", "node": 2983, "naklon": null }, +{ "label": "43/41", "node": 2995, "naklon": null }, +{ "label": "43/42", "node": 2763, "naklon": null }, +{ "label": "43/43", "node": 2764, "naklon": null }, +{ "label": "43/44", "node": 2765, "naklon": null }, +{ "label": "43/45", "node": 2766, "naklon": null }, +{ "label": "43/46", "node": 2767, "naklon": null }, +{ "label": "43/47", "node": 2768, "naklon": null }, +{ "label": "43/48", "node": 3018, "naklon": null }, +{ "label": "43/49", "node": 2982, "naklon": null }, +{ "label": "43/50", "node": 3019, "naklon": 0 }, +{ "label": "43/51", "node": 3013, "naklon": null }, +{ "label": "43/52", "node": 3007, "naklon": null }, +{ "label": "43/53", "node": 2980, "naklon": null }, +{ "label": "43/54", "node": 3011, "naklon": null }, +{ "label": "43/55", "node": 2672, "naklon": null }, +{ "label": "43/56", "node": 2673, "naklon": null }, +{ "label": "43/57", "node": 2674, "naklon": null }, +{ "label": "43/58", "node": 2675, "naklon": null }, +{ "label": "43/59", "node": 2676, "naklon": null }, +{ "label": "43/60", "node": 2677, "naklon": null }, +{ "label": "43/61", "node": 2678, "naklon": null }, +{ "label": "43/62", "node": 2679, "naklon": null }, +{ "label": "43/63", "node": 2680, "naklon": null }, +{ "label": "43/64", "node": 2840, "naklon": null }, +{ "label": "43/65", "node": 2682, "naklon": null }, +{ "label": "43/66", "node": 2683, "naklon": null }, +{ "label": "43/67", "node": 2684, "naklon": 0 }, +{ "label": "43/68", "node": 2685, "naklon": null }, +{ "label": "43/69", "node": 2686, "naklon": null }, +{ "label": "43/70", "node": 2687, "naklon": null }, +{ "label": "43/71", "node": 2688, "naklon": null }, +{ "label": "43/72", "node": 2689, "naklon": null }, +{ "label": "43/73", "node": 2690, "naklon": null }, +{ "label": "43/74", "node": 2691, "naklon": null }, +{ "label": "43/75", "node": 2692, "naklon": null }, +{ "label": "43/76", "node": 2693, "naklon": 0 }, +{ "label": "43/77", "node": 2694, "naklon": null }, +{ "label": "43/78", "node": 2695, "naklon": null }, +{ "label": "43/79", "node": 2696, "naklon": 0 }, +{ "label": "43/80", "node": 2697, "naklon": null }, +{ "label": "43/81", "node": 2698, "naklon": 0 }, +{ "label": "43/82", "node": 2699, "naklon": null }, +{ "label": "43/83", "node": 2700, "naklon": 0 }, +{ "label": "43/84", "node": 2744, "naklon": null }, +{ "label": "43/85", "node": 2745, "naklon": 0 }, +{ "label": "43/86", "node": 2746, "naklon": null }, +{ "label": "43/87", "node": 2747, "naklon": 0 }, +{ "label": "43/88", "node": 2748, "naklon": null }, +{ "label": "43/89", "node": 2749, "naklon": 0 }, +{ "label": "43/90", "node": 2841, "naklon": null }, +{ "label": "45/1", "node": 4237, "naklon": 5 }, +{ "label": "45/2", "node": 4226, "naklon": 5 }, +{ "label": "45/3", "node": 4242, "naklon": 5 }, +{ "label": "45/4", "node": 4179, "naklon": 5 }, +{ "label": "45/5", "node": 4247, "naklon": 5 }, +{ "label": "45/6", "node": 4245, "naklon": 5 }, +{ "label": "45/7", "node": 3872, "naklon": 5 }, +{ "label": "45/8", "node": 4175, "naklon": 5 }, +{ "label": "45/9", "node": 4236, "naklon": 5 }, +{ "label": "45/10", "node": 4170, "naklon": 5 }, +{ "label": "45/11", "node": 4238, "naklon": 5 }, +{ "label": "45/12", "node": 4246, "naklon": 5 }, +{ "label": "45/13", "node": 4166, "naklon": 5 }, +{ "label": "45/14", "node": 4227, "naklon": 5 }, +{ "label": "45/15", "node": 4171, "naklon": 5 }, +{ "label": "45/16", "node": 4180, "naklon": 5 }, +{ "label": "45/17", "node": 4244, "naklon": 5 }, +{ "label": "45/18", "node": 4199, "naklon": 5 }, +{ "label": "45/19", "node": 4239, "naklon": 5 }, +{ "label": "45/20", "node": 4207, "naklon": 5 }, +{ "label": "45/21", "node": 4223, "naklon": 5 }, +{ "label": "45/22", "node": 4230, "naklon": 5 }, +{ "label": "45/23", "node": 4233, "naklon": 5 }, +{ "label": "45/24", "node": 4222, "naklon": 5 }, +{ "label": "45/25", "node": 4217, "naklon": 5 }, +{ "label": "45/26", "node": 4243, "naklon": 5 }, +{ "label": "45/27", "node": 4200, "naklon": 5 }, +{ "label": "45/28", "node": 4228, "naklon": 5 }, +{ "label": "45/29", "node": 4211, "naklon": 5 }, +{ "label": "45/30", "node": 4234, "naklon": 5 }, +{ "label": "45/31", "node": 4235, "naklon": 5 }, +{ "label": "45/32", "node": 4203, "naklon": 5 }, +{ "label": "45/33", "node": 4240, "naklon": 5 }, +{ "label": "45/34", "node": 4224, "naklon": 5 }, +{ "label": "45/35", "node": 4232, "naklon": 5 }, +{ "label": "45/36", "node": 4231, "naklon": 5 }, +{ "label": "45/37", "node": 4161, "naklon": 5 }, +{ "label": "45/38", "node": 4225, "naklon": 5 }, +{ "label": "45/39", "node": 4241, "naklon": 5 }, +{ "label": "45/40", "node": 4229, "naklon": 5 }, +{ "label": "45/41", "node": 4221, "naklon": 5 }, +{ "label": "45/42", "node": 4212, "naklon": 5 }, +{ "label": "45/43", "node": 4216, "naklon": 5 }, +{ "label": "45/44", "node": 3864, "naklon": null }, +{ "label": "46/1", "node": 3806, "naklon": 5 }, +{ "label": "46/2", "node": 3813, "naklon": 5 }, +{ "label": "46/3", "node": 3815, "naklon": 5 }, +{ "label": "46/4", "node": 3807, "naklon": 5 }, +{ "label": "46/5", "node": 3895, "naklon": 5 }, +{ "label": "46/6", "node": 3809, "naklon": 5 }, +{ "label": "46/7", "node": 3820, "naklon": 5 }, +{ "label": "46/8", "node": 3805, "naklon": 5 }, +{ "label": "46/9", "node": 3894, "naklon": 0 }, +{ "label": "46/10", "node": 4055, "naklon": 0 }, +{ "label": "46/11", "node": 3812, "naklon": 5 }, +{ "label": "46/12", "node": 3822, "naklon": 5 }, +{ "label": "46/13", "node": 3821, "naklon": 5 }, +{ "label": "46/14", "node": 3808, "naklon": 5 }, +{ "label": "46/15", "node": 3799, "naklon": 5 }, +{ "label": "46/16", "node": 3816, "naklon": 5 }, +{ "label": "46/17", "node": 3751, "naklon": 5 }, +{ "label": "46/18", "node": 3814, "naklon": 5 }, +{ "label": "46/19", "node": 4044, "naklon": 0 }, +{ "label": "46/20", "node": 3931, "naklon": 0 }, +{ "label": "46/21", "node": 3902, "naklon": 5 }, +{ "label": "46/22", "node": 3916, "naklon": 5 }, +{ "label": "46/23", "node": 3892, "naklon": 5 }, +{ "label": "46/24", "node": 3914, "naklon": 5 }, +{ "label": "46/25", "node": 3898, "naklon": 5 }, +{ "label": "46/26", "node": 3897, "naklon": 5 }, +{ "label": "46/27", "node": 3885, "naklon": 5 }, +{ "label": "46/28", "node": 3906, "naklon": 5 }, +{ "label": "46/29", "node": 3930, "naklon": 0 }, +{ "label": "46/30", "node": 3936, "naklon": 0 }, +{ "label": "46/31", "node": 3860, "naklon": 5 }, +{ "label": "46/32", "node": 3841, "naklon": 5 }, +{ "label": "46/33", "node": 3873, "naklon": 5 }, +{ "label": "46/34", "node": 3854, "naklon": 5 }, +{ "label": "46/35", "node": 3939, "naklon": 5 }, +{ "label": "46/36", "node": 3858, "naklon": 5 }, +{ "label": "46/37", "node": 3940, "naklon": 5 }, +{ "label": "46/38", "node": 4035, "naklon": 5 }, +{ "label": "47/1", "node": 3373, "naklon": 0 }, +{ "label": "47/2", "node": 3374, "naklon": 0 }, +{ "label": "47/3", "node": 3384, "naklon": 0 }, +{ "label": "47/4", "node": 3385, "naklon": 0 }, +{ "label": "48/1", "node": 4051, "naklon": 5 }, +{ "label": "48/2", "node": 4041, "naklon": 5 }, +{ "label": "48/3", "node": 4056, "naklon": 5 }, +{ "label": "48/4", "node": 3875, "naklon": 5 }, +{ "label": "48/5", "node": 4061, "naklon": 5 }, +{ "label": "48/6", "node": 4047, "naklon": 5 }, +{ "label": "48/7", "node": 4060, "naklon": 5 }, +{ "label": "48/8", "node": 4059, "naklon": 5 }, +{ "label": "48/9", "node": 4058, "naklon": 5 }, +{ "label": "48/10", "node": 3635, "naklon": 5 }, +{ "label": "48/11", "node": 3640, "naklon": 5 }, +{ "label": "48/12", "node": 3747, "naklon": 5 }, +{ "label": "48/13", "node": 3629, "naklon": 5 }, +{ "label": "48/14", "node": 4048, "naklon": 5 }, +{ "label": "48/15", "node": 4063, "naklon": 5 }, +{ "label": "48/16", "node": 4062, "naklon": 5 }, +{ "label": "48/17", "node": 4043, "naklon": 5 }, +{ "label": "48/18", "node": 4052, "naklon": 5 }, +{ "label": "48/19", "node": 4042, "naklon": 5 }, +{ "label": "48/20", "node": 4053, "naklon": 5 }, +{ "label": "50/15A", "node": 4167, "naklon": null }, +{ "label": "50/15B", "node": 4159, "naklon": null }, +{ "label": "50/1", "node": 4183, "naklon": 0 }, +{ "label": "50/2", "node": 4157, "naklon": 0 }, +{ "label": "50/3", "node": 4160, "naklon": 0 }, +{ "label": "50/4", "node": 4173, "naklon": 0 }, +{ "label": "50/5", "node": 4177, "naklon": 0 }, +{ "label": "50/6", "node": 4174, "naklon": 0 }, +{ "label": "50/7", "node": 4178, "naklon": 0 }, +{ "label": "50/8", "node": 4195, "naklon": 0 }, +{ "label": "50/9", "node": 4169, "naklon": 0 }, +{ "label": "50/10", "node": 4162, "naklon": 0 }, +{ "label": "50/11", "node": 4158, "naklon": 0 }, +{ "label": "50/12", "node": 4182, "naklon": 0 }, +{ "label": "50/13", "node": 4194, "naklon": 0 }, +{ "label": "50/14", "node": 4184, "naklon": 0 }, +{ "label": "50/16", "node": 4197, "naklon": null }, +{ "label": "50/17", "node": 4164, "naklon": null }, +{ "label": "50/18", "node": 3306, "naklon": null }, +{ "label": "50/19", "node": 4168, "naklon": null }, +{ "label": "50/20", "node": 4193, "naklon": null }, +{ "label": "50/21", "node": 4187, "naklon": null }, +{ "label": "50/22", "node": 4163, "naklon": null }, +{ "label": "50/23", "node": 4165, "naklon": null }, +{ "label": "50/24", "node": 4185, "naklon": null }, +{ "label": "50/25", "node": 3904, "naklon": null }, +{ "label": "53/1", "node": 2619, "naklon": 0 }, +{ "label": "53/2", "node": 2623, "naklon": 0 }, +{ "label": "53/3", "node": 2617, "naklon": 0 }, +{ "label": "53/4", "node": 2622, "naklon": 0 }, +{ "label": "53/5", "node": 2618, "naklon": 0 }, +{ "label": "53/6", "node": 2626, "naklon": 0 }, +{ "label": "53/7", "node": 2869, "naklon": 0 }, +{ "label": "53/8", "node": 2613, "naklon": 0 }, +{ "label": "53/9", "node": 2608, "naklon": 0 }, +{ "label": "53/10", "node": 2611, "naklon": 0 }, +{ "label": "53/11", "node": 2598, "naklon": 0 }, +{ "label": "53/12", "node": 3528, "naklon": 0 }, +{ "label": "53/13", "node": 3545, "naklon": 0 }, +{ "label": "53/14", "node": 2620, "naklon": 0 }, +{ "label": "53/15", "node": 2612, "naklon": 0 }, +{ "label": "53/16", "node": 2615, "naklon": 0 }, +{ "label": "53/17", "node": 3722, "naklon": 0 }, +{ "label": "53/18", "node": 2624, "naklon": 0 }, +{ "label": "53/19", "node": 2609, "naklon": 0 }, +{ "label": "53/20", "node": 2625, "naklon": 0 }, +{ "label": "53/21", "node": 2602, "naklon": 0 }, +{ "label": "53/22", "node": 2610, "naklon": 0 }, +{ "label": "53/23", "node": 2599, "naklon": 0 }, +{ "label": "53/24", "node": 2605, "naklon": 0 }, +{ "label": "53/25", "node": 2593, "naklon": 0 }, +{ "label": "53/26", "node": 3074, "naklon": 0 }, +{ "label": "53/27", "node": 2740, "naklon": 0 }, +{ "label": "53/28", "node": 2614, "naklon": 0 }, +{ "label": "53/29", "node": 2601, "naklon": 0 }, +{ "label": "53/30", "node": 4196, "naklon": 0 }, +{ "label": "53/31", "node": 2607, "naklon": 0 }, +{ "label": "53/32", "node": 2582, "naklon": 0 }, +{ "label": "53/33", "node": 2594, "naklon": 0 }, +{ "label": "53/34", "node": 2589, "naklon": 0 }, +{ "label": "53/35", "node": 2596, "naklon": 0 }, +{ "label": "53/36", "node": 2603, "naklon": 0 }, +{ "label": "53/37", "node": 2597, "naklon": 0 }, +{ "label": "53/38", "node": 2590, "naklon": 0 }, +{ "label": "53/39", "node": 2581, "naklon": 0 }, +{ "label": "53/40", "node": 2583, "naklon": 0 }, +{ "label": "53/41", "node": 2580, "naklon": 0 }, +{ "label": "53/42", "node": 2579, "naklon": 0 }, +{ "label": "53/43", "node": 2797, "naklon": 0 }, +{ "label": "53/44", "node": 2577, "naklon": 0 }, +{ "label": "53/45", "node": 2586, "naklon": 0 }, +{ "label": "53/46", "node": 2588, "naklon": 0 }, +{ "label": "53/47", "node": 2591, "naklon": 0 }, +{ "label": "53/48", "node": 2592, "naklon": 0 }, +{ "label": "53/49", "node": 2573, "naklon": 0 }, +{ "label": "53/50", "node": 2595, "naklon": 0 }, +{ "label": "53/51", "node": 2587, "naklon": 0 }, +{ "label": "53/52", "node": 2578, "naklon": 0 }, +{ "label": "53/53", "node": 2574, "naklon": 0 }, +{ "label": "53/54", "node": 2571, "naklon": 0 }, +{ "label": "53/55", "node": 2570, "naklon": 0 }, +{ "label": "53/56", "node": 2576, "naklon": 0 }, +{ "label": "53/57", "node": 2881, "naklon": 0 }, +{ "label": "53/58", "node": 2575, "naklon": 0 }, +{ "label": "53/59", "node": 2572, "naklon": 0 }, +{ "label": "53/60", "node": 2569, "naklon": 0 }, +{ "label": "55/1", "node": 4324, "naklon": 0 }, +{ "label": "55/2", "node": 4319, "naklon": 0 }, +{ "label": "55/3", "node": 4327, "naklon": 0 }, +{ "label": "55/4", "node": 4333, "naklon": 0 }, +{ "label": "55/5", "node": 4332, "naklon": 0 }, +{ "label": "55/6", "node": 4320, "naklon": 0 }, +{ "label": "55/7", "node": 4317, "naklon": 0 }, +{ "label": "55/8", "node": 4318, "naklon": 0 }, +{ "label": "55/9", "node": 4328, "naklon": 0 }, +{ "label": "55/10", "node": 4323, "naklon": 0 }, +{ "label": "55/11", "node": 4325, "naklon": 0 }, +{ "label": "55/12", "node": 4326, "naklon": 0 }, +{ "label": "55/13", "node": 4316, "naklon": 0 }, +{ "label": "55/14", "node": 4322, "naklon": 0 }, +{ "label": "55/15", "node": 4331, "naklon": 0 }, +{ "label": "55/16", "node": 4321, "naklon": 0 }, +{ "label": "55/17", "node": 4315, "naklon": 0 }, +{ "label": "55/18", "node": 4329, "naklon": 0 }, +{ "label": "55/19", "node": 4334, "naklon": 0 }, +{ "label": "55/20", "node": 4330, "naklon": 0 } +]; + +module.exports = { naklony }; diff --git a/RVO22/databases/modbus_config.js b/RVO22/databases/modbus_config.js new file mode 100755 index 0000000..b73116a --- /dev/null +++ b/RVO22/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/RVO22/databases/nodes.table b/RVO22/databases/nodes.table new file mode 100755 index 0000000..6a30ec2 --- /dev/null +++ b/RVO22/databases/nodes.table @@ -0,0 +1,43 @@ +node:number|pole_number:string|node_type:string|tbname:string|line:number|profile:string|processed:boolean|status:boolean|time_of_last_communication:number ++|2637|8|NEMA|pE5X8NQPaow6vlOZxk6aXl0q42ezGBMyWgDVjR3L|2||1|1|1760574272017|............. ++|2638|9|NEMA|6lQGaY9RDywdVzObj0Pag3kPg4NBn3exEK51LWZq|2||1|1|1760574272241|............. ++|3778|10|NEMA|m6EYyZoJ4gWexdjVPAR5bK7RDOq9wv2N5XzKGplr|2||1|1|1760573870700|............. ++|3089|11|NEMA|JzwxZXOvDj1bVrN4nkW5lqA8qdyBl3MRKLpGPgaQ|2||1|1|1760573864597|............. ++|2641|12|NEMA|g9OxBZ5KRwNznlY6pAppO2AWXvjdEL4eGQobMDy2|2||1|1|1760574280502|............. ++|2642|13|NEMA|OzNMgZ9n43qPbjXmy7zwxKA2DKdYvW5e6pxGRrVa|2||1|1|1760574280693|............. ++|2643|14|NEMA|JX1ObgmqGZ54DMyYL7aDNokEVdve38WKRzwjNrQ9|2||1|1|1760574280837|............. ++|2644|15|NEMA|RvmwNz8QPblKp41GD7lKl8kJrLVYoBO92dMegn6W|2||1|1|1760574281013|............. ++|2646|17|NEMA|3JjOWdylwgNLzxVab7NaXvkZ2vG64rq8PEB5QmDo|2||1|1|1760573684541|............. ++|4128|18|NEMA|XMBbew5z4ELrZa2mRAd36278vPN6gy3DdVYlpKjq|2||1|1|1760573876468|............. ++|2648|19|NEMA|gYbDLqlyZVoRerQpB72MjbkWJnwM5z24POKa8Exj|2||1|1|1760573686011|............. ++|2649|20|NEMA|zdQO8GwxDqjRgP4137YVMWANyKlpem2nL65rvVJY|2||1|1|1760573686155|............. ++|4122|21|NEMA|WlVJBygjDZMeKX3vnAMRao08NqdmG2x1Y69LQ4P5|2||1|1|1760573871196|............. ++|4126|22|NEMA|5dBNwRp9graYJxZn409NPyklVov1b2QLPDqGm6XK|2||1|1|1760573875925|............. ++|2653|24|NEMA|1JMYvnx2RzKEo4aWQ7DGwqkL8yZV3m9NBePXbrdj|1||1|1|1760573686986|............. ++|2654|25|NEMA|PjLblDgRBO6WQqnxmkJ1K90Jv3ewZN4p5a89yKdY|1||1|1|1760573706032|............. ++|2656|27|NEMA|d5xjWYMwEJon6rLlK7yE1l7qgV4DaOeNB9ZX3Gzb|1||1|1|1760573706783|............. ++|4123|28|NEMA|gRoJEyXVx4qD9er287L4R47wBzGldaPjLWQKm3Mv|1||1|1|1760573875749|............. ++|2658|29|NEMA|K94XLav1glVRnyQ6r01PvBAme3YJwBxM5oOzdP2j|1||1|1|1760573707166|............. ++|2659|30|NEMA|d9x2V5LGYBzXp4mMRAOm1WkPloaqJwnQj6DgrNe3|1||1|1|1760573707550|............. ++|2578|31|NEMA|B5EoxeMVp4zwr8nqW0GBKaARjvD1PNamOGbLg63Z|1||1|1|1760574268359|............. ++|2661|32|NEMA|aw4eELG2DlPMdn1JW0BMKWAqQXOZRN3xB5yp8VKr|1||1|1|1760573738275|............. ++|4116|34|NEMA|eod9aRWLVl34Gx1Dn7VNMW72rz6qjgmpEXwQJN5Z|1||1|1|1760573871052|............. ++|2664|35|NEMA|3a5oqJN1bgnx4Ol9dk89P37ByE6jQ8mKDWMpGrLV|1||1|1|1760573738482|............. ++|2665|36|NEMA|EjgWGnXaLy9opPOz20n4DZ786BlYM3w1deVQvbKr|1||1|1|1760573765437|............. ++|2666|37|NEMA|wvKJdZML6mXP4DzWBAXxM6AjxNloa5g23Ve9Y1ry|1||1|1|1760573774417|............. ++|2667|38|NEMA|Nzp2OoJlqn6r1ZgvdA3Brr7abBwP5G4eE3RQmyxD|1||1|0|1759985233649|............. ++|3056|39|NEMA|PLBJzmK1r3Gynd6OW0gK680e5wV4vx9bDEqNgYR8|1||1|1|1760573852613|............. ++|2631|2|NEMA|BaY3Xpy1EbKGjLq2O7malN7rx8owgQz9P4dDJRmN|2||1|1|1760573880799|............. ++|3088|3|NEMA|DbQY6zyveZRwK5drV0Z8zQ7joE4XJM83N9xl2nWq|2||1|1|1760573864421|............. ++|2813|4|NEMA|apKVJBwOyrP35m2lv7KYVZ0YXbeWNd64En9GxRqg|2||1|1|1760573851942|............. ++|2777|5|NEMA|o9vbeQlLMVg8j5dq4keLlQ0NxZpEmnXzwYKO1ar2|2||1|1|1760573851750|............. ++|3764|41|NEMA|rDbQ84xzwgdqEoPm3kbEBO09anOZY1RXyBv2LVM6|1||1|1|1760573870525|............. ++|2671|42|NEMA|E6Kg9oDnLWyzPRMva7v5BXkJxp4VG58qO2w1lZYe|1||1|1|1760573836220|............. ++|3015|32/1|IP65|o9vbeQlLMVg8j5dq4kegpXANxZpEmnXzwYKO1ar2|1||1|1|1760573852102|............. ++|4367|7|NEMA|2O14VBzl8aDmWdNw3A59nEAGyZ5qLJoEMpj6R9ng|2||1|1|1760573876660|............. ++|4103|23|NEMA|Z5KyJe9nEg1QNbWlX0w4OwkoDjBLdqzR83VGv624|1||1|1|1760573870860|............. ++|2636|6|NEMA|gP1eOZVj3Q9lv5aDEk458J7rdpqW8yLm2BbKzJxM|2||1|1|1760574271826|............. ++|2630|1|NEMA|zrR51V2ajQ9ZLygPKkEMw9kYDq38xOJolENBXGnv|2||1|1|1760574183116|............. ++|2655|26|NEMA|dz4ojlpP85JMgDLZWkQJKB7aKYqQexEr62GXRV1y|1||1|1|1760573706383|............. ++|3592|16|NEMA|RO8rjaBDy21qPQJzW7omOr0pK3xmNleVZg9Ed4Gw|2||1|1|1760573866386|............. ++|2669|40|NEMA|52dD6ZlV1QaOpRBmbAqG5XkKnGzWMLj4eJq38Pgo|1||1|1|1760573835948|............. diff --git a/RVO22/databases/nodes_original/nodes_original.table b/RVO22/databases/nodes_original/nodes_original.table new file mode 100755 index 0000000..4c67ebe --- /dev/null +++ b/RVO22/databases/nodes_original/nodes_original.table @@ -0,0 +1 @@ +[{"2637": "pE5X8NQPaow6vlOZxk6aXl0q42ezGBMyWgDVjR3L"}, {"2638": "6lQGaY9RDywdVzObj0Pag3kPg4NBn3exEK51LWZq"}, {"3778": "m6EYyZoJ4gWexdjVPAR5bK7RDOq9wv2N5XzKGplr"}, {"3089": "JzwxZXOvDj1bVrN4nkW5lqA8qdyBl3MRKLpGPgaQ"}, {"2641": "g9OxBZ5KRwNznlY6pAppO2AWXvjdEL4eGQobMDy2"}, {"2642": "OzNMgZ9n43qPbjXmy7zwxKA2DKdYvW5e6pxGRrVa"}, {"2643": "JX1ObgmqGZ54DMyYL7aDNokEVdve38WKRzwjNrQ9"}, {"2644": "RvmwNz8QPblKp41GD7lKl8kJrLVYoBO92dMegn6W"}, {"2646": "3JjOWdylwgNLzxVab7NaXvkZ2vG64rq8PEB5QmDo"}, {"4128": "XMBbew5z4ELrZa2mRAd36278vPN6gy3DdVYlpKjq"}, {"2648": "gYbDLqlyZVoRerQpB72MjbkWJnwM5z24POKa8Exj"}, {"2649": "zdQO8GwxDqjRgP4137YVMWANyKlpem2nL65rvVJY"}, {"4122": "WlVJBygjDZMeKX3vnAMRao08NqdmG2x1Y69LQ4P5"}, {"4126": "5dBNwRp9graYJxZn409NPyklVov1b2QLPDqGm6XK"}, {"2653": "1JMYvnx2RzKEo4aWQ7DGwqkL8yZV3m9NBePXbrdj"}, {"2654": "PjLblDgRBO6WQqnxmkJ1K90Jv3ewZN4p5a89yKdY"}, {"2656": "d5xjWYMwEJon6rLlK7yE1l7qgV4DaOeNB9ZX3Gzb"}, {"4123": "gRoJEyXVx4qD9er287L4R47wBzGldaPjLWQKm3Mv"}, {"2658": "K94XLav1glVRnyQ6r01PvBAme3YJwBxM5oOzdP2j"}, {"2659": "d9x2V5LGYBzXp4mMRAOm1WkPloaqJwnQj6DgrNe3"}, {"2578": "B5EoxeMVp4zwr8nqW0GBKaARjvD1PNamOGbLg63Z"}, {"2661": "aw4eELG2DlPMdn1JW0BMKWAqQXOZRN3xB5yp8VKr"}, {"4116": "eod9aRWLVl34Gx1Dn7VNMW72rz6qjgmpEXwQJN5Z"}, {"2664": "3a5oqJN1bgnx4Ol9dk89P37ByE6jQ8mKDWMpGrLV"}, {"2665": "EjgWGnXaLy9opPOz20n4DZ786BlYM3w1deVQvbKr"}, {"2666": "wvKJdZML6mXP4DzWBAXxM6AjxNloa5g23Ve9Y1ry"}, {"2667": "Nzp2OoJlqn6r1ZgvdA3Brr7abBwP5G4eE3RQmyxD"}, {"3056": "PLBJzmK1r3Gynd6OW0gK680e5wV4vx9bDEqNgYR8"}, {"2631": "BaY3Xpy1EbKGjLq2O7malN7rx8owgQz9P4dDJRmN"}, {"3088": "DbQY6zyveZRwK5drV0Z8zQ7joE4XJM83N9xl2nWq"}, {"2813": "apKVJBwOyrP35m2lv7KYVZ0YXbeWNd64En9GxRqg"}, {"2777": "o9vbeQlLMVg8j5dq4keLlQ0NxZpEmnXzwYKO1ar2"}, {"3764": "rDbQ84xzwgdqEoPm3kbEBO09anOZY1RXyBv2LVM6"}, {"2671": "E6Kg9oDnLWyzPRMva7v5BXkJxp4VG58qO2w1lZYe"}, {"3015": "o9vbeQlLMVg8j5dq4kegpXANxZpEmnXzwYKO1ar2"}, {"4367": "2O14VBzl8aDmWdNw3A59nEAGyZ5qLJoEMpj6R9ng"}, {"4103": "Z5KyJe9nEg1QNbWlX0w4OwkoDjBLdqzR83VGv624"}, {"2636": "gP1eOZVj3Q9lv5aDEk458J7rdpqW8yLm2BbKzJxM"}, {"2630": "zrR51V2ajQ9ZLygPKkEMw9kYDq38xOJolENBXGnv"}, {"2655": "dz4ojlpP85JMgDLZWkQJKB7aKYqQexEr62GXRV1y"}, {"3592": "RO8rjaBDy21qPQJzW7omOr0pK3xmNleVZg9Ed4Gw"}, {"2669": "52dD6ZlV1QaOpRBmbAqG5XkKnGzWMLj4eJq38Pgo"}] \ No newline at end of file diff --git a/RVO22/databases/notifications.table b/RVO22/databases/notifications.table new file mode 100755 index 0000000..f7c96cb --- /dev/null +++ b/RVO22/databases/notifications.table @@ -0,0 +1,41 @@ +key:string|weight:string|sk:string|en:string ++|switching_profile_point_applied_to_line|INFORMATIONAL|Aplikovaný bod spínacieho profilu na línií č. ${line} : ${value}|Switching profile point applied to line no. ${line} : ${value}|............... ++|dusk_has_occured|INFORMATIONAL|Nastal súmrak: ${value}|Dusk has occured: ${value}|............... ++|dawn_has_occured|INFORMATIONAL|Nastal úsvit: ${value}|Dawn has occured: ${value}|............... ++|dimming_profile_was_successfully_received_by_node|NOTICE|Stmievací profil bol úspešne prijatý nodom č. ${node}|Dimming profile was successfully received by node no. ${node}|............... ++|master_node_is_responding_again|NOTICE|Master node začal znovu odpovedať|Master node is responding again|............... ++|command_was_sent_from_terminal_interface|DEBUG|Z terminálu bol odoslaný príkaz|A command was sent from terminal interface|............... ++|master_node_is_not_responding|ALERT|Master node neodpovedá|Master node is not responding|............... ++|configuration_of_dimming_profile_to_node_failed|ALERT|Konfigurácia stmievacieho profilu pre node č. ${node} zlyhala|Configuration of dimming profile to node no. ${node} has failed|............... ++|circuit_breaker_was_turned_on_line|NOTICE|Zapnutie ističa na línii č. ${line}|Circuit breaker was turned on - line no. ${line}|............... ++|circuit_breaker_was_turned_off_line|ERROR|Vypnutie ističa na línií č. ${line}|Circuit breaker was turned off - line no. ${line}|............... ++|dimming_profile_was_processed_for_node|INFORMATIONAL|Stmievací profil bol spracovaný pre node č. ${node}|Dimming profile was processed for node no. ${node}|............... ++|switching_profile_was_processed_for_line|INFORMATIONAL|Spínací profil bol spracovaný pre líniu č. ${line}|Switching profile was processed for line no. ${line}|............... ++|thermometer_is_not_responding|WARNING|Teplomer neodpovedá|Thermometer is not responding|............... ++|thermometer_is_responding_again|NOTICE|Teplomer znovu odpovedá|Thermometer is responding again|............... ++|thermometer_sends_invalid_data|WARNING|Teplomer posiela neplatné hodnoty|Thermometer sends invalid data|............... ++|main_switch_has_been_turned_off|CRITICAL|Hlavný vypínač bol vypnutý|Main switch has been turned off|............... ++|main_switch_has_been_turned_on|NOTICE|Hlavný vypínač bol zapnutý|Main switch has been turned on|............... ++|power_supply_has_disconnected_input|ALERT|Napájací zdroj nemá napätie na vstupe|Power supply has disconnected input|............... ++|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_main_open|NOTICE|Hlavné dvere boli otvorené|Main door has been opened|............... ++|door_em_open|NOTICE|Dvere silovej časti boli otvorené|Power door has been opened|............... ++|door_main_open_without_permission|WARNING|Hlavné dvere boli otvorené bez povolenia - zapnutá siréna|Main door has been opened without permission - alarm is on|............... ++|door_em_open_without_permission|WARNING|Dvere silovej časti boli otvorené bez povolenia|Power door has been opened without permission|............... ++|door_main_close|NOTICE|Hlavné dvere boli zatvorené|Main door has been closed|............... ++|door_em_close|NOTICE|Dvere silovej časti boli zatvorené|Power door has been closed|............... ++|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|............... ++|electrometer_ok|NOTICE|Elektromer znovu odpovedá|Electrometer is responding again|............... ++|no_voltage_on_phase|CRITICAL|Na fáze č. ${phase} nie je napätie|No voltage detected on phase no. ${phase}|............... ++|voltage_on_phase_restored|NOTICE|Napätie na fáze č. ${phase} bolo obnovené|Voltage on phase no. ${phase} has been restored|............... ++|flow_start|NOTICE|FLOW bol spustený|FLOW has been started |............... ++|twilight_sensor_nok|ERROR|Sensor súmraku neodpovedá|Twilight sensor is not responding|............... ++|twilight_sensor_ok|NOTICE|Sensor súmraku znovu odpovedá|Twilight sensor is responding again|............... ++|lamps_have_turned_on|NOTICE|Lampy sa zapli|Lamps have turned on|............... ++|lamps_have_turned_off|NOTICE|Lampy sa vypli|Lamps have turned off|............... ++|flow_restart|NOTICE|FLOW bol reštartovaný|FLOW has been restarted|............... ++|nodes_db_changed|NOTICE|Zmena v node databáze|Node db has changed|............... diff --git a/RVO22/databases/pins.table b/RVO22/databases/pins.table new file mode 100755 index 0000000..0eb3d05 --- /dev/null +++ b/RVO22/databases/pins.table @@ -0,0 +1,14 @@ +pin:string|type:string|line:number +*|input1_01|door_condition|0|........... +*|input1_02|rotary_switch_state|0|........... +*|input1_03|rotary_switch_state|0|........... +*|input1_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/RVO22/databases/relays.table b/RVO22/databases/relays.table new file mode 100755 index 0000000..540fd60 --- /dev/null +++ b/RVO22/databases/relays.table @@ -0,0 +1,5 @@ +line:number|tbname:string|contactor:number|profile:string ++|0|rDbQ84xzwgdqEoPm3kbEXy09anOZY1RXyBv2LVM6|1||........... ++|3|nJL5lPMwBx23YpqRe0rp327damXvWVbOrD4gNzy8|9|{"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}|................................................................................................................................................................................................................................................................................................................................... ++|1|E6Kg9oDnLWyzPRMva7v5vbkJxp4VG58qO2w1lZYe|9|{"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|roKgWqY95V3mXMRzyAjKde0bLjexpJPvaGDBw826|9|{"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/RVO22/databases/settings.table b/RVO22/databases/settings.table new file mode 100755 index 0000000..c829f97 --- /dev/null +++ b/RVO22/databases/settings.table @@ -0,0 +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|project_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|cloud_topic:string|has_main_switch:boolean|daily_report:boolean|send_changed_node_numbers:boolean ++|rvo_senica_22_ip109|en|28.F46E9D0E0000|48.70826502|17.28455203|192.168.252.1|rvo_senica_22_ip109|9excvr7yBcF3gl3kYZGY|1883|0|48|unipi|ttyUSB0|1|20|5|6|3|u109|0|1|1|................................................... diff --git a/RVO22/databases/tbdata.nosql b/RVO22/databases/tbdata.nosql new file mode 100755 index 0000000..d841fcb --- /dev/null +++ b/RVO22/databases/tbdata.nosql @@ -0,0 +1,4 @@ +-"rDbQ84xzwgdqEoPm3kbEXy09anOZY1RXyBv2LVM6":[{"ts":1760530404436,"values":{"_event":{"type":"notice","status":"new","source":{"func":"modbus_reader","component":"1699965957410","component_name":"Modbus reader","edge":"rDbQ84xzwgdqEoPm3kbEXy09anOZY1RXyBv2LVM6"},"message":{"sk":"rvo_senica_22_ip109: FLOW bol reštartovaný","en":"rvo_senica_22_ip109: FLOW has been restarted"},"message_data":""}}}],"id":"3000313001cl71b"} +-"rDbQ84xzwgdqEoPm3kbEXy09anOZY1RXyBv2LVM6":[{"ts":1760530404529,"values":{"edge_fw_version":"2025-10-08","maintenance_mode":false}}],"id":"3000313002cl70b"} +-"rDbQ84xzwgdqEoPm3kbEXy09anOZY1RXyBv2LVM6":[{"ts":1760530404542,"values":{"statecode":2,"power_mode":"Automatic"}}],"id":"3000313004cl70b"} +-"rDbQ84xzwgdqEoPm3kbEXy09anOZY1RXyBv2LVM6":[{"ts":1760530404591,"values":{"_event":{"type":"notice","status":"new","source":{"func":"rsPort.open()","component":"1699963668903","component_name":"DIDO_Controller","edge":"rDbQ84xzwgdqEoPm3kbEXy09anOZY1RXyBv2LVM6"},"message":{"sk":"rvo_senica_22_ip109: FLOW bol spustený","en":"rvo_senica_22_ip109: FLOW has been started "},"message_data":""}}}],"id":"3000313006cl70b"} diff --git a/RVO22/databases/tbdatacloud.nosql b/RVO22/databases/tbdatacloud.nosql new file mode 100755 index 0000000..0753fcd --- /dev/null +++ b/RVO22/databases/tbdatacloud.nosql @@ -0,0 +1,3 @@ +-"rDbQ84xzwgdqEoPm3kbEXy09anOZY1RXyBv2LVM6":[{"ts":1760530404529,"values":{"edge_fw_version":"2025-10-08","maintenance_mode":false}}],"id":"3000313003cl71b"} +-"rDbQ84xzwgdqEoPm3kbEXy09anOZY1RXyBv2LVM6":[{"ts":1760530404542,"values":{"statecode":2,"power_mode":"Automatic"}}],"id":"3000313005cl71b"} +-"rDbQ84xzwgdqEoPm3kbEXy09anOZY1RXyBv2LVM6":[{"ts":1760530404591,"values":{"_event":{"type":"notice","status":"new","source":{"func":"rsPort.open()","component":"1699963668903","component_name":"DIDO_Controller","edge":"rDbQ84xzwgdqEoPm3kbEXy09anOZY1RXyBv2LVM6"},"message":{"sk":"rvo_senica_22_ip109: FLOW bol spustený","en":"rvo_senica_22_ip109: FLOW has been started "},"message_data":""}}}],"id":"3000313007cl71b"} diff --git a/RVO22/databases/total_energy.js b/RVO22/databases/total_energy.js new file mode 100755 index 0000000..dde340e --- /dev/null +++ b/RVO22/databases/total_energy.js @@ -0,0 +1,38 @@ +//key is rvo_number, value is max energy when lamps are on +const total_energy = { + 1: 580, + 2: 1100, + 3: 3700, + 4: 4100, + 7: 360, + 12: 1700, + 13: 5400, + 14: 440, + 15: 6100, + 16: 4800, + 20: 1600, + 21: 1000, + 22: 2600, + 23: 1000, + 25: 2600, + 33: 240, + 34: 4000, + 35: 2700, + 36: 820, + 37: 1400, + 35: 3500, + 39: 1170, + 41: 740, + 42: 660, + 43: 4900, + 45: 930, + 46: 700, + 47: 1100, + 48: 1500, + 50: 3200, + 53: 1250, + 55: 1000, + 56: 5500 +} + +module.exports = total_energy; diff --git a/RVO22/debug.js b/RVO22/debug.js new file mode 100755 index 0000000..9818194 --- /dev/null +++ b/RVO22/debug.js @@ -0,0 +1,16 @@ +// =================================================== +// FOR DEVELOPMENT +// Total.js - framework for Node.js platform +// https://www.totaljs.com +// =================================================== + +const options = {}; + +// options.ip = '127.0.0.1'; +// options.port = parseInt(process.argv[2]); +// options.config = { name: 'Total.js' }; +// options.sleep = 3000; +// options.inspector = 9229; +// options.watch = ['private']; + +require('total.js/debug')(options); \ No newline at end of file diff --git a/RVO22/err.txt b/RVO22/err.txt new file mode 100755 index 0000000..68a8f0b --- /dev/null +++ b/RVO22/err.txt @@ -0,0 +1,74 @@ +[2024-10-24T00:24:15.696] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-24T01:24:27.837] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-24T02:24:40.082] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-24T03:24:52.353] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-24T04:25:06.588] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-24T05:25:18.843] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-24T06:25:31.067] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-24T07:25:43.330] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-24T08:25:55.505] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-24T09:26:07.664] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-24T10:26:19.792] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-24T11:26:31.931] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-24T12:26:44.121] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-24T13:26:56.226] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-24T14:27:08.349] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-24T15:27:20.461] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-24T16:27:32.591] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-24T17:27:44.700] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-24T18:27:56.874] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-24T19:28:09.022] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-24T20:28:21.172] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-24T21:28:33.331] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-24T22:28:45.474] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-24T23:28:57.665] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-25T00:29:09.778] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-25T01:29:21.918] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-25T02:29:34.189] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-25T03:29:46.472] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-25T04:29:59.682] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-25T05:30:11.920] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-25T06:30:24.156] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-25T07:30:36.440] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-25T08:30:48.644] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-25T09:31:00.951] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-25T10:31:13.381] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-25T11:31:25.607] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-25T12:31:37.772] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-25T13:31:49.934] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-25T14:32:02.130] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-25T15:32:14.304] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-25T16:32:26.441] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2025-09-23T14:00:58.463] [ERROR] errLogs - uncaughtException: Cannot read property 'getHours' of undefined +[2025-09-23T14:00:58.464] [ERROR] errLogs - TypeError: Cannot read property 'getHours' of undefined + at Timeout.emptyReportToSend [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:00:58.465] [ERROR] errLogs - uncaughtException: Cannot read property 'getHours' of undefined +[2025-09-23T14:00:58.466] [ERROR] errLogs - TypeError: Cannot read property 'getHours' of undefined + at Timeout.emptyReportToSend [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:00:58.477] [ERROR] errLogs - uncaughtException: Cannot read property 'getHours' of undefined +[2025-09-23T14:00:58.478] [ERROR] errLogs - TypeError: Cannot read property 'getHours' of undefined + at Timeout.emptyReportToSend [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:01:04.230] [ERROR] errLogs - uncaughtException: date.getHours is not a function +[2025-09-23T14:01:04.230] [ERROR] errLogs - TypeError: date.getHours is not a function + at emptyReportToSend (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at Timeout.dailyReportCheck [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1351:5) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:01:04.231] [ERROR] errLogs - uncaughtException: date.getHours is not a function +[2025-09-23T14:01:04.232] [ERROR] errLogs - TypeError: date.getHours is not a function + at emptyReportToSend (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at Timeout.dailyReportCheck [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1351:5) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:01:04.236] [ERROR] errLogs - uncaughtException: date.getHours is not a function +[2025-09-23T14:01:04.237] [ERROR] errLogs - TypeError: date.getHours is not a function + at emptyReportToSend (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at Timeout.dailyReportCheck [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1351:5) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) diff --git a/RVO22/flow/cloudmqttconnect.js b/RVO22/flow/cloudmqttconnect.js new file mode 100755 index 0000000..b03491f --- /dev/null +++ b/RVO22/flow/cloudmqttconnect.js @@ -0,0 +1,357 @@ +exports.id = 'cloudmqttconnect'; +exports.title = 'Cloud connect mqtt'; +exports.group = 'MQTT'; +exports.color = '#888600'; +exports.version = '1.0.2'; +exports.icon = 'sign-out'; +exports.input = 2; +exports.output = 2; +exports.options = { host: 'tb-stage.worksys.io', port: 1883, clientid: "", username: "" }; + +exports.html = `
+
+
+
Hostname or IP address (if not empty - setting will override db setting)
+
+
+
Port
+
+
+
+
+
@(Client id)
+
+
+
topic
+
+
+
`; + + + +const { promisifyBuilder } = require('./helper/db_helper'); +const fs = require('fs'); +const mqtt = require('mqtt'); +const nosql = NOSQL('tbdatacloud'); + +const SEND_TO = { + debug: 0, + rpcCall: 1, +} + +//CONFIG +let saveTelemetryOnError = true;//backup_on_failure overrides this value +//------------------------ + +const noSqlFileSizeLimit = 4194304;//use 5MB - 4194304 +let insertNoSqlCounter = 0; +let insertBackupNoSqlCounter = 0; +let processingData = false; + +let backup_on_failure = true;//== saveTelemetryOnError - create backup client send failure +let restore_from_backup = 50; //how many rows process at once? +let restore_backup_wait = 3;//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; + + +exports.install = function(instance) { + + var client; + var opts; + var clientReady = false; + + let o = {}; //options + + function main() { + loadSettings(); + } + + //set opts according to db settings + function loadSettings() { + + o = instance.options; + if (!o.topic) o.topic = FLOW.GLOBALS.settings.cloud_topic; + + opts = { + host: o.host, + port: o.port, + clientId: o.clientid, + username: o.username, + rejectUnauthorized: false, + resubscribe: false + }; + + console.log("wsmqttpublich -> loadSettings from instance.options", o); + + if (!o.topic) { + instance.status("Not configured", "white"); + console.log("Cloud mqtt connect: no topic selected"); + return; + } + + connectToTbServer(); + } + + function connectToTbServer() { + var url = "mqtt://" + opts.host + ":" + opts.port; + console.log("MQTT URL: ", url); + + client = mqtt.connect(url, opts); + + client.on('connect', function() { + client.subscribe(`${o.topic}_backward`, (err) => { + if (!err) { + console.log("MQTT subscribed"); + } + }); + instance.status("Connected", "green"); + clientReady = true; + sendClientError = true; + }); + + client.on('reconnect', function() { + instance.status("Reconnecting", "yellow"); + clientReady = false; + }); + + client.on('message', function(topic, message) { + // message is type of buffer + message = message.toString(); + if (message[0] === '{') { + TRY(function() { + + message = JSON.parse(message); + if (message.hasOwnProperty("device") && message.hasOwnProperty("data") && message.data.hasOwnProperty("id")) { + client.publish(`${o.topic}_forward`, `{"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 } }); + } + + }, () => instance.debug('MQTT: Error parsing data', message)); + } + + instance.send(SEND_TO.rpcCall, { "topic": o.topic, "content": message }); + }); + + client.on('close', function() { + clientReady = false; + + instance.status("Disconnected", "red"); + instance.send(SEND_TO.debug, { "message": "Client CLOSE signal received !" }); + }); + + client.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) { + console.log('MQTT client error', err); + sendClientError = false; + } + clientReady = false; + }); + + } + + + instance.on('0', function(data) { + + if (clientReady) { + //do we have some data in backup file? if any, process data from database + if (saveTelemetryOnError) { + //read telemetry data and send back to server + if (!processingData) processDataFromDatabase(); + } + + let stringifiedJson = JSON.stringify(data.data) + client.publish(`${o.topic}_forward`, stringifiedJson, { qos: 1 }); + } + 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 (saveTelemetryOnError && o.topic) { + //create new file from tbdata.nosql, if file size exceeds given limit, and clear tbdata.nosql + makeBackupFromDbFile(); + + //write to tb + data.data.id = UID(); + nosql.insert(data.data); + } + } + }); + + instance.on("1", _ => { + main(); + }) + + instance.close = function(done) { + if (clientReady) { + client.end(); + } + }; + + + function getDbBackupFileCounter(type) { + var files = fs.readdirSync(__dirname + "/../databases"); + + let counter = 0; + for (var i = 0; i < files.length; i++) { + + if (files[i] == "tbdatacloud.nosql") continue; + + if (files[i].endsWith(".nosql")) { + + let pos = files[i].indexOf("."); + if (pos > -1) { + + let fileCounter = counter; + let firstDigit = files[i].slice(0, pos); + + fileCounter = parseInt(firstDigit); + if (isNaN(fileCounter)) fileCounter = 0; + //console.log("getDbBackupFileCounter digit:", files[i], firstDigit, fileCounter, isNaN(fileCounter), type); + + if (type == "max") { + if (fileCounter > counter) { + counter = fileCounter; + } + } + else if (type == "min") { + if (counter == 0) counter = fileCounter; + + if (fileCounter < counter) { + counter = fileCounter; + } + } + } + } + + } + + if (type == "max") counter++; + + return counter; + } + + const makeBackupFromDbFile = async () => { + + if (!saveTelemetryOnError) return; + + //to avoid large file: tbdata.nosql + + //init value is 0! + if (insertNoSqlCounter > 0) { + --insertNoSqlCounter; + return; + } + + insertNoSqlCounter = 100; + + let source = __dirname + "/../databases/tbdatacloud.nosql"; + + var stats = fs.statSync(source); + var fileSizeInBytes = stats.size; + + if (fileSizeInBytes > noSqlFileSizeLimit) { + + let counter = 1; + counter = getDbBackupFileCounter("max"); + + let destination = __dirname + "/../databases/" + counter + "." + "tbdatacloud.nosql"; + + //make backup file + fs.copyFileSync(source, destination); + //fs.renameSync(p, p + "." + counter); + + //clear tbdata.nosql + fs.writeFileSync(source, ""); + fs.truncateSync(source, 0); + + } + } + + const processDataFromDatabase = async () => { + + if (restore_from_backup <= 0) return; + + //calculate diff + const now = new Date(); + let currentTime = now.getTime(); + let diff = currentTime - lastRestoreTime; + + if ((diff / 1000) < restore_backup_wait) { + //console.log("*********restore_backup_wait", diff, restore_backup_wait); + return; + } + + processingData = true; + + //get filename to process + let counter = getDbBackupFileCounter("min"); + + //we have some backup files + let dataBase = 'tbdata'; + + var nosql; + if (counter == 0) dataBase = 'tbdatacloud'; + else dataBase = counter + "." + 'tbdatacloud'; + + nosql = NOSQL(dataBase); + + //select all data - use limit restore_from_backup + let records = await promisifyBuilder(nosql.find().take(restore_from_backup)); + + for (let i = 0; i < records.length; i++) { + if (clientReady) { + + let item = records[i]; + let id = item.id; + + if (id !== undefined) { + //console.log("------------processDataFromDatabase - remove", id, dataBase, i); + + try { + + let message = JSON.parse(JSON.stringify(item)); + delete message.id; + client.publish(`${o.topic}_forward`, JSON.stringify(message), { qos: 1 }); + + //remove from database + await promisifyBuilder(nosql.remove().where("id", id)); + + } catch (error) { + //process error + console.log("processDataFromDatabase", error); + } + + } + + } + else { + processingData = false; + return; + } + } + + if (records.length > 0) { + //clean backup file + if (counter > 0) nosql.clean(); + } + + //no data in db, remove + if (records.length == 0) { + if (counter > 0) nosql.drop(); + } + + const d = new Date(); + lastRestoreTime = d.getTime(); + + processingData = false; + + } + + instance.on('options', main); + +}; diff --git a/RVO22/flow/cmd_manager.js b/RVO22/flow/cmd_manager.js new file mode 100755 index 0000000..25912df --- /dev/null +++ b/RVO22/flow/cmd_manager.js @@ -0,0 +1,3071 @@ +exports.id = 'cmd_manager'; +exports.title = 'CMD Manager'; +exports.group = 'Worksys'; +exports.color = '#5D9CEC'; +exports.version = '0.0.3'; +exports.output = ['red', 'blue', 'yellow', 'blue', 'white', 'green']; +exports.input = 3; +exports.icon = 'cloud-upload'; + +exports.html = ` +
+
+
+
RPC - run RPC calls

+
+
+
@(User)
+
+
+
@(Password)
+
+
+
@(My edge)
+
+
+
+`; +exports.readme = `Manager for CMD calls`; + + +exports.install = function(instance) { + + 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, isEmptyObject, emptyJsObject, writeToFile, addToArrayIfUnique } = require('./helper/utils'); + const bitwise = require('bitwise'); + + var SunCalc = require('./helper/suncalc'); + const DataToTbHandler = require('./helper/DataToTbHandler'); + const errorHandler = require('./helper/ErrorToServiceHandler'); + const { sendNotification } = require('./helper/notification_reporter'); + const process = require('process'); + const { errLogger, logger, monitor } = require('./helper/logger'); + + //for accelerometer purposes + const { naklony } = require("../databases/accelerometer_db"); + + const dbNodes = TABLE("nodes"); + const dbRelays = TABLE("relays"); + + let GLOBALS; + let SETTINGS; + let rsPort; + let tbHandler; + + // runTasks intervals + const SHORT_INTERVAL = 30; + const LONG_INTERVAL = 300; + + //send data to following instances: + const SEND_TO = { + debug: 0, + tb: 1, + http_response: 2, + dido_controller: 3, + infoSender: 4, + dailyReport: 5 + } + + 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 + } + + 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 sendNodeReadout = null; // interval for sending agregate data from node + + 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["1"] = minutes; // dimming + priorities["76"] = minutes; // power + + minutes = 5; + priorities["75"] = minutes; // current + priorities["79"] = minutes; // energy + priorities["87"] = minutes; // aktualny cas + //priorities["84"] = minutes; //accelerometer + + minutes = 10; + priorities["74"] = minutes; // voltage + priorities["77"] = minutes; // power factor + priorities["78"] = minutes; // frequency + + minutes = 60; + priorities["0"] = minutes; // statecode + priorities["6"] = minutes; // dusk + priorities["7"] = minutes; // dawn + priorities["8"] = minutes; // profile + + minutes = 60 * 24; + priorities["89"] = minutes; // verzia fw + priorities["80"] = minutes; // lifetime + + //prikazy kt sa budu spustat na dany node - see config.js in terminal-oms.app. (1 - dimming) + let listOfCommands = [0, 1, 6, 7, 8, 74, 75, 76, 77, 78, 79, 80, 87, 89]; + + 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; + + // holds dusk, dawn (and more) values + let sunCalcResult; + + //helper container for counting resolved group of commands (commands related to set profile) + let cmdCounter = {};//key is node, value is counter + + //TODO: is this set working?? According to previous checks, sets do not work + //if sending of profile to node fails, we send notification and push node into set, so we do not send notification twice + const nodeProfileSendFail = new Set(); + + //we expect to get current temperature in Senica from senica-prod01 + let temperatureInSenica = null; + let accelerometerInterval = null; + + //NOTE: daily reports senica: + //rvo_is_on status, we monitor all nodes - if true, power and dimming should be not 0, if false, 24/7 nodes should be 0, other rvo should not respond + let rvo_is_on; + let previous_rvo_is_on_value; + let handleDailyReport; //setInterval for dailyReportHandler function + let dailyReport = {}; //data needed for daily report + let reportToSend = {}; //final report which we send to cloud + let breakerCounter = null; // status of breakers after flow starts is not in report + let rvoPeriod; // interval of checking dusk dawn and if rvo_is_on + let initialReportStatus = false; + + const DAILY_REPORT_HANDLER_TIME = 3_600_000; + const SET_SUNCALC_RESULT_TIME = 3_600_000; + const SET_RVO_PERIOD_TIME = 300_000; + const ADD_NODE_TO_REPORT_TIME = 3_600_000; + + //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); + + let now = new Date(); + console.log("Cmd-mngr installed", now.toLocaleString("sk-SK")); + + sunCalcResult = calculateDuskDawn(); + + handleRsPort(); + + customTasksInterval = setInterval(reportEdgeDateTimeAndNumberOfLuminaires, 120_000); + setTimeout(reportEdgeDateTimeAndNumberOfLuminaires, 4000); + + //dailyReport related + emptyReportToSend(); + breakerCounter = Object.keys(relaysData).length - 1; // we get number of lines (breakers) except of line 0 + rvoPeriod = setInterval(setRvoPeriod, SET_RVO_PERIOD_TIME); + setTimeout(setRvoPeriod, 3000); + setInterval(setSunCalcResult, SET_SUNCALC_RESULT_TIME); + handleDailyReport = setInterval(dailyReportHandler, DAILY_REPORT_HANDLER_TIME); + + + setCorrectTime = setInterval(setCorrectPlcTimeOnceADay, 60000 * 60); // 1 hour + setCorrectPlcTimeOnceADay(); + + sendNodeReadout = setInterval(sendNodesData, 150_000); + accelerometerInterval = setInterval(accelerometerData, 60000 * 30); //30 min + } + + + 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" + //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 + // if node regular readout does not respond, we repeat request + params.repeatCounter = 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-mngr: 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.byte4 = 96; + params.recipient = 1; + params.register = 8; + params.rw = 1;//write + params.timestamp = timestamp; + 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.byte4 = 96; + params.recipient = 1; + params.register = 8; + params.rw = 1;//write + params.timestamp = timestamp; + 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). + */ + + 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.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.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 + { + + logger.debug("processNodeProfile: Threshold lux level for DUSK/DAWN", node); + + let params = getParams(); + params.type = "set_node_profile"; + params.address = node; + params.register = 96; + params.recipient = 1; + params.rw = 1;//write + params.timestamp = timestamp; + 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(); + params.type = "set_node_profile"; + params.address = node; + params.register = 97; + params.recipient = 1; + params.rw = 1;//write + params.timestamp = timestamp; + 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.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); + + 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); + + console.log("proces profile finished *********************") + } + + + 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; + }); + } + + + 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) { + for (let k in nodesData) { + 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`); + } + } + } + + + function loadRelaysData(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 (value.contactor == 1) processAllNodeProfilesOnLine(value.line); + } + } + + + function reportOnlineNodeStatus(line) { + //Po zapnutí línie broadcastovo aktualizovať predtým čas a o 3 sek neskor - status, brightness + + logger.debug("Cmd-mngr: ----->reportOnlineNodeStatus for line", line); + + const d = new Date(); + + // broadcast actual time + let params = getParams(); + params.address = 0xffffffff;//Broadcast + params.byte1 = d.getHours(); + params.byte2 = d.getMinutes(); + params.recipient = 2;//2 broadcast, address = 0 + params.register = 87;//Actual time + params.rw = 1;//write + params.type = "node-onetime-write"; + params.timestamp = d.getTime() + 30000; + params.info = "run broadcast: Actual time"; + //params.debug = true; + + tasks.push(params); + + let sec = 3; + setTimeout(function() { + //Po zapnutí línie - spraviť hromadný refresh stavu práve zapnutých svietidiel + + let time = Date.now(); + + for (let k in nodesData) { + + //potrebujem nody k danej linii + 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].node_status_before_offline === true || nodesData[k].status === true) { + status = "OK"; + nodesData[k].time_of_last_communication = time; + } + + nodesData[k].readout.status = status; + + updateNodeStatus(k, status === "OK" ? true : false); + if (nodesData[k].hasOwnProperty("node_status_before_offline")) delete nodesData[k].node_status_before_offline; + sendTelemetry({ status: status }, tbname, time); + + //vyreportovanie dimming, current, input power pre liniu pre vsetky nody + //Prud + { + let params = getParams(); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 75;//prud + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = time + 4000; + params.info = 'read current'; + //params.debug = true; + tasks.push(params); + } + + //vykon + { + let params = getParams(); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 76;//výkon + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = time + 4100; + params.info = 'read power'; + //params.debug = true; + + tasks.push(params); + } + //dimming + { + let params = getParams(); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 1;//dimming + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = time + 4200; + params.info = 'read dimming'; + //params.debug = true; + + tasks.push(params); + } + + } + } + + }, sec * 1000); + } + + + function reportOfflineNodeStatus(line) { + + logger.info("Cmd-mngr: ------>reportOffLineNodeStatus for line ", line); + + values = {}; + values["dimming"] = 0;//brightness + values["power"] = 0;//výkon + values["current"] = 0;//prúd + values["status"] = "OFFLINE"; + + const date = Date.now(); + + Object.keys(nodesData).forEach(node => { + + //potrebujem nody k danej linii + if (line == nodesData[node].line || line == undefined) { + + let tbname = nodesData[node].tbname; + let nodeStatus = nodesData[node].status; + + //in case we have reported offline node status, we return (continue with next node) + if (nodeStatus === "OFFLINE") return; + + nodesData[node].node_status_before_offline = nodeStatus; + nodesData[node].status = "OFFLINE"; + nodesData[node].readout = {}; + + sendTelemetry({ ...values }, tbname, date); + } + }); + + } + + + function turnLine(onOrOff, line, info) { + let obj = { + line: line, + command: onOrOff, + info: info + }; + + //to assure, handleDailyReportFunction do not run before rvo_is_on variable changes. So after every line switch we reset the timer + clearInterval(handleDailyReport); + handleDailyReport = setInterval(dailyReportHandler, DAILY_REPORT_HANDLER_TIME); + + //logger.debug("linia", line, obj); + instance.send(SEND_TO.dido_controller, obj); + } + + + 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"; + 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]) { + //CRC_ERROR + message = "NOK"; + error = "CRC_ERROR c1"; + instance.send(SEND_TO.debug, "CRC_ERROR c1"); + } + + 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") { + instance.send(SEND_TO.debug, bytes); + instance.send(SEND_TO.debug, "RESPONSE " + type + " - " + bytes[4]); + + //logger.debug(SEND_TO.debug, "RESPONSE " + type + " - " + bytes[4], bytes); + + error = "type is: " + type; + + message = "NOK"; + } + + return { message, type, error }; + } + + + //BUILD TASKS// + function buildTasks(params) { + + //return; + console.log("buidTAaasks start ****************", params); + monitor.info("buildTasks - params", params); + + let processLine; //defined line + let init = false; + let processLineProfiles = true; + let processBroadcast = true; + let processNodes = true; + + if (params == undefined) { + init = true; + tasks = []; + logger.debug("-->buildTasks clear tasks"); + } + else { + processLineProfiles = params.processLineProfiles; + processBroadcast = false; + processNodes = false; + + processLine = params.line; + } + + let now = new Date(); + + //process line profiles + if (processLineProfiles) { + + let keys = Object.keys(relaysData); + + for (let i = 0; i < keys.length; i++) { + + let line = parseInt(keys[i]); + let profilestr = relaysData[line].profile; + + if (processLine != undefined) { + if (processLine != line) continue; + } + + try { + + /** + * we process line profiles: timepoints, astro clock, lux_sensor, offsets ... + */ + if (profilestr === "") throw ("Profile is not defined"); + let profile = JSON.parse(profilestr); + 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; + + // add name to regular profile timepoint and delete unused end_time key: + time_points.forEach(point => { + point.name = "profileTimepoint" + delete point.end_time; + }); + + //monitor.info("buildTasks: time_points", time_points); + + + /** + * 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 astro clock true, we remove all regular profile points + time_points = []; + + //TODO: when astro clock == true, is offset calculated ??? + //let duskAstroClockOffset = profile.dusk_astro_clock_offset; + //let dawnAstroClockOffset = profile.dawn_astro_clock_offset; + //console.log("line astro clock offsets dusk a dawn: ", duskAstroClockOffset, dawnAstroClockOffset); + // maybe add dusk dawn offset to calculateDuskDawn ?? what dusk dawn will be if dawn_lux_sensor == true?? + //let sunCalcResult = calculateDuskDawn(new Date(), line, duskAstroClockOffset, dawnAstroClockOffset); + + 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 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); + + 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); + + 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(':'); + + let ad = new Date(); + ad.setHours(parseInt(ahours), parseInt(aminutes), 0); + + let bd = new Date(); + bd.setHours(parseInt(bhours), parseInt(bminutes), 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++) { + + let start_time = new Date(); + let [hours, minutes] = time_points[t].start_time.split(':'); + start_time.setHours(parseInt(hours), parseInt(minutes), 0); + + //task is in 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(); + params.type = "relay"; + params.line = parseInt(line); + params.value = time_points[t].value; + params.tbname = relaysData[line].tbname; + params.timestamp = start_time.getTime(); + + // 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; + + //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)) { + 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; + + params.debug = true; + + //turn on/off line + tasks.push(params); + monitor.info("TimePoint params: ", params.info, start_time); + } + + monitor.info("-->time_points final", line, time_points); + + //ensure to turn on/off according to calculated currentValue + let params = getParams(); + params.type = "relay"; + params.line = parseInt(line); + params.tbname = relaysData[line].tbname; + params.value = currentValue; + params.timestamp = i; + params.debug = true; + + //logger.debug(now.toLocaleString("sk-SK")); + 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; + + tasks.push(params); + + } catch (error) { + if (profilestr !== "") { + //errLogger.error(profilestr, error); + console.log(`Cmd_mngr: Unable to process line profile ${line}. Error: `, error); + errorHandler.sendMessageToService(profilestr + "-" + error, 0, "js_error"); + } else { + turnLine("off", line, "No line profile. Switching it off on startup"); + } + } + + } + //logger.debug("tasks:"); + //logger.debug(tasks); + } + + + //NOTE: PROCESS DEFAULT BROADCASTS - Time of dusk, Time of dawn, Actual Time + if (processBroadcast) { + + let d = new Date(); + let time = d.getTime(); + //let sunCalcResult = calculateDuskDawn(); + + { + let params = getParams(); + + params.address = 0xffffffff;//broadcast + params.byte1 = sunCalcResult["dusk_hours"]; + params.byte2 = sunCalcResult["dusk_minutes"]; + params.recipient = 2;//2 broadcast, + params.register = 6;//Time of dusk + params.rw = 1;//write + params.type = "node-regular-write"; + params.timestamp = time + 60000; + params.addMinutesToTimestamp = 60 * 3; //kazde 3 hodiny zisti novy dusk + params.info = "Broadcast-duskTime"; + + tasks.push(params); + } + + { + let params = getParams(); + + params.address = 0xffffffff;//broadcast + params.byte1 = sunCalcResult["dawn_hours"]; + params.byte2 = sunCalcResult["dawn_minutes"]; + params.recipient = 2; //2 broadcast + params.register = 7;//Time of dawn + params.rw = 1;//write + params.type = "node-regular-write"; + params.timestamp = time + 60001; + params.addMinutesToTimestamp = 60 * 3; //kazde 3 hodiny zisti novy dawn + params.info = "Broadcast-dawnTime"; + + tasks.push(params); + } + + { + let params = getParams(); + + params.address = 0xffffffff;//broadcast + params.byte1 = d.getHours(); + params.byte2 = d.getMinutes(); + params.recipient = 2; //2 broadcast + params.register = 87;//Actual time + params.rw = 1;//write + params.type = "node-regular-write"; + params.timestamp = time + 60002; + params.addMinutesToTimestamp = 5; + params.info = "run broadcast: Actual time"; + + tasks.push(params); + } + + } + + //process nodes & tasks - read node's data + if (processNodes) { + + let time = Date.now(); + + for (let k in nodesData) { + let address = parseInt(k); + let tbname = nodesData[k].tbname; + let register = 0; + + for (let i = 0; i < listOfCommands.length; i++) { + + register = listOfCommands[i]; + let addMinutesToTimestamp = priorities[register]; + + let params = getParams(); + + params.address = address; + params.recipient = 1; + params.register = register; + params.type = register == 1 ? "node-dimming-read" : "node-regular-read"; + params.tbname = tbname; + params.timestamp = time + 5000 + i * 500 + addMinutesToTimestamp * 1000; //to make slight time difference + params.addMinutesToTimestamp = addMinutesToTimestamp; + params.info = "Node regular read command"; + + tasks.push(params); + } + + } + } + + + //niektore ulohy sa vygeneruju iba 1x pri starte!!! + if (!init) return; + + + //Master node FW version - modifies SETTINGS.masterNodeIsResponding + { + let params = getParams(); + params.type = "cmd-master"; + params.register = 4; + params.address = 0; + params.timestamp = 0; + params.addMinutesToTimestamp = 5; + params.tbname = SETTINGS.rvoTbName; + params.info = "Master node FW verzia"; + //params.debug = true; + + tasks.push(params); + } + + //kazdu hodinu skontrolovat nastavenie profilov + { + let params = getParams(); + params.type = "process_profiles"; + params.timestamp = Date.now() + 60001; + params.addMinutesToTimestamp = 60;//60 = every hour + params.info = "detekcia nespracovaných profilov linie a nodov"; + //params.debug = true; + + tasks.push(params); + } + + monitor.info("tasks created:", tasks.length); + } + + + /** + * We process line profile, where "astro_clock": true + * example profile: + * + "dawn_lux_sensor": true, + "dusk_lux_sensor": true, + "dawn_lux_sensor_value": 5, + "dusk_lux_sensor_value": 5, + "dawn_astro_clock_offset": 0, + "dusk_astro_clock_offset": 10, + "dawn_lux_sensor_time_window": 30, + "dusk_lux_sensor_time_window": 30, + "dawn_astro_clock_time_window": 60, + "dusk_astro_clock_time_window": 60 + + * if dawn: if currentTimestamp is in timewindow "dawnTime + and - dawn_lux_sensor_time_window" and lux value >= lux_sensor_value, we switch off the line. + * if dusk: we do oposite + * + * dawn: usvit - lux je nad hranicou - vypnem + * dusk: sumrak - lux je pod hranicou - zapnem + */ + 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++) { + + let line = keys[i]; //line is turned off by default + let profilestr = relaysData[line].profile; + const contactor = relaysData[line].contactor; + + try { + + let profile = JSON.parse(profilestr); + if (Object.keys(profile).length === 0) throw ("turnOnOffLinesAccordingToLuxSensor - profile is not defined"); + + 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 (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"); + } + } + } + + //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 (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"); + } + } + } + + } + + } catch (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) { + //MASTER + if (node == 0) return; + + let nodeObj = nodesData[node]; + if (nodeObj == undefined) return; + + let nodeCurrentStatus = nodeObj.status; + const now = Date.now(); + + let data = null; + + if (nodeCurrentStatus === "OFFLINE") { + data = { status: newStatus }; + nodeDbStatusModify(node, data); + return; + } + else 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; + } + + } + + + 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 }; + } + }); + }); + } + + + function processDailyReport() { + + const now = Date.now(); + + for (const [key, value] of Object.entries(dailyReport)) { + + if (["name", "time", "dusk_and_dawn"].includes(key)) continue; + + let poleNumber = nodesData[key]["pole_number"]; + let line = dailyReport[key].line; + let nodeType = nodesData[key]["node_type"]; + let fullNodeName = key // key == nodeNumber + + if (poleNumber && nodeType) { + fullNodeName = SETTINGS.rvo_number + "/" + poleNumber + "_" + line + "L_" + key + "_" + nodeType; + } else { + fullNodeName = key; + } + + if (rvo_is_on) { + + if (value.initialTs) { + if (value.initialTs + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["night_no_data"], fullNodeName); + console.log('report nedostava ziadne data uz hodinu', fullNodeName); + value.initialTs = now; + } + } + if (value.dimmingIsZeroTime) { + if (value.dimmingIsZeroTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["night_dimming=0"], fullNodeName); + console.log("report node dimming je 0 ale ma svietit", fullNodeName); + value.dimmingIsZeroTime = now; + } + } + if (value.powerIsZeroTime) { + if (value.powerIsZeroTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["night_power=0"], fullNodeName); + console.log("report node power je 0 ale ma svietit", fullNodeName); + value.powerIsZeroTime = now; + } + } + + } else { + + let contactorStatus = relaysData[line].contactor; + if (contactorStatus === 1) { + + if (value.initialTs) { + if (value.initialTs + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["day_24/7_no_data"], fullNodeName); + console.log('node je na 24/7 ale nedostava ziadne data uz hodinu', fullNodeName); + value.initialTs = now; + } + } + if (value.dimmingIsOnButShouldBeOffTime) { + if (value.dimmingIsOnButShouldBeOffTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["day_24/7_dimming>0"], fullNodeName); + console.log("report dimming je > 0 ale nema svietit", fullNodeName); + value.dimmingIsOnButShouldBeOffTime = now; + } + } + if (value.powerIsOnButShouldBeOffTime) { + if (value.powerIsOnButShouldBeOffTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["day_24/7_power>0"], fullNodeName); + console.log("report power je > 0 ale nema svietit", fullNodeName); + value.powerIsOnButShouldBeOffTime = now; + } + } + + } + + } + + } + + let report = {}; + report["name"] = SETTINGS.rvo_name; + report["time"] = new Date(); + report["report"] = reportToSend; + + writeToFile(F.path.root("report_data.log"), report, true); + instance.send(SEND_TO.dailyReport, report); + } + + + function dailyReportHandler() { + + if (!SETTINGS.daily_report) return; + + // after dawn we empty reportToSend and start to get data for a new day + const date = new Date(); + const hour = date.getHours(); + const minute = date.getMinutes(); + + console.log("now: ", hour, minute, "suncalc: ", sunCalcResult.dawn_hours, sunCalcResult.dawn_minutes); + + if (hour === sunCalcResult.dawn_hours) { + + //NOTE: ak je este pred usvitom, spracujeme report a posleme na cloud, ak uz je po usvite, resetujeme report plnime data noveho dna + if (minute >= sunCalcResult.dawn_minutes - 2) { + emptyReportToSend(); + emptyDailyReport(); + console.log("Podmienka 1 v dailyReport handler"); + } else { + processDailyReport(); + emptyReportToSend(); + emptyDailyReport(); + console.log("Podmienka 2 v dailyReport handler"); + } + + initialReportStatus = true; + + // ak sa funkcia spusti o hodinu alebo 2 neskor, ako je usvit (moze sa to stat, kedze kazde zapnutie/vypnutie linii odznova spusti casovac. + } else if (hour === sunCalcResult.dawn_hours + 1 || hour === sunCalcResult.dawn_hours + 2) { + if (!initialReportStatus) { + emptyReportToSend(); + emptyDailyReport(); + initialReportStatus = true; + console.log("Podmienka 3 v dailyReport handler"); + } else { + processDailyReport(); + initialReportStatus = true; + console.log("Podmienka 4 v dailyReport handler"); + } + } else { + processDailyReport(); + initialReportStatus = false; + console.log("Podmienka 5 v dailyReport handler"); + } + + console.log("initialReportStatus: ", initialReportStatus); + + } + + function emptyReportToSend() { + emptyJsObject(reportToSend); + reportToSend["contactor"] = { off: [], on: [] }; + reportToSend["night_no_data"] = []; + reportToSend["night_dimming=0"] = []; + reportToSend["night_power=0"] = []; + reportToSend["day_24/7_no_data"] = []; + reportToSend["day_24/7_dimming>0"] = []; + reportToSend["day_24/7_power>0"] = []; + console.log(`resetuje sa reportToSend`); + } + + + //NOTE: ked je initialTs stale rovnaky a zistime ze linie su vypnute (relaysData.line.contactor) - zistim, ci je node na tej linii. Vieme, ze ak je linia vypnuta je to v poriadku lebo nie je na 24/7 linii + //ak je na 24/7 linii, reportujeme, ze neprijima data + function emptyDailyReport() { + const ts = Date.now(); + emptyJsObject(dailyReport); + + //NOTE: do dailyReport dame vsetky nody a pravidelne kontrolujeme ci maju data + //ked nastane sumrak/usvit a svetla maju zacat/prestat svietit, dailyReport spravime nanovo: + for (const [key, value] of Object.entries(nodesData)) { + dailyReport[value.node] = { line: value.line, initialTs: ts }; + } + + console.log("dailyReport: ", dailyReport); + } + + + async function runTasks() { + + clearInterval(interval); + + let currentTimestamp = Date.now(); + + //sort tasks based on timestamp + 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) { + instance.send(SEND_TO.debug, "no tasks created"); + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + if (!rsPort.isOpen) { + instance.send(SEND_TO.debug, "!rsPort.isOpen"); + //await rsPort.open(); + //console.log("Cmd-mngr: !rsPort.isOpen"); + } + + let currentTask = tasks[0]; + + if (currentTask.debug) { + //logger.debug("--->task to process", currentTask); + } + + if (currentTask.timestamp <= currentTimestamp) { + let params = { ...tasks[0] }; + + //allow terminal commands + if (SETTINGS.maintenance_mode && params.type !== "cmd-terminal") { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + let type = params.type; + let tbname = params.tbname; + let node = params.address; + let register = params.register; + let line = null; + let itIsNodeCommand; + + if (nodesData[node] !== undefined) { + line = nodesData[node].line; + itIsNodeCommand = true; + } + + if (params.line !== undefined) line = params.line; + + if (params.addMinutesToTimestamp > 0 || params.timePointName) { + tasks[0].timestamp = currentTimestamp + tasks[0].addMinutesToTimestamp * 60000; + } else { + tasks.shift(); + } + + //kontrola nespracovanych profilov nodov + //TODO: co ked niektore nody neprijimaju profily? kazdu hodinu zahltuju "tasks" array + if (type == "process_profiles") { + //na vsetky zapnutych liniach sa spracuju nespracovane profily nodov + loadRelaysData(); + interval = setInterval(runTasks, SHORT_INTERVAL); + return; + } + + //relay + if (type == "relay") { + + const timePointName = params.timePointName; + const value = params.value; + + let date = new Date(); + date.setDate(date.getDate() + 1);//next day + + let sunCalcResult; + if (timePointName) sunCalcResult = calculateDuskDawn(date, params.line); + + + if (timePointName == "dawn") { + tasks[0].timestamp = sunCalcResult.dawn_time; + } + else if (timePointName == "dusk") { + tasks[0].timestamp = sunCalcResult.dusk_time; + } + else if (timePointName == "luxOn") { + tasks[0].timestamp = sunCalcResult.dusk_time + params.dusk_lux_sensor_time_window * 60000; + } + else if (timePointName == "luxOff") { + tasks[0].timestamp = sunCalcResult.dawn_time + params.dawn_lux_sensor_time_window * 60000; + } + else if (timePointName == "profileTimepoint") { + tasks[0].timestamp = currentTimestamp + tasks[0].addMinutesToTimestamp * 60000; + } + + let info = "aplikovany bod profilu"; + let onOrOff = ""; + value == 1 ? onOrOff = "on" : onOrOff = "off"; + + turnLine(onOrOff, params.line, info); + + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + if (!SETTINGS.masterNodeIsResponding) { + //ak neodpoveda, nebudeme vykonavat ziadne commands, okrem cmd-terminal cmd-master + errorHandler.sendMessageToService("Master node is not responding"); + + let stop = true; + + if (type === "cmd-terminal" || type === "cmd-master") stop = false; + if (stop) { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + } + + let contactorStatus = 1; + if (relaysData[line] != undefined) contactorStatus = relaysData[line].contactor; + + if (line === 0 || contactorStatus === 0 || FLOW.deviceStatus.state_of_breaker[line] === "Off") { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + // TODO: -> status offline for rvo if rotary_switch_state is OFF, this is source of errors + // check if rotary_switch_state == "Off" + // state_of_braker: disconnected = true? + + if (!rsPort.isOpen) { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + //RE-CALCULATE VALUES + //set actual time for broadcast + if (register == 87 && params.recipient === 2) { + var d = new Date(); + params.byte1 = d.getHours();//h + params.byte2 = d.getMinutes();//m + } + + //SET DUSK/DAWN FOR BROADCAST + //Time of dusk + if (register == 6 && params.recipient === 2) { + + if (type != "cmd-terminal") { + params.byte1 = sunCalcResult["dusk_hours"];//h + params.byte2 = sunCalcResult["dusk_minutes"];//m + } + } + + //Time of dawn + if (register == 7 && params.recipient === 2) { + if (type != "cmd-terminal") { + params.byte1 = sunCalcResult["dawn_hours"];//h + params.byte2 = sunCalcResult["dawn_minutes"];//m + } + } + //----------------------- + + instance.send(SEND_TO.debug, "address: " + node + " register:" + register + "type: " + type); + + var startTime, endTime; + startTime = new Date(); + + let saveToTb = true; + if (!tbname) saveToTb = false; + + let resp = com_generic(node, params.recipient, params.rw, register, params.name, params.byte1, params.byte2, params.byte3, params.byte4); + let readBytes = 11; + let timeout = 4000; + + + // await keyword is important, otherwise incorrect data is returned! + await writeData(rsPort, resp, readBytes, timeout).then(function(data) { + + //sometimes happens, that status of node changes to OK, NOK even if line was turned off and should be status OFFLINE. To prevent this, we return if line contactor is 0: + if (itIsNodeCommand && line && relaysData[line].contactor !== 1) return; + + 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); + + //ak sa odpoved zacina 0 - je to v poriadku, inak je NOK + let message = result.message; // OK, NOK + let message_type = result.type; + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + console.log("detected response:", result); + logger.debug("Cmd-mngr: writeData done " + message_type + " duration: " + timeDiff + " type: " + params.debug, params, result); + } + } + + let values = {}; + + //CMD FINISHED + if (message == "OK") { + + updateNodeStatus(node, true); + + //write + if (type == "set_node_profile") { + let result = cmdCounterResolve(node); + if (result == 0) { + dbNodes.modify({ processed: true }).where("node", node).make(function(builder) { + builder.callback(function(err, response) { + + sendNotification("Cmd-mngr: process cmd", SETTINGS.rvoTbName, "dimming_profile_was_successfully_received_by_node", { node: node }, "", SEND_TO.tb, instance); + + logger.debug("--> profil úspešne odoslaný na node č. " + node); + nodesData[node].processed = true; + nodeProfileSendFail.delete(node); + }); + }); + } + } + + //parse read response + if (params.rw == 0) { + values = processResponse(register, dataBytes); //read + } + + if (itIsNodeCommand) { + values.comm_status = "OK"; + values.status = "OK"; + nodesData[node].readout = { ...nodesData[node].readout, ...values }; + + + if (SETTINGS.daily_report) { + //TODO: co ak nedostavame odpovede z nodu ? Musime vyreportovat!! + //v dailyReport teda musi byt kompletny zoznam nodov a neustale kontrolovat, ci maju data, ak nie report node - neodpoveda + if (register === 1) { + + let now = Date.now(); + + if (rvo_is_on === true) { + + if ("dimmingIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].dimmingIsOnButShouldBeOffTime; + + if (values.dimming > 0) { + if ("dimmingIsZeroTime" in dailyReport[node]) delete dailyReport[node].dimmingIsZeroTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if (!("dimmingIsZeroTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], dimmingIsZeroTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } else { + + if ("dimmingIsZeroTime" in dailyReport[node]) delete dailyReport[node].dimmingIsZeroTime; + + if (values.dimming > 0) { + if (!("dimmingIsOnButShouldBeOffTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], dimmingIsOnButShouldBeOffTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if ("dimmingIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].dimmingIsOnButShouldBeOffTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } + } + + if (register === 76) { + + let now = Date.now(); + + if (rvo_is_on === true) { + + if ("powerIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].powerIsOnButShouldBeOffTime; + + if (values.power > 1) { + if ("powerIsZeroTime" in dailyReport[node]) delete dailyReport[node].powerIsZeroTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if (!("powerIsZeroTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], powerIsZeroTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } else { + + if ("powerIsZeroTime" in dailyReport[node]) delete dailyReport[node].powerIsZeroTime; + + if (values.power > 1) { + if (!("powerIsOnButShouldBeOffTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], powerIsOnButShouldBeOffTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if ("powerIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].powerIsOnButShouldBeOffTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } + } + } + + } + + //master node + if (node == 0) { + sendNotification("Cmd-mngr: 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; + } + + if (params.debug) { + //logger.debug("saveToTb", saveToTb, tbname, values); + } + + if (saveToTb && type != "node-regular-read") { + sendTelemetry(values, tbname); + } + else { + if (type == "cmd-terminal") { + terminalCommandResponse(params, "SUCCESS", data); + } + } + + } + else { + terminalCommandResponse(params, "ERROR", data); + handleNokResponseOnRsPort("handleNOK else block", params, itIsNodeCommand, saveToTb); + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + //logger.debug("writeData err: ", error, result, params); + logger.debug("writeData err: ", tbname, node, register, values); + } + } + + //logger.debug(error, result, params); + } + }).catch(function(reason) { + + //console.log("writeData catch exception", reason); + instance.send(SEND_TO.debug, reason); + + terminalCommandResponse(params, "FAILURE", null, reason); + handleNokResponseOnRsPort("handleNOK catch block", params, itIsNodeCommand, saveToTb); + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + logger.debug("-->WRITE FAILED: " + reason, params.debug, params); + } + } + + }); + + } + 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); + } + + + // if node does not respond to request, we repeat request 3 times: + function repeatCommand(params) { + params.repeatCounter++; + if (params.repeatCounter < 4) { + params.timestamp = 0; + params.addMinutesToTimestamp = 0; + tasks.push(params); + } + } + + function handleNokResponseOnRsPort(message, params, itIsNodeCommand, saveToTb) { + + let node = params.address; + let register = params.register; + let type = params.type; + let tbName = params.tbname; + if (!tbName) return; + + let values = {}; + + let updateStatus = updateNodeStatus(node, false); + + if (itIsNodeCommand) { + values.comm_status = "NOK"; + nodesData[node].readout.comm_status = "NOK"; + repeatCommand(params); + } + + if (updateStatus) { + values.status = "NOK"; + nodesData[node].readout.status = "NOK"; + } + + if (type === "node-regular-read") return; + + //master node + if (node == 0) { + sendNotification("Cmd-mngr: 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; + + if (register == 4) values["master_node_version"] = "NOK"; + } + + if (type == "set_node_profile") { + delete cmdCounter[node]; + logger.debug("profil nebol úspešne odoslaný na node č. ", params); + + if (!nodeProfileSendFail.has(node)) { + sendNotification("Cmd-mngr: process cmd", tbName, "configuration_of_dimming_profile_to_node_failed", { node: node }, "", SEND_TO.tb, instance); + nodeProfileSendFail.add(node); + } + } + + // console.log("------",node, register, type, itIsNodeCommand, updateStatus, saveToTb, values); + if (saveToTb) { + sendTelemetry(values, tbName); + } + + } + + + function sendNodesData() { + Object.keys(nodesData).forEach(node => { + if (nodesData[node]["status"] !== "OFFLINE") { + sendTelemetry(nodesData[node].readout, nodesData[node].tbname); + nodesData[node].readout = {}; + } + }) + } + + + /** + * 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; + } + + 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); + + //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 === "OFFLINE") { + nodeObj.node_status_before_offline === true ? number_of_ok_luminaires++ : number_of_nok_luminaires++; + } + else if (nodeObj.status == true) 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 - ts % 60000 //round to full minute + }; + + sendTelemetry(values, SETTINGS.rvoTbName, ts); + } + + + function setSunCalcResult() { + //if next day, we get new dusk and dawn. To make sure, in local timezone 2:00 means 00:00 in utc (it means next day) + if (new Date().getHours() === 2) { + sunCalcResult = calculateDuskDawn(); + console.log("Novy suncalc: ", sunCalcResult); + } + } + + + function setRvoPeriod() { + + if (!SETTINGS.daily_report) return; + + const ts = Date.now(); + + previous_rvo_is_on_value = rvo_is_on; + + if (ts < sunCalcResult.dawn_time - 1_800_000) { // nodes should be on (00:00 -> 06:00 ( - pol hodina, lebo rvo vypina skor) + rvo_is_on = true; + } else if (sunCalcResult.dawn_time - 1_800_000 < ts && ts < sunCalcResult.dusk_time + 1_800_000) { // nodes should be off 06:00 -> 21:00 + rvo_is_on = false; + } else if (sunCalcResult.dusk_time + 1_800_000 < ts) { // nodes should be on 21:00 -> 00:00 + rvo_is_on = true; + } + + if (previous_rvo_is_on_value !== rvo_is_on) { + emptyDailyReport(); + console.log("rvo_is: ", rvo_is_on, previous_rvo_is_on_value); + } + } + + + function handleRsPort() { + + if (rsPort) { + rsPort.removeAllListeners(); + rsPort = null; + } + + //! 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-mngr: rsPort opened success"); + + 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); + + }).catch(function(reason) { + instance.send(SEND_TO.debug, "Cmd-mngr: RPC runSyncExec - promise rejected:" + reason); + }); + }); + + rsPort.on('error', function(err) { + errorHandler.sendMessageToService([exports.title, "unable to open port", SETTINGS.serial_port, err.message], 0); + monitor.info("Cmd-mngr: Error on rsPort", err.message); + }); + + rsPort.on("close", () => { + monitor.info("Cmd-mngr: rsPort closed, reconnecting..."); + setTimeout(handleRsPort, 1000); + }); + + rsPort.open(); + } + + + instance.on("close", () => { + clearInterval(interval); + clearInterval(customTasksInterval); + clearInterval(setCorrectTime); + clearInterval(sendNodeReadout); + clearInterval(accelerometerInterval); + rsPort.close(); + }); + + instance.on("0", _ => { + main(); + }) + + + instance.on("2", _ => { + console.log("dailyReport, reportToSend, rvo_is_on", dailyReport, reportToSend, rvo_is_on, previous_rvo_is_on_value); + }) + + instance.on("1", 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(); + return; + } + else if (flowdata.data == "close") { + rsPort.close(); + return; + } + else if (flowdata.data == "clean") { + tasks = []; + return; + } + else if (flowdata.data == "buildtasks") { + //build & run + return; + } + else if (flowdata.data == "run") { + //durations = []; + + if (tasks.length == 0) { + + buildTasks(); + + if (rsPort.isOpen) { + interval = setInterval(runTasks, 100); + } + else { + instance.send(SEND_TO.debug, "port is not opened!!!"); + } + } + } + else { + //terminal data - object + //logger.debug("flowdata", flowdata.data); + + if (typeof flowdata.data === 'object') { + //logger.debug("dido", flowdata.data); + if (flowdata.data.hasOwnProperty("sender")) { + //data from dido_controller + if (flowdata.data.sender == "dido_controller") { + + if (flowdata.data.hasOwnProperty("cmd")) { + let cmd = flowdata.data.cmd; + + if (cmd == "buildTasks") { + clearInterval(interval); + + logger.debug("-->Cmd-mngr: BUILD TASKS"); + buildTasks(); + + //logger.debug("tasks:"); + //logger.debug(tasks); + + logger.debug("-->Cmd-mngr: RUN TASKS"); + interval = setInterval(runTasks, 5000); + } + else if (cmd == "reload_relays") { + loadRelaysData(flowdata.data.line); + + if (flowdata.data.dataChanged) { + if (!flowdata.data.value) { + reportOfflineNodeStatus(flowdata.data.line); + } + else { + reportOnlineNodeStatus(flowdata.data.line); + } + } + + } + else if (cmd == "rotary_switch_state") { + let value = flowdata.data.value; + + //state was changed + if (rotary_switch_state != value) { + if (value == "Off") { + //vyreportovat vsetky svietdla + reportOfflineNodeStatus(); + } + + rotary_switch_state = value; + } + } + 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) { + + // we send lux_sensor value to all nodes: + let params = getParams(PRIORITY_TYPES.node_broadcast); + + params.recipient = 2;//2 broadcast, address = 0 + params.address = 0xffffffff;//Broadcast + + let ba = longToByteArray(lux_sensor); + + params.byte3 = ba[1];//msb + params.byte4 = ba[0]; + params.timestamp = PRIORITY_TYPES.node_broadcast; + params.info = "run broadcast: Actual Lux level from cabinet"; + params.register = 95;//Actual Lux level from cabinet + params.rw = 1;//write + + tasks.push(params); + + //process profiles + turnOnOffLinesAccordingToLuxSensor(lux_sensor); + } + } + else if (cmd == "state_of_breaker") { + //istic linie + + breakerCounter--; + + let value = flowdata.data.value; + let line = parseInt(flowdata.data.line); + + let dataChanged = false; + if (state_of_breaker[line] != value) dataChanged = true; + + state_of_breaker[line] = value; + + let status = "OK"; + if (value == "Off") status = "NOK"; + + if (dataChanged) { + + if (relaysData.hasOwnProperty(line)) { + let tbname = relaysData[line].tbname; + + if (value == "Off") { + sendNotification("Cmd-mngr: onData", tbname, "circuit_breaker_was_turned_off_line", { line: line }, "", SEND_TO.tb, instance, "circuit_breaker"); + if (breakerCounter < 0) reportToSend["contactor"]["off"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + else { + sendNotification("Cmd-mngr: onData", tbname, "circuit_breaker_was_turned_on_line", { line: line }, "", SEND_TO.tb, instance, "circuit_breaker"); + if (breakerCounter < 0) reportToSend["contactor"]["on"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + + //report status liniu + sendTelemetry({ status: status }, tbname) + + //current value + if (value == "Off") reportOfflineNodeStatus(line); //vyreportovat vsetky svietidla na linii + } + + } + } + else { + logger.debug("undefined cmd", cmd); + } + } + } + + return; + } + + //data from worksys + if (flowdata.data.hasOwnProperty("topic")) { + + let data = getNested(flowdata.data, "content", "data"); + + //if we get temperature in senica from senica-prod01 + let temperature = getNested(flowdata.data, "content", "senica_temperature"); + + if (temperature !== undefined) { + temperatureInSenica = temperature; + return; + } + + if (data === undefined) { + console.log("Invalid rpc command came from platform"); + return; + } + + let command = data.params.command; + let method = data.method; + let profile = data.params.payload; + if (profile == undefined) profile = ""; + let entity = data.params.entities[0]; + let entity_type = entity.entity_type; + let tbname = entity.tb_name; + + instance.send(SEND_TO.debug, flowdata.data); + 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") { + + //let command = data.params.command; + let value = data.params.payload.value; + + if (command == "dimming") { + + let nodeWasFound = false; + let keys = Object.keys(nodesData); + + //logger.debug("-----", keys); + + 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); + + value = parseInt(value); + if (value > 0) value = value + 128; + + params.type = "node-onetime-write"; + params.tbname = tbname; + params.address = node; + params.register = 1; + params.recipient = 1; + params.byte4 = value; + params.rw = 1; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'set dimming from platform'; + //params.debug = true; + + //debug(params); + logger.debug("dimming", params); + + tasks.push(params); + + 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); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 1; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read dimming (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + //pridame aj vyreportovanie - vykon + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 76; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read Input Power (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + //pridame aj vyreportovanie - prud svietidla + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 75; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read Input Current (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + //pridame aj vyreportovanie - power faktor - ucinnik + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 77; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read power factor (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + }, 4000); + + nodeWasFound = true; + break; + } + } + + if (!nodeWasFound) { + logger.debug("set dimming from platform", "unable to find tbname", tbname); + } + } + else { + instance.send(SEND_TO.debug, "undefined command " + command); + logger.debug("undefined command", command); + } + + return; + } + 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++) { + let node = keys[i]; + if (tbname == nodesData[node].tbname) { + + 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"); + + //profil úspešne prijatý pre node č. xx + sendNotification("Cmd-mngr", tbname, "dimming_profile_was_processed_for_node", { node: node }, profile, SEND_TO.tb, instance); + + nodesData[node].processed = false; + nodesData[node].profile = profile; + + processNodeProfile(node); + }); + }); + } + } + } + else { + + instance.send(SEND_TO.debug, "unknown method " + method); + logger.debug("unknown method", method); + + return; + } + } + + //nastav profil linie z platformy + 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") { + + 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++) { + let line = keys[i]; + if (tbname == relaysData[line].tbname) { + //zmazeme tasky + 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) { + + //update profile + logger.debug("worksys - update relay profile done:", profile); + instance.send(SEND_TO.debug, "worksys - update relay profile done"); + + relaysData[line].profile = profile; + + loadRelaysData(line) + logger.debug("loadRelaysData DONE for line", line); + + buildTasks({ processLineProfiles: true, line: line }); + + sendNotification("Cmd-mngr: set profile from worksys", tbname, "switching_profile_was_processed_for_line", { line: line }, profile, SEND_TO.tb, instance); + }); + }); + break; + } + } + } + else if (method == "set_command") { + let value = data.params.payload.value; + + 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; + + 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"); + if (line != 0) reportToSend["contactor"]["off"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + else { + turnLine("on", line, "command received from platform"); + if (line != 0) reportToSend["contactor"]["on"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + } + } + else { + instance.send(SEND_TO.debug, "undefined method " + method); + logger.debug("undefined method", method); + } + + return; + } + else { + instance.send(SEND_TO.debug, "UNKNOW entity_type " + entity_type); + logger.debug("UNKNOW entity_type", entity_type); + } + return; + } + + //terminal + if (!rsPort.isOpen) await rsPort.open(); + + let params = flowdata.data.body; + if (params == undefined) { + //logger.debug("Cmd-mngr: flowdata.data.body is undefined"); + return; + } + + params.priority = PRIORITY_TYPES.terminal; + params.type = "cmd-terminal"; + params.tbname = ""; + params.timestamp = PRIORITY_TYPES.terminal; + params.addMinutesToTimestamp = 0;// do not repeat task!!! + params.debug = true; + + let timestamp = Date.now(); + params.refFlowdataKey = timestamp; + //params.refFlowdata = flowdata; + //refFlowdata = flowdata; + + //console.log("flowdata", flowdata); + + cleanUpRefFlowdataObj(); + + refFlowdataObj[timestamp] = flowdata; + + //fix + //params.address = params.adress; + logger.debug("received from terminal", params); + logger.debug("date/time:", new Date()); + logger.debug("tasks length:", tasks.length); + + //tasks = []; + + //add to tasks + tasks.push(params); + + } + } + }) + + + //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) + } + + + /** + * 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; + + RESTBuilder.make(function(builder) { + + if (!builder) return; + + builder.method('GET'); + builder.url('http://192.168.252.2:8004/gettime?projects_id=1'); + + builder.callback(function(err, response, output) { + + 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); + } + + }); + } + + } 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); + + } else { + //console.log("Read-only", stdout); + + 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]: [ + { + "ts": date, + "values": values + } + ] + } + + tbHandler.sendToTb(dataToTb, instance); + } + + + function calculateDuskDawn(date, line, duskOffset = 0, dawnOffset = 0) { + + if (date === undefined) date = new Date(); + + 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); + } + + //if(profile.dawn_lux_sensor == false) + { + if (profile.hasOwnProperty("dawn_astro_clock_offset")) dawn_astro_clock_offset = parseInt(profile.dawn_astro_clock_offset); + } + + } + + } catch (error) { + if (profilestr != "") { + logger.debug(profilestr); + logger.debug(error); + } + } + + 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; + } + + //Dimming, CCT + else if (register == 1) { + let brightness = 0; + let dimming = byte0; + if (dimming > 128) { + //dimming = -128; + brightness = dimming - 128; + } + + //cct + //Ak Byte3 == 1: CCT = (Byte2*256)+Byte1 + let cct; + if (byte3 == 1) cct = byte2 * 256 + byte1; + else cct = bytesToInt(bytes.slice(0, 3)); + + //cct podla auditu + + values["dimming"] = brightness; + return values; + } + + // + else if (register == 4) { + values["master_node_version"] = bytes[1] + "." + bytes[2]; + //logger.debug("FW Version", register, bytes); + } + + //Napätie + else if (register == 74) { + let voltage = (bytesToInt(bytes) * 0.1).toFixed(1); + values["voltage"] = Number(voltage); + } + + //Prúd + else if (register == 75) { + let current = bytesToInt(bytes); + values["current"] = current; + } + + //výkon + else if (register == 76) { + let power = (bytesToInt(bytes) * 0.1).toFixed(2); + values["power"] = Number(power); + } + + //účinník + else if (register == 77) { + let power_factor = Math.cos(bytesToInt(bytes) * 0.1 * (Math.PI / 180)).toFixed(2); + values["power_factor"] = Number(power_factor); + } + + //frekvencia + else if (register == 78) { + let frequency = (bytesToInt(bytes) * 0.1).toFixed(2); + values["frequency"] = Number(frequency); + } + + //energia + else if (register == 79) { + let energy = bytesToInt(bytes); + values["energy"] = energy / 1000; //energia v kWh -> delit 1000 + } + + //doba života + else if (register == 80) { + let lifetime = (bytesToInt(bytes) / 60).toFixed(2); + values["lifetime"] = Number(lifetime); + } + + //nastavenie profilu + else if (register == 8) { + let time_schedule_settings = bytesToInt(bytes); + values["time_schedule_settings"] = time_schedule_settings; + } + + //naklon - nateraz sa z nodu nevycitava! kvoli problemom s accelerometrom a vracanymi hodnotami, posielame temp a x y z vo funkcii accelerometerData() + else if (register == 84) { + values["temperature"] = byte3 >= 128 ? (byte3 - 128) * (-1) : byte3; + values["inclination_x"] = byte2 >= 128 ? (byte2 - 128) * (-1) : byte2; + values["inclination_y"] = byte1 >= 128 ? (byte1 - 128) * (-1) : byte1; + values["inclination_z"] = byte0 >= 128 ? (byte0 - 128) * (-1) : byte0; + } + + //FW verzia nodu + else if (register == 89) { + //formát: "Byte3: Byte2.Byte1 (Byte0)" + values["fw_version"] = byte3 + ":" + byte2 + "." + byte1 + "(" + byte0 + ")"; + } + + else if (register == 87 || register == 6 || register == 7) { + var d = new Date(); + d.setHours(byte3, byte2, 0, 0); + let timestamp = d.getTime(); + + //aktuálny čas + if (register == 87) values["actual_time"] = timestamp; + //čas súmraku + else if (register == 6) values["dusk_time"] = timestamp; + //čas úsvitu + else if (register == 7) values["dawn_time"] = timestamp; + } + + 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; + + } + + + function getObjectByTbValue(object, tbname) { + return object[Object.keys(object).find(key => object[key].tbname === tbname)]; + } + + + function isObject(item) { + return (typeof item === "object" && !Array.isArray(item) && item !== null); + } + + + // we fake data, that should be received from accelerometer, as they are a bit unreliable. (temperature, x,y,z) + function accelerometerData() { + + if (temperatureInSenica === null) return; + + //clone nodesData and relaysData objects + let nodesData_clone = JSON.parse(JSON.stringify(nodesData)); + let relaysData_clone = JSON.parse(JSON.stringify(relaysData)); + + for (const key in relaysData_clone) { + + const lineData = relaysData_clone[key]; + const lineNumber = lineData.line; + const contactor = lineData.contactor; + + if (lineNumber === 0) continue; + + if (contactor === 1) { + + let date = Date.now(); + + Object.keys(nodesData_clone).forEach((node, index) => { + + setTimeout(function() { + + if (nodesData_clone[node].line === lineNumber) { + + // NOTE: if status of luminaire is NOK or OFFLINE, we do not send data; + let status = nodesData_clone[node].status; + if (status === "OFFLINE" || !status) return; + + let x = null; + if (naklony.hasOwnProperty(node)) x = naklony[node].naklon; + if (x === null) x = 0; + + sendTelemetry({ temperature: Math.round(temperatureInSenica + 10 + Math.floor(Math.random() * 3)), inclination_x: x, inclination_y: 0, inclination_z: 0 }, nodesData_clone[node].tbname, date); + } + + }, (index + 1) * 500); + }) + + } + } + } + + +} // end of instance.export + diff --git a/RVO22/flow/code.js b/RVO22/flow/code.js new file mode 100755 index 0000000..63b31bf --- /dev/null +++ b/RVO22/flow/code.js @@ -0,0 +1,90 @@ +exports.id = 'code'; +exports.title = 'Code'; +exports.group = 'Common'; +exports.color = '#656D78'; +exports.input = true; +exports.output = 1; +exports.author = 'Peter Širka'; +exports.icon = 'code'; +exports.version = '1.2.0'; +exports.options = { outputs: 1, code: 'send(0, value);', keepmessage: true }; + +exports.html = `
+
+
+
@(Number of outputs)
+
@(Minimum is 1)
+
+
+
@(Code)
+
@(Keep message instance)
+
+`; + +exports.readme = `# Code + +This component executes custom JavaScript code as it is and it doesn't contain any secure scope. + +\`\`\`javascript +// value {Object} contains received data +// send(outputIndex, newValue) sends a new value +// error(value) sends an error +// instance {Object} a current component instance +// flowdata {Object} a current flowdata +// repository {Object} a current repository of flowdata +// Example: + +// send() can be execute multiple times +send(0, value); +\`\`\``; + +exports.install = function(instance) { + + var fn; + + instance.on('data', function(response) { + if (fn) { + try { + fn(response.data, instance, response, instance.options, response.repository, require); + } catch (e) { + response.data = e; + instance.throw(response); + } + } + }); + + instance.reconfigure = function() { + try { + if (instance.options.code) { + instance.status(''); + var code = 'var send = function(index, value) { if (options.keepmessage) { flowdata.data = value; instance.send2(index, flowdata); } else instance.send2(index, value);}; var error = function(err) { instance.throw(err); }; ' + instance.options.code; + fn = new Function('value', 'instance', 'flowdata', 'options', 'repository', 'require', code); + } else { + instance.status('Not configured', 'red'); + fn = null; + } + } catch (e) { + fn = null; + instance.error('Code: ' + e.message); + } + }; + + instance.on('options', instance.reconfigure); + instance.reconfigure(); +}; \ No newline at end of file diff --git a/RVO22/flow/comment.js b/RVO22/flow/comment.js new file mode 100755 index 0000000..1e0cd13 --- /dev/null +++ b/RVO22/flow/comment.js @@ -0,0 +1,11 @@ +exports.id = 'comment'; +exports.title = 'Comment'; +exports.group = 'Common'; +exports.color = '#704cff'; +exports.author = 'Martin Smola'; +exports.icon = 'comment'; +exports.traffic = false; +exports.version = '1.0.0'; +exports.readme = '# Comment'; + +exports.install = function() {}; diff --git a/RVO22/flow/count.js b/RVO22/flow/count.js new file mode 100755 index 0000000..fa92ee9 --- /dev/null +++ b/RVO22/flow/count.js @@ -0,0 +1,60 @@ +exports.id = 'count'; +exports.title = 'Count'; +exports.version = '1.0.1'; +exports.author = 'John Graves'; +exports.color = '#656D78'; +exports.icon = 'plus-square'; +exports.input = 2; +exports.output = 1; +exports.options = { increment: 1, initialvalue: 1 }; +exports.readme = `# Counter + +Counter Number of times called.`; + +exports.html = `
+
@(Initial Value)
+
@(Increment)
+

Example Video

+
`; + +exports.readme = `# Count + +This component counts the number of messages received. + +__Response:__ + +Integer value based on the initial value and increment settings. + +__Arguments:__ +- Initial Value: What number should be output on the receipt of the first message. +- Increment: What should the increment be for each following message received.`; + +exports.install = function(instance) { + + var count = 0; + var initialCall = true; + + instance.on('data', function(flowdata) { + var index = flowdata.index; + if (index) { + instance.debug('Reset Count.'); + count = instance.options.initialvalue; + initialCall = true; + } else { + // If this is the first time, set the value to 'initial value' + if(initialCall) { + initialCall = false; + count = instance.options.initialvalue; + } else + count = count+instance.options.increment; + instance.status('Count:' + count); + instance.send2(count); + } + }); + + instance.on('options', function() { + count = instance.options.initialvalue; + initialCall = true; + }); + +}; diff --git a/RVO22/flow/db_connector.js b/RVO22/flow/db_connector.js new file mode 100755 index 0000000..65ee94b --- /dev/null +++ b/RVO22/flow/db_connector.js @@ -0,0 +1,286 @@ +exports.id = 'db_connector'; +exports.title = 'DbConnector'; +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.html = `
+
+
+
DbConnector
+
+
+
`; + +exports.readme = `# read/write data to tables`; + +const instanceSendTo = { + debug: 0, + http_response: 1, +} + +const { promisifyBuilder, makeMapFromDbResult } = require('./helper/db_helper.js'); + +function extractWhereParams(params) +{ + let name = params[0]; + let operator = '='; + let value = params[1]; + + if(params.length == 3) + { + operator = params[1]; + value = params[2]; + } + + return {name: name, operator: operator, value: value}; +} + +exports.install = function(instance) { + + let refFlowdata = null;//holds reference to httprequest flowdata + + instance.on("close", () => { + + }) + + + instance.on("data", async function(flowdata) { + + let params = flowdata.data.body; + console.log("DbConnector", params); + + refFlowdata = flowdata; + + if(refFlowdata != undefined) + { + //make http response + let responseObj = {}; + responseObj["type"] = "SUCESS"; + + try{ + + let table = params.table; + let action = params.action; + + + if(params.data != undefined) + { + let className = params.data.className; + + if(className == "SqlQueryBuilder") + { + let type = params.data.type; + + console.log("SqlQueryBuilder---->", params.data); + + if(type == "SELECT") + { + let table = params.data.queryData.tables[0].table; + + const db = TABLE(table); + var builder = db.find(); + + let result = await promisifyBuilder(builder); + + let response = {}; + response["result"] = result; + response["success"] = true; + + responseObj["data"] = response; + + //console.log(responseObj); + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + } + + return; + } + } + + + console.log("db_connector---->", table, action); + + //actions: read, replace, insert, delete, update... + + if(action == "read") + { + const db = TABLE(params.table); + + //where builder.where('age', '<', 15); + //builder.where('id', 3403); + + var builder = db.find(); + + //https://docs.totaljs.com/latest/en.html#api~DatabaseBuilder~builder.where + if(params.hasOwnProperty("where")) + { + //optionalCan contain "=", "<=", "<", ">=", ">". + //Default value: '=' + + //1.["production_line", 1] + //2. ["or", ["production_line", 1], ["production_line", 2], "end"] + + if (Array.isArray(params.where)) { + + let multipleConditions = false; + + if(params.where[0] == "or") multipleConditions = true; + if (Array.isArray(params.where[0])) multipleConditions = true; + + if(multipleConditions) + { + + for(var i = 0; i < params.where.length; i++) + { + const item = params.where[i]; + + if(item === "or") builder.or(); + + if (Array.isArray(item)) + { + const { name, operator, value } = extractWhereParams(item); + builder.where(name, operator, value); + } + + if(item === "end") builder.end(); + + } + + } + else + { + const { name, operator, value } = extractWhereParams(params.where); + builder.where(name, operator, value); + } + + } + + /* + if(params.where.length >=2 ) + { + let name = params.where[0]; + let operator = '='; + let value = params.where[1]; + + if(params.where.length == 3) + { + operator = params.where[1]; + value = params.where[2]; + } + + builder.where(name, operator, value); + } + */ + } + + if(params.hasOwnProperty("between")) + { + builder.between(params.between[0], params.between[1], params.between[2]); + } + + let response = await promisifyBuilder(builder); + responseObj["data"] = response; + + //console.log(responseObj); + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + + return; + } + + if(action == "delete") + { + + } + + + if(action == "update") + { + //! data receiving from terminal (params) + // { + // hostname: 'localhost', + // table: 'settings', + // action: 'update', + // body: { + // rvo_name: 'terrrr', + // lang: 'en', + // temperature_adress: '28.427B45920702', + // latitude: 48.70826502, + // longitude: 17.28455203, + // mqtt_host: '192.168.252.4', + // mqtt_clientid: 'showroom_test_panel_led', + // mqtt_username: 'xmRd6RJxW53WZe4vMFLU', + // mqtt_port: 1883, + // maintanace_mode: false + // } + // } + const tableToModify = TABLE(params.table); + const newValues = params.body; + + tableToModify.modify(newValues).make(function(builder) { + + builder.callback(function(err, response) { + + if(!err) + { + responseObj["data"] = response; + responseObj["tableUpdated"] = true; + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + } + }); + }); + + } + + if(action == "replace") + { + //truncate table + const db = TABLE(params.table); + var builder = db.remove(); + db.clean(); + + //insert data + let data = params.data; + + for(let i = 0; i < data.length; i++) + { + //console.log(data[i]); + db.insert(data[i]); + } + + console.log("insert done"); + + let responseObj = {}; + responseObj["type"] = "SUCESS"; + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + + + } + + + + } catch (error) { + //console.log(error); + responseObj["type"] = "ERROR"; + responseObj["message"] = error; + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + } + } + }) +} + + diff --git a/RVO22/flow/db_init.js b/RVO22/flow/db_init.js new file mode 100755 index 0000000..b399878 --- /dev/null +++ b/RVO22/flow/db_init.js @@ -0,0 +1,113 @@ +exports.id = 'db_init'; +exports.title = 'DB Initialization'; +exports.group = 'Worksys'; +exports.color = '#888600'; +exports.version = '1.0.2'; +exports.icon = 'sign-out'; +exports.output = 2; + +exports.readme = ` + # DB initialization +`; + +const { promisifyBuilder, makeMapFromDbResult } = require('./helper/db_helper.js'); +const { initNotification } = require('./helper/notification_reporter'); +const errorHandler = require('./helper/ErrorToServiceHandler'); +const total_energy = require('../databases/total_energy'); + +const SEND_TO = { + db_init: 0, + infoSender: 1 +}; + + +exports.install = async function(instance) { + const dbNodes = TABLE("nodes"); + const dbRelays = TABLE("relays"); + const dbSettings = TABLE("settings"); + 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 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.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"]; + Object.keys(dbs.nodesData).forEach(node => dbs.nodesData[node].readout = {}) + + let rvo_number = responseSettings[0]["rvo_name"].match(/\D+(\d{1,2})_/)[1]; + + dbs.settings = { + edge_fw_version: "2025-10-08", //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"], + phases: responseSettings[0]["phases"], + cloud_topic: responseSettings[0]["cloud_topic"], + has_main_switch: responseSettings[0]["has_main_switch"], + daily_report: responseSettings[0]["daily_report"], + send_changed_node_numbers: responseSettings[0]["send_changed_node_numbers"], + rvo_number: rvo_number, + + //dynamic values + masterNodeIsResponding: true, //cmd_manager + maintenance_mode: false, + } + + + dbs.settings.energy_to_switch_lamps = total_energy[rvo_number]; + if (dbs.settings.energy_to_switch_lamps === undefined) console.log('=============== db_init.js: energy_to_switch_lamps is undefined'); + + FLOW.dbLoaded = true; + errorHandler.setProjectId(dbs.settings.project_id); + initNotification(); + + //APP START - send to data services + const toService = { + id: dbs.settings.project_id, + name: dbs.settings.rvo_name, + fw_version: dbs.settings.edge_fw_version, + startdate: new Date().toISOString().slice(0, 19).replace('T', ' '), + js_error: "", + error_message: "" + }; + + instance.send(SEND_TO.infoSender, toService); + console.log("----------------> START - message send to service", toService); + + setTimeout(() => { + console.log("DB_INIT - data loaded"); + instance.send(SEND_TO.db_init, "_") + }, 5000) + +}; + diff --git a/RVO22/flow/debug.js b/RVO22/flow/debug.js new file mode 100755 index 0000000..00cb259 --- /dev/null +++ b/RVO22/flow/debug.js @@ -0,0 +1,100 @@ +exports.id = 'debug'; +exports.title = 'Debug'; +exports.author = 'Peter Širka'; +exports.color = '#967ADC'; +exports.click = true; +exports.input = true; +exports.icon = 'bug'; +exports.version = '2.0.4'; +exports.options = { enabled: true, repository: false, type: 'data' }; +exports.readme = `# Debug + +Prints data to the debug tab.`; + +exports.html = `
+
+
+
@(Output type)
+
@(Path to the property (leave empty to show the whole data object))
+
@(A group name)
+
@(Enabled)
+
+
+
`; + +exports.install = function(instance) { + + instance.on('data', function(response) { + if (instance.options.enabled) { + + var opt = instance.options; + var rep = response.repository; + var val = response.data; + var id = response.id; + + switch (instance.options.type){ + case 'both': + var data = {}; + data.repository = rep; + data.data = val instanceof Error ? { error: val.message, stack: val.stack } : val; + instance.debug(safeparse(opt.property ? U.get(data, opt.property) : data), undefined, opt.group, id); + break; + case 'repository': + instance.debug(safeparse(opt.property ? U.get(rep, opt.property) : rep), undefined, opt.group, id); + break; + case 'data': + default: + if (val instanceof Error) + instance.debug({ error: val.message, stack: val.stack }, undefined, opt.group, id); + else + instance.debug(safeparse(opt.property ? U.get(val, opt.property) : val), undefined, opt.group, id); + break; + } + } + }); + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + instance.save(); + }); + + instance.on('options', function() { + instance.custom.status(); + }); + + instance.custom.status = function() { + instance.status(instance.options.enabled ? 'Enabled' : 'Disabled'); + }; + + instance.custom.status(); + + function safeparse(o) { + + if (o instanceof Buffer) + return o; + + if (o === undefined) + return 'undefined'; + + if (o === null) + return 'null'; + + var cache = []; + var str = JSON.stringify(o, function(key, value) { + if (typeof value === 'object' && value !== null) { + if (cache.indexOf(value) !== -1) { + try { + return JSON.parse(JSON.stringify(value)); + } catch (error) { + return; + } + } + cache.push(value); + } + return value; + }); + cache = null; + return JSON.parse(str); + } +}; diff --git a/RVO22/flow/designer.json b/RVO22/flow/designer.json new file mode 100755 index 0000000..580f5a3 --- /dev/null +++ b/RVO22/flow/designer.json @@ -0,0 +1,3102 @@ +{ + "tabs": [ + { + "name": "MAIN PUSH", + "linker": "main-push", + "id": "1612772287426", + "index": 0 + }, + { + "name": "CMD manager", + "linker": "cmd-manager", + "id": "1615551125555", + "index": 1 + }, + { + "name": "Devices", + "linker": "devices", + "id": "1611921777196", + "index": 2 + } + ], + "components": [ + { + "id": "1611951142547", + "component": "debug", + "tab": "1611921777196", + "name": "ERROR", + "x": 598, + "y": 60, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#DA4453", + "notes": "" + }, + { + "id": "1612776786008", + "component": "wsmqttpublish", + "tab": "1612772287426", + "name": "WS MQTT publish", + "x": 281.75, + "y": 174, + "connections": { + "0": [ + { + "index": "0", + "id": "1615551060773" + } + ], + "1": [ + { + "index": "0", + "id": "1618300858252" + }, + { + "index": "0", + "id": "1618558465485" + } + ], + "2": [ + { + "index": "0", + "id": "1634303685503" + } + ], + "3": [ + { + "index": "0", + "id": "1731068754606" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Connected", + "color": "green" + }, + "options": { + "username": "", + "clientid": "", + "port": "1883", + "host": "" + }, + "color": "#888600", + "notes": "" + }, + { + "id": "1612778461252", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "tb-push", + "x": 72.75, + "y": 328, + "connections": { + "0": [ + { + "index": "0", + "id": "1612783322136" + }, + { + "index": "1", + "id": "1612776786008" + }, + { + "index": "0", + "id": "1731068754606" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1612783322136", + "component": "debug", + "tab": "1612772287426", + "name": "to TB", + "x": 283.75, + "y": 324, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615551060773", + "component": "debug", + "tab": "1612772287426", + "name": "errors from MQTT Broker", + "x": 594, + "y": 57, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#DA4453", + "notes": "" + }, + { + "id": "1615563373927", + "component": "debug", + "tab": "1615551125555", + "name": "Debug", + "x": 755, + "y": 155, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#DA4453", + "notes": "" + }, + { + "id": "1615566865233", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "tb-push", + "x": 755, + "y": 248, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1615798582262", + "component": "debug", + "tab": "1615551125555", + "name": "CMD_debug", + "x": 755, + "y": 346, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615802995322", + "component": "debug", + "tab": "1611921777196", + "name": "Debug", + "x": 596.8833312988281, + "y": 566.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Disabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": false + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615809128443", + "component": "debug", + "tab": "1611921777196", + "name": "tempToTb", + "x": 595.8833312988281, + "y": 658.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615809595184", + "component": "virtualwireout", + "tab": "1611921777196", + "name": "tb-push", + "x": 597.8833312988281, + "y": 377.25, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1616165795916", + "component": "httproute", + "tab": "1615551125555", + "name": "POST /terminal", + "x": 135, + "y": 547, + "connections": { + "0": [ + { + "index": "0", + "id": "1684060205000" + }, + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Listening", + "color": "green" + }, + "options": { + "timeout": 10, + "cachepolicy": 0, + "cacheexpire": "5 minutes", + "size": 5, + "url": "/terminal", + "method": "POST", + "name": "", + "flags": [ + "id:1616165795916", + "post", + 10000 + ], + "emptyresponse": false + }, + "color": "#5D9CEC", + "notes": "### Configuration\n\n- __POST /terminal__\n- flags: \n- maximum request data length: __5 kB__\n- empty response: __false__\n- cache policy: __no cache__\n- cache expire: __5 minutes__", + "cloning": false + }, + { + "id": "1616165824813", + "component": "httpresponse", + "tab": "1615551125555", + "name": "HTTP Response", + "x": 753, + "y": 423, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "json" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1617104731852", + "component": "debug", + "tab": "1615551125555", + "name": "DIDO_Debug", + "x": 669, + "y": 1040, + "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": "turnOff line", + "x": 133, + "y": 1161, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "object", + "data": "{line: 3, command: \"turnOff\", force: true}" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1617115013095", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "tb-push", + "x": 669, + "y": 1150, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1617284749681", + "component": "trigger", + "tab": "1615551125555", + "name": "update profile / node", + "x": 112, + "y": 208, + "connections": { + "0": [ + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "data": "profile_nodes", + "datatype": "string" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1618235171399", + "component": "trigger", + "tab": "1615551125555", + "name": "tun tasks", + "x": 184, + "y": 279, + "connections": { + "0": [ + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "data": "run" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1618300858252", + "component": "debug", + "tab": "1612772287426", + "name": "wsmqtt-exit1", + "x": 597.8833312988281, + "y": 149, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1618393583970", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "to-cmd-manager", + "x": 668.8833312988281, + "y": 1269, + "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": 132.88333129882812, + "y": 367, + "connections": { + "0": [ + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "platform-rpc-call", + "color": "gray" + }, + "options": { + "wirename": "platform-rpc-call" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1618393759854", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "cmd_to_dido", + "x": 119.88333129882812, + "y": 1007, + "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": 752.8833312988281, + "y": 527, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "cmd_to_dido", + "color": "gray" + }, + "options": { + "wirename": "cmd_to_dido" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1618558465485", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "platform-rpc-call", + "x": 597.8833312988281, + "y": 247, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "platform-rpc-call", + "color": "gray" + }, + "options": { + "wirename": "platform-rpc-call" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1618572059773", + "component": "trigger", + "tab": "1615551125555", + "name": "turnOn line", + "x": 132, + "y": 1085, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "data": "{line: 1, command: \"turnOn\", force: true}", + "datatype": "object" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1619515097737", + "component": "cmd_manager", + "tab": "1615551125555", + "name": "CMD Manager", + "x": 452.1091003417969, + "y": 341.05455017089844, + "connections": { + "0": [ + { + "index": "0", + "id": "1615563373927" + } + ], + "1": [ + { + "index": "0", + "id": "1615566865233" + }, + { + "index": "0", + "id": "1615798582262" + } + ], + "2": [ + { + "index": "0", + "id": "1616165824813" + } + ], + "3": [ + { + "index": "0", + "id": "1618393827655" + } + ], + "4": [ + { + "index": "0", + "id": "1635936391935" + } + ], + "5": [ + { + "index": "0", + "id": "1757006030239" + }, + { + "index": "0", + "id": "1757006060377" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1619605019281", + "component": "httproute", + "tab": "1615551125555", + "name": "GET db", + "x": 173, + "y": 653, + "connections": { + "0": [ + { + "index": "0", + "id": "1684060205000" + }, + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Listening", + "color": "green" + }, + "options": { + "timeout": 5, + "cachepolicy": 0, + "cacheexpire": "5 minutes", + "size": 5, + "url": "/db", + "method": "GET", + "name": "", + "flags": [ + "id:1619605019281", + "get", + 5000 + ] + }, + "color": "#5D9CEC", + "notes": "### Configuration\n\n- __GET /db__\n- flags: undefined\n- maximum request data length: __5 kB__\n- empty response: __undefined__\n- cache policy: __no cache__\n- cache expire: __5 minutes__", + "cloning": false + }, + { + "id": "1619784672383", + "component": "trigger", + "tab": "1615551125555", + "name": "turnOnAlarm", + "x": 120, + "y": 1234, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "object", + "data": "{command: \"turnOnAlarm\"}" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1619784812964", + "component": "trigger", + "tab": "1615551125555", + "name": "turnOffAlarm", + "x": 118, + "y": 1307, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "object", + "data": "{command: \"turnOffAlarm\"}" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1621340721628", + "component": "virtualwireout", + "tab": "1611921777196", + "name": "modbus_to_dido", + "x": 599, + "y": 471, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "modbus_to_dido", + "color": "gray" + }, + "options": { + "wirename": "modbus_to_dido" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1622640022885", + "component": "httproute", + "tab": "1615551125555", + "name": "POST /db_connector", + "x": 98, + "y": 1586, + "connections": { + "0": [ + { + "index": "0", + "id": "1622640073521" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Listening", + "color": "green" + }, + "options": { + "timeout": 5, + "cachepolicy": 0, + "cacheexpire": "5 minutes", + "size": 5, + "url": "/db_connector", + "method": "POST", + "flags": [ + "id:1622640022885", + "post", + 5000 + ] + }, + "color": "#5D9CEC", + "notes": "### Configuration\n\n- __POST /db_connector__\n- flags: \n- maximum request data length: __5 kB__\n- empty response: __undefined__\n- cache policy: __no cache__\n- cache expire: __5 minutes__", + "cloning": false + }, + { + "id": "1622640073521", + "component": "db_connector", + "tab": "1615551125555", + "name": "DbConnector", + "x": 372, + "y": 1572, + "connections": { + "1": [ + { + "index": "0", + "id": "1622641420685" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "edge": "undefined" + }, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1622641420685", + "component": "httpresponse", + "tab": "1615551125555", + "name": "HTTP Response", + "x": 596, + "y": 1586, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1634303504177", + "component": "monitormemory", + "tab": "1612772287426", + "name": "RAM", + "x": 69.88333129882812, + "y": 888.5, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465281992" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "858.88 MB / 985.68 MB", + "color": "gray" + }, + "options": { + "enabled": true, + "interval": 30000 + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1634303533779", + "component": "monitordisk", + "tab": "1612772287426", + "name": "disk", + "x": 70.88333129882812, + "y": 982.5, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465821120" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "5.78 GB / 7.26 GB", + "color": "gray" + }, + "options": { + "enabled": true, + "path": "/", + "interval": 30000 + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1634303595494", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "send-to-services", + "x": 51.883331298828125, + "y": 1400.5, + "connections": { + "0": [ + { + "index": "0", + "id": "1634463186563" + }, + { + "index": "1", + "id": "1634488120710" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1634303602169", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "send-to-services", + "x": 426.8833312988281, + "y": 878.5, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1634303685503", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "send-to-services", + "x": 600.8833312988281, + "y": 341.5, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1634303743260", + "component": "httprequest", + "tab": "1612772287426", + "name": "192.168.252.2:8004/sentmessage", + "reference": "", + "x": 506.8833312988281, + "y": 1331.7333374023438, + "connections": { + "0": [ + { + "index": "0", + "id": "1635327431236" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "url": "http://192.168.252.2:8004/sentmessage", + "method": "POST", + "stringify": "json" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1634463186563", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 305.75, + "y": 1442, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634464580289", + "component": "code", + "tab": "1612772287426", + "name": "Code", + "x": 245, + "y": 787, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465243324" + }, + { + "index": "0", + "id": "1634303602169" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "keepmessage": true, + "code": "let response = {};\nresponse.cpu = value.cpu;\nresponse.uptime = value.uptime;\n\nsend(0, response);", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1634465243324", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 428, + "y": 784, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634465281992", + "component": "code", + "tab": "1612772287426", + "name": "Code", + "x": 245, + "y": 884, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465338103" + }, + { + "index": "0", + "id": "1634303602169" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "keepmessage": true, + "code": "value.sender = \"ram\";\n\nlet response = {};\n\nresponse.memory_total = Math.round(value.total / (1024 ** 2));\nresponse.memory_free = Math.round(value.free / (1024 ** 2));\nresponse.memory_used = Math.round(value.used / (1024 ** 2));\n\nsend(0, response);", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1634465338103", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 429, + "y": 976, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634465821120", + "component": "code", + "tab": "1612772287426", + "name": "Code", + "x": 245, + "y": 978, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465892500" + }, + { + "index": "0", + "id": "1634303602169" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "keepmessage": true, + "code": "value.sender = \"hdd\";\n\nlet response = {};\n\nresponse.hdd_total = Math.round(value.total / (1024 ** 2));\nresponse.hdd_free = Math.round(value.free / (1024 ** 2));\nresponse.hdd_used = Math.round(value.used / (1024 ** 2));\n\nsend(0, response);", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1634465892500", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 432, + "y": 1068, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634484067516", + "component": "debug", + "tab": "1612772287426", + "name": "Send info", + "x": 513, + "y": 1441, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634488120710", + "component": "infosender", + "tab": "1612772287426", + "name": "Info sender", + "x": 301, + "y": 1336, + "connections": { + "0": [ + { + "index": "0", + "id": "1634484067516" + }, + { + "index": "0", + "id": "1634303743260" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "edge": "undefined" + }, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1635327431236", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 837.8833312988281, + "y": 1325.5, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1635936391935", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "send-to-services", + "x": 753, + "y": 623, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1637069803394", + "component": "monitorconsumption", + "tab": "1612772287426", + "name": "CPU", + "x": 69, + "y": 791, + "connections": { + "0": [ + { + "index": "0", + "id": "1634464580289" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "49.2% / 69.91 MB", + "color": "gray" + }, + "options": { + "monitorfiles": true, + "monitorconnections": true, + "monitorsize": true, + "monitorconsumption": true, + "enabled": true, + "interval": 30000 + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1683664161036", + "component": "debug", + "tab": "1615551125555", + "name": "CMDtoDIDO", + "x": 392, + "y": 1012, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1683981346282", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "from-dido-controller", + "x": 112, + "y": 459, + "connections": { + "0": [ + { + "index": "0", + "id": "1684055037116" + }, + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "from-dido-controller", + "color": "gray" + }, + "options": { + "wirename": "from-dido-controller" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1684055037116", + "component": "debug", + "tab": "1615551125555", + "name": "from dido to cmd", + "x": 451, + "y": 532, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1684060205000", + "component": "debug", + "tab": "1615551125555", + "name": "HTTP routes", + "x": 450, + "y": 639, + "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": "MDBToDido", + "x": 598, + "y": 147, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1699963668903", + "component": "dido_controller", + "tab": "1615551125555", + "name": "DIDO_Controller", + "x": 397, + "y": 1131, + "connections": { + "0": [ + { + "index": "0", + "id": "1617104731852" + } + ], + "1": [ + { + "index": "0", + "id": "1617104731852" + }, + { + "index": "0", + "id": "1617115013095" + } + ], + "2": [ + { + "index": "0", + "id": "1618393583970" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "edge": "undefined" + }, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1699964678894", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "modbus_to_dido", + "x": 96, + "y": 924, + "connections": { + "0": [ + { + "index": "0", + "id": "1699963668903" + }, + { + "index": "0", + "id": "1699964793925" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "modbus_to_dido", + "color": "gray" + }, + "options": { + "wirename": "modbus_to_dido" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1699964793925", + "component": "debug", + "tab": "1615551125555", + "name": "modbusToDido", + "x": 388, + "y": 920, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1699965957410", + "component": "modbus_reader", + "tab": "1611921777196", + "name": "Modbus reader", + "x": 232, + "y": 175, + "connections": { + "0": [ + { + "index": "0", + "id": "1611951142547" + } + ], + "1": [ + { + "index": "0", + "id": "1621340721628" + }, + { + "index": "0", + "id": "1684179110403" + }, + { + "index": "0", + "id": "1717441414646" + } + ], + "2": [ + { + "index": "0", + "id": "1615809595184" + }, + { + "index": "0", + "id": "1714752862828" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1700411878636", + "component": "thermometer", + "tab": "1611921777196", + "name": "Thermometer", + "x": 234.75, + "y": 444, + "connections": { + "0": [ + { + "index": "0", + "id": "1615802995322" + } + ], + "1": [ + { + "index": "0", + "id": "1615809595184" + }, + { + "index": "0", + "id": "1615809128443" + } + ], + "2": [ + { + "index": "0", + "id": "1621340721628" + }, + { + "index": "0", + "id": "1732889185927" + }, + { + "index": "0", + "id": "1717441414646" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#5CB36D", + "notes": "" + }, + { + "id": "1714752862828", + "component": "debug", + "tab": "1611921777196", + "name": "MDBToTb", + "x": 766, + "y": 324, + "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": 764.0833282470703, + "y": 222, + "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\telse if(value.status === \"NOK-thermometer\")\n\t{\n\t\tsend(0, {\"thermometer\": \"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\telse if(value.values.hasOwnProperty(\"temperature\"))\n\t{\n\t\tsend(0, {\"thermometer\": \"OK\"});\n\t}\n}", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1717442627834", + "component": "debug", + "tab": "1611921777196", + "name": "modbus service", + "x": 966.0833282470703, + "y": 165, + "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": 968.0833282470703, + "y": 268, + "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": 88.75, + "y": 1685, + "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": 296, + "y": 1671, + "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\", \"Flow has been restarted\", \"Node db has changed\"]", + "types": "[\"emergency\", \"critical\", \"error\", \"alert\"]", + "name": "" + }, + "color": "#30E193", + "notes": "" + }, + { + "id": "1718016073501", + "component": "httprequest", + "tab": "1612772287426", + "name": "http://192.168.252.2:8004/slack", + "x": 495, + "y": 1753, + "connections": { + "0": [ + { + "index": "0", + "id": "1718016086212" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "url": "http://192.168.252.2:8004/slack", + "method": "POST", + "stringify": "json" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1718016086212", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 832, + "y": 1664, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "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": 87, + "y": 1591, + "connections": { + "0": [ + { + "index": "0", + "id": "1718016052341" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "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\": \"\" } } } ] }", + "datatype": "object" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1729855334955", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "platform-rpc-call", + "x": 599.9333343505859, + "y": 541.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "platform-rpc-call", + "color": "gray" + }, + "options": { + "wirename": "platform-rpc-call" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1729855371093", + "component": "debug", + "tab": "1612772287426", + "name": "rpc cloud", + "x": 601.9333343505859, + "y": 440.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1731068658334", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 75.75, + "y": 184, + "connections": { + "0": [ + { + "index": "0", + "id": "1612776786008" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731068754606", + "component": "cloudmqttconnect", + "tab": "1612772287426", + "name": "MQTT to senica-prod01", + "x": 284.75, + "y": 452, + "connections": { + "1": [ + { + "index": "0", + "id": "1729855371093" + }, + { + "index": "0", + "id": "1729855334955" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Connected", + "color": "green" + }, + "options": { + "username": "", + "clientid": "", + "port": "2764", + "host": "192.168.252.2", + "topic": "" + }, + "color": "#888600", + "notes": "" + }, + { + "id": "1731069001548", + "component": "db_init", + "tab": "1612772287426", + "name": "DB Initialization", + "x": 1003.75, + "y": 240.25, + "connections": { + "0": [ + { + "index": "0", + "id": "1731069033416" + } + ], + "1": [ + { + "index": "0", + "id": "1747561603739" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#888600", + "notes": "" + }, + { + "id": "1731069033416", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "db-init", + "x": 1244.75, + "y": 233.25, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069059135", + "component": "showdb", + "tab": "1612772287426", + "name": "Show db data", + "x": 1186.75, + "y": 821.25, + "connections": { + "0": [ + { + "index": "0", + "id": "1731069079243" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#888600", + "notes": "" + }, + { + "id": "1731069079243", + "component": "debug", + "tab": "1612772287426", + "name": "dbData", + "x": 1390.75, + "y": 870.25, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1731069116691", + "component": "trigger", + "tab": "1612772287426", + "name": "settings", + "x": 934.75, + "y": 669.75, + "connections": { + "0": [ + { + "index": "0", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069131637", + "component": "trigger", + "tab": "1612772287426", + "name": "relaysData", + "x": 876.75, + "y": 733.75, + "connections": { + "0": [ + { + "index": "1", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069137374", + "component": "trigger", + "tab": "1612772287426", + "name": "nodesData", + "x": 852.75, + "y": 794.75, + "connections": { + "0": [ + { + "index": "2", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069179846", + "component": "trigger", + "tab": "1612772287426", + "name": "pinsData", + "x": 850.75, + "y": 861.75, + "connections": { + "0": [ + { + "index": "3", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069192937", + "component": "trigger", + "tab": "1612772287426", + "name": "sample data", + "x": 857.75, + "y": 928.75, + "connections": { + "0": [ + { + "index": "4", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069264443", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 63.75, + "y": 1279, + "connections": { + "0": [ + { + "index": "0", + "id": "1634488120710" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069334626", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "db-init", + "x": 172.88333129882812, + "y": 129, + "connections": { + "0": [ + { + "index": "0", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069548145", + "component": "virtualwirein", + "tab": "1611921777196", + "name": "db-init", + "x": 46.75, + "y": 192, + "connections": { + "0": [ + { + "index": "0", + "id": "1699965957410" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069567152", + "component": "virtualwirein", + "tab": "1611921777196", + "name": "db-init", + "x": 44.75, + "y": 465, + "connections": { + "0": [ + { + "index": "0", + "id": "1700411878636" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731070156936", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "db-init", + "x": 126.88333129882812, + "y": 1377, + "connections": { + "0": [ + { + "index": "2", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731234189516", + "component": "trigger", + "tab": "1612772287426", + "name": "monitor.txt", + "x": 882.75, + "y": 991.75, + "connections": { + "0": [ + { + "index": "5", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731234189551", + "component": "trigger", + "tab": "1612772287426", + "name": "err.txt", + "x": 904.75, + "y": 1053.75, + "connections": { + "0": [ + { + "index": "6", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1732700042559", + "component": "nodesdb_change_check", + "tab": "1612772287426", + "name": "Nodes DB change check", + "x": 266.8833312988281, + "y": 1980.2333984375, + "connections": { + "0": [ + { + "index": "0", + "id": "1732700071298" + }, + { + "index": "0", + "id": "1732700642917" + } + ], + "1": [ + { + "index": "0", + "id": "1759958914348" + }, + { + "index": "0", + "id": "1759959003114" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#888600", + "notes": "" + }, + { + "id": "1732700057052", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 76.75, + "y": 1988, + "connections": { + "0": [ + { + "index": "0", + "id": "1732700042559" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1732700071298", + "component": "debug", + "tab": "1612772287426", + "name": "nodesChange", + "x": 571.8833312988281, + "y": 2018.2333984375, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1732700642917", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "tb-push", + "x": 567.8833312988281, + "y": 1933, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1732889185927", + "component": "debug", + "tab": "1611921777196", + "name": "tempToDido", + "x": 594.8833312988281, + "y": 753, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1733574412965", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 72.75, + "y": 474, + "connections": { + "0": [ + { + "index": "1", + "id": "1731068754606" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1747561603739", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "send-to-services", + "x": 1243.8833312988281, + "y": 334.5, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1747562867845", + "component": "comment", + "tab": "1612772287426", + "name": "FLOW STARTING POINT", + "x": 1003.5666656494141, + "y": 178, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#704cff", + "notes": "" + }, + { + "id": "1749211698385", + "component": "trigger", + "tab": "1612772287426", + "name": "deviceStatus", + "x": 911.75, + "y": 1116.75, + "connections": { + "0": [ + { + "index": "7", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1757006030239", + "component": "httprequest", + "tab": "1615551125555", + "name": "192.168.252.2:8015/daily_report", + "x": 756.5666656494141, + "y": 715.4499969482422, + "connections": { + "0": [ + { + "index": "0", + "id": "1757006045804" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "stringify": "json", + "method": "POST", + "url": "http://192.168.252.2:8015/daily_report" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1757006045804", + "component": "debug", + "tab": "1615551125555", + "name": "ddd", + "x": 1091.566665649414, + "y": 711.4499969482422, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1757006060377", + "component": "debug", + "tab": "1615551125555", + "name": "reportDebug", + "x": 749.5666656494141, + "y": 799.4499969482422, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1759958914348", + "component": "httprequest", + "tab": "1612772287426", + "name": "http://192.168.252.2:8015/node_numbers", + "x": 571, + "y": 2111, + "connections": { + "0": [ + { + "index": "0", + "id": "1759958927094" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "stringify": "json", + "method": "POST", + "url": "http://192.168.252.2:8015/node_numbers" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1759958927094", + "component": "debug", + "tab": "1612772287426", + "name": "nodesChangeCloud", + "x": 951.8833312988281, + "y": 2109.2333984375, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1759959003114", + "component": "debug", + "tab": "1612772287426", + "name": "nodeChangeCloud1", + "x": 574, + "y": 2218, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1760020290879", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 84.75, + "y": 1787, + "connections": { + "0": [ + { + "index": "1", + "id": "1718016052341" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + } + ], + "version": 615 +} diff --git a/RVO22/flow/dido_controller.js b/RVO22/flow/dido_controller.js new file mode 100755 index 0000000..d16fb19 --- /dev/null +++ b/RVO22/flow/dido_controller.js @@ -0,0 +1,1486 @@ +exports.id = 'dido_controller'; +exports.title = 'DIDO_Controller'; +exports.version = '2.0.0'; +exports.group = 'Worksys'; +exports.color = '#2134B0'; +exports.input = 3; +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 + +state_of_main_switch - reportovat stav hlaveho istica : 0-> off 1-> on +rotary_switch_state - sem by sa mal reportovat stav vstupov manual a auto pola nasledovnej logiky: Manual = 1 a Auto = 0 -> Manu +Manual = 0 a Auto = 0 -> Off, Manual = 0 a Auto = 1 -> Automatic + +door_condition - pin 6, dverový kontakt -> 1 -> vyreportuje Closed, 0 -> vyreportuje Ope +twilight_sensor - hodnotu, ktoru vracia ten analogovy vstup (17) treba poslat sem ako float number. Zrejme tu potom pridame nejaky koeficient prevodu na luxy + +Na kazdu liniu +state_of_breaker - podla indexu istica sa reportuje jeho stav, teda istic na liniu 1: 0-> off, 1-> on +state_of_contactor - podla indexu stkaca sa reportuje jeho stav, teda stykac 1 na liniu 1: 0-> off, 1-> on +*/ + +const { errLogger, logger, monitor } = require('./helper/logger'); +const SerialPort = require('serialport'); +const WebSocket = require('ws'); +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 errorHandler = require('./helper/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 hasMainSwitch; + +let alarmStatus = "OFF"; + +const SEND_TO = { + debug: 0, + tb: 1, + cmd_manager: 2 +} + + +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 = {}; + let rsPortReceivedData = []; + + //to be able to get proper twilight values + let twilight_sensor_interval = 5;//minutes + let twilight_sensor = []; + const twilight_sensor_array = []; + let twilightError = false; + + monitor.info("DIDO_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-we make it global to see it from outside + FLOW.deviceStatus = { //key is device name: temperature,.... + "state_of_main_switch": "Off", //Hlavny istic (alebo druhy dverovy kontakt) + "rotary_switch_state": "Off", //Prevadzkovy + "door_condition": "closed", //Dverový kontakt + "em": "OK", //elektromer rvo + "temperature": "OK", //templomer + "battery": "OK", //Bateria + "power_supply": "OK", //Zdroj + "master_node": "OK", //MN - GLOBALS.settings.masterNodeIsResponding + "no_voltage": "OK", //GLOBALS.settings.no_voltage - vypadok napatia na faze + "state_of_breaker": {}, //"Off",//Istic + "state_of_contactor": {}, //"Off",//Stykac + "twilight_sensor": "OK" //lux sensor + }; + let deviceStatus = FLOW.deviceStatus; + + + function main() { + + GLOBALS = FLOW.GLOBALS; + SETTINGS = FLOW.GLOBALS.settings; + rvoTbName = SETTINGS.rvoTbName; + pinsData = GLOBALS.pinsData; + relaysData = GLOBALS.relaysData; + + tbHandler = new DataToTbHandler(SEND_TO.tb); + tbHandler.setSender(exports.title); + + controller_type = SETTINGS.controller_type; //"lm" or "unipi" + hasMainSwitch = SETTINGS.has_main_switch; + + if (controller_type == "") controller_type = "lm"; + + 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, "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; + } + } + + //report RVO version relaysData[0].tbname; + let values = {}; + values["edge_fw_version"] = SETTINGS.edge_fw_version; + values["maintenance_mode"] = SETTINGS.maintenance_mode; + + sendTelemetry(values, rvoTbName); + + 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); + } + + + function handleRsPort() { + + if (rsPort) { + rsPort.removeAllListeners(); + rsPort = null; + } + + //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('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) { + if (!err) { + monitor.info(exports.title + "--->Digital in_out has been set (runSyncExec was sucessfull)"); + + turnAlarm("off"); + 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('error', err => { + let message = "Dido: rsPort error: " + err.message; + logger.debug(message); + monitor.info(message); + errorHandler.sendMessageToService(message); + }) + + rsPort.on("close", () => { + let message = "Dido: rsPort closed - reconnecting ..."; + logger.debug(message); + monitor.info(message); + setTimeout(handleRsPort, 1000); + }) + + rsPort.open(); + } + + + function handleWebSocket() { + + if (ws) { + ws.removeAllListeners(); + ws = null; + } + + //to keep websocket opened, we send request every 150 seconds + let startRequests = null; + + console.log("handleWebSocket function called"); + ws = new WebSocket('ws:/0.0.0.0:1234/ws'); + + ws.onopen = function open() { + + instance.send(0, exports.title + " running"); + turnAlarm("off"); + + initialSetting(); + + setTimeout(function() { ws.send(JSON.stringify({ cmd: "all" })) }, 5000); + // we request dev info about neuron device from evok to keep websocket connection alive + // for some reason this request returns no data, but connection keeps alive + startRequests = setInterval(() => { + ws.send(JSON.stringify({ "cmd": "filter", "dev": ["neuron"] })); + }, 150000) + }; + + + // 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 = async 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; + + 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 => { + logger.debug('Dido: websocket error', err); + }) + + ws.onclose = function() { + logger.debug('Dido: websocket onclose, reconnecting...') + clearInterval(startRequests); + setTimeout(handleWebSocket, 1000); + } + } + + 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 turnAlarm(onOrOff) { + let value = 0; + if (onOrOff == "on") value = 1; + + if (value == 1 && SETTINGS.maintenance_mode) return; + + alarmStatus = "OFF"; + if (value == 1) alarmStatus = "ON"; + + if (rsPort) { + let arr = [0x55]; + arr.push(13); + arr.push(0); + arr.push(value); + + rsPort.write(Buffer.from(arr), function(err) { + logger.debug(`sirena - ${onOrOff}`); + }); + } + else if (ws) { + let cmd = { "cmd": "set", "dev": "relay", "circuit": "1_01", "value": value }; + ws.send(JSON.stringify(cmd)); + logger.debug(`sirena - ${onOrOff}`); + } + } + + + 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") { + bits.push(0); + } + else bits.push(1); + + if (deviceStatus["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); + } + + + // turn line on or off + function turnLine(onOrOff, line, pin, force, info) { + //onOrOff => "on" or "off" + let value = 0; + if (onOrOff == "on") value = 1; + + if (force == undefined) force = false; + + if (line == 0) { + if (value == 1 && alarmStatus == "ON") turnAlarm("off"); + SETTINGS.maintenance_mode = value ? true : false; + + 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); + return; + } + + if (pin === undefined) pin = getPin(line); + + if (pin === undefined) { + errLogger.error("pin is undefined!", line); + return; + } + + if (!force) { + if (relaysData[line].contactor == value) { + instance.send(SEND_TO.debug, `line is already ${onOrOff} ` + line); + logger.debug(`Dido: turnLine: line is already ${onOrOff} `, line); + return; + } + } + + // if(!rsPort.isOpen && !ws) + if (!rsPort && !ws) { + errLogger.error("Dido - port or websocket is not opened"); + return; + } + + if (rsPort) { + let arr = [0x55]; + arr.push(pin); + arr.push(0); + arr.push(value); + + rsPort.write(Buffer.from(arr), function(err) { + if (err === undefined) { + monitor.info(`Dido: turnLine ${onOrOff} zapisal do rsPort-u`, line, pin, arr, info); + switchLogic(arr); + } + else { + monitor.info(`Dido: turnLine ${onOrOff} WRITE error`, err); + } + }); + + } + else if (ws) { + //pin = "relay1_03" or "input1_01" ... we must make just "1_01" with slice method + monitor.info(`Dido: turnLine ${onOrOff} - (line, pin, force)`, line, pin, force, info); + let cmd = { "cmd": "set", "dev": "relay", "circuit": pin.slice(5), "value": value }; + ws.send(JSON.stringify(cmd)); + } + + //if rvo is 24/7, it has just one switching profile point at 13:00. we do not want to send notification as it repeats every day. + //const d = new Date(); + //if(d.getHours() != 13) sendNotification("Dido_controller: ", SETTINGS.rvoTbName, "switching_profile_point_applied_to_line", { line: line, value: onOrOff }, "", SEND_TO.tb, instance); + } + + + // 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; + + // 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) { + const status = flowdata.data.status; + if (status == "NOK-twilight_sensor") { + deviceStatus["twilight_sensor"] = "NOK"; + } + else if (status == "NOK-em340" || status == "NOK-em111") { + deviceStatus["em"] = "NOK"; + } + else if (status == "NOK-thermometer") { + deviceStatus["temperature"] = "NOK"; + } + } + else if ("values" in flowdata.data) { + 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" + } + else if (values.hasOwnProperty("temperature")) { + deviceStatus["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"; + } + + sendTelemetry(values, rvoTbName); + } + + sendRvoStatus(); + }) + + + + + // we expect array as flowdata.data + instance.on("1", flowdata => { + + //console.log(flowdata.data); + + if (!flowdata.data instanceof Object) return; + + let obj = flowdata.data; + let line = obj.line; + 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"); + }) + + + function calculateStateCode() { + + let bits = []; + + //Hlavny istic - state_of_main_switch => v rvo senica je to druhy door pre silovu cast (EM) + if (deviceStatus["state_of_main_switch"] === "closed" || deviceStatus["state_of_main_switch"] === "Off") { + bits.push(0); + } + else { + bits.push(1); + } + + //Prevadzkovy mod - Manual, Off, Automatic, maintenance_mode = true/false // DAVA 2 BITY + if (!SETTINGS.maintenance_mode) { + if (deviceStatus["rotary_switch_state"] === "Manual") { + bits.push(0); + bits.push(1); + } + + if (deviceStatus["rotary_switch_state"] === "Automatic") { + bits.push(0); + bits.push(0); + } + + if (deviceStatus["rotary_switch_state"] === "Off") { + bits.push(1); + bits.push(0); + } + } + else { + bits.push(1); + bits.push(1); + } + + //Dverovy kontakt + if (deviceStatus["door_condition"] === "closed") { + bits.push(0); + } + else { + bits.push(1); + } + + //EM + if (deviceStatus["em"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //Teplomer + if (deviceStatus["temperature"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //Batéria + if (deviceStatus["battery"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //Zdroj + if (deviceStatus["power_supply"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //MN + if (deviceStatus["master_node"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //výpadok napätia na fáze + if (deviceStatus["no_voltage"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + if (deviceStatus["twilight_sensor"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + // doplnime do 16 bitov (2 byty) + for (let i = bits.length; i < 16; i++) { + bits.push(0); + } + + // console.log("calculateStateCode - deviceStatus", deviceStatus); + // 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; + } + + + async function sendRvoStatus() { + + if (SETTINGS === undefined) return; + SETTINGS.masterNodeIsResponding ? deviceStatus["master_node"] = "OK" : deviceStatus["master_node"] = "NOK"; + + 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 pinsForRvoStatus(controllerType, hasMainSwitch) { + + let pins = []; + + if (controllerType === "lm") { + pins = [1, 4, 6]; + if (hasMainSwitch === 1) { + pins = [4, 6]; + } + } else if (controllerType === "unipi") { + pins = ["input1_01", "input1_04", "input1_05"]; + if (hasMainSwitch === 1) { + pins = ["input1_01", "input1_04"]; + } + } + + return pins; + } + + + function checkRvoStatus() { + + // 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 + //set RVO state + let status = "OK"; + + for (const [key, value] of Object.entries(deviceStatus)) { + if (["em", "twilight_sensor", "temperature", "master_node"].includes(key) && value === "NOK") status = "NOK"; + } + + if (status === "OK") { + + let pinIndexes = pinsForRvoStatus(controller_type, hasMainSwitch); + + for (const pinIndex of pinIndexes) { + if (previousValues[pinIndex] === 0) { + if ((pinIndex === 6 || pinIndex === 'input1_01' || pinIndex === 'input1_05') && SETTINGS.maintenance_mode) continue; + status = "NOK"; + break; + } + } + } + + // battery status. If value is 1 - battery is NOK + if (previousValues[5] === 1) status = "NOK"; + if (SETTINGS.no_voltage.size > 0) status = "NOK"; + + // console.log("rvo status",status) + return status; + } + + + // we pass array to function in case of rsPort ==> switchLogic([55,3,0,1]) ==> [[55,3,0,1]] + // we pass two values in case of websocket ==> switchLogic("relay1_03",1) ==> ["relay1_03",1] + const switchLogic = (...args) => { + + let values = {}; + let pinIndex, newPinValue, twilight; + + //data from rsPort + if (args.length == 1) { + pinIndex = args[0][1] + 1; + if (pinIndex === 17) pinIndex--; + newPinValue = args[0][3]; + twilight = args[0][2]; + } + //data from websocket + else { + pinIndex = args[0]; + newPinValue = args[1]; + } + + 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; + + //default value + let value = "On"; + if (newPinValue === 0) value = "Off"; + + //Hlavny istic + if (type === "state_of_main_switch" && hasMainSwitch) { + if (newPinValue === 0 && newPinValue !== previousValues[pinIndex]) { + sendNotification("switchLogic", rvoTbName, "main_switch_has_been_turned_off", {}, "", SEND_TO.tb, instance, "state_of_main_switch"); + 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"); + deviceStatus["state_of_main_switch"] = "On"; + } + } + + //Prevadzkovy mod + 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"; + + deviceStatus["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, "power_supply_has_disconnected_input", {}, "", SEND_TO.tb, instance, "power_supply"); + + deviceStatus["power_supply"] = "NOK"; + } + else if (newPinValue === 1 && newPinValue !== previousValues[pinIndex]) { + sendNotification("switchLogic", rvoTbName, "power_supply_works_correctly", {}, "", SEND_TO.tb, instance, "power_supply"); + + deviceStatus["power_supply"] = "OK"; + } + } + + //Bateria - 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"); + + deviceStatus["battery"] = "NOK"; + } + else if (newPinValue === 0 && newPinValue !== previousValues[pinIndex]) { + sendNotification("switchLogic", rvoTbName, "battery_level_is_ok", {}, "", SEND_TO.tb, instance, "battery_level"); + + deviceStatus["battery"] = "OK"; + } + } + + //Dverovy kontakt - pin 6 + //! Ak je rvo s dvoma dverovymi kontaktami, ked pride z evoku signal z input1_05, co bol predytm "state_of_main switch" handlujeme ho teraz ako 'door_condition' + else if (type == "door_condition" || type === "state_of_main_switch") { + newPinValue === 0 ? value = "open" : value = "closed"; + + let door = "door_main"; + if (type === "state_of_main_switch") door = "door_em"; + + if (value === "open") { + if (SETTINGS.maintenance_mode) { + sendNotification("switchLogic", rvoTbName, door + "_open", {}, "", SEND_TO.tb, instance, door); + } else { + sendNotification("switchLogic", rvoTbName, door + "_open_without_permission", {}, "", SEND_TO.tb, instance, door); + + // 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 (value === "closed") { + if (alarmStatus == "ON") turnAlarm("off"); + sendNotification("switchLogic", rvoTbName, door + "_close", {}, "", SEND_TO.tb, instance, door); + } + + deviceStatus[type] = value; + } + + //lux sensor + else if (type == "twilight_sensor") { + //! TODO - to show nok status, if lux value is not changing more then 10 times. + //Daylight is far more than 1000. So most of the day, when it is sunshine comes just value 1000. But lux sensor is not NOK. + //This is not the case in LM. If value from LM is the same 10x, there is 99% possibility, that sensor is NOK. + value = newPinValue; + + if (controller_type === 'lm') { + value = parseFloat(newPinValue + (256 * twilight)); + + 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 && !twilightError) { + twilightError = true; + let value = twilight_sensor_array.shift(); + + newPinValue = 0; + } + else if (set.size !== 1 && twilightError) { + //sendNotification("switchLogic", rvoTbName, 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) { + 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); + } + } + + 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); + } + + deviceStatus["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 (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 }); + + //mame iba 3 istice. vyreportujeme a ohandlujeme liniu na tom istom istici ako paralelna linia (napr linia 1, paralelna s nou je linia 4, key je string "4") + // ak je 7 linii, na 1 istici je linia 1,4,7 + + if (line == 1) { + + const lineOnSameBraker = [4, 7]; + + for (var i = 0; i < lineOnSameBraker.length; i++) { + if (!relaysData.hasOwnProperty(lineOnSameBraker[i])) continue; + + 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; + reportLineStatus(lineOnSameBraker[i]); + + values[type] = value; + const tbname = relaysData[lineOnSameBraker[i]].tbname; + sendTelemetry(values, tbname); + + delete values[type]; + } + + } + else { + const lineOnSameBraker = line + 3 + ""; + + if (relaysData.hasOwnProperty(lineOnSameBraker)) { + 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; + reportLineStatus(line + 3); + + values[type] = value; + const tbname = relaysData[lineOnSameBraker].tbname; + sendTelemetry(values, tbname); + + delete values[type]; + } + } + + } + + if (value == "Off") values["status"] = "NOK"; + deviceStatus["state_of_breaker"][line] = value; + + reportLineStatus(line); + } + else return; + + values[type] = value; + + if (type == "rotary_switch_state") { + if (SETTINGS.maintenance_mode) value = "maintenance"; + value = value.toLowerCase(); + values["power_mode"] = value; + } + + if (newPinValue != previousValues[pinIndex]) previousValues[pinIndex] = newPinValue; + if (Object.keys(values).length > 0 && tbname) sendTelemetry(values, tbname); + } + + + function sendTelemetry(values, tbname, date = Date.now()) { + let dataToTb = { + [tbname]: [ + { + "ts": date, + "values": values + } + ] + }; + + tbHandler.sendToTb(dataToTb, instance); + } + + + function isObject(item) { + return (typeof item === "object" && !Array.isArray(item) && item !== null); + } + +} //end of 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 +// *|input1_01|state_of_main_switch|0|........... +// *|input1_02|rotary_switch_state|0|........... +// *|input1_03|rotary_switch_state|0|........... +// *|intut1_04|power_supply|0|........... +// *|input1_05|door_condition|0|........... +// *|input1_06|state_of_breaker|1|........... +// *|input1_07|state_of_breaker|2|........... +// *|input1_08|state_of_breaker|3|........... +// *|relay1_02|state_of_contactor|1|........... +// *|relay1_03|state_of_contactor|2|........... +// *|relay1_04|state_of_contactor|3|........... +// *|287D8776E0013CE9|temperature|0|........... + + +//! pins_data --> from UNIPI +// { +// 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 } +// } + +//! relays_data +// { +// '0': { +// line: 0, +// tbname: 'KjbN4q7JPZmexgdnz2yKQ98YAWwO0Q3BMX6ERLoV', +// contactor: 1, +// profile: '' +// }, +// '1': { +// line: 1, +// tbname: 'RMgnK93rkoAazbqdQ4yBG95Z1YXGx6pmwBeVEP2O', +// contactor: 0, +// profile: '{"intervals":[{"value":0,"end_time":"20:00","start_time":"13:00"},{"value":1,"end_time":"10:00","start_time":"20:00"},{"value":0,"end_time":"10:20","start_time":"10:00"},{"value":1,"end_time":"10:40","start_time":"10:20"},{"value":0,"end_time":"11:00","start_time":"10:40"},{"value":1,"end_time":"11:30","start_time":"11:00"},{"value":0,"end_time":"11:50","start_time":"11:30"},{"value":1,"end_time":"13:00","start_time":"11:50"}],"astro_clock":false,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' +// }, +// '2': { +// line: 2, +// tbname: 'dlE1VQjYrNx9gZRmb38gG08oLBO4qaAk2M6JPnG7', +// contactor: 0, +// profile: '{"intervals":[{"value":0,"end_time":"20:00","start_time":"13:00"},{"value":1,"end_time":"10:00","start_time":"20:00"},{"value":0,"end_time":"10:20","start_time":"10:00"},{"value":1,"end_time":"10:40","start_time":"10:20"},{"value":0,"end_time":"11:00","start_time":"10:40"},{"value":1,"end_time":"11:30","start_time":"11:00"},{"value":0,"end_time":"11:50","start_time":"11:30"},{"value":1,"end_time":"13:00","start_time":"11:50"}],"astro_clock":false,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' +// }, +// '3': { +// line: 3, +// tbname: 'vnmG4kJxaXWNBgMQq0D7Aj5e9oZzOAlr6LdR3w2V', +// contactor: 0, +// profile: '{"intervals":[{"value":0,"end_time":"20:30","start_time":"13:00"},{"value":1,"end_time":"00:10","start_time":"20:30"},{"value":0,"end_time":"13:00","start_time":"05:40"},{"value":1,"end_time":"05:40","start_time":"00:10"}],"astro_clock":true,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' +// } +// } + + + + + +// { +// "jbN4q7JPZmexgdnz2yKbWGDYAWwO0Q3BMX6ERLoV": [ +// { +// "ts": 1700409326353, +// "values": { +// "_event": { +// "type": "notice", +// "status": "new", +// "source": { +// "func": "rsPort.open()", +// "component": "1700343402190", +// "component_name": "DIDO_Controller", +// "edge": "jbN4q7JPZmexgdnz2yKbWGDYAWwO0Q3BMX6ERLoV" +// }, +// "message": "al_shariff_10.0.0.38: FLOW has been started ", +// "message_data": "" +// } +// } +// } +// ] +// } diff --git a/RVO22/flow/helper/DataToTbHandler.js b/RVO22/flow/helper/DataToTbHandler.js new file mode 100755 index 0000000..716ef7b --- /dev/null +++ b/RVO22/flow/helper/DataToTbHandler.js @@ -0,0 +1,187 @@ +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; + this.itIsNodeReadout = false; + this.sender = ""; + + // if attribute change difference is less than limit value, we do not send to tb. + this.attributeChangeLimit = { + temperature: 0.5, + Phase_1_voltage: 2, + Phase_2_voltage: 2, + Phase_3_voltage: 2, + Phase_1_current: 0.1, + Phase_2_current: 0.1, + Phase_3_current: 0.1, + Phase_1_power: 2, + Phase_2_power: 2, + Phase_3_power: 2, + total_power: 2, + total_energy: 1, + Phase_1_pow_factor: 0.1, + Phase_2_pow_factor: 0.1, + Phase_3_pow_factor: 0.1, + power_factor: 0.1, + lifetime: 2, + voltage: 2, + power: 2, + frequency: 3, + energy: 0.1, + current: 2, + inclination_x: 10, + inclination_y: 10, + inclination_z: 10 + }; + + } + + dump() { + console.log("----------------------------"); + console.log("previousValues", this.previousValues); + console.log("----------------------------"); + } + + setSender(sender) { + this.sender = sender; + } + + isEmptyObject(obj) { + for (var _ in obj) { + return false; + } + return true; + } + + + sendToTb(data, instance) { + + //not to modify data object, we do deep copy: + let dataCopy = JSON.parse(JSON.stringify(data)); + + let keys = Object.keys(dataCopy); + + if (keys.length == 0) { + if (this.debug) console.log("sendToTb received empty object", dataCopy); + return; + } + + let tbname = keys[0]; + let ts; + + let arrayOfValues = dataCopy[tbname]; + let arrayOfValuesToSend = []; + + for (let i = 0; i < arrayOfValues.length; i++) { + + ts = arrayOfValues[i].ts; + let values = this.prepareValuesForTb(tbname, ts, arrayOfValues[i].values); + + if (!this.isEmptyObject(values)) { + arrayOfValuesToSend.push({ ts: ts, values: values }); + } + + } + + if (arrayOfValuesToSend.length == 0) { + //if(this.debug) console.log("data not sent - empty array"); + return; + } + + this.messageCounter++; + + let dataToTbModified = { + [tbname]: arrayOfValuesToSend + } + + //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); + instance.send(this.index, dataToTbModified); + } + + + getDiffTimestamp(key) { + //TODO set different value for given key!!! + //if(key == "status") this.timeToHoldTbValue = 2*60*60;//2h + return this.timeToHoldTbValue * 1000; + } + + + prepareValuesForTb(tbname, timestamp, values) { + + let keys = Object.keys(values); + + if (keys.includes("lifetime")) this.itIsNodeReadout = true; + + if (!this.previousValues.hasOwnProperty(tbname)) { + this.previousValues[tbname] = {}; + } + + //if(this.debug) console.log("prepareValuesForTb", tbname, timestamp, values); + + for (let i = 0; i < keys.length; i++) { + + let key = keys[i]; + let value = values[key]; + + if (!this.previousValues[tbname].hasOwnProperty(key)) { + this.previousValues[tbname][key] = { ts: timestamp, value: value }; + continue; + } + + // attributeData ==> {voltage: {ts:333333, value:5}} + let attributeData = this.previousValues[tbname][key]; + let attributeToChange = false; + if (key in this.attributeChangeLimit) attributeToChange = true; + let limit = this.attributeChangeLimit[key]; + let timestampDiffToRemoveKey; + + //this will ensure "node statecode" will be sent just once an hour + if (this.itIsNodeReadout && key === "statecode") { + attributeData.value = value; + this.itIsNodeReadout = false; + timestampDiffToRemoveKey = 1 * 60 * 60 * 1000; // 1 hour + } + + if (key === "twilight_sensor" && value > 100) { + attributeData.value = value; + } + + //if edge, master or node version do not change, send just once a day: + if (["edge_fw_version", "master_node_version", "fw_version"].includes(key)) { + timestampDiffToRemoveKey = 24 * 60 * 60 * 1000; + } + + if (attributeData.value === value || attributeToChange && Math.abs(attributeData.value - value) < limit) { + + let diff = timestamp - attributeData.ts; + if (!timestampDiffToRemoveKey) timestampDiffToRemoveKey = this.getDiffTimestamp(key); + + if (diff > timestampDiffToRemoveKey) { + attributeData.ts = Date.now(); + //if(this.debug) console.log(this.sender + ": update ts for key", key, "diff is", diff, "messageCounter", this.messageCounter); + } + else { + delete values[key]; + //if(this.debug) console.log(this.sender + ": delete key", key, "diff is", diff, "messageCounter", this.messageCounter, timestampDiffToRemoveKey); + } + } + else { + attributeData.value = value; + attributeData.ts = timestamp; + } + + } + + return values; + } +} + +module.exports = DataToTbHandler; + diff --git a/RVO22/flow/helper/ErrorToServiceHandler.js b/RVO22/flow/helper/ErrorToServiceHandler.js new file mode 100755 index 0000000..2b27c32 --- /dev/null +++ b/RVO22/flow/helper/ErrorToServiceHandler.js @@ -0,0 +1,91 @@ +const { MD5 } = require('./md5.js'); +const { networkInterfaces } = require('os'); + +class ErrorToServiceHandler { + constructor() { + this.previousValues = {}; + + this.project_id = undefined; + + const nets = networkInterfaces(); + this.ipAddresses = {}; + + for (const name of Object.keys(nets)) { + for (const net of nets[name]) { + // Skip over non-IPv4 and internal (i.e. 127.0.0.1) addresses + if (net.family === 'IPv4' && !net.internal) { + if (!this.ipAddresses[name]) { + this.ipAddresses[name] = []; + } + this.ipAddresses[name].push(net.address); + } + } + } + } + + setProjectId(project_id) { + this.project_id = project_id; + } + + processMessage(message, seconds) { + if (Array.isArray(message)) message = message.join(', '); + + let key = MD5(message); + let ts = Date.now(); + + //keep in memory - default value is 1h + if (seconds === undefined) seconds = 60 * 60; + + if (!this.previousValues.hasOwnProperty(key)) { + this.previousValues[key] = { ts: ts, duration: seconds }; + } + + let diff = (ts - this.previousValues[key].ts); + if (diff < this.previousValues[key].duration * 1000) return false; + + this.previousValues[key].ts = ts; + + return message; + } + + sendMessageToService(message, seconds, message_type) { + + // if error occures too early FLOW.GLOBALS.settings.project_id is still undefined + if (this.project_id === undefined) { + console.log("ErrorToServiceHandler.js: no project_id"); + return; + } + + let f = this.processMessage(message, seconds); + if (f === false) return; + + if (message_type === undefined) message_type = "error_message"; + + let toService = { + id: this.project_id, + ipAddresses: this.ipAddresses + }; + + //js_error || error_message + toService[message_type] = message; + + console.log("ErrorToServiceHandler------------------------>send to service", toService); + + RESTBuilder.make(function(builder) { + builder.method('POST'); + builder.post(toService); + builder.url('http://192.168.252.2:8004/sentmessage'); + + builder.callback(function(err, response, output) { + console.log("process.on error send", err, response, output, toService); + }); + }); + + } +} + +const errorHandler = new ErrorToServiceHandler(); + + +module.exports = errorHandler; +//module.exports = ErrorToServiceHandler; diff --git a/RVO22/flow/helper/db_helper.js b/RVO22/flow/helper/db_helper.js new file mode 100755 index 0000000..40e796c --- /dev/null +++ b/RVO22/flow/helper/db_helper.js @@ -0,0 +1,44 @@ +function promisifyBuilder(builder) +{ + return new Promise((resolve, reject) => { + + try{ + + builder.callback(function(err, response) { + + if(err != null) reject(err); + resolve(response); + }); + + } catch (error) { + reject(error); + } + }) +} + +function makeMapFromDbResult(response, ...keys) +{ + let s = "-"; + let data = {}; + + for(let i = 0; i < response.length; i++) + { + let record = response[i]; + + let k = []; + for(let j = 0; j < keys.length; j++) + { + k.push( record[keys[j]] ); + } + + let key = k.join(s); + data[ key ] = record; + } + + return data; +} + +module.exports = { + promisifyBuilder, + makeMapFromDbResult + } \ No newline at end of file diff --git a/RVO22/flow/helper/logger.js b/RVO22/flow/helper/logger.js new file mode 100755 index 0000000..2585639 --- /dev/null +++ b/RVO22/flow/helper/logger.js @@ -0,0 +1,30 @@ +//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/RVO22/flow/helper/md5.js b/RVO22/flow/helper/md5.js new file mode 100755 index 0000000..d3b0480 --- /dev/null +++ b/RVO22/flow/helper/md5.js @@ -0,0 +1,5 @@ +function MD5(d){var r = M(V(Y(X(d),8*d.length)));return r.toLowerCase()};function M(d){for(var _,m="0123456789ABCDEF",f="",r=0;r>>4&15)+m.charAt(15&_);return f}function X(d){for(var _=Array(d.length>>2),m=0;m<_.length;m++)_[m]=0;for(m=0;m<8*d.length;m+=8)_[m>>5]|=(255&d.charCodeAt(m/8))<>5]>>>m%32&255);return _}function Y(d,_){d[_>>5]|=128<<_%32,d[14+(_+64>>>9<<4)]=_;for(var m=1732584193,f=-271733879,r=-1732584194,i=271733878,n=0;n>16)+(_>>16)+(m>>16)<<16|65535&m}function bit_rol(d,_){return d<<_|d>>>32-_} + +module.exports = { + MD5 +} \ No newline at end of file diff --git a/RVO22/flow/helper/notification_reporter.js b/RVO22/flow/helper/notification_reporter.js new file mode 100755 index 0000000..839c12c --- /dev/null +++ b/RVO22/flow/helper/notification_reporter.js @@ -0,0 +1,121 @@ +//key is device, value = message {} +let sentValues = {}; +let notificationsData = null; +let rvoName; + +//sendNotification("CMD Manager: process cmd", SETTINGS.rvoTbName, "dimming_profile_was_successfully_received_by_node", { node: node }, "", SEND_TO.tb, instance); + +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 +}; + +function getKey(map, val) { + return Object.keys(map).findItem(key => map[key] === val); +} + +//https://stackoverflow.com/questions/41117799/string-interpolation-on-variable +var template = (tpl, args) => tpl.replace(/\${(\w+)}/g, (_, v) => args[v]); + + +function initNotification() { + notificationsData = FLOW.GLOBALS.notificationsData; + rvoName = FLOW.GLOBALS.settings.rvo_name; +} + + +function sendNotification(func, device, key, params, extra, tb_output, instance, saveKey) { + + let storeToSendValues = true; + if (saveKey == undefined) storeToSendValues = false; + + let weight = ""; + let message = {}; + + let notification = notificationsData[key]; + + if (notification) { + weight = notification.weight.toLowerCase(); + + Object.keys(notification).forEach(item => { + if (["en", "sk", "de", "cz", "it", "es"].includes(item)) { + message[item] = rvoName + ": " + template(notification[item], params); + } + }) + } + else { + //console.error("sendNotification: Notifications: undefined key", key, func, notificationsData); + console.error("sendNotification: Notifications: undefined key", key, func); + return false; + } + + //detect invalid err weight + if (getKey(ERRWEIGHT, weight) == undefined) { + console.error("sendNotification: Notifications: undefined weight", weight, key, func); + return false; + } + + if (sentValues.hasOwnProperty(saveKey)) { + if (JSON.stringify(sentValues[saveKey]) == JSON.stringify(message)) { + return false; + } + } + + if (sentValues[saveKey] == undefined) { + if (storeToSendValues) { + //do not send - flow is was started + sentValues[saveKey] = message; + return false; + } + } + + if (storeToSendValues) sentValues[saveKey] = message; + + let content = { + "type": weight, + "status": "new", + "source": { + "func": func, + "component": instance.id, + "component_name": instance.name, + "edge": device + }, + "message": message, + "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 + + return true; + +} + +module.exports = { + sendNotification, + ERRWEIGHT, + initNotification +} + diff --git a/RVO22/flow/helper/register.js b/RVO22/flow/helper/register.js new file mode 100755 index 0000000..fc1d008 --- /dev/null +++ b/RVO22/flow/helper/register.js @@ -0,0 +1,144 @@ +/* +0 - cislo registra / prikaz +1 - recepient - 0 = master, 1 = slave (slave je automaticky group a broadcast) +2 - r/rw - read/write +3- register name - nazov registra / prikazu (len pre info - zobrazenie v aplikacii) + +4,5,6,7, - jednotlive byte-y - nazov byte-u +4-7 - RES. a prazdny string "" sa nezobrazia!!! +*/ + +//124 zaznamov +const registers = [ + ["0","1","R","Status","","",""], + ["1","1","RW","Dimming","R-Channel ","G-Channel","B-Channel ","W - Channel"], + ["2","1","R","Device types","","",".",""], + ["3","1","RW","Group addresses 1-4","Groups Add. 4","Groups Add. 3","Groups Add. 2","Groups Add. 1"], + ["4","1","RW","Group addresses 5-8","Groups Add. 8","Groups Add. 7","Groups Add. 6","Groups Add. 5"], + ["5","1","RW","Serial number (MAC)","","","",""], + ["6","1","RW","Time of dusk","HH","MM","SS","EXTRA"], + ["7","1","RW","Time of dawn","HH","MM","SS","EXTRA"], + ["8","1","RW","Time Schedule settings","TBD","TBD","Movement sensor","Time Schedule"], + ["9","1","RW","TS1 Time point 1","HH","MM","SS","Ext. Device"], + ["10","1","RW","TS1 Time point 1 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["11","1","RW","TS1 Time point 2","HH","MM","SS","Ext. Device"], + ["12","1","RW","TS1 Time point 2 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["13","1","RW","TS1 Time point 3","HH","MM","SS","Ext. Device"], + ["14","1","RW","TS1 Time point 3 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["15","1","RW","TS1 Time point 4","HH","MM","SS","Ext. Device"], + ["16","1","RW","TS1 Time point 4 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["17","1","RW","TS1 Time point 5","HH","MM","SS","Ext. Device"], + ["18","1","RW","TS1 Time point 5 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["19","1","RW","TS1 Time point 6","HH","MM","SS","Ext. Device"], + ["20","1","RW","TS1 Time point 6 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["21","1","RW","TS1 Time point 7","HH","MM","SS","Ext. Device"], + ["22","1","RW","TS1 Time point 7 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["23","1","RW","TS1 Time point 8","HH","MM","SS","Ext. Device"], + ["24","1","RW","TS1 Time point 8 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["25","1","RW","TS1 Time point 9","HH","MM","SS","Ext. Device"], + ["26","1","RW","TS1 Time point 9 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["27","1","RW","TS1 Time point 10","HH","MM","SS","Ext. Device"], + ["28","1","RW","TS1 Time point 10 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["29","1","RW","TS1 Time point 11","HH","MM","SS","Ext. Device"], + ["30","1","RW","TS1 Time point 11 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["31","1","RW","TS1 Time point 12","HH","MM","SS","Ext. Device"], + ["32","1","RW","TS1 Time point 12 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["33","1","RW","TS1 Time point 13","HH","MM","SS","Ext. Device"], + ["34","1","RW","TS1 Time point 13 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["35","1","RW","TS1 Time point 14","HH","MM","SS","Ext. Device"], + ["36","1","RW","TS1 Time point 14 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["37","1","RW","TS1 Time point 15","HH","MM","SS","Ext. Device"], + ["38","1","RW","TS1 Time point 15 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["39","1","RW","TS1 Time point 16","HH","MM","SS","Ext. Device"], + ["40","1","RW","TS1 Time point 16 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["41","1","RW","TS2 Time point 1","HH","MM","SS","Ext. Device"], + ["42","1","RW","TS2 Time point 1 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["43","1","RW","TS2 Time point 2","HH","MM","SS","Ext. Device"], + ["44","1","RW","TS2 Time point 2 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["45","1","RW","TS2 Time point 3","HH","MM","SS","Ext. Device"], + ["46","1","RW","TS2 Time point 3 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["47","1","RW","TS2 Time point 4","HH","MM","SS","Ext. Device"], + ["48","1","RW","TS2 Time point 4 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["49","1","RW","TS2 Time point 5","HH","MM","SS","Ext. Device"], + ["50","1","RW","TS2 Time point 5 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["51","1","RW","TS2 Time point 6","HH","MM","SS","Ext. Device"], + ["52","1","RW","TS2 Time point 6 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["53","1","RW","TS2 Time point 7","HH","MM","SS","Ext. Device"], + ["54","1","RW","TS2 Time point 7 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["55","1","RW","TS2 Time point 8","HH","MM","SS","Ext. Device"], + ["56","1","RW","TS2 Time point 8 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["57","1","RW","TS2 Time point 9","HH","MM","SS","Ext. Device"], + ["58","1","RW","TS2 Time point 9 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["59","1","RW","TS2 Time point 10","HH","MM","SS","Ext. Device"], + ["60","1","RW","TS2 Time point 10 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["61","1","RW","TS2 Time point 11","HH","MM","SS","Ext. Device"], + ["62","1","RW","TS2 Time point 11 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["63","1","RW","TS2 Time point 12","HH","MM","SS","Ext. Device"], + ["64","1","RW","TS2 Time point 12 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["65","1","RW","TS2 Time point 13","HH","MM","SS","Ext. Device"], + ["66","1","RW","TS2 Time point 13 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["67","1","RW","TS2 Time point 14","HH","MM","SS","Ext. Device"], + ["68","1","RW","TS2 Time point 14 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["69","1","RW","TS2 Time point 15","HH","MM","SS","Ext. Device"], + ["70","1","RW","TS2 Time point 15 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["71","1","RW","TS2 Time point 16","HH","MM","SS","Ext. Device"], + ["72","1","RW","TS2 Time point 16 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["73","1","RW","Power meter status","TBD","","",""], + ["74","1","R","Input Voltage","","","",""], + ["75","1","R","Input Current","","","",""], + ["76","1","R","Input Power","","","",""], + ["77","1","R","Cos phi","","","",""], + ["78","1","R","Frequency","","","",""], + ["79","1","RW","Energy","","","",""], + ["80","1","RW","Lifetime","","","",""], + ["81","1","RW","Power on cycles (input)","","","",""], + ["82","1","RW","Power on cycles (relay)","","","",""], + ["83","1","R","Time since last power on","","","",""], + ["84","1","R","Accelerometer data","","","",""], + ["85","1","RW","GPS latitude","pos/neg","deg","min ","sec"], + ["86","1","RW","GPS longitude","pos/neg","deg","min ","sec"], + ["87","1","RW","Actual time","HH","MM","SS","RES."], + ["88","1","RW","Actual date","Day of week","Day","Month","Year"], + ["89","1","R","Production data 1","","","",""], + ["90","1","R","Production data 2","","","",""], + ["91","1","RW","Network ID","NID3","NID2","NID1","NID0"], + ["95","1","RW","Actual Lux level from cabinet","RES.","RES.","HB","LB"], + ["96","1","RW","Threshold lux level","Dusk HB","Dusk LB","Dawn HB","Dawn LB"], + ["97","1","RW","Adjust period","Dusk HB","Dusk LB","Dawn HB","Dawn LB"], + ["98","1","RW","Offset","RES.","RES.","Dusk","Dawn"], + ["99","1","RW","CCT min/max range","max-H","max-L","min-H","min-L"], + ["100","1","RW","DALI interface","Cmd ID","Add","Cmd","Resp"], + ["101","1","RW","Module FW ver","v1","v2","v3","v4"], + ["102","1","RW","Module MAC-H","unused","unused","M1","M2"], + ["103","1","RW","Module MAC-L","M3","M4","M5","M6"], + ["122","1","R","FW update status/control register","Byte3","Byte2","Byte1","Byte0"], + ["123","1","R","FW update - data index","Byte3","Byte2","Byte1","Byte0"], + ["124","1","R","FW update - data","Byte3","Byte2","Byte1","Byte0"], + ["0","0","R","Status","","","",""], + ["1","0","RW","Control register","RES.","RES.","RES.","init mode enable"], + ["2","0","R","Device types","","","",""], + ["3","0","R","Serial number (MAC)","","","",""], + ["4","0","R","Production data 1","","","",""], + ["5","0","R","Production data 2","","","",""], + ["6","0","RW","Network ID","NID3","NID2","NID1","NID0"], + ["7","0","RW","RS232 settings","param.","param.","Baudrate H","Baudrate L"], + ["8","0","R","Accelerometer data","","","",""], + ["9","0","RW","Module FW ver","v1","v2","v3","v4"], + ["10","0","RW","Module MAC-H","unused","unused","M1","M2"], + ["11","0","RW","Module MAC-L","M3","M4","M5","M6"], + ["32","0","RW","FW update status/control register","Byte3","Byte2","Byte1","Byte0"], + ["33","0","RW","FW update - data index","Byte3","Byte2","Byte1","Byte0"], + ["34","0","RW","FW update - data","Byte3","Byte2","Byte1","Byte0"], + ["125","0","RW","Debug Register","Byte3","Byte2","Byte1","Byte0"], + ["126","0","RW","Network Control Register","Byte3","Byte2","Byte1","Byte0"], + ["127","0","R","Network Status Register","Byte3","Byte2","Byte1","Byte0"], + ["128","0","RW","Node XX Serial Number Register","SER3","SER2","SER1","SER0"], + ["256","0","R","Node XX Network Status Register","","","",""] +]; + +let register = {}; + +module.exports = { + registers, + register +} \ No newline at end of file diff --git a/RVO22/flow/helper/serialport_helper.js b/RVO22/flow/helper/serialport_helper.js new file mode 100755 index 0000000..7f5920d --- /dev/null +++ b/RVO22/flow/helper/serialport_helper.js @@ -0,0 +1,99 @@ +const { exec } = require('child_process'); + +function openPort(port) { + return new Promise((resolve, reject) => { + + var callbackError = function(err) { + port.removeListener('error', callbackError); + port.removeListener('open', callbackError); + + reject(err.message); + }; + + var callbackOpen = function(data) { + port.removeListener('error', callbackError); + port.removeListener('open', callbackOpen); + + resolve("port open: ok"); + }; + + port.on('error', callbackError); + port.on('open', callbackOpen); + + port.open(); + + }) +} + +function runSyncExec(command) { + return new Promise((resolve, reject) => { + + exec(command, (error, stdout, stderr) => { + if (error == null) resolve(stdout); + reject(error); + }); + + }) +} + +async function writeData(port, data, readbytes, timeout) { + return new Promise((resolve, reject) => { + + // 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) { + + port.write(Buffer.from(data), function(err) { + if (err) { + reject(err.message); + } + }); + + 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 +} diff --git a/RVO22/flow/helper/suncalc.js b/RVO22/flow/helper/suncalc.js new file mode 100755 index 0000000..c9ca56d --- /dev/null +++ b/RVO22/flow/helper/suncalc.js @@ -0,0 +1,317 @@ +/* + (c) 2011-2015, Vladimir Agafonkin + SunCalc is a JavaScript library for calculating sun/moon position and light phases. + https://github.com/mourner/suncalc +*/ + +(function () { 'use strict'; + +// shortcuts for easier to read formulas + +var PI = Math.PI, + sin = Math.sin, + cos = Math.cos, + tan = Math.tan, + asin = Math.asin, + atan = Math.atan2, + acos = Math.acos, + rad = PI / 180; + +// sun calculations are based on http://aa.quae.nl/en/reken/zonpositie.html formulas + + +// date/time constants and conversions + +var dayMs = 1000 * 60 * 60 * 24, + J1970 = 2440588, + J2000 = 2451545; + +function toJulian(date) { return date.valueOf() / dayMs - 0.5 + J1970; } +function fromJulian(j) { return new Date((j + 0.5 - J1970) * dayMs); } +function toDays(date) { return toJulian(date) - J2000; } + + +// general calculations for position + +var e = rad * 23.4397; // obliquity of the Earth + +function rightAscension(l, b) { return atan(sin(l) * cos(e) - tan(b) * sin(e), cos(l)); } +function declination(l, b) { return asin(sin(b) * cos(e) + cos(b) * sin(e) * sin(l)); } + +function azimuth(H, phi, dec) { return atan(sin(H), cos(H) * sin(phi) - tan(dec) * cos(phi)); } +function altitude(H, phi, dec) { return asin(sin(phi) * sin(dec) + cos(phi) * cos(dec) * cos(H)); } + +function siderealTime(d, lw) { return rad * (280.16 + 360.9856235 * d) - lw; } + +function astroRefraction(h) { + if (h < 0) // the following formula works for positive altitudes only. + h = 0; // if h = -0.08901179 a div/0 would occur. + + // formula 16.4 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + // 1.02 / tan(h + 10.26 / (h + 5.10)) h in degrees, result in arc minutes -> converted to rad: + return 0.0002967 / Math.tan(h + 0.00312536 / (h + 0.08901179)); +} + +// general sun calculations + +function solarMeanAnomaly(d) { return rad * (357.5291 + 0.98560028 * d); } + +function eclipticLongitude(M) { + + var C = rad * (1.9148 * sin(M) + 0.02 * sin(2 * M) + 0.0003 * sin(3 * M)), // equation of center + P = rad * 102.9372; // perihelion of the Earth + + return M + C + P + PI; +} + +function sunCoords(d) { + + var M = solarMeanAnomaly(d), + L = eclipticLongitude(M); + + return { + dec: declination(L, 0), + ra: rightAscension(L, 0) + }; +} + + +var SunCalc = {}; + + +// calculates sun position for a given date and latitude/longitude + +SunCalc.getPosition = function (date, lat, lng) { + + var lw = rad * -lng, + phi = rad * lat, + d = toDays(date), + + c = sunCoords(d), + H = siderealTime(d, lw) - c.ra; + + return { + azimuth: azimuth(H, phi, c.dec), + altitude: altitude(H, phi, c.dec) + }; +}; + + +// sun times configuration (angle, morning name, evening name) + +var times = SunCalc.times = [ + [-0.833, 'sunrise', 'sunset' ], + [ -0.3, 'sunriseEnd', 'sunsetStart' ], + [ -6, 'dawn', 'dusk' ], + [ -12, 'nauticalDawn', 'nauticalDusk'], + [ -18, 'nightEnd', 'night' ], + [ 6, 'goldenHourEnd', 'goldenHour' ] +]; + +// adds a custom time to the times config + +SunCalc.addTime = function (angle, riseName, setName) { + times.push([angle, riseName, setName]); +}; + + +// calculations for sun times + +var J0 = 0.0009; + +function julianCycle(d, lw) { return Math.round(d - J0 - lw / (2 * PI)); } + +function approxTransit(Ht, lw, n) { return J0 + (Ht + lw) / (2 * PI) + n; } +function solarTransitJ(ds, M, L) { return J2000 + ds + 0.0053 * sin(M) - 0.0069 * sin(2 * L); } + +function hourAngle(h, phi, d) { return acos((sin(h) - sin(phi) * sin(d)) / (cos(phi) * cos(d))); } +function observerAngle(height) { return -2.076 * Math.sqrt(height) / 60; } + +// returns set time for the given sun altitude +function getSetJ(h, lw, phi, dec, n, M, L) { + + var w = hourAngle(h, phi, dec), + a = approxTransit(w, lw, n); + return solarTransitJ(a, M, L); +} + + +// calculates sun times for a given date, latitude/longitude, and, optionally, +// the observer height (in meters) relative to the horizon + +SunCalc.getTimes = function (date, lat, lng, height) { + + height = height || 0; + + var lw = rad * -lng, + phi = rad * lat, + + dh = observerAngle(height), + + d = toDays(date), + n = julianCycle(d, lw), + ds = approxTransit(0, lw, n), + + M = solarMeanAnomaly(ds), + L = eclipticLongitude(M), + dec = declination(L, 0), + + Jnoon = solarTransitJ(ds, M, L), + + i, len, time, h0, Jset, Jrise; + + + var result = { + solarNoon: fromJulian(Jnoon), + nadir: fromJulian(Jnoon - 0.5) + }; + + for (i = 0, len = times.length; i < len; i += 1) { + time = times[i]; + h0 = (time[0] + dh) * rad; + + Jset = getSetJ(h0, lw, phi, dec, n, M, L); + Jrise = Jnoon - (Jset - Jnoon); + + result[time[1]] = fromJulian(Jrise); + result[time[2]] = fromJulian(Jset); + } + + return result; +}; + + +// moon calculations, based on http://aa.quae.nl/en/reken/hemelpositie.html formulas + +function moonCoords(d) { // geocentric ecliptic coordinates of the moon + + var L = rad * (218.316 + 13.176396 * d), // ecliptic longitude + M = rad * (134.963 + 13.064993 * d), // mean anomaly + F = rad * (93.272 + 13.229350 * d), // mean distance + + l = L + rad * 6.289 * sin(M), // longitude + b = rad * 5.128 * sin(F), // latitude + dt = 385001 - 20905 * cos(M); // distance to the moon in km + + return { + ra: rightAscension(l, b), + dec: declination(l, b), + dist: dt + }; +} + +SunCalc.getMoonPosition = function (date, lat, lng) { + + var lw = rad * -lng, + phi = rad * lat, + d = toDays(date), + + c = moonCoords(d), + H = siderealTime(d, lw) - c.ra, + h = altitude(H, phi, c.dec), + // formula 14.1 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + pa = atan(sin(H), tan(phi) * cos(c.dec) - sin(c.dec) * cos(H)); + + h = h + astroRefraction(h); // altitude correction for refraction + + return { + azimuth: azimuth(H, phi, c.dec), + altitude: h, + distance: c.dist, + parallacticAngle: pa + }; +}; + + +// calculations for illumination parameters of the moon, +// based on http://idlastro.gsfc.nasa.gov/ftp/pro/astro/mphase.pro formulas and +// Chapter 48 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + +SunCalc.getMoonIllumination = function (date) { + + var d = toDays(date || new Date()), + s = sunCoords(d), + m = moonCoords(d), + + sdist = 149598000, // distance from Earth to Sun in km + + phi = acos(sin(s.dec) * sin(m.dec) + cos(s.dec) * cos(m.dec) * cos(s.ra - m.ra)), + inc = atan(sdist * sin(phi), m.dist - sdist * cos(phi)), + angle = atan(cos(s.dec) * sin(s.ra - m.ra), sin(s.dec) * cos(m.dec) - + cos(s.dec) * sin(m.dec) * cos(s.ra - m.ra)); + + return { + fraction: (1 + cos(inc)) / 2, + phase: 0.5 + 0.5 * inc * (angle < 0 ? -1 : 1) / Math.PI, + angle: angle + }; +}; + + +function hoursLater(date, h) { + return new Date(date.valueOf() + h * dayMs / 24); +} + +// calculations for moon rise/set times are based on http://www.stargazing.net/kepler/moonrise.html article + +SunCalc.getMoonTimes = function (date, lat, lng, inUTC) { + var t = new Date(date); + if (inUTC) t.setUTCHours(0, 0, 0, 0); + else t.setHours(0, 0, 0, 0); + + var hc = 0.133 * rad, + h0 = SunCalc.getMoonPosition(t, lat, lng).altitude - hc, + h1, h2, rise, set, a, b, xe, ye, d, roots, x1, x2, dx; + + // go in 2-hour chunks, each time seeing if a 3-point quadratic curve crosses zero (which means rise or set) + for (var i = 1; i <= 24; i += 2) { + h1 = SunCalc.getMoonPosition(hoursLater(t, i), lat, lng).altitude - hc; + h2 = SunCalc.getMoonPosition(hoursLater(t, i + 1), lat, lng).altitude - hc; + + a = (h0 + h2) / 2 - h1; + b = (h2 - h0) / 2; + xe = -b / (2 * a); + ye = (a * xe + b) * xe + h1; + d = b * b - 4 * a * h1; + roots = 0; + + if (d >= 0) { + dx = Math.sqrt(d) / (Math.abs(a) * 2); + x1 = xe - dx; + x2 = xe + dx; + if (Math.abs(x1) <= 1) roots++; + if (Math.abs(x2) <= 1) roots++; + if (x1 < -1) x1 = x2; + } + + if (roots === 1) { + if (h0 < 0) rise = i + x1; + else set = i + x1; + + } else if (roots === 2) { + rise = i + (ye < 0 ? x2 : x1); + set = i + (ye < 0 ? x1 : x2); + } + + if (rise && set) break; + + h0 = h2; + } + + var result = {}; + + if (rise) result.rise = hoursLater(t, rise); + if (set) result.set = hoursLater(t, set); + + if (!rise && !set) result[ye > 0 ? 'alwaysUp' : 'alwaysDown'] = true; + + return result; +}; + + +// export as Node module / AMD module / browser variable +if (typeof exports === 'object' && typeof module !== 'undefined') module.exports = SunCalc; +else if (typeof define === 'function' && define.amd) define(SunCalc); +else window.SunCalc = SunCalc; + +}()); diff --git a/RVO22/flow/helper/utils.js b/RVO22/flow/helper/utils.js new file mode 100755 index 0000000..dbffe45 --- /dev/null +++ b/RVO22/flow/helper/utils.js @@ -0,0 +1,161 @@ +const fs = require('fs').promises; + +function bytesToInt(bytes, numberOfBytes) { + let buffer = []; + if (Array.isArray(bytes)) { + buffer = bytes.slice(0); + if (numberOfBytes != undefined) { + buffer = bytes.slice(bytes.length - numberOfBytes); + } + } + else buffer.push(bytes); + + let result = 0; + for (let i = 0; i < buffer.length; i++) { + result = (result << 8) | buffer[i]; + } + + return result >>> 0; //ensure it's an unsigned 32-bit number +} + +function resizeArray(arr, newSize, defaultValue) { + while (newSize > arr.length) + arr.push(defaultValue); + arr.length = newSize; +} + +longToByteArray = function(/*long*/long) { + // we want to represent the input as a 8-bytes array + var byteArray = [0, 0, 0, 0, 0, 0, 0, 0]; + + for (var index = 0; index < byteArray.length; index++) { + var byte = long & 0xff; + byteArray[index] = byte; + long = (long - byte) / 256; + } + + return byteArray; +}; + +function addDays(date, days) { + var result = new Date(date); + result.setDate(result.getDate() + days); + return result; +} + +/* +sleep(2000).then(() => { + // Do something after the sleep! + + +}); +*/ + +function sleep(time) { + return new Promise((resolve) => setTimeout(resolve, time)); +} + +function isEmptyObject(obj) { + for (var name in obj) { + return false; + } + return true; +} + +function emptyJsObject(jsObject) { + Object.keys(jsObject).forEach(key => delete jsObject[key]); +} + +function convertUTCDateToLocalDate(date) { + var newDate = new Date(date); + newDate.setMinutes(date.getMinutes() + date.getTimezoneOffset()); + return newDate; +} + +function addZeroBefore(n) { + return (n < 10 ? '0' : '') + n; +} + + +/** + * Asynchronously writes data to a file. + * + * @param {string} filePath The path to the file. + * @param {string} data The data to write to the file. + * @param {boolean} [append=false] If true, appends the data to the file. If false, it overwrites the file. + */ +async function writeToFile(filePath, data, append = false) { + if (typeof data !== 'string') data = JSON.stringify(data, null, 2); + try { + if (append) { + // Append the data to the end of the file. This is the simplest way to append. + await fs.appendFile(filePath, data, 'utf8'); + console.log(`Successfully appended data to ${filePath} using fs.appendFile.`); + } else { + // Overwrite the file with the new data. + await fs.writeFile(filePath, data, 'utf8'); + console.log(`Successfully wrote (overwrote) data to ${filePath} using fs.writeFile.`); + } + } catch (error) { + console.error(`Error writing to file ${filePath}:`, error); + } +} + + + /** + * Checks if an item is present in an array and adds it if it's not. + * * @param {Array} arr The array to check. + * @param {*} item The item to add. + * @returns {Array} The modified array. + */ +const addToArrayIfUnique = (arr, item) => { + if (!arr.includes(item)) { + arr.push(item); + } + return arr; +}; + + +var convertBase = function() { + + function convertBase(baseFrom, baseTo) { + return function(num) { + return parseInt(num, baseFrom).toString(baseTo); + + }; + } + + // binary to decimal + convertBase.bin2dec = convertBase(2, 10); + + // binary to hexadecimal + convertBase.bin2hex = convertBase(2, 16); + + // decimal to binary + convertBase.dec2bin = convertBase(10, 2); + + // decimal to hexadecimal + convertBase.dec2hex = convertBase(10, 16); + + // hexadecimal to binary + convertBase.hex2bin = convertBase(16, 2); + + // hexadecimal to decimal + convertBase.hex2dec = convertBase(16, 10); + + return convertBase; +}(); + +module.exports = { + bytesToInt, + longToByteArray, + addDays, + addZeroBefore, + resizeArray, + isEmptyObject, + emptyJsObject, + sleep, + convertUTCDateToLocalDate, + writeToFile, + addToArrayIfUnique +} diff --git a/RVO22/flow/httprequest.js b/RVO22/flow/httprequest.js new file mode 100755 index 0000000..469c8cb --- /dev/null +++ b/RVO22/flow/httprequest.js @@ -0,0 +1,137 @@ +exports.id = 'httprequest'; +exports.title = 'HTTP Request'; +exports.group = 'HTTP'; +exports.color = '#5D9CEC'; +exports.input = true; +exports.version = '2.0.1'; +exports.output = 1; +exports.author = 'Peter Širka'; +exports.icon = 'cloud-upload'; + +exports.html = `
+
@(URL address)
+
+
+
@(HTTP method)
+
+
+
@(Serialization)
+
+
+
@(Download the content in chunks)
+
@(Keep persistent cookies)
+
@(Disable DNS cache)
+
@(Keep alive connection)
+
+
+
+
@(Custom headers)
+
@(Cookies)
+
+
+
+ +
+
+
+
@(User)
+
+
+
@(Password)
+
+
+
+
+
`; + +exports.readme = `# Request + +This component creates a request with received data. + +__Response:__ +\`\`\`javascript +{ + data: String, + headers: Object, + status: Number, + host: String +} +\`\`\` + +__Dynamic arguments__: +Are performed via FlowData repository and can be used for URL address or for custom headers/cookies/auth. Use \`repository\` component for creating of dynamic arguments. Dynamic values are replaced in the form \`{key}\`: + +- url address e.g. \`https://.../{key}/\` +- headers values e.g. \`{token}\` +- cookies values e.g. \`{token}\``; + +exports.install = function(instance) { + + var can = false; + var flags = null; + var cookies2 = null; + + instance.on('data', function(response) { + can && instance.custom.send(response); + }); + + instance.custom.send = function(response) { + var options = instance.options; + + var headers = null; + var cookies = null; + + options.headers && Object.keys(options.headers).forEach(function(key) { + !headers && (headers = {}); + headers[key] = response.arg(options.headers[key]); + }); + + if (options.username && options.userpassword) { + !headers && (headers = {}); + headers['Authorization'] = 'Basic ' + U.createBuffer(response.arg(options.username + ':' + options.userpassword)).toString('base64'); + } + + options.cookies && Object.keys(options.cookies).forEach(function(key) { + !cookies && (cookies = {}); + cookies[key] = response.arg(options.cookies[key]); + }); + + if (options.chunks) { + U.download(response.arg(options.url), flags, options.stringify === 'none' ? null : response.data, function(err, response) { + response.on('data', (chunks) => instance.send2(chunks)); + }, cookies || cookies2, headers); + } else { + U.request(response.arg(options.url), flags, options.stringify === 'none' ? null : response.data, 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) + instance.error(err, response); + }, cookies || cookies2, headers); + } + }; + + instance.reconfigure = function() { + var options = instance.options; + can = options.url && options.url && options.method && options.stringify ? true : false; + instance.status(can ? '' : 'Not configured', can ? undefined : 'red'); + + if (!can) + return; + + flags = []; + flags.push(options.method.toLowerCase()); + options.stringify === 'json' && flags.push('json'); + options.stringify === 'raw' && flags.push('raw'); + options.keepalive && flags.push('keepalive'); + !options.nodns && flags.push('dnscache'); + if (options.persistentcookies) { + flags.push('cookies'); + cookies2 = {}; + } else + cookies2 = null; + }; + + instance.on('options', instance.reconfigure); + instance.reconfigure(); +}; \ No newline at end of file diff --git a/RVO22/flow/httpresponse.js b/RVO22/flow/httpresponse.js new file mode 100755 index 0000000..160a3bb --- /dev/null +++ b/RVO22/flow/httpresponse.js @@ -0,0 +1,76 @@ +exports.id = 'httpresponse'; +exports.title = 'HTTP Response'; +exports.group = 'HTTP'; +exports.color = '#5D9CEC'; +exports.icon = 'arrow-right'; +exports.input = true; +exports.output = ['#666D76']; +exports.version = '2.0.0'; +exports.author = 'Martin Smola'; +exports.readme = `# HTTP response + +HTTP response will respond with data recieved using data-type set in Settings form or plain text if not set. Output is the message duration \`Number\` in seconds.`; + +exports.html = `
+
@(Response data-type)
+
JSON is by default.
+
`; + +exports.install = function(instance) { + + var dursum = 0; + var durcount = 0; + + instance.on('data', function(flowdata) { + + var ctrl = flowdata.repository.controller; + var data = flowdata.data; + + if (!ctrl) { + instance.throw('No controller to use for response!'); + return; + } + + durcount++; + dursum += ((new Date() - flowdata.begin) / 1000).floor(2); + setTimeout2(instance.id, instance.custom.duration, 500, 10); + + ctrl.$flowdata = flowdata; + + var datatype = instance.options.datatype || 'json'; + if (datatype === 'emptyresponse') + return ctrl.plain(''); + + if (datatype !== 'json' && typeof(data) !== 'string') { + instance.throw('Incorect type of data, expected string, got ' + typeof(data)); + ctrl.plain(data == null ? '' : data.toString()); + return; + } + + switch(datatype) { + case 'html': + ctrl.content(data, 'text/html'); + break; + case 'plain': + ctrl.plain(data); + break; + case 'xml': + ctrl.content(data, 'text/xml'); + break; + default: + ctrl.json(data); + break; + } + }); + + instance.on('service', function() { + dursum = 0; + durcount = 0; + }); + + instance.custom.duration = function() { + var avg = (dursum / durcount).floor(2); + instance.status(avg + ' sec.'); + instance.send2(0, avg); + }; +}; diff --git a/RVO22/flow/httproute.js b/RVO22/flow/httproute.js new file mode 100755 index 0000000..583a19d --- /dev/null +++ b/RVO22/flow/httproute.js @@ -0,0 +1,326 @@ +exports.id = 'httproute'; +exports.title = 'HTTP Route'; +exports.group = 'HTTP'; +exports.color = '#5D9CEC'; +exports.icon = 'globe'; +exports.input = false; +exports.output = ['#6CAC5A', '#37BC9B']; +exports.version = '1.2.3'; +exports.author = 'Martin Smola'; +exports.cloning = false; +exports.options = { method: 'GET', url: '', size: 5, cacheexpire: '5 minutes', cachepolicy: 0, timeout: 5 }; +exports.dateupdated = '2021-01-21 18:30d'; +exports.readme = `# HTTP route + +__Outputs__: +- first output: raw data (cache is empty or is disabled) +- second output: cached data + +If one of the outputs is disabled then automatic responce with code "503 service unavailable" is sent. + +When a request comes in bellow object is available at \`flowdata.data\`: + +\`\`\`javascript +{ + params: { id: '1' }, // params for dynamic routes, e.g. /test/{id} + query: { msg: 'Hello' }, // parsed query string, e.g. /test/1?msg=Hello + body: { test: 'OK' }, // object if json requests otherwise string + headers: {}, // headers data + session: {}, // session data + user: {}, // user data + files: [], // uploaded files + url: '/users/', // a relative URL address + referrer: '/', // referrer + mobile: false, // determines mobile device + robot: false, // determines search robots/crawlsers + language: 'en' // determines language +} +\`\`\` + +See [documentation for flags](https://docs.totaljs.com/latest/en.html#api~HttpRouteOptionsFlags~unauthorize). These method flags are set automatically e.g. \`get, post, put, patch or delete\` + +--- + +\`id:ROUTE_ID\` flag cannot be used since it's already used by this component internally`; + +exports.html = `
+
+ +
+ +
+
+
@(HTTP method)
+
+
+
@(URL address)
+
+
+
+
+
@(Additional flags)
+
@(Separate flags by comma e.g. json, authorize)
+
+
+
@(Max. request size)
+
@(In kB kilobytes)
+
+
+
@(Timeout)
+
@(In seconds.)
+
+
+
+
+
+
@(Automatically respond with 200 OK?)
+
@(If not checked you need to use HTTP response component to respond to the request.)
+
+
@(Custom headers)
+
@(Cookies)
+
+
+
+
+
+
@(Cache policy)
+
@(User instance must contain id property.)
+
+
+
@(Expiration)
+
@(E.g. 5 minutes)
+
+
+
+`; + +exports.install = function(instance) { + + var route; + + var uninstall = function(id) { + if (F.is4) { + route && route.remove(); + route = null; + } else + UNINSTALL('route', id); + }; + + instance.custom.emptyresponse = function(self) { + self.plain(); + }; + + instance.reconfigure = function() { + + var options = instance.options; + + if (!options.url) { + instance.status('Not configured', 'red'); + return; + } + + if (typeof(options.flags) === 'string') + options.flags = options.flags.split(',').trim(); + + uninstall('id:' + instance.id); + + var flags = options.flags || []; + + flags.push('id:' + instance.id); + + if (!F.is4) + flags.push(options.method.toLowerCase()); + + options.timeout && flags.push(options.timeout * 1000); + + // Make unique values + flags = flags.filter(function(v, i, a) { + if(F.is4 && v.toString().toLowerCase() === options.method.toLowerCase()) + return false; // remove method + return a.indexOf(v) === i; + }); + + options.flags = flags; + var handler = function() { + + if (instance.paused || (instance.isDisabled && (instance.isDisabled('output', 0) || instance.isDisabled('output', 1)))) { + instance.status('503 Service Unavailable'); + this.status = 503; + this.json(); + return; + } + + var key; + var self = this; + + if (instance.options.emptyresponse) { + instance.status('200 OK'); + setTimeout(instance.custom.emptyresponse, 100, self); + + if (instance.hasConnection(0)) { + var data = instance.make({ + query: self.query, + body: self.body, + session: self.session, + user: self.user, + files: self.files, + headers: self.req.headers, + url: self.url, + params: self.params + }); + instance.send2(0, data); + } + + return; + } + + switch (instance.options.cachepolicy) { + case 1: // URL + key = 'rro' + instance.id + self.url.hash(); + break; + case 2: // URL + query + case 3: // URL + query + user + key = self.url; + var keys = Object.keys(self.query); + keys.sort(); + for (var i = 0, length = keys.length; i < length; i++) + key += keys[i] + self.query[keys[i]] + '&'; + if (instance.options.cachepolicy === 3 && self.user) + key += 'iduser' + self.user.id; + key = 'rro' + instance.id + key.hash(); + break; + } + + if (key && F.cache.get2(key)) { + var data = instance.make(F.cache.get2(key)); + data.repository.controller = self; + instance.send2(1, data); + } else { + + var data = instance.make({ + query: self.query, + body: self.body, + session: self.session, + user: self.user, + files: self.files, + headers: self.req.headers, + url: self.url, + params: self.params, + mobile: self.mobile, + robot: self.robot, + referrer: self.referrer, + language: self.language + }); + + data.repository.controller = self; + instance.send2(0, data); + key && FINISHED(self.res, () => F.cache.set(key, self.$flowdata.data, instance.options.cacheexpire)); + } + }; + + if (F.is4) + route = ROUTE(options.method.toUpperCase() + ' ' + options.url, handler, flags, options.size || 5); + else + F.route(options.url, handler, flags, options.size || 5); + + instance.status('Listening', 'green'); + }; + + instance.reconfigure(); + instance.on('options', instance.reconfigure); + instance.on('close', function(){ + uninstall('id:' + instance.id); + }); +}; + +// check url exists +FLOW.trigger('httproutecheckurl', function(next, data) { + var url = data.url; + var method = data.method; + if (url[url.length - 1] !== '/') + url += '/'; + var exists = F.routes.web.findItem(r => r.urlraw === url && r.method === method); + next(exists != null); +}); + +exports.uninstall = function() { + FLOW.trigger('httproutecheckurl', null); +}; diff --git a/RVO22/flow/infosender.js b/RVO22/flow/infosender.js new file mode 100755 index 0000000..587724f --- /dev/null +++ b/RVO22/flow/infosender.js @@ -0,0 +1,81 @@ +exports.id = 'infosender'; +exports.title = 'Info sender'; +exports.version = '1.0.0'; +exports.group = 'Worksys'; +exports.color = '#2134B0'; +exports.input = 2; +exports.output = 1 +exports.icon = 'bolt'; + +const { networkInterfaces } = require('os'); + +exports.html = `
+
+
+
CSV Import
+
+
+
`; + +exports.readme = `# send all data to projects.worksys.io, required to monitor status of controller(unipi)`; + +exports.install = function(instance) { + + let id; + let allValues = {}; + let sendAllValuesInterval; + let configured = false; + + let now = new Date(); + console.log(exports.title, "INSTALLED", now.toLocaleString("sk-SK")); + + const nets = networkInterfaces(); + let ipAddresses = Object.create(null); // Or just '{}', an empty object + + for (const name of Object.keys(nets)) { + for (const net of nets[name]) { + // Skip over non-IPv4 and internal (i.e. 127.0.0.1) addresses + if (net.family === 'IPv4' && !net.internal) { + if (!ipAddresses[name]) { + ipAddresses[name] = []; + } + ipAddresses[name].push(net.address); + } + } + } + + function sendValues() { + if (!configured) return; + + if (Object.keys(allValues).length > 0) { + let dataToSend = { ...allValues }; + dataToSend.id = id; + dataToSend.ipAddresses = ipAddresses; + + instance.send(0, dataToSend); + + allValues = {}; + } + } + + instance.on("close", () => { + clearInterval(sendAllValuesInterval); + }) + + instance.on("0", _ => { + id = FLOW.GLOBALS.settings.project_id; + if (id) configured = true; + else console.log(exports.title, "InfoSender: Unable to send data, no id"); + }) + + instance.on("1", flowdata => { + allValues = { ...allValues, ...flowdata.data }; + //console.log("DATA RECEIVED", flowdata.data); + }) + + sendAllValuesInterval = setInterval(() => { + sendValues(); + }, 60000 * 3); + +} + diff --git a/RVO22/flow/modbus_reader.js b/RVO22/flow/modbus_reader.js new file mode 100755 index 0000000..d6d9dad --- /dev/null +++ b/RVO22/flow/modbus_reader.js @@ -0,0 +1,346 @@ +exports.id = 'modbus_reader'; +exports.title = 'Modbus reader'; +exports.version = '2.0.0'; +exports.group = 'Worksys'; +exports.color = '#2134B0'; +exports.input = 1; +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; +//number of phases inRVO +let phases; +//phases where voltage is 0 (set) +let noVoltage; +let energyToSwitchLamps; + +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.phases = this.buildPhases(); + + this.startSocket(); + } + + buildPhases = () => { + let a = []; + for (let i = 1; i <= phases; i++) { + a.push(`Phase_${i}_voltage`) + } + return a; + } + + startSocket = () => { + + let obj = this; + + if (this.socket) { + this.socket.removeAllListeners(); + this.socket = null; + } + + 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('Modbus_reader: Socket connection error', e); //'ECONNREFUSED' or 'ECONNRESET' ?? + }); + + this.socket.on('close', function() { + console.log('Modbus_reader: Socket connection closed - Waiting 10 seconds before connecting 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 we just start to loop devices from the beginning, or there is just 1 device in config, we wait whole timeoutInterval + if (this.indexInDeviceConfig == 0 || deviceConfig.length === 1) 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 (this.phases.includes(singleValue)) { + let l = singleValue.split("_"); + let phase = parseInt(l[1]); + + // console.log(values[singleValue], tbName); + + if (values[singleValue] == 0) { + noVoltage.add(phase); + sendNotification("modbus_reader: checkNullVoltage", tbName, "no_voltage_on_phase", { phase: phase }, "", SEND_TO.tb, instance, "voltage" + phase); + // console.log('no voltage') + } + else { + noVoltage.delete(phase); + // console.log('voltage detected') + sendNotification("modbus_reader: checkNullVoltage", tbName, "voltage_on_phase_restored", { phase: phase }, "", SEND_TO.tb, instance, "voltage" + phase); + } + } + }) + } + + /** + * function sends notification to slack and to tb, if EM total_power value changes more than numberOfNodes*15. This should show, that RVO lamps has been switched on or off + */ + lampSwitchNotification = (values) => { + + if (!values.hasOwnProperty("total_power")) return; + + const actualTotalPower = values.total_power; + + if (actualTotalPower > energyToSwitchLamps && 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 <= energyToSwitchLamps && 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; + } + + function main() { + + phases = FLOW.GLOBALS.settings.phases; + tbName = FLOW.GLOBALS.settings.rvoTbName; + noVoltage = FLOW.GLOBALS.settings.no_voltage; + energyToSwitchLamps = FLOW.GLOBALS.settings.energy_to_switch_lamps / 2.5; //half value is enought to show if lamps are turned on or off + if (deviceConfig.length) mainSocket = new SocketWithClients(); + else console.log("Modbus_reader: no modbus device in configuration"); + + // this notification is to show, that flow (unipi) has been restarted + sendNotification("modbus_reader", tbName, "flow_restart", {}, "", SEND_TO.slack, instance); + } + + instance.on("0", function(_) { + main(); + }) + +} + diff --git a/RVO22/flow/monitorconsumption.js b/RVO22/flow/monitorconsumption.js new file mode 100755 index 0000000..64cc58e --- /dev/null +++ b/RVO22/flow/monitorconsumption.js @@ -0,0 +1,156 @@ +exports.id = 'monitorconsumption'; +exports.title = 'Consumption'; +exports.version = '1.0.0'; +exports.author = 'Peter Širka'; +exports.group = 'Monitoring'; +exports.color = '#967ADC'; +exports.input = 0; +exports.output = 1; +exports.icon = 'bug'; +exports.options = { interval: 5000, enabled: true, monitorconsumption: true, monitorsize: true, monitorconnections: true, monitorfiles: true }; +exports.click = true; +exports.readme = `# Consumption monitoring + +This component measure CPU and memory consumption, open files and open connections of this application. It uses these Linux commands: \`ps\`, \`lsof\`, \`netstat\` and \`df\`. + +__Data Example__: + +\`\`\`javascript +{ + cpu: 0, // percentage + memory: 4096, // in bytes + size: 34303, // directory size in bytes + files: 34, // count of open files + connections: 343, // count of connections + uptime: '1-12:34:00' +} +\`\`\``; + +exports.html = `
+
+
+
@(Interval in milliseconds)
+
+
+
+
Monitor: Consumption + uptime
+
Monitor: Count of open files
+
Monitor: Count of open connections
+
Monitor: Directory size
+
`; + +exports.install = function(instance) { + + var current = { cpu: 0, memory: 0, files: 0, connections: 0, size: 0, uptime: '', counter: 0 }; + var tproc = null; + var Exec = require('child_process').exec; + var reg_empty = /\s{2,}/g; + var reg_appdisksize = /^[\d.,]+/; + + instance.custom.run = function() { + + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + + var arr = []; + + // Get CPU and Memory consumption + instance.options.monitorconsumption && arr.push(function(next) { + Exec('ps -p {0} -o %cpu,rss,etime'.format(process.pid), function(err, response) { + + if (err) { + instance.throw(err); + } else { + var line = response.split('\n')[1]; + line = line.trim().replace(reg_empty, ' ').split(' '); + var cpu = line[0].parseFloat(); + current.cpu = cpu.floor(1); + current.memory = line[1].parseInt2() * 1024; // kB to bytes + current.uptime = line[2]; + } + + next(); + }); + }); + + // Get count of open files + instance.options.monitorfiles && arr.push(function(next) { + Exec('lsof -a -p {0} | wc -l'.format(process.pid), function(err, response) { + if (err) + instance.throw(err); + else + current.files = response.trim().parseInt2(); + next(); + }); + }); + + // Get count of opened network connections + instance.options.monitorconnections && arr.push(function(next) { + Exec('netstat -an | grep :{0} | wc -l'.format(F.port), function(err, response) { + if (err) { + instance.throw(err); + } else { + current.connections = response.trim().parseInt2() - 1; + if (current.connections < 0) + current.connections = 0; + } + next(); + }); + }); + + // Get directory size + instance.options.monitorsize && current.counter % 5 !== 0 && arr.push(function(next) { + Exec('du -hsb ' + process.cwd(), function(err, response) { + if (err) { + instance.throw(err); + } else { + var match = response.trim().match(reg_appdisksize); + match && (current.size = match.toString().trim().parseInt2()); + } + next(); + }); + }); + + arr.async(function() { + + tproc && clearTimeout(tproc); + + if (instance.options.enabled) { + tproc = setTimeout(instance.custom.run, instance.options.interval); + instance.send2(current); + } + + instance.custom.status(); + current.counter++; + }); + }; + + instance.custom.status = function() { + if (instance.options.enabled) + instance.status('{0}% / {1}'.format(current.cpu, current.memory.filesize())); + else + instance.status('Disabled', 'red'); + }; + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + + if (instance.options.enabled) { + current.counter = 0; + instance.custom.run(); + } + + }); + + instance.on('close', function() { + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + }); + + setTimeout(instance.custom.run, 1000); +}; \ No newline at end of file diff --git a/RVO22/flow/monitordisk.js b/RVO22/flow/monitordisk.js new file mode 100755 index 0000000..f4fdaa0 --- /dev/null +++ b/RVO22/flow/monitordisk.js @@ -0,0 +1,96 @@ +exports.id = 'monitordisk'; +exports.title = 'Disk'; +exports.version = '1.0.0'; +exports.author = 'Peter Širka'; +exports.group = 'Monitoring'; +exports.color = '#F6BB42'; +exports.output = 1; +exports.icon = 'hdd-o'; +exports.click = true; +exports.options = { interval: 8000, path: '/', enabled: true }; +exports.readme = `# Disk monitoring + +This component monitors disk \`bytes\` consumption in Linux systems. It uses \`df\` command. + +__Data Example__: + +\`\`\`javascript +{ + total: 474549649408, + used: 39125245952, + free: 411294994432 +} +\`\`\``; + +exports.html = `
+
+
+
@(Interval in milliseconds)
+
+
+
@(Path)
+
+
+
`; + +exports.install = function(instance) { + + var current = { total: 0, used: 0, free: 0, path: '', type: '', percentUsed: 0 }; + var tproc = null; + + instance.custom.run = function() { + + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + + if (!instance.options.enabled) + return; + + require('child_process').exec('df -hTB1 ' + instance.options.path, function(err, response) { + + tproc = setTimeout(instance.custom.run, instance.options.interval); + + if (err) { + instance.error(err); + return; + } + + response.parseTerminal(function(line) { + if (line[0][0] !== '/') + return; + current.total = line[2].parseInt(); + current.free = line[4].parseInt(); + current.used = line[3].parseInt(); + current.path = instance.options.path || '/'; + current.type = line[1]; + current.percentUsed = line[5]; + instance.custom.status(); + instance.send2(current); + }); + }); + }; + + instance.custom.status = function() { + if (instance.options.enabled) + instance.status(current.free.filesize() + ' / ' + current.total.filesize()); + else + instance.status('Disabled', 'red'); + }; + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + instance.options.enabled && instance.custom.run(); + }); + + instance.on('close', function() { + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + }); + + setTimeout(instance.custom.run, 1000); +}; \ No newline at end of file diff --git a/RVO22/flow/monitormemory.js b/RVO22/flow/monitormemory.js new file mode 100755 index 0000000..2decbc4 --- /dev/null +++ b/RVO22/flow/monitormemory.js @@ -0,0 +1,87 @@ +exports.id = 'monitormemory'; +exports.title = 'Memory'; +exports.version = '1.0.0'; +exports.author = 'Peter Širka'; +exports.group = 'Monitoring'; +exports.color = '#F6BB42'; +exports.output = 1; +exports.click = true; +exports.icon = 'microchip'; +exports.options = { interval: 8000, enabled: true }; +exports.readme = `# Memory monitoring + +This component monitors memory \`bytes\` consumption in Linux systems. It uses \`free\` command. + +__Data Example__: + +\`\`\`javascript +{ + total: 33558769664, + used: 1998868480, + free: 2653708288 +} +\`\`\``; + +exports.html = `
+
+
+
@(Interval in milliseconds)
+
+
+
`; + +exports.install = function(instance) { + + var current = { total: 0, used: 0, free: 0 }; + var tproc = null; + + instance.custom.run = function() { + + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + + if (!instance.options.enabled) + return; + + require('child_process').exec('free -b -t', function(err, response) { + + tproc = setTimeout(instance.custom.run, instance.options.interval); + + if (err) { + instance.error(err); + return; + } + + var memory = response.split('\n')[1].match(/\d+/g); + current.total = memory[0].parseInt(); + current.used = memory[1].parseInt() - memory[3].parseInt(); + current.free = current.total - current.used; + instance.custom.status(); + instance.send2(current); + }); + }; + + instance.custom.status = function() { + if (instance.options.enabled) + instance.status(current.free.filesize() + ' / ' + current.total.filesize()); + else + instance.status('Disabled', 'red'); + }; + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + instance.options.enabled && instance.custom.run(); + }); + + instance.on('close', function() { + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + }); + + setTimeout(instance.custom.run, 1000); +}; \ No newline at end of file diff --git a/RVO22/flow/nodesdb_changecheck.js b/RVO22/flow/nodesdb_changecheck.js new file mode 100755 index 0000000..9adab62 --- /dev/null +++ b/RVO22/flow/nodesdb_changecheck.js @@ -0,0 +1,77 @@ +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 = 2; +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); + } + } + + //kedze do slacku posielame stringy, na cloud musime previest vsetky stringy spat na objekty: + // Funkcia na parsovanie všetkých reťazcov v poli + const parseArray = (arr) => { + return arr.map(jsonString => JSON.parse(jsonString)); + }; + + 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); + if (FLOW.GLOBALS.settings.send_changed_node_numbers) instance.send(1, { aktualneNody: parseArray(zmenene), originalne: parseArray(Array.from(set2)) }); + } + 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/RVO22/flow/show_dbdata.js b/RVO22/flow/show_dbdata.js new file mode 100755 index 0000000..1e23ff7 --- /dev/null +++ b/RVO22/flow/show_dbdata.js @@ -0,0 +1,243 @@ +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 = 8; +exports.output = 1; + +const { exec } = require('child_process'); + +exports.install = 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 }) + }) + instance.on("5", _ => { + exec("sudo tail -n 25 monitor.txt", (err, stdout, stderr) => { + if (err || stderr) instance.send(0, { err, stderr }); + else instance.send(0, stdout); + }) + }) + instance.on("6", _ => { + exec("sudo tail -n 25 err.txt", (err, stdout, stderr) => { + if (err || stderr) instance.send(0, { err, stderr }); + else instance.send(0, stdout); + }) + }) + instance.on("7", _ => { + instance.send(0, FLOW.deviceStatus); + }) +}; + + +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/RVO22/flow/slack_filter.js b/RVO22/flow/slack_filter.js new file mode 100755 index 0000000..6618523 --- /dev/null +++ b/RVO22/flow/slack_filter.js @@ -0,0 +1,188 @@ +exports.id = 'slack_filter'; +exports.title = 'Slack Filter'; +exports.group = 'Citysys'; +exports.color = '#30E193'; +exports.input = 2; +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 = `
+
+
+
@(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('0', 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']['en']; + 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"] = []; + } + + instance.options.name = FLOW.GLOBALS.settings.rvo_name; + if (instance.options.name) { + instance.status('Running'); + running = true; + } else { + instance.status('Please run options again', 'red'); + running = false; + } + } catch (e) { + instance.error('Citysys connector: ' + e.message); + } + }; + + instance.on('options', instance.reconfigure); + + instance.on("1", _ => { + instance.reconfigure(); + }) +}; diff --git a/RVO22/flow/thermometer.js b/RVO22/flow/thermometer.js new file mode 100755 index 0000000..fc7074d --- /dev/null +++ b/RVO22/flow/thermometer.js @@ -0,0 +1,99 @@ +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 = 5;//minutes +let NUMBER_OF_FAILURES_TO_SEND_ERROR = 13; + +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) => { + + 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); + setTimeout(main, 20000); + }) +}; diff --git a/RVO22/flow/trigger.js b/RVO22/flow/trigger.js new file mode 100755 index 0000000..27545a8 --- /dev/null +++ b/RVO22/flow/trigger.js @@ -0,0 +1,79 @@ +exports.id = 'trigger'; +exports.title = 'Trigger'; +exports.group = 'Inputs'; +exports.color = '#F6BB42'; +exports.click = true; +exports.output = 1; +exports.version = '1.1.0'; +exports.author = 'Martin Smola'; +exports.icon = 'play'; + +exports.html = `
+
@(Data type (String by default))
+
@(Data)
+
Trigger 5s after initialization.
+
@(Useful when there's a need to run certain flow when the app restarts, etc.)
+
`; + +exports.readme = `# Trigger + +- Clicking on the component starts the chain +- Settings allows to set a data-type and a value`; + +exports.install = function(instance) { + + var value; + + instance.on('click', () => instance.send2(value)); + + instance.reconfigure = function() { + var options = instance.options; + value = null; + switch (options.datatype) { + case 'integer': + value = options.data.parseInt2('error'); + value = value === 'error' ? NaN : value; + break; + case 'float': + value = options.data.parseFloat2('error'); + value = value === 'error' ? NaN : value; + break; + case 'date': + options.data = options.data.toString(); + var num = options.data.parseInt('error'); + num === 'error' && (num = options.data.parseDate('error')); + num === 'error' && (num = null); + value = num ? new Date(num).toUTCString() : num; + break; + case 'object': + try { + value = (new Function('return ' + options.data))(); + } catch (e) { + instance.error(e); + } + break; + case 'boolean': + value = options.data.parseBoolean(); + break; + case 'buffer': + try { + value = U.createBuffer(options.data); + } catch (e) { + instance.error(e); + } + break; + case 'string': + default: + value = '' + (options.data || ''); + break; + } + }; + + instance.on('options', instance.reconfigure); + instance.reconfigure(); + + if (instance.options.restart) + setTimeout(function(){ + instance.send2(value); + }, 5000); +}; diff --git a/RVO22/flow/variables.txt b/RVO22/flow/variables.txt new file mode 100755 index 0000000..e69de29 diff --git a/RVO22/flow/virtualwirein.js b/RVO22/flow/virtualwirein.js new file mode 100755 index 0000000..38a4e42 --- /dev/null +++ b/RVO22/flow/virtualwirein.js @@ -0,0 +1,43 @@ +exports.id = 'virtualwirein'; +exports.title = 'Virtual wire in'; +exports.version = '1.0.0'; +exports.author = 'Martin Smola'; +exports.color = '#303E4D'; +exports.icon = 'sign-in'; +exports.input = false; +exports.output = 1; +exports.options = {}; +exports.readme = `# Virtual wire in + +When the wires between the components are mess it's time to use Virtual wire.`; + +exports.html = `
+
@(Wire name)
+
+`; + +exports.install = function(instance) { + + instance.custom.reconfigure = function(options){ + if (instance.options.wirename) { + instance.status(instance.options.wirename); + } else + instance.status('Not configured', 'red'); + }; + + ON('virtualwire', function(wirename, flowdata){ + if (instance.options.wirename && instance.options.wirename === wirename) + instance.send(flowdata); + }); + + instance.on('options', instance.custom.reconfigure); + instance.custom.reconfigure(); +}; diff --git a/RVO22/flow/virtualwireout.js b/RVO22/flow/virtualwireout.js new file mode 100755 index 0000000..94a1e4f --- /dev/null +++ b/RVO22/flow/virtualwireout.js @@ -0,0 +1,41 @@ +exports.id = 'virtualwireout'; +exports.title = 'Virtual wire out'; +exports.version = '1.0.0'; +exports.author = 'Martin Smola'; +exports.color = '#303E4D'; +exports.icon = 'sign-out'; +exports.input = true; +exports.options = {}; +exports.readme = `# Virtual wire out + +When the wires between the components are mess it's time to use Virtual wire.`; + +exports.html = `
+
@(Wire name)
+
+`; + +exports.install = function(instance) { + + instance.custom.reconfigure = function(){ + if (instance.options.wirename) { + instance.status(instance.options.wirename); + } else + instance.status('Not configured', 'red'); + }; + + instance.on('data', function(flowdata) { + EMIT('virtualwire', instance.options.wirename, flowdata); + }); + + instance.on('options', instance.custom.reconfigure); + instance.custom.reconfigure(); +}; diff --git a/RVO22/flow/wsmqttpublish.js b/RVO22/flow/wsmqttpublish.js new file mode 100755 index 0000000..0eba804 --- /dev/null +++ b/RVO22/flow/wsmqttpublish.js @@ -0,0 +1,448 @@ +exports.id = 'wsmqttpublish'; +exports.title = 'WS MQTT publish'; +exports.group = 'MQTT'; +exports.color = '#888600'; +exports.version = '1.0.2'; +exports.icon = 'sign-out'; +exports.input = 2; +exports.output = 3; +exports.options = { host: 'tb-stage.worksys.io', port: 1883, clientid: "", username: "" }; + +exports.html = `
+
+
+
Hostname or IP address (if not empty - setting will override db setting)
+
+
+
Port
+
+
+
+
+
@(Client id)
+
+
+
@(Username)
+
+
+
`; + + +exports.readme = ` +# WS MQTT Publish + +Version 1.0.3. + +Added: +- database collections, +- 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 = { + debug: 0, + rpcCall: 1, + services: 2 +} + +//CONFIG +let createTelemetryBackup = true; +let saveTelemetryOnError = true;//backup_on_failure overrides this value +//------------------------ + +let rollers; +if (createTelemetryBackup) rollers = require('streamroller'); + +const noSqlFileSizeLimit = 4194304;//use 5MB - 4194304 +let insertNoSqlCounter = 0; +let insertBackupNoSqlCounter = 0; +let processingData = false; + +let backup_on_failure = false;//== saveTelemetryOnError - create backup client 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; + +process.on('uncaughtException', function(err) { + + errLogger.error('uncaughtException:', err.message) + errLogger.error(err.stack); + + //TODO + //send to service + + //process.exit(1); +}) + +const nosql = NOSQL('tbdata'); +const nosqlBackup = NOSQL('/backup/tbdata'); + + +exports.install = function(instance) { + + var client; + var opts; + var clientReady = false; + + // wsmqtt status for notification purposes on projects.worksys.io database + let wsmqttName = null; + let sendWsStatusVar = null; + let wsmqtt_status = 'disconnected'; + + 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'; + } + + function sendWsStatus() { + instance.send(SEND_TO.services, { [wsmqttName]: wsmqtt_status }); + } + + + function main() { + if (!FLOW.dbLoaded) return; + + loadSettings(); + clearInterval(sendWsStatus); + sendWsStatusVar = setInterval(sendWsStatus, 180000); + } + + //set opts according to db settings + function loadSettings() { + + if (instance.options.host !== "") { + //override settings from database + var o = instance.options; + opts = { + host: o.host, + port: o.port, + clientId: o.clientid, + username: o.username, + rejectUnauthorized: false, + resubscribe: false + }; + + wsmqttName = getWsmqttName(o.host); + + console.log("wsmqttpublich -> loadSettings from instance.options", instance.options); + } + else { + + const SETTINGS = FLOW.GLOBALS.settings; + backup_on_failure = SETTINGS.backup_on_failure; + saveTelemetryOnError = backup_on_failure; + + restore_from_backup = SETTINGS.restore_from_backup; + restore_backup_wait = SETTINGS.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; + + opts = { + host: mqtt_host, + port: mqtt_port, + keepalive: 10, + clientId: mqtt_clientid, + username: mqtt_username, + rejectUnauthorized: false, + resubscribe: false + }; + + wsmqttName = getWsmqttName(mqtt_host); + } + + connectToTbServer(); + } + + function connectToTbServer() { + 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"); + //monitor.info("MQTT client connected"); + + sendClientError = true; + clientReady = true; + wsmqtt_status = 'connected'; + }); + + client.on('reconnect', function() { + instance.status("Reconnecting", "yellow"); + clientReady = false; + }); + + client.on('message', function(topic, message) { + // message is type of buffer + message = message.toString(); + if (message[0] === '{') { + TRY(function() { + + message = JSON.parse(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 } }); + } + + }, () => instance.debug('MQTT: Error parsing data', message)); + } + + instance.send(SEND_TO.rpcCall, { "topic": topic, "content": message }); + }); + + client.on('close', function() { + clientReady = false; + wsmqtt_status = 'disconnected'; + + instance.status("Disconnected", "red"); + instance.send(SEND_TO.debug, { "message": "Client CLOSE signal received !" }); + }); + + client.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; + wsmqtt_status = 'disconnected'; + }); + + } + + + instance.on("0", _ => { + main(); + }) + + + instance.on('1', function(data) { + + if (clientReady) { + //do we have some data in backup file? if any, process data from database + if (saveTelemetryOnError) { + //read telemetry data and send back to server + if (!processingData) processDataFromDatabase(); + } + + let stringifiedJson = JSON.stringify(data.data); + client.publish("v1/gateway/telemetry", stringifiedJson, { qos: 1 }); + + //backup telemetry + if (createTelemetryBackup) { + data.data.id = UID(); + nosqlBackup.insert(data.data); + + insertBackupNoSqlCounter++; + if (insertBackupNoSqlCounter > 150) { + let options = { compress: true }; + let path = __dirname + "/../databases/backup/tbdata.nosql"; + var stream = new rollers.RollingFileStream(path, noSqlFileSizeLimit, 150, options); + stream.write(""); + stream.end(); + + insertBackupNoSqlCounter = 0; + } + } + + } + 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 (saveTelemetryOnError) { + //create new file from tbdata.nosql, if file size exceeds given limit, and clear tbdata.nosql + makeBackupFromDbFile(); + + //write to tb + data.data.id = UID(); + nosql.insert(data.data); + } + } + }); + + + instance.close = function(done) { + if (clientReady) { + client.end(); + clearInterval(sendWsStatusVar); + } + }; + + + function getDbBackupFileCounter(type) { + var files = fs.readdirSync(__dirname + "/../databases"); + + let counter = 0; + for (var i = 0; i < files.length; i++) { + + if (files[i] == "tbdata.nosql") continue; + + if (files[i].endsWith(".nosql")) { + + let pos = files[i].indexOf("."); + if (pos > -1) { + + let fileCounter = counter; + let firstDigit = files[i].slice(0, pos); + + fileCounter = parseInt(firstDigit); + if (isNaN(fileCounter)) fileCounter = 0; + //console.log("getDbBackupFileCounter digit:", files[i], firstDigit, fileCounter, isNaN(fileCounter), type); + + if (type == "max") { + if (fileCounter > counter) { + counter = fileCounter; + } + } + else if (type == "min") { + if (counter == 0) counter = fileCounter; + + if (fileCounter < counter) { + counter = fileCounter; + } + } + } + } + + } + + if (type == "max") counter++; + + return counter; + } + + const makeBackupFromDbFile = async () => { + + if (!saveTelemetryOnError) return; + + //to avoid large file: tbdata.nosql + + //init value is 0! + if (insertNoSqlCounter > 0) { + --insertNoSqlCounter; + return; + } + + insertNoSqlCounter = 100; + + let source = __dirname + "/../databases/tbdata.nosql"; + + var stats = fs.statSync(source); + var fileSizeInBytes = stats.size; + + if (fileSizeInBytes > noSqlFileSizeLimit) { + + let counter = 1; + counter = getDbBackupFileCounter("max"); + + let destination = __dirname + "/../databases/" + counter + "." + "tbdata.nosql"; + + //make backup file + fs.copyFileSync(source, destination); + //fs.renameSync(p, p + "." + counter); + + //clear tbdata.nosql + fs.writeFileSync(source, ""); + fs.truncateSync(source, 0); + + } + } + + const processDataFromDatabase = async () => { + + if (restore_from_backup <= 0) return; + + //calculate diff + const now = new Date(); + let currentTime = now.getTime(); + let diff = currentTime - lastRestoreTime; + + if ((diff / 1000) < restore_backup_wait) { + //console.log("*********restore_backup_wait", diff, restore_backup_wait); + return; + } + + processingData = true; + + //get filename to process + let counter = getDbBackupFileCounter("min"); + + //we have some backup files + let dataBase = 'tbdata'; + + var nosql; + if (counter == 0) dataBase = 'tbdata'; + else dataBase = counter + "." + 'tbdata'; + + nosql = NOSQL(dataBase); + + //select all data - use limit restore_from_backup + let records = await promisifyBuilder(nosql.find().take(restore_from_backup)); + + for (let i = 0; i < records.length; i++) { + if (clientReady) { + + let item = records[i]; + let id = item.id; + + if (id !== undefined) { + //console.log("------------processDataFromDatabase - remove", id, dataBase, i); + + try { + + let message = JSON.parse(JSON.stringify(item)); + delete message.id; + + client.publish("v1/gateway/telemetry", JSON.stringify(message), { qos: 1 }); + + //remove from database + await promisifyBuilder(nosql.remove().where("id", id)); + + } catch (error) { + //process error + console.log("processDataFromDatabase", error); + } + + } + + } + else { + processingData = false; + return; + } + } + + if (records.length > 0) { + //clean backup file + if (counter > 0) nosql.clean(); + } + + //no data in db, remove + if (records.length == 0) { + if (counter > 0) nosql.drop(); + } + + const d = new Date(); + lastRestoreTime = d.getTime(); + + processingData = false; + + } + + instance.on('options', main); + //instance.reconfigure(); +}; diff --git a/RVO22/monitor.txt b/RVO22/monitor.txt new file mode 100755 index 0000000..e8c5dd1 --- /dev/null +++ b/RVO22/monitor.txt @@ -0,0 +1,314 @@ +[2025-10-09T16:47:12.684] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-09T16:47:18.031] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-09T16:47:18.036] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-09T16:47:18.037] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-09T16:47:18.038] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-09T16:47:18.042] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T16:47:18.043] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-10-10T05:32:00.042Z +[2025-10-09T16:47:18.045] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-10-09T16:45:00.044Z +[2025-10-09T16:47:18.045] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T16:47:18.046] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-10-09T16:47:18.047] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-09T16:47:18.048] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-09T16:47:18.050] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T16:47:18.051] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-10-10T05:32:00.051Z +[2025-10-09T16:47:18.052] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-10-09T16:45:00.052Z +[2025-10-09T16:47:18.052] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T16:47:18.053] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-10-09T16:47:18.054] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-09T16:47:18.055] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-09T16:47:18.057] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T16:47:18.058] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-10-10T05:32:00.058Z +[2025-10-09T16:47:18.059] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-10-09T16:45:00.058Z +[2025-10-09T16:47:18.059] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T16:47:18.060] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-10-09T16:47:18.064] [INFO] monitorLogs - tasks created: 602 +[2025-10-09T16:47:18.067] [INFO] monitorLogs - -->FLOW bol spustený rDbQ84xzwgdqEoPm3kbEXy09anOZY1RXyBv2LVM6 2025-08-08 +[2025-10-09T16:47:23.074] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-09T18:25:23.831] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-09T18:25:23.835] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-09T18:25:23.837] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-09T18:59:17.331] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-09T18:59:22.677] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-09T18:59:22.682] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-09T18:59:22.683] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-09T18:59:22.684] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-09T18:59:22.688] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T18:59:22.689] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-10-10T05:32:00.688Z +[2025-10-09T18:59:22.691] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-10-10T16:45:00.690Z +[2025-10-09T18:59:22.691] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T18:59:22.693] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-10-09T18:59:22.693] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-09T18:59:22.694] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-09T18:59:22.696] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T18:59:22.697] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-10-10T05:32:00.697Z +[2025-10-09T18:59:22.698] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-10-10T16:45:00.698Z +[2025-10-09T18:59:22.698] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T18:59:22.699] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-10-09T18:59:22.700] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-09T18:59:22.701] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-09T18:59:22.703] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T18:59:22.704] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-10-10T05:32:00.704Z +[2025-10-09T18:59:22.705] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-10-10T16:45:00.704Z +[2025-10-09T18:59:22.705] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T18:59:22.706] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-10-09T18:59:22.710] [INFO] monitorLogs - tasks created: 602 +[2025-10-09T18:59:22.713] [INFO] monitorLogs - -->FLOW bol spustený rDbQ84xzwgdqEoPm3kbEXy09anOZY1RXyBv2LVM6 2025-08-08 +[2025-10-09T18:59:27.719] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-10T03:59:25.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-10 03:59:25 +[2025-10-10T06:54:35.412] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-10T06:54:35.416] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-10T06:54:35.418] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-10T18:21:54.271] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-10T18:21:54.276] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-10T18:21:54.278] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-11T03:59:26.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-11 03:59:26 +[2025-10-11T06:56:58.203] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-11T06:56:58.207] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-11T06:56:58.209] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-11T18:24:16.347] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-11T18:24:16.363] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-11T18:24:16.366] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-12T03:59:28.031] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-12 03:59:28 +[2025-10-12T06:54:19.876] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-12T06:54:19.880] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-12T06:54:19.882] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-12T18:21:37.917] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-12T18:21:37.919] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-12T18:21:37.921] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-13T03:59:30.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-13 03:59:30 +[2025-10-13T06:54:12.460] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-13T06:54:12.464] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-13T06:54:12.466] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-13T09:21:17.341] [INFO] monitorLogs - turnLine on - (line, SETTINGS.maintenance_mode) 0 true command received from platform +[2025-10-13T09:21:25.974] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false command received from platform +[2025-10-13T09:21:33.653] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false command received from platform +[2025-10-13T09:21:41.652] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false command received from platform +[2025-10-13T09:27:15.732] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false command received from platform +[2025-10-13T09:27:21.807] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false command received from platform +[2025-10-13T09:27:26.286] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false command received from platform +[2025-10-13T09:27:31.408] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false command received from platform +[2025-10-13T18:29:02.629] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-13T18:29:02.638] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-13T18:29:02.639] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-14T03:59:31.019] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-14 03:59:31 +[2025-10-14T06:54:03.752] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-14T06:54:03.755] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-14T06:54:03.757] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-14T18:16:20.880] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-14T18:16:20.893] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-14T18:16:20.895] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-15T03:59:33.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-15 03:59:33 +[2025-10-15T06:58:56.310] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-15T06:58:56.314] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-15T06:58:56.316] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-15T14:13:19.185] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-15T14:13:24.538] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-15T14:13:24.543] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-15T14:13:24.544] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-15T14:13:24.545] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-15T14:13:24.549] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-15T14:13:24.550] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-10-16T05:41:00.550Z +[2025-10-15T14:13:24.552] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-10-15T16:33:00.551Z +[2025-10-15T14:13:24.552] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:41', name: 'luxOff' }, + { value: 1, start_time: '18:33', name: 'luxOn' } +] +[2025-10-15T14:13:24.554] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-10-15T14:13:24.554] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-15T14:13:24.555] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-15T14:13:24.557] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-15T14:13:24.558] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-10-16T05:41:00.558Z +[2025-10-15T14:13:24.559] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-10-15T16:33:00.559Z +[2025-10-15T14:13:24.560] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:41', name: 'luxOff' }, + { value: 1, start_time: '18:33', name: 'luxOn' } +] +[2025-10-15T14:13:24.561] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-10-15T14:13:24.561] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-15T14:13:24.562] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-15T14:13:24.564] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-15T14:13:24.565] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-10-16T05:41:00.565Z +[2025-10-15T14:13:24.566] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-10-15T16:33:00.566Z +[2025-10-15T14:13:24.567] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:41', name: 'luxOff' }, + { value: 1, start_time: '18:33', name: 'luxOn' } +] +[2025-10-15T14:13:24.568] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-10-15T14:13:24.589] [INFO] monitorLogs - tasks created: 602 +[2025-10-15T14:13:24.592] [INFO] monitorLogs - -->FLOW bol spustený rDbQ84xzwgdqEoPm3kbEXy09anOZY1RXyBv2LVM6 2025-10-08 +[2025-10-15T14:13:29.599] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-15T18:17:00.178] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-15T18:17:00.184] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-15T18:17:00.186] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor diff --git a/RVO22/package-lock.json b/RVO22/package-lock.json new file mode 100755 index 0000000..3c5c1ba --- /dev/null +++ b/RVO22/package-lock.json @@ -0,0 +1,2139 @@ +{ + "name": "emptyproject", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "emptyproject", + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "bitwise": "^2.1.0", + "easy-crc": "0.0.2", + "jsmodbus": "^4.0.6", + "log4js": "^6.3.0", + "moment": "^2.30.1", + "mqtt": "^4.2.6", + "nodemailer": "^6.9.7", + "serialport": "^9.2.8", + "total.js": "^3.4.13" + } + }, + "node_modules/@serialport/binding-abstract": { + "version": "9.2.3", + "resolved": "https://registry.npmjs.org/@serialport/binding-abstract/-/binding-abstract-9.2.3.tgz", + "integrity": "sha512-cQs9tbIlG3P0IrOWyVirqlhWuJ7Ms2Zh9m2108z6Y5UW/iVj6wEOiW8EmK9QX9jmJXYllE7wgGgvVozP5oCj3w==", + "dependencies": { + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/binding-mock": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/binding-mock/-/binding-mock-9.2.4.tgz", + "integrity": "sha512-dpEhACCs44oQhh6ajJfJdvQdK38Vq0N4W6iD/gdplglDCK7qXRQCMUjJIeKdS/HSEiWkC3bwumUhUufdsOyT4g==", + "dependencies": { + "@serialport/binding-abstract": "9.2.3", + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/bindings": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/@serialport/bindings/-/bindings-9.2.8.tgz", + "integrity": "sha512-hSLxTe0tADZ3LMMGwvEJWOC/TaFQTyPeFalUCsJ1lSQ0k6bPF04JwrtB/C81GetmDBTNRY0GlD0SNtKCc7Dr5g==", + "hasInstallScript": true, + "dependencies": { + "@serialport/binding-abstract": "9.2.3", + "@serialport/parser-readline": "9.2.4", + "bindings": "^1.5.0", + "debug": "^4.3.2", + "nan": "^2.15.0", + "prebuild-install": "^7.0.0" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-byte-length": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-byte-length/-/parser-byte-length-9.2.4.tgz", + "integrity": "sha512-sQD/iw4ZMU3xW9PLi0/GlvU6Y623jGeWecbMkO7izUo/6P7gtfv1c9ikd5h0kwL8AoAOpQA1lxdHIKox+umBUg==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-cctalk": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-cctalk/-/parser-cctalk-9.2.4.tgz", + "integrity": "sha512-T4TU5vQMwmo9AB3gQLFDWbfJXlW5jd9guEsB/nqKjFHTv0FXPdZ7DQ2TpSp8RnHWxU3GX6kYTaDO20BKzc8GPQ==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-delimiter": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-delimiter/-/parser-delimiter-9.2.4.tgz", + "integrity": "sha512-4nvTAoYAgkxFiXrkI+3CA49Yd43CODjeszh89EK+I9c8wOZ+etZduRCzINYPiy26g7zO+GRAb9FoPCsY+sYcbQ==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-inter-byte-timeout": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-inter-byte-timeout/-/parser-inter-byte-timeout-9.2.4.tgz", + "integrity": "sha512-SOAdvr0oBQIOCXX198hiTlxs4JTKg9j5piapw5tNq52fwDOWdbYrFneT/wN04UTMKaDrJuEvXq6T4rv4j7nJ5A==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-readline": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-readline/-/parser-readline-9.2.4.tgz", + "integrity": "sha512-Z1/qrZTQUVhNSJP1hd9YfDvq0o7d87rNwAjjRKbVpa7Qi51tG5BnKt43IV3NFMyBlVcRe0rnIb3tJu57E0SOwg==", + "dependencies": { + "@serialport/parser-delimiter": "9.2.4" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-ready": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-ready/-/parser-ready-9.2.4.tgz", + "integrity": "sha512-Pyi94Itjl6qAURwIZr/gmZpMAyTmKXThm6vL5DoAWGQjcRHWB0gwv2TY2v7N+mQLJYUKU3cMnvnATXxHm7xjxw==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-regex": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-regex/-/parser-regex-9.2.4.tgz", + "integrity": "sha512-sI/cVvPOYz+Dbv4ZdnW16qAwvXiFf/1pGASQdbveRTlgJDdz7sRNlCBifzfTN2xljwvCTZYqiudKvDdC1TepRQ==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/stream": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/stream/-/stream-9.2.4.tgz", + "integrity": "sha512-bLye8Ub4vUFQGmkh8qEqehr7SE7EJs2yDs0h9jzuL5oKi+F34CFmWkEErO8GAOQ8YNn7p6b3GxUgs+0BrHHDZQ==", + "dependencies": { + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "node_modules/are-we-there-yet": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", + "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/base64-js": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", + "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==" + }, + "node_modules/bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "dependencies": { + "file-uri-to-path": "1.0.0" + } + }, + "node_modules/bitwise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/bitwise/-/bitwise-2.1.0.tgz", + "integrity": "sha512-XKgAhMXCh4H/3oNwAHAsAO0iC89s9cOiumgYwSHjSobGWxYjv62YhkL9QEdvGP151xypCtMlAfKK79GEcd2eRQ==" + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/bl/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/buffer": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz", + "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==", + "dependencies": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + }, + "node_modules/buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" + }, + "node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, + "node_modules/code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/commist": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/commist/-/commist-1.1.0.tgz", + "integrity": "sha512-rraC8NXWOEjhADbZe9QBNzLAN5Q3fsTPQtBV+fEVj6xKIgDgNiEVE6ZNfHpZOqfQ21YUzfVNUXLOEZquYvQPPg==", + "dependencies": { + "leven": "^2.1.0", + "minimist": "^1.1.0" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "node_modules/concat-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", + "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", + "engines": [ + "node >= 6.0" + ], + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.0.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/concat-stream/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" + }, + "node_modules/core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "node_modules/crc": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/crc/-/crc-3.4.0.tgz", + "integrity": "sha512-ycVC2+4/DLgXXq7QweYi2znhqDuZz6P5TQXnkQo8v15XY/5p/IWeZwsSE31Ifo8w15b8TWLsqhXOjXyilHuQxw==" + }, + "node_modules/date-format": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.11.tgz", + "integrity": "sha512-VS20KRyorrbMCQmpdl2hg5KaOUsda1RbnsJg461FfrcyCUg+pkd0b40BSW4niQyTheww4DBXQnS7HwSrKkipLw==", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" + }, + "node_modules/detect-libc": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz", + "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==", + "engines": { + "node": ">=8" + } + }, + "node_modules/duplexify": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.2.tgz", + "integrity": "sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw==", + "dependencies": { + "end-of-stream": "^1.4.1", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1", + "stream-shift": "^1.0.0" + } + }, + "node_modules/duplexify/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/easy-crc": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/easy-crc/-/easy-crc-0.0.2.tgz", + "integrity": "sha512-h6eqIdhJRe0p271/xZJbM/0klCi13mW5IB7ZEzEGH11yV4QXWAkD4yPErz0fXdhFrd6sZ4Q1k5Iky2kMsMNePw==" + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" + }, + "node_modules/flatted": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", + "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==" + }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, + "node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "node_modules/gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha512-14x4kjc6lkD3ltw589k0NrPD6cCNTD6CWoVUNpB85+DrtONoZn+Rug6xZU5RvSC4+TZPxA5AnBibQYAvZn41Hg==", + "dependencies": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "node_modules/github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==" + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" + }, + "node_modules/has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" + }, + "node_modules/help-me": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/help-me/-/help-me-3.0.0.tgz", + "integrity": "sha512-hx73jClhyk910sidBB7ERlnhMlFsJJIBqSVMFDwPN8o2v9nmp5KgLq1Xz1Bf1fCMMZ6mPrX159iG0VLy/fPMtQ==", + "dependencies": { + "glob": "^7.1.6", + "readable-stream": "^3.6.0" + } + }, + "node_modules/help-me/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, + "node_modules/is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==", + "dependencies": { + "number-is-nan": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "node_modules/js-sdsl": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz", + "integrity": "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/js-sdsl" + } + }, + "node_modules/jsmodbus": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/jsmodbus/-/jsmodbus-4.0.6.tgz", + "integrity": "sha512-gCmjoaERErK5Rn9Lu/BN07fY13MoWV7JKgGzrnkPlQPdPxYcwDhLtYcmpFFpZ4J9NPZZBSezi1UkLZO/DnNppA==", + "dependencies": { + "crc": "3.4.0", + "debug": "^3.1.0" + }, + "bin": { + "jsmodbus": "bin/jsmodbus.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/jsmodbus/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/leven": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", + "integrity": "sha1-wuep93IJTe6dNCAq6KzORoeHVYA=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/log4js": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.5.2.tgz", + "integrity": "sha512-DXtpNtt+KDOMT7RHUDIur/WsSA3rntlUh9Zg4XCdV42wUuMmbFkl38+LZ92Z5QvQA7mD5kAVkLiBSEH/tvUB8A==", + "dependencies": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "flatted": "^3.2.5", + "rfdc": "^1.3.0", + "streamroller": "^3.1.1" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" + }, + "node_modules/moment": { + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", + "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==", + "engines": { + "node": "*" + } + }, + "node_modules/mqtt": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/mqtt/-/mqtt-4.3.7.tgz", + "integrity": "sha512-ew3qwG/TJRorTz47eW46vZ5oBw5MEYbQZVaEji44j5lAUSQSqIEoul7Kua/BatBW0H0kKQcC9kwUHa1qzaWHSw==", + "dependencies": { + "commist": "^1.0.0", + "concat-stream": "^2.0.0", + "debug": "^4.1.1", + "duplexify": "^4.1.1", + "help-me": "^3.0.0", + "inherits": "^2.0.3", + "lru-cache": "^6.0.0", + "minimist": "^1.2.5", + "mqtt-packet": "^6.8.0", + "number-allocator": "^1.0.9", + "pump": "^3.0.0", + "readable-stream": "^3.6.0", + "reinterval": "^1.1.0", + "rfdc": "^1.3.0", + "split2": "^3.1.0", + "ws": "^7.5.5", + "xtend": "^4.0.2" + }, + "bin": { + "mqtt": "bin/mqtt.js", + "mqtt_pub": "bin/pub.js", + "mqtt_sub": "bin/sub.js" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/mqtt-packet": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/mqtt-packet/-/mqtt-packet-6.10.0.tgz", + "integrity": "sha512-ja8+mFKIHdB1Tpl6vac+sktqy3gA8t9Mduom1BA75cI+R9AHnZOiaBQwpGiWnaVJLDGRdNhQmFaAqd7tkKSMGA==", + "dependencies": { + "bl": "^4.0.2", + "debug": "^4.1.1", + "process-nextick-args": "^2.0.1" + } + }, + "node_modules/mqtt/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/nan": { + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.16.0.tgz", + "integrity": "sha512-UdAqHyFngu7TfQKsCBgAA6pWDkT8MAO7d0jyOecVhN5354xbLqdn8mV9Tat9gepAupm0bt2DbeaSC8vS52MuFA==" + }, + "node_modules/napi-build-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", + "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==" + }, + "node_modules/node-abi": { + "version": "3.22.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.22.0.tgz", + "integrity": "sha512-u4uAs/4Zzmp/jjsD9cyFYDXeISfUWaAVWshPmDZOFOv4Xl4SbzTXm53I04C2uRueYJ+0t5PEtLH/owbn2Npf/w==", + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/nodemailer": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.7.tgz", + "integrity": "sha512-rUtR77ksqex/eZRLmQ21LKVH5nAAsVicAtAYudK7JgwenEDZ0UIQ1adUGqErz7sMkWYxWTTU1aeP2Jga6WQyJw==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "dependencies": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "node_modules/number-allocator": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/number-allocator/-/number-allocator-1.0.14.tgz", + "integrity": "sha512-OrL44UTVAvkKdOdRQZIJpLkAdjXGTRda052sN4sO77bKEzYYqWKMBjQvrJFzqygI99gL6Z4u2xctPW1tB8ErvA==", + "dependencies": { + "debug": "^4.3.1", + "js-sdsl": "4.3.0" + } + }, + "node_modules/number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/prebuild-install": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.0.tgz", + "integrity": "sha512-CNcMgI1xBypOyGqjp3wOc8AAo1nMhZS3Cwd3iHIxOdAUbb+YxdNuM4Z5iIrZ8RLvOsf3F3bl7b7xGq6DjQoNYA==", + "dependencies": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^1.0.1", + "node-abi": "^3.3.0", + "npmlog": "^4.0.1", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + }, + "bin": { + "prebuild-install": "bin.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/reinterval": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reinterval/-/reinterval-1.1.0.tgz", + "integrity": "sha1-M2Hs+jymwYKDOA3Qu5VG85D17Oc=" + }, + "node_modules/rfdc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==" + }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/serialport": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/serialport/-/serialport-9.2.8.tgz", + "integrity": "sha512-FsWpMQgSJxi93JgWl5xM1f9/Z8IjRJuaUEoHqLf8FPBLw7gMhInuHOBhI2onQufWIYPGTz3H3oGcu1nCaK1EfA==", + "dependencies": { + "@serialport/binding-mock": "9.2.4", + "@serialport/bindings": "9.2.8", + "@serialport/parser-byte-length": "9.2.4", + "@serialport/parser-cctalk": "9.2.4", + "@serialport/parser-delimiter": "9.2.4", + "@serialport/parser-inter-byte-timeout": "9.2.4", + "@serialport/parser-readline": "9.2.4", + "@serialport/parser-ready": "9.2.4", + "@serialport/parser-regex": "9.2.4", + "@serialport/stream": "9.2.4", + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "node_modules/split2": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", + "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", + "dependencies": { + "readable-stream": "^3.0.0" + } + }, + "node_modules/split2/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==" + }, + "node_modules/streamroller": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.1.1.tgz", + "integrity": "sha512-iPhtd9unZ6zKdWgMeYGfSBuqCngyJy1B/GPi/lTpwGpa3bajuX30GjUVd0/Tn/Xhg0mr4DOSENozz9Y06qyonQ==", + "dependencies": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "fs-extra": "^10.1.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dependencies": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/tar-fs": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "dependencies": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tar-stream/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/total.js": { + "version": "3.4.13", + "resolved": "https://registry.npmjs.org/total.js/-/total.js-3.4.13.tgz", + "integrity": "sha512-lAH4gEixlPFbrE3xfKADAcHfO79IFq2wKa9GTsrgRzIR5MTg3mNH7+4IxvX1pK8faoYb/0oYSJ1YTsAa5hIFFQ==", + "bin": { + "total": "bin/totaljs", + "total.js": "bin/totaljs", + "totaljs": "bin/totaljs", + "totalpackage": "bin/tpm", + "tpm": "bin/tpm" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, + "node_modules/universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "node_modules/wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "node_modules/ws": { + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } + }, + "dependencies": { + "@serialport/binding-abstract": { + "version": "9.2.3", + "resolved": "https://registry.npmjs.org/@serialport/binding-abstract/-/binding-abstract-9.2.3.tgz", + "integrity": "sha512-cQs9tbIlG3P0IrOWyVirqlhWuJ7Ms2Zh9m2108z6Y5UW/iVj6wEOiW8EmK9QX9jmJXYllE7wgGgvVozP5oCj3w==", + "requires": { + "debug": "^4.3.2" + } + }, + "@serialport/binding-mock": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/binding-mock/-/binding-mock-9.2.4.tgz", + "integrity": "sha512-dpEhACCs44oQhh6ajJfJdvQdK38Vq0N4W6iD/gdplglDCK7qXRQCMUjJIeKdS/HSEiWkC3bwumUhUufdsOyT4g==", + "requires": { + "@serialport/binding-abstract": "9.2.3", + "debug": "^4.3.2" + } + }, + "@serialport/bindings": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/@serialport/bindings/-/bindings-9.2.8.tgz", + "integrity": "sha512-hSLxTe0tADZ3LMMGwvEJWOC/TaFQTyPeFalUCsJ1lSQ0k6bPF04JwrtB/C81GetmDBTNRY0GlD0SNtKCc7Dr5g==", + "requires": { + "@serialport/binding-abstract": "9.2.3", + "@serialport/parser-readline": "9.2.4", + "bindings": "^1.5.0", + "debug": "^4.3.2", + "nan": "^2.15.0", + "prebuild-install": "^7.0.0" + } + }, + "@serialport/parser-byte-length": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-byte-length/-/parser-byte-length-9.2.4.tgz", + "integrity": "sha512-sQD/iw4ZMU3xW9PLi0/GlvU6Y623jGeWecbMkO7izUo/6P7gtfv1c9ikd5h0kwL8AoAOpQA1lxdHIKox+umBUg==" + }, + "@serialport/parser-cctalk": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-cctalk/-/parser-cctalk-9.2.4.tgz", + "integrity": "sha512-T4TU5vQMwmo9AB3gQLFDWbfJXlW5jd9guEsB/nqKjFHTv0FXPdZ7DQ2TpSp8RnHWxU3GX6kYTaDO20BKzc8GPQ==" + }, + "@serialport/parser-delimiter": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-delimiter/-/parser-delimiter-9.2.4.tgz", + "integrity": "sha512-4nvTAoYAgkxFiXrkI+3CA49Yd43CODjeszh89EK+I9c8wOZ+etZduRCzINYPiy26g7zO+GRAb9FoPCsY+sYcbQ==" + }, + "@serialport/parser-inter-byte-timeout": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-inter-byte-timeout/-/parser-inter-byte-timeout-9.2.4.tgz", + "integrity": "sha512-SOAdvr0oBQIOCXX198hiTlxs4JTKg9j5piapw5tNq52fwDOWdbYrFneT/wN04UTMKaDrJuEvXq6T4rv4j7nJ5A==" + }, + "@serialport/parser-readline": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-readline/-/parser-readline-9.2.4.tgz", + "integrity": "sha512-Z1/qrZTQUVhNSJP1hd9YfDvq0o7d87rNwAjjRKbVpa7Qi51tG5BnKt43IV3NFMyBlVcRe0rnIb3tJu57E0SOwg==", + "requires": { + "@serialport/parser-delimiter": "9.2.4" + } + }, + "@serialport/parser-ready": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-ready/-/parser-ready-9.2.4.tgz", + "integrity": "sha512-Pyi94Itjl6qAURwIZr/gmZpMAyTmKXThm6vL5DoAWGQjcRHWB0gwv2TY2v7N+mQLJYUKU3cMnvnATXxHm7xjxw==" + }, + "@serialport/parser-regex": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-regex/-/parser-regex-9.2.4.tgz", + "integrity": "sha512-sI/cVvPOYz+Dbv4ZdnW16qAwvXiFf/1pGASQdbveRTlgJDdz7sRNlCBifzfTN2xljwvCTZYqiudKvDdC1TepRQ==" + }, + "@serialport/stream": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/stream/-/stream-9.2.4.tgz", + "integrity": "sha512-bLye8Ub4vUFQGmkh8qEqehr7SE7EJs2yDs0h9jzuL5oKi+F34CFmWkEErO8GAOQ8YNn7p6b3GxUgs+0BrHHDZQ==", + "requires": { + "debug": "^4.3.2" + } + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==" + }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "are-we-there-yet": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", + "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "base64-js": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", + "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==" + }, + "bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "requires": { + "file-uri-to-path": "1.0.0" + } + }, + "bitwise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/bitwise/-/bitwise-2.1.0.tgz", + "integrity": "sha512-XKgAhMXCh4H/3oNwAHAsAO0iC89s9cOiumgYwSHjSobGWxYjv62YhkL9QEdvGP151xypCtMlAfKK79GEcd2eRQ==" + }, + "bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "requires": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "buffer": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz", + "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==", + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" + }, + "chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==" + }, + "commist": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/commist/-/commist-1.1.0.tgz", + "integrity": "sha512-rraC8NXWOEjhADbZe9QBNzLAN5Q3fsTPQtBV+fEVj6xKIgDgNiEVE6ZNfHpZOqfQ21YUzfVNUXLOEZquYvQPPg==", + "requires": { + "leven": "^2.1.0", + "minimist": "^1.1.0" + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "concat-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", + "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.0.2", + "typedarray": "^0.0.6" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "crc": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/crc/-/crc-3.4.0.tgz", + "integrity": "sha512-ycVC2+4/DLgXXq7QweYi2znhqDuZz6P5TQXnkQo8v15XY/5p/IWeZwsSE31Ifo8w15b8TWLsqhXOjXyilHuQxw==" + }, + "date-format": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.11.tgz", + "integrity": "sha512-VS20KRyorrbMCQmpdl2hg5KaOUsda1RbnsJg461FfrcyCUg+pkd0b40BSW4niQyTheww4DBXQnS7HwSrKkipLw==" + }, + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "requires": { + "ms": "2.1.2" + } + }, + "decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "requires": { + "mimic-response": "^3.1.0" + } + }, + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==" + }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" + }, + "detect-libc": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz", + "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==" + }, + "duplexify": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.2.tgz", + "integrity": "sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw==", + "requires": { + "end-of-stream": "^1.4.1", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1", + "stream-shift": "^1.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "easy-crc": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/easy-crc/-/easy-crc-0.0.2.tgz", + "integrity": "sha512-h6eqIdhJRe0p271/xZJbM/0klCi13mW5IB7ZEzEGH11yV4QXWAkD4yPErz0fXdhFrd6sZ4Q1k5Iky2kMsMNePw==" + }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "requires": { + "once": "^1.4.0" + } + }, + "expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==" + }, + "file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" + }, + "flatted": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", + "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==" + }, + "fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, + "fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha512-14x4kjc6lkD3ltw589k0NrPD6cCNTD6CWoVUNpB85+DrtONoZn+Rug6xZU5RvSC4+TZPxA5AnBibQYAvZn41Hg==", + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==" + }, + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" + }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" + }, + "help-me": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/help-me/-/help-me-3.0.0.tgz", + "integrity": "sha512-hx73jClhyk910sidBB7ERlnhMlFsJJIBqSVMFDwPN8o2v9nmp5KgLq1Xz1Bf1fCMMZ6mPrX159iG0VLy/fPMtQ==", + "requires": { + "glob": "^7.1.6", + "readable-stream": "^3.6.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==", + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "js-sdsl": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz", + "integrity": "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==" + }, + "jsmodbus": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/jsmodbus/-/jsmodbus-4.0.6.tgz", + "integrity": "sha512-gCmjoaERErK5Rn9Lu/BN07fY13MoWV7JKgGzrnkPlQPdPxYcwDhLtYcmpFFpZ4J9NPZZBSezi1UkLZO/DnNppA==", + "requires": { + "crc": "3.4.0", + "debug": "^3.1.0" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "requires": { + "ms": "^2.1.1" + } + } + } + }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, + "leven": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", + "integrity": "sha1-wuep93IJTe6dNCAq6KzORoeHVYA=" + }, + "log4js": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.5.2.tgz", + "integrity": "sha512-DXtpNtt+KDOMT7RHUDIur/WsSA3rntlUh9Zg4XCdV42wUuMmbFkl38+LZ92Z5QvQA7mD5kAVkLiBSEH/tvUB8A==", + "requires": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "flatted": "^3.2.5", + "rfdc": "^1.3.0", + "streamroller": "^3.1.1" + } + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "requires": { + "yallist": "^4.0.0" + } + }, + "mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==" + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==" + }, + "mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" + }, + "moment": { + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", + "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==" + }, + "mqtt": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/mqtt/-/mqtt-4.3.7.tgz", + "integrity": "sha512-ew3qwG/TJRorTz47eW46vZ5oBw5MEYbQZVaEji44j5lAUSQSqIEoul7Kua/BatBW0H0kKQcC9kwUHa1qzaWHSw==", + "requires": { + "commist": "^1.0.0", + "concat-stream": "^2.0.0", + "debug": "^4.1.1", + "duplexify": "^4.1.1", + "help-me": "^3.0.0", + "inherits": "^2.0.3", + "lru-cache": "^6.0.0", + "minimist": "^1.2.5", + "mqtt-packet": "^6.8.0", + "number-allocator": "^1.0.9", + "pump": "^3.0.0", + "readable-stream": "^3.6.0", + "reinterval": "^1.1.0", + "rfdc": "^1.3.0", + "split2": "^3.1.0", + "ws": "^7.5.5", + "xtend": "^4.0.2" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "mqtt-packet": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/mqtt-packet/-/mqtt-packet-6.10.0.tgz", + "integrity": "sha512-ja8+mFKIHdB1Tpl6vac+sktqy3gA8t9Mduom1BA75cI+R9AHnZOiaBQwpGiWnaVJLDGRdNhQmFaAqd7tkKSMGA==", + "requires": { + "bl": "^4.0.2", + "debug": "^4.1.1", + "process-nextick-args": "^2.0.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "nan": { + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.16.0.tgz", + "integrity": "sha512-UdAqHyFngu7TfQKsCBgAA6pWDkT8MAO7d0jyOecVhN5354xbLqdn8mV9Tat9gepAupm0bt2DbeaSC8vS52MuFA==" + }, + "napi-build-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", + "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==" + }, + "node-abi": { + "version": "3.22.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.22.0.tgz", + "integrity": "sha512-u4uAs/4Zzmp/jjsD9cyFYDXeISfUWaAVWshPmDZOFOv4Xl4SbzTXm53I04C2uRueYJ+0t5PEtLH/owbn2Npf/w==", + "requires": { + "semver": "^7.3.5" + } + }, + "nodemailer": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.7.tgz", + "integrity": "sha512-rUtR77ksqex/eZRLmQ21LKVH5nAAsVicAtAYudK7JgwenEDZ0UIQ1adUGqErz7sMkWYxWTTU1aeP2Jga6WQyJw==" + }, + "npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "number-allocator": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/number-allocator/-/number-allocator-1.0.14.tgz", + "integrity": "sha512-OrL44UTVAvkKdOdRQZIJpLkAdjXGTRda052sN4sO77bKEzYYqWKMBjQvrJFzqygI99gL6Z4u2xctPW1tB8ErvA==", + "requires": { + "debug": "^4.3.1", + "js-sdsl": "4.3.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==" + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==" + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==" + }, + "prebuild-install": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.0.tgz", + "integrity": "sha512-CNcMgI1xBypOyGqjp3wOc8AAo1nMhZS3Cwd3iHIxOdAUbb+YxdNuM4Z5iIrZ8RLvOsf3F3bl7b7xGq6DjQoNYA==", + "requires": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^1.0.1", + "node-abi": "^3.3.0", + "npmlog": "^4.0.1", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + } + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + } + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "reinterval": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reinterval/-/reinterval-1.1.0.tgz", + "integrity": "sha1-M2Hs+jymwYKDOA3Qu5VG85D17Oc=" + }, + "rfdc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==" + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "requires": { + "lru-cache": "^6.0.0" + } + }, + "serialport": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/serialport/-/serialport-9.2.8.tgz", + "integrity": "sha512-FsWpMQgSJxi93JgWl5xM1f9/Z8IjRJuaUEoHqLf8FPBLw7gMhInuHOBhI2onQufWIYPGTz3H3oGcu1nCaK1EfA==", + "requires": { + "@serialport/binding-mock": "9.2.4", + "@serialport/bindings": "9.2.8", + "@serialport/parser-byte-length": "9.2.4", + "@serialport/parser-cctalk": "9.2.4", + "@serialport/parser-delimiter": "9.2.4", + "@serialport/parser-inter-byte-timeout": "9.2.4", + "@serialport/parser-readline": "9.2.4", + "@serialport/parser-ready": "9.2.4", + "@serialport/parser-regex": "9.2.4", + "@serialport/stream": "9.2.4", + "debug": "^4.3.2" + } + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==" + }, + "simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "requires": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "split2": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", + "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", + "requires": { + "readable-stream": "^3.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==" + }, + "streamroller": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.1.1.tgz", + "integrity": "sha512-iPhtd9unZ6zKdWgMeYGfSBuqCngyJy1B/GPi/lTpwGpa3bajuX30GjUVd0/Tn/Xhg0mr4DOSENozz9Y06qyonQ==", + "requires": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "fs-extra": "^10.1.0" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" + }, + "tar-fs": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "requires": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "requires": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "total.js": { + "version": "3.4.13", + "resolved": "https://registry.npmjs.org/total.js/-/total.js-3.4.13.tgz", + "integrity": "sha512-lAH4gEixlPFbrE3xfKADAcHfO79IFq2wKa9GTsrgRzIR5MTg3mNH7+4IxvX1pK8faoYb/0oYSJ1YTsAa5hIFFQ==" + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, + "universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==" + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "requires": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "ws": { + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "requires": {} + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } + } +} diff --git a/RVO22/package.json b/RVO22/package.json new file mode 100755 index 0000000..7f7c795 --- /dev/null +++ b/RVO22/package.json @@ -0,0 +1,30 @@ +{ + "name": "emptyproject", + "description": "Total.js empty project.", + "version": "1.0.0", + "main": "debug.js", + "dependencies": { + "bitwise": "^2.1.0", + "easy-crc": "0.0.2", + "jsmodbus": "^4.0.6", + "log4js": "^6.3.0", + "moment": "^2.30.1", + "mqtt": "^4.2.6", + "nodemailer": "^6.9.7", + "serialport": "^9.2.8", + "total.js": "^3.4.13" + }, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "https://github.com/totaljs/emptyproject-flow" + }, + "keywords": [ + "empty", + "project" + ], + "author": "Peter Širka", + "license": "MIT" +} diff --git a/RVO22/release.js b/RVO22/release.js new file mode 100755 index 0000000..02d52ff --- /dev/null +++ b/RVO22/release.js @@ -0,0 +1,15 @@ +// =================================================== +// FOR PRODUCTION +// Total.js - framework for Node.js platform +// https://www.totaljs.com +// =================================================== + +const options = {'ip':'0.0.0.0', 'port':12345}; + +// options.ip = '127.0.0.1'; +// options.port = parseInt(process.argv[2]); +// options.config = { name: 'Total.js' }; +// options.sleep = 3000; + +require('total.js').http('release', options); +// require('total.js').cluster.http(5, 'release', options); diff --git a/RVO22/release.js.json b/RVO22/release.js.json new file mode 100755 index 0000000..1f7cc5c --- /dev/null +++ b/RVO22/release.js.json @@ -0,0 +1,34 @@ +{ + "pid": 422, + "stats": [ + { + "id": null, + "version": { + "node": "v14.18.1", + "total": "3.4.13", + "app": "1.0.0" + }, + "pid": 422, + "thread": "", + "mode": "release", + "overload": 0, + "date": "2025-10-16T00:24:15.346Z", + "memory": 21.33, + "rm": 0, + "fm": 0, + "wm": 0, + "mm": 0, + "om": 4, + "em": 0, + "dbrm": 0, + "dbwm": 0, + "usage": 0, + "requests": 0, + "pending": 0, + "errors": 0, + "timeouts": 0, + "uptime": 732, + "online": 0 + } + ] +} \ No newline at end of file diff --git a/RVO22/report_data.log b/RVO22/report_data.log new file mode 100755 index 0000000..15b4720 --- /dev/null +++ b/RVO22/report_data.log @@ -0,0 +1,178 @@ +{ + "name": "rvo_senica_22_ip109", + "time": "2025-10-15T13:13:30.208Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_22_ip109", + "time": "2025-10-15T14:13:30.206Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_22_ip109", + "time": "2025-10-15T15:13:30.207Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_22_ip109", + "time": "2025-10-15T16:13:30.208Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_22_ip109", + "time": "2025-10-15T17:33:12.482Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_22_ip109", + "time": "2025-10-15T18:33:12.483Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "22/38_1L_2667_NEMA" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_22_ip109", + "time": "2025-10-15T19:33:12.483Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "22/38_1L_2667_NEMA" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_22_ip109", + "time": "2025-10-15T20:33:12.484Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "22/38_1L_2667_NEMA" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_22_ip109", + "time": "2025-10-15T21:33:12.484Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "22/38_1L_2667_NEMA" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_22_ip109", + "time": "2025-10-15T22:33:12.484Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "22/38_1L_2667_NEMA" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_22_ip109", + "time": "2025-10-15T23:33:12.485Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "22/38_1L_2667_NEMA" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +} \ No newline at end of file From b2adef622de0d9ac16ff40dc5d9b7eab7f6afba5 Mon Sep 17 00:00:00 2001 From: Jakub Klena Date: Thu, 16 Oct 2025 02:25:01 +0200 Subject: [PATCH 13/30] Backup senica-RVO23 on 16.10.2025 --- RVO23/addSwitch.py | 36 + RVO23/cloud_topic.py | 76 + RVO23/config | 12 + RVO23/createNode.py | 43 + RVO23/databases/accelerometer_db.js | 3055 ++++++++++++++++ RVO23/databases/modbus_config.js | 114 + RVO23/databases/nodes.table | 36 + .../nodes_original/nodes_original.table | 1 + RVO23/databases/notifications.table | 41 + RVO23/databases/pins.table | 14 + RVO23/databases/relays.table | 5 + RVO23/databases/settings.table | 2 + RVO23/databases/tbdata.nosql | 4 + RVO23/databases/tbdatacloud.nosql | 3 + RVO23/databases/total_energy.js | 38 + RVO23/debug.js | 16 + RVO23/err.txt | 78 + RVO23/flow/cloudmqttconnect.js | 357 ++ RVO23/flow/cmd_manager.js | 3071 ++++++++++++++++ RVO23/flow/code.js | 90 + RVO23/flow/comment.js | 11 + RVO23/flow/count.js | 60 + RVO23/flow/db_connector.js | 286 ++ RVO23/flow/db_init.js | 113 + RVO23/flow/debug.js | 100 + RVO23/flow/designer.json | 3102 +++++++++++++++++ RVO23/flow/dido_controller.js | 1486 ++++++++ RVO23/flow/helper/DataToTbHandler.js | 187 + RVO23/flow/helper/ErrorToServiceHandler.js | 91 + RVO23/flow/helper/db_helper.js | 44 + RVO23/flow/helper/logger.js | 30 + RVO23/flow/helper/md5.js | 5 + RVO23/flow/helper/notification_reporter.js | 121 + RVO23/flow/helper/register.js | 144 + RVO23/flow/helper/serialport_helper.js | 99 + RVO23/flow/helper/suncalc.js | 317 ++ RVO23/flow/helper/utils.js | 161 + RVO23/flow/httprequest.js | 137 + RVO23/flow/httpresponse.js | 76 + RVO23/flow/httproute.js | 326 ++ RVO23/flow/infosender.js | 81 + RVO23/flow/modbus_reader.js | 346 ++ RVO23/flow/monitorconsumption.js | 156 + RVO23/flow/monitordisk.js | 96 + RVO23/flow/monitormemory.js | 87 + RVO23/flow/nodesdb_changecheck.js | 77 + RVO23/flow/show_dbdata.js | 243 ++ RVO23/flow/slack_filter.js | 188 + RVO23/flow/thermometer.js | 99 + RVO23/flow/trigger.js | 79 + RVO23/flow/variables.txt | 0 RVO23/flow/virtualwirein.js | 43 + RVO23/flow/virtualwireout.js | 41 + RVO23/flow/wsmqttpublish.js | 448 +++ RVO23/monitor.txt | 2284 ++++++++++++ RVO23/package-lock.json | 2139 ++++++++++++ RVO23/package.json | 30 + RVO23/release.js | 15 + RVO23/release.js.json | 34 + RVO23/report_data.log | 208 ++ 60 files changed, 20682 insertions(+) create mode 100755 RVO23/addSwitch.py create mode 100755 RVO23/cloud_topic.py create mode 100755 RVO23/config create mode 100755 RVO23/createNode.py create mode 100755 RVO23/databases/accelerometer_db.js create mode 100755 RVO23/databases/modbus_config.js create mode 100755 RVO23/databases/nodes.table create mode 100755 RVO23/databases/nodes_original/nodes_original.table create mode 100755 RVO23/databases/notifications.table create mode 100755 RVO23/databases/pins.table create mode 100755 RVO23/databases/relays.table create mode 100755 RVO23/databases/settings.table create mode 100755 RVO23/databases/tbdata.nosql create mode 100755 RVO23/databases/tbdatacloud.nosql create mode 100755 RVO23/databases/total_energy.js create mode 100755 RVO23/debug.js create mode 100755 RVO23/err.txt create mode 100755 RVO23/flow/cloudmqttconnect.js create mode 100755 RVO23/flow/cmd_manager.js create mode 100755 RVO23/flow/code.js create mode 100755 RVO23/flow/comment.js create mode 100755 RVO23/flow/count.js create mode 100755 RVO23/flow/db_connector.js create mode 100755 RVO23/flow/db_init.js create mode 100755 RVO23/flow/debug.js create mode 100755 RVO23/flow/designer.json create mode 100755 RVO23/flow/dido_controller.js create mode 100755 RVO23/flow/helper/DataToTbHandler.js create mode 100755 RVO23/flow/helper/ErrorToServiceHandler.js create mode 100755 RVO23/flow/helper/db_helper.js create mode 100755 RVO23/flow/helper/logger.js create mode 100755 RVO23/flow/helper/md5.js create mode 100755 RVO23/flow/helper/notification_reporter.js create mode 100755 RVO23/flow/helper/register.js create mode 100755 RVO23/flow/helper/serialport_helper.js create mode 100755 RVO23/flow/helper/suncalc.js create mode 100755 RVO23/flow/helper/utils.js create mode 100755 RVO23/flow/httprequest.js create mode 100755 RVO23/flow/httpresponse.js create mode 100755 RVO23/flow/httproute.js create mode 100755 RVO23/flow/infosender.js create mode 100755 RVO23/flow/modbus_reader.js create mode 100755 RVO23/flow/monitorconsumption.js create mode 100755 RVO23/flow/monitordisk.js create mode 100755 RVO23/flow/monitormemory.js create mode 100755 RVO23/flow/nodesdb_changecheck.js create mode 100755 RVO23/flow/show_dbdata.js create mode 100755 RVO23/flow/slack_filter.js create mode 100755 RVO23/flow/thermometer.js create mode 100755 RVO23/flow/trigger.js create mode 100755 RVO23/flow/variables.txt create mode 100755 RVO23/flow/virtualwirein.js create mode 100755 RVO23/flow/virtualwireout.js create mode 100755 RVO23/flow/wsmqttpublish.js create mode 100755 RVO23/monitor.txt create mode 100755 RVO23/package-lock.json create mode 100755 RVO23/package.json create mode 100755 RVO23/release.js create mode 100755 RVO23/release.js.json create mode 100755 RVO23/report_data.log diff --git a/RVO23/addSwitch.py b/RVO23/addSwitch.py new file mode 100755 index 0000000..c35e96b --- /dev/null +++ b/RVO23/addSwitch.py @@ -0,0 +1,36 @@ +import os + +def process_set_file(): + """ + Checks if /root/flowserver exists, reads set.txt, and modifies the second line. + """ + default_folder = "/root/flowserver" if os.path.exists("/root/flowserver") else "/home/unipi/flowserver" + flag = 1 if default_folder == "/root/flowserver" else 0 + + try: + with open("/home/unipi/flowserver/databases/settings.table", "r") as f: + lines = f.readlines() + + if len(lines) >= 2: + lines[0] = lines[0].rstrip('\n') + "|main_switch:boolean\n" + second_line = lines[1].strip() # remove trailing newline + last_pipe_index = second_line.rfind("|") + + if last_pipe_index != -1: + modified_line = second_line[:last_pipe_index + 1] + str(flag) + "|" + second_line[last_pipe_index + 1:] + lines[1] = modified_line + else: + print("Warning: No '|' character found in the second line of set.txt") + + with open("/home/unipi/flowserver/databases/settings.table", "w") as f: + f.writelines(lines) + else: + print("Warning: settings.table has less than two lines.") + + except FileNotFoundError: + print("Error: settings.table not found.") + except Exception as e: + print(e) + +# if __name__ == "__main__": +process_set_file() diff --git a/RVO23/cloud_topic.py b/RVO23/cloud_topic.py new file mode 100755 index 0000000..77c31f1 --- /dev/null +++ b/RVO23/cloud_topic.py @@ -0,0 +1,76 @@ +# import os +# +# def modify_file(file_path): +# """ +# Modifies the given file by: +# 1. Appending "|cloud_topic" to the first line. +# 2. Inserting the text from the third "." to the first "|" on the second line after the last "|" character. +# +# Args: +# file_path (str): The path to the file to be modified. +# """ +# +# with open(file_path, 'r+') as f: +# lines = f.readlines() +# +# # Modify the first line +# lines[0] += "|cloud_topic:string" +# +# # Modify the second line +# second_line = lines[1].strip() # Remove leading/trailing whitespace +# first_pipe_index = second_line.find('|') +# third_dot_index = second_line.find('.', second_line.find('.', second_line.find('.') + 1) + 1) +# text_to_insert = second_line[third_dot_index:first_pipe_index] +# +# last_pipe_index = second_line.rfind('|') +# lines[1] = second_line[:last_pipe_index + 1] + text_to_insert + "|" + second_line[last_pipe_index + 1:] +# +# print(first_pipe_index, third_dot_index, text_to_insert, last_pipe_index) +# # Write the modified lines back to the file +# # f.seek(0) +# # f.writelines(lines) +# # f.truncate() +# +# # Example usage: +# file_path = "settings.table" # Replace with the actual file path +# modify_file(file_path) +# + + +def modify_file(file_path): + """ + Modifies the given file by: + 1. Appending "|cloud_topic" to the first line. + 2. Inserting the text between the third "." and the second "|" on the second line after the last "|" character. + + Args: + file_path (str): The path to the file to be modified. + """ + + with open(file_path, 'r+') as f: + lines = f.readlines() + + first_line = lines[0].strip() + first_line += "|cloud_topic:string\n" + # Modify the first line + lines[0] = first_line + + # Modify the second line + second_line = lines[1].strip() # Remove leading/trailing whitespace + first_pipe_index = second_line.find('|') + second_pipe_index = second_line.find('|', first_pipe_index + 1) + third_dot_index = second_line.find('.', second_line.find('.', second_line.find('.') + 1) + 1) + text_to_insert = "u" + second_line[third_dot_index+1:second_pipe_index] + + last_pipe_index = second_line.rfind('|') + lines[1] = second_line[:last_pipe_index + 1] + text_to_insert + "|" + second_line[last_pipe_index + 1:] + + print(first_pipe_index, third_dot_index, text_to_insert, last_pipe_index) + # Write the modified lines back to the file + f.seek(0) + f.writelines(lines) + f.truncate() + +# Example usage: +file_path = "/home/unipi/flowserver/databases/settings.table" # Replace with the actual file path +modify_file(file_path) diff --git a/RVO23/config b/RVO23/config new file mode 100755 index 0000000..cd0a8a9 --- /dev/null +++ b/RVO23/config @@ -0,0 +1,12 @@ +name : Total.js Flow +default_timezone : Europe/Bratislava + +// Packages settings +package#flow (Object) : { url: '/' } + + +table.relays : line:number|tbname:string|contactor:number|profile:string +table.nodes : node:number|pole_number:string|node_type:string|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|project_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|cloud_topic:string|has_main_switch:boolean|daily_report:boolean|send_changed_node_numbers:boolean +table.pins : pin:string|type:string|line:number +table.notifications : key:string|weight:string|sk:string|en:string diff --git a/RVO23/createNode.py b/RVO23/createNode.py new file mode 100755 index 0000000..a8cea91 --- /dev/null +++ b/RVO23/createNode.py @@ -0,0 +1,43 @@ +print("zaciname") +import re, json + +search_str = '|' +final = [] +counter = 1 +with open("/home/unipi/flowserver/databases/nodes.table", 'r') as file: +# with open("/home/rasta5man/dev/oms/flowserver/databases/nodes.table", 'r') as file: + # Read each line in the file + for line in file: + # Print each line + line = line.strip() + print(line) + if counter != 1: + i = [m.start() for m in re.finditer(re.escape(search_str), line)] + node = line[ i[0] + 1 : i[1] ] + tbname = line[ i[3] + 1 : i[4] ] + final.append({node:tbname}) + counter += 1 +print(json.dumps(final)) +f = open("/home/unipi/flowserver/databases/nodes_original/nodes_original.table", "w") +f.write(json.dumps(final)) +f.close() + + +# +# # ``d`` has to be replaced with a different character +# old_character = "'" +# +# # ``t`` will replace ``d` +# new_character = '"' +# resultant_string = 0; +# with open("/home/unipi/flowserver/databases/nodes_original/nodes_original.table", 'r') as file: +# for line in file: +# resultant_string = re.sub("'", '"', line) +# +# resultant_string = re.sub(" ", "", resultant_string) +# print(resultant_string) +# +# f = open("/home/unipi/flowserver/databases/nodes_original/nodes_original.table", "w") +# f.write(str(resultant_string)) +# f.close() +# diff --git a/RVO23/databases/accelerometer_db.js b/RVO23/databases/accelerometer_db.js new file mode 100755 index 0000000..fdfc7fd --- /dev/null +++ b/RVO23/databases/accelerometer_db.js @@ -0,0 +1,3055 @@ +let naklony = { + "3993": { "label": "1/3A", "naklon": 0 }, + "3989": { "label": "1/3B", "naklon": 15 }, + "3976": { "label": "1/1", "naklon": 0 }, + "4181": { "label": "1/2", "naklon": 0 }, + "4376": { "label": "1/4", "naklon": 15 }, + "3868": { "label": "1/5", "naklon": 15 }, + "3728": { "label": "1/6", "naklon": 15 }, + "3730": { "label": "1/7", "naklon": 0 }, + "4374": { "label": "1/8", "naklon": 0 }, + "3718": { "label": "1/9", "naklon": 15 }, + "4375": { "label": "1/10", "naklon": 15 }, + "4172": { "label": "1/11", "naklon": 15 }, + "4176": { "label": "1/12", "naklon": 15 }, + "3800": { "label": "2/1", "naklon": 5 }, + "3823": { "label": "2/2", "naklon": 5 }, + "3905": { "label": "2/3", "naklon": 5 }, + "3803": { "label": "2/4", "naklon": 5 }, + "3817": { "label": "2/5", "naklon": 5 }, + "3818": { "label": "2/6", "naklon": 5 }, + "3811": { "label": "2/7", "naklon": 5 }, + "3915": { "label": "2/8", "naklon": 5 }, + "3843": { "label": "2/9", "naklon": 10 }, + "3827": { "label": "2/10", "naklon": 10 }, + "4220": { "label": "2/11", "naklon": 10 }, + "3826": { "label": "2/12", "naklon": 10 }, + "3834": { "label": "2/13", "naklon": 10 }, + "3838": { "label": "2/14", "naklon": 10 }, + "2823": { "label": "2/15", "naklon": 10 }, + "3750": { "label": "2/16", "naklon": 10 }, + "3378": { "label": "2/17", "naklon": 0 }, + "3376": { "label": "2/18", "naklon": 0 }, + "3379": { "label": "2/19", "naklon": 0 }, + "3285": { "label": "2/20", "naklon": 0 }, + "3382": { "label": "2/21", "naklon": 0 }, + "3383": { "label": "2/22", "naklon": 0 }, + "3375": { "label": "2/24", "naklon": 0 }, + "3381": { "label": "2/25", "naklon": 0 }, + "3380": { "label": "2/26", "naklon": 0 }, + "3828": { "label": "2/27", "naklon": 10 }, + "3377": { "label": "2/28", "naklon": 0 }, + "3591": { "label": "7/1", "naklon": 0 }, + "3587": { "label": "7/2", "naklon": 0 }, + "3468": { "label": "7/3", "naklon": 0 }, + "3466": { "label": "7/4", "naklon": 0 }, + "3474": { "label": "7/5", "naklon": 0 }, + "3481": { "label": "7/6", "naklon": 0 }, + "3589": { "label": "7/7", "naklon": 0 }, + "3472": { "label": "7/8", "naklon": 0 }, + "3473": { "label": "7/9", "naklon": 0 }, + "3584": { "label": "7/10", "naklon": 0 }, + "3571": { "label": "7/11", "naklon": 0 }, + "3476": { "label": "7/12", "naklon": 0 }, + "3590": { "label": "7/13", "naklon": 0 }, + "3478": { "label": "7/14", "naklon": 0 }, + "3471": { "label": "7/15", "naklon": 0 }, + "3467": { "label": "7/16", "naklon": 0 }, + "3479": { "label": "7/17", "naklon": 0 }, + "3480": { "label": "7/18", "naklon": 0 }, + "3477": { "label": "7/19", "naklon": 0 }, + "3362": { "label": "12/1", "naklon": 0 }, + "3355": { "label": "12/2", "naklon": 0 }, + "3356": { "label": "12/3", "naklon": 0 }, + "3349": { "label": "12/4", "naklon": 0 }, + "3357": { "label": "12/5", "naklon": 0 }, + "3350": { "label": "12/6", "naklon": 0 }, + "3353": { "label": "12/7", "naklon": 0 }, + "3539": { "label": "12/8", "naklon": 0 }, + "3050": { "label": "12/9", "naklon": 0 }, + "3361": { "label": "12/10", "naklon": 0 }, + "3360": { "label": "12/11", "naklon": 0 }, + "3358": { "label": "12/12", "naklon": 0 }, + "3541": { "label": "12/13", "naklon": 0 }, + "3551": { "label": "12/14", "naklon": 0 }, + "3514": { "label": "12/15", "naklon": 0 }, + "3547": { "label": "12/16", "naklon": 0 }, + "3562": { "label": "12/17", "naklon": 0 }, + "3525": { "label": "12/18", "naklon": 0 }, + "3558": { "label": "12/19", "naklon": 0 }, + "3511": { "label": "12/20", "naklon": 0 }, + "3058": { "label": "12/21", "naklon": 0 }, + "3062": { "label": "12/22", "naklon": 0 }, + "3070": { "label": "12/23", "naklon": 0 }, + "3447": { "label": "12/24", "naklon": 0 }, + "3056": { "label": "12/25", "naklon": 0 }, + "3057": { "label": "12/26", "naklon": 0 }, + "3071": { "label": "12/27", "naklon": 0 }, + "3061": { "label": "12/28", "naklon": 0 }, + "3069": { "label": "12/29", "naklon": 0 }, + "3077": { "label": "12/30", "naklon": 0 }, + "3080": { "label": "12/31", "naklon": 0 }, + "3081": { "label": "12/32", "naklon": 0 }, + "3078": { "label": "12/33", "naklon": 0 }, + "4037": { "label": "12/34", "naklon": 0 }, + "3067": { "label": "12/35", "naklon": 0 }, + "3051": { "label": "12/36", "naklon": 0 }, + "2924": { "label": "12/37", "naklon": 0 }, + "3060": { "label": "12/38", "naklon": 0 }, + "3073": { "label": "12/39", "naklon": 0 }, + "3469": { "label": "12/40", "naklon": 0 }, + "2923": { "label": "12/41", "naklon": 0 }, + "2925": { "label": "12/42", "naklon": 0 }, + "3359": { "label": "12/43", "naklon": 0 }, + "3055": { "label": "12/44", "naklon": 0 }, + "2922": { "label": "12/45", "naklon": 0 }, + "3084": { "label": "12/46", "naklon": 0 }, + "3064": { "label": "12/47", "naklon": 0 }, + "3066": { "label": "12/48", "naklon": 0 }, + "3072": { "label": "12/49", "naklon": 0 }, + "3415": { "label": "13/13A", "naklon": 0 }, + "3409": { "label": "13/13B", "naklon": 0 }, + "3399": { "label": "13/13C", "naklon": 0 }, + "3410": { "label": "13/29A", "naklon": 0 }, + "3407": { "label": "13/29B", "naklon": 0 }, + "3405": { "label": "13/34A", "naklon": 0 }, + "3404": { "label": "13/34B", "naklon": 0 }, + "3392": { "label": "13/45A", "naklon": 0 }, + "3386": { "label": "13/45B", "naklon": 0 }, + "3303": { "label": "13/60A", "naklon": 3 }, + "3302": { "label": "13/60B", "naklon": 3 }, + "3319": { "label": "13/70A", "naklon": 6 }, + "3317": { "label": "13/70B", "naklon": 6 }, + "3326": { "label": "13/70C", "naklon": 6 }, + "3351": { "label": "13/73A", "naklon": 6 }, + "3313": { "label": "13/73B", "naklon": 6 }, + "3316": { "label": "13/83A", "naklon": 0 }, + "3320": { "label": "13/83B", "naklon": 0 }, + "3336": { "label": "13/95A", "naklon": 0 }, + "3323": { "label": "13/95B", "naklon": 0 }, + "3339": { "label": "13/98A", "naklon": 0 }, + "3333": { "label": "13/98B", "naklon": 0 }, + "3425": { "label": "13/1", "naklon": 0 }, + "3419": { "label": "13/2", "naklon": 0 }, + "3416": { "label": "13/3", "naklon": 0 }, + "3332": { "label": "13/4", "naklon": 0 }, + "3422": { "label": "13/5", "naklon": 0 }, + "3417": { "label": "13/6", "naklon": 0 }, + "3418": { "label": "13/7", "naklon": 0 }, + "3424": { "label": "13/8", "naklon": 0 }, + "3334": { "label": "13/9", "naklon": 0 }, + "4363": { "label": "13/10", "naklon": 0 }, + "3423": { "label": "13/11", "naklon": 0 }, + "3406": { "label": "13/12", "naklon": 0 }, + "3411": { "label": "13/14", "naklon": 0 }, + "3412": { "label": "13/15", "naklon": 0 }, + "3413": { "label": "13/16", "naklon": 0 }, + "3414": { "label": "13/17", "naklon": 0 }, + "3391": { "label": "13/18", "naklon": 0 }, + "3370": { "label": "13/19", "naklon": 0 }, + "3369": { "label": "13/20", "naklon": 0 }, + "3408": { "label": "13/21", "naklon": 0 }, + "3393": { "label": "13/22", "naklon": 0 }, + "3128": { "label": "13/23", "naklon": 0 }, + "3197": { "label": "13/24", "naklon": 0 }, + "4364": { "label": "13/25", "naklon": 0 }, + "3155": { "label": "13/26", "naklon": 0 }, + "3196": { "label": "13/27", "naklon": 0 }, + "3144": { "label": "13/28", "naklon": 0 }, + "3150": { "label": "13/30", "naklon": 0 }, + "3390": { "label": "13/31", "naklon": 0 }, + "3401": { "label": "13/32", "naklon": 0 }, + "3275": { "label": "13/33", "naklon": 0 }, + "3371": { "label": "13/35", "naklon": 0 }, + "3389": { "label": "13/36", "naklon": 0 }, + "3388": { "label": "13/37", "naklon": 0 }, + "3365": { "label": "13/38", "naklon": 0 }, + "3363": { "label": "13/39", "naklon": 0 }, + "3397": { "label": "13/40", "naklon": 0 }, + "3567": { "label": "13/40/1", "naklon": 0 }, + "3387": { "label": "13/41", "naklon": 0 }, + "3403": { "label": "13/42", "naklon": 0 }, + "3147": { "label": "13/43", "naklon": 0 }, + "3141": { "label": "13/44", "naklon": 0 }, + "3364": { "label": "13/46", "naklon": 0 }, + "3367": { "label": "13/47", "naklon": 0 }, + "3368": { "label": "13/48", "naklon": 0 }, + "3402": { "label": "13/49", "naklon": 0 }, + "3366": { "label": "13/50", "naklon": 0 }, + "3395": { "label": "13/51", "naklon": 0 }, + "3372": { "label": "13/52", "naklon": 0 }, + "3394": { "label": "13/53", "naklon": 0 }, + "3308": { "label": "13/54", "naklon": 0 }, + "3847": { "label": "13/54/1", "naklon": 0 }, + "3312": { "label": "13/55", "naklon": 3 }, + "3309": { "label": "13/56", "naklon": 3 }, + "3311": { "label": "13/57", "naklon": 3 }, + "3310": { "label": "13/58", "naklon": 3 }, + "4365": { "label": "13/59", "naklon": 3 }, + "4093": { "label": "13/60/1", "naklon": 3 }, + "3304": { "label": "13/61", "naklon": 3 }, + "3307": { "label": "13/62", "naklon": 3 }, + "3271": { "label": "13/63", "naklon": 3 }, + "3301": { "label": "13/64", "naklon": 3 }, + "4366": { "label": "13/65", "naklon": 3 }, + "3300": { "label": "13/66", "naklon": 3 }, + "3185": { "label": "13/67", "naklon": 0 }, + "3184": { "label": "13/68", "naklon": 0 }, + "3188": { "label": "13/69", "naklon": 0 }, + "3343": { "label": "13/71", "naklon": 6 }, + "3819": { "label": "13/71/1", "naklon": 6 }, + "3880": { "label": "13/71/2", "naklon": 6 }, + "3348": { "label": "13/72", "naklon": 6 }, + "3344": { "label": "13/74", "naklon": 6 }, + "3346": { "label": "13/75", "naklon": 6 }, + "3597": { "label": "13/75/1", "naklon": 6 }, + "3345": { "label": "13/76", "naklon": 6 }, + "3322": { "label": "13/77", "naklon": 0 }, + "3325": { "label": "13/78", "naklon": 0 }, + "4310": { "label": "13/78/1", "naklon": 0 }, + "3315": { "label": "13/79", "naklon": 0 }, + "3328": { "label": "13/80", "naklon": 0 }, + "3321": { "label": "13/81", "naklon": 0 }, + "3324": { "label": "13/82", "naklon": 0 }, + "3140": { "label": "13/84", "naklon": 0 }, + "3153": { "label": "13/85", "naklon": 0 }, + "3145": { "label": "13/86", "naklon": 0 }, + "3134": { "label": "13/87", "naklon": 0 }, + "3151": { "label": "13/88", "naklon": 0 }, + "3143": { "label": "13/89", "naklon": 0 }, + "3318": { "label": "13/90", "naklon": 0 }, + "3347": { "label": "13/91", "naklon": 0 }, + "3314": { "label": "13/94", "naklon": 0 }, + "3331": { "label": "13/96", "naklon": 0 }, + "3327": { "label": "13/97", "naklon": 0 }, + "3329": { "label": "13/99", "naklon": 0 }, + "3337": { "label": "13/100", "naklon": 0 }, + "3330": { "label": "13/101", "naklon": 0 }, + "3335": { "label": "13/102", "naklon": 0 }, + "3420": { "label": "13/103", "naklon": 0 }, + "3421": { "label": "13/104", "naklon": 0 }, + "4361": { "label": "13/105", "naklon": 0 }, + "4362": { "label": "13/106", "naklon": 0 }, + "3526": { "label": "13/107", "naklon": 0 }, + "4424": { "label": "13/108", "naklon": null }, + "3561": { "label": "13/109", "naklon": null }, + "3527": { "label": "13/110", "naklon": null }, + "3521": { "label": "13/111", "naklon": null }, + "3552": { "label": "13/112", "naklon": null }, + "3544": { "label": "13/113", "naklon": null }, + "3534": { "label": "13/114", "naklon": null }, + "3516": { "label": "13/115", "naklon": null }, + "3513": { "label": "13/116", "naklon": null }, + "3565": { "label": "13/117", "naklon": null }, + "3866": { "label": "13/118", "naklon": null }, + "3136": { "label": "14/1", "naklon": 0 }, + "3137": { "label": "14/2", "naklon": 0 }, + "3135": { "label": "14/3", "naklon": 0 }, + "3149": { "label": "14/4", "naklon": 0 }, + "3142": { "label": "14/5", "naklon": 0 }, + "3342": { "label": "14/6", "naklon": 0 }, + "3340": { "label": "14/7", "naklon": 0 }, + "3152": { "label": "14/8", "naklon": 0 }, + "3886": { "label": "14/9", "naklon": 0 }, + "3341": { "label": "14/10", "naklon": null }, + "3352": { "label": "14/11", "naklon": null }, + "3396": { "label": "15/1", "naklon": 5 }, + "2784": { "label": "15/2", "naklon": 5 }, + "2788": { "label": "15/3", "naklon": 5 }, + "2801": { "label": "15/4", "naklon": 5 }, + "2815": { "label": "15/5", "naklon": 5 }, + "2829": { "label": "15/6", "naklon": 5 }, + "2796": { "label": "15/7", "naklon": 5 }, + "2803": { "label": "15/8", "naklon": 5 }, + "4304": { "label": "15/8/1", "naklon": 5 }, + "4311": { "label": "15/8/2", "naklon": 5 }, + "2821": { "label": "15/9", "naklon": 5 }, + "3400": { "label": "15/10", "naklon": 5 }, + "2799": { "label": "15/11", "naklon": 5 }, + "2804": { "label": "15/12", "naklon": 5 }, + "4303": { "label": "15/12/1", "naklon": 5 }, + "4309": { "label": "15/12/2", "naklon": 5 }, + "2806": { "label": "15/13", "naklon": 5 }, + "2787": { "label": "15/14", "naklon": 5 }, + "2809": { "label": "15/15", "naklon": 5 }, + "2814": { "label": "15/16", "naklon": 0 }, + "3934": { "label": "15/17", "naklon": 0 }, + "3192": { "label": "15/18", "naklon": 0 }, + "2812": { "label": "15/19", "naklon": 0 }, + "4070": { "label": "15/20", "naklon": 0 }, + "2826": { "label": "15/21", "naklon": 0 }, + "2808": { "label": "15/22", "naklon": 3 }, + "2795": { "label": "15/23", "naklon": 3 }, + "2807": { "label": "15/24", "naklon": 3 }, + "2831": { "label": "15/25", "naklon": 0 }, + "2862": { "label": "15/26", "naklon": null }, + "2861": { "label": "15/27", "naklon": 0 }, + "2866": { "label": "15/28", "naklon": 0 }, + "3546": { "label": "15/28/1", "naklon": 0 }, + "4146": { "label": "15/29", "naklon": 0 }, + "3001": { "label": "15/29/1", "naklon": 0 }, + "2835": { "label": "15/30", "naklon": 0 }, + "2874": { "label": "15/31", "naklon": 0 }, + "2852": { "label": "15/32", "naklon": 0 }, + "2851": { "label": "15/33", "naklon": 0 }, + "3560": { "label": "15/33/1", "naklon": 0 }, + "2858": { "label": "15/34", "naklon": 0 }, + "4306": { "label": "15/34/1", "naklon": 0 }, + "2856": { "label": "15/35", "naklon": 0 }, + "2847": { "label": "15/36", "naklon": 0 }, + "3556": { "label": "15/36/1", "naklon": 0 }, + "3950": { "label": "15/37", "naklon": 0 }, + "2848": { "label": "15/38", "naklon": 0 }, + "2863": { "label": "15/39", "naklon": 0 }, + "4313": { "label": "15/39/1", "naklon": 0 }, + "2873": { "label": "15/40", "naklon": 0 }, + "2984": { "label": "15/40/1", "naklon": 0 }, + "2854": { "label": "15/41", "naklon": 0 }, + "2859": { "label": "15/42", "naklon": 0 }, + "2872": { "label": "15/43", "naklon": 0 }, + "2849": { "label": "15/44", "naklon": 0 }, + "2864": { "label": "15/45", "naklon": 0 }, + "3553": { "label": "15/46", "naklon": null }, + "3021": { "label": "15/47", "naklon": null }, + "3008": { "label": "15/47/1", "naklon": null }, + "3017": { "label": "15/48", "naklon": null }, + "3014": { "label": "15/49", "naklon": null }, + "2981": { "label": "15/50", "naklon": null }, + "3020": { "label": "15/51", "naklon": null }, + "3027": { "label": "15/52", "naklon": null }, + "3006": { "label": "15/53", "naklon": null }, + "3012": { "label": "15/54", "naklon": null }, + "2738": { "label": "15/55", "naklon": 0 }, + "2725": { "label": "15/56", "naklon": 0 }, + "3016": { "label": "15/57", "naklon": null }, + "3005": { "label": "15/58", "naklon": null }, + "3009": { "label": "15/58/1", "naklon": null }, + "3010": { "label": "15/59", "naklon": 0 }, + "3538": { "label": "15/59/1", "naklon": 0 }, + "4145": { "label": "15/59/2", "naklon": 0 }, + "2713": { "label": "15/60", "naklon": 0 }, + "2789": { "label": "15/61", "naklon": 0 }, + "2736": { "label": "15/62", "naklon": 0 }, + "2739": { "label": "15/63", "naklon": 0 }, + "4346": { "label": "15/64", "naklon": 0 }, + "2731": { "label": "15/65", "naklon": 0 }, + "2818": { "label": "15/66", "naklon": 0 }, + "3557": { "label": "15/66/1", "naklon": 0 }, + "2822": { "label": "15/67", "naklon": 0 }, + "2833": { "label": "15/68", "naklon": 0 }, + "2834": { "label": "15/69", "naklon": 0 }, + "3097": { "label": "15/70", "naklon": 0 }, + "2824": { "label": "15/71", "naklon": 0 }, + "2828": { "label": "15/72", "naklon": 0 }, + "2600": { "label": "15/73", "naklon": 0 }, + "4314": { "label": "15/73/1", "naklon": 0 }, + "2832": { "label": "15/74", "naklon": 0 }, + "4360": { "label": "15/75", "naklon": 0 }, + "2846": { "label": "15/76", "naklon": 0 }, + "2584": { "label": "15/77", "naklon": 0 }, + "2843": { "label": "15/78", "naklon": 0 }, + "4308": { "label": "15/78/1", "naklon": 0 }, + "4144": { "label": "15/79", "naklon": null }, + "2844": { "label": "15/80", "naklon": 0 }, + "2842": { "label": "15/81", "naklon": 0 }, + "2838": { "label": "15/82", "naklon": 0 }, + "2837": { "label": "15/83", "naklon": null }, + "3555": { "label": "15/83/1", "naklon": null }, + "2839": { "label": "15/84", "naklon": 0 }, + "2830": { "label": "15/85", "naklon": 0 }, + "4066": { "label": "15/86", "naklon": 0 }, + "2836": { "label": "15/87", "naklon": 0 }, + "2911": { "label": "15/88", "naklon": 0 }, + "2825": { "label": "15/89", "naklon": 0 }, + "2811": { "label": "15/90", "naklon": 0 }, + "3740": { "label": "15/94", "naklon": 15 }, + "2734": { "label": "15/95", "naklon": 15 }, + "3105": { "label": "15/96", "naklon": 15 }, + "2732": { "label": "15/97", "naklon": 15 }, + "2727": { "label": "15/98", "naklon": 15 }, + "2735": { "label": "15/99", "naklon": 15 }, + "3926": { "label": "15/100", "naklon": 15 }, + "2918": { "label": "15/101", "naklon": 0 }, + "2705": { "label": "15/102", "naklon": 10 }, + "2708": { "label": "15/103", "naklon": 10 }, + "2721": { "label": "15/104", "naklon": 10 }, + "2719": { "label": "15/105", "naklon": 10 }, + "2919": { "label": "15/106", "naklon": 10 }, + "3101": { "label": "15/107", "naklon": 10 }, + "2853": { "label": "15/108", "naklon": 10 }, + "2715": { "label": "15/109", "naklon": 10 }, + "2712": { "label": "15/110", "naklon": 0 }, + "2711": { "label": "15/111", "naklon": 0 }, + "2709": { "label": "15/112", "naklon": 0 }, + "2710": { "label": "15/113", "naklon": 0 }, + "2907": { "label": "15/114", "naklon": 0 }, + "2906": { "label": "15/115", "naklon": 0 }, + "2908": { "label": "15/116", "naklon": 0 }, + "2901": { "label": "15/117", "naklon": 0 }, + "2913": { "label": "15/118", "naklon": 0 }, + "3656": { "label": "15/119", "naklon": 0 }, + "2781": { "label": "15/120", "naklon": 0 }, + "2802": { "label": "15/121", "naklon": 0 }, + "2791": { "label": "15/122", "naklon": 0 }, + "2783": { "label": "15/123", "naklon": 0 }, + "2794": { "label": "15/124", "naklon": 0 }, + "3139": { "label": "15/125", "naklon": 0 }, + "3229": { "label": "15/126", "naklon": 5 }, + "3239": { "label": "15/127", "naklon": 5 }, + "3230": { "label": "15/128", "naklon": 5 }, + "4016": { "label": "15/129", "naklon": null }, + "3608": { "label": "16/16A", "naklon": 0 }, + "4151": { "label": "16/16B", "naklon": 0 }, + "3710": { "label": "16/1", "naklon": 0 }, + "3726": { "label": "16/2", "naklon": 0 }, + "3743": { "label": "16/3", "naklon": 0 }, + "3724": { "label": "16/4", "naklon": 0 }, + "3712": { "label": "16/5", "naklon": 0 }, + "3739": { "label": "16/6", "naklon": 0 }, + "3742": { "label": "16/7", "naklon": 0 }, + "3731": { "label": "16/8", "naklon": 0 }, + "3727": { "label": "16/9", "naklon": 0 }, + "3729": { "label": "16/10", "naklon": 0 }, + "3736": { "label": "16/11", "naklon": 0 }, + "3713": { "label": "16/12", "naklon": 0 }, + "3715": { "label": "16/13", "naklon": 0 }, + "3733": { "label": "16/14", "naklon": 0 }, + "3732": { "label": "16/15", "naklon": 0 }, + "3634": { "label": "16/17", "naklon": 0 }, + "3610": { "label": "16/18", "naklon": 0 }, + "3626": { "label": "16/19", "naklon": 0 }, + "3618": { "label": "16/20", "naklon": 0 }, + "3619": { "label": "16/21", "naklon": 0 }, + "3628": { "label": "16/22", "naklon": 0 }, + "3615": { "label": "16/23", "naklon": 0 }, + "3609": { "label": "16/24", "naklon": 0 }, + "3606": { "label": "16/25", "naklon": 0 }, + "3624": { "label": "16/26", "naklon": 0 }, + "3627": { "label": "16/27", "naklon": 0 }, + "3607": { "label": "16/28", "naklon": 0 }, + "4370": { "label": "16/29", "naklon": 0 }, + "3692": { "label": "16/30", "naklon": 0 }, + "3614": { "label": "16/31", "naklon": 0 }, + "3623": { "label": "16/32", "naklon": 0 }, + "4373": { "label": "16/33", "naklon": 0 }, + "3620": { "label": "16/34", "naklon": 0 }, + "3685": { "label": "16/35", "naklon": 0 }, + "3616": { "label": "16/36", "naklon": 0 }, + "3686": { "label": "16/37", "naklon": 0 }, + "3688": { "label": "16/38", "naklon": 0 }, + "3684": { "label": "16/39", "naklon": 0 }, + "3825": { "label": "16/40", "naklon": 0 }, + "3865": { "label": "16/41", "naklon": 0 }, + "3824": { "label": "16/42", "naklon": 0 }, + "3871": { "label": "16/43", "naklon": 0 }, + "3801": { "label": "16/44", "naklon": 0 }, + "3862": { "label": "16/45", "naklon": 0 }, + "3876": { "label": "16/46", "naklon": 0 }, + "3861": { "label": "16/47", "naklon": 0 }, + "4215": { "label": "16/48", "naklon": 0 }, + "3605": { "label": "16/49", "naklon": 10 }, + "3603": { "label": "16/50", "naklon": 10 }, + "3592": { "label": "16/51", "naklon": 10 }, + "3598": { "label": "16/52", "naklon": 10 }, + "3594": { "label": "16/53", "naklon": 10 }, + "3593": { "label": "16/54", "naklon": 10 }, + "3630": { "label": "16/55", "naklon": 10 }, + "3763": { "label": "16/56", "naklon": 10 }, + "3746": { "label": "16/57", "naklon": 10 }, + "3699": { "label": "16/58", "naklon": 0 }, + "3698": { "label": "16/59", "naklon": 0 }, + "3709": { "label": "16/60", "naklon": null }, + "3708": { "label": "16/61", "naklon": 0 }, + "3703": { "label": "16/62", "naklon": null }, + "3700": { "label": "16/63", "naklon": 0 }, + "3701": { "label": "16/64", "naklon": null }, + "3704": { "label": "16/65", "naklon": 0 }, + "3707": { "label": "16/66", "naklon": null }, + "3810": { "label": "16/67", "naklon": 0 }, + "4208": { "label": "16/68", "naklon": null }, + "3867": { "label": "16/69", "naklon": 0 }, + "4372": { "label": "16/70", "naklon": null }, + "3881": { "label": "16/71", "naklon": 0 }, + "4204": { "label": "16/72", "naklon": null }, + "3869": { "label": "16/73", "naklon": 0 }, + "4202": { "label": "16/74", "naklon": null }, + "3830": { "label": "16/75", "naklon": 0 }, + "3870": { "label": "16/76", "naklon": null }, + "3964": { "label": "16/77", "naklon": 0 }, + "3849": { "label": "16/78", "naklon": 0 }, + "3694": { "label": "16/79", "naklon": null }, + "3717": { "label": "16/80", "naklon": 0 }, + "3877": { "label": "16/81", "naklon": null }, + "3755": { "label": "16/82", "naklon": 0 }, + "3725": { "label": "16/83", "naklon": null }, + "3716": { "label": "16/84", "naklon": 0 }, + "3696": { "label": "16/85", "naklon": null }, + "3702": { "label": "16/86", "naklon": 0 }, + "3706": { "label": "16/87", "naklon": null }, + "3850": { "label": "16/88", "naklon": 0 }, + "3848": { "label": "16/89", "naklon": null }, + "3737": { "label": "16/90", "naklon": null }, + "3705": { "label": "16/91", "naklon": 0 }, + "3723": { "label": "16/92", "naklon": null }, + "3842": { "label": "16/93", "naklon": 0 }, + "3735": { "label": "16/94", "naklon": null }, + "3719": { "label": "16/95", "naklon": 0 }, + "3697": { "label": "16/96", "naklon": 0 }, + "3711": { "label": "16/97", "naklon": 0 }, + "4107": { "label": "16/98", "naklon": null }, + "4112": { "label": "16/99", "naklon": 5 }, + "4106": { "label": "16/100", "naklon": 5 }, + "4111": { "label": "16/101", "naklon": 5 }, + "4091": { "label": "16/102", "naklon": null }, + "4104": { "label": "16/103", "naklon": 5 }, + "4094": { "label": "16/104", "naklon": null }, + "4089": { "label": "16/105", "naklon": 5 }, + "4095": { "label": "16/106", "naklon": null }, + "4102": { "label": "16/107", "naklon": 5 }, + "4105": { "label": "16/108", "naklon": null }, + "3859": { "label": "16/109", "naklon": null }, + "4090": { "label": "16/110", "naklon": 5 }, + "4110": { "label": "16/111", "naklon": null }, + "4097": { "label": "16/112", "naklon": 5 }, + "4099": { "label": "16/113", "naklon": null }, + "4096": { "label": "16/114", "naklon": null }, + "4101": { "label": "16/115", "naklon": 5 }, + "4109": { "label": "16/116", "naklon": null }, + "4092": { "label": "16/117", "naklon": 5 }, + "3631": { "label": "16/118", "naklon": null }, + "3632": { "label": "16/119", "naklon": 0 }, + "3641": { "label": "16/120", "naklon": null }, + "3638": { "label": "16/121", "naklon": 0 }, + "3637": { "label": "16/122", "naklon": null }, + "4142": { "label": "16/123", "naklon": null }, + "4147": { "label": "16/124", "naklon": 5 }, + "4139": { "label": "16/125", "naklon": 5 }, + "3172": { "label": "20/30A", "naklon": 2 }, + "3164": { "label": "20/30B", "naklon": 2 }, + "3247": { "label": "20/1", "naklon": 10 }, + "3296": { "label": "20/2", "naklon": 10 }, + "3246": { "label": "20/3", "naklon": 10 }, + "3270": { "label": "20/4", "naklon": 10 }, + "3294": { "label": "20/5", "naklon": 10 }, + "3298": { "label": "20/6", "naklon": 10 }, + "3297": { "label": "20/7", "naklon": 10 }, + "3293": { "label": "20/8", "naklon": 10 }, + "3299": { "label": "20/9", "naklon": 10 }, + "3295": { "label": "20/10", "naklon": 10 }, + "3244": { "label": "20/11", "naklon": 10 }, + "3249": { "label": "20/12", "naklon": 10 }, + "3268": { "label": "20/13", "naklon": 10 }, + "3245": { "label": "20/14", "naklon": 10 }, + "3278": { "label": "20/15", "naklon": 10 }, + "3280": { "label": "20/16", "naklon": 10 }, + "3292": { "label": "20/17", "naklon": 10 }, + "3287": { "label": "20/18", "naklon": 10 }, + "3282": { "label": "20/19", "naklon": 10 }, + "3273": { "label": "20/20", "naklon": 0 }, + "3157": { "label": "20/21", "naklon": 0 }, + "3283": { "label": "20/22", "naklon": 0 }, + "3159": { "label": "20/23", "naklon": 0 }, + "3289": { "label": "20/24", "naklon": 0 }, + "3163": { "label": "20/25", "naklon": 0 }, + "3126": { "label": "20/26", "naklon": 0 }, + "3171": { "label": "20/27", "naklon": 0 }, + "3162": { "label": "20/28", "naklon": 0 }, + "3279": { "label": "20/29", "naklon": 10 }, + "3173": { "label": "20/31", "naklon": 0 }, + "3127": { "label": "20/32", "naklon": 0 }, + "3131": { "label": "20/33", "naklon": 0 }, + "3129": { "label": "20/34", "naklon": 0 }, + "3276": { "label": "20/35", "naklon": 2 }, + "3290": { "label": "20/36", "naklon": 2 }, + "3132": { "label": "20/37", "naklon": 0 }, + "3138": { "label": "20/38", "naklon": 0 }, + "3272": { "label": "20/39", "naklon": 0 }, + "3291": { "label": "20/40", "naklon": 0 }, + "3277": { "label": "20/41", "naklon": 10 }, + "3286": { "label": "20/42", "naklon": 10 }, + "3281": { "label": "20/43", "naklon": 10 }, + "3288": { "label": "20/44", "naklon": 10 }, + "3284": { "label": "20/45", "naklon": 10 }, + "3167": { "label": "20/46", "naklon": 10 }, + "3872": { "label": "20/47", "naklon": 0 }, + "3124": { "label": "20/48", "naklon": 0 }, + "3133": { "label": "20/49", "naklon": 0 }, + "3158": { "label": "20/50", "naklon": 0 }, + "3169": { "label": "20/51", "naklon": 0 }, + "3146": { "label": "20/52", "naklon": 0 }, + "3160": { "label": "20/53", "naklon": 0 }, + "3248": { "label": "20/54", "naklon": 0 }, + "3156": { "label": "20/55", "naklon": 0 }, + "3161": { "label": "20/56", "naklon": 0 }, + "3170": { "label": "20/57", "naklon": 0 }, + "3168": { "label": "20/58", "naklon": 0 }, + "3125": { "label": "20/59", "naklon": 0 }, + "3166": { "label": "20/60", "naklon": 0 }, + "3130": { "label": "20/61", "naklon": 0 }, + "3563": { "label": "20/62", "naklon": 0 }, + "3550": { "label": "20/63", "naklon": null }, + "3269": { "label": "20/67", "naklon": 0 }, + "2921": { "label": "21/1", "naklon": 0 }, + "2707": { "label": "21/2", "naklon": 0 }, + "2723": { "label": "21/3", "naklon": 0 }, + "2716": { "label": "21/4", "naklon": 0 }, + "2717": { "label": "21/5", "naklon": 0 }, + "2720": { "label": "21/6", "naklon": 0 }, + "2722": { "label": "21/7", "naklon": 0 }, + "2718": { "label": "21/8", "naklon": 0 }, + "2724": { "label": "21/9", "naklon": 0 }, + "2742": { "label": "21/10", "naklon": 0 }, + "2743": { "label": "21/11", "naklon": 0 }, + "2733": { "label": "21/12", "naklon": 0 }, + "2903": { "label": "21/14", "naklon": 0 }, + "2917": { "label": "21/15", "naklon": 0 }, + "2897": { "label": "21/16", "naklon": 0 }, + "2914": { "label": "21/17", "naklon": 0 }, + "2898": { "label": "21/18", "naklon": 0 }, + "2773": { "label": "21/19", "naklon": 0 }, + "2895": { "label": "21/20", "naklon": 0 }, + "2896": { "label": "21/21", "naklon": 0 }, + "2771": { "label": "21/22", "naklon": 0 }, + "2772": { "label": "21/23", "naklon": 0 }, + "2793": { "label": "21/24", "naklon": 0 }, + "2902": { "label": "21/25", "naklon": 0 }, + "2910": { "label": "21/26", "naklon": 0 }, + "2909": { "label": "21/27", "naklon": 0 }, + "2920": { "label": "21/28", "naklon": 0 }, + "2916": { "label": "21/29", "naklon": 0 }, + "2904": { "label": "21/30", "naklon": 0 }, + "2915": { "label": "21/31", "naklon": 0 }, + "2905": { "label": "21/32", "naklon": 0 }, + "2900": { "label": "21/33", "naklon": 0 }, + "2899": { "label": "21/34", "naklon": 0 }, + "2741": { "label": "21/36", "naklon": 0 }, + "2714": { "label": "21/37", "naklon": 0 }, + "2701": { "label": "21/38", "naklon": 0 }, + "2703": { "label": "21/39", "naklon": 0 }, + "2704": { "label": "21/40", "naklon": 0 }, + "2702": { "label": "21/41", "naklon": 0 }, + "2706": { "label": "21/42", "naklon": 0 }, + "2776": { "label": "21/43", "naklon": 0 }, + "2770": { "label": "21/44", "naklon": 0 }, + "2786": { "label": "21/45", "naklon": 0 }, + "2779": { "label": "21/46", "naklon": 0 }, + "2782": { "label": "21/47", "naklon": 0 }, + "2785": { "label": "21/48", "naklon": 0 }, + "2769": { "label": "21/49", "naklon": 0 }, + "3354": { "label": "21/50", "naklon": 0 }, + "2778": { "label": "21/51", "naklon": 0 }, + "2775": { "label": "21/52", "naklon": 0 }, + "2780": { "label": "21/53", "naklon": 0 }, + "2790": { "label": "21/54", "naklon": 0 }, + "2792": { "label": "21/55", "naklon": 0 }, + "2774": { "label": "21/56", "naklon": 0 }, + "2630": { "label": "22/1", "naklon": 0 }, + "2631": { "label": "22/2", "naklon": 0 }, + "2632": { "label": "22/3", "naklon": 0 }, + "2633": { "label": "22/4", "naklon": 0 }, + "2634": { "label": "22/5", "naklon": 0 }, + "2636": { "label": "22/6", "naklon": 0 }, + "4367": { "label": "22/7", "naklon": 0 }, + "2637": { "label": "22/8", "naklon": 0 }, + "2638": { "label": "22/9", "naklon": 0 }, + "2639": { "label": "22/10", "naklon": 0 }, + "2640": { "label": "22/11", "naklon": 0 }, + "2641": { "label": "22/12", "naklon": 0 }, + "2642": { "label": "22/13", "naklon": 0 }, + "2643": { "label": "22/14", "naklon": 0 }, + "2644": { "label": "22/15", "naklon": 0 }, + "2645": { "label": "22/16", "naklon": 0 }, + "2646": { "label": "22/17", "naklon": 0 }, + "2647": { "label": "22/18", "naklon": 0 }, + "2648": { "label": "22/19", "naklon": 0 }, + "2649": { "label": "22/20", "naklon": 0 }, + "2650": { "label": "22/21", "naklon": 0 }, + "2651": { "label": "22/22", "naklon": 0 }, + "4103": { "label": "22/23", "naklon": 0 }, + "2653": { "label": "22/24", "naklon": 0 }, + "2654": { "label": "22/25", "naklon": 0 }, + "2655": { "label": "22/26", "naklon": 0 }, + "2656": { "label": "22/27", "naklon": 0 }, + "2657": { "label": "22/28", "naklon": 0 }, + "2658": { "label": "22/29", "naklon": 0 }, + "2659": { "label": "22/30", "naklon": 0 }, + "2660": { "label": "22/31", "naklon": 0 }, + "2661": { "label": "22/32", "naklon": 0 }, + "3015": { "label": "22/32/1", "naklon": 0 }, + "2662": { "label": "22/33", "naklon": 0 }, + "2663": { "label": "22/34", "naklon": 0 }, + "2664": { "label": "22/35", "naklon": 0 }, + "2665": { "label": "22/36", "naklon": 0 }, + "2666": { "label": "22/37", "naklon": 0 }, + "2667": { "label": "22/38", "naklon": 0 }, + "2668": { "label": "22/39", "naklon": 0 }, + "2669": { "label": "22/40", "naklon": null }, + "2670": { "label": "22/41", "naklon": null }, + "2671": { "label": "22/42", "naklon": null }, + "3087": { "label": "23/9A", "naklon": 10 }, + "3090": { "label": "23/9B", "naklon": 10 }, + "3075": { "label": "23/1", "naklon": 0 }, + "3089": { "label": "23/2", "naklon": 0 }, + "3088": { "label": "23/3", "naklon": 0 }, + "3228": { "label": "23/4", "naklon": 10 }, + "2751": { "label": "23/5", "naklon": 10 }, + "3243": { "label": "23/6", "naklon": 10 }, + "4349": { "label": "23/7", "naklon": 10 }, + "3102": { "label": "23/8", "naklon": 10 }, + "3099": { "label": "23/10", "naklon": 10 }, + "3103": { "label": "23/11", "naklon": 10 }, + "3093": { "label": "23/12", "naklon": 10 }, + "3098": { "label": "23/13", "naklon": 10 }, + "3092": { "label": "23/14", "naklon": 10 }, + "3233": { "label": "23/15", "naklon": 0 }, + "3095": { "label": "23/16", "naklon": 0 }, + "4074": { "label": "23/17", "naklon": 0 }, + "2729": { "label": "23/18", "naklon": 0 }, + "3234": { "label": "23/19", "naklon": 0 }, + "3094": { "label": "23/20", "naklon": 0 }, + "2817": { "label": "23/21", "naklon": 0 }, + "3226": { "label": "23/22", "naklon": 0 }, + "3225": { "label": "23/23", "naklon": 0 }, + "3237": { "label": "23/24", "naklon": 0 }, + "4250": { "label": "23/25", "naklon": 0 }, + "3059": { "label": "23/26", "naklon": 10 }, + "3238": { "label": "23/27", "naklon": 10 }, + "3242": { "label": "23/28", "naklon": 10 }, + "3236": { "label": "23/29", "naklon": 10 }, + "3112": { "label": "23/30", "naklon": 10 }, + "3224": { "label": "23/31", "naklon": 0 }, + "4298": { "label": "23/32", "naklon": 10 }, + "4150": { "label": "23/33", "naklon": 10 }, + "3091": { "label": "23/34", "naklon": 10 }, + "3771": { "label": "25/1", "naklon": 5 }, + "3777": { "label": "25/2", "naklon": 5 }, + "3749": { "label": "25/3", "naklon": 5 }, + "3769": { "label": "25/4", "naklon": 5 }, + "3765": { "label": "25/5", "naklon": 5 }, + "3785": { "label": "25/6", "naklon": 5 }, + "3761": { "label": "25/7", "naklon": 5 }, + "3758": { "label": "25/8", "naklon": 5 }, + "3766": { "label": "25/9", "naklon": 5 }, + "3779": { "label": "25/10", "naklon": 5 }, + "3899": { "label": "25/11", "naklon": 10 }, + "3922": { "label": "25/12", "naklon": 10 }, + "3912": { "label": "25/13", "naklon": 10 }, + "3933": { "label": "25/14", "naklon": 10 }, + "3921": { "label": "25/15", "naklon": 10 }, + "4300": { "label": "25/16", "naklon": 10 }, + "3927": { "label": "25/17", "naklon": 10 }, + "3212": { "label": "25/18", "naklon": 10 }, + "3208": { "label": "25/19", "naklon": 10 }, + "3207": { "label": "25/20", "naklon": 10 }, + "4294": { "label": "25/21", "naklon": 10 }, + "3209": { "label": "25/22", "naklon": 10 }, + "3745": { "label": "25/23", "naklon": 10 }, + "3762": { "label": "25/24", "naklon": 10 }, + "3215": { "label": "25/25", "naklon": 10 }, + "3210": { "label": "25/26", "naklon": 10 }, + "3211": { "label": "25/27", "naklon": 10 }, + "3206": { "label": "25/28", "naklon": 10 }, + "3918": { "label": "25/29", "naklon": 5 }, + "3928": { "label": "25/30", "naklon": 5 }, + "3917": { "label": "25/31", "naklon": 5 }, + "4029": { "label": "25/32", "naklon": 0 }, + "4038": { "label": "25/33", "naklon": 0 }, + "4022": { "label": "25/34", "naklon": 0 }, + "3937": { "label": "25/35", "naklon": 0 }, + "3190": { "label": "25/36", "naklon": 0 }, + "3835": { "label": "25/37", "naklon": 0 }, + "3201": { "label": "25/38", "naklon": 0 }, + "3193": { "label": "25/39", "naklon": 0 }, + "3191": { "label": "25/40", "naklon": 0 }, + "3203": { "label": "25/41", "naklon": 0 }, + "4301": { "label": "25/42", "naklon": 0 }, + "3223": { "label": "25/43", "naklon": 0 }, + "3202": { "label": "25/44", "naklon": 0 }, + "3205": { "label": "25/45", "naklon": 0 }, + "3194": { "label": "25/46", "naklon": 0 }, + "3198": { "label": "25/47", "naklon": 0 }, + "3204": { "label": "25/48", "naklon": 0 }, + "3200": { "label": "25/49", "naklon": 0 }, + "3216": { "label": "25/50", "naklon": 0 }, + "3932": { "label": "25/51", "naklon": 5 }, + "3923": { "label": "25/52", "naklon": 5 }, + "3913": { "label": "25/53", "naklon": 5 }, + "3900": { "label": "25/54", "naklon": 5 }, + "4189": { "label": "25/55", "naklon": 10 }, + "4191": { "label": "25/56", "naklon": 10 }, + "3790": { "label": "25/57", "naklon": 10 }, + "4190": { "label": "25/58", "naklon": 10 }, + "4302": { "label": "25/59", "naklon": 0 }, + "4351": { "label": "25/60", "naklon": 0 }, + "4075": { "label": "25/61", "naklon": 0 }, + "4071": { "label": "25/62", "naklon": 0 }, + "3784": { "label": "25/63", "naklon": 0 }, + "4065": { "label": "25/64", "naklon": 0 }, + "4297": { "label": "25/65", "naklon": 0 }, + "4295": { "label": "25/66", "naklon": 0 }, + "4299": { "label": "25/67", "naklon": 0 }, + "3772": { "label": "25/68", "naklon": 0 }, + "3941": { "label": "25/69", "naklon": 0 }, + "3782": { "label": "25/70", "naklon": 0 }, + "4068": { "label": "25/71", "naklon": 0 }, + "4073": { "label": "25/72", "naklon": 0 }, + "3901": { "label": "25/73", "naklon": 5 }, + "4296": { "label": "25/74", "naklon": 5 }, + "3910": { "label": "25/75", "naklon": 5 }, + "4293": { "label": "25/76", "naklon": 5 }, + "3919": { "label": "25/77", "naklon": 5 }, + "3924": { "label": "25/78", "naklon": 5 }, + "3909": { "label": "25/79", "naklon": 5 }, + "3896": { "label": "25/80", "naklon": 5 }, + "3911": { "label": "25/81", "naklon": 5 }, + "2819": { "label": "25/82", "naklon": 15 }, + "3776": { "label": "25/83", "naklon": 15 }, + "3752": { "label": "25/84", "naklon": 15 }, + "4353": { "label": "25/85", "naklon": 15 }, + "3791": { "label": "25/86", "naklon": 0 }, + "3770": { "label": "25/87", "naklon": 0 }, + "3760": { "label": "25/88", "naklon": 0 }, + "3115": { "label": "25/89", "naklon": 0 }, + "3738": { "label": "25/90", "naklon": 0 }, + "3748": { "label": "25/91", "naklon": 0 }, + "3753": { "label": "25/92", "naklon": 0 }, + "3775": { "label": "25/93", "naklon": 0 }, + "3778": { "label": "25/94", "naklon": 5 }, + "4078": { "label": "25/95", "naklon": 5 }, + "4088": { "label": "25/96", "naklon": 5 }, + "3856": { "label": "25/97", "naklon": 5 }, + "4084": { "label": "25/98", "naklon": 5 }, + "4069": { "label": "25/99", "naklon": 5 }, + "4188": { "label": "25/100", "naklon": 5 }, + "4064": { "label": "25/101", "naklon": 5 }, + "3792": { "label": "25/102", "naklon": 5 }, + "3780": { "label": "25/103", "naklon": 5 }, + "4034": { "label": "25/104", "naklon": 5 }, + "4072": { "label": "25/105", "naklon": 5 }, + "3884": { "label": "25/106", "naklon": 5 }, + "3793": { "label": "25/107", "naklon": 5 }, + "3863": { "label": "25/108", "naklon": 5 }, + "3855": { "label": "25/109", "naklon": 5 }, + "3846": { "label": "33/1", "naklon": 0 }, + "3943": { "label": "33/2", "naklon": 0 }, + "3903": { "label": "33/3", "naklon": 0 }, + "3982": { "label": "33/4", "naklon": 0 }, + "3879": { "label": "33/5", "naklon": 0 }, + "3887": { "label": "33/6", "naklon": 0 }, + "3920": { "label": "33/7", "naklon": 5 }, + "3942": { "label": "33/8", "naklon": 5 }, + "3829": { "label": "33/9", "naklon": null }, + "3452": { "label": "34/79A", "naklon": 6 }, + "3460": { "label": "34/79B", "naklon": 6 }, + "3443": { "label": "34/90A", "naklon": 6 }, + "3445": { "label": "34/90B", "naklon": 6 }, + "3457": { "label": "34/90C", "naklon": 6 }, + "3461": { "label": "34/97A", "naklon": 6 }, + "3463": { "label": "34/97B", "naklon": 6 }, + "3426": { "label": "34/98A", "naklon": 6 }, + "3444": { "label": "34/98B", "naklon": 6 }, + "3453": { "label": "34/99A", "naklon": 6 }, + "3455": { "label": "34/99B", "naklon": 6 }, + "4009": { "label": "34/1", "naklon": 0 }, + "3602": { "label": "34/2", "naklon": 0 }, + "3441": { "label": "34/3", "naklon": 0 }, + "3464": { "label": "34/4", "naklon": 0 }, + "3883": { "label": "34/5", "naklon": 0 }, + "4098": { "label": "34/6", "naklon": 0 }, + "4003": { "label": "34/7", "naklon": 0 }, + "4004": { "label": "34/8", "naklon": 0 }, + "3888": { "label": "34/9", "naklon": 0 }, + "3997": { "label": "34/10", "naklon": 0 }, + "4006": { "label": "34/11", "naklon": 0 }, + "4000": { "label": "34/12", "naklon": 0 }, + "4011": { "label": "34/13", "naklon": 0 }, + "3999": { "label": "34/14", "naklon": 0 }, + "3981": { "label": "34/15", "naklon": 0 }, + "3988": { "label": "34/16", "naklon": 0 }, + "3986": { "label": "34/17", "naklon": 0 }, + "3998": { "label": "34/18", "naklon": 0 }, + "3983": { "label": "34/19", "naklon": 0 }, + "4005": { "label": "34/20", "naklon": 0 }, + "4001": { "label": "34/21", "naklon": 0 }, + "4008": { "label": "34/22", "naklon": 0 }, + "4002": { "label": "34/23", "naklon": 0 }, + "3996": { "label": "34/24", "naklon": 0 }, + "4007": { "label": "34/25", "naklon": 0 }, + "4113": { "label": "34/26", "naklon": 15 }, + "3595": { "label": "34/27", "naklon": 5 }, + "3599": { "label": "34/28", "naklon": 5 }, + "3601": { "label": "34/29", "naklon": 5 }, + "4205": { "label": "34/30", "naklon": 0 }, + "3987": { "label": "34/31", "naklon": null }, + "4214": { "label": "34/32", "naklon": 0 }, + "4226": { "label": "34/33", "naklon": 0 }, + "4209": { "label": "34/34", "naklon": 0 }, + "4201": { "label": "34/35", "naklon": 0 }, + "3440": { "label": "34/36", "naklon": 0 }, + "3465": { "label": "34/37", "naklon": 0 }, + "3446": { "label": "34/38", "naklon": 0 }, + "4039": { "label": "34/39", "naklon": 5 }, + "4057": { "label": "34/40", "naklon": 5 }, + "3985": { "label": "34/41", "naklon": 0 }, + "3882": { "label": "34/42", "naklon": 0 }, + "4040": { "label": "34/43", "naklon": 5 }, + "3231": { "label": "34/44", "naklon": 0 }, + "3227": { "label": "34/45", "naklon": 0 }, + "3431": { "label": "34/46", "naklon": 0 }, + "4013": { "label": "34/47", "naklon": 0 }, + "4045": { "label": "34/48", "naklon": 0 }, + "3949": { "label": "34/49", "naklon": 0 }, + "3953": { "label": "34/50", "naklon": 0 }, + "3952": { "label": "34/51", "naklon": 0 }, + "3995": { "label": "34/52", "naklon": 0 }, + "3992": { "label": "34/53", "naklon": 0 }, + "4198": { "label": "34/54", "naklon": 0 }, + "3935": { "label": "34/55", "naklon": 0 }, + "4050": { "label": "34/56", "naklon": 0 }, + "4049": { "label": "34/57", "naklon": 0 }, + "4054": { "label": "34/58", "naklon": 0 }, + "3663": { "label": "34/59", "naklon": 6 }, + "3661": { "label": "34/60", "naklon": 6 }, + "3664": { "label": "34/61", "naklon": 6 }, + "3660": { "label": "34/62", "naklon": 6 }, + "3662": { "label": "34/63", "naklon": 6 }, + "3665": { "label": "34/65", "naklon": 6 }, + "3667": { "label": "34/66", "naklon": 6 }, + "3675": { "label": "34/67", "naklon": 6 }, + "3666": { "label": "34/68", "naklon": 6 }, + "3652": { "label": "34/69", "naklon": 6 }, + "3458": { "label": "34/70", "naklon": 6 }, + "4425": { "label": "34/70/1", "naklon": 6 }, + "3459": { "label": "34/71", "naklon": 6 }, + "3435": { "label": "34/72", "naklon": 6 }, + "3448": { "label": "34/73", "naklon": 6 }, + "3451": { "label": "34/74", "naklon": 6 }, + "3442": { "label": "34/75", "naklon": 6 }, + "3449": { "label": "34/76", "naklon": 6 }, + "3450": { "label": "34/77", "naklon": 6 }, + "3433": { "label": "34/78", "naklon": 6 }, + "3432": { "label": "34/80", "naklon": 12 }, + "3470": { "label": "34/81", "naklon": 12 }, + "3438": { "label": "34/82", "naklon": 12 }, + "3439": { "label": "34/83", "naklon": 12 }, + "4028": { "label": "34/84", "naklon": 5 }, + "3596": { "label": "34/85", "naklon": 5 }, + "4021": { "label": "34/86", "naklon": 5 }, + "3437": { "label": "34/87", "naklon": 12 }, + "3428": { "label": "34/88", "naklon": 12 }, + "3430": { "label": "34/89", "naklon": 12 }, + "3454": { "label": "34/91", "naklon": 6 }, + "3492": { "label": "34/92", "naklon": 6 }, + "3462": { "label": "34/93", "naklon": 6 }, + "3427": { "label": "34/94", "naklon": 6 }, + "3434": { "label": "34/95", "naklon": 6 }, + "3456": { "label": "34/96", "naklon": 6 }, + "4307": { "label": "34/98/1", "naklon": 6 }, + "3968": { "label": "35/1", "naklon": 0 }, + "3969": { "label": "35/2", "naklon": 0 }, + "3947": { "label": "35/3", "naklon": 0 }, + "3979": { "label": "35/4", "naklon": 0 }, + "3959": { "label": "35/5", "naklon": 0 }, + "3948": { "label": "35/6", "naklon": 0 }, + "3961": { "label": "35/7", "naklon": 0 }, + "3956": { "label": "35/8", "naklon": 0 }, + "3604": { "label": "35/9", "naklon": 0 }, + "3944": { "label": "35/10", "naklon": 0 }, + "3960": { "label": "35/11", "naklon": 0 }, + "3958": { "label": "35/12", "naklon": 0 }, + "4036": { "label": "35/13", "naklon": 5 }, + "3893": { "label": "35/18", "naklon": 5 }, + "4108": { "label": "35/19", "naklon": 5 }, + "4017": { "label": "35/20", "naklon": 5 }, + "3963": { "label": "35/21", "naklon": 0 }, + "3658": { "label": "35/22", "naklon": 0 }, + "3975": { "label": "35/23", "naklon": 0 }, + "3980": { "label": "35/24", "naklon": 0 }, + "4012": { "label": "35/25", "naklon": 0 }, + "3655": { "label": "35/26", "naklon": 0 }, + "3962": { "label": "35/27", "naklon": 0 }, + "3945": { "label": "35/28", "naklon": 0 }, + "3569": { "label": "35/29", "naklon": 0 }, + "3429": { "label": "35/30", "naklon": 0 }, + "3657": { "label": "35/31", "naklon": 0 }, + "3646": { "label": "35/32", "naklon": 0 }, + "3622": { "label": "35/33", "naklon": 0 }, + "3612": { "label": "35/34", "naklon": 0 }, + "3955": { "label": "35/35", "naklon": 0 }, + "3878": { "label": "35/37", "naklon": 0 }, + "3965": { "label": "35/38", "naklon": 0 }, + "3970": { "label": "35/39", "naklon": 0 }, + "3611": { "label": "35/40", "naklon": 0 }, + "2635": { "label": "35/41", "naklon": 0 }, + "3978": { "label": "35/42", "naklon": 0 }, + "4213": { "label": "35/43", "naklon": 0 }, + "3984": { "label": "35/44", "naklon": 0 }, + "4218": { "label": "35/45", "naklon": 0 }, + "3973": { "label": "35/46", "naklon": 0 }, + "3974": { "label": "35/47", "naklon": 0 }, + "3759": { "label": "35/48", "naklon": 0 }, + "3844": { "label": "35/49", "naklon": 0 }, + "3804": { "label": "35/50", "naklon": 0 }, + "3831": { "label": "35/51", "naklon": 0 }, + "3643": { "label": "35/52", "naklon": 0 }, + "3966": { "label": "35/53", "naklon": 0 }, + "3971": { "label": "35/54", "naklon": 0 }, + "3650": { "label": "35/55", "naklon": 6 }, + "3651": { "label": "35/56", "naklon": 6 }, + "3669": { "label": "35/57", "naklon": 6 }, + "3648": { "label": "35/58", "naklon": 6 }, + "3645": { "label": "35/59", "naklon": 6 }, + "3659": { "label": "35/60", "naklon": 6 }, + "3647": { "label": "35/61", "naklon": 6 }, + "3644": { "label": "35/62", "naklon": 6 }, + "3671": { "label": "35/63", "naklon": 6 }, + "3682": { "label": "35/64", "naklon": 6 }, + "3672": { "label": "35/65", "naklon": 6 }, + "3683": { "label": "35/66", "naklon": 6 }, + "3673": { "label": "35/67", "naklon": 6 }, + "3674": { "label": "35/68", "naklon": 6 }, + "3679": { "label": "35/69", "naklon": 6 }, + "3649": { "label": "35/70", "naklon": 6 }, + "3687": { "label": "35/71", "naklon": 6 }, + "3677": { "label": "35/72", "naklon": 6 }, + "3690": { "label": "35/73", "naklon": 6 }, + "3691": { "label": "35/74", "naklon": 6 }, + "3676": { "label": "35/75", "naklon": 6 }, + "3680": { "label": "35/76", "naklon": 6 }, + "3668": { "label": "35/77", "naklon": 6 }, + "3681": { "label": "35/78", "naklon": 6 }, + "3670": { "label": "35/79", "naklon": 6 }, + "3689": { "label": "35/80", "naklon": 6 }, + "3678": { "label": "35/81", "naklon": 6 }, + "3693": { "label": "35/82", "naklon": 6 }, + "3654": { "label": "35/83", "naklon": null }, + "4086": { "label": "36/1", "naklon": 0 }, + "4085": { "label": "36/2", "naklon": 0 }, + "4083": { "label": "36/3", "naklon": 0 }, + "4087": { "label": "36/4", "naklon": 0 }, + "4077": { "label": "36/5", "naklon": 0 }, + "4082": { "label": "36/6", "naklon": 0 }, + "4186": { "label": "36/7", "naklon": 0 }, + "4206": { "label": "36/8", "naklon": 0 }, + "4080": { "label": "36/9", "naklon": 0 }, + "4081": { "label": "36/10", "naklon": 0 }, + "4210": { "label": "36/11", "naklon": 0 }, + "4079": { "label": "36/12", "naklon": 0 }, + "4076": { "label": "36/13", "naklon": 0 }, + "3852": { "label": "36/14", "naklon": 0 }, + "2813": { "label": "36/15", "naklon": 0 }, + "4219": { "label": "36/16", "naklon": 0 }, + "3104": { "label": "37/1A", "naklon": 15 }, + "3121": { "label": "37/1B", "naklon": 15 }, + "3113": { "label": "37/2", "naklon": 10 }, + "3118": { "label": "37/3", "naklon": 10 }, + "3111": { "label": "37/4", "naklon": 10 }, + "4020": { "label": "37/5", "naklon": 10 }, + "3119": { "label": "37/6", "naklon": 10 }, + "3110": { "label": "37/7", "naklon": 10 }, + "3108": { "label": "37/8", "naklon": 10 }, + "3107": { "label": "37/12", "naklon": 0 }, + "3199": { "label": "37/13", "naklon": 0 }, + "3120": { "label": "37/14", "naklon": 0 }, + "3122": { "label": "37/15", "naklon": 0 }, + "3908": { "label": "37/16", "naklon": 0 }, + "3114": { "label": "37/17", "naklon": 0 }, + "3105": { "label": "37/18", "naklon": 0 }, + "3116": { "label": "37/19", "naklon": 0 }, + "3106": { "label": "37/20", "naklon": 0 }, + "2887": { "label": "37/21", "naklon": 5 }, + "2888": { "label": "37/22", "naklon": 5 }, + "2877": { "label": "37/23", "naklon": 5 }, + "2891": { "label": "37/24", "naklon": 5 }, + "2886": { "label": "37/25", "naklon": 5 }, + "2892": { "label": "37/26", "naklon": 5 }, + "2882": { "label": "37/27", "naklon": 5 }, + "2883": { "label": "37/28", "naklon": 5 }, + "2876": { "label": "37/29", "naklon": 5 }, + "3109": { "label": "37/30", "naklon": 5 }, + "4152": { "label": "37/31", "naklon": 5 }, + "3117": { "label": "37/32", "naklon": 5 }, + "2870": { "label": "37/33", "naklon": 5 }, + "2867": { "label": "37/34", "naklon": 0 }, + "2865": { "label": "37/35", "naklon": 0 }, + "3096": { "label": "37/36", "naklon": 0 }, + "2871": { "label": "37/37", "naklon": 0 }, + "2884": { "label": "37/38", "naklon": 0 }, + "2855": { "label": "37/39", "naklon": 0 }, + "2878": { "label": "37/40", "naklon": 0 }, + "2889": { "label": "37/41", "naklon": 0 }, + "2879": { "label": "37/42", "naklon": 0 }, + "2850": { "label": "37/43", "naklon": 0 }, + "2894": { "label": "37/44", "naklon": 0 }, + "2880": { "label": "37/45", "naklon": 0 }, + "2893": { "label": "37/46", "naklon": 0 }, + "2890": { "label": "37/47", "naklon": 0 }, + "4355": { "label": "37/48", "naklon": 0 }, + "2885": { "label": "37/49", "naklon": 0 }, + "2875": { "label": "37/50", "naklon": 0 }, + "3486": { "label": "38/30A", "naklon": 5 }, + "3714": { "label": "38/30B", "naklon": 0 }, + "3483": { "label": "38/32A", "naklon": 5 }, + "3496": { "label": "38/32B", "naklon": 0 }, + "3487": { "label": "38/35A", "naklon": 5 }, + "3498": { "label": "38/35B", "naklon": 5 }, + "3578": { "label": "38/38A", "naklon": 5 }, + "3508": { "label": "38/38B", "naklon": 5 }, + "3787": { "label": "38/59A", "naklon": 5 }, + "3491": { "label": "38/59B", "naklon": 5 }, + "3568": { "label": "38/1", "naklon": null }, + "3502": { "label": "38/2", "naklon": 0 }, + "3836": { "label": "38/3", "naklon": 0 }, + "3588": { "label": "38/4", "naklon": 0 }, + "3493": { "label": "38/5", "naklon": 0 }, + "3580": { "label": "38/6", "naklon": 0 }, + "3572": { "label": "38/7", "naklon": 0 }, + "3506": { "label": "38/8", "naklon": 0 }, + "3503": { "label": "38/9", "naklon": 0 }, + "3579": { "label": "38/10", "naklon": 0 }, + "3586": { "label": "38/11", "naklon": 0 }, + "3495": { "label": "38/12", "naklon": 5 }, + "3492": { "label": "38/13", "naklon": 5 }, + "3532": { "label": "38/14", "naklon": 5 }, + "3574": { "label": "38/15", "naklon": 5 }, + "4140": { "label": "38/16", "naklon": 5 }, + "3795": { "label": "38/17", "naklon": 5 }, + "3788": { "label": "38/18", "naklon": 5 }, + "3796": { "label": "38/19", "naklon": 5 }, + "3797": { "label": "38/20", "naklon": 5 }, + "3798": { "label": "38/21", "naklon": 5 }, + "3786": { "label": "38/22", "naklon": 5 }, + "4067": { "label": "38/23", "naklon": 5 }, + "3773": { "label": "38/24", "naklon": 5 }, + "3774": { "label": "38/25", "naklon": 5 }, + "3789": { "label": "38/26", "naklon": 5 }, + "3520": { "label": "38/27", "naklon": null }, + "3577": { "label": "38/29", "naklon": 5 }, + "3530": { "label": "38/31", "naklon": null }, + "3488": { "label": "38/33", "naklon": 5 }, + "3505": { "label": "38/34", "naklon": 5 }, + "3497": { "label": "38/36", "naklon": 5 }, + "3490": { "label": "38/37", "naklon": 5 }, + "3585": { "label": "38/39", "naklon": 5 }, + "3582": { "label": "38/40", "naklon": 5 }, + "3507": { "label": "38/41", "naklon": 5 }, + "3484": { "label": "38/42", "naklon": 5 }, + "3501": { "label": "38/43", "naklon": 5 }, + "3581": { "label": "38/44", "naklon": 5 }, + "4192": { "label": "38/45", "naklon": 5 }, + "3576": { "label": "38/46", "naklon": 5 }, + "3489": { "label": "38/47", "naklon": 5 }, + "3573": { "label": "38/48", "naklon": 5 }, + "3504": { "label": "38/49", "naklon": 5 }, + "3794": { "label": "38/50", "naklon": 5 }, + "3485": { "label": "38/51", "naklon": 5 }, + "3482": { "label": "38/52", "naklon": 5 }, + "3575": { "label": "38/53", "naklon": 5 }, + "3499": { "label": "38/54", "naklon": 5 }, + "3494": { "label": "38/55", "naklon": 5 }, + "3583": { "label": "38/56", "naklon": 5 }, + "3570": { "label": "38/57", "naklon": 5 }, + "3500": { "label": "38/58", "naklon": 0 }, + "3510": { "label": "38/63", "naklon": null }, + "3512": { "label": "38/64", "naklon": null }, + "3535": { "label": "38/67", "naklon": null }, + "3531": { "label": "38/68", "naklon": null }, + "3537": { "label": "38/69", "naklon": null }, + "3522": { "label": "39/1", "naklon": 10 }, + "4018": { "label": "39/2", "naklon": 10 }, + "4019": { "label": "39/3", "naklon": 10 }, + "4154": { "label": "39/4", "naklon": 5 }, + "3907": { "label": "39/5", "naklon": 5 }, + "4148": { "label": "39/6", "naklon": 0 }, + "4153": { "label": "39/7", "naklon": 0 }, + "3938": { "label": "39/8", "naklon": 0 }, + "3802": { "label": "39/9", "naklon": 0 }, + "4015": { "label": "39/10", "naklon": 0 }, + "3929": { "label": "39/11", "naklon": 0 }, + "3946": { "label": "39/12", "naklon": 0 }, + "4014": { "label": "39/13", "naklon": 0 }, + "4155": { "label": "39/14", "naklon": 0 }, + "4149": { "label": "39/15", "naklon": 0 }, + "3642": { "label": "39/16", "naklon": 0 }, + "3636": { "label": "39/17", "naklon": 5 }, + "3991": { "label": "39/18", "naklon": 0 }, + "3994": { "label": "39/19", "naklon": 0 }, + "3990": { "label": "39/20", "naklon": 0 }, + "3967": { "label": "39/21", "naklon": 0 }, + "3977": { "label": "39/22", "naklon": 0 }, + "3757": { "label": "39/23", "naklon": 15 }, + "3633": { "label": "39/24", "naklon": 15 }, + "3744": { "label": "39/25", "naklon": 15 }, + "4023": { "label": "39/26", "naklon": 5 }, + "3720": { "label": "39/27", "naklon": 5 }, + "3734": { "label": "39/28", "naklon": 5 }, + "3741": { "label": "39/29", "naklon": 5 }, + "3721": { "label": "39/30", "naklon": 5 }, + "3845": { "label": "39/31", "naklon": 0 }, + "3840": { "label": "39/32", "naklon": 0 }, + "3837": { "label": "39/33", "naklon": null }, + "3839": { "label": "39/34", "naklon": 0 }, + "3542": { "label": "41/1", "naklon": null }, + "3566": { "label": "41/2", "naklon": null }, + "3548": { "label": "41/3", "naklon": null }, + "3515": { "label": "41/4", "naklon": null }, + "3559": { "label": "41/5", "naklon": null }, + "3509": { "label": "41/6", "naklon": null }, + "3524": { "label": "41/7", "naklon": null }, + "3518": { "label": "41/8", "naklon": null }, + "3182": { "label": "41/9", "naklon": null }, + "3187": { "label": "41/10", "naklon": null }, + "3195": { "label": "41/11", "naklon": 0 }, + "3857": { "label": "41/12", "naklon": 0 }, + "3183": { "label": "41/13", "naklon": 0 }, + "3177": { "label": "41/14", "naklon": 0 }, + "3189": { "label": "41/15", "naklon": 0 }, + "3186": { "label": "41/16", "naklon": 0 }, + "3178": { "label": "42/1", "naklon": 0 }, + "3219": { "label": "42/2", "naklon": 0 }, + "3475": { "label": "42/3", "naklon": 0 }, + "3175": { "label": "42/4", "naklon": 0 }, + "3222": { "label": "42/5", "naklon": 0 }, + "3221": { "label": "42/6", "naklon": 0 }, + "3181": { "label": "42/7", "naklon": 0 }, + "3180": { "label": "42/8", "naklon": 0 }, + "3218": { "label": "42/9", "naklon": 0 }, + "3176": { "label": "42/10", "naklon": 0 }, + "3174": { "label": "42/11", "naklon": 0 }, + "3220": { "label": "42/12", "naklon": 0 }, + "3533": { "label": "42/13", "naklon": null }, + "3543": { "label": "42/14", "naklon": null }, + "3554": { "label": "42/15", "naklon": null }, + "3549": { "label": "42/16", "naklon": null }, + "2857": { "label": "43/1", "naklon": 5 }, + "2752": { "label": "43/2", "naklon": 5 }, + "2753": { "label": "43/3", "naklon": 5 }, + "3024": { "label": "43/4", "naklon": 5 }, + "2754": { "label": "43/5", "naklon": 5 }, + "4423": { "label": "43/6", "naklon": 5 }, + "4368": { "label": "43/7", "naklon": 5 }, + "2978": { "label": "43/8", "naklon": 5 }, + "2868": { "label": "43/9", "naklon": 5 }, + "4377": { "label": "43/10", "naklon": 5 }, + "2757": { "label": "43/11", "naklon": 5 }, + "2970": { "label": "43/12", "naklon": 5 }, + "2758": { "label": "43/13", "naklon": 5 }, + "4378": { "label": "43/14", "naklon": 5 }, + "2759": { "label": "43/15", "naklon": 5 }, + "4342": { "label": "43/16", "naklon": 5 }, + "3026": { "label": "43/17", "naklon": null }, + "2986": { "label": "43/18", "naklon": null }, + "4343": { "label": "43/19", "naklon": null }, + "2760": { "label": "43/20", "naklon": null }, + "4379": { "label": "43/21", "naklon": null }, + "2971": { "label": "43/22", "naklon": null }, + "2761": { "label": "43/23", "naklon": null }, + "2762": { "label": "43/24", "naklon": null }, + "4339": { "label": "43/25", "naklon": null }, + "4380": { "label": "43/26", "naklon": null }, + "2975": { "label": "43/27", "naklon": null }, + "3003": { "label": "43/28", "naklon": null }, + "4338": { "label": "43/29", "naklon": null }, + "3002": { "label": "43/30", "naklon": null }, + "4345": { "label": "43/31", "naklon": null }, + "2979": { "label": "43/32", "naklon": null }, + "2989": { "label": "43/33", "naklon": null }, + "2996": { "label": "43/34", "naklon": null }, + "2972": { "label": "43/35", "naklon": null }, + "2988": { "label": "43/36", "naklon": null }, + "4344": { "label": "43/37", "naklon": null }, + "3022": { "label": "43/38", "naklon": null }, + "4341": { "label": "43/39", "naklon": null }, + "2983": { "label": "43/40", "naklon": null }, + "2995": { "label": "43/41", "naklon": null }, + "2763": { "label": "43/42", "naklon": null }, + "2764": { "label": "43/43", "naklon": null }, + "2765": { "label": "43/44", "naklon": null }, + "2766": { "label": "43/45", "naklon": null }, + "2767": { "label": "43/46", "naklon": null }, + "2768": { "label": "43/47", "naklon": null }, + "3018": { "label": "43/48", "naklon": null }, + "2982": { "label": "43/49", "naklon": null }, + "3019": { "label": "43/50", "naklon": 0 }, + "3013": { "label": "43/51", "naklon": null }, + "3007": { "label": "43/52", "naklon": null }, + "2980": { "label": "43/53", "naklon": null }, + "3011": { "label": "43/54", "naklon": null }, + "2672": { "label": "43/55", "naklon": null }, + "2673": { "label": "43/56", "naklon": null }, + "2674": { "label": "43/57", "naklon": null }, + "2675": { "label": "43/58", "naklon": null }, + "2676": { "label": "43/59", "naklon": null }, + "2677": { "label": "43/60", "naklon": null }, + "2678": { "label": "43/61", "naklon": null }, + "2679": { "label": "43/62", "naklon": null }, + "2680": { "label": "43/63", "naklon": null }, + "2840": { "label": "43/64", "naklon": null }, + "2682": { "label": "43/65", "naklon": null }, + "2683": { "label": "43/66", "naklon": null }, + "2684": { "label": "43/67", "naklon": 0 }, + "2685": { "label": "43/68", "naklon": null }, + "2686": { "label": "43/69", "naklon": null }, + "2687": { "label": "43/70", "naklon": null }, + "2688": { "label": "43/71", "naklon": null }, + "2689": { "label": "43/72", "naklon": null }, + "2690": { "label": "43/73", "naklon": null }, + "2691": { "label": "43/74", "naklon": null }, + "2692": { "label": "43/75", "naklon": null }, + "2693": { "label": "43/76", "naklon": 0 }, + "2694": { "label": "43/77", "naklon": null }, + "2695": { "label": "43/78", "naklon": null }, + "2696": { "label": "43/79", "naklon": 0 }, + "2697": { "label": "43/80", "naklon": null }, + "2698": { "label": "43/81", "naklon": 0 }, + "2699": { "label": "43/82", "naklon": null }, + "2700": { "label": "43/83", "naklon": 0 }, + "2744": { "label": "43/84", "naklon": null }, + "2745": { "label": "43/85", "naklon": 0 }, + "2746": { "label": "43/86", "naklon": null }, + "2747": { "label": "43/87", "naklon": 0 }, + "2748": { "label": "43/88", "naklon": null }, + "2749": { "label": "43/89", "naklon": 0 }, + "2841": { "label": "43/90", "naklon": null }, + "4237": { "label": "45/1", "naklon": 5 }, + "4226": { "label": "45/2", "naklon": 5 }, + "4242": { "label": "45/3", "naklon": 5 }, + "4179": { "label": "45/4", "naklon": 5 }, + "4247": { "label": "45/5", "naklon": 5 }, + "4245": { "label": "45/6", "naklon": 5 }, + "3872": { "label": "45/7", "naklon": 5 }, + "4175": { "label": "45/8", "naklon": 5 }, + "4236": { "label": "45/9", "naklon": 5 }, + "4170": { "label": "45/10", "naklon": 5 }, + "4238": { "label": "45/11", "naklon": 5 }, + "4246": { "label": "45/12", "naklon": 5 }, + "4166": { "label": "45/13", "naklon": 5 }, + "4227": { "label": "45/14", "naklon": 5 }, + "4171": { "label": "45/15", "naklon": 5 }, + "4180": { "label": "45/16", "naklon": 5 }, + "4244": { "label": "45/17", "naklon": 5 }, + "4199": { "label": "45/18", "naklon": 5 }, + "4239": { "label": "45/19", "naklon": 5 }, + "4207": { "label": "45/20", "naklon": 5 }, + "4223": { "label": "45/21", "naklon": 5 }, + "4230": { "label": "45/22", "naklon": 5 }, + "4233": { "label": "45/23", "naklon": 5 }, + "4222": { "label": "45/24", "naklon": 5 }, + "4217": { "label": "45/25", "naklon": 5 }, + "4243": { "label": "45/26", "naklon": 5 }, + "4200": { "label": "45/27", "naklon": 5 }, + "4228": { "label": "45/28", "naklon": 5 }, + "4211": { "label": "45/29", "naklon": 5 }, + "4234": { "label": "45/30", "naklon": 5 }, + "4235": { "label": "45/31", "naklon": 5 }, + "4203": { "label": "45/32", "naklon": 5 }, + "4240": { "label": "45/33", "naklon": 5 }, + "4224": { "label": "45/34", "naklon": 5 }, + "4232": { "label": "45/35", "naklon": 5 }, + "4231": { "label": "45/36", "naklon": 5 }, + "4161": { "label": "45/37", "naklon": 5 }, + "4225": { "label": "45/38", "naklon": 5 }, + "4241": { "label": "45/39", "naklon": 5 }, + "4229": { "label": "45/40", "naklon": 5 }, + "4221": { "label": "45/41", "naklon": 5 }, + "4212": { "label": "45/42", "naklon": 5 }, + "4216": { "label": "45/43", "naklon": 5 }, + "3864": { "label": "45/44", "naklon": null }, + "3806": { "label": "46/1", "naklon": 5 }, + "3813": { "label": "46/2", "naklon": 5 }, + "3815": { "label": "46/3", "naklon": 5 }, + "3807": { "label": "46/4", "naklon": 5 }, + "3895": { "label": "46/5", "naklon": 5 }, + "3809": { "label": "46/6", "naklon": 5 }, + "3820": { "label": "46/7", "naklon": 5 }, + "3805": { "label": "46/8", "naklon": 5 }, + "3894": { "label": "46/9", "naklon": 0 }, + "4055": { "label": "46/10", "naklon": 0 }, + "3812": { "label": "46/11", "naklon": 5 }, + "3822": { "label": "46/12", "naklon": 5 }, + "3821": { "label": "46/13", "naklon": 5 }, + "3808": { "label": "46/14", "naklon": 5 }, + "3799": { "label": "46/15", "naklon": 5 }, + "3816": { "label": "46/16", "naklon": 5 }, + "3751": { "label": "46/17", "naklon": 5 }, + "3814": { "label": "46/18", "naklon": 5 }, + "4044": { "label": "46/19", "naklon": 0 }, + "3931": { "label": "46/20", "naklon": 0 }, + "3902": { "label": "46/21", "naklon": 5 }, + "3916": { "label": "46/22", "naklon": 5 }, + "3892": { "label": "46/23", "naklon": 5 }, + "3914": { "label": "46/24", "naklon": 5 }, + "3898": { "label": "46/25", "naklon": 5 }, + "3897": { "label": "46/26", "naklon": 5 }, + "3885": { "label": "46/27", "naklon": 5 }, + "3906": { "label": "46/28", "naklon": 5 }, + "3930": { "label": "46/29", "naklon": 0 }, + "3936": { "label": "46/30", "naklon": 0 }, + "3860": { "label": "46/31", "naklon": 5 }, + "3841": { "label": "46/32", "naklon": 5 }, + "3873": { "label": "46/33", "naklon": 5 }, + "3854": { "label": "46/34", "naklon": 5 }, + "3939": { "label": "46/35", "naklon": 5 }, + "3858": { "label": "46/36", "naklon": 5 }, + "3940": { "label": "46/37", "naklon": 5 }, + "4035": { "label": "46/38", "naklon": 5 }, + "3373": { "label": "47/1", "naklon": 0 }, + "3374": { "label": "47/2", "naklon": 0 }, + "3384": { "label": "47/3", "naklon": 0 }, + "3385": { "label": "47/4", "naklon": 0 }, + "4051": { "label": "48/1", "naklon": 5 }, + "4041": { "label": "48/2", "naklon": 5 }, + "4056": { "label": "48/3", "naklon": 5 }, + "3875": { "label": "48/4", "naklon": 5 }, + "4061": { "label": "48/5", "naklon": 5 }, + "4047": { "label": "48/6", "naklon": 5 }, + "4060": { "label": "48/7", "naklon": 5 }, + "4059": { "label": "48/8", "naklon": 5 }, + "4058": { "label": "48/9", "naklon": 5 }, + "3635": { "label": "48/10", "naklon": 5 }, + "3640": { "label": "48/11", "naklon": 5 }, + "3747": { "label": "48/12", "naklon": 5 }, + "3629": { "label": "48/13", "naklon": 5 }, + "4048": { "label": "48/14", "naklon": 5 }, + "4063": { "label": "48/15", "naklon": 5 }, + "4062": { "label": "48/16", "naklon": 5 }, + "4043": { "label": "48/17", "naklon": 5 }, + "4052": { "label": "48/18", "naklon": 5 }, + "4042": { "label": "48/19", "naklon": 5 }, + "4053": { "label": "48/20", "naklon": 5 }, + "4167": { "label": "50/15A", "naklon": null }, + "4159": { "label": "50/15B", "naklon": null }, + "4183": { "label": "50/1", "naklon": 0 }, + "4157": { "label": "50/2", "naklon": 0 }, + "4160": { "label": "50/3", "naklon": 0 }, + "4173": { "label": "50/4", "naklon": 0 }, + "4177": { "label": "50/5", "naklon": 0 }, + "4174": { "label": "50/6", "naklon": 0 }, + "4178": { "label": "50/7", "naklon": 0 }, + "4195": { "label": "50/8", "naklon": 0 }, + "4169": { "label": "50/9", "naklon": 0 }, + "4162": { "label": "50/10", "naklon": 0 }, + "4158": { "label": "50/11", "naklon": 0 }, + "4182": { "label": "50/12", "naklon": 0 }, + "4194": { "label": "50/13", "naklon": 0 }, + "4184": { "label": "50/14", "naklon": 0 }, + "4197": { "label": "50/16", "naklon": null }, + "4164": { "label": "50/17", "naklon": null }, + "3306": { "label": "50/18", "naklon": null }, + "4168": { "label": "50/19", "naklon": null }, + "4193": { "label": "50/20", "naklon": null }, + "4187": { "label": "50/21", "naklon": null }, + "4163": { "label": "50/22", "naklon": null }, + "4165": { "label": "50/23", "naklon": null }, + "4185": { "label": "50/24", "naklon": null }, + "3904": { "label": "50/25", "naklon": null }, + "2619": { "label": "53/1", "naklon": 0 }, + "2623": { "label": "53/2", "naklon": 0 }, + "2617": { "label": "53/3", "naklon": 0 }, + "2622": { "label": "53/4", "naklon": 0 }, + "2618": { "label": "53/5", "naklon": 0 }, + "2626": { "label": "53/6", "naklon": 0 }, + "2869": { "label": "53/7", "naklon": 0 }, + "2613": { "label": "53/8", "naklon": 0 }, + "2608": { "label": "53/9", "naklon": 0 }, + "2611": { "label": "53/10", "naklon": 0 }, + "2598": { "label": "53/11", "naklon": 0 }, + "3528": { "label": "53/12", "naklon": 0 }, + "3545": { "label": "53/13", "naklon": 0 }, + "2620": { "label": "53/14", "naklon": 0 }, + "2612": { "label": "53/15", "naklon": 0 }, + "2615": { "label": "53/16", "naklon": 0 }, + "3722": { "label": "53/17", "naklon": 0 }, + "2624": { "label": "53/18", "naklon": 0 }, + "2609": { "label": "53/19", "naklon": 0 }, + "2625": { "label": "53/20", "naklon": 0 }, + "2602": { "label": "53/21", "naklon": 0 }, + "2610": { "label": "53/22", "naklon": 0 }, + "2599": { "label": "53/23", "naklon": 0 }, + "2605": { "label": "53/24", "naklon": 0 }, + "2593": { "label": "53/25", "naklon": 0 }, + "3074": { "label": "53/26", "naklon": 0 }, + "2740": { "label": "53/27", "naklon": 0 }, + "2614": { "label": "53/28", "naklon": 0 }, + "2601": { "label": "53/29", "naklon": 0 }, + "4196": { "label": "53/30", "naklon": 0 }, + "2607": { "label": "53/31", "naklon": 0 }, + "2582": { "label": "53/32", "naklon": 0 }, + "2594": { "label": "53/33", "naklon": 0 }, + "2589": { "label": "53/34", "naklon": 0 }, + "2596": { "label": "53/35", "naklon": 0 }, + "2603": { "label": "53/36", "naklon": 0 }, + "2597": { "label": "53/37", "naklon": 0 }, + "2590": { "label": "53/38", "naklon": 0 }, + "2581": { "label": "53/39", "naklon": 0 }, + "2583": { "label": "53/40", "naklon": 0 }, + "2580": { "label": "53/41", "naklon": 0 }, + "2579": { "label": "53/42", "naklon": 0 }, + "2797": { "label": "53/43", "naklon": 0 }, + "2577": { "label": "53/44", "naklon": 0 }, + "2586": { "label": "53/45", "naklon": 0 }, + "2588": { "label": "53/46", "naklon": 0 }, + "2591": { "label": "53/47", "naklon": 0 }, + "2592": { "label": "53/48", "naklon": 0 }, + "2573": { "label": "53/49", "naklon": 0 }, + "2595": { "label": "53/50", "naklon": 0 }, + "2587": { "label": "53/51", "naklon": 0 }, + "2578": { "label": "53/52", "naklon": 0 }, + "2574": { "label": "53/53", "naklon": 0 }, + "2571": { "label": "53/54", "naklon": 0 }, + "2570": { "label": "53/55", "naklon": 0 }, + "2576": { "label": "53/56", "naklon": 0 }, + "2881": { "label": "53/57", "naklon": 0 }, + "2575": { "label": "53/58", "naklon": 0 }, + "2572": { "label": "53/59", "naklon": 0 }, + "2569": { "label": "53/60", "naklon": 0 }, + "4324": { "label": "55/1", "naklon": 0 }, + "4319": { "label": "55/2", "naklon": 0 }, + "4327": { "label": "55/3", "naklon": 0 }, + "4333": { "label": "55/4", "naklon": 0 }, + "4332": { "label": "55/5", "naklon": 0 }, + "4320": { "label": "55/6", "naklon": 0 }, + "4317": { "label": "55/7", "naklon": 0 }, + "4318": { "label": "55/8", "naklon": 0 }, + "4328": { "label": "55/9", "naklon": 0 }, + "4323": { "label": "55/10", "naklon": 0 }, + "4325": { "label": "55/11", "naklon": 0 }, + "4326": { "label": "55/12", "naklon": 0 }, + "4316": { "label": "55/13", "naklon": 0 }, + "4322": { "label": "55/14", "naklon": 0 }, + "4331": { "label": "55/15", "naklon": 0 }, + "4321": { "label": "55/16", "naklon": 0 }, + "4315": { "label": "55/17", "naklon": 0 }, + "4329": { "label": "55/18", "naklon": 0 }, + "4334": { "label": "55/19", "naklon": 0 }, + "4330": { "label": "55/20", "naklon": 0 } +}; + + +let svetlaSorted = [{ "label": "1/3A", "node": 3993, "naklon": 0 }, +{ "label": "1/3B", "node": 3989, "naklon": 15 }, +{ "label": "1/1", "node": 3976, "naklon": 0 }, +{ "label": "1/2", "node": 4181, "naklon": 0 }, +{ "label": "1/4", "node": 4376, "naklon": 15 }, +{ "label": "1/5", "node": 3868, "naklon": 15 }, +{ "label": "1/6", "node": 3728, "naklon": 15 }, +{ "label": "1/7", "node": 3730, "naklon": 0 }, +{ "label": "1/8", "node": 4374, "naklon": 0 }, +{ "label": "1/9", "node": 3718, "naklon": 15 }, +{ "label": "1/10", "node": 4375, "naklon": 15 }, +{ "label": "1/11", "node": 4172, "naklon": 15 }, +{ "label": "1/12", "node": 4176, "naklon": 15 }, +{ "label": "2/1", "node": 3800, "naklon": 5 }, +{ "label": "2/2", "node": 3823, "naklon": 5 }, +{ "label": "2/3", "node": 3905, "naklon": 5 }, +{ "label": "2/4", "node": 3803, "naklon": 5 }, +{ "label": "2/5", "node": 3817, "naklon": 5 }, +{ "label": "2/6", "node": 3818, "naklon": 5 }, +{ "label": "2/7", "node": 3811, "naklon": 5 }, +{ "label": "2/8", "node": 3915, "naklon": 5 }, +{ "label": "2/9", "node": 3843, "naklon": 10 }, +{ "label": "2/10", "node": 3827, "naklon": 10 }, +{ "label": "2/11", "node": 4220, "naklon": 10 }, +{ "label": "2/12", "node": 3826, "naklon": 10 }, +{ "label": "2/13", "node": 3834, "naklon": 10 }, +{ "label": "2/14", "node": 3838, "naklon": 10 }, +{ "label": "2/15", "node": 2823, "naklon": 10 }, +{ "label": "2/16", "node": 3750, "naklon": 10 }, +{ "label": "2/17", "node": 3378, "naklon": 0 }, +{ "label": "2/18", "node": 3376, "naklon": 0 }, +{ "label": "2/19", "node": 3379, "naklon": 0 }, +{ "label": "2/20", "node": 3285, "naklon": 0 }, +{ "label": "2/21", "node": 3382, "naklon": 0 }, +{ "label": "2/22", "node": 3383, "naklon": 0 }, +{ "label": "2/24", "node": 3375, "naklon": 0 }, +{ "label": "2/25", "node": 3381, "naklon": 0 }, +{ "label": "2/26", "node": 3380, "naklon": 0 }, +{ "label": "2/27", "node": 3828, "naklon": 10 }, +{ "label": "2/28", "node": 3377, "naklon": 0 }, +{ "label": "7/1", "node": 3591, "naklon": 0 }, +{ "label": "7/2", "node": 3587, "naklon": 0 }, +{ "label": "7/3", "node": 3468, "naklon": 0 }, +{ "label": "7/4", "node": 3466, "naklon": 0 }, +{ "label": "7/5", "node": 3474, "naklon": 0 }, +{ "label": "7/6", "node": 3481, "naklon": 0 }, +{ "label": "7/7", "node": 3589, "naklon": 0 }, +{ "label": "7/8", "node": 3472, "naklon": 0 }, +{ "label": "7/9", "node": 3473, "naklon": 0 }, +{ "label": "7/10", "node": 3584, "naklon": 0 }, +{ "label": "7/11", "node": 3571, "naklon": 0 }, +{ "label": "7/12", "node": 3476, "naklon": 0 }, +{ "label": "7/13", "node": 3590, "naklon": 0 }, +{ "label": "7/14", "node": 3478, "naklon": 0 }, +{ "label": "7/15", "node": 3471, "naklon": 0 }, +{ "label": "7/16", "node": 3467, "naklon": 0 }, +{ "label": "7/17", "node": 3479, "naklon": 0 }, +{ "label": "7/18", "node": 3480, "naklon": 0 }, +{ "label": "7/19", "node": 3477, "naklon": 0 }, +{ "label": "12/1", "node": 3362, "naklon": 0 }, +{ "label": "12/2", "node": 3355, "naklon": 0 }, +{ "label": "12/3", "node": 3356, "naklon": 0 }, +{ "label": "12/4", "node": 3349, "naklon": 0 }, +{ "label": "12/5", "node": 3357, "naklon": 0 }, +{ "label": "12/6", "node": 3350, "naklon": 0 }, +{ "label": "12/7", "node": 3353, "naklon": 0 }, +{ "label": "12/8", "node": 3539, "naklon": 0 }, +{ "label": "12/9", "node": 3050, "naklon": 0 }, +{ "label": "12/10", "node": 3361, "naklon": 0 }, +{ "label": "12/11", "node": 3360, "naklon": 0 }, +{ "label": "12/12", "node": 3358, "naklon": 0 }, +{ "label": "12/13", "node": 3541, "naklon": 0 }, +{ "label": "12/14", "node": 3551, "naklon": 0 }, +{ "label": "12/15", "node": 3514, "naklon": 0 }, +{ "label": "12/16", "node": 3547, "naklon": 0 }, +{ "label": "12/17", "node": 3562, "naklon": 0 }, +{ "label": "12/18", "node": 3525, "naklon": 0 }, +{ "label": "12/19", "node": 3558, "naklon": 0 }, +{ "label": "12/20", "node": 3511, "naklon": 0 }, +{ "label": "12/21", "node": 3058, "naklon": 0 }, +{ "label": "12/22", "node": 3062, "naklon": 0 }, +{ "label": "12/23", "node": 3070, "naklon": 0 }, +{ "label": "12/24", "node": 3447, "naklon": 0 }, +{ "label": "12/25", "node": 3056, "naklon": 0 }, +{ "label": "12/26", "node": 3057, "naklon": 0 }, +{ "label": "12/27", "node": 3071, "naklon": 0 }, +{ "label": "12/28", "node": 3061, "naklon": 0 }, +{ "label": "12/29", "node": 3069, "naklon": 0 }, +{ "label": "12/30", "node": 3077, "naklon": 0 }, +{ "label": "12/31", "node": 3080, "naklon": 0 }, +{ "label": "12/32", "node": 3081, "naklon": 0 }, +{ "label": "12/33", "node": 3078, "naklon": 0 }, +{ "label": "12/34", "node": 4037, "naklon": 0 }, +{ "label": "12/35", "node": 3067, "naklon": 0 }, +{ "label": "12/36", "node": 3051, "naklon": 0 }, +{ "label": "12/37", "node": 2924, "naklon": 0 }, +{ "label": "12/38", "node": 3060, "naklon": 0 }, +{ "label": "12/39", "node": 3073, "naklon": 0 }, +{ "label": "12/40", "node": 3469, "naklon": 0 }, +{ "label": "12/41", "node": 2923, "naklon": 0 }, +{ "label": "12/42", "node": 2925, "naklon": 0 }, +{ "label": "12/43", "node": 3359, "naklon": 0 }, +{ "label": "12/44", "node": 3055, "naklon": 0 }, +{ "label": "12/45", "node": 2922, "naklon": 0 }, +{ "label": "12/46", "node": 3084, "naklon": 0 }, +{ "label": "12/47", "node": 3064, "naklon": 0 }, +{ "label": "12/48", "node": 3066, "naklon": 0 }, +{ "label": "12/49", "node": 3072, "naklon": 0 }, +{ "label": "13/13A", "node": 3415, "naklon": 0 }, +{ "label": "13/13B", "node": 3409, "naklon": 0 }, +{ "label": "13/13C", "node": 3399, "naklon": 0 }, +{ "label": "13/29A", "node": 3410, "naklon": 0 }, +{ "label": "13/29B", "node": 3407, "naklon": 0 }, +{ "label": "13/34A", "node": 3405, "naklon": 0 }, +{ "label": "13/34B", "node": 3404, "naklon": 0 }, +{ "label": "13/45A", "node": 3392, "naklon": 0 }, +{ "label": "13/45B", "node": 3386, "naklon": 0 }, +{ "label": "13/60A", "node": 3303, "naklon": 3 }, +{ "label": "13/60B", "node": 3302, "naklon": 3 }, +{ "label": "13/70A", "node": 3319, "naklon": 6 }, +{ "label": "13/70B", "node": 3317, "naklon": 6 }, +{ "label": "13/70C", "node": 3326, "naklon": 6 }, +{ "label": "13/73A", "node": 3351, "naklon": 6 }, +{ "label": "13/73B", "node": 3313, "naklon": 6 }, +{ "label": "13/83A", "node": 3316, "naklon": 0 }, +{ "label": "13/83B", "node": 3320, "naklon": 0 }, +{ "label": "13/95A", "node": 3336, "naklon": 0 }, +{ "label": "13/95B", "node": 3323, "naklon": 0 }, +{ "label": "13/98A", "node": 3339, "naklon": 0 }, +{ "label": "13/98B", "node": 3333, "naklon": 0 }, +{ "label": "13/1", "node": 3425, "naklon": 0 }, +{ "label": "13/2", "node": 3419, "naklon": 0 }, +{ "label": "13/3", "node": 3416, "naklon": 0 }, +{ "label": "13/4", "node": 3332, "naklon": 0 }, +{ "label": "13/5", "node": 3422, "naklon": 0 }, +{ "label": "13/6", "node": 3417, "naklon": 0 }, +{ "label": "13/7", "node": 3418, "naklon": 0 }, +{ "label": "13/8", "node": 3424, "naklon": 0 }, +{ "label": "13/9", "node": 3334, "naklon": 0 }, +{ "label": "13/10", "node": 4363, "naklon": 0 }, +{ "label": "13/11", "node": 3423, "naklon": 0 }, +{ "label": "13/12", "node": 3406, "naklon": 0 }, +{ "label": "13/14", "node": 3411, "naklon": 0 }, +{ "label": "13/15", "node": 3412, "naklon": 0 }, +{ "label": "13/16", "node": 3413, "naklon": 0 }, +{ "label": "13/17", "node": 3414, "naklon": 0 }, +{ "label": "13/18", "node": 3391, "naklon": 0 }, +{ "label": "13/19", "node": 3370, "naklon": 0 }, +{ "label": "13/20", "node": 3369, "naklon": 0 }, +{ "label": "13/21", "node": 3408, "naklon": 0 }, +{ "label": "13/22", "node": 3393, "naklon": 0 }, +{ "label": "13/23", "node": 3128, "naklon": 0 }, +{ "label": "13/24", "node": 3197, "naklon": 0 }, +{ "label": "13/25", "node": 4364, "naklon": 0 }, +{ "label": "13/26", "node": 3155, "naklon": 0 }, +{ "label": "13/27", "node": 3196, "naklon": 0 }, +{ "label": "13/28", "node": 3144, "naklon": 0 }, +{ "label": "13/30", "node": 3150, "naklon": 0 }, +{ "label": "13/31", "node": 3390, "naklon": 0 }, +{ "label": "13/32", "node": 3401, "naklon": 0 }, +{ "label": "13/33", "node": 3275, "naklon": 0 }, +{ "label": "13/35", "node": 3371, "naklon": 0 }, +{ "label": "13/36", "node": 3389, "naklon": 0 }, +{ "label": "13/37", "node": 3388, "naklon": 0 }, +{ "label": "13/38", "node": 3365, "naklon": 0 }, +{ "label": "13/39", "node": 3363, "naklon": 0 }, +{ "label": "13/40", "node": 3397, "naklon": 0 }, +{ "label": "13/40/1", "node": 3567, "naklon": 0 }, +{ "label": "13/41", "node": 3387, "naklon": 0 }, +{ "label": "13/42", "node": 3403, "naklon": 0 }, +{ "label": "13/43", "node": 3147, "naklon": 0 }, +{ "label": "13/44", "node": 3141, "naklon": 0 }, +{ "label": "13/46", "node": 3364, "naklon": 0 }, +{ "label": "13/47", "node": 3367, "naklon": 0 }, +{ "label": "13/48", "node": 3368, "naklon": 0 }, +{ "label": "13/49", "node": 3402, "naklon": 0 }, +{ "label": "13/50", "node": 3366, "naklon": 0 }, +{ "label": "13/51", "node": 3395, "naklon": 0 }, +{ "label": "13/52", "node": 3372, "naklon": 0 }, +{ "label": "13/53", "node": 3394, "naklon": 0 }, +{ "label": "13/54", "node": 3308, "naklon": 0 }, +{ "label": "13/54/1", "node": 3847, "naklon": 0 }, +{ "label": "13/55", "node": 3312, "naklon": 3 }, +{ "label": "13/56", "node": 3309, "naklon": 3 }, +{ "label": "13/57", "node": 3311, "naklon": 3 }, +{ "label": "13/58", "node": 3310, "naklon": 3 }, +{ "label": "13/59", "node": 4365, "naklon": 3 }, +{ "label": "13/60/1", "node": 4093, "naklon": 3 }, +{ "label": "13/61", "node": 3304, "naklon": 3 }, +{ "label": "13/62", "node": 3307, "naklon": 3 }, +{ "label": "13/63", "node": 3271, "naklon": 3 }, +{ "label": "13/64", "node": 3301, "naklon": 3 }, +{ "label": "13/65", "node": 4366, "naklon": 3 }, +{ "label": "13/66", "node": 3300, "naklon": 3 }, +{ "label": "13/67", "node": 3185, "naklon": 0 }, +{ "label": "13/68", "node": 3184, "naklon": 0 }, +{ "label": "13/69", "node": 3188, "naklon": 0 }, +{ "label": "13/71", "node": 3343, "naklon": 6 }, +{ "label": "13/71/1", "node": 3819, "naklon": 6 }, +{ "label": "13/71/2", "node": 3880, "naklon": 6 }, +{ "label": "13/72", "node": 3348, "naklon": 6 }, +{ "label": "13/74", "node": 3344, "naklon": 6 }, +{ "label": "13/75", "node": 3346, "naklon": 6 }, +{ "label": "13/75/1", "node": 3597, "naklon": 6 }, +{ "label": "13/76", "node": 3345, "naklon": 6 }, +{ "label": "13/77", "node": 3322, "naklon": 0 }, +{ "label": "13/78", "node": 3325, "naklon": 0 }, +{ "label": "13/78/1", "node": 4310, "naklon": 0 }, +{ "label": "13/79", "node": 3315, "naklon": 0 }, +{ "label": "13/80", "node": 3328, "naklon": 0 }, +{ "label": "13/81", "node": 3321, "naklon": 0 }, +{ "label": "13/82", "node": 3324, "naklon": 0 }, +{ "label": "13/84", "node": 3140, "naklon": 0 }, +{ "label": "13/85", "node": 3153, "naklon": 0 }, +{ "label": "13/86", "node": 3145, "naklon": 0 }, +{ "label": "13/87", "node": 3134, "naklon": 0 }, +{ "label": "13/88", "node": 3151, "naklon": 0 }, +{ "label": "13/89", "node": 3143, "naklon": 0 }, +{ "label": "13/90", "node": 3318, "naklon": 0 }, +{ "label": "13/91", "node": 3347, "naklon": 0 }, +{ "label": "13/94", "node": 3314, "naklon": 0 }, +{ "label": "13/96", "node": 3331, "naklon": 0 }, +{ "label": "13/97", "node": 3327, "naklon": 0 }, +{ "label": "13/99", "node": 3329, "naklon": 0 }, +{ "label": "13/100", "node": 3337, "naklon": 0 }, +{ "label": "13/101", "node": 3330, "naklon": 0 }, +{ "label": "13/102", "node": 3335, "naklon": 0 }, +{ "label": "13/103", "node": 3420, "naklon": 0 }, +{ "label": "13/104", "node": 3421, "naklon": 0 }, +{ "label": "13/105", "node": 4361, "naklon": 0 }, +{ "label": "13/106", "node": 4362, "naklon": 0 }, +{ "label": "13/107", "node": 3526, "naklon": 0 }, +{ "label": "13/108", "node": 4424, "naklon": null }, +{ "label": "13/109", "node": 3561, "naklon": null }, +{ "label": "13/110", "node": 3527, "naklon": null }, +{ "label": "13/111", "node": 3521, "naklon": null }, +{ "label": "13/112", "node": 3552, "naklon": null }, +{ "label": "13/113", "node": 3544, "naklon": null }, +{ "label": "13/114", "node": 3534, "naklon": null }, +{ "label": "13/115", "node": 3516, "naklon": null }, +{ "label": "13/116", "node": 3513, "naklon": null }, +{ "label": "13/117", "node": 3565, "naklon": null }, +{ "label": "13/118", "node": 3866, "naklon": null }, +{ "label": "14/1", "node": 3136, "naklon": 0 }, +{ "label": "14/2", "node": 3137, "naklon": 0 }, +{ "label": "14/3", "node": 3135, "naklon": 0 }, +{ "label": "14/4", "node": 3149, "naklon": 0 }, +{ "label": "14/5", "node": 3142, "naklon": 0 }, +{ "label": "14/6", "node": 3342, "naklon": 0 }, +{ "label": "14/7", "node": 3340, "naklon": 0 }, +{ "label": "14/8", "node": 3152, "naklon": 0 }, +{ "label": "14/9", "node": 3886, "naklon": 0 }, +{ "label": "14/10", "node": 3341, "naklon": null }, +{ "label": "14/11", "node": 3352, "naklon": null }, +{ "label": "15/1", "node": 3396, "naklon": 5 }, +{ "label": "15/2", "node": 2784, "naklon": 5 }, +{ "label": "15/3", "node": 2788, "naklon": 5 }, +{ "label": "15/4", "node": 2801, "naklon": 5 }, +{ "label": "15/5", "node": 2815, "naklon": 5 }, +{ "label": "15/6", "node": 2829, "naklon": 5 }, +{ "label": "15/7", "node": 2796, "naklon": 5 }, +{ "label": "15/8", "node": 2803, "naklon": 5 }, +{ "label": "15/8/1", "node": 4304, "naklon": 5 }, +{ "label": "15/8/2", "node": 4311, "naklon": 5 }, +{ "label": "15/9", "node": 2821, "naklon": 5 }, +{ "label": "15/10", "node": 3400, "naklon": 5 }, +{ "label": "15/11", "node": 2799, "naklon": 5 }, +{ "label": "15/12", "node": 2804, "naklon": 5 }, +{ "label": "15/12/1", "node": 4303, "naklon": 5 }, +{ "label": "15/12/2", "node": 4309, "naklon": 5 }, +{ "label": "15/13", "node": 2806, "naklon": 5 }, +{ "label": "15/14", "node": 2787, "naklon": 5 }, +{ "label": "15/15", "node": 2809, "naklon": 5 }, +{ "label": "15/16", "node": 2814, "naklon": 0 }, +{ "label": "15/17", "node": 3934, "naklon": 0 }, +{ "label": "15/18", "node": 3192, "naklon": 0 }, +{ "label": "15/19", "node": 2812, "naklon": 0 }, +{ "label": "15/20", "node": 4070, "naklon": 0 }, +{ "label": "15/21", "node": 2826, "naklon": 0 }, +{ "label": "15/22", "node": 2808, "naklon": 3 }, +{ "label": "15/23", "node": 2795, "naklon": 3 }, +{ "label": "15/24", "node": 2807, "naklon": 3 }, +{ "label": "15/25", "node": 2831, "naklon": 0 }, +{ "label": "15/26", "node": 2862, "naklon": null }, +{ "label": "15/27", "node": 2861, "naklon": 0 }, +{ "label": "15/28", "node": 2866, "naklon": 0 }, +{ "label": "15/28/1", "node": 3546, "naklon": 0 }, +{ "label": "15/29", "node": 4146, "naklon": 0 }, +{ "label": "15/29/1", "node": 3001, "naklon": 0 }, +{ "label": "15/30", "node": 2835, "naklon": 0 }, +{ "label": "15/31", "node": 2874, "naklon": 0 }, +{ "label": "15/32", "node": 2852, "naklon": 0 }, +{ "label": "15/33", "node": 2851, "naklon": 0 }, +{ "label": "15/33/1", "node": 3560, "naklon": 0 }, +{ "label": "15/34", "node": 2858, "naklon": 0 }, +{ "label": "15/34/1", "node": 4306, "naklon": 0 }, +{ "label": "15/35", "node": 2856, "naklon": 0 }, +{ "label": "15/36", "node": 2847, "naklon": 0 }, +{ "label": "15/36/1", "node": 3556, "naklon": 0 }, +{ "label": "15/37", "node": 3950, "naklon": 0 }, +{ "label": "15/38", "node": 2848, "naklon": 0 }, +{ "label": "15/39", "node": 2863, "naklon": 0 }, +{ "label": "15/39/1", "node": 4313, "naklon": 0 }, +{ "label": "15/40", "node": 2873, "naklon": 0 }, +{ "label": "15/40/1", "node": 2984, "naklon": 0 }, +{ "label": "15/41", "node": 2854, "naklon": 0 }, +{ "label": "15/42", "node": 2859, "naklon": 0 }, +{ "label": "15/43", "node": 2872, "naklon": 0 }, +{ "label": "15/44", "node": 2849, "naklon": 0 }, +{ "label": "15/45", "node": 2864, "naklon": 0 }, +{ "label": "15/46", "node": 3553, "naklon": null }, +{ "label": "15/47", "node": 3021, "naklon": null }, +{ "label": "15/47/1", "node": 3008, "naklon": null }, +{ "label": "15/48", "node": 3017, "naklon": null }, +{ "label": "15/49", "node": 3014, "naklon": null }, +{ "label": "15/50", "node": 2981, "naklon": null }, +{ "label": "15/51", "node": 3020, "naklon": null }, +{ "label": "15/52", "node": 3027, "naklon": null }, +{ "label": "15/53", "node": 3006, "naklon": null }, +{ "label": "15/54", "node": 3012, "naklon": null }, +{ "label": "15/55", "node": 2738, "naklon": 0 }, +{ "label": "15/56", "node": 2725, "naklon": 0 }, +{ "label": "15/57", "node": 3016, "naklon": null }, +{ "label": "15/58", "node": 3005, "naklon": null }, +{ "label": "15/58/1", "node": 3009, "naklon": null }, +{ "label": "15/59", "node": 3010, "naklon": 0 }, +{ "label": "15/59/1", "node": 3538, "naklon": 0 }, +{ "label": "15/59/2", "node": 4145, "naklon": 0 }, +{ "label": "15/60", "node": 2713, "naklon": 0 }, +{ "label": "15/61", "node": 2789, "naklon": 0 }, +{ "label": "15/62", "node": 2736, "naklon": 0 }, +{ "label": "15/63", "node": 2739, "naklon": 0 }, +{ "label": "15/64", "node": 4346, "naklon": 0 }, +{ "label": "15/65", "node": 2731, "naklon": 0 }, +{ "label": "15/66", "node": 2818, "naklon": 0 }, +{ "label": "15/66/1", "node": 3557, "naklon": 0 }, +{ "label": "15/67", "node": 2822, "naklon": 0 }, +{ "label": "15/68", "node": 2833, "naklon": 0 }, +{ "label": "15/69", "node": 2834, "naklon": 0 }, +{ "label": "15/70", "node": 3097, "naklon": 0 }, +{ "label": "15/71", "node": 2824, "naklon": 0 }, +{ "label": "15/72", "node": 2828, "naklon": 0 }, +{ "label": "15/73", "node": 2600, "naklon": 0 }, +{ "label": "15/73/1", "node": 4314, "naklon": 0 }, +{ "label": "15/74", "node": 2832, "naklon": 0 }, +{ "label": "15/75", "node": 4360, "naklon": 0 }, +{ "label": "15/76", "node": 2846, "naklon": 0 }, +{ "label": "15/77", "node": 2584, "naklon": 0 }, +{ "label": "15/78", "node": 2843, "naklon": 0 }, +{ "label": "15/78/1", "node": 4308, "naklon": 0 }, +{ "label": "15/79", "node": 4144, "naklon": null }, +{ "label": "15/80", "node": 2844, "naklon": 0 }, +{ "label": "15/81", "node": 2842, "naklon": 0 }, +{ "label": "15/82", "node": 2838, "naklon": 0 }, +{ "label": "15/83", "node": 2837, "naklon": null }, +{ "label": "15/83/1", "node": 3555, "naklon": null }, +{ "label": "15/84", "node": 2839, "naklon": 0 }, +{ "label": "15/85", "node": 2830, "naklon": 0 }, +{ "label": "15/86", "node": 4066, "naklon": 0 }, +{ "label": "15/87", "node": 2836, "naklon": 0 }, +{ "label": "15/88", "node": 2911, "naklon": 0 }, +{ "label": "15/89", "node": 2825, "naklon": 0 }, +{ "label": "15/90", "node": 2811, "naklon": 0 }, +{ "label": "15/94", "node": 3740, "naklon": 15 }, +{ "label": "15/95", "node": 2734, "naklon": 15 }, +{ "label": "15/96", "node": 3105, "naklon": 15 }, +{ "label": "15/97", "node": 2732, "naklon": 15 }, +{ "label": "15/98", "node": 2727, "naklon": 15 }, +{ "label": "15/99", "node": 2735, "naklon": 15 }, +{ "label": "15/100", "node": 3926, "naklon": 15 }, +{ "label": "15/101", "node": 2918, "naklon": 0 }, +{ "label": "15/102", "node": 2705, "naklon": 10 }, +{ "label": "15/103", "node": 2708, "naklon": 10 }, +{ "label": "15/104", "node": 2721, "naklon": 10 }, +{ "label": "15/105", "node": 2719, "naklon": 10 }, +{ "label": "15/106", "node": 2919, "naklon": 10 }, +{ "label": "15/107", "node": 3101, "naklon": 10 }, +{ "label": "15/108", "node": 2853, "naklon": 10 }, +{ "label": "15/109", "node": 2715, "naklon": 10 }, +{ "label": "15/110", "node": 2712, "naklon": 0 }, +{ "label": "15/111", "node": 2711, "naklon": 0 }, +{ "label": "15/112", "node": 2709, "naklon": 0 }, +{ "label": "15/113", "node": 2710, "naklon": 0 }, +{ "label": "15/114", "node": 2907, "naklon": 0 }, +{ "label": "15/115", "node": 2906, "naklon": 0 }, +{ "label": "15/116", "node": 2908, "naklon": 0 }, +{ "label": "15/117", "node": 2901, "naklon": 0 }, +{ "label": "15/118", "node": 2913, "naklon": 0 }, +{ "label": "15/119", "node": 3656, "naklon": 0 }, +{ "label": "15/120", "node": 2781, "naklon": 0 }, +{ "label": "15/121", "node": 2802, "naklon": 0 }, +{ "label": "15/122", "node": 2791, "naklon": 0 }, +{ "label": "15/123", "node": 2783, "naklon": 0 }, +{ "label": "15/124", "node": 2794, "naklon": 0 }, +{ "label": "15/125", "node": 3139, "naklon": 0 }, +{ "label": "15/126", "node": 3229, "naklon": 5 }, +{ "label": "15/127", "node": 3239, "naklon": 5 }, +{ "label": "15/128", "node": 3230, "naklon": 5 }, +{ "label": "15/129", "node": 4016, "naklon": null }, +{ "label": "16/16A", "node": 3608, "naklon": 0 }, +{ "label": "16/16B", "node": 4151, "naklon": 0 }, +{ "label": "16/1", "node": 3710, "naklon": 0 }, +{ "label": "16/2", "node": 3726, "naklon": 0 }, +{ "label": "16/3", "node": 3743, "naklon": 0 }, +{ "label": "16/4", "node": 3724, "naklon": 0 }, +{ "label": "16/5", "node": 3712, "naklon": 0 }, +{ "label": "16/6", "node": 3739, "naklon": 0 }, +{ "label": "16/7", "node": 3742, "naklon": 0 }, +{ "label": "16/8", "node": 3731, "naklon": 0 }, +{ "label": "16/9", "node": 3727, "naklon": 0 }, +{ "label": "16/10", "node": 3729, "naklon": 0 }, +{ "label": "16/11", "node": 3736, "naklon": 0 }, +{ "label": "16/12", "node": 3713, "naklon": 0 }, +{ "label": "16/13", "node": 3715, "naklon": 0 }, +{ "label": "16/14", "node": 3733, "naklon": 0 }, +{ "label": "16/15", "node": 3732, "naklon": 0 }, +{ "label": "16/17", "node": 3634, "naklon": 0 }, +{ "label": "16/18", "node": 3610, "naklon": 0 }, +{ "label": "16/19", "node": 3626, "naklon": 0 }, +{ "label": "16/20", "node": 3618, "naklon": 0 }, +{ "label": "16/21", "node": 3619, "naklon": 0 }, +{ "label": "16/22", "node": 3628, "naklon": 0 }, +{ "label": "16/23", "node": 3615, "naklon": 0 }, +{ "label": "16/24", "node": 3609, "naklon": 0 }, +{ "label": "16/25", "node": 3606, "naklon": 0 }, +{ "label": "16/26", "node": 3624, "naklon": 0 }, +{ "label": "16/27", "node": 3627, "naklon": 0 }, +{ "label": "16/28", "node": 3607, "naklon": 0 }, +{ "label": "16/29", "node": 4370, "naklon": 0 }, +{ "label": "16/30", "node": 3692, "naklon": 0 }, +{ "label": "16/31", "node": 3614, "naklon": 0 }, +{ "label": "16/32", "node": 3623, "naklon": 0 }, +{ "label": "16/33", "node": 4373, "naklon": 0 }, +{ "label": "16/34", "node": 3620, "naklon": 0 }, +{ "label": "16/35", "node": 3685, "naklon": 0 }, +{ "label": "16/36", "node": 3616, "naklon": 0 }, +{ "label": "16/37", "node": 3686, "naklon": 0 }, +{ "label": "16/38", "node": 3688, "naklon": 0 }, +{ "label": "16/39", "node": 3684, "naklon": 0 }, +{ "label": "16/40", "node": 3825, "naklon": 0 }, +{ "label": "16/41", "node": 3865, "naklon": 0 }, +{ "label": "16/42", "node": 3824, "naklon": 0 }, +{ "label": "16/43", "node": 3871, "naklon": 0 }, +{ "label": "16/44", "node": 3801, "naklon": 0 }, +{ "label": "16/45", "node": 3862, "naklon": 0 }, +{ "label": "16/46", "node": 3876, "naklon": 0 }, +{ "label": "16/47", "node": 3861, "naklon": 0 }, +{ "label": "16/48", "node": 4215, "naklon": 0 }, +{ "label": "16/49", "node": 3605, "naklon": 10 }, +{ "label": "16/50", "node": 3603, "naklon": 10 }, +{ "label": "16/51", "node": 3592, "naklon": 10 }, +{ "label": "16/52", "node": 3598, "naklon": 10 }, +{ "label": "16/53", "node": 3594, "naklon": 10 }, +{ "label": "16/54", "node": 3593, "naklon": 10 }, +{ "label": "16/55", "node": 3630, "naklon": 10 }, +{ "label": "16/56", "node": 3763, "naklon": 10 }, +{ "label": "16/57", "node": 3746, "naklon": 10 }, +{ "label": "16/58", "node": 3699, "naklon": 0 }, +{ "label": "16/59", "node": 3698, "naklon": 0 }, +{ "label": "16/60", "node": 3709, "naklon": null }, +{ "label": "16/61", "node": 3708, "naklon": 0 }, +{ "label": "16/62", "node": 3703, "naklon": null }, +{ "label": "16/63", "node": 3700, "naklon": 0 }, +{ "label": "16/64", "node": 3701, "naklon": null }, +{ "label": "16/65", "node": 3704, "naklon": 0 }, +{ "label": "16/66", "node": 3707, "naklon": null }, +{ "label": "16/67", "node": 3810, "naklon": 0 }, +{ "label": "16/68", "node": 4208, "naklon": null }, +{ "label": "16/69", "node": 3867, "naklon": 0 }, +{ "label": "16/70", "node": 4372, "naklon": null }, +{ "label": "16/71", "node": 3881, "naklon": 0 }, +{ "label": "16/72", "node": 4204, "naklon": null }, +{ "label": "16/73", "node": 3869, "naklon": 0 }, +{ "label": "16/74", "node": 4202, "naklon": null }, +{ "label": "16/75", "node": 3830, "naklon": 0 }, +{ "label": "16/76", "node": 3870, "naklon": null }, +{ "label": "16/77", "node": 3964, "naklon": 0 }, +{ "label": "16/78", "node": 3849, "naklon": 0 }, +{ "label": "16/79", "node": 3694, "naklon": null }, +{ "label": "16/80", "node": 3717, "naklon": 0 }, +{ "label": "16/81", "node": 3877, "naklon": null }, +{ "label": "16/82", "node": 3755, "naklon": 0 }, +{ "label": "16/83", "node": 3725, "naklon": null }, +{ "label": "16/84", "node": 3716, "naklon": 0 }, +{ "label": "16/85", "node": 3696, "naklon": null }, +{ "label": "16/86", "node": 3702, "naklon": 0 }, +{ "label": "16/87", "node": 3706, "naklon": null }, +{ "label": "16/88", "node": 3850, "naklon": 0 }, +{ "label": "16/89", "node": 3848, "naklon": null }, +{ "label": "16/90", "node": 3737, "naklon": null }, +{ "label": "16/91", "node": 3705, "naklon": 0 }, +{ "label": "16/92", "node": 3723, "naklon": null }, +{ "label": "16/93", "node": 3842, "naklon": 0 }, +{ "label": "16/94", "node": 3735, "naklon": null }, +{ "label": "16/95", "node": 3719, "naklon": 0 }, +{ "label": "16/96", "node": 3697, "naklon": 0 }, +{ "label": "16/97", "node": 3711, "naklon": 0 }, +{ "label": "16/98", "node": 4107, "naklon": null }, +{ "label": "16/99", "node": 4112, "naklon": 5 }, +{ "label": "16/100", "node": 4106, "naklon": 5 }, +{ "label": "16/101", "node": 4111, "naklon": 5 }, +{ "label": "16/102", "node": 4091, "naklon": null }, +{ "label": "16/103", "node": 4104, "naklon": 5 }, +{ "label": "16/104", "node": 4094, "naklon": null }, +{ "label": "16/105", "node": 4089, "naklon": 5 }, +{ "label": "16/106", "node": 4095, "naklon": null }, +{ "label": "16/107", "node": 4102, "naklon": 5 }, +{ "label": "16/108", "node": 4105, "naklon": null }, +{ "label": "16/109", "node": 3859, "naklon": null }, +{ "label": "16/110", "node": 4090, "naklon": 5 }, +{ "label": "16/111", "node": 4110, "naklon": null }, +{ "label": "16/112", "node": 4097, "naklon": 5 }, +{ "label": "16/113", "node": 4099, "naklon": null }, +{ "label": "16/114", "node": 4096, "naklon": null }, +{ "label": "16/115", "node": 4101, "naklon": 5 }, +{ "label": "16/116", "node": 4109, "naklon": null }, +{ "label": "16/117", "node": 4092, "naklon": 5 }, +{ "label": "16/118", "node": 3631, "naklon": null }, +{ "label": "16/119", "node": 3632, "naklon": 0 }, +{ "label": "16/120", "node": 3641, "naklon": null }, +{ "label": "16/121", "node": 3638, "naklon": 0 }, +{ "label": "16/122", "node": 3637, "naklon": null }, +{ "label": "16/123", "node": 4142, "naklon": null }, +{ "label": "16/124", "node": 4147, "naklon": 5 }, +{ "label": "16/125", "node": 4139, "naklon": 5 }, +{ "label": "20/30A", "node": 3172, "naklon": 2 }, +{ "label": "20/30B", "node": 3164, "naklon": 2 }, +{ "label": "20/1", "node": 3247, "naklon": 10 }, +{ "label": "20/2", "node": 3296, "naklon": 10 }, +{ "label": "20/3", "node": 3246, "naklon": 10 }, +{ "label": "20/4", "node": 3270, "naklon": 10 }, +{ "label": "20/5", "node": 3294, "naklon": 10 }, +{ "label": "20/6", "node": 3298, "naklon": 10 }, +{ "label": "20/7", "node": 3297, "naklon": 10 }, +{ "label": "20/8", "node": 3293, "naklon": 10 }, +{ "label": "20/9", "node": 3299, "naklon": 10 }, +{ "label": "20/10", "node": 3295, "naklon": 10 }, +{ "label": "20/11", "node": 3244, "naklon": 10 }, +{ "label": "20/12", "node": 3249, "naklon": 10 }, +{ "label": "20/13", "node": 3268, "naklon": 10 }, +{ "label": "20/14", "node": 3245, "naklon": 10 }, +{ "label": "20/15", "node": 3278, "naklon": 10 }, +{ "label": "20/16", "node": 3280, "naklon": 10 }, +{ "label": "20/17", "node": 3292, "naklon": 10 }, +{ "label": "20/18", "node": 3287, "naklon": 10 }, +{ "label": "20/19", "node": 3282, "naklon": 10 }, +{ "label": "20/20", "node": 3273, "naklon": 0 }, +{ "label": "20/21", "node": 3157, "naklon": 0 }, +{ "label": "20/22", "node": 3283, "naklon": 0 }, +{ "label": "20/23", "node": 3159, "naklon": 0 }, +{ "label": "20/24", "node": 3289, "naklon": 0 }, +{ "label": "20/25", "node": 3163, "naklon": 0 }, +{ "label": "20/26", "node": 3126, "naklon": 0 }, +{ "label": "20/27", "node": 3171, "naklon": 0 }, +{ "label": "20/28", "node": 3162, "naklon": 0 }, +{ "label": "20/29", "node": 3279, "naklon": 10 }, +{ "label": "20/31", "node": 3173, "naklon": 0 }, +{ "label": "20/32", "node": 3127, "naklon": 0 }, +{ "label": "20/33", "node": 3131, "naklon": 0 }, +{ "label": "20/34", "node": 3129, "naklon": 0 }, +{ "label": "20/35", "node": 3276, "naklon": 2 }, +{ "label": "20/36", "node": 3290, "naklon": 2 }, +{ "label": "20/37", "node": 3132, "naklon": 0 }, +{ "label": "20/38", "node": 3138, "naklon": 0 }, +{ "label": "20/39", "node": 3272, "naklon": 0 }, +{ "label": "20/40", "node": 3291, "naklon": 0 }, +{ "label": "20/41", "node": 3277, "naklon": 10 }, +{ "label": "20/42", "node": 3286, "naklon": 10 }, +{ "label": "20/43", "node": 3281, "naklon": 10 }, +{ "label": "20/44", "node": 3288, "naklon": 10 }, +{ "label": "20/45", "node": 3284, "naklon": 10 }, +{ "label": "20/46", "node": 3167, "naklon": 10 }, +{ "label": "20/47", "node": 3872, "naklon": 0 }, +{ "label": "20/48", "node": 3124, "naklon": 0 }, +{ "label": "20/49", "node": 3133, "naklon": 0 }, +{ "label": "20/50", "node": 3158, "naklon": 0 }, +{ "label": "20/51", "node": 3169, "naklon": 0 }, +{ "label": "20/52", "node": 3146, "naklon": 0 }, +{ "label": "20/53", "node": 3160, "naklon": 0 }, +{ "label": "20/54", "node": 3248, "naklon": 0 }, +{ "label": "20/55", "node": 3156, "naklon": 0 }, +{ "label": "20/56", "node": 3161, "naklon": 0 }, +{ "label": "20/57", "node": 3170, "naklon": 0 }, +{ "label": "20/58", "node": 3168, "naklon": 0 }, +{ "label": "20/59", "node": 3125, "naklon": 0 }, +{ "label": "20/60", "node": 3166, "naklon": 0 }, +{ "label": "20/61", "node": 3130, "naklon": 0 }, +{ "label": "20/62", "node": 3563, "naklon": 0 }, +{ "label": "20/63", "node": 3550, "naklon": null }, +{ "label": "20/67", "node": 3269, "naklon": 0 }, +{ "label": "21/1", "node": 2921, "naklon": 0 }, +{ "label": "21/2", "node": 2707, "naklon": 0 }, +{ "label": "21/3", "node": 2723, "naklon": 0 }, +{ "label": "21/4", "node": 2716, "naklon": 0 }, +{ "label": "21/5", "node": 2717, "naklon": 0 }, +{ "label": "21/6", "node": 2720, "naklon": 0 }, +{ "label": "21/7", "node": 2722, "naklon": 0 }, +{ "label": "21/8", "node": 2718, "naklon": 0 }, +{ "label": "21/9", "node": 2724, "naklon": 0 }, +{ "label": "21/10", "node": 2742, "naklon": 0 }, +{ "label": "21/11", "node": 2743, "naklon": 0 }, +{ "label": "21/12", "node": 2733, "naklon": 0 }, +{ "label": "21/14", "node": 2903, "naklon": 0 }, +{ "label": "21/15", "node": 2917, "naklon": 0 }, +{ "label": "21/16", "node": 2897, "naklon": 0 }, +{ "label": "21/17", "node": 2914, "naklon": 0 }, +{ "label": "21/18", "node": 2898, "naklon": 0 }, +{ "label": "21/19", "node": 2773, "naklon": 0 }, +{ "label": "21/20", "node": 2895, "naklon": 0 }, +{ "label": "21/21", "node": 2896, "naklon": 0 }, +{ "label": "21/22", "node": 2771, "naklon": 0 }, +{ "label": "21/23", "node": 2772, "naklon": 0 }, +{ "label": "21/24", "node": 2793, "naklon": 0 }, +{ "label": "21/25", "node": 2902, "naklon": 0 }, +{ "label": "21/26", "node": 2910, "naklon": 0 }, +{ "label": "21/27", "node": 2909, "naklon": 0 }, +{ "label": "21/28", "node": 2920, "naklon": 0 }, +{ "label": "21/29", "node": 2916, "naklon": 0 }, +{ "label": "21/30", "node": 2904, "naklon": 0 }, +{ "label": "21/31", "node": 2915, "naklon": 0 }, +{ "label": "21/32", "node": 2905, "naklon": 0 }, +{ "label": "21/33", "node": 2900, "naklon": 0 }, +{ "label": "21/34", "node": 2899, "naklon": 0 }, +{ "label": "21/36", "node": 2741, "naklon": 0 }, +{ "label": "21/37", "node": 2714, "naklon": 0 }, +{ "label": "21/38", "node": 2701, "naklon": 0 }, +{ "label": "21/39", "node": 2703, "naklon": 0 }, +{ "label": "21/40", "node": 2704, "naklon": 0 }, +{ "label": "21/41", "node": 2702, "naklon": 0 }, +{ "label": "21/42", "node": 2706, "naklon": 0 }, +{ "label": "21/43", "node": 2776, "naklon": 0 }, +{ "label": "21/44", "node": 2770, "naklon": 0 }, +{ "label": "21/45", "node": 2786, "naklon": 0 }, +{ "label": "21/46", "node": 2779, "naklon": 0 }, +{ "label": "21/47", "node": 2782, "naklon": 0 }, +{ "label": "21/48", "node": 2785, "naklon": 0 }, +{ "label": "21/49", "node": 2769, "naklon": 0 }, +{ "label": "21/50", "node": 3354, "naklon": 0 }, +{ "label": "21/51", "node": 2778, "naklon": 0 }, +{ "label": "21/52", "node": 2775, "naklon": 0 }, +{ "label": "21/53", "node": 2780, "naklon": 0 }, +{ "label": "21/54", "node": 2790, "naklon": 0 }, +{ "label": "21/55", "node": 2792, "naklon": 0 }, +{ "label": "21/56", "node": 2774, "naklon": 0 }, +{ "label": "22/1", "node": 2630, "naklon": 0 }, +{ "label": "22/2", "node": 2631, "naklon": 0 }, +{ "label": "22/3", "node": 2632, "naklon": 0 }, +{ "label": "22/4", "node": 2633, "naklon": 0 }, +{ "label": "22/5", "node": 2634, "naklon": 0 }, +{ "label": "22/6", "node": 2636, "naklon": 0 }, +{ "label": "22/7", "node": 4367, "naklon": 0 }, +{ "label": "22/8", "node": 2637, "naklon": 0 }, +{ "label": "22/9", "node": 2638, "naklon": 0 }, +{ "label": "22/10", "node": 2639, "naklon": 0 }, +{ "label": "22/11", "node": 2640, "naklon": 0 }, +{ "label": "22/12", "node": 2641, "naklon": 0 }, +{ "label": "22/13", "node": 2642, "naklon": 0 }, +{ "label": "22/14", "node": 2643, "naklon": 0 }, +{ "label": "22/15", "node": 2644, "naklon": 0 }, +{ "label": "22/16", "node": 2645, "naklon": 0 }, +{ "label": "22/17", "node": 2646, "naklon": 0 }, +{ "label": "22/18", "node": 2647, "naklon": 0 }, +{ "label": "22/19", "node": 2648, "naklon": 0 }, +{ "label": "22/20", "node": 2649, "naklon": 0 }, +{ "label": "22/21", "node": 2650, "naklon": 0 }, +{ "label": "22/22", "node": 2651, "naklon": 0 }, +{ "label": "22/23", "node": 4103, "naklon": 0 }, +{ "label": "22/24", "node": 2653, "naklon": 0 }, +{ "label": "22/25", "node": 2654, "naklon": 0 }, +{ "label": "22/26", "node": 2655, "naklon": 0 }, +{ "label": "22/27", "node": 2656, "naklon": 0 }, +{ "label": "22/28", "node": 2657, "naklon": 0 }, +{ "label": "22/29", "node": 2658, "naklon": 0 }, +{ "label": "22/30", "node": 2659, "naklon": 0 }, +{ "label": "22/31", "node": 2660, "naklon": 0 }, +{ "label": "22/32", "node": 2661, "naklon": 0 }, +{ "label": "22/32/1", "node": 3015, "naklon": 0 }, +{ "label": "22/33", "node": 2662, "naklon": 0 }, +{ "label": "22/34", "node": 2663, "naklon": 0 }, +{ "label": "22/35", "node": 2664, "naklon": 0 }, +{ "label": "22/36", "node": 2665, "naklon": 0 }, +{ "label": "22/37", "node": 2666, "naklon": 0 }, +{ "label": "22/38", "node": 2667, "naklon": 0 }, +{ "label": "22/39", "node": 2668, "naklon": 0 }, +{ "label": "22/40", "node": 2669, "naklon": null }, +{ "label": "22/41", "node": 2670, "naklon": null }, +{ "label": "22/42", "node": 2671, "naklon": null }, +{ "label": "23/9A", "node": 3087, "naklon": 10 }, +{ "label": "23/9B", "node": 3090, "naklon": 10 }, +{ "label": "23/1", "node": 3075, "naklon": 0 }, +{ "label": "23/2", "node": 3089, "naklon": 0 }, +{ "label": "23/3", "node": 3088, "naklon": 0 }, +{ "label": "23/4", "node": 3228, "naklon": 10 }, +{ "label": "23/5", "node": 2751, "naklon": 10 }, +{ "label": "23/6", "node": 3243, "naklon": 10 }, +{ "label": "23/7", "node": 4349, "naklon": 10 }, +{ "label": "23/8", "node": 3102, "naklon": 10 }, +{ "label": "23/10", "node": 3099, "naklon": 10 }, +{ "label": "23/11", "node": 3103, "naklon": 10 }, +{ "label": "23/12", "node": 3093, "naklon": 10 }, +{ "label": "23/13", "node": 3098, "naklon": 10 }, +{ "label": "23/14", "node": 3092, "naklon": 10 }, +{ "label": "23/15", "node": 3233, "naklon": 0 }, +{ "label": "23/16", "node": 3095, "naklon": 0 }, +{ "label": "23/17", "node": 4074, "naklon": 0 }, +{ "label": "23/18", "node": 2729, "naklon": 0 }, +{ "label": "23/19", "node": 3234, "naklon": 0 }, +{ "label": "23/20", "node": 3094, "naklon": 0 }, +{ "label": "23/21", "node": 2817, "naklon": 0 }, +{ "label": "23/22", "node": 3226, "naklon": 0 }, +{ "label": "23/23", "node": 3225, "naklon": 0 }, +{ "label": "23/24", "node": 3237, "naklon": 0 }, +{ "label": "23/25", "node": 4250, "naklon": 0 }, +{ "label": "23/26", "node": 3059, "naklon": 10 }, +{ "label": "23/27", "node": 3238, "naklon": 10 }, +{ "label": "23/28", "node": 3242, "naklon": 10 }, +{ "label": "23/29", "node": 3236, "naklon": 10 }, +{ "label": "23/30", "node": 3112, "naklon": 10 }, +{ "label": "23/31", "node": 3224, "naklon": 0 }, +{ "label": "23/32", "node": 4298, "naklon": 10 }, +{ "label": "23/33", "node": 4150, "naklon": 10 }, +{ "label": "23/34", "node": 3091, "naklon": 10 }, +{ "label": "25/1", "node": 3771, "naklon": 5 }, +{ "label": "25/2", "node": 3777, "naklon": 5 }, +{ "label": "25/3", "node": 3749, "naklon": 5 }, +{ "label": "25/4", "node": 3769, "naklon": 5 }, +{ "label": "25/5", "node": 3765, "naklon": 5 }, +{ "label": "25/6", "node": 3785, "naklon": 5 }, +{ "label": "25/7", "node": 3761, "naklon": 5 }, +{ "label": "25/8", "node": 3758, "naklon": 5 }, +{ "label": "25/9", "node": 3766, "naklon": 5 }, +{ "label": "25/10", "node": 3779, "naklon": 5 }, +{ "label": "25/11", "node": 3899, "naklon": 10 }, +{ "label": "25/12", "node": 3922, "naklon": 10 }, +{ "label": "25/13", "node": 3912, "naklon": 10 }, +{ "label": "25/14", "node": 3933, "naklon": 10 }, +{ "label": "25/15", "node": 3921, "naklon": 10 }, +{ "label": "25/16", "node": 4300, "naklon": 10 }, +{ "label": "25/17", "node": 3927, "naklon": 10 }, +{ "label": "25/18", "node": 3212, "naklon": 10 }, +{ "label": "25/19", "node": 3208, "naklon": 10 }, +{ "label": "25/20", "node": 3207, "naklon": 10 }, +{ "label": "25/21", "node": 4294, "naklon": 10 }, +{ "label": "25/22", "node": 3209, "naklon": 10 }, +{ "label": "25/23", "node": 3745, "naklon": 10 }, +{ "label": "25/24", "node": 3762, "naklon": 10 }, +{ "label": "25/25", "node": 3215, "naklon": 10 }, +{ "label": "25/26", "node": 3210, "naklon": 10 }, +{ "label": "25/27", "node": 3211, "naklon": 10 }, +{ "label": "25/28", "node": 3206, "naklon": 10 }, +{ "label": "25/29", "node": 3918, "naklon": 5 }, +{ "label": "25/30", "node": 3928, "naklon": 5 }, +{ "label": "25/31", "node": 3917, "naklon": 5 }, +{ "label": "25/32", "node": 4029, "naklon": 0 }, +{ "label": "25/33", "node": 4038, "naklon": 0 }, +{ "label": "25/34", "node": 4022, "naklon": 0 }, +{ "label": "25/35", "node": 3937, "naklon": 0 }, +{ "label": "25/36", "node": 3190, "naklon": 0 }, +{ "label": "25/37", "node": 3835, "naklon": 0 }, +{ "label": "25/38", "node": 3201, "naklon": 0 }, +{ "label": "25/39", "node": 3193, "naklon": 0 }, +{ "label": "25/40", "node": 3191, "naklon": 0 }, +{ "label": "25/41", "node": 3203, "naklon": 0 }, +{ "label": "25/42", "node": 4301, "naklon": 0 }, +{ "label": "25/43", "node": 3223, "naklon": 0 }, +{ "label": "25/44", "node": 3202, "naklon": 0 }, +{ "label": "25/45", "node": 3205, "naklon": 0 }, +{ "label": "25/46", "node": 3194, "naklon": 0 }, +{ "label": "25/47", "node": 3198, "naklon": 0 }, +{ "label": "25/48", "node": 3204, "naklon": 0 }, +{ "label": "25/49", "node": 3200, "naklon": 0 }, +{ "label": "25/50", "node": 3216, "naklon": 0 }, +{ "label": "25/51", "node": 3932, "naklon": 5 }, +{ "label": "25/52", "node": 3923, "naklon": 5 }, +{ "label": "25/53", "node": 3913, "naklon": 5 }, +{ "label": "25/54", "node": 3900, "naklon": 5 }, +{ "label": "25/55", "node": 4189, "naklon": 10 }, +{ "label": "25/56", "node": 4191, "naklon": 10 }, +{ "label": "25/57", "node": 3790, "naklon": 10 }, +{ "label": "25/58", "node": 4190, "naklon": 10 }, +{ "label": "25/59", "node": 4302, "naklon": 0 }, +{ "label": "25/60", "node": 4351, "naklon": 0 }, +{ "label": "25/61", "node": 4075, "naklon": 0 }, +{ "label": "25/62", "node": 4071, "naklon": 0 }, +{ "label": "25/63", "node": 3784, "naklon": 0 }, +{ "label": "25/64", "node": 4065, "naklon": 0 }, +{ "label": "25/65", "node": 4297, "naklon": 0 }, +{ "label": "25/66", "node": 4295, "naklon": 0 }, +{ "label": "25/67", "node": 4299, "naklon": 0 }, +{ "label": "25/68", "node": 3772, "naklon": 0 }, +{ "label": "25/69", "node": 3941, "naklon": 0 }, +{ "label": "25/70", "node": 3782, "naklon": 0 }, +{ "label": "25/71", "node": 4068, "naklon": 0 }, +{ "label": "25/72", "node": 4073, "naklon": 0 }, +{ "label": "25/73", "node": 3901, "naklon": 5 }, +{ "label": "25/74", "node": 4296, "naklon": 5 }, +{ "label": "25/75", "node": 3910, "naklon": 5 }, +{ "label": "25/76", "node": 4293, "naklon": 5 }, +{ "label": "25/77", "node": 3919, "naklon": 5 }, +{ "label": "25/78", "node": 3924, "naklon": 5 }, +{ "label": "25/79", "node": 3909, "naklon": 5 }, +{ "label": "25/80", "node": 3896, "naklon": 5 }, +{ "label": "25/81", "node": 3911, "naklon": 5 }, +{ "label": "25/82", "node": 2819, "naklon": 15 }, +{ "label": "25/83", "node": 3776, "naklon": 15 }, +{ "label": "25/84", "node": 3752, "naklon": 15 }, +{ "label": "25/85", "node": 4353, "naklon": 15 }, +{ "label": "25/86", "node": 3791, "naklon": 0 }, +{ "label": "25/87", "node": 3770, "naklon": 0 }, +{ "label": "25/88", "node": 3760, "naklon": 0 }, +{ "label": "25/89", "node": 3115, "naklon": 0 }, +{ "label": "25/90", "node": 3738, "naklon": 0 }, +{ "label": "25/91", "node": 3748, "naklon": 0 }, +{ "label": "25/92", "node": 3753, "naklon": 0 }, +{ "label": "25/93", "node": 3775, "naklon": 0 }, +{ "label": "25/94", "node": 3778, "naklon": 5 }, +{ "label": "25/95", "node": 4078, "naklon": 5 }, +{ "label": "25/96", "node": 4088, "naklon": 5 }, +{ "label": "25/97", "node": 3856, "naklon": 5 }, +{ "label": "25/98", "node": 4084, "naklon": 5 }, +{ "label": "25/99", "node": 4069, "naklon": 5 }, +{ "label": "25/100", "node": 4188, "naklon": 5 }, +{ "label": "25/101", "node": 4064, "naklon": 5 }, +{ "label": "25/102", "node": 3792, "naklon": 5 }, +{ "label": "25/103", "node": 3780, "naklon": 5 }, +{ "label": "25/104", "node": 4034, "naklon": 5 }, +{ "label": "25/105", "node": 4072, "naklon": 5 }, +{ "label": "25/106", "node": 3884, "naklon": 5 }, +{ "label": "25/107", "node": 3793, "naklon": 5 }, +{ "label": "25/108", "node": 3863, "naklon": 5 }, +{ "label": "25/109", "node": 3855, "naklon": 5 }, +{ "label": "33/1", "node": 3846, "naklon": 0 }, +{ "label": "33/2", "node": 3943, "naklon": 0 }, +{ "label": "33/3", "node": 3903, "naklon": 0 }, +{ "label": "33/4", "node": 3982, "naklon": 0 }, +{ "label": "33/5", "node": 3879, "naklon": 0 }, +{ "label": "33/6", "node": 3887, "naklon": 0 }, +{ "label": "33/7", "node": 3920, "naklon": 5 }, +{ "label": "33/8", "node": 3942, "naklon": 5 }, +{ "label": "33/9", "node": 3829, "naklon": null }, +{ "label": "34/79A", "node": 3452, "naklon": 6 }, +{ "label": "34/79B", "node": 3460, "naklon": 6 }, +{ "label": "34/90A", "node": 3443, "naklon": 6 }, +{ "label": "34/90B", "node": 3445, "naklon": 6 }, +{ "label": "34/90C", "node": 3457, "naklon": 6 }, +{ "label": "34/97A", "node": 3461, "naklon": 6 }, +{ "label": "34/97B", "node": 3463, "naklon": 6 }, +{ "label": "34/98A", "node": 3426, "naklon": 6 }, +{ "label": "34/98B", "node": 3444, "naklon": 6 }, +{ "label": "34/99A", "node": 3453, "naklon": 6 }, +{ "label": "34/99B", "node": 3455, "naklon": 6 }, +{ "label": "34/1", "node": 4009, "naklon": 0 }, +{ "label": "34/2", "node": 3602, "naklon": 0 }, +{ "label": "34/3", "node": 3441, "naklon": 0 }, +{ "label": "34/4", "node": 3464, "naklon": 0 }, +{ "label": "34/5", "node": 3883, "naklon": 0 }, +{ "label": "34/6", "node": 4098, "naklon": 0 }, +{ "label": "34/7", "node": 4003, "naklon": 0 }, +{ "label": "34/8", "node": 4004, "naklon": 0 }, +{ "label": "34/9", "node": 3888, "naklon": 0 }, +{ "label": "34/10", "node": 3997, "naklon": 0 }, +{ "label": "34/11", "node": 4006, "naklon": 0 }, +{ "label": "34/12", "node": 4000, "naklon": 0 }, +{ "label": "34/13", "node": 4011, "naklon": 0 }, +{ "label": "34/14", "node": 3999, "naklon": 0 }, +{ "label": "34/15", "node": 3981, "naklon": 0 }, +{ "label": "34/16", "node": 3988, "naklon": 0 }, +{ "label": "34/17", "node": 3986, "naklon": 0 }, +{ "label": "34/18", "node": 3998, "naklon": 0 }, +{ "label": "34/19", "node": 3983, "naklon": 0 }, +{ "label": "34/20", "node": 4005, "naklon": 0 }, +{ "label": "34/21", "node": 4001, "naklon": 0 }, +{ "label": "34/22", "node": 4008, "naklon": 0 }, +{ "label": "34/23", "node": 4002, "naklon": 0 }, +{ "label": "34/24", "node": 3996, "naklon": 0 }, +{ "label": "34/25", "node": 4007, "naklon": 0 }, +{ "label": "34/26", "node": 4113, "naklon": 15 }, +{ "label": "34/27", "node": 3595, "naklon": 5 }, +{ "label": "34/28", "node": 3599, "naklon": 5 }, +{ "label": "34/29", "node": 3601, "naklon": 5 }, +{ "label": "34/30", "node": 4205, "naklon": 0 }, +{ "label": "34/31", "node": 3987, "naklon": null }, +{ "label": "34/32", "node": 4214, "naklon": 0 }, +{ "label": "34/33", "node": 4226, "naklon": 0 }, +{ "label": "34/34", "node": 4209, "naklon": 0 }, +{ "label": "34/35", "node": 4201, "naklon": 0 }, +{ "label": "34/36", "node": 3440, "naklon": 0 }, +{ "label": "34/37", "node": 3465, "naklon": 0 }, +{ "label": "34/38", "node": 3446, "naklon": 0 }, +{ "label": "34/39", "node": 4039, "naklon": 5 }, +{ "label": "34/40", "node": 4057, "naklon": 5 }, +{ "label": "34/41", "node": 3985, "naklon": 0 }, +{ "label": "34/42", "node": 3882, "naklon": 0 }, +{ "label": "34/43", "node": 4040, "naklon": 5 }, +{ "label": "34/44", "node": 3231, "naklon": 0 }, +{ "label": "34/45", "node": 3227, "naklon": 0 }, +{ "label": "34/46", "node": 3431, "naklon": 0 }, +{ "label": "34/47", "node": 4013, "naklon": 0 }, +{ "label": "34/48", "node": 4045, "naklon": 0 }, +{ "label": "34/49", "node": 3949, "naklon": 0 }, +{ "label": "34/50", "node": 3953, "naklon": 0 }, +{ "label": "34/51", "node": 3952, "naklon": 0 }, +{ "label": "34/52", "node": 3995, "naklon": 0 }, +{ "label": "34/53", "node": 3992, "naklon": 0 }, +{ "label": "34/54", "node": 4198, "naklon": 0 }, +{ "label": "34/55", "node": 3935, "naklon": 0 }, +{ "label": "34/56", "node": 4050, "naklon": 0 }, +{ "label": "34/57", "node": 4049, "naklon": 0 }, +{ "label": "34/58", "node": 4054, "naklon": 0 }, +{ "label": "34/59", "node": 3663, "naklon": 6 }, +{ "label": "34/60", "node": 3661, "naklon": 6 }, +{ "label": "34/61", "node": 3664, "naklon": 6 }, +{ "label": "34/62", "node": 3660, "naklon": 6 }, +{ "label": "34/63", "node": 3662, "naklon": 6 }, +{ "label": "34/65", "node": 3665, "naklon": 6 }, +{ "label": "34/66", "node": 3667, "naklon": 6 }, +{ "label": "34/67", "node": 3675, "naklon": 6 }, +{ "label": "34/68", "node": 3666, "naklon": 6 }, +{ "label": "34/69", "node": 3652, "naklon": 6 }, +{ "label": "34/70", "node": 3458, "naklon": 6 }, +{ "label": "34/70/1", "node": 4425, "naklon": 6 }, +{ "label": "34/71", "node": 3459, "naklon": 6 }, +{ "label": "34/72", "node": 3435, "naklon": 6 }, +{ "label": "34/73", "node": 3448, "naklon": 6 }, +{ "label": "34/74", "node": 3451, "naklon": 6 }, +{ "label": "34/75", "node": 3442, "naklon": 6 }, +{ "label": "34/76", "node": 3449, "naklon": 6 }, +{ "label": "34/77", "node": 3450, "naklon": 6 }, +{ "label": "34/78", "node": 3433, "naklon": 6 }, +{ "label": "34/80", "node": 3432, "naklon": 12 }, +{ "label": "34/81", "node": 3470, "naklon": 12 }, +{ "label": "34/82", "node": 3438, "naklon": 12 }, +{ "label": "34/83", "node": 3439, "naklon": 12 }, +{ "label": "34/84", "node": 4028, "naklon": 5 }, +{ "label": "34/85", "node": 3596, "naklon": 5 }, +{ "label": "34/86", "node": 4021, "naklon": 5 }, +{ "label": "34/87", "node": 3437, "naklon": 12 }, +{ "label": "34/88", "node": 3428, "naklon": 12 }, +{ "label": "34/89", "node": 3430, "naklon": 12 }, +{ "label": "34/91", "node": 3454, "naklon": 6 }, +{ "label": "34/92", "node": 3492, "naklon": 6 }, +{ "label": "34/93", "node": 3462, "naklon": 6 }, +{ "label": "34/94", "node": 3427, "naklon": 6 }, +{ "label": "34/95", "node": 3434, "naklon": 6 }, +{ "label": "34/96", "node": 3456, "naklon": 6 }, +{ "label": "34/98/1", "node": 4307, "naklon": 6 }, +{ "label": "35/1", "node": 3968, "naklon": 0 }, +{ "label": "35/2", "node": 3969, "naklon": 0 }, +{ "label": "35/3", "node": 3947, "naklon": 0 }, +{ "label": "35/4", "node": 3979, "naklon": 0 }, +{ "label": "35/5", "node": 3959, "naklon": 0 }, +{ "label": "35/6", "node": 3948, "naklon": 0 }, +{ "label": "35/7", "node": 3961, "naklon": 0 }, +{ "label": "35/8", "node": 3956, "naklon": 0 }, +{ "label": "35/9", "node": 3604, "naklon": 0 }, +{ "label": "35/10", "node": 3944, "naklon": 0 }, +{ "label": "35/11", "node": 3960, "naklon": 0 }, +{ "label": "35/12", "node": 3958, "naklon": 0 }, +{ "label": "35/13", "node": 4036, "naklon": 5 }, +{ "label": "35/18", "node": 3893, "naklon": 5 }, +{ "label": "35/19", "node": 4108, "naklon": 5 }, +{ "label": "35/20", "node": 4017, "naklon": 5 }, +{ "label": "35/21", "node": 3963, "naklon": 0 }, +{ "label": "35/22", "node": 3658, "naklon": 0 }, +{ "label": "35/23", "node": 3975, "naklon": 0 }, +{ "label": "35/24", "node": 3980, "naklon": 0 }, +{ "label": "35/25", "node": 4012, "naklon": 0 }, +{ "label": "35/26", "node": 3655, "naklon": 0 }, +{ "label": "35/27", "node": 3962, "naklon": 0 }, +{ "label": "35/28", "node": 3945, "naklon": 0 }, +{ "label": "35/29", "node": 3569, "naklon": 0 }, +{ "label": "35/30", "node": 3429, "naklon": 0 }, +{ "label": "35/31", "node": 3657, "naklon": 0 }, +{ "label": "35/32", "node": 3646, "naklon": 0 }, +{ "label": "35/33", "node": 3622, "naklon": 0 }, +{ "label": "35/34", "node": 3612, "naklon": 0 }, +{ "label": "35/35", "node": 3955, "naklon": 0 }, +{ "label": "35/37", "node": 3878, "naklon": 0 }, +{ "label": "35/38", "node": 3965, "naklon": 0 }, +{ "label": "35/39", "node": 3970, "naklon": 0 }, +{ "label": "35/40", "node": 3611, "naklon": 0 }, +{ "label": "35/41", "node": 2635, "naklon": 0 }, +{ "label": "35/42", "node": 3978, "naklon": 0 }, +{ "label": "35/43", "node": 4213, "naklon": 0 }, +{ "label": "35/44", "node": 3984, "naklon": 0 }, +{ "label": "35/45", "node": 4218, "naklon": 0 }, +{ "label": "35/46", "node": 3973, "naklon": 0 }, +{ "label": "35/47", "node": 3974, "naklon": 0 }, +{ "label": "35/48", "node": 3759, "naklon": 0 }, +{ "label": "35/49", "node": 3844, "naklon": 0 }, +{ "label": "35/50", "node": 3804, "naklon": 0 }, +{ "label": "35/51", "node": 3831, "naklon": 0 }, +{ "label": "35/52", "node": 3643, "naklon": 0 }, +{ "label": "35/53", "node": 3966, "naklon": 0 }, +{ "label": "35/54", "node": 3971, "naklon": 0 }, +{ "label": "35/55", "node": 3650, "naklon": 6 }, +{ "label": "35/56", "node": 3651, "naklon": 6 }, +{ "label": "35/57", "node": 3669, "naklon": 6 }, +{ "label": "35/58", "node": 3648, "naklon": 6 }, +{ "label": "35/59", "node": 3645, "naklon": 6 }, +{ "label": "35/60", "node": 3659, "naklon": 6 }, +{ "label": "35/61", "node": 3647, "naklon": 6 }, +{ "label": "35/62", "node": 3644, "naklon": 6 }, +{ "label": "35/63", "node": 3671, "naklon": 6 }, +{ "label": "35/64", "node": 3682, "naklon": 6 }, +{ "label": "35/65", "node": 3672, "naklon": 6 }, +{ "label": "35/66", "node": 3683, "naklon": 6 }, +{ "label": "35/67", "node": 3673, "naklon": 6 }, +{ "label": "35/68", "node": 3674, "naklon": 6 }, +{ "label": "35/69", "node": 3679, "naklon": 6 }, +{ "label": "35/70", "node": 3649, "naklon": 6 }, +{ "label": "35/71", "node": 3687, "naklon": 6 }, +{ "label": "35/72", "node": 3677, "naklon": 6 }, +{ "label": "35/73", "node": 3690, "naklon": 6 }, +{ "label": "35/74", "node": 3691, "naklon": 6 }, +{ "label": "35/75", "node": 3676, "naklon": 6 }, +{ "label": "35/76", "node": 3680, "naklon": 6 }, +{ "label": "35/77", "node": 3668, "naklon": 6 }, +{ "label": "35/78", "node": 3681, "naklon": 6 }, +{ "label": "35/79", "node": 3670, "naklon": 6 }, +{ "label": "35/80", "node": 3689, "naklon": 6 }, +{ "label": "35/81", "node": 3678, "naklon": 6 }, +{ "label": "35/82", "node": 3693, "naklon": 6 }, +{ "label": "35/83", "node": 3654, "naklon": null }, +{ "label": "36/1", "node": 4086, "naklon": 0 }, +{ "label": "36/2", "node": 4085, "naklon": 0 }, +{ "label": "36/3", "node": 4083, "naklon": 0 }, +{ "label": "36/4", "node": 4087, "naklon": 0 }, +{ "label": "36/5", "node": 4077, "naklon": 0 }, +{ "label": "36/6", "node": 4082, "naklon": 0 }, +{ "label": "36/7", "node": 4186, "naklon": 0 }, +{ "label": "36/8", "node": 4206, "naklon": 0 }, +{ "label": "36/9", "node": 4080, "naklon": 0 }, +{ "label": "36/10", "node": 4081, "naklon": 0 }, +{ "label": "36/11", "node": 4210, "naklon": 0 }, +{ "label": "36/12", "node": 4079, "naklon": 0 }, +{ "label": "36/13", "node": 4076, "naklon": 0 }, +{ "label": "36/14", "node": 3852, "naklon": 0 }, +{ "label": "36/15", "node": 2813, "naklon": 0 }, +{ "label": "36/16", "node": 4219, "naklon": 0 }, +{ "label": "37/1A", "node": 3104, "naklon": 15 }, +{ "label": "37/1B", "node": 3121, "naklon": 15 }, +{ "label": "37/2", "node": 3113, "naklon": 10 }, +{ "label": "37/3", "node": 3118, "naklon": 10 }, +{ "label": "37/4", "node": 3111, "naklon": 10 }, +{ "label": "37/5", "node": 4020, "naklon": 10 }, +{ "label": "37/6", "node": 3119, "naklon": 10 }, +{ "label": "37/7", "node": 3110, "naklon": 10 }, +{ "label": "37/8", "node": 3108, "naklon": 10 }, +{ "label": "37/12", "node": 3107, "naklon": 0 }, +{ "label": "37/13", "node": 3199, "naklon": 0 }, +{ "label": "37/14", "node": 3120, "naklon": 0 }, +{ "label": "37/15", "node": 3122, "naklon": 0 }, +{ "label": "37/16", "node": 3908, "naklon": 0 }, +{ "label": "37/17", "node": 3114, "naklon": 0 }, +{ "label": "37/18", "node": 3105, "naklon": 0 }, +{ "label": "37/19", "node": 3116, "naklon": 0 }, +{ "label": "37/20", "node": 3106, "naklon": 0 }, +{ "label": "37/21", "node": 2887, "naklon": 5 }, +{ "label": "37/22", "node": 2888, "naklon": 5 }, +{ "label": "37/23", "node": 2877, "naklon": 5 }, +{ "label": "37/24", "node": 2891, "naklon": 5 }, +{ "label": "37/25", "node": 2886, "naklon": 5 }, +{ "label": "37/26", "node": 2892, "naklon": 5 }, +{ "label": "37/27", "node": 2882, "naklon": 5 }, +{ "label": "37/28", "node": 2883, "naklon": 5 }, +{ "label": "37/29", "node": 2876, "naklon": 5 }, +{ "label": "37/30", "node": 3109, "naklon": 5 }, +{ "label": "37/31", "node": 4152, "naklon": 5 }, +{ "label": "37/32", "node": 3117, "naklon": 5 }, +{ "label": "37/33", "node": 2870, "naklon": 5 }, +{ "label": "37/34", "node": 2867, "naklon": 0 }, +{ "label": "37/35", "node": 2865, "naklon": 0 }, +{ "label": "37/36", "node": 3096, "naklon": 0 }, +{ "label": "37/37", "node": 2871, "naklon": 0 }, +{ "label": "37/38", "node": 2884, "naklon": 0 }, +{ "label": "37/39", "node": 2855, "naklon": 0 }, +{ "label": "37/40", "node": 2878, "naklon": 0 }, +{ "label": "37/41", "node": 2889, "naklon": 0 }, +{ "label": "37/42", "node": 2879, "naklon": 0 }, +{ "label": "37/43", "node": 2850, "naklon": 0 }, +{ "label": "37/44", "node": 2894, "naklon": 0 }, +{ "label": "37/45", "node": 2880, "naklon": 0 }, +{ "label": "37/46", "node": 2893, "naklon": 0 }, +{ "label": "37/47", "node": 2890, "naklon": 0 }, +{ "label": "37/48", "node": 4355, "naklon": 0 }, +{ "label": "37/49", "node": 2885, "naklon": 0 }, +{ "label": "37/50", "node": 2875, "naklon": 0 }, +{ "label": "38/30A", "node": 3486, "naklon": 5 }, +{ "label": "38/30B", "node": 3714, "naklon": 0 }, +{ "label": "38/32A", "node": 3483, "naklon": 5 }, +{ "label": "38/32B", "node": 3496, "naklon": 0 }, +{ "label": "38/35A", "node": 3487, "naklon": 5 }, +{ "label": "38/35B", "node": 3498, "naklon": 5 }, +{ "label": "38/38A", "node": 3578, "naklon": 5 }, +{ "label": "38/38B", "node": 3508, "naklon": 5 }, +{ "label": "38/59A", "node": 3787, "naklon": 5 }, +{ "label": "38/59B", "node": 3491, "naklon": 5 }, +{ "label": "38/1", "node": 3568, "naklon": null }, +{ "label": "38/2", "node": 3502, "naklon": 0 }, +{ "label": "38/3", "node": 3836, "naklon": 0 }, +{ "label": "38/4", "node": 3588, "naklon": 0 }, +{ "label": "38/5", "node": 3493, "naklon": 0 }, +{ "label": "38/6", "node": 3580, "naklon": 0 }, +{ "label": "38/7", "node": 3572, "naklon": 0 }, +{ "label": "38/8", "node": 3506, "naklon": 0 }, +{ "label": "38/9", "node": 3503, "naklon": 0 }, +{ "label": "38/10", "node": 3579, "naklon": 0 }, +{ "label": "38/11", "node": 3586, "naklon": 0 }, +{ "label": "38/12", "node": 3495, "naklon": 5 }, +{ "label": "38/13", "node": 3492, "naklon": 5 }, +{ "label": "38/14", "node": 3532, "naklon": 5 }, +{ "label": "38/15", "node": 3574, "naklon": 5 }, +{ "label": "38/16", "node": 4140, "naklon": 5 }, +{ "label": "38/17", "node": 3795, "naklon": 5 }, +{ "label": "38/18", "node": 3788, "naklon": 5 }, +{ "label": "38/19", "node": 3796, "naklon": 5 }, +{ "label": "38/20", "node": 3797, "naklon": 5 }, +{ "label": "38/21", "node": 3798, "naklon": 5 }, +{ "label": "38/22", "node": 3786, "naklon": 5 }, +{ "label": "38/23", "node": 4067, "naklon": 5 }, +{ "label": "38/24", "node": 3773, "naklon": 5 }, +{ "label": "38/25", "node": 3774, "naklon": 5 }, +{ "label": "38/26", "node": 3789, "naklon": 5 }, +{ "label": "38/27", "node": 3520, "naklon": null }, +{ "label": "38/29", "node": 3577, "naklon": 5 }, +{ "label": "38/31", "node": 3530, "naklon": null }, +{ "label": "38/33", "node": 3488, "naklon": 5 }, +{ "label": "38/34", "node": 3505, "naklon": 5 }, +{ "label": "38/36", "node": 3497, "naklon": 5 }, +{ "label": "38/37", "node": 3490, "naklon": 5 }, +{ "label": "38/39", "node": 3585, "naklon": 5 }, +{ "label": "38/40", "node": 3582, "naklon": 5 }, +{ "label": "38/41", "node": 3507, "naklon": 5 }, +{ "label": "38/42", "node": 3484, "naklon": 5 }, +{ "label": "38/43", "node": 3501, "naklon": 5 }, +{ "label": "38/44", "node": 3581, "naklon": 5 }, +{ "label": "38/45", "node": 4192, "naklon": 5 }, +{ "label": "38/46", "node": 3576, "naklon": 5 }, +{ "label": "38/47", "node": 3489, "naklon": 5 }, +{ "label": "38/48", "node": 3573, "naklon": 5 }, +{ "label": "38/49", "node": 3504, "naklon": 5 }, +{ "label": "38/50", "node": 3794, "naklon": 5 }, +{ "label": "38/51", "node": 3485, "naklon": 5 }, +{ "label": "38/52", "node": 3482, "naklon": 5 }, +{ "label": "38/53", "node": 3575, "naklon": 5 }, +{ "label": "38/54", "node": 3499, "naklon": 5 }, +{ "label": "38/55", "node": 3494, "naklon": 5 }, +{ "label": "38/56", "node": 3583, "naklon": 5 }, +{ "label": "38/57", "node": 3570, "naklon": 5 }, +{ "label": "38/58", "node": 3500, "naklon": 0 }, +{ "label": "38/63", "node": 3510, "naklon": null }, +{ "label": "38/64", "node": 3512, "naklon": null }, +{ "label": "38/67", "node": 3535, "naklon": null }, +{ "label": "38/68", "node": 3531, "naklon": null }, +{ "label": "38/69", "node": 3537, "naklon": null }, +{ "label": "39/1", "node": 3522, "naklon": 10 }, +{ "label": "39/2", "node": 4018, "naklon": 10 }, +{ "label": "39/3", "node": 4019, "naklon": 10 }, +{ "label": "39/4", "node": 4154, "naklon": 5 }, +{ "label": "39/5", "node": 3907, "naklon": 5 }, +{ "label": "39/6", "node": 4148, "naklon": 0 }, +{ "label": "39/7", "node": 4153, "naklon": 0 }, +{ "label": "39/8", "node": 3938, "naklon": 0 }, +{ "label": "39/9", "node": 3802, "naklon": 0 }, +{ "label": "39/10", "node": 4015, "naklon": 0 }, +{ "label": "39/11", "node": 3929, "naklon": 0 }, +{ "label": "39/12", "node": 3946, "naklon": 0 }, +{ "label": "39/13", "node": 4014, "naklon": 0 }, +{ "label": "39/14", "node": 4155, "naklon": 0 }, +{ "label": "39/15", "node": 4149, "naklon": 0 }, +{ "label": "39/16", "node": 3642, "naklon": 0 }, +{ "label": "39/17", "node": 3636, "naklon": 5 }, +{ "label": "39/18", "node": 3991, "naklon": 0 }, +{ "label": "39/19", "node": 3994, "naklon": 0 }, +{ "label": "39/20", "node": 3990, "naklon": 0 }, +{ "label": "39/21", "node": 3967, "naklon": 0 }, +{ "label": "39/22", "node": 3977, "naklon": 0 }, +{ "label": "39/23", "node": 3757, "naklon": 15 }, +{ "label": "39/24", "node": 3633, "naklon": 15 }, +{ "label": "39/25", "node": 3744, "naklon": 15 }, +{ "label": "39/26", "node": 4023, "naklon": 5 }, +{ "label": "39/27", "node": 3720, "naklon": 5 }, +{ "label": "39/28", "node": 3734, "naklon": 5 }, +{ "label": "39/29", "node": 3741, "naklon": 5 }, +{ "label": "39/30", "node": 3721, "naklon": 5 }, +{ "label": "39/31", "node": 3845, "naklon": 0 }, +{ "label": "39/32", "node": 3840, "naklon": 0 }, +{ "label": "39/33", "node": 3837, "naklon": null }, +{ "label": "39/34", "node": 3839, "naklon": 0 }, +{ "label": "41/1", "node": 3542, "naklon": null }, +{ "label": "41/2", "node": 3566, "naklon": null }, +{ "label": "41/3", "node": 3548, "naklon": null }, +{ "label": "41/4", "node": 3515, "naklon": null }, +{ "label": "41/5", "node": 3559, "naklon": null }, +{ "label": "41/6", "node": 3509, "naklon": null }, +{ "label": "41/7", "node": 3524, "naklon": null }, +{ "label": "41/8", "node": 3518, "naklon": null }, +{ "label": "41/9", "node": 3182, "naklon": null }, +{ "label": "41/10", "node": 3187, "naklon": null }, +{ "label": "41/11", "node": 3195, "naklon": 0 }, +{ "label": "41/12", "node": 3857, "naklon": 0 }, +{ "label": "41/13", "node": 3183, "naklon": 0 }, +{ "label": "41/14", "node": 3177, "naklon": 0 }, +{ "label": "41/15", "node": 3189, "naklon": 0 }, +{ "label": "41/16", "node": 3186, "naklon": 0 }, +{ "label": "42/1", "node": 3178, "naklon": 0 }, +{ "label": "42/2", "node": 3219, "naklon": 0 }, +{ "label": "42/3", "node": 3475, "naklon": 0 }, +{ "label": "42/4", "node": 3175, "naklon": 0 }, +{ "label": "42/5", "node": 3222, "naklon": 0 }, +{ "label": "42/6", "node": 3221, "naklon": 0 }, +{ "label": "42/7", "node": 3181, "naklon": 0 }, +{ "label": "42/8", "node": 3180, "naklon": 0 }, +{ "label": "42/9", "node": 3218, "naklon": 0 }, +{ "label": "42/10", "node": 3176, "naklon": 0 }, +{ "label": "42/11", "node": 3174, "naklon": 0 }, +{ "label": "42/12", "node": 3220, "naklon": 0 }, +{ "label": "42/13", "node": 3533, "naklon": null }, +{ "label": "42/14", "node": 3543, "naklon": null }, +{ "label": "42/15", "node": 3554, "naklon": null }, +{ "label": "42/16", "node": 3549, "naklon": null }, +{ "label": "43/1", "node": 2857, "naklon": 5 }, +{ "label": "43/2", "node": 2752, "naklon": 5 }, +{ "label": "43/3", "node": 2753, "naklon": 5 }, +{ "label": "43/4", "node": 3024, "naklon": 5 }, +{ "label": "43/5", "node": 2754, "naklon": 5 }, +{ "label": "43/6", "node": 4423, "naklon": 5 }, +{ "label": "43/7", "node": 4368, "naklon": 5 }, +{ "label": "43/8", "node": 2978, "naklon": 5 }, +{ "label": "43/9", "node": 2868, "naklon": 5 }, +{ "label": "43/10", "node": 4377, "naklon": 5 }, +{ "label": "43/11", "node": 2757, "naklon": 5 }, +{ "label": "43/12", "node": 2970, "naklon": 5 }, +{ "label": "43/13", "node": 2758, "naklon": 5 }, +{ "label": "43/14", "node": 4378, "naklon": 5 }, +{ "label": "43/15", "node": 2759, "naklon": 5 }, +{ "label": "43/16", "node": 4342, "naklon": 5 }, +{ "label": "43/17", "node": 3026, "naklon": null }, +{ "label": "43/18", "node": 2986, "naklon": null }, +{ "label": "43/19", "node": 4343, "naklon": null }, +{ "label": "43/20", "node": 2760, "naklon": null }, +{ "label": "43/21", "node": 4379, "naklon": null }, +{ "label": "43/22", "node": 2971, "naklon": null }, +{ "label": "43/23", "node": 2761, "naklon": null }, +{ "label": "43/24", "node": 2762, "naklon": null }, +{ "label": "43/25", "node": 4339, "naklon": null }, +{ "label": "43/26", "node": 4380, "naklon": null }, +{ "label": "43/27", "node": 2975, "naklon": null }, +{ "label": "43/28", "node": 3003, "naklon": null }, +{ "label": "43/29", "node": 4338, "naklon": null }, +{ "label": "43/30", "node": 3002, "naklon": null }, +{ "label": "43/31", "node": 4345, "naklon": null }, +{ "label": "43/32", "node": 2979, "naklon": null }, +{ "label": "43/33", "node": 2989, "naklon": null }, +{ "label": "43/34", "node": 2996, "naklon": null }, +{ "label": "43/35", "node": 2972, "naklon": null }, +{ "label": "43/36", "node": 2988, "naklon": null }, +{ "label": "43/37", "node": 4344, "naklon": null }, +{ "label": "43/38", "node": 3022, "naklon": null }, +{ "label": "43/39", "node": 4341, "naklon": null }, +{ "label": "43/40", "node": 2983, "naklon": null }, +{ "label": "43/41", "node": 2995, "naklon": null }, +{ "label": "43/42", "node": 2763, "naklon": null }, +{ "label": "43/43", "node": 2764, "naklon": null }, +{ "label": "43/44", "node": 2765, "naklon": null }, +{ "label": "43/45", "node": 2766, "naklon": null }, +{ "label": "43/46", "node": 2767, "naklon": null }, +{ "label": "43/47", "node": 2768, "naklon": null }, +{ "label": "43/48", "node": 3018, "naklon": null }, +{ "label": "43/49", "node": 2982, "naklon": null }, +{ "label": "43/50", "node": 3019, "naklon": 0 }, +{ "label": "43/51", "node": 3013, "naklon": null }, +{ "label": "43/52", "node": 3007, "naklon": null }, +{ "label": "43/53", "node": 2980, "naklon": null }, +{ "label": "43/54", "node": 3011, "naklon": null }, +{ "label": "43/55", "node": 2672, "naklon": null }, +{ "label": "43/56", "node": 2673, "naklon": null }, +{ "label": "43/57", "node": 2674, "naklon": null }, +{ "label": "43/58", "node": 2675, "naklon": null }, +{ "label": "43/59", "node": 2676, "naklon": null }, +{ "label": "43/60", "node": 2677, "naklon": null }, +{ "label": "43/61", "node": 2678, "naklon": null }, +{ "label": "43/62", "node": 2679, "naklon": null }, +{ "label": "43/63", "node": 2680, "naklon": null }, +{ "label": "43/64", "node": 2840, "naklon": null }, +{ "label": "43/65", "node": 2682, "naklon": null }, +{ "label": "43/66", "node": 2683, "naklon": null }, +{ "label": "43/67", "node": 2684, "naklon": 0 }, +{ "label": "43/68", "node": 2685, "naklon": null }, +{ "label": "43/69", "node": 2686, "naklon": null }, +{ "label": "43/70", "node": 2687, "naklon": null }, +{ "label": "43/71", "node": 2688, "naklon": null }, +{ "label": "43/72", "node": 2689, "naklon": null }, +{ "label": "43/73", "node": 2690, "naklon": null }, +{ "label": "43/74", "node": 2691, "naklon": null }, +{ "label": "43/75", "node": 2692, "naklon": null }, +{ "label": "43/76", "node": 2693, "naklon": 0 }, +{ "label": "43/77", "node": 2694, "naklon": null }, +{ "label": "43/78", "node": 2695, "naklon": null }, +{ "label": "43/79", "node": 2696, "naklon": 0 }, +{ "label": "43/80", "node": 2697, "naklon": null }, +{ "label": "43/81", "node": 2698, "naklon": 0 }, +{ "label": "43/82", "node": 2699, "naklon": null }, +{ "label": "43/83", "node": 2700, "naklon": 0 }, +{ "label": "43/84", "node": 2744, "naklon": null }, +{ "label": "43/85", "node": 2745, "naklon": 0 }, +{ "label": "43/86", "node": 2746, "naklon": null }, +{ "label": "43/87", "node": 2747, "naklon": 0 }, +{ "label": "43/88", "node": 2748, "naklon": null }, +{ "label": "43/89", "node": 2749, "naklon": 0 }, +{ "label": "43/90", "node": 2841, "naklon": null }, +{ "label": "45/1", "node": 4237, "naklon": 5 }, +{ "label": "45/2", "node": 4226, "naklon": 5 }, +{ "label": "45/3", "node": 4242, "naklon": 5 }, +{ "label": "45/4", "node": 4179, "naklon": 5 }, +{ "label": "45/5", "node": 4247, "naklon": 5 }, +{ "label": "45/6", "node": 4245, "naklon": 5 }, +{ "label": "45/7", "node": 3872, "naklon": 5 }, +{ "label": "45/8", "node": 4175, "naklon": 5 }, +{ "label": "45/9", "node": 4236, "naklon": 5 }, +{ "label": "45/10", "node": 4170, "naklon": 5 }, +{ "label": "45/11", "node": 4238, "naklon": 5 }, +{ "label": "45/12", "node": 4246, "naklon": 5 }, +{ "label": "45/13", "node": 4166, "naklon": 5 }, +{ "label": "45/14", "node": 4227, "naklon": 5 }, +{ "label": "45/15", "node": 4171, "naklon": 5 }, +{ "label": "45/16", "node": 4180, "naklon": 5 }, +{ "label": "45/17", "node": 4244, "naklon": 5 }, +{ "label": "45/18", "node": 4199, "naklon": 5 }, +{ "label": "45/19", "node": 4239, "naklon": 5 }, +{ "label": "45/20", "node": 4207, "naklon": 5 }, +{ "label": "45/21", "node": 4223, "naklon": 5 }, +{ "label": "45/22", "node": 4230, "naklon": 5 }, +{ "label": "45/23", "node": 4233, "naklon": 5 }, +{ "label": "45/24", "node": 4222, "naklon": 5 }, +{ "label": "45/25", "node": 4217, "naklon": 5 }, +{ "label": "45/26", "node": 4243, "naklon": 5 }, +{ "label": "45/27", "node": 4200, "naklon": 5 }, +{ "label": "45/28", "node": 4228, "naklon": 5 }, +{ "label": "45/29", "node": 4211, "naklon": 5 }, +{ "label": "45/30", "node": 4234, "naklon": 5 }, +{ "label": "45/31", "node": 4235, "naklon": 5 }, +{ "label": "45/32", "node": 4203, "naklon": 5 }, +{ "label": "45/33", "node": 4240, "naklon": 5 }, +{ "label": "45/34", "node": 4224, "naklon": 5 }, +{ "label": "45/35", "node": 4232, "naklon": 5 }, +{ "label": "45/36", "node": 4231, "naklon": 5 }, +{ "label": "45/37", "node": 4161, "naklon": 5 }, +{ "label": "45/38", "node": 4225, "naklon": 5 }, +{ "label": "45/39", "node": 4241, "naklon": 5 }, +{ "label": "45/40", "node": 4229, "naklon": 5 }, +{ "label": "45/41", "node": 4221, "naklon": 5 }, +{ "label": "45/42", "node": 4212, "naklon": 5 }, +{ "label": "45/43", "node": 4216, "naklon": 5 }, +{ "label": "45/44", "node": 3864, "naklon": null }, +{ "label": "46/1", "node": 3806, "naklon": 5 }, +{ "label": "46/2", "node": 3813, "naklon": 5 }, +{ "label": "46/3", "node": 3815, "naklon": 5 }, +{ "label": "46/4", "node": 3807, "naklon": 5 }, +{ "label": "46/5", "node": 3895, "naklon": 5 }, +{ "label": "46/6", "node": 3809, "naklon": 5 }, +{ "label": "46/7", "node": 3820, "naklon": 5 }, +{ "label": "46/8", "node": 3805, "naklon": 5 }, +{ "label": "46/9", "node": 3894, "naklon": 0 }, +{ "label": "46/10", "node": 4055, "naklon": 0 }, +{ "label": "46/11", "node": 3812, "naklon": 5 }, +{ "label": "46/12", "node": 3822, "naklon": 5 }, +{ "label": "46/13", "node": 3821, "naklon": 5 }, +{ "label": "46/14", "node": 3808, "naklon": 5 }, +{ "label": "46/15", "node": 3799, "naklon": 5 }, +{ "label": "46/16", "node": 3816, "naklon": 5 }, +{ "label": "46/17", "node": 3751, "naklon": 5 }, +{ "label": "46/18", "node": 3814, "naklon": 5 }, +{ "label": "46/19", "node": 4044, "naklon": 0 }, +{ "label": "46/20", "node": 3931, "naklon": 0 }, +{ "label": "46/21", "node": 3902, "naklon": 5 }, +{ "label": "46/22", "node": 3916, "naklon": 5 }, +{ "label": "46/23", "node": 3892, "naklon": 5 }, +{ "label": "46/24", "node": 3914, "naklon": 5 }, +{ "label": "46/25", "node": 3898, "naklon": 5 }, +{ "label": "46/26", "node": 3897, "naklon": 5 }, +{ "label": "46/27", "node": 3885, "naklon": 5 }, +{ "label": "46/28", "node": 3906, "naklon": 5 }, +{ "label": "46/29", "node": 3930, "naklon": 0 }, +{ "label": "46/30", "node": 3936, "naklon": 0 }, +{ "label": "46/31", "node": 3860, "naklon": 5 }, +{ "label": "46/32", "node": 3841, "naklon": 5 }, +{ "label": "46/33", "node": 3873, "naklon": 5 }, +{ "label": "46/34", "node": 3854, "naklon": 5 }, +{ "label": "46/35", "node": 3939, "naklon": 5 }, +{ "label": "46/36", "node": 3858, "naklon": 5 }, +{ "label": "46/37", "node": 3940, "naklon": 5 }, +{ "label": "46/38", "node": 4035, "naklon": 5 }, +{ "label": "47/1", "node": 3373, "naklon": 0 }, +{ "label": "47/2", "node": 3374, "naklon": 0 }, +{ "label": "47/3", "node": 3384, "naklon": 0 }, +{ "label": "47/4", "node": 3385, "naklon": 0 }, +{ "label": "48/1", "node": 4051, "naklon": 5 }, +{ "label": "48/2", "node": 4041, "naklon": 5 }, +{ "label": "48/3", "node": 4056, "naklon": 5 }, +{ "label": "48/4", "node": 3875, "naklon": 5 }, +{ "label": "48/5", "node": 4061, "naklon": 5 }, +{ "label": "48/6", "node": 4047, "naklon": 5 }, +{ "label": "48/7", "node": 4060, "naklon": 5 }, +{ "label": "48/8", "node": 4059, "naklon": 5 }, +{ "label": "48/9", "node": 4058, "naklon": 5 }, +{ "label": "48/10", "node": 3635, "naklon": 5 }, +{ "label": "48/11", "node": 3640, "naklon": 5 }, +{ "label": "48/12", "node": 3747, "naklon": 5 }, +{ "label": "48/13", "node": 3629, "naklon": 5 }, +{ "label": "48/14", "node": 4048, "naklon": 5 }, +{ "label": "48/15", "node": 4063, "naklon": 5 }, +{ "label": "48/16", "node": 4062, "naklon": 5 }, +{ "label": "48/17", "node": 4043, "naklon": 5 }, +{ "label": "48/18", "node": 4052, "naklon": 5 }, +{ "label": "48/19", "node": 4042, "naklon": 5 }, +{ "label": "48/20", "node": 4053, "naklon": 5 }, +{ "label": "50/15A", "node": 4167, "naklon": null }, +{ "label": "50/15B", "node": 4159, "naklon": null }, +{ "label": "50/1", "node": 4183, "naklon": 0 }, +{ "label": "50/2", "node": 4157, "naklon": 0 }, +{ "label": "50/3", "node": 4160, "naklon": 0 }, +{ "label": "50/4", "node": 4173, "naklon": 0 }, +{ "label": "50/5", "node": 4177, "naklon": 0 }, +{ "label": "50/6", "node": 4174, "naklon": 0 }, +{ "label": "50/7", "node": 4178, "naklon": 0 }, +{ "label": "50/8", "node": 4195, "naklon": 0 }, +{ "label": "50/9", "node": 4169, "naklon": 0 }, +{ "label": "50/10", "node": 4162, "naklon": 0 }, +{ "label": "50/11", "node": 4158, "naklon": 0 }, +{ "label": "50/12", "node": 4182, "naklon": 0 }, +{ "label": "50/13", "node": 4194, "naklon": 0 }, +{ "label": "50/14", "node": 4184, "naklon": 0 }, +{ "label": "50/16", "node": 4197, "naklon": null }, +{ "label": "50/17", "node": 4164, "naklon": null }, +{ "label": "50/18", "node": 3306, "naklon": null }, +{ "label": "50/19", "node": 4168, "naklon": null }, +{ "label": "50/20", "node": 4193, "naklon": null }, +{ "label": "50/21", "node": 4187, "naklon": null }, +{ "label": "50/22", "node": 4163, "naklon": null }, +{ "label": "50/23", "node": 4165, "naklon": null }, +{ "label": "50/24", "node": 4185, "naklon": null }, +{ "label": "50/25", "node": 3904, "naklon": null }, +{ "label": "53/1", "node": 2619, "naklon": 0 }, +{ "label": "53/2", "node": 2623, "naklon": 0 }, +{ "label": "53/3", "node": 2617, "naklon": 0 }, +{ "label": "53/4", "node": 2622, "naklon": 0 }, +{ "label": "53/5", "node": 2618, "naklon": 0 }, +{ "label": "53/6", "node": 2626, "naklon": 0 }, +{ "label": "53/7", "node": 2869, "naklon": 0 }, +{ "label": "53/8", "node": 2613, "naklon": 0 }, +{ "label": "53/9", "node": 2608, "naklon": 0 }, +{ "label": "53/10", "node": 2611, "naklon": 0 }, +{ "label": "53/11", "node": 2598, "naklon": 0 }, +{ "label": "53/12", "node": 3528, "naklon": 0 }, +{ "label": "53/13", "node": 3545, "naklon": 0 }, +{ "label": "53/14", "node": 2620, "naklon": 0 }, +{ "label": "53/15", "node": 2612, "naklon": 0 }, +{ "label": "53/16", "node": 2615, "naklon": 0 }, +{ "label": "53/17", "node": 3722, "naklon": 0 }, +{ "label": "53/18", "node": 2624, "naklon": 0 }, +{ "label": "53/19", "node": 2609, "naklon": 0 }, +{ "label": "53/20", "node": 2625, "naklon": 0 }, +{ "label": "53/21", "node": 2602, "naklon": 0 }, +{ "label": "53/22", "node": 2610, "naklon": 0 }, +{ "label": "53/23", "node": 2599, "naklon": 0 }, +{ "label": "53/24", "node": 2605, "naklon": 0 }, +{ "label": "53/25", "node": 2593, "naklon": 0 }, +{ "label": "53/26", "node": 3074, "naklon": 0 }, +{ "label": "53/27", "node": 2740, "naklon": 0 }, +{ "label": "53/28", "node": 2614, "naklon": 0 }, +{ "label": "53/29", "node": 2601, "naklon": 0 }, +{ "label": "53/30", "node": 4196, "naklon": 0 }, +{ "label": "53/31", "node": 2607, "naklon": 0 }, +{ "label": "53/32", "node": 2582, "naklon": 0 }, +{ "label": "53/33", "node": 2594, "naklon": 0 }, +{ "label": "53/34", "node": 2589, "naklon": 0 }, +{ "label": "53/35", "node": 2596, "naklon": 0 }, +{ "label": "53/36", "node": 2603, "naklon": 0 }, +{ "label": "53/37", "node": 2597, "naklon": 0 }, +{ "label": "53/38", "node": 2590, "naklon": 0 }, +{ "label": "53/39", "node": 2581, "naklon": 0 }, +{ "label": "53/40", "node": 2583, "naklon": 0 }, +{ "label": "53/41", "node": 2580, "naklon": 0 }, +{ "label": "53/42", "node": 2579, "naklon": 0 }, +{ "label": "53/43", "node": 2797, "naklon": 0 }, +{ "label": "53/44", "node": 2577, "naklon": 0 }, +{ "label": "53/45", "node": 2586, "naklon": 0 }, +{ "label": "53/46", "node": 2588, "naklon": 0 }, +{ "label": "53/47", "node": 2591, "naklon": 0 }, +{ "label": "53/48", "node": 2592, "naklon": 0 }, +{ "label": "53/49", "node": 2573, "naklon": 0 }, +{ "label": "53/50", "node": 2595, "naklon": 0 }, +{ "label": "53/51", "node": 2587, "naklon": 0 }, +{ "label": "53/52", "node": 2578, "naklon": 0 }, +{ "label": "53/53", "node": 2574, "naklon": 0 }, +{ "label": "53/54", "node": 2571, "naklon": 0 }, +{ "label": "53/55", "node": 2570, "naklon": 0 }, +{ "label": "53/56", "node": 2576, "naklon": 0 }, +{ "label": "53/57", "node": 2881, "naklon": 0 }, +{ "label": "53/58", "node": 2575, "naklon": 0 }, +{ "label": "53/59", "node": 2572, "naklon": 0 }, +{ "label": "53/60", "node": 2569, "naklon": 0 }, +{ "label": "55/1", "node": 4324, "naklon": 0 }, +{ "label": "55/2", "node": 4319, "naklon": 0 }, +{ "label": "55/3", "node": 4327, "naklon": 0 }, +{ "label": "55/4", "node": 4333, "naklon": 0 }, +{ "label": "55/5", "node": 4332, "naklon": 0 }, +{ "label": "55/6", "node": 4320, "naklon": 0 }, +{ "label": "55/7", "node": 4317, "naklon": 0 }, +{ "label": "55/8", "node": 4318, "naklon": 0 }, +{ "label": "55/9", "node": 4328, "naklon": 0 }, +{ "label": "55/10", "node": 4323, "naklon": 0 }, +{ "label": "55/11", "node": 4325, "naklon": 0 }, +{ "label": "55/12", "node": 4326, "naklon": 0 }, +{ "label": "55/13", "node": 4316, "naklon": 0 }, +{ "label": "55/14", "node": 4322, "naklon": 0 }, +{ "label": "55/15", "node": 4331, "naklon": 0 }, +{ "label": "55/16", "node": 4321, "naklon": 0 }, +{ "label": "55/17", "node": 4315, "naklon": 0 }, +{ "label": "55/18", "node": 4329, "naklon": 0 }, +{ "label": "55/19", "node": 4334, "naklon": 0 }, +{ "label": "55/20", "node": 4330, "naklon": 0 } +]; + +module.exports = { naklony }; diff --git a/RVO23/databases/modbus_config.js b/RVO23/databases/modbus_config.js new file mode 100755 index 0000000..b73116a --- /dev/null +++ b/RVO23/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/RVO23/databases/nodes.table b/RVO23/databases/nodes.table new file mode 100755 index 0000000..7a71f8c --- /dev/null +++ b/RVO23/databases/nodes.table @@ -0,0 +1,36 @@ +node:number|pole_number:string|node_type:string|tbname:string|line:number|profile:string|processed:boolean|status:boolean|time_of_last_communication:number ++|3236|29|NEMA|rDbQ84xzwgdqEoPm3kbEVd09anOZY1RXyBv2LVM6|1||1|1|1760574014554|. ++|3059|26|NEMA|Nzp2OoJlqn6r1ZgvdA3BEK7abBwP5G4eE3RQmyxD|1||1|1|1760574023723|. ++|3343|2|NEMA|pE5X8NQPaow6vlOZxk6aby0q42ezGBMyWgDVjR3L|1||1|1|1760574016040|. ++|4150|33|NEMA|XMBbew5z4ELrZa2mRAd3nW78vPN6gy3DdVYlpKjq|1||1|1|1760574016743|. ++|3237|24|NEMA|3a5oqJN1bgnx4Ol9dk894Z7ByE6jQ8mKDWMpGrLV|1||1|1|1760574054612|. ++|3238|27|NEMA|PLBJzmK1r3Gynd6OW0gKgP0e5wV4vx9bDEqNgYR8|1||1|1|1760574054740|. ++|3242|28|NEMA|52dD6ZlV1QaOpRBmbAqG9QkKnGzWMLj4eJq38Pgo|1||1|1|1760574054867|. ++|3243|6|NEMA|g9OxBZ5KRwNznlY6pAppLdAWXvjdEL4eGQobMDy2|1||1|1|1760574015752|. ++|4074|17|NEMA|gRoJEyXVx4qD9er287L4xm7wBzGldaPjLWQKm3Mv|1||1|1|1760574016567|. ++|3123|25|NEMA|EjgWGnXaLy9opPOz20n42V786BlYM3w1deVQvbKr|1||1|0|1760071927933|. ++|4759|32|Kamera|nJL5lPMwBx23YpqRe0rpEv7damXvWVbOrD4gNzy8|1||1|1|1760574020896|. ++|4757|7|NEMA|OzNMgZ9n43qPbjXmy7zwLdA2DKdYvW5e6pxGRrVa|1||1|1|1760574020560|. ++|2729|18|NEMA|K94XLav1glVRnyQ6r01PMaAme3YJwBxM5oOzdP2j|1||1|1|1760574021231|. ++|2751|5|NEMA|JzwxZXOvDj1bVrN4nkW5VKA8qdyBl3MRKLpGPgaQ|1||1|1|1760574021391|. ++|3598|1|NEMA|2O14VBzl8aDmWdNw3A59qbAGyZ5qLJoEMpj6R9ng|1||1|1|1760574016200|. ++|2817|21|NEMA|aw4eELG2DlPMdn1JW0BMNbAqQXOZRN3xB5yp8VKr|1||1|1|1760574023371|. ++|3087|9A|NEMA|RvmwNz8QPblKp41GD7lKOVkJrLVYoBO92dMegn6W|1||1|1|1760574023947|. ++|4756|3|NEMA|6lQGaY9RDywdVzObj0PaYykPg4NBn3exEK51LWZq|1||1|1|1760574020400|. ++|3090|9B|NEMA|5dBNwRp9graYJxZn409NoQklVov1b2QLPDqGm6XK|1||1|1|1760574024139|. ++|3091|34|NEMA|gYbDLqlyZVoRerQpB72M9pkWJnwM5z24POKa8Exj|1||1|1|1760574024346|. ++|3092|14|NEMA|PjLblDgRBO6WQqnxmkJ1450Jv3ewZN4p5a89yKdY|1||1|1|1760574024522|. ++|3093|12|NEMA|Z5KyJe9nEg1QNbWlX0w4VmkoDjBLdqzR83VGv624|1||1|1|1760574024777|. ++|3094|20|NEMA|B5EoxeMVp4zwr8nqW0GB4xARjvD1PNamOGbLg63Z|1||1|1|1760574025065|. ++|3634|16|NEMA|d5xjWYMwEJon6rLlK7yEnK7qgV4DaOeNB9ZX3Gzb|1||1|1|1760574016375|. ++|3098|13|NEMA|1JMYvnx2RzKEo4aWQ7DG4GkL8yZV3m9NBePXbrdj|1||1|1|1760574025272|. ++|3099|10|NEMA|WlVJBygjDZMeKX3vnAMRMO08NqdmG2x1Y69LQ4P5|1||1|1|1760574025464|. ++|3102|8|NEMA|JX1ObgmqGZ54DMyYL7aDrdkEVdve38WKRzwjNrQ9|1||1|1|1760574025672|. ++|3113|11|NEMA|3JjOWdylwgNLzxVab7Na8BkZ2vG64rq8PEB5QmDo|1||1|1|1760574026039|. ++|3112|30|NEMA|E6Kg9oDnLWyzPRMva7v5xxkJxp4VG58qO2w1lZYe|1||1|1|1760574025847|. ++|3224|31|NEMA|roKgWqY95V3mXMRzyAjKvz0bLjexpJPvaGDBw826|1||1|1|1760574053814|. ++|3225|23|NEMA|eod9aRWLVl34Gx1Dn7VNjM72rz6qjgmpEXwQJN5Z|1||1|1|1760574053974|. ++|3226|22|NEMA|ZmRwd93QL4gaezxEbAx28Ok1prn2XjlPvGyqJ6BO|1||1|1|1760574014411|. ++|3228|4|NEMA|m6EYyZoJ4gWexdjVPAR59E7RDOq9wv2N5XzKGplr|1||1|1|1760574013979|. ++|2668|15|NEMA|dz4ojlpP85JMgDLZWkQJ3z7aKYqQexEr62GXRV1y|1||1|1|1760574088153|. ++|4754|19|NEMA|d9x2V5LGYBzXp4mMRAOmnqkPloaqJwnQj6DgrNe3|1||1|1|1760574020161|. diff --git a/RVO23/databases/nodes_original/nodes_original.table b/RVO23/databases/nodes_original/nodes_original.table new file mode 100755 index 0000000..f2c5865 --- /dev/null +++ b/RVO23/databases/nodes_original/nodes_original.table @@ -0,0 +1 @@ +[{"3236": "rDbQ84xzwgdqEoPm3kbEVd09anOZY1RXyBv2LVM6"}, {"3059": "Nzp2OoJlqn6r1ZgvdA3BEK7abBwP5G4eE3RQmyxD"}, {"3343": "pE5X8NQPaow6vlOZxk6aby0q42ezGBMyWgDVjR3L"}, {"4150": "XMBbew5z4ELrZa2mRAd3nW78vPN6gy3DdVYlpKjq"}, {"3237": "3a5oqJN1bgnx4Ol9dk894Z7ByE6jQ8mKDWMpGrLV"}, {"3238": "PLBJzmK1r3Gynd6OW0gKgP0e5wV4vx9bDEqNgYR8"}, {"3242": "52dD6ZlV1QaOpRBmbAqG9QkKnGzWMLj4eJq38Pgo"}, {"3243": "g9OxBZ5KRwNznlY6pAppLdAWXvjdEL4eGQobMDy2"}, {"4074": "gRoJEyXVx4qD9er287L4xm7wBzGldaPjLWQKm3Mv"}, {"3123": "EjgWGnXaLy9opPOz20n42V786BlYM3w1deVQvbKr"}, {"4759": "nJL5lPMwBx23YpqRe0rpEv7damXvWVbOrD4gNzy8"}, {"4757": "OzNMgZ9n43qPbjXmy7zwLdA2DKdYvW5e6pxGRrVa"}, {"2729": "K94XLav1glVRnyQ6r01PMaAme3YJwBxM5oOzdP2j"}, {"2751": "JzwxZXOvDj1bVrN4nkW5VKA8qdyBl3MRKLpGPgaQ"}, {"3598": "2O14VBzl8aDmWdNw3A59qbAGyZ5qLJoEMpj6R9ng"}, {"2817": "aw4eELG2DlPMdn1JW0BMNbAqQXOZRN3xB5yp8VKr"}, {"3087": "RvmwNz8QPblKp41GD7lKOVkJrLVYoBO92dMegn6W"}, {"4756": "6lQGaY9RDywdVzObj0PaYykPg4NBn3exEK51LWZq"}, {"3090": "5dBNwRp9graYJxZn409NoQklVov1b2QLPDqGm6XK"}, {"3091": "gYbDLqlyZVoRerQpB72M9pkWJnwM5z24POKa8Exj"}, {"3092": "PjLblDgRBO6WQqnxmkJ1450Jv3ewZN4p5a89yKdY"}, {"3093": "Z5KyJe9nEg1QNbWlX0w4VmkoDjBLdqzR83VGv624"}, {"3094": "B5EoxeMVp4zwr8nqW0GB4xARjvD1PNamOGbLg63Z"}, {"3634": "d5xjWYMwEJon6rLlK7yEnK7qgV4DaOeNB9ZX3Gzb"}, {"3098": "1JMYvnx2RzKEo4aWQ7DG4GkL8yZV3m9NBePXbrdj"}, {"3099": "WlVJBygjDZMeKX3vnAMRMO08NqdmG2x1Y69LQ4P5"}, {"3102": "JX1ObgmqGZ54DMyYL7aDrdkEVdve38WKRzwjNrQ9"}, {"3113": "3JjOWdylwgNLzxVab7Na8BkZ2vG64rq8PEB5QmDo"}, {"3112": "E6Kg9oDnLWyzPRMva7v5xxkJxp4VG58qO2w1lZYe"}, {"3224": "roKgWqY95V3mXMRzyAjKvz0bLjexpJPvaGDBw826"}, {"3225": "eod9aRWLVl34Gx1Dn7VNjM72rz6qjgmpEXwQJN5Z"}, {"3226": "ZmRwd93QL4gaezxEbAx28Ok1prn2XjlPvGyqJ6BO"}, {"3228": "m6EYyZoJ4gWexdjVPAR59E7RDOq9wv2N5XzKGplr"}, {"2668": "dz4ojlpP85JMgDLZWkQJ3z7aKYqQexEr62GXRV1y"}, {"4754": "d9x2V5LGYBzXp4mMRAOmnqkPloaqJwnQj6DgrNe3"}] \ No newline at end of file diff --git a/RVO23/databases/notifications.table b/RVO23/databases/notifications.table new file mode 100755 index 0000000..f7c96cb --- /dev/null +++ b/RVO23/databases/notifications.table @@ -0,0 +1,41 @@ +key:string|weight:string|sk:string|en:string ++|switching_profile_point_applied_to_line|INFORMATIONAL|Aplikovaný bod spínacieho profilu na línií č. ${line} : ${value}|Switching profile point applied to line no. ${line} : ${value}|............... ++|dusk_has_occured|INFORMATIONAL|Nastal súmrak: ${value}|Dusk has occured: ${value}|............... ++|dawn_has_occured|INFORMATIONAL|Nastal úsvit: ${value}|Dawn has occured: ${value}|............... ++|dimming_profile_was_successfully_received_by_node|NOTICE|Stmievací profil bol úspešne prijatý nodom č. ${node}|Dimming profile was successfully received by node no. ${node}|............... ++|master_node_is_responding_again|NOTICE|Master node začal znovu odpovedať|Master node is responding again|............... ++|command_was_sent_from_terminal_interface|DEBUG|Z terminálu bol odoslaný príkaz|A command was sent from terminal interface|............... ++|master_node_is_not_responding|ALERT|Master node neodpovedá|Master node is not responding|............... ++|configuration_of_dimming_profile_to_node_failed|ALERT|Konfigurácia stmievacieho profilu pre node č. ${node} zlyhala|Configuration of dimming profile to node no. ${node} has failed|............... ++|circuit_breaker_was_turned_on_line|NOTICE|Zapnutie ističa na línii č. ${line}|Circuit breaker was turned on - line no. ${line}|............... ++|circuit_breaker_was_turned_off_line|ERROR|Vypnutie ističa na línií č. ${line}|Circuit breaker was turned off - line no. ${line}|............... ++|dimming_profile_was_processed_for_node|INFORMATIONAL|Stmievací profil bol spracovaný pre node č. ${node}|Dimming profile was processed for node no. ${node}|............... ++|switching_profile_was_processed_for_line|INFORMATIONAL|Spínací profil bol spracovaný pre líniu č. ${line}|Switching profile was processed for line no. ${line}|............... ++|thermometer_is_not_responding|WARNING|Teplomer neodpovedá|Thermometer is not responding|............... ++|thermometer_is_responding_again|NOTICE|Teplomer znovu odpovedá|Thermometer is responding again|............... ++|thermometer_sends_invalid_data|WARNING|Teplomer posiela neplatné hodnoty|Thermometer sends invalid data|............... ++|main_switch_has_been_turned_off|CRITICAL|Hlavný vypínač bol vypnutý|Main switch has been turned off|............... ++|main_switch_has_been_turned_on|NOTICE|Hlavný vypínač bol zapnutý|Main switch has been turned on|............... ++|power_supply_has_disconnected_input|ALERT|Napájací zdroj nemá napätie na vstupe|Power supply has disconnected input|............... ++|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_main_open|NOTICE|Hlavné dvere boli otvorené|Main door has been opened|............... ++|door_em_open|NOTICE|Dvere silovej časti boli otvorené|Power door has been opened|............... ++|door_main_open_without_permission|WARNING|Hlavné dvere boli otvorené bez povolenia - zapnutá siréna|Main door has been opened without permission - alarm is on|............... ++|door_em_open_without_permission|WARNING|Dvere silovej časti boli otvorené bez povolenia|Power door has been opened without permission|............... ++|door_main_close|NOTICE|Hlavné dvere boli zatvorené|Main door has been closed|............... ++|door_em_close|NOTICE|Dvere silovej časti boli zatvorené|Power door has been closed|............... ++|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|............... ++|electrometer_ok|NOTICE|Elektromer znovu odpovedá|Electrometer is responding again|............... ++|no_voltage_on_phase|CRITICAL|Na fáze č. ${phase} nie je napätie|No voltage detected on phase no. ${phase}|............... ++|voltage_on_phase_restored|NOTICE|Napätie na fáze č. ${phase} bolo obnovené|Voltage on phase no. ${phase} has been restored|............... ++|flow_start|NOTICE|FLOW bol spustený|FLOW has been started |............... ++|twilight_sensor_nok|ERROR|Sensor súmraku neodpovedá|Twilight sensor is not responding|............... ++|twilight_sensor_ok|NOTICE|Sensor súmraku znovu odpovedá|Twilight sensor is responding again|............... ++|lamps_have_turned_on|NOTICE|Lampy sa zapli|Lamps have turned on|............... ++|lamps_have_turned_off|NOTICE|Lampy sa vypli|Lamps have turned off|............... ++|flow_restart|NOTICE|FLOW bol reštartovaný|FLOW has been restarted|............... ++|nodes_db_changed|NOTICE|Zmena v node databáze|Node db has changed|............... diff --git a/RVO23/databases/pins.table b/RVO23/databases/pins.table new file mode 100755 index 0000000..0eb3d05 --- /dev/null +++ b/RVO23/databases/pins.table @@ -0,0 +1,14 @@ +pin:string|type:string|line:number +*|input1_01|door_condition|0|........... +*|input1_02|rotary_switch_state|0|........... +*|input1_03|rotary_switch_state|0|........... +*|input1_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/RVO23/databases/relays.table b/RVO23/databases/relays.table new file mode 100755 index 0000000..98c1b91 --- /dev/null +++ b/RVO23/databases/relays.table @@ -0,0 +1,5 @@ +line:number|tbname:string|contactor:number|profile:string ++|0|WlVJBygjDZMeKX3vnAMRrQ08NqdmG2x1Y69LQ4P5|1||........... ++|3|DbQY6zyveZRwK5drV0Z8XL7joE4XJM83N9xl2nWq|9|{"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}|................................................................................................................................................................................................................................................................................................................................... ++|1|zrR51V2ajQ9ZLygPKkEMnpkYDq38xOJolENBXGnv|9|{"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|BaY3Xpy1EbKGjLq2O7maLo7rx8owgQz9P4dDJRmN|9|{"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/RVO23/databases/settings.table b/RVO23/databases/settings.table new file mode 100755 index 0000000..fbc147e --- /dev/null +++ b/RVO23/databases/settings.table @@ -0,0 +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|project_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|cloud_topic:string|has_main_switch:boolean|daily_report:boolean|send_changed_node_numbers:boolean ++|rvo_senica_23_ip110|sk|28.E22E9D0E0000|48.679317199|17.36576261|192.168.252.1|rvo_senica_23_ip110|FYQriv2vupZc0xyFVJkI|1883|0|53|unipi|ttyUSB0|1|20|5|6|3|u110|0|1|1|................................................... diff --git a/RVO23/databases/tbdata.nosql b/RVO23/databases/tbdata.nosql new file mode 100755 index 0000000..e8d3912 --- /dev/null +++ b/RVO23/databases/tbdata.nosql @@ -0,0 +1,4 @@ +-"WlVJBygjDZMeKX3vnAMRrQ08NqdmG2x1Y69LQ4P5":[{"ts":1760522431455,"values":{"_event":{"type":"notice","status":"new","source":{"func":"modbus_reader","component":"1699965957410","component_name":"Modbus reader","edge":"WlVJBygjDZMeKX3vnAMRrQ08NqdmG2x1Y69LQ4P5"},"message":{"sk":"rvo_senica_23_ip110: FLOW bol reštartovaný","en":"rvo_senica_23_ip110: FLOW has been restarted"},"message_data":""}}}],"id":"3000180001lt71b"} +-"WlVJBygjDZMeKX3vnAMRrQ08NqdmG2x1Y69LQ4P5":[{"ts":1760522431546,"values":{"edge_fw_version":"2025-10-08","maintenance_mode":false}}],"id":"3000180002lt70b"} +-"WlVJBygjDZMeKX3vnAMRrQ08NqdmG2x1Y69LQ4P5":[{"ts":1760522431560,"values":{"statecode":2,"power_mode":"Automatic"}}],"id":"3000180004lt70b"} +-"WlVJBygjDZMeKX3vnAMRrQ08NqdmG2x1Y69LQ4P5":[{"ts":1760522431590,"values":{"_event":{"type":"notice","status":"new","source":{"func":"rsPort.open()","component":"1699963668903","component_name":"DIDO_Controller","edge":"WlVJBygjDZMeKX3vnAMRrQ08NqdmG2x1Y69LQ4P5"},"message":{"sk":"rvo_senica_23_ip110: FLOW bol spustený","en":"rvo_senica_23_ip110: FLOW has been started "},"message_data":""}}}],"id":"3000180006lt70b"} diff --git a/RVO23/databases/tbdatacloud.nosql b/RVO23/databases/tbdatacloud.nosql new file mode 100755 index 0000000..3ca30f1 --- /dev/null +++ b/RVO23/databases/tbdatacloud.nosql @@ -0,0 +1,3 @@ +-"WlVJBygjDZMeKX3vnAMRrQ08NqdmG2x1Y69LQ4P5":[{"ts":1760522431546,"values":{"edge_fw_version":"2025-10-08","maintenance_mode":false}}],"id":"3000180003lt71b"} +-"WlVJBygjDZMeKX3vnAMRrQ08NqdmG2x1Y69LQ4P5":[{"ts":1760522431560,"values":{"statecode":2,"power_mode":"Automatic"}}],"id":"3000180005lt71b"} +-"WlVJBygjDZMeKX3vnAMRrQ08NqdmG2x1Y69LQ4P5":[{"ts":1760522431590,"values":{"_event":{"type":"notice","status":"new","source":{"func":"rsPort.open()","component":"1699963668903","component_name":"DIDO_Controller","edge":"WlVJBygjDZMeKX3vnAMRrQ08NqdmG2x1Y69LQ4P5"},"message":{"sk":"rvo_senica_23_ip110: FLOW bol spustený","en":"rvo_senica_23_ip110: FLOW has been started "},"message_data":""}}}],"id":"3000180007lt71b"} diff --git a/RVO23/databases/total_energy.js b/RVO23/databases/total_energy.js new file mode 100755 index 0000000..dde340e --- /dev/null +++ b/RVO23/databases/total_energy.js @@ -0,0 +1,38 @@ +//key is rvo_number, value is max energy when lamps are on +const total_energy = { + 1: 580, + 2: 1100, + 3: 3700, + 4: 4100, + 7: 360, + 12: 1700, + 13: 5400, + 14: 440, + 15: 6100, + 16: 4800, + 20: 1600, + 21: 1000, + 22: 2600, + 23: 1000, + 25: 2600, + 33: 240, + 34: 4000, + 35: 2700, + 36: 820, + 37: 1400, + 35: 3500, + 39: 1170, + 41: 740, + 42: 660, + 43: 4900, + 45: 930, + 46: 700, + 47: 1100, + 48: 1500, + 50: 3200, + 53: 1250, + 55: 1000, + 56: 5500 +} + +module.exports = total_energy; diff --git a/RVO23/debug.js b/RVO23/debug.js new file mode 100755 index 0000000..9818194 --- /dev/null +++ b/RVO23/debug.js @@ -0,0 +1,16 @@ +// =================================================== +// FOR DEVELOPMENT +// Total.js - framework for Node.js platform +// https://www.totaljs.com +// =================================================== + +const options = {}; + +// options.ip = '127.0.0.1'; +// options.port = parseInt(process.argv[2]); +// options.config = { name: 'Total.js' }; +// options.sleep = 3000; +// options.inspector = 9229; +// options.watch = ['private']; + +require('total.js/debug')(options); \ No newline at end of file diff --git a/RVO23/err.txt b/RVO23/err.txt new file mode 100755 index 0000000..5a2c4c9 --- /dev/null +++ b/RVO23/err.txt @@ -0,0 +1,78 @@ +[2024-10-25T21:00:49.080] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-25T22:01:01.214] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-25T23:01:13.497] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T00:01:25.752] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T01:01:38.033] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T02:01:50.264] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T03:02:02.483] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T04:02:15.706] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T05:02:27.925] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T06:02:40.203] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T07:02:52.477] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T08:03:04.793] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T09:03:17.066] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T10:03:29.353] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T11:03:41.857] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T12:03:54.117] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T13:04:06.355] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T14:04:18.581] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T15:04:30.817] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T16:04:43.005] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T17:04:55.175] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T18:05:07.453] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T19:05:19.575] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T20:05:31.731] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T21:05:43.909] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T22:05:56.018] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T23:06:08.136] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T00:06:20.256] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T01:06:32.398] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T02:06:44.552] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T02:06:56.707] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T03:07:08.826] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T04:07:21.874] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T05:07:34.023] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T06:07:46.148] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T07:07:58.302] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T08:08:10.533] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T09:08:22.842] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T10:08:34.941] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T11:08:47.047] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T12:08:59.185] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T13:09:11.278] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T14:09:23.378] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T15:09:35.497] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-12-08T13:40:50.373] [ERROR] errLogs - Thermometer Thermometer: temperatureAddress is not defined +[2025-09-23T14:09:04.447] [ERROR] errLogs - uncaughtException: Cannot read property 'getHours' of undefined +[2025-09-23T14:09:04.449] [ERROR] errLogs - TypeError: Cannot read property 'getHours' of undefined + at Timeout.emptyReportToSend [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:09:04.450] [ERROR] errLogs - uncaughtException: Cannot read property 'getHours' of undefined +[2025-09-23T14:09:04.450] [ERROR] errLogs - TypeError: Cannot read property 'getHours' of undefined + at Timeout.emptyReportToSend [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:09:04.459] [ERROR] errLogs - uncaughtException: Cannot read property 'getHours' of undefined +[2025-09-23T14:09:04.460] [ERROR] errLogs - TypeError: Cannot read property 'getHours' of undefined + at Timeout.emptyReportToSend [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:09:10.195] [ERROR] errLogs - uncaughtException: date.getHours is not a function +[2025-09-23T14:09:10.196] [ERROR] errLogs - TypeError: date.getHours is not a function + at emptyReportToSend (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at Timeout.dailyReportCheck [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1351:5) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:09:10.196] [ERROR] errLogs - uncaughtException: date.getHours is not a function +[2025-09-23T14:09:10.197] [ERROR] errLogs - TypeError: date.getHours is not a function + at emptyReportToSend (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at Timeout.dailyReportCheck [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1351:5) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:09:10.202] [ERROR] errLogs - uncaughtException: date.getHours is not a function +[2025-09-23T14:09:10.202] [ERROR] errLogs - TypeError: date.getHours is not a function + at emptyReportToSend (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at Timeout.dailyReportCheck [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1351:5) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) diff --git a/RVO23/flow/cloudmqttconnect.js b/RVO23/flow/cloudmqttconnect.js new file mode 100755 index 0000000..b03491f --- /dev/null +++ b/RVO23/flow/cloudmqttconnect.js @@ -0,0 +1,357 @@ +exports.id = 'cloudmqttconnect'; +exports.title = 'Cloud connect mqtt'; +exports.group = 'MQTT'; +exports.color = '#888600'; +exports.version = '1.0.2'; +exports.icon = 'sign-out'; +exports.input = 2; +exports.output = 2; +exports.options = { host: 'tb-stage.worksys.io', port: 1883, clientid: "", username: "" }; + +exports.html = `
+
+
+
Hostname or IP address (if not empty - setting will override db setting)
+
+
+
Port
+
+
+
+
+
@(Client id)
+
+
+
topic
+
+
+
`; + + + +const { promisifyBuilder } = require('./helper/db_helper'); +const fs = require('fs'); +const mqtt = require('mqtt'); +const nosql = NOSQL('tbdatacloud'); + +const SEND_TO = { + debug: 0, + rpcCall: 1, +} + +//CONFIG +let saveTelemetryOnError = true;//backup_on_failure overrides this value +//------------------------ + +const noSqlFileSizeLimit = 4194304;//use 5MB - 4194304 +let insertNoSqlCounter = 0; +let insertBackupNoSqlCounter = 0; +let processingData = false; + +let backup_on_failure = true;//== saveTelemetryOnError - create backup client send failure +let restore_from_backup = 50; //how many rows process at once? +let restore_backup_wait = 3;//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; + + +exports.install = function(instance) { + + var client; + var opts; + var clientReady = false; + + let o = {}; //options + + function main() { + loadSettings(); + } + + //set opts according to db settings + function loadSettings() { + + o = instance.options; + if (!o.topic) o.topic = FLOW.GLOBALS.settings.cloud_topic; + + opts = { + host: o.host, + port: o.port, + clientId: o.clientid, + username: o.username, + rejectUnauthorized: false, + resubscribe: false + }; + + console.log("wsmqttpublich -> loadSettings from instance.options", o); + + if (!o.topic) { + instance.status("Not configured", "white"); + console.log("Cloud mqtt connect: no topic selected"); + return; + } + + connectToTbServer(); + } + + function connectToTbServer() { + var url = "mqtt://" + opts.host + ":" + opts.port; + console.log("MQTT URL: ", url); + + client = mqtt.connect(url, opts); + + client.on('connect', function() { + client.subscribe(`${o.topic}_backward`, (err) => { + if (!err) { + console.log("MQTT subscribed"); + } + }); + instance.status("Connected", "green"); + clientReady = true; + sendClientError = true; + }); + + client.on('reconnect', function() { + instance.status("Reconnecting", "yellow"); + clientReady = false; + }); + + client.on('message', function(topic, message) { + // message is type of buffer + message = message.toString(); + if (message[0] === '{') { + TRY(function() { + + message = JSON.parse(message); + if (message.hasOwnProperty("device") && message.hasOwnProperty("data") && message.data.hasOwnProperty("id")) { + client.publish(`${o.topic}_forward`, `{"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 } }); + } + + }, () => instance.debug('MQTT: Error parsing data', message)); + } + + instance.send(SEND_TO.rpcCall, { "topic": o.topic, "content": message }); + }); + + client.on('close', function() { + clientReady = false; + + instance.status("Disconnected", "red"); + instance.send(SEND_TO.debug, { "message": "Client CLOSE signal received !" }); + }); + + client.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) { + console.log('MQTT client error', err); + sendClientError = false; + } + clientReady = false; + }); + + } + + + instance.on('0', function(data) { + + if (clientReady) { + //do we have some data in backup file? if any, process data from database + if (saveTelemetryOnError) { + //read telemetry data and send back to server + if (!processingData) processDataFromDatabase(); + } + + let stringifiedJson = JSON.stringify(data.data) + client.publish(`${o.topic}_forward`, stringifiedJson, { qos: 1 }); + } + 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 (saveTelemetryOnError && o.topic) { + //create new file from tbdata.nosql, if file size exceeds given limit, and clear tbdata.nosql + makeBackupFromDbFile(); + + //write to tb + data.data.id = UID(); + nosql.insert(data.data); + } + } + }); + + instance.on("1", _ => { + main(); + }) + + instance.close = function(done) { + if (clientReady) { + client.end(); + } + }; + + + function getDbBackupFileCounter(type) { + var files = fs.readdirSync(__dirname + "/../databases"); + + let counter = 0; + for (var i = 0; i < files.length; i++) { + + if (files[i] == "tbdatacloud.nosql") continue; + + if (files[i].endsWith(".nosql")) { + + let pos = files[i].indexOf("."); + if (pos > -1) { + + let fileCounter = counter; + let firstDigit = files[i].slice(0, pos); + + fileCounter = parseInt(firstDigit); + if (isNaN(fileCounter)) fileCounter = 0; + //console.log("getDbBackupFileCounter digit:", files[i], firstDigit, fileCounter, isNaN(fileCounter), type); + + if (type == "max") { + if (fileCounter > counter) { + counter = fileCounter; + } + } + else if (type == "min") { + if (counter == 0) counter = fileCounter; + + if (fileCounter < counter) { + counter = fileCounter; + } + } + } + } + + } + + if (type == "max") counter++; + + return counter; + } + + const makeBackupFromDbFile = async () => { + + if (!saveTelemetryOnError) return; + + //to avoid large file: tbdata.nosql + + //init value is 0! + if (insertNoSqlCounter > 0) { + --insertNoSqlCounter; + return; + } + + insertNoSqlCounter = 100; + + let source = __dirname + "/../databases/tbdatacloud.nosql"; + + var stats = fs.statSync(source); + var fileSizeInBytes = stats.size; + + if (fileSizeInBytes > noSqlFileSizeLimit) { + + let counter = 1; + counter = getDbBackupFileCounter("max"); + + let destination = __dirname + "/../databases/" + counter + "." + "tbdatacloud.nosql"; + + //make backup file + fs.copyFileSync(source, destination); + //fs.renameSync(p, p + "." + counter); + + //clear tbdata.nosql + fs.writeFileSync(source, ""); + fs.truncateSync(source, 0); + + } + } + + const processDataFromDatabase = async () => { + + if (restore_from_backup <= 0) return; + + //calculate diff + const now = new Date(); + let currentTime = now.getTime(); + let diff = currentTime - lastRestoreTime; + + if ((diff / 1000) < restore_backup_wait) { + //console.log("*********restore_backup_wait", diff, restore_backup_wait); + return; + } + + processingData = true; + + //get filename to process + let counter = getDbBackupFileCounter("min"); + + //we have some backup files + let dataBase = 'tbdata'; + + var nosql; + if (counter == 0) dataBase = 'tbdatacloud'; + else dataBase = counter + "." + 'tbdatacloud'; + + nosql = NOSQL(dataBase); + + //select all data - use limit restore_from_backup + let records = await promisifyBuilder(nosql.find().take(restore_from_backup)); + + for (let i = 0; i < records.length; i++) { + if (clientReady) { + + let item = records[i]; + let id = item.id; + + if (id !== undefined) { + //console.log("------------processDataFromDatabase - remove", id, dataBase, i); + + try { + + let message = JSON.parse(JSON.stringify(item)); + delete message.id; + client.publish(`${o.topic}_forward`, JSON.stringify(message), { qos: 1 }); + + //remove from database + await promisifyBuilder(nosql.remove().where("id", id)); + + } catch (error) { + //process error + console.log("processDataFromDatabase", error); + } + + } + + } + else { + processingData = false; + return; + } + } + + if (records.length > 0) { + //clean backup file + if (counter > 0) nosql.clean(); + } + + //no data in db, remove + if (records.length == 0) { + if (counter > 0) nosql.drop(); + } + + const d = new Date(); + lastRestoreTime = d.getTime(); + + processingData = false; + + } + + instance.on('options', main); + +}; diff --git a/RVO23/flow/cmd_manager.js b/RVO23/flow/cmd_manager.js new file mode 100755 index 0000000..25912df --- /dev/null +++ b/RVO23/flow/cmd_manager.js @@ -0,0 +1,3071 @@ +exports.id = 'cmd_manager'; +exports.title = 'CMD Manager'; +exports.group = 'Worksys'; +exports.color = '#5D9CEC'; +exports.version = '0.0.3'; +exports.output = ['red', 'blue', 'yellow', 'blue', 'white', 'green']; +exports.input = 3; +exports.icon = 'cloud-upload'; + +exports.html = ` +
+
+
+
RPC - run RPC calls

+
+
+
@(User)
+
+
+
@(Password)
+
+
+
@(My edge)
+
+
+
+`; +exports.readme = `Manager for CMD calls`; + + +exports.install = function(instance) { + + 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, isEmptyObject, emptyJsObject, writeToFile, addToArrayIfUnique } = require('./helper/utils'); + const bitwise = require('bitwise'); + + var SunCalc = require('./helper/suncalc'); + const DataToTbHandler = require('./helper/DataToTbHandler'); + const errorHandler = require('./helper/ErrorToServiceHandler'); + const { sendNotification } = require('./helper/notification_reporter'); + const process = require('process'); + const { errLogger, logger, monitor } = require('./helper/logger'); + + //for accelerometer purposes + const { naklony } = require("../databases/accelerometer_db"); + + const dbNodes = TABLE("nodes"); + const dbRelays = TABLE("relays"); + + let GLOBALS; + let SETTINGS; + let rsPort; + let tbHandler; + + // runTasks intervals + const SHORT_INTERVAL = 30; + const LONG_INTERVAL = 300; + + //send data to following instances: + const SEND_TO = { + debug: 0, + tb: 1, + http_response: 2, + dido_controller: 3, + infoSender: 4, + dailyReport: 5 + } + + 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 + } + + 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 sendNodeReadout = null; // interval for sending agregate data from node + + 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["1"] = minutes; // dimming + priorities["76"] = minutes; // power + + minutes = 5; + priorities["75"] = minutes; // current + priorities["79"] = minutes; // energy + priorities["87"] = minutes; // aktualny cas + //priorities["84"] = minutes; //accelerometer + + minutes = 10; + priorities["74"] = minutes; // voltage + priorities["77"] = minutes; // power factor + priorities["78"] = minutes; // frequency + + minutes = 60; + priorities["0"] = minutes; // statecode + priorities["6"] = minutes; // dusk + priorities["7"] = minutes; // dawn + priorities["8"] = minutes; // profile + + minutes = 60 * 24; + priorities["89"] = minutes; // verzia fw + priorities["80"] = minutes; // lifetime + + //prikazy kt sa budu spustat na dany node - see config.js in terminal-oms.app. (1 - dimming) + let listOfCommands = [0, 1, 6, 7, 8, 74, 75, 76, 77, 78, 79, 80, 87, 89]; + + 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; + + // holds dusk, dawn (and more) values + let sunCalcResult; + + //helper container for counting resolved group of commands (commands related to set profile) + let cmdCounter = {};//key is node, value is counter + + //TODO: is this set working?? According to previous checks, sets do not work + //if sending of profile to node fails, we send notification and push node into set, so we do not send notification twice + const nodeProfileSendFail = new Set(); + + //we expect to get current temperature in Senica from senica-prod01 + let temperatureInSenica = null; + let accelerometerInterval = null; + + //NOTE: daily reports senica: + //rvo_is_on status, we monitor all nodes - if true, power and dimming should be not 0, if false, 24/7 nodes should be 0, other rvo should not respond + let rvo_is_on; + let previous_rvo_is_on_value; + let handleDailyReport; //setInterval for dailyReportHandler function + let dailyReport = {}; //data needed for daily report + let reportToSend = {}; //final report which we send to cloud + let breakerCounter = null; // status of breakers after flow starts is not in report + let rvoPeriod; // interval of checking dusk dawn and if rvo_is_on + let initialReportStatus = false; + + const DAILY_REPORT_HANDLER_TIME = 3_600_000; + const SET_SUNCALC_RESULT_TIME = 3_600_000; + const SET_RVO_PERIOD_TIME = 300_000; + const ADD_NODE_TO_REPORT_TIME = 3_600_000; + + //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); + + let now = new Date(); + console.log("Cmd-mngr installed", now.toLocaleString("sk-SK")); + + sunCalcResult = calculateDuskDawn(); + + handleRsPort(); + + customTasksInterval = setInterval(reportEdgeDateTimeAndNumberOfLuminaires, 120_000); + setTimeout(reportEdgeDateTimeAndNumberOfLuminaires, 4000); + + //dailyReport related + emptyReportToSend(); + breakerCounter = Object.keys(relaysData).length - 1; // we get number of lines (breakers) except of line 0 + rvoPeriod = setInterval(setRvoPeriod, SET_RVO_PERIOD_TIME); + setTimeout(setRvoPeriod, 3000); + setInterval(setSunCalcResult, SET_SUNCALC_RESULT_TIME); + handleDailyReport = setInterval(dailyReportHandler, DAILY_REPORT_HANDLER_TIME); + + + setCorrectTime = setInterval(setCorrectPlcTimeOnceADay, 60000 * 60); // 1 hour + setCorrectPlcTimeOnceADay(); + + sendNodeReadout = setInterval(sendNodesData, 150_000); + accelerometerInterval = setInterval(accelerometerData, 60000 * 30); //30 min + } + + + 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" + //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 + // if node regular readout does not respond, we repeat request + params.repeatCounter = 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-mngr: 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.byte4 = 96; + params.recipient = 1; + params.register = 8; + params.rw = 1;//write + params.timestamp = timestamp; + 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.byte4 = 96; + params.recipient = 1; + params.register = 8; + params.rw = 1;//write + params.timestamp = timestamp; + 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). + */ + + 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.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.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 + { + + logger.debug("processNodeProfile: Threshold lux level for DUSK/DAWN", node); + + let params = getParams(); + params.type = "set_node_profile"; + params.address = node; + params.register = 96; + params.recipient = 1; + params.rw = 1;//write + params.timestamp = timestamp; + 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(); + params.type = "set_node_profile"; + params.address = node; + params.register = 97; + params.recipient = 1; + params.rw = 1;//write + params.timestamp = timestamp; + 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.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); + + 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); + + console.log("proces profile finished *********************") + } + + + 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; + }); + } + + + 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) { + for (let k in nodesData) { + 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`); + } + } + } + + + function loadRelaysData(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 (value.contactor == 1) processAllNodeProfilesOnLine(value.line); + } + } + + + function reportOnlineNodeStatus(line) { + //Po zapnutí línie broadcastovo aktualizovať predtým čas a o 3 sek neskor - status, brightness + + logger.debug("Cmd-mngr: ----->reportOnlineNodeStatus for line", line); + + const d = new Date(); + + // broadcast actual time + let params = getParams(); + params.address = 0xffffffff;//Broadcast + params.byte1 = d.getHours(); + params.byte2 = d.getMinutes(); + params.recipient = 2;//2 broadcast, address = 0 + params.register = 87;//Actual time + params.rw = 1;//write + params.type = "node-onetime-write"; + params.timestamp = d.getTime() + 30000; + params.info = "run broadcast: Actual time"; + //params.debug = true; + + tasks.push(params); + + let sec = 3; + setTimeout(function() { + //Po zapnutí línie - spraviť hromadný refresh stavu práve zapnutých svietidiel + + let time = Date.now(); + + for (let k in nodesData) { + + //potrebujem nody k danej linii + 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].node_status_before_offline === true || nodesData[k].status === true) { + status = "OK"; + nodesData[k].time_of_last_communication = time; + } + + nodesData[k].readout.status = status; + + updateNodeStatus(k, status === "OK" ? true : false); + if (nodesData[k].hasOwnProperty("node_status_before_offline")) delete nodesData[k].node_status_before_offline; + sendTelemetry({ status: status }, tbname, time); + + //vyreportovanie dimming, current, input power pre liniu pre vsetky nody + //Prud + { + let params = getParams(); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 75;//prud + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = time + 4000; + params.info = 'read current'; + //params.debug = true; + tasks.push(params); + } + + //vykon + { + let params = getParams(); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 76;//výkon + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = time + 4100; + params.info = 'read power'; + //params.debug = true; + + tasks.push(params); + } + //dimming + { + let params = getParams(); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 1;//dimming + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = time + 4200; + params.info = 'read dimming'; + //params.debug = true; + + tasks.push(params); + } + + } + } + + }, sec * 1000); + } + + + function reportOfflineNodeStatus(line) { + + logger.info("Cmd-mngr: ------>reportOffLineNodeStatus for line ", line); + + values = {}; + values["dimming"] = 0;//brightness + values["power"] = 0;//výkon + values["current"] = 0;//prúd + values["status"] = "OFFLINE"; + + const date = Date.now(); + + Object.keys(nodesData).forEach(node => { + + //potrebujem nody k danej linii + if (line == nodesData[node].line || line == undefined) { + + let tbname = nodesData[node].tbname; + let nodeStatus = nodesData[node].status; + + //in case we have reported offline node status, we return (continue with next node) + if (nodeStatus === "OFFLINE") return; + + nodesData[node].node_status_before_offline = nodeStatus; + nodesData[node].status = "OFFLINE"; + nodesData[node].readout = {}; + + sendTelemetry({ ...values }, tbname, date); + } + }); + + } + + + function turnLine(onOrOff, line, info) { + let obj = { + line: line, + command: onOrOff, + info: info + }; + + //to assure, handleDailyReportFunction do not run before rvo_is_on variable changes. So after every line switch we reset the timer + clearInterval(handleDailyReport); + handleDailyReport = setInterval(dailyReportHandler, DAILY_REPORT_HANDLER_TIME); + + //logger.debug("linia", line, obj); + instance.send(SEND_TO.dido_controller, obj); + } + + + 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"; + 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]) { + //CRC_ERROR + message = "NOK"; + error = "CRC_ERROR c1"; + instance.send(SEND_TO.debug, "CRC_ERROR c1"); + } + + 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") { + instance.send(SEND_TO.debug, bytes); + instance.send(SEND_TO.debug, "RESPONSE " + type + " - " + bytes[4]); + + //logger.debug(SEND_TO.debug, "RESPONSE " + type + " - " + bytes[4], bytes); + + error = "type is: " + type; + + message = "NOK"; + } + + return { message, type, error }; + } + + + //BUILD TASKS// + function buildTasks(params) { + + //return; + console.log("buidTAaasks start ****************", params); + monitor.info("buildTasks - params", params); + + let processLine; //defined line + let init = false; + let processLineProfiles = true; + let processBroadcast = true; + let processNodes = true; + + if (params == undefined) { + init = true; + tasks = []; + logger.debug("-->buildTasks clear tasks"); + } + else { + processLineProfiles = params.processLineProfiles; + processBroadcast = false; + processNodes = false; + + processLine = params.line; + } + + let now = new Date(); + + //process line profiles + if (processLineProfiles) { + + let keys = Object.keys(relaysData); + + for (let i = 0; i < keys.length; i++) { + + let line = parseInt(keys[i]); + let profilestr = relaysData[line].profile; + + if (processLine != undefined) { + if (processLine != line) continue; + } + + try { + + /** + * we process line profiles: timepoints, astro clock, lux_sensor, offsets ... + */ + if (profilestr === "") throw ("Profile is not defined"); + let profile = JSON.parse(profilestr); + 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; + + // add name to regular profile timepoint and delete unused end_time key: + time_points.forEach(point => { + point.name = "profileTimepoint" + delete point.end_time; + }); + + //monitor.info("buildTasks: time_points", time_points); + + + /** + * 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 astro clock true, we remove all regular profile points + time_points = []; + + //TODO: when astro clock == true, is offset calculated ??? + //let duskAstroClockOffset = profile.dusk_astro_clock_offset; + //let dawnAstroClockOffset = profile.dawn_astro_clock_offset; + //console.log("line astro clock offsets dusk a dawn: ", duskAstroClockOffset, dawnAstroClockOffset); + // maybe add dusk dawn offset to calculateDuskDawn ?? what dusk dawn will be if dawn_lux_sensor == true?? + //let sunCalcResult = calculateDuskDawn(new Date(), line, duskAstroClockOffset, dawnAstroClockOffset); + + 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 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); + + 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); + + 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(':'); + + let ad = new Date(); + ad.setHours(parseInt(ahours), parseInt(aminutes), 0); + + let bd = new Date(); + bd.setHours(parseInt(bhours), parseInt(bminutes), 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++) { + + let start_time = new Date(); + let [hours, minutes] = time_points[t].start_time.split(':'); + start_time.setHours(parseInt(hours), parseInt(minutes), 0); + + //task is in 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(); + params.type = "relay"; + params.line = parseInt(line); + params.value = time_points[t].value; + params.tbname = relaysData[line].tbname; + params.timestamp = start_time.getTime(); + + // 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; + + //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)) { + 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; + + params.debug = true; + + //turn on/off line + tasks.push(params); + monitor.info("TimePoint params: ", params.info, start_time); + } + + monitor.info("-->time_points final", line, time_points); + + //ensure to turn on/off according to calculated currentValue + let params = getParams(); + params.type = "relay"; + params.line = parseInt(line); + params.tbname = relaysData[line].tbname; + params.value = currentValue; + params.timestamp = i; + params.debug = true; + + //logger.debug(now.toLocaleString("sk-SK")); + 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; + + tasks.push(params); + + } catch (error) { + if (profilestr !== "") { + //errLogger.error(profilestr, error); + console.log(`Cmd_mngr: Unable to process line profile ${line}. Error: `, error); + errorHandler.sendMessageToService(profilestr + "-" + error, 0, "js_error"); + } else { + turnLine("off", line, "No line profile. Switching it off on startup"); + } + } + + } + //logger.debug("tasks:"); + //logger.debug(tasks); + } + + + //NOTE: PROCESS DEFAULT BROADCASTS - Time of dusk, Time of dawn, Actual Time + if (processBroadcast) { + + let d = new Date(); + let time = d.getTime(); + //let sunCalcResult = calculateDuskDawn(); + + { + let params = getParams(); + + params.address = 0xffffffff;//broadcast + params.byte1 = sunCalcResult["dusk_hours"]; + params.byte2 = sunCalcResult["dusk_minutes"]; + params.recipient = 2;//2 broadcast, + params.register = 6;//Time of dusk + params.rw = 1;//write + params.type = "node-regular-write"; + params.timestamp = time + 60000; + params.addMinutesToTimestamp = 60 * 3; //kazde 3 hodiny zisti novy dusk + params.info = "Broadcast-duskTime"; + + tasks.push(params); + } + + { + let params = getParams(); + + params.address = 0xffffffff;//broadcast + params.byte1 = sunCalcResult["dawn_hours"]; + params.byte2 = sunCalcResult["dawn_minutes"]; + params.recipient = 2; //2 broadcast + params.register = 7;//Time of dawn + params.rw = 1;//write + params.type = "node-regular-write"; + params.timestamp = time + 60001; + params.addMinutesToTimestamp = 60 * 3; //kazde 3 hodiny zisti novy dawn + params.info = "Broadcast-dawnTime"; + + tasks.push(params); + } + + { + let params = getParams(); + + params.address = 0xffffffff;//broadcast + params.byte1 = d.getHours(); + params.byte2 = d.getMinutes(); + params.recipient = 2; //2 broadcast + params.register = 87;//Actual time + params.rw = 1;//write + params.type = "node-regular-write"; + params.timestamp = time + 60002; + params.addMinutesToTimestamp = 5; + params.info = "run broadcast: Actual time"; + + tasks.push(params); + } + + } + + //process nodes & tasks - read node's data + if (processNodes) { + + let time = Date.now(); + + for (let k in nodesData) { + let address = parseInt(k); + let tbname = nodesData[k].tbname; + let register = 0; + + for (let i = 0; i < listOfCommands.length; i++) { + + register = listOfCommands[i]; + let addMinutesToTimestamp = priorities[register]; + + let params = getParams(); + + params.address = address; + params.recipient = 1; + params.register = register; + params.type = register == 1 ? "node-dimming-read" : "node-regular-read"; + params.tbname = tbname; + params.timestamp = time + 5000 + i * 500 + addMinutesToTimestamp * 1000; //to make slight time difference + params.addMinutesToTimestamp = addMinutesToTimestamp; + params.info = "Node regular read command"; + + tasks.push(params); + } + + } + } + + + //niektore ulohy sa vygeneruju iba 1x pri starte!!! + if (!init) return; + + + //Master node FW version - modifies SETTINGS.masterNodeIsResponding + { + let params = getParams(); + params.type = "cmd-master"; + params.register = 4; + params.address = 0; + params.timestamp = 0; + params.addMinutesToTimestamp = 5; + params.tbname = SETTINGS.rvoTbName; + params.info = "Master node FW verzia"; + //params.debug = true; + + tasks.push(params); + } + + //kazdu hodinu skontrolovat nastavenie profilov + { + let params = getParams(); + params.type = "process_profiles"; + params.timestamp = Date.now() + 60001; + params.addMinutesToTimestamp = 60;//60 = every hour + params.info = "detekcia nespracovaných profilov linie a nodov"; + //params.debug = true; + + tasks.push(params); + } + + monitor.info("tasks created:", tasks.length); + } + + + /** + * We process line profile, where "astro_clock": true + * example profile: + * + "dawn_lux_sensor": true, + "dusk_lux_sensor": true, + "dawn_lux_sensor_value": 5, + "dusk_lux_sensor_value": 5, + "dawn_astro_clock_offset": 0, + "dusk_astro_clock_offset": 10, + "dawn_lux_sensor_time_window": 30, + "dusk_lux_sensor_time_window": 30, + "dawn_astro_clock_time_window": 60, + "dusk_astro_clock_time_window": 60 + + * if dawn: if currentTimestamp is in timewindow "dawnTime + and - dawn_lux_sensor_time_window" and lux value >= lux_sensor_value, we switch off the line. + * if dusk: we do oposite + * + * dawn: usvit - lux je nad hranicou - vypnem + * dusk: sumrak - lux je pod hranicou - zapnem + */ + 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++) { + + let line = keys[i]; //line is turned off by default + let profilestr = relaysData[line].profile; + const contactor = relaysData[line].contactor; + + try { + + let profile = JSON.parse(profilestr); + if (Object.keys(profile).length === 0) throw ("turnOnOffLinesAccordingToLuxSensor - profile is not defined"); + + 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 (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"); + } + } + } + + //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 (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"); + } + } + } + + } + + } catch (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) { + //MASTER + if (node == 0) return; + + let nodeObj = nodesData[node]; + if (nodeObj == undefined) return; + + let nodeCurrentStatus = nodeObj.status; + const now = Date.now(); + + let data = null; + + if (nodeCurrentStatus === "OFFLINE") { + data = { status: newStatus }; + nodeDbStatusModify(node, data); + return; + } + else 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; + } + + } + + + 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 }; + } + }); + }); + } + + + function processDailyReport() { + + const now = Date.now(); + + for (const [key, value] of Object.entries(dailyReport)) { + + if (["name", "time", "dusk_and_dawn"].includes(key)) continue; + + let poleNumber = nodesData[key]["pole_number"]; + let line = dailyReport[key].line; + let nodeType = nodesData[key]["node_type"]; + let fullNodeName = key // key == nodeNumber + + if (poleNumber && nodeType) { + fullNodeName = SETTINGS.rvo_number + "/" + poleNumber + "_" + line + "L_" + key + "_" + nodeType; + } else { + fullNodeName = key; + } + + if (rvo_is_on) { + + if (value.initialTs) { + if (value.initialTs + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["night_no_data"], fullNodeName); + console.log('report nedostava ziadne data uz hodinu', fullNodeName); + value.initialTs = now; + } + } + if (value.dimmingIsZeroTime) { + if (value.dimmingIsZeroTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["night_dimming=0"], fullNodeName); + console.log("report node dimming je 0 ale ma svietit", fullNodeName); + value.dimmingIsZeroTime = now; + } + } + if (value.powerIsZeroTime) { + if (value.powerIsZeroTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["night_power=0"], fullNodeName); + console.log("report node power je 0 ale ma svietit", fullNodeName); + value.powerIsZeroTime = now; + } + } + + } else { + + let contactorStatus = relaysData[line].contactor; + if (contactorStatus === 1) { + + if (value.initialTs) { + if (value.initialTs + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["day_24/7_no_data"], fullNodeName); + console.log('node je na 24/7 ale nedostava ziadne data uz hodinu', fullNodeName); + value.initialTs = now; + } + } + if (value.dimmingIsOnButShouldBeOffTime) { + if (value.dimmingIsOnButShouldBeOffTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["day_24/7_dimming>0"], fullNodeName); + console.log("report dimming je > 0 ale nema svietit", fullNodeName); + value.dimmingIsOnButShouldBeOffTime = now; + } + } + if (value.powerIsOnButShouldBeOffTime) { + if (value.powerIsOnButShouldBeOffTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["day_24/7_power>0"], fullNodeName); + console.log("report power je > 0 ale nema svietit", fullNodeName); + value.powerIsOnButShouldBeOffTime = now; + } + } + + } + + } + + } + + let report = {}; + report["name"] = SETTINGS.rvo_name; + report["time"] = new Date(); + report["report"] = reportToSend; + + writeToFile(F.path.root("report_data.log"), report, true); + instance.send(SEND_TO.dailyReport, report); + } + + + function dailyReportHandler() { + + if (!SETTINGS.daily_report) return; + + // after dawn we empty reportToSend and start to get data for a new day + const date = new Date(); + const hour = date.getHours(); + const minute = date.getMinutes(); + + console.log("now: ", hour, minute, "suncalc: ", sunCalcResult.dawn_hours, sunCalcResult.dawn_minutes); + + if (hour === sunCalcResult.dawn_hours) { + + //NOTE: ak je este pred usvitom, spracujeme report a posleme na cloud, ak uz je po usvite, resetujeme report plnime data noveho dna + if (minute >= sunCalcResult.dawn_minutes - 2) { + emptyReportToSend(); + emptyDailyReport(); + console.log("Podmienka 1 v dailyReport handler"); + } else { + processDailyReport(); + emptyReportToSend(); + emptyDailyReport(); + console.log("Podmienka 2 v dailyReport handler"); + } + + initialReportStatus = true; + + // ak sa funkcia spusti o hodinu alebo 2 neskor, ako je usvit (moze sa to stat, kedze kazde zapnutie/vypnutie linii odznova spusti casovac. + } else if (hour === sunCalcResult.dawn_hours + 1 || hour === sunCalcResult.dawn_hours + 2) { + if (!initialReportStatus) { + emptyReportToSend(); + emptyDailyReport(); + initialReportStatus = true; + console.log("Podmienka 3 v dailyReport handler"); + } else { + processDailyReport(); + initialReportStatus = true; + console.log("Podmienka 4 v dailyReport handler"); + } + } else { + processDailyReport(); + initialReportStatus = false; + console.log("Podmienka 5 v dailyReport handler"); + } + + console.log("initialReportStatus: ", initialReportStatus); + + } + + function emptyReportToSend() { + emptyJsObject(reportToSend); + reportToSend["contactor"] = { off: [], on: [] }; + reportToSend["night_no_data"] = []; + reportToSend["night_dimming=0"] = []; + reportToSend["night_power=0"] = []; + reportToSend["day_24/7_no_data"] = []; + reportToSend["day_24/7_dimming>0"] = []; + reportToSend["day_24/7_power>0"] = []; + console.log(`resetuje sa reportToSend`); + } + + + //NOTE: ked je initialTs stale rovnaky a zistime ze linie su vypnute (relaysData.line.contactor) - zistim, ci je node na tej linii. Vieme, ze ak je linia vypnuta je to v poriadku lebo nie je na 24/7 linii + //ak je na 24/7 linii, reportujeme, ze neprijima data + function emptyDailyReport() { + const ts = Date.now(); + emptyJsObject(dailyReport); + + //NOTE: do dailyReport dame vsetky nody a pravidelne kontrolujeme ci maju data + //ked nastane sumrak/usvit a svetla maju zacat/prestat svietit, dailyReport spravime nanovo: + for (const [key, value] of Object.entries(nodesData)) { + dailyReport[value.node] = { line: value.line, initialTs: ts }; + } + + console.log("dailyReport: ", dailyReport); + } + + + async function runTasks() { + + clearInterval(interval); + + let currentTimestamp = Date.now(); + + //sort tasks based on timestamp + 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) { + instance.send(SEND_TO.debug, "no tasks created"); + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + if (!rsPort.isOpen) { + instance.send(SEND_TO.debug, "!rsPort.isOpen"); + //await rsPort.open(); + //console.log("Cmd-mngr: !rsPort.isOpen"); + } + + let currentTask = tasks[0]; + + if (currentTask.debug) { + //logger.debug("--->task to process", currentTask); + } + + if (currentTask.timestamp <= currentTimestamp) { + let params = { ...tasks[0] }; + + //allow terminal commands + if (SETTINGS.maintenance_mode && params.type !== "cmd-terminal") { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + let type = params.type; + let tbname = params.tbname; + let node = params.address; + let register = params.register; + let line = null; + let itIsNodeCommand; + + if (nodesData[node] !== undefined) { + line = nodesData[node].line; + itIsNodeCommand = true; + } + + if (params.line !== undefined) line = params.line; + + if (params.addMinutesToTimestamp > 0 || params.timePointName) { + tasks[0].timestamp = currentTimestamp + tasks[0].addMinutesToTimestamp * 60000; + } else { + tasks.shift(); + } + + //kontrola nespracovanych profilov nodov + //TODO: co ked niektore nody neprijimaju profily? kazdu hodinu zahltuju "tasks" array + if (type == "process_profiles") { + //na vsetky zapnutych liniach sa spracuju nespracovane profily nodov + loadRelaysData(); + interval = setInterval(runTasks, SHORT_INTERVAL); + return; + } + + //relay + if (type == "relay") { + + const timePointName = params.timePointName; + const value = params.value; + + let date = new Date(); + date.setDate(date.getDate() + 1);//next day + + let sunCalcResult; + if (timePointName) sunCalcResult = calculateDuskDawn(date, params.line); + + + if (timePointName == "dawn") { + tasks[0].timestamp = sunCalcResult.dawn_time; + } + else if (timePointName == "dusk") { + tasks[0].timestamp = sunCalcResult.dusk_time; + } + else if (timePointName == "luxOn") { + tasks[0].timestamp = sunCalcResult.dusk_time + params.dusk_lux_sensor_time_window * 60000; + } + else if (timePointName == "luxOff") { + tasks[0].timestamp = sunCalcResult.dawn_time + params.dawn_lux_sensor_time_window * 60000; + } + else if (timePointName == "profileTimepoint") { + tasks[0].timestamp = currentTimestamp + tasks[0].addMinutesToTimestamp * 60000; + } + + let info = "aplikovany bod profilu"; + let onOrOff = ""; + value == 1 ? onOrOff = "on" : onOrOff = "off"; + + turnLine(onOrOff, params.line, info); + + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + if (!SETTINGS.masterNodeIsResponding) { + //ak neodpoveda, nebudeme vykonavat ziadne commands, okrem cmd-terminal cmd-master + errorHandler.sendMessageToService("Master node is not responding"); + + let stop = true; + + if (type === "cmd-terminal" || type === "cmd-master") stop = false; + if (stop) { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + } + + let contactorStatus = 1; + if (relaysData[line] != undefined) contactorStatus = relaysData[line].contactor; + + if (line === 0 || contactorStatus === 0 || FLOW.deviceStatus.state_of_breaker[line] === "Off") { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + // TODO: -> status offline for rvo if rotary_switch_state is OFF, this is source of errors + // check if rotary_switch_state == "Off" + // state_of_braker: disconnected = true? + + if (!rsPort.isOpen) { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + //RE-CALCULATE VALUES + //set actual time for broadcast + if (register == 87 && params.recipient === 2) { + var d = new Date(); + params.byte1 = d.getHours();//h + params.byte2 = d.getMinutes();//m + } + + //SET DUSK/DAWN FOR BROADCAST + //Time of dusk + if (register == 6 && params.recipient === 2) { + + if (type != "cmd-terminal") { + params.byte1 = sunCalcResult["dusk_hours"];//h + params.byte2 = sunCalcResult["dusk_minutes"];//m + } + } + + //Time of dawn + if (register == 7 && params.recipient === 2) { + if (type != "cmd-terminal") { + params.byte1 = sunCalcResult["dawn_hours"];//h + params.byte2 = sunCalcResult["dawn_minutes"];//m + } + } + //----------------------- + + instance.send(SEND_TO.debug, "address: " + node + " register:" + register + "type: " + type); + + var startTime, endTime; + startTime = new Date(); + + let saveToTb = true; + if (!tbname) saveToTb = false; + + let resp = com_generic(node, params.recipient, params.rw, register, params.name, params.byte1, params.byte2, params.byte3, params.byte4); + let readBytes = 11; + let timeout = 4000; + + + // await keyword is important, otherwise incorrect data is returned! + await writeData(rsPort, resp, readBytes, timeout).then(function(data) { + + //sometimes happens, that status of node changes to OK, NOK even if line was turned off and should be status OFFLINE. To prevent this, we return if line contactor is 0: + if (itIsNodeCommand && line && relaysData[line].contactor !== 1) return; + + 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); + + //ak sa odpoved zacina 0 - je to v poriadku, inak je NOK + let message = result.message; // OK, NOK + let message_type = result.type; + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + console.log("detected response:", result); + logger.debug("Cmd-mngr: writeData done " + message_type + " duration: " + timeDiff + " type: " + params.debug, params, result); + } + } + + let values = {}; + + //CMD FINISHED + if (message == "OK") { + + updateNodeStatus(node, true); + + //write + if (type == "set_node_profile") { + let result = cmdCounterResolve(node); + if (result == 0) { + dbNodes.modify({ processed: true }).where("node", node).make(function(builder) { + builder.callback(function(err, response) { + + sendNotification("Cmd-mngr: process cmd", SETTINGS.rvoTbName, "dimming_profile_was_successfully_received_by_node", { node: node }, "", SEND_TO.tb, instance); + + logger.debug("--> profil úspešne odoslaný na node č. " + node); + nodesData[node].processed = true; + nodeProfileSendFail.delete(node); + }); + }); + } + } + + //parse read response + if (params.rw == 0) { + values = processResponse(register, dataBytes); //read + } + + if (itIsNodeCommand) { + values.comm_status = "OK"; + values.status = "OK"; + nodesData[node].readout = { ...nodesData[node].readout, ...values }; + + + if (SETTINGS.daily_report) { + //TODO: co ak nedostavame odpovede z nodu ? Musime vyreportovat!! + //v dailyReport teda musi byt kompletny zoznam nodov a neustale kontrolovat, ci maju data, ak nie report node - neodpoveda + if (register === 1) { + + let now = Date.now(); + + if (rvo_is_on === true) { + + if ("dimmingIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].dimmingIsOnButShouldBeOffTime; + + if (values.dimming > 0) { + if ("dimmingIsZeroTime" in dailyReport[node]) delete dailyReport[node].dimmingIsZeroTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if (!("dimmingIsZeroTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], dimmingIsZeroTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } else { + + if ("dimmingIsZeroTime" in dailyReport[node]) delete dailyReport[node].dimmingIsZeroTime; + + if (values.dimming > 0) { + if (!("dimmingIsOnButShouldBeOffTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], dimmingIsOnButShouldBeOffTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if ("dimmingIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].dimmingIsOnButShouldBeOffTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } + } + + if (register === 76) { + + let now = Date.now(); + + if (rvo_is_on === true) { + + if ("powerIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].powerIsOnButShouldBeOffTime; + + if (values.power > 1) { + if ("powerIsZeroTime" in dailyReport[node]) delete dailyReport[node].powerIsZeroTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if (!("powerIsZeroTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], powerIsZeroTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } else { + + if ("powerIsZeroTime" in dailyReport[node]) delete dailyReport[node].powerIsZeroTime; + + if (values.power > 1) { + if (!("powerIsOnButShouldBeOffTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], powerIsOnButShouldBeOffTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if ("powerIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].powerIsOnButShouldBeOffTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } + } + } + + } + + //master node + if (node == 0) { + sendNotification("Cmd-mngr: 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; + } + + if (params.debug) { + //logger.debug("saveToTb", saveToTb, tbname, values); + } + + if (saveToTb && type != "node-regular-read") { + sendTelemetry(values, tbname); + } + else { + if (type == "cmd-terminal") { + terminalCommandResponse(params, "SUCCESS", data); + } + } + + } + else { + terminalCommandResponse(params, "ERROR", data); + handleNokResponseOnRsPort("handleNOK else block", params, itIsNodeCommand, saveToTb); + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + //logger.debug("writeData err: ", error, result, params); + logger.debug("writeData err: ", tbname, node, register, values); + } + } + + //logger.debug(error, result, params); + } + }).catch(function(reason) { + + //console.log("writeData catch exception", reason); + instance.send(SEND_TO.debug, reason); + + terminalCommandResponse(params, "FAILURE", null, reason); + handleNokResponseOnRsPort("handleNOK catch block", params, itIsNodeCommand, saveToTb); + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + logger.debug("-->WRITE FAILED: " + reason, params.debug, params); + } + } + + }); + + } + 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); + } + + + // if node does not respond to request, we repeat request 3 times: + function repeatCommand(params) { + params.repeatCounter++; + if (params.repeatCounter < 4) { + params.timestamp = 0; + params.addMinutesToTimestamp = 0; + tasks.push(params); + } + } + + function handleNokResponseOnRsPort(message, params, itIsNodeCommand, saveToTb) { + + let node = params.address; + let register = params.register; + let type = params.type; + let tbName = params.tbname; + if (!tbName) return; + + let values = {}; + + let updateStatus = updateNodeStatus(node, false); + + if (itIsNodeCommand) { + values.comm_status = "NOK"; + nodesData[node].readout.comm_status = "NOK"; + repeatCommand(params); + } + + if (updateStatus) { + values.status = "NOK"; + nodesData[node].readout.status = "NOK"; + } + + if (type === "node-regular-read") return; + + //master node + if (node == 0) { + sendNotification("Cmd-mngr: 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; + + if (register == 4) values["master_node_version"] = "NOK"; + } + + if (type == "set_node_profile") { + delete cmdCounter[node]; + logger.debug("profil nebol úspešne odoslaný na node č. ", params); + + if (!nodeProfileSendFail.has(node)) { + sendNotification("Cmd-mngr: process cmd", tbName, "configuration_of_dimming_profile_to_node_failed", { node: node }, "", SEND_TO.tb, instance); + nodeProfileSendFail.add(node); + } + } + + // console.log("------",node, register, type, itIsNodeCommand, updateStatus, saveToTb, values); + if (saveToTb) { + sendTelemetry(values, tbName); + } + + } + + + function sendNodesData() { + Object.keys(nodesData).forEach(node => { + if (nodesData[node]["status"] !== "OFFLINE") { + sendTelemetry(nodesData[node].readout, nodesData[node].tbname); + nodesData[node].readout = {}; + } + }) + } + + + /** + * 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; + } + + 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); + + //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 === "OFFLINE") { + nodeObj.node_status_before_offline === true ? number_of_ok_luminaires++ : number_of_nok_luminaires++; + } + else if (nodeObj.status == true) 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 - ts % 60000 //round to full minute + }; + + sendTelemetry(values, SETTINGS.rvoTbName, ts); + } + + + function setSunCalcResult() { + //if next day, we get new dusk and dawn. To make sure, in local timezone 2:00 means 00:00 in utc (it means next day) + if (new Date().getHours() === 2) { + sunCalcResult = calculateDuskDawn(); + console.log("Novy suncalc: ", sunCalcResult); + } + } + + + function setRvoPeriod() { + + if (!SETTINGS.daily_report) return; + + const ts = Date.now(); + + previous_rvo_is_on_value = rvo_is_on; + + if (ts < sunCalcResult.dawn_time - 1_800_000) { // nodes should be on (00:00 -> 06:00 ( - pol hodina, lebo rvo vypina skor) + rvo_is_on = true; + } else if (sunCalcResult.dawn_time - 1_800_000 < ts && ts < sunCalcResult.dusk_time + 1_800_000) { // nodes should be off 06:00 -> 21:00 + rvo_is_on = false; + } else if (sunCalcResult.dusk_time + 1_800_000 < ts) { // nodes should be on 21:00 -> 00:00 + rvo_is_on = true; + } + + if (previous_rvo_is_on_value !== rvo_is_on) { + emptyDailyReport(); + console.log("rvo_is: ", rvo_is_on, previous_rvo_is_on_value); + } + } + + + function handleRsPort() { + + if (rsPort) { + rsPort.removeAllListeners(); + rsPort = null; + } + + //! 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-mngr: rsPort opened success"); + + 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); + + }).catch(function(reason) { + instance.send(SEND_TO.debug, "Cmd-mngr: RPC runSyncExec - promise rejected:" + reason); + }); + }); + + rsPort.on('error', function(err) { + errorHandler.sendMessageToService([exports.title, "unable to open port", SETTINGS.serial_port, err.message], 0); + monitor.info("Cmd-mngr: Error on rsPort", err.message); + }); + + rsPort.on("close", () => { + monitor.info("Cmd-mngr: rsPort closed, reconnecting..."); + setTimeout(handleRsPort, 1000); + }); + + rsPort.open(); + } + + + instance.on("close", () => { + clearInterval(interval); + clearInterval(customTasksInterval); + clearInterval(setCorrectTime); + clearInterval(sendNodeReadout); + clearInterval(accelerometerInterval); + rsPort.close(); + }); + + instance.on("0", _ => { + main(); + }) + + + instance.on("2", _ => { + console.log("dailyReport, reportToSend, rvo_is_on", dailyReport, reportToSend, rvo_is_on, previous_rvo_is_on_value); + }) + + instance.on("1", 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(); + return; + } + else if (flowdata.data == "close") { + rsPort.close(); + return; + } + else if (flowdata.data == "clean") { + tasks = []; + return; + } + else if (flowdata.data == "buildtasks") { + //build & run + return; + } + else if (flowdata.data == "run") { + //durations = []; + + if (tasks.length == 0) { + + buildTasks(); + + if (rsPort.isOpen) { + interval = setInterval(runTasks, 100); + } + else { + instance.send(SEND_TO.debug, "port is not opened!!!"); + } + } + } + else { + //terminal data - object + //logger.debug("flowdata", flowdata.data); + + if (typeof flowdata.data === 'object') { + //logger.debug("dido", flowdata.data); + if (flowdata.data.hasOwnProperty("sender")) { + //data from dido_controller + if (flowdata.data.sender == "dido_controller") { + + if (flowdata.data.hasOwnProperty("cmd")) { + let cmd = flowdata.data.cmd; + + if (cmd == "buildTasks") { + clearInterval(interval); + + logger.debug("-->Cmd-mngr: BUILD TASKS"); + buildTasks(); + + //logger.debug("tasks:"); + //logger.debug(tasks); + + logger.debug("-->Cmd-mngr: RUN TASKS"); + interval = setInterval(runTasks, 5000); + } + else if (cmd == "reload_relays") { + loadRelaysData(flowdata.data.line); + + if (flowdata.data.dataChanged) { + if (!flowdata.data.value) { + reportOfflineNodeStatus(flowdata.data.line); + } + else { + reportOnlineNodeStatus(flowdata.data.line); + } + } + + } + else if (cmd == "rotary_switch_state") { + let value = flowdata.data.value; + + //state was changed + if (rotary_switch_state != value) { + if (value == "Off") { + //vyreportovat vsetky svietdla + reportOfflineNodeStatus(); + } + + rotary_switch_state = value; + } + } + 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) { + + // we send lux_sensor value to all nodes: + let params = getParams(PRIORITY_TYPES.node_broadcast); + + params.recipient = 2;//2 broadcast, address = 0 + params.address = 0xffffffff;//Broadcast + + let ba = longToByteArray(lux_sensor); + + params.byte3 = ba[1];//msb + params.byte4 = ba[0]; + params.timestamp = PRIORITY_TYPES.node_broadcast; + params.info = "run broadcast: Actual Lux level from cabinet"; + params.register = 95;//Actual Lux level from cabinet + params.rw = 1;//write + + tasks.push(params); + + //process profiles + turnOnOffLinesAccordingToLuxSensor(lux_sensor); + } + } + else if (cmd == "state_of_breaker") { + //istic linie + + breakerCounter--; + + let value = flowdata.data.value; + let line = parseInt(flowdata.data.line); + + let dataChanged = false; + if (state_of_breaker[line] != value) dataChanged = true; + + state_of_breaker[line] = value; + + let status = "OK"; + if (value == "Off") status = "NOK"; + + if (dataChanged) { + + if (relaysData.hasOwnProperty(line)) { + let tbname = relaysData[line].tbname; + + if (value == "Off") { + sendNotification("Cmd-mngr: onData", tbname, "circuit_breaker_was_turned_off_line", { line: line }, "", SEND_TO.tb, instance, "circuit_breaker"); + if (breakerCounter < 0) reportToSend["contactor"]["off"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + else { + sendNotification("Cmd-mngr: onData", tbname, "circuit_breaker_was_turned_on_line", { line: line }, "", SEND_TO.tb, instance, "circuit_breaker"); + if (breakerCounter < 0) reportToSend["contactor"]["on"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + + //report status liniu + sendTelemetry({ status: status }, tbname) + + //current value + if (value == "Off") reportOfflineNodeStatus(line); //vyreportovat vsetky svietidla na linii + } + + } + } + else { + logger.debug("undefined cmd", cmd); + } + } + } + + return; + } + + //data from worksys + if (flowdata.data.hasOwnProperty("topic")) { + + let data = getNested(flowdata.data, "content", "data"); + + //if we get temperature in senica from senica-prod01 + let temperature = getNested(flowdata.data, "content", "senica_temperature"); + + if (temperature !== undefined) { + temperatureInSenica = temperature; + return; + } + + if (data === undefined) { + console.log("Invalid rpc command came from platform"); + return; + } + + let command = data.params.command; + let method = data.method; + let profile = data.params.payload; + if (profile == undefined) profile = ""; + let entity = data.params.entities[0]; + let entity_type = entity.entity_type; + let tbname = entity.tb_name; + + instance.send(SEND_TO.debug, flowdata.data); + 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") { + + //let command = data.params.command; + let value = data.params.payload.value; + + if (command == "dimming") { + + let nodeWasFound = false; + let keys = Object.keys(nodesData); + + //logger.debug("-----", keys); + + 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); + + value = parseInt(value); + if (value > 0) value = value + 128; + + params.type = "node-onetime-write"; + params.tbname = tbname; + params.address = node; + params.register = 1; + params.recipient = 1; + params.byte4 = value; + params.rw = 1; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'set dimming from platform'; + //params.debug = true; + + //debug(params); + logger.debug("dimming", params); + + tasks.push(params); + + 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); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 1; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read dimming (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + //pridame aj vyreportovanie - vykon + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 76; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read Input Power (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + //pridame aj vyreportovanie - prud svietidla + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 75; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read Input Current (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + //pridame aj vyreportovanie - power faktor - ucinnik + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 77; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read power factor (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + }, 4000); + + nodeWasFound = true; + break; + } + } + + if (!nodeWasFound) { + logger.debug("set dimming from platform", "unable to find tbname", tbname); + } + } + else { + instance.send(SEND_TO.debug, "undefined command " + command); + logger.debug("undefined command", command); + } + + return; + } + 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++) { + let node = keys[i]; + if (tbname == nodesData[node].tbname) { + + 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"); + + //profil úspešne prijatý pre node č. xx + sendNotification("Cmd-mngr", tbname, "dimming_profile_was_processed_for_node", { node: node }, profile, SEND_TO.tb, instance); + + nodesData[node].processed = false; + nodesData[node].profile = profile; + + processNodeProfile(node); + }); + }); + } + } + } + else { + + instance.send(SEND_TO.debug, "unknown method " + method); + logger.debug("unknown method", method); + + return; + } + } + + //nastav profil linie z platformy + 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") { + + 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++) { + let line = keys[i]; + if (tbname == relaysData[line].tbname) { + //zmazeme tasky + 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) { + + //update profile + logger.debug("worksys - update relay profile done:", profile); + instance.send(SEND_TO.debug, "worksys - update relay profile done"); + + relaysData[line].profile = profile; + + loadRelaysData(line) + logger.debug("loadRelaysData DONE for line", line); + + buildTasks({ processLineProfiles: true, line: line }); + + sendNotification("Cmd-mngr: set profile from worksys", tbname, "switching_profile_was_processed_for_line", { line: line }, profile, SEND_TO.tb, instance); + }); + }); + break; + } + } + } + else if (method == "set_command") { + let value = data.params.payload.value; + + 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; + + 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"); + if (line != 0) reportToSend["contactor"]["off"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + else { + turnLine("on", line, "command received from platform"); + if (line != 0) reportToSend["contactor"]["on"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + } + } + else { + instance.send(SEND_TO.debug, "undefined method " + method); + logger.debug("undefined method", method); + } + + return; + } + else { + instance.send(SEND_TO.debug, "UNKNOW entity_type " + entity_type); + logger.debug("UNKNOW entity_type", entity_type); + } + return; + } + + //terminal + if (!rsPort.isOpen) await rsPort.open(); + + let params = flowdata.data.body; + if (params == undefined) { + //logger.debug("Cmd-mngr: flowdata.data.body is undefined"); + return; + } + + params.priority = PRIORITY_TYPES.terminal; + params.type = "cmd-terminal"; + params.tbname = ""; + params.timestamp = PRIORITY_TYPES.terminal; + params.addMinutesToTimestamp = 0;// do not repeat task!!! + params.debug = true; + + let timestamp = Date.now(); + params.refFlowdataKey = timestamp; + //params.refFlowdata = flowdata; + //refFlowdata = flowdata; + + //console.log("flowdata", flowdata); + + cleanUpRefFlowdataObj(); + + refFlowdataObj[timestamp] = flowdata; + + //fix + //params.address = params.adress; + logger.debug("received from terminal", params); + logger.debug("date/time:", new Date()); + logger.debug("tasks length:", tasks.length); + + //tasks = []; + + //add to tasks + tasks.push(params); + + } + } + }) + + + //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) + } + + + /** + * 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; + + RESTBuilder.make(function(builder) { + + if (!builder) return; + + builder.method('GET'); + builder.url('http://192.168.252.2:8004/gettime?projects_id=1'); + + builder.callback(function(err, response, output) { + + 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); + } + + }); + } + + } 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); + + } else { + //console.log("Read-only", stdout); + + 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]: [ + { + "ts": date, + "values": values + } + ] + } + + tbHandler.sendToTb(dataToTb, instance); + } + + + function calculateDuskDawn(date, line, duskOffset = 0, dawnOffset = 0) { + + if (date === undefined) date = new Date(); + + 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); + } + + //if(profile.dawn_lux_sensor == false) + { + if (profile.hasOwnProperty("dawn_astro_clock_offset")) dawn_astro_clock_offset = parseInt(profile.dawn_astro_clock_offset); + } + + } + + } catch (error) { + if (profilestr != "") { + logger.debug(profilestr); + logger.debug(error); + } + } + + 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; + } + + //Dimming, CCT + else if (register == 1) { + let brightness = 0; + let dimming = byte0; + if (dimming > 128) { + //dimming = -128; + brightness = dimming - 128; + } + + //cct + //Ak Byte3 == 1: CCT = (Byte2*256)+Byte1 + let cct; + if (byte3 == 1) cct = byte2 * 256 + byte1; + else cct = bytesToInt(bytes.slice(0, 3)); + + //cct podla auditu + + values["dimming"] = brightness; + return values; + } + + // + else if (register == 4) { + values["master_node_version"] = bytes[1] + "." + bytes[2]; + //logger.debug("FW Version", register, bytes); + } + + //Napätie + else if (register == 74) { + let voltage = (bytesToInt(bytes) * 0.1).toFixed(1); + values["voltage"] = Number(voltage); + } + + //Prúd + else if (register == 75) { + let current = bytesToInt(bytes); + values["current"] = current; + } + + //výkon + else if (register == 76) { + let power = (bytesToInt(bytes) * 0.1).toFixed(2); + values["power"] = Number(power); + } + + //účinník + else if (register == 77) { + let power_factor = Math.cos(bytesToInt(bytes) * 0.1 * (Math.PI / 180)).toFixed(2); + values["power_factor"] = Number(power_factor); + } + + //frekvencia + else if (register == 78) { + let frequency = (bytesToInt(bytes) * 0.1).toFixed(2); + values["frequency"] = Number(frequency); + } + + //energia + else if (register == 79) { + let energy = bytesToInt(bytes); + values["energy"] = energy / 1000; //energia v kWh -> delit 1000 + } + + //doba života + else if (register == 80) { + let lifetime = (bytesToInt(bytes) / 60).toFixed(2); + values["lifetime"] = Number(lifetime); + } + + //nastavenie profilu + else if (register == 8) { + let time_schedule_settings = bytesToInt(bytes); + values["time_schedule_settings"] = time_schedule_settings; + } + + //naklon - nateraz sa z nodu nevycitava! kvoli problemom s accelerometrom a vracanymi hodnotami, posielame temp a x y z vo funkcii accelerometerData() + else if (register == 84) { + values["temperature"] = byte3 >= 128 ? (byte3 - 128) * (-1) : byte3; + values["inclination_x"] = byte2 >= 128 ? (byte2 - 128) * (-1) : byte2; + values["inclination_y"] = byte1 >= 128 ? (byte1 - 128) * (-1) : byte1; + values["inclination_z"] = byte0 >= 128 ? (byte0 - 128) * (-1) : byte0; + } + + //FW verzia nodu + else if (register == 89) { + //formát: "Byte3: Byte2.Byte1 (Byte0)" + values["fw_version"] = byte3 + ":" + byte2 + "." + byte1 + "(" + byte0 + ")"; + } + + else if (register == 87 || register == 6 || register == 7) { + var d = new Date(); + d.setHours(byte3, byte2, 0, 0); + let timestamp = d.getTime(); + + //aktuálny čas + if (register == 87) values["actual_time"] = timestamp; + //čas súmraku + else if (register == 6) values["dusk_time"] = timestamp; + //čas úsvitu + else if (register == 7) values["dawn_time"] = timestamp; + } + + 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; + + } + + + function getObjectByTbValue(object, tbname) { + return object[Object.keys(object).find(key => object[key].tbname === tbname)]; + } + + + function isObject(item) { + return (typeof item === "object" && !Array.isArray(item) && item !== null); + } + + + // we fake data, that should be received from accelerometer, as they are a bit unreliable. (temperature, x,y,z) + function accelerometerData() { + + if (temperatureInSenica === null) return; + + //clone nodesData and relaysData objects + let nodesData_clone = JSON.parse(JSON.stringify(nodesData)); + let relaysData_clone = JSON.parse(JSON.stringify(relaysData)); + + for (const key in relaysData_clone) { + + const lineData = relaysData_clone[key]; + const lineNumber = lineData.line; + const contactor = lineData.contactor; + + if (lineNumber === 0) continue; + + if (contactor === 1) { + + let date = Date.now(); + + Object.keys(nodesData_clone).forEach((node, index) => { + + setTimeout(function() { + + if (nodesData_clone[node].line === lineNumber) { + + // NOTE: if status of luminaire is NOK or OFFLINE, we do not send data; + let status = nodesData_clone[node].status; + if (status === "OFFLINE" || !status) return; + + let x = null; + if (naklony.hasOwnProperty(node)) x = naklony[node].naklon; + if (x === null) x = 0; + + sendTelemetry({ temperature: Math.round(temperatureInSenica + 10 + Math.floor(Math.random() * 3)), inclination_x: x, inclination_y: 0, inclination_z: 0 }, nodesData_clone[node].tbname, date); + } + + }, (index + 1) * 500); + }) + + } + } + } + + +} // end of instance.export + diff --git a/RVO23/flow/code.js b/RVO23/flow/code.js new file mode 100755 index 0000000..63b31bf --- /dev/null +++ b/RVO23/flow/code.js @@ -0,0 +1,90 @@ +exports.id = 'code'; +exports.title = 'Code'; +exports.group = 'Common'; +exports.color = '#656D78'; +exports.input = true; +exports.output = 1; +exports.author = 'Peter Širka'; +exports.icon = 'code'; +exports.version = '1.2.0'; +exports.options = { outputs: 1, code: 'send(0, value);', keepmessage: true }; + +exports.html = `
+
+
+
@(Number of outputs)
+
@(Minimum is 1)
+
+
+
@(Code)
+
@(Keep message instance)
+
+`; + +exports.readme = `# Code + +This component executes custom JavaScript code as it is and it doesn't contain any secure scope. + +\`\`\`javascript +// value {Object} contains received data +// send(outputIndex, newValue) sends a new value +// error(value) sends an error +// instance {Object} a current component instance +// flowdata {Object} a current flowdata +// repository {Object} a current repository of flowdata +// Example: + +// send() can be execute multiple times +send(0, value); +\`\`\``; + +exports.install = function(instance) { + + var fn; + + instance.on('data', function(response) { + if (fn) { + try { + fn(response.data, instance, response, instance.options, response.repository, require); + } catch (e) { + response.data = e; + instance.throw(response); + } + } + }); + + instance.reconfigure = function() { + try { + if (instance.options.code) { + instance.status(''); + var code = 'var send = function(index, value) { if (options.keepmessage) { flowdata.data = value; instance.send2(index, flowdata); } else instance.send2(index, value);}; var error = function(err) { instance.throw(err); }; ' + instance.options.code; + fn = new Function('value', 'instance', 'flowdata', 'options', 'repository', 'require', code); + } else { + instance.status('Not configured', 'red'); + fn = null; + } + } catch (e) { + fn = null; + instance.error('Code: ' + e.message); + } + }; + + instance.on('options', instance.reconfigure); + instance.reconfigure(); +}; \ No newline at end of file diff --git a/RVO23/flow/comment.js b/RVO23/flow/comment.js new file mode 100755 index 0000000..1e0cd13 --- /dev/null +++ b/RVO23/flow/comment.js @@ -0,0 +1,11 @@ +exports.id = 'comment'; +exports.title = 'Comment'; +exports.group = 'Common'; +exports.color = '#704cff'; +exports.author = 'Martin Smola'; +exports.icon = 'comment'; +exports.traffic = false; +exports.version = '1.0.0'; +exports.readme = '# Comment'; + +exports.install = function() {}; diff --git a/RVO23/flow/count.js b/RVO23/flow/count.js new file mode 100755 index 0000000..fa92ee9 --- /dev/null +++ b/RVO23/flow/count.js @@ -0,0 +1,60 @@ +exports.id = 'count'; +exports.title = 'Count'; +exports.version = '1.0.1'; +exports.author = 'John Graves'; +exports.color = '#656D78'; +exports.icon = 'plus-square'; +exports.input = 2; +exports.output = 1; +exports.options = { increment: 1, initialvalue: 1 }; +exports.readme = `# Counter + +Counter Number of times called.`; + +exports.html = `
+
@(Initial Value)
+
@(Increment)
+

Example Video

+
`; + +exports.readme = `# Count + +This component counts the number of messages received. + +__Response:__ + +Integer value based on the initial value and increment settings. + +__Arguments:__ +- Initial Value: What number should be output on the receipt of the first message. +- Increment: What should the increment be for each following message received.`; + +exports.install = function(instance) { + + var count = 0; + var initialCall = true; + + instance.on('data', function(flowdata) { + var index = flowdata.index; + if (index) { + instance.debug('Reset Count.'); + count = instance.options.initialvalue; + initialCall = true; + } else { + // If this is the first time, set the value to 'initial value' + if(initialCall) { + initialCall = false; + count = instance.options.initialvalue; + } else + count = count+instance.options.increment; + instance.status('Count:' + count); + instance.send2(count); + } + }); + + instance.on('options', function() { + count = instance.options.initialvalue; + initialCall = true; + }); + +}; diff --git a/RVO23/flow/db_connector.js b/RVO23/flow/db_connector.js new file mode 100755 index 0000000..65ee94b --- /dev/null +++ b/RVO23/flow/db_connector.js @@ -0,0 +1,286 @@ +exports.id = 'db_connector'; +exports.title = 'DbConnector'; +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.html = `
+
+
+
DbConnector
+
+
+
`; + +exports.readme = `# read/write data to tables`; + +const instanceSendTo = { + debug: 0, + http_response: 1, +} + +const { promisifyBuilder, makeMapFromDbResult } = require('./helper/db_helper.js'); + +function extractWhereParams(params) +{ + let name = params[0]; + let operator = '='; + let value = params[1]; + + if(params.length == 3) + { + operator = params[1]; + value = params[2]; + } + + return {name: name, operator: operator, value: value}; +} + +exports.install = function(instance) { + + let refFlowdata = null;//holds reference to httprequest flowdata + + instance.on("close", () => { + + }) + + + instance.on("data", async function(flowdata) { + + let params = flowdata.data.body; + console.log("DbConnector", params); + + refFlowdata = flowdata; + + if(refFlowdata != undefined) + { + //make http response + let responseObj = {}; + responseObj["type"] = "SUCESS"; + + try{ + + let table = params.table; + let action = params.action; + + + if(params.data != undefined) + { + let className = params.data.className; + + if(className == "SqlQueryBuilder") + { + let type = params.data.type; + + console.log("SqlQueryBuilder---->", params.data); + + if(type == "SELECT") + { + let table = params.data.queryData.tables[0].table; + + const db = TABLE(table); + var builder = db.find(); + + let result = await promisifyBuilder(builder); + + let response = {}; + response["result"] = result; + response["success"] = true; + + responseObj["data"] = response; + + //console.log(responseObj); + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + } + + return; + } + } + + + console.log("db_connector---->", table, action); + + //actions: read, replace, insert, delete, update... + + if(action == "read") + { + const db = TABLE(params.table); + + //where builder.where('age', '<', 15); + //builder.where('id', 3403); + + var builder = db.find(); + + //https://docs.totaljs.com/latest/en.html#api~DatabaseBuilder~builder.where + if(params.hasOwnProperty("where")) + { + //optionalCan contain "=", "<=", "<", ">=", ">". + //Default value: '=' + + //1.["production_line", 1] + //2. ["or", ["production_line", 1], ["production_line", 2], "end"] + + if (Array.isArray(params.where)) { + + let multipleConditions = false; + + if(params.where[0] == "or") multipleConditions = true; + if (Array.isArray(params.where[0])) multipleConditions = true; + + if(multipleConditions) + { + + for(var i = 0; i < params.where.length; i++) + { + const item = params.where[i]; + + if(item === "or") builder.or(); + + if (Array.isArray(item)) + { + const { name, operator, value } = extractWhereParams(item); + builder.where(name, operator, value); + } + + if(item === "end") builder.end(); + + } + + } + else + { + const { name, operator, value } = extractWhereParams(params.where); + builder.where(name, operator, value); + } + + } + + /* + if(params.where.length >=2 ) + { + let name = params.where[0]; + let operator = '='; + let value = params.where[1]; + + if(params.where.length == 3) + { + operator = params.where[1]; + value = params.where[2]; + } + + builder.where(name, operator, value); + } + */ + } + + if(params.hasOwnProperty("between")) + { + builder.between(params.between[0], params.between[1], params.between[2]); + } + + let response = await promisifyBuilder(builder); + responseObj["data"] = response; + + //console.log(responseObj); + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + + return; + } + + if(action == "delete") + { + + } + + + if(action == "update") + { + //! data receiving from terminal (params) + // { + // hostname: 'localhost', + // table: 'settings', + // action: 'update', + // body: { + // rvo_name: 'terrrr', + // lang: 'en', + // temperature_adress: '28.427B45920702', + // latitude: 48.70826502, + // longitude: 17.28455203, + // mqtt_host: '192.168.252.4', + // mqtt_clientid: 'showroom_test_panel_led', + // mqtt_username: 'xmRd6RJxW53WZe4vMFLU', + // mqtt_port: 1883, + // maintanace_mode: false + // } + // } + const tableToModify = TABLE(params.table); + const newValues = params.body; + + tableToModify.modify(newValues).make(function(builder) { + + builder.callback(function(err, response) { + + if(!err) + { + responseObj["data"] = response; + responseObj["tableUpdated"] = true; + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + } + }); + }); + + } + + if(action == "replace") + { + //truncate table + const db = TABLE(params.table); + var builder = db.remove(); + db.clean(); + + //insert data + let data = params.data; + + for(let i = 0; i < data.length; i++) + { + //console.log(data[i]); + db.insert(data[i]); + } + + console.log("insert done"); + + let responseObj = {}; + responseObj["type"] = "SUCESS"; + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + + + } + + + + } catch (error) { + //console.log(error); + responseObj["type"] = "ERROR"; + responseObj["message"] = error; + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + } + } + }) +} + + diff --git a/RVO23/flow/db_init.js b/RVO23/flow/db_init.js new file mode 100755 index 0000000..b399878 --- /dev/null +++ b/RVO23/flow/db_init.js @@ -0,0 +1,113 @@ +exports.id = 'db_init'; +exports.title = 'DB Initialization'; +exports.group = 'Worksys'; +exports.color = '#888600'; +exports.version = '1.0.2'; +exports.icon = 'sign-out'; +exports.output = 2; + +exports.readme = ` + # DB initialization +`; + +const { promisifyBuilder, makeMapFromDbResult } = require('./helper/db_helper.js'); +const { initNotification } = require('./helper/notification_reporter'); +const errorHandler = require('./helper/ErrorToServiceHandler'); +const total_energy = require('../databases/total_energy'); + +const SEND_TO = { + db_init: 0, + infoSender: 1 +}; + + +exports.install = async function(instance) { + const dbNodes = TABLE("nodes"); + const dbRelays = TABLE("relays"); + const dbSettings = TABLE("settings"); + 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 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.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"]; + Object.keys(dbs.nodesData).forEach(node => dbs.nodesData[node].readout = {}) + + let rvo_number = responseSettings[0]["rvo_name"].match(/\D+(\d{1,2})_/)[1]; + + dbs.settings = { + edge_fw_version: "2025-10-08", //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"], + phases: responseSettings[0]["phases"], + cloud_topic: responseSettings[0]["cloud_topic"], + has_main_switch: responseSettings[0]["has_main_switch"], + daily_report: responseSettings[0]["daily_report"], + send_changed_node_numbers: responseSettings[0]["send_changed_node_numbers"], + rvo_number: rvo_number, + + //dynamic values + masterNodeIsResponding: true, //cmd_manager + maintenance_mode: false, + } + + + dbs.settings.energy_to_switch_lamps = total_energy[rvo_number]; + if (dbs.settings.energy_to_switch_lamps === undefined) console.log('=============== db_init.js: energy_to_switch_lamps is undefined'); + + FLOW.dbLoaded = true; + errorHandler.setProjectId(dbs.settings.project_id); + initNotification(); + + //APP START - send to data services + const toService = { + id: dbs.settings.project_id, + name: dbs.settings.rvo_name, + fw_version: dbs.settings.edge_fw_version, + startdate: new Date().toISOString().slice(0, 19).replace('T', ' '), + js_error: "", + error_message: "" + }; + + instance.send(SEND_TO.infoSender, toService); + console.log("----------------> START - message send to service", toService); + + setTimeout(() => { + console.log("DB_INIT - data loaded"); + instance.send(SEND_TO.db_init, "_") + }, 5000) + +}; + diff --git a/RVO23/flow/debug.js b/RVO23/flow/debug.js new file mode 100755 index 0000000..00cb259 --- /dev/null +++ b/RVO23/flow/debug.js @@ -0,0 +1,100 @@ +exports.id = 'debug'; +exports.title = 'Debug'; +exports.author = 'Peter Širka'; +exports.color = '#967ADC'; +exports.click = true; +exports.input = true; +exports.icon = 'bug'; +exports.version = '2.0.4'; +exports.options = { enabled: true, repository: false, type: 'data' }; +exports.readme = `# Debug + +Prints data to the debug tab.`; + +exports.html = `
+
+
+
@(Output type)
+
@(Path to the property (leave empty to show the whole data object))
+
@(A group name)
+
@(Enabled)
+
+
+
`; + +exports.install = function(instance) { + + instance.on('data', function(response) { + if (instance.options.enabled) { + + var opt = instance.options; + var rep = response.repository; + var val = response.data; + var id = response.id; + + switch (instance.options.type){ + case 'both': + var data = {}; + data.repository = rep; + data.data = val instanceof Error ? { error: val.message, stack: val.stack } : val; + instance.debug(safeparse(opt.property ? U.get(data, opt.property) : data), undefined, opt.group, id); + break; + case 'repository': + instance.debug(safeparse(opt.property ? U.get(rep, opt.property) : rep), undefined, opt.group, id); + break; + case 'data': + default: + if (val instanceof Error) + instance.debug({ error: val.message, stack: val.stack }, undefined, opt.group, id); + else + instance.debug(safeparse(opt.property ? U.get(val, opt.property) : val), undefined, opt.group, id); + break; + } + } + }); + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + instance.save(); + }); + + instance.on('options', function() { + instance.custom.status(); + }); + + instance.custom.status = function() { + instance.status(instance.options.enabled ? 'Enabled' : 'Disabled'); + }; + + instance.custom.status(); + + function safeparse(o) { + + if (o instanceof Buffer) + return o; + + if (o === undefined) + return 'undefined'; + + if (o === null) + return 'null'; + + var cache = []; + var str = JSON.stringify(o, function(key, value) { + if (typeof value === 'object' && value !== null) { + if (cache.indexOf(value) !== -1) { + try { + return JSON.parse(JSON.stringify(value)); + } catch (error) { + return; + } + } + cache.push(value); + } + return value; + }); + cache = null; + return JSON.parse(str); + } +}; diff --git a/RVO23/flow/designer.json b/RVO23/flow/designer.json new file mode 100755 index 0000000..580f5a3 --- /dev/null +++ b/RVO23/flow/designer.json @@ -0,0 +1,3102 @@ +{ + "tabs": [ + { + "name": "MAIN PUSH", + "linker": "main-push", + "id": "1612772287426", + "index": 0 + }, + { + "name": "CMD manager", + "linker": "cmd-manager", + "id": "1615551125555", + "index": 1 + }, + { + "name": "Devices", + "linker": "devices", + "id": "1611921777196", + "index": 2 + } + ], + "components": [ + { + "id": "1611951142547", + "component": "debug", + "tab": "1611921777196", + "name": "ERROR", + "x": 598, + "y": 60, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#DA4453", + "notes": "" + }, + { + "id": "1612776786008", + "component": "wsmqttpublish", + "tab": "1612772287426", + "name": "WS MQTT publish", + "x": 281.75, + "y": 174, + "connections": { + "0": [ + { + "index": "0", + "id": "1615551060773" + } + ], + "1": [ + { + "index": "0", + "id": "1618300858252" + }, + { + "index": "0", + "id": "1618558465485" + } + ], + "2": [ + { + "index": "0", + "id": "1634303685503" + } + ], + "3": [ + { + "index": "0", + "id": "1731068754606" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Connected", + "color": "green" + }, + "options": { + "username": "", + "clientid": "", + "port": "1883", + "host": "" + }, + "color": "#888600", + "notes": "" + }, + { + "id": "1612778461252", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "tb-push", + "x": 72.75, + "y": 328, + "connections": { + "0": [ + { + "index": "0", + "id": "1612783322136" + }, + { + "index": "1", + "id": "1612776786008" + }, + { + "index": "0", + "id": "1731068754606" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1612783322136", + "component": "debug", + "tab": "1612772287426", + "name": "to TB", + "x": 283.75, + "y": 324, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615551060773", + "component": "debug", + "tab": "1612772287426", + "name": "errors from MQTT Broker", + "x": 594, + "y": 57, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#DA4453", + "notes": "" + }, + { + "id": "1615563373927", + "component": "debug", + "tab": "1615551125555", + "name": "Debug", + "x": 755, + "y": 155, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#DA4453", + "notes": "" + }, + { + "id": "1615566865233", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "tb-push", + "x": 755, + "y": 248, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1615798582262", + "component": "debug", + "tab": "1615551125555", + "name": "CMD_debug", + "x": 755, + "y": 346, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615802995322", + "component": "debug", + "tab": "1611921777196", + "name": "Debug", + "x": 596.8833312988281, + "y": 566.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Disabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": false + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615809128443", + "component": "debug", + "tab": "1611921777196", + "name": "tempToTb", + "x": 595.8833312988281, + "y": 658.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615809595184", + "component": "virtualwireout", + "tab": "1611921777196", + "name": "tb-push", + "x": 597.8833312988281, + "y": 377.25, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1616165795916", + "component": "httproute", + "tab": "1615551125555", + "name": "POST /terminal", + "x": 135, + "y": 547, + "connections": { + "0": [ + { + "index": "0", + "id": "1684060205000" + }, + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Listening", + "color": "green" + }, + "options": { + "timeout": 10, + "cachepolicy": 0, + "cacheexpire": "5 minutes", + "size": 5, + "url": "/terminal", + "method": "POST", + "name": "", + "flags": [ + "id:1616165795916", + "post", + 10000 + ], + "emptyresponse": false + }, + "color": "#5D9CEC", + "notes": "### Configuration\n\n- __POST /terminal__\n- flags: \n- maximum request data length: __5 kB__\n- empty response: __false__\n- cache policy: __no cache__\n- cache expire: __5 minutes__", + "cloning": false + }, + { + "id": "1616165824813", + "component": "httpresponse", + "tab": "1615551125555", + "name": "HTTP Response", + "x": 753, + "y": 423, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "json" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1617104731852", + "component": "debug", + "tab": "1615551125555", + "name": "DIDO_Debug", + "x": 669, + "y": 1040, + "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": "turnOff line", + "x": 133, + "y": 1161, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "object", + "data": "{line: 3, command: \"turnOff\", force: true}" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1617115013095", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "tb-push", + "x": 669, + "y": 1150, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1617284749681", + "component": "trigger", + "tab": "1615551125555", + "name": "update profile / node", + "x": 112, + "y": 208, + "connections": { + "0": [ + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "data": "profile_nodes", + "datatype": "string" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1618235171399", + "component": "trigger", + "tab": "1615551125555", + "name": "tun tasks", + "x": 184, + "y": 279, + "connections": { + "0": [ + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "data": "run" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1618300858252", + "component": "debug", + "tab": "1612772287426", + "name": "wsmqtt-exit1", + "x": 597.8833312988281, + "y": 149, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1618393583970", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "to-cmd-manager", + "x": 668.8833312988281, + "y": 1269, + "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": 132.88333129882812, + "y": 367, + "connections": { + "0": [ + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "platform-rpc-call", + "color": "gray" + }, + "options": { + "wirename": "platform-rpc-call" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1618393759854", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "cmd_to_dido", + "x": 119.88333129882812, + "y": 1007, + "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": 752.8833312988281, + "y": 527, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "cmd_to_dido", + "color": "gray" + }, + "options": { + "wirename": "cmd_to_dido" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1618558465485", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "platform-rpc-call", + "x": 597.8833312988281, + "y": 247, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "platform-rpc-call", + "color": "gray" + }, + "options": { + "wirename": "platform-rpc-call" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1618572059773", + "component": "trigger", + "tab": "1615551125555", + "name": "turnOn line", + "x": 132, + "y": 1085, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "data": "{line: 1, command: \"turnOn\", force: true}", + "datatype": "object" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1619515097737", + "component": "cmd_manager", + "tab": "1615551125555", + "name": "CMD Manager", + "x": 452.1091003417969, + "y": 341.05455017089844, + "connections": { + "0": [ + { + "index": "0", + "id": "1615563373927" + } + ], + "1": [ + { + "index": "0", + "id": "1615566865233" + }, + { + "index": "0", + "id": "1615798582262" + } + ], + "2": [ + { + "index": "0", + "id": "1616165824813" + } + ], + "3": [ + { + "index": "0", + "id": "1618393827655" + } + ], + "4": [ + { + "index": "0", + "id": "1635936391935" + } + ], + "5": [ + { + "index": "0", + "id": "1757006030239" + }, + { + "index": "0", + "id": "1757006060377" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1619605019281", + "component": "httproute", + "tab": "1615551125555", + "name": "GET db", + "x": 173, + "y": 653, + "connections": { + "0": [ + { + "index": "0", + "id": "1684060205000" + }, + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Listening", + "color": "green" + }, + "options": { + "timeout": 5, + "cachepolicy": 0, + "cacheexpire": "5 minutes", + "size": 5, + "url": "/db", + "method": "GET", + "name": "", + "flags": [ + "id:1619605019281", + "get", + 5000 + ] + }, + "color": "#5D9CEC", + "notes": "### Configuration\n\n- __GET /db__\n- flags: undefined\n- maximum request data length: __5 kB__\n- empty response: __undefined__\n- cache policy: __no cache__\n- cache expire: __5 minutes__", + "cloning": false + }, + { + "id": "1619784672383", + "component": "trigger", + "tab": "1615551125555", + "name": "turnOnAlarm", + "x": 120, + "y": 1234, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "object", + "data": "{command: \"turnOnAlarm\"}" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1619784812964", + "component": "trigger", + "tab": "1615551125555", + "name": "turnOffAlarm", + "x": 118, + "y": 1307, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "object", + "data": "{command: \"turnOffAlarm\"}" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1621340721628", + "component": "virtualwireout", + "tab": "1611921777196", + "name": "modbus_to_dido", + "x": 599, + "y": 471, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "modbus_to_dido", + "color": "gray" + }, + "options": { + "wirename": "modbus_to_dido" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1622640022885", + "component": "httproute", + "tab": "1615551125555", + "name": "POST /db_connector", + "x": 98, + "y": 1586, + "connections": { + "0": [ + { + "index": "0", + "id": "1622640073521" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Listening", + "color": "green" + }, + "options": { + "timeout": 5, + "cachepolicy": 0, + "cacheexpire": "5 minutes", + "size": 5, + "url": "/db_connector", + "method": "POST", + "flags": [ + "id:1622640022885", + "post", + 5000 + ] + }, + "color": "#5D9CEC", + "notes": "### Configuration\n\n- __POST /db_connector__\n- flags: \n- maximum request data length: __5 kB__\n- empty response: __undefined__\n- cache policy: __no cache__\n- cache expire: __5 minutes__", + "cloning": false + }, + { + "id": "1622640073521", + "component": "db_connector", + "tab": "1615551125555", + "name": "DbConnector", + "x": 372, + "y": 1572, + "connections": { + "1": [ + { + "index": "0", + "id": "1622641420685" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "edge": "undefined" + }, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1622641420685", + "component": "httpresponse", + "tab": "1615551125555", + "name": "HTTP Response", + "x": 596, + "y": 1586, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1634303504177", + "component": "monitormemory", + "tab": "1612772287426", + "name": "RAM", + "x": 69.88333129882812, + "y": 888.5, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465281992" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "858.88 MB / 985.68 MB", + "color": "gray" + }, + "options": { + "enabled": true, + "interval": 30000 + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1634303533779", + "component": "monitordisk", + "tab": "1612772287426", + "name": "disk", + "x": 70.88333129882812, + "y": 982.5, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465821120" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "5.78 GB / 7.26 GB", + "color": "gray" + }, + "options": { + "enabled": true, + "path": "/", + "interval": 30000 + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1634303595494", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "send-to-services", + "x": 51.883331298828125, + "y": 1400.5, + "connections": { + "0": [ + { + "index": "0", + "id": "1634463186563" + }, + { + "index": "1", + "id": "1634488120710" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1634303602169", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "send-to-services", + "x": 426.8833312988281, + "y": 878.5, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1634303685503", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "send-to-services", + "x": 600.8833312988281, + "y": 341.5, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1634303743260", + "component": "httprequest", + "tab": "1612772287426", + "name": "192.168.252.2:8004/sentmessage", + "reference": "", + "x": 506.8833312988281, + "y": 1331.7333374023438, + "connections": { + "0": [ + { + "index": "0", + "id": "1635327431236" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "url": "http://192.168.252.2:8004/sentmessage", + "method": "POST", + "stringify": "json" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1634463186563", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 305.75, + "y": 1442, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634464580289", + "component": "code", + "tab": "1612772287426", + "name": "Code", + "x": 245, + "y": 787, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465243324" + }, + { + "index": "0", + "id": "1634303602169" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "keepmessage": true, + "code": "let response = {};\nresponse.cpu = value.cpu;\nresponse.uptime = value.uptime;\n\nsend(0, response);", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1634465243324", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 428, + "y": 784, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634465281992", + "component": "code", + "tab": "1612772287426", + "name": "Code", + "x": 245, + "y": 884, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465338103" + }, + { + "index": "0", + "id": "1634303602169" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "keepmessage": true, + "code": "value.sender = \"ram\";\n\nlet response = {};\n\nresponse.memory_total = Math.round(value.total / (1024 ** 2));\nresponse.memory_free = Math.round(value.free / (1024 ** 2));\nresponse.memory_used = Math.round(value.used / (1024 ** 2));\n\nsend(0, response);", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1634465338103", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 429, + "y": 976, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634465821120", + "component": "code", + "tab": "1612772287426", + "name": "Code", + "x": 245, + "y": 978, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465892500" + }, + { + "index": "0", + "id": "1634303602169" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "keepmessage": true, + "code": "value.sender = \"hdd\";\n\nlet response = {};\n\nresponse.hdd_total = Math.round(value.total / (1024 ** 2));\nresponse.hdd_free = Math.round(value.free / (1024 ** 2));\nresponse.hdd_used = Math.round(value.used / (1024 ** 2));\n\nsend(0, response);", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1634465892500", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 432, + "y": 1068, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634484067516", + "component": "debug", + "tab": "1612772287426", + "name": "Send info", + "x": 513, + "y": 1441, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634488120710", + "component": "infosender", + "tab": "1612772287426", + "name": "Info sender", + "x": 301, + "y": 1336, + "connections": { + "0": [ + { + "index": "0", + "id": "1634484067516" + }, + { + "index": "0", + "id": "1634303743260" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "edge": "undefined" + }, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1635327431236", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 837.8833312988281, + "y": 1325.5, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1635936391935", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "send-to-services", + "x": 753, + "y": 623, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1637069803394", + "component": "monitorconsumption", + "tab": "1612772287426", + "name": "CPU", + "x": 69, + "y": 791, + "connections": { + "0": [ + { + "index": "0", + "id": "1634464580289" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "49.2% / 69.91 MB", + "color": "gray" + }, + "options": { + "monitorfiles": true, + "monitorconnections": true, + "monitorsize": true, + "monitorconsumption": true, + "enabled": true, + "interval": 30000 + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1683664161036", + "component": "debug", + "tab": "1615551125555", + "name": "CMDtoDIDO", + "x": 392, + "y": 1012, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1683981346282", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "from-dido-controller", + "x": 112, + "y": 459, + "connections": { + "0": [ + { + "index": "0", + "id": "1684055037116" + }, + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "from-dido-controller", + "color": "gray" + }, + "options": { + "wirename": "from-dido-controller" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1684055037116", + "component": "debug", + "tab": "1615551125555", + "name": "from dido to cmd", + "x": 451, + "y": 532, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1684060205000", + "component": "debug", + "tab": "1615551125555", + "name": "HTTP routes", + "x": 450, + "y": 639, + "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": "MDBToDido", + "x": 598, + "y": 147, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1699963668903", + "component": "dido_controller", + "tab": "1615551125555", + "name": "DIDO_Controller", + "x": 397, + "y": 1131, + "connections": { + "0": [ + { + "index": "0", + "id": "1617104731852" + } + ], + "1": [ + { + "index": "0", + "id": "1617104731852" + }, + { + "index": "0", + "id": "1617115013095" + } + ], + "2": [ + { + "index": "0", + "id": "1618393583970" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "edge": "undefined" + }, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1699964678894", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "modbus_to_dido", + "x": 96, + "y": 924, + "connections": { + "0": [ + { + "index": "0", + "id": "1699963668903" + }, + { + "index": "0", + "id": "1699964793925" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "modbus_to_dido", + "color": "gray" + }, + "options": { + "wirename": "modbus_to_dido" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1699964793925", + "component": "debug", + "tab": "1615551125555", + "name": "modbusToDido", + "x": 388, + "y": 920, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1699965957410", + "component": "modbus_reader", + "tab": "1611921777196", + "name": "Modbus reader", + "x": 232, + "y": 175, + "connections": { + "0": [ + { + "index": "0", + "id": "1611951142547" + } + ], + "1": [ + { + "index": "0", + "id": "1621340721628" + }, + { + "index": "0", + "id": "1684179110403" + }, + { + "index": "0", + "id": "1717441414646" + } + ], + "2": [ + { + "index": "0", + "id": "1615809595184" + }, + { + "index": "0", + "id": "1714752862828" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1700411878636", + "component": "thermometer", + "tab": "1611921777196", + "name": "Thermometer", + "x": 234.75, + "y": 444, + "connections": { + "0": [ + { + "index": "0", + "id": "1615802995322" + } + ], + "1": [ + { + "index": "0", + "id": "1615809595184" + }, + { + "index": "0", + "id": "1615809128443" + } + ], + "2": [ + { + "index": "0", + "id": "1621340721628" + }, + { + "index": "0", + "id": "1732889185927" + }, + { + "index": "0", + "id": "1717441414646" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#5CB36D", + "notes": "" + }, + { + "id": "1714752862828", + "component": "debug", + "tab": "1611921777196", + "name": "MDBToTb", + "x": 766, + "y": 324, + "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": 764.0833282470703, + "y": 222, + "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\telse if(value.status === \"NOK-thermometer\")\n\t{\n\t\tsend(0, {\"thermometer\": \"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\telse if(value.values.hasOwnProperty(\"temperature\"))\n\t{\n\t\tsend(0, {\"thermometer\": \"OK\"});\n\t}\n}", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1717442627834", + "component": "debug", + "tab": "1611921777196", + "name": "modbus service", + "x": 966.0833282470703, + "y": 165, + "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": 968.0833282470703, + "y": 268, + "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": 88.75, + "y": 1685, + "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": 296, + "y": 1671, + "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\", \"Flow has been restarted\", \"Node db has changed\"]", + "types": "[\"emergency\", \"critical\", \"error\", \"alert\"]", + "name": "" + }, + "color": "#30E193", + "notes": "" + }, + { + "id": "1718016073501", + "component": "httprequest", + "tab": "1612772287426", + "name": "http://192.168.252.2:8004/slack", + "x": 495, + "y": 1753, + "connections": { + "0": [ + { + "index": "0", + "id": "1718016086212" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "url": "http://192.168.252.2:8004/slack", + "method": "POST", + "stringify": "json" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1718016086212", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 832, + "y": 1664, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "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": 87, + "y": 1591, + "connections": { + "0": [ + { + "index": "0", + "id": "1718016052341" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "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\": \"\" } } } ] }", + "datatype": "object" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1729855334955", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "platform-rpc-call", + "x": 599.9333343505859, + "y": 541.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "platform-rpc-call", + "color": "gray" + }, + "options": { + "wirename": "platform-rpc-call" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1729855371093", + "component": "debug", + "tab": "1612772287426", + "name": "rpc cloud", + "x": 601.9333343505859, + "y": 440.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1731068658334", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 75.75, + "y": 184, + "connections": { + "0": [ + { + "index": "0", + "id": "1612776786008" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731068754606", + "component": "cloudmqttconnect", + "tab": "1612772287426", + "name": "MQTT to senica-prod01", + "x": 284.75, + "y": 452, + "connections": { + "1": [ + { + "index": "0", + "id": "1729855371093" + }, + { + "index": "0", + "id": "1729855334955" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Connected", + "color": "green" + }, + "options": { + "username": "", + "clientid": "", + "port": "2764", + "host": "192.168.252.2", + "topic": "" + }, + "color": "#888600", + "notes": "" + }, + { + "id": "1731069001548", + "component": "db_init", + "tab": "1612772287426", + "name": "DB Initialization", + "x": 1003.75, + "y": 240.25, + "connections": { + "0": [ + { + "index": "0", + "id": "1731069033416" + } + ], + "1": [ + { + "index": "0", + "id": "1747561603739" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#888600", + "notes": "" + }, + { + "id": "1731069033416", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "db-init", + "x": 1244.75, + "y": 233.25, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069059135", + "component": "showdb", + "tab": "1612772287426", + "name": "Show db data", + "x": 1186.75, + "y": 821.25, + "connections": { + "0": [ + { + "index": "0", + "id": "1731069079243" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#888600", + "notes": "" + }, + { + "id": "1731069079243", + "component": "debug", + "tab": "1612772287426", + "name": "dbData", + "x": 1390.75, + "y": 870.25, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1731069116691", + "component": "trigger", + "tab": "1612772287426", + "name": "settings", + "x": 934.75, + "y": 669.75, + "connections": { + "0": [ + { + "index": "0", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069131637", + "component": "trigger", + "tab": "1612772287426", + "name": "relaysData", + "x": 876.75, + "y": 733.75, + "connections": { + "0": [ + { + "index": "1", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069137374", + "component": "trigger", + "tab": "1612772287426", + "name": "nodesData", + "x": 852.75, + "y": 794.75, + "connections": { + "0": [ + { + "index": "2", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069179846", + "component": "trigger", + "tab": "1612772287426", + "name": "pinsData", + "x": 850.75, + "y": 861.75, + "connections": { + "0": [ + { + "index": "3", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069192937", + "component": "trigger", + "tab": "1612772287426", + "name": "sample data", + "x": 857.75, + "y": 928.75, + "connections": { + "0": [ + { + "index": "4", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069264443", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 63.75, + "y": 1279, + "connections": { + "0": [ + { + "index": "0", + "id": "1634488120710" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069334626", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "db-init", + "x": 172.88333129882812, + "y": 129, + "connections": { + "0": [ + { + "index": "0", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069548145", + "component": "virtualwirein", + "tab": "1611921777196", + "name": "db-init", + "x": 46.75, + "y": 192, + "connections": { + "0": [ + { + "index": "0", + "id": "1699965957410" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069567152", + "component": "virtualwirein", + "tab": "1611921777196", + "name": "db-init", + "x": 44.75, + "y": 465, + "connections": { + "0": [ + { + "index": "0", + "id": "1700411878636" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731070156936", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "db-init", + "x": 126.88333129882812, + "y": 1377, + "connections": { + "0": [ + { + "index": "2", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731234189516", + "component": "trigger", + "tab": "1612772287426", + "name": "monitor.txt", + "x": 882.75, + "y": 991.75, + "connections": { + "0": [ + { + "index": "5", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731234189551", + "component": "trigger", + "tab": "1612772287426", + "name": "err.txt", + "x": 904.75, + "y": 1053.75, + "connections": { + "0": [ + { + "index": "6", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1732700042559", + "component": "nodesdb_change_check", + "tab": "1612772287426", + "name": "Nodes DB change check", + "x": 266.8833312988281, + "y": 1980.2333984375, + "connections": { + "0": [ + { + "index": "0", + "id": "1732700071298" + }, + { + "index": "0", + "id": "1732700642917" + } + ], + "1": [ + { + "index": "0", + "id": "1759958914348" + }, + { + "index": "0", + "id": "1759959003114" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#888600", + "notes": "" + }, + { + "id": "1732700057052", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 76.75, + "y": 1988, + "connections": { + "0": [ + { + "index": "0", + "id": "1732700042559" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1732700071298", + "component": "debug", + "tab": "1612772287426", + "name": "nodesChange", + "x": 571.8833312988281, + "y": 2018.2333984375, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1732700642917", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "tb-push", + "x": 567.8833312988281, + "y": 1933, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1732889185927", + "component": "debug", + "tab": "1611921777196", + "name": "tempToDido", + "x": 594.8833312988281, + "y": 753, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1733574412965", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 72.75, + "y": 474, + "connections": { + "0": [ + { + "index": "1", + "id": "1731068754606" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1747561603739", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "send-to-services", + "x": 1243.8833312988281, + "y": 334.5, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1747562867845", + "component": "comment", + "tab": "1612772287426", + "name": "FLOW STARTING POINT", + "x": 1003.5666656494141, + "y": 178, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#704cff", + "notes": "" + }, + { + "id": "1749211698385", + "component": "trigger", + "tab": "1612772287426", + "name": "deviceStatus", + "x": 911.75, + "y": 1116.75, + "connections": { + "0": [ + { + "index": "7", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1757006030239", + "component": "httprequest", + "tab": "1615551125555", + "name": "192.168.252.2:8015/daily_report", + "x": 756.5666656494141, + "y": 715.4499969482422, + "connections": { + "0": [ + { + "index": "0", + "id": "1757006045804" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "stringify": "json", + "method": "POST", + "url": "http://192.168.252.2:8015/daily_report" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1757006045804", + "component": "debug", + "tab": "1615551125555", + "name": "ddd", + "x": 1091.566665649414, + "y": 711.4499969482422, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1757006060377", + "component": "debug", + "tab": "1615551125555", + "name": "reportDebug", + "x": 749.5666656494141, + "y": 799.4499969482422, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1759958914348", + "component": "httprequest", + "tab": "1612772287426", + "name": "http://192.168.252.2:8015/node_numbers", + "x": 571, + "y": 2111, + "connections": { + "0": [ + { + "index": "0", + "id": "1759958927094" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "stringify": "json", + "method": "POST", + "url": "http://192.168.252.2:8015/node_numbers" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1759958927094", + "component": "debug", + "tab": "1612772287426", + "name": "nodesChangeCloud", + "x": 951.8833312988281, + "y": 2109.2333984375, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1759959003114", + "component": "debug", + "tab": "1612772287426", + "name": "nodeChangeCloud1", + "x": 574, + "y": 2218, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1760020290879", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 84.75, + "y": 1787, + "connections": { + "0": [ + { + "index": "1", + "id": "1718016052341" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + } + ], + "version": 615 +} diff --git a/RVO23/flow/dido_controller.js b/RVO23/flow/dido_controller.js new file mode 100755 index 0000000..d16fb19 --- /dev/null +++ b/RVO23/flow/dido_controller.js @@ -0,0 +1,1486 @@ +exports.id = 'dido_controller'; +exports.title = 'DIDO_Controller'; +exports.version = '2.0.0'; +exports.group = 'Worksys'; +exports.color = '#2134B0'; +exports.input = 3; +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 + +state_of_main_switch - reportovat stav hlaveho istica : 0-> off 1-> on +rotary_switch_state - sem by sa mal reportovat stav vstupov manual a auto pola nasledovnej logiky: Manual = 1 a Auto = 0 -> Manu +Manual = 0 a Auto = 0 -> Off, Manual = 0 a Auto = 1 -> Automatic + +door_condition - pin 6, dverový kontakt -> 1 -> vyreportuje Closed, 0 -> vyreportuje Ope +twilight_sensor - hodnotu, ktoru vracia ten analogovy vstup (17) treba poslat sem ako float number. Zrejme tu potom pridame nejaky koeficient prevodu na luxy + +Na kazdu liniu +state_of_breaker - podla indexu istica sa reportuje jeho stav, teda istic na liniu 1: 0-> off, 1-> on +state_of_contactor - podla indexu stkaca sa reportuje jeho stav, teda stykac 1 na liniu 1: 0-> off, 1-> on +*/ + +const { errLogger, logger, monitor } = require('./helper/logger'); +const SerialPort = require('serialport'); +const WebSocket = require('ws'); +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 errorHandler = require('./helper/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 hasMainSwitch; + +let alarmStatus = "OFF"; + +const SEND_TO = { + debug: 0, + tb: 1, + cmd_manager: 2 +} + + +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 = {}; + let rsPortReceivedData = []; + + //to be able to get proper twilight values + let twilight_sensor_interval = 5;//minutes + let twilight_sensor = []; + const twilight_sensor_array = []; + let twilightError = false; + + monitor.info("DIDO_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-we make it global to see it from outside + FLOW.deviceStatus = { //key is device name: temperature,.... + "state_of_main_switch": "Off", //Hlavny istic (alebo druhy dverovy kontakt) + "rotary_switch_state": "Off", //Prevadzkovy + "door_condition": "closed", //Dverový kontakt + "em": "OK", //elektromer rvo + "temperature": "OK", //templomer + "battery": "OK", //Bateria + "power_supply": "OK", //Zdroj + "master_node": "OK", //MN - GLOBALS.settings.masterNodeIsResponding + "no_voltage": "OK", //GLOBALS.settings.no_voltage - vypadok napatia na faze + "state_of_breaker": {}, //"Off",//Istic + "state_of_contactor": {}, //"Off",//Stykac + "twilight_sensor": "OK" //lux sensor + }; + let deviceStatus = FLOW.deviceStatus; + + + function main() { + + GLOBALS = FLOW.GLOBALS; + SETTINGS = FLOW.GLOBALS.settings; + rvoTbName = SETTINGS.rvoTbName; + pinsData = GLOBALS.pinsData; + relaysData = GLOBALS.relaysData; + + tbHandler = new DataToTbHandler(SEND_TO.tb); + tbHandler.setSender(exports.title); + + controller_type = SETTINGS.controller_type; //"lm" or "unipi" + hasMainSwitch = SETTINGS.has_main_switch; + + if (controller_type == "") controller_type = "lm"; + + 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, "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; + } + } + + //report RVO version relaysData[0].tbname; + let values = {}; + values["edge_fw_version"] = SETTINGS.edge_fw_version; + values["maintenance_mode"] = SETTINGS.maintenance_mode; + + sendTelemetry(values, rvoTbName); + + 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); + } + + + function handleRsPort() { + + if (rsPort) { + rsPort.removeAllListeners(); + rsPort = null; + } + + //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('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) { + if (!err) { + monitor.info(exports.title + "--->Digital in_out has been set (runSyncExec was sucessfull)"); + + turnAlarm("off"); + 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('error', err => { + let message = "Dido: rsPort error: " + err.message; + logger.debug(message); + monitor.info(message); + errorHandler.sendMessageToService(message); + }) + + rsPort.on("close", () => { + let message = "Dido: rsPort closed - reconnecting ..."; + logger.debug(message); + monitor.info(message); + setTimeout(handleRsPort, 1000); + }) + + rsPort.open(); + } + + + function handleWebSocket() { + + if (ws) { + ws.removeAllListeners(); + ws = null; + } + + //to keep websocket opened, we send request every 150 seconds + let startRequests = null; + + console.log("handleWebSocket function called"); + ws = new WebSocket('ws:/0.0.0.0:1234/ws'); + + ws.onopen = function open() { + + instance.send(0, exports.title + " running"); + turnAlarm("off"); + + initialSetting(); + + setTimeout(function() { ws.send(JSON.stringify({ cmd: "all" })) }, 5000); + // we request dev info about neuron device from evok to keep websocket connection alive + // for some reason this request returns no data, but connection keeps alive + startRequests = setInterval(() => { + ws.send(JSON.stringify({ "cmd": "filter", "dev": ["neuron"] })); + }, 150000) + }; + + + // 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 = async 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; + + 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 => { + logger.debug('Dido: websocket error', err); + }) + + ws.onclose = function() { + logger.debug('Dido: websocket onclose, reconnecting...') + clearInterval(startRequests); + setTimeout(handleWebSocket, 1000); + } + } + + 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 turnAlarm(onOrOff) { + let value = 0; + if (onOrOff == "on") value = 1; + + if (value == 1 && SETTINGS.maintenance_mode) return; + + alarmStatus = "OFF"; + if (value == 1) alarmStatus = "ON"; + + if (rsPort) { + let arr = [0x55]; + arr.push(13); + arr.push(0); + arr.push(value); + + rsPort.write(Buffer.from(arr), function(err) { + logger.debug(`sirena - ${onOrOff}`); + }); + } + else if (ws) { + let cmd = { "cmd": "set", "dev": "relay", "circuit": "1_01", "value": value }; + ws.send(JSON.stringify(cmd)); + logger.debug(`sirena - ${onOrOff}`); + } + } + + + 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") { + bits.push(0); + } + else bits.push(1); + + if (deviceStatus["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); + } + + + // turn line on or off + function turnLine(onOrOff, line, pin, force, info) { + //onOrOff => "on" or "off" + let value = 0; + if (onOrOff == "on") value = 1; + + if (force == undefined) force = false; + + if (line == 0) { + if (value == 1 && alarmStatus == "ON") turnAlarm("off"); + SETTINGS.maintenance_mode = value ? true : false; + + 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); + return; + } + + if (pin === undefined) pin = getPin(line); + + if (pin === undefined) { + errLogger.error("pin is undefined!", line); + return; + } + + if (!force) { + if (relaysData[line].contactor == value) { + instance.send(SEND_TO.debug, `line is already ${onOrOff} ` + line); + logger.debug(`Dido: turnLine: line is already ${onOrOff} `, line); + return; + } + } + + // if(!rsPort.isOpen && !ws) + if (!rsPort && !ws) { + errLogger.error("Dido - port or websocket is not opened"); + return; + } + + if (rsPort) { + let arr = [0x55]; + arr.push(pin); + arr.push(0); + arr.push(value); + + rsPort.write(Buffer.from(arr), function(err) { + if (err === undefined) { + monitor.info(`Dido: turnLine ${onOrOff} zapisal do rsPort-u`, line, pin, arr, info); + switchLogic(arr); + } + else { + monitor.info(`Dido: turnLine ${onOrOff} WRITE error`, err); + } + }); + + } + else if (ws) { + //pin = "relay1_03" or "input1_01" ... we must make just "1_01" with slice method + monitor.info(`Dido: turnLine ${onOrOff} - (line, pin, force)`, line, pin, force, info); + let cmd = { "cmd": "set", "dev": "relay", "circuit": pin.slice(5), "value": value }; + ws.send(JSON.stringify(cmd)); + } + + //if rvo is 24/7, it has just one switching profile point at 13:00. we do not want to send notification as it repeats every day. + //const d = new Date(); + //if(d.getHours() != 13) sendNotification("Dido_controller: ", SETTINGS.rvoTbName, "switching_profile_point_applied_to_line", { line: line, value: onOrOff }, "", SEND_TO.tb, instance); + } + + + // 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; + + // 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) { + const status = flowdata.data.status; + if (status == "NOK-twilight_sensor") { + deviceStatus["twilight_sensor"] = "NOK"; + } + else if (status == "NOK-em340" || status == "NOK-em111") { + deviceStatus["em"] = "NOK"; + } + else if (status == "NOK-thermometer") { + deviceStatus["temperature"] = "NOK"; + } + } + else if ("values" in flowdata.data) { + 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" + } + else if (values.hasOwnProperty("temperature")) { + deviceStatus["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"; + } + + sendTelemetry(values, rvoTbName); + } + + sendRvoStatus(); + }) + + + + + // we expect array as flowdata.data + instance.on("1", flowdata => { + + //console.log(flowdata.data); + + if (!flowdata.data instanceof Object) return; + + let obj = flowdata.data; + let line = obj.line; + 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"); + }) + + + function calculateStateCode() { + + let bits = []; + + //Hlavny istic - state_of_main_switch => v rvo senica je to druhy door pre silovu cast (EM) + if (deviceStatus["state_of_main_switch"] === "closed" || deviceStatus["state_of_main_switch"] === "Off") { + bits.push(0); + } + else { + bits.push(1); + } + + //Prevadzkovy mod - Manual, Off, Automatic, maintenance_mode = true/false // DAVA 2 BITY + if (!SETTINGS.maintenance_mode) { + if (deviceStatus["rotary_switch_state"] === "Manual") { + bits.push(0); + bits.push(1); + } + + if (deviceStatus["rotary_switch_state"] === "Automatic") { + bits.push(0); + bits.push(0); + } + + if (deviceStatus["rotary_switch_state"] === "Off") { + bits.push(1); + bits.push(0); + } + } + else { + bits.push(1); + bits.push(1); + } + + //Dverovy kontakt + if (deviceStatus["door_condition"] === "closed") { + bits.push(0); + } + else { + bits.push(1); + } + + //EM + if (deviceStatus["em"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //Teplomer + if (deviceStatus["temperature"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //Batéria + if (deviceStatus["battery"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //Zdroj + if (deviceStatus["power_supply"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //MN + if (deviceStatus["master_node"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //výpadok napätia na fáze + if (deviceStatus["no_voltage"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + if (deviceStatus["twilight_sensor"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + // doplnime do 16 bitov (2 byty) + for (let i = bits.length; i < 16; i++) { + bits.push(0); + } + + // console.log("calculateStateCode - deviceStatus", deviceStatus); + // 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; + } + + + async function sendRvoStatus() { + + if (SETTINGS === undefined) return; + SETTINGS.masterNodeIsResponding ? deviceStatus["master_node"] = "OK" : deviceStatus["master_node"] = "NOK"; + + 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 pinsForRvoStatus(controllerType, hasMainSwitch) { + + let pins = []; + + if (controllerType === "lm") { + pins = [1, 4, 6]; + if (hasMainSwitch === 1) { + pins = [4, 6]; + } + } else if (controllerType === "unipi") { + pins = ["input1_01", "input1_04", "input1_05"]; + if (hasMainSwitch === 1) { + pins = ["input1_01", "input1_04"]; + } + } + + return pins; + } + + + function checkRvoStatus() { + + // 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 + //set RVO state + let status = "OK"; + + for (const [key, value] of Object.entries(deviceStatus)) { + if (["em", "twilight_sensor", "temperature", "master_node"].includes(key) && value === "NOK") status = "NOK"; + } + + if (status === "OK") { + + let pinIndexes = pinsForRvoStatus(controller_type, hasMainSwitch); + + for (const pinIndex of pinIndexes) { + if (previousValues[pinIndex] === 0) { + if ((pinIndex === 6 || pinIndex === 'input1_01' || pinIndex === 'input1_05') && SETTINGS.maintenance_mode) continue; + status = "NOK"; + break; + } + } + } + + // battery status. If value is 1 - battery is NOK + if (previousValues[5] === 1) status = "NOK"; + if (SETTINGS.no_voltage.size > 0) status = "NOK"; + + // console.log("rvo status",status) + return status; + } + + + // we pass array to function in case of rsPort ==> switchLogic([55,3,0,1]) ==> [[55,3,0,1]] + // we pass two values in case of websocket ==> switchLogic("relay1_03",1) ==> ["relay1_03",1] + const switchLogic = (...args) => { + + let values = {}; + let pinIndex, newPinValue, twilight; + + //data from rsPort + if (args.length == 1) { + pinIndex = args[0][1] + 1; + if (pinIndex === 17) pinIndex--; + newPinValue = args[0][3]; + twilight = args[0][2]; + } + //data from websocket + else { + pinIndex = args[0]; + newPinValue = args[1]; + } + + 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; + + //default value + let value = "On"; + if (newPinValue === 0) value = "Off"; + + //Hlavny istic + if (type === "state_of_main_switch" && hasMainSwitch) { + if (newPinValue === 0 && newPinValue !== previousValues[pinIndex]) { + sendNotification("switchLogic", rvoTbName, "main_switch_has_been_turned_off", {}, "", SEND_TO.tb, instance, "state_of_main_switch"); + 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"); + deviceStatus["state_of_main_switch"] = "On"; + } + } + + //Prevadzkovy mod + 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"; + + deviceStatus["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, "power_supply_has_disconnected_input", {}, "", SEND_TO.tb, instance, "power_supply"); + + deviceStatus["power_supply"] = "NOK"; + } + else if (newPinValue === 1 && newPinValue !== previousValues[pinIndex]) { + sendNotification("switchLogic", rvoTbName, "power_supply_works_correctly", {}, "", SEND_TO.tb, instance, "power_supply"); + + deviceStatus["power_supply"] = "OK"; + } + } + + //Bateria - 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"); + + deviceStatus["battery"] = "NOK"; + } + else if (newPinValue === 0 && newPinValue !== previousValues[pinIndex]) { + sendNotification("switchLogic", rvoTbName, "battery_level_is_ok", {}, "", SEND_TO.tb, instance, "battery_level"); + + deviceStatus["battery"] = "OK"; + } + } + + //Dverovy kontakt - pin 6 + //! Ak je rvo s dvoma dverovymi kontaktami, ked pride z evoku signal z input1_05, co bol predytm "state_of_main switch" handlujeme ho teraz ako 'door_condition' + else if (type == "door_condition" || type === "state_of_main_switch") { + newPinValue === 0 ? value = "open" : value = "closed"; + + let door = "door_main"; + if (type === "state_of_main_switch") door = "door_em"; + + if (value === "open") { + if (SETTINGS.maintenance_mode) { + sendNotification("switchLogic", rvoTbName, door + "_open", {}, "", SEND_TO.tb, instance, door); + } else { + sendNotification("switchLogic", rvoTbName, door + "_open_without_permission", {}, "", SEND_TO.tb, instance, door); + + // 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 (value === "closed") { + if (alarmStatus == "ON") turnAlarm("off"); + sendNotification("switchLogic", rvoTbName, door + "_close", {}, "", SEND_TO.tb, instance, door); + } + + deviceStatus[type] = value; + } + + //lux sensor + else if (type == "twilight_sensor") { + //! TODO - to show nok status, if lux value is not changing more then 10 times. + //Daylight is far more than 1000. So most of the day, when it is sunshine comes just value 1000. But lux sensor is not NOK. + //This is not the case in LM. If value from LM is the same 10x, there is 99% possibility, that sensor is NOK. + value = newPinValue; + + if (controller_type === 'lm') { + value = parseFloat(newPinValue + (256 * twilight)); + + 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 && !twilightError) { + twilightError = true; + let value = twilight_sensor_array.shift(); + + newPinValue = 0; + } + else if (set.size !== 1 && twilightError) { + //sendNotification("switchLogic", rvoTbName, 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) { + 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); + } + } + + 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); + } + + deviceStatus["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 (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 }); + + //mame iba 3 istice. vyreportujeme a ohandlujeme liniu na tom istom istici ako paralelna linia (napr linia 1, paralelna s nou je linia 4, key je string "4") + // ak je 7 linii, na 1 istici je linia 1,4,7 + + if (line == 1) { + + const lineOnSameBraker = [4, 7]; + + for (var i = 0; i < lineOnSameBraker.length; i++) { + if (!relaysData.hasOwnProperty(lineOnSameBraker[i])) continue; + + 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; + reportLineStatus(lineOnSameBraker[i]); + + values[type] = value; + const tbname = relaysData[lineOnSameBraker[i]].tbname; + sendTelemetry(values, tbname); + + delete values[type]; + } + + } + else { + const lineOnSameBraker = line + 3 + ""; + + if (relaysData.hasOwnProperty(lineOnSameBraker)) { + 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; + reportLineStatus(line + 3); + + values[type] = value; + const tbname = relaysData[lineOnSameBraker].tbname; + sendTelemetry(values, tbname); + + delete values[type]; + } + } + + } + + if (value == "Off") values["status"] = "NOK"; + deviceStatus["state_of_breaker"][line] = value; + + reportLineStatus(line); + } + else return; + + values[type] = value; + + if (type == "rotary_switch_state") { + if (SETTINGS.maintenance_mode) value = "maintenance"; + value = value.toLowerCase(); + values["power_mode"] = value; + } + + if (newPinValue != previousValues[pinIndex]) previousValues[pinIndex] = newPinValue; + if (Object.keys(values).length > 0 && tbname) sendTelemetry(values, tbname); + } + + + function sendTelemetry(values, tbname, date = Date.now()) { + let dataToTb = { + [tbname]: [ + { + "ts": date, + "values": values + } + ] + }; + + tbHandler.sendToTb(dataToTb, instance); + } + + + function isObject(item) { + return (typeof item === "object" && !Array.isArray(item) && item !== null); + } + +} //end of 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 +// *|input1_01|state_of_main_switch|0|........... +// *|input1_02|rotary_switch_state|0|........... +// *|input1_03|rotary_switch_state|0|........... +// *|intut1_04|power_supply|0|........... +// *|input1_05|door_condition|0|........... +// *|input1_06|state_of_breaker|1|........... +// *|input1_07|state_of_breaker|2|........... +// *|input1_08|state_of_breaker|3|........... +// *|relay1_02|state_of_contactor|1|........... +// *|relay1_03|state_of_contactor|2|........... +// *|relay1_04|state_of_contactor|3|........... +// *|287D8776E0013CE9|temperature|0|........... + + +//! pins_data --> from UNIPI +// { +// 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 } +// } + +//! relays_data +// { +// '0': { +// line: 0, +// tbname: 'KjbN4q7JPZmexgdnz2yKQ98YAWwO0Q3BMX6ERLoV', +// contactor: 1, +// profile: '' +// }, +// '1': { +// line: 1, +// tbname: 'RMgnK93rkoAazbqdQ4yBG95Z1YXGx6pmwBeVEP2O', +// contactor: 0, +// profile: '{"intervals":[{"value":0,"end_time":"20:00","start_time":"13:00"},{"value":1,"end_time":"10:00","start_time":"20:00"},{"value":0,"end_time":"10:20","start_time":"10:00"},{"value":1,"end_time":"10:40","start_time":"10:20"},{"value":0,"end_time":"11:00","start_time":"10:40"},{"value":1,"end_time":"11:30","start_time":"11:00"},{"value":0,"end_time":"11:50","start_time":"11:30"},{"value":1,"end_time":"13:00","start_time":"11:50"}],"astro_clock":false,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' +// }, +// '2': { +// line: 2, +// tbname: 'dlE1VQjYrNx9gZRmb38gG08oLBO4qaAk2M6JPnG7', +// contactor: 0, +// profile: '{"intervals":[{"value":0,"end_time":"20:00","start_time":"13:00"},{"value":1,"end_time":"10:00","start_time":"20:00"},{"value":0,"end_time":"10:20","start_time":"10:00"},{"value":1,"end_time":"10:40","start_time":"10:20"},{"value":0,"end_time":"11:00","start_time":"10:40"},{"value":1,"end_time":"11:30","start_time":"11:00"},{"value":0,"end_time":"11:50","start_time":"11:30"},{"value":1,"end_time":"13:00","start_time":"11:50"}],"astro_clock":false,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' +// }, +// '3': { +// line: 3, +// tbname: 'vnmG4kJxaXWNBgMQq0D7Aj5e9oZzOAlr6LdR3w2V', +// contactor: 0, +// profile: '{"intervals":[{"value":0,"end_time":"20:30","start_time":"13:00"},{"value":1,"end_time":"00:10","start_time":"20:30"},{"value":0,"end_time":"13:00","start_time":"05:40"},{"value":1,"end_time":"05:40","start_time":"00:10"}],"astro_clock":true,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' +// } +// } + + + + + +// { +// "jbN4q7JPZmexgdnz2yKbWGDYAWwO0Q3BMX6ERLoV": [ +// { +// "ts": 1700409326353, +// "values": { +// "_event": { +// "type": "notice", +// "status": "new", +// "source": { +// "func": "rsPort.open()", +// "component": "1700343402190", +// "component_name": "DIDO_Controller", +// "edge": "jbN4q7JPZmexgdnz2yKbWGDYAWwO0Q3BMX6ERLoV" +// }, +// "message": "al_shariff_10.0.0.38: FLOW has been started ", +// "message_data": "" +// } +// } +// } +// ] +// } diff --git a/RVO23/flow/helper/DataToTbHandler.js b/RVO23/flow/helper/DataToTbHandler.js new file mode 100755 index 0000000..716ef7b --- /dev/null +++ b/RVO23/flow/helper/DataToTbHandler.js @@ -0,0 +1,187 @@ +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; + this.itIsNodeReadout = false; + this.sender = ""; + + // if attribute change difference is less than limit value, we do not send to tb. + this.attributeChangeLimit = { + temperature: 0.5, + Phase_1_voltage: 2, + Phase_2_voltage: 2, + Phase_3_voltage: 2, + Phase_1_current: 0.1, + Phase_2_current: 0.1, + Phase_3_current: 0.1, + Phase_1_power: 2, + Phase_2_power: 2, + Phase_3_power: 2, + total_power: 2, + total_energy: 1, + Phase_1_pow_factor: 0.1, + Phase_2_pow_factor: 0.1, + Phase_3_pow_factor: 0.1, + power_factor: 0.1, + lifetime: 2, + voltage: 2, + power: 2, + frequency: 3, + energy: 0.1, + current: 2, + inclination_x: 10, + inclination_y: 10, + inclination_z: 10 + }; + + } + + dump() { + console.log("----------------------------"); + console.log("previousValues", this.previousValues); + console.log("----------------------------"); + } + + setSender(sender) { + this.sender = sender; + } + + isEmptyObject(obj) { + for (var _ in obj) { + return false; + } + return true; + } + + + sendToTb(data, instance) { + + //not to modify data object, we do deep copy: + let dataCopy = JSON.parse(JSON.stringify(data)); + + let keys = Object.keys(dataCopy); + + if (keys.length == 0) { + if (this.debug) console.log("sendToTb received empty object", dataCopy); + return; + } + + let tbname = keys[0]; + let ts; + + let arrayOfValues = dataCopy[tbname]; + let arrayOfValuesToSend = []; + + for (let i = 0; i < arrayOfValues.length; i++) { + + ts = arrayOfValues[i].ts; + let values = this.prepareValuesForTb(tbname, ts, arrayOfValues[i].values); + + if (!this.isEmptyObject(values)) { + arrayOfValuesToSend.push({ ts: ts, values: values }); + } + + } + + if (arrayOfValuesToSend.length == 0) { + //if(this.debug) console.log("data not sent - empty array"); + return; + } + + this.messageCounter++; + + let dataToTbModified = { + [tbname]: arrayOfValuesToSend + } + + //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); + instance.send(this.index, dataToTbModified); + } + + + getDiffTimestamp(key) { + //TODO set different value for given key!!! + //if(key == "status") this.timeToHoldTbValue = 2*60*60;//2h + return this.timeToHoldTbValue * 1000; + } + + + prepareValuesForTb(tbname, timestamp, values) { + + let keys = Object.keys(values); + + if (keys.includes("lifetime")) this.itIsNodeReadout = true; + + if (!this.previousValues.hasOwnProperty(tbname)) { + this.previousValues[tbname] = {}; + } + + //if(this.debug) console.log("prepareValuesForTb", tbname, timestamp, values); + + for (let i = 0; i < keys.length; i++) { + + let key = keys[i]; + let value = values[key]; + + if (!this.previousValues[tbname].hasOwnProperty(key)) { + this.previousValues[tbname][key] = { ts: timestamp, value: value }; + continue; + } + + // attributeData ==> {voltage: {ts:333333, value:5}} + let attributeData = this.previousValues[tbname][key]; + let attributeToChange = false; + if (key in this.attributeChangeLimit) attributeToChange = true; + let limit = this.attributeChangeLimit[key]; + let timestampDiffToRemoveKey; + + //this will ensure "node statecode" will be sent just once an hour + if (this.itIsNodeReadout && key === "statecode") { + attributeData.value = value; + this.itIsNodeReadout = false; + timestampDiffToRemoveKey = 1 * 60 * 60 * 1000; // 1 hour + } + + if (key === "twilight_sensor" && value > 100) { + attributeData.value = value; + } + + //if edge, master or node version do not change, send just once a day: + if (["edge_fw_version", "master_node_version", "fw_version"].includes(key)) { + timestampDiffToRemoveKey = 24 * 60 * 60 * 1000; + } + + if (attributeData.value === value || attributeToChange && Math.abs(attributeData.value - value) < limit) { + + let diff = timestamp - attributeData.ts; + if (!timestampDiffToRemoveKey) timestampDiffToRemoveKey = this.getDiffTimestamp(key); + + if (diff > timestampDiffToRemoveKey) { + attributeData.ts = Date.now(); + //if(this.debug) console.log(this.sender + ": update ts for key", key, "diff is", diff, "messageCounter", this.messageCounter); + } + else { + delete values[key]; + //if(this.debug) console.log(this.sender + ": delete key", key, "diff is", diff, "messageCounter", this.messageCounter, timestampDiffToRemoveKey); + } + } + else { + attributeData.value = value; + attributeData.ts = timestamp; + } + + } + + return values; + } +} + +module.exports = DataToTbHandler; + diff --git a/RVO23/flow/helper/ErrorToServiceHandler.js b/RVO23/flow/helper/ErrorToServiceHandler.js new file mode 100755 index 0000000..2b27c32 --- /dev/null +++ b/RVO23/flow/helper/ErrorToServiceHandler.js @@ -0,0 +1,91 @@ +const { MD5 } = require('./md5.js'); +const { networkInterfaces } = require('os'); + +class ErrorToServiceHandler { + constructor() { + this.previousValues = {}; + + this.project_id = undefined; + + const nets = networkInterfaces(); + this.ipAddresses = {}; + + for (const name of Object.keys(nets)) { + for (const net of nets[name]) { + // Skip over non-IPv4 and internal (i.e. 127.0.0.1) addresses + if (net.family === 'IPv4' && !net.internal) { + if (!this.ipAddresses[name]) { + this.ipAddresses[name] = []; + } + this.ipAddresses[name].push(net.address); + } + } + } + } + + setProjectId(project_id) { + this.project_id = project_id; + } + + processMessage(message, seconds) { + if (Array.isArray(message)) message = message.join(', '); + + let key = MD5(message); + let ts = Date.now(); + + //keep in memory - default value is 1h + if (seconds === undefined) seconds = 60 * 60; + + if (!this.previousValues.hasOwnProperty(key)) { + this.previousValues[key] = { ts: ts, duration: seconds }; + } + + let diff = (ts - this.previousValues[key].ts); + if (diff < this.previousValues[key].duration * 1000) return false; + + this.previousValues[key].ts = ts; + + return message; + } + + sendMessageToService(message, seconds, message_type) { + + // if error occures too early FLOW.GLOBALS.settings.project_id is still undefined + if (this.project_id === undefined) { + console.log("ErrorToServiceHandler.js: no project_id"); + return; + } + + let f = this.processMessage(message, seconds); + if (f === false) return; + + if (message_type === undefined) message_type = "error_message"; + + let toService = { + id: this.project_id, + ipAddresses: this.ipAddresses + }; + + //js_error || error_message + toService[message_type] = message; + + console.log("ErrorToServiceHandler------------------------>send to service", toService); + + RESTBuilder.make(function(builder) { + builder.method('POST'); + builder.post(toService); + builder.url('http://192.168.252.2:8004/sentmessage'); + + builder.callback(function(err, response, output) { + console.log("process.on error send", err, response, output, toService); + }); + }); + + } +} + +const errorHandler = new ErrorToServiceHandler(); + + +module.exports = errorHandler; +//module.exports = ErrorToServiceHandler; diff --git a/RVO23/flow/helper/db_helper.js b/RVO23/flow/helper/db_helper.js new file mode 100755 index 0000000..40e796c --- /dev/null +++ b/RVO23/flow/helper/db_helper.js @@ -0,0 +1,44 @@ +function promisifyBuilder(builder) +{ + return new Promise((resolve, reject) => { + + try{ + + builder.callback(function(err, response) { + + if(err != null) reject(err); + resolve(response); + }); + + } catch (error) { + reject(error); + } + }) +} + +function makeMapFromDbResult(response, ...keys) +{ + let s = "-"; + let data = {}; + + for(let i = 0; i < response.length; i++) + { + let record = response[i]; + + let k = []; + for(let j = 0; j < keys.length; j++) + { + k.push( record[keys[j]] ); + } + + let key = k.join(s); + data[ key ] = record; + } + + return data; +} + +module.exports = { + promisifyBuilder, + makeMapFromDbResult + } \ No newline at end of file diff --git a/RVO23/flow/helper/logger.js b/RVO23/flow/helper/logger.js new file mode 100755 index 0000000..2585639 --- /dev/null +++ b/RVO23/flow/helper/logger.js @@ -0,0 +1,30 @@ +//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/RVO23/flow/helper/md5.js b/RVO23/flow/helper/md5.js new file mode 100755 index 0000000..d3b0480 --- /dev/null +++ b/RVO23/flow/helper/md5.js @@ -0,0 +1,5 @@ +function MD5(d){var r = M(V(Y(X(d),8*d.length)));return r.toLowerCase()};function M(d){for(var _,m="0123456789ABCDEF",f="",r=0;r>>4&15)+m.charAt(15&_);return f}function X(d){for(var _=Array(d.length>>2),m=0;m<_.length;m++)_[m]=0;for(m=0;m<8*d.length;m+=8)_[m>>5]|=(255&d.charCodeAt(m/8))<>5]>>>m%32&255);return _}function Y(d,_){d[_>>5]|=128<<_%32,d[14+(_+64>>>9<<4)]=_;for(var m=1732584193,f=-271733879,r=-1732584194,i=271733878,n=0;n>16)+(_>>16)+(m>>16)<<16|65535&m}function bit_rol(d,_){return d<<_|d>>>32-_} + +module.exports = { + MD5 +} \ No newline at end of file diff --git a/RVO23/flow/helper/notification_reporter.js b/RVO23/flow/helper/notification_reporter.js new file mode 100755 index 0000000..839c12c --- /dev/null +++ b/RVO23/flow/helper/notification_reporter.js @@ -0,0 +1,121 @@ +//key is device, value = message {} +let sentValues = {}; +let notificationsData = null; +let rvoName; + +//sendNotification("CMD Manager: process cmd", SETTINGS.rvoTbName, "dimming_profile_was_successfully_received_by_node", { node: node }, "", SEND_TO.tb, instance); + +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 +}; + +function getKey(map, val) { + return Object.keys(map).findItem(key => map[key] === val); +} + +//https://stackoverflow.com/questions/41117799/string-interpolation-on-variable +var template = (tpl, args) => tpl.replace(/\${(\w+)}/g, (_, v) => args[v]); + + +function initNotification() { + notificationsData = FLOW.GLOBALS.notificationsData; + rvoName = FLOW.GLOBALS.settings.rvo_name; +} + + +function sendNotification(func, device, key, params, extra, tb_output, instance, saveKey) { + + let storeToSendValues = true; + if (saveKey == undefined) storeToSendValues = false; + + let weight = ""; + let message = {}; + + let notification = notificationsData[key]; + + if (notification) { + weight = notification.weight.toLowerCase(); + + Object.keys(notification).forEach(item => { + if (["en", "sk", "de", "cz", "it", "es"].includes(item)) { + message[item] = rvoName + ": " + template(notification[item], params); + } + }) + } + else { + //console.error("sendNotification: Notifications: undefined key", key, func, notificationsData); + console.error("sendNotification: Notifications: undefined key", key, func); + return false; + } + + //detect invalid err weight + if (getKey(ERRWEIGHT, weight) == undefined) { + console.error("sendNotification: Notifications: undefined weight", weight, key, func); + return false; + } + + if (sentValues.hasOwnProperty(saveKey)) { + if (JSON.stringify(sentValues[saveKey]) == JSON.stringify(message)) { + return false; + } + } + + if (sentValues[saveKey] == undefined) { + if (storeToSendValues) { + //do not send - flow is was started + sentValues[saveKey] = message; + return false; + } + } + + if (storeToSendValues) sentValues[saveKey] = message; + + let content = { + "type": weight, + "status": "new", + "source": { + "func": func, + "component": instance.id, + "component_name": instance.name, + "edge": device + }, + "message": message, + "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 + + return true; + +} + +module.exports = { + sendNotification, + ERRWEIGHT, + initNotification +} + diff --git a/RVO23/flow/helper/register.js b/RVO23/flow/helper/register.js new file mode 100755 index 0000000..fc1d008 --- /dev/null +++ b/RVO23/flow/helper/register.js @@ -0,0 +1,144 @@ +/* +0 - cislo registra / prikaz +1 - recepient - 0 = master, 1 = slave (slave je automaticky group a broadcast) +2 - r/rw - read/write +3- register name - nazov registra / prikazu (len pre info - zobrazenie v aplikacii) + +4,5,6,7, - jednotlive byte-y - nazov byte-u +4-7 - RES. a prazdny string "" sa nezobrazia!!! +*/ + +//124 zaznamov +const registers = [ + ["0","1","R","Status","","",""], + ["1","1","RW","Dimming","R-Channel ","G-Channel","B-Channel ","W - Channel"], + ["2","1","R","Device types","","",".",""], + ["3","1","RW","Group addresses 1-4","Groups Add. 4","Groups Add. 3","Groups Add. 2","Groups Add. 1"], + ["4","1","RW","Group addresses 5-8","Groups Add. 8","Groups Add. 7","Groups Add. 6","Groups Add. 5"], + ["5","1","RW","Serial number (MAC)","","","",""], + ["6","1","RW","Time of dusk","HH","MM","SS","EXTRA"], + ["7","1","RW","Time of dawn","HH","MM","SS","EXTRA"], + ["8","1","RW","Time Schedule settings","TBD","TBD","Movement sensor","Time Schedule"], + ["9","1","RW","TS1 Time point 1","HH","MM","SS","Ext. Device"], + ["10","1","RW","TS1 Time point 1 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["11","1","RW","TS1 Time point 2","HH","MM","SS","Ext. Device"], + ["12","1","RW","TS1 Time point 2 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["13","1","RW","TS1 Time point 3","HH","MM","SS","Ext. Device"], + ["14","1","RW","TS1 Time point 3 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["15","1","RW","TS1 Time point 4","HH","MM","SS","Ext. Device"], + ["16","1","RW","TS1 Time point 4 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["17","1","RW","TS1 Time point 5","HH","MM","SS","Ext. Device"], + ["18","1","RW","TS1 Time point 5 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["19","1","RW","TS1 Time point 6","HH","MM","SS","Ext. Device"], + ["20","1","RW","TS1 Time point 6 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["21","1","RW","TS1 Time point 7","HH","MM","SS","Ext. Device"], + ["22","1","RW","TS1 Time point 7 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["23","1","RW","TS1 Time point 8","HH","MM","SS","Ext. Device"], + ["24","1","RW","TS1 Time point 8 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["25","1","RW","TS1 Time point 9","HH","MM","SS","Ext. Device"], + ["26","1","RW","TS1 Time point 9 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["27","1","RW","TS1 Time point 10","HH","MM","SS","Ext. Device"], + ["28","1","RW","TS1 Time point 10 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["29","1","RW","TS1 Time point 11","HH","MM","SS","Ext. Device"], + ["30","1","RW","TS1 Time point 11 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["31","1","RW","TS1 Time point 12","HH","MM","SS","Ext. Device"], + ["32","1","RW","TS1 Time point 12 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["33","1","RW","TS1 Time point 13","HH","MM","SS","Ext. Device"], + ["34","1","RW","TS1 Time point 13 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["35","1","RW","TS1 Time point 14","HH","MM","SS","Ext. Device"], + ["36","1","RW","TS1 Time point 14 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["37","1","RW","TS1 Time point 15","HH","MM","SS","Ext. Device"], + ["38","1","RW","TS1 Time point 15 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["39","1","RW","TS1 Time point 16","HH","MM","SS","Ext. Device"], + ["40","1","RW","TS1 Time point 16 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["41","1","RW","TS2 Time point 1","HH","MM","SS","Ext. Device"], + ["42","1","RW","TS2 Time point 1 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["43","1","RW","TS2 Time point 2","HH","MM","SS","Ext. Device"], + ["44","1","RW","TS2 Time point 2 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["45","1","RW","TS2 Time point 3","HH","MM","SS","Ext. Device"], + ["46","1","RW","TS2 Time point 3 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["47","1","RW","TS2 Time point 4","HH","MM","SS","Ext. Device"], + ["48","1","RW","TS2 Time point 4 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["49","1","RW","TS2 Time point 5","HH","MM","SS","Ext. Device"], + ["50","1","RW","TS2 Time point 5 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["51","1","RW","TS2 Time point 6","HH","MM","SS","Ext. Device"], + ["52","1","RW","TS2 Time point 6 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["53","1","RW","TS2 Time point 7","HH","MM","SS","Ext. Device"], + ["54","1","RW","TS2 Time point 7 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["55","1","RW","TS2 Time point 8","HH","MM","SS","Ext. Device"], + ["56","1","RW","TS2 Time point 8 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["57","1","RW","TS2 Time point 9","HH","MM","SS","Ext. Device"], + ["58","1","RW","TS2 Time point 9 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["59","1","RW","TS2 Time point 10","HH","MM","SS","Ext. Device"], + ["60","1","RW","TS2 Time point 10 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["61","1","RW","TS2 Time point 11","HH","MM","SS","Ext. Device"], + ["62","1","RW","TS2 Time point 11 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["63","1","RW","TS2 Time point 12","HH","MM","SS","Ext. Device"], + ["64","1","RW","TS2 Time point 12 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["65","1","RW","TS2 Time point 13","HH","MM","SS","Ext. Device"], + ["66","1","RW","TS2 Time point 13 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["67","1","RW","TS2 Time point 14","HH","MM","SS","Ext. Device"], + ["68","1","RW","TS2 Time point 14 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["69","1","RW","TS2 Time point 15","HH","MM","SS","Ext. Device"], + ["70","1","RW","TS2 Time point 15 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["71","1","RW","TS2 Time point 16","HH","MM","SS","Ext. Device"], + ["72","1","RW","TS2 Time point 16 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["73","1","RW","Power meter status","TBD","","",""], + ["74","1","R","Input Voltage","","","",""], + ["75","1","R","Input Current","","","",""], + ["76","1","R","Input Power","","","",""], + ["77","1","R","Cos phi","","","",""], + ["78","1","R","Frequency","","","",""], + ["79","1","RW","Energy","","","",""], + ["80","1","RW","Lifetime","","","",""], + ["81","1","RW","Power on cycles (input)","","","",""], + ["82","1","RW","Power on cycles (relay)","","","",""], + ["83","1","R","Time since last power on","","","",""], + ["84","1","R","Accelerometer data","","","",""], + ["85","1","RW","GPS latitude","pos/neg","deg","min ","sec"], + ["86","1","RW","GPS longitude","pos/neg","deg","min ","sec"], + ["87","1","RW","Actual time","HH","MM","SS","RES."], + ["88","1","RW","Actual date","Day of week","Day","Month","Year"], + ["89","1","R","Production data 1","","","",""], + ["90","1","R","Production data 2","","","",""], + ["91","1","RW","Network ID","NID3","NID2","NID1","NID0"], + ["95","1","RW","Actual Lux level from cabinet","RES.","RES.","HB","LB"], + ["96","1","RW","Threshold lux level","Dusk HB","Dusk LB","Dawn HB","Dawn LB"], + ["97","1","RW","Adjust period","Dusk HB","Dusk LB","Dawn HB","Dawn LB"], + ["98","1","RW","Offset","RES.","RES.","Dusk","Dawn"], + ["99","1","RW","CCT min/max range","max-H","max-L","min-H","min-L"], + ["100","1","RW","DALI interface","Cmd ID","Add","Cmd","Resp"], + ["101","1","RW","Module FW ver","v1","v2","v3","v4"], + ["102","1","RW","Module MAC-H","unused","unused","M1","M2"], + ["103","1","RW","Module MAC-L","M3","M4","M5","M6"], + ["122","1","R","FW update status/control register","Byte3","Byte2","Byte1","Byte0"], + ["123","1","R","FW update - data index","Byte3","Byte2","Byte1","Byte0"], + ["124","1","R","FW update - data","Byte3","Byte2","Byte1","Byte0"], + ["0","0","R","Status","","","",""], + ["1","0","RW","Control register","RES.","RES.","RES.","init mode enable"], + ["2","0","R","Device types","","","",""], + ["3","0","R","Serial number (MAC)","","","",""], + ["4","0","R","Production data 1","","","",""], + ["5","0","R","Production data 2","","","",""], + ["6","0","RW","Network ID","NID3","NID2","NID1","NID0"], + ["7","0","RW","RS232 settings","param.","param.","Baudrate H","Baudrate L"], + ["8","0","R","Accelerometer data","","","",""], + ["9","0","RW","Module FW ver","v1","v2","v3","v4"], + ["10","0","RW","Module MAC-H","unused","unused","M1","M2"], + ["11","0","RW","Module MAC-L","M3","M4","M5","M6"], + ["32","0","RW","FW update status/control register","Byte3","Byte2","Byte1","Byte0"], + ["33","0","RW","FW update - data index","Byte3","Byte2","Byte1","Byte0"], + ["34","0","RW","FW update - data","Byte3","Byte2","Byte1","Byte0"], + ["125","0","RW","Debug Register","Byte3","Byte2","Byte1","Byte0"], + ["126","0","RW","Network Control Register","Byte3","Byte2","Byte1","Byte0"], + ["127","0","R","Network Status Register","Byte3","Byte2","Byte1","Byte0"], + ["128","0","RW","Node XX Serial Number Register","SER3","SER2","SER1","SER0"], + ["256","0","R","Node XX Network Status Register","","","",""] +]; + +let register = {}; + +module.exports = { + registers, + register +} \ No newline at end of file diff --git a/RVO23/flow/helper/serialport_helper.js b/RVO23/flow/helper/serialport_helper.js new file mode 100755 index 0000000..7f5920d --- /dev/null +++ b/RVO23/flow/helper/serialport_helper.js @@ -0,0 +1,99 @@ +const { exec } = require('child_process'); + +function openPort(port) { + return new Promise((resolve, reject) => { + + var callbackError = function(err) { + port.removeListener('error', callbackError); + port.removeListener('open', callbackError); + + reject(err.message); + }; + + var callbackOpen = function(data) { + port.removeListener('error', callbackError); + port.removeListener('open', callbackOpen); + + resolve("port open: ok"); + }; + + port.on('error', callbackError); + port.on('open', callbackOpen); + + port.open(); + + }) +} + +function runSyncExec(command) { + return new Promise((resolve, reject) => { + + exec(command, (error, stdout, stderr) => { + if (error == null) resolve(stdout); + reject(error); + }); + + }) +} + +async function writeData(port, data, readbytes, timeout) { + return new Promise((resolve, reject) => { + + // 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) { + + port.write(Buffer.from(data), function(err) { + if (err) { + reject(err.message); + } + }); + + 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 +} diff --git a/RVO23/flow/helper/suncalc.js b/RVO23/flow/helper/suncalc.js new file mode 100755 index 0000000..c9ca56d --- /dev/null +++ b/RVO23/flow/helper/suncalc.js @@ -0,0 +1,317 @@ +/* + (c) 2011-2015, Vladimir Agafonkin + SunCalc is a JavaScript library for calculating sun/moon position and light phases. + https://github.com/mourner/suncalc +*/ + +(function () { 'use strict'; + +// shortcuts for easier to read formulas + +var PI = Math.PI, + sin = Math.sin, + cos = Math.cos, + tan = Math.tan, + asin = Math.asin, + atan = Math.atan2, + acos = Math.acos, + rad = PI / 180; + +// sun calculations are based on http://aa.quae.nl/en/reken/zonpositie.html formulas + + +// date/time constants and conversions + +var dayMs = 1000 * 60 * 60 * 24, + J1970 = 2440588, + J2000 = 2451545; + +function toJulian(date) { return date.valueOf() / dayMs - 0.5 + J1970; } +function fromJulian(j) { return new Date((j + 0.5 - J1970) * dayMs); } +function toDays(date) { return toJulian(date) - J2000; } + + +// general calculations for position + +var e = rad * 23.4397; // obliquity of the Earth + +function rightAscension(l, b) { return atan(sin(l) * cos(e) - tan(b) * sin(e), cos(l)); } +function declination(l, b) { return asin(sin(b) * cos(e) + cos(b) * sin(e) * sin(l)); } + +function azimuth(H, phi, dec) { return atan(sin(H), cos(H) * sin(phi) - tan(dec) * cos(phi)); } +function altitude(H, phi, dec) { return asin(sin(phi) * sin(dec) + cos(phi) * cos(dec) * cos(H)); } + +function siderealTime(d, lw) { return rad * (280.16 + 360.9856235 * d) - lw; } + +function astroRefraction(h) { + if (h < 0) // the following formula works for positive altitudes only. + h = 0; // if h = -0.08901179 a div/0 would occur. + + // formula 16.4 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + // 1.02 / tan(h + 10.26 / (h + 5.10)) h in degrees, result in arc minutes -> converted to rad: + return 0.0002967 / Math.tan(h + 0.00312536 / (h + 0.08901179)); +} + +// general sun calculations + +function solarMeanAnomaly(d) { return rad * (357.5291 + 0.98560028 * d); } + +function eclipticLongitude(M) { + + var C = rad * (1.9148 * sin(M) + 0.02 * sin(2 * M) + 0.0003 * sin(3 * M)), // equation of center + P = rad * 102.9372; // perihelion of the Earth + + return M + C + P + PI; +} + +function sunCoords(d) { + + var M = solarMeanAnomaly(d), + L = eclipticLongitude(M); + + return { + dec: declination(L, 0), + ra: rightAscension(L, 0) + }; +} + + +var SunCalc = {}; + + +// calculates sun position for a given date and latitude/longitude + +SunCalc.getPosition = function (date, lat, lng) { + + var lw = rad * -lng, + phi = rad * lat, + d = toDays(date), + + c = sunCoords(d), + H = siderealTime(d, lw) - c.ra; + + return { + azimuth: azimuth(H, phi, c.dec), + altitude: altitude(H, phi, c.dec) + }; +}; + + +// sun times configuration (angle, morning name, evening name) + +var times = SunCalc.times = [ + [-0.833, 'sunrise', 'sunset' ], + [ -0.3, 'sunriseEnd', 'sunsetStart' ], + [ -6, 'dawn', 'dusk' ], + [ -12, 'nauticalDawn', 'nauticalDusk'], + [ -18, 'nightEnd', 'night' ], + [ 6, 'goldenHourEnd', 'goldenHour' ] +]; + +// adds a custom time to the times config + +SunCalc.addTime = function (angle, riseName, setName) { + times.push([angle, riseName, setName]); +}; + + +// calculations for sun times + +var J0 = 0.0009; + +function julianCycle(d, lw) { return Math.round(d - J0 - lw / (2 * PI)); } + +function approxTransit(Ht, lw, n) { return J0 + (Ht + lw) / (2 * PI) + n; } +function solarTransitJ(ds, M, L) { return J2000 + ds + 0.0053 * sin(M) - 0.0069 * sin(2 * L); } + +function hourAngle(h, phi, d) { return acos((sin(h) - sin(phi) * sin(d)) / (cos(phi) * cos(d))); } +function observerAngle(height) { return -2.076 * Math.sqrt(height) / 60; } + +// returns set time for the given sun altitude +function getSetJ(h, lw, phi, dec, n, M, L) { + + var w = hourAngle(h, phi, dec), + a = approxTransit(w, lw, n); + return solarTransitJ(a, M, L); +} + + +// calculates sun times for a given date, latitude/longitude, and, optionally, +// the observer height (in meters) relative to the horizon + +SunCalc.getTimes = function (date, lat, lng, height) { + + height = height || 0; + + var lw = rad * -lng, + phi = rad * lat, + + dh = observerAngle(height), + + d = toDays(date), + n = julianCycle(d, lw), + ds = approxTransit(0, lw, n), + + M = solarMeanAnomaly(ds), + L = eclipticLongitude(M), + dec = declination(L, 0), + + Jnoon = solarTransitJ(ds, M, L), + + i, len, time, h0, Jset, Jrise; + + + var result = { + solarNoon: fromJulian(Jnoon), + nadir: fromJulian(Jnoon - 0.5) + }; + + for (i = 0, len = times.length; i < len; i += 1) { + time = times[i]; + h0 = (time[0] + dh) * rad; + + Jset = getSetJ(h0, lw, phi, dec, n, M, L); + Jrise = Jnoon - (Jset - Jnoon); + + result[time[1]] = fromJulian(Jrise); + result[time[2]] = fromJulian(Jset); + } + + return result; +}; + + +// moon calculations, based on http://aa.quae.nl/en/reken/hemelpositie.html formulas + +function moonCoords(d) { // geocentric ecliptic coordinates of the moon + + var L = rad * (218.316 + 13.176396 * d), // ecliptic longitude + M = rad * (134.963 + 13.064993 * d), // mean anomaly + F = rad * (93.272 + 13.229350 * d), // mean distance + + l = L + rad * 6.289 * sin(M), // longitude + b = rad * 5.128 * sin(F), // latitude + dt = 385001 - 20905 * cos(M); // distance to the moon in km + + return { + ra: rightAscension(l, b), + dec: declination(l, b), + dist: dt + }; +} + +SunCalc.getMoonPosition = function (date, lat, lng) { + + var lw = rad * -lng, + phi = rad * lat, + d = toDays(date), + + c = moonCoords(d), + H = siderealTime(d, lw) - c.ra, + h = altitude(H, phi, c.dec), + // formula 14.1 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + pa = atan(sin(H), tan(phi) * cos(c.dec) - sin(c.dec) * cos(H)); + + h = h + astroRefraction(h); // altitude correction for refraction + + return { + azimuth: azimuth(H, phi, c.dec), + altitude: h, + distance: c.dist, + parallacticAngle: pa + }; +}; + + +// calculations for illumination parameters of the moon, +// based on http://idlastro.gsfc.nasa.gov/ftp/pro/astro/mphase.pro formulas and +// Chapter 48 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + +SunCalc.getMoonIllumination = function (date) { + + var d = toDays(date || new Date()), + s = sunCoords(d), + m = moonCoords(d), + + sdist = 149598000, // distance from Earth to Sun in km + + phi = acos(sin(s.dec) * sin(m.dec) + cos(s.dec) * cos(m.dec) * cos(s.ra - m.ra)), + inc = atan(sdist * sin(phi), m.dist - sdist * cos(phi)), + angle = atan(cos(s.dec) * sin(s.ra - m.ra), sin(s.dec) * cos(m.dec) - + cos(s.dec) * sin(m.dec) * cos(s.ra - m.ra)); + + return { + fraction: (1 + cos(inc)) / 2, + phase: 0.5 + 0.5 * inc * (angle < 0 ? -1 : 1) / Math.PI, + angle: angle + }; +}; + + +function hoursLater(date, h) { + return new Date(date.valueOf() + h * dayMs / 24); +} + +// calculations for moon rise/set times are based on http://www.stargazing.net/kepler/moonrise.html article + +SunCalc.getMoonTimes = function (date, lat, lng, inUTC) { + var t = new Date(date); + if (inUTC) t.setUTCHours(0, 0, 0, 0); + else t.setHours(0, 0, 0, 0); + + var hc = 0.133 * rad, + h0 = SunCalc.getMoonPosition(t, lat, lng).altitude - hc, + h1, h2, rise, set, a, b, xe, ye, d, roots, x1, x2, dx; + + // go in 2-hour chunks, each time seeing if a 3-point quadratic curve crosses zero (which means rise or set) + for (var i = 1; i <= 24; i += 2) { + h1 = SunCalc.getMoonPosition(hoursLater(t, i), lat, lng).altitude - hc; + h2 = SunCalc.getMoonPosition(hoursLater(t, i + 1), lat, lng).altitude - hc; + + a = (h0 + h2) / 2 - h1; + b = (h2 - h0) / 2; + xe = -b / (2 * a); + ye = (a * xe + b) * xe + h1; + d = b * b - 4 * a * h1; + roots = 0; + + if (d >= 0) { + dx = Math.sqrt(d) / (Math.abs(a) * 2); + x1 = xe - dx; + x2 = xe + dx; + if (Math.abs(x1) <= 1) roots++; + if (Math.abs(x2) <= 1) roots++; + if (x1 < -1) x1 = x2; + } + + if (roots === 1) { + if (h0 < 0) rise = i + x1; + else set = i + x1; + + } else if (roots === 2) { + rise = i + (ye < 0 ? x2 : x1); + set = i + (ye < 0 ? x1 : x2); + } + + if (rise && set) break; + + h0 = h2; + } + + var result = {}; + + if (rise) result.rise = hoursLater(t, rise); + if (set) result.set = hoursLater(t, set); + + if (!rise && !set) result[ye > 0 ? 'alwaysUp' : 'alwaysDown'] = true; + + return result; +}; + + +// export as Node module / AMD module / browser variable +if (typeof exports === 'object' && typeof module !== 'undefined') module.exports = SunCalc; +else if (typeof define === 'function' && define.amd) define(SunCalc); +else window.SunCalc = SunCalc; + +}()); diff --git a/RVO23/flow/helper/utils.js b/RVO23/flow/helper/utils.js new file mode 100755 index 0000000..dbffe45 --- /dev/null +++ b/RVO23/flow/helper/utils.js @@ -0,0 +1,161 @@ +const fs = require('fs').promises; + +function bytesToInt(bytes, numberOfBytes) { + let buffer = []; + if (Array.isArray(bytes)) { + buffer = bytes.slice(0); + if (numberOfBytes != undefined) { + buffer = bytes.slice(bytes.length - numberOfBytes); + } + } + else buffer.push(bytes); + + let result = 0; + for (let i = 0; i < buffer.length; i++) { + result = (result << 8) | buffer[i]; + } + + return result >>> 0; //ensure it's an unsigned 32-bit number +} + +function resizeArray(arr, newSize, defaultValue) { + while (newSize > arr.length) + arr.push(defaultValue); + arr.length = newSize; +} + +longToByteArray = function(/*long*/long) { + // we want to represent the input as a 8-bytes array + var byteArray = [0, 0, 0, 0, 0, 0, 0, 0]; + + for (var index = 0; index < byteArray.length; index++) { + var byte = long & 0xff; + byteArray[index] = byte; + long = (long - byte) / 256; + } + + return byteArray; +}; + +function addDays(date, days) { + var result = new Date(date); + result.setDate(result.getDate() + days); + return result; +} + +/* +sleep(2000).then(() => { + // Do something after the sleep! + + +}); +*/ + +function sleep(time) { + return new Promise((resolve) => setTimeout(resolve, time)); +} + +function isEmptyObject(obj) { + for (var name in obj) { + return false; + } + return true; +} + +function emptyJsObject(jsObject) { + Object.keys(jsObject).forEach(key => delete jsObject[key]); +} + +function convertUTCDateToLocalDate(date) { + var newDate = new Date(date); + newDate.setMinutes(date.getMinutes() + date.getTimezoneOffset()); + return newDate; +} + +function addZeroBefore(n) { + return (n < 10 ? '0' : '') + n; +} + + +/** + * Asynchronously writes data to a file. + * + * @param {string} filePath The path to the file. + * @param {string} data The data to write to the file. + * @param {boolean} [append=false] If true, appends the data to the file. If false, it overwrites the file. + */ +async function writeToFile(filePath, data, append = false) { + if (typeof data !== 'string') data = JSON.stringify(data, null, 2); + try { + if (append) { + // Append the data to the end of the file. This is the simplest way to append. + await fs.appendFile(filePath, data, 'utf8'); + console.log(`Successfully appended data to ${filePath} using fs.appendFile.`); + } else { + // Overwrite the file with the new data. + await fs.writeFile(filePath, data, 'utf8'); + console.log(`Successfully wrote (overwrote) data to ${filePath} using fs.writeFile.`); + } + } catch (error) { + console.error(`Error writing to file ${filePath}:`, error); + } +} + + + /** + * Checks if an item is present in an array and adds it if it's not. + * * @param {Array} arr The array to check. + * @param {*} item The item to add. + * @returns {Array} The modified array. + */ +const addToArrayIfUnique = (arr, item) => { + if (!arr.includes(item)) { + arr.push(item); + } + return arr; +}; + + +var convertBase = function() { + + function convertBase(baseFrom, baseTo) { + return function(num) { + return parseInt(num, baseFrom).toString(baseTo); + + }; + } + + // binary to decimal + convertBase.bin2dec = convertBase(2, 10); + + // binary to hexadecimal + convertBase.bin2hex = convertBase(2, 16); + + // decimal to binary + convertBase.dec2bin = convertBase(10, 2); + + // decimal to hexadecimal + convertBase.dec2hex = convertBase(10, 16); + + // hexadecimal to binary + convertBase.hex2bin = convertBase(16, 2); + + // hexadecimal to decimal + convertBase.hex2dec = convertBase(16, 10); + + return convertBase; +}(); + +module.exports = { + bytesToInt, + longToByteArray, + addDays, + addZeroBefore, + resizeArray, + isEmptyObject, + emptyJsObject, + sleep, + convertUTCDateToLocalDate, + writeToFile, + addToArrayIfUnique +} diff --git a/RVO23/flow/httprequest.js b/RVO23/flow/httprequest.js new file mode 100755 index 0000000..469c8cb --- /dev/null +++ b/RVO23/flow/httprequest.js @@ -0,0 +1,137 @@ +exports.id = 'httprequest'; +exports.title = 'HTTP Request'; +exports.group = 'HTTP'; +exports.color = '#5D9CEC'; +exports.input = true; +exports.version = '2.0.1'; +exports.output = 1; +exports.author = 'Peter Širka'; +exports.icon = 'cloud-upload'; + +exports.html = `
+
@(URL address)
+
+
+
@(HTTP method)
+
+
+
@(Serialization)
+
+
+
@(Download the content in chunks)
+
@(Keep persistent cookies)
+
@(Disable DNS cache)
+
@(Keep alive connection)
+
+
+
+
@(Custom headers)
+
@(Cookies)
+
+
+
+ +
+
+
+
@(User)
+
+
+
@(Password)
+
+
+
+
+
`; + +exports.readme = `# Request + +This component creates a request with received data. + +__Response:__ +\`\`\`javascript +{ + data: String, + headers: Object, + status: Number, + host: String +} +\`\`\` + +__Dynamic arguments__: +Are performed via FlowData repository and can be used for URL address or for custom headers/cookies/auth. Use \`repository\` component for creating of dynamic arguments. Dynamic values are replaced in the form \`{key}\`: + +- url address e.g. \`https://.../{key}/\` +- headers values e.g. \`{token}\` +- cookies values e.g. \`{token}\``; + +exports.install = function(instance) { + + var can = false; + var flags = null; + var cookies2 = null; + + instance.on('data', function(response) { + can && instance.custom.send(response); + }); + + instance.custom.send = function(response) { + var options = instance.options; + + var headers = null; + var cookies = null; + + options.headers && Object.keys(options.headers).forEach(function(key) { + !headers && (headers = {}); + headers[key] = response.arg(options.headers[key]); + }); + + if (options.username && options.userpassword) { + !headers && (headers = {}); + headers['Authorization'] = 'Basic ' + U.createBuffer(response.arg(options.username + ':' + options.userpassword)).toString('base64'); + } + + options.cookies && Object.keys(options.cookies).forEach(function(key) { + !cookies && (cookies = {}); + cookies[key] = response.arg(options.cookies[key]); + }); + + if (options.chunks) { + U.download(response.arg(options.url), flags, options.stringify === 'none' ? null : response.data, function(err, response) { + response.on('data', (chunks) => instance.send2(chunks)); + }, cookies || cookies2, headers); + } else { + U.request(response.arg(options.url), flags, options.stringify === 'none' ? null : response.data, 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) + instance.error(err, response); + }, cookies || cookies2, headers); + } + }; + + instance.reconfigure = function() { + var options = instance.options; + can = options.url && options.url && options.method && options.stringify ? true : false; + instance.status(can ? '' : 'Not configured', can ? undefined : 'red'); + + if (!can) + return; + + flags = []; + flags.push(options.method.toLowerCase()); + options.stringify === 'json' && flags.push('json'); + options.stringify === 'raw' && flags.push('raw'); + options.keepalive && flags.push('keepalive'); + !options.nodns && flags.push('dnscache'); + if (options.persistentcookies) { + flags.push('cookies'); + cookies2 = {}; + } else + cookies2 = null; + }; + + instance.on('options', instance.reconfigure); + instance.reconfigure(); +}; \ No newline at end of file diff --git a/RVO23/flow/httpresponse.js b/RVO23/flow/httpresponse.js new file mode 100755 index 0000000..160a3bb --- /dev/null +++ b/RVO23/flow/httpresponse.js @@ -0,0 +1,76 @@ +exports.id = 'httpresponse'; +exports.title = 'HTTP Response'; +exports.group = 'HTTP'; +exports.color = '#5D9CEC'; +exports.icon = 'arrow-right'; +exports.input = true; +exports.output = ['#666D76']; +exports.version = '2.0.0'; +exports.author = 'Martin Smola'; +exports.readme = `# HTTP response + +HTTP response will respond with data recieved using data-type set in Settings form or plain text if not set. Output is the message duration \`Number\` in seconds.`; + +exports.html = `
+
@(Response data-type)
+
JSON is by default.
+
`; + +exports.install = function(instance) { + + var dursum = 0; + var durcount = 0; + + instance.on('data', function(flowdata) { + + var ctrl = flowdata.repository.controller; + var data = flowdata.data; + + if (!ctrl) { + instance.throw('No controller to use for response!'); + return; + } + + durcount++; + dursum += ((new Date() - flowdata.begin) / 1000).floor(2); + setTimeout2(instance.id, instance.custom.duration, 500, 10); + + ctrl.$flowdata = flowdata; + + var datatype = instance.options.datatype || 'json'; + if (datatype === 'emptyresponse') + return ctrl.plain(''); + + if (datatype !== 'json' && typeof(data) !== 'string') { + instance.throw('Incorect type of data, expected string, got ' + typeof(data)); + ctrl.plain(data == null ? '' : data.toString()); + return; + } + + switch(datatype) { + case 'html': + ctrl.content(data, 'text/html'); + break; + case 'plain': + ctrl.plain(data); + break; + case 'xml': + ctrl.content(data, 'text/xml'); + break; + default: + ctrl.json(data); + break; + } + }); + + instance.on('service', function() { + dursum = 0; + durcount = 0; + }); + + instance.custom.duration = function() { + var avg = (dursum / durcount).floor(2); + instance.status(avg + ' sec.'); + instance.send2(0, avg); + }; +}; diff --git a/RVO23/flow/httproute.js b/RVO23/flow/httproute.js new file mode 100755 index 0000000..583a19d --- /dev/null +++ b/RVO23/flow/httproute.js @@ -0,0 +1,326 @@ +exports.id = 'httproute'; +exports.title = 'HTTP Route'; +exports.group = 'HTTP'; +exports.color = '#5D9CEC'; +exports.icon = 'globe'; +exports.input = false; +exports.output = ['#6CAC5A', '#37BC9B']; +exports.version = '1.2.3'; +exports.author = 'Martin Smola'; +exports.cloning = false; +exports.options = { method: 'GET', url: '', size: 5, cacheexpire: '5 minutes', cachepolicy: 0, timeout: 5 }; +exports.dateupdated = '2021-01-21 18:30d'; +exports.readme = `# HTTP route + +__Outputs__: +- first output: raw data (cache is empty or is disabled) +- second output: cached data + +If one of the outputs is disabled then automatic responce with code "503 service unavailable" is sent. + +When a request comes in bellow object is available at \`flowdata.data\`: + +\`\`\`javascript +{ + params: { id: '1' }, // params for dynamic routes, e.g. /test/{id} + query: { msg: 'Hello' }, // parsed query string, e.g. /test/1?msg=Hello + body: { test: 'OK' }, // object if json requests otherwise string + headers: {}, // headers data + session: {}, // session data + user: {}, // user data + files: [], // uploaded files + url: '/users/', // a relative URL address + referrer: '/', // referrer + mobile: false, // determines mobile device + robot: false, // determines search robots/crawlsers + language: 'en' // determines language +} +\`\`\` + +See [documentation for flags](https://docs.totaljs.com/latest/en.html#api~HttpRouteOptionsFlags~unauthorize). These method flags are set automatically e.g. \`get, post, put, patch or delete\` + +--- + +\`id:ROUTE_ID\` flag cannot be used since it's already used by this component internally`; + +exports.html = `
+
+ +
+ +
+
+
@(HTTP method)
+
+
+
@(URL address)
+
+
+
+
+
@(Additional flags)
+
@(Separate flags by comma e.g. json, authorize)
+
+
+
@(Max. request size)
+
@(In kB kilobytes)
+
+
+
@(Timeout)
+
@(In seconds.)
+
+
+
+
+
+
@(Automatically respond with 200 OK?)
+
@(If not checked you need to use HTTP response component to respond to the request.)
+
+
@(Custom headers)
+
@(Cookies)
+
+
+
+
+
+
@(Cache policy)
+
@(User instance must contain id property.)
+
+
+
@(Expiration)
+
@(E.g. 5 minutes)
+
+
+
+`; + +exports.install = function(instance) { + + var route; + + var uninstall = function(id) { + if (F.is4) { + route && route.remove(); + route = null; + } else + UNINSTALL('route', id); + }; + + instance.custom.emptyresponse = function(self) { + self.plain(); + }; + + instance.reconfigure = function() { + + var options = instance.options; + + if (!options.url) { + instance.status('Not configured', 'red'); + return; + } + + if (typeof(options.flags) === 'string') + options.flags = options.flags.split(',').trim(); + + uninstall('id:' + instance.id); + + var flags = options.flags || []; + + flags.push('id:' + instance.id); + + if (!F.is4) + flags.push(options.method.toLowerCase()); + + options.timeout && flags.push(options.timeout * 1000); + + // Make unique values + flags = flags.filter(function(v, i, a) { + if(F.is4 && v.toString().toLowerCase() === options.method.toLowerCase()) + return false; // remove method + return a.indexOf(v) === i; + }); + + options.flags = flags; + var handler = function() { + + if (instance.paused || (instance.isDisabled && (instance.isDisabled('output', 0) || instance.isDisabled('output', 1)))) { + instance.status('503 Service Unavailable'); + this.status = 503; + this.json(); + return; + } + + var key; + var self = this; + + if (instance.options.emptyresponse) { + instance.status('200 OK'); + setTimeout(instance.custom.emptyresponse, 100, self); + + if (instance.hasConnection(0)) { + var data = instance.make({ + query: self.query, + body: self.body, + session: self.session, + user: self.user, + files: self.files, + headers: self.req.headers, + url: self.url, + params: self.params + }); + instance.send2(0, data); + } + + return; + } + + switch (instance.options.cachepolicy) { + case 1: // URL + key = 'rro' + instance.id + self.url.hash(); + break; + case 2: // URL + query + case 3: // URL + query + user + key = self.url; + var keys = Object.keys(self.query); + keys.sort(); + for (var i = 0, length = keys.length; i < length; i++) + key += keys[i] + self.query[keys[i]] + '&'; + if (instance.options.cachepolicy === 3 && self.user) + key += 'iduser' + self.user.id; + key = 'rro' + instance.id + key.hash(); + break; + } + + if (key && F.cache.get2(key)) { + var data = instance.make(F.cache.get2(key)); + data.repository.controller = self; + instance.send2(1, data); + } else { + + var data = instance.make({ + query: self.query, + body: self.body, + session: self.session, + user: self.user, + files: self.files, + headers: self.req.headers, + url: self.url, + params: self.params, + mobile: self.mobile, + robot: self.robot, + referrer: self.referrer, + language: self.language + }); + + data.repository.controller = self; + instance.send2(0, data); + key && FINISHED(self.res, () => F.cache.set(key, self.$flowdata.data, instance.options.cacheexpire)); + } + }; + + if (F.is4) + route = ROUTE(options.method.toUpperCase() + ' ' + options.url, handler, flags, options.size || 5); + else + F.route(options.url, handler, flags, options.size || 5); + + instance.status('Listening', 'green'); + }; + + instance.reconfigure(); + instance.on('options', instance.reconfigure); + instance.on('close', function(){ + uninstall('id:' + instance.id); + }); +}; + +// check url exists +FLOW.trigger('httproutecheckurl', function(next, data) { + var url = data.url; + var method = data.method; + if (url[url.length - 1] !== '/') + url += '/'; + var exists = F.routes.web.findItem(r => r.urlraw === url && r.method === method); + next(exists != null); +}); + +exports.uninstall = function() { + FLOW.trigger('httproutecheckurl', null); +}; diff --git a/RVO23/flow/infosender.js b/RVO23/flow/infosender.js new file mode 100755 index 0000000..587724f --- /dev/null +++ b/RVO23/flow/infosender.js @@ -0,0 +1,81 @@ +exports.id = 'infosender'; +exports.title = 'Info sender'; +exports.version = '1.0.0'; +exports.group = 'Worksys'; +exports.color = '#2134B0'; +exports.input = 2; +exports.output = 1 +exports.icon = 'bolt'; + +const { networkInterfaces } = require('os'); + +exports.html = `
+
+
+
CSV Import
+
+
+
`; + +exports.readme = `# send all data to projects.worksys.io, required to monitor status of controller(unipi)`; + +exports.install = function(instance) { + + let id; + let allValues = {}; + let sendAllValuesInterval; + let configured = false; + + let now = new Date(); + console.log(exports.title, "INSTALLED", now.toLocaleString("sk-SK")); + + const nets = networkInterfaces(); + let ipAddresses = Object.create(null); // Or just '{}', an empty object + + for (const name of Object.keys(nets)) { + for (const net of nets[name]) { + // Skip over non-IPv4 and internal (i.e. 127.0.0.1) addresses + if (net.family === 'IPv4' && !net.internal) { + if (!ipAddresses[name]) { + ipAddresses[name] = []; + } + ipAddresses[name].push(net.address); + } + } + } + + function sendValues() { + if (!configured) return; + + if (Object.keys(allValues).length > 0) { + let dataToSend = { ...allValues }; + dataToSend.id = id; + dataToSend.ipAddresses = ipAddresses; + + instance.send(0, dataToSend); + + allValues = {}; + } + } + + instance.on("close", () => { + clearInterval(sendAllValuesInterval); + }) + + instance.on("0", _ => { + id = FLOW.GLOBALS.settings.project_id; + if (id) configured = true; + else console.log(exports.title, "InfoSender: Unable to send data, no id"); + }) + + instance.on("1", flowdata => { + allValues = { ...allValues, ...flowdata.data }; + //console.log("DATA RECEIVED", flowdata.data); + }) + + sendAllValuesInterval = setInterval(() => { + sendValues(); + }, 60000 * 3); + +} + diff --git a/RVO23/flow/modbus_reader.js b/RVO23/flow/modbus_reader.js new file mode 100755 index 0000000..d6d9dad --- /dev/null +++ b/RVO23/flow/modbus_reader.js @@ -0,0 +1,346 @@ +exports.id = 'modbus_reader'; +exports.title = 'Modbus reader'; +exports.version = '2.0.0'; +exports.group = 'Worksys'; +exports.color = '#2134B0'; +exports.input = 1; +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; +//number of phases inRVO +let phases; +//phases where voltage is 0 (set) +let noVoltage; +let energyToSwitchLamps; + +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.phases = this.buildPhases(); + + this.startSocket(); + } + + buildPhases = () => { + let a = []; + for (let i = 1; i <= phases; i++) { + a.push(`Phase_${i}_voltage`) + } + return a; + } + + startSocket = () => { + + let obj = this; + + if (this.socket) { + this.socket.removeAllListeners(); + this.socket = null; + } + + 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('Modbus_reader: Socket connection error', e); //'ECONNREFUSED' or 'ECONNRESET' ?? + }); + + this.socket.on('close', function() { + console.log('Modbus_reader: Socket connection closed - Waiting 10 seconds before connecting 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 we just start to loop devices from the beginning, or there is just 1 device in config, we wait whole timeoutInterval + if (this.indexInDeviceConfig == 0 || deviceConfig.length === 1) 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 (this.phases.includes(singleValue)) { + let l = singleValue.split("_"); + let phase = parseInt(l[1]); + + // console.log(values[singleValue], tbName); + + if (values[singleValue] == 0) { + noVoltage.add(phase); + sendNotification("modbus_reader: checkNullVoltage", tbName, "no_voltage_on_phase", { phase: phase }, "", SEND_TO.tb, instance, "voltage" + phase); + // console.log('no voltage') + } + else { + noVoltage.delete(phase); + // console.log('voltage detected') + sendNotification("modbus_reader: checkNullVoltage", tbName, "voltage_on_phase_restored", { phase: phase }, "", SEND_TO.tb, instance, "voltage" + phase); + } + } + }) + } + + /** + * function sends notification to slack and to tb, if EM total_power value changes more than numberOfNodes*15. This should show, that RVO lamps has been switched on or off + */ + lampSwitchNotification = (values) => { + + if (!values.hasOwnProperty("total_power")) return; + + const actualTotalPower = values.total_power; + + if (actualTotalPower > energyToSwitchLamps && 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 <= energyToSwitchLamps && 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; + } + + function main() { + + phases = FLOW.GLOBALS.settings.phases; + tbName = FLOW.GLOBALS.settings.rvoTbName; + noVoltage = FLOW.GLOBALS.settings.no_voltage; + energyToSwitchLamps = FLOW.GLOBALS.settings.energy_to_switch_lamps / 2.5; //half value is enought to show if lamps are turned on or off + if (deviceConfig.length) mainSocket = new SocketWithClients(); + else console.log("Modbus_reader: no modbus device in configuration"); + + // this notification is to show, that flow (unipi) has been restarted + sendNotification("modbus_reader", tbName, "flow_restart", {}, "", SEND_TO.slack, instance); + } + + instance.on("0", function(_) { + main(); + }) + +} + diff --git a/RVO23/flow/monitorconsumption.js b/RVO23/flow/monitorconsumption.js new file mode 100755 index 0000000..64cc58e --- /dev/null +++ b/RVO23/flow/monitorconsumption.js @@ -0,0 +1,156 @@ +exports.id = 'monitorconsumption'; +exports.title = 'Consumption'; +exports.version = '1.0.0'; +exports.author = 'Peter Širka'; +exports.group = 'Monitoring'; +exports.color = '#967ADC'; +exports.input = 0; +exports.output = 1; +exports.icon = 'bug'; +exports.options = { interval: 5000, enabled: true, monitorconsumption: true, monitorsize: true, monitorconnections: true, monitorfiles: true }; +exports.click = true; +exports.readme = `# Consumption monitoring + +This component measure CPU and memory consumption, open files and open connections of this application. It uses these Linux commands: \`ps\`, \`lsof\`, \`netstat\` and \`df\`. + +__Data Example__: + +\`\`\`javascript +{ + cpu: 0, // percentage + memory: 4096, // in bytes + size: 34303, // directory size in bytes + files: 34, // count of open files + connections: 343, // count of connections + uptime: '1-12:34:00' +} +\`\`\``; + +exports.html = `
+
+
+
@(Interval in milliseconds)
+
+
+
+
Monitor: Consumption + uptime
+
Monitor: Count of open files
+
Monitor: Count of open connections
+
Monitor: Directory size
+
`; + +exports.install = function(instance) { + + var current = { cpu: 0, memory: 0, files: 0, connections: 0, size: 0, uptime: '', counter: 0 }; + var tproc = null; + var Exec = require('child_process').exec; + var reg_empty = /\s{2,}/g; + var reg_appdisksize = /^[\d.,]+/; + + instance.custom.run = function() { + + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + + var arr = []; + + // Get CPU and Memory consumption + instance.options.monitorconsumption && arr.push(function(next) { + Exec('ps -p {0} -o %cpu,rss,etime'.format(process.pid), function(err, response) { + + if (err) { + instance.throw(err); + } else { + var line = response.split('\n')[1]; + line = line.trim().replace(reg_empty, ' ').split(' '); + var cpu = line[0].parseFloat(); + current.cpu = cpu.floor(1); + current.memory = line[1].parseInt2() * 1024; // kB to bytes + current.uptime = line[2]; + } + + next(); + }); + }); + + // Get count of open files + instance.options.monitorfiles && arr.push(function(next) { + Exec('lsof -a -p {0} | wc -l'.format(process.pid), function(err, response) { + if (err) + instance.throw(err); + else + current.files = response.trim().parseInt2(); + next(); + }); + }); + + // Get count of opened network connections + instance.options.monitorconnections && arr.push(function(next) { + Exec('netstat -an | grep :{0} | wc -l'.format(F.port), function(err, response) { + if (err) { + instance.throw(err); + } else { + current.connections = response.trim().parseInt2() - 1; + if (current.connections < 0) + current.connections = 0; + } + next(); + }); + }); + + // Get directory size + instance.options.monitorsize && current.counter % 5 !== 0 && arr.push(function(next) { + Exec('du -hsb ' + process.cwd(), function(err, response) { + if (err) { + instance.throw(err); + } else { + var match = response.trim().match(reg_appdisksize); + match && (current.size = match.toString().trim().parseInt2()); + } + next(); + }); + }); + + arr.async(function() { + + tproc && clearTimeout(tproc); + + if (instance.options.enabled) { + tproc = setTimeout(instance.custom.run, instance.options.interval); + instance.send2(current); + } + + instance.custom.status(); + current.counter++; + }); + }; + + instance.custom.status = function() { + if (instance.options.enabled) + instance.status('{0}% / {1}'.format(current.cpu, current.memory.filesize())); + else + instance.status('Disabled', 'red'); + }; + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + + if (instance.options.enabled) { + current.counter = 0; + instance.custom.run(); + } + + }); + + instance.on('close', function() { + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + }); + + setTimeout(instance.custom.run, 1000); +}; \ No newline at end of file diff --git a/RVO23/flow/monitordisk.js b/RVO23/flow/monitordisk.js new file mode 100755 index 0000000..f4fdaa0 --- /dev/null +++ b/RVO23/flow/monitordisk.js @@ -0,0 +1,96 @@ +exports.id = 'monitordisk'; +exports.title = 'Disk'; +exports.version = '1.0.0'; +exports.author = 'Peter Širka'; +exports.group = 'Monitoring'; +exports.color = '#F6BB42'; +exports.output = 1; +exports.icon = 'hdd-o'; +exports.click = true; +exports.options = { interval: 8000, path: '/', enabled: true }; +exports.readme = `# Disk monitoring + +This component monitors disk \`bytes\` consumption in Linux systems. It uses \`df\` command. + +__Data Example__: + +\`\`\`javascript +{ + total: 474549649408, + used: 39125245952, + free: 411294994432 +} +\`\`\``; + +exports.html = `
+
+
+
@(Interval in milliseconds)
+
+
+
@(Path)
+
+
+
`; + +exports.install = function(instance) { + + var current = { total: 0, used: 0, free: 0, path: '', type: '', percentUsed: 0 }; + var tproc = null; + + instance.custom.run = function() { + + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + + if (!instance.options.enabled) + return; + + require('child_process').exec('df -hTB1 ' + instance.options.path, function(err, response) { + + tproc = setTimeout(instance.custom.run, instance.options.interval); + + if (err) { + instance.error(err); + return; + } + + response.parseTerminal(function(line) { + if (line[0][0] !== '/') + return; + current.total = line[2].parseInt(); + current.free = line[4].parseInt(); + current.used = line[3].parseInt(); + current.path = instance.options.path || '/'; + current.type = line[1]; + current.percentUsed = line[5]; + instance.custom.status(); + instance.send2(current); + }); + }); + }; + + instance.custom.status = function() { + if (instance.options.enabled) + instance.status(current.free.filesize() + ' / ' + current.total.filesize()); + else + instance.status('Disabled', 'red'); + }; + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + instance.options.enabled && instance.custom.run(); + }); + + instance.on('close', function() { + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + }); + + setTimeout(instance.custom.run, 1000); +}; \ No newline at end of file diff --git a/RVO23/flow/monitormemory.js b/RVO23/flow/monitormemory.js new file mode 100755 index 0000000..2decbc4 --- /dev/null +++ b/RVO23/flow/monitormemory.js @@ -0,0 +1,87 @@ +exports.id = 'monitormemory'; +exports.title = 'Memory'; +exports.version = '1.0.0'; +exports.author = 'Peter Širka'; +exports.group = 'Monitoring'; +exports.color = '#F6BB42'; +exports.output = 1; +exports.click = true; +exports.icon = 'microchip'; +exports.options = { interval: 8000, enabled: true }; +exports.readme = `# Memory monitoring + +This component monitors memory \`bytes\` consumption in Linux systems. It uses \`free\` command. + +__Data Example__: + +\`\`\`javascript +{ + total: 33558769664, + used: 1998868480, + free: 2653708288 +} +\`\`\``; + +exports.html = `
+
+
+
@(Interval in milliseconds)
+
+
+
`; + +exports.install = function(instance) { + + var current = { total: 0, used: 0, free: 0 }; + var tproc = null; + + instance.custom.run = function() { + + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + + if (!instance.options.enabled) + return; + + require('child_process').exec('free -b -t', function(err, response) { + + tproc = setTimeout(instance.custom.run, instance.options.interval); + + if (err) { + instance.error(err); + return; + } + + var memory = response.split('\n')[1].match(/\d+/g); + current.total = memory[0].parseInt(); + current.used = memory[1].parseInt() - memory[3].parseInt(); + current.free = current.total - current.used; + instance.custom.status(); + instance.send2(current); + }); + }; + + instance.custom.status = function() { + if (instance.options.enabled) + instance.status(current.free.filesize() + ' / ' + current.total.filesize()); + else + instance.status('Disabled', 'red'); + }; + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + instance.options.enabled && instance.custom.run(); + }); + + instance.on('close', function() { + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + }); + + setTimeout(instance.custom.run, 1000); +}; \ No newline at end of file diff --git a/RVO23/flow/nodesdb_changecheck.js b/RVO23/flow/nodesdb_changecheck.js new file mode 100755 index 0000000..9adab62 --- /dev/null +++ b/RVO23/flow/nodesdb_changecheck.js @@ -0,0 +1,77 @@ +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 = 2; +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); + } + } + + //kedze do slacku posielame stringy, na cloud musime previest vsetky stringy spat na objekty: + // Funkcia na parsovanie všetkých reťazcov v poli + const parseArray = (arr) => { + return arr.map(jsonString => JSON.parse(jsonString)); + }; + + 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); + if (FLOW.GLOBALS.settings.send_changed_node_numbers) instance.send(1, { aktualneNody: parseArray(zmenene), originalne: parseArray(Array.from(set2)) }); + } + 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/RVO23/flow/show_dbdata.js b/RVO23/flow/show_dbdata.js new file mode 100755 index 0000000..1e23ff7 --- /dev/null +++ b/RVO23/flow/show_dbdata.js @@ -0,0 +1,243 @@ +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 = 8; +exports.output = 1; + +const { exec } = require('child_process'); + +exports.install = 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 }) + }) + instance.on("5", _ => { + exec("sudo tail -n 25 monitor.txt", (err, stdout, stderr) => { + if (err || stderr) instance.send(0, { err, stderr }); + else instance.send(0, stdout); + }) + }) + instance.on("6", _ => { + exec("sudo tail -n 25 err.txt", (err, stdout, stderr) => { + if (err || stderr) instance.send(0, { err, stderr }); + else instance.send(0, stdout); + }) + }) + instance.on("7", _ => { + instance.send(0, FLOW.deviceStatus); + }) +}; + + +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/RVO23/flow/slack_filter.js b/RVO23/flow/slack_filter.js new file mode 100755 index 0000000..6618523 --- /dev/null +++ b/RVO23/flow/slack_filter.js @@ -0,0 +1,188 @@ +exports.id = 'slack_filter'; +exports.title = 'Slack Filter'; +exports.group = 'Citysys'; +exports.color = '#30E193'; +exports.input = 2; +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 = `
+
+
+
@(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('0', 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']['en']; + 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"] = []; + } + + instance.options.name = FLOW.GLOBALS.settings.rvo_name; + if (instance.options.name) { + instance.status('Running'); + running = true; + } else { + instance.status('Please run options again', 'red'); + running = false; + } + } catch (e) { + instance.error('Citysys connector: ' + e.message); + } + }; + + instance.on('options', instance.reconfigure); + + instance.on("1", _ => { + instance.reconfigure(); + }) +}; diff --git a/RVO23/flow/thermometer.js b/RVO23/flow/thermometer.js new file mode 100755 index 0000000..fc7074d --- /dev/null +++ b/RVO23/flow/thermometer.js @@ -0,0 +1,99 @@ +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 = 5;//minutes +let NUMBER_OF_FAILURES_TO_SEND_ERROR = 13; + +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) => { + + 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); + setTimeout(main, 20000); + }) +}; diff --git a/RVO23/flow/trigger.js b/RVO23/flow/trigger.js new file mode 100755 index 0000000..27545a8 --- /dev/null +++ b/RVO23/flow/trigger.js @@ -0,0 +1,79 @@ +exports.id = 'trigger'; +exports.title = 'Trigger'; +exports.group = 'Inputs'; +exports.color = '#F6BB42'; +exports.click = true; +exports.output = 1; +exports.version = '1.1.0'; +exports.author = 'Martin Smola'; +exports.icon = 'play'; + +exports.html = `
+
@(Data type (String by default))
+
@(Data)
+
Trigger 5s after initialization.
+
@(Useful when there's a need to run certain flow when the app restarts, etc.)
+
`; + +exports.readme = `# Trigger + +- Clicking on the component starts the chain +- Settings allows to set a data-type and a value`; + +exports.install = function(instance) { + + var value; + + instance.on('click', () => instance.send2(value)); + + instance.reconfigure = function() { + var options = instance.options; + value = null; + switch (options.datatype) { + case 'integer': + value = options.data.parseInt2('error'); + value = value === 'error' ? NaN : value; + break; + case 'float': + value = options.data.parseFloat2('error'); + value = value === 'error' ? NaN : value; + break; + case 'date': + options.data = options.data.toString(); + var num = options.data.parseInt('error'); + num === 'error' && (num = options.data.parseDate('error')); + num === 'error' && (num = null); + value = num ? new Date(num).toUTCString() : num; + break; + case 'object': + try { + value = (new Function('return ' + options.data))(); + } catch (e) { + instance.error(e); + } + break; + case 'boolean': + value = options.data.parseBoolean(); + break; + case 'buffer': + try { + value = U.createBuffer(options.data); + } catch (e) { + instance.error(e); + } + break; + case 'string': + default: + value = '' + (options.data || ''); + break; + } + }; + + instance.on('options', instance.reconfigure); + instance.reconfigure(); + + if (instance.options.restart) + setTimeout(function(){ + instance.send2(value); + }, 5000); +}; diff --git a/RVO23/flow/variables.txt b/RVO23/flow/variables.txt new file mode 100755 index 0000000..e69de29 diff --git a/RVO23/flow/virtualwirein.js b/RVO23/flow/virtualwirein.js new file mode 100755 index 0000000..38a4e42 --- /dev/null +++ b/RVO23/flow/virtualwirein.js @@ -0,0 +1,43 @@ +exports.id = 'virtualwirein'; +exports.title = 'Virtual wire in'; +exports.version = '1.0.0'; +exports.author = 'Martin Smola'; +exports.color = '#303E4D'; +exports.icon = 'sign-in'; +exports.input = false; +exports.output = 1; +exports.options = {}; +exports.readme = `# Virtual wire in + +When the wires between the components are mess it's time to use Virtual wire.`; + +exports.html = `
+
@(Wire name)
+
+`; + +exports.install = function(instance) { + + instance.custom.reconfigure = function(options){ + if (instance.options.wirename) { + instance.status(instance.options.wirename); + } else + instance.status('Not configured', 'red'); + }; + + ON('virtualwire', function(wirename, flowdata){ + if (instance.options.wirename && instance.options.wirename === wirename) + instance.send(flowdata); + }); + + instance.on('options', instance.custom.reconfigure); + instance.custom.reconfigure(); +}; diff --git a/RVO23/flow/virtualwireout.js b/RVO23/flow/virtualwireout.js new file mode 100755 index 0000000..94a1e4f --- /dev/null +++ b/RVO23/flow/virtualwireout.js @@ -0,0 +1,41 @@ +exports.id = 'virtualwireout'; +exports.title = 'Virtual wire out'; +exports.version = '1.0.0'; +exports.author = 'Martin Smola'; +exports.color = '#303E4D'; +exports.icon = 'sign-out'; +exports.input = true; +exports.options = {}; +exports.readme = `# Virtual wire out + +When the wires between the components are mess it's time to use Virtual wire.`; + +exports.html = `
+
@(Wire name)
+
+`; + +exports.install = function(instance) { + + instance.custom.reconfigure = function(){ + if (instance.options.wirename) { + instance.status(instance.options.wirename); + } else + instance.status('Not configured', 'red'); + }; + + instance.on('data', function(flowdata) { + EMIT('virtualwire', instance.options.wirename, flowdata); + }); + + instance.on('options', instance.custom.reconfigure); + instance.custom.reconfigure(); +}; diff --git a/RVO23/flow/wsmqttpublish.js b/RVO23/flow/wsmqttpublish.js new file mode 100755 index 0000000..0eba804 --- /dev/null +++ b/RVO23/flow/wsmqttpublish.js @@ -0,0 +1,448 @@ +exports.id = 'wsmqttpublish'; +exports.title = 'WS MQTT publish'; +exports.group = 'MQTT'; +exports.color = '#888600'; +exports.version = '1.0.2'; +exports.icon = 'sign-out'; +exports.input = 2; +exports.output = 3; +exports.options = { host: 'tb-stage.worksys.io', port: 1883, clientid: "", username: "" }; + +exports.html = `
+
+
+
Hostname or IP address (if not empty - setting will override db setting)
+
+
+
Port
+
+
+
+
+
@(Client id)
+
+
+
@(Username)
+
+
+
`; + + +exports.readme = ` +# WS MQTT Publish + +Version 1.0.3. + +Added: +- database collections, +- 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 = { + debug: 0, + rpcCall: 1, + services: 2 +} + +//CONFIG +let createTelemetryBackup = true; +let saveTelemetryOnError = true;//backup_on_failure overrides this value +//------------------------ + +let rollers; +if (createTelemetryBackup) rollers = require('streamroller'); + +const noSqlFileSizeLimit = 4194304;//use 5MB - 4194304 +let insertNoSqlCounter = 0; +let insertBackupNoSqlCounter = 0; +let processingData = false; + +let backup_on_failure = false;//== saveTelemetryOnError - create backup client 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; + +process.on('uncaughtException', function(err) { + + errLogger.error('uncaughtException:', err.message) + errLogger.error(err.stack); + + //TODO + //send to service + + //process.exit(1); +}) + +const nosql = NOSQL('tbdata'); +const nosqlBackup = NOSQL('/backup/tbdata'); + + +exports.install = function(instance) { + + var client; + var opts; + var clientReady = false; + + // wsmqtt status for notification purposes on projects.worksys.io database + let wsmqttName = null; + let sendWsStatusVar = null; + let wsmqtt_status = 'disconnected'; + + 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'; + } + + function sendWsStatus() { + instance.send(SEND_TO.services, { [wsmqttName]: wsmqtt_status }); + } + + + function main() { + if (!FLOW.dbLoaded) return; + + loadSettings(); + clearInterval(sendWsStatus); + sendWsStatusVar = setInterval(sendWsStatus, 180000); + } + + //set opts according to db settings + function loadSettings() { + + if (instance.options.host !== "") { + //override settings from database + var o = instance.options; + opts = { + host: o.host, + port: o.port, + clientId: o.clientid, + username: o.username, + rejectUnauthorized: false, + resubscribe: false + }; + + wsmqttName = getWsmqttName(o.host); + + console.log("wsmqttpublich -> loadSettings from instance.options", instance.options); + } + else { + + const SETTINGS = FLOW.GLOBALS.settings; + backup_on_failure = SETTINGS.backup_on_failure; + saveTelemetryOnError = backup_on_failure; + + restore_from_backup = SETTINGS.restore_from_backup; + restore_backup_wait = SETTINGS.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; + + opts = { + host: mqtt_host, + port: mqtt_port, + keepalive: 10, + clientId: mqtt_clientid, + username: mqtt_username, + rejectUnauthorized: false, + resubscribe: false + }; + + wsmqttName = getWsmqttName(mqtt_host); + } + + connectToTbServer(); + } + + function connectToTbServer() { + 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"); + //monitor.info("MQTT client connected"); + + sendClientError = true; + clientReady = true; + wsmqtt_status = 'connected'; + }); + + client.on('reconnect', function() { + instance.status("Reconnecting", "yellow"); + clientReady = false; + }); + + client.on('message', function(topic, message) { + // message is type of buffer + message = message.toString(); + if (message[0] === '{') { + TRY(function() { + + message = JSON.parse(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 } }); + } + + }, () => instance.debug('MQTT: Error parsing data', message)); + } + + instance.send(SEND_TO.rpcCall, { "topic": topic, "content": message }); + }); + + client.on('close', function() { + clientReady = false; + wsmqtt_status = 'disconnected'; + + instance.status("Disconnected", "red"); + instance.send(SEND_TO.debug, { "message": "Client CLOSE signal received !" }); + }); + + client.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; + wsmqtt_status = 'disconnected'; + }); + + } + + + instance.on("0", _ => { + main(); + }) + + + instance.on('1', function(data) { + + if (clientReady) { + //do we have some data in backup file? if any, process data from database + if (saveTelemetryOnError) { + //read telemetry data and send back to server + if (!processingData) processDataFromDatabase(); + } + + let stringifiedJson = JSON.stringify(data.data); + client.publish("v1/gateway/telemetry", stringifiedJson, { qos: 1 }); + + //backup telemetry + if (createTelemetryBackup) { + data.data.id = UID(); + nosqlBackup.insert(data.data); + + insertBackupNoSqlCounter++; + if (insertBackupNoSqlCounter > 150) { + let options = { compress: true }; + let path = __dirname + "/../databases/backup/tbdata.nosql"; + var stream = new rollers.RollingFileStream(path, noSqlFileSizeLimit, 150, options); + stream.write(""); + stream.end(); + + insertBackupNoSqlCounter = 0; + } + } + + } + 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 (saveTelemetryOnError) { + //create new file from tbdata.nosql, if file size exceeds given limit, and clear tbdata.nosql + makeBackupFromDbFile(); + + //write to tb + data.data.id = UID(); + nosql.insert(data.data); + } + } + }); + + + instance.close = function(done) { + if (clientReady) { + client.end(); + clearInterval(sendWsStatusVar); + } + }; + + + function getDbBackupFileCounter(type) { + var files = fs.readdirSync(__dirname + "/../databases"); + + let counter = 0; + for (var i = 0; i < files.length; i++) { + + if (files[i] == "tbdata.nosql") continue; + + if (files[i].endsWith(".nosql")) { + + let pos = files[i].indexOf("."); + if (pos > -1) { + + let fileCounter = counter; + let firstDigit = files[i].slice(0, pos); + + fileCounter = parseInt(firstDigit); + if (isNaN(fileCounter)) fileCounter = 0; + //console.log("getDbBackupFileCounter digit:", files[i], firstDigit, fileCounter, isNaN(fileCounter), type); + + if (type == "max") { + if (fileCounter > counter) { + counter = fileCounter; + } + } + else if (type == "min") { + if (counter == 0) counter = fileCounter; + + if (fileCounter < counter) { + counter = fileCounter; + } + } + } + } + + } + + if (type == "max") counter++; + + return counter; + } + + const makeBackupFromDbFile = async () => { + + if (!saveTelemetryOnError) return; + + //to avoid large file: tbdata.nosql + + //init value is 0! + if (insertNoSqlCounter > 0) { + --insertNoSqlCounter; + return; + } + + insertNoSqlCounter = 100; + + let source = __dirname + "/../databases/tbdata.nosql"; + + var stats = fs.statSync(source); + var fileSizeInBytes = stats.size; + + if (fileSizeInBytes > noSqlFileSizeLimit) { + + let counter = 1; + counter = getDbBackupFileCounter("max"); + + let destination = __dirname + "/../databases/" + counter + "." + "tbdata.nosql"; + + //make backup file + fs.copyFileSync(source, destination); + //fs.renameSync(p, p + "." + counter); + + //clear tbdata.nosql + fs.writeFileSync(source, ""); + fs.truncateSync(source, 0); + + } + } + + const processDataFromDatabase = async () => { + + if (restore_from_backup <= 0) return; + + //calculate diff + const now = new Date(); + let currentTime = now.getTime(); + let diff = currentTime - lastRestoreTime; + + if ((diff / 1000) < restore_backup_wait) { + //console.log("*********restore_backup_wait", diff, restore_backup_wait); + return; + } + + processingData = true; + + //get filename to process + let counter = getDbBackupFileCounter("min"); + + //we have some backup files + let dataBase = 'tbdata'; + + var nosql; + if (counter == 0) dataBase = 'tbdata'; + else dataBase = counter + "." + 'tbdata'; + + nosql = NOSQL(dataBase); + + //select all data - use limit restore_from_backup + let records = await promisifyBuilder(nosql.find().take(restore_from_backup)); + + for (let i = 0; i < records.length; i++) { + if (clientReady) { + + let item = records[i]; + let id = item.id; + + if (id !== undefined) { + //console.log("------------processDataFromDatabase - remove", id, dataBase, i); + + try { + + let message = JSON.parse(JSON.stringify(item)); + delete message.id; + + client.publish("v1/gateway/telemetry", JSON.stringify(message), { qos: 1 }); + + //remove from database + await promisifyBuilder(nosql.remove().where("id", id)); + + } catch (error) { + //process error + console.log("processDataFromDatabase", error); + } + + } + + } + else { + processingData = false; + return; + } + } + + if (records.length > 0) { + //clean backup file + if (counter > 0) nosql.clean(); + } + + //no data in db, remove + if (records.length == 0) { + if (counter > 0) nosql.drop(); + } + + const d = new Date(); + lastRestoreTime = d.getTime(); + + processingData = false; + + } + + instance.on('options', main); + //instance.reconfigure(); +}; diff --git a/RVO23/monitor.txt b/RVO23/monitor.txt new file mode 100755 index 0000000..e15ffe2 --- /dev/null +++ b/RVO23/monitor.txt @@ -0,0 +1,2284 @@ +[2025-07-11T21:08:27.021] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-11T21:08:27.045] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-11T21:08:27.047] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-12T03:49:51.014] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-12 03:49:51 +[2025-07-12T04:45:00.018] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-12T04:45:00.022] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-12T04:45:00.024] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-12T21:08:17.738] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-12T21:08:17.766] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-12T21:08:17.768] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-13T03:49:52.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-13 03:49:52 +[2025-07-13T04:44:50.614] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-13T04:44:50.617] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-13T04:44:50.619] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-13T21:08:08.243] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-13T21:08:08.253] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-13T21:08:08.255] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-14T03:49:53.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-14 03:49:53 +[2025-07-14T04:44:41.116] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-14T04:44:41.120] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-14T04:44:41.122] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-14T21:07:58.776] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-14T21:07:58.783] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-14T21:07:58.785] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-15T03:49:55.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-15 03:49:55 +[2025-07-15T04:47:03.356] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-15T04:47:03.358] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-15T04:47:03.361] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-15T21:02:49.731] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-15T21:02:49.740] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-15T21:02:49.742] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-16T03:49:56.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-16 03:49:56 +[2025-07-16T04:49:25.043] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-16T04:49:25.046] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-16T04:49:25.048] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-16T20:55:09.265] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-16T20:55:09.272] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-16T20:55:09.274] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-17T03:49:57.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-17 03:49:57 +[2025-07-17T04:54:16.736] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-17T04:54:16.740] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-17T04:54:16.743] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-17T21:00:01.508] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-17T21:00:01.532] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-17T21:00:01.534] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-18T03:49:58.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-18 03:49:58 +[2025-07-18T05:04:10.269] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-18T05:04:10.273] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-18T05:04:10.275] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-18T21:04:54.251] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-18T21:04:54.265] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-18T21:04:54.267] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-19T03:49:59.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-19 03:49:59 +[2025-07-19T04:56:30.257] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-19T04:56:30.261] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-19T04:56:30.263] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-19T21:02:14.347] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-19T21:02:14.370] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-19T21:02:14.372] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-20T03:50:01.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-20 03:50:01 +[2025-07-20T04:53:51.725] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-20T04:53:51.728] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-20T04:53:51.730] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-20T20:59:36.460] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-20T20:59:36.489] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-20T20:59:36.492] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-21T03:50:02.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-21 03:50:02 +[2025-07-21T04:53:42.982] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-21T04:53:42.984] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-21T04:53:42.987] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-21T20:34:22.806] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-21T20:34:22.833] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-21T20:34:22.836] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-22T03:50:03.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-22 03:50:03 +[2025-07-22T04:53:34.555] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-22T04:53:34.558] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-22T04:53:34.561] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-22T09:31:07.795] [INFO] monitorLogs - turnLine on - (line, SETTINGS.maintenance_mode) 0 true command received from platform +[2025-07-22T09:31:21.826] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false command received from platform +[2025-07-22T09:32:37.346] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false command received from platform +[2025-07-22T09:32:44.385] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false command received from platform +[2025-07-22T09:40:18.138] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false command received from platform +[2025-07-22T20:59:19.131] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-22T20:59:19.134] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-22T20:59:19.135] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-23T03:50:04.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-23 03:50:04 +[2025-07-23T04:55:56.040] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-23T04:55:56.042] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-23T04:55:56.044] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-23T08:07:24.159] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-07-23T08:07:29.510] [INFO] monitorLogs - buildTasks - params undefined +[2025-07-23T08:07:29.515] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-07-23T08:07:29.516] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-07-23T08:07:29.517] [INFO] monitorLogs - profile: { + 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 +} +[2025-07-23T08:07:29.521] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-07-23T08:07:29.522] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-07-24T03:44:00.521Z +[2025-07-23T08:07:29.524] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-07-23T19:12:00.523Z +[2025-07-23T08:07:29.524] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '5:44', name: 'luxOff' }, + { value: 1, start_time: '21:12', name: 'luxOn' } +] +[2025-07-23T08:07:29.526] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-07-23T08:07:29.526] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-07-23T08:07:29.527] [INFO] monitorLogs - profile: { + 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 +} +[2025-07-23T08:07:29.529] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-07-23T08:07:29.530] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-07-24T03:44:00.530Z +[2025-07-23T08:07:29.531] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-07-23T19:12:00.531Z +[2025-07-23T08:07:29.531] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '5:44', name: 'luxOff' }, + { value: 1, start_time: '21:12', name: 'luxOn' } +] +[2025-07-23T08:07:29.532] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-07-23T08:07:29.533] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-07-23T08:07:29.534] [INFO] monitorLogs - profile: { + 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 +} +[2025-07-23T08:07:29.536] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-07-23T08:07:29.537] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-07-24T03:44:00.537Z +[2025-07-23T08:07:29.537] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-07-23T19:12:00.537Z +[2025-07-23T08:07:29.538] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '5:44', name: 'luxOff' }, + { value: 1, start_time: '21:12', name: 'luxOn' } +] +[2025-07-23T08:07:29.539] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-07-23T08:07:29.543] [INFO] monitorLogs - tasks created: 504 +[2025-07-23T08:07:29.545] [INFO] monitorLogs - -->FLOW bol spustený WlVJBygjDZMeKX3vnAMRrQ08NqdmG2x1Y69LQ4P5 2025-07-08 +[2025-07-23T08:07:34.551] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-23T20:57:51.978] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-23T20:57:52.001] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-23T20:57:52.003] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-24T03:07:32.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-24 03:07:32 +[2025-07-24T04:59:31.010] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-24T04:59:31.014] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-24T04:59:31.016] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-24T20:50:12.245] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-24T20:50:12.266] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-24T20:50:12.269] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-25T03:07:33.013] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-25 03:07:33 +[2025-07-25T05:01:52.903] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-25T05:01:52.906] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-25T05:01:52.909] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-25T20:47:34.189] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-25T20:47:34.211] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-25T20:47:34.213] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-26T03:07:34.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-26 03:07:34 +[2025-07-26T05:01:44.914] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-26T05:01:44.918] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-26T05:01:44.921] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-26T20:52:25.965] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-26T20:52:25.972] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-26T20:52:25.975] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-27T03:07:35.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-27 03:07:35 +[2025-07-27T05:04:07.104] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-27T05:04:07.108] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-27T05:04:07.110] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-27T20:42:15.749] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-27T20:42:15.765] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-27T20:42:15.767] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-28T03:07:36.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-28 03:07:36 +[2025-07-28T05:05:42.105] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-28T05:05:42.107] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-28T05:05:42.109] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-28T07:49:18.689] [INFO] monitorLogs - turnLine on - (line, SETTINGS.maintenance_mode) 0 true command received from platform +[2025-07-28T08:12:49.826] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false command received from platform +[2025-07-28T08:13:02.626] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false command received from platform +[2025-07-28T08:13:06.466] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false command received from platform +[2025-07-28T08:13:14.785] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false command received from platform +[2025-07-28T08:13:19.265] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false command received from platform +[2025-07-28T08:13:34.626] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false command received from platform +[2025-07-28T08:13:43.587] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false command received from platform +[2025-07-28T20:45:35.443] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-28T20:45:35.475] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-28T20:45:35.477] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-29T03:07:38.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-29 03:07:38 +[2025-07-29T05:04:48.432] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-29T05:04:48.436] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-29T05:04:48.438] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-29T12:19:39.070] [INFO] monitorLogs - MQTT client error Error: connect ECONNREFUSED 192.168.252.1:1883 + at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1159:16) { + errno: -111, + code: 'ECONNREFUSED', + syscall: 'connect', + address: '192.168.252.1', + port: 1883 +} +[2025-07-29T20:50:30.219] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-29T20:50:30.254] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-29T20:50:30.257] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-30T03:07:39.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-30 03:07:39 +[2025-07-30T05:04:41.016] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-30T05:04:41.020] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-30T05:04:41.022] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-30T20:45:20.248] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-30T20:45:20.254] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-30T20:45:20.256] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-31T03:07:40.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-31 03:07:40 +[2025-07-31T05:07:02.220] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-31T05:07:02.224] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-31T05:07:02.227] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-31T20:47:41.527] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-31T20:47:41.536] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-31T20:47:41.538] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-01T03:07:41.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-01 03:07:41 +[2025-08-01T05:06:53.052] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-01T05:06:53.056] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-01T05:06:53.058] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-01T20:32:29.211] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-01T20:32:29.219] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-01T20:32:29.221] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-02T03:07:42.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-02 03:07:42 +[2025-08-02T05:09:14.891] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-02T05:09:14.895] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-02T05:09:14.897] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-02T20:37:21.898] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-02T20:37:21.906] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-02T20:37:21.908] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-03T03:07:43.013] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-03 03:07:43 +[2025-08-03T05:19:07.946] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-03T05:19:07.950] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-03T05:19:07.952] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-03T20:42:13.653] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-03T20:42:13.663] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-03T20:42:13.665] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-04T03:07:45.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-04 03:07:45 +[2025-08-04T05:11:28.967] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-04T05:11:28.971] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-04T05:11:28.973] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-04T20:42:06.103] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-04T20:42:06.110] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-04T20:42:06.112] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-05T03:07:46.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-05 03:07:46 +[2025-08-05T05:18:51.452] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-05T05:18:51.456] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-05T05:18:51.458] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-05T20:36:55.955] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-05T20:36:55.975] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-05T20:36:55.977] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-06T03:07:47.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-06 03:07:47 +[2025-08-06T05:13:41.832] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-06T05:13:41.836] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-06T05:13:41.838] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-06T13:46:19.163] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-08-06T13:46:24.514] [INFO] monitorLogs - buildTasks - params undefined +[2025-08-06T13:46:24.518] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-08-06T13:46:24.519] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-08-06T13:46:24.520] [INFO] monitorLogs - profile: { + 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 +} +[2025-08-06T13:46:24.524] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-08-06T13:46:24.526] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-08-07T04:02:00.525Z +[2025-08-06T13:46:24.527] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-08-06T18:53:00.527Z +[2025-08-06T13:46:24.528] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '6:2', name: 'luxOff' }, + { value: 1, start_time: '20:53', name: 'luxOn' } +] +[2025-08-06T13:46:24.529] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-08-06T13:46:24.530] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-08-06T13:46:24.530] [INFO] monitorLogs - profile: { + 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 +} +[2025-08-06T13:46:24.533] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-08-06T13:46:24.533] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-08-07T04:02:00.533Z +[2025-08-06T13:46:24.534] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-08-06T18:53:00.534Z +[2025-08-06T13:46:24.535] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '6:2', name: 'luxOff' }, + { value: 1, start_time: '20:53', name: 'luxOn' } +] +[2025-08-06T13:46:24.536] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-08-06T13:46:24.537] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-08-06T13:46:24.537] [INFO] monitorLogs - profile: { + 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 +} +[2025-08-06T13:46:24.539] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-08-06T13:46:24.540] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-08-07T04:02:00.540Z +[2025-08-06T13:46:24.541] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-08-06T18:53:00.541Z +[2025-08-06T13:46:24.541] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '6:2', name: 'luxOff' }, + { value: 1, start_time: '20:53', name: 'luxOn' } +] +[2025-08-06T13:46:24.542] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-08-06T13:46:24.546] [INFO] monitorLogs - tasks created: 504 +[2025-08-06T13:46:24.548] [INFO] monitorLogs - -->FLOW bol spustený WlVJBygjDZMeKX3vnAMRrQ08NqdmG2x1Y69LQ4P5 2025-08-08 +[2025-08-06T13:46:29.554] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-06T20:35:33.827] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-06T20:35:33.857] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-06T20:35:33.860] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-07T03:46:26.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-07 03:46:26 +[2025-08-07T05:17:20.448] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-07T05:17:20.452] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-07T05:17:20.454] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-07T20:35:25.120] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-07T20:35:25.131] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-07T20:35:25.133] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-08T03:46:28.013] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-08 03:46:28 +[2025-08-08T05:17:14.018] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-08T05:17:14.023] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-08T05:17:14.025] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-08T20:35:19.596] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-08T20:35:19.615] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-08T20:35:19.617] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-09T03:46:29.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-09 03:46:29 +[2025-08-09T05:17:06.254] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-09T05:17:06.258] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-09T05:17:06.261] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-09T20:35:10.940] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-09T20:35:10.960] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-09T20:35:10.962] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-10T03:46:30.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-10 03:46:30 +[2025-08-10T05:19:27.516] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-10T05:19:27.520] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-10T05:19:27.522] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-10T20:32:32.373] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-10T20:32:32.385] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-10T20:32:32.387] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-11T03:46:32.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-11 03:46:32 +[2025-08-11T05:21:50.962] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-11T05:21:50.966] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-11T05:21:50.968] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-11T20:29:54.389] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-11T20:29:54.423] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-11T20:29:54.425] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-12T03:46:33.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-12 03:46:33 +[2025-08-12T05:21:42.622] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-12T05:21:42.626] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-12T05:21:42.628] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-12T20:29:46.425] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-12T20:29:46.443] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-12T20:29:46.445] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-13T03:46:34.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-13 03:46:34 +[2025-08-13T05:24:05.318] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-13T05:24:05.322] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-13T05:24:05.324] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-13T20:27:07.047] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-13T20:27:07.055] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-13T20:27:07.057] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-14T03:46:35.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-14 03:46:35 +[2025-08-14T05:26:26.782] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-14T05:26:26.785] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-14T05:26:26.788] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-14T20:24:28.696] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-14T20:24:28.703] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-14T20:24:28.705] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-15T03:46:37.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-15 03:46:37 +[2025-08-15T05:26:19.579] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-15T05:26:19.583] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-15T05:26:19.585] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-15T20:21:49.561] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-15T20:21:49.568] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-15T20:21:49.570] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-16T03:46:38.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-16 03:46:38 +[2025-08-16T05:28:40.856] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-16T05:28:40.860] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-16T05:28:40.862] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-16T20:19:09.987] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-16T20:19:10.002] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-16T20:19:10.005] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-17T03:46:39.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-17 03:46:39 +[2025-08-17T05:31:02.084] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-17T05:31:02.087] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-17T05:31:02.089] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-17T20:19:00.399] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-17T20:19:00.416] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-17T20:19:00.419] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-18T03:46:41.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-18 03:46:41 +[2025-08-18T05:30:53.557] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-18T05:30:53.561] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-18T05:30:53.563] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-18T20:18:52.236] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-18T20:18:52.243] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-18T20:18:52.245] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-19T03:46:42.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-19 03:46:42 +[2025-08-19T05:33:14.778] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-19T05:33:14.781] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-19T05:33:14.783] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-19T20:16:12.158] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-19T20:16:12.160] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-19T20:16:12.162] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-20T03:46:43.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-20 03:46:43 +[2025-08-20T05:33:06.357] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-20T05:33:06.361] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-20T05:33:06.363] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-20T11:16:57.395] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false command received from platform +[2025-08-20T11:17:04.754] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false command received from platform +[2025-08-20T11:17:14.985] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false command received from platform +[2025-08-20T11:24:10.339] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false command received from platform +[2025-08-20T11:24:18.978] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false command received from platform +[2025-08-20T11:24:29.126] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false command received from platform +[2025-08-20T16:51:49.567] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-08-20T16:51:54.983] [INFO] monitorLogs - buildTasks - params undefined +[2025-08-20T16:51:54.988] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-08-20T16:51:54.989] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-08-20T16:51:54.990] [INFO] monitorLogs - profile: { + 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 +} +[2025-08-20T16:51:54.994] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-08-20T16:51:54.995] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-08-21T04:21:00.995Z +[2025-08-20T16:51:54.997] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-08-20T18:28:00.997Z +[2025-08-20T16:51:54.997] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '6:21', name: 'luxOff' }, + { value: 1, start_time: '20:28', name: 'luxOn' } +] +[2025-08-20T16:51:54.999] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-08-20T16:51:54.999] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-08-20T16:51:55.000] [INFO] monitorLogs - profile: { + 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 +} +[2025-08-20T16:51:55.002] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-08-20T16:51:55.003] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-08-21T04:21:00.003Z +[2025-08-20T16:51:55.004] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-08-20T18:28:00.004Z +[2025-08-20T16:51:55.004] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '6:21', name: 'luxOff' }, + { value: 1, start_time: '20:28', name: 'luxOn' } +] +[2025-08-20T16:51:55.005] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-08-20T16:51:55.006] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-08-20T16:51:55.007] [INFO] monitorLogs - profile: { + 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 +} +[2025-08-20T16:51:55.009] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-08-20T16:51:55.010] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-08-21T04:21:00.009Z +[2025-08-20T16:51:55.010] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-08-20T18:28:00.010Z +[2025-08-20T16:51:55.011] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '6:21', name: 'luxOff' }, + { value: 1, start_time: '20:28', name: 'luxOn' } +] +[2025-08-20T16:51:55.012] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-08-20T16:51:55.016] [INFO] monitorLogs - tasks created: 504 +[2025-08-20T16:51:55.018] [INFO] monitorLogs - -->FLOW bol spustený WlVJBygjDZMeKX3vnAMRrQ08NqdmG2x1Y69LQ4P5 2025-08-08 +[2025-08-20T16:52:00.024] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-20T20:12:51.859] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-20T20:12:51.867] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-20T20:12:51.870] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-21T03:51:58.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-21 03:51:58 +[2025-08-21T05:39:49.657] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-21T05:39:49.661] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-21T05:39:49.663] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-21T19:57:42.378] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-21T19:57:42.394] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-21T19:57:42.396] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-22T03:51:59.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-22 03:51:59 +[2025-08-22T05:44:41.513] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-22T05:44:41.517] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-22T05:44:41.520] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-22T20:07:34.699] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-22T20:07:34.702] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-22T20:07:34.704] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-23T03:52:00.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-23 03:52:00 +[2025-08-23T05:42:01.582] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-23T05:42:01.591] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-23T05:42:01.593] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-23T20:07:26.158] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-23T20:07:26.166] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-23T20:07:26.168] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-24T03:52:01.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-24 03:52:01 +[2025-08-24T05:39:23.626] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-24T05:39:23.631] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-24T05:39:23.633] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-24T20:04:47.367] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-24T20:04:47.370] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-24T20:04:47.372] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-25T03:52:03.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-25 03:52:03 +[2025-08-25T05:44:15.951] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-25T05:44:15.955] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-25T05:44:15.957] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-25T20:02:08.168] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-25T20:02:08.176] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-25T20:02:08.179] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-26T03:52:04.013] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-26 03:52:04 +[2025-08-26T05:44:06.348] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-26T05:44:06.352] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-26T05:44:06.355] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-26T19:59:29.660] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-26T19:59:29.685] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-26T19:59:29.688] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-27T03:52:05.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-27 03:52:05 +[2025-08-27T05:46:29.674] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-27T05:46:29.678] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-27T05:46:29.680] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-27T19:59:21.030] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-27T19:59:21.040] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-27T19:59:21.042] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-28T03:52:06.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-28 03:52:06 +[2025-08-28T05:46:20.196] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-28T05:46:20.200] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-28T05:46:20.202] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-28T19:56:40.829] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-28T19:56:40.836] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-28T19:56:40.838] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-29T03:52:07.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-29 03:52:07 +[2025-08-29T05:48:40.918] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-29T05:48:40.921] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-29T05:48:40.924] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-29T19:46:29.837] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-29T19:46:29.840] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-29T19:46:29.842] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-30T03:52:09.013] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-30 03:52:09 +[2025-08-30T05:48:33.745] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-30T05:48:33.748] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-30T05:48:33.750] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-30T19:41:21.016] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-30T19:41:21.026] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-30T19:41:21.028] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-31T03:52:10.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-31 03:52:10 +[2025-08-31T06:03:27.223] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-31T06:03:27.226] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-31T06:03:27.228] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-31T19:51:13.470] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-31T19:51:13.483] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-31T19:51:13.485] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-01T03:52:11.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-01 03:52:11 +[2025-09-01T05:53:16.585] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-01T05:53:16.589] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-01T05:53:16.591] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-01T08:55:47.162] [INFO] monitorLogs - turnLine on - (line, SETTINGS.maintenance_mode) 0 true command received from platform +[2025-09-01T08:55:51.615] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false command received from platform +[2025-09-01T08:55:58.495] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false command received from platform +[2025-09-01T08:56:07.938] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false command received from platform +[2025-09-01T09:18:31.596] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false command received from platform +[2025-09-01T09:18:35.115] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false command received from platform +[2025-09-01T09:18:41.195] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false command received from platform +[2025-09-01T09:18:49.195] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false command received from platform +[2025-09-01T14:30:49.160] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-09-01T14:30:54.510] [INFO] monitorLogs - buildTasks - params undefined +[2025-09-01T14:30:54.514] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-09-01T14:30:54.515] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-09-01T14:30:54.516] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-01T14:30:54.520] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-01T14:30:54.522] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-09-02T04:38:00.521Z +[2025-09-01T14:30:54.523] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-09-01T18:05:00.523Z +[2025-09-01T14:30:54.524] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '6:38', name: 'luxOff' }, + { value: 1, start_time: '20:5', name: 'luxOn' } +] +[2025-09-01T14:30:54.525] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-09-01T14:30:54.526] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-09-01T14:30:54.526] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-01T14:30:54.529] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-01T14:30:54.529] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-09-02T04:38:00.529Z +[2025-09-01T14:30:54.530] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-09-01T18:05:00.530Z +[2025-09-01T14:30:54.531] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '6:38', name: 'luxOff' }, + { value: 1, start_time: '20:5', name: 'luxOn' } +] +[2025-09-01T14:30:54.532] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-09-01T14:30:54.533] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-09-01T14:30:54.533] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-01T14:30:54.535] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-01T14:30:54.536] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-09-02T04:38:00.536Z +[2025-09-01T14:30:54.537] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-09-01T18:05:00.537Z +[2025-09-01T14:30:54.537] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '6:38', name: 'luxOff' }, + { value: 1, start_time: '20:5', name: 'luxOn' } +] +[2025-09-01T14:30:54.538] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-09-01T14:30:54.542] [INFO] monitorLogs - tasks created: 504 +[2025-09-01T14:30:54.544] [INFO] monitorLogs - -->FLOW bol spustený WlVJBygjDZMeKX3vnAMRrQ08NqdmG2x1Y69LQ4P5 2025-08-08 +[2025-09-01T14:30:59.550] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-01T19:47:14.895] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-01T19:47:14.903] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-01T19:47:14.906] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-02T03:30:57.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-02 03:30:57 +[2025-09-02T05:51:50.027] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-02T05:51:50.032] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-02T05:51:50.034] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-02T19:39:36.427] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-02T19:39:36.434] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-02T19:39:36.437] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-03T03:30:58.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-03 03:30:58 +[2025-09-03T05:59:12.046] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-03T05:59:12.050] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-03T05:59:12.052] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-03T19:44:27.847] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-03T19:44:27.851] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-03T19:44:27.853] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-04T03:30:59.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-04 03:30:59 +[2025-09-04T05:56:31.979] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-04T05:56:31.984] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-04T05:56:31.986] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-04T19:41:49.174] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-04T19:41:49.189] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-04T19:41:49.192] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-05T03:31:01.015] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-05 03:31:01 +[2025-09-05T05:58:55.761] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-05T05:58:55.765] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-05T05:58:55.767] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-05T19:39:10.506] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-05T19:39:10.508] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-05T19:39:10.510] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-06T03:31:02.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-06 03:31:02 +[2025-09-06T06:11:18.914] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-06T06:11:18.918] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-06T06:11:18.921] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-06T19:39:01.833] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-06T19:39:01.840] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-06T19:39:01.842] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-07T03:31:03.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-07 03:31:03 +[2025-09-07T05:58:38.114] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-07T05:58:38.118] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-07T05:58:38.121] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-07T19:36:23.109] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-07T19:36:23.115] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-07T19:36:23.117] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-08T03:31:04.013] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-08 03:31:04 +[2025-09-08T06:00:59.849] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-08T06:00:59.853] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-08T06:00:59.855] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-08T19:33:43.335] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-08T19:33:43.342] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-08T19:33:43.345] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-09T03:31:05.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-09 03:31:05 +[2025-09-09T06:03:22.008] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-09T06:03:22.012] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-09T06:03:22.014] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-09T19:28:34.678] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-09T19:28:34.689] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-09T19:28:34.691] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-10T03:31:06.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-10 03:31:06 +[2025-09-10T06:05:43.812] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-10T06:05:43.817] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-10T06:05:43.819] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-10T19:18:23.447] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-10T19:18:23.459] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-10T19:18:23.460] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-11T03:31:08.014] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-11 03:31:08 +[2025-09-11T06:13:08.006] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-11T06:13:08.009] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-11T06:13:08.011] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-11T19:28:18.131] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-11T19:28:18.145] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-11T19:28:18.147] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-12T03:31:09.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-12 03:31:09 +[2025-09-12T06:07:57.898] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-12T06:07:57.905] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-12T06:07:57.908] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-12T15:14:53.193] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-09-12T15:14:58.542] [INFO] monitorLogs - buildTasks - params undefined +[2025-09-12T15:14:58.546] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-09-12T15:14:58.547] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-09-12T15:14:58.548] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-12T15:14:58.552] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-12T15:14:58.553] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-09-13T04:54:00.552Z +[2025-09-12T15:14:58.555] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-09-12T17:42:00.554Z +[2025-09-12T15:14:58.555] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '6:54', name: 'luxOff' }, + { value: 1, start_time: '19:42', name: 'luxOn' } +] +[2025-09-12T15:14:58.556] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-09-12T15:14:58.557] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-09-12T15:14:58.558] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-12T15:14:58.560] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-12T15:14:58.561] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-09-13T04:54:00.561Z +[2025-09-12T15:14:58.562] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-09-12T17:42:00.562Z +[2025-09-12T15:14:58.562] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '6:54', name: 'luxOff' }, + { value: 1, start_time: '19:42', name: 'luxOn' } +] +[2025-09-12T15:14:58.563] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-09-12T15:14:58.564] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-09-12T15:14:58.565] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-12T15:14:58.567] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-12T15:14:58.568] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-09-13T04:54:00.567Z +[2025-09-12T15:14:58.568] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-09-12T17:42:00.568Z +[2025-09-12T15:14:58.569] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '6:54', name: 'luxOff' }, + { value: 1, start_time: '19:42', name: 'luxOn' } +] +[2025-09-12T15:14:58.570] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-09-12T15:14:58.574] [INFO] monitorLogs - tasks created: 504 +[2025-09-12T15:14:58.577] [INFO] monitorLogs - -->FLOW bol spustený WlVJBygjDZMeKX3vnAMRrQ08NqdmG2x1Y69LQ4P5 2025-08-08 +[2025-09-12T15:15:03.582] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-12T19:18:34.063] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-12T19:18:34.071] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-12T19:18:34.074] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-13T03:15:00.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-13 03:15:00 +[2025-09-13T06:23:19.609] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-13T06:23:19.613] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-13T06:23:19.615] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-13T19:18:25.342] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-13T19:18:25.350] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-13T19:18:25.352] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-14T03:15:01.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-14 03:15:01 +[2025-09-14T06:23:11.389] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-14T06:23:11.393] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-14T06:23:11.395] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-14T19:20:47.788] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-14T19:20:47.795] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-14T19:20:47.797] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-15T03:15:02.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-15 03:15:02 +[2025-09-15T06:10:31.073] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-15T06:10:31.076] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-15T06:10:31.079] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-15T19:18:09.218] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-15T19:18:09.230] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-15T19:18:09.232] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-16T03:15:03.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-16 03:15:03 +[2025-09-16T06:30:25.661] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-16T06:30:25.665] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-16T06:30:25.667] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-16T15:47:59.430] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-09-16T15:48:04.777] [INFO] monitorLogs - buildTasks - params undefined +[2025-09-16T15:48:04.782] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-09-16T15:48:04.783] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-09-16T15:48:04.784] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-16T15:48:04.788] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-16T15:48:04.790] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-09-17T04:59:00.789Z +[2025-09-16T15:48:04.791] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-09-16T17:33:00.791Z +[2025-09-16T15:48:04.792] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '6:59', name: 'luxOff' }, + { value: 1, start_time: '19:33', name: 'luxOn' } +] +[2025-09-16T15:48:04.793] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-09-16T15:48:04.794] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-09-16T15:48:04.795] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-16T15:48:04.797] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-16T15:48:04.798] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-09-17T04:59:00.798Z +[2025-09-16T15:48:04.799] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-09-16T17:33:00.798Z +[2025-09-16T15:48:04.799] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '6:59', name: 'luxOff' }, + { value: 1, start_time: '19:33', name: 'luxOn' } +] +[2025-09-16T15:48:04.800] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-09-16T15:48:04.801] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-09-16T15:48:04.802] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-16T15:48:04.804] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-16T15:48:04.805] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-09-17T04:59:00.804Z +[2025-09-16T15:48:04.805] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-09-16T17:33:00.805Z +[2025-09-16T15:48:04.806] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '6:59', name: 'luxOff' }, + { value: 1, start_time: '19:33', name: 'luxOn' } +] +[2025-09-16T15:48:04.807] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-09-16T15:48:04.810] [INFO] monitorLogs - tasks created: 504 +[2025-09-16T15:48:04.813] [INFO] monitorLogs - -->FLOW bol spustený WlVJBygjDZMeKX3vnAMRrQ08NqdmG2x1Y69LQ4P5 2025-08-08 +[2025-09-16T15:48:09.819] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-16T19:14:02.684] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-16T19:14:02.690] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-16T19:14:02.693] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-17T03:48:06.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-17 03:48:06 +[2025-09-17T06:18:48.276] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-17T06:18:48.279] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-17T06:18:48.281] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-17T19:16:24.689] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-17T19:16:24.692] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-17T19:16:24.694] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-17T20:44:13.362] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-09-17T20:44:18.709] [INFO] monitorLogs - buildTasks - params undefined +[2025-09-17T20:44:18.714] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-09-17T20:44:18.715] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-09-17T20:44:18.716] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-17T20:44:18.720] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-17T20:44:18.722] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-09-18T05:01:00.721Z +[2025-09-17T20:44:18.723] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-09-18T17:31:00.723Z +[2025-09-17T20:44:18.724] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:1', name: 'luxOff' }, + { value: 1, start_time: '19:31', name: 'luxOn' } +] +[2025-09-17T20:44:18.725] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-09-17T20:44:18.726] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-09-17T20:44:18.727] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-17T20:44:18.729] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-17T20:44:18.730] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-09-18T05:01:00.730Z +[2025-09-17T20:44:18.731] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-09-18T17:31:00.730Z +[2025-09-17T20:44:18.731] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:1', name: 'luxOff' }, + { value: 1, start_time: '19:31', name: 'luxOn' } +] +[2025-09-17T20:44:18.732] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-09-17T20:44:18.733] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-09-17T20:44:18.733] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-17T20:44:18.736] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-17T20:44:18.736] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-09-18T05:01:00.736Z +[2025-09-17T20:44:18.737] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-09-18T17:31:00.737Z +[2025-09-17T20:44:18.738] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:1', name: 'luxOff' }, + { value: 1, start_time: '19:31', name: 'luxOn' } +] +[2025-09-17T20:44:18.739] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-09-17T20:44:18.742] [INFO] monitorLogs - tasks created: 504 +[2025-09-17T20:44:18.744] [INFO] monitorLogs - -->FLOW bol spustený WlVJBygjDZMeKX3vnAMRrQ08NqdmG2x1Y69LQ4P5 2025-08-08 +[2025-09-17T20:44:23.751] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-18T03:44:21.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-18 03:44:21 +[2025-09-18T06:21:33.816] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-18T06:21:33.819] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-18T06:21:33.821] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-18T19:14:09.140] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-18T19:14:09.183] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-18T19:14:09.185] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-19T03:44:22.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-19 03:44:22 +[2025-09-19T06:16:24.763] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-19T06:16:24.766] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-19T06:16:24.768] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-19T11:23:50.711] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-09-19T11:23:56.052] [INFO] monitorLogs - buildTasks - params undefined +[2025-09-19T11:23:56.057] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-09-19T11:23:56.058] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-09-19T11:23:56.058] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-19T11:23:56.062] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-19T11:23:56.064] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-09-20T05:04:00.063Z +[2025-09-19T11:23:56.065] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-09-19T17:27:00.065Z +[2025-09-19T11:23:56.066] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:4', name: 'luxOff' }, + { value: 1, start_time: '19:27', name: 'luxOn' } +] +[2025-09-19T11:23:56.067] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-09-19T11:23:56.068] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-09-19T11:23:56.069] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-19T11:23:56.071] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-19T11:23:56.072] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-09-20T05:04:00.072Z +[2025-09-19T11:23:56.073] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-09-19T17:27:00.072Z +[2025-09-19T11:23:56.073] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:4', name: 'luxOff' }, + { value: 1, start_time: '19:27', name: 'luxOn' } +] +[2025-09-19T11:23:56.074] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-09-19T11:23:56.075] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-09-19T11:23:56.076] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-19T11:23:56.078] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-19T11:23:56.078] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-09-20T05:04:00.078Z +[2025-09-19T11:23:56.079] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-09-19T17:27:00.079Z +[2025-09-19T11:23:56.080] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:4', name: 'luxOff' }, + { value: 1, start_time: '19:27', name: 'luxOn' } +] +[2025-09-19T11:23:56.081] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-09-19T11:23:56.084] [INFO] monitorLogs - tasks created: 504 +[2025-09-19T11:23:56.087] [INFO] monitorLogs - -->FLOW bol spustený WlVJBygjDZMeKX3vnAMRrQ08NqdmG2x1Y69LQ4P5 2025-08-08 +[2025-09-19T11:24:01.093] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-19T19:10:47.137] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-19T19:10:47.150] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-19T19:10:47.152] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-20T03:23:57.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-20 03:23:57 +[2025-09-20T06:18:02.435] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-20T06:18:02.439] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-20T06:18:02.441] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-20T19:08:07.598] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-20T19:08:07.600] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-20T19:08:07.602] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-21T01:29:23.147] [INFO] monitorLogs - MQTT client error Error: connect ECONNREFUSED 192.168.252.1:1883 + at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1159:16) { + errno: -111, + code: 'ECONNREFUSED', + syscall: 'connect', + address: '192.168.252.1', + port: 1883 +} +[2025-09-21T03:23:59.016] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-21 03:23:59 +[2025-09-21T06:17:55.304] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-21T06:17:55.307] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-21T06:17:55.309] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-21T18:13:52.196] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-09-21T18:13:57.554] [INFO] monitorLogs - buildTasks - params undefined +[2025-09-21T18:13:57.559] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-09-21T18:13:57.560] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-09-21T18:13:57.560] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-21T18:13:57.564] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-21T18:13:57.566] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-09-22T05:06:00.565Z +[2025-09-21T18:13:57.567] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-09-21T17:23:00.567Z +[2025-09-21T18:13:57.568] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:6', name: 'luxOff' }, + { value: 1, start_time: '19:23', name: 'luxOn' } +] +[2025-09-21T18:13:57.569] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-09-21T18:13:57.570] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-09-21T18:13:57.570] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-21T18:13:57.573] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-21T18:13:57.574] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-09-22T05:06:00.573Z +[2025-09-21T18:13:57.574] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-09-21T17:23:00.574Z +[2025-09-21T18:13:57.575] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:6', name: 'luxOff' }, + { value: 1, start_time: '19:23', name: 'luxOn' } +] +[2025-09-21T18:13:57.576] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-09-21T18:13:57.577] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-09-21T18:13:57.577] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-21T18:13:57.580] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-21T18:13:57.580] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-09-22T05:06:00.580Z +[2025-09-21T18:13:57.581] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-09-21T17:23:00.581Z +[2025-09-21T18:13:57.582] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:6', name: 'luxOff' }, + { value: 1, start_time: '19:23', name: 'luxOn' } +] +[2025-09-21T18:13:57.583] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-09-21T18:13:57.586] [INFO] monitorLogs - tasks created: 504 +[2025-09-21T18:13:57.588] [INFO] monitorLogs - -->FLOW bol spustený WlVJBygjDZMeKX3vnAMRrQ08NqdmG2x1Y69LQ4P5 2025-08-08 +[2025-09-21T18:14:02.594] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-21T19:06:54.048] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-21T19:06:54.050] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-21T19:06:54.053] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-22T03:13:59.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-22 03:13:59 +[2025-09-22T06:19:11.791] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-22T06:19:11.795] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-22T06:19:11.797] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-22T19:01:45.048] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-22T19:01:45.055] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-22T19:01:45.057] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-23T03:14:00.014] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-23 03:14:00 +[2025-09-23T06:26:34.324] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-23T06:26:34.327] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-23T06:26:34.330] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-23T13:08:59.182] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-09-23T13:09:04.548] [INFO] monitorLogs - buildTasks - params undefined +[2025-09-23T13:09:04.553] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-09-23T13:09:04.554] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-09-23T13:09:04.554] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-23T13:09:04.558] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-23T13:09:04.560] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-09-24T05:09:00.559Z +[2025-09-23T13:09:04.561] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-09-23T17:18:00.561Z +[2025-09-23T13:09:04.562] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:9', name: 'luxOff' }, + { value: 1, start_time: '19:18', name: 'luxOn' } +] +[2025-09-23T13:09:04.563] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-09-23T13:09:04.564] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-09-23T13:09:04.564] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-23T13:09:04.567] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-23T13:09:04.567] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-09-24T05:09:00.567Z +[2025-09-23T13:09:04.568] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-09-23T17:18:00.568Z +[2025-09-23T13:09:04.569] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:9', name: 'luxOff' }, + { value: 1, start_time: '19:18', name: 'luxOn' } +] +[2025-09-23T13:09:04.570] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-09-23T13:09:04.571] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-09-23T13:09:04.571] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-23T13:09:04.573] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-23T13:09:04.574] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-09-24T05:09:00.574Z +[2025-09-23T13:09:04.575] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-09-23T17:18:00.575Z +[2025-09-23T13:09:04.575] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:9', name: 'luxOff' }, + { value: 1, start_time: '19:18', name: 'luxOn' } +] +[2025-09-23T13:09:04.576] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-09-23T13:09:04.580] [INFO] monitorLogs - tasks created: 504 +[2025-09-23T13:09:04.582] [INFO] monitorLogs - -->FLOW bol spustený WlVJBygjDZMeKX3vnAMRrQ08NqdmG2x1Y69LQ4P5 2025-08-08 +[2025-09-23T13:09:09.587] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-23T14:35:30.104] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-09-23T14:35:35.444] [INFO] monitorLogs - buildTasks - params undefined +[2025-09-23T14:35:35.449] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-09-23T14:35:35.450] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-09-23T14:35:35.450] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-23T14:35:35.454] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-23T14:35:35.456] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-09-24T05:09:00.455Z +[2025-09-23T14:35:35.457] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-09-23T17:18:00.457Z +[2025-09-23T14:35:35.458] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:9', name: 'luxOff' }, + { value: 1, start_time: '19:18', name: 'luxOn' } +] +[2025-09-23T14:35:35.459] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-09-23T14:35:35.460] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-09-23T14:35:35.460] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-23T14:35:35.463] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-23T14:35:35.463] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-09-24T05:09:00.463Z +[2025-09-23T14:35:35.464] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-09-23T17:18:00.464Z +[2025-09-23T14:35:35.465] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:9', name: 'luxOff' }, + { value: 1, start_time: '19:18', name: 'luxOn' } +] +[2025-09-23T14:35:35.466] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-09-23T14:35:35.467] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-09-23T14:35:35.467] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-23T14:35:35.469] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-23T14:35:35.470] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-09-24T05:09:00.470Z +[2025-09-23T14:35:35.471] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-09-23T17:18:00.471Z +[2025-09-23T14:35:35.471] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:9', name: 'luxOff' }, + { value: 1, start_time: '19:18', name: 'luxOn' } +] +[2025-09-23T14:35:35.472] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-09-23T14:35:35.476] [INFO] monitorLogs - tasks created: 504 +[2025-09-23T14:35:35.478] [INFO] monitorLogs - -->FLOW bol spustený WlVJBygjDZMeKX3vnAMRrQ08NqdmG2x1Y69LQ4P5 2025-08-08 +[2025-09-23T14:35:40.483] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-23T18:54:14.072] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-23T18:54:14.080] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-23T18:54:14.082] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-24T03:35:37.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-24 03:35:37 +[2025-09-24T06:39:07.998] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-24T06:39:08.001] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-24T06:39:08.004] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-24T18:51:35.227] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-24T18:51:35.229] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-24T18:51:35.231] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-25T03:35:38.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-25 03:35:38 +[2025-09-25T06:44:00.237] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-25T06:44:00.241] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-25T06:44:00.243] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-25T16:04:46.259] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-09-25T16:04:51.625] [INFO] monitorLogs - buildTasks - params undefined +[2025-09-25T16:04:51.630] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-09-25T16:04:51.631] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-09-25T16:04:51.631] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-25T16:04:51.635] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-25T16:04:51.637] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-09-26T05:12:00.636Z +[2025-09-25T16:04:51.638] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-09-25T17:14:00.638Z +[2025-09-25T16:04:51.639] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:12', name: 'luxOff' }, + { value: 1, start_time: '19:14', name: 'luxOn' } +] +[2025-09-25T16:04:51.640] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-09-25T16:04:51.641] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-09-25T16:04:51.641] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-25T16:04:51.644] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-25T16:04:51.644] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-09-26T05:12:00.644Z +[2025-09-25T16:04:51.645] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-09-25T17:14:00.645Z +[2025-09-25T16:04:51.646] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:12', name: 'luxOff' }, + { value: 1, start_time: '19:14', name: 'luxOn' } +] +[2025-09-25T16:04:51.647] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-09-25T16:04:51.648] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-09-25T16:04:51.648] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-25T16:04:51.650] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-25T16:04:51.651] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-09-26T05:12:00.651Z +[2025-09-25T16:04:51.652] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-09-25T17:14:00.652Z +[2025-09-25T16:04:51.652] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:12', name: 'luxOff' }, + { value: 1, start_time: '19:14', name: 'luxOn' } +] +[2025-09-25T16:04:51.653] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-09-25T16:04:51.657] [INFO] monitorLogs - tasks created: 504 +[2025-09-25T16:04:51.677] [INFO] monitorLogs - -->FLOW bol spustený WlVJBygjDZMeKX3vnAMRrQ08NqdmG2x1Y69LQ4P5 2025-08-08 +[2025-09-25T16:04:56.665] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-25T16:35:49.035] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-09-25T16:35:54.377] [INFO] monitorLogs - buildTasks - params undefined +[2025-09-25T16:35:54.382] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-09-25T16:35:54.383] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-09-25T16:35:54.383] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-25T16:35:54.388] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-25T16:35:54.389] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-09-26T05:12:00.388Z +[2025-09-25T16:35:54.391] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-09-25T17:14:00.390Z +[2025-09-25T16:35:54.391] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:12', name: 'luxOff' }, + { value: 1, start_time: '19:14', name: 'luxOn' } +] +[2025-09-25T16:35:54.392] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-09-25T16:35:54.393] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-09-25T16:35:54.394] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-25T16:35:54.397] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-25T16:35:54.397] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-09-26T05:12:00.397Z +[2025-09-25T16:35:54.398] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-09-25T17:14:00.398Z +[2025-09-25T16:35:54.399] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:12', name: 'luxOff' }, + { value: 1, start_time: '19:14', name: 'luxOn' } +] +[2025-09-25T16:35:54.400] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-09-25T16:35:54.400] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-09-25T16:35:54.401] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-25T16:35:54.403] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-25T16:35:54.404] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-09-26T05:12:00.404Z +[2025-09-25T16:35:54.405] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-09-25T17:14:00.405Z +[2025-09-25T16:35:54.405] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:12', name: 'luxOff' }, + { value: 1, start_time: '19:14', name: 'luxOn' } +] +[2025-09-25T16:35:54.406] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-09-25T16:35:54.410] [INFO] monitorLogs - tasks created: 504 +[2025-09-25T16:35:54.413] [INFO] monitorLogs - -->FLOW bol spustený WlVJBygjDZMeKX3vnAMRrQ08NqdmG2x1Y69LQ4P5 2025-08-08 +[2025-09-25T16:35:59.418] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-25T18:41:35.821] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-25T18:41:35.824] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-25T18:41:35.827] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-26T03:35:56.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-26 03:35:56 +[2025-09-26T06:36:32.179] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-26T06:36:32.183] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-26T06:36:32.184] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-26T18:54:00.509] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-26T18:54:00.513] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-26T18:54:00.515] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-27T03:35:57.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-27 03:35:57 +[2025-09-27T06:36:23.086] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-27T06:36:23.090] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-27T06:36:23.092] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-27T18:53:51.469] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-27T18:53:51.471] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-27T18:53:51.473] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-28T03:35:58.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-28 03:35:58 +[2025-09-28T06:36:13.934] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-28T06:36:13.937] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-28T06:36:13.939] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-28T18:51:11.658] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-28T18:51:11.660] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-28T18:51:11.662] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-29T03:35:59.042] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-29 03:35:59 +[2025-09-29T06:31:03.655] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-29T06:31:03.658] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-29T06:31:03.660] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-29T18:51:02.502] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-29T18:51:02.504] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-29T18:51:02.506] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-30T03:36:00.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-30 03:36:00 +[2025-09-30T06:30:54.561] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-30T06:30:54.564] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-30T06:30:54.566] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-30T18:48:22.981] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-30T18:48:22.983] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-30T18:48:22.985] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-01T03:36:01.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-01 03:36:01 +[2025-10-01T06:38:17.092] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-01T06:38:17.098] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-01T06:38:17.100] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-01T18:45:44.017] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-01T18:45:44.032] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-01T18:45:44.034] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-02T03:36:02.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-02 03:36:02 +[2025-10-02T06:35:38.105] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-02T06:35:38.109] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-02T06:35:38.111] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-02T18:43:04.384] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-02T18:43:04.386] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-02T18:43:04.388] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-03T03:36:03.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-03 03:36:03 +[2025-10-03T06:38:00.114] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-03T06:38:00.118] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-03T06:38:00.119] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-03T14:51:33.865] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-03T14:51:39.227] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-03T14:51:39.232] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-03T14:51:39.233] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-03T14:51:39.234] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-03T14:51:39.238] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-03T14:51:39.239] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-10-04T05:23:00.238Z +[2025-10-03T14:51:39.241] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-10-03T16:57:00.240Z +[2025-10-03T14:51:39.241] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:23', name: 'luxOff' }, + { value: 1, start_time: '18:57', name: 'luxOn' } +] +[2025-10-03T14:51:39.242] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-10-03T14:51:39.243] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-03T14:51:39.244] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-03T14:51:39.246] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-03T14:51:39.247] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-10-04T05:23:00.247Z +[2025-10-03T14:51:39.248] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-10-03T16:57:00.248Z +[2025-10-03T14:51:39.249] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:23', name: 'luxOff' }, + { value: 1, start_time: '18:57', name: 'luxOn' } +] +[2025-10-03T14:51:39.250] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-10-03T14:51:39.250] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-03T14:51:39.251] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-03T14:51:39.253] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-03T14:51:39.254] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-10-04T05:23:00.254Z +[2025-10-03T14:51:39.254] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-10-03T16:57:00.254Z +[2025-10-03T14:51:39.255] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:23', name: 'luxOff' }, + { value: 1, start_time: '18:57', name: 'luxOn' } +] +[2025-10-03T14:51:39.256] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-10-03T14:51:39.259] [INFO] monitorLogs - tasks created: 504 +[2025-10-03T14:51:39.262] [INFO] monitorLogs - -->FLOW bol spustený WlVJBygjDZMeKX3vnAMRrQ08NqdmG2x1Y69LQ4P5 2025-08-08 +[2025-10-03T14:51:44.268] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-03T18:40:11.781] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-03T18:40:11.787] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-03T18:40:11.790] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-04T03:51:40.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-04 03:51:40 +[2025-10-04T06:37:37.343] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-04T06:37:37.347] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-04T06:37:37.349] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-04T18:32:31.260] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-04T18:32:31.263] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-04T18:32:31.265] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-05T03:51:41.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-05 03:51:41 +[2025-10-05T06:39:58.737] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-05T06:39:58.740] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-05T06:39:58.742] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-05T18:34:53.310] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-05T18:34:53.317] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-05T18:34:53.319] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-06T03:51:42.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-06 03:51:42 +[2025-10-06T06:49:52.663] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-06T06:49:52.666] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-06T06:49:52.668] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-06T18:27:12.793] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-06T18:27:12.795] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-06T18:27:12.797] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-07T03:51:43.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-07 03:51:43 +[2025-10-07T06:47:13.275] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-07T06:47:13.279] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-07T06:47:13.281] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-07T18:32:06.758] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-07T18:32:06.767] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-07T18:32:06.769] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-08T03:51:44.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-08 03:51:44 +[2025-10-08T06:44:35.743] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-08T06:44:35.746] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-08T06:44:35.749] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-08T18:29:27.356] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-08T18:29:27.359] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-08T18:29:27.361] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-09T03:51:45.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-09 03:51:45 +[2025-10-09T06:56:58.880] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-09T06:56:58.884] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-09T06:56:58.886] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-09T16:56:42.088] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-09T16:56:47.424] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-09T16:56:47.430] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-09T16:56:47.431] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-09T16:56:47.431] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-09T16:56:47.436] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T16:56:47.437] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-10-10T05:32:00.436Z +[2025-10-09T16:56:47.438] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-10-09T16:45:00.438Z +[2025-10-09T16:56:47.439] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T16:56:47.440] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-10-09T16:56:47.441] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-09T16:56:47.442] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-09T16:56:47.444] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T16:56:47.445] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-10-10T05:32:00.445Z +[2025-10-09T16:56:47.446] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-10-09T16:45:00.445Z +[2025-10-09T16:56:47.446] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T16:56:47.447] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-10-09T16:56:47.448] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-09T16:56:47.448] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-09T16:56:47.451] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T16:56:47.451] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-10-10T05:32:00.451Z +[2025-10-09T16:56:47.452] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-10-09T16:45:00.452Z +[2025-10-09T16:56:47.453] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T16:56:47.454] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-10-09T16:56:47.457] [INFO] monitorLogs - tasks created: 504 +[2025-10-09T16:56:47.460] [INFO] monitorLogs - -->FLOW bol spustený WlVJBygjDZMeKX3vnAMRrQ08NqdmG2x1Y69LQ4P5 2025-08-08 +[2025-10-09T16:56:52.464] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-09T17:14:16.260] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-09T17:14:21.615] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-09T17:14:21.620] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-09T17:14:21.621] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-09T17:14:21.621] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-09T17:14:21.625] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T17:14:21.627] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-10-10T05:32:00.626Z +[2025-10-09T17:14:21.628] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-10-09T16:45:00.628Z +[2025-10-09T17:14:21.629] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T17:14:21.630] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-10-09T17:14:21.631] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-09T17:14:21.631] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-09T17:14:21.634] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T17:14:21.634] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-10-10T05:32:00.634Z +[2025-10-09T17:14:21.635] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-10-09T16:45:00.635Z +[2025-10-09T17:14:21.636] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T17:14:21.637] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-10-09T17:14:21.638] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-09T17:14:21.638] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-09T17:14:21.640] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T17:14:21.641] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-10-10T05:32:00.641Z +[2025-10-09T17:14:21.642] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-10-09T16:45:00.642Z +[2025-10-09T17:14:21.642] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T17:14:21.643] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-10-09T17:14:21.647] [INFO] monitorLogs - tasks created: 504 +[2025-10-09T17:14:21.649] [INFO] monitorLogs - -->FLOW bol spustený WlVJBygjDZMeKX3vnAMRrQ08NqdmG2x1Y69LQ4P5 2025-08-08 +[2025-10-09T17:14:26.654] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-09T18:24:51.764] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-09T18:24:51.767] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-09T18:24:51.770] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-09T19:09:14.497] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-09T19:09:19.836] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-09T19:09:19.841] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-09T19:09:19.842] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-09T19:09:19.843] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-09T19:09:19.847] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T19:09:19.848] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-10-10T05:32:00.847Z +[2025-10-09T19:09:19.850] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-10-10T16:45:00.849Z +[2025-10-09T19:09:19.850] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T19:09:19.851] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-10-09T19:09:19.852] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-09T19:09:19.853] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-09T19:09:19.855] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T19:09:19.856] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-10-10T05:32:00.856Z +[2025-10-09T19:09:19.857] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-10-10T16:45:00.857Z +[2025-10-09T19:09:19.858] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T19:09:19.859] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-10-09T19:09:19.859] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-09T19:09:19.860] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-09T19:09:19.862] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T19:09:19.863] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-10-10T05:32:00.863Z +[2025-10-09T19:09:19.863] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-10-10T16:45:00.863Z +[2025-10-09T19:09:19.864] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T19:09:19.865] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-10-09T19:09:19.869] [INFO] monitorLogs - tasks created: 504 +[2025-10-09T19:09:19.872] [INFO] monitorLogs - -->FLOW bol spustený WlVJBygjDZMeKX3vnAMRrQ08NqdmG2x1Y69LQ4P5 2025-08-08 +[2025-10-09T19:09:24.877] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-10T03:09:21.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-10 03:09:21 +[2025-10-10T06:56:59.755] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-10T06:56:59.758] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-10T06:56:59.760] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-10T18:21:47.450] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-10T18:21:47.452] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-10T18:21:47.454] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-11T03:09:22.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-11 03:09:22 +[2025-10-11T06:59:23.287] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-11T06:59:23.291] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-11T06:59:23.293] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-11T18:24:10.973] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-11T18:24:10.979] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-11T18:24:10.981] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-12T03:09:23.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-12 03:09:23 +[2025-10-12T06:56:44.288] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-12T06:56:44.291] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-12T06:56:44.293] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-12T18:21:32.221] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-12T18:21:32.274] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-12T18:21:32.276] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-13T03:09:24.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-13 03:09:24 +[2025-10-13T06:51:35.393] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-13T06:51:35.397] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-13T06:51:35.399] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-13T18:23:55.645] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-13T18:23:55.651] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-13T18:23:55.653] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-14T03:09:25.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-14 03:09:25 +[2025-10-14T06:53:58.463] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-14T06:53:58.469] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-14T06:53:58.471] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-14T18:16:16.069] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-14T18:16:16.077] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-14T18:16:16.079] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-15T03:09:26.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-15 03:09:26 +[2025-10-15T07:01:21.460] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-15T07:01:21.463] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-15T07:01:21.465] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-15T12:00:26.187] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-15T12:00:31.556] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-15T12:00:31.561] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-15T12:00:31.562] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-15T12:00:31.563] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-15T12:00:31.567] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-15T12:00:31.568] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-10-16T05:41:00.568Z +[2025-10-15T12:00:31.570] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-10-15T16:33:00.570Z +[2025-10-15T12:00:31.570] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:41', name: 'luxOff' }, + { value: 1, start_time: '18:33', name: 'luxOn' } +] +[2025-10-15T12:00:31.572] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-10-15T12:00:31.573] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-15T12:00:31.573] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-15T12:00:31.575] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-15T12:00:31.576] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-10-16T05:41:00.576Z +[2025-10-15T12:00:31.577] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-10-15T16:33:00.577Z +[2025-10-15T12:00:31.578] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:41', name: 'luxOff' }, + { value: 1, start_time: '18:33', name: 'luxOn' } +] +[2025-10-15T12:00:31.579] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-10-15T12:00:31.579] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-15T12:00:31.580] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-15T12:00:31.582] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-15T12:00:31.583] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-10-16T05:41:00.583Z +[2025-10-15T12:00:31.584] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-10-15T16:33:00.583Z +[2025-10-15T12:00:31.584] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:41', name: 'luxOff' }, + { value: 1, start_time: '18:33', name: 'luxOn' } +] +[2025-10-15T12:00:31.585] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-10-15T12:00:31.589] [INFO] monitorLogs - tasks created: 504 +[2025-10-15T12:00:31.591] [INFO] monitorLogs - -->FLOW bol spustený WlVJBygjDZMeKX3vnAMRrQ08NqdmG2x1Y69LQ4P5 2025-10-08 +[2025-10-15T12:00:36.597] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-15T18:14:33.779] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-15T18:14:33.785] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-15T18:14:33.788] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor diff --git a/RVO23/package-lock.json b/RVO23/package-lock.json new file mode 100755 index 0000000..3c5c1ba --- /dev/null +++ b/RVO23/package-lock.json @@ -0,0 +1,2139 @@ +{ + "name": "emptyproject", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "emptyproject", + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "bitwise": "^2.1.0", + "easy-crc": "0.0.2", + "jsmodbus": "^4.0.6", + "log4js": "^6.3.0", + "moment": "^2.30.1", + "mqtt": "^4.2.6", + "nodemailer": "^6.9.7", + "serialport": "^9.2.8", + "total.js": "^3.4.13" + } + }, + "node_modules/@serialport/binding-abstract": { + "version": "9.2.3", + "resolved": "https://registry.npmjs.org/@serialport/binding-abstract/-/binding-abstract-9.2.3.tgz", + "integrity": "sha512-cQs9tbIlG3P0IrOWyVirqlhWuJ7Ms2Zh9m2108z6Y5UW/iVj6wEOiW8EmK9QX9jmJXYllE7wgGgvVozP5oCj3w==", + "dependencies": { + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/binding-mock": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/binding-mock/-/binding-mock-9.2.4.tgz", + "integrity": "sha512-dpEhACCs44oQhh6ajJfJdvQdK38Vq0N4W6iD/gdplglDCK7qXRQCMUjJIeKdS/HSEiWkC3bwumUhUufdsOyT4g==", + "dependencies": { + "@serialport/binding-abstract": "9.2.3", + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/bindings": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/@serialport/bindings/-/bindings-9.2.8.tgz", + "integrity": "sha512-hSLxTe0tADZ3LMMGwvEJWOC/TaFQTyPeFalUCsJ1lSQ0k6bPF04JwrtB/C81GetmDBTNRY0GlD0SNtKCc7Dr5g==", + "hasInstallScript": true, + "dependencies": { + "@serialport/binding-abstract": "9.2.3", + "@serialport/parser-readline": "9.2.4", + "bindings": "^1.5.0", + "debug": "^4.3.2", + "nan": "^2.15.0", + "prebuild-install": "^7.0.0" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-byte-length": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-byte-length/-/parser-byte-length-9.2.4.tgz", + "integrity": "sha512-sQD/iw4ZMU3xW9PLi0/GlvU6Y623jGeWecbMkO7izUo/6P7gtfv1c9ikd5h0kwL8AoAOpQA1lxdHIKox+umBUg==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-cctalk": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-cctalk/-/parser-cctalk-9.2.4.tgz", + "integrity": "sha512-T4TU5vQMwmo9AB3gQLFDWbfJXlW5jd9guEsB/nqKjFHTv0FXPdZ7DQ2TpSp8RnHWxU3GX6kYTaDO20BKzc8GPQ==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-delimiter": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-delimiter/-/parser-delimiter-9.2.4.tgz", + "integrity": "sha512-4nvTAoYAgkxFiXrkI+3CA49Yd43CODjeszh89EK+I9c8wOZ+etZduRCzINYPiy26g7zO+GRAb9FoPCsY+sYcbQ==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-inter-byte-timeout": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-inter-byte-timeout/-/parser-inter-byte-timeout-9.2.4.tgz", + "integrity": "sha512-SOAdvr0oBQIOCXX198hiTlxs4JTKg9j5piapw5tNq52fwDOWdbYrFneT/wN04UTMKaDrJuEvXq6T4rv4j7nJ5A==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-readline": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-readline/-/parser-readline-9.2.4.tgz", + "integrity": "sha512-Z1/qrZTQUVhNSJP1hd9YfDvq0o7d87rNwAjjRKbVpa7Qi51tG5BnKt43IV3NFMyBlVcRe0rnIb3tJu57E0SOwg==", + "dependencies": { + "@serialport/parser-delimiter": "9.2.4" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-ready": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-ready/-/parser-ready-9.2.4.tgz", + "integrity": "sha512-Pyi94Itjl6qAURwIZr/gmZpMAyTmKXThm6vL5DoAWGQjcRHWB0gwv2TY2v7N+mQLJYUKU3cMnvnATXxHm7xjxw==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-regex": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-regex/-/parser-regex-9.2.4.tgz", + "integrity": "sha512-sI/cVvPOYz+Dbv4ZdnW16qAwvXiFf/1pGASQdbveRTlgJDdz7sRNlCBifzfTN2xljwvCTZYqiudKvDdC1TepRQ==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/stream": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/stream/-/stream-9.2.4.tgz", + "integrity": "sha512-bLye8Ub4vUFQGmkh8qEqehr7SE7EJs2yDs0h9jzuL5oKi+F34CFmWkEErO8GAOQ8YNn7p6b3GxUgs+0BrHHDZQ==", + "dependencies": { + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "node_modules/are-we-there-yet": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", + "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/base64-js": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", + "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==" + }, + "node_modules/bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "dependencies": { + "file-uri-to-path": "1.0.0" + } + }, + "node_modules/bitwise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/bitwise/-/bitwise-2.1.0.tgz", + "integrity": "sha512-XKgAhMXCh4H/3oNwAHAsAO0iC89s9cOiumgYwSHjSobGWxYjv62YhkL9QEdvGP151xypCtMlAfKK79GEcd2eRQ==" + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/bl/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/buffer": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz", + "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==", + "dependencies": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + }, + "node_modules/buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" + }, + "node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, + "node_modules/code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/commist": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/commist/-/commist-1.1.0.tgz", + "integrity": "sha512-rraC8NXWOEjhADbZe9QBNzLAN5Q3fsTPQtBV+fEVj6xKIgDgNiEVE6ZNfHpZOqfQ21YUzfVNUXLOEZquYvQPPg==", + "dependencies": { + "leven": "^2.1.0", + "minimist": "^1.1.0" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "node_modules/concat-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", + "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", + "engines": [ + "node >= 6.0" + ], + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.0.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/concat-stream/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" + }, + "node_modules/core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "node_modules/crc": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/crc/-/crc-3.4.0.tgz", + "integrity": "sha512-ycVC2+4/DLgXXq7QweYi2znhqDuZz6P5TQXnkQo8v15XY/5p/IWeZwsSE31Ifo8w15b8TWLsqhXOjXyilHuQxw==" + }, + "node_modules/date-format": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.11.tgz", + "integrity": "sha512-VS20KRyorrbMCQmpdl2hg5KaOUsda1RbnsJg461FfrcyCUg+pkd0b40BSW4niQyTheww4DBXQnS7HwSrKkipLw==", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" + }, + "node_modules/detect-libc": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz", + "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==", + "engines": { + "node": ">=8" + } + }, + "node_modules/duplexify": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.2.tgz", + "integrity": "sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw==", + "dependencies": { + "end-of-stream": "^1.4.1", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1", + "stream-shift": "^1.0.0" + } + }, + "node_modules/duplexify/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/easy-crc": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/easy-crc/-/easy-crc-0.0.2.tgz", + "integrity": "sha512-h6eqIdhJRe0p271/xZJbM/0klCi13mW5IB7ZEzEGH11yV4QXWAkD4yPErz0fXdhFrd6sZ4Q1k5Iky2kMsMNePw==" + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" + }, + "node_modules/flatted": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", + "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==" + }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, + "node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "node_modules/gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha512-14x4kjc6lkD3ltw589k0NrPD6cCNTD6CWoVUNpB85+DrtONoZn+Rug6xZU5RvSC4+TZPxA5AnBibQYAvZn41Hg==", + "dependencies": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "node_modules/github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==" + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" + }, + "node_modules/has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" + }, + "node_modules/help-me": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/help-me/-/help-me-3.0.0.tgz", + "integrity": "sha512-hx73jClhyk910sidBB7ERlnhMlFsJJIBqSVMFDwPN8o2v9nmp5KgLq1Xz1Bf1fCMMZ6mPrX159iG0VLy/fPMtQ==", + "dependencies": { + "glob": "^7.1.6", + "readable-stream": "^3.6.0" + } + }, + "node_modules/help-me/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, + "node_modules/is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==", + "dependencies": { + "number-is-nan": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "node_modules/js-sdsl": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz", + "integrity": "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/js-sdsl" + } + }, + "node_modules/jsmodbus": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/jsmodbus/-/jsmodbus-4.0.6.tgz", + "integrity": "sha512-gCmjoaERErK5Rn9Lu/BN07fY13MoWV7JKgGzrnkPlQPdPxYcwDhLtYcmpFFpZ4J9NPZZBSezi1UkLZO/DnNppA==", + "dependencies": { + "crc": "3.4.0", + "debug": "^3.1.0" + }, + "bin": { + "jsmodbus": "bin/jsmodbus.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/jsmodbus/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/leven": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", + "integrity": "sha1-wuep93IJTe6dNCAq6KzORoeHVYA=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/log4js": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.5.2.tgz", + "integrity": "sha512-DXtpNtt+KDOMT7RHUDIur/WsSA3rntlUh9Zg4XCdV42wUuMmbFkl38+LZ92Z5QvQA7mD5kAVkLiBSEH/tvUB8A==", + "dependencies": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "flatted": "^3.2.5", + "rfdc": "^1.3.0", + "streamroller": "^3.1.1" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" + }, + "node_modules/moment": { + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", + "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==", + "engines": { + "node": "*" + } + }, + "node_modules/mqtt": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/mqtt/-/mqtt-4.3.7.tgz", + "integrity": "sha512-ew3qwG/TJRorTz47eW46vZ5oBw5MEYbQZVaEji44j5lAUSQSqIEoul7Kua/BatBW0H0kKQcC9kwUHa1qzaWHSw==", + "dependencies": { + "commist": "^1.0.0", + "concat-stream": "^2.0.0", + "debug": "^4.1.1", + "duplexify": "^4.1.1", + "help-me": "^3.0.0", + "inherits": "^2.0.3", + "lru-cache": "^6.0.0", + "minimist": "^1.2.5", + "mqtt-packet": "^6.8.0", + "number-allocator": "^1.0.9", + "pump": "^3.0.0", + "readable-stream": "^3.6.0", + "reinterval": "^1.1.0", + "rfdc": "^1.3.0", + "split2": "^3.1.0", + "ws": "^7.5.5", + "xtend": "^4.0.2" + }, + "bin": { + "mqtt": "bin/mqtt.js", + "mqtt_pub": "bin/pub.js", + "mqtt_sub": "bin/sub.js" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/mqtt-packet": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/mqtt-packet/-/mqtt-packet-6.10.0.tgz", + "integrity": "sha512-ja8+mFKIHdB1Tpl6vac+sktqy3gA8t9Mduom1BA75cI+R9AHnZOiaBQwpGiWnaVJLDGRdNhQmFaAqd7tkKSMGA==", + "dependencies": { + "bl": "^4.0.2", + "debug": "^4.1.1", + "process-nextick-args": "^2.0.1" + } + }, + "node_modules/mqtt/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/nan": { + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.16.0.tgz", + "integrity": "sha512-UdAqHyFngu7TfQKsCBgAA6pWDkT8MAO7d0jyOecVhN5354xbLqdn8mV9Tat9gepAupm0bt2DbeaSC8vS52MuFA==" + }, + "node_modules/napi-build-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", + "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==" + }, + "node_modules/node-abi": { + "version": "3.22.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.22.0.tgz", + "integrity": "sha512-u4uAs/4Zzmp/jjsD9cyFYDXeISfUWaAVWshPmDZOFOv4Xl4SbzTXm53I04C2uRueYJ+0t5PEtLH/owbn2Npf/w==", + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/nodemailer": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.7.tgz", + "integrity": "sha512-rUtR77ksqex/eZRLmQ21LKVH5nAAsVicAtAYudK7JgwenEDZ0UIQ1adUGqErz7sMkWYxWTTU1aeP2Jga6WQyJw==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "dependencies": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "node_modules/number-allocator": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/number-allocator/-/number-allocator-1.0.14.tgz", + "integrity": "sha512-OrL44UTVAvkKdOdRQZIJpLkAdjXGTRda052sN4sO77bKEzYYqWKMBjQvrJFzqygI99gL6Z4u2xctPW1tB8ErvA==", + "dependencies": { + "debug": "^4.3.1", + "js-sdsl": "4.3.0" + } + }, + "node_modules/number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/prebuild-install": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.0.tgz", + "integrity": "sha512-CNcMgI1xBypOyGqjp3wOc8AAo1nMhZS3Cwd3iHIxOdAUbb+YxdNuM4Z5iIrZ8RLvOsf3F3bl7b7xGq6DjQoNYA==", + "dependencies": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^1.0.1", + "node-abi": "^3.3.0", + "npmlog": "^4.0.1", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + }, + "bin": { + "prebuild-install": "bin.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/reinterval": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reinterval/-/reinterval-1.1.0.tgz", + "integrity": "sha1-M2Hs+jymwYKDOA3Qu5VG85D17Oc=" + }, + "node_modules/rfdc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==" + }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/serialport": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/serialport/-/serialport-9.2.8.tgz", + "integrity": "sha512-FsWpMQgSJxi93JgWl5xM1f9/Z8IjRJuaUEoHqLf8FPBLw7gMhInuHOBhI2onQufWIYPGTz3H3oGcu1nCaK1EfA==", + "dependencies": { + "@serialport/binding-mock": "9.2.4", + "@serialport/bindings": "9.2.8", + "@serialport/parser-byte-length": "9.2.4", + "@serialport/parser-cctalk": "9.2.4", + "@serialport/parser-delimiter": "9.2.4", + "@serialport/parser-inter-byte-timeout": "9.2.4", + "@serialport/parser-readline": "9.2.4", + "@serialport/parser-ready": "9.2.4", + "@serialport/parser-regex": "9.2.4", + "@serialport/stream": "9.2.4", + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "node_modules/split2": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", + "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", + "dependencies": { + "readable-stream": "^3.0.0" + } + }, + "node_modules/split2/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==" + }, + "node_modules/streamroller": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.1.1.tgz", + "integrity": "sha512-iPhtd9unZ6zKdWgMeYGfSBuqCngyJy1B/GPi/lTpwGpa3bajuX30GjUVd0/Tn/Xhg0mr4DOSENozz9Y06qyonQ==", + "dependencies": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "fs-extra": "^10.1.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dependencies": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/tar-fs": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "dependencies": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tar-stream/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/total.js": { + "version": "3.4.13", + "resolved": "https://registry.npmjs.org/total.js/-/total.js-3.4.13.tgz", + "integrity": "sha512-lAH4gEixlPFbrE3xfKADAcHfO79IFq2wKa9GTsrgRzIR5MTg3mNH7+4IxvX1pK8faoYb/0oYSJ1YTsAa5hIFFQ==", + "bin": { + "total": "bin/totaljs", + "total.js": "bin/totaljs", + "totaljs": "bin/totaljs", + "totalpackage": "bin/tpm", + "tpm": "bin/tpm" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, + "node_modules/universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "node_modules/wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "node_modules/ws": { + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } + }, + "dependencies": { + "@serialport/binding-abstract": { + "version": "9.2.3", + "resolved": "https://registry.npmjs.org/@serialport/binding-abstract/-/binding-abstract-9.2.3.tgz", + "integrity": "sha512-cQs9tbIlG3P0IrOWyVirqlhWuJ7Ms2Zh9m2108z6Y5UW/iVj6wEOiW8EmK9QX9jmJXYllE7wgGgvVozP5oCj3w==", + "requires": { + "debug": "^4.3.2" + } + }, + "@serialport/binding-mock": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/binding-mock/-/binding-mock-9.2.4.tgz", + "integrity": "sha512-dpEhACCs44oQhh6ajJfJdvQdK38Vq0N4W6iD/gdplglDCK7qXRQCMUjJIeKdS/HSEiWkC3bwumUhUufdsOyT4g==", + "requires": { + "@serialport/binding-abstract": "9.2.3", + "debug": "^4.3.2" + } + }, + "@serialport/bindings": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/@serialport/bindings/-/bindings-9.2.8.tgz", + "integrity": "sha512-hSLxTe0tADZ3LMMGwvEJWOC/TaFQTyPeFalUCsJ1lSQ0k6bPF04JwrtB/C81GetmDBTNRY0GlD0SNtKCc7Dr5g==", + "requires": { + "@serialport/binding-abstract": "9.2.3", + "@serialport/parser-readline": "9.2.4", + "bindings": "^1.5.0", + "debug": "^4.3.2", + "nan": "^2.15.0", + "prebuild-install": "^7.0.0" + } + }, + "@serialport/parser-byte-length": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-byte-length/-/parser-byte-length-9.2.4.tgz", + "integrity": "sha512-sQD/iw4ZMU3xW9PLi0/GlvU6Y623jGeWecbMkO7izUo/6P7gtfv1c9ikd5h0kwL8AoAOpQA1lxdHIKox+umBUg==" + }, + "@serialport/parser-cctalk": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-cctalk/-/parser-cctalk-9.2.4.tgz", + "integrity": "sha512-T4TU5vQMwmo9AB3gQLFDWbfJXlW5jd9guEsB/nqKjFHTv0FXPdZ7DQ2TpSp8RnHWxU3GX6kYTaDO20BKzc8GPQ==" + }, + "@serialport/parser-delimiter": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-delimiter/-/parser-delimiter-9.2.4.tgz", + "integrity": "sha512-4nvTAoYAgkxFiXrkI+3CA49Yd43CODjeszh89EK+I9c8wOZ+etZduRCzINYPiy26g7zO+GRAb9FoPCsY+sYcbQ==" + }, + "@serialport/parser-inter-byte-timeout": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-inter-byte-timeout/-/parser-inter-byte-timeout-9.2.4.tgz", + "integrity": "sha512-SOAdvr0oBQIOCXX198hiTlxs4JTKg9j5piapw5tNq52fwDOWdbYrFneT/wN04UTMKaDrJuEvXq6T4rv4j7nJ5A==" + }, + "@serialport/parser-readline": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-readline/-/parser-readline-9.2.4.tgz", + "integrity": "sha512-Z1/qrZTQUVhNSJP1hd9YfDvq0o7d87rNwAjjRKbVpa7Qi51tG5BnKt43IV3NFMyBlVcRe0rnIb3tJu57E0SOwg==", + "requires": { + "@serialport/parser-delimiter": "9.2.4" + } + }, + "@serialport/parser-ready": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-ready/-/parser-ready-9.2.4.tgz", + "integrity": "sha512-Pyi94Itjl6qAURwIZr/gmZpMAyTmKXThm6vL5DoAWGQjcRHWB0gwv2TY2v7N+mQLJYUKU3cMnvnATXxHm7xjxw==" + }, + "@serialport/parser-regex": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-regex/-/parser-regex-9.2.4.tgz", + "integrity": "sha512-sI/cVvPOYz+Dbv4ZdnW16qAwvXiFf/1pGASQdbveRTlgJDdz7sRNlCBifzfTN2xljwvCTZYqiudKvDdC1TepRQ==" + }, + "@serialport/stream": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/stream/-/stream-9.2.4.tgz", + "integrity": "sha512-bLye8Ub4vUFQGmkh8qEqehr7SE7EJs2yDs0h9jzuL5oKi+F34CFmWkEErO8GAOQ8YNn7p6b3GxUgs+0BrHHDZQ==", + "requires": { + "debug": "^4.3.2" + } + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==" + }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "are-we-there-yet": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", + "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "base64-js": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", + "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==" + }, + "bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "requires": { + "file-uri-to-path": "1.0.0" + } + }, + "bitwise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/bitwise/-/bitwise-2.1.0.tgz", + "integrity": "sha512-XKgAhMXCh4H/3oNwAHAsAO0iC89s9cOiumgYwSHjSobGWxYjv62YhkL9QEdvGP151xypCtMlAfKK79GEcd2eRQ==" + }, + "bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "requires": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "buffer": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz", + "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==", + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" + }, + "chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==" + }, + "commist": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/commist/-/commist-1.1.0.tgz", + "integrity": "sha512-rraC8NXWOEjhADbZe9QBNzLAN5Q3fsTPQtBV+fEVj6xKIgDgNiEVE6ZNfHpZOqfQ21YUzfVNUXLOEZquYvQPPg==", + "requires": { + "leven": "^2.1.0", + "minimist": "^1.1.0" + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "concat-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", + "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.0.2", + "typedarray": "^0.0.6" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "crc": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/crc/-/crc-3.4.0.tgz", + "integrity": "sha512-ycVC2+4/DLgXXq7QweYi2znhqDuZz6P5TQXnkQo8v15XY/5p/IWeZwsSE31Ifo8w15b8TWLsqhXOjXyilHuQxw==" + }, + "date-format": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.11.tgz", + "integrity": "sha512-VS20KRyorrbMCQmpdl2hg5KaOUsda1RbnsJg461FfrcyCUg+pkd0b40BSW4niQyTheww4DBXQnS7HwSrKkipLw==" + }, + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "requires": { + "ms": "2.1.2" + } + }, + "decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "requires": { + "mimic-response": "^3.1.0" + } + }, + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==" + }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" + }, + "detect-libc": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz", + "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==" + }, + "duplexify": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.2.tgz", + "integrity": "sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw==", + "requires": { + "end-of-stream": "^1.4.1", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1", + "stream-shift": "^1.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "easy-crc": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/easy-crc/-/easy-crc-0.0.2.tgz", + "integrity": "sha512-h6eqIdhJRe0p271/xZJbM/0klCi13mW5IB7ZEzEGH11yV4QXWAkD4yPErz0fXdhFrd6sZ4Q1k5Iky2kMsMNePw==" + }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "requires": { + "once": "^1.4.0" + } + }, + "expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==" + }, + "file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" + }, + "flatted": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", + "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==" + }, + "fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, + "fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha512-14x4kjc6lkD3ltw589k0NrPD6cCNTD6CWoVUNpB85+DrtONoZn+Rug6xZU5RvSC4+TZPxA5AnBibQYAvZn41Hg==", + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==" + }, + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" + }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" + }, + "help-me": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/help-me/-/help-me-3.0.0.tgz", + "integrity": "sha512-hx73jClhyk910sidBB7ERlnhMlFsJJIBqSVMFDwPN8o2v9nmp5KgLq1Xz1Bf1fCMMZ6mPrX159iG0VLy/fPMtQ==", + "requires": { + "glob": "^7.1.6", + "readable-stream": "^3.6.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==", + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "js-sdsl": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz", + "integrity": "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==" + }, + "jsmodbus": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/jsmodbus/-/jsmodbus-4.0.6.tgz", + "integrity": "sha512-gCmjoaERErK5Rn9Lu/BN07fY13MoWV7JKgGzrnkPlQPdPxYcwDhLtYcmpFFpZ4J9NPZZBSezi1UkLZO/DnNppA==", + "requires": { + "crc": "3.4.0", + "debug": "^3.1.0" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "requires": { + "ms": "^2.1.1" + } + } + } + }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, + "leven": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", + "integrity": "sha1-wuep93IJTe6dNCAq6KzORoeHVYA=" + }, + "log4js": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.5.2.tgz", + "integrity": "sha512-DXtpNtt+KDOMT7RHUDIur/WsSA3rntlUh9Zg4XCdV42wUuMmbFkl38+LZ92Z5QvQA7mD5kAVkLiBSEH/tvUB8A==", + "requires": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "flatted": "^3.2.5", + "rfdc": "^1.3.0", + "streamroller": "^3.1.1" + } + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "requires": { + "yallist": "^4.0.0" + } + }, + "mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==" + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==" + }, + "mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" + }, + "moment": { + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", + "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==" + }, + "mqtt": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/mqtt/-/mqtt-4.3.7.tgz", + "integrity": "sha512-ew3qwG/TJRorTz47eW46vZ5oBw5MEYbQZVaEji44j5lAUSQSqIEoul7Kua/BatBW0H0kKQcC9kwUHa1qzaWHSw==", + "requires": { + "commist": "^1.0.0", + "concat-stream": "^2.0.0", + "debug": "^4.1.1", + "duplexify": "^4.1.1", + "help-me": "^3.0.0", + "inherits": "^2.0.3", + "lru-cache": "^6.0.0", + "minimist": "^1.2.5", + "mqtt-packet": "^6.8.0", + "number-allocator": "^1.0.9", + "pump": "^3.0.0", + "readable-stream": "^3.6.0", + "reinterval": "^1.1.0", + "rfdc": "^1.3.0", + "split2": "^3.1.0", + "ws": "^7.5.5", + "xtend": "^4.0.2" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "mqtt-packet": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/mqtt-packet/-/mqtt-packet-6.10.0.tgz", + "integrity": "sha512-ja8+mFKIHdB1Tpl6vac+sktqy3gA8t9Mduom1BA75cI+R9AHnZOiaBQwpGiWnaVJLDGRdNhQmFaAqd7tkKSMGA==", + "requires": { + "bl": "^4.0.2", + "debug": "^4.1.1", + "process-nextick-args": "^2.0.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "nan": { + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.16.0.tgz", + "integrity": "sha512-UdAqHyFngu7TfQKsCBgAA6pWDkT8MAO7d0jyOecVhN5354xbLqdn8mV9Tat9gepAupm0bt2DbeaSC8vS52MuFA==" + }, + "napi-build-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", + "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==" + }, + "node-abi": { + "version": "3.22.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.22.0.tgz", + "integrity": "sha512-u4uAs/4Zzmp/jjsD9cyFYDXeISfUWaAVWshPmDZOFOv4Xl4SbzTXm53I04C2uRueYJ+0t5PEtLH/owbn2Npf/w==", + "requires": { + "semver": "^7.3.5" + } + }, + "nodemailer": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.7.tgz", + "integrity": "sha512-rUtR77ksqex/eZRLmQ21LKVH5nAAsVicAtAYudK7JgwenEDZ0UIQ1adUGqErz7sMkWYxWTTU1aeP2Jga6WQyJw==" + }, + "npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "number-allocator": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/number-allocator/-/number-allocator-1.0.14.tgz", + "integrity": "sha512-OrL44UTVAvkKdOdRQZIJpLkAdjXGTRda052sN4sO77bKEzYYqWKMBjQvrJFzqygI99gL6Z4u2xctPW1tB8ErvA==", + "requires": { + "debug": "^4.3.1", + "js-sdsl": "4.3.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==" + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==" + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==" + }, + "prebuild-install": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.0.tgz", + "integrity": "sha512-CNcMgI1xBypOyGqjp3wOc8AAo1nMhZS3Cwd3iHIxOdAUbb+YxdNuM4Z5iIrZ8RLvOsf3F3bl7b7xGq6DjQoNYA==", + "requires": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^1.0.1", + "node-abi": "^3.3.0", + "npmlog": "^4.0.1", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + } + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + } + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "reinterval": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reinterval/-/reinterval-1.1.0.tgz", + "integrity": "sha1-M2Hs+jymwYKDOA3Qu5VG85D17Oc=" + }, + "rfdc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==" + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "requires": { + "lru-cache": "^6.0.0" + } + }, + "serialport": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/serialport/-/serialport-9.2.8.tgz", + "integrity": "sha512-FsWpMQgSJxi93JgWl5xM1f9/Z8IjRJuaUEoHqLf8FPBLw7gMhInuHOBhI2onQufWIYPGTz3H3oGcu1nCaK1EfA==", + "requires": { + "@serialport/binding-mock": "9.2.4", + "@serialport/bindings": "9.2.8", + "@serialport/parser-byte-length": "9.2.4", + "@serialport/parser-cctalk": "9.2.4", + "@serialport/parser-delimiter": "9.2.4", + "@serialport/parser-inter-byte-timeout": "9.2.4", + "@serialport/parser-readline": "9.2.4", + "@serialport/parser-ready": "9.2.4", + "@serialport/parser-regex": "9.2.4", + "@serialport/stream": "9.2.4", + "debug": "^4.3.2" + } + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==" + }, + "simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "requires": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "split2": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", + "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", + "requires": { + "readable-stream": "^3.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==" + }, + "streamroller": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.1.1.tgz", + "integrity": "sha512-iPhtd9unZ6zKdWgMeYGfSBuqCngyJy1B/GPi/lTpwGpa3bajuX30GjUVd0/Tn/Xhg0mr4DOSENozz9Y06qyonQ==", + "requires": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "fs-extra": "^10.1.0" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" + }, + "tar-fs": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "requires": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "requires": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "total.js": { + "version": "3.4.13", + "resolved": "https://registry.npmjs.org/total.js/-/total.js-3.4.13.tgz", + "integrity": "sha512-lAH4gEixlPFbrE3xfKADAcHfO79IFq2wKa9GTsrgRzIR5MTg3mNH7+4IxvX1pK8faoYb/0oYSJ1YTsAa5hIFFQ==" + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, + "universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==" + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "requires": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "ws": { + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "requires": {} + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } + } +} diff --git a/RVO23/package.json b/RVO23/package.json new file mode 100755 index 0000000..7f7c795 --- /dev/null +++ b/RVO23/package.json @@ -0,0 +1,30 @@ +{ + "name": "emptyproject", + "description": "Total.js empty project.", + "version": "1.0.0", + "main": "debug.js", + "dependencies": { + "bitwise": "^2.1.0", + "easy-crc": "0.0.2", + "jsmodbus": "^4.0.6", + "log4js": "^6.3.0", + "moment": "^2.30.1", + "mqtt": "^4.2.6", + "nodemailer": "^6.9.7", + "serialport": "^9.2.8", + "total.js": "^3.4.13" + }, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "https://github.com/totaljs/emptyproject-flow" + }, + "keywords": [ + "empty", + "project" + ], + "author": "Peter Širka", + "license": "MIT" +} diff --git a/RVO23/release.js b/RVO23/release.js new file mode 100755 index 0000000..02d52ff --- /dev/null +++ b/RVO23/release.js @@ -0,0 +1,15 @@ +// =================================================== +// FOR PRODUCTION +// Total.js - framework for Node.js platform +// https://www.totaljs.com +// =================================================== + +const options = {'ip':'0.0.0.0', 'port':12345}; + +// options.ip = '127.0.0.1'; +// options.port = parseInt(process.argv[2]); +// options.config = { name: 'Total.js' }; +// options.sleep = 3000; + +require('total.js').http('release', options); +// require('total.js').cluster.http(5, 'release', options); diff --git a/RVO23/release.js.json b/RVO23/release.js.json new file mode 100755 index 0000000..0ab65fa --- /dev/null +++ b/RVO23/release.js.json @@ -0,0 +1,34 @@ +{ + "pid": 407, + "stats": [ + { + "id": null, + "version": { + "node": "v14.18.1", + "total": "3.4.13", + "app": "1.0.0" + }, + "pid": 407, + "thread": "", + "mode": "release", + "overload": 0, + "date": "2025-10-16T00:24:22.383Z", + "memory": 26.12, + "rm": 0, + "fm": 0, + "wm": 0, + "mm": 0, + "om": 2, + "em": 0, + "dbrm": 0, + "dbwm": 0, + "usage": 0, + "requests": 7, + "pending": 0, + "errors": 0, + "timeouts": 0, + "uptime": 865, + "online": 0 + } + ] +} \ No newline at end of file diff --git a/RVO23/report_data.log b/RVO23/report_data.log new file mode 100755 index 0000000..7d0a5c9 --- /dev/null +++ b/RVO23/report_data.log @@ -0,0 +1,208 @@ +{ + "name": "rvo_senica_23_ip110", + "time": "2025-10-15T11:00:37.208Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_23_ip110", + "time": "2025-10-15T12:00:37.206Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_23_ip110", + "time": "2025-10-15T13:00:37.206Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_23_ip110", + "time": "2025-10-15T14:00:37.206Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_23_ip110", + "time": "2025-10-15T15:00:37.206Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_23_ip110", + "time": "2025-10-15T16:00:37.207Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_23_ip110", + "time": "2025-10-15T17:33:14.469Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_23_ip110", + "time": "2025-10-15T18:33:14.471Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "23/25_1L_3123_NEMA" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_23_ip110", + "time": "2025-10-15T19:33:14.470Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "23/25_1L_3123_NEMA" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_23_ip110", + "time": "2025-10-15T20:33:14.470Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "23/25_1L_3123_NEMA" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_23_ip110", + "time": "2025-10-15T21:33:14.470Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "23/25_1L_3123_NEMA" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_23_ip110", + "time": "2025-10-15T22:33:14.471Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "23/25_1L_3123_NEMA" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_23_ip110", + "time": "2025-10-15T23:33:14.473Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "23/25_1L_3123_NEMA" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +} \ No newline at end of file From cf772fe147ecf149c42055d006bb84215f9816fc Mon Sep 17 00:00:00 2001 From: Jakub Klena Date: Thu, 16 Oct 2025 02:25:14 +0200 Subject: [PATCH 14/30] Backup senica-RVO25 on 16.10.2025 --- RVO25/addSwitch.py | 36 + RVO25/cloud_topic.py | 76 + RVO25/cmd.log | 0 RVO25/config | 12 + RVO25/createNode.py | 43 + RVO25/databases/accelerometer_db.js | 3055 ++++++++++++++++ RVO25/databases/modbus_config.js | 114 + RVO25/databases/nodes.table | 110 + .../nodes_original/nodes_original.table | 1 + RVO25/databases/notifications.table | 41 + RVO25/databases/pins.table | 16 + RVO25/databases/relays.table | 7 + RVO25/databases/settings.table | 2 + RVO25/databases/tbdata.nosql | 4 + RVO25/databases/tbdatacloud.nosql | 3 + RVO25/databases/total_energy.js | 38 + RVO25/debug.js | 16 + RVO25/err.txt | 51 + RVO25/flow/cloudmqttconnect.js | 357 ++ RVO25/flow/cmd_manager.js | 3071 ++++++++++++++++ RVO25/flow/code.js | 90 + RVO25/flow/comment.js | 11 + RVO25/flow/count.js | 60 + RVO25/flow/db_connector.js | 286 ++ RVO25/flow/db_init.js | 113 + RVO25/flow/debug.js | 100 + RVO25/flow/designer.json | 3102 +++++++++++++++++ RVO25/flow/dido_controller.js | 1486 ++++++++ RVO25/flow/helper/DataToTbHandler.js | 187 + RVO25/flow/helper/ErrorToServiceHandler.js | 91 + RVO25/flow/helper/db_helper.js | 44 + RVO25/flow/helper/logger.js | 30 + RVO25/flow/helper/md5.js | 5 + RVO25/flow/helper/notification_reporter.js | 121 + RVO25/flow/helper/register.js | 144 + RVO25/flow/helper/serialport_helper.js | 99 + RVO25/flow/helper/suncalc.js | 317 ++ RVO25/flow/helper/utils.js | 161 + RVO25/flow/httprequest.js | 137 + RVO25/flow/httpresponse.js | 76 + RVO25/flow/httproute.js | 326 ++ RVO25/flow/infosender.js | 81 + RVO25/flow/modbus_reader.js | 346 ++ RVO25/flow/monitorconsumption.js | 156 + RVO25/flow/monitordisk.js | 96 + RVO25/flow/monitormemory.js | 87 + RVO25/flow/nodesdb_changecheck.js | 77 + RVO25/flow/show_dbdata.js | 243 ++ RVO25/flow/slack_filter.js | 188 + RVO25/flow/thermometer.js | 99 + RVO25/flow/trigger.js | 79 + RVO25/flow/variables.txt | 0 RVO25/flow/virtualwirein.js | 43 + RVO25/flow/virtualwireout.js | 41 + RVO25/flow/wsmqttpublish.js | 448 +++ RVO25/flow_15_1_2025/cloudmqttconnect.js | 374 ++ RVO25/flow_15_1_2025/cmd_manager.js | 2988 ++++++++++++++++ RVO25/flow_15_1_2025/code.js | 90 + RVO25/flow_15_1_2025/comment.js | 11 + RVO25/flow_15_1_2025/db_connector.js | 286 ++ RVO25/flow_15_1_2025/db_init.js | 106 + RVO25/flow_15_1_2025/debug.js | 100 + RVO25/flow_15_1_2025/designer.json | 2846 +++++++++++++++ RVO25/flow_15_1_2025/dido_controller.js | 1524 ++++++++ .../flow_15_1_2025/helper/DataToTbHandler.js | 166 + .../helper/ErrorToServiceHandler.js | 126 + RVO25/flow_15_1_2025/helper/db_helper.js | 44 + RVO25/flow_15_1_2025/helper/logger.js | 30 + RVO25/flow_15_1_2025/helper/md5.js | 5 + .../helper/notification_reporter.js | 131 + RVO25/flow_15_1_2025/helper/register.js | 144 + .../helper/serialport_helper.js | 100 + RVO25/flow_15_1_2025/helper/suncalc.js | 317 ++ RVO25/flow_15_1_2025/helper/utils.js | 124 + RVO25/flow_15_1_2025/httprequest.js | 137 + RVO25/flow_15_1_2025/httpresponse.js | 76 + RVO25/flow_15_1_2025/httproute.js | 326 ++ RVO25/flow_15_1_2025/infosender.js | 101 + RVO25/flow_15_1_2025/modbus_reader.js | 367 ++ RVO25/flow_15_1_2025/monitorconsumption.js | 156 + RVO25/flow_15_1_2025/monitordisk.js | 96 + RVO25/flow_15_1_2025/monitormemory.js | 87 + RVO25/flow_15_1_2025/nodesdb_changecheck.js | 70 + RVO25/flow_15_1_2025/show_dbdata.js | 241 ++ RVO25/flow_15_1_2025/slack_filter.js | 187 + RVO25/flow_15_1_2025/thermometer.js | 98 + RVO25/flow_15_1_2025/trigger.js | 79 + RVO25/flow_15_1_2025/virtualwirein.js | 43 + RVO25/flow_15_1_2025/virtualwireout.js | 41 + RVO25/flow_15_1_2025/wsmqttpublish.js | 477 +++ RVO25/monitor.txt | 522 +++ RVO25/package-lock.json | 2139 ++++++++++++ RVO25/package.json | 30 + RVO25/release.js | 15 + RVO25/release.js.json | 34 + RVO25/report_data.log | 172 + 96 files changed, 31029 insertions(+) create mode 100755 RVO25/addSwitch.py create mode 100755 RVO25/cloud_topic.py create mode 100755 RVO25/cmd.log create mode 100755 RVO25/config create mode 100755 RVO25/createNode.py create mode 100755 RVO25/databases/accelerometer_db.js create mode 100755 RVO25/databases/modbus_config.js create mode 100755 RVO25/databases/nodes.table create mode 100755 RVO25/databases/nodes_original/nodes_original.table create mode 100755 RVO25/databases/notifications.table create mode 100755 RVO25/databases/pins.table create mode 100755 RVO25/databases/relays.table create mode 100755 RVO25/databases/settings.table create mode 100755 RVO25/databases/tbdata.nosql create mode 100755 RVO25/databases/tbdatacloud.nosql create mode 100755 RVO25/databases/total_energy.js create mode 100755 RVO25/debug.js create mode 100755 RVO25/err.txt create mode 100755 RVO25/flow/cloudmqttconnect.js create mode 100755 RVO25/flow/cmd_manager.js create mode 100755 RVO25/flow/code.js create mode 100755 RVO25/flow/comment.js create mode 100755 RVO25/flow/count.js create mode 100755 RVO25/flow/db_connector.js create mode 100755 RVO25/flow/db_init.js create mode 100755 RVO25/flow/debug.js create mode 100755 RVO25/flow/designer.json create mode 100755 RVO25/flow/dido_controller.js create mode 100755 RVO25/flow/helper/DataToTbHandler.js create mode 100755 RVO25/flow/helper/ErrorToServiceHandler.js create mode 100755 RVO25/flow/helper/db_helper.js create mode 100755 RVO25/flow/helper/logger.js create mode 100755 RVO25/flow/helper/md5.js create mode 100755 RVO25/flow/helper/notification_reporter.js create mode 100755 RVO25/flow/helper/register.js create mode 100755 RVO25/flow/helper/serialport_helper.js create mode 100755 RVO25/flow/helper/suncalc.js create mode 100755 RVO25/flow/helper/utils.js create mode 100755 RVO25/flow/httprequest.js create mode 100755 RVO25/flow/httpresponse.js create mode 100755 RVO25/flow/httproute.js create mode 100755 RVO25/flow/infosender.js create mode 100755 RVO25/flow/modbus_reader.js create mode 100755 RVO25/flow/monitorconsumption.js create mode 100755 RVO25/flow/monitordisk.js create mode 100755 RVO25/flow/monitormemory.js create mode 100755 RVO25/flow/nodesdb_changecheck.js create mode 100755 RVO25/flow/show_dbdata.js create mode 100755 RVO25/flow/slack_filter.js create mode 100755 RVO25/flow/thermometer.js create mode 100755 RVO25/flow/trigger.js create mode 100755 RVO25/flow/variables.txt create mode 100755 RVO25/flow/virtualwirein.js create mode 100755 RVO25/flow/virtualwireout.js create mode 100755 RVO25/flow/wsmqttpublish.js create mode 100755 RVO25/flow_15_1_2025/cloudmqttconnect.js create mode 100755 RVO25/flow_15_1_2025/cmd_manager.js create mode 100755 RVO25/flow_15_1_2025/code.js create mode 100755 RVO25/flow_15_1_2025/comment.js create mode 100755 RVO25/flow_15_1_2025/db_connector.js create mode 100755 RVO25/flow_15_1_2025/db_init.js create mode 100755 RVO25/flow_15_1_2025/debug.js create mode 100755 RVO25/flow_15_1_2025/designer.json create mode 100755 RVO25/flow_15_1_2025/dido_controller.js create mode 100755 RVO25/flow_15_1_2025/helper/DataToTbHandler.js create mode 100755 RVO25/flow_15_1_2025/helper/ErrorToServiceHandler.js create mode 100755 RVO25/flow_15_1_2025/helper/db_helper.js create mode 100755 RVO25/flow_15_1_2025/helper/logger.js create mode 100755 RVO25/flow_15_1_2025/helper/md5.js create mode 100755 RVO25/flow_15_1_2025/helper/notification_reporter.js create mode 100755 RVO25/flow_15_1_2025/helper/register.js create mode 100755 RVO25/flow_15_1_2025/helper/serialport_helper.js create mode 100755 RVO25/flow_15_1_2025/helper/suncalc.js create mode 100755 RVO25/flow_15_1_2025/helper/utils.js create mode 100755 RVO25/flow_15_1_2025/httprequest.js create mode 100755 RVO25/flow_15_1_2025/httpresponse.js create mode 100755 RVO25/flow_15_1_2025/httproute.js create mode 100755 RVO25/flow_15_1_2025/infosender.js create mode 100755 RVO25/flow_15_1_2025/modbus_reader.js create mode 100755 RVO25/flow_15_1_2025/monitorconsumption.js create mode 100755 RVO25/flow_15_1_2025/monitordisk.js create mode 100755 RVO25/flow_15_1_2025/monitormemory.js create mode 100755 RVO25/flow_15_1_2025/nodesdb_changecheck.js create mode 100755 RVO25/flow_15_1_2025/show_dbdata.js create mode 100755 RVO25/flow_15_1_2025/slack_filter.js create mode 100755 RVO25/flow_15_1_2025/thermometer.js create mode 100755 RVO25/flow_15_1_2025/trigger.js create mode 100755 RVO25/flow_15_1_2025/virtualwirein.js create mode 100755 RVO25/flow_15_1_2025/virtualwireout.js create mode 100755 RVO25/flow_15_1_2025/wsmqttpublish.js create mode 100755 RVO25/monitor.txt create mode 100755 RVO25/package-lock.json create mode 100755 RVO25/package.json create mode 100755 RVO25/release.js create mode 100755 RVO25/release.js.json create mode 100755 RVO25/report_data.log diff --git a/RVO25/addSwitch.py b/RVO25/addSwitch.py new file mode 100755 index 0000000..c35e96b --- /dev/null +++ b/RVO25/addSwitch.py @@ -0,0 +1,36 @@ +import os + +def process_set_file(): + """ + Checks if /root/flowserver exists, reads set.txt, and modifies the second line. + """ + default_folder = "/root/flowserver" if os.path.exists("/root/flowserver") else "/home/unipi/flowserver" + flag = 1 if default_folder == "/root/flowserver" else 0 + + try: + with open("/home/unipi/flowserver/databases/settings.table", "r") as f: + lines = f.readlines() + + if len(lines) >= 2: + lines[0] = lines[0].rstrip('\n') + "|main_switch:boolean\n" + second_line = lines[1].strip() # remove trailing newline + last_pipe_index = second_line.rfind("|") + + if last_pipe_index != -1: + modified_line = second_line[:last_pipe_index + 1] + str(flag) + "|" + second_line[last_pipe_index + 1:] + lines[1] = modified_line + else: + print("Warning: No '|' character found in the second line of set.txt") + + with open("/home/unipi/flowserver/databases/settings.table", "w") as f: + f.writelines(lines) + else: + print("Warning: settings.table has less than two lines.") + + except FileNotFoundError: + print("Error: settings.table not found.") + except Exception as e: + print(e) + +# if __name__ == "__main__": +process_set_file() diff --git a/RVO25/cloud_topic.py b/RVO25/cloud_topic.py new file mode 100755 index 0000000..77c31f1 --- /dev/null +++ b/RVO25/cloud_topic.py @@ -0,0 +1,76 @@ +# import os +# +# def modify_file(file_path): +# """ +# Modifies the given file by: +# 1. Appending "|cloud_topic" to the first line. +# 2. Inserting the text from the third "." to the first "|" on the second line after the last "|" character. +# +# Args: +# file_path (str): The path to the file to be modified. +# """ +# +# with open(file_path, 'r+') as f: +# lines = f.readlines() +# +# # Modify the first line +# lines[0] += "|cloud_topic:string" +# +# # Modify the second line +# second_line = lines[1].strip() # Remove leading/trailing whitespace +# first_pipe_index = second_line.find('|') +# third_dot_index = second_line.find('.', second_line.find('.', second_line.find('.') + 1) + 1) +# text_to_insert = second_line[third_dot_index:first_pipe_index] +# +# last_pipe_index = second_line.rfind('|') +# lines[1] = second_line[:last_pipe_index + 1] + text_to_insert + "|" + second_line[last_pipe_index + 1:] +# +# print(first_pipe_index, third_dot_index, text_to_insert, last_pipe_index) +# # Write the modified lines back to the file +# # f.seek(0) +# # f.writelines(lines) +# # f.truncate() +# +# # Example usage: +# file_path = "settings.table" # Replace with the actual file path +# modify_file(file_path) +# + + +def modify_file(file_path): + """ + Modifies the given file by: + 1. Appending "|cloud_topic" to the first line. + 2. Inserting the text between the third "." and the second "|" on the second line after the last "|" character. + + Args: + file_path (str): The path to the file to be modified. + """ + + with open(file_path, 'r+') as f: + lines = f.readlines() + + first_line = lines[0].strip() + first_line += "|cloud_topic:string\n" + # Modify the first line + lines[0] = first_line + + # Modify the second line + second_line = lines[1].strip() # Remove leading/trailing whitespace + first_pipe_index = second_line.find('|') + second_pipe_index = second_line.find('|', first_pipe_index + 1) + third_dot_index = second_line.find('.', second_line.find('.', second_line.find('.') + 1) + 1) + text_to_insert = "u" + second_line[third_dot_index+1:second_pipe_index] + + last_pipe_index = second_line.rfind('|') + lines[1] = second_line[:last_pipe_index + 1] + text_to_insert + "|" + second_line[last_pipe_index + 1:] + + print(first_pipe_index, third_dot_index, text_to_insert, last_pipe_index) + # Write the modified lines back to the file + f.seek(0) + f.writelines(lines) + f.truncate() + +# Example usage: +file_path = "/home/unipi/flowserver/databases/settings.table" # Replace with the actual file path +modify_file(file_path) diff --git a/RVO25/cmd.log b/RVO25/cmd.log new file mode 100755 index 0000000..e69de29 diff --git a/RVO25/config b/RVO25/config new file mode 100755 index 0000000..cd0a8a9 --- /dev/null +++ b/RVO25/config @@ -0,0 +1,12 @@ +name : Total.js Flow +default_timezone : Europe/Bratislava + +// Packages settings +package#flow (Object) : { url: '/' } + + +table.relays : line:number|tbname:string|contactor:number|profile:string +table.nodes : node:number|pole_number:string|node_type:string|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|project_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|cloud_topic:string|has_main_switch:boolean|daily_report:boolean|send_changed_node_numbers:boolean +table.pins : pin:string|type:string|line:number +table.notifications : key:string|weight:string|sk:string|en:string diff --git a/RVO25/createNode.py b/RVO25/createNode.py new file mode 100755 index 0000000..a8cea91 --- /dev/null +++ b/RVO25/createNode.py @@ -0,0 +1,43 @@ +print("zaciname") +import re, json + +search_str = '|' +final = [] +counter = 1 +with open("/home/unipi/flowserver/databases/nodes.table", 'r') as file: +# with open("/home/rasta5man/dev/oms/flowserver/databases/nodes.table", 'r') as file: + # Read each line in the file + for line in file: + # Print each line + line = line.strip() + print(line) + if counter != 1: + i = [m.start() for m in re.finditer(re.escape(search_str), line)] + node = line[ i[0] + 1 : i[1] ] + tbname = line[ i[3] + 1 : i[4] ] + final.append({node:tbname}) + counter += 1 +print(json.dumps(final)) +f = open("/home/unipi/flowserver/databases/nodes_original/nodes_original.table", "w") +f.write(json.dumps(final)) +f.close() + + +# +# # ``d`` has to be replaced with a different character +# old_character = "'" +# +# # ``t`` will replace ``d` +# new_character = '"' +# resultant_string = 0; +# with open("/home/unipi/flowserver/databases/nodes_original/nodes_original.table", 'r') as file: +# for line in file: +# resultant_string = re.sub("'", '"', line) +# +# resultant_string = re.sub(" ", "", resultant_string) +# print(resultant_string) +# +# f = open("/home/unipi/flowserver/databases/nodes_original/nodes_original.table", "w") +# f.write(str(resultant_string)) +# f.close() +# diff --git a/RVO25/databases/accelerometer_db.js b/RVO25/databases/accelerometer_db.js new file mode 100755 index 0000000..fdfc7fd --- /dev/null +++ b/RVO25/databases/accelerometer_db.js @@ -0,0 +1,3055 @@ +let naklony = { + "3993": { "label": "1/3A", "naklon": 0 }, + "3989": { "label": "1/3B", "naklon": 15 }, + "3976": { "label": "1/1", "naklon": 0 }, + "4181": { "label": "1/2", "naklon": 0 }, + "4376": { "label": "1/4", "naklon": 15 }, + "3868": { "label": "1/5", "naklon": 15 }, + "3728": { "label": "1/6", "naklon": 15 }, + "3730": { "label": "1/7", "naklon": 0 }, + "4374": { "label": "1/8", "naklon": 0 }, + "3718": { "label": "1/9", "naklon": 15 }, + "4375": { "label": "1/10", "naklon": 15 }, + "4172": { "label": "1/11", "naklon": 15 }, + "4176": { "label": "1/12", "naklon": 15 }, + "3800": { "label": "2/1", "naklon": 5 }, + "3823": { "label": "2/2", "naklon": 5 }, + "3905": { "label": "2/3", "naklon": 5 }, + "3803": { "label": "2/4", "naklon": 5 }, + "3817": { "label": "2/5", "naklon": 5 }, + "3818": { "label": "2/6", "naklon": 5 }, + "3811": { "label": "2/7", "naklon": 5 }, + "3915": { "label": "2/8", "naklon": 5 }, + "3843": { "label": "2/9", "naklon": 10 }, + "3827": { "label": "2/10", "naklon": 10 }, + "4220": { "label": "2/11", "naklon": 10 }, + "3826": { "label": "2/12", "naklon": 10 }, + "3834": { "label": "2/13", "naklon": 10 }, + "3838": { "label": "2/14", "naklon": 10 }, + "2823": { "label": "2/15", "naklon": 10 }, + "3750": { "label": "2/16", "naklon": 10 }, + "3378": { "label": "2/17", "naklon": 0 }, + "3376": { "label": "2/18", "naklon": 0 }, + "3379": { "label": "2/19", "naklon": 0 }, + "3285": { "label": "2/20", "naklon": 0 }, + "3382": { "label": "2/21", "naklon": 0 }, + "3383": { "label": "2/22", "naklon": 0 }, + "3375": { "label": "2/24", "naklon": 0 }, + "3381": { "label": "2/25", "naklon": 0 }, + "3380": { "label": "2/26", "naklon": 0 }, + "3828": { "label": "2/27", "naklon": 10 }, + "3377": { "label": "2/28", "naklon": 0 }, + "3591": { "label": "7/1", "naklon": 0 }, + "3587": { "label": "7/2", "naklon": 0 }, + "3468": { "label": "7/3", "naklon": 0 }, + "3466": { "label": "7/4", "naklon": 0 }, + "3474": { "label": "7/5", "naklon": 0 }, + "3481": { "label": "7/6", "naklon": 0 }, + "3589": { "label": "7/7", "naklon": 0 }, + "3472": { "label": "7/8", "naklon": 0 }, + "3473": { "label": "7/9", "naklon": 0 }, + "3584": { "label": "7/10", "naklon": 0 }, + "3571": { "label": "7/11", "naklon": 0 }, + "3476": { "label": "7/12", "naklon": 0 }, + "3590": { "label": "7/13", "naklon": 0 }, + "3478": { "label": "7/14", "naklon": 0 }, + "3471": { "label": "7/15", "naklon": 0 }, + "3467": { "label": "7/16", "naklon": 0 }, + "3479": { "label": "7/17", "naklon": 0 }, + "3480": { "label": "7/18", "naklon": 0 }, + "3477": { "label": "7/19", "naklon": 0 }, + "3362": { "label": "12/1", "naklon": 0 }, + "3355": { "label": "12/2", "naklon": 0 }, + "3356": { "label": "12/3", "naklon": 0 }, + "3349": { "label": "12/4", "naklon": 0 }, + "3357": { "label": "12/5", "naklon": 0 }, + "3350": { "label": "12/6", "naklon": 0 }, + "3353": { "label": "12/7", "naklon": 0 }, + "3539": { "label": "12/8", "naklon": 0 }, + "3050": { "label": "12/9", "naklon": 0 }, + "3361": { "label": "12/10", "naklon": 0 }, + "3360": { "label": "12/11", "naklon": 0 }, + "3358": { "label": "12/12", "naklon": 0 }, + "3541": { "label": "12/13", "naklon": 0 }, + "3551": { "label": "12/14", "naklon": 0 }, + "3514": { "label": "12/15", "naklon": 0 }, + "3547": { "label": "12/16", "naklon": 0 }, + "3562": { "label": "12/17", "naklon": 0 }, + "3525": { "label": "12/18", "naklon": 0 }, + "3558": { "label": "12/19", "naklon": 0 }, + "3511": { "label": "12/20", "naklon": 0 }, + "3058": { "label": "12/21", "naklon": 0 }, + "3062": { "label": "12/22", "naklon": 0 }, + "3070": { "label": "12/23", "naklon": 0 }, + "3447": { "label": "12/24", "naklon": 0 }, + "3056": { "label": "12/25", "naklon": 0 }, + "3057": { "label": "12/26", "naklon": 0 }, + "3071": { "label": "12/27", "naklon": 0 }, + "3061": { "label": "12/28", "naklon": 0 }, + "3069": { "label": "12/29", "naklon": 0 }, + "3077": { "label": "12/30", "naklon": 0 }, + "3080": { "label": "12/31", "naklon": 0 }, + "3081": { "label": "12/32", "naklon": 0 }, + "3078": { "label": "12/33", "naklon": 0 }, + "4037": { "label": "12/34", "naklon": 0 }, + "3067": { "label": "12/35", "naklon": 0 }, + "3051": { "label": "12/36", "naklon": 0 }, + "2924": { "label": "12/37", "naklon": 0 }, + "3060": { "label": "12/38", "naklon": 0 }, + "3073": { "label": "12/39", "naklon": 0 }, + "3469": { "label": "12/40", "naklon": 0 }, + "2923": { "label": "12/41", "naklon": 0 }, + "2925": { "label": "12/42", "naklon": 0 }, + "3359": { "label": "12/43", "naklon": 0 }, + "3055": { "label": "12/44", "naklon": 0 }, + "2922": { "label": "12/45", "naklon": 0 }, + "3084": { "label": "12/46", "naklon": 0 }, + "3064": { "label": "12/47", "naklon": 0 }, + "3066": { "label": "12/48", "naklon": 0 }, + "3072": { "label": "12/49", "naklon": 0 }, + "3415": { "label": "13/13A", "naklon": 0 }, + "3409": { "label": "13/13B", "naklon": 0 }, + "3399": { "label": "13/13C", "naklon": 0 }, + "3410": { "label": "13/29A", "naklon": 0 }, + "3407": { "label": "13/29B", "naklon": 0 }, + "3405": { "label": "13/34A", "naklon": 0 }, + "3404": { "label": "13/34B", "naklon": 0 }, + "3392": { "label": "13/45A", "naklon": 0 }, + "3386": { "label": "13/45B", "naklon": 0 }, + "3303": { "label": "13/60A", "naklon": 3 }, + "3302": { "label": "13/60B", "naklon": 3 }, + "3319": { "label": "13/70A", "naklon": 6 }, + "3317": { "label": "13/70B", "naklon": 6 }, + "3326": { "label": "13/70C", "naklon": 6 }, + "3351": { "label": "13/73A", "naklon": 6 }, + "3313": { "label": "13/73B", "naklon": 6 }, + "3316": { "label": "13/83A", "naklon": 0 }, + "3320": { "label": "13/83B", "naklon": 0 }, + "3336": { "label": "13/95A", "naklon": 0 }, + "3323": { "label": "13/95B", "naklon": 0 }, + "3339": { "label": "13/98A", "naklon": 0 }, + "3333": { "label": "13/98B", "naklon": 0 }, + "3425": { "label": "13/1", "naklon": 0 }, + "3419": { "label": "13/2", "naklon": 0 }, + "3416": { "label": "13/3", "naklon": 0 }, + "3332": { "label": "13/4", "naklon": 0 }, + "3422": { "label": "13/5", "naklon": 0 }, + "3417": { "label": "13/6", "naklon": 0 }, + "3418": { "label": "13/7", "naklon": 0 }, + "3424": { "label": "13/8", "naklon": 0 }, + "3334": { "label": "13/9", "naklon": 0 }, + "4363": { "label": "13/10", "naklon": 0 }, + "3423": { "label": "13/11", "naklon": 0 }, + "3406": { "label": "13/12", "naklon": 0 }, + "3411": { "label": "13/14", "naklon": 0 }, + "3412": { "label": "13/15", "naklon": 0 }, + "3413": { "label": "13/16", "naklon": 0 }, + "3414": { "label": "13/17", "naklon": 0 }, + "3391": { "label": "13/18", "naklon": 0 }, + "3370": { "label": "13/19", "naklon": 0 }, + "3369": { "label": "13/20", "naklon": 0 }, + "3408": { "label": "13/21", "naklon": 0 }, + "3393": { "label": "13/22", "naklon": 0 }, + "3128": { "label": "13/23", "naklon": 0 }, + "3197": { "label": "13/24", "naklon": 0 }, + "4364": { "label": "13/25", "naklon": 0 }, + "3155": { "label": "13/26", "naklon": 0 }, + "3196": { "label": "13/27", "naklon": 0 }, + "3144": { "label": "13/28", "naklon": 0 }, + "3150": { "label": "13/30", "naklon": 0 }, + "3390": { "label": "13/31", "naklon": 0 }, + "3401": { "label": "13/32", "naklon": 0 }, + "3275": { "label": "13/33", "naklon": 0 }, + "3371": { "label": "13/35", "naklon": 0 }, + "3389": { "label": "13/36", "naklon": 0 }, + "3388": { "label": "13/37", "naklon": 0 }, + "3365": { "label": "13/38", "naklon": 0 }, + "3363": { "label": "13/39", "naklon": 0 }, + "3397": { "label": "13/40", "naklon": 0 }, + "3567": { "label": "13/40/1", "naklon": 0 }, + "3387": { "label": "13/41", "naklon": 0 }, + "3403": { "label": "13/42", "naklon": 0 }, + "3147": { "label": "13/43", "naklon": 0 }, + "3141": { "label": "13/44", "naklon": 0 }, + "3364": { "label": "13/46", "naklon": 0 }, + "3367": { "label": "13/47", "naklon": 0 }, + "3368": { "label": "13/48", "naklon": 0 }, + "3402": { "label": "13/49", "naklon": 0 }, + "3366": { "label": "13/50", "naklon": 0 }, + "3395": { "label": "13/51", "naklon": 0 }, + "3372": { "label": "13/52", "naklon": 0 }, + "3394": { "label": "13/53", "naklon": 0 }, + "3308": { "label": "13/54", "naklon": 0 }, + "3847": { "label": "13/54/1", "naklon": 0 }, + "3312": { "label": "13/55", "naklon": 3 }, + "3309": { "label": "13/56", "naklon": 3 }, + "3311": { "label": "13/57", "naklon": 3 }, + "3310": { "label": "13/58", "naklon": 3 }, + "4365": { "label": "13/59", "naklon": 3 }, + "4093": { "label": "13/60/1", "naklon": 3 }, + "3304": { "label": "13/61", "naklon": 3 }, + "3307": { "label": "13/62", "naklon": 3 }, + "3271": { "label": "13/63", "naklon": 3 }, + "3301": { "label": "13/64", "naklon": 3 }, + "4366": { "label": "13/65", "naklon": 3 }, + "3300": { "label": "13/66", "naklon": 3 }, + "3185": { "label": "13/67", "naklon": 0 }, + "3184": { "label": "13/68", "naklon": 0 }, + "3188": { "label": "13/69", "naklon": 0 }, + "3343": { "label": "13/71", "naklon": 6 }, + "3819": { "label": "13/71/1", "naklon": 6 }, + "3880": { "label": "13/71/2", "naklon": 6 }, + "3348": { "label": "13/72", "naklon": 6 }, + "3344": { "label": "13/74", "naklon": 6 }, + "3346": { "label": "13/75", "naklon": 6 }, + "3597": { "label": "13/75/1", "naklon": 6 }, + "3345": { "label": "13/76", "naklon": 6 }, + "3322": { "label": "13/77", "naklon": 0 }, + "3325": { "label": "13/78", "naklon": 0 }, + "4310": { "label": "13/78/1", "naklon": 0 }, + "3315": { "label": "13/79", "naklon": 0 }, + "3328": { "label": "13/80", "naklon": 0 }, + "3321": { "label": "13/81", "naklon": 0 }, + "3324": { "label": "13/82", "naklon": 0 }, + "3140": { "label": "13/84", "naklon": 0 }, + "3153": { "label": "13/85", "naklon": 0 }, + "3145": { "label": "13/86", "naklon": 0 }, + "3134": { "label": "13/87", "naklon": 0 }, + "3151": { "label": "13/88", "naklon": 0 }, + "3143": { "label": "13/89", "naklon": 0 }, + "3318": { "label": "13/90", "naklon": 0 }, + "3347": { "label": "13/91", "naklon": 0 }, + "3314": { "label": "13/94", "naklon": 0 }, + "3331": { "label": "13/96", "naklon": 0 }, + "3327": { "label": "13/97", "naklon": 0 }, + "3329": { "label": "13/99", "naklon": 0 }, + "3337": { "label": "13/100", "naklon": 0 }, + "3330": { "label": "13/101", "naklon": 0 }, + "3335": { "label": "13/102", "naklon": 0 }, + "3420": { "label": "13/103", "naklon": 0 }, + "3421": { "label": "13/104", "naklon": 0 }, + "4361": { "label": "13/105", "naklon": 0 }, + "4362": { "label": "13/106", "naklon": 0 }, + "3526": { "label": "13/107", "naklon": 0 }, + "4424": { "label": "13/108", "naklon": null }, + "3561": { "label": "13/109", "naklon": null }, + "3527": { "label": "13/110", "naklon": null }, + "3521": { "label": "13/111", "naklon": null }, + "3552": { "label": "13/112", "naklon": null }, + "3544": { "label": "13/113", "naklon": null }, + "3534": { "label": "13/114", "naklon": null }, + "3516": { "label": "13/115", "naklon": null }, + "3513": { "label": "13/116", "naklon": null }, + "3565": { "label": "13/117", "naklon": null }, + "3866": { "label": "13/118", "naklon": null }, + "3136": { "label": "14/1", "naklon": 0 }, + "3137": { "label": "14/2", "naklon": 0 }, + "3135": { "label": "14/3", "naklon": 0 }, + "3149": { "label": "14/4", "naklon": 0 }, + "3142": { "label": "14/5", "naklon": 0 }, + "3342": { "label": "14/6", "naklon": 0 }, + "3340": { "label": "14/7", "naklon": 0 }, + "3152": { "label": "14/8", "naklon": 0 }, + "3886": { "label": "14/9", "naklon": 0 }, + "3341": { "label": "14/10", "naklon": null }, + "3352": { "label": "14/11", "naklon": null }, + "3396": { "label": "15/1", "naklon": 5 }, + "2784": { "label": "15/2", "naklon": 5 }, + "2788": { "label": "15/3", "naklon": 5 }, + "2801": { "label": "15/4", "naklon": 5 }, + "2815": { "label": "15/5", "naklon": 5 }, + "2829": { "label": "15/6", "naklon": 5 }, + "2796": { "label": "15/7", "naklon": 5 }, + "2803": { "label": "15/8", "naklon": 5 }, + "4304": { "label": "15/8/1", "naklon": 5 }, + "4311": { "label": "15/8/2", "naklon": 5 }, + "2821": { "label": "15/9", "naklon": 5 }, + "3400": { "label": "15/10", "naklon": 5 }, + "2799": { "label": "15/11", "naklon": 5 }, + "2804": { "label": "15/12", "naklon": 5 }, + "4303": { "label": "15/12/1", "naklon": 5 }, + "4309": { "label": "15/12/2", "naklon": 5 }, + "2806": { "label": "15/13", "naklon": 5 }, + "2787": { "label": "15/14", "naklon": 5 }, + "2809": { "label": "15/15", "naklon": 5 }, + "2814": { "label": "15/16", "naklon": 0 }, + "3934": { "label": "15/17", "naklon": 0 }, + "3192": { "label": "15/18", "naklon": 0 }, + "2812": { "label": "15/19", "naklon": 0 }, + "4070": { "label": "15/20", "naklon": 0 }, + "2826": { "label": "15/21", "naklon": 0 }, + "2808": { "label": "15/22", "naklon": 3 }, + "2795": { "label": "15/23", "naklon": 3 }, + "2807": { "label": "15/24", "naklon": 3 }, + "2831": { "label": "15/25", "naklon": 0 }, + "2862": { "label": "15/26", "naklon": null }, + "2861": { "label": "15/27", "naklon": 0 }, + "2866": { "label": "15/28", "naklon": 0 }, + "3546": { "label": "15/28/1", "naklon": 0 }, + "4146": { "label": "15/29", "naklon": 0 }, + "3001": { "label": "15/29/1", "naklon": 0 }, + "2835": { "label": "15/30", "naklon": 0 }, + "2874": { "label": "15/31", "naklon": 0 }, + "2852": { "label": "15/32", "naklon": 0 }, + "2851": { "label": "15/33", "naklon": 0 }, + "3560": { "label": "15/33/1", "naklon": 0 }, + "2858": { "label": "15/34", "naklon": 0 }, + "4306": { "label": "15/34/1", "naklon": 0 }, + "2856": { "label": "15/35", "naklon": 0 }, + "2847": { "label": "15/36", "naklon": 0 }, + "3556": { "label": "15/36/1", "naklon": 0 }, + "3950": { "label": "15/37", "naklon": 0 }, + "2848": { "label": "15/38", "naklon": 0 }, + "2863": { "label": "15/39", "naklon": 0 }, + "4313": { "label": "15/39/1", "naklon": 0 }, + "2873": { "label": "15/40", "naklon": 0 }, + "2984": { "label": "15/40/1", "naklon": 0 }, + "2854": { "label": "15/41", "naklon": 0 }, + "2859": { "label": "15/42", "naklon": 0 }, + "2872": { "label": "15/43", "naklon": 0 }, + "2849": { "label": "15/44", "naklon": 0 }, + "2864": { "label": "15/45", "naklon": 0 }, + "3553": { "label": "15/46", "naklon": null }, + "3021": { "label": "15/47", "naklon": null }, + "3008": { "label": "15/47/1", "naklon": null }, + "3017": { "label": "15/48", "naklon": null }, + "3014": { "label": "15/49", "naklon": null }, + "2981": { "label": "15/50", "naklon": null }, + "3020": { "label": "15/51", "naklon": null }, + "3027": { "label": "15/52", "naklon": null }, + "3006": { "label": "15/53", "naklon": null }, + "3012": { "label": "15/54", "naklon": null }, + "2738": { "label": "15/55", "naklon": 0 }, + "2725": { "label": "15/56", "naklon": 0 }, + "3016": { "label": "15/57", "naklon": null }, + "3005": { "label": "15/58", "naklon": null }, + "3009": { "label": "15/58/1", "naklon": null }, + "3010": { "label": "15/59", "naklon": 0 }, + "3538": { "label": "15/59/1", "naklon": 0 }, + "4145": { "label": "15/59/2", "naklon": 0 }, + "2713": { "label": "15/60", "naklon": 0 }, + "2789": { "label": "15/61", "naklon": 0 }, + "2736": { "label": "15/62", "naklon": 0 }, + "2739": { "label": "15/63", "naklon": 0 }, + "4346": { "label": "15/64", "naklon": 0 }, + "2731": { "label": "15/65", "naklon": 0 }, + "2818": { "label": "15/66", "naklon": 0 }, + "3557": { "label": "15/66/1", "naklon": 0 }, + "2822": { "label": "15/67", "naklon": 0 }, + "2833": { "label": "15/68", "naklon": 0 }, + "2834": { "label": "15/69", "naklon": 0 }, + "3097": { "label": "15/70", "naklon": 0 }, + "2824": { "label": "15/71", "naklon": 0 }, + "2828": { "label": "15/72", "naklon": 0 }, + "2600": { "label": "15/73", "naklon": 0 }, + "4314": { "label": "15/73/1", "naklon": 0 }, + "2832": { "label": "15/74", "naklon": 0 }, + "4360": { "label": "15/75", "naklon": 0 }, + "2846": { "label": "15/76", "naklon": 0 }, + "2584": { "label": "15/77", "naklon": 0 }, + "2843": { "label": "15/78", "naklon": 0 }, + "4308": { "label": "15/78/1", "naklon": 0 }, + "4144": { "label": "15/79", "naklon": null }, + "2844": { "label": "15/80", "naklon": 0 }, + "2842": { "label": "15/81", "naklon": 0 }, + "2838": { "label": "15/82", "naklon": 0 }, + "2837": { "label": "15/83", "naklon": null }, + "3555": { "label": "15/83/1", "naklon": null }, + "2839": { "label": "15/84", "naklon": 0 }, + "2830": { "label": "15/85", "naklon": 0 }, + "4066": { "label": "15/86", "naklon": 0 }, + "2836": { "label": "15/87", "naklon": 0 }, + "2911": { "label": "15/88", "naklon": 0 }, + "2825": { "label": "15/89", "naklon": 0 }, + "2811": { "label": "15/90", "naklon": 0 }, + "3740": { "label": "15/94", "naklon": 15 }, + "2734": { "label": "15/95", "naklon": 15 }, + "3105": { "label": "15/96", "naklon": 15 }, + "2732": { "label": "15/97", "naklon": 15 }, + "2727": { "label": "15/98", "naklon": 15 }, + "2735": { "label": "15/99", "naklon": 15 }, + "3926": { "label": "15/100", "naklon": 15 }, + "2918": { "label": "15/101", "naklon": 0 }, + "2705": { "label": "15/102", "naklon": 10 }, + "2708": { "label": "15/103", "naklon": 10 }, + "2721": { "label": "15/104", "naklon": 10 }, + "2719": { "label": "15/105", "naklon": 10 }, + "2919": { "label": "15/106", "naklon": 10 }, + "3101": { "label": "15/107", "naklon": 10 }, + "2853": { "label": "15/108", "naklon": 10 }, + "2715": { "label": "15/109", "naklon": 10 }, + "2712": { "label": "15/110", "naklon": 0 }, + "2711": { "label": "15/111", "naklon": 0 }, + "2709": { "label": "15/112", "naklon": 0 }, + "2710": { "label": "15/113", "naklon": 0 }, + "2907": { "label": "15/114", "naklon": 0 }, + "2906": { "label": "15/115", "naklon": 0 }, + "2908": { "label": "15/116", "naklon": 0 }, + "2901": { "label": "15/117", "naklon": 0 }, + "2913": { "label": "15/118", "naklon": 0 }, + "3656": { "label": "15/119", "naklon": 0 }, + "2781": { "label": "15/120", "naklon": 0 }, + "2802": { "label": "15/121", "naklon": 0 }, + "2791": { "label": "15/122", "naklon": 0 }, + "2783": { "label": "15/123", "naklon": 0 }, + "2794": { "label": "15/124", "naklon": 0 }, + "3139": { "label": "15/125", "naklon": 0 }, + "3229": { "label": "15/126", "naklon": 5 }, + "3239": { "label": "15/127", "naklon": 5 }, + "3230": { "label": "15/128", "naklon": 5 }, + "4016": { "label": "15/129", "naklon": null }, + "3608": { "label": "16/16A", "naklon": 0 }, + "4151": { "label": "16/16B", "naklon": 0 }, + "3710": { "label": "16/1", "naklon": 0 }, + "3726": { "label": "16/2", "naklon": 0 }, + "3743": { "label": "16/3", "naklon": 0 }, + "3724": { "label": "16/4", "naklon": 0 }, + "3712": { "label": "16/5", "naklon": 0 }, + "3739": { "label": "16/6", "naklon": 0 }, + "3742": { "label": "16/7", "naklon": 0 }, + "3731": { "label": "16/8", "naklon": 0 }, + "3727": { "label": "16/9", "naklon": 0 }, + "3729": { "label": "16/10", "naklon": 0 }, + "3736": { "label": "16/11", "naklon": 0 }, + "3713": { "label": "16/12", "naklon": 0 }, + "3715": { "label": "16/13", "naklon": 0 }, + "3733": { "label": "16/14", "naklon": 0 }, + "3732": { "label": "16/15", "naklon": 0 }, + "3634": { "label": "16/17", "naklon": 0 }, + "3610": { "label": "16/18", "naklon": 0 }, + "3626": { "label": "16/19", "naklon": 0 }, + "3618": { "label": "16/20", "naklon": 0 }, + "3619": { "label": "16/21", "naklon": 0 }, + "3628": { "label": "16/22", "naklon": 0 }, + "3615": { "label": "16/23", "naklon": 0 }, + "3609": { "label": "16/24", "naklon": 0 }, + "3606": { "label": "16/25", "naklon": 0 }, + "3624": { "label": "16/26", "naklon": 0 }, + "3627": { "label": "16/27", "naklon": 0 }, + "3607": { "label": "16/28", "naklon": 0 }, + "4370": { "label": "16/29", "naklon": 0 }, + "3692": { "label": "16/30", "naklon": 0 }, + "3614": { "label": "16/31", "naklon": 0 }, + "3623": { "label": "16/32", "naklon": 0 }, + "4373": { "label": "16/33", "naklon": 0 }, + "3620": { "label": "16/34", "naklon": 0 }, + "3685": { "label": "16/35", "naklon": 0 }, + "3616": { "label": "16/36", "naklon": 0 }, + "3686": { "label": "16/37", "naklon": 0 }, + "3688": { "label": "16/38", "naklon": 0 }, + "3684": { "label": "16/39", "naklon": 0 }, + "3825": { "label": "16/40", "naklon": 0 }, + "3865": { "label": "16/41", "naklon": 0 }, + "3824": { "label": "16/42", "naklon": 0 }, + "3871": { "label": "16/43", "naklon": 0 }, + "3801": { "label": "16/44", "naklon": 0 }, + "3862": { "label": "16/45", "naklon": 0 }, + "3876": { "label": "16/46", "naklon": 0 }, + "3861": { "label": "16/47", "naklon": 0 }, + "4215": { "label": "16/48", "naklon": 0 }, + "3605": { "label": "16/49", "naklon": 10 }, + "3603": { "label": "16/50", "naklon": 10 }, + "3592": { "label": "16/51", "naklon": 10 }, + "3598": { "label": "16/52", "naklon": 10 }, + "3594": { "label": "16/53", "naklon": 10 }, + "3593": { "label": "16/54", "naklon": 10 }, + "3630": { "label": "16/55", "naklon": 10 }, + "3763": { "label": "16/56", "naklon": 10 }, + "3746": { "label": "16/57", "naklon": 10 }, + "3699": { "label": "16/58", "naklon": 0 }, + "3698": { "label": "16/59", "naklon": 0 }, + "3709": { "label": "16/60", "naklon": null }, + "3708": { "label": "16/61", "naklon": 0 }, + "3703": { "label": "16/62", "naklon": null }, + "3700": { "label": "16/63", "naklon": 0 }, + "3701": { "label": "16/64", "naklon": null }, + "3704": { "label": "16/65", "naklon": 0 }, + "3707": { "label": "16/66", "naklon": null }, + "3810": { "label": "16/67", "naklon": 0 }, + "4208": { "label": "16/68", "naklon": null }, + "3867": { "label": "16/69", "naklon": 0 }, + "4372": { "label": "16/70", "naklon": null }, + "3881": { "label": "16/71", "naklon": 0 }, + "4204": { "label": "16/72", "naklon": null }, + "3869": { "label": "16/73", "naklon": 0 }, + "4202": { "label": "16/74", "naklon": null }, + "3830": { "label": "16/75", "naklon": 0 }, + "3870": { "label": "16/76", "naklon": null }, + "3964": { "label": "16/77", "naklon": 0 }, + "3849": { "label": "16/78", "naklon": 0 }, + "3694": { "label": "16/79", "naklon": null }, + "3717": { "label": "16/80", "naklon": 0 }, + "3877": { "label": "16/81", "naklon": null }, + "3755": { "label": "16/82", "naklon": 0 }, + "3725": { "label": "16/83", "naklon": null }, + "3716": { "label": "16/84", "naklon": 0 }, + "3696": { "label": "16/85", "naklon": null }, + "3702": { "label": "16/86", "naklon": 0 }, + "3706": { "label": "16/87", "naklon": null }, + "3850": { "label": "16/88", "naklon": 0 }, + "3848": { "label": "16/89", "naklon": null }, + "3737": { "label": "16/90", "naklon": null }, + "3705": { "label": "16/91", "naklon": 0 }, + "3723": { "label": "16/92", "naklon": null }, + "3842": { "label": "16/93", "naklon": 0 }, + "3735": { "label": "16/94", "naklon": null }, + "3719": { "label": "16/95", "naklon": 0 }, + "3697": { "label": "16/96", "naklon": 0 }, + "3711": { "label": "16/97", "naklon": 0 }, + "4107": { "label": "16/98", "naklon": null }, + "4112": { "label": "16/99", "naklon": 5 }, + "4106": { "label": "16/100", "naklon": 5 }, + "4111": { "label": "16/101", "naklon": 5 }, + "4091": { "label": "16/102", "naklon": null }, + "4104": { "label": "16/103", "naklon": 5 }, + "4094": { "label": "16/104", "naklon": null }, + "4089": { "label": "16/105", "naklon": 5 }, + "4095": { "label": "16/106", "naklon": null }, + "4102": { "label": "16/107", "naklon": 5 }, + "4105": { "label": "16/108", "naklon": null }, + "3859": { "label": "16/109", "naklon": null }, + "4090": { "label": "16/110", "naklon": 5 }, + "4110": { "label": "16/111", "naklon": null }, + "4097": { "label": "16/112", "naklon": 5 }, + "4099": { "label": "16/113", "naklon": null }, + "4096": { "label": "16/114", "naklon": null }, + "4101": { "label": "16/115", "naklon": 5 }, + "4109": { "label": "16/116", "naklon": null }, + "4092": { "label": "16/117", "naklon": 5 }, + "3631": { "label": "16/118", "naklon": null }, + "3632": { "label": "16/119", "naklon": 0 }, + "3641": { "label": "16/120", "naklon": null }, + "3638": { "label": "16/121", "naklon": 0 }, + "3637": { "label": "16/122", "naklon": null }, + "4142": { "label": "16/123", "naklon": null }, + "4147": { "label": "16/124", "naklon": 5 }, + "4139": { "label": "16/125", "naklon": 5 }, + "3172": { "label": "20/30A", "naklon": 2 }, + "3164": { "label": "20/30B", "naklon": 2 }, + "3247": { "label": "20/1", "naklon": 10 }, + "3296": { "label": "20/2", "naklon": 10 }, + "3246": { "label": "20/3", "naklon": 10 }, + "3270": { "label": "20/4", "naklon": 10 }, + "3294": { "label": "20/5", "naklon": 10 }, + "3298": { "label": "20/6", "naklon": 10 }, + "3297": { "label": "20/7", "naklon": 10 }, + "3293": { "label": "20/8", "naklon": 10 }, + "3299": { "label": "20/9", "naklon": 10 }, + "3295": { "label": "20/10", "naklon": 10 }, + "3244": { "label": "20/11", "naklon": 10 }, + "3249": { "label": "20/12", "naklon": 10 }, + "3268": { "label": "20/13", "naklon": 10 }, + "3245": { "label": "20/14", "naklon": 10 }, + "3278": { "label": "20/15", "naklon": 10 }, + "3280": { "label": "20/16", "naklon": 10 }, + "3292": { "label": "20/17", "naklon": 10 }, + "3287": { "label": "20/18", "naklon": 10 }, + "3282": { "label": "20/19", "naklon": 10 }, + "3273": { "label": "20/20", "naklon": 0 }, + "3157": { "label": "20/21", "naklon": 0 }, + "3283": { "label": "20/22", "naklon": 0 }, + "3159": { "label": "20/23", "naklon": 0 }, + "3289": { "label": "20/24", "naklon": 0 }, + "3163": { "label": "20/25", "naklon": 0 }, + "3126": { "label": "20/26", "naklon": 0 }, + "3171": { "label": "20/27", "naklon": 0 }, + "3162": { "label": "20/28", "naklon": 0 }, + "3279": { "label": "20/29", "naklon": 10 }, + "3173": { "label": "20/31", "naklon": 0 }, + "3127": { "label": "20/32", "naklon": 0 }, + "3131": { "label": "20/33", "naklon": 0 }, + "3129": { "label": "20/34", "naklon": 0 }, + "3276": { "label": "20/35", "naklon": 2 }, + "3290": { "label": "20/36", "naklon": 2 }, + "3132": { "label": "20/37", "naklon": 0 }, + "3138": { "label": "20/38", "naklon": 0 }, + "3272": { "label": "20/39", "naklon": 0 }, + "3291": { "label": "20/40", "naklon": 0 }, + "3277": { "label": "20/41", "naklon": 10 }, + "3286": { "label": "20/42", "naklon": 10 }, + "3281": { "label": "20/43", "naklon": 10 }, + "3288": { "label": "20/44", "naklon": 10 }, + "3284": { "label": "20/45", "naklon": 10 }, + "3167": { "label": "20/46", "naklon": 10 }, + "3872": { "label": "20/47", "naklon": 0 }, + "3124": { "label": "20/48", "naklon": 0 }, + "3133": { "label": "20/49", "naklon": 0 }, + "3158": { "label": "20/50", "naklon": 0 }, + "3169": { "label": "20/51", "naklon": 0 }, + "3146": { "label": "20/52", "naklon": 0 }, + "3160": { "label": "20/53", "naklon": 0 }, + "3248": { "label": "20/54", "naklon": 0 }, + "3156": { "label": "20/55", "naklon": 0 }, + "3161": { "label": "20/56", "naklon": 0 }, + "3170": { "label": "20/57", "naklon": 0 }, + "3168": { "label": "20/58", "naklon": 0 }, + "3125": { "label": "20/59", "naklon": 0 }, + "3166": { "label": "20/60", "naklon": 0 }, + "3130": { "label": "20/61", "naklon": 0 }, + "3563": { "label": "20/62", "naklon": 0 }, + "3550": { "label": "20/63", "naklon": null }, + "3269": { "label": "20/67", "naklon": 0 }, + "2921": { "label": "21/1", "naklon": 0 }, + "2707": { "label": "21/2", "naklon": 0 }, + "2723": { "label": "21/3", "naklon": 0 }, + "2716": { "label": "21/4", "naklon": 0 }, + "2717": { "label": "21/5", "naklon": 0 }, + "2720": { "label": "21/6", "naklon": 0 }, + "2722": { "label": "21/7", "naklon": 0 }, + "2718": { "label": "21/8", "naklon": 0 }, + "2724": { "label": "21/9", "naklon": 0 }, + "2742": { "label": "21/10", "naklon": 0 }, + "2743": { "label": "21/11", "naklon": 0 }, + "2733": { "label": "21/12", "naklon": 0 }, + "2903": { "label": "21/14", "naklon": 0 }, + "2917": { "label": "21/15", "naklon": 0 }, + "2897": { "label": "21/16", "naklon": 0 }, + "2914": { "label": "21/17", "naklon": 0 }, + "2898": { "label": "21/18", "naklon": 0 }, + "2773": { "label": "21/19", "naklon": 0 }, + "2895": { "label": "21/20", "naklon": 0 }, + "2896": { "label": "21/21", "naklon": 0 }, + "2771": { "label": "21/22", "naklon": 0 }, + "2772": { "label": "21/23", "naklon": 0 }, + "2793": { "label": "21/24", "naklon": 0 }, + "2902": { "label": "21/25", "naklon": 0 }, + "2910": { "label": "21/26", "naklon": 0 }, + "2909": { "label": "21/27", "naklon": 0 }, + "2920": { "label": "21/28", "naklon": 0 }, + "2916": { "label": "21/29", "naklon": 0 }, + "2904": { "label": "21/30", "naklon": 0 }, + "2915": { "label": "21/31", "naklon": 0 }, + "2905": { "label": "21/32", "naklon": 0 }, + "2900": { "label": "21/33", "naklon": 0 }, + "2899": { "label": "21/34", "naklon": 0 }, + "2741": { "label": "21/36", "naklon": 0 }, + "2714": { "label": "21/37", "naklon": 0 }, + "2701": { "label": "21/38", "naklon": 0 }, + "2703": { "label": "21/39", "naklon": 0 }, + "2704": { "label": "21/40", "naklon": 0 }, + "2702": { "label": "21/41", "naklon": 0 }, + "2706": { "label": "21/42", "naklon": 0 }, + "2776": { "label": "21/43", "naklon": 0 }, + "2770": { "label": "21/44", "naklon": 0 }, + "2786": { "label": "21/45", "naklon": 0 }, + "2779": { "label": "21/46", "naklon": 0 }, + "2782": { "label": "21/47", "naklon": 0 }, + "2785": { "label": "21/48", "naklon": 0 }, + "2769": { "label": "21/49", "naklon": 0 }, + "3354": { "label": "21/50", "naklon": 0 }, + "2778": { "label": "21/51", "naklon": 0 }, + "2775": { "label": "21/52", "naklon": 0 }, + "2780": { "label": "21/53", "naklon": 0 }, + "2790": { "label": "21/54", "naklon": 0 }, + "2792": { "label": "21/55", "naklon": 0 }, + "2774": { "label": "21/56", "naklon": 0 }, + "2630": { "label": "22/1", "naklon": 0 }, + "2631": { "label": "22/2", "naklon": 0 }, + "2632": { "label": "22/3", "naklon": 0 }, + "2633": { "label": "22/4", "naklon": 0 }, + "2634": { "label": "22/5", "naklon": 0 }, + "2636": { "label": "22/6", "naklon": 0 }, + "4367": { "label": "22/7", "naklon": 0 }, + "2637": { "label": "22/8", "naklon": 0 }, + "2638": { "label": "22/9", "naklon": 0 }, + "2639": { "label": "22/10", "naklon": 0 }, + "2640": { "label": "22/11", "naklon": 0 }, + "2641": { "label": "22/12", "naklon": 0 }, + "2642": { "label": "22/13", "naklon": 0 }, + "2643": { "label": "22/14", "naklon": 0 }, + "2644": { "label": "22/15", "naklon": 0 }, + "2645": { "label": "22/16", "naklon": 0 }, + "2646": { "label": "22/17", "naklon": 0 }, + "2647": { "label": "22/18", "naklon": 0 }, + "2648": { "label": "22/19", "naklon": 0 }, + "2649": { "label": "22/20", "naklon": 0 }, + "2650": { "label": "22/21", "naklon": 0 }, + "2651": { "label": "22/22", "naklon": 0 }, + "4103": { "label": "22/23", "naklon": 0 }, + "2653": { "label": "22/24", "naklon": 0 }, + "2654": { "label": "22/25", "naklon": 0 }, + "2655": { "label": "22/26", "naklon": 0 }, + "2656": { "label": "22/27", "naklon": 0 }, + "2657": { "label": "22/28", "naklon": 0 }, + "2658": { "label": "22/29", "naklon": 0 }, + "2659": { "label": "22/30", "naklon": 0 }, + "2660": { "label": "22/31", "naklon": 0 }, + "2661": { "label": "22/32", "naklon": 0 }, + "3015": { "label": "22/32/1", "naklon": 0 }, + "2662": { "label": "22/33", "naklon": 0 }, + "2663": { "label": "22/34", "naklon": 0 }, + "2664": { "label": "22/35", "naklon": 0 }, + "2665": { "label": "22/36", "naklon": 0 }, + "2666": { "label": "22/37", "naklon": 0 }, + "2667": { "label": "22/38", "naklon": 0 }, + "2668": { "label": "22/39", "naklon": 0 }, + "2669": { "label": "22/40", "naklon": null }, + "2670": { "label": "22/41", "naklon": null }, + "2671": { "label": "22/42", "naklon": null }, + "3087": { "label": "23/9A", "naklon": 10 }, + "3090": { "label": "23/9B", "naklon": 10 }, + "3075": { "label": "23/1", "naklon": 0 }, + "3089": { "label": "23/2", "naklon": 0 }, + "3088": { "label": "23/3", "naklon": 0 }, + "3228": { "label": "23/4", "naklon": 10 }, + "2751": { "label": "23/5", "naklon": 10 }, + "3243": { "label": "23/6", "naklon": 10 }, + "4349": { "label": "23/7", "naklon": 10 }, + "3102": { "label": "23/8", "naklon": 10 }, + "3099": { "label": "23/10", "naklon": 10 }, + "3103": { "label": "23/11", "naklon": 10 }, + "3093": { "label": "23/12", "naklon": 10 }, + "3098": { "label": "23/13", "naklon": 10 }, + "3092": { "label": "23/14", "naklon": 10 }, + "3233": { "label": "23/15", "naklon": 0 }, + "3095": { "label": "23/16", "naklon": 0 }, + "4074": { "label": "23/17", "naklon": 0 }, + "2729": { "label": "23/18", "naklon": 0 }, + "3234": { "label": "23/19", "naklon": 0 }, + "3094": { "label": "23/20", "naklon": 0 }, + "2817": { "label": "23/21", "naklon": 0 }, + "3226": { "label": "23/22", "naklon": 0 }, + "3225": { "label": "23/23", "naklon": 0 }, + "3237": { "label": "23/24", "naklon": 0 }, + "4250": { "label": "23/25", "naklon": 0 }, + "3059": { "label": "23/26", "naklon": 10 }, + "3238": { "label": "23/27", "naklon": 10 }, + "3242": { "label": "23/28", "naklon": 10 }, + "3236": { "label": "23/29", "naklon": 10 }, + "3112": { "label": "23/30", "naklon": 10 }, + "3224": { "label": "23/31", "naklon": 0 }, + "4298": { "label": "23/32", "naklon": 10 }, + "4150": { "label": "23/33", "naklon": 10 }, + "3091": { "label": "23/34", "naklon": 10 }, + "3771": { "label": "25/1", "naklon": 5 }, + "3777": { "label": "25/2", "naklon": 5 }, + "3749": { "label": "25/3", "naklon": 5 }, + "3769": { "label": "25/4", "naklon": 5 }, + "3765": { "label": "25/5", "naklon": 5 }, + "3785": { "label": "25/6", "naklon": 5 }, + "3761": { "label": "25/7", "naklon": 5 }, + "3758": { "label": "25/8", "naklon": 5 }, + "3766": { "label": "25/9", "naklon": 5 }, + "3779": { "label": "25/10", "naklon": 5 }, + "3899": { "label": "25/11", "naklon": 10 }, + "3922": { "label": "25/12", "naklon": 10 }, + "3912": { "label": "25/13", "naklon": 10 }, + "3933": { "label": "25/14", "naklon": 10 }, + "3921": { "label": "25/15", "naklon": 10 }, + "4300": { "label": "25/16", "naklon": 10 }, + "3927": { "label": "25/17", "naklon": 10 }, + "3212": { "label": "25/18", "naklon": 10 }, + "3208": { "label": "25/19", "naklon": 10 }, + "3207": { "label": "25/20", "naklon": 10 }, + "4294": { "label": "25/21", "naklon": 10 }, + "3209": { "label": "25/22", "naklon": 10 }, + "3745": { "label": "25/23", "naklon": 10 }, + "3762": { "label": "25/24", "naklon": 10 }, + "3215": { "label": "25/25", "naklon": 10 }, + "3210": { "label": "25/26", "naklon": 10 }, + "3211": { "label": "25/27", "naklon": 10 }, + "3206": { "label": "25/28", "naklon": 10 }, + "3918": { "label": "25/29", "naklon": 5 }, + "3928": { "label": "25/30", "naklon": 5 }, + "3917": { "label": "25/31", "naklon": 5 }, + "4029": { "label": "25/32", "naklon": 0 }, + "4038": { "label": "25/33", "naklon": 0 }, + "4022": { "label": "25/34", "naklon": 0 }, + "3937": { "label": "25/35", "naklon": 0 }, + "3190": { "label": "25/36", "naklon": 0 }, + "3835": { "label": "25/37", "naklon": 0 }, + "3201": { "label": "25/38", "naklon": 0 }, + "3193": { "label": "25/39", "naklon": 0 }, + "3191": { "label": "25/40", "naklon": 0 }, + "3203": { "label": "25/41", "naklon": 0 }, + "4301": { "label": "25/42", "naklon": 0 }, + "3223": { "label": "25/43", "naklon": 0 }, + "3202": { "label": "25/44", "naklon": 0 }, + "3205": { "label": "25/45", "naklon": 0 }, + "3194": { "label": "25/46", "naklon": 0 }, + "3198": { "label": "25/47", "naklon": 0 }, + "3204": { "label": "25/48", "naklon": 0 }, + "3200": { "label": "25/49", "naklon": 0 }, + "3216": { "label": "25/50", "naklon": 0 }, + "3932": { "label": "25/51", "naklon": 5 }, + "3923": { "label": "25/52", "naklon": 5 }, + "3913": { "label": "25/53", "naklon": 5 }, + "3900": { "label": "25/54", "naklon": 5 }, + "4189": { "label": "25/55", "naklon": 10 }, + "4191": { "label": "25/56", "naklon": 10 }, + "3790": { "label": "25/57", "naklon": 10 }, + "4190": { "label": "25/58", "naklon": 10 }, + "4302": { "label": "25/59", "naklon": 0 }, + "4351": { "label": "25/60", "naklon": 0 }, + "4075": { "label": "25/61", "naklon": 0 }, + "4071": { "label": "25/62", "naklon": 0 }, + "3784": { "label": "25/63", "naklon": 0 }, + "4065": { "label": "25/64", "naklon": 0 }, + "4297": { "label": "25/65", "naklon": 0 }, + "4295": { "label": "25/66", "naklon": 0 }, + "4299": { "label": "25/67", "naklon": 0 }, + "3772": { "label": "25/68", "naklon": 0 }, + "3941": { "label": "25/69", "naklon": 0 }, + "3782": { "label": "25/70", "naklon": 0 }, + "4068": { "label": "25/71", "naklon": 0 }, + "4073": { "label": "25/72", "naklon": 0 }, + "3901": { "label": "25/73", "naklon": 5 }, + "4296": { "label": "25/74", "naklon": 5 }, + "3910": { "label": "25/75", "naklon": 5 }, + "4293": { "label": "25/76", "naklon": 5 }, + "3919": { "label": "25/77", "naklon": 5 }, + "3924": { "label": "25/78", "naklon": 5 }, + "3909": { "label": "25/79", "naklon": 5 }, + "3896": { "label": "25/80", "naklon": 5 }, + "3911": { "label": "25/81", "naklon": 5 }, + "2819": { "label": "25/82", "naklon": 15 }, + "3776": { "label": "25/83", "naklon": 15 }, + "3752": { "label": "25/84", "naklon": 15 }, + "4353": { "label": "25/85", "naklon": 15 }, + "3791": { "label": "25/86", "naklon": 0 }, + "3770": { "label": "25/87", "naklon": 0 }, + "3760": { "label": "25/88", "naklon": 0 }, + "3115": { "label": "25/89", "naklon": 0 }, + "3738": { "label": "25/90", "naklon": 0 }, + "3748": { "label": "25/91", "naklon": 0 }, + "3753": { "label": "25/92", "naklon": 0 }, + "3775": { "label": "25/93", "naklon": 0 }, + "3778": { "label": "25/94", "naklon": 5 }, + "4078": { "label": "25/95", "naklon": 5 }, + "4088": { "label": "25/96", "naklon": 5 }, + "3856": { "label": "25/97", "naklon": 5 }, + "4084": { "label": "25/98", "naklon": 5 }, + "4069": { "label": "25/99", "naklon": 5 }, + "4188": { "label": "25/100", "naklon": 5 }, + "4064": { "label": "25/101", "naklon": 5 }, + "3792": { "label": "25/102", "naklon": 5 }, + "3780": { "label": "25/103", "naklon": 5 }, + "4034": { "label": "25/104", "naklon": 5 }, + "4072": { "label": "25/105", "naklon": 5 }, + "3884": { "label": "25/106", "naklon": 5 }, + "3793": { "label": "25/107", "naklon": 5 }, + "3863": { "label": "25/108", "naklon": 5 }, + "3855": { "label": "25/109", "naklon": 5 }, + "3846": { "label": "33/1", "naklon": 0 }, + "3943": { "label": "33/2", "naklon": 0 }, + "3903": { "label": "33/3", "naklon": 0 }, + "3982": { "label": "33/4", "naklon": 0 }, + "3879": { "label": "33/5", "naklon": 0 }, + "3887": { "label": "33/6", "naklon": 0 }, + "3920": { "label": "33/7", "naklon": 5 }, + "3942": { "label": "33/8", "naklon": 5 }, + "3829": { "label": "33/9", "naklon": null }, + "3452": { "label": "34/79A", "naklon": 6 }, + "3460": { "label": "34/79B", "naklon": 6 }, + "3443": { "label": "34/90A", "naklon": 6 }, + "3445": { "label": "34/90B", "naklon": 6 }, + "3457": { "label": "34/90C", "naklon": 6 }, + "3461": { "label": "34/97A", "naklon": 6 }, + "3463": { "label": "34/97B", "naklon": 6 }, + "3426": { "label": "34/98A", "naklon": 6 }, + "3444": { "label": "34/98B", "naklon": 6 }, + "3453": { "label": "34/99A", "naklon": 6 }, + "3455": { "label": "34/99B", "naklon": 6 }, + "4009": { "label": "34/1", "naklon": 0 }, + "3602": { "label": "34/2", "naklon": 0 }, + "3441": { "label": "34/3", "naklon": 0 }, + "3464": { "label": "34/4", "naklon": 0 }, + "3883": { "label": "34/5", "naklon": 0 }, + "4098": { "label": "34/6", "naklon": 0 }, + "4003": { "label": "34/7", "naklon": 0 }, + "4004": { "label": "34/8", "naklon": 0 }, + "3888": { "label": "34/9", "naklon": 0 }, + "3997": { "label": "34/10", "naklon": 0 }, + "4006": { "label": "34/11", "naklon": 0 }, + "4000": { "label": "34/12", "naklon": 0 }, + "4011": { "label": "34/13", "naklon": 0 }, + "3999": { "label": "34/14", "naklon": 0 }, + "3981": { "label": "34/15", "naklon": 0 }, + "3988": { "label": "34/16", "naklon": 0 }, + "3986": { "label": "34/17", "naklon": 0 }, + "3998": { "label": "34/18", "naklon": 0 }, + "3983": { "label": "34/19", "naklon": 0 }, + "4005": { "label": "34/20", "naklon": 0 }, + "4001": { "label": "34/21", "naklon": 0 }, + "4008": { "label": "34/22", "naklon": 0 }, + "4002": { "label": "34/23", "naklon": 0 }, + "3996": { "label": "34/24", "naklon": 0 }, + "4007": { "label": "34/25", "naklon": 0 }, + "4113": { "label": "34/26", "naklon": 15 }, + "3595": { "label": "34/27", "naklon": 5 }, + "3599": { "label": "34/28", "naklon": 5 }, + "3601": { "label": "34/29", "naklon": 5 }, + "4205": { "label": "34/30", "naklon": 0 }, + "3987": { "label": "34/31", "naklon": null }, + "4214": { "label": "34/32", "naklon": 0 }, + "4226": { "label": "34/33", "naklon": 0 }, + "4209": { "label": "34/34", "naklon": 0 }, + "4201": { "label": "34/35", "naklon": 0 }, + "3440": { "label": "34/36", "naklon": 0 }, + "3465": { "label": "34/37", "naklon": 0 }, + "3446": { "label": "34/38", "naklon": 0 }, + "4039": { "label": "34/39", "naklon": 5 }, + "4057": { "label": "34/40", "naklon": 5 }, + "3985": { "label": "34/41", "naklon": 0 }, + "3882": { "label": "34/42", "naklon": 0 }, + "4040": { "label": "34/43", "naklon": 5 }, + "3231": { "label": "34/44", "naklon": 0 }, + "3227": { "label": "34/45", "naklon": 0 }, + "3431": { "label": "34/46", "naklon": 0 }, + "4013": { "label": "34/47", "naklon": 0 }, + "4045": { "label": "34/48", "naklon": 0 }, + "3949": { "label": "34/49", "naklon": 0 }, + "3953": { "label": "34/50", "naklon": 0 }, + "3952": { "label": "34/51", "naklon": 0 }, + "3995": { "label": "34/52", "naklon": 0 }, + "3992": { "label": "34/53", "naklon": 0 }, + "4198": { "label": "34/54", "naklon": 0 }, + "3935": { "label": "34/55", "naklon": 0 }, + "4050": { "label": "34/56", "naklon": 0 }, + "4049": { "label": "34/57", "naklon": 0 }, + "4054": { "label": "34/58", "naklon": 0 }, + "3663": { "label": "34/59", "naklon": 6 }, + "3661": { "label": "34/60", "naklon": 6 }, + "3664": { "label": "34/61", "naklon": 6 }, + "3660": { "label": "34/62", "naklon": 6 }, + "3662": { "label": "34/63", "naklon": 6 }, + "3665": { "label": "34/65", "naklon": 6 }, + "3667": { "label": "34/66", "naklon": 6 }, + "3675": { "label": "34/67", "naklon": 6 }, + "3666": { "label": "34/68", "naklon": 6 }, + "3652": { "label": "34/69", "naklon": 6 }, + "3458": { "label": "34/70", "naklon": 6 }, + "4425": { "label": "34/70/1", "naklon": 6 }, + "3459": { "label": "34/71", "naklon": 6 }, + "3435": { "label": "34/72", "naklon": 6 }, + "3448": { "label": "34/73", "naklon": 6 }, + "3451": { "label": "34/74", "naklon": 6 }, + "3442": { "label": "34/75", "naklon": 6 }, + "3449": { "label": "34/76", "naklon": 6 }, + "3450": { "label": "34/77", "naklon": 6 }, + "3433": { "label": "34/78", "naklon": 6 }, + "3432": { "label": "34/80", "naklon": 12 }, + "3470": { "label": "34/81", "naklon": 12 }, + "3438": { "label": "34/82", "naklon": 12 }, + "3439": { "label": "34/83", "naklon": 12 }, + "4028": { "label": "34/84", "naklon": 5 }, + "3596": { "label": "34/85", "naklon": 5 }, + "4021": { "label": "34/86", "naklon": 5 }, + "3437": { "label": "34/87", "naklon": 12 }, + "3428": { "label": "34/88", "naklon": 12 }, + "3430": { "label": "34/89", "naklon": 12 }, + "3454": { "label": "34/91", "naklon": 6 }, + "3492": { "label": "34/92", "naklon": 6 }, + "3462": { "label": "34/93", "naklon": 6 }, + "3427": { "label": "34/94", "naklon": 6 }, + "3434": { "label": "34/95", "naklon": 6 }, + "3456": { "label": "34/96", "naklon": 6 }, + "4307": { "label": "34/98/1", "naklon": 6 }, + "3968": { "label": "35/1", "naklon": 0 }, + "3969": { "label": "35/2", "naklon": 0 }, + "3947": { "label": "35/3", "naklon": 0 }, + "3979": { "label": "35/4", "naklon": 0 }, + "3959": { "label": "35/5", "naklon": 0 }, + "3948": { "label": "35/6", "naklon": 0 }, + "3961": { "label": "35/7", "naklon": 0 }, + "3956": { "label": "35/8", "naklon": 0 }, + "3604": { "label": "35/9", "naklon": 0 }, + "3944": { "label": "35/10", "naklon": 0 }, + "3960": { "label": "35/11", "naklon": 0 }, + "3958": { "label": "35/12", "naklon": 0 }, + "4036": { "label": "35/13", "naklon": 5 }, + "3893": { "label": "35/18", "naklon": 5 }, + "4108": { "label": "35/19", "naklon": 5 }, + "4017": { "label": "35/20", "naklon": 5 }, + "3963": { "label": "35/21", "naklon": 0 }, + "3658": { "label": "35/22", "naklon": 0 }, + "3975": { "label": "35/23", "naklon": 0 }, + "3980": { "label": "35/24", "naklon": 0 }, + "4012": { "label": "35/25", "naklon": 0 }, + "3655": { "label": "35/26", "naklon": 0 }, + "3962": { "label": "35/27", "naklon": 0 }, + "3945": { "label": "35/28", "naklon": 0 }, + "3569": { "label": "35/29", "naklon": 0 }, + "3429": { "label": "35/30", "naklon": 0 }, + "3657": { "label": "35/31", "naklon": 0 }, + "3646": { "label": "35/32", "naklon": 0 }, + "3622": { "label": "35/33", "naklon": 0 }, + "3612": { "label": "35/34", "naklon": 0 }, + "3955": { "label": "35/35", "naklon": 0 }, + "3878": { "label": "35/37", "naklon": 0 }, + "3965": { "label": "35/38", "naklon": 0 }, + "3970": { "label": "35/39", "naklon": 0 }, + "3611": { "label": "35/40", "naklon": 0 }, + "2635": { "label": "35/41", "naklon": 0 }, + "3978": { "label": "35/42", "naklon": 0 }, + "4213": { "label": "35/43", "naklon": 0 }, + "3984": { "label": "35/44", "naklon": 0 }, + "4218": { "label": "35/45", "naklon": 0 }, + "3973": { "label": "35/46", "naklon": 0 }, + "3974": { "label": "35/47", "naklon": 0 }, + "3759": { "label": "35/48", "naklon": 0 }, + "3844": { "label": "35/49", "naklon": 0 }, + "3804": { "label": "35/50", "naklon": 0 }, + "3831": { "label": "35/51", "naklon": 0 }, + "3643": { "label": "35/52", "naklon": 0 }, + "3966": { "label": "35/53", "naklon": 0 }, + "3971": { "label": "35/54", "naklon": 0 }, + "3650": { "label": "35/55", "naklon": 6 }, + "3651": { "label": "35/56", "naklon": 6 }, + "3669": { "label": "35/57", "naklon": 6 }, + "3648": { "label": "35/58", "naklon": 6 }, + "3645": { "label": "35/59", "naklon": 6 }, + "3659": { "label": "35/60", "naklon": 6 }, + "3647": { "label": "35/61", "naklon": 6 }, + "3644": { "label": "35/62", "naklon": 6 }, + "3671": { "label": "35/63", "naklon": 6 }, + "3682": { "label": "35/64", "naklon": 6 }, + "3672": { "label": "35/65", "naklon": 6 }, + "3683": { "label": "35/66", "naklon": 6 }, + "3673": { "label": "35/67", "naklon": 6 }, + "3674": { "label": "35/68", "naklon": 6 }, + "3679": { "label": "35/69", "naklon": 6 }, + "3649": { "label": "35/70", "naklon": 6 }, + "3687": { "label": "35/71", "naklon": 6 }, + "3677": { "label": "35/72", "naklon": 6 }, + "3690": { "label": "35/73", "naklon": 6 }, + "3691": { "label": "35/74", "naklon": 6 }, + "3676": { "label": "35/75", "naklon": 6 }, + "3680": { "label": "35/76", "naklon": 6 }, + "3668": { "label": "35/77", "naklon": 6 }, + "3681": { "label": "35/78", "naklon": 6 }, + "3670": { "label": "35/79", "naklon": 6 }, + "3689": { "label": "35/80", "naklon": 6 }, + "3678": { "label": "35/81", "naklon": 6 }, + "3693": { "label": "35/82", "naklon": 6 }, + "3654": { "label": "35/83", "naklon": null }, + "4086": { "label": "36/1", "naklon": 0 }, + "4085": { "label": "36/2", "naklon": 0 }, + "4083": { "label": "36/3", "naklon": 0 }, + "4087": { "label": "36/4", "naklon": 0 }, + "4077": { "label": "36/5", "naklon": 0 }, + "4082": { "label": "36/6", "naklon": 0 }, + "4186": { "label": "36/7", "naklon": 0 }, + "4206": { "label": "36/8", "naklon": 0 }, + "4080": { "label": "36/9", "naklon": 0 }, + "4081": { "label": "36/10", "naklon": 0 }, + "4210": { "label": "36/11", "naklon": 0 }, + "4079": { "label": "36/12", "naklon": 0 }, + "4076": { "label": "36/13", "naklon": 0 }, + "3852": { "label": "36/14", "naklon": 0 }, + "2813": { "label": "36/15", "naklon": 0 }, + "4219": { "label": "36/16", "naklon": 0 }, + "3104": { "label": "37/1A", "naklon": 15 }, + "3121": { "label": "37/1B", "naklon": 15 }, + "3113": { "label": "37/2", "naklon": 10 }, + "3118": { "label": "37/3", "naklon": 10 }, + "3111": { "label": "37/4", "naklon": 10 }, + "4020": { "label": "37/5", "naklon": 10 }, + "3119": { "label": "37/6", "naklon": 10 }, + "3110": { "label": "37/7", "naklon": 10 }, + "3108": { "label": "37/8", "naklon": 10 }, + "3107": { "label": "37/12", "naklon": 0 }, + "3199": { "label": "37/13", "naklon": 0 }, + "3120": { "label": "37/14", "naklon": 0 }, + "3122": { "label": "37/15", "naklon": 0 }, + "3908": { "label": "37/16", "naklon": 0 }, + "3114": { "label": "37/17", "naklon": 0 }, + "3105": { "label": "37/18", "naklon": 0 }, + "3116": { "label": "37/19", "naklon": 0 }, + "3106": { "label": "37/20", "naklon": 0 }, + "2887": { "label": "37/21", "naklon": 5 }, + "2888": { "label": "37/22", "naklon": 5 }, + "2877": { "label": "37/23", "naklon": 5 }, + "2891": { "label": "37/24", "naklon": 5 }, + "2886": { "label": "37/25", "naklon": 5 }, + "2892": { "label": "37/26", "naklon": 5 }, + "2882": { "label": "37/27", "naklon": 5 }, + "2883": { "label": "37/28", "naklon": 5 }, + "2876": { "label": "37/29", "naklon": 5 }, + "3109": { "label": "37/30", "naklon": 5 }, + "4152": { "label": "37/31", "naklon": 5 }, + "3117": { "label": "37/32", "naklon": 5 }, + "2870": { "label": "37/33", "naklon": 5 }, + "2867": { "label": "37/34", "naklon": 0 }, + "2865": { "label": "37/35", "naklon": 0 }, + "3096": { "label": "37/36", "naklon": 0 }, + "2871": { "label": "37/37", "naklon": 0 }, + "2884": { "label": "37/38", "naklon": 0 }, + "2855": { "label": "37/39", "naklon": 0 }, + "2878": { "label": "37/40", "naklon": 0 }, + "2889": { "label": "37/41", "naklon": 0 }, + "2879": { "label": "37/42", "naklon": 0 }, + "2850": { "label": "37/43", "naklon": 0 }, + "2894": { "label": "37/44", "naklon": 0 }, + "2880": { "label": "37/45", "naklon": 0 }, + "2893": { "label": "37/46", "naklon": 0 }, + "2890": { "label": "37/47", "naklon": 0 }, + "4355": { "label": "37/48", "naklon": 0 }, + "2885": { "label": "37/49", "naklon": 0 }, + "2875": { "label": "37/50", "naklon": 0 }, + "3486": { "label": "38/30A", "naklon": 5 }, + "3714": { "label": "38/30B", "naklon": 0 }, + "3483": { "label": "38/32A", "naklon": 5 }, + "3496": { "label": "38/32B", "naklon": 0 }, + "3487": { "label": "38/35A", "naklon": 5 }, + "3498": { "label": "38/35B", "naklon": 5 }, + "3578": { "label": "38/38A", "naklon": 5 }, + "3508": { "label": "38/38B", "naklon": 5 }, + "3787": { "label": "38/59A", "naklon": 5 }, + "3491": { "label": "38/59B", "naklon": 5 }, + "3568": { "label": "38/1", "naklon": null }, + "3502": { "label": "38/2", "naklon": 0 }, + "3836": { "label": "38/3", "naklon": 0 }, + "3588": { "label": "38/4", "naklon": 0 }, + "3493": { "label": "38/5", "naklon": 0 }, + "3580": { "label": "38/6", "naklon": 0 }, + "3572": { "label": "38/7", "naklon": 0 }, + "3506": { "label": "38/8", "naklon": 0 }, + "3503": { "label": "38/9", "naklon": 0 }, + "3579": { "label": "38/10", "naklon": 0 }, + "3586": { "label": "38/11", "naklon": 0 }, + "3495": { "label": "38/12", "naklon": 5 }, + "3492": { "label": "38/13", "naklon": 5 }, + "3532": { "label": "38/14", "naklon": 5 }, + "3574": { "label": "38/15", "naklon": 5 }, + "4140": { "label": "38/16", "naklon": 5 }, + "3795": { "label": "38/17", "naklon": 5 }, + "3788": { "label": "38/18", "naklon": 5 }, + "3796": { "label": "38/19", "naklon": 5 }, + "3797": { "label": "38/20", "naklon": 5 }, + "3798": { "label": "38/21", "naklon": 5 }, + "3786": { "label": "38/22", "naklon": 5 }, + "4067": { "label": "38/23", "naklon": 5 }, + "3773": { "label": "38/24", "naklon": 5 }, + "3774": { "label": "38/25", "naklon": 5 }, + "3789": { "label": "38/26", "naklon": 5 }, + "3520": { "label": "38/27", "naklon": null }, + "3577": { "label": "38/29", "naklon": 5 }, + "3530": { "label": "38/31", "naklon": null }, + "3488": { "label": "38/33", "naklon": 5 }, + "3505": { "label": "38/34", "naklon": 5 }, + "3497": { "label": "38/36", "naklon": 5 }, + "3490": { "label": "38/37", "naklon": 5 }, + "3585": { "label": "38/39", "naklon": 5 }, + "3582": { "label": "38/40", "naklon": 5 }, + "3507": { "label": "38/41", "naklon": 5 }, + "3484": { "label": "38/42", "naklon": 5 }, + "3501": { "label": "38/43", "naklon": 5 }, + "3581": { "label": "38/44", "naklon": 5 }, + "4192": { "label": "38/45", "naklon": 5 }, + "3576": { "label": "38/46", "naklon": 5 }, + "3489": { "label": "38/47", "naklon": 5 }, + "3573": { "label": "38/48", "naklon": 5 }, + "3504": { "label": "38/49", "naklon": 5 }, + "3794": { "label": "38/50", "naklon": 5 }, + "3485": { "label": "38/51", "naklon": 5 }, + "3482": { "label": "38/52", "naklon": 5 }, + "3575": { "label": "38/53", "naklon": 5 }, + "3499": { "label": "38/54", "naklon": 5 }, + "3494": { "label": "38/55", "naklon": 5 }, + "3583": { "label": "38/56", "naklon": 5 }, + "3570": { "label": "38/57", "naklon": 5 }, + "3500": { "label": "38/58", "naklon": 0 }, + "3510": { "label": "38/63", "naklon": null }, + "3512": { "label": "38/64", "naklon": null }, + "3535": { "label": "38/67", "naklon": null }, + "3531": { "label": "38/68", "naklon": null }, + "3537": { "label": "38/69", "naklon": null }, + "3522": { "label": "39/1", "naklon": 10 }, + "4018": { "label": "39/2", "naklon": 10 }, + "4019": { "label": "39/3", "naklon": 10 }, + "4154": { "label": "39/4", "naklon": 5 }, + "3907": { "label": "39/5", "naklon": 5 }, + "4148": { "label": "39/6", "naklon": 0 }, + "4153": { "label": "39/7", "naklon": 0 }, + "3938": { "label": "39/8", "naklon": 0 }, + "3802": { "label": "39/9", "naklon": 0 }, + "4015": { "label": "39/10", "naklon": 0 }, + "3929": { "label": "39/11", "naklon": 0 }, + "3946": { "label": "39/12", "naklon": 0 }, + "4014": { "label": "39/13", "naklon": 0 }, + "4155": { "label": "39/14", "naklon": 0 }, + "4149": { "label": "39/15", "naklon": 0 }, + "3642": { "label": "39/16", "naklon": 0 }, + "3636": { "label": "39/17", "naklon": 5 }, + "3991": { "label": "39/18", "naklon": 0 }, + "3994": { "label": "39/19", "naklon": 0 }, + "3990": { "label": "39/20", "naklon": 0 }, + "3967": { "label": "39/21", "naklon": 0 }, + "3977": { "label": "39/22", "naklon": 0 }, + "3757": { "label": "39/23", "naklon": 15 }, + "3633": { "label": "39/24", "naklon": 15 }, + "3744": { "label": "39/25", "naklon": 15 }, + "4023": { "label": "39/26", "naklon": 5 }, + "3720": { "label": "39/27", "naklon": 5 }, + "3734": { "label": "39/28", "naklon": 5 }, + "3741": { "label": "39/29", "naklon": 5 }, + "3721": { "label": "39/30", "naklon": 5 }, + "3845": { "label": "39/31", "naklon": 0 }, + "3840": { "label": "39/32", "naklon": 0 }, + "3837": { "label": "39/33", "naklon": null }, + "3839": { "label": "39/34", "naklon": 0 }, + "3542": { "label": "41/1", "naklon": null }, + "3566": { "label": "41/2", "naklon": null }, + "3548": { "label": "41/3", "naklon": null }, + "3515": { "label": "41/4", "naklon": null }, + "3559": { "label": "41/5", "naklon": null }, + "3509": { "label": "41/6", "naklon": null }, + "3524": { "label": "41/7", "naklon": null }, + "3518": { "label": "41/8", "naklon": null }, + "3182": { "label": "41/9", "naklon": null }, + "3187": { "label": "41/10", "naklon": null }, + "3195": { "label": "41/11", "naklon": 0 }, + "3857": { "label": "41/12", "naklon": 0 }, + "3183": { "label": "41/13", "naklon": 0 }, + "3177": { "label": "41/14", "naklon": 0 }, + "3189": { "label": "41/15", "naklon": 0 }, + "3186": { "label": "41/16", "naklon": 0 }, + "3178": { "label": "42/1", "naklon": 0 }, + "3219": { "label": "42/2", "naklon": 0 }, + "3475": { "label": "42/3", "naklon": 0 }, + "3175": { "label": "42/4", "naklon": 0 }, + "3222": { "label": "42/5", "naklon": 0 }, + "3221": { "label": "42/6", "naklon": 0 }, + "3181": { "label": "42/7", "naklon": 0 }, + "3180": { "label": "42/8", "naklon": 0 }, + "3218": { "label": "42/9", "naklon": 0 }, + "3176": { "label": "42/10", "naklon": 0 }, + "3174": { "label": "42/11", "naklon": 0 }, + "3220": { "label": "42/12", "naklon": 0 }, + "3533": { "label": "42/13", "naklon": null }, + "3543": { "label": "42/14", "naklon": null }, + "3554": { "label": "42/15", "naklon": null }, + "3549": { "label": "42/16", "naklon": null }, + "2857": { "label": "43/1", "naklon": 5 }, + "2752": { "label": "43/2", "naklon": 5 }, + "2753": { "label": "43/3", "naklon": 5 }, + "3024": { "label": "43/4", "naklon": 5 }, + "2754": { "label": "43/5", "naklon": 5 }, + "4423": { "label": "43/6", "naklon": 5 }, + "4368": { "label": "43/7", "naklon": 5 }, + "2978": { "label": "43/8", "naklon": 5 }, + "2868": { "label": "43/9", "naklon": 5 }, + "4377": { "label": "43/10", "naklon": 5 }, + "2757": { "label": "43/11", "naklon": 5 }, + "2970": { "label": "43/12", "naklon": 5 }, + "2758": { "label": "43/13", "naklon": 5 }, + "4378": { "label": "43/14", "naklon": 5 }, + "2759": { "label": "43/15", "naklon": 5 }, + "4342": { "label": "43/16", "naklon": 5 }, + "3026": { "label": "43/17", "naklon": null }, + "2986": { "label": "43/18", "naklon": null }, + "4343": { "label": "43/19", "naklon": null }, + "2760": { "label": "43/20", "naklon": null }, + "4379": { "label": "43/21", "naklon": null }, + "2971": { "label": "43/22", "naklon": null }, + "2761": { "label": "43/23", "naklon": null }, + "2762": { "label": "43/24", "naklon": null }, + "4339": { "label": "43/25", "naklon": null }, + "4380": { "label": "43/26", "naklon": null }, + "2975": { "label": "43/27", "naklon": null }, + "3003": { "label": "43/28", "naklon": null }, + "4338": { "label": "43/29", "naklon": null }, + "3002": { "label": "43/30", "naklon": null }, + "4345": { "label": "43/31", "naklon": null }, + "2979": { "label": "43/32", "naklon": null }, + "2989": { "label": "43/33", "naklon": null }, + "2996": { "label": "43/34", "naklon": null }, + "2972": { "label": "43/35", "naklon": null }, + "2988": { "label": "43/36", "naklon": null }, + "4344": { "label": "43/37", "naklon": null }, + "3022": { "label": "43/38", "naklon": null }, + "4341": { "label": "43/39", "naklon": null }, + "2983": { "label": "43/40", "naklon": null }, + "2995": { "label": "43/41", "naklon": null }, + "2763": { "label": "43/42", "naklon": null }, + "2764": { "label": "43/43", "naklon": null }, + "2765": { "label": "43/44", "naklon": null }, + "2766": { "label": "43/45", "naklon": null }, + "2767": { "label": "43/46", "naklon": null }, + "2768": { "label": "43/47", "naklon": null }, + "3018": { "label": "43/48", "naklon": null }, + "2982": { "label": "43/49", "naklon": null }, + "3019": { "label": "43/50", "naklon": 0 }, + "3013": { "label": "43/51", "naklon": null }, + "3007": { "label": "43/52", "naklon": null }, + "2980": { "label": "43/53", "naklon": null }, + "3011": { "label": "43/54", "naklon": null }, + "2672": { "label": "43/55", "naklon": null }, + "2673": { "label": "43/56", "naklon": null }, + "2674": { "label": "43/57", "naklon": null }, + "2675": { "label": "43/58", "naklon": null }, + "2676": { "label": "43/59", "naklon": null }, + "2677": { "label": "43/60", "naklon": null }, + "2678": { "label": "43/61", "naklon": null }, + "2679": { "label": "43/62", "naklon": null }, + "2680": { "label": "43/63", "naklon": null }, + "2840": { "label": "43/64", "naklon": null }, + "2682": { "label": "43/65", "naklon": null }, + "2683": { "label": "43/66", "naklon": null }, + "2684": { "label": "43/67", "naklon": 0 }, + "2685": { "label": "43/68", "naklon": null }, + "2686": { "label": "43/69", "naklon": null }, + "2687": { "label": "43/70", "naklon": null }, + "2688": { "label": "43/71", "naklon": null }, + "2689": { "label": "43/72", "naklon": null }, + "2690": { "label": "43/73", "naklon": null }, + "2691": { "label": "43/74", "naklon": null }, + "2692": { "label": "43/75", "naklon": null }, + "2693": { "label": "43/76", "naklon": 0 }, + "2694": { "label": "43/77", "naklon": null }, + "2695": { "label": "43/78", "naklon": null }, + "2696": { "label": "43/79", "naklon": 0 }, + "2697": { "label": "43/80", "naklon": null }, + "2698": { "label": "43/81", "naklon": 0 }, + "2699": { "label": "43/82", "naklon": null }, + "2700": { "label": "43/83", "naklon": 0 }, + "2744": { "label": "43/84", "naklon": null }, + "2745": { "label": "43/85", "naklon": 0 }, + "2746": { "label": "43/86", "naklon": null }, + "2747": { "label": "43/87", "naklon": 0 }, + "2748": { "label": "43/88", "naklon": null }, + "2749": { "label": "43/89", "naklon": 0 }, + "2841": { "label": "43/90", "naklon": null }, + "4237": { "label": "45/1", "naklon": 5 }, + "4226": { "label": "45/2", "naklon": 5 }, + "4242": { "label": "45/3", "naklon": 5 }, + "4179": { "label": "45/4", "naklon": 5 }, + "4247": { "label": "45/5", "naklon": 5 }, + "4245": { "label": "45/6", "naklon": 5 }, + "3872": { "label": "45/7", "naklon": 5 }, + "4175": { "label": "45/8", "naklon": 5 }, + "4236": { "label": "45/9", "naklon": 5 }, + "4170": { "label": "45/10", "naklon": 5 }, + "4238": { "label": "45/11", "naklon": 5 }, + "4246": { "label": "45/12", "naklon": 5 }, + "4166": { "label": "45/13", "naklon": 5 }, + "4227": { "label": "45/14", "naklon": 5 }, + "4171": { "label": "45/15", "naklon": 5 }, + "4180": { "label": "45/16", "naklon": 5 }, + "4244": { "label": "45/17", "naklon": 5 }, + "4199": { "label": "45/18", "naklon": 5 }, + "4239": { "label": "45/19", "naklon": 5 }, + "4207": { "label": "45/20", "naklon": 5 }, + "4223": { "label": "45/21", "naklon": 5 }, + "4230": { "label": "45/22", "naklon": 5 }, + "4233": { "label": "45/23", "naklon": 5 }, + "4222": { "label": "45/24", "naklon": 5 }, + "4217": { "label": "45/25", "naklon": 5 }, + "4243": { "label": "45/26", "naklon": 5 }, + "4200": { "label": "45/27", "naklon": 5 }, + "4228": { "label": "45/28", "naklon": 5 }, + "4211": { "label": "45/29", "naklon": 5 }, + "4234": { "label": "45/30", "naklon": 5 }, + "4235": { "label": "45/31", "naklon": 5 }, + "4203": { "label": "45/32", "naklon": 5 }, + "4240": { "label": "45/33", "naklon": 5 }, + "4224": { "label": "45/34", "naklon": 5 }, + "4232": { "label": "45/35", "naklon": 5 }, + "4231": { "label": "45/36", "naklon": 5 }, + "4161": { "label": "45/37", "naklon": 5 }, + "4225": { "label": "45/38", "naklon": 5 }, + "4241": { "label": "45/39", "naklon": 5 }, + "4229": { "label": "45/40", "naklon": 5 }, + "4221": { "label": "45/41", "naklon": 5 }, + "4212": { "label": "45/42", "naklon": 5 }, + "4216": { "label": "45/43", "naklon": 5 }, + "3864": { "label": "45/44", "naklon": null }, + "3806": { "label": "46/1", "naklon": 5 }, + "3813": { "label": "46/2", "naklon": 5 }, + "3815": { "label": "46/3", "naklon": 5 }, + "3807": { "label": "46/4", "naklon": 5 }, + "3895": { "label": "46/5", "naklon": 5 }, + "3809": { "label": "46/6", "naklon": 5 }, + "3820": { "label": "46/7", "naklon": 5 }, + "3805": { "label": "46/8", "naklon": 5 }, + "3894": { "label": "46/9", "naklon": 0 }, + "4055": { "label": "46/10", "naklon": 0 }, + "3812": { "label": "46/11", "naklon": 5 }, + "3822": { "label": "46/12", "naklon": 5 }, + "3821": { "label": "46/13", "naklon": 5 }, + "3808": { "label": "46/14", "naklon": 5 }, + "3799": { "label": "46/15", "naklon": 5 }, + "3816": { "label": "46/16", "naklon": 5 }, + "3751": { "label": "46/17", "naklon": 5 }, + "3814": { "label": "46/18", "naklon": 5 }, + "4044": { "label": "46/19", "naklon": 0 }, + "3931": { "label": "46/20", "naklon": 0 }, + "3902": { "label": "46/21", "naklon": 5 }, + "3916": { "label": "46/22", "naklon": 5 }, + "3892": { "label": "46/23", "naklon": 5 }, + "3914": { "label": "46/24", "naklon": 5 }, + "3898": { "label": "46/25", "naklon": 5 }, + "3897": { "label": "46/26", "naklon": 5 }, + "3885": { "label": "46/27", "naklon": 5 }, + "3906": { "label": "46/28", "naklon": 5 }, + "3930": { "label": "46/29", "naklon": 0 }, + "3936": { "label": "46/30", "naklon": 0 }, + "3860": { "label": "46/31", "naklon": 5 }, + "3841": { "label": "46/32", "naklon": 5 }, + "3873": { "label": "46/33", "naklon": 5 }, + "3854": { "label": "46/34", "naklon": 5 }, + "3939": { "label": "46/35", "naklon": 5 }, + "3858": { "label": "46/36", "naklon": 5 }, + "3940": { "label": "46/37", "naklon": 5 }, + "4035": { "label": "46/38", "naklon": 5 }, + "3373": { "label": "47/1", "naklon": 0 }, + "3374": { "label": "47/2", "naklon": 0 }, + "3384": { "label": "47/3", "naklon": 0 }, + "3385": { "label": "47/4", "naklon": 0 }, + "4051": { "label": "48/1", "naklon": 5 }, + "4041": { "label": "48/2", "naklon": 5 }, + "4056": { "label": "48/3", "naklon": 5 }, + "3875": { "label": "48/4", "naklon": 5 }, + "4061": { "label": "48/5", "naklon": 5 }, + "4047": { "label": "48/6", "naklon": 5 }, + "4060": { "label": "48/7", "naklon": 5 }, + "4059": { "label": "48/8", "naklon": 5 }, + "4058": { "label": "48/9", "naklon": 5 }, + "3635": { "label": "48/10", "naklon": 5 }, + "3640": { "label": "48/11", "naklon": 5 }, + "3747": { "label": "48/12", "naklon": 5 }, + "3629": { "label": "48/13", "naklon": 5 }, + "4048": { "label": "48/14", "naklon": 5 }, + "4063": { "label": "48/15", "naklon": 5 }, + "4062": { "label": "48/16", "naklon": 5 }, + "4043": { "label": "48/17", "naklon": 5 }, + "4052": { "label": "48/18", "naklon": 5 }, + "4042": { "label": "48/19", "naklon": 5 }, + "4053": { "label": "48/20", "naklon": 5 }, + "4167": { "label": "50/15A", "naklon": null }, + "4159": { "label": "50/15B", "naklon": null }, + "4183": { "label": "50/1", "naklon": 0 }, + "4157": { "label": "50/2", "naklon": 0 }, + "4160": { "label": "50/3", "naklon": 0 }, + "4173": { "label": "50/4", "naklon": 0 }, + "4177": { "label": "50/5", "naklon": 0 }, + "4174": { "label": "50/6", "naklon": 0 }, + "4178": { "label": "50/7", "naklon": 0 }, + "4195": { "label": "50/8", "naklon": 0 }, + "4169": { "label": "50/9", "naklon": 0 }, + "4162": { "label": "50/10", "naklon": 0 }, + "4158": { "label": "50/11", "naklon": 0 }, + "4182": { "label": "50/12", "naklon": 0 }, + "4194": { "label": "50/13", "naklon": 0 }, + "4184": { "label": "50/14", "naklon": 0 }, + "4197": { "label": "50/16", "naklon": null }, + "4164": { "label": "50/17", "naklon": null }, + "3306": { "label": "50/18", "naklon": null }, + "4168": { "label": "50/19", "naklon": null }, + "4193": { "label": "50/20", "naklon": null }, + "4187": { "label": "50/21", "naklon": null }, + "4163": { "label": "50/22", "naklon": null }, + "4165": { "label": "50/23", "naklon": null }, + "4185": { "label": "50/24", "naklon": null }, + "3904": { "label": "50/25", "naklon": null }, + "2619": { "label": "53/1", "naklon": 0 }, + "2623": { "label": "53/2", "naklon": 0 }, + "2617": { "label": "53/3", "naklon": 0 }, + "2622": { "label": "53/4", "naklon": 0 }, + "2618": { "label": "53/5", "naklon": 0 }, + "2626": { "label": "53/6", "naklon": 0 }, + "2869": { "label": "53/7", "naklon": 0 }, + "2613": { "label": "53/8", "naklon": 0 }, + "2608": { "label": "53/9", "naklon": 0 }, + "2611": { "label": "53/10", "naklon": 0 }, + "2598": { "label": "53/11", "naklon": 0 }, + "3528": { "label": "53/12", "naklon": 0 }, + "3545": { "label": "53/13", "naklon": 0 }, + "2620": { "label": "53/14", "naklon": 0 }, + "2612": { "label": "53/15", "naklon": 0 }, + "2615": { "label": "53/16", "naklon": 0 }, + "3722": { "label": "53/17", "naklon": 0 }, + "2624": { "label": "53/18", "naklon": 0 }, + "2609": { "label": "53/19", "naklon": 0 }, + "2625": { "label": "53/20", "naklon": 0 }, + "2602": { "label": "53/21", "naklon": 0 }, + "2610": { "label": "53/22", "naklon": 0 }, + "2599": { "label": "53/23", "naklon": 0 }, + "2605": { "label": "53/24", "naklon": 0 }, + "2593": { "label": "53/25", "naklon": 0 }, + "3074": { "label": "53/26", "naklon": 0 }, + "2740": { "label": "53/27", "naklon": 0 }, + "2614": { "label": "53/28", "naklon": 0 }, + "2601": { "label": "53/29", "naklon": 0 }, + "4196": { "label": "53/30", "naklon": 0 }, + "2607": { "label": "53/31", "naklon": 0 }, + "2582": { "label": "53/32", "naklon": 0 }, + "2594": { "label": "53/33", "naklon": 0 }, + "2589": { "label": "53/34", "naklon": 0 }, + "2596": { "label": "53/35", "naklon": 0 }, + "2603": { "label": "53/36", "naklon": 0 }, + "2597": { "label": "53/37", "naklon": 0 }, + "2590": { "label": "53/38", "naklon": 0 }, + "2581": { "label": "53/39", "naklon": 0 }, + "2583": { "label": "53/40", "naklon": 0 }, + "2580": { "label": "53/41", "naklon": 0 }, + "2579": { "label": "53/42", "naklon": 0 }, + "2797": { "label": "53/43", "naklon": 0 }, + "2577": { "label": "53/44", "naklon": 0 }, + "2586": { "label": "53/45", "naklon": 0 }, + "2588": { "label": "53/46", "naklon": 0 }, + "2591": { "label": "53/47", "naklon": 0 }, + "2592": { "label": "53/48", "naklon": 0 }, + "2573": { "label": "53/49", "naklon": 0 }, + "2595": { "label": "53/50", "naklon": 0 }, + "2587": { "label": "53/51", "naklon": 0 }, + "2578": { "label": "53/52", "naklon": 0 }, + "2574": { "label": "53/53", "naklon": 0 }, + "2571": { "label": "53/54", "naklon": 0 }, + "2570": { "label": "53/55", "naklon": 0 }, + "2576": { "label": "53/56", "naklon": 0 }, + "2881": { "label": "53/57", "naklon": 0 }, + "2575": { "label": "53/58", "naklon": 0 }, + "2572": { "label": "53/59", "naklon": 0 }, + "2569": { "label": "53/60", "naklon": 0 }, + "4324": { "label": "55/1", "naklon": 0 }, + "4319": { "label": "55/2", "naklon": 0 }, + "4327": { "label": "55/3", "naklon": 0 }, + "4333": { "label": "55/4", "naklon": 0 }, + "4332": { "label": "55/5", "naklon": 0 }, + "4320": { "label": "55/6", "naklon": 0 }, + "4317": { "label": "55/7", "naklon": 0 }, + "4318": { "label": "55/8", "naklon": 0 }, + "4328": { "label": "55/9", "naklon": 0 }, + "4323": { "label": "55/10", "naklon": 0 }, + "4325": { "label": "55/11", "naklon": 0 }, + "4326": { "label": "55/12", "naklon": 0 }, + "4316": { "label": "55/13", "naklon": 0 }, + "4322": { "label": "55/14", "naklon": 0 }, + "4331": { "label": "55/15", "naklon": 0 }, + "4321": { "label": "55/16", "naklon": 0 }, + "4315": { "label": "55/17", "naklon": 0 }, + "4329": { "label": "55/18", "naklon": 0 }, + "4334": { "label": "55/19", "naklon": 0 }, + "4330": { "label": "55/20", "naklon": 0 } +}; + + +let svetlaSorted = [{ "label": "1/3A", "node": 3993, "naklon": 0 }, +{ "label": "1/3B", "node": 3989, "naklon": 15 }, +{ "label": "1/1", "node": 3976, "naklon": 0 }, +{ "label": "1/2", "node": 4181, "naklon": 0 }, +{ "label": "1/4", "node": 4376, "naklon": 15 }, +{ "label": "1/5", "node": 3868, "naklon": 15 }, +{ "label": "1/6", "node": 3728, "naklon": 15 }, +{ "label": "1/7", "node": 3730, "naklon": 0 }, +{ "label": "1/8", "node": 4374, "naklon": 0 }, +{ "label": "1/9", "node": 3718, "naklon": 15 }, +{ "label": "1/10", "node": 4375, "naklon": 15 }, +{ "label": "1/11", "node": 4172, "naklon": 15 }, +{ "label": "1/12", "node": 4176, "naklon": 15 }, +{ "label": "2/1", "node": 3800, "naklon": 5 }, +{ "label": "2/2", "node": 3823, "naklon": 5 }, +{ "label": "2/3", "node": 3905, "naklon": 5 }, +{ "label": "2/4", "node": 3803, "naklon": 5 }, +{ "label": "2/5", "node": 3817, "naklon": 5 }, +{ "label": "2/6", "node": 3818, "naklon": 5 }, +{ "label": "2/7", "node": 3811, "naklon": 5 }, +{ "label": "2/8", "node": 3915, "naklon": 5 }, +{ "label": "2/9", "node": 3843, "naklon": 10 }, +{ "label": "2/10", "node": 3827, "naklon": 10 }, +{ "label": "2/11", "node": 4220, "naklon": 10 }, +{ "label": "2/12", "node": 3826, "naklon": 10 }, +{ "label": "2/13", "node": 3834, "naklon": 10 }, +{ "label": "2/14", "node": 3838, "naklon": 10 }, +{ "label": "2/15", "node": 2823, "naklon": 10 }, +{ "label": "2/16", "node": 3750, "naklon": 10 }, +{ "label": "2/17", "node": 3378, "naklon": 0 }, +{ "label": "2/18", "node": 3376, "naklon": 0 }, +{ "label": "2/19", "node": 3379, "naklon": 0 }, +{ "label": "2/20", "node": 3285, "naklon": 0 }, +{ "label": "2/21", "node": 3382, "naklon": 0 }, +{ "label": "2/22", "node": 3383, "naklon": 0 }, +{ "label": "2/24", "node": 3375, "naklon": 0 }, +{ "label": "2/25", "node": 3381, "naklon": 0 }, +{ "label": "2/26", "node": 3380, "naklon": 0 }, +{ "label": "2/27", "node": 3828, "naklon": 10 }, +{ "label": "2/28", "node": 3377, "naklon": 0 }, +{ "label": "7/1", "node": 3591, "naklon": 0 }, +{ "label": "7/2", "node": 3587, "naklon": 0 }, +{ "label": "7/3", "node": 3468, "naklon": 0 }, +{ "label": "7/4", "node": 3466, "naklon": 0 }, +{ "label": "7/5", "node": 3474, "naklon": 0 }, +{ "label": "7/6", "node": 3481, "naklon": 0 }, +{ "label": "7/7", "node": 3589, "naklon": 0 }, +{ "label": "7/8", "node": 3472, "naklon": 0 }, +{ "label": "7/9", "node": 3473, "naklon": 0 }, +{ "label": "7/10", "node": 3584, "naklon": 0 }, +{ "label": "7/11", "node": 3571, "naklon": 0 }, +{ "label": "7/12", "node": 3476, "naklon": 0 }, +{ "label": "7/13", "node": 3590, "naklon": 0 }, +{ "label": "7/14", "node": 3478, "naklon": 0 }, +{ "label": "7/15", "node": 3471, "naklon": 0 }, +{ "label": "7/16", "node": 3467, "naklon": 0 }, +{ "label": "7/17", "node": 3479, "naklon": 0 }, +{ "label": "7/18", "node": 3480, "naklon": 0 }, +{ "label": "7/19", "node": 3477, "naklon": 0 }, +{ "label": "12/1", "node": 3362, "naklon": 0 }, +{ "label": "12/2", "node": 3355, "naklon": 0 }, +{ "label": "12/3", "node": 3356, "naklon": 0 }, +{ "label": "12/4", "node": 3349, "naklon": 0 }, +{ "label": "12/5", "node": 3357, "naklon": 0 }, +{ "label": "12/6", "node": 3350, "naklon": 0 }, +{ "label": "12/7", "node": 3353, "naklon": 0 }, +{ "label": "12/8", "node": 3539, "naklon": 0 }, +{ "label": "12/9", "node": 3050, "naklon": 0 }, +{ "label": "12/10", "node": 3361, "naklon": 0 }, +{ "label": "12/11", "node": 3360, "naklon": 0 }, +{ "label": "12/12", "node": 3358, "naklon": 0 }, +{ "label": "12/13", "node": 3541, "naklon": 0 }, +{ "label": "12/14", "node": 3551, "naklon": 0 }, +{ "label": "12/15", "node": 3514, "naklon": 0 }, +{ "label": "12/16", "node": 3547, "naklon": 0 }, +{ "label": "12/17", "node": 3562, "naklon": 0 }, +{ "label": "12/18", "node": 3525, "naklon": 0 }, +{ "label": "12/19", "node": 3558, "naklon": 0 }, +{ "label": "12/20", "node": 3511, "naklon": 0 }, +{ "label": "12/21", "node": 3058, "naklon": 0 }, +{ "label": "12/22", "node": 3062, "naklon": 0 }, +{ "label": "12/23", "node": 3070, "naklon": 0 }, +{ "label": "12/24", "node": 3447, "naklon": 0 }, +{ "label": "12/25", "node": 3056, "naklon": 0 }, +{ "label": "12/26", "node": 3057, "naklon": 0 }, +{ "label": "12/27", "node": 3071, "naklon": 0 }, +{ "label": "12/28", "node": 3061, "naklon": 0 }, +{ "label": "12/29", "node": 3069, "naklon": 0 }, +{ "label": "12/30", "node": 3077, "naklon": 0 }, +{ "label": "12/31", "node": 3080, "naklon": 0 }, +{ "label": "12/32", "node": 3081, "naklon": 0 }, +{ "label": "12/33", "node": 3078, "naklon": 0 }, +{ "label": "12/34", "node": 4037, "naklon": 0 }, +{ "label": "12/35", "node": 3067, "naklon": 0 }, +{ "label": "12/36", "node": 3051, "naklon": 0 }, +{ "label": "12/37", "node": 2924, "naklon": 0 }, +{ "label": "12/38", "node": 3060, "naklon": 0 }, +{ "label": "12/39", "node": 3073, "naklon": 0 }, +{ "label": "12/40", "node": 3469, "naklon": 0 }, +{ "label": "12/41", "node": 2923, "naklon": 0 }, +{ "label": "12/42", "node": 2925, "naklon": 0 }, +{ "label": "12/43", "node": 3359, "naklon": 0 }, +{ "label": "12/44", "node": 3055, "naklon": 0 }, +{ "label": "12/45", "node": 2922, "naklon": 0 }, +{ "label": "12/46", "node": 3084, "naklon": 0 }, +{ "label": "12/47", "node": 3064, "naklon": 0 }, +{ "label": "12/48", "node": 3066, "naklon": 0 }, +{ "label": "12/49", "node": 3072, "naklon": 0 }, +{ "label": "13/13A", "node": 3415, "naklon": 0 }, +{ "label": "13/13B", "node": 3409, "naklon": 0 }, +{ "label": "13/13C", "node": 3399, "naklon": 0 }, +{ "label": "13/29A", "node": 3410, "naklon": 0 }, +{ "label": "13/29B", "node": 3407, "naklon": 0 }, +{ "label": "13/34A", "node": 3405, "naklon": 0 }, +{ "label": "13/34B", "node": 3404, "naklon": 0 }, +{ "label": "13/45A", "node": 3392, "naklon": 0 }, +{ "label": "13/45B", "node": 3386, "naklon": 0 }, +{ "label": "13/60A", "node": 3303, "naklon": 3 }, +{ "label": "13/60B", "node": 3302, "naklon": 3 }, +{ "label": "13/70A", "node": 3319, "naklon": 6 }, +{ "label": "13/70B", "node": 3317, "naklon": 6 }, +{ "label": "13/70C", "node": 3326, "naklon": 6 }, +{ "label": "13/73A", "node": 3351, "naklon": 6 }, +{ "label": "13/73B", "node": 3313, "naklon": 6 }, +{ "label": "13/83A", "node": 3316, "naklon": 0 }, +{ "label": "13/83B", "node": 3320, "naklon": 0 }, +{ "label": "13/95A", "node": 3336, "naklon": 0 }, +{ "label": "13/95B", "node": 3323, "naklon": 0 }, +{ "label": "13/98A", "node": 3339, "naklon": 0 }, +{ "label": "13/98B", "node": 3333, "naklon": 0 }, +{ "label": "13/1", "node": 3425, "naklon": 0 }, +{ "label": "13/2", "node": 3419, "naklon": 0 }, +{ "label": "13/3", "node": 3416, "naklon": 0 }, +{ "label": "13/4", "node": 3332, "naklon": 0 }, +{ "label": "13/5", "node": 3422, "naklon": 0 }, +{ "label": "13/6", "node": 3417, "naklon": 0 }, +{ "label": "13/7", "node": 3418, "naklon": 0 }, +{ "label": "13/8", "node": 3424, "naklon": 0 }, +{ "label": "13/9", "node": 3334, "naklon": 0 }, +{ "label": "13/10", "node": 4363, "naklon": 0 }, +{ "label": "13/11", "node": 3423, "naklon": 0 }, +{ "label": "13/12", "node": 3406, "naklon": 0 }, +{ "label": "13/14", "node": 3411, "naklon": 0 }, +{ "label": "13/15", "node": 3412, "naklon": 0 }, +{ "label": "13/16", "node": 3413, "naklon": 0 }, +{ "label": "13/17", "node": 3414, "naklon": 0 }, +{ "label": "13/18", "node": 3391, "naklon": 0 }, +{ "label": "13/19", "node": 3370, "naklon": 0 }, +{ "label": "13/20", "node": 3369, "naklon": 0 }, +{ "label": "13/21", "node": 3408, "naklon": 0 }, +{ "label": "13/22", "node": 3393, "naklon": 0 }, +{ "label": "13/23", "node": 3128, "naklon": 0 }, +{ "label": "13/24", "node": 3197, "naklon": 0 }, +{ "label": "13/25", "node": 4364, "naklon": 0 }, +{ "label": "13/26", "node": 3155, "naklon": 0 }, +{ "label": "13/27", "node": 3196, "naklon": 0 }, +{ "label": "13/28", "node": 3144, "naklon": 0 }, +{ "label": "13/30", "node": 3150, "naklon": 0 }, +{ "label": "13/31", "node": 3390, "naklon": 0 }, +{ "label": "13/32", "node": 3401, "naklon": 0 }, +{ "label": "13/33", "node": 3275, "naklon": 0 }, +{ "label": "13/35", "node": 3371, "naklon": 0 }, +{ "label": "13/36", "node": 3389, "naklon": 0 }, +{ "label": "13/37", "node": 3388, "naklon": 0 }, +{ "label": "13/38", "node": 3365, "naklon": 0 }, +{ "label": "13/39", "node": 3363, "naklon": 0 }, +{ "label": "13/40", "node": 3397, "naklon": 0 }, +{ "label": "13/40/1", "node": 3567, "naklon": 0 }, +{ "label": "13/41", "node": 3387, "naklon": 0 }, +{ "label": "13/42", "node": 3403, "naklon": 0 }, +{ "label": "13/43", "node": 3147, "naklon": 0 }, +{ "label": "13/44", "node": 3141, "naklon": 0 }, +{ "label": "13/46", "node": 3364, "naklon": 0 }, +{ "label": "13/47", "node": 3367, "naklon": 0 }, +{ "label": "13/48", "node": 3368, "naklon": 0 }, +{ "label": "13/49", "node": 3402, "naklon": 0 }, +{ "label": "13/50", "node": 3366, "naklon": 0 }, +{ "label": "13/51", "node": 3395, "naklon": 0 }, +{ "label": "13/52", "node": 3372, "naklon": 0 }, +{ "label": "13/53", "node": 3394, "naklon": 0 }, +{ "label": "13/54", "node": 3308, "naklon": 0 }, +{ "label": "13/54/1", "node": 3847, "naklon": 0 }, +{ "label": "13/55", "node": 3312, "naklon": 3 }, +{ "label": "13/56", "node": 3309, "naklon": 3 }, +{ "label": "13/57", "node": 3311, "naklon": 3 }, +{ "label": "13/58", "node": 3310, "naklon": 3 }, +{ "label": "13/59", "node": 4365, "naklon": 3 }, +{ "label": "13/60/1", "node": 4093, "naklon": 3 }, +{ "label": "13/61", "node": 3304, "naklon": 3 }, +{ "label": "13/62", "node": 3307, "naklon": 3 }, +{ "label": "13/63", "node": 3271, "naklon": 3 }, +{ "label": "13/64", "node": 3301, "naklon": 3 }, +{ "label": "13/65", "node": 4366, "naklon": 3 }, +{ "label": "13/66", "node": 3300, "naklon": 3 }, +{ "label": "13/67", "node": 3185, "naklon": 0 }, +{ "label": "13/68", "node": 3184, "naklon": 0 }, +{ "label": "13/69", "node": 3188, "naklon": 0 }, +{ "label": "13/71", "node": 3343, "naklon": 6 }, +{ "label": "13/71/1", "node": 3819, "naklon": 6 }, +{ "label": "13/71/2", "node": 3880, "naklon": 6 }, +{ "label": "13/72", "node": 3348, "naklon": 6 }, +{ "label": "13/74", "node": 3344, "naklon": 6 }, +{ "label": "13/75", "node": 3346, "naklon": 6 }, +{ "label": "13/75/1", "node": 3597, "naklon": 6 }, +{ "label": "13/76", "node": 3345, "naklon": 6 }, +{ "label": "13/77", "node": 3322, "naklon": 0 }, +{ "label": "13/78", "node": 3325, "naklon": 0 }, +{ "label": "13/78/1", "node": 4310, "naklon": 0 }, +{ "label": "13/79", "node": 3315, "naklon": 0 }, +{ "label": "13/80", "node": 3328, "naklon": 0 }, +{ "label": "13/81", "node": 3321, "naklon": 0 }, +{ "label": "13/82", "node": 3324, "naklon": 0 }, +{ "label": "13/84", "node": 3140, "naklon": 0 }, +{ "label": "13/85", "node": 3153, "naklon": 0 }, +{ "label": "13/86", "node": 3145, "naklon": 0 }, +{ "label": "13/87", "node": 3134, "naklon": 0 }, +{ "label": "13/88", "node": 3151, "naklon": 0 }, +{ "label": "13/89", "node": 3143, "naklon": 0 }, +{ "label": "13/90", "node": 3318, "naklon": 0 }, +{ "label": "13/91", "node": 3347, "naklon": 0 }, +{ "label": "13/94", "node": 3314, "naklon": 0 }, +{ "label": "13/96", "node": 3331, "naklon": 0 }, +{ "label": "13/97", "node": 3327, "naklon": 0 }, +{ "label": "13/99", "node": 3329, "naklon": 0 }, +{ "label": "13/100", "node": 3337, "naklon": 0 }, +{ "label": "13/101", "node": 3330, "naklon": 0 }, +{ "label": "13/102", "node": 3335, "naklon": 0 }, +{ "label": "13/103", "node": 3420, "naklon": 0 }, +{ "label": "13/104", "node": 3421, "naklon": 0 }, +{ "label": "13/105", "node": 4361, "naklon": 0 }, +{ "label": "13/106", "node": 4362, "naklon": 0 }, +{ "label": "13/107", "node": 3526, "naklon": 0 }, +{ "label": "13/108", "node": 4424, "naklon": null }, +{ "label": "13/109", "node": 3561, "naklon": null }, +{ "label": "13/110", "node": 3527, "naklon": null }, +{ "label": "13/111", "node": 3521, "naklon": null }, +{ "label": "13/112", "node": 3552, "naklon": null }, +{ "label": "13/113", "node": 3544, "naklon": null }, +{ "label": "13/114", "node": 3534, "naklon": null }, +{ "label": "13/115", "node": 3516, "naklon": null }, +{ "label": "13/116", "node": 3513, "naklon": null }, +{ "label": "13/117", "node": 3565, "naklon": null }, +{ "label": "13/118", "node": 3866, "naklon": null }, +{ "label": "14/1", "node": 3136, "naklon": 0 }, +{ "label": "14/2", "node": 3137, "naklon": 0 }, +{ "label": "14/3", "node": 3135, "naklon": 0 }, +{ "label": "14/4", "node": 3149, "naklon": 0 }, +{ "label": "14/5", "node": 3142, "naklon": 0 }, +{ "label": "14/6", "node": 3342, "naklon": 0 }, +{ "label": "14/7", "node": 3340, "naklon": 0 }, +{ "label": "14/8", "node": 3152, "naklon": 0 }, +{ "label": "14/9", "node": 3886, "naklon": 0 }, +{ "label": "14/10", "node": 3341, "naklon": null }, +{ "label": "14/11", "node": 3352, "naklon": null }, +{ "label": "15/1", "node": 3396, "naklon": 5 }, +{ "label": "15/2", "node": 2784, "naklon": 5 }, +{ "label": "15/3", "node": 2788, "naklon": 5 }, +{ "label": "15/4", "node": 2801, "naklon": 5 }, +{ "label": "15/5", "node": 2815, "naklon": 5 }, +{ "label": "15/6", "node": 2829, "naklon": 5 }, +{ "label": "15/7", "node": 2796, "naklon": 5 }, +{ "label": "15/8", "node": 2803, "naklon": 5 }, +{ "label": "15/8/1", "node": 4304, "naklon": 5 }, +{ "label": "15/8/2", "node": 4311, "naklon": 5 }, +{ "label": "15/9", "node": 2821, "naklon": 5 }, +{ "label": "15/10", "node": 3400, "naklon": 5 }, +{ "label": "15/11", "node": 2799, "naklon": 5 }, +{ "label": "15/12", "node": 2804, "naklon": 5 }, +{ "label": "15/12/1", "node": 4303, "naklon": 5 }, +{ "label": "15/12/2", "node": 4309, "naklon": 5 }, +{ "label": "15/13", "node": 2806, "naklon": 5 }, +{ "label": "15/14", "node": 2787, "naklon": 5 }, +{ "label": "15/15", "node": 2809, "naklon": 5 }, +{ "label": "15/16", "node": 2814, "naklon": 0 }, +{ "label": "15/17", "node": 3934, "naklon": 0 }, +{ "label": "15/18", "node": 3192, "naklon": 0 }, +{ "label": "15/19", "node": 2812, "naklon": 0 }, +{ "label": "15/20", "node": 4070, "naklon": 0 }, +{ "label": "15/21", "node": 2826, "naklon": 0 }, +{ "label": "15/22", "node": 2808, "naklon": 3 }, +{ "label": "15/23", "node": 2795, "naklon": 3 }, +{ "label": "15/24", "node": 2807, "naklon": 3 }, +{ "label": "15/25", "node": 2831, "naklon": 0 }, +{ "label": "15/26", "node": 2862, "naklon": null }, +{ "label": "15/27", "node": 2861, "naklon": 0 }, +{ "label": "15/28", "node": 2866, "naklon": 0 }, +{ "label": "15/28/1", "node": 3546, "naklon": 0 }, +{ "label": "15/29", "node": 4146, "naklon": 0 }, +{ "label": "15/29/1", "node": 3001, "naklon": 0 }, +{ "label": "15/30", "node": 2835, "naklon": 0 }, +{ "label": "15/31", "node": 2874, "naklon": 0 }, +{ "label": "15/32", "node": 2852, "naklon": 0 }, +{ "label": "15/33", "node": 2851, "naklon": 0 }, +{ "label": "15/33/1", "node": 3560, "naklon": 0 }, +{ "label": "15/34", "node": 2858, "naklon": 0 }, +{ "label": "15/34/1", "node": 4306, "naklon": 0 }, +{ "label": "15/35", "node": 2856, "naklon": 0 }, +{ "label": "15/36", "node": 2847, "naklon": 0 }, +{ "label": "15/36/1", "node": 3556, "naklon": 0 }, +{ "label": "15/37", "node": 3950, "naklon": 0 }, +{ "label": "15/38", "node": 2848, "naklon": 0 }, +{ "label": "15/39", "node": 2863, "naklon": 0 }, +{ "label": "15/39/1", "node": 4313, "naklon": 0 }, +{ "label": "15/40", "node": 2873, "naklon": 0 }, +{ "label": "15/40/1", "node": 2984, "naklon": 0 }, +{ "label": "15/41", "node": 2854, "naklon": 0 }, +{ "label": "15/42", "node": 2859, "naklon": 0 }, +{ "label": "15/43", "node": 2872, "naklon": 0 }, +{ "label": "15/44", "node": 2849, "naklon": 0 }, +{ "label": "15/45", "node": 2864, "naklon": 0 }, +{ "label": "15/46", "node": 3553, "naklon": null }, +{ "label": "15/47", "node": 3021, "naklon": null }, +{ "label": "15/47/1", "node": 3008, "naklon": null }, +{ "label": "15/48", "node": 3017, "naklon": null }, +{ "label": "15/49", "node": 3014, "naklon": null }, +{ "label": "15/50", "node": 2981, "naklon": null }, +{ "label": "15/51", "node": 3020, "naklon": null }, +{ "label": "15/52", "node": 3027, "naklon": null }, +{ "label": "15/53", "node": 3006, "naklon": null }, +{ "label": "15/54", "node": 3012, "naklon": null }, +{ "label": "15/55", "node": 2738, "naklon": 0 }, +{ "label": "15/56", "node": 2725, "naklon": 0 }, +{ "label": "15/57", "node": 3016, "naklon": null }, +{ "label": "15/58", "node": 3005, "naklon": null }, +{ "label": "15/58/1", "node": 3009, "naklon": null }, +{ "label": "15/59", "node": 3010, "naklon": 0 }, +{ "label": "15/59/1", "node": 3538, "naklon": 0 }, +{ "label": "15/59/2", "node": 4145, "naklon": 0 }, +{ "label": "15/60", "node": 2713, "naklon": 0 }, +{ "label": "15/61", "node": 2789, "naklon": 0 }, +{ "label": "15/62", "node": 2736, "naklon": 0 }, +{ "label": "15/63", "node": 2739, "naklon": 0 }, +{ "label": "15/64", "node": 4346, "naklon": 0 }, +{ "label": "15/65", "node": 2731, "naklon": 0 }, +{ "label": "15/66", "node": 2818, "naklon": 0 }, +{ "label": "15/66/1", "node": 3557, "naklon": 0 }, +{ "label": "15/67", "node": 2822, "naklon": 0 }, +{ "label": "15/68", "node": 2833, "naklon": 0 }, +{ "label": "15/69", "node": 2834, "naklon": 0 }, +{ "label": "15/70", "node": 3097, "naklon": 0 }, +{ "label": "15/71", "node": 2824, "naklon": 0 }, +{ "label": "15/72", "node": 2828, "naklon": 0 }, +{ "label": "15/73", "node": 2600, "naklon": 0 }, +{ "label": "15/73/1", "node": 4314, "naklon": 0 }, +{ "label": "15/74", "node": 2832, "naklon": 0 }, +{ "label": "15/75", "node": 4360, "naklon": 0 }, +{ "label": "15/76", "node": 2846, "naklon": 0 }, +{ "label": "15/77", "node": 2584, "naklon": 0 }, +{ "label": "15/78", "node": 2843, "naklon": 0 }, +{ "label": "15/78/1", "node": 4308, "naklon": 0 }, +{ "label": "15/79", "node": 4144, "naklon": null }, +{ "label": "15/80", "node": 2844, "naklon": 0 }, +{ "label": "15/81", "node": 2842, "naklon": 0 }, +{ "label": "15/82", "node": 2838, "naklon": 0 }, +{ "label": "15/83", "node": 2837, "naklon": null }, +{ "label": "15/83/1", "node": 3555, "naklon": null }, +{ "label": "15/84", "node": 2839, "naklon": 0 }, +{ "label": "15/85", "node": 2830, "naklon": 0 }, +{ "label": "15/86", "node": 4066, "naklon": 0 }, +{ "label": "15/87", "node": 2836, "naklon": 0 }, +{ "label": "15/88", "node": 2911, "naklon": 0 }, +{ "label": "15/89", "node": 2825, "naklon": 0 }, +{ "label": "15/90", "node": 2811, "naklon": 0 }, +{ "label": "15/94", "node": 3740, "naklon": 15 }, +{ "label": "15/95", "node": 2734, "naklon": 15 }, +{ "label": "15/96", "node": 3105, "naklon": 15 }, +{ "label": "15/97", "node": 2732, "naklon": 15 }, +{ "label": "15/98", "node": 2727, "naklon": 15 }, +{ "label": "15/99", "node": 2735, "naklon": 15 }, +{ "label": "15/100", "node": 3926, "naklon": 15 }, +{ "label": "15/101", "node": 2918, "naklon": 0 }, +{ "label": "15/102", "node": 2705, "naklon": 10 }, +{ "label": "15/103", "node": 2708, "naklon": 10 }, +{ "label": "15/104", "node": 2721, "naklon": 10 }, +{ "label": "15/105", "node": 2719, "naklon": 10 }, +{ "label": "15/106", "node": 2919, "naklon": 10 }, +{ "label": "15/107", "node": 3101, "naklon": 10 }, +{ "label": "15/108", "node": 2853, "naklon": 10 }, +{ "label": "15/109", "node": 2715, "naklon": 10 }, +{ "label": "15/110", "node": 2712, "naklon": 0 }, +{ "label": "15/111", "node": 2711, "naklon": 0 }, +{ "label": "15/112", "node": 2709, "naklon": 0 }, +{ "label": "15/113", "node": 2710, "naklon": 0 }, +{ "label": "15/114", "node": 2907, "naklon": 0 }, +{ "label": "15/115", "node": 2906, "naklon": 0 }, +{ "label": "15/116", "node": 2908, "naklon": 0 }, +{ "label": "15/117", "node": 2901, "naklon": 0 }, +{ "label": "15/118", "node": 2913, "naklon": 0 }, +{ "label": "15/119", "node": 3656, "naklon": 0 }, +{ "label": "15/120", "node": 2781, "naklon": 0 }, +{ "label": "15/121", "node": 2802, "naklon": 0 }, +{ "label": "15/122", "node": 2791, "naklon": 0 }, +{ "label": "15/123", "node": 2783, "naklon": 0 }, +{ "label": "15/124", "node": 2794, "naklon": 0 }, +{ "label": "15/125", "node": 3139, "naklon": 0 }, +{ "label": "15/126", "node": 3229, "naklon": 5 }, +{ "label": "15/127", "node": 3239, "naklon": 5 }, +{ "label": "15/128", "node": 3230, "naklon": 5 }, +{ "label": "15/129", "node": 4016, "naklon": null }, +{ "label": "16/16A", "node": 3608, "naklon": 0 }, +{ "label": "16/16B", "node": 4151, "naklon": 0 }, +{ "label": "16/1", "node": 3710, "naklon": 0 }, +{ "label": "16/2", "node": 3726, "naklon": 0 }, +{ "label": "16/3", "node": 3743, "naklon": 0 }, +{ "label": "16/4", "node": 3724, "naklon": 0 }, +{ "label": "16/5", "node": 3712, "naklon": 0 }, +{ "label": "16/6", "node": 3739, "naklon": 0 }, +{ "label": "16/7", "node": 3742, "naklon": 0 }, +{ "label": "16/8", "node": 3731, "naklon": 0 }, +{ "label": "16/9", "node": 3727, "naklon": 0 }, +{ "label": "16/10", "node": 3729, "naklon": 0 }, +{ "label": "16/11", "node": 3736, "naklon": 0 }, +{ "label": "16/12", "node": 3713, "naklon": 0 }, +{ "label": "16/13", "node": 3715, "naklon": 0 }, +{ "label": "16/14", "node": 3733, "naklon": 0 }, +{ "label": "16/15", "node": 3732, "naklon": 0 }, +{ "label": "16/17", "node": 3634, "naklon": 0 }, +{ "label": "16/18", "node": 3610, "naklon": 0 }, +{ "label": "16/19", "node": 3626, "naklon": 0 }, +{ "label": "16/20", "node": 3618, "naklon": 0 }, +{ "label": "16/21", "node": 3619, "naklon": 0 }, +{ "label": "16/22", "node": 3628, "naklon": 0 }, +{ "label": "16/23", "node": 3615, "naklon": 0 }, +{ "label": "16/24", "node": 3609, "naklon": 0 }, +{ "label": "16/25", "node": 3606, "naklon": 0 }, +{ "label": "16/26", "node": 3624, "naklon": 0 }, +{ "label": "16/27", "node": 3627, "naklon": 0 }, +{ "label": "16/28", "node": 3607, "naklon": 0 }, +{ "label": "16/29", "node": 4370, "naklon": 0 }, +{ "label": "16/30", "node": 3692, "naklon": 0 }, +{ "label": "16/31", "node": 3614, "naklon": 0 }, +{ "label": "16/32", "node": 3623, "naklon": 0 }, +{ "label": "16/33", "node": 4373, "naklon": 0 }, +{ "label": "16/34", "node": 3620, "naklon": 0 }, +{ "label": "16/35", "node": 3685, "naklon": 0 }, +{ "label": "16/36", "node": 3616, "naklon": 0 }, +{ "label": "16/37", "node": 3686, "naklon": 0 }, +{ "label": "16/38", "node": 3688, "naklon": 0 }, +{ "label": "16/39", "node": 3684, "naklon": 0 }, +{ "label": "16/40", "node": 3825, "naklon": 0 }, +{ "label": "16/41", "node": 3865, "naklon": 0 }, +{ "label": "16/42", "node": 3824, "naklon": 0 }, +{ "label": "16/43", "node": 3871, "naklon": 0 }, +{ "label": "16/44", "node": 3801, "naklon": 0 }, +{ "label": "16/45", "node": 3862, "naklon": 0 }, +{ "label": "16/46", "node": 3876, "naklon": 0 }, +{ "label": "16/47", "node": 3861, "naklon": 0 }, +{ "label": "16/48", "node": 4215, "naklon": 0 }, +{ "label": "16/49", "node": 3605, "naklon": 10 }, +{ "label": "16/50", "node": 3603, "naklon": 10 }, +{ "label": "16/51", "node": 3592, "naklon": 10 }, +{ "label": "16/52", "node": 3598, "naklon": 10 }, +{ "label": "16/53", "node": 3594, "naklon": 10 }, +{ "label": "16/54", "node": 3593, "naklon": 10 }, +{ "label": "16/55", "node": 3630, "naklon": 10 }, +{ "label": "16/56", "node": 3763, "naklon": 10 }, +{ "label": "16/57", "node": 3746, "naklon": 10 }, +{ "label": "16/58", "node": 3699, "naklon": 0 }, +{ "label": "16/59", "node": 3698, "naklon": 0 }, +{ "label": "16/60", "node": 3709, "naklon": null }, +{ "label": "16/61", "node": 3708, "naklon": 0 }, +{ "label": "16/62", "node": 3703, "naklon": null }, +{ "label": "16/63", "node": 3700, "naklon": 0 }, +{ "label": "16/64", "node": 3701, "naklon": null }, +{ "label": "16/65", "node": 3704, "naklon": 0 }, +{ "label": "16/66", "node": 3707, "naklon": null }, +{ "label": "16/67", "node": 3810, "naklon": 0 }, +{ "label": "16/68", "node": 4208, "naklon": null }, +{ "label": "16/69", "node": 3867, "naklon": 0 }, +{ "label": "16/70", "node": 4372, "naklon": null }, +{ "label": "16/71", "node": 3881, "naklon": 0 }, +{ "label": "16/72", "node": 4204, "naklon": null }, +{ "label": "16/73", "node": 3869, "naklon": 0 }, +{ "label": "16/74", "node": 4202, "naklon": null }, +{ "label": "16/75", "node": 3830, "naklon": 0 }, +{ "label": "16/76", "node": 3870, "naklon": null }, +{ "label": "16/77", "node": 3964, "naklon": 0 }, +{ "label": "16/78", "node": 3849, "naklon": 0 }, +{ "label": "16/79", "node": 3694, "naklon": null }, +{ "label": "16/80", "node": 3717, "naklon": 0 }, +{ "label": "16/81", "node": 3877, "naklon": null }, +{ "label": "16/82", "node": 3755, "naklon": 0 }, +{ "label": "16/83", "node": 3725, "naklon": null }, +{ "label": "16/84", "node": 3716, "naklon": 0 }, +{ "label": "16/85", "node": 3696, "naklon": null }, +{ "label": "16/86", "node": 3702, "naklon": 0 }, +{ "label": "16/87", "node": 3706, "naklon": null }, +{ "label": "16/88", "node": 3850, "naklon": 0 }, +{ "label": "16/89", "node": 3848, "naklon": null }, +{ "label": "16/90", "node": 3737, "naklon": null }, +{ "label": "16/91", "node": 3705, "naklon": 0 }, +{ "label": "16/92", "node": 3723, "naklon": null }, +{ "label": "16/93", "node": 3842, "naklon": 0 }, +{ "label": "16/94", "node": 3735, "naklon": null }, +{ "label": "16/95", "node": 3719, "naklon": 0 }, +{ "label": "16/96", "node": 3697, "naklon": 0 }, +{ "label": "16/97", "node": 3711, "naklon": 0 }, +{ "label": "16/98", "node": 4107, "naklon": null }, +{ "label": "16/99", "node": 4112, "naklon": 5 }, +{ "label": "16/100", "node": 4106, "naklon": 5 }, +{ "label": "16/101", "node": 4111, "naklon": 5 }, +{ "label": "16/102", "node": 4091, "naklon": null }, +{ "label": "16/103", "node": 4104, "naklon": 5 }, +{ "label": "16/104", "node": 4094, "naklon": null }, +{ "label": "16/105", "node": 4089, "naklon": 5 }, +{ "label": "16/106", "node": 4095, "naklon": null }, +{ "label": "16/107", "node": 4102, "naklon": 5 }, +{ "label": "16/108", "node": 4105, "naklon": null }, +{ "label": "16/109", "node": 3859, "naklon": null }, +{ "label": "16/110", "node": 4090, "naklon": 5 }, +{ "label": "16/111", "node": 4110, "naklon": null }, +{ "label": "16/112", "node": 4097, "naklon": 5 }, +{ "label": "16/113", "node": 4099, "naklon": null }, +{ "label": "16/114", "node": 4096, "naklon": null }, +{ "label": "16/115", "node": 4101, "naklon": 5 }, +{ "label": "16/116", "node": 4109, "naklon": null }, +{ "label": "16/117", "node": 4092, "naklon": 5 }, +{ "label": "16/118", "node": 3631, "naklon": null }, +{ "label": "16/119", "node": 3632, "naklon": 0 }, +{ "label": "16/120", "node": 3641, "naklon": null }, +{ "label": "16/121", "node": 3638, "naklon": 0 }, +{ "label": "16/122", "node": 3637, "naklon": null }, +{ "label": "16/123", "node": 4142, "naklon": null }, +{ "label": "16/124", "node": 4147, "naklon": 5 }, +{ "label": "16/125", "node": 4139, "naklon": 5 }, +{ "label": "20/30A", "node": 3172, "naklon": 2 }, +{ "label": "20/30B", "node": 3164, "naklon": 2 }, +{ "label": "20/1", "node": 3247, "naklon": 10 }, +{ "label": "20/2", "node": 3296, "naklon": 10 }, +{ "label": "20/3", "node": 3246, "naklon": 10 }, +{ "label": "20/4", "node": 3270, "naklon": 10 }, +{ "label": "20/5", "node": 3294, "naklon": 10 }, +{ "label": "20/6", "node": 3298, "naklon": 10 }, +{ "label": "20/7", "node": 3297, "naklon": 10 }, +{ "label": "20/8", "node": 3293, "naklon": 10 }, +{ "label": "20/9", "node": 3299, "naklon": 10 }, +{ "label": "20/10", "node": 3295, "naklon": 10 }, +{ "label": "20/11", "node": 3244, "naklon": 10 }, +{ "label": "20/12", "node": 3249, "naklon": 10 }, +{ "label": "20/13", "node": 3268, "naklon": 10 }, +{ "label": "20/14", "node": 3245, "naklon": 10 }, +{ "label": "20/15", "node": 3278, "naklon": 10 }, +{ "label": "20/16", "node": 3280, "naklon": 10 }, +{ "label": "20/17", "node": 3292, "naklon": 10 }, +{ "label": "20/18", "node": 3287, "naklon": 10 }, +{ "label": "20/19", "node": 3282, "naklon": 10 }, +{ "label": "20/20", "node": 3273, "naklon": 0 }, +{ "label": "20/21", "node": 3157, "naklon": 0 }, +{ "label": "20/22", "node": 3283, "naklon": 0 }, +{ "label": "20/23", "node": 3159, "naklon": 0 }, +{ "label": "20/24", "node": 3289, "naklon": 0 }, +{ "label": "20/25", "node": 3163, "naklon": 0 }, +{ "label": "20/26", "node": 3126, "naklon": 0 }, +{ "label": "20/27", "node": 3171, "naklon": 0 }, +{ "label": "20/28", "node": 3162, "naklon": 0 }, +{ "label": "20/29", "node": 3279, "naklon": 10 }, +{ "label": "20/31", "node": 3173, "naklon": 0 }, +{ "label": "20/32", "node": 3127, "naklon": 0 }, +{ "label": "20/33", "node": 3131, "naklon": 0 }, +{ "label": "20/34", "node": 3129, "naklon": 0 }, +{ "label": "20/35", "node": 3276, "naklon": 2 }, +{ "label": "20/36", "node": 3290, "naklon": 2 }, +{ "label": "20/37", "node": 3132, "naklon": 0 }, +{ "label": "20/38", "node": 3138, "naklon": 0 }, +{ "label": "20/39", "node": 3272, "naklon": 0 }, +{ "label": "20/40", "node": 3291, "naklon": 0 }, +{ "label": "20/41", "node": 3277, "naklon": 10 }, +{ "label": "20/42", "node": 3286, "naklon": 10 }, +{ "label": "20/43", "node": 3281, "naklon": 10 }, +{ "label": "20/44", "node": 3288, "naklon": 10 }, +{ "label": "20/45", "node": 3284, "naklon": 10 }, +{ "label": "20/46", "node": 3167, "naklon": 10 }, +{ "label": "20/47", "node": 3872, "naklon": 0 }, +{ "label": "20/48", "node": 3124, "naklon": 0 }, +{ "label": "20/49", "node": 3133, "naklon": 0 }, +{ "label": "20/50", "node": 3158, "naklon": 0 }, +{ "label": "20/51", "node": 3169, "naklon": 0 }, +{ "label": "20/52", "node": 3146, "naklon": 0 }, +{ "label": "20/53", "node": 3160, "naklon": 0 }, +{ "label": "20/54", "node": 3248, "naklon": 0 }, +{ "label": "20/55", "node": 3156, "naklon": 0 }, +{ "label": "20/56", "node": 3161, "naklon": 0 }, +{ "label": "20/57", "node": 3170, "naklon": 0 }, +{ "label": "20/58", "node": 3168, "naklon": 0 }, +{ "label": "20/59", "node": 3125, "naklon": 0 }, +{ "label": "20/60", "node": 3166, "naklon": 0 }, +{ "label": "20/61", "node": 3130, "naklon": 0 }, +{ "label": "20/62", "node": 3563, "naklon": 0 }, +{ "label": "20/63", "node": 3550, "naklon": null }, +{ "label": "20/67", "node": 3269, "naklon": 0 }, +{ "label": "21/1", "node": 2921, "naklon": 0 }, +{ "label": "21/2", "node": 2707, "naklon": 0 }, +{ "label": "21/3", "node": 2723, "naklon": 0 }, +{ "label": "21/4", "node": 2716, "naklon": 0 }, +{ "label": "21/5", "node": 2717, "naklon": 0 }, +{ "label": "21/6", "node": 2720, "naklon": 0 }, +{ "label": "21/7", "node": 2722, "naklon": 0 }, +{ "label": "21/8", "node": 2718, "naklon": 0 }, +{ "label": "21/9", "node": 2724, "naklon": 0 }, +{ "label": "21/10", "node": 2742, "naklon": 0 }, +{ "label": "21/11", "node": 2743, "naklon": 0 }, +{ "label": "21/12", "node": 2733, "naklon": 0 }, +{ "label": "21/14", "node": 2903, "naklon": 0 }, +{ "label": "21/15", "node": 2917, "naklon": 0 }, +{ "label": "21/16", "node": 2897, "naklon": 0 }, +{ "label": "21/17", "node": 2914, "naklon": 0 }, +{ "label": "21/18", "node": 2898, "naklon": 0 }, +{ "label": "21/19", "node": 2773, "naklon": 0 }, +{ "label": "21/20", "node": 2895, "naklon": 0 }, +{ "label": "21/21", "node": 2896, "naklon": 0 }, +{ "label": "21/22", "node": 2771, "naklon": 0 }, +{ "label": "21/23", "node": 2772, "naklon": 0 }, +{ "label": "21/24", "node": 2793, "naklon": 0 }, +{ "label": "21/25", "node": 2902, "naklon": 0 }, +{ "label": "21/26", "node": 2910, "naklon": 0 }, +{ "label": "21/27", "node": 2909, "naklon": 0 }, +{ "label": "21/28", "node": 2920, "naklon": 0 }, +{ "label": "21/29", "node": 2916, "naklon": 0 }, +{ "label": "21/30", "node": 2904, "naklon": 0 }, +{ "label": "21/31", "node": 2915, "naklon": 0 }, +{ "label": "21/32", "node": 2905, "naklon": 0 }, +{ "label": "21/33", "node": 2900, "naklon": 0 }, +{ "label": "21/34", "node": 2899, "naklon": 0 }, +{ "label": "21/36", "node": 2741, "naklon": 0 }, +{ "label": "21/37", "node": 2714, "naklon": 0 }, +{ "label": "21/38", "node": 2701, "naklon": 0 }, +{ "label": "21/39", "node": 2703, "naklon": 0 }, +{ "label": "21/40", "node": 2704, "naklon": 0 }, +{ "label": "21/41", "node": 2702, "naklon": 0 }, +{ "label": "21/42", "node": 2706, "naklon": 0 }, +{ "label": "21/43", "node": 2776, "naklon": 0 }, +{ "label": "21/44", "node": 2770, "naklon": 0 }, +{ "label": "21/45", "node": 2786, "naklon": 0 }, +{ "label": "21/46", "node": 2779, "naklon": 0 }, +{ "label": "21/47", "node": 2782, "naklon": 0 }, +{ "label": "21/48", "node": 2785, "naklon": 0 }, +{ "label": "21/49", "node": 2769, "naklon": 0 }, +{ "label": "21/50", "node": 3354, "naklon": 0 }, +{ "label": "21/51", "node": 2778, "naklon": 0 }, +{ "label": "21/52", "node": 2775, "naklon": 0 }, +{ "label": "21/53", "node": 2780, "naklon": 0 }, +{ "label": "21/54", "node": 2790, "naklon": 0 }, +{ "label": "21/55", "node": 2792, "naklon": 0 }, +{ "label": "21/56", "node": 2774, "naklon": 0 }, +{ "label": "22/1", "node": 2630, "naklon": 0 }, +{ "label": "22/2", "node": 2631, "naklon": 0 }, +{ "label": "22/3", "node": 2632, "naklon": 0 }, +{ "label": "22/4", "node": 2633, "naklon": 0 }, +{ "label": "22/5", "node": 2634, "naklon": 0 }, +{ "label": "22/6", "node": 2636, "naklon": 0 }, +{ "label": "22/7", "node": 4367, "naklon": 0 }, +{ "label": "22/8", "node": 2637, "naklon": 0 }, +{ "label": "22/9", "node": 2638, "naklon": 0 }, +{ "label": "22/10", "node": 2639, "naklon": 0 }, +{ "label": "22/11", "node": 2640, "naklon": 0 }, +{ "label": "22/12", "node": 2641, "naklon": 0 }, +{ "label": "22/13", "node": 2642, "naklon": 0 }, +{ "label": "22/14", "node": 2643, "naklon": 0 }, +{ "label": "22/15", "node": 2644, "naklon": 0 }, +{ "label": "22/16", "node": 2645, "naklon": 0 }, +{ "label": "22/17", "node": 2646, "naklon": 0 }, +{ "label": "22/18", "node": 2647, "naklon": 0 }, +{ "label": "22/19", "node": 2648, "naklon": 0 }, +{ "label": "22/20", "node": 2649, "naklon": 0 }, +{ "label": "22/21", "node": 2650, "naklon": 0 }, +{ "label": "22/22", "node": 2651, "naklon": 0 }, +{ "label": "22/23", "node": 4103, "naklon": 0 }, +{ "label": "22/24", "node": 2653, "naklon": 0 }, +{ "label": "22/25", "node": 2654, "naklon": 0 }, +{ "label": "22/26", "node": 2655, "naklon": 0 }, +{ "label": "22/27", "node": 2656, "naklon": 0 }, +{ "label": "22/28", "node": 2657, "naklon": 0 }, +{ "label": "22/29", "node": 2658, "naklon": 0 }, +{ "label": "22/30", "node": 2659, "naklon": 0 }, +{ "label": "22/31", "node": 2660, "naklon": 0 }, +{ "label": "22/32", "node": 2661, "naklon": 0 }, +{ "label": "22/32/1", "node": 3015, "naklon": 0 }, +{ "label": "22/33", "node": 2662, "naklon": 0 }, +{ "label": "22/34", "node": 2663, "naklon": 0 }, +{ "label": "22/35", "node": 2664, "naklon": 0 }, +{ "label": "22/36", "node": 2665, "naklon": 0 }, +{ "label": "22/37", "node": 2666, "naklon": 0 }, +{ "label": "22/38", "node": 2667, "naklon": 0 }, +{ "label": "22/39", "node": 2668, "naklon": 0 }, +{ "label": "22/40", "node": 2669, "naklon": null }, +{ "label": "22/41", "node": 2670, "naklon": null }, +{ "label": "22/42", "node": 2671, "naklon": null }, +{ "label": "23/9A", "node": 3087, "naklon": 10 }, +{ "label": "23/9B", "node": 3090, "naklon": 10 }, +{ "label": "23/1", "node": 3075, "naklon": 0 }, +{ "label": "23/2", "node": 3089, "naklon": 0 }, +{ "label": "23/3", "node": 3088, "naklon": 0 }, +{ "label": "23/4", "node": 3228, "naklon": 10 }, +{ "label": "23/5", "node": 2751, "naklon": 10 }, +{ "label": "23/6", "node": 3243, "naklon": 10 }, +{ "label": "23/7", "node": 4349, "naklon": 10 }, +{ "label": "23/8", "node": 3102, "naklon": 10 }, +{ "label": "23/10", "node": 3099, "naklon": 10 }, +{ "label": "23/11", "node": 3103, "naklon": 10 }, +{ "label": "23/12", "node": 3093, "naklon": 10 }, +{ "label": "23/13", "node": 3098, "naklon": 10 }, +{ "label": "23/14", "node": 3092, "naklon": 10 }, +{ "label": "23/15", "node": 3233, "naklon": 0 }, +{ "label": "23/16", "node": 3095, "naklon": 0 }, +{ "label": "23/17", "node": 4074, "naklon": 0 }, +{ "label": "23/18", "node": 2729, "naklon": 0 }, +{ "label": "23/19", "node": 3234, "naklon": 0 }, +{ "label": "23/20", "node": 3094, "naklon": 0 }, +{ "label": "23/21", "node": 2817, "naklon": 0 }, +{ "label": "23/22", "node": 3226, "naklon": 0 }, +{ "label": "23/23", "node": 3225, "naklon": 0 }, +{ "label": "23/24", "node": 3237, "naklon": 0 }, +{ "label": "23/25", "node": 4250, "naklon": 0 }, +{ "label": "23/26", "node": 3059, "naklon": 10 }, +{ "label": "23/27", "node": 3238, "naklon": 10 }, +{ "label": "23/28", "node": 3242, "naklon": 10 }, +{ "label": "23/29", "node": 3236, "naklon": 10 }, +{ "label": "23/30", "node": 3112, "naklon": 10 }, +{ "label": "23/31", "node": 3224, "naklon": 0 }, +{ "label": "23/32", "node": 4298, "naklon": 10 }, +{ "label": "23/33", "node": 4150, "naklon": 10 }, +{ "label": "23/34", "node": 3091, "naklon": 10 }, +{ "label": "25/1", "node": 3771, "naklon": 5 }, +{ "label": "25/2", "node": 3777, "naklon": 5 }, +{ "label": "25/3", "node": 3749, "naklon": 5 }, +{ "label": "25/4", "node": 3769, "naklon": 5 }, +{ "label": "25/5", "node": 3765, "naklon": 5 }, +{ "label": "25/6", "node": 3785, "naklon": 5 }, +{ "label": "25/7", "node": 3761, "naklon": 5 }, +{ "label": "25/8", "node": 3758, "naklon": 5 }, +{ "label": "25/9", "node": 3766, "naklon": 5 }, +{ "label": "25/10", "node": 3779, "naklon": 5 }, +{ "label": "25/11", "node": 3899, "naklon": 10 }, +{ "label": "25/12", "node": 3922, "naklon": 10 }, +{ "label": "25/13", "node": 3912, "naklon": 10 }, +{ "label": "25/14", "node": 3933, "naklon": 10 }, +{ "label": "25/15", "node": 3921, "naklon": 10 }, +{ "label": "25/16", "node": 4300, "naklon": 10 }, +{ "label": "25/17", "node": 3927, "naklon": 10 }, +{ "label": "25/18", "node": 3212, "naklon": 10 }, +{ "label": "25/19", "node": 3208, "naklon": 10 }, +{ "label": "25/20", "node": 3207, "naklon": 10 }, +{ "label": "25/21", "node": 4294, "naklon": 10 }, +{ "label": "25/22", "node": 3209, "naklon": 10 }, +{ "label": "25/23", "node": 3745, "naklon": 10 }, +{ "label": "25/24", "node": 3762, "naklon": 10 }, +{ "label": "25/25", "node": 3215, "naklon": 10 }, +{ "label": "25/26", "node": 3210, "naklon": 10 }, +{ "label": "25/27", "node": 3211, "naklon": 10 }, +{ "label": "25/28", "node": 3206, "naklon": 10 }, +{ "label": "25/29", "node": 3918, "naklon": 5 }, +{ "label": "25/30", "node": 3928, "naklon": 5 }, +{ "label": "25/31", "node": 3917, "naklon": 5 }, +{ "label": "25/32", "node": 4029, "naklon": 0 }, +{ "label": "25/33", "node": 4038, "naklon": 0 }, +{ "label": "25/34", "node": 4022, "naklon": 0 }, +{ "label": "25/35", "node": 3937, "naklon": 0 }, +{ "label": "25/36", "node": 3190, "naklon": 0 }, +{ "label": "25/37", "node": 3835, "naklon": 0 }, +{ "label": "25/38", "node": 3201, "naklon": 0 }, +{ "label": "25/39", "node": 3193, "naklon": 0 }, +{ "label": "25/40", "node": 3191, "naklon": 0 }, +{ "label": "25/41", "node": 3203, "naklon": 0 }, +{ "label": "25/42", "node": 4301, "naklon": 0 }, +{ "label": "25/43", "node": 3223, "naklon": 0 }, +{ "label": "25/44", "node": 3202, "naklon": 0 }, +{ "label": "25/45", "node": 3205, "naklon": 0 }, +{ "label": "25/46", "node": 3194, "naklon": 0 }, +{ "label": "25/47", "node": 3198, "naklon": 0 }, +{ "label": "25/48", "node": 3204, "naklon": 0 }, +{ "label": "25/49", "node": 3200, "naklon": 0 }, +{ "label": "25/50", "node": 3216, "naklon": 0 }, +{ "label": "25/51", "node": 3932, "naklon": 5 }, +{ "label": "25/52", "node": 3923, "naklon": 5 }, +{ "label": "25/53", "node": 3913, "naklon": 5 }, +{ "label": "25/54", "node": 3900, "naklon": 5 }, +{ "label": "25/55", "node": 4189, "naklon": 10 }, +{ "label": "25/56", "node": 4191, "naklon": 10 }, +{ "label": "25/57", "node": 3790, "naklon": 10 }, +{ "label": "25/58", "node": 4190, "naklon": 10 }, +{ "label": "25/59", "node": 4302, "naklon": 0 }, +{ "label": "25/60", "node": 4351, "naklon": 0 }, +{ "label": "25/61", "node": 4075, "naklon": 0 }, +{ "label": "25/62", "node": 4071, "naklon": 0 }, +{ "label": "25/63", "node": 3784, "naklon": 0 }, +{ "label": "25/64", "node": 4065, "naklon": 0 }, +{ "label": "25/65", "node": 4297, "naklon": 0 }, +{ "label": "25/66", "node": 4295, "naklon": 0 }, +{ "label": "25/67", "node": 4299, "naklon": 0 }, +{ "label": "25/68", "node": 3772, "naklon": 0 }, +{ "label": "25/69", "node": 3941, "naklon": 0 }, +{ "label": "25/70", "node": 3782, "naklon": 0 }, +{ "label": "25/71", "node": 4068, "naklon": 0 }, +{ "label": "25/72", "node": 4073, "naklon": 0 }, +{ "label": "25/73", "node": 3901, "naklon": 5 }, +{ "label": "25/74", "node": 4296, "naklon": 5 }, +{ "label": "25/75", "node": 3910, "naklon": 5 }, +{ "label": "25/76", "node": 4293, "naklon": 5 }, +{ "label": "25/77", "node": 3919, "naklon": 5 }, +{ "label": "25/78", "node": 3924, "naklon": 5 }, +{ "label": "25/79", "node": 3909, "naklon": 5 }, +{ "label": "25/80", "node": 3896, "naklon": 5 }, +{ "label": "25/81", "node": 3911, "naklon": 5 }, +{ "label": "25/82", "node": 2819, "naklon": 15 }, +{ "label": "25/83", "node": 3776, "naklon": 15 }, +{ "label": "25/84", "node": 3752, "naklon": 15 }, +{ "label": "25/85", "node": 4353, "naklon": 15 }, +{ "label": "25/86", "node": 3791, "naklon": 0 }, +{ "label": "25/87", "node": 3770, "naklon": 0 }, +{ "label": "25/88", "node": 3760, "naklon": 0 }, +{ "label": "25/89", "node": 3115, "naklon": 0 }, +{ "label": "25/90", "node": 3738, "naklon": 0 }, +{ "label": "25/91", "node": 3748, "naklon": 0 }, +{ "label": "25/92", "node": 3753, "naklon": 0 }, +{ "label": "25/93", "node": 3775, "naklon": 0 }, +{ "label": "25/94", "node": 3778, "naklon": 5 }, +{ "label": "25/95", "node": 4078, "naklon": 5 }, +{ "label": "25/96", "node": 4088, "naklon": 5 }, +{ "label": "25/97", "node": 3856, "naklon": 5 }, +{ "label": "25/98", "node": 4084, "naklon": 5 }, +{ "label": "25/99", "node": 4069, "naklon": 5 }, +{ "label": "25/100", "node": 4188, "naklon": 5 }, +{ "label": "25/101", "node": 4064, "naklon": 5 }, +{ "label": "25/102", "node": 3792, "naklon": 5 }, +{ "label": "25/103", "node": 3780, "naklon": 5 }, +{ "label": "25/104", "node": 4034, "naklon": 5 }, +{ "label": "25/105", "node": 4072, "naklon": 5 }, +{ "label": "25/106", "node": 3884, "naklon": 5 }, +{ "label": "25/107", "node": 3793, "naklon": 5 }, +{ "label": "25/108", "node": 3863, "naklon": 5 }, +{ "label": "25/109", "node": 3855, "naklon": 5 }, +{ "label": "33/1", "node": 3846, "naklon": 0 }, +{ "label": "33/2", "node": 3943, "naklon": 0 }, +{ "label": "33/3", "node": 3903, "naklon": 0 }, +{ "label": "33/4", "node": 3982, "naklon": 0 }, +{ "label": "33/5", "node": 3879, "naklon": 0 }, +{ "label": "33/6", "node": 3887, "naklon": 0 }, +{ "label": "33/7", "node": 3920, "naklon": 5 }, +{ "label": "33/8", "node": 3942, "naklon": 5 }, +{ "label": "33/9", "node": 3829, "naklon": null }, +{ "label": "34/79A", "node": 3452, "naklon": 6 }, +{ "label": "34/79B", "node": 3460, "naklon": 6 }, +{ "label": "34/90A", "node": 3443, "naklon": 6 }, +{ "label": "34/90B", "node": 3445, "naklon": 6 }, +{ "label": "34/90C", "node": 3457, "naklon": 6 }, +{ "label": "34/97A", "node": 3461, "naklon": 6 }, +{ "label": "34/97B", "node": 3463, "naklon": 6 }, +{ "label": "34/98A", "node": 3426, "naklon": 6 }, +{ "label": "34/98B", "node": 3444, "naklon": 6 }, +{ "label": "34/99A", "node": 3453, "naklon": 6 }, +{ "label": "34/99B", "node": 3455, "naklon": 6 }, +{ "label": "34/1", "node": 4009, "naklon": 0 }, +{ "label": "34/2", "node": 3602, "naklon": 0 }, +{ "label": "34/3", "node": 3441, "naklon": 0 }, +{ "label": "34/4", "node": 3464, "naklon": 0 }, +{ "label": "34/5", "node": 3883, "naklon": 0 }, +{ "label": "34/6", "node": 4098, "naklon": 0 }, +{ "label": "34/7", "node": 4003, "naklon": 0 }, +{ "label": "34/8", "node": 4004, "naklon": 0 }, +{ "label": "34/9", "node": 3888, "naklon": 0 }, +{ "label": "34/10", "node": 3997, "naklon": 0 }, +{ "label": "34/11", "node": 4006, "naklon": 0 }, +{ "label": "34/12", "node": 4000, "naklon": 0 }, +{ "label": "34/13", "node": 4011, "naklon": 0 }, +{ "label": "34/14", "node": 3999, "naklon": 0 }, +{ "label": "34/15", "node": 3981, "naklon": 0 }, +{ "label": "34/16", "node": 3988, "naklon": 0 }, +{ "label": "34/17", "node": 3986, "naklon": 0 }, +{ "label": "34/18", "node": 3998, "naklon": 0 }, +{ "label": "34/19", "node": 3983, "naklon": 0 }, +{ "label": "34/20", "node": 4005, "naklon": 0 }, +{ "label": "34/21", "node": 4001, "naklon": 0 }, +{ "label": "34/22", "node": 4008, "naklon": 0 }, +{ "label": "34/23", "node": 4002, "naklon": 0 }, +{ "label": "34/24", "node": 3996, "naklon": 0 }, +{ "label": "34/25", "node": 4007, "naklon": 0 }, +{ "label": "34/26", "node": 4113, "naklon": 15 }, +{ "label": "34/27", "node": 3595, "naklon": 5 }, +{ "label": "34/28", "node": 3599, "naklon": 5 }, +{ "label": "34/29", "node": 3601, "naklon": 5 }, +{ "label": "34/30", "node": 4205, "naklon": 0 }, +{ "label": "34/31", "node": 3987, "naklon": null }, +{ "label": "34/32", "node": 4214, "naklon": 0 }, +{ "label": "34/33", "node": 4226, "naklon": 0 }, +{ "label": "34/34", "node": 4209, "naklon": 0 }, +{ "label": "34/35", "node": 4201, "naklon": 0 }, +{ "label": "34/36", "node": 3440, "naklon": 0 }, +{ "label": "34/37", "node": 3465, "naklon": 0 }, +{ "label": "34/38", "node": 3446, "naklon": 0 }, +{ "label": "34/39", "node": 4039, "naklon": 5 }, +{ "label": "34/40", "node": 4057, "naklon": 5 }, +{ "label": "34/41", "node": 3985, "naklon": 0 }, +{ "label": "34/42", "node": 3882, "naklon": 0 }, +{ "label": "34/43", "node": 4040, "naklon": 5 }, +{ "label": "34/44", "node": 3231, "naklon": 0 }, +{ "label": "34/45", "node": 3227, "naklon": 0 }, +{ "label": "34/46", "node": 3431, "naklon": 0 }, +{ "label": "34/47", "node": 4013, "naklon": 0 }, +{ "label": "34/48", "node": 4045, "naklon": 0 }, +{ "label": "34/49", "node": 3949, "naklon": 0 }, +{ "label": "34/50", "node": 3953, "naklon": 0 }, +{ "label": "34/51", "node": 3952, "naklon": 0 }, +{ "label": "34/52", "node": 3995, "naklon": 0 }, +{ "label": "34/53", "node": 3992, "naklon": 0 }, +{ "label": "34/54", "node": 4198, "naklon": 0 }, +{ "label": "34/55", "node": 3935, "naklon": 0 }, +{ "label": "34/56", "node": 4050, "naklon": 0 }, +{ "label": "34/57", "node": 4049, "naklon": 0 }, +{ "label": "34/58", "node": 4054, "naklon": 0 }, +{ "label": "34/59", "node": 3663, "naklon": 6 }, +{ "label": "34/60", "node": 3661, "naklon": 6 }, +{ "label": "34/61", "node": 3664, "naklon": 6 }, +{ "label": "34/62", "node": 3660, "naklon": 6 }, +{ "label": "34/63", "node": 3662, "naklon": 6 }, +{ "label": "34/65", "node": 3665, "naklon": 6 }, +{ "label": "34/66", "node": 3667, "naklon": 6 }, +{ "label": "34/67", "node": 3675, "naklon": 6 }, +{ "label": "34/68", "node": 3666, "naklon": 6 }, +{ "label": "34/69", "node": 3652, "naklon": 6 }, +{ "label": "34/70", "node": 3458, "naklon": 6 }, +{ "label": "34/70/1", "node": 4425, "naklon": 6 }, +{ "label": "34/71", "node": 3459, "naklon": 6 }, +{ "label": "34/72", "node": 3435, "naklon": 6 }, +{ "label": "34/73", "node": 3448, "naklon": 6 }, +{ "label": "34/74", "node": 3451, "naklon": 6 }, +{ "label": "34/75", "node": 3442, "naklon": 6 }, +{ "label": "34/76", "node": 3449, "naklon": 6 }, +{ "label": "34/77", "node": 3450, "naklon": 6 }, +{ "label": "34/78", "node": 3433, "naklon": 6 }, +{ "label": "34/80", "node": 3432, "naklon": 12 }, +{ "label": "34/81", "node": 3470, "naklon": 12 }, +{ "label": "34/82", "node": 3438, "naklon": 12 }, +{ "label": "34/83", "node": 3439, "naklon": 12 }, +{ "label": "34/84", "node": 4028, "naklon": 5 }, +{ "label": "34/85", "node": 3596, "naklon": 5 }, +{ "label": "34/86", "node": 4021, "naklon": 5 }, +{ "label": "34/87", "node": 3437, "naklon": 12 }, +{ "label": "34/88", "node": 3428, "naklon": 12 }, +{ "label": "34/89", "node": 3430, "naklon": 12 }, +{ "label": "34/91", "node": 3454, "naklon": 6 }, +{ "label": "34/92", "node": 3492, "naklon": 6 }, +{ "label": "34/93", "node": 3462, "naklon": 6 }, +{ "label": "34/94", "node": 3427, "naklon": 6 }, +{ "label": "34/95", "node": 3434, "naklon": 6 }, +{ "label": "34/96", "node": 3456, "naklon": 6 }, +{ "label": "34/98/1", "node": 4307, "naklon": 6 }, +{ "label": "35/1", "node": 3968, "naklon": 0 }, +{ "label": "35/2", "node": 3969, "naklon": 0 }, +{ "label": "35/3", "node": 3947, "naklon": 0 }, +{ "label": "35/4", "node": 3979, "naklon": 0 }, +{ "label": "35/5", "node": 3959, "naklon": 0 }, +{ "label": "35/6", "node": 3948, "naklon": 0 }, +{ "label": "35/7", "node": 3961, "naklon": 0 }, +{ "label": "35/8", "node": 3956, "naklon": 0 }, +{ "label": "35/9", "node": 3604, "naklon": 0 }, +{ "label": "35/10", "node": 3944, "naklon": 0 }, +{ "label": "35/11", "node": 3960, "naklon": 0 }, +{ "label": "35/12", "node": 3958, "naklon": 0 }, +{ "label": "35/13", "node": 4036, "naklon": 5 }, +{ "label": "35/18", "node": 3893, "naklon": 5 }, +{ "label": "35/19", "node": 4108, "naklon": 5 }, +{ "label": "35/20", "node": 4017, "naklon": 5 }, +{ "label": "35/21", "node": 3963, "naklon": 0 }, +{ "label": "35/22", "node": 3658, "naklon": 0 }, +{ "label": "35/23", "node": 3975, "naklon": 0 }, +{ "label": "35/24", "node": 3980, "naklon": 0 }, +{ "label": "35/25", "node": 4012, "naklon": 0 }, +{ "label": "35/26", "node": 3655, "naklon": 0 }, +{ "label": "35/27", "node": 3962, "naklon": 0 }, +{ "label": "35/28", "node": 3945, "naklon": 0 }, +{ "label": "35/29", "node": 3569, "naklon": 0 }, +{ "label": "35/30", "node": 3429, "naklon": 0 }, +{ "label": "35/31", "node": 3657, "naklon": 0 }, +{ "label": "35/32", "node": 3646, "naklon": 0 }, +{ "label": "35/33", "node": 3622, "naklon": 0 }, +{ "label": "35/34", "node": 3612, "naklon": 0 }, +{ "label": "35/35", "node": 3955, "naklon": 0 }, +{ "label": "35/37", "node": 3878, "naklon": 0 }, +{ "label": "35/38", "node": 3965, "naklon": 0 }, +{ "label": "35/39", "node": 3970, "naklon": 0 }, +{ "label": "35/40", "node": 3611, "naklon": 0 }, +{ "label": "35/41", "node": 2635, "naklon": 0 }, +{ "label": "35/42", "node": 3978, "naklon": 0 }, +{ "label": "35/43", "node": 4213, "naklon": 0 }, +{ "label": "35/44", "node": 3984, "naklon": 0 }, +{ "label": "35/45", "node": 4218, "naklon": 0 }, +{ "label": "35/46", "node": 3973, "naklon": 0 }, +{ "label": "35/47", "node": 3974, "naklon": 0 }, +{ "label": "35/48", "node": 3759, "naklon": 0 }, +{ "label": "35/49", "node": 3844, "naklon": 0 }, +{ "label": "35/50", "node": 3804, "naklon": 0 }, +{ "label": "35/51", "node": 3831, "naklon": 0 }, +{ "label": "35/52", "node": 3643, "naklon": 0 }, +{ "label": "35/53", "node": 3966, "naklon": 0 }, +{ "label": "35/54", "node": 3971, "naklon": 0 }, +{ "label": "35/55", "node": 3650, "naklon": 6 }, +{ "label": "35/56", "node": 3651, "naklon": 6 }, +{ "label": "35/57", "node": 3669, "naklon": 6 }, +{ "label": "35/58", "node": 3648, "naklon": 6 }, +{ "label": "35/59", "node": 3645, "naklon": 6 }, +{ "label": "35/60", "node": 3659, "naklon": 6 }, +{ "label": "35/61", "node": 3647, "naklon": 6 }, +{ "label": "35/62", "node": 3644, "naklon": 6 }, +{ "label": "35/63", "node": 3671, "naklon": 6 }, +{ "label": "35/64", "node": 3682, "naklon": 6 }, +{ "label": "35/65", "node": 3672, "naklon": 6 }, +{ "label": "35/66", "node": 3683, "naklon": 6 }, +{ "label": "35/67", "node": 3673, "naklon": 6 }, +{ "label": "35/68", "node": 3674, "naklon": 6 }, +{ "label": "35/69", "node": 3679, "naklon": 6 }, +{ "label": "35/70", "node": 3649, "naklon": 6 }, +{ "label": "35/71", "node": 3687, "naklon": 6 }, +{ "label": "35/72", "node": 3677, "naklon": 6 }, +{ "label": "35/73", "node": 3690, "naklon": 6 }, +{ "label": "35/74", "node": 3691, "naklon": 6 }, +{ "label": "35/75", "node": 3676, "naklon": 6 }, +{ "label": "35/76", "node": 3680, "naklon": 6 }, +{ "label": "35/77", "node": 3668, "naklon": 6 }, +{ "label": "35/78", "node": 3681, "naklon": 6 }, +{ "label": "35/79", "node": 3670, "naklon": 6 }, +{ "label": "35/80", "node": 3689, "naklon": 6 }, +{ "label": "35/81", "node": 3678, "naklon": 6 }, +{ "label": "35/82", "node": 3693, "naklon": 6 }, +{ "label": "35/83", "node": 3654, "naklon": null }, +{ "label": "36/1", "node": 4086, "naklon": 0 }, +{ "label": "36/2", "node": 4085, "naklon": 0 }, +{ "label": "36/3", "node": 4083, "naklon": 0 }, +{ "label": "36/4", "node": 4087, "naklon": 0 }, +{ "label": "36/5", "node": 4077, "naklon": 0 }, +{ "label": "36/6", "node": 4082, "naklon": 0 }, +{ "label": "36/7", "node": 4186, "naklon": 0 }, +{ "label": "36/8", "node": 4206, "naklon": 0 }, +{ "label": "36/9", "node": 4080, "naklon": 0 }, +{ "label": "36/10", "node": 4081, "naklon": 0 }, +{ "label": "36/11", "node": 4210, "naklon": 0 }, +{ "label": "36/12", "node": 4079, "naklon": 0 }, +{ "label": "36/13", "node": 4076, "naklon": 0 }, +{ "label": "36/14", "node": 3852, "naklon": 0 }, +{ "label": "36/15", "node": 2813, "naklon": 0 }, +{ "label": "36/16", "node": 4219, "naklon": 0 }, +{ "label": "37/1A", "node": 3104, "naklon": 15 }, +{ "label": "37/1B", "node": 3121, "naklon": 15 }, +{ "label": "37/2", "node": 3113, "naklon": 10 }, +{ "label": "37/3", "node": 3118, "naklon": 10 }, +{ "label": "37/4", "node": 3111, "naklon": 10 }, +{ "label": "37/5", "node": 4020, "naklon": 10 }, +{ "label": "37/6", "node": 3119, "naklon": 10 }, +{ "label": "37/7", "node": 3110, "naklon": 10 }, +{ "label": "37/8", "node": 3108, "naklon": 10 }, +{ "label": "37/12", "node": 3107, "naklon": 0 }, +{ "label": "37/13", "node": 3199, "naklon": 0 }, +{ "label": "37/14", "node": 3120, "naklon": 0 }, +{ "label": "37/15", "node": 3122, "naklon": 0 }, +{ "label": "37/16", "node": 3908, "naklon": 0 }, +{ "label": "37/17", "node": 3114, "naklon": 0 }, +{ "label": "37/18", "node": 3105, "naklon": 0 }, +{ "label": "37/19", "node": 3116, "naklon": 0 }, +{ "label": "37/20", "node": 3106, "naklon": 0 }, +{ "label": "37/21", "node": 2887, "naklon": 5 }, +{ "label": "37/22", "node": 2888, "naklon": 5 }, +{ "label": "37/23", "node": 2877, "naklon": 5 }, +{ "label": "37/24", "node": 2891, "naklon": 5 }, +{ "label": "37/25", "node": 2886, "naklon": 5 }, +{ "label": "37/26", "node": 2892, "naklon": 5 }, +{ "label": "37/27", "node": 2882, "naklon": 5 }, +{ "label": "37/28", "node": 2883, "naklon": 5 }, +{ "label": "37/29", "node": 2876, "naklon": 5 }, +{ "label": "37/30", "node": 3109, "naklon": 5 }, +{ "label": "37/31", "node": 4152, "naklon": 5 }, +{ "label": "37/32", "node": 3117, "naklon": 5 }, +{ "label": "37/33", "node": 2870, "naklon": 5 }, +{ "label": "37/34", "node": 2867, "naklon": 0 }, +{ "label": "37/35", "node": 2865, "naklon": 0 }, +{ "label": "37/36", "node": 3096, "naklon": 0 }, +{ "label": "37/37", "node": 2871, "naklon": 0 }, +{ "label": "37/38", "node": 2884, "naklon": 0 }, +{ "label": "37/39", "node": 2855, "naklon": 0 }, +{ "label": "37/40", "node": 2878, "naklon": 0 }, +{ "label": "37/41", "node": 2889, "naklon": 0 }, +{ "label": "37/42", "node": 2879, "naklon": 0 }, +{ "label": "37/43", "node": 2850, "naklon": 0 }, +{ "label": "37/44", "node": 2894, "naklon": 0 }, +{ "label": "37/45", "node": 2880, "naklon": 0 }, +{ "label": "37/46", "node": 2893, "naklon": 0 }, +{ "label": "37/47", "node": 2890, "naklon": 0 }, +{ "label": "37/48", "node": 4355, "naklon": 0 }, +{ "label": "37/49", "node": 2885, "naklon": 0 }, +{ "label": "37/50", "node": 2875, "naklon": 0 }, +{ "label": "38/30A", "node": 3486, "naklon": 5 }, +{ "label": "38/30B", "node": 3714, "naklon": 0 }, +{ "label": "38/32A", "node": 3483, "naklon": 5 }, +{ "label": "38/32B", "node": 3496, "naklon": 0 }, +{ "label": "38/35A", "node": 3487, "naklon": 5 }, +{ "label": "38/35B", "node": 3498, "naklon": 5 }, +{ "label": "38/38A", "node": 3578, "naklon": 5 }, +{ "label": "38/38B", "node": 3508, "naklon": 5 }, +{ "label": "38/59A", "node": 3787, "naklon": 5 }, +{ "label": "38/59B", "node": 3491, "naklon": 5 }, +{ "label": "38/1", "node": 3568, "naklon": null }, +{ "label": "38/2", "node": 3502, "naklon": 0 }, +{ "label": "38/3", "node": 3836, "naklon": 0 }, +{ "label": "38/4", "node": 3588, "naklon": 0 }, +{ "label": "38/5", "node": 3493, "naklon": 0 }, +{ "label": "38/6", "node": 3580, "naklon": 0 }, +{ "label": "38/7", "node": 3572, "naklon": 0 }, +{ "label": "38/8", "node": 3506, "naklon": 0 }, +{ "label": "38/9", "node": 3503, "naklon": 0 }, +{ "label": "38/10", "node": 3579, "naklon": 0 }, +{ "label": "38/11", "node": 3586, "naklon": 0 }, +{ "label": "38/12", "node": 3495, "naklon": 5 }, +{ "label": "38/13", "node": 3492, "naklon": 5 }, +{ "label": "38/14", "node": 3532, "naklon": 5 }, +{ "label": "38/15", "node": 3574, "naklon": 5 }, +{ "label": "38/16", "node": 4140, "naklon": 5 }, +{ "label": "38/17", "node": 3795, "naklon": 5 }, +{ "label": "38/18", "node": 3788, "naklon": 5 }, +{ "label": "38/19", "node": 3796, "naklon": 5 }, +{ "label": "38/20", "node": 3797, "naklon": 5 }, +{ "label": "38/21", "node": 3798, "naklon": 5 }, +{ "label": "38/22", "node": 3786, "naklon": 5 }, +{ "label": "38/23", "node": 4067, "naklon": 5 }, +{ "label": "38/24", "node": 3773, "naklon": 5 }, +{ "label": "38/25", "node": 3774, "naklon": 5 }, +{ "label": "38/26", "node": 3789, "naklon": 5 }, +{ "label": "38/27", "node": 3520, "naklon": null }, +{ "label": "38/29", "node": 3577, "naklon": 5 }, +{ "label": "38/31", "node": 3530, "naklon": null }, +{ "label": "38/33", "node": 3488, "naklon": 5 }, +{ "label": "38/34", "node": 3505, "naklon": 5 }, +{ "label": "38/36", "node": 3497, "naklon": 5 }, +{ "label": "38/37", "node": 3490, "naklon": 5 }, +{ "label": "38/39", "node": 3585, "naklon": 5 }, +{ "label": "38/40", "node": 3582, "naklon": 5 }, +{ "label": "38/41", "node": 3507, "naklon": 5 }, +{ "label": "38/42", "node": 3484, "naklon": 5 }, +{ "label": "38/43", "node": 3501, "naklon": 5 }, +{ "label": "38/44", "node": 3581, "naklon": 5 }, +{ "label": "38/45", "node": 4192, "naklon": 5 }, +{ "label": "38/46", "node": 3576, "naklon": 5 }, +{ "label": "38/47", "node": 3489, "naklon": 5 }, +{ "label": "38/48", "node": 3573, "naklon": 5 }, +{ "label": "38/49", "node": 3504, "naklon": 5 }, +{ "label": "38/50", "node": 3794, "naklon": 5 }, +{ "label": "38/51", "node": 3485, "naklon": 5 }, +{ "label": "38/52", "node": 3482, "naklon": 5 }, +{ "label": "38/53", "node": 3575, "naklon": 5 }, +{ "label": "38/54", "node": 3499, "naklon": 5 }, +{ "label": "38/55", "node": 3494, "naklon": 5 }, +{ "label": "38/56", "node": 3583, "naklon": 5 }, +{ "label": "38/57", "node": 3570, "naklon": 5 }, +{ "label": "38/58", "node": 3500, "naklon": 0 }, +{ "label": "38/63", "node": 3510, "naklon": null }, +{ "label": "38/64", "node": 3512, "naklon": null }, +{ "label": "38/67", "node": 3535, "naklon": null }, +{ "label": "38/68", "node": 3531, "naklon": null }, +{ "label": "38/69", "node": 3537, "naklon": null }, +{ "label": "39/1", "node": 3522, "naklon": 10 }, +{ "label": "39/2", "node": 4018, "naklon": 10 }, +{ "label": "39/3", "node": 4019, "naklon": 10 }, +{ "label": "39/4", "node": 4154, "naklon": 5 }, +{ "label": "39/5", "node": 3907, "naklon": 5 }, +{ "label": "39/6", "node": 4148, "naklon": 0 }, +{ "label": "39/7", "node": 4153, "naklon": 0 }, +{ "label": "39/8", "node": 3938, "naklon": 0 }, +{ "label": "39/9", "node": 3802, "naklon": 0 }, +{ "label": "39/10", "node": 4015, "naklon": 0 }, +{ "label": "39/11", "node": 3929, "naklon": 0 }, +{ "label": "39/12", "node": 3946, "naklon": 0 }, +{ "label": "39/13", "node": 4014, "naklon": 0 }, +{ "label": "39/14", "node": 4155, "naklon": 0 }, +{ "label": "39/15", "node": 4149, "naklon": 0 }, +{ "label": "39/16", "node": 3642, "naklon": 0 }, +{ "label": "39/17", "node": 3636, "naklon": 5 }, +{ "label": "39/18", "node": 3991, "naklon": 0 }, +{ "label": "39/19", "node": 3994, "naklon": 0 }, +{ "label": "39/20", "node": 3990, "naklon": 0 }, +{ "label": "39/21", "node": 3967, "naklon": 0 }, +{ "label": "39/22", "node": 3977, "naklon": 0 }, +{ "label": "39/23", "node": 3757, "naklon": 15 }, +{ "label": "39/24", "node": 3633, "naklon": 15 }, +{ "label": "39/25", "node": 3744, "naklon": 15 }, +{ "label": "39/26", "node": 4023, "naklon": 5 }, +{ "label": "39/27", "node": 3720, "naklon": 5 }, +{ "label": "39/28", "node": 3734, "naklon": 5 }, +{ "label": "39/29", "node": 3741, "naklon": 5 }, +{ "label": "39/30", "node": 3721, "naklon": 5 }, +{ "label": "39/31", "node": 3845, "naklon": 0 }, +{ "label": "39/32", "node": 3840, "naklon": 0 }, +{ "label": "39/33", "node": 3837, "naklon": null }, +{ "label": "39/34", "node": 3839, "naklon": 0 }, +{ "label": "41/1", "node": 3542, "naklon": null }, +{ "label": "41/2", "node": 3566, "naklon": null }, +{ "label": "41/3", "node": 3548, "naklon": null }, +{ "label": "41/4", "node": 3515, "naklon": null }, +{ "label": "41/5", "node": 3559, "naklon": null }, +{ "label": "41/6", "node": 3509, "naklon": null }, +{ "label": "41/7", "node": 3524, "naklon": null }, +{ "label": "41/8", "node": 3518, "naklon": null }, +{ "label": "41/9", "node": 3182, "naklon": null }, +{ "label": "41/10", "node": 3187, "naklon": null }, +{ "label": "41/11", "node": 3195, "naklon": 0 }, +{ "label": "41/12", "node": 3857, "naklon": 0 }, +{ "label": "41/13", "node": 3183, "naklon": 0 }, +{ "label": "41/14", "node": 3177, "naklon": 0 }, +{ "label": "41/15", "node": 3189, "naklon": 0 }, +{ "label": "41/16", "node": 3186, "naklon": 0 }, +{ "label": "42/1", "node": 3178, "naklon": 0 }, +{ "label": "42/2", "node": 3219, "naklon": 0 }, +{ "label": "42/3", "node": 3475, "naklon": 0 }, +{ "label": "42/4", "node": 3175, "naklon": 0 }, +{ "label": "42/5", "node": 3222, "naklon": 0 }, +{ "label": "42/6", "node": 3221, "naklon": 0 }, +{ "label": "42/7", "node": 3181, "naklon": 0 }, +{ "label": "42/8", "node": 3180, "naklon": 0 }, +{ "label": "42/9", "node": 3218, "naklon": 0 }, +{ "label": "42/10", "node": 3176, "naklon": 0 }, +{ "label": "42/11", "node": 3174, "naklon": 0 }, +{ "label": "42/12", "node": 3220, "naklon": 0 }, +{ "label": "42/13", "node": 3533, "naklon": null }, +{ "label": "42/14", "node": 3543, "naklon": null }, +{ "label": "42/15", "node": 3554, "naklon": null }, +{ "label": "42/16", "node": 3549, "naklon": null }, +{ "label": "43/1", "node": 2857, "naklon": 5 }, +{ "label": "43/2", "node": 2752, "naklon": 5 }, +{ "label": "43/3", "node": 2753, "naklon": 5 }, +{ "label": "43/4", "node": 3024, "naklon": 5 }, +{ "label": "43/5", "node": 2754, "naklon": 5 }, +{ "label": "43/6", "node": 4423, "naklon": 5 }, +{ "label": "43/7", "node": 4368, "naklon": 5 }, +{ "label": "43/8", "node": 2978, "naklon": 5 }, +{ "label": "43/9", "node": 2868, "naklon": 5 }, +{ "label": "43/10", "node": 4377, "naklon": 5 }, +{ "label": "43/11", "node": 2757, "naklon": 5 }, +{ "label": "43/12", "node": 2970, "naklon": 5 }, +{ "label": "43/13", "node": 2758, "naklon": 5 }, +{ "label": "43/14", "node": 4378, "naklon": 5 }, +{ "label": "43/15", "node": 2759, "naklon": 5 }, +{ "label": "43/16", "node": 4342, "naklon": 5 }, +{ "label": "43/17", "node": 3026, "naklon": null }, +{ "label": "43/18", "node": 2986, "naklon": null }, +{ "label": "43/19", "node": 4343, "naklon": null }, +{ "label": "43/20", "node": 2760, "naklon": null }, +{ "label": "43/21", "node": 4379, "naklon": null }, +{ "label": "43/22", "node": 2971, "naklon": null }, +{ "label": "43/23", "node": 2761, "naklon": null }, +{ "label": "43/24", "node": 2762, "naklon": null }, +{ "label": "43/25", "node": 4339, "naklon": null }, +{ "label": "43/26", "node": 4380, "naklon": null }, +{ "label": "43/27", "node": 2975, "naklon": null }, +{ "label": "43/28", "node": 3003, "naklon": null }, +{ "label": "43/29", "node": 4338, "naklon": null }, +{ "label": "43/30", "node": 3002, "naklon": null }, +{ "label": "43/31", "node": 4345, "naklon": null }, +{ "label": "43/32", "node": 2979, "naklon": null }, +{ "label": "43/33", "node": 2989, "naklon": null }, +{ "label": "43/34", "node": 2996, "naklon": null }, +{ "label": "43/35", "node": 2972, "naklon": null }, +{ "label": "43/36", "node": 2988, "naklon": null }, +{ "label": "43/37", "node": 4344, "naklon": null }, +{ "label": "43/38", "node": 3022, "naklon": null }, +{ "label": "43/39", "node": 4341, "naklon": null }, +{ "label": "43/40", "node": 2983, "naklon": null }, +{ "label": "43/41", "node": 2995, "naklon": null }, +{ "label": "43/42", "node": 2763, "naklon": null }, +{ "label": "43/43", "node": 2764, "naklon": null }, +{ "label": "43/44", "node": 2765, "naklon": null }, +{ "label": "43/45", "node": 2766, "naklon": null }, +{ "label": "43/46", "node": 2767, "naklon": null }, +{ "label": "43/47", "node": 2768, "naklon": null }, +{ "label": "43/48", "node": 3018, "naklon": null }, +{ "label": "43/49", "node": 2982, "naklon": null }, +{ "label": "43/50", "node": 3019, "naklon": 0 }, +{ "label": "43/51", "node": 3013, "naklon": null }, +{ "label": "43/52", "node": 3007, "naklon": null }, +{ "label": "43/53", "node": 2980, "naklon": null }, +{ "label": "43/54", "node": 3011, "naklon": null }, +{ "label": "43/55", "node": 2672, "naklon": null }, +{ "label": "43/56", "node": 2673, "naklon": null }, +{ "label": "43/57", "node": 2674, "naklon": null }, +{ "label": "43/58", "node": 2675, "naklon": null }, +{ "label": "43/59", "node": 2676, "naklon": null }, +{ "label": "43/60", "node": 2677, "naklon": null }, +{ "label": "43/61", "node": 2678, "naklon": null }, +{ "label": "43/62", "node": 2679, "naklon": null }, +{ "label": "43/63", "node": 2680, "naklon": null }, +{ "label": "43/64", "node": 2840, "naklon": null }, +{ "label": "43/65", "node": 2682, "naklon": null }, +{ "label": "43/66", "node": 2683, "naklon": null }, +{ "label": "43/67", "node": 2684, "naklon": 0 }, +{ "label": "43/68", "node": 2685, "naklon": null }, +{ "label": "43/69", "node": 2686, "naklon": null }, +{ "label": "43/70", "node": 2687, "naklon": null }, +{ "label": "43/71", "node": 2688, "naklon": null }, +{ "label": "43/72", "node": 2689, "naklon": null }, +{ "label": "43/73", "node": 2690, "naklon": null }, +{ "label": "43/74", "node": 2691, "naklon": null }, +{ "label": "43/75", "node": 2692, "naklon": null }, +{ "label": "43/76", "node": 2693, "naklon": 0 }, +{ "label": "43/77", "node": 2694, "naklon": null }, +{ "label": "43/78", "node": 2695, "naklon": null }, +{ "label": "43/79", "node": 2696, "naklon": 0 }, +{ "label": "43/80", "node": 2697, "naklon": null }, +{ "label": "43/81", "node": 2698, "naklon": 0 }, +{ "label": "43/82", "node": 2699, "naklon": null }, +{ "label": "43/83", "node": 2700, "naklon": 0 }, +{ "label": "43/84", "node": 2744, "naklon": null }, +{ "label": "43/85", "node": 2745, "naklon": 0 }, +{ "label": "43/86", "node": 2746, "naklon": null }, +{ "label": "43/87", "node": 2747, "naklon": 0 }, +{ "label": "43/88", "node": 2748, "naklon": null }, +{ "label": "43/89", "node": 2749, "naklon": 0 }, +{ "label": "43/90", "node": 2841, "naklon": null }, +{ "label": "45/1", "node": 4237, "naklon": 5 }, +{ "label": "45/2", "node": 4226, "naklon": 5 }, +{ "label": "45/3", "node": 4242, "naklon": 5 }, +{ "label": "45/4", "node": 4179, "naklon": 5 }, +{ "label": "45/5", "node": 4247, "naklon": 5 }, +{ "label": "45/6", "node": 4245, "naklon": 5 }, +{ "label": "45/7", "node": 3872, "naklon": 5 }, +{ "label": "45/8", "node": 4175, "naklon": 5 }, +{ "label": "45/9", "node": 4236, "naklon": 5 }, +{ "label": "45/10", "node": 4170, "naklon": 5 }, +{ "label": "45/11", "node": 4238, "naklon": 5 }, +{ "label": "45/12", "node": 4246, "naklon": 5 }, +{ "label": "45/13", "node": 4166, "naklon": 5 }, +{ "label": "45/14", "node": 4227, "naklon": 5 }, +{ "label": "45/15", "node": 4171, "naklon": 5 }, +{ "label": "45/16", "node": 4180, "naklon": 5 }, +{ "label": "45/17", "node": 4244, "naklon": 5 }, +{ "label": "45/18", "node": 4199, "naklon": 5 }, +{ "label": "45/19", "node": 4239, "naklon": 5 }, +{ "label": "45/20", "node": 4207, "naklon": 5 }, +{ "label": "45/21", "node": 4223, "naklon": 5 }, +{ "label": "45/22", "node": 4230, "naklon": 5 }, +{ "label": "45/23", "node": 4233, "naklon": 5 }, +{ "label": "45/24", "node": 4222, "naklon": 5 }, +{ "label": "45/25", "node": 4217, "naklon": 5 }, +{ "label": "45/26", "node": 4243, "naklon": 5 }, +{ "label": "45/27", "node": 4200, "naklon": 5 }, +{ "label": "45/28", "node": 4228, "naklon": 5 }, +{ "label": "45/29", "node": 4211, "naklon": 5 }, +{ "label": "45/30", "node": 4234, "naklon": 5 }, +{ "label": "45/31", "node": 4235, "naklon": 5 }, +{ "label": "45/32", "node": 4203, "naklon": 5 }, +{ "label": "45/33", "node": 4240, "naklon": 5 }, +{ "label": "45/34", "node": 4224, "naklon": 5 }, +{ "label": "45/35", "node": 4232, "naklon": 5 }, +{ "label": "45/36", "node": 4231, "naklon": 5 }, +{ "label": "45/37", "node": 4161, "naklon": 5 }, +{ "label": "45/38", "node": 4225, "naklon": 5 }, +{ "label": "45/39", "node": 4241, "naklon": 5 }, +{ "label": "45/40", "node": 4229, "naklon": 5 }, +{ "label": "45/41", "node": 4221, "naklon": 5 }, +{ "label": "45/42", "node": 4212, "naklon": 5 }, +{ "label": "45/43", "node": 4216, "naklon": 5 }, +{ "label": "45/44", "node": 3864, "naklon": null }, +{ "label": "46/1", "node": 3806, "naklon": 5 }, +{ "label": "46/2", "node": 3813, "naklon": 5 }, +{ "label": "46/3", "node": 3815, "naklon": 5 }, +{ "label": "46/4", "node": 3807, "naklon": 5 }, +{ "label": "46/5", "node": 3895, "naklon": 5 }, +{ "label": "46/6", "node": 3809, "naklon": 5 }, +{ "label": "46/7", "node": 3820, "naklon": 5 }, +{ "label": "46/8", "node": 3805, "naklon": 5 }, +{ "label": "46/9", "node": 3894, "naklon": 0 }, +{ "label": "46/10", "node": 4055, "naklon": 0 }, +{ "label": "46/11", "node": 3812, "naklon": 5 }, +{ "label": "46/12", "node": 3822, "naklon": 5 }, +{ "label": "46/13", "node": 3821, "naklon": 5 }, +{ "label": "46/14", "node": 3808, "naklon": 5 }, +{ "label": "46/15", "node": 3799, "naklon": 5 }, +{ "label": "46/16", "node": 3816, "naklon": 5 }, +{ "label": "46/17", "node": 3751, "naklon": 5 }, +{ "label": "46/18", "node": 3814, "naklon": 5 }, +{ "label": "46/19", "node": 4044, "naklon": 0 }, +{ "label": "46/20", "node": 3931, "naklon": 0 }, +{ "label": "46/21", "node": 3902, "naklon": 5 }, +{ "label": "46/22", "node": 3916, "naklon": 5 }, +{ "label": "46/23", "node": 3892, "naklon": 5 }, +{ "label": "46/24", "node": 3914, "naklon": 5 }, +{ "label": "46/25", "node": 3898, "naklon": 5 }, +{ "label": "46/26", "node": 3897, "naklon": 5 }, +{ "label": "46/27", "node": 3885, "naklon": 5 }, +{ "label": "46/28", "node": 3906, "naklon": 5 }, +{ "label": "46/29", "node": 3930, "naklon": 0 }, +{ "label": "46/30", "node": 3936, "naklon": 0 }, +{ "label": "46/31", "node": 3860, "naklon": 5 }, +{ "label": "46/32", "node": 3841, "naklon": 5 }, +{ "label": "46/33", "node": 3873, "naklon": 5 }, +{ "label": "46/34", "node": 3854, "naklon": 5 }, +{ "label": "46/35", "node": 3939, "naklon": 5 }, +{ "label": "46/36", "node": 3858, "naklon": 5 }, +{ "label": "46/37", "node": 3940, "naklon": 5 }, +{ "label": "46/38", "node": 4035, "naklon": 5 }, +{ "label": "47/1", "node": 3373, "naklon": 0 }, +{ "label": "47/2", "node": 3374, "naklon": 0 }, +{ "label": "47/3", "node": 3384, "naklon": 0 }, +{ "label": "47/4", "node": 3385, "naklon": 0 }, +{ "label": "48/1", "node": 4051, "naklon": 5 }, +{ "label": "48/2", "node": 4041, "naklon": 5 }, +{ "label": "48/3", "node": 4056, "naklon": 5 }, +{ "label": "48/4", "node": 3875, "naklon": 5 }, +{ "label": "48/5", "node": 4061, "naklon": 5 }, +{ "label": "48/6", "node": 4047, "naklon": 5 }, +{ "label": "48/7", "node": 4060, "naklon": 5 }, +{ "label": "48/8", "node": 4059, "naklon": 5 }, +{ "label": "48/9", "node": 4058, "naklon": 5 }, +{ "label": "48/10", "node": 3635, "naklon": 5 }, +{ "label": "48/11", "node": 3640, "naklon": 5 }, +{ "label": "48/12", "node": 3747, "naklon": 5 }, +{ "label": "48/13", "node": 3629, "naklon": 5 }, +{ "label": "48/14", "node": 4048, "naklon": 5 }, +{ "label": "48/15", "node": 4063, "naklon": 5 }, +{ "label": "48/16", "node": 4062, "naklon": 5 }, +{ "label": "48/17", "node": 4043, "naklon": 5 }, +{ "label": "48/18", "node": 4052, "naklon": 5 }, +{ "label": "48/19", "node": 4042, "naklon": 5 }, +{ "label": "48/20", "node": 4053, "naklon": 5 }, +{ "label": "50/15A", "node": 4167, "naklon": null }, +{ "label": "50/15B", "node": 4159, "naklon": null }, +{ "label": "50/1", "node": 4183, "naklon": 0 }, +{ "label": "50/2", "node": 4157, "naklon": 0 }, +{ "label": "50/3", "node": 4160, "naklon": 0 }, +{ "label": "50/4", "node": 4173, "naklon": 0 }, +{ "label": "50/5", "node": 4177, "naklon": 0 }, +{ "label": "50/6", "node": 4174, "naklon": 0 }, +{ "label": "50/7", "node": 4178, "naklon": 0 }, +{ "label": "50/8", "node": 4195, "naklon": 0 }, +{ "label": "50/9", "node": 4169, "naklon": 0 }, +{ "label": "50/10", "node": 4162, "naklon": 0 }, +{ "label": "50/11", "node": 4158, "naklon": 0 }, +{ "label": "50/12", "node": 4182, "naklon": 0 }, +{ "label": "50/13", "node": 4194, "naklon": 0 }, +{ "label": "50/14", "node": 4184, "naklon": 0 }, +{ "label": "50/16", "node": 4197, "naklon": null }, +{ "label": "50/17", "node": 4164, "naklon": null }, +{ "label": "50/18", "node": 3306, "naklon": null }, +{ "label": "50/19", "node": 4168, "naklon": null }, +{ "label": "50/20", "node": 4193, "naklon": null }, +{ "label": "50/21", "node": 4187, "naklon": null }, +{ "label": "50/22", "node": 4163, "naklon": null }, +{ "label": "50/23", "node": 4165, "naklon": null }, +{ "label": "50/24", "node": 4185, "naklon": null }, +{ "label": "50/25", "node": 3904, "naklon": null }, +{ "label": "53/1", "node": 2619, "naklon": 0 }, +{ "label": "53/2", "node": 2623, "naklon": 0 }, +{ "label": "53/3", "node": 2617, "naklon": 0 }, +{ "label": "53/4", "node": 2622, "naklon": 0 }, +{ "label": "53/5", "node": 2618, "naklon": 0 }, +{ "label": "53/6", "node": 2626, "naklon": 0 }, +{ "label": "53/7", "node": 2869, "naklon": 0 }, +{ "label": "53/8", "node": 2613, "naklon": 0 }, +{ "label": "53/9", "node": 2608, "naklon": 0 }, +{ "label": "53/10", "node": 2611, "naklon": 0 }, +{ "label": "53/11", "node": 2598, "naklon": 0 }, +{ "label": "53/12", "node": 3528, "naklon": 0 }, +{ "label": "53/13", "node": 3545, "naklon": 0 }, +{ "label": "53/14", "node": 2620, "naklon": 0 }, +{ "label": "53/15", "node": 2612, "naklon": 0 }, +{ "label": "53/16", "node": 2615, "naklon": 0 }, +{ "label": "53/17", "node": 3722, "naklon": 0 }, +{ "label": "53/18", "node": 2624, "naklon": 0 }, +{ "label": "53/19", "node": 2609, "naklon": 0 }, +{ "label": "53/20", "node": 2625, "naklon": 0 }, +{ "label": "53/21", "node": 2602, "naklon": 0 }, +{ "label": "53/22", "node": 2610, "naklon": 0 }, +{ "label": "53/23", "node": 2599, "naklon": 0 }, +{ "label": "53/24", "node": 2605, "naklon": 0 }, +{ "label": "53/25", "node": 2593, "naklon": 0 }, +{ "label": "53/26", "node": 3074, "naklon": 0 }, +{ "label": "53/27", "node": 2740, "naklon": 0 }, +{ "label": "53/28", "node": 2614, "naklon": 0 }, +{ "label": "53/29", "node": 2601, "naklon": 0 }, +{ "label": "53/30", "node": 4196, "naklon": 0 }, +{ "label": "53/31", "node": 2607, "naklon": 0 }, +{ "label": "53/32", "node": 2582, "naklon": 0 }, +{ "label": "53/33", "node": 2594, "naklon": 0 }, +{ "label": "53/34", "node": 2589, "naklon": 0 }, +{ "label": "53/35", "node": 2596, "naklon": 0 }, +{ "label": "53/36", "node": 2603, "naklon": 0 }, +{ "label": "53/37", "node": 2597, "naklon": 0 }, +{ "label": "53/38", "node": 2590, "naklon": 0 }, +{ "label": "53/39", "node": 2581, "naklon": 0 }, +{ "label": "53/40", "node": 2583, "naklon": 0 }, +{ "label": "53/41", "node": 2580, "naklon": 0 }, +{ "label": "53/42", "node": 2579, "naklon": 0 }, +{ "label": "53/43", "node": 2797, "naklon": 0 }, +{ "label": "53/44", "node": 2577, "naklon": 0 }, +{ "label": "53/45", "node": 2586, "naklon": 0 }, +{ "label": "53/46", "node": 2588, "naklon": 0 }, +{ "label": "53/47", "node": 2591, "naklon": 0 }, +{ "label": "53/48", "node": 2592, "naklon": 0 }, +{ "label": "53/49", "node": 2573, "naklon": 0 }, +{ "label": "53/50", "node": 2595, "naklon": 0 }, +{ "label": "53/51", "node": 2587, "naklon": 0 }, +{ "label": "53/52", "node": 2578, "naklon": 0 }, +{ "label": "53/53", "node": 2574, "naklon": 0 }, +{ "label": "53/54", "node": 2571, "naklon": 0 }, +{ "label": "53/55", "node": 2570, "naklon": 0 }, +{ "label": "53/56", "node": 2576, "naklon": 0 }, +{ "label": "53/57", "node": 2881, "naklon": 0 }, +{ "label": "53/58", "node": 2575, "naklon": 0 }, +{ "label": "53/59", "node": 2572, "naklon": 0 }, +{ "label": "53/60", "node": 2569, "naklon": 0 }, +{ "label": "55/1", "node": 4324, "naklon": 0 }, +{ "label": "55/2", "node": 4319, "naklon": 0 }, +{ "label": "55/3", "node": 4327, "naklon": 0 }, +{ "label": "55/4", "node": 4333, "naklon": 0 }, +{ "label": "55/5", "node": 4332, "naklon": 0 }, +{ "label": "55/6", "node": 4320, "naklon": 0 }, +{ "label": "55/7", "node": 4317, "naklon": 0 }, +{ "label": "55/8", "node": 4318, "naklon": 0 }, +{ "label": "55/9", "node": 4328, "naklon": 0 }, +{ "label": "55/10", "node": 4323, "naklon": 0 }, +{ "label": "55/11", "node": 4325, "naklon": 0 }, +{ "label": "55/12", "node": 4326, "naklon": 0 }, +{ "label": "55/13", "node": 4316, "naklon": 0 }, +{ "label": "55/14", "node": 4322, "naklon": 0 }, +{ "label": "55/15", "node": 4331, "naklon": 0 }, +{ "label": "55/16", "node": 4321, "naklon": 0 }, +{ "label": "55/17", "node": 4315, "naklon": 0 }, +{ "label": "55/18", "node": 4329, "naklon": 0 }, +{ "label": "55/19", "node": 4334, "naklon": 0 }, +{ "label": "55/20", "node": 4330, "naklon": 0 } +]; + +module.exports = { naklony }; diff --git a/RVO25/databases/modbus_config.js b/RVO25/databases/modbus_config.js new file mode 100755 index 0000000..b73116a --- /dev/null +++ b/RVO25/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/RVO25/databases/nodes.table b/RVO25/databases/nodes.table new file mode 100755 index 0000000..f2fb758 --- /dev/null +++ b/RVO25/databases/nodes.table @@ -0,0 +1,110 @@ +node:number|pole_number:string|node_type:string|tbname:string|line:number|profile:string|processed:boolean|status:boolean|time_of_last_communication:number ++|3203|41|NEMA|Nzp2OoJlqn6r1ZgvdA3B2Y7abBwP5G4eE3RQmyxD|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":13,"dusk_lux_sensor_value":13,"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|1760574011686|............. ++|3212|18|NEMA|d5xjWYMwEJon6rLlK7yENX7qgV4DaOeNB9ZX3Gzb|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":13,"dusk_lux_sensor_value":13,"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|1760574162934|............. ++|3919|77|NEMA|d9x2V5LGYBzXp4mMRAOm5ekPloaqJwnQj6DgrNe3|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":13,"dusk_lux_sensor_value":13,"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|1760574113003|............. ++|3927|17|NEMA|dz4ojlpP85JMgDLZWkQJpr7aKYqQexEr62GXRV1y|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":13,"dusk_lux_sensor_value":13,"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|1760573746058|............. ++|4299|67|NEMA|RvmwNz8QPblKp41GD7lK9pkJrLVYoBO92dMegn6W|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":13,"dusk_lux_sensor_value":13,"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|1760573814056|............. ++|4353|85|NEMA|Nzp2OoJlqn6r1ZgvdA3BwY7abBwP5G4eE3RQmyxD|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":13,"dusk_lux_sensor_value":13,"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|1760573816982|............. ++|3912|13|NEMA|3JjOWdylwgNLzxVab7NapxkZ2vG64rq8PEB5QmDo|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":13,"dusk_lux_sensor_value":13,"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|1760573661240|............. ++|3913|53|NEMA|zrR51V2ajQ9ZLygPKkEMQ4kYDq38xOJolENBXGnv|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":13,"dusk_lux_sensor_value":13,"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|1760574109806|............. ++|3917|31|NEMA|52dD6ZlV1QaOpRBmbAqGDrkKnGzWMLj4eJq38Pgo|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":13,"dusk_lux_sensor_value":13,"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|1760574109982|............. ++|3918|29|NEMA|Nzp2OoJlqn6r1ZgvdA3Be57abBwP5G4eE3RQmyxD|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":13,"dusk_lux_sensor_value":13,"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|1760574112684|............. ++|3921|15|NEMA|1JMYvnx2RzKEo4aWQ7DGpQkL8yZV3m9NBePXbrdj|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":13,"dusk_lux_sensor_value":13,"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|1760574164165|............. ++|3922|12|NEMA|RO8rjaBDy21qPQJzW7omNp0pK3xmNleVZg9Ed4Gw|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":13,"dusk_lux_sensor_value":13,"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|1760574122804|............. ++|3923|52|NEMA|5dBNwRp9graYJxZn409NZrklVov1b2QLPDqGm6XK|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":13,"dusk_lux_sensor_value":13,"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|1760574131341|............. ++|3924|78|NEMA|B5EoxeMVp4zwr8nqW0GBMeARjvD1PNamOGbLg63Z|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":13,"dusk_lux_sensor_value":13,"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|1760573657723|............. ++|3928|30|NEMA|PLBJzmK1r3Gynd6OW0gKem0e5wV4vx9bDEqNgYR8|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":13,"dusk_lux_sensor_value":13,"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|1760574289768|............. ++|3932|51|NEMA|WlVJBygjDZMeKX3vnAMRQ208NqdmG2x1Y69LQ4P5|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":13,"dusk_lux_sensor_value":13,"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|1760574289976|............. ++|3933|14|NEMA|Z5KyJe9nEg1QNbWlX0w4NNkoDjBLdqzR83VGv624|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":13,"dusk_lux_sensor_value":13,"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|1760574195102|............. ++|3937|35|NEMA|nJL5lPMwBx23YpqRe0rp4p7damXvWVbOrD4gNzy8|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":13,"dusk_lux_sensor_value":13,"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|1760574292230|............. ++|3941|69|NEMA|3JjOWdylwgNLzxVab7NaQykZ2vG64rq8PEB5QmDo|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":13,"dusk_lux_sensor_value":13,"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|1760573799235|............. ++|4022|34|NEMA|roKgWqY95V3mXMRzyAjKYr0bLjexpJPvaGDBw826|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":13,"dusk_lux_sensor_value":13,"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|1760573796581|............. ++|4029|32|NEMA|rDbQ84xzwgdqEoPm3kbEgZ09anOZY1RXyBv2LVM6|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":13,"dusk_lux_sensor_value":13,"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|1760573798387|............. ++|4038|33|NEMA|E6Kg9oDnLWyzPRMva7v5RwkJxp4VG58qO2w1lZYe|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":13,"dusk_lux_sensor_value":13,"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|1760574298258|............. ++|4064|101|NEMA|apKVJBwOyrP35m2lv7KYZq0YXbeWNd64En9GxRqg|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":13,"dusk_lux_sensor_value":13,"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|1760573686150|............. ++|3496|64|NEMA|g9OxBZ5KRwNznlY6pAppKPAWXvjdEL4eGQobMDy2|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":13,"dusk_lux_sensor_value":13,"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|1760573968038|............. ++|4068|71|NEMA|1JMYvnx2RzKEo4aWQ7DGQVkL8yZV3m9NBePXbrdj|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":13,"dusk_lux_sensor_value":13,"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|1760574112156|............. ++|4069|99|NEMA|BaY3Xpy1EbKGjLq2O7maPD7rx8owgQz9P4dDJRmN|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":13,"dusk_lux_sensor_value":13,"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|1760574153565|............. ++|4351|60|NEMA|pE5X8NQPaow6vlOZxk6a910q42ezGBMyWgDVjR3L|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":13,"dusk_lux_sensor_value":13,"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|1760573815415|............. ++|4071|62|NEMA|m6EYyZoJ4gWexdjVPAR5QP7RDOq9wv2N5XzKGplr|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":13,"dusk_lux_sensor_value":13,"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|1760574114154|............. ++|4072|105|NEMA|pE5X8NQPaow6vlOZxk6a110q42ezGBMyWgDVjR3L|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":13,"dusk_lux_sensor_value":13,"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|1760574115769|............. ++|4073|72|NEMA|PjLblDgRBO6WQqnxmkJ1QY0Jv3ewZN4p5a89yKdY|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":13,"dusk_lux_sensor_value":13,"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|1760574116681|............. ++|4075|61|NEMA|6lQGaY9RDywdVzObj0PaGjkPg4NBn3exEK51LWZq|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":13,"dusk_lux_sensor_value":13,"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|1760574117128|............. ++|4078|95|NEMA|WlVJBygjDZMeKX3vnAMRe208NqdmG2x1Y69LQ4P5|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":13,"dusk_lux_sensor_value":13,"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|1760574155804|............. ++|4084|98|NEMA|zrR51V2ajQ9ZLygPKkEM24kYDq38xOJolENBXGnv|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":13,"dusk_lux_sensor_value":13,"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|1760574123044|............. ++|4088|96|NEMA|5dBNwRp9graYJxZn409NVrklVov1b2QLPDqGm6XK|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":13,"dusk_lux_sensor_value":13,"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|1760574123875|............. ++|4188|100|NEMA|DbQY6zyveZRwK5drV0Z8gR7joE4XJM83N9xl2nWq|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":13,"dusk_lux_sensor_value":13,"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|1760574124739|............. ++|4189|55|NEMA|DbQY6zyveZRwK5drV0Z8QR7joE4XJM83N9xl2nWq|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":13,"dusk_lux_sensor_value":13,"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|1760573809787|............. ++|4190|58|NEMA|gP1eOZVj3Q9lv5aDEk45Y47rdpqW8yLm2BbKzJxM|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":13,"dusk_lux_sensor_value":13,"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|1760573809931|............. ++|4191|56|NEMA|apKVJBwOyrP35m2lv7KYQq0YXbeWNd64En9GxRqg|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":13,"dusk_lux_sensor_value":13,"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|1760573810475|............. ++|4293|76|Kamera|K94XLav1glVRnyQ6r01PwNAme3YJwBxM5oOzdP2j|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":13,"dusk_lux_sensor_value":13,"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|1760573811274|............. ++|4294|21|NEMA|d9x2V5LGYBzXp4mMRAOmpXkPloaqJwnQj6DgrNe3|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":13,"dusk_lux_sensor_value":13,"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|1760573812585|............. ++|4295|66|NEMA|B5EoxeMVp4zwr8nqW0GBgaARjvD1PNamOGbLg63Z|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":13,"dusk_lux_sensor_value":13,"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|1760574130334|............. ++|4296|74|NEMA|d5xjWYMwEJon6rLlK7yEoJ7qgV4DaOeNB9ZX3Gzb|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":13,"dusk_lux_sensor_value":13,"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|1760573813560|............. ++|4297|65|NEMA|OzNMgZ9n43qPbjXmy7zwoYA2DKdYvW5e6pxGRrVa|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":13,"dusk_lux_sensor_value":13,"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|1760573813720|............. ++|4300|16|NEMA|PjLblDgRBO6WQqnxmkJ1pm0Jv3ewZN4p5a89yKdY|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":13,"dusk_lux_sensor_value":13,"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|1760574132093|............. ++|4301|42|NEMA|PLBJzmK1r3Gynd6OW0gKrY0e5wV4vx9bDEqNgYR8|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":13,"dusk_lux_sensor_value":13,"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|1760573814600|............. ++|4302|59|NEMA|2O14VBzl8aDmWdNw3A59MMAGyZ5qLJoEMpj6R9ng|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":13,"dusk_lux_sensor_value":13,"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|1760573815175|............. ++|2819|82|03-Repeater|3a5oqJN1bgnx4Ol9dk89xa7ByE6jQ8mKDWMpGrLV|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":13,"dusk_lux_sensor_value":13,"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|1760573713730|............. ++|3190|36|NEMA|ZmRwd93QL4gaezxEbAx2oWk1prn2XjlPvGyqJ6BO|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":13,"dusk_lux_sensor_value":13,"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|1760573819908|............. ++|3191|40|NEMA|wvKJdZML6mXP4DzWBAXxQzAjxNloa5g23Ve9Y1ry|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":13,"dusk_lux_sensor_value":13,"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|1760574214241|............. ++|3193|39|NEMA|EjgWGnXaLy9opPOz20n4mn786BlYM3w1deVQvbKr|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":13,"dusk_lux_sensor_value":13,"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|1760574220380|............. ++|3194|46|NEMA|roKgWqY95V3mXMRzyAjKY30bLjexpJPvaGDBw826|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":13,"dusk_lux_sensor_value":13,"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|1760574223658|............. ++|3198|47|NEMA|nJL5lPMwBx23YpqRe0rp437damXvWVbOrD4gNzy8|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":13,"dusk_lux_sensor_value":13,"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|1760574227783|............. ++|3200|49|NEMA|gYbDLqlyZVoRerQpB72MdRkWJnwM5z24POKa8Exj|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":13,"dusk_lux_sensor_value":13,"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|1760573823425|............. ++|3201|38|NEMA|3a5oqJN1bgnx4Ol9dk89ma7ByE6jQ8mKDWMpGrLV|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":13,"dusk_lux_sensor_value":13,"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|1760574229797|............. ++|3202|44|NEMA|rDbQ84xzwgdqEoPm3kbEgL09anOZY1RXyBv2LVM6|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":13,"dusk_lux_sensor_value":13,"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|1760573869871|............. ++|3204|48|NEMA|XMBbew5z4ELrZa2mRAd3b178vPN6gy3DdVYlpKjq|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":13,"dusk_lux_sensor_value":13,"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|1760574012006|............. ++|3205|45|NEMA|E6Kg9oDnLWyzPRMva7v5RBkJxp4VG58qO2w1lZYe|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":13,"dusk_lux_sensor_value":13,"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|1760574013333|............. ++|3206|28|NEMA|wvKJdZML6mXP4DzWBAXxgpAjxNloa5g23Ve9Y1ry|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":13,"dusk_lux_sensor_value":13,"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|1760574013877|............. ++|3207|20|NEMA|K94XLav1glVRnyQ6r01PZRAme3YJwBxM5oOzdP2j|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":13,"dusk_lux_sensor_value":13,"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|1760574015108|............. ++|3208|19|NEMA|gRoJEyXVx4qD9er287L4pL7wBzGldaPjLWQKm3Mv|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":13,"dusk_lux_sensor_value":13,"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|1760573963786|............. ++|3209|22|NEMA|B5EoxeMVp4zwr8nqW0GBGvARjvD1PNamOGbLg63Z|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":13,"dusk_lux_sensor_value":13,"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|1760573965033|............. ++|3210|26|NEMA|3a5oqJN1bgnx4Ol9dk89wz7ByE6jQ8mKDWMpGrLV|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":13,"dusk_lux_sensor_value":13,"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|1760573965369|............. ++|3211|27|NEMA|EjgWGnXaLy9opPOz20n4NX786BlYM3w1deVQvbKr|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":13,"dusk_lux_sensor_value":13,"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|1760573965592|............. ++|3215|25|NEMA|eod9aRWLVl34Gx1Dn7VNXy72rz6qjgmpEXwQJN5Z|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":13,"dusk_lux_sensor_value":13,"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|1760573966056|............. ++|3216|50|NEMA|zdQO8GwxDqjRgP4137YVQGANyKlpem2nL65rvVJY|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":13,"dusk_lux_sensor_value":13,"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|1760573966488|............. ++|3223|43|NEMA|52dD6ZlV1QaOpRBmbAqGexkKnGzWMLj4eJq38Pgo|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":13,"dusk_lux_sensor_value":13,"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|1760573966664|............. ++|3884|106|IP65|6lQGaY9RDywdVzObj0Pa6jkPg4NBn3exEK51LWZq|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":13,"dusk_lux_sensor_value":13,"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|1760574245225|............. ++|4034|104|NEMA|2O14VBzl8aDmWdNw3A59wMAGyZ5qLJoEMpj6R9ng|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":13,"dusk_lux_sensor_value":13,"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|1760574297154|............. ++|3745|23|NEMA|aw4eELG2DlPMdn1JW0BMpeAqQXOZRN3xB5yp8VKr|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":13,"dusk_lux_sensor_value":13,"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|1760573972035|............. ++|3748|91|NEMA|nJL5lPMwBx23YpqRe0rp837damXvWVbOrD4gNzy8|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":13,"dusk_lux_sensor_value":13,"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|1760573972419|............. ++|3749|3|NEMA|2O14VBzl8aDmWdNw3A595mAGyZ5qLJoEMpj6R9ng|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":13,"dusk_lux_sensor_value":13,"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|1760574248823|............. ++|3752|84|NEMA|wvKJdZML6mXP4DzWBAXxBzAjxNloa5g23Ve9Y1ry|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":13,"dusk_lux_sensor_value":13,"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|1760573843027|............. ++|3753|92|NEMA|XMBbew5z4ELrZa2mRAd39178vPN6gy3DdVYlpKjq|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":13,"dusk_lux_sensor_value":13,"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|1760573973411|............. ++|3758|8|NEMA|g9OxBZ5KRwNznlY6pAppNLAWXvjdEL4eGQobMDy2|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":13,"dusk_lux_sensor_value":13,"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|1760574251125|............. ++|3760|88|NEMA|rDbQ84xzwgdqEoPm3kbEYL09anOZY1RXyBv2LVM6|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":13,"dusk_lux_sensor_value":13,"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|1760574251477|............. ++|3761|7|NEMA|JzwxZXOvDj1bVrN4nkW53XA8qdyBl3MRKLpGPgaQ|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":13,"dusk_lux_sensor_value":13,"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|1760574254898|............. ++|3762|24|NEMA|ZmRwd93QL4gaezxEbAx2Nek1prn2XjlPvGyqJ6BO|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":13,"dusk_lux_sensor_value":13,"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|1760573970581|............. ++|2651|89|NEMA|E6Kg9oDnLWyzPRMva7v5gBkJxp4VG58qO2w1lZYe|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":13,"dusk_lux_sensor_value":13,"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|1760573817365|............. ++|3765|5|NEMA|6lQGaY9RDywdVzObj0PapDkPg4NBn3exEK51LWZq|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":13,"dusk_lux_sensor_value":13,"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|1760574168242|............. ++|3766|9|NEMA|OzNMgZ9n43qPbjXmy7zwNXA2DKdYvW5e6pxGRrVa|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":13,"dusk_lux_sensor_value":13,"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|1760574168898|............. ++|3769|4|02-Repeater|pE5X8NQPaow6vlOZxk6a680q42ezGBMyWgDVjR3L|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":13,"dusk_lux_sensor_value":13,"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|1760574169889|............. ++|3770|87|NEMA|52dD6ZlV1QaOpRBmbAqGVxkKnGzWMLj4eJq38Pgo|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":13,"dusk_lux_sensor_value":13,"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|1760574170337|............. ++|3771|1|NEMA|o9vbeQlLMVg8j5dq4keLZ60NxZpEmnXzwYKO1ar2|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":13,"dusk_lux_sensor_value":13,"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|1760574171200|............. ++|3772|68|NEMA|RO8rjaBDy21qPQJzW7omZd0pK3xmNleVZg9Ed4Gw|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":13,"dusk_lux_sensor_value":13,"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|1760573853115|............. ++|3775|93|NEMA|gYbDLqlyZVoRerQpB72MwRkWJnwM5z24POKa8Exj|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":13,"dusk_lux_sensor_value":13,"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|1760574202857|............. ++|3776|83|NEMA|EjgWGnXaLy9opPOz20n4Rn786BlYM3w1deVQvbKr|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":13,"dusk_lux_sensor_value":13,"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|1760573787180|............. ++|3777|2|NEMA|gP1eOZVj3Q9lv5aDEk454R7rdpqW8yLm2BbKzJxM|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":13,"dusk_lux_sensor_value":13,"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|1760574212322|............. ++|2670|94|NEMA|zdQO8GwxDqjRgP4137YV3GANyKlpem2nL65rvVJY|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":13,"dusk_lux_sensor_value":13,"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|1760573818357|............. ++|3779|10|NEMA|JX1ObgmqGZ54DMyYL7aDMKkEVdve38WKRzwjNrQ9|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":13,"dusk_lux_sensor_value":13,"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|1760573792840|............. ++|3780|103|NEMA|gP1eOZVj3Q9lv5aDEk45w47rdpqW8yLm2BbKzJxM|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":13,"dusk_lux_sensor_value":13,"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|1760574223865|............. ++|3782|70|NEMA|Z5KyJe9nEg1QNbWlX0w4o9koDjBLdqzR83VGv624|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":13,"dusk_lux_sensor_value":13,"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|1760573859687|............. ++|3784|63|NEMA|JzwxZXOvDj1bVrN4nkW5QLA8qdyBl3MRKLpGPgaQ|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":13,"dusk_lux_sensor_value":13,"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|1760574235441|............. ++|3785|6|NEMA|m6EYyZoJ4gWexdjVPAR5xl7RDOq9wv2N5XzKGplr|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":13,"dusk_lux_sensor_value":13,"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|1760574237183|............. ++|3790|57|NEMA|o9vbeQlLMVg8j5dq4keLv50NxZpEmnXzwYKO1ar2|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":13,"dusk_lux_sensor_value":13,"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|1760574237599|............. ++|3791|86|NEMA|PLBJzmK1r3Gynd6OW0gKZY0e5wV4vx9bDEqNgYR8|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":13,"dusk_lux_sensor_value":13,"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|1760573804511|............. ++|3792|102|NEMA|o9vbeQlLMVg8j5dq4keLE50NxZpEmnXzwYKO1ar2|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":13,"dusk_lux_sensor_value":13,"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|1760574240077|............. ++|3793|107|NEMA|m6EYyZoJ4gWexdjVPAR5RP7RDOq9wv2N5XzKGplr|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":13,"dusk_lux_sensor_value":13,"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|1760574240253|............. ++|3855|109|NEMA|g9OxBZ5KRwNznlY6pAppxPAWXvjdEL4eGQobMDy2|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":13,"dusk_lux_sensor_value":13,"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|1760574242492|............. ++|3856|97|NEMA|ZmRwd93QL4gaezxEbAx23Kk1prn2XjlPvGyqJ6BO|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":13,"dusk_lux_sensor_value":13,"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|1760574244154|............. ++|3863|108|NEMA|JzwxZXOvDj1bVrN4nkW5nLA8qdyBl3MRKLpGPgaQ|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":13,"dusk_lux_sensor_value":13,"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|1760574245018|............. ++|3896|80|NEMA|ZmRwd93QL4gaezxEbAx2bWk1prn2XjlPvGyqJ6BO|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":13,"dusk_lux_sensor_value":13,"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|1760573706359|............. ++|3899|11|NEMA|RvmwNz8QPblKp41GD7lKNnkJrLVYoBO92dMegn6W|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":13,"dusk_lux_sensor_value":13,"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|1760573709349|............. ++|3900|54|NEMA|BaY3Xpy1EbKGjLq2O7maED7rx8owgQz9P4dDJRmN|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":13,"dusk_lux_sensor_value":13,"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|1760574128320|............. ++|3901|73|NEMA|dz4ojlpP85JMgDLZWkQJQd7aKYqQexEr62GXRV1y|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":13,"dusk_lux_sensor_value":13,"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|1760574130686|............. ++|3909|79|NEMA|aw4eELG2DlPMdn1JW0BMjMAqQXOZRN3xB5yp8VKr|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":13,"dusk_lux_sensor_value":13,"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|1760574131166|............. ++|3910|75|Wifi|gRoJEyXVx4qD9er287L4Q57wBzGldaPjLWQKm3Mv|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":13,"dusk_lux_sensor_value":13,"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|1760574133356|............. ++|3911|81|NEMA|eod9aRWLVl34Gx1Dn7VN8P72rz6qjgmpEXwQJN5Z|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":13,"dusk_lux_sensor_value":13,"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|1760573721532|............. ++|3835|37|NEMA|eod9aRWLVl34Gx1Dn7VNQP72rz6qjgmpEXwQJN5Z|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":13,"dusk_lux_sensor_value":13,"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|1760573990118|............. ++|3738|90|NEMA|roKgWqY95V3mXMRzyAjK430bLjexpJPvaGDBw826|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":13,"dusk_lux_sensor_value":13,"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|1760573969685|. diff --git a/RVO25/databases/nodes_original/nodes_original.table b/RVO25/databases/nodes_original/nodes_original.table new file mode 100755 index 0000000..1768741 --- /dev/null +++ b/RVO25/databases/nodes_original/nodes_original.table @@ -0,0 +1 @@ +[{"3203": "Nzp2OoJlqn6r1ZgvdA3B2Y7abBwP5G4eE3RQmyxD"}, {"3212": "d5xjWYMwEJon6rLlK7yENX7qgV4DaOeNB9ZX3Gzb"}, {"3919": "d9x2V5LGYBzXp4mMRAOm5ekPloaqJwnQj6DgrNe3"}, {"3927": "dz4ojlpP85JMgDLZWkQJpr7aKYqQexEr62GXRV1y"}, {"4299": "RvmwNz8QPblKp41GD7lK9pkJrLVYoBO92dMegn6W"}, {"4353": "Nzp2OoJlqn6r1ZgvdA3BwY7abBwP5G4eE3RQmyxD"}, {"3912": "3JjOWdylwgNLzxVab7NapxkZ2vG64rq8PEB5QmDo"}, {"3913": "zrR51V2ajQ9ZLygPKkEMQ4kYDq38xOJolENBXGnv"}, {"3917": "52dD6ZlV1QaOpRBmbAqGDrkKnGzWMLj4eJq38Pgo"}, {"3918": "Nzp2OoJlqn6r1ZgvdA3Be57abBwP5G4eE3RQmyxD"}, {"3921": "1JMYvnx2RzKEo4aWQ7DGpQkL8yZV3m9NBePXbrdj"}, {"3922": "RO8rjaBDy21qPQJzW7omNp0pK3xmNleVZg9Ed4Gw"}, {"3923": "5dBNwRp9graYJxZn409NZrklVov1b2QLPDqGm6XK"}, {"3924": "B5EoxeMVp4zwr8nqW0GBMeARjvD1PNamOGbLg63Z"}, {"3928": "PLBJzmK1r3Gynd6OW0gKem0e5wV4vx9bDEqNgYR8"}, {"3932": "WlVJBygjDZMeKX3vnAMRQ208NqdmG2x1Y69LQ4P5"}, {"3933": "Z5KyJe9nEg1QNbWlX0w4NNkoDjBLdqzR83VGv624"}, {"3937": "nJL5lPMwBx23YpqRe0rp4p7damXvWVbOrD4gNzy8"}, {"3941": "3JjOWdylwgNLzxVab7NaQykZ2vG64rq8PEB5QmDo"}, {"4022": "roKgWqY95V3mXMRzyAjKYr0bLjexpJPvaGDBw826"}, {"4029": "rDbQ84xzwgdqEoPm3kbEgZ09anOZY1RXyBv2LVM6"}, {"4038": "E6Kg9oDnLWyzPRMva7v5RwkJxp4VG58qO2w1lZYe"}, {"4064": "apKVJBwOyrP35m2lv7KYZq0YXbeWNd64En9GxRqg"}, {"3496": "g9OxBZ5KRwNznlY6pAppKPAWXvjdEL4eGQobMDy2"}, {"4068": "1JMYvnx2RzKEo4aWQ7DGQVkL8yZV3m9NBePXbrdj"}, {"4069": "BaY3Xpy1EbKGjLq2O7maPD7rx8owgQz9P4dDJRmN"}, {"4351": "pE5X8NQPaow6vlOZxk6a910q42ezGBMyWgDVjR3L"}, {"4071": "m6EYyZoJ4gWexdjVPAR5QP7RDOq9wv2N5XzKGplr"}, {"4072": "pE5X8NQPaow6vlOZxk6a110q42ezGBMyWgDVjR3L"}, {"4073": "PjLblDgRBO6WQqnxmkJ1QY0Jv3ewZN4p5a89yKdY"}, {"4075": "6lQGaY9RDywdVzObj0PaGjkPg4NBn3exEK51LWZq"}, {"4078": "WlVJBygjDZMeKX3vnAMRe208NqdmG2x1Y69LQ4P5"}, {"4084": "zrR51V2ajQ9ZLygPKkEM24kYDq38xOJolENBXGnv"}, {"4088": "5dBNwRp9graYJxZn409NVrklVov1b2QLPDqGm6XK"}, {"4188": "DbQY6zyveZRwK5drV0Z8gR7joE4XJM83N9xl2nWq"}, {"4189": "DbQY6zyveZRwK5drV0Z8QR7joE4XJM83N9xl2nWq"}, {"4190": "gP1eOZVj3Q9lv5aDEk45Y47rdpqW8yLm2BbKzJxM"}, {"4191": "apKVJBwOyrP35m2lv7KYQq0YXbeWNd64En9GxRqg"}, {"4293": "K94XLav1glVRnyQ6r01PwNAme3YJwBxM5oOzdP2j"}, {"4294": "d9x2V5LGYBzXp4mMRAOmpXkPloaqJwnQj6DgrNe3"}, {"4295": "B5EoxeMVp4zwr8nqW0GBgaARjvD1PNamOGbLg63Z"}, {"4296": "d5xjWYMwEJon6rLlK7yEoJ7qgV4DaOeNB9ZX3Gzb"}, {"4297": "OzNMgZ9n43qPbjXmy7zwoYA2DKdYvW5e6pxGRrVa"}, {"4300": "PjLblDgRBO6WQqnxmkJ1pm0Jv3ewZN4p5a89yKdY"}, {"4301": "PLBJzmK1r3Gynd6OW0gKrY0e5wV4vx9bDEqNgYR8"}, {"4302": "2O14VBzl8aDmWdNw3A59MMAGyZ5qLJoEMpj6R9ng"}, {"2819": "3a5oqJN1bgnx4Ol9dk89xa7ByE6jQ8mKDWMpGrLV"}, {"3190": "ZmRwd93QL4gaezxEbAx2oWk1prn2XjlPvGyqJ6BO"}, {"3191": "wvKJdZML6mXP4DzWBAXxQzAjxNloa5g23Ve9Y1ry"}, {"3193": "EjgWGnXaLy9opPOz20n4mn786BlYM3w1deVQvbKr"}, {"3194": "roKgWqY95V3mXMRzyAjKY30bLjexpJPvaGDBw826"}, {"3198": "nJL5lPMwBx23YpqRe0rp437damXvWVbOrD4gNzy8"}, {"3200": "gYbDLqlyZVoRerQpB72MdRkWJnwM5z24POKa8Exj"}, {"3201": "3a5oqJN1bgnx4Ol9dk89ma7ByE6jQ8mKDWMpGrLV"}, {"3202": "rDbQ84xzwgdqEoPm3kbEgL09anOZY1RXyBv2LVM6"}, {"3204": "XMBbew5z4ELrZa2mRAd3b178vPN6gy3DdVYlpKjq"}, {"3205": "E6Kg9oDnLWyzPRMva7v5RBkJxp4VG58qO2w1lZYe"}, {"3206": "wvKJdZML6mXP4DzWBAXxgpAjxNloa5g23Ve9Y1ry"}, {"3207": "K94XLav1glVRnyQ6r01PZRAme3YJwBxM5oOzdP2j"}, {"3208": "gRoJEyXVx4qD9er287L4pL7wBzGldaPjLWQKm3Mv"}, {"3209": "B5EoxeMVp4zwr8nqW0GBGvARjvD1PNamOGbLg63Z"}, {"3210": "3a5oqJN1bgnx4Ol9dk89wz7ByE6jQ8mKDWMpGrLV"}, {"3211": "EjgWGnXaLy9opPOz20n4NX786BlYM3w1deVQvbKr"}, {"3215": "eod9aRWLVl34Gx1Dn7VNXy72rz6qjgmpEXwQJN5Z"}, {"3216": "zdQO8GwxDqjRgP4137YVQGANyKlpem2nL65rvVJY"}, {"3223": "52dD6ZlV1QaOpRBmbAqGexkKnGzWMLj4eJq38Pgo"}, {"3884": "6lQGaY9RDywdVzObj0Pa6jkPg4NBn3exEK51LWZq"}, {"4034": "2O14VBzl8aDmWdNw3A59wMAGyZ5qLJoEMpj6R9ng"}, {"3745": "aw4eELG2DlPMdn1JW0BMpeAqQXOZRN3xB5yp8VKr"}, {"3748": "nJL5lPMwBx23YpqRe0rp837damXvWVbOrD4gNzy8"}, {"3749": "2O14VBzl8aDmWdNw3A595mAGyZ5qLJoEMpj6R9ng"}, {"3752": "wvKJdZML6mXP4DzWBAXxBzAjxNloa5g23Ve9Y1ry"}, {"3753": "XMBbew5z4ELrZa2mRAd39178vPN6gy3DdVYlpKjq"}, {"3758": "g9OxBZ5KRwNznlY6pAppNLAWXvjdEL4eGQobMDy2"}, {"3760": "rDbQ84xzwgdqEoPm3kbEYL09anOZY1RXyBv2LVM6"}, {"3761": "JzwxZXOvDj1bVrN4nkW53XA8qdyBl3MRKLpGPgaQ"}, {"3762": "ZmRwd93QL4gaezxEbAx2Nek1prn2XjlPvGyqJ6BO"}, {"2651": "E6Kg9oDnLWyzPRMva7v5gBkJxp4VG58qO2w1lZYe"}, {"3765": "6lQGaY9RDywdVzObj0PapDkPg4NBn3exEK51LWZq"}, {"3766": "OzNMgZ9n43qPbjXmy7zwNXA2DKdYvW5e6pxGRrVa"}, {"3769": "pE5X8NQPaow6vlOZxk6a680q42ezGBMyWgDVjR3L"}, {"3770": "52dD6ZlV1QaOpRBmbAqGVxkKnGzWMLj4eJq38Pgo"}, {"3771": "o9vbeQlLMVg8j5dq4keLZ60NxZpEmnXzwYKO1ar2"}, {"3772": "RO8rjaBDy21qPQJzW7omZd0pK3xmNleVZg9Ed4Gw"}, {"3775": "gYbDLqlyZVoRerQpB72MwRkWJnwM5z24POKa8Exj"}, {"3776": "EjgWGnXaLy9opPOz20n4Rn786BlYM3w1deVQvbKr"}, {"3777": "gP1eOZVj3Q9lv5aDEk454R7rdpqW8yLm2BbKzJxM"}, {"2670": "zdQO8GwxDqjRgP4137YV3GANyKlpem2nL65rvVJY"}, {"3779": "JX1ObgmqGZ54DMyYL7aDMKkEVdve38WKRzwjNrQ9"}, {"3780": "gP1eOZVj3Q9lv5aDEk45w47rdpqW8yLm2BbKzJxM"}, {"3782": "Z5KyJe9nEg1QNbWlX0w4o9koDjBLdqzR83VGv624"}, {"3784": "JzwxZXOvDj1bVrN4nkW5QLA8qdyBl3MRKLpGPgaQ"}, {"3785": "m6EYyZoJ4gWexdjVPAR5xl7RDOq9wv2N5XzKGplr"}, {"3790": "o9vbeQlLMVg8j5dq4keLv50NxZpEmnXzwYKO1ar2"}, {"3791": "PLBJzmK1r3Gynd6OW0gKZY0e5wV4vx9bDEqNgYR8"}, {"3792": "o9vbeQlLMVg8j5dq4keLE50NxZpEmnXzwYKO1ar2"}, {"3793": "m6EYyZoJ4gWexdjVPAR5RP7RDOq9wv2N5XzKGplr"}, {"3855": "g9OxBZ5KRwNznlY6pAppxPAWXvjdEL4eGQobMDy2"}, {"3856": "ZmRwd93QL4gaezxEbAx23Kk1prn2XjlPvGyqJ6BO"}, {"3863": "JzwxZXOvDj1bVrN4nkW5nLA8qdyBl3MRKLpGPgaQ"}, {"3896": "ZmRwd93QL4gaezxEbAx2bWk1prn2XjlPvGyqJ6BO"}, {"3899": "RvmwNz8QPblKp41GD7lKNnkJrLVYoBO92dMegn6W"}, {"3900": "BaY3Xpy1EbKGjLq2O7maED7rx8owgQz9P4dDJRmN"}, {"3901": "dz4ojlpP85JMgDLZWkQJQd7aKYqQexEr62GXRV1y"}, {"3909": "aw4eELG2DlPMdn1JW0BMjMAqQXOZRN3xB5yp8VKr"}, {"3910": "gRoJEyXVx4qD9er287L4Q57wBzGldaPjLWQKm3Mv"}, {"3911": "eod9aRWLVl34Gx1Dn7VN8P72rz6qjgmpEXwQJN5Z"}, {"3835": "eod9aRWLVl34Gx1Dn7VNQP72rz6qjgmpEXwQJN5Z"}, {"3738": "roKgWqY95V3mXMRzyAjK430bLjexpJPvaGDBw826"}] \ No newline at end of file diff --git a/RVO25/databases/notifications.table b/RVO25/databases/notifications.table new file mode 100755 index 0000000..f7c96cb --- /dev/null +++ b/RVO25/databases/notifications.table @@ -0,0 +1,41 @@ +key:string|weight:string|sk:string|en:string ++|switching_profile_point_applied_to_line|INFORMATIONAL|Aplikovaný bod spínacieho profilu na línií č. ${line} : ${value}|Switching profile point applied to line no. ${line} : ${value}|............... ++|dusk_has_occured|INFORMATIONAL|Nastal súmrak: ${value}|Dusk has occured: ${value}|............... ++|dawn_has_occured|INFORMATIONAL|Nastal úsvit: ${value}|Dawn has occured: ${value}|............... ++|dimming_profile_was_successfully_received_by_node|NOTICE|Stmievací profil bol úspešne prijatý nodom č. ${node}|Dimming profile was successfully received by node no. ${node}|............... ++|master_node_is_responding_again|NOTICE|Master node začal znovu odpovedať|Master node is responding again|............... ++|command_was_sent_from_terminal_interface|DEBUG|Z terminálu bol odoslaný príkaz|A command was sent from terminal interface|............... ++|master_node_is_not_responding|ALERT|Master node neodpovedá|Master node is not responding|............... ++|configuration_of_dimming_profile_to_node_failed|ALERT|Konfigurácia stmievacieho profilu pre node č. ${node} zlyhala|Configuration of dimming profile to node no. ${node} has failed|............... ++|circuit_breaker_was_turned_on_line|NOTICE|Zapnutie ističa na línii č. ${line}|Circuit breaker was turned on - line no. ${line}|............... ++|circuit_breaker_was_turned_off_line|ERROR|Vypnutie ističa na línií č. ${line}|Circuit breaker was turned off - line no. ${line}|............... ++|dimming_profile_was_processed_for_node|INFORMATIONAL|Stmievací profil bol spracovaný pre node č. ${node}|Dimming profile was processed for node no. ${node}|............... ++|switching_profile_was_processed_for_line|INFORMATIONAL|Spínací profil bol spracovaný pre líniu č. ${line}|Switching profile was processed for line no. ${line}|............... ++|thermometer_is_not_responding|WARNING|Teplomer neodpovedá|Thermometer is not responding|............... ++|thermometer_is_responding_again|NOTICE|Teplomer znovu odpovedá|Thermometer is responding again|............... ++|thermometer_sends_invalid_data|WARNING|Teplomer posiela neplatné hodnoty|Thermometer sends invalid data|............... ++|main_switch_has_been_turned_off|CRITICAL|Hlavný vypínač bol vypnutý|Main switch has been turned off|............... ++|main_switch_has_been_turned_on|NOTICE|Hlavný vypínač bol zapnutý|Main switch has been turned on|............... ++|power_supply_has_disconnected_input|ALERT|Napájací zdroj nemá napätie na vstupe|Power supply has disconnected input|............... ++|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_main_open|NOTICE|Hlavné dvere boli otvorené|Main door has been opened|............... ++|door_em_open|NOTICE|Dvere silovej časti boli otvorené|Power door has been opened|............... ++|door_main_open_without_permission|WARNING|Hlavné dvere boli otvorené bez povolenia - zapnutá siréna|Main door has been opened without permission - alarm is on|............... ++|door_em_open_without_permission|WARNING|Dvere silovej časti boli otvorené bez povolenia|Power door has been opened without permission|............... ++|door_main_close|NOTICE|Hlavné dvere boli zatvorené|Main door has been closed|............... ++|door_em_close|NOTICE|Dvere silovej časti boli zatvorené|Power door has been closed|............... ++|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|............... ++|electrometer_ok|NOTICE|Elektromer znovu odpovedá|Electrometer is responding again|............... ++|no_voltage_on_phase|CRITICAL|Na fáze č. ${phase} nie je napätie|No voltage detected on phase no. ${phase}|............... ++|voltage_on_phase_restored|NOTICE|Napätie na fáze č. ${phase} bolo obnovené|Voltage on phase no. ${phase} has been restored|............... ++|flow_start|NOTICE|FLOW bol spustený|FLOW has been started |............... ++|twilight_sensor_nok|ERROR|Sensor súmraku neodpovedá|Twilight sensor is not responding|............... ++|twilight_sensor_ok|NOTICE|Sensor súmraku znovu odpovedá|Twilight sensor is responding again|............... ++|lamps_have_turned_on|NOTICE|Lampy sa zapli|Lamps have turned on|............... ++|lamps_have_turned_off|NOTICE|Lampy sa vypli|Lamps have turned off|............... ++|flow_restart|NOTICE|FLOW bol reštartovaný|FLOW has been restarted|............... ++|nodes_db_changed|NOTICE|Zmena v node databáze|Node db has changed|............... diff --git a/RVO25/databases/pins.table b/RVO25/databases/pins.table new file mode 100755 index 0000000..100c15e --- /dev/null +++ b/RVO25/databases/pins.table @@ -0,0 +1,16 @@ +pin:string|type:string|line:number +*|input1_01|door_condition|0|........... +*|input1_02|rotary_switch_state|0|........... +*|input1_03|rotary_switch_state|0|........... +*|input1_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|........... +*|relay1_05|state_of_contactor|4|........... +*|relay1_06|state_of_contactor|5|........... +*|28F46E9D0E00008B|temperature|0|........... +*|twilight_sensor|twilight_sensor|0|........... diff --git a/RVO25/databases/relays.table b/RVO25/databases/relays.table new file mode 100755 index 0000000..87734c2 --- /dev/null +++ b/RVO25/databases/relays.table @@ -0,0 +1,7 @@ +line:number|tbname:string|contactor:number|profile:string ++|0|XMBbew5z4ELrZa2mRAd3RV78vPN6gy3DdVYlpKjq|1||........... ++|3|apKVJBwOyrP35m2lv7KYpV0YXbeWNd64En9GxRqg|9|{"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}|.......................................................................................................................................................................................................................................................................................................................................................................................................................................... ++|1|BaY3Xpy1EbKGjLq2O7maNY7rx8owgQz9P4dDJRmN|9|{"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|DbQY6zyveZRwK5drV0Z8BE7joE4XJM83N9xl2nWq|9|{"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}|....................................................................................................................................................................................................................................................................................................................................................................................... ++|4|K94XLav1glVRnyQ6r01PXyAme3YJwBxM5oOzdP2j|9|{"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}|.................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................. ++|5|d9x2V5LGYBzXp4mMRAOmwykPloaqJwnQj6DgrNe3|9|{"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}|.................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................. diff --git a/RVO25/databases/settings.table b/RVO25/databases/settings.table new file mode 100755 index 0000000..68b0a34 --- /dev/null +++ b/RVO25/databases/settings.table @@ -0,0 +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|project_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|cloud_topic:string|has_main_switch:boolean|daily_report:boolean|send_changed_node_numbers:boolean ++|rvo_senica_25_ip121|en|28.01FC9C0E0000|48.70826502|17.28455203|192.168.252.1|rvo_senica_25_ip121|PAUSKZDkIzRyvXkHIoxp|1883|0|60|unipi|ttyUSB0|1|20|5|6|3|u121|0|1|1|................................................... diff --git a/RVO25/databases/tbdata.nosql b/RVO25/databases/tbdata.nosql new file mode 100755 index 0000000..f9c10df --- /dev/null +++ b/RVO25/databases/tbdata.nosql @@ -0,0 +1,4 @@ +-"XMBbew5z4ELrZa2mRAd3RV78vPN6gy3DdVYlpKjq":[{"ts":1760535535450,"values":{"_event":{"type":"notice","status":"new","source":{"func":"modbus_reader","component":"1699965957410","component_name":"Modbus reader","edge":"XMBbew5z4ELrZa2mRAd3RV78vPN6gy3DdVYlpKjq"},"message":{"sk":"rvo_senica_25_ip121: FLOW bol reštartovaný","en":"rvo_senica_25_ip121: FLOW has been restarted"},"message_data":""}}}],"id":"3000399001fr71b"} +-"XMBbew5z4ELrZa2mRAd3RV78vPN6gy3DdVYlpKjq":[{"ts":1760535535545,"values":{"edge_fw_version":"2025-10-08","maintenance_mode":false}}],"id":"3000399002fr70b"} +-"XMBbew5z4ELrZa2mRAd3RV78vPN6gy3DdVYlpKjq":[{"ts":1760535535558,"values":{"statecode":2,"power_mode":"Automatic"}}],"id":"3000399004fr70b"} +-"XMBbew5z4ELrZa2mRAd3RV78vPN6gy3DdVYlpKjq":[{"ts":1760535535616,"values":{"_event":{"type":"notice","status":"new","source":{"func":"rsPort.open()","component":"1699963668903","component_name":"DIDO_Controller","edge":"XMBbew5z4ELrZa2mRAd3RV78vPN6gy3DdVYlpKjq"},"message":{"sk":"rvo_senica_25_ip121: FLOW bol spustený","en":"rvo_senica_25_ip121: FLOW has been started "},"message_data":""}}}],"id":"3000399006fr70b"} diff --git a/RVO25/databases/tbdatacloud.nosql b/RVO25/databases/tbdatacloud.nosql new file mode 100755 index 0000000..f279796 --- /dev/null +++ b/RVO25/databases/tbdatacloud.nosql @@ -0,0 +1,3 @@ +-"XMBbew5z4ELrZa2mRAd3RV78vPN6gy3DdVYlpKjq":[{"ts":1760535535545,"values":{"edge_fw_version":"2025-10-08","maintenance_mode":false}}],"id":"3000399003fr71b"} +-"XMBbew5z4ELrZa2mRAd3RV78vPN6gy3DdVYlpKjq":[{"ts":1760535535558,"values":{"statecode":2,"power_mode":"Automatic"}}],"id":"3000399005fr71b"} +-"XMBbew5z4ELrZa2mRAd3RV78vPN6gy3DdVYlpKjq":[{"ts":1760535535616,"values":{"_event":{"type":"notice","status":"new","source":{"func":"rsPort.open()","component":"1699963668903","component_name":"DIDO_Controller","edge":"XMBbew5z4ELrZa2mRAd3RV78vPN6gy3DdVYlpKjq"},"message":{"sk":"rvo_senica_25_ip121: FLOW bol spustený","en":"rvo_senica_25_ip121: FLOW has been started "},"message_data":""}}}],"id":"3000399007fr71b"} diff --git a/RVO25/databases/total_energy.js b/RVO25/databases/total_energy.js new file mode 100755 index 0000000..dde340e --- /dev/null +++ b/RVO25/databases/total_energy.js @@ -0,0 +1,38 @@ +//key is rvo_number, value is max energy when lamps are on +const total_energy = { + 1: 580, + 2: 1100, + 3: 3700, + 4: 4100, + 7: 360, + 12: 1700, + 13: 5400, + 14: 440, + 15: 6100, + 16: 4800, + 20: 1600, + 21: 1000, + 22: 2600, + 23: 1000, + 25: 2600, + 33: 240, + 34: 4000, + 35: 2700, + 36: 820, + 37: 1400, + 35: 3500, + 39: 1170, + 41: 740, + 42: 660, + 43: 4900, + 45: 930, + 46: 700, + 47: 1100, + 48: 1500, + 50: 3200, + 53: 1250, + 55: 1000, + 56: 5500 +} + +module.exports = total_energy; diff --git a/RVO25/debug.js b/RVO25/debug.js new file mode 100755 index 0000000..9818194 --- /dev/null +++ b/RVO25/debug.js @@ -0,0 +1,16 @@ +// =================================================== +// FOR DEVELOPMENT +// Total.js - framework for Node.js platform +// https://www.totaljs.com +// =================================================== + +const options = {}; + +// options.ip = '127.0.0.1'; +// options.port = parseInt(process.argv[2]); +// options.config = { name: 'Total.js' }; +// options.sleep = 3000; +// options.inspector = 9229; +// options.watch = ['private']; + +require('total.js/debug')(options); \ No newline at end of file diff --git a/RVO25/err.txt b/RVO25/err.txt new file mode 100755 index 0000000..5e99f74 --- /dev/null +++ b/RVO25/err.txt @@ -0,0 +1,51 @@ +[2024-10-25T13:16:03.832] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-25T14:16:48.882] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-25T15:17:24.180] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-25T16:18:28.591] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-25T17:19:46.559] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-25T18:20:25.751] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-25T19:21:16.567] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-25T20:21:24.715] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-25T21:21:46.398] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-25T22:22:17.819] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-25T23:22:39.532] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T00:23:18.689] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T01:23:59.781] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T02:24:46.681] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T03:25:12.264] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T04:26:01.110] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T05:26:15.067] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T06:26:34.816] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T07:27:19.796] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T08:28:08.718] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T09:28:36.273] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T10:29:07.710] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T11:29:31.381] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T12:30:06.724] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T13:30:34.271] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T14:31:21.265] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T15:31:58.537] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T16:32:43.568] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T17:33:38.258] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T18:34:23.271] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T19:35:06.374] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T20:35:55.296] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T21:36:44.181] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T22:37:21.435] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T23:37:47.066] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T00:38:16.609] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T01:38:51.928] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T02:39:36.898] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T02:40:08.384] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T03:40:35.990] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T04:40:59.794] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T05:41:40.985] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T06:42:06.623] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T07:42:34.199] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T08:43:19.275] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T09:43:52.639] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T10:44:16.306] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T11:45:14.910] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T12:46:01.902] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T13:46:41.083] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T14:47:00.861] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK diff --git a/RVO25/flow/cloudmqttconnect.js b/RVO25/flow/cloudmqttconnect.js new file mode 100755 index 0000000..b03491f --- /dev/null +++ b/RVO25/flow/cloudmqttconnect.js @@ -0,0 +1,357 @@ +exports.id = 'cloudmqttconnect'; +exports.title = 'Cloud connect mqtt'; +exports.group = 'MQTT'; +exports.color = '#888600'; +exports.version = '1.0.2'; +exports.icon = 'sign-out'; +exports.input = 2; +exports.output = 2; +exports.options = { host: 'tb-stage.worksys.io', port: 1883, clientid: "", username: "" }; + +exports.html = `
+
+
+
Hostname or IP address (if not empty - setting will override db setting)
+
+
+
Port
+
+
+
+
+
@(Client id)
+
+
+
topic
+
+
+
`; + + + +const { promisifyBuilder } = require('./helper/db_helper'); +const fs = require('fs'); +const mqtt = require('mqtt'); +const nosql = NOSQL('tbdatacloud'); + +const SEND_TO = { + debug: 0, + rpcCall: 1, +} + +//CONFIG +let saveTelemetryOnError = true;//backup_on_failure overrides this value +//------------------------ + +const noSqlFileSizeLimit = 4194304;//use 5MB - 4194304 +let insertNoSqlCounter = 0; +let insertBackupNoSqlCounter = 0; +let processingData = false; + +let backup_on_failure = true;//== saveTelemetryOnError - create backup client send failure +let restore_from_backup = 50; //how many rows process at once? +let restore_backup_wait = 3;//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; + + +exports.install = function(instance) { + + var client; + var opts; + var clientReady = false; + + let o = {}; //options + + function main() { + loadSettings(); + } + + //set opts according to db settings + function loadSettings() { + + o = instance.options; + if (!o.topic) o.topic = FLOW.GLOBALS.settings.cloud_topic; + + opts = { + host: o.host, + port: o.port, + clientId: o.clientid, + username: o.username, + rejectUnauthorized: false, + resubscribe: false + }; + + console.log("wsmqttpublich -> loadSettings from instance.options", o); + + if (!o.topic) { + instance.status("Not configured", "white"); + console.log("Cloud mqtt connect: no topic selected"); + return; + } + + connectToTbServer(); + } + + function connectToTbServer() { + var url = "mqtt://" + opts.host + ":" + opts.port; + console.log("MQTT URL: ", url); + + client = mqtt.connect(url, opts); + + client.on('connect', function() { + client.subscribe(`${o.topic}_backward`, (err) => { + if (!err) { + console.log("MQTT subscribed"); + } + }); + instance.status("Connected", "green"); + clientReady = true; + sendClientError = true; + }); + + client.on('reconnect', function() { + instance.status("Reconnecting", "yellow"); + clientReady = false; + }); + + client.on('message', function(topic, message) { + // message is type of buffer + message = message.toString(); + if (message[0] === '{') { + TRY(function() { + + message = JSON.parse(message); + if (message.hasOwnProperty("device") && message.hasOwnProperty("data") && message.data.hasOwnProperty("id")) { + client.publish(`${o.topic}_forward`, `{"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 } }); + } + + }, () => instance.debug('MQTT: Error parsing data', message)); + } + + instance.send(SEND_TO.rpcCall, { "topic": o.topic, "content": message }); + }); + + client.on('close', function() { + clientReady = false; + + instance.status("Disconnected", "red"); + instance.send(SEND_TO.debug, { "message": "Client CLOSE signal received !" }); + }); + + client.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) { + console.log('MQTT client error', err); + sendClientError = false; + } + clientReady = false; + }); + + } + + + instance.on('0', function(data) { + + if (clientReady) { + //do we have some data in backup file? if any, process data from database + if (saveTelemetryOnError) { + //read telemetry data and send back to server + if (!processingData) processDataFromDatabase(); + } + + let stringifiedJson = JSON.stringify(data.data) + client.publish(`${o.topic}_forward`, stringifiedJson, { qos: 1 }); + } + 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 (saveTelemetryOnError && o.topic) { + //create new file from tbdata.nosql, if file size exceeds given limit, and clear tbdata.nosql + makeBackupFromDbFile(); + + //write to tb + data.data.id = UID(); + nosql.insert(data.data); + } + } + }); + + instance.on("1", _ => { + main(); + }) + + instance.close = function(done) { + if (clientReady) { + client.end(); + } + }; + + + function getDbBackupFileCounter(type) { + var files = fs.readdirSync(__dirname + "/../databases"); + + let counter = 0; + for (var i = 0; i < files.length; i++) { + + if (files[i] == "tbdatacloud.nosql") continue; + + if (files[i].endsWith(".nosql")) { + + let pos = files[i].indexOf("."); + if (pos > -1) { + + let fileCounter = counter; + let firstDigit = files[i].slice(0, pos); + + fileCounter = parseInt(firstDigit); + if (isNaN(fileCounter)) fileCounter = 0; + //console.log("getDbBackupFileCounter digit:", files[i], firstDigit, fileCounter, isNaN(fileCounter), type); + + if (type == "max") { + if (fileCounter > counter) { + counter = fileCounter; + } + } + else if (type == "min") { + if (counter == 0) counter = fileCounter; + + if (fileCounter < counter) { + counter = fileCounter; + } + } + } + } + + } + + if (type == "max") counter++; + + return counter; + } + + const makeBackupFromDbFile = async () => { + + if (!saveTelemetryOnError) return; + + //to avoid large file: tbdata.nosql + + //init value is 0! + if (insertNoSqlCounter > 0) { + --insertNoSqlCounter; + return; + } + + insertNoSqlCounter = 100; + + let source = __dirname + "/../databases/tbdatacloud.nosql"; + + var stats = fs.statSync(source); + var fileSizeInBytes = stats.size; + + if (fileSizeInBytes > noSqlFileSizeLimit) { + + let counter = 1; + counter = getDbBackupFileCounter("max"); + + let destination = __dirname + "/../databases/" + counter + "." + "tbdatacloud.nosql"; + + //make backup file + fs.copyFileSync(source, destination); + //fs.renameSync(p, p + "." + counter); + + //clear tbdata.nosql + fs.writeFileSync(source, ""); + fs.truncateSync(source, 0); + + } + } + + const processDataFromDatabase = async () => { + + if (restore_from_backup <= 0) return; + + //calculate diff + const now = new Date(); + let currentTime = now.getTime(); + let diff = currentTime - lastRestoreTime; + + if ((diff / 1000) < restore_backup_wait) { + //console.log("*********restore_backup_wait", diff, restore_backup_wait); + return; + } + + processingData = true; + + //get filename to process + let counter = getDbBackupFileCounter("min"); + + //we have some backup files + let dataBase = 'tbdata'; + + var nosql; + if (counter == 0) dataBase = 'tbdatacloud'; + else dataBase = counter + "." + 'tbdatacloud'; + + nosql = NOSQL(dataBase); + + //select all data - use limit restore_from_backup + let records = await promisifyBuilder(nosql.find().take(restore_from_backup)); + + for (let i = 0; i < records.length; i++) { + if (clientReady) { + + let item = records[i]; + let id = item.id; + + if (id !== undefined) { + //console.log("------------processDataFromDatabase - remove", id, dataBase, i); + + try { + + let message = JSON.parse(JSON.stringify(item)); + delete message.id; + client.publish(`${o.topic}_forward`, JSON.stringify(message), { qos: 1 }); + + //remove from database + await promisifyBuilder(nosql.remove().where("id", id)); + + } catch (error) { + //process error + console.log("processDataFromDatabase", error); + } + + } + + } + else { + processingData = false; + return; + } + } + + if (records.length > 0) { + //clean backup file + if (counter > 0) nosql.clean(); + } + + //no data in db, remove + if (records.length == 0) { + if (counter > 0) nosql.drop(); + } + + const d = new Date(); + lastRestoreTime = d.getTime(); + + processingData = false; + + } + + instance.on('options', main); + +}; diff --git a/RVO25/flow/cmd_manager.js b/RVO25/flow/cmd_manager.js new file mode 100755 index 0000000..25912df --- /dev/null +++ b/RVO25/flow/cmd_manager.js @@ -0,0 +1,3071 @@ +exports.id = 'cmd_manager'; +exports.title = 'CMD Manager'; +exports.group = 'Worksys'; +exports.color = '#5D9CEC'; +exports.version = '0.0.3'; +exports.output = ['red', 'blue', 'yellow', 'blue', 'white', 'green']; +exports.input = 3; +exports.icon = 'cloud-upload'; + +exports.html = ` +
+
+
+
RPC - run RPC calls

+
+
+
@(User)
+
+
+
@(Password)
+
+
+
@(My edge)
+
+
+
+`; +exports.readme = `Manager for CMD calls`; + + +exports.install = function(instance) { + + 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, isEmptyObject, emptyJsObject, writeToFile, addToArrayIfUnique } = require('./helper/utils'); + const bitwise = require('bitwise'); + + var SunCalc = require('./helper/suncalc'); + const DataToTbHandler = require('./helper/DataToTbHandler'); + const errorHandler = require('./helper/ErrorToServiceHandler'); + const { sendNotification } = require('./helper/notification_reporter'); + const process = require('process'); + const { errLogger, logger, monitor } = require('./helper/logger'); + + //for accelerometer purposes + const { naklony } = require("../databases/accelerometer_db"); + + const dbNodes = TABLE("nodes"); + const dbRelays = TABLE("relays"); + + let GLOBALS; + let SETTINGS; + let rsPort; + let tbHandler; + + // runTasks intervals + const SHORT_INTERVAL = 30; + const LONG_INTERVAL = 300; + + //send data to following instances: + const SEND_TO = { + debug: 0, + tb: 1, + http_response: 2, + dido_controller: 3, + infoSender: 4, + dailyReport: 5 + } + + 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 + } + + 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 sendNodeReadout = null; // interval for sending agregate data from node + + 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["1"] = minutes; // dimming + priorities["76"] = minutes; // power + + minutes = 5; + priorities["75"] = minutes; // current + priorities["79"] = minutes; // energy + priorities["87"] = minutes; // aktualny cas + //priorities["84"] = minutes; //accelerometer + + minutes = 10; + priorities["74"] = minutes; // voltage + priorities["77"] = minutes; // power factor + priorities["78"] = minutes; // frequency + + minutes = 60; + priorities["0"] = minutes; // statecode + priorities["6"] = minutes; // dusk + priorities["7"] = minutes; // dawn + priorities["8"] = minutes; // profile + + minutes = 60 * 24; + priorities["89"] = minutes; // verzia fw + priorities["80"] = minutes; // lifetime + + //prikazy kt sa budu spustat na dany node - see config.js in terminal-oms.app. (1 - dimming) + let listOfCommands = [0, 1, 6, 7, 8, 74, 75, 76, 77, 78, 79, 80, 87, 89]; + + 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; + + // holds dusk, dawn (and more) values + let sunCalcResult; + + //helper container for counting resolved group of commands (commands related to set profile) + let cmdCounter = {};//key is node, value is counter + + //TODO: is this set working?? According to previous checks, sets do not work + //if sending of profile to node fails, we send notification and push node into set, so we do not send notification twice + const nodeProfileSendFail = new Set(); + + //we expect to get current temperature in Senica from senica-prod01 + let temperatureInSenica = null; + let accelerometerInterval = null; + + //NOTE: daily reports senica: + //rvo_is_on status, we monitor all nodes - if true, power and dimming should be not 0, if false, 24/7 nodes should be 0, other rvo should not respond + let rvo_is_on; + let previous_rvo_is_on_value; + let handleDailyReport; //setInterval for dailyReportHandler function + let dailyReport = {}; //data needed for daily report + let reportToSend = {}; //final report which we send to cloud + let breakerCounter = null; // status of breakers after flow starts is not in report + let rvoPeriod; // interval of checking dusk dawn and if rvo_is_on + let initialReportStatus = false; + + const DAILY_REPORT_HANDLER_TIME = 3_600_000; + const SET_SUNCALC_RESULT_TIME = 3_600_000; + const SET_RVO_PERIOD_TIME = 300_000; + const ADD_NODE_TO_REPORT_TIME = 3_600_000; + + //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); + + let now = new Date(); + console.log("Cmd-mngr installed", now.toLocaleString("sk-SK")); + + sunCalcResult = calculateDuskDawn(); + + handleRsPort(); + + customTasksInterval = setInterval(reportEdgeDateTimeAndNumberOfLuminaires, 120_000); + setTimeout(reportEdgeDateTimeAndNumberOfLuminaires, 4000); + + //dailyReport related + emptyReportToSend(); + breakerCounter = Object.keys(relaysData).length - 1; // we get number of lines (breakers) except of line 0 + rvoPeriod = setInterval(setRvoPeriod, SET_RVO_PERIOD_TIME); + setTimeout(setRvoPeriod, 3000); + setInterval(setSunCalcResult, SET_SUNCALC_RESULT_TIME); + handleDailyReport = setInterval(dailyReportHandler, DAILY_REPORT_HANDLER_TIME); + + + setCorrectTime = setInterval(setCorrectPlcTimeOnceADay, 60000 * 60); // 1 hour + setCorrectPlcTimeOnceADay(); + + sendNodeReadout = setInterval(sendNodesData, 150_000); + accelerometerInterval = setInterval(accelerometerData, 60000 * 30); //30 min + } + + + 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" + //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 + // if node regular readout does not respond, we repeat request + params.repeatCounter = 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-mngr: 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.byte4 = 96; + params.recipient = 1; + params.register = 8; + params.rw = 1;//write + params.timestamp = timestamp; + 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.byte4 = 96; + params.recipient = 1; + params.register = 8; + params.rw = 1;//write + params.timestamp = timestamp; + 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). + */ + + 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.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.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 + { + + logger.debug("processNodeProfile: Threshold lux level for DUSK/DAWN", node); + + let params = getParams(); + params.type = "set_node_profile"; + params.address = node; + params.register = 96; + params.recipient = 1; + params.rw = 1;//write + params.timestamp = timestamp; + 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(); + params.type = "set_node_profile"; + params.address = node; + params.register = 97; + params.recipient = 1; + params.rw = 1;//write + params.timestamp = timestamp; + 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.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); + + 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); + + console.log("proces profile finished *********************") + } + + + 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; + }); + } + + + 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) { + for (let k in nodesData) { + 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`); + } + } + } + + + function loadRelaysData(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 (value.contactor == 1) processAllNodeProfilesOnLine(value.line); + } + } + + + function reportOnlineNodeStatus(line) { + //Po zapnutí línie broadcastovo aktualizovať predtým čas a o 3 sek neskor - status, brightness + + logger.debug("Cmd-mngr: ----->reportOnlineNodeStatus for line", line); + + const d = new Date(); + + // broadcast actual time + let params = getParams(); + params.address = 0xffffffff;//Broadcast + params.byte1 = d.getHours(); + params.byte2 = d.getMinutes(); + params.recipient = 2;//2 broadcast, address = 0 + params.register = 87;//Actual time + params.rw = 1;//write + params.type = "node-onetime-write"; + params.timestamp = d.getTime() + 30000; + params.info = "run broadcast: Actual time"; + //params.debug = true; + + tasks.push(params); + + let sec = 3; + setTimeout(function() { + //Po zapnutí línie - spraviť hromadný refresh stavu práve zapnutých svietidiel + + let time = Date.now(); + + for (let k in nodesData) { + + //potrebujem nody k danej linii + 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].node_status_before_offline === true || nodesData[k].status === true) { + status = "OK"; + nodesData[k].time_of_last_communication = time; + } + + nodesData[k].readout.status = status; + + updateNodeStatus(k, status === "OK" ? true : false); + if (nodesData[k].hasOwnProperty("node_status_before_offline")) delete nodesData[k].node_status_before_offline; + sendTelemetry({ status: status }, tbname, time); + + //vyreportovanie dimming, current, input power pre liniu pre vsetky nody + //Prud + { + let params = getParams(); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 75;//prud + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = time + 4000; + params.info = 'read current'; + //params.debug = true; + tasks.push(params); + } + + //vykon + { + let params = getParams(); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 76;//výkon + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = time + 4100; + params.info = 'read power'; + //params.debug = true; + + tasks.push(params); + } + //dimming + { + let params = getParams(); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 1;//dimming + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = time + 4200; + params.info = 'read dimming'; + //params.debug = true; + + tasks.push(params); + } + + } + } + + }, sec * 1000); + } + + + function reportOfflineNodeStatus(line) { + + logger.info("Cmd-mngr: ------>reportOffLineNodeStatus for line ", line); + + values = {}; + values["dimming"] = 0;//brightness + values["power"] = 0;//výkon + values["current"] = 0;//prúd + values["status"] = "OFFLINE"; + + const date = Date.now(); + + Object.keys(nodesData).forEach(node => { + + //potrebujem nody k danej linii + if (line == nodesData[node].line || line == undefined) { + + let tbname = nodesData[node].tbname; + let nodeStatus = nodesData[node].status; + + //in case we have reported offline node status, we return (continue with next node) + if (nodeStatus === "OFFLINE") return; + + nodesData[node].node_status_before_offline = nodeStatus; + nodesData[node].status = "OFFLINE"; + nodesData[node].readout = {}; + + sendTelemetry({ ...values }, tbname, date); + } + }); + + } + + + function turnLine(onOrOff, line, info) { + let obj = { + line: line, + command: onOrOff, + info: info + }; + + //to assure, handleDailyReportFunction do not run before rvo_is_on variable changes. So after every line switch we reset the timer + clearInterval(handleDailyReport); + handleDailyReport = setInterval(dailyReportHandler, DAILY_REPORT_HANDLER_TIME); + + //logger.debug("linia", line, obj); + instance.send(SEND_TO.dido_controller, obj); + } + + + 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"; + 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]) { + //CRC_ERROR + message = "NOK"; + error = "CRC_ERROR c1"; + instance.send(SEND_TO.debug, "CRC_ERROR c1"); + } + + 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") { + instance.send(SEND_TO.debug, bytes); + instance.send(SEND_TO.debug, "RESPONSE " + type + " - " + bytes[4]); + + //logger.debug(SEND_TO.debug, "RESPONSE " + type + " - " + bytes[4], bytes); + + error = "type is: " + type; + + message = "NOK"; + } + + return { message, type, error }; + } + + + //BUILD TASKS// + function buildTasks(params) { + + //return; + console.log("buidTAaasks start ****************", params); + monitor.info("buildTasks - params", params); + + let processLine; //defined line + let init = false; + let processLineProfiles = true; + let processBroadcast = true; + let processNodes = true; + + if (params == undefined) { + init = true; + tasks = []; + logger.debug("-->buildTasks clear tasks"); + } + else { + processLineProfiles = params.processLineProfiles; + processBroadcast = false; + processNodes = false; + + processLine = params.line; + } + + let now = new Date(); + + //process line profiles + if (processLineProfiles) { + + let keys = Object.keys(relaysData); + + for (let i = 0; i < keys.length; i++) { + + let line = parseInt(keys[i]); + let profilestr = relaysData[line].profile; + + if (processLine != undefined) { + if (processLine != line) continue; + } + + try { + + /** + * we process line profiles: timepoints, astro clock, lux_sensor, offsets ... + */ + if (profilestr === "") throw ("Profile is not defined"); + let profile = JSON.parse(profilestr); + 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; + + // add name to regular profile timepoint and delete unused end_time key: + time_points.forEach(point => { + point.name = "profileTimepoint" + delete point.end_time; + }); + + //monitor.info("buildTasks: time_points", time_points); + + + /** + * 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 astro clock true, we remove all regular profile points + time_points = []; + + //TODO: when astro clock == true, is offset calculated ??? + //let duskAstroClockOffset = profile.dusk_astro_clock_offset; + //let dawnAstroClockOffset = profile.dawn_astro_clock_offset; + //console.log("line astro clock offsets dusk a dawn: ", duskAstroClockOffset, dawnAstroClockOffset); + // maybe add dusk dawn offset to calculateDuskDawn ?? what dusk dawn will be if dawn_lux_sensor == true?? + //let sunCalcResult = calculateDuskDawn(new Date(), line, duskAstroClockOffset, dawnAstroClockOffset); + + 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 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); + + 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); + + 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(':'); + + let ad = new Date(); + ad.setHours(parseInt(ahours), parseInt(aminutes), 0); + + let bd = new Date(); + bd.setHours(parseInt(bhours), parseInt(bminutes), 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++) { + + let start_time = new Date(); + let [hours, minutes] = time_points[t].start_time.split(':'); + start_time.setHours(parseInt(hours), parseInt(minutes), 0); + + //task is in 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(); + params.type = "relay"; + params.line = parseInt(line); + params.value = time_points[t].value; + params.tbname = relaysData[line].tbname; + params.timestamp = start_time.getTime(); + + // 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; + + //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)) { + 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; + + params.debug = true; + + //turn on/off line + tasks.push(params); + monitor.info("TimePoint params: ", params.info, start_time); + } + + monitor.info("-->time_points final", line, time_points); + + //ensure to turn on/off according to calculated currentValue + let params = getParams(); + params.type = "relay"; + params.line = parseInt(line); + params.tbname = relaysData[line].tbname; + params.value = currentValue; + params.timestamp = i; + params.debug = true; + + //logger.debug(now.toLocaleString("sk-SK")); + 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; + + tasks.push(params); + + } catch (error) { + if (profilestr !== "") { + //errLogger.error(profilestr, error); + console.log(`Cmd_mngr: Unable to process line profile ${line}. Error: `, error); + errorHandler.sendMessageToService(profilestr + "-" + error, 0, "js_error"); + } else { + turnLine("off", line, "No line profile. Switching it off on startup"); + } + } + + } + //logger.debug("tasks:"); + //logger.debug(tasks); + } + + + //NOTE: PROCESS DEFAULT BROADCASTS - Time of dusk, Time of dawn, Actual Time + if (processBroadcast) { + + let d = new Date(); + let time = d.getTime(); + //let sunCalcResult = calculateDuskDawn(); + + { + let params = getParams(); + + params.address = 0xffffffff;//broadcast + params.byte1 = sunCalcResult["dusk_hours"]; + params.byte2 = sunCalcResult["dusk_minutes"]; + params.recipient = 2;//2 broadcast, + params.register = 6;//Time of dusk + params.rw = 1;//write + params.type = "node-regular-write"; + params.timestamp = time + 60000; + params.addMinutesToTimestamp = 60 * 3; //kazde 3 hodiny zisti novy dusk + params.info = "Broadcast-duskTime"; + + tasks.push(params); + } + + { + let params = getParams(); + + params.address = 0xffffffff;//broadcast + params.byte1 = sunCalcResult["dawn_hours"]; + params.byte2 = sunCalcResult["dawn_minutes"]; + params.recipient = 2; //2 broadcast + params.register = 7;//Time of dawn + params.rw = 1;//write + params.type = "node-regular-write"; + params.timestamp = time + 60001; + params.addMinutesToTimestamp = 60 * 3; //kazde 3 hodiny zisti novy dawn + params.info = "Broadcast-dawnTime"; + + tasks.push(params); + } + + { + let params = getParams(); + + params.address = 0xffffffff;//broadcast + params.byte1 = d.getHours(); + params.byte2 = d.getMinutes(); + params.recipient = 2; //2 broadcast + params.register = 87;//Actual time + params.rw = 1;//write + params.type = "node-regular-write"; + params.timestamp = time + 60002; + params.addMinutesToTimestamp = 5; + params.info = "run broadcast: Actual time"; + + tasks.push(params); + } + + } + + //process nodes & tasks - read node's data + if (processNodes) { + + let time = Date.now(); + + for (let k in nodesData) { + let address = parseInt(k); + let tbname = nodesData[k].tbname; + let register = 0; + + for (let i = 0; i < listOfCommands.length; i++) { + + register = listOfCommands[i]; + let addMinutesToTimestamp = priorities[register]; + + let params = getParams(); + + params.address = address; + params.recipient = 1; + params.register = register; + params.type = register == 1 ? "node-dimming-read" : "node-regular-read"; + params.tbname = tbname; + params.timestamp = time + 5000 + i * 500 + addMinutesToTimestamp * 1000; //to make slight time difference + params.addMinutesToTimestamp = addMinutesToTimestamp; + params.info = "Node regular read command"; + + tasks.push(params); + } + + } + } + + + //niektore ulohy sa vygeneruju iba 1x pri starte!!! + if (!init) return; + + + //Master node FW version - modifies SETTINGS.masterNodeIsResponding + { + let params = getParams(); + params.type = "cmd-master"; + params.register = 4; + params.address = 0; + params.timestamp = 0; + params.addMinutesToTimestamp = 5; + params.tbname = SETTINGS.rvoTbName; + params.info = "Master node FW verzia"; + //params.debug = true; + + tasks.push(params); + } + + //kazdu hodinu skontrolovat nastavenie profilov + { + let params = getParams(); + params.type = "process_profiles"; + params.timestamp = Date.now() + 60001; + params.addMinutesToTimestamp = 60;//60 = every hour + params.info = "detekcia nespracovaných profilov linie a nodov"; + //params.debug = true; + + tasks.push(params); + } + + monitor.info("tasks created:", tasks.length); + } + + + /** + * We process line profile, where "astro_clock": true + * example profile: + * + "dawn_lux_sensor": true, + "dusk_lux_sensor": true, + "dawn_lux_sensor_value": 5, + "dusk_lux_sensor_value": 5, + "dawn_astro_clock_offset": 0, + "dusk_astro_clock_offset": 10, + "dawn_lux_sensor_time_window": 30, + "dusk_lux_sensor_time_window": 30, + "dawn_astro_clock_time_window": 60, + "dusk_astro_clock_time_window": 60 + + * if dawn: if currentTimestamp is in timewindow "dawnTime + and - dawn_lux_sensor_time_window" and lux value >= lux_sensor_value, we switch off the line. + * if dusk: we do oposite + * + * dawn: usvit - lux je nad hranicou - vypnem + * dusk: sumrak - lux je pod hranicou - zapnem + */ + 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++) { + + let line = keys[i]; //line is turned off by default + let profilestr = relaysData[line].profile; + const contactor = relaysData[line].contactor; + + try { + + let profile = JSON.parse(profilestr); + if (Object.keys(profile).length === 0) throw ("turnOnOffLinesAccordingToLuxSensor - profile is not defined"); + + 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 (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"); + } + } + } + + //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 (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"); + } + } + } + + } + + } catch (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) { + //MASTER + if (node == 0) return; + + let nodeObj = nodesData[node]; + if (nodeObj == undefined) return; + + let nodeCurrentStatus = nodeObj.status; + const now = Date.now(); + + let data = null; + + if (nodeCurrentStatus === "OFFLINE") { + data = { status: newStatus }; + nodeDbStatusModify(node, data); + return; + } + else 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; + } + + } + + + 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 }; + } + }); + }); + } + + + function processDailyReport() { + + const now = Date.now(); + + for (const [key, value] of Object.entries(dailyReport)) { + + if (["name", "time", "dusk_and_dawn"].includes(key)) continue; + + let poleNumber = nodesData[key]["pole_number"]; + let line = dailyReport[key].line; + let nodeType = nodesData[key]["node_type"]; + let fullNodeName = key // key == nodeNumber + + if (poleNumber && nodeType) { + fullNodeName = SETTINGS.rvo_number + "/" + poleNumber + "_" + line + "L_" + key + "_" + nodeType; + } else { + fullNodeName = key; + } + + if (rvo_is_on) { + + if (value.initialTs) { + if (value.initialTs + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["night_no_data"], fullNodeName); + console.log('report nedostava ziadne data uz hodinu', fullNodeName); + value.initialTs = now; + } + } + if (value.dimmingIsZeroTime) { + if (value.dimmingIsZeroTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["night_dimming=0"], fullNodeName); + console.log("report node dimming je 0 ale ma svietit", fullNodeName); + value.dimmingIsZeroTime = now; + } + } + if (value.powerIsZeroTime) { + if (value.powerIsZeroTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["night_power=0"], fullNodeName); + console.log("report node power je 0 ale ma svietit", fullNodeName); + value.powerIsZeroTime = now; + } + } + + } else { + + let contactorStatus = relaysData[line].contactor; + if (contactorStatus === 1) { + + if (value.initialTs) { + if (value.initialTs + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["day_24/7_no_data"], fullNodeName); + console.log('node je na 24/7 ale nedostava ziadne data uz hodinu', fullNodeName); + value.initialTs = now; + } + } + if (value.dimmingIsOnButShouldBeOffTime) { + if (value.dimmingIsOnButShouldBeOffTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["day_24/7_dimming>0"], fullNodeName); + console.log("report dimming je > 0 ale nema svietit", fullNodeName); + value.dimmingIsOnButShouldBeOffTime = now; + } + } + if (value.powerIsOnButShouldBeOffTime) { + if (value.powerIsOnButShouldBeOffTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["day_24/7_power>0"], fullNodeName); + console.log("report power je > 0 ale nema svietit", fullNodeName); + value.powerIsOnButShouldBeOffTime = now; + } + } + + } + + } + + } + + let report = {}; + report["name"] = SETTINGS.rvo_name; + report["time"] = new Date(); + report["report"] = reportToSend; + + writeToFile(F.path.root("report_data.log"), report, true); + instance.send(SEND_TO.dailyReport, report); + } + + + function dailyReportHandler() { + + if (!SETTINGS.daily_report) return; + + // after dawn we empty reportToSend and start to get data for a new day + const date = new Date(); + const hour = date.getHours(); + const minute = date.getMinutes(); + + console.log("now: ", hour, minute, "suncalc: ", sunCalcResult.dawn_hours, sunCalcResult.dawn_minutes); + + if (hour === sunCalcResult.dawn_hours) { + + //NOTE: ak je este pred usvitom, spracujeme report a posleme na cloud, ak uz je po usvite, resetujeme report plnime data noveho dna + if (minute >= sunCalcResult.dawn_minutes - 2) { + emptyReportToSend(); + emptyDailyReport(); + console.log("Podmienka 1 v dailyReport handler"); + } else { + processDailyReport(); + emptyReportToSend(); + emptyDailyReport(); + console.log("Podmienka 2 v dailyReport handler"); + } + + initialReportStatus = true; + + // ak sa funkcia spusti o hodinu alebo 2 neskor, ako je usvit (moze sa to stat, kedze kazde zapnutie/vypnutie linii odznova spusti casovac. + } else if (hour === sunCalcResult.dawn_hours + 1 || hour === sunCalcResult.dawn_hours + 2) { + if (!initialReportStatus) { + emptyReportToSend(); + emptyDailyReport(); + initialReportStatus = true; + console.log("Podmienka 3 v dailyReport handler"); + } else { + processDailyReport(); + initialReportStatus = true; + console.log("Podmienka 4 v dailyReport handler"); + } + } else { + processDailyReport(); + initialReportStatus = false; + console.log("Podmienka 5 v dailyReport handler"); + } + + console.log("initialReportStatus: ", initialReportStatus); + + } + + function emptyReportToSend() { + emptyJsObject(reportToSend); + reportToSend["contactor"] = { off: [], on: [] }; + reportToSend["night_no_data"] = []; + reportToSend["night_dimming=0"] = []; + reportToSend["night_power=0"] = []; + reportToSend["day_24/7_no_data"] = []; + reportToSend["day_24/7_dimming>0"] = []; + reportToSend["day_24/7_power>0"] = []; + console.log(`resetuje sa reportToSend`); + } + + + //NOTE: ked je initialTs stale rovnaky a zistime ze linie su vypnute (relaysData.line.contactor) - zistim, ci je node na tej linii. Vieme, ze ak je linia vypnuta je to v poriadku lebo nie je na 24/7 linii + //ak je na 24/7 linii, reportujeme, ze neprijima data + function emptyDailyReport() { + const ts = Date.now(); + emptyJsObject(dailyReport); + + //NOTE: do dailyReport dame vsetky nody a pravidelne kontrolujeme ci maju data + //ked nastane sumrak/usvit a svetla maju zacat/prestat svietit, dailyReport spravime nanovo: + for (const [key, value] of Object.entries(nodesData)) { + dailyReport[value.node] = { line: value.line, initialTs: ts }; + } + + console.log("dailyReport: ", dailyReport); + } + + + async function runTasks() { + + clearInterval(interval); + + let currentTimestamp = Date.now(); + + //sort tasks based on timestamp + 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) { + instance.send(SEND_TO.debug, "no tasks created"); + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + if (!rsPort.isOpen) { + instance.send(SEND_TO.debug, "!rsPort.isOpen"); + //await rsPort.open(); + //console.log("Cmd-mngr: !rsPort.isOpen"); + } + + let currentTask = tasks[0]; + + if (currentTask.debug) { + //logger.debug("--->task to process", currentTask); + } + + if (currentTask.timestamp <= currentTimestamp) { + let params = { ...tasks[0] }; + + //allow terminal commands + if (SETTINGS.maintenance_mode && params.type !== "cmd-terminal") { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + let type = params.type; + let tbname = params.tbname; + let node = params.address; + let register = params.register; + let line = null; + let itIsNodeCommand; + + if (nodesData[node] !== undefined) { + line = nodesData[node].line; + itIsNodeCommand = true; + } + + if (params.line !== undefined) line = params.line; + + if (params.addMinutesToTimestamp > 0 || params.timePointName) { + tasks[0].timestamp = currentTimestamp + tasks[0].addMinutesToTimestamp * 60000; + } else { + tasks.shift(); + } + + //kontrola nespracovanych profilov nodov + //TODO: co ked niektore nody neprijimaju profily? kazdu hodinu zahltuju "tasks" array + if (type == "process_profiles") { + //na vsetky zapnutych liniach sa spracuju nespracovane profily nodov + loadRelaysData(); + interval = setInterval(runTasks, SHORT_INTERVAL); + return; + } + + //relay + if (type == "relay") { + + const timePointName = params.timePointName; + const value = params.value; + + let date = new Date(); + date.setDate(date.getDate() + 1);//next day + + let sunCalcResult; + if (timePointName) sunCalcResult = calculateDuskDawn(date, params.line); + + + if (timePointName == "dawn") { + tasks[0].timestamp = sunCalcResult.dawn_time; + } + else if (timePointName == "dusk") { + tasks[0].timestamp = sunCalcResult.dusk_time; + } + else if (timePointName == "luxOn") { + tasks[0].timestamp = sunCalcResult.dusk_time + params.dusk_lux_sensor_time_window * 60000; + } + else if (timePointName == "luxOff") { + tasks[0].timestamp = sunCalcResult.dawn_time + params.dawn_lux_sensor_time_window * 60000; + } + else if (timePointName == "profileTimepoint") { + tasks[0].timestamp = currentTimestamp + tasks[0].addMinutesToTimestamp * 60000; + } + + let info = "aplikovany bod profilu"; + let onOrOff = ""; + value == 1 ? onOrOff = "on" : onOrOff = "off"; + + turnLine(onOrOff, params.line, info); + + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + if (!SETTINGS.masterNodeIsResponding) { + //ak neodpoveda, nebudeme vykonavat ziadne commands, okrem cmd-terminal cmd-master + errorHandler.sendMessageToService("Master node is not responding"); + + let stop = true; + + if (type === "cmd-terminal" || type === "cmd-master") stop = false; + if (stop) { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + } + + let contactorStatus = 1; + if (relaysData[line] != undefined) contactorStatus = relaysData[line].contactor; + + if (line === 0 || contactorStatus === 0 || FLOW.deviceStatus.state_of_breaker[line] === "Off") { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + // TODO: -> status offline for rvo if rotary_switch_state is OFF, this is source of errors + // check if rotary_switch_state == "Off" + // state_of_braker: disconnected = true? + + if (!rsPort.isOpen) { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + //RE-CALCULATE VALUES + //set actual time for broadcast + if (register == 87 && params.recipient === 2) { + var d = new Date(); + params.byte1 = d.getHours();//h + params.byte2 = d.getMinutes();//m + } + + //SET DUSK/DAWN FOR BROADCAST + //Time of dusk + if (register == 6 && params.recipient === 2) { + + if (type != "cmd-terminal") { + params.byte1 = sunCalcResult["dusk_hours"];//h + params.byte2 = sunCalcResult["dusk_minutes"];//m + } + } + + //Time of dawn + if (register == 7 && params.recipient === 2) { + if (type != "cmd-terminal") { + params.byte1 = sunCalcResult["dawn_hours"];//h + params.byte2 = sunCalcResult["dawn_minutes"];//m + } + } + //----------------------- + + instance.send(SEND_TO.debug, "address: " + node + " register:" + register + "type: " + type); + + var startTime, endTime; + startTime = new Date(); + + let saveToTb = true; + if (!tbname) saveToTb = false; + + let resp = com_generic(node, params.recipient, params.rw, register, params.name, params.byte1, params.byte2, params.byte3, params.byte4); + let readBytes = 11; + let timeout = 4000; + + + // await keyword is important, otherwise incorrect data is returned! + await writeData(rsPort, resp, readBytes, timeout).then(function(data) { + + //sometimes happens, that status of node changes to OK, NOK even if line was turned off and should be status OFFLINE. To prevent this, we return if line contactor is 0: + if (itIsNodeCommand && line && relaysData[line].contactor !== 1) return; + + 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); + + //ak sa odpoved zacina 0 - je to v poriadku, inak je NOK + let message = result.message; // OK, NOK + let message_type = result.type; + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + console.log("detected response:", result); + logger.debug("Cmd-mngr: writeData done " + message_type + " duration: " + timeDiff + " type: " + params.debug, params, result); + } + } + + let values = {}; + + //CMD FINISHED + if (message == "OK") { + + updateNodeStatus(node, true); + + //write + if (type == "set_node_profile") { + let result = cmdCounterResolve(node); + if (result == 0) { + dbNodes.modify({ processed: true }).where("node", node).make(function(builder) { + builder.callback(function(err, response) { + + sendNotification("Cmd-mngr: process cmd", SETTINGS.rvoTbName, "dimming_profile_was_successfully_received_by_node", { node: node }, "", SEND_TO.tb, instance); + + logger.debug("--> profil úspešne odoslaný na node č. " + node); + nodesData[node].processed = true; + nodeProfileSendFail.delete(node); + }); + }); + } + } + + //parse read response + if (params.rw == 0) { + values = processResponse(register, dataBytes); //read + } + + if (itIsNodeCommand) { + values.comm_status = "OK"; + values.status = "OK"; + nodesData[node].readout = { ...nodesData[node].readout, ...values }; + + + if (SETTINGS.daily_report) { + //TODO: co ak nedostavame odpovede z nodu ? Musime vyreportovat!! + //v dailyReport teda musi byt kompletny zoznam nodov a neustale kontrolovat, ci maju data, ak nie report node - neodpoveda + if (register === 1) { + + let now = Date.now(); + + if (rvo_is_on === true) { + + if ("dimmingIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].dimmingIsOnButShouldBeOffTime; + + if (values.dimming > 0) { + if ("dimmingIsZeroTime" in dailyReport[node]) delete dailyReport[node].dimmingIsZeroTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if (!("dimmingIsZeroTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], dimmingIsZeroTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } else { + + if ("dimmingIsZeroTime" in dailyReport[node]) delete dailyReport[node].dimmingIsZeroTime; + + if (values.dimming > 0) { + if (!("dimmingIsOnButShouldBeOffTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], dimmingIsOnButShouldBeOffTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if ("dimmingIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].dimmingIsOnButShouldBeOffTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } + } + + if (register === 76) { + + let now = Date.now(); + + if (rvo_is_on === true) { + + if ("powerIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].powerIsOnButShouldBeOffTime; + + if (values.power > 1) { + if ("powerIsZeroTime" in dailyReport[node]) delete dailyReport[node].powerIsZeroTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if (!("powerIsZeroTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], powerIsZeroTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } else { + + if ("powerIsZeroTime" in dailyReport[node]) delete dailyReport[node].powerIsZeroTime; + + if (values.power > 1) { + if (!("powerIsOnButShouldBeOffTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], powerIsOnButShouldBeOffTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if ("powerIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].powerIsOnButShouldBeOffTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } + } + } + + } + + //master node + if (node == 0) { + sendNotification("Cmd-mngr: 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; + } + + if (params.debug) { + //logger.debug("saveToTb", saveToTb, tbname, values); + } + + if (saveToTb && type != "node-regular-read") { + sendTelemetry(values, tbname); + } + else { + if (type == "cmd-terminal") { + terminalCommandResponse(params, "SUCCESS", data); + } + } + + } + else { + terminalCommandResponse(params, "ERROR", data); + handleNokResponseOnRsPort("handleNOK else block", params, itIsNodeCommand, saveToTb); + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + //logger.debug("writeData err: ", error, result, params); + logger.debug("writeData err: ", tbname, node, register, values); + } + } + + //logger.debug(error, result, params); + } + }).catch(function(reason) { + + //console.log("writeData catch exception", reason); + instance.send(SEND_TO.debug, reason); + + terminalCommandResponse(params, "FAILURE", null, reason); + handleNokResponseOnRsPort("handleNOK catch block", params, itIsNodeCommand, saveToTb); + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + logger.debug("-->WRITE FAILED: " + reason, params.debug, params); + } + } + + }); + + } + 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); + } + + + // if node does not respond to request, we repeat request 3 times: + function repeatCommand(params) { + params.repeatCounter++; + if (params.repeatCounter < 4) { + params.timestamp = 0; + params.addMinutesToTimestamp = 0; + tasks.push(params); + } + } + + function handleNokResponseOnRsPort(message, params, itIsNodeCommand, saveToTb) { + + let node = params.address; + let register = params.register; + let type = params.type; + let tbName = params.tbname; + if (!tbName) return; + + let values = {}; + + let updateStatus = updateNodeStatus(node, false); + + if (itIsNodeCommand) { + values.comm_status = "NOK"; + nodesData[node].readout.comm_status = "NOK"; + repeatCommand(params); + } + + if (updateStatus) { + values.status = "NOK"; + nodesData[node].readout.status = "NOK"; + } + + if (type === "node-regular-read") return; + + //master node + if (node == 0) { + sendNotification("Cmd-mngr: 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; + + if (register == 4) values["master_node_version"] = "NOK"; + } + + if (type == "set_node_profile") { + delete cmdCounter[node]; + logger.debug("profil nebol úspešne odoslaný na node č. ", params); + + if (!nodeProfileSendFail.has(node)) { + sendNotification("Cmd-mngr: process cmd", tbName, "configuration_of_dimming_profile_to_node_failed", { node: node }, "", SEND_TO.tb, instance); + nodeProfileSendFail.add(node); + } + } + + // console.log("------",node, register, type, itIsNodeCommand, updateStatus, saveToTb, values); + if (saveToTb) { + sendTelemetry(values, tbName); + } + + } + + + function sendNodesData() { + Object.keys(nodesData).forEach(node => { + if (nodesData[node]["status"] !== "OFFLINE") { + sendTelemetry(nodesData[node].readout, nodesData[node].tbname); + nodesData[node].readout = {}; + } + }) + } + + + /** + * 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; + } + + 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); + + //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 === "OFFLINE") { + nodeObj.node_status_before_offline === true ? number_of_ok_luminaires++ : number_of_nok_luminaires++; + } + else if (nodeObj.status == true) 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 - ts % 60000 //round to full minute + }; + + sendTelemetry(values, SETTINGS.rvoTbName, ts); + } + + + function setSunCalcResult() { + //if next day, we get new dusk and dawn. To make sure, in local timezone 2:00 means 00:00 in utc (it means next day) + if (new Date().getHours() === 2) { + sunCalcResult = calculateDuskDawn(); + console.log("Novy suncalc: ", sunCalcResult); + } + } + + + function setRvoPeriod() { + + if (!SETTINGS.daily_report) return; + + const ts = Date.now(); + + previous_rvo_is_on_value = rvo_is_on; + + if (ts < sunCalcResult.dawn_time - 1_800_000) { // nodes should be on (00:00 -> 06:00 ( - pol hodina, lebo rvo vypina skor) + rvo_is_on = true; + } else if (sunCalcResult.dawn_time - 1_800_000 < ts && ts < sunCalcResult.dusk_time + 1_800_000) { // nodes should be off 06:00 -> 21:00 + rvo_is_on = false; + } else if (sunCalcResult.dusk_time + 1_800_000 < ts) { // nodes should be on 21:00 -> 00:00 + rvo_is_on = true; + } + + if (previous_rvo_is_on_value !== rvo_is_on) { + emptyDailyReport(); + console.log("rvo_is: ", rvo_is_on, previous_rvo_is_on_value); + } + } + + + function handleRsPort() { + + if (rsPort) { + rsPort.removeAllListeners(); + rsPort = null; + } + + //! 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-mngr: rsPort opened success"); + + 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); + + }).catch(function(reason) { + instance.send(SEND_TO.debug, "Cmd-mngr: RPC runSyncExec - promise rejected:" + reason); + }); + }); + + rsPort.on('error', function(err) { + errorHandler.sendMessageToService([exports.title, "unable to open port", SETTINGS.serial_port, err.message], 0); + monitor.info("Cmd-mngr: Error on rsPort", err.message); + }); + + rsPort.on("close", () => { + monitor.info("Cmd-mngr: rsPort closed, reconnecting..."); + setTimeout(handleRsPort, 1000); + }); + + rsPort.open(); + } + + + instance.on("close", () => { + clearInterval(interval); + clearInterval(customTasksInterval); + clearInterval(setCorrectTime); + clearInterval(sendNodeReadout); + clearInterval(accelerometerInterval); + rsPort.close(); + }); + + instance.on("0", _ => { + main(); + }) + + + instance.on("2", _ => { + console.log("dailyReport, reportToSend, rvo_is_on", dailyReport, reportToSend, rvo_is_on, previous_rvo_is_on_value); + }) + + instance.on("1", 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(); + return; + } + else if (flowdata.data == "close") { + rsPort.close(); + return; + } + else if (flowdata.data == "clean") { + tasks = []; + return; + } + else if (flowdata.data == "buildtasks") { + //build & run + return; + } + else if (flowdata.data == "run") { + //durations = []; + + if (tasks.length == 0) { + + buildTasks(); + + if (rsPort.isOpen) { + interval = setInterval(runTasks, 100); + } + else { + instance.send(SEND_TO.debug, "port is not opened!!!"); + } + } + } + else { + //terminal data - object + //logger.debug("flowdata", flowdata.data); + + if (typeof flowdata.data === 'object') { + //logger.debug("dido", flowdata.data); + if (flowdata.data.hasOwnProperty("sender")) { + //data from dido_controller + if (flowdata.data.sender == "dido_controller") { + + if (flowdata.data.hasOwnProperty("cmd")) { + let cmd = flowdata.data.cmd; + + if (cmd == "buildTasks") { + clearInterval(interval); + + logger.debug("-->Cmd-mngr: BUILD TASKS"); + buildTasks(); + + //logger.debug("tasks:"); + //logger.debug(tasks); + + logger.debug("-->Cmd-mngr: RUN TASKS"); + interval = setInterval(runTasks, 5000); + } + else if (cmd == "reload_relays") { + loadRelaysData(flowdata.data.line); + + if (flowdata.data.dataChanged) { + if (!flowdata.data.value) { + reportOfflineNodeStatus(flowdata.data.line); + } + else { + reportOnlineNodeStatus(flowdata.data.line); + } + } + + } + else if (cmd == "rotary_switch_state") { + let value = flowdata.data.value; + + //state was changed + if (rotary_switch_state != value) { + if (value == "Off") { + //vyreportovat vsetky svietdla + reportOfflineNodeStatus(); + } + + rotary_switch_state = value; + } + } + 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) { + + // we send lux_sensor value to all nodes: + let params = getParams(PRIORITY_TYPES.node_broadcast); + + params.recipient = 2;//2 broadcast, address = 0 + params.address = 0xffffffff;//Broadcast + + let ba = longToByteArray(lux_sensor); + + params.byte3 = ba[1];//msb + params.byte4 = ba[0]; + params.timestamp = PRIORITY_TYPES.node_broadcast; + params.info = "run broadcast: Actual Lux level from cabinet"; + params.register = 95;//Actual Lux level from cabinet + params.rw = 1;//write + + tasks.push(params); + + //process profiles + turnOnOffLinesAccordingToLuxSensor(lux_sensor); + } + } + else if (cmd == "state_of_breaker") { + //istic linie + + breakerCounter--; + + let value = flowdata.data.value; + let line = parseInt(flowdata.data.line); + + let dataChanged = false; + if (state_of_breaker[line] != value) dataChanged = true; + + state_of_breaker[line] = value; + + let status = "OK"; + if (value == "Off") status = "NOK"; + + if (dataChanged) { + + if (relaysData.hasOwnProperty(line)) { + let tbname = relaysData[line].tbname; + + if (value == "Off") { + sendNotification("Cmd-mngr: onData", tbname, "circuit_breaker_was_turned_off_line", { line: line }, "", SEND_TO.tb, instance, "circuit_breaker"); + if (breakerCounter < 0) reportToSend["contactor"]["off"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + else { + sendNotification("Cmd-mngr: onData", tbname, "circuit_breaker_was_turned_on_line", { line: line }, "", SEND_TO.tb, instance, "circuit_breaker"); + if (breakerCounter < 0) reportToSend["contactor"]["on"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + + //report status liniu + sendTelemetry({ status: status }, tbname) + + //current value + if (value == "Off") reportOfflineNodeStatus(line); //vyreportovat vsetky svietidla na linii + } + + } + } + else { + logger.debug("undefined cmd", cmd); + } + } + } + + return; + } + + //data from worksys + if (flowdata.data.hasOwnProperty("topic")) { + + let data = getNested(flowdata.data, "content", "data"); + + //if we get temperature in senica from senica-prod01 + let temperature = getNested(flowdata.data, "content", "senica_temperature"); + + if (temperature !== undefined) { + temperatureInSenica = temperature; + return; + } + + if (data === undefined) { + console.log("Invalid rpc command came from platform"); + return; + } + + let command = data.params.command; + let method = data.method; + let profile = data.params.payload; + if (profile == undefined) profile = ""; + let entity = data.params.entities[0]; + let entity_type = entity.entity_type; + let tbname = entity.tb_name; + + instance.send(SEND_TO.debug, flowdata.data); + 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") { + + //let command = data.params.command; + let value = data.params.payload.value; + + if (command == "dimming") { + + let nodeWasFound = false; + let keys = Object.keys(nodesData); + + //logger.debug("-----", keys); + + 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); + + value = parseInt(value); + if (value > 0) value = value + 128; + + params.type = "node-onetime-write"; + params.tbname = tbname; + params.address = node; + params.register = 1; + params.recipient = 1; + params.byte4 = value; + params.rw = 1; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'set dimming from platform'; + //params.debug = true; + + //debug(params); + logger.debug("dimming", params); + + tasks.push(params); + + 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); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 1; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read dimming (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + //pridame aj vyreportovanie - vykon + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 76; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read Input Power (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + //pridame aj vyreportovanie - prud svietidla + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 75; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read Input Current (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + //pridame aj vyreportovanie - power faktor - ucinnik + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 77; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read power factor (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + }, 4000); + + nodeWasFound = true; + break; + } + } + + if (!nodeWasFound) { + logger.debug("set dimming from platform", "unable to find tbname", tbname); + } + } + else { + instance.send(SEND_TO.debug, "undefined command " + command); + logger.debug("undefined command", command); + } + + return; + } + 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++) { + let node = keys[i]; + if (tbname == nodesData[node].tbname) { + + 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"); + + //profil úspešne prijatý pre node č. xx + sendNotification("Cmd-mngr", tbname, "dimming_profile_was_processed_for_node", { node: node }, profile, SEND_TO.tb, instance); + + nodesData[node].processed = false; + nodesData[node].profile = profile; + + processNodeProfile(node); + }); + }); + } + } + } + else { + + instance.send(SEND_TO.debug, "unknown method " + method); + logger.debug("unknown method", method); + + return; + } + } + + //nastav profil linie z platformy + 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") { + + 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++) { + let line = keys[i]; + if (tbname == relaysData[line].tbname) { + //zmazeme tasky + 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) { + + //update profile + logger.debug("worksys - update relay profile done:", profile); + instance.send(SEND_TO.debug, "worksys - update relay profile done"); + + relaysData[line].profile = profile; + + loadRelaysData(line) + logger.debug("loadRelaysData DONE for line", line); + + buildTasks({ processLineProfiles: true, line: line }); + + sendNotification("Cmd-mngr: set profile from worksys", tbname, "switching_profile_was_processed_for_line", { line: line }, profile, SEND_TO.tb, instance); + }); + }); + break; + } + } + } + else if (method == "set_command") { + let value = data.params.payload.value; + + 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; + + 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"); + if (line != 0) reportToSend["contactor"]["off"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + else { + turnLine("on", line, "command received from platform"); + if (line != 0) reportToSend["contactor"]["on"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + } + } + else { + instance.send(SEND_TO.debug, "undefined method " + method); + logger.debug("undefined method", method); + } + + return; + } + else { + instance.send(SEND_TO.debug, "UNKNOW entity_type " + entity_type); + logger.debug("UNKNOW entity_type", entity_type); + } + return; + } + + //terminal + if (!rsPort.isOpen) await rsPort.open(); + + let params = flowdata.data.body; + if (params == undefined) { + //logger.debug("Cmd-mngr: flowdata.data.body is undefined"); + return; + } + + params.priority = PRIORITY_TYPES.terminal; + params.type = "cmd-terminal"; + params.tbname = ""; + params.timestamp = PRIORITY_TYPES.terminal; + params.addMinutesToTimestamp = 0;// do not repeat task!!! + params.debug = true; + + let timestamp = Date.now(); + params.refFlowdataKey = timestamp; + //params.refFlowdata = flowdata; + //refFlowdata = flowdata; + + //console.log("flowdata", flowdata); + + cleanUpRefFlowdataObj(); + + refFlowdataObj[timestamp] = flowdata; + + //fix + //params.address = params.adress; + logger.debug("received from terminal", params); + logger.debug("date/time:", new Date()); + logger.debug("tasks length:", tasks.length); + + //tasks = []; + + //add to tasks + tasks.push(params); + + } + } + }) + + + //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) + } + + + /** + * 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; + + RESTBuilder.make(function(builder) { + + if (!builder) return; + + builder.method('GET'); + builder.url('http://192.168.252.2:8004/gettime?projects_id=1'); + + builder.callback(function(err, response, output) { + + 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); + } + + }); + } + + } 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); + + } else { + //console.log("Read-only", stdout); + + 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]: [ + { + "ts": date, + "values": values + } + ] + } + + tbHandler.sendToTb(dataToTb, instance); + } + + + function calculateDuskDawn(date, line, duskOffset = 0, dawnOffset = 0) { + + if (date === undefined) date = new Date(); + + 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); + } + + //if(profile.dawn_lux_sensor == false) + { + if (profile.hasOwnProperty("dawn_astro_clock_offset")) dawn_astro_clock_offset = parseInt(profile.dawn_astro_clock_offset); + } + + } + + } catch (error) { + if (profilestr != "") { + logger.debug(profilestr); + logger.debug(error); + } + } + + 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; + } + + //Dimming, CCT + else if (register == 1) { + let brightness = 0; + let dimming = byte0; + if (dimming > 128) { + //dimming = -128; + brightness = dimming - 128; + } + + //cct + //Ak Byte3 == 1: CCT = (Byte2*256)+Byte1 + let cct; + if (byte3 == 1) cct = byte2 * 256 + byte1; + else cct = bytesToInt(bytes.slice(0, 3)); + + //cct podla auditu + + values["dimming"] = brightness; + return values; + } + + // + else if (register == 4) { + values["master_node_version"] = bytes[1] + "." + bytes[2]; + //logger.debug("FW Version", register, bytes); + } + + //Napätie + else if (register == 74) { + let voltage = (bytesToInt(bytes) * 0.1).toFixed(1); + values["voltage"] = Number(voltage); + } + + //Prúd + else if (register == 75) { + let current = bytesToInt(bytes); + values["current"] = current; + } + + //výkon + else if (register == 76) { + let power = (bytesToInt(bytes) * 0.1).toFixed(2); + values["power"] = Number(power); + } + + //účinník + else if (register == 77) { + let power_factor = Math.cos(bytesToInt(bytes) * 0.1 * (Math.PI / 180)).toFixed(2); + values["power_factor"] = Number(power_factor); + } + + //frekvencia + else if (register == 78) { + let frequency = (bytesToInt(bytes) * 0.1).toFixed(2); + values["frequency"] = Number(frequency); + } + + //energia + else if (register == 79) { + let energy = bytesToInt(bytes); + values["energy"] = energy / 1000; //energia v kWh -> delit 1000 + } + + //doba života + else if (register == 80) { + let lifetime = (bytesToInt(bytes) / 60).toFixed(2); + values["lifetime"] = Number(lifetime); + } + + //nastavenie profilu + else if (register == 8) { + let time_schedule_settings = bytesToInt(bytes); + values["time_schedule_settings"] = time_schedule_settings; + } + + //naklon - nateraz sa z nodu nevycitava! kvoli problemom s accelerometrom a vracanymi hodnotami, posielame temp a x y z vo funkcii accelerometerData() + else if (register == 84) { + values["temperature"] = byte3 >= 128 ? (byte3 - 128) * (-1) : byte3; + values["inclination_x"] = byte2 >= 128 ? (byte2 - 128) * (-1) : byte2; + values["inclination_y"] = byte1 >= 128 ? (byte1 - 128) * (-1) : byte1; + values["inclination_z"] = byte0 >= 128 ? (byte0 - 128) * (-1) : byte0; + } + + //FW verzia nodu + else if (register == 89) { + //formát: "Byte3: Byte2.Byte1 (Byte0)" + values["fw_version"] = byte3 + ":" + byte2 + "." + byte1 + "(" + byte0 + ")"; + } + + else if (register == 87 || register == 6 || register == 7) { + var d = new Date(); + d.setHours(byte3, byte2, 0, 0); + let timestamp = d.getTime(); + + //aktuálny čas + if (register == 87) values["actual_time"] = timestamp; + //čas súmraku + else if (register == 6) values["dusk_time"] = timestamp; + //čas úsvitu + else if (register == 7) values["dawn_time"] = timestamp; + } + + 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; + + } + + + function getObjectByTbValue(object, tbname) { + return object[Object.keys(object).find(key => object[key].tbname === tbname)]; + } + + + function isObject(item) { + return (typeof item === "object" && !Array.isArray(item) && item !== null); + } + + + // we fake data, that should be received from accelerometer, as they are a bit unreliable. (temperature, x,y,z) + function accelerometerData() { + + if (temperatureInSenica === null) return; + + //clone nodesData and relaysData objects + let nodesData_clone = JSON.parse(JSON.stringify(nodesData)); + let relaysData_clone = JSON.parse(JSON.stringify(relaysData)); + + for (const key in relaysData_clone) { + + const lineData = relaysData_clone[key]; + const lineNumber = lineData.line; + const contactor = lineData.contactor; + + if (lineNumber === 0) continue; + + if (contactor === 1) { + + let date = Date.now(); + + Object.keys(nodesData_clone).forEach((node, index) => { + + setTimeout(function() { + + if (nodesData_clone[node].line === lineNumber) { + + // NOTE: if status of luminaire is NOK or OFFLINE, we do not send data; + let status = nodesData_clone[node].status; + if (status === "OFFLINE" || !status) return; + + let x = null; + if (naklony.hasOwnProperty(node)) x = naklony[node].naklon; + if (x === null) x = 0; + + sendTelemetry({ temperature: Math.round(temperatureInSenica + 10 + Math.floor(Math.random() * 3)), inclination_x: x, inclination_y: 0, inclination_z: 0 }, nodesData_clone[node].tbname, date); + } + + }, (index + 1) * 500); + }) + + } + } + } + + +} // end of instance.export + diff --git a/RVO25/flow/code.js b/RVO25/flow/code.js new file mode 100755 index 0000000..63b31bf --- /dev/null +++ b/RVO25/flow/code.js @@ -0,0 +1,90 @@ +exports.id = 'code'; +exports.title = 'Code'; +exports.group = 'Common'; +exports.color = '#656D78'; +exports.input = true; +exports.output = 1; +exports.author = 'Peter Širka'; +exports.icon = 'code'; +exports.version = '1.2.0'; +exports.options = { outputs: 1, code: 'send(0, value);', keepmessage: true }; + +exports.html = `
+
+
+
@(Number of outputs)
+
@(Minimum is 1)
+
+
+
@(Code)
+
@(Keep message instance)
+
+`; + +exports.readme = `# Code + +This component executes custom JavaScript code as it is and it doesn't contain any secure scope. + +\`\`\`javascript +// value {Object} contains received data +// send(outputIndex, newValue) sends a new value +// error(value) sends an error +// instance {Object} a current component instance +// flowdata {Object} a current flowdata +// repository {Object} a current repository of flowdata +// Example: + +// send() can be execute multiple times +send(0, value); +\`\`\``; + +exports.install = function(instance) { + + var fn; + + instance.on('data', function(response) { + if (fn) { + try { + fn(response.data, instance, response, instance.options, response.repository, require); + } catch (e) { + response.data = e; + instance.throw(response); + } + } + }); + + instance.reconfigure = function() { + try { + if (instance.options.code) { + instance.status(''); + var code = 'var send = function(index, value) { if (options.keepmessage) { flowdata.data = value; instance.send2(index, flowdata); } else instance.send2(index, value);}; var error = function(err) { instance.throw(err); }; ' + instance.options.code; + fn = new Function('value', 'instance', 'flowdata', 'options', 'repository', 'require', code); + } else { + instance.status('Not configured', 'red'); + fn = null; + } + } catch (e) { + fn = null; + instance.error('Code: ' + e.message); + } + }; + + instance.on('options', instance.reconfigure); + instance.reconfigure(); +}; \ No newline at end of file diff --git a/RVO25/flow/comment.js b/RVO25/flow/comment.js new file mode 100755 index 0000000..1e0cd13 --- /dev/null +++ b/RVO25/flow/comment.js @@ -0,0 +1,11 @@ +exports.id = 'comment'; +exports.title = 'Comment'; +exports.group = 'Common'; +exports.color = '#704cff'; +exports.author = 'Martin Smola'; +exports.icon = 'comment'; +exports.traffic = false; +exports.version = '1.0.0'; +exports.readme = '# Comment'; + +exports.install = function() {}; diff --git a/RVO25/flow/count.js b/RVO25/flow/count.js new file mode 100755 index 0000000..fa92ee9 --- /dev/null +++ b/RVO25/flow/count.js @@ -0,0 +1,60 @@ +exports.id = 'count'; +exports.title = 'Count'; +exports.version = '1.0.1'; +exports.author = 'John Graves'; +exports.color = '#656D78'; +exports.icon = 'plus-square'; +exports.input = 2; +exports.output = 1; +exports.options = { increment: 1, initialvalue: 1 }; +exports.readme = `# Counter + +Counter Number of times called.`; + +exports.html = `
+
@(Initial Value)
+
@(Increment)
+

Example Video

+
`; + +exports.readme = `# Count + +This component counts the number of messages received. + +__Response:__ + +Integer value based on the initial value and increment settings. + +__Arguments:__ +- Initial Value: What number should be output on the receipt of the first message. +- Increment: What should the increment be for each following message received.`; + +exports.install = function(instance) { + + var count = 0; + var initialCall = true; + + instance.on('data', function(flowdata) { + var index = flowdata.index; + if (index) { + instance.debug('Reset Count.'); + count = instance.options.initialvalue; + initialCall = true; + } else { + // If this is the first time, set the value to 'initial value' + if(initialCall) { + initialCall = false; + count = instance.options.initialvalue; + } else + count = count+instance.options.increment; + instance.status('Count:' + count); + instance.send2(count); + } + }); + + instance.on('options', function() { + count = instance.options.initialvalue; + initialCall = true; + }); + +}; diff --git a/RVO25/flow/db_connector.js b/RVO25/flow/db_connector.js new file mode 100755 index 0000000..65ee94b --- /dev/null +++ b/RVO25/flow/db_connector.js @@ -0,0 +1,286 @@ +exports.id = 'db_connector'; +exports.title = 'DbConnector'; +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.html = `
+
+
+
DbConnector
+
+
+
`; + +exports.readme = `# read/write data to tables`; + +const instanceSendTo = { + debug: 0, + http_response: 1, +} + +const { promisifyBuilder, makeMapFromDbResult } = require('./helper/db_helper.js'); + +function extractWhereParams(params) +{ + let name = params[0]; + let operator = '='; + let value = params[1]; + + if(params.length == 3) + { + operator = params[1]; + value = params[2]; + } + + return {name: name, operator: operator, value: value}; +} + +exports.install = function(instance) { + + let refFlowdata = null;//holds reference to httprequest flowdata + + instance.on("close", () => { + + }) + + + instance.on("data", async function(flowdata) { + + let params = flowdata.data.body; + console.log("DbConnector", params); + + refFlowdata = flowdata; + + if(refFlowdata != undefined) + { + //make http response + let responseObj = {}; + responseObj["type"] = "SUCESS"; + + try{ + + let table = params.table; + let action = params.action; + + + if(params.data != undefined) + { + let className = params.data.className; + + if(className == "SqlQueryBuilder") + { + let type = params.data.type; + + console.log("SqlQueryBuilder---->", params.data); + + if(type == "SELECT") + { + let table = params.data.queryData.tables[0].table; + + const db = TABLE(table); + var builder = db.find(); + + let result = await promisifyBuilder(builder); + + let response = {}; + response["result"] = result; + response["success"] = true; + + responseObj["data"] = response; + + //console.log(responseObj); + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + } + + return; + } + } + + + console.log("db_connector---->", table, action); + + //actions: read, replace, insert, delete, update... + + if(action == "read") + { + const db = TABLE(params.table); + + //where builder.where('age', '<', 15); + //builder.where('id', 3403); + + var builder = db.find(); + + //https://docs.totaljs.com/latest/en.html#api~DatabaseBuilder~builder.where + if(params.hasOwnProperty("where")) + { + //optionalCan contain "=", "<=", "<", ">=", ">". + //Default value: '=' + + //1.["production_line", 1] + //2. ["or", ["production_line", 1], ["production_line", 2], "end"] + + if (Array.isArray(params.where)) { + + let multipleConditions = false; + + if(params.where[0] == "or") multipleConditions = true; + if (Array.isArray(params.where[0])) multipleConditions = true; + + if(multipleConditions) + { + + for(var i = 0; i < params.where.length; i++) + { + const item = params.where[i]; + + if(item === "or") builder.or(); + + if (Array.isArray(item)) + { + const { name, operator, value } = extractWhereParams(item); + builder.where(name, operator, value); + } + + if(item === "end") builder.end(); + + } + + } + else + { + const { name, operator, value } = extractWhereParams(params.where); + builder.where(name, operator, value); + } + + } + + /* + if(params.where.length >=2 ) + { + let name = params.where[0]; + let operator = '='; + let value = params.where[1]; + + if(params.where.length == 3) + { + operator = params.where[1]; + value = params.where[2]; + } + + builder.where(name, operator, value); + } + */ + } + + if(params.hasOwnProperty("between")) + { + builder.between(params.between[0], params.between[1], params.between[2]); + } + + let response = await promisifyBuilder(builder); + responseObj["data"] = response; + + //console.log(responseObj); + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + + return; + } + + if(action == "delete") + { + + } + + + if(action == "update") + { + //! data receiving from terminal (params) + // { + // hostname: 'localhost', + // table: 'settings', + // action: 'update', + // body: { + // rvo_name: 'terrrr', + // lang: 'en', + // temperature_adress: '28.427B45920702', + // latitude: 48.70826502, + // longitude: 17.28455203, + // mqtt_host: '192.168.252.4', + // mqtt_clientid: 'showroom_test_panel_led', + // mqtt_username: 'xmRd6RJxW53WZe4vMFLU', + // mqtt_port: 1883, + // maintanace_mode: false + // } + // } + const tableToModify = TABLE(params.table); + const newValues = params.body; + + tableToModify.modify(newValues).make(function(builder) { + + builder.callback(function(err, response) { + + if(!err) + { + responseObj["data"] = response; + responseObj["tableUpdated"] = true; + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + } + }); + }); + + } + + if(action == "replace") + { + //truncate table + const db = TABLE(params.table); + var builder = db.remove(); + db.clean(); + + //insert data + let data = params.data; + + for(let i = 0; i < data.length; i++) + { + //console.log(data[i]); + db.insert(data[i]); + } + + console.log("insert done"); + + let responseObj = {}; + responseObj["type"] = "SUCESS"; + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + + + } + + + + } catch (error) { + //console.log(error); + responseObj["type"] = "ERROR"; + responseObj["message"] = error; + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + } + } + }) +} + + diff --git a/RVO25/flow/db_init.js b/RVO25/flow/db_init.js new file mode 100755 index 0000000..b399878 --- /dev/null +++ b/RVO25/flow/db_init.js @@ -0,0 +1,113 @@ +exports.id = 'db_init'; +exports.title = 'DB Initialization'; +exports.group = 'Worksys'; +exports.color = '#888600'; +exports.version = '1.0.2'; +exports.icon = 'sign-out'; +exports.output = 2; + +exports.readme = ` + # DB initialization +`; + +const { promisifyBuilder, makeMapFromDbResult } = require('./helper/db_helper.js'); +const { initNotification } = require('./helper/notification_reporter'); +const errorHandler = require('./helper/ErrorToServiceHandler'); +const total_energy = require('../databases/total_energy'); + +const SEND_TO = { + db_init: 0, + infoSender: 1 +}; + + +exports.install = async function(instance) { + const dbNodes = TABLE("nodes"); + const dbRelays = TABLE("relays"); + const dbSettings = TABLE("settings"); + 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 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.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"]; + Object.keys(dbs.nodesData).forEach(node => dbs.nodesData[node].readout = {}) + + let rvo_number = responseSettings[0]["rvo_name"].match(/\D+(\d{1,2})_/)[1]; + + dbs.settings = { + edge_fw_version: "2025-10-08", //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"], + phases: responseSettings[0]["phases"], + cloud_topic: responseSettings[0]["cloud_topic"], + has_main_switch: responseSettings[0]["has_main_switch"], + daily_report: responseSettings[0]["daily_report"], + send_changed_node_numbers: responseSettings[0]["send_changed_node_numbers"], + rvo_number: rvo_number, + + //dynamic values + masterNodeIsResponding: true, //cmd_manager + maintenance_mode: false, + } + + + dbs.settings.energy_to_switch_lamps = total_energy[rvo_number]; + if (dbs.settings.energy_to_switch_lamps === undefined) console.log('=============== db_init.js: energy_to_switch_lamps is undefined'); + + FLOW.dbLoaded = true; + errorHandler.setProjectId(dbs.settings.project_id); + initNotification(); + + //APP START - send to data services + const toService = { + id: dbs.settings.project_id, + name: dbs.settings.rvo_name, + fw_version: dbs.settings.edge_fw_version, + startdate: new Date().toISOString().slice(0, 19).replace('T', ' '), + js_error: "", + error_message: "" + }; + + instance.send(SEND_TO.infoSender, toService); + console.log("----------------> START - message send to service", toService); + + setTimeout(() => { + console.log("DB_INIT - data loaded"); + instance.send(SEND_TO.db_init, "_") + }, 5000) + +}; + diff --git a/RVO25/flow/debug.js b/RVO25/flow/debug.js new file mode 100755 index 0000000..00cb259 --- /dev/null +++ b/RVO25/flow/debug.js @@ -0,0 +1,100 @@ +exports.id = 'debug'; +exports.title = 'Debug'; +exports.author = 'Peter Širka'; +exports.color = '#967ADC'; +exports.click = true; +exports.input = true; +exports.icon = 'bug'; +exports.version = '2.0.4'; +exports.options = { enabled: true, repository: false, type: 'data' }; +exports.readme = `# Debug + +Prints data to the debug tab.`; + +exports.html = `
+
+
+
@(Output type)
+
@(Path to the property (leave empty to show the whole data object))
+
@(A group name)
+
@(Enabled)
+
+
+
`; + +exports.install = function(instance) { + + instance.on('data', function(response) { + if (instance.options.enabled) { + + var opt = instance.options; + var rep = response.repository; + var val = response.data; + var id = response.id; + + switch (instance.options.type){ + case 'both': + var data = {}; + data.repository = rep; + data.data = val instanceof Error ? { error: val.message, stack: val.stack } : val; + instance.debug(safeparse(opt.property ? U.get(data, opt.property) : data), undefined, opt.group, id); + break; + case 'repository': + instance.debug(safeparse(opt.property ? U.get(rep, opt.property) : rep), undefined, opt.group, id); + break; + case 'data': + default: + if (val instanceof Error) + instance.debug({ error: val.message, stack: val.stack }, undefined, opt.group, id); + else + instance.debug(safeparse(opt.property ? U.get(val, opt.property) : val), undefined, opt.group, id); + break; + } + } + }); + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + instance.save(); + }); + + instance.on('options', function() { + instance.custom.status(); + }); + + instance.custom.status = function() { + instance.status(instance.options.enabled ? 'Enabled' : 'Disabled'); + }; + + instance.custom.status(); + + function safeparse(o) { + + if (o instanceof Buffer) + return o; + + if (o === undefined) + return 'undefined'; + + if (o === null) + return 'null'; + + var cache = []; + var str = JSON.stringify(o, function(key, value) { + if (typeof value === 'object' && value !== null) { + if (cache.indexOf(value) !== -1) { + try { + return JSON.parse(JSON.stringify(value)); + } catch (error) { + return; + } + } + cache.push(value); + } + return value; + }); + cache = null; + return JSON.parse(str); + } +}; diff --git a/RVO25/flow/designer.json b/RVO25/flow/designer.json new file mode 100755 index 0000000..580f5a3 --- /dev/null +++ b/RVO25/flow/designer.json @@ -0,0 +1,3102 @@ +{ + "tabs": [ + { + "name": "MAIN PUSH", + "linker": "main-push", + "id": "1612772287426", + "index": 0 + }, + { + "name": "CMD manager", + "linker": "cmd-manager", + "id": "1615551125555", + "index": 1 + }, + { + "name": "Devices", + "linker": "devices", + "id": "1611921777196", + "index": 2 + } + ], + "components": [ + { + "id": "1611951142547", + "component": "debug", + "tab": "1611921777196", + "name": "ERROR", + "x": 598, + "y": 60, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#DA4453", + "notes": "" + }, + { + "id": "1612776786008", + "component": "wsmqttpublish", + "tab": "1612772287426", + "name": "WS MQTT publish", + "x": 281.75, + "y": 174, + "connections": { + "0": [ + { + "index": "0", + "id": "1615551060773" + } + ], + "1": [ + { + "index": "0", + "id": "1618300858252" + }, + { + "index": "0", + "id": "1618558465485" + } + ], + "2": [ + { + "index": "0", + "id": "1634303685503" + } + ], + "3": [ + { + "index": "0", + "id": "1731068754606" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Connected", + "color": "green" + }, + "options": { + "username": "", + "clientid": "", + "port": "1883", + "host": "" + }, + "color": "#888600", + "notes": "" + }, + { + "id": "1612778461252", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "tb-push", + "x": 72.75, + "y": 328, + "connections": { + "0": [ + { + "index": "0", + "id": "1612783322136" + }, + { + "index": "1", + "id": "1612776786008" + }, + { + "index": "0", + "id": "1731068754606" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1612783322136", + "component": "debug", + "tab": "1612772287426", + "name": "to TB", + "x": 283.75, + "y": 324, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615551060773", + "component": "debug", + "tab": "1612772287426", + "name": "errors from MQTT Broker", + "x": 594, + "y": 57, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#DA4453", + "notes": "" + }, + { + "id": "1615563373927", + "component": "debug", + "tab": "1615551125555", + "name": "Debug", + "x": 755, + "y": 155, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#DA4453", + "notes": "" + }, + { + "id": "1615566865233", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "tb-push", + "x": 755, + "y": 248, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1615798582262", + "component": "debug", + "tab": "1615551125555", + "name": "CMD_debug", + "x": 755, + "y": 346, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615802995322", + "component": "debug", + "tab": "1611921777196", + "name": "Debug", + "x": 596.8833312988281, + "y": 566.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Disabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": false + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615809128443", + "component": "debug", + "tab": "1611921777196", + "name": "tempToTb", + "x": 595.8833312988281, + "y": 658.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615809595184", + "component": "virtualwireout", + "tab": "1611921777196", + "name": "tb-push", + "x": 597.8833312988281, + "y": 377.25, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1616165795916", + "component": "httproute", + "tab": "1615551125555", + "name": "POST /terminal", + "x": 135, + "y": 547, + "connections": { + "0": [ + { + "index": "0", + "id": "1684060205000" + }, + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Listening", + "color": "green" + }, + "options": { + "timeout": 10, + "cachepolicy": 0, + "cacheexpire": "5 minutes", + "size": 5, + "url": "/terminal", + "method": "POST", + "name": "", + "flags": [ + "id:1616165795916", + "post", + 10000 + ], + "emptyresponse": false + }, + "color": "#5D9CEC", + "notes": "### Configuration\n\n- __POST /terminal__\n- flags: \n- maximum request data length: __5 kB__\n- empty response: __false__\n- cache policy: __no cache__\n- cache expire: __5 minutes__", + "cloning": false + }, + { + "id": "1616165824813", + "component": "httpresponse", + "tab": "1615551125555", + "name": "HTTP Response", + "x": 753, + "y": 423, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "json" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1617104731852", + "component": "debug", + "tab": "1615551125555", + "name": "DIDO_Debug", + "x": 669, + "y": 1040, + "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": "turnOff line", + "x": 133, + "y": 1161, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "object", + "data": "{line: 3, command: \"turnOff\", force: true}" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1617115013095", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "tb-push", + "x": 669, + "y": 1150, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1617284749681", + "component": "trigger", + "tab": "1615551125555", + "name": "update profile / node", + "x": 112, + "y": 208, + "connections": { + "0": [ + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "data": "profile_nodes", + "datatype": "string" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1618235171399", + "component": "trigger", + "tab": "1615551125555", + "name": "tun tasks", + "x": 184, + "y": 279, + "connections": { + "0": [ + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "data": "run" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1618300858252", + "component": "debug", + "tab": "1612772287426", + "name": "wsmqtt-exit1", + "x": 597.8833312988281, + "y": 149, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1618393583970", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "to-cmd-manager", + "x": 668.8833312988281, + "y": 1269, + "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": 132.88333129882812, + "y": 367, + "connections": { + "0": [ + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "platform-rpc-call", + "color": "gray" + }, + "options": { + "wirename": "platform-rpc-call" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1618393759854", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "cmd_to_dido", + "x": 119.88333129882812, + "y": 1007, + "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": 752.8833312988281, + "y": 527, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "cmd_to_dido", + "color": "gray" + }, + "options": { + "wirename": "cmd_to_dido" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1618558465485", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "platform-rpc-call", + "x": 597.8833312988281, + "y": 247, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "platform-rpc-call", + "color": "gray" + }, + "options": { + "wirename": "platform-rpc-call" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1618572059773", + "component": "trigger", + "tab": "1615551125555", + "name": "turnOn line", + "x": 132, + "y": 1085, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "data": "{line: 1, command: \"turnOn\", force: true}", + "datatype": "object" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1619515097737", + "component": "cmd_manager", + "tab": "1615551125555", + "name": "CMD Manager", + "x": 452.1091003417969, + "y": 341.05455017089844, + "connections": { + "0": [ + { + "index": "0", + "id": "1615563373927" + } + ], + "1": [ + { + "index": "0", + "id": "1615566865233" + }, + { + "index": "0", + "id": "1615798582262" + } + ], + "2": [ + { + "index": "0", + "id": "1616165824813" + } + ], + "3": [ + { + "index": "0", + "id": "1618393827655" + } + ], + "4": [ + { + "index": "0", + "id": "1635936391935" + } + ], + "5": [ + { + "index": "0", + "id": "1757006030239" + }, + { + "index": "0", + "id": "1757006060377" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1619605019281", + "component": "httproute", + "tab": "1615551125555", + "name": "GET db", + "x": 173, + "y": 653, + "connections": { + "0": [ + { + "index": "0", + "id": "1684060205000" + }, + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Listening", + "color": "green" + }, + "options": { + "timeout": 5, + "cachepolicy": 0, + "cacheexpire": "5 minutes", + "size": 5, + "url": "/db", + "method": "GET", + "name": "", + "flags": [ + "id:1619605019281", + "get", + 5000 + ] + }, + "color": "#5D9CEC", + "notes": "### Configuration\n\n- __GET /db__\n- flags: undefined\n- maximum request data length: __5 kB__\n- empty response: __undefined__\n- cache policy: __no cache__\n- cache expire: __5 minutes__", + "cloning": false + }, + { + "id": "1619784672383", + "component": "trigger", + "tab": "1615551125555", + "name": "turnOnAlarm", + "x": 120, + "y": 1234, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "object", + "data": "{command: \"turnOnAlarm\"}" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1619784812964", + "component": "trigger", + "tab": "1615551125555", + "name": "turnOffAlarm", + "x": 118, + "y": 1307, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "object", + "data": "{command: \"turnOffAlarm\"}" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1621340721628", + "component": "virtualwireout", + "tab": "1611921777196", + "name": "modbus_to_dido", + "x": 599, + "y": 471, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "modbus_to_dido", + "color": "gray" + }, + "options": { + "wirename": "modbus_to_dido" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1622640022885", + "component": "httproute", + "tab": "1615551125555", + "name": "POST /db_connector", + "x": 98, + "y": 1586, + "connections": { + "0": [ + { + "index": "0", + "id": "1622640073521" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Listening", + "color": "green" + }, + "options": { + "timeout": 5, + "cachepolicy": 0, + "cacheexpire": "5 minutes", + "size": 5, + "url": "/db_connector", + "method": "POST", + "flags": [ + "id:1622640022885", + "post", + 5000 + ] + }, + "color": "#5D9CEC", + "notes": "### Configuration\n\n- __POST /db_connector__\n- flags: \n- maximum request data length: __5 kB__\n- empty response: __undefined__\n- cache policy: __no cache__\n- cache expire: __5 minutes__", + "cloning": false + }, + { + "id": "1622640073521", + "component": "db_connector", + "tab": "1615551125555", + "name": "DbConnector", + "x": 372, + "y": 1572, + "connections": { + "1": [ + { + "index": "0", + "id": "1622641420685" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "edge": "undefined" + }, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1622641420685", + "component": "httpresponse", + "tab": "1615551125555", + "name": "HTTP Response", + "x": 596, + "y": 1586, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1634303504177", + "component": "monitormemory", + "tab": "1612772287426", + "name": "RAM", + "x": 69.88333129882812, + "y": 888.5, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465281992" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "858.88 MB / 985.68 MB", + "color": "gray" + }, + "options": { + "enabled": true, + "interval": 30000 + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1634303533779", + "component": "monitordisk", + "tab": "1612772287426", + "name": "disk", + "x": 70.88333129882812, + "y": 982.5, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465821120" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "5.78 GB / 7.26 GB", + "color": "gray" + }, + "options": { + "enabled": true, + "path": "/", + "interval": 30000 + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1634303595494", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "send-to-services", + "x": 51.883331298828125, + "y": 1400.5, + "connections": { + "0": [ + { + "index": "0", + "id": "1634463186563" + }, + { + "index": "1", + "id": "1634488120710" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1634303602169", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "send-to-services", + "x": 426.8833312988281, + "y": 878.5, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1634303685503", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "send-to-services", + "x": 600.8833312988281, + "y": 341.5, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1634303743260", + "component": "httprequest", + "tab": "1612772287426", + "name": "192.168.252.2:8004/sentmessage", + "reference": "", + "x": 506.8833312988281, + "y": 1331.7333374023438, + "connections": { + "0": [ + { + "index": "0", + "id": "1635327431236" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "url": "http://192.168.252.2:8004/sentmessage", + "method": "POST", + "stringify": "json" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1634463186563", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 305.75, + "y": 1442, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634464580289", + "component": "code", + "tab": "1612772287426", + "name": "Code", + "x": 245, + "y": 787, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465243324" + }, + { + "index": "0", + "id": "1634303602169" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "keepmessage": true, + "code": "let response = {};\nresponse.cpu = value.cpu;\nresponse.uptime = value.uptime;\n\nsend(0, response);", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1634465243324", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 428, + "y": 784, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634465281992", + "component": "code", + "tab": "1612772287426", + "name": "Code", + "x": 245, + "y": 884, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465338103" + }, + { + "index": "0", + "id": "1634303602169" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "keepmessage": true, + "code": "value.sender = \"ram\";\n\nlet response = {};\n\nresponse.memory_total = Math.round(value.total / (1024 ** 2));\nresponse.memory_free = Math.round(value.free / (1024 ** 2));\nresponse.memory_used = Math.round(value.used / (1024 ** 2));\n\nsend(0, response);", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1634465338103", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 429, + "y": 976, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634465821120", + "component": "code", + "tab": "1612772287426", + "name": "Code", + "x": 245, + "y": 978, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465892500" + }, + { + "index": "0", + "id": "1634303602169" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "keepmessage": true, + "code": "value.sender = \"hdd\";\n\nlet response = {};\n\nresponse.hdd_total = Math.round(value.total / (1024 ** 2));\nresponse.hdd_free = Math.round(value.free / (1024 ** 2));\nresponse.hdd_used = Math.round(value.used / (1024 ** 2));\n\nsend(0, response);", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1634465892500", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 432, + "y": 1068, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634484067516", + "component": "debug", + "tab": "1612772287426", + "name": "Send info", + "x": 513, + "y": 1441, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634488120710", + "component": "infosender", + "tab": "1612772287426", + "name": "Info sender", + "x": 301, + "y": 1336, + "connections": { + "0": [ + { + "index": "0", + "id": "1634484067516" + }, + { + "index": "0", + "id": "1634303743260" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "edge": "undefined" + }, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1635327431236", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 837.8833312988281, + "y": 1325.5, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1635936391935", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "send-to-services", + "x": 753, + "y": 623, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1637069803394", + "component": "monitorconsumption", + "tab": "1612772287426", + "name": "CPU", + "x": 69, + "y": 791, + "connections": { + "0": [ + { + "index": "0", + "id": "1634464580289" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "49.2% / 69.91 MB", + "color": "gray" + }, + "options": { + "monitorfiles": true, + "monitorconnections": true, + "monitorsize": true, + "monitorconsumption": true, + "enabled": true, + "interval": 30000 + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1683664161036", + "component": "debug", + "tab": "1615551125555", + "name": "CMDtoDIDO", + "x": 392, + "y": 1012, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1683981346282", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "from-dido-controller", + "x": 112, + "y": 459, + "connections": { + "0": [ + { + "index": "0", + "id": "1684055037116" + }, + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "from-dido-controller", + "color": "gray" + }, + "options": { + "wirename": "from-dido-controller" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1684055037116", + "component": "debug", + "tab": "1615551125555", + "name": "from dido to cmd", + "x": 451, + "y": 532, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1684060205000", + "component": "debug", + "tab": "1615551125555", + "name": "HTTP routes", + "x": 450, + "y": 639, + "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": "MDBToDido", + "x": 598, + "y": 147, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1699963668903", + "component": "dido_controller", + "tab": "1615551125555", + "name": "DIDO_Controller", + "x": 397, + "y": 1131, + "connections": { + "0": [ + { + "index": "0", + "id": "1617104731852" + } + ], + "1": [ + { + "index": "0", + "id": "1617104731852" + }, + { + "index": "0", + "id": "1617115013095" + } + ], + "2": [ + { + "index": "0", + "id": "1618393583970" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "edge": "undefined" + }, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1699964678894", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "modbus_to_dido", + "x": 96, + "y": 924, + "connections": { + "0": [ + { + "index": "0", + "id": "1699963668903" + }, + { + "index": "0", + "id": "1699964793925" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "modbus_to_dido", + "color": "gray" + }, + "options": { + "wirename": "modbus_to_dido" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1699964793925", + "component": "debug", + "tab": "1615551125555", + "name": "modbusToDido", + "x": 388, + "y": 920, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1699965957410", + "component": "modbus_reader", + "tab": "1611921777196", + "name": "Modbus reader", + "x": 232, + "y": 175, + "connections": { + "0": [ + { + "index": "0", + "id": "1611951142547" + } + ], + "1": [ + { + "index": "0", + "id": "1621340721628" + }, + { + "index": "0", + "id": "1684179110403" + }, + { + "index": "0", + "id": "1717441414646" + } + ], + "2": [ + { + "index": "0", + "id": "1615809595184" + }, + { + "index": "0", + "id": "1714752862828" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1700411878636", + "component": "thermometer", + "tab": "1611921777196", + "name": "Thermometer", + "x": 234.75, + "y": 444, + "connections": { + "0": [ + { + "index": "0", + "id": "1615802995322" + } + ], + "1": [ + { + "index": "0", + "id": "1615809595184" + }, + { + "index": "0", + "id": "1615809128443" + } + ], + "2": [ + { + "index": "0", + "id": "1621340721628" + }, + { + "index": "0", + "id": "1732889185927" + }, + { + "index": "0", + "id": "1717441414646" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#5CB36D", + "notes": "" + }, + { + "id": "1714752862828", + "component": "debug", + "tab": "1611921777196", + "name": "MDBToTb", + "x": 766, + "y": 324, + "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": 764.0833282470703, + "y": 222, + "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\telse if(value.status === \"NOK-thermometer\")\n\t{\n\t\tsend(0, {\"thermometer\": \"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\telse if(value.values.hasOwnProperty(\"temperature\"))\n\t{\n\t\tsend(0, {\"thermometer\": \"OK\"});\n\t}\n}", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1717442627834", + "component": "debug", + "tab": "1611921777196", + "name": "modbus service", + "x": 966.0833282470703, + "y": 165, + "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": 968.0833282470703, + "y": 268, + "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": 88.75, + "y": 1685, + "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": 296, + "y": 1671, + "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\", \"Flow has been restarted\", \"Node db has changed\"]", + "types": "[\"emergency\", \"critical\", \"error\", \"alert\"]", + "name": "" + }, + "color": "#30E193", + "notes": "" + }, + { + "id": "1718016073501", + "component": "httprequest", + "tab": "1612772287426", + "name": "http://192.168.252.2:8004/slack", + "x": 495, + "y": 1753, + "connections": { + "0": [ + { + "index": "0", + "id": "1718016086212" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "url": "http://192.168.252.2:8004/slack", + "method": "POST", + "stringify": "json" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1718016086212", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 832, + "y": 1664, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "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": 87, + "y": 1591, + "connections": { + "0": [ + { + "index": "0", + "id": "1718016052341" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "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\": \"\" } } } ] }", + "datatype": "object" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1729855334955", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "platform-rpc-call", + "x": 599.9333343505859, + "y": 541.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "platform-rpc-call", + "color": "gray" + }, + "options": { + "wirename": "platform-rpc-call" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1729855371093", + "component": "debug", + "tab": "1612772287426", + "name": "rpc cloud", + "x": 601.9333343505859, + "y": 440.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1731068658334", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 75.75, + "y": 184, + "connections": { + "0": [ + { + "index": "0", + "id": "1612776786008" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731068754606", + "component": "cloudmqttconnect", + "tab": "1612772287426", + "name": "MQTT to senica-prod01", + "x": 284.75, + "y": 452, + "connections": { + "1": [ + { + "index": "0", + "id": "1729855371093" + }, + { + "index": "0", + "id": "1729855334955" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Connected", + "color": "green" + }, + "options": { + "username": "", + "clientid": "", + "port": "2764", + "host": "192.168.252.2", + "topic": "" + }, + "color": "#888600", + "notes": "" + }, + { + "id": "1731069001548", + "component": "db_init", + "tab": "1612772287426", + "name": "DB Initialization", + "x": 1003.75, + "y": 240.25, + "connections": { + "0": [ + { + "index": "0", + "id": "1731069033416" + } + ], + "1": [ + { + "index": "0", + "id": "1747561603739" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#888600", + "notes": "" + }, + { + "id": "1731069033416", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "db-init", + "x": 1244.75, + "y": 233.25, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069059135", + "component": "showdb", + "tab": "1612772287426", + "name": "Show db data", + "x": 1186.75, + "y": 821.25, + "connections": { + "0": [ + { + "index": "0", + "id": "1731069079243" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#888600", + "notes": "" + }, + { + "id": "1731069079243", + "component": "debug", + "tab": "1612772287426", + "name": "dbData", + "x": 1390.75, + "y": 870.25, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1731069116691", + "component": "trigger", + "tab": "1612772287426", + "name": "settings", + "x": 934.75, + "y": 669.75, + "connections": { + "0": [ + { + "index": "0", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069131637", + "component": "trigger", + "tab": "1612772287426", + "name": "relaysData", + "x": 876.75, + "y": 733.75, + "connections": { + "0": [ + { + "index": "1", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069137374", + "component": "trigger", + "tab": "1612772287426", + "name": "nodesData", + "x": 852.75, + "y": 794.75, + "connections": { + "0": [ + { + "index": "2", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069179846", + "component": "trigger", + "tab": "1612772287426", + "name": "pinsData", + "x": 850.75, + "y": 861.75, + "connections": { + "0": [ + { + "index": "3", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069192937", + "component": "trigger", + "tab": "1612772287426", + "name": "sample data", + "x": 857.75, + "y": 928.75, + "connections": { + "0": [ + { + "index": "4", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069264443", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 63.75, + "y": 1279, + "connections": { + "0": [ + { + "index": "0", + "id": "1634488120710" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069334626", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "db-init", + "x": 172.88333129882812, + "y": 129, + "connections": { + "0": [ + { + "index": "0", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069548145", + "component": "virtualwirein", + "tab": "1611921777196", + "name": "db-init", + "x": 46.75, + "y": 192, + "connections": { + "0": [ + { + "index": "0", + "id": "1699965957410" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069567152", + "component": "virtualwirein", + "tab": "1611921777196", + "name": "db-init", + "x": 44.75, + "y": 465, + "connections": { + "0": [ + { + "index": "0", + "id": "1700411878636" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731070156936", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "db-init", + "x": 126.88333129882812, + "y": 1377, + "connections": { + "0": [ + { + "index": "2", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731234189516", + "component": "trigger", + "tab": "1612772287426", + "name": "monitor.txt", + "x": 882.75, + "y": 991.75, + "connections": { + "0": [ + { + "index": "5", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731234189551", + "component": "trigger", + "tab": "1612772287426", + "name": "err.txt", + "x": 904.75, + "y": 1053.75, + "connections": { + "0": [ + { + "index": "6", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1732700042559", + "component": "nodesdb_change_check", + "tab": "1612772287426", + "name": "Nodes DB change check", + "x": 266.8833312988281, + "y": 1980.2333984375, + "connections": { + "0": [ + { + "index": "0", + "id": "1732700071298" + }, + { + "index": "0", + "id": "1732700642917" + } + ], + "1": [ + { + "index": "0", + "id": "1759958914348" + }, + { + "index": "0", + "id": "1759959003114" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#888600", + "notes": "" + }, + { + "id": "1732700057052", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 76.75, + "y": 1988, + "connections": { + "0": [ + { + "index": "0", + "id": "1732700042559" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1732700071298", + "component": "debug", + "tab": "1612772287426", + "name": "nodesChange", + "x": 571.8833312988281, + "y": 2018.2333984375, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1732700642917", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "tb-push", + "x": 567.8833312988281, + "y": 1933, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1732889185927", + "component": "debug", + "tab": "1611921777196", + "name": "tempToDido", + "x": 594.8833312988281, + "y": 753, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1733574412965", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 72.75, + "y": 474, + "connections": { + "0": [ + { + "index": "1", + "id": "1731068754606" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1747561603739", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "send-to-services", + "x": 1243.8833312988281, + "y": 334.5, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1747562867845", + "component": "comment", + "tab": "1612772287426", + "name": "FLOW STARTING POINT", + "x": 1003.5666656494141, + "y": 178, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#704cff", + "notes": "" + }, + { + "id": "1749211698385", + "component": "trigger", + "tab": "1612772287426", + "name": "deviceStatus", + "x": 911.75, + "y": 1116.75, + "connections": { + "0": [ + { + "index": "7", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1757006030239", + "component": "httprequest", + "tab": "1615551125555", + "name": "192.168.252.2:8015/daily_report", + "x": 756.5666656494141, + "y": 715.4499969482422, + "connections": { + "0": [ + { + "index": "0", + "id": "1757006045804" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "stringify": "json", + "method": "POST", + "url": "http://192.168.252.2:8015/daily_report" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1757006045804", + "component": "debug", + "tab": "1615551125555", + "name": "ddd", + "x": 1091.566665649414, + "y": 711.4499969482422, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1757006060377", + "component": "debug", + "tab": "1615551125555", + "name": "reportDebug", + "x": 749.5666656494141, + "y": 799.4499969482422, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1759958914348", + "component": "httprequest", + "tab": "1612772287426", + "name": "http://192.168.252.2:8015/node_numbers", + "x": 571, + "y": 2111, + "connections": { + "0": [ + { + "index": "0", + "id": "1759958927094" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "stringify": "json", + "method": "POST", + "url": "http://192.168.252.2:8015/node_numbers" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1759958927094", + "component": "debug", + "tab": "1612772287426", + "name": "nodesChangeCloud", + "x": 951.8833312988281, + "y": 2109.2333984375, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1759959003114", + "component": "debug", + "tab": "1612772287426", + "name": "nodeChangeCloud1", + "x": 574, + "y": 2218, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1760020290879", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 84.75, + "y": 1787, + "connections": { + "0": [ + { + "index": "1", + "id": "1718016052341" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + } + ], + "version": 615 +} diff --git a/RVO25/flow/dido_controller.js b/RVO25/flow/dido_controller.js new file mode 100755 index 0000000..d16fb19 --- /dev/null +++ b/RVO25/flow/dido_controller.js @@ -0,0 +1,1486 @@ +exports.id = 'dido_controller'; +exports.title = 'DIDO_Controller'; +exports.version = '2.0.0'; +exports.group = 'Worksys'; +exports.color = '#2134B0'; +exports.input = 3; +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 + +state_of_main_switch - reportovat stav hlaveho istica : 0-> off 1-> on +rotary_switch_state - sem by sa mal reportovat stav vstupov manual a auto pola nasledovnej logiky: Manual = 1 a Auto = 0 -> Manu +Manual = 0 a Auto = 0 -> Off, Manual = 0 a Auto = 1 -> Automatic + +door_condition - pin 6, dverový kontakt -> 1 -> vyreportuje Closed, 0 -> vyreportuje Ope +twilight_sensor - hodnotu, ktoru vracia ten analogovy vstup (17) treba poslat sem ako float number. Zrejme tu potom pridame nejaky koeficient prevodu na luxy + +Na kazdu liniu +state_of_breaker - podla indexu istica sa reportuje jeho stav, teda istic na liniu 1: 0-> off, 1-> on +state_of_contactor - podla indexu stkaca sa reportuje jeho stav, teda stykac 1 na liniu 1: 0-> off, 1-> on +*/ + +const { errLogger, logger, monitor } = require('./helper/logger'); +const SerialPort = require('serialport'); +const WebSocket = require('ws'); +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 errorHandler = require('./helper/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 hasMainSwitch; + +let alarmStatus = "OFF"; + +const SEND_TO = { + debug: 0, + tb: 1, + cmd_manager: 2 +} + + +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 = {}; + let rsPortReceivedData = []; + + //to be able to get proper twilight values + let twilight_sensor_interval = 5;//minutes + let twilight_sensor = []; + const twilight_sensor_array = []; + let twilightError = false; + + monitor.info("DIDO_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-we make it global to see it from outside + FLOW.deviceStatus = { //key is device name: temperature,.... + "state_of_main_switch": "Off", //Hlavny istic (alebo druhy dverovy kontakt) + "rotary_switch_state": "Off", //Prevadzkovy + "door_condition": "closed", //Dverový kontakt + "em": "OK", //elektromer rvo + "temperature": "OK", //templomer + "battery": "OK", //Bateria + "power_supply": "OK", //Zdroj + "master_node": "OK", //MN - GLOBALS.settings.masterNodeIsResponding + "no_voltage": "OK", //GLOBALS.settings.no_voltage - vypadok napatia na faze + "state_of_breaker": {}, //"Off",//Istic + "state_of_contactor": {}, //"Off",//Stykac + "twilight_sensor": "OK" //lux sensor + }; + let deviceStatus = FLOW.deviceStatus; + + + function main() { + + GLOBALS = FLOW.GLOBALS; + SETTINGS = FLOW.GLOBALS.settings; + rvoTbName = SETTINGS.rvoTbName; + pinsData = GLOBALS.pinsData; + relaysData = GLOBALS.relaysData; + + tbHandler = new DataToTbHandler(SEND_TO.tb); + tbHandler.setSender(exports.title); + + controller_type = SETTINGS.controller_type; //"lm" or "unipi" + hasMainSwitch = SETTINGS.has_main_switch; + + if (controller_type == "") controller_type = "lm"; + + 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, "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; + } + } + + //report RVO version relaysData[0].tbname; + let values = {}; + values["edge_fw_version"] = SETTINGS.edge_fw_version; + values["maintenance_mode"] = SETTINGS.maintenance_mode; + + sendTelemetry(values, rvoTbName); + + 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); + } + + + function handleRsPort() { + + if (rsPort) { + rsPort.removeAllListeners(); + rsPort = null; + } + + //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('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) { + if (!err) { + monitor.info(exports.title + "--->Digital in_out has been set (runSyncExec was sucessfull)"); + + turnAlarm("off"); + 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('error', err => { + let message = "Dido: rsPort error: " + err.message; + logger.debug(message); + monitor.info(message); + errorHandler.sendMessageToService(message); + }) + + rsPort.on("close", () => { + let message = "Dido: rsPort closed - reconnecting ..."; + logger.debug(message); + monitor.info(message); + setTimeout(handleRsPort, 1000); + }) + + rsPort.open(); + } + + + function handleWebSocket() { + + if (ws) { + ws.removeAllListeners(); + ws = null; + } + + //to keep websocket opened, we send request every 150 seconds + let startRequests = null; + + console.log("handleWebSocket function called"); + ws = new WebSocket('ws:/0.0.0.0:1234/ws'); + + ws.onopen = function open() { + + instance.send(0, exports.title + " running"); + turnAlarm("off"); + + initialSetting(); + + setTimeout(function() { ws.send(JSON.stringify({ cmd: "all" })) }, 5000); + // we request dev info about neuron device from evok to keep websocket connection alive + // for some reason this request returns no data, but connection keeps alive + startRequests = setInterval(() => { + ws.send(JSON.stringify({ "cmd": "filter", "dev": ["neuron"] })); + }, 150000) + }; + + + // 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 = async 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; + + 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 => { + logger.debug('Dido: websocket error', err); + }) + + ws.onclose = function() { + logger.debug('Dido: websocket onclose, reconnecting...') + clearInterval(startRequests); + setTimeout(handleWebSocket, 1000); + } + } + + 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 turnAlarm(onOrOff) { + let value = 0; + if (onOrOff == "on") value = 1; + + if (value == 1 && SETTINGS.maintenance_mode) return; + + alarmStatus = "OFF"; + if (value == 1) alarmStatus = "ON"; + + if (rsPort) { + let arr = [0x55]; + arr.push(13); + arr.push(0); + arr.push(value); + + rsPort.write(Buffer.from(arr), function(err) { + logger.debug(`sirena - ${onOrOff}`); + }); + } + else if (ws) { + let cmd = { "cmd": "set", "dev": "relay", "circuit": "1_01", "value": value }; + ws.send(JSON.stringify(cmd)); + logger.debug(`sirena - ${onOrOff}`); + } + } + + + 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") { + bits.push(0); + } + else bits.push(1); + + if (deviceStatus["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); + } + + + // turn line on or off + function turnLine(onOrOff, line, pin, force, info) { + //onOrOff => "on" or "off" + let value = 0; + if (onOrOff == "on") value = 1; + + if (force == undefined) force = false; + + if (line == 0) { + if (value == 1 && alarmStatus == "ON") turnAlarm("off"); + SETTINGS.maintenance_mode = value ? true : false; + + 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); + return; + } + + if (pin === undefined) pin = getPin(line); + + if (pin === undefined) { + errLogger.error("pin is undefined!", line); + return; + } + + if (!force) { + if (relaysData[line].contactor == value) { + instance.send(SEND_TO.debug, `line is already ${onOrOff} ` + line); + logger.debug(`Dido: turnLine: line is already ${onOrOff} `, line); + return; + } + } + + // if(!rsPort.isOpen && !ws) + if (!rsPort && !ws) { + errLogger.error("Dido - port or websocket is not opened"); + return; + } + + if (rsPort) { + let arr = [0x55]; + arr.push(pin); + arr.push(0); + arr.push(value); + + rsPort.write(Buffer.from(arr), function(err) { + if (err === undefined) { + monitor.info(`Dido: turnLine ${onOrOff} zapisal do rsPort-u`, line, pin, arr, info); + switchLogic(arr); + } + else { + monitor.info(`Dido: turnLine ${onOrOff} WRITE error`, err); + } + }); + + } + else if (ws) { + //pin = "relay1_03" or "input1_01" ... we must make just "1_01" with slice method + monitor.info(`Dido: turnLine ${onOrOff} - (line, pin, force)`, line, pin, force, info); + let cmd = { "cmd": "set", "dev": "relay", "circuit": pin.slice(5), "value": value }; + ws.send(JSON.stringify(cmd)); + } + + //if rvo is 24/7, it has just one switching profile point at 13:00. we do not want to send notification as it repeats every day. + //const d = new Date(); + //if(d.getHours() != 13) sendNotification("Dido_controller: ", SETTINGS.rvoTbName, "switching_profile_point_applied_to_line", { line: line, value: onOrOff }, "", SEND_TO.tb, instance); + } + + + // 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; + + // 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) { + const status = flowdata.data.status; + if (status == "NOK-twilight_sensor") { + deviceStatus["twilight_sensor"] = "NOK"; + } + else if (status == "NOK-em340" || status == "NOK-em111") { + deviceStatus["em"] = "NOK"; + } + else if (status == "NOK-thermometer") { + deviceStatus["temperature"] = "NOK"; + } + } + else if ("values" in flowdata.data) { + 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" + } + else if (values.hasOwnProperty("temperature")) { + deviceStatus["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"; + } + + sendTelemetry(values, rvoTbName); + } + + sendRvoStatus(); + }) + + + + + // we expect array as flowdata.data + instance.on("1", flowdata => { + + //console.log(flowdata.data); + + if (!flowdata.data instanceof Object) return; + + let obj = flowdata.data; + let line = obj.line; + 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"); + }) + + + function calculateStateCode() { + + let bits = []; + + //Hlavny istic - state_of_main_switch => v rvo senica je to druhy door pre silovu cast (EM) + if (deviceStatus["state_of_main_switch"] === "closed" || deviceStatus["state_of_main_switch"] === "Off") { + bits.push(0); + } + else { + bits.push(1); + } + + //Prevadzkovy mod - Manual, Off, Automatic, maintenance_mode = true/false // DAVA 2 BITY + if (!SETTINGS.maintenance_mode) { + if (deviceStatus["rotary_switch_state"] === "Manual") { + bits.push(0); + bits.push(1); + } + + if (deviceStatus["rotary_switch_state"] === "Automatic") { + bits.push(0); + bits.push(0); + } + + if (deviceStatus["rotary_switch_state"] === "Off") { + bits.push(1); + bits.push(0); + } + } + else { + bits.push(1); + bits.push(1); + } + + //Dverovy kontakt + if (deviceStatus["door_condition"] === "closed") { + bits.push(0); + } + else { + bits.push(1); + } + + //EM + if (deviceStatus["em"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //Teplomer + if (deviceStatus["temperature"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //Batéria + if (deviceStatus["battery"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //Zdroj + if (deviceStatus["power_supply"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //MN + if (deviceStatus["master_node"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //výpadok napätia na fáze + if (deviceStatus["no_voltage"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + if (deviceStatus["twilight_sensor"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + // doplnime do 16 bitov (2 byty) + for (let i = bits.length; i < 16; i++) { + bits.push(0); + } + + // console.log("calculateStateCode - deviceStatus", deviceStatus); + // 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; + } + + + async function sendRvoStatus() { + + if (SETTINGS === undefined) return; + SETTINGS.masterNodeIsResponding ? deviceStatus["master_node"] = "OK" : deviceStatus["master_node"] = "NOK"; + + 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 pinsForRvoStatus(controllerType, hasMainSwitch) { + + let pins = []; + + if (controllerType === "lm") { + pins = [1, 4, 6]; + if (hasMainSwitch === 1) { + pins = [4, 6]; + } + } else if (controllerType === "unipi") { + pins = ["input1_01", "input1_04", "input1_05"]; + if (hasMainSwitch === 1) { + pins = ["input1_01", "input1_04"]; + } + } + + return pins; + } + + + function checkRvoStatus() { + + // 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 + //set RVO state + let status = "OK"; + + for (const [key, value] of Object.entries(deviceStatus)) { + if (["em", "twilight_sensor", "temperature", "master_node"].includes(key) && value === "NOK") status = "NOK"; + } + + if (status === "OK") { + + let pinIndexes = pinsForRvoStatus(controller_type, hasMainSwitch); + + for (const pinIndex of pinIndexes) { + if (previousValues[pinIndex] === 0) { + if ((pinIndex === 6 || pinIndex === 'input1_01' || pinIndex === 'input1_05') && SETTINGS.maintenance_mode) continue; + status = "NOK"; + break; + } + } + } + + // battery status. If value is 1 - battery is NOK + if (previousValues[5] === 1) status = "NOK"; + if (SETTINGS.no_voltage.size > 0) status = "NOK"; + + // console.log("rvo status",status) + return status; + } + + + // we pass array to function in case of rsPort ==> switchLogic([55,3,0,1]) ==> [[55,3,0,1]] + // we pass two values in case of websocket ==> switchLogic("relay1_03",1) ==> ["relay1_03",1] + const switchLogic = (...args) => { + + let values = {}; + let pinIndex, newPinValue, twilight; + + //data from rsPort + if (args.length == 1) { + pinIndex = args[0][1] + 1; + if (pinIndex === 17) pinIndex--; + newPinValue = args[0][3]; + twilight = args[0][2]; + } + //data from websocket + else { + pinIndex = args[0]; + newPinValue = args[1]; + } + + 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; + + //default value + let value = "On"; + if (newPinValue === 0) value = "Off"; + + //Hlavny istic + if (type === "state_of_main_switch" && hasMainSwitch) { + if (newPinValue === 0 && newPinValue !== previousValues[pinIndex]) { + sendNotification("switchLogic", rvoTbName, "main_switch_has_been_turned_off", {}, "", SEND_TO.tb, instance, "state_of_main_switch"); + 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"); + deviceStatus["state_of_main_switch"] = "On"; + } + } + + //Prevadzkovy mod + 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"; + + deviceStatus["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, "power_supply_has_disconnected_input", {}, "", SEND_TO.tb, instance, "power_supply"); + + deviceStatus["power_supply"] = "NOK"; + } + else if (newPinValue === 1 && newPinValue !== previousValues[pinIndex]) { + sendNotification("switchLogic", rvoTbName, "power_supply_works_correctly", {}, "", SEND_TO.tb, instance, "power_supply"); + + deviceStatus["power_supply"] = "OK"; + } + } + + //Bateria - 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"); + + deviceStatus["battery"] = "NOK"; + } + else if (newPinValue === 0 && newPinValue !== previousValues[pinIndex]) { + sendNotification("switchLogic", rvoTbName, "battery_level_is_ok", {}, "", SEND_TO.tb, instance, "battery_level"); + + deviceStatus["battery"] = "OK"; + } + } + + //Dverovy kontakt - pin 6 + //! Ak je rvo s dvoma dverovymi kontaktami, ked pride z evoku signal z input1_05, co bol predytm "state_of_main switch" handlujeme ho teraz ako 'door_condition' + else if (type == "door_condition" || type === "state_of_main_switch") { + newPinValue === 0 ? value = "open" : value = "closed"; + + let door = "door_main"; + if (type === "state_of_main_switch") door = "door_em"; + + if (value === "open") { + if (SETTINGS.maintenance_mode) { + sendNotification("switchLogic", rvoTbName, door + "_open", {}, "", SEND_TO.tb, instance, door); + } else { + sendNotification("switchLogic", rvoTbName, door + "_open_without_permission", {}, "", SEND_TO.tb, instance, door); + + // 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 (value === "closed") { + if (alarmStatus == "ON") turnAlarm("off"); + sendNotification("switchLogic", rvoTbName, door + "_close", {}, "", SEND_TO.tb, instance, door); + } + + deviceStatus[type] = value; + } + + //lux sensor + else if (type == "twilight_sensor") { + //! TODO - to show nok status, if lux value is not changing more then 10 times. + //Daylight is far more than 1000. So most of the day, when it is sunshine comes just value 1000. But lux sensor is not NOK. + //This is not the case in LM. If value from LM is the same 10x, there is 99% possibility, that sensor is NOK. + value = newPinValue; + + if (controller_type === 'lm') { + value = parseFloat(newPinValue + (256 * twilight)); + + 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 && !twilightError) { + twilightError = true; + let value = twilight_sensor_array.shift(); + + newPinValue = 0; + } + else if (set.size !== 1 && twilightError) { + //sendNotification("switchLogic", rvoTbName, 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) { + 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); + } + } + + 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); + } + + deviceStatus["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 (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 }); + + //mame iba 3 istice. vyreportujeme a ohandlujeme liniu na tom istom istici ako paralelna linia (napr linia 1, paralelna s nou je linia 4, key je string "4") + // ak je 7 linii, na 1 istici je linia 1,4,7 + + if (line == 1) { + + const lineOnSameBraker = [4, 7]; + + for (var i = 0; i < lineOnSameBraker.length; i++) { + if (!relaysData.hasOwnProperty(lineOnSameBraker[i])) continue; + + 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; + reportLineStatus(lineOnSameBraker[i]); + + values[type] = value; + const tbname = relaysData[lineOnSameBraker[i]].tbname; + sendTelemetry(values, tbname); + + delete values[type]; + } + + } + else { + const lineOnSameBraker = line + 3 + ""; + + if (relaysData.hasOwnProperty(lineOnSameBraker)) { + 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; + reportLineStatus(line + 3); + + values[type] = value; + const tbname = relaysData[lineOnSameBraker].tbname; + sendTelemetry(values, tbname); + + delete values[type]; + } + } + + } + + if (value == "Off") values["status"] = "NOK"; + deviceStatus["state_of_breaker"][line] = value; + + reportLineStatus(line); + } + else return; + + values[type] = value; + + if (type == "rotary_switch_state") { + if (SETTINGS.maintenance_mode) value = "maintenance"; + value = value.toLowerCase(); + values["power_mode"] = value; + } + + if (newPinValue != previousValues[pinIndex]) previousValues[pinIndex] = newPinValue; + if (Object.keys(values).length > 0 && tbname) sendTelemetry(values, tbname); + } + + + function sendTelemetry(values, tbname, date = Date.now()) { + let dataToTb = { + [tbname]: [ + { + "ts": date, + "values": values + } + ] + }; + + tbHandler.sendToTb(dataToTb, instance); + } + + + function isObject(item) { + return (typeof item === "object" && !Array.isArray(item) && item !== null); + } + +} //end of 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 +// *|input1_01|state_of_main_switch|0|........... +// *|input1_02|rotary_switch_state|0|........... +// *|input1_03|rotary_switch_state|0|........... +// *|intut1_04|power_supply|0|........... +// *|input1_05|door_condition|0|........... +// *|input1_06|state_of_breaker|1|........... +// *|input1_07|state_of_breaker|2|........... +// *|input1_08|state_of_breaker|3|........... +// *|relay1_02|state_of_contactor|1|........... +// *|relay1_03|state_of_contactor|2|........... +// *|relay1_04|state_of_contactor|3|........... +// *|287D8776E0013CE9|temperature|0|........... + + +//! pins_data --> from UNIPI +// { +// 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 } +// } + +//! relays_data +// { +// '0': { +// line: 0, +// tbname: 'KjbN4q7JPZmexgdnz2yKQ98YAWwO0Q3BMX6ERLoV', +// contactor: 1, +// profile: '' +// }, +// '1': { +// line: 1, +// tbname: 'RMgnK93rkoAazbqdQ4yBG95Z1YXGx6pmwBeVEP2O', +// contactor: 0, +// profile: '{"intervals":[{"value":0,"end_time":"20:00","start_time":"13:00"},{"value":1,"end_time":"10:00","start_time":"20:00"},{"value":0,"end_time":"10:20","start_time":"10:00"},{"value":1,"end_time":"10:40","start_time":"10:20"},{"value":0,"end_time":"11:00","start_time":"10:40"},{"value":1,"end_time":"11:30","start_time":"11:00"},{"value":0,"end_time":"11:50","start_time":"11:30"},{"value":1,"end_time":"13:00","start_time":"11:50"}],"astro_clock":false,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' +// }, +// '2': { +// line: 2, +// tbname: 'dlE1VQjYrNx9gZRmb38gG08oLBO4qaAk2M6JPnG7', +// contactor: 0, +// profile: '{"intervals":[{"value":0,"end_time":"20:00","start_time":"13:00"},{"value":1,"end_time":"10:00","start_time":"20:00"},{"value":0,"end_time":"10:20","start_time":"10:00"},{"value":1,"end_time":"10:40","start_time":"10:20"},{"value":0,"end_time":"11:00","start_time":"10:40"},{"value":1,"end_time":"11:30","start_time":"11:00"},{"value":0,"end_time":"11:50","start_time":"11:30"},{"value":1,"end_time":"13:00","start_time":"11:50"}],"astro_clock":false,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' +// }, +// '3': { +// line: 3, +// tbname: 'vnmG4kJxaXWNBgMQq0D7Aj5e9oZzOAlr6LdR3w2V', +// contactor: 0, +// profile: '{"intervals":[{"value":0,"end_time":"20:30","start_time":"13:00"},{"value":1,"end_time":"00:10","start_time":"20:30"},{"value":0,"end_time":"13:00","start_time":"05:40"},{"value":1,"end_time":"05:40","start_time":"00:10"}],"astro_clock":true,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' +// } +// } + + + + + +// { +// "jbN4q7JPZmexgdnz2yKbWGDYAWwO0Q3BMX6ERLoV": [ +// { +// "ts": 1700409326353, +// "values": { +// "_event": { +// "type": "notice", +// "status": "new", +// "source": { +// "func": "rsPort.open()", +// "component": "1700343402190", +// "component_name": "DIDO_Controller", +// "edge": "jbN4q7JPZmexgdnz2yKbWGDYAWwO0Q3BMX6ERLoV" +// }, +// "message": "al_shariff_10.0.0.38: FLOW has been started ", +// "message_data": "" +// } +// } +// } +// ] +// } diff --git a/RVO25/flow/helper/DataToTbHandler.js b/RVO25/flow/helper/DataToTbHandler.js new file mode 100755 index 0000000..716ef7b --- /dev/null +++ b/RVO25/flow/helper/DataToTbHandler.js @@ -0,0 +1,187 @@ +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; + this.itIsNodeReadout = false; + this.sender = ""; + + // if attribute change difference is less than limit value, we do not send to tb. + this.attributeChangeLimit = { + temperature: 0.5, + Phase_1_voltage: 2, + Phase_2_voltage: 2, + Phase_3_voltage: 2, + Phase_1_current: 0.1, + Phase_2_current: 0.1, + Phase_3_current: 0.1, + Phase_1_power: 2, + Phase_2_power: 2, + Phase_3_power: 2, + total_power: 2, + total_energy: 1, + Phase_1_pow_factor: 0.1, + Phase_2_pow_factor: 0.1, + Phase_3_pow_factor: 0.1, + power_factor: 0.1, + lifetime: 2, + voltage: 2, + power: 2, + frequency: 3, + energy: 0.1, + current: 2, + inclination_x: 10, + inclination_y: 10, + inclination_z: 10 + }; + + } + + dump() { + console.log("----------------------------"); + console.log("previousValues", this.previousValues); + console.log("----------------------------"); + } + + setSender(sender) { + this.sender = sender; + } + + isEmptyObject(obj) { + for (var _ in obj) { + return false; + } + return true; + } + + + sendToTb(data, instance) { + + //not to modify data object, we do deep copy: + let dataCopy = JSON.parse(JSON.stringify(data)); + + let keys = Object.keys(dataCopy); + + if (keys.length == 0) { + if (this.debug) console.log("sendToTb received empty object", dataCopy); + return; + } + + let tbname = keys[0]; + let ts; + + let arrayOfValues = dataCopy[tbname]; + let arrayOfValuesToSend = []; + + for (let i = 0; i < arrayOfValues.length; i++) { + + ts = arrayOfValues[i].ts; + let values = this.prepareValuesForTb(tbname, ts, arrayOfValues[i].values); + + if (!this.isEmptyObject(values)) { + arrayOfValuesToSend.push({ ts: ts, values: values }); + } + + } + + if (arrayOfValuesToSend.length == 0) { + //if(this.debug) console.log("data not sent - empty array"); + return; + } + + this.messageCounter++; + + let dataToTbModified = { + [tbname]: arrayOfValuesToSend + } + + //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); + instance.send(this.index, dataToTbModified); + } + + + getDiffTimestamp(key) { + //TODO set different value for given key!!! + //if(key == "status") this.timeToHoldTbValue = 2*60*60;//2h + return this.timeToHoldTbValue * 1000; + } + + + prepareValuesForTb(tbname, timestamp, values) { + + let keys = Object.keys(values); + + if (keys.includes("lifetime")) this.itIsNodeReadout = true; + + if (!this.previousValues.hasOwnProperty(tbname)) { + this.previousValues[tbname] = {}; + } + + //if(this.debug) console.log("prepareValuesForTb", tbname, timestamp, values); + + for (let i = 0; i < keys.length; i++) { + + let key = keys[i]; + let value = values[key]; + + if (!this.previousValues[tbname].hasOwnProperty(key)) { + this.previousValues[tbname][key] = { ts: timestamp, value: value }; + continue; + } + + // attributeData ==> {voltage: {ts:333333, value:5}} + let attributeData = this.previousValues[tbname][key]; + let attributeToChange = false; + if (key in this.attributeChangeLimit) attributeToChange = true; + let limit = this.attributeChangeLimit[key]; + let timestampDiffToRemoveKey; + + //this will ensure "node statecode" will be sent just once an hour + if (this.itIsNodeReadout && key === "statecode") { + attributeData.value = value; + this.itIsNodeReadout = false; + timestampDiffToRemoveKey = 1 * 60 * 60 * 1000; // 1 hour + } + + if (key === "twilight_sensor" && value > 100) { + attributeData.value = value; + } + + //if edge, master or node version do not change, send just once a day: + if (["edge_fw_version", "master_node_version", "fw_version"].includes(key)) { + timestampDiffToRemoveKey = 24 * 60 * 60 * 1000; + } + + if (attributeData.value === value || attributeToChange && Math.abs(attributeData.value - value) < limit) { + + let diff = timestamp - attributeData.ts; + if (!timestampDiffToRemoveKey) timestampDiffToRemoveKey = this.getDiffTimestamp(key); + + if (diff > timestampDiffToRemoveKey) { + attributeData.ts = Date.now(); + //if(this.debug) console.log(this.sender + ": update ts for key", key, "diff is", diff, "messageCounter", this.messageCounter); + } + else { + delete values[key]; + //if(this.debug) console.log(this.sender + ": delete key", key, "diff is", diff, "messageCounter", this.messageCounter, timestampDiffToRemoveKey); + } + } + else { + attributeData.value = value; + attributeData.ts = timestamp; + } + + } + + return values; + } +} + +module.exports = DataToTbHandler; + diff --git a/RVO25/flow/helper/ErrorToServiceHandler.js b/RVO25/flow/helper/ErrorToServiceHandler.js new file mode 100755 index 0000000..2b27c32 --- /dev/null +++ b/RVO25/flow/helper/ErrorToServiceHandler.js @@ -0,0 +1,91 @@ +const { MD5 } = require('./md5.js'); +const { networkInterfaces } = require('os'); + +class ErrorToServiceHandler { + constructor() { + this.previousValues = {}; + + this.project_id = undefined; + + const nets = networkInterfaces(); + this.ipAddresses = {}; + + for (const name of Object.keys(nets)) { + for (const net of nets[name]) { + // Skip over non-IPv4 and internal (i.e. 127.0.0.1) addresses + if (net.family === 'IPv4' && !net.internal) { + if (!this.ipAddresses[name]) { + this.ipAddresses[name] = []; + } + this.ipAddresses[name].push(net.address); + } + } + } + } + + setProjectId(project_id) { + this.project_id = project_id; + } + + processMessage(message, seconds) { + if (Array.isArray(message)) message = message.join(', '); + + let key = MD5(message); + let ts = Date.now(); + + //keep in memory - default value is 1h + if (seconds === undefined) seconds = 60 * 60; + + if (!this.previousValues.hasOwnProperty(key)) { + this.previousValues[key] = { ts: ts, duration: seconds }; + } + + let diff = (ts - this.previousValues[key].ts); + if (diff < this.previousValues[key].duration * 1000) return false; + + this.previousValues[key].ts = ts; + + return message; + } + + sendMessageToService(message, seconds, message_type) { + + // if error occures too early FLOW.GLOBALS.settings.project_id is still undefined + if (this.project_id === undefined) { + console.log("ErrorToServiceHandler.js: no project_id"); + return; + } + + let f = this.processMessage(message, seconds); + if (f === false) return; + + if (message_type === undefined) message_type = "error_message"; + + let toService = { + id: this.project_id, + ipAddresses: this.ipAddresses + }; + + //js_error || error_message + toService[message_type] = message; + + console.log("ErrorToServiceHandler------------------------>send to service", toService); + + RESTBuilder.make(function(builder) { + builder.method('POST'); + builder.post(toService); + builder.url('http://192.168.252.2:8004/sentmessage'); + + builder.callback(function(err, response, output) { + console.log("process.on error send", err, response, output, toService); + }); + }); + + } +} + +const errorHandler = new ErrorToServiceHandler(); + + +module.exports = errorHandler; +//module.exports = ErrorToServiceHandler; diff --git a/RVO25/flow/helper/db_helper.js b/RVO25/flow/helper/db_helper.js new file mode 100755 index 0000000..40e796c --- /dev/null +++ b/RVO25/flow/helper/db_helper.js @@ -0,0 +1,44 @@ +function promisifyBuilder(builder) +{ + return new Promise((resolve, reject) => { + + try{ + + builder.callback(function(err, response) { + + if(err != null) reject(err); + resolve(response); + }); + + } catch (error) { + reject(error); + } + }) +} + +function makeMapFromDbResult(response, ...keys) +{ + let s = "-"; + let data = {}; + + for(let i = 0; i < response.length; i++) + { + let record = response[i]; + + let k = []; + for(let j = 0; j < keys.length; j++) + { + k.push( record[keys[j]] ); + } + + let key = k.join(s); + data[ key ] = record; + } + + return data; +} + +module.exports = { + promisifyBuilder, + makeMapFromDbResult + } \ No newline at end of file diff --git a/RVO25/flow/helper/logger.js b/RVO25/flow/helper/logger.js new file mode 100755 index 0000000..2585639 --- /dev/null +++ b/RVO25/flow/helper/logger.js @@ -0,0 +1,30 @@ +//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/RVO25/flow/helper/md5.js b/RVO25/flow/helper/md5.js new file mode 100755 index 0000000..d3b0480 --- /dev/null +++ b/RVO25/flow/helper/md5.js @@ -0,0 +1,5 @@ +function MD5(d){var r = M(V(Y(X(d),8*d.length)));return r.toLowerCase()};function M(d){for(var _,m="0123456789ABCDEF",f="",r=0;r>>4&15)+m.charAt(15&_);return f}function X(d){for(var _=Array(d.length>>2),m=0;m<_.length;m++)_[m]=0;for(m=0;m<8*d.length;m+=8)_[m>>5]|=(255&d.charCodeAt(m/8))<>5]>>>m%32&255);return _}function Y(d,_){d[_>>5]|=128<<_%32,d[14+(_+64>>>9<<4)]=_;for(var m=1732584193,f=-271733879,r=-1732584194,i=271733878,n=0;n>16)+(_>>16)+(m>>16)<<16|65535&m}function bit_rol(d,_){return d<<_|d>>>32-_} + +module.exports = { + MD5 +} \ No newline at end of file diff --git a/RVO25/flow/helper/notification_reporter.js b/RVO25/flow/helper/notification_reporter.js new file mode 100755 index 0000000..839c12c --- /dev/null +++ b/RVO25/flow/helper/notification_reporter.js @@ -0,0 +1,121 @@ +//key is device, value = message {} +let sentValues = {}; +let notificationsData = null; +let rvoName; + +//sendNotification("CMD Manager: process cmd", SETTINGS.rvoTbName, "dimming_profile_was_successfully_received_by_node", { node: node }, "", SEND_TO.tb, instance); + +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 +}; + +function getKey(map, val) { + return Object.keys(map).findItem(key => map[key] === val); +} + +//https://stackoverflow.com/questions/41117799/string-interpolation-on-variable +var template = (tpl, args) => tpl.replace(/\${(\w+)}/g, (_, v) => args[v]); + + +function initNotification() { + notificationsData = FLOW.GLOBALS.notificationsData; + rvoName = FLOW.GLOBALS.settings.rvo_name; +} + + +function sendNotification(func, device, key, params, extra, tb_output, instance, saveKey) { + + let storeToSendValues = true; + if (saveKey == undefined) storeToSendValues = false; + + let weight = ""; + let message = {}; + + let notification = notificationsData[key]; + + if (notification) { + weight = notification.weight.toLowerCase(); + + Object.keys(notification).forEach(item => { + if (["en", "sk", "de", "cz", "it", "es"].includes(item)) { + message[item] = rvoName + ": " + template(notification[item], params); + } + }) + } + else { + //console.error("sendNotification: Notifications: undefined key", key, func, notificationsData); + console.error("sendNotification: Notifications: undefined key", key, func); + return false; + } + + //detect invalid err weight + if (getKey(ERRWEIGHT, weight) == undefined) { + console.error("sendNotification: Notifications: undefined weight", weight, key, func); + return false; + } + + if (sentValues.hasOwnProperty(saveKey)) { + if (JSON.stringify(sentValues[saveKey]) == JSON.stringify(message)) { + return false; + } + } + + if (sentValues[saveKey] == undefined) { + if (storeToSendValues) { + //do not send - flow is was started + sentValues[saveKey] = message; + return false; + } + } + + if (storeToSendValues) sentValues[saveKey] = message; + + let content = { + "type": weight, + "status": "new", + "source": { + "func": func, + "component": instance.id, + "component_name": instance.name, + "edge": device + }, + "message": message, + "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 + + return true; + +} + +module.exports = { + sendNotification, + ERRWEIGHT, + initNotification +} + diff --git a/RVO25/flow/helper/register.js b/RVO25/flow/helper/register.js new file mode 100755 index 0000000..fc1d008 --- /dev/null +++ b/RVO25/flow/helper/register.js @@ -0,0 +1,144 @@ +/* +0 - cislo registra / prikaz +1 - recepient - 0 = master, 1 = slave (slave je automaticky group a broadcast) +2 - r/rw - read/write +3- register name - nazov registra / prikazu (len pre info - zobrazenie v aplikacii) + +4,5,6,7, - jednotlive byte-y - nazov byte-u +4-7 - RES. a prazdny string "" sa nezobrazia!!! +*/ + +//124 zaznamov +const registers = [ + ["0","1","R","Status","","",""], + ["1","1","RW","Dimming","R-Channel ","G-Channel","B-Channel ","W - Channel"], + ["2","1","R","Device types","","",".",""], + ["3","1","RW","Group addresses 1-4","Groups Add. 4","Groups Add. 3","Groups Add. 2","Groups Add. 1"], + ["4","1","RW","Group addresses 5-8","Groups Add. 8","Groups Add. 7","Groups Add. 6","Groups Add. 5"], + ["5","1","RW","Serial number (MAC)","","","",""], + ["6","1","RW","Time of dusk","HH","MM","SS","EXTRA"], + ["7","1","RW","Time of dawn","HH","MM","SS","EXTRA"], + ["8","1","RW","Time Schedule settings","TBD","TBD","Movement sensor","Time Schedule"], + ["9","1","RW","TS1 Time point 1","HH","MM","SS","Ext. Device"], + ["10","1","RW","TS1 Time point 1 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["11","1","RW","TS1 Time point 2","HH","MM","SS","Ext. Device"], + ["12","1","RW","TS1 Time point 2 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["13","1","RW","TS1 Time point 3","HH","MM","SS","Ext. Device"], + ["14","1","RW","TS1 Time point 3 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["15","1","RW","TS1 Time point 4","HH","MM","SS","Ext. Device"], + ["16","1","RW","TS1 Time point 4 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["17","1","RW","TS1 Time point 5","HH","MM","SS","Ext. Device"], + ["18","1","RW","TS1 Time point 5 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["19","1","RW","TS1 Time point 6","HH","MM","SS","Ext. Device"], + ["20","1","RW","TS1 Time point 6 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["21","1","RW","TS1 Time point 7","HH","MM","SS","Ext. Device"], + ["22","1","RW","TS1 Time point 7 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["23","1","RW","TS1 Time point 8","HH","MM","SS","Ext. Device"], + ["24","1","RW","TS1 Time point 8 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["25","1","RW","TS1 Time point 9","HH","MM","SS","Ext. Device"], + ["26","1","RW","TS1 Time point 9 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["27","1","RW","TS1 Time point 10","HH","MM","SS","Ext. Device"], + ["28","1","RW","TS1 Time point 10 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["29","1","RW","TS1 Time point 11","HH","MM","SS","Ext. Device"], + ["30","1","RW","TS1 Time point 11 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["31","1","RW","TS1 Time point 12","HH","MM","SS","Ext. Device"], + ["32","1","RW","TS1 Time point 12 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["33","1","RW","TS1 Time point 13","HH","MM","SS","Ext. Device"], + ["34","1","RW","TS1 Time point 13 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["35","1","RW","TS1 Time point 14","HH","MM","SS","Ext. Device"], + ["36","1","RW","TS1 Time point 14 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["37","1","RW","TS1 Time point 15","HH","MM","SS","Ext. Device"], + ["38","1","RW","TS1 Time point 15 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["39","1","RW","TS1 Time point 16","HH","MM","SS","Ext. Device"], + ["40","1","RW","TS1 Time point 16 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["41","1","RW","TS2 Time point 1","HH","MM","SS","Ext. Device"], + ["42","1","RW","TS2 Time point 1 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["43","1","RW","TS2 Time point 2","HH","MM","SS","Ext. Device"], + ["44","1","RW","TS2 Time point 2 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["45","1","RW","TS2 Time point 3","HH","MM","SS","Ext. Device"], + ["46","1","RW","TS2 Time point 3 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["47","1","RW","TS2 Time point 4","HH","MM","SS","Ext. Device"], + ["48","1","RW","TS2 Time point 4 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["49","1","RW","TS2 Time point 5","HH","MM","SS","Ext. Device"], + ["50","1","RW","TS2 Time point 5 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["51","1","RW","TS2 Time point 6","HH","MM","SS","Ext. Device"], + ["52","1","RW","TS2 Time point 6 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["53","1","RW","TS2 Time point 7","HH","MM","SS","Ext. Device"], + ["54","1","RW","TS2 Time point 7 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["55","1","RW","TS2 Time point 8","HH","MM","SS","Ext. Device"], + ["56","1","RW","TS2 Time point 8 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["57","1","RW","TS2 Time point 9","HH","MM","SS","Ext. Device"], + ["58","1","RW","TS2 Time point 9 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["59","1","RW","TS2 Time point 10","HH","MM","SS","Ext. Device"], + ["60","1","RW","TS2 Time point 10 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["61","1","RW","TS2 Time point 11","HH","MM","SS","Ext. Device"], + ["62","1","RW","TS2 Time point 11 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["63","1","RW","TS2 Time point 12","HH","MM","SS","Ext. Device"], + ["64","1","RW","TS2 Time point 12 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["65","1","RW","TS2 Time point 13","HH","MM","SS","Ext. Device"], + ["66","1","RW","TS2 Time point 13 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["67","1","RW","TS2 Time point 14","HH","MM","SS","Ext. Device"], + ["68","1","RW","TS2 Time point 14 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["69","1","RW","TS2 Time point 15","HH","MM","SS","Ext. Device"], + ["70","1","RW","TS2 Time point 15 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["71","1","RW","TS2 Time point 16","HH","MM","SS","Ext. Device"], + ["72","1","RW","TS2 Time point 16 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["73","1","RW","Power meter status","TBD","","",""], + ["74","1","R","Input Voltage","","","",""], + ["75","1","R","Input Current","","","",""], + ["76","1","R","Input Power","","","",""], + ["77","1","R","Cos phi","","","",""], + ["78","1","R","Frequency","","","",""], + ["79","1","RW","Energy","","","",""], + ["80","1","RW","Lifetime","","","",""], + ["81","1","RW","Power on cycles (input)","","","",""], + ["82","1","RW","Power on cycles (relay)","","","",""], + ["83","1","R","Time since last power on","","","",""], + ["84","1","R","Accelerometer data","","","",""], + ["85","1","RW","GPS latitude","pos/neg","deg","min ","sec"], + ["86","1","RW","GPS longitude","pos/neg","deg","min ","sec"], + ["87","1","RW","Actual time","HH","MM","SS","RES."], + ["88","1","RW","Actual date","Day of week","Day","Month","Year"], + ["89","1","R","Production data 1","","","",""], + ["90","1","R","Production data 2","","","",""], + ["91","1","RW","Network ID","NID3","NID2","NID1","NID0"], + ["95","1","RW","Actual Lux level from cabinet","RES.","RES.","HB","LB"], + ["96","1","RW","Threshold lux level","Dusk HB","Dusk LB","Dawn HB","Dawn LB"], + ["97","1","RW","Adjust period","Dusk HB","Dusk LB","Dawn HB","Dawn LB"], + ["98","1","RW","Offset","RES.","RES.","Dusk","Dawn"], + ["99","1","RW","CCT min/max range","max-H","max-L","min-H","min-L"], + ["100","1","RW","DALI interface","Cmd ID","Add","Cmd","Resp"], + ["101","1","RW","Module FW ver","v1","v2","v3","v4"], + ["102","1","RW","Module MAC-H","unused","unused","M1","M2"], + ["103","1","RW","Module MAC-L","M3","M4","M5","M6"], + ["122","1","R","FW update status/control register","Byte3","Byte2","Byte1","Byte0"], + ["123","1","R","FW update - data index","Byte3","Byte2","Byte1","Byte0"], + ["124","1","R","FW update - data","Byte3","Byte2","Byte1","Byte0"], + ["0","0","R","Status","","","",""], + ["1","0","RW","Control register","RES.","RES.","RES.","init mode enable"], + ["2","0","R","Device types","","","",""], + ["3","0","R","Serial number (MAC)","","","",""], + ["4","0","R","Production data 1","","","",""], + ["5","0","R","Production data 2","","","",""], + ["6","0","RW","Network ID","NID3","NID2","NID1","NID0"], + ["7","0","RW","RS232 settings","param.","param.","Baudrate H","Baudrate L"], + ["8","0","R","Accelerometer data","","","",""], + ["9","0","RW","Module FW ver","v1","v2","v3","v4"], + ["10","0","RW","Module MAC-H","unused","unused","M1","M2"], + ["11","0","RW","Module MAC-L","M3","M4","M5","M6"], + ["32","0","RW","FW update status/control register","Byte3","Byte2","Byte1","Byte0"], + ["33","0","RW","FW update - data index","Byte3","Byte2","Byte1","Byte0"], + ["34","0","RW","FW update - data","Byte3","Byte2","Byte1","Byte0"], + ["125","0","RW","Debug Register","Byte3","Byte2","Byte1","Byte0"], + ["126","0","RW","Network Control Register","Byte3","Byte2","Byte1","Byte0"], + ["127","0","R","Network Status Register","Byte3","Byte2","Byte1","Byte0"], + ["128","0","RW","Node XX Serial Number Register","SER3","SER2","SER1","SER0"], + ["256","0","R","Node XX Network Status Register","","","",""] +]; + +let register = {}; + +module.exports = { + registers, + register +} \ No newline at end of file diff --git a/RVO25/flow/helper/serialport_helper.js b/RVO25/flow/helper/serialport_helper.js new file mode 100755 index 0000000..7f5920d --- /dev/null +++ b/RVO25/flow/helper/serialport_helper.js @@ -0,0 +1,99 @@ +const { exec } = require('child_process'); + +function openPort(port) { + return new Promise((resolve, reject) => { + + var callbackError = function(err) { + port.removeListener('error', callbackError); + port.removeListener('open', callbackError); + + reject(err.message); + }; + + var callbackOpen = function(data) { + port.removeListener('error', callbackError); + port.removeListener('open', callbackOpen); + + resolve("port open: ok"); + }; + + port.on('error', callbackError); + port.on('open', callbackOpen); + + port.open(); + + }) +} + +function runSyncExec(command) { + return new Promise((resolve, reject) => { + + exec(command, (error, stdout, stderr) => { + if (error == null) resolve(stdout); + reject(error); + }); + + }) +} + +async function writeData(port, data, readbytes, timeout) { + return new Promise((resolve, reject) => { + + // 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) { + + port.write(Buffer.from(data), function(err) { + if (err) { + reject(err.message); + } + }); + + 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 +} diff --git a/RVO25/flow/helper/suncalc.js b/RVO25/flow/helper/suncalc.js new file mode 100755 index 0000000..c9ca56d --- /dev/null +++ b/RVO25/flow/helper/suncalc.js @@ -0,0 +1,317 @@ +/* + (c) 2011-2015, Vladimir Agafonkin + SunCalc is a JavaScript library for calculating sun/moon position and light phases. + https://github.com/mourner/suncalc +*/ + +(function () { 'use strict'; + +// shortcuts for easier to read formulas + +var PI = Math.PI, + sin = Math.sin, + cos = Math.cos, + tan = Math.tan, + asin = Math.asin, + atan = Math.atan2, + acos = Math.acos, + rad = PI / 180; + +// sun calculations are based on http://aa.quae.nl/en/reken/zonpositie.html formulas + + +// date/time constants and conversions + +var dayMs = 1000 * 60 * 60 * 24, + J1970 = 2440588, + J2000 = 2451545; + +function toJulian(date) { return date.valueOf() / dayMs - 0.5 + J1970; } +function fromJulian(j) { return new Date((j + 0.5 - J1970) * dayMs); } +function toDays(date) { return toJulian(date) - J2000; } + + +// general calculations for position + +var e = rad * 23.4397; // obliquity of the Earth + +function rightAscension(l, b) { return atan(sin(l) * cos(e) - tan(b) * sin(e), cos(l)); } +function declination(l, b) { return asin(sin(b) * cos(e) + cos(b) * sin(e) * sin(l)); } + +function azimuth(H, phi, dec) { return atan(sin(H), cos(H) * sin(phi) - tan(dec) * cos(phi)); } +function altitude(H, phi, dec) { return asin(sin(phi) * sin(dec) + cos(phi) * cos(dec) * cos(H)); } + +function siderealTime(d, lw) { return rad * (280.16 + 360.9856235 * d) - lw; } + +function astroRefraction(h) { + if (h < 0) // the following formula works for positive altitudes only. + h = 0; // if h = -0.08901179 a div/0 would occur. + + // formula 16.4 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + // 1.02 / tan(h + 10.26 / (h + 5.10)) h in degrees, result in arc minutes -> converted to rad: + return 0.0002967 / Math.tan(h + 0.00312536 / (h + 0.08901179)); +} + +// general sun calculations + +function solarMeanAnomaly(d) { return rad * (357.5291 + 0.98560028 * d); } + +function eclipticLongitude(M) { + + var C = rad * (1.9148 * sin(M) + 0.02 * sin(2 * M) + 0.0003 * sin(3 * M)), // equation of center + P = rad * 102.9372; // perihelion of the Earth + + return M + C + P + PI; +} + +function sunCoords(d) { + + var M = solarMeanAnomaly(d), + L = eclipticLongitude(M); + + return { + dec: declination(L, 0), + ra: rightAscension(L, 0) + }; +} + + +var SunCalc = {}; + + +// calculates sun position for a given date and latitude/longitude + +SunCalc.getPosition = function (date, lat, lng) { + + var lw = rad * -lng, + phi = rad * lat, + d = toDays(date), + + c = sunCoords(d), + H = siderealTime(d, lw) - c.ra; + + return { + azimuth: azimuth(H, phi, c.dec), + altitude: altitude(H, phi, c.dec) + }; +}; + + +// sun times configuration (angle, morning name, evening name) + +var times = SunCalc.times = [ + [-0.833, 'sunrise', 'sunset' ], + [ -0.3, 'sunriseEnd', 'sunsetStart' ], + [ -6, 'dawn', 'dusk' ], + [ -12, 'nauticalDawn', 'nauticalDusk'], + [ -18, 'nightEnd', 'night' ], + [ 6, 'goldenHourEnd', 'goldenHour' ] +]; + +// adds a custom time to the times config + +SunCalc.addTime = function (angle, riseName, setName) { + times.push([angle, riseName, setName]); +}; + + +// calculations for sun times + +var J0 = 0.0009; + +function julianCycle(d, lw) { return Math.round(d - J0 - lw / (2 * PI)); } + +function approxTransit(Ht, lw, n) { return J0 + (Ht + lw) / (2 * PI) + n; } +function solarTransitJ(ds, M, L) { return J2000 + ds + 0.0053 * sin(M) - 0.0069 * sin(2 * L); } + +function hourAngle(h, phi, d) { return acos((sin(h) - sin(phi) * sin(d)) / (cos(phi) * cos(d))); } +function observerAngle(height) { return -2.076 * Math.sqrt(height) / 60; } + +// returns set time for the given sun altitude +function getSetJ(h, lw, phi, dec, n, M, L) { + + var w = hourAngle(h, phi, dec), + a = approxTransit(w, lw, n); + return solarTransitJ(a, M, L); +} + + +// calculates sun times for a given date, latitude/longitude, and, optionally, +// the observer height (in meters) relative to the horizon + +SunCalc.getTimes = function (date, lat, lng, height) { + + height = height || 0; + + var lw = rad * -lng, + phi = rad * lat, + + dh = observerAngle(height), + + d = toDays(date), + n = julianCycle(d, lw), + ds = approxTransit(0, lw, n), + + M = solarMeanAnomaly(ds), + L = eclipticLongitude(M), + dec = declination(L, 0), + + Jnoon = solarTransitJ(ds, M, L), + + i, len, time, h0, Jset, Jrise; + + + var result = { + solarNoon: fromJulian(Jnoon), + nadir: fromJulian(Jnoon - 0.5) + }; + + for (i = 0, len = times.length; i < len; i += 1) { + time = times[i]; + h0 = (time[0] + dh) * rad; + + Jset = getSetJ(h0, lw, phi, dec, n, M, L); + Jrise = Jnoon - (Jset - Jnoon); + + result[time[1]] = fromJulian(Jrise); + result[time[2]] = fromJulian(Jset); + } + + return result; +}; + + +// moon calculations, based on http://aa.quae.nl/en/reken/hemelpositie.html formulas + +function moonCoords(d) { // geocentric ecliptic coordinates of the moon + + var L = rad * (218.316 + 13.176396 * d), // ecliptic longitude + M = rad * (134.963 + 13.064993 * d), // mean anomaly + F = rad * (93.272 + 13.229350 * d), // mean distance + + l = L + rad * 6.289 * sin(M), // longitude + b = rad * 5.128 * sin(F), // latitude + dt = 385001 - 20905 * cos(M); // distance to the moon in km + + return { + ra: rightAscension(l, b), + dec: declination(l, b), + dist: dt + }; +} + +SunCalc.getMoonPosition = function (date, lat, lng) { + + var lw = rad * -lng, + phi = rad * lat, + d = toDays(date), + + c = moonCoords(d), + H = siderealTime(d, lw) - c.ra, + h = altitude(H, phi, c.dec), + // formula 14.1 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + pa = atan(sin(H), tan(phi) * cos(c.dec) - sin(c.dec) * cos(H)); + + h = h + astroRefraction(h); // altitude correction for refraction + + return { + azimuth: azimuth(H, phi, c.dec), + altitude: h, + distance: c.dist, + parallacticAngle: pa + }; +}; + + +// calculations for illumination parameters of the moon, +// based on http://idlastro.gsfc.nasa.gov/ftp/pro/astro/mphase.pro formulas and +// Chapter 48 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + +SunCalc.getMoonIllumination = function (date) { + + var d = toDays(date || new Date()), + s = sunCoords(d), + m = moonCoords(d), + + sdist = 149598000, // distance from Earth to Sun in km + + phi = acos(sin(s.dec) * sin(m.dec) + cos(s.dec) * cos(m.dec) * cos(s.ra - m.ra)), + inc = atan(sdist * sin(phi), m.dist - sdist * cos(phi)), + angle = atan(cos(s.dec) * sin(s.ra - m.ra), sin(s.dec) * cos(m.dec) - + cos(s.dec) * sin(m.dec) * cos(s.ra - m.ra)); + + return { + fraction: (1 + cos(inc)) / 2, + phase: 0.5 + 0.5 * inc * (angle < 0 ? -1 : 1) / Math.PI, + angle: angle + }; +}; + + +function hoursLater(date, h) { + return new Date(date.valueOf() + h * dayMs / 24); +} + +// calculations for moon rise/set times are based on http://www.stargazing.net/kepler/moonrise.html article + +SunCalc.getMoonTimes = function (date, lat, lng, inUTC) { + var t = new Date(date); + if (inUTC) t.setUTCHours(0, 0, 0, 0); + else t.setHours(0, 0, 0, 0); + + var hc = 0.133 * rad, + h0 = SunCalc.getMoonPosition(t, lat, lng).altitude - hc, + h1, h2, rise, set, a, b, xe, ye, d, roots, x1, x2, dx; + + // go in 2-hour chunks, each time seeing if a 3-point quadratic curve crosses zero (which means rise or set) + for (var i = 1; i <= 24; i += 2) { + h1 = SunCalc.getMoonPosition(hoursLater(t, i), lat, lng).altitude - hc; + h2 = SunCalc.getMoonPosition(hoursLater(t, i + 1), lat, lng).altitude - hc; + + a = (h0 + h2) / 2 - h1; + b = (h2 - h0) / 2; + xe = -b / (2 * a); + ye = (a * xe + b) * xe + h1; + d = b * b - 4 * a * h1; + roots = 0; + + if (d >= 0) { + dx = Math.sqrt(d) / (Math.abs(a) * 2); + x1 = xe - dx; + x2 = xe + dx; + if (Math.abs(x1) <= 1) roots++; + if (Math.abs(x2) <= 1) roots++; + if (x1 < -1) x1 = x2; + } + + if (roots === 1) { + if (h0 < 0) rise = i + x1; + else set = i + x1; + + } else if (roots === 2) { + rise = i + (ye < 0 ? x2 : x1); + set = i + (ye < 0 ? x1 : x2); + } + + if (rise && set) break; + + h0 = h2; + } + + var result = {}; + + if (rise) result.rise = hoursLater(t, rise); + if (set) result.set = hoursLater(t, set); + + if (!rise && !set) result[ye > 0 ? 'alwaysUp' : 'alwaysDown'] = true; + + return result; +}; + + +// export as Node module / AMD module / browser variable +if (typeof exports === 'object' && typeof module !== 'undefined') module.exports = SunCalc; +else if (typeof define === 'function' && define.amd) define(SunCalc); +else window.SunCalc = SunCalc; + +}()); diff --git a/RVO25/flow/helper/utils.js b/RVO25/flow/helper/utils.js new file mode 100755 index 0000000..dbffe45 --- /dev/null +++ b/RVO25/flow/helper/utils.js @@ -0,0 +1,161 @@ +const fs = require('fs').promises; + +function bytesToInt(bytes, numberOfBytes) { + let buffer = []; + if (Array.isArray(bytes)) { + buffer = bytes.slice(0); + if (numberOfBytes != undefined) { + buffer = bytes.slice(bytes.length - numberOfBytes); + } + } + else buffer.push(bytes); + + let result = 0; + for (let i = 0; i < buffer.length; i++) { + result = (result << 8) | buffer[i]; + } + + return result >>> 0; //ensure it's an unsigned 32-bit number +} + +function resizeArray(arr, newSize, defaultValue) { + while (newSize > arr.length) + arr.push(defaultValue); + arr.length = newSize; +} + +longToByteArray = function(/*long*/long) { + // we want to represent the input as a 8-bytes array + var byteArray = [0, 0, 0, 0, 0, 0, 0, 0]; + + for (var index = 0; index < byteArray.length; index++) { + var byte = long & 0xff; + byteArray[index] = byte; + long = (long - byte) / 256; + } + + return byteArray; +}; + +function addDays(date, days) { + var result = new Date(date); + result.setDate(result.getDate() + days); + return result; +} + +/* +sleep(2000).then(() => { + // Do something after the sleep! + + +}); +*/ + +function sleep(time) { + return new Promise((resolve) => setTimeout(resolve, time)); +} + +function isEmptyObject(obj) { + for (var name in obj) { + return false; + } + return true; +} + +function emptyJsObject(jsObject) { + Object.keys(jsObject).forEach(key => delete jsObject[key]); +} + +function convertUTCDateToLocalDate(date) { + var newDate = new Date(date); + newDate.setMinutes(date.getMinutes() + date.getTimezoneOffset()); + return newDate; +} + +function addZeroBefore(n) { + return (n < 10 ? '0' : '') + n; +} + + +/** + * Asynchronously writes data to a file. + * + * @param {string} filePath The path to the file. + * @param {string} data The data to write to the file. + * @param {boolean} [append=false] If true, appends the data to the file. If false, it overwrites the file. + */ +async function writeToFile(filePath, data, append = false) { + if (typeof data !== 'string') data = JSON.stringify(data, null, 2); + try { + if (append) { + // Append the data to the end of the file. This is the simplest way to append. + await fs.appendFile(filePath, data, 'utf8'); + console.log(`Successfully appended data to ${filePath} using fs.appendFile.`); + } else { + // Overwrite the file with the new data. + await fs.writeFile(filePath, data, 'utf8'); + console.log(`Successfully wrote (overwrote) data to ${filePath} using fs.writeFile.`); + } + } catch (error) { + console.error(`Error writing to file ${filePath}:`, error); + } +} + + + /** + * Checks if an item is present in an array and adds it if it's not. + * * @param {Array} arr The array to check. + * @param {*} item The item to add. + * @returns {Array} The modified array. + */ +const addToArrayIfUnique = (arr, item) => { + if (!arr.includes(item)) { + arr.push(item); + } + return arr; +}; + + +var convertBase = function() { + + function convertBase(baseFrom, baseTo) { + return function(num) { + return parseInt(num, baseFrom).toString(baseTo); + + }; + } + + // binary to decimal + convertBase.bin2dec = convertBase(2, 10); + + // binary to hexadecimal + convertBase.bin2hex = convertBase(2, 16); + + // decimal to binary + convertBase.dec2bin = convertBase(10, 2); + + // decimal to hexadecimal + convertBase.dec2hex = convertBase(10, 16); + + // hexadecimal to binary + convertBase.hex2bin = convertBase(16, 2); + + // hexadecimal to decimal + convertBase.hex2dec = convertBase(16, 10); + + return convertBase; +}(); + +module.exports = { + bytesToInt, + longToByteArray, + addDays, + addZeroBefore, + resizeArray, + isEmptyObject, + emptyJsObject, + sleep, + convertUTCDateToLocalDate, + writeToFile, + addToArrayIfUnique +} diff --git a/RVO25/flow/httprequest.js b/RVO25/flow/httprequest.js new file mode 100755 index 0000000..469c8cb --- /dev/null +++ b/RVO25/flow/httprequest.js @@ -0,0 +1,137 @@ +exports.id = 'httprequest'; +exports.title = 'HTTP Request'; +exports.group = 'HTTP'; +exports.color = '#5D9CEC'; +exports.input = true; +exports.version = '2.0.1'; +exports.output = 1; +exports.author = 'Peter Širka'; +exports.icon = 'cloud-upload'; + +exports.html = `
+
@(URL address)
+
+
+
@(HTTP method)
+
+
+
@(Serialization)
+
+
+
@(Download the content in chunks)
+
@(Keep persistent cookies)
+
@(Disable DNS cache)
+
@(Keep alive connection)
+
+
+
+
@(Custom headers)
+
@(Cookies)
+
+
+
+ +
+
+
+
@(User)
+
+
+
@(Password)
+
+
+
+
+
`; + +exports.readme = `# Request + +This component creates a request with received data. + +__Response:__ +\`\`\`javascript +{ + data: String, + headers: Object, + status: Number, + host: String +} +\`\`\` + +__Dynamic arguments__: +Are performed via FlowData repository and can be used for URL address or for custom headers/cookies/auth. Use \`repository\` component for creating of dynamic arguments. Dynamic values are replaced in the form \`{key}\`: + +- url address e.g. \`https://.../{key}/\` +- headers values e.g. \`{token}\` +- cookies values e.g. \`{token}\``; + +exports.install = function(instance) { + + var can = false; + var flags = null; + var cookies2 = null; + + instance.on('data', function(response) { + can && instance.custom.send(response); + }); + + instance.custom.send = function(response) { + var options = instance.options; + + var headers = null; + var cookies = null; + + options.headers && Object.keys(options.headers).forEach(function(key) { + !headers && (headers = {}); + headers[key] = response.arg(options.headers[key]); + }); + + if (options.username && options.userpassword) { + !headers && (headers = {}); + headers['Authorization'] = 'Basic ' + U.createBuffer(response.arg(options.username + ':' + options.userpassword)).toString('base64'); + } + + options.cookies && Object.keys(options.cookies).forEach(function(key) { + !cookies && (cookies = {}); + cookies[key] = response.arg(options.cookies[key]); + }); + + if (options.chunks) { + U.download(response.arg(options.url), flags, options.stringify === 'none' ? null : response.data, function(err, response) { + response.on('data', (chunks) => instance.send2(chunks)); + }, cookies || cookies2, headers); + } else { + U.request(response.arg(options.url), flags, options.stringify === 'none' ? null : response.data, 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) + instance.error(err, response); + }, cookies || cookies2, headers); + } + }; + + instance.reconfigure = function() { + var options = instance.options; + can = options.url && options.url && options.method && options.stringify ? true : false; + instance.status(can ? '' : 'Not configured', can ? undefined : 'red'); + + if (!can) + return; + + flags = []; + flags.push(options.method.toLowerCase()); + options.stringify === 'json' && flags.push('json'); + options.stringify === 'raw' && flags.push('raw'); + options.keepalive && flags.push('keepalive'); + !options.nodns && flags.push('dnscache'); + if (options.persistentcookies) { + flags.push('cookies'); + cookies2 = {}; + } else + cookies2 = null; + }; + + instance.on('options', instance.reconfigure); + instance.reconfigure(); +}; \ No newline at end of file diff --git a/RVO25/flow/httpresponse.js b/RVO25/flow/httpresponse.js new file mode 100755 index 0000000..160a3bb --- /dev/null +++ b/RVO25/flow/httpresponse.js @@ -0,0 +1,76 @@ +exports.id = 'httpresponse'; +exports.title = 'HTTP Response'; +exports.group = 'HTTP'; +exports.color = '#5D9CEC'; +exports.icon = 'arrow-right'; +exports.input = true; +exports.output = ['#666D76']; +exports.version = '2.0.0'; +exports.author = 'Martin Smola'; +exports.readme = `# HTTP response + +HTTP response will respond with data recieved using data-type set in Settings form or plain text if not set. Output is the message duration \`Number\` in seconds.`; + +exports.html = `
+
@(Response data-type)
+
JSON is by default.
+
`; + +exports.install = function(instance) { + + var dursum = 0; + var durcount = 0; + + instance.on('data', function(flowdata) { + + var ctrl = flowdata.repository.controller; + var data = flowdata.data; + + if (!ctrl) { + instance.throw('No controller to use for response!'); + return; + } + + durcount++; + dursum += ((new Date() - flowdata.begin) / 1000).floor(2); + setTimeout2(instance.id, instance.custom.duration, 500, 10); + + ctrl.$flowdata = flowdata; + + var datatype = instance.options.datatype || 'json'; + if (datatype === 'emptyresponse') + return ctrl.plain(''); + + if (datatype !== 'json' && typeof(data) !== 'string') { + instance.throw('Incorect type of data, expected string, got ' + typeof(data)); + ctrl.plain(data == null ? '' : data.toString()); + return; + } + + switch(datatype) { + case 'html': + ctrl.content(data, 'text/html'); + break; + case 'plain': + ctrl.plain(data); + break; + case 'xml': + ctrl.content(data, 'text/xml'); + break; + default: + ctrl.json(data); + break; + } + }); + + instance.on('service', function() { + dursum = 0; + durcount = 0; + }); + + instance.custom.duration = function() { + var avg = (dursum / durcount).floor(2); + instance.status(avg + ' sec.'); + instance.send2(0, avg); + }; +}; diff --git a/RVO25/flow/httproute.js b/RVO25/flow/httproute.js new file mode 100755 index 0000000..583a19d --- /dev/null +++ b/RVO25/flow/httproute.js @@ -0,0 +1,326 @@ +exports.id = 'httproute'; +exports.title = 'HTTP Route'; +exports.group = 'HTTP'; +exports.color = '#5D9CEC'; +exports.icon = 'globe'; +exports.input = false; +exports.output = ['#6CAC5A', '#37BC9B']; +exports.version = '1.2.3'; +exports.author = 'Martin Smola'; +exports.cloning = false; +exports.options = { method: 'GET', url: '', size: 5, cacheexpire: '5 minutes', cachepolicy: 0, timeout: 5 }; +exports.dateupdated = '2021-01-21 18:30d'; +exports.readme = `# HTTP route + +__Outputs__: +- first output: raw data (cache is empty or is disabled) +- second output: cached data + +If one of the outputs is disabled then automatic responce with code "503 service unavailable" is sent. + +When a request comes in bellow object is available at \`flowdata.data\`: + +\`\`\`javascript +{ + params: { id: '1' }, // params for dynamic routes, e.g. /test/{id} + query: { msg: 'Hello' }, // parsed query string, e.g. /test/1?msg=Hello + body: { test: 'OK' }, // object if json requests otherwise string + headers: {}, // headers data + session: {}, // session data + user: {}, // user data + files: [], // uploaded files + url: '/users/', // a relative URL address + referrer: '/', // referrer + mobile: false, // determines mobile device + robot: false, // determines search robots/crawlsers + language: 'en' // determines language +} +\`\`\` + +See [documentation for flags](https://docs.totaljs.com/latest/en.html#api~HttpRouteOptionsFlags~unauthorize). These method flags are set automatically e.g. \`get, post, put, patch or delete\` + +--- + +\`id:ROUTE_ID\` flag cannot be used since it's already used by this component internally`; + +exports.html = `
+
+ +
+ +
+
+
@(HTTP method)
+
+
+
@(URL address)
+
+
+
+
+
@(Additional flags)
+
@(Separate flags by comma e.g. json, authorize)
+
+
+
@(Max. request size)
+
@(In kB kilobytes)
+
+
+
@(Timeout)
+
@(In seconds.)
+
+
+
+
+
+
@(Automatically respond with 200 OK?)
+
@(If not checked you need to use HTTP response component to respond to the request.)
+
+
@(Custom headers)
+
@(Cookies)
+
+
+
+
+
+
@(Cache policy)
+
@(User instance must contain id property.)
+
+
+
@(Expiration)
+
@(E.g. 5 minutes)
+
+
+
+`; + +exports.install = function(instance) { + + var route; + + var uninstall = function(id) { + if (F.is4) { + route && route.remove(); + route = null; + } else + UNINSTALL('route', id); + }; + + instance.custom.emptyresponse = function(self) { + self.plain(); + }; + + instance.reconfigure = function() { + + var options = instance.options; + + if (!options.url) { + instance.status('Not configured', 'red'); + return; + } + + if (typeof(options.flags) === 'string') + options.flags = options.flags.split(',').trim(); + + uninstall('id:' + instance.id); + + var flags = options.flags || []; + + flags.push('id:' + instance.id); + + if (!F.is4) + flags.push(options.method.toLowerCase()); + + options.timeout && flags.push(options.timeout * 1000); + + // Make unique values + flags = flags.filter(function(v, i, a) { + if(F.is4 && v.toString().toLowerCase() === options.method.toLowerCase()) + return false; // remove method + return a.indexOf(v) === i; + }); + + options.flags = flags; + var handler = function() { + + if (instance.paused || (instance.isDisabled && (instance.isDisabled('output', 0) || instance.isDisabled('output', 1)))) { + instance.status('503 Service Unavailable'); + this.status = 503; + this.json(); + return; + } + + var key; + var self = this; + + if (instance.options.emptyresponse) { + instance.status('200 OK'); + setTimeout(instance.custom.emptyresponse, 100, self); + + if (instance.hasConnection(0)) { + var data = instance.make({ + query: self.query, + body: self.body, + session: self.session, + user: self.user, + files: self.files, + headers: self.req.headers, + url: self.url, + params: self.params + }); + instance.send2(0, data); + } + + return; + } + + switch (instance.options.cachepolicy) { + case 1: // URL + key = 'rro' + instance.id + self.url.hash(); + break; + case 2: // URL + query + case 3: // URL + query + user + key = self.url; + var keys = Object.keys(self.query); + keys.sort(); + for (var i = 0, length = keys.length; i < length; i++) + key += keys[i] + self.query[keys[i]] + '&'; + if (instance.options.cachepolicy === 3 && self.user) + key += 'iduser' + self.user.id; + key = 'rro' + instance.id + key.hash(); + break; + } + + if (key && F.cache.get2(key)) { + var data = instance.make(F.cache.get2(key)); + data.repository.controller = self; + instance.send2(1, data); + } else { + + var data = instance.make({ + query: self.query, + body: self.body, + session: self.session, + user: self.user, + files: self.files, + headers: self.req.headers, + url: self.url, + params: self.params, + mobile: self.mobile, + robot: self.robot, + referrer: self.referrer, + language: self.language + }); + + data.repository.controller = self; + instance.send2(0, data); + key && FINISHED(self.res, () => F.cache.set(key, self.$flowdata.data, instance.options.cacheexpire)); + } + }; + + if (F.is4) + route = ROUTE(options.method.toUpperCase() + ' ' + options.url, handler, flags, options.size || 5); + else + F.route(options.url, handler, flags, options.size || 5); + + instance.status('Listening', 'green'); + }; + + instance.reconfigure(); + instance.on('options', instance.reconfigure); + instance.on('close', function(){ + uninstall('id:' + instance.id); + }); +}; + +// check url exists +FLOW.trigger('httproutecheckurl', function(next, data) { + var url = data.url; + var method = data.method; + if (url[url.length - 1] !== '/') + url += '/'; + var exists = F.routes.web.findItem(r => r.urlraw === url && r.method === method); + next(exists != null); +}); + +exports.uninstall = function() { + FLOW.trigger('httproutecheckurl', null); +}; diff --git a/RVO25/flow/infosender.js b/RVO25/flow/infosender.js new file mode 100755 index 0000000..587724f --- /dev/null +++ b/RVO25/flow/infosender.js @@ -0,0 +1,81 @@ +exports.id = 'infosender'; +exports.title = 'Info sender'; +exports.version = '1.0.0'; +exports.group = 'Worksys'; +exports.color = '#2134B0'; +exports.input = 2; +exports.output = 1 +exports.icon = 'bolt'; + +const { networkInterfaces } = require('os'); + +exports.html = `
+
+
+
CSV Import
+
+
+
`; + +exports.readme = `# send all data to projects.worksys.io, required to monitor status of controller(unipi)`; + +exports.install = function(instance) { + + let id; + let allValues = {}; + let sendAllValuesInterval; + let configured = false; + + let now = new Date(); + console.log(exports.title, "INSTALLED", now.toLocaleString("sk-SK")); + + const nets = networkInterfaces(); + let ipAddresses = Object.create(null); // Or just '{}', an empty object + + for (const name of Object.keys(nets)) { + for (const net of nets[name]) { + // Skip over non-IPv4 and internal (i.e. 127.0.0.1) addresses + if (net.family === 'IPv4' && !net.internal) { + if (!ipAddresses[name]) { + ipAddresses[name] = []; + } + ipAddresses[name].push(net.address); + } + } + } + + function sendValues() { + if (!configured) return; + + if (Object.keys(allValues).length > 0) { + let dataToSend = { ...allValues }; + dataToSend.id = id; + dataToSend.ipAddresses = ipAddresses; + + instance.send(0, dataToSend); + + allValues = {}; + } + } + + instance.on("close", () => { + clearInterval(sendAllValuesInterval); + }) + + instance.on("0", _ => { + id = FLOW.GLOBALS.settings.project_id; + if (id) configured = true; + else console.log(exports.title, "InfoSender: Unable to send data, no id"); + }) + + instance.on("1", flowdata => { + allValues = { ...allValues, ...flowdata.data }; + //console.log("DATA RECEIVED", flowdata.data); + }) + + sendAllValuesInterval = setInterval(() => { + sendValues(); + }, 60000 * 3); + +} + diff --git a/RVO25/flow/modbus_reader.js b/RVO25/flow/modbus_reader.js new file mode 100755 index 0000000..d6d9dad --- /dev/null +++ b/RVO25/flow/modbus_reader.js @@ -0,0 +1,346 @@ +exports.id = 'modbus_reader'; +exports.title = 'Modbus reader'; +exports.version = '2.0.0'; +exports.group = 'Worksys'; +exports.color = '#2134B0'; +exports.input = 1; +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; +//number of phases inRVO +let phases; +//phases where voltage is 0 (set) +let noVoltage; +let energyToSwitchLamps; + +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.phases = this.buildPhases(); + + this.startSocket(); + } + + buildPhases = () => { + let a = []; + for (let i = 1; i <= phases; i++) { + a.push(`Phase_${i}_voltage`) + } + return a; + } + + startSocket = () => { + + let obj = this; + + if (this.socket) { + this.socket.removeAllListeners(); + this.socket = null; + } + + 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('Modbus_reader: Socket connection error', e); //'ECONNREFUSED' or 'ECONNRESET' ?? + }); + + this.socket.on('close', function() { + console.log('Modbus_reader: Socket connection closed - Waiting 10 seconds before connecting 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 we just start to loop devices from the beginning, or there is just 1 device in config, we wait whole timeoutInterval + if (this.indexInDeviceConfig == 0 || deviceConfig.length === 1) 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 (this.phases.includes(singleValue)) { + let l = singleValue.split("_"); + let phase = parseInt(l[1]); + + // console.log(values[singleValue], tbName); + + if (values[singleValue] == 0) { + noVoltage.add(phase); + sendNotification("modbus_reader: checkNullVoltage", tbName, "no_voltage_on_phase", { phase: phase }, "", SEND_TO.tb, instance, "voltage" + phase); + // console.log('no voltage') + } + else { + noVoltage.delete(phase); + // console.log('voltage detected') + sendNotification("modbus_reader: checkNullVoltage", tbName, "voltage_on_phase_restored", { phase: phase }, "", SEND_TO.tb, instance, "voltage" + phase); + } + } + }) + } + + /** + * function sends notification to slack and to tb, if EM total_power value changes more than numberOfNodes*15. This should show, that RVO lamps has been switched on or off + */ + lampSwitchNotification = (values) => { + + if (!values.hasOwnProperty("total_power")) return; + + const actualTotalPower = values.total_power; + + if (actualTotalPower > energyToSwitchLamps && 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 <= energyToSwitchLamps && 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; + } + + function main() { + + phases = FLOW.GLOBALS.settings.phases; + tbName = FLOW.GLOBALS.settings.rvoTbName; + noVoltage = FLOW.GLOBALS.settings.no_voltage; + energyToSwitchLamps = FLOW.GLOBALS.settings.energy_to_switch_lamps / 2.5; //half value is enought to show if lamps are turned on or off + if (deviceConfig.length) mainSocket = new SocketWithClients(); + else console.log("Modbus_reader: no modbus device in configuration"); + + // this notification is to show, that flow (unipi) has been restarted + sendNotification("modbus_reader", tbName, "flow_restart", {}, "", SEND_TO.slack, instance); + } + + instance.on("0", function(_) { + main(); + }) + +} + diff --git a/RVO25/flow/monitorconsumption.js b/RVO25/flow/monitorconsumption.js new file mode 100755 index 0000000..64cc58e --- /dev/null +++ b/RVO25/flow/monitorconsumption.js @@ -0,0 +1,156 @@ +exports.id = 'monitorconsumption'; +exports.title = 'Consumption'; +exports.version = '1.0.0'; +exports.author = 'Peter Širka'; +exports.group = 'Monitoring'; +exports.color = '#967ADC'; +exports.input = 0; +exports.output = 1; +exports.icon = 'bug'; +exports.options = { interval: 5000, enabled: true, monitorconsumption: true, monitorsize: true, monitorconnections: true, monitorfiles: true }; +exports.click = true; +exports.readme = `# Consumption monitoring + +This component measure CPU and memory consumption, open files and open connections of this application. It uses these Linux commands: \`ps\`, \`lsof\`, \`netstat\` and \`df\`. + +__Data Example__: + +\`\`\`javascript +{ + cpu: 0, // percentage + memory: 4096, // in bytes + size: 34303, // directory size in bytes + files: 34, // count of open files + connections: 343, // count of connections + uptime: '1-12:34:00' +} +\`\`\``; + +exports.html = `
+
+
+
@(Interval in milliseconds)
+
+
+
+
Monitor: Consumption + uptime
+
Monitor: Count of open files
+
Monitor: Count of open connections
+
Monitor: Directory size
+
`; + +exports.install = function(instance) { + + var current = { cpu: 0, memory: 0, files: 0, connections: 0, size: 0, uptime: '', counter: 0 }; + var tproc = null; + var Exec = require('child_process').exec; + var reg_empty = /\s{2,}/g; + var reg_appdisksize = /^[\d.,]+/; + + instance.custom.run = function() { + + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + + var arr = []; + + // Get CPU and Memory consumption + instance.options.monitorconsumption && arr.push(function(next) { + Exec('ps -p {0} -o %cpu,rss,etime'.format(process.pid), function(err, response) { + + if (err) { + instance.throw(err); + } else { + var line = response.split('\n')[1]; + line = line.trim().replace(reg_empty, ' ').split(' '); + var cpu = line[0].parseFloat(); + current.cpu = cpu.floor(1); + current.memory = line[1].parseInt2() * 1024; // kB to bytes + current.uptime = line[2]; + } + + next(); + }); + }); + + // Get count of open files + instance.options.monitorfiles && arr.push(function(next) { + Exec('lsof -a -p {0} | wc -l'.format(process.pid), function(err, response) { + if (err) + instance.throw(err); + else + current.files = response.trim().parseInt2(); + next(); + }); + }); + + // Get count of opened network connections + instance.options.monitorconnections && arr.push(function(next) { + Exec('netstat -an | grep :{0} | wc -l'.format(F.port), function(err, response) { + if (err) { + instance.throw(err); + } else { + current.connections = response.trim().parseInt2() - 1; + if (current.connections < 0) + current.connections = 0; + } + next(); + }); + }); + + // Get directory size + instance.options.monitorsize && current.counter % 5 !== 0 && arr.push(function(next) { + Exec('du -hsb ' + process.cwd(), function(err, response) { + if (err) { + instance.throw(err); + } else { + var match = response.trim().match(reg_appdisksize); + match && (current.size = match.toString().trim().parseInt2()); + } + next(); + }); + }); + + arr.async(function() { + + tproc && clearTimeout(tproc); + + if (instance.options.enabled) { + tproc = setTimeout(instance.custom.run, instance.options.interval); + instance.send2(current); + } + + instance.custom.status(); + current.counter++; + }); + }; + + instance.custom.status = function() { + if (instance.options.enabled) + instance.status('{0}% / {1}'.format(current.cpu, current.memory.filesize())); + else + instance.status('Disabled', 'red'); + }; + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + + if (instance.options.enabled) { + current.counter = 0; + instance.custom.run(); + } + + }); + + instance.on('close', function() { + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + }); + + setTimeout(instance.custom.run, 1000); +}; \ No newline at end of file diff --git a/RVO25/flow/monitordisk.js b/RVO25/flow/monitordisk.js new file mode 100755 index 0000000..f4fdaa0 --- /dev/null +++ b/RVO25/flow/monitordisk.js @@ -0,0 +1,96 @@ +exports.id = 'monitordisk'; +exports.title = 'Disk'; +exports.version = '1.0.0'; +exports.author = 'Peter Širka'; +exports.group = 'Monitoring'; +exports.color = '#F6BB42'; +exports.output = 1; +exports.icon = 'hdd-o'; +exports.click = true; +exports.options = { interval: 8000, path: '/', enabled: true }; +exports.readme = `# Disk monitoring + +This component monitors disk \`bytes\` consumption in Linux systems. It uses \`df\` command. + +__Data Example__: + +\`\`\`javascript +{ + total: 474549649408, + used: 39125245952, + free: 411294994432 +} +\`\`\``; + +exports.html = `
+
+
+
@(Interval in milliseconds)
+
+
+
@(Path)
+
+
+
`; + +exports.install = function(instance) { + + var current = { total: 0, used: 0, free: 0, path: '', type: '', percentUsed: 0 }; + var tproc = null; + + instance.custom.run = function() { + + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + + if (!instance.options.enabled) + return; + + require('child_process').exec('df -hTB1 ' + instance.options.path, function(err, response) { + + tproc = setTimeout(instance.custom.run, instance.options.interval); + + if (err) { + instance.error(err); + return; + } + + response.parseTerminal(function(line) { + if (line[0][0] !== '/') + return; + current.total = line[2].parseInt(); + current.free = line[4].parseInt(); + current.used = line[3].parseInt(); + current.path = instance.options.path || '/'; + current.type = line[1]; + current.percentUsed = line[5]; + instance.custom.status(); + instance.send2(current); + }); + }); + }; + + instance.custom.status = function() { + if (instance.options.enabled) + instance.status(current.free.filesize() + ' / ' + current.total.filesize()); + else + instance.status('Disabled', 'red'); + }; + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + instance.options.enabled && instance.custom.run(); + }); + + instance.on('close', function() { + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + }); + + setTimeout(instance.custom.run, 1000); +}; \ No newline at end of file diff --git a/RVO25/flow/monitormemory.js b/RVO25/flow/monitormemory.js new file mode 100755 index 0000000..2decbc4 --- /dev/null +++ b/RVO25/flow/monitormemory.js @@ -0,0 +1,87 @@ +exports.id = 'monitormemory'; +exports.title = 'Memory'; +exports.version = '1.0.0'; +exports.author = 'Peter Širka'; +exports.group = 'Monitoring'; +exports.color = '#F6BB42'; +exports.output = 1; +exports.click = true; +exports.icon = 'microchip'; +exports.options = { interval: 8000, enabled: true }; +exports.readme = `# Memory monitoring + +This component monitors memory \`bytes\` consumption in Linux systems. It uses \`free\` command. + +__Data Example__: + +\`\`\`javascript +{ + total: 33558769664, + used: 1998868480, + free: 2653708288 +} +\`\`\``; + +exports.html = `
+
+
+
@(Interval in milliseconds)
+
+
+
`; + +exports.install = function(instance) { + + var current = { total: 0, used: 0, free: 0 }; + var tproc = null; + + instance.custom.run = function() { + + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + + if (!instance.options.enabled) + return; + + require('child_process').exec('free -b -t', function(err, response) { + + tproc = setTimeout(instance.custom.run, instance.options.interval); + + if (err) { + instance.error(err); + return; + } + + var memory = response.split('\n')[1].match(/\d+/g); + current.total = memory[0].parseInt(); + current.used = memory[1].parseInt() - memory[3].parseInt(); + current.free = current.total - current.used; + instance.custom.status(); + instance.send2(current); + }); + }; + + instance.custom.status = function() { + if (instance.options.enabled) + instance.status(current.free.filesize() + ' / ' + current.total.filesize()); + else + instance.status('Disabled', 'red'); + }; + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + instance.options.enabled && instance.custom.run(); + }); + + instance.on('close', function() { + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + }); + + setTimeout(instance.custom.run, 1000); +}; \ No newline at end of file diff --git a/RVO25/flow/nodesdb_changecheck.js b/RVO25/flow/nodesdb_changecheck.js new file mode 100755 index 0000000..9adab62 --- /dev/null +++ b/RVO25/flow/nodesdb_changecheck.js @@ -0,0 +1,77 @@ +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 = 2; +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); + } + } + + //kedze do slacku posielame stringy, na cloud musime previest vsetky stringy spat na objekty: + // Funkcia na parsovanie všetkých reťazcov v poli + const parseArray = (arr) => { + return arr.map(jsonString => JSON.parse(jsonString)); + }; + + 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); + if (FLOW.GLOBALS.settings.send_changed_node_numbers) instance.send(1, { aktualneNody: parseArray(zmenene), originalne: parseArray(Array.from(set2)) }); + } + 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/RVO25/flow/show_dbdata.js b/RVO25/flow/show_dbdata.js new file mode 100755 index 0000000..1e23ff7 --- /dev/null +++ b/RVO25/flow/show_dbdata.js @@ -0,0 +1,243 @@ +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 = 8; +exports.output = 1; + +const { exec } = require('child_process'); + +exports.install = 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 }) + }) + instance.on("5", _ => { + exec("sudo tail -n 25 monitor.txt", (err, stdout, stderr) => { + if (err || stderr) instance.send(0, { err, stderr }); + else instance.send(0, stdout); + }) + }) + instance.on("6", _ => { + exec("sudo tail -n 25 err.txt", (err, stdout, stderr) => { + if (err || stderr) instance.send(0, { err, stderr }); + else instance.send(0, stdout); + }) + }) + instance.on("7", _ => { + instance.send(0, FLOW.deviceStatus); + }) +}; + + +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/RVO25/flow/slack_filter.js b/RVO25/flow/slack_filter.js new file mode 100755 index 0000000..6618523 --- /dev/null +++ b/RVO25/flow/slack_filter.js @@ -0,0 +1,188 @@ +exports.id = 'slack_filter'; +exports.title = 'Slack Filter'; +exports.group = 'Citysys'; +exports.color = '#30E193'; +exports.input = 2; +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 = `
+
+
+
@(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('0', 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']['en']; + 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"] = []; + } + + instance.options.name = FLOW.GLOBALS.settings.rvo_name; + if (instance.options.name) { + instance.status('Running'); + running = true; + } else { + instance.status('Please run options again', 'red'); + running = false; + } + } catch (e) { + instance.error('Citysys connector: ' + e.message); + } + }; + + instance.on('options', instance.reconfigure); + + instance.on("1", _ => { + instance.reconfigure(); + }) +}; diff --git a/RVO25/flow/thermometer.js b/RVO25/flow/thermometer.js new file mode 100755 index 0000000..fc7074d --- /dev/null +++ b/RVO25/flow/thermometer.js @@ -0,0 +1,99 @@ +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 = 5;//minutes +let NUMBER_OF_FAILURES_TO_SEND_ERROR = 13; + +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) => { + + 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); + setTimeout(main, 20000); + }) +}; diff --git a/RVO25/flow/trigger.js b/RVO25/flow/trigger.js new file mode 100755 index 0000000..27545a8 --- /dev/null +++ b/RVO25/flow/trigger.js @@ -0,0 +1,79 @@ +exports.id = 'trigger'; +exports.title = 'Trigger'; +exports.group = 'Inputs'; +exports.color = '#F6BB42'; +exports.click = true; +exports.output = 1; +exports.version = '1.1.0'; +exports.author = 'Martin Smola'; +exports.icon = 'play'; + +exports.html = `
+
@(Data type (String by default))
+
@(Data)
+
Trigger 5s after initialization.
+
@(Useful when there's a need to run certain flow when the app restarts, etc.)
+
`; + +exports.readme = `# Trigger + +- Clicking on the component starts the chain +- Settings allows to set a data-type and a value`; + +exports.install = function(instance) { + + var value; + + instance.on('click', () => instance.send2(value)); + + instance.reconfigure = function() { + var options = instance.options; + value = null; + switch (options.datatype) { + case 'integer': + value = options.data.parseInt2('error'); + value = value === 'error' ? NaN : value; + break; + case 'float': + value = options.data.parseFloat2('error'); + value = value === 'error' ? NaN : value; + break; + case 'date': + options.data = options.data.toString(); + var num = options.data.parseInt('error'); + num === 'error' && (num = options.data.parseDate('error')); + num === 'error' && (num = null); + value = num ? new Date(num).toUTCString() : num; + break; + case 'object': + try { + value = (new Function('return ' + options.data))(); + } catch (e) { + instance.error(e); + } + break; + case 'boolean': + value = options.data.parseBoolean(); + break; + case 'buffer': + try { + value = U.createBuffer(options.data); + } catch (e) { + instance.error(e); + } + break; + case 'string': + default: + value = '' + (options.data || ''); + break; + } + }; + + instance.on('options', instance.reconfigure); + instance.reconfigure(); + + if (instance.options.restart) + setTimeout(function(){ + instance.send2(value); + }, 5000); +}; diff --git a/RVO25/flow/variables.txt b/RVO25/flow/variables.txt new file mode 100755 index 0000000..e69de29 diff --git a/RVO25/flow/virtualwirein.js b/RVO25/flow/virtualwirein.js new file mode 100755 index 0000000..38a4e42 --- /dev/null +++ b/RVO25/flow/virtualwirein.js @@ -0,0 +1,43 @@ +exports.id = 'virtualwirein'; +exports.title = 'Virtual wire in'; +exports.version = '1.0.0'; +exports.author = 'Martin Smola'; +exports.color = '#303E4D'; +exports.icon = 'sign-in'; +exports.input = false; +exports.output = 1; +exports.options = {}; +exports.readme = `# Virtual wire in + +When the wires between the components are mess it's time to use Virtual wire.`; + +exports.html = `
+
@(Wire name)
+
+`; + +exports.install = function(instance) { + + instance.custom.reconfigure = function(options){ + if (instance.options.wirename) { + instance.status(instance.options.wirename); + } else + instance.status('Not configured', 'red'); + }; + + ON('virtualwire', function(wirename, flowdata){ + if (instance.options.wirename && instance.options.wirename === wirename) + instance.send(flowdata); + }); + + instance.on('options', instance.custom.reconfigure); + instance.custom.reconfigure(); +}; diff --git a/RVO25/flow/virtualwireout.js b/RVO25/flow/virtualwireout.js new file mode 100755 index 0000000..94a1e4f --- /dev/null +++ b/RVO25/flow/virtualwireout.js @@ -0,0 +1,41 @@ +exports.id = 'virtualwireout'; +exports.title = 'Virtual wire out'; +exports.version = '1.0.0'; +exports.author = 'Martin Smola'; +exports.color = '#303E4D'; +exports.icon = 'sign-out'; +exports.input = true; +exports.options = {}; +exports.readme = `# Virtual wire out + +When the wires between the components are mess it's time to use Virtual wire.`; + +exports.html = `
+
@(Wire name)
+
+`; + +exports.install = function(instance) { + + instance.custom.reconfigure = function(){ + if (instance.options.wirename) { + instance.status(instance.options.wirename); + } else + instance.status('Not configured', 'red'); + }; + + instance.on('data', function(flowdata) { + EMIT('virtualwire', instance.options.wirename, flowdata); + }); + + instance.on('options', instance.custom.reconfigure); + instance.custom.reconfigure(); +}; diff --git a/RVO25/flow/wsmqttpublish.js b/RVO25/flow/wsmqttpublish.js new file mode 100755 index 0000000..0eba804 --- /dev/null +++ b/RVO25/flow/wsmqttpublish.js @@ -0,0 +1,448 @@ +exports.id = 'wsmqttpublish'; +exports.title = 'WS MQTT publish'; +exports.group = 'MQTT'; +exports.color = '#888600'; +exports.version = '1.0.2'; +exports.icon = 'sign-out'; +exports.input = 2; +exports.output = 3; +exports.options = { host: 'tb-stage.worksys.io', port: 1883, clientid: "", username: "" }; + +exports.html = `
+
+
+
Hostname or IP address (if not empty - setting will override db setting)
+
+
+
Port
+
+
+
+
+
@(Client id)
+
+
+
@(Username)
+
+
+
`; + + +exports.readme = ` +# WS MQTT Publish + +Version 1.0.3. + +Added: +- database collections, +- 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 = { + debug: 0, + rpcCall: 1, + services: 2 +} + +//CONFIG +let createTelemetryBackup = true; +let saveTelemetryOnError = true;//backup_on_failure overrides this value +//------------------------ + +let rollers; +if (createTelemetryBackup) rollers = require('streamroller'); + +const noSqlFileSizeLimit = 4194304;//use 5MB - 4194304 +let insertNoSqlCounter = 0; +let insertBackupNoSqlCounter = 0; +let processingData = false; + +let backup_on_failure = false;//== saveTelemetryOnError - create backup client 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; + +process.on('uncaughtException', function(err) { + + errLogger.error('uncaughtException:', err.message) + errLogger.error(err.stack); + + //TODO + //send to service + + //process.exit(1); +}) + +const nosql = NOSQL('tbdata'); +const nosqlBackup = NOSQL('/backup/tbdata'); + + +exports.install = function(instance) { + + var client; + var opts; + var clientReady = false; + + // wsmqtt status for notification purposes on projects.worksys.io database + let wsmqttName = null; + let sendWsStatusVar = null; + let wsmqtt_status = 'disconnected'; + + 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'; + } + + function sendWsStatus() { + instance.send(SEND_TO.services, { [wsmqttName]: wsmqtt_status }); + } + + + function main() { + if (!FLOW.dbLoaded) return; + + loadSettings(); + clearInterval(sendWsStatus); + sendWsStatusVar = setInterval(sendWsStatus, 180000); + } + + //set opts according to db settings + function loadSettings() { + + if (instance.options.host !== "") { + //override settings from database + var o = instance.options; + opts = { + host: o.host, + port: o.port, + clientId: o.clientid, + username: o.username, + rejectUnauthorized: false, + resubscribe: false + }; + + wsmqttName = getWsmqttName(o.host); + + console.log("wsmqttpublich -> loadSettings from instance.options", instance.options); + } + else { + + const SETTINGS = FLOW.GLOBALS.settings; + backup_on_failure = SETTINGS.backup_on_failure; + saveTelemetryOnError = backup_on_failure; + + restore_from_backup = SETTINGS.restore_from_backup; + restore_backup_wait = SETTINGS.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; + + opts = { + host: mqtt_host, + port: mqtt_port, + keepalive: 10, + clientId: mqtt_clientid, + username: mqtt_username, + rejectUnauthorized: false, + resubscribe: false + }; + + wsmqttName = getWsmqttName(mqtt_host); + } + + connectToTbServer(); + } + + function connectToTbServer() { + 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"); + //monitor.info("MQTT client connected"); + + sendClientError = true; + clientReady = true; + wsmqtt_status = 'connected'; + }); + + client.on('reconnect', function() { + instance.status("Reconnecting", "yellow"); + clientReady = false; + }); + + client.on('message', function(topic, message) { + // message is type of buffer + message = message.toString(); + if (message[0] === '{') { + TRY(function() { + + message = JSON.parse(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 } }); + } + + }, () => instance.debug('MQTT: Error parsing data', message)); + } + + instance.send(SEND_TO.rpcCall, { "topic": topic, "content": message }); + }); + + client.on('close', function() { + clientReady = false; + wsmqtt_status = 'disconnected'; + + instance.status("Disconnected", "red"); + instance.send(SEND_TO.debug, { "message": "Client CLOSE signal received !" }); + }); + + client.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; + wsmqtt_status = 'disconnected'; + }); + + } + + + instance.on("0", _ => { + main(); + }) + + + instance.on('1', function(data) { + + if (clientReady) { + //do we have some data in backup file? if any, process data from database + if (saveTelemetryOnError) { + //read telemetry data and send back to server + if (!processingData) processDataFromDatabase(); + } + + let stringifiedJson = JSON.stringify(data.data); + client.publish("v1/gateway/telemetry", stringifiedJson, { qos: 1 }); + + //backup telemetry + if (createTelemetryBackup) { + data.data.id = UID(); + nosqlBackup.insert(data.data); + + insertBackupNoSqlCounter++; + if (insertBackupNoSqlCounter > 150) { + let options = { compress: true }; + let path = __dirname + "/../databases/backup/tbdata.nosql"; + var stream = new rollers.RollingFileStream(path, noSqlFileSizeLimit, 150, options); + stream.write(""); + stream.end(); + + insertBackupNoSqlCounter = 0; + } + } + + } + 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 (saveTelemetryOnError) { + //create new file from tbdata.nosql, if file size exceeds given limit, and clear tbdata.nosql + makeBackupFromDbFile(); + + //write to tb + data.data.id = UID(); + nosql.insert(data.data); + } + } + }); + + + instance.close = function(done) { + if (clientReady) { + client.end(); + clearInterval(sendWsStatusVar); + } + }; + + + function getDbBackupFileCounter(type) { + var files = fs.readdirSync(__dirname + "/../databases"); + + let counter = 0; + for (var i = 0; i < files.length; i++) { + + if (files[i] == "tbdata.nosql") continue; + + if (files[i].endsWith(".nosql")) { + + let pos = files[i].indexOf("."); + if (pos > -1) { + + let fileCounter = counter; + let firstDigit = files[i].slice(0, pos); + + fileCounter = parseInt(firstDigit); + if (isNaN(fileCounter)) fileCounter = 0; + //console.log("getDbBackupFileCounter digit:", files[i], firstDigit, fileCounter, isNaN(fileCounter), type); + + if (type == "max") { + if (fileCounter > counter) { + counter = fileCounter; + } + } + else if (type == "min") { + if (counter == 0) counter = fileCounter; + + if (fileCounter < counter) { + counter = fileCounter; + } + } + } + } + + } + + if (type == "max") counter++; + + return counter; + } + + const makeBackupFromDbFile = async () => { + + if (!saveTelemetryOnError) return; + + //to avoid large file: tbdata.nosql + + //init value is 0! + if (insertNoSqlCounter > 0) { + --insertNoSqlCounter; + return; + } + + insertNoSqlCounter = 100; + + let source = __dirname + "/../databases/tbdata.nosql"; + + var stats = fs.statSync(source); + var fileSizeInBytes = stats.size; + + if (fileSizeInBytes > noSqlFileSizeLimit) { + + let counter = 1; + counter = getDbBackupFileCounter("max"); + + let destination = __dirname + "/../databases/" + counter + "." + "tbdata.nosql"; + + //make backup file + fs.copyFileSync(source, destination); + //fs.renameSync(p, p + "." + counter); + + //clear tbdata.nosql + fs.writeFileSync(source, ""); + fs.truncateSync(source, 0); + + } + } + + const processDataFromDatabase = async () => { + + if (restore_from_backup <= 0) return; + + //calculate diff + const now = new Date(); + let currentTime = now.getTime(); + let diff = currentTime - lastRestoreTime; + + if ((diff / 1000) < restore_backup_wait) { + //console.log("*********restore_backup_wait", diff, restore_backup_wait); + return; + } + + processingData = true; + + //get filename to process + let counter = getDbBackupFileCounter("min"); + + //we have some backup files + let dataBase = 'tbdata'; + + var nosql; + if (counter == 0) dataBase = 'tbdata'; + else dataBase = counter + "." + 'tbdata'; + + nosql = NOSQL(dataBase); + + //select all data - use limit restore_from_backup + let records = await promisifyBuilder(nosql.find().take(restore_from_backup)); + + for (let i = 0; i < records.length; i++) { + if (clientReady) { + + let item = records[i]; + let id = item.id; + + if (id !== undefined) { + //console.log("------------processDataFromDatabase - remove", id, dataBase, i); + + try { + + let message = JSON.parse(JSON.stringify(item)); + delete message.id; + + client.publish("v1/gateway/telemetry", JSON.stringify(message), { qos: 1 }); + + //remove from database + await promisifyBuilder(nosql.remove().where("id", id)); + + } catch (error) { + //process error + console.log("processDataFromDatabase", error); + } + + } + + } + else { + processingData = false; + return; + } + } + + if (records.length > 0) { + //clean backup file + if (counter > 0) nosql.clean(); + } + + //no data in db, remove + if (records.length == 0) { + if (counter > 0) nosql.drop(); + } + + const d = new Date(); + lastRestoreTime = d.getTime(); + + processingData = false; + + } + + instance.on('options', main); + //instance.reconfigure(); +}; diff --git a/RVO25/flow_15_1_2025/cloudmqttconnect.js b/RVO25/flow_15_1_2025/cloudmqttconnect.js new file mode 100755 index 0000000..d619784 --- /dev/null +++ b/RVO25/flow_15_1_2025/cloudmqttconnect.js @@ -0,0 +1,374 @@ +exports.id = 'cloudmqttconnect'; +exports.title = 'Cloud connect mqtt'; +exports.group = 'MQTT'; +exports.color = '#888600'; +exports.version = '1.0.2'; +exports.icon = 'sign-out'; +exports.input = 2; +exports.output = 2; +exports.options = { host: 'tb-stage.worksys.io', port: 1883, clientid: "", username: "" }; + +exports.html = `
+
+
+
Hostname or IP address (if not empty - setting will override db setting)
+
+
+
Port
+
+
+
+
+
@(Client id)
+
+
+
topic
+
+
+
`; + + + +const { promisifyBuilder } = require('./helper/db_helper'); +const fs = require('fs'); +const mqtt = require('mqtt'); +const nosql = NOSQL('tbdatacloud'); + +const SEND_TO = { + debug: 0, + rpcCall: 1, +} + +//CONFIG +let saveTelemetryOnError = true;//backup_on_failure overrides this value +//------------------------ + +const noSqlFileSizeLimit = 4194304;//use 5MB - 4194304 +let insertNoSqlCounter = 0; +let insertBackupNoSqlCounter = 0; +let processingData = false; + +let backup_on_failure = true;//== saveTelemetryOnError - create backup client send failure +let restore_from_backup = 50; //how many rows process at once? +let restore_backup_wait = 3;//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; + + +exports.install = function(instance) { + + var client; + var opts; + var clientReady = false; + + let o = null; //options + + function main() + { + loadSettings(); + } + + //set opts according to db settings + function loadSettings() + { + + o = instance.options; + if(!o.topic) o.topic = FLOW.GLOBALS.settings.cloud_topic; + + opts = { + host: o.host, + port: o.port, + clientId: o.clientid, + username: o.username, + rejectUnauthorized: false, + resubscribe: false + }; + + console.log("wsmqttpublich -> loadSettings from instance.options",o); + + connectToTbServer(); + } + + function connectToTbServer() + { + var url = "mqtt://" + opts.host + ":" + opts.port; + console.log("MQTT URL: ", url); + + client = mqtt.connect(url, opts); + + client.on('connect', function() { + client.subscribe(`${o.topic}_backward`, (err) => { + if (!err) { + console.log("MQTT subscribed"); + } + }); + instance.status("Connected", "green"); + clientReady = true; + sendClientError = true; + }); + + client.on('reconnect', function() { + instance.status("Reconnecting", "yellow"); + clientReady = false; + }); + + client.on('message', function(topic, message) { + // message is type of buffer + message = message.toString(); + if (message[0] === '{') { + TRY(function() { + + message = JSON.parse(message); + if (message.hasOwnProperty("device") && message.hasOwnProperty("data") && message.data.hasOwnProperty("id")) { + client.publish(`${o.topic}_forward`, `{"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}}); + } + + }, () => instance.debug('MQTT: Error parsing data', message)); + } + + instance.send(SEND_TO.rpcCall, {"topic":o.topic, "content":message }); + }); + + client.on('close', function() { + clientReady = false; + + instance.status("Disconnected", "red"); + instance.send(SEND_TO.debug, {"message":"Client CLOSE signal received !"}); + }); + + client.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) { + console.log('MQTT client error', err); + sendClientError = false; + } + clientReady = false; + }); + + } + + + instance.on('0', function(data) { + + if(clientReady) + { + //do we have some data in backup file? if any, process data from database + if(saveTelemetryOnError) + { + //read telemetry data and send back to server + if(!processingData) processDataFromDatabase(); + } + + let stringifiedJson = JSON.stringify(data.data) + client.publish(`${o.topic}_forward`, stringifiedJson, {qos: 1}); + } + 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(saveTelemetryOnError) + { + //create new file from tbdata.nosql, if file size exceeds given limit, and clear tbdata.nosql + makeBackupFromDbFile(); + + //write to tb + data.data.id = UID(); + nosql.insert(data.data); + } + } + }); + + instance.on("1", _ => { + main(); + }) + + instance.close = function(done) { + if(clientReady){ + client.end(); + } + }; + + + function getDbBackupFileCounter(type) + { + var files = fs.readdirSync(__dirname + "/../databases"); + + let counter = 0; + for(var i = 0; i < files.length; i++) + { + + if(files[i] == "tbdatacloud.nosql") continue; + + if(files[i].endsWith(".nosql")) + { + + let pos = files[i].indexOf("."); + if(pos > -1) + { + + let fileCounter = counter; + let firstDigit = files[i].slice(0, pos); + + fileCounter = parseInt(firstDigit); + if(isNaN(fileCounter)) fileCounter = 0; + //console.log("getDbBackupFileCounter digit:", files[i], firstDigit, fileCounter, isNaN(fileCounter), type); + + if(type == "max") + { + if(fileCounter > counter) + { + counter = fileCounter; + } + } + else if(type == "min") + { + if(counter == 0) counter = fileCounter; + + if(fileCounter < counter) + { + counter = fileCounter; + } + } + } + } + + } + + if(type == "max") counter++; + + return counter; + } + + const makeBackupFromDbFile = async () => { + + if(!saveTelemetryOnError) return; + + //to avoid large file: tbdata.nosql + + //init value is 0! + if(insertNoSqlCounter > 0) + { + --insertNoSqlCounter; + return; + } + + insertNoSqlCounter = 100; + + let source = __dirname + "/../databases/tbdatacloud.nosql"; + + var stats = fs.statSync(source); + var fileSizeInBytes = stats.size; + + if(fileSizeInBytes > noSqlFileSizeLimit) + { + + let counter = 1; + counter = getDbBackupFileCounter("max"); + + let destination = __dirname + "/../databases/" + counter + "." + "tbdatacloud.nosql"; + + //make backup file + fs.copyFileSync(source, destination); + //fs.renameSync(p, p + "." + counter); + + //clear tbdata.nosql + fs.writeFileSync(source, ""); + fs.truncateSync(source, 0); + + } + } + + const processDataFromDatabase = async () => { + + if(restore_from_backup <= 0) return; + + //calculate diff + const now = new Date(); + let currentTime = now.getTime(); + let diff = currentTime - lastRestoreTime; + + if( (diff / 1000) < restore_backup_wait) + { + //console.log("*********restore_backup_wait", diff, restore_backup_wait); + return; + } + + processingData = true; + + //get filename to process + let counter = getDbBackupFileCounter("min"); + + //we have some backup files + let dataBase = 'tbdata'; + + var nosql; + if(counter == 0) dataBase = 'tbdatacloud'; + else dataBase = counter + "." + 'tbdatacloud'; + + nosql = NOSQL(dataBase); + + //select all data - use limit restore_from_backup + let records = await promisifyBuilder(nosql.find().take(restore_from_backup)); + + for(let i = 0; i < records.length; i++) + { + if(clientReady) { + + let item = records[i]; + let id = item.id; + + if(id !== undefined) + { + //console.log("------------processDataFromDatabase - remove", id, dataBase, i); + + try { + + let message = JSON.parse(JSON.stringify(item)); + delete message.id; + client.publish(`${o.topic}_forward`, JSON.stringify(message), {qos:1}); + + //remove from database + await promisifyBuilder(nosql.remove().where("id", id)); + + } catch(error) { + //process error + console.log("processDataFromDatabase", error); + } + + } + + } + else + { + processingData = false; + return; + } + } + + if(records.length > 0) + { + //clean backup file + if(counter > 0) nosql.clean(); + } + + //no data in db, remove + if(records.length == 0) + { + if(counter > 0) nosql.drop(); + } + + const d = new Date(); + lastRestoreTime = d.getTime(); + + processingData = false; + + } + + instance.on('options', main); + +}; diff --git a/RVO25/flow_15_1_2025/cmd_manager.js b/RVO25/flow_15_1_2025/cmd_manager.js new file mode 100755 index 0000000..a960aaa --- /dev/null +++ b/RVO25/flow_15_1_2025/cmd_manager.js @@ -0,0 +1,2988 @@ +exports.id = 'cmd_manager'; +exports.title = 'CMD Manager'; +exports.group = 'Worksys'; +exports.color = '#5D9CEC'; +exports.version = '0.0.3'; +exports.output = ['red', 'blue', 'yellow', 'blue', 'white']; +exports.input = 3; +exports.icon = 'cloud-upload'; + +exports.html = ` +
+
+
+
RPC - run RPC calls

+
+
+
@(User)
+
+
+
@(Password)
+
+
+
@(My edge)
+
+
+
+`; +exports.readme = `Manager for CMD calls`; + + +exports.install = function(instance) { + + 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'); + + 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'); + + const dbNodes = TABLE("nodes"); + const dbRelays = TABLE("relays"); + + let GLOBALS; + let SETTINGS; + let rsPort; + let tbHandler; + + // runTasks intervals + const SHORT_INTERVAL = 30; + const LONG_INTERVAL = 300; + + //send data to following instances: + const SEND_TO = { + debug: 0, + tb: 1, + http_response: 2, + dido_controller: 3, + infoSender: 4 + } + + 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 + } + + 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 + + //if sending of profile to node fails, we send notification and push node into set, so we do not send notification twice + const nodeProfileSendFail = new Set(); + + //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(); + } + + + 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" + //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); + + 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); + + console.log("proces profile finished *********************") + } + + + 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; + }); + } + + + 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) { + for (let k in nodesData) { + 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`); + } + } + } + + + function loadRelaysData(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 (value.contactor == 1) processAllNodeProfilesOnLine(value.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 = {}; + + 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.byte1 = hours;//h + params.byte2 = minutes;//m + params.byte3 = seconds;//s + params.byte4 = 0; + params.recipient = 2;//2 broadcast, address = 0 + params.register = 87;//Actual time + params.rw = 1;//write + + //other values + params.type = "cmd"; + params.timestamp = Date.now() + 60000; + params.addMinutesToTimestamp = addMinutesToTimestamp; + params.info = "run broadcast: Actual time"; + + tasks.push(params); + + let sec = 3; + 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) { + 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); + + 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'; + //params.debug = true; + + tasks.push(params); + } + + //Prúd + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "cmd"; + params.tbname = tbname; + params.address = node; + params.register = 75;//prud + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read current'; + //params.debug = true; + + tasks.push(params); + } + + //výkon + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "cmd"; + params.tbname = tbname; + params.address = node; + params.register = 76;//výkon + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read power'; + //params.debug = true; + + tasks.push(params); + } + } + } + }, sec * 1000); + } + + + 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"; + + const date = Date.now(); + + // 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); + }) + + } + + + function turnLine(onOrOff, line, info) { + let obj = { + line: line, + command: onOrOff, + info: info + }; + + logger.debug("linia", line, obj); + instance.send(SEND_TO.dido_controller, obj); + } + + + + 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"; + 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]) { + //CRC_ERROR + message = "NOK"; + error = "CRC_ERROR c1"; + instance.send(SEND_TO.debug, "CRC_ERROR c1"); + } + + 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") { + instance.send(SEND_TO.debug, bytes); + instance.send(SEND_TO.debug, "RESPONSE " + type + " - " + bytes[4]); + + //logger.debug(SEND_TO.debug, "RESPONSE " + type + " - " + bytes[4], bytes); + + error = "type is: " + type; + + message = "NOK"; + } + + return { message, type, error }; + } + + + //BUILD TASKS// + function buildTasks(params) { + //report SETTINGS.edge_fw_version as fw_version + //report date as startdate + + //return; + console.log("buidTAaasks start ****************", params); + + monitor.info("buildTasks - params", params); + + let processLine; //defined line + let init = false; + let processLineProfiles = true; + let processBroadcast = true; + let processNodes = true; + + if (params == undefined) { + init = true; + tasks = []; + logger.debug("-->buildTasks clear tasks"); + } + else { + processLineProfiles = false; + processBroadcast = false; + processNodes = false; + + processLineProfiles = params.processLineProfiles; + processLine = params.line; + } + + //load profiles pre vsetky linie: + let now = new Date(); + + if (processLineProfiles) { + //process line profiles + let keys = Object.keys(relaysData); + 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; + } + + try { + + /** + * we process line profiles: timepoints, astro clock, lux_sensor, offsets ... + */ + if (profilestr === "") throw ("Profile is not defined"); + let profile = JSON.parse(profilestr); + 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; + + // add name to regular profile timepoint and delete unused end_time key: + time_points.forEach(point => { + point.name = "profileTimepoint" + delete point.end_time; + }); + + //monitor.info("buildTasks: time_points", time_points); + + + /** + * 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 astro clock true, we remove all regular profile points + time_points = []; + + 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 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); + + 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); + + 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(':'); + + let ad = new Date(); + ad.setHours(parseInt(ahours), parseInt(aminutes), 0); + + let bd = new Date(); + bd.setHours(parseInt(bhours), parseInt(bminutes), 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++) { + + let start_time = new Date(); + let [hours, minutes] = time_points[t].start_time.split(':'); + start_time.setHours(parseInt(hours), parseInt(minutes), 0); + + //task is in 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); + params.value = time_points[t].value; + params.tbname = relaysData[line].tbname; + params.timestamp = start_time.getTime(); + + 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; + + //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)) { + 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; + + params.debug = true; + + //turn on/off line + tasks.push(params); + monitor.info("TimePoint params: ", params.info, start_time); + } + + monitor.info("-->time_points final", line, time_points); + + //ensure to turn on/off according to calculated currentValue + let params = getParams(PRIORITY_TYPES.terminal); + params.type = "relay"; + params.line = parseInt(line); + params.tbname = relaysData[line].tbname; + params.value = currentValue; + + params.timestamp = PRIORITY_TYPES.terminal; + params.addMinutesToTimestamp = 0; + params.debug = true; + + //logger.debug(now.toLocaleString("sk-SK")); + 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; + + tasks.push(params); + + } catch (error) { + if (profilestr !== "") { + //errLogger.error(profilestr, error); + errorHandler.sendMessageToService(profilestr + "-" + error, 0, "js_error"); + } + } + + } + + //logger.debug("tasks:"); + //logger.debug(tasks); + } + + + //PROCESS DEFAULT BROADCASTS + //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.register = 6;//Time of dusk - Reg 6 + params.rw = 1;//write + + //other values + params.type = "cmd"; + params.timestamp = Date.now() + 60000; + params.addMinutesToTimestamp = addMinutesToTimestamp; + params.info = "Broadcast-duskTime"; + + tasks.push(params); + } + + { + + //run broadcast Time of dawn + 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 + params.byte3 = 0;//s + params.byte4 = 0; + params.recipient = 2; //2 broadcast + params.register = 7;//Time of dawn - Reg 6 + params.rw = 1;//write + + //other values + params.type = "cmd"; + params.timestamp = Date.now() + 60000; + params.addMinutesToTimestamp = addMinutesToTimestamp; + params.info = "Broadcast-dawnTime"; + + tasks.push(params); + } + + { + //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 + params.byte3 = seconds;//s + params.byte4 = 0; + params.recipient = 2; //2 broadcast + params.register = 87;//Actual time + params.rw = 1;//write + + //other values + params.type = "cmd"; + params.timestamp = Date.now() + 60000; + params.addMinutesToTimestamp = addMinutesToTimestamp; + params.info = "run broadcast: Actual time"; + + tasks.push(params); + } + + } + + //process nodes & tasks + //reportovanie pre platformu + 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++) { + register = listOfCommands[i]; + + let params = getParams(PRIORITY_TYPES.node_cmd); + + //core rpc values + params.address = address; + params.byte1 = 0; + params.byte2 = 0; + params.byte3 = 0; + params.byte4 = 0; + 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) { + timestampStart = timestampStart + addMinutesToTimestamp * 60000; + } + + //other values + params.type = "cmd"; + params.tbname = tbname; + params.timestamp = timestampStart; + params.addMinutesToTimestamp = addMinutesToTimestamp; + params.info = "generated cmd - buildTasks (node)"; + + tasks.push(params); + + } + } + } + + + //niektore ulohy sa vygeneruju iba 1x pri starte!!! + if (!init) return; + + + //Priebežne (raz za cca 5 minút) je potrebné vyčítať z Master nodu verziu jeho FW. + //Jedná sa o register 10. Rovnaká interpretácia ako pri FW verzii nodu. + //Adresa mastera je 0. V prípade že kedykoľvek nastane situácia že Master Node neodpovedá (napríklad pri vyčítaní telemetrie z nodu nevráti žiadne dáta), + //tak treba vyreportovať string "NOK". + { + let params = getParams(PRIORITY_TYPES.fw_detection); + params.type = "cmd-master"; + params.register = 4; + params.address = 0; + params.timestamp = Date.now() + 60000; + params.addMinutesToTimestamp = 5; + params.tbname = SETTINGS.rvoTbName; + params.info = "Master node FW verzia"; + //params.debug = true; + + //this will set SETTINGS.masterNodeIsResponding + + tasks.push(params); + } + + //kazdu hodinu skontrolovat nastavenie profilov + { + let params = getParams(PRIORITY_TYPES.fw_detection); + params.type = "process_profiles"; + params.timestamp = Date.now() + 60000; + params.addMinutesToTimestamp = 60;//60 = every hour + params.info = "detekcia nespracovaných profilov linie a nodov"; + //params.debug = true; + + tasks.push(params); + } + + monitor.info("tasks created:", tasks.length); + } + + + /** + * We process line profile, where "astro_clock": true + * example profile: + * + "dawn_lux_sensor": true, + "dusk_lux_sensor": true, + "dawn_lux_sensor_value": 5, + "dusk_lux_sensor_value": 5, + "dawn_astro_clock_offset": 0, + "dusk_astro_clock_offset": 10, + "dawn_lux_sensor_time_window": 30, + "dusk_lux_sensor_time_window": 30, + "dawn_astro_clock_time_window": 60, + "dusk_astro_clock_time_window": 60 + + * if dawn: if currentTimestamp is in timewindow "dawnTime + and - dawn_lux_sensor_time_window" and lux value >= lux_sensor_value, we switch off the line. + * if dusk: we do oposite + * + * dawn: usvit - lux je nad hranicou - vypnem + * dusk: sumrak - lux je pod hranicou - zapnem + */ + 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++) { + + let line = keys[i]; //line is turned off by default + let profilestr = relaysData[line].profile; + const contactor = relaysData[line].contactor; + + try { + + let profile = JSON.parse(profilestr); + if (Object.keys(profile).length === 0) throw ("turnOnOffLinesAccordingToLuxSensor - profile is not defined"); + + 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 (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"); + } + } + } + + //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 (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"); + } + } + } + + } + + } catch (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) { + //MASTER + if (node == 0) return; + + let nodeObj = nodesData[node]; + 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; + } + + } + + + 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 }; + } + }); + }); + } + + + async function runTasks() { + + clearInterval(interval); + + let currentTimestamp = Date.now(); + + //report dusk, dawn--------------------------------- + if (reportDuskDawn.dusk_time < currentTimestamp) { + //vyreportuj iba ak nie je velky rozdiel napr. 60 sekund + 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); + reportDuskDawn.dusk_time_reported = sunCalcResult.dusk_time; + } + } + + var nextDay = new Date(); + nextDay.setDate(nextDay.getDate() + 1); + + sunCalcResult = calculateDuskDawn(nextDay); + reportDuskDawn.dusk_time = sunCalcResult.dusk_time; + } + + if (reportDuskDawn.dawn_time < currentTimestamp) { + //vyreportuj iba ak nie je velky rozdiel napr. 60 sekund + 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); + reportDuskDawn.dawn_time_reported = sunCalcResult.dawn_time; + } + } + + var nextDay = new Date(); + nextDay.setDate(nextDay.getDate() + 1); + + sunCalcResult = calculateDuskDawn(nextDay); + reportDuskDawn.dawn_time = sunCalcResult.dawn_time; + + } + //-------------------------------------------------------- + + //sort tasks based on timestamp + 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) { + instance.send(SEND_TO.debug, "no tasks created"); + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + 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) { + //logger.debug("--->task to process", currentTask); + } + + if (currentTask.timestamp <= currentTimestamp) { + let params = { ...tasks[0] }; + + //allow terminal commands + if (SETTINGS.maintenance_mode && params.type !== "cmd-terminal") { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + let type = params.type; + let tbname = params.tbname; + let node = params.address; + + let line = null; + + //rpc related + if (nodesData[node] !== undefined) line = nodesData[node].line; + if (params.line !== undefined) line = params.line; + + let repeatTask = false; + if (params.addMinutesToTimestamp > 0 || params.timePointName) repeatTask = true; + + if (repeatTask) { + if (type === "cmd" || type === "cmd-master") { + //set next start time automatically + tasks[0].timestamp = currentTimestamp + tasks[0].addMinutesToTimestamp * 60000; + } + } + else { + tasks.shift(); + } + + //kontrola nespracovanych profilov nodov + if (type == "process_profiles") { + tasks[0].timestamp = currentTimestamp + tasks[0].addMinutesToTimestamp * 60000; + + //vsetky linie kt. su zapnute, a spracuju sa nespracovane profily nodov + loadRelaysData(); + + interval = setInterval(runTasks, SHORT_INTERVAL); + return; + } + + //relay + if (type == "relay") { + + const timePointName = params.timePointName; + const value = params.value; + + let date = new Date(); + date.setDate(date.getDate() + 1);//next day + + let sunCalcResult; + if (timePointName) sunCalcResult = calculateDuskDawn(date, params.line); + + if (timePointName == "dawn") { + tasks[0].timestamp = sunCalcResult.dawn_time; + } + else if (timePointName == "dusk") { + tasks[0].timestamp = sunCalcResult.dusk_time; + } + else if (timePointName == "luxOn") { + tasks[0].timestamp = sunCalcResult.dusk_time + params.dusk_lux_sensor_time_window * 60000; + } + else if (timePointName == "luxOff") { + tasks[0].timestamp = sunCalcResult.dawn_time + params.dawn_lux_sensor_time_window * 60000; + } + else if (timePointName == "profileTimepoint") { + tasks[0].timestamp = currentTimestamp + tasks[0].addMinutesToTimestamp * 60000; + } + + let info = "aplikovany bod profilu"; + let onOrOff = ""; + value == 1 ? onOrOff = "on" : onOrOff = "off"; + + turnLine(onOrOff, params.line, info); + + interval = setInterval(runTasks, SHORT_INTERVAL); + return; + } + + //zhodeny hlavny istic + let disconnected = false; + //if(rotary_switch_state == "Off") disconnected = true; + + //state_of_breaker[line] - alebo istic linie + 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" }; + + 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; + + if (!disconnectedReport[tbname]) { + sendTelemetry(values, tbname) + } + + interval = setInterval(runTasks, SHORT_INTERVAL); + + return; + } + + disconnectedReport[tbname] = false; + + const register = params.register; + + //high_priority + if (!SETTINGS.masterNodeIsResponding) { + //ak neodpoveda, nebudeme vykonavat ziadne commands, okrem cmd-terminal, a fw version + errorHandler.sendMessageToService("Master node is not responding"); + + let stop = true; + + //fw version - register == 4 + if (type == "cmd-terminal" || register == 4) stop = false; + if (stop) { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + } + + let contactorStatus = 1; + if (relaysData[line] != undefined) contactorStatus = relaysData[line].contactor; + + if (line == 0 || contactorStatus == 0) { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + // TODO: -> status offline for rvo if rotary_switch_state is OFF, this is source of errors + // + // let relayStatus = 1; + // if (relaysData[line] != undefined) { + // relayStatus = relaysData[line].contactor; + // } + + // if (line == 0) relayStatus = 0; + // if (type == "cmd-terminal") relayStatus = 1; + + // //check if rotary_switch_state == "Off" + // if (relayStatus == 0) { + // console.log("------------------------------------relayStatus", relayStatus, line); + // let values = { "status": "OFFLINE" }; + + // if(tbname) sendTelemetry(values, tbname) + + // interval = setInterval(runTasks, SHORT_INTERVAL); + // return; + // } + + if (!rsPort.isOpen) { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + //RE-CALCULATE VALUES + //set actual time for broadcast + if (register == 87 && params.recipient === 2) { + var d = new Date(); + params.byte1 = d.getHours();//h + params.byte2 = d.getMinutes();//m + params.byte3 = 0;//s + params.byte4 = 0; + } + + //SET DUSK/DAWN FOR BROADCAST + //Time of dusk + if (register == 6 && params.recipient === 2) { + + if (type != "cmd-terminal") { + let sunCalcResult = calculateDuskDawn(); + params.byte1 = sunCalcResult["dusk_hours"];//h + params.byte2 = sunCalcResult["dusk_minutes"];//m + params.byte3 = 0;//s + params.byte4 = 0; + + //TODO astrohodiny + let dusk = "Time of dusk: " + sunCalcResult["dusk"]; + } + } + + //Time of dawn + if (register == 7 && params.recipient === 2) { + if (type != "cmd-terminal") { + let sunCalcResult = calculateDuskDawn(); + params.byte1 = sunCalcResult["dawn_hours"];//h + params.byte2 = sunCalcResult["dawn_minutes"];//m + params.byte3 = 0;//s + params.byte4 = 0; + + //TODO astrohodiny + let dawn = "Time of dawn: " + sunCalcResult["dawn"]; + } + + } + //----------------------- + + instance.send(SEND_TO.debug, "address: " + node + " register:" + register + "type: " + 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(node, params.recipient, params.rw, register, params.name, params.byte1, params.byte2, params.byte3, params.byte4); + let readBytes = 11; + let timeout = 4000; + + // await keyword is important, otherwise incorrect data is returned! + 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); + + //ak sa odpoved zacina 0 - je to v poriadku, inak je NOK + let message = result.message; // OK, NOK + let message_type = result.type; + let error = result.error; + + if (params.debug != "generated cmd") { + //debug("writeData: done " + message_type + " duration: " + timeDiff + " message_type: " + params.debug, params); + } + + // 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); + // } + // } + + //debug("writeData: done " + message_type + " duration: " + timeDiff + " message_type: " + params.debug); + //debug("writeData done", message_type, "duration", timeDiff, "message_type", params.debug, result); + + let values = {}; + + //CMD FINISHED + if (message == "OK") { + + updateNodeStatus(node, true); + + //write + if (type == "set_node_profile") { + let result = cmdCounterResolve(node); + if (result == 0) { + dbNodes.modify({ processed: true }).where("node", node).make(function(builder) { + builder.callback(function(err, response) { + + sendNotification("CMD Manager: process cmd", SETTINGS.rvoTbName, "dimming_profile_was_successfully_received_by_node", { node: node }, "", SEND_TO.tb, instance); + + logger.debug("--> profil úspešne odoslaný na node č. " + node); + nodesData[node].processed = true; + nodeProfileSendFail.delete(node); + }); + }); + } + } + + //parse read response + if (params.rw == 0) { + values = processResponse(register, dataBytes); //read + } + + if (itIsNodeCommand) { + values.comm_status = "OK"; + values.status = "OK"; + } + + //master node + if (node == 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; + } + + //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.debug) { + //logger.debug("saveToTb", saveToTb, tbname, values); + } + + if (saveToTb) { + sendTelemetry(values, tbname) + } + else { + if (type == "cmd-terminal") { + terminalCommandResponse(params, "SUCCESS", data); + } + } + + } + else { + + terminalCommandResponse(params, "ERROR", data) + handleNokResponseOnRsPort("handleNOK else block", params, itIsNodeCommand, saveToTb); + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + //logger.debug("writeData err: ", error, result, params); + logger.debug("writeData err: ", tbname, node, register, values); + } + } + + //logger.debug(error, result, params); + } + }).catch(function(reason) { + + console.log("writeData catch exception", reason); + instance.send(SEND_TO.debug, reason); + + terminalCommandResponse(params, "FAILURE", null, reason); + handleNokResponseOnRsPort("handleNOK catch block", params, itIsNodeCommand, saveToTb); + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + logger.debug("-->WRITE FAILED: " + reason, params.debug, params); + } + } + + }); + + } + 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); + } + + + function handleNokResponseOnRsPort(message, params, itIsNodeCommand, saveToTb) { + + let node = params.address; + let register = params.register; + let type = params.type; + let tbName = params.tbname; + if (!tbName) return; + + let values = {}; + + // console.log(message); + let updateStatus = updateNodeStatus(node, false); + + //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; + + if (register == 4) values["master_node_version"] = "NOK"; + } + + if (type == "set_node_profile") { + delete cmdCounter[node]; + logger.debug("profil nebol úspešne odoslaný na node č. ", params); + + if (!nodeProfileSendFail.has(node)) { + sendNotification("CMD Manager: process cmd", tbName, "configuration_of_dimming_profile_to_node_failed", { node: node }, "", SEND_TO.tb, instance); + nodeProfileSendFail.add(node); + } + } + + if (itIsNodeCommand) { + values.comm_status = "NOK"; + } + + 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); + }); + }); + + 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); + + instance.send(SEND_TO.debug, err.message); + }); + + rsPort.on("close", () => { + setTimeout(() => rsPort.open(), 1000); + }); + + 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.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(); + return; + } + else if (flowdata.data == "close") { + rsPort.close(); + return; + } + else if (flowdata.data == "clean") { + tasks = []; + return; + } + else if (flowdata.data == "buildtasks") { + //build & run + return; + } + else if (flowdata.data == "run") { + //durations = []; + + if (tasks.length == 0) { + + buildTasks(); + + if (rsPort.isOpen) { + interval = setInterval(runTasks, 100); + } + else { + instance.send(SEND_TO.debug, "port is not opened!!!"); + } + } + } + else { + //terminal data - object + //logger.debug("flowdata", flowdata.data); + + if (typeof flowdata.data === 'object') { + //logger.debug("dido", flowdata.data); + if (flowdata.data.hasOwnProperty("sender")) { + //data from dido_controller + if (flowdata.data.sender == "dido_controller") { + + if (flowdata.data.hasOwnProperty("cmd")) { + let cmd = flowdata.data.cmd; + + if (cmd == "buildTasks") { + clearInterval(interval); + + logger.debug("-->CMD MANAGER - BUILD TASKS"); + buildTasks(); + + //logger.debug("tasks:"); + //logger.debug(tasks); + + logger.debug("-->CMD MANAGER - RUN TASKS"); + interval = setInterval(runTasks, LONG_INTERVAL); + } + else if (cmd == "reload_relays") { + loadRelaysData(flowdata.data.line); + + if (flowdata.data.dataChanged) { + if (!flowdata.data.value) { + reportOfflineNodeStatus(flowdata.data.line); + } + else { + reportOnlineNodeStatus(flowdata.data.line); + } + } + + } + else if (cmd == "rotary_switch_state") { + let value = flowdata.data.value; + + //state was changed + if (rotary_switch_state != value) { + if (value == "Off") { + //vyreportovat vsetky svietdla + reportOfflineNodeStatus(); + } + + rotary_switch_state = value; + } + } + 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) { + + // we send lux_sensor value to all nodes: + let params = getParams(PRIORITY_TYPES.node_broadcast); + + params.recipient = 2;//2 broadcast, address = 0 + params.address = 0xffffffff;//Broadcast + + let ba = longToByteArray(lux_sensor); + + params.byte3 = ba[1];//msb + params.byte4 = ba[0]; + params.timestamp = PRIORITY_TYPES.node_broadcast; + params.info = "run broadcast: Actual Lux level from cabinet"; + params.register = 95;//Actual Lux level from cabinet + params.rw = 1;//write + + tasks.push(params); + + //process profiles + turnOnOffLinesAccordingToLuxSensor(lux_sensor); + } + } + else if (cmd == "state_of_breaker") { + //istic linie + let value = flowdata.data.value; + let line = parseInt(flowdata.data.line); + + let dataChanged = false; + if (state_of_breaker[line] != value) dataChanged = true; + + state_of_breaker[line] = value; + + let status = "OK"; + if (value == "Off") status = "NOK"; + + if (dataChanged) { + + 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"); + + //report status liniu + sendTelemetry({ status: status }, tbname) + + //current value + if (value == "Off") reportOfflineNodeStatus(line); //vyreportovat vsetky svietidla na linii + } + + } + } + else { + logger.debug("undefined cmd", cmd); + } + } + } + + return; + } + + //data from worksys + 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 command = data.params.command; + let method = data.method; + let profile = data.params.payload; + if (profile == undefined) profile = ""; + let entity = data.params.entities[0]; + let entity_type = entity.entity_type; + let tbname = entity.tb_name; + + instance.send(SEND_TO.debug, flowdata.data); + 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") { + + //let command = data.params.command; + let value = data.params.payload.value; + + if (command == "dimming") { + + let nodeWasFound = false; + let keys = Object.keys(nodesData); + + //logger.debug("-----", keys); + + 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); + + 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; + + //ak linia je + + //debug(params); + logger.debug("dimming", params); + + tasks.push(params); + + 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); + + 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); + } + + //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; + + tasks.push(params); + } + + //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; + + tasks.push(params); + } + + //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; + + tasks.push(params); + } + + }, 4000); + + + nodeWasFound = true; + + break; + } + } + + if (!nodeWasFound) { + logger.debug("set dimming from platform", "unable to find tbname", tbname); + } + } + else { + instance.send(SEND_TO.debug, "undefined command " + command); + logger.debug("undefined command", command); + } + + return; + } + 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++) { + let node = keys[i]; + if (tbname == nodesData[node].tbname) { + + 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"); + + //profil úspešne prijatý pre node č. xx + 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; + + processNodeProfile(node); + }); + }); + } + } + } + else { + + instance.send(SEND_TO.debug, "unknown method " + method); + logger.debug("unknown method", method); + + return; + } + } + + //nastav profil linie z platformy + 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") { + + 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++) { + let line = keys[i]; + if (tbname == relaysData[line].tbname) { + //zmazeme tasky + 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) { + + //update profile + 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); + + }); + }); + break; + } + } + } + else if (method == "set_command") { + let value = data.params.payload.value; + + 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; + + 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"); + } + } + else { + instance.send(SEND_TO.debug, "undefined method " + method); + logger.debug("undefined method", method); + } + + return; + } + else { + instance.send(SEND_TO.debug, "UNKNOW entity_type " + entity_type); + logger.debug("UNKNOW entity_type", entity_type); + } + return; + } + + //terminal + if (!rsPort.isOpen) await rsPort.open(); + + let params = flowdata.data.body; + if (params == undefined) { + //logger.debug("CMD manager flowdata.data.body is undefined"); + return; + } + + params.priority = PRIORITY_TYPES.terminal; + params.type = "cmd-terminal"; + params.tbname = ""; + params.timestamp = PRIORITY_TYPES.terminal; + params.addMinutesToTimestamp = 0;// do not repeat task!!! + params.debug = true; + + let timestamp = Date.now(); + params.refFlowdataKey = timestamp; + //params.refFlowdata = flowdata; + //refFlowdata = flowdata; + + //console.log("flowdata", flowdata); + + cleanUpRefFlowdataObj(); + + refFlowdataObj[timestamp] = flowdata; + + //fix + //params.address = params.adress; + logger.debug("received from terminal", params); + logger.debug("date/time:", new Date()); + logger.debug("tasks length:", tasks.length); + + //tasks = []; + + //add to tasks + tasks.push(params); + + } + } + }) + + + //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) + } + + + /** + * 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; + + RESTBuilder.make(function(builder) { + + if (!builder) return; + + builder.method('GET'); + builder.url('http://192.168.252.2:8004/gettime?projects_id=1'); + + builder.callback(function(err, response, output) { + + 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); + } + + }); + } + + } 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); + + } else { + //console.log("Read-only", stdout); + + 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]: [ + { + "ts": date, + "values": values + } + ] + } + + 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); + } + + //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); + } + } + + 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; + } + + //Dimming, CCT + if (register == 1) { + let brightness = 0; + let dimming = byte0; + if (dimming > 128) { + //dimming = -128; + brightness = dimming - 128; + } + + //cct + //Ak Byte3 == 1: CCT = (Byte2*256)+Byte1 + let cct; + if (byte3 == 1) cct = byte2 * 256 + byte1; + else cct = bytesToInt(bytes.slice(0, 3)); + + //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; + } + + 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, 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 + ")"; + } + + 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; + + } + + function getObjectByTbValue(object, tbname) { + return object[Object.keys(object).find(key => object[key].tbname === tbname)]; + } + + function isObject(item) { + return (typeof item === "object" && !Array.isArray(item) && item !== null); + } + +} // end of instance.export + diff --git a/RVO25/flow_15_1_2025/code.js b/RVO25/flow_15_1_2025/code.js new file mode 100755 index 0000000..63b31bf --- /dev/null +++ b/RVO25/flow_15_1_2025/code.js @@ -0,0 +1,90 @@ +exports.id = 'code'; +exports.title = 'Code'; +exports.group = 'Common'; +exports.color = '#656D78'; +exports.input = true; +exports.output = 1; +exports.author = 'Peter Širka'; +exports.icon = 'code'; +exports.version = '1.2.0'; +exports.options = { outputs: 1, code: 'send(0, value);', keepmessage: true }; + +exports.html = `
+
+
+
@(Number of outputs)
+
@(Minimum is 1)
+
+
+
@(Code)
+
@(Keep message instance)
+
+`; + +exports.readme = `# Code + +This component executes custom JavaScript code as it is and it doesn't contain any secure scope. + +\`\`\`javascript +// value {Object} contains received data +// send(outputIndex, newValue) sends a new value +// error(value) sends an error +// instance {Object} a current component instance +// flowdata {Object} a current flowdata +// repository {Object} a current repository of flowdata +// Example: + +// send() can be execute multiple times +send(0, value); +\`\`\``; + +exports.install = function(instance) { + + var fn; + + instance.on('data', function(response) { + if (fn) { + try { + fn(response.data, instance, response, instance.options, response.repository, require); + } catch (e) { + response.data = e; + instance.throw(response); + } + } + }); + + instance.reconfigure = function() { + try { + if (instance.options.code) { + instance.status(''); + var code = 'var send = function(index, value) { if (options.keepmessage) { flowdata.data = value; instance.send2(index, flowdata); } else instance.send2(index, value);}; var error = function(err) { instance.throw(err); }; ' + instance.options.code; + fn = new Function('value', 'instance', 'flowdata', 'options', 'repository', 'require', code); + } else { + instance.status('Not configured', 'red'); + fn = null; + } + } catch (e) { + fn = null; + instance.error('Code: ' + e.message); + } + }; + + instance.on('options', instance.reconfigure); + instance.reconfigure(); +}; \ No newline at end of file diff --git a/RVO25/flow_15_1_2025/comment.js b/RVO25/flow_15_1_2025/comment.js new file mode 100755 index 0000000..1e0cd13 --- /dev/null +++ b/RVO25/flow_15_1_2025/comment.js @@ -0,0 +1,11 @@ +exports.id = 'comment'; +exports.title = 'Comment'; +exports.group = 'Common'; +exports.color = '#704cff'; +exports.author = 'Martin Smola'; +exports.icon = 'comment'; +exports.traffic = false; +exports.version = '1.0.0'; +exports.readme = '# Comment'; + +exports.install = function() {}; diff --git a/RVO25/flow_15_1_2025/db_connector.js b/RVO25/flow_15_1_2025/db_connector.js new file mode 100755 index 0000000..65ee94b --- /dev/null +++ b/RVO25/flow_15_1_2025/db_connector.js @@ -0,0 +1,286 @@ +exports.id = 'db_connector'; +exports.title = 'DbConnector'; +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.html = `
+
+
+
DbConnector
+
+
+
`; + +exports.readme = `# read/write data to tables`; + +const instanceSendTo = { + debug: 0, + http_response: 1, +} + +const { promisifyBuilder, makeMapFromDbResult } = require('./helper/db_helper.js'); + +function extractWhereParams(params) +{ + let name = params[0]; + let operator = '='; + let value = params[1]; + + if(params.length == 3) + { + operator = params[1]; + value = params[2]; + } + + return {name: name, operator: operator, value: value}; +} + +exports.install = function(instance) { + + let refFlowdata = null;//holds reference to httprequest flowdata + + instance.on("close", () => { + + }) + + + instance.on("data", async function(flowdata) { + + let params = flowdata.data.body; + console.log("DbConnector", params); + + refFlowdata = flowdata; + + if(refFlowdata != undefined) + { + //make http response + let responseObj = {}; + responseObj["type"] = "SUCESS"; + + try{ + + let table = params.table; + let action = params.action; + + + if(params.data != undefined) + { + let className = params.data.className; + + if(className == "SqlQueryBuilder") + { + let type = params.data.type; + + console.log("SqlQueryBuilder---->", params.data); + + if(type == "SELECT") + { + let table = params.data.queryData.tables[0].table; + + const db = TABLE(table); + var builder = db.find(); + + let result = await promisifyBuilder(builder); + + let response = {}; + response["result"] = result; + response["success"] = true; + + responseObj["data"] = response; + + //console.log(responseObj); + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + } + + return; + } + } + + + console.log("db_connector---->", table, action); + + //actions: read, replace, insert, delete, update... + + if(action == "read") + { + const db = TABLE(params.table); + + //where builder.where('age', '<', 15); + //builder.where('id', 3403); + + var builder = db.find(); + + //https://docs.totaljs.com/latest/en.html#api~DatabaseBuilder~builder.where + if(params.hasOwnProperty("where")) + { + //optionalCan contain "=", "<=", "<", ">=", ">". + //Default value: '=' + + //1.["production_line", 1] + //2. ["or", ["production_line", 1], ["production_line", 2], "end"] + + if (Array.isArray(params.where)) { + + let multipleConditions = false; + + if(params.where[0] == "or") multipleConditions = true; + if (Array.isArray(params.where[0])) multipleConditions = true; + + if(multipleConditions) + { + + for(var i = 0; i < params.where.length; i++) + { + const item = params.where[i]; + + if(item === "or") builder.or(); + + if (Array.isArray(item)) + { + const { name, operator, value } = extractWhereParams(item); + builder.where(name, operator, value); + } + + if(item === "end") builder.end(); + + } + + } + else + { + const { name, operator, value } = extractWhereParams(params.where); + builder.where(name, operator, value); + } + + } + + /* + if(params.where.length >=2 ) + { + let name = params.where[0]; + let operator = '='; + let value = params.where[1]; + + if(params.where.length == 3) + { + operator = params.where[1]; + value = params.where[2]; + } + + builder.where(name, operator, value); + } + */ + } + + if(params.hasOwnProperty("between")) + { + builder.between(params.between[0], params.between[1], params.between[2]); + } + + let response = await promisifyBuilder(builder); + responseObj["data"] = response; + + //console.log(responseObj); + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + + return; + } + + if(action == "delete") + { + + } + + + if(action == "update") + { + //! data receiving from terminal (params) + // { + // hostname: 'localhost', + // table: 'settings', + // action: 'update', + // body: { + // rvo_name: 'terrrr', + // lang: 'en', + // temperature_adress: '28.427B45920702', + // latitude: 48.70826502, + // longitude: 17.28455203, + // mqtt_host: '192.168.252.4', + // mqtt_clientid: 'showroom_test_panel_led', + // mqtt_username: 'xmRd6RJxW53WZe4vMFLU', + // mqtt_port: 1883, + // maintanace_mode: false + // } + // } + const tableToModify = TABLE(params.table); + const newValues = params.body; + + tableToModify.modify(newValues).make(function(builder) { + + builder.callback(function(err, response) { + + if(!err) + { + responseObj["data"] = response; + responseObj["tableUpdated"] = true; + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + } + }); + }); + + } + + if(action == "replace") + { + //truncate table + const db = TABLE(params.table); + var builder = db.remove(); + db.clean(); + + //insert data + let data = params.data; + + for(let i = 0; i < data.length; i++) + { + //console.log(data[i]); + db.insert(data[i]); + } + + console.log("insert done"); + + let responseObj = {}; + responseObj["type"] = "SUCESS"; + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + + + } + + + + } catch (error) { + //console.log(error); + responseObj["type"] = "ERROR"; + responseObj["message"] = error; + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + } + } + }) +} + + diff --git a/RVO25/flow_15_1_2025/db_init.js b/RVO25/flow_15_1_2025/db_init.js new file mode 100755 index 0000000..ddd0aa0 --- /dev/null +++ b/RVO25/flow_15_1_2025/db_init.js @@ -0,0 +1,106 @@ +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 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 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.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 : "2025-01-09", //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"], + phases: responseSettings[0]["phases"], + cloud_topic: responseSettings[0]["cloud_topic"], + + //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/RVO25/flow_15_1_2025/debug.js b/RVO25/flow_15_1_2025/debug.js new file mode 100755 index 0000000..00cb259 --- /dev/null +++ b/RVO25/flow_15_1_2025/debug.js @@ -0,0 +1,100 @@ +exports.id = 'debug'; +exports.title = 'Debug'; +exports.author = 'Peter Širka'; +exports.color = '#967ADC'; +exports.click = true; +exports.input = true; +exports.icon = 'bug'; +exports.version = '2.0.4'; +exports.options = { enabled: true, repository: false, type: 'data' }; +exports.readme = `# Debug + +Prints data to the debug tab.`; + +exports.html = `
+
+
+
@(Output type)
+
@(Path to the property (leave empty to show the whole data object))
+
@(A group name)
+
@(Enabled)
+
+
+
`; + +exports.install = function(instance) { + + instance.on('data', function(response) { + if (instance.options.enabled) { + + var opt = instance.options; + var rep = response.repository; + var val = response.data; + var id = response.id; + + switch (instance.options.type){ + case 'both': + var data = {}; + data.repository = rep; + data.data = val instanceof Error ? { error: val.message, stack: val.stack } : val; + instance.debug(safeparse(opt.property ? U.get(data, opt.property) : data), undefined, opt.group, id); + break; + case 'repository': + instance.debug(safeparse(opt.property ? U.get(rep, opt.property) : rep), undefined, opt.group, id); + break; + case 'data': + default: + if (val instanceof Error) + instance.debug({ error: val.message, stack: val.stack }, undefined, opt.group, id); + else + instance.debug(safeparse(opt.property ? U.get(val, opt.property) : val), undefined, opt.group, id); + break; + } + } + }); + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + instance.save(); + }); + + instance.on('options', function() { + instance.custom.status(); + }); + + instance.custom.status = function() { + instance.status(instance.options.enabled ? 'Enabled' : 'Disabled'); + }; + + instance.custom.status(); + + function safeparse(o) { + + if (o instanceof Buffer) + return o; + + if (o === undefined) + return 'undefined'; + + if (o === null) + return 'null'; + + var cache = []; + var str = JSON.stringify(o, function(key, value) { + if (typeof value === 'object' && value !== null) { + if (cache.indexOf(value) !== -1) { + try { + return JSON.parse(JSON.stringify(value)); + } catch (error) { + return; + } + } + cache.push(value); + } + return value; + }); + cache = null; + return JSON.parse(str); + } +}; diff --git a/RVO25/flow_15_1_2025/designer.json b/RVO25/flow_15_1_2025/designer.json new file mode 100755 index 0000000..fbdda76 --- /dev/null +++ b/RVO25/flow_15_1_2025/designer.json @@ -0,0 +1,2846 @@ +{ + "tabs": [ + { + "name": "MAIN PUSH", + "linker": "main-push", + "id": "1612772287426", + "index": 0 + }, + { + "name": "CMD manager", + "linker": "cmd-manager", + "id": "1615551125555", + "index": 1 + }, + { + "name": "Devices", + "linker": "devices", + "id": "1611921777196", + "index": 2 + } + ], + "components": [ + { + "id": "1611951142547", + "component": "debug", + "tab": "1611921777196", + "name": "ERROR", + "x": 598, + "y": 60, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "color": "#DA4453", + "notes": "", + "options": { + "type": "data", + "repository": false, + "enabled": true + } + }, + { + "id": "1612776786008", + "component": "wsmqttpublish", + "tab": "1612772287426", + "name": "WS MQTT publish", + "x": 304.75, + "y": 237, + "connections": { + "0": [ + { + "index": "0", + "id": "1615551060773" + } + ], + "1": [ + { + "index": "0", + "id": "1618300858252" + }, + { + "index": "0", + "id": "1618558465485" + } + ], + "2": [ + { + "index": "0", + "id": "1618300863816" + }, + { + "index": "0", + "id": "1634303685503" + } + ], + "3": [ + { + "index": "0", + "id": "1731068754606" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Reconnecting", + "color": "yellow" + }, + "color": "#888600", + "notes": "", + "options": { + "username": "", + "clientid": "", + "port": "1883", + "host": "" + } + }, + { + "id": "1612778461252", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "tb-push", + "x": 86.75, + "y": 375, + "connections": { + "0": [ + { + "index": "0", + "id": "1612783322136" + }, + { + "index": "1", + "id": "1612776786008" + }, + { + "index": "0", + "id": "1731068754606" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "color": "#303E4D", + "notes": "", + "options": { + "wirename": "tb-push" + } + }, + { + "id": "1612783322136", + "component": "debug", + "tab": "1612772287426", + "name": "to TB", + "x": 306.75, + "y": 371, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "color": "#967ADC", + "notes": "", + "options": { + "type": "data", + "repository": false, + "enabled": true + } + }, + { + "id": "1615551060773", + "component": "debug", + "tab": "1612772287426", + "name": "errors from MQTT Broker", + "x": 650, + "y": 76, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "color": "#DA4453", + "notes": "", + "options": { + "type": "data", + "repository": false, + "enabled": true + } + }, + { + "id": "1615563373927", + "component": "debug", + "tab": "1615551125555", + "name": "Debug", + "x": 753, + "y": 150, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "color": "#DA4453", + "notes": "", + "options": { + "type": "data", + "repository": false, + "enabled": true + } + }, + { + "id": "1615566865233", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "tb-push", + "x": 761, + "y": 251, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "color": "#303E4D", + "notes": "", + "options": { + "wirename": "tb-push" + } + }, + { + "id": "1615798582262", + "component": "debug", + "tab": "1615551125555", + "name": "CMD_debug", + "x": 765, + "y": 350, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "color": "#967ADC", + "notes": "", + "options": { + "type": "data", + "repository": false, + "enabled": true + } + }, + { + "id": "1615802995322", + "component": "debug", + "tab": "1611921777196", + "name": "Debug", + "x": 595.8833312988281, + "y": 557.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Disabled", + "color": "gray" + }, + "color": "#967ADC", + "notes": "", + "options": { + "type": "data", + "repository": false, + "enabled": false + } + }, + { + "id": "1615809128443", + "component": "debug", + "tab": "1611921777196", + "name": "tempToTb", + "x": 598.8833312988281, + "y": 654.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "color": "#967ADC", + "notes": "", + "options": { + "type": "data", + "repository": false, + "enabled": true + } + }, + { + "id": "1615809595184", + "component": "virtualwireout", + "tab": "1611921777196", + "name": "tb-push", + "x": 594.8833312988281, + "y": 350.25, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "color": "#303E4D", + "notes": "", + "options": { + "wirename": "tb-push" + } + }, + { + "id": "1616165795916", + "component": "httproute", + "tab": "1615551125555", + "name": "POST /terminal", + "x": 114, + "y": 546, + "connections": { + "0": [ + { + "index": "0", + "id": "1684060205000" + }, + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Listening", + "color": "green" + }, + "color": "#5D9CEC", + "notes": "### Configuration\n\n- __POST /terminal__\n- flags: \n- maximum request data length: __5 kB__\n- empty response: __false__\n- cache policy: __no cache__\n- cache expire: __5 minutes__", + "cloning": false, + "options": { + "timeout": 10, + "cachepolicy": 0, + "cacheexpire": "5 minutes", + "size": 5, + "url": "/terminal", + "method": "POST", + "name": "", + "flags": [ + "id:1616165795916", + "post", + 10000 + ], + "emptyresponse": false + } + }, + { + "id": "1616165824813", + "component": "httpresponse", + "tab": "1615551125555", + "name": "HTTP Response", + "x": 772, + "y": 443, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "color": "#5D9CEC", + "notes": "", + "options": { + "datatype": "json" + } + }, + { + "id": "1617104731852", + "component": "debug", + "tab": "1615551125555", + "name": "DIDO_Debug", + "x": 669, + "y": 1040, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "color": "#967ADC", + "notes": "", + "options": { + "type": "data", + "repository": false, + "enabled": true + } + }, + { + "id": "1617114651703", + "component": "trigger", + "tab": "1615551125555", + "name": "turnOff line", + "x": 88, + "y": 1158, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "color": "#F6BB42", + "notes": "", + "options": { + "datatype": "object", + "data": "{line: 3, command: \"turnOff\", force: true}" + } + }, + { + "id": "1617115013095", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "tb-push", + "x": 669, + "y": 1150, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "color": "#303E4D", + "notes": "", + "options": { + "wirename": "tb-push" + } + }, + { + "id": "1617284749681", + "component": "trigger", + "tab": "1615551125555", + "name": "update profile / node", + "x": 112, + "y": 215, + "connections": { + "0": [ + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "color": "#F6BB42", + "notes": "", + "options": { + "data": "profile_nodes", + "datatype": "string" + } + }, + { + "id": "1618235171399", + "component": "trigger", + "tab": "1615551125555", + "name": "tun tasks", + "x": 119, + "y": 280, + "connections": { + "0": [ + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "color": "#F6BB42", + "notes": "", + "options": { + "data": "run" + } + }, + { + "id": "1618300858252", + "component": "debug", + "tab": "1612772287426", + "name": "wsmqtt-exit1", + "x": 650.8833312988281, + "y": 160, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "color": "#967ADC", + "notes": "", + "options": { + "type": "data", + "repository": false, + "enabled": true + } + }, + { + "id": "1618300863816", + "component": "debug", + "tab": "1612772287426", + "name": "wsmqtt-exit2", + "x": 845.8833312988281, + "y": 320, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "color": "#967ADC", + "notes": "", + "options": { + "type": "data", + "repository": false, + "enabled": true + } + }, + { + "id": "1618393583970", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "to-cmd-manager", + "x": 668.8833312988281, + "y": 1269, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "from-dido-controller", + "color": "gray" + }, + "color": "#303E4D", + "notes": "", + "options": { + "wirename": "from-dido-controller" + } + }, + { + "id": "1618393674428", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "platform-rpc-call", + "x": 119.88333129882812, + "y": 369, + "connections": { + "0": [ + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "platform-rpc-call", + "color": "gray" + }, + "color": "#303E4D", + "notes": "", + "options": { + "wirename": "platform-rpc-call" + } + }, + { + "id": "1618393759854", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "cmd_to_dido", + "x": 93.88333129882812, + "y": 1007, + "connections": { + "0": [ + { + "index": "0", + "id": "1683664161036" + }, + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "cmd_to_dido", + "color": "gray" + }, + "color": "#303E4D", + "notes": "", + "options": { + "wirename": "cmd_to_dido" + } + }, + { + "id": "1618393827655", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "cmd_to_dido", + "x": 779.8833312988281, + "y": 552, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "cmd_to_dido", + "color": "gray" + }, + "color": "#303E4D", + "notes": "", + "options": { + "wirename": "cmd_to_dido" + } + }, + { + "id": "1618558465485", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "platform-rpc-call", + "x": 649.8833312988281, + "y": 246, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "platform-rpc-call", + "color": "gray" + }, + "color": "#303E4D", + "notes": "", + "options": { + "wirename": "platform-rpc-call" + } + }, + { + "id": "1618572059773", + "component": "trigger", + "tab": "1615551125555", + "name": "turnOn line", + "x": 89, + "y": 1085, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "color": "#F6BB42", + "notes": "", + "options": { + "data": "{line: 1, command: \"turnOn\", force: true}", + "datatype": "object" + } + }, + { + "id": "1619515097737", + "component": "cmd_manager", + "tab": "1615551125555", + "name": "CMD Manager", + "x": 452.1091003417969, + "y": 341.05455017089844, + "connections": { + "0": [ + { + "index": "0", + "id": "1615563373927" + } + ], + "1": [ + { + "index": "0", + "id": "1615566865233" + }, + { + "index": "0", + "id": "1615798582262" + } + ], + "2": [ + { + "index": "0", + "id": "1616165824813" + } + ], + "3": [ + { + "index": "0", + "id": "1618393827655" + } + ], + "4": [ + { + "index": "0", + "id": "1635936391935" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "color": "#5D9CEC", + "notes": "", + "options": {} + }, + { + "id": "1619605019281", + "component": "httproute", + "tab": "1615551125555", + "name": "GET db", + "x": 115, + "y": 651, + "connections": { + "0": [ + { + "index": "0", + "id": "1684060205000" + }, + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Listening", + "color": "green" + }, + "color": "#5D9CEC", + "notes": "### Configuration\n\n- __GET /db__\n- flags: undefined\n- maximum request data length: __5 kB__\n- empty response: __undefined__\n- cache policy: __no cache__\n- cache expire: __5 minutes__", + "cloning": false, + "options": { + "timeout": 5, + "cachepolicy": 0, + "cacheexpire": "5 minutes", + "size": 5, + "url": "/db", + "method": "GET", + "name": "", + "flags": [ + "id:1619605019281", + "get", + 5000 + ] + } + }, + { + "id": "1619784672383", + "component": "trigger", + "tab": "1615551125555", + "name": "turnOnAlarm", + "x": 85, + "y": 1231, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "color": "#F6BB42", + "notes": "", + "options": { + "datatype": "object", + "data": "{command: \"turnOnAlarm\"}" + } + }, + { + "id": "1619784812964", + "component": "trigger", + "tab": "1615551125555", + "name": "turnOffAlarm", + "x": 84, + "y": 1304, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "color": "#F6BB42", + "notes": "", + "options": { + "datatype": "object", + "data": "{command: \"turnOffAlarm\"}" + } + }, + { + "id": "1621340721628", + "component": "virtualwireout", + "tab": "1611921777196", + "name": "modbus_to_dido", + "x": 596, + "y": 462, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "modbus_to_dido", + "color": "gray" + }, + "color": "#303E4D", + "notes": "", + "options": { + "wirename": "modbus_to_dido" + } + }, + { + "id": "1622640022885", + "component": "httproute", + "tab": "1615551125555", + "name": "POST /db_connector", + "x": 98, + "y": 1586, + "connections": { + "0": [ + { + "index": "0", + "id": "1622640073521" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Listening", + "color": "green" + }, + "color": "#5D9CEC", + "notes": "### Configuration\n\n- __POST /db_connector__\n- flags: \n- maximum request data length: __5 kB__\n- empty response: __undefined__\n- cache policy: __no cache__\n- cache expire: __5 minutes__", + "cloning": false, + "options": { + "timeout": 5, + "cachepolicy": 0, + "cacheexpire": "5 minutes", + "size": 5, + "url": "/db_connector", + "method": "POST", + "flags": [ + "id:1622640022885", + "post", + 5000 + ] + } + }, + { + "id": "1622640073521", + "component": "db_connector", + "tab": "1615551125555", + "name": "DbConnector", + "x": 372, + "y": 1572, + "connections": { + "1": [ + { + "index": "0", + "id": "1622641420685" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "color": "#2134B0", + "notes": "", + "options": { + "edge": "undefined" + } + }, + { + "id": "1622641420685", + "component": "httpresponse", + "tab": "1615551125555", + "name": "HTTP Response", + "x": 596, + "y": 1586, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "color": "#5D9CEC", + "notes": "", + "options": {} + }, + { + "id": "1634303504177", + "component": "monitormemory", + "tab": "1612772287426", + "name": "RAM", + "x": 69.88333129882812, + "y": 885.5, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465281992" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "776.75 MB / 987.80 MB", + "color": "gray" + }, + "color": "#F6BB42", + "notes": "", + "options": { + "enabled": true, + "interval": 30000 + } + }, + { + "id": "1634303533779", + "component": "monitordisk", + "tab": "1612772287426", + "name": "disk", + "x": 70.88333129882812, + "y": 982.5, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465821120" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "5.79 GB / 7.26 GB", + "color": "gray" + }, + "color": "#F6BB42", + "notes": "", + "options": { + "enabled": true, + "path": "/", + "interval": 30000 + } + }, + { + "id": "1634303595494", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "send-to-services", + "x": 51.883331298828125, + "y": 1400.5, + "connections": { + "0": [ + { + "index": "0", + "id": "1634463186563" + }, + { + "index": "1", + "id": "1634488120710" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "color": "#303E4D", + "notes": "", + "options": { + "wirename": "send-to-services" + } + }, + { + "id": "1634303602169", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "send-to-services", + "x": 426.8833312988281, + "y": 878.5, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "color": "#303E4D", + "notes": "", + "options": { + "wirename": "send-to-services" + } + }, + { + "id": "1634303685503", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "send-to-services", + "x": 650.8833312988281, + "y": 355.5, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "color": "#303E4D", + "notes": "", + "options": { + "wirename": "send-to-services" + } + }, + { + "id": "1634303743260", + "component": "httprequest", + "tab": "1612772287426", + "name": "192.168.252.2:8004/sentmessage", + "reference": "", + "x": 480.8833312988281, + "y": 1334.7333374023438, + "connections": { + "0": [ + { + "index": "0", + "id": "1635327431236" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "color": "#5D9CEC", + "notes": "", + "options": { + "url": "http://192.168.252.2:8004/sentmessage", + "method": "POST", + "stringify": "json" + } + }, + { + "id": "1634463186563", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 280.75, + "y": 1446, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "color": "#967ADC", + "notes": "", + "options": { + "type": "data", + "repository": false, + "enabled": true + } + }, + { + "id": "1634464580289", + "component": "code", + "tab": "1612772287426", + "name": "Code", + "x": 253, + "y": 788, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465243324" + }, + { + "index": "0", + "id": "1634303602169" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "color": "#656D78", + "notes": "", + "options": { + "keepmessage": true, + "code": "let response = {};\nresponse.cpu = value.cpu;\nresponse.uptime = value.uptime;\n\nsend(0, response);", + "outputs": 1 + } + }, + { + "id": "1634465243324", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 428, + "y": 784, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "color": "#967ADC", + "notes": "", + "options": { + "type": "data", + "repository": false, + "enabled": true + } + }, + { + "id": "1634465281992", + "component": "code", + "tab": "1612772287426", + "name": "Code", + "x": 242, + "y": 884, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465338103" + }, + { + "index": "0", + "id": "1634303602169" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "color": "#656D78", + "notes": "", + "options": { + "keepmessage": true, + "code": "value.sender = \"ram\";\n//let total = value.total/1024/1024;\n//let free = value.free/1024/1024;\n//let used = value.used/1024/1024;\nlet response = {};\n//value.memory_total = (total).toFixed(0) + ' MB';\n//value.memory_free = (free).toFixed(0) + ' MB';\n//value.memory_used = (used).toFixed(0) + ' MB';\n\nresponse.memory_total = value.total;\nresponse.memory_free = value.free;\nresponse.memory_used = value.used;\n\nsend(0, response);", + "outputs": 1 + } + }, + { + "id": "1634465338103", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 429, + "y": 976, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "color": "#967ADC", + "notes": "", + "options": { + "type": "data", + "repository": false, + "enabled": true + } + }, + { + "id": "1634465821120", + "component": "code", + "tab": "1612772287426", + "name": "Code", + "x": 245, + "y": 978, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465892500" + }, + { + "index": "0", + "id": "1634303602169" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "color": "#656D78", + "notes": "", + "options": { + "keepmessage": true, + "code": "value.sender = \"hdd\";\n//let total = value.total/1024/1024;\n//let free = value.free/1024/1024;\n//let used = value.used/1024/1024;\nlet response = {};\n//value.hdd_total = (total).toFixed(0) + ' MB';\n//value.hdd_free = (free).toFixed(0) + ' MB';\n//value.used = (used).toFixed(0) + ' MB';\n\nresponse.hdd_total = value.total;\nresponse.hdd_free = value.free;\nresponse.hdd_used = value.used;\n\nsend(0, response);", + "outputs": 1 + } + }, + { + "id": "1634465892500", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 432, + "y": 1068, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "color": "#967ADC", + "notes": "", + "options": { + "type": "data", + "repository": false, + "enabled": true + } + }, + { + "id": "1634484067516", + "component": "debug", + "tab": "1612772287426", + "name": "Send info", + "x": 480, + "y": 1441, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "color": "#967ADC", + "notes": "", + "options": { + "type": "data", + "repository": false, + "enabled": true + } + }, + { + "id": "1634488120710", + "component": "infosender", + "tab": "1612772287426", + "name": "Info sender", + "x": 285, + "y": 1338, + "connections": { + "0": [ + { + "index": "0", + "id": "1634484067516" + }, + { + "index": "0", + "id": "1634303743260" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "color": "#2134B0", + "notes": "", + "options": { + "edge": "undefined" + } + }, + { + "id": "1635327431236", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 795.8833312988281, + "y": 1329.5, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "color": "#967ADC", + "notes": "", + "options": { + "type": "data", + "repository": false, + "enabled": true + } + }, + { + "id": "1635936391935", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "send-to-services", + "x": 778, + "y": 656, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "color": "#303E4D", + "notes": "", + "options": { + "wirename": "send-to-services" + } + }, + { + "id": "1637069803394", + "component": "monitorconsumption", + "tab": "1612772287426", + "name": "CPU", + "x": 69, + "y": 791, + "connections": { + "0": [ + { + "index": "0", + "id": "1634464580289" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "1.5% / 72.32 MB", + "color": "gray" + }, + "color": "#967ADC", + "notes": "", + "options": { + "monitorfiles": true, + "monitorconnections": true, + "monitorsize": true, + "monitorconsumption": true, + "enabled": true, + "interval": 30000 + } + }, + { + "id": "1683664161036", + "component": "debug", + "tab": "1615551125555", + "name": "CMDtoDIDO", + "x": 392, + "y": 1012, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "color": "#967ADC", + "notes": "", + "options": { + "type": "data", + "repository": false, + "enabled": true + } + }, + { + "id": "1683981346282", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "from-dido-controller", + "x": 113, + "y": 456, + "connections": { + "0": [ + { + "index": "0", + "id": "1684055037116" + }, + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "from-dido-controller", + "color": "gray" + }, + "color": "#303E4D", + "notes": "", + "options": { + "wirename": "from-dido-controller" + } + }, + { + "id": "1684055037116", + "component": "debug", + "tab": "1615551125555", + "name": "from dido to cmd", + "x": 448, + "y": 519, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "color": "#967ADC", + "notes": "", + "options": { + "type": "data", + "repository": false, + "enabled": true + } + }, + { + "id": "1684060205000", + "component": "debug", + "tab": "1615551125555", + "name": "HTTP routes", + "x": 447, + "y": 620, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "color": "#967ADC", + "notes": "", + "options": { + "type": "data", + "repository": false, + "enabled": true + } + }, + { + "id": "1684179110403", + "component": "debug", + "tab": "1611921777196", + "name": "MDBToDido", + "x": 598, + "y": 147, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "color": "#967ADC", + "notes": "", + "options": { + "type": "data", + "repository": false, + "enabled": true + } + }, + { + "id": "1699963668903", + "component": "dido_controller", + "tab": "1615551125555", + "name": "DIDO_Controller", + "x": 397, + "y": 1131, + "connections": { + "0": [ + { + "index": "0", + "id": "1617104731852" + } + ], + "1": [ + { + "index": "0", + "id": "1617104731852" + }, + { + "index": "0", + "id": "1617115013095" + } + ], + "2": [ + { + "index": "0", + "id": "1618393583970" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "color": "#2134B0", + "notes": "", + "options": { + "edge": "undefined" + } + }, + { + "id": "1699964678894", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "modbus_to_dido", + "x": 96, + "y": 924, + "connections": { + "0": [ + { + "index": "0", + "id": "1699963668903" + }, + { + "index": "0", + "id": "1699964793925" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "modbus_to_dido", + "color": "gray" + }, + "color": "#303E4D", + "notes": "", + "options": { + "wirename": "modbus_to_dido" + } + }, + { + "id": "1699964793925", + "component": "debug", + "tab": "1615551125555", + "name": "modbusToDido", + "x": 388, + "y": 920, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "color": "#967ADC", + "notes": "", + "options": { + "type": "data", + "repository": false, + "enabled": true + } + }, + { + "id": "1699965957410", + "component": "modbus_reader", + "tab": "1611921777196", + "name": "Modbus reader", + "x": 232, + "y": 175, + "connections": { + "0": [ + { + "index": "0", + "id": "1611951142547" + } + ], + "1": [ + { + "index": "0", + "id": "1621340721628" + }, + { + "index": "0", + "id": "1684179110403" + }, + { + "index": "0", + "id": "1717441414646" + } + ], + "2": [ + { + "index": "0", + "id": "1615809595184" + }, + { + "index": "0", + "id": "1714752862828" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "color": "#2134B0", + "notes": "", + "options": {} + }, + { + "id": "1700411878636", + "component": "thermometer", + "tab": "1611921777196", + "name": "Thermometer", + "x": 234.75, + "y": 444, + "connections": { + "0": [ + { + "index": "0", + "id": "1615802995322" + } + ], + "1": [ + { + "index": "0", + "id": "1615809595184" + }, + { + "index": "0", + "id": "1615809128443" + } + ], + "2": [ + { + "index": "0", + "id": "1621340721628" + }, + { + "index": "0", + "id": "1732889185927" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "color": "#5CB36D", + "notes": "", + "options": {} + }, + { + "id": "1714752862828", + "component": "debug", + "tab": "1611921777196", + "name": "MDBToTb", + "x": 599, + "y": 257, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "color": "#967ADC", + "notes": "", + "options": { + "type": "data", + "repository": false, + "enabled": true + } + }, + { + "id": "1717441414646", + "component": "code", + "tab": "1611921777196", + "name": "device-status", + "x": 755.0833282470703, + "y": 209, + "connections": { + "0": [ + { + "index": "0", + "id": "1717442627834" + }, + { + "index": "0", + "id": "1717442631338" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "color": "#656D78", + "notes": "", + "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 + } + }, + { + "id": "1717442627834", + "component": "debug", + "tab": "1611921777196", + "name": "modbus service", + "x": 966.0833282470703, + "y": 152, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "color": "#967ADC", + "notes": "", + "options": { + "type": "data", + "repository": false, + "enabled": true + } + }, + { + "id": "1717442631338", + "component": "virtualwireout", + "tab": "1611921777196", + "name": "send-to-services", + "x": 968.0833282470703, + "y": 268, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "color": "#303E4D", + "notes": "", + "options": { + "wirename": "send-to-services" + } + }, + { + "id": "1718016045116", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "tb-push", + "x": 77.75, + "y": 1630, + "connections": { + "0": [ + { + "index": "0", + "id": "1718016052341" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "color": "#303E4D", + "notes": "", + "options": { + "wirename": "tb-push" + } + }, + { + "id": "1718016052341", + "component": "slack_filter", + "tab": "1612772287426", + "name": "Slack Filter", + "x": 296, + "y": 1671, + "connections": { + "0": [ + { + "index": "0", + "id": "1718016086212" + }, + { + "index": "0", + "id": "1718016073501" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Running", + "color": "gray" + }, + "color": "#30E193", + "notes": "", + "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\", \"Node db has changed\"]", + "types": "[\"emergency\", \"critical\", \"error\", \"alert\"]", + "name": "al_shariff_10.0.0.38" + } + }, + { + "id": "1718016073501", + "component": "httprequest", + "tab": "1612772287426", + "name": "http://192.168.252.2:8004/slack", + "x": 495, + "y": 1753, + "connections": { + "0": [ + { + "index": "0", + "id": "1718016086212" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "color": "#5D9CEC", + "notes": "", + "options": { + "url": "http://192.168.252.2:8004/slack", + "method": "POST", + "stringify": "json" + } + }, + { + "id": "1718016086212", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 832, + "y": 1664, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "color": "#967ADC", + "notes": "", + "options": { + "type": "data", + "repository": false, + "enabled": true + } + }, + { + "id": "1718016094070", + "component": "trigger", + "tab": "1612772287426", + "name": "Trigger", + "x": 79, + "y": 1723, + "connections": { + "0": [ + { + "index": "0", + "id": "1718016052341" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "color": "#F6BB42", + "notes": "", + "options": { + "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\": \"\" } } } ] }", + "datatype": "object" + } + }, + { + "id": "1729855334955", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "platform-rpc-call", + "x": 649.9333343505859, + "y": 541.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "platform-rpc-call", + "color": "gray" + }, + "color": "#303E4D", + "notes": "", + "options": { + "wirename": "platform-rpc-call" + } + }, + { + "id": "1729855371093", + "component": "debug", + "tab": "1612772287426", + "name": "rpc cloud", + "x": 650.9333343505859, + "y": 451.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "color": "#967ADC", + "notes": "", + "options": { + "type": "data", + "repository": false, + "enabled": true + } + }, + { + "id": "1731068658334", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 90.75, + "y": 250, + "connections": { + "0": [ + { + "index": "0", + "id": "1612776786008" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "color": "#303E4D", + "notes": "", + "options": { + "wirename": "db-init" + } + }, + { + "id": "1731068754606", + "component": "cloudmqttconnect", + "tab": "1612772287426", + "name": "MQTT client - to senica-prod01", + "x": 304.75, + "y": 474, + "connections": { + "1": [ + { + "index": "0", + "id": "1729855371093" + }, + { + "index": "0", + "id": "1729855334955" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Reconnecting", + "color": "yellow" + }, + "color": "#888600", + "notes": "", + "options": { + "username": "", + "clientid": "", + "port": "2764", + "host": "192.168.252.2", + "topic": "" + } + }, + { + "id": "1731069001548", + "component": "db_init", + "tab": "1612772287426", + "name": "DB Initialization", + "x": 91.75, + "y": 55.25, + "connections": { + "0": [ + { + "index": "0", + "id": "1731069033416" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "color": "#888600", + "notes": "", + "options": {} + }, + { + "id": "1731069033416", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "db-init", + "x": 343.75, + "y": 50.25, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "color": "#303E4D", + "notes": "", + "options": { + "wirename": "db-init" + } + }, + { + "id": "1731069059135", + "component": "showdb", + "tab": "1612772287426", + "name": "Show db data", + "x": 1121.75, + "y": 814.25, + "connections": { + "0": [ + { + "index": "0", + "id": "1731069079243" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "color": "#888600", + "notes": "", + "options": {} + }, + { + "id": "1731069079243", + "component": "debug", + "tab": "1612772287426", + "name": "dbData", + "x": 1315.75, + "y": 853.25, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "color": "#967ADC", + "notes": "", + "options": { + "type": "data", + "repository": false, + "enabled": true + } + }, + { + "id": "1731069116691", + "component": "trigger", + "tab": "1612772287426", + "name": "settings", + "x": 911.75, + "y": 710.75, + "connections": { + "0": [ + { + "index": "0", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "color": "#F6BB42", + "notes": "", + "options": {} + }, + { + "id": "1731069131637", + "component": "trigger", + "tab": "1612772287426", + "name": "relaysData", + "x": 832.75, + "y": 775.75, + "connections": { + "0": [ + { + "index": "1", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "color": "#F6BB42", + "notes": "", + "options": {} + }, + { + "id": "1731069137374", + "component": "trigger", + "tab": "1612772287426", + "name": "nodesData", + "x": 747.75, + "y": 840.75, + "connections": { + "0": [ + { + "index": "2", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "color": "#F6BB42", + "notes": "", + "options": {} + }, + { + "id": "1731069179846", + "component": "trigger", + "tab": "1612772287426", + "name": "pinsData", + "x": 803.75, + "y": 899.75, + "connections": { + "0": [ + { + "index": "3", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "color": "#F6BB42", + "notes": "", + "options": {} + }, + { + "id": "1731069192937", + "component": "trigger", + "tab": "1612772287426", + "name": "sample data", + "x": 858.75, + "y": 959.75, + "connections": { + "0": [ + { + "index": "4", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "color": "#F6BB42", + "notes": "", + "options": {} + }, + { + "id": "1731069264443", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 63.75, + "y": 1279, + "connections": { + "0": [ + { + "index": "0", + "id": "1634488120710" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "color": "#303E4D", + "notes": "", + "options": { + "wirename": "db-init" + } + }, + { + "id": "1731069334626", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "db-init", + "x": 151.88333129882812, + "y": 148, + "connections": { + "0": [ + { + "index": "0", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "color": "#303E4D", + "notes": "", + "options": { + "wirename": "db-init" + } + }, + { + "id": "1731069548145", + "component": "virtualwirein", + "tab": "1611921777196", + "name": "db-init", + "x": 46.75, + "y": 192, + "connections": { + "0": [ + { + "index": "0", + "id": "1699965957410" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "color": "#303E4D", + "notes": "", + "options": { + "wirename": "db-init" + } + }, + { + "id": "1731069567152", + "component": "virtualwirein", + "tab": "1611921777196", + "name": "db-init", + "x": 44.75, + "y": 465, + "connections": { + "0": [ + { + "index": "0", + "id": "1700411878636" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "color": "#303E4D", + "notes": "", + "options": { + "wirename": "db-init" + } + }, + { + "id": "1731070156936", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "db-init", + "x": 89.88333129882812, + "y": 1381, + "connections": { + "0": [ + { + "index": "2", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "color": "#303E4D", + "notes": "", + "options": { + "wirename": "db-init" + } + }, + { + "id": "1731234189516", + "component": "trigger", + "tab": "1612772287426", + "name": "monitor.txt", + "x": 915.75, + "y": 1017.75, + "connections": { + "0": [ + { + "index": "5", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "color": "#F6BB42", + "notes": "", + "options": {} + }, + { + "id": "1731234189551", + "component": "trigger", + "tab": "1612772287426", + "name": "err.txt", + "x": 966.75, + "y": 1080.75, + "connections": { + "0": [ + { + "index": "6", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "color": "#F6BB42", + "notes": "", + "options": {} + }, + { + "id": "1732700042559", + "component": "nodesdb_change_check", + "tab": "1612772287426", + "name": "Nodes DB change check", + "x": 263.8833312988281, + "y": 1993.2333984375, + "connections": { + "0": [ + { + "index": "0", + "id": "1732700071298" + }, + { + "index": "0", + "id": "1732700642917" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "color": "#888600", + "notes": "", + "options": {} + }, + { + "id": "1732700057052", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 84.75, + "y": 1994, + "connections": { + "0": [ + { + "index": "0", + "id": "1732700042559" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "color": "#303E4D", + "notes": "", + "options": { + "wirename": "db-init" + } + }, + { + "id": "1732700071298", + "component": "debug", + "tab": "1612772287426", + "name": "nodesChange", + "x": 561.8833312988281, + "y": 2055.2333984375, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "color": "#967ADC", + "notes": "", + "options": { + "type": "data", + "repository": false, + "enabled": true + } + }, + { + "id": "1732700642917", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "tb-push", + "x": 557.8833312988281, + "y": 1949, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "color": "#303E4D", + "notes": "", + "options": { + "wirename": "tb-push" + } + }, + { + "id": "1732889185927", + "component": "debug", + "tab": "1611921777196", + "name": "tempToDido", + "x": 594.8833312988281, + "y": 745, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "color": "#967ADC", + "notes": "", + "options": { + "type": "data", + "repository": false, + "enabled": true + } + }, + { + "id": "1733574412965", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 86.75, + "y": 495, + "connections": { + "0": [ + { + "index": "1", + "id": "1731068754606" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "color": "#303E4D", + "notes": "", + "options": { + "wirename": "db-init" + } + } + ], + "version": 618 +} diff --git a/RVO25/flow_15_1_2025/dido_controller.js b/RVO25/flow_15_1_2025/dido_controller.js new file mode 100755 index 0000000..8415921 --- /dev/null +++ b/RVO25/flow_15_1_2025/dido_controller.js @@ -0,0 +1,1524 @@ +exports.id = 'dido_controller'; +exports.title = 'DIDO_Controller'; +exports.version = '2.0.0'; +exports.group = 'Worksys'; +exports.color = '#2134B0'; +exports.input = 3; +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 { 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 +} + + +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 = {}; + 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"); + + //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 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 + }; + + + function main() { + + GLOBALS = FLOW.GLOBALS; + SETTINGS = FLOW.GLOBALS.settings; + rvoTbName = SETTINGS.rvoTbName; + pinsData = GLOBALS.pinsData; + relaysData = GLOBALS.relaysData; + + 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"; + + 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, "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; + turnLine("off", 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; + + sendTelemetry(values, rvoTbName); + + 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) { + if (!err) { + monitor.info(exports.title + "--->Digital in_out has been set (runSyncExec was sucessfull)"); + + turnAlarm("off"); + 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() { + + //to keep websocket opened, we send request every 150 seconds + let startRequests = null; + + console.log("handleWebSocket function called"); + ws = new WebSocket('ws:/0.0.0.0:1234/ws'); + + ws.onopen = function open() { + + instance.send(0, exports.title + " running"); + turnAlarm("off"); + + // useTurnOffCounter = true; + // turnOffCounter = relaysData.length - 1; + initialSetting(); + ws.send(JSON.stringify({ "cmd": "all" })); + + // we request dev info about neuron device from evok to keep websocket connection alive + // for some reason this request returns no data, but connection keeps alive + // https://evok.api-docs.io/1.0/mpqzDwPwirsoq7i5A/websocket + startRequests = setInterval(() => { + // console.log(" *** data from evok requested"); + ws.send(JSON.stringify({ "cmd": "filter", "dev": ["neuron"] })); + }, 150000) + }; + + + // 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 = async 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; + + 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) => { + monitor.info('websocket error, reconnect') + instance.send(SEND_TO.debug, err.message); + clearInterval(startRequests); + ws = null; + setTimeout(handleWebSocket, 1000); + }) + + + ws.onclose = function() { + // connection closed, discard old websocket and create a new one in 5s + // stopRequests(); + monitor.info('websocket onclose, reconnect') + clearInterval(startRequests); + ws = null; + console.log("ws is null now, reconnecting..."); + setTimeout(handleWebSocket, 1000); + } + } + + 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 turnAlarm(onOrOff) { + let value = 0; + if (onOrOff == "on") value = 1; + + if (value == 1 && SETTINGS.maintenance_mode) return; + + alarmStatus = "OFF"; + if (value == 1) alarmStatus = "ON"; + + if (rsPort) { + let arr = [0x55]; + arr.push(13); + arr.push(0); + arr.push(value); + + rsPort.write(Buffer.from(arr), function(err) { + logger.debug(`sirena - ${onOrOff}`); + }); + } + else if (ws) { + let cmd = { "cmd": "set", "dev": "relay", "circuit": "1_01", "value": value }; + ws.send(JSON.stringify(cmd)); + logger.debug(`sirena - ${onOrOff}`); + } + } + + + 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") { + bits.push(0); + } + else bits.push(1); + + if (deviceStatus["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); + } + + + // turn line on or off + function turnLine(onOrOff, line, pin, force, info) { + //onOrOff => "on" or "off" + let value = 0; + if (onOrOff == "on") value = 1; + + if (force == undefined) force = false; + + if (line == 0) { + if (value == 1 && alarmStatus == "ON") turnAlarm("off"); + SETTINGS.maintenance_mode = value ? true : false; + + 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); + return; + } + + if (pin === undefined) pin = getPin(line); + + if (pin === undefined) { + errLogger.error("pin is undefined!", line); + return; + } + + if (!force) { + if (relaysData[line].contactor == value) { + instance.send(SEND_TO.debug, `line is already ${onOrOff} ` + line); + logger.debug(`turnLine: line is already ${onOrOff} `, 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(value); + + rsPort.write(Buffer.from(arr), function(err) { + if (err === undefined) { + monitor.info(`turnLine ${onOrOff} zapisal do rsPort-u`, line, pin, arr, info); + switchLogic(arr); + } + else { + monitor.info(`turnLine ${onOrOff} 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 }; + ws.send(JSON.stringify(cmd)); + switchLogic(pin, value) + } + + //if rvo is 24/7, it has just one switching profile point at 13:00. we do not want to send notification as it repeats every day. + //const d = new Date(); + //if(d.getHours() != 13) sendNotification("Dido_controller: ", SETTINGS.rvoTbName, "switching_profile_point_applied_to_line", { line: line, value: onOrOff }, "", SEND_TO.tb, instance); + } + + + // 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; + + // 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) { + const status = flowdata.data.status; + if (status == "NOK-twilight_sensor") { + deviceStatus["twilight_sensor"] = "NOK"; + } + else if (status == "NOK-em340" || status == "NOK-em111") { + deviceStatus["em"] = "NOK"; + } + else if (status == "NOK-thermometer") { + deviceStatus["temperature"] = "NOK"; + } + } + else if ("values" in flowdata.data) { + 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" + } + else if (values.hasOwnProperty("temperature")) { + deviceStatus["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"; + } + + sendTelemetry(values, rvoTbName); + } + + sendRvoStatus(); + }) + + + // we expect array as flowdata.data + instance.on("1", flowdata => { + + console.log(flowdata.data); + + if (!flowdata.data instanceof Object) return; + + let obj = flowdata.data; + let line = obj.line; + 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"); + + //! ake data prichadzaju z cmd_manager.js ??? + //TODO transform to websocket + if (Array.isArray(obj)) { + + rsPort.write(Buffer.from(obj), function(err) { + switchLogic(obj); + + instance.send(SEND_TO.debug, { "WRITE": obj }); + }); + } + }) + + + function calculateStateCode() { + + 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") { + bits.push(0); + } + else { + bits.push(1); + } + + //Prevádzkový mód - Manual, Off, Automatic, maintenance_mode = true/false // DAVA 2 BITY + if (!SETTINGS.maintenance_mode) { + if (deviceStatus["rotary_switch_state"] == "Manual") { + bits.push(0); + bits.push(1); + } + + if (deviceStatus["rotary_switch_state"] == "Automatic") { + bits.push(0); + bits.push(0); + } + + if (deviceStatus["rotary_switch_state"] == "Off") { + bits.push(1); + bits.push(0); + } + } + else { + bits.push(1); + bits.push(1); + } + + //Dverový kontakt + if (deviceStatus["door_condition"] == "closed") { + bits.push(0); + } + else { + bits.push(1); + } + + //EM + if (deviceStatus["em"] == "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //Teplomer + if (deviceStatus["temperature"] == "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //Batéria + if (deviceStatus["battery"] == "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //Zdroj + if (deviceStatus["power_supply"] == "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //MN + if (deviceStatus["master_node"] == "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //výpadok napätia na fáze + if (deviceStatus["no_voltage"] == "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + if (deviceStatus["twilight_sensor"] == "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + // doplnime do 16 bitov (2 byty) + for (let i = bits.length; i < 16; i++) { + bits.push(0); + } + + // console.log("calculateStateCode - deviceStatus", deviceStatus); + // 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; + } + + + async function sendRvoStatus() { + + if (SETTINGS === undefined) return; + SETTINGS.masterNodeIsResponding ? deviceStatus["master_node"] = "OK" : deviceStatus["master_node"] = "NOK"; + + 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() { + + // 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 + //set RVO state + let status = "OK"; + + for (const [key, value] of Object.entries(deviceStatus)) { + if (["em", "twilight_sensor", "temperature", "master_node"].includes(key) && value == "NOK") status = "NOK"; + } + + if (status == "OK") { + let pinIndexes = [1, 4, 6]; + if (controller_type == 'unipi') pinIndexes = ['input1_01', 'input1_04', 'input1_05']; + + for (const pinIndex of pinIndexes) { + if (previousValues[pinIndex] === 0) { + if ((pinIndex === 6 || pinIndex === 'input1_01' || pinIndex === 'input1_05') && SETTINGS.maintenance_mode) continue; + status = "NOK"; + break; + } + } + } + + // battery status. If value is 1 - battery is NOK + if (previousValues[5] === 1) status = "NOK"; + if (SETTINGS.no_voltage.size > 0) status = "NOK"; + + // console.log("rvo status",status) + return status; + } + + + // we pass array to function in case of rsPort ==> switchLogic([55,3,0,1]) ==> [[55,3,0,1]] + // we pass two values in case of websocket ==> switchLogic("relay1_03",1) ==> ["relay1_03",1] + const switchLogic = (...args) => { + + let values = {}; + let pinIndex, newPinValue, twilight; + + //data from rsPort + if (args.length == 1) { + pinIndex = args[0][1] + 1; + if (pinIndex === 17) pinIndex--; + newPinValue = args[0][3]; + twilight = args[0][2]; + } + //data from websocket + else { + pinIndex = args[0]; + newPinValue = args[1]; + } + + 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; + + //default value + let value = "On"; + if (newPinValue === 0) value = "Off"; + + //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"; + + // 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"); + + // deviceStatus["state_of_main_switch"] = "On"; + // } + // } + + //Prevádzkový mód + 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"; + + deviceStatus["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, "power_supply_has_disconnected_input", {}, "", SEND_TO.tb, instance, "power_supply"); + + deviceStatus["power_supply"] = "NOK"; + } + else if (newPinValue === 1 && newPinValue !== previousValues[pinIndex]) { + sendNotification("switchLogic", rvoTbName, "power_supply_works_correctly", {}, "", SEND_TO.tb, instance, "power_supply"); + + deviceStatus["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"); + + deviceStatus["battery"] = "NOK"; + } + else if (newPinValue === 0 && newPinValue !== previousValues[pinIndex]) { + sendNotification("switchLogic", rvoTbName, "battery_level_is_ok", {}, "", SEND_TO.tb, instance, "battery_level"); + + deviceStatus["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' + else if (type == "door_condition" || type === "state_of_main_switch") { + newPinValue === 0 ? value = "open" : value = "closed"; + + 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, "door_opened_without_permission", {}, "", SEND_TO.tb, instance, "rvo_door"); + + // 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 (value === "closed") { + if (alarmStatus == "ON") turnAlarm("off"); + sendNotification("switchLogic", rvoTbName, "door_closed", {}, "", SEND_TO.tb, instance, "rvo_door"); + } + + deviceStatus[type] = value; + } + + //lux sensor + else if (type == "twilight_sensor") { + //! TODO - to show nok status, if lux value is not changing more then 10 times. + //Daylight is far more than 1000. So most of the day, when it is sunshine comes just value 1000. But lux sensor is not NOK. + //This is not the case in LM. If value from LM is the same 10x, there is 99% possibility, that sensor is NOK. + value = newPinValue; + + if (controller_type === 'lm') { + value = parseFloat(newPinValue + (256 * twilight)); + + 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 && !twilightError) { + twilightError = true; + let value = twilight_sensor_array.shift(); + + newPinValue = 0; + } + else if (set.size !== 1 && twilightError) { + //sendNotification("switchLogic", rvoTbName, 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) { + 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); + } + } + + 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); + } + + deviceStatus["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) + // { + // let time = 0; + // if(value) time = 1000 * 10;//10 sekund + + // let dataChanged = false; + // if(relaysData[line].contactor != newPinValue) dataChanged = true; + // relaysData[line].contactor = newPinValue; // 0,1 + + // //ak bola predchadzajuci stav off a novy stav je on, budu sa nastavovat nespracovane node profiles + // //a budu sa odosielat commandy, tie vsak mozu zlyhat, a preto potrebujeme ich spusti trochu neskor + // setTimeout(function(){ + // instance.send(SEND_TO.cmd_manager, {sender: "dido_controller", cmd: "reload_relays", line: line, time: time, value: value, dataChanged: dataChanged}); + // }, time); + + // reportLineStatus(line); + // } + // else + // { + // errLogger.error("modify table relays failed", err); + // } + + // }); + // }); + } + + 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 }); + + //mame iba 3 istice. vyreportujeme a ohandlujeme liniu na tom istom istici ako paralelna linia (napr linia 1, paralelna s nou je linia 4, key je string "4") + // ak je 7 linii, na 1 istici je linia 1,4,7 + + if (line == 1) { + + const lineOnSameBraker = [4, 7]; + + for (var i = 0; i < lineOnSameBraker.length; i++) { + if (!relaysData.hasOwnProperty(lineOnSameBraker[i])) continue; + + 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; + reportLineStatus(lineOnSameBraker[i]); + + values[type] = value; + const tbname = relaysData[lineOnSameBraker[i]].tbname; + sendTelemetry(values, tbname); + + delete values[type]; + } + + } + else { + const lineOnSameBraker = line + 3 + ""; + + if (relaysData.hasOwnProperty(lineOnSameBraker)) { + 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; + reportLineStatus(line + 3); + + values[type] = value; + const tbname = relaysData[lineOnSameBraker].tbname; + sendTelemetry(values, tbname); + + delete values[type]; + } + } + + } + + if (value == "Off") values["status"] = "NOK"; + deviceStatus["state_of_breaker"][line] = value; + + reportLineStatus(line); + } + else return; + + values[type] = value; + + if (type == "rotary_switch_state") { + if (SETTINGS.maintenance_mode) value = "maintenance"; + value = value.toLowerCase(); + values["power_mode"] = value; + } + + if (newPinValue != previousValues[pinIndex]) previousValues[pinIndex] = newPinValue; + if (Object.keys(values).length > 0 && tbname) sendTelemetry(values, tbname); + } + + + function sendTelemetry(values, tbname, date = Date.now()) { + let dataToTb = { + [tbname]: [ + { + "ts": date, + "values": values + } + ] + }; + + tbHandler.sendToTb(dataToTb, instance); + } + + + function isObject(item) { + return (typeof item === "object" && !Array.isArray(item) && item !== null); + } + +} //end of 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 +// *|input1_01|state_of_main_switch|0|........... +// *|input1_02|rotary_switch_state|0|........... +// *|input1_03|rotary_switch_state|0|........... +// *|intut1_04|power_supply|0|........... +// *|input1_05|door_condition|0|........... +// *|input1_06|state_of_breaker|1|........... +// *|input1_07|state_of_breaker|2|........... +// *|input1_08|state_of_breaker|3|........... +// *|relay1_02|state_of_contactor|1|........... +// *|relay1_03|state_of_contactor|2|........... +// *|relay1_04|state_of_contactor|3|........... +// *|287D8776E0013CE9|temperature|0|........... + + +//! pins_data --> from UNIPI +// { +// 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 } +// } + +//! relays_data +// { +// '0': { +// line: 0, +// tbname: 'KjbN4q7JPZmexgdnz2yKQ98YAWwO0Q3BMX6ERLoV', +// contactor: 1, +// profile: '' +// }, +// '1': { +// line: 1, +// tbname: 'RMgnK93rkoAazbqdQ4yBG95Z1YXGx6pmwBeVEP2O', +// contactor: 0, +// profile: '{"intervals":[{"value":0,"end_time":"20:00","start_time":"13:00"},{"value":1,"end_time":"10:00","start_time":"20:00"},{"value":0,"end_time":"10:20","start_time":"10:00"},{"value":1,"end_time":"10:40","start_time":"10:20"},{"value":0,"end_time":"11:00","start_time":"10:40"},{"value":1,"end_time":"11:30","start_time":"11:00"},{"value":0,"end_time":"11:50","start_time":"11:30"},{"value":1,"end_time":"13:00","start_time":"11:50"}],"astro_clock":false,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' +// }, +// '2': { +// line: 2, +// tbname: 'dlE1VQjYrNx9gZRmb38gG08oLBO4qaAk2M6JPnG7', +// contactor: 0, +// profile: '{"intervals":[{"value":0,"end_time":"20:00","start_time":"13:00"},{"value":1,"end_time":"10:00","start_time":"20:00"},{"value":0,"end_time":"10:20","start_time":"10:00"},{"value":1,"end_time":"10:40","start_time":"10:20"},{"value":0,"end_time":"11:00","start_time":"10:40"},{"value":1,"end_time":"11:30","start_time":"11:00"},{"value":0,"end_time":"11:50","start_time":"11:30"},{"value":1,"end_time":"13:00","start_time":"11:50"}],"astro_clock":false,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' +// }, +// '3': { +// line: 3, +// tbname: 'vnmG4kJxaXWNBgMQq0D7Aj5e9oZzOAlr6LdR3w2V', +// contactor: 0, +// profile: '{"intervals":[{"value":0,"end_time":"20:30","start_time":"13:00"},{"value":1,"end_time":"00:10","start_time":"20:30"},{"value":0,"end_time":"13:00","start_time":"05:40"},{"value":1,"end_time":"05:40","start_time":"00:10"}],"astro_clock":true,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' +// } +// } + + + + + +// { +// "jbN4q7JPZmexgdnz2yKbWGDYAWwO0Q3BMX6ERLoV": [ +// { +// "ts": 1700409326353, +// "values": { +// "_event": { +// "type": "notice", +// "status": "new", +// "source": { +// "func": "rsPort.open()", +// "component": "1700343402190", +// "component_name": "DIDO_Controller", +// "edge": "jbN4q7JPZmexgdnz2yKbWGDYAWwO0Q3BMX6ERLoV" +// }, +// "message": "al_shariff_10.0.0.38: FLOW has been started ", +// "message_data": "" +// } +// } +// } +// ] +// } diff --git a/RVO25/flow_15_1_2025/helper/DataToTbHandler.js b/RVO25/flow_15_1_2025/helper/DataToTbHandler.js new file mode 100755 index 0000000..65e4ec3 --- /dev/null +++ b/RVO25/flow_15_1_2025/helper/DataToTbHandler.js @@ -0,0 +1,166 @@ +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; + + this.sender = ""; + + // if attribute difference is less than limit value, we do not send to tb. + this.attributeChangeLimit = { + temperature: 0.5, + Phase_1_voltage: 2, + Phase_2_voltage: 2, + Phase_3_voltage: 2, + Phase_1_current: 0.1, + Phase_2_current: 0.1, + Phase_3_current: 0.1, + Phase_1_power: 2, + Phase_2_power: 2, + Phase_3_power: 2, + total_power: 2, + Phase_1_pow_factor: 0.1, + Phase_2_pow_factor: 0.1, + Phase_3_pow_factor: 0.1, + power_factor: 0.1, + lifetime: 0.5, + voltage: 2, + power: 2, + frequency: 3, + energy: 0.1, + current: 2, + inclination_x: 10, + inclination_y: 10, + inclination_z: 10 + }; + } + + dump() { + console.log("----------------------------"); + console.log("previousValues", this.previousValues); + console.log("----------------------------"); + } + + setSender(sender) { + this.sender = sender; + } + + isEmptyObject(obj) { + for (var name in obj) { + return false; + } + return true; + } + + sendToTb(dataToTb, instance) { + + let keys = Object.keys(dataToTb); + + if(keys.length == 0) + { + if(this.debug) console.log("sendToTb received empty object", dataToTb); + return; + } + + let tbname = keys[0]; + let ts; + + let arrayOfValues = dataToTb[tbname]; + let arrayOfValuesToSend = []; + + for(let i = 0; i < arrayOfValues.length; i++) + { + ts = arrayOfValues[i].ts; + let values = this.prepareValuesForTb(tbname, ts, arrayOfValues[i].values); + + if(!this.isEmptyObject(values)) + { + arrayOfValuesToSend.push({ts: ts, values: values}); + } + } + + if(arrayOfValuesToSend.length == 0) + { + //if(this.debug) console.log("data not sent - empty array"); + return; + } + + this.messageCounter++; + + let dataToTbModified = { + [tbname]: arrayOfValuesToSend + } + + //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); + instance.send(this.index, dataToTbModified); + } + + getDiffTimestamp(key) { + //TODO set different value for given key!!! + //if(key == "status") this.timeToHoldTbValue = 2*60*60;//2h + return this.timeToHoldTbValue * 1000; + } + + prepareValuesForTb(tbname, timestamp, values) { + + let keys = Object.keys(values); + if(!this.previousValues.hasOwnProperty(tbname)) + { + this.previousValues[tbname] = {}; + } + + //if(this.debug) console.log("prepareValuesForTb", tbname, timestamp, values); + + for(let i = 0; i < keys.length; i++) + { + let key = keys[i]; + let value = values[key]; + + if(!this.previousValues[tbname].hasOwnProperty(key)) + { + this.previousValues[tbname][key] = {ts: timestamp, value: value}; + continue; + } + + // attributeData ==> voltage: {ts:333333, value:5} + let attributeData = this.previousValues[tbname][key]; + let attributeToChange = false; + if(key in this.attributeChangeLimit) attributeToChange = true; + let limit = this.attributeChangeLimit[key]; + + if(attributeData.value === value || attributeToChange && Math.abs(attributeData.value - value) < limit) + { + let diff = timestamp - attributeData.ts; + let timestampDiffToRemoveKey = this.getDiffTimestamp(key); + if(diff > timestampDiffToRemoveKey) + { + attributeData.ts = Date.now(); + //if(this.debug) console.log(this.sender + ": update ts for key", key, "diff is", diff, "messageCounter", this.messageCounter); + } + else + { + delete values[key]; + //if(this.debug) console.log(this.sender + ": delete key", key, "diff is", diff, "messageCounter", this.messageCounter, timestampDiffToRemoveKey); + } + } + else + { + attributeData.value = value; + attributeData.ts = timestamp; + } + + } + + return values; + } +} + +module.exports = DataToTbHandler; + diff --git a/RVO25/flow_15_1_2025/helper/ErrorToServiceHandler.js b/RVO25/flow_15_1_2025/helper/ErrorToServiceHandler.js new file mode 100755 index 0000000..110ea8b --- /dev/null +++ b/RVO25/flow_15_1_2025/helper/ErrorToServiceHandler.js @@ -0,0 +1,126 @@ +const { MD5 } = require('./md5.js'); +const { networkInterfaces } = require('os'); + +class ErrorToServiceHandler +{ + constructor() { + this.previousValues = {}; + + this.projects_id = undefined; + + const nets = networkInterfaces(); + this.ipAddresses = Object.create(null); // Or just '{}', an empty object + + for (const name of Object.keys(nets)) { + for (const net of nets[name]) { + // Skip over non-IPv4 and internal (i.e. 127.0.0.1) addresses + if (net.family === 'IPv4' && !net.internal) { + if (!this.ipAddresses[name]) { + this.ipAddresses[name] = []; + } + this.ipAddresses[name].push(net.address); + } + } + } + + //console.log(this.ipAddresses); + + } + + setProjectsId(projects_id) + { + this.projects_id = projects_id; + } + + processMessage(message, seconds, message_type) + { + if(message_type == undefined) message_type = "error_message"; + if(Array.isArray(message)) message = message.join(', '); + + let key = MD5(message); + let timestamp = new Date().getTime(); + + //keep in memory - default value is 1h + if (seconds === undefined) seconds = 60*60; + + if(!this.previousValues.hasOwnProperty(key)) + { + this.previousValues[key] = {ts: timestamp, duration: seconds}; + } + + let diff = (timestamp - this.previousValues[key].ts); + if(diff < this.previousValues[key].duration*1000) return false; + + this.previousValues[key].ts = timestamp; + + return true; + } + + sendMessageToService(message, seconds, message_type) + { + + let f = this.processMessage(message, seconds, message_type); + if(!f) return; + + /* + //------------- + if(message_type == undefined) message_type = "error_message"; + if(Array.isArray(message)) message = message.join(', '); + + let key = MD5(message); + let timestamp = new Date().getTime(); + + //keep in memory + if (seconds === undefined) seconds = 60*60; + + if(!this.previousValues.hasOwnProperty(key)) + { + this.previousValues[key] = {ts: timestamp, duration: seconds}; + } + + let diff = (timestamp - this.previousValues[key].ts); + if(diff < this.previousValues[key].duration*1000) return; + + this.previousValues[key].ts = timestamp; + */ + + //------------------------- + + //send to service + + let dataToInfoSender = {id: this.projects_id}; + + //js_error || error_message + dataToInfoSender[message_type] = message; + dataToInfoSender.ipAddresses = this.ipAddresses; + + 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) + { + console.log("this.projects_id is undefined"); + return; + } + */ + + RESTBuilder.make(function(builder) { + builder.method('POST'); + builder.post(dataToInfoSender); + builder.url('http://192.168.252.2:8004/sentmessage'); + + builder.callback(function(err, response, output) { + console.log("process.on error send", err, response, output, dataToInfoSender); + }); + }); + + + } +} + +module.exports = ErrorToServiceHandler; \ No newline at end of file diff --git a/RVO25/flow_15_1_2025/helper/db_helper.js b/RVO25/flow_15_1_2025/helper/db_helper.js new file mode 100755 index 0000000..40e796c --- /dev/null +++ b/RVO25/flow_15_1_2025/helper/db_helper.js @@ -0,0 +1,44 @@ +function promisifyBuilder(builder) +{ + return new Promise((resolve, reject) => { + + try{ + + builder.callback(function(err, response) { + + if(err != null) reject(err); + resolve(response); + }); + + } catch (error) { + reject(error); + } + }) +} + +function makeMapFromDbResult(response, ...keys) +{ + let s = "-"; + let data = {}; + + for(let i = 0; i < response.length; i++) + { + let record = response[i]; + + let k = []; + for(let j = 0; j < keys.length; j++) + { + k.push( record[keys[j]] ); + } + + let key = k.join(s); + data[ key ] = record; + } + + return data; +} + +module.exports = { + promisifyBuilder, + makeMapFromDbResult + } \ No newline at end of file diff --git a/RVO25/flow_15_1_2025/helper/logger.js b/RVO25/flow_15_1_2025/helper/logger.js new file mode 100755 index 0000000..2585639 --- /dev/null +++ b/RVO25/flow_15_1_2025/helper/logger.js @@ -0,0 +1,30 @@ +//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/RVO25/flow_15_1_2025/helper/md5.js b/RVO25/flow_15_1_2025/helper/md5.js new file mode 100755 index 0000000..d3b0480 --- /dev/null +++ b/RVO25/flow_15_1_2025/helper/md5.js @@ -0,0 +1,5 @@ +function MD5(d){var r = M(V(Y(X(d),8*d.length)));return r.toLowerCase()};function M(d){for(var _,m="0123456789ABCDEF",f="",r=0;r>>4&15)+m.charAt(15&_);return f}function X(d){for(var _=Array(d.length>>2),m=0;m<_.length;m++)_[m]=0;for(m=0;m<8*d.length;m+=8)_[m>>5]|=(255&d.charCodeAt(m/8))<>5]>>>m%32&255);return _}function Y(d,_){d[_>>5]|=128<<_%32,d[14+(_+64>>>9<<4)]=_;for(var m=1732584193,f=-271733879,r=-1732584194,i=271733878,n=0;n>16)+(_>>16)+(m>>16)<<16|65535&m}function bit_rol(d,_){return d<<_|d>>>32-_} + +module.exports = { + MD5 +} \ No newline at end of file diff --git a/RVO25/flow_15_1_2025/helper/notification_reporter.js b/RVO25/flow_15_1_2025/helper/notification_reporter.js new file mode 100755 index 0000000..61c0aef --- /dev/null +++ b/RVO25/flow_15_1_2025/helper/notification_reporter.js @@ -0,0 +1,131 @@ +//key is device, value = str +let sentValues= {}; +let notificationsData = null; + +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 +}; + +function getKey(map, val) { + return Object.keys(map).findItem(key => map[key] === val); +} + +//https://stackoverflow.com/questions/41117799/string-interpolation-on-variable +var template = (tpl, args) => tpl.replace(/\${(\w+)}/g, (_, v) => args[v]); + + +function initNotification() { + notificationsData = FLOW.GLOBALS.notificationsData; +} + +function sendNotification(func, device, key, params, extra, tb_output, instance, saveKey) { + + // return; + + let storeToSendValues = true; + if(saveKey == undefined) storeToSendValues = false; + + let lang = FLOW.GLOBALS.settings.language; + if(lang != "en" || lang != "sk") lang = "en"; + + let tpl = key; + let weight = ""; + + if(notificationsData[key]) + { + weight = notificationsData[key].weight; + weight = weight.toLowerCase(); + + tpl = notificationsData[key][lang]; + tpl = template(tpl, params); + } + else + { + //console.error("sendNotification: Notifications: undefined key", key, func, notificationsData); + console.error("sendNotification: Notifications: undefined key", key, func ); + return false; + } + + //detect invalid err weight + if(getKey(ERRWEIGHT, weight) == undefined) + { + console.error("sendNotification: Notifications: undefined weight", weight, key, func); + return false; + } + + if(sentValues.hasOwnProperty(saveKey)) + { + if(sentValues[saveKey] == tpl) + { + return false; + } + } + + if(sentValues[saveKey] == undefined) + { + if(storeToSendValues) + { + //do not send - flow is was started + sentValues[saveKey] = tpl; + return false; + } + } + + if(saveKey == "rvo_door") + { + //console.log("******", saveKey, sentValues[saveKey], tpl); + } + + if(storeToSendValues) sentValues[saveKey] = tpl; + + let str = FLOW.GLOBALS.settings.rvo_name; + if(str != "") str = str + ": "; + str = str + tpl; + + 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 + + return true; + +} + +module.exports = { + sendNotification, + ERRWEIGHT, + initNotification +} diff --git a/RVO25/flow_15_1_2025/helper/register.js b/RVO25/flow_15_1_2025/helper/register.js new file mode 100755 index 0000000..fc1d008 --- /dev/null +++ b/RVO25/flow_15_1_2025/helper/register.js @@ -0,0 +1,144 @@ +/* +0 - cislo registra / prikaz +1 - recepient - 0 = master, 1 = slave (slave je automaticky group a broadcast) +2 - r/rw - read/write +3- register name - nazov registra / prikazu (len pre info - zobrazenie v aplikacii) + +4,5,6,7, - jednotlive byte-y - nazov byte-u +4-7 - RES. a prazdny string "" sa nezobrazia!!! +*/ + +//124 zaznamov +const registers = [ + ["0","1","R","Status","","",""], + ["1","1","RW","Dimming","R-Channel ","G-Channel","B-Channel ","W - Channel"], + ["2","1","R","Device types","","",".",""], + ["3","1","RW","Group addresses 1-4","Groups Add. 4","Groups Add. 3","Groups Add. 2","Groups Add. 1"], + ["4","1","RW","Group addresses 5-8","Groups Add. 8","Groups Add. 7","Groups Add. 6","Groups Add. 5"], + ["5","1","RW","Serial number (MAC)","","","",""], + ["6","1","RW","Time of dusk","HH","MM","SS","EXTRA"], + ["7","1","RW","Time of dawn","HH","MM","SS","EXTRA"], + ["8","1","RW","Time Schedule settings","TBD","TBD","Movement sensor","Time Schedule"], + ["9","1","RW","TS1 Time point 1","HH","MM","SS","Ext. Device"], + ["10","1","RW","TS1 Time point 1 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["11","1","RW","TS1 Time point 2","HH","MM","SS","Ext. Device"], + ["12","1","RW","TS1 Time point 2 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["13","1","RW","TS1 Time point 3","HH","MM","SS","Ext. Device"], + ["14","1","RW","TS1 Time point 3 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["15","1","RW","TS1 Time point 4","HH","MM","SS","Ext. Device"], + ["16","1","RW","TS1 Time point 4 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["17","1","RW","TS1 Time point 5","HH","MM","SS","Ext. Device"], + ["18","1","RW","TS1 Time point 5 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["19","1","RW","TS1 Time point 6","HH","MM","SS","Ext. Device"], + ["20","1","RW","TS1 Time point 6 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["21","1","RW","TS1 Time point 7","HH","MM","SS","Ext. Device"], + ["22","1","RW","TS1 Time point 7 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["23","1","RW","TS1 Time point 8","HH","MM","SS","Ext. Device"], + ["24","1","RW","TS1 Time point 8 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["25","1","RW","TS1 Time point 9","HH","MM","SS","Ext. Device"], + ["26","1","RW","TS1 Time point 9 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["27","1","RW","TS1 Time point 10","HH","MM","SS","Ext. Device"], + ["28","1","RW","TS1 Time point 10 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["29","1","RW","TS1 Time point 11","HH","MM","SS","Ext. Device"], + ["30","1","RW","TS1 Time point 11 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["31","1","RW","TS1 Time point 12","HH","MM","SS","Ext. Device"], + ["32","1","RW","TS1 Time point 12 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["33","1","RW","TS1 Time point 13","HH","MM","SS","Ext. Device"], + ["34","1","RW","TS1 Time point 13 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["35","1","RW","TS1 Time point 14","HH","MM","SS","Ext. Device"], + ["36","1","RW","TS1 Time point 14 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["37","1","RW","TS1 Time point 15","HH","MM","SS","Ext. Device"], + ["38","1","RW","TS1 Time point 15 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["39","1","RW","TS1 Time point 16","HH","MM","SS","Ext. Device"], + ["40","1","RW","TS1 Time point 16 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["41","1","RW","TS2 Time point 1","HH","MM","SS","Ext. Device"], + ["42","1","RW","TS2 Time point 1 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["43","1","RW","TS2 Time point 2","HH","MM","SS","Ext. Device"], + ["44","1","RW","TS2 Time point 2 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["45","1","RW","TS2 Time point 3","HH","MM","SS","Ext. Device"], + ["46","1","RW","TS2 Time point 3 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["47","1","RW","TS2 Time point 4","HH","MM","SS","Ext. Device"], + ["48","1","RW","TS2 Time point 4 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["49","1","RW","TS2 Time point 5","HH","MM","SS","Ext. Device"], + ["50","1","RW","TS2 Time point 5 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["51","1","RW","TS2 Time point 6","HH","MM","SS","Ext. Device"], + ["52","1","RW","TS2 Time point 6 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["53","1","RW","TS2 Time point 7","HH","MM","SS","Ext. Device"], + ["54","1","RW","TS2 Time point 7 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["55","1","RW","TS2 Time point 8","HH","MM","SS","Ext. Device"], + ["56","1","RW","TS2 Time point 8 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["57","1","RW","TS2 Time point 9","HH","MM","SS","Ext. Device"], + ["58","1","RW","TS2 Time point 9 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["59","1","RW","TS2 Time point 10","HH","MM","SS","Ext. Device"], + ["60","1","RW","TS2 Time point 10 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["61","1","RW","TS2 Time point 11","HH","MM","SS","Ext. Device"], + ["62","1","RW","TS2 Time point 11 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["63","1","RW","TS2 Time point 12","HH","MM","SS","Ext. Device"], + ["64","1","RW","TS2 Time point 12 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["65","1","RW","TS2 Time point 13","HH","MM","SS","Ext. Device"], + ["66","1","RW","TS2 Time point 13 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["67","1","RW","TS2 Time point 14","HH","MM","SS","Ext. Device"], + ["68","1","RW","TS2 Time point 14 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["69","1","RW","TS2 Time point 15","HH","MM","SS","Ext. Device"], + ["70","1","RW","TS2 Time point 15 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["71","1","RW","TS2 Time point 16","HH","MM","SS","Ext. Device"], + ["72","1","RW","TS2 Time point 16 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["73","1","RW","Power meter status","TBD","","",""], + ["74","1","R","Input Voltage","","","",""], + ["75","1","R","Input Current","","","",""], + ["76","1","R","Input Power","","","",""], + ["77","1","R","Cos phi","","","",""], + ["78","1","R","Frequency","","","",""], + ["79","1","RW","Energy","","","",""], + ["80","1","RW","Lifetime","","","",""], + ["81","1","RW","Power on cycles (input)","","","",""], + ["82","1","RW","Power on cycles (relay)","","","",""], + ["83","1","R","Time since last power on","","","",""], + ["84","1","R","Accelerometer data","","","",""], + ["85","1","RW","GPS latitude","pos/neg","deg","min ","sec"], + ["86","1","RW","GPS longitude","pos/neg","deg","min ","sec"], + ["87","1","RW","Actual time","HH","MM","SS","RES."], + ["88","1","RW","Actual date","Day of week","Day","Month","Year"], + ["89","1","R","Production data 1","","","",""], + ["90","1","R","Production data 2","","","",""], + ["91","1","RW","Network ID","NID3","NID2","NID1","NID0"], + ["95","1","RW","Actual Lux level from cabinet","RES.","RES.","HB","LB"], + ["96","1","RW","Threshold lux level","Dusk HB","Dusk LB","Dawn HB","Dawn LB"], + ["97","1","RW","Adjust period","Dusk HB","Dusk LB","Dawn HB","Dawn LB"], + ["98","1","RW","Offset","RES.","RES.","Dusk","Dawn"], + ["99","1","RW","CCT min/max range","max-H","max-L","min-H","min-L"], + ["100","1","RW","DALI interface","Cmd ID","Add","Cmd","Resp"], + ["101","1","RW","Module FW ver","v1","v2","v3","v4"], + ["102","1","RW","Module MAC-H","unused","unused","M1","M2"], + ["103","1","RW","Module MAC-L","M3","M4","M5","M6"], + ["122","1","R","FW update status/control register","Byte3","Byte2","Byte1","Byte0"], + ["123","1","R","FW update - data index","Byte3","Byte2","Byte1","Byte0"], + ["124","1","R","FW update - data","Byte3","Byte2","Byte1","Byte0"], + ["0","0","R","Status","","","",""], + ["1","0","RW","Control register","RES.","RES.","RES.","init mode enable"], + ["2","0","R","Device types","","","",""], + ["3","0","R","Serial number (MAC)","","","",""], + ["4","0","R","Production data 1","","","",""], + ["5","0","R","Production data 2","","","",""], + ["6","0","RW","Network ID","NID3","NID2","NID1","NID0"], + ["7","0","RW","RS232 settings","param.","param.","Baudrate H","Baudrate L"], + ["8","0","R","Accelerometer data","","","",""], + ["9","0","RW","Module FW ver","v1","v2","v3","v4"], + ["10","0","RW","Module MAC-H","unused","unused","M1","M2"], + ["11","0","RW","Module MAC-L","M3","M4","M5","M6"], + ["32","0","RW","FW update status/control register","Byte3","Byte2","Byte1","Byte0"], + ["33","0","RW","FW update - data index","Byte3","Byte2","Byte1","Byte0"], + ["34","0","RW","FW update - data","Byte3","Byte2","Byte1","Byte0"], + ["125","0","RW","Debug Register","Byte3","Byte2","Byte1","Byte0"], + ["126","0","RW","Network Control Register","Byte3","Byte2","Byte1","Byte0"], + ["127","0","R","Network Status Register","Byte3","Byte2","Byte1","Byte0"], + ["128","0","RW","Node XX Serial Number Register","SER3","SER2","SER1","SER0"], + ["256","0","R","Node XX Network Status Register","","","",""] +]; + +let register = {}; + +module.exports = { + registers, + register +} \ No newline at end of file diff --git a/RVO25/flow_15_1_2025/helper/serialport_helper.js b/RVO25/flow_15_1_2025/helper/serialport_helper.js new file mode 100755 index 0000000..8efa6af --- /dev/null +++ b/RVO25/flow_15_1_2025/helper/serialport_helper.js @@ -0,0 +1,100 @@ +const { exec } = require('child_process'); + +function openPort(port){ + return new Promise((resolve, reject) => { + + var callbackError = function(err) { + port.removeListener('error', callbackError); + port.removeListener('open', callbackError); + + reject(err.message); + }; + + var callbackOpen = function(data) { + port.removeListener('error', callbackError); + port.removeListener('open', callbackOpen); + + resolve("port open: ok"); + }; + + port.on('error', callbackError); + port.on('open', callbackOpen); + + port.open(); + + }) +} + +function runSyncExec(command){ + return new Promise((resolve, reject) => { + + exec(command, (error, stdout, stderr) => { + if(error == null) resolve(stdout); + reject(error); + }); + + }) +} + +async function writeData(port, data, readbytes, timeout){ + return new Promise((resolve, reject) => { + + // 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) { + + port.write(Buffer.from(data), function(err) { + if (err) { + reject(err.message); + } + }); + + 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 +} diff --git a/RVO25/flow_15_1_2025/helper/suncalc.js b/RVO25/flow_15_1_2025/helper/suncalc.js new file mode 100755 index 0000000..c9ca56d --- /dev/null +++ b/RVO25/flow_15_1_2025/helper/suncalc.js @@ -0,0 +1,317 @@ +/* + (c) 2011-2015, Vladimir Agafonkin + SunCalc is a JavaScript library for calculating sun/moon position and light phases. + https://github.com/mourner/suncalc +*/ + +(function () { 'use strict'; + +// shortcuts for easier to read formulas + +var PI = Math.PI, + sin = Math.sin, + cos = Math.cos, + tan = Math.tan, + asin = Math.asin, + atan = Math.atan2, + acos = Math.acos, + rad = PI / 180; + +// sun calculations are based on http://aa.quae.nl/en/reken/zonpositie.html formulas + + +// date/time constants and conversions + +var dayMs = 1000 * 60 * 60 * 24, + J1970 = 2440588, + J2000 = 2451545; + +function toJulian(date) { return date.valueOf() / dayMs - 0.5 + J1970; } +function fromJulian(j) { return new Date((j + 0.5 - J1970) * dayMs); } +function toDays(date) { return toJulian(date) - J2000; } + + +// general calculations for position + +var e = rad * 23.4397; // obliquity of the Earth + +function rightAscension(l, b) { return atan(sin(l) * cos(e) - tan(b) * sin(e), cos(l)); } +function declination(l, b) { return asin(sin(b) * cos(e) + cos(b) * sin(e) * sin(l)); } + +function azimuth(H, phi, dec) { return atan(sin(H), cos(H) * sin(phi) - tan(dec) * cos(phi)); } +function altitude(H, phi, dec) { return asin(sin(phi) * sin(dec) + cos(phi) * cos(dec) * cos(H)); } + +function siderealTime(d, lw) { return rad * (280.16 + 360.9856235 * d) - lw; } + +function astroRefraction(h) { + if (h < 0) // the following formula works for positive altitudes only. + h = 0; // if h = -0.08901179 a div/0 would occur. + + // formula 16.4 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + // 1.02 / tan(h + 10.26 / (h + 5.10)) h in degrees, result in arc minutes -> converted to rad: + return 0.0002967 / Math.tan(h + 0.00312536 / (h + 0.08901179)); +} + +// general sun calculations + +function solarMeanAnomaly(d) { return rad * (357.5291 + 0.98560028 * d); } + +function eclipticLongitude(M) { + + var C = rad * (1.9148 * sin(M) + 0.02 * sin(2 * M) + 0.0003 * sin(3 * M)), // equation of center + P = rad * 102.9372; // perihelion of the Earth + + return M + C + P + PI; +} + +function sunCoords(d) { + + var M = solarMeanAnomaly(d), + L = eclipticLongitude(M); + + return { + dec: declination(L, 0), + ra: rightAscension(L, 0) + }; +} + + +var SunCalc = {}; + + +// calculates sun position for a given date and latitude/longitude + +SunCalc.getPosition = function (date, lat, lng) { + + var lw = rad * -lng, + phi = rad * lat, + d = toDays(date), + + c = sunCoords(d), + H = siderealTime(d, lw) - c.ra; + + return { + azimuth: azimuth(H, phi, c.dec), + altitude: altitude(H, phi, c.dec) + }; +}; + + +// sun times configuration (angle, morning name, evening name) + +var times = SunCalc.times = [ + [-0.833, 'sunrise', 'sunset' ], + [ -0.3, 'sunriseEnd', 'sunsetStart' ], + [ -6, 'dawn', 'dusk' ], + [ -12, 'nauticalDawn', 'nauticalDusk'], + [ -18, 'nightEnd', 'night' ], + [ 6, 'goldenHourEnd', 'goldenHour' ] +]; + +// adds a custom time to the times config + +SunCalc.addTime = function (angle, riseName, setName) { + times.push([angle, riseName, setName]); +}; + + +// calculations for sun times + +var J0 = 0.0009; + +function julianCycle(d, lw) { return Math.round(d - J0 - lw / (2 * PI)); } + +function approxTransit(Ht, lw, n) { return J0 + (Ht + lw) / (2 * PI) + n; } +function solarTransitJ(ds, M, L) { return J2000 + ds + 0.0053 * sin(M) - 0.0069 * sin(2 * L); } + +function hourAngle(h, phi, d) { return acos((sin(h) - sin(phi) * sin(d)) / (cos(phi) * cos(d))); } +function observerAngle(height) { return -2.076 * Math.sqrt(height) / 60; } + +// returns set time for the given sun altitude +function getSetJ(h, lw, phi, dec, n, M, L) { + + var w = hourAngle(h, phi, dec), + a = approxTransit(w, lw, n); + return solarTransitJ(a, M, L); +} + + +// calculates sun times for a given date, latitude/longitude, and, optionally, +// the observer height (in meters) relative to the horizon + +SunCalc.getTimes = function (date, lat, lng, height) { + + height = height || 0; + + var lw = rad * -lng, + phi = rad * lat, + + dh = observerAngle(height), + + d = toDays(date), + n = julianCycle(d, lw), + ds = approxTransit(0, lw, n), + + M = solarMeanAnomaly(ds), + L = eclipticLongitude(M), + dec = declination(L, 0), + + Jnoon = solarTransitJ(ds, M, L), + + i, len, time, h0, Jset, Jrise; + + + var result = { + solarNoon: fromJulian(Jnoon), + nadir: fromJulian(Jnoon - 0.5) + }; + + for (i = 0, len = times.length; i < len; i += 1) { + time = times[i]; + h0 = (time[0] + dh) * rad; + + Jset = getSetJ(h0, lw, phi, dec, n, M, L); + Jrise = Jnoon - (Jset - Jnoon); + + result[time[1]] = fromJulian(Jrise); + result[time[2]] = fromJulian(Jset); + } + + return result; +}; + + +// moon calculations, based on http://aa.quae.nl/en/reken/hemelpositie.html formulas + +function moonCoords(d) { // geocentric ecliptic coordinates of the moon + + var L = rad * (218.316 + 13.176396 * d), // ecliptic longitude + M = rad * (134.963 + 13.064993 * d), // mean anomaly + F = rad * (93.272 + 13.229350 * d), // mean distance + + l = L + rad * 6.289 * sin(M), // longitude + b = rad * 5.128 * sin(F), // latitude + dt = 385001 - 20905 * cos(M); // distance to the moon in km + + return { + ra: rightAscension(l, b), + dec: declination(l, b), + dist: dt + }; +} + +SunCalc.getMoonPosition = function (date, lat, lng) { + + var lw = rad * -lng, + phi = rad * lat, + d = toDays(date), + + c = moonCoords(d), + H = siderealTime(d, lw) - c.ra, + h = altitude(H, phi, c.dec), + // formula 14.1 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + pa = atan(sin(H), tan(phi) * cos(c.dec) - sin(c.dec) * cos(H)); + + h = h + astroRefraction(h); // altitude correction for refraction + + return { + azimuth: azimuth(H, phi, c.dec), + altitude: h, + distance: c.dist, + parallacticAngle: pa + }; +}; + + +// calculations for illumination parameters of the moon, +// based on http://idlastro.gsfc.nasa.gov/ftp/pro/astro/mphase.pro formulas and +// Chapter 48 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + +SunCalc.getMoonIllumination = function (date) { + + var d = toDays(date || new Date()), + s = sunCoords(d), + m = moonCoords(d), + + sdist = 149598000, // distance from Earth to Sun in km + + phi = acos(sin(s.dec) * sin(m.dec) + cos(s.dec) * cos(m.dec) * cos(s.ra - m.ra)), + inc = atan(sdist * sin(phi), m.dist - sdist * cos(phi)), + angle = atan(cos(s.dec) * sin(s.ra - m.ra), sin(s.dec) * cos(m.dec) - + cos(s.dec) * sin(m.dec) * cos(s.ra - m.ra)); + + return { + fraction: (1 + cos(inc)) / 2, + phase: 0.5 + 0.5 * inc * (angle < 0 ? -1 : 1) / Math.PI, + angle: angle + }; +}; + + +function hoursLater(date, h) { + return new Date(date.valueOf() + h * dayMs / 24); +} + +// calculations for moon rise/set times are based on http://www.stargazing.net/kepler/moonrise.html article + +SunCalc.getMoonTimes = function (date, lat, lng, inUTC) { + var t = new Date(date); + if (inUTC) t.setUTCHours(0, 0, 0, 0); + else t.setHours(0, 0, 0, 0); + + var hc = 0.133 * rad, + h0 = SunCalc.getMoonPosition(t, lat, lng).altitude - hc, + h1, h2, rise, set, a, b, xe, ye, d, roots, x1, x2, dx; + + // go in 2-hour chunks, each time seeing if a 3-point quadratic curve crosses zero (which means rise or set) + for (var i = 1; i <= 24; i += 2) { + h1 = SunCalc.getMoonPosition(hoursLater(t, i), lat, lng).altitude - hc; + h2 = SunCalc.getMoonPosition(hoursLater(t, i + 1), lat, lng).altitude - hc; + + a = (h0 + h2) / 2 - h1; + b = (h2 - h0) / 2; + xe = -b / (2 * a); + ye = (a * xe + b) * xe + h1; + d = b * b - 4 * a * h1; + roots = 0; + + if (d >= 0) { + dx = Math.sqrt(d) / (Math.abs(a) * 2); + x1 = xe - dx; + x2 = xe + dx; + if (Math.abs(x1) <= 1) roots++; + if (Math.abs(x2) <= 1) roots++; + if (x1 < -1) x1 = x2; + } + + if (roots === 1) { + if (h0 < 0) rise = i + x1; + else set = i + x1; + + } else if (roots === 2) { + rise = i + (ye < 0 ? x2 : x1); + set = i + (ye < 0 ? x1 : x2); + } + + if (rise && set) break; + + h0 = h2; + } + + var result = {}; + + if (rise) result.rise = hoursLater(t, rise); + if (set) result.set = hoursLater(t, set); + + if (!rise && !set) result[ye > 0 ? 'alwaysUp' : 'alwaysDown'] = true; + + return result; +}; + + +// export as Node module / AMD module / browser variable +if (typeof exports === 'object' && typeof module !== 'undefined') module.exports = SunCalc; +else if (typeof define === 'function' && define.amd) define(SunCalc); +else window.SunCalc = SunCalc; + +}()); diff --git a/RVO25/flow_15_1_2025/helper/utils.js b/RVO25/flow_15_1_2025/helper/utils.js new file mode 100755 index 0000000..a16210c --- /dev/null +++ b/RVO25/flow_15_1_2025/helper/utils.js @@ -0,0 +1,124 @@ +function bytesToInt(bytes, numberOfBytes) +{ + let buffer = []; + if(Array.isArray(bytes)) + { + buffer = bytes.slice(0); + if(numberOfBytes != undefined) + { + buffer = bytes.slice(bytes.length - numberOfBytes); + } + } + else buffer.push(bytes); + + //var decimal = (buffer[0] << 24) + (buffer[1] << 16) + (buffer[2] << 8) + buffer[3]; + let l = (buffer.length - 1) * 8; + + let decimal = 0; + for(let i = 0; i < buffer.length; i++) + { + var s = buffer[i] << l; + if(l < 8) s = buffer[i] + decimal = decimal + s; + + l = l - 8; + + } + + return decimal; +} + +function resizeArray(arr, newSize, defaultValue) { + while(newSize > arr.length) + arr.push(defaultValue); + arr.length = newSize; +} + +longToByteArray = function(/*long*/long) { + // we want to represent the input as a 8-bytes array + var byteArray = [0, 0, 0, 0, 0, 0, 0, 0]; + + for ( var index = 0; index < byteArray.length; index ++ ) { + var byte = long & 0xff; + byteArray [ index ] = byte; + long = (long - byte) / 256 ; + } + + return byteArray; + }; + +function addDays(date, days) { + var result = new Date(date); + result.setDate(result.getDate() + days); + return result; +} + +/* +sleep(2000).then(() => { + // Do something after the sleep! + + +}); +*/ + +function sleep (time) { + return new Promise((resolve) => setTimeout(resolve, time)); +} + +function isEmptyObject( obj ) { + for ( var name in obj ) { + return false; + } + return true; +} + +function convertUTCDateToLocalDate(date) { + var newDate = new Date(date); + newDate.setMinutes(date.getMinutes() + date.getTimezoneOffset()); + return newDate; +} + +function addZeroBefore(n) { + return (n < 10 ? '0' : '') + n; +} + +var convertBase = function () { + + function convertBase(baseFrom, baseTo) { + return function (num) { + return parseInt(num, baseFrom).toString(baseTo); + + }; + } + + // binary to decimal + convertBase.bin2dec = convertBase(2, 10); + + // binary to hexadecimal + convertBase.bin2hex = convertBase(2, 16); + + // decimal to binary + convertBase.dec2bin = convertBase(10, 2); + + // decimal to hexadecimal + convertBase.dec2hex = convertBase(10, 16); + + // hexadecimal to binary + convertBase.hex2bin = convertBase(16, 2); + + // hexadecimal to decimal + convertBase.hex2dec = convertBase(16, 10); + + return convertBase; + }(); + +module.exports = { + bytesToInt, + longToByteArray, + addDays, + addZeroBefore, + resizeArray, + isEmptyObject, + sleep, + convertUTCDateToLocalDate +} \ No newline at end of file diff --git a/RVO25/flow_15_1_2025/httprequest.js b/RVO25/flow_15_1_2025/httprequest.js new file mode 100755 index 0000000..469c8cb --- /dev/null +++ b/RVO25/flow_15_1_2025/httprequest.js @@ -0,0 +1,137 @@ +exports.id = 'httprequest'; +exports.title = 'HTTP Request'; +exports.group = 'HTTP'; +exports.color = '#5D9CEC'; +exports.input = true; +exports.version = '2.0.1'; +exports.output = 1; +exports.author = 'Peter Širka'; +exports.icon = 'cloud-upload'; + +exports.html = `
+
@(URL address)
+
+
+
@(HTTP method)
+
+
+
@(Serialization)
+
+
+
@(Download the content in chunks)
+
@(Keep persistent cookies)
+
@(Disable DNS cache)
+
@(Keep alive connection)
+
+
+
+
@(Custom headers)
+
@(Cookies)
+
+
+
+ +
+
+
+
@(User)
+
+
+
@(Password)
+
+
+
+
+
`; + +exports.readme = `# Request + +This component creates a request with received data. + +__Response:__ +\`\`\`javascript +{ + data: String, + headers: Object, + status: Number, + host: String +} +\`\`\` + +__Dynamic arguments__: +Are performed via FlowData repository and can be used for URL address or for custom headers/cookies/auth. Use \`repository\` component for creating of dynamic arguments. Dynamic values are replaced in the form \`{key}\`: + +- url address e.g. \`https://.../{key}/\` +- headers values e.g. \`{token}\` +- cookies values e.g. \`{token}\``; + +exports.install = function(instance) { + + var can = false; + var flags = null; + var cookies2 = null; + + instance.on('data', function(response) { + can && instance.custom.send(response); + }); + + instance.custom.send = function(response) { + var options = instance.options; + + var headers = null; + var cookies = null; + + options.headers && Object.keys(options.headers).forEach(function(key) { + !headers && (headers = {}); + headers[key] = response.arg(options.headers[key]); + }); + + if (options.username && options.userpassword) { + !headers && (headers = {}); + headers['Authorization'] = 'Basic ' + U.createBuffer(response.arg(options.username + ':' + options.userpassword)).toString('base64'); + } + + options.cookies && Object.keys(options.cookies).forEach(function(key) { + !cookies && (cookies = {}); + cookies[key] = response.arg(options.cookies[key]); + }); + + if (options.chunks) { + U.download(response.arg(options.url), flags, options.stringify === 'none' ? null : response.data, function(err, response) { + response.on('data', (chunks) => instance.send2(chunks)); + }, cookies || cookies2, headers); + } else { + U.request(response.arg(options.url), flags, options.stringify === 'none' ? null : response.data, 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) + instance.error(err, response); + }, cookies || cookies2, headers); + } + }; + + instance.reconfigure = function() { + var options = instance.options; + can = options.url && options.url && options.method && options.stringify ? true : false; + instance.status(can ? '' : 'Not configured', can ? undefined : 'red'); + + if (!can) + return; + + flags = []; + flags.push(options.method.toLowerCase()); + options.stringify === 'json' && flags.push('json'); + options.stringify === 'raw' && flags.push('raw'); + options.keepalive && flags.push('keepalive'); + !options.nodns && flags.push('dnscache'); + if (options.persistentcookies) { + flags.push('cookies'); + cookies2 = {}; + } else + cookies2 = null; + }; + + instance.on('options', instance.reconfigure); + instance.reconfigure(); +}; \ No newline at end of file diff --git a/RVO25/flow_15_1_2025/httpresponse.js b/RVO25/flow_15_1_2025/httpresponse.js new file mode 100755 index 0000000..160a3bb --- /dev/null +++ b/RVO25/flow_15_1_2025/httpresponse.js @@ -0,0 +1,76 @@ +exports.id = 'httpresponse'; +exports.title = 'HTTP Response'; +exports.group = 'HTTP'; +exports.color = '#5D9CEC'; +exports.icon = 'arrow-right'; +exports.input = true; +exports.output = ['#666D76']; +exports.version = '2.0.0'; +exports.author = 'Martin Smola'; +exports.readme = `# HTTP response + +HTTP response will respond with data recieved using data-type set in Settings form or plain text if not set. Output is the message duration \`Number\` in seconds.`; + +exports.html = `
+
@(Response data-type)
+
JSON is by default.
+
`; + +exports.install = function(instance) { + + var dursum = 0; + var durcount = 0; + + instance.on('data', function(flowdata) { + + var ctrl = flowdata.repository.controller; + var data = flowdata.data; + + if (!ctrl) { + instance.throw('No controller to use for response!'); + return; + } + + durcount++; + dursum += ((new Date() - flowdata.begin) / 1000).floor(2); + setTimeout2(instance.id, instance.custom.duration, 500, 10); + + ctrl.$flowdata = flowdata; + + var datatype = instance.options.datatype || 'json'; + if (datatype === 'emptyresponse') + return ctrl.plain(''); + + if (datatype !== 'json' && typeof(data) !== 'string') { + instance.throw('Incorect type of data, expected string, got ' + typeof(data)); + ctrl.plain(data == null ? '' : data.toString()); + return; + } + + switch(datatype) { + case 'html': + ctrl.content(data, 'text/html'); + break; + case 'plain': + ctrl.plain(data); + break; + case 'xml': + ctrl.content(data, 'text/xml'); + break; + default: + ctrl.json(data); + break; + } + }); + + instance.on('service', function() { + dursum = 0; + durcount = 0; + }); + + instance.custom.duration = function() { + var avg = (dursum / durcount).floor(2); + instance.status(avg + ' sec.'); + instance.send2(0, avg); + }; +}; diff --git a/RVO25/flow_15_1_2025/httproute.js b/RVO25/flow_15_1_2025/httproute.js new file mode 100755 index 0000000..583a19d --- /dev/null +++ b/RVO25/flow_15_1_2025/httproute.js @@ -0,0 +1,326 @@ +exports.id = 'httproute'; +exports.title = 'HTTP Route'; +exports.group = 'HTTP'; +exports.color = '#5D9CEC'; +exports.icon = 'globe'; +exports.input = false; +exports.output = ['#6CAC5A', '#37BC9B']; +exports.version = '1.2.3'; +exports.author = 'Martin Smola'; +exports.cloning = false; +exports.options = { method: 'GET', url: '', size: 5, cacheexpire: '5 minutes', cachepolicy: 0, timeout: 5 }; +exports.dateupdated = '2021-01-21 18:30d'; +exports.readme = `# HTTP route + +__Outputs__: +- first output: raw data (cache is empty or is disabled) +- second output: cached data + +If one of the outputs is disabled then automatic responce with code "503 service unavailable" is sent. + +When a request comes in bellow object is available at \`flowdata.data\`: + +\`\`\`javascript +{ + params: { id: '1' }, // params for dynamic routes, e.g. /test/{id} + query: { msg: 'Hello' }, // parsed query string, e.g. /test/1?msg=Hello + body: { test: 'OK' }, // object if json requests otherwise string + headers: {}, // headers data + session: {}, // session data + user: {}, // user data + files: [], // uploaded files + url: '/users/', // a relative URL address + referrer: '/', // referrer + mobile: false, // determines mobile device + robot: false, // determines search robots/crawlsers + language: 'en' // determines language +} +\`\`\` + +See [documentation for flags](https://docs.totaljs.com/latest/en.html#api~HttpRouteOptionsFlags~unauthorize). These method flags are set automatically e.g. \`get, post, put, patch or delete\` + +--- + +\`id:ROUTE_ID\` flag cannot be used since it's already used by this component internally`; + +exports.html = `
+
+ +
+ +
+
+
@(HTTP method)
+
+
+
@(URL address)
+
+
+
+
+
@(Additional flags)
+
@(Separate flags by comma e.g. json, authorize)
+
+
+
@(Max. request size)
+
@(In kB kilobytes)
+
+
+
@(Timeout)
+
@(In seconds.)
+
+
+
+
+
+
@(Automatically respond with 200 OK?)
+
@(If not checked you need to use HTTP response component to respond to the request.)
+
+
@(Custom headers)
+
@(Cookies)
+
+
+
+
+
+
@(Cache policy)
+
@(User instance must contain id property.)
+
+
+
@(Expiration)
+
@(E.g. 5 minutes)
+
+
+
+`; + +exports.install = function(instance) { + + var route; + + var uninstall = function(id) { + if (F.is4) { + route && route.remove(); + route = null; + } else + UNINSTALL('route', id); + }; + + instance.custom.emptyresponse = function(self) { + self.plain(); + }; + + instance.reconfigure = function() { + + var options = instance.options; + + if (!options.url) { + instance.status('Not configured', 'red'); + return; + } + + if (typeof(options.flags) === 'string') + options.flags = options.flags.split(',').trim(); + + uninstall('id:' + instance.id); + + var flags = options.flags || []; + + flags.push('id:' + instance.id); + + if (!F.is4) + flags.push(options.method.toLowerCase()); + + options.timeout && flags.push(options.timeout * 1000); + + // Make unique values + flags = flags.filter(function(v, i, a) { + if(F.is4 && v.toString().toLowerCase() === options.method.toLowerCase()) + return false; // remove method + return a.indexOf(v) === i; + }); + + options.flags = flags; + var handler = function() { + + if (instance.paused || (instance.isDisabled && (instance.isDisabled('output', 0) || instance.isDisabled('output', 1)))) { + instance.status('503 Service Unavailable'); + this.status = 503; + this.json(); + return; + } + + var key; + var self = this; + + if (instance.options.emptyresponse) { + instance.status('200 OK'); + setTimeout(instance.custom.emptyresponse, 100, self); + + if (instance.hasConnection(0)) { + var data = instance.make({ + query: self.query, + body: self.body, + session: self.session, + user: self.user, + files: self.files, + headers: self.req.headers, + url: self.url, + params: self.params + }); + instance.send2(0, data); + } + + return; + } + + switch (instance.options.cachepolicy) { + case 1: // URL + key = 'rro' + instance.id + self.url.hash(); + break; + case 2: // URL + query + case 3: // URL + query + user + key = self.url; + var keys = Object.keys(self.query); + keys.sort(); + for (var i = 0, length = keys.length; i < length; i++) + key += keys[i] + self.query[keys[i]] + '&'; + if (instance.options.cachepolicy === 3 && self.user) + key += 'iduser' + self.user.id; + key = 'rro' + instance.id + key.hash(); + break; + } + + if (key && F.cache.get2(key)) { + var data = instance.make(F.cache.get2(key)); + data.repository.controller = self; + instance.send2(1, data); + } else { + + var data = instance.make({ + query: self.query, + body: self.body, + session: self.session, + user: self.user, + files: self.files, + headers: self.req.headers, + url: self.url, + params: self.params, + mobile: self.mobile, + robot: self.robot, + referrer: self.referrer, + language: self.language + }); + + data.repository.controller = self; + instance.send2(0, data); + key && FINISHED(self.res, () => F.cache.set(key, self.$flowdata.data, instance.options.cacheexpire)); + } + }; + + if (F.is4) + route = ROUTE(options.method.toUpperCase() + ' ' + options.url, handler, flags, options.size || 5); + else + F.route(options.url, handler, flags, options.size || 5); + + instance.status('Listening', 'green'); + }; + + instance.reconfigure(); + instance.on('options', instance.reconfigure); + instance.on('close', function(){ + uninstall('id:' + instance.id); + }); +}; + +// check url exists +FLOW.trigger('httproutecheckurl', function(next, data) { + var url = data.url; + var method = data.method; + if (url[url.length - 1] !== '/') + url += '/'; + var exists = F.routes.web.findItem(r => r.urlraw === url && r.method === method); + next(exists != null); +}); + +exports.uninstall = function() { + FLOW.trigger('httproutecheckurl', null); +}; diff --git a/RVO25/flow_15_1_2025/infosender.js b/RVO25/flow_15_1_2025/infosender.js new file mode 100755 index 0000000..c7afd83 --- /dev/null +++ b/RVO25/flow_15_1_2025/infosender.js @@ -0,0 +1,101 @@ +exports.id = 'infosender'; +exports.title = 'Info sender'; +exports.version = '1.0.0'; +exports.group = 'Worksys'; +exports.color = '#2134B0'; +exports.input = 2; +exports.output = 1 +exports.icon = 'bolt'; + +const { networkInterfaces } = require('os'); + +exports.html = `
+
+
+
CSV Import
+
+
+
`; + +exports.readme = `# send all data to projects.worksys.io, required to monitor status of controller(unipi)`; + +exports.install = function(instance) { + + let id; + let allValues = {}; + let sendAllValuesInterval; + let configured = false; + + let now = new Date(); + console.log(exports.title, "INSTALLED", now.toLocaleString("sk-SK")); + + const nets = networkInterfaces(); + let ipAddresses = Object.create(null); // Or just '{}', an empty object + + for (const name of Object.keys(nets)) { + for (const net of nets[name]) { + // Skip over non-IPv4 and internal (i.e. 127.0.0.1) addresses + if (net.family === 'IPv4' && !net.internal) { + if (!ipAddresses[name]) { + ipAddresses[name] = []; + } + ipAddresses[name].push(net.address); + } + } + } + + function sendValues() + { + if(!configured) return; + + if(Object.keys(allValues).length > 0) + { + if(id) + { + delete allValues.__force__; + let dataToSend = {...allValues}; + dataToSend.id = id; + dataToSend.ipAddresses = ipAddresses; + + instance.send(0, dataToSend); + + allValues = {}; + } + else + { + console.log(exports.title, "unable to send data, no id"); + } + + } + } + + instance.on("close", () => { + clearInterval(sendAllValuesInterval); + }) + + instance.on("0", _ => { + id = FLOW.GLOBALS.settings.project_id; + configured = true; + }) + + instance.on("1", flowdata => { + + allValues = { ...allValues, ...flowdata.data}; + //console.log("DATA RECEIVED", flowdata.data); + + //__force__ + if(flowdata.data.hasOwnProperty("__force__")) + { + if(flowdata.data.__force__) + { + sendValues(); + } + } + }) + + sendAllValuesInterval = setInterval(() => { + sendValues(); + }, 60000*3); + +} + diff --git a/RVO25/flow_15_1_2025/modbus_reader.js b/RVO25/flow_15_1_2025/modbus_reader.js new file mode 100755 index 0000000..b907148 --- /dev/null +++ b/RVO25/flow_15_1_2025/modbus_reader.js @@ -0,0 +1,367 @@ +exports.id = 'modbus_reader'; +exports.title = 'Modbus reader'; +exports.version = '2.0.0'; +exports.group = 'Worksys'; +exports.color = '#2134B0'; +exports.input = 1; +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; +//number of phases inRVO +let phases; +//phases where voltage is 0 (set) +let noVoltage; + +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.phases = this.buildPhases(); + + this.startSocket(); + } + + buildPhases = () => { + let a = []; + for (let i = 1; i<= phases; i++) { + a.push(`Phase_${i}_voltage`) + } + return a; + } + + 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 (this.phases.includes(singleValue)) + { + let l = singleValue.split("_"); + let phase = parseInt(l[1]); + + // console.log(values[singleValue], tbName); + + if(values[singleValue] == 0) + { + noVoltage.add(phase); + sendNotification("modbus_reader: checkNullVoltage", tbName, "no_voltage_on_phase", {phase: phase}, "", SEND_TO.tb, instance, "voltage" + phase ); + // console.log('no voltage') + } + else + { + noVoltage.delete(phase); + // console.log('voltage detected') + sendNotification("modbus_reader: checkNullVoltage", tbName, "voltage_on_phase_restored", {phase: phase}, "", SEND_TO.tb, instance, "voltage" + phase); + } + } + }) + } + + /** + * function sends notification to slack and to tb, if EM total_power value changes more than numberOfNodes*15. This should show, that RVO lamps has been switched on or off + */ + lampSwitchNotification = (values) => { + + if(!values.hasOwnProperty("total_power")) return; + + const actualTotalPower = values.total_power; + + const numberOfNodes = Object.keys(FLOW.GLOBALS.nodesData).length; + if(numberOfNodes == 0) numberOfNodes = 20; // to make sure, we send notification if totalPower is more than 300 + + if(actualTotalPower > numberOfNodes * 15 && this.onNotificationSent == false) + { + sendNotification("modbus_reader: lampSwitchNotification", tbName, "lamps_have_turned_on", {}, "", SEND_TO.tb, instance); + this.onNotificationSent = true; + this.offNotificationSent = false; + } + else if(actualTotalPower <= numberOfNodes * 15 && this.offNotificationSent == false) + { + 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; + } + + function main() { + + phases = FLOW.GLOBALS.settings.phases; + tbName = FLOW.GLOBALS.settings.rvoTbName; + noVoltage = FLOW.GLOBALS.settings.no_voltage; + mainSocket = new SocketWithClients(); + + // this notification is to show, that flow (unipi) has been restarted + sendNotification("modbus_reader", tbName, "flow_restart", {}, "", SEND_TO.slack, instance); + } + + instance.on("0", function(_) { + main(); + }) + +} + diff --git a/RVO25/flow_15_1_2025/monitorconsumption.js b/RVO25/flow_15_1_2025/monitorconsumption.js new file mode 100755 index 0000000..64cc58e --- /dev/null +++ b/RVO25/flow_15_1_2025/monitorconsumption.js @@ -0,0 +1,156 @@ +exports.id = 'monitorconsumption'; +exports.title = 'Consumption'; +exports.version = '1.0.0'; +exports.author = 'Peter Širka'; +exports.group = 'Monitoring'; +exports.color = '#967ADC'; +exports.input = 0; +exports.output = 1; +exports.icon = 'bug'; +exports.options = { interval: 5000, enabled: true, monitorconsumption: true, monitorsize: true, monitorconnections: true, monitorfiles: true }; +exports.click = true; +exports.readme = `# Consumption monitoring + +This component measure CPU and memory consumption, open files and open connections of this application. It uses these Linux commands: \`ps\`, \`lsof\`, \`netstat\` and \`df\`. + +__Data Example__: + +\`\`\`javascript +{ + cpu: 0, // percentage + memory: 4096, // in bytes + size: 34303, // directory size in bytes + files: 34, // count of open files + connections: 343, // count of connections + uptime: '1-12:34:00' +} +\`\`\``; + +exports.html = `
+
+
+
@(Interval in milliseconds)
+
+
+
+
Monitor: Consumption + uptime
+
Monitor: Count of open files
+
Monitor: Count of open connections
+
Monitor: Directory size
+
`; + +exports.install = function(instance) { + + var current = { cpu: 0, memory: 0, files: 0, connections: 0, size: 0, uptime: '', counter: 0 }; + var tproc = null; + var Exec = require('child_process').exec; + var reg_empty = /\s{2,}/g; + var reg_appdisksize = /^[\d.,]+/; + + instance.custom.run = function() { + + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + + var arr = []; + + // Get CPU and Memory consumption + instance.options.monitorconsumption && arr.push(function(next) { + Exec('ps -p {0} -o %cpu,rss,etime'.format(process.pid), function(err, response) { + + if (err) { + instance.throw(err); + } else { + var line = response.split('\n')[1]; + line = line.trim().replace(reg_empty, ' ').split(' '); + var cpu = line[0].parseFloat(); + current.cpu = cpu.floor(1); + current.memory = line[1].parseInt2() * 1024; // kB to bytes + current.uptime = line[2]; + } + + next(); + }); + }); + + // Get count of open files + instance.options.monitorfiles && arr.push(function(next) { + Exec('lsof -a -p {0} | wc -l'.format(process.pid), function(err, response) { + if (err) + instance.throw(err); + else + current.files = response.trim().parseInt2(); + next(); + }); + }); + + // Get count of opened network connections + instance.options.monitorconnections && arr.push(function(next) { + Exec('netstat -an | grep :{0} | wc -l'.format(F.port), function(err, response) { + if (err) { + instance.throw(err); + } else { + current.connections = response.trim().parseInt2() - 1; + if (current.connections < 0) + current.connections = 0; + } + next(); + }); + }); + + // Get directory size + instance.options.monitorsize && current.counter % 5 !== 0 && arr.push(function(next) { + Exec('du -hsb ' + process.cwd(), function(err, response) { + if (err) { + instance.throw(err); + } else { + var match = response.trim().match(reg_appdisksize); + match && (current.size = match.toString().trim().parseInt2()); + } + next(); + }); + }); + + arr.async(function() { + + tproc && clearTimeout(tproc); + + if (instance.options.enabled) { + tproc = setTimeout(instance.custom.run, instance.options.interval); + instance.send2(current); + } + + instance.custom.status(); + current.counter++; + }); + }; + + instance.custom.status = function() { + if (instance.options.enabled) + instance.status('{0}% / {1}'.format(current.cpu, current.memory.filesize())); + else + instance.status('Disabled', 'red'); + }; + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + + if (instance.options.enabled) { + current.counter = 0; + instance.custom.run(); + } + + }); + + instance.on('close', function() { + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + }); + + setTimeout(instance.custom.run, 1000); +}; \ No newline at end of file diff --git a/RVO25/flow_15_1_2025/monitordisk.js b/RVO25/flow_15_1_2025/monitordisk.js new file mode 100755 index 0000000..f4fdaa0 --- /dev/null +++ b/RVO25/flow_15_1_2025/monitordisk.js @@ -0,0 +1,96 @@ +exports.id = 'monitordisk'; +exports.title = 'Disk'; +exports.version = '1.0.0'; +exports.author = 'Peter Širka'; +exports.group = 'Monitoring'; +exports.color = '#F6BB42'; +exports.output = 1; +exports.icon = 'hdd-o'; +exports.click = true; +exports.options = { interval: 8000, path: '/', enabled: true }; +exports.readme = `# Disk monitoring + +This component monitors disk \`bytes\` consumption in Linux systems. It uses \`df\` command. + +__Data Example__: + +\`\`\`javascript +{ + total: 474549649408, + used: 39125245952, + free: 411294994432 +} +\`\`\``; + +exports.html = `
+
+
+
@(Interval in milliseconds)
+
+
+
@(Path)
+
+
+
`; + +exports.install = function(instance) { + + var current = { total: 0, used: 0, free: 0, path: '', type: '', percentUsed: 0 }; + var tproc = null; + + instance.custom.run = function() { + + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + + if (!instance.options.enabled) + return; + + require('child_process').exec('df -hTB1 ' + instance.options.path, function(err, response) { + + tproc = setTimeout(instance.custom.run, instance.options.interval); + + if (err) { + instance.error(err); + return; + } + + response.parseTerminal(function(line) { + if (line[0][0] !== '/') + return; + current.total = line[2].parseInt(); + current.free = line[4].parseInt(); + current.used = line[3].parseInt(); + current.path = instance.options.path || '/'; + current.type = line[1]; + current.percentUsed = line[5]; + instance.custom.status(); + instance.send2(current); + }); + }); + }; + + instance.custom.status = function() { + if (instance.options.enabled) + instance.status(current.free.filesize() + ' / ' + current.total.filesize()); + else + instance.status('Disabled', 'red'); + }; + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + instance.options.enabled && instance.custom.run(); + }); + + instance.on('close', function() { + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + }); + + setTimeout(instance.custom.run, 1000); +}; \ No newline at end of file diff --git a/RVO25/flow_15_1_2025/monitormemory.js b/RVO25/flow_15_1_2025/monitormemory.js new file mode 100755 index 0000000..2decbc4 --- /dev/null +++ b/RVO25/flow_15_1_2025/monitormemory.js @@ -0,0 +1,87 @@ +exports.id = 'monitormemory'; +exports.title = 'Memory'; +exports.version = '1.0.0'; +exports.author = 'Peter Širka'; +exports.group = 'Monitoring'; +exports.color = '#F6BB42'; +exports.output = 1; +exports.click = true; +exports.icon = 'microchip'; +exports.options = { interval: 8000, enabled: true }; +exports.readme = `# Memory monitoring + +This component monitors memory \`bytes\` consumption in Linux systems. It uses \`free\` command. + +__Data Example__: + +\`\`\`javascript +{ + total: 33558769664, + used: 1998868480, + free: 2653708288 +} +\`\`\``; + +exports.html = `
+
+
+
@(Interval in milliseconds)
+
+
+
`; + +exports.install = function(instance) { + + var current = { total: 0, used: 0, free: 0 }; + var tproc = null; + + instance.custom.run = function() { + + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + + if (!instance.options.enabled) + return; + + require('child_process').exec('free -b -t', function(err, response) { + + tproc = setTimeout(instance.custom.run, instance.options.interval); + + if (err) { + instance.error(err); + return; + } + + var memory = response.split('\n')[1].match(/\d+/g); + current.total = memory[0].parseInt(); + current.used = memory[1].parseInt() - memory[3].parseInt(); + current.free = current.total - current.used; + instance.custom.status(); + instance.send2(current); + }); + }; + + instance.custom.status = function() { + if (instance.options.enabled) + instance.status(current.free.filesize() + ' / ' + current.total.filesize()); + else + instance.status('Disabled', 'red'); + }; + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + instance.options.enabled && instance.custom.run(); + }); + + instance.on('close', function() { + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + }); + + setTimeout(instance.custom.run, 1000); +}; \ No newline at end of file diff --git a/RVO25/flow_15_1_2025/nodesdb_changecheck.js b/RVO25/flow_15_1_2025/nodesdb_changecheck.js new file mode 100755 index 0000000..be1e700 --- /dev/null +++ b/RVO25/flow_15_1_2025/nodesdb_changecheck.js @@ -0,0 +1,70 @@ +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/RVO25/flow_15_1_2025/show_dbdata.js b/RVO25/flow_15_1_2025/show_dbdata.js new file mode 100755 index 0000000..d01eecd --- /dev/null +++ b/RVO25/flow_15_1_2025/show_dbdata.js @@ -0,0 +1,241 @@ +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 = 7; +exports.output = 1; + +const { exec } = require('child_process'); + +exports.install = 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}) + }) + instance.on("5", _ => { + exec("sudo tail -n 25 monitor.txt" , (err, stdout, stderr) => { + if (err || stderr) instance.send(0,{err, stderr}); + else instance.send(0,stdout); + }) + }) + instance.on("6", _ => { + exec("sudo tail -n 25 err.txt" , (err, stdout, stderr) => { + if (err || stderr) instance.send(0,{err, stderr}); + else instance.send(0,stdout); + }) + }) +}; + + + +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/RVO25/flow_15_1_2025/slack_filter.js b/RVO25/flow_15_1_2025/slack_filter.js new file mode 100755 index 0000000..753c24a --- /dev/null +++ b/RVO25/flow_15_1_2025/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 = `
+
+
+
@(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"] = []; + } + + instance.options.name = FLOW.GLOBALS.settings.rvo_name; + if (instance.options.name) { + instance.status('Running'); + running = true; + } else { + instance.status('Please run options again', 'red'); + running = false; + } + } catch (e) { + instance.error('Citysys connector: ' + e.message); + } + }; + + instance.on('options', instance.reconfigure); + setTimeout(instance.reconfigure, 10000); + + +}; diff --git a/RVO25/flow_15_1_2025/thermometer.js b/RVO25/flow_15_1_2025/thermometer.js new file mode 100755 index 0000000..fa015c6 --- /dev/null +++ b/RVO25/flow_15_1_2025/thermometer.js @@ -0,0 +1,98 @@ +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 = 5;//minutes +let NUMBER_OF_FAILURES_TO_SEND_ERROR = 13; + +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) => { + + 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); + setTimeout(main, 20000); + }) +}; diff --git a/RVO25/flow_15_1_2025/trigger.js b/RVO25/flow_15_1_2025/trigger.js new file mode 100755 index 0000000..27545a8 --- /dev/null +++ b/RVO25/flow_15_1_2025/trigger.js @@ -0,0 +1,79 @@ +exports.id = 'trigger'; +exports.title = 'Trigger'; +exports.group = 'Inputs'; +exports.color = '#F6BB42'; +exports.click = true; +exports.output = 1; +exports.version = '1.1.0'; +exports.author = 'Martin Smola'; +exports.icon = 'play'; + +exports.html = `
+
@(Data type (String by default))
+
@(Data)
+
Trigger 5s after initialization.
+
@(Useful when there's a need to run certain flow when the app restarts, etc.)
+
`; + +exports.readme = `# Trigger + +- Clicking on the component starts the chain +- Settings allows to set a data-type and a value`; + +exports.install = function(instance) { + + var value; + + instance.on('click', () => instance.send2(value)); + + instance.reconfigure = function() { + var options = instance.options; + value = null; + switch (options.datatype) { + case 'integer': + value = options.data.parseInt2('error'); + value = value === 'error' ? NaN : value; + break; + case 'float': + value = options.data.parseFloat2('error'); + value = value === 'error' ? NaN : value; + break; + case 'date': + options.data = options.data.toString(); + var num = options.data.parseInt('error'); + num === 'error' && (num = options.data.parseDate('error')); + num === 'error' && (num = null); + value = num ? new Date(num).toUTCString() : num; + break; + case 'object': + try { + value = (new Function('return ' + options.data))(); + } catch (e) { + instance.error(e); + } + break; + case 'boolean': + value = options.data.parseBoolean(); + break; + case 'buffer': + try { + value = U.createBuffer(options.data); + } catch (e) { + instance.error(e); + } + break; + case 'string': + default: + value = '' + (options.data || ''); + break; + } + }; + + instance.on('options', instance.reconfigure); + instance.reconfigure(); + + if (instance.options.restart) + setTimeout(function(){ + instance.send2(value); + }, 5000); +}; diff --git a/RVO25/flow_15_1_2025/virtualwirein.js b/RVO25/flow_15_1_2025/virtualwirein.js new file mode 100755 index 0000000..38a4e42 --- /dev/null +++ b/RVO25/flow_15_1_2025/virtualwirein.js @@ -0,0 +1,43 @@ +exports.id = 'virtualwirein'; +exports.title = 'Virtual wire in'; +exports.version = '1.0.0'; +exports.author = 'Martin Smola'; +exports.color = '#303E4D'; +exports.icon = 'sign-in'; +exports.input = false; +exports.output = 1; +exports.options = {}; +exports.readme = `# Virtual wire in + +When the wires between the components are mess it's time to use Virtual wire.`; + +exports.html = `
+
@(Wire name)
+
+`; + +exports.install = function(instance) { + + instance.custom.reconfigure = function(options){ + if (instance.options.wirename) { + instance.status(instance.options.wirename); + } else + instance.status('Not configured', 'red'); + }; + + ON('virtualwire', function(wirename, flowdata){ + if (instance.options.wirename && instance.options.wirename === wirename) + instance.send(flowdata); + }); + + instance.on('options', instance.custom.reconfigure); + instance.custom.reconfigure(); +}; diff --git a/RVO25/flow_15_1_2025/virtualwireout.js b/RVO25/flow_15_1_2025/virtualwireout.js new file mode 100755 index 0000000..94a1e4f --- /dev/null +++ b/RVO25/flow_15_1_2025/virtualwireout.js @@ -0,0 +1,41 @@ +exports.id = 'virtualwireout'; +exports.title = 'Virtual wire out'; +exports.version = '1.0.0'; +exports.author = 'Martin Smola'; +exports.color = '#303E4D'; +exports.icon = 'sign-out'; +exports.input = true; +exports.options = {}; +exports.readme = `# Virtual wire out + +When the wires between the components are mess it's time to use Virtual wire.`; + +exports.html = `
+
@(Wire name)
+
+`; + +exports.install = function(instance) { + + instance.custom.reconfigure = function(){ + if (instance.options.wirename) { + instance.status(instance.options.wirename); + } else + instance.status('Not configured', 'red'); + }; + + instance.on('data', function(flowdata) { + EMIT('virtualwire', instance.options.wirename, flowdata); + }); + + instance.on('options', instance.custom.reconfigure); + instance.custom.reconfigure(); +}; diff --git a/RVO25/flow_15_1_2025/wsmqttpublish.js b/RVO25/flow_15_1_2025/wsmqttpublish.js new file mode 100755 index 0000000..b2a218d --- /dev/null +++ b/RVO25/flow_15_1_2025/wsmqttpublish.js @@ -0,0 +1,477 @@ +exports.id = 'wsmqttpublish'; +exports.title = 'WS MQTT publish'; +exports.group = 'MQTT'; +exports.color = '#888600'; +exports.version = '1.0.2'; +exports.icon = 'sign-out'; +exports.input = 2; +exports.output = 3; +exports.options = { host: 'tb-stage.worksys.io', port: 1883, clientid: "", username: "" }; + +exports.html = `
+
+
+
Hostname or IP address (if not empty - setting will override db setting)
+
+
+
Port
+
+
+
+
+
@(Client id)
+
+
+
@(Username)
+
+
+
`; + + +exports.readme = ` +# WS MQTT Publish + +Version 1.0.3. + +Added: +- database collections, +- 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 = { + debug: 0, + rpcCall: 1, + services: 2 +} + +//CONFIG +let createTelemetryBackup = true; +let saveTelemetryOnError = true;//backup_on_failure overrides this value +//------------------------ + +let rollers; +if(createTelemetryBackup) rollers = require('streamroller'); + +const noSqlFileSizeLimit = 4194304;//use 5MB - 4194304 +let insertNoSqlCounter = 0; +let insertBackupNoSqlCounter = 0; +let processingData = false; + +let backup_on_failure = false;//== saveTelemetryOnError - create backup client 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; + +process.on('uncaughtException', function (err) { + + errLogger.error('uncaughtException:', err.message) + errLogger.error(err.stack); + + //TODO + //send to service + + //process.exit(1); +}) + +const nosql = NOSQL('tbdata'); +const nosqlBackup = NOSQL('/backup/tbdata'); + + +exports.install = function(instance) { + + var client; + var opts; + var clientReady = false; + + // wsmqtt status for notification purposes on projects.worksys.io database + let wsmqttName = null; + let sendWsStatusVar = null; + let wsmqtt_status = 'disconnected'; + + 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'; + } + + function sendWsStatus() + { + instance.send(SEND_TO.services, {[wsmqttName]: wsmqtt_status}); + } + + + function main() + { + if(!FLOW.dbLoaded) return; + + loadSettings(); + clearInterval(sendWsStatus); + sendWsStatusVar = setInterval(sendWsStatus, 180000); + } + + //set opts according to db settings + function loadSettings() + { + + if(instance.options.host !== "") + { + //override settings from database + var o = instance.options; + opts = { + host: o.host, + port: o.port, + clientId: o.clientid, + username: o.username, + rejectUnauthorized: false, + resubscribe: false + }; + + wsmqttName = getWsmqttName(o.host); + + console.log("wsmqttpublich -> loadSettings from instance.options", instance.options); + } + else + { + + const SETTINGS = FLOW.GLOBALS.settings; + backup_on_failure = SETTINGS.backup_on_failure; + saveTelemetryOnError = backup_on_failure; + + restore_from_backup = SETTINGS.restore_from_backup; + restore_backup_wait = SETTINGS.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; + + opts = { + host: mqtt_host, + port: mqtt_port, + keepalive: 10, + clientId: mqtt_clientid, + username: mqtt_username, + rejectUnauthorized: false, + resubscribe: false + }; + + wsmqttName = getWsmqttName(mqtt_host); + } + + connectToTbServer(); + } + + function connectToTbServer() + { + 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"); + monitor.info("MQTT client connected"); + + sendClientError = true; + clientReady = true; + wsmqtt_status = 'connected'; + }); + + client.on('reconnect', function() { + instance.status("Reconnecting", "yellow"); + clientReady = false; + }); + + client.on('message', function(topic, message) { + // message is type of buffer + message = message.toString(); + if (message[0] === '{') { + TRY(function() { + + message = JSON.parse(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}}); + } + + }, () => instance.debug('MQTT: Error parsing data', message)); + } + + instance.send(SEND_TO.rpcCall, {"topic":topic, "content":message }); + }); + + client.on('close', function() { + clientReady = false; + wsmqtt_status = 'disconnected'; + + instance.status("Disconnected", "red"); + instance.send(SEND_TO.debug, {"message":"Client CLOSE signal received !"}); + }); + + client.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; + wsmqtt_status = 'disconnected'; + }); + + } + + + instance.on("0", _ => { + main(); + }) + + + instance.on('1', function(data) { + + if(clientReady) + { + //do we have some data in backup file? if any, process data from database + if(saveTelemetryOnError) + { + //read telemetry data and send back to server + if(!processingData) processDataFromDatabase(); + } + + let stringifiedJson = JSON.stringify(data.data); + client.publish("v1/gateway/telemetry", stringifiedJson, {qos: 1}); + + //backup telemetry + if(createTelemetryBackup) + { + data.data.id = UID(); + nosqlBackup.insert(data.data); + + insertBackupNoSqlCounter++; + if(insertBackupNoSqlCounter > 150) + { + let options = {compress: true}; + let path = __dirname + "/../databases/backup/tbdata.nosql"; + var stream = new rollers.RollingFileStream(path, noSqlFileSizeLimit, 150, options); + stream.write(""); + stream.end(); + + insertBackupNoSqlCounter = 0; + } + } + + } + 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(saveTelemetryOnError) + { + //create new file from tbdata.nosql, if file size exceeds given limit, and clear tbdata.nosql + makeBackupFromDbFile(); + + //write to tb + data.data.id = UID(); + nosql.insert(data.data); + } + } + }); + + + instance.close = function(done) { + if(clientReady){ + client.end(); + clearInterval(sendWsStatusVar); + } + }; + + + function getDbBackupFileCounter(type) + { + var files = fs.readdirSync(__dirname + "/../databases"); + + let counter = 0; + for(var i = 0; i < files.length; i++) + { + + if(files[i] == "tbdata.nosql") continue; + + if(files[i].endsWith(".nosql")) + { + + let pos = files[i].indexOf("."); + if(pos > -1) + { + + let fileCounter = counter; + let firstDigit = files[i].slice(0, pos); + + fileCounter = parseInt(firstDigit); + if(isNaN(fileCounter)) fileCounter = 0; + //console.log("getDbBackupFileCounter digit:", files[i], firstDigit, fileCounter, isNaN(fileCounter), type); + + if(type == "max") + { + if(fileCounter > counter) + { + counter = fileCounter; + } + } + else if(type == "min") + { + if(counter == 0) counter = fileCounter; + + if(fileCounter < counter) + { + counter = fileCounter; + } + } + } + } + + } + + if(type == "max") counter++; + + return counter; + } + + const makeBackupFromDbFile = async () => { + + if(!saveTelemetryOnError) return; + + //to avoid large file: tbdata.nosql + + //init value is 0! + if(insertNoSqlCounter > 0) + { + --insertNoSqlCounter; + return; + } + + insertNoSqlCounter = 100; + + let source = __dirname + "/../databases/tbdata.nosql"; + + var stats = fs.statSync(source); + var fileSizeInBytes = stats.size; + + if(fileSizeInBytes > noSqlFileSizeLimit) + { + + let counter = 1; + counter = getDbBackupFileCounter("max"); + + let destination = __dirname + "/../databases/" + counter + "." + "tbdata.nosql"; + + //make backup file + fs.copyFileSync(source, destination); + //fs.renameSync(p, p + "." + counter); + + //clear tbdata.nosql + fs.writeFileSync(source, ""); + fs.truncateSync(source, 0); + + } + } + + const processDataFromDatabase = async () => { + + if(restore_from_backup <= 0) return; + + //calculate diff + const now = new Date(); + let currentTime = now.getTime(); + let diff = currentTime - lastRestoreTime; + + if( (diff / 1000) < restore_backup_wait) + { + //console.log("*********restore_backup_wait", diff, restore_backup_wait); + return; + } + + processingData = true; + + //get filename to process + let counter = getDbBackupFileCounter("min"); + + //we have some backup files + let dataBase = 'tbdata'; + + var nosql; + if(counter == 0) dataBase = 'tbdata'; + else dataBase = counter + "." + 'tbdata'; + + nosql = NOSQL(dataBase); + + //select all data - use limit restore_from_backup + let records = await promisifyBuilder(nosql.find().take(restore_from_backup)); + + for(let i = 0; i < records.length; i++) + { + if(clientReady) { + + let item = records[i]; + let id = item.id; + + if(id !== undefined) + { + //console.log("------------processDataFromDatabase - remove", id, dataBase, i); + + try { + + let message = JSON.parse(JSON.stringify(item)); + delete message.id; + + client.publish("v1/gateway/telemetry", JSON.stringify(message), {qos:1}); + + //remove from database + await promisifyBuilder(nosql.remove().where("id", id)); + + } catch(error) { + //process error + console.log("processDataFromDatabase", error); + } + + } + + } + else + { + processingData = false; + return; + } + } + + if(records.length > 0) + { + //clean backup file + if(counter > 0) nosql.clean(); + } + + //no data in db, remove + if(records.length == 0) + { + if(counter > 0) nosql.drop(); + } + + const d = new Date(); + lastRestoreTime = d.getTime(); + + processingData = false; + + } + + instance.on('options', main); + //instance.reconfigure(); +}; diff --git a/RVO25/monitor.txt b/RVO25/monitor.txt new file mode 100755 index 0000000..57e1604 --- /dev/null +++ b/RVO25/monitor.txt @@ -0,0 +1,522 @@ +[2025-10-02T06:34:30.111] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-02T06:34:35.486] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-02T06:34:35.491] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-02T06:34:35.492] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-02T06:34:35.493] [INFO] monitorLogs - 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 +} +[2025-10-02T06:34:35.495] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-02T06:34:35.497] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-10-02T11:00:00.496Z +[2025-10-02T06:34:35.498] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-02T06:34:35.499] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-10-02T06:34:35.500] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-02T06:34:35.501] [INFO] monitorLogs - 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 +} +[2025-10-02T06:34:35.502] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-02T06:34:35.503] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-10-02T11:00:00.502Z +[2025-10-02T06:34:35.503] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-02T06:34:35.505] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-10-02T06:34:35.505] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-02T06:34:35.506] [INFO] monitorLogs - 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 +} +[2025-10-02T06:34:35.507] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-02T06:34:35.508] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-10-02T11:00:00.508Z +[2025-10-02T06:34:35.509] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-02T06:34:35.510] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-10-02T06:34:35.510] [INFO] monitorLogs - buildTasks: profile for line 4 +[2025-10-02T06:34:35.511] [INFO] monitorLogs - 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 +} +[2025-10-02T06:34:35.512] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-02T06:34:35.513] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 4 2025-10-02T11:00:00.513Z +[2025-10-02T06:34:35.513] [INFO] monitorLogs - -->time_points final 4 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-02T06:34:35.514] [INFO] monitorLogs - -->currentValue for relay 4 1 +[2025-10-02T06:34:35.515] [INFO] monitorLogs - buildTasks: profile for line 5 +[2025-10-02T06:34:35.516] [INFO] monitorLogs - 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 +} +[2025-10-02T06:34:35.517] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-02T06:34:35.518] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 5 2025-10-02T11:00:00.517Z +[2025-10-02T06:34:35.518] [INFO] monitorLogs - -->time_points final 5 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-02T06:34:35.519] [INFO] monitorLogs - -->currentValue for relay 5 1 +[2025-10-02T06:34:35.545] [INFO] monitorLogs - tasks created: 1541 +[2025-10-02T06:34:35.547] [INFO] monitorLogs - -->FLOW bol spustený XMBbew5z4ELrZa2mRAd3RV78vPN6gy3DdVYlpKjq 2025-08-08 +[2025-10-02T06:34:40.559] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-02T06:34:40.864] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-10-02T06:34:41.169] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-10-02T06:34:41.473] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false aplikovany bod profilu +[2025-10-02T06:34:41.778] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false aplikovany bod profilu +[2025-10-03T03:34:38.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-03 03:34:38 +[2025-10-03T14:43:26.059] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-03T14:43:31.408] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-03T14:43:31.413] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-03T14:43:31.414] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-03T14:43:31.415] [INFO] monitorLogs - 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 +} +[2025-10-03T14:43:31.417] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-03T14:43:31.419] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-10-04T11:00:00.418Z +[2025-10-03T14:43:31.420] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-03T14:43:31.421] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-10-03T14:43:31.422] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-03T14:43:31.423] [INFO] monitorLogs - 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 +} +[2025-10-03T14:43:31.424] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-03T14:43:31.425] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-10-04T11:00:00.424Z +[2025-10-03T14:43:31.425] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-03T14:43:31.427] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-10-03T14:43:31.427] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-03T14:43:31.428] [INFO] monitorLogs - 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 +} +[2025-10-03T14:43:31.429] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-03T14:43:31.430] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-10-04T11:00:00.430Z +[2025-10-03T14:43:31.430] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-03T14:43:31.431] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-10-03T14:43:31.432] [INFO] monitorLogs - buildTasks: profile for line 4 +[2025-10-03T14:43:31.433] [INFO] monitorLogs - 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 +} +[2025-10-03T14:43:31.434] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-03T14:43:31.435] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 4 2025-10-04T11:00:00.435Z +[2025-10-03T14:43:31.435] [INFO] monitorLogs - -->time_points final 4 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-03T14:43:31.436] [INFO] monitorLogs - -->currentValue for relay 4 1 +[2025-10-03T14:43:31.437] [INFO] monitorLogs - buildTasks: profile for line 5 +[2025-10-03T14:43:31.437] [INFO] monitorLogs - 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 +} +[2025-10-03T14:43:31.439] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-03T14:43:31.439] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 5 2025-10-04T11:00:00.439Z +[2025-10-03T14:43:31.440] [INFO] monitorLogs - -->time_points final 5 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-03T14:43:31.441] [INFO] monitorLogs - -->currentValue for relay 5 1 +[2025-10-03T14:43:31.466] [INFO] monitorLogs - tasks created: 1541 +[2025-10-03T14:43:31.468] [INFO] monitorLogs - -->FLOW bol spustený XMBbew5z4ELrZa2mRAd3RV78vPN6gy3DdVYlpKjq 2025-08-08 +[2025-10-03T14:43:36.480] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-04T03:43:33.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-04 03:43:33 +[2025-10-05T03:43:35.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-05 03:43:35 +[2025-10-06T03:43:37.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-06 03:43:37 +[2025-10-07T03:43:39.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-07 03:43:39 +[2025-10-08T03:43:41.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-08 03:43:41 +[2025-10-09T03:43:42.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-09 03:43:42 +[2025-10-09T16:49:00.885] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-09T16:49:06.247] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-09T16:49:06.253] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-09T16:49:06.254] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-09T16:49:06.254] [INFO] monitorLogs - 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 +} +[2025-10-09T16:49:06.257] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T16:49:06.259] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-10-10T11:00:00.258Z +[2025-10-09T16:49:06.260] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-09T16:49:06.261] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-10-09T16:49:06.262] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-09T16:49:06.262] [INFO] monitorLogs - 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 +} +[2025-10-09T16:49:06.264] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T16:49:06.264] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-10-10T11:00:00.264Z +[2025-10-09T16:49:06.265] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-09T16:49:06.266] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-10-09T16:49:06.267] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-09T16:49:06.268] [INFO] monitorLogs - 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 +} +[2025-10-09T16:49:06.269] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T16:49:06.270] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-10-10T11:00:00.270Z +[2025-10-09T16:49:06.270] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-09T16:49:06.271] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-10-09T16:49:06.272] [INFO] monitorLogs - buildTasks: profile for line 4 +[2025-10-09T16:49:06.273] [INFO] monitorLogs - 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 +} +[2025-10-09T16:49:06.274] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T16:49:06.275] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 4 2025-10-10T11:00:00.275Z +[2025-10-09T16:49:06.275] [INFO] monitorLogs - -->time_points final 4 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-09T16:49:06.276] [INFO] monitorLogs - -->currentValue for relay 4 1 +[2025-10-09T16:49:06.277] [INFO] monitorLogs - buildTasks: profile for line 5 +[2025-10-09T16:49:06.278] [INFO] monitorLogs - 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 +} +[2025-10-09T16:49:06.279] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T16:49:06.280] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 5 2025-10-10T11:00:00.279Z +[2025-10-09T16:49:06.280] [INFO] monitorLogs - -->time_points final 5 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-09T16:49:06.281] [INFO] monitorLogs - -->currentValue for relay 5 1 +[2025-10-09T16:49:06.306] [INFO] monitorLogs - tasks created: 1541 +[2025-10-09T16:49:06.308] [INFO] monitorLogs - -->FLOW bol spustený XMBbew5z4ELrZa2mRAd3RV78vPN6gy3DdVYlpKjq 2025-08-08 +[2025-10-09T16:49:11.322] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-09T19:01:05.031] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-09T19:01:10.396] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-09T19:01:10.402] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-09T19:01:10.403] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-09T19:01:10.403] [INFO] monitorLogs - 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 +} +[2025-10-09T19:01:10.406] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T19:01:10.408] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-10-10T11:00:00.407Z +[2025-10-09T19:01:10.409] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-09T19:01:10.410] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-10-09T19:01:10.411] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-09T19:01:10.411] [INFO] monitorLogs - 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 +} +[2025-10-09T19:01:10.413] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T19:01:10.414] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-10-10T11:00:00.413Z +[2025-10-09T19:01:10.414] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-09T19:01:10.415] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-10-09T19:01:10.416] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-09T19:01:10.416] [INFO] monitorLogs - 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 +} +[2025-10-09T19:01:10.418] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T19:01:10.419] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-10-10T11:00:00.418Z +[2025-10-09T19:01:10.419] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-09T19:01:10.420] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-10-09T19:01:10.421] [INFO] monitorLogs - buildTasks: profile for line 4 +[2025-10-09T19:01:10.421] [INFO] monitorLogs - 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 +} +[2025-10-09T19:01:10.423] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T19:01:10.423] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 4 2025-10-10T11:00:00.423Z +[2025-10-09T19:01:10.424] [INFO] monitorLogs - -->time_points final 4 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-09T19:01:10.425] [INFO] monitorLogs - -->currentValue for relay 4 1 +[2025-10-09T19:01:10.426] [INFO] monitorLogs - buildTasks: profile for line 5 +[2025-10-09T19:01:10.426] [INFO] monitorLogs - 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 +} +[2025-10-09T19:01:10.428] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T19:01:10.428] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 5 2025-10-10T11:00:00.428Z +[2025-10-09T19:01:10.429] [INFO] monitorLogs - -->time_points final 5 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-09T19:01:10.430] [INFO] monitorLogs - -->currentValue for relay 5 1 +[2025-10-09T19:01:10.455] [INFO] monitorLogs - tasks created: 1541 +[2025-10-09T19:01:10.458] [INFO] monitorLogs - -->FLOW bol spustený XMBbew5z4ELrZa2mRAd3RV78vPN6gy3DdVYlpKjq 2025-08-08 +[2025-10-09T19:01:15.469] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-10T03:01:13.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-10 03:01:13 +[2025-10-11T03:01:15.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-11 03:01:15 +[2025-10-12T03:01:17.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-12 03:01:17 +[2025-10-13T03:01:19.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-13 03:01:19 +[2025-10-14T03:01:20.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-14 03:01:20 +[2025-10-15T03:01:22.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-15 03:01:22 +[2025-10-15T15:38:50.191] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-15T15:38:55.554] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-15T15:38:55.559] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-15T15:38:55.561] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-15T15:38:55.561] [INFO] monitorLogs - 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 +} +[2025-10-15T15:38:55.564] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-15T15:38:55.566] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-10-16T11:00:00.565Z +[2025-10-15T15:38:55.567] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-15T15:38:55.568] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-10-15T15:38:55.569] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-15T15:38:55.569] [INFO] monitorLogs - 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 +} +[2025-10-15T15:38:55.571] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-15T15:38:55.571] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-10-16T11:00:00.571Z +[2025-10-15T15:38:55.572] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-15T15:38:55.573] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-10-15T15:38:55.574] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-15T15:38:55.574] [INFO] monitorLogs - 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 +} +[2025-10-15T15:38:55.576] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-15T15:38:55.577] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-10-16T11:00:00.576Z +[2025-10-15T15:38:55.577] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-15T15:38:55.579] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-10-15T15:38:55.580] [INFO] monitorLogs - buildTasks: profile for line 4 +[2025-10-15T15:38:55.581] [INFO] monitorLogs - 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 +} +[2025-10-15T15:38:55.582] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-15T15:38:55.583] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 4 2025-10-16T11:00:00.583Z +[2025-10-15T15:38:55.583] [INFO] monitorLogs - -->time_points final 4 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-15T15:38:55.584] [INFO] monitorLogs - -->currentValue for relay 4 1 +[2025-10-15T15:38:55.585] [INFO] monitorLogs - buildTasks: profile for line 5 +[2025-10-15T15:38:55.586] [INFO] monitorLogs - 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 +} +[2025-10-15T15:38:55.587] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-15T15:38:55.588] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 5 2025-10-16T11:00:00.587Z +[2025-10-15T15:38:55.588] [INFO] monitorLogs - -->time_points final 5 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-15T15:38:55.589] [INFO] monitorLogs - -->currentValue for relay 5 1 +[2025-10-15T15:38:55.615] [INFO] monitorLogs - tasks created: 1541 +[2025-10-15T15:38:55.618] [INFO] monitorLogs - -->FLOW bol spustený XMBbew5z4ELrZa2mRAd3RV78vPN6gy3DdVYlpKjq 2025-10-08 +[2025-10-15T15:39:00.630] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu diff --git a/RVO25/package-lock.json b/RVO25/package-lock.json new file mode 100755 index 0000000..3c5c1ba --- /dev/null +++ b/RVO25/package-lock.json @@ -0,0 +1,2139 @@ +{ + "name": "emptyproject", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "emptyproject", + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "bitwise": "^2.1.0", + "easy-crc": "0.0.2", + "jsmodbus": "^4.0.6", + "log4js": "^6.3.0", + "moment": "^2.30.1", + "mqtt": "^4.2.6", + "nodemailer": "^6.9.7", + "serialport": "^9.2.8", + "total.js": "^3.4.13" + } + }, + "node_modules/@serialport/binding-abstract": { + "version": "9.2.3", + "resolved": "https://registry.npmjs.org/@serialport/binding-abstract/-/binding-abstract-9.2.3.tgz", + "integrity": "sha512-cQs9tbIlG3P0IrOWyVirqlhWuJ7Ms2Zh9m2108z6Y5UW/iVj6wEOiW8EmK9QX9jmJXYllE7wgGgvVozP5oCj3w==", + "dependencies": { + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/binding-mock": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/binding-mock/-/binding-mock-9.2.4.tgz", + "integrity": "sha512-dpEhACCs44oQhh6ajJfJdvQdK38Vq0N4W6iD/gdplglDCK7qXRQCMUjJIeKdS/HSEiWkC3bwumUhUufdsOyT4g==", + "dependencies": { + "@serialport/binding-abstract": "9.2.3", + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/bindings": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/@serialport/bindings/-/bindings-9.2.8.tgz", + "integrity": "sha512-hSLxTe0tADZ3LMMGwvEJWOC/TaFQTyPeFalUCsJ1lSQ0k6bPF04JwrtB/C81GetmDBTNRY0GlD0SNtKCc7Dr5g==", + "hasInstallScript": true, + "dependencies": { + "@serialport/binding-abstract": "9.2.3", + "@serialport/parser-readline": "9.2.4", + "bindings": "^1.5.0", + "debug": "^4.3.2", + "nan": "^2.15.0", + "prebuild-install": "^7.0.0" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-byte-length": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-byte-length/-/parser-byte-length-9.2.4.tgz", + "integrity": "sha512-sQD/iw4ZMU3xW9PLi0/GlvU6Y623jGeWecbMkO7izUo/6P7gtfv1c9ikd5h0kwL8AoAOpQA1lxdHIKox+umBUg==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-cctalk": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-cctalk/-/parser-cctalk-9.2.4.tgz", + "integrity": "sha512-T4TU5vQMwmo9AB3gQLFDWbfJXlW5jd9guEsB/nqKjFHTv0FXPdZ7DQ2TpSp8RnHWxU3GX6kYTaDO20BKzc8GPQ==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-delimiter": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-delimiter/-/parser-delimiter-9.2.4.tgz", + "integrity": "sha512-4nvTAoYAgkxFiXrkI+3CA49Yd43CODjeszh89EK+I9c8wOZ+etZduRCzINYPiy26g7zO+GRAb9FoPCsY+sYcbQ==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-inter-byte-timeout": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-inter-byte-timeout/-/parser-inter-byte-timeout-9.2.4.tgz", + "integrity": "sha512-SOAdvr0oBQIOCXX198hiTlxs4JTKg9j5piapw5tNq52fwDOWdbYrFneT/wN04UTMKaDrJuEvXq6T4rv4j7nJ5A==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-readline": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-readline/-/parser-readline-9.2.4.tgz", + "integrity": "sha512-Z1/qrZTQUVhNSJP1hd9YfDvq0o7d87rNwAjjRKbVpa7Qi51tG5BnKt43IV3NFMyBlVcRe0rnIb3tJu57E0SOwg==", + "dependencies": { + "@serialport/parser-delimiter": "9.2.4" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-ready": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-ready/-/parser-ready-9.2.4.tgz", + "integrity": "sha512-Pyi94Itjl6qAURwIZr/gmZpMAyTmKXThm6vL5DoAWGQjcRHWB0gwv2TY2v7N+mQLJYUKU3cMnvnATXxHm7xjxw==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-regex": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-regex/-/parser-regex-9.2.4.tgz", + "integrity": "sha512-sI/cVvPOYz+Dbv4ZdnW16qAwvXiFf/1pGASQdbveRTlgJDdz7sRNlCBifzfTN2xljwvCTZYqiudKvDdC1TepRQ==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/stream": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/stream/-/stream-9.2.4.tgz", + "integrity": "sha512-bLye8Ub4vUFQGmkh8qEqehr7SE7EJs2yDs0h9jzuL5oKi+F34CFmWkEErO8GAOQ8YNn7p6b3GxUgs+0BrHHDZQ==", + "dependencies": { + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "node_modules/are-we-there-yet": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", + "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/base64-js": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", + "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==" + }, + "node_modules/bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "dependencies": { + "file-uri-to-path": "1.0.0" + } + }, + "node_modules/bitwise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/bitwise/-/bitwise-2.1.0.tgz", + "integrity": "sha512-XKgAhMXCh4H/3oNwAHAsAO0iC89s9cOiumgYwSHjSobGWxYjv62YhkL9QEdvGP151xypCtMlAfKK79GEcd2eRQ==" + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/bl/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/buffer": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz", + "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==", + "dependencies": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + }, + "node_modules/buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" + }, + "node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, + "node_modules/code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/commist": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/commist/-/commist-1.1.0.tgz", + "integrity": "sha512-rraC8NXWOEjhADbZe9QBNzLAN5Q3fsTPQtBV+fEVj6xKIgDgNiEVE6ZNfHpZOqfQ21YUzfVNUXLOEZquYvQPPg==", + "dependencies": { + "leven": "^2.1.0", + "minimist": "^1.1.0" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "node_modules/concat-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", + "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", + "engines": [ + "node >= 6.0" + ], + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.0.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/concat-stream/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" + }, + "node_modules/core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "node_modules/crc": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/crc/-/crc-3.4.0.tgz", + "integrity": "sha512-ycVC2+4/DLgXXq7QweYi2znhqDuZz6P5TQXnkQo8v15XY/5p/IWeZwsSE31Ifo8w15b8TWLsqhXOjXyilHuQxw==" + }, + "node_modules/date-format": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.11.tgz", + "integrity": "sha512-VS20KRyorrbMCQmpdl2hg5KaOUsda1RbnsJg461FfrcyCUg+pkd0b40BSW4niQyTheww4DBXQnS7HwSrKkipLw==", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" + }, + "node_modules/detect-libc": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz", + "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==", + "engines": { + "node": ">=8" + } + }, + "node_modules/duplexify": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.2.tgz", + "integrity": "sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw==", + "dependencies": { + "end-of-stream": "^1.4.1", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1", + "stream-shift": "^1.0.0" + } + }, + "node_modules/duplexify/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/easy-crc": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/easy-crc/-/easy-crc-0.0.2.tgz", + "integrity": "sha512-h6eqIdhJRe0p271/xZJbM/0klCi13mW5IB7ZEzEGH11yV4QXWAkD4yPErz0fXdhFrd6sZ4Q1k5Iky2kMsMNePw==" + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" + }, + "node_modules/flatted": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", + "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==" + }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, + "node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "node_modules/gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha512-14x4kjc6lkD3ltw589k0NrPD6cCNTD6CWoVUNpB85+DrtONoZn+Rug6xZU5RvSC4+TZPxA5AnBibQYAvZn41Hg==", + "dependencies": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "node_modules/github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==" + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" + }, + "node_modules/has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" + }, + "node_modules/help-me": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/help-me/-/help-me-3.0.0.tgz", + "integrity": "sha512-hx73jClhyk910sidBB7ERlnhMlFsJJIBqSVMFDwPN8o2v9nmp5KgLq1Xz1Bf1fCMMZ6mPrX159iG0VLy/fPMtQ==", + "dependencies": { + "glob": "^7.1.6", + "readable-stream": "^3.6.0" + } + }, + "node_modules/help-me/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, + "node_modules/is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==", + "dependencies": { + "number-is-nan": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "node_modules/js-sdsl": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz", + "integrity": "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/js-sdsl" + } + }, + "node_modules/jsmodbus": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/jsmodbus/-/jsmodbus-4.0.6.tgz", + "integrity": "sha512-gCmjoaERErK5Rn9Lu/BN07fY13MoWV7JKgGzrnkPlQPdPxYcwDhLtYcmpFFpZ4J9NPZZBSezi1UkLZO/DnNppA==", + "dependencies": { + "crc": "3.4.0", + "debug": "^3.1.0" + }, + "bin": { + "jsmodbus": "bin/jsmodbus.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/jsmodbus/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/leven": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", + "integrity": "sha1-wuep93IJTe6dNCAq6KzORoeHVYA=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/log4js": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.5.2.tgz", + "integrity": "sha512-DXtpNtt+KDOMT7RHUDIur/WsSA3rntlUh9Zg4XCdV42wUuMmbFkl38+LZ92Z5QvQA7mD5kAVkLiBSEH/tvUB8A==", + "dependencies": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "flatted": "^3.2.5", + "rfdc": "^1.3.0", + "streamroller": "^3.1.1" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" + }, + "node_modules/moment": { + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", + "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==", + "engines": { + "node": "*" + } + }, + "node_modules/mqtt": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/mqtt/-/mqtt-4.3.7.tgz", + "integrity": "sha512-ew3qwG/TJRorTz47eW46vZ5oBw5MEYbQZVaEji44j5lAUSQSqIEoul7Kua/BatBW0H0kKQcC9kwUHa1qzaWHSw==", + "dependencies": { + "commist": "^1.0.0", + "concat-stream": "^2.0.0", + "debug": "^4.1.1", + "duplexify": "^4.1.1", + "help-me": "^3.0.0", + "inherits": "^2.0.3", + "lru-cache": "^6.0.0", + "minimist": "^1.2.5", + "mqtt-packet": "^6.8.0", + "number-allocator": "^1.0.9", + "pump": "^3.0.0", + "readable-stream": "^3.6.0", + "reinterval": "^1.1.0", + "rfdc": "^1.3.0", + "split2": "^3.1.0", + "ws": "^7.5.5", + "xtend": "^4.0.2" + }, + "bin": { + "mqtt": "bin/mqtt.js", + "mqtt_pub": "bin/pub.js", + "mqtt_sub": "bin/sub.js" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/mqtt-packet": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/mqtt-packet/-/mqtt-packet-6.10.0.tgz", + "integrity": "sha512-ja8+mFKIHdB1Tpl6vac+sktqy3gA8t9Mduom1BA75cI+R9AHnZOiaBQwpGiWnaVJLDGRdNhQmFaAqd7tkKSMGA==", + "dependencies": { + "bl": "^4.0.2", + "debug": "^4.1.1", + "process-nextick-args": "^2.0.1" + } + }, + "node_modules/mqtt/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/nan": { + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.16.0.tgz", + "integrity": "sha512-UdAqHyFngu7TfQKsCBgAA6pWDkT8MAO7d0jyOecVhN5354xbLqdn8mV9Tat9gepAupm0bt2DbeaSC8vS52MuFA==" + }, + "node_modules/napi-build-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", + "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==" + }, + "node_modules/node-abi": { + "version": "3.22.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.22.0.tgz", + "integrity": "sha512-u4uAs/4Zzmp/jjsD9cyFYDXeISfUWaAVWshPmDZOFOv4Xl4SbzTXm53I04C2uRueYJ+0t5PEtLH/owbn2Npf/w==", + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/nodemailer": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.7.tgz", + "integrity": "sha512-rUtR77ksqex/eZRLmQ21LKVH5nAAsVicAtAYudK7JgwenEDZ0UIQ1adUGqErz7sMkWYxWTTU1aeP2Jga6WQyJw==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "dependencies": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "node_modules/number-allocator": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/number-allocator/-/number-allocator-1.0.14.tgz", + "integrity": "sha512-OrL44UTVAvkKdOdRQZIJpLkAdjXGTRda052sN4sO77bKEzYYqWKMBjQvrJFzqygI99gL6Z4u2xctPW1tB8ErvA==", + "dependencies": { + "debug": "^4.3.1", + "js-sdsl": "4.3.0" + } + }, + "node_modules/number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/prebuild-install": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.0.tgz", + "integrity": "sha512-CNcMgI1xBypOyGqjp3wOc8AAo1nMhZS3Cwd3iHIxOdAUbb+YxdNuM4Z5iIrZ8RLvOsf3F3bl7b7xGq6DjQoNYA==", + "dependencies": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^1.0.1", + "node-abi": "^3.3.0", + "npmlog": "^4.0.1", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + }, + "bin": { + "prebuild-install": "bin.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/reinterval": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reinterval/-/reinterval-1.1.0.tgz", + "integrity": "sha1-M2Hs+jymwYKDOA3Qu5VG85D17Oc=" + }, + "node_modules/rfdc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==" + }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/serialport": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/serialport/-/serialport-9.2.8.tgz", + "integrity": "sha512-FsWpMQgSJxi93JgWl5xM1f9/Z8IjRJuaUEoHqLf8FPBLw7gMhInuHOBhI2onQufWIYPGTz3H3oGcu1nCaK1EfA==", + "dependencies": { + "@serialport/binding-mock": "9.2.4", + "@serialport/bindings": "9.2.8", + "@serialport/parser-byte-length": "9.2.4", + "@serialport/parser-cctalk": "9.2.4", + "@serialport/parser-delimiter": "9.2.4", + "@serialport/parser-inter-byte-timeout": "9.2.4", + "@serialport/parser-readline": "9.2.4", + "@serialport/parser-ready": "9.2.4", + "@serialport/parser-regex": "9.2.4", + "@serialport/stream": "9.2.4", + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "node_modules/split2": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", + "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", + "dependencies": { + "readable-stream": "^3.0.0" + } + }, + "node_modules/split2/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==" + }, + "node_modules/streamroller": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.1.1.tgz", + "integrity": "sha512-iPhtd9unZ6zKdWgMeYGfSBuqCngyJy1B/GPi/lTpwGpa3bajuX30GjUVd0/Tn/Xhg0mr4DOSENozz9Y06qyonQ==", + "dependencies": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "fs-extra": "^10.1.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dependencies": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/tar-fs": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "dependencies": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tar-stream/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/total.js": { + "version": "3.4.13", + "resolved": "https://registry.npmjs.org/total.js/-/total.js-3.4.13.tgz", + "integrity": "sha512-lAH4gEixlPFbrE3xfKADAcHfO79IFq2wKa9GTsrgRzIR5MTg3mNH7+4IxvX1pK8faoYb/0oYSJ1YTsAa5hIFFQ==", + "bin": { + "total": "bin/totaljs", + "total.js": "bin/totaljs", + "totaljs": "bin/totaljs", + "totalpackage": "bin/tpm", + "tpm": "bin/tpm" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, + "node_modules/universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "node_modules/wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "node_modules/ws": { + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } + }, + "dependencies": { + "@serialport/binding-abstract": { + "version": "9.2.3", + "resolved": "https://registry.npmjs.org/@serialport/binding-abstract/-/binding-abstract-9.2.3.tgz", + "integrity": "sha512-cQs9tbIlG3P0IrOWyVirqlhWuJ7Ms2Zh9m2108z6Y5UW/iVj6wEOiW8EmK9QX9jmJXYllE7wgGgvVozP5oCj3w==", + "requires": { + "debug": "^4.3.2" + } + }, + "@serialport/binding-mock": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/binding-mock/-/binding-mock-9.2.4.tgz", + "integrity": "sha512-dpEhACCs44oQhh6ajJfJdvQdK38Vq0N4W6iD/gdplglDCK7qXRQCMUjJIeKdS/HSEiWkC3bwumUhUufdsOyT4g==", + "requires": { + "@serialport/binding-abstract": "9.2.3", + "debug": "^4.3.2" + } + }, + "@serialport/bindings": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/@serialport/bindings/-/bindings-9.2.8.tgz", + "integrity": "sha512-hSLxTe0tADZ3LMMGwvEJWOC/TaFQTyPeFalUCsJ1lSQ0k6bPF04JwrtB/C81GetmDBTNRY0GlD0SNtKCc7Dr5g==", + "requires": { + "@serialport/binding-abstract": "9.2.3", + "@serialport/parser-readline": "9.2.4", + "bindings": "^1.5.0", + "debug": "^4.3.2", + "nan": "^2.15.0", + "prebuild-install": "^7.0.0" + } + }, + "@serialport/parser-byte-length": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-byte-length/-/parser-byte-length-9.2.4.tgz", + "integrity": "sha512-sQD/iw4ZMU3xW9PLi0/GlvU6Y623jGeWecbMkO7izUo/6P7gtfv1c9ikd5h0kwL8AoAOpQA1lxdHIKox+umBUg==" + }, + "@serialport/parser-cctalk": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-cctalk/-/parser-cctalk-9.2.4.tgz", + "integrity": "sha512-T4TU5vQMwmo9AB3gQLFDWbfJXlW5jd9guEsB/nqKjFHTv0FXPdZ7DQ2TpSp8RnHWxU3GX6kYTaDO20BKzc8GPQ==" + }, + "@serialport/parser-delimiter": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-delimiter/-/parser-delimiter-9.2.4.tgz", + "integrity": "sha512-4nvTAoYAgkxFiXrkI+3CA49Yd43CODjeszh89EK+I9c8wOZ+etZduRCzINYPiy26g7zO+GRAb9FoPCsY+sYcbQ==" + }, + "@serialport/parser-inter-byte-timeout": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-inter-byte-timeout/-/parser-inter-byte-timeout-9.2.4.tgz", + "integrity": "sha512-SOAdvr0oBQIOCXX198hiTlxs4JTKg9j5piapw5tNq52fwDOWdbYrFneT/wN04UTMKaDrJuEvXq6T4rv4j7nJ5A==" + }, + "@serialport/parser-readline": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-readline/-/parser-readline-9.2.4.tgz", + "integrity": "sha512-Z1/qrZTQUVhNSJP1hd9YfDvq0o7d87rNwAjjRKbVpa7Qi51tG5BnKt43IV3NFMyBlVcRe0rnIb3tJu57E0SOwg==", + "requires": { + "@serialport/parser-delimiter": "9.2.4" + } + }, + "@serialport/parser-ready": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-ready/-/parser-ready-9.2.4.tgz", + "integrity": "sha512-Pyi94Itjl6qAURwIZr/gmZpMAyTmKXThm6vL5DoAWGQjcRHWB0gwv2TY2v7N+mQLJYUKU3cMnvnATXxHm7xjxw==" + }, + "@serialport/parser-regex": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-regex/-/parser-regex-9.2.4.tgz", + "integrity": "sha512-sI/cVvPOYz+Dbv4ZdnW16qAwvXiFf/1pGASQdbveRTlgJDdz7sRNlCBifzfTN2xljwvCTZYqiudKvDdC1TepRQ==" + }, + "@serialport/stream": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/stream/-/stream-9.2.4.tgz", + "integrity": "sha512-bLye8Ub4vUFQGmkh8qEqehr7SE7EJs2yDs0h9jzuL5oKi+F34CFmWkEErO8GAOQ8YNn7p6b3GxUgs+0BrHHDZQ==", + "requires": { + "debug": "^4.3.2" + } + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==" + }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "are-we-there-yet": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", + "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "base64-js": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", + "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==" + }, + "bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "requires": { + "file-uri-to-path": "1.0.0" + } + }, + "bitwise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/bitwise/-/bitwise-2.1.0.tgz", + "integrity": "sha512-XKgAhMXCh4H/3oNwAHAsAO0iC89s9cOiumgYwSHjSobGWxYjv62YhkL9QEdvGP151xypCtMlAfKK79GEcd2eRQ==" + }, + "bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "requires": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "buffer": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz", + "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==", + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" + }, + "chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==" + }, + "commist": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/commist/-/commist-1.1.0.tgz", + "integrity": "sha512-rraC8NXWOEjhADbZe9QBNzLAN5Q3fsTPQtBV+fEVj6xKIgDgNiEVE6ZNfHpZOqfQ21YUzfVNUXLOEZquYvQPPg==", + "requires": { + "leven": "^2.1.0", + "minimist": "^1.1.0" + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "concat-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", + "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.0.2", + "typedarray": "^0.0.6" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "crc": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/crc/-/crc-3.4.0.tgz", + "integrity": "sha512-ycVC2+4/DLgXXq7QweYi2znhqDuZz6P5TQXnkQo8v15XY/5p/IWeZwsSE31Ifo8w15b8TWLsqhXOjXyilHuQxw==" + }, + "date-format": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.11.tgz", + "integrity": "sha512-VS20KRyorrbMCQmpdl2hg5KaOUsda1RbnsJg461FfrcyCUg+pkd0b40BSW4niQyTheww4DBXQnS7HwSrKkipLw==" + }, + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "requires": { + "ms": "2.1.2" + } + }, + "decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "requires": { + "mimic-response": "^3.1.0" + } + }, + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==" + }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" + }, + "detect-libc": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz", + "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==" + }, + "duplexify": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.2.tgz", + "integrity": "sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw==", + "requires": { + "end-of-stream": "^1.4.1", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1", + "stream-shift": "^1.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "easy-crc": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/easy-crc/-/easy-crc-0.0.2.tgz", + "integrity": "sha512-h6eqIdhJRe0p271/xZJbM/0klCi13mW5IB7ZEzEGH11yV4QXWAkD4yPErz0fXdhFrd6sZ4Q1k5Iky2kMsMNePw==" + }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "requires": { + "once": "^1.4.0" + } + }, + "expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==" + }, + "file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" + }, + "flatted": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", + "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==" + }, + "fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, + "fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha512-14x4kjc6lkD3ltw589k0NrPD6cCNTD6CWoVUNpB85+DrtONoZn+Rug6xZU5RvSC4+TZPxA5AnBibQYAvZn41Hg==", + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==" + }, + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" + }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" + }, + "help-me": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/help-me/-/help-me-3.0.0.tgz", + "integrity": "sha512-hx73jClhyk910sidBB7ERlnhMlFsJJIBqSVMFDwPN8o2v9nmp5KgLq1Xz1Bf1fCMMZ6mPrX159iG0VLy/fPMtQ==", + "requires": { + "glob": "^7.1.6", + "readable-stream": "^3.6.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==", + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "js-sdsl": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz", + "integrity": "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==" + }, + "jsmodbus": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/jsmodbus/-/jsmodbus-4.0.6.tgz", + "integrity": "sha512-gCmjoaERErK5Rn9Lu/BN07fY13MoWV7JKgGzrnkPlQPdPxYcwDhLtYcmpFFpZ4J9NPZZBSezi1UkLZO/DnNppA==", + "requires": { + "crc": "3.4.0", + "debug": "^3.1.0" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "requires": { + "ms": "^2.1.1" + } + } + } + }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, + "leven": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", + "integrity": "sha1-wuep93IJTe6dNCAq6KzORoeHVYA=" + }, + "log4js": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.5.2.tgz", + "integrity": "sha512-DXtpNtt+KDOMT7RHUDIur/WsSA3rntlUh9Zg4XCdV42wUuMmbFkl38+LZ92Z5QvQA7mD5kAVkLiBSEH/tvUB8A==", + "requires": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "flatted": "^3.2.5", + "rfdc": "^1.3.0", + "streamroller": "^3.1.1" + } + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "requires": { + "yallist": "^4.0.0" + } + }, + "mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==" + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==" + }, + "mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" + }, + "moment": { + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", + "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==" + }, + "mqtt": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/mqtt/-/mqtt-4.3.7.tgz", + "integrity": "sha512-ew3qwG/TJRorTz47eW46vZ5oBw5MEYbQZVaEji44j5lAUSQSqIEoul7Kua/BatBW0H0kKQcC9kwUHa1qzaWHSw==", + "requires": { + "commist": "^1.0.0", + "concat-stream": "^2.0.0", + "debug": "^4.1.1", + "duplexify": "^4.1.1", + "help-me": "^3.0.0", + "inherits": "^2.0.3", + "lru-cache": "^6.0.0", + "minimist": "^1.2.5", + "mqtt-packet": "^6.8.0", + "number-allocator": "^1.0.9", + "pump": "^3.0.0", + "readable-stream": "^3.6.0", + "reinterval": "^1.1.0", + "rfdc": "^1.3.0", + "split2": "^3.1.0", + "ws": "^7.5.5", + "xtend": "^4.0.2" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "mqtt-packet": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/mqtt-packet/-/mqtt-packet-6.10.0.tgz", + "integrity": "sha512-ja8+mFKIHdB1Tpl6vac+sktqy3gA8t9Mduom1BA75cI+R9AHnZOiaBQwpGiWnaVJLDGRdNhQmFaAqd7tkKSMGA==", + "requires": { + "bl": "^4.0.2", + "debug": "^4.1.1", + "process-nextick-args": "^2.0.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "nan": { + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.16.0.tgz", + "integrity": "sha512-UdAqHyFngu7TfQKsCBgAA6pWDkT8MAO7d0jyOecVhN5354xbLqdn8mV9Tat9gepAupm0bt2DbeaSC8vS52MuFA==" + }, + "napi-build-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", + "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==" + }, + "node-abi": { + "version": "3.22.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.22.0.tgz", + "integrity": "sha512-u4uAs/4Zzmp/jjsD9cyFYDXeISfUWaAVWshPmDZOFOv4Xl4SbzTXm53I04C2uRueYJ+0t5PEtLH/owbn2Npf/w==", + "requires": { + "semver": "^7.3.5" + } + }, + "nodemailer": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.7.tgz", + "integrity": "sha512-rUtR77ksqex/eZRLmQ21LKVH5nAAsVicAtAYudK7JgwenEDZ0UIQ1adUGqErz7sMkWYxWTTU1aeP2Jga6WQyJw==" + }, + "npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "number-allocator": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/number-allocator/-/number-allocator-1.0.14.tgz", + "integrity": "sha512-OrL44UTVAvkKdOdRQZIJpLkAdjXGTRda052sN4sO77bKEzYYqWKMBjQvrJFzqygI99gL6Z4u2xctPW1tB8ErvA==", + "requires": { + "debug": "^4.3.1", + "js-sdsl": "4.3.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==" + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==" + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==" + }, + "prebuild-install": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.0.tgz", + "integrity": "sha512-CNcMgI1xBypOyGqjp3wOc8AAo1nMhZS3Cwd3iHIxOdAUbb+YxdNuM4Z5iIrZ8RLvOsf3F3bl7b7xGq6DjQoNYA==", + "requires": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^1.0.1", + "node-abi": "^3.3.0", + "npmlog": "^4.0.1", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + } + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + } + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "reinterval": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reinterval/-/reinterval-1.1.0.tgz", + "integrity": "sha1-M2Hs+jymwYKDOA3Qu5VG85D17Oc=" + }, + "rfdc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==" + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "requires": { + "lru-cache": "^6.0.0" + } + }, + "serialport": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/serialport/-/serialport-9.2.8.tgz", + "integrity": "sha512-FsWpMQgSJxi93JgWl5xM1f9/Z8IjRJuaUEoHqLf8FPBLw7gMhInuHOBhI2onQufWIYPGTz3H3oGcu1nCaK1EfA==", + "requires": { + "@serialport/binding-mock": "9.2.4", + "@serialport/bindings": "9.2.8", + "@serialport/parser-byte-length": "9.2.4", + "@serialport/parser-cctalk": "9.2.4", + "@serialport/parser-delimiter": "9.2.4", + "@serialport/parser-inter-byte-timeout": "9.2.4", + "@serialport/parser-readline": "9.2.4", + "@serialport/parser-ready": "9.2.4", + "@serialport/parser-regex": "9.2.4", + "@serialport/stream": "9.2.4", + "debug": "^4.3.2" + } + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==" + }, + "simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "requires": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "split2": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", + "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", + "requires": { + "readable-stream": "^3.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==" + }, + "streamroller": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.1.1.tgz", + "integrity": "sha512-iPhtd9unZ6zKdWgMeYGfSBuqCngyJy1B/GPi/lTpwGpa3bajuX30GjUVd0/Tn/Xhg0mr4DOSENozz9Y06qyonQ==", + "requires": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "fs-extra": "^10.1.0" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" + }, + "tar-fs": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "requires": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "requires": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "total.js": { + "version": "3.4.13", + "resolved": "https://registry.npmjs.org/total.js/-/total.js-3.4.13.tgz", + "integrity": "sha512-lAH4gEixlPFbrE3xfKADAcHfO79IFq2wKa9GTsrgRzIR5MTg3mNH7+4IxvX1pK8faoYb/0oYSJ1YTsAa5hIFFQ==" + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, + "universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==" + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "requires": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "ws": { + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "requires": {} + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } + } +} diff --git a/RVO25/package.json b/RVO25/package.json new file mode 100755 index 0000000..7f7c795 --- /dev/null +++ b/RVO25/package.json @@ -0,0 +1,30 @@ +{ + "name": "emptyproject", + "description": "Total.js empty project.", + "version": "1.0.0", + "main": "debug.js", + "dependencies": { + "bitwise": "^2.1.0", + "easy-crc": "0.0.2", + "jsmodbus": "^4.0.6", + "log4js": "^6.3.0", + "moment": "^2.30.1", + "mqtt": "^4.2.6", + "nodemailer": "^6.9.7", + "serialport": "^9.2.8", + "total.js": "^3.4.13" + }, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "https://github.com/totaljs/emptyproject-flow" + }, + "keywords": [ + "empty", + "project" + ], + "author": "Peter Širka", + "license": "MIT" +} diff --git a/RVO25/release.js b/RVO25/release.js new file mode 100755 index 0000000..02d52ff --- /dev/null +++ b/RVO25/release.js @@ -0,0 +1,15 @@ +// =================================================== +// FOR PRODUCTION +// Total.js - framework for Node.js platform +// https://www.totaljs.com +// =================================================== + +const options = {'ip':'0.0.0.0', 'port':12345}; + +// options.ip = '127.0.0.1'; +// options.port = parseInt(process.argv[2]); +// options.config = { name: 'Total.js' }; +// options.sleep = 3000; + +require('total.js').http('release', options); +// require('total.js').cluster.http(5, 'release', options); diff --git a/RVO25/release.js.json b/RVO25/release.js.json new file mode 100755 index 0000000..9362cd5 --- /dev/null +++ b/RVO25/release.js.json @@ -0,0 +1,34 @@ +{ + "pid": 419, + "stats": [ + { + "id": null, + "version": { + "node": "v14.18.1", + "total": "3.4.13", + "app": "1.0.0" + }, + "pid": 419, + "thread": "", + "mode": "release", + "overload": 0, + "date": "2025-10-16T00:24:46.256Z", + "memory": 28.83, + "rm": 0, + "fm": 0, + "wm": 0, + "mm": 0, + "om": 30, + "em": 1, + "dbrm": 0, + "dbwm": 0, + "usage": 0, + "requests": 0, + "pending": 0, + "errors": 0, + "timeouts": 0, + "uptime": 647, + "online": 0 + } + ] +} \ No newline at end of file diff --git a/RVO25/report_data.log b/RVO25/report_data.log new file mode 100755 index 0000000..828f92d --- /dev/null +++ b/RVO25/report_data.log @@ -0,0 +1,172 @@ +{ + "name": "rvo_senica_25_ip121", + "time": "2025-10-15T14:39:01.853Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_25_ip121", + "time": "2025-10-15T15:39:01.853Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_25_ip121", + "time": "2025-10-15T16:39:01.848Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_25_ip121", + "time": "2025-10-15T17:39:01.853Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [ + "25/103_1L_3780_NEMA", + "25/32_1L_4029_NEMA" + ], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_25_ip121", + "time": "2025-10-15T18:39:01.848Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [ + "25/103_1L_3780_NEMA", + "25/32_1L_4029_NEMA" + ], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_25_ip121", + "time": "2025-10-15T19:39:01.853Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [ + "25/103_1L_3780_NEMA", + "25/32_1L_4029_NEMA" + ], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_25_ip121", + "time": "2025-10-15T20:39:01.848Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [ + "25/103_1L_3780_NEMA", + "25/32_1L_4029_NEMA" + ], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_25_ip121", + "time": "2025-10-15T21:39:01.850Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [ + "25/103_1L_3780_NEMA", + "25/32_1L_4029_NEMA" + ], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_25_ip121", + "time": "2025-10-15T22:39:01.854Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [ + "25/103_1L_3780_NEMA", + "25/32_1L_4029_NEMA" + ], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_25_ip121", + "time": "2025-10-15T23:39:01.849Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [ + "25/103_1L_3780_NEMA", + "25/32_1L_4029_NEMA" + ], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +} \ No newline at end of file From 41f484c275a13cffad56f6aafc1a7fa51714226d Mon Sep 17 00:00:00 2001 From: Jakub Klena Date: Thu, 16 Oct 2025 02:25:23 +0200 Subject: [PATCH 15/30] Backup senica-RVO33 on 16.10.2025 --- RVO33/addSwitch.py | 36 + RVO33/cloud_topic.py | 76 + RVO33/config | 12 + RVO33/createNode.py | 43 + RVO33/databases/accelerometer_db.js | 3055 ++++++++++++++++ RVO33/databases/modbus_config.js | 114 + RVO33/databases/nodes.table | 10 + .../nodes_original/nodes_original.table | 1 + RVO33/databases/notifications.table | 41 + RVO33/databases/pins.table | 14 + RVO33/databases/relays.table | 5 + RVO33/databases/settings.table | 2 + RVO33/databases/tbdata.nosql | 4 + RVO33/databases/tbdatacloud.nosql | 3 + RVO33/databases/total_energy.js | 38 + RVO33/debug.js | 16 + RVO33/err.txt | 52 + RVO33/flow/cloudmqttconnect.js | 357 ++ RVO33/flow/cmd_manager.js | 3071 ++++++++++++++++ RVO33/flow/code.js | 90 + RVO33/flow/comment.js | 11 + RVO33/flow/count.js | 60 + RVO33/flow/db_connector.js | 286 ++ RVO33/flow/db_init.js | 113 + RVO33/flow/debug.js | 100 + RVO33/flow/designer.json | 3102 +++++++++++++++++ RVO33/flow/dido_controller.js | 1486 ++++++++ RVO33/flow/helper/DataToTbHandler.js | 187 + RVO33/flow/helper/ErrorToServiceHandler.js | 91 + RVO33/flow/helper/db_helper.js | 44 + RVO33/flow/helper/logger.js | 30 + RVO33/flow/helper/md5.js | 5 + RVO33/flow/helper/notification_reporter.js | 121 + RVO33/flow/helper/register.js | 144 + RVO33/flow/helper/serialport_helper.js | 99 + RVO33/flow/helper/suncalc.js | 317 ++ RVO33/flow/helper/utils.js | 161 + RVO33/flow/httprequest.js | 137 + RVO33/flow/httpresponse.js | 76 + RVO33/flow/httproute.js | 326 ++ RVO33/flow/infosender.js | 81 + RVO33/flow/modbus_reader.js | 346 ++ RVO33/flow/monitorconsumption.js | 156 + RVO33/flow/monitordisk.js | 96 + RVO33/flow/monitormemory.js | 87 + RVO33/flow/nodesdb_changecheck.js | 77 + RVO33/flow/show_dbdata.js | 243 ++ RVO33/flow/slack_filter.js | 188 + RVO33/flow/thermometer.js | 99 + RVO33/flow/trigger.js | 79 + RVO33/flow/variables.txt | 0 RVO33/flow/virtualwirein.js | 43 + RVO33/flow/virtualwireout.js | 41 + RVO33/flow/wsmqttpublish.js | 448 +++ RVO33/monitor.txt | 400 +++ RVO33/package-lock.json | 2125 +++++++++++ RVO33/package.json | 29 + RVO33/release.js | 15 + RVO33/release.js.json | 34 + RVO33/report_data.log | 151 + 60 files changed, 18674 insertions(+) create mode 100755 RVO33/addSwitch.py create mode 100755 RVO33/cloud_topic.py create mode 100755 RVO33/config create mode 100755 RVO33/createNode.py create mode 100755 RVO33/databases/accelerometer_db.js create mode 100755 RVO33/databases/modbus_config.js create mode 100755 RVO33/databases/nodes.table create mode 100755 RVO33/databases/nodes_original/nodes_original.table create mode 100755 RVO33/databases/notifications.table create mode 100755 RVO33/databases/pins.table create mode 100755 RVO33/databases/relays.table create mode 100755 RVO33/databases/settings.table create mode 100755 RVO33/databases/tbdata.nosql create mode 100755 RVO33/databases/tbdatacloud.nosql create mode 100755 RVO33/databases/total_energy.js create mode 100755 RVO33/debug.js create mode 100755 RVO33/err.txt create mode 100755 RVO33/flow/cloudmqttconnect.js create mode 100755 RVO33/flow/cmd_manager.js create mode 100755 RVO33/flow/code.js create mode 100755 RVO33/flow/comment.js create mode 100755 RVO33/flow/count.js create mode 100755 RVO33/flow/db_connector.js create mode 100755 RVO33/flow/db_init.js create mode 100755 RVO33/flow/debug.js create mode 100755 RVO33/flow/designer.json create mode 100755 RVO33/flow/dido_controller.js create mode 100755 RVO33/flow/helper/DataToTbHandler.js create mode 100755 RVO33/flow/helper/ErrorToServiceHandler.js create mode 100755 RVO33/flow/helper/db_helper.js create mode 100755 RVO33/flow/helper/logger.js create mode 100755 RVO33/flow/helper/md5.js create mode 100755 RVO33/flow/helper/notification_reporter.js create mode 100755 RVO33/flow/helper/register.js create mode 100755 RVO33/flow/helper/serialport_helper.js create mode 100755 RVO33/flow/helper/suncalc.js create mode 100755 RVO33/flow/helper/utils.js create mode 100755 RVO33/flow/httprequest.js create mode 100755 RVO33/flow/httpresponse.js create mode 100755 RVO33/flow/httproute.js create mode 100755 RVO33/flow/infosender.js create mode 100755 RVO33/flow/modbus_reader.js create mode 100755 RVO33/flow/monitorconsumption.js create mode 100755 RVO33/flow/monitordisk.js create mode 100755 RVO33/flow/monitormemory.js create mode 100755 RVO33/flow/nodesdb_changecheck.js create mode 100755 RVO33/flow/show_dbdata.js create mode 100755 RVO33/flow/slack_filter.js create mode 100755 RVO33/flow/thermometer.js create mode 100755 RVO33/flow/trigger.js create mode 100755 RVO33/flow/variables.txt create mode 100755 RVO33/flow/virtualwirein.js create mode 100755 RVO33/flow/virtualwireout.js create mode 100755 RVO33/flow/wsmqttpublish.js create mode 100755 RVO33/monitor.txt create mode 100755 RVO33/package-lock.json create mode 100755 RVO33/package.json create mode 100755 RVO33/release.js create mode 100755 RVO33/release.js.json create mode 100755 RVO33/report_data.log diff --git a/RVO33/addSwitch.py b/RVO33/addSwitch.py new file mode 100755 index 0000000..c35e96b --- /dev/null +++ b/RVO33/addSwitch.py @@ -0,0 +1,36 @@ +import os + +def process_set_file(): + """ + Checks if /root/flowserver exists, reads set.txt, and modifies the second line. + """ + default_folder = "/root/flowserver" if os.path.exists("/root/flowserver") else "/home/unipi/flowserver" + flag = 1 if default_folder == "/root/flowserver" else 0 + + try: + with open("/home/unipi/flowserver/databases/settings.table", "r") as f: + lines = f.readlines() + + if len(lines) >= 2: + lines[0] = lines[0].rstrip('\n') + "|main_switch:boolean\n" + second_line = lines[1].strip() # remove trailing newline + last_pipe_index = second_line.rfind("|") + + if last_pipe_index != -1: + modified_line = second_line[:last_pipe_index + 1] + str(flag) + "|" + second_line[last_pipe_index + 1:] + lines[1] = modified_line + else: + print("Warning: No '|' character found in the second line of set.txt") + + with open("/home/unipi/flowserver/databases/settings.table", "w") as f: + f.writelines(lines) + else: + print("Warning: settings.table has less than two lines.") + + except FileNotFoundError: + print("Error: settings.table not found.") + except Exception as e: + print(e) + +# if __name__ == "__main__": +process_set_file() diff --git a/RVO33/cloud_topic.py b/RVO33/cloud_topic.py new file mode 100755 index 0000000..77c31f1 --- /dev/null +++ b/RVO33/cloud_topic.py @@ -0,0 +1,76 @@ +# import os +# +# def modify_file(file_path): +# """ +# Modifies the given file by: +# 1. Appending "|cloud_topic" to the first line. +# 2. Inserting the text from the third "." to the first "|" on the second line after the last "|" character. +# +# Args: +# file_path (str): The path to the file to be modified. +# """ +# +# with open(file_path, 'r+') as f: +# lines = f.readlines() +# +# # Modify the first line +# lines[0] += "|cloud_topic:string" +# +# # Modify the second line +# second_line = lines[1].strip() # Remove leading/trailing whitespace +# first_pipe_index = second_line.find('|') +# third_dot_index = second_line.find('.', second_line.find('.', second_line.find('.') + 1) + 1) +# text_to_insert = second_line[third_dot_index:first_pipe_index] +# +# last_pipe_index = second_line.rfind('|') +# lines[1] = second_line[:last_pipe_index + 1] + text_to_insert + "|" + second_line[last_pipe_index + 1:] +# +# print(first_pipe_index, third_dot_index, text_to_insert, last_pipe_index) +# # Write the modified lines back to the file +# # f.seek(0) +# # f.writelines(lines) +# # f.truncate() +# +# # Example usage: +# file_path = "settings.table" # Replace with the actual file path +# modify_file(file_path) +# + + +def modify_file(file_path): + """ + Modifies the given file by: + 1. Appending "|cloud_topic" to the first line. + 2. Inserting the text between the third "." and the second "|" on the second line after the last "|" character. + + Args: + file_path (str): The path to the file to be modified. + """ + + with open(file_path, 'r+') as f: + lines = f.readlines() + + first_line = lines[0].strip() + first_line += "|cloud_topic:string\n" + # Modify the first line + lines[0] = first_line + + # Modify the second line + second_line = lines[1].strip() # Remove leading/trailing whitespace + first_pipe_index = second_line.find('|') + second_pipe_index = second_line.find('|', first_pipe_index + 1) + third_dot_index = second_line.find('.', second_line.find('.', second_line.find('.') + 1) + 1) + text_to_insert = "u" + second_line[third_dot_index+1:second_pipe_index] + + last_pipe_index = second_line.rfind('|') + lines[1] = second_line[:last_pipe_index + 1] + text_to_insert + "|" + second_line[last_pipe_index + 1:] + + print(first_pipe_index, third_dot_index, text_to_insert, last_pipe_index) + # Write the modified lines back to the file + f.seek(0) + f.writelines(lines) + f.truncate() + +# Example usage: +file_path = "/home/unipi/flowserver/databases/settings.table" # Replace with the actual file path +modify_file(file_path) diff --git a/RVO33/config b/RVO33/config new file mode 100755 index 0000000..cd0a8a9 --- /dev/null +++ b/RVO33/config @@ -0,0 +1,12 @@ +name : Total.js Flow +default_timezone : Europe/Bratislava + +// Packages settings +package#flow (Object) : { url: '/' } + + +table.relays : line:number|tbname:string|contactor:number|profile:string +table.nodes : node:number|pole_number:string|node_type:string|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|project_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|cloud_topic:string|has_main_switch:boolean|daily_report:boolean|send_changed_node_numbers:boolean +table.pins : pin:string|type:string|line:number +table.notifications : key:string|weight:string|sk:string|en:string diff --git a/RVO33/createNode.py b/RVO33/createNode.py new file mode 100755 index 0000000..a8cea91 --- /dev/null +++ b/RVO33/createNode.py @@ -0,0 +1,43 @@ +print("zaciname") +import re, json + +search_str = '|' +final = [] +counter = 1 +with open("/home/unipi/flowserver/databases/nodes.table", 'r') as file: +# with open("/home/rasta5man/dev/oms/flowserver/databases/nodes.table", 'r') as file: + # Read each line in the file + for line in file: + # Print each line + line = line.strip() + print(line) + if counter != 1: + i = [m.start() for m in re.finditer(re.escape(search_str), line)] + node = line[ i[0] + 1 : i[1] ] + tbname = line[ i[3] + 1 : i[4] ] + final.append({node:tbname}) + counter += 1 +print(json.dumps(final)) +f = open("/home/unipi/flowserver/databases/nodes_original/nodes_original.table", "w") +f.write(json.dumps(final)) +f.close() + + +# +# # ``d`` has to be replaced with a different character +# old_character = "'" +# +# # ``t`` will replace ``d` +# new_character = '"' +# resultant_string = 0; +# with open("/home/unipi/flowserver/databases/nodes_original/nodes_original.table", 'r') as file: +# for line in file: +# resultant_string = re.sub("'", '"', line) +# +# resultant_string = re.sub(" ", "", resultant_string) +# print(resultant_string) +# +# f = open("/home/unipi/flowserver/databases/nodes_original/nodes_original.table", "w") +# f.write(str(resultant_string)) +# f.close() +# diff --git a/RVO33/databases/accelerometer_db.js b/RVO33/databases/accelerometer_db.js new file mode 100755 index 0000000..fdfc7fd --- /dev/null +++ b/RVO33/databases/accelerometer_db.js @@ -0,0 +1,3055 @@ +let naklony = { + "3993": { "label": "1/3A", "naklon": 0 }, + "3989": { "label": "1/3B", "naklon": 15 }, + "3976": { "label": "1/1", "naklon": 0 }, + "4181": { "label": "1/2", "naklon": 0 }, + "4376": { "label": "1/4", "naklon": 15 }, + "3868": { "label": "1/5", "naklon": 15 }, + "3728": { "label": "1/6", "naklon": 15 }, + "3730": { "label": "1/7", "naklon": 0 }, + "4374": { "label": "1/8", "naklon": 0 }, + "3718": { "label": "1/9", "naklon": 15 }, + "4375": { "label": "1/10", "naklon": 15 }, + "4172": { "label": "1/11", "naklon": 15 }, + "4176": { "label": "1/12", "naklon": 15 }, + "3800": { "label": "2/1", "naklon": 5 }, + "3823": { "label": "2/2", "naklon": 5 }, + "3905": { "label": "2/3", "naklon": 5 }, + "3803": { "label": "2/4", "naklon": 5 }, + "3817": { "label": "2/5", "naklon": 5 }, + "3818": { "label": "2/6", "naklon": 5 }, + "3811": { "label": "2/7", "naklon": 5 }, + "3915": { "label": "2/8", "naklon": 5 }, + "3843": { "label": "2/9", "naklon": 10 }, + "3827": { "label": "2/10", "naklon": 10 }, + "4220": { "label": "2/11", "naklon": 10 }, + "3826": { "label": "2/12", "naklon": 10 }, + "3834": { "label": "2/13", "naklon": 10 }, + "3838": { "label": "2/14", "naklon": 10 }, + "2823": { "label": "2/15", "naklon": 10 }, + "3750": { "label": "2/16", "naklon": 10 }, + "3378": { "label": "2/17", "naklon": 0 }, + "3376": { "label": "2/18", "naklon": 0 }, + "3379": { "label": "2/19", "naklon": 0 }, + "3285": { "label": "2/20", "naklon": 0 }, + "3382": { "label": "2/21", "naklon": 0 }, + "3383": { "label": "2/22", "naklon": 0 }, + "3375": { "label": "2/24", "naklon": 0 }, + "3381": { "label": "2/25", "naklon": 0 }, + "3380": { "label": "2/26", "naklon": 0 }, + "3828": { "label": "2/27", "naklon": 10 }, + "3377": { "label": "2/28", "naklon": 0 }, + "3591": { "label": "7/1", "naklon": 0 }, + "3587": { "label": "7/2", "naklon": 0 }, + "3468": { "label": "7/3", "naklon": 0 }, + "3466": { "label": "7/4", "naklon": 0 }, + "3474": { "label": "7/5", "naklon": 0 }, + "3481": { "label": "7/6", "naklon": 0 }, + "3589": { "label": "7/7", "naklon": 0 }, + "3472": { "label": "7/8", "naklon": 0 }, + "3473": { "label": "7/9", "naklon": 0 }, + "3584": { "label": "7/10", "naklon": 0 }, + "3571": { "label": "7/11", "naklon": 0 }, + "3476": { "label": "7/12", "naklon": 0 }, + "3590": { "label": "7/13", "naklon": 0 }, + "3478": { "label": "7/14", "naklon": 0 }, + "3471": { "label": "7/15", "naklon": 0 }, + "3467": { "label": "7/16", "naklon": 0 }, + "3479": { "label": "7/17", "naklon": 0 }, + "3480": { "label": "7/18", "naklon": 0 }, + "3477": { "label": "7/19", "naklon": 0 }, + "3362": { "label": "12/1", "naklon": 0 }, + "3355": { "label": "12/2", "naklon": 0 }, + "3356": { "label": "12/3", "naklon": 0 }, + "3349": { "label": "12/4", "naklon": 0 }, + "3357": { "label": "12/5", "naklon": 0 }, + "3350": { "label": "12/6", "naklon": 0 }, + "3353": { "label": "12/7", "naklon": 0 }, + "3539": { "label": "12/8", "naklon": 0 }, + "3050": { "label": "12/9", "naklon": 0 }, + "3361": { "label": "12/10", "naklon": 0 }, + "3360": { "label": "12/11", "naklon": 0 }, + "3358": { "label": "12/12", "naklon": 0 }, + "3541": { "label": "12/13", "naklon": 0 }, + "3551": { "label": "12/14", "naklon": 0 }, + "3514": { "label": "12/15", "naklon": 0 }, + "3547": { "label": "12/16", "naklon": 0 }, + "3562": { "label": "12/17", "naklon": 0 }, + "3525": { "label": "12/18", "naklon": 0 }, + "3558": { "label": "12/19", "naklon": 0 }, + "3511": { "label": "12/20", "naklon": 0 }, + "3058": { "label": "12/21", "naklon": 0 }, + "3062": { "label": "12/22", "naklon": 0 }, + "3070": { "label": "12/23", "naklon": 0 }, + "3447": { "label": "12/24", "naklon": 0 }, + "3056": { "label": "12/25", "naklon": 0 }, + "3057": { "label": "12/26", "naklon": 0 }, + "3071": { "label": "12/27", "naklon": 0 }, + "3061": { "label": "12/28", "naklon": 0 }, + "3069": { "label": "12/29", "naklon": 0 }, + "3077": { "label": "12/30", "naklon": 0 }, + "3080": { "label": "12/31", "naklon": 0 }, + "3081": { "label": "12/32", "naklon": 0 }, + "3078": { "label": "12/33", "naklon": 0 }, + "4037": { "label": "12/34", "naklon": 0 }, + "3067": { "label": "12/35", "naklon": 0 }, + "3051": { "label": "12/36", "naklon": 0 }, + "2924": { "label": "12/37", "naklon": 0 }, + "3060": { "label": "12/38", "naklon": 0 }, + "3073": { "label": "12/39", "naklon": 0 }, + "3469": { "label": "12/40", "naklon": 0 }, + "2923": { "label": "12/41", "naklon": 0 }, + "2925": { "label": "12/42", "naklon": 0 }, + "3359": { "label": "12/43", "naklon": 0 }, + "3055": { "label": "12/44", "naklon": 0 }, + "2922": { "label": "12/45", "naklon": 0 }, + "3084": { "label": "12/46", "naklon": 0 }, + "3064": { "label": "12/47", "naklon": 0 }, + "3066": { "label": "12/48", "naklon": 0 }, + "3072": { "label": "12/49", "naklon": 0 }, + "3415": { "label": "13/13A", "naklon": 0 }, + "3409": { "label": "13/13B", "naklon": 0 }, + "3399": { "label": "13/13C", "naklon": 0 }, + "3410": { "label": "13/29A", "naklon": 0 }, + "3407": { "label": "13/29B", "naklon": 0 }, + "3405": { "label": "13/34A", "naklon": 0 }, + "3404": { "label": "13/34B", "naklon": 0 }, + "3392": { "label": "13/45A", "naklon": 0 }, + "3386": { "label": "13/45B", "naklon": 0 }, + "3303": { "label": "13/60A", "naklon": 3 }, + "3302": { "label": "13/60B", "naklon": 3 }, + "3319": { "label": "13/70A", "naklon": 6 }, + "3317": { "label": "13/70B", "naklon": 6 }, + "3326": { "label": "13/70C", "naklon": 6 }, + "3351": { "label": "13/73A", "naklon": 6 }, + "3313": { "label": "13/73B", "naklon": 6 }, + "3316": { "label": "13/83A", "naklon": 0 }, + "3320": { "label": "13/83B", "naklon": 0 }, + "3336": { "label": "13/95A", "naklon": 0 }, + "3323": { "label": "13/95B", "naklon": 0 }, + "3339": { "label": "13/98A", "naklon": 0 }, + "3333": { "label": "13/98B", "naklon": 0 }, + "3425": { "label": "13/1", "naklon": 0 }, + "3419": { "label": "13/2", "naklon": 0 }, + "3416": { "label": "13/3", "naklon": 0 }, + "3332": { "label": "13/4", "naklon": 0 }, + "3422": { "label": "13/5", "naklon": 0 }, + "3417": { "label": "13/6", "naklon": 0 }, + "3418": { "label": "13/7", "naklon": 0 }, + "3424": { "label": "13/8", "naklon": 0 }, + "3334": { "label": "13/9", "naklon": 0 }, + "4363": { "label": "13/10", "naklon": 0 }, + "3423": { "label": "13/11", "naklon": 0 }, + "3406": { "label": "13/12", "naklon": 0 }, + "3411": { "label": "13/14", "naklon": 0 }, + "3412": { "label": "13/15", "naklon": 0 }, + "3413": { "label": "13/16", "naklon": 0 }, + "3414": { "label": "13/17", "naklon": 0 }, + "3391": { "label": "13/18", "naklon": 0 }, + "3370": { "label": "13/19", "naklon": 0 }, + "3369": { "label": "13/20", "naklon": 0 }, + "3408": { "label": "13/21", "naklon": 0 }, + "3393": { "label": "13/22", "naklon": 0 }, + "3128": { "label": "13/23", "naklon": 0 }, + "3197": { "label": "13/24", "naklon": 0 }, + "4364": { "label": "13/25", "naklon": 0 }, + "3155": { "label": "13/26", "naklon": 0 }, + "3196": { "label": "13/27", "naklon": 0 }, + "3144": { "label": "13/28", "naklon": 0 }, + "3150": { "label": "13/30", "naklon": 0 }, + "3390": { "label": "13/31", "naklon": 0 }, + "3401": { "label": "13/32", "naklon": 0 }, + "3275": { "label": "13/33", "naklon": 0 }, + "3371": { "label": "13/35", "naklon": 0 }, + "3389": { "label": "13/36", "naklon": 0 }, + "3388": { "label": "13/37", "naklon": 0 }, + "3365": { "label": "13/38", "naklon": 0 }, + "3363": { "label": "13/39", "naklon": 0 }, + "3397": { "label": "13/40", "naklon": 0 }, + "3567": { "label": "13/40/1", "naklon": 0 }, + "3387": { "label": "13/41", "naklon": 0 }, + "3403": { "label": "13/42", "naklon": 0 }, + "3147": { "label": "13/43", "naklon": 0 }, + "3141": { "label": "13/44", "naklon": 0 }, + "3364": { "label": "13/46", "naklon": 0 }, + "3367": { "label": "13/47", "naklon": 0 }, + "3368": { "label": "13/48", "naklon": 0 }, + "3402": { "label": "13/49", "naklon": 0 }, + "3366": { "label": "13/50", "naklon": 0 }, + "3395": { "label": "13/51", "naklon": 0 }, + "3372": { "label": "13/52", "naklon": 0 }, + "3394": { "label": "13/53", "naklon": 0 }, + "3308": { "label": "13/54", "naklon": 0 }, + "3847": { "label": "13/54/1", "naklon": 0 }, + "3312": { "label": "13/55", "naklon": 3 }, + "3309": { "label": "13/56", "naklon": 3 }, + "3311": { "label": "13/57", "naklon": 3 }, + "3310": { "label": "13/58", "naklon": 3 }, + "4365": { "label": "13/59", "naklon": 3 }, + "4093": { "label": "13/60/1", "naklon": 3 }, + "3304": { "label": "13/61", "naklon": 3 }, + "3307": { "label": "13/62", "naklon": 3 }, + "3271": { "label": "13/63", "naklon": 3 }, + "3301": { "label": "13/64", "naklon": 3 }, + "4366": { "label": "13/65", "naklon": 3 }, + "3300": { "label": "13/66", "naklon": 3 }, + "3185": { "label": "13/67", "naklon": 0 }, + "3184": { "label": "13/68", "naklon": 0 }, + "3188": { "label": "13/69", "naklon": 0 }, + "3343": { "label": "13/71", "naklon": 6 }, + "3819": { "label": "13/71/1", "naklon": 6 }, + "3880": { "label": "13/71/2", "naklon": 6 }, + "3348": { "label": "13/72", "naklon": 6 }, + "3344": { "label": "13/74", "naklon": 6 }, + "3346": { "label": "13/75", "naklon": 6 }, + "3597": { "label": "13/75/1", "naklon": 6 }, + "3345": { "label": "13/76", "naklon": 6 }, + "3322": { "label": "13/77", "naklon": 0 }, + "3325": { "label": "13/78", "naklon": 0 }, + "4310": { "label": "13/78/1", "naklon": 0 }, + "3315": { "label": "13/79", "naklon": 0 }, + "3328": { "label": "13/80", "naklon": 0 }, + "3321": { "label": "13/81", "naklon": 0 }, + "3324": { "label": "13/82", "naklon": 0 }, + "3140": { "label": "13/84", "naklon": 0 }, + "3153": { "label": "13/85", "naklon": 0 }, + "3145": { "label": "13/86", "naklon": 0 }, + "3134": { "label": "13/87", "naklon": 0 }, + "3151": { "label": "13/88", "naklon": 0 }, + "3143": { "label": "13/89", "naklon": 0 }, + "3318": { "label": "13/90", "naklon": 0 }, + "3347": { "label": "13/91", "naklon": 0 }, + "3314": { "label": "13/94", "naklon": 0 }, + "3331": { "label": "13/96", "naklon": 0 }, + "3327": { "label": "13/97", "naklon": 0 }, + "3329": { "label": "13/99", "naklon": 0 }, + "3337": { "label": "13/100", "naklon": 0 }, + "3330": { "label": "13/101", "naklon": 0 }, + "3335": { "label": "13/102", "naklon": 0 }, + "3420": { "label": "13/103", "naklon": 0 }, + "3421": { "label": "13/104", "naklon": 0 }, + "4361": { "label": "13/105", "naklon": 0 }, + "4362": { "label": "13/106", "naklon": 0 }, + "3526": { "label": "13/107", "naklon": 0 }, + "4424": { "label": "13/108", "naklon": null }, + "3561": { "label": "13/109", "naklon": null }, + "3527": { "label": "13/110", "naklon": null }, + "3521": { "label": "13/111", "naklon": null }, + "3552": { "label": "13/112", "naklon": null }, + "3544": { "label": "13/113", "naklon": null }, + "3534": { "label": "13/114", "naklon": null }, + "3516": { "label": "13/115", "naklon": null }, + "3513": { "label": "13/116", "naklon": null }, + "3565": { "label": "13/117", "naklon": null }, + "3866": { "label": "13/118", "naklon": null }, + "3136": { "label": "14/1", "naklon": 0 }, + "3137": { "label": "14/2", "naklon": 0 }, + "3135": { "label": "14/3", "naklon": 0 }, + "3149": { "label": "14/4", "naklon": 0 }, + "3142": { "label": "14/5", "naklon": 0 }, + "3342": { "label": "14/6", "naklon": 0 }, + "3340": { "label": "14/7", "naklon": 0 }, + "3152": { "label": "14/8", "naklon": 0 }, + "3886": { "label": "14/9", "naklon": 0 }, + "3341": { "label": "14/10", "naklon": null }, + "3352": { "label": "14/11", "naklon": null }, + "3396": { "label": "15/1", "naklon": 5 }, + "2784": { "label": "15/2", "naklon": 5 }, + "2788": { "label": "15/3", "naklon": 5 }, + "2801": { "label": "15/4", "naklon": 5 }, + "2815": { "label": "15/5", "naklon": 5 }, + "2829": { "label": "15/6", "naklon": 5 }, + "2796": { "label": "15/7", "naklon": 5 }, + "2803": { "label": "15/8", "naklon": 5 }, + "4304": { "label": "15/8/1", "naklon": 5 }, + "4311": { "label": "15/8/2", "naklon": 5 }, + "2821": { "label": "15/9", "naklon": 5 }, + "3400": { "label": "15/10", "naklon": 5 }, + "2799": { "label": "15/11", "naklon": 5 }, + "2804": { "label": "15/12", "naklon": 5 }, + "4303": { "label": "15/12/1", "naklon": 5 }, + "4309": { "label": "15/12/2", "naklon": 5 }, + "2806": { "label": "15/13", "naklon": 5 }, + "2787": { "label": "15/14", "naklon": 5 }, + "2809": { "label": "15/15", "naklon": 5 }, + "2814": { "label": "15/16", "naklon": 0 }, + "3934": { "label": "15/17", "naklon": 0 }, + "3192": { "label": "15/18", "naklon": 0 }, + "2812": { "label": "15/19", "naklon": 0 }, + "4070": { "label": "15/20", "naklon": 0 }, + "2826": { "label": "15/21", "naklon": 0 }, + "2808": { "label": "15/22", "naklon": 3 }, + "2795": { "label": "15/23", "naklon": 3 }, + "2807": { "label": "15/24", "naklon": 3 }, + "2831": { "label": "15/25", "naklon": 0 }, + "2862": { "label": "15/26", "naklon": null }, + "2861": { "label": "15/27", "naklon": 0 }, + "2866": { "label": "15/28", "naklon": 0 }, + "3546": { "label": "15/28/1", "naklon": 0 }, + "4146": { "label": "15/29", "naklon": 0 }, + "3001": { "label": "15/29/1", "naklon": 0 }, + "2835": { "label": "15/30", "naklon": 0 }, + "2874": { "label": "15/31", "naklon": 0 }, + "2852": { "label": "15/32", "naklon": 0 }, + "2851": { "label": "15/33", "naklon": 0 }, + "3560": { "label": "15/33/1", "naklon": 0 }, + "2858": { "label": "15/34", "naklon": 0 }, + "4306": { "label": "15/34/1", "naklon": 0 }, + "2856": { "label": "15/35", "naklon": 0 }, + "2847": { "label": "15/36", "naklon": 0 }, + "3556": { "label": "15/36/1", "naklon": 0 }, + "3950": { "label": "15/37", "naklon": 0 }, + "2848": { "label": "15/38", "naklon": 0 }, + "2863": { "label": "15/39", "naklon": 0 }, + "4313": { "label": "15/39/1", "naklon": 0 }, + "2873": { "label": "15/40", "naklon": 0 }, + "2984": { "label": "15/40/1", "naklon": 0 }, + "2854": { "label": "15/41", "naklon": 0 }, + "2859": { "label": "15/42", "naklon": 0 }, + "2872": { "label": "15/43", "naklon": 0 }, + "2849": { "label": "15/44", "naklon": 0 }, + "2864": { "label": "15/45", "naklon": 0 }, + "3553": { "label": "15/46", "naklon": null }, + "3021": { "label": "15/47", "naklon": null }, + "3008": { "label": "15/47/1", "naklon": null }, + "3017": { "label": "15/48", "naklon": null }, + "3014": { "label": "15/49", "naklon": null }, + "2981": { "label": "15/50", "naklon": null }, + "3020": { "label": "15/51", "naklon": null }, + "3027": { "label": "15/52", "naklon": null }, + "3006": { "label": "15/53", "naklon": null }, + "3012": { "label": "15/54", "naklon": null }, + "2738": { "label": "15/55", "naklon": 0 }, + "2725": { "label": "15/56", "naklon": 0 }, + "3016": { "label": "15/57", "naklon": null }, + "3005": { "label": "15/58", "naklon": null }, + "3009": { "label": "15/58/1", "naklon": null }, + "3010": { "label": "15/59", "naklon": 0 }, + "3538": { "label": "15/59/1", "naklon": 0 }, + "4145": { "label": "15/59/2", "naklon": 0 }, + "2713": { "label": "15/60", "naklon": 0 }, + "2789": { "label": "15/61", "naklon": 0 }, + "2736": { "label": "15/62", "naklon": 0 }, + "2739": { "label": "15/63", "naklon": 0 }, + "4346": { "label": "15/64", "naklon": 0 }, + "2731": { "label": "15/65", "naklon": 0 }, + "2818": { "label": "15/66", "naklon": 0 }, + "3557": { "label": "15/66/1", "naklon": 0 }, + "2822": { "label": "15/67", "naklon": 0 }, + "2833": { "label": "15/68", "naklon": 0 }, + "2834": { "label": "15/69", "naklon": 0 }, + "3097": { "label": "15/70", "naklon": 0 }, + "2824": { "label": "15/71", "naklon": 0 }, + "2828": { "label": "15/72", "naklon": 0 }, + "2600": { "label": "15/73", "naklon": 0 }, + "4314": { "label": "15/73/1", "naklon": 0 }, + "2832": { "label": "15/74", "naklon": 0 }, + "4360": { "label": "15/75", "naklon": 0 }, + "2846": { "label": "15/76", "naklon": 0 }, + "2584": { "label": "15/77", "naklon": 0 }, + "2843": { "label": "15/78", "naklon": 0 }, + "4308": { "label": "15/78/1", "naklon": 0 }, + "4144": { "label": "15/79", "naklon": null }, + "2844": { "label": "15/80", "naklon": 0 }, + "2842": { "label": "15/81", "naklon": 0 }, + "2838": { "label": "15/82", "naklon": 0 }, + "2837": { "label": "15/83", "naklon": null }, + "3555": { "label": "15/83/1", "naklon": null }, + "2839": { "label": "15/84", "naklon": 0 }, + "2830": { "label": "15/85", "naklon": 0 }, + "4066": { "label": "15/86", "naklon": 0 }, + "2836": { "label": "15/87", "naklon": 0 }, + "2911": { "label": "15/88", "naklon": 0 }, + "2825": { "label": "15/89", "naklon": 0 }, + "2811": { "label": "15/90", "naklon": 0 }, + "3740": { "label": "15/94", "naklon": 15 }, + "2734": { "label": "15/95", "naklon": 15 }, + "3105": { "label": "15/96", "naklon": 15 }, + "2732": { "label": "15/97", "naklon": 15 }, + "2727": { "label": "15/98", "naklon": 15 }, + "2735": { "label": "15/99", "naklon": 15 }, + "3926": { "label": "15/100", "naklon": 15 }, + "2918": { "label": "15/101", "naklon": 0 }, + "2705": { "label": "15/102", "naklon": 10 }, + "2708": { "label": "15/103", "naklon": 10 }, + "2721": { "label": "15/104", "naklon": 10 }, + "2719": { "label": "15/105", "naklon": 10 }, + "2919": { "label": "15/106", "naklon": 10 }, + "3101": { "label": "15/107", "naklon": 10 }, + "2853": { "label": "15/108", "naklon": 10 }, + "2715": { "label": "15/109", "naklon": 10 }, + "2712": { "label": "15/110", "naklon": 0 }, + "2711": { "label": "15/111", "naklon": 0 }, + "2709": { "label": "15/112", "naklon": 0 }, + "2710": { "label": "15/113", "naklon": 0 }, + "2907": { "label": "15/114", "naklon": 0 }, + "2906": { "label": "15/115", "naklon": 0 }, + "2908": { "label": "15/116", "naklon": 0 }, + "2901": { "label": "15/117", "naklon": 0 }, + "2913": { "label": "15/118", "naklon": 0 }, + "3656": { "label": "15/119", "naklon": 0 }, + "2781": { "label": "15/120", "naklon": 0 }, + "2802": { "label": "15/121", "naklon": 0 }, + "2791": { "label": "15/122", "naklon": 0 }, + "2783": { "label": "15/123", "naklon": 0 }, + "2794": { "label": "15/124", "naklon": 0 }, + "3139": { "label": "15/125", "naklon": 0 }, + "3229": { "label": "15/126", "naklon": 5 }, + "3239": { "label": "15/127", "naklon": 5 }, + "3230": { "label": "15/128", "naklon": 5 }, + "4016": { "label": "15/129", "naklon": null }, + "3608": { "label": "16/16A", "naklon": 0 }, + "4151": { "label": "16/16B", "naklon": 0 }, + "3710": { "label": "16/1", "naklon": 0 }, + "3726": { "label": "16/2", "naklon": 0 }, + "3743": { "label": "16/3", "naklon": 0 }, + "3724": { "label": "16/4", "naklon": 0 }, + "3712": { "label": "16/5", "naklon": 0 }, + "3739": { "label": "16/6", "naklon": 0 }, + "3742": { "label": "16/7", "naklon": 0 }, + "3731": { "label": "16/8", "naklon": 0 }, + "3727": { "label": "16/9", "naklon": 0 }, + "3729": { "label": "16/10", "naklon": 0 }, + "3736": { "label": "16/11", "naklon": 0 }, + "3713": { "label": "16/12", "naklon": 0 }, + "3715": { "label": "16/13", "naklon": 0 }, + "3733": { "label": "16/14", "naklon": 0 }, + "3732": { "label": "16/15", "naklon": 0 }, + "3634": { "label": "16/17", "naklon": 0 }, + "3610": { "label": "16/18", "naklon": 0 }, + "3626": { "label": "16/19", "naklon": 0 }, + "3618": { "label": "16/20", "naklon": 0 }, + "3619": { "label": "16/21", "naklon": 0 }, + "3628": { "label": "16/22", "naklon": 0 }, + "3615": { "label": "16/23", "naklon": 0 }, + "3609": { "label": "16/24", "naklon": 0 }, + "3606": { "label": "16/25", "naklon": 0 }, + "3624": { "label": "16/26", "naklon": 0 }, + "3627": { "label": "16/27", "naklon": 0 }, + "3607": { "label": "16/28", "naklon": 0 }, + "4370": { "label": "16/29", "naklon": 0 }, + "3692": { "label": "16/30", "naklon": 0 }, + "3614": { "label": "16/31", "naklon": 0 }, + "3623": { "label": "16/32", "naklon": 0 }, + "4373": { "label": "16/33", "naklon": 0 }, + "3620": { "label": "16/34", "naklon": 0 }, + "3685": { "label": "16/35", "naklon": 0 }, + "3616": { "label": "16/36", "naklon": 0 }, + "3686": { "label": "16/37", "naklon": 0 }, + "3688": { "label": "16/38", "naklon": 0 }, + "3684": { "label": "16/39", "naklon": 0 }, + "3825": { "label": "16/40", "naklon": 0 }, + "3865": { "label": "16/41", "naklon": 0 }, + "3824": { "label": "16/42", "naklon": 0 }, + "3871": { "label": "16/43", "naklon": 0 }, + "3801": { "label": "16/44", "naklon": 0 }, + "3862": { "label": "16/45", "naklon": 0 }, + "3876": { "label": "16/46", "naklon": 0 }, + "3861": { "label": "16/47", "naklon": 0 }, + "4215": { "label": "16/48", "naklon": 0 }, + "3605": { "label": "16/49", "naklon": 10 }, + "3603": { "label": "16/50", "naklon": 10 }, + "3592": { "label": "16/51", "naklon": 10 }, + "3598": { "label": "16/52", "naklon": 10 }, + "3594": { "label": "16/53", "naklon": 10 }, + "3593": { "label": "16/54", "naklon": 10 }, + "3630": { "label": "16/55", "naklon": 10 }, + "3763": { "label": "16/56", "naklon": 10 }, + "3746": { "label": "16/57", "naklon": 10 }, + "3699": { "label": "16/58", "naklon": 0 }, + "3698": { "label": "16/59", "naklon": 0 }, + "3709": { "label": "16/60", "naklon": null }, + "3708": { "label": "16/61", "naklon": 0 }, + "3703": { "label": "16/62", "naklon": null }, + "3700": { "label": "16/63", "naklon": 0 }, + "3701": { "label": "16/64", "naklon": null }, + "3704": { "label": "16/65", "naklon": 0 }, + "3707": { "label": "16/66", "naklon": null }, + "3810": { "label": "16/67", "naklon": 0 }, + "4208": { "label": "16/68", "naklon": null }, + "3867": { "label": "16/69", "naklon": 0 }, + "4372": { "label": "16/70", "naklon": null }, + "3881": { "label": "16/71", "naklon": 0 }, + "4204": { "label": "16/72", "naklon": null }, + "3869": { "label": "16/73", "naklon": 0 }, + "4202": { "label": "16/74", "naklon": null }, + "3830": { "label": "16/75", "naklon": 0 }, + "3870": { "label": "16/76", "naklon": null }, + "3964": { "label": "16/77", "naklon": 0 }, + "3849": { "label": "16/78", "naklon": 0 }, + "3694": { "label": "16/79", "naklon": null }, + "3717": { "label": "16/80", "naklon": 0 }, + "3877": { "label": "16/81", "naklon": null }, + "3755": { "label": "16/82", "naklon": 0 }, + "3725": { "label": "16/83", "naklon": null }, + "3716": { "label": "16/84", "naklon": 0 }, + "3696": { "label": "16/85", "naklon": null }, + "3702": { "label": "16/86", "naklon": 0 }, + "3706": { "label": "16/87", "naklon": null }, + "3850": { "label": "16/88", "naklon": 0 }, + "3848": { "label": "16/89", "naklon": null }, + "3737": { "label": "16/90", "naklon": null }, + "3705": { "label": "16/91", "naklon": 0 }, + "3723": { "label": "16/92", "naklon": null }, + "3842": { "label": "16/93", "naklon": 0 }, + "3735": { "label": "16/94", "naklon": null }, + "3719": { "label": "16/95", "naklon": 0 }, + "3697": { "label": "16/96", "naklon": 0 }, + "3711": { "label": "16/97", "naklon": 0 }, + "4107": { "label": "16/98", "naklon": null }, + "4112": { "label": "16/99", "naklon": 5 }, + "4106": { "label": "16/100", "naklon": 5 }, + "4111": { "label": "16/101", "naklon": 5 }, + "4091": { "label": "16/102", "naklon": null }, + "4104": { "label": "16/103", "naklon": 5 }, + "4094": { "label": "16/104", "naklon": null }, + "4089": { "label": "16/105", "naklon": 5 }, + "4095": { "label": "16/106", "naklon": null }, + "4102": { "label": "16/107", "naklon": 5 }, + "4105": { "label": "16/108", "naklon": null }, + "3859": { "label": "16/109", "naklon": null }, + "4090": { "label": "16/110", "naklon": 5 }, + "4110": { "label": "16/111", "naklon": null }, + "4097": { "label": "16/112", "naklon": 5 }, + "4099": { "label": "16/113", "naklon": null }, + "4096": { "label": "16/114", "naklon": null }, + "4101": { "label": "16/115", "naklon": 5 }, + "4109": { "label": "16/116", "naklon": null }, + "4092": { "label": "16/117", "naklon": 5 }, + "3631": { "label": "16/118", "naklon": null }, + "3632": { "label": "16/119", "naklon": 0 }, + "3641": { "label": "16/120", "naklon": null }, + "3638": { "label": "16/121", "naklon": 0 }, + "3637": { "label": "16/122", "naklon": null }, + "4142": { "label": "16/123", "naklon": null }, + "4147": { "label": "16/124", "naklon": 5 }, + "4139": { "label": "16/125", "naklon": 5 }, + "3172": { "label": "20/30A", "naklon": 2 }, + "3164": { "label": "20/30B", "naklon": 2 }, + "3247": { "label": "20/1", "naklon": 10 }, + "3296": { "label": "20/2", "naklon": 10 }, + "3246": { "label": "20/3", "naklon": 10 }, + "3270": { "label": "20/4", "naklon": 10 }, + "3294": { "label": "20/5", "naklon": 10 }, + "3298": { "label": "20/6", "naklon": 10 }, + "3297": { "label": "20/7", "naklon": 10 }, + "3293": { "label": "20/8", "naklon": 10 }, + "3299": { "label": "20/9", "naklon": 10 }, + "3295": { "label": "20/10", "naklon": 10 }, + "3244": { "label": "20/11", "naklon": 10 }, + "3249": { "label": "20/12", "naklon": 10 }, + "3268": { "label": "20/13", "naklon": 10 }, + "3245": { "label": "20/14", "naklon": 10 }, + "3278": { "label": "20/15", "naklon": 10 }, + "3280": { "label": "20/16", "naklon": 10 }, + "3292": { "label": "20/17", "naklon": 10 }, + "3287": { "label": "20/18", "naklon": 10 }, + "3282": { "label": "20/19", "naklon": 10 }, + "3273": { "label": "20/20", "naklon": 0 }, + "3157": { "label": "20/21", "naklon": 0 }, + "3283": { "label": "20/22", "naklon": 0 }, + "3159": { "label": "20/23", "naklon": 0 }, + "3289": { "label": "20/24", "naklon": 0 }, + "3163": { "label": "20/25", "naklon": 0 }, + "3126": { "label": "20/26", "naklon": 0 }, + "3171": { "label": "20/27", "naklon": 0 }, + "3162": { "label": "20/28", "naklon": 0 }, + "3279": { "label": "20/29", "naklon": 10 }, + "3173": { "label": "20/31", "naklon": 0 }, + "3127": { "label": "20/32", "naklon": 0 }, + "3131": { "label": "20/33", "naklon": 0 }, + "3129": { "label": "20/34", "naklon": 0 }, + "3276": { "label": "20/35", "naklon": 2 }, + "3290": { "label": "20/36", "naklon": 2 }, + "3132": { "label": "20/37", "naklon": 0 }, + "3138": { "label": "20/38", "naklon": 0 }, + "3272": { "label": "20/39", "naklon": 0 }, + "3291": { "label": "20/40", "naklon": 0 }, + "3277": { "label": "20/41", "naklon": 10 }, + "3286": { "label": "20/42", "naklon": 10 }, + "3281": { "label": "20/43", "naklon": 10 }, + "3288": { "label": "20/44", "naklon": 10 }, + "3284": { "label": "20/45", "naklon": 10 }, + "3167": { "label": "20/46", "naklon": 10 }, + "3872": { "label": "20/47", "naklon": 0 }, + "3124": { "label": "20/48", "naklon": 0 }, + "3133": { "label": "20/49", "naklon": 0 }, + "3158": { "label": "20/50", "naklon": 0 }, + "3169": { "label": "20/51", "naklon": 0 }, + "3146": { "label": "20/52", "naklon": 0 }, + "3160": { "label": "20/53", "naklon": 0 }, + "3248": { "label": "20/54", "naklon": 0 }, + "3156": { "label": "20/55", "naklon": 0 }, + "3161": { "label": "20/56", "naklon": 0 }, + "3170": { "label": "20/57", "naklon": 0 }, + "3168": { "label": "20/58", "naklon": 0 }, + "3125": { "label": "20/59", "naklon": 0 }, + "3166": { "label": "20/60", "naklon": 0 }, + "3130": { "label": "20/61", "naklon": 0 }, + "3563": { "label": "20/62", "naklon": 0 }, + "3550": { "label": "20/63", "naklon": null }, + "3269": { "label": "20/67", "naklon": 0 }, + "2921": { "label": "21/1", "naklon": 0 }, + "2707": { "label": "21/2", "naklon": 0 }, + "2723": { "label": "21/3", "naklon": 0 }, + "2716": { "label": "21/4", "naklon": 0 }, + "2717": { "label": "21/5", "naklon": 0 }, + "2720": { "label": "21/6", "naklon": 0 }, + "2722": { "label": "21/7", "naklon": 0 }, + "2718": { "label": "21/8", "naklon": 0 }, + "2724": { "label": "21/9", "naklon": 0 }, + "2742": { "label": "21/10", "naklon": 0 }, + "2743": { "label": "21/11", "naklon": 0 }, + "2733": { "label": "21/12", "naklon": 0 }, + "2903": { "label": "21/14", "naklon": 0 }, + "2917": { "label": "21/15", "naklon": 0 }, + "2897": { "label": "21/16", "naklon": 0 }, + "2914": { "label": "21/17", "naklon": 0 }, + "2898": { "label": "21/18", "naklon": 0 }, + "2773": { "label": "21/19", "naklon": 0 }, + "2895": { "label": "21/20", "naklon": 0 }, + "2896": { "label": "21/21", "naklon": 0 }, + "2771": { "label": "21/22", "naklon": 0 }, + "2772": { "label": "21/23", "naklon": 0 }, + "2793": { "label": "21/24", "naklon": 0 }, + "2902": { "label": "21/25", "naklon": 0 }, + "2910": { "label": "21/26", "naklon": 0 }, + "2909": { "label": "21/27", "naklon": 0 }, + "2920": { "label": "21/28", "naklon": 0 }, + "2916": { "label": "21/29", "naklon": 0 }, + "2904": { "label": "21/30", "naklon": 0 }, + "2915": { "label": "21/31", "naklon": 0 }, + "2905": { "label": "21/32", "naklon": 0 }, + "2900": { "label": "21/33", "naklon": 0 }, + "2899": { "label": "21/34", "naklon": 0 }, + "2741": { "label": "21/36", "naklon": 0 }, + "2714": { "label": "21/37", "naklon": 0 }, + "2701": { "label": "21/38", "naklon": 0 }, + "2703": { "label": "21/39", "naklon": 0 }, + "2704": { "label": "21/40", "naklon": 0 }, + "2702": { "label": "21/41", "naklon": 0 }, + "2706": { "label": "21/42", "naklon": 0 }, + "2776": { "label": "21/43", "naklon": 0 }, + "2770": { "label": "21/44", "naklon": 0 }, + "2786": { "label": "21/45", "naklon": 0 }, + "2779": { "label": "21/46", "naklon": 0 }, + "2782": { "label": "21/47", "naklon": 0 }, + "2785": { "label": "21/48", "naklon": 0 }, + "2769": { "label": "21/49", "naklon": 0 }, + "3354": { "label": "21/50", "naklon": 0 }, + "2778": { "label": "21/51", "naklon": 0 }, + "2775": { "label": "21/52", "naklon": 0 }, + "2780": { "label": "21/53", "naklon": 0 }, + "2790": { "label": "21/54", "naklon": 0 }, + "2792": { "label": "21/55", "naklon": 0 }, + "2774": { "label": "21/56", "naklon": 0 }, + "2630": { "label": "22/1", "naklon": 0 }, + "2631": { "label": "22/2", "naklon": 0 }, + "2632": { "label": "22/3", "naklon": 0 }, + "2633": { "label": "22/4", "naklon": 0 }, + "2634": { "label": "22/5", "naklon": 0 }, + "2636": { "label": "22/6", "naklon": 0 }, + "4367": { "label": "22/7", "naklon": 0 }, + "2637": { "label": "22/8", "naklon": 0 }, + "2638": { "label": "22/9", "naklon": 0 }, + "2639": { "label": "22/10", "naklon": 0 }, + "2640": { "label": "22/11", "naklon": 0 }, + "2641": { "label": "22/12", "naklon": 0 }, + "2642": { "label": "22/13", "naklon": 0 }, + "2643": { "label": "22/14", "naklon": 0 }, + "2644": { "label": "22/15", "naklon": 0 }, + "2645": { "label": "22/16", "naklon": 0 }, + "2646": { "label": "22/17", "naklon": 0 }, + "2647": { "label": "22/18", "naklon": 0 }, + "2648": { "label": "22/19", "naklon": 0 }, + "2649": { "label": "22/20", "naklon": 0 }, + "2650": { "label": "22/21", "naklon": 0 }, + "2651": { "label": "22/22", "naklon": 0 }, + "4103": { "label": "22/23", "naklon": 0 }, + "2653": { "label": "22/24", "naklon": 0 }, + "2654": { "label": "22/25", "naklon": 0 }, + "2655": { "label": "22/26", "naklon": 0 }, + "2656": { "label": "22/27", "naklon": 0 }, + "2657": { "label": "22/28", "naklon": 0 }, + "2658": { "label": "22/29", "naklon": 0 }, + "2659": { "label": "22/30", "naklon": 0 }, + "2660": { "label": "22/31", "naklon": 0 }, + "2661": { "label": "22/32", "naklon": 0 }, + "3015": { "label": "22/32/1", "naklon": 0 }, + "2662": { "label": "22/33", "naklon": 0 }, + "2663": { "label": "22/34", "naklon": 0 }, + "2664": { "label": "22/35", "naklon": 0 }, + "2665": { "label": "22/36", "naklon": 0 }, + "2666": { "label": "22/37", "naklon": 0 }, + "2667": { "label": "22/38", "naklon": 0 }, + "2668": { "label": "22/39", "naklon": 0 }, + "2669": { "label": "22/40", "naklon": null }, + "2670": { "label": "22/41", "naklon": null }, + "2671": { "label": "22/42", "naklon": null }, + "3087": { "label": "23/9A", "naklon": 10 }, + "3090": { "label": "23/9B", "naklon": 10 }, + "3075": { "label": "23/1", "naklon": 0 }, + "3089": { "label": "23/2", "naklon": 0 }, + "3088": { "label": "23/3", "naklon": 0 }, + "3228": { "label": "23/4", "naklon": 10 }, + "2751": { "label": "23/5", "naklon": 10 }, + "3243": { "label": "23/6", "naklon": 10 }, + "4349": { "label": "23/7", "naklon": 10 }, + "3102": { "label": "23/8", "naklon": 10 }, + "3099": { "label": "23/10", "naklon": 10 }, + "3103": { "label": "23/11", "naklon": 10 }, + "3093": { "label": "23/12", "naklon": 10 }, + "3098": { "label": "23/13", "naklon": 10 }, + "3092": { "label": "23/14", "naklon": 10 }, + "3233": { "label": "23/15", "naklon": 0 }, + "3095": { "label": "23/16", "naklon": 0 }, + "4074": { "label": "23/17", "naklon": 0 }, + "2729": { "label": "23/18", "naklon": 0 }, + "3234": { "label": "23/19", "naklon": 0 }, + "3094": { "label": "23/20", "naklon": 0 }, + "2817": { "label": "23/21", "naklon": 0 }, + "3226": { "label": "23/22", "naklon": 0 }, + "3225": { "label": "23/23", "naklon": 0 }, + "3237": { "label": "23/24", "naklon": 0 }, + "4250": { "label": "23/25", "naklon": 0 }, + "3059": { "label": "23/26", "naklon": 10 }, + "3238": { "label": "23/27", "naklon": 10 }, + "3242": { "label": "23/28", "naklon": 10 }, + "3236": { "label": "23/29", "naklon": 10 }, + "3112": { "label": "23/30", "naklon": 10 }, + "3224": { "label": "23/31", "naklon": 0 }, + "4298": { "label": "23/32", "naklon": 10 }, + "4150": { "label": "23/33", "naklon": 10 }, + "3091": { "label": "23/34", "naklon": 10 }, + "3771": { "label": "25/1", "naklon": 5 }, + "3777": { "label": "25/2", "naklon": 5 }, + "3749": { "label": "25/3", "naklon": 5 }, + "3769": { "label": "25/4", "naklon": 5 }, + "3765": { "label": "25/5", "naklon": 5 }, + "3785": { "label": "25/6", "naklon": 5 }, + "3761": { "label": "25/7", "naklon": 5 }, + "3758": { "label": "25/8", "naklon": 5 }, + "3766": { "label": "25/9", "naklon": 5 }, + "3779": { "label": "25/10", "naklon": 5 }, + "3899": { "label": "25/11", "naklon": 10 }, + "3922": { "label": "25/12", "naklon": 10 }, + "3912": { "label": "25/13", "naklon": 10 }, + "3933": { "label": "25/14", "naklon": 10 }, + "3921": { "label": "25/15", "naklon": 10 }, + "4300": { "label": "25/16", "naklon": 10 }, + "3927": { "label": "25/17", "naklon": 10 }, + "3212": { "label": "25/18", "naklon": 10 }, + "3208": { "label": "25/19", "naklon": 10 }, + "3207": { "label": "25/20", "naklon": 10 }, + "4294": { "label": "25/21", "naklon": 10 }, + "3209": { "label": "25/22", "naklon": 10 }, + "3745": { "label": "25/23", "naklon": 10 }, + "3762": { "label": "25/24", "naklon": 10 }, + "3215": { "label": "25/25", "naklon": 10 }, + "3210": { "label": "25/26", "naklon": 10 }, + "3211": { "label": "25/27", "naklon": 10 }, + "3206": { "label": "25/28", "naklon": 10 }, + "3918": { "label": "25/29", "naklon": 5 }, + "3928": { "label": "25/30", "naklon": 5 }, + "3917": { "label": "25/31", "naklon": 5 }, + "4029": { "label": "25/32", "naklon": 0 }, + "4038": { "label": "25/33", "naklon": 0 }, + "4022": { "label": "25/34", "naklon": 0 }, + "3937": { "label": "25/35", "naklon": 0 }, + "3190": { "label": "25/36", "naklon": 0 }, + "3835": { "label": "25/37", "naklon": 0 }, + "3201": { "label": "25/38", "naklon": 0 }, + "3193": { "label": "25/39", "naklon": 0 }, + "3191": { "label": "25/40", "naklon": 0 }, + "3203": { "label": "25/41", "naklon": 0 }, + "4301": { "label": "25/42", "naklon": 0 }, + "3223": { "label": "25/43", "naklon": 0 }, + "3202": { "label": "25/44", "naklon": 0 }, + "3205": { "label": "25/45", "naklon": 0 }, + "3194": { "label": "25/46", "naklon": 0 }, + "3198": { "label": "25/47", "naklon": 0 }, + "3204": { "label": "25/48", "naklon": 0 }, + "3200": { "label": "25/49", "naklon": 0 }, + "3216": { "label": "25/50", "naklon": 0 }, + "3932": { "label": "25/51", "naklon": 5 }, + "3923": { "label": "25/52", "naklon": 5 }, + "3913": { "label": "25/53", "naklon": 5 }, + "3900": { "label": "25/54", "naklon": 5 }, + "4189": { "label": "25/55", "naklon": 10 }, + "4191": { "label": "25/56", "naklon": 10 }, + "3790": { "label": "25/57", "naklon": 10 }, + "4190": { "label": "25/58", "naklon": 10 }, + "4302": { "label": "25/59", "naklon": 0 }, + "4351": { "label": "25/60", "naklon": 0 }, + "4075": { "label": "25/61", "naklon": 0 }, + "4071": { "label": "25/62", "naklon": 0 }, + "3784": { "label": "25/63", "naklon": 0 }, + "4065": { "label": "25/64", "naklon": 0 }, + "4297": { "label": "25/65", "naklon": 0 }, + "4295": { "label": "25/66", "naklon": 0 }, + "4299": { "label": "25/67", "naklon": 0 }, + "3772": { "label": "25/68", "naklon": 0 }, + "3941": { "label": "25/69", "naklon": 0 }, + "3782": { "label": "25/70", "naklon": 0 }, + "4068": { "label": "25/71", "naklon": 0 }, + "4073": { "label": "25/72", "naklon": 0 }, + "3901": { "label": "25/73", "naklon": 5 }, + "4296": { "label": "25/74", "naklon": 5 }, + "3910": { "label": "25/75", "naklon": 5 }, + "4293": { "label": "25/76", "naklon": 5 }, + "3919": { "label": "25/77", "naklon": 5 }, + "3924": { "label": "25/78", "naklon": 5 }, + "3909": { "label": "25/79", "naklon": 5 }, + "3896": { "label": "25/80", "naklon": 5 }, + "3911": { "label": "25/81", "naklon": 5 }, + "2819": { "label": "25/82", "naklon": 15 }, + "3776": { "label": "25/83", "naklon": 15 }, + "3752": { "label": "25/84", "naklon": 15 }, + "4353": { "label": "25/85", "naklon": 15 }, + "3791": { "label": "25/86", "naklon": 0 }, + "3770": { "label": "25/87", "naklon": 0 }, + "3760": { "label": "25/88", "naklon": 0 }, + "3115": { "label": "25/89", "naklon": 0 }, + "3738": { "label": "25/90", "naklon": 0 }, + "3748": { "label": "25/91", "naklon": 0 }, + "3753": { "label": "25/92", "naklon": 0 }, + "3775": { "label": "25/93", "naklon": 0 }, + "3778": { "label": "25/94", "naklon": 5 }, + "4078": { "label": "25/95", "naklon": 5 }, + "4088": { "label": "25/96", "naklon": 5 }, + "3856": { "label": "25/97", "naklon": 5 }, + "4084": { "label": "25/98", "naklon": 5 }, + "4069": { "label": "25/99", "naklon": 5 }, + "4188": { "label": "25/100", "naklon": 5 }, + "4064": { "label": "25/101", "naklon": 5 }, + "3792": { "label": "25/102", "naklon": 5 }, + "3780": { "label": "25/103", "naklon": 5 }, + "4034": { "label": "25/104", "naklon": 5 }, + "4072": { "label": "25/105", "naklon": 5 }, + "3884": { "label": "25/106", "naklon": 5 }, + "3793": { "label": "25/107", "naklon": 5 }, + "3863": { "label": "25/108", "naklon": 5 }, + "3855": { "label": "25/109", "naklon": 5 }, + "3846": { "label": "33/1", "naklon": 0 }, + "3943": { "label": "33/2", "naklon": 0 }, + "3903": { "label": "33/3", "naklon": 0 }, + "3982": { "label": "33/4", "naklon": 0 }, + "3879": { "label": "33/5", "naklon": 0 }, + "3887": { "label": "33/6", "naklon": 0 }, + "3920": { "label": "33/7", "naklon": 5 }, + "3942": { "label": "33/8", "naklon": 5 }, + "3829": { "label": "33/9", "naklon": null }, + "3452": { "label": "34/79A", "naklon": 6 }, + "3460": { "label": "34/79B", "naklon": 6 }, + "3443": { "label": "34/90A", "naklon": 6 }, + "3445": { "label": "34/90B", "naklon": 6 }, + "3457": { "label": "34/90C", "naklon": 6 }, + "3461": { "label": "34/97A", "naklon": 6 }, + "3463": { "label": "34/97B", "naklon": 6 }, + "3426": { "label": "34/98A", "naklon": 6 }, + "3444": { "label": "34/98B", "naklon": 6 }, + "3453": { "label": "34/99A", "naklon": 6 }, + "3455": { "label": "34/99B", "naklon": 6 }, + "4009": { "label": "34/1", "naklon": 0 }, + "3602": { "label": "34/2", "naklon": 0 }, + "3441": { "label": "34/3", "naklon": 0 }, + "3464": { "label": "34/4", "naklon": 0 }, + "3883": { "label": "34/5", "naklon": 0 }, + "4098": { "label": "34/6", "naklon": 0 }, + "4003": { "label": "34/7", "naklon": 0 }, + "4004": { "label": "34/8", "naklon": 0 }, + "3888": { "label": "34/9", "naklon": 0 }, + "3997": { "label": "34/10", "naklon": 0 }, + "4006": { "label": "34/11", "naklon": 0 }, + "4000": { "label": "34/12", "naklon": 0 }, + "4011": { "label": "34/13", "naklon": 0 }, + "3999": { "label": "34/14", "naklon": 0 }, + "3981": { "label": "34/15", "naklon": 0 }, + "3988": { "label": "34/16", "naklon": 0 }, + "3986": { "label": "34/17", "naklon": 0 }, + "3998": { "label": "34/18", "naklon": 0 }, + "3983": { "label": "34/19", "naklon": 0 }, + "4005": { "label": "34/20", "naklon": 0 }, + "4001": { "label": "34/21", "naklon": 0 }, + "4008": { "label": "34/22", "naklon": 0 }, + "4002": { "label": "34/23", "naklon": 0 }, + "3996": { "label": "34/24", "naklon": 0 }, + "4007": { "label": "34/25", "naklon": 0 }, + "4113": { "label": "34/26", "naklon": 15 }, + "3595": { "label": "34/27", "naklon": 5 }, + "3599": { "label": "34/28", "naklon": 5 }, + "3601": { "label": "34/29", "naklon": 5 }, + "4205": { "label": "34/30", "naklon": 0 }, + "3987": { "label": "34/31", "naklon": null }, + "4214": { "label": "34/32", "naklon": 0 }, + "4226": { "label": "34/33", "naklon": 0 }, + "4209": { "label": "34/34", "naklon": 0 }, + "4201": { "label": "34/35", "naklon": 0 }, + "3440": { "label": "34/36", "naklon": 0 }, + "3465": { "label": "34/37", "naklon": 0 }, + "3446": { "label": "34/38", "naklon": 0 }, + "4039": { "label": "34/39", "naklon": 5 }, + "4057": { "label": "34/40", "naklon": 5 }, + "3985": { "label": "34/41", "naklon": 0 }, + "3882": { "label": "34/42", "naklon": 0 }, + "4040": { "label": "34/43", "naklon": 5 }, + "3231": { "label": "34/44", "naklon": 0 }, + "3227": { "label": "34/45", "naklon": 0 }, + "3431": { "label": "34/46", "naklon": 0 }, + "4013": { "label": "34/47", "naklon": 0 }, + "4045": { "label": "34/48", "naklon": 0 }, + "3949": { "label": "34/49", "naklon": 0 }, + "3953": { "label": "34/50", "naklon": 0 }, + "3952": { "label": "34/51", "naklon": 0 }, + "3995": { "label": "34/52", "naklon": 0 }, + "3992": { "label": "34/53", "naklon": 0 }, + "4198": { "label": "34/54", "naklon": 0 }, + "3935": { "label": "34/55", "naklon": 0 }, + "4050": { "label": "34/56", "naklon": 0 }, + "4049": { "label": "34/57", "naklon": 0 }, + "4054": { "label": "34/58", "naklon": 0 }, + "3663": { "label": "34/59", "naklon": 6 }, + "3661": { "label": "34/60", "naklon": 6 }, + "3664": { "label": "34/61", "naklon": 6 }, + "3660": { "label": "34/62", "naklon": 6 }, + "3662": { "label": "34/63", "naklon": 6 }, + "3665": { "label": "34/65", "naklon": 6 }, + "3667": { "label": "34/66", "naklon": 6 }, + "3675": { "label": "34/67", "naklon": 6 }, + "3666": { "label": "34/68", "naklon": 6 }, + "3652": { "label": "34/69", "naklon": 6 }, + "3458": { "label": "34/70", "naklon": 6 }, + "4425": { "label": "34/70/1", "naklon": 6 }, + "3459": { "label": "34/71", "naklon": 6 }, + "3435": { "label": "34/72", "naklon": 6 }, + "3448": { "label": "34/73", "naklon": 6 }, + "3451": { "label": "34/74", "naklon": 6 }, + "3442": { "label": "34/75", "naklon": 6 }, + "3449": { "label": "34/76", "naklon": 6 }, + "3450": { "label": "34/77", "naklon": 6 }, + "3433": { "label": "34/78", "naklon": 6 }, + "3432": { "label": "34/80", "naklon": 12 }, + "3470": { "label": "34/81", "naklon": 12 }, + "3438": { "label": "34/82", "naklon": 12 }, + "3439": { "label": "34/83", "naklon": 12 }, + "4028": { "label": "34/84", "naklon": 5 }, + "3596": { "label": "34/85", "naklon": 5 }, + "4021": { "label": "34/86", "naklon": 5 }, + "3437": { "label": "34/87", "naklon": 12 }, + "3428": { "label": "34/88", "naklon": 12 }, + "3430": { "label": "34/89", "naklon": 12 }, + "3454": { "label": "34/91", "naklon": 6 }, + "3492": { "label": "34/92", "naklon": 6 }, + "3462": { "label": "34/93", "naklon": 6 }, + "3427": { "label": "34/94", "naklon": 6 }, + "3434": { "label": "34/95", "naklon": 6 }, + "3456": { "label": "34/96", "naklon": 6 }, + "4307": { "label": "34/98/1", "naklon": 6 }, + "3968": { "label": "35/1", "naklon": 0 }, + "3969": { "label": "35/2", "naklon": 0 }, + "3947": { "label": "35/3", "naklon": 0 }, + "3979": { "label": "35/4", "naklon": 0 }, + "3959": { "label": "35/5", "naklon": 0 }, + "3948": { "label": "35/6", "naklon": 0 }, + "3961": { "label": "35/7", "naklon": 0 }, + "3956": { "label": "35/8", "naklon": 0 }, + "3604": { "label": "35/9", "naklon": 0 }, + "3944": { "label": "35/10", "naklon": 0 }, + "3960": { "label": "35/11", "naklon": 0 }, + "3958": { "label": "35/12", "naklon": 0 }, + "4036": { "label": "35/13", "naklon": 5 }, + "3893": { "label": "35/18", "naklon": 5 }, + "4108": { "label": "35/19", "naklon": 5 }, + "4017": { "label": "35/20", "naklon": 5 }, + "3963": { "label": "35/21", "naklon": 0 }, + "3658": { "label": "35/22", "naklon": 0 }, + "3975": { "label": "35/23", "naklon": 0 }, + "3980": { "label": "35/24", "naklon": 0 }, + "4012": { "label": "35/25", "naklon": 0 }, + "3655": { "label": "35/26", "naklon": 0 }, + "3962": { "label": "35/27", "naklon": 0 }, + "3945": { "label": "35/28", "naklon": 0 }, + "3569": { "label": "35/29", "naklon": 0 }, + "3429": { "label": "35/30", "naklon": 0 }, + "3657": { "label": "35/31", "naklon": 0 }, + "3646": { "label": "35/32", "naklon": 0 }, + "3622": { "label": "35/33", "naklon": 0 }, + "3612": { "label": "35/34", "naklon": 0 }, + "3955": { "label": "35/35", "naklon": 0 }, + "3878": { "label": "35/37", "naklon": 0 }, + "3965": { "label": "35/38", "naklon": 0 }, + "3970": { "label": "35/39", "naklon": 0 }, + "3611": { "label": "35/40", "naklon": 0 }, + "2635": { "label": "35/41", "naklon": 0 }, + "3978": { "label": "35/42", "naklon": 0 }, + "4213": { "label": "35/43", "naklon": 0 }, + "3984": { "label": "35/44", "naklon": 0 }, + "4218": { "label": "35/45", "naklon": 0 }, + "3973": { "label": "35/46", "naklon": 0 }, + "3974": { "label": "35/47", "naklon": 0 }, + "3759": { "label": "35/48", "naklon": 0 }, + "3844": { "label": "35/49", "naklon": 0 }, + "3804": { "label": "35/50", "naklon": 0 }, + "3831": { "label": "35/51", "naklon": 0 }, + "3643": { "label": "35/52", "naklon": 0 }, + "3966": { "label": "35/53", "naklon": 0 }, + "3971": { "label": "35/54", "naklon": 0 }, + "3650": { "label": "35/55", "naklon": 6 }, + "3651": { "label": "35/56", "naklon": 6 }, + "3669": { "label": "35/57", "naklon": 6 }, + "3648": { "label": "35/58", "naklon": 6 }, + "3645": { "label": "35/59", "naklon": 6 }, + "3659": { "label": "35/60", "naklon": 6 }, + "3647": { "label": "35/61", "naklon": 6 }, + "3644": { "label": "35/62", "naklon": 6 }, + "3671": { "label": "35/63", "naklon": 6 }, + "3682": { "label": "35/64", "naklon": 6 }, + "3672": { "label": "35/65", "naklon": 6 }, + "3683": { "label": "35/66", "naklon": 6 }, + "3673": { "label": "35/67", "naklon": 6 }, + "3674": { "label": "35/68", "naklon": 6 }, + "3679": { "label": "35/69", "naklon": 6 }, + "3649": { "label": "35/70", "naklon": 6 }, + "3687": { "label": "35/71", "naklon": 6 }, + "3677": { "label": "35/72", "naklon": 6 }, + "3690": { "label": "35/73", "naklon": 6 }, + "3691": { "label": "35/74", "naklon": 6 }, + "3676": { "label": "35/75", "naklon": 6 }, + "3680": { "label": "35/76", "naklon": 6 }, + "3668": { "label": "35/77", "naklon": 6 }, + "3681": { "label": "35/78", "naklon": 6 }, + "3670": { "label": "35/79", "naklon": 6 }, + "3689": { "label": "35/80", "naklon": 6 }, + "3678": { "label": "35/81", "naklon": 6 }, + "3693": { "label": "35/82", "naklon": 6 }, + "3654": { "label": "35/83", "naklon": null }, + "4086": { "label": "36/1", "naklon": 0 }, + "4085": { "label": "36/2", "naklon": 0 }, + "4083": { "label": "36/3", "naklon": 0 }, + "4087": { "label": "36/4", "naklon": 0 }, + "4077": { "label": "36/5", "naklon": 0 }, + "4082": { "label": "36/6", "naklon": 0 }, + "4186": { "label": "36/7", "naklon": 0 }, + "4206": { "label": "36/8", "naklon": 0 }, + "4080": { "label": "36/9", "naklon": 0 }, + "4081": { "label": "36/10", "naklon": 0 }, + "4210": { "label": "36/11", "naklon": 0 }, + "4079": { "label": "36/12", "naklon": 0 }, + "4076": { "label": "36/13", "naklon": 0 }, + "3852": { "label": "36/14", "naklon": 0 }, + "2813": { "label": "36/15", "naklon": 0 }, + "4219": { "label": "36/16", "naklon": 0 }, + "3104": { "label": "37/1A", "naklon": 15 }, + "3121": { "label": "37/1B", "naklon": 15 }, + "3113": { "label": "37/2", "naklon": 10 }, + "3118": { "label": "37/3", "naklon": 10 }, + "3111": { "label": "37/4", "naklon": 10 }, + "4020": { "label": "37/5", "naklon": 10 }, + "3119": { "label": "37/6", "naklon": 10 }, + "3110": { "label": "37/7", "naklon": 10 }, + "3108": { "label": "37/8", "naklon": 10 }, + "3107": { "label": "37/12", "naklon": 0 }, + "3199": { "label": "37/13", "naklon": 0 }, + "3120": { "label": "37/14", "naklon": 0 }, + "3122": { "label": "37/15", "naklon": 0 }, + "3908": { "label": "37/16", "naklon": 0 }, + "3114": { "label": "37/17", "naklon": 0 }, + "3105": { "label": "37/18", "naklon": 0 }, + "3116": { "label": "37/19", "naklon": 0 }, + "3106": { "label": "37/20", "naklon": 0 }, + "2887": { "label": "37/21", "naklon": 5 }, + "2888": { "label": "37/22", "naklon": 5 }, + "2877": { "label": "37/23", "naklon": 5 }, + "2891": { "label": "37/24", "naklon": 5 }, + "2886": { "label": "37/25", "naklon": 5 }, + "2892": { "label": "37/26", "naklon": 5 }, + "2882": { "label": "37/27", "naklon": 5 }, + "2883": { "label": "37/28", "naklon": 5 }, + "2876": { "label": "37/29", "naklon": 5 }, + "3109": { "label": "37/30", "naklon": 5 }, + "4152": { "label": "37/31", "naklon": 5 }, + "3117": { "label": "37/32", "naklon": 5 }, + "2870": { "label": "37/33", "naklon": 5 }, + "2867": { "label": "37/34", "naklon": 0 }, + "2865": { "label": "37/35", "naklon": 0 }, + "3096": { "label": "37/36", "naklon": 0 }, + "2871": { "label": "37/37", "naklon": 0 }, + "2884": { "label": "37/38", "naklon": 0 }, + "2855": { "label": "37/39", "naklon": 0 }, + "2878": { "label": "37/40", "naklon": 0 }, + "2889": { "label": "37/41", "naklon": 0 }, + "2879": { "label": "37/42", "naklon": 0 }, + "2850": { "label": "37/43", "naklon": 0 }, + "2894": { "label": "37/44", "naklon": 0 }, + "2880": { "label": "37/45", "naklon": 0 }, + "2893": { "label": "37/46", "naklon": 0 }, + "2890": { "label": "37/47", "naklon": 0 }, + "4355": { "label": "37/48", "naklon": 0 }, + "2885": { "label": "37/49", "naklon": 0 }, + "2875": { "label": "37/50", "naklon": 0 }, + "3486": { "label": "38/30A", "naklon": 5 }, + "3714": { "label": "38/30B", "naklon": 0 }, + "3483": { "label": "38/32A", "naklon": 5 }, + "3496": { "label": "38/32B", "naklon": 0 }, + "3487": { "label": "38/35A", "naklon": 5 }, + "3498": { "label": "38/35B", "naklon": 5 }, + "3578": { "label": "38/38A", "naklon": 5 }, + "3508": { "label": "38/38B", "naklon": 5 }, + "3787": { "label": "38/59A", "naklon": 5 }, + "3491": { "label": "38/59B", "naklon": 5 }, + "3568": { "label": "38/1", "naklon": null }, + "3502": { "label": "38/2", "naklon": 0 }, + "3836": { "label": "38/3", "naklon": 0 }, + "3588": { "label": "38/4", "naklon": 0 }, + "3493": { "label": "38/5", "naklon": 0 }, + "3580": { "label": "38/6", "naklon": 0 }, + "3572": { "label": "38/7", "naklon": 0 }, + "3506": { "label": "38/8", "naklon": 0 }, + "3503": { "label": "38/9", "naklon": 0 }, + "3579": { "label": "38/10", "naklon": 0 }, + "3586": { "label": "38/11", "naklon": 0 }, + "3495": { "label": "38/12", "naklon": 5 }, + "3492": { "label": "38/13", "naklon": 5 }, + "3532": { "label": "38/14", "naklon": 5 }, + "3574": { "label": "38/15", "naklon": 5 }, + "4140": { "label": "38/16", "naklon": 5 }, + "3795": { "label": "38/17", "naklon": 5 }, + "3788": { "label": "38/18", "naklon": 5 }, + "3796": { "label": "38/19", "naklon": 5 }, + "3797": { "label": "38/20", "naklon": 5 }, + "3798": { "label": "38/21", "naklon": 5 }, + "3786": { "label": "38/22", "naklon": 5 }, + "4067": { "label": "38/23", "naklon": 5 }, + "3773": { "label": "38/24", "naklon": 5 }, + "3774": { "label": "38/25", "naklon": 5 }, + "3789": { "label": "38/26", "naklon": 5 }, + "3520": { "label": "38/27", "naklon": null }, + "3577": { "label": "38/29", "naklon": 5 }, + "3530": { "label": "38/31", "naklon": null }, + "3488": { "label": "38/33", "naklon": 5 }, + "3505": { "label": "38/34", "naklon": 5 }, + "3497": { "label": "38/36", "naklon": 5 }, + "3490": { "label": "38/37", "naklon": 5 }, + "3585": { "label": "38/39", "naklon": 5 }, + "3582": { "label": "38/40", "naklon": 5 }, + "3507": { "label": "38/41", "naklon": 5 }, + "3484": { "label": "38/42", "naklon": 5 }, + "3501": { "label": "38/43", "naklon": 5 }, + "3581": { "label": "38/44", "naklon": 5 }, + "4192": { "label": "38/45", "naklon": 5 }, + "3576": { "label": "38/46", "naklon": 5 }, + "3489": { "label": "38/47", "naklon": 5 }, + "3573": { "label": "38/48", "naklon": 5 }, + "3504": { "label": "38/49", "naklon": 5 }, + "3794": { "label": "38/50", "naklon": 5 }, + "3485": { "label": "38/51", "naklon": 5 }, + "3482": { "label": "38/52", "naklon": 5 }, + "3575": { "label": "38/53", "naklon": 5 }, + "3499": { "label": "38/54", "naklon": 5 }, + "3494": { "label": "38/55", "naklon": 5 }, + "3583": { "label": "38/56", "naklon": 5 }, + "3570": { "label": "38/57", "naklon": 5 }, + "3500": { "label": "38/58", "naklon": 0 }, + "3510": { "label": "38/63", "naklon": null }, + "3512": { "label": "38/64", "naklon": null }, + "3535": { "label": "38/67", "naklon": null }, + "3531": { "label": "38/68", "naklon": null }, + "3537": { "label": "38/69", "naklon": null }, + "3522": { "label": "39/1", "naklon": 10 }, + "4018": { "label": "39/2", "naklon": 10 }, + "4019": { "label": "39/3", "naklon": 10 }, + "4154": { "label": "39/4", "naklon": 5 }, + "3907": { "label": "39/5", "naklon": 5 }, + "4148": { "label": "39/6", "naklon": 0 }, + "4153": { "label": "39/7", "naklon": 0 }, + "3938": { "label": "39/8", "naklon": 0 }, + "3802": { "label": "39/9", "naklon": 0 }, + "4015": { "label": "39/10", "naklon": 0 }, + "3929": { "label": "39/11", "naklon": 0 }, + "3946": { "label": "39/12", "naklon": 0 }, + "4014": { "label": "39/13", "naklon": 0 }, + "4155": { "label": "39/14", "naklon": 0 }, + "4149": { "label": "39/15", "naklon": 0 }, + "3642": { "label": "39/16", "naklon": 0 }, + "3636": { "label": "39/17", "naklon": 5 }, + "3991": { "label": "39/18", "naklon": 0 }, + "3994": { "label": "39/19", "naklon": 0 }, + "3990": { "label": "39/20", "naklon": 0 }, + "3967": { "label": "39/21", "naklon": 0 }, + "3977": { "label": "39/22", "naklon": 0 }, + "3757": { "label": "39/23", "naklon": 15 }, + "3633": { "label": "39/24", "naklon": 15 }, + "3744": { "label": "39/25", "naklon": 15 }, + "4023": { "label": "39/26", "naklon": 5 }, + "3720": { "label": "39/27", "naklon": 5 }, + "3734": { "label": "39/28", "naklon": 5 }, + "3741": { "label": "39/29", "naklon": 5 }, + "3721": { "label": "39/30", "naklon": 5 }, + "3845": { "label": "39/31", "naklon": 0 }, + "3840": { "label": "39/32", "naklon": 0 }, + "3837": { "label": "39/33", "naklon": null }, + "3839": { "label": "39/34", "naklon": 0 }, + "3542": { "label": "41/1", "naklon": null }, + "3566": { "label": "41/2", "naklon": null }, + "3548": { "label": "41/3", "naklon": null }, + "3515": { "label": "41/4", "naklon": null }, + "3559": { "label": "41/5", "naklon": null }, + "3509": { "label": "41/6", "naklon": null }, + "3524": { "label": "41/7", "naklon": null }, + "3518": { "label": "41/8", "naklon": null }, + "3182": { "label": "41/9", "naklon": null }, + "3187": { "label": "41/10", "naklon": null }, + "3195": { "label": "41/11", "naklon": 0 }, + "3857": { "label": "41/12", "naklon": 0 }, + "3183": { "label": "41/13", "naklon": 0 }, + "3177": { "label": "41/14", "naklon": 0 }, + "3189": { "label": "41/15", "naklon": 0 }, + "3186": { "label": "41/16", "naklon": 0 }, + "3178": { "label": "42/1", "naklon": 0 }, + "3219": { "label": "42/2", "naklon": 0 }, + "3475": { "label": "42/3", "naklon": 0 }, + "3175": { "label": "42/4", "naklon": 0 }, + "3222": { "label": "42/5", "naklon": 0 }, + "3221": { "label": "42/6", "naklon": 0 }, + "3181": { "label": "42/7", "naklon": 0 }, + "3180": { "label": "42/8", "naklon": 0 }, + "3218": { "label": "42/9", "naklon": 0 }, + "3176": { "label": "42/10", "naklon": 0 }, + "3174": { "label": "42/11", "naklon": 0 }, + "3220": { "label": "42/12", "naklon": 0 }, + "3533": { "label": "42/13", "naklon": null }, + "3543": { "label": "42/14", "naklon": null }, + "3554": { "label": "42/15", "naklon": null }, + "3549": { "label": "42/16", "naklon": null }, + "2857": { "label": "43/1", "naklon": 5 }, + "2752": { "label": "43/2", "naklon": 5 }, + "2753": { "label": "43/3", "naklon": 5 }, + "3024": { "label": "43/4", "naklon": 5 }, + "2754": { "label": "43/5", "naklon": 5 }, + "4423": { "label": "43/6", "naklon": 5 }, + "4368": { "label": "43/7", "naklon": 5 }, + "2978": { "label": "43/8", "naklon": 5 }, + "2868": { "label": "43/9", "naklon": 5 }, + "4377": { "label": "43/10", "naklon": 5 }, + "2757": { "label": "43/11", "naklon": 5 }, + "2970": { "label": "43/12", "naklon": 5 }, + "2758": { "label": "43/13", "naklon": 5 }, + "4378": { "label": "43/14", "naklon": 5 }, + "2759": { "label": "43/15", "naklon": 5 }, + "4342": { "label": "43/16", "naklon": 5 }, + "3026": { "label": "43/17", "naklon": null }, + "2986": { "label": "43/18", "naklon": null }, + "4343": { "label": "43/19", "naklon": null }, + "2760": { "label": "43/20", "naklon": null }, + "4379": { "label": "43/21", "naklon": null }, + "2971": { "label": "43/22", "naklon": null }, + "2761": { "label": "43/23", "naklon": null }, + "2762": { "label": "43/24", "naklon": null }, + "4339": { "label": "43/25", "naklon": null }, + "4380": { "label": "43/26", "naklon": null }, + "2975": { "label": "43/27", "naklon": null }, + "3003": { "label": "43/28", "naklon": null }, + "4338": { "label": "43/29", "naklon": null }, + "3002": { "label": "43/30", "naklon": null }, + "4345": { "label": "43/31", "naklon": null }, + "2979": { "label": "43/32", "naklon": null }, + "2989": { "label": "43/33", "naklon": null }, + "2996": { "label": "43/34", "naklon": null }, + "2972": { "label": "43/35", "naklon": null }, + "2988": { "label": "43/36", "naklon": null }, + "4344": { "label": "43/37", "naklon": null }, + "3022": { "label": "43/38", "naklon": null }, + "4341": { "label": "43/39", "naklon": null }, + "2983": { "label": "43/40", "naklon": null }, + "2995": { "label": "43/41", "naklon": null }, + "2763": { "label": "43/42", "naklon": null }, + "2764": { "label": "43/43", "naklon": null }, + "2765": { "label": "43/44", "naklon": null }, + "2766": { "label": "43/45", "naklon": null }, + "2767": { "label": "43/46", "naklon": null }, + "2768": { "label": "43/47", "naklon": null }, + "3018": { "label": "43/48", "naklon": null }, + "2982": { "label": "43/49", "naklon": null }, + "3019": { "label": "43/50", "naklon": 0 }, + "3013": { "label": "43/51", "naklon": null }, + "3007": { "label": "43/52", "naklon": null }, + "2980": { "label": "43/53", "naklon": null }, + "3011": { "label": "43/54", "naklon": null }, + "2672": { "label": "43/55", "naklon": null }, + "2673": { "label": "43/56", "naklon": null }, + "2674": { "label": "43/57", "naklon": null }, + "2675": { "label": "43/58", "naklon": null }, + "2676": { "label": "43/59", "naklon": null }, + "2677": { "label": "43/60", "naklon": null }, + "2678": { "label": "43/61", "naklon": null }, + "2679": { "label": "43/62", "naklon": null }, + "2680": { "label": "43/63", "naklon": null }, + "2840": { "label": "43/64", "naklon": null }, + "2682": { "label": "43/65", "naklon": null }, + "2683": { "label": "43/66", "naklon": null }, + "2684": { "label": "43/67", "naklon": 0 }, + "2685": { "label": "43/68", "naklon": null }, + "2686": { "label": "43/69", "naklon": null }, + "2687": { "label": "43/70", "naklon": null }, + "2688": { "label": "43/71", "naklon": null }, + "2689": { "label": "43/72", "naklon": null }, + "2690": { "label": "43/73", "naklon": null }, + "2691": { "label": "43/74", "naklon": null }, + "2692": { "label": "43/75", "naklon": null }, + "2693": { "label": "43/76", "naklon": 0 }, + "2694": { "label": "43/77", "naklon": null }, + "2695": { "label": "43/78", "naklon": null }, + "2696": { "label": "43/79", "naklon": 0 }, + "2697": { "label": "43/80", "naklon": null }, + "2698": { "label": "43/81", "naklon": 0 }, + "2699": { "label": "43/82", "naklon": null }, + "2700": { "label": "43/83", "naklon": 0 }, + "2744": { "label": "43/84", "naklon": null }, + "2745": { "label": "43/85", "naklon": 0 }, + "2746": { "label": "43/86", "naklon": null }, + "2747": { "label": "43/87", "naklon": 0 }, + "2748": { "label": "43/88", "naklon": null }, + "2749": { "label": "43/89", "naklon": 0 }, + "2841": { "label": "43/90", "naklon": null }, + "4237": { "label": "45/1", "naklon": 5 }, + "4226": { "label": "45/2", "naklon": 5 }, + "4242": { "label": "45/3", "naklon": 5 }, + "4179": { "label": "45/4", "naklon": 5 }, + "4247": { "label": "45/5", "naklon": 5 }, + "4245": { "label": "45/6", "naklon": 5 }, + "3872": { "label": "45/7", "naklon": 5 }, + "4175": { "label": "45/8", "naklon": 5 }, + "4236": { "label": "45/9", "naklon": 5 }, + "4170": { "label": "45/10", "naklon": 5 }, + "4238": { "label": "45/11", "naklon": 5 }, + "4246": { "label": "45/12", "naklon": 5 }, + "4166": { "label": "45/13", "naklon": 5 }, + "4227": { "label": "45/14", "naklon": 5 }, + "4171": { "label": "45/15", "naklon": 5 }, + "4180": { "label": "45/16", "naklon": 5 }, + "4244": { "label": "45/17", "naklon": 5 }, + "4199": { "label": "45/18", "naklon": 5 }, + "4239": { "label": "45/19", "naklon": 5 }, + "4207": { "label": "45/20", "naklon": 5 }, + "4223": { "label": "45/21", "naklon": 5 }, + "4230": { "label": "45/22", "naklon": 5 }, + "4233": { "label": "45/23", "naklon": 5 }, + "4222": { "label": "45/24", "naklon": 5 }, + "4217": { "label": "45/25", "naklon": 5 }, + "4243": { "label": "45/26", "naklon": 5 }, + "4200": { "label": "45/27", "naklon": 5 }, + "4228": { "label": "45/28", "naklon": 5 }, + "4211": { "label": "45/29", "naklon": 5 }, + "4234": { "label": "45/30", "naklon": 5 }, + "4235": { "label": "45/31", "naklon": 5 }, + "4203": { "label": "45/32", "naklon": 5 }, + "4240": { "label": "45/33", "naklon": 5 }, + "4224": { "label": "45/34", "naklon": 5 }, + "4232": { "label": "45/35", "naklon": 5 }, + "4231": { "label": "45/36", "naklon": 5 }, + "4161": { "label": "45/37", "naklon": 5 }, + "4225": { "label": "45/38", "naklon": 5 }, + "4241": { "label": "45/39", "naklon": 5 }, + "4229": { "label": "45/40", "naklon": 5 }, + "4221": { "label": "45/41", "naklon": 5 }, + "4212": { "label": "45/42", "naklon": 5 }, + "4216": { "label": "45/43", "naklon": 5 }, + "3864": { "label": "45/44", "naklon": null }, + "3806": { "label": "46/1", "naklon": 5 }, + "3813": { "label": "46/2", "naklon": 5 }, + "3815": { "label": "46/3", "naklon": 5 }, + "3807": { "label": "46/4", "naklon": 5 }, + "3895": { "label": "46/5", "naklon": 5 }, + "3809": { "label": "46/6", "naklon": 5 }, + "3820": { "label": "46/7", "naklon": 5 }, + "3805": { "label": "46/8", "naklon": 5 }, + "3894": { "label": "46/9", "naklon": 0 }, + "4055": { "label": "46/10", "naklon": 0 }, + "3812": { "label": "46/11", "naklon": 5 }, + "3822": { "label": "46/12", "naklon": 5 }, + "3821": { "label": "46/13", "naklon": 5 }, + "3808": { "label": "46/14", "naklon": 5 }, + "3799": { "label": "46/15", "naklon": 5 }, + "3816": { "label": "46/16", "naklon": 5 }, + "3751": { "label": "46/17", "naklon": 5 }, + "3814": { "label": "46/18", "naklon": 5 }, + "4044": { "label": "46/19", "naklon": 0 }, + "3931": { "label": "46/20", "naklon": 0 }, + "3902": { "label": "46/21", "naklon": 5 }, + "3916": { "label": "46/22", "naklon": 5 }, + "3892": { "label": "46/23", "naklon": 5 }, + "3914": { "label": "46/24", "naklon": 5 }, + "3898": { "label": "46/25", "naklon": 5 }, + "3897": { "label": "46/26", "naklon": 5 }, + "3885": { "label": "46/27", "naklon": 5 }, + "3906": { "label": "46/28", "naklon": 5 }, + "3930": { "label": "46/29", "naklon": 0 }, + "3936": { "label": "46/30", "naklon": 0 }, + "3860": { "label": "46/31", "naklon": 5 }, + "3841": { "label": "46/32", "naklon": 5 }, + "3873": { "label": "46/33", "naklon": 5 }, + "3854": { "label": "46/34", "naklon": 5 }, + "3939": { "label": "46/35", "naklon": 5 }, + "3858": { "label": "46/36", "naklon": 5 }, + "3940": { "label": "46/37", "naklon": 5 }, + "4035": { "label": "46/38", "naklon": 5 }, + "3373": { "label": "47/1", "naklon": 0 }, + "3374": { "label": "47/2", "naklon": 0 }, + "3384": { "label": "47/3", "naklon": 0 }, + "3385": { "label": "47/4", "naklon": 0 }, + "4051": { "label": "48/1", "naklon": 5 }, + "4041": { "label": "48/2", "naklon": 5 }, + "4056": { "label": "48/3", "naklon": 5 }, + "3875": { "label": "48/4", "naklon": 5 }, + "4061": { "label": "48/5", "naklon": 5 }, + "4047": { "label": "48/6", "naklon": 5 }, + "4060": { "label": "48/7", "naklon": 5 }, + "4059": { "label": "48/8", "naklon": 5 }, + "4058": { "label": "48/9", "naklon": 5 }, + "3635": { "label": "48/10", "naklon": 5 }, + "3640": { "label": "48/11", "naklon": 5 }, + "3747": { "label": "48/12", "naklon": 5 }, + "3629": { "label": "48/13", "naklon": 5 }, + "4048": { "label": "48/14", "naklon": 5 }, + "4063": { "label": "48/15", "naklon": 5 }, + "4062": { "label": "48/16", "naklon": 5 }, + "4043": { "label": "48/17", "naklon": 5 }, + "4052": { "label": "48/18", "naklon": 5 }, + "4042": { "label": "48/19", "naklon": 5 }, + "4053": { "label": "48/20", "naklon": 5 }, + "4167": { "label": "50/15A", "naklon": null }, + "4159": { "label": "50/15B", "naklon": null }, + "4183": { "label": "50/1", "naklon": 0 }, + "4157": { "label": "50/2", "naklon": 0 }, + "4160": { "label": "50/3", "naklon": 0 }, + "4173": { "label": "50/4", "naklon": 0 }, + "4177": { "label": "50/5", "naklon": 0 }, + "4174": { "label": "50/6", "naklon": 0 }, + "4178": { "label": "50/7", "naklon": 0 }, + "4195": { "label": "50/8", "naklon": 0 }, + "4169": { "label": "50/9", "naklon": 0 }, + "4162": { "label": "50/10", "naklon": 0 }, + "4158": { "label": "50/11", "naklon": 0 }, + "4182": { "label": "50/12", "naklon": 0 }, + "4194": { "label": "50/13", "naklon": 0 }, + "4184": { "label": "50/14", "naklon": 0 }, + "4197": { "label": "50/16", "naklon": null }, + "4164": { "label": "50/17", "naklon": null }, + "3306": { "label": "50/18", "naklon": null }, + "4168": { "label": "50/19", "naklon": null }, + "4193": { "label": "50/20", "naklon": null }, + "4187": { "label": "50/21", "naklon": null }, + "4163": { "label": "50/22", "naklon": null }, + "4165": { "label": "50/23", "naklon": null }, + "4185": { "label": "50/24", "naklon": null }, + "3904": { "label": "50/25", "naklon": null }, + "2619": { "label": "53/1", "naklon": 0 }, + "2623": { "label": "53/2", "naklon": 0 }, + "2617": { "label": "53/3", "naklon": 0 }, + "2622": { "label": "53/4", "naklon": 0 }, + "2618": { "label": "53/5", "naklon": 0 }, + "2626": { "label": "53/6", "naklon": 0 }, + "2869": { "label": "53/7", "naklon": 0 }, + "2613": { "label": "53/8", "naklon": 0 }, + "2608": { "label": "53/9", "naklon": 0 }, + "2611": { "label": "53/10", "naklon": 0 }, + "2598": { "label": "53/11", "naklon": 0 }, + "3528": { "label": "53/12", "naklon": 0 }, + "3545": { "label": "53/13", "naklon": 0 }, + "2620": { "label": "53/14", "naklon": 0 }, + "2612": { "label": "53/15", "naklon": 0 }, + "2615": { "label": "53/16", "naklon": 0 }, + "3722": { "label": "53/17", "naklon": 0 }, + "2624": { "label": "53/18", "naklon": 0 }, + "2609": { "label": "53/19", "naklon": 0 }, + "2625": { "label": "53/20", "naklon": 0 }, + "2602": { "label": "53/21", "naklon": 0 }, + "2610": { "label": "53/22", "naklon": 0 }, + "2599": { "label": "53/23", "naklon": 0 }, + "2605": { "label": "53/24", "naklon": 0 }, + "2593": { "label": "53/25", "naklon": 0 }, + "3074": { "label": "53/26", "naklon": 0 }, + "2740": { "label": "53/27", "naklon": 0 }, + "2614": { "label": "53/28", "naklon": 0 }, + "2601": { "label": "53/29", "naklon": 0 }, + "4196": { "label": "53/30", "naklon": 0 }, + "2607": { "label": "53/31", "naklon": 0 }, + "2582": { "label": "53/32", "naklon": 0 }, + "2594": { "label": "53/33", "naklon": 0 }, + "2589": { "label": "53/34", "naklon": 0 }, + "2596": { "label": "53/35", "naklon": 0 }, + "2603": { "label": "53/36", "naklon": 0 }, + "2597": { "label": "53/37", "naklon": 0 }, + "2590": { "label": "53/38", "naklon": 0 }, + "2581": { "label": "53/39", "naklon": 0 }, + "2583": { "label": "53/40", "naklon": 0 }, + "2580": { "label": "53/41", "naklon": 0 }, + "2579": { "label": "53/42", "naklon": 0 }, + "2797": { "label": "53/43", "naklon": 0 }, + "2577": { "label": "53/44", "naklon": 0 }, + "2586": { "label": "53/45", "naklon": 0 }, + "2588": { "label": "53/46", "naklon": 0 }, + "2591": { "label": "53/47", "naklon": 0 }, + "2592": { "label": "53/48", "naklon": 0 }, + "2573": { "label": "53/49", "naklon": 0 }, + "2595": { "label": "53/50", "naklon": 0 }, + "2587": { "label": "53/51", "naklon": 0 }, + "2578": { "label": "53/52", "naklon": 0 }, + "2574": { "label": "53/53", "naklon": 0 }, + "2571": { "label": "53/54", "naklon": 0 }, + "2570": { "label": "53/55", "naklon": 0 }, + "2576": { "label": "53/56", "naklon": 0 }, + "2881": { "label": "53/57", "naklon": 0 }, + "2575": { "label": "53/58", "naklon": 0 }, + "2572": { "label": "53/59", "naklon": 0 }, + "2569": { "label": "53/60", "naklon": 0 }, + "4324": { "label": "55/1", "naklon": 0 }, + "4319": { "label": "55/2", "naklon": 0 }, + "4327": { "label": "55/3", "naklon": 0 }, + "4333": { "label": "55/4", "naklon": 0 }, + "4332": { "label": "55/5", "naklon": 0 }, + "4320": { "label": "55/6", "naklon": 0 }, + "4317": { "label": "55/7", "naklon": 0 }, + "4318": { "label": "55/8", "naklon": 0 }, + "4328": { "label": "55/9", "naklon": 0 }, + "4323": { "label": "55/10", "naklon": 0 }, + "4325": { "label": "55/11", "naklon": 0 }, + "4326": { "label": "55/12", "naklon": 0 }, + "4316": { "label": "55/13", "naklon": 0 }, + "4322": { "label": "55/14", "naklon": 0 }, + "4331": { "label": "55/15", "naklon": 0 }, + "4321": { "label": "55/16", "naklon": 0 }, + "4315": { "label": "55/17", "naklon": 0 }, + "4329": { "label": "55/18", "naklon": 0 }, + "4334": { "label": "55/19", "naklon": 0 }, + "4330": { "label": "55/20", "naklon": 0 } +}; + + +let svetlaSorted = [{ "label": "1/3A", "node": 3993, "naklon": 0 }, +{ "label": "1/3B", "node": 3989, "naklon": 15 }, +{ "label": "1/1", "node": 3976, "naklon": 0 }, +{ "label": "1/2", "node": 4181, "naklon": 0 }, +{ "label": "1/4", "node": 4376, "naklon": 15 }, +{ "label": "1/5", "node": 3868, "naklon": 15 }, +{ "label": "1/6", "node": 3728, "naklon": 15 }, +{ "label": "1/7", "node": 3730, "naklon": 0 }, +{ "label": "1/8", "node": 4374, "naklon": 0 }, +{ "label": "1/9", "node": 3718, "naklon": 15 }, +{ "label": "1/10", "node": 4375, "naklon": 15 }, +{ "label": "1/11", "node": 4172, "naklon": 15 }, +{ "label": "1/12", "node": 4176, "naklon": 15 }, +{ "label": "2/1", "node": 3800, "naklon": 5 }, +{ "label": "2/2", "node": 3823, "naklon": 5 }, +{ "label": "2/3", "node": 3905, "naklon": 5 }, +{ "label": "2/4", "node": 3803, "naklon": 5 }, +{ "label": "2/5", "node": 3817, "naklon": 5 }, +{ "label": "2/6", "node": 3818, "naklon": 5 }, +{ "label": "2/7", "node": 3811, "naklon": 5 }, +{ "label": "2/8", "node": 3915, "naklon": 5 }, +{ "label": "2/9", "node": 3843, "naklon": 10 }, +{ "label": "2/10", "node": 3827, "naklon": 10 }, +{ "label": "2/11", "node": 4220, "naklon": 10 }, +{ "label": "2/12", "node": 3826, "naklon": 10 }, +{ "label": "2/13", "node": 3834, "naklon": 10 }, +{ "label": "2/14", "node": 3838, "naklon": 10 }, +{ "label": "2/15", "node": 2823, "naklon": 10 }, +{ "label": "2/16", "node": 3750, "naklon": 10 }, +{ "label": "2/17", "node": 3378, "naklon": 0 }, +{ "label": "2/18", "node": 3376, "naklon": 0 }, +{ "label": "2/19", "node": 3379, "naklon": 0 }, +{ "label": "2/20", "node": 3285, "naklon": 0 }, +{ "label": "2/21", "node": 3382, "naklon": 0 }, +{ "label": "2/22", "node": 3383, "naklon": 0 }, +{ "label": "2/24", "node": 3375, "naklon": 0 }, +{ "label": "2/25", "node": 3381, "naklon": 0 }, +{ "label": "2/26", "node": 3380, "naklon": 0 }, +{ "label": "2/27", "node": 3828, "naklon": 10 }, +{ "label": "2/28", "node": 3377, "naklon": 0 }, +{ "label": "7/1", "node": 3591, "naklon": 0 }, +{ "label": "7/2", "node": 3587, "naklon": 0 }, +{ "label": "7/3", "node": 3468, "naklon": 0 }, +{ "label": "7/4", "node": 3466, "naklon": 0 }, +{ "label": "7/5", "node": 3474, "naklon": 0 }, +{ "label": "7/6", "node": 3481, "naklon": 0 }, +{ "label": "7/7", "node": 3589, "naklon": 0 }, +{ "label": "7/8", "node": 3472, "naklon": 0 }, +{ "label": "7/9", "node": 3473, "naklon": 0 }, +{ "label": "7/10", "node": 3584, "naklon": 0 }, +{ "label": "7/11", "node": 3571, "naklon": 0 }, +{ "label": "7/12", "node": 3476, "naklon": 0 }, +{ "label": "7/13", "node": 3590, "naklon": 0 }, +{ "label": "7/14", "node": 3478, "naklon": 0 }, +{ "label": "7/15", "node": 3471, "naklon": 0 }, +{ "label": "7/16", "node": 3467, "naklon": 0 }, +{ "label": "7/17", "node": 3479, "naklon": 0 }, +{ "label": "7/18", "node": 3480, "naklon": 0 }, +{ "label": "7/19", "node": 3477, "naklon": 0 }, +{ "label": "12/1", "node": 3362, "naklon": 0 }, +{ "label": "12/2", "node": 3355, "naklon": 0 }, +{ "label": "12/3", "node": 3356, "naklon": 0 }, +{ "label": "12/4", "node": 3349, "naklon": 0 }, +{ "label": "12/5", "node": 3357, "naklon": 0 }, +{ "label": "12/6", "node": 3350, "naklon": 0 }, +{ "label": "12/7", "node": 3353, "naklon": 0 }, +{ "label": "12/8", "node": 3539, "naklon": 0 }, +{ "label": "12/9", "node": 3050, "naklon": 0 }, +{ "label": "12/10", "node": 3361, "naklon": 0 }, +{ "label": "12/11", "node": 3360, "naklon": 0 }, +{ "label": "12/12", "node": 3358, "naklon": 0 }, +{ "label": "12/13", "node": 3541, "naklon": 0 }, +{ "label": "12/14", "node": 3551, "naklon": 0 }, +{ "label": "12/15", "node": 3514, "naklon": 0 }, +{ "label": "12/16", "node": 3547, "naklon": 0 }, +{ "label": "12/17", "node": 3562, "naklon": 0 }, +{ "label": "12/18", "node": 3525, "naklon": 0 }, +{ "label": "12/19", "node": 3558, "naklon": 0 }, +{ "label": "12/20", "node": 3511, "naklon": 0 }, +{ "label": "12/21", "node": 3058, "naklon": 0 }, +{ "label": "12/22", "node": 3062, "naklon": 0 }, +{ "label": "12/23", "node": 3070, "naklon": 0 }, +{ "label": "12/24", "node": 3447, "naklon": 0 }, +{ "label": "12/25", "node": 3056, "naklon": 0 }, +{ "label": "12/26", "node": 3057, "naklon": 0 }, +{ "label": "12/27", "node": 3071, "naklon": 0 }, +{ "label": "12/28", "node": 3061, "naklon": 0 }, +{ "label": "12/29", "node": 3069, "naklon": 0 }, +{ "label": "12/30", "node": 3077, "naklon": 0 }, +{ "label": "12/31", "node": 3080, "naklon": 0 }, +{ "label": "12/32", "node": 3081, "naklon": 0 }, +{ "label": "12/33", "node": 3078, "naklon": 0 }, +{ "label": "12/34", "node": 4037, "naklon": 0 }, +{ "label": "12/35", "node": 3067, "naklon": 0 }, +{ "label": "12/36", "node": 3051, "naklon": 0 }, +{ "label": "12/37", "node": 2924, "naklon": 0 }, +{ "label": "12/38", "node": 3060, "naklon": 0 }, +{ "label": "12/39", "node": 3073, "naklon": 0 }, +{ "label": "12/40", "node": 3469, "naklon": 0 }, +{ "label": "12/41", "node": 2923, "naklon": 0 }, +{ "label": "12/42", "node": 2925, "naklon": 0 }, +{ "label": "12/43", "node": 3359, "naklon": 0 }, +{ "label": "12/44", "node": 3055, "naklon": 0 }, +{ "label": "12/45", "node": 2922, "naklon": 0 }, +{ "label": "12/46", "node": 3084, "naklon": 0 }, +{ "label": "12/47", "node": 3064, "naklon": 0 }, +{ "label": "12/48", "node": 3066, "naklon": 0 }, +{ "label": "12/49", "node": 3072, "naklon": 0 }, +{ "label": "13/13A", "node": 3415, "naklon": 0 }, +{ "label": "13/13B", "node": 3409, "naklon": 0 }, +{ "label": "13/13C", "node": 3399, "naklon": 0 }, +{ "label": "13/29A", "node": 3410, "naklon": 0 }, +{ "label": "13/29B", "node": 3407, "naklon": 0 }, +{ "label": "13/34A", "node": 3405, "naklon": 0 }, +{ "label": "13/34B", "node": 3404, "naklon": 0 }, +{ "label": "13/45A", "node": 3392, "naklon": 0 }, +{ "label": "13/45B", "node": 3386, "naklon": 0 }, +{ "label": "13/60A", "node": 3303, "naklon": 3 }, +{ "label": "13/60B", "node": 3302, "naklon": 3 }, +{ "label": "13/70A", "node": 3319, "naklon": 6 }, +{ "label": "13/70B", "node": 3317, "naklon": 6 }, +{ "label": "13/70C", "node": 3326, "naklon": 6 }, +{ "label": "13/73A", "node": 3351, "naklon": 6 }, +{ "label": "13/73B", "node": 3313, "naklon": 6 }, +{ "label": "13/83A", "node": 3316, "naklon": 0 }, +{ "label": "13/83B", "node": 3320, "naklon": 0 }, +{ "label": "13/95A", "node": 3336, "naklon": 0 }, +{ "label": "13/95B", "node": 3323, "naklon": 0 }, +{ "label": "13/98A", "node": 3339, "naklon": 0 }, +{ "label": "13/98B", "node": 3333, "naklon": 0 }, +{ "label": "13/1", "node": 3425, "naklon": 0 }, +{ "label": "13/2", "node": 3419, "naklon": 0 }, +{ "label": "13/3", "node": 3416, "naklon": 0 }, +{ "label": "13/4", "node": 3332, "naklon": 0 }, +{ "label": "13/5", "node": 3422, "naklon": 0 }, +{ "label": "13/6", "node": 3417, "naklon": 0 }, +{ "label": "13/7", "node": 3418, "naklon": 0 }, +{ "label": "13/8", "node": 3424, "naklon": 0 }, +{ "label": "13/9", "node": 3334, "naklon": 0 }, +{ "label": "13/10", "node": 4363, "naklon": 0 }, +{ "label": "13/11", "node": 3423, "naklon": 0 }, +{ "label": "13/12", "node": 3406, "naklon": 0 }, +{ "label": "13/14", "node": 3411, "naklon": 0 }, +{ "label": "13/15", "node": 3412, "naklon": 0 }, +{ "label": "13/16", "node": 3413, "naklon": 0 }, +{ "label": "13/17", "node": 3414, "naklon": 0 }, +{ "label": "13/18", "node": 3391, "naklon": 0 }, +{ "label": "13/19", "node": 3370, "naklon": 0 }, +{ "label": "13/20", "node": 3369, "naklon": 0 }, +{ "label": "13/21", "node": 3408, "naklon": 0 }, +{ "label": "13/22", "node": 3393, "naklon": 0 }, +{ "label": "13/23", "node": 3128, "naklon": 0 }, +{ "label": "13/24", "node": 3197, "naklon": 0 }, +{ "label": "13/25", "node": 4364, "naklon": 0 }, +{ "label": "13/26", "node": 3155, "naklon": 0 }, +{ "label": "13/27", "node": 3196, "naklon": 0 }, +{ "label": "13/28", "node": 3144, "naklon": 0 }, +{ "label": "13/30", "node": 3150, "naklon": 0 }, +{ "label": "13/31", "node": 3390, "naklon": 0 }, +{ "label": "13/32", "node": 3401, "naklon": 0 }, +{ "label": "13/33", "node": 3275, "naklon": 0 }, +{ "label": "13/35", "node": 3371, "naklon": 0 }, +{ "label": "13/36", "node": 3389, "naklon": 0 }, +{ "label": "13/37", "node": 3388, "naklon": 0 }, +{ "label": "13/38", "node": 3365, "naklon": 0 }, +{ "label": "13/39", "node": 3363, "naklon": 0 }, +{ "label": "13/40", "node": 3397, "naklon": 0 }, +{ "label": "13/40/1", "node": 3567, "naklon": 0 }, +{ "label": "13/41", "node": 3387, "naklon": 0 }, +{ "label": "13/42", "node": 3403, "naklon": 0 }, +{ "label": "13/43", "node": 3147, "naklon": 0 }, +{ "label": "13/44", "node": 3141, "naklon": 0 }, +{ "label": "13/46", "node": 3364, "naklon": 0 }, +{ "label": "13/47", "node": 3367, "naklon": 0 }, +{ "label": "13/48", "node": 3368, "naklon": 0 }, +{ "label": "13/49", "node": 3402, "naklon": 0 }, +{ "label": "13/50", "node": 3366, "naklon": 0 }, +{ "label": "13/51", "node": 3395, "naklon": 0 }, +{ "label": "13/52", "node": 3372, "naklon": 0 }, +{ "label": "13/53", "node": 3394, "naklon": 0 }, +{ "label": "13/54", "node": 3308, "naklon": 0 }, +{ "label": "13/54/1", "node": 3847, "naklon": 0 }, +{ "label": "13/55", "node": 3312, "naklon": 3 }, +{ "label": "13/56", "node": 3309, "naklon": 3 }, +{ "label": "13/57", "node": 3311, "naklon": 3 }, +{ "label": "13/58", "node": 3310, "naklon": 3 }, +{ "label": "13/59", "node": 4365, "naklon": 3 }, +{ "label": "13/60/1", "node": 4093, "naklon": 3 }, +{ "label": "13/61", "node": 3304, "naklon": 3 }, +{ "label": "13/62", "node": 3307, "naklon": 3 }, +{ "label": "13/63", "node": 3271, "naklon": 3 }, +{ "label": "13/64", "node": 3301, "naklon": 3 }, +{ "label": "13/65", "node": 4366, "naklon": 3 }, +{ "label": "13/66", "node": 3300, "naklon": 3 }, +{ "label": "13/67", "node": 3185, "naklon": 0 }, +{ "label": "13/68", "node": 3184, "naklon": 0 }, +{ "label": "13/69", "node": 3188, "naklon": 0 }, +{ "label": "13/71", "node": 3343, "naklon": 6 }, +{ "label": "13/71/1", "node": 3819, "naklon": 6 }, +{ "label": "13/71/2", "node": 3880, "naklon": 6 }, +{ "label": "13/72", "node": 3348, "naklon": 6 }, +{ "label": "13/74", "node": 3344, "naklon": 6 }, +{ "label": "13/75", "node": 3346, "naklon": 6 }, +{ "label": "13/75/1", "node": 3597, "naklon": 6 }, +{ "label": "13/76", "node": 3345, "naklon": 6 }, +{ "label": "13/77", "node": 3322, "naklon": 0 }, +{ "label": "13/78", "node": 3325, "naklon": 0 }, +{ "label": "13/78/1", "node": 4310, "naklon": 0 }, +{ "label": "13/79", "node": 3315, "naklon": 0 }, +{ "label": "13/80", "node": 3328, "naklon": 0 }, +{ "label": "13/81", "node": 3321, "naklon": 0 }, +{ "label": "13/82", "node": 3324, "naklon": 0 }, +{ "label": "13/84", "node": 3140, "naklon": 0 }, +{ "label": "13/85", "node": 3153, "naklon": 0 }, +{ "label": "13/86", "node": 3145, "naklon": 0 }, +{ "label": "13/87", "node": 3134, "naklon": 0 }, +{ "label": "13/88", "node": 3151, "naklon": 0 }, +{ "label": "13/89", "node": 3143, "naklon": 0 }, +{ "label": "13/90", "node": 3318, "naklon": 0 }, +{ "label": "13/91", "node": 3347, "naklon": 0 }, +{ "label": "13/94", "node": 3314, "naklon": 0 }, +{ "label": "13/96", "node": 3331, "naklon": 0 }, +{ "label": "13/97", "node": 3327, "naklon": 0 }, +{ "label": "13/99", "node": 3329, "naklon": 0 }, +{ "label": "13/100", "node": 3337, "naklon": 0 }, +{ "label": "13/101", "node": 3330, "naklon": 0 }, +{ "label": "13/102", "node": 3335, "naklon": 0 }, +{ "label": "13/103", "node": 3420, "naklon": 0 }, +{ "label": "13/104", "node": 3421, "naklon": 0 }, +{ "label": "13/105", "node": 4361, "naklon": 0 }, +{ "label": "13/106", "node": 4362, "naklon": 0 }, +{ "label": "13/107", "node": 3526, "naklon": 0 }, +{ "label": "13/108", "node": 4424, "naklon": null }, +{ "label": "13/109", "node": 3561, "naklon": null }, +{ "label": "13/110", "node": 3527, "naklon": null }, +{ "label": "13/111", "node": 3521, "naklon": null }, +{ "label": "13/112", "node": 3552, "naklon": null }, +{ "label": "13/113", "node": 3544, "naklon": null }, +{ "label": "13/114", "node": 3534, "naklon": null }, +{ "label": "13/115", "node": 3516, "naklon": null }, +{ "label": "13/116", "node": 3513, "naklon": null }, +{ "label": "13/117", "node": 3565, "naklon": null }, +{ "label": "13/118", "node": 3866, "naklon": null }, +{ "label": "14/1", "node": 3136, "naklon": 0 }, +{ "label": "14/2", "node": 3137, "naklon": 0 }, +{ "label": "14/3", "node": 3135, "naklon": 0 }, +{ "label": "14/4", "node": 3149, "naklon": 0 }, +{ "label": "14/5", "node": 3142, "naklon": 0 }, +{ "label": "14/6", "node": 3342, "naklon": 0 }, +{ "label": "14/7", "node": 3340, "naklon": 0 }, +{ "label": "14/8", "node": 3152, "naklon": 0 }, +{ "label": "14/9", "node": 3886, "naklon": 0 }, +{ "label": "14/10", "node": 3341, "naklon": null }, +{ "label": "14/11", "node": 3352, "naklon": null }, +{ "label": "15/1", "node": 3396, "naklon": 5 }, +{ "label": "15/2", "node": 2784, "naklon": 5 }, +{ "label": "15/3", "node": 2788, "naklon": 5 }, +{ "label": "15/4", "node": 2801, "naklon": 5 }, +{ "label": "15/5", "node": 2815, "naklon": 5 }, +{ "label": "15/6", "node": 2829, "naklon": 5 }, +{ "label": "15/7", "node": 2796, "naklon": 5 }, +{ "label": "15/8", "node": 2803, "naklon": 5 }, +{ "label": "15/8/1", "node": 4304, "naklon": 5 }, +{ "label": "15/8/2", "node": 4311, "naklon": 5 }, +{ "label": "15/9", "node": 2821, "naklon": 5 }, +{ "label": "15/10", "node": 3400, "naklon": 5 }, +{ "label": "15/11", "node": 2799, "naklon": 5 }, +{ "label": "15/12", "node": 2804, "naklon": 5 }, +{ "label": "15/12/1", "node": 4303, "naklon": 5 }, +{ "label": "15/12/2", "node": 4309, "naklon": 5 }, +{ "label": "15/13", "node": 2806, "naklon": 5 }, +{ "label": "15/14", "node": 2787, "naklon": 5 }, +{ "label": "15/15", "node": 2809, "naklon": 5 }, +{ "label": "15/16", "node": 2814, "naklon": 0 }, +{ "label": "15/17", "node": 3934, "naklon": 0 }, +{ "label": "15/18", "node": 3192, "naklon": 0 }, +{ "label": "15/19", "node": 2812, "naklon": 0 }, +{ "label": "15/20", "node": 4070, "naklon": 0 }, +{ "label": "15/21", "node": 2826, "naklon": 0 }, +{ "label": "15/22", "node": 2808, "naklon": 3 }, +{ "label": "15/23", "node": 2795, "naklon": 3 }, +{ "label": "15/24", "node": 2807, "naklon": 3 }, +{ "label": "15/25", "node": 2831, "naklon": 0 }, +{ "label": "15/26", "node": 2862, "naklon": null }, +{ "label": "15/27", "node": 2861, "naklon": 0 }, +{ "label": "15/28", "node": 2866, "naklon": 0 }, +{ "label": "15/28/1", "node": 3546, "naklon": 0 }, +{ "label": "15/29", "node": 4146, "naklon": 0 }, +{ "label": "15/29/1", "node": 3001, "naklon": 0 }, +{ "label": "15/30", "node": 2835, "naklon": 0 }, +{ "label": "15/31", "node": 2874, "naklon": 0 }, +{ "label": "15/32", "node": 2852, "naklon": 0 }, +{ "label": "15/33", "node": 2851, "naklon": 0 }, +{ "label": "15/33/1", "node": 3560, "naklon": 0 }, +{ "label": "15/34", "node": 2858, "naklon": 0 }, +{ "label": "15/34/1", "node": 4306, "naklon": 0 }, +{ "label": "15/35", "node": 2856, "naklon": 0 }, +{ "label": "15/36", "node": 2847, "naklon": 0 }, +{ "label": "15/36/1", "node": 3556, "naklon": 0 }, +{ "label": "15/37", "node": 3950, "naklon": 0 }, +{ "label": "15/38", "node": 2848, "naklon": 0 }, +{ "label": "15/39", "node": 2863, "naklon": 0 }, +{ "label": "15/39/1", "node": 4313, "naklon": 0 }, +{ "label": "15/40", "node": 2873, "naklon": 0 }, +{ "label": "15/40/1", "node": 2984, "naklon": 0 }, +{ "label": "15/41", "node": 2854, "naklon": 0 }, +{ "label": "15/42", "node": 2859, "naklon": 0 }, +{ "label": "15/43", "node": 2872, "naklon": 0 }, +{ "label": "15/44", "node": 2849, "naklon": 0 }, +{ "label": "15/45", "node": 2864, "naklon": 0 }, +{ "label": "15/46", "node": 3553, "naklon": null }, +{ "label": "15/47", "node": 3021, "naklon": null }, +{ "label": "15/47/1", "node": 3008, "naklon": null }, +{ "label": "15/48", "node": 3017, "naklon": null }, +{ "label": "15/49", "node": 3014, "naklon": null }, +{ "label": "15/50", "node": 2981, "naklon": null }, +{ "label": "15/51", "node": 3020, "naklon": null }, +{ "label": "15/52", "node": 3027, "naklon": null }, +{ "label": "15/53", "node": 3006, "naklon": null }, +{ "label": "15/54", "node": 3012, "naklon": null }, +{ "label": "15/55", "node": 2738, "naklon": 0 }, +{ "label": "15/56", "node": 2725, "naklon": 0 }, +{ "label": "15/57", "node": 3016, "naklon": null }, +{ "label": "15/58", "node": 3005, "naklon": null }, +{ "label": "15/58/1", "node": 3009, "naklon": null }, +{ "label": "15/59", "node": 3010, "naklon": 0 }, +{ "label": "15/59/1", "node": 3538, "naklon": 0 }, +{ "label": "15/59/2", "node": 4145, "naklon": 0 }, +{ "label": "15/60", "node": 2713, "naklon": 0 }, +{ "label": "15/61", "node": 2789, "naklon": 0 }, +{ "label": "15/62", "node": 2736, "naklon": 0 }, +{ "label": "15/63", "node": 2739, "naklon": 0 }, +{ "label": "15/64", "node": 4346, "naklon": 0 }, +{ "label": "15/65", "node": 2731, "naklon": 0 }, +{ "label": "15/66", "node": 2818, "naklon": 0 }, +{ "label": "15/66/1", "node": 3557, "naklon": 0 }, +{ "label": "15/67", "node": 2822, "naklon": 0 }, +{ "label": "15/68", "node": 2833, "naklon": 0 }, +{ "label": "15/69", "node": 2834, "naklon": 0 }, +{ "label": "15/70", "node": 3097, "naklon": 0 }, +{ "label": "15/71", "node": 2824, "naklon": 0 }, +{ "label": "15/72", "node": 2828, "naklon": 0 }, +{ "label": "15/73", "node": 2600, "naklon": 0 }, +{ "label": "15/73/1", "node": 4314, "naklon": 0 }, +{ "label": "15/74", "node": 2832, "naklon": 0 }, +{ "label": "15/75", "node": 4360, "naklon": 0 }, +{ "label": "15/76", "node": 2846, "naklon": 0 }, +{ "label": "15/77", "node": 2584, "naklon": 0 }, +{ "label": "15/78", "node": 2843, "naklon": 0 }, +{ "label": "15/78/1", "node": 4308, "naklon": 0 }, +{ "label": "15/79", "node": 4144, "naklon": null }, +{ "label": "15/80", "node": 2844, "naklon": 0 }, +{ "label": "15/81", "node": 2842, "naklon": 0 }, +{ "label": "15/82", "node": 2838, "naklon": 0 }, +{ "label": "15/83", "node": 2837, "naklon": null }, +{ "label": "15/83/1", "node": 3555, "naklon": null }, +{ "label": "15/84", "node": 2839, "naklon": 0 }, +{ "label": "15/85", "node": 2830, "naklon": 0 }, +{ "label": "15/86", "node": 4066, "naklon": 0 }, +{ "label": "15/87", "node": 2836, "naklon": 0 }, +{ "label": "15/88", "node": 2911, "naklon": 0 }, +{ "label": "15/89", "node": 2825, "naklon": 0 }, +{ "label": "15/90", "node": 2811, "naklon": 0 }, +{ "label": "15/94", "node": 3740, "naklon": 15 }, +{ "label": "15/95", "node": 2734, "naklon": 15 }, +{ "label": "15/96", "node": 3105, "naklon": 15 }, +{ "label": "15/97", "node": 2732, "naklon": 15 }, +{ "label": "15/98", "node": 2727, "naklon": 15 }, +{ "label": "15/99", "node": 2735, "naklon": 15 }, +{ "label": "15/100", "node": 3926, "naklon": 15 }, +{ "label": "15/101", "node": 2918, "naklon": 0 }, +{ "label": "15/102", "node": 2705, "naklon": 10 }, +{ "label": "15/103", "node": 2708, "naklon": 10 }, +{ "label": "15/104", "node": 2721, "naklon": 10 }, +{ "label": "15/105", "node": 2719, "naklon": 10 }, +{ "label": "15/106", "node": 2919, "naklon": 10 }, +{ "label": "15/107", "node": 3101, "naklon": 10 }, +{ "label": "15/108", "node": 2853, "naklon": 10 }, +{ "label": "15/109", "node": 2715, "naklon": 10 }, +{ "label": "15/110", "node": 2712, "naklon": 0 }, +{ "label": "15/111", "node": 2711, "naklon": 0 }, +{ "label": "15/112", "node": 2709, "naklon": 0 }, +{ "label": "15/113", "node": 2710, "naklon": 0 }, +{ "label": "15/114", "node": 2907, "naklon": 0 }, +{ "label": "15/115", "node": 2906, "naklon": 0 }, +{ "label": "15/116", "node": 2908, "naklon": 0 }, +{ "label": "15/117", "node": 2901, "naklon": 0 }, +{ "label": "15/118", "node": 2913, "naklon": 0 }, +{ "label": "15/119", "node": 3656, "naklon": 0 }, +{ "label": "15/120", "node": 2781, "naklon": 0 }, +{ "label": "15/121", "node": 2802, "naklon": 0 }, +{ "label": "15/122", "node": 2791, "naklon": 0 }, +{ "label": "15/123", "node": 2783, "naklon": 0 }, +{ "label": "15/124", "node": 2794, "naklon": 0 }, +{ "label": "15/125", "node": 3139, "naklon": 0 }, +{ "label": "15/126", "node": 3229, "naklon": 5 }, +{ "label": "15/127", "node": 3239, "naklon": 5 }, +{ "label": "15/128", "node": 3230, "naklon": 5 }, +{ "label": "15/129", "node": 4016, "naklon": null }, +{ "label": "16/16A", "node": 3608, "naklon": 0 }, +{ "label": "16/16B", "node": 4151, "naklon": 0 }, +{ "label": "16/1", "node": 3710, "naklon": 0 }, +{ "label": "16/2", "node": 3726, "naklon": 0 }, +{ "label": "16/3", "node": 3743, "naklon": 0 }, +{ "label": "16/4", "node": 3724, "naklon": 0 }, +{ "label": "16/5", "node": 3712, "naklon": 0 }, +{ "label": "16/6", "node": 3739, "naklon": 0 }, +{ "label": "16/7", "node": 3742, "naklon": 0 }, +{ "label": "16/8", "node": 3731, "naklon": 0 }, +{ "label": "16/9", "node": 3727, "naklon": 0 }, +{ "label": "16/10", "node": 3729, "naklon": 0 }, +{ "label": "16/11", "node": 3736, "naklon": 0 }, +{ "label": "16/12", "node": 3713, "naklon": 0 }, +{ "label": "16/13", "node": 3715, "naklon": 0 }, +{ "label": "16/14", "node": 3733, "naklon": 0 }, +{ "label": "16/15", "node": 3732, "naklon": 0 }, +{ "label": "16/17", "node": 3634, "naklon": 0 }, +{ "label": "16/18", "node": 3610, "naklon": 0 }, +{ "label": "16/19", "node": 3626, "naklon": 0 }, +{ "label": "16/20", "node": 3618, "naklon": 0 }, +{ "label": "16/21", "node": 3619, "naklon": 0 }, +{ "label": "16/22", "node": 3628, "naklon": 0 }, +{ "label": "16/23", "node": 3615, "naklon": 0 }, +{ "label": "16/24", "node": 3609, "naklon": 0 }, +{ "label": "16/25", "node": 3606, "naklon": 0 }, +{ "label": "16/26", "node": 3624, "naklon": 0 }, +{ "label": "16/27", "node": 3627, "naklon": 0 }, +{ "label": "16/28", "node": 3607, "naklon": 0 }, +{ "label": "16/29", "node": 4370, "naklon": 0 }, +{ "label": "16/30", "node": 3692, "naklon": 0 }, +{ "label": "16/31", "node": 3614, "naklon": 0 }, +{ "label": "16/32", "node": 3623, "naklon": 0 }, +{ "label": "16/33", "node": 4373, "naklon": 0 }, +{ "label": "16/34", "node": 3620, "naklon": 0 }, +{ "label": "16/35", "node": 3685, "naklon": 0 }, +{ "label": "16/36", "node": 3616, "naklon": 0 }, +{ "label": "16/37", "node": 3686, "naklon": 0 }, +{ "label": "16/38", "node": 3688, "naklon": 0 }, +{ "label": "16/39", "node": 3684, "naklon": 0 }, +{ "label": "16/40", "node": 3825, "naklon": 0 }, +{ "label": "16/41", "node": 3865, "naklon": 0 }, +{ "label": "16/42", "node": 3824, "naklon": 0 }, +{ "label": "16/43", "node": 3871, "naklon": 0 }, +{ "label": "16/44", "node": 3801, "naklon": 0 }, +{ "label": "16/45", "node": 3862, "naklon": 0 }, +{ "label": "16/46", "node": 3876, "naklon": 0 }, +{ "label": "16/47", "node": 3861, "naklon": 0 }, +{ "label": "16/48", "node": 4215, "naklon": 0 }, +{ "label": "16/49", "node": 3605, "naklon": 10 }, +{ "label": "16/50", "node": 3603, "naklon": 10 }, +{ "label": "16/51", "node": 3592, "naklon": 10 }, +{ "label": "16/52", "node": 3598, "naklon": 10 }, +{ "label": "16/53", "node": 3594, "naklon": 10 }, +{ "label": "16/54", "node": 3593, "naklon": 10 }, +{ "label": "16/55", "node": 3630, "naklon": 10 }, +{ "label": "16/56", "node": 3763, "naklon": 10 }, +{ "label": "16/57", "node": 3746, "naklon": 10 }, +{ "label": "16/58", "node": 3699, "naklon": 0 }, +{ "label": "16/59", "node": 3698, "naklon": 0 }, +{ "label": "16/60", "node": 3709, "naklon": null }, +{ "label": "16/61", "node": 3708, "naklon": 0 }, +{ "label": "16/62", "node": 3703, "naklon": null }, +{ "label": "16/63", "node": 3700, "naklon": 0 }, +{ "label": "16/64", "node": 3701, "naklon": null }, +{ "label": "16/65", "node": 3704, "naklon": 0 }, +{ "label": "16/66", "node": 3707, "naklon": null }, +{ "label": "16/67", "node": 3810, "naklon": 0 }, +{ "label": "16/68", "node": 4208, "naklon": null }, +{ "label": "16/69", "node": 3867, "naklon": 0 }, +{ "label": "16/70", "node": 4372, "naklon": null }, +{ "label": "16/71", "node": 3881, "naklon": 0 }, +{ "label": "16/72", "node": 4204, "naklon": null }, +{ "label": "16/73", "node": 3869, "naklon": 0 }, +{ "label": "16/74", "node": 4202, "naklon": null }, +{ "label": "16/75", "node": 3830, "naklon": 0 }, +{ "label": "16/76", "node": 3870, "naklon": null }, +{ "label": "16/77", "node": 3964, "naklon": 0 }, +{ "label": "16/78", "node": 3849, "naklon": 0 }, +{ "label": "16/79", "node": 3694, "naklon": null }, +{ "label": "16/80", "node": 3717, "naklon": 0 }, +{ "label": "16/81", "node": 3877, "naklon": null }, +{ "label": "16/82", "node": 3755, "naklon": 0 }, +{ "label": "16/83", "node": 3725, "naklon": null }, +{ "label": "16/84", "node": 3716, "naklon": 0 }, +{ "label": "16/85", "node": 3696, "naklon": null }, +{ "label": "16/86", "node": 3702, "naklon": 0 }, +{ "label": "16/87", "node": 3706, "naklon": null }, +{ "label": "16/88", "node": 3850, "naklon": 0 }, +{ "label": "16/89", "node": 3848, "naklon": null }, +{ "label": "16/90", "node": 3737, "naklon": null }, +{ "label": "16/91", "node": 3705, "naklon": 0 }, +{ "label": "16/92", "node": 3723, "naklon": null }, +{ "label": "16/93", "node": 3842, "naklon": 0 }, +{ "label": "16/94", "node": 3735, "naklon": null }, +{ "label": "16/95", "node": 3719, "naklon": 0 }, +{ "label": "16/96", "node": 3697, "naklon": 0 }, +{ "label": "16/97", "node": 3711, "naklon": 0 }, +{ "label": "16/98", "node": 4107, "naklon": null }, +{ "label": "16/99", "node": 4112, "naklon": 5 }, +{ "label": "16/100", "node": 4106, "naklon": 5 }, +{ "label": "16/101", "node": 4111, "naklon": 5 }, +{ "label": "16/102", "node": 4091, "naklon": null }, +{ "label": "16/103", "node": 4104, "naklon": 5 }, +{ "label": "16/104", "node": 4094, "naklon": null }, +{ "label": "16/105", "node": 4089, "naklon": 5 }, +{ "label": "16/106", "node": 4095, "naklon": null }, +{ "label": "16/107", "node": 4102, "naklon": 5 }, +{ "label": "16/108", "node": 4105, "naklon": null }, +{ "label": "16/109", "node": 3859, "naklon": null }, +{ "label": "16/110", "node": 4090, "naklon": 5 }, +{ "label": "16/111", "node": 4110, "naklon": null }, +{ "label": "16/112", "node": 4097, "naklon": 5 }, +{ "label": "16/113", "node": 4099, "naklon": null }, +{ "label": "16/114", "node": 4096, "naklon": null }, +{ "label": "16/115", "node": 4101, "naklon": 5 }, +{ "label": "16/116", "node": 4109, "naklon": null }, +{ "label": "16/117", "node": 4092, "naklon": 5 }, +{ "label": "16/118", "node": 3631, "naklon": null }, +{ "label": "16/119", "node": 3632, "naklon": 0 }, +{ "label": "16/120", "node": 3641, "naklon": null }, +{ "label": "16/121", "node": 3638, "naklon": 0 }, +{ "label": "16/122", "node": 3637, "naklon": null }, +{ "label": "16/123", "node": 4142, "naklon": null }, +{ "label": "16/124", "node": 4147, "naklon": 5 }, +{ "label": "16/125", "node": 4139, "naklon": 5 }, +{ "label": "20/30A", "node": 3172, "naklon": 2 }, +{ "label": "20/30B", "node": 3164, "naklon": 2 }, +{ "label": "20/1", "node": 3247, "naklon": 10 }, +{ "label": "20/2", "node": 3296, "naklon": 10 }, +{ "label": "20/3", "node": 3246, "naklon": 10 }, +{ "label": "20/4", "node": 3270, "naklon": 10 }, +{ "label": "20/5", "node": 3294, "naklon": 10 }, +{ "label": "20/6", "node": 3298, "naklon": 10 }, +{ "label": "20/7", "node": 3297, "naklon": 10 }, +{ "label": "20/8", "node": 3293, "naklon": 10 }, +{ "label": "20/9", "node": 3299, "naklon": 10 }, +{ "label": "20/10", "node": 3295, "naklon": 10 }, +{ "label": "20/11", "node": 3244, "naklon": 10 }, +{ "label": "20/12", "node": 3249, "naklon": 10 }, +{ "label": "20/13", "node": 3268, "naklon": 10 }, +{ "label": "20/14", "node": 3245, "naklon": 10 }, +{ "label": "20/15", "node": 3278, "naklon": 10 }, +{ "label": "20/16", "node": 3280, "naklon": 10 }, +{ "label": "20/17", "node": 3292, "naklon": 10 }, +{ "label": "20/18", "node": 3287, "naklon": 10 }, +{ "label": "20/19", "node": 3282, "naklon": 10 }, +{ "label": "20/20", "node": 3273, "naklon": 0 }, +{ "label": "20/21", "node": 3157, "naklon": 0 }, +{ "label": "20/22", "node": 3283, "naklon": 0 }, +{ "label": "20/23", "node": 3159, "naklon": 0 }, +{ "label": "20/24", "node": 3289, "naklon": 0 }, +{ "label": "20/25", "node": 3163, "naklon": 0 }, +{ "label": "20/26", "node": 3126, "naklon": 0 }, +{ "label": "20/27", "node": 3171, "naklon": 0 }, +{ "label": "20/28", "node": 3162, "naklon": 0 }, +{ "label": "20/29", "node": 3279, "naklon": 10 }, +{ "label": "20/31", "node": 3173, "naklon": 0 }, +{ "label": "20/32", "node": 3127, "naklon": 0 }, +{ "label": "20/33", "node": 3131, "naklon": 0 }, +{ "label": "20/34", "node": 3129, "naklon": 0 }, +{ "label": "20/35", "node": 3276, "naklon": 2 }, +{ "label": "20/36", "node": 3290, "naklon": 2 }, +{ "label": "20/37", "node": 3132, "naklon": 0 }, +{ "label": "20/38", "node": 3138, "naklon": 0 }, +{ "label": "20/39", "node": 3272, "naklon": 0 }, +{ "label": "20/40", "node": 3291, "naklon": 0 }, +{ "label": "20/41", "node": 3277, "naklon": 10 }, +{ "label": "20/42", "node": 3286, "naklon": 10 }, +{ "label": "20/43", "node": 3281, "naklon": 10 }, +{ "label": "20/44", "node": 3288, "naklon": 10 }, +{ "label": "20/45", "node": 3284, "naklon": 10 }, +{ "label": "20/46", "node": 3167, "naklon": 10 }, +{ "label": "20/47", "node": 3872, "naklon": 0 }, +{ "label": "20/48", "node": 3124, "naklon": 0 }, +{ "label": "20/49", "node": 3133, "naklon": 0 }, +{ "label": "20/50", "node": 3158, "naklon": 0 }, +{ "label": "20/51", "node": 3169, "naklon": 0 }, +{ "label": "20/52", "node": 3146, "naklon": 0 }, +{ "label": "20/53", "node": 3160, "naklon": 0 }, +{ "label": "20/54", "node": 3248, "naklon": 0 }, +{ "label": "20/55", "node": 3156, "naklon": 0 }, +{ "label": "20/56", "node": 3161, "naklon": 0 }, +{ "label": "20/57", "node": 3170, "naklon": 0 }, +{ "label": "20/58", "node": 3168, "naklon": 0 }, +{ "label": "20/59", "node": 3125, "naklon": 0 }, +{ "label": "20/60", "node": 3166, "naklon": 0 }, +{ "label": "20/61", "node": 3130, "naklon": 0 }, +{ "label": "20/62", "node": 3563, "naklon": 0 }, +{ "label": "20/63", "node": 3550, "naklon": null }, +{ "label": "20/67", "node": 3269, "naklon": 0 }, +{ "label": "21/1", "node": 2921, "naklon": 0 }, +{ "label": "21/2", "node": 2707, "naklon": 0 }, +{ "label": "21/3", "node": 2723, "naklon": 0 }, +{ "label": "21/4", "node": 2716, "naklon": 0 }, +{ "label": "21/5", "node": 2717, "naklon": 0 }, +{ "label": "21/6", "node": 2720, "naklon": 0 }, +{ "label": "21/7", "node": 2722, "naklon": 0 }, +{ "label": "21/8", "node": 2718, "naklon": 0 }, +{ "label": "21/9", "node": 2724, "naklon": 0 }, +{ "label": "21/10", "node": 2742, "naklon": 0 }, +{ "label": "21/11", "node": 2743, "naklon": 0 }, +{ "label": "21/12", "node": 2733, "naklon": 0 }, +{ "label": "21/14", "node": 2903, "naklon": 0 }, +{ "label": "21/15", "node": 2917, "naklon": 0 }, +{ "label": "21/16", "node": 2897, "naklon": 0 }, +{ "label": "21/17", "node": 2914, "naklon": 0 }, +{ "label": "21/18", "node": 2898, "naklon": 0 }, +{ "label": "21/19", "node": 2773, "naklon": 0 }, +{ "label": "21/20", "node": 2895, "naklon": 0 }, +{ "label": "21/21", "node": 2896, "naklon": 0 }, +{ "label": "21/22", "node": 2771, "naklon": 0 }, +{ "label": "21/23", "node": 2772, "naklon": 0 }, +{ "label": "21/24", "node": 2793, "naklon": 0 }, +{ "label": "21/25", "node": 2902, "naklon": 0 }, +{ "label": "21/26", "node": 2910, "naklon": 0 }, +{ "label": "21/27", "node": 2909, "naklon": 0 }, +{ "label": "21/28", "node": 2920, "naklon": 0 }, +{ "label": "21/29", "node": 2916, "naklon": 0 }, +{ "label": "21/30", "node": 2904, "naklon": 0 }, +{ "label": "21/31", "node": 2915, "naklon": 0 }, +{ "label": "21/32", "node": 2905, "naklon": 0 }, +{ "label": "21/33", "node": 2900, "naklon": 0 }, +{ "label": "21/34", "node": 2899, "naklon": 0 }, +{ "label": "21/36", "node": 2741, "naklon": 0 }, +{ "label": "21/37", "node": 2714, "naklon": 0 }, +{ "label": "21/38", "node": 2701, "naklon": 0 }, +{ "label": "21/39", "node": 2703, "naklon": 0 }, +{ "label": "21/40", "node": 2704, "naklon": 0 }, +{ "label": "21/41", "node": 2702, "naklon": 0 }, +{ "label": "21/42", "node": 2706, "naklon": 0 }, +{ "label": "21/43", "node": 2776, "naklon": 0 }, +{ "label": "21/44", "node": 2770, "naklon": 0 }, +{ "label": "21/45", "node": 2786, "naklon": 0 }, +{ "label": "21/46", "node": 2779, "naklon": 0 }, +{ "label": "21/47", "node": 2782, "naklon": 0 }, +{ "label": "21/48", "node": 2785, "naklon": 0 }, +{ "label": "21/49", "node": 2769, "naklon": 0 }, +{ "label": "21/50", "node": 3354, "naklon": 0 }, +{ "label": "21/51", "node": 2778, "naklon": 0 }, +{ "label": "21/52", "node": 2775, "naklon": 0 }, +{ "label": "21/53", "node": 2780, "naklon": 0 }, +{ "label": "21/54", "node": 2790, "naklon": 0 }, +{ "label": "21/55", "node": 2792, "naklon": 0 }, +{ "label": "21/56", "node": 2774, "naklon": 0 }, +{ "label": "22/1", "node": 2630, "naklon": 0 }, +{ "label": "22/2", "node": 2631, "naklon": 0 }, +{ "label": "22/3", "node": 2632, "naklon": 0 }, +{ "label": "22/4", "node": 2633, "naklon": 0 }, +{ "label": "22/5", "node": 2634, "naklon": 0 }, +{ "label": "22/6", "node": 2636, "naklon": 0 }, +{ "label": "22/7", "node": 4367, "naklon": 0 }, +{ "label": "22/8", "node": 2637, "naklon": 0 }, +{ "label": "22/9", "node": 2638, "naklon": 0 }, +{ "label": "22/10", "node": 2639, "naklon": 0 }, +{ "label": "22/11", "node": 2640, "naklon": 0 }, +{ "label": "22/12", "node": 2641, "naklon": 0 }, +{ "label": "22/13", "node": 2642, "naklon": 0 }, +{ "label": "22/14", "node": 2643, "naklon": 0 }, +{ "label": "22/15", "node": 2644, "naklon": 0 }, +{ "label": "22/16", "node": 2645, "naklon": 0 }, +{ "label": "22/17", "node": 2646, "naklon": 0 }, +{ "label": "22/18", "node": 2647, "naklon": 0 }, +{ "label": "22/19", "node": 2648, "naklon": 0 }, +{ "label": "22/20", "node": 2649, "naklon": 0 }, +{ "label": "22/21", "node": 2650, "naklon": 0 }, +{ "label": "22/22", "node": 2651, "naklon": 0 }, +{ "label": "22/23", "node": 4103, "naklon": 0 }, +{ "label": "22/24", "node": 2653, "naklon": 0 }, +{ "label": "22/25", "node": 2654, "naklon": 0 }, +{ "label": "22/26", "node": 2655, "naklon": 0 }, +{ "label": "22/27", "node": 2656, "naklon": 0 }, +{ "label": "22/28", "node": 2657, "naklon": 0 }, +{ "label": "22/29", "node": 2658, "naklon": 0 }, +{ "label": "22/30", "node": 2659, "naklon": 0 }, +{ "label": "22/31", "node": 2660, "naklon": 0 }, +{ "label": "22/32", "node": 2661, "naklon": 0 }, +{ "label": "22/32/1", "node": 3015, "naklon": 0 }, +{ "label": "22/33", "node": 2662, "naklon": 0 }, +{ "label": "22/34", "node": 2663, "naklon": 0 }, +{ "label": "22/35", "node": 2664, "naklon": 0 }, +{ "label": "22/36", "node": 2665, "naklon": 0 }, +{ "label": "22/37", "node": 2666, "naklon": 0 }, +{ "label": "22/38", "node": 2667, "naklon": 0 }, +{ "label": "22/39", "node": 2668, "naklon": 0 }, +{ "label": "22/40", "node": 2669, "naklon": null }, +{ "label": "22/41", "node": 2670, "naklon": null }, +{ "label": "22/42", "node": 2671, "naklon": null }, +{ "label": "23/9A", "node": 3087, "naklon": 10 }, +{ "label": "23/9B", "node": 3090, "naklon": 10 }, +{ "label": "23/1", "node": 3075, "naklon": 0 }, +{ "label": "23/2", "node": 3089, "naklon": 0 }, +{ "label": "23/3", "node": 3088, "naklon": 0 }, +{ "label": "23/4", "node": 3228, "naklon": 10 }, +{ "label": "23/5", "node": 2751, "naklon": 10 }, +{ "label": "23/6", "node": 3243, "naklon": 10 }, +{ "label": "23/7", "node": 4349, "naklon": 10 }, +{ "label": "23/8", "node": 3102, "naklon": 10 }, +{ "label": "23/10", "node": 3099, "naklon": 10 }, +{ "label": "23/11", "node": 3103, "naklon": 10 }, +{ "label": "23/12", "node": 3093, "naklon": 10 }, +{ "label": "23/13", "node": 3098, "naklon": 10 }, +{ "label": "23/14", "node": 3092, "naklon": 10 }, +{ "label": "23/15", "node": 3233, "naklon": 0 }, +{ "label": "23/16", "node": 3095, "naklon": 0 }, +{ "label": "23/17", "node": 4074, "naklon": 0 }, +{ "label": "23/18", "node": 2729, "naklon": 0 }, +{ "label": "23/19", "node": 3234, "naklon": 0 }, +{ "label": "23/20", "node": 3094, "naklon": 0 }, +{ "label": "23/21", "node": 2817, "naklon": 0 }, +{ "label": "23/22", "node": 3226, "naklon": 0 }, +{ "label": "23/23", "node": 3225, "naklon": 0 }, +{ "label": "23/24", "node": 3237, "naklon": 0 }, +{ "label": "23/25", "node": 4250, "naklon": 0 }, +{ "label": "23/26", "node": 3059, "naklon": 10 }, +{ "label": "23/27", "node": 3238, "naklon": 10 }, +{ "label": "23/28", "node": 3242, "naklon": 10 }, +{ "label": "23/29", "node": 3236, "naklon": 10 }, +{ "label": "23/30", "node": 3112, "naklon": 10 }, +{ "label": "23/31", "node": 3224, "naklon": 0 }, +{ "label": "23/32", "node": 4298, "naklon": 10 }, +{ "label": "23/33", "node": 4150, "naklon": 10 }, +{ "label": "23/34", "node": 3091, "naklon": 10 }, +{ "label": "25/1", "node": 3771, "naklon": 5 }, +{ "label": "25/2", "node": 3777, "naklon": 5 }, +{ "label": "25/3", "node": 3749, "naklon": 5 }, +{ "label": "25/4", "node": 3769, "naklon": 5 }, +{ "label": "25/5", "node": 3765, "naklon": 5 }, +{ "label": "25/6", "node": 3785, "naklon": 5 }, +{ "label": "25/7", "node": 3761, "naklon": 5 }, +{ "label": "25/8", "node": 3758, "naklon": 5 }, +{ "label": "25/9", "node": 3766, "naklon": 5 }, +{ "label": "25/10", "node": 3779, "naklon": 5 }, +{ "label": "25/11", "node": 3899, "naklon": 10 }, +{ "label": "25/12", "node": 3922, "naklon": 10 }, +{ "label": "25/13", "node": 3912, "naklon": 10 }, +{ "label": "25/14", "node": 3933, "naklon": 10 }, +{ "label": "25/15", "node": 3921, "naklon": 10 }, +{ "label": "25/16", "node": 4300, "naklon": 10 }, +{ "label": "25/17", "node": 3927, "naklon": 10 }, +{ "label": "25/18", "node": 3212, "naklon": 10 }, +{ "label": "25/19", "node": 3208, "naklon": 10 }, +{ "label": "25/20", "node": 3207, "naklon": 10 }, +{ "label": "25/21", "node": 4294, "naklon": 10 }, +{ "label": "25/22", "node": 3209, "naklon": 10 }, +{ "label": "25/23", "node": 3745, "naklon": 10 }, +{ "label": "25/24", "node": 3762, "naklon": 10 }, +{ "label": "25/25", "node": 3215, "naklon": 10 }, +{ "label": "25/26", "node": 3210, "naklon": 10 }, +{ "label": "25/27", "node": 3211, "naklon": 10 }, +{ "label": "25/28", "node": 3206, "naklon": 10 }, +{ "label": "25/29", "node": 3918, "naklon": 5 }, +{ "label": "25/30", "node": 3928, "naklon": 5 }, +{ "label": "25/31", "node": 3917, "naklon": 5 }, +{ "label": "25/32", "node": 4029, "naklon": 0 }, +{ "label": "25/33", "node": 4038, "naklon": 0 }, +{ "label": "25/34", "node": 4022, "naklon": 0 }, +{ "label": "25/35", "node": 3937, "naklon": 0 }, +{ "label": "25/36", "node": 3190, "naklon": 0 }, +{ "label": "25/37", "node": 3835, "naklon": 0 }, +{ "label": "25/38", "node": 3201, "naklon": 0 }, +{ "label": "25/39", "node": 3193, "naklon": 0 }, +{ "label": "25/40", "node": 3191, "naklon": 0 }, +{ "label": "25/41", "node": 3203, "naklon": 0 }, +{ "label": "25/42", "node": 4301, "naklon": 0 }, +{ "label": "25/43", "node": 3223, "naklon": 0 }, +{ "label": "25/44", "node": 3202, "naklon": 0 }, +{ "label": "25/45", "node": 3205, "naklon": 0 }, +{ "label": "25/46", "node": 3194, "naklon": 0 }, +{ "label": "25/47", "node": 3198, "naklon": 0 }, +{ "label": "25/48", "node": 3204, "naklon": 0 }, +{ "label": "25/49", "node": 3200, "naklon": 0 }, +{ "label": "25/50", "node": 3216, "naklon": 0 }, +{ "label": "25/51", "node": 3932, "naklon": 5 }, +{ "label": "25/52", "node": 3923, "naklon": 5 }, +{ "label": "25/53", "node": 3913, "naklon": 5 }, +{ "label": "25/54", "node": 3900, "naklon": 5 }, +{ "label": "25/55", "node": 4189, "naklon": 10 }, +{ "label": "25/56", "node": 4191, "naklon": 10 }, +{ "label": "25/57", "node": 3790, "naklon": 10 }, +{ "label": "25/58", "node": 4190, "naklon": 10 }, +{ "label": "25/59", "node": 4302, "naklon": 0 }, +{ "label": "25/60", "node": 4351, "naklon": 0 }, +{ "label": "25/61", "node": 4075, "naklon": 0 }, +{ "label": "25/62", "node": 4071, "naklon": 0 }, +{ "label": "25/63", "node": 3784, "naklon": 0 }, +{ "label": "25/64", "node": 4065, "naklon": 0 }, +{ "label": "25/65", "node": 4297, "naklon": 0 }, +{ "label": "25/66", "node": 4295, "naklon": 0 }, +{ "label": "25/67", "node": 4299, "naklon": 0 }, +{ "label": "25/68", "node": 3772, "naklon": 0 }, +{ "label": "25/69", "node": 3941, "naklon": 0 }, +{ "label": "25/70", "node": 3782, "naklon": 0 }, +{ "label": "25/71", "node": 4068, "naklon": 0 }, +{ "label": "25/72", "node": 4073, "naklon": 0 }, +{ "label": "25/73", "node": 3901, "naklon": 5 }, +{ "label": "25/74", "node": 4296, "naklon": 5 }, +{ "label": "25/75", "node": 3910, "naklon": 5 }, +{ "label": "25/76", "node": 4293, "naklon": 5 }, +{ "label": "25/77", "node": 3919, "naklon": 5 }, +{ "label": "25/78", "node": 3924, "naklon": 5 }, +{ "label": "25/79", "node": 3909, "naklon": 5 }, +{ "label": "25/80", "node": 3896, "naklon": 5 }, +{ "label": "25/81", "node": 3911, "naklon": 5 }, +{ "label": "25/82", "node": 2819, "naklon": 15 }, +{ "label": "25/83", "node": 3776, "naklon": 15 }, +{ "label": "25/84", "node": 3752, "naklon": 15 }, +{ "label": "25/85", "node": 4353, "naklon": 15 }, +{ "label": "25/86", "node": 3791, "naklon": 0 }, +{ "label": "25/87", "node": 3770, "naklon": 0 }, +{ "label": "25/88", "node": 3760, "naklon": 0 }, +{ "label": "25/89", "node": 3115, "naklon": 0 }, +{ "label": "25/90", "node": 3738, "naklon": 0 }, +{ "label": "25/91", "node": 3748, "naklon": 0 }, +{ "label": "25/92", "node": 3753, "naklon": 0 }, +{ "label": "25/93", "node": 3775, "naklon": 0 }, +{ "label": "25/94", "node": 3778, "naklon": 5 }, +{ "label": "25/95", "node": 4078, "naklon": 5 }, +{ "label": "25/96", "node": 4088, "naklon": 5 }, +{ "label": "25/97", "node": 3856, "naklon": 5 }, +{ "label": "25/98", "node": 4084, "naklon": 5 }, +{ "label": "25/99", "node": 4069, "naklon": 5 }, +{ "label": "25/100", "node": 4188, "naklon": 5 }, +{ "label": "25/101", "node": 4064, "naklon": 5 }, +{ "label": "25/102", "node": 3792, "naklon": 5 }, +{ "label": "25/103", "node": 3780, "naklon": 5 }, +{ "label": "25/104", "node": 4034, "naklon": 5 }, +{ "label": "25/105", "node": 4072, "naklon": 5 }, +{ "label": "25/106", "node": 3884, "naklon": 5 }, +{ "label": "25/107", "node": 3793, "naklon": 5 }, +{ "label": "25/108", "node": 3863, "naklon": 5 }, +{ "label": "25/109", "node": 3855, "naklon": 5 }, +{ "label": "33/1", "node": 3846, "naklon": 0 }, +{ "label": "33/2", "node": 3943, "naklon": 0 }, +{ "label": "33/3", "node": 3903, "naklon": 0 }, +{ "label": "33/4", "node": 3982, "naklon": 0 }, +{ "label": "33/5", "node": 3879, "naklon": 0 }, +{ "label": "33/6", "node": 3887, "naklon": 0 }, +{ "label": "33/7", "node": 3920, "naklon": 5 }, +{ "label": "33/8", "node": 3942, "naklon": 5 }, +{ "label": "33/9", "node": 3829, "naklon": null }, +{ "label": "34/79A", "node": 3452, "naklon": 6 }, +{ "label": "34/79B", "node": 3460, "naklon": 6 }, +{ "label": "34/90A", "node": 3443, "naklon": 6 }, +{ "label": "34/90B", "node": 3445, "naklon": 6 }, +{ "label": "34/90C", "node": 3457, "naklon": 6 }, +{ "label": "34/97A", "node": 3461, "naklon": 6 }, +{ "label": "34/97B", "node": 3463, "naklon": 6 }, +{ "label": "34/98A", "node": 3426, "naklon": 6 }, +{ "label": "34/98B", "node": 3444, "naklon": 6 }, +{ "label": "34/99A", "node": 3453, "naklon": 6 }, +{ "label": "34/99B", "node": 3455, "naklon": 6 }, +{ "label": "34/1", "node": 4009, "naklon": 0 }, +{ "label": "34/2", "node": 3602, "naklon": 0 }, +{ "label": "34/3", "node": 3441, "naklon": 0 }, +{ "label": "34/4", "node": 3464, "naklon": 0 }, +{ "label": "34/5", "node": 3883, "naklon": 0 }, +{ "label": "34/6", "node": 4098, "naklon": 0 }, +{ "label": "34/7", "node": 4003, "naklon": 0 }, +{ "label": "34/8", "node": 4004, "naklon": 0 }, +{ "label": "34/9", "node": 3888, "naklon": 0 }, +{ "label": "34/10", "node": 3997, "naklon": 0 }, +{ "label": "34/11", "node": 4006, "naklon": 0 }, +{ "label": "34/12", "node": 4000, "naklon": 0 }, +{ "label": "34/13", "node": 4011, "naklon": 0 }, +{ "label": "34/14", "node": 3999, "naklon": 0 }, +{ "label": "34/15", "node": 3981, "naklon": 0 }, +{ "label": "34/16", "node": 3988, "naklon": 0 }, +{ "label": "34/17", "node": 3986, "naklon": 0 }, +{ "label": "34/18", "node": 3998, "naklon": 0 }, +{ "label": "34/19", "node": 3983, "naklon": 0 }, +{ "label": "34/20", "node": 4005, "naklon": 0 }, +{ "label": "34/21", "node": 4001, "naklon": 0 }, +{ "label": "34/22", "node": 4008, "naklon": 0 }, +{ "label": "34/23", "node": 4002, "naklon": 0 }, +{ "label": "34/24", "node": 3996, "naklon": 0 }, +{ "label": "34/25", "node": 4007, "naklon": 0 }, +{ "label": "34/26", "node": 4113, "naklon": 15 }, +{ "label": "34/27", "node": 3595, "naklon": 5 }, +{ "label": "34/28", "node": 3599, "naklon": 5 }, +{ "label": "34/29", "node": 3601, "naklon": 5 }, +{ "label": "34/30", "node": 4205, "naklon": 0 }, +{ "label": "34/31", "node": 3987, "naklon": null }, +{ "label": "34/32", "node": 4214, "naklon": 0 }, +{ "label": "34/33", "node": 4226, "naklon": 0 }, +{ "label": "34/34", "node": 4209, "naklon": 0 }, +{ "label": "34/35", "node": 4201, "naklon": 0 }, +{ "label": "34/36", "node": 3440, "naklon": 0 }, +{ "label": "34/37", "node": 3465, "naklon": 0 }, +{ "label": "34/38", "node": 3446, "naklon": 0 }, +{ "label": "34/39", "node": 4039, "naklon": 5 }, +{ "label": "34/40", "node": 4057, "naklon": 5 }, +{ "label": "34/41", "node": 3985, "naklon": 0 }, +{ "label": "34/42", "node": 3882, "naklon": 0 }, +{ "label": "34/43", "node": 4040, "naklon": 5 }, +{ "label": "34/44", "node": 3231, "naklon": 0 }, +{ "label": "34/45", "node": 3227, "naklon": 0 }, +{ "label": "34/46", "node": 3431, "naklon": 0 }, +{ "label": "34/47", "node": 4013, "naklon": 0 }, +{ "label": "34/48", "node": 4045, "naklon": 0 }, +{ "label": "34/49", "node": 3949, "naklon": 0 }, +{ "label": "34/50", "node": 3953, "naklon": 0 }, +{ "label": "34/51", "node": 3952, "naklon": 0 }, +{ "label": "34/52", "node": 3995, "naklon": 0 }, +{ "label": "34/53", "node": 3992, "naklon": 0 }, +{ "label": "34/54", "node": 4198, "naklon": 0 }, +{ "label": "34/55", "node": 3935, "naklon": 0 }, +{ "label": "34/56", "node": 4050, "naklon": 0 }, +{ "label": "34/57", "node": 4049, "naklon": 0 }, +{ "label": "34/58", "node": 4054, "naklon": 0 }, +{ "label": "34/59", "node": 3663, "naklon": 6 }, +{ "label": "34/60", "node": 3661, "naklon": 6 }, +{ "label": "34/61", "node": 3664, "naklon": 6 }, +{ "label": "34/62", "node": 3660, "naklon": 6 }, +{ "label": "34/63", "node": 3662, "naklon": 6 }, +{ "label": "34/65", "node": 3665, "naklon": 6 }, +{ "label": "34/66", "node": 3667, "naklon": 6 }, +{ "label": "34/67", "node": 3675, "naklon": 6 }, +{ "label": "34/68", "node": 3666, "naklon": 6 }, +{ "label": "34/69", "node": 3652, "naklon": 6 }, +{ "label": "34/70", "node": 3458, "naklon": 6 }, +{ "label": "34/70/1", "node": 4425, "naklon": 6 }, +{ "label": "34/71", "node": 3459, "naklon": 6 }, +{ "label": "34/72", "node": 3435, "naklon": 6 }, +{ "label": "34/73", "node": 3448, "naklon": 6 }, +{ "label": "34/74", "node": 3451, "naklon": 6 }, +{ "label": "34/75", "node": 3442, "naklon": 6 }, +{ "label": "34/76", "node": 3449, "naklon": 6 }, +{ "label": "34/77", "node": 3450, "naklon": 6 }, +{ "label": "34/78", "node": 3433, "naklon": 6 }, +{ "label": "34/80", "node": 3432, "naklon": 12 }, +{ "label": "34/81", "node": 3470, "naklon": 12 }, +{ "label": "34/82", "node": 3438, "naklon": 12 }, +{ "label": "34/83", "node": 3439, "naklon": 12 }, +{ "label": "34/84", "node": 4028, "naklon": 5 }, +{ "label": "34/85", "node": 3596, "naklon": 5 }, +{ "label": "34/86", "node": 4021, "naklon": 5 }, +{ "label": "34/87", "node": 3437, "naklon": 12 }, +{ "label": "34/88", "node": 3428, "naklon": 12 }, +{ "label": "34/89", "node": 3430, "naklon": 12 }, +{ "label": "34/91", "node": 3454, "naklon": 6 }, +{ "label": "34/92", "node": 3492, "naklon": 6 }, +{ "label": "34/93", "node": 3462, "naklon": 6 }, +{ "label": "34/94", "node": 3427, "naklon": 6 }, +{ "label": "34/95", "node": 3434, "naklon": 6 }, +{ "label": "34/96", "node": 3456, "naklon": 6 }, +{ "label": "34/98/1", "node": 4307, "naklon": 6 }, +{ "label": "35/1", "node": 3968, "naklon": 0 }, +{ "label": "35/2", "node": 3969, "naklon": 0 }, +{ "label": "35/3", "node": 3947, "naklon": 0 }, +{ "label": "35/4", "node": 3979, "naklon": 0 }, +{ "label": "35/5", "node": 3959, "naklon": 0 }, +{ "label": "35/6", "node": 3948, "naklon": 0 }, +{ "label": "35/7", "node": 3961, "naklon": 0 }, +{ "label": "35/8", "node": 3956, "naklon": 0 }, +{ "label": "35/9", "node": 3604, "naklon": 0 }, +{ "label": "35/10", "node": 3944, "naklon": 0 }, +{ "label": "35/11", "node": 3960, "naklon": 0 }, +{ "label": "35/12", "node": 3958, "naklon": 0 }, +{ "label": "35/13", "node": 4036, "naklon": 5 }, +{ "label": "35/18", "node": 3893, "naklon": 5 }, +{ "label": "35/19", "node": 4108, "naklon": 5 }, +{ "label": "35/20", "node": 4017, "naklon": 5 }, +{ "label": "35/21", "node": 3963, "naklon": 0 }, +{ "label": "35/22", "node": 3658, "naklon": 0 }, +{ "label": "35/23", "node": 3975, "naklon": 0 }, +{ "label": "35/24", "node": 3980, "naklon": 0 }, +{ "label": "35/25", "node": 4012, "naklon": 0 }, +{ "label": "35/26", "node": 3655, "naklon": 0 }, +{ "label": "35/27", "node": 3962, "naklon": 0 }, +{ "label": "35/28", "node": 3945, "naklon": 0 }, +{ "label": "35/29", "node": 3569, "naklon": 0 }, +{ "label": "35/30", "node": 3429, "naklon": 0 }, +{ "label": "35/31", "node": 3657, "naklon": 0 }, +{ "label": "35/32", "node": 3646, "naklon": 0 }, +{ "label": "35/33", "node": 3622, "naklon": 0 }, +{ "label": "35/34", "node": 3612, "naklon": 0 }, +{ "label": "35/35", "node": 3955, "naklon": 0 }, +{ "label": "35/37", "node": 3878, "naklon": 0 }, +{ "label": "35/38", "node": 3965, "naklon": 0 }, +{ "label": "35/39", "node": 3970, "naklon": 0 }, +{ "label": "35/40", "node": 3611, "naklon": 0 }, +{ "label": "35/41", "node": 2635, "naklon": 0 }, +{ "label": "35/42", "node": 3978, "naklon": 0 }, +{ "label": "35/43", "node": 4213, "naklon": 0 }, +{ "label": "35/44", "node": 3984, "naklon": 0 }, +{ "label": "35/45", "node": 4218, "naklon": 0 }, +{ "label": "35/46", "node": 3973, "naklon": 0 }, +{ "label": "35/47", "node": 3974, "naklon": 0 }, +{ "label": "35/48", "node": 3759, "naklon": 0 }, +{ "label": "35/49", "node": 3844, "naklon": 0 }, +{ "label": "35/50", "node": 3804, "naklon": 0 }, +{ "label": "35/51", "node": 3831, "naklon": 0 }, +{ "label": "35/52", "node": 3643, "naklon": 0 }, +{ "label": "35/53", "node": 3966, "naklon": 0 }, +{ "label": "35/54", "node": 3971, "naklon": 0 }, +{ "label": "35/55", "node": 3650, "naklon": 6 }, +{ "label": "35/56", "node": 3651, "naklon": 6 }, +{ "label": "35/57", "node": 3669, "naklon": 6 }, +{ "label": "35/58", "node": 3648, "naklon": 6 }, +{ "label": "35/59", "node": 3645, "naklon": 6 }, +{ "label": "35/60", "node": 3659, "naklon": 6 }, +{ "label": "35/61", "node": 3647, "naklon": 6 }, +{ "label": "35/62", "node": 3644, "naklon": 6 }, +{ "label": "35/63", "node": 3671, "naklon": 6 }, +{ "label": "35/64", "node": 3682, "naklon": 6 }, +{ "label": "35/65", "node": 3672, "naklon": 6 }, +{ "label": "35/66", "node": 3683, "naklon": 6 }, +{ "label": "35/67", "node": 3673, "naklon": 6 }, +{ "label": "35/68", "node": 3674, "naklon": 6 }, +{ "label": "35/69", "node": 3679, "naklon": 6 }, +{ "label": "35/70", "node": 3649, "naklon": 6 }, +{ "label": "35/71", "node": 3687, "naklon": 6 }, +{ "label": "35/72", "node": 3677, "naklon": 6 }, +{ "label": "35/73", "node": 3690, "naklon": 6 }, +{ "label": "35/74", "node": 3691, "naklon": 6 }, +{ "label": "35/75", "node": 3676, "naklon": 6 }, +{ "label": "35/76", "node": 3680, "naklon": 6 }, +{ "label": "35/77", "node": 3668, "naklon": 6 }, +{ "label": "35/78", "node": 3681, "naklon": 6 }, +{ "label": "35/79", "node": 3670, "naklon": 6 }, +{ "label": "35/80", "node": 3689, "naklon": 6 }, +{ "label": "35/81", "node": 3678, "naklon": 6 }, +{ "label": "35/82", "node": 3693, "naklon": 6 }, +{ "label": "35/83", "node": 3654, "naklon": null }, +{ "label": "36/1", "node": 4086, "naklon": 0 }, +{ "label": "36/2", "node": 4085, "naklon": 0 }, +{ "label": "36/3", "node": 4083, "naklon": 0 }, +{ "label": "36/4", "node": 4087, "naklon": 0 }, +{ "label": "36/5", "node": 4077, "naklon": 0 }, +{ "label": "36/6", "node": 4082, "naklon": 0 }, +{ "label": "36/7", "node": 4186, "naklon": 0 }, +{ "label": "36/8", "node": 4206, "naklon": 0 }, +{ "label": "36/9", "node": 4080, "naklon": 0 }, +{ "label": "36/10", "node": 4081, "naklon": 0 }, +{ "label": "36/11", "node": 4210, "naklon": 0 }, +{ "label": "36/12", "node": 4079, "naklon": 0 }, +{ "label": "36/13", "node": 4076, "naklon": 0 }, +{ "label": "36/14", "node": 3852, "naklon": 0 }, +{ "label": "36/15", "node": 2813, "naklon": 0 }, +{ "label": "36/16", "node": 4219, "naklon": 0 }, +{ "label": "37/1A", "node": 3104, "naklon": 15 }, +{ "label": "37/1B", "node": 3121, "naklon": 15 }, +{ "label": "37/2", "node": 3113, "naklon": 10 }, +{ "label": "37/3", "node": 3118, "naklon": 10 }, +{ "label": "37/4", "node": 3111, "naklon": 10 }, +{ "label": "37/5", "node": 4020, "naklon": 10 }, +{ "label": "37/6", "node": 3119, "naklon": 10 }, +{ "label": "37/7", "node": 3110, "naklon": 10 }, +{ "label": "37/8", "node": 3108, "naklon": 10 }, +{ "label": "37/12", "node": 3107, "naklon": 0 }, +{ "label": "37/13", "node": 3199, "naklon": 0 }, +{ "label": "37/14", "node": 3120, "naklon": 0 }, +{ "label": "37/15", "node": 3122, "naklon": 0 }, +{ "label": "37/16", "node": 3908, "naklon": 0 }, +{ "label": "37/17", "node": 3114, "naklon": 0 }, +{ "label": "37/18", "node": 3105, "naklon": 0 }, +{ "label": "37/19", "node": 3116, "naklon": 0 }, +{ "label": "37/20", "node": 3106, "naklon": 0 }, +{ "label": "37/21", "node": 2887, "naklon": 5 }, +{ "label": "37/22", "node": 2888, "naklon": 5 }, +{ "label": "37/23", "node": 2877, "naklon": 5 }, +{ "label": "37/24", "node": 2891, "naklon": 5 }, +{ "label": "37/25", "node": 2886, "naklon": 5 }, +{ "label": "37/26", "node": 2892, "naklon": 5 }, +{ "label": "37/27", "node": 2882, "naklon": 5 }, +{ "label": "37/28", "node": 2883, "naklon": 5 }, +{ "label": "37/29", "node": 2876, "naklon": 5 }, +{ "label": "37/30", "node": 3109, "naklon": 5 }, +{ "label": "37/31", "node": 4152, "naklon": 5 }, +{ "label": "37/32", "node": 3117, "naklon": 5 }, +{ "label": "37/33", "node": 2870, "naklon": 5 }, +{ "label": "37/34", "node": 2867, "naklon": 0 }, +{ "label": "37/35", "node": 2865, "naklon": 0 }, +{ "label": "37/36", "node": 3096, "naklon": 0 }, +{ "label": "37/37", "node": 2871, "naklon": 0 }, +{ "label": "37/38", "node": 2884, "naklon": 0 }, +{ "label": "37/39", "node": 2855, "naklon": 0 }, +{ "label": "37/40", "node": 2878, "naklon": 0 }, +{ "label": "37/41", "node": 2889, "naklon": 0 }, +{ "label": "37/42", "node": 2879, "naklon": 0 }, +{ "label": "37/43", "node": 2850, "naklon": 0 }, +{ "label": "37/44", "node": 2894, "naklon": 0 }, +{ "label": "37/45", "node": 2880, "naklon": 0 }, +{ "label": "37/46", "node": 2893, "naklon": 0 }, +{ "label": "37/47", "node": 2890, "naklon": 0 }, +{ "label": "37/48", "node": 4355, "naklon": 0 }, +{ "label": "37/49", "node": 2885, "naklon": 0 }, +{ "label": "37/50", "node": 2875, "naklon": 0 }, +{ "label": "38/30A", "node": 3486, "naklon": 5 }, +{ "label": "38/30B", "node": 3714, "naklon": 0 }, +{ "label": "38/32A", "node": 3483, "naklon": 5 }, +{ "label": "38/32B", "node": 3496, "naklon": 0 }, +{ "label": "38/35A", "node": 3487, "naklon": 5 }, +{ "label": "38/35B", "node": 3498, "naklon": 5 }, +{ "label": "38/38A", "node": 3578, "naklon": 5 }, +{ "label": "38/38B", "node": 3508, "naklon": 5 }, +{ "label": "38/59A", "node": 3787, "naklon": 5 }, +{ "label": "38/59B", "node": 3491, "naklon": 5 }, +{ "label": "38/1", "node": 3568, "naklon": null }, +{ "label": "38/2", "node": 3502, "naklon": 0 }, +{ "label": "38/3", "node": 3836, "naklon": 0 }, +{ "label": "38/4", "node": 3588, "naklon": 0 }, +{ "label": "38/5", "node": 3493, "naklon": 0 }, +{ "label": "38/6", "node": 3580, "naklon": 0 }, +{ "label": "38/7", "node": 3572, "naklon": 0 }, +{ "label": "38/8", "node": 3506, "naklon": 0 }, +{ "label": "38/9", "node": 3503, "naklon": 0 }, +{ "label": "38/10", "node": 3579, "naklon": 0 }, +{ "label": "38/11", "node": 3586, "naklon": 0 }, +{ "label": "38/12", "node": 3495, "naklon": 5 }, +{ "label": "38/13", "node": 3492, "naklon": 5 }, +{ "label": "38/14", "node": 3532, "naklon": 5 }, +{ "label": "38/15", "node": 3574, "naklon": 5 }, +{ "label": "38/16", "node": 4140, "naklon": 5 }, +{ "label": "38/17", "node": 3795, "naklon": 5 }, +{ "label": "38/18", "node": 3788, "naklon": 5 }, +{ "label": "38/19", "node": 3796, "naklon": 5 }, +{ "label": "38/20", "node": 3797, "naklon": 5 }, +{ "label": "38/21", "node": 3798, "naklon": 5 }, +{ "label": "38/22", "node": 3786, "naklon": 5 }, +{ "label": "38/23", "node": 4067, "naklon": 5 }, +{ "label": "38/24", "node": 3773, "naklon": 5 }, +{ "label": "38/25", "node": 3774, "naklon": 5 }, +{ "label": "38/26", "node": 3789, "naklon": 5 }, +{ "label": "38/27", "node": 3520, "naklon": null }, +{ "label": "38/29", "node": 3577, "naklon": 5 }, +{ "label": "38/31", "node": 3530, "naklon": null }, +{ "label": "38/33", "node": 3488, "naklon": 5 }, +{ "label": "38/34", "node": 3505, "naklon": 5 }, +{ "label": "38/36", "node": 3497, "naklon": 5 }, +{ "label": "38/37", "node": 3490, "naklon": 5 }, +{ "label": "38/39", "node": 3585, "naklon": 5 }, +{ "label": "38/40", "node": 3582, "naklon": 5 }, +{ "label": "38/41", "node": 3507, "naklon": 5 }, +{ "label": "38/42", "node": 3484, "naklon": 5 }, +{ "label": "38/43", "node": 3501, "naklon": 5 }, +{ "label": "38/44", "node": 3581, "naklon": 5 }, +{ "label": "38/45", "node": 4192, "naklon": 5 }, +{ "label": "38/46", "node": 3576, "naklon": 5 }, +{ "label": "38/47", "node": 3489, "naklon": 5 }, +{ "label": "38/48", "node": 3573, "naklon": 5 }, +{ "label": "38/49", "node": 3504, "naklon": 5 }, +{ "label": "38/50", "node": 3794, "naklon": 5 }, +{ "label": "38/51", "node": 3485, "naklon": 5 }, +{ "label": "38/52", "node": 3482, "naklon": 5 }, +{ "label": "38/53", "node": 3575, "naklon": 5 }, +{ "label": "38/54", "node": 3499, "naklon": 5 }, +{ "label": "38/55", "node": 3494, "naklon": 5 }, +{ "label": "38/56", "node": 3583, "naklon": 5 }, +{ "label": "38/57", "node": 3570, "naklon": 5 }, +{ "label": "38/58", "node": 3500, "naklon": 0 }, +{ "label": "38/63", "node": 3510, "naklon": null }, +{ "label": "38/64", "node": 3512, "naklon": null }, +{ "label": "38/67", "node": 3535, "naklon": null }, +{ "label": "38/68", "node": 3531, "naklon": null }, +{ "label": "38/69", "node": 3537, "naklon": null }, +{ "label": "39/1", "node": 3522, "naklon": 10 }, +{ "label": "39/2", "node": 4018, "naklon": 10 }, +{ "label": "39/3", "node": 4019, "naklon": 10 }, +{ "label": "39/4", "node": 4154, "naklon": 5 }, +{ "label": "39/5", "node": 3907, "naklon": 5 }, +{ "label": "39/6", "node": 4148, "naklon": 0 }, +{ "label": "39/7", "node": 4153, "naklon": 0 }, +{ "label": "39/8", "node": 3938, "naklon": 0 }, +{ "label": "39/9", "node": 3802, "naklon": 0 }, +{ "label": "39/10", "node": 4015, "naklon": 0 }, +{ "label": "39/11", "node": 3929, "naklon": 0 }, +{ "label": "39/12", "node": 3946, "naklon": 0 }, +{ "label": "39/13", "node": 4014, "naklon": 0 }, +{ "label": "39/14", "node": 4155, "naklon": 0 }, +{ "label": "39/15", "node": 4149, "naklon": 0 }, +{ "label": "39/16", "node": 3642, "naklon": 0 }, +{ "label": "39/17", "node": 3636, "naklon": 5 }, +{ "label": "39/18", "node": 3991, "naklon": 0 }, +{ "label": "39/19", "node": 3994, "naklon": 0 }, +{ "label": "39/20", "node": 3990, "naklon": 0 }, +{ "label": "39/21", "node": 3967, "naklon": 0 }, +{ "label": "39/22", "node": 3977, "naklon": 0 }, +{ "label": "39/23", "node": 3757, "naklon": 15 }, +{ "label": "39/24", "node": 3633, "naklon": 15 }, +{ "label": "39/25", "node": 3744, "naklon": 15 }, +{ "label": "39/26", "node": 4023, "naklon": 5 }, +{ "label": "39/27", "node": 3720, "naklon": 5 }, +{ "label": "39/28", "node": 3734, "naklon": 5 }, +{ "label": "39/29", "node": 3741, "naklon": 5 }, +{ "label": "39/30", "node": 3721, "naklon": 5 }, +{ "label": "39/31", "node": 3845, "naklon": 0 }, +{ "label": "39/32", "node": 3840, "naklon": 0 }, +{ "label": "39/33", "node": 3837, "naklon": null }, +{ "label": "39/34", "node": 3839, "naklon": 0 }, +{ "label": "41/1", "node": 3542, "naklon": null }, +{ "label": "41/2", "node": 3566, "naklon": null }, +{ "label": "41/3", "node": 3548, "naklon": null }, +{ "label": "41/4", "node": 3515, "naklon": null }, +{ "label": "41/5", "node": 3559, "naklon": null }, +{ "label": "41/6", "node": 3509, "naklon": null }, +{ "label": "41/7", "node": 3524, "naklon": null }, +{ "label": "41/8", "node": 3518, "naklon": null }, +{ "label": "41/9", "node": 3182, "naklon": null }, +{ "label": "41/10", "node": 3187, "naklon": null }, +{ "label": "41/11", "node": 3195, "naklon": 0 }, +{ "label": "41/12", "node": 3857, "naklon": 0 }, +{ "label": "41/13", "node": 3183, "naklon": 0 }, +{ "label": "41/14", "node": 3177, "naklon": 0 }, +{ "label": "41/15", "node": 3189, "naklon": 0 }, +{ "label": "41/16", "node": 3186, "naklon": 0 }, +{ "label": "42/1", "node": 3178, "naklon": 0 }, +{ "label": "42/2", "node": 3219, "naklon": 0 }, +{ "label": "42/3", "node": 3475, "naklon": 0 }, +{ "label": "42/4", "node": 3175, "naklon": 0 }, +{ "label": "42/5", "node": 3222, "naklon": 0 }, +{ "label": "42/6", "node": 3221, "naklon": 0 }, +{ "label": "42/7", "node": 3181, "naklon": 0 }, +{ "label": "42/8", "node": 3180, "naklon": 0 }, +{ "label": "42/9", "node": 3218, "naklon": 0 }, +{ "label": "42/10", "node": 3176, "naklon": 0 }, +{ "label": "42/11", "node": 3174, "naklon": 0 }, +{ "label": "42/12", "node": 3220, "naklon": 0 }, +{ "label": "42/13", "node": 3533, "naklon": null }, +{ "label": "42/14", "node": 3543, "naklon": null }, +{ "label": "42/15", "node": 3554, "naklon": null }, +{ "label": "42/16", "node": 3549, "naklon": null }, +{ "label": "43/1", "node": 2857, "naklon": 5 }, +{ "label": "43/2", "node": 2752, "naklon": 5 }, +{ "label": "43/3", "node": 2753, "naklon": 5 }, +{ "label": "43/4", "node": 3024, "naklon": 5 }, +{ "label": "43/5", "node": 2754, "naklon": 5 }, +{ "label": "43/6", "node": 4423, "naklon": 5 }, +{ "label": "43/7", "node": 4368, "naklon": 5 }, +{ "label": "43/8", "node": 2978, "naklon": 5 }, +{ "label": "43/9", "node": 2868, "naklon": 5 }, +{ "label": "43/10", "node": 4377, "naklon": 5 }, +{ "label": "43/11", "node": 2757, "naklon": 5 }, +{ "label": "43/12", "node": 2970, "naklon": 5 }, +{ "label": "43/13", "node": 2758, "naklon": 5 }, +{ "label": "43/14", "node": 4378, "naklon": 5 }, +{ "label": "43/15", "node": 2759, "naklon": 5 }, +{ "label": "43/16", "node": 4342, "naklon": 5 }, +{ "label": "43/17", "node": 3026, "naklon": null }, +{ "label": "43/18", "node": 2986, "naklon": null }, +{ "label": "43/19", "node": 4343, "naklon": null }, +{ "label": "43/20", "node": 2760, "naklon": null }, +{ "label": "43/21", "node": 4379, "naklon": null }, +{ "label": "43/22", "node": 2971, "naklon": null }, +{ "label": "43/23", "node": 2761, "naklon": null }, +{ "label": "43/24", "node": 2762, "naklon": null }, +{ "label": "43/25", "node": 4339, "naklon": null }, +{ "label": "43/26", "node": 4380, "naklon": null }, +{ "label": "43/27", "node": 2975, "naklon": null }, +{ "label": "43/28", "node": 3003, "naklon": null }, +{ "label": "43/29", "node": 4338, "naklon": null }, +{ "label": "43/30", "node": 3002, "naklon": null }, +{ "label": "43/31", "node": 4345, "naklon": null }, +{ "label": "43/32", "node": 2979, "naklon": null }, +{ "label": "43/33", "node": 2989, "naklon": null }, +{ "label": "43/34", "node": 2996, "naklon": null }, +{ "label": "43/35", "node": 2972, "naklon": null }, +{ "label": "43/36", "node": 2988, "naklon": null }, +{ "label": "43/37", "node": 4344, "naklon": null }, +{ "label": "43/38", "node": 3022, "naklon": null }, +{ "label": "43/39", "node": 4341, "naklon": null }, +{ "label": "43/40", "node": 2983, "naklon": null }, +{ "label": "43/41", "node": 2995, "naklon": null }, +{ "label": "43/42", "node": 2763, "naklon": null }, +{ "label": "43/43", "node": 2764, "naklon": null }, +{ "label": "43/44", "node": 2765, "naklon": null }, +{ "label": "43/45", "node": 2766, "naklon": null }, +{ "label": "43/46", "node": 2767, "naklon": null }, +{ "label": "43/47", "node": 2768, "naklon": null }, +{ "label": "43/48", "node": 3018, "naklon": null }, +{ "label": "43/49", "node": 2982, "naklon": null }, +{ "label": "43/50", "node": 3019, "naklon": 0 }, +{ "label": "43/51", "node": 3013, "naklon": null }, +{ "label": "43/52", "node": 3007, "naklon": null }, +{ "label": "43/53", "node": 2980, "naklon": null }, +{ "label": "43/54", "node": 3011, "naklon": null }, +{ "label": "43/55", "node": 2672, "naklon": null }, +{ "label": "43/56", "node": 2673, "naklon": null }, +{ "label": "43/57", "node": 2674, "naklon": null }, +{ "label": "43/58", "node": 2675, "naklon": null }, +{ "label": "43/59", "node": 2676, "naklon": null }, +{ "label": "43/60", "node": 2677, "naklon": null }, +{ "label": "43/61", "node": 2678, "naklon": null }, +{ "label": "43/62", "node": 2679, "naklon": null }, +{ "label": "43/63", "node": 2680, "naklon": null }, +{ "label": "43/64", "node": 2840, "naklon": null }, +{ "label": "43/65", "node": 2682, "naklon": null }, +{ "label": "43/66", "node": 2683, "naklon": null }, +{ "label": "43/67", "node": 2684, "naklon": 0 }, +{ "label": "43/68", "node": 2685, "naklon": null }, +{ "label": "43/69", "node": 2686, "naklon": null }, +{ "label": "43/70", "node": 2687, "naklon": null }, +{ "label": "43/71", "node": 2688, "naklon": null }, +{ "label": "43/72", "node": 2689, "naklon": null }, +{ "label": "43/73", "node": 2690, "naklon": null }, +{ "label": "43/74", "node": 2691, "naklon": null }, +{ "label": "43/75", "node": 2692, "naklon": null }, +{ "label": "43/76", "node": 2693, "naklon": 0 }, +{ "label": "43/77", "node": 2694, "naklon": null }, +{ "label": "43/78", "node": 2695, "naklon": null }, +{ "label": "43/79", "node": 2696, "naklon": 0 }, +{ "label": "43/80", "node": 2697, "naklon": null }, +{ "label": "43/81", "node": 2698, "naklon": 0 }, +{ "label": "43/82", "node": 2699, "naklon": null }, +{ "label": "43/83", "node": 2700, "naklon": 0 }, +{ "label": "43/84", "node": 2744, "naklon": null }, +{ "label": "43/85", "node": 2745, "naklon": 0 }, +{ "label": "43/86", "node": 2746, "naklon": null }, +{ "label": "43/87", "node": 2747, "naklon": 0 }, +{ "label": "43/88", "node": 2748, "naklon": null }, +{ "label": "43/89", "node": 2749, "naklon": 0 }, +{ "label": "43/90", "node": 2841, "naklon": null }, +{ "label": "45/1", "node": 4237, "naklon": 5 }, +{ "label": "45/2", "node": 4226, "naklon": 5 }, +{ "label": "45/3", "node": 4242, "naklon": 5 }, +{ "label": "45/4", "node": 4179, "naklon": 5 }, +{ "label": "45/5", "node": 4247, "naklon": 5 }, +{ "label": "45/6", "node": 4245, "naklon": 5 }, +{ "label": "45/7", "node": 3872, "naklon": 5 }, +{ "label": "45/8", "node": 4175, "naklon": 5 }, +{ "label": "45/9", "node": 4236, "naklon": 5 }, +{ "label": "45/10", "node": 4170, "naklon": 5 }, +{ "label": "45/11", "node": 4238, "naklon": 5 }, +{ "label": "45/12", "node": 4246, "naklon": 5 }, +{ "label": "45/13", "node": 4166, "naklon": 5 }, +{ "label": "45/14", "node": 4227, "naklon": 5 }, +{ "label": "45/15", "node": 4171, "naklon": 5 }, +{ "label": "45/16", "node": 4180, "naklon": 5 }, +{ "label": "45/17", "node": 4244, "naklon": 5 }, +{ "label": "45/18", "node": 4199, "naklon": 5 }, +{ "label": "45/19", "node": 4239, "naklon": 5 }, +{ "label": "45/20", "node": 4207, "naklon": 5 }, +{ "label": "45/21", "node": 4223, "naklon": 5 }, +{ "label": "45/22", "node": 4230, "naklon": 5 }, +{ "label": "45/23", "node": 4233, "naklon": 5 }, +{ "label": "45/24", "node": 4222, "naklon": 5 }, +{ "label": "45/25", "node": 4217, "naklon": 5 }, +{ "label": "45/26", "node": 4243, "naklon": 5 }, +{ "label": "45/27", "node": 4200, "naklon": 5 }, +{ "label": "45/28", "node": 4228, "naklon": 5 }, +{ "label": "45/29", "node": 4211, "naklon": 5 }, +{ "label": "45/30", "node": 4234, "naklon": 5 }, +{ "label": "45/31", "node": 4235, "naklon": 5 }, +{ "label": "45/32", "node": 4203, "naklon": 5 }, +{ "label": "45/33", "node": 4240, "naklon": 5 }, +{ "label": "45/34", "node": 4224, "naklon": 5 }, +{ "label": "45/35", "node": 4232, "naklon": 5 }, +{ "label": "45/36", "node": 4231, "naklon": 5 }, +{ "label": "45/37", "node": 4161, "naklon": 5 }, +{ "label": "45/38", "node": 4225, "naklon": 5 }, +{ "label": "45/39", "node": 4241, "naklon": 5 }, +{ "label": "45/40", "node": 4229, "naklon": 5 }, +{ "label": "45/41", "node": 4221, "naklon": 5 }, +{ "label": "45/42", "node": 4212, "naklon": 5 }, +{ "label": "45/43", "node": 4216, "naklon": 5 }, +{ "label": "45/44", "node": 3864, "naklon": null }, +{ "label": "46/1", "node": 3806, "naklon": 5 }, +{ "label": "46/2", "node": 3813, "naklon": 5 }, +{ "label": "46/3", "node": 3815, "naklon": 5 }, +{ "label": "46/4", "node": 3807, "naklon": 5 }, +{ "label": "46/5", "node": 3895, "naklon": 5 }, +{ "label": "46/6", "node": 3809, "naklon": 5 }, +{ "label": "46/7", "node": 3820, "naklon": 5 }, +{ "label": "46/8", "node": 3805, "naklon": 5 }, +{ "label": "46/9", "node": 3894, "naklon": 0 }, +{ "label": "46/10", "node": 4055, "naklon": 0 }, +{ "label": "46/11", "node": 3812, "naklon": 5 }, +{ "label": "46/12", "node": 3822, "naklon": 5 }, +{ "label": "46/13", "node": 3821, "naklon": 5 }, +{ "label": "46/14", "node": 3808, "naklon": 5 }, +{ "label": "46/15", "node": 3799, "naklon": 5 }, +{ "label": "46/16", "node": 3816, "naklon": 5 }, +{ "label": "46/17", "node": 3751, "naklon": 5 }, +{ "label": "46/18", "node": 3814, "naklon": 5 }, +{ "label": "46/19", "node": 4044, "naklon": 0 }, +{ "label": "46/20", "node": 3931, "naklon": 0 }, +{ "label": "46/21", "node": 3902, "naklon": 5 }, +{ "label": "46/22", "node": 3916, "naklon": 5 }, +{ "label": "46/23", "node": 3892, "naklon": 5 }, +{ "label": "46/24", "node": 3914, "naklon": 5 }, +{ "label": "46/25", "node": 3898, "naklon": 5 }, +{ "label": "46/26", "node": 3897, "naklon": 5 }, +{ "label": "46/27", "node": 3885, "naklon": 5 }, +{ "label": "46/28", "node": 3906, "naklon": 5 }, +{ "label": "46/29", "node": 3930, "naklon": 0 }, +{ "label": "46/30", "node": 3936, "naklon": 0 }, +{ "label": "46/31", "node": 3860, "naklon": 5 }, +{ "label": "46/32", "node": 3841, "naklon": 5 }, +{ "label": "46/33", "node": 3873, "naklon": 5 }, +{ "label": "46/34", "node": 3854, "naklon": 5 }, +{ "label": "46/35", "node": 3939, "naklon": 5 }, +{ "label": "46/36", "node": 3858, "naklon": 5 }, +{ "label": "46/37", "node": 3940, "naklon": 5 }, +{ "label": "46/38", "node": 4035, "naklon": 5 }, +{ "label": "47/1", "node": 3373, "naklon": 0 }, +{ "label": "47/2", "node": 3374, "naklon": 0 }, +{ "label": "47/3", "node": 3384, "naklon": 0 }, +{ "label": "47/4", "node": 3385, "naklon": 0 }, +{ "label": "48/1", "node": 4051, "naklon": 5 }, +{ "label": "48/2", "node": 4041, "naklon": 5 }, +{ "label": "48/3", "node": 4056, "naklon": 5 }, +{ "label": "48/4", "node": 3875, "naklon": 5 }, +{ "label": "48/5", "node": 4061, "naklon": 5 }, +{ "label": "48/6", "node": 4047, "naklon": 5 }, +{ "label": "48/7", "node": 4060, "naklon": 5 }, +{ "label": "48/8", "node": 4059, "naklon": 5 }, +{ "label": "48/9", "node": 4058, "naklon": 5 }, +{ "label": "48/10", "node": 3635, "naklon": 5 }, +{ "label": "48/11", "node": 3640, "naklon": 5 }, +{ "label": "48/12", "node": 3747, "naklon": 5 }, +{ "label": "48/13", "node": 3629, "naklon": 5 }, +{ "label": "48/14", "node": 4048, "naklon": 5 }, +{ "label": "48/15", "node": 4063, "naklon": 5 }, +{ "label": "48/16", "node": 4062, "naklon": 5 }, +{ "label": "48/17", "node": 4043, "naklon": 5 }, +{ "label": "48/18", "node": 4052, "naklon": 5 }, +{ "label": "48/19", "node": 4042, "naklon": 5 }, +{ "label": "48/20", "node": 4053, "naklon": 5 }, +{ "label": "50/15A", "node": 4167, "naklon": null }, +{ "label": "50/15B", "node": 4159, "naklon": null }, +{ "label": "50/1", "node": 4183, "naklon": 0 }, +{ "label": "50/2", "node": 4157, "naklon": 0 }, +{ "label": "50/3", "node": 4160, "naklon": 0 }, +{ "label": "50/4", "node": 4173, "naklon": 0 }, +{ "label": "50/5", "node": 4177, "naklon": 0 }, +{ "label": "50/6", "node": 4174, "naklon": 0 }, +{ "label": "50/7", "node": 4178, "naklon": 0 }, +{ "label": "50/8", "node": 4195, "naklon": 0 }, +{ "label": "50/9", "node": 4169, "naklon": 0 }, +{ "label": "50/10", "node": 4162, "naklon": 0 }, +{ "label": "50/11", "node": 4158, "naklon": 0 }, +{ "label": "50/12", "node": 4182, "naklon": 0 }, +{ "label": "50/13", "node": 4194, "naklon": 0 }, +{ "label": "50/14", "node": 4184, "naklon": 0 }, +{ "label": "50/16", "node": 4197, "naklon": null }, +{ "label": "50/17", "node": 4164, "naklon": null }, +{ "label": "50/18", "node": 3306, "naklon": null }, +{ "label": "50/19", "node": 4168, "naklon": null }, +{ "label": "50/20", "node": 4193, "naklon": null }, +{ "label": "50/21", "node": 4187, "naklon": null }, +{ "label": "50/22", "node": 4163, "naklon": null }, +{ "label": "50/23", "node": 4165, "naklon": null }, +{ "label": "50/24", "node": 4185, "naklon": null }, +{ "label": "50/25", "node": 3904, "naklon": null }, +{ "label": "53/1", "node": 2619, "naklon": 0 }, +{ "label": "53/2", "node": 2623, "naklon": 0 }, +{ "label": "53/3", "node": 2617, "naklon": 0 }, +{ "label": "53/4", "node": 2622, "naklon": 0 }, +{ "label": "53/5", "node": 2618, "naklon": 0 }, +{ "label": "53/6", "node": 2626, "naklon": 0 }, +{ "label": "53/7", "node": 2869, "naklon": 0 }, +{ "label": "53/8", "node": 2613, "naklon": 0 }, +{ "label": "53/9", "node": 2608, "naklon": 0 }, +{ "label": "53/10", "node": 2611, "naklon": 0 }, +{ "label": "53/11", "node": 2598, "naklon": 0 }, +{ "label": "53/12", "node": 3528, "naklon": 0 }, +{ "label": "53/13", "node": 3545, "naklon": 0 }, +{ "label": "53/14", "node": 2620, "naklon": 0 }, +{ "label": "53/15", "node": 2612, "naklon": 0 }, +{ "label": "53/16", "node": 2615, "naklon": 0 }, +{ "label": "53/17", "node": 3722, "naklon": 0 }, +{ "label": "53/18", "node": 2624, "naklon": 0 }, +{ "label": "53/19", "node": 2609, "naklon": 0 }, +{ "label": "53/20", "node": 2625, "naklon": 0 }, +{ "label": "53/21", "node": 2602, "naklon": 0 }, +{ "label": "53/22", "node": 2610, "naklon": 0 }, +{ "label": "53/23", "node": 2599, "naklon": 0 }, +{ "label": "53/24", "node": 2605, "naklon": 0 }, +{ "label": "53/25", "node": 2593, "naklon": 0 }, +{ "label": "53/26", "node": 3074, "naklon": 0 }, +{ "label": "53/27", "node": 2740, "naklon": 0 }, +{ "label": "53/28", "node": 2614, "naklon": 0 }, +{ "label": "53/29", "node": 2601, "naklon": 0 }, +{ "label": "53/30", "node": 4196, "naklon": 0 }, +{ "label": "53/31", "node": 2607, "naklon": 0 }, +{ "label": "53/32", "node": 2582, "naklon": 0 }, +{ "label": "53/33", "node": 2594, "naklon": 0 }, +{ "label": "53/34", "node": 2589, "naklon": 0 }, +{ "label": "53/35", "node": 2596, "naklon": 0 }, +{ "label": "53/36", "node": 2603, "naklon": 0 }, +{ "label": "53/37", "node": 2597, "naklon": 0 }, +{ "label": "53/38", "node": 2590, "naklon": 0 }, +{ "label": "53/39", "node": 2581, "naklon": 0 }, +{ "label": "53/40", "node": 2583, "naklon": 0 }, +{ "label": "53/41", "node": 2580, "naklon": 0 }, +{ "label": "53/42", "node": 2579, "naklon": 0 }, +{ "label": "53/43", "node": 2797, "naklon": 0 }, +{ "label": "53/44", "node": 2577, "naklon": 0 }, +{ "label": "53/45", "node": 2586, "naklon": 0 }, +{ "label": "53/46", "node": 2588, "naklon": 0 }, +{ "label": "53/47", "node": 2591, "naklon": 0 }, +{ "label": "53/48", "node": 2592, "naklon": 0 }, +{ "label": "53/49", "node": 2573, "naklon": 0 }, +{ "label": "53/50", "node": 2595, "naklon": 0 }, +{ "label": "53/51", "node": 2587, "naklon": 0 }, +{ "label": "53/52", "node": 2578, "naklon": 0 }, +{ "label": "53/53", "node": 2574, "naklon": 0 }, +{ "label": "53/54", "node": 2571, "naklon": 0 }, +{ "label": "53/55", "node": 2570, "naklon": 0 }, +{ "label": "53/56", "node": 2576, "naklon": 0 }, +{ "label": "53/57", "node": 2881, "naklon": 0 }, +{ "label": "53/58", "node": 2575, "naklon": 0 }, +{ "label": "53/59", "node": 2572, "naklon": 0 }, +{ "label": "53/60", "node": 2569, "naklon": 0 }, +{ "label": "55/1", "node": 4324, "naklon": 0 }, +{ "label": "55/2", "node": 4319, "naklon": 0 }, +{ "label": "55/3", "node": 4327, "naklon": 0 }, +{ "label": "55/4", "node": 4333, "naklon": 0 }, +{ "label": "55/5", "node": 4332, "naklon": 0 }, +{ "label": "55/6", "node": 4320, "naklon": 0 }, +{ "label": "55/7", "node": 4317, "naklon": 0 }, +{ "label": "55/8", "node": 4318, "naklon": 0 }, +{ "label": "55/9", "node": 4328, "naklon": 0 }, +{ "label": "55/10", "node": 4323, "naklon": 0 }, +{ "label": "55/11", "node": 4325, "naklon": 0 }, +{ "label": "55/12", "node": 4326, "naklon": 0 }, +{ "label": "55/13", "node": 4316, "naklon": 0 }, +{ "label": "55/14", "node": 4322, "naklon": 0 }, +{ "label": "55/15", "node": 4331, "naklon": 0 }, +{ "label": "55/16", "node": 4321, "naklon": 0 }, +{ "label": "55/17", "node": 4315, "naklon": 0 }, +{ "label": "55/18", "node": 4329, "naklon": 0 }, +{ "label": "55/19", "node": 4334, "naklon": 0 }, +{ "label": "55/20", "node": 4330, "naklon": 0 } +]; + +module.exports = { naklony }; diff --git a/RVO33/databases/modbus_config.js b/RVO33/databases/modbus_config.js new file mode 100755 index 0000000..b73116a --- /dev/null +++ b/RVO33/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/RVO33/databases/nodes.table b/RVO33/databases/nodes.table new file mode 100755 index 0000000..3638ca4 --- /dev/null +++ b/RVO33/databases/nodes.table @@ -0,0 +1,10 @@ +node:number|pole_number:string|node_type:string|tbname:string|line:number|profile:string|processed:boolean|status:boolean|time_of_last_communication:number ++|3942|8|NEMA|apKVJBwOyrP35m2lv7KYjM0YXbeWNd64En9GxRqg|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760574186624|............. ++|3879|5|NEMA|zrR51V2ajQ9ZLygPKkEMXykYDq38xOJolENBXGnv|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760574182934|............. ++|3943|2|NEMA|zdQO8GwxDqjRgP4137YV6WANyKlpem2nL65rvVJY|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760574188909|............. ++|3887|6|NEMA|BaY3Xpy1EbKGjLq2O7magg7rx8owgQz9P4dDJRmN|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760574183445|............. ++|3982|4|NEMA|5dBNwRp9graYJxZn409NayklVov1b2QLPDqGm6XK|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760574189628|............. ++|3903|3|NEMA|WlVJBygjDZMeKX3vnAMRdo08NqdmG2x1Y69LQ4P5|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760574187423|............. ++|3920|7|NEMA|DbQY6zyveZRwK5drV0Z8P57joE4XJM83N9xl2nWq|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760574184963|............. ++|3829|9|NEMA|eod9aRWLVl34Gx1Dn7Vo3DA2rz6qjgmpEXwQJN5Z|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760574180249|............. ++|3846|1|NEMA|gYbDLqlyZVoRerQpB72M5bkWJnwM5z24POKa8Exj|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760574186912|............. diff --git a/RVO33/databases/nodes_original/nodes_original.table b/RVO33/databases/nodes_original/nodes_original.table new file mode 100755 index 0000000..fcbd11c --- /dev/null +++ b/RVO33/databases/nodes_original/nodes_original.table @@ -0,0 +1 @@ +[{"3942": "apKVJBwOyrP35m2lv7KYjM0YXbeWNd64En9GxRqg"}, {"3879": "zrR51V2ajQ9ZLygPKkEMXykYDq38xOJolENBXGnv"}, {"3943": "zdQO8GwxDqjRgP4137YV6WANyKlpem2nL65rvVJY"}, {"3887": "BaY3Xpy1EbKGjLq2O7magg7rx8owgQz9P4dDJRmN"}, {"3982": "5dBNwRp9graYJxZn409NayklVov1b2QLPDqGm6XK"}, {"3903": "WlVJBygjDZMeKX3vnAMRdo08NqdmG2x1Y69LQ4P5"}, {"3920": "DbQY6zyveZRwK5drV0Z8P57joE4XJM83N9xl2nWq"}, {"3829": "eod9aRWLVl34Gx1Dn7Vo3DA2rz6qjgmpEXwQJN5Z"}, {"3846": "gYbDLqlyZVoRerQpB72M5bkWJnwM5z24POKa8Exj"}] \ No newline at end of file diff --git a/RVO33/databases/notifications.table b/RVO33/databases/notifications.table new file mode 100755 index 0000000..f7c96cb --- /dev/null +++ b/RVO33/databases/notifications.table @@ -0,0 +1,41 @@ +key:string|weight:string|sk:string|en:string ++|switching_profile_point_applied_to_line|INFORMATIONAL|Aplikovaný bod spínacieho profilu na línií č. ${line} : ${value}|Switching profile point applied to line no. ${line} : ${value}|............... ++|dusk_has_occured|INFORMATIONAL|Nastal súmrak: ${value}|Dusk has occured: ${value}|............... ++|dawn_has_occured|INFORMATIONAL|Nastal úsvit: ${value}|Dawn has occured: ${value}|............... ++|dimming_profile_was_successfully_received_by_node|NOTICE|Stmievací profil bol úspešne prijatý nodom č. ${node}|Dimming profile was successfully received by node no. ${node}|............... ++|master_node_is_responding_again|NOTICE|Master node začal znovu odpovedať|Master node is responding again|............... ++|command_was_sent_from_terminal_interface|DEBUG|Z terminálu bol odoslaný príkaz|A command was sent from terminal interface|............... ++|master_node_is_not_responding|ALERT|Master node neodpovedá|Master node is not responding|............... ++|configuration_of_dimming_profile_to_node_failed|ALERT|Konfigurácia stmievacieho profilu pre node č. ${node} zlyhala|Configuration of dimming profile to node no. ${node} has failed|............... ++|circuit_breaker_was_turned_on_line|NOTICE|Zapnutie ističa na línii č. ${line}|Circuit breaker was turned on - line no. ${line}|............... ++|circuit_breaker_was_turned_off_line|ERROR|Vypnutie ističa na línií č. ${line}|Circuit breaker was turned off - line no. ${line}|............... ++|dimming_profile_was_processed_for_node|INFORMATIONAL|Stmievací profil bol spracovaný pre node č. ${node}|Dimming profile was processed for node no. ${node}|............... ++|switching_profile_was_processed_for_line|INFORMATIONAL|Spínací profil bol spracovaný pre líniu č. ${line}|Switching profile was processed for line no. ${line}|............... ++|thermometer_is_not_responding|WARNING|Teplomer neodpovedá|Thermometer is not responding|............... ++|thermometer_is_responding_again|NOTICE|Teplomer znovu odpovedá|Thermometer is responding again|............... ++|thermometer_sends_invalid_data|WARNING|Teplomer posiela neplatné hodnoty|Thermometer sends invalid data|............... ++|main_switch_has_been_turned_off|CRITICAL|Hlavný vypínač bol vypnutý|Main switch has been turned off|............... ++|main_switch_has_been_turned_on|NOTICE|Hlavný vypínač bol zapnutý|Main switch has been turned on|............... ++|power_supply_has_disconnected_input|ALERT|Napájací zdroj nemá napätie na vstupe|Power supply has disconnected input|............... ++|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_main_open|NOTICE|Hlavné dvere boli otvorené|Main door has been opened|............... ++|door_em_open|NOTICE|Dvere silovej časti boli otvorené|Power door has been opened|............... ++|door_main_open_without_permission|WARNING|Hlavné dvere boli otvorené bez povolenia - zapnutá siréna|Main door has been opened without permission - alarm is on|............... ++|door_em_open_without_permission|WARNING|Dvere silovej časti boli otvorené bez povolenia|Power door has been opened without permission|............... ++|door_main_close|NOTICE|Hlavné dvere boli zatvorené|Main door has been closed|............... ++|door_em_close|NOTICE|Dvere silovej časti boli zatvorené|Power door has been closed|............... ++|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|............... ++|electrometer_ok|NOTICE|Elektromer znovu odpovedá|Electrometer is responding again|............... ++|no_voltage_on_phase|CRITICAL|Na fáze č. ${phase} nie je napätie|No voltage detected on phase no. ${phase}|............... ++|voltage_on_phase_restored|NOTICE|Napätie na fáze č. ${phase} bolo obnovené|Voltage on phase no. ${phase} has been restored|............... ++|flow_start|NOTICE|FLOW bol spustený|FLOW has been started |............... ++|twilight_sensor_nok|ERROR|Sensor súmraku neodpovedá|Twilight sensor is not responding|............... ++|twilight_sensor_ok|NOTICE|Sensor súmraku znovu odpovedá|Twilight sensor is responding again|............... ++|lamps_have_turned_on|NOTICE|Lampy sa zapli|Lamps have turned on|............... ++|lamps_have_turned_off|NOTICE|Lampy sa vypli|Lamps have turned off|............... ++|flow_restart|NOTICE|FLOW bol reštartovaný|FLOW has been restarted|............... ++|nodes_db_changed|NOTICE|Zmena v node databáze|Node db has changed|............... diff --git a/RVO33/databases/pins.table b/RVO33/databases/pins.table new file mode 100755 index 0000000..0eb3d05 --- /dev/null +++ b/RVO33/databases/pins.table @@ -0,0 +1,14 @@ +pin:string|type:string|line:number +*|input1_01|door_condition|0|........... +*|input1_02|rotary_switch_state|0|........... +*|input1_03|rotary_switch_state|0|........... +*|input1_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/RVO33/databases/relays.table b/RVO33/databases/relays.table new file mode 100755 index 0000000..73bfbdb --- /dev/null +++ b/RVO33/databases/relays.table @@ -0,0 +1,5 @@ +line:number|tbname:string|contactor:number|profile:string ++|0|apKVJBwOyrP35m2lv7KYq50YXbeWNd64En9GxRqg|1||........... ++|1|roKgWqY95V3mXMRzyAjKno0bLjexpJPvaGDBw826|9|{"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|nJL5lPMwBx23YpqRe0rpr97damXvWVbOrD4gNzy8|9|{"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|XMBbew5z4ELrZa2mRAd3D278vPN6gy3DdVYlpKjq|9|{"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}|.................................................................................................................. diff --git a/RVO33/databases/settings.table b/RVO33/databases/settings.table new file mode 100755 index 0000000..fb149ca --- /dev/null +++ b/RVO33/databases/settings.table @@ -0,0 +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|project_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|cloud_topic:string|has_main_switch:boolean|daily_report:boolean|send_changed_node_numbers:boolean ++|rvo_senica_33_ip127|en|28.672B9D0E0000|48.70826502|17.28455203|192.168.252.1|rvo_senica_33_ip127|ZZgkOQiQ05HWtEm7TjPl|1883|0|63|unipi|ttyUSB0|1|20|5|6|3|u127|0|1|1|................................................... diff --git a/RVO33/databases/tbdata.nosql b/RVO33/databases/tbdata.nosql new file mode 100755 index 0000000..cfb4676 --- /dev/null +++ b/RVO33/databases/tbdata.nosql @@ -0,0 +1,4 @@ +-"apKVJBwOyrP35m2lv7KYq50YXbeWNd64En9GxRqg":[{"ts":1760535145413,"values":{"_event":{"type":"notice","status":"new","source":{"func":"modbus_reader","component":"1699965957410","component_name":"Modbus reader","edge":"apKVJBwOyrP35m2lv7KYq50YXbeWNd64En9GxRqg"},"message":{"sk":"rvo_senica_33_ip127: FLOW bol reštartovaný","en":"rvo_senica_33_ip127: FLOW has been restarted"},"message_data":""}}}],"id":"3000392001le71b"} +-"apKVJBwOyrP35m2lv7KYq50YXbeWNd64En9GxRqg":[{"ts":1760535145488,"values":{"edge_fw_version":"2025-10-08","maintenance_mode":false}}],"id":"3000392002le70b"} +-"apKVJBwOyrP35m2lv7KYq50YXbeWNd64En9GxRqg":[{"ts":1760535145501,"values":{"statecode":2,"power_mode":"Automatic"}}],"id":"3000392004le70b"} +-"apKVJBwOyrP35m2lv7KYq50YXbeWNd64En9GxRqg":[{"ts":1760535145524,"values":{"_event":{"type":"notice","status":"new","source":{"func":"rsPort.open()","component":"1699963668903","component_name":"DIDO_Controller","edge":"apKVJBwOyrP35m2lv7KYq50YXbeWNd64En9GxRqg"},"message":{"sk":"rvo_senica_33_ip127: FLOW bol spustený","en":"rvo_senica_33_ip127: FLOW has been started "},"message_data":""}}}],"id":"3000392006le70b"} diff --git a/RVO33/databases/tbdatacloud.nosql b/RVO33/databases/tbdatacloud.nosql new file mode 100755 index 0000000..729737f --- /dev/null +++ b/RVO33/databases/tbdatacloud.nosql @@ -0,0 +1,3 @@ +-"apKVJBwOyrP35m2lv7KYq50YXbeWNd64En9GxRqg":[{"ts":1760535145488,"values":{"edge_fw_version":"2025-10-08","maintenance_mode":false}}],"id":"3000392003le71b"} +-"apKVJBwOyrP35m2lv7KYq50YXbeWNd64En9GxRqg":[{"ts":1760535145501,"values":{"statecode":2,"power_mode":"Automatic"}}],"id":"3000392005le71b"} +-"apKVJBwOyrP35m2lv7KYq50YXbeWNd64En9GxRqg":[{"ts":1760535145524,"values":{"_event":{"type":"notice","status":"new","source":{"func":"rsPort.open()","component":"1699963668903","component_name":"DIDO_Controller","edge":"apKVJBwOyrP35m2lv7KYq50YXbeWNd64En9GxRqg"},"message":{"sk":"rvo_senica_33_ip127: FLOW bol spustený","en":"rvo_senica_33_ip127: FLOW has been started "},"message_data":""}}}],"id":"3000392007le71b"} diff --git a/RVO33/databases/total_energy.js b/RVO33/databases/total_energy.js new file mode 100755 index 0000000..dde340e --- /dev/null +++ b/RVO33/databases/total_energy.js @@ -0,0 +1,38 @@ +//key is rvo_number, value is max energy when lamps are on +const total_energy = { + 1: 580, + 2: 1100, + 3: 3700, + 4: 4100, + 7: 360, + 12: 1700, + 13: 5400, + 14: 440, + 15: 6100, + 16: 4800, + 20: 1600, + 21: 1000, + 22: 2600, + 23: 1000, + 25: 2600, + 33: 240, + 34: 4000, + 35: 2700, + 36: 820, + 37: 1400, + 35: 3500, + 39: 1170, + 41: 740, + 42: 660, + 43: 4900, + 45: 930, + 46: 700, + 47: 1100, + 48: 1500, + 50: 3200, + 53: 1250, + 55: 1000, + 56: 5500 +} + +module.exports = total_energy; diff --git a/RVO33/debug.js b/RVO33/debug.js new file mode 100755 index 0000000..9818194 --- /dev/null +++ b/RVO33/debug.js @@ -0,0 +1,16 @@ +// =================================================== +// FOR DEVELOPMENT +// Total.js - framework for Node.js platform +// https://www.totaljs.com +// =================================================== + +const options = {}; + +// options.ip = '127.0.0.1'; +// options.port = parseInt(process.argv[2]); +// options.config = { name: 'Total.js' }; +// options.sleep = 3000; +// options.inspector = 9229; +// options.watch = ['private']; + +require('total.js/debug')(options); \ No newline at end of file diff --git a/RVO33/err.txt b/RVO33/err.txt new file mode 100755 index 0000000..59b20f1 --- /dev/null +++ b/RVO33/err.txt @@ -0,0 +1,52 @@ +[2024-10-19T05:37:51.687] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-19T06:38:28.884] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-19T07:39:09.987] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-19T08:39:47.139] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-19T09:42:45.572] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-19T10:42:57.552] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-19T11:43:25.034] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-19T12:46:46.773] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-19T13:47:20.122] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-19T14:47:43.842] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-19T15:51:26.952] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-19T16:54:29.336] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-19T17:57:37.538] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-19T18:58:10.888] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-19T19:58:51.934] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-19T20:59:36.854] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-19T21:59:58.504] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-19T23:00:37.613] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-20T00:01:07.022] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2025-09-23T14:01:43.336] [ERROR] errLogs - uncaughtException: Cannot read property 'getHours' of undefined +[2025-09-23T14:01:43.337] [ERROR] errLogs - TypeError: Cannot read property 'getHours' of undefined + at Timeout.emptyReportToSend [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:01:43.338] [ERROR] errLogs - uncaughtException: Cannot read property 'getHours' of undefined +[2025-09-23T14:01:43.339] [ERROR] errLogs - TypeError: Cannot read property 'getHours' of undefined + at Timeout.emptyReportToSend [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:01:43.349] [ERROR] errLogs - uncaughtException: Cannot read property 'getHours' of undefined +[2025-09-23T14:01:43.349] [ERROR] errLogs - TypeError: Cannot read property 'getHours' of undefined + at Timeout.emptyReportToSend [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:01:49.057] [ERROR] errLogs - uncaughtException: date.getHours is not a function +[2025-09-23T14:01:49.057] [ERROR] errLogs - TypeError: date.getHours is not a function + at emptyReportToSend (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at Timeout.dailyReportCheck [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1351:5) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:01:49.058] [ERROR] errLogs - uncaughtException: date.getHours is not a function +[2025-09-23T14:01:49.059] [ERROR] errLogs - TypeError: date.getHours is not a function + at emptyReportToSend (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at Timeout.dailyReportCheck [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1351:5) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:01:49.065] [ERROR] errLogs - uncaughtException: date.getHours is not a function +[2025-09-23T14:01:49.066] [ERROR] errLogs - TypeError: date.getHours is not a function + at emptyReportToSend (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at Timeout.dailyReportCheck [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1351:5) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) diff --git a/RVO33/flow/cloudmqttconnect.js b/RVO33/flow/cloudmqttconnect.js new file mode 100755 index 0000000..b03491f --- /dev/null +++ b/RVO33/flow/cloudmqttconnect.js @@ -0,0 +1,357 @@ +exports.id = 'cloudmqttconnect'; +exports.title = 'Cloud connect mqtt'; +exports.group = 'MQTT'; +exports.color = '#888600'; +exports.version = '1.0.2'; +exports.icon = 'sign-out'; +exports.input = 2; +exports.output = 2; +exports.options = { host: 'tb-stage.worksys.io', port: 1883, clientid: "", username: "" }; + +exports.html = `
+
+
+
Hostname or IP address (if not empty - setting will override db setting)
+
+
+
Port
+
+
+
+
+
@(Client id)
+
+
+
topic
+
+
+
`; + + + +const { promisifyBuilder } = require('./helper/db_helper'); +const fs = require('fs'); +const mqtt = require('mqtt'); +const nosql = NOSQL('tbdatacloud'); + +const SEND_TO = { + debug: 0, + rpcCall: 1, +} + +//CONFIG +let saveTelemetryOnError = true;//backup_on_failure overrides this value +//------------------------ + +const noSqlFileSizeLimit = 4194304;//use 5MB - 4194304 +let insertNoSqlCounter = 0; +let insertBackupNoSqlCounter = 0; +let processingData = false; + +let backup_on_failure = true;//== saveTelemetryOnError - create backup client send failure +let restore_from_backup = 50; //how many rows process at once? +let restore_backup_wait = 3;//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; + + +exports.install = function(instance) { + + var client; + var opts; + var clientReady = false; + + let o = {}; //options + + function main() { + loadSettings(); + } + + //set opts according to db settings + function loadSettings() { + + o = instance.options; + if (!o.topic) o.topic = FLOW.GLOBALS.settings.cloud_topic; + + opts = { + host: o.host, + port: o.port, + clientId: o.clientid, + username: o.username, + rejectUnauthorized: false, + resubscribe: false + }; + + console.log("wsmqttpublich -> loadSettings from instance.options", o); + + if (!o.topic) { + instance.status("Not configured", "white"); + console.log("Cloud mqtt connect: no topic selected"); + return; + } + + connectToTbServer(); + } + + function connectToTbServer() { + var url = "mqtt://" + opts.host + ":" + opts.port; + console.log("MQTT URL: ", url); + + client = mqtt.connect(url, opts); + + client.on('connect', function() { + client.subscribe(`${o.topic}_backward`, (err) => { + if (!err) { + console.log("MQTT subscribed"); + } + }); + instance.status("Connected", "green"); + clientReady = true; + sendClientError = true; + }); + + client.on('reconnect', function() { + instance.status("Reconnecting", "yellow"); + clientReady = false; + }); + + client.on('message', function(topic, message) { + // message is type of buffer + message = message.toString(); + if (message[0] === '{') { + TRY(function() { + + message = JSON.parse(message); + if (message.hasOwnProperty("device") && message.hasOwnProperty("data") && message.data.hasOwnProperty("id")) { + client.publish(`${o.topic}_forward`, `{"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 } }); + } + + }, () => instance.debug('MQTT: Error parsing data', message)); + } + + instance.send(SEND_TO.rpcCall, { "topic": o.topic, "content": message }); + }); + + client.on('close', function() { + clientReady = false; + + instance.status("Disconnected", "red"); + instance.send(SEND_TO.debug, { "message": "Client CLOSE signal received !" }); + }); + + client.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) { + console.log('MQTT client error', err); + sendClientError = false; + } + clientReady = false; + }); + + } + + + instance.on('0', function(data) { + + if (clientReady) { + //do we have some data in backup file? if any, process data from database + if (saveTelemetryOnError) { + //read telemetry data and send back to server + if (!processingData) processDataFromDatabase(); + } + + let stringifiedJson = JSON.stringify(data.data) + client.publish(`${o.topic}_forward`, stringifiedJson, { qos: 1 }); + } + 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 (saveTelemetryOnError && o.topic) { + //create new file from tbdata.nosql, if file size exceeds given limit, and clear tbdata.nosql + makeBackupFromDbFile(); + + //write to tb + data.data.id = UID(); + nosql.insert(data.data); + } + } + }); + + instance.on("1", _ => { + main(); + }) + + instance.close = function(done) { + if (clientReady) { + client.end(); + } + }; + + + function getDbBackupFileCounter(type) { + var files = fs.readdirSync(__dirname + "/../databases"); + + let counter = 0; + for (var i = 0; i < files.length; i++) { + + if (files[i] == "tbdatacloud.nosql") continue; + + if (files[i].endsWith(".nosql")) { + + let pos = files[i].indexOf("."); + if (pos > -1) { + + let fileCounter = counter; + let firstDigit = files[i].slice(0, pos); + + fileCounter = parseInt(firstDigit); + if (isNaN(fileCounter)) fileCounter = 0; + //console.log("getDbBackupFileCounter digit:", files[i], firstDigit, fileCounter, isNaN(fileCounter), type); + + if (type == "max") { + if (fileCounter > counter) { + counter = fileCounter; + } + } + else if (type == "min") { + if (counter == 0) counter = fileCounter; + + if (fileCounter < counter) { + counter = fileCounter; + } + } + } + } + + } + + if (type == "max") counter++; + + return counter; + } + + const makeBackupFromDbFile = async () => { + + if (!saveTelemetryOnError) return; + + //to avoid large file: tbdata.nosql + + //init value is 0! + if (insertNoSqlCounter > 0) { + --insertNoSqlCounter; + return; + } + + insertNoSqlCounter = 100; + + let source = __dirname + "/../databases/tbdatacloud.nosql"; + + var stats = fs.statSync(source); + var fileSizeInBytes = stats.size; + + if (fileSizeInBytes > noSqlFileSizeLimit) { + + let counter = 1; + counter = getDbBackupFileCounter("max"); + + let destination = __dirname + "/../databases/" + counter + "." + "tbdatacloud.nosql"; + + //make backup file + fs.copyFileSync(source, destination); + //fs.renameSync(p, p + "." + counter); + + //clear tbdata.nosql + fs.writeFileSync(source, ""); + fs.truncateSync(source, 0); + + } + } + + const processDataFromDatabase = async () => { + + if (restore_from_backup <= 0) return; + + //calculate diff + const now = new Date(); + let currentTime = now.getTime(); + let diff = currentTime - lastRestoreTime; + + if ((diff / 1000) < restore_backup_wait) { + //console.log("*********restore_backup_wait", diff, restore_backup_wait); + return; + } + + processingData = true; + + //get filename to process + let counter = getDbBackupFileCounter("min"); + + //we have some backup files + let dataBase = 'tbdata'; + + var nosql; + if (counter == 0) dataBase = 'tbdatacloud'; + else dataBase = counter + "." + 'tbdatacloud'; + + nosql = NOSQL(dataBase); + + //select all data - use limit restore_from_backup + let records = await promisifyBuilder(nosql.find().take(restore_from_backup)); + + for (let i = 0; i < records.length; i++) { + if (clientReady) { + + let item = records[i]; + let id = item.id; + + if (id !== undefined) { + //console.log("------------processDataFromDatabase - remove", id, dataBase, i); + + try { + + let message = JSON.parse(JSON.stringify(item)); + delete message.id; + client.publish(`${o.topic}_forward`, JSON.stringify(message), { qos: 1 }); + + //remove from database + await promisifyBuilder(nosql.remove().where("id", id)); + + } catch (error) { + //process error + console.log("processDataFromDatabase", error); + } + + } + + } + else { + processingData = false; + return; + } + } + + if (records.length > 0) { + //clean backup file + if (counter > 0) nosql.clean(); + } + + //no data in db, remove + if (records.length == 0) { + if (counter > 0) nosql.drop(); + } + + const d = new Date(); + lastRestoreTime = d.getTime(); + + processingData = false; + + } + + instance.on('options', main); + +}; diff --git a/RVO33/flow/cmd_manager.js b/RVO33/flow/cmd_manager.js new file mode 100755 index 0000000..25912df --- /dev/null +++ b/RVO33/flow/cmd_manager.js @@ -0,0 +1,3071 @@ +exports.id = 'cmd_manager'; +exports.title = 'CMD Manager'; +exports.group = 'Worksys'; +exports.color = '#5D9CEC'; +exports.version = '0.0.3'; +exports.output = ['red', 'blue', 'yellow', 'blue', 'white', 'green']; +exports.input = 3; +exports.icon = 'cloud-upload'; + +exports.html = ` +
+
+
+
RPC - run RPC calls

+
+
+
@(User)
+
+
+
@(Password)
+
+
+
@(My edge)
+
+
+
+`; +exports.readme = `Manager for CMD calls`; + + +exports.install = function(instance) { + + 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, isEmptyObject, emptyJsObject, writeToFile, addToArrayIfUnique } = require('./helper/utils'); + const bitwise = require('bitwise'); + + var SunCalc = require('./helper/suncalc'); + const DataToTbHandler = require('./helper/DataToTbHandler'); + const errorHandler = require('./helper/ErrorToServiceHandler'); + const { sendNotification } = require('./helper/notification_reporter'); + const process = require('process'); + const { errLogger, logger, monitor } = require('./helper/logger'); + + //for accelerometer purposes + const { naklony } = require("../databases/accelerometer_db"); + + const dbNodes = TABLE("nodes"); + const dbRelays = TABLE("relays"); + + let GLOBALS; + let SETTINGS; + let rsPort; + let tbHandler; + + // runTasks intervals + const SHORT_INTERVAL = 30; + const LONG_INTERVAL = 300; + + //send data to following instances: + const SEND_TO = { + debug: 0, + tb: 1, + http_response: 2, + dido_controller: 3, + infoSender: 4, + dailyReport: 5 + } + + 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 + } + + 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 sendNodeReadout = null; // interval for sending agregate data from node + + 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["1"] = minutes; // dimming + priorities["76"] = minutes; // power + + minutes = 5; + priorities["75"] = minutes; // current + priorities["79"] = minutes; // energy + priorities["87"] = minutes; // aktualny cas + //priorities["84"] = minutes; //accelerometer + + minutes = 10; + priorities["74"] = minutes; // voltage + priorities["77"] = minutes; // power factor + priorities["78"] = minutes; // frequency + + minutes = 60; + priorities["0"] = minutes; // statecode + priorities["6"] = minutes; // dusk + priorities["7"] = minutes; // dawn + priorities["8"] = minutes; // profile + + minutes = 60 * 24; + priorities["89"] = minutes; // verzia fw + priorities["80"] = minutes; // lifetime + + //prikazy kt sa budu spustat na dany node - see config.js in terminal-oms.app. (1 - dimming) + let listOfCommands = [0, 1, 6, 7, 8, 74, 75, 76, 77, 78, 79, 80, 87, 89]; + + 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; + + // holds dusk, dawn (and more) values + let sunCalcResult; + + //helper container for counting resolved group of commands (commands related to set profile) + let cmdCounter = {};//key is node, value is counter + + //TODO: is this set working?? According to previous checks, sets do not work + //if sending of profile to node fails, we send notification and push node into set, so we do not send notification twice + const nodeProfileSendFail = new Set(); + + //we expect to get current temperature in Senica from senica-prod01 + let temperatureInSenica = null; + let accelerometerInterval = null; + + //NOTE: daily reports senica: + //rvo_is_on status, we monitor all nodes - if true, power and dimming should be not 0, if false, 24/7 nodes should be 0, other rvo should not respond + let rvo_is_on; + let previous_rvo_is_on_value; + let handleDailyReport; //setInterval for dailyReportHandler function + let dailyReport = {}; //data needed for daily report + let reportToSend = {}; //final report which we send to cloud + let breakerCounter = null; // status of breakers after flow starts is not in report + let rvoPeriod; // interval of checking dusk dawn and if rvo_is_on + let initialReportStatus = false; + + const DAILY_REPORT_HANDLER_TIME = 3_600_000; + const SET_SUNCALC_RESULT_TIME = 3_600_000; + const SET_RVO_PERIOD_TIME = 300_000; + const ADD_NODE_TO_REPORT_TIME = 3_600_000; + + //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); + + let now = new Date(); + console.log("Cmd-mngr installed", now.toLocaleString("sk-SK")); + + sunCalcResult = calculateDuskDawn(); + + handleRsPort(); + + customTasksInterval = setInterval(reportEdgeDateTimeAndNumberOfLuminaires, 120_000); + setTimeout(reportEdgeDateTimeAndNumberOfLuminaires, 4000); + + //dailyReport related + emptyReportToSend(); + breakerCounter = Object.keys(relaysData).length - 1; // we get number of lines (breakers) except of line 0 + rvoPeriod = setInterval(setRvoPeriod, SET_RVO_PERIOD_TIME); + setTimeout(setRvoPeriod, 3000); + setInterval(setSunCalcResult, SET_SUNCALC_RESULT_TIME); + handleDailyReport = setInterval(dailyReportHandler, DAILY_REPORT_HANDLER_TIME); + + + setCorrectTime = setInterval(setCorrectPlcTimeOnceADay, 60000 * 60); // 1 hour + setCorrectPlcTimeOnceADay(); + + sendNodeReadout = setInterval(sendNodesData, 150_000); + accelerometerInterval = setInterval(accelerometerData, 60000 * 30); //30 min + } + + + 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" + //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 + // if node regular readout does not respond, we repeat request + params.repeatCounter = 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-mngr: 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.byte4 = 96; + params.recipient = 1; + params.register = 8; + params.rw = 1;//write + params.timestamp = timestamp; + 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.byte4 = 96; + params.recipient = 1; + params.register = 8; + params.rw = 1;//write + params.timestamp = timestamp; + 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). + */ + + 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.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.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 + { + + logger.debug("processNodeProfile: Threshold lux level for DUSK/DAWN", node); + + let params = getParams(); + params.type = "set_node_profile"; + params.address = node; + params.register = 96; + params.recipient = 1; + params.rw = 1;//write + params.timestamp = timestamp; + 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(); + params.type = "set_node_profile"; + params.address = node; + params.register = 97; + params.recipient = 1; + params.rw = 1;//write + params.timestamp = timestamp; + 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.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); + + 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); + + console.log("proces profile finished *********************") + } + + + 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; + }); + } + + + 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) { + for (let k in nodesData) { + 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`); + } + } + } + + + function loadRelaysData(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 (value.contactor == 1) processAllNodeProfilesOnLine(value.line); + } + } + + + function reportOnlineNodeStatus(line) { + //Po zapnutí línie broadcastovo aktualizovať predtým čas a o 3 sek neskor - status, brightness + + logger.debug("Cmd-mngr: ----->reportOnlineNodeStatus for line", line); + + const d = new Date(); + + // broadcast actual time + let params = getParams(); + params.address = 0xffffffff;//Broadcast + params.byte1 = d.getHours(); + params.byte2 = d.getMinutes(); + params.recipient = 2;//2 broadcast, address = 0 + params.register = 87;//Actual time + params.rw = 1;//write + params.type = "node-onetime-write"; + params.timestamp = d.getTime() + 30000; + params.info = "run broadcast: Actual time"; + //params.debug = true; + + tasks.push(params); + + let sec = 3; + setTimeout(function() { + //Po zapnutí línie - spraviť hromadný refresh stavu práve zapnutých svietidiel + + let time = Date.now(); + + for (let k in nodesData) { + + //potrebujem nody k danej linii + 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].node_status_before_offline === true || nodesData[k].status === true) { + status = "OK"; + nodesData[k].time_of_last_communication = time; + } + + nodesData[k].readout.status = status; + + updateNodeStatus(k, status === "OK" ? true : false); + if (nodesData[k].hasOwnProperty("node_status_before_offline")) delete nodesData[k].node_status_before_offline; + sendTelemetry({ status: status }, tbname, time); + + //vyreportovanie dimming, current, input power pre liniu pre vsetky nody + //Prud + { + let params = getParams(); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 75;//prud + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = time + 4000; + params.info = 'read current'; + //params.debug = true; + tasks.push(params); + } + + //vykon + { + let params = getParams(); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 76;//výkon + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = time + 4100; + params.info = 'read power'; + //params.debug = true; + + tasks.push(params); + } + //dimming + { + let params = getParams(); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 1;//dimming + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = time + 4200; + params.info = 'read dimming'; + //params.debug = true; + + tasks.push(params); + } + + } + } + + }, sec * 1000); + } + + + function reportOfflineNodeStatus(line) { + + logger.info("Cmd-mngr: ------>reportOffLineNodeStatus for line ", line); + + values = {}; + values["dimming"] = 0;//brightness + values["power"] = 0;//výkon + values["current"] = 0;//prúd + values["status"] = "OFFLINE"; + + const date = Date.now(); + + Object.keys(nodesData).forEach(node => { + + //potrebujem nody k danej linii + if (line == nodesData[node].line || line == undefined) { + + let tbname = nodesData[node].tbname; + let nodeStatus = nodesData[node].status; + + //in case we have reported offline node status, we return (continue with next node) + if (nodeStatus === "OFFLINE") return; + + nodesData[node].node_status_before_offline = nodeStatus; + nodesData[node].status = "OFFLINE"; + nodesData[node].readout = {}; + + sendTelemetry({ ...values }, tbname, date); + } + }); + + } + + + function turnLine(onOrOff, line, info) { + let obj = { + line: line, + command: onOrOff, + info: info + }; + + //to assure, handleDailyReportFunction do not run before rvo_is_on variable changes. So after every line switch we reset the timer + clearInterval(handleDailyReport); + handleDailyReport = setInterval(dailyReportHandler, DAILY_REPORT_HANDLER_TIME); + + //logger.debug("linia", line, obj); + instance.send(SEND_TO.dido_controller, obj); + } + + + 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"; + 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]) { + //CRC_ERROR + message = "NOK"; + error = "CRC_ERROR c1"; + instance.send(SEND_TO.debug, "CRC_ERROR c1"); + } + + 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") { + instance.send(SEND_TO.debug, bytes); + instance.send(SEND_TO.debug, "RESPONSE " + type + " - " + bytes[4]); + + //logger.debug(SEND_TO.debug, "RESPONSE " + type + " - " + bytes[4], bytes); + + error = "type is: " + type; + + message = "NOK"; + } + + return { message, type, error }; + } + + + //BUILD TASKS// + function buildTasks(params) { + + //return; + console.log("buidTAaasks start ****************", params); + monitor.info("buildTasks - params", params); + + let processLine; //defined line + let init = false; + let processLineProfiles = true; + let processBroadcast = true; + let processNodes = true; + + if (params == undefined) { + init = true; + tasks = []; + logger.debug("-->buildTasks clear tasks"); + } + else { + processLineProfiles = params.processLineProfiles; + processBroadcast = false; + processNodes = false; + + processLine = params.line; + } + + let now = new Date(); + + //process line profiles + if (processLineProfiles) { + + let keys = Object.keys(relaysData); + + for (let i = 0; i < keys.length; i++) { + + let line = parseInt(keys[i]); + let profilestr = relaysData[line].profile; + + if (processLine != undefined) { + if (processLine != line) continue; + } + + try { + + /** + * we process line profiles: timepoints, astro clock, lux_sensor, offsets ... + */ + if (profilestr === "") throw ("Profile is not defined"); + let profile = JSON.parse(profilestr); + 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; + + // add name to regular profile timepoint and delete unused end_time key: + time_points.forEach(point => { + point.name = "profileTimepoint" + delete point.end_time; + }); + + //monitor.info("buildTasks: time_points", time_points); + + + /** + * 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 astro clock true, we remove all regular profile points + time_points = []; + + //TODO: when astro clock == true, is offset calculated ??? + //let duskAstroClockOffset = profile.dusk_astro_clock_offset; + //let dawnAstroClockOffset = profile.dawn_astro_clock_offset; + //console.log("line astro clock offsets dusk a dawn: ", duskAstroClockOffset, dawnAstroClockOffset); + // maybe add dusk dawn offset to calculateDuskDawn ?? what dusk dawn will be if dawn_lux_sensor == true?? + //let sunCalcResult = calculateDuskDawn(new Date(), line, duskAstroClockOffset, dawnAstroClockOffset); + + 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 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); + + 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); + + 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(':'); + + let ad = new Date(); + ad.setHours(parseInt(ahours), parseInt(aminutes), 0); + + let bd = new Date(); + bd.setHours(parseInt(bhours), parseInt(bminutes), 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++) { + + let start_time = new Date(); + let [hours, minutes] = time_points[t].start_time.split(':'); + start_time.setHours(parseInt(hours), parseInt(minutes), 0); + + //task is in 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(); + params.type = "relay"; + params.line = parseInt(line); + params.value = time_points[t].value; + params.tbname = relaysData[line].tbname; + params.timestamp = start_time.getTime(); + + // 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; + + //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)) { + 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; + + params.debug = true; + + //turn on/off line + tasks.push(params); + monitor.info("TimePoint params: ", params.info, start_time); + } + + monitor.info("-->time_points final", line, time_points); + + //ensure to turn on/off according to calculated currentValue + let params = getParams(); + params.type = "relay"; + params.line = parseInt(line); + params.tbname = relaysData[line].tbname; + params.value = currentValue; + params.timestamp = i; + params.debug = true; + + //logger.debug(now.toLocaleString("sk-SK")); + 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; + + tasks.push(params); + + } catch (error) { + if (profilestr !== "") { + //errLogger.error(profilestr, error); + console.log(`Cmd_mngr: Unable to process line profile ${line}. Error: `, error); + errorHandler.sendMessageToService(profilestr + "-" + error, 0, "js_error"); + } else { + turnLine("off", line, "No line profile. Switching it off on startup"); + } + } + + } + //logger.debug("tasks:"); + //logger.debug(tasks); + } + + + //NOTE: PROCESS DEFAULT BROADCASTS - Time of dusk, Time of dawn, Actual Time + if (processBroadcast) { + + let d = new Date(); + let time = d.getTime(); + //let sunCalcResult = calculateDuskDawn(); + + { + let params = getParams(); + + params.address = 0xffffffff;//broadcast + params.byte1 = sunCalcResult["dusk_hours"]; + params.byte2 = sunCalcResult["dusk_minutes"]; + params.recipient = 2;//2 broadcast, + params.register = 6;//Time of dusk + params.rw = 1;//write + params.type = "node-regular-write"; + params.timestamp = time + 60000; + params.addMinutesToTimestamp = 60 * 3; //kazde 3 hodiny zisti novy dusk + params.info = "Broadcast-duskTime"; + + tasks.push(params); + } + + { + let params = getParams(); + + params.address = 0xffffffff;//broadcast + params.byte1 = sunCalcResult["dawn_hours"]; + params.byte2 = sunCalcResult["dawn_minutes"]; + params.recipient = 2; //2 broadcast + params.register = 7;//Time of dawn + params.rw = 1;//write + params.type = "node-regular-write"; + params.timestamp = time + 60001; + params.addMinutesToTimestamp = 60 * 3; //kazde 3 hodiny zisti novy dawn + params.info = "Broadcast-dawnTime"; + + tasks.push(params); + } + + { + let params = getParams(); + + params.address = 0xffffffff;//broadcast + params.byte1 = d.getHours(); + params.byte2 = d.getMinutes(); + params.recipient = 2; //2 broadcast + params.register = 87;//Actual time + params.rw = 1;//write + params.type = "node-regular-write"; + params.timestamp = time + 60002; + params.addMinutesToTimestamp = 5; + params.info = "run broadcast: Actual time"; + + tasks.push(params); + } + + } + + //process nodes & tasks - read node's data + if (processNodes) { + + let time = Date.now(); + + for (let k in nodesData) { + let address = parseInt(k); + let tbname = nodesData[k].tbname; + let register = 0; + + for (let i = 0; i < listOfCommands.length; i++) { + + register = listOfCommands[i]; + let addMinutesToTimestamp = priorities[register]; + + let params = getParams(); + + params.address = address; + params.recipient = 1; + params.register = register; + params.type = register == 1 ? "node-dimming-read" : "node-regular-read"; + params.tbname = tbname; + params.timestamp = time + 5000 + i * 500 + addMinutesToTimestamp * 1000; //to make slight time difference + params.addMinutesToTimestamp = addMinutesToTimestamp; + params.info = "Node regular read command"; + + tasks.push(params); + } + + } + } + + + //niektore ulohy sa vygeneruju iba 1x pri starte!!! + if (!init) return; + + + //Master node FW version - modifies SETTINGS.masterNodeIsResponding + { + let params = getParams(); + params.type = "cmd-master"; + params.register = 4; + params.address = 0; + params.timestamp = 0; + params.addMinutesToTimestamp = 5; + params.tbname = SETTINGS.rvoTbName; + params.info = "Master node FW verzia"; + //params.debug = true; + + tasks.push(params); + } + + //kazdu hodinu skontrolovat nastavenie profilov + { + let params = getParams(); + params.type = "process_profiles"; + params.timestamp = Date.now() + 60001; + params.addMinutesToTimestamp = 60;//60 = every hour + params.info = "detekcia nespracovaných profilov linie a nodov"; + //params.debug = true; + + tasks.push(params); + } + + monitor.info("tasks created:", tasks.length); + } + + + /** + * We process line profile, where "astro_clock": true + * example profile: + * + "dawn_lux_sensor": true, + "dusk_lux_sensor": true, + "dawn_lux_sensor_value": 5, + "dusk_lux_sensor_value": 5, + "dawn_astro_clock_offset": 0, + "dusk_astro_clock_offset": 10, + "dawn_lux_sensor_time_window": 30, + "dusk_lux_sensor_time_window": 30, + "dawn_astro_clock_time_window": 60, + "dusk_astro_clock_time_window": 60 + + * if dawn: if currentTimestamp is in timewindow "dawnTime + and - dawn_lux_sensor_time_window" and lux value >= lux_sensor_value, we switch off the line. + * if dusk: we do oposite + * + * dawn: usvit - lux je nad hranicou - vypnem + * dusk: sumrak - lux je pod hranicou - zapnem + */ + 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++) { + + let line = keys[i]; //line is turned off by default + let profilestr = relaysData[line].profile; + const contactor = relaysData[line].contactor; + + try { + + let profile = JSON.parse(profilestr); + if (Object.keys(profile).length === 0) throw ("turnOnOffLinesAccordingToLuxSensor - profile is not defined"); + + 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 (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"); + } + } + } + + //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 (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"); + } + } + } + + } + + } catch (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) { + //MASTER + if (node == 0) return; + + let nodeObj = nodesData[node]; + if (nodeObj == undefined) return; + + let nodeCurrentStatus = nodeObj.status; + const now = Date.now(); + + let data = null; + + if (nodeCurrentStatus === "OFFLINE") { + data = { status: newStatus }; + nodeDbStatusModify(node, data); + return; + } + else 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; + } + + } + + + 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 }; + } + }); + }); + } + + + function processDailyReport() { + + const now = Date.now(); + + for (const [key, value] of Object.entries(dailyReport)) { + + if (["name", "time", "dusk_and_dawn"].includes(key)) continue; + + let poleNumber = nodesData[key]["pole_number"]; + let line = dailyReport[key].line; + let nodeType = nodesData[key]["node_type"]; + let fullNodeName = key // key == nodeNumber + + if (poleNumber && nodeType) { + fullNodeName = SETTINGS.rvo_number + "/" + poleNumber + "_" + line + "L_" + key + "_" + nodeType; + } else { + fullNodeName = key; + } + + if (rvo_is_on) { + + if (value.initialTs) { + if (value.initialTs + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["night_no_data"], fullNodeName); + console.log('report nedostava ziadne data uz hodinu', fullNodeName); + value.initialTs = now; + } + } + if (value.dimmingIsZeroTime) { + if (value.dimmingIsZeroTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["night_dimming=0"], fullNodeName); + console.log("report node dimming je 0 ale ma svietit", fullNodeName); + value.dimmingIsZeroTime = now; + } + } + if (value.powerIsZeroTime) { + if (value.powerIsZeroTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["night_power=0"], fullNodeName); + console.log("report node power je 0 ale ma svietit", fullNodeName); + value.powerIsZeroTime = now; + } + } + + } else { + + let contactorStatus = relaysData[line].contactor; + if (contactorStatus === 1) { + + if (value.initialTs) { + if (value.initialTs + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["day_24/7_no_data"], fullNodeName); + console.log('node je na 24/7 ale nedostava ziadne data uz hodinu', fullNodeName); + value.initialTs = now; + } + } + if (value.dimmingIsOnButShouldBeOffTime) { + if (value.dimmingIsOnButShouldBeOffTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["day_24/7_dimming>0"], fullNodeName); + console.log("report dimming je > 0 ale nema svietit", fullNodeName); + value.dimmingIsOnButShouldBeOffTime = now; + } + } + if (value.powerIsOnButShouldBeOffTime) { + if (value.powerIsOnButShouldBeOffTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["day_24/7_power>0"], fullNodeName); + console.log("report power je > 0 ale nema svietit", fullNodeName); + value.powerIsOnButShouldBeOffTime = now; + } + } + + } + + } + + } + + let report = {}; + report["name"] = SETTINGS.rvo_name; + report["time"] = new Date(); + report["report"] = reportToSend; + + writeToFile(F.path.root("report_data.log"), report, true); + instance.send(SEND_TO.dailyReport, report); + } + + + function dailyReportHandler() { + + if (!SETTINGS.daily_report) return; + + // after dawn we empty reportToSend and start to get data for a new day + const date = new Date(); + const hour = date.getHours(); + const minute = date.getMinutes(); + + console.log("now: ", hour, minute, "suncalc: ", sunCalcResult.dawn_hours, sunCalcResult.dawn_minutes); + + if (hour === sunCalcResult.dawn_hours) { + + //NOTE: ak je este pred usvitom, spracujeme report a posleme na cloud, ak uz je po usvite, resetujeme report plnime data noveho dna + if (minute >= sunCalcResult.dawn_minutes - 2) { + emptyReportToSend(); + emptyDailyReport(); + console.log("Podmienka 1 v dailyReport handler"); + } else { + processDailyReport(); + emptyReportToSend(); + emptyDailyReport(); + console.log("Podmienka 2 v dailyReport handler"); + } + + initialReportStatus = true; + + // ak sa funkcia spusti o hodinu alebo 2 neskor, ako je usvit (moze sa to stat, kedze kazde zapnutie/vypnutie linii odznova spusti casovac. + } else if (hour === sunCalcResult.dawn_hours + 1 || hour === sunCalcResult.dawn_hours + 2) { + if (!initialReportStatus) { + emptyReportToSend(); + emptyDailyReport(); + initialReportStatus = true; + console.log("Podmienka 3 v dailyReport handler"); + } else { + processDailyReport(); + initialReportStatus = true; + console.log("Podmienka 4 v dailyReport handler"); + } + } else { + processDailyReport(); + initialReportStatus = false; + console.log("Podmienka 5 v dailyReport handler"); + } + + console.log("initialReportStatus: ", initialReportStatus); + + } + + function emptyReportToSend() { + emptyJsObject(reportToSend); + reportToSend["contactor"] = { off: [], on: [] }; + reportToSend["night_no_data"] = []; + reportToSend["night_dimming=0"] = []; + reportToSend["night_power=0"] = []; + reportToSend["day_24/7_no_data"] = []; + reportToSend["day_24/7_dimming>0"] = []; + reportToSend["day_24/7_power>0"] = []; + console.log(`resetuje sa reportToSend`); + } + + + //NOTE: ked je initialTs stale rovnaky a zistime ze linie su vypnute (relaysData.line.contactor) - zistim, ci je node na tej linii. Vieme, ze ak je linia vypnuta je to v poriadku lebo nie je na 24/7 linii + //ak je na 24/7 linii, reportujeme, ze neprijima data + function emptyDailyReport() { + const ts = Date.now(); + emptyJsObject(dailyReport); + + //NOTE: do dailyReport dame vsetky nody a pravidelne kontrolujeme ci maju data + //ked nastane sumrak/usvit a svetla maju zacat/prestat svietit, dailyReport spravime nanovo: + for (const [key, value] of Object.entries(nodesData)) { + dailyReport[value.node] = { line: value.line, initialTs: ts }; + } + + console.log("dailyReport: ", dailyReport); + } + + + async function runTasks() { + + clearInterval(interval); + + let currentTimestamp = Date.now(); + + //sort tasks based on timestamp + 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) { + instance.send(SEND_TO.debug, "no tasks created"); + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + if (!rsPort.isOpen) { + instance.send(SEND_TO.debug, "!rsPort.isOpen"); + //await rsPort.open(); + //console.log("Cmd-mngr: !rsPort.isOpen"); + } + + let currentTask = tasks[0]; + + if (currentTask.debug) { + //logger.debug("--->task to process", currentTask); + } + + if (currentTask.timestamp <= currentTimestamp) { + let params = { ...tasks[0] }; + + //allow terminal commands + if (SETTINGS.maintenance_mode && params.type !== "cmd-terminal") { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + let type = params.type; + let tbname = params.tbname; + let node = params.address; + let register = params.register; + let line = null; + let itIsNodeCommand; + + if (nodesData[node] !== undefined) { + line = nodesData[node].line; + itIsNodeCommand = true; + } + + if (params.line !== undefined) line = params.line; + + if (params.addMinutesToTimestamp > 0 || params.timePointName) { + tasks[0].timestamp = currentTimestamp + tasks[0].addMinutesToTimestamp * 60000; + } else { + tasks.shift(); + } + + //kontrola nespracovanych profilov nodov + //TODO: co ked niektore nody neprijimaju profily? kazdu hodinu zahltuju "tasks" array + if (type == "process_profiles") { + //na vsetky zapnutych liniach sa spracuju nespracovane profily nodov + loadRelaysData(); + interval = setInterval(runTasks, SHORT_INTERVAL); + return; + } + + //relay + if (type == "relay") { + + const timePointName = params.timePointName; + const value = params.value; + + let date = new Date(); + date.setDate(date.getDate() + 1);//next day + + let sunCalcResult; + if (timePointName) sunCalcResult = calculateDuskDawn(date, params.line); + + + if (timePointName == "dawn") { + tasks[0].timestamp = sunCalcResult.dawn_time; + } + else if (timePointName == "dusk") { + tasks[0].timestamp = sunCalcResult.dusk_time; + } + else if (timePointName == "luxOn") { + tasks[0].timestamp = sunCalcResult.dusk_time + params.dusk_lux_sensor_time_window * 60000; + } + else if (timePointName == "luxOff") { + tasks[0].timestamp = sunCalcResult.dawn_time + params.dawn_lux_sensor_time_window * 60000; + } + else if (timePointName == "profileTimepoint") { + tasks[0].timestamp = currentTimestamp + tasks[0].addMinutesToTimestamp * 60000; + } + + let info = "aplikovany bod profilu"; + let onOrOff = ""; + value == 1 ? onOrOff = "on" : onOrOff = "off"; + + turnLine(onOrOff, params.line, info); + + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + if (!SETTINGS.masterNodeIsResponding) { + //ak neodpoveda, nebudeme vykonavat ziadne commands, okrem cmd-terminal cmd-master + errorHandler.sendMessageToService("Master node is not responding"); + + let stop = true; + + if (type === "cmd-terminal" || type === "cmd-master") stop = false; + if (stop) { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + } + + let contactorStatus = 1; + if (relaysData[line] != undefined) contactorStatus = relaysData[line].contactor; + + if (line === 0 || contactorStatus === 0 || FLOW.deviceStatus.state_of_breaker[line] === "Off") { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + // TODO: -> status offline for rvo if rotary_switch_state is OFF, this is source of errors + // check if rotary_switch_state == "Off" + // state_of_braker: disconnected = true? + + if (!rsPort.isOpen) { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + //RE-CALCULATE VALUES + //set actual time for broadcast + if (register == 87 && params.recipient === 2) { + var d = new Date(); + params.byte1 = d.getHours();//h + params.byte2 = d.getMinutes();//m + } + + //SET DUSK/DAWN FOR BROADCAST + //Time of dusk + if (register == 6 && params.recipient === 2) { + + if (type != "cmd-terminal") { + params.byte1 = sunCalcResult["dusk_hours"];//h + params.byte2 = sunCalcResult["dusk_minutes"];//m + } + } + + //Time of dawn + if (register == 7 && params.recipient === 2) { + if (type != "cmd-terminal") { + params.byte1 = sunCalcResult["dawn_hours"];//h + params.byte2 = sunCalcResult["dawn_minutes"];//m + } + } + //----------------------- + + instance.send(SEND_TO.debug, "address: " + node + " register:" + register + "type: " + type); + + var startTime, endTime; + startTime = new Date(); + + let saveToTb = true; + if (!tbname) saveToTb = false; + + let resp = com_generic(node, params.recipient, params.rw, register, params.name, params.byte1, params.byte2, params.byte3, params.byte4); + let readBytes = 11; + let timeout = 4000; + + + // await keyword is important, otherwise incorrect data is returned! + await writeData(rsPort, resp, readBytes, timeout).then(function(data) { + + //sometimes happens, that status of node changes to OK, NOK even if line was turned off and should be status OFFLINE. To prevent this, we return if line contactor is 0: + if (itIsNodeCommand && line && relaysData[line].contactor !== 1) return; + + 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); + + //ak sa odpoved zacina 0 - je to v poriadku, inak je NOK + let message = result.message; // OK, NOK + let message_type = result.type; + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + console.log("detected response:", result); + logger.debug("Cmd-mngr: writeData done " + message_type + " duration: " + timeDiff + " type: " + params.debug, params, result); + } + } + + let values = {}; + + //CMD FINISHED + if (message == "OK") { + + updateNodeStatus(node, true); + + //write + if (type == "set_node_profile") { + let result = cmdCounterResolve(node); + if (result == 0) { + dbNodes.modify({ processed: true }).where("node", node).make(function(builder) { + builder.callback(function(err, response) { + + sendNotification("Cmd-mngr: process cmd", SETTINGS.rvoTbName, "dimming_profile_was_successfully_received_by_node", { node: node }, "", SEND_TO.tb, instance); + + logger.debug("--> profil úspešne odoslaný na node č. " + node); + nodesData[node].processed = true; + nodeProfileSendFail.delete(node); + }); + }); + } + } + + //parse read response + if (params.rw == 0) { + values = processResponse(register, dataBytes); //read + } + + if (itIsNodeCommand) { + values.comm_status = "OK"; + values.status = "OK"; + nodesData[node].readout = { ...nodesData[node].readout, ...values }; + + + if (SETTINGS.daily_report) { + //TODO: co ak nedostavame odpovede z nodu ? Musime vyreportovat!! + //v dailyReport teda musi byt kompletny zoznam nodov a neustale kontrolovat, ci maju data, ak nie report node - neodpoveda + if (register === 1) { + + let now = Date.now(); + + if (rvo_is_on === true) { + + if ("dimmingIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].dimmingIsOnButShouldBeOffTime; + + if (values.dimming > 0) { + if ("dimmingIsZeroTime" in dailyReport[node]) delete dailyReport[node].dimmingIsZeroTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if (!("dimmingIsZeroTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], dimmingIsZeroTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } else { + + if ("dimmingIsZeroTime" in dailyReport[node]) delete dailyReport[node].dimmingIsZeroTime; + + if (values.dimming > 0) { + if (!("dimmingIsOnButShouldBeOffTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], dimmingIsOnButShouldBeOffTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if ("dimmingIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].dimmingIsOnButShouldBeOffTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } + } + + if (register === 76) { + + let now = Date.now(); + + if (rvo_is_on === true) { + + if ("powerIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].powerIsOnButShouldBeOffTime; + + if (values.power > 1) { + if ("powerIsZeroTime" in dailyReport[node]) delete dailyReport[node].powerIsZeroTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if (!("powerIsZeroTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], powerIsZeroTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } else { + + if ("powerIsZeroTime" in dailyReport[node]) delete dailyReport[node].powerIsZeroTime; + + if (values.power > 1) { + if (!("powerIsOnButShouldBeOffTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], powerIsOnButShouldBeOffTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if ("powerIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].powerIsOnButShouldBeOffTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } + } + } + + } + + //master node + if (node == 0) { + sendNotification("Cmd-mngr: 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; + } + + if (params.debug) { + //logger.debug("saveToTb", saveToTb, tbname, values); + } + + if (saveToTb && type != "node-regular-read") { + sendTelemetry(values, tbname); + } + else { + if (type == "cmd-terminal") { + terminalCommandResponse(params, "SUCCESS", data); + } + } + + } + else { + terminalCommandResponse(params, "ERROR", data); + handleNokResponseOnRsPort("handleNOK else block", params, itIsNodeCommand, saveToTb); + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + //logger.debug("writeData err: ", error, result, params); + logger.debug("writeData err: ", tbname, node, register, values); + } + } + + //logger.debug(error, result, params); + } + }).catch(function(reason) { + + //console.log("writeData catch exception", reason); + instance.send(SEND_TO.debug, reason); + + terminalCommandResponse(params, "FAILURE", null, reason); + handleNokResponseOnRsPort("handleNOK catch block", params, itIsNodeCommand, saveToTb); + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + logger.debug("-->WRITE FAILED: " + reason, params.debug, params); + } + } + + }); + + } + 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); + } + + + // if node does not respond to request, we repeat request 3 times: + function repeatCommand(params) { + params.repeatCounter++; + if (params.repeatCounter < 4) { + params.timestamp = 0; + params.addMinutesToTimestamp = 0; + tasks.push(params); + } + } + + function handleNokResponseOnRsPort(message, params, itIsNodeCommand, saveToTb) { + + let node = params.address; + let register = params.register; + let type = params.type; + let tbName = params.tbname; + if (!tbName) return; + + let values = {}; + + let updateStatus = updateNodeStatus(node, false); + + if (itIsNodeCommand) { + values.comm_status = "NOK"; + nodesData[node].readout.comm_status = "NOK"; + repeatCommand(params); + } + + if (updateStatus) { + values.status = "NOK"; + nodesData[node].readout.status = "NOK"; + } + + if (type === "node-regular-read") return; + + //master node + if (node == 0) { + sendNotification("Cmd-mngr: 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; + + if (register == 4) values["master_node_version"] = "NOK"; + } + + if (type == "set_node_profile") { + delete cmdCounter[node]; + logger.debug("profil nebol úspešne odoslaný na node č. ", params); + + if (!nodeProfileSendFail.has(node)) { + sendNotification("Cmd-mngr: process cmd", tbName, "configuration_of_dimming_profile_to_node_failed", { node: node }, "", SEND_TO.tb, instance); + nodeProfileSendFail.add(node); + } + } + + // console.log("------",node, register, type, itIsNodeCommand, updateStatus, saveToTb, values); + if (saveToTb) { + sendTelemetry(values, tbName); + } + + } + + + function sendNodesData() { + Object.keys(nodesData).forEach(node => { + if (nodesData[node]["status"] !== "OFFLINE") { + sendTelemetry(nodesData[node].readout, nodesData[node].tbname); + nodesData[node].readout = {}; + } + }) + } + + + /** + * 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; + } + + 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); + + //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 === "OFFLINE") { + nodeObj.node_status_before_offline === true ? number_of_ok_luminaires++ : number_of_nok_luminaires++; + } + else if (nodeObj.status == true) 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 - ts % 60000 //round to full minute + }; + + sendTelemetry(values, SETTINGS.rvoTbName, ts); + } + + + function setSunCalcResult() { + //if next day, we get new dusk and dawn. To make sure, in local timezone 2:00 means 00:00 in utc (it means next day) + if (new Date().getHours() === 2) { + sunCalcResult = calculateDuskDawn(); + console.log("Novy suncalc: ", sunCalcResult); + } + } + + + function setRvoPeriod() { + + if (!SETTINGS.daily_report) return; + + const ts = Date.now(); + + previous_rvo_is_on_value = rvo_is_on; + + if (ts < sunCalcResult.dawn_time - 1_800_000) { // nodes should be on (00:00 -> 06:00 ( - pol hodina, lebo rvo vypina skor) + rvo_is_on = true; + } else if (sunCalcResult.dawn_time - 1_800_000 < ts && ts < sunCalcResult.dusk_time + 1_800_000) { // nodes should be off 06:00 -> 21:00 + rvo_is_on = false; + } else if (sunCalcResult.dusk_time + 1_800_000 < ts) { // nodes should be on 21:00 -> 00:00 + rvo_is_on = true; + } + + if (previous_rvo_is_on_value !== rvo_is_on) { + emptyDailyReport(); + console.log("rvo_is: ", rvo_is_on, previous_rvo_is_on_value); + } + } + + + function handleRsPort() { + + if (rsPort) { + rsPort.removeAllListeners(); + rsPort = null; + } + + //! 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-mngr: rsPort opened success"); + + 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); + + }).catch(function(reason) { + instance.send(SEND_TO.debug, "Cmd-mngr: RPC runSyncExec - promise rejected:" + reason); + }); + }); + + rsPort.on('error', function(err) { + errorHandler.sendMessageToService([exports.title, "unable to open port", SETTINGS.serial_port, err.message], 0); + monitor.info("Cmd-mngr: Error on rsPort", err.message); + }); + + rsPort.on("close", () => { + monitor.info("Cmd-mngr: rsPort closed, reconnecting..."); + setTimeout(handleRsPort, 1000); + }); + + rsPort.open(); + } + + + instance.on("close", () => { + clearInterval(interval); + clearInterval(customTasksInterval); + clearInterval(setCorrectTime); + clearInterval(sendNodeReadout); + clearInterval(accelerometerInterval); + rsPort.close(); + }); + + instance.on("0", _ => { + main(); + }) + + + instance.on("2", _ => { + console.log("dailyReport, reportToSend, rvo_is_on", dailyReport, reportToSend, rvo_is_on, previous_rvo_is_on_value); + }) + + instance.on("1", 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(); + return; + } + else if (flowdata.data == "close") { + rsPort.close(); + return; + } + else if (flowdata.data == "clean") { + tasks = []; + return; + } + else if (flowdata.data == "buildtasks") { + //build & run + return; + } + else if (flowdata.data == "run") { + //durations = []; + + if (tasks.length == 0) { + + buildTasks(); + + if (rsPort.isOpen) { + interval = setInterval(runTasks, 100); + } + else { + instance.send(SEND_TO.debug, "port is not opened!!!"); + } + } + } + else { + //terminal data - object + //logger.debug("flowdata", flowdata.data); + + if (typeof flowdata.data === 'object') { + //logger.debug("dido", flowdata.data); + if (flowdata.data.hasOwnProperty("sender")) { + //data from dido_controller + if (flowdata.data.sender == "dido_controller") { + + if (flowdata.data.hasOwnProperty("cmd")) { + let cmd = flowdata.data.cmd; + + if (cmd == "buildTasks") { + clearInterval(interval); + + logger.debug("-->Cmd-mngr: BUILD TASKS"); + buildTasks(); + + //logger.debug("tasks:"); + //logger.debug(tasks); + + logger.debug("-->Cmd-mngr: RUN TASKS"); + interval = setInterval(runTasks, 5000); + } + else if (cmd == "reload_relays") { + loadRelaysData(flowdata.data.line); + + if (flowdata.data.dataChanged) { + if (!flowdata.data.value) { + reportOfflineNodeStatus(flowdata.data.line); + } + else { + reportOnlineNodeStatus(flowdata.data.line); + } + } + + } + else if (cmd == "rotary_switch_state") { + let value = flowdata.data.value; + + //state was changed + if (rotary_switch_state != value) { + if (value == "Off") { + //vyreportovat vsetky svietdla + reportOfflineNodeStatus(); + } + + rotary_switch_state = value; + } + } + 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) { + + // we send lux_sensor value to all nodes: + let params = getParams(PRIORITY_TYPES.node_broadcast); + + params.recipient = 2;//2 broadcast, address = 0 + params.address = 0xffffffff;//Broadcast + + let ba = longToByteArray(lux_sensor); + + params.byte3 = ba[1];//msb + params.byte4 = ba[0]; + params.timestamp = PRIORITY_TYPES.node_broadcast; + params.info = "run broadcast: Actual Lux level from cabinet"; + params.register = 95;//Actual Lux level from cabinet + params.rw = 1;//write + + tasks.push(params); + + //process profiles + turnOnOffLinesAccordingToLuxSensor(lux_sensor); + } + } + else if (cmd == "state_of_breaker") { + //istic linie + + breakerCounter--; + + let value = flowdata.data.value; + let line = parseInt(flowdata.data.line); + + let dataChanged = false; + if (state_of_breaker[line] != value) dataChanged = true; + + state_of_breaker[line] = value; + + let status = "OK"; + if (value == "Off") status = "NOK"; + + if (dataChanged) { + + if (relaysData.hasOwnProperty(line)) { + let tbname = relaysData[line].tbname; + + if (value == "Off") { + sendNotification("Cmd-mngr: onData", tbname, "circuit_breaker_was_turned_off_line", { line: line }, "", SEND_TO.tb, instance, "circuit_breaker"); + if (breakerCounter < 0) reportToSend["contactor"]["off"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + else { + sendNotification("Cmd-mngr: onData", tbname, "circuit_breaker_was_turned_on_line", { line: line }, "", SEND_TO.tb, instance, "circuit_breaker"); + if (breakerCounter < 0) reportToSend["contactor"]["on"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + + //report status liniu + sendTelemetry({ status: status }, tbname) + + //current value + if (value == "Off") reportOfflineNodeStatus(line); //vyreportovat vsetky svietidla na linii + } + + } + } + else { + logger.debug("undefined cmd", cmd); + } + } + } + + return; + } + + //data from worksys + if (flowdata.data.hasOwnProperty("topic")) { + + let data = getNested(flowdata.data, "content", "data"); + + //if we get temperature in senica from senica-prod01 + let temperature = getNested(flowdata.data, "content", "senica_temperature"); + + if (temperature !== undefined) { + temperatureInSenica = temperature; + return; + } + + if (data === undefined) { + console.log("Invalid rpc command came from platform"); + return; + } + + let command = data.params.command; + let method = data.method; + let profile = data.params.payload; + if (profile == undefined) profile = ""; + let entity = data.params.entities[0]; + let entity_type = entity.entity_type; + let tbname = entity.tb_name; + + instance.send(SEND_TO.debug, flowdata.data); + 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") { + + //let command = data.params.command; + let value = data.params.payload.value; + + if (command == "dimming") { + + let nodeWasFound = false; + let keys = Object.keys(nodesData); + + //logger.debug("-----", keys); + + 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); + + value = parseInt(value); + if (value > 0) value = value + 128; + + params.type = "node-onetime-write"; + params.tbname = tbname; + params.address = node; + params.register = 1; + params.recipient = 1; + params.byte4 = value; + params.rw = 1; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'set dimming from platform'; + //params.debug = true; + + //debug(params); + logger.debug("dimming", params); + + tasks.push(params); + + 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); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 1; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read dimming (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + //pridame aj vyreportovanie - vykon + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 76; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read Input Power (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + //pridame aj vyreportovanie - prud svietidla + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 75; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read Input Current (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + //pridame aj vyreportovanie - power faktor - ucinnik + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 77; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read power factor (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + }, 4000); + + nodeWasFound = true; + break; + } + } + + if (!nodeWasFound) { + logger.debug("set dimming from platform", "unable to find tbname", tbname); + } + } + else { + instance.send(SEND_TO.debug, "undefined command " + command); + logger.debug("undefined command", command); + } + + return; + } + 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++) { + let node = keys[i]; + if (tbname == nodesData[node].tbname) { + + 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"); + + //profil úspešne prijatý pre node č. xx + sendNotification("Cmd-mngr", tbname, "dimming_profile_was_processed_for_node", { node: node }, profile, SEND_TO.tb, instance); + + nodesData[node].processed = false; + nodesData[node].profile = profile; + + processNodeProfile(node); + }); + }); + } + } + } + else { + + instance.send(SEND_TO.debug, "unknown method " + method); + logger.debug("unknown method", method); + + return; + } + } + + //nastav profil linie z platformy + 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") { + + 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++) { + let line = keys[i]; + if (tbname == relaysData[line].tbname) { + //zmazeme tasky + 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) { + + //update profile + logger.debug("worksys - update relay profile done:", profile); + instance.send(SEND_TO.debug, "worksys - update relay profile done"); + + relaysData[line].profile = profile; + + loadRelaysData(line) + logger.debug("loadRelaysData DONE for line", line); + + buildTasks({ processLineProfiles: true, line: line }); + + sendNotification("Cmd-mngr: set profile from worksys", tbname, "switching_profile_was_processed_for_line", { line: line }, profile, SEND_TO.tb, instance); + }); + }); + break; + } + } + } + else if (method == "set_command") { + let value = data.params.payload.value; + + 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; + + 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"); + if (line != 0) reportToSend["contactor"]["off"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + else { + turnLine("on", line, "command received from platform"); + if (line != 0) reportToSend["contactor"]["on"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + } + } + else { + instance.send(SEND_TO.debug, "undefined method " + method); + logger.debug("undefined method", method); + } + + return; + } + else { + instance.send(SEND_TO.debug, "UNKNOW entity_type " + entity_type); + logger.debug("UNKNOW entity_type", entity_type); + } + return; + } + + //terminal + if (!rsPort.isOpen) await rsPort.open(); + + let params = flowdata.data.body; + if (params == undefined) { + //logger.debug("Cmd-mngr: flowdata.data.body is undefined"); + return; + } + + params.priority = PRIORITY_TYPES.terminal; + params.type = "cmd-terminal"; + params.tbname = ""; + params.timestamp = PRIORITY_TYPES.terminal; + params.addMinutesToTimestamp = 0;// do not repeat task!!! + params.debug = true; + + let timestamp = Date.now(); + params.refFlowdataKey = timestamp; + //params.refFlowdata = flowdata; + //refFlowdata = flowdata; + + //console.log("flowdata", flowdata); + + cleanUpRefFlowdataObj(); + + refFlowdataObj[timestamp] = flowdata; + + //fix + //params.address = params.adress; + logger.debug("received from terminal", params); + logger.debug("date/time:", new Date()); + logger.debug("tasks length:", tasks.length); + + //tasks = []; + + //add to tasks + tasks.push(params); + + } + } + }) + + + //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) + } + + + /** + * 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; + + RESTBuilder.make(function(builder) { + + if (!builder) return; + + builder.method('GET'); + builder.url('http://192.168.252.2:8004/gettime?projects_id=1'); + + builder.callback(function(err, response, output) { + + 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); + } + + }); + } + + } 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); + + } else { + //console.log("Read-only", stdout); + + 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]: [ + { + "ts": date, + "values": values + } + ] + } + + tbHandler.sendToTb(dataToTb, instance); + } + + + function calculateDuskDawn(date, line, duskOffset = 0, dawnOffset = 0) { + + if (date === undefined) date = new Date(); + + 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); + } + + //if(profile.dawn_lux_sensor == false) + { + if (profile.hasOwnProperty("dawn_astro_clock_offset")) dawn_astro_clock_offset = parseInt(profile.dawn_astro_clock_offset); + } + + } + + } catch (error) { + if (profilestr != "") { + logger.debug(profilestr); + logger.debug(error); + } + } + + 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; + } + + //Dimming, CCT + else if (register == 1) { + let brightness = 0; + let dimming = byte0; + if (dimming > 128) { + //dimming = -128; + brightness = dimming - 128; + } + + //cct + //Ak Byte3 == 1: CCT = (Byte2*256)+Byte1 + let cct; + if (byte3 == 1) cct = byte2 * 256 + byte1; + else cct = bytesToInt(bytes.slice(0, 3)); + + //cct podla auditu + + values["dimming"] = brightness; + return values; + } + + // + else if (register == 4) { + values["master_node_version"] = bytes[1] + "." + bytes[2]; + //logger.debug("FW Version", register, bytes); + } + + //Napätie + else if (register == 74) { + let voltage = (bytesToInt(bytes) * 0.1).toFixed(1); + values["voltage"] = Number(voltage); + } + + //Prúd + else if (register == 75) { + let current = bytesToInt(bytes); + values["current"] = current; + } + + //výkon + else if (register == 76) { + let power = (bytesToInt(bytes) * 0.1).toFixed(2); + values["power"] = Number(power); + } + + //účinník + else if (register == 77) { + let power_factor = Math.cos(bytesToInt(bytes) * 0.1 * (Math.PI / 180)).toFixed(2); + values["power_factor"] = Number(power_factor); + } + + //frekvencia + else if (register == 78) { + let frequency = (bytesToInt(bytes) * 0.1).toFixed(2); + values["frequency"] = Number(frequency); + } + + //energia + else if (register == 79) { + let energy = bytesToInt(bytes); + values["energy"] = energy / 1000; //energia v kWh -> delit 1000 + } + + //doba života + else if (register == 80) { + let lifetime = (bytesToInt(bytes) / 60).toFixed(2); + values["lifetime"] = Number(lifetime); + } + + //nastavenie profilu + else if (register == 8) { + let time_schedule_settings = bytesToInt(bytes); + values["time_schedule_settings"] = time_schedule_settings; + } + + //naklon - nateraz sa z nodu nevycitava! kvoli problemom s accelerometrom a vracanymi hodnotami, posielame temp a x y z vo funkcii accelerometerData() + else if (register == 84) { + values["temperature"] = byte3 >= 128 ? (byte3 - 128) * (-1) : byte3; + values["inclination_x"] = byte2 >= 128 ? (byte2 - 128) * (-1) : byte2; + values["inclination_y"] = byte1 >= 128 ? (byte1 - 128) * (-1) : byte1; + values["inclination_z"] = byte0 >= 128 ? (byte0 - 128) * (-1) : byte0; + } + + //FW verzia nodu + else if (register == 89) { + //formát: "Byte3: Byte2.Byte1 (Byte0)" + values["fw_version"] = byte3 + ":" + byte2 + "." + byte1 + "(" + byte0 + ")"; + } + + else if (register == 87 || register == 6 || register == 7) { + var d = new Date(); + d.setHours(byte3, byte2, 0, 0); + let timestamp = d.getTime(); + + //aktuálny čas + if (register == 87) values["actual_time"] = timestamp; + //čas súmraku + else if (register == 6) values["dusk_time"] = timestamp; + //čas úsvitu + else if (register == 7) values["dawn_time"] = timestamp; + } + + 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; + + } + + + function getObjectByTbValue(object, tbname) { + return object[Object.keys(object).find(key => object[key].tbname === tbname)]; + } + + + function isObject(item) { + return (typeof item === "object" && !Array.isArray(item) && item !== null); + } + + + // we fake data, that should be received from accelerometer, as they are a bit unreliable. (temperature, x,y,z) + function accelerometerData() { + + if (temperatureInSenica === null) return; + + //clone nodesData and relaysData objects + let nodesData_clone = JSON.parse(JSON.stringify(nodesData)); + let relaysData_clone = JSON.parse(JSON.stringify(relaysData)); + + for (const key in relaysData_clone) { + + const lineData = relaysData_clone[key]; + const lineNumber = lineData.line; + const contactor = lineData.contactor; + + if (lineNumber === 0) continue; + + if (contactor === 1) { + + let date = Date.now(); + + Object.keys(nodesData_clone).forEach((node, index) => { + + setTimeout(function() { + + if (nodesData_clone[node].line === lineNumber) { + + // NOTE: if status of luminaire is NOK or OFFLINE, we do not send data; + let status = nodesData_clone[node].status; + if (status === "OFFLINE" || !status) return; + + let x = null; + if (naklony.hasOwnProperty(node)) x = naklony[node].naklon; + if (x === null) x = 0; + + sendTelemetry({ temperature: Math.round(temperatureInSenica + 10 + Math.floor(Math.random() * 3)), inclination_x: x, inclination_y: 0, inclination_z: 0 }, nodesData_clone[node].tbname, date); + } + + }, (index + 1) * 500); + }) + + } + } + } + + +} // end of instance.export + diff --git a/RVO33/flow/code.js b/RVO33/flow/code.js new file mode 100755 index 0000000..63b31bf --- /dev/null +++ b/RVO33/flow/code.js @@ -0,0 +1,90 @@ +exports.id = 'code'; +exports.title = 'Code'; +exports.group = 'Common'; +exports.color = '#656D78'; +exports.input = true; +exports.output = 1; +exports.author = 'Peter Širka'; +exports.icon = 'code'; +exports.version = '1.2.0'; +exports.options = { outputs: 1, code: 'send(0, value);', keepmessage: true }; + +exports.html = `
+
+
+
@(Number of outputs)
+
@(Minimum is 1)
+
+
+
@(Code)
+
@(Keep message instance)
+
+`; + +exports.readme = `# Code + +This component executes custom JavaScript code as it is and it doesn't contain any secure scope. + +\`\`\`javascript +// value {Object} contains received data +// send(outputIndex, newValue) sends a new value +// error(value) sends an error +// instance {Object} a current component instance +// flowdata {Object} a current flowdata +// repository {Object} a current repository of flowdata +// Example: + +// send() can be execute multiple times +send(0, value); +\`\`\``; + +exports.install = function(instance) { + + var fn; + + instance.on('data', function(response) { + if (fn) { + try { + fn(response.data, instance, response, instance.options, response.repository, require); + } catch (e) { + response.data = e; + instance.throw(response); + } + } + }); + + instance.reconfigure = function() { + try { + if (instance.options.code) { + instance.status(''); + var code = 'var send = function(index, value) { if (options.keepmessage) { flowdata.data = value; instance.send2(index, flowdata); } else instance.send2(index, value);}; var error = function(err) { instance.throw(err); }; ' + instance.options.code; + fn = new Function('value', 'instance', 'flowdata', 'options', 'repository', 'require', code); + } else { + instance.status('Not configured', 'red'); + fn = null; + } + } catch (e) { + fn = null; + instance.error('Code: ' + e.message); + } + }; + + instance.on('options', instance.reconfigure); + instance.reconfigure(); +}; \ No newline at end of file diff --git a/RVO33/flow/comment.js b/RVO33/flow/comment.js new file mode 100755 index 0000000..1e0cd13 --- /dev/null +++ b/RVO33/flow/comment.js @@ -0,0 +1,11 @@ +exports.id = 'comment'; +exports.title = 'Comment'; +exports.group = 'Common'; +exports.color = '#704cff'; +exports.author = 'Martin Smola'; +exports.icon = 'comment'; +exports.traffic = false; +exports.version = '1.0.0'; +exports.readme = '# Comment'; + +exports.install = function() {}; diff --git a/RVO33/flow/count.js b/RVO33/flow/count.js new file mode 100755 index 0000000..fa92ee9 --- /dev/null +++ b/RVO33/flow/count.js @@ -0,0 +1,60 @@ +exports.id = 'count'; +exports.title = 'Count'; +exports.version = '1.0.1'; +exports.author = 'John Graves'; +exports.color = '#656D78'; +exports.icon = 'plus-square'; +exports.input = 2; +exports.output = 1; +exports.options = { increment: 1, initialvalue: 1 }; +exports.readme = `# Counter + +Counter Number of times called.`; + +exports.html = `
+
@(Initial Value)
+
@(Increment)
+

Example Video

+
`; + +exports.readme = `# Count + +This component counts the number of messages received. + +__Response:__ + +Integer value based on the initial value and increment settings. + +__Arguments:__ +- Initial Value: What number should be output on the receipt of the first message. +- Increment: What should the increment be for each following message received.`; + +exports.install = function(instance) { + + var count = 0; + var initialCall = true; + + instance.on('data', function(flowdata) { + var index = flowdata.index; + if (index) { + instance.debug('Reset Count.'); + count = instance.options.initialvalue; + initialCall = true; + } else { + // If this is the first time, set the value to 'initial value' + if(initialCall) { + initialCall = false; + count = instance.options.initialvalue; + } else + count = count+instance.options.increment; + instance.status('Count:' + count); + instance.send2(count); + } + }); + + instance.on('options', function() { + count = instance.options.initialvalue; + initialCall = true; + }); + +}; diff --git a/RVO33/flow/db_connector.js b/RVO33/flow/db_connector.js new file mode 100755 index 0000000..65ee94b --- /dev/null +++ b/RVO33/flow/db_connector.js @@ -0,0 +1,286 @@ +exports.id = 'db_connector'; +exports.title = 'DbConnector'; +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.html = `
+
+
+
DbConnector
+
+
+
`; + +exports.readme = `# read/write data to tables`; + +const instanceSendTo = { + debug: 0, + http_response: 1, +} + +const { promisifyBuilder, makeMapFromDbResult } = require('./helper/db_helper.js'); + +function extractWhereParams(params) +{ + let name = params[0]; + let operator = '='; + let value = params[1]; + + if(params.length == 3) + { + operator = params[1]; + value = params[2]; + } + + return {name: name, operator: operator, value: value}; +} + +exports.install = function(instance) { + + let refFlowdata = null;//holds reference to httprequest flowdata + + instance.on("close", () => { + + }) + + + instance.on("data", async function(flowdata) { + + let params = flowdata.data.body; + console.log("DbConnector", params); + + refFlowdata = flowdata; + + if(refFlowdata != undefined) + { + //make http response + let responseObj = {}; + responseObj["type"] = "SUCESS"; + + try{ + + let table = params.table; + let action = params.action; + + + if(params.data != undefined) + { + let className = params.data.className; + + if(className == "SqlQueryBuilder") + { + let type = params.data.type; + + console.log("SqlQueryBuilder---->", params.data); + + if(type == "SELECT") + { + let table = params.data.queryData.tables[0].table; + + const db = TABLE(table); + var builder = db.find(); + + let result = await promisifyBuilder(builder); + + let response = {}; + response["result"] = result; + response["success"] = true; + + responseObj["data"] = response; + + //console.log(responseObj); + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + } + + return; + } + } + + + console.log("db_connector---->", table, action); + + //actions: read, replace, insert, delete, update... + + if(action == "read") + { + const db = TABLE(params.table); + + //where builder.where('age', '<', 15); + //builder.where('id', 3403); + + var builder = db.find(); + + //https://docs.totaljs.com/latest/en.html#api~DatabaseBuilder~builder.where + if(params.hasOwnProperty("where")) + { + //optionalCan contain "=", "<=", "<", ">=", ">". + //Default value: '=' + + //1.["production_line", 1] + //2. ["or", ["production_line", 1], ["production_line", 2], "end"] + + if (Array.isArray(params.where)) { + + let multipleConditions = false; + + if(params.where[0] == "or") multipleConditions = true; + if (Array.isArray(params.where[0])) multipleConditions = true; + + if(multipleConditions) + { + + for(var i = 0; i < params.where.length; i++) + { + const item = params.where[i]; + + if(item === "or") builder.or(); + + if (Array.isArray(item)) + { + const { name, operator, value } = extractWhereParams(item); + builder.where(name, operator, value); + } + + if(item === "end") builder.end(); + + } + + } + else + { + const { name, operator, value } = extractWhereParams(params.where); + builder.where(name, operator, value); + } + + } + + /* + if(params.where.length >=2 ) + { + let name = params.where[0]; + let operator = '='; + let value = params.where[1]; + + if(params.where.length == 3) + { + operator = params.where[1]; + value = params.where[2]; + } + + builder.where(name, operator, value); + } + */ + } + + if(params.hasOwnProperty("between")) + { + builder.between(params.between[0], params.between[1], params.between[2]); + } + + let response = await promisifyBuilder(builder); + responseObj["data"] = response; + + //console.log(responseObj); + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + + return; + } + + if(action == "delete") + { + + } + + + if(action == "update") + { + //! data receiving from terminal (params) + // { + // hostname: 'localhost', + // table: 'settings', + // action: 'update', + // body: { + // rvo_name: 'terrrr', + // lang: 'en', + // temperature_adress: '28.427B45920702', + // latitude: 48.70826502, + // longitude: 17.28455203, + // mqtt_host: '192.168.252.4', + // mqtt_clientid: 'showroom_test_panel_led', + // mqtt_username: 'xmRd6RJxW53WZe4vMFLU', + // mqtt_port: 1883, + // maintanace_mode: false + // } + // } + const tableToModify = TABLE(params.table); + const newValues = params.body; + + tableToModify.modify(newValues).make(function(builder) { + + builder.callback(function(err, response) { + + if(!err) + { + responseObj["data"] = response; + responseObj["tableUpdated"] = true; + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + } + }); + }); + + } + + if(action == "replace") + { + //truncate table + const db = TABLE(params.table); + var builder = db.remove(); + db.clean(); + + //insert data + let data = params.data; + + for(let i = 0; i < data.length; i++) + { + //console.log(data[i]); + db.insert(data[i]); + } + + console.log("insert done"); + + let responseObj = {}; + responseObj["type"] = "SUCESS"; + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + + + } + + + + } catch (error) { + //console.log(error); + responseObj["type"] = "ERROR"; + responseObj["message"] = error; + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + } + } + }) +} + + diff --git a/RVO33/flow/db_init.js b/RVO33/flow/db_init.js new file mode 100755 index 0000000..b399878 --- /dev/null +++ b/RVO33/flow/db_init.js @@ -0,0 +1,113 @@ +exports.id = 'db_init'; +exports.title = 'DB Initialization'; +exports.group = 'Worksys'; +exports.color = '#888600'; +exports.version = '1.0.2'; +exports.icon = 'sign-out'; +exports.output = 2; + +exports.readme = ` + # DB initialization +`; + +const { promisifyBuilder, makeMapFromDbResult } = require('./helper/db_helper.js'); +const { initNotification } = require('./helper/notification_reporter'); +const errorHandler = require('./helper/ErrorToServiceHandler'); +const total_energy = require('../databases/total_energy'); + +const SEND_TO = { + db_init: 0, + infoSender: 1 +}; + + +exports.install = async function(instance) { + const dbNodes = TABLE("nodes"); + const dbRelays = TABLE("relays"); + const dbSettings = TABLE("settings"); + 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 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.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"]; + Object.keys(dbs.nodesData).forEach(node => dbs.nodesData[node].readout = {}) + + let rvo_number = responseSettings[0]["rvo_name"].match(/\D+(\d{1,2})_/)[1]; + + dbs.settings = { + edge_fw_version: "2025-10-08", //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"], + phases: responseSettings[0]["phases"], + cloud_topic: responseSettings[0]["cloud_topic"], + has_main_switch: responseSettings[0]["has_main_switch"], + daily_report: responseSettings[0]["daily_report"], + send_changed_node_numbers: responseSettings[0]["send_changed_node_numbers"], + rvo_number: rvo_number, + + //dynamic values + masterNodeIsResponding: true, //cmd_manager + maintenance_mode: false, + } + + + dbs.settings.energy_to_switch_lamps = total_energy[rvo_number]; + if (dbs.settings.energy_to_switch_lamps === undefined) console.log('=============== db_init.js: energy_to_switch_lamps is undefined'); + + FLOW.dbLoaded = true; + errorHandler.setProjectId(dbs.settings.project_id); + initNotification(); + + //APP START - send to data services + const toService = { + id: dbs.settings.project_id, + name: dbs.settings.rvo_name, + fw_version: dbs.settings.edge_fw_version, + startdate: new Date().toISOString().slice(0, 19).replace('T', ' '), + js_error: "", + error_message: "" + }; + + instance.send(SEND_TO.infoSender, toService); + console.log("----------------> START - message send to service", toService); + + setTimeout(() => { + console.log("DB_INIT - data loaded"); + instance.send(SEND_TO.db_init, "_") + }, 5000) + +}; + diff --git a/RVO33/flow/debug.js b/RVO33/flow/debug.js new file mode 100755 index 0000000..00cb259 --- /dev/null +++ b/RVO33/flow/debug.js @@ -0,0 +1,100 @@ +exports.id = 'debug'; +exports.title = 'Debug'; +exports.author = 'Peter Širka'; +exports.color = '#967ADC'; +exports.click = true; +exports.input = true; +exports.icon = 'bug'; +exports.version = '2.0.4'; +exports.options = { enabled: true, repository: false, type: 'data' }; +exports.readme = `# Debug + +Prints data to the debug tab.`; + +exports.html = `
+
+
+
@(Output type)
+
@(Path to the property (leave empty to show the whole data object))
+
@(A group name)
+
@(Enabled)
+
+
+
`; + +exports.install = function(instance) { + + instance.on('data', function(response) { + if (instance.options.enabled) { + + var opt = instance.options; + var rep = response.repository; + var val = response.data; + var id = response.id; + + switch (instance.options.type){ + case 'both': + var data = {}; + data.repository = rep; + data.data = val instanceof Error ? { error: val.message, stack: val.stack } : val; + instance.debug(safeparse(opt.property ? U.get(data, opt.property) : data), undefined, opt.group, id); + break; + case 'repository': + instance.debug(safeparse(opt.property ? U.get(rep, opt.property) : rep), undefined, opt.group, id); + break; + case 'data': + default: + if (val instanceof Error) + instance.debug({ error: val.message, stack: val.stack }, undefined, opt.group, id); + else + instance.debug(safeparse(opt.property ? U.get(val, opt.property) : val), undefined, opt.group, id); + break; + } + } + }); + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + instance.save(); + }); + + instance.on('options', function() { + instance.custom.status(); + }); + + instance.custom.status = function() { + instance.status(instance.options.enabled ? 'Enabled' : 'Disabled'); + }; + + instance.custom.status(); + + function safeparse(o) { + + if (o instanceof Buffer) + return o; + + if (o === undefined) + return 'undefined'; + + if (o === null) + return 'null'; + + var cache = []; + var str = JSON.stringify(o, function(key, value) { + if (typeof value === 'object' && value !== null) { + if (cache.indexOf(value) !== -1) { + try { + return JSON.parse(JSON.stringify(value)); + } catch (error) { + return; + } + } + cache.push(value); + } + return value; + }); + cache = null; + return JSON.parse(str); + } +}; diff --git a/RVO33/flow/designer.json b/RVO33/flow/designer.json new file mode 100755 index 0000000..580f5a3 --- /dev/null +++ b/RVO33/flow/designer.json @@ -0,0 +1,3102 @@ +{ + "tabs": [ + { + "name": "MAIN PUSH", + "linker": "main-push", + "id": "1612772287426", + "index": 0 + }, + { + "name": "CMD manager", + "linker": "cmd-manager", + "id": "1615551125555", + "index": 1 + }, + { + "name": "Devices", + "linker": "devices", + "id": "1611921777196", + "index": 2 + } + ], + "components": [ + { + "id": "1611951142547", + "component": "debug", + "tab": "1611921777196", + "name": "ERROR", + "x": 598, + "y": 60, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#DA4453", + "notes": "" + }, + { + "id": "1612776786008", + "component": "wsmqttpublish", + "tab": "1612772287426", + "name": "WS MQTT publish", + "x": 281.75, + "y": 174, + "connections": { + "0": [ + { + "index": "0", + "id": "1615551060773" + } + ], + "1": [ + { + "index": "0", + "id": "1618300858252" + }, + { + "index": "0", + "id": "1618558465485" + } + ], + "2": [ + { + "index": "0", + "id": "1634303685503" + } + ], + "3": [ + { + "index": "0", + "id": "1731068754606" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Connected", + "color": "green" + }, + "options": { + "username": "", + "clientid": "", + "port": "1883", + "host": "" + }, + "color": "#888600", + "notes": "" + }, + { + "id": "1612778461252", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "tb-push", + "x": 72.75, + "y": 328, + "connections": { + "0": [ + { + "index": "0", + "id": "1612783322136" + }, + { + "index": "1", + "id": "1612776786008" + }, + { + "index": "0", + "id": "1731068754606" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1612783322136", + "component": "debug", + "tab": "1612772287426", + "name": "to TB", + "x": 283.75, + "y": 324, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615551060773", + "component": "debug", + "tab": "1612772287426", + "name": "errors from MQTT Broker", + "x": 594, + "y": 57, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#DA4453", + "notes": "" + }, + { + "id": "1615563373927", + "component": "debug", + "tab": "1615551125555", + "name": "Debug", + "x": 755, + "y": 155, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#DA4453", + "notes": "" + }, + { + "id": "1615566865233", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "tb-push", + "x": 755, + "y": 248, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1615798582262", + "component": "debug", + "tab": "1615551125555", + "name": "CMD_debug", + "x": 755, + "y": 346, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615802995322", + "component": "debug", + "tab": "1611921777196", + "name": "Debug", + "x": 596.8833312988281, + "y": 566.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Disabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": false + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615809128443", + "component": "debug", + "tab": "1611921777196", + "name": "tempToTb", + "x": 595.8833312988281, + "y": 658.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615809595184", + "component": "virtualwireout", + "tab": "1611921777196", + "name": "tb-push", + "x": 597.8833312988281, + "y": 377.25, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1616165795916", + "component": "httproute", + "tab": "1615551125555", + "name": "POST /terminal", + "x": 135, + "y": 547, + "connections": { + "0": [ + { + "index": "0", + "id": "1684060205000" + }, + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Listening", + "color": "green" + }, + "options": { + "timeout": 10, + "cachepolicy": 0, + "cacheexpire": "5 minutes", + "size": 5, + "url": "/terminal", + "method": "POST", + "name": "", + "flags": [ + "id:1616165795916", + "post", + 10000 + ], + "emptyresponse": false + }, + "color": "#5D9CEC", + "notes": "### Configuration\n\n- __POST /terminal__\n- flags: \n- maximum request data length: __5 kB__\n- empty response: __false__\n- cache policy: __no cache__\n- cache expire: __5 minutes__", + "cloning": false + }, + { + "id": "1616165824813", + "component": "httpresponse", + "tab": "1615551125555", + "name": "HTTP Response", + "x": 753, + "y": 423, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "json" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1617104731852", + "component": "debug", + "tab": "1615551125555", + "name": "DIDO_Debug", + "x": 669, + "y": 1040, + "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": "turnOff line", + "x": 133, + "y": 1161, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "object", + "data": "{line: 3, command: \"turnOff\", force: true}" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1617115013095", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "tb-push", + "x": 669, + "y": 1150, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1617284749681", + "component": "trigger", + "tab": "1615551125555", + "name": "update profile / node", + "x": 112, + "y": 208, + "connections": { + "0": [ + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "data": "profile_nodes", + "datatype": "string" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1618235171399", + "component": "trigger", + "tab": "1615551125555", + "name": "tun tasks", + "x": 184, + "y": 279, + "connections": { + "0": [ + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "data": "run" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1618300858252", + "component": "debug", + "tab": "1612772287426", + "name": "wsmqtt-exit1", + "x": 597.8833312988281, + "y": 149, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1618393583970", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "to-cmd-manager", + "x": 668.8833312988281, + "y": 1269, + "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": 132.88333129882812, + "y": 367, + "connections": { + "0": [ + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "platform-rpc-call", + "color": "gray" + }, + "options": { + "wirename": "platform-rpc-call" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1618393759854", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "cmd_to_dido", + "x": 119.88333129882812, + "y": 1007, + "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": 752.8833312988281, + "y": 527, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "cmd_to_dido", + "color": "gray" + }, + "options": { + "wirename": "cmd_to_dido" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1618558465485", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "platform-rpc-call", + "x": 597.8833312988281, + "y": 247, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "platform-rpc-call", + "color": "gray" + }, + "options": { + "wirename": "platform-rpc-call" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1618572059773", + "component": "trigger", + "tab": "1615551125555", + "name": "turnOn line", + "x": 132, + "y": 1085, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "data": "{line: 1, command: \"turnOn\", force: true}", + "datatype": "object" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1619515097737", + "component": "cmd_manager", + "tab": "1615551125555", + "name": "CMD Manager", + "x": 452.1091003417969, + "y": 341.05455017089844, + "connections": { + "0": [ + { + "index": "0", + "id": "1615563373927" + } + ], + "1": [ + { + "index": "0", + "id": "1615566865233" + }, + { + "index": "0", + "id": "1615798582262" + } + ], + "2": [ + { + "index": "0", + "id": "1616165824813" + } + ], + "3": [ + { + "index": "0", + "id": "1618393827655" + } + ], + "4": [ + { + "index": "0", + "id": "1635936391935" + } + ], + "5": [ + { + "index": "0", + "id": "1757006030239" + }, + { + "index": "0", + "id": "1757006060377" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1619605019281", + "component": "httproute", + "tab": "1615551125555", + "name": "GET db", + "x": 173, + "y": 653, + "connections": { + "0": [ + { + "index": "0", + "id": "1684060205000" + }, + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Listening", + "color": "green" + }, + "options": { + "timeout": 5, + "cachepolicy": 0, + "cacheexpire": "5 minutes", + "size": 5, + "url": "/db", + "method": "GET", + "name": "", + "flags": [ + "id:1619605019281", + "get", + 5000 + ] + }, + "color": "#5D9CEC", + "notes": "### Configuration\n\n- __GET /db__\n- flags: undefined\n- maximum request data length: __5 kB__\n- empty response: __undefined__\n- cache policy: __no cache__\n- cache expire: __5 minutes__", + "cloning": false + }, + { + "id": "1619784672383", + "component": "trigger", + "tab": "1615551125555", + "name": "turnOnAlarm", + "x": 120, + "y": 1234, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "object", + "data": "{command: \"turnOnAlarm\"}" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1619784812964", + "component": "trigger", + "tab": "1615551125555", + "name": "turnOffAlarm", + "x": 118, + "y": 1307, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "object", + "data": "{command: \"turnOffAlarm\"}" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1621340721628", + "component": "virtualwireout", + "tab": "1611921777196", + "name": "modbus_to_dido", + "x": 599, + "y": 471, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "modbus_to_dido", + "color": "gray" + }, + "options": { + "wirename": "modbus_to_dido" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1622640022885", + "component": "httproute", + "tab": "1615551125555", + "name": "POST /db_connector", + "x": 98, + "y": 1586, + "connections": { + "0": [ + { + "index": "0", + "id": "1622640073521" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Listening", + "color": "green" + }, + "options": { + "timeout": 5, + "cachepolicy": 0, + "cacheexpire": "5 minutes", + "size": 5, + "url": "/db_connector", + "method": "POST", + "flags": [ + "id:1622640022885", + "post", + 5000 + ] + }, + "color": "#5D9CEC", + "notes": "### Configuration\n\n- __POST /db_connector__\n- flags: \n- maximum request data length: __5 kB__\n- empty response: __undefined__\n- cache policy: __no cache__\n- cache expire: __5 minutes__", + "cloning": false + }, + { + "id": "1622640073521", + "component": "db_connector", + "tab": "1615551125555", + "name": "DbConnector", + "x": 372, + "y": 1572, + "connections": { + "1": [ + { + "index": "0", + "id": "1622641420685" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "edge": "undefined" + }, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1622641420685", + "component": "httpresponse", + "tab": "1615551125555", + "name": "HTTP Response", + "x": 596, + "y": 1586, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1634303504177", + "component": "monitormemory", + "tab": "1612772287426", + "name": "RAM", + "x": 69.88333129882812, + "y": 888.5, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465281992" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "858.88 MB / 985.68 MB", + "color": "gray" + }, + "options": { + "enabled": true, + "interval": 30000 + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1634303533779", + "component": "monitordisk", + "tab": "1612772287426", + "name": "disk", + "x": 70.88333129882812, + "y": 982.5, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465821120" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "5.78 GB / 7.26 GB", + "color": "gray" + }, + "options": { + "enabled": true, + "path": "/", + "interval": 30000 + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1634303595494", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "send-to-services", + "x": 51.883331298828125, + "y": 1400.5, + "connections": { + "0": [ + { + "index": "0", + "id": "1634463186563" + }, + { + "index": "1", + "id": "1634488120710" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1634303602169", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "send-to-services", + "x": 426.8833312988281, + "y": 878.5, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1634303685503", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "send-to-services", + "x": 600.8833312988281, + "y": 341.5, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1634303743260", + "component": "httprequest", + "tab": "1612772287426", + "name": "192.168.252.2:8004/sentmessage", + "reference": "", + "x": 506.8833312988281, + "y": 1331.7333374023438, + "connections": { + "0": [ + { + "index": "0", + "id": "1635327431236" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "url": "http://192.168.252.2:8004/sentmessage", + "method": "POST", + "stringify": "json" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1634463186563", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 305.75, + "y": 1442, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634464580289", + "component": "code", + "tab": "1612772287426", + "name": "Code", + "x": 245, + "y": 787, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465243324" + }, + { + "index": "0", + "id": "1634303602169" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "keepmessage": true, + "code": "let response = {};\nresponse.cpu = value.cpu;\nresponse.uptime = value.uptime;\n\nsend(0, response);", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1634465243324", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 428, + "y": 784, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634465281992", + "component": "code", + "tab": "1612772287426", + "name": "Code", + "x": 245, + "y": 884, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465338103" + }, + { + "index": "0", + "id": "1634303602169" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "keepmessage": true, + "code": "value.sender = \"ram\";\n\nlet response = {};\n\nresponse.memory_total = Math.round(value.total / (1024 ** 2));\nresponse.memory_free = Math.round(value.free / (1024 ** 2));\nresponse.memory_used = Math.round(value.used / (1024 ** 2));\n\nsend(0, response);", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1634465338103", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 429, + "y": 976, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634465821120", + "component": "code", + "tab": "1612772287426", + "name": "Code", + "x": 245, + "y": 978, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465892500" + }, + { + "index": "0", + "id": "1634303602169" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "keepmessage": true, + "code": "value.sender = \"hdd\";\n\nlet response = {};\n\nresponse.hdd_total = Math.round(value.total / (1024 ** 2));\nresponse.hdd_free = Math.round(value.free / (1024 ** 2));\nresponse.hdd_used = Math.round(value.used / (1024 ** 2));\n\nsend(0, response);", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1634465892500", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 432, + "y": 1068, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634484067516", + "component": "debug", + "tab": "1612772287426", + "name": "Send info", + "x": 513, + "y": 1441, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634488120710", + "component": "infosender", + "tab": "1612772287426", + "name": "Info sender", + "x": 301, + "y": 1336, + "connections": { + "0": [ + { + "index": "0", + "id": "1634484067516" + }, + { + "index": "0", + "id": "1634303743260" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "edge": "undefined" + }, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1635327431236", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 837.8833312988281, + "y": 1325.5, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1635936391935", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "send-to-services", + "x": 753, + "y": 623, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1637069803394", + "component": "monitorconsumption", + "tab": "1612772287426", + "name": "CPU", + "x": 69, + "y": 791, + "connections": { + "0": [ + { + "index": "0", + "id": "1634464580289" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "49.2% / 69.91 MB", + "color": "gray" + }, + "options": { + "monitorfiles": true, + "monitorconnections": true, + "monitorsize": true, + "monitorconsumption": true, + "enabled": true, + "interval": 30000 + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1683664161036", + "component": "debug", + "tab": "1615551125555", + "name": "CMDtoDIDO", + "x": 392, + "y": 1012, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1683981346282", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "from-dido-controller", + "x": 112, + "y": 459, + "connections": { + "0": [ + { + "index": "0", + "id": "1684055037116" + }, + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "from-dido-controller", + "color": "gray" + }, + "options": { + "wirename": "from-dido-controller" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1684055037116", + "component": "debug", + "tab": "1615551125555", + "name": "from dido to cmd", + "x": 451, + "y": 532, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1684060205000", + "component": "debug", + "tab": "1615551125555", + "name": "HTTP routes", + "x": 450, + "y": 639, + "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": "MDBToDido", + "x": 598, + "y": 147, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1699963668903", + "component": "dido_controller", + "tab": "1615551125555", + "name": "DIDO_Controller", + "x": 397, + "y": 1131, + "connections": { + "0": [ + { + "index": "0", + "id": "1617104731852" + } + ], + "1": [ + { + "index": "0", + "id": "1617104731852" + }, + { + "index": "0", + "id": "1617115013095" + } + ], + "2": [ + { + "index": "0", + "id": "1618393583970" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "edge": "undefined" + }, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1699964678894", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "modbus_to_dido", + "x": 96, + "y": 924, + "connections": { + "0": [ + { + "index": "0", + "id": "1699963668903" + }, + { + "index": "0", + "id": "1699964793925" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "modbus_to_dido", + "color": "gray" + }, + "options": { + "wirename": "modbus_to_dido" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1699964793925", + "component": "debug", + "tab": "1615551125555", + "name": "modbusToDido", + "x": 388, + "y": 920, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1699965957410", + "component": "modbus_reader", + "tab": "1611921777196", + "name": "Modbus reader", + "x": 232, + "y": 175, + "connections": { + "0": [ + { + "index": "0", + "id": "1611951142547" + } + ], + "1": [ + { + "index": "0", + "id": "1621340721628" + }, + { + "index": "0", + "id": "1684179110403" + }, + { + "index": "0", + "id": "1717441414646" + } + ], + "2": [ + { + "index": "0", + "id": "1615809595184" + }, + { + "index": "0", + "id": "1714752862828" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1700411878636", + "component": "thermometer", + "tab": "1611921777196", + "name": "Thermometer", + "x": 234.75, + "y": 444, + "connections": { + "0": [ + { + "index": "0", + "id": "1615802995322" + } + ], + "1": [ + { + "index": "0", + "id": "1615809595184" + }, + { + "index": "0", + "id": "1615809128443" + } + ], + "2": [ + { + "index": "0", + "id": "1621340721628" + }, + { + "index": "0", + "id": "1732889185927" + }, + { + "index": "0", + "id": "1717441414646" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#5CB36D", + "notes": "" + }, + { + "id": "1714752862828", + "component": "debug", + "tab": "1611921777196", + "name": "MDBToTb", + "x": 766, + "y": 324, + "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": 764.0833282470703, + "y": 222, + "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\telse if(value.status === \"NOK-thermometer\")\n\t{\n\t\tsend(0, {\"thermometer\": \"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\telse if(value.values.hasOwnProperty(\"temperature\"))\n\t{\n\t\tsend(0, {\"thermometer\": \"OK\"});\n\t}\n}", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1717442627834", + "component": "debug", + "tab": "1611921777196", + "name": "modbus service", + "x": 966.0833282470703, + "y": 165, + "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": 968.0833282470703, + "y": 268, + "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": 88.75, + "y": 1685, + "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": 296, + "y": 1671, + "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\", \"Flow has been restarted\", \"Node db has changed\"]", + "types": "[\"emergency\", \"critical\", \"error\", \"alert\"]", + "name": "" + }, + "color": "#30E193", + "notes": "" + }, + { + "id": "1718016073501", + "component": "httprequest", + "tab": "1612772287426", + "name": "http://192.168.252.2:8004/slack", + "x": 495, + "y": 1753, + "connections": { + "0": [ + { + "index": "0", + "id": "1718016086212" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "url": "http://192.168.252.2:8004/slack", + "method": "POST", + "stringify": "json" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1718016086212", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 832, + "y": 1664, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "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": 87, + "y": 1591, + "connections": { + "0": [ + { + "index": "0", + "id": "1718016052341" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "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\": \"\" } } } ] }", + "datatype": "object" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1729855334955", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "platform-rpc-call", + "x": 599.9333343505859, + "y": 541.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "platform-rpc-call", + "color": "gray" + }, + "options": { + "wirename": "platform-rpc-call" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1729855371093", + "component": "debug", + "tab": "1612772287426", + "name": "rpc cloud", + "x": 601.9333343505859, + "y": 440.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1731068658334", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 75.75, + "y": 184, + "connections": { + "0": [ + { + "index": "0", + "id": "1612776786008" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731068754606", + "component": "cloudmqttconnect", + "tab": "1612772287426", + "name": "MQTT to senica-prod01", + "x": 284.75, + "y": 452, + "connections": { + "1": [ + { + "index": "0", + "id": "1729855371093" + }, + { + "index": "0", + "id": "1729855334955" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Connected", + "color": "green" + }, + "options": { + "username": "", + "clientid": "", + "port": "2764", + "host": "192.168.252.2", + "topic": "" + }, + "color": "#888600", + "notes": "" + }, + { + "id": "1731069001548", + "component": "db_init", + "tab": "1612772287426", + "name": "DB Initialization", + "x": 1003.75, + "y": 240.25, + "connections": { + "0": [ + { + "index": "0", + "id": "1731069033416" + } + ], + "1": [ + { + "index": "0", + "id": "1747561603739" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#888600", + "notes": "" + }, + { + "id": "1731069033416", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "db-init", + "x": 1244.75, + "y": 233.25, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069059135", + "component": "showdb", + "tab": "1612772287426", + "name": "Show db data", + "x": 1186.75, + "y": 821.25, + "connections": { + "0": [ + { + "index": "0", + "id": "1731069079243" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#888600", + "notes": "" + }, + { + "id": "1731069079243", + "component": "debug", + "tab": "1612772287426", + "name": "dbData", + "x": 1390.75, + "y": 870.25, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1731069116691", + "component": "trigger", + "tab": "1612772287426", + "name": "settings", + "x": 934.75, + "y": 669.75, + "connections": { + "0": [ + { + "index": "0", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069131637", + "component": "trigger", + "tab": "1612772287426", + "name": "relaysData", + "x": 876.75, + "y": 733.75, + "connections": { + "0": [ + { + "index": "1", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069137374", + "component": "trigger", + "tab": "1612772287426", + "name": "nodesData", + "x": 852.75, + "y": 794.75, + "connections": { + "0": [ + { + "index": "2", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069179846", + "component": "trigger", + "tab": "1612772287426", + "name": "pinsData", + "x": 850.75, + "y": 861.75, + "connections": { + "0": [ + { + "index": "3", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069192937", + "component": "trigger", + "tab": "1612772287426", + "name": "sample data", + "x": 857.75, + "y": 928.75, + "connections": { + "0": [ + { + "index": "4", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069264443", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 63.75, + "y": 1279, + "connections": { + "0": [ + { + "index": "0", + "id": "1634488120710" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069334626", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "db-init", + "x": 172.88333129882812, + "y": 129, + "connections": { + "0": [ + { + "index": "0", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069548145", + "component": "virtualwirein", + "tab": "1611921777196", + "name": "db-init", + "x": 46.75, + "y": 192, + "connections": { + "0": [ + { + "index": "0", + "id": "1699965957410" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069567152", + "component": "virtualwirein", + "tab": "1611921777196", + "name": "db-init", + "x": 44.75, + "y": 465, + "connections": { + "0": [ + { + "index": "0", + "id": "1700411878636" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731070156936", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "db-init", + "x": 126.88333129882812, + "y": 1377, + "connections": { + "0": [ + { + "index": "2", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731234189516", + "component": "trigger", + "tab": "1612772287426", + "name": "monitor.txt", + "x": 882.75, + "y": 991.75, + "connections": { + "0": [ + { + "index": "5", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731234189551", + "component": "trigger", + "tab": "1612772287426", + "name": "err.txt", + "x": 904.75, + "y": 1053.75, + "connections": { + "0": [ + { + "index": "6", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1732700042559", + "component": "nodesdb_change_check", + "tab": "1612772287426", + "name": "Nodes DB change check", + "x": 266.8833312988281, + "y": 1980.2333984375, + "connections": { + "0": [ + { + "index": "0", + "id": "1732700071298" + }, + { + "index": "0", + "id": "1732700642917" + } + ], + "1": [ + { + "index": "0", + "id": "1759958914348" + }, + { + "index": "0", + "id": "1759959003114" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#888600", + "notes": "" + }, + { + "id": "1732700057052", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 76.75, + "y": 1988, + "connections": { + "0": [ + { + "index": "0", + "id": "1732700042559" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1732700071298", + "component": "debug", + "tab": "1612772287426", + "name": "nodesChange", + "x": 571.8833312988281, + "y": 2018.2333984375, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1732700642917", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "tb-push", + "x": 567.8833312988281, + "y": 1933, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1732889185927", + "component": "debug", + "tab": "1611921777196", + "name": "tempToDido", + "x": 594.8833312988281, + "y": 753, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1733574412965", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 72.75, + "y": 474, + "connections": { + "0": [ + { + "index": "1", + "id": "1731068754606" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1747561603739", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "send-to-services", + "x": 1243.8833312988281, + "y": 334.5, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1747562867845", + "component": "comment", + "tab": "1612772287426", + "name": "FLOW STARTING POINT", + "x": 1003.5666656494141, + "y": 178, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#704cff", + "notes": "" + }, + { + "id": "1749211698385", + "component": "trigger", + "tab": "1612772287426", + "name": "deviceStatus", + "x": 911.75, + "y": 1116.75, + "connections": { + "0": [ + { + "index": "7", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1757006030239", + "component": "httprequest", + "tab": "1615551125555", + "name": "192.168.252.2:8015/daily_report", + "x": 756.5666656494141, + "y": 715.4499969482422, + "connections": { + "0": [ + { + "index": "0", + "id": "1757006045804" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "stringify": "json", + "method": "POST", + "url": "http://192.168.252.2:8015/daily_report" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1757006045804", + "component": "debug", + "tab": "1615551125555", + "name": "ddd", + "x": 1091.566665649414, + "y": 711.4499969482422, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1757006060377", + "component": "debug", + "tab": "1615551125555", + "name": "reportDebug", + "x": 749.5666656494141, + "y": 799.4499969482422, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1759958914348", + "component": "httprequest", + "tab": "1612772287426", + "name": "http://192.168.252.2:8015/node_numbers", + "x": 571, + "y": 2111, + "connections": { + "0": [ + { + "index": "0", + "id": "1759958927094" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "stringify": "json", + "method": "POST", + "url": "http://192.168.252.2:8015/node_numbers" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1759958927094", + "component": "debug", + "tab": "1612772287426", + "name": "nodesChangeCloud", + "x": 951.8833312988281, + "y": 2109.2333984375, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1759959003114", + "component": "debug", + "tab": "1612772287426", + "name": "nodeChangeCloud1", + "x": 574, + "y": 2218, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1760020290879", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 84.75, + "y": 1787, + "connections": { + "0": [ + { + "index": "1", + "id": "1718016052341" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + } + ], + "version": 615 +} diff --git a/RVO33/flow/dido_controller.js b/RVO33/flow/dido_controller.js new file mode 100755 index 0000000..d16fb19 --- /dev/null +++ b/RVO33/flow/dido_controller.js @@ -0,0 +1,1486 @@ +exports.id = 'dido_controller'; +exports.title = 'DIDO_Controller'; +exports.version = '2.0.0'; +exports.group = 'Worksys'; +exports.color = '#2134B0'; +exports.input = 3; +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 + +state_of_main_switch - reportovat stav hlaveho istica : 0-> off 1-> on +rotary_switch_state - sem by sa mal reportovat stav vstupov manual a auto pola nasledovnej logiky: Manual = 1 a Auto = 0 -> Manu +Manual = 0 a Auto = 0 -> Off, Manual = 0 a Auto = 1 -> Automatic + +door_condition - pin 6, dverový kontakt -> 1 -> vyreportuje Closed, 0 -> vyreportuje Ope +twilight_sensor - hodnotu, ktoru vracia ten analogovy vstup (17) treba poslat sem ako float number. Zrejme tu potom pridame nejaky koeficient prevodu na luxy + +Na kazdu liniu +state_of_breaker - podla indexu istica sa reportuje jeho stav, teda istic na liniu 1: 0-> off, 1-> on +state_of_contactor - podla indexu stkaca sa reportuje jeho stav, teda stykac 1 na liniu 1: 0-> off, 1-> on +*/ + +const { errLogger, logger, monitor } = require('./helper/logger'); +const SerialPort = require('serialport'); +const WebSocket = require('ws'); +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 errorHandler = require('./helper/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 hasMainSwitch; + +let alarmStatus = "OFF"; + +const SEND_TO = { + debug: 0, + tb: 1, + cmd_manager: 2 +} + + +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 = {}; + let rsPortReceivedData = []; + + //to be able to get proper twilight values + let twilight_sensor_interval = 5;//minutes + let twilight_sensor = []; + const twilight_sensor_array = []; + let twilightError = false; + + monitor.info("DIDO_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-we make it global to see it from outside + FLOW.deviceStatus = { //key is device name: temperature,.... + "state_of_main_switch": "Off", //Hlavny istic (alebo druhy dverovy kontakt) + "rotary_switch_state": "Off", //Prevadzkovy + "door_condition": "closed", //Dverový kontakt + "em": "OK", //elektromer rvo + "temperature": "OK", //templomer + "battery": "OK", //Bateria + "power_supply": "OK", //Zdroj + "master_node": "OK", //MN - GLOBALS.settings.masterNodeIsResponding + "no_voltage": "OK", //GLOBALS.settings.no_voltage - vypadok napatia na faze + "state_of_breaker": {}, //"Off",//Istic + "state_of_contactor": {}, //"Off",//Stykac + "twilight_sensor": "OK" //lux sensor + }; + let deviceStatus = FLOW.deviceStatus; + + + function main() { + + GLOBALS = FLOW.GLOBALS; + SETTINGS = FLOW.GLOBALS.settings; + rvoTbName = SETTINGS.rvoTbName; + pinsData = GLOBALS.pinsData; + relaysData = GLOBALS.relaysData; + + tbHandler = new DataToTbHandler(SEND_TO.tb); + tbHandler.setSender(exports.title); + + controller_type = SETTINGS.controller_type; //"lm" or "unipi" + hasMainSwitch = SETTINGS.has_main_switch; + + if (controller_type == "") controller_type = "lm"; + + 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, "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; + } + } + + //report RVO version relaysData[0].tbname; + let values = {}; + values["edge_fw_version"] = SETTINGS.edge_fw_version; + values["maintenance_mode"] = SETTINGS.maintenance_mode; + + sendTelemetry(values, rvoTbName); + + 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); + } + + + function handleRsPort() { + + if (rsPort) { + rsPort.removeAllListeners(); + rsPort = null; + } + + //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('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) { + if (!err) { + monitor.info(exports.title + "--->Digital in_out has been set (runSyncExec was sucessfull)"); + + turnAlarm("off"); + 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('error', err => { + let message = "Dido: rsPort error: " + err.message; + logger.debug(message); + monitor.info(message); + errorHandler.sendMessageToService(message); + }) + + rsPort.on("close", () => { + let message = "Dido: rsPort closed - reconnecting ..."; + logger.debug(message); + monitor.info(message); + setTimeout(handleRsPort, 1000); + }) + + rsPort.open(); + } + + + function handleWebSocket() { + + if (ws) { + ws.removeAllListeners(); + ws = null; + } + + //to keep websocket opened, we send request every 150 seconds + let startRequests = null; + + console.log("handleWebSocket function called"); + ws = new WebSocket('ws:/0.0.0.0:1234/ws'); + + ws.onopen = function open() { + + instance.send(0, exports.title + " running"); + turnAlarm("off"); + + initialSetting(); + + setTimeout(function() { ws.send(JSON.stringify({ cmd: "all" })) }, 5000); + // we request dev info about neuron device from evok to keep websocket connection alive + // for some reason this request returns no data, but connection keeps alive + startRequests = setInterval(() => { + ws.send(JSON.stringify({ "cmd": "filter", "dev": ["neuron"] })); + }, 150000) + }; + + + // 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 = async 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; + + 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 => { + logger.debug('Dido: websocket error', err); + }) + + ws.onclose = function() { + logger.debug('Dido: websocket onclose, reconnecting...') + clearInterval(startRequests); + setTimeout(handleWebSocket, 1000); + } + } + + 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 turnAlarm(onOrOff) { + let value = 0; + if (onOrOff == "on") value = 1; + + if (value == 1 && SETTINGS.maintenance_mode) return; + + alarmStatus = "OFF"; + if (value == 1) alarmStatus = "ON"; + + if (rsPort) { + let arr = [0x55]; + arr.push(13); + arr.push(0); + arr.push(value); + + rsPort.write(Buffer.from(arr), function(err) { + logger.debug(`sirena - ${onOrOff}`); + }); + } + else if (ws) { + let cmd = { "cmd": "set", "dev": "relay", "circuit": "1_01", "value": value }; + ws.send(JSON.stringify(cmd)); + logger.debug(`sirena - ${onOrOff}`); + } + } + + + 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") { + bits.push(0); + } + else bits.push(1); + + if (deviceStatus["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); + } + + + // turn line on or off + function turnLine(onOrOff, line, pin, force, info) { + //onOrOff => "on" or "off" + let value = 0; + if (onOrOff == "on") value = 1; + + if (force == undefined) force = false; + + if (line == 0) { + if (value == 1 && alarmStatus == "ON") turnAlarm("off"); + SETTINGS.maintenance_mode = value ? true : false; + + 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); + return; + } + + if (pin === undefined) pin = getPin(line); + + if (pin === undefined) { + errLogger.error("pin is undefined!", line); + return; + } + + if (!force) { + if (relaysData[line].contactor == value) { + instance.send(SEND_TO.debug, `line is already ${onOrOff} ` + line); + logger.debug(`Dido: turnLine: line is already ${onOrOff} `, line); + return; + } + } + + // if(!rsPort.isOpen && !ws) + if (!rsPort && !ws) { + errLogger.error("Dido - port or websocket is not opened"); + return; + } + + if (rsPort) { + let arr = [0x55]; + arr.push(pin); + arr.push(0); + arr.push(value); + + rsPort.write(Buffer.from(arr), function(err) { + if (err === undefined) { + monitor.info(`Dido: turnLine ${onOrOff} zapisal do rsPort-u`, line, pin, arr, info); + switchLogic(arr); + } + else { + monitor.info(`Dido: turnLine ${onOrOff} WRITE error`, err); + } + }); + + } + else if (ws) { + //pin = "relay1_03" or "input1_01" ... we must make just "1_01" with slice method + monitor.info(`Dido: turnLine ${onOrOff} - (line, pin, force)`, line, pin, force, info); + let cmd = { "cmd": "set", "dev": "relay", "circuit": pin.slice(5), "value": value }; + ws.send(JSON.stringify(cmd)); + } + + //if rvo is 24/7, it has just one switching profile point at 13:00. we do not want to send notification as it repeats every day. + //const d = new Date(); + //if(d.getHours() != 13) sendNotification("Dido_controller: ", SETTINGS.rvoTbName, "switching_profile_point_applied_to_line", { line: line, value: onOrOff }, "", SEND_TO.tb, instance); + } + + + // 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; + + // 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) { + const status = flowdata.data.status; + if (status == "NOK-twilight_sensor") { + deviceStatus["twilight_sensor"] = "NOK"; + } + else if (status == "NOK-em340" || status == "NOK-em111") { + deviceStatus["em"] = "NOK"; + } + else if (status == "NOK-thermometer") { + deviceStatus["temperature"] = "NOK"; + } + } + else if ("values" in flowdata.data) { + 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" + } + else if (values.hasOwnProperty("temperature")) { + deviceStatus["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"; + } + + sendTelemetry(values, rvoTbName); + } + + sendRvoStatus(); + }) + + + + + // we expect array as flowdata.data + instance.on("1", flowdata => { + + //console.log(flowdata.data); + + if (!flowdata.data instanceof Object) return; + + let obj = flowdata.data; + let line = obj.line; + 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"); + }) + + + function calculateStateCode() { + + let bits = []; + + //Hlavny istic - state_of_main_switch => v rvo senica je to druhy door pre silovu cast (EM) + if (deviceStatus["state_of_main_switch"] === "closed" || deviceStatus["state_of_main_switch"] === "Off") { + bits.push(0); + } + else { + bits.push(1); + } + + //Prevadzkovy mod - Manual, Off, Automatic, maintenance_mode = true/false // DAVA 2 BITY + if (!SETTINGS.maintenance_mode) { + if (deviceStatus["rotary_switch_state"] === "Manual") { + bits.push(0); + bits.push(1); + } + + if (deviceStatus["rotary_switch_state"] === "Automatic") { + bits.push(0); + bits.push(0); + } + + if (deviceStatus["rotary_switch_state"] === "Off") { + bits.push(1); + bits.push(0); + } + } + else { + bits.push(1); + bits.push(1); + } + + //Dverovy kontakt + if (deviceStatus["door_condition"] === "closed") { + bits.push(0); + } + else { + bits.push(1); + } + + //EM + if (deviceStatus["em"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //Teplomer + if (deviceStatus["temperature"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //Batéria + if (deviceStatus["battery"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //Zdroj + if (deviceStatus["power_supply"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //MN + if (deviceStatus["master_node"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //výpadok napätia na fáze + if (deviceStatus["no_voltage"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + if (deviceStatus["twilight_sensor"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + // doplnime do 16 bitov (2 byty) + for (let i = bits.length; i < 16; i++) { + bits.push(0); + } + + // console.log("calculateStateCode - deviceStatus", deviceStatus); + // 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; + } + + + async function sendRvoStatus() { + + if (SETTINGS === undefined) return; + SETTINGS.masterNodeIsResponding ? deviceStatus["master_node"] = "OK" : deviceStatus["master_node"] = "NOK"; + + 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 pinsForRvoStatus(controllerType, hasMainSwitch) { + + let pins = []; + + if (controllerType === "lm") { + pins = [1, 4, 6]; + if (hasMainSwitch === 1) { + pins = [4, 6]; + } + } else if (controllerType === "unipi") { + pins = ["input1_01", "input1_04", "input1_05"]; + if (hasMainSwitch === 1) { + pins = ["input1_01", "input1_04"]; + } + } + + return pins; + } + + + function checkRvoStatus() { + + // 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 + //set RVO state + let status = "OK"; + + for (const [key, value] of Object.entries(deviceStatus)) { + if (["em", "twilight_sensor", "temperature", "master_node"].includes(key) && value === "NOK") status = "NOK"; + } + + if (status === "OK") { + + let pinIndexes = pinsForRvoStatus(controller_type, hasMainSwitch); + + for (const pinIndex of pinIndexes) { + if (previousValues[pinIndex] === 0) { + if ((pinIndex === 6 || pinIndex === 'input1_01' || pinIndex === 'input1_05') && SETTINGS.maintenance_mode) continue; + status = "NOK"; + break; + } + } + } + + // battery status. If value is 1 - battery is NOK + if (previousValues[5] === 1) status = "NOK"; + if (SETTINGS.no_voltage.size > 0) status = "NOK"; + + // console.log("rvo status",status) + return status; + } + + + // we pass array to function in case of rsPort ==> switchLogic([55,3,0,1]) ==> [[55,3,0,1]] + // we pass two values in case of websocket ==> switchLogic("relay1_03",1) ==> ["relay1_03",1] + const switchLogic = (...args) => { + + let values = {}; + let pinIndex, newPinValue, twilight; + + //data from rsPort + if (args.length == 1) { + pinIndex = args[0][1] + 1; + if (pinIndex === 17) pinIndex--; + newPinValue = args[0][3]; + twilight = args[0][2]; + } + //data from websocket + else { + pinIndex = args[0]; + newPinValue = args[1]; + } + + 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; + + //default value + let value = "On"; + if (newPinValue === 0) value = "Off"; + + //Hlavny istic + if (type === "state_of_main_switch" && hasMainSwitch) { + if (newPinValue === 0 && newPinValue !== previousValues[pinIndex]) { + sendNotification("switchLogic", rvoTbName, "main_switch_has_been_turned_off", {}, "", SEND_TO.tb, instance, "state_of_main_switch"); + 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"); + deviceStatus["state_of_main_switch"] = "On"; + } + } + + //Prevadzkovy mod + 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"; + + deviceStatus["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, "power_supply_has_disconnected_input", {}, "", SEND_TO.tb, instance, "power_supply"); + + deviceStatus["power_supply"] = "NOK"; + } + else if (newPinValue === 1 && newPinValue !== previousValues[pinIndex]) { + sendNotification("switchLogic", rvoTbName, "power_supply_works_correctly", {}, "", SEND_TO.tb, instance, "power_supply"); + + deviceStatus["power_supply"] = "OK"; + } + } + + //Bateria - 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"); + + deviceStatus["battery"] = "NOK"; + } + else if (newPinValue === 0 && newPinValue !== previousValues[pinIndex]) { + sendNotification("switchLogic", rvoTbName, "battery_level_is_ok", {}, "", SEND_TO.tb, instance, "battery_level"); + + deviceStatus["battery"] = "OK"; + } + } + + //Dverovy kontakt - pin 6 + //! Ak je rvo s dvoma dverovymi kontaktami, ked pride z evoku signal z input1_05, co bol predytm "state_of_main switch" handlujeme ho teraz ako 'door_condition' + else if (type == "door_condition" || type === "state_of_main_switch") { + newPinValue === 0 ? value = "open" : value = "closed"; + + let door = "door_main"; + if (type === "state_of_main_switch") door = "door_em"; + + if (value === "open") { + if (SETTINGS.maintenance_mode) { + sendNotification("switchLogic", rvoTbName, door + "_open", {}, "", SEND_TO.tb, instance, door); + } else { + sendNotification("switchLogic", rvoTbName, door + "_open_without_permission", {}, "", SEND_TO.tb, instance, door); + + // 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 (value === "closed") { + if (alarmStatus == "ON") turnAlarm("off"); + sendNotification("switchLogic", rvoTbName, door + "_close", {}, "", SEND_TO.tb, instance, door); + } + + deviceStatus[type] = value; + } + + //lux sensor + else if (type == "twilight_sensor") { + //! TODO - to show nok status, if lux value is not changing more then 10 times. + //Daylight is far more than 1000. So most of the day, when it is sunshine comes just value 1000. But lux sensor is not NOK. + //This is not the case in LM. If value from LM is the same 10x, there is 99% possibility, that sensor is NOK. + value = newPinValue; + + if (controller_type === 'lm') { + value = parseFloat(newPinValue + (256 * twilight)); + + 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 && !twilightError) { + twilightError = true; + let value = twilight_sensor_array.shift(); + + newPinValue = 0; + } + else if (set.size !== 1 && twilightError) { + //sendNotification("switchLogic", rvoTbName, 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) { + 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); + } + } + + 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); + } + + deviceStatus["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 (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 }); + + //mame iba 3 istice. vyreportujeme a ohandlujeme liniu na tom istom istici ako paralelna linia (napr linia 1, paralelna s nou je linia 4, key je string "4") + // ak je 7 linii, na 1 istici je linia 1,4,7 + + if (line == 1) { + + const lineOnSameBraker = [4, 7]; + + for (var i = 0; i < lineOnSameBraker.length; i++) { + if (!relaysData.hasOwnProperty(lineOnSameBraker[i])) continue; + + 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; + reportLineStatus(lineOnSameBraker[i]); + + values[type] = value; + const tbname = relaysData[lineOnSameBraker[i]].tbname; + sendTelemetry(values, tbname); + + delete values[type]; + } + + } + else { + const lineOnSameBraker = line + 3 + ""; + + if (relaysData.hasOwnProperty(lineOnSameBraker)) { + 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; + reportLineStatus(line + 3); + + values[type] = value; + const tbname = relaysData[lineOnSameBraker].tbname; + sendTelemetry(values, tbname); + + delete values[type]; + } + } + + } + + if (value == "Off") values["status"] = "NOK"; + deviceStatus["state_of_breaker"][line] = value; + + reportLineStatus(line); + } + else return; + + values[type] = value; + + if (type == "rotary_switch_state") { + if (SETTINGS.maintenance_mode) value = "maintenance"; + value = value.toLowerCase(); + values["power_mode"] = value; + } + + if (newPinValue != previousValues[pinIndex]) previousValues[pinIndex] = newPinValue; + if (Object.keys(values).length > 0 && tbname) sendTelemetry(values, tbname); + } + + + function sendTelemetry(values, tbname, date = Date.now()) { + let dataToTb = { + [tbname]: [ + { + "ts": date, + "values": values + } + ] + }; + + tbHandler.sendToTb(dataToTb, instance); + } + + + function isObject(item) { + return (typeof item === "object" && !Array.isArray(item) && item !== null); + } + +} //end of 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 +// *|input1_01|state_of_main_switch|0|........... +// *|input1_02|rotary_switch_state|0|........... +// *|input1_03|rotary_switch_state|0|........... +// *|intut1_04|power_supply|0|........... +// *|input1_05|door_condition|0|........... +// *|input1_06|state_of_breaker|1|........... +// *|input1_07|state_of_breaker|2|........... +// *|input1_08|state_of_breaker|3|........... +// *|relay1_02|state_of_contactor|1|........... +// *|relay1_03|state_of_contactor|2|........... +// *|relay1_04|state_of_contactor|3|........... +// *|287D8776E0013CE9|temperature|0|........... + + +//! pins_data --> from UNIPI +// { +// 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 } +// } + +//! relays_data +// { +// '0': { +// line: 0, +// tbname: 'KjbN4q7JPZmexgdnz2yKQ98YAWwO0Q3BMX6ERLoV', +// contactor: 1, +// profile: '' +// }, +// '1': { +// line: 1, +// tbname: 'RMgnK93rkoAazbqdQ4yBG95Z1YXGx6pmwBeVEP2O', +// contactor: 0, +// profile: '{"intervals":[{"value":0,"end_time":"20:00","start_time":"13:00"},{"value":1,"end_time":"10:00","start_time":"20:00"},{"value":0,"end_time":"10:20","start_time":"10:00"},{"value":1,"end_time":"10:40","start_time":"10:20"},{"value":0,"end_time":"11:00","start_time":"10:40"},{"value":1,"end_time":"11:30","start_time":"11:00"},{"value":0,"end_time":"11:50","start_time":"11:30"},{"value":1,"end_time":"13:00","start_time":"11:50"}],"astro_clock":false,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' +// }, +// '2': { +// line: 2, +// tbname: 'dlE1VQjYrNx9gZRmb38gG08oLBO4qaAk2M6JPnG7', +// contactor: 0, +// profile: '{"intervals":[{"value":0,"end_time":"20:00","start_time":"13:00"},{"value":1,"end_time":"10:00","start_time":"20:00"},{"value":0,"end_time":"10:20","start_time":"10:00"},{"value":1,"end_time":"10:40","start_time":"10:20"},{"value":0,"end_time":"11:00","start_time":"10:40"},{"value":1,"end_time":"11:30","start_time":"11:00"},{"value":0,"end_time":"11:50","start_time":"11:30"},{"value":1,"end_time":"13:00","start_time":"11:50"}],"astro_clock":false,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' +// }, +// '3': { +// line: 3, +// tbname: 'vnmG4kJxaXWNBgMQq0D7Aj5e9oZzOAlr6LdR3w2V', +// contactor: 0, +// profile: '{"intervals":[{"value":0,"end_time":"20:30","start_time":"13:00"},{"value":1,"end_time":"00:10","start_time":"20:30"},{"value":0,"end_time":"13:00","start_time":"05:40"},{"value":1,"end_time":"05:40","start_time":"00:10"}],"astro_clock":true,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' +// } +// } + + + + + +// { +// "jbN4q7JPZmexgdnz2yKbWGDYAWwO0Q3BMX6ERLoV": [ +// { +// "ts": 1700409326353, +// "values": { +// "_event": { +// "type": "notice", +// "status": "new", +// "source": { +// "func": "rsPort.open()", +// "component": "1700343402190", +// "component_name": "DIDO_Controller", +// "edge": "jbN4q7JPZmexgdnz2yKbWGDYAWwO0Q3BMX6ERLoV" +// }, +// "message": "al_shariff_10.0.0.38: FLOW has been started ", +// "message_data": "" +// } +// } +// } +// ] +// } diff --git a/RVO33/flow/helper/DataToTbHandler.js b/RVO33/flow/helper/DataToTbHandler.js new file mode 100755 index 0000000..716ef7b --- /dev/null +++ b/RVO33/flow/helper/DataToTbHandler.js @@ -0,0 +1,187 @@ +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; + this.itIsNodeReadout = false; + this.sender = ""; + + // if attribute change difference is less than limit value, we do not send to tb. + this.attributeChangeLimit = { + temperature: 0.5, + Phase_1_voltage: 2, + Phase_2_voltage: 2, + Phase_3_voltage: 2, + Phase_1_current: 0.1, + Phase_2_current: 0.1, + Phase_3_current: 0.1, + Phase_1_power: 2, + Phase_2_power: 2, + Phase_3_power: 2, + total_power: 2, + total_energy: 1, + Phase_1_pow_factor: 0.1, + Phase_2_pow_factor: 0.1, + Phase_3_pow_factor: 0.1, + power_factor: 0.1, + lifetime: 2, + voltage: 2, + power: 2, + frequency: 3, + energy: 0.1, + current: 2, + inclination_x: 10, + inclination_y: 10, + inclination_z: 10 + }; + + } + + dump() { + console.log("----------------------------"); + console.log("previousValues", this.previousValues); + console.log("----------------------------"); + } + + setSender(sender) { + this.sender = sender; + } + + isEmptyObject(obj) { + for (var _ in obj) { + return false; + } + return true; + } + + + sendToTb(data, instance) { + + //not to modify data object, we do deep copy: + let dataCopy = JSON.parse(JSON.stringify(data)); + + let keys = Object.keys(dataCopy); + + if (keys.length == 0) { + if (this.debug) console.log("sendToTb received empty object", dataCopy); + return; + } + + let tbname = keys[0]; + let ts; + + let arrayOfValues = dataCopy[tbname]; + let arrayOfValuesToSend = []; + + for (let i = 0; i < arrayOfValues.length; i++) { + + ts = arrayOfValues[i].ts; + let values = this.prepareValuesForTb(tbname, ts, arrayOfValues[i].values); + + if (!this.isEmptyObject(values)) { + arrayOfValuesToSend.push({ ts: ts, values: values }); + } + + } + + if (arrayOfValuesToSend.length == 0) { + //if(this.debug) console.log("data not sent - empty array"); + return; + } + + this.messageCounter++; + + let dataToTbModified = { + [tbname]: arrayOfValuesToSend + } + + //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); + instance.send(this.index, dataToTbModified); + } + + + getDiffTimestamp(key) { + //TODO set different value for given key!!! + //if(key == "status") this.timeToHoldTbValue = 2*60*60;//2h + return this.timeToHoldTbValue * 1000; + } + + + prepareValuesForTb(tbname, timestamp, values) { + + let keys = Object.keys(values); + + if (keys.includes("lifetime")) this.itIsNodeReadout = true; + + if (!this.previousValues.hasOwnProperty(tbname)) { + this.previousValues[tbname] = {}; + } + + //if(this.debug) console.log("prepareValuesForTb", tbname, timestamp, values); + + for (let i = 0; i < keys.length; i++) { + + let key = keys[i]; + let value = values[key]; + + if (!this.previousValues[tbname].hasOwnProperty(key)) { + this.previousValues[tbname][key] = { ts: timestamp, value: value }; + continue; + } + + // attributeData ==> {voltage: {ts:333333, value:5}} + let attributeData = this.previousValues[tbname][key]; + let attributeToChange = false; + if (key in this.attributeChangeLimit) attributeToChange = true; + let limit = this.attributeChangeLimit[key]; + let timestampDiffToRemoveKey; + + //this will ensure "node statecode" will be sent just once an hour + if (this.itIsNodeReadout && key === "statecode") { + attributeData.value = value; + this.itIsNodeReadout = false; + timestampDiffToRemoveKey = 1 * 60 * 60 * 1000; // 1 hour + } + + if (key === "twilight_sensor" && value > 100) { + attributeData.value = value; + } + + //if edge, master or node version do not change, send just once a day: + if (["edge_fw_version", "master_node_version", "fw_version"].includes(key)) { + timestampDiffToRemoveKey = 24 * 60 * 60 * 1000; + } + + if (attributeData.value === value || attributeToChange && Math.abs(attributeData.value - value) < limit) { + + let diff = timestamp - attributeData.ts; + if (!timestampDiffToRemoveKey) timestampDiffToRemoveKey = this.getDiffTimestamp(key); + + if (diff > timestampDiffToRemoveKey) { + attributeData.ts = Date.now(); + //if(this.debug) console.log(this.sender + ": update ts for key", key, "diff is", diff, "messageCounter", this.messageCounter); + } + else { + delete values[key]; + //if(this.debug) console.log(this.sender + ": delete key", key, "diff is", diff, "messageCounter", this.messageCounter, timestampDiffToRemoveKey); + } + } + else { + attributeData.value = value; + attributeData.ts = timestamp; + } + + } + + return values; + } +} + +module.exports = DataToTbHandler; + diff --git a/RVO33/flow/helper/ErrorToServiceHandler.js b/RVO33/flow/helper/ErrorToServiceHandler.js new file mode 100755 index 0000000..2b27c32 --- /dev/null +++ b/RVO33/flow/helper/ErrorToServiceHandler.js @@ -0,0 +1,91 @@ +const { MD5 } = require('./md5.js'); +const { networkInterfaces } = require('os'); + +class ErrorToServiceHandler { + constructor() { + this.previousValues = {}; + + this.project_id = undefined; + + const nets = networkInterfaces(); + this.ipAddresses = {}; + + for (const name of Object.keys(nets)) { + for (const net of nets[name]) { + // Skip over non-IPv4 and internal (i.e. 127.0.0.1) addresses + if (net.family === 'IPv4' && !net.internal) { + if (!this.ipAddresses[name]) { + this.ipAddresses[name] = []; + } + this.ipAddresses[name].push(net.address); + } + } + } + } + + setProjectId(project_id) { + this.project_id = project_id; + } + + processMessage(message, seconds) { + if (Array.isArray(message)) message = message.join(', '); + + let key = MD5(message); + let ts = Date.now(); + + //keep in memory - default value is 1h + if (seconds === undefined) seconds = 60 * 60; + + if (!this.previousValues.hasOwnProperty(key)) { + this.previousValues[key] = { ts: ts, duration: seconds }; + } + + let diff = (ts - this.previousValues[key].ts); + if (diff < this.previousValues[key].duration * 1000) return false; + + this.previousValues[key].ts = ts; + + return message; + } + + sendMessageToService(message, seconds, message_type) { + + // if error occures too early FLOW.GLOBALS.settings.project_id is still undefined + if (this.project_id === undefined) { + console.log("ErrorToServiceHandler.js: no project_id"); + return; + } + + let f = this.processMessage(message, seconds); + if (f === false) return; + + if (message_type === undefined) message_type = "error_message"; + + let toService = { + id: this.project_id, + ipAddresses: this.ipAddresses + }; + + //js_error || error_message + toService[message_type] = message; + + console.log("ErrorToServiceHandler------------------------>send to service", toService); + + RESTBuilder.make(function(builder) { + builder.method('POST'); + builder.post(toService); + builder.url('http://192.168.252.2:8004/sentmessage'); + + builder.callback(function(err, response, output) { + console.log("process.on error send", err, response, output, toService); + }); + }); + + } +} + +const errorHandler = new ErrorToServiceHandler(); + + +module.exports = errorHandler; +//module.exports = ErrorToServiceHandler; diff --git a/RVO33/flow/helper/db_helper.js b/RVO33/flow/helper/db_helper.js new file mode 100755 index 0000000..40e796c --- /dev/null +++ b/RVO33/flow/helper/db_helper.js @@ -0,0 +1,44 @@ +function promisifyBuilder(builder) +{ + return new Promise((resolve, reject) => { + + try{ + + builder.callback(function(err, response) { + + if(err != null) reject(err); + resolve(response); + }); + + } catch (error) { + reject(error); + } + }) +} + +function makeMapFromDbResult(response, ...keys) +{ + let s = "-"; + let data = {}; + + for(let i = 0; i < response.length; i++) + { + let record = response[i]; + + let k = []; + for(let j = 0; j < keys.length; j++) + { + k.push( record[keys[j]] ); + } + + let key = k.join(s); + data[ key ] = record; + } + + return data; +} + +module.exports = { + promisifyBuilder, + makeMapFromDbResult + } \ No newline at end of file diff --git a/RVO33/flow/helper/logger.js b/RVO33/flow/helper/logger.js new file mode 100755 index 0000000..2585639 --- /dev/null +++ b/RVO33/flow/helper/logger.js @@ -0,0 +1,30 @@ +//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/RVO33/flow/helper/md5.js b/RVO33/flow/helper/md5.js new file mode 100755 index 0000000..d3b0480 --- /dev/null +++ b/RVO33/flow/helper/md5.js @@ -0,0 +1,5 @@ +function MD5(d){var r = M(V(Y(X(d),8*d.length)));return r.toLowerCase()};function M(d){for(var _,m="0123456789ABCDEF",f="",r=0;r>>4&15)+m.charAt(15&_);return f}function X(d){for(var _=Array(d.length>>2),m=0;m<_.length;m++)_[m]=0;for(m=0;m<8*d.length;m+=8)_[m>>5]|=(255&d.charCodeAt(m/8))<>5]>>>m%32&255);return _}function Y(d,_){d[_>>5]|=128<<_%32,d[14+(_+64>>>9<<4)]=_;for(var m=1732584193,f=-271733879,r=-1732584194,i=271733878,n=0;n>16)+(_>>16)+(m>>16)<<16|65535&m}function bit_rol(d,_){return d<<_|d>>>32-_} + +module.exports = { + MD5 +} \ No newline at end of file diff --git a/RVO33/flow/helper/notification_reporter.js b/RVO33/flow/helper/notification_reporter.js new file mode 100755 index 0000000..839c12c --- /dev/null +++ b/RVO33/flow/helper/notification_reporter.js @@ -0,0 +1,121 @@ +//key is device, value = message {} +let sentValues = {}; +let notificationsData = null; +let rvoName; + +//sendNotification("CMD Manager: process cmd", SETTINGS.rvoTbName, "dimming_profile_was_successfully_received_by_node", { node: node }, "", SEND_TO.tb, instance); + +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 +}; + +function getKey(map, val) { + return Object.keys(map).findItem(key => map[key] === val); +} + +//https://stackoverflow.com/questions/41117799/string-interpolation-on-variable +var template = (tpl, args) => tpl.replace(/\${(\w+)}/g, (_, v) => args[v]); + + +function initNotification() { + notificationsData = FLOW.GLOBALS.notificationsData; + rvoName = FLOW.GLOBALS.settings.rvo_name; +} + + +function sendNotification(func, device, key, params, extra, tb_output, instance, saveKey) { + + let storeToSendValues = true; + if (saveKey == undefined) storeToSendValues = false; + + let weight = ""; + let message = {}; + + let notification = notificationsData[key]; + + if (notification) { + weight = notification.weight.toLowerCase(); + + Object.keys(notification).forEach(item => { + if (["en", "sk", "de", "cz", "it", "es"].includes(item)) { + message[item] = rvoName + ": " + template(notification[item], params); + } + }) + } + else { + //console.error("sendNotification: Notifications: undefined key", key, func, notificationsData); + console.error("sendNotification: Notifications: undefined key", key, func); + return false; + } + + //detect invalid err weight + if (getKey(ERRWEIGHT, weight) == undefined) { + console.error("sendNotification: Notifications: undefined weight", weight, key, func); + return false; + } + + if (sentValues.hasOwnProperty(saveKey)) { + if (JSON.stringify(sentValues[saveKey]) == JSON.stringify(message)) { + return false; + } + } + + if (sentValues[saveKey] == undefined) { + if (storeToSendValues) { + //do not send - flow is was started + sentValues[saveKey] = message; + return false; + } + } + + if (storeToSendValues) sentValues[saveKey] = message; + + let content = { + "type": weight, + "status": "new", + "source": { + "func": func, + "component": instance.id, + "component_name": instance.name, + "edge": device + }, + "message": message, + "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 + + return true; + +} + +module.exports = { + sendNotification, + ERRWEIGHT, + initNotification +} + diff --git a/RVO33/flow/helper/register.js b/RVO33/flow/helper/register.js new file mode 100755 index 0000000..fc1d008 --- /dev/null +++ b/RVO33/flow/helper/register.js @@ -0,0 +1,144 @@ +/* +0 - cislo registra / prikaz +1 - recepient - 0 = master, 1 = slave (slave je automaticky group a broadcast) +2 - r/rw - read/write +3- register name - nazov registra / prikazu (len pre info - zobrazenie v aplikacii) + +4,5,6,7, - jednotlive byte-y - nazov byte-u +4-7 - RES. a prazdny string "" sa nezobrazia!!! +*/ + +//124 zaznamov +const registers = [ + ["0","1","R","Status","","",""], + ["1","1","RW","Dimming","R-Channel ","G-Channel","B-Channel ","W - Channel"], + ["2","1","R","Device types","","",".",""], + ["3","1","RW","Group addresses 1-4","Groups Add. 4","Groups Add. 3","Groups Add. 2","Groups Add. 1"], + ["4","1","RW","Group addresses 5-8","Groups Add. 8","Groups Add. 7","Groups Add. 6","Groups Add. 5"], + ["5","1","RW","Serial number (MAC)","","","",""], + ["6","1","RW","Time of dusk","HH","MM","SS","EXTRA"], + ["7","1","RW","Time of dawn","HH","MM","SS","EXTRA"], + ["8","1","RW","Time Schedule settings","TBD","TBD","Movement sensor","Time Schedule"], + ["9","1","RW","TS1 Time point 1","HH","MM","SS","Ext. Device"], + ["10","1","RW","TS1 Time point 1 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["11","1","RW","TS1 Time point 2","HH","MM","SS","Ext. Device"], + ["12","1","RW","TS1 Time point 2 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["13","1","RW","TS1 Time point 3","HH","MM","SS","Ext. Device"], + ["14","1","RW","TS1 Time point 3 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["15","1","RW","TS1 Time point 4","HH","MM","SS","Ext. Device"], + ["16","1","RW","TS1 Time point 4 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["17","1","RW","TS1 Time point 5","HH","MM","SS","Ext. Device"], + ["18","1","RW","TS1 Time point 5 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["19","1","RW","TS1 Time point 6","HH","MM","SS","Ext. Device"], + ["20","1","RW","TS1 Time point 6 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["21","1","RW","TS1 Time point 7","HH","MM","SS","Ext. Device"], + ["22","1","RW","TS1 Time point 7 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["23","1","RW","TS1 Time point 8","HH","MM","SS","Ext. Device"], + ["24","1","RW","TS1 Time point 8 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["25","1","RW","TS1 Time point 9","HH","MM","SS","Ext. Device"], + ["26","1","RW","TS1 Time point 9 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["27","1","RW","TS1 Time point 10","HH","MM","SS","Ext. Device"], + ["28","1","RW","TS1 Time point 10 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["29","1","RW","TS1 Time point 11","HH","MM","SS","Ext. Device"], + ["30","1","RW","TS1 Time point 11 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["31","1","RW","TS1 Time point 12","HH","MM","SS","Ext. Device"], + ["32","1","RW","TS1 Time point 12 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["33","1","RW","TS1 Time point 13","HH","MM","SS","Ext. Device"], + ["34","1","RW","TS1 Time point 13 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["35","1","RW","TS1 Time point 14","HH","MM","SS","Ext. Device"], + ["36","1","RW","TS1 Time point 14 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["37","1","RW","TS1 Time point 15","HH","MM","SS","Ext. Device"], + ["38","1","RW","TS1 Time point 15 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["39","1","RW","TS1 Time point 16","HH","MM","SS","Ext. Device"], + ["40","1","RW","TS1 Time point 16 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["41","1","RW","TS2 Time point 1","HH","MM","SS","Ext. Device"], + ["42","1","RW","TS2 Time point 1 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["43","1","RW","TS2 Time point 2","HH","MM","SS","Ext. Device"], + ["44","1","RW","TS2 Time point 2 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["45","1","RW","TS2 Time point 3","HH","MM","SS","Ext. Device"], + ["46","1","RW","TS2 Time point 3 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["47","1","RW","TS2 Time point 4","HH","MM","SS","Ext. Device"], + ["48","1","RW","TS2 Time point 4 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["49","1","RW","TS2 Time point 5","HH","MM","SS","Ext. Device"], + ["50","1","RW","TS2 Time point 5 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["51","1","RW","TS2 Time point 6","HH","MM","SS","Ext. Device"], + ["52","1","RW","TS2 Time point 6 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["53","1","RW","TS2 Time point 7","HH","MM","SS","Ext. Device"], + ["54","1","RW","TS2 Time point 7 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["55","1","RW","TS2 Time point 8","HH","MM","SS","Ext. Device"], + ["56","1","RW","TS2 Time point 8 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["57","1","RW","TS2 Time point 9","HH","MM","SS","Ext. Device"], + ["58","1","RW","TS2 Time point 9 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["59","1","RW","TS2 Time point 10","HH","MM","SS","Ext. Device"], + ["60","1","RW","TS2 Time point 10 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["61","1","RW","TS2 Time point 11","HH","MM","SS","Ext. Device"], + ["62","1","RW","TS2 Time point 11 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["63","1","RW","TS2 Time point 12","HH","MM","SS","Ext. Device"], + ["64","1","RW","TS2 Time point 12 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["65","1","RW","TS2 Time point 13","HH","MM","SS","Ext. Device"], + ["66","1","RW","TS2 Time point 13 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["67","1","RW","TS2 Time point 14","HH","MM","SS","Ext. Device"], + ["68","1","RW","TS2 Time point 14 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["69","1","RW","TS2 Time point 15","HH","MM","SS","Ext. Device"], + ["70","1","RW","TS2 Time point 15 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["71","1","RW","TS2 Time point 16","HH","MM","SS","Ext. Device"], + ["72","1","RW","TS2 Time point 16 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["73","1","RW","Power meter status","TBD","","",""], + ["74","1","R","Input Voltage","","","",""], + ["75","1","R","Input Current","","","",""], + ["76","1","R","Input Power","","","",""], + ["77","1","R","Cos phi","","","",""], + ["78","1","R","Frequency","","","",""], + ["79","1","RW","Energy","","","",""], + ["80","1","RW","Lifetime","","","",""], + ["81","1","RW","Power on cycles (input)","","","",""], + ["82","1","RW","Power on cycles (relay)","","","",""], + ["83","1","R","Time since last power on","","","",""], + ["84","1","R","Accelerometer data","","","",""], + ["85","1","RW","GPS latitude","pos/neg","deg","min ","sec"], + ["86","1","RW","GPS longitude","pos/neg","deg","min ","sec"], + ["87","1","RW","Actual time","HH","MM","SS","RES."], + ["88","1","RW","Actual date","Day of week","Day","Month","Year"], + ["89","1","R","Production data 1","","","",""], + ["90","1","R","Production data 2","","","",""], + ["91","1","RW","Network ID","NID3","NID2","NID1","NID0"], + ["95","1","RW","Actual Lux level from cabinet","RES.","RES.","HB","LB"], + ["96","1","RW","Threshold lux level","Dusk HB","Dusk LB","Dawn HB","Dawn LB"], + ["97","1","RW","Adjust period","Dusk HB","Dusk LB","Dawn HB","Dawn LB"], + ["98","1","RW","Offset","RES.","RES.","Dusk","Dawn"], + ["99","1","RW","CCT min/max range","max-H","max-L","min-H","min-L"], + ["100","1","RW","DALI interface","Cmd ID","Add","Cmd","Resp"], + ["101","1","RW","Module FW ver","v1","v2","v3","v4"], + ["102","1","RW","Module MAC-H","unused","unused","M1","M2"], + ["103","1","RW","Module MAC-L","M3","M4","M5","M6"], + ["122","1","R","FW update status/control register","Byte3","Byte2","Byte1","Byte0"], + ["123","1","R","FW update - data index","Byte3","Byte2","Byte1","Byte0"], + ["124","1","R","FW update - data","Byte3","Byte2","Byte1","Byte0"], + ["0","0","R","Status","","","",""], + ["1","0","RW","Control register","RES.","RES.","RES.","init mode enable"], + ["2","0","R","Device types","","","",""], + ["3","0","R","Serial number (MAC)","","","",""], + ["4","0","R","Production data 1","","","",""], + ["5","0","R","Production data 2","","","",""], + ["6","0","RW","Network ID","NID3","NID2","NID1","NID0"], + ["7","0","RW","RS232 settings","param.","param.","Baudrate H","Baudrate L"], + ["8","0","R","Accelerometer data","","","",""], + ["9","0","RW","Module FW ver","v1","v2","v3","v4"], + ["10","0","RW","Module MAC-H","unused","unused","M1","M2"], + ["11","0","RW","Module MAC-L","M3","M4","M5","M6"], + ["32","0","RW","FW update status/control register","Byte3","Byte2","Byte1","Byte0"], + ["33","0","RW","FW update - data index","Byte3","Byte2","Byte1","Byte0"], + ["34","0","RW","FW update - data","Byte3","Byte2","Byte1","Byte0"], + ["125","0","RW","Debug Register","Byte3","Byte2","Byte1","Byte0"], + ["126","0","RW","Network Control Register","Byte3","Byte2","Byte1","Byte0"], + ["127","0","R","Network Status Register","Byte3","Byte2","Byte1","Byte0"], + ["128","0","RW","Node XX Serial Number Register","SER3","SER2","SER1","SER0"], + ["256","0","R","Node XX Network Status Register","","","",""] +]; + +let register = {}; + +module.exports = { + registers, + register +} \ No newline at end of file diff --git a/RVO33/flow/helper/serialport_helper.js b/RVO33/flow/helper/serialport_helper.js new file mode 100755 index 0000000..7f5920d --- /dev/null +++ b/RVO33/flow/helper/serialport_helper.js @@ -0,0 +1,99 @@ +const { exec } = require('child_process'); + +function openPort(port) { + return new Promise((resolve, reject) => { + + var callbackError = function(err) { + port.removeListener('error', callbackError); + port.removeListener('open', callbackError); + + reject(err.message); + }; + + var callbackOpen = function(data) { + port.removeListener('error', callbackError); + port.removeListener('open', callbackOpen); + + resolve("port open: ok"); + }; + + port.on('error', callbackError); + port.on('open', callbackOpen); + + port.open(); + + }) +} + +function runSyncExec(command) { + return new Promise((resolve, reject) => { + + exec(command, (error, stdout, stderr) => { + if (error == null) resolve(stdout); + reject(error); + }); + + }) +} + +async function writeData(port, data, readbytes, timeout) { + return new Promise((resolve, reject) => { + + // 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) { + + port.write(Buffer.from(data), function(err) { + if (err) { + reject(err.message); + } + }); + + 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 +} diff --git a/RVO33/flow/helper/suncalc.js b/RVO33/flow/helper/suncalc.js new file mode 100755 index 0000000..c9ca56d --- /dev/null +++ b/RVO33/flow/helper/suncalc.js @@ -0,0 +1,317 @@ +/* + (c) 2011-2015, Vladimir Agafonkin + SunCalc is a JavaScript library for calculating sun/moon position and light phases. + https://github.com/mourner/suncalc +*/ + +(function () { 'use strict'; + +// shortcuts for easier to read formulas + +var PI = Math.PI, + sin = Math.sin, + cos = Math.cos, + tan = Math.tan, + asin = Math.asin, + atan = Math.atan2, + acos = Math.acos, + rad = PI / 180; + +// sun calculations are based on http://aa.quae.nl/en/reken/zonpositie.html formulas + + +// date/time constants and conversions + +var dayMs = 1000 * 60 * 60 * 24, + J1970 = 2440588, + J2000 = 2451545; + +function toJulian(date) { return date.valueOf() / dayMs - 0.5 + J1970; } +function fromJulian(j) { return new Date((j + 0.5 - J1970) * dayMs); } +function toDays(date) { return toJulian(date) - J2000; } + + +// general calculations for position + +var e = rad * 23.4397; // obliquity of the Earth + +function rightAscension(l, b) { return atan(sin(l) * cos(e) - tan(b) * sin(e), cos(l)); } +function declination(l, b) { return asin(sin(b) * cos(e) + cos(b) * sin(e) * sin(l)); } + +function azimuth(H, phi, dec) { return atan(sin(H), cos(H) * sin(phi) - tan(dec) * cos(phi)); } +function altitude(H, phi, dec) { return asin(sin(phi) * sin(dec) + cos(phi) * cos(dec) * cos(H)); } + +function siderealTime(d, lw) { return rad * (280.16 + 360.9856235 * d) - lw; } + +function astroRefraction(h) { + if (h < 0) // the following formula works for positive altitudes only. + h = 0; // if h = -0.08901179 a div/0 would occur. + + // formula 16.4 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + // 1.02 / tan(h + 10.26 / (h + 5.10)) h in degrees, result in arc minutes -> converted to rad: + return 0.0002967 / Math.tan(h + 0.00312536 / (h + 0.08901179)); +} + +// general sun calculations + +function solarMeanAnomaly(d) { return rad * (357.5291 + 0.98560028 * d); } + +function eclipticLongitude(M) { + + var C = rad * (1.9148 * sin(M) + 0.02 * sin(2 * M) + 0.0003 * sin(3 * M)), // equation of center + P = rad * 102.9372; // perihelion of the Earth + + return M + C + P + PI; +} + +function sunCoords(d) { + + var M = solarMeanAnomaly(d), + L = eclipticLongitude(M); + + return { + dec: declination(L, 0), + ra: rightAscension(L, 0) + }; +} + + +var SunCalc = {}; + + +// calculates sun position for a given date and latitude/longitude + +SunCalc.getPosition = function (date, lat, lng) { + + var lw = rad * -lng, + phi = rad * lat, + d = toDays(date), + + c = sunCoords(d), + H = siderealTime(d, lw) - c.ra; + + return { + azimuth: azimuth(H, phi, c.dec), + altitude: altitude(H, phi, c.dec) + }; +}; + + +// sun times configuration (angle, morning name, evening name) + +var times = SunCalc.times = [ + [-0.833, 'sunrise', 'sunset' ], + [ -0.3, 'sunriseEnd', 'sunsetStart' ], + [ -6, 'dawn', 'dusk' ], + [ -12, 'nauticalDawn', 'nauticalDusk'], + [ -18, 'nightEnd', 'night' ], + [ 6, 'goldenHourEnd', 'goldenHour' ] +]; + +// adds a custom time to the times config + +SunCalc.addTime = function (angle, riseName, setName) { + times.push([angle, riseName, setName]); +}; + + +// calculations for sun times + +var J0 = 0.0009; + +function julianCycle(d, lw) { return Math.round(d - J0 - lw / (2 * PI)); } + +function approxTransit(Ht, lw, n) { return J0 + (Ht + lw) / (2 * PI) + n; } +function solarTransitJ(ds, M, L) { return J2000 + ds + 0.0053 * sin(M) - 0.0069 * sin(2 * L); } + +function hourAngle(h, phi, d) { return acos((sin(h) - sin(phi) * sin(d)) / (cos(phi) * cos(d))); } +function observerAngle(height) { return -2.076 * Math.sqrt(height) / 60; } + +// returns set time for the given sun altitude +function getSetJ(h, lw, phi, dec, n, M, L) { + + var w = hourAngle(h, phi, dec), + a = approxTransit(w, lw, n); + return solarTransitJ(a, M, L); +} + + +// calculates sun times for a given date, latitude/longitude, and, optionally, +// the observer height (in meters) relative to the horizon + +SunCalc.getTimes = function (date, lat, lng, height) { + + height = height || 0; + + var lw = rad * -lng, + phi = rad * lat, + + dh = observerAngle(height), + + d = toDays(date), + n = julianCycle(d, lw), + ds = approxTransit(0, lw, n), + + M = solarMeanAnomaly(ds), + L = eclipticLongitude(M), + dec = declination(L, 0), + + Jnoon = solarTransitJ(ds, M, L), + + i, len, time, h0, Jset, Jrise; + + + var result = { + solarNoon: fromJulian(Jnoon), + nadir: fromJulian(Jnoon - 0.5) + }; + + for (i = 0, len = times.length; i < len; i += 1) { + time = times[i]; + h0 = (time[0] + dh) * rad; + + Jset = getSetJ(h0, lw, phi, dec, n, M, L); + Jrise = Jnoon - (Jset - Jnoon); + + result[time[1]] = fromJulian(Jrise); + result[time[2]] = fromJulian(Jset); + } + + return result; +}; + + +// moon calculations, based on http://aa.quae.nl/en/reken/hemelpositie.html formulas + +function moonCoords(d) { // geocentric ecliptic coordinates of the moon + + var L = rad * (218.316 + 13.176396 * d), // ecliptic longitude + M = rad * (134.963 + 13.064993 * d), // mean anomaly + F = rad * (93.272 + 13.229350 * d), // mean distance + + l = L + rad * 6.289 * sin(M), // longitude + b = rad * 5.128 * sin(F), // latitude + dt = 385001 - 20905 * cos(M); // distance to the moon in km + + return { + ra: rightAscension(l, b), + dec: declination(l, b), + dist: dt + }; +} + +SunCalc.getMoonPosition = function (date, lat, lng) { + + var lw = rad * -lng, + phi = rad * lat, + d = toDays(date), + + c = moonCoords(d), + H = siderealTime(d, lw) - c.ra, + h = altitude(H, phi, c.dec), + // formula 14.1 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + pa = atan(sin(H), tan(phi) * cos(c.dec) - sin(c.dec) * cos(H)); + + h = h + astroRefraction(h); // altitude correction for refraction + + return { + azimuth: azimuth(H, phi, c.dec), + altitude: h, + distance: c.dist, + parallacticAngle: pa + }; +}; + + +// calculations for illumination parameters of the moon, +// based on http://idlastro.gsfc.nasa.gov/ftp/pro/astro/mphase.pro formulas and +// Chapter 48 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + +SunCalc.getMoonIllumination = function (date) { + + var d = toDays(date || new Date()), + s = sunCoords(d), + m = moonCoords(d), + + sdist = 149598000, // distance from Earth to Sun in km + + phi = acos(sin(s.dec) * sin(m.dec) + cos(s.dec) * cos(m.dec) * cos(s.ra - m.ra)), + inc = atan(sdist * sin(phi), m.dist - sdist * cos(phi)), + angle = atan(cos(s.dec) * sin(s.ra - m.ra), sin(s.dec) * cos(m.dec) - + cos(s.dec) * sin(m.dec) * cos(s.ra - m.ra)); + + return { + fraction: (1 + cos(inc)) / 2, + phase: 0.5 + 0.5 * inc * (angle < 0 ? -1 : 1) / Math.PI, + angle: angle + }; +}; + + +function hoursLater(date, h) { + return new Date(date.valueOf() + h * dayMs / 24); +} + +// calculations for moon rise/set times are based on http://www.stargazing.net/kepler/moonrise.html article + +SunCalc.getMoonTimes = function (date, lat, lng, inUTC) { + var t = new Date(date); + if (inUTC) t.setUTCHours(0, 0, 0, 0); + else t.setHours(0, 0, 0, 0); + + var hc = 0.133 * rad, + h0 = SunCalc.getMoonPosition(t, lat, lng).altitude - hc, + h1, h2, rise, set, a, b, xe, ye, d, roots, x1, x2, dx; + + // go in 2-hour chunks, each time seeing if a 3-point quadratic curve crosses zero (which means rise or set) + for (var i = 1; i <= 24; i += 2) { + h1 = SunCalc.getMoonPosition(hoursLater(t, i), lat, lng).altitude - hc; + h2 = SunCalc.getMoonPosition(hoursLater(t, i + 1), lat, lng).altitude - hc; + + a = (h0 + h2) / 2 - h1; + b = (h2 - h0) / 2; + xe = -b / (2 * a); + ye = (a * xe + b) * xe + h1; + d = b * b - 4 * a * h1; + roots = 0; + + if (d >= 0) { + dx = Math.sqrt(d) / (Math.abs(a) * 2); + x1 = xe - dx; + x2 = xe + dx; + if (Math.abs(x1) <= 1) roots++; + if (Math.abs(x2) <= 1) roots++; + if (x1 < -1) x1 = x2; + } + + if (roots === 1) { + if (h0 < 0) rise = i + x1; + else set = i + x1; + + } else if (roots === 2) { + rise = i + (ye < 0 ? x2 : x1); + set = i + (ye < 0 ? x1 : x2); + } + + if (rise && set) break; + + h0 = h2; + } + + var result = {}; + + if (rise) result.rise = hoursLater(t, rise); + if (set) result.set = hoursLater(t, set); + + if (!rise && !set) result[ye > 0 ? 'alwaysUp' : 'alwaysDown'] = true; + + return result; +}; + + +// export as Node module / AMD module / browser variable +if (typeof exports === 'object' && typeof module !== 'undefined') module.exports = SunCalc; +else if (typeof define === 'function' && define.amd) define(SunCalc); +else window.SunCalc = SunCalc; + +}()); diff --git a/RVO33/flow/helper/utils.js b/RVO33/flow/helper/utils.js new file mode 100755 index 0000000..dbffe45 --- /dev/null +++ b/RVO33/flow/helper/utils.js @@ -0,0 +1,161 @@ +const fs = require('fs').promises; + +function bytesToInt(bytes, numberOfBytes) { + let buffer = []; + if (Array.isArray(bytes)) { + buffer = bytes.slice(0); + if (numberOfBytes != undefined) { + buffer = bytes.slice(bytes.length - numberOfBytes); + } + } + else buffer.push(bytes); + + let result = 0; + for (let i = 0; i < buffer.length; i++) { + result = (result << 8) | buffer[i]; + } + + return result >>> 0; //ensure it's an unsigned 32-bit number +} + +function resizeArray(arr, newSize, defaultValue) { + while (newSize > arr.length) + arr.push(defaultValue); + arr.length = newSize; +} + +longToByteArray = function(/*long*/long) { + // we want to represent the input as a 8-bytes array + var byteArray = [0, 0, 0, 0, 0, 0, 0, 0]; + + for (var index = 0; index < byteArray.length; index++) { + var byte = long & 0xff; + byteArray[index] = byte; + long = (long - byte) / 256; + } + + return byteArray; +}; + +function addDays(date, days) { + var result = new Date(date); + result.setDate(result.getDate() + days); + return result; +} + +/* +sleep(2000).then(() => { + // Do something after the sleep! + + +}); +*/ + +function sleep(time) { + return new Promise((resolve) => setTimeout(resolve, time)); +} + +function isEmptyObject(obj) { + for (var name in obj) { + return false; + } + return true; +} + +function emptyJsObject(jsObject) { + Object.keys(jsObject).forEach(key => delete jsObject[key]); +} + +function convertUTCDateToLocalDate(date) { + var newDate = new Date(date); + newDate.setMinutes(date.getMinutes() + date.getTimezoneOffset()); + return newDate; +} + +function addZeroBefore(n) { + return (n < 10 ? '0' : '') + n; +} + + +/** + * Asynchronously writes data to a file. + * + * @param {string} filePath The path to the file. + * @param {string} data The data to write to the file. + * @param {boolean} [append=false] If true, appends the data to the file. If false, it overwrites the file. + */ +async function writeToFile(filePath, data, append = false) { + if (typeof data !== 'string') data = JSON.stringify(data, null, 2); + try { + if (append) { + // Append the data to the end of the file. This is the simplest way to append. + await fs.appendFile(filePath, data, 'utf8'); + console.log(`Successfully appended data to ${filePath} using fs.appendFile.`); + } else { + // Overwrite the file with the new data. + await fs.writeFile(filePath, data, 'utf8'); + console.log(`Successfully wrote (overwrote) data to ${filePath} using fs.writeFile.`); + } + } catch (error) { + console.error(`Error writing to file ${filePath}:`, error); + } +} + + + /** + * Checks if an item is present in an array and adds it if it's not. + * * @param {Array} arr The array to check. + * @param {*} item The item to add. + * @returns {Array} The modified array. + */ +const addToArrayIfUnique = (arr, item) => { + if (!arr.includes(item)) { + arr.push(item); + } + return arr; +}; + + +var convertBase = function() { + + function convertBase(baseFrom, baseTo) { + return function(num) { + return parseInt(num, baseFrom).toString(baseTo); + + }; + } + + // binary to decimal + convertBase.bin2dec = convertBase(2, 10); + + // binary to hexadecimal + convertBase.bin2hex = convertBase(2, 16); + + // decimal to binary + convertBase.dec2bin = convertBase(10, 2); + + // decimal to hexadecimal + convertBase.dec2hex = convertBase(10, 16); + + // hexadecimal to binary + convertBase.hex2bin = convertBase(16, 2); + + // hexadecimal to decimal + convertBase.hex2dec = convertBase(16, 10); + + return convertBase; +}(); + +module.exports = { + bytesToInt, + longToByteArray, + addDays, + addZeroBefore, + resizeArray, + isEmptyObject, + emptyJsObject, + sleep, + convertUTCDateToLocalDate, + writeToFile, + addToArrayIfUnique +} diff --git a/RVO33/flow/httprequest.js b/RVO33/flow/httprequest.js new file mode 100755 index 0000000..469c8cb --- /dev/null +++ b/RVO33/flow/httprequest.js @@ -0,0 +1,137 @@ +exports.id = 'httprequest'; +exports.title = 'HTTP Request'; +exports.group = 'HTTP'; +exports.color = '#5D9CEC'; +exports.input = true; +exports.version = '2.0.1'; +exports.output = 1; +exports.author = 'Peter Širka'; +exports.icon = 'cloud-upload'; + +exports.html = `
+
@(URL address)
+
+
+
@(HTTP method)
+
+
+
@(Serialization)
+
+
+
@(Download the content in chunks)
+
@(Keep persistent cookies)
+
@(Disable DNS cache)
+
@(Keep alive connection)
+
+
+
+
@(Custom headers)
+
@(Cookies)
+
+
+
+ +
+
+
+
@(User)
+
+
+
@(Password)
+
+
+
+
+
`; + +exports.readme = `# Request + +This component creates a request with received data. + +__Response:__ +\`\`\`javascript +{ + data: String, + headers: Object, + status: Number, + host: String +} +\`\`\` + +__Dynamic arguments__: +Are performed via FlowData repository and can be used for URL address or for custom headers/cookies/auth. Use \`repository\` component for creating of dynamic arguments. Dynamic values are replaced in the form \`{key}\`: + +- url address e.g. \`https://.../{key}/\` +- headers values e.g. \`{token}\` +- cookies values e.g. \`{token}\``; + +exports.install = function(instance) { + + var can = false; + var flags = null; + var cookies2 = null; + + instance.on('data', function(response) { + can && instance.custom.send(response); + }); + + instance.custom.send = function(response) { + var options = instance.options; + + var headers = null; + var cookies = null; + + options.headers && Object.keys(options.headers).forEach(function(key) { + !headers && (headers = {}); + headers[key] = response.arg(options.headers[key]); + }); + + if (options.username && options.userpassword) { + !headers && (headers = {}); + headers['Authorization'] = 'Basic ' + U.createBuffer(response.arg(options.username + ':' + options.userpassword)).toString('base64'); + } + + options.cookies && Object.keys(options.cookies).forEach(function(key) { + !cookies && (cookies = {}); + cookies[key] = response.arg(options.cookies[key]); + }); + + if (options.chunks) { + U.download(response.arg(options.url), flags, options.stringify === 'none' ? null : response.data, function(err, response) { + response.on('data', (chunks) => instance.send2(chunks)); + }, cookies || cookies2, headers); + } else { + U.request(response.arg(options.url), flags, options.stringify === 'none' ? null : response.data, 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) + instance.error(err, response); + }, cookies || cookies2, headers); + } + }; + + instance.reconfigure = function() { + var options = instance.options; + can = options.url && options.url && options.method && options.stringify ? true : false; + instance.status(can ? '' : 'Not configured', can ? undefined : 'red'); + + if (!can) + return; + + flags = []; + flags.push(options.method.toLowerCase()); + options.stringify === 'json' && flags.push('json'); + options.stringify === 'raw' && flags.push('raw'); + options.keepalive && flags.push('keepalive'); + !options.nodns && flags.push('dnscache'); + if (options.persistentcookies) { + flags.push('cookies'); + cookies2 = {}; + } else + cookies2 = null; + }; + + instance.on('options', instance.reconfigure); + instance.reconfigure(); +}; \ No newline at end of file diff --git a/RVO33/flow/httpresponse.js b/RVO33/flow/httpresponse.js new file mode 100755 index 0000000..160a3bb --- /dev/null +++ b/RVO33/flow/httpresponse.js @@ -0,0 +1,76 @@ +exports.id = 'httpresponse'; +exports.title = 'HTTP Response'; +exports.group = 'HTTP'; +exports.color = '#5D9CEC'; +exports.icon = 'arrow-right'; +exports.input = true; +exports.output = ['#666D76']; +exports.version = '2.0.0'; +exports.author = 'Martin Smola'; +exports.readme = `# HTTP response + +HTTP response will respond with data recieved using data-type set in Settings form or plain text if not set. Output is the message duration \`Number\` in seconds.`; + +exports.html = `
+
@(Response data-type)
+
JSON is by default.
+
`; + +exports.install = function(instance) { + + var dursum = 0; + var durcount = 0; + + instance.on('data', function(flowdata) { + + var ctrl = flowdata.repository.controller; + var data = flowdata.data; + + if (!ctrl) { + instance.throw('No controller to use for response!'); + return; + } + + durcount++; + dursum += ((new Date() - flowdata.begin) / 1000).floor(2); + setTimeout2(instance.id, instance.custom.duration, 500, 10); + + ctrl.$flowdata = flowdata; + + var datatype = instance.options.datatype || 'json'; + if (datatype === 'emptyresponse') + return ctrl.plain(''); + + if (datatype !== 'json' && typeof(data) !== 'string') { + instance.throw('Incorect type of data, expected string, got ' + typeof(data)); + ctrl.plain(data == null ? '' : data.toString()); + return; + } + + switch(datatype) { + case 'html': + ctrl.content(data, 'text/html'); + break; + case 'plain': + ctrl.plain(data); + break; + case 'xml': + ctrl.content(data, 'text/xml'); + break; + default: + ctrl.json(data); + break; + } + }); + + instance.on('service', function() { + dursum = 0; + durcount = 0; + }); + + instance.custom.duration = function() { + var avg = (dursum / durcount).floor(2); + instance.status(avg + ' sec.'); + instance.send2(0, avg); + }; +}; diff --git a/RVO33/flow/httproute.js b/RVO33/flow/httproute.js new file mode 100755 index 0000000..583a19d --- /dev/null +++ b/RVO33/flow/httproute.js @@ -0,0 +1,326 @@ +exports.id = 'httproute'; +exports.title = 'HTTP Route'; +exports.group = 'HTTP'; +exports.color = '#5D9CEC'; +exports.icon = 'globe'; +exports.input = false; +exports.output = ['#6CAC5A', '#37BC9B']; +exports.version = '1.2.3'; +exports.author = 'Martin Smola'; +exports.cloning = false; +exports.options = { method: 'GET', url: '', size: 5, cacheexpire: '5 minutes', cachepolicy: 0, timeout: 5 }; +exports.dateupdated = '2021-01-21 18:30d'; +exports.readme = `# HTTP route + +__Outputs__: +- first output: raw data (cache is empty or is disabled) +- second output: cached data + +If one of the outputs is disabled then automatic responce with code "503 service unavailable" is sent. + +When a request comes in bellow object is available at \`flowdata.data\`: + +\`\`\`javascript +{ + params: { id: '1' }, // params for dynamic routes, e.g. /test/{id} + query: { msg: 'Hello' }, // parsed query string, e.g. /test/1?msg=Hello + body: { test: 'OK' }, // object if json requests otherwise string + headers: {}, // headers data + session: {}, // session data + user: {}, // user data + files: [], // uploaded files + url: '/users/', // a relative URL address + referrer: '/', // referrer + mobile: false, // determines mobile device + robot: false, // determines search robots/crawlsers + language: 'en' // determines language +} +\`\`\` + +See [documentation for flags](https://docs.totaljs.com/latest/en.html#api~HttpRouteOptionsFlags~unauthorize). These method flags are set automatically e.g. \`get, post, put, patch or delete\` + +--- + +\`id:ROUTE_ID\` flag cannot be used since it's already used by this component internally`; + +exports.html = `
+
+ +
+ +
+
+
@(HTTP method)
+
+
+
@(URL address)
+
+
+
+
+
@(Additional flags)
+
@(Separate flags by comma e.g. json, authorize)
+
+
+
@(Max. request size)
+
@(In kB kilobytes)
+
+
+
@(Timeout)
+
@(In seconds.)
+
+
+
+
+
+
@(Automatically respond with 200 OK?)
+
@(If not checked you need to use HTTP response component to respond to the request.)
+
+
@(Custom headers)
+
@(Cookies)
+
+
+
+
+
+
@(Cache policy)
+
@(User instance must contain id property.)
+
+
+
@(Expiration)
+
@(E.g. 5 minutes)
+
+
+
+`; + +exports.install = function(instance) { + + var route; + + var uninstall = function(id) { + if (F.is4) { + route && route.remove(); + route = null; + } else + UNINSTALL('route', id); + }; + + instance.custom.emptyresponse = function(self) { + self.plain(); + }; + + instance.reconfigure = function() { + + var options = instance.options; + + if (!options.url) { + instance.status('Not configured', 'red'); + return; + } + + if (typeof(options.flags) === 'string') + options.flags = options.flags.split(',').trim(); + + uninstall('id:' + instance.id); + + var flags = options.flags || []; + + flags.push('id:' + instance.id); + + if (!F.is4) + flags.push(options.method.toLowerCase()); + + options.timeout && flags.push(options.timeout * 1000); + + // Make unique values + flags = flags.filter(function(v, i, a) { + if(F.is4 && v.toString().toLowerCase() === options.method.toLowerCase()) + return false; // remove method + return a.indexOf(v) === i; + }); + + options.flags = flags; + var handler = function() { + + if (instance.paused || (instance.isDisabled && (instance.isDisabled('output', 0) || instance.isDisabled('output', 1)))) { + instance.status('503 Service Unavailable'); + this.status = 503; + this.json(); + return; + } + + var key; + var self = this; + + if (instance.options.emptyresponse) { + instance.status('200 OK'); + setTimeout(instance.custom.emptyresponse, 100, self); + + if (instance.hasConnection(0)) { + var data = instance.make({ + query: self.query, + body: self.body, + session: self.session, + user: self.user, + files: self.files, + headers: self.req.headers, + url: self.url, + params: self.params + }); + instance.send2(0, data); + } + + return; + } + + switch (instance.options.cachepolicy) { + case 1: // URL + key = 'rro' + instance.id + self.url.hash(); + break; + case 2: // URL + query + case 3: // URL + query + user + key = self.url; + var keys = Object.keys(self.query); + keys.sort(); + for (var i = 0, length = keys.length; i < length; i++) + key += keys[i] + self.query[keys[i]] + '&'; + if (instance.options.cachepolicy === 3 && self.user) + key += 'iduser' + self.user.id; + key = 'rro' + instance.id + key.hash(); + break; + } + + if (key && F.cache.get2(key)) { + var data = instance.make(F.cache.get2(key)); + data.repository.controller = self; + instance.send2(1, data); + } else { + + var data = instance.make({ + query: self.query, + body: self.body, + session: self.session, + user: self.user, + files: self.files, + headers: self.req.headers, + url: self.url, + params: self.params, + mobile: self.mobile, + robot: self.robot, + referrer: self.referrer, + language: self.language + }); + + data.repository.controller = self; + instance.send2(0, data); + key && FINISHED(self.res, () => F.cache.set(key, self.$flowdata.data, instance.options.cacheexpire)); + } + }; + + if (F.is4) + route = ROUTE(options.method.toUpperCase() + ' ' + options.url, handler, flags, options.size || 5); + else + F.route(options.url, handler, flags, options.size || 5); + + instance.status('Listening', 'green'); + }; + + instance.reconfigure(); + instance.on('options', instance.reconfigure); + instance.on('close', function(){ + uninstall('id:' + instance.id); + }); +}; + +// check url exists +FLOW.trigger('httproutecheckurl', function(next, data) { + var url = data.url; + var method = data.method; + if (url[url.length - 1] !== '/') + url += '/'; + var exists = F.routes.web.findItem(r => r.urlraw === url && r.method === method); + next(exists != null); +}); + +exports.uninstall = function() { + FLOW.trigger('httproutecheckurl', null); +}; diff --git a/RVO33/flow/infosender.js b/RVO33/flow/infosender.js new file mode 100755 index 0000000..587724f --- /dev/null +++ b/RVO33/flow/infosender.js @@ -0,0 +1,81 @@ +exports.id = 'infosender'; +exports.title = 'Info sender'; +exports.version = '1.0.0'; +exports.group = 'Worksys'; +exports.color = '#2134B0'; +exports.input = 2; +exports.output = 1 +exports.icon = 'bolt'; + +const { networkInterfaces } = require('os'); + +exports.html = `
+
+
+
CSV Import
+
+
+
`; + +exports.readme = `# send all data to projects.worksys.io, required to monitor status of controller(unipi)`; + +exports.install = function(instance) { + + let id; + let allValues = {}; + let sendAllValuesInterval; + let configured = false; + + let now = new Date(); + console.log(exports.title, "INSTALLED", now.toLocaleString("sk-SK")); + + const nets = networkInterfaces(); + let ipAddresses = Object.create(null); // Or just '{}', an empty object + + for (const name of Object.keys(nets)) { + for (const net of nets[name]) { + // Skip over non-IPv4 and internal (i.e. 127.0.0.1) addresses + if (net.family === 'IPv4' && !net.internal) { + if (!ipAddresses[name]) { + ipAddresses[name] = []; + } + ipAddresses[name].push(net.address); + } + } + } + + function sendValues() { + if (!configured) return; + + if (Object.keys(allValues).length > 0) { + let dataToSend = { ...allValues }; + dataToSend.id = id; + dataToSend.ipAddresses = ipAddresses; + + instance.send(0, dataToSend); + + allValues = {}; + } + } + + instance.on("close", () => { + clearInterval(sendAllValuesInterval); + }) + + instance.on("0", _ => { + id = FLOW.GLOBALS.settings.project_id; + if (id) configured = true; + else console.log(exports.title, "InfoSender: Unable to send data, no id"); + }) + + instance.on("1", flowdata => { + allValues = { ...allValues, ...flowdata.data }; + //console.log("DATA RECEIVED", flowdata.data); + }) + + sendAllValuesInterval = setInterval(() => { + sendValues(); + }, 60000 * 3); + +} + diff --git a/RVO33/flow/modbus_reader.js b/RVO33/flow/modbus_reader.js new file mode 100755 index 0000000..d6d9dad --- /dev/null +++ b/RVO33/flow/modbus_reader.js @@ -0,0 +1,346 @@ +exports.id = 'modbus_reader'; +exports.title = 'Modbus reader'; +exports.version = '2.0.0'; +exports.group = 'Worksys'; +exports.color = '#2134B0'; +exports.input = 1; +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; +//number of phases inRVO +let phases; +//phases where voltage is 0 (set) +let noVoltage; +let energyToSwitchLamps; + +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.phases = this.buildPhases(); + + this.startSocket(); + } + + buildPhases = () => { + let a = []; + for (let i = 1; i <= phases; i++) { + a.push(`Phase_${i}_voltage`) + } + return a; + } + + startSocket = () => { + + let obj = this; + + if (this.socket) { + this.socket.removeAllListeners(); + this.socket = null; + } + + 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('Modbus_reader: Socket connection error', e); //'ECONNREFUSED' or 'ECONNRESET' ?? + }); + + this.socket.on('close', function() { + console.log('Modbus_reader: Socket connection closed - Waiting 10 seconds before connecting 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 we just start to loop devices from the beginning, or there is just 1 device in config, we wait whole timeoutInterval + if (this.indexInDeviceConfig == 0 || deviceConfig.length === 1) 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 (this.phases.includes(singleValue)) { + let l = singleValue.split("_"); + let phase = parseInt(l[1]); + + // console.log(values[singleValue], tbName); + + if (values[singleValue] == 0) { + noVoltage.add(phase); + sendNotification("modbus_reader: checkNullVoltage", tbName, "no_voltage_on_phase", { phase: phase }, "", SEND_TO.tb, instance, "voltage" + phase); + // console.log('no voltage') + } + else { + noVoltage.delete(phase); + // console.log('voltage detected') + sendNotification("modbus_reader: checkNullVoltage", tbName, "voltage_on_phase_restored", { phase: phase }, "", SEND_TO.tb, instance, "voltage" + phase); + } + } + }) + } + + /** + * function sends notification to slack and to tb, if EM total_power value changes more than numberOfNodes*15. This should show, that RVO lamps has been switched on or off + */ + lampSwitchNotification = (values) => { + + if (!values.hasOwnProperty("total_power")) return; + + const actualTotalPower = values.total_power; + + if (actualTotalPower > energyToSwitchLamps && 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 <= energyToSwitchLamps && 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; + } + + function main() { + + phases = FLOW.GLOBALS.settings.phases; + tbName = FLOW.GLOBALS.settings.rvoTbName; + noVoltage = FLOW.GLOBALS.settings.no_voltage; + energyToSwitchLamps = FLOW.GLOBALS.settings.energy_to_switch_lamps / 2.5; //half value is enought to show if lamps are turned on or off + if (deviceConfig.length) mainSocket = new SocketWithClients(); + else console.log("Modbus_reader: no modbus device in configuration"); + + // this notification is to show, that flow (unipi) has been restarted + sendNotification("modbus_reader", tbName, "flow_restart", {}, "", SEND_TO.slack, instance); + } + + instance.on("0", function(_) { + main(); + }) + +} + diff --git a/RVO33/flow/monitorconsumption.js b/RVO33/flow/monitorconsumption.js new file mode 100755 index 0000000..64cc58e --- /dev/null +++ b/RVO33/flow/monitorconsumption.js @@ -0,0 +1,156 @@ +exports.id = 'monitorconsumption'; +exports.title = 'Consumption'; +exports.version = '1.0.0'; +exports.author = 'Peter Širka'; +exports.group = 'Monitoring'; +exports.color = '#967ADC'; +exports.input = 0; +exports.output = 1; +exports.icon = 'bug'; +exports.options = { interval: 5000, enabled: true, monitorconsumption: true, monitorsize: true, monitorconnections: true, monitorfiles: true }; +exports.click = true; +exports.readme = `# Consumption monitoring + +This component measure CPU and memory consumption, open files and open connections of this application. It uses these Linux commands: \`ps\`, \`lsof\`, \`netstat\` and \`df\`. + +__Data Example__: + +\`\`\`javascript +{ + cpu: 0, // percentage + memory: 4096, // in bytes + size: 34303, // directory size in bytes + files: 34, // count of open files + connections: 343, // count of connections + uptime: '1-12:34:00' +} +\`\`\``; + +exports.html = `
+
+
+
@(Interval in milliseconds)
+
+
+
+
Monitor: Consumption + uptime
+
Monitor: Count of open files
+
Monitor: Count of open connections
+
Monitor: Directory size
+
`; + +exports.install = function(instance) { + + var current = { cpu: 0, memory: 0, files: 0, connections: 0, size: 0, uptime: '', counter: 0 }; + var tproc = null; + var Exec = require('child_process').exec; + var reg_empty = /\s{2,}/g; + var reg_appdisksize = /^[\d.,]+/; + + instance.custom.run = function() { + + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + + var arr = []; + + // Get CPU and Memory consumption + instance.options.monitorconsumption && arr.push(function(next) { + Exec('ps -p {0} -o %cpu,rss,etime'.format(process.pid), function(err, response) { + + if (err) { + instance.throw(err); + } else { + var line = response.split('\n')[1]; + line = line.trim().replace(reg_empty, ' ').split(' '); + var cpu = line[0].parseFloat(); + current.cpu = cpu.floor(1); + current.memory = line[1].parseInt2() * 1024; // kB to bytes + current.uptime = line[2]; + } + + next(); + }); + }); + + // Get count of open files + instance.options.monitorfiles && arr.push(function(next) { + Exec('lsof -a -p {0} | wc -l'.format(process.pid), function(err, response) { + if (err) + instance.throw(err); + else + current.files = response.trim().parseInt2(); + next(); + }); + }); + + // Get count of opened network connections + instance.options.monitorconnections && arr.push(function(next) { + Exec('netstat -an | grep :{0} | wc -l'.format(F.port), function(err, response) { + if (err) { + instance.throw(err); + } else { + current.connections = response.trim().parseInt2() - 1; + if (current.connections < 0) + current.connections = 0; + } + next(); + }); + }); + + // Get directory size + instance.options.monitorsize && current.counter % 5 !== 0 && arr.push(function(next) { + Exec('du -hsb ' + process.cwd(), function(err, response) { + if (err) { + instance.throw(err); + } else { + var match = response.trim().match(reg_appdisksize); + match && (current.size = match.toString().trim().parseInt2()); + } + next(); + }); + }); + + arr.async(function() { + + tproc && clearTimeout(tproc); + + if (instance.options.enabled) { + tproc = setTimeout(instance.custom.run, instance.options.interval); + instance.send2(current); + } + + instance.custom.status(); + current.counter++; + }); + }; + + instance.custom.status = function() { + if (instance.options.enabled) + instance.status('{0}% / {1}'.format(current.cpu, current.memory.filesize())); + else + instance.status('Disabled', 'red'); + }; + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + + if (instance.options.enabled) { + current.counter = 0; + instance.custom.run(); + } + + }); + + instance.on('close', function() { + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + }); + + setTimeout(instance.custom.run, 1000); +}; \ No newline at end of file diff --git a/RVO33/flow/monitordisk.js b/RVO33/flow/monitordisk.js new file mode 100755 index 0000000..f4fdaa0 --- /dev/null +++ b/RVO33/flow/monitordisk.js @@ -0,0 +1,96 @@ +exports.id = 'monitordisk'; +exports.title = 'Disk'; +exports.version = '1.0.0'; +exports.author = 'Peter Širka'; +exports.group = 'Monitoring'; +exports.color = '#F6BB42'; +exports.output = 1; +exports.icon = 'hdd-o'; +exports.click = true; +exports.options = { interval: 8000, path: '/', enabled: true }; +exports.readme = `# Disk monitoring + +This component monitors disk \`bytes\` consumption in Linux systems. It uses \`df\` command. + +__Data Example__: + +\`\`\`javascript +{ + total: 474549649408, + used: 39125245952, + free: 411294994432 +} +\`\`\``; + +exports.html = `
+
+
+
@(Interval in milliseconds)
+
+
+
@(Path)
+
+
+
`; + +exports.install = function(instance) { + + var current = { total: 0, used: 0, free: 0, path: '', type: '', percentUsed: 0 }; + var tproc = null; + + instance.custom.run = function() { + + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + + if (!instance.options.enabled) + return; + + require('child_process').exec('df -hTB1 ' + instance.options.path, function(err, response) { + + tproc = setTimeout(instance.custom.run, instance.options.interval); + + if (err) { + instance.error(err); + return; + } + + response.parseTerminal(function(line) { + if (line[0][0] !== '/') + return; + current.total = line[2].parseInt(); + current.free = line[4].parseInt(); + current.used = line[3].parseInt(); + current.path = instance.options.path || '/'; + current.type = line[1]; + current.percentUsed = line[5]; + instance.custom.status(); + instance.send2(current); + }); + }); + }; + + instance.custom.status = function() { + if (instance.options.enabled) + instance.status(current.free.filesize() + ' / ' + current.total.filesize()); + else + instance.status('Disabled', 'red'); + }; + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + instance.options.enabled && instance.custom.run(); + }); + + instance.on('close', function() { + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + }); + + setTimeout(instance.custom.run, 1000); +}; \ No newline at end of file diff --git a/RVO33/flow/monitormemory.js b/RVO33/flow/monitormemory.js new file mode 100755 index 0000000..2decbc4 --- /dev/null +++ b/RVO33/flow/monitormemory.js @@ -0,0 +1,87 @@ +exports.id = 'monitormemory'; +exports.title = 'Memory'; +exports.version = '1.0.0'; +exports.author = 'Peter Širka'; +exports.group = 'Monitoring'; +exports.color = '#F6BB42'; +exports.output = 1; +exports.click = true; +exports.icon = 'microchip'; +exports.options = { interval: 8000, enabled: true }; +exports.readme = `# Memory monitoring + +This component monitors memory \`bytes\` consumption in Linux systems. It uses \`free\` command. + +__Data Example__: + +\`\`\`javascript +{ + total: 33558769664, + used: 1998868480, + free: 2653708288 +} +\`\`\``; + +exports.html = `
+
+
+
@(Interval in milliseconds)
+
+
+
`; + +exports.install = function(instance) { + + var current = { total: 0, used: 0, free: 0 }; + var tproc = null; + + instance.custom.run = function() { + + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + + if (!instance.options.enabled) + return; + + require('child_process').exec('free -b -t', function(err, response) { + + tproc = setTimeout(instance.custom.run, instance.options.interval); + + if (err) { + instance.error(err); + return; + } + + var memory = response.split('\n')[1].match(/\d+/g); + current.total = memory[0].parseInt(); + current.used = memory[1].parseInt() - memory[3].parseInt(); + current.free = current.total - current.used; + instance.custom.status(); + instance.send2(current); + }); + }; + + instance.custom.status = function() { + if (instance.options.enabled) + instance.status(current.free.filesize() + ' / ' + current.total.filesize()); + else + instance.status('Disabled', 'red'); + }; + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + instance.options.enabled && instance.custom.run(); + }); + + instance.on('close', function() { + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + }); + + setTimeout(instance.custom.run, 1000); +}; \ No newline at end of file diff --git a/RVO33/flow/nodesdb_changecheck.js b/RVO33/flow/nodesdb_changecheck.js new file mode 100755 index 0000000..9adab62 --- /dev/null +++ b/RVO33/flow/nodesdb_changecheck.js @@ -0,0 +1,77 @@ +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 = 2; +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); + } + } + + //kedze do slacku posielame stringy, na cloud musime previest vsetky stringy spat na objekty: + // Funkcia na parsovanie všetkých reťazcov v poli + const parseArray = (arr) => { + return arr.map(jsonString => JSON.parse(jsonString)); + }; + + 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); + if (FLOW.GLOBALS.settings.send_changed_node_numbers) instance.send(1, { aktualneNody: parseArray(zmenene), originalne: parseArray(Array.from(set2)) }); + } + 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/RVO33/flow/show_dbdata.js b/RVO33/flow/show_dbdata.js new file mode 100755 index 0000000..1e23ff7 --- /dev/null +++ b/RVO33/flow/show_dbdata.js @@ -0,0 +1,243 @@ +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 = 8; +exports.output = 1; + +const { exec } = require('child_process'); + +exports.install = 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 }) + }) + instance.on("5", _ => { + exec("sudo tail -n 25 monitor.txt", (err, stdout, stderr) => { + if (err || stderr) instance.send(0, { err, stderr }); + else instance.send(0, stdout); + }) + }) + instance.on("6", _ => { + exec("sudo tail -n 25 err.txt", (err, stdout, stderr) => { + if (err || stderr) instance.send(0, { err, stderr }); + else instance.send(0, stdout); + }) + }) + instance.on("7", _ => { + instance.send(0, FLOW.deviceStatus); + }) +}; + + +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/RVO33/flow/slack_filter.js b/RVO33/flow/slack_filter.js new file mode 100755 index 0000000..6618523 --- /dev/null +++ b/RVO33/flow/slack_filter.js @@ -0,0 +1,188 @@ +exports.id = 'slack_filter'; +exports.title = 'Slack Filter'; +exports.group = 'Citysys'; +exports.color = '#30E193'; +exports.input = 2; +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 = `
+
+
+
@(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('0', 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']['en']; + 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"] = []; + } + + instance.options.name = FLOW.GLOBALS.settings.rvo_name; + if (instance.options.name) { + instance.status('Running'); + running = true; + } else { + instance.status('Please run options again', 'red'); + running = false; + } + } catch (e) { + instance.error('Citysys connector: ' + e.message); + } + }; + + instance.on('options', instance.reconfigure); + + instance.on("1", _ => { + instance.reconfigure(); + }) +}; diff --git a/RVO33/flow/thermometer.js b/RVO33/flow/thermometer.js new file mode 100755 index 0000000..fc7074d --- /dev/null +++ b/RVO33/flow/thermometer.js @@ -0,0 +1,99 @@ +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 = 5;//minutes +let NUMBER_OF_FAILURES_TO_SEND_ERROR = 13; + +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) => { + + 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); + setTimeout(main, 20000); + }) +}; diff --git a/RVO33/flow/trigger.js b/RVO33/flow/trigger.js new file mode 100755 index 0000000..27545a8 --- /dev/null +++ b/RVO33/flow/trigger.js @@ -0,0 +1,79 @@ +exports.id = 'trigger'; +exports.title = 'Trigger'; +exports.group = 'Inputs'; +exports.color = '#F6BB42'; +exports.click = true; +exports.output = 1; +exports.version = '1.1.0'; +exports.author = 'Martin Smola'; +exports.icon = 'play'; + +exports.html = `
+
@(Data type (String by default))
+
@(Data)
+
Trigger 5s after initialization.
+
@(Useful when there's a need to run certain flow when the app restarts, etc.)
+
`; + +exports.readme = `# Trigger + +- Clicking on the component starts the chain +- Settings allows to set a data-type and a value`; + +exports.install = function(instance) { + + var value; + + instance.on('click', () => instance.send2(value)); + + instance.reconfigure = function() { + var options = instance.options; + value = null; + switch (options.datatype) { + case 'integer': + value = options.data.parseInt2('error'); + value = value === 'error' ? NaN : value; + break; + case 'float': + value = options.data.parseFloat2('error'); + value = value === 'error' ? NaN : value; + break; + case 'date': + options.data = options.data.toString(); + var num = options.data.parseInt('error'); + num === 'error' && (num = options.data.parseDate('error')); + num === 'error' && (num = null); + value = num ? new Date(num).toUTCString() : num; + break; + case 'object': + try { + value = (new Function('return ' + options.data))(); + } catch (e) { + instance.error(e); + } + break; + case 'boolean': + value = options.data.parseBoolean(); + break; + case 'buffer': + try { + value = U.createBuffer(options.data); + } catch (e) { + instance.error(e); + } + break; + case 'string': + default: + value = '' + (options.data || ''); + break; + } + }; + + instance.on('options', instance.reconfigure); + instance.reconfigure(); + + if (instance.options.restart) + setTimeout(function(){ + instance.send2(value); + }, 5000); +}; diff --git a/RVO33/flow/variables.txt b/RVO33/flow/variables.txt new file mode 100755 index 0000000..e69de29 diff --git a/RVO33/flow/virtualwirein.js b/RVO33/flow/virtualwirein.js new file mode 100755 index 0000000..38a4e42 --- /dev/null +++ b/RVO33/flow/virtualwirein.js @@ -0,0 +1,43 @@ +exports.id = 'virtualwirein'; +exports.title = 'Virtual wire in'; +exports.version = '1.0.0'; +exports.author = 'Martin Smola'; +exports.color = '#303E4D'; +exports.icon = 'sign-in'; +exports.input = false; +exports.output = 1; +exports.options = {}; +exports.readme = `# Virtual wire in + +When the wires between the components are mess it's time to use Virtual wire.`; + +exports.html = `
+
@(Wire name)
+
+`; + +exports.install = function(instance) { + + instance.custom.reconfigure = function(options){ + if (instance.options.wirename) { + instance.status(instance.options.wirename); + } else + instance.status('Not configured', 'red'); + }; + + ON('virtualwire', function(wirename, flowdata){ + if (instance.options.wirename && instance.options.wirename === wirename) + instance.send(flowdata); + }); + + instance.on('options', instance.custom.reconfigure); + instance.custom.reconfigure(); +}; diff --git a/RVO33/flow/virtualwireout.js b/RVO33/flow/virtualwireout.js new file mode 100755 index 0000000..94a1e4f --- /dev/null +++ b/RVO33/flow/virtualwireout.js @@ -0,0 +1,41 @@ +exports.id = 'virtualwireout'; +exports.title = 'Virtual wire out'; +exports.version = '1.0.0'; +exports.author = 'Martin Smola'; +exports.color = '#303E4D'; +exports.icon = 'sign-out'; +exports.input = true; +exports.options = {}; +exports.readme = `# Virtual wire out + +When the wires between the components are mess it's time to use Virtual wire.`; + +exports.html = `
+
@(Wire name)
+
+`; + +exports.install = function(instance) { + + instance.custom.reconfigure = function(){ + if (instance.options.wirename) { + instance.status(instance.options.wirename); + } else + instance.status('Not configured', 'red'); + }; + + instance.on('data', function(flowdata) { + EMIT('virtualwire', instance.options.wirename, flowdata); + }); + + instance.on('options', instance.custom.reconfigure); + instance.custom.reconfigure(); +}; diff --git a/RVO33/flow/wsmqttpublish.js b/RVO33/flow/wsmqttpublish.js new file mode 100755 index 0000000..0eba804 --- /dev/null +++ b/RVO33/flow/wsmqttpublish.js @@ -0,0 +1,448 @@ +exports.id = 'wsmqttpublish'; +exports.title = 'WS MQTT publish'; +exports.group = 'MQTT'; +exports.color = '#888600'; +exports.version = '1.0.2'; +exports.icon = 'sign-out'; +exports.input = 2; +exports.output = 3; +exports.options = { host: 'tb-stage.worksys.io', port: 1883, clientid: "", username: "" }; + +exports.html = `
+
+
+
Hostname or IP address (if not empty - setting will override db setting)
+
+
+
Port
+
+
+
+
+
@(Client id)
+
+
+
@(Username)
+
+
+
`; + + +exports.readme = ` +# WS MQTT Publish + +Version 1.0.3. + +Added: +- database collections, +- 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 = { + debug: 0, + rpcCall: 1, + services: 2 +} + +//CONFIG +let createTelemetryBackup = true; +let saveTelemetryOnError = true;//backup_on_failure overrides this value +//------------------------ + +let rollers; +if (createTelemetryBackup) rollers = require('streamroller'); + +const noSqlFileSizeLimit = 4194304;//use 5MB - 4194304 +let insertNoSqlCounter = 0; +let insertBackupNoSqlCounter = 0; +let processingData = false; + +let backup_on_failure = false;//== saveTelemetryOnError - create backup client 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; + +process.on('uncaughtException', function(err) { + + errLogger.error('uncaughtException:', err.message) + errLogger.error(err.stack); + + //TODO + //send to service + + //process.exit(1); +}) + +const nosql = NOSQL('tbdata'); +const nosqlBackup = NOSQL('/backup/tbdata'); + + +exports.install = function(instance) { + + var client; + var opts; + var clientReady = false; + + // wsmqtt status for notification purposes on projects.worksys.io database + let wsmqttName = null; + let sendWsStatusVar = null; + let wsmqtt_status = 'disconnected'; + + 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'; + } + + function sendWsStatus() { + instance.send(SEND_TO.services, { [wsmqttName]: wsmqtt_status }); + } + + + function main() { + if (!FLOW.dbLoaded) return; + + loadSettings(); + clearInterval(sendWsStatus); + sendWsStatusVar = setInterval(sendWsStatus, 180000); + } + + //set opts according to db settings + function loadSettings() { + + if (instance.options.host !== "") { + //override settings from database + var o = instance.options; + opts = { + host: o.host, + port: o.port, + clientId: o.clientid, + username: o.username, + rejectUnauthorized: false, + resubscribe: false + }; + + wsmqttName = getWsmqttName(o.host); + + console.log("wsmqttpublich -> loadSettings from instance.options", instance.options); + } + else { + + const SETTINGS = FLOW.GLOBALS.settings; + backup_on_failure = SETTINGS.backup_on_failure; + saveTelemetryOnError = backup_on_failure; + + restore_from_backup = SETTINGS.restore_from_backup; + restore_backup_wait = SETTINGS.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; + + opts = { + host: mqtt_host, + port: mqtt_port, + keepalive: 10, + clientId: mqtt_clientid, + username: mqtt_username, + rejectUnauthorized: false, + resubscribe: false + }; + + wsmqttName = getWsmqttName(mqtt_host); + } + + connectToTbServer(); + } + + function connectToTbServer() { + 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"); + //monitor.info("MQTT client connected"); + + sendClientError = true; + clientReady = true; + wsmqtt_status = 'connected'; + }); + + client.on('reconnect', function() { + instance.status("Reconnecting", "yellow"); + clientReady = false; + }); + + client.on('message', function(topic, message) { + // message is type of buffer + message = message.toString(); + if (message[0] === '{') { + TRY(function() { + + message = JSON.parse(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 } }); + } + + }, () => instance.debug('MQTT: Error parsing data', message)); + } + + instance.send(SEND_TO.rpcCall, { "topic": topic, "content": message }); + }); + + client.on('close', function() { + clientReady = false; + wsmqtt_status = 'disconnected'; + + instance.status("Disconnected", "red"); + instance.send(SEND_TO.debug, { "message": "Client CLOSE signal received !" }); + }); + + client.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; + wsmqtt_status = 'disconnected'; + }); + + } + + + instance.on("0", _ => { + main(); + }) + + + instance.on('1', function(data) { + + if (clientReady) { + //do we have some data in backup file? if any, process data from database + if (saveTelemetryOnError) { + //read telemetry data and send back to server + if (!processingData) processDataFromDatabase(); + } + + let stringifiedJson = JSON.stringify(data.data); + client.publish("v1/gateway/telemetry", stringifiedJson, { qos: 1 }); + + //backup telemetry + if (createTelemetryBackup) { + data.data.id = UID(); + nosqlBackup.insert(data.data); + + insertBackupNoSqlCounter++; + if (insertBackupNoSqlCounter > 150) { + let options = { compress: true }; + let path = __dirname + "/../databases/backup/tbdata.nosql"; + var stream = new rollers.RollingFileStream(path, noSqlFileSizeLimit, 150, options); + stream.write(""); + stream.end(); + + insertBackupNoSqlCounter = 0; + } + } + + } + 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 (saveTelemetryOnError) { + //create new file from tbdata.nosql, if file size exceeds given limit, and clear tbdata.nosql + makeBackupFromDbFile(); + + //write to tb + data.data.id = UID(); + nosql.insert(data.data); + } + } + }); + + + instance.close = function(done) { + if (clientReady) { + client.end(); + clearInterval(sendWsStatusVar); + } + }; + + + function getDbBackupFileCounter(type) { + var files = fs.readdirSync(__dirname + "/../databases"); + + let counter = 0; + for (var i = 0; i < files.length; i++) { + + if (files[i] == "tbdata.nosql") continue; + + if (files[i].endsWith(".nosql")) { + + let pos = files[i].indexOf("."); + if (pos > -1) { + + let fileCounter = counter; + let firstDigit = files[i].slice(0, pos); + + fileCounter = parseInt(firstDigit); + if (isNaN(fileCounter)) fileCounter = 0; + //console.log("getDbBackupFileCounter digit:", files[i], firstDigit, fileCounter, isNaN(fileCounter), type); + + if (type == "max") { + if (fileCounter > counter) { + counter = fileCounter; + } + } + else if (type == "min") { + if (counter == 0) counter = fileCounter; + + if (fileCounter < counter) { + counter = fileCounter; + } + } + } + } + + } + + if (type == "max") counter++; + + return counter; + } + + const makeBackupFromDbFile = async () => { + + if (!saveTelemetryOnError) return; + + //to avoid large file: tbdata.nosql + + //init value is 0! + if (insertNoSqlCounter > 0) { + --insertNoSqlCounter; + return; + } + + insertNoSqlCounter = 100; + + let source = __dirname + "/../databases/tbdata.nosql"; + + var stats = fs.statSync(source); + var fileSizeInBytes = stats.size; + + if (fileSizeInBytes > noSqlFileSizeLimit) { + + let counter = 1; + counter = getDbBackupFileCounter("max"); + + let destination = __dirname + "/../databases/" + counter + "." + "tbdata.nosql"; + + //make backup file + fs.copyFileSync(source, destination); + //fs.renameSync(p, p + "." + counter); + + //clear tbdata.nosql + fs.writeFileSync(source, ""); + fs.truncateSync(source, 0); + + } + } + + const processDataFromDatabase = async () => { + + if (restore_from_backup <= 0) return; + + //calculate diff + const now = new Date(); + let currentTime = now.getTime(); + let diff = currentTime - lastRestoreTime; + + if ((diff / 1000) < restore_backup_wait) { + //console.log("*********restore_backup_wait", diff, restore_backup_wait); + return; + } + + processingData = true; + + //get filename to process + let counter = getDbBackupFileCounter("min"); + + //we have some backup files + let dataBase = 'tbdata'; + + var nosql; + if (counter == 0) dataBase = 'tbdata'; + else dataBase = counter + "." + 'tbdata'; + + nosql = NOSQL(dataBase); + + //select all data - use limit restore_from_backup + let records = await promisifyBuilder(nosql.find().take(restore_from_backup)); + + for (let i = 0; i < records.length; i++) { + if (clientReady) { + + let item = records[i]; + let id = item.id; + + if (id !== undefined) { + //console.log("------------processDataFromDatabase - remove", id, dataBase, i); + + try { + + let message = JSON.parse(JSON.stringify(item)); + delete message.id; + + client.publish("v1/gateway/telemetry", JSON.stringify(message), { qos: 1 }); + + //remove from database + await promisifyBuilder(nosql.remove().where("id", id)); + + } catch (error) { + //process error + console.log("processDataFromDatabase", error); + } + + } + + } + else { + processingData = false; + return; + } + } + + if (records.length > 0) { + //clean backup file + if (counter > 0) nosql.clean(); + } + + //no data in db, remove + if (records.length == 0) { + if (counter > 0) nosql.drop(); + } + + const d = new Date(); + lastRestoreTime = d.getTime(); + + processingData = false; + + } + + instance.on('options', main); + //instance.reconfigure(); +}; diff --git a/RVO33/monitor.txt b/RVO33/monitor.txt new file mode 100755 index 0000000..4d8ae2a --- /dev/null +++ b/RVO33/monitor.txt @@ -0,0 +1,400 @@ +[2025-09-23T14:28:10.211] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-09-23T14:28:15.549] [INFO] monitorLogs - buildTasks - params undefined +[2025-09-23T14:28:15.554] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-09-23T14:28:15.555] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-09-23T14:28:15.555] [INFO] monitorLogs - 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 +} +[2025-09-23T14:28:15.558] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-23T14:28:15.559] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-09-24T11:00:00.558Z +[2025-09-23T14:28:15.560] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-09-23T14:28:15.562] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-09-23T14:28:15.562] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-09-23T14:28:15.563] [INFO] monitorLogs - 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 +} +[2025-09-23T14:28:15.564] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-23T14:28:15.565] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-09-24T11:00:00.565Z +[2025-09-23T14:28:15.566] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-09-23T14:28:15.567] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-09-23T14:28:15.568] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-09-23T14:28:15.568] [INFO] monitorLogs - 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 +} +[2025-09-23T14:28:15.570] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-23T14:28:15.570] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-09-24T11:00:00.570Z +[2025-09-23T14:28:15.571] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-09-23T14:28:15.572] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-09-23T14:28:15.574] [INFO] monitorLogs - tasks created: 137 +[2025-09-23T14:28:15.576] [INFO] monitorLogs - -->FLOW bol spustený apKVJBwOyrP35m2lv7KYq50YXbeWNd64En9GxRqg 2025-08-08 +[2025-09-23T14:28:20.579] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-24T03:28:17.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-24 03:28:17 +[2025-09-25T03:28:18.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-25 03:28:18 +[2025-09-25T16:26:47.568] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-09-25T16:26:52.902] [INFO] monitorLogs - buildTasks - params undefined +[2025-09-25T16:26:52.907] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-09-25T16:26:52.908] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-09-25T16:26:52.908] [INFO] monitorLogs - 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 +} +[2025-09-25T16:26:52.911] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-25T16:26:52.913] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-09-26T11:00:00.912Z +[2025-09-25T16:26:52.914] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-09-25T16:26:52.915] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-09-25T16:26:52.916] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-09-25T16:26:52.916] [INFO] monitorLogs - 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 +} +[2025-09-25T16:26:52.918] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-25T16:26:52.919] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-09-26T11:00:00.918Z +[2025-09-25T16:26:52.919] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-09-25T16:26:52.920] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-09-25T16:26:52.921] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-09-25T16:26:52.922] [INFO] monitorLogs - 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 +} +[2025-09-25T16:26:52.923] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-25T16:26:52.924] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-09-26T11:00:00.924Z +[2025-09-25T16:26:52.925] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-09-25T16:26:52.926] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-09-25T16:26:52.928] [INFO] monitorLogs - tasks created: 137 +[2025-09-25T16:26:52.931] [INFO] monitorLogs - -->FLOW bol spustený apKVJBwOyrP35m2lv7KYq50YXbeWNd64En9GxRqg 2025-08-08 +[2025-09-25T16:26:57.933] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-26T03:26:54.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-26 03:26:54 +[2025-09-27T03:26:56.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-27 03:26:56 +[2025-09-28T03:26:57.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-28 03:26:57 +[2025-09-29T03:26:58.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-29 03:26:58 +[2025-09-30T03:26:59.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-30 03:26:59 +[2025-10-01T03:27:01.014] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-01 03:27:01 +[2025-10-02T03:27:02.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-02 03:27:02 +[2025-10-03T03:27:03.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-03 03:27:03 +[2025-10-03T14:42:30.885] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-03T14:42:36.227] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-03T14:42:36.232] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-03T14:42:36.233] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-03T14:42:36.233] [INFO] monitorLogs - 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 +} +[2025-10-03T14:42:36.236] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-03T14:42:36.238] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-10-04T11:00:00.237Z +[2025-10-03T14:42:36.239] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-03T14:42:36.240] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-10-03T14:42:36.241] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-03T14:42:36.241] [INFO] monitorLogs - 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 +} +[2025-10-03T14:42:36.243] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-03T14:42:36.244] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-10-04T11:00:00.243Z +[2025-10-03T14:42:36.244] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-03T14:42:36.245] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-10-03T14:42:36.246] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-03T14:42:36.247] [INFO] monitorLogs - 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 +} +[2025-10-03T14:42:36.248] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-03T14:42:36.249] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-10-04T11:00:00.249Z +[2025-10-03T14:42:36.250] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-03T14:42:36.251] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-10-03T14:42:36.252] [INFO] monitorLogs - tasks created: 137 +[2025-10-03T14:42:36.255] [INFO] monitorLogs - -->FLOW bol spustený apKVJBwOyrP35m2lv7KYq50YXbeWNd64En9GxRqg 2025-08-08 +[2025-10-03T14:42:41.257] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-04T03:42:38.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-04 03:42:38 +[2025-10-05T03:42:39.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-05 03:42:39 +[2025-10-06T03:42:40.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-06 03:42:40 +[2025-10-07T03:42:41.013] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-07 03:42:41 +[2025-10-08T03:42:43.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-08 03:42:43 +[2025-10-09T03:42:44.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-09 03:42:44 +[2025-10-09T16:48:06.798] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-09T16:48:12.141] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-09T16:48:12.146] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-09T16:48:12.147] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-09T16:48:12.147] [INFO] monitorLogs - 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 +} +[2025-10-09T16:48:12.150] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T16:48:12.152] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-10-10T11:00:00.151Z +[2025-10-09T16:48:12.153] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-09T16:48:12.155] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-10-09T16:48:12.155] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-09T16:48:12.156] [INFO] monitorLogs - 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 +} +[2025-10-09T16:48:12.157] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T16:48:12.159] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-10-10T11:00:00.158Z +[2025-10-09T16:48:12.159] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-09T16:48:12.160] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-10-09T16:48:12.161] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-09T16:48:12.162] [INFO] monitorLogs - 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 +} +[2025-10-09T16:48:12.163] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T16:48:12.164] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-10-10T11:00:00.164Z +[2025-10-09T16:48:12.164] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-09T16:48:12.165] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-10-09T16:48:12.167] [INFO] monitorLogs - tasks created: 137 +[2025-10-09T16:48:12.169] [INFO] monitorLogs - -->FLOW bol spustený apKVJBwOyrP35m2lv7KYq50YXbeWNd64En9GxRqg 2025-08-08 +[2025-10-09T16:48:17.172] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-09T19:00:12.153] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-09T19:00:17.485] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-09T19:00:17.490] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-09T19:00:17.491] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-09T19:00:17.491] [INFO] monitorLogs - 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 +} +[2025-10-09T19:00:17.494] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T19:00:17.496] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-10-10T11:00:00.495Z +[2025-10-09T19:00:17.497] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-09T19:00:17.498] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-10-09T19:00:17.499] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-09T19:00:17.499] [INFO] monitorLogs - 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 +} +[2025-10-09T19:00:17.501] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T19:00:17.501] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-10-10T11:00:00.501Z +[2025-10-09T19:00:17.502] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-09T19:00:17.503] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-10-09T19:00:17.504] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-09T19:00:17.504] [INFO] monitorLogs - 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 +} +[2025-10-09T19:00:17.506] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T19:00:17.506] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-10-10T11:00:00.506Z +[2025-10-09T19:00:17.507] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-09T19:00:17.508] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-10-09T19:00:17.510] [INFO] monitorLogs - tasks created: 137 +[2025-10-09T19:00:17.512] [INFO] monitorLogs - -->FLOW bol spustený apKVJBwOyrP35m2lv7KYq50YXbeWNd64En9GxRqg 2025-08-08 +[2025-10-09T19:00:22.514] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-10T03:00:19.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-10 03:00:19 +[2025-10-11T03:00:20.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-11 03:00:20 +[2025-10-12T03:00:21.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-12 03:00:21 +[2025-10-13T03:00:22.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-13 03:00:22 +[2025-10-14T03:00:24.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-14 03:00:24 +[2025-10-15T03:00:25.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-15 03:00:25 +[2025-10-15T15:32:20.161] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-15T15:32:25.497] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-15T15:32:25.502] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-15T15:32:25.503] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-15T15:32:25.504] [INFO] monitorLogs - 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 +} +[2025-10-15T15:32:25.507] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-15T15:32:25.508] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-10-16T11:00:00.507Z +[2025-10-15T15:32:25.509] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-15T15:32:25.510] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-10-15T15:32:25.511] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-15T15:32:25.512] [INFO] monitorLogs - 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 +} +[2025-10-15T15:32:25.513] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-15T15:32:25.514] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-10-16T11:00:00.514Z +[2025-10-15T15:32:25.515] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-15T15:32:25.516] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-10-15T15:32:25.516] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-15T15:32:25.517] [INFO] monitorLogs - 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 +} +[2025-10-15T15:32:25.518] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-15T15:32:25.519] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-10-16T11:00:00.519Z +[2025-10-15T15:32:25.520] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-15T15:32:25.521] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-10-15T15:32:25.522] [INFO] monitorLogs - tasks created: 137 +[2025-10-15T15:32:25.525] [INFO] monitorLogs - -->FLOW bol spustený apKVJBwOyrP35m2lv7KYq50YXbeWNd64En9GxRqg 2025-10-08 +[2025-10-15T15:32:30.528] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu diff --git a/RVO33/package-lock.json b/RVO33/package-lock.json new file mode 100755 index 0000000..cc5cfd9 --- /dev/null +++ b/RVO33/package-lock.json @@ -0,0 +1,2125 @@ +{ + "name": "emptyproject", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "emptyproject", + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "bitwise": "^2.1.0", + "easy-crc": "0.0.2", + "jsmodbus": "^4.0.6", + "log4js": "^6.3.0", + "mqtt": "^4.2.6", + "nodemailer": "^6.9.7", + "serialport": "^9.2.8", + "total.js": "^3.4.13" + } + }, + "node_modules/@serialport/binding-abstract": { + "version": "9.2.3", + "resolved": "https://registry.npmjs.org/@serialport/binding-abstract/-/binding-abstract-9.2.3.tgz", + "integrity": "sha512-cQs9tbIlG3P0IrOWyVirqlhWuJ7Ms2Zh9m2108z6Y5UW/iVj6wEOiW8EmK9QX9jmJXYllE7wgGgvVozP5oCj3w==", + "dependencies": { + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/binding-mock": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/binding-mock/-/binding-mock-9.2.4.tgz", + "integrity": "sha512-dpEhACCs44oQhh6ajJfJdvQdK38Vq0N4W6iD/gdplglDCK7qXRQCMUjJIeKdS/HSEiWkC3bwumUhUufdsOyT4g==", + "dependencies": { + "@serialport/binding-abstract": "9.2.3", + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/bindings": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/@serialport/bindings/-/bindings-9.2.8.tgz", + "integrity": "sha512-hSLxTe0tADZ3LMMGwvEJWOC/TaFQTyPeFalUCsJ1lSQ0k6bPF04JwrtB/C81GetmDBTNRY0GlD0SNtKCc7Dr5g==", + "hasInstallScript": true, + "dependencies": { + "@serialport/binding-abstract": "9.2.3", + "@serialport/parser-readline": "9.2.4", + "bindings": "^1.5.0", + "debug": "^4.3.2", + "nan": "^2.15.0", + "prebuild-install": "^7.0.0" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-byte-length": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-byte-length/-/parser-byte-length-9.2.4.tgz", + "integrity": "sha512-sQD/iw4ZMU3xW9PLi0/GlvU6Y623jGeWecbMkO7izUo/6P7gtfv1c9ikd5h0kwL8AoAOpQA1lxdHIKox+umBUg==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-cctalk": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-cctalk/-/parser-cctalk-9.2.4.tgz", + "integrity": "sha512-T4TU5vQMwmo9AB3gQLFDWbfJXlW5jd9guEsB/nqKjFHTv0FXPdZ7DQ2TpSp8RnHWxU3GX6kYTaDO20BKzc8GPQ==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-delimiter": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-delimiter/-/parser-delimiter-9.2.4.tgz", + "integrity": "sha512-4nvTAoYAgkxFiXrkI+3CA49Yd43CODjeszh89EK+I9c8wOZ+etZduRCzINYPiy26g7zO+GRAb9FoPCsY+sYcbQ==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-inter-byte-timeout": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-inter-byte-timeout/-/parser-inter-byte-timeout-9.2.4.tgz", + "integrity": "sha512-SOAdvr0oBQIOCXX198hiTlxs4JTKg9j5piapw5tNq52fwDOWdbYrFneT/wN04UTMKaDrJuEvXq6T4rv4j7nJ5A==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-readline": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-readline/-/parser-readline-9.2.4.tgz", + "integrity": "sha512-Z1/qrZTQUVhNSJP1hd9YfDvq0o7d87rNwAjjRKbVpa7Qi51tG5BnKt43IV3NFMyBlVcRe0rnIb3tJu57E0SOwg==", + "dependencies": { + "@serialport/parser-delimiter": "9.2.4" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-ready": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-ready/-/parser-ready-9.2.4.tgz", + "integrity": "sha512-Pyi94Itjl6qAURwIZr/gmZpMAyTmKXThm6vL5DoAWGQjcRHWB0gwv2TY2v7N+mQLJYUKU3cMnvnATXxHm7xjxw==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-regex": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-regex/-/parser-regex-9.2.4.tgz", + "integrity": "sha512-sI/cVvPOYz+Dbv4ZdnW16qAwvXiFf/1pGASQdbveRTlgJDdz7sRNlCBifzfTN2xljwvCTZYqiudKvDdC1TepRQ==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/stream": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/stream/-/stream-9.2.4.tgz", + "integrity": "sha512-bLye8Ub4vUFQGmkh8qEqehr7SE7EJs2yDs0h9jzuL5oKi+F34CFmWkEErO8GAOQ8YNn7p6b3GxUgs+0BrHHDZQ==", + "dependencies": { + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "node_modules/are-we-there-yet": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", + "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/base64-js": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", + "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==" + }, + "node_modules/bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "dependencies": { + "file-uri-to-path": "1.0.0" + } + }, + "node_modules/bitwise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/bitwise/-/bitwise-2.1.0.tgz", + "integrity": "sha512-XKgAhMXCh4H/3oNwAHAsAO0iC89s9cOiumgYwSHjSobGWxYjv62YhkL9QEdvGP151xypCtMlAfKK79GEcd2eRQ==" + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/bl/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/buffer": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz", + "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==", + "dependencies": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + }, + "node_modules/buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" + }, + "node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, + "node_modules/code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/commist": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/commist/-/commist-1.1.0.tgz", + "integrity": "sha512-rraC8NXWOEjhADbZe9QBNzLAN5Q3fsTPQtBV+fEVj6xKIgDgNiEVE6ZNfHpZOqfQ21YUzfVNUXLOEZquYvQPPg==", + "dependencies": { + "leven": "^2.1.0", + "minimist": "^1.1.0" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "node_modules/concat-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", + "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", + "engines": [ + "node >= 6.0" + ], + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.0.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/concat-stream/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" + }, + "node_modules/core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "node_modules/crc": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/crc/-/crc-3.4.0.tgz", + "integrity": "sha512-ycVC2+4/DLgXXq7QweYi2znhqDuZz6P5TQXnkQo8v15XY/5p/IWeZwsSE31Ifo8w15b8TWLsqhXOjXyilHuQxw==" + }, + "node_modules/date-format": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.11.tgz", + "integrity": "sha512-VS20KRyorrbMCQmpdl2hg5KaOUsda1RbnsJg461FfrcyCUg+pkd0b40BSW4niQyTheww4DBXQnS7HwSrKkipLw==", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" + }, + "node_modules/detect-libc": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz", + "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==", + "engines": { + "node": ">=8" + } + }, + "node_modules/duplexify": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.2.tgz", + "integrity": "sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw==", + "dependencies": { + "end-of-stream": "^1.4.1", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1", + "stream-shift": "^1.0.0" + } + }, + "node_modules/duplexify/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/easy-crc": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/easy-crc/-/easy-crc-0.0.2.tgz", + "integrity": "sha512-h6eqIdhJRe0p271/xZJbM/0klCi13mW5IB7ZEzEGH11yV4QXWAkD4yPErz0fXdhFrd6sZ4Q1k5Iky2kMsMNePw==" + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" + }, + "node_modules/flatted": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", + "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==" + }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, + "node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "node_modules/gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha512-14x4kjc6lkD3ltw589k0NrPD6cCNTD6CWoVUNpB85+DrtONoZn+Rug6xZU5RvSC4+TZPxA5AnBibQYAvZn41Hg==", + "dependencies": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "node_modules/github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==" + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" + }, + "node_modules/has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" + }, + "node_modules/help-me": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/help-me/-/help-me-3.0.0.tgz", + "integrity": "sha512-hx73jClhyk910sidBB7ERlnhMlFsJJIBqSVMFDwPN8o2v9nmp5KgLq1Xz1Bf1fCMMZ6mPrX159iG0VLy/fPMtQ==", + "dependencies": { + "glob": "^7.1.6", + "readable-stream": "^3.6.0" + } + }, + "node_modules/help-me/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, + "node_modules/is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==", + "dependencies": { + "number-is-nan": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "node_modules/js-sdsl": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz", + "integrity": "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/js-sdsl" + } + }, + "node_modules/jsmodbus": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/jsmodbus/-/jsmodbus-4.0.6.tgz", + "integrity": "sha512-gCmjoaERErK5Rn9Lu/BN07fY13MoWV7JKgGzrnkPlQPdPxYcwDhLtYcmpFFpZ4J9NPZZBSezi1UkLZO/DnNppA==", + "dependencies": { + "crc": "3.4.0", + "debug": "^3.1.0" + }, + "bin": { + "jsmodbus": "bin/jsmodbus.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/jsmodbus/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/leven": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", + "integrity": "sha1-wuep93IJTe6dNCAq6KzORoeHVYA=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/log4js": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.5.2.tgz", + "integrity": "sha512-DXtpNtt+KDOMT7RHUDIur/WsSA3rntlUh9Zg4XCdV42wUuMmbFkl38+LZ92Z5QvQA7mD5kAVkLiBSEH/tvUB8A==", + "dependencies": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "flatted": "^3.2.5", + "rfdc": "^1.3.0", + "streamroller": "^3.1.1" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" + }, + "node_modules/mqtt": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/mqtt/-/mqtt-4.3.7.tgz", + "integrity": "sha512-ew3qwG/TJRorTz47eW46vZ5oBw5MEYbQZVaEji44j5lAUSQSqIEoul7Kua/BatBW0H0kKQcC9kwUHa1qzaWHSw==", + "dependencies": { + "commist": "^1.0.0", + "concat-stream": "^2.0.0", + "debug": "^4.1.1", + "duplexify": "^4.1.1", + "help-me": "^3.0.0", + "inherits": "^2.0.3", + "lru-cache": "^6.0.0", + "minimist": "^1.2.5", + "mqtt-packet": "^6.8.0", + "number-allocator": "^1.0.9", + "pump": "^3.0.0", + "readable-stream": "^3.6.0", + "reinterval": "^1.1.0", + "rfdc": "^1.3.0", + "split2": "^3.1.0", + "ws": "^7.5.5", + "xtend": "^4.0.2" + }, + "bin": { + "mqtt": "bin/mqtt.js", + "mqtt_pub": "bin/pub.js", + "mqtt_sub": "bin/sub.js" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/mqtt-packet": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/mqtt-packet/-/mqtt-packet-6.10.0.tgz", + "integrity": "sha512-ja8+mFKIHdB1Tpl6vac+sktqy3gA8t9Mduom1BA75cI+R9AHnZOiaBQwpGiWnaVJLDGRdNhQmFaAqd7tkKSMGA==", + "dependencies": { + "bl": "^4.0.2", + "debug": "^4.1.1", + "process-nextick-args": "^2.0.1" + } + }, + "node_modules/mqtt/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/nan": { + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.16.0.tgz", + "integrity": "sha512-UdAqHyFngu7TfQKsCBgAA6pWDkT8MAO7d0jyOecVhN5354xbLqdn8mV9Tat9gepAupm0bt2DbeaSC8vS52MuFA==" + }, + "node_modules/napi-build-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", + "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==" + }, + "node_modules/node-abi": { + "version": "3.22.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.22.0.tgz", + "integrity": "sha512-u4uAs/4Zzmp/jjsD9cyFYDXeISfUWaAVWshPmDZOFOv4Xl4SbzTXm53I04C2uRueYJ+0t5PEtLH/owbn2Npf/w==", + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/nodemailer": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.7.tgz", + "integrity": "sha512-rUtR77ksqex/eZRLmQ21LKVH5nAAsVicAtAYudK7JgwenEDZ0UIQ1adUGqErz7sMkWYxWTTU1aeP2Jga6WQyJw==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "dependencies": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "node_modules/number-allocator": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/number-allocator/-/number-allocator-1.0.14.tgz", + "integrity": "sha512-OrL44UTVAvkKdOdRQZIJpLkAdjXGTRda052sN4sO77bKEzYYqWKMBjQvrJFzqygI99gL6Z4u2xctPW1tB8ErvA==", + "dependencies": { + "debug": "^4.3.1", + "js-sdsl": "4.3.0" + } + }, + "node_modules/number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/prebuild-install": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.0.tgz", + "integrity": "sha512-CNcMgI1xBypOyGqjp3wOc8AAo1nMhZS3Cwd3iHIxOdAUbb+YxdNuM4Z5iIrZ8RLvOsf3F3bl7b7xGq6DjQoNYA==", + "dependencies": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^1.0.1", + "node-abi": "^3.3.0", + "npmlog": "^4.0.1", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + }, + "bin": { + "prebuild-install": "bin.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/reinterval": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reinterval/-/reinterval-1.1.0.tgz", + "integrity": "sha1-M2Hs+jymwYKDOA3Qu5VG85D17Oc=" + }, + "node_modules/rfdc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==" + }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/serialport": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/serialport/-/serialport-9.2.8.tgz", + "integrity": "sha512-FsWpMQgSJxi93JgWl5xM1f9/Z8IjRJuaUEoHqLf8FPBLw7gMhInuHOBhI2onQufWIYPGTz3H3oGcu1nCaK1EfA==", + "dependencies": { + "@serialport/binding-mock": "9.2.4", + "@serialport/bindings": "9.2.8", + "@serialport/parser-byte-length": "9.2.4", + "@serialport/parser-cctalk": "9.2.4", + "@serialport/parser-delimiter": "9.2.4", + "@serialport/parser-inter-byte-timeout": "9.2.4", + "@serialport/parser-readline": "9.2.4", + "@serialport/parser-ready": "9.2.4", + "@serialport/parser-regex": "9.2.4", + "@serialport/stream": "9.2.4", + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "node_modules/split2": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", + "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", + "dependencies": { + "readable-stream": "^3.0.0" + } + }, + "node_modules/split2/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==" + }, + "node_modules/streamroller": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.1.1.tgz", + "integrity": "sha512-iPhtd9unZ6zKdWgMeYGfSBuqCngyJy1B/GPi/lTpwGpa3bajuX30GjUVd0/Tn/Xhg0mr4DOSENozz9Y06qyonQ==", + "dependencies": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "fs-extra": "^10.1.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dependencies": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/tar-fs": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "dependencies": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tar-stream/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/total.js": { + "version": "3.4.13", + "resolved": "https://registry.npmjs.org/total.js/-/total.js-3.4.13.tgz", + "integrity": "sha512-lAH4gEixlPFbrE3xfKADAcHfO79IFq2wKa9GTsrgRzIR5MTg3mNH7+4IxvX1pK8faoYb/0oYSJ1YTsAa5hIFFQ==", + "bin": { + "total": "bin/totaljs", + "total.js": "bin/totaljs", + "totaljs": "bin/totaljs", + "totalpackage": "bin/tpm", + "tpm": "bin/tpm" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, + "node_modules/universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "node_modules/wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "node_modules/ws": { + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } + }, + "dependencies": { + "@serialport/binding-abstract": { + "version": "9.2.3", + "resolved": "https://registry.npmjs.org/@serialport/binding-abstract/-/binding-abstract-9.2.3.tgz", + "integrity": "sha512-cQs9tbIlG3P0IrOWyVirqlhWuJ7Ms2Zh9m2108z6Y5UW/iVj6wEOiW8EmK9QX9jmJXYllE7wgGgvVozP5oCj3w==", + "requires": { + "debug": "^4.3.2" + } + }, + "@serialport/binding-mock": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/binding-mock/-/binding-mock-9.2.4.tgz", + "integrity": "sha512-dpEhACCs44oQhh6ajJfJdvQdK38Vq0N4W6iD/gdplglDCK7qXRQCMUjJIeKdS/HSEiWkC3bwumUhUufdsOyT4g==", + "requires": { + "@serialport/binding-abstract": "9.2.3", + "debug": "^4.3.2" + } + }, + "@serialport/bindings": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/@serialport/bindings/-/bindings-9.2.8.tgz", + "integrity": "sha512-hSLxTe0tADZ3LMMGwvEJWOC/TaFQTyPeFalUCsJ1lSQ0k6bPF04JwrtB/C81GetmDBTNRY0GlD0SNtKCc7Dr5g==", + "requires": { + "@serialport/binding-abstract": "9.2.3", + "@serialport/parser-readline": "9.2.4", + "bindings": "^1.5.0", + "debug": "^4.3.2", + "nan": "^2.15.0", + "prebuild-install": "^7.0.0" + } + }, + "@serialport/parser-byte-length": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-byte-length/-/parser-byte-length-9.2.4.tgz", + "integrity": "sha512-sQD/iw4ZMU3xW9PLi0/GlvU6Y623jGeWecbMkO7izUo/6P7gtfv1c9ikd5h0kwL8AoAOpQA1lxdHIKox+umBUg==" + }, + "@serialport/parser-cctalk": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-cctalk/-/parser-cctalk-9.2.4.tgz", + "integrity": "sha512-T4TU5vQMwmo9AB3gQLFDWbfJXlW5jd9guEsB/nqKjFHTv0FXPdZ7DQ2TpSp8RnHWxU3GX6kYTaDO20BKzc8GPQ==" + }, + "@serialport/parser-delimiter": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-delimiter/-/parser-delimiter-9.2.4.tgz", + "integrity": "sha512-4nvTAoYAgkxFiXrkI+3CA49Yd43CODjeszh89EK+I9c8wOZ+etZduRCzINYPiy26g7zO+GRAb9FoPCsY+sYcbQ==" + }, + "@serialport/parser-inter-byte-timeout": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-inter-byte-timeout/-/parser-inter-byte-timeout-9.2.4.tgz", + "integrity": "sha512-SOAdvr0oBQIOCXX198hiTlxs4JTKg9j5piapw5tNq52fwDOWdbYrFneT/wN04UTMKaDrJuEvXq6T4rv4j7nJ5A==" + }, + "@serialport/parser-readline": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-readline/-/parser-readline-9.2.4.tgz", + "integrity": "sha512-Z1/qrZTQUVhNSJP1hd9YfDvq0o7d87rNwAjjRKbVpa7Qi51tG5BnKt43IV3NFMyBlVcRe0rnIb3tJu57E0SOwg==", + "requires": { + "@serialport/parser-delimiter": "9.2.4" + } + }, + "@serialport/parser-ready": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-ready/-/parser-ready-9.2.4.tgz", + "integrity": "sha512-Pyi94Itjl6qAURwIZr/gmZpMAyTmKXThm6vL5DoAWGQjcRHWB0gwv2TY2v7N+mQLJYUKU3cMnvnATXxHm7xjxw==" + }, + "@serialport/parser-regex": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-regex/-/parser-regex-9.2.4.tgz", + "integrity": "sha512-sI/cVvPOYz+Dbv4ZdnW16qAwvXiFf/1pGASQdbveRTlgJDdz7sRNlCBifzfTN2xljwvCTZYqiudKvDdC1TepRQ==" + }, + "@serialport/stream": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/stream/-/stream-9.2.4.tgz", + "integrity": "sha512-bLye8Ub4vUFQGmkh8qEqehr7SE7EJs2yDs0h9jzuL5oKi+F34CFmWkEErO8GAOQ8YNn7p6b3GxUgs+0BrHHDZQ==", + "requires": { + "debug": "^4.3.2" + } + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==" + }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "are-we-there-yet": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", + "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "base64-js": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", + "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==" + }, + "bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "requires": { + "file-uri-to-path": "1.0.0" + } + }, + "bitwise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/bitwise/-/bitwise-2.1.0.tgz", + "integrity": "sha512-XKgAhMXCh4H/3oNwAHAsAO0iC89s9cOiumgYwSHjSobGWxYjv62YhkL9QEdvGP151xypCtMlAfKK79GEcd2eRQ==" + }, + "bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "requires": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "buffer": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz", + "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==", + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" + }, + "chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==" + }, + "commist": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/commist/-/commist-1.1.0.tgz", + "integrity": "sha512-rraC8NXWOEjhADbZe9QBNzLAN5Q3fsTPQtBV+fEVj6xKIgDgNiEVE6ZNfHpZOqfQ21YUzfVNUXLOEZquYvQPPg==", + "requires": { + "leven": "^2.1.0", + "minimist": "^1.1.0" + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "concat-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", + "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.0.2", + "typedarray": "^0.0.6" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "crc": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/crc/-/crc-3.4.0.tgz", + "integrity": "sha512-ycVC2+4/DLgXXq7QweYi2znhqDuZz6P5TQXnkQo8v15XY/5p/IWeZwsSE31Ifo8w15b8TWLsqhXOjXyilHuQxw==" + }, + "date-format": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.11.tgz", + "integrity": "sha512-VS20KRyorrbMCQmpdl2hg5KaOUsda1RbnsJg461FfrcyCUg+pkd0b40BSW4niQyTheww4DBXQnS7HwSrKkipLw==" + }, + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "requires": { + "ms": "2.1.2" + } + }, + "decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "requires": { + "mimic-response": "^3.1.0" + } + }, + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==" + }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" + }, + "detect-libc": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz", + "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==" + }, + "duplexify": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.2.tgz", + "integrity": "sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw==", + "requires": { + "end-of-stream": "^1.4.1", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1", + "stream-shift": "^1.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "easy-crc": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/easy-crc/-/easy-crc-0.0.2.tgz", + "integrity": "sha512-h6eqIdhJRe0p271/xZJbM/0klCi13mW5IB7ZEzEGH11yV4QXWAkD4yPErz0fXdhFrd6sZ4Q1k5Iky2kMsMNePw==" + }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "requires": { + "once": "^1.4.0" + } + }, + "expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==" + }, + "file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" + }, + "flatted": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", + "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==" + }, + "fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, + "fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha512-14x4kjc6lkD3ltw589k0NrPD6cCNTD6CWoVUNpB85+DrtONoZn+Rug6xZU5RvSC4+TZPxA5AnBibQYAvZn41Hg==", + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==" + }, + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" + }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" + }, + "help-me": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/help-me/-/help-me-3.0.0.tgz", + "integrity": "sha512-hx73jClhyk910sidBB7ERlnhMlFsJJIBqSVMFDwPN8o2v9nmp5KgLq1Xz1Bf1fCMMZ6mPrX159iG0VLy/fPMtQ==", + "requires": { + "glob": "^7.1.6", + "readable-stream": "^3.6.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==", + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "js-sdsl": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz", + "integrity": "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==" + }, + "jsmodbus": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/jsmodbus/-/jsmodbus-4.0.6.tgz", + "integrity": "sha512-gCmjoaERErK5Rn9Lu/BN07fY13MoWV7JKgGzrnkPlQPdPxYcwDhLtYcmpFFpZ4J9NPZZBSezi1UkLZO/DnNppA==", + "requires": { + "crc": "3.4.0", + "debug": "^3.1.0" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "requires": { + "ms": "^2.1.1" + } + } + } + }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, + "leven": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", + "integrity": "sha1-wuep93IJTe6dNCAq6KzORoeHVYA=" + }, + "log4js": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.5.2.tgz", + "integrity": "sha512-DXtpNtt+KDOMT7RHUDIur/WsSA3rntlUh9Zg4XCdV42wUuMmbFkl38+LZ92Z5QvQA7mD5kAVkLiBSEH/tvUB8A==", + "requires": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "flatted": "^3.2.5", + "rfdc": "^1.3.0", + "streamroller": "^3.1.1" + } + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "requires": { + "yallist": "^4.0.0" + } + }, + "mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==" + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==" + }, + "mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" + }, + "mqtt": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/mqtt/-/mqtt-4.3.7.tgz", + "integrity": "sha512-ew3qwG/TJRorTz47eW46vZ5oBw5MEYbQZVaEji44j5lAUSQSqIEoul7Kua/BatBW0H0kKQcC9kwUHa1qzaWHSw==", + "requires": { + "commist": "^1.0.0", + "concat-stream": "^2.0.0", + "debug": "^4.1.1", + "duplexify": "^4.1.1", + "help-me": "^3.0.0", + "inherits": "^2.0.3", + "lru-cache": "^6.0.0", + "minimist": "^1.2.5", + "mqtt-packet": "^6.8.0", + "number-allocator": "^1.0.9", + "pump": "^3.0.0", + "readable-stream": "^3.6.0", + "reinterval": "^1.1.0", + "rfdc": "^1.3.0", + "split2": "^3.1.0", + "ws": "^7.5.5", + "xtend": "^4.0.2" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "mqtt-packet": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/mqtt-packet/-/mqtt-packet-6.10.0.tgz", + "integrity": "sha512-ja8+mFKIHdB1Tpl6vac+sktqy3gA8t9Mduom1BA75cI+R9AHnZOiaBQwpGiWnaVJLDGRdNhQmFaAqd7tkKSMGA==", + "requires": { + "bl": "^4.0.2", + "debug": "^4.1.1", + "process-nextick-args": "^2.0.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "nan": { + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.16.0.tgz", + "integrity": "sha512-UdAqHyFngu7TfQKsCBgAA6pWDkT8MAO7d0jyOecVhN5354xbLqdn8mV9Tat9gepAupm0bt2DbeaSC8vS52MuFA==" + }, + "napi-build-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", + "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==" + }, + "node-abi": { + "version": "3.22.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.22.0.tgz", + "integrity": "sha512-u4uAs/4Zzmp/jjsD9cyFYDXeISfUWaAVWshPmDZOFOv4Xl4SbzTXm53I04C2uRueYJ+0t5PEtLH/owbn2Npf/w==", + "requires": { + "semver": "^7.3.5" + } + }, + "nodemailer": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.7.tgz", + "integrity": "sha512-rUtR77ksqex/eZRLmQ21LKVH5nAAsVicAtAYudK7JgwenEDZ0UIQ1adUGqErz7sMkWYxWTTU1aeP2Jga6WQyJw==" + }, + "npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "number-allocator": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/number-allocator/-/number-allocator-1.0.14.tgz", + "integrity": "sha512-OrL44UTVAvkKdOdRQZIJpLkAdjXGTRda052sN4sO77bKEzYYqWKMBjQvrJFzqygI99gL6Z4u2xctPW1tB8ErvA==", + "requires": { + "debug": "^4.3.1", + "js-sdsl": "4.3.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==" + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==" + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==" + }, + "prebuild-install": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.0.tgz", + "integrity": "sha512-CNcMgI1xBypOyGqjp3wOc8AAo1nMhZS3Cwd3iHIxOdAUbb+YxdNuM4Z5iIrZ8RLvOsf3F3bl7b7xGq6DjQoNYA==", + "requires": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^1.0.1", + "node-abi": "^3.3.0", + "npmlog": "^4.0.1", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + } + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + } + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "reinterval": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reinterval/-/reinterval-1.1.0.tgz", + "integrity": "sha1-M2Hs+jymwYKDOA3Qu5VG85D17Oc=" + }, + "rfdc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==" + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "requires": { + "lru-cache": "^6.0.0" + } + }, + "serialport": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/serialport/-/serialport-9.2.8.tgz", + "integrity": "sha512-FsWpMQgSJxi93JgWl5xM1f9/Z8IjRJuaUEoHqLf8FPBLw7gMhInuHOBhI2onQufWIYPGTz3H3oGcu1nCaK1EfA==", + "requires": { + "@serialport/binding-mock": "9.2.4", + "@serialport/bindings": "9.2.8", + "@serialport/parser-byte-length": "9.2.4", + "@serialport/parser-cctalk": "9.2.4", + "@serialport/parser-delimiter": "9.2.4", + "@serialport/parser-inter-byte-timeout": "9.2.4", + "@serialport/parser-readline": "9.2.4", + "@serialport/parser-ready": "9.2.4", + "@serialport/parser-regex": "9.2.4", + "@serialport/stream": "9.2.4", + "debug": "^4.3.2" + } + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==" + }, + "simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "requires": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "split2": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", + "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", + "requires": { + "readable-stream": "^3.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==" + }, + "streamroller": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.1.1.tgz", + "integrity": "sha512-iPhtd9unZ6zKdWgMeYGfSBuqCngyJy1B/GPi/lTpwGpa3bajuX30GjUVd0/Tn/Xhg0mr4DOSENozz9Y06qyonQ==", + "requires": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "fs-extra": "^10.1.0" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" + }, + "tar-fs": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "requires": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "requires": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "total.js": { + "version": "3.4.13", + "resolved": "https://registry.npmjs.org/total.js/-/total.js-3.4.13.tgz", + "integrity": "sha512-lAH4gEixlPFbrE3xfKADAcHfO79IFq2wKa9GTsrgRzIR5MTg3mNH7+4IxvX1pK8faoYb/0oYSJ1YTsAa5hIFFQ==" + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, + "universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==" + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "requires": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "ws": { + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "requires": {} + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } + } +} diff --git a/RVO33/package.json b/RVO33/package.json new file mode 100755 index 0000000..e524d7c --- /dev/null +++ b/RVO33/package.json @@ -0,0 +1,29 @@ +{ + "name": "emptyproject", + "description": "Total.js empty project.", + "version": "1.0.0", + "main": "debug.js", + "dependencies": { + "bitwise": "^2.1.0", + "easy-crc": "0.0.2", + "jsmodbus": "^4.0.6", + "log4js": "^6.3.0", + "mqtt": "^4.2.6", + "nodemailer": "^6.9.7", + "serialport": "^9.2.8", + "total.js": "^3.4.13" + }, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "https://github.com/totaljs/emptyproject-flow" + }, + "keywords": [ + "empty", + "project" + ], + "author": "Peter Širka", + "license": "MIT" +} diff --git a/RVO33/release.js b/RVO33/release.js new file mode 100755 index 0000000..02d52ff --- /dev/null +++ b/RVO33/release.js @@ -0,0 +1,15 @@ +// =================================================== +// FOR PRODUCTION +// Total.js - framework for Node.js platform +// https://www.totaljs.com +// =================================================== + +const options = {'ip':'0.0.0.0', 'port':12345}; + +// options.ip = '127.0.0.1'; +// options.port = parseInt(process.argv[2]); +// options.config = { name: 'Total.js' }; +// options.sleep = 3000; + +require('total.js').http('release', options); +// require('total.js').cluster.http(5, 'release', options); diff --git a/RVO33/release.js.json b/RVO33/release.js.json new file mode 100755 index 0000000..f70746c --- /dev/null +++ b/RVO33/release.js.json @@ -0,0 +1,34 @@ +{ + "pid": 382, + "stats": [ + { + "id": null, + "version": { + "node": "v14.18.1", + "total": "3.4.13", + "app": "1.0.0" + }, + "pid": 382, + "thread": "", + "mode": "release", + "overload": 0, + "date": "2025-10-16T00:24:16.186Z", + "memory": 23.59, + "rm": 0, + "fm": 0, + "wm": 0, + "mm": 0, + "om": 0, + "em": 1, + "dbrm": 0, + "dbwm": 0, + "usage": 0, + "requests": 7, + "pending": 0, + "errors": 0, + "timeouts": 0, + "uptime": 653, + "online": 0 + } + ] +} \ No newline at end of file diff --git a/RVO33/report_data.log b/RVO33/report_data.log new file mode 100755 index 0000000..f56c2e3 --- /dev/null +++ b/RVO33/report_data.log @@ -0,0 +1,151 @@ +{ + "name": "rvo_senica_33_ip127", + "time": "2025-10-15T14:32:31.137Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_33_ip127", + "time": "2025-10-15T15:32:31.133Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_33_ip127", + "time": "2025-10-15T16:32:31.134Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_33_ip127", + "time": "2025-10-15T17:32:31.134Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_33_ip127", + "time": "2025-10-15T18:32:31.134Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_33_ip127", + "time": "2025-10-15T19:32:31.135Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_33_ip127", + "time": "2025-10-15T20:32:31.134Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_33_ip127", + "time": "2025-10-15T21:32:31.135Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_33_ip127", + "time": "2025-10-15T22:32:31.135Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_33_ip127", + "time": "2025-10-15T23:32:31.136Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +} \ No newline at end of file From 1467900c8083e0ba8cf12942bab7dd5c476b9cfb Mon Sep 17 00:00:00 2001 From: Jakub Klena Date: Thu, 16 Oct 2025 02:25:32 +0200 Subject: [PATCH 16/30] Backup senica-RVO34 on 16.10.2025 --- RVO34/addSwitch.py | 36 + RVO34/cloud_topic.py | 76 + RVO34/config | 12 + RVO34/createNode.py | 43 + RVO34/databases/accelerometer_db.js | 3055 ++++++++++++ RVO34/databases/modbus_config.js | 114 + RVO34/databases/nodes.table | 108 + .../nodes_original/nodes_original.table | 1 + RVO34/databases/notifications.table | 41 + RVO34/databases/pins.table | 18 + RVO34/databases/relays.table | 9 + RVO34/databases/settings.table | 2 + RVO34/databases/tbdata.nosql | 4 + RVO34/databases/tbdatacloud.nosql | 3 + RVO34/databases/total_energy.js | 38 + RVO34/debug.js | 16 + RVO34/err.txt | 1931 ++++++++ RVO34/flow/cloudmqttconnect.js | 357 ++ RVO34/flow/cmd_manager.js | 3071 +++++++++++++ RVO34/flow/code.js | 90 + RVO34/flow/comment.js | 11 + RVO34/flow/count.js | 60 + RVO34/flow/db_connector.js | 286 ++ RVO34/flow/db_init.js | 113 + RVO34/flow/debug.js | 100 + RVO34/flow/designer.json | 3102 +++++++++++++ RVO34/flow/dido_controller.js | 1486 ++++++ RVO34/flow/helper/DataToTbHandler.js | 187 + RVO34/flow/helper/ErrorToServiceHandler.js | 91 + RVO34/flow/helper/db_helper.js | 44 + RVO34/flow/helper/logger.js | 30 + RVO34/flow/helper/md5.js | 5 + RVO34/flow/helper/notification_reporter.js | 121 + RVO34/flow/helper/register.js | 144 + RVO34/flow/helper/serialport_helper.js | 99 + RVO34/flow/helper/suncalc.js | 317 ++ RVO34/flow/helper/utils.js | 161 + RVO34/flow/httprequest.js | 137 + RVO34/flow/httpresponse.js | 76 + RVO34/flow/httproute.js | 326 ++ RVO34/flow/infosender.js | 81 + RVO34/flow/modbus_reader.js | 346 ++ RVO34/flow/monitorconsumption.js | 156 + RVO34/flow/monitordisk.js | 96 + RVO34/flow/monitormemory.js | 87 + RVO34/flow/nodesdb_changecheck.js | 77 + RVO34/flow/show_dbdata.js | 243 + RVO34/flow/slack_filter.js | 188 + RVO34/flow/thermometer.js | 99 + RVO34/flow/trigger.js | 79 + RVO34/flow/variables.txt | 0 RVO34/flow/virtualwirein.js | 43 + RVO34/flow/virtualwireout.js | 41 + RVO34/flow/wsmqttpublish.js | 448 ++ RVO34/monitor.txt | 4087 +++++++++++++++++ RVO34/package-lock.json | 2139 +++++++++ RVO34/package.json | 30 + RVO34/release.js | 15 + RVO34/release.js.json | 34 + RVO34/report_data.log | 187 + 60 files changed, 24397 insertions(+) create mode 100755 RVO34/addSwitch.py create mode 100755 RVO34/cloud_topic.py create mode 100755 RVO34/config create mode 100755 RVO34/createNode.py create mode 100755 RVO34/databases/accelerometer_db.js create mode 100755 RVO34/databases/modbus_config.js create mode 100755 RVO34/databases/nodes.table create mode 100755 RVO34/databases/nodes_original/nodes_original.table create mode 100755 RVO34/databases/notifications.table create mode 100755 RVO34/databases/pins.table create mode 100755 RVO34/databases/relays.table create mode 100755 RVO34/databases/settings.table create mode 100755 RVO34/databases/tbdata.nosql create mode 100755 RVO34/databases/tbdatacloud.nosql create mode 100755 RVO34/databases/total_energy.js create mode 100755 RVO34/debug.js create mode 100755 RVO34/err.txt create mode 100755 RVO34/flow/cloudmqttconnect.js create mode 100755 RVO34/flow/cmd_manager.js create mode 100755 RVO34/flow/code.js create mode 100755 RVO34/flow/comment.js create mode 100755 RVO34/flow/count.js create mode 100755 RVO34/flow/db_connector.js create mode 100755 RVO34/flow/db_init.js create mode 100755 RVO34/flow/debug.js create mode 100755 RVO34/flow/designer.json create mode 100755 RVO34/flow/dido_controller.js create mode 100755 RVO34/flow/helper/DataToTbHandler.js create mode 100755 RVO34/flow/helper/ErrorToServiceHandler.js create mode 100755 RVO34/flow/helper/db_helper.js create mode 100755 RVO34/flow/helper/logger.js create mode 100755 RVO34/flow/helper/md5.js create mode 100755 RVO34/flow/helper/notification_reporter.js create mode 100755 RVO34/flow/helper/register.js create mode 100755 RVO34/flow/helper/serialport_helper.js create mode 100755 RVO34/flow/helper/suncalc.js create mode 100755 RVO34/flow/helper/utils.js create mode 100755 RVO34/flow/httprequest.js create mode 100755 RVO34/flow/httpresponse.js create mode 100755 RVO34/flow/httproute.js create mode 100755 RVO34/flow/infosender.js create mode 100755 RVO34/flow/modbus_reader.js create mode 100755 RVO34/flow/monitorconsumption.js create mode 100755 RVO34/flow/monitordisk.js create mode 100755 RVO34/flow/monitormemory.js create mode 100755 RVO34/flow/nodesdb_changecheck.js create mode 100755 RVO34/flow/show_dbdata.js create mode 100755 RVO34/flow/slack_filter.js create mode 100755 RVO34/flow/thermometer.js create mode 100755 RVO34/flow/trigger.js create mode 100755 RVO34/flow/variables.txt create mode 100755 RVO34/flow/virtualwirein.js create mode 100755 RVO34/flow/virtualwireout.js create mode 100755 RVO34/flow/wsmqttpublish.js create mode 100755 RVO34/monitor.txt create mode 100755 RVO34/package-lock.json create mode 100755 RVO34/package.json create mode 100755 RVO34/release.js create mode 100755 RVO34/release.js.json create mode 100755 RVO34/report_data.log diff --git a/RVO34/addSwitch.py b/RVO34/addSwitch.py new file mode 100755 index 0000000..c35e96b --- /dev/null +++ b/RVO34/addSwitch.py @@ -0,0 +1,36 @@ +import os + +def process_set_file(): + """ + Checks if /root/flowserver exists, reads set.txt, and modifies the second line. + """ + default_folder = "/root/flowserver" if os.path.exists("/root/flowserver") else "/home/unipi/flowserver" + flag = 1 if default_folder == "/root/flowserver" else 0 + + try: + with open("/home/unipi/flowserver/databases/settings.table", "r") as f: + lines = f.readlines() + + if len(lines) >= 2: + lines[0] = lines[0].rstrip('\n') + "|main_switch:boolean\n" + second_line = lines[1].strip() # remove trailing newline + last_pipe_index = second_line.rfind("|") + + if last_pipe_index != -1: + modified_line = second_line[:last_pipe_index + 1] + str(flag) + "|" + second_line[last_pipe_index + 1:] + lines[1] = modified_line + else: + print("Warning: No '|' character found in the second line of set.txt") + + with open("/home/unipi/flowserver/databases/settings.table", "w") as f: + f.writelines(lines) + else: + print("Warning: settings.table has less than two lines.") + + except FileNotFoundError: + print("Error: settings.table not found.") + except Exception as e: + print(e) + +# if __name__ == "__main__": +process_set_file() diff --git a/RVO34/cloud_topic.py b/RVO34/cloud_topic.py new file mode 100755 index 0000000..77c31f1 --- /dev/null +++ b/RVO34/cloud_topic.py @@ -0,0 +1,76 @@ +# import os +# +# def modify_file(file_path): +# """ +# Modifies the given file by: +# 1. Appending "|cloud_topic" to the first line. +# 2. Inserting the text from the third "." to the first "|" on the second line after the last "|" character. +# +# Args: +# file_path (str): The path to the file to be modified. +# """ +# +# with open(file_path, 'r+') as f: +# lines = f.readlines() +# +# # Modify the first line +# lines[0] += "|cloud_topic:string" +# +# # Modify the second line +# second_line = lines[1].strip() # Remove leading/trailing whitespace +# first_pipe_index = second_line.find('|') +# third_dot_index = second_line.find('.', second_line.find('.', second_line.find('.') + 1) + 1) +# text_to_insert = second_line[third_dot_index:first_pipe_index] +# +# last_pipe_index = second_line.rfind('|') +# lines[1] = second_line[:last_pipe_index + 1] + text_to_insert + "|" + second_line[last_pipe_index + 1:] +# +# print(first_pipe_index, third_dot_index, text_to_insert, last_pipe_index) +# # Write the modified lines back to the file +# # f.seek(0) +# # f.writelines(lines) +# # f.truncate() +# +# # Example usage: +# file_path = "settings.table" # Replace with the actual file path +# modify_file(file_path) +# + + +def modify_file(file_path): + """ + Modifies the given file by: + 1. Appending "|cloud_topic" to the first line. + 2. Inserting the text between the third "." and the second "|" on the second line after the last "|" character. + + Args: + file_path (str): The path to the file to be modified. + """ + + with open(file_path, 'r+') as f: + lines = f.readlines() + + first_line = lines[0].strip() + first_line += "|cloud_topic:string\n" + # Modify the first line + lines[0] = first_line + + # Modify the second line + second_line = lines[1].strip() # Remove leading/trailing whitespace + first_pipe_index = second_line.find('|') + second_pipe_index = second_line.find('|', first_pipe_index + 1) + third_dot_index = second_line.find('.', second_line.find('.', second_line.find('.') + 1) + 1) + text_to_insert = "u" + second_line[third_dot_index+1:second_pipe_index] + + last_pipe_index = second_line.rfind('|') + lines[1] = second_line[:last_pipe_index + 1] + text_to_insert + "|" + second_line[last_pipe_index + 1:] + + print(first_pipe_index, third_dot_index, text_to_insert, last_pipe_index) + # Write the modified lines back to the file + f.seek(0) + f.writelines(lines) + f.truncate() + +# Example usage: +file_path = "/home/unipi/flowserver/databases/settings.table" # Replace with the actual file path +modify_file(file_path) diff --git a/RVO34/config b/RVO34/config new file mode 100755 index 0000000..cd0a8a9 --- /dev/null +++ b/RVO34/config @@ -0,0 +1,12 @@ +name : Total.js Flow +default_timezone : Europe/Bratislava + +// Packages settings +package#flow (Object) : { url: '/' } + + +table.relays : line:number|tbname:string|contactor:number|profile:string +table.nodes : node:number|pole_number:string|node_type:string|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|project_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|cloud_topic:string|has_main_switch:boolean|daily_report:boolean|send_changed_node_numbers:boolean +table.pins : pin:string|type:string|line:number +table.notifications : key:string|weight:string|sk:string|en:string diff --git a/RVO34/createNode.py b/RVO34/createNode.py new file mode 100755 index 0000000..a8cea91 --- /dev/null +++ b/RVO34/createNode.py @@ -0,0 +1,43 @@ +print("zaciname") +import re, json + +search_str = '|' +final = [] +counter = 1 +with open("/home/unipi/flowserver/databases/nodes.table", 'r') as file: +# with open("/home/rasta5man/dev/oms/flowserver/databases/nodes.table", 'r') as file: + # Read each line in the file + for line in file: + # Print each line + line = line.strip() + print(line) + if counter != 1: + i = [m.start() for m in re.finditer(re.escape(search_str), line)] + node = line[ i[0] + 1 : i[1] ] + tbname = line[ i[3] + 1 : i[4] ] + final.append({node:tbname}) + counter += 1 +print(json.dumps(final)) +f = open("/home/unipi/flowserver/databases/nodes_original/nodes_original.table", "w") +f.write(json.dumps(final)) +f.close() + + +# +# # ``d`` has to be replaced with a different character +# old_character = "'" +# +# # ``t`` will replace ``d` +# new_character = '"' +# resultant_string = 0; +# with open("/home/unipi/flowserver/databases/nodes_original/nodes_original.table", 'r') as file: +# for line in file: +# resultant_string = re.sub("'", '"', line) +# +# resultant_string = re.sub(" ", "", resultant_string) +# print(resultant_string) +# +# f = open("/home/unipi/flowserver/databases/nodes_original/nodes_original.table", "w") +# f.write(str(resultant_string)) +# f.close() +# diff --git a/RVO34/databases/accelerometer_db.js b/RVO34/databases/accelerometer_db.js new file mode 100755 index 0000000..fdfc7fd --- /dev/null +++ b/RVO34/databases/accelerometer_db.js @@ -0,0 +1,3055 @@ +let naklony = { + "3993": { "label": "1/3A", "naklon": 0 }, + "3989": { "label": "1/3B", "naklon": 15 }, + "3976": { "label": "1/1", "naklon": 0 }, + "4181": { "label": "1/2", "naklon": 0 }, + "4376": { "label": "1/4", "naklon": 15 }, + "3868": { "label": "1/5", "naklon": 15 }, + "3728": { "label": "1/6", "naklon": 15 }, + "3730": { "label": "1/7", "naklon": 0 }, + "4374": { "label": "1/8", "naklon": 0 }, + "3718": { "label": "1/9", "naklon": 15 }, + "4375": { "label": "1/10", "naklon": 15 }, + "4172": { "label": "1/11", "naklon": 15 }, + "4176": { "label": "1/12", "naklon": 15 }, + "3800": { "label": "2/1", "naklon": 5 }, + "3823": { "label": "2/2", "naklon": 5 }, + "3905": { "label": "2/3", "naklon": 5 }, + "3803": { "label": "2/4", "naklon": 5 }, + "3817": { "label": "2/5", "naklon": 5 }, + "3818": { "label": "2/6", "naklon": 5 }, + "3811": { "label": "2/7", "naklon": 5 }, + "3915": { "label": "2/8", "naklon": 5 }, + "3843": { "label": "2/9", "naklon": 10 }, + "3827": { "label": "2/10", "naklon": 10 }, + "4220": { "label": "2/11", "naklon": 10 }, + "3826": { "label": "2/12", "naklon": 10 }, + "3834": { "label": "2/13", "naklon": 10 }, + "3838": { "label": "2/14", "naklon": 10 }, + "2823": { "label": "2/15", "naklon": 10 }, + "3750": { "label": "2/16", "naklon": 10 }, + "3378": { "label": "2/17", "naklon": 0 }, + "3376": { "label": "2/18", "naklon": 0 }, + "3379": { "label": "2/19", "naklon": 0 }, + "3285": { "label": "2/20", "naklon": 0 }, + "3382": { "label": "2/21", "naklon": 0 }, + "3383": { "label": "2/22", "naklon": 0 }, + "3375": { "label": "2/24", "naklon": 0 }, + "3381": { "label": "2/25", "naklon": 0 }, + "3380": { "label": "2/26", "naklon": 0 }, + "3828": { "label": "2/27", "naklon": 10 }, + "3377": { "label": "2/28", "naklon": 0 }, + "3591": { "label": "7/1", "naklon": 0 }, + "3587": { "label": "7/2", "naklon": 0 }, + "3468": { "label": "7/3", "naklon": 0 }, + "3466": { "label": "7/4", "naklon": 0 }, + "3474": { "label": "7/5", "naklon": 0 }, + "3481": { "label": "7/6", "naklon": 0 }, + "3589": { "label": "7/7", "naklon": 0 }, + "3472": { "label": "7/8", "naklon": 0 }, + "3473": { "label": "7/9", "naklon": 0 }, + "3584": { "label": "7/10", "naklon": 0 }, + "3571": { "label": "7/11", "naklon": 0 }, + "3476": { "label": "7/12", "naklon": 0 }, + "3590": { "label": "7/13", "naklon": 0 }, + "3478": { "label": "7/14", "naklon": 0 }, + "3471": { "label": "7/15", "naklon": 0 }, + "3467": { "label": "7/16", "naklon": 0 }, + "3479": { "label": "7/17", "naklon": 0 }, + "3480": { "label": "7/18", "naklon": 0 }, + "3477": { "label": "7/19", "naklon": 0 }, + "3362": { "label": "12/1", "naklon": 0 }, + "3355": { "label": "12/2", "naklon": 0 }, + "3356": { "label": "12/3", "naklon": 0 }, + "3349": { "label": "12/4", "naklon": 0 }, + "3357": { "label": "12/5", "naklon": 0 }, + "3350": { "label": "12/6", "naklon": 0 }, + "3353": { "label": "12/7", "naklon": 0 }, + "3539": { "label": "12/8", "naklon": 0 }, + "3050": { "label": "12/9", "naklon": 0 }, + "3361": { "label": "12/10", "naklon": 0 }, + "3360": { "label": "12/11", "naklon": 0 }, + "3358": { "label": "12/12", "naklon": 0 }, + "3541": { "label": "12/13", "naklon": 0 }, + "3551": { "label": "12/14", "naklon": 0 }, + "3514": { "label": "12/15", "naklon": 0 }, + "3547": { "label": "12/16", "naklon": 0 }, + "3562": { "label": "12/17", "naklon": 0 }, + "3525": { "label": "12/18", "naklon": 0 }, + "3558": { "label": "12/19", "naklon": 0 }, + "3511": { "label": "12/20", "naklon": 0 }, + "3058": { "label": "12/21", "naklon": 0 }, + "3062": { "label": "12/22", "naklon": 0 }, + "3070": { "label": "12/23", "naklon": 0 }, + "3447": { "label": "12/24", "naklon": 0 }, + "3056": { "label": "12/25", "naklon": 0 }, + "3057": { "label": "12/26", "naklon": 0 }, + "3071": { "label": "12/27", "naklon": 0 }, + "3061": { "label": "12/28", "naklon": 0 }, + "3069": { "label": "12/29", "naklon": 0 }, + "3077": { "label": "12/30", "naklon": 0 }, + "3080": { "label": "12/31", "naklon": 0 }, + "3081": { "label": "12/32", "naklon": 0 }, + "3078": { "label": "12/33", "naklon": 0 }, + "4037": { "label": "12/34", "naklon": 0 }, + "3067": { "label": "12/35", "naklon": 0 }, + "3051": { "label": "12/36", "naklon": 0 }, + "2924": { "label": "12/37", "naklon": 0 }, + "3060": { "label": "12/38", "naklon": 0 }, + "3073": { "label": "12/39", "naklon": 0 }, + "3469": { "label": "12/40", "naklon": 0 }, + "2923": { "label": "12/41", "naklon": 0 }, + "2925": { "label": "12/42", "naklon": 0 }, + "3359": { "label": "12/43", "naklon": 0 }, + "3055": { "label": "12/44", "naklon": 0 }, + "2922": { "label": "12/45", "naklon": 0 }, + "3084": { "label": "12/46", "naklon": 0 }, + "3064": { "label": "12/47", "naklon": 0 }, + "3066": { "label": "12/48", "naklon": 0 }, + "3072": { "label": "12/49", "naklon": 0 }, + "3415": { "label": "13/13A", "naklon": 0 }, + "3409": { "label": "13/13B", "naklon": 0 }, + "3399": { "label": "13/13C", "naklon": 0 }, + "3410": { "label": "13/29A", "naklon": 0 }, + "3407": { "label": "13/29B", "naklon": 0 }, + "3405": { "label": "13/34A", "naklon": 0 }, + "3404": { "label": "13/34B", "naklon": 0 }, + "3392": { "label": "13/45A", "naklon": 0 }, + "3386": { "label": "13/45B", "naklon": 0 }, + "3303": { "label": "13/60A", "naklon": 3 }, + "3302": { "label": "13/60B", "naklon": 3 }, + "3319": { "label": "13/70A", "naklon": 6 }, + "3317": { "label": "13/70B", "naklon": 6 }, + "3326": { "label": "13/70C", "naklon": 6 }, + "3351": { "label": "13/73A", "naklon": 6 }, + "3313": { "label": "13/73B", "naklon": 6 }, + "3316": { "label": "13/83A", "naklon": 0 }, + "3320": { "label": "13/83B", "naklon": 0 }, + "3336": { "label": "13/95A", "naklon": 0 }, + "3323": { "label": "13/95B", "naklon": 0 }, + "3339": { "label": "13/98A", "naklon": 0 }, + "3333": { "label": "13/98B", "naklon": 0 }, + "3425": { "label": "13/1", "naklon": 0 }, + "3419": { "label": "13/2", "naklon": 0 }, + "3416": { "label": "13/3", "naklon": 0 }, + "3332": { "label": "13/4", "naklon": 0 }, + "3422": { "label": "13/5", "naklon": 0 }, + "3417": { "label": "13/6", "naklon": 0 }, + "3418": { "label": "13/7", "naklon": 0 }, + "3424": { "label": "13/8", "naklon": 0 }, + "3334": { "label": "13/9", "naklon": 0 }, + "4363": { "label": "13/10", "naklon": 0 }, + "3423": { "label": "13/11", "naklon": 0 }, + "3406": { "label": "13/12", "naklon": 0 }, + "3411": { "label": "13/14", "naklon": 0 }, + "3412": { "label": "13/15", "naklon": 0 }, + "3413": { "label": "13/16", "naklon": 0 }, + "3414": { "label": "13/17", "naklon": 0 }, + "3391": { "label": "13/18", "naklon": 0 }, + "3370": { "label": "13/19", "naklon": 0 }, + "3369": { "label": "13/20", "naklon": 0 }, + "3408": { "label": "13/21", "naklon": 0 }, + "3393": { "label": "13/22", "naklon": 0 }, + "3128": { "label": "13/23", "naklon": 0 }, + "3197": { "label": "13/24", "naklon": 0 }, + "4364": { "label": "13/25", "naklon": 0 }, + "3155": { "label": "13/26", "naklon": 0 }, + "3196": { "label": "13/27", "naklon": 0 }, + "3144": { "label": "13/28", "naklon": 0 }, + "3150": { "label": "13/30", "naklon": 0 }, + "3390": { "label": "13/31", "naklon": 0 }, + "3401": { "label": "13/32", "naklon": 0 }, + "3275": { "label": "13/33", "naklon": 0 }, + "3371": { "label": "13/35", "naklon": 0 }, + "3389": { "label": "13/36", "naklon": 0 }, + "3388": { "label": "13/37", "naklon": 0 }, + "3365": { "label": "13/38", "naklon": 0 }, + "3363": { "label": "13/39", "naklon": 0 }, + "3397": { "label": "13/40", "naklon": 0 }, + "3567": { "label": "13/40/1", "naklon": 0 }, + "3387": { "label": "13/41", "naklon": 0 }, + "3403": { "label": "13/42", "naklon": 0 }, + "3147": { "label": "13/43", "naklon": 0 }, + "3141": { "label": "13/44", "naklon": 0 }, + "3364": { "label": "13/46", "naklon": 0 }, + "3367": { "label": "13/47", "naklon": 0 }, + "3368": { "label": "13/48", "naklon": 0 }, + "3402": { "label": "13/49", "naklon": 0 }, + "3366": { "label": "13/50", "naklon": 0 }, + "3395": { "label": "13/51", "naklon": 0 }, + "3372": { "label": "13/52", "naklon": 0 }, + "3394": { "label": "13/53", "naklon": 0 }, + "3308": { "label": "13/54", "naklon": 0 }, + "3847": { "label": "13/54/1", "naklon": 0 }, + "3312": { "label": "13/55", "naklon": 3 }, + "3309": { "label": "13/56", "naklon": 3 }, + "3311": { "label": "13/57", "naklon": 3 }, + "3310": { "label": "13/58", "naklon": 3 }, + "4365": { "label": "13/59", "naklon": 3 }, + "4093": { "label": "13/60/1", "naklon": 3 }, + "3304": { "label": "13/61", "naklon": 3 }, + "3307": { "label": "13/62", "naklon": 3 }, + "3271": { "label": "13/63", "naklon": 3 }, + "3301": { "label": "13/64", "naklon": 3 }, + "4366": { "label": "13/65", "naklon": 3 }, + "3300": { "label": "13/66", "naklon": 3 }, + "3185": { "label": "13/67", "naklon": 0 }, + "3184": { "label": "13/68", "naklon": 0 }, + "3188": { "label": "13/69", "naklon": 0 }, + "3343": { "label": "13/71", "naklon": 6 }, + "3819": { "label": "13/71/1", "naklon": 6 }, + "3880": { "label": "13/71/2", "naklon": 6 }, + "3348": { "label": "13/72", "naklon": 6 }, + "3344": { "label": "13/74", "naklon": 6 }, + "3346": { "label": "13/75", "naklon": 6 }, + "3597": { "label": "13/75/1", "naklon": 6 }, + "3345": { "label": "13/76", "naklon": 6 }, + "3322": { "label": "13/77", "naklon": 0 }, + "3325": { "label": "13/78", "naklon": 0 }, + "4310": { "label": "13/78/1", "naklon": 0 }, + "3315": { "label": "13/79", "naklon": 0 }, + "3328": { "label": "13/80", "naklon": 0 }, + "3321": { "label": "13/81", "naklon": 0 }, + "3324": { "label": "13/82", "naklon": 0 }, + "3140": { "label": "13/84", "naklon": 0 }, + "3153": { "label": "13/85", "naklon": 0 }, + "3145": { "label": "13/86", "naklon": 0 }, + "3134": { "label": "13/87", "naklon": 0 }, + "3151": { "label": "13/88", "naklon": 0 }, + "3143": { "label": "13/89", "naklon": 0 }, + "3318": { "label": "13/90", "naklon": 0 }, + "3347": { "label": "13/91", "naklon": 0 }, + "3314": { "label": "13/94", "naklon": 0 }, + "3331": { "label": "13/96", "naklon": 0 }, + "3327": { "label": "13/97", "naklon": 0 }, + "3329": { "label": "13/99", "naklon": 0 }, + "3337": { "label": "13/100", "naklon": 0 }, + "3330": { "label": "13/101", "naklon": 0 }, + "3335": { "label": "13/102", "naklon": 0 }, + "3420": { "label": "13/103", "naklon": 0 }, + "3421": { "label": "13/104", "naklon": 0 }, + "4361": { "label": "13/105", "naklon": 0 }, + "4362": { "label": "13/106", "naklon": 0 }, + "3526": { "label": "13/107", "naklon": 0 }, + "4424": { "label": "13/108", "naklon": null }, + "3561": { "label": "13/109", "naklon": null }, + "3527": { "label": "13/110", "naklon": null }, + "3521": { "label": "13/111", "naklon": null }, + "3552": { "label": "13/112", "naklon": null }, + "3544": { "label": "13/113", "naklon": null }, + "3534": { "label": "13/114", "naklon": null }, + "3516": { "label": "13/115", "naklon": null }, + "3513": { "label": "13/116", "naklon": null }, + "3565": { "label": "13/117", "naklon": null }, + "3866": { "label": "13/118", "naklon": null }, + "3136": { "label": "14/1", "naklon": 0 }, + "3137": { "label": "14/2", "naklon": 0 }, + "3135": { "label": "14/3", "naklon": 0 }, + "3149": { "label": "14/4", "naklon": 0 }, + "3142": { "label": "14/5", "naklon": 0 }, + "3342": { "label": "14/6", "naklon": 0 }, + "3340": { "label": "14/7", "naklon": 0 }, + "3152": { "label": "14/8", "naklon": 0 }, + "3886": { "label": "14/9", "naklon": 0 }, + "3341": { "label": "14/10", "naklon": null }, + "3352": { "label": "14/11", "naklon": null }, + "3396": { "label": "15/1", "naklon": 5 }, + "2784": { "label": "15/2", "naklon": 5 }, + "2788": { "label": "15/3", "naklon": 5 }, + "2801": { "label": "15/4", "naklon": 5 }, + "2815": { "label": "15/5", "naklon": 5 }, + "2829": { "label": "15/6", "naklon": 5 }, + "2796": { "label": "15/7", "naklon": 5 }, + "2803": { "label": "15/8", "naklon": 5 }, + "4304": { "label": "15/8/1", "naklon": 5 }, + "4311": { "label": "15/8/2", "naklon": 5 }, + "2821": { "label": "15/9", "naklon": 5 }, + "3400": { "label": "15/10", "naklon": 5 }, + "2799": { "label": "15/11", "naklon": 5 }, + "2804": { "label": "15/12", "naklon": 5 }, + "4303": { "label": "15/12/1", "naklon": 5 }, + "4309": { "label": "15/12/2", "naklon": 5 }, + "2806": { "label": "15/13", "naklon": 5 }, + "2787": { "label": "15/14", "naklon": 5 }, + "2809": { "label": "15/15", "naklon": 5 }, + "2814": { "label": "15/16", "naklon": 0 }, + "3934": { "label": "15/17", "naklon": 0 }, + "3192": { "label": "15/18", "naklon": 0 }, + "2812": { "label": "15/19", "naklon": 0 }, + "4070": { "label": "15/20", "naklon": 0 }, + "2826": { "label": "15/21", "naklon": 0 }, + "2808": { "label": "15/22", "naklon": 3 }, + "2795": { "label": "15/23", "naklon": 3 }, + "2807": { "label": "15/24", "naklon": 3 }, + "2831": { "label": "15/25", "naklon": 0 }, + "2862": { "label": "15/26", "naklon": null }, + "2861": { "label": "15/27", "naklon": 0 }, + "2866": { "label": "15/28", "naklon": 0 }, + "3546": { "label": "15/28/1", "naklon": 0 }, + "4146": { "label": "15/29", "naklon": 0 }, + "3001": { "label": "15/29/1", "naklon": 0 }, + "2835": { "label": "15/30", "naklon": 0 }, + "2874": { "label": "15/31", "naklon": 0 }, + "2852": { "label": "15/32", "naklon": 0 }, + "2851": { "label": "15/33", "naklon": 0 }, + "3560": { "label": "15/33/1", "naklon": 0 }, + "2858": { "label": "15/34", "naklon": 0 }, + "4306": { "label": "15/34/1", "naklon": 0 }, + "2856": { "label": "15/35", "naklon": 0 }, + "2847": { "label": "15/36", "naklon": 0 }, + "3556": { "label": "15/36/1", "naklon": 0 }, + "3950": { "label": "15/37", "naklon": 0 }, + "2848": { "label": "15/38", "naklon": 0 }, + "2863": { "label": "15/39", "naklon": 0 }, + "4313": { "label": "15/39/1", "naklon": 0 }, + "2873": { "label": "15/40", "naklon": 0 }, + "2984": { "label": "15/40/1", "naklon": 0 }, + "2854": { "label": "15/41", "naklon": 0 }, + "2859": { "label": "15/42", "naklon": 0 }, + "2872": { "label": "15/43", "naklon": 0 }, + "2849": { "label": "15/44", "naklon": 0 }, + "2864": { "label": "15/45", "naklon": 0 }, + "3553": { "label": "15/46", "naklon": null }, + "3021": { "label": "15/47", "naklon": null }, + "3008": { "label": "15/47/1", "naklon": null }, + "3017": { "label": "15/48", "naklon": null }, + "3014": { "label": "15/49", "naklon": null }, + "2981": { "label": "15/50", "naklon": null }, + "3020": { "label": "15/51", "naklon": null }, + "3027": { "label": "15/52", "naklon": null }, + "3006": { "label": "15/53", "naklon": null }, + "3012": { "label": "15/54", "naklon": null }, + "2738": { "label": "15/55", "naklon": 0 }, + "2725": { "label": "15/56", "naklon": 0 }, + "3016": { "label": "15/57", "naklon": null }, + "3005": { "label": "15/58", "naklon": null }, + "3009": { "label": "15/58/1", "naklon": null }, + "3010": { "label": "15/59", "naklon": 0 }, + "3538": { "label": "15/59/1", "naklon": 0 }, + "4145": { "label": "15/59/2", "naklon": 0 }, + "2713": { "label": "15/60", "naklon": 0 }, + "2789": { "label": "15/61", "naklon": 0 }, + "2736": { "label": "15/62", "naklon": 0 }, + "2739": { "label": "15/63", "naklon": 0 }, + "4346": { "label": "15/64", "naklon": 0 }, + "2731": { "label": "15/65", "naklon": 0 }, + "2818": { "label": "15/66", "naklon": 0 }, + "3557": { "label": "15/66/1", "naklon": 0 }, + "2822": { "label": "15/67", "naklon": 0 }, + "2833": { "label": "15/68", "naklon": 0 }, + "2834": { "label": "15/69", "naklon": 0 }, + "3097": { "label": "15/70", "naklon": 0 }, + "2824": { "label": "15/71", "naklon": 0 }, + "2828": { "label": "15/72", "naklon": 0 }, + "2600": { "label": "15/73", "naklon": 0 }, + "4314": { "label": "15/73/1", "naklon": 0 }, + "2832": { "label": "15/74", "naklon": 0 }, + "4360": { "label": "15/75", "naklon": 0 }, + "2846": { "label": "15/76", "naklon": 0 }, + "2584": { "label": "15/77", "naklon": 0 }, + "2843": { "label": "15/78", "naklon": 0 }, + "4308": { "label": "15/78/1", "naklon": 0 }, + "4144": { "label": "15/79", "naklon": null }, + "2844": { "label": "15/80", "naklon": 0 }, + "2842": { "label": "15/81", "naklon": 0 }, + "2838": { "label": "15/82", "naklon": 0 }, + "2837": { "label": "15/83", "naklon": null }, + "3555": { "label": "15/83/1", "naklon": null }, + "2839": { "label": "15/84", "naklon": 0 }, + "2830": { "label": "15/85", "naklon": 0 }, + "4066": { "label": "15/86", "naklon": 0 }, + "2836": { "label": "15/87", "naklon": 0 }, + "2911": { "label": "15/88", "naklon": 0 }, + "2825": { "label": "15/89", "naklon": 0 }, + "2811": { "label": "15/90", "naklon": 0 }, + "3740": { "label": "15/94", "naklon": 15 }, + "2734": { "label": "15/95", "naklon": 15 }, + "3105": { "label": "15/96", "naklon": 15 }, + "2732": { "label": "15/97", "naklon": 15 }, + "2727": { "label": "15/98", "naklon": 15 }, + "2735": { "label": "15/99", "naklon": 15 }, + "3926": { "label": "15/100", "naklon": 15 }, + "2918": { "label": "15/101", "naklon": 0 }, + "2705": { "label": "15/102", "naklon": 10 }, + "2708": { "label": "15/103", "naklon": 10 }, + "2721": { "label": "15/104", "naklon": 10 }, + "2719": { "label": "15/105", "naklon": 10 }, + "2919": { "label": "15/106", "naklon": 10 }, + "3101": { "label": "15/107", "naklon": 10 }, + "2853": { "label": "15/108", "naklon": 10 }, + "2715": { "label": "15/109", "naklon": 10 }, + "2712": { "label": "15/110", "naklon": 0 }, + "2711": { "label": "15/111", "naklon": 0 }, + "2709": { "label": "15/112", "naklon": 0 }, + "2710": { "label": "15/113", "naklon": 0 }, + "2907": { "label": "15/114", "naklon": 0 }, + "2906": { "label": "15/115", "naklon": 0 }, + "2908": { "label": "15/116", "naklon": 0 }, + "2901": { "label": "15/117", "naklon": 0 }, + "2913": { "label": "15/118", "naklon": 0 }, + "3656": { "label": "15/119", "naklon": 0 }, + "2781": { "label": "15/120", "naklon": 0 }, + "2802": { "label": "15/121", "naklon": 0 }, + "2791": { "label": "15/122", "naklon": 0 }, + "2783": { "label": "15/123", "naklon": 0 }, + "2794": { "label": "15/124", "naklon": 0 }, + "3139": { "label": "15/125", "naklon": 0 }, + "3229": { "label": "15/126", "naklon": 5 }, + "3239": { "label": "15/127", "naklon": 5 }, + "3230": { "label": "15/128", "naklon": 5 }, + "4016": { "label": "15/129", "naklon": null }, + "3608": { "label": "16/16A", "naklon": 0 }, + "4151": { "label": "16/16B", "naklon": 0 }, + "3710": { "label": "16/1", "naklon": 0 }, + "3726": { "label": "16/2", "naklon": 0 }, + "3743": { "label": "16/3", "naklon": 0 }, + "3724": { "label": "16/4", "naklon": 0 }, + "3712": { "label": "16/5", "naklon": 0 }, + "3739": { "label": "16/6", "naklon": 0 }, + "3742": { "label": "16/7", "naklon": 0 }, + "3731": { "label": "16/8", "naklon": 0 }, + "3727": { "label": "16/9", "naklon": 0 }, + "3729": { "label": "16/10", "naklon": 0 }, + "3736": { "label": "16/11", "naklon": 0 }, + "3713": { "label": "16/12", "naklon": 0 }, + "3715": { "label": "16/13", "naklon": 0 }, + "3733": { "label": "16/14", "naklon": 0 }, + "3732": { "label": "16/15", "naklon": 0 }, + "3634": { "label": "16/17", "naklon": 0 }, + "3610": { "label": "16/18", "naklon": 0 }, + "3626": { "label": "16/19", "naklon": 0 }, + "3618": { "label": "16/20", "naklon": 0 }, + "3619": { "label": "16/21", "naklon": 0 }, + "3628": { "label": "16/22", "naklon": 0 }, + "3615": { "label": "16/23", "naklon": 0 }, + "3609": { "label": "16/24", "naklon": 0 }, + "3606": { "label": "16/25", "naklon": 0 }, + "3624": { "label": "16/26", "naklon": 0 }, + "3627": { "label": "16/27", "naklon": 0 }, + "3607": { "label": "16/28", "naklon": 0 }, + "4370": { "label": "16/29", "naklon": 0 }, + "3692": { "label": "16/30", "naklon": 0 }, + "3614": { "label": "16/31", "naklon": 0 }, + "3623": { "label": "16/32", "naklon": 0 }, + "4373": { "label": "16/33", "naklon": 0 }, + "3620": { "label": "16/34", "naklon": 0 }, + "3685": { "label": "16/35", "naklon": 0 }, + "3616": { "label": "16/36", "naklon": 0 }, + "3686": { "label": "16/37", "naklon": 0 }, + "3688": { "label": "16/38", "naklon": 0 }, + "3684": { "label": "16/39", "naklon": 0 }, + "3825": { "label": "16/40", "naklon": 0 }, + "3865": { "label": "16/41", "naklon": 0 }, + "3824": { "label": "16/42", "naklon": 0 }, + "3871": { "label": "16/43", "naklon": 0 }, + "3801": { "label": "16/44", "naklon": 0 }, + "3862": { "label": "16/45", "naklon": 0 }, + "3876": { "label": "16/46", "naklon": 0 }, + "3861": { "label": "16/47", "naklon": 0 }, + "4215": { "label": "16/48", "naklon": 0 }, + "3605": { "label": "16/49", "naklon": 10 }, + "3603": { "label": "16/50", "naklon": 10 }, + "3592": { "label": "16/51", "naklon": 10 }, + "3598": { "label": "16/52", "naklon": 10 }, + "3594": { "label": "16/53", "naklon": 10 }, + "3593": { "label": "16/54", "naklon": 10 }, + "3630": { "label": "16/55", "naklon": 10 }, + "3763": { "label": "16/56", "naklon": 10 }, + "3746": { "label": "16/57", "naklon": 10 }, + "3699": { "label": "16/58", "naklon": 0 }, + "3698": { "label": "16/59", "naklon": 0 }, + "3709": { "label": "16/60", "naklon": null }, + "3708": { "label": "16/61", "naklon": 0 }, + "3703": { "label": "16/62", "naklon": null }, + "3700": { "label": "16/63", "naklon": 0 }, + "3701": { "label": "16/64", "naklon": null }, + "3704": { "label": "16/65", "naklon": 0 }, + "3707": { "label": "16/66", "naklon": null }, + "3810": { "label": "16/67", "naklon": 0 }, + "4208": { "label": "16/68", "naklon": null }, + "3867": { "label": "16/69", "naklon": 0 }, + "4372": { "label": "16/70", "naklon": null }, + "3881": { "label": "16/71", "naklon": 0 }, + "4204": { "label": "16/72", "naklon": null }, + "3869": { "label": "16/73", "naklon": 0 }, + "4202": { "label": "16/74", "naklon": null }, + "3830": { "label": "16/75", "naklon": 0 }, + "3870": { "label": "16/76", "naklon": null }, + "3964": { "label": "16/77", "naklon": 0 }, + "3849": { "label": "16/78", "naklon": 0 }, + "3694": { "label": "16/79", "naklon": null }, + "3717": { "label": "16/80", "naklon": 0 }, + "3877": { "label": "16/81", "naklon": null }, + "3755": { "label": "16/82", "naklon": 0 }, + "3725": { "label": "16/83", "naklon": null }, + "3716": { "label": "16/84", "naklon": 0 }, + "3696": { "label": "16/85", "naklon": null }, + "3702": { "label": "16/86", "naklon": 0 }, + "3706": { "label": "16/87", "naklon": null }, + "3850": { "label": "16/88", "naklon": 0 }, + "3848": { "label": "16/89", "naklon": null }, + "3737": { "label": "16/90", "naklon": null }, + "3705": { "label": "16/91", "naklon": 0 }, + "3723": { "label": "16/92", "naklon": null }, + "3842": { "label": "16/93", "naklon": 0 }, + "3735": { "label": "16/94", "naklon": null }, + "3719": { "label": "16/95", "naklon": 0 }, + "3697": { "label": "16/96", "naklon": 0 }, + "3711": { "label": "16/97", "naklon": 0 }, + "4107": { "label": "16/98", "naklon": null }, + "4112": { "label": "16/99", "naklon": 5 }, + "4106": { "label": "16/100", "naklon": 5 }, + "4111": { "label": "16/101", "naklon": 5 }, + "4091": { "label": "16/102", "naklon": null }, + "4104": { "label": "16/103", "naklon": 5 }, + "4094": { "label": "16/104", "naklon": null }, + "4089": { "label": "16/105", "naklon": 5 }, + "4095": { "label": "16/106", "naklon": null }, + "4102": { "label": "16/107", "naklon": 5 }, + "4105": { "label": "16/108", "naklon": null }, + "3859": { "label": "16/109", "naklon": null }, + "4090": { "label": "16/110", "naklon": 5 }, + "4110": { "label": "16/111", "naklon": null }, + "4097": { "label": "16/112", "naklon": 5 }, + "4099": { "label": "16/113", "naklon": null }, + "4096": { "label": "16/114", "naklon": null }, + "4101": { "label": "16/115", "naklon": 5 }, + "4109": { "label": "16/116", "naklon": null }, + "4092": { "label": "16/117", "naklon": 5 }, + "3631": { "label": "16/118", "naklon": null }, + "3632": { "label": "16/119", "naklon": 0 }, + "3641": { "label": "16/120", "naklon": null }, + "3638": { "label": "16/121", "naklon": 0 }, + "3637": { "label": "16/122", "naklon": null }, + "4142": { "label": "16/123", "naklon": null }, + "4147": { "label": "16/124", "naklon": 5 }, + "4139": { "label": "16/125", "naklon": 5 }, + "3172": { "label": "20/30A", "naklon": 2 }, + "3164": { "label": "20/30B", "naklon": 2 }, + "3247": { "label": "20/1", "naklon": 10 }, + "3296": { "label": "20/2", "naklon": 10 }, + "3246": { "label": "20/3", "naklon": 10 }, + "3270": { "label": "20/4", "naklon": 10 }, + "3294": { "label": "20/5", "naklon": 10 }, + "3298": { "label": "20/6", "naklon": 10 }, + "3297": { "label": "20/7", "naklon": 10 }, + "3293": { "label": "20/8", "naklon": 10 }, + "3299": { "label": "20/9", "naklon": 10 }, + "3295": { "label": "20/10", "naklon": 10 }, + "3244": { "label": "20/11", "naklon": 10 }, + "3249": { "label": "20/12", "naklon": 10 }, + "3268": { "label": "20/13", "naklon": 10 }, + "3245": { "label": "20/14", "naklon": 10 }, + "3278": { "label": "20/15", "naklon": 10 }, + "3280": { "label": "20/16", "naklon": 10 }, + "3292": { "label": "20/17", "naklon": 10 }, + "3287": { "label": "20/18", "naklon": 10 }, + "3282": { "label": "20/19", "naklon": 10 }, + "3273": { "label": "20/20", "naklon": 0 }, + "3157": { "label": "20/21", "naklon": 0 }, + "3283": { "label": "20/22", "naklon": 0 }, + "3159": { "label": "20/23", "naklon": 0 }, + "3289": { "label": "20/24", "naklon": 0 }, + "3163": { "label": "20/25", "naklon": 0 }, + "3126": { "label": "20/26", "naklon": 0 }, + "3171": { "label": "20/27", "naklon": 0 }, + "3162": { "label": "20/28", "naklon": 0 }, + "3279": { "label": "20/29", "naklon": 10 }, + "3173": { "label": "20/31", "naklon": 0 }, + "3127": { "label": "20/32", "naklon": 0 }, + "3131": { "label": "20/33", "naklon": 0 }, + "3129": { "label": "20/34", "naklon": 0 }, + "3276": { "label": "20/35", "naklon": 2 }, + "3290": { "label": "20/36", "naklon": 2 }, + "3132": { "label": "20/37", "naklon": 0 }, + "3138": { "label": "20/38", "naklon": 0 }, + "3272": { "label": "20/39", "naklon": 0 }, + "3291": { "label": "20/40", "naklon": 0 }, + "3277": { "label": "20/41", "naklon": 10 }, + "3286": { "label": "20/42", "naklon": 10 }, + "3281": { "label": "20/43", "naklon": 10 }, + "3288": { "label": "20/44", "naklon": 10 }, + "3284": { "label": "20/45", "naklon": 10 }, + "3167": { "label": "20/46", "naklon": 10 }, + "3872": { "label": "20/47", "naklon": 0 }, + "3124": { "label": "20/48", "naklon": 0 }, + "3133": { "label": "20/49", "naklon": 0 }, + "3158": { "label": "20/50", "naklon": 0 }, + "3169": { "label": "20/51", "naklon": 0 }, + "3146": { "label": "20/52", "naklon": 0 }, + "3160": { "label": "20/53", "naklon": 0 }, + "3248": { "label": "20/54", "naklon": 0 }, + "3156": { "label": "20/55", "naklon": 0 }, + "3161": { "label": "20/56", "naklon": 0 }, + "3170": { "label": "20/57", "naklon": 0 }, + "3168": { "label": "20/58", "naklon": 0 }, + "3125": { "label": "20/59", "naklon": 0 }, + "3166": { "label": "20/60", "naklon": 0 }, + "3130": { "label": "20/61", "naklon": 0 }, + "3563": { "label": "20/62", "naklon": 0 }, + "3550": { "label": "20/63", "naklon": null }, + "3269": { "label": "20/67", "naklon": 0 }, + "2921": { "label": "21/1", "naklon": 0 }, + "2707": { "label": "21/2", "naklon": 0 }, + "2723": { "label": "21/3", "naklon": 0 }, + "2716": { "label": "21/4", "naklon": 0 }, + "2717": { "label": "21/5", "naklon": 0 }, + "2720": { "label": "21/6", "naklon": 0 }, + "2722": { "label": "21/7", "naklon": 0 }, + "2718": { "label": "21/8", "naklon": 0 }, + "2724": { "label": "21/9", "naklon": 0 }, + "2742": { "label": "21/10", "naklon": 0 }, + "2743": { "label": "21/11", "naklon": 0 }, + "2733": { "label": "21/12", "naklon": 0 }, + "2903": { "label": "21/14", "naklon": 0 }, + "2917": { "label": "21/15", "naklon": 0 }, + "2897": { "label": "21/16", "naklon": 0 }, + "2914": { "label": "21/17", "naklon": 0 }, + "2898": { "label": "21/18", "naklon": 0 }, + "2773": { "label": "21/19", "naklon": 0 }, + "2895": { "label": "21/20", "naklon": 0 }, + "2896": { "label": "21/21", "naklon": 0 }, + "2771": { "label": "21/22", "naklon": 0 }, + "2772": { "label": "21/23", "naklon": 0 }, + "2793": { "label": "21/24", "naklon": 0 }, + "2902": { "label": "21/25", "naklon": 0 }, + "2910": { "label": "21/26", "naklon": 0 }, + "2909": { "label": "21/27", "naklon": 0 }, + "2920": { "label": "21/28", "naklon": 0 }, + "2916": { "label": "21/29", "naklon": 0 }, + "2904": { "label": "21/30", "naklon": 0 }, + "2915": { "label": "21/31", "naklon": 0 }, + "2905": { "label": "21/32", "naklon": 0 }, + "2900": { "label": "21/33", "naklon": 0 }, + "2899": { "label": "21/34", "naklon": 0 }, + "2741": { "label": "21/36", "naklon": 0 }, + "2714": { "label": "21/37", "naklon": 0 }, + "2701": { "label": "21/38", "naklon": 0 }, + "2703": { "label": "21/39", "naklon": 0 }, + "2704": { "label": "21/40", "naklon": 0 }, + "2702": { "label": "21/41", "naklon": 0 }, + "2706": { "label": "21/42", "naklon": 0 }, + "2776": { "label": "21/43", "naklon": 0 }, + "2770": { "label": "21/44", "naklon": 0 }, + "2786": { "label": "21/45", "naklon": 0 }, + "2779": { "label": "21/46", "naklon": 0 }, + "2782": { "label": "21/47", "naklon": 0 }, + "2785": { "label": "21/48", "naklon": 0 }, + "2769": { "label": "21/49", "naklon": 0 }, + "3354": { "label": "21/50", "naklon": 0 }, + "2778": { "label": "21/51", "naklon": 0 }, + "2775": { "label": "21/52", "naklon": 0 }, + "2780": { "label": "21/53", "naklon": 0 }, + "2790": { "label": "21/54", "naklon": 0 }, + "2792": { "label": "21/55", "naklon": 0 }, + "2774": { "label": "21/56", "naklon": 0 }, + "2630": { "label": "22/1", "naklon": 0 }, + "2631": { "label": "22/2", "naklon": 0 }, + "2632": { "label": "22/3", "naklon": 0 }, + "2633": { "label": "22/4", "naklon": 0 }, + "2634": { "label": "22/5", "naklon": 0 }, + "2636": { "label": "22/6", "naklon": 0 }, + "4367": { "label": "22/7", "naklon": 0 }, + "2637": { "label": "22/8", "naklon": 0 }, + "2638": { "label": "22/9", "naklon": 0 }, + "2639": { "label": "22/10", "naklon": 0 }, + "2640": { "label": "22/11", "naklon": 0 }, + "2641": { "label": "22/12", "naklon": 0 }, + "2642": { "label": "22/13", "naklon": 0 }, + "2643": { "label": "22/14", "naklon": 0 }, + "2644": { "label": "22/15", "naklon": 0 }, + "2645": { "label": "22/16", "naklon": 0 }, + "2646": { "label": "22/17", "naklon": 0 }, + "2647": { "label": "22/18", "naklon": 0 }, + "2648": { "label": "22/19", "naklon": 0 }, + "2649": { "label": "22/20", "naklon": 0 }, + "2650": { "label": "22/21", "naklon": 0 }, + "2651": { "label": "22/22", "naklon": 0 }, + "4103": { "label": "22/23", "naklon": 0 }, + "2653": { "label": "22/24", "naklon": 0 }, + "2654": { "label": "22/25", "naklon": 0 }, + "2655": { "label": "22/26", "naklon": 0 }, + "2656": { "label": "22/27", "naklon": 0 }, + "2657": { "label": "22/28", "naklon": 0 }, + "2658": { "label": "22/29", "naklon": 0 }, + "2659": { "label": "22/30", "naklon": 0 }, + "2660": { "label": "22/31", "naklon": 0 }, + "2661": { "label": "22/32", "naklon": 0 }, + "3015": { "label": "22/32/1", "naklon": 0 }, + "2662": { "label": "22/33", "naklon": 0 }, + "2663": { "label": "22/34", "naklon": 0 }, + "2664": { "label": "22/35", "naklon": 0 }, + "2665": { "label": "22/36", "naklon": 0 }, + "2666": { "label": "22/37", "naklon": 0 }, + "2667": { "label": "22/38", "naklon": 0 }, + "2668": { "label": "22/39", "naklon": 0 }, + "2669": { "label": "22/40", "naklon": null }, + "2670": { "label": "22/41", "naklon": null }, + "2671": { "label": "22/42", "naklon": null }, + "3087": { "label": "23/9A", "naklon": 10 }, + "3090": { "label": "23/9B", "naklon": 10 }, + "3075": { "label": "23/1", "naklon": 0 }, + "3089": { "label": "23/2", "naklon": 0 }, + "3088": { "label": "23/3", "naklon": 0 }, + "3228": { "label": "23/4", "naklon": 10 }, + "2751": { "label": "23/5", "naklon": 10 }, + "3243": { "label": "23/6", "naklon": 10 }, + "4349": { "label": "23/7", "naklon": 10 }, + "3102": { "label": "23/8", "naklon": 10 }, + "3099": { "label": "23/10", "naklon": 10 }, + "3103": { "label": "23/11", "naklon": 10 }, + "3093": { "label": "23/12", "naklon": 10 }, + "3098": { "label": "23/13", "naklon": 10 }, + "3092": { "label": "23/14", "naklon": 10 }, + "3233": { "label": "23/15", "naklon": 0 }, + "3095": { "label": "23/16", "naklon": 0 }, + "4074": { "label": "23/17", "naklon": 0 }, + "2729": { "label": "23/18", "naklon": 0 }, + "3234": { "label": "23/19", "naklon": 0 }, + "3094": { "label": "23/20", "naklon": 0 }, + "2817": { "label": "23/21", "naklon": 0 }, + "3226": { "label": "23/22", "naklon": 0 }, + "3225": { "label": "23/23", "naklon": 0 }, + "3237": { "label": "23/24", "naklon": 0 }, + "4250": { "label": "23/25", "naklon": 0 }, + "3059": { "label": "23/26", "naklon": 10 }, + "3238": { "label": "23/27", "naklon": 10 }, + "3242": { "label": "23/28", "naklon": 10 }, + "3236": { "label": "23/29", "naklon": 10 }, + "3112": { "label": "23/30", "naklon": 10 }, + "3224": { "label": "23/31", "naklon": 0 }, + "4298": { "label": "23/32", "naklon": 10 }, + "4150": { "label": "23/33", "naklon": 10 }, + "3091": { "label": "23/34", "naklon": 10 }, + "3771": { "label": "25/1", "naklon": 5 }, + "3777": { "label": "25/2", "naklon": 5 }, + "3749": { "label": "25/3", "naklon": 5 }, + "3769": { "label": "25/4", "naklon": 5 }, + "3765": { "label": "25/5", "naklon": 5 }, + "3785": { "label": "25/6", "naklon": 5 }, + "3761": { "label": "25/7", "naklon": 5 }, + "3758": { "label": "25/8", "naklon": 5 }, + "3766": { "label": "25/9", "naklon": 5 }, + "3779": { "label": "25/10", "naklon": 5 }, + "3899": { "label": "25/11", "naklon": 10 }, + "3922": { "label": "25/12", "naklon": 10 }, + "3912": { "label": "25/13", "naklon": 10 }, + "3933": { "label": "25/14", "naklon": 10 }, + "3921": { "label": "25/15", "naklon": 10 }, + "4300": { "label": "25/16", "naklon": 10 }, + "3927": { "label": "25/17", "naklon": 10 }, + "3212": { "label": "25/18", "naklon": 10 }, + "3208": { "label": "25/19", "naklon": 10 }, + "3207": { "label": "25/20", "naklon": 10 }, + "4294": { "label": "25/21", "naklon": 10 }, + "3209": { "label": "25/22", "naklon": 10 }, + "3745": { "label": "25/23", "naklon": 10 }, + "3762": { "label": "25/24", "naklon": 10 }, + "3215": { "label": "25/25", "naklon": 10 }, + "3210": { "label": "25/26", "naklon": 10 }, + "3211": { "label": "25/27", "naklon": 10 }, + "3206": { "label": "25/28", "naklon": 10 }, + "3918": { "label": "25/29", "naklon": 5 }, + "3928": { "label": "25/30", "naklon": 5 }, + "3917": { "label": "25/31", "naklon": 5 }, + "4029": { "label": "25/32", "naklon": 0 }, + "4038": { "label": "25/33", "naklon": 0 }, + "4022": { "label": "25/34", "naklon": 0 }, + "3937": { "label": "25/35", "naklon": 0 }, + "3190": { "label": "25/36", "naklon": 0 }, + "3835": { "label": "25/37", "naklon": 0 }, + "3201": { "label": "25/38", "naklon": 0 }, + "3193": { "label": "25/39", "naklon": 0 }, + "3191": { "label": "25/40", "naklon": 0 }, + "3203": { "label": "25/41", "naklon": 0 }, + "4301": { "label": "25/42", "naklon": 0 }, + "3223": { "label": "25/43", "naklon": 0 }, + "3202": { "label": "25/44", "naklon": 0 }, + "3205": { "label": "25/45", "naklon": 0 }, + "3194": { "label": "25/46", "naklon": 0 }, + "3198": { "label": "25/47", "naklon": 0 }, + "3204": { "label": "25/48", "naklon": 0 }, + "3200": { "label": "25/49", "naklon": 0 }, + "3216": { "label": "25/50", "naklon": 0 }, + "3932": { "label": "25/51", "naklon": 5 }, + "3923": { "label": "25/52", "naklon": 5 }, + "3913": { "label": "25/53", "naklon": 5 }, + "3900": { "label": "25/54", "naklon": 5 }, + "4189": { "label": "25/55", "naklon": 10 }, + "4191": { "label": "25/56", "naklon": 10 }, + "3790": { "label": "25/57", "naklon": 10 }, + "4190": { "label": "25/58", "naklon": 10 }, + "4302": { "label": "25/59", "naklon": 0 }, + "4351": { "label": "25/60", "naklon": 0 }, + "4075": { "label": "25/61", "naklon": 0 }, + "4071": { "label": "25/62", "naklon": 0 }, + "3784": { "label": "25/63", "naklon": 0 }, + "4065": { "label": "25/64", "naklon": 0 }, + "4297": { "label": "25/65", "naklon": 0 }, + "4295": { "label": "25/66", "naklon": 0 }, + "4299": { "label": "25/67", "naklon": 0 }, + "3772": { "label": "25/68", "naklon": 0 }, + "3941": { "label": "25/69", "naklon": 0 }, + "3782": { "label": "25/70", "naklon": 0 }, + "4068": { "label": "25/71", "naklon": 0 }, + "4073": { "label": "25/72", "naklon": 0 }, + "3901": { "label": "25/73", "naklon": 5 }, + "4296": { "label": "25/74", "naklon": 5 }, + "3910": { "label": "25/75", "naklon": 5 }, + "4293": { "label": "25/76", "naklon": 5 }, + "3919": { "label": "25/77", "naklon": 5 }, + "3924": { "label": "25/78", "naklon": 5 }, + "3909": { "label": "25/79", "naklon": 5 }, + "3896": { "label": "25/80", "naklon": 5 }, + "3911": { "label": "25/81", "naklon": 5 }, + "2819": { "label": "25/82", "naklon": 15 }, + "3776": { "label": "25/83", "naklon": 15 }, + "3752": { "label": "25/84", "naklon": 15 }, + "4353": { "label": "25/85", "naklon": 15 }, + "3791": { "label": "25/86", "naklon": 0 }, + "3770": { "label": "25/87", "naklon": 0 }, + "3760": { "label": "25/88", "naklon": 0 }, + "3115": { "label": "25/89", "naklon": 0 }, + "3738": { "label": "25/90", "naklon": 0 }, + "3748": { "label": "25/91", "naklon": 0 }, + "3753": { "label": "25/92", "naklon": 0 }, + "3775": { "label": "25/93", "naklon": 0 }, + "3778": { "label": "25/94", "naklon": 5 }, + "4078": { "label": "25/95", "naklon": 5 }, + "4088": { "label": "25/96", "naklon": 5 }, + "3856": { "label": "25/97", "naklon": 5 }, + "4084": { "label": "25/98", "naklon": 5 }, + "4069": { "label": "25/99", "naklon": 5 }, + "4188": { "label": "25/100", "naklon": 5 }, + "4064": { "label": "25/101", "naklon": 5 }, + "3792": { "label": "25/102", "naklon": 5 }, + "3780": { "label": "25/103", "naklon": 5 }, + "4034": { "label": "25/104", "naklon": 5 }, + "4072": { "label": "25/105", "naklon": 5 }, + "3884": { "label": "25/106", "naklon": 5 }, + "3793": { "label": "25/107", "naklon": 5 }, + "3863": { "label": "25/108", "naklon": 5 }, + "3855": { "label": "25/109", "naklon": 5 }, + "3846": { "label": "33/1", "naklon": 0 }, + "3943": { "label": "33/2", "naklon": 0 }, + "3903": { "label": "33/3", "naklon": 0 }, + "3982": { "label": "33/4", "naklon": 0 }, + "3879": { "label": "33/5", "naklon": 0 }, + "3887": { "label": "33/6", "naklon": 0 }, + "3920": { "label": "33/7", "naklon": 5 }, + "3942": { "label": "33/8", "naklon": 5 }, + "3829": { "label": "33/9", "naklon": null }, + "3452": { "label": "34/79A", "naklon": 6 }, + "3460": { "label": "34/79B", "naklon": 6 }, + "3443": { "label": "34/90A", "naklon": 6 }, + "3445": { "label": "34/90B", "naklon": 6 }, + "3457": { "label": "34/90C", "naklon": 6 }, + "3461": { "label": "34/97A", "naklon": 6 }, + "3463": { "label": "34/97B", "naklon": 6 }, + "3426": { "label": "34/98A", "naklon": 6 }, + "3444": { "label": "34/98B", "naklon": 6 }, + "3453": { "label": "34/99A", "naklon": 6 }, + "3455": { "label": "34/99B", "naklon": 6 }, + "4009": { "label": "34/1", "naklon": 0 }, + "3602": { "label": "34/2", "naklon": 0 }, + "3441": { "label": "34/3", "naklon": 0 }, + "3464": { "label": "34/4", "naklon": 0 }, + "3883": { "label": "34/5", "naklon": 0 }, + "4098": { "label": "34/6", "naklon": 0 }, + "4003": { "label": "34/7", "naklon": 0 }, + "4004": { "label": "34/8", "naklon": 0 }, + "3888": { "label": "34/9", "naklon": 0 }, + "3997": { "label": "34/10", "naklon": 0 }, + "4006": { "label": "34/11", "naklon": 0 }, + "4000": { "label": "34/12", "naklon": 0 }, + "4011": { "label": "34/13", "naklon": 0 }, + "3999": { "label": "34/14", "naklon": 0 }, + "3981": { "label": "34/15", "naklon": 0 }, + "3988": { "label": "34/16", "naklon": 0 }, + "3986": { "label": "34/17", "naklon": 0 }, + "3998": { "label": "34/18", "naklon": 0 }, + "3983": { "label": "34/19", "naklon": 0 }, + "4005": { "label": "34/20", "naklon": 0 }, + "4001": { "label": "34/21", "naklon": 0 }, + "4008": { "label": "34/22", "naklon": 0 }, + "4002": { "label": "34/23", "naklon": 0 }, + "3996": { "label": "34/24", "naklon": 0 }, + "4007": { "label": "34/25", "naklon": 0 }, + "4113": { "label": "34/26", "naklon": 15 }, + "3595": { "label": "34/27", "naklon": 5 }, + "3599": { "label": "34/28", "naklon": 5 }, + "3601": { "label": "34/29", "naklon": 5 }, + "4205": { "label": "34/30", "naklon": 0 }, + "3987": { "label": "34/31", "naklon": null }, + "4214": { "label": "34/32", "naklon": 0 }, + "4226": { "label": "34/33", "naklon": 0 }, + "4209": { "label": "34/34", "naklon": 0 }, + "4201": { "label": "34/35", "naklon": 0 }, + "3440": { "label": "34/36", "naklon": 0 }, + "3465": { "label": "34/37", "naklon": 0 }, + "3446": { "label": "34/38", "naklon": 0 }, + "4039": { "label": "34/39", "naklon": 5 }, + "4057": { "label": "34/40", "naklon": 5 }, + "3985": { "label": "34/41", "naklon": 0 }, + "3882": { "label": "34/42", "naklon": 0 }, + "4040": { "label": "34/43", "naklon": 5 }, + "3231": { "label": "34/44", "naklon": 0 }, + "3227": { "label": "34/45", "naklon": 0 }, + "3431": { "label": "34/46", "naklon": 0 }, + "4013": { "label": "34/47", "naklon": 0 }, + "4045": { "label": "34/48", "naklon": 0 }, + "3949": { "label": "34/49", "naklon": 0 }, + "3953": { "label": "34/50", "naklon": 0 }, + "3952": { "label": "34/51", "naklon": 0 }, + "3995": { "label": "34/52", "naklon": 0 }, + "3992": { "label": "34/53", "naklon": 0 }, + "4198": { "label": "34/54", "naklon": 0 }, + "3935": { "label": "34/55", "naklon": 0 }, + "4050": { "label": "34/56", "naklon": 0 }, + "4049": { "label": "34/57", "naklon": 0 }, + "4054": { "label": "34/58", "naklon": 0 }, + "3663": { "label": "34/59", "naklon": 6 }, + "3661": { "label": "34/60", "naklon": 6 }, + "3664": { "label": "34/61", "naklon": 6 }, + "3660": { "label": "34/62", "naklon": 6 }, + "3662": { "label": "34/63", "naklon": 6 }, + "3665": { "label": "34/65", "naklon": 6 }, + "3667": { "label": "34/66", "naklon": 6 }, + "3675": { "label": "34/67", "naklon": 6 }, + "3666": { "label": "34/68", "naklon": 6 }, + "3652": { "label": "34/69", "naklon": 6 }, + "3458": { "label": "34/70", "naklon": 6 }, + "4425": { "label": "34/70/1", "naklon": 6 }, + "3459": { "label": "34/71", "naklon": 6 }, + "3435": { "label": "34/72", "naklon": 6 }, + "3448": { "label": "34/73", "naklon": 6 }, + "3451": { "label": "34/74", "naklon": 6 }, + "3442": { "label": "34/75", "naklon": 6 }, + "3449": { "label": "34/76", "naklon": 6 }, + "3450": { "label": "34/77", "naklon": 6 }, + "3433": { "label": "34/78", "naklon": 6 }, + "3432": { "label": "34/80", "naklon": 12 }, + "3470": { "label": "34/81", "naklon": 12 }, + "3438": { "label": "34/82", "naklon": 12 }, + "3439": { "label": "34/83", "naklon": 12 }, + "4028": { "label": "34/84", "naklon": 5 }, + "3596": { "label": "34/85", "naklon": 5 }, + "4021": { "label": "34/86", "naklon": 5 }, + "3437": { "label": "34/87", "naklon": 12 }, + "3428": { "label": "34/88", "naklon": 12 }, + "3430": { "label": "34/89", "naklon": 12 }, + "3454": { "label": "34/91", "naklon": 6 }, + "3492": { "label": "34/92", "naklon": 6 }, + "3462": { "label": "34/93", "naklon": 6 }, + "3427": { "label": "34/94", "naklon": 6 }, + "3434": { "label": "34/95", "naklon": 6 }, + "3456": { "label": "34/96", "naklon": 6 }, + "4307": { "label": "34/98/1", "naklon": 6 }, + "3968": { "label": "35/1", "naklon": 0 }, + "3969": { "label": "35/2", "naklon": 0 }, + "3947": { "label": "35/3", "naklon": 0 }, + "3979": { "label": "35/4", "naklon": 0 }, + "3959": { "label": "35/5", "naklon": 0 }, + "3948": { "label": "35/6", "naklon": 0 }, + "3961": { "label": "35/7", "naklon": 0 }, + "3956": { "label": "35/8", "naklon": 0 }, + "3604": { "label": "35/9", "naklon": 0 }, + "3944": { "label": "35/10", "naklon": 0 }, + "3960": { "label": "35/11", "naklon": 0 }, + "3958": { "label": "35/12", "naklon": 0 }, + "4036": { "label": "35/13", "naklon": 5 }, + "3893": { "label": "35/18", "naklon": 5 }, + "4108": { "label": "35/19", "naklon": 5 }, + "4017": { "label": "35/20", "naklon": 5 }, + "3963": { "label": "35/21", "naklon": 0 }, + "3658": { "label": "35/22", "naklon": 0 }, + "3975": { "label": "35/23", "naklon": 0 }, + "3980": { "label": "35/24", "naklon": 0 }, + "4012": { "label": "35/25", "naklon": 0 }, + "3655": { "label": "35/26", "naklon": 0 }, + "3962": { "label": "35/27", "naklon": 0 }, + "3945": { "label": "35/28", "naklon": 0 }, + "3569": { "label": "35/29", "naklon": 0 }, + "3429": { "label": "35/30", "naklon": 0 }, + "3657": { "label": "35/31", "naklon": 0 }, + "3646": { "label": "35/32", "naklon": 0 }, + "3622": { "label": "35/33", "naklon": 0 }, + "3612": { "label": "35/34", "naklon": 0 }, + "3955": { "label": "35/35", "naklon": 0 }, + "3878": { "label": "35/37", "naklon": 0 }, + "3965": { "label": "35/38", "naklon": 0 }, + "3970": { "label": "35/39", "naklon": 0 }, + "3611": { "label": "35/40", "naklon": 0 }, + "2635": { "label": "35/41", "naklon": 0 }, + "3978": { "label": "35/42", "naklon": 0 }, + "4213": { "label": "35/43", "naklon": 0 }, + "3984": { "label": "35/44", "naklon": 0 }, + "4218": { "label": "35/45", "naklon": 0 }, + "3973": { "label": "35/46", "naklon": 0 }, + "3974": { "label": "35/47", "naklon": 0 }, + "3759": { "label": "35/48", "naklon": 0 }, + "3844": { "label": "35/49", "naklon": 0 }, + "3804": { "label": "35/50", "naklon": 0 }, + "3831": { "label": "35/51", "naklon": 0 }, + "3643": { "label": "35/52", "naklon": 0 }, + "3966": { "label": "35/53", "naklon": 0 }, + "3971": { "label": "35/54", "naklon": 0 }, + "3650": { "label": "35/55", "naklon": 6 }, + "3651": { "label": "35/56", "naklon": 6 }, + "3669": { "label": "35/57", "naklon": 6 }, + "3648": { "label": "35/58", "naklon": 6 }, + "3645": { "label": "35/59", "naklon": 6 }, + "3659": { "label": "35/60", "naklon": 6 }, + "3647": { "label": "35/61", "naklon": 6 }, + "3644": { "label": "35/62", "naklon": 6 }, + "3671": { "label": "35/63", "naklon": 6 }, + "3682": { "label": "35/64", "naklon": 6 }, + "3672": { "label": "35/65", "naklon": 6 }, + "3683": { "label": "35/66", "naklon": 6 }, + "3673": { "label": "35/67", "naklon": 6 }, + "3674": { "label": "35/68", "naklon": 6 }, + "3679": { "label": "35/69", "naklon": 6 }, + "3649": { "label": "35/70", "naklon": 6 }, + "3687": { "label": "35/71", "naklon": 6 }, + "3677": { "label": "35/72", "naklon": 6 }, + "3690": { "label": "35/73", "naklon": 6 }, + "3691": { "label": "35/74", "naklon": 6 }, + "3676": { "label": "35/75", "naklon": 6 }, + "3680": { "label": "35/76", "naklon": 6 }, + "3668": { "label": "35/77", "naklon": 6 }, + "3681": { "label": "35/78", "naklon": 6 }, + "3670": { "label": "35/79", "naklon": 6 }, + "3689": { "label": "35/80", "naklon": 6 }, + "3678": { "label": "35/81", "naklon": 6 }, + "3693": { "label": "35/82", "naklon": 6 }, + "3654": { "label": "35/83", "naklon": null }, + "4086": { "label": "36/1", "naklon": 0 }, + "4085": { "label": "36/2", "naklon": 0 }, + "4083": { "label": "36/3", "naklon": 0 }, + "4087": { "label": "36/4", "naklon": 0 }, + "4077": { "label": "36/5", "naklon": 0 }, + "4082": { "label": "36/6", "naklon": 0 }, + "4186": { "label": "36/7", "naklon": 0 }, + "4206": { "label": "36/8", "naklon": 0 }, + "4080": { "label": "36/9", "naklon": 0 }, + "4081": { "label": "36/10", "naklon": 0 }, + "4210": { "label": "36/11", "naklon": 0 }, + "4079": { "label": "36/12", "naklon": 0 }, + "4076": { "label": "36/13", "naklon": 0 }, + "3852": { "label": "36/14", "naklon": 0 }, + "2813": { "label": "36/15", "naklon": 0 }, + "4219": { "label": "36/16", "naklon": 0 }, + "3104": { "label": "37/1A", "naklon": 15 }, + "3121": { "label": "37/1B", "naklon": 15 }, + "3113": { "label": "37/2", "naklon": 10 }, + "3118": { "label": "37/3", "naklon": 10 }, + "3111": { "label": "37/4", "naklon": 10 }, + "4020": { "label": "37/5", "naklon": 10 }, + "3119": { "label": "37/6", "naklon": 10 }, + "3110": { "label": "37/7", "naklon": 10 }, + "3108": { "label": "37/8", "naklon": 10 }, + "3107": { "label": "37/12", "naklon": 0 }, + "3199": { "label": "37/13", "naklon": 0 }, + "3120": { "label": "37/14", "naklon": 0 }, + "3122": { "label": "37/15", "naklon": 0 }, + "3908": { "label": "37/16", "naklon": 0 }, + "3114": { "label": "37/17", "naklon": 0 }, + "3105": { "label": "37/18", "naklon": 0 }, + "3116": { "label": "37/19", "naklon": 0 }, + "3106": { "label": "37/20", "naklon": 0 }, + "2887": { "label": "37/21", "naklon": 5 }, + "2888": { "label": "37/22", "naklon": 5 }, + "2877": { "label": "37/23", "naklon": 5 }, + "2891": { "label": "37/24", "naklon": 5 }, + "2886": { "label": "37/25", "naklon": 5 }, + "2892": { "label": "37/26", "naklon": 5 }, + "2882": { "label": "37/27", "naklon": 5 }, + "2883": { "label": "37/28", "naklon": 5 }, + "2876": { "label": "37/29", "naklon": 5 }, + "3109": { "label": "37/30", "naklon": 5 }, + "4152": { "label": "37/31", "naklon": 5 }, + "3117": { "label": "37/32", "naklon": 5 }, + "2870": { "label": "37/33", "naklon": 5 }, + "2867": { "label": "37/34", "naklon": 0 }, + "2865": { "label": "37/35", "naklon": 0 }, + "3096": { "label": "37/36", "naklon": 0 }, + "2871": { "label": "37/37", "naklon": 0 }, + "2884": { "label": "37/38", "naklon": 0 }, + "2855": { "label": "37/39", "naklon": 0 }, + "2878": { "label": "37/40", "naklon": 0 }, + "2889": { "label": "37/41", "naklon": 0 }, + "2879": { "label": "37/42", "naklon": 0 }, + "2850": { "label": "37/43", "naklon": 0 }, + "2894": { "label": "37/44", "naklon": 0 }, + "2880": { "label": "37/45", "naklon": 0 }, + "2893": { "label": "37/46", "naklon": 0 }, + "2890": { "label": "37/47", "naklon": 0 }, + "4355": { "label": "37/48", "naklon": 0 }, + "2885": { "label": "37/49", "naklon": 0 }, + "2875": { "label": "37/50", "naklon": 0 }, + "3486": { "label": "38/30A", "naklon": 5 }, + "3714": { "label": "38/30B", "naklon": 0 }, + "3483": { "label": "38/32A", "naklon": 5 }, + "3496": { "label": "38/32B", "naklon": 0 }, + "3487": { "label": "38/35A", "naklon": 5 }, + "3498": { "label": "38/35B", "naklon": 5 }, + "3578": { "label": "38/38A", "naklon": 5 }, + "3508": { "label": "38/38B", "naklon": 5 }, + "3787": { "label": "38/59A", "naklon": 5 }, + "3491": { "label": "38/59B", "naklon": 5 }, + "3568": { "label": "38/1", "naklon": null }, + "3502": { "label": "38/2", "naklon": 0 }, + "3836": { "label": "38/3", "naklon": 0 }, + "3588": { "label": "38/4", "naklon": 0 }, + "3493": { "label": "38/5", "naklon": 0 }, + "3580": { "label": "38/6", "naklon": 0 }, + "3572": { "label": "38/7", "naklon": 0 }, + "3506": { "label": "38/8", "naklon": 0 }, + "3503": { "label": "38/9", "naklon": 0 }, + "3579": { "label": "38/10", "naklon": 0 }, + "3586": { "label": "38/11", "naklon": 0 }, + "3495": { "label": "38/12", "naklon": 5 }, + "3492": { "label": "38/13", "naklon": 5 }, + "3532": { "label": "38/14", "naklon": 5 }, + "3574": { "label": "38/15", "naklon": 5 }, + "4140": { "label": "38/16", "naklon": 5 }, + "3795": { "label": "38/17", "naklon": 5 }, + "3788": { "label": "38/18", "naklon": 5 }, + "3796": { "label": "38/19", "naklon": 5 }, + "3797": { "label": "38/20", "naklon": 5 }, + "3798": { "label": "38/21", "naklon": 5 }, + "3786": { "label": "38/22", "naklon": 5 }, + "4067": { "label": "38/23", "naklon": 5 }, + "3773": { "label": "38/24", "naklon": 5 }, + "3774": { "label": "38/25", "naklon": 5 }, + "3789": { "label": "38/26", "naklon": 5 }, + "3520": { "label": "38/27", "naklon": null }, + "3577": { "label": "38/29", "naklon": 5 }, + "3530": { "label": "38/31", "naklon": null }, + "3488": { "label": "38/33", "naklon": 5 }, + "3505": { "label": "38/34", "naklon": 5 }, + "3497": { "label": "38/36", "naklon": 5 }, + "3490": { "label": "38/37", "naklon": 5 }, + "3585": { "label": "38/39", "naklon": 5 }, + "3582": { "label": "38/40", "naklon": 5 }, + "3507": { "label": "38/41", "naklon": 5 }, + "3484": { "label": "38/42", "naklon": 5 }, + "3501": { "label": "38/43", "naklon": 5 }, + "3581": { "label": "38/44", "naklon": 5 }, + "4192": { "label": "38/45", "naklon": 5 }, + "3576": { "label": "38/46", "naklon": 5 }, + "3489": { "label": "38/47", "naklon": 5 }, + "3573": { "label": "38/48", "naklon": 5 }, + "3504": { "label": "38/49", "naklon": 5 }, + "3794": { "label": "38/50", "naklon": 5 }, + "3485": { "label": "38/51", "naklon": 5 }, + "3482": { "label": "38/52", "naklon": 5 }, + "3575": { "label": "38/53", "naklon": 5 }, + "3499": { "label": "38/54", "naklon": 5 }, + "3494": { "label": "38/55", "naklon": 5 }, + "3583": { "label": "38/56", "naklon": 5 }, + "3570": { "label": "38/57", "naklon": 5 }, + "3500": { "label": "38/58", "naklon": 0 }, + "3510": { "label": "38/63", "naklon": null }, + "3512": { "label": "38/64", "naklon": null }, + "3535": { "label": "38/67", "naklon": null }, + "3531": { "label": "38/68", "naklon": null }, + "3537": { "label": "38/69", "naklon": null }, + "3522": { "label": "39/1", "naklon": 10 }, + "4018": { "label": "39/2", "naklon": 10 }, + "4019": { "label": "39/3", "naklon": 10 }, + "4154": { "label": "39/4", "naklon": 5 }, + "3907": { "label": "39/5", "naklon": 5 }, + "4148": { "label": "39/6", "naklon": 0 }, + "4153": { "label": "39/7", "naklon": 0 }, + "3938": { "label": "39/8", "naklon": 0 }, + "3802": { "label": "39/9", "naklon": 0 }, + "4015": { "label": "39/10", "naklon": 0 }, + "3929": { "label": "39/11", "naklon": 0 }, + "3946": { "label": "39/12", "naklon": 0 }, + "4014": { "label": "39/13", "naklon": 0 }, + "4155": { "label": "39/14", "naklon": 0 }, + "4149": { "label": "39/15", "naklon": 0 }, + "3642": { "label": "39/16", "naklon": 0 }, + "3636": { "label": "39/17", "naklon": 5 }, + "3991": { "label": "39/18", "naklon": 0 }, + "3994": { "label": "39/19", "naklon": 0 }, + "3990": { "label": "39/20", "naklon": 0 }, + "3967": { "label": "39/21", "naklon": 0 }, + "3977": { "label": "39/22", "naklon": 0 }, + "3757": { "label": "39/23", "naklon": 15 }, + "3633": { "label": "39/24", "naklon": 15 }, + "3744": { "label": "39/25", "naklon": 15 }, + "4023": { "label": "39/26", "naklon": 5 }, + "3720": { "label": "39/27", "naklon": 5 }, + "3734": { "label": "39/28", "naklon": 5 }, + "3741": { "label": "39/29", "naklon": 5 }, + "3721": { "label": "39/30", "naklon": 5 }, + "3845": { "label": "39/31", "naklon": 0 }, + "3840": { "label": "39/32", "naklon": 0 }, + "3837": { "label": "39/33", "naklon": null }, + "3839": { "label": "39/34", "naklon": 0 }, + "3542": { "label": "41/1", "naklon": null }, + "3566": { "label": "41/2", "naklon": null }, + "3548": { "label": "41/3", "naklon": null }, + "3515": { "label": "41/4", "naklon": null }, + "3559": { "label": "41/5", "naklon": null }, + "3509": { "label": "41/6", "naklon": null }, + "3524": { "label": "41/7", "naklon": null }, + "3518": { "label": "41/8", "naklon": null }, + "3182": { "label": "41/9", "naklon": null }, + "3187": { "label": "41/10", "naklon": null }, + "3195": { "label": "41/11", "naklon": 0 }, + "3857": { "label": "41/12", "naklon": 0 }, + "3183": { "label": "41/13", "naklon": 0 }, + "3177": { "label": "41/14", "naklon": 0 }, + "3189": { "label": "41/15", "naklon": 0 }, + "3186": { "label": "41/16", "naklon": 0 }, + "3178": { "label": "42/1", "naklon": 0 }, + "3219": { "label": "42/2", "naklon": 0 }, + "3475": { "label": "42/3", "naklon": 0 }, + "3175": { "label": "42/4", "naklon": 0 }, + "3222": { "label": "42/5", "naklon": 0 }, + "3221": { "label": "42/6", "naklon": 0 }, + "3181": { "label": "42/7", "naklon": 0 }, + "3180": { "label": "42/8", "naklon": 0 }, + "3218": { "label": "42/9", "naklon": 0 }, + "3176": { "label": "42/10", "naklon": 0 }, + "3174": { "label": "42/11", "naklon": 0 }, + "3220": { "label": "42/12", "naklon": 0 }, + "3533": { "label": "42/13", "naklon": null }, + "3543": { "label": "42/14", "naklon": null }, + "3554": { "label": "42/15", "naklon": null }, + "3549": { "label": "42/16", "naklon": null }, + "2857": { "label": "43/1", "naklon": 5 }, + "2752": { "label": "43/2", "naklon": 5 }, + "2753": { "label": "43/3", "naklon": 5 }, + "3024": { "label": "43/4", "naklon": 5 }, + "2754": { "label": "43/5", "naklon": 5 }, + "4423": { "label": "43/6", "naklon": 5 }, + "4368": { "label": "43/7", "naklon": 5 }, + "2978": { "label": "43/8", "naklon": 5 }, + "2868": { "label": "43/9", "naklon": 5 }, + "4377": { "label": "43/10", "naklon": 5 }, + "2757": { "label": "43/11", "naklon": 5 }, + "2970": { "label": "43/12", "naklon": 5 }, + "2758": { "label": "43/13", "naklon": 5 }, + "4378": { "label": "43/14", "naklon": 5 }, + "2759": { "label": "43/15", "naklon": 5 }, + "4342": { "label": "43/16", "naklon": 5 }, + "3026": { "label": "43/17", "naklon": null }, + "2986": { "label": "43/18", "naklon": null }, + "4343": { "label": "43/19", "naklon": null }, + "2760": { "label": "43/20", "naklon": null }, + "4379": { "label": "43/21", "naklon": null }, + "2971": { "label": "43/22", "naklon": null }, + "2761": { "label": "43/23", "naklon": null }, + "2762": { "label": "43/24", "naklon": null }, + "4339": { "label": "43/25", "naklon": null }, + "4380": { "label": "43/26", "naklon": null }, + "2975": { "label": "43/27", "naklon": null }, + "3003": { "label": "43/28", "naklon": null }, + "4338": { "label": "43/29", "naklon": null }, + "3002": { "label": "43/30", "naklon": null }, + "4345": { "label": "43/31", "naklon": null }, + "2979": { "label": "43/32", "naklon": null }, + "2989": { "label": "43/33", "naklon": null }, + "2996": { "label": "43/34", "naklon": null }, + "2972": { "label": "43/35", "naklon": null }, + "2988": { "label": "43/36", "naklon": null }, + "4344": { "label": "43/37", "naklon": null }, + "3022": { "label": "43/38", "naklon": null }, + "4341": { "label": "43/39", "naklon": null }, + "2983": { "label": "43/40", "naklon": null }, + "2995": { "label": "43/41", "naklon": null }, + "2763": { "label": "43/42", "naklon": null }, + "2764": { "label": "43/43", "naklon": null }, + "2765": { "label": "43/44", "naklon": null }, + "2766": { "label": "43/45", "naklon": null }, + "2767": { "label": "43/46", "naklon": null }, + "2768": { "label": "43/47", "naklon": null }, + "3018": { "label": "43/48", "naklon": null }, + "2982": { "label": "43/49", "naklon": null }, + "3019": { "label": "43/50", "naklon": 0 }, + "3013": { "label": "43/51", "naklon": null }, + "3007": { "label": "43/52", "naklon": null }, + "2980": { "label": "43/53", "naklon": null }, + "3011": { "label": "43/54", "naklon": null }, + "2672": { "label": "43/55", "naklon": null }, + "2673": { "label": "43/56", "naklon": null }, + "2674": { "label": "43/57", "naklon": null }, + "2675": { "label": "43/58", "naklon": null }, + "2676": { "label": "43/59", "naklon": null }, + "2677": { "label": "43/60", "naklon": null }, + "2678": { "label": "43/61", "naklon": null }, + "2679": { "label": "43/62", "naklon": null }, + "2680": { "label": "43/63", "naklon": null }, + "2840": { "label": "43/64", "naklon": null }, + "2682": { "label": "43/65", "naklon": null }, + "2683": { "label": "43/66", "naklon": null }, + "2684": { "label": "43/67", "naklon": 0 }, + "2685": { "label": "43/68", "naklon": null }, + "2686": { "label": "43/69", "naklon": null }, + "2687": { "label": "43/70", "naklon": null }, + "2688": { "label": "43/71", "naklon": null }, + "2689": { "label": "43/72", "naklon": null }, + "2690": { "label": "43/73", "naklon": null }, + "2691": { "label": "43/74", "naklon": null }, + "2692": { "label": "43/75", "naklon": null }, + "2693": { "label": "43/76", "naklon": 0 }, + "2694": { "label": "43/77", "naklon": null }, + "2695": { "label": "43/78", "naklon": null }, + "2696": { "label": "43/79", "naklon": 0 }, + "2697": { "label": "43/80", "naklon": null }, + "2698": { "label": "43/81", "naklon": 0 }, + "2699": { "label": "43/82", "naklon": null }, + "2700": { "label": "43/83", "naklon": 0 }, + "2744": { "label": "43/84", "naklon": null }, + "2745": { "label": "43/85", "naklon": 0 }, + "2746": { "label": "43/86", "naklon": null }, + "2747": { "label": "43/87", "naklon": 0 }, + "2748": { "label": "43/88", "naklon": null }, + "2749": { "label": "43/89", "naklon": 0 }, + "2841": { "label": "43/90", "naklon": null }, + "4237": { "label": "45/1", "naklon": 5 }, + "4226": { "label": "45/2", "naklon": 5 }, + "4242": { "label": "45/3", "naklon": 5 }, + "4179": { "label": "45/4", "naklon": 5 }, + "4247": { "label": "45/5", "naklon": 5 }, + "4245": { "label": "45/6", "naklon": 5 }, + "3872": { "label": "45/7", "naklon": 5 }, + "4175": { "label": "45/8", "naklon": 5 }, + "4236": { "label": "45/9", "naklon": 5 }, + "4170": { "label": "45/10", "naklon": 5 }, + "4238": { "label": "45/11", "naklon": 5 }, + "4246": { "label": "45/12", "naklon": 5 }, + "4166": { "label": "45/13", "naklon": 5 }, + "4227": { "label": "45/14", "naklon": 5 }, + "4171": { "label": "45/15", "naklon": 5 }, + "4180": { "label": "45/16", "naklon": 5 }, + "4244": { "label": "45/17", "naklon": 5 }, + "4199": { "label": "45/18", "naklon": 5 }, + "4239": { "label": "45/19", "naklon": 5 }, + "4207": { "label": "45/20", "naklon": 5 }, + "4223": { "label": "45/21", "naklon": 5 }, + "4230": { "label": "45/22", "naklon": 5 }, + "4233": { "label": "45/23", "naklon": 5 }, + "4222": { "label": "45/24", "naklon": 5 }, + "4217": { "label": "45/25", "naklon": 5 }, + "4243": { "label": "45/26", "naklon": 5 }, + "4200": { "label": "45/27", "naklon": 5 }, + "4228": { "label": "45/28", "naklon": 5 }, + "4211": { "label": "45/29", "naklon": 5 }, + "4234": { "label": "45/30", "naklon": 5 }, + "4235": { "label": "45/31", "naklon": 5 }, + "4203": { "label": "45/32", "naklon": 5 }, + "4240": { "label": "45/33", "naklon": 5 }, + "4224": { "label": "45/34", "naklon": 5 }, + "4232": { "label": "45/35", "naklon": 5 }, + "4231": { "label": "45/36", "naklon": 5 }, + "4161": { "label": "45/37", "naklon": 5 }, + "4225": { "label": "45/38", "naklon": 5 }, + "4241": { "label": "45/39", "naklon": 5 }, + "4229": { "label": "45/40", "naklon": 5 }, + "4221": { "label": "45/41", "naklon": 5 }, + "4212": { "label": "45/42", "naklon": 5 }, + "4216": { "label": "45/43", "naklon": 5 }, + "3864": { "label": "45/44", "naklon": null }, + "3806": { "label": "46/1", "naklon": 5 }, + "3813": { "label": "46/2", "naklon": 5 }, + "3815": { "label": "46/3", "naklon": 5 }, + "3807": { "label": "46/4", "naklon": 5 }, + "3895": { "label": "46/5", "naklon": 5 }, + "3809": { "label": "46/6", "naklon": 5 }, + "3820": { "label": "46/7", "naklon": 5 }, + "3805": { "label": "46/8", "naklon": 5 }, + "3894": { "label": "46/9", "naklon": 0 }, + "4055": { "label": "46/10", "naklon": 0 }, + "3812": { "label": "46/11", "naklon": 5 }, + "3822": { "label": "46/12", "naklon": 5 }, + "3821": { "label": "46/13", "naklon": 5 }, + "3808": { "label": "46/14", "naklon": 5 }, + "3799": { "label": "46/15", "naklon": 5 }, + "3816": { "label": "46/16", "naklon": 5 }, + "3751": { "label": "46/17", "naklon": 5 }, + "3814": { "label": "46/18", "naklon": 5 }, + "4044": { "label": "46/19", "naklon": 0 }, + "3931": { "label": "46/20", "naklon": 0 }, + "3902": { "label": "46/21", "naklon": 5 }, + "3916": { "label": "46/22", "naklon": 5 }, + "3892": { "label": "46/23", "naklon": 5 }, + "3914": { "label": "46/24", "naklon": 5 }, + "3898": { "label": "46/25", "naklon": 5 }, + "3897": { "label": "46/26", "naklon": 5 }, + "3885": { "label": "46/27", "naklon": 5 }, + "3906": { "label": "46/28", "naklon": 5 }, + "3930": { "label": "46/29", "naklon": 0 }, + "3936": { "label": "46/30", "naklon": 0 }, + "3860": { "label": "46/31", "naklon": 5 }, + "3841": { "label": "46/32", "naklon": 5 }, + "3873": { "label": "46/33", "naklon": 5 }, + "3854": { "label": "46/34", "naklon": 5 }, + "3939": { "label": "46/35", "naklon": 5 }, + "3858": { "label": "46/36", "naklon": 5 }, + "3940": { "label": "46/37", "naklon": 5 }, + "4035": { "label": "46/38", "naklon": 5 }, + "3373": { "label": "47/1", "naklon": 0 }, + "3374": { "label": "47/2", "naklon": 0 }, + "3384": { "label": "47/3", "naklon": 0 }, + "3385": { "label": "47/4", "naklon": 0 }, + "4051": { "label": "48/1", "naklon": 5 }, + "4041": { "label": "48/2", "naklon": 5 }, + "4056": { "label": "48/3", "naklon": 5 }, + "3875": { "label": "48/4", "naklon": 5 }, + "4061": { "label": "48/5", "naklon": 5 }, + "4047": { "label": "48/6", "naklon": 5 }, + "4060": { "label": "48/7", "naklon": 5 }, + "4059": { "label": "48/8", "naklon": 5 }, + "4058": { "label": "48/9", "naklon": 5 }, + "3635": { "label": "48/10", "naklon": 5 }, + "3640": { "label": "48/11", "naklon": 5 }, + "3747": { "label": "48/12", "naklon": 5 }, + "3629": { "label": "48/13", "naklon": 5 }, + "4048": { "label": "48/14", "naklon": 5 }, + "4063": { "label": "48/15", "naklon": 5 }, + "4062": { "label": "48/16", "naklon": 5 }, + "4043": { "label": "48/17", "naklon": 5 }, + "4052": { "label": "48/18", "naklon": 5 }, + "4042": { "label": "48/19", "naklon": 5 }, + "4053": { "label": "48/20", "naklon": 5 }, + "4167": { "label": "50/15A", "naklon": null }, + "4159": { "label": "50/15B", "naklon": null }, + "4183": { "label": "50/1", "naklon": 0 }, + "4157": { "label": "50/2", "naklon": 0 }, + "4160": { "label": "50/3", "naklon": 0 }, + "4173": { "label": "50/4", "naklon": 0 }, + "4177": { "label": "50/5", "naklon": 0 }, + "4174": { "label": "50/6", "naklon": 0 }, + "4178": { "label": "50/7", "naklon": 0 }, + "4195": { "label": "50/8", "naklon": 0 }, + "4169": { "label": "50/9", "naklon": 0 }, + "4162": { "label": "50/10", "naklon": 0 }, + "4158": { "label": "50/11", "naklon": 0 }, + "4182": { "label": "50/12", "naklon": 0 }, + "4194": { "label": "50/13", "naklon": 0 }, + "4184": { "label": "50/14", "naklon": 0 }, + "4197": { "label": "50/16", "naklon": null }, + "4164": { "label": "50/17", "naklon": null }, + "3306": { "label": "50/18", "naklon": null }, + "4168": { "label": "50/19", "naklon": null }, + "4193": { "label": "50/20", "naklon": null }, + "4187": { "label": "50/21", "naklon": null }, + "4163": { "label": "50/22", "naklon": null }, + "4165": { "label": "50/23", "naklon": null }, + "4185": { "label": "50/24", "naklon": null }, + "3904": { "label": "50/25", "naklon": null }, + "2619": { "label": "53/1", "naklon": 0 }, + "2623": { "label": "53/2", "naklon": 0 }, + "2617": { "label": "53/3", "naklon": 0 }, + "2622": { "label": "53/4", "naklon": 0 }, + "2618": { "label": "53/5", "naklon": 0 }, + "2626": { "label": "53/6", "naklon": 0 }, + "2869": { "label": "53/7", "naklon": 0 }, + "2613": { "label": "53/8", "naklon": 0 }, + "2608": { "label": "53/9", "naklon": 0 }, + "2611": { "label": "53/10", "naklon": 0 }, + "2598": { "label": "53/11", "naklon": 0 }, + "3528": { "label": "53/12", "naklon": 0 }, + "3545": { "label": "53/13", "naklon": 0 }, + "2620": { "label": "53/14", "naklon": 0 }, + "2612": { "label": "53/15", "naklon": 0 }, + "2615": { "label": "53/16", "naklon": 0 }, + "3722": { "label": "53/17", "naklon": 0 }, + "2624": { "label": "53/18", "naklon": 0 }, + "2609": { "label": "53/19", "naklon": 0 }, + "2625": { "label": "53/20", "naklon": 0 }, + "2602": { "label": "53/21", "naklon": 0 }, + "2610": { "label": "53/22", "naklon": 0 }, + "2599": { "label": "53/23", "naklon": 0 }, + "2605": { "label": "53/24", "naklon": 0 }, + "2593": { "label": "53/25", "naklon": 0 }, + "3074": { "label": "53/26", "naklon": 0 }, + "2740": { "label": "53/27", "naklon": 0 }, + "2614": { "label": "53/28", "naklon": 0 }, + "2601": { "label": "53/29", "naklon": 0 }, + "4196": { "label": "53/30", "naklon": 0 }, + "2607": { "label": "53/31", "naklon": 0 }, + "2582": { "label": "53/32", "naklon": 0 }, + "2594": { "label": "53/33", "naklon": 0 }, + "2589": { "label": "53/34", "naklon": 0 }, + "2596": { "label": "53/35", "naklon": 0 }, + "2603": { "label": "53/36", "naklon": 0 }, + "2597": { "label": "53/37", "naklon": 0 }, + "2590": { "label": "53/38", "naklon": 0 }, + "2581": { "label": "53/39", "naklon": 0 }, + "2583": { "label": "53/40", "naklon": 0 }, + "2580": { "label": "53/41", "naklon": 0 }, + "2579": { "label": "53/42", "naklon": 0 }, + "2797": { "label": "53/43", "naklon": 0 }, + "2577": { "label": "53/44", "naklon": 0 }, + "2586": { "label": "53/45", "naklon": 0 }, + "2588": { "label": "53/46", "naklon": 0 }, + "2591": { "label": "53/47", "naklon": 0 }, + "2592": { "label": "53/48", "naklon": 0 }, + "2573": { "label": "53/49", "naklon": 0 }, + "2595": { "label": "53/50", "naklon": 0 }, + "2587": { "label": "53/51", "naklon": 0 }, + "2578": { "label": "53/52", "naklon": 0 }, + "2574": { "label": "53/53", "naklon": 0 }, + "2571": { "label": "53/54", "naklon": 0 }, + "2570": { "label": "53/55", "naklon": 0 }, + "2576": { "label": "53/56", "naklon": 0 }, + "2881": { "label": "53/57", "naklon": 0 }, + "2575": { "label": "53/58", "naklon": 0 }, + "2572": { "label": "53/59", "naklon": 0 }, + "2569": { "label": "53/60", "naklon": 0 }, + "4324": { "label": "55/1", "naklon": 0 }, + "4319": { "label": "55/2", "naklon": 0 }, + "4327": { "label": "55/3", "naklon": 0 }, + "4333": { "label": "55/4", "naklon": 0 }, + "4332": { "label": "55/5", "naklon": 0 }, + "4320": { "label": "55/6", "naklon": 0 }, + "4317": { "label": "55/7", "naklon": 0 }, + "4318": { "label": "55/8", "naklon": 0 }, + "4328": { "label": "55/9", "naklon": 0 }, + "4323": { "label": "55/10", "naklon": 0 }, + "4325": { "label": "55/11", "naklon": 0 }, + "4326": { "label": "55/12", "naklon": 0 }, + "4316": { "label": "55/13", "naklon": 0 }, + "4322": { "label": "55/14", "naklon": 0 }, + "4331": { "label": "55/15", "naklon": 0 }, + "4321": { "label": "55/16", "naklon": 0 }, + "4315": { "label": "55/17", "naklon": 0 }, + "4329": { "label": "55/18", "naklon": 0 }, + "4334": { "label": "55/19", "naklon": 0 }, + "4330": { "label": "55/20", "naklon": 0 } +}; + + +let svetlaSorted = [{ "label": "1/3A", "node": 3993, "naklon": 0 }, +{ "label": "1/3B", "node": 3989, "naklon": 15 }, +{ "label": "1/1", "node": 3976, "naklon": 0 }, +{ "label": "1/2", "node": 4181, "naklon": 0 }, +{ "label": "1/4", "node": 4376, "naklon": 15 }, +{ "label": "1/5", "node": 3868, "naklon": 15 }, +{ "label": "1/6", "node": 3728, "naklon": 15 }, +{ "label": "1/7", "node": 3730, "naklon": 0 }, +{ "label": "1/8", "node": 4374, "naklon": 0 }, +{ "label": "1/9", "node": 3718, "naklon": 15 }, +{ "label": "1/10", "node": 4375, "naklon": 15 }, +{ "label": "1/11", "node": 4172, "naklon": 15 }, +{ "label": "1/12", "node": 4176, "naklon": 15 }, +{ "label": "2/1", "node": 3800, "naklon": 5 }, +{ "label": "2/2", "node": 3823, "naklon": 5 }, +{ "label": "2/3", "node": 3905, "naklon": 5 }, +{ "label": "2/4", "node": 3803, "naklon": 5 }, +{ "label": "2/5", "node": 3817, "naklon": 5 }, +{ "label": "2/6", "node": 3818, "naklon": 5 }, +{ "label": "2/7", "node": 3811, "naklon": 5 }, +{ "label": "2/8", "node": 3915, "naklon": 5 }, +{ "label": "2/9", "node": 3843, "naklon": 10 }, +{ "label": "2/10", "node": 3827, "naklon": 10 }, +{ "label": "2/11", "node": 4220, "naklon": 10 }, +{ "label": "2/12", "node": 3826, "naklon": 10 }, +{ "label": "2/13", "node": 3834, "naklon": 10 }, +{ "label": "2/14", "node": 3838, "naklon": 10 }, +{ "label": "2/15", "node": 2823, "naklon": 10 }, +{ "label": "2/16", "node": 3750, "naklon": 10 }, +{ "label": "2/17", "node": 3378, "naklon": 0 }, +{ "label": "2/18", "node": 3376, "naklon": 0 }, +{ "label": "2/19", "node": 3379, "naklon": 0 }, +{ "label": "2/20", "node": 3285, "naklon": 0 }, +{ "label": "2/21", "node": 3382, "naklon": 0 }, +{ "label": "2/22", "node": 3383, "naklon": 0 }, +{ "label": "2/24", "node": 3375, "naklon": 0 }, +{ "label": "2/25", "node": 3381, "naklon": 0 }, +{ "label": "2/26", "node": 3380, "naklon": 0 }, +{ "label": "2/27", "node": 3828, "naklon": 10 }, +{ "label": "2/28", "node": 3377, "naklon": 0 }, +{ "label": "7/1", "node": 3591, "naklon": 0 }, +{ "label": "7/2", "node": 3587, "naklon": 0 }, +{ "label": "7/3", "node": 3468, "naklon": 0 }, +{ "label": "7/4", "node": 3466, "naklon": 0 }, +{ "label": "7/5", "node": 3474, "naklon": 0 }, +{ "label": "7/6", "node": 3481, "naklon": 0 }, +{ "label": "7/7", "node": 3589, "naklon": 0 }, +{ "label": "7/8", "node": 3472, "naklon": 0 }, +{ "label": "7/9", "node": 3473, "naklon": 0 }, +{ "label": "7/10", "node": 3584, "naklon": 0 }, +{ "label": "7/11", "node": 3571, "naklon": 0 }, +{ "label": "7/12", "node": 3476, "naklon": 0 }, +{ "label": "7/13", "node": 3590, "naklon": 0 }, +{ "label": "7/14", "node": 3478, "naklon": 0 }, +{ "label": "7/15", "node": 3471, "naklon": 0 }, +{ "label": "7/16", "node": 3467, "naklon": 0 }, +{ "label": "7/17", "node": 3479, "naklon": 0 }, +{ "label": "7/18", "node": 3480, "naklon": 0 }, +{ "label": "7/19", "node": 3477, "naklon": 0 }, +{ "label": "12/1", "node": 3362, "naklon": 0 }, +{ "label": "12/2", "node": 3355, "naklon": 0 }, +{ "label": "12/3", "node": 3356, "naklon": 0 }, +{ "label": "12/4", "node": 3349, "naklon": 0 }, +{ "label": "12/5", "node": 3357, "naklon": 0 }, +{ "label": "12/6", "node": 3350, "naklon": 0 }, +{ "label": "12/7", "node": 3353, "naklon": 0 }, +{ "label": "12/8", "node": 3539, "naklon": 0 }, +{ "label": "12/9", "node": 3050, "naklon": 0 }, +{ "label": "12/10", "node": 3361, "naklon": 0 }, +{ "label": "12/11", "node": 3360, "naklon": 0 }, +{ "label": "12/12", "node": 3358, "naklon": 0 }, +{ "label": "12/13", "node": 3541, "naklon": 0 }, +{ "label": "12/14", "node": 3551, "naklon": 0 }, +{ "label": "12/15", "node": 3514, "naklon": 0 }, +{ "label": "12/16", "node": 3547, "naklon": 0 }, +{ "label": "12/17", "node": 3562, "naklon": 0 }, +{ "label": "12/18", "node": 3525, "naklon": 0 }, +{ "label": "12/19", "node": 3558, "naklon": 0 }, +{ "label": "12/20", "node": 3511, "naklon": 0 }, +{ "label": "12/21", "node": 3058, "naklon": 0 }, +{ "label": "12/22", "node": 3062, "naklon": 0 }, +{ "label": "12/23", "node": 3070, "naklon": 0 }, +{ "label": "12/24", "node": 3447, "naklon": 0 }, +{ "label": "12/25", "node": 3056, "naklon": 0 }, +{ "label": "12/26", "node": 3057, "naklon": 0 }, +{ "label": "12/27", "node": 3071, "naklon": 0 }, +{ "label": "12/28", "node": 3061, "naklon": 0 }, +{ "label": "12/29", "node": 3069, "naklon": 0 }, +{ "label": "12/30", "node": 3077, "naklon": 0 }, +{ "label": "12/31", "node": 3080, "naklon": 0 }, +{ "label": "12/32", "node": 3081, "naklon": 0 }, +{ "label": "12/33", "node": 3078, "naklon": 0 }, +{ "label": "12/34", "node": 4037, "naklon": 0 }, +{ "label": "12/35", "node": 3067, "naklon": 0 }, +{ "label": "12/36", "node": 3051, "naklon": 0 }, +{ "label": "12/37", "node": 2924, "naklon": 0 }, +{ "label": "12/38", "node": 3060, "naklon": 0 }, +{ "label": "12/39", "node": 3073, "naklon": 0 }, +{ "label": "12/40", "node": 3469, "naklon": 0 }, +{ "label": "12/41", "node": 2923, "naklon": 0 }, +{ "label": "12/42", "node": 2925, "naklon": 0 }, +{ "label": "12/43", "node": 3359, "naklon": 0 }, +{ "label": "12/44", "node": 3055, "naklon": 0 }, +{ "label": "12/45", "node": 2922, "naklon": 0 }, +{ "label": "12/46", "node": 3084, "naklon": 0 }, +{ "label": "12/47", "node": 3064, "naklon": 0 }, +{ "label": "12/48", "node": 3066, "naklon": 0 }, +{ "label": "12/49", "node": 3072, "naklon": 0 }, +{ "label": "13/13A", "node": 3415, "naklon": 0 }, +{ "label": "13/13B", "node": 3409, "naklon": 0 }, +{ "label": "13/13C", "node": 3399, "naklon": 0 }, +{ "label": "13/29A", "node": 3410, "naklon": 0 }, +{ "label": "13/29B", "node": 3407, "naklon": 0 }, +{ "label": "13/34A", "node": 3405, "naklon": 0 }, +{ "label": "13/34B", "node": 3404, "naklon": 0 }, +{ "label": "13/45A", "node": 3392, "naklon": 0 }, +{ "label": "13/45B", "node": 3386, "naklon": 0 }, +{ "label": "13/60A", "node": 3303, "naklon": 3 }, +{ "label": "13/60B", "node": 3302, "naklon": 3 }, +{ "label": "13/70A", "node": 3319, "naklon": 6 }, +{ "label": "13/70B", "node": 3317, "naklon": 6 }, +{ "label": "13/70C", "node": 3326, "naklon": 6 }, +{ "label": "13/73A", "node": 3351, "naklon": 6 }, +{ "label": "13/73B", "node": 3313, "naklon": 6 }, +{ "label": "13/83A", "node": 3316, "naklon": 0 }, +{ "label": "13/83B", "node": 3320, "naklon": 0 }, +{ "label": "13/95A", "node": 3336, "naklon": 0 }, +{ "label": "13/95B", "node": 3323, "naklon": 0 }, +{ "label": "13/98A", "node": 3339, "naklon": 0 }, +{ "label": "13/98B", "node": 3333, "naklon": 0 }, +{ "label": "13/1", "node": 3425, "naklon": 0 }, +{ "label": "13/2", "node": 3419, "naklon": 0 }, +{ "label": "13/3", "node": 3416, "naklon": 0 }, +{ "label": "13/4", "node": 3332, "naklon": 0 }, +{ "label": "13/5", "node": 3422, "naklon": 0 }, +{ "label": "13/6", "node": 3417, "naklon": 0 }, +{ "label": "13/7", "node": 3418, "naklon": 0 }, +{ "label": "13/8", "node": 3424, "naklon": 0 }, +{ "label": "13/9", "node": 3334, "naklon": 0 }, +{ "label": "13/10", "node": 4363, "naklon": 0 }, +{ "label": "13/11", "node": 3423, "naklon": 0 }, +{ "label": "13/12", "node": 3406, "naklon": 0 }, +{ "label": "13/14", "node": 3411, "naklon": 0 }, +{ "label": "13/15", "node": 3412, "naklon": 0 }, +{ "label": "13/16", "node": 3413, "naklon": 0 }, +{ "label": "13/17", "node": 3414, "naklon": 0 }, +{ "label": "13/18", "node": 3391, "naklon": 0 }, +{ "label": "13/19", "node": 3370, "naklon": 0 }, +{ "label": "13/20", "node": 3369, "naklon": 0 }, +{ "label": "13/21", "node": 3408, "naklon": 0 }, +{ "label": "13/22", "node": 3393, "naklon": 0 }, +{ "label": "13/23", "node": 3128, "naklon": 0 }, +{ "label": "13/24", "node": 3197, "naklon": 0 }, +{ "label": "13/25", "node": 4364, "naklon": 0 }, +{ "label": "13/26", "node": 3155, "naklon": 0 }, +{ "label": "13/27", "node": 3196, "naklon": 0 }, +{ "label": "13/28", "node": 3144, "naklon": 0 }, +{ "label": "13/30", "node": 3150, "naklon": 0 }, +{ "label": "13/31", "node": 3390, "naklon": 0 }, +{ "label": "13/32", "node": 3401, "naklon": 0 }, +{ "label": "13/33", "node": 3275, "naklon": 0 }, +{ "label": "13/35", "node": 3371, "naklon": 0 }, +{ "label": "13/36", "node": 3389, "naklon": 0 }, +{ "label": "13/37", "node": 3388, "naklon": 0 }, +{ "label": "13/38", "node": 3365, "naklon": 0 }, +{ "label": "13/39", "node": 3363, "naklon": 0 }, +{ "label": "13/40", "node": 3397, "naklon": 0 }, +{ "label": "13/40/1", "node": 3567, "naklon": 0 }, +{ "label": "13/41", "node": 3387, "naklon": 0 }, +{ "label": "13/42", "node": 3403, "naklon": 0 }, +{ "label": "13/43", "node": 3147, "naklon": 0 }, +{ "label": "13/44", "node": 3141, "naklon": 0 }, +{ "label": "13/46", "node": 3364, "naklon": 0 }, +{ "label": "13/47", "node": 3367, "naklon": 0 }, +{ "label": "13/48", "node": 3368, "naklon": 0 }, +{ "label": "13/49", "node": 3402, "naklon": 0 }, +{ "label": "13/50", "node": 3366, "naklon": 0 }, +{ "label": "13/51", "node": 3395, "naklon": 0 }, +{ "label": "13/52", "node": 3372, "naklon": 0 }, +{ "label": "13/53", "node": 3394, "naklon": 0 }, +{ "label": "13/54", "node": 3308, "naklon": 0 }, +{ "label": "13/54/1", "node": 3847, "naklon": 0 }, +{ "label": "13/55", "node": 3312, "naklon": 3 }, +{ "label": "13/56", "node": 3309, "naklon": 3 }, +{ "label": "13/57", "node": 3311, "naklon": 3 }, +{ "label": "13/58", "node": 3310, "naklon": 3 }, +{ "label": "13/59", "node": 4365, "naklon": 3 }, +{ "label": "13/60/1", "node": 4093, "naklon": 3 }, +{ "label": "13/61", "node": 3304, "naklon": 3 }, +{ "label": "13/62", "node": 3307, "naklon": 3 }, +{ "label": "13/63", "node": 3271, "naklon": 3 }, +{ "label": "13/64", "node": 3301, "naklon": 3 }, +{ "label": "13/65", "node": 4366, "naklon": 3 }, +{ "label": "13/66", "node": 3300, "naklon": 3 }, +{ "label": "13/67", "node": 3185, "naklon": 0 }, +{ "label": "13/68", "node": 3184, "naklon": 0 }, +{ "label": "13/69", "node": 3188, "naklon": 0 }, +{ "label": "13/71", "node": 3343, "naklon": 6 }, +{ "label": "13/71/1", "node": 3819, "naklon": 6 }, +{ "label": "13/71/2", "node": 3880, "naklon": 6 }, +{ "label": "13/72", "node": 3348, "naklon": 6 }, +{ "label": "13/74", "node": 3344, "naklon": 6 }, +{ "label": "13/75", "node": 3346, "naklon": 6 }, +{ "label": "13/75/1", "node": 3597, "naklon": 6 }, +{ "label": "13/76", "node": 3345, "naklon": 6 }, +{ "label": "13/77", "node": 3322, "naklon": 0 }, +{ "label": "13/78", "node": 3325, "naklon": 0 }, +{ "label": "13/78/1", "node": 4310, "naklon": 0 }, +{ "label": "13/79", "node": 3315, "naklon": 0 }, +{ "label": "13/80", "node": 3328, "naklon": 0 }, +{ "label": "13/81", "node": 3321, "naklon": 0 }, +{ "label": "13/82", "node": 3324, "naklon": 0 }, +{ "label": "13/84", "node": 3140, "naklon": 0 }, +{ "label": "13/85", "node": 3153, "naklon": 0 }, +{ "label": "13/86", "node": 3145, "naklon": 0 }, +{ "label": "13/87", "node": 3134, "naklon": 0 }, +{ "label": "13/88", "node": 3151, "naklon": 0 }, +{ "label": "13/89", "node": 3143, "naklon": 0 }, +{ "label": "13/90", "node": 3318, "naklon": 0 }, +{ "label": "13/91", "node": 3347, "naklon": 0 }, +{ "label": "13/94", "node": 3314, "naklon": 0 }, +{ "label": "13/96", "node": 3331, "naklon": 0 }, +{ "label": "13/97", "node": 3327, "naklon": 0 }, +{ "label": "13/99", "node": 3329, "naklon": 0 }, +{ "label": "13/100", "node": 3337, "naklon": 0 }, +{ "label": "13/101", "node": 3330, "naklon": 0 }, +{ "label": "13/102", "node": 3335, "naklon": 0 }, +{ "label": "13/103", "node": 3420, "naklon": 0 }, +{ "label": "13/104", "node": 3421, "naklon": 0 }, +{ "label": "13/105", "node": 4361, "naklon": 0 }, +{ "label": "13/106", "node": 4362, "naklon": 0 }, +{ "label": "13/107", "node": 3526, "naklon": 0 }, +{ "label": "13/108", "node": 4424, "naklon": null }, +{ "label": "13/109", "node": 3561, "naklon": null }, +{ "label": "13/110", "node": 3527, "naklon": null }, +{ "label": "13/111", "node": 3521, "naklon": null }, +{ "label": "13/112", "node": 3552, "naklon": null }, +{ "label": "13/113", "node": 3544, "naklon": null }, +{ "label": "13/114", "node": 3534, "naklon": null }, +{ "label": "13/115", "node": 3516, "naklon": null }, +{ "label": "13/116", "node": 3513, "naklon": null }, +{ "label": "13/117", "node": 3565, "naklon": null }, +{ "label": "13/118", "node": 3866, "naklon": null }, +{ "label": "14/1", "node": 3136, "naklon": 0 }, +{ "label": "14/2", "node": 3137, "naklon": 0 }, +{ "label": "14/3", "node": 3135, "naklon": 0 }, +{ "label": "14/4", "node": 3149, "naklon": 0 }, +{ "label": "14/5", "node": 3142, "naklon": 0 }, +{ "label": "14/6", "node": 3342, "naklon": 0 }, +{ "label": "14/7", "node": 3340, "naklon": 0 }, +{ "label": "14/8", "node": 3152, "naklon": 0 }, +{ "label": "14/9", "node": 3886, "naklon": 0 }, +{ "label": "14/10", "node": 3341, "naklon": null }, +{ "label": "14/11", "node": 3352, "naklon": null }, +{ "label": "15/1", "node": 3396, "naklon": 5 }, +{ "label": "15/2", "node": 2784, "naklon": 5 }, +{ "label": "15/3", "node": 2788, "naklon": 5 }, +{ "label": "15/4", "node": 2801, "naklon": 5 }, +{ "label": "15/5", "node": 2815, "naklon": 5 }, +{ "label": "15/6", "node": 2829, "naklon": 5 }, +{ "label": "15/7", "node": 2796, "naklon": 5 }, +{ "label": "15/8", "node": 2803, "naklon": 5 }, +{ "label": "15/8/1", "node": 4304, "naklon": 5 }, +{ "label": "15/8/2", "node": 4311, "naklon": 5 }, +{ "label": "15/9", "node": 2821, "naklon": 5 }, +{ "label": "15/10", "node": 3400, "naklon": 5 }, +{ "label": "15/11", "node": 2799, "naklon": 5 }, +{ "label": "15/12", "node": 2804, "naklon": 5 }, +{ "label": "15/12/1", "node": 4303, "naklon": 5 }, +{ "label": "15/12/2", "node": 4309, "naklon": 5 }, +{ "label": "15/13", "node": 2806, "naklon": 5 }, +{ "label": "15/14", "node": 2787, "naklon": 5 }, +{ "label": "15/15", "node": 2809, "naklon": 5 }, +{ "label": "15/16", "node": 2814, "naklon": 0 }, +{ "label": "15/17", "node": 3934, "naklon": 0 }, +{ "label": "15/18", "node": 3192, "naklon": 0 }, +{ "label": "15/19", "node": 2812, "naklon": 0 }, +{ "label": "15/20", "node": 4070, "naklon": 0 }, +{ "label": "15/21", "node": 2826, "naklon": 0 }, +{ "label": "15/22", "node": 2808, "naklon": 3 }, +{ "label": "15/23", "node": 2795, "naklon": 3 }, +{ "label": "15/24", "node": 2807, "naklon": 3 }, +{ "label": "15/25", "node": 2831, "naklon": 0 }, +{ "label": "15/26", "node": 2862, "naklon": null }, +{ "label": "15/27", "node": 2861, "naklon": 0 }, +{ "label": "15/28", "node": 2866, "naklon": 0 }, +{ "label": "15/28/1", "node": 3546, "naklon": 0 }, +{ "label": "15/29", "node": 4146, "naklon": 0 }, +{ "label": "15/29/1", "node": 3001, "naklon": 0 }, +{ "label": "15/30", "node": 2835, "naklon": 0 }, +{ "label": "15/31", "node": 2874, "naklon": 0 }, +{ "label": "15/32", "node": 2852, "naklon": 0 }, +{ "label": "15/33", "node": 2851, "naklon": 0 }, +{ "label": "15/33/1", "node": 3560, "naklon": 0 }, +{ "label": "15/34", "node": 2858, "naklon": 0 }, +{ "label": "15/34/1", "node": 4306, "naklon": 0 }, +{ "label": "15/35", "node": 2856, "naklon": 0 }, +{ "label": "15/36", "node": 2847, "naklon": 0 }, +{ "label": "15/36/1", "node": 3556, "naklon": 0 }, +{ "label": "15/37", "node": 3950, "naklon": 0 }, +{ "label": "15/38", "node": 2848, "naklon": 0 }, +{ "label": "15/39", "node": 2863, "naklon": 0 }, +{ "label": "15/39/1", "node": 4313, "naklon": 0 }, +{ "label": "15/40", "node": 2873, "naklon": 0 }, +{ "label": "15/40/1", "node": 2984, "naklon": 0 }, +{ "label": "15/41", "node": 2854, "naklon": 0 }, +{ "label": "15/42", "node": 2859, "naklon": 0 }, +{ "label": "15/43", "node": 2872, "naklon": 0 }, +{ "label": "15/44", "node": 2849, "naklon": 0 }, +{ "label": "15/45", "node": 2864, "naklon": 0 }, +{ "label": "15/46", "node": 3553, "naklon": null }, +{ "label": "15/47", "node": 3021, "naklon": null }, +{ "label": "15/47/1", "node": 3008, "naklon": null }, +{ "label": "15/48", "node": 3017, "naklon": null }, +{ "label": "15/49", "node": 3014, "naklon": null }, +{ "label": "15/50", "node": 2981, "naklon": null }, +{ "label": "15/51", "node": 3020, "naklon": null }, +{ "label": "15/52", "node": 3027, "naklon": null }, +{ "label": "15/53", "node": 3006, "naklon": null }, +{ "label": "15/54", "node": 3012, "naklon": null }, +{ "label": "15/55", "node": 2738, "naklon": 0 }, +{ "label": "15/56", "node": 2725, "naklon": 0 }, +{ "label": "15/57", "node": 3016, "naklon": null }, +{ "label": "15/58", "node": 3005, "naklon": null }, +{ "label": "15/58/1", "node": 3009, "naklon": null }, +{ "label": "15/59", "node": 3010, "naklon": 0 }, +{ "label": "15/59/1", "node": 3538, "naklon": 0 }, +{ "label": "15/59/2", "node": 4145, "naklon": 0 }, +{ "label": "15/60", "node": 2713, "naklon": 0 }, +{ "label": "15/61", "node": 2789, "naklon": 0 }, +{ "label": "15/62", "node": 2736, "naklon": 0 }, +{ "label": "15/63", "node": 2739, "naklon": 0 }, +{ "label": "15/64", "node": 4346, "naklon": 0 }, +{ "label": "15/65", "node": 2731, "naklon": 0 }, +{ "label": "15/66", "node": 2818, "naklon": 0 }, +{ "label": "15/66/1", "node": 3557, "naklon": 0 }, +{ "label": "15/67", "node": 2822, "naklon": 0 }, +{ "label": "15/68", "node": 2833, "naklon": 0 }, +{ "label": "15/69", "node": 2834, "naklon": 0 }, +{ "label": "15/70", "node": 3097, "naklon": 0 }, +{ "label": "15/71", "node": 2824, "naklon": 0 }, +{ "label": "15/72", "node": 2828, "naklon": 0 }, +{ "label": "15/73", "node": 2600, "naklon": 0 }, +{ "label": "15/73/1", "node": 4314, "naklon": 0 }, +{ "label": "15/74", "node": 2832, "naklon": 0 }, +{ "label": "15/75", "node": 4360, "naklon": 0 }, +{ "label": "15/76", "node": 2846, "naklon": 0 }, +{ "label": "15/77", "node": 2584, "naklon": 0 }, +{ "label": "15/78", "node": 2843, "naklon": 0 }, +{ "label": "15/78/1", "node": 4308, "naklon": 0 }, +{ "label": "15/79", "node": 4144, "naklon": null }, +{ "label": "15/80", "node": 2844, "naklon": 0 }, +{ "label": "15/81", "node": 2842, "naklon": 0 }, +{ "label": "15/82", "node": 2838, "naklon": 0 }, +{ "label": "15/83", "node": 2837, "naklon": null }, +{ "label": "15/83/1", "node": 3555, "naklon": null }, +{ "label": "15/84", "node": 2839, "naklon": 0 }, +{ "label": "15/85", "node": 2830, "naklon": 0 }, +{ "label": "15/86", "node": 4066, "naklon": 0 }, +{ "label": "15/87", "node": 2836, "naklon": 0 }, +{ "label": "15/88", "node": 2911, "naklon": 0 }, +{ "label": "15/89", "node": 2825, "naklon": 0 }, +{ "label": "15/90", "node": 2811, "naklon": 0 }, +{ "label": "15/94", "node": 3740, "naklon": 15 }, +{ "label": "15/95", "node": 2734, "naklon": 15 }, +{ "label": "15/96", "node": 3105, "naklon": 15 }, +{ "label": "15/97", "node": 2732, "naklon": 15 }, +{ "label": "15/98", "node": 2727, "naklon": 15 }, +{ "label": "15/99", "node": 2735, "naklon": 15 }, +{ "label": "15/100", "node": 3926, "naklon": 15 }, +{ "label": "15/101", "node": 2918, "naklon": 0 }, +{ "label": "15/102", "node": 2705, "naklon": 10 }, +{ "label": "15/103", "node": 2708, "naklon": 10 }, +{ "label": "15/104", "node": 2721, "naklon": 10 }, +{ "label": "15/105", "node": 2719, "naklon": 10 }, +{ "label": "15/106", "node": 2919, "naklon": 10 }, +{ "label": "15/107", "node": 3101, "naklon": 10 }, +{ "label": "15/108", "node": 2853, "naklon": 10 }, +{ "label": "15/109", "node": 2715, "naklon": 10 }, +{ "label": "15/110", "node": 2712, "naklon": 0 }, +{ "label": "15/111", "node": 2711, "naklon": 0 }, +{ "label": "15/112", "node": 2709, "naklon": 0 }, +{ "label": "15/113", "node": 2710, "naklon": 0 }, +{ "label": "15/114", "node": 2907, "naklon": 0 }, +{ "label": "15/115", "node": 2906, "naklon": 0 }, +{ "label": "15/116", "node": 2908, "naklon": 0 }, +{ "label": "15/117", "node": 2901, "naklon": 0 }, +{ "label": "15/118", "node": 2913, "naklon": 0 }, +{ "label": "15/119", "node": 3656, "naklon": 0 }, +{ "label": "15/120", "node": 2781, "naklon": 0 }, +{ "label": "15/121", "node": 2802, "naklon": 0 }, +{ "label": "15/122", "node": 2791, "naklon": 0 }, +{ "label": "15/123", "node": 2783, "naklon": 0 }, +{ "label": "15/124", "node": 2794, "naklon": 0 }, +{ "label": "15/125", "node": 3139, "naklon": 0 }, +{ "label": "15/126", "node": 3229, "naklon": 5 }, +{ "label": "15/127", "node": 3239, "naklon": 5 }, +{ "label": "15/128", "node": 3230, "naklon": 5 }, +{ "label": "15/129", "node": 4016, "naklon": null }, +{ "label": "16/16A", "node": 3608, "naklon": 0 }, +{ "label": "16/16B", "node": 4151, "naklon": 0 }, +{ "label": "16/1", "node": 3710, "naklon": 0 }, +{ "label": "16/2", "node": 3726, "naklon": 0 }, +{ "label": "16/3", "node": 3743, "naklon": 0 }, +{ "label": "16/4", "node": 3724, "naklon": 0 }, +{ "label": "16/5", "node": 3712, "naklon": 0 }, +{ "label": "16/6", "node": 3739, "naklon": 0 }, +{ "label": "16/7", "node": 3742, "naklon": 0 }, +{ "label": "16/8", "node": 3731, "naklon": 0 }, +{ "label": "16/9", "node": 3727, "naklon": 0 }, +{ "label": "16/10", "node": 3729, "naklon": 0 }, +{ "label": "16/11", "node": 3736, "naklon": 0 }, +{ "label": "16/12", "node": 3713, "naklon": 0 }, +{ "label": "16/13", "node": 3715, "naklon": 0 }, +{ "label": "16/14", "node": 3733, "naklon": 0 }, +{ "label": "16/15", "node": 3732, "naklon": 0 }, +{ "label": "16/17", "node": 3634, "naklon": 0 }, +{ "label": "16/18", "node": 3610, "naklon": 0 }, +{ "label": "16/19", "node": 3626, "naklon": 0 }, +{ "label": "16/20", "node": 3618, "naklon": 0 }, +{ "label": "16/21", "node": 3619, "naklon": 0 }, +{ "label": "16/22", "node": 3628, "naklon": 0 }, +{ "label": "16/23", "node": 3615, "naklon": 0 }, +{ "label": "16/24", "node": 3609, "naklon": 0 }, +{ "label": "16/25", "node": 3606, "naklon": 0 }, +{ "label": "16/26", "node": 3624, "naklon": 0 }, +{ "label": "16/27", "node": 3627, "naklon": 0 }, +{ "label": "16/28", "node": 3607, "naklon": 0 }, +{ "label": "16/29", "node": 4370, "naklon": 0 }, +{ "label": "16/30", "node": 3692, "naklon": 0 }, +{ "label": "16/31", "node": 3614, "naklon": 0 }, +{ "label": "16/32", "node": 3623, "naklon": 0 }, +{ "label": "16/33", "node": 4373, "naklon": 0 }, +{ "label": "16/34", "node": 3620, "naklon": 0 }, +{ "label": "16/35", "node": 3685, "naklon": 0 }, +{ "label": "16/36", "node": 3616, "naklon": 0 }, +{ "label": "16/37", "node": 3686, "naklon": 0 }, +{ "label": "16/38", "node": 3688, "naklon": 0 }, +{ "label": "16/39", "node": 3684, "naklon": 0 }, +{ "label": "16/40", "node": 3825, "naklon": 0 }, +{ "label": "16/41", "node": 3865, "naklon": 0 }, +{ "label": "16/42", "node": 3824, "naklon": 0 }, +{ "label": "16/43", "node": 3871, "naklon": 0 }, +{ "label": "16/44", "node": 3801, "naklon": 0 }, +{ "label": "16/45", "node": 3862, "naklon": 0 }, +{ "label": "16/46", "node": 3876, "naklon": 0 }, +{ "label": "16/47", "node": 3861, "naklon": 0 }, +{ "label": "16/48", "node": 4215, "naklon": 0 }, +{ "label": "16/49", "node": 3605, "naklon": 10 }, +{ "label": "16/50", "node": 3603, "naklon": 10 }, +{ "label": "16/51", "node": 3592, "naklon": 10 }, +{ "label": "16/52", "node": 3598, "naklon": 10 }, +{ "label": "16/53", "node": 3594, "naklon": 10 }, +{ "label": "16/54", "node": 3593, "naklon": 10 }, +{ "label": "16/55", "node": 3630, "naklon": 10 }, +{ "label": "16/56", "node": 3763, "naklon": 10 }, +{ "label": "16/57", "node": 3746, "naklon": 10 }, +{ "label": "16/58", "node": 3699, "naklon": 0 }, +{ "label": "16/59", "node": 3698, "naklon": 0 }, +{ "label": "16/60", "node": 3709, "naklon": null }, +{ "label": "16/61", "node": 3708, "naklon": 0 }, +{ "label": "16/62", "node": 3703, "naklon": null }, +{ "label": "16/63", "node": 3700, "naklon": 0 }, +{ "label": "16/64", "node": 3701, "naklon": null }, +{ "label": "16/65", "node": 3704, "naklon": 0 }, +{ "label": "16/66", "node": 3707, "naklon": null }, +{ "label": "16/67", "node": 3810, "naklon": 0 }, +{ "label": "16/68", "node": 4208, "naklon": null }, +{ "label": "16/69", "node": 3867, "naklon": 0 }, +{ "label": "16/70", "node": 4372, "naklon": null }, +{ "label": "16/71", "node": 3881, "naklon": 0 }, +{ "label": "16/72", "node": 4204, "naklon": null }, +{ "label": "16/73", "node": 3869, "naklon": 0 }, +{ "label": "16/74", "node": 4202, "naklon": null }, +{ "label": "16/75", "node": 3830, "naklon": 0 }, +{ "label": "16/76", "node": 3870, "naklon": null }, +{ "label": "16/77", "node": 3964, "naklon": 0 }, +{ "label": "16/78", "node": 3849, "naklon": 0 }, +{ "label": "16/79", "node": 3694, "naklon": null }, +{ "label": "16/80", "node": 3717, "naklon": 0 }, +{ "label": "16/81", "node": 3877, "naklon": null }, +{ "label": "16/82", "node": 3755, "naklon": 0 }, +{ "label": "16/83", "node": 3725, "naklon": null }, +{ "label": "16/84", "node": 3716, "naklon": 0 }, +{ "label": "16/85", "node": 3696, "naklon": null }, +{ "label": "16/86", "node": 3702, "naklon": 0 }, +{ "label": "16/87", "node": 3706, "naklon": null }, +{ "label": "16/88", "node": 3850, "naklon": 0 }, +{ "label": "16/89", "node": 3848, "naklon": null }, +{ "label": "16/90", "node": 3737, "naklon": null }, +{ "label": "16/91", "node": 3705, "naklon": 0 }, +{ "label": "16/92", "node": 3723, "naklon": null }, +{ "label": "16/93", "node": 3842, "naklon": 0 }, +{ "label": "16/94", "node": 3735, "naklon": null }, +{ "label": "16/95", "node": 3719, "naklon": 0 }, +{ "label": "16/96", "node": 3697, "naklon": 0 }, +{ "label": "16/97", "node": 3711, "naklon": 0 }, +{ "label": "16/98", "node": 4107, "naklon": null }, +{ "label": "16/99", "node": 4112, "naklon": 5 }, +{ "label": "16/100", "node": 4106, "naklon": 5 }, +{ "label": "16/101", "node": 4111, "naklon": 5 }, +{ "label": "16/102", "node": 4091, "naklon": null }, +{ "label": "16/103", "node": 4104, "naklon": 5 }, +{ "label": "16/104", "node": 4094, "naklon": null }, +{ "label": "16/105", "node": 4089, "naklon": 5 }, +{ "label": "16/106", "node": 4095, "naklon": null }, +{ "label": "16/107", "node": 4102, "naklon": 5 }, +{ "label": "16/108", "node": 4105, "naklon": null }, +{ "label": "16/109", "node": 3859, "naklon": null }, +{ "label": "16/110", "node": 4090, "naklon": 5 }, +{ "label": "16/111", "node": 4110, "naklon": null }, +{ "label": "16/112", "node": 4097, "naklon": 5 }, +{ "label": "16/113", "node": 4099, "naklon": null }, +{ "label": "16/114", "node": 4096, "naklon": null }, +{ "label": "16/115", "node": 4101, "naklon": 5 }, +{ "label": "16/116", "node": 4109, "naklon": null }, +{ "label": "16/117", "node": 4092, "naklon": 5 }, +{ "label": "16/118", "node": 3631, "naklon": null }, +{ "label": "16/119", "node": 3632, "naklon": 0 }, +{ "label": "16/120", "node": 3641, "naklon": null }, +{ "label": "16/121", "node": 3638, "naklon": 0 }, +{ "label": "16/122", "node": 3637, "naklon": null }, +{ "label": "16/123", "node": 4142, "naklon": null }, +{ "label": "16/124", "node": 4147, "naklon": 5 }, +{ "label": "16/125", "node": 4139, "naklon": 5 }, +{ "label": "20/30A", "node": 3172, "naklon": 2 }, +{ "label": "20/30B", "node": 3164, "naklon": 2 }, +{ "label": "20/1", "node": 3247, "naklon": 10 }, +{ "label": "20/2", "node": 3296, "naklon": 10 }, +{ "label": "20/3", "node": 3246, "naklon": 10 }, +{ "label": "20/4", "node": 3270, "naklon": 10 }, +{ "label": "20/5", "node": 3294, "naklon": 10 }, +{ "label": "20/6", "node": 3298, "naklon": 10 }, +{ "label": "20/7", "node": 3297, "naklon": 10 }, +{ "label": "20/8", "node": 3293, "naklon": 10 }, +{ "label": "20/9", "node": 3299, "naklon": 10 }, +{ "label": "20/10", "node": 3295, "naklon": 10 }, +{ "label": "20/11", "node": 3244, "naklon": 10 }, +{ "label": "20/12", "node": 3249, "naklon": 10 }, +{ "label": "20/13", "node": 3268, "naklon": 10 }, +{ "label": "20/14", "node": 3245, "naklon": 10 }, +{ "label": "20/15", "node": 3278, "naklon": 10 }, +{ "label": "20/16", "node": 3280, "naklon": 10 }, +{ "label": "20/17", "node": 3292, "naklon": 10 }, +{ "label": "20/18", "node": 3287, "naklon": 10 }, +{ "label": "20/19", "node": 3282, "naklon": 10 }, +{ "label": "20/20", "node": 3273, "naklon": 0 }, +{ "label": "20/21", "node": 3157, "naklon": 0 }, +{ "label": "20/22", "node": 3283, "naklon": 0 }, +{ "label": "20/23", "node": 3159, "naklon": 0 }, +{ "label": "20/24", "node": 3289, "naklon": 0 }, +{ "label": "20/25", "node": 3163, "naklon": 0 }, +{ "label": "20/26", "node": 3126, "naklon": 0 }, +{ "label": "20/27", "node": 3171, "naklon": 0 }, +{ "label": "20/28", "node": 3162, "naklon": 0 }, +{ "label": "20/29", "node": 3279, "naklon": 10 }, +{ "label": "20/31", "node": 3173, "naklon": 0 }, +{ "label": "20/32", "node": 3127, "naklon": 0 }, +{ "label": "20/33", "node": 3131, "naklon": 0 }, +{ "label": "20/34", "node": 3129, "naklon": 0 }, +{ "label": "20/35", "node": 3276, "naklon": 2 }, +{ "label": "20/36", "node": 3290, "naklon": 2 }, +{ "label": "20/37", "node": 3132, "naklon": 0 }, +{ "label": "20/38", "node": 3138, "naklon": 0 }, +{ "label": "20/39", "node": 3272, "naklon": 0 }, +{ "label": "20/40", "node": 3291, "naklon": 0 }, +{ "label": "20/41", "node": 3277, "naklon": 10 }, +{ "label": "20/42", "node": 3286, "naklon": 10 }, +{ "label": "20/43", "node": 3281, "naklon": 10 }, +{ "label": "20/44", "node": 3288, "naklon": 10 }, +{ "label": "20/45", "node": 3284, "naklon": 10 }, +{ "label": "20/46", "node": 3167, "naklon": 10 }, +{ "label": "20/47", "node": 3872, "naklon": 0 }, +{ "label": "20/48", "node": 3124, "naklon": 0 }, +{ "label": "20/49", "node": 3133, "naklon": 0 }, +{ "label": "20/50", "node": 3158, "naklon": 0 }, +{ "label": "20/51", "node": 3169, "naklon": 0 }, +{ "label": "20/52", "node": 3146, "naklon": 0 }, +{ "label": "20/53", "node": 3160, "naklon": 0 }, +{ "label": "20/54", "node": 3248, "naklon": 0 }, +{ "label": "20/55", "node": 3156, "naklon": 0 }, +{ "label": "20/56", "node": 3161, "naklon": 0 }, +{ "label": "20/57", "node": 3170, "naklon": 0 }, +{ "label": "20/58", "node": 3168, "naklon": 0 }, +{ "label": "20/59", "node": 3125, "naklon": 0 }, +{ "label": "20/60", "node": 3166, "naklon": 0 }, +{ "label": "20/61", "node": 3130, "naklon": 0 }, +{ "label": "20/62", "node": 3563, "naklon": 0 }, +{ "label": "20/63", "node": 3550, "naklon": null }, +{ "label": "20/67", "node": 3269, "naklon": 0 }, +{ "label": "21/1", "node": 2921, "naklon": 0 }, +{ "label": "21/2", "node": 2707, "naklon": 0 }, +{ "label": "21/3", "node": 2723, "naklon": 0 }, +{ "label": "21/4", "node": 2716, "naklon": 0 }, +{ "label": "21/5", "node": 2717, "naklon": 0 }, +{ "label": "21/6", "node": 2720, "naklon": 0 }, +{ "label": "21/7", "node": 2722, "naklon": 0 }, +{ "label": "21/8", "node": 2718, "naklon": 0 }, +{ "label": "21/9", "node": 2724, "naklon": 0 }, +{ "label": "21/10", "node": 2742, "naklon": 0 }, +{ "label": "21/11", "node": 2743, "naklon": 0 }, +{ "label": "21/12", "node": 2733, "naklon": 0 }, +{ "label": "21/14", "node": 2903, "naklon": 0 }, +{ "label": "21/15", "node": 2917, "naklon": 0 }, +{ "label": "21/16", "node": 2897, "naklon": 0 }, +{ "label": "21/17", "node": 2914, "naklon": 0 }, +{ "label": "21/18", "node": 2898, "naklon": 0 }, +{ "label": "21/19", "node": 2773, "naklon": 0 }, +{ "label": "21/20", "node": 2895, "naklon": 0 }, +{ "label": "21/21", "node": 2896, "naklon": 0 }, +{ "label": "21/22", "node": 2771, "naklon": 0 }, +{ "label": "21/23", "node": 2772, "naklon": 0 }, +{ "label": "21/24", "node": 2793, "naklon": 0 }, +{ "label": "21/25", "node": 2902, "naklon": 0 }, +{ "label": "21/26", "node": 2910, "naklon": 0 }, +{ "label": "21/27", "node": 2909, "naklon": 0 }, +{ "label": "21/28", "node": 2920, "naklon": 0 }, +{ "label": "21/29", "node": 2916, "naklon": 0 }, +{ "label": "21/30", "node": 2904, "naklon": 0 }, +{ "label": "21/31", "node": 2915, "naklon": 0 }, +{ "label": "21/32", "node": 2905, "naklon": 0 }, +{ "label": "21/33", "node": 2900, "naklon": 0 }, +{ "label": "21/34", "node": 2899, "naklon": 0 }, +{ "label": "21/36", "node": 2741, "naklon": 0 }, +{ "label": "21/37", "node": 2714, "naklon": 0 }, +{ "label": "21/38", "node": 2701, "naklon": 0 }, +{ "label": "21/39", "node": 2703, "naklon": 0 }, +{ "label": "21/40", "node": 2704, "naklon": 0 }, +{ "label": "21/41", "node": 2702, "naklon": 0 }, +{ "label": "21/42", "node": 2706, "naklon": 0 }, +{ "label": "21/43", "node": 2776, "naklon": 0 }, +{ "label": "21/44", "node": 2770, "naklon": 0 }, +{ "label": "21/45", "node": 2786, "naklon": 0 }, +{ "label": "21/46", "node": 2779, "naklon": 0 }, +{ "label": "21/47", "node": 2782, "naklon": 0 }, +{ "label": "21/48", "node": 2785, "naklon": 0 }, +{ "label": "21/49", "node": 2769, "naklon": 0 }, +{ "label": "21/50", "node": 3354, "naklon": 0 }, +{ "label": "21/51", "node": 2778, "naklon": 0 }, +{ "label": "21/52", "node": 2775, "naklon": 0 }, +{ "label": "21/53", "node": 2780, "naklon": 0 }, +{ "label": "21/54", "node": 2790, "naklon": 0 }, +{ "label": "21/55", "node": 2792, "naklon": 0 }, +{ "label": "21/56", "node": 2774, "naklon": 0 }, +{ "label": "22/1", "node": 2630, "naklon": 0 }, +{ "label": "22/2", "node": 2631, "naklon": 0 }, +{ "label": "22/3", "node": 2632, "naklon": 0 }, +{ "label": "22/4", "node": 2633, "naklon": 0 }, +{ "label": "22/5", "node": 2634, "naklon": 0 }, +{ "label": "22/6", "node": 2636, "naklon": 0 }, +{ "label": "22/7", "node": 4367, "naklon": 0 }, +{ "label": "22/8", "node": 2637, "naklon": 0 }, +{ "label": "22/9", "node": 2638, "naklon": 0 }, +{ "label": "22/10", "node": 2639, "naklon": 0 }, +{ "label": "22/11", "node": 2640, "naklon": 0 }, +{ "label": "22/12", "node": 2641, "naklon": 0 }, +{ "label": "22/13", "node": 2642, "naklon": 0 }, +{ "label": "22/14", "node": 2643, "naklon": 0 }, +{ "label": "22/15", "node": 2644, "naklon": 0 }, +{ "label": "22/16", "node": 2645, "naklon": 0 }, +{ "label": "22/17", "node": 2646, "naklon": 0 }, +{ "label": "22/18", "node": 2647, "naklon": 0 }, +{ "label": "22/19", "node": 2648, "naklon": 0 }, +{ "label": "22/20", "node": 2649, "naklon": 0 }, +{ "label": "22/21", "node": 2650, "naklon": 0 }, +{ "label": "22/22", "node": 2651, "naklon": 0 }, +{ "label": "22/23", "node": 4103, "naklon": 0 }, +{ "label": "22/24", "node": 2653, "naklon": 0 }, +{ "label": "22/25", "node": 2654, "naklon": 0 }, +{ "label": "22/26", "node": 2655, "naklon": 0 }, +{ "label": "22/27", "node": 2656, "naklon": 0 }, +{ "label": "22/28", "node": 2657, "naklon": 0 }, +{ "label": "22/29", "node": 2658, "naklon": 0 }, +{ "label": "22/30", "node": 2659, "naklon": 0 }, +{ "label": "22/31", "node": 2660, "naklon": 0 }, +{ "label": "22/32", "node": 2661, "naklon": 0 }, +{ "label": "22/32/1", "node": 3015, "naklon": 0 }, +{ "label": "22/33", "node": 2662, "naklon": 0 }, +{ "label": "22/34", "node": 2663, "naklon": 0 }, +{ "label": "22/35", "node": 2664, "naklon": 0 }, +{ "label": "22/36", "node": 2665, "naklon": 0 }, +{ "label": "22/37", "node": 2666, "naklon": 0 }, +{ "label": "22/38", "node": 2667, "naklon": 0 }, +{ "label": "22/39", "node": 2668, "naklon": 0 }, +{ "label": "22/40", "node": 2669, "naklon": null }, +{ "label": "22/41", "node": 2670, "naklon": null }, +{ "label": "22/42", "node": 2671, "naklon": null }, +{ "label": "23/9A", "node": 3087, "naklon": 10 }, +{ "label": "23/9B", "node": 3090, "naklon": 10 }, +{ "label": "23/1", "node": 3075, "naklon": 0 }, +{ "label": "23/2", "node": 3089, "naklon": 0 }, +{ "label": "23/3", "node": 3088, "naklon": 0 }, +{ "label": "23/4", "node": 3228, "naklon": 10 }, +{ "label": "23/5", "node": 2751, "naklon": 10 }, +{ "label": "23/6", "node": 3243, "naklon": 10 }, +{ "label": "23/7", "node": 4349, "naklon": 10 }, +{ "label": "23/8", "node": 3102, "naklon": 10 }, +{ "label": "23/10", "node": 3099, "naklon": 10 }, +{ "label": "23/11", "node": 3103, "naklon": 10 }, +{ "label": "23/12", "node": 3093, "naklon": 10 }, +{ "label": "23/13", "node": 3098, "naklon": 10 }, +{ "label": "23/14", "node": 3092, "naklon": 10 }, +{ "label": "23/15", "node": 3233, "naklon": 0 }, +{ "label": "23/16", "node": 3095, "naklon": 0 }, +{ "label": "23/17", "node": 4074, "naklon": 0 }, +{ "label": "23/18", "node": 2729, "naklon": 0 }, +{ "label": "23/19", "node": 3234, "naklon": 0 }, +{ "label": "23/20", "node": 3094, "naklon": 0 }, +{ "label": "23/21", "node": 2817, "naklon": 0 }, +{ "label": "23/22", "node": 3226, "naklon": 0 }, +{ "label": "23/23", "node": 3225, "naklon": 0 }, +{ "label": "23/24", "node": 3237, "naklon": 0 }, +{ "label": "23/25", "node": 4250, "naklon": 0 }, +{ "label": "23/26", "node": 3059, "naklon": 10 }, +{ "label": "23/27", "node": 3238, "naklon": 10 }, +{ "label": "23/28", "node": 3242, "naklon": 10 }, +{ "label": "23/29", "node": 3236, "naklon": 10 }, +{ "label": "23/30", "node": 3112, "naklon": 10 }, +{ "label": "23/31", "node": 3224, "naklon": 0 }, +{ "label": "23/32", "node": 4298, "naklon": 10 }, +{ "label": "23/33", "node": 4150, "naklon": 10 }, +{ "label": "23/34", "node": 3091, "naklon": 10 }, +{ "label": "25/1", "node": 3771, "naklon": 5 }, +{ "label": "25/2", "node": 3777, "naklon": 5 }, +{ "label": "25/3", "node": 3749, "naklon": 5 }, +{ "label": "25/4", "node": 3769, "naklon": 5 }, +{ "label": "25/5", "node": 3765, "naklon": 5 }, +{ "label": "25/6", "node": 3785, "naklon": 5 }, +{ "label": "25/7", "node": 3761, "naklon": 5 }, +{ "label": "25/8", "node": 3758, "naklon": 5 }, +{ "label": "25/9", "node": 3766, "naklon": 5 }, +{ "label": "25/10", "node": 3779, "naklon": 5 }, +{ "label": "25/11", "node": 3899, "naklon": 10 }, +{ "label": "25/12", "node": 3922, "naklon": 10 }, +{ "label": "25/13", "node": 3912, "naklon": 10 }, +{ "label": "25/14", "node": 3933, "naklon": 10 }, +{ "label": "25/15", "node": 3921, "naklon": 10 }, +{ "label": "25/16", "node": 4300, "naklon": 10 }, +{ "label": "25/17", "node": 3927, "naklon": 10 }, +{ "label": "25/18", "node": 3212, "naklon": 10 }, +{ "label": "25/19", "node": 3208, "naklon": 10 }, +{ "label": "25/20", "node": 3207, "naklon": 10 }, +{ "label": "25/21", "node": 4294, "naklon": 10 }, +{ "label": "25/22", "node": 3209, "naklon": 10 }, +{ "label": "25/23", "node": 3745, "naklon": 10 }, +{ "label": "25/24", "node": 3762, "naklon": 10 }, +{ "label": "25/25", "node": 3215, "naklon": 10 }, +{ "label": "25/26", "node": 3210, "naklon": 10 }, +{ "label": "25/27", "node": 3211, "naklon": 10 }, +{ "label": "25/28", "node": 3206, "naklon": 10 }, +{ "label": "25/29", "node": 3918, "naklon": 5 }, +{ "label": "25/30", "node": 3928, "naklon": 5 }, +{ "label": "25/31", "node": 3917, "naklon": 5 }, +{ "label": "25/32", "node": 4029, "naklon": 0 }, +{ "label": "25/33", "node": 4038, "naklon": 0 }, +{ "label": "25/34", "node": 4022, "naklon": 0 }, +{ "label": "25/35", "node": 3937, "naklon": 0 }, +{ "label": "25/36", "node": 3190, "naklon": 0 }, +{ "label": "25/37", "node": 3835, "naklon": 0 }, +{ "label": "25/38", "node": 3201, "naklon": 0 }, +{ "label": "25/39", "node": 3193, "naklon": 0 }, +{ "label": "25/40", "node": 3191, "naklon": 0 }, +{ "label": "25/41", "node": 3203, "naklon": 0 }, +{ "label": "25/42", "node": 4301, "naklon": 0 }, +{ "label": "25/43", "node": 3223, "naklon": 0 }, +{ "label": "25/44", "node": 3202, "naklon": 0 }, +{ "label": "25/45", "node": 3205, "naklon": 0 }, +{ "label": "25/46", "node": 3194, "naklon": 0 }, +{ "label": "25/47", "node": 3198, "naklon": 0 }, +{ "label": "25/48", "node": 3204, "naklon": 0 }, +{ "label": "25/49", "node": 3200, "naklon": 0 }, +{ "label": "25/50", "node": 3216, "naklon": 0 }, +{ "label": "25/51", "node": 3932, "naklon": 5 }, +{ "label": "25/52", "node": 3923, "naklon": 5 }, +{ "label": "25/53", "node": 3913, "naklon": 5 }, +{ "label": "25/54", "node": 3900, "naklon": 5 }, +{ "label": "25/55", "node": 4189, "naklon": 10 }, +{ "label": "25/56", "node": 4191, "naklon": 10 }, +{ "label": "25/57", "node": 3790, "naklon": 10 }, +{ "label": "25/58", "node": 4190, "naklon": 10 }, +{ "label": "25/59", "node": 4302, "naklon": 0 }, +{ "label": "25/60", "node": 4351, "naklon": 0 }, +{ "label": "25/61", "node": 4075, "naklon": 0 }, +{ "label": "25/62", "node": 4071, "naklon": 0 }, +{ "label": "25/63", "node": 3784, "naklon": 0 }, +{ "label": "25/64", "node": 4065, "naklon": 0 }, +{ "label": "25/65", "node": 4297, "naklon": 0 }, +{ "label": "25/66", "node": 4295, "naklon": 0 }, +{ "label": "25/67", "node": 4299, "naklon": 0 }, +{ "label": "25/68", "node": 3772, "naklon": 0 }, +{ "label": "25/69", "node": 3941, "naklon": 0 }, +{ "label": "25/70", "node": 3782, "naklon": 0 }, +{ "label": "25/71", "node": 4068, "naklon": 0 }, +{ "label": "25/72", "node": 4073, "naklon": 0 }, +{ "label": "25/73", "node": 3901, "naklon": 5 }, +{ "label": "25/74", "node": 4296, "naklon": 5 }, +{ "label": "25/75", "node": 3910, "naklon": 5 }, +{ "label": "25/76", "node": 4293, "naklon": 5 }, +{ "label": "25/77", "node": 3919, "naklon": 5 }, +{ "label": "25/78", "node": 3924, "naklon": 5 }, +{ "label": "25/79", "node": 3909, "naklon": 5 }, +{ "label": "25/80", "node": 3896, "naklon": 5 }, +{ "label": "25/81", "node": 3911, "naklon": 5 }, +{ "label": "25/82", "node": 2819, "naklon": 15 }, +{ "label": "25/83", "node": 3776, "naklon": 15 }, +{ "label": "25/84", "node": 3752, "naklon": 15 }, +{ "label": "25/85", "node": 4353, "naklon": 15 }, +{ "label": "25/86", "node": 3791, "naklon": 0 }, +{ "label": "25/87", "node": 3770, "naklon": 0 }, +{ "label": "25/88", "node": 3760, "naklon": 0 }, +{ "label": "25/89", "node": 3115, "naklon": 0 }, +{ "label": "25/90", "node": 3738, "naklon": 0 }, +{ "label": "25/91", "node": 3748, "naklon": 0 }, +{ "label": "25/92", "node": 3753, "naklon": 0 }, +{ "label": "25/93", "node": 3775, "naklon": 0 }, +{ "label": "25/94", "node": 3778, "naklon": 5 }, +{ "label": "25/95", "node": 4078, "naklon": 5 }, +{ "label": "25/96", "node": 4088, "naklon": 5 }, +{ "label": "25/97", "node": 3856, "naklon": 5 }, +{ "label": "25/98", "node": 4084, "naklon": 5 }, +{ "label": "25/99", "node": 4069, "naklon": 5 }, +{ "label": "25/100", "node": 4188, "naklon": 5 }, +{ "label": "25/101", "node": 4064, "naklon": 5 }, +{ "label": "25/102", "node": 3792, "naklon": 5 }, +{ "label": "25/103", "node": 3780, "naklon": 5 }, +{ "label": "25/104", "node": 4034, "naklon": 5 }, +{ "label": "25/105", "node": 4072, "naklon": 5 }, +{ "label": "25/106", "node": 3884, "naklon": 5 }, +{ "label": "25/107", "node": 3793, "naklon": 5 }, +{ "label": "25/108", "node": 3863, "naklon": 5 }, +{ "label": "25/109", "node": 3855, "naklon": 5 }, +{ "label": "33/1", "node": 3846, "naklon": 0 }, +{ "label": "33/2", "node": 3943, "naklon": 0 }, +{ "label": "33/3", "node": 3903, "naklon": 0 }, +{ "label": "33/4", "node": 3982, "naklon": 0 }, +{ "label": "33/5", "node": 3879, "naklon": 0 }, +{ "label": "33/6", "node": 3887, "naklon": 0 }, +{ "label": "33/7", "node": 3920, "naklon": 5 }, +{ "label": "33/8", "node": 3942, "naklon": 5 }, +{ "label": "33/9", "node": 3829, "naklon": null }, +{ "label": "34/79A", "node": 3452, "naklon": 6 }, +{ "label": "34/79B", "node": 3460, "naklon": 6 }, +{ "label": "34/90A", "node": 3443, "naklon": 6 }, +{ "label": "34/90B", "node": 3445, "naklon": 6 }, +{ "label": "34/90C", "node": 3457, "naklon": 6 }, +{ "label": "34/97A", "node": 3461, "naklon": 6 }, +{ "label": "34/97B", "node": 3463, "naklon": 6 }, +{ "label": "34/98A", "node": 3426, "naklon": 6 }, +{ "label": "34/98B", "node": 3444, "naklon": 6 }, +{ "label": "34/99A", "node": 3453, "naklon": 6 }, +{ "label": "34/99B", "node": 3455, "naklon": 6 }, +{ "label": "34/1", "node": 4009, "naklon": 0 }, +{ "label": "34/2", "node": 3602, "naklon": 0 }, +{ "label": "34/3", "node": 3441, "naklon": 0 }, +{ "label": "34/4", "node": 3464, "naklon": 0 }, +{ "label": "34/5", "node": 3883, "naklon": 0 }, +{ "label": "34/6", "node": 4098, "naklon": 0 }, +{ "label": "34/7", "node": 4003, "naklon": 0 }, +{ "label": "34/8", "node": 4004, "naklon": 0 }, +{ "label": "34/9", "node": 3888, "naklon": 0 }, +{ "label": "34/10", "node": 3997, "naklon": 0 }, +{ "label": "34/11", "node": 4006, "naklon": 0 }, +{ "label": "34/12", "node": 4000, "naklon": 0 }, +{ "label": "34/13", "node": 4011, "naklon": 0 }, +{ "label": "34/14", "node": 3999, "naklon": 0 }, +{ "label": "34/15", "node": 3981, "naklon": 0 }, +{ "label": "34/16", "node": 3988, "naklon": 0 }, +{ "label": "34/17", "node": 3986, "naklon": 0 }, +{ "label": "34/18", "node": 3998, "naklon": 0 }, +{ "label": "34/19", "node": 3983, "naklon": 0 }, +{ "label": "34/20", "node": 4005, "naklon": 0 }, +{ "label": "34/21", "node": 4001, "naklon": 0 }, +{ "label": "34/22", "node": 4008, "naklon": 0 }, +{ "label": "34/23", "node": 4002, "naklon": 0 }, +{ "label": "34/24", "node": 3996, "naklon": 0 }, +{ "label": "34/25", "node": 4007, "naklon": 0 }, +{ "label": "34/26", "node": 4113, "naklon": 15 }, +{ "label": "34/27", "node": 3595, "naklon": 5 }, +{ "label": "34/28", "node": 3599, "naklon": 5 }, +{ "label": "34/29", "node": 3601, "naklon": 5 }, +{ "label": "34/30", "node": 4205, "naklon": 0 }, +{ "label": "34/31", "node": 3987, "naklon": null }, +{ "label": "34/32", "node": 4214, "naklon": 0 }, +{ "label": "34/33", "node": 4226, "naklon": 0 }, +{ "label": "34/34", "node": 4209, "naklon": 0 }, +{ "label": "34/35", "node": 4201, "naklon": 0 }, +{ "label": "34/36", "node": 3440, "naklon": 0 }, +{ "label": "34/37", "node": 3465, "naklon": 0 }, +{ "label": "34/38", "node": 3446, "naklon": 0 }, +{ "label": "34/39", "node": 4039, "naklon": 5 }, +{ "label": "34/40", "node": 4057, "naklon": 5 }, +{ "label": "34/41", "node": 3985, "naklon": 0 }, +{ "label": "34/42", "node": 3882, "naklon": 0 }, +{ "label": "34/43", "node": 4040, "naklon": 5 }, +{ "label": "34/44", "node": 3231, "naklon": 0 }, +{ "label": "34/45", "node": 3227, "naklon": 0 }, +{ "label": "34/46", "node": 3431, "naklon": 0 }, +{ "label": "34/47", "node": 4013, "naklon": 0 }, +{ "label": "34/48", "node": 4045, "naklon": 0 }, +{ "label": "34/49", "node": 3949, "naklon": 0 }, +{ "label": "34/50", "node": 3953, "naklon": 0 }, +{ "label": "34/51", "node": 3952, "naklon": 0 }, +{ "label": "34/52", "node": 3995, "naklon": 0 }, +{ "label": "34/53", "node": 3992, "naklon": 0 }, +{ "label": "34/54", "node": 4198, "naklon": 0 }, +{ "label": "34/55", "node": 3935, "naklon": 0 }, +{ "label": "34/56", "node": 4050, "naklon": 0 }, +{ "label": "34/57", "node": 4049, "naklon": 0 }, +{ "label": "34/58", "node": 4054, "naklon": 0 }, +{ "label": "34/59", "node": 3663, "naklon": 6 }, +{ "label": "34/60", "node": 3661, "naklon": 6 }, +{ "label": "34/61", "node": 3664, "naklon": 6 }, +{ "label": "34/62", "node": 3660, "naklon": 6 }, +{ "label": "34/63", "node": 3662, "naklon": 6 }, +{ "label": "34/65", "node": 3665, "naklon": 6 }, +{ "label": "34/66", "node": 3667, "naklon": 6 }, +{ "label": "34/67", "node": 3675, "naklon": 6 }, +{ "label": "34/68", "node": 3666, "naklon": 6 }, +{ "label": "34/69", "node": 3652, "naklon": 6 }, +{ "label": "34/70", "node": 3458, "naklon": 6 }, +{ "label": "34/70/1", "node": 4425, "naklon": 6 }, +{ "label": "34/71", "node": 3459, "naklon": 6 }, +{ "label": "34/72", "node": 3435, "naklon": 6 }, +{ "label": "34/73", "node": 3448, "naklon": 6 }, +{ "label": "34/74", "node": 3451, "naklon": 6 }, +{ "label": "34/75", "node": 3442, "naklon": 6 }, +{ "label": "34/76", "node": 3449, "naklon": 6 }, +{ "label": "34/77", "node": 3450, "naklon": 6 }, +{ "label": "34/78", "node": 3433, "naklon": 6 }, +{ "label": "34/80", "node": 3432, "naklon": 12 }, +{ "label": "34/81", "node": 3470, "naklon": 12 }, +{ "label": "34/82", "node": 3438, "naklon": 12 }, +{ "label": "34/83", "node": 3439, "naklon": 12 }, +{ "label": "34/84", "node": 4028, "naklon": 5 }, +{ "label": "34/85", "node": 3596, "naklon": 5 }, +{ "label": "34/86", "node": 4021, "naklon": 5 }, +{ "label": "34/87", "node": 3437, "naklon": 12 }, +{ "label": "34/88", "node": 3428, "naklon": 12 }, +{ "label": "34/89", "node": 3430, "naklon": 12 }, +{ "label": "34/91", "node": 3454, "naklon": 6 }, +{ "label": "34/92", "node": 3492, "naklon": 6 }, +{ "label": "34/93", "node": 3462, "naklon": 6 }, +{ "label": "34/94", "node": 3427, "naklon": 6 }, +{ "label": "34/95", "node": 3434, "naklon": 6 }, +{ "label": "34/96", "node": 3456, "naklon": 6 }, +{ "label": "34/98/1", "node": 4307, "naklon": 6 }, +{ "label": "35/1", "node": 3968, "naklon": 0 }, +{ "label": "35/2", "node": 3969, "naklon": 0 }, +{ "label": "35/3", "node": 3947, "naklon": 0 }, +{ "label": "35/4", "node": 3979, "naklon": 0 }, +{ "label": "35/5", "node": 3959, "naklon": 0 }, +{ "label": "35/6", "node": 3948, "naklon": 0 }, +{ "label": "35/7", "node": 3961, "naklon": 0 }, +{ "label": "35/8", "node": 3956, "naklon": 0 }, +{ "label": "35/9", "node": 3604, "naklon": 0 }, +{ "label": "35/10", "node": 3944, "naklon": 0 }, +{ "label": "35/11", "node": 3960, "naklon": 0 }, +{ "label": "35/12", "node": 3958, "naklon": 0 }, +{ "label": "35/13", "node": 4036, "naklon": 5 }, +{ "label": "35/18", "node": 3893, "naklon": 5 }, +{ "label": "35/19", "node": 4108, "naklon": 5 }, +{ "label": "35/20", "node": 4017, "naklon": 5 }, +{ "label": "35/21", "node": 3963, "naklon": 0 }, +{ "label": "35/22", "node": 3658, "naklon": 0 }, +{ "label": "35/23", "node": 3975, "naklon": 0 }, +{ "label": "35/24", "node": 3980, "naklon": 0 }, +{ "label": "35/25", "node": 4012, "naklon": 0 }, +{ "label": "35/26", "node": 3655, "naklon": 0 }, +{ "label": "35/27", "node": 3962, "naklon": 0 }, +{ "label": "35/28", "node": 3945, "naklon": 0 }, +{ "label": "35/29", "node": 3569, "naklon": 0 }, +{ "label": "35/30", "node": 3429, "naklon": 0 }, +{ "label": "35/31", "node": 3657, "naklon": 0 }, +{ "label": "35/32", "node": 3646, "naklon": 0 }, +{ "label": "35/33", "node": 3622, "naklon": 0 }, +{ "label": "35/34", "node": 3612, "naklon": 0 }, +{ "label": "35/35", "node": 3955, "naklon": 0 }, +{ "label": "35/37", "node": 3878, "naklon": 0 }, +{ "label": "35/38", "node": 3965, "naklon": 0 }, +{ "label": "35/39", "node": 3970, "naklon": 0 }, +{ "label": "35/40", "node": 3611, "naklon": 0 }, +{ "label": "35/41", "node": 2635, "naklon": 0 }, +{ "label": "35/42", "node": 3978, "naklon": 0 }, +{ "label": "35/43", "node": 4213, "naklon": 0 }, +{ "label": "35/44", "node": 3984, "naklon": 0 }, +{ "label": "35/45", "node": 4218, "naklon": 0 }, +{ "label": "35/46", "node": 3973, "naklon": 0 }, +{ "label": "35/47", "node": 3974, "naklon": 0 }, +{ "label": "35/48", "node": 3759, "naklon": 0 }, +{ "label": "35/49", "node": 3844, "naklon": 0 }, +{ "label": "35/50", "node": 3804, "naklon": 0 }, +{ "label": "35/51", "node": 3831, "naklon": 0 }, +{ "label": "35/52", "node": 3643, "naklon": 0 }, +{ "label": "35/53", "node": 3966, "naklon": 0 }, +{ "label": "35/54", "node": 3971, "naklon": 0 }, +{ "label": "35/55", "node": 3650, "naklon": 6 }, +{ "label": "35/56", "node": 3651, "naklon": 6 }, +{ "label": "35/57", "node": 3669, "naklon": 6 }, +{ "label": "35/58", "node": 3648, "naklon": 6 }, +{ "label": "35/59", "node": 3645, "naklon": 6 }, +{ "label": "35/60", "node": 3659, "naklon": 6 }, +{ "label": "35/61", "node": 3647, "naklon": 6 }, +{ "label": "35/62", "node": 3644, "naklon": 6 }, +{ "label": "35/63", "node": 3671, "naklon": 6 }, +{ "label": "35/64", "node": 3682, "naklon": 6 }, +{ "label": "35/65", "node": 3672, "naklon": 6 }, +{ "label": "35/66", "node": 3683, "naklon": 6 }, +{ "label": "35/67", "node": 3673, "naklon": 6 }, +{ "label": "35/68", "node": 3674, "naklon": 6 }, +{ "label": "35/69", "node": 3679, "naklon": 6 }, +{ "label": "35/70", "node": 3649, "naklon": 6 }, +{ "label": "35/71", "node": 3687, "naklon": 6 }, +{ "label": "35/72", "node": 3677, "naklon": 6 }, +{ "label": "35/73", "node": 3690, "naklon": 6 }, +{ "label": "35/74", "node": 3691, "naklon": 6 }, +{ "label": "35/75", "node": 3676, "naklon": 6 }, +{ "label": "35/76", "node": 3680, "naklon": 6 }, +{ "label": "35/77", "node": 3668, "naklon": 6 }, +{ "label": "35/78", "node": 3681, "naklon": 6 }, +{ "label": "35/79", "node": 3670, "naklon": 6 }, +{ "label": "35/80", "node": 3689, "naklon": 6 }, +{ "label": "35/81", "node": 3678, "naklon": 6 }, +{ "label": "35/82", "node": 3693, "naklon": 6 }, +{ "label": "35/83", "node": 3654, "naklon": null }, +{ "label": "36/1", "node": 4086, "naklon": 0 }, +{ "label": "36/2", "node": 4085, "naklon": 0 }, +{ "label": "36/3", "node": 4083, "naklon": 0 }, +{ "label": "36/4", "node": 4087, "naklon": 0 }, +{ "label": "36/5", "node": 4077, "naklon": 0 }, +{ "label": "36/6", "node": 4082, "naklon": 0 }, +{ "label": "36/7", "node": 4186, "naklon": 0 }, +{ "label": "36/8", "node": 4206, "naklon": 0 }, +{ "label": "36/9", "node": 4080, "naklon": 0 }, +{ "label": "36/10", "node": 4081, "naklon": 0 }, +{ "label": "36/11", "node": 4210, "naklon": 0 }, +{ "label": "36/12", "node": 4079, "naklon": 0 }, +{ "label": "36/13", "node": 4076, "naklon": 0 }, +{ "label": "36/14", "node": 3852, "naklon": 0 }, +{ "label": "36/15", "node": 2813, "naklon": 0 }, +{ "label": "36/16", "node": 4219, "naklon": 0 }, +{ "label": "37/1A", "node": 3104, "naklon": 15 }, +{ "label": "37/1B", "node": 3121, "naklon": 15 }, +{ "label": "37/2", "node": 3113, "naklon": 10 }, +{ "label": "37/3", "node": 3118, "naklon": 10 }, +{ "label": "37/4", "node": 3111, "naklon": 10 }, +{ "label": "37/5", "node": 4020, "naklon": 10 }, +{ "label": "37/6", "node": 3119, "naklon": 10 }, +{ "label": "37/7", "node": 3110, "naklon": 10 }, +{ "label": "37/8", "node": 3108, "naklon": 10 }, +{ "label": "37/12", "node": 3107, "naklon": 0 }, +{ "label": "37/13", "node": 3199, "naklon": 0 }, +{ "label": "37/14", "node": 3120, "naklon": 0 }, +{ "label": "37/15", "node": 3122, "naklon": 0 }, +{ "label": "37/16", "node": 3908, "naklon": 0 }, +{ "label": "37/17", "node": 3114, "naklon": 0 }, +{ "label": "37/18", "node": 3105, "naklon": 0 }, +{ "label": "37/19", "node": 3116, "naklon": 0 }, +{ "label": "37/20", "node": 3106, "naklon": 0 }, +{ "label": "37/21", "node": 2887, "naklon": 5 }, +{ "label": "37/22", "node": 2888, "naklon": 5 }, +{ "label": "37/23", "node": 2877, "naklon": 5 }, +{ "label": "37/24", "node": 2891, "naklon": 5 }, +{ "label": "37/25", "node": 2886, "naklon": 5 }, +{ "label": "37/26", "node": 2892, "naklon": 5 }, +{ "label": "37/27", "node": 2882, "naklon": 5 }, +{ "label": "37/28", "node": 2883, "naklon": 5 }, +{ "label": "37/29", "node": 2876, "naklon": 5 }, +{ "label": "37/30", "node": 3109, "naklon": 5 }, +{ "label": "37/31", "node": 4152, "naklon": 5 }, +{ "label": "37/32", "node": 3117, "naklon": 5 }, +{ "label": "37/33", "node": 2870, "naklon": 5 }, +{ "label": "37/34", "node": 2867, "naklon": 0 }, +{ "label": "37/35", "node": 2865, "naklon": 0 }, +{ "label": "37/36", "node": 3096, "naklon": 0 }, +{ "label": "37/37", "node": 2871, "naklon": 0 }, +{ "label": "37/38", "node": 2884, "naklon": 0 }, +{ "label": "37/39", "node": 2855, "naklon": 0 }, +{ "label": "37/40", "node": 2878, "naklon": 0 }, +{ "label": "37/41", "node": 2889, "naklon": 0 }, +{ "label": "37/42", "node": 2879, "naklon": 0 }, +{ "label": "37/43", "node": 2850, "naklon": 0 }, +{ "label": "37/44", "node": 2894, "naklon": 0 }, +{ "label": "37/45", "node": 2880, "naklon": 0 }, +{ "label": "37/46", "node": 2893, "naklon": 0 }, +{ "label": "37/47", "node": 2890, "naklon": 0 }, +{ "label": "37/48", "node": 4355, "naklon": 0 }, +{ "label": "37/49", "node": 2885, "naklon": 0 }, +{ "label": "37/50", "node": 2875, "naklon": 0 }, +{ "label": "38/30A", "node": 3486, "naklon": 5 }, +{ "label": "38/30B", "node": 3714, "naklon": 0 }, +{ "label": "38/32A", "node": 3483, "naklon": 5 }, +{ "label": "38/32B", "node": 3496, "naklon": 0 }, +{ "label": "38/35A", "node": 3487, "naklon": 5 }, +{ "label": "38/35B", "node": 3498, "naklon": 5 }, +{ "label": "38/38A", "node": 3578, "naklon": 5 }, +{ "label": "38/38B", "node": 3508, "naklon": 5 }, +{ "label": "38/59A", "node": 3787, "naklon": 5 }, +{ "label": "38/59B", "node": 3491, "naklon": 5 }, +{ "label": "38/1", "node": 3568, "naklon": null }, +{ "label": "38/2", "node": 3502, "naklon": 0 }, +{ "label": "38/3", "node": 3836, "naklon": 0 }, +{ "label": "38/4", "node": 3588, "naklon": 0 }, +{ "label": "38/5", "node": 3493, "naklon": 0 }, +{ "label": "38/6", "node": 3580, "naklon": 0 }, +{ "label": "38/7", "node": 3572, "naklon": 0 }, +{ "label": "38/8", "node": 3506, "naklon": 0 }, +{ "label": "38/9", "node": 3503, "naklon": 0 }, +{ "label": "38/10", "node": 3579, "naklon": 0 }, +{ "label": "38/11", "node": 3586, "naklon": 0 }, +{ "label": "38/12", "node": 3495, "naklon": 5 }, +{ "label": "38/13", "node": 3492, "naklon": 5 }, +{ "label": "38/14", "node": 3532, "naklon": 5 }, +{ "label": "38/15", "node": 3574, "naklon": 5 }, +{ "label": "38/16", "node": 4140, "naklon": 5 }, +{ "label": "38/17", "node": 3795, "naklon": 5 }, +{ "label": "38/18", "node": 3788, "naklon": 5 }, +{ "label": "38/19", "node": 3796, "naklon": 5 }, +{ "label": "38/20", "node": 3797, "naklon": 5 }, +{ "label": "38/21", "node": 3798, "naklon": 5 }, +{ "label": "38/22", "node": 3786, "naklon": 5 }, +{ "label": "38/23", "node": 4067, "naklon": 5 }, +{ "label": "38/24", "node": 3773, "naklon": 5 }, +{ "label": "38/25", "node": 3774, "naklon": 5 }, +{ "label": "38/26", "node": 3789, "naklon": 5 }, +{ "label": "38/27", "node": 3520, "naklon": null }, +{ "label": "38/29", "node": 3577, "naklon": 5 }, +{ "label": "38/31", "node": 3530, "naklon": null }, +{ "label": "38/33", "node": 3488, "naklon": 5 }, +{ "label": "38/34", "node": 3505, "naklon": 5 }, +{ "label": "38/36", "node": 3497, "naklon": 5 }, +{ "label": "38/37", "node": 3490, "naklon": 5 }, +{ "label": "38/39", "node": 3585, "naklon": 5 }, +{ "label": "38/40", "node": 3582, "naklon": 5 }, +{ "label": "38/41", "node": 3507, "naklon": 5 }, +{ "label": "38/42", "node": 3484, "naklon": 5 }, +{ "label": "38/43", "node": 3501, "naklon": 5 }, +{ "label": "38/44", "node": 3581, "naklon": 5 }, +{ "label": "38/45", "node": 4192, "naklon": 5 }, +{ "label": "38/46", "node": 3576, "naklon": 5 }, +{ "label": "38/47", "node": 3489, "naklon": 5 }, +{ "label": "38/48", "node": 3573, "naklon": 5 }, +{ "label": "38/49", "node": 3504, "naklon": 5 }, +{ "label": "38/50", "node": 3794, "naklon": 5 }, +{ "label": "38/51", "node": 3485, "naklon": 5 }, +{ "label": "38/52", "node": 3482, "naklon": 5 }, +{ "label": "38/53", "node": 3575, "naklon": 5 }, +{ "label": "38/54", "node": 3499, "naklon": 5 }, +{ "label": "38/55", "node": 3494, "naklon": 5 }, +{ "label": "38/56", "node": 3583, "naklon": 5 }, +{ "label": "38/57", "node": 3570, "naklon": 5 }, +{ "label": "38/58", "node": 3500, "naklon": 0 }, +{ "label": "38/63", "node": 3510, "naklon": null }, +{ "label": "38/64", "node": 3512, "naklon": null }, +{ "label": "38/67", "node": 3535, "naklon": null }, +{ "label": "38/68", "node": 3531, "naklon": null }, +{ "label": "38/69", "node": 3537, "naklon": null }, +{ "label": "39/1", "node": 3522, "naklon": 10 }, +{ "label": "39/2", "node": 4018, "naklon": 10 }, +{ "label": "39/3", "node": 4019, "naklon": 10 }, +{ "label": "39/4", "node": 4154, "naklon": 5 }, +{ "label": "39/5", "node": 3907, "naklon": 5 }, +{ "label": "39/6", "node": 4148, "naklon": 0 }, +{ "label": "39/7", "node": 4153, "naklon": 0 }, +{ "label": "39/8", "node": 3938, "naklon": 0 }, +{ "label": "39/9", "node": 3802, "naklon": 0 }, +{ "label": "39/10", "node": 4015, "naklon": 0 }, +{ "label": "39/11", "node": 3929, "naklon": 0 }, +{ "label": "39/12", "node": 3946, "naklon": 0 }, +{ "label": "39/13", "node": 4014, "naklon": 0 }, +{ "label": "39/14", "node": 4155, "naklon": 0 }, +{ "label": "39/15", "node": 4149, "naklon": 0 }, +{ "label": "39/16", "node": 3642, "naklon": 0 }, +{ "label": "39/17", "node": 3636, "naklon": 5 }, +{ "label": "39/18", "node": 3991, "naklon": 0 }, +{ "label": "39/19", "node": 3994, "naklon": 0 }, +{ "label": "39/20", "node": 3990, "naklon": 0 }, +{ "label": "39/21", "node": 3967, "naklon": 0 }, +{ "label": "39/22", "node": 3977, "naklon": 0 }, +{ "label": "39/23", "node": 3757, "naklon": 15 }, +{ "label": "39/24", "node": 3633, "naklon": 15 }, +{ "label": "39/25", "node": 3744, "naklon": 15 }, +{ "label": "39/26", "node": 4023, "naklon": 5 }, +{ "label": "39/27", "node": 3720, "naklon": 5 }, +{ "label": "39/28", "node": 3734, "naklon": 5 }, +{ "label": "39/29", "node": 3741, "naklon": 5 }, +{ "label": "39/30", "node": 3721, "naklon": 5 }, +{ "label": "39/31", "node": 3845, "naklon": 0 }, +{ "label": "39/32", "node": 3840, "naklon": 0 }, +{ "label": "39/33", "node": 3837, "naklon": null }, +{ "label": "39/34", "node": 3839, "naklon": 0 }, +{ "label": "41/1", "node": 3542, "naklon": null }, +{ "label": "41/2", "node": 3566, "naklon": null }, +{ "label": "41/3", "node": 3548, "naklon": null }, +{ "label": "41/4", "node": 3515, "naklon": null }, +{ "label": "41/5", "node": 3559, "naklon": null }, +{ "label": "41/6", "node": 3509, "naklon": null }, +{ "label": "41/7", "node": 3524, "naklon": null }, +{ "label": "41/8", "node": 3518, "naklon": null }, +{ "label": "41/9", "node": 3182, "naklon": null }, +{ "label": "41/10", "node": 3187, "naklon": null }, +{ "label": "41/11", "node": 3195, "naklon": 0 }, +{ "label": "41/12", "node": 3857, "naklon": 0 }, +{ "label": "41/13", "node": 3183, "naklon": 0 }, +{ "label": "41/14", "node": 3177, "naklon": 0 }, +{ "label": "41/15", "node": 3189, "naklon": 0 }, +{ "label": "41/16", "node": 3186, "naklon": 0 }, +{ "label": "42/1", "node": 3178, "naklon": 0 }, +{ "label": "42/2", "node": 3219, "naklon": 0 }, +{ "label": "42/3", "node": 3475, "naklon": 0 }, +{ "label": "42/4", "node": 3175, "naklon": 0 }, +{ "label": "42/5", "node": 3222, "naklon": 0 }, +{ "label": "42/6", "node": 3221, "naklon": 0 }, +{ "label": "42/7", "node": 3181, "naklon": 0 }, +{ "label": "42/8", "node": 3180, "naklon": 0 }, +{ "label": "42/9", "node": 3218, "naklon": 0 }, +{ "label": "42/10", "node": 3176, "naklon": 0 }, +{ "label": "42/11", "node": 3174, "naklon": 0 }, +{ "label": "42/12", "node": 3220, "naklon": 0 }, +{ "label": "42/13", "node": 3533, "naklon": null }, +{ "label": "42/14", "node": 3543, "naklon": null }, +{ "label": "42/15", "node": 3554, "naklon": null }, +{ "label": "42/16", "node": 3549, "naklon": null }, +{ "label": "43/1", "node": 2857, "naklon": 5 }, +{ "label": "43/2", "node": 2752, "naklon": 5 }, +{ "label": "43/3", "node": 2753, "naklon": 5 }, +{ "label": "43/4", "node": 3024, "naklon": 5 }, +{ "label": "43/5", "node": 2754, "naklon": 5 }, +{ "label": "43/6", "node": 4423, "naklon": 5 }, +{ "label": "43/7", "node": 4368, "naklon": 5 }, +{ "label": "43/8", "node": 2978, "naklon": 5 }, +{ "label": "43/9", "node": 2868, "naklon": 5 }, +{ "label": "43/10", "node": 4377, "naklon": 5 }, +{ "label": "43/11", "node": 2757, "naklon": 5 }, +{ "label": "43/12", "node": 2970, "naklon": 5 }, +{ "label": "43/13", "node": 2758, "naklon": 5 }, +{ "label": "43/14", "node": 4378, "naklon": 5 }, +{ "label": "43/15", "node": 2759, "naklon": 5 }, +{ "label": "43/16", "node": 4342, "naklon": 5 }, +{ "label": "43/17", "node": 3026, "naklon": null }, +{ "label": "43/18", "node": 2986, "naklon": null }, +{ "label": "43/19", "node": 4343, "naklon": null }, +{ "label": "43/20", "node": 2760, "naklon": null }, +{ "label": "43/21", "node": 4379, "naklon": null }, +{ "label": "43/22", "node": 2971, "naklon": null }, +{ "label": "43/23", "node": 2761, "naklon": null }, +{ "label": "43/24", "node": 2762, "naklon": null }, +{ "label": "43/25", "node": 4339, "naklon": null }, +{ "label": "43/26", "node": 4380, "naklon": null }, +{ "label": "43/27", "node": 2975, "naklon": null }, +{ "label": "43/28", "node": 3003, "naklon": null }, +{ "label": "43/29", "node": 4338, "naklon": null }, +{ "label": "43/30", "node": 3002, "naklon": null }, +{ "label": "43/31", "node": 4345, "naklon": null }, +{ "label": "43/32", "node": 2979, "naklon": null }, +{ "label": "43/33", "node": 2989, "naklon": null }, +{ "label": "43/34", "node": 2996, "naklon": null }, +{ "label": "43/35", "node": 2972, "naklon": null }, +{ "label": "43/36", "node": 2988, "naklon": null }, +{ "label": "43/37", "node": 4344, "naklon": null }, +{ "label": "43/38", "node": 3022, "naklon": null }, +{ "label": "43/39", "node": 4341, "naklon": null }, +{ "label": "43/40", "node": 2983, "naklon": null }, +{ "label": "43/41", "node": 2995, "naklon": null }, +{ "label": "43/42", "node": 2763, "naklon": null }, +{ "label": "43/43", "node": 2764, "naklon": null }, +{ "label": "43/44", "node": 2765, "naklon": null }, +{ "label": "43/45", "node": 2766, "naklon": null }, +{ "label": "43/46", "node": 2767, "naklon": null }, +{ "label": "43/47", "node": 2768, "naklon": null }, +{ "label": "43/48", "node": 3018, "naklon": null }, +{ "label": "43/49", "node": 2982, "naklon": null }, +{ "label": "43/50", "node": 3019, "naklon": 0 }, +{ "label": "43/51", "node": 3013, "naklon": null }, +{ "label": "43/52", "node": 3007, "naklon": null }, +{ "label": "43/53", "node": 2980, "naklon": null }, +{ "label": "43/54", "node": 3011, "naklon": null }, +{ "label": "43/55", "node": 2672, "naklon": null }, +{ "label": "43/56", "node": 2673, "naklon": null }, +{ "label": "43/57", "node": 2674, "naklon": null }, +{ "label": "43/58", "node": 2675, "naklon": null }, +{ "label": "43/59", "node": 2676, "naklon": null }, +{ "label": "43/60", "node": 2677, "naklon": null }, +{ "label": "43/61", "node": 2678, "naklon": null }, +{ "label": "43/62", "node": 2679, "naklon": null }, +{ "label": "43/63", "node": 2680, "naklon": null }, +{ "label": "43/64", "node": 2840, "naklon": null }, +{ "label": "43/65", "node": 2682, "naklon": null }, +{ "label": "43/66", "node": 2683, "naklon": null }, +{ "label": "43/67", "node": 2684, "naklon": 0 }, +{ "label": "43/68", "node": 2685, "naklon": null }, +{ "label": "43/69", "node": 2686, "naklon": null }, +{ "label": "43/70", "node": 2687, "naklon": null }, +{ "label": "43/71", "node": 2688, "naklon": null }, +{ "label": "43/72", "node": 2689, "naklon": null }, +{ "label": "43/73", "node": 2690, "naklon": null }, +{ "label": "43/74", "node": 2691, "naklon": null }, +{ "label": "43/75", "node": 2692, "naklon": null }, +{ "label": "43/76", "node": 2693, "naklon": 0 }, +{ "label": "43/77", "node": 2694, "naklon": null }, +{ "label": "43/78", "node": 2695, "naklon": null }, +{ "label": "43/79", "node": 2696, "naklon": 0 }, +{ "label": "43/80", "node": 2697, "naklon": null }, +{ "label": "43/81", "node": 2698, "naklon": 0 }, +{ "label": "43/82", "node": 2699, "naklon": null }, +{ "label": "43/83", "node": 2700, "naklon": 0 }, +{ "label": "43/84", "node": 2744, "naklon": null }, +{ "label": "43/85", "node": 2745, "naklon": 0 }, +{ "label": "43/86", "node": 2746, "naklon": null }, +{ "label": "43/87", "node": 2747, "naklon": 0 }, +{ "label": "43/88", "node": 2748, "naklon": null }, +{ "label": "43/89", "node": 2749, "naklon": 0 }, +{ "label": "43/90", "node": 2841, "naklon": null }, +{ "label": "45/1", "node": 4237, "naklon": 5 }, +{ "label": "45/2", "node": 4226, "naklon": 5 }, +{ "label": "45/3", "node": 4242, "naklon": 5 }, +{ "label": "45/4", "node": 4179, "naklon": 5 }, +{ "label": "45/5", "node": 4247, "naklon": 5 }, +{ "label": "45/6", "node": 4245, "naklon": 5 }, +{ "label": "45/7", "node": 3872, "naklon": 5 }, +{ "label": "45/8", "node": 4175, "naklon": 5 }, +{ "label": "45/9", "node": 4236, "naklon": 5 }, +{ "label": "45/10", "node": 4170, "naklon": 5 }, +{ "label": "45/11", "node": 4238, "naklon": 5 }, +{ "label": "45/12", "node": 4246, "naklon": 5 }, +{ "label": "45/13", "node": 4166, "naklon": 5 }, +{ "label": "45/14", "node": 4227, "naklon": 5 }, +{ "label": "45/15", "node": 4171, "naklon": 5 }, +{ "label": "45/16", "node": 4180, "naklon": 5 }, +{ "label": "45/17", "node": 4244, "naklon": 5 }, +{ "label": "45/18", "node": 4199, "naklon": 5 }, +{ "label": "45/19", "node": 4239, "naklon": 5 }, +{ "label": "45/20", "node": 4207, "naklon": 5 }, +{ "label": "45/21", "node": 4223, "naklon": 5 }, +{ "label": "45/22", "node": 4230, "naklon": 5 }, +{ "label": "45/23", "node": 4233, "naklon": 5 }, +{ "label": "45/24", "node": 4222, "naklon": 5 }, +{ "label": "45/25", "node": 4217, "naklon": 5 }, +{ "label": "45/26", "node": 4243, "naklon": 5 }, +{ "label": "45/27", "node": 4200, "naklon": 5 }, +{ "label": "45/28", "node": 4228, "naklon": 5 }, +{ "label": "45/29", "node": 4211, "naklon": 5 }, +{ "label": "45/30", "node": 4234, "naklon": 5 }, +{ "label": "45/31", "node": 4235, "naklon": 5 }, +{ "label": "45/32", "node": 4203, "naklon": 5 }, +{ "label": "45/33", "node": 4240, "naklon": 5 }, +{ "label": "45/34", "node": 4224, "naklon": 5 }, +{ "label": "45/35", "node": 4232, "naklon": 5 }, +{ "label": "45/36", "node": 4231, "naklon": 5 }, +{ "label": "45/37", "node": 4161, "naklon": 5 }, +{ "label": "45/38", "node": 4225, "naklon": 5 }, +{ "label": "45/39", "node": 4241, "naklon": 5 }, +{ "label": "45/40", "node": 4229, "naklon": 5 }, +{ "label": "45/41", "node": 4221, "naklon": 5 }, +{ "label": "45/42", "node": 4212, "naklon": 5 }, +{ "label": "45/43", "node": 4216, "naklon": 5 }, +{ "label": "45/44", "node": 3864, "naklon": null }, +{ "label": "46/1", "node": 3806, "naklon": 5 }, +{ "label": "46/2", "node": 3813, "naklon": 5 }, +{ "label": "46/3", "node": 3815, "naklon": 5 }, +{ "label": "46/4", "node": 3807, "naklon": 5 }, +{ "label": "46/5", "node": 3895, "naklon": 5 }, +{ "label": "46/6", "node": 3809, "naklon": 5 }, +{ "label": "46/7", "node": 3820, "naklon": 5 }, +{ "label": "46/8", "node": 3805, "naklon": 5 }, +{ "label": "46/9", "node": 3894, "naklon": 0 }, +{ "label": "46/10", "node": 4055, "naklon": 0 }, +{ "label": "46/11", "node": 3812, "naklon": 5 }, +{ "label": "46/12", "node": 3822, "naklon": 5 }, +{ "label": "46/13", "node": 3821, "naklon": 5 }, +{ "label": "46/14", "node": 3808, "naklon": 5 }, +{ "label": "46/15", "node": 3799, "naklon": 5 }, +{ "label": "46/16", "node": 3816, "naklon": 5 }, +{ "label": "46/17", "node": 3751, "naklon": 5 }, +{ "label": "46/18", "node": 3814, "naklon": 5 }, +{ "label": "46/19", "node": 4044, "naklon": 0 }, +{ "label": "46/20", "node": 3931, "naklon": 0 }, +{ "label": "46/21", "node": 3902, "naklon": 5 }, +{ "label": "46/22", "node": 3916, "naklon": 5 }, +{ "label": "46/23", "node": 3892, "naklon": 5 }, +{ "label": "46/24", "node": 3914, "naklon": 5 }, +{ "label": "46/25", "node": 3898, "naklon": 5 }, +{ "label": "46/26", "node": 3897, "naklon": 5 }, +{ "label": "46/27", "node": 3885, "naklon": 5 }, +{ "label": "46/28", "node": 3906, "naklon": 5 }, +{ "label": "46/29", "node": 3930, "naklon": 0 }, +{ "label": "46/30", "node": 3936, "naklon": 0 }, +{ "label": "46/31", "node": 3860, "naklon": 5 }, +{ "label": "46/32", "node": 3841, "naklon": 5 }, +{ "label": "46/33", "node": 3873, "naklon": 5 }, +{ "label": "46/34", "node": 3854, "naklon": 5 }, +{ "label": "46/35", "node": 3939, "naklon": 5 }, +{ "label": "46/36", "node": 3858, "naklon": 5 }, +{ "label": "46/37", "node": 3940, "naklon": 5 }, +{ "label": "46/38", "node": 4035, "naklon": 5 }, +{ "label": "47/1", "node": 3373, "naklon": 0 }, +{ "label": "47/2", "node": 3374, "naklon": 0 }, +{ "label": "47/3", "node": 3384, "naklon": 0 }, +{ "label": "47/4", "node": 3385, "naklon": 0 }, +{ "label": "48/1", "node": 4051, "naklon": 5 }, +{ "label": "48/2", "node": 4041, "naklon": 5 }, +{ "label": "48/3", "node": 4056, "naklon": 5 }, +{ "label": "48/4", "node": 3875, "naklon": 5 }, +{ "label": "48/5", "node": 4061, "naklon": 5 }, +{ "label": "48/6", "node": 4047, "naklon": 5 }, +{ "label": "48/7", "node": 4060, "naklon": 5 }, +{ "label": "48/8", "node": 4059, "naklon": 5 }, +{ "label": "48/9", "node": 4058, "naklon": 5 }, +{ "label": "48/10", "node": 3635, "naklon": 5 }, +{ "label": "48/11", "node": 3640, "naklon": 5 }, +{ "label": "48/12", "node": 3747, "naklon": 5 }, +{ "label": "48/13", "node": 3629, "naklon": 5 }, +{ "label": "48/14", "node": 4048, "naklon": 5 }, +{ "label": "48/15", "node": 4063, "naklon": 5 }, +{ "label": "48/16", "node": 4062, "naklon": 5 }, +{ "label": "48/17", "node": 4043, "naklon": 5 }, +{ "label": "48/18", "node": 4052, "naklon": 5 }, +{ "label": "48/19", "node": 4042, "naklon": 5 }, +{ "label": "48/20", "node": 4053, "naklon": 5 }, +{ "label": "50/15A", "node": 4167, "naklon": null }, +{ "label": "50/15B", "node": 4159, "naklon": null }, +{ "label": "50/1", "node": 4183, "naklon": 0 }, +{ "label": "50/2", "node": 4157, "naklon": 0 }, +{ "label": "50/3", "node": 4160, "naklon": 0 }, +{ "label": "50/4", "node": 4173, "naklon": 0 }, +{ "label": "50/5", "node": 4177, "naklon": 0 }, +{ "label": "50/6", "node": 4174, "naklon": 0 }, +{ "label": "50/7", "node": 4178, "naklon": 0 }, +{ "label": "50/8", "node": 4195, "naklon": 0 }, +{ "label": "50/9", "node": 4169, "naklon": 0 }, +{ "label": "50/10", "node": 4162, "naklon": 0 }, +{ "label": "50/11", "node": 4158, "naklon": 0 }, +{ "label": "50/12", "node": 4182, "naklon": 0 }, +{ "label": "50/13", "node": 4194, "naklon": 0 }, +{ "label": "50/14", "node": 4184, "naklon": 0 }, +{ "label": "50/16", "node": 4197, "naklon": null }, +{ "label": "50/17", "node": 4164, "naklon": null }, +{ "label": "50/18", "node": 3306, "naklon": null }, +{ "label": "50/19", "node": 4168, "naklon": null }, +{ "label": "50/20", "node": 4193, "naklon": null }, +{ "label": "50/21", "node": 4187, "naklon": null }, +{ "label": "50/22", "node": 4163, "naklon": null }, +{ "label": "50/23", "node": 4165, "naklon": null }, +{ "label": "50/24", "node": 4185, "naklon": null }, +{ "label": "50/25", "node": 3904, "naklon": null }, +{ "label": "53/1", "node": 2619, "naklon": 0 }, +{ "label": "53/2", "node": 2623, "naklon": 0 }, +{ "label": "53/3", "node": 2617, "naklon": 0 }, +{ "label": "53/4", "node": 2622, "naklon": 0 }, +{ "label": "53/5", "node": 2618, "naklon": 0 }, +{ "label": "53/6", "node": 2626, "naklon": 0 }, +{ "label": "53/7", "node": 2869, "naklon": 0 }, +{ "label": "53/8", "node": 2613, "naklon": 0 }, +{ "label": "53/9", "node": 2608, "naklon": 0 }, +{ "label": "53/10", "node": 2611, "naklon": 0 }, +{ "label": "53/11", "node": 2598, "naklon": 0 }, +{ "label": "53/12", "node": 3528, "naklon": 0 }, +{ "label": "53/13", "node": 3545, "naklon": 0 }, +{ "label": "53/14", "node": 2620, "naklon": 0 }, +{ "label": "53/15", "node": 2612, "naklon": 0 }, +{ "label": "53/16", "node": 2615, "naklon": 0 }, +{ "label": "53/17", "node": 3722, "naklon": 0 }, +{ "label": "53/18", "node": 2624, "naklon": 0 }, +{ "label": "53/19", "node": 2609, "naklon": 0 }, +{ "label": "53/20", "node": 2625, "naklon": 0 }, +{ "label": "53/21", "node": 2602, "naklon": 0 }, +{ "label": "53/22", "node": 2610, "naklon": 0 }, +{ "label": "53/23", "node": 2599, "naklon": 0 }, +{ "label": "53/24", "node": 2605, "naklon": 0 }, +{ "label": "53/25", "node": 2593, "naklon": 0 }, +{ "label": "53/26", "node": 3074, "naklon": 0 }, +{ "label": "53/27", "node": 2740, "naklon": 0 }, +{ "label": "53/28", "node": 2614, "naklon": 0 }, +{ "label": "53/29", "node": 2601, "naklon": 0 }, +{ "label": "53/30", "node": 4196, "naklon": 0 }, +{ "label": "53/31", "node": 2607, "naklon": 0 }, +{ "label": "53/32", "node": 2582, "naklon": 0 }, +{ "label": "53/33", "node": 2594, "naklon": 0 }, +{ "label": "53/34", "node": 2589, "naklon": 0 }, +{ "label": "53/35", "node": 2596, "naklon": 0 }, +{ "label": "53/36", "node": 2603, "naklon": 0 }, +{ "label": "53/37", "node": 2597, "naklon": 0 }, +{ "label": "53/38", "node": 2590, "naklon": 0 }, +{ "label": "53/39", "node": 2581, "naklon": 0 }, +{ "label": "53/40", "node": 2583, "naklon": 0 }, +{ "label": "53/41", "node": 2580, "naklon": 0 }, +{ "label": "53/42", "node": 2579, "naklon": 0 }, +{ "label": "53/43", "node": 2797, "naklon": 0 }, +{ "label": "53/44", "node": 2577, "naklon": 0 }, +{ "label": "53/45", "node": 2586, "naklon": 0 }, +{ "label": "53/46", "node": 2588, "naklon": 0 }, +{ "label": "53/47", "node": 2591, "naklon": 0 }, +{ "label": "53/48", "node": 2592, "naklon": 0 }, +{ "label": "53/49", "node": 2573, "naklon": 0 }, +{ "label": "53/50", "node": 2595, "naklon": 0 }, +{ "label": "53/51", "node": 2587, "naklon": 0 }, +{ "label": "53/52", "node": 2578, "naklon": 0 }, +{ "label": "53/53", "node": 2574, "naklon": 0 }, +{ "label": "53/54", "node": 2571, "naklon": 0 }, +{ "label": "53/55", "node": 2570, "naklon": 0 }, +{ "label": "53/56", "node": 2576, "naklon": 0 }, +{ "label": "53/57", "node": 2881, "naklon": 0 }, +{ "label": "53/58", "node": 2575, "naklon": 0 }, +{ "label": "53/59", "node": 2572, "naklon": 0 }, +{ "label": "53/60", "node": 2569, "naklon": 0 }, +{ "label": "55/1", "node": 4324, "naklon": 0 }, +{ "label": "55/2", "node": 4319, "naklon": 0 }, +{ "label": "55/3", "node": 4327, "naklon": 0 }, +{ "label": "55/4", "node": 4333, "naklon": 0 }, +{ "label": "55/5", "node": 4332, "naklon": 0 }, +{ "label": "55/6", "node": 4320, "naklon": 0 }, +{ "label": "55/7", "node": 4317, "naklon": 0 }, +{ "label": "55/8", "node": 4318, "naklon": 0 }, +{ "label": "55/9", "node": 4328, "naklon": 0 }, +{ "label": "55/10", "node": 4323, "naklon": 0 }, +{ "label": "55/11", "node": 4325, "naklon": 0 }, +{ "label": "55/12", "node": 4326, "naklon": 0 }, +{ "label": "55/13", "node": 4316, "naklon": 0 }, +{ "label": "55/14", "node": 4322, "naklon": 0 }, +{ "label": "55/15", "node": 4331, "naklon": 0 }, +{ "label": "55/16", "node": 4321, "naklon": 0 }, +{ "label": "55/17", "node": 4315, "naklon": 0 }, +{ "label": "55/18", "node": 4329, "naklon": 0 }, +{ "label": "55/19", "node": 4334, "naklon": 0 }, +{ "label": "55/20", "node": 4330, "naklon": 0 } +]; + +module.exports = { naklony }; diff --git a/RVO34/databases/modbus_config.js b/RVO34/databases/modbus_config.js new file mode 100755 index 0000000..b73116a --- /dev/null +++ b/RVO34/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/RVO34/databases/nodes.table b/RVO34/databases/nodes.table new file mode 100755 index 0000000..09b1f16 --- /dev/null +++ b/RVO34/databases/nodes.table @@ -0,0 +1,108 @@ +node:number|pole_number:string|node_type:string|tbname:string|line:number|profile:string|processed:boolean|status:boolean|time_of_last_communication:number ++|4198|54|NEMA|PjLblDgRBO6WQqnxmkJ1Yx0Jv3ewZN4p5a89yKdY|1||1|1|1760573768462|............. ++|3857|46|NEMA|g9OxBZ5KRwNznlY6pAppd6AWXvjdEL4eGQobMDy2|1||1|1|1760573875688|............. ++|3427|94|NEMA|2O14VBzl8aDmWdNw3A59PgAGyZ5qLJoEMpj6R9ng|1||1|1|1760573797777|............. ++|3428|88|NEMA|zdQO8GwxDqjRgP4137YVK5ANyKlpem2nL65rvVJY|1||1|1|1760573798000|............. ++|3433|78|NEMA|EjgWGnXaLy9opPOz20n4ja786BlYM3w1deVQvbKr|1||1|1|1760573800924|............. ++|3434|95|NEMA|pE5X8NQPaow6vlOZxk6aRX0q42ezGBMyWgDVjR3L|1||1|1|1760573805956|............. ++|3430|89|NEMA|WlVJBygjDZMeKX3vnAMRbR08NqdmG2x1Y69LQ4P5|1||1|1|1760573798288|............. ++|3435|72|NEMA|E6Kg9oDnLWyzPRMva7v5mJkJxp4VG58qO2w1lZYe|1||1|1|1760573806771|............. ++|3492|92|NEMA|o9vbeQlLMVg8j5dq4keLo40NxZpEmnXzwYKO1ar2|1||1|1|1760574125957|............. ++|3437|87|NEMA|gYbDLqlyZVoRerQpB72M48kWJnwM5z24POKa8Exj|1||1|1|1760573807042|............. ++|3438|82|NEMA|rDbQ84xzwgdqEoPm3kbEyy09anOZY1RXyBv2LVM6|1||1|0|1757390776362|............. ++|3439|83|NEMA|E6Kg9oDnLWyzPRMva7v5mbkJxp4VG58qO2w1lZYe|1||1|1|1760573956331|............. ++|3440|36|NEMA|BaY3Xpy1EbKGjLq2O7maBg7rx8owgQz9P4dDJRmN|1||1|1|1760573822730|............. ++|3441|3|NEMA|OzNMgZ9n43qPbjXmy7zw98A2DKdYvW5e6pxGRrVa|1||1|1|1760573960932|............. ++|3849|75|NEMA|ZmRwd93QL4gaezxEbAx2KVk1prn2XjlPvGyqJ6BO|1||1|1|1760573875433|............. ++|3444|98B|NEMA|OzNMgZ9n43qPbjXmy7zwdbA2DKdYvW5e6pxGRrVa|1||1|1|1760573832188|............. ++|3819|90B|NEMA|zrR51V2ajQ9ZLygPKkEMxakYDq38xOJolENBXGnv|1||1|1|1760573874075|............. ++|3446|38|NEMA|apKVJBwOyrP35m2lv7KYbM0YXbeWNd64En9GxRqg|1||1|1|1760573835942|............. ++|3448|73|NEMA|roKgWqY95V3mXMRzyAjKgo0bLjexpJPvaGDBw826|1||1|1|1760573968904|............. ++|3449|76|NEMA|eod9aRWLVl34Gx1Dn7VNRr72rz6qjgmpEXwQJN5Z|1||1|1|1760573970629|............. ++|3450|77|NEMA|3a5oqJN1bgnx4Ol9dk89JQ7ByE6jQ8mKDWMpGrLV|1||1|1|1760573971859|............. ++|3452|79A|NEMA|wvKJdZML6mXP4DzWBAXxpPAjxNloa5g23Ve9Y1ry|1||1|1|1760573972227|............. ++|3453|99A|NEMA|JX1ObgmqGZ54DMyYL7aDpGkEVdve38WKRzwjNrQ9|1||1|1|1760573837955|............. ++|3454|91|NEMA|apKVJBwOyrP35m2lv7KYg10YXbeWNd64En9GxRqg|1||1|1|1760573838146|............. ++|3455|99B|NEMA|RvmwNz8QPblKp41GD7lKLQkJrLVYoBO92dMegn6W|1||1|1|1760573838306|............. ++|3456|96|NEMA|6lQGaY9RDywdVzObj0ParWkPg4NBn3exEK51LWZq|1||1|1|1760573838482|............. ++|3457|90C|NEMA|BaY3Xpy1EbKGjLq2O7ma1w7rx8owgQz9P4dDJRmN|1||1|1|1760574220179|............. ++|4065|70|NEMA|52dD6ZlV1QaOpRBmbAqG2ekKnGzWMLj4eJq38Pgo|1||1|1|1760573765363|............. ++|3459|71|NEMA|rDbQ84xzwgdqEoPm3kbEyY09anOZY1RXyBv2LVM6|1||1|1|1760574233838|............. ++|3460|79B|NEMA|Nzp2OoJlqn6r1ZgvdA3BlL7abBwP5G4eE3RQmyxD|1||1|1|1760574234046|............. ++|3461|97A|NEMA|m6EYyZoJ4gWexdjVPAR52v7RDOq9wv2N5XzKGplr|1||1|1|1760573839217|............. ++|3463|97B|NEMA|JzwxZXOvDj1bVrN4nkW5mbA8qdyBl3MRKLpGPgaQ|1||1|1|1760574241330|............. ++|3464|4|NEMA|JX1ObgmqGZ54DMyYL7aDavkEVdve38WKRzwjNrQ9|1||1|1|1760574241474|............. ++|3596|85|NEMA|nJL5lPMwBx23YpqRe0rpY27damXvWVbOrD4gNzy8|1||1|1|1760574243871|............. ++|3599|28|NEMA|roKgWqY95V3mXMRzyAjKxo0bLjexpJPvaGDBw826|1||1|1|1760574245324|............. ++|3601|29|NEMA|nJL5lPMwBx23YpqRe0rpb97damXvWVbOrD4gNzy8|1||1|1|1760574249031|............. ++|3602|2|NEMA|g9OxBZ5KRwNznlY6pAppg6AWXvjdEL4eGQobMDy2|1||1|1|1760574249206|............. ++|3652|69|NEMA|PLBJzmK1r3Gynd6OW0gKne0e5wV4vx9bDEqNgYR8|1||1|1|1760573856502|............. ++|3660|62|NEMA|ZmRwd93QL4gaezxEbAx2KLk1prn2XjlPvGyqJ6BO|1||1|1|1760573869122|............. ++|3661|60|NEMA|B5EoxeMVp4zwr8nqW0GBrlARjvD1PNamOGbLg63Z|1||1|1|1760573872765|............. ++|3662|63|NEMA|eod9aRWLVl34Gx1Dn7VNRj72rz6qjgmpEXwQJN5Z|1||1|1|1760573872988|............. ++|3664|61|NEMA|aw4eELG2DlPMdn1JW0BMg8AqQXOZRN3xB5yp8VKr|1||1|1|1760573873308|............. ++|3665|65|NEMA|3a5oqJN1bgnx4Ol9dk89Jo7ByE6jQ8mKDWMpGrLV|1||1|1|1760573873452|............. ++|3666|68|NEMA|Nzp2OoJlqn6r1ZgvdA3Blo7abBwP5G4eE3RQmyxD|1||1|1|1760573873595|............. ++|3667|66|NEMA|EjgWGnXaLy9opPOz20n4jB786BlYM3w1deVQvbKr|1||1|1|1760573873739|............. ++|3675|67|NEMA|wvKJdZML6mXP4DzWBAXxpKAjxNloa5g23Ve9Y1ry|1||1|1|1760573873883|............. ++|3882|42|NEMA|pE5X8NQPaow6vlOZxk6awE0q42ezGBMyWgDVjR3L|1||1|1|1760573876040|............. ++|2755|5|NEMA|RvmwNz8QPblKp41GD7lK8BkJrLVYoBO92dMegn6W|1||1|1|1760573796786|............. ++|3888|9|NEMA|1JMYvnx2RzKEo4aWQ7DGVjkL8yZV3m9NBePXbrdj|1||1|1|1760573876215|............. ++|3935|55|NEMA|dz4ojlpP85JMgDLZWkQJeK7aKYqQexEr62GXRV1y|1||1|1|1760573886567|............. ++|3949|49|NEMA|RvmwNz8QPblKp41GD7lKbBkJrLVYoBO92dMegn6W|1||1|1|1760573887765|............. ++|3952|51|NEMA|3JjOWdylwgNLzxVab7NamgkZ2vG64rq8PEB5QmDo|1||1|1|1760573887925|............. ++|3953|50|NEMA|RO8rjaBDy21qPQJzW7omrw0pK3xmNleVZg9Ed4Gw|1||1|1|1760573888293|............. ++|3981|15|NEMA|d9x2V5LGYBzXp4mMRAOmdGkPloaqJwnQj6DgrNe3|1||1|1|1760573896983|............. ++|3983|19|NEMA|eod9aRWLVl34Gx1Dn7VNZj72rz6qjgmpEXwQJN5Z|1||1|1|1760573897175|............. ++|3985|41|NEMA|2O14VBzl8aDmWdNw3A59OKAGyZ5qLJoEMpj6R9ng|1||1|1|1760573897542|............. ++|3986|17|NEMA|aw4eELG2DlPMdn1JW0BMO8AqQXOZRN3xB5yp8VKr|1||1|1|1760573897718|............. ++|3987|31|NEMA|gYbDLqlyZVoRerQpB72MObkWJnwM5z24POKa8Exj|1||1|1|1760573897910|............. ++|3988|16|NEMA|B5EoxeMVp4zwr8nqW0GBXlARjvD1PNamOGbLg63Z|1||1|1|1760573898069|............. ++|3992|53|NEMA|1JMYvnx2RzKEo4aWQ7DGbjkL8yZV3m9NBePXbrdj|1||1|1|1760573976348|............. ++|3995|52|NEMA|Z5KyJe9nEg1QNbWlX0w4ZbkoDjBLdqzR83VGv624|1||1|1|1760573725185|............. ++|3996|24|NEMA|PLBJzmK1r3Gynd6OW0gKJe0e5wV4vx9bDEqNgYR8|1||1|1|1760573725680|............. ++|3997|10|NEMA|PjLblDgRBO6WQqnxmkJ1qx0Jv3ewZN4p5a89yKdY|1||1|1|1760573726016|............. ++|3998|18|NEMA|ZmRwd93QL4gaezxEbAx2YLk1prn2XjlPvGyqJ6BO|1||1|1|1760573726176|............. ++|3999|14|NEMA|K94XLav1glVRnyQ6r01PO5Ame3YJwBxM5oOzdP2j|1||1|1|1760573727645|............. ++|2616|12|NEMA|d5xjWYMwEJon6rLlK7yEMD7qgV4DaOeNB9ZX3Gzb|1||1|1|1760573793543|............. ++|4002|23|NEMA|Nzp2OoJlqn6r1ZgvdA3BOo7abBwP5G4eE3RQmyxD|1||1|1|1760573902367|............. ++|4003|7|NEMA|3JjOWdylwgNLzxVab7NargkZ2vG64rq8PEB5QmDo|1||1|1|1760573823050|............. ++|4004|8|NEMA|Z5KyJe9nEg1QNbWlX0w42bkoDjBLdqzR83VGv624|1||1|1|1760573823305|............. ++|4005|20|NEMA|3a5oqJN1bgnx4Ol9dk89Oo7ByE6jQ8mKDWMpGrLV|1||1|1|1760574179394|............. ++|4006|11|NEMA|dz4ojlpP85JMgDLZWkQJYK7aKYqQexEr62GXRV1y|1||1|0|1759379604673|............. ++|4007|25|NEMA|52dD6ZlV1QaOpRBmbAqGqekKnGzWMLj4eJq38Pgo|1||1|1|1760573751065|............. ++|4008|22|NEMA|wvKJdZML6mXP4DzWBAXxeKAjxNloa5g23Ve9Y1ry|1||1|1|1760573849026|............. ++|4011|13|NEMA|gRoJEyXVx4qD9er287L4va7wBzGldaPjLWQKm3Mv|1||1|1|1760573849824|............. ++|4013|47|NEMA|OzNMgZ9n43qPbjXmy7zw48A2DKdYvW5e6pxGRrVa|1||1|1|1760573755139|............. ++|4021|86|NEMA|XMBbew5z4ELrZa2mRAd3lw78vPN6gy3DdVYlpKjq|1||1|1|1760573755347|............. ++|4039|39|NEMA|o9vbeQlLMVg8j5dq4keLwo0NxZpEmnXzwYKO1ar2|1||1|1|1760574271843|............. ++|4040|43|NEMA|6lQGaY9RDywdVzObj0PaKokPg4NBn3exEK51LWZq|1||1|1|1760574272051|............. ++|4050|56|NEMA|d5xjWYMwEJon6rLlK7yEeD7qgV4DaOeNB9ZX3Gzb|1||1|1|1760573764612|............. ++|4054|58|NEMA|K94XLav1glVRnyQ6r01Pz5Ame3YJwBxM5oOzdP2j|1||1|1|1760573764788|............. ++|4057|40|NEMA|gP1eOZVj3Q9lv5aDEk45Ov7rdpqW8yLm2BbKzJxM|1||1|1|1760573764996|............. ++|4098|6|NEMA|RO8rjaBDy21qPQJzW7om3w0pK3xmNleVZg9Ed4Gw|1||1|1|1760573768079|............. ++|4113|26|NEMA|rDbQ84xzwgdqEoPm3kbElY09anOZY1RXyBv2LVM6|1||1|1|1760573768270|............. ++|4201|35|NEMA|zrR51V2ajQ9ZLygPKkEM8ykYDq38xOJolENBXGnv|1||1|1|1760574215371|............. ++|4205|30|NEMA|XMBbew5z4ELrZa2mRAd3N278vPN6gy3DdVYlpKjq|1||1|1|1760574215578|............. ++|3653|45|NEMA|JzwxZXOvDj1bVrN4nkW5W5A8qdyBl3MRKLpGPgaQ|1||1|1|1760574249590|............. ++|3231|44|NEMA|m6EYyZoJ4gWexdjVPAR54a7RDOq9wv2N5XzKGplr|1||1|1|1760574167093|............. ++|3872|7|NEMA|6lQGaY9RDywdVzObj0P1z8kPg4NBn3exEK51LWZq|1||1|1|1760573875864|............. ++|3872|98/1|NEMA-IP65|6lQGaY9RDywdVzObj0P1z8kPg4NBn3exEK51LWZq|1||1|1|1760573875864|............. ++|4425|70/1|IP65|pE5X8NQPaow6vlOZxk6gEj7q42ezGBMyWgDVjR3L|1||1|1|1760574217943|............. ++|4009|1|NEMA|JzwxZXOvDj1bVrN4nkW5K5A8qdyBl3MRKLpGPgaQ|1||1|1|1760573751385|............. ++|4028|84|NEMA|roKgWqY95V3mXMRzyAjKge0bLjexpJPvaGDBw826|1||1|1|1760574271652|............. ++|4045|48|NEMA|JX1ObgmqGZ54DMyYL7aDQvkEVdve38WKRzwjNrQ9|1||1|1|1760574135111|............. ++|4049|57|NEMA|gRoJEyXVx4qD9er287L49a7wBzGldaPjLWQKm3Mv|1||1|1|1760573761353|............. ++|3443|90A|NEMA|5dBNwRp9graYJxZn409NzwklVov1b2QLPDqGm6XK|1||1|1|1760574208645|............. ++|4001|21|NEMA|EjgWGnXaLy9opPOz20n4XB786BlYM3w1deVQvbKr|1||1|1|1760573727853|............. ++|3451|74|NEMA|nJL5lPMwBx23YpqRe0rpY97damXvWVbOrD4gNzy8|1||1|1|1760573972019|............. ++|4209|34|NEMA|5dBNwRp9graYJxZn409NOyklVov1b2QLPDqGm6XK|1||1|1|1760573771018|............. ++|3462|93|NEMA|gP1eOZVj3Q9lv5aDEk456V7rdpqW8yLm2BbKzJxM|1||1|1|1760574237433|............. ++|4214|32|NEMA|zdQO8GwxDqjRgP4137YV4WANyKlpem2nL65rvVJY|1||1|1|1760573772440|............. ++|3426|98A|NEMA|g9OxBZ5KRwNznlY6pApp81AWXvjdEL4eGQobMDy2|1||1|1|1760573797617|............. ++|3465|37|NEMA|DbQY6zyveZRwK5drV0Z8557joE4XJM83N9xl2nWq|1||1|1|1760573840095|............. ++|3470|81|NEMA|52dD6ZlV1QaOpRBmbAqG2qkKnGzWMLj4eJq38Pgo|1||1|1|1760574242481|............. ++|3432|80|NEMA|PLBJzmK1r3Gynd6OW0gKnx0e5wV4vx9bDEqNgYR8|1||1|1|1760573798496|............. ++|3663|59|NEMA|d9x2V5LGYBzXp4mMRAOmZGkPloaqJwnQj6DgrNe3|1||1|1|1760573873148|............. ++|4026|33|NEMA|WlVJBygjDZMeKX3vnAMRjo08NqdmG2x1Y69LQ4P5|1||1|1|1760573755554|............. ++|3595|27|NEMA|E6Kg9oDnLWyzPRMva7v5dJkJxp4VG58qO2w1lZYe|1||1|1|1760574243455|............. diff --git a/RVO34/databases/nodes_original/nodes_original.table b/RVO34/databases/nodes_original/nodes_original.table new file mode 100755 index 0000000..3f924f2 --- /dev/null +++ b/RVO34/databases/nodes_original/nodes_original.table @@ -0,0 +1 @@ +[{"4198": "PjLblDgRBO6WQqnxmkJ1Yx0Jv3ewZN4p5a89yKdY"}, {"3857": "g9OxBZ5KRwNznlY6pAppd6AWXvjdEL4eGQobMDy2"}, {"3427": "2O14VBzl8aDmWdNw3A59PgAGyZ5qLJoEMpj6R9ng"}, {"3428": "zdQO8GwxDqjRgP4137YVK5ANyKlpem2nL65rvVJY"}, {"3433": "EjgWGnXaLy9opPOz20n4ja786BlYM3w1deVQvbKr"}, {"3434": "pE5X8NQPaow6vlOZxk6aRX0q42ezGBMyWgDVjR3L"}, {"3430": "WlVJBygjDZMeKX3vnAMRbR08NqdmG2x1Y69LQ4P5"}, {"3435": "E6Kg9oDnLWyzPRMva7v5mJkJxp4VG58qO2w1lZYe"}, {"3492": "o9vbeQlLMVg8j5dq4keLo40NxZpEmnXzwYKO1ar2"}, {"3437": "gYbDLqlyZVoRerQpB72M48kWJnwM5z24POKa8Exj"}, {"3438": "rDbQ84xzwgdqEoPm3kbEyy09anOZY1RXyBv2LVM6"}, {"3439": "E6Kg9oDnLWyzPRMva7v5mbkJxp4VG58qO2w1lZYe"}, {"3440": "BaY3Xpy1EbKGjLq2O7maBg7rx8owgQz9P4dDJRmN"}, {"3441": "OzNMgZ9n43qPbjXmy7zw98A2DKdYvW5e6pxGRrVa"}, {"3849": "ZmRwd93QL4gaezxEbAx2KVk1prn2XjlPvGyqJ6BO"}, {"3444": "OzNMgZ9n43qPbjXmy7zwdbA2DKdYvW5e6pxGRrVa"}, {"3819": "zrR51V2ajQ9ZLygPKkEMxakYDq38xOJolENBXGnv"}, {"3446": "apKVJBwOyrP35m2lv7KYbM0YXbeWNd64En9GxRqg"}, {"3448": "roKgWqY95V3mXMRzyAjKgo0bLjexpJPvaGDBw826"}, {"3449": "eod9aRWLVl34Gx1Dn7VNRr72rz6qjgmpEXwQJN5Z"}, {"3450": "3a5oqJN1bgnx4Ol9dk89JQ7ByE6jQ8mKDWMpGrLV"}, {"3452": "wvKJdZML6mXP4DzWBAXxpPAjxNloa5g23Ve9Y1ry"}, {"3453": "JX1ObgmqGZ54DMyYL7aDpGkEVdve38WKRzwjNrQ9"}, {"3454": "apKVJBwOyrP35m2lv7KYg10YXbeWNd64En9GxRqg"}, {"3455": "RvmwNz8QPblKp41GD7lKLQkJrLVYoBO92dMegn6W"}, {"3456": "6lQGaY9RDywdVzObj0ParWkPg4NBn3exEK51LWZq"}, {"3457": "BaY3Xpy1EbKGjLq2O7ma1w7rx8owgQz9P4dDJRmN"}, {"4065": "52dD6ZlV1QaOpRBmbAqG2ekKnGzWMLj4eJq38Pgo"}, {"3459": "rDbQ84xzwgdqEoPm3kbEyY09anOZY1RXyBv2LVM6"}, {"3460": "Nzp2OoJlqn6r1ZgvdA3BlL7abBwP5G4eE3RQmyxD"}, {"3461": "m6EYyZoJ4gWexdjVPAR52v7RDOq9wv2N5XzKGplr"}, {"3463": "JzwxZXOvDj1bVrN4nkW5mbA8qdyBl3MRKLpGPgaQ"}, {"3464": "JX1ObgmqGZ54DMyYL7aDavkEVdve38WKRzwjNrQ9"}, {"3596": "nJL5lPMwBx23YpqRe0rpY27damXvWVbOrD4gNzy8"}, {"3599": "roKgWqY95V3mXMRzyAjKxo0bLjexpJPvaGDBw826"}, {"3601": "nJL5lPMwBx23YpqRe0rpb97damXvWVbOrD4gNzy8"}, {"3602": "g9OxBZ5KRwNznlY6pAppg6AWXvjdEL4eGQobMDy2"}, {"3652": "PLBJzmK1r3Gynd6OW0gKne0e5wV4vx9bDEqNgYR8"}, {"3660": "ZmRwd93QL4gaezxEbAx2KLk1prn2XjlPvGyqJ6BO"}, {"3661": "B5EoxeMVp4zwr8nqW0GBrlARjvD1PNamOGbLg63Z"}, {"3662": "eod9aRWLVl34Gx1Dn7VNRj72rz6qjgmpEXwQJN5Z"}, {"3664": "aw4eELG2DlPMdn1JW0BMg8AqQXOZRN3xB5yp8VKr"}, {"3665": "3a5oqJN1bgnx4Ol9dk89Jo7ByE6jQ8mKDWMpGrLV"}, {"3666": "Nzp2OoJlqn6r1ZgvdA3Blo7abBwP5G4eE3RQmyxD"}, {"3667": "EjgWGnXaLy9opPOz20n4jB786BlYM3w1deVQvbKr"}, {"3675": "wvKJdZML6mXP4DzWBAXxpKAjxNloa5g23Ve9Y1ry"}, {"3882": "pE5X8NQPaow6vlOZxk6awE0q42ezGBMyWgDVjR3L"}, {"2755": "RvmwNz8QPblKp41GD7lK8BkJrLVYoBO92dMegn6W"}, {"3888": "1JMYvnx2RzKEo4aWQ7DGVjkL8yZV3m9NBePXbrdj"}, {"3935": "dz4ojlpP85JMgDLZWkQJeK7aKYqQexEr62GXRV1y"}, {"3949": "RvmwNz8QPblKp41GD7lKbBkJrLVYoBO92dMegn6W"}, {"3952": "3JjOWdylwgNLzxVab7NamgkZ2vG64rq8PEB5QmDo"}, {"3953": "RO8rjaBDy21qPQJzW7omrw0pK3xmNleVZg9Ed4Gw"}, {"3981": "d9x2V5LGYBzXp4mMRAOmdGkPloaqJwnQj6DgrNe3"}, {"3983": "eod9aRWLVl34Gx1Dn7VNZj72rz6qjgmpEXwQJN5Z"}, {"3985": "2O14VBzl8aDmWdNw3A59OKAGyZ5qLJoEMpj6R9ng"}, {"3986": "aw4eELG2DlPMdn1JW0BMO8AqQXOZRN3xB5yp8VKr"}, {"3987": "gYbDLqlyZVoRerQpB72MObkWJnwM5z24POKa8Exj"}, {"3988": "B5EoxeMVp4zwr8nqW0GBXlARjvD1PNamOGbLg63Z"}, {"3992": "1JMYvnx2RzKEo4aWQ7DGbjkL8yZV3m9NBePXbrdj"}, {"3995": "Z5KyJe9nEg1QNbWlX0w4ZbkoDjBLdqzR83VGv624"}, {"3996": "PLBJzmK1r3Gynd6OW0gKJe0e5wV4vx9bDEqNgYR8"}, {"3997": "PjLblDgRBO6WQqnxmkJ1qx0Jv3ewZN4p5a89yKdY"}, {"3998": "ZmRwd93QL4gaezxEbAx2YLk1prn2XjlPvGyqJ6BO"}, {"3999": "K94XLav1glVRnyQ6r01PO5Ame3YJwBxM5oOzdP2j"}, {"2616": "d5xjWYMwEJon6rLlK7yEMD7qgV4DaOeNB9ZX3Gzb"}, {"4002": "Nzp2OoJlqn6r1ZgvdA3BOo7abBwP5G4eE3RQmyxD"}, {"4003": "3JjOWdylwgNLzxVab7NargkZ2vG64rq8PEB5QmDo"}, {"4004": "Z5KyJe9nEg1QNbWlX0w42bkoDjBLdqzR83VGv624"}, {"4005": "3a5oqJN1bgnx4Ol9dk89Oo7ByE6jQ8mKDWMpGrLV"}, {"4006": "dz4ojlpP85JMgDLZWkQJYK7aKYqQexEr62GXRV1y"}, {"4007": "52dD6ZlV1QaOpRBmbAqGqekKnGzWMLj4eJq38Pgo"}, {"4008": "wvKJdZML6mXP4DzWBAXxeKAjxNloa5g23Ve9Y1ry"}, {"4011": "gRoJEyXVx4qD9er287L4va7wBzGldaPjLWQKm3Mv"}, {"4013": "OzNMgZ9n43qPbjXmy7zw48A2DKdYvW5e6pxGRrVa"}, {"4021": "XMBbew5z4ELrZa2mRAd3lw78vPN6gy3DdVYlpKjq"}, {"4039": "o9vbeQlLMVg8j5dq4keLwo0NxZpEmnXzwYKO1ar2"}, {"4040": "6lQGaY9RDywdVzObj0PaKokPg4NBn3exEK51LWZq"}, {"4050": "d5xjWYMwEJon6rLlK7yEeD7qgV4DaOeNB9ZX3Gzb"}, {"4054": "K94XLav1glVRnyQ6r01Pz5Ame3YJwBxM5oOzdP2j"}, {"4057": "gP1eOZVj3Q9lv5aDEk45Ov7rdpqW8yLm2BbKzJxM"}, {"4098": "RO8rjaBDy21qPQJzW7om3w0pK3xmNleVZg9Ed4Gw"}, {"4113": "rDbQ84xzwgdqEoPm3kbElY09anOZY1RXyBv2LVM6"}, {"4201": "zrR51V2ajQ9ZLygPKkEM8ykYDq38xOJolENBXGnv"}, {"4205": "XMBbew5z4ELrZa2mRAd3N278vPN6gy3DdVYlpKjq"}, {"3653": "JzwxZXOvDj1bVrN4nkW5W5A8qdyBl3MRKLpGPgaQ"}, {"3231": "m6EYyZoJ4gWexdjVPAR54a7RDOq9wv2N5XzKGplr"}, {"3872": "6lQGaY9RDywdVzObj0P1z8kPg4NBn3exEK51LWZq"}, {"3872": "6lQGaY9RDywdVzObj0P1z8kPg4NBn3exEK51LWZq"}, {"4425": "pE5X8NQPaow6vlOZxk6gEj7q42ezGBMyWgDVjR3L"}, {"4009": "JzwxZXOvDj1bVrN4nkW5K5A8qdyBl3MRKLpGPgaQ"}, {"4028": "roKgWqY95V3mXMRzyAjKge0bLjexpJPvaGDBw826"}, {"4045": "JX1ObgmqGZ54DMyYL7aDQvkEVdve38WKRzwjNrQ9"}, {"4049": "gRoJEyXVx4qD9er287L49a7wBzGldaPjLWQKm3Mv"}, {"3443": "5dBNwRp9graYJxZn409NzwklVov1b2QLPDqGm6XK"}, {"4001": "EjgWGnXaLy9opPOz20n4XB786BlYM3w1deVQvbKr"}, {"3451": "nJL5lPMwBx23YpqRe0rpY97damXvWVbOrD4gNzy8"}, {"4209": "5dBNwRp9graYJxZn409NOyklVov1b2QLPDqGm6XK"}, {"3462": "gP1eOZVj3Q9lv5aDEk456V7rdpqW8yLm2BbKzJxM"}, {"4214": "zdQO8GwxDqjRgP4137YV4WANyKlpem2nL65rvVJY"}, {"3426": "g9OxBZ5KRwNznlY6pApp81AWXvjdEL4eGQobMDy2"}, {"3465": "DbQY6zyveZRwK5drV0Z8557joE4XJM83N9xl2nWq"}, {"3470": "52dD6ZlV1QaOpRBmbAqG2qkKnGzWMLj4eJq38Pgo"}, {"3432": "PLBJzmK1r3Gynd6OW0gKnx0e5wV4vx9bDEqNgYR8"}, {"3663": "d9x2V5LGYBzXp4mMRAOmZGkPloaqJwnQj6DgrNe3"}, {"4026": "WlVJBygjDZMeKX3vnAMRjo08NqdmG2x1Y69LQ4P5"}, {"3595": "E6Kg9oDnLWyzPRMva7v5dJkJxp4VG58qO2w1lZYe"}] \ No newline at end of file diff --git a/RVO34/databases/notifications.table b/RVO34/databases/notifications.table new file mode 100755 index 0000000..f7c96cb --- /dev/null +++ b/RVO34/databases/notifications.table @@ -0,0 +1,41 @@ +key:string|weight:string|sk:string|en:string ++|switching_profile_point_applied_to_line|INFORMATIONAL|Aplikovaný bod spínacieho profilu na línií č. ${line} : ${value}|Switching profile point applied to line no. ${line} : ${value}|............... ++|dusk_has_occured|INFORMATIONAL|Nastal súmrak: ${value}|Dusk has occured: ${value}|............... ++|dawn_has_occured|INFORMATIONAL|Nastal úsvit: ${value}|Dawn has occured: ${value}|............... ++|dimming_profile_was_successfully_received_by_node|NOTICE|Stmievací profil bol úspešne prijatý nodom č. ${node}|Dimming profile was successfully received by node no. ${node}|............... ++|master_node_is_responding_again|NOTICE|Master node začal znovu odpovedať|Master node is responding again|............... ++|command_was_sent_from_terminal_interface|DEBUG|Z terminálu bol odoslaný príkaz|A command was sent from terminal interface|............... ++|master_node_is_not_responding|ALERT|Master node neodpovedá|Master node is not responding|............... ++|configuration_of_dimming_profile_to_node_failed|ALERT|Konfigurácia stmievacieho profilu pre node č. ${node} zlyhala|Configuration of dimming profile to node no. ${node} has failed|............... ++|circuit_breaker_was_turned_on_line|NOTICE|Zapnutie ističa na línii č. ${line}|Circuit breaker was turned on - line no. ${line}|............... ++|circuit_breaker_was_turned_off_line|ERROR|Vypnutie ističa na línií č. ${line}|Circuit breaker was turned off - line no. ${line}|............... ++|dimming_profile_was_processed_for_node|INFORMATIONAL|Stmievací profil bol spracovaný pre node č. ${node}|Dimming profile was processed for node no. ${node}|............... ++|switching_profile_was_processed_for_line|INFORMATIONAL|Spínací profil bol spracovaný pre líniu č. ${line}|Switching profile was processed for line no. ${line}|............... ++|thermometer_is_not_responding|WARNING|Teplomer neodpovedá|Thermometer is not responding|............... ++|thermometer_is_responding_again|NOTICE|Teplomer znovu odpovedá|Thermometer is responding again|............... ++|thermometer_sends_invalid_data|WARNING|Teplomer posiela neplatné hodnoty|Thermometer sends invalid data|............... ++|main_switch_has_been_turned_off|CRITICAL|Hlavný vypínač bol vypnutý|Main switch has been turned off|............... ++|main_switch_has_been_turned_on|NOTICE|Hlavný vypínač bol zapnutý|Main switch has been turned on|............... ++|power_supply_has_disconnected_input|ALERT|Napájací zdroj nemá napätie na vstupe|Power supply has disconnected input|............... ++|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_main_open|NOTICE|Hlavné dvere boli otvorené|Main door has been opened|............... ++|door_em_open|NOTICE|Dvere silovej časti boli otvorené|Power door has been opened|............... ++|door_main_open_without_permission|WARNING|Hlavné dvere boli otvorené bez povolenia - zapnutá siréna|Main door has been opened without permission - alarm is on|............... ++|door_em_open_without_permission|WARNING|Dvere silovej časti boli otvorené bez povolenia|Power door has been opened without permission|............... ++|door_main_close|NOTICE|Hlavné dvere boli zatvorené|Main door has been closed|............... ++|door_em_close|NOTICE|Dvere silovej časti boli zatvorené|Power door has been closed|............... ++|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|............... ++|electrometer_ok|NOTICE|Elektromer znovu odpovedá|Electrometer is responding again|............... ++|no_voltage_on_phase|CRITICAL|Na fáze č. ${phase} nie je napätie|No voltage detected on phase no. ${phase}|............... ++|voltage_on_phase_restored|NOTICE|Napätie na fáze č. ${phase} bolo obnovené|Voltage on phase no. ${phase} has been restored|............... ++|flow_start|NOTICE|FLOW bol spustený|FLOW has been started |............... ++|twilight_sensor_nok|ERROR|Sensor súmraku neodpovedá|Twilight sensor is not responding|............... ++|twilight_sensor_ok|NOTICE|Sensor súmraku znovu odpovedá|Twilight sensor is responding again|............... ++|lamps_have_turned_on|NOTICE|Lampy sa zapli|Lamps have turned on|............... ++|lamps_have_turned_off|NOTICE|Lampy sa vypli|Lamps have turned off|............... ++|flow_restart|NOTICE|FLOW bol reštartovaný|FLOW has been restarted|............... ++|nodes_db_changed|NOTICE|Zmena v node databáze|Node db has changed|............... diff --git a/RVO34/databases/pins.table b/RVO34/databases/pins.table new file mode 100755 index 0000000..688b8b2 --- /dev/null +++ b/RVO34/databases/pins.table @@ -0,0 +1,18 @@ +pin:string|type:string|line:number +*|input1_01|door_condition|0|........... +*|input1_02|rotary_switch_state|0|........... +*|input1_03|rotary_switch_state|0|........... +*|input1_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|........... +*|relay1_05|state_of_contactor|4|........... +*|relay1_06|state_of_contactor|5|........... +*|relay1_07|state_of_contactor|6|........... +*|relay1_08|state_of_contactor|7|........... +*|28F46E9D0E00008B|temperature|0|........... +*|twilight_sensor|twilight_sensor|0|........... diff --git a/RVO34/databases/relays.table b/RVO34/databases/relays.table new file mode 100755 index 0000000..c4fa7bf --- /dev/null +++ b/RVO34/databases/relays.table @@ -0,0 +1,9 @@ +line:number|tbname:string|contactor:number|profile:string ++|0|o9vbeQlLMVg8j5dq4keLWb0NxZpEmnXzwYKO1ar2|1||........... ++|1|o9vbeQlLMVg8j5dq4keLJo0NxZpEmnXzwYKO1ar2|9|{"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|gP1eOZVj3Q9lv5aDEk45Pv7rdpqW8yLm2BbKzJxM|9|{"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|2O14VBzl8aDmWdNw3A59RKAGyZ5qLJoEMpj6R9ng|9|{"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}|........... ++|4|zdQO8GwxDqjRgP4137YVgaANyKlpem2nL65rvVJY|9|{"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}|........... ++|5|WlVJBygjDZMeKX3vnAMRPZ08NqdmG2x1Y69LQ4P5|9|{"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}|........... ++|6|5dBNwRp9graYJxZn409Np3klVov1b2QLPDqGm6XK|9|{"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}|........... ++|7|zrR51V2ajQ9ZLygPKkEMvJkYDq38xOJolENBXGnv|9|{"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/RVO34/databases/settings.table b/RVO34/databases/settings.table new file mode 100755 index 0000000..ceccbbd --- /dev/null +++ b/RVO34/databases/settings.table @@ -0,0 +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|project_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|cloud_topic:string|has_main_switch:boolean|daily_report:boolean|send_changed_node_numbers:boolean ++|rvo_senica_34_10.0.0.128|en|28.AC4F9D0E0000|48.70826502|17.28455203|192.168.252.1|rvo_senica_34_10.0.0.127|S4vvTUFpQSMM1vnuNal8|1883|0|64|unipi|ttyUSB0|1|20|5|6|3|u128|0|1|1|................................................... diff --git a/RVO34/databases/tbdata.nosql b/RVO34/databases/tbdata.nosql new file mode 100755 index 0000000..38e8912 --- /dev/null +++ b/RVO34/databases/tbdata.nosql @@ -0,0 +1,4 @@ +-"o9vbeQlLMVg8j5dq4keLWb0NxZpEmnXzwYKO1ar2":[{"ts":1760530127344,"values":{"_event":{"type":"notice","status":"new","source":{"func":"modbus_reader","component":"1699965957410","component_name":"Modbus reader","edge":"o9vbeQlLMVg8j5dq4keLWb0NxZpEmnXzwYKO1ar2"},"message":{"sk":"rvo_senica_34_10.0.0.128: FLOW bol reštartovaný","en":"rvo_senica_34_10.0.0.128: FLOW has been restarted"},"message_data":""}}}],"id":"3000309001eg71b"} +-"o9vbeQlLMVg8j5dq4keLWb0NxZpEmnXzwYKO1ar2":[{"ts":1760530127440,"values":{"edge_fw_version":"2025-10-08","maintenance_mode":false}}],"id":"3000309002eg70b"} +-"o9vbeQlLMVg8j5dq4keLWb0NxZpEmnXzwYKO1ar2":[{"ts":1760530127453,"values":{"statecode":2,"power_mode":"Automatic"}}],"id":"3000309004eg70b"} +-"o9vbeQlLMVg8j5dq4keLWb0NxZpEmnXzwYKO1ar2":[{"ts":1760530127531,"values":{"_event":{"type":"notice","status":"new","source":{"func":"rsPort.open()","component":"1699963668903","component_name":"DIDO_Controller","edge":"o9vbeQlLMVg8j5dq4keLWb0NxZpEmnXzwYKO1ar2"},"message":{"sk":"rvo_senica_34_10.0.0.128: FLOW bol spustený","en":"rvo_senica_34_10.0.0.128: FLOW has been started "},"message_data":""}}}],"id":"3000309006eg70b"} diff --git a/RVO34/databases/tbdatacloud.nosql b/RVO34/databases/tbdatacloud.nosql new file mode 100755 index 0000000..e378daf --- /dev/null +++ b/RVO34/databases/tbdatacloud.nosql @@ -0,0 +1,3 @@ +-"o9vbeQlLMVg8j5dq4keLWb0NxZpEmnXzwYKO1ar2":[{"ts":1760530127440,"values":{"edge_fw_version":"2025-10-08","maintenance_mode":false}}],"id":"3000309003eg71b"} +-"o9vbeQlLMVg8j5dq4keLWb0NxZpEmnXzwYKO1ar2":[{"ts":1760530127453,"values":{"statecode":2,"power_mode":"Automatic"}}],"id":"3000309005eg71b"} +-"o9vbeQlLMVg8j5dq4keLWb0NxZpEmnXzwYKO1ar2":[{"ts":1760530127531,"values":{"_event":{"type":"notice","status":"new","source":{"func":"rsPort.open()","component":"1699963668903","component_name":"DIDO_Controller","edge":"o9vbeQlLMVg8j5dq4keLWb0NxZpEmnXzwYKO1ar2"},"message":{"sk":"rvo_senica_34_10.0.0.128: FLOW bol spustený","en":"rvo_senica_34_10.0.0.128: FLOW has been started "},"message_data":""}}}],"id":"3000309007eg71b"} diff --git a/RVO34/databases/total_energy.js b/RVO34/databases/total_energy.js new file mode 100755 index 0000000..dde340e --- /dev/null +++ b/RVO34/databases/total_energy.js @@ -0,0 +1,38 @@ +//key is rvo_number, value is max energy when lamps are on +const total_energy = { + 1: 580, + 2: 1100, + 3: 3700, + 4: 4100, + 7: 360, + 12: 1700, + 13: 5400, + 14: 440, + 15: 6100, + 16: 4800, + 20: 1600, + 21: 1000, + 22: 2600, + 23: 1000, + 25: 2600, + 33: 240, + 34: 4000, + 35: 2700, + 36: 820, + 37: 1400, + 35: 3500, + 39: 1170, + 41: 740, + 42: 660, + 43: 4900, + 45: 930, + 46: 700, + 47: 1100, + 48: 1500, + 50: 3200, + 53: 1250, + 55: 1000, + 56: 5500 +} + +module.exports = total_energy; diff --git a/RVO34/debug.js b/RVO34/debug.js new file mode 100755 index 0000000..9818194 --- /dev/null +++ b/RVO34/debug.js @@ -0,0 +1,16 @@ +// =================================================== +// FOR DEVELOPMENT +// Total.js - framework for Node.js platform +// https://www.totaljs.com +// =================================================== + +const options = {}; + +// options.ip = '127.0.0.1'; +// options.port = parseInt(process.argv[2]); +// options.config = { name: 'Total.js' }; +// options.sleep = 3000; +// options.inspector = 9229; +// options.watch = ['private']; + +require('total.js/debug')(options); \ No newline at end of file diff --git a/RVO34/err.txt b/RVO34/err.txt new file mode 100755 index 0000000..b7d7155 --- /dev/null +++ b/RVO34/err.txt @@ -0,0 +1,1931 @@ +[2024-10-13T00:56:42.468] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-13T01:57:21.663] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-13T02:57:56.964] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-13T03:58:45.960] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-13T04:59:17.342] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-13T06:00:02.338] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-13T07:00:53.158] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-13T08:01:36.186] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-13T09:02:19.175] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-13T10:02:48.617] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-13T11:03:08.328] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-13T12:03:14.528] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-13T13:03:40.087] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-13T14:04:46.397] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-13T15:05:06.184] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-13T16:05:23.983] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-13T17:05:45.688] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-13T18:06:03.519] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-13T19:06:34.983] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-13T20:07:08.365] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-13T21:07:45.628] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-13T22:08:30.660] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-13T23:09:02.077] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-14T00:09:35.428] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-14T01:10:12.653] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-14T02:10:59.578] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-14T03:11:44.566] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-14T04:12:13.128] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-14T05:12:27.068] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-14T06:12:58.461] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-14T07:13:25.991] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-14T08:13:32.133] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-14T09:13:59.600] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-14T10:14:07.683] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-14T11:14:25.464] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-14T12:14:45.127] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-14T13:15:20.370] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-14T14:15:42.102] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2025-04-30T20:19:43.891] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-04-30T20:19:43.891] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-04-30T20:19:43.892] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-04-30T20:19:43.893] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-04-30T20:19:43.899] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-04-30T20:19:43.900] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-04-30T20:49:43.890] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-04-30T20:49:43.891] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-04-30T20:49:43.892] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-04-30T20:49:43.892] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-04-30T20:49:43.895] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-04-30T20:49:43.896] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-04-30T21:19:43.895] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-04-30T21:19:43.896] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-04-30T21:19:43.897] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-04-30T21:19:43.897] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-04-30T21:19:43.900] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-04-30T21:19:43.901] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-04-30T21:49:43.903] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-04-30T21:49:43.904] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-04-30T21:49:43.904] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-04-30T21:49:43.905] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-04-30T21:49:43.908] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-04-30T21:49:43.908] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-04-30T22:19:43.911] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-04-30T22:19:43.912] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-04-30T22:19:43.912] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-04-30T22:19:43.913] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-04-30T22:19:43.916] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-04-30T22:19:43.917] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-04-30T22:49:43.919] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-04-30T22:49:43.920] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-04-30T22:49:43.920] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-04-30T22:49:43.921] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-04-30T22:49:43.923] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-04-30T22:49:43.924] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-04-30T23:19:43.922] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-04-30T23:19:43.923] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-04-30T23:19:43.924] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-04-30T23:19:43.924] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-04-30T23:19:43.927] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-04-30T23:19:43.927] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-04-30T23:49:43.931] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-04-30T23:49:43.932] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-04-30T23:49:43.933] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-04-30T23:49:43.933] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-04-30T23:49:43.936] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-04-30T23:49:43.936] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-01T00:19:43.931] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-01T00:19:43.932] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-01T00:19:43.932] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-01T00:19:43.933] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-01T00:19:43.935] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-01T00:19:43.936] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-01T00:49:43.932] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-01T00:49:43.932] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-01T00:49:43.933] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-01T00:49:43.933] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-01T00:49:43.936] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-01T00:49:43.936] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-01T01:19:43.930] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-01T01:19:43.931] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-01T01:19:43.932] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-01T01:19:43.932] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-01T01:19:43.941] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-01T01:19:43.942] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-01T01:49:43.931] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-01T01:49:43.932] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-01T01:49:43.933] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-01T01:49:43.933] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-01T01:49:43.936] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-01T01:49:43.937] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-01T02:19:43.931] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-01T02:19:43.932] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-01T02:19:43.932] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-01T02:19:43.933] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-01T02:19:43.935] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-01T02:19:43.935] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-01T02:49:43.931] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-01T02:49:43.932] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-01T02:49:43.932] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-01T02:49:43.933] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-01T02:49:43.934] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-01T02:49:43.935] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-01T03:19:43.932] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-01T03:19:43.933] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-01T03:19:43.933] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-01T03:19:43.934] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-01T03:19:43.935] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-01T03:19:43.936] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-01T03:49:45.197] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-01T03:49:45.198] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-01T03:49:45.199] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-01T03:49:45.199] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-01T03:49:45.202] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-01T03:49:45.203] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-01T04:19:45.198] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-01T04:19:45.199] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-01T04:19:45.200] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-01T04:19:45.200] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-01T04:19:45.202] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-01T04:19:45.202] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-01T04:49:45.200] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-01T04:49:45.201] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-01T04:49:45.201] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-01T04:49:45.202] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-01T04:49:45.204] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-01T04:49:45.204] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-01T20:49:45.205] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-01T20:49:45.206] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-01T20:49:45.207] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-01T20:49:45.208] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-01T20:49:45.219] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-01T20:49:45.220] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-01T21:19:45.204] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-01T21:19:45.204] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-01T21:19:45.205] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-01T21:19:45.206] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-01T21:19:45.208] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-01T21:19:45.209] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-01T21:49:45.205] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-01T21:49:45.206] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-01T21:49:45.206] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-01T21:49:45.207] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-01T21:49:45.209] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-01T21:49:45.209] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-01T22:19:45.205] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-01T22:19:45.206] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-01T22:19:45.207] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-01T22:19:45.207] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-01T22:19:45.209] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-01T22:19:45.210] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-01T22:49:45.205] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-01T22:49:45.206] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-01T22:49:45.206] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-01T22:49:45.207] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-01T22:49:45.209] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-01T22:49:45.209] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-01T23:19:45.206] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-01T23:19:45.207] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-01T23:19:45.208] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-01T23:19:45.208] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-01T23:19:45.211] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-01T23:19:45.211] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-01T23:49:45.206] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-01T23:49:45.207] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-01T23:49:45.208] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-01T23:49:45.208] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-01T23:49:45.210] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-01T23:49:45.211] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-02T00:19:45.208] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-02T00:19:45.208] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-02T00:19:45.209] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-02T00:19:45.210] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-02T00:19:45.211] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-02T00:19:45.212] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-02T00:49:45.207] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-02T00:49:45.208] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-02T00:49:45.209] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-02T00:49:45.209] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-02T00:49:45.211] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-02T00:49:45.212] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-02T01:19:45.207] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-02T01:19:45.208] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-02T01:19:45.209] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-02T01:19:45.209] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-02T01:19:45.211] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-02T01:19:45.212] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-02T01:49:45.213] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-02T01:49:45.214] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-02T01:49:45.215] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-02T01:49:45.215] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-02T01:49:45.217] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-02T01:49:45.218] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-02T02:19:45.210] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-02T02:19:45.210] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-02T02:19:45.211] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-02T02:19:45.211] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-02T02:19:45.213] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-02T02:19:45.214] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-02T02:49:45.210] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-02T02:49:45.211] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-02T02:49:45.211] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-02T02:49:45.212] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-02T02:49:45.214] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-02T02:49:45.215] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-02T03:19:45.210] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-02T03:19:45.211] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-02T03:19:45.212] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-02T03:19:45.212] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-02T03:19:45.214] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-02T03:19:45.215] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-02T03:49:46.220] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-02T03:49:46.221] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-02T03:49:46.221] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-02T03:49:46.222] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-02T03:49:46.224] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-02T03:49:46.224] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-02T04:19:46.221] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-02T04:19:46.221] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-02T04:19:46.222] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-02T04:19:46.222] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-02T04:19:46.224] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-02T04:19:46.225] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-02T04:49:46.222] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-02T04:49:46.223] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-02T04:49:46.223] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-02T04:49:46.224] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-02T04:49:46.226] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-02T04:49:46.226] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-02T20:49:46.232] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-02T20:49:46.233] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-02T20:49:46.233] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-02T20:49:46.234] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-02T20:49:46.245] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-02T20:49:46.245] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-02T21:19:46.230] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-02T21:19:46.231] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-02T21:19:46.232] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-02T21:19:46.232] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-02T21:19:46.234] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-02T21:19:46.235] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-02T21:49:46.231] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-02T21:49:46.232] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-02T21:49:46.232] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-02T21:49:46.233] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-02T21:49:46.235] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-02T21:49:46.236] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-02T22:19:46.233] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-02T22:19:46.234] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-02T22:19:46.234] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-02T22:19:46.235] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-02T22:19:46.237] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-02T22:19:46.238] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-02T22:49:46.234] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-02T22:49:46.235] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-02T22:49:46.235] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-02T22:49:46.236] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-02T22:49:46.238] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-02T22:49:46.238] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-02T23:19:46.233] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-02T23:19:46.234] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-02T23:19:46.235] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-02T23:19:46.235] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-02T23:19:46.237] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-02T23:19:46.238] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-02T23:49:46.233] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-02T23:49:46.233] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-02T23:49:46.234] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-02T23:49:46.234] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-02T23:49:46.236] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-02T23:49:46.237] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-03T00:19:46.234] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-03T00:19:46.235] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-03T00:19:46.236] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-03T00:19:46.236] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-03T00:19:46.239] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-03T00:19:46.239] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-03T00:49:46.235] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-03T00:49:46.236] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-03T00:49:46.237] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-03T00:49:46.237] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-03T00:49:46.239] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-03T00:49:46.240] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-03T01:19:46.235] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-03T01:19:46.236] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-03T01:19:46.237] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-03T01:19:46.237] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-03T01:19:46.239] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-03T01:19:46.240] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-03T01:49:46.235] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-03T01:49:46.236] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-03T01:49:46.237] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-03T01:49:46.237] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-03T01:49:46.240] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-03T01:49:46.241] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-03T02:19:46.236] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-03T02:19:46.236] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-03T02:19:46.237] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-03T02:19:46.237] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-03T02:19:46.239] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-03T02:19:46.240] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-03T02:49:46.235] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-03T02:49:46.236] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-03T02:49:46.236] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-03T02:49:46.237] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-03T02:49:46.239] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-03T02:49:46.240] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-03T03:19:46.235] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-03T03:19:46.236] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-03T03:19:46.236] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-03T03:19:46.237] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-03T03:19:46.239] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-03T03:19:46.239] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-03T03:49:48.233] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-03T03:49:48.234] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-03T03:49:48.234] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-03T03:49:48.235] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-03T03:49:48.237] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-03T03:49:48.237] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-03T04:19:48.232] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-03T04:19:48.233] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-03T04:19:48.234] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-03T04:19:48.235] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-03T04:19:48.237] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-03T04:19:48.238] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-03T04:49:48.234] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-03T04:49:48.235] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-03T04:49:48.235] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-03T04:49:48.236] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-03T04:49:48.238] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-03T04:49:48.238] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-03T20:19:48.245] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-03T20:19:48.246] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-03T20:19:48.247] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-03T20:19:48.248] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-03T20:19:48.258] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-03T20:19:48.259] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-03T20:49:48.245] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-03T20:49:48.246] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-03T20:49:48.246] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-03T20:49:48.247] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-03T20:49:48.248] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-03T20:49:48.249] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-03T21:19:48.246] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-03T21:19:48.247] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-03T21:19:48.248] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-03T21:19:48.248] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-03T21:19:48.250] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-03T21:19:48.251] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-03T21:49:48.246] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-03T21:49:48.247] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-03T21:49:48.248] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-03T21:49:48.249] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-03T21:49:48.252] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-03T21:49:48.253] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-03T22:19:48.246] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-03T22:19:48.246] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-03T22:19:48.247] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-03T22:19:48.247] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-03T22:19:48.249] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-03T22:19:48.250] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-03T22:49:48.247] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-03T22:49:48.248] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-03T22:49:48.248] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-03T22:49:48.249] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-03T22:49:48.251] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-03T22:49:48.252] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-03T23:19:48.247] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-03T23:19:48.248] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-03T23:19:48.249] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-03T23:19:48.249] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-03T23:19:48.251] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-03T23:19:48.251] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-03T23:49:48.247] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-03T23:49:48.248] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-03T23:49:48.249] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-03T23:49:48.249] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-03T23:49:48.252] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-03T23:49:48.252] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-04T00:19:48.247] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-04T00:19:48.248] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-04T00:19:48.248] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-04T00:19:48.249] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-04T00:19:48.250] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-04T00:19:48.251] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-04T00:49:48.248] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-04T00:49:48.249] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-04T00:49:48.250] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-04T00:49:48.250] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-04T00:49:48.252] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-04T00:49:48.253] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-04T01:19:48.248] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-04T01:19:48.248] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-04T01:19:48.249] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-04T01:19:48.249] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-04T01:19:48.251] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-04T01:19:48.252] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-04T01:49:48.249] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-04T01:49:48.249] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-04T01:49:48.250] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-04T01:49:48.250] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-04T01:49:48.253] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-04T01:49:48.253] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-04T02:19:48.248] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-04T02:19:48.249] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-04T02:19:48.250] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-04T02:19:48.250] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-04T02:19:48.252] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-04T02:19:48.253] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-04T02:49:48.248] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-04T02:49:48.249] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-04T02:49:48.249] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-04T02:49:48.250] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-04T02:49:48.252] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-04T02:49:48.252] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-04T03:19:48.249] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-04T03:19:48.250] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-04T03:19:48.250] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-04T03:19:48.251] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-04T03:19:48.253] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-04T03:19:48.253] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-04T03:49:50.251] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-04T03:49:50.252] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-04T03:49:50.252] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-04T03:49:50.253] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-04T03:49:50.255] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-04T03:49:50.255] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-04T04:19:50.253] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-04T04:19:50.254] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-04T04:19:50.254] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-04T04:19:50.255] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-04T04:19:50.257] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-04T04:19:50.258] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-04T04:49:50.252] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-04T04:49:50.253] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-04T04:49:50.254] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-04T04:49:50.254] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-04T04:49:50.257] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-04T04:49:50.258] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-04T05:19:50.254] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-04T05:19:50.255] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-04T05:19:50.255] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-04T05:19:50.256] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-04T05:19:50.258] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-04T05:19:50.258] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-04T20:49:50.257] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-04T20:49:50.258] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-04T20:49:50.259] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-04T20:49:50.259] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-04T20:49:50.270] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-04T20:49:50.270] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-04T21:19:50.256] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-04T21:19:50.257] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-04T21:19:50.258] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-04T21:19:50.258] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-04T21:19:50.260] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-04T21:19:50.261] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-04T21:49:50.256] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-04T21:49:50.256] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-04T21:49:50.257] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-04T21:49:50.257] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-04T21:49:50.259] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-04T21:49:50.260] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-04T22:19:50.257] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-04T22:19:50.258] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-04T22:19:50.258] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-04T22:19:50.259] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-04T22:19:50.260] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-04T22:19:50.261] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-04T22:49:50.256] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-04T22:49:50.257] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-04T22:49:50.257] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-04T22:49:50.258] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-04T22:49:50.259] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-04T22:49:50.260] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-04T23:19:50.257] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-04T23:19:50.258] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-04T23:19:50.259] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-04T23:19:50.259] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-04T23:19:50.261] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-04T23:19:50.262] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-04T23:49:50.258] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-04T23:49:50.259] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-04T23:49:50.259] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-04T23:49:50.260] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-04T23:49:50.262] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-04T23:49:50.262] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-05T00:19:50.258] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-05T00:19:50.258] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-05T00:19:50.259] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-05T00:19:50.259] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-05T00:19:50.262] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-05T00:19:50.262] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-05T00:49:50.258] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-05T00:49:50.259] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-05T00:49:50.259] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-05T00:49:50.260] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-05T00:49:50.261] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-05T00:49:50.262] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-05T01:19:50.260] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-05T01:19:50.261] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-05T01:19:50.261] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-05T01:19:50.262] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-05T01:19:50.264] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-05T01:19:50.264] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-05T01:49:50.259] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-05T01:49:50.260] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-05T01:49:50.261] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-05T01:49:50.262] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-05T01:49:50.264] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-05T01:49:50.264] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-05T02:19:50.260] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-05T02:19:50.261] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-05T02:19:50.261] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-05T02:19:50.262] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-05T02:19:50.264] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-05T02:19:50.265] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-05T02:49:50.259] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-05T02:49:50.260] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-05T02:49:50.261] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-05T02:49:50.261] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-05T02:49:50.263] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-05T02:49:50.264] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-05T03:19:50.261] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-05T03:19:50.262] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-05T03:19:50.262] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-05T03:19:50.263] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-05T03:19:50.265] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-05T03:19:50.266] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-05T03:49:51.259] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-05T03:49:51.260] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-05T03:49:51.260] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-05T03:49:51.261] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-05T03:49:51.262] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-05T03:49:51.263] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-05T04:19:51.259] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-05T04:19:51.260] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-05T04:19:51.261] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-05T04:19:51.261] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-05T04:19:51.263] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-05T04:19:51.264] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-05T04:49:51.260] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-05T04:49:51.261] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-05T04:49:51.262] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-05T04:49:51.263] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-05T04:49:51.265] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-05T04:49:51.266] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-05T05:19:51.260] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-05T05:19:51.261] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-05T05:19:51.261] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-05T05:19:51.262] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-05T05:19:51.264] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-05T05:19:51.265] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-05T20:19:51.265] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-05T20:19:51.266] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-05T20:19:51.267] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-05T20:19:51.267] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-05T20:19:51.279] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-05T20:19:51.280] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-05T20:49:51.262] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-05T20:49:51.263] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-05T20:49:51.264] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-05T20:49:51.264] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-05T20:49:51.266] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-05T20:49:51.267] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-05T21:19:51.263] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-05T21:19:51.264] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-05T21:19:51.265] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-05T21:19:51.265] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-05T21:19:51.267] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-05T21:19:51.267] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-05T21:49:51.264] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-05T21:49:51.265] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-05T21:49:51.266] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-05T21:49:51.266] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-05T21:49:51.268] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-05T21:49:51.269] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-05T22:19:51.263] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-05T22:19:51.264] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-05T22:19:51.264] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-05T22:19:51.265] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-05T22:19:51.267] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-05T22:19:51.267] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-05T22:49:51.264] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-05T22:49:51.265] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-05T22:49:51.265] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-05T22:49:51.265] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-05T22:49:51.267] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-05T22:49:51.268] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-05T23:19:51.263] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-05T23:19:51.264] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-05T23:19:51.265] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-05T23:19:51.265] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-05T23:19:51.267] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-05T23:19:51.268] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-05T23:49:51.263] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-05T23:49:51.264] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-05T23:49:51.264] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-05T23:49:51.265] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-05T23:49:51.266] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-05T23:49:51.267] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-06T00:19:51.264] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-06T00:19:51.265] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-06T00:19:51.265] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-06T00:19:51.265] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-06T00:19:51.267] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-06T00:19:51.268] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-06T00:49:51.263] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-06T00:49:51.264] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-06T00:49:51.265] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-06T00:49:51.265] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-06T00:49:51.267] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-06T00:49:51.268] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-06T01:19:51.266] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-06T01:19:51.267] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-06T01:19:51.267] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-06T01:19:51.267] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-06T01:19:51.269] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-06T01:19:51.270] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-06T01:49:51.265] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-06T01:49:51.266] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-06T01:49:51.266] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-06T01:49:51.267] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-06T01:49:51.269] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-06T01:49:51.269] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-06T02:19:51.266] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-06T02:19:51.267] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-06T02:19:51.268] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-06T02:19:51.268] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-06T02:19:51.270] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-06T02:19:51.271] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-06T02:49:51.267] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-06T02:49:51.268] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-06T02:49:51.269] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-06T02:49:51.269] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-06T02:49:51.271] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-06T02:49:51.272] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-06T03:19:51.268] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-06T03:19:51.269] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-06T03:19:51.270] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-06T03:19:51.270] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-06T03:19:51.272] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-06T03:19:51.273] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-06T03:49:52.262] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-06T03:49:52.263] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-06T03:49:52.264] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-06T03:49:52.264] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-06T03:49:52.266] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-06T03:49:52.266] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-06T04:19:52.263] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-06T04:19:52.264] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-06T04:19:52.264] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-06T04:19:52.265] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-06T04:19:52.267] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-06T04:19:52.267] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-06T04:49:52.262] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-06T04:49:52.263] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-06T04:49:52.263] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-06T04:49:52.264] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-06T04:49:52.265] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-06T04:49:52.266] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-06T20:49:52.267] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-06T20:49:52.268] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-06T20:49:52.269] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-06T20:49:52.269] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-06T20:49:52.281] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-06T20:49:52.282] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-06T21:19:52.265] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-06T21:19:52.266] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-06T21:19:52.267] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-06T21:19:52.267] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-06T21:19:52.269] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-06T21:19:52.270] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-06T21:49:52.268] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-06T21:49:52.270] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-06T21:49:52.270] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-06T21:49:52.271] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-06T21:49:52.273] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-06T21:49:52.274] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-06T22:19:52.267] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-06T22:19:52.268] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-06T22:19:52.269] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-06T22:19:52.269] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-06T22:19:52.271] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-06T22:19:52.272] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-06T22:49:52.268] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-06T22:49:52.268] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-06T22:49:52.269] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-06T22:49:52.269] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-06T22:49:52.271] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-06T22:49:52.272] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-06T23:19:52.268] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-06T23:19:52.269] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-06T23:19:52.269] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-06T23:19:52.270] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-06T23:19:52.272] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-06T23:19:52.272] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-06T23:49:52.268] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-06T23:49:52.269] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-06T23:49:52.269] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-06T23:49:52.270] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-06T23:49:52.272] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-06T23:49:52.272] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-07T00:19:52.268] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-07T00:19:52.269] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-07T00:19:52.269] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-07T00:19:52.270] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-07T00:19:52.272] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-07T00:19:52.272] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-07T00:49:52.269] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-07T00:49:52.270] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-07T00:49:52.271] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-07T00:49:52.271] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-07T00:49:52.273] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-07T00:49:52.274] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-07T01:19:52.269] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-07T01:19:52.270] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-07T01:19:52.271] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-07T01:19:52.271] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-07T01:19:52.273] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-07T01:19:52.274] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-07T01:49:52.271] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-07T01:49:52.271] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-07T01:49:52.272] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-07T01:49:52.272] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-07T01:49:52.274] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-07T01:49:52.275] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-07T02:19:52.270] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-07T02:19:52.271] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-07T02:19:52.272] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-07T02:19:52.272] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-07T02:19:52.274] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-07T02:19:52.275] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-07T02:49:52.270] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-07T02:49:52.271] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-07T02:49:52.271] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-07T02:49:52.271] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-07T02:49:52.273] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-07T02:49:52.274] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-07T03:19:52.271] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-07T03:19:52.272] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-07T03:19:52.273] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-07T03:19:52.273] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-07T03:19:52.275] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-07T03:19:52.276] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-07T03:49:54.269] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-07T03:49:54.270] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-07T03:49:54.271] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-07T03:49:54.272] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-07T03:49:54.274] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-07T03:49:54.275] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-07T04:19:54.270] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-07T04:19:54.271] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-07T04:19:54.271] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-07T04:19:54.272] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-07T04:19:54.274] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-07T04:19:54.274] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-07T04:49:54.270] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-07T04:49:54.270] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-07T04:49:54.271] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-07T04:49:54.272] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-05-07T04:49:54.273] [ERROR] errLogs - uncaughtException: Cannot read property 'naklon' of undefined +[2025-05-07T04:49:54.274] [ERROR] errLogs - TypeError: Cannot read property 'naklon' of undefined + at Timeout._onTimeout (/home/unipi/flowserver/flow/cmd_manager.js:2871:37) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:00:37.393] [ERROR] errLogs - uncaughtException: Cannot read property 'getHours' of undefined +[2025-09-23T14:00:37.394] [ERROR] errLogs - TypeError: Cannot read property 'getHours' of undefined + at Timeout.emptyReportToSend [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:00:37.395] [ERROR] errLogs - uncaughtException: Cannot read property 'getHours' of undefined +[2025-09-23T14:00:37.396] [ERROR] errLogs - TypeError: Cannot read property 'getHours' of undefined + at Timeout.emptyReportToSend [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:00:37.406] [ERROR] errLogs - uncaughtException: Cannot read property 'getHours' of undefined +[2025-09-23T14:00:37.407] [ERROR] errLogs - TypeError: Cannot read property 'getHours' of undefined + at Timeout.emptyReportToSend [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:00:44.414] [ERROR] errLogs - uncaughtException: date.getHours is not a function +[2025-09-23T14:00:44.415] [ERROR] errLogs - TypeError: date.getHours is not a function + at emptyReportToSend (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at Timeout.dailyReportCheck [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1351:5) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:00:44.416] [ERROR] errLogs - uncaughtException: date.getHours is not a function +[2025-09-23T14:00:44.416] [ERROR] errLogs - TypeError: date.getHours is not a function + at emptyReportToSend (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at Timeout.dailyReportCheck [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1351:5) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:00:44.421] [ERROR] errLogs - uncaughtException: date.getHours is not a function +[2025-09-23T14:00:44.422] [ERROR] errLogs - TypeError: date.getHours is not a function + at emptyReportToSend (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at Timeout.dailyReportCheck [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1351:5) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) diff --git a/RVO34/flow/cloudmqttconnect.js b/RVO34/flow/cloudmqttconnect.js new file mode 100755 index 0000000..b03491f --- /dev/null +++ b/RVO34/flow/cloudmqttconnect.js @@ -0,0 +1,357 @@ +exports.id = 'cloudmqttconnect'; +exports.title = 'Cloud connect mqtt'; +exports.group = 'MQTT'; +exports.color = '#888600'; +exports.version = '1.0.2'; +exports.icon = 'sign-out'; +exports.input = 2; +exports.output = 2; +exports.options = { host: 'tb-stage.worksys.io', port: 1883, clientid: "", username: "" }; + +exports.html = `
+
+
+
Hostname or IP address (if not empty - setting will override db setting)
+
+
+
Port
+
+
+
+
+
@(Client id)
+
+
+
topic
+
+
+
`; + + + +const { promisifyBuilder } = require('./helper/db_helper'); +const fs = require('fs'); +const mqtt = require('mqtt'); +const nosql = NOSQL('tbdatacloud'); + +const SEND_TO = { + debug: 0, + rpcCall: 1, +} + +//CONFIG +let saveTelemetryOnError = true;//backup_on_failure overrides this value +//------------------------ + +const noSqlFileSizeLimit = 4194304;//use 5MB - 4194304 +let insertNoSqlCounter = 0; +let insertBackupNoSqlCounter = 0; +let processingData = false; + +let backup_on_failure = true;//== saveTelemetryOnError - create backup client send failure +let restore_from_backup = 50; //how many rows process at once? +let restore_backup_wait = 3;//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; + + +exports.install = function(instance) { + + var client; + var opts; + var clientReady = false; + + let o = {}; //options + + function main() { + loadSettings(); + } + + //set opts according to db settings + function loadSettings() { + + o = instance.options; + if (!o.topic) o.topic = FLOW.GLOBALS.settings.cloud_topic; + + opts = { + host: o.host, + port: o.port, + clientId: o.clientid, + username: o.username, + rejectUnauthorized: false, + resubscribe: false + }; + + console.log("wsmqttpublich -> loadSettings from instance.options", o); + + if (!o.topic) { + instance.status("Not configured", "white"); + console.log("Cloud mqtt connect: no topic selected"); + return; + } + + connectToTbServer(); + } + + function connectToTbServer() { + var url = "mqtt://" + opts.host + ":" + opts.port; + console.log("MQTT URL: ", url); + + client = mqtt.connect(url, opts); + + client.on('connect', function() { + client.subscribe(`${o.topic}_backward`, (err) => { + if (!err) { + console.log("MQTT subscribed"); + } + }); + instance.status("Connected", "green"); + clientReady = true; + sendClientError = true; + }); + + client.on('reconnect', function() { + instance.status("Reconnecting", "yellow"); + clientReady = false; + }); + + client.on('message', function(topic, message) { + // message is type of buffer + message = message.toString(); + if (message[0] === '{') { + TRY(function() { + + message = JSON.parse(message); + if (message.hasOwnProperty("device") && message.hasOwnProperty("data") && message.data.hasOwnProperty("id")) { + client.publish(`${o.topic}_forward`, `{"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 } }); + } + + }, () => instance.debug('MQTT: Error parsing data', message)); + } + + instance.send(SEND_TO.rpcCall, { "topic": o.topic, "content": message }); + }); + + client.on('close', function() { + clientReady = false; + + instance.status("Disconnected", "red"); + instance.send(SEND_TO.debug, { "message": "Client CLOSE signal received !" }); + }); + + client.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) { + console.log('MQTT client error', err); + sendClientError = false; + } + clientReady = false; + }); + + } + + + instance.on('0', function(data) { + + if (clientReady) { + //do we have some data in backup file? if any, process data from database + if (saveTelemetryOnError) { + //read telemetry data and send back to server + if (!processingData) processDataFromDatabase(); + } + + let stringifiedJson = JSON.stringify(data.data) + client.publish(`${o.topic}_forward`, stringifiedJson, { qos: 1 }); + } + 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 (saveTelemetryOnError && o.topic) { + //create new file from tbdata.nosql, if file size exceeds given limit, and clear tbdata.nosql + makeBackupFromDbFile(); + + //write to tb + data.data.id = UID(); + nosql.insert(data.data); + } + } + }); + + instance.on("1", _ => { + main(); + }) + + instance.close = function(done) { + if (clientReady) { + client.end(); + } + }; + + + function getDbBackupFileCounter(type) { + var files = fs.readdirSync(__dirname + "/../databases"); + + let counter = 0; + for (var i = 0; i < files.length; i++) { + + if (files[i] == "tbdatacloud.nosql") continue; + + if (files[i].endsWith(".nosql")) { + + let pos = files[i].indexOf("."); + if (pos > -1) { + + let fileCounter = counter; + let firstDigit = files[i].slice(0, pos); + + fileCounter = parseInt(firstDigit); + if (isNaN(fileCounter)) fileCounter = 0; + //console.log("getDbBackupFileCounter digit:", files[i], firstDigit, fileCounter, isNaN(fileCounter), type); + + if (type == "max") { + if (fileCounter > counter) { + counter = fileCounter; + } + } + else if (type == "min") { + if (counter == 0) counter = fileCounter; + + if (fileCounter < counter) { + counter = fileCounter; + } + } + } + } + + } + + if (type == "max") counter++; + + return counter; + } + + const makeBackupFromDbFile = async () => { + + if (!saveTelemetryOnError) return; + + //to avoid large file: tbdata.nosql + + //init value is 0! + if (insertNoSqlCounter > 0) { + --insertNoSqlCounter; + return; + } + + insertNoSqlCounter = 100; + + let source = __dirname + "/../databases/tbdatacloud.nosql"; + + var stats = fs.statSync(source); + var fileSizeInBytes = stats.size; + + if (fileSizeInBytes > noSqlFileSizeLimit) { + + let counter = 1; + counter = getDbBackupFileCounter("max"); + + let destination = __dirname + "/../databases/" + counter + "." + "tbdatacloud.nosql"; + + //make backup file + fs.copyFileSync(source, destination); + //fs.renameSync(p, p + "." + counter); + + //clear tbdata.nosql + fs.writeFileSync(source, ""); + fs.truncateSync(source, 0); + + } + } + + const processDataFromDatabase = async () => { + + if (restore_from_backup <= 0) return; + + //calculate diff + const now = new Date(); + let currentTime = now.getTime(); + let diff = currentTime - lastRestoreTime; + + if ((diff / 1000) < restore_backup_wait) { + //console.log("*********restore_backup_wait", diff, restore_backup_wait); + return; + } + + processingData = true; + + //get filename to process + let counter = getDbBackupFileCounter("min"); + + //we have some backup files + let dataBase = 'tbdata'; + + var nosql; + if (counter == 0) dataBase = 'tbdatacloud'; + else dataBase = counter + "." + 'tbdatacloud'; + + nosql = NOSQL(dataBase); + + //select all data - use limit restore_from_backup + let records = await promisifyBuilder(nosql.find().take(restore_from_backup)); + + for (let i = 0; i < records.length; i++) { + if (clientReady) { + + let item = records[i]; + let id = item.id; + + if (id !== undefined) { + //console.log("------------processDataFromDatabase - remove", id, dataBase, i); + + try { + + let message = JSON.parse(JSON.stringify(item)); + delete message.id; + client.publish(`${o.topic}_forward`, JSON.stringify(message), { qos: 1 }); + + //remove from database + await promisifyBuilder(nosql.remove().where("id", id)); + + } catch (error) { + //process error + console.log("processDataFromDatabase", error); + } + + } + + } + else { + processingData = false; + return; + } + } + + if (records.length > 0) { + //clean backup file + if (counter > 0) nosql.clean(); + } + + //no data in db, remove + if (records.length == 0) { + if (counter > 0) nosql.drop(); + } + + const d = new Date(); + lastRestoreTime = d.getTime(); + + processingData = false; + + } + + instance.on('options', main); + +}; diff --git a/RVO34/flow/cmd_manager.js b/RVO34/flow/cmd_manager.js new file mode 100755 index 0000000..25912df --- /dev/null +++ b/RVO34/flow/cmd_manager.js @@ -0,0 +1,3071 @@ +exports.id = 'cmd_manager'; +exports.title = 'CMD Manager'; +exports.group = 'Worksys'; +exports.color = '#5D9CEC'; +exports.version = '0.0.3'; +exports.output = ['red', 'blue', 'yellow', 'blue', 'white', 'green']; +exports.input = 3; +exports.icon = 'cloud-upload'; + +exports.html = ` +
+
+
+
RPC - run RPC calls

+
+
+
@(User)
+
+
+
@(Password)
+
+
+
@(My edge)
+
+
+
+`; +exports.readme = `Manager for CMD calls`; + + +exports.install = function(instance) { + + 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, isEmptyObject, emptyJsObject, writeToFile, addToArrayIfUnique } = require('./helper/utils'); + const bitwise = require('bitwise'); + + var SunCalc = require('./helper/suncalc'); + const DataToTbHandler = require('./helper/DataToTbHandler'); + const errorHandler = require('./helper/ErrorToServiceHandler'); + const { sendNotification } = require('./helper/notification_reporter'); + const process = require('process'); + const { errLogger, logger, monitor } = require('./helper/logger'); + + //for accelerometer purposes + const { naklony } = require("../databases/accelerometer_db"); + + const dbNodes = TABLE("nodes"); + const dbRelays = TABLE("relays"); + + let GLOBALS; + let SETTINGS; + let rsPort; + let tbHandler; + + // runTasks intervals + const SHORT_INTERVAL = 30; + const LONG_INTERVAL = 300; + + //send data to following instances: + const SEND_TO = { + debug: 0, + tb: 1, + http_response: 2, + dido_controller: 3, + infoSender: 4, + dailyReport: 5 + } + + 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 + } + + 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 sendNodeReadout = null; // interval for sending agregate data from node + + 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["1"] = minutes; // dimming + priorities["76"] = minutes; // power + + minutes = 5; + priorities["75"] = minutes; // current + priorities["79"] = minutes; // energy + priorities["87"] = minutes; // aktualny cas + //priorities["84"] = minutes; //accelerometer + + minutes = 10; + priorities["74"] = minutes; // voltage + priorities["77"] = minutes; // power factor + priorities["78"] = minutes; // frequency + + minutes = 60; + priorities["0"] = minutes; // statecode + priorities["6"] = minutes; // dusk + priorities["7"] = minutes; // dawn + priorities["8"] = minutes; // profile + + minutes = 60 * 24; + priorities["89"] = minutes; // verzia fw + priorities["80"] = minutes; // lifetime + + //prikazy kt sa budu spustat na dany node - see config.js in terminal-oms.app. (1 - dimming) + let listOfCommands = [0, 1, 6, 7, 8, 74, 75, 76, 77, 78, 79, 80, 87, 89]; + + 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; + + // holds dusk, dawn (and more) values + let sunCalcResult; + + //helper container for counting resolved group of commands (commands related to set profile) + let cmdCounter = {};//key is node, value is counter + + //TODO: is this set working?? According to previous checks, sets do not work + //if sending of profile to node fails, we send notification and push node into set, so we do not send notification twice + const nodeProfileSendFail = new Set(); + + //we expect to get current temperature in Senica from senica-prod01 + let temperatureInSenica = null; + let accelerometerInterval = null; + + //NOTE: daily reports senica: + //rvo_is_on status, we monitor all nodes - if true, power and dimming should be not 0, if false, 24/7 nodes should be 0, other rvo should not respond + let rvo_is_on; + let previous_rvo_is_on_value; + let handleDailyReport; //setInterval for dailyReportHandler function + let dailyReport = {}; //data needed for daily report + let reportToSend = {}; //final report which we send to cloud + let breakerCounter = null; // status of breakers after flow starts is not in report + let rvoPeriod; // interval of checking dusk dawn and if rvo_is_on + let initialReportStatus = false; + + const DAILY_REPORT_HANDLER_TIME = 3_600_000; + const SET_SUNCALC_RESULT_TIME = 3_600_000; + const SET_RVO_PERIOD_TIME = 300_000; + const ADD_NODE_TO_REPORT_TIME = 3_600_000; + + //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); + + let now = new Date(); + console.log("Cmd-mngr installed", now.toLocaleString("sk-SK")); + + sunCalcResult = calculateDuskDawn(); + + handleRsPort(); + + customTasksInterval = setInterval(reportEdgeDateTimeAndNumberOfLuminaires, 120_000); + setTimeout(reportEdgeDateTimeAndNumberOfLuminaires, 4000); + + //dailyReport related + emptyReportToSend(); + breakerCounter = Object.keys(relaysData).length - 1; // we get number of lines (breakers) except of line 0 + rvoPeriod = setInterval(setRvoPeriod, SET_RVO_PERIOD_TIME); + setTimeout(setRvoPeriod, 3000); + setInterval(setSunCalcResult, SET_SUNCALC_RESULT_TIME); + handleDailyReport = setInterval(dailyReportHandler, DAILY_REPORT_HANDLER_TIME); + + + setCorrectTime = setInterval(setCorrectPlcTimeOnceADay, 60000 * 60); // 1 hour + setCorrectPlcTimeOnceADay(); + + sendNodeReadout = setInterval(sendNodesData, 150_000); + accelerometerInterval = setInterval(accelerometerData, 60000 * 30); //30 min + } + + + 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" + //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 + // if node regular readout does not respond, we repeat request + params.repeatCounter = 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-mngr: 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.byte4 = 96; + params.recipient = 1; + params.register = 8; + params.rw = 1;//write + params.timestamp = timestamp; + 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.byte4 = 96; + params.recipient = 1; + params.register = 8; + params.rw = 1;//write + params.timestamp = timestamp; + 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). + */ + + 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.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.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 + { + + logger.debug("processNodeProfile: Threshold lux level for DUSK/DAWN", node); + + let params = getParams(); + params.type = "set_node_profile"; + params.address = node; + params.register = 96; + params.recipient = 1; + params.rw = 1;//write + params.timestamp = timestamp; + 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(); + params.type = "set_node_profile"; + params.address = node; + params.register = 97; + params.recipient = 1; + params.rw = 1;//write + params.timestamp = timestamp; + 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.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); + + 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); + + console.log("proces profile finished *********************") + } + + + 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; + }); + } + + + 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) { + for (let k in nodesData) { + 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`); + } + } + } + + + function loadRelaysData(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 (value.contactor == 1) processAllNodeProfilesOnLine(value.line); + } + } + + + function reportOnlineNodeStatus(line) { + //Po zapnutí línie broadcastovo aktualizovať predtým čas a o 3 sek neskor - status, brightness + + logger.debug("Cmd-mngr: ----->reportOnlineNodeStatus for line", line); + + const d = new Date(); + + // broadcast actual time + let params = getParams(); + params.address = 0xffffffff;//Broadcast + params.byte1 = d.getHours(); + params.byte2 = d.getMinutes(); + params.recipient = 2;//2 broadcast, address = 0 + params.register = 87;//Actual time + params.rw = 1;//write + params.type = "node-onetime-write"; + params.timestamp = d.getTime() + 30000; + params.info = "run broadcast: Actual time"; + //params.debug = true; + + tasks.push(params); + + let sec = 3; + setTimeout(function() { + //Po zapnutí línie - spraviť hromadný refresh stavu práve zapnutých svietidiel + + let time = Date.now(); + + for (let k in nodesData) { + + //potrebujem nody k danej linii + 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].node_status_before_offline === true || nodesData[k].status === true) { + status = "OK"; + nodesData[k].time_of_last_communication = time; + } + + nodesData[k].readout.status = status; + + updateNodeStatus(k, status === "OK" ? true : false); + if (nodesData[k].hasOwnProperty("node_status_before_offline")) delete nodesData[k].node_status_before_offline; + sendTelemetry({ status: status }, tbname, time); + + //vyreportovanie dimming, current, input power pre liniu pre vsetky nody + //Prud + { + let params = getParams(); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 75;//prud + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = time + 4000; + params.info = 'read current'; + //params.debug = true; + tasks.push(params); + } + + //vykon + { + let params = getParams(); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 76;//výkon + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = time + 4100; + params.info = 'read power'; + //params.debug = true; + + tasks.push(params); + } + //dimming + { + let params = getParams(); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 1;//dimming + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = time + 4200; + params.info = 'read dimming'; + //params.debug = true; + + tasks.push(params); + } + + } + } + + }, sec * 1000); + } + + + function reportOfflineNodeStatus(line) { + + logger.info("Cmd-mngr: ------>reportOffLineNodeStatus for line ", line); + + values = {}; + values["dimming"] = 0;//brightness + values["power"] = 0;//výkon + values["current"] = 0;//prúd + values["status"] = "OFFLINE"; + + const date = Date.now(); + + Object.keys(nodesData).forEach(node => { + + //potrebujem nody k danej linii + if (line == nodesData[node].line || line == undefined) { + + let tbname = nodesData[node].tbname; + let nodeStatus = nodesData[node].status; + + //in case we have reported offline node status, we return (continue with next node) + if (nodeStatus === "OFFLINE") return; + + nodesData[node].node_status_before_offline = nodeStatus; + nodesData[node].status = "OFFLINE"; + nodesData[node].readout = {}; + + sendTelemetry({ ...values }, tbname, date); + } + }); + + } + + + function turnLine(onOrOff, line, info) { + let obj = { + line: line, + command: onOrOff, + info: info + }; + + //to assure, handleDailyReportFunction do not run before rvo_is_on variable changes. So after every line switch we reset the timer + clearInterval(handleDailyReport); + handleDailyReport = setInterval(dailyReportHandler, DAILY_REPORT_HANDLER_TIME); + + //logger.debug("linia", line, obj); + instance.send(SEND_TO.dido_controller, obj); + } + + + 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"; + 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]) { + //CRC_ERROR + message = "NOK"; + error = "CRC_ERROR c1"; + instance.send(SEND_TO.debug, "CRC_ERROR c1"); + } + + 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") { + instance.send(SEND_TO.debug, bytes); + instance.send(SEND_TO.debug, "RESPONSE " + type + " - " + bytes[4]); + + //logger.debug(SEND_TO.debug, "RESPONSE " + type + " - " + bytes[4], bytes); + + error = "type is: " + type; + + message = "NOK"; + } + + return { message, type, error }; + } + + + //BUILD TASKS// + function buildTasks(params) { + + //return; + console.log("buidTAaasks start ****************", params); + monitor.info("buildTasks - params", params); + + let processLine; //defined line + let init = false; + let processLineProfiles = true; + let processBroadcast = true; + let processNodes = true; + + if (params == undefined) { + init = true; + tasks = []; + logger.debug("-->buildTasks clear tasks"); + } + else { + processLineProfiles = params.processLineProfiles; + processBroadcast = false; + processNodes = false; + + processLine = params.line; + } + + let now = new Date(); + + //process line profiles + if (processLineProfiles) { + + let keys = Object.keys(relaysData); + + for (let i = 0; i < keys.length; i++) { + + let line = parseInt(keys[i]); + let profilestr = relaysData[line].profile; + + if (processLine != undefined) { + if (processLine != line) continue; + } + + try { + + /** + * we process line profiles: timepoints, astro clock, lux_sensor, offsets ... + */ + if (profilestr === "") throw ("Profile is not defined"); + let profile = JSON.parse(profilestr); + 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; + + // add name to regular profile timepoint and delete unused end_time key: + time_points.forEach(point => { + point.name = "profileTimepoint" + delete point.end_time; + }); + + //monitor.info("buildTasks: time_points", time_points); + + + /** + * 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 astro clock true, we remove all regular profile points + time_points = []; + + //TODO: when astro clock == true, is offset calculated ??? + //let duskAstroClockOffset = profile.dusk_astro_clock_offset; + //let dawnAstroClockOffset = profile.dawn_astro_clock_offset; + //console.log("line astro clock offsets dusk a dawn: ", duskAstroClockOffset, dawnAstroClockOffset); + // maybe add dusk dawn offset to calculateDuskDawn ?? what dusk dawn will be if dawn_lux_sensor == true?? + //let sunCalcResult = calculateDuskDawn(new Date(), line, duskAstroClockOffset, dawnAstroClockOffset); + + 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 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); + + 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); + + 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(':'); + + let ad = new Date(); + ad.setHours(parseInt(ahours), parseInt(aminutes), 0); + + let bd = new Date(); + bd.setHours(parseInt(bhours), parseInt(bminutes), 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++) { + + let start_time = new Date(); + let [hours, minutes] = time_points[t].start_time.split(':'); + start_time.setHours(parseInt(hours), parseInt(minutes), 0); + + //task is in 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(); + params.type = "relay"; + params.line = parseInt(line); + params.value = time_points[t].value; + params.tbname = relaysData[line].tbname; + params.timestamp = start_time.getTime(); + + // 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; + + //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)) { + 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; + + params.debug = true; + + //turn on/off line + tasks.push(params); + monitor.info("TimePoint params: ", params.info, start_time); + } + + monitor.info("-->time_points final", line, time_points); + + //ensure to turn on/off according to calculated currentValue + let params = getParams(); + params.type = "relay"; + params.line = parseInt(line); + params.tbname = relaysData[line].tbname; + params.value = currentValue; + params.timestamp = i; + params.debug = true; + + //logger.debug(now.toLocaleString("sk-SK")); + 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; + + tasks.push(params); + + } catch (error) { + if (profilestr !== "") { + //errLogger.error(profilestr, error); + console.log(`Cmd_mngr: Unable to process line profile ${line}. Error: `, error); + errorHandler.sendMessageToService(profilestr + "-" + error, 0, "js_error"); + } else { + turnLine("off", line, "No line profile. Switching it off on startup"); + } + } + + } + //logger.debug("tasks:"); + //logger.debug(tasks); + } + + + //NOTE: PROCESS DEFAULT BROADCASTS - Time of dusk, Time of dawn, Actual Time + if (processBroadcast) { + + let d = new Date(); + let time = d.getTime(); + //let sunCalcResult = calculateDuskDawn(); + + { + let params = getParams(); + + params.address = 0xffffffff;//broadcast + params.byte1 = sunCalcResult["dusk_hours"]; + params.byte2 = sunCalcResult["dusk_minutes"]; + params.recipient = 2;//2 broadcast, + params.register = 6;//Time of dusk + params.rw = 1;//write + params.type = "node-regular-write"; + params.timestamp = time + 60000; + params.addMinutesToTimestamp = 60 * 3; //kazde 3 hodiny zisti novy dusk + params.info = "Broadcast-duskTime"; + + tasks.push(params); + } + + { + let params = getParams(); + + params.address = 0xffffffff;//broadcast + params.byte1 = sunCalcResult["dawn_hours"]; + params.byte2 = sunCalcResult["dawn_minutes"]; + params.recipient = 2; //2 broadcast + params.register = 7;//Time of dawn + params.rw = 1;//write + params.type = "node-regular-write"; + params.timestamp = time + 60001; + params.addMinutesToTimestamp = 60 * 3; //kazde 3 hodiny zisti novy dawn + params.info = "Broadcast-dawnTime"; + + tasks.push(params); + } + + { + let params = getParams(); + + params.address = 0xffffffff;//broadcast + params.byte1 = d.getHours(); + params.byte2 = d.getMinutes(); + params.recipient = 2; //2 broadcast + params.register = 87;//Actual time + params.rw = 1;//write + params.type = "node-regular-write"; + params.timestamp = time + 60002; + params.addMinutesToTimestamp = 5; + params.info = "run broadcast: Actual time"; + + tasks.push(params); + } + + } + + //process nodes & tasks - read node's data + if (processNodes) { + + let time = Date.now(); + + for (let k in nodesData) { + let address = parseInt(k); + let tbname = nodesData[k].tbname; + let register = 0; + + for (let i = 0; i < listOfCommands.length; i++) { + + register = listOfCommands[i]; + let addMinutesToTimestamp = priorities[register]; + + let params = getParams(); + + params.address = address; + params.recipient = 1; + params.register = register; + params.type = register == 1 ? "node-dimming-read" : "node-regular-read"; + params.tbname = tbname; + params.timestamp = time + 5000 + i * 500 + addMinutesToTimestamp * 1000; //to make slight time difference + params.addMinutesToTimestamp = addMinutesToTimestamp; + params.info = "Node regular read command"; + + tasks.push(params); + } + + } + } + + + //niektore ulohy sa vygeneruju iba 1x pri starte!!! + if (!init) return; + + + //Master node FW version - modifies SETTINGS.masterNodeIsResponding + { + let params = getParams(); + params.type = "cmd-master"; + params.register = 4; + params.address = 0; + params.timestamp = 0; + params.addMinutesToTimestamp = 5; + params.tbname = SETTINGS.rvoTbName; + params.info = "Master node FW verzia"; + //params.debug = true; + + tasks.push(params); + } + + //kazdu hodinu skontrolovat nastavenie profilov + { + let params = getParams(); + params.type = "process_profiles"; + params.timestamp = Date.now() + 60001; + params.addMinutesToTimestamp = 60;//60 = every hour + params.info = "detekcia nespracovaných profilov linie a nodov"; + //params.debug = true; + + tasks.push(params); + } + + monitor.info("tasks created:", tasks.length); + } + + + /** + * We process line profile, where "astro_clock": true + * example profile: + * + "dawn_lux_sensor": true, + "dusk_lux_sensor": true, + "dawn_lux_sensor_value": 5, + "dusk_lux_sensor_value": 5, + "dawn_astro_clock_offset": 0, + "dusk_astro_clock_offset": 10, + "dawn_lux_sensor_time_window": 30, + "dusk_lux_sensor_time_window": 30, + "dawn_astro_clock_time_window": 60, + "dusk_astro_clock_time_window": 60 + + * if dawn: if currentTimestamp is in timewindow "dawnTime + and - dawn_lux_sensor_time_window" and lux value >= lux_sensor_value, we switch off the line. + * if dusk: we do oposite + * + * dawn: usvit - lux je nad hranicou - vypnem + * dusk: sumrak - lux je pod hranicou - zapnem + */ + 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++) { + + let line = keys[i]; //line is turned off by default + let profilestr = relaysData[line].profile; + const contactor = relaysData[line].contactor; + + try { + + let profile = JSON.parse(profilestr); + if (Object.keys(profile).length === 0) throw ("turnOnOffLinesAccordingToLuxSensor - profile is not defined"); + + 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 (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"); + } + } + } + + //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 (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"); + } + } + } + + } + + } catch (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) { + //MASTER + if (node == 0) return; + + let nodeObj = nodesData[node]; + if (nodeObj == undefined) return; + + let nodeCurrentStatus = nodeObj.status; + const now = Date.now(); + + let data = null; + + if (nodeCurrentStatus === "OFFLINE") { + data = { status: newStatus }; + nodeDbStatusModify(node, data); + return; + } + else 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; + } + + } + + + 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 }; + } + }); + }); + } + + + function processDailyReport() { + + const now = Date.now(); + + for (const [key, value] of Object.entries(dailyReport)) { + + if (["name", "time", "dusk_and_dawn"].includes(key)) continue; + + let poleNumber = nodesData[key]["pole_number"]; + let line = dailyReport[key].line; + let nodeType = nodesData[key]["node_type"]; + let fullNodeName = key // key == nodeNumber + + if (poleNumber && nodeType) { + fullNodeName = SETTINGS.rvo_number + "/" + poleNumber + "_" + line + "L_" + key + "_" + nodeType; + } else { + fullNodeName = key; + } + + if (rvo_is_on) { + + if (value.initialTs) { + if (value.initialTs + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["night_no_data"], fullNodeName); + console.log('report nedostava ziadne data uz hodinu', fullNodeName); + value.initialTs = now; + } + } + if (value.dimmingIsZeroTime) { + if (value.dimmingIsZeroTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["night_dimming=0"], fullNodeName); + console.log("report node dimming je 0 ale ma svietit", fullNodeName); + value.dimmingIsZeroTime = now; + } + } + if (value.powerIsZeroTime) { + if (value.powerIsZeroTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["night_power=0"], fullNodeName); + console.log("report node power je 0 ale ma svietit", fullNodeName); + value.powerIsZeroTime = now; + } + } + + } else { + + let contactorStatus = relaysData[line].contactor; + if (contactorStatus === 1) { + + if (value.initialTs) { + if (value.initialTs + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["day_24/7_no_data"], fullNodeName); + console.log('node je na 24/7 ale nedostava ziadne data uz hodinu', fullNodeName); + value.initialTs = now; + } + } + if (value.dimmingIsOnButShouldBeOffTime) { + if (value.dimmingIsOnButShouldBeOffTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["day_24/7_dimming>0"], fullNodeName); + console.log("report dimming je > 0 ale nema svietit", fullNodeName); + value.dimmingIsOnButShouldBeOffTime = now; + } + } + if (value.powerIsOnButShouldBeOffTime) { + if (value.powerIsOnButShouldBeOffTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["day_24/7_power>0"], fullNodeName); + console.log("report power je > 0 ale nema svietit", fullNodeName); + value.powerIsOnButShouldBeOffTime = now; + } + } + + } + + } + + } + + let report = {}; + report["name"] = SETTINGS.rvo_name; + report["time"] = new Date(); + report["report"] = reportToSend; + + writeToFile(F.path.root("report_data.log"), report, true); + instance.send(SEND_TO.dailyReport, report); + } + + + function dailyReportHandler() { + + if (!SETTINGS.daily_report) return; + + // after dawn we empty reportToSend and start to get data for a new day + const date = new Date(); + const hour = date.getHours(); + const minute = date.getMinutes(); + + console.log("now: ", hour, minute, "suncalc: ", sunCalcResult.dawn_hours, sunCalcResult.dawn_minutes); + + if (hour === sunCalcResult.dawn_hours) { + + //NOTE: ak je este pred usvitom, spracujeme report a posleme na cloud, ak uz je po usvite, resetujeme report plnime data noveho dna + if (minute >= sunCalcResult.dawn_minutes - 2) { + emptyReportToSend(); + emptyDailyReport(); + console.log("Podmienka 1 v dailyReport handler"); + } else { + processDailyReport(); + emptyReportToSend(); + emptyDailyReport(); + console.log("Podmienka 2 v dailyReport handler"); + } + + initialReportStatus = true; + + // ak sa funkcia spusti o hodinu alebo 2 neskor, ako je usvit (moze sa to stat, kedze kazde zapnutie/vypnutie linii odznova spusti casovac. + } else if (hour === sunCalcResult.dawn_hours + 1 || hour === sunCalcResult.dawn_hours + 2) { + if (!initialReportStatus) { + emptyReportToSend(); + emptyDailyReport(); + initialReportStatus = true; + console.log("Podmienka 3 v dailyReport handler"); + } else { + processDailyReport(); + initialReportStatus = true; + console.log("Podmienka 4 v dailyReport handler"); + } + } else { + processDailyReport(); + initialReportStatus = false; + console.log("Podmienka 5 v dailyReport handler"); + } + + console.log("initialReportStatus: ", initialReportStatus); + + } + + function emptyReportToSend() { + emptyJsObject(reportToSend); + reportToSend["contactor"] = { off: [], on: [] }; + reportToSend["night_no_data"] = []; + reportToSend["night_dimming=0"] = []; + reportToSend["night_power=0"] = []; + reportToSend["day_24/7_no_data"] = []; + reportToSend["day_24/7_dimming>0"] = []; + reportToSend["day_24/7_power>0"] = []; + console.log(`resetuje sa reportToSend`); + } + + + //NOTE: ked je initialTs stale rovnaky a zistime ze linie su vypnute (relaysData.line.contactor) - zistim, ci je node na tej linii. Vieme, ze ak je linia vypnuta je to v poriadku lebo nie je na 24/7 linii + //ak je na 24/7 linii, reportujeme, ze neprijima data + function emptyDailyReport() { + const ts = Date.now(); + emptyJsObject(dailyReport); + + //NOTE: do dailyReport dame vsetky nody a pravidelne kontrolujeme ci maju data + //ked nastane sumrak/usvit a svetla maju zacat/prestat svietit, dailyReport spravime nanovo: + for (const [key, value] of Object.entries(nodesData)) { + dailyReport[value.node] = { line: value.line, initialTs: ts }; + } + + console.log("dailyReport: ", dailyReport); + } + + + async function runTasks() { + + clearInterval(interval); + + let currentTimestamp = Date.now(); + + //sort tasks based on timestamp + 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) { + instance.send(SEND_TO.debug, "no tasks created"); + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + if (!rsPort.isOpen) { + instance.send(SEND_TO.debug, "!rsPort.isOpen"); + //await rsPort.open(); + //console.log("Cmd-mngr: !rsPort.isOpen"); + } + + let currentTask = tasks[0]; + + if (currentTask.debug) { + //logger.debug("--->task to process", currentTask); + } + + if (currentTask.timestamp <= currentTimestamp) { + let params = { ...tasks[0] }; + + //allow terminal commands + if (SETTINGS.maintenance_mode && params.type !== "cmd-terminal") { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + let type = params.type; + let tbname = params.tbname; + let node = params.address; + let register = params.register; + let line = null; + let itIsNodeCommand; + + if (nodesData[node] !== undefined) { + line = nodesData[node].line; + itIsNodeCommand = true; + } + + if (params.line !== undefined) line = params.line; + + if (params.addMinutesToTimestamp > 0 || params.timePointName) { + tasks[0].timestamp = currentTimestamp + tasks[0].addMinutesToTimestamp * 60000; + } else { + tasks.shift(); + } + + //kontrola nespracovanych profilov nodov + //TODO: co ked niektore nody neprijimaju profily? kazdu hodinu zahltuju "tasks" array + if (type == "process_profiles") { + //na vsetky zapnutych liniach sa spracuju nespracovane profily nodov + loadRelaysData(); + interval = setInterval(runTasks, SHORT_INTERVAL); + return; + } + + //relay + if (type == "relay") { + + const timePointName = params.timePointName; + const value = params.value; + + let date = new Date(); + date.setDate(date.getDate() + 1);//next day + + let sunCalcResult; + if (timePointName) sunCalcResult = calculateDuskDawn(date, params.line); + + + if (timePointName == "dawn") { + tasks[0].timestamp = sunCalcResult.dawn_time; + } + else if (timePointName == "dusk") { + tasks[0].timestamp = sunCalcResult.dusk_time; + } + else if (timePointName == "luxOn") { + tasks[0].timestamp = sunCalcResult.dusk_time + params.dusk_lux_sensor_time_window * 60000; + } + else if (timePointName == "luxOff") { + tasks[0].timestamp = sunCalcResult.dawn_time + params.dawn_lux_sensor_time_window * 60000; + } + else if (timePointName == "profileTimepoint") { + tasks[0].timestamp = currentTimestamp + tasks[0].addMinutesToTimestamp * 60000; + } + + let info = "aplikovany bod profilu"; + let onOrOff = ""; + value == 1 ? onOrOff = "on" : onOrOff = "off"; + + turnLine(onOrOff, params.line, info); + + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + if (!SETTINGS.masterNodeIsResponding) { + //ak neodpoveda, nebudeme vykonavat ziadne commands, okrem cmd-terminal cmd-master + errorHandler.sendMessageToService("Master node is not responding"); + + let stop = true; + + if (type === "cmd-terminal" || type === "cmd-master") stop = false; + if (stop) { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + } + + let contactorStatus = 1; + if (relaysData[line] != undefined) contactorStatus = relaysData[line].contactor; + + if (line === 0 || contactorStatus === 0 || FLOW.deviceStatus.state_of_breaker[line] === "Off") { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + // TODO: -> status offline for rvo if rotary_switch_state is OFF, this is source of errors + // check if rotary_switch_state == "Off" + // state_of_braker: disconnected = true? + + if (!rsPort.isOpen) { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + //RE-CALCULATE VALUES + //set actual time for broadcast + if (register == 87 && params.recipient === 2) { + var d = new Date(); + params.byte1 = d.getHours();//h + params.byte2 = d.getMinutes();//m + } + + //SET DUSK/DAWN FOR BROADCAST + //Time of dusk + if (register == 6 && params.recipient === 2) { + + if (type != "cmd-terminal") { + params.byte1 = sunCalcResult["dusk_hours"];//h + params.byte2 = sunCalcResult["dusk_minutes"];//m + } + } + + //Time of dawn + if (register == 7 && params.recipient === 2) { + if (type != "cmd-terminal") { + params.byte1 = sunCalcResult["dawn_hours"];//h + params.byte2 = sunCalcResult["dawn_minutes"];//m + } + } + //----------------------- + + instance.send(SEND_TO.debug, "address: " + node + " register:" + register + "type: " + type); + + var startTime, endTime; + startTime = new Date(); + + let saveToTb = true; + if (!tbname) saveToTb = false; + + let resp = com_generic(node, params.recipient, params.rw, register, params.name, params.byte1, params.byte2, params.byte3, params.byte4); + let readBytes = 11; + let timeout = 4000; + + + // await keyword is important, otherwise incorrect data is returned! + await writeData(rsPort, resp, readBytes, timeout).then(function(data) { + + //sometimes happens, that status of node changes to OK, NOK even if line was turned off and should be status OFFLINE. To prevent this, we return if line contactor is 0: + if (itIsNodeCommand && line && relaysData[line].contactor !== 1) return; + + 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); + + //ak sa odpoved zacina 0 - je to v poriadku, inak je NOK + let message = result.message; // OK, NOK + let message_type = result.type; + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + console.log("detected response:", result); + logger.debug("Cmd-mngr: writeData done " + message_type + " duration: " + timeDiff + " type: " + params.debug, params, result); + } + } + + let values = {}; + + //CMD FINISHED + if (message == "OK") { + + updateNodeStatus(node, true); + + //write + if (type == "set_node_profile") { + let result = cmdCounterResolve(node); + if (result == 0) { + dbNodes.modify({ processed: true }).where("node", node).make(function(builder) { + builder.callback(function(err, response) { + + sendNotification("Cmd-mngr: process cmd", SETTINGS.rvoTbName, "dimming_profile_was_successfully_received_by_node", { node: node }, "", SEND_TO.tb, instance); + + logger.debug("--> profil úspešne odoslaný na node č. " + node); + nodesData[node].processed = true; + nodeProfileSendFail.delete(node); + }); + }); + } + } + + //parse read response + if (params.rw == 0) { + values = processResponse(register, dataBytes); //read + } + + if (itIsNodeCommand) { + values.comm_status = "OK"; + values.status = "OK"; + nodesData[node].readout = { ...nodesData[node].readout, ...values }; + + + if (SETTINGS.daily_report) { + //TODO: co ak nedostavame odpovede z nodu ? Musime vyreportovat!! + //v dailyReport teda musi byt kompletny zoznam nodov a neustale kontrolovat, ci maju data, ak nie report node - neodpoveda + if (register === 1) { + + let now = Date.now(); + + if (rvo_is_on === true) { + + if ("dimmingIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].dimmingIsOnButShouldBeOffTime; + + if (values.dimming > 0) { + if ("dimmingIsZeroTime" in dailyReport[node]) delete dailyReport[node].dimmingIsZeroTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if (!("dimmingIsZeroTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], dimmingIsZeroTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } else { + + if ("dimmingIsZeroTime" in dailyReport[node]) delete dailyReport[node].dimmingIsZeroTime; + + if (values.dimming > 0) { + if (!("dimmingIsOnButShouldBeOffTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], dimmingIsOnButShouldBeOffTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if ("dimmingIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].dimmingIsOnButShouldBeOffTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } + } + + if (register === 76) { + + let now = Date.now(); + + if (rvo_is_on === true) { + + if ("powerIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].powerIsOnButShouldBeOffTime; + + if (values.power > 1) { + if ("powerIsZeroTime" in dailyReport[node]) delete dailyReport[node].powerIsZeroTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if (!("powerIsZeroTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], powerIsZeroTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } else { + + if ("powerIsZeroTime" in dailyReport[node]) delete dailyReport[node].powerIsZeroTime; + + if (values.power > 1) { + if (!("powerIsOnButShouldBeOffTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], powerIsOnButShouldBeOffTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if ("powerIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].powerIsOnButShouldBeOffTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } + } + } + + } + + //master node + if (node == 0) { + sendNotification("Cmd-mngr: 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; + } + + if (params.debug) { + //logger.debug("saveToTb", saveToTb, tbname, values); + } + + if (saveToTb && type != "node-regular-read") { + sendTelemetry(values, tbname); + } + else { + if (type == "cmd-terminal") { + terminalCommandResponse(params, "SUCCESS", data); + } + } + + } + else { + terminalCommandResponse(params, "ERROR", data); + handleNokResponseOnRsPort("handleNOK else block", params, itIsNodeCommand, saveToTb); + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + //logger.debug("writeData err: ", error, result, params); + logger.debug("writeData err: ", tbname, node, register, values); + } + } + + //logger.debug(error, result, params); + } + }).catch(function(reason) { + + //console.log("writeData catch exception", reason); + instance.send(SEND_TO.debug, reason); + + terminalCommandResponse(params, "FAILURE", null, reason); + handleNokResponseOnRsPort("handleNOK catch block", params, itIsNodeCommand, saveToTb); + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + logger.debug("-->WRITE FAILED: " + reason, params.debug, params); + } + } + + }); + + } + 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); + } + + + // if node does not respond to request, we repeat request 3 times: + function repeatCommand(params) { + params.repeatCounter++; + if (params.repeatCounter < 4) { + params.timestamp = 0; + params.addMinutesToTimestamp = 0; + tasks.push(params); + } + } + + function handleNokResponseOnRsPort(message, params, itIsNodeCommand, saveToTb) { + + let node = params.address; + let register = params.register; + let type = params.type; + let tbName = params.tbname; + if (!tbName) return; + + let values = {}; + + let updateStatus = updateNodeStatus(node, false); + + if (itIsNodeCommand) { + values.comm_status = "NOK"; + nodesData[node].readout.comm_status = "NOK"; + repeatCommand(params); + } + + if (updateStatus) { + values.status = "NOK"; + nodesData[node].readout.status = "NOK"; + } + + if (type === "node-regular-read") return; + + //master node + if (node == 0) { + sendNotification("Cmd-mngr: 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; + + if (register == 4) values["master_node_version"] = "NOK"; + } + + if (type == "set_node_profile") { + delete cmdCounter[node]; + logger.debug("profil nebol úspešne odoslaný na node č. ", params); + + if (!nodeProfileSendFail.has(node)) { + sendNotification("Cmd-mngr: process cmd", tbName, "configuration_of_dimming_profile_to_node_failed", { node: node }, "", SEND_TO.tb, instance); + nodeProfileSendFail.add(node); + } + } + + // console.log("------",node, register, type, itIsNodeCommand, updateStatus, saveToTb, values); + if (saveToTb) { + sendTelemetry(values, tbName); + } + + } + + + function sendNodesData() { + Object.keys(nodesData).forEach(node => { + if (nodesData[node]["status"] !== "OFFLINE") { + sendTelemetry(nodesData[node].readout, nodesData[node].tbname); + nodesData[node].readout = {}; + } + }) + } + + + /** + * 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; + } + + 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); + + //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 === "OFFLINE") { + nodeObj.node_status_before_offline === true ? number_of_ok_luminaires++ : number_of_nok_luminaires++; + } + else if (nodeObj.status == true) 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 - ts % 60000 //round to full minute + }; + + sendTelemetry(values, SETTINGS.rvoTbName, ts); + } + + + function setSunCalcResult() { + //if next day, we get new dusk and dawn. To make sure, in local timezone 2:00 means 00:00 in utc (it means next day) + if (new Date().getHours() === 2) { + sunCalcResult = calculateDuskDawn(); + console.log("Novy suncalc: ", sunCalcResult); + } + } + + + function setRvoPeriod() { + + if (!SETTINGS.daily_report) return; + + const ts = Date.now(); + + previous_rvo_is_on_value = rvo_is_on; + + if (ts < sunCalcResult.dawn_time - 1_800_000) { // nodes should be on (00:00 -> 06:00 ( - pol hodina, lebo rvo vypina skor) + rvo_is_on = true; + } else if (sunCalcResult.dawn_time - 1_800_000 < ts && ts < sunCalcResult.dusk_time + 1_800_000) { // nodes should be off 06:00 -> 21:00 + rvo_is_on = false; + } else if (sunCalcResult.dusk_time + 1_800_000 < ts) { // nodes should be on 21:00 -> 00:00 + rvo_is_on = true; + } + + if (previous_rvo_is_on_value !== rvo_is_on) { + emptyDailyReport(); + console.log("rvo_is: ", rvo_is_on, previous_rvo_is_on_value); + } + } + + + function handleRsPort() { + + if (rsPort) { + rsPort.removeAllListeners(); + rsPort = null; + } + + //! 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-mngr: rsPort opened success"); + + 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); + + }).catch(function(reason) { + instance.send(SEND_TO.debug, "Cmd-mngr: RPC runSyncExec - promise rejected:" + reason); + }); + }); + + rsPort.on('error', function(err) { + errorHandler.sendMessageToService([exports.title, "unable to open port", SETTINGS.serial_port, err.message], 0); + monitor.info("Cmd-mngr: Error on rsPort", err.message); + }); + + rsPort.on("close", () => { + monitor.info("Cmd-mngr: rsPort closed, reconnecting..."); + setTimeout(handleRsPort, 1000); + }); + + rsPort.open(); + } + + + instance.on("close", () => { + clearInterval(interval); + clearInterval(customTasksInterval); + clearInterval(setCorrectTime); + clearInterval(sendNodeReadout); + clearInterval(accelerometerInterval); + rsPort.close(); + }); + + instance.on("0", _ => { + main(); + }) + + + instance.on("2", _ => { + console.log("dailyReport, reportToSend, rvo_is_on", dailyReport, reportToSend, rvo_is_on, previous_rvo_is_on_value); + }) + + instance.on("1", 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(); + return; + } + else if (flowdata.data == "close") { + rsPort.close(); + return; + } + else if (flowdata.data == "clean") { + tasks = []; + return; + } + else if (flowdata.data == "buildtasks") { + //build & run + return; + } + else if (flowdata.data == "run") { + //durations = []; + + if (tasks.length == 0) { + + buildTasks(); + + if (rsPort.isOpen) { + interval = setInterval(runTasks, 100); + } + else { + instance.send(SEND_TO.debug, "port is not opened!!!"); + } + } + } + else { + //terminal data - object + //logger.debug("flowdata", flowdata.data); + + if (typeof flowdata.data === 'object') { + //logger.debug("dido", flowdata.data); + if (flowdata.data.hasOwnProperty("sender")) { + //data from dido_controller + if (flowdata.data.sender == "dido_controller") { + + if (flowdata.data.hasOwnProperty("cmd")) { + let cmd = flowdata.data.cmd; + + if (cmd == "buildTasks") { + clearInterval(interval); + + logger.debug("-->Cmd-mngr: BUILD TASKS"); + buildTasks(); + + //logger.debug("tasks:"); + //logger.debug(tasks); + + logger.debug("-->Cmd-mngr: RUN TASKS"); + interval = setInterval(runTasks, 5000); + } + else if (cmd == "reload_relays") { + loadRelaysData(flowdata.data.line); + + if (flowdata.data.dataChanged) { + if (!flowdata.data.value) { + reportOfflineNodeStatus(flowdata.data.line); + } + else { + reportOnlineNodeStatus(flowdata.data.line); + } + } + + } + else if (cmd == "rotary_switch_state") { + let value = flowdata.data.value; + + //state was changed + if (rotary_switch_state != value) { + if (value == "Off") { + //vyreportovat vsetky svietdla + reportOfflineNodeStatus(); + } + + rotary_switch_state = value; + } + } + 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) { + + // we send lux_sensor value to all nodes: + let params = getParams(PRIORITY_TYPES.node_broadcast); + + params.recipient = 2;//2 broadcast, address = 0 + params.address = 0xffffffff;//Broadcast + + let ba = longToByteArray(lux_sensor); + + params.byte3 = ba[1];//msb + params.byte4 = ba[0]; + params.timestamp = PRIORITY_TYPES.node_broadcast; + params.info = "run broadcast: Actual Lux level from cabinet"; + params.register = 95;//Actual Lux level from cabinet + params.rw = 1;//write + + tasks.push(params); + + //process profiles + turnOnOffLinesAccordingToLuxSensor(lux_sensor); + } + } + else if (cmd == "state_of_breaker") { + //istic linie + + breakerCounter--; + + let value = flowdata.data.value; + let line = parseInt(flowdata.data.line); + + let dataChanged = false; + if (state_of_breaker[line] != value) dataChanged = true; + + state_of_breaker[line] = value; + + let status = "OK"; + if (value == "Off") status = "NOK"; + + if (dataChanged) { + + if (relaysData.hasOwnProperty(line)) { + let tbname = relaysData[line].tbname; + + if (value == "Off") { + sendNotification("Cmd-mngr: onData", tbname, "circuit_breaker_was_turned_off_line", { line: line }, "", SEND_TO.tb, instance, "circuit_breaker"); + if (breakerCounter < 0) reportToSend["contactor"]["off"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + else { + sendNotification("Cmd-mngr: onData", tbname, "circuit_breaker_was_turned_on_line", { line: line }, "", SEND_TO.tb, instance, "circuit_breaker"); + if (breakerCounter < 0) reportToSend["contactor"]["on"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + + //report status liniu + sendTelemetry({ status: status }, tbname) + + //current value + if (value == "Off") reportOfflineNodeStatus(line); //vyreportovat vsetky svietidla na linii + } + + } + } + else { + logger.debug("undefined cmd", cmd); + } + } + } + + return; + } + + //data from worksys + if (flowdata.data.hasOwnProperty("topic")) { + + let data = getNested(flowdata.data, "content", "data"); + + //if we get temperature in senica from senica-prod01 + let temperature = getNested(flowdata.data, "content", "senica_temperature"); + + if (temperature !== undefined) { + temperatureInSenica = temperature; + return; + } + + if (data === undefined) { + console.log("Invalid rpc command came from platform"); + return; + } + + let command = data.params.command; + let method = data.method; + let profile = data.params.payload; + if (profile == undefined) profile = ""; + let entity = data.params.entities[0]; + let entity_type = entity.entity_type; + let tbname = entity.tb_name; + + instance.send(SEND_TO.debug, flowdata.data); + 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") { + + //let command = data.params.command; + let value = data.params.payload.value; + + if (command == "dimming") { + + let nodeWasFound = false; + let keys = Object.keys(nodesData); + + //logger.debug("-----", keys); + + 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); + + value = parseInt(value); + if (value > 0) value = value + 128; + + params.type = "node-onetime-write"; + params.tbname = tbname; + params.address = node; + params.register = 1; + params.recipient = 1; + params.byte4 = value; + params.rw = 1; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'set dimming from platform'; + //params.debug = true; + + //debug(params); + logger.debug("dimming", params); + + tasks.push(params); + + 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); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 1; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read dimming (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + //pridame aj vyreportovanie - vykon + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 76; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read Input Power (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + //pridame aj vyreportovanie - prud svietidla + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 75; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read Input Current (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + //pridame aj vyreportovanie - power faktor - ucinnik + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 77; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read power factor (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + }, 4000); + + nodeWasFound = true; + break; + } + } + + if (!nodeWasFound) { + logger.debug("set dimming from platform", "unable to find tbname", tbname); + } + } + else { + instance.send(SEND_TO.debug, "undefined command " + command); + logger.debug("undefined command", command); + } + + return; + } + 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++) { + let node = keys[i]; + if (tbname == nodesData[node].tbname) { + + 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"); + + //profil úspešne prijatý pre node č. xx + sendNotification("Cmd-mngr", tbname, "dimming_profile_was_processed_for_node", { node: node }, profile, SEND_TO.tb, instance); + + nodesData[node].processed = false; + nodesData[node].profile = profile; + + processNodeProfile(node); + }); + }); + } + } + } + else { + + instance.send(SEND_TO.debug, "unknown method " + method); + logger.debug("unknown method", method); + + return; + } + } + + //nastav profil linie z platformy + 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") { + + 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++) { + let line = keys[i]; + if (tbname == relaysData[line].tbname) { + //zmazeme tasky + 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) { + + //update profile + logger.debug("worksys - update relay profile done:", profile); + instance.send(SEND_TO.debug, "worksys - update relay profile done"); + + relaysData[line].profile = profile; + + loadRelaysData(line) + logger.debug("loadRelaysData DONE for line", line); + + buildTasks({ processLineProfiles: true, line: line }); + + sendNotification("Cmd-mngr: set profile from worksys", tbname, "switching_profile_was_processed_for_line", { line: line }, profile, SEND_TO.tb, instance); + }); + }); + break; + } + } + } + else if (method == "set_command") { + let value = data.params.payload.value; + + 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; + + 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"); + if (line != 0) reportToSend["contactor"]["off"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + else { + turnLine("on", line, "command received from platform"); + if (line != 0) reportToSend["contactor"]["on"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + } + } + else { + instance.send(SEND_TO.debug, "undefined method " + method); + logger.debug("undefined method", method); + } + + return; + } + else { + instance.send(SEND_TO.debug, "UNKNOW entity_type " + entity_type); + logger.debug("UNKNOW entity_type", entity_type); + } + return; + } + + //terminal + if (!rsPort.isOpen) await rsPort.open(); + + let params = flowdata.data.body; + if (params == undefined) { + //logger.debug("Cmd-mngr: flowdata.data.body is undefined"); + return; + } + + params.priority = PRIORITY_TYPES.terminal; + params.type = "cmd-terminal"; + params.tbname = ""; + params.timestamp = PRIORITY_TYPES.terminal; + params.addMinutesToTimestamp = 0;// do not repeat task!!! + params.debug = true; + + let timestamp = Date.now(); + params.refFlowdataKey = timestamp; + //params.refFlowdata = flowdata; + //refFlowdata = flowdata; + + //console.log("flowdata", flowdata); + + cleanUpRefFlowdataObj(); + + refFlowdataObj[timestamp] = flowdata; + + //fix + //params.address = params.adress; + logger.debug("received from terminal", params); + logger.debug("date/time:", new Date()); + logger.debug("tasks length:", tasks.length); + + //tasks = []; + + //add to tasks + tasks.push(params); + + } + } + }) + + + //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) + } + + + /** + * 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; + + RESTBuilder.make(function(builder) { + + if (!builder) return; + + builder.method('GET'); + builder.url('http://192.168.252.2:8004/gettime?projects_id=1'); + + builder.callback(function(err, response, output) { + + 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); + } + + }); + } + + } 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); + + } else { + //console.log("Read-only", stdout); + + 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]: [ + { + "ts": date, + "values": values + } + ] + } + + tbHandler.sendToTb(dataToTb, instance); + } + + + function calculateDuskDawn(date, line, duskOffset = 0, dawnOffset = 0) { + + if (date === undefined) date = new Date(); + + 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); + } + + //if(profile.dawn_lux_sensor == false) + { + if (profile.hasOwnProperty("dawn_astro_clock_offset")) dawn_astro_clock_offset = parseInt(profile.dawn_astro_clock_offset); + } + + } + + } catch (error) { + if (profilestr != "") { + logger.debug(profilestr); + logger.debug(error); + } + } + + 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; + } + + //Dimming, CCT + else if (register == 1) { + let brightness = 0; + let dimming = byte0; + if (dimming > 128) { + //dimming = -128; + brightness = dimming - 128; + } + + //cct + //Ak Byte3 == 1: CCT = (Byte2*256)+Byte1 + let cct; + if (byte3 == 1) cct = byte2 * 256 + byte1; + else cct = bytesToInt(bytes.slice(0, 3)); + + //cct podla auditu + + values["dimming"] = brightness; + return values; + } + + // + else if (register == 4) { + values["master_node_version"] = bytes[1] + "." + bytes[2]; + //logger.debug("FW Version", register, bytes); + } + + //Napätie + else if (register == 74) { + let voltage = (bytesToInt(bytes) * 0.1).toFixed(1); + values["voltage"] = Number(voltage); + } + + //Prúd + else if (register == 75) { + let current = bytesToInt(bytes); + values["current"] = current; + } + + //výkon + else if (register == 76) { + let power = (bytesToInt(bytes) * 0.1).toFixed(2); + values["power"] = Number(power); + } + + //účinník + else if (register == 77) { + let power_factor = Math.cos(bytesToInt(bytes) * 0.1 * (Math.PI / 180)).toFixed(2); + values["power_factor"] = Number(power_factor); + } + + //frekvencia + else if (register == 78) { + let frequency = (bytesToInt(bytes) * 0.1).toFixed(2); + values["frequency"] = Number(frequency); + } + + //energia + else if (register == 79) { + let energy = bytesToInt(bytes); + values["energy"] = energy / 1000; //energia v kWh -> delit 1000 + } + + //doba života + else if (register == 80) { + let lifetime = (bytesToInt(bytes) / 60).toFixed(2); + values["lifetime"] = Number(lifetime); + } + + //nastavenie profilu + else if (register == 8) { + let time_schedule_settings = bytesToInt(bytes); + values["time_schedule_settings"] = time_schedule_settings; + } + + //naklon - nateraz sa z nodu nevycitava! kvoli problemom s accelerometrom a vracanymi hodnotami, posielame temp a x y z vo funkcii accelerometerData() + else if (register == 84) { + values["temperature"] = byte3 >= 128 ? (byte3 - 128) * (-1) : byte3; + values["inclination_x"] = byte2 >= 128 ? (byte2 - 128) * (-1) : byte2; + values["inclination_y"] = byte1 >= 128 ? (byte1 - 128) * (-1) : byte1; + values["inclination_z"] = byte0 >= 128 ? (byte0 - 128) * (-1) : byte0; + } + + //FW verzia nodu + else if (register == 89) { + //formát: "Byte3: Byte2.Byte1 (Byte0)" + values["fw_version"] = byte3 + ":" + byte2 + "." + byte1 + "(" + byte0 + ")"; + } + + else if (register == 87 || register == 6 || register == 7) { + var d = new Date(); + d.setHours(byte3, byte2, 0, 0); + let timestamp = d.getTime(); + + //aktuálny čas + if (register == 87) values["actual_time"] = timestamp; + //čas súmraku + else if (register == 6) values["dusk_time"] = timestamp; + //čas úsvitu + else if (register == 7) values["dawn_time"] = timestamp; + } + + 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; + + } + + + function getObjectByTbValue(object, tbname) { + return object[Object.keys(object).find(key => object[key].tbname === tbname)]; + } + + + function isObject(item) { + return (typeof item === "object" && !Array.isArray(item) && item !== null); + } + + + // we fake data, that should be received from accelerometer, as they are a bit unreliable. (temperature, x,y,z) + function accelerometerData() { + + if (temperatureInSenica === null) return; + + //clone nodesData and relaysData objects + let nodesData_clone = JSON.parse(JSON.stringify(nodesData)); + let relaysData_clone = JSON.parse(JSON.stringify(relaysData)); + + for (const key in relaysData_clone) { + + const lineData = relaysData_clone[key]; + const lineNumber = lineData.line; + const contactor = lineData.contactor; + + if (lineNumber === 0) continue; + + if (contactor === 1) { + + let date = Date.now(); + + Object.keys(nodesData_clone).forEach((node, index) => { + + setTimeout(function() { + + if (nodesData_clone[node].line === lineNumber) { + + // NOTE: if status of luminaire is NOK or OFFLINE, we do not send data; + let status = nodesData_clone[node].status; + if (status === "OFFLINE" || !status) return; + + let x = null; + if (naklony.hasOwnProperty(node)) x = naklony[node].naklon; + if (x === null) x = 0; + + sendTelemetry({ temperature: Math.round(temperatureInSenica + 10 + Math.floor(Math.random() * 3)), inclination_x: x, inclination_y: 0, inclination_z: 0 }, nodesData_clone[node].tbname, date); + } + + }, (index + 1) * 500); + }) + + } + } + } + + +} // end of instance.export + diff --git a/RVO34/flow/code.js b/RVO34/flow/code.js new file mode 100755 index 0000000..63b31bf --- /dev/null +++ b/RVO34/flow/code.js @@ -0,0 +1,90 @@ +exports.id = 'code'; +exports.title = 'Code'; +exports.group = 'Common'; +exports.color = '#656D78'; +exports.input = true; +exports.output = 1; +exports.author = 'Peter Širka'; +exports.icon = 'code'; +exports.version = '1.2.0'; +exports.options = { outputs: 1, code: 'send(0, value);', keepmessage: true }; + +exports.html = `
+
+
+
@(Number of outputs)
+
@(Minimum is 1)
+
+
+
@(Code)
+
@(Keep message instance)
+
+`; + +exports.readme = `# Code + +This component executes custom JavaScript code as it is and it doesn't contain any secure scope. + +\`\`\`javascript +// value {Object} contains received data +// send(outputIndex, newValue) sends a new value +// error(value) sends an error +// instance {Object} a current component instance +// flowdata {Object} a current flowdata +// repository {Object} a current repository of flowdata +// Example: + +// send() can be execute multiple times +send(0, value); +\`\`\``; + +exports.install = function(instance) { + + var fn; + + instance.on('data', function(response) { + if (fn) { + try { + fn(response.data, instance, response, instance.options, response.repository, require); + } catch (e) { + response.data = e; + instance.throw(response); + } + } + }); + + instance.reconfigure = function() { + try { + if (instance.options.code) { + instance.status(''); + var code = 'var send = function(index, value) { if (options.keepmessage) { flowdata.data = value; instance.send2(index, flowdata); } else instance.send2(index, value);}; var error = function(err) { instance.throw(err); }; ' + instance.options.code; + fn = new Function('value', 'instance', 'flowdata', 'options', 'repository', 'require', code); + } else { + instance.status('Not configured', 'red'); + fn = null; + } + } catch (e) { + fn = null; + instance.error('Code: ' + e.message); + } + }; + + instance.on('options', instance.reconfigure); + instance.reconfigure(); +}; \ No newline at end of file diff --git a/RVO34/flow/comment.js b/RVO34/flow/comment.js new file mode 100755 index 0000000..1e0cd13 --- /dev/null +++ b/RVO34/flow/comment.js @@ -0,0 +1,11 @@ +exports.id = 'comment'; +exports.title = 'Comment'; +exports.group = 'Common'; +exports.color = '#704cff'; +exports.author = 'Martin Smola'; +exports.icon = 'comment'; +exports.traffic = false; +exports.version = '1.0.0'; +exports.readme = '# Comment'; + +exports.install = function() {}; diff --git a/RVO34/flow/count.js b/RVO34/flow/count.js new file mode 100755 index 0000000..fa92ee9 --- /dev/null +++ b/RVO34/flow/count.js @@ -0,0 +1,60 @@ +exports.id = 'count'; +exports.title = 'Count'; +exports.version = '1.0.1'; +exports.author = 'John Graves'; +exports.color = '#656D78'; +exports.icon = 'plus-square'; +exports.input = 2; +exports.output = 1; +exports.options = { increment: 1, initialvalue: 1 }; +exports.readme = `# Counter + +Counter Number of times called.`; + +exports.html = `
+
@(Initial Value)
+
@(Increment)
+

Example Video

+
`; + +exports.readme = `# Count + +This component counts the number of messages received. + +__Response:__ + +Integer value based on the initial value and increment settings. + +__Arguments:__ +- Initial Value: What number should be output on the receipt of the first message. +- Increment: What should the increment be for each following message received.`; + +exports.install = function(instance) { + + var count = 0; + var initialCall = true; + + instance.on('data', function(flowdata) { + var index = flowdata.index; + if (index) { + instance.debug('Reset Count.'); + count = instance.options.initialvalue; + initialCall = true; + } else { + // If this is the first time, set the value to 'initial value' + if(initialCall) { + initialCall = false; + count = instance.options.initialvalue; + } else + count = count+instance.options.increment; + instance.status('Count:' + count); + instance.send2(count); + } + }); + + instance.on('options', function() { + count = instance.options.initialvalue; + initialCall = true; + }); + +}; diff --git a/RVO34/flow/db_connector.js b/RVO34/flow/db_connector.js new file mode 100755 index 0000000..65ee94b --- /dev/null +++ b/RVO34/flow/db_connector.js @@ -0,0 +1,286 @@ +exports.id = 'db_connector'; +exports.title = 'DbConnector'; +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.html = `
+
+
+
DbConnector
+
+
+
`; + +exports.readme = `# read/write data to tables`; + +const instanceSendTo = { + debug: 0, + http_response: 1, +} + +const { promisifyBuilder, makeMapFromDbResult } = require('./helper/db_helper.js'); + +function extractWhereParams(params) +{ + let name = params[0]; + let operator = '='; + let value = params[1]; + + if(params.length == 3) + { + operator = params[1]; + value = params[2]; + } + + return {name: name, operator: operator, value: value}; +} + +exports.install = function(instance) { + + let refFlowdata = null;//holds reference to httprequest flowdata + + instance.on("close", () => { + + }) + + + instance.on("data", async function(flowdata) { + + let params = flowdata.data.body; + console.log("DbConnector", params); + + refFlowdata = flowdata; + + if(refFlowdata != undefined) + { + //make http response + let responseObj = {}; + responseObj["type"] = "SUCESS"; + + try{ + + let table = params.table; + let action = params.action; + + + if(params.data != undefined) + { + let className = params.data.className; + + if(className == "SqlQueryBuilder") + { + let type = params.data.type; + + console.log("SqlQueryBuilder---->", params.data); + + if(type == "SELECT") + { + let table = params.data.queryData.tables[0].table; + + const db = TABLE(table); + var builder = db.find(); + + let result = await promisifyBuilder(builder); + + let response = {}; + response["result"] = result; + response["success"] = true; + + responseObj["data"] = response; + + //console.log(responseObj); + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + } + + return; + } + } + + + console.log("db_connector---->", table, action); + + //actions: read, replace, insert, delete, update... + + if(action == "read") + { + const db = TABLE(params.table); + + //where builder.where('age', '<', 15); + //builder.where('id', 3403); + + var builder = db.find(); + + //https://docs.totaljs.com/latest/en.html#api~DatabaseBuilder~builder.where + if(params.hasOwnProperty("where")) + { + //optionalCan contain "=", "<=", "<", ">=", ">". + //Default value: '=' + + //1.["production_line", 1] + //2. ["or", ["production_line", 1], ["production_line", 2], "end"] + + if (Array.isArray(params.where)) { + + let multipleConditions = false; + + if(params.where[0] == "or") multipleConditions = true; + if (Array.isArray(params.where[0])) multipleConditions = true; + + if(multipleConditions) + { + + for(var i = 0; i < params.where.length; i++) + { + const item = params.where[i]; + + if(item === "or") builder.or(); + + if (Array.isArray(item)) + { + const { name, operator, value } = extractWhereParams(item); + builder.where(name, operator, value); + } + + if(item === "end") builder.end(); + + } + + } + else + { + const { name, operator, value } = extractWhereParams(params.where); + builder.where(name, operator, value); + } + + } + + /* + if(params.where.length >=2 ) + { + let name = params.where[0]; + let operator = '='; + let value = params.where[1]; + + if(params.where.length == 3) + { + operator = params.where[1]; + value = params.where[2]; + } + + builder.where(name, operator, value); + } + */ + } + + if(params.hasOwnProperty("between")) + { + builder.between(params.between[0], params.between[1], params.between[2]); + } + + let response = await promisifyBuilder(builder); + responseObj["data"] = response; + + //console.log(responseObj); + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + + return; + } + + if(action == "delete") + { + + } + + + if(action == "update") + { + //! data receiving from terminal (params) + // { + // hostname: 'localhost', + // table: 'settings', + // action: 'update', + // body: { + // rvo_name: 'terrrr', + // lang: 'en', + // temperature_adress: '28.427B45920702', + // latitude: 48.70826502, + // longitude: 17.28455203, + // mqtt_host: '192.168.252.4', + // mqtt_clientid: 'showroom_test_panel_led', + // mqtt_username: 'xmRd6RJxW53WZe4vMFLU', + // mqtt_port: 1883, + // maintanace_mode: false + // } + // } + const tableToModify = TABLE(params.table); + const newValues = params.body; + + tableToModify.modify(newValues).make(function(builder) { + + builder.callback(function(err, response) { + + if(!err) + { + responseObj["data"] = response; + responseObj["tableUpdated"] = true; + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + } + }); + }); + + } + + if(action == "replace") + { + //truncate table + const db = TABLE(params.table); + var builder = db.remove(); + db.clean(); + + //insert data + let data = params.data; + + for(let i = 0; i < data.length; i++) + { + //console.log(data[i]); + db.insert(data[i]); + } + + console.log("insert done"); + + let responseObj = {}; + responseObj["type"] = "SUCESS"; + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + + + } + + + + } catch (error) { + //console.log(error); + responseObj["type"] = "ERROR"; + responseObj["message"] = error; + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + } + } + }) +} + + diff --git a/RVO34/flow/db_init.js b/RVO34/flow/db_init.js new file mode 100755 index 0000000..b399878 --- /dev/null +++ b/RVO34/flow/db_init.js @@ -0,0 +1,113 @@ +exports.id = 'db_init'; +exports.title = 'DB Initialization'; +exports.group = 'Worksys'; +exports.color = '#888600'; +exports.version = '1.0.2'; +exports.icon = 'sign-out'; +exports.output = 2; + +exports.readme = ` + # DB initialization +`; + +const { promisifyBuilder, makeMapFromDbResult } = require('./helper/db_helper.js'); +const { initNotification } = require('./helper/notification_reporter'); +const errorHandler = require('./helper/ErrorToServiceHandler'); +const total_energy = require('../databases/total_energy'); + +const SEND_TO = { + db_init: 0, + infoSender: 1 +}; + + +exports.install = async function(instance) { + const dbNodes = TABLE("nodes"); + const dbRelays = TABLE("relays"); + const dbSettings = TABLE("settings"); + 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 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.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"]; + Object.keys(dbs.nodesData).forEach(node => dbs.nodesData[node].readout = {}) + + let rvo_number = responseSettings[0]["rvo_name"].match(/\D+(\d{1,2})_/)[1]; + + dbs.settings = { + edge_fw_version: "2025-10-08", //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"], + phases: responseSettings[0]["phases"], + cloud_topic: responseSettings[0]["cloud_topic"], + has_main_switch: responseSettings[0]["has_main_switch"], + daily_report: responseSettings[0]["daily_report"], + send_changed_node_numbers: responseSettings[0]["send_changed_node_numbers"], + rvo_number: rvo_number, + + //dynamic values + masterNodeIsResponding: true, //cmd_manager + maintenance_mode: false, + } + + + dbs.settings.energy_to_switch_lamps = total_energy[rvo_number]; + if (dbs.settings.energy_to_switch_lamps === undefined) console.log('=============== db_init.js: energy_to_switch_lamps is undefined'); + + FLOW.dbLoaded = true; + errorHandler.setProjectId(dbs.settings.project_id); + initNotification(); + + //APP START - send to data services + const toService = { + id: dbs.settings.project_id, + name: dbs.settings.rvo_name, + fw_version: dbs.settings.edge_fw_version, + startdate: new Date().toISOString().slice(0, 19).replace('T', ' '), + js_error: "", + error_message: "" + }; + + instance.send(SEND_TO.infoSender, toService); + console.log("----------------> START - message send to service", toService); + + setTimeout(() => { + console.log("DB_INIT - data loaded"); + instance.send(SEND_TO.db_init, "_") + }, 5000) + +}; + diff --git a/RVO34/flow/debug.js b/RVO34/flow/debug.js new file mode 100755 index 0000000..00cb259 --- /dev/null +++ b/RVO34/flow/debug.js @@ -0,0 +1,100 @@ +exports.id = 'debug'; +exports.title = 'Debug'; +exports.author = 'Peter Širka'; +exports.color = '#967ADC'; +exports.click = true; +exports.input = true; +exports.icon = 'bug'; +exports.version = '2.0.4'; +exports.options = { enabled: true, repository: false, type: 'data' }; +exports.readme = `# Debug + +Prints data to the debug tab.`; + +exports.html = `
+
+
+
@(Output type)
+
@(Path to the property (leave empty to show the whole data object))
+
@(A group name)
+
@(Enabled)
+
+
+
`; + +exports.install = function(instance) { + + instance.on('data', function(response) { + if (instance.options.enabled) { + + var opt = instance.options; + var rep = response.repository; + var val = response.data; + var id = response.id; + + switch (instance.options.type){ + case 'both': + var data = {}; + data.repository = rep; + data.data = val instanceof Error ? { error: val.message, stack: val.stack } : val; + instance.debug(safeparse(opt.property ? U.get(data, opt.property) : data), undefined, opt.group, id); + break; + case 'repository': + instance.debug(safeparse(opt.property ? U.get(rep, opt.property) : rep), undefined, opt.group, id); + break; + case 'data': + default: + if (val instanceof Error) + instance.debug({ error: val.message, stack: val.stack }, undefined, opt.group, id); + else + instance.debug(safeparse(opt.property ? U.get(val, opt.property) : val), undefined, opt.group, id); + break; + } + } + }); + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + instance.save(); + }); + + instance.on('options', function() { + instance.custom.status(); + }); + + instance.custom.status = function() { + instance.status(instance.options.enabled ? 'Enabled' : 'Disabled'); + }; + + instance.custom.status(); + + function safeparse(o) { + + if (o instanceof Buffer) + return o; + + if (o === undefined) + return 'undefined'; + + if (o === null) + return 'null'; + + var cache = []; + var str = JSON.stringify(o, function(key, value) { + if (typeof value === 'object' && value !== null) { + if (cache.indexOf(value) !== -1) { + try { + return JSON.parse(JSON.stringify(value)); + } catch (error) { + return; + } + } + cache.push(value); + } + return value; + }); + cache = null; + return JSON.parse(str); + } +}; diff --git a/RVO34/flow/designer.json b/RVO34/flow/designer.json new file mode 100755 index 0000000..580f5a3 --- /dev/null +++ b/RVO34/flow/designer.json @@ -0,0 +1,3102 @@ +{ + "tabs": [ + { + "name": "MAIN PUSH", + "linker": "main-push", + "id": "1612772287426", + "index": 0 + }, + { + "name": "CMD manager", + "linker": "cmd-manager", + "id": "1615551125555", + "index": 1 + }, + { + "name": "Devices", + "linker": "devices", + "id": "1611921777196", + "index": 2 + } + ], + "components": [ + { + "id": "1611951142547", + "component": "debug", + "tab": "1611921777196", + "name": "ERROR", + "x": 598, + "y": 60, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#DA4453", + "notes": "" + }, + { + "id": "1612776786008", + "component": "wsmqttpublish", + "tab": "1612772287426", + "name": "WS MQTT publish", + "x": 281.75, + "y": 174, + "connections": { + "0": [ + { + "index": "0", + "id": "1615551060773" + } + ], + "1": [ + { + "index": "0", + "id": "1618300858252" + }, + { + "index": "0", + "id": "1618558465485" + } + ], + "2": [ + { + "index": "0", + "id": "1634303685503" + } + ], + "3": [ + { + "index": "0", + "id": "1731068754606" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Connected", + "color": "green" + }, + "options": { + "username": "", + "clientid": "", + "port": "1883", + "host": "" + }, + "color": "#888600", + "notes": "" + }, + { + "id": "1612778461252", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "tb-push", + "x": 72.75, + "y": 328, + "connections": { + "0": [ + { + "index": "0", + "id": "1612783322136" + }, + { + "index": "1", + "id": "1612776786008" + }, + { + "index": "0", + "id": "1731068754606" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1612783322136", + "component": "debug", + "tab": "1612772287426", + "name": "to TB", + "x": 283.75, + "y": 324, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615551060773", + "component": "debug", + "tab": "1612772287426", + "name": "errors from MQTT Broker", + "x": 594, + "y": 57, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#DA4453", + "notes": "" + }, + { + "id": "1615563373927", + "component": "debug", + "tab": "1615551125555", + "name": "Debug", + "x": 755, + "y": 155, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#DA4453", + "notes": "" + }, + { + "id": "1615566865233", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "tb-push", + "x": 755, + "y": 248, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1615798582262", + "component": "debug", + "tab": "1615551125555", + "name": "CMD_debug", + "x": 755, + "y": 346, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615802995322", + "component": "debug", + "tab": "1611921777196", + "name": "Debug", + "x": 596.8833312988281, + "y": 566.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Disabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": false + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615809128443", + "component": "debug", + "tab": "1611921777196", + "name": "tempToTb", + "x": 595.8833312988281, + "y": 658.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615809595184", + "component": "virtualwireout", + "tab": "1611921777196", + "name": "tb-push", + "x": 597.8833312988281, + "y": 377.25, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1616165795916", + "component": "httproute", + "tab": "1615551125555", + "name": "POST /terminal", + "x": 135, + "y": 547, + "connections": { + "0": [ + { + "index": "0", + "id": "1684060205000" + }, + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Listening", + "color": "green" + }, + "options": { + "timeout": 10, + "cachepolicy": 0, + "cacheexpire": "5 minutes", + "size": 5, + "url": "/terminal", + "method": "POST", + "name": "", + "flags": [ + "id:1616165795916", + "post", + 10000 + ], + "emptyresponse": false + }, + "color": "#5D9CEC", + "notes": "### Configuration\n\n- __POST /terminal__\n- flags: \n- maximum request data length: __5 kB__\n- empty response: __false__\n- cache policy: __no cache__\n- cache expire: __5 minutes__", + "cloning": false + }, + { + "id": "1616165824813", + "component": "httpresponse", + "tab": "1615551125555", + "name": "HTTP Response", + "x": 753, + "y": 423, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "json" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1617104731852", + "component": "debug", + "tab": "1615551125555", + "name": "DIDO_Debug", + "x": 669, + "y": 1040, + "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": "turnOff line", + "x": 133, + "y": 1161, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "object", + "data": "{line: 3, command: \"turnOff\", force: true}" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1617115013095", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "tb-push", + "x": 669, + "y": 1150, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1617284749681", + "component": "trigger", + "tab": "1615551125555", + "name": "update profile / node", + "x": 112, + "y": 208, + "connections": { + "0": [ + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "data": "profile_nodes", + "datatype": "string" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1618235171399", + "component": "trigger", + "tab": "1615551125555", + "name": "tun tasks", + "x": 184, + "y": 279, + "connections": { + "0": [ + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "data": "run" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1618300858252", + "component": "debug", + "tab": "1612772287426", + "name": "wsmqtt-exit1", + "x": 597.8833312988281, + "y": 149, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1618393583970", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "to-cmd-manager", + "x": 668.8833312988281, + "y": 1269, + "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": 132.88333129882812, + "y": 367, + "connections": { + "0": [ + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "platform-rpc-call", + "color": "gray" + }, + "options": { + "wirename": "platform-rpc-call" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1618393759854", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "cmd_to_dido", + "x": 119.88333129882812, + "y": 1007, + "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": 752.8833312988281, + "y": 527, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "cmd_to_dido", + "color": "gray" + }, + "options": { + "wirename": "cmd_to_dido" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1618558465485", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "platform-rpc-call", + "x": 597.8833312988281, + "y": 247, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "platform-rpc-call", + "color": "gray" + }, + "options": { + "wirename": "platform-rpc-call" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1618572059773", + "component": "trigger", + "tab": "1615551125555", + "name": "turnOn line", + "x": 132, + "y": 1085, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "data": "{line: 1, command: \"turnOn\", force: true}", + "datatype": "object" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1619515097737", + "component": "cmd_manager", + "tab": "1615551125555", + "name": "CMD Manager", + "x": 452.1091003417969, + "y": 341.05455017089844, + "connections": { + "0": [ + { + "index": "0", + "id": "1615563373927" + } + ], + "1": [ + { + "index": "0", + "id": "1615566865233" + }, + { + "index": "0", + "id": "1615798582262" + } + ], + "2": [ + { + "index": "0", + "id": "1616165824813" + } + ], + "3": [ + { + "index": "0", + "id": "1618393827655" + } + ], + "4": [ + { + "index": "0", + "id": "1635936391935" + } + ], + "5": [ + { + "index": "0", + "id": "1757006030239" + }, + { + "index": "0", + "id": "1757006060377" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1619605019281", + "component": "httproute", + "tab": "1615551125555", + "name": "GET db", + "x": 173, + "y": 653, + "connections": { + "0": [ + { + "index": "0", + "id": "1684060205000" + }, + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Listening", + "color": "green" + }, + "options": { + "timeout": 5, + "cachepolicy": 0, + "cacheexpire": "5 minutes", + "size": 5, + "url": "/db", + "method": "GET", + "name": "", + "flags": [ + "id:1619605019281", + "get", + 5000 + ] + }, + "color": "#5D9CEC", + "notes": "### Configuration\n\n- __GET /db__\n- flags: undefined\n- maximum request data length: __5 kB__\n- empty response: __undefined__\n- cache policy: __no cache__\n- cache expire: __5 minutes__", + "cloning": false + }, + { + "id": "1619784672383", + "component": "trigger", + "tab": "1615551125555", + "name": "turnOnAlarm", + "x": 120, + "y": 1234, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "object", + "data": "{command: \"turnOnAlarm\"}" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1619784812964", + "component": "trigger", + "tab": "1615551125555", + "name": "turnOffAlarm", + "x": 118, + "y": 1307, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "object", + "data": "{command: \"turnOffAlarm\"}" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1621340721628", + "component": "virtualwireout", + "tab": "1611921777196", + "name": "modbus_to_dido", + "x": 599, + "y": 471, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "modbus_to_dido", + "color": "gray" + }, + "options": { + "wirename": "modbus_to_dido" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1622640022885", + "component": "httproute", + "tab": "1615551125555", + "name": "POST /db_connector", + "x": 98, + "y": 1586, + "connections": { + "0": [ + { + "index": "0", + "id": "1622640073521" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Listening", + "color": "green" + }, + "options": { + "timeout": 5, + "cachepolicy": 0, + "cacheexpire": "5 minutes", + "size": 5, + "url": "/db_connector", + "method": "POST", + "flags": [ + "id:1622640022885", + "post", + 5000 + ] + }, + "color": "#5D9CEC", + "notes": "### Configuration\n\n- __POST /db_connector__\n- flags: \n- maximum request data length: __5 kB__\n- empty response: __undefined__\n- cache policy: __no cache__\n- cache expire: __5 minutes__", + "cloning": false + }, + { + "id": "1622640073521", + "component": "db_connector", + "tab": "1615551125555", + "name": "DbConnector", + "x": 372, + "y": 1572, + "connections": { + "1": [ + { + "index": "0", + "id": "1622641420685" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "edge": "undefined" + }, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1622641420685", + "component": "httpresponse", + "tab": "1615551125555", + "name": "HTTP Response", + "x": 596, + "y": 1586, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1634303504177", + "component": "monitormemory", + "tab": "1612772287426", + "name": "RAM", + "x": 69.88333129882812, + "y": 888.5, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465281992" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "858.88 MB / 985.68 MB", + "color": "gray" + }, + "options": { + "enabled": true, + "interval": 30000 + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1634303533779", + "component": "monitordisk", + "tab": "1612772287426", + "name": "disk", + "x": 70.88333129882812, + "y": 982.5, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465821120" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "5.78 GB / 7.26 GB", + "color": "gray" + }, + "options": { + "enabled": true, + "path": "/", + "interval": 30000 + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1634303595494", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "send-to-services", + "x": 51.883331298828125, + "y": 1400.5, + "connections": { + "0": [ + { + "index": "0", + "id": "1634463186563" + }, + { + "index": "1", + "id": "1634488120710" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1634303602169", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "send-to-services", + "x": 426.8833312988281, + "y": 878.5, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1634303685503", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "send-to-services", + "x": 600.8833312988281, + "y": 341.5, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1634303743260", + "component": "httprequest", + "tab": "1612772287426", + "name": "192.168.252.2:8004/sentmessage", + "reference": "", + "x": 506.8833312988281, + "y": 1331.7333374023438, + "connections": { + "0": [ + { + "index": "0", + "id": "1635327431236" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "url": "http://192.168.252.2:8004/sentmessage", + "method": "POST", + "stringify": "json" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1634463186563", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 305.75, + "y": 1442, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634464580289", + "component": "code", + "tab": "1612772287426", + "name": "Code", + "x": 245, + "y": 787, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465243324" + }, + { + "index": "0", + "id": "1634303602169" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "keepmessage": true, + "code": "let response = {};\nresponse.cpu = value.cpu;\nresponse.uptime = value.uptime;\n\nsend(0, response);", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1634465243324", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 428, + "y": 784, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634465281992", + "component": "code", + "tab": "1612772287426", + "name": "Code", + "x": 245, + "y": 884, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465338103" + }, + { + "index": "0", + "id": "1634303602169" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "keepmessage": true, + "code": "value.sender = \"ram\";\n\nlet response = {};\n\nresponse.memory_total = Math.round(value.total / (1024 ** 2));\nresponse.memory_free = Math.round(value.free / (1024 ** 2));\nresponse.memory_used = Math.round(value.used / (1024 ** 2));\n\nsend(0, response);", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1634465338103", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 429, + "y": 976, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634465821120", + "component": "code", + "tab": "1612772287426", + "name": "Code", + "x": 245, + "y": 978, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465892500" + }, + { + "index": "0", + "id": "1634303602169" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "keepmessage": true, + "code": "value.sender = \"hdd\";\n\nlet response = {};\n\nresponse.hdd_total = Math.round(value.total / (1024 ** 2));\nresponse.hdd_free = Math.round(value.free / (1024 ** 2));\nresponse.hdd_used = Math.round(value.used / (1024 ** 2));\n\nsend(0, response);", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1634465892500", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 432, + "y": 1068, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634484067516", + "component": "debug", + "tab": "1612772287426", + "name": "Send info", + "x": 513, + "y": 1441, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634488120710", + "component": "infosender", + "tab": "1612772287426", + "name": "Info sender", + "x": 301, + "y": 1336, + "connections": { + "0": [ + { + "index": "0", + "id": "1634484067516" + }, + { + "index": "0", + "id": "1634303743260" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "edge": "undefined" + }, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1635327431236", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 837.8833312988281, + "y": 1325.5, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1635936391935", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "send-to-services", + "x": 753, + "y": 623, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1637069803394", + "component": "monitorconsumption", + "tab": "1612772287426", + "name": "CPU", + "x": 69, + "y": 791, + "connections": { + "0": [ + { + "index": "0", + "id": "1634464580289" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "49.2% / 69.91 MB", + "color": "gray" + }, + "options": { + "monitorfiles": true, + "monitorconnections": true, + "monitorsize": true, + "monitorconsumption": true, + "enabled": true, + "interval": 30000 + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1683664161036", + "component": "debug", + "tab": "1615551125555", + "name": "CMDtoDIDO", + "x": 392, + "y": 1012, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1683981346282", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "from-dido-controller", + "x": 112, + "y": 459, + "connections": { + "0": [ + { + "index": "0", + "id": "1684055037116" + }, + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "from-dido-controller", + "color": "gray" + }, + "options": { + "wirename": "from-dido-controller" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1684055037116", + "component": "debug", + "tab": "1615551125555", + "name": "from dido to cmd", + "x": 451, + "y": 532, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1684060205000", + "component": "debug", + "tab": "1615551125555", + "name": "HTTP routes", + "x": 450, + "y": 639, + "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": "MDBToDido", + "x": 598, + "y": 147, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1699963668903", + "component": "dido_controller", + "tab": "1615551125555", + "name": "DIDO_Controller", + "x": 397, + "y": 1131, + "connections": { + "0": [ + { + "index": "0", + "id": "1617104731852" + } + ], + "1": [ + { + "index": "0", + "id": "1617104731852" + }, + { + "index": "0", + "id": "1617115013095" + } + ], + "2": [ + { + "index": "0", + "id": "1618393583970" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "edge": "undefined" + }, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1699964678894", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "modbus_to_dido", + "x": 96, + "y": 924, + "connections": { + "0": [ + { + "index": "0", + "id": "1699963668903" + }, + { + "index": "0", + "id": "1699964793925" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "modbus_to_dido", + "color": "gray" + }, + "options": { + "wirename": "modbus_to_dido" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1699964793925", + "component": "debug", + "tab": "1615551125555", + "name": "modbusToDido", + "x": 388, + "y": 920, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1699965957410", + "component": "modbus_reader", + "tab": "1611921777196", + "name": "Modbus reader", + "x": 232, + "y": 175, + "connections": { + "0": [ + { + "index": "0", + "id": "1611951142547" + } + ], + "1": [ + { + "index": "0", + "id": "1621340721628" + }, + { + "index": "0", + "id": "1684179110403" + }, + { + "index": "0", + "id": "1717441414646" + } + ], + "2": [ + { + "index": "0", + "id": "1615809595184" + }, + { + "index": "0", + "id": "1714752862828" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1700411878636", + "component": "thermometer", + "tab": "1611921777196", + "name": "Thermometer", + "x": 234.75, + "y": 444, + "connections": { + "0": [ + { + "index": "0", + "id": "1615802995322" + } + ], + "1": [ + { + "index": "0", + "id": "1615809595184" + }, + { + "index": "0", + "id": "1615809128443" + } + ], + "2": [ + { + "index": "0", + "id": "1621340721628" + }, + { + "index": "0", + "id": "1732889185927" + }, + { + "index": "0", + "id": "1717441414646" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#5CB36D", + "notes": "" + }, + { + "id": "1714752862828", + "component": "debug", + "tab": "1611921777196", + "name": "MDBToTb", + "x": 766, + "y": 324, + "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": 764.0833282470703, + "y": 222, + "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\telse if(value.status === \"NOK-thermometer\")\n\t{\n\t\tsend(0, {\"thermometer\": \"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\telse if(value.values.hasOwnProperty(\"temperature\"))\n\t{\n\t\tsend(0, {\"thermometer\": \"OK\"});\n\t}\n}", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1717442627834", + "component": "debug", + "tab": "1611921777196", + "name": "modbus service", + "x": 966.0833282470703, + "y": 165, + "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": 968.0833282470703, + "y": 268, + "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": 88.75, + "y": 1685, + "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": 296, + "y": 1671, + "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\", \"Flow has been restarted\", \"Node db has changed\"]", + "types": "[\"emergency\", \"critical\", \"error\", \"alert\"]", + "name": "" + }, + "color": "#30E193", + "notes": "" + }, + { + "id": "1718016073501", + "component": "httprequest", + "tab": "1612772287426", + "name": "http://192.168.252.2:8004/slack", + "x": 495, + "y": 1753, + "connections": { + "0": [ + { + "index": "0", + "id": "1718016086212" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "url": "http://192.168.252.2:8004/slack", + "method": "POST", + "stringify": "json" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1718016086212", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 832, + "y": 1664, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "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": 87, + "y": 1591, + "connections": { + "0": [ + { + "index": "0", + "id": "1718016052341" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "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\": \"\" } } } ] }", + "datatype": "object" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1729855334955", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "platform-rpc-call", + "x": 599.9333343505859, + "y": 541.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "platform-rpc-call", + "color": "gray" + }, + "options": { + "wirename": "platform-rpc-call" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1729855371093", + "component": "debug", + "tab": "1612772287426", + "name": "rpc cloud", + "x": 601.9333343505859, + "y": 440.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1731068658334", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 75.75, + "y": 184, + "connections": { + "0": [ + { + "index": "0", + "id": "1612776786008" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731068754606", + "component": "cloudmqttconnect", + "tab": "1612772287426", + "name": "MQTT to senica-prod01", + "x": 284.75, + "y": 452, + "connections": { + "1": [ + { + "index": "0", + "id": "1729855371093" + }, + { + "index": "0", + "id": "1729855334955" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Connected", + "color": "green" + }, + "options": { + "username": "", + "clientid": "", + "port": "2764", + "host": "192.168.252.2", + "topic": "" + }, + "color": "#888600", + "notes": "" + }, + { + "id": "1731069001548", + "component": "db_init", + "tab": "1612772287426", + "name": "DB Initialization", + "x": 1003.75, + "y": 240.25, + "connections": { + "0": [ + { + "index": "0", + "id": "1731069033416" + } + ], + "1": [ + { + "index": "0", + "id": "1747561603739" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#888600", + "notes": "" + }, + { + "id": "1731069033416", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "db-init", + "x": 1244.75, + "y": 233.25, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069059135", + "component": "showdb", + "tab": "1612772287426", + "name": "Show db data", + "x": 1186.75, + "y": 821.25, + "connections": { + "0": [ + { + "index": "0", + "id": "1731069079243" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#888600", + "notes": "" + }, + { + "id": "1731069079243", + "component": "debug", + "tab": "1612772287426", + "name": "dbData", + "x": 1390.75, + "y": 870.25, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1731069116691", + "component": "trigger", + "tab": "1612772287426", + "name": "settings", + "x": 934.75, + "y": 669.75, + "connections": { + "0": [ + { + "index": "0", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069131637", + "component": "trigger", + "tab": "1612772287426", + "name": "relaysData", + "x": 876.75, + "y": 733.75, + "connections": { + "0": [ + { + "index": "1", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069137374", + "component": "trigger", + "tab": "1612772287426", + "name": "nodesData", + "x": 852.75, + "y": 794.75, + "connections": { + "0": [ + { + "index": "2", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069179846", + "component": "trigger", + "tab": "1612772287426", + "name": "pinsData", + "x": 850.75, + "y": 861.75, + "connections": { + "0": [ + { + "index": "3", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069192937", + "component": "trigger", + "tab": "1612772287426", + "name": "sample data", + "x": 857.75, + "y": 928.75, + "connections": { + "0": [ + { + "index": "4", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069264443", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 63.75, + "y": 1279, + "connections": { + "0": [ + { + "index": "0", + "id": "1634488120710" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069334626", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "db-init", + "x": 172.88333129882812, + "y": 129, + "connections": { + "0": [ + { + "index": "0", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069548145", + "component": "virtualwirein", + "tab": "1611921777196", + "name": "db-init", + "x": 46.75, + "y": 192, + "connections": { + "0": [ + { + "index": "0", + "id": "1699965957410" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069567152", + "component": "virtualwirein", + "tab": "1611921777196", + "name": "db-init", + "x": 44.75, + "y": 465, + "connections": { + "0": [ + { + "index": "0", + "id": "1700411878636" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731070156936", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "db-init", + "x": 126.88333129882812, + "y": 1377, + "connections": { + "0": [ + { + "index": "2", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731234189516", + "component": "trigger", + "tab": "1612772287426", + "name": "monitor.txt", + "x": 882.75, + "y": 991.75, + "connections": { + "0": [ + { + "index": "5", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731234189551", + "component": "trigger", + "tab": "1612772287426", + "name": "err.txt", + "x": 904.75, + "y": 1053.75, + "connections": { + "0": [ + { + "index": "6", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1732700042559", + "component": "nodesdb_change_check", + "tab": "1612772287426", + "name": "Nodes DB change check", + "x": 266.8833312988281, + "y": 1980.2333984375, + "connections": { + "0": [ + { + "index": "0", + "id": "1732700071298" + }, + { + "index": "0", + "id": "1732700642917" + } + ], + "1": [ + { + "index": "0", + "id": "1759958914348" + }, + { + "index": "0", + "id": "1759959003114" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#888600", + "notes": "" + }, + { + "id": "1732700057052", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 76.75, + "y": 1988, + "connections": { + "0": [ + { + "index": "0", + "id": "1732700042559" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1732700071298", + "component": "debug", + "tab": "1612772287426", + "name": "nodesChange", + "x": 571.8833312988281, + "y": 2018.2333984375, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1732700642917", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "tb-push", + "x": 567.8833312988281, + "y": 1933, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1732889185927", + "component": "debug", + "tab": "1611921777196", + "name": "tempToDido", + "x": 594.8833312988281, + "y": 753, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1733574412965", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 72.75, + "y": 474, + "connections": { + "0": [ + { + "index": "1", + "id": "1731068754606" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1747561603739", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "send-to-services", + "x": 1243.8833312988281, + "y": 334.5, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1747562867845", + "component": "comment", + "tab": "1612772287426", + "name": "FLOW STARTING POINT", + "x": 1003.5666656494141, + "y": 178, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#704cff", + "notes": "" + }, + { + "id": "1749211698385", + "component": "trigger", + "tab": "1612772287426", + "name": "deviceStatus", + "x": 911.75, + "y": 1116.75, + "connections": { + "0": [ + { + "index": "7", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1757006030239", + "component": "httprequest", + "tab": "1615551125555", + "name": "192.168.252.2:8015/daily_report", + "x": 756.5666656494141, + "y": 715.4499969482422, + "connections": { + "0": [ + { + "index": "0", + "id": "1757006045804" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "stringify": "json", + "method": "POST", + "url": "http://192.168.252.2:8015/daily_report" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1757006045804", + "component": "debug", + "tab": "1615551125555", + "name": "ddd", + "x": 1091.566665649414, + "y": 711.4499969482422, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1757006060377", + "component": "debug", + "tab": "1615551125555", + "name": "reportDebug", + "x": 749.5666656494141, + "y": 799.4499969482422, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1759958914348", + "component": "httprequest", + "tab": "1612772287426", + "name": "http://192.168.252.2:8015/node_numbers", + "x": 571, + "y": 2111, + "connections": { + "0": [ + { + "index": "0", + "id": "1759958927094" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "stringify": "json", + "method": "POST", + "url": "http://192.168.252.2:8015/node_numbers" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1759958927094", + "component": "debug", + "tab": "1612772287426", + "name": "nodesChangeCloud", + "x": 951.8833312988281, + "y": 2109.2333984375, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1759959003114", + "component": "debug", + "tab": "1612772287426", + "name": "nodeChangeCloud1", + "x": 574, + "y": 2218, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1760020290879", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 84.75, + "y": 1787, + "connections": { + "0": [ + { + "index": "1", + "id": "1718016052341" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + } + ], + "version": 615 +} diff --git a/RVO34/flow/dido_controller.js b/RVO34/flow/dido_controller.js new file mode 100755 index 0000000..d16fb19 --- /dev/null +++ b/RVO34/flow/dido_controller.js @@ -0,0 +1,1486 @@ +exports.id = 'dido_controller'; +exports.title = 'DIDO_Controller'; +exports.version = '2.0.0'; +exports.group = 'Worksys'; +exports.color = '#2134B0'; +exports.input = 3; +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 + +state_of_main_switch - reportovat stav hlaveho istica : 0-> off 1-> on +rotary_switch_state - sem by sa mal reportovat stav vstupov manual a auto pola nasledovnej logiky: Manual = 1 a Auto = 0 -> Manu +Manual = 0 a Auto = 0 -> Off, Manual = 0 a Auto = 1 -> Automatic + +door_condition - pin 6, dverový kontakt -> 1 -> vyreportuje Closed, 0 -> vyreportuje Ope +twilight_sensor - hodnotu, ktoru vracia ten analogovy vstup (17) treba poslat sem ako float number. Zrejme tu potom pridame nejaky koeficient prevodu na luxy + +Na kazdu liniu +state_of_breaker - podla indexu istica sa reportuje jeho stav, teda istic na liniu 1: 0-> off, 1-> on +state_of_contactor - podla indexu stkaca sa reportuje jeho stav, teda stykac 1 na liniu 1: 0-> off, 1-> on +*/ + +const { errLogger, logger, monitor } = require('./helper/logger'); +const SerialPort = require('serialport'); +const WebSocket = require('ws'); +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 errorHandler = require('./helper/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 hasMainSwitch; + +let alarmStatus = "OFF"; + +const SEND_TO = { + debug: 0, + tb: 1, + cmd_manager: 2 +} + + +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 = {}; + let rsPortReceivedData = []; + + //to be able to get proper twilight values + let twilight_sensor_interval = 5;//minutes + let twilight_sensor = []; + const twilight_sensor_array = []; + let twilightError = false; + + monitor.info("DIDO_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-we make it global to see it from outside + FLOW.deviceStatus = { //key is device name: temperature,.... + "state_of_main_switch": "Off", //Hlavny istic (alebo druhy dverovy kontakt) + "rotary_switch_state": "Off", //Prevadzkovy + "door_condition": "closed", //Dverový kontakt + "em": "OK", //elektromer rvo + "temperature": "OK", //templomer + "battery": "OK", //Bateria + "power_supply": "OK", //Zdroj + "master_node": "OK", //MN - GLOBALS.settings.masterNodeIsResponding + "no_voltage": "OK", //GLOBALS.settings.no_voltage - vypadok napatia na faze + "state_of_breaker": {}, //"Off",//Istic + "state_of_contactor": {}, //"Off",//Stykac + "twilight_sensor": "OK" //lux sensor + }; + let deviceStatus = FLOW.deviceStatus; + + + function main() { + + GLOBALS = FLOW.GLOBALS; + SETTINGS = FLOW.GLOBALS.settings; + rvoTbName = SETTINGS.rvoTbName; + pinsData = GLOBALS.pinsData; + relaysData = GLOBALS.relaysData; + + tbHandler = new DataToTbHandler(SEND_TO.tb); + tbHandler.setSender(exports.title); + + controller_type = SETTINGS.controller_type; //"lm" or "unipi" + hasMainSwitch = SETTINGS.has_main_switch; + + if (controller_type == "") controller_type = "lm"; + + 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, "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; + } + } + + //report RVO version relaysData[0].tbname; + let values = {}; + values["edge_fw_version"] = SETTINGS.edge_fw_version; + values["maintenance_mode"] = SETTINGS.maintenance_mode; + + sendTelemetry(values, rvoTbName); + + 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); + } + + + function handleRsPort() { + + if (rsPort) { + rsPort.removeAllListeners(); + rsPort = null; + } + + //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('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) { + if (!err) { + monitor.info(exports.title + "--->Digital in_out has been set (runSyncExec was sucessfull)"); + + turnAlarm("off"); + 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('error', err => { + let message = "Dido: rsPort error: " + err.message; + logger.debug(message); + monitor.info(message); + errorHandler.sendMessageToService(message); + }) + + rsPort.on("close", () => { + let message = "Dido: rsPort closed - reconnecting ..."; + logger.debug(message); + monitor.info(message); + setTimeout(handleRsPort, 1000); + }) + + rsPort.open(); + } + + + function handleWebSocket() { + + if (ws) { + ws.removeAllListeners(); + ws = null; + } + + //to keep websocket opened, we send request every 150 seconds + let startRequests = null; + + console.log("handleWebSocket function called"); + ws = new WebSocket('ws:/0.0.0.0:1234/ws'); + + ws.onopen = function open() { + + instance.send(0, exports.title + " running"); + turnAlarm("off"); + + initialSetting(); + + setTimeout(function() { ws.send(JSON.stringify({ cmd: "all" })) }, 5000); + // we request dev info about neuron device from evok to keep websocket connection alive + // for some reason this request returns no data, but connection keeps alive + startRequests = setInterval(() => { + ws.send(JSON.stringify({ "cmd": "filter", "dev": ["neuron"] })); + }, 150000) + }; + + + // 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 = async 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; + + 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 => { + logger.debug('Dido: websocket error', err); + }) + + ws.onclose = function() { + logger.debug('Dido: websocket onclose, reconnecting...') + clearInterval(startRequests); + setTimeout(handleWebSocket, 1000); + } + } + + 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 turnAlarm(onOrOff) { + let value = 0; + if (onOrOff == "on") value = 1; + + if (value == 1 && SETTINGS.maintenance_mode) return; + + alarmStatus = "OFF"; + if (value == 1) alarmStatus = "ON"; + + if (rsPort) { + let arr = [0x55]; + arr.push(13); + arr.push(0); + arr.push(value); + + rsPort.write(Buffer.from(arr), function(err) { + logger.debug(`sirena - ${onOrOff}`); + }); + } + else if (ws) { + let cmd = { "cmd": "set", "dev": "relay", "circuit": "1_01", "value": value }; + ws.send(JSON.stringify(cmd)); + logger.debug(`sirena - ${onOrOff}`); + } + } + + + 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") { + bits.push(0); + } + else bits.push(1); + + if (deviceStatus["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); + } + + + // turn line on or off + function turnLine(onOrOff, line, pin, force, info) { + //onOrOff => "on" or "off" + let value = 0; + if (onOrOff == "on") value = 1; + + if (force == undefined) force = false; + + if (line == 0) { + if (value == 1 && alarmStatus == "ON") turnAlarm("off"); + SETTINGS.maintenance_mode = value ? true : false; + + 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); + return; + } + + if (pin === undefined) pin = getPin(line); + + if (pin === undefined) { + errLogger.error("pin is undefined!", line); + return; + } + + if (!force) { + if (relaysData[line].contactor == value) { + instance.send(SEND_TO.debug, `line is already ${onOrOff} ` + line); + logger.debug(`Dido: turnLine: line is already ${onOrOff} `, line); + return; + } + } + + // if(!rsPort.isOpen && !ws) + if (!rsPort && !ws) { + errLogger.error("Dido - port or websocket is not opened"); + return; + } + + if (rsPort) { + let arr = [0x55]; + arr.push(pin); + arr.push(0); + arr.push(value); + + rsPort.write(Buffer.from(arr), function(err) { + if (err === undefined) { + monitor.info(`Dido: turnLine ${onOrOff} zapisal do rsPort-u`, line, pin, arr, info); + switchLogic(arr); + } + else { + monitor.info(`Dido: turnLine ${onOrOff} WRITE error`, err); + } + }); + + } + else if (ws) { + //pin = "relay1_03" or "input1_01" ... we must make just "1_01" with slice method + monitor.info(`Dido: turnLine ${onOrOff} - (line, pin, force)`, line, pin, force, info); + let cmd = { "cmd": "set", "dev": "relay", "circuit": pin.slice(5), "value": value }; + ws.send(JSON.stringify(cmd)); + } + + //if rvo is 24/7, it has just one switching profile point at 13:00. we do not want to send notification as it repeats every day. + //const d = new Date(); + //if(d.getHours() != 13) sendNotification("Dido_controller: ", SETTINGS.rvoTbName, "switching_profile_point_applied_to_line", { line: line, value: onOrOff }, "", SEND_TO.tb, instance); + } + + + // 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; + + // 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) { + const status = flowdata.data.status; + if (status == "NOK-twilight_sensor") { + deviceStatus["twilight_sensor"] = "NOK"; + } + else if (status == "NOK-em340" || status == "NOK-em111") { + deviceStatus["em"] = "NOK"; + } + else if (status == "NOK-thermometer") { + deviceStatus["temperature"] = "NOK"; + } + } + else if ("values" in flowdata.data) { + 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" + } + else if (values.hasOwnProperty("temperature")) { + deviceStatus["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"; + } + + sendTelemetry(values, rvoTbName); + } + + sendRvoStatus(); + }) + + + + + // we expect array as flowdata.data + instance.on("1", flowdata => { + + //console.log(flowdata.data); + + if (!flowdata.data instanceof Object) return; + + let obj = flowdata.data; + let line = obj.line; + 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"); + }) + + + function calculateStateCode() { + + let bits = []; + + //Hlavny istic - state_of_main_switch => v rvo senica je to druhy door pre silovu cast (EM) + if (deviceStatus["state_of_main_switch"] === "closed" || deviceStatus["state_of_main_switch"] === "Off") { + bits.push(0); + } + else { + bits.push(1); + } + + //Prevadzkovy mod - Manual, Off, Automatic, maintenance_mode = true/false // DAVA 2 BITY + if (!SETTINGS.maintenance_mode) { + if (deviceStatus["rotary_switch_state"] === "Manual") { + bits.push(0); + bits.push(1); + } + + if (deviceStatus["rotary_switch_state"] === "Automatic") { + bits.push(0); + bits.push(0); + } + + if (deviceStatus["rotary_switch_state"] === "Off") { + bits.push(1); + bits.push(0); + } + } + else { + bits.push(1); + bits.push(1); + } + + //Dverovy kontakt + if (deviceStatus["door_condition"] === "closed") { + bits.push(0); + } + else { + bits.push(1); + } + + //EM + if (deviceStatus["em"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //Teplomer + if (deviceStatus["temperature"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //Batéria + if (deviceStatus["battery"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //Zdroj + if (deviceStatus["power_supply"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //MN + if (deviceStatus["master_node"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //výpadok napätia na fáze + if (deviceStatus["no_voltage"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + if (deviceStatus["twilight_sensor"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + // doplnime do 16 bitov (2 byty) + for (let i = bits.length; i < 16; i++) { + bits.push(0); + } + + // console.log("calculateStateCode - deviceStatus", deviceStatus); + // 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; + } + + + async function sendRvoStatus() { + + if (SETTINGS === undefined) return; + SETTINGS.masterNodeIsResponding ? deviceStatus["master_node"] = "OK" : deviceStatus["master_node"] = "NOK"; + + 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 pinsForRvoStatus(controllerType, hasMainSwitch) { + + let pins = []; + + if (controllerType === "lm") { + pins = [1, 4, 6]; + if (hasMainSwitch === 1) { + pins = [4, 6]; + } + } else if (controllerType === "unipi") { + pins = ["input1_01", "input1_04", "input1_05"]; + if (hasMainSwitch === 1) { + pins = ["input1_01", "input1_04"]; + } + } + + return pins; + } + + + function checkRvoStatus() { + + // 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 + //set RVO state + let status = "OK"; + + for (const [key, value] of Object.entries(deviceStatus)) { + if (["em", "twilight_sensor", "temperature", "master_node"].includes(key) && value === "NOK") status = "NOK"; + } + + if (status === "OK") { + + let pinIndexes = pinsForRvoStatus(controller_type, hasMainSwitch); + + for (const pinIndex of pinIndexes) { + if (previousValues[pinIndex] === 0) { + if ((pinIndex === 6 || pinIndex === 'input1_01' || pinIndex === 'input1_05') && SETTINGS.maintenance_mode) continue; + status = "NOK"; + break; + } + } + } + + // battery status. If value is 1 - battery is NOK + if (previousValues[5] === 1) status = "NOK"; + if (SETTINGS.no_voltage.size > 0) status = "NOK"; + + // console.log("rvo status",status) + return status; + } + + + // we pass array to function in case of rsPort ==> switchLogic([55,3,0,1]) ==> [[55,3,0,1]] + // we pass two values in case of websocket ==> switchLogic("relay1_03",1) ==> ["relay1_03",1] + const switchLogic = (...args) => { + + let values = {}; + let pinIndex, newPinValue, twilight; + + //data from rsPort + if (args.length == 1) { + pinIndex = args[0][1] + 1; + if (pinIndex === 17) pinIndex--; + newPinValue = args[0][3]; + twilight = args[0][2]; + } + //data from websocket + else { + pinIndex = args[0]; + newPinValue = args[1]; + } + + 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; + + //default value + let value = "On"; + if (newPinValue === 0) value = "Off"; + + //Hlavny istic + if (type === "state_of_main_switch" && hasMainSwitch) { + if (newPinValue === 0 && newPinValue !== previousValues[pinIndex]) { + sendNotification("switchLogic", rvoTbName, "main_switch_has_been_turned_off", {}, "", SEND_TO.tb, instance, "state_of_main_switch"); + 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"); + deviceStatus["state_of_main_switch"] = "On"; + } + } + + //Prevadzkovy mod + 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"; + + deviceStatus["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, "power_supply_has_disconnected_input", {}, "", SEND_TO.tb, instance, "power_supply"); + + deviceStatus["power_supply"] = "NOK"; + } + else if (newPinValue === 1 && newPinValue !== previousValues[pinIndex]) { + sendNotification("switchLogic", rvoTbName, "power_supply_works_correctly", {}, "", SEND_TO.tb, instance, "power_supply"); + + deviceStatus["power_supply"] = "OK"; + } + } + + //Bateria - 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"); + + deviceStatus["battery"] = "NOK"; + } + else if (newPinValue === 0 && newPinValue !== previousValues[pinIndex]) { + sendNotification("switchLogic", rvoTbName, "battery_level_is_ok", {}, "", SEND_TO.tb, instance, "battery_level"); + + deviceStatus["battery"] = "OK"; + } + } + + //Dverovy kontakt - pin 6 + //! Ak je rvo s dvoma dverovymi kontaktami, ked pride z evoku signal z input1_05, co bol predytm "state_of_main switch" handlujeme ho teraz ako 'door_condition' + else if (type == "door_condition" || type === "state_of_main_switch") { + newPinValue === 0 ? value = "open" : value = "closed"; + + let door = "door_main"; + if (type === "state_of_main_switch") door = "door_em"; + + if (value === "open") { + if (SETTINGS.maintenance_mode) { + sendNotification("switchLogic", rvoTbName, door + "_open", {}, "", SEND_TO.tb, instance, door); + } else { + sendNotification("switchLogic", rvoTbName, door + "_open_without_permission", {}, "", SEND_TO.tb, instance, door); + + // 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 (value === "closed") { + if (alarmStatus == "ON") turnAlarm("off"); + sendNotification("switchLogic", rvoTbName, door + "_close", {}, "", SEND_TO.tb, instance, door); + } + + deviceStatus[type] = value; + } + + //lux sensor + else if (type == "twilight_sensor") { + //! TODO - to show nok status, if lux value is not changing more then 10 times. + //Daylight is far more than 1000. So most of the day, when it is sunshine comes just value 1000. But lux sensor is not NOK. + //This is not the case in LM. If value from LM is the same 10x, there is 99% possibility, that sensor is NOK. + value = newPinValue; + + if (controller_type === 'lm') { + value = parseFloat(newPinValue + (256 * twilight)); + + 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 && !twilightError) { + twilightError = true; + let value = twilight_sensor_array.shift(); + + newPinValue = 0; + } + else if (set.size !== 1 && twilightError) { + //sendNotification("switchLogic", rvoTbName, 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) { + 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); + } + } + + 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); + } + + deviceStatus["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 (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 }); + + //mame iba 3 istice. vyreportujeme a ohandlujeme liniu na tom istom istici ako paralelna linia (napr linia 1, paralelna s nou je linia 4, key je string "4") + // ak je 7 linii, na 1 istici je linia 1,4,7 + + if (line == 1) { + + const lineOnSameBraker = [4, 7]; + + for (var i = 0; i < lineOnSameBraker.length; i++) { + if (!relaysData.hasOwnProperty(lineOnSameBraker[i])) continue; + + 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; + reportLineStatus(lineOnSameBraker[i]); + + values[type] = value; + const tbname = relaysData[lineOnSameBraker[i]].tbname; + sendTelemetry(values, tbname); + + delete values[type]; + } + + } + else { + const lineOnSameBraker = line + 3 + ""; + + if (relaysData.hasOwnProperty(lineOnSameBraker)) { + 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; + reportLineStatus(line + 3); + + values[type] = value; + const tbname = relaysData[lineOnSameBraker].tbname; + sendTelemetry(values, tbname); + + delete values[type]; + } + } + + } + + if (value == "Off") values["status"] = "NOK"; + deviceStatus["state_of_breaker"][line] = value; + + reportLineStatus(line); + } + else return; + + values[type] = value; + + if (type == "rotary_switch_state") { + if (SETTINGS.maintenance_mode) value = "maintenance"; + value = value.toLowerCase(); + values["power_mode"] = value; + } + + if (newPinValue != previousValues[pinIndex]) previousValues[pinIndex] = newPinValue; + if (Object.keys(values).length > 0 && tbname) sendTelemetry(values, tbname); + } + + + function sendTelemetry(values, tbname, date = Date.now()) { + let dataToTb = { + [tbname]: [ + { + "ts": date, + "values": values + } + ] + }; + + tbHandler.sendToTb(dataToTb, instance); + } + + + function isObject(item) { + return (typeof item === "object" && !Array.isArray(item) && item !== null); + } + +} //end of 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 +// *|input1_01|state_of_main_switch|0|........... +// *|input1_02|rotary_switch_state|0|........... +// *|input1_03|rotary_switch_state|0|........... +// *|intut1_04|power_supply|0|........... +// *|input1_05|door_condition|0|........... +// *|input1_06|state_of_breaker|1|........... +// *|input1_07|state_of_breaker|2|........... +// *|input1_08|state_of_breaker|3|........... +// *|relay1_02|state_of_contactor|1|........... +// *|relay1_03|state_of_contactor|2|........... +// *|relay1_04|state_of_contactor|3|........... +// *|287D8776E0013CE9|temperature|0|........... + + +//! pins_data --> from UNIPI +// { +// 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 } +// } + +//! relays_data +// { +// '0': { +// line: 0, +// tbname: 'KjbN4q7JPZmexgdnz2yKQ98YAWwO0Q3BMX6ERLoV', +// contactor: 1, +// profile: '' +// }, +// '1': { +// line: 1, +// tbname: 'RMgnK93rkoAazbqdQ4yBG95Z1YXGx6pmwBeVEP2O', +// contactor: 0, +// profile: '{"intervals":[{"value":0,"end_time":"20:00","start_time":"13:00"},{"value":1,"end_time":"10:00","start_time":"20:00"},{"value":0,"end_time":"10:20","start_time":"10:00"},{"value":1,"end_time":"10:40","start_time":"10:20"},{"value":0,"end_time":"11:00","start_time":"10:40"},{"value":1,"end_time":"11:30","start_time":"11:00"},{"value":0,"end_time":"11:50","start_time":"11:30"},{"value":1,"end_time":"13:00","start_time":"11:50"}],"astro_clock":false,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' +// }, +// '2': { +// line: 2, +// tbname: 'dlE1VQjYrNx9gZRmb38gG08oLBO4qaAk2M6JPnG7', +// contactor: 0, +// profile: '{"intervals":[{"value":0,"end_time":"20:00","start_time":"13:00"},{"value":1,"end_time":"10:00","start_time":"20:00"},{"value":0,"end_time":"10:20","start_time":"10:00"},{"value":1,"end_time":"10:40","start_time":"10:20"},{"value":0,"end_time":"11:00","start_time":"10:40"},{"value":1,"end_time":"11:30","start_time":"11:00"},{"value":0,"end_time":"11:50","start_time":"11:30"},{"value":1,"end_time":"13:00","start_time":"11:50"}],"astro_clock":false,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' +// }, +// '3': { +// line: 3, +// tbname: 'vnmG4kJxaXWNBgMQq0D7Aj5e9oZzOAlr6LdR3w2V', +// contactor: 0, +// profile: '{"intervals":[{"value":0,"end_time":"20:30","start_time":"13:00"},{"value":1,"end_time":"00:10","start_time":"20:30"},{"value":0,"end_time":"13:00","start_time":"05:40"},{"value":1,"end_time":"05:40","start_time":"00:10"}],"astro_clock":true,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' +// } +// } + + + + + +// { +// "jbN4q7JPZmexgdnz2yKbWGDYAWwO0Q3BMX6ERLoV": [ +// { +// "ts": 1700409326353, +// "values": { +// "_event": { +// "type": "notice", +// "status": "new", +// "source": { +// "func": "rsPort.open()", +// "component": "1700343402190", +// "component_name": "DIDO_Controller", +// "edge": "jbN4q7JPZmexgdnz2yKbWGDYAWwO0Q3BMX6ERLoV" +// }, +// "message": "al_shariff_10.0.0.38: FLOW has been started ", +// "message_data": "" +// } +// } +// } +// ] +// } diff --git a/RVO34/flow/helper/DataToTbHandler.js b/RVO34/flow/helper/DataToTbHandler.js new file mode 100755 index 0000000..716ef7b --- /dev/null +++ b/RVO34/flow/helper/DataToTbHandler.js @@ -0,0 +1,187 @@ +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; + this.itIsNodeReadout = false; + this.sender = ""; + + // if attribute change difference is less than limit value, we do not send to tb. + this.attributeChangeLimit = { + temperature: 0.5, + Phase_1_voltage: 2, + Phase_2_voltage: 2, + Phase_3_voltage: 2, + Phase_1_current: 0.1, + Phase_2_current: 0.1, + Phase_3_current: 0.1, + Phase_1_power: 2, + Phase_2_power: 2, + Phase_3_power: 2, + total_power: 2, + total_energy: 1, + Phase_1_pow_factor: 0.1, + Phase_2_pow_factor: 0.1, + Phase_3_pow_factor: 0.1, + power_factor: 0.1, + lifetime: 2, + voltage: 2, + power: 2, + frequency: 3, + energy: 0.1, + current: 2, + inclination_x: 10, + inclination_y: 10, + inclination_z: 10 + }; + + } + + dump() { + console.log("----------------------------"); + console.log("previousValues", this.previousValues); + console.log("----------------------------"); + } + + setSender(sender) { + this.sender = sender; + } + + isEmptyObject(obj) { + for (var _ in obj) { + return false; + } + return true; + } + + + sendToTb(data, instance) { + + //not to modify data object, we do deep copy: + let dataCopy = JSON.parse(JSON.stringify(data)); + + let keys = Object.keys(dataCopy); + + if (keys.length == 0) { + if (this.debug) console.log("sendToTb received empty object", dataCopy); + return; + } + + let tbname = keys[0]; + let ts; + + let arrayOfValues = dataCopy[tbname]; + let arrayOfValuesToSend = []; + + for (let i = 0; i < arrayOfValues.length; i++) { + + ts = arrayOfValues[i].ts; + let values = this.prepareValuesForTb(tbname, ts, arrayOfValues[i].values); + + if (!this.isEmptyObject(values)) { + arrayOfValuesToSend.push({ ts: ts, values: values }); + } + + } + + if (arrayOfValuesToSend.length == 0) { + //if(this.debug) console.log("data not sent - empty array"); + return; + } + + this.messageCounter++; + + let dataToTbModified = { + [tbname]: arrayOfValuesToSend + } + + //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); + instance.send(this.index, dataToTbModified); + } + + + getDiffTimestamp(key) { + //TODO set different value for given key!!! + //if(key == "status") this.timeToHoldTbValue = 2*60*60;//2h + return this.timeToHoldTbValue * 1000; + } + + + prepareValuesForTb(tbname, timestamp, values) { + + let keys = Object.keys(values); + + if (keys.includes("lifetime")) this.itIsNodeReadout = true; + + if (!this.previousValues.hasOwnProperty(tbname)) { + this.previousValues[tbname] = {}; + } + + //if(this.debug) console.log("prepareValuesForTb", tbname, timestamp, values); + + for (let i = 0; i < keys.length; i++) { + + let key = keys[i]; + let value = values[key]; + + if (!this.previousValues[tbname].hasOwnProperty(key)) { + this.previousValues[tbname][key] = { ts: timestamp, value: value }; + continue; + } + + // attributeData ==> {voltage: {ts:333333, value:5}} + let attributeData = this.previousValues[tbname][key]; + let attributeToChange = false; + if (key in this.attributeChangeLimit) attributeToChange = true; + let limit = this.attributeChangeLimit[key]; + let timestampDiffToRemoveKey; + + //this will ensure "node statecode" will be sent just once an hour + if (this.itIsNodeReadout && key === "statecode") { + attributeData.value = value; + this.itIsNodeReadout = false; + timestampDiffToRemoveKey = 1 * 60 * 60 * 1000; // 1 hour + } + + if (key === "twilight_sensor" && value > 100) { + attributeData.value = value; + } + + //if edge, master or node version do not change, send just once a day: + if (["edge_fw_version", "master_node_version", "fw_version"].includes(key)) { + timestampDiffToRemoveKey = 24 * 60 * 60 * 1000; + } + + if (attributeData.value === value || attributeToChange && Math.abs(attributeData.value - value) < limit) { + + let diff = timestamp - attributeData.ts; + if (!timestampDiffToRemoveKey) timestampDiffToRemoveKey = this.getDiffTimestamp(key); + + if (diff > timestampDiffToRemoveKey) { + attributeData.ts = Date.now(); + //if(this.debug) console.log(this.sender + ": update ts for key", key, "diff is", diff, "messageCounter", this.messageCounter); + } + else { + delete values[key]; + //if(this.debug) console.log(this.sender + ": delete key", key, "diff is", diff, "messageCounter", this.messageCounter, timestampDiffToRemoveKey); + } + } + else { + attributeData.value = value; + attributeData.ts = timestamp; + } + + } + + return values; + } +} + +module.exports = DataToTbHandler; + diff --git a/RVO34/flow/helper/ErrorToServiceHandler.js b/RVO34/flow/helper/ErrorToServiceHandler.js new file mode 100755 index 0000000..2b27c32 --- /dev/null +++ b/RVO34/flow/helper/ErrorToServiceHandler.js @@ -0,0 +1,91 @@ +const { MD5 } = require('./md5.js'); +const { networkInterfaces } = require('os'); + +class ErrorToServiceHandler { + constructor() { + this.previousValues = {}; + + this.project_id = undefined; + + const nets = networkInterfaces(); + this.ipAddresses = {}; + + for (const name of Object.keys(nets)) { + for (const net of nets[name]) { + // Skip over non-IPv4 and internal (i.e. 127.0.0.1) addresses + if (net.family === 'IPv4' && !net.internal) { + if (!this.ipAddresses[name]) { + this.ipAddresses[name] = []; + } + this.ipAddresses[name].push(net.address); + } + } + } + } + + setProjectId(project_id) { + this.project_id = project_id; + } + + processMessage(message, seconds) { + if (Array.isArray(message)) message = message.join(', '); + + let key = MD5(message); + let ts = Date.now(); + + //keep in memory - default value is 1h + if (seconds === undefined) seconds = 60 * 60; + + if (!this.previousValues.hasOwnProperty(key)) { + this.previousValues[key] = { ts: ts, duration: seconds }; + } + + let diff = (ts - this.previousValues[key].ts); + if (diff < this.previousValues[key].duration * 1000) return false; + + this.previousValues[key].ts = ts; + + return message; + } + + sendMessageToService(message, seconds, message_type) { + + // if error occures too early FLOW.GLOBALS.settings.project_id is still undefined + if (this.project_id === undefined) { + console.log("ErrorToServiceHandler.js: no project_id"); + return; + } + + let f = this.processMessage(message, seconds); + if (f === false) return; + + if (message_type === undefined) message_type = "error_message"; + + let toService = { + id: this.project_id, + ipAddresses: this.ipAddresses + }; + + //js_error || error_message + toService[message_type] = message; + + console.log("ErrorToServiceHandler------------------------>send to service", toService); + + RESTBuilder.make(function(builder) { + builder.method('POST'); + builder.post(toService); + builder.url('http://192.168.252.2:8004/sentmessage'); + + builder.callback(function(err, response, output) { + console.log("process.on error send", err, response, output, toService); + }); + }); + + } +} + +const errorHandler = new ErrorToServiceHandler(); + + +module.exports = errorHandler; +//module.exports = ErrorToServiceHandler; diff --git a/RVO34/flow/helper/db_helper.js b/RVO34/flow/helper/db_helper.js new file mode 100755 index 0000000..40e796c --- /dev/null +++ b/RVO34/flow/helper/db_helper.js @@ -0,0 +1,44 @@ +function promisifyBuilder(builder) +{ + return new Promise((resolve, reject) => { + + try{ + + builder.callback(function(err, response) { + + if(err != null) reject(err); + resolve(response); + }); + + } catch (error) { + reject(error); + } + }) +} + +function makeMapFromDbResult(response, ...keys) +{ + let s = "-"; + let data = {}; + + for(let i = 0; i < response.length; i++) + { + let record = response[i]; + + let k = []; + for(let j = 0; j < keys.length; j++) + { + k.push( record[keys[j]] ); + } + + let key = k.join(s); + data[ key ] = record; + } + + return data; +} + +module.exports = { + promisifyBuilder, + makeMapFromDbResult + } \ No newline at end of file diff --git a/RVO34/flow/helper/logger.js b/RVO34/flow/helper/logger.js new file mode 100755 index 0000000..2585639 --- /dev/null +++ b/RVO34/flow/helper/logger.js @@ -0,0 +1,30 @@ +//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/RVO34/flow/helper/md5.js b/RVO34/flow/helper/md5.js new file mode 100755 index 0000000..d3b0480 --- /dev/null +++ b/RVO34/flow/helper/md5.js @@ -0,0 +1,5 @@ +function MD5(d){var r = M(V(Y(X(d),8*d.length)));return r.toLowerCase()};function M(d){for(var _,m="0123456789ABCDEF",f="",r=0;r>>4&15)+m.charAt(15&_);return f}function X(d){for(var _=Array(d.length>>2),m=0;m<_.length;m++)_[m]=0;for(m=0;m<8*d.length;m+=8)_[m>>5]|=(255&d.charCodeAt(m/8))<>5]>>>m%32&255);return _}function Y(d,_){d[_>>5]|=128<<_%32,d[14+(_+64>>>9<<4)]=_;for(var m=1732584193,f=-271733879,r=-1732584194,i=271733878,n=0;n>16)+(_>>16)+(m>>16)<<16|65535&m}function bit_rol(d,_){return d<<_|d>>>32-_} + +module.exports = { + MD5 +} \ No newline at end of file diff --git a/RVO34/flow/helper/notification_reporter.js b/RVO34/flow/helper/notification_reporter.js new file mode 100755 index 0000000..839c12c --- /dev/null +++ b/RVO34/flow/helper/notification_reporter.js @@ -0,0 +1,121 @@ +//key is device, value = message {} +let sentValues = {}; +let notificationsData = null; +let rvoName; + +//sendNotification("CMD Manager: process cmd", SETTINGS.rvoTbName, "dimming_profile_was_successfully_received_by_node", { node: node }, "", SEND_TO.tb, instance); + +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 +}; + +function getKey(map, val) { + return Object.keys(map).findItem(key => map[key] === val); +} + +//https://stackoverflow.com/questions/41117799/string-interpolation-on-variable +var template = (tpl, args) => tpl.replace(/\${(\w+)}/g, (_, v) => args[v]); + + +function initNotification() { + notificationsData = FLOW.GLOBALS.notificationsData; + rvoName = FLOW.GLOBALS.settings.rvo_name; +} + + +function sendNotification(func, device, key, params, extra, tb_output, instance, saveKey) { + + let storeToSendValues = true; + if (saveKey == undefined) storeToSendValues = false; + + let weight = ""; + let message = {}; + + let notification = notificationsData[key]; + + if (notification) { + weight = notification.weight.toLowerCase(); + + Object.keys(notification).forEach(item => { + if (["en", "sk", "de", "cz", "it", "es"].includes(item)) { + message[item] = rvoName + ": " + template(notification[item], params); + } + }) + } + else { + //console.error("sendNotification: Notifications: undefined key", key, func, notificationsData); + console.error("sendNotification: Notifications: undefined key", key, func); + return false; + } + + //detect invalid err weight + if (getKey(ERRWEIGHT, weight) == undefined) { + console.error("sendNotification: Notifications: undefined weight", weight, key, func); + return false; + } + + if (sentValues.hasOwnProperty(saveKey)) { + if (JSON.stringify(sentValues[saveKey]) == JSON.stringify(message)) { + return false; + } + } + + if (sentValues[saveKey] == undefined) { + if (storeToSendValues) { + //do not send - flow is was started + sentValues[saveKey] = message; + return false; + } + } + + if (storeToSendValues) sentValues[saveKey] = message; + + let content = { + "type": weight, + "status": "new", + "source": { + "func": func, + "component": instance.id, + "component_name": instance.name, + "edge": device + }, + "message": message, + "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 + + return true; + +} + +module.exports = { + sendNotification, + ERRWEIGHT, + initNotification +} + diff --git a/RVO34/flow/helper/register.js b/RVO34/flow/helper/register.js new file mode 100755 index 0000000..fc1d008 --- /dev/null +++ b/RVO34/flow/helper/register.js @@ -0,0 +1,144 @@ +/* +0 - cislo registra / prikaz +1 - recepient - 0 = master, 1 = slave (slave je automaticky group a broadcast) +2 - r/rw - read/write +3- register name - nazov registra / prikazu (len pre info - zobrazenie v aplikacii) + +4,5,6,7, - jednotlive byte-y - nazov byte-u +4-7 - RES. a prazdny string "" sa nezobrazia!!! +*/ + +//124 zaznamov +const registers = [ + ["0","1","R","Status","","",""], + ["1","1","RW","Dimming","R-Channel ","G-Channel","B-Channel ","W - Channel"], + ["2","1","R","Device types","","",".",""], + ["3","1","RW","Group addresses 1-4","Groups Add. 4","Groups Add. 3","Groups Add. 2","Groups Add. 1"], + ["4","1","RW","Group addresses 5-8","Groups Add. 8","Groups Add. 7","Groups Add. 6","Groups Add. 5"], + ["5","1","RW","Serial number (MAC)","","","",""], + ["6","1","RW","Time of dusk","HH","MM","SS","EXTRA"], + ["7","1","RW","Time of dawn","HH","MM","SS","EXTRA"], + ["8","1","RW","Time Schedule settings","TBD","TBD","Movement sensor","Time Schedule"], + ["9","1","RW","TS1 Time point 1","HH","MM","SS","Ext. Device"], + ["10","1","RW","TS1 Time point 1 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["11","1","RW","TS1 Time point 2","HH","MM","SS","Ext. Device"], + ["12","1","RW","TS1 Time point 2 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["13","1","RW","TS1 Time point 3","HH","MM","SS","Ext. Device"], + ["14","1","RW","TS1 Time point 3 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["15","1","RW","TS1 Time point 4","HH","MM","SS","Ext. Device"], + ["16","1","RW","TS1 Time point 4 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["17","1","RW","TS1 Time point 5","HH","MM","SS","Ext. Device"], + ["18","1","RW","TS1 Time point 5 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["19","1","RW","TS1 Time point 6","HH","MM","SS","Ext. Device"], + ["20","1","RW","TS1 Time point 6 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["21","1","RW","TS1 Time point 7","HH","MM","SS","Ext. Device"], + ["22","1","RW","TS1 Time point 7 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["23","1","RW","TS1 Time point 8","HH","MM","SS","Ext. Device"], + ["24","1","RW","TS1 Time point 8 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["25","1","RW","TS1 Time point 9","HH","MM","SS","Ext. Device"], + ["26","1","RW","TS1 Time point 9 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["27","1","RW","TS1 Time point 10","HH","MM","SS","Ext. Device"], + ["28","1","RW","TS1 Time point 10 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["29","1","RW","TS1 Time point 11","HH","MM","SS","Ext. Device"], + ["30","1","RW","TS1 Time point 11 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["31","1","RW","TS1 Time point 12","HH","MM","SS","Ext. Device"], + ["32","1","RW","TS1 Time point 12 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["33","1","RW","TS1 Time point 13","HH","MM","SS","Ext. Device"], + ["34","1","RW","TS1 Time point 13 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["35","1","RW","TS1 Time point 14","HH","MM","SS","Ext. Device"], + ["36","1","RW","TS1 Time point 14 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["37","1","RW","TS1 Time point 15","HH","MM","SS","Ext. Device"], + ["38","1","RW","TS1 Time point 15 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["39","1","RW","TS1 Time point 16","HH","MM","SS","Ext. Device"], + ["40","1","RW","TS1 Time point 16 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["41","1","RW","TS2 Time point 1","HH","MM","SS","Ext. Device"], + ["42","1","RW","TS2 Time point 1 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["43","1","RW","TS2 Time point 2","HH","MM","SS","Ext. Device"], + ["44","1","RW","TS2 Time point 2 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["45","1","RW","TS2 Time point 3","HH","MM","SS","Ext. Device"], + ["46","1","RW","TS2 Time point 3 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["47","1","RW","TS2 Time point 4","HH","MM","SS","Ext. Device"], + ["48","1","RW","TS2 Time point 4 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["49","1","RW","TS2 Time point 5","HH","MM","SS","Ext. Device"], + ["50","1","RW","TS2 Time point 5 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["51","1","RW","TS2 Time point 6","HH","MM","SS","Ext. Device"], + ["52","1","RW","TS2 Time point 6 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["53","1","RW","TS2 Time point 7","HH","MM","SS","Ext. Device"], + ["54","1","RW","TS2 Time point 7 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["55","1","RW","TS2 Time point 8","HH","MM","SS","Ext. Device"], + ["56","1","RW","TS2 Time point 8 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["57","1","RW","TS2 Time point 9","HH","MM","SS","Ext. Device"], + ["58","1","RW","TS2 Time point 9 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["59","1","RW","TS2 Time point 10","HH","MM","SS","Ext. Device"], + ["60","1","RW","TS2 Time point 10 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["61","1","RW","TS2 Time point 11","HH","MM","SS","Ext. Device"], + ["62","1","RW","TS2 Time point 11 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["63","1","RW","TS2 Time point 12","HH","MM","SS","Ext. Device"], + ["64","1","RW","TS2 Time point 12 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["65","1","RW","TS2 Time point 13","HH","MM","SS","Ext. Device"], + ["66","1","RW","TS2 Time point 13 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["67","1","RW","TS2 Time point 14","HH","MM","SS","Ext. Device"], + ["68","1","RW","TS2 Time point 14 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["69","1","RW","TS2 Time point 15","HH","MM","SS","Ext. Device"], + ["70","1","RW","TS2 Time point 15 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["71","1","RW","TS2 Time point 16","HH","MM","SS","Ext. Device"], + ["72","1","RW","TS2 Time point 16 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["73","1","RW","Power meter status","TBD","","",""], + ["74","1","R","Input Voltage","","","",""], + ["75","1","R","Input Current","","","",""], + ["76","1","R","Input Power","","","",""], + ["77","1","R","Cos phi","","","",""], + ["78","1","R","Frequency","","","",""], + ["79","1","RW","Energy","","","",""], + ["80","1","RW","Lifetime","","","",""], + ["81","1","RW","Power on cycles (input)","","","",""], + ["82","1","RW","Power on cycles (relay)","","","",""], + ["83","1","R","Time since last power on","","","",""], + ["84","1","R","Accelerometer data","","","",""], + ["85","1","RW","GPS latitude","pos/neg","deg","min ","sec"], + ["86","1","RW","GPS longitude","pos/neg","deg","min ","sec"], + ["87","1","RW","Actual time","HH","MM","SS","RES."], + ["88","1","RW","Actual date","Day of week","Day","Month","Year"], + ["89","1","R","Production data 1","","","",""], + ["90","1","R","Production data 2","","","",""], + ["91","1","RW","Network ID","NID3","NID2","NID1","NID0"], + ["95","1","RW","Actual Lux level from cabinet","RES.","RES.","HB","LB"], + ["96","1","RW","Threshold lux level","Dusk HB","Dusk LB","Dawn HB","Dawn LB"], + ["97","1","RW","Adjust period","Dusk HB","Dusk LB","Dawn HB","Dawn LB"], + ["98","1","RW","Offset","RES.","RES.","Dusk","Dawn"], + ["99","1","RW","CCT min/max range","max-H","max-L","min-H","min-L"], + ["100","1","RW","DALI interface","Cmd ID","Add","Cmd","Resp"], + ["101","1","RW","Module FW ver","v1","v2","v3","v4"], + ["102","1","RW","Module MAC-H","unused","unused","M1","M2"], + ["103","1","RW","Module MAC-L","M3","M4","M5","M6"], + ["122","1","R","FW update status/control register","Byte3","Byte2","Byte1","Byte0"], + ["123","1","R","FW update - data index","Byte3","Byte2","Byte1","Byte0"], + ["124","1","R","FW update - data","Byte3","Byte2","Byte1","Byte0"], + ["0","0","R","Status","","","",""], + ["1","0","RW","Control register","RES.","RES.","RES.","init mode enable"], + ["2","0","R","Device types","","","",""], + ["3","0","R","Serial number (MAC)","","","",""], + ["4","0","R","Production data 1","","","",""], + ["5","0","R","Production data 2","","","",""], + ["6","0","RW","Network ID","NID3","NID2","NID1","NID0"], + ["7","0","RW","RS232 settings","param.","param.","Baudrate H","Baudrate L"], + ["8","0","R","Accelerometer data","","","",""], + ["9","0","RW","Module FW ver","v1","v2","v3","v4"], + ["10","0","RW","Module MAC-H","unused","unused","M1","M2"], + ["11","0","RW","Module MAC-L","M3","M4","M5","M6"], + ["32","0","RW","FW update status/control register","Byte3","Byte2","Byte1","Byte0"], + ["33","0","RW","FW update - data index","Byte3","Byte2","Byte1","Byte0"], + ["34","0","RW","FW update - data","Byte3","Byte2","Byte1","Byte0"], + ["125","0","RW","Debug Register","Byte3","Byte2","Byte1","Byte0"], + ["126","0","RW","Network Control Register","Byte3","Byte2","Byte1","Byte0"], + ["127","0","R","Network Status Register","Byte3","Byte2","Byte1","Byte0"], + ["128","0","RW","Node XX Serial Number Register","SER3","SER2","SER1","SER0"], + ["256","0","R","Node XX Network Status Register","","","",""] +]; + +let register = {}; + +module.exports = { + registers, + register +} \ No newline at end of file diff --git a/RVO34/flow/helper/serialport_helper.js b/RVO34/flow/helper/serialport_helper.js new file mode 100755 index 0000000..7f5920d --- /dev/null +++ b/RVO34/flow/helper/serialport_helper.js @@ -0,0 +1,99 @@ +const { exec } = require('child_process'); + +function openPort(port) { + return new Promise((resolve, reject) => { + + var callbackError = function(err) { + port.removeListener('error', callbackError); + port.removeListener('open', callbackError); + + reject(err.message); + }; + + var callbackOpen = function(data) { + port.removeListener('error', callbackError); + port.removeListener('open', callbackOpen); + + resolve("port open: ok"); + }; + + port.on('error', callbackError); + port.on('open', callbackOpen); + + port.open(); + + }) +} + +function runSyncExec(command) { + return new Promise((resolve, reject) => { + + exec(command, (error, stdout, stderr) => { + if (error == null) resolve(stdout); + reject(error); + }); + + }) +} + +async function writeData(port, data, readbytes, timeout) { + return new Promise((resolve, reject) => { + + // 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) { + + port.write(Buffer.from(data), function(err) { + if (err) { + reject(err.message); + } + }); + + 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 +} diff --git a/RVO34/flow/helper/suncalc.js b/RVO34/flow/helper/suncalc.js new file mode 100755 index 0000000..c9ca56d --- /dev/null +++ b/RVO34/flow/helper/suncalc.js @@ -0,0 +1,317 @@ +/* + (c) 2011-2015, Vladimir Agafonkin + SunCalc is a JavaScript library for calculating sun/moon position and light phases. + https://github.com/mourner/suncalc +*/ + +(function () { 'use strict'; + +// shortcuts for easier to read formulas + +var PI = Math.PI, + sin = Math.sin, + cos = Math.cos, + tan = Math.tan, + asin = Math.asin, + atan = Math.atan2, + acos = Math.acos, + rad = PI / 180; + +// sun calculations are based on http://aa.quae.nl/en/reken/zonpositie.html formulas + + +// date/time constants and conversions + +var dayMs = 1000 * 60 * 60 * 24, + J1970 = 2440588, + J2000 = 2451545; + +function toJulian(date) { return date.valueOf() / dayMs - 0.5 + J1970; } +function fromJulian(j) { return new Date((j + 0.5 - J1970) * dayMs); } +function toDays(date) { return toJulian(date) - J2000; } + + +// general calculations for position + +var e = rad * 23.4397; // obliquity of the Earth + +function rightAscension(l, b) { return atan(sin(l) * cos(e) - tan(b) * sin(e), cos(l)); } +function declination(l, b) { return asin(sin(b) * cos(e) + cos(b) * sin(e) * sin(l)); } + +function azimuth(H, phi, dec) { return atan(sin(H), cos(H) * sin(phi) - tan(dec) * cos(phi)); } +function altitude(H, phi, dec) { return asin(sin(phi) * sin(dec) + cos(phi) * cos(dec) * cos(H)); } + +function siderealTime(d, lw) { return rad * (280.16 + 360.9856235 * d) - lw; } + +function astroRefraction(h) { + if (h < 0) // the following formula works for positive altitudes only. + h = 0; // if h = -0.08901179 a div/0 would occur. + + // formula 16.4 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + // 1.02 / tan(h + 10.26 / (h + 5.10)) h in degrees, result in arc minutes -> converted to rad: + return 0.0002967 / Math.tan(h + 0.00312536 / (h + 0.08901179)); +} + +// general sun calculations + +function solarMeanAnomaly(d) { return rad * (357.5291 + 0.98560028 * d); } + +function eclipticLongitude(M) { + + var C = rad * (1.9148 * sin(M) + 0.02 * sin(2 * M) + 0.0003 * sin(3 * M)), // equation of center + P = rad * 102.9372; // perihelion of the Earth + + return M + C + P + PI; +} + +function sunCoords(d) { + + var M = solarMeanAnomaly(d), + L = eclipticLongitude(M); + + return { + dec: declination(L, 0), + ra: rightAscension(L, 0) + }; +} + + +var SunCalc = {}; + + +// calculates sun position for a given date and latitude/longitude + +SunCalc.getPosition = function (date, lat, lng) { + + var lw = rad * -lng, + phi = rad * lat, + d = toDays(date), + + c = sunCoords(d), + H = siderealTime(d, lw) - c.ra; + + return { + azimuth: azimuth(H, phi, c.dec), + altitude: altitude(H, phi, c.dec) + }; +}; + + +// sun times configuration (angle, morning name, evening name) + +var times = SunCalc.times = [ + [-0.833, 'sunrise', 'sunset' ], + [ -0.3, 'sunriseEnd', 'sunsetStart' ], + [ -6, 'dawn', 'dusk' ], + [ -12, 'nauticalDawn', 'nauticalDusk'], + [ -18, 'nightEnd', 'night' ], + [ 6, 'goldenHourEnd', 'goldenHour' ] +]; + +// adds a custom time to the times config + +SunCalc.addTime = function (angle, riseName, setName) { + times.push([angle, riseName, setName]); +}; + + +// calculations for sun times + +var J0 = 0.0009; + +function julianCycle(d, lw) { return Math.round(d - J0 - lw / (2 * PI)); } + +function approxTransit(Ht, lw, n) { return J0 + (Ht + lw) / (2 * PI) + n; } +function solarTransitJ(ds, M, L) { return J2000 + ds + 0.0053 * sin(M) - 0.0069 * sin(2 * L); } + +function hourAngle(h, phi, d) { return acos((sin(h) - sin(phi) * sin(d)) / (cos(phi) * cos(d))); } +function observerAngle(height) { return -2.076 * Math.sqrt(height) / 60; } + +// returns set time for the given sun altitude +function getSetJ(h, lw, phi, dec, n, M, L) { + + var w = hourAngle(h, phi, dec), + a = approxTransit(w, lw, n); + return solarTransitJ(a, M, L); +} + + +// calculates sun times for a given date, latitude/longitude, and, optionally, +// the observer height (in meters) relative to the horizon + +SunCalc.getTimes = function (date, lat, lng, height) { + + height = height || 0; + + var lw = rad * -lng, + phi = rad * lat, + + dh = observerAngle(height), + + d = toDays(date), + n = julianCycle(d, lw), + ds = approxTransit(0, lw, n), + + M = solarMeanAnomaly(ds), + L = eclipticLongitude(M), + dec = declination(L, 0), + + Jnoon = solarTransitJ(ds, M, L), + + i, len, time, h0, Jset, Jrise; + + + var result = { + solarNoon: fromJulian(Jnoon), + nadir: fromJulian(Jnoon - 0.5) + }; + + for (i = 0, len = times.length; i < len; i += 1) { + time = times[i]; + h0 = (time[0] + dh) * rad; + + Jset = getSetJ(h0, lw, phi, dec, n, M, L); + Jrise = Jnoon - (Jset - Jnoon); + + result[time[1]] = fromJulian(Jrise); + result[time[2]] = fromJulian(Jset); + } + + return result; +}; + + +// moon calculations, based on http://aa.quae.nl/en/reken/hemelpositie.html formulas + +function moonCoords(d) { // geocentric ecliptic coordinates of the moon + + var L = rad * (218.316 + 13.176396 * d), // ecliptic longitude + M = rad * (134.963 + 13.064993 * d), // mean anomaly + F = rad * (93.272 + 13.229350 * d), // mean distance + + l = L + rad * 6.289 * sin(M), // longitude + b = rad * 5.128 * sin(F), // latitude + dt = 385001 - 20905 * cos(M); // distance to the moon in km + + return { + ra: rightAscension(l, b), + dec: declination(l, b), + dist: dt + }; +} + +SunCalc.getMoonPosition = function (date, lat, lng) { + + var lw = rad * -lng, + phi = rad * lat, + d = toDays(date), + + c = moonCoords(d), + H = siderealTime(d, lw) - c.ra, + h = altitude(H, phi, c.dec), + // formula 14.1 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + pa = atan(sin(H), tan(phi) * cos(c.dec) - sin(c.dec) * cos(H)); + + h = h + astroRefraction(h); // altitude correction for refraction + + return { + azimuth: azimuth(H, phi, c.dec), + altitude: h, + distance: c.dist, + parallacticAngle: pa + }; +}; + + +// calculations for illumination parameters of the moon, +// based on http://idlastro.gsfc.nasa.gov/ftp/pro/astro/mphase.pro formulas and +// Chapter 48 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + +SunCalc.getMoonIllumination = function (date) { + + var d = toDays(date || new Date()), + s = sunCoords(d), + m = moonCoords(d), + + sdist = 149598000, // distance from Earth to Sun in km + + phi = acos(sin(s.dec) * sin(m.dec) + cos(s.dec) * cos(m.dec) * cos(s.ra - m.ra)), + inc = atan(sdist * sin(phi), m.dist - sdist * cos(phi)), + angle = atan(cos(s.dec) * sin(s.ra - m.ra), sin(s.dec) * cos(m.dec) - + cos(s.dec) * sin(m.dec) * cos(s.ra - m.ra)); + + return { + fraction: (1 + cos(inc)) / 2, + phase: 0.5 + 0.5 * inc * (angle < 0 ? -1 : 1) / Math.PI, + angle: angle + }; +}; + + +function hoursLater(date, h) { + return new Date(date.valueOf() + h * dayMs / 24); +} + +// calculations for moon rise/set times are based on http://www.stargazing.net/kepler/moonrise.html article + +SunCalc.getMoonTimes = function (date, lat, lng, inUTC) { + var t = new Date(date); + if (inUTC) t.setUTCHours(0, 0, 0, 0); + else t.setHours(0, 0, 0, 0); + + var hc = 0.133 * rad, + h0 = SunCalc.getMoonPosition(t, lat, lng).altitude - hc, + h1, h2, rise, set, a, b, xe, ye, d, roots, x1, x2, dx; + + // go in 2-hour chunks, each time seeing if a 3-point quadratic curve crosses zero (which means rise or set) + for (var i = 1; i <= 24; i += 2) { + h1 = SunCalc.getMoonPosition(hoursLater(t, i), lat, lng).altitude - hc; + h2 = SunCalc.getMoonPosition(hoursLater(t, i + 1), lat, lng).altitude - hc; + + a = (h0 + h2) / 2 - h1; + b = (h2 - h0) / 2; + xe = -b / (2 * a); + ye = (a * xe + b) * xe + h1; + d = b * b - 4 * a * h1; + roots = 0; + + if (d >= 0) { + dx = Math.sqrt(d) / (Math.abs(a) * 2); + x1 = xe - dx; + x2 = xe + dx; + if (Math.abs(x1) <= 1) roots++; + if (Math.abs(x2) <= 1) roots++; + if (x1 < -1) x1 = x2; + } + + if (roots === 1) { + if (h0 < 0) rise = i + x1; + else set = i + x1; + + } else if (roots === 2) { + rise = i + (ye < 0 ? x2 : x1); + set = i + (ye < 0 ? x1 : x2); + } + + if (rise && set) break; + + h0 = h2; + } + + var result = {}; + + if (rise) result.rise = hoursLater(t, rise); + if (set) result.set = hoursLater(t, set); + + if (!rise && !set) result[ye > 0 ? 'alwaysUp' : 'alwaysDown'] = true; + + return result; +}; + + +// export as Node module / AMD module / browser variable +if (typeof exports === 'object' && typeof module !== 'undefined') module.exports = SunCalc; +else if (typeof define === 'function' && define.amd) define(SunCalc); +else window.SunCalc = SunCalc; + +}()); diff --git a/RVO34/flow/helper/utils.js b/RVO34/flow/helper/utils.js new file mode 100755 index 0000000..dbffe45 --- /dev/null +++ b/RVO34/flow/helper/utils.js @@ -0,0 +1,161 @@ +const fs = require('fs').promises; + +function bytesToInt(bytes, numberOfBytes) { + let buffer = []; + if (Array.isArray(bytes)) { + buffer = bytes.slice(0); + if (numberOfBytes != undefined) { + buffer = bytes.slice(bytes.length - numberOfBytes); + } + } + else buffer.push(bytes); + + let result = 0; + for (let i = 0; i < buffer.length; i++) { + result = (result << 8) | buffer[i]; + } + + return result >>> 0; //ensure it's an unsigned 32-bit number +} + +function resizeArray(arr, newSize, defaultValue) { + while (newSize > arr.length) + arr.push(defaultValue); + arr.length = newSize; +} + +longToByteArray = function(/*long*/long) { + // we want to represent the input as a 8-bytes array + var byteArray = [0, 0, 0, 0, 0, 0, 0, 0]; + + for (var index = 0; index < byteArray.length; index++) { + var byte = long & 0xff; + byteArray[index] = byte; + long = (long - byte) / 256; + } + + return byteArray; +}; + +function addDays(date, days) { + var result = new Date(date); + result.setDate(result.getDate() + days); + return result; +} + +/* +sleep(2000).then(() => { + // Do something after the sleep! + + +}); +*/ + +function sleep(time) { + return new Promise((resolve) => setTimeout(resolve, time)); +} + +function isEmptyObject(obj) { + for (var name in obj) { + return false; + } + return true; +} + +function emptyJsObject(jsObject) { + Object.keys(jsObject).forEach(key => delete jsObject[key]); +} + +function convertUTCDateToLocalDate(date) { + var newDate = new Date(date); + newDate.setMinutes(date.getMinutes() + date.getTimezoneOffset()); + return newDate; +} + +function addZeroBefore(n) { + return (n < 10 ? '0' : '') + n; +} + + +/** + * Asynchronously writes data to a file. + * + * @param {string} filePath The path to the file. + * @param {string} data The data to write to the file. + * @param {boolean} [append=false] If true, appends the data to the file. If false, it overwrites the file. + */ +async function writeToFile(filePath, data, append = false) { + if (typeof data !== 'string') data = JSON.stringify(data, null, 2); + try { + if (append) { + // Append the data to the end of the file. This is the simplest way to append. + await fs.appendFile(filePath, data, 'utf8'); + console.log(`Successfully appended data to ${filePath} using fs.appendFile.`); + } else { + // Overwrite the file with the new data. + await fs.writeFile(filePath, data, 'utf8'); + console.log(`Successfully wrote (overwrote) data to ${filePath} using fs.writeFile.`); + } + } catch (error) { + console.error(`Error writing to file ${filePath}:`, error); + } +} + + + /** + * Checks if an item is present in an array and adds it if it's not. + * * @param {Array} arr The array to check. + * @param {*} item The item to add. + * @returns {Array} The modified array. + */ +const addToArrayIfUnique = (arr, item) => { + if (!arr.includes(item)) { + arr.push(item); + } + return arr; +}; + + +var convertBase = function() { + + function convertBase(baseFrom, baseTo) { + return function(num) { + return parseInt(num, baseFrom).toString(baseTo); + + }; + } + + // binary to decimal + convertBase.bin2dec = convertBase(2, 10); + + // binary to hexadecimal + convertBase.bin2hex = convertBase(2, 16); + + // decimal to binary + convertBase.dec2bin = convertBase(10, 2); + + // decimal to hexadecimal + convertBase.dec2hex = convertBase(10, 16); + + // hexadecimal to binary + convertBase.hex2bin = convertBase(16, 2); + + // hexadecimal to decimal + convertBase.hex2dec = convertBase(16, 10); + + return convertBase; +}(); + +module.exports = { + bytesToInt, + longToByteArray, + addDays, + addZeroBefore, + resizeArray, + isEmptyObject, + emptyJsObject, + sleep, + convertUTCDateToLocalDate, + writeToFile, + addToArrayIfUnique +} diff --git a/RVO34/flow/httprequest.js b/RVO34/flow/httprequest.js new file mode 100755 index 0000000..469c8cb --- /dev/null +++ b/RVO34/flow/httprequest.js @@ -0,0 +1,137 @@ +exports.id = 'httprequest'; +exports.title = 'HTTP Request'; +exports.group = 'HTTP'; +exports.color = '#5D9CEC'; +exports.input = true; +exports.version = '2.0.1'; +exports.output = 1; +exports.author = 'Peter Širka'; +exports.icon = 'cloud-upload'; + +exports.html = `
+
@(URL address)
+
+
+
@(HTTP method)
+
+
+
@(Serialization)
+
+
+
@(Download the content in chunks)
+
@(Keep persistent cookies)
+
@(Disable DNS cache)
+
@(Keep alive connection)
+
+
+
+
@(Custom headers)
+
@(Cookies)
+
+
+
+ +
+
+
+
@(User)
+
+
+
@(Password)
+
+
+
+
+
`; + +exports.readme = `# Request + +This component creates a request with received data. + +__Response:__ +\`\`\`javascript +{ + data: String, + headers: Object, + status: Number, + host: String +} +\`\`\` + +__Dynamic arguments__: +Are performed via FlowData repository and can be used for URL address or for custom headers/cookies/auth. Use \`repository\` component for creating of dynamic arguments. Dynamic values are replaced in the form \`{key}\`: + +- url address e.g. \`https://.../{key}/\` +- headers values e.g. \`{token}\` +- cookies values e.g. \`{token}\``; + +exports.install = function(instance) { + + var can = false; + var flags = null; + var cookies2 = null; + + instance.on('data', function(response) { + can && instance.custom.send(response); + }); + + instance.custom.send = function(response) { + var options = instance.options; + + var headers = null; + var cookies = null; + + options.headers && Object.keys(options.headers).forEach(function(key) { + !headers && (headers = {}); + headers[key] = response.arg(options.headers[key]); + }); + + if (options.username && options.userpassword) { + !headers && (headers = {}); + headers['Authorization'] = 'Basic ' + U.createBuffer(response.arg(options.username + ':' + options.userpassword)).toString('base64'); + } + + options.cookies && Object.keys(options.cookies).forEach(function(key) { + !cookies && (cookies = {}); + cookies[key] = response.arg(options.cookies[key]); + }); + + if (options.chunks) { + U.download(response.arg(options.url), flags, options.stringify === 'none' ? null : response.data, function(err, response) { + response.on('data', (chunks) => instance.send2(chunks)); + }, cookies || cookies2, headers); + } else { + U.request(response.arg(options.url), flags, options.stringify === 'none' ? null : response.data, 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) + instance.error(err, response); + }, cookies || cookies2, headers); + } + }; + + instance.reconfigure = function() { + var options = instance.options; + can = options.url && options.url && options.method && options.stringify ? true : false; + instance.status(can ? '' : 'Not configured', can ? undefined : 'red'); + + if (!can) + return; + + flags = []; + flags.push(options.method.toLowerCase()); + options.stringify === 'json' && flags.push('json'); + options.stringify === 'raw' && flags.push('raw'); + options.keepalive && flags.push('keepalive'); + !options.nodns && flags.push('dnscache'); + if (options.persistentcookies) { + flags.push('cookies'); + cookies2 = {}; + } else + cookies2 = null; + }; + + instance.on('options', instance.reconfigure); + instance.reconfigure(); +}; \ No newline at end of file diff --git a/RVO34/flow/httpresponse.js b/RVO34/flow/httpresponse.js new file mode 100755 index 0000000..160a3bb --- /dev/null +++ b/RVO34/flow/httpresponse.js @@ -0,0 +1,76 @@ +exports.id = 'httpresponse'; +exports.title = 'HTTP Response'; +exports.group = 'HTTP'; +exports.color = '#5D9CEC'; +exports.icon = 'arrow-right'; +exports.input = true; +exports.output = ['#666D76']; +exports.version = '2.0.0'; +exports.author = 'Martin Smola'; +exports.readme = `# HTTP response + +HTTP response will respond with data recieved using data-type set in Settings form or plain text if not set. Output is the message duration \`Number\` in seconds.`; + +exports.html = `
+
@(Response data-type)
+
JSON is by default.
+
`; + +exports.install = function(instance) { + + var dursum = 0; + var durcount = 0; + + instance.on('data', function(flowdata) { + + var ctrl = flowdata.repository.controller; + var data = flowdata.data; + + if (!ctrl) { + instance.throw('No controller to use for response!'); + return; + } + + durcount++; + dursum += ((new Date() - flowdata.begin) / 1000).floor(2); + setTimeout2(instance.id, instance.custom.duration, 500, 10); + + ctrl.$flowdata = flowdata; + + var datatype = instance.options.datatype || 'json'; + if (datatype === 'emptyresponse') + return ctrl.plain(''); + + if (datatype !== 'json' && typeof(data) !== 'string') { + instance.throw('Incorect type of data, expected string, got ' + typeof(data)); + ctrl.plain(data == null ? '' : data.toString()); + return; + } + + switch(datatype) { + case 'html': + ctrl.content(data, 'text/html'); + break; + case 'plain': + ctrl.plain(data); + break; + case 'xml': + ctrl.content(data, 'text/xml'); + break; + default: + ctrl.json(data); + break; + } + }); + + instance.on('service', function() { + dursum = 0; + durcount = 0; + }); + + instance.custom.duration = function() { + var avg = (dursum / durcount).floor(2); + instance.status(avg + ' sec.'); + instance.send2(0, avg); + }; +}; diff --git a/RVO34/flow/httproute.js b/RVO34/flow/httproute.js new file mode 100755 index 0000000..583a19d --- /dev/null +++ b/RVO34/flow/httproute.js @@ -0,0 +1,326 @@ +exports.id = 'httproute'; +exports.title = 'HTTP Route'; +exports.group = 'HTTP'; +exports.color = '#5D9CEC'; +exports.icon = 'globe'; +exports.input = false; +exports.output = ['#6CAC5A', '#37BC9B']; +exports.version = '1.2.3'; +exports.author = 'Martin Smola'; +exports.cloning = false; +exports.options = { method: 'GET', url: '', size: 5, cacheexpire: '5 minutes', cachepolicy: 0, timeout: 5 }; +exports.dateupdated = '2021-01-21 18:30d'; +exports.readme = `# HTTP route + +__Outputs__: +- first output: raw data (cache is empty or is disabled) +- second output: cached data + +If one of the outputs is disabled then automatic responce with code "503 service unavailable" is sent. + +When a request comes in bellow object is available at \`flowdata.data\`: + +\`\`\`javascript +{ + params: { id: '1' }, // params for dynamic routes, e.g. /test/{id} + query: { msg: 'Hello' }, // parsed query string, e.g. /test/1?msg=Hello + body: { test: 'OK' }, // object if json requests otherwise string + headers: {}, // headers data + session: {}, // session data + user: {}, // user data + files: [], // uploaded files + url: '/users/', // a relative URL address + referrer: '/', // referrer + mobile: false, // determines mobile device + robot: false, // determines search robots/crawlsers + language: 'en' // determines language +} +\`\`\` + +See [documentation for flags](https://docs.totaljs.com/latest/en.html#api~HttpRouteOptionsFlags~unauthorize). These method flags are set automatically e.g. \`get, post, put, patch or delete\` + +--- + +\`id:ROUTE_ID\` flag cannot be used since it's already used by this component internally`; + +exports.html = `
+
+ +
+ +
+
+
@(HTTP method)
+
+
+
@(URL address)
+
+
+
+
+
@(Additional flags)
+
@(Separate flags by comma e.g. json, authorize)
+
+
+
@(Max. request size)
+
@(In kB kilobytes)
+
+
+
@(Timeout)
+
@(In seconds.)
+
+
+
+
+
+
@(Automatically respond with 200 OK?)
+
@(If not checked you need to use HTTP response component to respond to the request.)
+
+
@(Custom headers)
+
@(Cookies)
+
+
+
+
+
+
@(Cache policy)
+
@(User instance must contain id property.)
+
+
+
@(Expiration)
+
@(E.g. 5 minutes)
+
+
+
+`; + +exports.install = function(instance) { + + var route; + + var uninstall = function(id) { + if (F.is4) { + route && route.remove(); + route = null; + } else + UNINSTALL('route', id); + }; + + instance.custom.emptyresponse = function(self) { + self.plain(); + }; + + instance.reconfigure = function() { + + var options = instance.options; + + if (!options.url) { + instance.status('Not configured', 'red'); + return; + } + + if (typeof(options.flags) === 'string') + options.flags = options.flags.split(',').trim(); + + uninstall('id:' + instance.id); + + var flags = options.flags || []; + + flags.push('id:' + instance.id); + + if (!F.is4) + flags.push(options.method.toLowerCase()); + + options.timeout && flags.push(options.timeout * 1000); + + // Make unique values + flags = flags.filter(function(v, i, a) { + if(F.is4 && v.toString().toLowerCase() === options.method.toLowerCase()) + return false; // remove method + return a.indexOf(v) === i; + }); + + options.flags = flags; + var handler = function() { + + if (instance.paused || (instance.isDisabled && (instance.isDisabled('output', 0) || instance.isDisabled('output', 1)))) { + instance.status('503 Service Unavailable'); + this.status = 503; + this.json(); + return; + } + + var key; + var self = this; + + if (instance.options.emptyresponse) { + instance.status('200 OK'); + setTimeout(instance.custom.emptyresponse, 100, self); + + if (instance.hasConnection(0)) { + var data = instance.make({ + query: self.query, + body: self.body, + session: self.session, + user: self.user, + files: self.files, + headers: self.req.headers, + url: self.url, + params: self.params + }); + instance.send2(0, data); + } + + return; + } + + switch (instance.options.cachepolicy) { + case 1: // URL + key = 'rro' + instance.id + self.url.hash(); + break; + case 2: // URL + query + case 3: // URL + query + user + key = self.url; + var keys = Object.keys(self.query); + keys.sort(); + for (var i = 0, length = keys.length; i < length; i++) + key += keys[i] + self.query[keys[i]] + '&'; + if (instance.options.cachepolicy === 3 && self.user) + key += 'iduser' + self.user.id; + key = 'rro' + instance.id + key.hash(); + break; + } + + if (key && F.cache.get2(key)) { + var data = instance.make(F.cache.get2(key)); + data.repository.controller = self; + instance.send2(1, data); + } else { + + var data = instance.make({ + query: self.query, + body: self.body, + session: self.session, + user: self.user, + files: self.files, + headers: self.req.headers, + url: self.url, + params: self.params, + mobile: self.mobile, + robot: self.robot, + referrer: self.referrer, + language: self.language + }); + + data.repository.controller = self; + instance.send2(0, data); + key && FINISHED(self.res, () => F.cache.set(key, self.$flowdata.data, instance.options.cacheexpire)); + } + }; + + if (F.is4) + route = ROUTE(options.method.toUpperCase() + ' ' + options.url, handler, flags, options.size || 5); + else + F.route(options.url, handler, flags, options.size || 5); + + instance.status('Listening', 'green'); + }; + + instance.reconfigure(); + instance.on('options', instance.reconfigure); + instance.on('close', function(){ + uninstall('id:' + instance.id); + }); +}; + +// check url exists +FLOW.trigger('httproutecheckurl', function(next, data) { + var url = data.url; + var method = data.method; + if (url[url.length - 1] !== '/') + url += '/'; + var exists = F.routes.web.findItem(r => r.urlraw === url && r.method === method); + next(exists != null); +}); + +exports.uninstall = function() { + FLOW.trigger('httproutecheckurl', null); +}; diff --git a/RVO34/flow/infosender.js b/RVO34/flow/infosender.js new file mode 100755 index 0000000..587724f --- /dev/null +++ b/RVO34/flow/infosender.js @@ -0,0 +1,81 @@ +exports.id = 'infosender'; +exports.title = 'Info sender'; +exports.version = '1.0.0'; +exports.group = 'Worksys'; +exports.color = '#2134B0'; +exports.input = 2; +exports.output = 1 +exports.icon = 'bolt'; + +const { networkInterfaces } = require('os'); + +exports.html = `
+
+
+
CSV Import
+
+
+
`; + +exports.readme = `# send all data to projects.worksys.io, required to monitor status of controller(unipi)`; + +exports.install = function(instance) { + + let id; + let allValues = {}; + let sendAllValuesInterval; + let configured = false; + + let now = new Date(); + console.log(exports.title, "INSTALLED", now.toLocaleString("sk-SK")); + + const nets = networkInterfaces(); + let ipAddresses = Object.create(null); // Or just '{}', an empty object + + for (const name of Object.keys(nets)) { + for (const net of nets[name]) { + // Skip over non-IPv4 and internal (i.e. 127.0.0.1) addresses + if (net.family === 'IPv4' && !net.internal) { + if (!ipAddresses[name]) { + ipAddresses[name] = []; + } + ipAddresses[name].push(net.address); + } + } + } + + function sendValues() { + if (!configured) return; + + if (Object.keys(allValues).length > 0) { + let dataToSend = { ...allValues }; + dataToSend.id = id; + dataToSend.ipAddresses = ipAddresses; + + instance.send(0, dataToSend); + + allValues = {}; + } + } + + instance.on("close", () => { + clearInterval(sendAllValuesInterval); + }) + + instance.on("0", _ => { + id = FLOW.GLOBALS.settings.project_id; + if (id) configured = true; + else console.log(exports.title, "InfoSender: Unable to send data, no id"); + }) + + instance.on("1", flowdata => { + allValues = { ...allValues, ...flowdata.data }; + //console.log("DATA RECEIVED", flowdata.data); + }) + + sendAllValuesInterval = setInterval(() => { + sendValues(); + }, 60000 * 3); + +} + diff --git a/RVO34/flow/modbus_reader.js b/RVO34/flow/modbus_reader.js new file mode 100755 index 0000000..d6d9dad --- /dev/null +++ b/RVO34/flow/modbus_reader.js @@ -0,0 +1,346 @@ +exports.id = 'modbus_reader'; +exports.title = 'Modbus reader'; +exports.version = '2.0.0'; +exports.group = 'Worksys'; +exports.color = '#2134B0'; +exports.input = 1; +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; +//number of phases inRVO +let phases; +//phases where voltage is 0 (set) +let noVoltage; +let energyToSwitchLamps; + +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.phases = this.buildPhases(); + + this.startSocket(); + } + + buildPhases = () => { + let a = []; + for (let i = 1; i <= phases; i++) { + a.push(`Phase_${i}_voltage`) + } + return a; + } + + startSocket = () => { + + let obj = this; + + if (this.socket) { + this.socket.removeAllListeners(); + this.socket = null; + } + + 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('Modbus_reader: Socket connection error', e); //'ECONNREFUSED' or 'ECONNRESET' ?? + }); + + this.socket.on('close', function() { + console.log('Modbus_reader: Socket connection closed - Waiting 10 seconds before connecting 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 we just start to loop devices from the beginning, or there is just 1 device in config, we wait whole timeoutInterval + if (this.indexInDeviceConfig == 0 || deviceConfig.length === 1) 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 (this.phases.includes(singleValue)) { + let l = singleValue.split("_"); + let phase = parseInt(l[1]); + + // console.log(values[singleValue], tbName); + + if (values[singleValue] == 0) { + noVoltage.add(phase); + sendNotification("modbus_reader: checkNullVoltage", tbName, "no_voltage_on_phase", { phase: phase }, "", SEND_TO.tb, instance, "voltage" + phase); + // console.log('no voltage') + } + else { + noVoltage.delete(phase); + // console.log('voltage detected') + sendNotification("modbus_reader: checkNullVoltage", tbName, "voltage_on_phase_restored", { phase: phase }, "", SEND_TO.tb, instance, "voltage" + phase); + } + } + }) + } + + /** + * function sends notification to slack and to tb, if EM total_power value changes more than numberOfNodes*15. This should show, that RVO lamps has been switched on or off + */ + lampSwitchNotification = (values) => { + + if (!values.hasOwnProperty("total_power")) return; + + const actualTotalPower = values.total_power; + + if (actualTotalPower > energyToSwitchLamps && 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 <= energyToSwitchLamps && 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; + } + + function main() { + + phases = FLOW.GLOBALS.settings.phases; + tbName = FLOW.GLOBALS.settings.rvoTbName; + noVoltage = FLOW.GLOBALS.settings.no_voltage; + energyToSwitchLamps = FLOW.GLOBALS.settings.energy_to_switch_lamps / 2.5; //half value is enought to show if lamps are turned on or off + if (deviceConfig.length) mainSocket = new SocketWithClients(); + else console.log("Modbus_reader: no modbus device in configuration"); + + // this notification is to show, that flow (unipi) has been restarted + sendNotification("modbus_reader", tbName, "flow_restart", {}, "", SEND_TO.slack, instance); + } + + instance.on("0", function(_) { + main(); + }) + +} + diff --git a/RVO34/flow/monitorconsumption.js b/RVO34/flow/monitorconsumption.js new file mode 100755 index 0000000..64cc58e --- /dev/null +++ b/RVO34/flow/monitorconsumption.js @@ -0,0 +1,156 @@ +exports.id = 'monitorconsumption'; +exports.title = 'Consumption'; +exports.version = '1.0.0'; +exports.author = 'Peter Širka'; +exports.group = 'Monitoring'; +exports.color = '#967ADC'; +exports.input = 0; +exports.output = 1; +exports.icon = 'bug'; +exports.options = { interval: 5000, enabled: true, monitorconsumption: true, monitorsize: true, monitorconnections: true, monitorfiles: true }; +exports.click = true; +exports.readme = `# Consumption monitoring + +This component measure CPU and memory consumption, open files and open connections of this application. It uses these Linux commands: \`ps\`, \`lsof\`, \`netstat\` and \`df\`. + +__Data Example__: + +\`\`\`javascript +{ + cpu: 0, // percentage + memory: 4096, // in bytes + size: 34303, // directory size in bytes + files: 34, // count of open files + connections: 343, // count of connections + uptime: '1-12:34:00' +} +\`\`\``; + +exports.html = `
+
+
+
@(Interval in milliseconds)
+
+
+
+
Monitor: Consumption + uptime
+
Monitor: Count of open files
+
Monitor: Count of open connections
+
Monitor: Directory size
+
`; + +exports.install = function(instance) { + + var current = { cpu: 0, memory: 0, files: 0, connections: 0, size: 0, uptime: '', counter: 0 }; + var tproc = null; + var Exec = require('child_process').exec; + var reg_empty = /\s{2,}/g; + var reg_appdisksize = /^[\d.,]+/; + + instance.custom.run = function() { + + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + + var arr = []; + + // Get CPU and Memory consumption + instance.options.monitorconsumption && arr.push(function(next) { + Exec('ps -p {0} -o %cpu,rss,etime'.format(process.pid), function(err, response) { + + if (err) { + instance.throw(err); + } else { + var line = response.split('\n')[1]; + line = line.trim().replace(reg_empty, ' ').split(' '); + var cpu = line[0].parseFloat(); + current.cpu = cpu.floor(1); + current.memory = line[1].parseInt2() * 1024; // kB to bytes + current.uptime = line[2]; + } + + next(); + }); + }); + + // Get count of open files + instance.options.monitorfiles && arr.push(function(next) { + Exec('lsof -a -p {0} | wc -l'.format(process.pid), function(err, response) { + if (err) + instance.throw(err); + else + current.files = response.trim().parseInt2(); + next(); + }); + }); + + // Get count of opened network connections + instance.options.monitorconnections && arr.push(function(next) { + Exec('netstat -an | grep :{0} | wc -l'.format(F.port), function(err, response) { + if (err) { + instance.throw(err); + } else { + current.connections = response.trim().parseInt2() - 1; + if (current.connections < 0) + current.connections = 0; + } + next(); + }); + }); + + // Get directory size + instance.options.monitorsize && current.counter % 5 !== 0 && arr.push(function(next) { + Exec('du -hsb ' + process.cwd(), function(err, response) { + if (err) { + instance.throw(err); + } else { + var match = response.trim().match(reg_appdisksize); + match && (current.size = match.toString().trim().parseInt2()); + } + next(); + }); + }); + + arr.async(function() { + + tproc && clearTimeout(tproc); + + if (instance.options.enabled) { + tproc = setTimeout(instance.custom.run, instance.options.interval); + instance.send2(current); + } + + instance.custom.status(); + current.counter++; + }); + }; + + instance.custom.status = function() { + if (instance.options.enabled) + instance.status('{0}% / {1}'.format(current.cpu, current.memory.filesize())); + else + instance.status('Disabled', 'red'); + }; + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + + if (instance.options.enabled) { + current.counter = 0; + instance.custom.run(); + } + + }); + + instance.on('close', function() { + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + }); + + setTimeout(instance.custom.run, 1000); +}; \ No newline at end of file diff --git a/RVO34/flow/monitordisk.js b/RVO34/flow/monitordisk.js new file mode 100755 index 0000000..f4fdaa0 --- /dev/null +++ b/RVO34/flow/monitordisk.js @@ -0,0 +1,96 @@ +exports.id = 'monitordisk'; +exports.title = 'Disk'; +exports.version = '1.0.0'; +exports.author = 'Peter Širka'; +exports.group = 'Monitoring'; +exports.color = '#F6BB42'; +exports.output = 1; +exports.icon = 'hdd-o'; +exports.click = true; +exports.options = { interval: 8000, path: '/', enabled: true }; +exports.readme = `# Disk monitoring + +This component monitors disk \`bytes\` consumption in Linux systems. It uses \`df\` command. + +__Data Example__: + +\`\`\`javascript +{ + total: 474549649408, + used: 39125245952, + free: 411294994432 +} +\`\`\``; + +exports.html = `
+
+
+
@(Interval in milliseconds)
+
+
+
@(Path)
+
+
+
`; + +exports.install = function(instance) { + + var current = { total: 0, used: 0, free: 0, path: '', type: '', percentUsed: 0 }; + var tproc = null; + + instance.custom.run = function() { + + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + + if (!instance.options.enabled) + return; + + require('child_process').exec('df -hTB1 ' + instance.options.path, function(err, response) { + + tproc = setTimeout(instance.custom.run, instance.options.interval); + + if (err) { + instance.error(err); + return; + } + + response.parseTerminal(function(line) { + if (line[0][0] !== '/') + return; + current.total = line[2].parseInt(); + current.free = line[4].parseInt(); + current.used = line[3].parseInt(); + current.path = instance.options.path || '/'; + current.type = line[1]; + current.percentUsed = line[5]; + instance.custom.status(); + instance.send2(current); + }); + }); + }; + + instance.custom.status = function() { + if (instance.options.enabled) + instance.status(current.free.filesize() + ' / ' + current.total.filesize()); + else + instance.status('Disabled', 'red'); + }; + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + instance.options.enabled && instance.custom.run(); + }); + + instance.on('close', function() { + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + }); + + setTimeout(instance.custom.run, 1000); +}; \ No newline at end of file diff --git a/RVO34/flow/monitormemory.js b/RVO34/flow/monitormemory.js new file mode 100755 index 0000000..2decbc4 --- /dev/null +++ b/RVO34/flow/monitormemory.js @@ -0,0 +1,87 @@ +exports.id = 'monitormemory'; +exports.title = 'Memory'; +exports.version = '1.0.0'; +exports.author = 'Peter Širka'; +exports.group = 'Monitoring'; +exports.color = '#F6BB42'; +exports.output = 1; +exports.click = true; +exports.icon = 'microchip'; +exports.options = { interval: 8000, enabled: true }; +exports.readme = `# Memory monitoring + +This component monitors memory \`bytes\` consumption in Linux systems. It uses \`free\` command. + +__Data Example__: + +\`\`\`javascript +{ + total: 33558769664, + used: 1998868480, + free: 2653708288 +} +\`\`\``; + +exports.html = `
+
+
+
@(Interval in milliseconds)
+
+
+
`; + +exports.install = function(instance) { + + var current = { total: 0, used: 0, free: 0 }; + var tproc = null; + + instance.custom.run = function() { + + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + + if (!instance.options.enabled) + return; + + require('child_process').exec('free -b -t', function(err, response) { + + tproc = setTimeout(instance.custom.run, instance.options.interval); + + if (err) { + instance.error(err); + return; + } + + var memory = response.split('\n')[1].match(/\d+/g); + current.total = memory[0].parseInt(); + current.used = memory[1].parseInt() - memory[3].parseInt(); + current.free = current.total - current.used; + instance.custom.status(); + instance.send2(current); + }); + }; + + instance.custom.status = function() { + if (instance.options.enabled) + instance.status(current.free.filesize() + ' / ' + current.total.filesize()); + else + instance.status('Disabled', 'red'); + }; + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + instance.options.enabled && instance.custom.run(); + }); + + instance.on('close', function() { + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + }); + + setTimeout(instance.custom.run, 1000); +}; \ No newline at end of file diff --git a/RVO34/flow/nodesdb_changecheck.js b/RVO34/flow/nodesdb_changecheck.js new file mode 100755 index 0000000..9adab62 --- /dev/null +++ b/RVO34/flow/nodesdb_changecheck.js @@ -0,0 +1,77 @@ +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 = 2; +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); + } + } + + //kedze do slacku posielame stringy, na cloud musime previest vsetky stringy spat na objekty: + // Funkcia na parsovanie všetkých reťazcov v poli + const parseArray = (arr) => { + return arr.map(jsonString => JSON.parse(jsonString)); + }; + + 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); + if (FLOW.GLOBALS.settings.send_changed_node_numbers) instance.send(1, { aktualneNody: parseArray(zmenene), originalne: parseArray(Array.from(set2)) }); + } + 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/RVO34/flow/show_dbdata.js b/RVO34/flow/show_dbdata.js new file mode 100755 index 0000000..1e23ff7 --- /dev/null +++ b/RVO34/flow/show_dbdata.js @@ -0,0 +1,243 @@ +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 = 8; +exports.output = 1; + +const { exec } = require('child_process'); + +exports.install = 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 }) + }) + instance.on("5", _ => { + exec("sudo tail -n 25 monitor.txt", (err, stdout, stderr) => { + if (err || stderr) instance.send(0, { err, stderr }); + else instance.send(0, stdout); + }) + }) + instance.on("6", _ => { + exec("sudo tail -n 25 err.txt", (err, stdout, stderr) => { + if (err || stderr) instance.send(0, { err, stderr }); + else instance.send(0, stdout); + }) + }) + instance.on("7", _ => { + instance.send(0, FLOW.deviceStatus); + }) +}; + + +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/RVO34/flow/slack_filter.js b/RVO34/flow/slack_filter.js new file mode 100755 index 0000000..6618523 --- /dev/null +++ b/RVO34/flow/slack_filter.js @@ -0,0 +1,188 @@ +exports.id = 'slack_filter'; +exports.title = 'Slack Filter'; +exports.group = 'Citysys'; +exports.color = '#30E193'; +exports.input = 2; +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 = `
+
+
+
@(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('0', 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']['en']; + 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"] = []; + } + + instance.options.name = FLOW.GLOBALS.settings.rvo_name; + if (instance.options.name) { + instance.status('Running'); + running = true; + } else { + instance.status('Please run options again', 'red'); + running = false; + } + } catch (e) { + instance.error('Citysys connector: ' + e.message); + } + }; + + instance.on('options', instance.reconfigure); + + instance.on("1", _ => { + instance.reconfigure(); + }) +}; diff --git a/RVO34/flow/thermometer.js b/RVO34/flow/thermometer.js new file mode 100755 index 0000000..fc7074d --- /dev/null +++ b/RVO34/flow/thermometer.js @@ -0,0 +1,99 @@ +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 = 5;//minutes +let NUMBER_OF_FAILURES_TO_SEND_ERROR = 13; + +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) => { + + 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); + setTimeout(main, 20000); + }) +}; diff --git a/RVO34/flow/trigger.js b/RVO34/flow/trigger.js new file mode 100755 index 0000000..27545a8 --- /dev/null +++ b/RVO34/flow/trigger.js @@ -0,0 +1,79 @@ +exports.id = 'trigger'; +exports.title = 'Trigger'; +exports.group = 'Inputs'; +exports.color = '#F6BB42'; +exports.click = true; +exports.output = 1; +exports.version = '1.1.0'; +exports.author = 'Martin Smola'; +exports.icon = 'play'; + +exports.html = `
+
@(Data type (String by default))
+
@(Data)
+
Trigger 5s after initialization.
+
@(Useful when there's a need to run certain flow when the app restarts, etc.)
+
`; + +exports.readme = `# Trigger + +- Clicking on the component starts the chain +- Settings allows to set a data-type and a value`; + +exports.install = function(instance) { + + var value; + + instance.on('click', () => instance.send2(value)); + + instance.reconfigure = function() { + var options = instance.options; + value = null; + switch (options.datatype) { + case 'integer': + value = options.data.parseInt2('error'); + value = value === 'error' ? NaN : value; + break; + case 'float': + value = options.data.parseFloat2('error'); + value = value === 'error' ? NaN : value; + break; + case 'date': + options.data = options.data.toString(); + var num = options.data.parseInt('error'); + num === 'error' && (num = options.data.parseDate('error')); + num === 'error' && (num = null); + value = num ? new Date(num).toUTCString() : num; + break; + case 'object': + try { + value = (new Function('return ' + options.data))(); + } catch (e) { + instance.error(e); + } + break; + case 'boolean': + value = options.data.parseBoolean(); + break; + case 'buffer': + try { + value = U.createBuffer(options.data); + } catch (e) { + instance.error(e); + } + break; + case 'string': + default: + value = '' + (options.data || ''); + break; + } + }; + + instance.on('options', instance.reconfigure); + instance.reconfigure(); + + if (instance.options.restart) + setTimeout(function(){ + instance.send2(value); + }, 5000); +}; diff --git a/RVO34/flow/variables.txt b/RVO34/flow/variables.txt new file mode 100755 index 0000000..e69de29 diff --git a/RVO34/flow/virtualwirein.js b/RVO34/flow/virtualwirein.js new file mode 100755 index 0000000..38a4e42 --- /dev/null +++ b/RVO34/flow/virtualwirein.js @@ -0,0 +1,43 @@ +exports.id = 'virtualwirein'; +exports.title = 'Virtual wire in'; +exports.version = '1.0.0'; +exports.author = 'Martin Smola'; +exports.color = '#303E4D'; +exports.icon = 'sign-in'; +exports.input = false; +exports.output = 1; +exports.options = {}; +exports.readme = `# Virtual wire in + +When the wires between the components are mess it's time to use Virtual wire.`; + +exports.html = `
+
@(Wire name)
+
+`; + +exports.install = function(instance) { + + instance.custom.reconfigure = function(options){ + if (instance.options.wirename) { + instance.status(instance.options.wirename); + } else + instance.status('Not configured', 'red'); + }; + + ON('virtualwire', function(wirename, flowdata){ + if (instance.options.wirename && instance.options.wirename === wirename) + instance.send(flowdata); + }); + + instance.on('options', instance.custom.reconfigure); + instance.custom.reconfigure(); +}; diff --git a/RVO34/flow/virtualwireout.js b/RVO34/flow/virtualwireout.js new file mode 100755 index 0000000..94a1e4f --- /dev/null +++ b/RVO34/flow/virtualwireout.js @@ -0,0 +1,41 @@ +exports.id = 'virtualwireout'; +exports.title = 'Virtual wire out'; +exports.version = '1.0.0'; +exports.author = 'Martin Smola'; +exports.color = '#303E4D'; +exports.icon = 'sign-out'; +exports.input = true; +exports.options = {}; +exports.readme = `# Virtual wire out + +When the wires between the components are mess it's time to use Virtual wire.`; + +exports.html = `
+
@(Wire name)
+
+`; + +exports.install = function(instance) { + + instance.custom.reconfigure = function(){ + if (instance.options.wirename) { + instance.status(instance.options.wirename); + } else + instance.status('Not configured', 'red'); + }; + + instance.on('data', function(flowdata) { + EMIT('virtualwire', instance.options.wirename, flowdata); + }); + + instance.on('options', instance.custom.reconfigure); + instance.custom.reconfigure(); +}; diff --git a/RVO34/flow/wsmqttpublish.js b/RVO34/flow/wsmqttpublish.js new file mode 100755 index 0000000..0eba804 --- /dev/null +++ b/RVO34/flow/wsmqttpublish.js @@ -0,0 +1,448 @@ +exports.id = 'wsmqttpublish'; +exports.title = 'WS MQTT publish'; +exports.group = 'MQTT'; +exports.color = '#888600'; +exports.version = '1.0.2'; +exports.icon = 'sign-out'; +exports.input = 2; +exports.output = 3; +exports.options = { host: 'tb-stage.worksys.io', port: 1883, clientid: "", username: "" }; + +exports.html = `
+
+
+
Hostname or IP address (if not empty - setting will override db setting)
+
+
+
Port
+
+
+
+
+
@(Client id)
+
+
+
@(Username)
+
+
+
`; + + +exports.readme = ` +# WS MQTT Publish + +Version 1.0.3. + +Added: +- database collections, +- 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 = { + debug: 0, + rpcCall: 1, + services: 2 +} + +//CONFIG +let createTelemetryBackup = true; +let saveTelemetryOnError = true;//backup_on_failure overrides this value +//------------------------ + +let rollers; +if (createTelemetryBackup) rollers = require('streamroller'); + +const noSqlFileSizeLimit = 4194304;//use 5MB - 4194304 +let insertNoSqlCounter = 0; +let insertBackupNoSqlCounter = 0; +let processingData = false; + +let backup_on_failure = false;//== saveTelemetryOnError - create backup client 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; + +process.on('uncaughtException', function(err) { + + errLogger.error('uncaughtException:', err.message) + errLogger.error(err.stack); + + //TODO + //send to service + + //process.exit(1); +}) + +const nosql = NOSQL('tbdata'); +const nosqlBackup = NOSQL('/backup/tbdata'); + + +exports.install = function(instance) { + + var client; + var opts; + var clientReady = false; + + // wsmqtt status for notification purposes on projects.worksys.io database + let wsmqttName = null; + let sendWsStatusVar = null; + let wsmqtt_status = 'disconnected'; + + 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'; + } + + function sendWsStatus() { + instance.send(SEND_TO.services, { [wsmqttName]: wsmqtt_status }); + } + + + function main() { + if (!FLOW.dbLoaded) return; + + loadSettings(); + clearInterval(sendWsStatus); + sendWsStatusVar = setInterval(sendWsStatus, 180000); + } + + //set opts according to db settings + function loadSettings() { + + if (instance.options.host !== "") { + //override settings from database + var o = instance.options; + opts = { + host: o.host, + port: o.port, + clientId: o.clientid, + username: o.username, + rejectUnauthorized: false, + resubscribe: false + }; + + wsmqttName = getWsmqttName(o.host); + + console.log("wsmqttpublich -> loadSettings from instance.options", instance.options); + } + else { + + const SETTINGS = FLOW.GLOBALS.settings; + backup_on_failure = SETTINGS.backup_on_failure; + saveTelemetryOnError = backup_on_failure; + + restore_from_backup = SETTINGS.restore_from_backup; + restore_backup_wait = SETTINGS.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; + + opts = { + host: mqtt_host, + port: mqtt_port, + keepalive: 10, + clientId: mqtt_clientid, + username: mqtt_username, + rejectUnauthorized: false, + resubscribe: false + }; + + wsmqttName = getWsmqttName(mqtt_host); + } + + connectToTbServer(); + } + + function connectToTbServer() { + 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"); + //monitor.info("MQTT client connected"); + + sendClientError = true; + clientReady = true; + wsmqtt_status = 'connected'; + }); + + client.on('reconnect', function() { + instance.status("Reconnecting", "yellow"); + clientReady = false; + }); + + client.on('message', function(topic, message) { + // message is type of buffer + message = message.toString(); + if (message[0] === '{') { + TRY(function() { + + message = JSON.parse(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 } }); + } + + }, () => instance.debug('MQTT: Error parsing data', message)); + } + + instance.send(SEND_TO.rpcCall, { "topic": topic, "content": message }); + }); + + client.on('close', function() { + clientReady = false; + wsmqtt_status = 'disconnected'; + + instance.status("Disconnected", "red"); + instance.send(SEND_TO.debug, { "message": "Client CLOSE signal received !" }); + }); + + client.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; + wsmqtt_status = 'disconnected'; + }); + + } + + + instance.on("0", _ => { + main(); + }) + + + instance.on('1', function(data) { + + if (clientReady) { + //do we have some data in backup file? if any, process data from database + if (saveTelemetryOnError) { + //read telemetry data and send back to server + if (!processingData) processDataFromDatabase(); + } + + let stringifiedJson = JSON.stringify(data.data); + client.publish("v1/gateway/telemetry", stringifiedJson, { qos: 1 }); + + //backup telemetry + if (createTelemetryBackup) { + data.data.id = UID(); + nosqlBackup.insert(data.data); + + insertBackupNoSqlCounter++; + if (insertBackupNoSqlCounter > 150) { + let options = { compress: true }; + let path = __dirname + "/../databases/backup/tbdata.nosql"; + var stream = new rollers.RollingFileStream(path, noSqlFileSizeLimit, 150, options); + stream.write(""); + stream.end(); + + insertBackupNoSqlCounter = 0; + } + } + + } + 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 (saveTelemetryOnError) { + //create new file from tbdata.nosql, if file size exceeds given limit, and clear tbdata.nosql + makeBackupFromDbFile(); + + //write to tb + data.data.id = UID(); + nosql.insert(data.data); + } + } + }); + + + instance.close = function(done) { + if (clientReady) { + client.end(); + clearInterval(sendWsStatusVar); + } + }; + + + function getDbBackupFileCounter(type) { + var files = fs.readdirSync(__dirname + "/../databases"); + + let counter = 0; + for (var i = 0; i < files.length; i++) { + + if (files[i] == "tbdata.nosql") continue; + + if (files[i].endsWith(".nosql")) { + + let pos = files[i].indexOf("."); + if (pos > -1) { + + let fileCounter = counter; + let firstDigit = files[i].slice(0, pos); + + fileCounter = parseInt(firstDigit); + if (isNaN(fileCounter)) fileCounter = 0; + //console.log("getDbBackupFileCounter digit:", files[i], firstDigit, fileCounter, isNaN(fileCounter), type); + + if (type == "max") { + if (fileCounter > counter) { + counter = fileCounter; + } + } + else if (type == "min") { + if (counter == 0) counter = fileCounter; + + if (fileCounter < counter) { + counter = fileCounter; + } + } + } + } + + } + + if (type == "max") counter++; + + return counter; + } + + const makeBackupFromDbFile = async () => { + + if (!saveTelemetryOnError) return; + + //to avoid large file: tbdata.nosql + + //init value is 0! + if (insertNoSqlCounter > 0) { + --insertNoSqlCounter; + return; + } + + insertNoSqlCounter = 100; + + let source = __dirname + "/../databases/tbdata.nosql"; + + var stats = fs.statSync(source); + var fileSizeInBytes = stats.size; + + if (fileSizeInBytes > noSqlFileSizeLimit) { + + let counter = 1; + counter = getDbBackupFileCounter("max"); + + let destination = __dirname + "/../databases/" + counter + "." + "tbdata.nosql"; + + //make backup file + fs.copyFileSync(source, destination); + //fs.renameSync(p, p + "." + counter); + + //clear tbdata.nosql + fs.writeFileSync(source, ""); + fs.truncateSync(source, 0); + + } + } + + const processDataFromDatabase = async () => { + + if (restore_from_backup <= 0) return; + + //calculate diff + const now = new Date(); + let currentTime = now.getTime(); + let diff = currentTime - lastRestoreTime; + + if ((diff / 1000) < restore_backup_wait) { + //console.log("*********restore_backup_wait", diff, restore_backup_wait); + return; + } + + processingData = true; + + //get filename to process + let counter = getDbBackupFileCounter("min"); + + //we have some backup files + let dataBase = 'tbdata'; + + var nosql; + if (counter == 0) dataBase = 'tbdata'; + else dataBase = counter + "." + 'tbdata'; + + nosql = NOSQL(dataBase); + + //select all data - use limit restore_from_backup + let records = await promisifyBuilder(nosql.find().take(restore_from_backup)); + + for (let i = 0; i < records.length; i++) { + if (clientReady) { + + let item = records[i]; + let id = item.id; + + if (id !== undefined) { + //console.log("------------processDataFromDatabase - remove", id, dataBase, i); + + try { + + let message = JSON.parse(JSON.stringify(item)); + delete message.id; + + client.publish("v1/gateway/telemetry", JSON.stringify(message), { qos: 1 }); + + //remove from database + await promisifyBuilder(nosql.remove().where("id", id)); + + } catch (error) { + //process error + console.log("processDataFromDatabase", error); + } + + } + + } + else { + processingData = false; + return; + } + } + + if (records.length > 0) { + //clean backup file + if (counter > 0) nosql.clean(); + } + + //no data in db, remove + if (records.length == 0) { + if (counter > 0) nosql.drop(); + } + + const d = new Date(); + lastRestoreTime = d.getTime(); + + processingData = false; + + } + + instance.on('options', main); + //instance.reconfigure(); +}; diff --git a/RVO34/monitor.txt b/RVO34/monitor.txt new file mode 100755 index 0000000..219a331 --- /dev/null +++ b/RVO34/monitor.txt @@ -0,0 +1,4087 @@ +[2025-07-22T03:05:26.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-22 03:05:26 +[2025-07-22T04:58:13.844] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-22T04:58:13.848] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-22T04:58:13.850] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-22T04:58:13.853] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-07-22T04:58:13.854] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-07-22T04:58:13.856] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 6 relay1_07 false Profile: dawn - turnOff line according to lux sensor +[2025-07-22T04:58:13.858] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 7 relay1_08 false Profile: dawn - turnOff line according to lux sensor +[2025-07-22T20:58:24.804] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-22T20:58:24.810] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-22T20:58:24.812] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-22T20:58:24.815] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-07-22T20:58:24.817] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-07-22T20:58:24.818] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 6 relay1_07 false Profile: dusk - turnOn line according to lux sensor +[2025-07-22T20:58:24.820] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 7 relay1_08 false Profile: dusk - turnOn line according to lux sensor +[2025-07-23T03:05:28.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-23 03:05:28 +[2025-07-23T04:57:19.720] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-23T04:57:19.728] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-23T04:57:19.731] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-23T04:57:19.733] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-07-23T04:57:19.735] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-07-23T04:57:19.737] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 6 relay1_07 false Profile: dawn - turnOff line according to lux sensor +[2025-07-23T04:57:19.739] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 7 relay1_08 false Profile: dawn - turnOff line according to lux sensor +[2025-07-23T20:57:36.492] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-23T20:57:36.499] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-23T20:57:36.501] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-23T20:57:36.503] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-07-23T20:57:36.505] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-07-23T20:57:36.507] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 6 relay1_07 false Profile: dusk - turnOn line according to lux sensor +[2025-07-23T20:57:36.509] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 7 relay1_08 false Profile: dusk - turnOn line according to lux sensor +[2025-07-24T03:05:30.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-24 03:05:30 +[2025-07-24T05:02:38.877] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-24T05:02:38.881] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-24T05:02:38.883] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-24T05:02:38.886] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-07-24T05:02:38.888] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-07-24T05:02:38.890] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 6 relay1_07 false Profile: dawn - turnOff line according to lux sensor +[2025-07-24T05:02:38.892] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 7 relay1_08 false Profile: dawn - turnOff line according to lux sensor +[2025-07-24T20:47:03.858] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-24T20:47:03.866] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-24T20:47:03.868] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-24T20:47:03.870] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-07-24T20:47:03.872] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-07-24T20:47:03.873] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 6 relay1_07 false Profile: dusk - turnOn line according to lux sensor +[2025-07-24T20:47:03.875] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 7 relay1_08 false Profile: dusk - turnOn line according to lux sensor +[2025-07-25T03:05:31.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-25 03:05:31 +[2025-07-25T05:04:16.850] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-25T05:04:16.858] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-25T05:04:16.860] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-25T05:04:16.862] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-07-25T05:04:16.864] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-07-25T05:04:16.866] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 6 relay1_07 false Profile: dawn - turnOff line according to lux sensor +[2025-07-25T05:04:16.868] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 7 relay1_08 false Profile: dawn - turnOff line according to lux sensor +[2025-07-25T20:44:37.098] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-25T20:44:37.105] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-25T20:44:37.108] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-25T20:44:37.110] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-07-25T20:44:37.111] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-07-25T20:44:37.113] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 6 relay1_07 false Profile: dusk - turnOn line according to lux sensor +[2025-07-25T20:44:37.115] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 7 relay1_08 false Profile: dusk - turnOn line according to lux sensor +[2025-07-26T03:05:33.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-26 03:05:33 +[2025-07-26T05:05:37.796] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-26T05:05:37.804] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-26T05:05:37.806] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-26T05:05:37.808] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-07-26T05:05:37.810] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-07-26T05:05:37.812] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 6 relay1_07 false Profile: dawn - turnOff line according to lux sensor +[2025-07-26T05:05:37.813] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 7 relay1_08 false Profile: dawn - turnOff line according to lux sensor +[2025-07-26T20:49:08.745] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-26T20:49:08.753] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-26T20:49:08.756] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-26T20:49:08.758] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-07-26T20:49:08.759] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-07-26T20:49:08.761] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 6 relay1_07 false Profile: dusk - turnOn line according to lux sensor +[2025-07-26T20:49:08.763] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 7 relay1_08 false Profile: dusk - turnOn line according to lux sensor +[2025-07-27T03:05:35.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-27 03:05:35 +[2025-07-27T05:06:32.424] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-27T05:06:32.432] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-27T05:06:32.435] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-27T05:06:32.437] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-07-27T05:06:32.439] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-07-27T05:06:32.441] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 6 relay1_07 false Profile: dawn - turnOff line according to lux sensor +[2025-07-27T05:06:32.442] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 7 relay1_08 false Profile: dawn - turnOff line according to lux sensor +[2025-07-27T20:35:05.529] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-27T20:35:05.536] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-27T20:35:05.538] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-27T20:35:05.540] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-07-27T20:35:05.543] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-07-27T20:35:05.544] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 6 relay1_07 false Profile: dusk - turnOn line according to lux sensor +[2025-07-27T20:35:05.546] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 7 relay1_08 false Profile: dusk - turnOn line according to lux sensor +[2025-07-28T03:05:36.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-28 03:05:36 +[2025-07-28T05:08:14.273] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-28T05:08:14.277] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-28T05:08:14.279] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-28T05:08:14.282] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-07-28T05:08:14.284] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-07-28T05:08:14.286] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 6 relay1_07 false Profile: dawn - turnOff line according to lux sensor +[2025-07-28T05:08:14.287] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 7 relay1_08 false Profile: dawn - turnOff line according to lux sensor +[2025-07-28T20:39:59.713] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-28T20:39:59.719] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-28T20:39:59.722] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-28T20:39:59.724] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-07-28T20:39:59.726] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-07-28T20:39:59.729] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 6 relay1_07 false Profile: dusk - turnOn line according to lux sensor +[2025-07-28T20:39:59.730] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 7 relay1_08 false Profile: dusk - turnOn line according to lux sensor +[2025-07-29T03:05:38.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-29 03:05:38 +[2025-07-29T05:07:54.665] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-29T05:07:54.674] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-29T05:07:54.677] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-29T05:07:54.679] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-07-29T05:07:54.681] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-07-29T05:07:54.683] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 6 relay1_07 false Profile: dawn - turnOff line according to lux sensor +[2025-07-29T05:07:54.685] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 7 relay1_08 false Profile: dawn - turnOff line according to lux sensor +[2025-07-29T12:19:35.456] [INFO] monitorLogs - MQTT client error Error: connect ECONNREFUSED 192.168.252.1:1883 + at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1159:16) { + errno: -111, + code: 'ECONNREFUSED', + syscall: 'connect', + address: '192.168.252.1', + port: 1883 +} +[2025-07-29T20:46:41.120] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-29T20:46:41.128] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-29T20:46:41.130] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-29T20:46:41.132] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-07-29T20:46:41.134] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-07-29T20:46:41.136] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 6 relay1_07 false Profile: dusk - turnOn line according to lux sensor +[2025-07-29T20:46:41.138] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 7 relay1_08 false Profile: dusk - turnOn line according to lux sensor +[2025-07-30T03:05:40.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-30 03:05:40 +[2025-07-30T05:08:05.290] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-30T05:08:05.299] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-30T05:08:05.303] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-30T05:08:05.305] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-07-30T05:08:05.307] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-07-30T05:08:05.308] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 6 relay1_07 false Profile: dawn - turnOff line according to lux sensor +[2025-07-30T05:08:05.310] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 7 relay1_08 false Profile: dawn - turnOff line according to lux sensor +[2025-07-30T20:42:41.157] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-30T20:42:41.165] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-30T20:42:41.168] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-30T20:42:41.170] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-07-30T20:42:41.173] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-07-30T20:42:41.175] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 6 relay1_07 false Profile: dusk - turnOn line according to lux sensor +[2025-07-30T20:42:41.176] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 7 relay1_08 false Profile: dusk - turnOn line according to lux sensor +[2025-07-31T03:05:41.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-31 03:05:41 +[2025-07-31T05:08:07.660] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-31T05:08:07.667] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-31T05:08:07.670] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-31T05:08:07.672] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-07-31T05:08:07.674] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-07-31T05:08:07.676] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 6 relay1_07 false Profile: dawn - turnOff line according to lux sensor +[2025-07-31T05:08:07.677] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 7 relay1_08 false Profile: dawn - turnOff line according to lux sensor +[2025-07-31T20:45:05.307] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-31T20:45:05.314] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-31T20:45:05.316] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-31T20:45:05.318] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-07-31T20:45:05.320] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-07-31T20:45:05.322] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 6 relay1_07 false Profile: dusk - turnOn line according to lux sensor +[2025-07-31T20:45:05.324] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 7 relay1_08 false Profile: dusk - turnOn line according to lux sensor +[2025-08-01T03:05:43.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-01 03:05:43 +[2025-08-01T05:10:28.813] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-01T05:10:28.821] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-01T05:10:28.823] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-01T05:10:28.825] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-08-01T05:10:28.828] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-08-01T05:10:28.830] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 6 relay1_07 false Profile: dawn - turnOff line according to lux sensor +[2025-08-01T05:10:28.831] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 7 relay1_08 false Profile: dawn - turnOff line according to lux sensor +[2025-08-01T20:26:19.881] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-01T20:26:19.889] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-01T20:26:19.891] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-01T20:26:19.893] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-08-01T20:26:19.895] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-08-01T20:26:19.897] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 6 relay1_07 false Profile: dusk - turnOn line according to lux sensor +[2025-08-01T20:26:19.899] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 7 relay1_08 false Profile: dusk - turnOn line according to lux sensor +[2025-08-02T03:05:45.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-02 03:05:45 +[2025-08-02T05:10:20.973] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-02T05:10:20.981] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-02T05:10:20.984] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-02T05:10:20.986] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-08-02T05:10:20.988] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-08-02T05:10:20.989] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 6 relay1_07 false Profile: dawn - turnOff line according to lux sensor +[2025-08-02T05:10:20.991] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 7 relay1_08 false Profile: dawn - turnOff line according to lux sensor +[2025-08-02T20:35:28.067] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-02T20:35:28.075] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-02T20:35:28.078] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-02T20:35:28.080] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-08-02T20:35:28.082] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-08-02T20:35:28.083] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 6 relay1_07 false Profile: dusk - turnOn line according to lux sensor +[2025-08-02T20:35:28.085] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 7 relay1_08 false Profile: dusk - turnOn line according to lux sensor +[2025-08-03T03:05:46.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-03 03:05:46 +[2025-08-03T05:25:51.126] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-03T05:25:51.134] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-03T05:25:51.137] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-03T05:25:51.139] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-08-03T05:25:51.140] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-08-03T05:25:51.142] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 6 relay1_07 false Profile: dawn - turnOff line according to lux sensor +[2025-08-03T05:25:51.144] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 7 relay1_08 false Profile: dawn - turnOff line according to lux sensor +[2025-08-03T20:41:11.375] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-03T20:41:11.382] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-03T20:41:11.385] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-03T20:41:11.387] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-08-03T20:41:11.389] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-08-03T20:41:11.391] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 6 relay1_07 false Profile: dusk - turnOn line according to lux sensor +[2025-08-03T20:41:11.392] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 7 relay1_08 false Profile: dusk - turnOn line according to lux sensor +[2025-08-04T03:05:48.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-04 03:05:48 +[2025-08-04T05:14:38.746] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-04T05:14:38.754] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-04T05:14:38.756] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-04T05:14:38.758] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-08-04T05:14:38.760] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-08-04T05:14:38.762] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 6 relay1_07 false Profile: dawn - turnOff line according to lux sensor +[2025-08-04T05:14:38.764] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 7 relay1_08 false Profile: dawn - turnOff line according to lux sensor +[2025-08-04T20:41:26.414] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-04T20:41:26.422] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-04T20:41:26.424] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-04T20:41:26.426] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-08-04T20:41:26.428] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-08-04T20:41:26.430] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 6 relay1_07 false Profile: dusk - turnOn line according to lux sensor +[2025-08-04T20:41:26.432] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 7 relay1_08 false Profile: dusk - turnOn line according to lux sensor +[2025-08-05T03:05:49.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-05 03:05:49 +[2025-08-05T05:21:15.623] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-05T05:21:15.631] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-05T05:21:15.634] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-05T05:21:15.636] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-08-05T05:21:15.637] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-08-05T05:21:15.639] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 6 relay1_07 false Profile: dawn - turnOff line according to lux sensor +[2025-08-05T05:21:15.641] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 7 relay1_08 false Profile: dawn - turnOff line according to lux sensor +[2025-08-05T20:36:04.334] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-05T20:36:04.342] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-05T20:36:04.344] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-05T20:36:04.346] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-08-05T20:36:04.348] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-08-05T20:36:04.350] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 6 relay1_07 false Profile: dusk - turnOn line according to lux sensor +[2025-08-05T20:36:04.352] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 7 relay1_08 false Profile: dusk - turnOn line according to lux sensor +[2025-08-06T03:05:51.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-06 03:05:51 +[2025-08-06T05:17:26.875] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-06T05:17:26.883] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-06T05:17:26.885] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-06T05:17:26.887] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-08-06T05:17:26.889] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-08-06T05:17:26.891] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 6 relay1_07 false Profile: dawn - turnOff line according to lux sensor +[2025-08-06T05:17:26.893] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 7 relay1_08 false Profile: dawn - turnOff line according to lux sensor +[2025-08-06T13:33:41.086] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-08-06T13:33:46.439] [INFO] monitorLogs - buildTasks - params undefined +[2025-08-06T13:33:46.443] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-08-06T13:33:46.444] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-08-06T13:33:46.445] [INFO] monitorLogs - profile: { + 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 +} +[2025-08-06T13:33:46.450] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-08-06T13:33:46.451] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-08-07T04:02:00.450Z +[2025-08-06T13:33:46.453] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-08-06T18:53:00.452Z +[2025-08-06T13:33:46.453] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '6:2', name: 'luxOff' }, + { value: 1, start_time: '20:53', name: 'luxOn' } +] +[2025-08-06T13:33:46.454] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-08-06T13:33:46.455] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-08-06T13:33:46.456] [INFO] monitorLogs - profile: { + 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 +} +[2025-08-06T13:33:46.458] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-08-06T13:33:46.459] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-08-07T04:02:00.459Z +[2025-08-06T13:33:46.460] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-08-06T18:53:00.460Z +[2025-08-06T13:33:46.460] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '6:2', name: 'luxOff' }, + { value: 1, start_time: '20:53', name: 'luxOn' } +] +[2025-08-06T13:33:46.461] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-08-06T13:33:46.462] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-08-06T13:33:46.463] [INFO] monitorLogs - profile: { + 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 +} +[2025-08-06T13:33:46.465] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-08-06T13:33:46.466] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-08-07T04:02:00.465Z +[2025-08-06T13:33:46.466] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-08-06T18:53:00.466Z +[2025-08-06T13:33:46.467] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '6:2', name: 'luxOff' }, + { value: 1, start_time: '20:53', name: 'luxOn' } +] +[2025-08-06T13:33:46.468] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-08-06T13:33:46.469] [INFO] monitorLogs - buildTasks: profile for line 4 +[2025-08-06T13:33:46.469] [INFO] monitorLogs - profile: { + 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 +} +[2025-08-06T13:33:46.471] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-08-06T13:33:46.472] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 4 2025-08-07T04:02:00.472Z +[2025-08-06T13:33:46.473] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 4 2025-08-06T18:53:00.473Z +[2025-08-06T13:33:46.473] [INFO] monitorLogs - -->time_points final 4 [ + { value: 0, start_time: '6:2', name: 'luxOff' }, + { value: 1, start_time: '20:53', name: 'luxOn' } +] +[2025-08-06T13:33:46.474] [INFO] monitorLogs - -->currentValue for relay 4 0 +[2025-08-06T13:33:46.475] [INFO] monitorLogs - buildTasks: profile for line 5 +[2025-08-06T13:33:46.476] [INFO] monitorLogs - profile: { + 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 +} +[2025-08-06T13:33:46.478] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-08-06T13:33:46.478] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 5 2025-08-07T04:02:00.478Z +[2025-08-06T13:33:46.479] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 5 2025-08-06T18:53:00.479Z +[2025-08-06T13:33:46.480] [INFO] monitorLogs - -->time_points final 5 [ + { value: 0, start_time: '6:2', name: 'luxOff' }, + { value: 1, start_time: '20:53', name: 'luxOn' } +] +[2025-08-06T13:33:46.481] [INFO] monitorLogs - -->currentValue for relay 5 0 +[2025-08-06T13:33:46.481] [INFO] monitorLogs - buildTasks: profile for line 6 +[2025-08-06T13:33:46.482] [INFO] monitorLogs - profile: { + 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 +} +[2025-08-06T13:33:46.502] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-08-06T13:33:46.503] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 6 2025-08-07T04:02:00.502Z +[2025-08-06T13:33:46.503] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 6 2025-08-06T18:53:00.503Z +[2025-08-06T13:33:46.504] [INFO] monitorLogs - -->time_points final 6 [ + { value: 0, start_time: '6:2', name: 'luxOff' }, + { value: 1, start_time: '20:53', name: 'luxOn' } +] +[2025-08-06T13:33:46.505] [INFO] monitorLogs - -->currentValue for relay 6 0 +[2025-08-06T13:33:46.506] [INFO] monitorLogs - buildTasks: profile for line 7 +[2025-08-06T13:33:46.507] [INFO] monitorLogs - profile: { + 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 +} +[2025-08-06T13:33:46.509] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-08-06T13:33:46.510] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 7 2025-08-07T04:02:00.509Z +[2025-08-06T13:33:46.510] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 7 2025-08-06T18:53:00.510Z +[2025-08-06T13:33:46.511] [INFO] monitorLogs - -->time_points final 7 [ + { value: 0, start_time: '6:2', name: 'luxOff' }, + { value: 1, start_time: '20:53', name: 'luxOn' } +] +[2025-08-06T13:33:46.512] [INFO] monitorLogs - -->currentValue for relay 7 0 +[2025-08-06T13:33:46.521] [INFO] monitorLogs - tasks created: 1510 +[2025-08-06T13:33:46.524] [INFO] monitorLogs - -->FLOW bol spustený o9vbeQlLMVg8j5dq4keLWb0NxZpEmnXzwYKO1ar2 2025-08-08 +[2025-08-06T13:33:51.537] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-06T20:33:24.071] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-06T20:33:24.078] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-06T20:33:24.081] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-06T20:33:24.084] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-08-06T20:33:24.086] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-08-06T20:33:24.088] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 6 relay1_07 false Profile: dusk - turnOn line according to lux sensor +[2025-08-06T20:33:24.091] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 7 relay1_08 false Profile: dusk - turnOn line according to lux sensor +[2025-08-07T03:33:48.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-07 03:33:48 +[2025-08-07T05:19:18.200] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-07T05:19:18.208] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-07T05:19:18.210] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-07T05:19:18.213] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-08-07T05:19:18.215] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-08-07T05:19:18.217] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 6 relay1_07 false Profile: dawn - turnOff line according to lux sensor +[2025-08-07T05:19:18.218] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 7 relay1_08 false Profile: dawn - turnOff line according to lux sensor +[2025-08-07T20:34:32.620] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-07T20:34:32.627] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-07T20:34:32.629] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-07T20:34:32.631] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-08-07T20:34:32.634] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-08-07T20:34:32.636] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 6 relay1_07 false Profile: dusk - turnOn line according to lux sensor +[2025-08-07T20:34:32.638] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 7 relay1_08 false Profile: dusk - turnOn line according to lux sensor +[2025-08-08T03:33:50.071] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-08 03:33:50 +[2025-08-08T05:19:50.656] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-08T05:19:50.665] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-08T05:19:50.667] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-08T05:19:50.670] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-08-08T05:19:50.672] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-08-08T05:19:50.674] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 6 relay1_07 false Profile: dawn - turnOff line according to lux sensor +[2025-08-08T05:19:50.676] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 7 relay1_08 false Profile: dawn - turnOff line according to lux sensor +[2025-08-08T20:32:34.791] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-08T20:32:34.799] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-08T20:32:34.801] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-08T20:32:34.803] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-08-08T20:32:34.805] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-08-08T20:32:34.807] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 6 relay1_07 false Profile: dusk - turnOn line according to lux sensor +[2025-08-08T20:32:34.808] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 7 relay1_08 false Profile: dusk - turnOn line according to lux sensor +[2025-08-09T03:33:51.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-09 03:33:51 +[2025-08-09T05:20:21.423] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-09T05:20:21.427] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-09T05:20:21.429] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-09T05:20:21.431] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-08-09T05:20:21.433] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-08-09T05:20:21.435] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 6 relay1_07 false Profile: dawn - turnOff line according to lux sensor +[2025-08-09T05:20:21.437] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 7 relay1_08 false Profile: dawn - turnOff line according to lux sensor +[2025-08-09T20:32:28.394] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-09T20:32:28.401] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-09T20:32:28.404] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-09T20:32:28.406] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-08-09T20:32:28.408] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-08-09T20:32:28.409] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 6 relay1_07 false Profile: dusk - turnOn line according to lux sensor +[2025-08-09T20:32:28.411] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 7 relay1_08 false Profile: dusk - turnOn line according to lux sensor +[2025-08-10T03:33:53.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-10 03:33:53 +[2025-08-10T05:20:54.239] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-10T05:20:54.243] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-10T05:20:54.245] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-10T05:20:54.247] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-08-10T05:20:54.249] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-08-10T05:20:54.251] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 6 relay1_07 false Profile: dawn - turnOff line according to lux sensor +[2025-08-10T05:20:54.253] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 7 relay1_08 false Profile: dawn - turnOff line according to lux sensor +[2025-08-10T20:31:06.961] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-10T20:31:06.969] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-10T20:31:06.972] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-10T20:31:06.974] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-08-10T20:31:06.976] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-08-10T20:31:06.978] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 6 relay1_07 false Profile: dusk - turnOn line according to lux sensor +[2025-08-10T20:31:06.980] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 7 relay1_08 false Profile: dusk - turnOn line according to lux sensor +[2025-08-11T03:33:55.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-11 03:33:55 +[2025-08-11T05:24:08.027] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-11T05:24:08.035] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-11T05:24:08.037] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-11T05:24:08.039] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-08-11T05:24:08.042] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-08-11T05:24:08.043] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 6 relay1_07 false Profile: dawn - turnOff line according to lux sensor +[2025-08-11T05:24:08.045] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 7 relay1_08 false Profile: dawn - turnOff line according to lux sensor +[2025-08-11T20:30:14.739] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-11T20:30:14.747] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-11T20:30:14.749] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-11T20:30:14.751] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-08-11T20:30:14.753] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-08-11T20:30:14.755] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 6 relay1_07 false Profile: dusk - turnOn line according to lux sensor +[2025-08-11T20:30:14.757] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 7 relay1_08 false Profile: dusk - turnOn line according to lux sensor +[2025-08-12T03:33:57.013] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-12 03:33:57 +[2025-08-12T05:25:24.868] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-12T05:25:24.872] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-12T05:25:24.874] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-12T05:25:24.877] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-08-12T05:25:24.878] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-08-12T05:25:24.880] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 6 relay1_07 false Profile: dawn - turnOff line according to lux sensor +[2025-08-12T05:25:24.882] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 7 relay1_08 false Profile: dawn - turnOff line according to lux sensor +[2025-08-12T20:27:16.824] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-12T20:27:16.832] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-12T20:27:16.834] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-12T20:27:16.836] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-08-12T20:27:16.838] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-08-12T20:27:16.840] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 6 relay1_07 false Profile: dusk - turnOn line according to lux sensor +[2025-08-12T20:27:16.842] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 7 relay1_08 false Profile: dusk - turnOn line according to lux sensor +[2025-08-13T03:33:58.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-13 03:33:58 +[2025-08-13T05:26:45.481] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-13T05:26:45.490] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-13T05:26:45.492] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-13T05:26:45.495] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-08-13T05:26:45.497] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-08-13T05:26:45.499] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 6 relay1_07 false Profile: dawn - turnOff line according to lux sensor +[2025-08-13T05:26:45.501] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 7 relay1_08 false Profile: dawn - turnOff line according to lux sensor +[2025-08-13T20:23:54.240] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-13T20:23:54.247] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-13T20:23:54.249] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-13T20:23:54.251] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-08-13T20:23:54.253] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-08-13T20:23:54.255] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 6 relay1_07 false Profile: dusk - turnOn line according to lux sensor +[2025-08-13T20:23:54.257] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 7 relay1_08 false Profile: dusk - turnOn line according to lux sensor +[2025-08-14T03:34:00.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-14 03:34:00 +[2025-08-14T05:27:34.196] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-14T05:27:34.200] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-14T05:27:34.202] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-14T05:27:34.205] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-08-14T05:27:34.207] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-08-14T05:27:34.209] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 6 relay1_07 false Profile: dawn - turnOff line according to lux sensor +[2025-08-14T05:27:34.210] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 7 relay1_08 false Profile: dawn - turnOff line according to lux sensor +[2025-08-14T20:23:21.633] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-14T20:23:21.640] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-14T20:23:21.644] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-14T20:23:21.646] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-08-14T20:23:21.648] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-08-14T20:23:21.650] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 6 relay1_07 false Profile: dusk - turnOn line according to lux sensor +[2025-08-14T20:23:21.651] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 7 relay1_08 false Profile: dusk - turnOn line according to lux sensor +[2025-08-15T03:34:02.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-15 03:34:02 +[2025-08-15T05:30:57.435] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-15T05:30:57.443] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-15T05:30:57.445] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-15T05:30:57.447] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-08-15T05:30:57.450] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-08-15T05:30:57.452] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 6 relay1_07 false Profile: dawn - turnOff line according to lux sensor +[2025-08-15T05:30:57.453] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 7 relay1_08 false Profile: dawn - turnOff line according to lux sensor +[2025-08-15T20:19:25.951] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-15T20:19:25.958] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-15T20:19:25.960] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-15T20:19:25.963] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-08-15T20:19:25.965] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-08-15T20:19:25.967] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 6 relay1_07 false Profile: dusk - turnOn line according to lux sensor +[2025-08-15T20:19:25.969] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 7 relay1_08 false Profile: dusk - turnOn line according to lux sensor +[2025-08-16T03:34:04.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-16 03:34:04 +[2025-08-16T05:30:53.906] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-16T05:30:53.910] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-16T05:30:53.912] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-16T05:30:53.914] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-08-16T05:30:53.916] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-08-16T05:30:53.918] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 6 relay1_07 false Profile: dawn - turnOff line according to lux sensor +[2025-08-16T05:30:53.920] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 7 relay1_08 false Profile: dawn - turnOff line according to lux sensor +[2025-08-16T20:16:45.029] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-16T20:16:45.037] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-16T20:16:45.039] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-16T20:16:45.042] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-08-16T20:16:45.043] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-08-16T20:16:45.045] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 6 relay1_07 false Profile: dusk - turnOn line according to lux sensor +[2025-08-16T20:16:45.047] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 7 relay1_08 false Profile: dusk - turnOn line according to lux sensor +[2025-08-17T03:34:05.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-17 03:34:05 +[2025-08-17T05:33:52.517] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-17T05:33:52.521] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-17T05:33:52.523] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-17T05:33:52.525] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-08-17T05:33:52.527] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-08-17T05:33:52.529] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 6 relay1_07 false Profile: dawn - turnOff line according to lux sensor +[2025-08-17T05:33:52.530] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 7 relay1_08 false Profile: dawn - turnOff line according to lux sensor +[2025-08-17T20:17:04.529] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-17T20:17:04.536] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-17T20:17:04.539] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-17T20:17:04.541] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-08-17T20:17:04.543] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-08-17T20:17:04.545] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 6 relay1_07 false Profile: dusk - turnOn line according to lux sensor +[2025-08-17T20:17:04.547] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 7 relay1_08 false Profile: dusk - turnOn line according to lux sensor +[2025-08-18T03:34:07.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-18 03:34:07 +[2025-08-18T05:33:39.994] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-18T05:33:39.998] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-18T05:33:40.000] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-18T05:33:40.003] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-08-18T05:33:40.005] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-08-18T05:33:40.007] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 6 relay1_07 false Profile: dawn - turnOff line according to lux sensor +[2025-08-18T05:33:40.009] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 7 relay1_08 false Profile: dawn - turnOff line according to lux sensor +[2025-08-18T20:16:19.084] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-18T20:16:19.091] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-18T20:16:19.094] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-18T20:16:19.096] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-08-18T20:16:19.098] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-08-18T20:16:19.100] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 6 relay1_07 false Profile: dusk - turnOn line according to lux sensor +[2025-08-18T20:16:19.102] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 7 relay1_08 false Profile: dusk - turnOn line according to lux sensor +[2025-08-19T03:34:09.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-19 03:34:09 +[2025-08-19T05:34:25.378] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-19T05:34:25.386] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-19T05:34:25.389] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-19T05:34:25.391] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-08-19T05:34:25.393] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-08-19T05:34:25.395] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 6 relay1_07 false Profile: dawn - turnOff line according to lux sensor +[2025-08-19T05:34:25.397] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 7 relay1_08 false Profile: dawn - turnOff line according to lux sensor +[2025-08-19T20:15:23.839] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-19T20:15:23.845] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-19T20:15:23.847] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-19T20:15:23.849] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-08-19T20:15:23.851] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-08-19T20:15:23.852] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 6 relay1_07 false Profile: dusk - turnOn line according to lux sensor +[2025-08-19T20:15:23.854] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 7 relay1_08 false Profile: dusk - turnOn line according to lux sensor +[2025-08-20T03:34:10.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-20 03:34:10 +[2025-08-20T05:36:16.265] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-20T05:36:16.269] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-20T05:36:16.271] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-20T05:36:16.274] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-08-20T05:36:16.275] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-08-20T05:36:16.277] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 6 relay1_07 false Profile: dawn - turnOff line according to lux sensor +[2025-08-20T05:36:16.279] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 7 relay1_08 false Profile: dawn - turnOff line according to lux sensor +[2025-08-20T20:11:30.599] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-20T20:11:30.606] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-20T20:11:30.609] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-20T20:11:30.611] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-08-20T20:11:30.613] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-08-20T20:11:30.615] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 6 relay1_07 false Profile: dusk - turnOn line according to lux sensor +[2025-08-20T20:11:30.616] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 7 relay1_08 false Profile: dusk - turnOn line according to lux sensor +[2025-08-21T03:34:12.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-21 03:34:12 +[2025-08-21T05:42:20.049] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-21T05:42:20.059] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-21T05:42:20.061] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-21T05:42:20.064] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-08-21T05:42:20.067] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-08-21T05:42:20.068] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 6 relay1_07 false Profile: dawn - turnOff line according to lux sensor +[2025-08-21T05:42:20.070] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 7 relay1_08 false Profile: dawn - turnOff line according to lux sensor +[2025-08-21T15:50:14.081] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-08-21T15:50:19.435] [INFO] monitorLogs - buildTasks - params undefined +[2025-08-21T15:50:19.440] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-08-21T15:50:19.441] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-08-21T15:50:19.441] [INFO] monitorLogs - profile: { + 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 +} +[2025-08-21T15:50:19.446] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-08-21T15:50:19.447] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-08-22T04:23:00.446Z +[2025-08-21T15:50:19.449] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-08-21T18:27:00.448Z +[2025-08-21T15:50:19.449] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '6:23', name: 'luxOff' }, + { value: 1, start_time: '20:27', name: 'luxOn' } +] +[2025-08-21T15:50:19.450] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-08-21T15:50:19.451] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-08-21T15:50:19.452] [INFO] monitorLogs - profile: { + 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 +} +[2025-08-21T15:50:19.454] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-08-21T15:50:19.455] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-08-22T04:23:00.455Z +[2025-08-21T15:50:19.456] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-08-21T18:27:00.456Z +[2025-08-21T15:50:19.457] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '6:23', name: 'luxOff' }, + { value: 1, start_time: '20:27', name: 'luxOn' } +] +[2025-08-21T15:50:19.457] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-08-21T15:50:19.458] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-08-21T15:50:19.459] [INFO] monitorLogs - profile: { + 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 +} +[2025-08-21T15:50:19.461] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-08-21T15:50:19.462] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-08-22T04:23:00.462Z +[2025-08-21T15:50:19.463] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-08-21T18:27:00.463Z +[2025-08-21T15:50:19.464] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '6:23', name: 'luxOff' }, + { value: 1, start_time: '20:27', name: 'luxOn' } +] +[2025-08-21T15:50:19.465] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-08-21T15:50:19.466] [INFO] monitorLogs - buildTasks: profile for line 4 +[2025-08-21T15:50:19.467] [INFO] monitorLogs - profile: { + 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 +} +[2025-08-21T15:50:19.469] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-08-21T15:50:19.469] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 4 2025-08-22T04:23:00.469Z +[2025-08-21T15:50:19.470] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 4 2025-08-21T18:27:00.470Z +[2025-08-21T15:50:19.471] [INFO] monitorLogs - -->time_points final 4 [ + { value: 0, start_time: '6:23', name: 'luxOff' }, + { value: 1, start_time: '20:27', name: 'luxOn' } +] +[2025-08-21T15:50:19.472] [INFO] monitorLogs - -->currentValue for relay 4 0 +[2025-08-21T15:50:19.473] [INFO] monitorLogs - buildTasks: profile for line 5 +[2025-08-21T15:50:19.473] [INFO] monitorLogs - profile: { + 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 +} +[2025-08-21T15:50:19.475] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-08-21T15:50:19.476] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 5 2025-08-22T04:23:00.476Z +[2025-08-21T15:50:19.477] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 5 2025-08-21T18:27:00.476Z +[2025-08-21T15:50:19.477] [INFO] monitorLogs - -->time_points final 5 [ + { value: 0, start_time: '6:23', name: 'luxOff' }, + { value: 1, start_time: '20:27', name: 'luxOn' } +] +[2025-08-21T15:50:19.478] [INFO] monitorLogs - -->currentValue for relay 5 0 +[2025-08-21T15:50:19.479] [INFO] monitorLogs - buildTasks: profile for line 6 +[2025-08-21T15:50:19.479] [INFO] monitorLogs - profile: { + 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 +} +[2025-08-21T15:50:19.481] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-08-21T15:50:19.482] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 6 2025-08-22T04:23:00.482Z +[2025-08-21T15:50:19.483] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 6 2025-08-21T18:27:00.483Z +[2025-08-21T15:50:19.484] [INFO] monitorLogs - -->time_points final 6 [ + { value: 0, start_time: '6:23', name: 'luxOff' }, + { value: 1, start_time: '20:27', name: 'luxOn' } +] +[2025-08-21T15:50:19.485] [INFO] monitorLogs - -->currentValue for relay 6 0 +[2025-08-21T15:50:19.485] [INFO] monitorLogs - buildTasks: profile for line 7 +[2025-08-21T15:50:19.486] [INFO] monitorLogs - profile: { + 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 +} +[2025-08-21T15:50:19.505] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-08-21T15:50:19.505] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 7 2025-08-22T04:23:00.505Z +[2025-08-21T15:50:19.506] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 7 2025-08-21T18:27:00.506Z +[2025-08-21T15:50:19.507] [INFO] monitorLogs - -->time_points final 7 [ + { value: 0, start_time: '6:23', name: 'luxOff' }, + { value: 1, start_time: '20:27', name: 'luxOn' } +] +[2025-08-21T15:50:19.508] [INFO] monitorLogs - -->currentValue for relay 7 0 +[2025-08-21T15:50:19.516] [INFO] monitorLogs - tasks created: 1510 +[2025-08-21T15:50:19.518] [INFO] monitorLogs - -->FLOW bol spustený o9vbeQlLMVg8j5dq4keLWb0NxZpEmnXzwYKO1ar2 2025-08-08 +[2025-08-21T15:50:24.532] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-21T19:52:28.273] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-21T19:52:28.282] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-21T19:52:28.284] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-21T19:52:28.287] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-08-21T19:52:28.289] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-08-21T19:52:28.291] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 6 relay1_07 false Profile: dusk - turnOn line according to lux sensor +[2025-08-21T19:52:28.294] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 7 relay1_08 false Profile: dusk - turnOn line according to lux sensor +[2025-08-22T03:50:22.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-22 03:50:22 +[2025-08-22T05:46:18.547] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-22T05:46:18.555] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-22T05:46:18.557] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-22T05:46:18.560] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-08-22T05:46:18.562] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-08-22T05:46:18.564] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 6 relay1_07 false Profile: dawn - turnOff line according to lux sensor +[2025-08-22T05:46:18.566] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 7 relay1_08 false Profile: dawn - turnOff line according to lux sensor +[2025-08-22T20:06:13.396] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-22T20:06:13.403] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-22T20:06:13.406] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-22T20:06:13.408] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-08-22T20:06:13.410] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-08-22T20:06:13.412] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 6 relay1_07 false Profile: dusk - turnOn line according to lux sensor +[2025-08-22T20:06:13.414] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 7 relay1_08 false Profile: dusk - turnOn line according to lux sensor +[2025-08-23T03:50:28.251] [INFO] monitorLogs - setCorrectPlcTimeOnceADay - function error SyntaxError: Unexpected token < in JSON at position 0 + at JSON.parse () + at /home/unipi/flowserver/flow/cmd_manager.js:2375:28 + at Object.exec_callback [as callback] (/home/unipi/flowserver/node_modules/total.js/builders.js:5803:3) + at IncomingMessage.request_process_end (/home/unipi/flowserver/node_modules/total.js/utils.js:1184:11) + at IncomingMessage.emit (events.js:412:35) + at endReadableNT (internal/streams/readable.js:1334:12) + at processTicksAndRejections (internal/process/task_queues.js:82:21) 503: Service Unavailable
503
Service Unavailable
+[2025-08-23T05:42:56.109] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-23T05:42:56.116] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-23T05:42:56.119] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-23T05:42:56.121] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-08-23T05:42:56.123] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-08-23T05:42:56.125] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 6 relay1_07 false Profile: dawn - turnOff line according to lux sensor +[2025-08-23T05:42:56.127] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 7 relay1_08 false Profile: dawn - turnOff line according to lux sensor +[2025-08-23T20:03:28.831] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-23T20:03:28.839] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-23T20:03:28.841] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-23T20:03:28.843] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-08-23T20:03:28.845] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-08-23T20:03:28.847] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 6 relay1_07 false Profile: dusk - turnOn line according to lux sensor +[2025-08-23T20:03:28.848] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 7 relay1_08 false Profile: dusk - turnOn line according to lux sensor +[2025-08-24T03:50:25.018] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-24 03:50:25 +[2025-08-24T05:44:03.331] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-24T05:44:03.337] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-24T05:44:03.339] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-24T05:44:03.341] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-08-24T05:44:03.344] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-08-24T05:44:03.346] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 6 relay1_07 false Profile: dawn - turnOff line according to lux sensor +[2025-08-24T05:44:03.348] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 7 relay1_08 false Profile: dawn - turnOff line according to lux sensor +[2025-08-24T20:04:49.389] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-24T20:04:49.397] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-24T20:04:49.399] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-24T20:04:49.401] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-08-24T20:04:49.403] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-08-24T20:04:49.405] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 6 relay1_07 false Profile: dusk - turnOn line according to lux sensor +[2025-08-24T20:04:49.407] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 7 relay1_08 false Profile: dusk - turnOn line according to lux sensor +[2025-08-25T03:50:26.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-25 03:50:26 +[2025-08-25T05:45:29.203] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-25T05:45:29.209] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-25T05:45:29.211] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-25T05:45:29.213] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-08-25T05:45:29.216] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-08-25T05:45:29.218] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 6 relay1_07 false Profile: dawn - turnOff line according to lux sensor +[2025-08-25T05:45:29.220] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 7 relay1_08 false Profile: dawn - turnOff line according to lux sensor +[2025-08-25T20:00:24.878] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-25T20:00:24.885] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-25T20:00:24.887] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-25T20:00:24.889] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-08-25T20:00:24.891] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-08-25T20:00:24.893] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 6 relay1_07 false Profile: dusk - turnOn line according to lux sensor +[2025-08-25T20:00:24.895] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 7 relay1_08 false Profile: dusk - turnOn line according to lux sensor +[2025-08-26T03:50:28.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-26 03:50:28 +[2025-08-26T05:46:35.009] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-26T05:46:35.017] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-26T05:46:35.020] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-26T05:46:35.022] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-08-26T05:46:35.024] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-08-26T05:46:35.026] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 6 relay1_07 false Profile: dawn - turnOff line according to lux sensor +[2025-08-26T05:46:35.028] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 7 relay1_08 false Profile: dawn - turnOff line according to lux sensor +[2025-08-26T20:00:13.824] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-26T20:00:13.831] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-26T20:00:13.833] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-26T20:00:13.835] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-08-26T20:00:13.837] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-08-26T20:00:13.839] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 6 relay1_07 false Profile: dusk - turnOn line according to lux sensor +[2025-08-26T20:00:13.841] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 7 relay1_08 false Profile: dusk - turnOn line according to lux sensor +[2025-08-27T03:50:29.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-27 03:50:29 +[2025-08-27T05:48:29.133] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-27T05:48:29.137] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-27T05:48:29.140] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-27T05:48:29.142] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-08-27T05:48:29.144] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-08-27T05:48:29.146] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 6 relay1_07 false Profile: dawn - turnOff line according to lux sensor +[2025-08-27T05:48:29.148] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 7 relay1_08 false Profile: dawn - turnOff line according to lux sensor +[2025-08-27T19:56:13.913] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-27T19:56:13.920] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-27T19:56:13.923] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-27T19:56:13.925] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-08-27T19:56:13.927] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-08-27T19:56:13.929] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 6 relay1_07 false Profile: dusk - turnOn line according to lux sensor +[2025-08-27T19:56:13.931] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 7 relay1_08 false Profile: dusk - turnOn line according to lux sensor +[2025-08-28T03:50:31.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-28 03:50:31 +[2025-08-28T05:47:54.230] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-28T05:47:54.236] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-28T05:47:54.238] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-28T05:47:54.240] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-08-28T05:47:54.242] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-08-28T05:47:54.243] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 6 relay1_07 false Profile: dawn - turnOff line according to lux sensor +[2025-08-28T05:47:54.245] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 7 relay1_08 false Profile: dawn - turnOff line according to lux sensor +[2025-08-28T05:50:31.039] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 6 relay1_07 false Profile: dawn - turnOff line according to lux sensor +[2025-08-28T19:55:13.939] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-28T19:55:13.945] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-28T19:55:13.947] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-28T19:55:13.949] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-08-28T19:55:13.951] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-08-28T19:55:13.953] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 6 relay1_07 false Profile: dusk - turnOn line according to lux sensor +[2025-08-28T19:55:13.955] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 7 relay1_08 false Profile: dusk - turnOn line according to lux sensor +[2025-08-29T03:50:33.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-29 03:50:33 +[2025-08-29T05:52:38.247] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-29T05:52:38.250] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-29T05:52:38.252] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-29T05:52:38.255] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-08-29T05:52:38.257] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-08-29T05:52:38.258] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 6 relay1_07 false Profile: dawn - turnOff line according to lux sensor +[2025-08-29T05:52:38.260] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 7 relay1_08 false Profile: dawn - turnOff line according to lux sensor +[2025-08-29T19:44:11.724] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-29T19:44:11.732] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-29T19:44:11.734] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-29T19:44:11.736] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-08-29T19:44:11.738] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-08-29T19:44:11.740] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 6 relay1_07 false Profile: dusk - turnOn line according to lux sensor +[2025-08-29T19:44:11.741] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 7 relay1_08 false Profile: dusk - turnOn line according to lux sensor +[2025-08-30T03:50:35.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-30 03:50:35 +[2025-08-30T05:51:30.140] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-30T05:51:30.143] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-30T05:51:30.145] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-30T05:51:30.148] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-08-30T05:51:30.150] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-08-30T05:51:30.152] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 6 relay1_07 false Profile: dawn - turnOff line according to lux sensor +[2025-08-30T05:51:30.154] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 7 relay1_08 false Profile: dawn - turnOff line according to lux sensor +[2025-08-30T19:35:38.088] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-30T19:35:38.095] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-30T19:35:38.097] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-30T19:35:38.100] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-08-30T19:35:38.102] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-08-30T19:35:38.104] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 6 relay1_07 false Profile: dusk - turnOn line according to lux sensor +[2025-08-30T19:35:38.106] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 7 relay1_08 false Profile: dusk - turnOn line according to lux sensor +[2025-08-31T03:50:36.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-31 03:50:36 +[2025-08-31T06:05:42.099] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-31T06:05:42.103] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-31T06:05:42.105] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-31T06:05:42.107] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-08-31T06:05:42.109] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-08-31T06:05:42.111] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 6 relay1_07 false Profile: dawn - turnOff line according to lux sensor +[2025-08-31T06:05:42.113] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 7 relay1_08 false Profile: dawn - turnOff line according to lux sensor +[2025-08-31T19:49:59.366] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-31T19:49:59.373] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-31T19:49:59.376] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-31T19:49:59.378] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-08-31T19:49:59.379] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-08-31T19:49:59.381] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 6 relay1_07 false Profile: dusk - turnOn line according to lux sensor +[2025-08-31T19:49:59.383] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 7 relay1_08 false Profile: dusk - turnOn line according to lux sensor +[2025-09-01T03:50:38.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-01 03:50:38 +[2025-09-01T05:55:38.886] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-01T05:55:38.889] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-01T05:55:38.891] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-01T05:55:38.894] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-09-01T05:55:38.896] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-09-01T05:55:38.898] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 6 relay1_07 false Profile: dawn - turnOff line according to lux sensor +[2025-09-01T05:55:38.900] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 7 relay1_08 false Profile: dawn - turnOff line according to lux sensor +[2025-09-01T19:47:19.447] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-01T19:47:19.454] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-01T19:47:19.457] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-01T19:47:19.459] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-09-01T19:47:19.461] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-09-01T19:47:19.462] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 6 relay1_07 false Profile: dusk - turnOn line according to lux sensor +[2025-09-01T19:47:19.464] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 7 relay1_08 false Profile: dusk - turnOn line according to lux sensor +[2025-09-02T03:50:40.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-02 03:50:40 +[2025-09-02T05:55:30.470] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-02T05:55:30.473] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-02T05:55:30.475] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-02T05:55:30.477] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-09-02T05:55:30.479] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-09-02T05:55:30.481] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 6 relay1_07 false Profile: dawn - turnOff line according to lux sensor +[2025-09-02T05:55:30.483] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 7 relay1_08 false Profile: dawn - turnOff line according to lux sensor +[2025-09-02T19:36:57.837] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-02T19:36:57.844] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-02T19:36:57.846] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-02T19:36:57.848] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-09-02T19:36:57.850] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-09-02T19:36:57.852] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 6 relay1_07 false Profile: dusk - turnOn line according to lux sensor +[2025-09-02T19:36:57.854] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 7 relay1_08 false Profile: dusk - turnOn line according to lux sensor +[2025-09-03T03:50:41.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-03 03:50:41 +[2025-09-03T06:03:58.805] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-03T06:03:58.809] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-03T06:03:58.811] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-03T06:03:58.814] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-09-03T06:03:58.816] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-09-03T06:03:58.818] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 6 relay1_07 false Profile: dawn - turnOff line according to lux sensor +[2025-09-03T06:03:58.820] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 7 relay1_08 false Profile: dawn - turnOff line according to lux sensor +[2025-09-03T19:43:01.096] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-03T19:43:01.104] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-03T19:43:01.106] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-03T19:43:01.108] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-09-03T19:43:01.110] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-09-03T19:43:01.112] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 6 relay1_07 false Profile: dusk - turnOn line according to lux sensor +[2025-09-03T19:43:01.114] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 7 relay1_08 false Profile: dusk - turnOn line according to lux sensor +[2025-09-04T03:50:43.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-04 03:50:43 +[2025-09-04T05:58:37.110] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-04T05:58:37.113] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-04T05:58:37.116] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-04T05:58:37.119] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-09-04T05:58:37.120] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-09-04T05:58:37.122] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 6 relay1_07 false Profile: dawn - turnOff line according to lux sensor +[2025-09-04T05:58:37.124] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 7 relay1_08 false Profile: dawn - turnOff line according to lux sensor +[2025-09-04T19:41:57.142] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-04T19:41:57.149] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-04T19:41:57.152] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-04T19:41:57.154] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-09-04T19:41:57.156] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-09-04T19:41:57.157] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 6 relay1_07 false Profile: dusk - turnOn line according to lux sensor +[2025-09-04T19:41:57.159] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 7 relay1_08 false Profile: dusk - turnOn line according to lux sensor +[2025-09-05T03:50:45.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-05 03:50:45 +[2025-09-05T06:00:53.280] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-05T06:00:53.284] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-05T06:00:53.286] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-05T06:00:53.289] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-09-05T06:00:53.291] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-09-05T06:00:53.293] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 6 relay1_07 false Profile: dawn - turnOff line according to lux sensor +[2025-09-05T06:00:53.295] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 7 relay1_08 false Profile: dawn - turnOff line according to lux sensor +[2025-09-05T19:38:01.056] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-05T19:38:01.064] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-05T19:38:01.066] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-05T19:38:01.068] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-09-05T19:38:01.070] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-09-05T19:38:01.072] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 6 relay1_07 false Profile: dusk - turnOn line according to lux sensor +[2025-09-05T19:38:01.074] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 7 relay1_08 false Profile: dusk - turnOn line according to lux sensor +[2025-09-06T03:50:46.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-06 03:50:46 +[2025-09-06T06:16:04.090] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-06T06:16:04.098] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-06T06:16:04.100] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-06T06:16:04.102] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-09-06T06:16:04.104] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-09-06T06:16:04.106] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 6 relay1_07 false Profile: dawn - turnOff line according to lux sensor +[2025-09-06T06:16:04.108] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 7 relay1_08 false Profile: dawn - turnOff line according to lux sensor +[2025-09-06T19:36:44.487] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-06T19:36:44.495] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-06T19:36:44.497] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-06T19:36:44.499] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-09-06T19:36:44.501] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-09-06T19:36:44.503] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 6 relay1_07 false Profile: dusk - turnOn line according to lux sensor +[2025-09-06T19:36:44.505] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 7 relay1_08 false Profile: dusk - turnOn line according to lux sensor +[2025-09-07T03:50:48.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-07 03:50:48 +[2025-09-07T06:03:04.571] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-07T06:03:04.575] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-07T06:03:04.577] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-07T06:03:04.579] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-09-07T06:03:04.581] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-09-07T06:03:04.583] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 6 relay1_07 false Profile: dawn - turnOff line according to lux sensor +[2025-09-07T06:03:04.584] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 7 relay1_08 false Profile: dawn - turnOff line according to lux sensor +[2025-09-07T19:32:48.374] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-07T19:32:48.376] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-07T19:32:48.378] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-07T19:32:48.380] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-09-07T19:32:48.382] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-09-07T19:32:48.384] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 6 relay1_07 false Profile: dusk - turnOn line according to lux sensor +[2025-09-07T19:32:48.386] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 7 relay1_08 false Profile: dusk - turnOn line according to lux sensor +[2025-09-08T03:50:50.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-08 03:50:50 +[2025-09-08T06:03:12.580] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-08T06:03:12.584] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-08T06:03:12.586] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-08T06:03:12.590] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-09-08T06:03:12.592] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-09-08T06:03:12.594] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 6 relay1_07 false Profile: dawn - turnOff line according to lux sensor +[2025-09-08T06:03:12.596] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 7 relay1_08 false Profile: dawn - turnOff line according to lux sensor +[2025-09-08T19:34:14.294] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-08T19:34:14.302] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-08T19:34:14.305] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-08T19:34:14.307] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-09-08T19:34:14.309] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-09-08T19:34:14.311] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 6 relay1_07 false Profile: dusk - turnOn line according to lux sensor +[2025-09-08T19:34:14.312] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 7 relay1_08 false Profile: dusk - turnOn line according to lux sensor +[2025-09-09T03:50:51.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-09 03:50:51 +[2025-09-09T06:06:53.402] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-09T06:06:53.409] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-09T06:06:53.412] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-09T06:06:53.414] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-09-09T06:06:53.416] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-09-09T06:06:53.418] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 6 relay1_07 false Profile: dawn - turnOff line according to lux sensor +[2025-09-09T06:06:53.420] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 7 relay1_08 false Profile: dawn - turnOff line according to lux sensor +[2025-09-09T12:27:06.315] [INFO] monitorLogs - turnLine on - (line, SETTINGS.maintenance_mode) 0 true command received from platform +[2025-09-09T12:27:16.497] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false command received from platform +[2025-09-09T12:27:26.142] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false command received from platform +[2025-09-09T12:27:32.869] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false command received from platform +[2025-09-09T12:27:41.822] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false command received from platform +[2025-09-09T12:27:45.982] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false command received from platform +[2025-09-09T12:27:54.302] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false command received from platform +[2025-09-09T12:27:57.501] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false command received from platform +[2025-09-09T12:28:06.461] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false command received from platform +[2025-09-09T12:28:12.541] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false command received from platform +[2025-09-09T12:28:19.902] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false command received from platform +[2025-09-09T12:28:23.421] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 6 relay1_07 false command received from platform +[2025-09-09T12:28:32.060] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 6 relay1_07 false command received from platform +[2025-09-09T12:28:35.581] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 7 relay1_08 false command received from platform +[2025-09-09T12:37:02.142] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false command received from platform +[2025-09-09T12:37:11.094] [INFO] monitorLogs - turnLine on - (line, SETTINGS.maintenance_mode) 0 true command received from platform +[2025-09-09T12:37:18.960] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 7 relay1_08 false command received from platform +[2025-09-09T12:45:49.482] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 7 relay1_08 false command received from platform +[2025-09-09T13:05:55.860] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 7 relay1_08 false command received from platform +[2025-09-09T13:06:00.981] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false command received from platform +[2025-09-09T19:27:26.324] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-09T19:27:26.326] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-09T19:27:26.329] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-09T19:27:26.331] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-09-09T19:27:26.333] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-09-09T19:27:26.335] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 6 relay1_07 false Profile: dusk - turnOn line according to lux sensor +[2025-09-09T19:27:26.337] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 7 relay1_08 false Profile: dusk - turnOn line according to lux sensor +[2025-09-10T03:50:53.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-10 03:50:53 +[2025-09-10T06:07:51.871] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-10T06:07:51.879] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-10T06:07:51.882] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-10T06:07:51.884] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-09-10T06:07:51.885] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-09-10T06:07:51.887] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 6 relay1_07 false Profile: dawn - turnOff line according to lux sensor +[2025-09-10T06:07:51.889] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 7 relay1_08 false Profile: dawn - turnOff line according to lux sensor +[2025-09-10T19:16:13.320] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-10T19:16:13.327] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-10T19:16:13.330] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-10T19:16:13.332] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-09-10T19:16:13.334] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-09-10T19:16:13.336] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 6 relay1_07 false Profile: dusk - turnOn line according to lux sensor +[2025-09-10T19:16:13.337] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 7 relay1_08 false Profile: dusk - turnOn line according to lux sensor +[2025-09-11T03:50:55.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-11 03:50:55 +[2025-09-11T06:15:44.182] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-11T06:15:44.190] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-11T06:15:44.192] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-11T06:15:44.195] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-09-11T06:15:44.196] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-09-11T06:15:44.198] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 6 relay1_07 false Profile: dawn - turnOff line according to lux sensor +[2025-09-11T06:15:44.200] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 7 relay1_08 false Profile: dawn - turnOff line according to lux sensor +[2025-09-11T08:44:39.140] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-09-11T08:44:44.487] [INFO] monitorLogs - buildTasks - params undefined +[2025-09-11T08:44:44.491] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-09-11T08:44:44.492] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-09-11T08:44:44.493] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-11T08:44:44.497] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-11T08:44:44.499] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-09-12T04:53:00.498Z +[2025-09-11T08:44:44.500] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-09-11T17:44:00.500Z +[2025-09-11T08:44:44.501] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '6:53', name: 'luxOff' }, + { value: 1, start_time: '19:44', name: 'luxOn' } +] +[2025-09-11T08:44:44.502] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-09-11T08:44:44.503] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-09-11T08:44:44.504] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-11T08:44:44.506] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-11T08:44:44.507] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-09-12T04:53:00.506Z +[2025-09-11T08:44:44.508] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-09-11T17:44:00.507Z +[2025-09-11T08:44:44.508] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '6:53', name: 'luxOff' }, + { value: 1, start_time: '19:44', name: 'luxOn' } +] +[2025-09-11T08:44:44.509] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-09-11T08:44:44.510] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-09-11T08:44:44.510] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-11T08:44:44.513] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-11T08:44:44.513] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-09-12T04:53:00.513Z +[2025-09-11T08:44:44.514] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-09-11T17:44:00.514Z +[2025-09-11T08:44:44.515] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '6:53', name: 'luxOff' }, + { value: 1, start_time: '19:44', name: 'luxOn' } +] +[2025-09-11T08:44:44.516] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-09-11T08:44:44.517] [INFO] monitorLogs - buildTasks: profile for line 4 +[2025-09-11T08:44:44.517] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-11T08:44:44.519] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-11T08:44:44.520] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 4 2025-09-12T04:53:00.520Z +[2025-09-11T08:44:44.521] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 4 2025-09-11T17:44:00.521Z +[2025-09-11T08:44:44.521] [INFO] monitorLogs - -->time_points final 4 [ + { value: 0, start_time: '6:53', name: 'luxOff' }, + { value: 1, start_time: '19:44', name: 'luxOn' } +] +[2025-09-11T08:44:44.522] [INFO] monitorLogs - -->currentValue for relay 4 0 +[2025-09-11T08:44:44.523] [INFO] monitorLogs - buildTasks: profile for line 5 +[2025-09-11T08:44:44.524] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-11T08:44:44.526] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-11T08:44:44.526] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 5 2025-09-12T04:53:00.526Z +[2025-09-11T08:44:44.527] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 5 2025-09-11T17:44:00.527Z +[2025-09-11T08:44:44.528] [INFO] monitorLogs - -->time_points final 5 [ + { value: 0, start_time: '6:53', name: 'luxOff' }, + { value: 1, start_time: '19:44', name: 'luxOn' } +] +[2025-09-11T08:44:44.546] [INFO] monitorLogs - -->currentValue for relay 5 0 +[2025-09-11T08:44:44.547] [INFO] monitorLogs - buildTasks: profile for line 6 +[2025-09-11T08:44:44.547] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-11T08:44:44.549] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-11T08:44:44.550] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 6 2025-09-12T04:53:00.550Z +[2025-09-11T08:44:44.551] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 6 2025-09-11T17:44:00.551Z +[2025-09-11T08:44:44.551] [INFO] monitorLogs - -->time_points final 6 [ + { value: 0, start_time: '6:53', name: 'luxOff' }, + { value: 1, start_time: '19:44', name: 'luxOn' } +] +[2025-09-11T08:44:44.552] [INFO] monitorLogs - -->currentValue for relay 6 0 +[2025-09-11T08:44:44.553] [INFO] monitorLogs - buildTasks: profile for line 7 +[2025-09-11T08:44:44.553] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-11T08:44:44.556] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-11T08:44:44.556] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 7 2025-09-12T04:53:00.556Z +[2025-09-11T08:44:44.557] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 7 2025-09-11T17:44:00.557Z +[2025-09-11T08:44:44.558] [INFO] monitorLogs - -->time_points final 7 [ + { value: 0, start_time: '6:53', name: 'luxOff' }, + { value: 1, start_time: '19:44', name: 'luxOn' } +] +[2025-09-11T08:44:44.559] [INFO] monitorLogs - -->currentValue for relay 7 0 +[2025-09-11T08:44:44.567] [INFO] monitorLogs - tasks created: 1510 +[2025-09-11T08:44:44.569] [INFO] monitorLogs - -->FLOW bol spustený o9vbeQlLMVg8j5dq4keLWb0NxZpEmnXzwYKO1ar2 2025-08-08 +[2025-09-11T08:44:49.584] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-11T19:26:02.547] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-11T19:26:02.557] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-11T19:26:02.560] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-11T19:26:02.562] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-09-11T19:26:02.565] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-09-11T19:26:02.567] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 6 relay1_07 false Profile: dusk - turnOn line according to lux sensor +[2025-09-11T19:26:02.569] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 7 relay1_08 false Profile: dusk - turnOn line according to lux sensor +[2025-09-12T03:44:45.017] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-12 03:44:45 +[2025-09-12T06:10:41.618] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-12T06:10:41.627] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-12T06:10:41.629] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-12T06:10:41.631] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-09-12T06:10:41.634] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-09-12T06:10:41.636] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 6 relay1_07 false Profile: dawn - turnOff line according to lux sensor +[2025-09-12T06:10:41.638] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 7 relay1_08 false Profile: dawn - turnOff line according to lux sensor +[2025-09-12T19:14:12.480] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-12T19:14:12.489] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-12T19:14:12.491] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-12T19:14:12.494] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-09-12T19:14:12.496] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-09-12T19:14:12.498] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 6 relay1_07 false Profile: dusk - turnOn line according to lux sensor +[2025-09-12T19:14:12.501] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 7 relay1_08 false Profile: dusk - turnOn line according to lux sensor +[2025-09-13T03:44:47.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-13 03:44:47 +[2025-09-13T06:25:58.413] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-13T06:25:58.422] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-13T06:25:58.425] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-13T06:25:58.427] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-09-13T06:25:58.429] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-09-13T06:25:58.431] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 6 relay1_07 false Profile: dawn - turnOff line according to lux sensor +[2025-09-13T06:25:58.433] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 7 relay1_08 false Profile: dawn - turnOff line according to lux sensor +[2025-09-13T19:17:18.995] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-13T19:17:19.003] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-13T19:17:19.005] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-13T19:17:19.007] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-09-13T19:17:19.010] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-09-13T19:17:19.012] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 6 relay1_07 false Profile: dusk - turnOn line according to lux sensor +[2025-09-13T19:17:19.013] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 7 relay1_08 false Profile: dusk - turnOn line according to lux sensor +[2025-09-14T03:44:48.013] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-14 03:44:48 +[2025-09-14T06:27:26.196] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-14T06:27:26.200] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-14T06:27:26.202] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-14T06:27:26.205] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-09-14T06:27:26.207] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-09-14T06:27:26.209] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 6 relay1_07 false Profile: dawn - turnOff line according to lux sensor +[2025-09-14T06:27:26.211] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 7 relay1_08 false Profile: dawn - turnOff line according to lux sensor +[2025-09-14T19:19:26.228] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-14T19:19:26.235] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-14T19:19:26.238] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-14T19:19:26.240] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-09-14T19:19:26.242] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-09-14T19:19:26.244] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 6 relay1_07 false Profile: dusk - turnOn line according to lux sensor +[2025-09-14T19:19:26.246] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 7 relay1_08 false Profile: dusk - turnOn line according to lux sensor +[2025-09-15T03:44:50.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-15 03:44:50 +[2025-09-15T06:14:14.077] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-15T06:14:14.086] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-15T06:14:14.088] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-15T06:14:14.091] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-09-15T06:14:14.093] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-09-15T06:14:14.095] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 6 relay1_07 false Profile: dawn - turnOff line according to lux sensor +[2025-09-15T06:14:14.096] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 7 relay1_08 false Profile: dawn - turnOff line according to lux sensor +[2025-09-15T19:18:36.931] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-15T19:18:36.939] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-15T19:18:36.942] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-15T19:18:36.944] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-09-15T19:18:36.946] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-09-15T19:18:36.948] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 6 relay1_07 false Profile: dusk - turnOn line according to lux sensor +[2025-09-15T19:18:36.950] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 7 relay1_08 false Profile: dusk - turnOn line according to lux sensor +[2025-09-16T03:44:51.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-16 03:44:51 +[2025-09-16T06:30:38.512] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-16T06:30:38.520] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-16T06:30:38.523] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-16T06:30:38.525] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-09-16T06:30:38.527] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-09-16T06:30:38.529] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 6 relay1_07 false Profile: dawn - turnOff line according to lux sensor +[2025-09-16T06:30:38.531] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 7 relay1_08 false Profile: dawn - turnOff line according to lux sensor +[2025-09-16T15:37:58.596] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-09-16T15:38:03.946] [INFO] monitorLogs - buildTasks - params undefined +[2025-09-16T15:38:03.952] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-09-16T15:38:03.953] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-09-16T15:38:03.953] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-16T15:38:03.958] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-16T15:38:03.960] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-09-17T05:00:00.959Z +[2025-09-16T15:38:03.961] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-09-16T17:34:00.961Z +[2025-09-16T15:38:03.962] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:0', name: 'luxOff' }, + { value: 1, start_time: '19:34', name: 'luxOn' } +] +[2025-09-16T15:38:03.963] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-09-16T15:38:03.964] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-09-16T15:38:03.965] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-16T15:38:03.967] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-16T15:38:03.968] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-09-17T05:00:00.968Z +[2025-09-16T15:38:03.969] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-09-16T17:34:00.969Z +[2025-09-16T15:38:03.970] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:0', name: 'luxOff' }, + { value: 1, start_time: '19:34', name: 'luxOn' } +] +[2025-09-16T15:38:03.971] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-09-16T15:38:03.972] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-09-16T15:38:03.973] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-16T15:38:03.975] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-16T15:38:03.976] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-09-17T05:00:00.976Z +[2025-09-16T15:38:03.977] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-09-16T17:34:00.977Z +[2025-09-16T15:38:03.978] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:0', name: 'luxOff' }, + { value: 1, start_time: '19:34', name: 'luxOn' } +] +[2025-09-16T15:38:03.979] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-09-16T15:38:03.980] [INFO] monitorLogs - buildTasks: profile for line 4 +[2025-09-16T15:38:03.981] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-16T15:38:03.984] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-16T15:38:03.984] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 4 2025-09-17T05:00:00.984Z +[2025-09-16T15:38:03.985] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 4 2025-09-16T17:34:00.985Z +[2025-09-16T15:38:03.986] [INFO] monitorLogs - -->time_points final 4 [ + { value: 0, start_time: '7:0', name: 'luxOff' }, + { value: 1, start_time: '19:34', name: 'luxOn' } +] +[2025-09-16T15:38:03.987] [INFO] monitorLogs - -->currentValue for relay 4 0 +[2025-09-16T15:38:03.988] [INFO] monitorLogs - buildTasks: profile for line 5 +[2025-09-16T15:38:03.989] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-16T15:38:03.991] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-16T15:38:03.992] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 5 2025-09-17T05:00:00.992Z +[2025-09-16T15:38:03.993] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 5 2025-09-16T17:34:00.993Z +[2025-09-16T15:38:03.994] [INFO] monitorLogs - -->time_points final 5 [ + { value: 0, start_time: '7:0', name: 'luxOff' }, + { value: 1, start_time: '19:34', name: 'luxOn' } +] +[2025-09-16T15:38:03.995] [INFO] monitorLogs - -->currentValue for relay 5 0 +[2025-09-16T15:38:03.995] [INFO] monitorLogs - buildTasks: profile for line 6 +[2025-09-16T15:38:03.996] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-16T15:38:03.998] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-16T15:38:03.999] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 6 2025-09-17T05:00:00.999Z +[2025-09-16T15:38:04.000] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 6 2025-09-16T17:34:00.000Z +[2025-09-16T15:38:04.001] [INFO] monitorLogs - -->time_points final 6 [ + { value: 0, start_time: '7:0', name: 'luxOff' }, + { value: 1, start_time: '19:34', name: 'luxOn' } +] +[2025-09-16T15:38:04.002] [INFO] monitorLogs - -->currentValue for relay 6 0 +[2025-09-16T15:38:04.003] [INFO] monitorLogs - buildTasks: profile for line 7 +[2025-09-16T15:38:04.003] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-16T15:38:04.006] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-16T15:38:04.006] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 7 2025-09-17T05:00:00.006Z +[2025-09-16T15:38:04.026] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 7 2025-09-16T17:34:00.026Z +[2025-09-16T15:38:04.027] [INFO] monitorLogs - -->time_points final 7 [ + { value: 0, start_time: '7:0', name: 'luxOff' }, + { value: 1, start_time: '19:34', name: 'luxOn' } +] +[2025-09-16T15:38:04.037] [INFO] monitorLogs - -->currentValue for relay 7 0 +[2025-09-16T15:38:04.045] [INFO] monitorLogs - tasks created: 1510 +[2025-09-16T15:38:04.049] [INFO] monitorLogs - -->FLOW bol spustený o9vbeQlLMVg8j5dq4keLWb0NxZpEmnXzwYKO1ar2 2025-08-08 +[2025-09-16T15:38:09.060] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-16T19:12:22.428] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-16T19:12:22.434] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-16T19:12:22.436] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-16T19:12:22.439] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-09-16T19:12:22.441] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-09-16T19:12:22.443] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 6 relay1_07 false Profile: dusk - turnOn line according to lux sensor +[2025-09-16T19:12:22.445] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 7 relay1_08 false Profile: dusk - turnOn line according to lux sensor +[2025-09-17T03:38:06.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-17 03:38:06 +[2025-09-17T06:21:40.883] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-17T06:21:40.887] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-17T06:21:40.889] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-17T06:21:40.891] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-09-17T06:21:40.893] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-09-17T06:21:40.894] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 6 relay1_07 false Profile: dawn - turnOff line according to lux sensor +[2025-09-17T06:21:40.896] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 7 relay1_08 false Profile: dawn - turnOff line according to lux sensor +[2025-09-17T19:14:44.606] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-17T19:14:44.611] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-17T19:14:44.614] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-17T19:14:44.616] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-09-17T19:14:44.618] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-09-17T19:14:44.620] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 6 relay1_07 false Profile: dusk - turnOn line according to lux sensor +[2025-09-17T19:14:44.621] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 7 relay1_08 false Profile: dusk - turnOn line according to lux sensor +[2025-09-17T20:32:26.716] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-09-17T20:32:32.063] [INFO] monitorLogs - buildTasks - params undefined +[2025-09-17T20:32:32.067] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-09-17T20:32:32.068] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-09-17T20:32:32.069] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-17T20:32:32.073] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-17T20:32:32.075] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-09-18T05:01:00.074Z +[2025-09-17T20:32:32.076] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-09-18T17:32:00.076Z +[2025-09-17T20:32:32.077] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:1', name: 'luxOff' }, + { value: 1, start_time: '19:32', name: 'luxOn' } +] +[2025-09-17T20:32:32.078] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-09-17T20:32:32.079] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-09-17T20:32:32.079] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-17T20:32:32.082] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-17T20:32:32.082] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-09-18T05:01:00.082Z +[2025-09-17T20:32:32.083] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-09-18T17:32:00.083Z +[2025-09-17T20:32:32.084] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:1', name: 'luxOff' }, + { value: 1, start_time: '19:32', name: 'luxOn' } +] +[2025-09-17T20:32:32.085] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-09-17T20:32:32.086] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-09-17T20:32:32.086] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-17T20:32:32.089] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-17T20:32:32.089] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-09-18T05:01:00.089Z +[2025-09-17T20:32:32.090] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-09-18T17:32:00.090Z +[2025-09-17T20:32:32.091] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:1', name: 'luxOff' }, + { value: 1, start_time: '19:32', name: 'luxOn' } +] +[2025-09-17T20:32:32.092] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-09-17T20:32:32.092] [INFO] monitorLogs - buildTasks: profile for line 4 +[2025-09-17T20:32:32.093] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-17T20:32:32.095] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-17T20:32:32.096] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 4 2025-09-18T05:01:00.096Z +[2025-09-17T20:32:32.097] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 4 2025-09-18T17:32:00.097Z +[2025-09-17T20:32:32.097] [INFO] monitorLogs - -->time_points final 4 [ + { value: 0, start_time: '7:1', name: 'luxOff' }, + { value: 1, start_time: '19:32', name: 'luxOn' } +] +[2025-09-17T20:32:32.098] [INFO] monitorLogs - -->currentValue for relay 4 1 +[2025-09-17T20:32:32.099] [INFO] monitorLogs - buildTasks: profile for line 5 +[2025-09-17T20:32:32.100] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-17T20:32:32.102] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-17T20:32:32.102] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 5 2025-09-18T05:01:00.102Z +[2025-09-17T20:32:32.103] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 5 2025-09-18T17:32:00.103Z +[2025-09-17T20:32:32.121] [INFO] monitorLogs - -->time_points final 5 [ + { value: 0, start_time: '7:1', name: 'luxOff' }, + { value: 1, start_time: '19:32', name: 'luxOn' } +] +[2025-09-17T20:32:32.122] [INFO] monitorLogs - -->currentValue for relay 5 1 +[2025-09-17T20:32:32.123] [INFO] monitorLogs - buildTasks: profile for line 6 +[2025-09-17T20:32:32.124] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-17T20:32:32.126] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-17T20:32:32.126] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 6 2025-09-18T05:01:00.126Z +[2025-09-17T20:32:32.127] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 6 2025-09-18T17:32:00.127Z +[2025-09-17T20:32:32.128] [INFO] monitorLogs - -->time_points final 6 [ + { value: 0, start_time: '7:1', name: 'luxOff' }, + { value: 1, start_time: '19:32', name: 'luxOn' } +] +[2025-09-17T20:32:32.129] [INFO] monitorLogs - -->currentValue for relay 6 1 +[2025-09-17T20:32:32.130] [INFO] monitorLogs - buildTasks: profile for line 7 +[2025-09-17T20:32:32.130] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-17T20:32:32.133] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-17T20:32:32.133] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 7 2025-09-18T05:01:00.133Z +[2025-09-17T20:32:32.134] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 7 2025-09-18T17:32:00.134Z +[2025-09-17T20:32:32.135] [INFO] monitorLogs - -->time_points final 7 [ + { value: 0, start_time: '7:1', name: 'luxOff' }, + { value: 1, start_time: '19:32', name: 'luxOn' } +] +[2025-09-17T20:32:32.136] [INFO] monitorLogs - -->currentValue for relay 7 1 +[2025-09-17T20:32:32.144] [INFO] monitorLogs - tasks created: 1510 +[2025-09-17T20:32:32.146] [INFO] monitorLogs - -->FLOW bol spustený o9vbeQlLMVg8j5dq4keLWb0NxZpEmnXzwYKO1ar2 2025-08-08 +[2025-09-17T20:32:37.159] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-18T03:32:34.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-18 03:32:34 +[2025-09-18T06:21:58.213] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-18T06:21:58.219] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-18T06:21:58.221] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-18T06:21:58.223] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-09-18T06:21:58.225] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-09-18T06:21:58.227] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 6 relay1_07 false Profile: dawn - turnOff line according to lux sensor +[2025-09-18T06:21:58.228] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 7 relay1_08 false Profile: dawn - turnOff line according to lux sensor +[2025-09-18T19:11:52.445] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-18T19:11:52.450] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-18T19:11:52.452] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-18T19:11:52.454] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-09-18T19:11:52.456] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-09-18T19:11:52.458] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 6 relay1_07 false Profile: dusk - turnOn line according to lux sensor +[2025-09-18T19:11:52.460] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 7 relay1_08 false Profile: dusk - turnOn line according to lux sensor +[2025-09-19T03:32:36.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-19 03:32:36 +[2025-09-19T06:17:28.624] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-19T06:17:28.630] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-19T06:17:28.632] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-19T06:17:28.634] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-09-19T06:17:28.636] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-09-19T06:17:28.638] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 6 relay1_07 false Profile: dawn - turnOff line according to lux sensor +[2025-09-19T06:17:28.640] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 7 relay1_08 false Profile: dawn - turnOff line according to lux sensor +[2025-09-19T11:11:58.428] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-09-19T11:12:03.786] [INFO] monitorLogs - buildTasks - params undefined +[2025-09-19T11:12:03.790] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-09-19T11:12:03.791] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-09-19T11:12:03.792] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-19T11:12:03.796] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-19T11:12:03.797] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-09-20T05:04:00.797Z +[2025-09-19T11:12:03.799] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-09-19T17:27:00.798Z +[2025-09-19T11:12:03.799] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:4', name: 'luxOff' }, + { value: 1, start_time: '19:27', name: 'luxOn' } +] +[2025-09-19T11:12:03.801] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-09-19T11:12:03.802] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-09-19T11:12:03.802] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-19T11:12:03.805] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-19T11:12:03.805] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-09-20T05:04:00.805Z +[2025-09-19T11:12:03.806] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-09-19T17:27:00.806Z +[2025-09-19T11:12:03.807] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:4', name: 'luxOff' }, + { value: 1, start_time: '19:27', name: 'luxOn' } +] +[2025-09-19T11:12:03.808] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-09-19T11:12:03.809] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-09-19T11:12:03.809] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-19T11:12:03.811] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-19T11:12:03.812] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-09-20T05:04:00.812Z +[2025-09-19T11:12:03.813] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-09-19T17:27:00.813Z +[2025-09-19T11:12:03.813] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:4', name: 'luxOff' }, + { value: 1, start_time: '19:27', name: 'luxOn' } +] +[2025-09-19T11:12:03.814] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-09-19T11:12:03.815] [INFO] monitorLogs - buildTasks: profile for line 4 +[2025-09-19T11:12:03.816] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-19T11:12:03.818] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-19T11:12:03.818] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 4 2025-09-20T05:04:00.818Z +[2025-09-19T11:12:03.819] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 4 2025-09-19T17:27:00.819Z +[2025-09-19T11:12:03.820] [INFO] monitorLogs - -->time_points final 4 [ + { value: 0, start_time: '7:4', name: 'luxOff' }, + { value: 1, start_time: '19:27', name: 'luxOn' } +] +[2025-09-19T11:12:03.821] [INFO] monitorLogs - -->currentValue for relay 4 0 +[2025-09-19T11:12:03.822] [INFO] monitorLogs - buildTasks: profile for line 5 +[2025-09-19T11:12:03.822] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-19T11:12:03.824] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-19T11:12:03.825] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 5 2025-09-20T05:04:00.825Z +[2025-09-19T11:12:03.826] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 5 2025-09-19T17:27:00.826Z +[2025-09-19T11:12:03.827] [INFO] monitorLogs - -->time_points final 5 [ + { value: 0, start_time: '7:4', name: 'luxOff' }, + { value: 1, start_time: '19:27', name: 'luxOn' } +] +[2025-09-19T11:12:03.828] [INFO] monitorLogs - -->currentValue for relay 5 0 +[2025-09-19T11:12:03.828] [INFO] monitorLogs - buildTasks: profile for line 6 +[2025-09-19T11:12:03.829] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-19T11:12:03.831] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-19T11:12:03.832] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 6 2025-09-20T05:04:00.831Z +[2025-09-19T11:12:03.850] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 6 2025-09-19T17:27:00.850Z +[2025-09-19T11:12:03.851] [INFO] monitorLogs - -->time_points final 6 [ + { value: 0, start_time: '7:4', name: 'luxOff' }, + { value: 1, start_time: '19:27', name: 'luxOn' } +] +[2025-09-19T11:12:03.852] [INFO] monitorLogs - -->currentValue for relay 6 0 +[2025-09-19T11:12:03.853] [INFO] monitorLogs - buildTasks: profile for line 7 +[2025-09-19T11:12:03.854] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-19T11:12:03.856] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-19T11:12:03.857] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 7 2025-09-20T05:04:00.856Z +[2025-09-19T11:12:03.857] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 7 2025-09-19T17:27:00.857Z +[2025-09-19T11:12:03.858] [INFO] monitorLogs - -->time_points final 7 [ + { value: 0, start_time: '7:4', name: 'luxOff' }, + { value: 1, start_time: '19:27', name: 'luxOn' } +] +[2025-09-19T11:12:03.859] [INFO] monitorLogs - -->currentValue for relay 7 0 +[2025-09-19T11:12:03.867] [INFO] monitorLogs - tasks created: 1510 +[2025-09-19T11:12:03.870] [INFO] monitorLogs - -->FLOW bol spustený o9vbeQlLMVg8j5dq4keLWb0NxZpEmnXzwYKO1ar2 2025-08-08 +[2025-09-19T11:12:08.883] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-19T19:11:57.433] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-19T19:11:57.440] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-19T19:11:57.442] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-19T19:11:57.445] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-09-19T19:11:57.447] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-09-19T19:11:57.449] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 6 relay1_07 false Profile: dusk - turnOn line according to lux sensor +[2025-09-19T19:11:57.451] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 7 relay1_08 false Profile: dusk - turnOn line according to lux sensor +[2025-09-20T03:12:05.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-20 03:12:05 +[2025-09-20T06:20:37.476] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-20T06:20:37.482] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-20T06:20:37.484] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-20T06:20:37.486] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-09-20T06:20:37.488] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-09-20T06:20:37.491] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 6 relay1_07 false Profile: dawn - turnOff line according to lux sensor +[2025-09-20T06:20:37.492] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 7 relay1_08 false Profile: dawn - turnOff line according to lux sensor +[2025-09-20T19:07:56.748] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-20T19:07:56.754] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-20T19:07:56.756] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-20T19:07:56.758] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-09-20T19:07:56.760] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-09-20T19:07:56.762] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 6 relay1_07 false Profile: dusk - turnOn line according to lux sensor +[2025-09-20T19:07:56.764] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 7 relay1_08 false Profile: dusk - turnOn line according to lux sensor +[2025-09-21T01:29:27.615] [INFO] monitorLogs - MQTT client error Error: connect ECONNREFUSED 192.168.252.1:1883 + at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1159:16) { + errno: -111, + code: 'ECONNREFUSED', + syscall: 'connect', + address: '192.168.252.1', + port: 1883 +} +[2025-09-21T03:12:07.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-21 03:12:07 +[2025-09-21T06:21:25.744] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-21T06:21:25.749] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-21T06:21:25.751] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-21T06:21:25.753] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-09-21T06:21:25.755] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-09-21T06:21:25.757] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 6 relay1_07 false Profile: dawn - turnOff line according to lux sensor +[2025-09-21T06:21:25.759] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 7 relay1_08 false Profile: dawn - turnOff line according to lux sensor +[2025-09-21T18:05:46.757] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-09-21T18:05:52.115] [INFO] monitorLogs - buildTasks - params undefined +[2025-09-21T18:05:52.120] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-09-21T18:05:52.121] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-09-21T18:05:52.122] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-21T18:05:52.126] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-21T18:05:52.127] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-09-22T05:07:00.127Z +[2025-09-21T18:05:52.129] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-09-21T17:23:00.129Z +[2025-09-21T18:05:52.130] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:7', name: 'luxOff' }, + { value: 1, start_time: '19:23', name: 'luxOn' } +] +[2025-09-21T18:05:52.131] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-09-21T18:05:52.132] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-09-21T18:05:52.132] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-21T18:05:52.135] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-21T18:05:52.135] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-09-22T05:07:00.135Z +[2025-09-21T18:05:52.136] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-09-21T17:23:00.136Z +[2025-09-21T18:05:52.137] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:7', name: 'luxOff' }, + { value: 1, start_time: '19:23', name: 'luxOn' } +] +[2025-09-21T18:05:52.138] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-09-21T18:05:52.139] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-09-21T18:05:52.139] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-21T18:05:52.141] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-21T18:05:52.142] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-09-22T05:07:00.142Z +[2025-09-21T18:05:52.143] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-09-21T17:23:00.143Z +[2025-09-21T18:05:52.144] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:7', name: 'luxOff' }, + { value: 1, start_time: '19:23', name: 'luxOn' } +] +[2025-09-21T18:05:52.145] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-09-21T18:05:52.145] [INFO] monitorLogs - buildTasks: profile for line 4 +[2025-09-21T18:05:52.146] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-21T18:05:52.148] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-21T18:05:52.149] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 4 2025-09-22T05:07:00.149Z +[2025-09-21T18:05:52.150] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 4 2025-09-21T17:23:00.150Z +[2025-09-21T18:05:52.150] [INFO] monitorLogs - -->time_points final 4 [ + { value: 0, start_time: '7:7', name: 'luxOff' }, + { value: 1, start_time: '19:23', name: 'luxOn' } +] +[2025-09-21T18:05:52.151] [INFO] monitorLogs - -->currentValue for relay 4 0 +[2025-09-21T18:05:52.152] [INFO] monitorLogs - buildTasks: profile for line 5 +[2025-09-21T18:05:52.153] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-21T18:05:52.155] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-21T18:05:52.155] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 5 2025-09-22T05:07:00.155Z +[2025-09-21T18:05:52.156] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 5 2025-09-21T17:23:00.156Z +[2025-09-21T18:05:52.157] [INFO] monitorLogs - -->time_points final 5 [ + { value: 0, start_time: '7:7', name: 'luxOff' }, + { value: 1, start_time: '19:23', name: 'luxOn' } +] +[2025-09-21T18:05:52.158] [INFO] monitorLogs - -->currentValue for relay 5 0 +[2025-09-21T18:05:52.159] [INFO] monitorLogs - buildTasks: profile for line 6 +[2025-09-21T18:05:52.159] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-21T18:05:52.179] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-21T18:05:52.180] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 6 2025-09-22T05:07:00.180Z +[2025-09-21T18:05:52.181] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 6 2025-09-21T17:23:00.180Z +[2025-09-21T18:05:52.181] [INFO] monitorLogs - -->time_points final 6 [ + { value: 0, start_time: '7:7', name: 'luxOff' }, + { value: 1, start_time: '19:23', name: 'luxOn' } +] +[2025-09-21T18:05:52.182] [INFO] monitorLogs - -->currentValue for relay 6 0 +[2025-09-21T18:05:52.183] [INFO] monitorLogs - buildTasks: profile for line 7 +[2025-09-21T18:05:52.183] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-21T18:05:52.186] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-21T18:05:52.187] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 7 2025-09-22T05:07:00.186Z +[2025-09-21T18:05:52.187] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 7 2025-09-21T17:23:00.187Z +[2025-09-21T18:05:52.188] [INFO] monitorLogs - -->time_points final 7 [ + { value: 0, start_time: '7:7', name: 'luxOff' }, + { value: 1, start_time: '19:23', name: 'luxOn' } +] +[2025-09-21T18:05:52.189] [INFO] monitorLogs - -->currentValue for relay 7 0 +[2025-09-21T18:05:52.197] [INFO] monitorLogs - tasks created: 1510 +[2025-09-21T18:05:52.200] [INFO] monitorLogs - -->FLOW bol spustený o9vbeQlLMVg8j5dq4keLWb0NxZpEmnXzwYKO1ar2 2025-08-08 +[2025-09-21T18:05:57.213] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-21T19:05:34.042] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-21T19:05:34.048] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-21T19:05:34.050] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-21T19:05:34.052] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-09-21T19:05:34.055] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-09-21T19:05:34.057] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 6 relay1_07 false Profile: dusk - turnOn line according to lux sensor +[2025-09-21T19:05:34.059] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 7 relay1_08 false Profile: dusk - turnOn line according to lux sensor +[2025-09-22T03:05:54.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-22 03:05:54 +[2025-09-22T06:21:36.451] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-22T06:21:36.457] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-22T06:21:36.459] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-22T06:21:36.462] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-09-22T06:21:36.464] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-09-22T06:21:36.466] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 6 relay1_07 false Profile: dawn - turnOff line according to lux sensor +[2025-09-22T06:21:36.468] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 7 relay1_08 false Profile: dawn - turnOff line according to lux sensor +[2025-09-22T06:24:17.147] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-09-22T18:59:25.281] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-22T18:59:25.288] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-22T18:59:25.290] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-22T18:59:25.292] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-09-22T18:59:25.294] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-09-22T18:59:25.296] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 6 relay1_07 false Profile: dusk - turnOn line according to lux sensor +[2025-09-22T18:59:25.298] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 7 relay1_08 false Profile: dusk - turnOn line according to lux sensor +[2025-09-23T03:05:56.016] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-23 03:05:56 +[2025-09-23T06:29:58.132] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-23T06:29:58.138] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-23T06:29:58.141] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-23T06:29:58.143] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-09-23T06:29:58.145] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-09-23T06:29:58.147] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 6 relay1_07 false Profile: dawn - turnOff line according to lux sensor +[2025-09-23T06:29:58.149] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 7 relay1_08 false Profile: dawn - turnOff line according to lux sensor +[2025-09-23T13:00:32.144] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-09-23T13:00:37.491] [INFO] monitorLogs - buildTasks - params undefined +[2025-09-23T13:00:37.496] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-09-23T13:00:37.497] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-09-23T13:00:37.497] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-23T13:00:37.502] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-23T13:00:37.503] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-09-24T05:09:00.502Z +[2025-09-23T13:00:37.504] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-09-23T17:19:00.504Z +[2025-09-23T13:00:37.505] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:9', name: 'luxOff' }, + { value: 1, start_time: '19:19', name: 'luxOn' } +] +[2025-09-23T13:00:37.506] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-09-23T13:00:37.507] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-09-23T13:00:37.508] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-23T13:00:37.510] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-23T13:00:37.511] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-09-24T05:09:00.511Z +[2025-09-23T13:00:37.512] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-09-23T17:19:00.511Z +[2025-09-23T13:00:37.512] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:9', name: 'luxOff' }, + { value: 1, start_time: '19:19', name: 'luxOn' } +] +[2025-09-23T13:00:37.513] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-09-23T13:00:37.514] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-09-23T13:00:37.515] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-23T13:00:37.517] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-23T13:00:37.517] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-09-24T05:09:00.517Z +[2025-09-23T13:00:37.518] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-09-23T17:19:00.518Z +[2025-09-23T13:00:37.519] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:9', name: 'luxOff' }, + { value: 1, start_time: '19:19', name: 'luxOn' } +] +[2025-09-23T13:00:37.521] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-09-23T13:00:37.522] [INFO] monitorLogs - buildTasks: profile for line 4 +[2025-09-23T13:00:37.522] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-23T13:00:37.524] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-23T13:00:37.525] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 4 2025-09-24T05:09:00.525Z +[2025-09-23T13:00:37.526] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 4 2025-09-23T17:19:00.526Z +[2025-09-23T13:00:37.526] [INFO] monitorLogs - -->time_points final 4 [ + { value: 0, start_time: '7:9', name: 'luxOff' }, + { value: 1, start_time: '19:19', name: 'luxOn' } +] +[2025-09-23T13:00:37.527] [INFO] monitorLogs - -->currentValue for relay 4 0 +[2025-09-23T13:00:37.528] [INFO] monitorLogs - buildTasks: profile for line 5 +[2025-09-23T13:00:37.529] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-23T13:00:37.531] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-23T13:00:37.531] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 5 2025-09-24T05:09:00.531Z +[2025-09-23T13:00:37.532] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 5 2025-09-23T17:19:00.532Z +[2025-09-23T13:00:37.533] [INFO] monitorLogs - -->time_points final 5 [ + { value: 0, start_time: '7:9', name: 'luxOff' }, + { value: 1, start_time: '19:19', name: 'luxOn' } +] +[2025-09-23T13:00:37.552] [INFO] monitorLogs - -->currentValue for relay 5 0 +[2025-09-23T13:00:37.553] [INFO] monitorLogs - buildTasks: profile for line 6 +[2025-09-23T13:00:37.553] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-23T13:00:37.555] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-23T13:00:37.556] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 6 2025-09-24T05:09:00.556Z +[2025-09-23T13:00:37.557] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 6 2025-09-23T17:19:00.556Z +[2025-09-23T13:00:37.557] [INFO] monitorLogs - -->time_points final 6 [ + { value: 0, start_time: '7:9', name: 'luxOff' }, + { value: 1, start_time: '19:19', name: 'luxOn' } +] +[2025-09-23T13:00:37.558] [INFO] monitorLogs - -->currentValue for relay 6 0 +[2025-09-23T13:00:37.559] [INFO] monitorLogs - buildTasks: profile for line 7 +[2025-09-23T13:00:37.559] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-23T13:00:37.562] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-23T13:00:37.562] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 7 2025-09-24T05:09:00.562Z +[2025-09-23T13:00:37.563] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 7 2025-09-23T17:19:00.563Z +[2025-09-23T13:00:37.564] [INFO] monitorLogs - -->time_points final 7 [ + { value: 0, start_time: '7:9', name: 'luxOff' }, + { value: 1, start_time: '19:19', name: 'luxOn' } +] +[2025-09-23T13:00:37.565] [INFO] monitorLogs - -->currentValue for relay 7 0 +[2025-09-23T13:00:37.572] [INFO] monitorLogs - tasks created: 1510 +[2025-09-23T13:00:37.575] [INFO] monitorLogs - -->FLOW bol spustený o9vbeQlLMVg8j5dq4keLWb0NxZpEmnXzwYKO1ar2 2025-08-08 +[2025-09-23T13:00:42.587] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-23T14:27:04.160] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-09-23T14:27:09.518] [INFO] monitorLogs - buildTasks - params undefined +[2025-09-23T14:27:09.523] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-09-23T14:27:09.524] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-09-23T14:27:09.525] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-23T14:27:09.529] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-23T14:27:09.531] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-09-24T05:09:00.530Z +[2025-09-23T14:27:09.532] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-09-23T17:19:00.532Z +[2025-09-23T14:27:09.533] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:9', name: 'luxOff' }, + { value: 1, start_time: '19:19', name: 'luxOn' } +] +[2025-09-23T14:27:09.534] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-09-23T14:27:09.535] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-09-23T14:27:09.535] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-23T14:27:09.538] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-23T14:27:09.539] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-09-24T05:09:00.538Z +[2025-09-23T14:27:09.540] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-09-23T17:19:00.539Z +[2025-09-23T14:27:09.540] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:9', name: 'luxOff' }, + { value: 1, start_time: '19:19', name: 'luxOn' } +] +[2025-09-23T14:27:09.541] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-09-23T14:27:09.542] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-09-23T14:27:09.542] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-23T14:27:09.545] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-23T14:27:09.545] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-09-24T05:09:00.545Z +[2025-09-23T14:27:09.546] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-09-23T17:19:00.546Z +[2025-09-23T14:27:09.547] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:9', name: 'luxOff' }, + { value: 1, start_time: '19:19', name: 'luxOn' } +] +[2025-09-23T14:27:09.549] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-09-23T14:27:09.549] [INFO] monitorLogs - buildTasks: profile for line 4 +[2025-09-23T14:27:09.550] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-23T14:27:09.552] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-23T14:27:09.553] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 4 2025-09-24T05:09:00.553Z +[2025-09-23T14:27:09.554] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 4 2025-09-23T17:19:00.553Z +[2025-09-23T14:27:09.554] [INFO] monitorLogs - -->time_points final 4 [ + { value: 0, start_time: '7:9', name: 'luxOff' }, + { value: 1, start_time: '19:19', name: 'luxOn' } +] +[2025-09-23T14:27:09.555] [INFO] monitorLogs - -->currentValue for relay 4 0 +[2025-09-23T14:27:09.556] [INFO] monitorLogs - buildTasks: profile for line 5 +[2025-09-23T14:27:09.557] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-23T14:27:09.559] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-23T14:27:09.559] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 5 2025-09-24T05:09:00.559Z +[2025-09-23T14:27:09.560] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 5 2025-09-23T17:19:00.560Z +[2025-09-23T14:27:09.561] [INFO] monitorLogs - -->time_points final 5 [ + { value: 0, start_time: '7:9', name: 'luxOff' }, + { value: 1, start_time: '19:19', name: 'luxOn' } +] +[2025-09-23T14:27:09.562] [INFO] monitorLogs - -->currentValue for relay 5 0 +[2025-09-23T14:27:09.562] [INFO] monitorLogs - buildTasks: profile for line 6 +[2025-09-23T14:27:09.563] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-23T14:27:09.565] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-23T14:27:09.566] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 6 2025-09-24T05:09:00.566Z +[2025-09-23T14:27:09.566] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 6 2025-09-23T17:19:00.566Z +[2025-09-23T14:27:09.567] [INFO] monitorLogs - -->time_points final 6 [ + { value: 0, start_time: '7:9', name: 'luxOff' }, + { value: 1, start_time: '19:19', name: 'luxOn' } +] +[2025-09-23T14:27:09.568] [INFO] monitorLogs - -->currentValue for relay 6 0 +[2025-09-23T14:27:09.569] [INFO] monitorLogs - buildTasks: profile for line 7 +[2025-09-23T14:27:09.569] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-23T14:27:09.589] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-23T14:27:09.589] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 7 2025-09-24T05:09:00.589Z +[2025-09-23T14:27:09.590] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 7 2025-09-23T17:19:00.590Z +[2025-09-23T14:27:09.591] [INFO] monitorLogs - -->time_points final 7 [ + { value: 0, start_time: '7:9', name: 'luxOff' }, + { value: 1, start_time: '19:19', name: 'luxOn' } +] +[2025-09-23T14:27:09.592] [INFO] monitorLogs - -->currentValue for relay 7 0 +[2025-09-23T14:27:09.600] [INFO] monitorLogs - tasks created: 1510 +[2025-09-23T14:27:09.603] [INFO] monitorLogs - -->FLOW bol spustený o9vbeQlLMVg8j5dq4keLWb0NxZpEmnXzwYKO1ar2 2025-08-08 +[2025-09-23T14:27:14.613] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-23T18:50:54.981] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-23T18:50:54.989] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-23T18:50:54.992] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-23T18:50:54.994] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-09-23T18:50:54.997] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-09-23T18:50:54.999] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 6 relay1_07 false Profile: dusk - turnOn line according to lux sensor +[2025-09-23T18:50:55.001] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 7 relay1_08 false Profile: dusk - turnOn line according to lux sensor +[2025-09-24T03:27:11.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-24 03:27:11 +[2025-09-24T06:43:34.356] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-24T06:43:34.363] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-24T06:43:34.365] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-24T06:43:34.367] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-09-24T06:43:34.370] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-09-24T06:43:34.372] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 6 relay1_07 false Profile: dawn - turnOff line according to lux sensor +[2025-09-24T06:43:34.374] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 7 relay1_08 false Profile: dawn - turnOff line according to lux sensor +[2025-09-24T18:48:33.088] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-24T18:48:33.096] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-24T18:48:33.098] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-24T18:48:33.100] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-09-24T18:48:33.102] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-09-24T18:48:33.104] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 6 relay1_07 false Profile: dusk - turnOn line according to lux sensor +[2025-09-24T18:48:33.106] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 7 relay1_08 false Profile: dusk - turnOn line according to lux sensor +[2025-09-25T03:27:12.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-25 03:27:12 +[2025-09-25T06:49:02.082] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-25T06:49:02.088] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-25T06:49:02.090] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-25T06:49:02.092] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-09-25T06:49:02.094] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-09-25T06:49:02.096] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 6 relay1_07 false Profile: dawn - turnOff line according to lux sensor +[2025-09-25T06:49:02.098] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 7 relay1_08 false Profile: dawn - turnOff line according to lux sensor +[2025-09-25T16:25:25.747] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-09-25T16:25:31.093] [INFO] monitorLogs - buildTasks - params undefined +[2025-09-25T16:25:31.099] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-09-25T16:25:31.100] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-09-25T16:25:31.100] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-25T16:25:31.105] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-25T16:25:31.106] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-09-26T05:12:00.105Z +[2025-09-25T16:25:31.107] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-09-25T17:14:00.107Z +[2025-09-25T16:25:31.108] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:12', name: 'luxOff' }, + { value: 1, start_time: '19:14', name: 'luxOn' } +] +[2025-09-25T16:25:31.109] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-09-25T16:25:31.110] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-09-25T16:25:31.111] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-25T16:25:31.113] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-25T16:25:31.114] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-09-26T05:12:00.114Z +[2025-09-25T16:25:31.115] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-09-25T17:14:00.115Z +[2025-09-25T16:25:31.115] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:12', name: 'luxOff' }, + { value: 1, start_time: '19:14', name: 'luxOn' } +] +[2025-09-25T16:25:31.116] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-09-25T16:25:31.117] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-09-25T16:25:31.118] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-25T16:25:31.120] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-25T16:25:31.121] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-09-26T05:12:00.121Z +[2025-09-25T16:25:31.121] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-09-25T17:14:00.121Z +[2025-09-25T16:25:31.122] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:12', name: 'luxOff' }, + { value: 1, start_time: '19:14', name: 'luxOn' } +] +[2025-09-25T16:25:31.123] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-09-25T16:25:31.124] [INFO] monitorLogs - buildTasks: profile for line 4 +[2025-09-25T16:25:31.124] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-25T16:25:31.127] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-25T16:25:31.127] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 4 2025-09-26T05:12:00.127Z +[2025-09-25T16:25:31.128] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 4 2025-09-25T17:14:00.128Z +[2025-09-25T16:25:31.129] [INFO] monitorLogs - -->time_points final 4 [ + { value: 0, start_time: '7:12', name: 'luxOff' }, + { value: 1, start_time: '19:14', name: 'luxOn' } +] +[2025-09-25T16:25:31.130] [INFO] monitorLogs - -->currentValue for relay 4 0 +[2025-09-25T16:25:31.131] [INFO] monitorLogs - buildTasks: profile for line 5 +[2025-09-25T16:25:31.131] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-25T16:25:31.133] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-25T16:25:31.134] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 5 2025-09-26T05:12:00.134Z +[2025-09-25T16:25:31.135] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 5 2025-09-25T17:14:00.134Z +[2025-09-25T16:25:31.135] [INFO] monitorLogs - -->time_points final 5 [ + { value: 0, start_time: '7:12', name: 'luxOff' }, + { value: 1, start_time: '19:14', name: 'luxOn' } +] +[2025-09-25T16:25:31.136] [INFO] monitorLogs - -->currentValue for relay 5 0 +[2025-09-25T16:25:31.137] [INFO] monitorLogs - buildTasks: profile for line 6 +[2025-09-25T16:25:31.138] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-25T16:25:31.140] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-25T16:25:31.157] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 6 2025-09-26T05:12:00.157Z +[2025-09-25T16:25:31.158] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 6 2025-09-25T17:14:00.158Z +[2025-09-25T16:25:31.158] [INFO] monitorLogs - -->time_points final 6 [ + { value: 0, start_time: '7:12', name: 'luxOff' }, + { value: 1, start_time: '19:14', name: 'luxOn' } +] +[2025-09-25T16:25:31.159] [INFO] monitorLogs - -->currentValue for relay 6 0 +[2025-09-25T16:25:31.160] [INFO] monitorLogs - buildTasks: profile for line 7 +[2025-09-25T16:25:31.161] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-25T16:25:31.163] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-25T16:25:31.164] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 7 2025-09-26T05:12:00.163Z +[2025-09-25T16:25:31.164] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 7 2025-09-25T17:14:00.164Z +[2025-09-25T16:25:31.165] [INFO] monitorLogs - -->time_points final 7 [ + { value: 0, start_time: '7:12', name: 'luxOff' }, + { value: 1, start_time: '19:14', name: 'luxOn' } +] +[2025-09-25T16:25:31.166] [INFO] monitorLogs - -->currentValue for relay 7 0 +[2025-09-25T16:25:31.174] [INFO] monitorLogs - tasks created: 1510 +[2025-09-25T16:25:31.176] [INFO] monitorLogs - -->FLOW bol spustený o9vbeQlLMVg8j5dq4keLWb0NxZpEmnXzwYKO1ar2 2025-08-08 +[2025-09-25T16:25:36.190] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-25T18:34:34.689] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-25T18:34:34.692] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-25T18:34:34.695] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-25T18:34:34.698] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-09-25T18:34:34.700] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-09-25T18:34:34.702] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 6 relay1_07 false Profile: dusk - turnOn line according to lux sensor +[2025-09-25T18:34:34.704] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 7 relay1_08 false Profile: dusk - turnOn line according to lux sensor +[2025-09-26T03:25:33.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-26 03:25:33 +[2025-09-26T06:42:20.596] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-26T06:42:20.603] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-26T06:42:20.605] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-26T06:42:20.607] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-09-26T06:42:20.609] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-09-26T06:42:20.611] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 6 relay1_07 false Profile: dawn - turnOff line according to lux sensor +[2025-09-26T06:42:20.613] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 7 relay1_08 false Profile: dawn - turnOff line according to lux sensor +[2025-09-26T18:52:07.765] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-26T18:52:07.772] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-26T18:52:07.774] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-26T18:52:07.776] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-09-26T18:52:07.778] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-09-26T18:52:07.780] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 6 relay1_07 false Profile: dusk - turnOn line according to lux sensor +[2025-09-26T18:52:07.782] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 7 relay1_08 false Profile: dusk - turnOn line according to lux sensor +[2025-09-27T03:25:35.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-27 03:25:35 +[2025-09-27T06:39:36.013] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-27T06:39:36.019] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-27T06:39:36.021] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-27T06:39:36.023] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-09-27T06:39:36.025] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-09-27T06:39:36.027] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 6 relay1_07 false Profile: dawn - turnOff line according to lux sensor +[2025-09-27T06:39:36.029] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 7 relay1_08 false Profile: dawn - turnOff line according to lux sensor +[2025-09-27T18:52:10.180] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-27T18:52:10.186] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-27T18:52:10.188] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-27T18:52:10.190] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-09-27T18:52:10.192] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-09-27T18:52:10.194] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 6 relay1_07 false Profile: dusk - turnOn line according to lux sensor +[2025-09-27T18:52:10.196] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 7 relay1_08 false Profile: dusk - turnOn line according to lux sensor +[2025-09-28T03:25:36.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-28 03:25:36 +[2025-09-28T06:37:45.147] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-28T06:37:45.153] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-28T06:37:45.155] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-28T06:37:45.157] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-09-28T06:37:45.159] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-09-28T06:37:45.161] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 6 relay1_07 false Profile: dawn - turnOff line according to lux sensor +[2025-09-28T06:37:45.163] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 7 relay1_08 false Profile: dawn - turnOff line according to lux sensor +[2025-09-28T18:50:44.658] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-28T18:50:44.664] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-28T18:50:44.668] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-28T18:50:44.669] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-09-28T18:50:44.671] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-09-28T18:50:44.673] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 6 relay1_07 false Profile: dusk - turnOn line according to lux sensor +[2025-09-28T18:50:44.675] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 7 relay1_08 false Profile: dusk - turnOn line according to lux sensor +[2025-09-29T03:25:38.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-29 03:25:38 +[2025-09-29T06:33:43.539] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-29T06:33:43.545] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-29T06:33:43.547] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-29T06:33:43.549] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-09-29T06:33:43.552] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-09-29T06:33:43.554] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 6 relay1_07 false Profile: dawn - turnOff line according to lux sensor +[2025-09-29T06:33:43.556] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 7 relay1_08 false Profile: dawn - turnOff line according to lux sensor +[2025-09-29T18:47:20.936] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-29T18:47:20.942] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-29T18:47:20.944] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-29T18:47:20.946] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-09-29T18:47:20.948] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-09-29T18:47:20.950] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 6 relay1_07 false Profile: dusk - turnOn line according to lux sensor +[2025-09-29T18:47:20.952] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 7 relay1_08 false Profile: dusk - turnOn line according to lux sensor +[2025-09-30T03:25:39.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-30 03:25:39 +[2025-09-30T06:34:53.386] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-30T06:34:53.393] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-30T06:34:53.395] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-30T06:34:53.397] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-09-30T06:34:53.399] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-09-30T06:34:53.401] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 6 relay1_07 false Profile: dawn - turnOff line according to lux sensor +[2025-09-30T06:34:53.403] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 7 relay1_08 false Profile: dawn - turnOff line according to lux sensor +[2025-09-30T18:45:28.556] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-30T18:45:28.562] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-30T18:45:28.564] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-30T18:45:28.566] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-09-30T18:45:28.568] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-09-30T18:45:28.570] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 6 relay1_07 false Profile: dusk - turnOn line according to lux sensor +[2025-09-30T18:45:28.571] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 7 relay1_08 false Profile: dusk - turnOn line according to lux sensor +[2025-10-01T03:25:41.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-01 03:25:41 +[2025-10-01T06:43:01.940] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-01T06:43:01.947] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-01T06:43:01.949] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-01T06:43:01.951] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-10-01T06:43:01.953] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-10-01T06:43:01.955] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 6 relay1_07 false Profile: dawn - turnOff line according to lux sensor +[2025-10-01T06:43:01.956] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 7 relay1_08 false Profile: dawn - turnOff line according to lux sensor +[2025-10-01T18:44:56.024] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-01T18:44:56.030] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-01T18:44:56.032] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-01T18:44:56.034] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-10-01T18:44:56.036] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-10-01T18:44:56.037] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 6 relay1_07 false Profile: dusk - turnOn line according to lux sensor +[2025-10-01T18:44:56.039] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 7 relay1_08 false Profile: dusk - turnOn line according to lux sensor +[2025-10-02T03:25:43.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-02 03:25:43 +[2025-10-02T06:38:15.621] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-02T06:38:15.627] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-02T06:38:15.629] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-02T06:38:15.631] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-10-02T06:38:15.633] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-10-02T06:38:15.635] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 6 relay1_07 false Profile: dawn - turnOff line according to lux sensor +[2025-10-02T06:38:15.637] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 7 relay1_08 false Profile: dawn - turnOff line according to lux sensor +[2025-10-02T08:18:55.623] [INFO] monitorLogs - turnLine on - (line, SETTINGS.maintenance_mode) 0 true command received from platform +[2025-10-02T08:19:02.656] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false command received from platform +[2025-10-02T08:19:07.144] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false command received from platform +[2025-10-02T08:19:13.216] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false command received from platform +[2025-10-02T08:19:17.056] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false command received from platform +[2025-10-02T08:19:23.456] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false command received from platform +[2025-10-02T08:19:31.135] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 6 relay1_07 false command received from platform +[2025-10-02T08:19:35.935] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 7 relay1_08 false command received from platform +[2025-10-02T08:40:18.792] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 7 relay1_08 false command received from platform +[2025-10-02T08:40:24.553] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 6 relay1_07 false command received from platform +[2025-10-02T08:40:28.391] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false command received from platform +[2025-10-02T08:40:32.230] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false command received from platform +[2025-10-02T08:40:39.591] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false command received from platform +[2025-10-02T08:40:51.750] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false command received from platform +[2025-10-02T08:40:57.191] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false command received from platform +[2025-10-02T08:41:20.552] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false command received from platform +[2025-10-02T18:42:47.914] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-02T18:42:47.920] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-02T18:42:47.922] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-02T18:42:47.924] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-10-02T18:42:47.926] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-10-02T18:42:47.928] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 6 relay1_07 false Profile: dusk - turnOn line according to lux sensor +[2025-10-02T18:42:47.930] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 7 relay1_08 false Profile: dusk - turnOn line according to lux sensor +[2025-10-03T03:25:44.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-03 03:25:44 +[2025-10-03T06:40:18.272] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-03T06:40:18.277] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-03T06:40:18.279] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-03T06:40:18.281] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-10-03T06:40:18.283] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-10-03T06:40:18.285] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 6 relay1_07 false Profile: dawn - turnOff line according to lux sensor +[2025-10-03T06:40:18.287] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 7 relay1_08 false Profile: dawn - turnOff line according to lux sensor +[2025-10-03T14:01:02.446] [INFO] monitorLogs - turnLine on - (line, SETTINGS.maintenance_mode) 0 true command received from platform +[2025-10-03T14:01:07.555] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false command received from platform +[2025-10-03T14:01:15.555] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false command received from platform +[2025-10-03T14:01:23.875] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false command received from platform +[2025-10-03T14:01:36.675] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false command received from platform +[2025-10-03T14:01:54.596] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false command received from platform +[2025-10-03T14:41:09.618] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-03T14:41:14.974] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-03T14:41:14.978] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-03T14:41:14.980] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-03T14:41:14.980] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-03T14:41:14.985] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-03T14:41:14.986] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-10-04T05:24:00.985Z +[2025-10-03T14:41:14.987] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-10-03T16:58:00.987Z +[2025-10-03T14:41:14.988] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:24', name: 'luxOff' }, + { value: 1, start_time: '18:58', name: 'luxOn' } +] +[2025-10-03T14:41:14.989] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-10-03T14:41:14.990] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-03T14:41:14.991] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-03T14:41:14.993] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-03T14:41:14.994] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-10-04T05:24:00.994Z +[2025-10-03T14:41:14.995] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-10-03T16:58:00.995Z +[2025-10-03T14:41:14.996] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:24', name: 'luxOff' }, + { value: 1, start_time: '18:58', name: 'luxOn' } +] +[2025-10-03T14:41:14.997] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-10-03T14:41:14.997] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-03T14:41:14.998] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-03T14:41:15.000] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-03T14:41:15.001] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-10-04T05:24:00.001Z +[2025-10-03T14:41:15.001] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-10-03T16:58:00.001Z +[2025-10-03T14:41:15.002] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:24', name: 'luxOff' }, + { value: 1, start_time: '18:58', name: 'luxOn' } +] +[2025-10-03T14:41:15.003] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-10-03T14:41:15.004] [INFO] monitorLogs - buildTasks: profile for line 4 +[2025-10-03T14:41:15.005] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-03T14:41:15.007] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-03T14:41:15.007] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 4 2025-10-04T05:24:00.007Z +[2025-10-03T14:41:15.008] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 4 2025-10-03T16:58:00.008Z +[2025-10-03T14:41:15.009] [INFO] monitorLogs - -->time_points final 4 [ + { value: 0, start_time: '7:24', name: 'luxOff' }, + { value: 1, start_time: '18:58', name: 'luxOn' } +] +[2025-10-03T14:41:15.010] [INFO] monitorLogs - -->currentValue for relay 4 0 +[2025-10-03T14:41:15.011] [INFO] monitorLogs - buildTasks: profile for line 5 +[2025-10-03T14:41:15.011] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-03T14:41:15.013] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-03T14:41:15.014] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 5 2025-10-04T05:24:00.014Z +[2025-10-03T14:41:15.015] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 5 2025-10-03T16:58:00.014Z +[2025-10-03T14:41:15.015] [INFO] monitorLogs - -->time_points final 5 [ + { value: 0, start_time: '7:24', name: 'luxOff' }, + { value: 1, start_time: '18:58', name: 'luxOn' } +] +[2025-10-03T14:41:15.016] [INFO] monitorLogs - -->currentValue for relay 5 0 +[2025-10-03T14:41:15.017] [INFO] monitorLogs - buildTasks: profile for line 6 +[2025-10-03T14:41:15.018] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-03T14:41:15.020] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-03T14:41:15.020] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 6 2025-10-04T05:24:00.020Z +[2025-10-03T14:41:15.022] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 6 2025-10-03T16:58:00.021Z +[2025-10-03T14:41:15.023] [INFO] monitorLogs - -->time_points final 6 [ + { value: 0, start_time: '7:24', name: 'luxOff' }, + { value: 1, start_time: '18:58', name: 'luxOn' } +] +[2025-10-03T14:41:15.041] [INFO] monitorLogs - -->currentValue for relay 6 0 +[2025-10-03T14:41:15.041] [INFO] monitorLogs - buildTasks: profile for line 7 +[2025-10-03T14:41:15.042] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-03T14:41:15.044] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-03T14:41:15.045] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 7 2025-10-04T05:24:00.044Z +[2025-10-03T14:41:15.045] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 7 2025-10-03T16:58:00.045Z +[2025-10-03T14:41:15.046] [INFO] monitorLogs - -->time_points final 7 [ + { value: 0, start_time: '7:24', name: 'luxOff' }, + { value: 1, start_time: '18:58', name: 'luxOn' } +] +[2025-10-03T14:41:15.047] [INFO] monitorLogs - -->currentValue for relay 7 0 +[2025-10-03T14:41:15.055] [INFO] monitorLogs - tasks created: 1510 +[2025-10-03T14:41:15.057] [INFO] monitorLogs - -->FLOW bol spustený o9vbeQlLMVg8j5dq4keLWb0NxZpEmnXzwYKO1ar2 2025-08-08 +[2025-10-03T14:41:20.071] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-03T18:39:14.102] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-03T18:39:14.108] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-03T18:39:14.112] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-03T18:39:14.114] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-10-03T18:39:14.117] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-10-03T18:39:14.119] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 6 relay1_07 false Profile: dusk - turnOn line according to lux sensor +[2025-10-03T18:39:14.121] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 7 relay1_08 false Profile: dusk - turnOn line according to lux sensor +[2025-10-04T03:41:17.020] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-04 03:41:17 +[2025-10-04T06:40:09.142] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-04T06:40:09.149] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-04T06:40:09.151] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-04T06:40:09.153] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-10-04T06:40:09.155] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-10-04T06:40:09.157] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 6 relay1_07 false Profile: dawn - turnOff line according to lux sensor +[2025-10-04T06:40:09.159] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 7 relay1_08 false Profile: dawn - turnOff line according to lux sensor +[2025-10-04T18:28:44.086] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-04T18:28:44.092] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-04T18:28:44.094] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-04T18:28:44.096] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-10-04T18:28:44.098] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-10-04T18:28:44.100] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 6 relay1_07 false Profile: dusk - turnOn line according to lux sensor +[2025-10-04T18:28:44.102] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 7 relay1_08 false Profile: dusk - turnOn line according to lux sensor +[2025-10-05T03:41:19.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-05 03:41:19 +[2025-10-05T06:43:23.887] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-05T06:43:23.894] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-05T06:43:23.896] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-05T06:43:23.898] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-10-05T06:43:23.900] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-10-05T06:43:23.902] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 6 relay1_07 false Profile: dawn - turnOff line according to lux sensor +[2025-10-05T06:43:23.904] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 7 relay1_08 false Profile: dawn - turnOff line according to lux sensor +[2025-10-05T18:33:41.277] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-05T18:33:41.281] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-05T18:33:41.283] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-05T18:33:41.285] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-10-05T18:33:41.287] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-10-05T18:33:41.289] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 6 relay1_07 false Profile: dusk - turnOn line according to lux sensor +[2025-10-05T18:33:41.291] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 7 relay1_08 false Profile: dusk - turnOn line according to lux sensor +[2025-10-06T03:41:20.014] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-06 03:41:20 +[2025-10-06T06:52:46.684] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-06T06:52:46.687] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-06T06:52:46.689] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-06T06:52:46.691] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-10-06T06:52:46.693] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-10-06T06:52:46.695] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 6 relay1_07 false Profile: dawn - turnOff line according to lux sensor +[2025-10-06T06:52:46.697] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 7 relay1_08 false Profile: dawn - turnOff line according to lux sensor +[2025-10-06T18:24:32.719] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-06T18:24:32.725] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-06T18:24:32.727] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-06T18:24:32.729] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-10-06T18:24:32.731] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-10-06T18:24:32.733] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 6 relay1_07 false Profile: dusk - turnOn line according to lux sensor +[2025-10-06T18:24:32.734] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 7 relay1_08 false Profile: dusk - turnOn line according to lux sensor +[2025-10-07T03:41:22.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-07 03:41:22 +[2025-10-07T06:48:39.599] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-07T06:48:39.605] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-07T06:48:39.607] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-07T06:48:39.609] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-10-07T06:48:39.611] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-10-07T06:48:39.613] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 6 relay1_07 false Profile: dawn - turnOff line according to lux sensor +[2025-10-07T06:48:39.614] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 7 relay1_08 false Profile: dawn - turnOff line according to lux sensor +[2025-10-07T18:29:26.246] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-07T18:29:26.251] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-07T18:29:26.254] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-07T18:29:26.256] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-10-07T18:29:26.258] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-10-07T18:29:26.260] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 6 relay1_07 false Profile: dusk - turnOn line according to lux sensor +[2025-10-07T18:29:26.261] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 7 relay1_08 false Profile: dusk - turnOn line according to lux sensor +[2025-10-08T03:41:23.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-08 03:41:23 +[2025-10-08T06:45:49.287] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-08T06:45:49.294] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-08T06:45:49.296] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-08T06:45:49.298] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-10-08T06:45:49.300] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-10-08T06:45:49.302] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 6 relay1_07 false Profile: dawn - turnOff line according to lux sensor +[2025-10-08T06:45:49.303] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 7 relay1_08 false Profile: dawn - turnOff line according to lux sensor +[2025-10-08T18:28:14.754] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-08T18:28:14.760] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-08T18:28:14.762] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-08T18:28:14.764] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-10-08T18:28:14.767] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-10-08T18:28:14.768] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 6 relay1_07 false Profile: dusk - turnOn line according to lux sensor +[2025-10-08T18:28:14.770] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 7 relay1_08 false Profile: dusk - turnOn line according to lux sensor +[2025-10-09T03:41:25.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-09 03:41:25 +[2025-10-09T07:02:52.601] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-09T07:02:52.607] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-09T07:02:52.609] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-09T07:02:52.610] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-10-09T07:02:52.612] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-10-09T07:02:52.614] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 6 relay1_07 false Profile: dawn - turnOff line according to lux sensor +[2025-10-09T07:02:52.616] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 7 relay1_08 false Profile: dawn - turnOff line according to lux sensor +[2025-10-09T16:46:44.917] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-09T16:46:50.269] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-09T16:46:50.274] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-09T16:46:50.275] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-09T16:46:50.276] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-09T16:46:50.280] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T16:46:50.281] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-10-10T05:32:00.281Z +[2025-10-09T16:46:50.283] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-10-09T16:45:00.283Z +[2025-10-09T16:46:50.284] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T16:46:50.285] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-10-09T16:46:50.286] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-09T16:46:50.286] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-09T16:46:50.289] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T16:46:50.289] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-10-10T05:32:00.289Z +[2025-10-09T16:46:50.290] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-10-09T16:45:00.290Z +[2025-10-09T16:46:50.291] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T16:46:50.292] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-10-09T16:46:50.293] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-09T16:46:50.293] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-09T16:46:50.295] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T16:46:50.296] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-10-10T05:32:00.296Z +[2025-10-09T16:46:50.297] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-10-09T16:45:00.297Z +[2025-10-09T16:46:50.297] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T16:46:50.298] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-10-09T16:46:50.299] [INFO] monitorLogs - buildTasks: profile for line 4 +[2025-10-09T16:46:50.300] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-09T16:46:50.302] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T16:46:50.303] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 4 2025-10-10T05:32:00.302Z +[2025-10-09T16:46:50.303] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 4 2025-10-09T16:45:00.303Z +[2025-10-09T16:46:50.304] [INFO] monitorLogs - -->time_points final 4 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T16:46:50.305] [INFO] monitorLogs - -->currentValue for relay 4 0 +[2025-10-09T16:46:50.306] [INFO] monitorLogs - buildTasks: profile for line 5 +[2025-10-09T16:46:50.306] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-09T16:46:50.309] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T16:46:50.309] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 5 2025-10-10T05:32:00.309Z +[2025-10-09T16:46:50.310] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 5 2025-10-09T16:45:00.310Z +[2025-10-09T16:46:50.311] [INFO] monitorLogs - -->time_points final 5 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T16:46:50.312] [INFO] monitorLogs - -->currentValue for relay 5 0 +[2025-10-09T16:46:50.330] [INFO] monitorLogs - buildTasks: profile for line 6 +[2025-10-09T16:46:50.330] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-09T16:46:50.332] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T16:46:50.333] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 6 2025-10-10T05:32:00.333Z +[2025-10-09T16:46:50.334] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 6 2025-10-09T16:45:00.334Z +[2025-10-09T16:46:50.334] [INFO] monitorLogs - -->time_points final 6 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T16:46:50.335] [INFO] monitorLogs - -->currentValue for relay 6 0 +[2025-10-09T16:46:50.336] [INFO] monitorLogs - buildTasks: profile for line 7 +[2025-10-09T16:46:50.337] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-09T16:46:50.339] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T16:46:50.340] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 7 2025-10-10T05:32:00.340Z +[2025-10-09T16:46:50.340] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 7 2025-10-09T16:45:00.340Z +[2025-10-09T16:46:50.341] [INFO] monitorLogs - -->time_points final 7 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T16:46:50.342] [INFO] monitorLogs - -->currentValue for relay 7 0 +[2025-10-09T16:46:50.350] [INFO] monitorLogs - tasks created: 1510 +[2025-10-09T16:46:50.352] [INFO] monitorLogs - -->FLOW bol spustený o9vbeQlLMVg8j5dq4keLWb0NxZpEmnXzwYKO1ar2 2025-08-08 +[2025-10-09T16:46:55.366] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-09T18:24:24.656] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-09T18:24:24.659] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-09T18:24:24.661] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-09T18:24:24.663] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-10-09T18:24:24.666] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-10-09T18:24:24.668] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 6 relay1_07 false Profile: dusk - turnOn line according to lux sensor +[2025-10-09T18:24:24.670] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 7 relay1_08 false Profile: dusk - turnOn line according to lux sensor +[2025-10-09T18:58:50.308] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-09T18:58:55.658] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-09T18:58:55.662] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-09T18:58:55.664] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-09T18:58:55.664] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-09T18:58:55.669] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T18:58:55.670] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-10-10T05:32:00.669Z +[2025-10-09T18:58:55.671] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-10-10T16:45:00.671Z +[2025-10-09T18:58:55.672] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T18:58:55.673] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-10-09T18:58:55.674] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-09T18:58:55.675] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-09T18:58:55.677] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T18:58:55.678] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-10-10T05:32:00.678Z +[2025-10-09T18:58:55.679] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-10-10T16:45:00.679Z +[2025-10-09T18:58:55.679] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T18:58:55.680] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-10-09T18:58:55.681] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-09T18:58:55.682] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-09T18:58:55.684] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T18:58:55.685] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-10-10T05:32:00.685Z +[2025-10-09T18:58:55.685] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-10-10T16:45:00.685Z +[2025-10-09T18:58:55.686] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T18:58:55.687] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-10-09T18:58:55.688] [INFO] monitorLogs - buildTasks: profile for line 4 +[2025-10-09T18:58:55.688] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-09T18:58:55.691] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T18:58:55.691] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 4 2025-10-10T05:32:00.691Z +[2025-10-09T18:58:55.692] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 4 2025-10-10T16:45:00.692Z +[2025-10-09T18:58:55.693] [INFO] monitorLogs - -->time_points final 4 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T18:58:55.694] [INFO] monitorLogs - -->currentValue for relay 4 1 +[2025-10-09T18:58:55.695] [INFO] monitorLogs - buildTasks: profile for line 5 +[2025-10-09T18:58:55.695] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-09T18:58:55.697] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T18:58:55.698] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 5 2025-10-10T05:32:00.698Z +[2025-10-09T18:58:55.699] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 5 2025-10-10T16:45:00.698Z +[2025-10-09T18:58:55.699] [INFO] monitorLogs - -->time_points final 5 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T18:58:55.700] [INFO] monitorLogs - -->currentValue for relay 5 1 +[2025-10-09T18:58:55.701] [INFO] monitorLogs - buildTasks: profile for line 6 +[2025-10-09T18:58:55.718] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-09T18:58:55.721] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T18:58:55.722] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 6 2025-10-10T05:32:00.722Z +[2025-10-09T18:58:55.723] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 6 2025-10-10T16:45:00.722Z +[2025-10-09T18:58:55.723] [INFO] monitorLogs - -->time_points final 6 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T18:58:55.724] [INFO] monitorLogs - -->currentValue for relay 6 1 +[2025-10-09T18:58:55.725] [INFO] monitorLogs - buildTasks: profile for line 7 +[2025-10-09T18:58:55.725] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-09T18:58:55.728] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T18:58:55.729] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 7 2025-10-10T05:32:00.729Z +[2025-10-09T18:58:55.730] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 7 2025-10-10T16:45:00.730Z +[2025-10-09T18:58:55.730] [INFO] monitorLogs - -->time_points final 7 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T18:58:55.731] [INFO] monitorLogs - -->currentValue for relay 7 1 +[2025-10-09T18:58:55.740] [INFO] monitorLogs - tasks created: 1510 +[2025-10-09T18:58:55.743] [INFO] monitorLogs - -->FLOW bol spustený o9vbeQlLMVg8j5dq4keLWb0NxZpEmnXzwYKO1ar2 2025-08-08 +[2025-10-09T18:59:00.756] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-10T03:58:57.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-10 03:58:57 +[2025-10-10T06:58:26.192] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-10T06:58:26.198] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-10T06:58:26.200] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-10T06:58:26.202] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-10-10T06:58:26.204] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-10-10T06:58:26.205] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 6 relay1_07 false Profile: dawn - turnOff line according to lux sensor +[2025-10-10T06:58:26.207] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 7 relay1_08 false Profile: dawn - turnOff line according to lux sensor +[2025-10-10T18:17:33.716] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-10T18:17:33.718] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-10T18:17:33.720] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-10T18:17:33.722] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-10-10T18:17:33.724] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-10-10T18:17:33.726] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 6 relay1_07 false Profile: dusk - turnOn line according to lux sensor +[2025-10-10T18:17:33.728] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 7 relay1_08 false Profile: dusk - turnOn line according to lux sensor +[2025-10-11T03:58:59.020] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-11 03:58:59 +[2025-10-11T06:59:21.974] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-11T06:59:21.978] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-11T06:59:21.980] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-11T06:59:21.982] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-10-11T06:59:21.984] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-10-11T06:59:21.986] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 6 relay1_07 false Profile: dawn - turnOff line according to lux sensor +[2025-10-11T06:59:21.988] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 7 relay1_08 false Profile: dawn - turnOff line according to lux sensor +[2025-10-11T18:23:27.605] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-11T18:23:27.608] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-11T18:23:27.610] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-11T18:23:27.612] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-10-11T18:23:27.613] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-10-11T18:23:27.615] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 6 relay1_07 false Profile: dusk - turnOn line according to lux sensor +[2025-10-11T18:23:27.617] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 7 relay1_08 false Profile: dusk - turnOn line according to lux sensor +[2025-10-12T03:59:00.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-12 03:59:00 +[2025-10-12T06:58:31.531] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-12T06:58:31.535] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-12T06:58:31.537] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-12T06:58:31.539] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-10-12T06:58:31.541] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-10-12T06:58:31.543] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 6 relay1_07 false Profile: dawn - turnOff line according to lux sensor +[2025-10-12T06:58:31.545] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 7 relay1_08 false Profile: dawn - turnOff line according to lux sensor +[2025-10-12T18:17:35.241] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-12T18:17:35.243] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-12T18:17:35.245] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-12T18:17:35.247] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-10-12T18:17:35.248] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-10-12T18:17:35.250] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 6 relay1_07 false Profile: dusk - turnOn line according to lux sensor +[2025-10-12T18:17:35.252] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 7 relay1_08 false Profile: dusk - turnOn line according to lux sensor +[2025-10-13T03:59:02.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-13 03:59:02 +[2025-10-13T06:55:32.311] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-13T06:55:32.315] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-13T06:55:32.317] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-13T06:55:32.318] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-10-13T06:55:32.320] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-10-13T06:55:32.322] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 6 relay1_07 false Profile: dawn - turnOff line according to lux sensor +[2025-10-13T06:55:32.324] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 7 relay1_08 false Profile: dawn - turnOff line according to lux sensor +[2025-10-13T18:21:24.760] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-13T18:21:24.763] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-13T18:21:24.765] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-13T18:21:24.767] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-10-13T18:21:24.769] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-10-13T18:21:24.770] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 6 relay1_07 false Profile: dusk - turnOn line according to lux sensor +[2025-10-13T18:21:24.772] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 7 relay1_08 false Profile: dusk - turnOn line according to lux sensor +[2025-10-14T03:59:03.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-14 03:59:03 +[2025-10-14T06:57:17.236] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-14T06:57:17.240] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-14T06:57:17.242] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-14T06:57:17.244] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-10-14T06:57:17.246] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-10-14T06:57:17.248] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 6 relay1_07 false Profile: dawn - turnOff line according to lux sensor +[2025-10-14T06:57:17.250] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 7 relay1_08 false Profile: dawn - turnOff line according to lux sensor +[2025-10-14T18:12:51.824] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-14T18:12:51.826] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-14T18:12:51.828] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-14T18:12:51.830] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-10-14T18:12:51.832] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-10-14T18:12:51.833] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 6 relay1_07 false Profile: dusk - turnOn line according to lux sensor +[2025-10-14T18:12:51.835] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 7 relay1_08 false Profile: dusk - turnOn line according to lux sensor +[2025-10-15T03:59:05.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-15 03:59:05 +[2025-10-15T07:04:29.691] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-15T07:04:29.695] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-15T07:04:29.697] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-15T07:04:29.699] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-10-15T07:04:29.700] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-10-15T07:04:29.702] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 6 relay1_07 false Profile: dawn - turnOff line according to lux sensor +[2025-10-15T07:04:29.704] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 7 relay1_08 false Profile: dawn - turnOff line according to lux sensor +[2025-10-15T14:08:42.081] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-15T14:08:47.449] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-15T14:08:47.454] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-15T14:08:47.455] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-15T14:08:47.456] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-15T14:08:47.460] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-15T14:08:47.461] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-10-16T05:41:00.460Z +[2025-10-15T14:08:47.463] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-10-15T16:33:00.462Z +[2025-10-15T14:08:47.463] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:41', name: 'luxOff' }, + { value: 1, start_time: '18:33', name: 'luxOn' } +] +[2025-10-15T14:08:47.464] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-10-15T14:08:47.465] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-15T14:08:47.466] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-15T14:08:47.468] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-15T14:08:47.469] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-10-16T05:41:00.469Z +[2025-10-15T14:08:47.470] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-10-15T16:33:00.470Z +[2025-10-15T14:08:47.470] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:41', name: 'luxOff' }, + { value: 1, start_time: '18:33', name: 'luxOn' } +] +[2025-10-15T14:08:47.472] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-10-15T14:08:47.472] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-15T14:08:47.473] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-15T14:08:47.475] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-15T14:08:47.476] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-10-16T05:41:00.475Z +[2025-10-15T14:08:47.476] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-10-15T16:33:00.476Z +[2025-10-15T14:08:47.477] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:41', name: 'luxOff' }, + { value: 1, start_time: '18:33', name: 'luxOn' } +] +[2025-10-15T14:08:47.478] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-10-15T14:08:47.479] [INFO] monitorLogs - buildTasks: profile for line 4 +[2025-10-15T14:08:47.479] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-15T14:08:47.482] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-15T14:08:47.482] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 4 2025-10-16T05:41:00.482Z +[2025-10-15T14:08:47.483] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 4 2025-10-15T16:33:00.483Z +[2025-10-15T14:08:47.484] [INFO] monitorLogs - -->time_points final 4 [ + { value: 0, start_time: '7:41', name: 'luxOff' }, + { value: 1, start_time: '18:33', name: 'luxOn' } +] +[2025-10-15T14:08:47.485] [INFO] monitorLogs - -->currentValue for relay 4 0 +[2025-10-15T14:08:47.485] [INFO] monitorLogs - buildTasks: profile for line 5 +[2025-10-15T14:08:47.486] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-15T14:08:47.488] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-15T14:08:47.489] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 5 2025-10-16T05:41:00.488Z +[2025-10-15T14:08:47.489] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 5 2025-10-15T16:33:00.489Z +[2025-10-15T14:08:47.490] [INFO] monitorLogs - -->time_points final 5 [ + { value: 0, start_time: '7:41', name: 'luxOff' }, + { value: 1, start_time: '18:33', name: 'luxOn' } +] +[2025-10-15T14:08:47.491] [INFO] monitorLogs - -->currentValue for relay 5 0 +[2025-10-15T14:08:47.492] [INFO] monitorLogs - buildTasks: profile for line 6 +[2025-10-15T14:08:47.492] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-15T14:08:47.511] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-15T14:08:47.511] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 6 2025-10-16T05:41:00.511Z +[2025-10-15T14:08:47.512] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 6 2025-10-15T16:33:00.512Z +[2025-10-15T14:08:47.513] [INFO] monitorLogs - -->time_points final 6 [ + { value: 0, start_time: '7:41', name: 'luxOff' }, + { value: 1, start_time: '18:33', name: 'luxOn' } +] +[2025-10-15T14:08:47.514] [INFO] monitorLogs - -->currentValue for relay 6 0 +[2025-10-15T14:08:47.515] [INFO] monitorLogs - buildTasks: profile for line 7 +[2025-10-15T14:08:47.516] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-15T14:08:47.518] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-15T14:08:47.519] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 7 2025-10-16T05:41:00.519Z +[2025-10-15T14:08:47.520] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 7 2025-10-15T16:33:00.520Z +[2025-10-15T14:08:47.520] [INFO] monitorLogs - -->time_points final 7 [ + { value: 0, start_time: '7:41', name: 'luxOff' }, + { value: 1, start_time: '18:33', name: 'luxOn' } +] +[2025-10-15T14:08:47.521] [INFO] monitorLogs - -->currentValue for relay 7 0 +[2025-10-15T14:08:47.529] [INFO] monitorLogs - tasks created: 1510 +[2025-10-15T14:08:47.532] [INFO] monitorLogs - -->FLOW bol spustený o9vbeQlLMVg8j5dq4keLWb0NxZpEmnXzwYKO1ar2 2025-10-08 +[2025-10-15T14:08:52.545] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-15T18:11:09.369] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-15T18:11:09.377] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-15T18:11:09.380] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-15T18:11:09.382] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-10-15T18:11:09.385] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-10-15T18:11:09.387] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 6 relay1_07 false Profile: dusk - turnOn line according to lux sensor +[2025-10-15T18:11:09.389] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 7 relay1_08 false Profile: dusk - turnOn line according to lux sensor diff --git a/RVO34/package-lock.json b/RVO34/package-lock.json new file mode 100755 index 0000000..3c5c1ba --- /dev/null +++ b/RVO34/package-lock.json @@ -0,0 +1,2139 @@ +{ + "name": "emptyproject", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "emptyproject", + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "bitwise": "^2.1.0", + "easy-crc": "0.0.2", + "jsmodbus": "^4.0.6", + "log4js": "^6.3.0", + "moment": "^2.30.1", + "mqtt": "^4.2.6", + "nodemailer": "^6.9.7", + "serialport": "^9.2.8", + "total.js": "^3.4.13" + } + }, + "node_modules/@serialport/binding-abstract": { + "version": "9.2.3", + "resolved": "https://registry.npmjs.org/@serialport/binding-abstract/-/binding-abstract-9.2.3.tgz", + "integrity": "sha512-cQs9tbIlG3P0IrOWyVirqlhWuJ7Ms2Zh9m2108z6Y5UW/iVj6wEOiW8EmK9QX9jmJXYllE7wgGgvVozP5oCj3w==", + "dependencies": { + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/binding-mock": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/binding-mock/-/binding-mock-9.2.4.tgz", + "integrity": "sha512-dpEhACCs44oQhh6ajJfJdvQdK38Vq0N4W6iD/gdplglDCK7qXRQCMUjJIeKdS/HSEiWkC3bwumUhUufdsOyT4g==", + "dependencies": { + "@serialport/binding-abstract": "9.2.3", + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/bindings": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/@serialport/bindings/-/bindings-9.2.8.tgz", + "integrity": "sha512-hSLxTe0tADZ3LMMGwvEJWOC/TaFQTyPeFalUCsJ1lSQ0k6bPF04JwrtB/C81GetmDBTNRY0GlD0SNtKCc7Dr5g==", + "hasInstallScript": true, + "dependencies": { + "@serialport/binding-abstract": "9.2.3", + "@serialport/parser-readline": "9.2.4", + "bindings": "^1.5.0", + "debug": "^4.3.2", + "nan": "^2.15.0", + "prebuild-install": "^7.0.0" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-byte-length": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-byte-length/-/parser-byte-length-9.2.4.tgz", + "integrity": "sha512-sQD/iw4ZMU3xW9PLi0/GlvU6Y623jGeWecbMkO7izUo/6P7gtfv1c9ikd5h0kwL8AoAOpQA1lxdHIKox+umBUg==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-cctalk": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-cctalk/-/parser-cctalk-9.2.4.tgz", + "integrity": "sha512-T4TU5vQMwmo9AB3gQLFDWbfJXlW5jd9guEsB/nqKjFHTv0FXPdZ7DQ2TpSp8RnHWxU3GX6kYTaDO20BKzc8GPQ==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-delimiter": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-delimiter/-/parser-delimiter-9.2.4.tgz", + "integrity": "sha512-4nvTAoYAgkxFiXrkI+3CA49Yd43CODjeszh89EK+I9c8wOZ+etZduRCzINYPiy26g7zO+GRAb9FoPCsY+sYcbQ==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-inter-byte-timeout": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-inter-byte-timeout/-/parser-inter-byte-timeout-9.2.4.tgz", + "integrity": "sha512-SOAdvr0oBQIOCXX198hiTlxs4JTKg9j5piapw5tNq52fwDOWdbYrFneT/wN04UTMKaDrJuEvXq6T4rv4j7nJ5A==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-readline": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-readline/-/parser-readline-9.2.4.tgz", + "integrity": "sha512-Z1/qrZTQUVhNSJP1hd9YfDvq0o7d87rNwAjjRKbVpa7Qi51tG5BnKt43IV3NFMyBlVcRe0rnIb3tJu57E0SOwg==", + "dependencies": { + "@serialport/parser-delimiter": "9.2.4" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-ready": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-ready/-/parser-ready-9.2.4.tgz", + "integrity": "sha512-Pyi94Itjl6qAURwIZr/gmZpMAyTmKXThm6vL5DoAWGQjcRHWB0gwv2TY2v7N+mQLJYUKU3cMnvnATXxHm7xjxw==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-regex": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-regex/-/parser-regex-9.2.4.tgz", + "integrity": "sha512-sI/cVvPOYz+Dbv4ZdnW16qAwvXiFf/1pGASQdbveRTlgJDdz7sRNlCBifzfTN2xljwvCTZYqiudKvDdC1TepRQ==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/stream": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/stream/-/stream-9.2.4.tgz", + "integrity": "sha512-bLye8Ub4vUFQGmkh8qEqehr7SE7EJs2yDs0h9jzuL5oKi+F34CFmWkEErO8GAOQ8YNn7p6b3GxUgs+0BrHHDZQ==", + "dependencies": { + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "node_modules/are-we-there-yet": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", + "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/base64-js": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", + "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==" + }, + "node_modules/bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "dependencies": { + "file-uri-to-path": "1.0.0" + } + }, + "node_modules/bitwise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/bitwise/-/bitwise-2.1.0.tgz", + "integrity": "sha512-XKgAhMXCh4H/3oNwAHAsAO0iC89s9cOiumgYwSHjSobGWxYjv62YhkL9QEdvGP151xypCtMlAfKK79GEcd2eRQ==" + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/bl/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/buffer": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz", + "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==", + "dependencies": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + }, + "node_modules/buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" + }, + "node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, + "node_modules/code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/commist": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/commist/-/commist-1.1.0.tgz", + "integrity": "sha512-rraC8NXWOEjhADbZe9QBNzLAN5Q3fsTPQtBV+fEVj6xKIgDgNiEVE6ZNfHpZOqfQ21YUzfVNUXLOEZquYvQPPg==", + "dependencies": { + "leven": "^2.1.0", + "minimist": "^1.1.0" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "node_modules/concat-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", + "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", + "engines": [ + "node >= 6.0" + ], + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.0.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/concat-stream/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" + }, + "node_modules/core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "node_modules/crc": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/crc/-/crc-3.4.0.tgz", + "integrity": "sha512-ycVC2+4/DLgXXq7QweYi2znhqDuZz6P5TQXnkQo8v15XY/5p/IWeZwsSE31Ifo8w15b8TWLsqhXOjXyilHuQxw==" + }, + "node_modules/date-format": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.11.tgz", + "integrity": "sha512-VS20KRyorrbMCQmpdl2hg5KaOUsda1RbnsJg461FfrcyCUg+pkd0b40BSW4niQyTheww4DBXQnS7HwSrKkipLw==", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" + }, + "node_modules/detect-libc": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz", + "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==", + "engines": { + "node": ">=8" + } + }, + "node_modules/duplexify": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.2.tgz", + "integrity": "sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw==", + "dependencies": { + "end-of-stream": "^1.4.1", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1", + "stream-shift": "^1.0.0" + } + }, + "node_modules/duplexify/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/easy-crc": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/easy-crc/-/easy-crc-0.0.2.tgz", + "integrity": "sha512-h6eqIdhJRe0p271/xZJbM/0klCi13mW5IB7ZEzEGH11yV4QXWAkD4yPErz0fXdhFrd6sZ4Q1k5Iky2kMsMNePw==" + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" + }, + "node_modules/flatted": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", + "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==" + }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, + "node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "node_modules/gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha512-14x4kjc6lkD3ltw589k0NrPD6cCNTD6CWoVUNpB85+DrtONoZn+Rug6xZU5RvSC4+TZPxA5AnBibQYAvZn41Hg==", + "dependencies": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "node_modules/github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==" + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" + }, + "node_modules/has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" + }, + "node_modules/help-me": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/help-me/-/help-me-3.0.0.tgz", + "integrity": "sha512-hx73jClhyk910sidBB7ERlnhMlFsJJIBqSVMFDwPN8o2v9nmp5KgLq1Xz1Bf1fCMMZ6mPrX159iG0VLy/fPMtQ==", + "dependencies": { + "glob": "^7.1.6", + "readable-stream": "^3.6.0" + } + }, + "node_modules/help-me/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, + "node_modules/is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==", + "dependencies": { + "number-is-nan": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "node_modules/js-sdsl": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz", + "integrity": "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/js-sdsl" + } + }, + "node_modules/jsmodbus": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/jsmodbus/-/jsmodbus-4.0.6.tgz", + "integrity": "sha512-gCmjoaERErK5Rn9Lu/BN07fY13MoWV7JKgGzrnkPlQPdPxYcwDhLtYcmpFFpZ4J9NPZZBSezi1UkLZO/DnNppA==", + "dependencies": { + "crc": "3.4.0", + "debug": "^3.1.0" + }, + "bin": { + "jsmodbus": "bin/jsmodbus.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/jsmodbus/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/leven": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", + "integrity": "sha1-wuep93IJTe6dNCAq6KzORoeHVYA=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/log4js": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.5.2.tgz", + "integrity": "sha512-DXtpNtt+KDOMT7RHUDIur/WsSA3rntlUh9Zg4XCdV42wUuMmbFkl38+LZ92Z5QvQA7mD5kAVkLiBSEH/tvUB8A==", + "dependencies": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "flatted": "^3.2.5", + "rfdc": "^1.3.0", + "streamroller": "^3.1.1" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" + }, + "node_modules/moment": { + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", + "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==", + "engines": { + "node": "*" + } + }, + "node_modules/mqtt": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/mqtt/-/mqtt-4.3.7.tgz", + "integrity": "sha512-ew3qwG/TJRorTz47eW46vZ5oBw5MEYbQZVaEji44j5lAUSQSqIEoul7Kua/BatBW0H0kKQcC9kwUHa1qzaWHSw==", + "dependencies": { + "commist": "^1.0.0", + "concat-stream": "^2.0.0", + "debug": "^4.1.1", + "duplexify": "^4.1.1", + "help-me": "^3.0.0", + "inherits": "^2.0.3", + "lru-cache": "^6.0.0", + "minimist": "^1.2.5", + "mqtt-packet": "^6.8.0", + "number-allocator": "^1.0.9", + "pump": "^3.0.0", + "readable-stream": "^3.6.0", + "reinterval": "^1.1.0", + "rfdc": "^1.3.0", + "split2": "^3.1.0", + "ws": "^7.5.5", + "xtend": "^4.0.2" + }, + "bin": { + "mqtt": "bin/mqtt.js", + "mqtt_pub": "bin/pub.js", + "mqtt_sub": "bin/sub.js" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/mqtt-packet": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/mqtt-packet/-/mqtt-packet-6.10.0.tgz", + "integrity": "sha512-ja8+mFKIHdB1Tpl6vac+sktqy3gA8t9Mduom1BA75cI+R9AHnZOiaBQwpGiWnaVJLDGRdNhQmFaAqd7tkKSMGA==", + "dependencies": { + "bl": "^4.0.2", + "debug": "^4.1.1", + "process-nextick-args": "^2.0.1" + } + }, + "node_modules/mqtt/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/nan": { + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.16.0.tgz", + "integrity": "sha512-UdAqHyFngu7TfQKsCBgAA6pWDkT8MAO7d0jyOecVhN5354xbLqdn8mV9Tat9gepAupm0bt2DbeaSC8vS52MuFA==" + }, + "node_modules/napi-build-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", + "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==" + }, + "node_modules/node-abi": { + "version": "3.22.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.22.0.tgz", + "integrity": "sha512-u4uAs/4Zzmp/jjsD9cyFYDXeISfUWaAVWshPmDZOFOv4Xl4SbzTXm53I04C2uRueYJ+0t5PEtLH/owbn2Npf/w==", + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/nodemailer": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.7.tgz", + "integrity": "sha512-rUtR77ksqex/eZRLmQ21LKVH5nAAsVicAtAYudK7JgwenEDZ0UIQ1adUGqErz7sMkWYxWTTU1aeP2Jga6WQyJw==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "dependencies": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "node_modules/number-allocator": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/number-allocator/-/number-allocator-1.0.14.tgz", + "integrity": "sha512-OrL44UTVAvkKdOdRQZIJpLkAdjXGTRda052sN4sO77bKEzYYqWKMBjQvrJFzqygI99gL6Z4u2xctPW1tB8ErvA==", + "dependencies": { + "debug": "^4.3.1", + "js-sdsl": "4.3.0" + } + }, + "node_modules/number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/prebuild-install": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.0.tgz", + "integrity": "sha512-CNcMgI1xBypOyGqjp3wOc8AAo1nMhZS3Cwd3iHIxOdAUbb+YxdNuM4Z5iIrZ8RLvOsf3F3bl7b7xGq6DjQoNYA==", + "dependencies": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^1.0.1", + "node-abi": "^3.3.0", + "npmlog": "^4.0.1", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + }, + "bin": { + "prebuild-install": "bin.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/reinterval": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reinterval/-/reinterval-1.1.0.tgz", + "integrity": "sha1-M2Hs+jymwYKDOA3Qu5VG85D17Oc=" + }, + "node_modules/rfdc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==" + }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/serialport": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/serialport/-/serialport-9.2.8.tgz", + "integrity": "sha512-FsWpMQgSJxi93JgWl5xM1f9/Z8IjRJuaUEoHqLf8FPBLw7gMhInuHOBhI2onQufWIYPGTz3H3oGcu1nCaK1EfA==", + "dependencies": { + "@serialport/binding-mock": "9.2.4", + "@serialport/bindings": "9.2.8", + "@serialport/parser-byte-length": "9.2.4", + "@serialport/parser-cctalk": "9.2.4", + "@serialport/parser-delimiter": "9.2.4", + "@serialport/parser-inter-byte-timeout": "9.2.4", + "@serialport/parser-readline": "9.2.4", + "@serialport/parser-ready": "9.2.4", + "@serialport/parser-regex": "9.2.4", + "@serialport/stream": "9.2.4", + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "node_modules/split2": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", + "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", + "dependencies": { + "readable-stream": "^3.0.0" + } + }, + "node_modules/split2/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==" + }, + "node_modules/streamroller": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.1.1.tgz", + "integrity": "sha512-iPhtd9unZ6zKdWgMeYGfSBuqCngyJy1B/GPi/lTpwGpa3bajuX30GjUVd0/Tn/Xhg0mr4DOSENozz9Y06qyonQ==", + "dependencies": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "fs-extra": "^10.1.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dependencies": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/tar-fs": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "dependencies": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tar-stream/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/total.js": { + "version": "3.4.13", + "resolved": "https://registry.npmjs.org/total.js/-/total.js-3.4.13.tgz", + "integrity": "sha512-lAH4gEixlPFbrE3xfKADAcHfO79IFq2wKa9GTsrgRzIR5MTg3mNH7+4IxvX1pK8faoYb/0oYSJ1YTsAa5hIFFQ==", + "bin": { + "total": "bin/totaljs", + "total.js": "bin/totaljs", + "totaljs": "bin/totaljs", + "totalpackage": "bin/tpm", + "tpm": "bin/tpm" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, + "node_modules/universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "node_modules/wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "node_modules/ws": { + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } + }, + "dependencies": { + "@serialport/binding-abstract": { + "version": "9.2.3", + "resolved": "https://registry.npmjs.org/@serialport/binding-abstract/-/binding-abstract-9.2.3.tgz", + "integrity": "sha512-cQs9tbIlG3P0IrOWyVirqlhWuJ7Ms2Zh9m2108z6Y5UW/iVj6wEOiW8EmK9QX9jmJXYllE7wgGgvVozP5oCj3w==", + "requires": { + "debug": "^4.3.2" + } + }, + "@serialport/binding-mock": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/binding-mock/-/binding-mock-9.2.4.tgz", + "integrity": "sha512-dpEhACCs44oQhh6ajJfJdvQdK38Vq0N4W6iD/gdplglDCK7qXRQCMUjJIeKdS/HSEiWkC3bwumUhUufdsOyT4g==", + "requires": { + "@serialport/binding-abstract": "9.2.3", + "debug": "^4.3.2" + } + }, + "@serialport/bindings": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/@serialport/bindings/-/bindings-9.2.8.tgz", + "integrity": "sha512-hSLxTe0tADZ3LMMGwvEJWOC/TaFQTyPeFalUCsJ1lSQ0k6bPF04JwrtB/C81GetmDBTNRY0GlD0SNtKCc7Dr5g==", + "requires": { + "@serialport/binding-abstract": "9.2.3", + "@serialport/parser-readline": "9.2.4", + "bindings": "^1.5.0", + "debug": "^4.3.2", + "nan": "^2.15.0", + "prebuild-install": "^7.0.0" + } + }, + "@serialport/parser-byte-length": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-byte-length/-/parser-byte-length-9.2.4.tgz", + "integrity": "sha512-sQD/iw4ZMU3xW9PLi0/GlvU6Y623jGeWecbMkO7izUo/6P7gtfv1c9ikd5h0kwL8AoAOpQA1lxdHIKox+umBUg==" + }, + "@serialport/parser-cctalk": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-cctalk/-/parser-cctalk-9.2.4.tgz", + "integrity": "sha512-T4TU5vQMwmo9AB3gQLFDWbfJXlW5jd9guEsB/nqKjFHTv0FXPdZ7DQ2TpSp8RnHWxU3GX6kYTaDO20BKzc8GPQ==" + }, + "@serialport/parser-delimiter": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-delimiter/-/parser-delimiter-9.2.4.tgz", + "integrity": "sha512-4nvTAoYAgkxFiXrkI+3CA49Yd43CODjeszh89EK+I9c8wOZ+etZduRCzINYPiy26g7zO+GRAb9FoPCsY+sYcbQ==" + }, + "@serialport/parser-inter-byte-timeout": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-inter-byte-timeout/-/parser-inter-byte-timeout-9.2.4.tgz", + "integrity": "sha512-SOAdvr0oBQIOCXX198hiTlxs4JTKg9j5piapw5tNq52fwDOWdbYrFneT/wN04UTMKaDrJuEvXq6T4rv4j7nJ5A==" + }, + "@serialport/parser-readline": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-readline/-/parser-readline-9.2.4.tgz", + "integrity": "sha512-Z1/qrZTQUVhNSJP1hd9YfDvq0o7d87rNwAjjRKbVpa7Qi51tG5BnKt43IV3NFMyBlVcRe0rnIb3tJu57E0SOwg==", + "requires": { + "@serialport/parser-delimiter": "9.2.4" + } + }, + "@serialport/parser-ready": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-ready/-/parser-ready-9.2.4.tgz", + "integrity": "sha512-Pyi94Itjl6qAURwIZr/gmZpMAyTmKXThm6vL5DoAWGQjcRHWB0gwv2TY2v7N+mQLJYUKU3cMnvnATXxHm7xjxw==" + }, + "@serialport/parser-regex": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-regex/-/parser-regex-9.2.4.tgz", + "integrity": "sha512-sI/cVvPOYz+Dbv4ZdnW16qAwvXiFf/1pGASQdbveRTlgJDdz7sRNlCBifzfTN2xljwvCTZYqiudKvDdC1TepRQ==" + }, + "@serialport/stream": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/stream/-/stream-9.2.4.tgz", + "integrity": "sha512-bLye8Ub4vUFQGmkh8qEqehr7SE7EJs2yDs0h9jzuL5oKi+F34CFmWkEErO8GAOQ8YNn7p6b3GxUgs+0BrHHDZQ==", + "requires": { + "debug": "^4.3.2" + } + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==" + }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "are-we-there-yet": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", + "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "base64-js": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", + "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==" + }, + "bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "requires": { + "file-uri-to-path": "1.0.0" + } + }, + "bitwise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/bitwise/-/bitwise-2.1.0.tgz", + "integrity": "sha512-XKgAhMXCh4H/3oNwAHAsAO0iC89s9cOiumgYwSHjSobGWxYjv62YhkL9QEdvGP151xypCtMlAfKK79GEcd2eRQ==" + }, + "bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "requires": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "buffer": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz", + "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==", + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" + }, + "chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==" + }, + "commist": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/commist/-/commist-1.1.0.tgz", + "integrity": "sha512-rraC8NXWOEjhADbZe9QBNzLAN5Q3fsTPQtBV+fEVj6xKIgDgNiEVE6ZNfHpZOqfQ21YUzfVNUXLOEZquYvQPPg==", + "requires": { + "leven": "^2.1.0", + "minimist": "^1.1.0" + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "concat-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", + "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.0.2", + "typedarray": "^0.0.6" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "crc": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/crc/-/crc-3.4.0.tgz", + "integrity": "sha512-ycVC2+4/DLgXXq7QweYi2znhqDuZz6P5TQXnkQo8v15XY/5p/IWeZwsSE31Ifo8w15b8TWLsqhXOjXyilHuQxw==" + }, + "date-format": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.11.tgz", + "integrity": "sha512-VS20KRyorrbMCQmpdl2hg5KaOUsda1RbnsJg461FfrcyCUg+pkd0b40BSW4niQyTheww4DBXQnS7HwSrKkipLw==" + }, + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "requires": { + "ms": "2.1.2" + } + }, + "decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "requires": { + "mimic-response": "^3.1.0" + } + }, + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==" + }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" + }, + "detect-libc": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz", + "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==" + }, + "duplexify": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.2.tgz", + "integrity": "sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw==", + "requires": { + "end-of-stream": "^1.4.1", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1", + "stream-shift": "^1.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "easy-crc": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/easy-crc/-/easy-crc-0.0.2.tgz", + "integrity": "sha512-h6eqIdhJRe0p271/xZJbM/0klCi13mW5IB7ZEzEGH11yV4QXWAkD4yPErz0fXdhFrd6sZ4Q1k5Iky2kMsMNePw==" + }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "requires": { + "once": "^1.4.0" + } + }, + "expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==" + }, + "file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" + }, + "flatted": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", + "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==" + }, + "fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, + "fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha512-14x4kjc6lkD3ltw589k0NrPD6cCNTD6CWoVUNpB85+DrtONoZn+Rug6xZU5RvSC4+TZPxA5AnBibQYAvZn41Hg==", + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==" + }, + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" + }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" + }, + "help-me": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/help-me/-/help-me-3.0.0.tgz", + "integrity": "sha512-hx73jClhyk910sidBB7ERlnhMlFsJJIBqSVMFDwPN8o2v9nmp5KgLq1Xz1Bf1fCMMZ6mPrX159iG0VLy/fPMtQ==", + "requires": { + "glob": "^7.1.6", + "readable-stream": "^3.6.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==", + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "js-sdsl": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz", + "integrity": "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==" + }, + "jsmodbus": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/jsmodbus/-/jsmodbus-4.0.6.tgz", + "integrity": "sha512-gCmjoaERErK5Rn9Lu/BN07fY13MoWV7JKgGzrnkPlQPdPxYcwDhLtYcmpFFpZ4J9NPZZBSezi1UkLZO/DnNppA==", + "requires": { + "crc": "3.4.0", + "debug": "^3.1.0" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "requires": { + "ms": "^2.1.1" + } + } + } + }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, + "leven": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", + "integrity": "sha1-wuep93IJTe6dNCAq6KzORoeHVYA=" + }, + "log4js": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.5.2.tgz", + "integrity": "sha512-DXtpNtt+KDOMT7RHUDIur/WsSA3rntlUh9Zg4XCdV42wUuMmbFkl38+LZ92Z5QvQA7mD5kAVkLiBSEH/tvUB8A==", + "requires": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "flatted": "^3.2.5", + "rfdc": "^1.3.0", + "streamroller": "^3.1.1" + } + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "requires": { + "yallist": "^4.0.0" + } + }, + "mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==" + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==" + }, + "mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" + }, + "moment": { + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", + "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==" + }, + "mqtt": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/mqtt/-/mqtt-4.3.7.tgz", + "integrity": "sha512-ew3qwG/TJRorTz47eW46vZ5oBw5MEYbQZVaEji44j5lAUSQSqIEoul7Kua/BatBW0H0kKQcC9kwUHa1qzaWHSw==", + "requires": { + "commist": "^1.0.0", + "concat-stream": "^2.0.0", + "debug": "^4.1.1", + "duplexify": "^4.1.1", + "help-me": "^3.0.0", + "inherits": "^2.0.3", + "lru-cache": "^6.0.0", + "minimist": "^1.2.5", + "mqtt-packet": "^6.8.0", + "number-allocator": "^1.0.9", + "pump": "^3.0.0", + "readable-stream": "^3.6.0", + "reinterval": "^1.1.0", + "rfdc": "^1.3.0", + "split2": "^3.1.0", + "ws": "^7.5.5", + "xtend": "^4.0.2" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "mqtt-packet": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/mqtt-packet/-/mqtt-packet-6.10.0.tgz", + "integrity": "sha512-ja8+mFKIHdB1Tpl6vac+sktqy3gA8t9Mduom1BA75cI+R9AHnZOiaBQwpGiWnaVJLDGRdNhQmFaAqd7tkKSMGA==", + "requires": { + "bl": "^4.0.2", + "debug": "^4.1.1", + "process-nextick-args": "^2.0.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "nan": { + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.16.0.tgz", + "integrity": "sha512-UdAqHyFngu7TfQKsCBgAA6pWDkT8MAO7d0jyOecVhN5354xbLqdn8mV9Tat9gepAupm0bt2DbeaSC8vS52MuFA==" + }, + "napi-build-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", + "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==" + }, + "node-abi": { + "version": "3.22.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.22.0.tgz", + "integrity": "sha512-u4uAs/4Zzmp/jjsD9cyFYDXeISfUWaAVWshPmDZOFOv4Xl4SbzTXm53I04C2uRueYJ+0t5PEtLH/owbn2Npf/w==", + "requires": { + "semver": "^7.3.5" + } + }, + "nodemailer": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.7.tgz", + "integrity": "sha512-rUtR77ksqex/eZRLmQ21LKVH5nAAsVicAtAYudK7JgwenEDZ0UIQ1adUGqErz7sMkWYxWTTU1aeP2Jga6WQyJw==" + }, + "npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "number-allocator": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/number-allocator/-/number-allocator-1.0.14.tgz", + "integrity": "sha512-OrL44UTVAvkKdOdRQZIJpLkAdjXGTRda052sN4sO77bKEzYYqWKMBjQvrJFzqygI99gL6Z4u2xctPW1tB8ErvA==", + "requires": { + "debug": "^4.3.1", + "js-sdsl": "4.3.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==" + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==" + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==" + }, + "prebuild-install": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.0.tgz", + "integrity": "sha512-CNcMgI1xBypOyGqjp3wOc8AAo1nMhZS3Cwd3iHIxOdAUbb+YxdNuM4Z5iIrZ8RLvOsf3F3bl7b7xGq6DjQoNYA==", + "requires": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^1.0.1", + "node-abi": "^3.3.0", + "npmlog": "^4.0.1", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + } + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + } + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "reinterval": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reinterval/-/reinterval-1.1.0.tgz", + "integrity": "sha1-M2Hs+jymwYKDOA3Qu5VG85D17Oc=" + }, + "rfdc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==" + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "requires": { + "lru-cache": "^6.0.0" + } + }, + "serialport": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/serialport/-/serialport-9.2.8.tgz", + "integrity": "sha512-FsWpMQgSJxi93JgWl5xM1f9/Z8IjRJuaUEoHqLf8FPBLw7gMhInuHOBhI2onQufWIYPGTz3H3oGcu1nCaK1EfA==", + "requires": { + "@serialport/binding-mock": "9.2.4", + "@serialport/bindings": "9.2.8", + "@serialport/parser-byte-length": "9.2.4", + "@serialport/parser-cctalk": "9.2.4", + "@serialport/parser-delimiter": "9.2.4", + "@serialport/parser-inter-byte-timeout": "9.2.4", + "@serialport/parser-readline": "9.2.4", + "@serialport/parser-ready": "9.2.4", + "@serialport/parser-regex": "9.2.4", + "@serialport/stream": "9.2.4", + "debug": "^4.3.2" + } + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==" + }, + "simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "requires": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "split2": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", + "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", + "requires": { + "readable-stream": "^3.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==" + }, + "streamroller": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.1.1.tgz", + "integrity": "sha512-iPhtd9unZ6zKdWgMeYGfSBuqCngyJy1B/GPi/lTpwGpa3bajuX30GjUVd0/Tn/Xhg0mr4DOSENozz9Y06qyonQ==", + "requires": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "fs-extra": "^10.1.0" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" + }, + "tar-fs": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "requires": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "requires": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "total.js": { + "version": "3.4.13", + "resolved": "https://registry.npmjs.org/total.js/-/total.js-3.4.13.tgz", + "integrity": "sha512-lAH4gEixlPFbrE3xfKADAcHfO79IFq2wKa9GTsrgRzIR5MTg3mNH7+4IxvX1pK8faoYb/0oYSJ1YTsAa5hIFFQ==" + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, + "universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==" + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "requires": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "ws": { + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "requires": {} + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } + } +} diff --git a/RVO34/package.json b/RVO34/package.json new file mode 100755 index 0000000..7f7c795 --- /dev/null +++ b/RVO34/package.json @@ -0,0 +1,30 @@ +{ + "name": "emptyproject", + "description": "Total.js empty project.", + "version": "1.0.0", + "main": "debug.js", + "dependencies": { + "bitwise": "^2.1.0", + "easy-crc": "0.0.2", + "jsmodbus": "^4.0.6", + "log4js": "^6.3.0", + "moment": "^2.30.1", + "mqtt": "^4.2.6", + "nodemailer": "^6.9.7", + "serialport": "^9.2.8", + "total.js": "^3.4.13" + }, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "https://github.com/totaljs/emptyproject-flow" + }, + "keywords": [ + "empty", + "project" + ], + "author": "Peter Širka", + "license": "MIT" +} diff --git a/RVO34/release.js b/RVO34/release.js new file mode 100755 index 0000000..02d52ff --- /dev/null +++ b/RVO34/release.js @@ -0,0 +1,15 @@ +// =================================================== +// FOR PRODUCTION +// Total.js - framework for Node.js platform +// https://www.totaljs.com +// =================================================== + +const options = {'ip':'0.0.0.0', 'port':12345}; + +// options.ip = '127.0.0.1'; +// options.port = parseInt(process.argv[2]); +// options.config = { name: 'Total.js' }; +// options.sleep = 3000; + +require('total.js').http('release', options); +// require('total.js').cluster.http(5, 'release', options); diff --git a/RVO34/release.js.json b/RVO34/release.js.json new file mode 100755 index 0000000..3b19502 --- /dev/null +++ b/RVO34/release.js.json @@ -0,0 +1,34 @@ +{ + "pid": 388, + "stats": [ + { + "id": null, + "version": { + "node": "v14.18.1", + "total": "3.4.13", + "app": "1.0.0" + }, + "pid": 388, + "thread": "", + "mode": "release", + "overload": 0, + "date": "2025-10-16T00:24:38.328Z", + "memory": 23.59, + "rm": 0, + "fm": 0, + "wm": 0, + "mm": 0, + "om": 20, + "em": 1, + "dbrm": 0, + "dbwm": 0, + "usage": 0, + "requests": 0, + "pending": 0, + "errors": 0, + "timeouts": 0, + "uptime": 737, + "online": 0 + } + ] +} \ No newline at end of file diff --git a/RVO34/report_data.log b/RVO34/report_data.log new file mode 100755 index 0000000..cc2ce04 --- /dev/null +++ b/RVO34/report_data.log @@ -0,0 +1,187 @@ +{ + "name": "rvo_senica_34_10.0.0.128", + "time": "2025-10-15T13:08:54.371Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_34_10.0.0.128", + "time": "2025-10-15T14:08:54.369Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_34_10.0.0.128", + "time": "2025-10-15T15:08:54.369Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_34_10.0.0.128", + "time": "2025-10-15T16:08:54.370Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_34_10.0.0.128", + "time": "2025-10-15T17:37:15.543Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "34/82_1L_3438_NEMA", + "34/11_1L_4006_NEMA" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_34_10.0.0.128", + "time": "2025-10-15T18:37:15.543Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "34/82_1L_3438_NEMA", + "34/11_1L_4006_NEMA" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_34_10.0.0.128", + "time": "2025-10-15T19:37:15.543Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "34/82_1L_3438_NEMA", + "34/11_1L_4006_NEMA" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_34_10.0.0.128", + "time": "2025-10-15T20:37:15.547Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "34/82_1L_3438_NEMA", + "34/11_1L_4006_NEMA" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_34_10.0.0.128", + "time": "2025-10-15T21:37:15.543Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "34/82_1L_3438_NEMA", + "34/11_1L_4006_NEMA" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_34_10.0.0.128", + "time": "2025-10-15T22:37:15.546Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "34/82_1L_3438_NEMA", + "34/11_1L_4006_NEMA" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_34_10.0.0.128", + "time": "2025-10-15T23:37:15.545Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "34/82_1L_3438_NEMA", + "34/11_1L_4006_NEMA" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +} \ No newline at end of file From 15c2f1eb9c8662c6832a77de62d76a6a80860d0b Mon Sep 17 00:00:00 2001 From: Jakub Klena Date: Thu, 16 Oct 2025 02:25:46 +0200 Subject: [PATCH 17/30] Backup senica-RVO35 on 16.10.2025 --- RVO35/addSwitch.py | 36 + RVO35/cloud_topic.py | 76 + RVO35/config | 12 + RVO35/createNode.py | 43 + RVO35/databases/accelerometer_db.js | 3055 ++++++++++++++++ RVO35/databases/modbus_config.js | 114 + RVO35/databases/nodes.table | 80 + .../nodes_original/nodes_original.table | 1 + RVO35/databases/notifications.table | 41 + RVO35/databases/pins.table | 17 + RVO35/databases/relays.table | 8 + RVO35/databases/settings.table | 2 + RVO35/databases/tbdata.nosql | 4 + RVO35/databases/tbdatacloud.nosql | 3 + RVO35/databases/total_energy.js | 38 + RVO35/debug.js | 16 + RVO35/err.txt | 107 + RVO35/flow/cloudmqttconnect.js | 357 ++ RVO35/flow/cmd_manager.js | 3071 ++++++++++++++++ RVO35/flow/code.js | 90 + RVO35/flow/comment.js | 11 + RVO35/flow/count.js | 60 + RVO35/flow/db_connector.js | 286 ++ RVO35/flow/db_init.js | 113 + RVO35/flow/debug.js | 100 + RVO35/flow/designer.json | 3102 +++++++++++++++++ RVO35/flow/dido_controller.js | 1486 ++++++++ RVO35/flow/helper/DataToTbHandler.js | 187 + RVO35/flow/helper/ErrorToServiceHandler.js | 91 + RVO35/flow/helper/db_helper.js | 44 + RVO35/flow/helper/logger.js | 30 + RVO35/flow/helper/md5.js | 5 + RVO35/flow/helper/notification_reporter.js | 121 + RVO35/flow/helper/register.js | 144 + RVO35/flow/helper/serialport_helper.js | 99 + RVO35/flow/helper/suncalc.js | 317 ++ RVO35/flow/helper/utils.js | 161 + RVO35/flow/httprequest.js | 137 + RVO35/flow/httpresponse.js | 76 + RVO35/flow/httproute.js | 326 ++ RVO35/flow/infosender.js | 81 + RVO35/flow/modbus_reader.js | 346 ++ RVO35/flow/monitorconsumption.js | 156 + RVO35/flow/monitordisk.js | 96 + RVO35/flow/monitormemory.js | 87 + RVO35/flow/nodesdb_changecheck.js | 77 + RVO35/flow/show_dbdata.js | 243 ++ RVO35/flow/slack_filter.js | 188 + RVO35/flow/thermometer.js | 98 + RVO35/flow/trigger.js | 79 + RVO35/flow/variables.txt | 0 RVO35/flow/virtualwirein.js | 43 + RVO35/flow/virtualwireout.js | 41 + RVO35/flow/wsmqttpublish.js | 448 +++ RVO35/flow_old/audit_test_panel.csv | 48 + RVO35/flow_old/cloudmqttconnect.js | 374 ++ RVO35/flow_old/cmd_manager.js | 2890 +++++++++++++++ RVO35/flow_old/code.js | 90 + RVO35/flow_old/comment.js | 11 + RVO35/flow_old/count.js | 60 + RVO35/flow_old/csv_import.js | 175 + RVO35/flow_old/db_connector.js | 286 ++ RVO35/flow_old/db_init.js | 106 + RVO35/flow_old/debug.js | 100 + RVO35/flow_old/designer.json | 2846 +++++++++++++++ RVO35/flow_old/dido_controller.js | 1473 ++++++++ RVO35/flow_old/helper/DataToTbHandler.js | 156 + .../flow_old/helper/ErrorToServiceHandler.js | 126 + RVO35/flow_old/helper/db_helper.js | 44 + RVO35/flow_old/helper/logger.js | 30 + RVO35/flow_old/helper/md5.js | 5 + .../flow_old/helper/notification_reporter.js | 131 + RVO35/flow_old/helper/register.js | 144 + RVO35/flow_old/helper/serialport_helper.js | 100 + RVO35/flow_old/helper/suncalc.js | 317 ++ RVO35/flow_old/helper/utils.js | 124 + RVO35/flow_old/httprequest.js | 137 + RVO35/flow_old/httpresponse.js | 76 + RVO35/flow_old/httproute.js | 326 ++ RVO35/flow_old/infosender.js | 101 + RVO35/flow_old/modbus_reader.js | 367 ++ RVO35/flow_old/monitorconsumption.js | 156 + RVO35/flow_old/monitordisk.js | 96 + RVO35/flow_old/monitormemory.js | 87 + RVO35/flow_old/nodesdb_changecheck.js | 70 + RVO35/flow_old/notifikacie.csv | 31 + RVO35/flow_old/show_dbdata.js | 241 ++ RVO35/flow_old/slack_filter.js | 187 + RVO35/flow_old/thermometer.js | 98 + RVO35/flow_old/trigger.js | 79 + RVO35/flow_old/variables.txt | 0 RVO35/flow_old/virtualwirein.js | 43 + RVO35/flow_old/virtualwireout.js | 41 + RVO35/flow_old/wsmqttpublish.js | 477 +++ RVO35/monitor.txt | 1241 +++++++ RVO35/package-lock.json | 2125 +++++++++++ RVO35/package.json | 29 + RVO35/release.js | 15 + RVO35/release.js.json | 34 + RVO35/report_data.log | 395 +++ 100 files changed, 32138 insertions(+) create mode 100755 RVO35/addSwitch.py create mode 100755 RVO35/cloud_topic.py create mode 100755 RVO35/config create mode 100755 RVO35/createNode.py create mode 100755 RVO35/databases/accelerometer_db.js create mode 100755 RVO35/databases/modbus_config.js create mode 100755 RVO35/databases/nodes.table create mode 100755 RVO35/databases/nodes_original/nodes_original.table create mode 100755 RVO35/databases/notifications.table create mode 100755 RVO35/databases/pins.table create mode 100755 RVO35/databases/relays.table create mode 100755 RVO35/databases/settings.table create mode 100755 RVO35/databases/tbdata.nosql create mode 100755 RVO35/databases/tbdatacloud.nosql create mode 100755 RVO35/databases/total_energy.js create mode 100755 RVO35/debug.js create mode 100755 RVO35/err.txt create mode 100755 RVO35/flow/cloudmqttconnect.js create mode 100755 RVO35/flow/cmd_manager.js create mode 100755 RVO35/flow/code.js create mode 100755 RVO35/flow/comment.js create mode 100755 RVO35/flow/count.js create mode 100755 RVO35/flow/db_connector.js create mode 100755 RVO35/flow/db_init.js create mode 100755 RVO35/flow/debug.js create mode 100755 RVO35/flow/designer.json create mode 100755 RVO35/flow/dido_controller.js create mode 100755 RVO35/flow/helper/DataToTbHandler.js create mode 100755 RVO35/flow/helper/ErrorToServiceHandler.js create mode 100755 RVO35/flow/helper/db_helper.js create mode 100755 RVO35/flow/helper/logger.js create mode 100755 RVO35/flow/helper/md5.js create mode 100755 RVO35/flow/helper/notification_reporter.js create mode 100755 RVO35/flow/helper/register.js create mode 100755 RVO35/flow/helper/serialport_helper.js create mode 100755 RVO35/flow/helper/suncalc.js create mode 100755 RVO35/flow/helper/utils.js create mode 100755 RVO35/flow/httprequest.js create mode 100755 RVO35/flow/httpresponse.js create mode 100755 RVO35/flow/httproute.js create mode 100755 RVO35/flow/infosender.js create mode 100755 RVO35/flow/modbus_reader.js create mode 100755 RVO35/flow/monitorconsumption.js create mode 100755 RVO35/flow/monitordisk.js create mode 100755 RVO35/flow/monitormemory.js create mode 100755 RVO35/flow/nodesdb_changecheck.js create mode 100755 RVO35/flow/show_dbdata.js create mode 100755 RVO35/flow/slack_filter.js create mode 100755 RVO35/flow/thermometer.js create mode 100755 RVO35/flow/trigger.js create mode 100755 RVO35/flow/variables.txt create mode 100755 RVO35/flow/virtualwirein.js create mode 100755 RVO35/flow/virtualwireout.js create mode 100755 RVO35/flow/wsmqttpublish.js create mode 100755 RVO35/flow_old/audit_test_panel.csv create mode 100755 RVO35/flow_old/cloudmqttconnect.js create mode 100755 RVO35/flow_old/cmd_manager.js create mode 100755 RVO35/flow_old/code.js create mode 100755 RVO35/flow_old/comment.js create mode 100755 RVO35/flow_old/count.js create mode 100755 RVO35/flow_old/csv_import.js create mode 100755 RVO35/flow_old/db_connector.js create mode 100755 RVO35/flow_old/db_init.js create mode 100755 RVO35/flow_old/debug.js create mode 100755 RVO35/flow_old/designer.json create mode 100755 RVO35/flow_old/dido_controller.js create mode 100755 RVO35/flow_old/helper/DataToTbHandler.js create mode 100755 RVO35/flow_old/helper/ErrorToServiceHandler.js create mode 100755 RVO35/flow_old/helper/db_helper.js create mode 100755 RVO35/flow_old/helper/logger.js create mode 100755 RVO35/flow_old/helper/md5.js create mode 100755 RVO35/flow_old/helper/notification_reporter.js create mode 100755 RVO35/flow_old/helper/register.js create mode 100755 RVO35/flow_old/helper/serialport_helper.js create mode 100755 RVO35/flow_old/helper/suncalc.js create mode 100755 RVO35/flow_old/helper/utils.js create mode 100755 RVO35/flow_old/httprequest.js create mode 100755 RVO35/flow_old/httpresponse.js create mode 100755 RVO35/flow_old/httproute.js create mode 100755 RVO35/flow_old/infosender.js create mode 100755 RVO35/flow_old/modbus_reader.js create mode 100755 RVO35/flow_old/monitorconsumption.js create mode 100755 RVO35/flow_old/monitordisk.js create mode 100755 RVO35/flow_old/monitormemory.js create mode 100755 RVO35/flow_old/nodesdb_changecheck.js create mode 100755 RVO35/flow_old/notifikacie.csv create mode 100755 RVO35/flow_old/show_dbdata.js create mode 100755 RVO35/flow_old/slack_filter.js create mode 100755 RVO35/flow_old/thermometer.js create mode 100755 RVO35/flow_old/trigger.js create mode 100755 RVO35/flow_old/variables.txt create mode 100755 RVO35/flow_old/virtualwirein.js create mode 100755 RVO35/flow_old/virtualwireout.js create mode 100755 RVO35/flow_old/wsmqttpublish.js create mode 100755 RVO35/monitor.txt create mode 100755 RVO35/package-lock.json create mode 100755 RVO35/package.json create mode 100755 RVO35/release.js create mode 100755 RVO35/release.js.json create mode 100755 RVO35/report_data.log diff --git a/RVO35/addSwitch.py b/RVO35/addSwitch.py new file mode 100755 index 0000000..c35e96b --- /dev/null +++ b/RVO35/addSwitch.py @@ -0,0 +1,36 @@ +import os + +def process_set_file(): + """ + Checks if /root/flowserver exists, reads set.txt, and modifies the second line. + """ + default_folder = "/root/flowserver" if os.path.exists("/root/flowserver") else "/home/unipi/flowserver" + flag = 1 if default_folder == "/root/flowserver" else 0 + + try: + with open("/home/unipi/flowserver/databases/settings.table", "r") as f: + lines = f.readlines() + + if len(lines) >= 2: + lines[0] = lines[0].rstrip('\n') + "|main_switch:boolean\n" + second_line = lines[1].strip() # remove trailing newline + last_pipe_index = second_line.rfind("|") + + if last_pipe_index != -1: + modified_line = second_line[:last_pipe_index + 1] + str(flag) + "|" + second_line[last_pipe_index + 1:] + lines[1] = modified_line + else: + print("Warning: No '|' character found in the second line of set.txt") + + with open("/home/unipi/flowserver/databases/settings.table", "w") as f: + f.writelines(lines) + else: + print("Warning: settings.table has less than two lines.") + + except FileNotFoundError: + print("Error: settings.table not found.") + except Exception as e: + print(e) + +# if __name__ == "__main__": +process_set_file() diff --git a/RVO35/cloud_topic.py b/RVO35/cloud_topic.py new file mode 100755 index 0000000..77c31f1 --- /dev/null +++ b/RVO35/cloud_topic.py @@ -0,0 +1,76 @@ +# import os +# +# def modify_file(file_path): +# """ +# Modifies the given file by: +# 1. Appending "|cloud_topic" to the first line. +# 2. Inserting the text from the third "." to the first "|" on the second line after the last "|" character. +# +# Args: +# file_path (str): The path to the file to be modified. +# """ +# +# with open(file_path, 'r+') as f: +# lines = f.readlines() +# +# # Modify the first line +# lines[0] += "|cloud_topic:string" +# +# # Modify the second line +# second_line = lines[1].strip() # Remove leading/trailing whitespace +# first_pipe_index = second_line.find('|') +# third_dot_index = second_line.find('.', second_line.find('.', second_line.find('.') + 1) + 1) +# text_to_insert = second_line[third_dot_index:first_pipe_index] +# +# last_pipe_index = second_line.rfind('|') +# lines[1] = second_line[:last_pipe_index + 1] + text_to_insert + "|" + second_line[last_pipe_index + 1:] +# +# print(first_pipe_index, third_dot_index, text_to_insert, last_pipe_index) +# # Write the modified lines back to the file +# # f.seek(0) +# # f.writelines(lines) +# # f.truncate() +# +# # Example usage: +# file_path = "settings.table" # Replace with the actual file path +# modify_file(file_path) +# + + +def modify_file(file_path): + """ + Modifies the given file by: + 1. Appending "|cloud_topic" to the first line. + 2. Inserting the text between the third "." and the second "|" on the second line after the last "|" character. + + Args: + file_path (str): The path to the file to be modified. + """ + + with open(file_path, 'r+') as f: + lines = f.readlines() + + first_line = lines[0].strip() + first_line += "|cloud_topic:string\n" + # Modify the first line + lines[0] = first_line + + # Modify the second line + second_line = lines[1].strip() # Remove leading/trailing whitespace + first_pipe_index = second_line.find('|') + second_pipe_index = second_line.find('|', first_pipe_index + 1) + third_dot_index = second_line.find('.', second_line.find('.', second_line.find('.') + 1) + 1) + text_to_insert = "u" + second_line[third_dot_index+1:second_pipe_index] + + last_pipe_index = second_line.rfind('|') + lines[1] = second_line[:last_pipe_index + 1] + text_to_insert + "|" + second_line[last_pipe_index + 1:] + + print(first_pipe_index, third_dot_index, text_to_insert, last_pipe_index) + # Write the modified lines back to the file + f.seek(0) + f.writelines(lines) + f.truncate() + +# Example usage: +file_path = "/home/unipi/flowserver/databases/settings.table" # Replace with the actual file path +modify_file(file_path) diff --git a/RVO35/config b/RVO35/config new file mode 100755 index 0000000..cd0a8a9 --- /dev/null +++ b/RVO35/config @@ -0,0 +1,12 @@ +name : Total.js Flow +default_timezone : Europe/Bratislava + +// Packages settings +package#flow (Object) : { url: '/' } + + +table.relays : line:number|tbname:string|contactor:number|profile:string +table.nodes : node:number|pole_number:string|node_type:string|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|project_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|cloud_topic:string|has_main_switch:boolean|daily_report:boolean|send_changed_node_numbers:boolean +table.pins : pin:string|type:string|line:number +table.notifications : key:string|weight:string|sk:string|en:string diff --git a/RVO35/createNode.py b/RVO35/createNode.py new file mode 100755 index 0000000..21406cc --- /dev/null +++ b/RVO35/createNode.py @@ -0,0 +1,43 @@ +print("zaciname") +import re, json + +search_str = '|' +final = [] +counter = 1 +with open("/home/unipi/flowserver/databases/nodes.table", 'r') as file: +# with open("/home/rasta5man/dev/oms/flowserver/databases/nodes.table", 'r') as file: + # Read each line in the file + for line in file: + # Print each line + line = line.strip() + print(line) + if counter != 1: + i = [m.start() for m in re.finditer(re.escape(search_str), line)] + node = line[ i[0] + 1 : i[1] ] + tbname = line[ i[1] + 1 : i[2] ] + final.append({node:tbname}) + counter += 1 +print(json.dumps(final)) +f = open("/home/unipi/flowserver/databases/nodes_original/nodes_original.table", "w") +f.write(json.dumps(final)) +f.close() + + +# +# # ``d`` has to be replaced with a different character +# old_character = "'" +# +# # ``t`` will replace ``d` +# new_character = '"' +# resultant_string = 0; +# with open("/home/unipi/flowserver/databases/nodes_original/nodes_original.table", 'r') as file: +# for line in file: +# resultant_string = re.sub("'", '"', line) +# +# resultant_string = re.sub(" ", "", resultant_string) +# print(resultant_string) +# +# f = open("/home/unipi/flowserver/databases/nodes_original/nodes_original.table", "w") +# f.write(str(resultant_string)) +# f.close() +# diff --git a/RVO35/databases/accelerometer_db.js b/RVO35/databases/accelerometer_db.js new file mode 100755 index 0000000..fdfc7fd --- /dev/null +++ b/RVO35/databases/accelerometer_db.js @@ -0,0 +1,3055 @@ +let naklony = { + "3993": { "label": "1/3A", "naklon": 0 }, + "3989": { "label": "1/3B", "naklon": 15 }, + "3976": { "label": "1/1", "naklon": 0 }, + "4181": { "label": "1/2", "naklon": 0 }, + "4376": { "label": "1/4", "naklon": 15 }, + "3868": { "label": "1/5", "naklon": 15 }, + "3728": { "label": "1/6", "naklon": 15 }, + "3730": { "label": "1/7", "naklon": 0 }, + "4374": { "label": "1/8", "naklon": 0 }, + "3718": { "label": "1/9", "naklon": 15 }, + "4375": { "label": "1/10", "naklon": 15 }, + "4172": { "label": "1/11", "naklon": 15 }, + "4176": { "label": "1/12", "naklon": 15 }, + "3800": { "label": "2/1", "naklon": 5 }, + "3823": { "label": "2/2", "naklon": 5 }, + "3905": { "label": "2/3", "naklon": 5 }, + "3803": { "label": "2/4", "naklon": 5 }, + "3817": { "label": "2/5", "naklon": 5 }, + "3818": { "label": "2/6", "naklon": 5 }, + "3811": { "label": "2/7", "naklon": 5 }, + "3915": { "label": "2/8", "naklon": 5 }, + "3843": { "label": "2/9", "naklon": 10 }, + "3827": { "label": "2/10", "naklon": 10 }, + "4220": { "label": "2/11", "naklon": 10 }, + "3826": { "label": "2/12", "naklon": 10 }, + "3834": { "label": "2/13", "naklon": 10 }, + "3838": { "label": "2/14", "naklon": 10 }, + "2823": { "label": "2/15", "naklon": 10 }, + "3750": { "label": "2/16", "naklon": 10 }, + "3378": { "label": "2/17", "naklon": 0 }, + "3376": { "label": "2/18", "naklon": 0 }, + "3379": { "label": "2/19", "naklon": 0 }, + "3285": { "label": "2/20", "naklon": 0 }, + "3382": { "label": "2/21", "naklon": 0 }, + "3383": { "label": "2/22", "naklon": 0 }, + "3375": { "label": "2/24", "naklon": 0 }, + "3381": { "label": "2/25", "naklon": 0 }, + "3380": { "label": "2/26", "naklon": 0 }, + "3828": { "label": "2/27", "naklon": 10 }, + "3377": { "label": "2/28", "naklon": 0 }, + "3591": { "label": "7/1", "naklon": 0 }, + "3587": { "label": "7/2", "naklon": 0 }, + "3468": { "label": "7/3", "naklon": 0 }, + "3466": { "label": "7/4", "naklon": 0 }, + "3474": { "label": "7/5", "naklon": 0 }, + "3481": { "label": "7/6", "naklon": 0 }, + "3589": { "label": "7/7", "naklon": 0 }, + "3472": { "label": "7/8", "naklon": 0 }, + "3473": { "label": "7/9", "naklon": 0 }, + "3584": { "label": "7/10", "naklon": 0 }, + "3571": { "label": "7/11", "naklon": 0 }, + "3476": { "label": "7/12", "naklon": 0 }, + "3590": { "label": "7/13", "naklon": 0 }, + "3478": { "label": "7/14", "naklon": 0 }, + "3471": { "label": "7/15", "naklon": 0 }, + "3467": { "label": "7/16", "naklon": 0 }, + "3479": { "label": "7/17", "naklon": 0 }, + "3480": { "label": "7/18", "naklon": 0 }, + "3477": { "label": "7/19", "naklon": 0 }, + "3362": { "label": "12/1", "naklon": 0 }, + "3355": { "label": "12/2", "naklon": 0 }, + "3356": { "label": "12/3", "naklon": 0 }, + "3349": { "label": "12/4", "naklon": 0 }, + "3357": { "label": "12/5", "naklon": 0 }, + "3350": { "label": "12/6", "naklon": 0 }, + "3353": { "label": "12/7", "naklon": 0 }, + "3539": { "label": "12/8", "naklon": 0 }, + "3050": { "label": "12/9", "naklon": 0 }, + "3361": { "label": "12/10", "naklon": 0 }, + "3360": { "label": "12/11", "naklon": 0 }, + "3358": { "label": "12/12", "naklon": 0 }, + "3541": { "label": "12/13", "naklon": 0 }, + "3551": { "label": "12/14", "naklon": 0 }, + "3514": { "label": "12/15", "naklon": 0 }, + "3547": { "label": "12/16", "naklon": 0 }, + "3562": { "label": "12/17", "naklon": 0 }, + "3525": { "label": "12/18", "naklon": 0 }, + "3558": { "label": "12/19", "naklon": 0 }, + "3511": { "label": "12/20", "naklon": 0 }, + "3058": { "label": "12/21", "naklon": 0 }, + "3062": { "label": "12/22", "naklon": 0 }, + "3070": { "label": "12/23", "naklon": 0 }, + "3447": { "label": "12/24", "naklon": 0 }, + "3056": { "label": "12/25", "naklon": 0 }, + "3057": { "label": "12/26", "naklon": 0 }, + "3071": { "label": "12/27", "naklon": 0 }, + "3061": { "label": "12/28", "naklon": 0 }, + "3069": { "label": "12/29", "naklon": 0 }, + "3077": { "label": "12/30", "naklon": 0 }, + "3080": { "label": "12/31", "naklon": 0 }, + "3081": { "label": "12/32", "naklon": 0 }, + "3078": { "label": "12/33", "naklon": 0 }, + "4037": { "label": "12/34", "naklon": 0 }, + "3067": { "label": "12/35", "naklon": 0 }, + "3051": { "label": "12/36", "naklon": 0 }, + "2924": { "label": "12/37", "naklon": 0 }, + "3060": { "label": "12/38", "naklon": 0 }, + "3073": { "label": "12/39", "naklon": 0 }, + "3469": { "label": "12/40", "naklon": 0 }, + "2923": { "label": "12/41", "naklon": 0 }, + "2925": { "label": "12/42", "naklon": 0 }, + "3359": { "label": "12/43", "naklon": 0 }, + "3055": { "label": "12/44", "naklon": 0 }, + "2922": { "label": "12/45", "naklon": 0 }, + "3084": { "label": "12/46", "naklon": 0 }, + "3064": { "label": "12/47", "naklon": 0 }, + "3066": { "label": "12/48", "naklon": 0 }, + "3072": { "label": "12/49", "naklon": 0 }, + "3415": { "label": "13/13A", "naklon": 0 }, + "3409": { "label": "13/13B", "naklon": 0 }, + "3399": { "label": "13/13C", "naklon": 0 }, + "3410": { "label": "13/29A", "naklon": 0 }, + "3407": { "label": "13/29B", "naklon": 0 }, + "3405": { "label": "13/34A", "naklon": 0 }, + "3404": { "label": "13/34B", "naklon": 0 }, + "3392": { "label": "13/45A", "naklon": 0 }, + "3386": { "label": "13/45B", "naklon": 0 }, + "3303": { "label": "13/60A", "naklon": 3 }, + "3302": { "label": "13/60B", "naklon": 3 }, + "3319": { "label": "13/70A", "naklon": 6 }, + "3317": { "label": "13/70B", "naklon": 6 }, + "3326": { "label": "13/70C", "naklon": 6 }, + "3351": { "label": "13/73A", "naklon": 6 }, + "3313": { "label": "13/73B", "naklon": 6 }, + "3316": { "label": "13/83A", "naklon": 0 }, + "3320": { "label": "13/83B", "naklon": 0 }, + "3336": { "label": "13/95A", "naklon": 0 }, + "3323": { "label": "13/95B", "naklon": 0 }, + "3339": { "label": "13/98A", "naklon": 0 }, + "3333": { "label": "13/98B", "naklon": 0 }, + "3425": { "label": "13/1", "naklon": 0 }, + "3419": { "label": "13/2", "naklon": 0 }, + "3416": { "label": "13/3", "naklon": 0 }, + "3332": { "label": "13/4", "naklon": 0 }, + "3422": { "label": "13/5", "naklon": 0 }, + "3417": { "label": "13/6", "naklon": 0 }, + "3418": { "label": "13/7", "naklon": 0 }, + "3424": { "label": "13/8", "naklon": 0 }, + "3334": { "label": "13/9", "naklon": 0 }, + "4363": { "label": "13/10", "naklon": 0 }, + "3423": { "label": "13/11", "naklon": 0 }, + "3406": { "label": "13/12", "naklon": 0 }, + "3411": { "label": "13/14", "naklon": 0 }, + "3412": { "label": "13/15", "naklon": 0 }, + "3413": { "label": "13/16", "naklon": 0 }, + "3414": { "label": "13/17", "naklon": 0 }, + "3391": { "label": "13/18", "naklon": 0 }, + "3370": { "label": "13/19", "naklon": 0 }, + "3369": { "label": "13/20", "naklon": 0 }, + "3408": { "label": "13/21", "naklon": 0 }, + "3393": { "label": "13/22", "naklon": 0 }, + "3128": { "label": "13/23", "naklon": 0 }, + "3197": { "label": "13/24", "naklon": 0 }, + "4364": { "label": "13/25", "naklon": 0 }, + "3155": { "label": "13/26", "naklon": 0 }, + "3196": { "label": "13/27", "naklon": 0 }, + "3144": { "label": "13/28", "naklon": 0 }, + "3150": { "label": "13/30", "naklon": 0 }, + "3390": { "label": "13/31", "naklon": 0 }, + "3401": { "label": "13/32", "naklon": 0 }, + "3275": { "label": "13/33", "naklon": 0 }, + "3371": { "label": "13/35", "naklon": 0 }, + "3389": { "label": "13/36", "naklon": 0 }, + "3388": { "label": "13/37", "naklon": 0 }, + "3365": { "label": "13/38", "naklon": 0 }, + "3363": { "label": "13/39", "naklon": 0 }, + "3397": { "label": "13/40", "naklon": 0 }, + "3567": { "label": "13/40/1", "naklon": 0 }, + "3387": { "label": "13/41", "naklon": 0 }, + "3403": { "label": "13/42", "naklon": 0 }, + "3147": { "label": "13/43", "naklon": 0 }, + "3141": { "label": "13/44", "naklon": 0 }, + "3364": { "label": "13/46", "naklon": 0 }, + "3367": { "label": "13/47", "naklon": 0 }, + "3368": { "label": "13/48", "naklon": 0 }, + "3402": { "label": "13/49", "naklon": 0 }, + "3366": { "label": "13/50", "naklon": 0 }, + "3395": { "label": "13/51", "naklon": 0 }, + "3372": { "label": "13/52", "naklon": 0 }, + "3394": { "label": "13/53", "naklon": 0 }, + "3308": { "label": "13/54", "naklon": 0 }, + "3847": { "label": "13/54/1", "naklon": 0 }, + "3312": { "label": "13/55", "naklon": 3 }, + "3309": { "label": "13/56", "naklon": 3 }, + "3311": { "label": "13/57", "naklon": 3 }, + "3310": { "label": "13/58", "naklon": 3 }, + "4365": { "label": "13/59", "naklon": 3 }, + "4093": { "label": "13/60/1", "naklon": 3 }, + "3304": { "label": "13/61", "naklon": 3 }, + "3307": { "label": "13/62", "naklon": 3 }, + "3271": { "label": "13/63", "naklon": 3 }, + "3301": { "label": "13/64", "naklon": 3 }, + "4366": { "label": "13/65", "naklon": 3 }, + "3300": { "label": "13/66", "naklon": 3 }, + "3185": { "label": "13/67", "naklon": 0 }, + "3184": { "label": "13/68", "naklon": 0 }, + "3188": { "label": "13/69", "naklon": 0 }, + "3343": { "label": "13/71", "naklon": 6 }, + "3819": { "label": "13/71/1", "naklon": 6 }, + "3880": { "label": "13/71/2", "naklon": 6 }, + "3348": { "label": "13/72", "naklon": 6 }, + "3344": { "label": "13/74", "naklon": 6 }, + "3346": { "label": "13/75", "naklon": 6 }, + "3597": { "label": "13/75/1", "naklon": 6 }, + "3345": { "label": "13/76", "naklon": 6 }, + "3322": { "label": "13/77", "naklon": 0 }, + "3325": { "label": "13/78", "naklon": 0 }, + "4310": { "label": "13/78/1", "naklon": 0 }, + "3315": { "label": "13/79", "naklon": 0 }, + "3328": { "label": "13/80", "naklon": 0 }, + "3321": { "label": "13/81", "naklon": 0 }, + "3324": { "label": "13/82", "naklon": 0 }, + "3140": { "label": "13/84", "naklon": 0 }, + "3153": { "label": "13/85", "naklon": 0 }, + "3145": { "label": "13/86", "naklon": 0 }, + "3134": { "label": "13/87", "naklon": 0 }, + "3151": { "label": "13/88", "naklon": 0 }, + "3143": { "label": "13/89", "naklon": 0 }, + "3318": { "label": "13/90", "naklon": 0 }, + "3347": { "label": "13/91", "naklon": 0 }, + "3314": { "label": "13/94", "naklon": 0 }, + "3331": { "label": "13/96", "naklon": 0 }, + "3327": { "label": "13/97", "naklon": 0 }, + "3329": { "label": "13/99", "naklon": 0 }, + "3337": { "label": "13/100", "naklon": 0 }, + "3330": { "label": "13/101", "naklon": 0 }, + "3335": { "label": "13/102", "naklon": 0 }, + "3420": { "label": "13/103", "naklon": 0 }, + "3421": { "label": "13/104", "naklon": 0 }, + "4361": { "label": "13/105", "naklon": 0 }, + "4362": { "label": "13/106", "naklon": 0 }, + "3526": { "label": "13/107", "naklon": 0 }, + "4424": { "label": "13/108", "naklon": null }, + "3561": { "label": "13/109", "naklon": null }, + "3527": { "label": "13/110", "naklon": null }, + "3521": { "label": "13/111", "naklon": null }, + "3552": { "label": "13/112", "naklon": null }, + "3544": { "label": "13/113", "naklon": null }, + "3534": { "label": "13/114", "naklon": null }, + "3516": { "label": "13/115", "naklon": null }, + "3513": { "label": "13/116", "naklon": null }, + "3565": { "label": "13/117", "naklon": null }, + "3866": { "label": "13/118", "naklon": null }, + "3136": { "label": "14/1", "naklon": 0 }, + "3137": { "label": "14/2", "naklon": 0 }, + "3135": { "label": "14/3", "naklon": 0 }, + "3149": { "label": "14/4", "naklon": 0 }, + "3142": { "label": "14/5", "naklon": 0 }, + "3342": { "label": "14/6", "naklon": 0 }, + "3340": { "label": "14/7", "naklon": 0 }, + "3152": { "label": "14/8", "naklon": 0 }, + "3886": { "label": "14/9", "naklon": 0 }, + "3341": { "label": "14/10", "naklon": null }, + "3352": { "label": "14/11", "naklon": null }, + "3396": { "label": "15/1", "naklon": 5 }, + "2784": { "label": "15/2", "naklon": 5 }, + "2788": { "label": "15/3", "naklon": 5 }, + "2801": { "label": "15/4", "naklon": 5 }, + "2815": { "label": "15/5", "naklon": 5 }, + "2829": { "label": "15/6", "naklon": 5 }, + "2796": { "label": "15/7", "naklon": 5 }, + "2803": { "label": "15/8", "naklon": 5 }, + "4304": { "label": "15/8/1", "naklon": 5 }, + "4311": { "label": "15/8/2", "naklon": 5 }, + "2821": { "label": "15/9", "naklon": 5 }, + "3400": { "label": "15/10", "naklon": 5 }, + "2799": { "label": "15/11", "naklon": 5 }, + "2804": { "label": "15/12", "naklon": 5 }, + "4303": { "label": "15/12/1", "naklon": 5 }, + "4309": { "label": "15/12/2", "naklon": 5 }, + "2806": { "label": "15/13", "naklon": 5 }, + "2787": { "label": "15/14", "naklon": 5 }, + "2809": { "label": "15/15", "naklon": 5 }, + "2814": { "label": "15/16", "naklon": 0 }, + "3934": { "label": "15/17", "naklon": 0 }, + "3192": { "label": "15/18", "naklon": 0 }, + "2812": { "label": "15/19", "naklon": 0 }, + "4070": { "label": "15/20", "naklon": 0 }, + "2826": { "label": "15/21", "naklon": 0 }, + "2808": { "label": "15/22", "naklon": 3 }, + "2795": { "label": "15/23", "naklon": 3 }, + "2807": { "label": "15/24", "naklon": 3 }, + "2831": { "label": "15/25", "naklon": 0 }, + "2862": { "label": "15/26", "naklon": null }, + "2861": { "label": "15/27", "naklon": 0 }, + "2866": { "label": "15/28", "naklon": 0 }, + "3546": { "label": "15/28/1", "naklon": 0 }, + "4146": { "label": "15/29", "naklon": 0 }, + "3001": { "label": "15/29/1", "naklon": 0 }, + "2835": { "label": "15/30", "naklon": 0 }, + "2874": { "label": "15/31", "naklon": 0 }, + "2852": { "label": "15/32", "naklon": 0 }, + "2851": { "label": "15/33", "naklon": 0 }, + "3560": { "label": "15/33/1", "naklon": 0 }, + "2858": { "label": "15/34", "naklon": 0 }, + "4306": { "label": "15/34/1", "naklon": 0 }, + "2856": { "label": "15/35", "naklon": 0 }, + "2847": { "label": "15/36", "naklon": 0 }, + "3556": { "label": "15/36/1", "naklon": 0 }, + "3950": { "label": "15/37", "naklon": 0 }, + "2848": { "label": "15/38", "naklon": 0 }, + "2863": { "label": "15/39", "naklon": 0 }, + "4313": { "label": "15/39/1", "naklon": 0 }, + "2873": { "label": "15/40", "naklon": 0 }, + "2984": { "label": "15/40/1", "naklon": 0 }, + "2854": { "label": "15/41", "naklon": 0 }, + "2859": { "label": "15/42", "naklon": 0 }, + "2872": { "label": "15/43", "naklon": 0 }, + "2849": { "label": "15/44", "naklon": 0 }, + "2864": { "label": "15/45", "naklon": 0 }, + "3553": { "label": "15/46", "naklon": null }, + "3021": { "label": "15/47", "naklon": null }, + "3008": { "label": "15/47/1", "naklon": null }, + "3017": { "label": "15/48", "naklon": null }, + "3014": { "label": "15/49", "naklon": null }, + "2981": { "label": "15/50", "naklon": null }, + "3020": { "label": "15/51", "naklon": null }, + "3027": { "label": "15/52", "naklon": null }, + "3006": { "label": "15/53", "naklon": null }, + "3012": { "label": "15/54", "naklon": null }, + "2738": { "label": "15/55", "naklon": 0 }, + "2725": { "label": "15/56", "naklon": 0 }, + "3016": { "label": "15/57", "naklon": null }, + "3005": { "label": "15/58", "naklon": null }, + "3009": { "label": "15/58/1", "naklon": null }, + "3010": { "label": "15/59", "naklon": 0 }, + "3538": { "label": "15/59/1", "naklon": 0 }, + "4145": { "label": "15/59/2", "naklon": 0 }, + "2713": { "label": "15/60", "naklon": 0 }, + "2789": { "label": "15/61", "naklon": 0 }, + "2736": { "label": "15/62", "naklon": 0 }, + "2739": { "label": "15/63", "naklon": 0 }, + "4346": { "label": "15/64", "naklon": 0 }, + "2731": { "label": "15/65", "naklon": 0 }, + "2818": { "label": "15/66", "naklon": 0 }, + "3557": { "label": "15/66/1", "naklon": 0 }, + "2822": { "label": "15/67", "naklon": 0 }, + "2833": { "label": "15/68", "naklon": 0 }, + "2834": { "label": "15/69", "naklon": 0 }, + "3097": { "label": "15/70", "naklon": 0 }, + "2824": { "label": "15/71", "naklon": 0 }, + "2828": { "label": "15/72", "naklon": 0 }, + "2600": { "label": "15/73", "naklon": 0 }, + "4314": { "label": "15/73/1", "naklon": 0 }, + "2832": { "label": "15/74", "naklon": 0 }, + "4360": { "label": "15/75", "naklon": 0 }, + "2846": { "label": "15/76", "naklon": 0 }, + "2584": { "label": "15/77", "naklon": 0 }, + "2843": { "label": "15/78", "naklon": 0 }, + "4308": { "label": "15/78/1", "naklon": 0 }, + "4144": { "label": "15/79", "naklon": null }, + "2844": { "label": "15/80", "naklon": 0 }, + "2842": { "label": "15/81", "naklon": 0 }, + "2838": { "label": "15/82", "naklon": 0 }, + "2837": { "label": "15/83", "naklon": null }, + "3555": { "label": "15/83/1", "naklon": null }, + "2839": { "label": "15/84", "naklon": 0 }, + "2830": { "label": "15/85", "naklon": 0 }, + "4066": { "label": "15/86", "naklon": 0 }, + "2836": { "label": "15/87", "naklon": 0 }, + "2911": { "label": "15/88", "naklon": 0 }, + "2825": { "label": "15/89", "naklon": 0 }, + "2811": { "label": "15/90", "naklon": 0 }, + "3740": { "label": "15/94", "naklon": 15 }, + "2734": { "label": "15/95", "naklon": 15 }, + "3105": { "label": "15/96", "naklon": 15 }, + "2732": { "label": "15/97", "naklon": 15 }, + "2727": { "label": "15/98", "naklon": 15 }, + "2735": { "label": "15/99", "naklon": 15 }, + "3926": { "label": "15/100", "naklon": 15 }, + "2918": { "label": "15/101", "naklon": 0 }, + "2705": { "label": "15/102", "naklon": 10 }, + "2708": { "label": "15/103", "naklon": 10 }, + "2721": { "label": "15/104", "naklon": 10 }, + "2719": { "label": "15/105", "naklon": 10 }, + "2919": { "label": "15/106", "naklon": 10 }, + "3101": { "label": "15/107", "naklon": 10 }, + "2853": { "label": "15/108", "naklon": 10 }, + "2715": { "label": "15/109", "naklon": 10 }, + "2712": { "label": "15/110", "naklon": 0 }, + "2711": { "label": "15/111", "naklon": 0 }, + "2709": { "label": "15/112", "naklon": 0 }, + "2710": { "label": "15/113", "naklon": 0 }, + "2907": { "label": "15/114", "naklon": 0 }, + "2906": { "label": "15/115", "naklon": 0 }, + "2908": { "label": "15/116", "naklon": 0 }, + "2901": { "label": "15/117", "naklon": 0 }, + "2913": { "label": "15/118", "naklon": 0 }, + "3656": { "label": "15/119", "naklon": 0 }, + "2781": { "label": "15/120", "naklon": 0 }, + "2802": { "label": "15/121", "naklon": 0 }, + "2791": { "label": "15/122", "naklon": 0 }, + "2783": { "label": "15/123", "naklon": 0 }, + "2794": { "label": "15/124", "naklon": 0 }, + "3139": { "label": "15/125", "naklon": 0 }, + "3229": { "label": "15/126", "naklon": 5 }, + "3239": { "label": "15/127", "naklon": 5 }, + "3230": { "label": "15/128", "naklon": 5 }, + "4016": { "label": "15/129", "naklon": null }, + "3608": { "label": "16/16A", "naklon": 0 }, + "4151": { "label": "16/16B", "naklon": 0 }, + "3710": { "label": "16/1", "naklon": 0 }, + "3726": { "label": "16/2", "naklon": 0 }, + "3743": { "label": "16/3", "naklon": 0 }, + "3724": { "label": "16/4", "naklon": 0 }, + "3712": { "label": "16/5", "naklon": 0 }, + "3739": { "label": "16/6", "naklon": 0 }, + "3742": { "label": "16/7", "naklon": 0 }, + "3731": { "label": "16/8", "naklon": 0 }, + "3727": { "label": "16/9", "naklon": 0 }, + "3729": { "label": "16/10", "naklon": 0 }, + "3736": { "label": "16/11", "naklon": 0 }, + "3713": { "label": "16/12", "naklon": 0 }, + "3715": { "label": "16/13", "naklon": 0 }, + "3733": { "label": "16/14", "naklon": 0 }, + "3732": { "label": "16/15", "naklon": 0 }, + "3634": { "label": "16/17", "naklon": 0 }, + "3610": { "label": "16/18", "naklon": 0 }, + "3626": { "label": "16/19", "naklon": 0 }, + "3618": { "label": "16/20", "naklon": 0 }, + "3619": { "label": "16/21", "naklon": 0 }, + "3628": { "label": "16/22", "naklon": 0 }, + "3615": { "label": "16/23", "naklon": 0 }, + "3609": { "label": "16/24", "naklon": 0 }, + "3606": { "label": "16/25", "naklon": 0 }, + "3624": { "label": "16/26", "naklon": 0 }, + "3627": { "label": "16/27", "naklon": 0 }, + "3607": { "label": "16/28", "naklon": 0 }, + "4370": { "label": "16/29", "naklon": 0 }, + "3692": { "label": "16/30", "naklon": 0 }, + "3614": { "label": "16/31", "naklon": 0 }, + "3623": { "label": "16/32", "naklon": 0 }, + "4373": { "label": "16/33", "naklon": 0 }, + "3620": { "label": "16/34", "naklon": 0 }, + "3685": { "label": "16/35", "naklon": 0 }, + "3616": { "label": "16/36", "naklon": 0 }, + "3686": { "label": "16/37", "naklon": 0 }, + "3688": { "label": "16/38", "naklon": 0 }, + "3684": { "label": "16/39", "naklon": 0 }, + "3825": { "label": "16/40", "naklon": 0 }, + "3865": { "label": "16/41", "naklon": 0 }, + "3824": { "label": "16/42", "naklon": 0 }, + "3871": { "label": "16/43", "naklon": 0 }, + "3801": { "label": "16/44", "naklon": 0 }, + "3862": { "label": "16/45", "naklon": 0 }, + "3876": { "label": "16/46", "naklon": 0 }, + "3861": { "label": "16/47", "naklon": 0 }, + "4215": { "label": "16/48", "naklon": 0 }, + "3605": { "label": "16/49", "naklon": 10 }, + "3603": { "label": "16/50", "naklon": 10 }, + "3592": { "label": "16/51", "naklon": 10 }, + "3598": { "label": "16/52", "naklon": 10 }, + "3594": { "label": "16/53", "naklon": 10 }, + "3593": { "label": "16/54", "naklon": 10 }, + "3630": { "label": "16/55", "naklon": 10 }, + "3763": { "label": "16/56", "naklon": 10 }, + "3746": { "label": "16/57", "naklon": 10 }, + "3699": { "label": "16/58", "naklon": 0 }, + "3698": { "label": "16/59", "naklon": 0 }, + "3709": { "label": "16/60", "naklon": null }, + "3708": { "label": "16/61", "naklon": 0 }, + "3703": { "label": "16/62", "naklon": null }, + "3700": { "label": "16/63", "naklon": 0 }, + "3701": { "label": "16/64", "naklon": null }, + "3704": { "label": "16/65", "naklon": 0 }, + "3707": { "label": "16/66", "naklon": null }, + "3810": { "label": "16/67", "naklon": 0 }, + "4208": { "label": "16/68", "naklon": null }, + "3867": { "label": "16/69", "naklon": 0 }, + "4372": { "label": "16/70", "naklon": null }, + "3881": { "label": "16/71", "naklon": 0 }, + "4204": { "label": "16/72", "naklon": null }, + "3869": { "label": "16/73", "naklon": 0 }, + "4202": { "label": "16/74", "naklon": null }, + "3830": { "label": "16/75", "naklon": 0 }, + "3870": { "label": "16/76", "naklon": null }, + "3964": { "label": "16/77", "naklon": 0 }, + "3849": { "label": "16/78", "naklon": 0 }, + "3694": { "label": "16/79", "naklon": null }, + "3717": { "label": "16/80", "naklon": 0 }, + "3877": { "label": "16/81", "naklon": null }, + "3755": { "label": "16/82", "naklon": 0 }, + "3725": { "label": "16/83", "naklon": null }, + "3716": { "label": "16/84", "naklon": 0 }, + "3696": { "label": "16/85", "naklon": null }, + "3702": { "label": "16/86", "naklon": 0 }, + "3706": { "label": "16/87", "naklon": null }, + "3850": { "label": "16/88", "naklon": 0 }, + "3848": { "label": "16/89", "naklon": null }, + "3737": { "label": "16/90", "naklon": null }, + "3705": { "label": "16/91", "naklon": 0 }, + "3723": { "label": "16/92", "naklon": null }, + "3842": { "label": "16/93", "naklon": 0 }, + "3735": { "label": "16/94", "naklon": null }, + "3719": { "label": "16/95", "naklon": 0 }, + "3697": { "label": "16/96", "naklon": 0 }, + "3711": { "label": "16/97", "naklon": 0 }, + "4107": { "label": "16/98", "naklon": null }, + "4112": { "label": "16/99", "naklon": 5 }, + "4106": { "label": "16/100", "naklon": 5 }, + "4111": { "label": "16/101", "naklon": 5 }, + "4091": { "label": "16/102", "naklon": null }, + "4104": { "label": "16/103", "naklon": 5 }, + "4094": { "label": "16/104", "naklon": null }, + "4089": { "label": "16/105", "naklon": 5 }, + "4095": { "label": "16/106", "naklon": null }, + "4102": { "label": "16/107", "naklon": 5 }, + "4105": { "label": "16/108", "naklon": null }, + "3859": { "label": "16/109", "naklon": null }, + "4090": { "label": "16/110", "naklon": 5 }, + "4110": { "label": "16/111", "naklon": null }, + "4097": { "label": "16/112", "naklon": 5 }, + "4099": { "label": "16/113", "naklon": null }, + "4096": { "label": "16/114", "naklon": null }, + "4101": { "label": "16/115", "naklon": 5 }, + "4109": { "label": "16/116", "naklon": null }, + "4092": { "label": "16/117", "naklon": 5 }, + "3631": { "label": "16/118", "naklon": null }, + "3632": { "label": "16/119", "naklon": 0 }, + "3641": { "label": "16/120", "naklon": null }, + "3638": { "label": "16/121", "naklon": 0 }, + "3637": { "label": "16/122", "naklon": null }, + "4142": { "label": "16/123", "naklon": null }, + "4147": { "label": "16/124", "naklon": 5 }, + "4139": { "label": "16/125", "naklon": 5 }, + "3172": { "label": "20/30A", "naklon": 2 }, + "3164": { "label": "20/30B", "naklon": 2 }, + "3247": { "label": "20/1", "naklon": 10 }, + "3296": { "label": "20/2", "naklon": 10 }, + "3246": { "label": "20/3", "naklon": 10 }, + "3270": { "label": "20/4", "naklon": 10 }, + "3294": { "label": "20/5", "naklon": 10 }, + "3298": { "label": "20/6", "naklon": 10 }, + "3297": { "label": "20/7", "naklon": 10 }, + "3293": { "label": "20/8", "naklon": 10 }, + "3299": { "label": "20/9", "naklon": 10 }, + "3295": { "label": "20/10", "naklon": 10 }, + "3244": { "label": "20/11", "naklon": 10 }, + "3249": { "label": "20/12", "naklon": 10 }, + "3268": { "label": "20/13", "naklon": 10 }, + "3245": { "label": "20/14", "naklon": 10 }, + "3278": { "label": "20/15", "naklon": 10 }, + "3280": { "label": "20/16", "naklon": 10 }, + "3292": { "label": "20/17", "naklon": 10 }, + "3287": { "label": "20/18", "naklon": 10 }, + "3282": { "label": "20/19", "naklon": 10 }, + "3273": { "label": "20/20", "naklon": 0 }, + "3157": { "label": "20/21", "naklon": 0 }, + "3283": { "label": "20/22", "naklon": 0 }, + "3159": { "label": "20/23", "naklon": 0 }, + "3289": { "label": "20/24", "naklon": 0 }, + "3163": { "label": "20/25", "naklon": 0 }, + "3126": { "label": "20/26", "naklon": 0 }, + "3171": { "label": "20/27", "naklon": 0 }, + "3162": { "label": "20/28", "naklon": 0 }, + "3279": { "label": "20/29", "naklon": 10 }, + "3173": { "label": "20/31", "naklon": 0 }, + "3127": { "label": "20/32", "naklon": 0 }, + "3131": { "label": "20/33", "naklon": 0 }, + "3129": { "label": "20/34", "naklon": 0 }, + "3276": { "label": "20/35", "naklon": 2 }, + "3290": { "label": "20/36", "naklon": 2 }, + "3132": { "label": "20/37", "naklon": 0 }, + "3138": { "label": "20/38", "naklon": 0 }, + "3272": { "label": "20/39", "naklon": 0 }, + "3291": { "label": "20/40", "naklon": 0 }, + "3277": { "label": "20/41", "naklon": 10 }, + "3286": { "label": "20/42", "naklon": 10 }, + "3281": { "label": "20/43", "naklon": 10 }, + "3288": { "label": "20/44", "naklon": 10 }, + "3284": { "label": "20/45", "naklon": 10 }, + "3167": { "label": "20/46", "naklon": 10 }, + "3872": { "label": "20/47", "naklon": 0 }, + "3124": { "label": "20/48", "naklon": 0 }, + "3133": { "label": "20/49", "naklon": 0 }, + "3158": { "label": "20/50", "naklon": 0 }, + "3169": { "label": "20/51", "naklon": 0 }, + "3146": { "label": "20/52", "naklon": 0 }, + "3160": { "label": "20/53", "naklon": 0 }, + "3248": { "label": "20/54", "naklon": 0 }, + "3156": { "label": "20/55", "naklon": 0 }, + "3161": { "label": "20/56", "naklon": 0 }, + "3170": { "label": "20/57", "naklon": 0 }, + "3168": { "label": "20/58", "naklon": 0 }, + "3125": { "label": "20/59", "naklon": 0 }, + "3166": { "label": "20/60", "naklon": 0 }, + "3130": { "label": "20/61", "naklon": 0 }, + "3563": { "label": "20/62", "naklon": 0 }, + "3550": { "label": "20/63", "naklon": null }, + "3269": { "label": "20/67", "naklon": 0 }, + "2921": { "label": "21/1", "naklon": 0 }, + "2707": { "label": "21/2", "naklon": 0 }, + "2723": { "label": "21/3", "naklon": 0 }, + "2716": { "label": "21/4", "naklon": 0 }, + "2717": { "label": "21/5", "naklon": 0 }, + "2720": { "label": "21/6", "naklon": 0 }, + "2722": { "label": "21/7", "naklon": 0 }, + "2718": { "label": "21/8", "naklon": 0 }, + "2724": { "label": "21/9", "naklon": 0 }, + "2742": { "label": "21/10", "naklon": 0 }, + "2743": { "label": "21/11", "naklon": 0 }, + "2733": { "label": "21/12", "naklon": 0 }, + "2903": { "label": "21/14", "naklon": 0 }, + "2917": { "label": "21/15", "naklon": 0 }, + "2897": { "label": "21/16", "naklon": 0 }, + "2914": { "label": "21/17", "naklon": 0 }, + "2898": { "label": "21/18", "naklon": 0 }, + "2773": { "label": "21/19", "naklon": 0 }, + "2895": { "label": "21/20", "naklon": 0 }, + "2896": { "label": "21/21", "naklon": 0 }, + "2771": { "label": "21/22", "naklon": 0 }, + "2772": { "label": "21/23", "naklon": 0 }, + "2793": { "label": "21/24", "naklon": 0 }, + "2902": { "label": "21/25", "naklon": 0 }, + "2910": { "label": "21/26", "naklon": 0 }, + "2909": { "label": "21/27", "naklon": 0 }, + "2920": { "label": "21/28", "naklon": 0 }, + "2916": { "label": "21/29", "naklon": 0 }, + "2904": { "label": "21/30", "naklon": 0 }, + "2915": { "label": "21/31", "naklon": 0 }, + "2905": { "label": "21/32", "naklon": 0 }, + "2900": { "label": "21/33", "naklon": 0 }, + "2899": { "label": "21/34", "naklon": 0 }, + "2741": { "label": "21/36", "naklon": 0 }, + "2714": { "label": "21/37", "naklon": 0 }, + "2701": { "label": "21/38", "naklon": 0 }, + "2703": { "label": "21/39", "naklon": 0 }, + "2704": { "label": "21/40", "naklon": 0 }, + "2702": { "label": "21/41", "naklon": 0 }, + "2706": { "label": "21/42", "naklon": 0 }, + "2776": { "label": "21/43", "naklon": 0 }, + "2770": { "label": "21/44", "naklon": 0 }, + "2786": { "label": "21/45", "naklon": 0 }, + "2779": { "label": "21/46", "naklon": 0 }, + "2782": { "label": "21/47", "naklon": 0 }, + "2785": { "label": "21/48", "naklon": 0 }, + "2769": { "label": "21/49", "naklon": 0 }, + "3354": { "label": "21/50", "naklon": 0 }, + "2778": { "label": "21/51", "naklon": 0 }, + "2775": { "label": "21/52", "naklon": 0 }, + "2780": { "label": "21/53", "naklon": 0 }, + "2790": { "label": "21/54", "naklon": 0 }, + "2792": { "label": "21/55", "naklon": 0 }, + "2774": { "label": "21/56", "naklon": 0 }, + "2630": { "label": "22/1", "naklon": 0 }, + "2631": { "label": "22/2", "naklon": 0 }, + "2632": { "label": "22/3", "naklon": 0 }, + "2633": { "label": "22/4", "naklon": 0 }, + "2634": { "label": "22/5", "naklon": 0 }, + "2636": { "label": "22/6", "naklon": 0 }, + "4367": { "label": "22/7", "naklon": 0 }, + "2637": { "label": "22/8", "naklon": 0 }, + "2638": { "label": "22/9", "naklon": 0 }, + "2639": { "label": "22/10", "naklon": 0 }, + "2640": { "label": "22/11", "naklon": 0 }, + "2641": { "label": "22/12", "naklon": 0 }, + "2642": { "label": "22/13", "naklon": 0 }, + "2643": { "label": "22/14", "naklon": 0 }, + "2644": { "label": "22/15", "naklon": 0 }, + "2645": { "label": "22/16", "naklon": 0 }, + "2646": { "label": "22/17", "naklon": 0 }, + "2647": { "label": "22/18", "naklon": 0 }, + "2648": { "label": "22/19", "naklon": 0 }, + "2649": { "label": "22/20", "naklon": 0 }, + "2650": { "label": "22/21", "naklon": 0 }, + "2651": { "label": "22/22", "naklon": 0 }, + "4103": { "label": "22/23", "naklon": 0 }, + "2653": { "label": "22/24", "naklon": 0 }, + "2654": { "label": "22/25", "naklon": 0 }, + "2655": { "label": "22/26", "naklon": 0 }, + "2656": { "label": "22/27", "naklon": 0 }, + "2657": { "label": "22/28", "naklon": 0 }, + "2658": { "label": "22/29", "naklon": 0 }, + "2659": { "label": "22/30", "naklon": 0 }, + "2660": { "label": "22/31", "naklon": 0 }, + "2661": { "label": "22/32", "naklon": 0 }, + "3015": { "label": "22/32/1", "naklon": 0 }, + "2662": { "label": "22/33", "naklon": 0 }, + "2663": { "label": "22/34", "naklon": 0 }, + "2664": { "label": "22/35", "naklon": 0 }, + "2665": { "label": "22/36", "naklon": 0 }, + "2666": { "label": "22/37", "naklon": 0 }, + "2667": { "label": "22/38", "naklon": 0 }, + "2668": { "label": "22/39", "naklon": 0 }, + "2669": { "label": "22/40", "naklon": null }, + "2670": { "label": "22/41", "naklon": null }, + "2671": { "label": "22/42", "naklon": null }, + "3087": { "label": "23/9A", "naklon": 10 }, + "3090": { "label": "23/9B", "naklon": 10 }, + "3075": { "label": "23/1", "naklon": 0 }, + "3089": { "label": "23/2", "naklon": 0 }, + "3088": { "label": "23/3", "naklon": 0 }, + "3228": { "label": "23/4", "naklon": 10 }, + "2751": { "label": "23/5", "naklon": 10 }, + "3243": { "label": "23/6", "naklon": 10 }, + "4349": { "label": "23/7", "naklon": 10 }, + "3102": { "label": "23/8", "naklon": 10 }, + "3099": { "label": "23/10", "naklon": 10 }, + "3103": { "label": "23/11", "naklon": 10 }, + "3093": { "label": "23/12", "naklon": 10 }, + "3098": { "label": "23/13", "naklon": 10 }, + "3092": { "label": "23/14", "naklon": 10 }, + "3233": { "label": "23/15", "naklon": 0 }, + "3095": { "label": "23/16", "naklon": 0 }, + "4074": { "label": "23/17", "naklon": 0 }, + "2729": { "label": "23/18", "naklon": 0 }, + "3234": { "label": "23/19", "naklon": 0 }, + "3094": { "label": "23/20", "naklon": 0 }, + "2817": { "label": "23/21", "naklon": 0 }, + "3226": { "label": "23/22", "naklon": 0 }, + "3225": { "label": "23/23", "naklon": 0 }, + "3237": { "label": "23/24", "naklon": 0 }, + "4250": { "label": "23/25", "naklon": 0 }, + "3059": { "label": "23/26", "naklon": 10 }, + "3238": { "label": "23/27", "naklon": 10 }, + "3242": { "label": "23/28", "naklon": 10 }, + "3236": { "label": "23/29", "naklon": 10 }, + "3112": { "label": "23/30", "naklon": 10 }, + "3224": { "label": "23/31", "naklon": 0 }, + "4298": { "label": "23/32", "naklon": 10 }, + "4150": { "label": "23/33", "naklon": 10 }, + "3091": { "label": "23/34", "naklon": 10 }, + "3771": { "label": "25/1", "naklon": 5 }, + "3777": { "label": "25/2", "naklon": 5 }, + "3749": { "label": "25/3", "naklon": 5 }, + "3769": { "label": "25/4", "naklon": 5 }, + "3765": { "label": "25/5", "naklon": 5 }, + "3785": { "label": "25/6", "naklon": 5 }, + "3761": { "label": "25/7", "naklon": 5 }, + "3758": { "label": "25/8", "naklon": 5 }, + "3766": { "label": "25/9", "naklon": 5 }, + "3779": { "label": "25/10", "naklon": 5 }, + "3899": { "label": "25/11", "naklon": 10 }, + "3922": { "label": "25/12", "naklon": 10 }, + "3912": { "label": "25/13", "naklon": 10 }, + "3933": { "label": "25/14", "naklon": 10 }, + "3921": { "label": "25/15", "naklon": 10 }, + "4300": { "label": "25/16", "naklon": 10 }, + "3927": { "label": "25/17", "naklon": 10 }, + "3212": { "label": "25/18", "naklon": 10 }, + "3208": { "label": "25/19", "naklon": 10 }, + "3207": { "label": "25/20", "naklon": 10 }, + "4294": { "label": "25/21", "naklon": 10 }, + "3209": { "label": "25/22", "naklon": 10 }, + "3745": { "label": "25/23", "naklon": 10 }, + "3762": { "label": "25/24", "naklon": 10 }, + "3215": { "label": "25/25", "naklon": 10 }, + "3210": { "label": "25/26", "naklon": 10 }, + "3211": { "label": "25/27", "naklon": 10 }, + "3206": { "label": "25/28", "naklon": 10 }, + "3918": { "label": "25/29", "naklon": 5 }, + "3928": { "label": "25/30", "naklon": 5 }, + "3917": { "label": "25/31", "naklon": 5 }, + "4029": { "label": "25/32", "naklon": 0 }, + "4038": { "label": "25/33", "naklon": 0 }, + "4022": { "label": "25/34", "naklon": 0 }, + "3937": { "label": "25/35", "naklon": 0 }, + "3190": { "label": "25/36", "naklon": 0 }, + "3835": { "label": "25/37", "naklon": 0 }, + "3201": { "label": "25/38", "naklon": 0 }, + "3193": { "label": "25/39", "naklon": 0 }, + "3191": { "label": "25/40", "naklon": 0 }, + "3203": { "label": "25/41", "naklon": 0 }, + "4301": { "label": "25/42", "naklon": 0 }, + "3223": { "label": "25/43", "naklon": 0 }, + "3202": { "label": "25/44", "naklon": 0 }, + "3205": { "label": "25/45", "naklon": 0 }, + "3194": { "label": "25/46", "naklon": 0 }, + "3198": { "label": "25/47", "naklon": 0 }, + "3204": { "label": "25/48", "naklon": 0 }, + "3200": { "label": "25/49", "naklon": 0 }, + "3216": { "label": "25/50", "naklon": 0 }, + "3932": { "label": "25/51", "naklon": 5 }, + "3923": { "label": "25/52", "naklon": 5 }, + "3913": { "label": "25/53", "naklon": 5 }, + "3900": { "label": "25/54", "naklon": 5 }, + "4189": { "label": "25/55", "naklon": 10 }, + "4191": { "label": "25/56", "naklon": 10 }, + "3790": { "label": "25/57", "naklon": 10 }, + "4190": { "label": "25/58", "naklon": 10 }, + "4302": { "label": "25/59", "naklon": 0 }, + "4351": { "label": "25/60", "naklon": 0 }, + "4075": { "label": "25/61", "naklon": 0 }, + "4071": { "label": "25/62", "naklon": 0 }, + "3784": { "label": "25/63", "naklon": 0 }, + "4065": { "label": "25/64", "naklon": 0 }, + "4297": { "label": "25/65", "naklon": 0 }, + "4295": { "label": "25/66", "naklon": 0 }, + "4299": { "label": "25/67", "naklon": 0 }, + "3772": { "label": "25/68", "naklon": 0 }, + "3941": { "label": "25/69", "naklon": 0 }, + "3782": { "label": "25/70", "naklon": 0 }, + "4068": { "label": "25/71", "naklon": 0 }, + "4073": { "label": "25/72", "naklon": 0 }, + "3901": { "label": "25/73", "naklon": 5 }, + "4296": { "label": "25/74", "naklon": 5 }, + "3910": { "label": "25/75", "naklon": 5 }, + "4293": { "label": "25/76", "naklon": 5 }, + "3919": { "label": "25/77", "naklon": 5 }, + "3924": { "label": "25/78", "naklon": 5 }, + "3909": { "label": "25/79", "naklon": 5 }, + "3896": { "label": "25/80", "naklon": 5 }, + "3911": { "label": "25/81", "naklon": 5 }, + "2819": { "label": "25/82", "naklon": 15 }, + "3776": { "label": "25/83", "naklon": 15 }, + "3752": { "label": "25/84", "naklon": 15 }, + "4353": { "label": "25/85", "naklon": 15 }, + "3791": { "label": "25/86", "naklon": 0 }, + "3770": { "label": "25/87", "naklon": 0 }, + "3760": { "label": "25/88", "naklon": 0 }, + "3115": { "label": "25/89", "naklon": 0 }, + "3738": { "label": "25/90", "naklon": 0 }, + "3748": { "label": "25/91", "naklon": 0 }, + "3753": { "label": "25/92", "naklon": 0 }, + "3775": { "label": "25/93", "naklon": 0 }, + "3778": { "label": "25/94", "naklon": 5 }, + "4078": { "label": "25/95", "naklon": 5 }, + "4088": { "label": "25/96", "naklon": 5 }, + "3856": { "label": "25/97", "naklon": 5 }, + "4084": { "label": "25/98", "naklon": 5 }, + "4069": { "label": "25/99", "naklon": 5 }, + "4188": { "label": "25/100", "naklon": 5 }, + "4064": { "label": "25/101", "naklon": 5 }, + "3792": { "label": "25/102", "naklon": 5 }, + "3780": { "label": "25/103", "naklon": 5 }, + "4034": { "label": "25/104", "naklon": 5 }, + "4072": { "label": "25/105", "naklon": 5 }, + "3884": { "label": "25/106", "naklon": 5 }, + "3793": { "label": "25/107", "naklon": 5 }, + "3863": { "label": "25/108", "naklon": 5 }, + "3855": { "label": "25/109", "naklon": 5 }, + "3846": { "label": "33/1", "naklon": 0 }, + "3943": { "label": "33/2", "naklon": 0 }, + "3903": { "label": "33/3", "naklon": 0 }, + "3982": { "label": "33/4", "naklon": 0 }, + "3879": { "label": "33/5", "naklon": 0 }, + "3887": { "label": "33/6", "naklon": 0 }, + "3920": { "label": "33/7", "naklon": 5 }, + "3942": { "label": "33/8", "naklon": 5 }, + "3829": { "label": "33/9", "naklon": null }, + "3452": { "label": "34/79A", "naklon": 6 }, + "3460": { "label": "34/79B", "naklon": 6 }, + "3443": { "label": "34/90A", "naklon": 6 }, + "3445": { "label": "34/90B", "naklon": 6 }, + "3457": { "label": "34/90C", "naklon": 6 }, + "3461": { "label": "34/97A", "naklon": 6 }, + "3463": { "label": "34/97B", "naklon": 6 }, + "3426": { "label": "34/98A", "naklon": 6 }, + "3444": { "label": "34/98B", "naklon": 6 }, + "3453": { "label": "34/99A", "naklon": 6 }, + "3455": { "label": "34/99B", "naklon": 6 }, + "4009": { "label": "34/1", "naklon": 0 }, + "3602": { "label": "34/2", "naklon": 0 }, + "3441": { "label": "34/3", "naklon": 0 }, + "3464": { "label": "34/4", "naklon": 0 }, + "3883": { "label": "34/5", "naklon": 0 }, + "4098": { "label": "34/6", "naklon": 0 }, + "4003": { "label": "34/7", "naklon": 0 }, + "4004": { "label": "34/8", "naklon": 0 }, + "3888": { "label": "34/9", "naklon": 0 }, + "3997": { "label": "34/10", "naklon": 0 }, + "4006": { "label": "34/11", "naklon": 0 }, + "4000": { "label": "34/12", "naklon": 0 }, + "4011": { "label": "34/13", "naklon": 0 }, + "3999": { "label": "34/14", "naklon": 0 }, + "3981": { "label": "34/15", "naklon": 0 }, + "3988": { "label": "34/16", "naklon": 0 }, + "3986": { "label": "34/17", "naklon": 0 }, + "3998": { "label": "34/18", "naklon": 0 }, + "3983": { "label": "34/19", "naklon": 0 }, + "4005": { "label": "34/20", "naklon": 0 }, + "4001": { "label": "34/21", "naklon": 0 }, + "4008": { "label": "34/22", "naklon": 0 }, + "4002": { "label": "34/23", "naklon": 0 }, + "3996": { "label": "34/24", "naklon": 0 }, + "4007": { "label": "34/25", "naklon": 0 }, + "4113": { "label": "34/26", "naklon": 15 }, + "3595": { "label": "34/27", "naklon": 5 }, + "3599": { "label": "34/28", "naklon": 5 }, + "3601": { "label": "34/29", "naklon": 5 }, + "4205": { "label": "34/30", "naklon": 0 }, + "3987": { "label": "34/31", "naklon": null }, + "4214": { "label": "34/32", "naklon": 0 }, + "4226": { "label": "34/33", "naklon": 0 }, + "4209": { "label": "34/34", "naklon": 0 }, + "4201": { "label": "34/35", "naklon": 0 }, + "3440": { "label": "34/36", "naklon": 0 }, + "3465": { "label": "34/37", "naklon": 0 }, + "3446": { "label": "34/38", "naklon": 0 }, + "4039": { "label": "34/39", "naklon": 5 }, + "4057": { "label": "34/40", "naklon": 5 }, + "3985": { "label": "34/41", "naklon": 0 }, + "3882": { "label": "34/42", "naklon": 0 }, + "4040": { "label": "34/43", "naklon": 5 }, + "3231": { "label": "34/44", "naklon": 0 }, + "3227": { "label": "34/45", "naklon": 0 }, + "3431": { "label": "34/46", "naklon": 0 }, + "4013": { "label": "34/47", "naklon": 0 }, + "4045": { "label": "34/48", "naklon": 0 }, + "3949": { "label": "34/49", "naklon": 0 }, + "3953": { "label": "34/50", "naklon": 0 }, + "3952": { "label": "34/51", "naklon": 0 }, + "3995": { "label": "34/52", "naklon": 0 }, + "3992": { "label": "34/53", "naklon": 0 }, + "4198": { "label": "34/54", "naklon": 0 }, + "3935": { "label": "34/55", "naklon": 0 }, + "4050": { "label": "34/56", "naklon": 0 }, + "4049": { "label": "34/57", "naklon": 0 }, + "4054": { "label": "34/58", "naklon": 0 }, + "3663": { "label": "34/59", "naklon": 6 }, + "3661": { "label": "34/60", "naklon": 6 }, + "3664": { "label": "34/61", "naklon": 6 }, + "3660": { "label": "34/62", "naklon": 6 }, + "3662": { "label": "34/63", "naklon": 6 }, + "3665": { "label": "34/65", "naklon": 6 }, + "3667": { "label": "34/66", "naklon": 6 }, + "3675": { "label": "34/67", "naklon": 6 }, + "3666": { "label": "34/68", "naklon": 6 }, + "3652": { "label": "34/69", "naklon": 6 }, + "3458": { "label": "34/70", "naklon": 6 }, + "4425": { "label": "34/70/1", "naklon": 6 }, + "3459": { "label": "34/71", "naklon": 6 }, + "3435": { "label": "34/72", "naklon": 6 }, + "3448": { "label": "34/73", "naklon": 6 }, + "3451": { "label": "34/74", "naklon": 6 }, + "3442": { "label": "34/75", "naklon": 6 }, + "3449": { "label": "34/76", "naklon": 6 }, + "3450": { "label": "34/77", "naklon": 6 }, + "3433": { "label": "34/78", "naklon": 6 }, + "3432": { "label": "34/80", "naklon": 12 }, + "3470": { "label": "34/81", "naklon": 12 }, + "3438": { "label": "34/82", "naklon": 12 }, + "3439": { "label": "34/83", "naklon": 12 }, + "4028": { "label": "34/84", "naklon": 5 }, + "3596": { "label": "34/85", "naklon": 5 }, + "4021": { "label": "34/86", "naklon": 5 }, + "3437": { "label": "34/87", "naklon": 12 }, + "3428": { "label": "34/88", "naklon": 12 }, + "3430": { "label": "34/89", "naklon": 12 }, + "3454": { "label": "34/91", "naklon": 6 }, + "3492": { "label": "34/92", "naklon": 6 }, + "3462": { "label": "34/93", "naklon": 6 }, + "3427": { "label": "34/94", "naklon": 6 }, + "3434": { "label": "34/95", "naklon": 6 }, + "3456": { "label": "34/96", "naklon": 6 }, + "4307": { "label": "34/98/1", "naklon": 6 }, + "3968": { "label": "35/1", "naklon": 0 }, + "3969": { "label": "35/2", "naklon": 0 }, + "3947": { "label": "35/3", "naklon": 0 }, + "3979": { "label": "35/4", "naklon": 0 }, + "3959": { "label": "35/5", "naklon": 0 }, + "3948": { "label": "35/6", "naklon": 0 }, + "3961": { "label": "35/7", "naklon": 0 }, + "3956": { "label": "35/8", "naklon": 0 }, + "3604": { "label": "35/9", "naklon": 0 }, + "3944": { "label": "35/10", "naklon": 0 }, + "3960": { "label": "35/11", "naklon": 0 }, + "3958": { "label": "35/12", "naklon": 0 }, + "4036": { "label": "35/13", "naklon": 5 }, + "3893": { "label": "35/18", "naklon": 5 }, + "4108": { "label": "35/19", "naklon": 5 }, + "4017": { "label": "35/20", "naklon": 5 }, + "3963": { "label": "35/21", "naklon": 0 }, + "3658": { "label": "35/22", "naklon": 0 }, + "3975": { "label": "35/23", "naklon": 0 }, + "3980": { "label": "35/24", "naklon": 0 }, + "4012": { "label": "35/25", "naklon": 0 }, + "3655": { "label": "35/26", "naklon": 0 }, + "3962": { "label": "35/27", "naklon": 0 }, + "3945": { "label": "35/28", "naklon": 0 }, + "3569": { "label": "35/29", "naklon": 0 }, + "3429": { "label": "35/30", "naklon": 0 }, + "3657": { "label": "35/31", "naklon": 0 }, + "3646": { "label": "35/32", "naklon": 0 }, + "3622": { "label": "35/33", "naklon": 0 }, + "3612": { "label": "35/34", "naklon": 0 }, + "3955": { "label": "35/35", "naklon": 0 }, + "3878": { "label": "35/37", "naklon": 0 }, + "3965": { "label": "35/38", "naklon": 0 }, + "3970": { "label": "35/39", "naklon": 0 }, + "3611": { "label": "35/40", "naklon": 0 }, + "2635": { "label": "35/41", "naklon": 0 }, + "3978": { "label": "35/42", "naklon": 0 }, + "4213": { "label": "35/43", "naklon": 0 }, + "3984": { "label": "35/44", "naklon": 0 }, + "4218": { "label": "35/45", "naklon": 0 }, + "3973": { "label": "35/46", "naklon": 0 }, + "3974": { "label": "35/47", "naklon": 0 }, + "3759": { "label": "35/48", "naklon": 0 }, + "3844": { "label": "35/49", "naklon": 0 }, + "3804": { "label": "35/50", "naklon": 0 }, + "3831": { "label": "35/51", "naklon": 0 }, + "3643": { "label": "35/52", "naklon": 0 }, + "3966": { "label": "35/53", "naklon": 0 }, + "3971": { "label": "35/54", "naklon": 0 }, + "3650": { "label": "35/55", "naklon": 6 }, + "3651": { "label": "35/56", "naklon": 6 }, + "3669": { "label": "35/57", "naklon": 6 }, + "3648": { "label": "35/58", "naklon": 6 }, + "3645": { "label": "35/59", "naklon": 6 }, + "3659": { "label": "35/60", "naklon": 6 }, + "3647": { "label": "35/61", "naklon": 6 }, + "3644": { "label": "35/62", "naklon": 6 }, + "3671": { "label": "35/63", "naklon": 6 }, + "3682": { "label": "35/64", "naklon": 6 }, + "3672": { "label": "35/65", "naklon": 6 }, + "3683": { "label": "35/66", "naklon": 6 }, + "3673": { "label": "35/67", "naklon": 6 }, + "3674": { "label": "35/68", "naklon": 6 }, + "3679": { "label": "35/69", "naklon": 6 }, + "3649": { "label": "35/70", "naklon": 6 }, + "3687": { "label": "35/71", "naklon": 6 }, + "3677": { "label": "35/72", "naklon": 6 }, + "3690": { "label": "35/73", "naklon": 6 }, + "3691": { "label": "35/74", "naklon": 6 }, + "3676": { "label": "35/75", "naklon": 6 }, + "3680": { "label": "35/76", "naklon": 6 }, + "3668": { "label": "35/77", "naklon": 6 }, + "3681": { "label": "35/78", "naklon": 6 }, + "3670": { "label": "35/79", "naklon": 6 }, + "3689": { "label": "35/80", "naklon": 6 }, + "3678": { "label": "35/81", "naklon": 6 }, + "3693": { "label": "35/82", "naklon": 6 }, + "3654": { "label": "35/83", "naklon": null }, + "4086": { "label": "36/1", "naklon": 0 }, + "4085": { "label": "36/2", "naklon": 0 }, + "4083": { "label": "36/3", "naklon": 0 }, + "4087": { "label": "36/4", "naklon": 0 }, + "4077": { "label": "36/5", "naklon": 0 }, + "4082": { "label": "36/6", "naklon": 0 }, + "4186": { "label": "36/7", "naklon": 0 }, + "4206": { "label": "36/8", "naklon": 0 }, + "4080": { "label": "36/9", "naklon": 0 }, + "4081": { "label": "36/10", "naklon": 0 }, + "4210": { "label": "36/11", "naklon": 0 }, + "4079": { "label": "36/12", "naklon": 0 }, + "4076": { "label": "36/13", "naklon": 0 }, + "3852": { "label": "36/14", "naklon": 0 }, + "2813": { "label": "36/15", "naklon": 0 }, + "4219": { "label": "36/16", "naklon": 0 }, + "3104": { "label": "37/1A", "naklon": 15 }, + "3121": { "label": "37/1B", "naklon": 15 }, + "3113": { "label": "37/2", "naklon": 10 }, + "3118": { "label": "37/3", "naklon": 10 }, + "3111": { "label": "37/4", "naklon": 10 }, + "4020": { "label": "37/5", "naklon": 10 }, + "3119": { "label": "37/6", "naklon": 10 }, + "3110": { "label": "37/7", "naklon": 10 }, + "3108": { "label": "37/8", "naklon": 10 }, + "3107": { "label": "37/12", "naklon": 0 }, + "3199": { "label": "37/13", "naklon": 0 }, + "3120": { "label": "37/14", "naklon": 0 }, + "3122": { "label": "37/15", "naklon": 0 }, + "3908": { "label": "37/16", "naklon": 0 }, + "3114": { "label": "37/17", "naklon": 0 }, + "3105": { "label": "37/18", "naklon": 0 }, + "3116": { "label": "37/19", "naklon": 0 }, + "3106": { "label": "37/20", "naklon": 0 }, + "2887": { "label": "37/21", "naklon": 5 }, + "2888": { "label": "37/22", "naklon": 5 }, + "2877": { "label": "37/23", "naklon": 5 }, + "2891": { "label": "37/24", "naklon": 5 }, + "2886": { "label": "37/25", "naklon": 5 }, + "2892": { "label": "37/26", "naklon": 5 }, + "2882": { "label": "37/27", "naklon": 5 }, + "2883": { "label": "37/28", "naklon": 5 }, + "2876": { "label": "37/29", "naklon": 5 }, + "3109": { "label": "37/30", "naklon": 5 }, + "4152": { "label": "37/31", "naklon": 5 }, + "3117": { "label": "37/32", "naklon": 5 }, + "2870": { "label": "37/33", "naklon": 5 }, + "2867": { "label": "37/34", "naklon": 0 }, + "2865": { "label": "37/35", "naklon": 0 }, + "3096": { "label": "37/36", "naklon": 0 }, + "2871": { "label": "37/37", "naklon": 0 }, + "2884": { "label": "37/38", "naklon": 0 }, + "2855": { "label": "37/39", "naklon": 0 }, + "2878": { "label": "37/40", "naklon": 0 }, + "2889": { "label": "37/41", "naklon": 0 }, + "2879": { "label": "37/42", "naklon": 0 }, + "2850": { "label": "37/43", "naklon": 0 }, + "2894": { "label": "37/44", "naklon": 0 }, + "2880": { "label": "37/45", "naklon": 0 }, + "2893": { "label": "37/46", "naklon": 0 }, + "2890": { "label": "37/47", "naklon": 0 }, + "4355": { "label": "37/48", "naklon": 0 }, + "2885": { "label": "37/49", "naklon": 0 }, + "2875": { "label": "37/50", "naklon": 0 }, + "3486": { "label": "38/30A", "naklon": 5 }, + "3714": { "label": "38/30B", "naklon": 0 }, + "3483": { "label": "38/32A", "naklon": 5 }, + "3496": { "label": "38/32B", "naklon": 0 }, + "3487": { "label": "38/35A", "naklon": 5 }, + "3498": { "label": "38/35B", "naklon": 5 }, + "3578": { "label": "38/38A", "naklon": 5 }, + "3508": { "label": "38/38B", "naklon": 5 }, + "3787": { "label": "38/59A", "naklon": 5 }, + "3491": { "label": "38/59B", "naklon": 5 }, + "3568": { "label": "38/1", "naklon": null }, + "3502": { "label": "38/2", "naklon": 0 }, + "3836": { "label": "38/3", "naklon": 0 }, + "3588": { "label": "38/4", "naklon": 0 }, + "3493": { "label": "38/5", "naklon": 0 }, + "3580": { "label": "38/6", "naklon": 0 }, + "3572": { "label": "38/7", "naklon": 0 }, + "3506": { "label": "38/8", "naklon": 0 }, + "3503": { "label": "38/9", "naklon": 0 }, + "3579": { "label": "38/10", "naklon": 0 }, + "3586": { "label": "38/11", "naklon": 0 }, + "3495": { "label": "38/12", "naklon": 5 }, + "3492": { "label": "38/13", "naklon": 5 }, + "3532": { "label": "38/14", "naklon": 5 }, + "3574": { "label": "38/15", "naklon": 5 }, + "4140": { "label": "38/16", "naklon": 5 }, + "3795": { "label": "38/17", "naklon": 5 }, + "3788": { "label": "38/18", "naklon": 5 }, + "3796": { "label": "38/19", "naklon": 5 }, + "3797": { "label": "38/20", "naklon": 5 }, + "3798": { "label": "38/21", "naklon": 5 }, + "3786": { "label": "38/22", "naklon": 5 }, + "4067": { "label": "38/23", "naklon": 5 }, + "3773": { "label": "38/24", "naklon": 5 }, + "3774": { "label": "38/25", "naklon": 5 }, + "3789": { "label": "38/26", "naklon": 5 }, + "3520": { "label": "38/27", "naklon": null }, + "3577": { "label": "38/29", "naklon": 5 }, + "3530": { "label": "38/31", "naklon": null }, + "3488": { "label": "38/33", "naklon": 5 }, + "3505": { "label": "38/34", "naklon": 5 }, + "3497": { "label": "38/36", "naklon": 5 }, + "3490": { "label": "38/37", "naklon": 5 }, + "3585": { "label": "38/39", "naklon": 5 }, + "3582": { "label": "38/40", "naklon": 5 }, + "3507": { "label": "38/41", "naklon": 5 }, + "3484": { "label": "38/42", "naklon": 5 }, + "3501": { "label": "38/43", "naklon": 5 }, + "3581": { "label": "38/44", "naklon": 5 }, + "4192": { "label": "38/45", "naklon": 5 }, + "3576": { "label": "38/46", "naklon": 5 }, + "3489": { "label": "38/47", "naklon": 5 }, + "3573": { "label": "38/48", "naklon": 5 }, + "3504": { "label": "38/49", "naklon": 5 }, + "3794": { "label": "38/50", "naklon": 5 }, + "3485": { "label": "38/51", "naklon": 5 }, + "3482": { "label": "38/52", "naklon": 5 }, + "3575": { "label": "38/53", "naklon": 5 }, + "3499": { "label": "38/54", "naklon": 5 }, + "3494": { "label": "38/55", "naklon": 5 }, + "3583": { "label": "38/56", "naklon": 5 }, + "3570": { "label": "38/57", "naklon": 5 }, + "3500": { "label": "38/58", "naklon": 0 }, + "3510": { "label": "38/63", "naklon": null }, + "3512": { "label": "38/64", "naklon": null }, + "3535": { "label": "38/67", "naklon": null }, + "3531": { "label": "38/68", "naklon": null }, + "3537": { "label": "38/69", "naklon": null }, + "3522": { "label": "39/1", "naklon": 10 }, + "4018": { "label": "39/2", "naklon": 10 }, + "4019": { "label": "39/3", "naklon": 10 }, + "4154": { "label": "39/4", "naklon": 5 }, + "3907": { "label": "39/5", "naklon": 5 }, + "4148": { "label": "39/6", "naklon": 0 }, + "4153": { "label": "39/7", "naklon": 0 }, + "3938": { "label": "39/8", "naklon": 0 }, + "3802": { "label": "39/9", "naklon": 0 }, + "4015": { "label": "39/10", "naklon": 0 }, + "3929": { "label": "39/11", "naklon": 0 }, + "3946": { "label": "39/12", "naklon": 0 }, + "4014": { "label": "39/13", "naklon": 0 }, + "4155": { "label": "39/14", "naklon": 0 }, + "4149": { "label": "39/15", "naklon": 0 }, + "3642": { "label": "39/16", "naklon": 0 }, + "3636": { "label": "39/17", "naklon": 5 }, + "3991": { "label": "39/18", "naklon": 0 }, + "3994": { "label": "39/19", "naklon": 0 }, + "3990": { "label": "39/20", "naklon": 0 }, + "3967": { "label": "39/21", "naklon": 0 }, + "3977": { "label": "39/22", "naklon": 0 }, + "3757": { "label": "39/23", "naklon": 15 }, + "3633": { "label": "39/24", "naklon": 15 }, + "3744": { "label": "39/25", "naklon": 15 }, + "4023": { "label": "39/26", "naklon": 5 }, + "3720": { "label": "39/27", "naklon": 5 }, + "3734": { "label": "39/28", "naklon": 5 }, + "3741": { "label": "39/29", "naklon": 5 }, + "3721": { "label": "39/30", "naklon": 5 }, + "3845": { "label": "39/31", "naklon": 0 }, + "3840": { "label": "39/32", "naklon": 0 }, + "3837": { "label": "39/33", "naklon": null }, + "3839": { "label": "39/34", "naklon": 0 }, + "3542": { "label": "41/1", "naklon": null }, + "3566": { "label": "41/2", "naklon": null }, + "3548": { "label": "41/3", "naklon": null }, + "3515": { "label": "41/4", "naklon": null }, + "3559": { "label": "41/5", "naklon": null }, + "3509": { "label": "41/6", "naklon": null }, + "3524": { "label": "41/7", "naklon": null }, + "3518": { "label": "41/8", "naklon": null }, + "3182": { "label": "41/9", "naklon": null }, + "3187": { "label": "41/10", "naklon": null }, + "3195": { "label": "41/11", "naklon": 0 }, + "3857": { "label": "41/12", "naklon": 0 }, + "3183": { "label": "41/13", "naklon": 0 }, + "3177": { "label": "41/14", "naklon": 0 }, + "3189": { "label": "41/15", "naklon": 0 }, + "3186": { "label": "41/16", "naklon": 0 }, + "3178": { "label": "42/1", "naklon": 0 }, + "3219": { "label": "42/2", "naklon": 0 }, + "3475": { "label": "42/3", "naklon": 0 }, + "3175": { "label": "42/4", "naklon": 0 }, + "3222": { "label": "42/5", "naklon": 0 }, + "3221": { "label": "42/6", "naklon": 0 }, + "3181": { "label": "42/7", "naklon": 0 }, + "3180": { "label": "42/8", "naklon": 0 }, + "3218": { "label": "42/9", "naklon": 0 }, + "3176": { "label": "42/10", "naklon": 0 }, + "3174": { "label": "42/11", "naklon": 0 }, + "3220": { "label": "42/12", "naklon": 0 }, + "3533": { "label": "42/13", "naklon": null }, + "3543": { "label": "42/14", "naklon": null }, + "3554": { "label": "42/15", "naklon": null }, + "3549": { "label": "42/16", "naklon": null }, + "2857": { "label": "43/1", "naklon": 5 }, + "2752": { "label": "43/2", "naklon": 5 }, + "2753": { "label": "43/3", "naklon": 5 }, + "3024": { "label": "43/4", "naklon": 5 }, + "2754": { "label": "43/5", "naklon": 5 }, + "4423": { "label": "43/6", "naklon": 5 }, + "4368": { "label": "43/7", "naklon": 5 }, + "2978": { "label": "43/8", "naklon": 5 }, + "2868": { "label": "43/9", "naklon": 5 }, + "4377": { "label": "43/10", "naklon": 5 }, + "2757": { "label": "43/11", "naklon": 5 }, + "2970": { "label": "43/12", "naklon": 5 }, + "2758": { "label": "43/13", "naklon": 5 }, + "4378": { "label": "43/14", "naklon": 5 }, + "2759": { "label": "43/15", "naklon": 5 }, + "4342": { "label": "43/16", "naklon": 5 }, + "3026": { "label": "43/17", "naklon": null }, + "2986": { "label": "43/18", "naklon": null }, + "4343": { "label": "43/19", "naklon": null }, + "2760": { "label": "43/20", "naklon": null }, + "4379": { "label": "43/21", "naklon": null }, + "2971": { "label": "43/22", "naklon": null }, + "2761": { "label": "43/23", "naklon": null }, + "2762": { "label": "43/24", "naklon": null }, + "4339": { "label": "43/25", "naklon": null }, + "4380": { "label": "43/26", "naklon": null }, + "2975": { "label": "43/27", "naklon": null }, + "3003": { "label": "43/28", "naklon": null }, + "4338": { "label": "43/29", "naklon": null }, + "3002": { "label": "43/30", "naklon": null }, + "4345": { "label": "43/31", "naklon": null }, + "2979": { "label": "43/32", "naklon": null }, + "2989": { "label": "43/33", "naklon": null }, + "2996": { "label": "43/34", "naklon": null }, + "2972": { "label": "43/35", "naklon": null }, + "2988": { "label": "43/36", "naklon": null }, + "4344": { "label": "43/37", "naklon": null }, + "3022": { "label": "43/38", "naklon": null }, + "4341": { "label": "43/39", "naklon": null }, + "2983": { "label": "43/40", "naklon": null }, + "2995": { "label": "43/41", "naklon": null }, + "2763": { "label": "43/42", "naklon": null }, + "2764": { "label": "43/43", "naklon": null }, + "2765": { "label": "43/44", "naklon": null }, + "2766": { "label": "43/45", "naklon": null }, + "2767": { "label": "43/46", "naklon": null }, + "2768": { "label": "43/47", "naklon": null }, + "3018": { "label": "43/48", "naklon": null }, + "2982": { "label": "43/49", "naklon": null }, + "3019": { "label": "43/50", "naklon": 0 }, + "3013": { "label": "43/51", "naklon": null }, + "3007": { "label": "43/52", "naklon": null }, + "2980": { "label": "43/53", "naklon": null }, + "3011": { "label": "43/54", "naklon": null }, + "2672": { "label": "43/55", "naklon": null }, + "2673": { "label": "43/56", "naklon": null }, + "2674": { "label": "43/57", "naklon": null }, + "2675": { "label": "43/58", "naklon": null }, + "2676": { "label": "43/59", "naklon": null }, + "2677": { "label": "43/60", "naklon": null }, + "2678": { "label": "43/61", "naklon": null }, + "2679": { "label": "43/62", "naklon": null }, + "2680": { "label": "43/63", "naklon": null }, + "2840": { "label": "43/64", "naklon": null }, + "2682": { "label": "43/65", "naklon": null }, + "2683": { "label": "43/66", "naklon": null }, + "2684": { "label": "43/67", "naklon": 0 }, + "2685": { "label": "43/68", "naklon": null }, + "2686": { "label": "43/69", "naklon": null }, + "2687": { "label": "43/70", "naklon": null }, + "2688": { "label": "43/71", "naklon": null }, + "2689": { "label": "43/72", "naklon": null }, + "2690": { "label": "43/73", "naklon": null }, + "2691": { "label": "43/74", "naklon": null }, + "2692": { "label": "43/75", "naklon": null }, + "2693": { "label": "43/76", "naklon": 0 }, + "2694": { "label": "43/77", "naklon": null }, + "2695": { "label": "43/78", "naklon": null }, + "2696": { "label": "43/79", "naklon": 0 }, + "2697": { "label": "43/80", "naklon": null }, + "2698": { "label": "43/81", "naklon": 0 }, + "2699": { "label": "43/82", "naklon": null }, + "2700": { "label": "43/83", "naklon": 0 }, + "2744": { "label": "43/84", "naklon": null }, + "2745": { "label": "43/85", "naklon": 0 }, + "2746": { "label": "43/86", "naklon": null }, + "2747": { "label": "43/87", "naklon": 0 }, + "2748": { "label": "43/88", "naklon": null }, + "2749": { "label": "43/89", "naklon": 0 }, + "2841": { "label": "43/90", "naklon": null }, + "4237": { "label": "45/1", "naklon": 5 }, + "4226": { "label": "45/2", "naklon": 5 }, + "4242": { "label": "45/3", "naklon": 5 }, + "4179": { "label": "45/4", "naklon": 5 }, + "4247": { "label": "45/5", "naklon": 5 }, + "4245": { "label": "45/6", "naklon": 5 }, + "3872": { "label": "45/7", "naklon": 5 }, + "4175": { "label": "45/8", "naklon": 5 }, + "4236": { "label": "45/9", "naklon": 5 }, + "4170": { "label": "45/10", "naklon": 5 }, + "4238": { "label": "45/11", "naklon": 5 }, + "4246": { "label": "45/12", "naklon": 5 }, + "4166": { "label": "45/13", "naklon": 5 }, + "4227": { "label": "45/14", "naklon": 5 }, + "4171": { "label": "45/15", "naklon": 5 }, + "4180": { "label": "45/16", "naklon": 5 }, + "4244": { "label": "45/17", "naklon": 5 }, + "4199": { "label": "45/18", "naklon": 5 }, + "4239": { "label": "45/19", "naklon": 5 }, + "4207": { "label": "45/20", "naklon": 5 }, + "4223": { "label": "45/21", "naklon": 5 }, + "4230": { "label": "45/22", "naklon": 5 }, + "4233": { "label": "45/23", "naklon": 5 }, + "4222": { "label": "45/24", "naklon": 5 }, + "4217": { "label": "45/25", "naklon": 5 }, + "4243": { "label": "45/26", "naklon": 5 }, + "4200": { "label": "45/27", "naklon": 5 }, + "4228": { "label": "45/28", "naklon": 5 }, + "4211": { "label": "45/29", "naklon": 5 }, + "4234": { "label": "45/30", "naklon": 5 }, + "4235": { "label": "45/31", "naklon": 5 }, + "4203": { "label": "45/32", "naklon": 5 }, + "4240": { "label": "45/33", "naklon": 5 }, + "4224": { "label": "45/34", "naklon": 5 }, + "4232": { "label": "45/35", "naklon": 5 }, + "4231": { "label": "45/36", "naklon": 5 }, + "4161": { "label": "45/37", "naklon": 5 }, + "4225": { "label": "45/38", "naklon": 5 }, + "4241": { "label": "45/39", "naklon": 5 }, + "4229": { "label": "45/40", "naklon": 5 }, + "4221": { "label": "45/41", "naklon": 5 }, + "4212": { "label": "45/42", "naklon": 5 }, + "4216": { "label": "45/43", "naklon": 5 }, + "3864": { "label": "45/44", "naklon": null }, + "3806": { "label": "46/1", "naklon": 5 }, + "3813": { "label": "46/2", "naklon": 5 }, + "3815": { "label": "46/3", "naklon": 5 }, + "3807": { "label": "46/4", "naklon": 5 }, + "3895": { "label": "46/5", "naklon": 5 }, + "3809": { "label": "46/6", "naklon": 5 }, + "3820": { "label": "46/7", "naklon": 5 }, + "3805": { "label": "46/8", "naklon": 5 }, + "3894": { "label": "46/9", "naklon": 0 }, + "4055": { "label": "46/10", "naklon": 0 }, + "3812": { "label": "46/11", "naklon": 5 }, + "3822": { "label": "46/12", "naklon": 5 }, + "3821": { "label": "46/13", "naklon": 5 }, + "3808": { "label": "46/14", "naklon": 5 }, + "3799": { "label": "46/15", "naklon": 5 }, + "3816": { "label": "46/16", "naklon": 5 }, + "3751": { "label": "46/17", "naklon": 5 }, + "3814": { "label": "46/18", "naklon": 5 }, + "4044": { "label": "46/19", "naklon": 0 }, + "3931": { "label": "46/20", "naklon": 0 }, + "3902": { "label": "46/21", "naklon": 5 }, + "3916": { "label": "46/22", "naklon": 5 }, + "3892": { "label": "46/23", "naklon": 5 }, + "3914": { "label": "46/24", "naklon": 5 }, + "3898": { "label": "46/25", "naklon": 5 }, + "3897": { "label": "46/26", "naklon": 5 }, + "3885": { "label": "46/27", "naklon": 5 }, + "3906": { "label": "46/28", "naklon": 5 }, + "3930": { "label": "46/29", "naklon": 0 }, + "3936": { "label": "46/30", "naklon": 0 }, + "3860": { "label": "46/31", "naklon": 5 }, + "3841": { "label": "46/32", "naklon": 5 }, + "3873": { "label": "46/33", "naklon": 5 }, + "3854": { "label": "46/34", "naklon": 5 }, + "3939": { "label": "46/35", "naklon": 5 }, + "3858": { "label": "46/36", "naklon": 5 }, + "3940": { "label": "46/37", "naklon": 5 }, + "4035": { "label": "46/38", "naklon": 5 }, + "3373": { "label": "47/1", "naklon": 0 }, + "3374": { "label": "47/2", "naklon": 0 }, + "3384": { "label": "47/3", "naklon": 0 }, + "3385": { "label": "47/4", "naklon": 0 }, + "4051": { "label": "48/1", "naklon": 5 }, + "4041": { "label": "48/2", "naklon": 5 }, + "4056": { "label": "48/3", "naklon": 5 }, + "3875": { "label": "48/4", "naklon": 5 }, + "4061": { "label": "48/5", "naklon": 5 }, + "4047": { "label": "48/6", "naklon": 5 }, + "4060": { "label": "48/7", "naklon": 5 }, + "4059": { "label": "48/8", "naklon": 5 }, + "4058": { "label": "48/9", "naklon": 5 }, + "3635": { "label": "48/10", "naklon": 5 }, + "3640": { "label": "48/11", "naklon": 5 }, + "3747": { "label": "48/12", "naklon": 5 }, + "3629": { "label": "48/13", "naklon": 5 }, + "4048": { "label": "48/14", "naklon": 5 }, + "4063": { "label": "48/15", "naklon": 5 }, + "4062": { "label": "48/16", "naklon": 5 }, + "4043": { "label": "48/17", "naklon": 5 }, + "4052": { "label": "48/18", "naklon": 5 }, + "4042": { "label": "48/19", "naklon": 5 }, + "4053": { "label": "48/20", "naklon": 5 }, + "4167": { "label": "50/15A", "naklon": null }, + "4159": { "label": "50/15B", "naklon": null }, + "4183": { "label": "50/1", "naklon": 0 }, + "4157": { "label": "50/2", "naklon": 0 }, + "4160": { "label": "50/3", "naklon": 0 }, + "4173": { "label": "50/4", "naklon": 0 }, + "4177": { "label": "50/5", "naklon": 0 }, + "4174": { "label": "50/6", "naklon": 0 }, + "4178": { "label": "50/7", "naklon": 0 }, + "4195": { "label": "50/8", "naklon": 0 }, + "4169": { "label": "50/9", "naklon": 0 }, + "4162": { "label": "50/10", "naklon": 0 }, + "4158": { "label": "50/11", "naklon": 0 }, + "4182": { "label": "50/12", "naklon": 0 }, + "4194": { "label": "50/13", "naklon": 0 }, + "4184": { "label": "50/14", "naklon": 0 }, + "4197": { "label": "50/16", "naklon": null }, + "4164": { "label": "50/17", "naklon": null }, + "3306": { "label": "50/18", "naklon": null }, + "4168": { "label": "50/19", "naklon": null }, + "4193": { "label": "50/20", "naklon": null }, + "4187": { "label": "50/21", "naklon": null }, + "4163": { "label": "50/22", "naklon": null }, + "4165": { "label": "50/23", "naklon": null }, + "4185": { "label": "50/24", "naklon": null }, + "3904": { "label": "50/25", "naklon": null }, + "2619": { "label": "53/1", "naklon": 0 }, + "2623": { "label": "53/2", "naklon": 0 }, + "2617": { "label": "53/3", "naklon": 0 }, + "2622": { "label": "53/4", "naklon": 0 }, + "2618": { "label": "53/5", "naklon": 0 }, + "2626": { "label": "53/6", "naklon": 0 }, + "2869": { "label": "53/7", "naklon": 0 }, + "2613": { "label": "53/8", "naklon": 0 }, + "2608": { "label": "53/9", "naklon": 0 }, + "2611": { "label": "53/10", "naklon": 0 }, + "2598": { "label": "53/11", "naklon": 0 }, + "3528": { "label": "53/12", "naklon": 0 }, + "3545": { "label": "53/13", "naklon": 0 }, + "2620": { "label": "53/14", "naklon": 0 }, + "2612": { "label": "53/15", "naklon": 0 }, + "2615": { "label": "53/16", "naklon": 0 }, + "3722": { "label": "53/17", "naklon": 0 }, + "2624": { "label": "53/18", "naklon": 0 }, + "2609": { "label": "53/19", "naklon": 0 }, + "2625": { "label": "53/20", "naklon": 0 }, + "2602": { "label": "53/21", "naklon": 0 }, + "2610": { "label": "53/22", "naklon": 0 }, + "2599": { "label": "53/23", "naklon": 0 }, + "2605": { "label": "53/24", "naklon": 0 }, + "2593": { "label": "53/25", "naklon": 0 }, + "3074": { "label": "53/26", "naklon": 0 }, + "2740": { "label": "53/27", "naklon": 0 }, + "2614": { "label": "53/28", "naklon": 0 }, + "2601": { "label": "53/29", "naklon": 0 }, + "4196": { "label": "53/30", "naklon": 0 }, + "2607": { "label": "53/31", "naklon": 0 }, + "2582": { "label": "53/32", "naklon": 0 }, + "2594": { "label": "53/33", "naklon": 0 }, + "2589": { "label": "53/34", "naklon": 0 }, + "2596": { "label": "53/35", "naklon": 0 }, + "2603": { "label": "53/36", "naklon": 0 }, + "2597": { "label": "53/37", "naklon": 0 }, + "2590": { "label": "53/38", "naklon": 0 }, + "2581": { "label": "53/39", "naklon": 0 }, + "2583": { "label": "53/40", "naklon": 0 }, + "2580": { "label": "53/41", "naklon": 0 }, + "2579": { "label": "53/42", "naklon": 0 }, + "2797": { "label": "53/43", "naklon": 0 }, + "2577": { "label": "53/44", "naklon": 0 }, + "2586": { "label": "53/45", "naklon": 0 }, + "2588": { "label": "53/46", "naklon": 0 }, + "2591": { "label": "53/47", "naklon": 0 }, + "2592": { "label": "53/48", "naklon": 0 }, + "2573": { "label": "53/49", "naklon": 0 }, + "2595": { "label": "53/50", "naklon": 0 }, + "2587": { "label": "53/51", "naklon": 0 }, + "2578": { "label": "53/52", "naklon": 0 }, + "2574": { "label": "53/53", "naklon": 0 }, + "2571": { "label": "53/54", "naklon": 0 }, + "2570": { "label": "53/55", "naklon": 0 }, + "2576": { "label": "53/56", "naklon": 0 }, + "2881": { "label": "53/57", "naklon": 0 }, + "2575": { "label": "53/58", "naklon": 0 }, + "2572": { "label": "53/59", "naklon": 0 }, + "2569": { "label": "53/60", "naklon": 0 }, + "4324": { "label": "55/1", "naklon": 0 }, + "4319": { "label": "55/2", "naklon": 0 }, + "4327": { "label": "55/3", "naklon": 0 }, + "4333": { "label": "55/4", "naklon": 0 }, + "4332": { "label": "55/5", "naklon": 0 }, + "4320": { "label": "55/6", "naklon": 0 }, + "4317": { "label": "55/7", "naklon": 0 }, + "4318": { "label": "55/8", "naklon": 0 }, + "4328": { "label": "55/9", "naklon": 0 }, + "4323": { "label": "55/10", "naklon": 0 }, + "4325": { "label": "55/11", "naklon": 0 }, + "4326": { "label": "55/12", "naklon": 0 }, + "4316": { "label": "55/13", "naklon": 0 }, + "4322": { "label": "55/14", "naklon": 0 }, + "4331": { "label": "55/15", "naklon": 0 }, + "4321": { "label": "55/16", "naklon": 0 }, + "4315": { "label": "55/17", "naklon": 0 }, + "4329": { "label": "55/18", "naklon": 0 }, + "4334": { "label": "55/19", "naklon": 0 }, + "4330": { "label": "55/20", "naklon": 0 } +}; + + +let svetlaSorted = [{ "label": "1/3A", "node": 3993, "naklon": 0 }, +{ "label": "1/3B", "node": 3989, "naklon": 15 }, +{ "label": "1/1", "node": 3976, "naklon": 0 }, +{ "label": "1/2", "node": 4181, "naklon": 0 }, +{ "label": "1/4", "node": 4376, "naklon": 15 }, +{ "label": "1/5", "node": 3868, "naklon": 15 }, +{ "label": "1/6", "node": 3728, "naklon": 15 }, +{ "label": "1/7", "node": 3730, "naklon": 0 }, +{ "label": "1/8", "node": 4374, "naklon": 0 }, +{ "label": "1/9", "node": 3718, "naklon": 15 }, +{ "label": "1/10", "node": 4375, "naklon": 15 }, +{ "label": "1/11", "node": 4172, "naklon": 15 }, +{ "label": "1/12", "node": 4176, "naklon": 15 }, +{ "label": "2/1", "node": 3800, "naklon": 5 }, +{ "label": "2/2", "node": 3823, "naklon": 5 }, +{ "label": "2/3", "node": 3905, "naklon": 5 }, +{ "label": "2/4", "node": 3803, "naklon": 5 }, +{ "label": "2/5", "node": 3817, "naklon": 5 }, +{ "label": "2/6", "node": 3818, "naklon": 5 }, +{ "label": "2/7", "node": 3811, "naklon": 5 }, +{ "label": "2/8", "node": 3915, "naklon": 5 }, +{ "label": "2/9", "node": 3843, "naklon": 10 }, +{ "label": "2/10", "node": 3827, "naklon": 10 }, +{ "label": "2/11", "node": 4220, "naklon": 10 }, +{ "label": "2/12", "node": 3826, "naklon": 10 }, +{ "label": "2/13", "node": 3834, "naklon": 10 }, +{ "label": "2/14", "node": 3838, "naklon": 10 }, +{ "label": "2/15", "node": 2823, "naklon": 10 }, +{ "label": "2/16", "node": 3750, "naklon": 10 }, +{ "label": "2/17", "node": 3378, "naklon": 0 }, +{ "label": "2/18", "node": 3376, "naklon": 0 }, +{ "label": "2/19", "node": 3379, "naklon": 0 }, +{ "label": "2/20", "node": 3285, "naklon": 0 }, +{ "label": "2/21", "node": 3382, "naklon": 0 }, +{ "label": "2/22", "node": 3383, "naklon": 0 }, +{ "label": "2/24", "node": 3375, "naklon": 0 }, +{ "label": "2/25", "node": 3381, "naklon": 0 }, +{ "label": "2/26", "node": 3380, "naklon": 0 }, +{ "label": "2/27", "node": 3828, "naklon": 10 }, +{ "label": "2/28", "node": 3377, "naklon": 0 }, +{ "label": "7/1", "node": 3591, "naklon": 0 }, +{ "label": "7/2", "node": 3587, "naklon": 0 }, +{ "label": "7/3", "node": 3468, "naklon": 0 }, +{ "label": "7/4", "node": 3466, "naklon": 0 }, +{ "label": "7/5", "node": 3474, "naklon": 0 }, +{ "label": "7/6", "node": 3481, "naklon": 0 }, +{ "label": "7/7", "node": 3589, "naklon": 0 }, +{ "label": "7/8", "node": 3472, "naklon": 0 }, +{ "label": "7/9", "node": 3473, "naklon": 0 }, +{ "label": "7/10", "node": 3584, "naklon": 0 }, +{ "label": "7/11", "node": 3571, "naklon": 0 }, +{ "label": "7/12", "node": 3476, "naklon": 0 }, +{ "label": "7/13", "node": 3590, "naklon": 0 }, +{ "label": "7/14", "node": 3478, "naklon": 0 }, +{ "label": "7/15", "node": 3471, "naklon": 0 }, +{ "label": "7/16", "node": 3467, "naklon": 0 }, +{ "label": "7/17", "node": 3479, "naklon": 0 }, +{ "label": "7/18", "node": 3480, "naklon": 0 }, +{ "label": "7/19", "node": 3477, "naklon": 0 }, +{ "label": "12/1", "node": 3362, "naklon": 0 }, +{ "label": "12/2", "node": 3355, "naklon": 0 }, +{ "label": "12/3", "node": 3356, "naklon": 0 }, +{ "label": "12/4", "node": 3349, "naklon": 0 }, +{ "label": "12/5", "node": 3357, "naklon": 0 }, +{ "label": "12/6", "node": 3350, "naklon": 0 }, +{ "label": "12/7", "node": 3353, "naklon": 0 }, +{ "label": "12/8", "node": 3539, "naklon": 0 }, +{ "label": "12/9", "node": 3050, "naklon": 0 }, +{ "label": "12/10", "node": 3361, "naklon": 0 }, +{ "label": "12/11", "node": 3360, "naklon": 0 }, +{ "label": "12/12", "node": 3358, "naklon": 0 }, +{ "label": "12/13", "node": 3541, "naklon": 0 }, +{ "label": "12/14", "node": 3551, "naklon": 0 }, +{ "label": "12/15", "node": 3514, "naklon": 0 }, +{ "label": "12/16", "node": 3547, "naklon": 0 }, +{ "label": "12/17", "node": 3562, "naklon": 0 }, +{ "label": "12/18", "node": 3525, "naklon": 0 }, +{ "label": "12/19", "node": 3558, "naklon": 0 }, +{ "label": "12/20", "node": 3511, "naklon": 0 }, +{ "label": "12/21", "node": 3058, "naklon": 0 }, +{ "label": "12/22", "node": 3062, "naklon": 0 }, +{ "label": "12/23", "node": 3070, "naklon": 0 }, +{ "label": "12/24", "node": 3447, "naklon": 0 }, +{ "label": "12/25", "node": 3056, "naklon": 0 }, +{ "label": "12/26", "node": 3057, "naklon": 0 }, +{ "label": "12/27", "node": 3071, "naklon": 0 }, +{ "label": "12/28", "node": 3061, "naklon": 0 }, +{ "label": "12/29", "node": 3069, "naklon": 0 }, +{ "label": "12/30", "node": 3077, "naklon": 0 }, +{ "label": "12/31", "node": 3080, "naklon": 0 }, +{ "label": "12/32", "node": 3081, "naklon": 0 }, +{ "label": "12/33", "node": 3078, "naklon": 0 }, +{ "label": "12/34", "node": 4037, "naklon": 0 }, +{ "label": "12/35", "node": 3067, "naklon": 0 }, +{ "label": "12/36", "node": 3051, "naklon": 0 }, +{ "label": "12/37", "node": 2924, "naklon": 0 }, +{ "label": "12/38", "node": 3060, "naklon": 0 }, +{ "label": "12/39", "node": 3073, "naklon": 0 }, +{ "label": "12/40", "node": 3469, "naklon": 0 }, +{ "label": "12/41", "node": 2923, "naklon": 0 }, +{ "label": "12/42", "node": 2925, "naklon": 0 }, +{ "label": "12/43", "node": 3359, "naklon": 0 }, +{ "label": "12/44", "node": 3055, "naklon": 0 }, +{ "label": "12/45", "node": 2922, "naklon": 0 }, +{ "label": "12/46", "node": 3084, "naklon": 0 }, +{ "label": "12/47", "node": 3064, "naklon": 0 }, +{ "label": "12/48", "node": 3066, "naklon": 0 }, +{ "label": "12/49", "node": 3072, "naklon": 0 }, +{ "label": "13/13A", "node": 3415, "naklon": 0 }, +{ "label": "13/13B", "node": 3409, "naklon": 0 }, +{ "label": "13/13C", "node": 3399, "naklon": 0 }, +{ "label": "13/29A", "node": 3410, "naklon": 0 }, +{ "label": "13/29B", "node": 3407, "naklon": 0 }, +{ "label": "13/34A", "node": 3405, "naklon": 0 }, +{ "label": "13/34B", "node": 3404, "naklon": 0 }, +{ "label": "13/45A", "node": 3392, "naklon": 0 }, +{ "label": "13/45B", "node": 3386, "naklon": 0 }, +{ "label": "13/60A", "node": 3303, "naklon": 3 }, +{ "label": "13/60B", "node": 3302, "naklon": 3 }, +{ "label": "13/70A", "node": 3319, "naklon": 6 }, +{ "label": "13/70B", "node": 3317, "naklon": 6 }, +{ "label": "13/70C", "node": 3326, "naklon": 6 }, +{ "label": "13/73A", "node": 3351, "naklon": 6 }, +{ "label": "13/73B", "node": 3313, "naklon": 6 }, +{ "label": "13/83A", "node": 3316, "naklon": 0 }, +{ "label": "13/83B", "node": 3320, "naklon": 0 }, +{ "label": "13/95A", "node": 3336, "naklon": 0 }, +{ "label": "13/95B", "node": 3323, "naklon": 0 }, +{ "label": "13/98A", "node": 3339, "naklon": 0 }, +{ "label": "13/98B", "node": 3333, "naklon": 0 }, +{ "label": "13/1", "node": 3425, "naklon": 0 }, +{ "label": "13/2", "node": 3419, "naklon": 0 }, +{ "label": "13/3", "node": 3416, "naklon": 0 }, +{ "label": "13/4", "node": 3332, "naklon": 0 }, +{ "label": "13/5", "node": 3422, "naklon": 0 }, +{ "label": "13/6", "node": 3417, "naklon": 0 }, +{ "label": "13/7", "node": 3418, "naklon": 0 }, +{ "label": "13/8", "node": 3424, "naklon": 0 }, +{ "label": "13/9", "node": 3334, "naklon": 0 }, +{ "label": "13/10", "node": 4363, "naklon": 0 }, +{ "label": "13/11", "node": 3423, "naklon": 0 }, +{ "label": "13/12", "node": 3406, "naklon": 0 }, +{ "label": "13/14", "node": 3411, "naklon": 0 }, +{ "label": "13/15", "node": 3412, "naklon": 0 }, +{ "label": "13/16", "node": 3413, "naklon": 0 }, +{ "label": "13/17", "node": 3414, "naklon": 0 }, +{ "label": "13/18", "node": 3391, "naklon": 0 }, +{ "label": "13/19", "node": 3370, "naklon": 0 }, +{ "label": "13/20", "node": 3369, "naklon": 0 }, +{ "label": "13/21", "node": 3408, "naklon": 0 }, +{ "label": "13/22", "node": 3393, "naklon": 0 }, +{ "label": "13/23", "node": 3128, "naklon": 0 }, +{ "label": "13/24", "node": 3197, "naklon": 0 }, +{ "label": "13/25", "node": 4364, "naklon": 0 }, +{ "label": "13/26", "node": 3155, "naklon": 0 }, +{ "label": "13/27", "node": 3196, "naklon": 0 }, +{ "label": "13/28", "node": 3144, "naklon": 0 }, +{ "label": "13/30", "node": 3150, "naklon": 0 }, +{ "label": "13/31", "node": 3390, "naklon": 0 }, +{ "label": "13/32", "node": 3401, "naklon": 0 }, +{ "label": "13/33", "node": 3275, "naklon": 0 }, +{ "label": "13/35", "node": 3371, "naklon": 0 }, +{ "label": "13/36", "node": 3389, "naklon": 0 }, +{ "label": "13/37", "node": 3388, "naklon": 0 }, +{ "label": "13/38", "node": 3365, "naklon": 0 }, +{ "label": "13/39", "node": 3363, "naklon": 0 }, +{ "label": "13/40", "node": 3397, "naklon": 0 }, +{ "label": "13/40/1", "node": 3567, "naklon": 0 }, +{ "label": "13/41", "node": 3387, "naklon": 0 }, +{ "label": "13/42", "node": 3403, "naklon": 0 }, +{ "label": "13/43", "node": 3147, "naklon": 0 }, +{ "label": "13/44", "node": 3141, "naklon": 0 }, +{ "label": "13/46", "node": 3364, "naklon": 0 }, +{ "label": "13/47", "node": 3367, "naklon": 0 }, +{ "label": "13/48", "node": 3368, "naklon": 0 }, +{ "label": "13/49", "node": 3402, "naklon": 0 }, +{ "label": "13/50", "node": 3366, "naklon": 0 }, +{ "label": "13/51", "node": 3395, "naklon": 0 }, +{ "label": "13/52", "node": 3372, "naklon": 0 }, +{ "label": "13/53", "node": 3394, "naklon": 0 }, +{ "label": "13/54", "node": 3308, "naklon": 0 }, +{ "label": "13/54/1", "node": 3847, "naklon": 0 }, +{ "label": "13/55", "node": 3312, "naklon": 3 }, +{ "label": "13/56", "node": 3309, "naklon": 3 }, +{ "label": "13/57", "node": 3311, "naklon": 3 }, +{ "label": "13/58", "node": 3310, "naklon": 3 }, +{ "label": "13/59", "node": 4365, "naklon": 3 }, +{ "label": "13/60/1", "node": 4093, "naklon": 3 }, +{ "label": "13/61", "node": 3304, "naklon": 3 }, +{ "label": "13/62", "node": 3307, "naklon": 3 }, +{ "label": "13/63", "node": 3271, "naklon": 3 }, +{ "label": "13/64", "node": 3301, "naklon": 3 }, +{ "label": "13/65", "node": 4366, "naklon": 3 }, +{ "label": "13/66", "node": 3300, "naklon": 3 }, +{ "label": "13/67", "node": 3185, "naklon": 0 }, +{ "label": "13/68", "node": 3184, "naklon": 0 }, +{ "label": "13/69", "node": 3188, "naklon": 0 }, +{ "label": "13/71", "node": 3343, "naklon": 6 }, +{ "label": "13/71/1", "node": 3819, "naklon": 6 }, +{ "label": "13/71/2", "node": 3880, "naklon": 6 }, +{ "label": "13/72", "node": 3348, "naklon": 6 }, +{ "label": "13/74", "node": 3344, "naklon": 6 }, +{ "label": "13/75", "node": 3346, "naklon": 6 }, +{ "label": "13/75/1", "node": 3597, "naklon": 6 }, +{ "label": "13/76", "node": 3345, "naklon": 6 }, +{ "label": "13/77", "node": 3322, "naklon": 0 }, +{ "label": "13/78", "node": 3325, "naklon": 0 }, +{ "label": "13/78/1", "node": 4310, "naklon": 0 }, +{ "label": "13/79", "node": 3315, "naklon": 0 }, +{ "label": "13/80", "node": 3328, "naklon": 0 }, +{ "label": "13/81", "node": 3321, "naklon": 0 }, +{ "label": "13/82", "node": 3324, "naklon": 0 }, +{ "label": "13/84", "node": 3140, "naklon": 0 }, +{ "label": "13/85", "node": 3153, "naklon": 0 }, +{ "label": "13/86", "node": 3145, "naklon": 0 }, +{ "label": "13/87", "node": 3134, "naklon": 0 }, +{ "label": "13/88", "node": 3151, "naklon": 0 }, +{ "label": "13/89", "node": 3143, "naklon": 0 }, +{ "label": "13/90", "node": 3318, "naklon": 0 }, +{ "label": "13/91", "node": 3347, "naklon": 0 }, +{ "label": "13/94", "node": 3314, "naklon": 0 }, +{ "label": "13/96", "node": 3331, "naklon": 0 }, +{ "label": "13/97", "node": 3327, "naklon": 0 }, +{ "label": "13/99", "node": 3329, "naklon": 0 }, +{ "label": "13/100", "node": 3337, "naklon": 0 }, +{ "label": "13/101", "node": 3330, "naklon": 0 }, +{ "label": "13/102", "node": 3335, "naklon": 0 }, +{ "label": "13/103", "node": 3420, "naklon": 0 }, +{ "label": "13/104", "node": 3421, "naklon": 0 }, +{ "label": "13/105", "node": 4361, "naklon": 0 }, +{ "label": "13/106", "node": 4362, "naklon": 0 }, +{ "label": "13/107", "node": 3526, "naklon": 0 }, +{ "label": "13/108", "node": 4424, "naklon": null }, +{ "label": "13/109", "node": 3561, "naklon": null }, +{ "label": "13/110", "node": 3527, "naklon": null }, +{ "label": "13/111", "node": 3521, "naklon": null }, +{ "label": "13/112", "node": 3552, "naklon": null }, +{ "label": "13/113", "node": 3544, "naklon": null }, +{ "label": "13/114", "node": 3534, "naklon": null }, +{ "label": "13/115", "node": 3516, "naklon": null }, +{ "label": "13/116", "node": 3513, "naklon": null }, +{ "label": "13/117", "node": 3565, "naklon": null }, +{ "label": "13/118", "node": 3866, "naklon": null }, +{ "label": "14/1", "node": 3136, "naklon": 0 }, +{ "label": "14/2", "node": 3137, "naklon": 0 }, +{ "label": "14/3", "node": 3135, "naklon": 0 }, +{ "label": "14/4", "node": 3149, "naklon": 0 }, +{ "label": "14/5", "node": 3142, "naklon": 0 }, +{ "label": "14/6", "node": 3342, "naklon": 0 }, +{ "label": "14/7", "node": 3340, "naklon": 0 }, +{ "label": "14/8", "node": 3152, "naklon": 0 }, +{ "label": "14/9", "node": 3886, "naklon": 0 }, +{ "label": "14/10", "node": 3341, "naklon": null }, +{ "label": "14/11", "node": 3352, "naklon": null }, +{ "label": "15/1", "node": 3396, "naklon": 5 }, +{ "label": "15/2", "node": 2784, "naklon": 5 }, +{ "label": "15/3", "node": 2788, "naklon": 5 }, +{ "label": "15/4", "node": 2801, "naklon": 5 }, +{ "label": "15/5", "node": 2815, "naklon": 5 }, +{ "label": "15/6", "node": 2829, "naklon": 5 }, +{ "label": "15/7", "node": 2796, "naklon": 5 }, +{ "label": "15/8", "node": 2803, "naklon": 5 }, +{ "label": "15/8/1", "node": 4304, "naklon": 5 }, +{ "label": "15/8/2", "node": 4311, "naklon": 5 }, +{ "label": "15/9", "node": 2821, "naklon": 5 }, +{ "label": "15/10", "node": 3400, "naklon": 5 }, +{ "label": "15/11", "node": 2799, "naklon": 5 }, +{ "label": "15/12", "node": 2804, "naklon": 5 }, +{ "label": "15/12/1", "node": 4303, "naklon": 5 }, +{ "label": "15/12/2", "node": 4309, "naklon": 5 }, +{ "label": "15/13", "node": 2806, "naklon": 5 }, +{ "label": "15/14", "node": 2787, "naklon": 5 }, +{ "label": "15/15", "node": 2809, "naklon": 5 }, +{ "label": "15/16", "node": 2814, "naklon": 0 }, +{ "label": "15/17", "node": 3934, "naklon": 0 }, +{ "label": "15/18", "node": 3192, "naklon": 0 }, +{ "label": "15/19", "node": 2812, "naklon": 0 }, +{ "label": "15/20", "node": 4070, "naklon": 0 }, +{ "label": "15/21", "node": 2826, "naklon": 0 }, +{ "label": "15/22", "node": 2808, "naklon": 3 }, +{ "label": "15/23", "node": 2795, "naklon": 3 }, +{ "label": "15/24", "node": 2807, "naklon": 3 }, +{ "label": "15/25", "node": 2831, "naklon": 0 }, +{ "label": "15/26", "node": 2862, "naklon": null }, +{ "label": "15/27", "node": 2861, "naklon": 0 }, +{ "label": "15/28", "node": 2866, "naklon": 0 }, +{ "label": "15/28/1", "node": 3546, "naklon": 0 }, +{ "label": "15/29", "node": 4146, "naklon": 0 }, +{ "label": "15/29/1", "node": 3001, "naklon": 0 }, +{ "label": "15/30", "node": 2835, "naklon": 0 }, +{ "label": "15/31", "node": 2874, "naklon": 0 }, +{ "label": "15/32", "node": 2852, "naklon": 0 }, +{ "label": "15/33", "node": 2851, "naklon": 0 }, +{ "label": "15/33/1", "node": 3560, "naklon": 0 }, +{ "label": "15/34", "node": 2858, "naklon": 0 }, +{ "label": "15/34/1", "node": 4306, "naklon": 0 }, +{ "label": "15/35", "node": 2856, "naklon": 0 }, +{ "label": "15/36", "node": 2847, "naklon": 0 }, +{ "label": "15/36/1", "node": 3556, "naklon": 0 }, +{ "label": "15/37", "node": 3950, "naklon": 0 }, +{ "label": "15/38", "node": 2848, "naklon": 0 }, +{ "label": "15/39", "node": 2863, "naklon": 0 }, +{ "label": "15/39/1", "node": 4313, "naklon": 0 }, +{ "label": "15/40", "node": 2873, "naklon": 0 }, +{ "label": "15/40/1", "node": 2984, "naklon": 0 }, +{ "label": "15/41", "node": 2854, "naklon": 0 }, +{ "label": "15/42", "node": 2859, "naklon": 0 }, +{ "label": "15/43", "node": 2872, "naklon": 0 }, +{ "label": "15/44", "node": 2849, "naklon": 0 }, +{ "label": "15/45", "node": 2864, "naklon": 0 }, +{ "label": "15/46", "node": 3553, "naklon": null }, +{ "label": "15/47", "node": 3021, "naklon": null }, +{ "label": "15/47/1", "node": 3008, "naklon": null }, +{ "label": "15/48", "node": 3017, "naklon": null }, +{ "label": "15/49", "node": 3014, "naklon": null }, +{ "label": "15/50", "node": 2981, "naklon": null }, +{ "label": "15/51", "node": 3020, "naklon": null }, +{ "label": "15/52", "node": 3027, "naklon": null }, +{ "label": "15/53", "node": 3006, "naklon": null }, +{ "label": "15/54", "node": 3012, "naklon": null }, +{ "label": "15/55", "node": 2738, "naklon": 0 }, +{ "label": "15/56", "node": 2725, "naklon": 0 }, +{ "label": "15/57", "node": 3016, "naklon": null }, +{ "label": "15/58", "node": 3005, "naklon": null }, +{ "label": "15/58/1", "node": 3009, "naklon": null }, +{ "label": "15/59", "node": 3010, "naklon": 0 }, +{ "label": "15/59/1", "node": 3538, "naklon": 0 }, +{ "label": "15/59/2", "node": 4145, "naklon": 0 }, +{ "label": "15/60", "node": 2713, "naklon": 0 }, +{ "label": "15/61", "node": 2789, "naklon": 0 }, +{ "label": "15/62", "node": 2736, "naklon": 0 }, +{ "label": "15/63", "node": 2739, "naklon": 0 }, +{ "label": "15/64", "node": 4346, "naklon": 0 }, +{ "label": "15/65", "node": 2731, "naklon": 0 }, +{ "label": "15/66", "node": 2818, "naklon": 0 }, +{ "label": "15/66/1", "node": 3557, "naklon": 0 }, +{ "label": "15/67", "node": 2822, "naklon": 0 }, +{ "label": "15/68", "node": 2833, "naklon": 0 }, +{ "label": "15/69", "node": 2834, "naklon": 0 }, +{ "label": "15/70", "node": 3097, "naklon": 0 }, +{ "label": "15/71", "node": 2824, "naklon": 0 }, +{ "label": "15/72", "node": 2828, "naklon": 0 }, +{ "label": "15/73", "node": 2600, "naklon": 0 }, +{ "label": "15/73/1", "node": 4314, "naklon": 0 }, +{ "label": "15/74", "node": 2832, "naklon": 0 }, +{ "label": "15/75", "node": 4360, "naklon": 0 }, +{ "label": "15/76", "node": 2846, "naklon": 0 }, +{ "label": "15/77", "node": 2584, "naklon": 0 }, +{ "label": "15/78", "node": 2843, "naklon": 0 }, +{ "label": "15/78/1", "node": 4308, "naklon": 0 }, +{ "label": "15/79", "node": 4144, "naklon": null }, +{ "label": "15/80", "node": 2844, "naklon": 0 }, +{ "label": "15/81", "node": 2842, "naklon": 0 }, +{ "label": "15/82", "node": 2838, "naklon": 0 }, +{ "label": "15/83", "node": 2837, "naklon": null }, +{ "label": "15/83/1", "node": 3555, "naklon": null }, +{ "label": "15/84", "node": 2839, "naklon": 0 }, +{ "label": "15/85", "node": 2830, "naklon": 0 }, +{ "label": "15/86", "node": 4066, "naklon": 0 }, +{ "label": "15/87", "node": 2836, "naklon": 0 }, +{ "label": "15/88", "node": 2911, "naklon": 0 }, +{ "label": "15/89", "node": 2825, "naklon": 0 }, +{ "label": "15/90", "node": 2811, "naklon": 0 }, +{ "label": "15/94", "node": 3740, "naklon": 15 }, +{ "label": "15/95", "node": 2734, "naklon": 15 }, +{ "label": "15/96", "node": 3105, "naklon": 15 }, +{ "label": "15/97", "node": 2732, "naklon": 15 }, +{ "label": "15/98", "node": 2727, "naklon": 15 }, +{ "label": "15/99", "node": 2735, "naklon": 15 }, +{ "label": "15/100", "node": 3926, "naklon": 15 }, +{ "label": "15/101", "node": 2918, "naklon": 0 }, +{ "label": "15/102", "node": 2705, "naklon": 10 }, +{ "label": "15/103", "node": 2708, "naklon": 10 }, +{ "label": "15/104", "node": 2721, "naklon": 10 }, +{ "label": "15/105", "node": 2719, "naklon": 10 }, +{ "label": "15/106", "node": 2919, "naklon": 10 }, +{ "label": "15/107", "node": 3101, "naklon": 10 }, +{ "label": "15/108", "node": 2853, "naklon": 10 }, +{ "label": "15/109", "node": 2715, "naklon": 10 }, +{ "label": "15/110", "node": 2712, "naklon": 0 }, +{ "label": "15/111", "node": 2711, "naklon": 0 }, +{ "label": "15/112", "node": 2709, "naklon": 0 }, +{ "label": "15/113", "node": 2710, "naklon": 0 }, +{ "label": "15/114", "node": 2907, "naklon": 0 }, +{ "label": "15/115", "node": 2906, "naklon": 0 }, +{ "label": "15/116", "node": 2908, "naklon": 0 }, +{ "label": "15/117", "node": 2901, "naklon": 0 }, +{ "label": "15/118", "node": 2913, "naklon": 0 }, +{ "label": "15/119", "node": 3656, "naklon": 0 }, +{ "label": "15/120", "node": 2781, "naklon": 0 }, +{ "label": "15/121", "node": 2802, "naklon": 0 }, +{ "label": "15/122", "node": 2791, "naklon": 0 }, +{ "label": "15/123", "node": 2783, "naklon": 0 }, +{ "label": "15/124", "node": 2794, "naklon": 0 }, +{ "label": "15/125", "node": 3139, "naklon": 0 }, +{ "label": "15/126", "node": 3229, "naklon": 5 }, +{ "label": "15/127", "node": 3239, "naklon": 5 }, +{ "label": "15/128", "node": 3230, "naklon": 5 }, +{ "label": "15/129", "node": 4016, "naklon": null }, +{ "label": "16/16A", "node": 3608, "naklon": 0 }, +{ "label": "16/16B", "node": 4151, "naklon": 0 }, +{ "label": "16/1", "node": 3710, "naklon": 0 }, +{ "label": "16/2", "node": 3726, "naklon": 0 }, +{ "label": "16/3", "node": 3743, "naklon": 0 }, +{ "label": "16/4", "node": 3724, "naklon": 0 }, +{ "label": "16/5", "node": 3712, "naklon": 0 }, +{ "label": "16/6", "node": 3739, "naklon": 0 }, +{ "label": "16/7", "node": 3742, "naklon": 0 }, +{ "label": "16/8", "node": 3731, "naklon": 0 }, +{ "label": "16/9", "node": 3727, "naklon": 0 }, +{ "label": "16/10", "node": 3729, "naklon": 0 }, +{ "label": "16/11", "node": 3736, "naklon": 0 }, +{ "label": "16/12", "node": 3713, "naklon": 0 }, +{ "label": "16/13", "node": 3715, "naklon": 0 }, +{ "label": "16/14", "node": 3733, "naklon": 0 }, +{ "label": "16/15", "node": 3732, "naklon": 0 }, +{ "label": "16/17", "node": 3634, "naklon": 0 }, +{ "label": "16/18", "node": 3610, "naklon": 0 }, +{ "label": "16/19", "node": 3626, "naklon": 0 }, +{ "label": "16/20", "node": 3618, "naklon": 0 }, +{ "label": "16/21", "node": 3619, "naklon": 0 }, +{ "label": "16/22", "node": 3628, "naklon": 0 }, +{ "label": "16/23", "node": 3615, "naklon": 0 }, +{ "label": "16/24", "node": 3609, "naklon": 0 }, +{ "label": "16/25", "node": 3606, "naklon": 0 }, +{ "label": "16/26", "node": 3624, "naklon": 0 }, +{ "label": "16/27", "node": 3627, "naklon": 0 }, +{ "label": "16/28", "node": 3607, "naklon": 0 }, +{ "label": "16/29", "node": 4370, "naklon": 0 }, +{ "label": "16/30", "node": 3692, "naklon": 0 }, +{ "label": "16/31", "node": 3614, "naklon": 0 }, +{ "label": "16/32", "node": 3623, "naklon": 0 }, +{ "label": "16/33", "node": 4373, "naklon": 0 }, +{ "label": "16/34", "node": 3620, "naklon": 0 }, +{ "label": "16/35", "node": 3685, "naklon": 0 }, +{ "label": "16/36", "node": 3616, "naklon": 0 }, +{ "label": "16/37", "node": 3686, "naklon": 0 }, +{ "label": "16/38", "node": 3688, "naklon": 0 }, +{ "label": "16/39", "node": 3684, "naklon": 0 }, +{ "label": "16/40", "node": 3825, "naklon": 0 }, +{ "label": "16/41", "node": 3865, "naklon": 0 }, +{ "label": "16/42", "node": 3824, "naklon": 0 }, +{ "label": "16/43", "node": 3871, "naklon": 0 }, +{ "label": "16/44", "node": 3801, "naklon": 0 }, +{ "label": "16/45", "node": 3862, "naklon": 0 }, +{ "label": "16/46", "node": 3876, "naklon": 0 }, +{ "label": "16/47", "node": 3861, "naklon": 0 }, +{ "label": "16/48", "node": 4215, "naklon": 0 }, +{ "label": "16/49", "node": 3605, "naklon": 10 }, +{ "label": "16/50", "node": 3603, "naklon": 10 }, +{ "label": "16/51", "node": 3592, "naklon": 10 }, +{ "label": "16/52", "node": 3598, "naklon": 10 }, +{ "label": "16/53", "node": 3594, "naklon": 10 }, +{ "label": "16/54", "node": 3593, "naklon": 10 }, +{ "label": "16/55", "node": 3630, "naklon": 10 }, +{ "label": "16/56", "node": 3763, "naklon": 10 }, +{ "label": "16/57", "node": 3746, "naklon": 10 }, +{ "label": "16/58", "node": 3699, "naklon": 0 }, +{ "label": "16/59", "node": 3698, "naklon": 0 }, +{ "label": "16/60", "node": 3709, "naklon": null }, +{ "label": "16/61", "node": 3708, "naklon": 0 }, +{ "label": "16/62", "node": 3703, "naklon": null }, +{ "label": "16/63", "node": 3700, "naklon": 0 }, +{ "label": "16/64", "node": 3701, "naklon": null }, +{ "label": "16/65", "node": 3704, "naklon": 0 }, +{ "label": "16/66", "node": 3707, "naklon": null }, +{ "label": "16/67", "node": 3810, "naklon": 0 }, +{ "label": "16/68", "node": 4208, "naklon": null }, +{ "label": "16/69", "node": 3867, "naklon": 0 }, +{ "label": "16/70", "node": 4372, "naklon": null }, +{ "label": "16/71", "node": 3881, "naklon": 0 }, +{ "label": "16/72", "node": 4204, "naklon": null }, +{ "label": "16/73", "node": 3869, "naklon": 0 }, +{ "label": "16/74", "node": 4202, "naklon": null }, +{ "label": "16/75", "node": 3830, "naklon": 0 }, +{ "label": "16/76", "node": 3870, "naklon": null }, +{ "label": "16/77", "node": 3964, "naklon": 0 }, +{ "label": "16/78", "node": 3849, "naklon": 0 }, +{ "label": "16/79", "node": 3694, "naklon": null }, +{ "label": "16/80", "node": 3717, "naklon": 0 }, +{ "label": "16/81", "node": 3877, "naklon": null }, +{ "label": "16/82", "node": 3755, "naklon": 0 }, +{ "label": "16/83", "node": 3725, "naklon": null }, +{ "label": "16/84", "node": 3716, "naklon": 0 }, +{ "label": "16/85", "node": 3696, "naklon": null }, +{ "label": "16/86", "node": 3702, "naklon": 0 }, +{ "label": "16/87", "node": 3706, "naklon": null }, +{ "label": "16/88", "node": 3850, "naklon": 0 }, +{ "label": "16/89", "node": 3848, "naklon": null }, +{ "label": "16/90", "node": 3737, "naklon": null }, +{ "label": "16/91", "node": 3705, "naklon": 0 }, +{ "label": "16/92", "node": 3723, "naklon": null }, +{ "label": "16/93", "node": 3842, "naklon": 0 }, +{ "label": "16/94", "node": 3735, "naklon": null }, +{ "label": "16/95", "node": 3719, "naklon": 0 }, +{ "label": "16/96", "node": 3697, "naklon": 0 }, +{ "label": "16/97", "node": 3711, "naklon": 0 }, +{ "label": "16/98", "node": 4107, "naklon": null }, +{ "label": "16/99", "node": 4112, "naklon": 5 }, +{ "label": "16/100", "node": 4106, "naklon": 5 }, +{ "label": "16/101", "node": 4111, "naklon": 5 }, +{ "label": "16/102", "node": 4091, "naklon": null }, +{ "label": "16/103", "node": 4104, "naklon": 5 }, +{ "label": "16/104", "node": 4094, "naklon": null }, +{ "label": "16/105", "node": 4089, "naklon": 5 }, +{ "label": "16/106", "node": 4095, "naklon": null }, +{ "label": "16/107", "node": 4102, "naklon": 5 }, +{ "label": "16/108", "node": 4105, "naklon": null }, +{ "label": "16/109", "node": 3859, "naklon": null }, +{ "label": "16/110", "node": 4090, "naklon": 5 }, +{ "label": "16/111", "node": 4110, "naklon": null }, +{ "label": "16/112", "node": 4097, "naklon": 5 }, +{ "label": "16/113", "node": 4099, "naklon": null }, +{ "label": "16/114", "node": 4096, "naklon": null }, +{ "label": "16/115", "node": 4101, "naklon": 5 }, +{ "label": "16/116", "node": 4109, "naklon": null }, +{ "label": "16/117", "node": 4092, "naklon": 5 }, +{ "label": "16/118", "node": 3631, "naklon": null }, +{ "label": "16/119", "node": 3632, "naklon": 0 }, +{ "label": "16/120", "node": 3641, "naklon": null }, +{ "label": "16/121", "node": 3638, "naklon": 0 }, +{ "label": "16/122", "node": 3637, "naklon": null }, +{ "label": "16/123", "node": 4142, "naklon": null }, +{ "label": "16/124", "node": 4147, "naklon": 5 }, +{ "label": "16/125", "node": 4139, "naklon": 5 }, +{ "label": "20/30A", "node": 3172, "naklon": 2 }, +{ "label": "20/30B", "node": 3164, "naklon": 2 }, +{ "label": "20/1", "node": 3247, "naklon": 10 }, +{ "label": "20/2", "node": 3296, "naklon": 10 }, +{ "label": "20/3", "node": 3246, "naklon": 10 }, +{ "label": "20/4", "node": 3270, "naklon": 10 }, +{ "label": "20/5", "node": 3294, "naklon": 10 }, +{ "label": "20/6", "node": 3298, "naklon": 10 }, +{ "label": "20/7", "node": 3297, "naklon": 10 }, +{ "label": "20/8", "node": 3293, "naklon": 10 }, +{ "label": "20/9", "node": 3299, "naklon": 10 }, +{ "label": "20/10", "node": 3295, "naklon": 10 }, +{ "label": "20/11", "node": 3244, "naklon": 10 }, +{ "label": "20/12", "node": 3249, "naklon": 10 }, +{ "label": "20/13", "node": 3268, "naklon": 10 }, +{ "label": "20/14", "node": 3245, "naklon": 10 }, +{ "label": "20/15", "node": 3278, "naklon": 10 }, +{ "label": "20/16", "node": 3280, "naklon": 10 }, +{ "label": "20/17", "node": 3292, "naklon": 10 }, +{ "label": "20/18", "node": 3287, "naklon": 10 }, +{ "label": "20/19", "node": 3282, "naklon": 10 }, +{ "label": "20/20", "node": 3273, "naklon": 0 }, +{ "label": "20/21", "node": 3157, "naklon": 0 }, +{ "label": "20/22", "node": 3283, "naklon": 0 }, +{ "label": "20/23", "node": 3159, "naklon": 0 }, +{ "label": "20/24", "node": 3289, "naklon": 0 }, +{ "label": "20/25", "node": 3163, "naklon": 0 }, +{ "label": "20/26", "node": 3126, "naklon": 0 }, +{ "label": "20/27", "node": 3171, "naklon": 0 }, +{ "label": "20/28", "node": 3162, "naklon": 0 }, +{ "label": "20/29", "node": 3279, "naklon": 10 }, +{ "label": "20/31", "node": 3173, "naklon": 0 }, +{ "label": "20/32", "node": 3127, "naklon": 0 }, +{ "label": "20/33", "node": 3131, "naklon": 0 }, +{ "label": "20/34", "node": 3129, "naklon": 0 }, +{ "label": "20/35", "node": 3276, "naklon": 2 }, +{ "label": "20/36", "node": 3290, "naklon": 2 }, +{ "label": "20/37", "node": 3132, "naklon": 0 }, +{ "label": "20/38", "node": 3138, "naklon": 0 }, +{ "label": "20/39", "node": 3272, "naklon": 0 }, +{ "label": "20/40", "node": 3291, "naklon": 0 }, +{ "label": "20/41", "node": 3277, "naklon": 10 }, +{ "label": "20/42", "node": 3286, "naklon": 10 }, +{ "label": "20/43", "node": 3281, "naklon": 10 }, +{ "label": "20/44", "node": 3288, "naklon": 10 }, +{ "label": "20/45", "node": 3284, "naklon": 10 }, +{ "label": "20/46", "node": 3167, "naklon": 10 }, +{ "label": "20/47", "node": 3872, "naklon": 0 }, +{ "label": "20/48", "node": 3124, "naklon": 0 }, +{ "label": "20/49", "node": 3133, "naklon": 0 }, +{ "label": "20/50", "node": 3158, "naklon": 0 }, +{ "label": "20/51", "node": 3169, "naklon": 0 }, +{ "label": "20/52", "node": 3146, "naklon": 0 }, +{ "label": "20/53", "node": 3160, "naklon": 0 }, +{ "label": "20/54", "node": 3248, "naklon": 0 }, +{ "label": "20/55", "node": 3156, "naklon": 0 }, +{ "label": "20/56", "node": 3161, "naklon": 0 }, +{ "label": "20/57", "node": 3170, "naklon": 0 }, +{ "label": "20/58", "node": 3168, "naklon": 0 }, +{ "label": "20/59", "node": 3125, "naklon": 0 }, +{ "label": "20/60", "node": 3166, "naklon": 0 }, +{ "label": "20/61", "node": 3130, "naklon": 0 }, +{ "label": "20/62", "node": 3563, "naklon": 0 }, +{ "label": "20/63", "node": 3550, "naklon": null }, +{ "label": "20/67", "node": 3269, "naklon": 0 }, +{ "label": "21/1", "node": 2921, "naklon": 0 }, +{ "label": "21/2", "node": 2707, "naklon": 0 }, +{ "label": "21/3", "node": 2723, "naklon": 0 }, +{ "label": "21/4", "node": 2716, "naklon": 0 }, +{ "label": "21/5", "node": 2717, "naklon": 0 }, +{ "label": "21/6", "node": 2720, "naklon": 0 }, +{ "label": "21/7", "node": 2722, "naklon": 0 }, +{ "label": "21/8", "node": 2718, "naklon": 0 }, +{ "label": "21/9", "node": 2724, "naklon": 0 }, +{ "label": "21/10", "node": 2742, "naklon": 0 }, +{ "label": "21/11", "node": 2743, "naklon": 0 }, +{ "label": "21/12", "node": 2733, "naklon": 0 }, +{ "label": "21/14", "node": 2903, "naklon": 0 }, +{ "label": "21/15", "node": 2917, "naklon": 0 }, +{ "label": "21/16", "node": 2897, "naklon": 0 }, +{ "label": "21/17", "node": 2914, "naklon": 0 }, +{ "label": "21/18", "node": 2898, "naklon": 0 }, +{ "label": "21/19", "node": 2773, "naklon": 0 }, +{ "label": "21/20", "node": 2895, "naklon": 0 }, +{ "label": "21/21", "node": 2896, "naklon": 0 }, +{ "label": "21/22", "node": 2771, "naklon": 0 }, +{ "label": "21/23", "node": 2772, "naklon": 0 }, +{ "label": "21/24", "node": 2793, "naklon": 0 }, +{ "label": "21/25", "node": 2902, "naklon": 0 }, +{ "label": "21/26", "node": 2910, "naklon": 0 }, +{ "label": "21/27", "node": 2909, "naklon": 0 }, +{ "label": "21/28", "node": 2920, "naklon": 0 }, +{ "label": "21/29", "node": 2916, "naklon": 0 }, +{ "label": "21/30", "node": 2904, "naklon": 0 }, +{ "label": "21/31", "node": 2915, "naklon": 0 }, +{ "label": "21/32", "node": 2905, "naklon": 0 }, +{ "label": "21/33", "node": 2900, "naklon": 0 }, +{ "label": "21/34", "node": 2899, "naklon": 0 }, +{ "label": "21/36", "node": 2741, "naklon": 0 }, +{ "label": "21/37", "node": 2714, "naklon": 0 }, +{ "label": "21/38", "node": 2701, "naklon": 0 }, +{ "label": "21/39", "node": 2703, "naklon": 0 }, +{ "label": "21/40", "node": 2704, "naklon": 0 }, +{ "label": "21/41", "node": 2702, "naklon": 0 }, +{ "label": "21/42", "node": 2706, "naklon": 0 }, +{ "label": "21/43", "node": 2776, "naklon": 0 }, +{ "label": "21/44", "node": 2770, "naklon": 0 }, +{ "label": "21/45", "node": 2786, "naklon": 0 }, +{ "label": "21/46", "node": 2779, "naklon": 0 }, +{ "label": "21/47", "node": 2782, "naklon": 0 }, +{ "label": "21/48", "node": 2785, "naklon": 0 }, +{ "label": "21/49", "node": 2769, "naklon": 0 }, +{ "label": "21/50", "node": 3354, "naklon": 0 }, +{ "label": "21/51", "node": 2778, "naklon": 0 }, +{ "label": "21/52", "node": 2775, "naklon": 0 }, +{ "label": "21/53", "node": 2780, "naklon": 0 }, +{ "label": "21/54", "node": 2790, "naklon": 0 }, +{ "label": "21/55", "node": 2792, "naklon": 0 }, +{ "label": "21/56", "node": 2774, "naklon": 0 }, +{ "label": "22/1", "node": 2630, "naklon": 0 }, +{ "label": "22/2", "node": 2631, "naklon": 0 }, +{ "label": "22/3", "node": 2632, "naklon": 0 }, +{ "label": "22/4", "node": 2633, "naklon": 0 }, +{ "label": "22/5", "node": 2634, "naklon": 0 }, +{ "label": "22/6", "node": 2636, "naklon": 0 }, +{ "label": "22/7", "node": 4367, "naklon": 0 }, +{ "label": "22/8", "node": 2637, "naklon": 0 }, +{ "label": "22/9", "node": 2638, "naklon": 0 }, +{ "label": "22/10", "node": 2639, "naklon": 0 }, +{ "label": "22/11", "node": 2640, "naklon": 0 }, +{ "label": "22/12", "node": 2641, "naklon": 0 }, +{ "label": "22/13", "node": 2642, "naklon": 0 }, +{ "label": "22/14", "node": 2643, "naklon": 0 }, +{ "label": "22/15", "node": 2644, "naklon": 0 }, +{ "label": "22/16", "node": 2645, "naklon": 0 }, +{ "label": "22/17", "node": 2646, "naklon": 0 }, +{ "label": "22/18", "node": 2647, "naklon": 0 }, +{ "label": "22/19", "node": 2648, "naklon": 0 }, +{ "label": "22/20", "node": 2649, "naklon": 0 }, +{ "label": "22/21", "node": 2650, "naklon": 0 }, +{ "label": "22/22", "node": 2651, "naklon": 0 }, +{ "label": "22/23", "node": 4103, "naklon": 0 }, +{ "label": "22/24", "node": 2653, "naklon": 0 }, +{ "label": "22/25", "node": 2654, "naklon": 0 }, +{ "label": "22/26", "node": 2655, "naklon": 0 }, +{ "label": "22/27", "node": 2656, "naklon": 0 }, +{ "label": "22/28", "node": 2657, "naklon": 0 }, +{ "label": "22/29", "node": 2658, "naklon": 0 }, +{ "label": "22/30", "node": 2659, "naklon": 0 }, +{ "label": "22/31", "node": 2660, "naklon": 0 }, +{ "label": "22/32", "node": 2661, "naklon": 0 }, +{ "label": "22/32/1", "node": 3015, "naklon": 0 }, +{ "label": "22/33", "node": 2662, "naklon": 0 }, +{ "label": "22/34", "node": 2663, "naklon": 0 }, +{ "label": "22/35", "node": 2664, "naklon": 0 }, +{ "label": "22/36", "node": 2665, "naklon": 0 }, +{ "label": "22/37", "node": 2666, "naklon": 0 }, +{ "label": "22/38", "node": 2667, "naklon": 0 }, +{ "label": "22/39", "node": 2668, "naklon": 0 }, +{ "label": "22/40", "node": 2669, "naklon": null }, +{ "label": "22/41", "node": 2670, "naklon": null }, +{ "label": "22/42", "node": 2671, "naklon": null }, +{ "label": "23/9A", "node": 3087, "naklon": 10 }, +{ "label": "23/9B", "node": 3090, "naklon": 10 }, +{ "label": "23/1", "node": 3075, "naklon": 0 }, +{ "label": "23/2", "node": 3089, "naklon": 0 }, +{ "label": "23/3", "node": 3088, "naklon": 0 }, +{ "label": "23/4", "node": 3228, "naklon": 10 }, +{ "label": "23/5", "node": 2751, "naklon": 10 }, +{ "label": "23/6", "node": 3243, "naklon": 10 }, +{ "label": "23/7", "node": 4349, "naklon": 10 }, +{ "label": "23/8", "node": 3102, "naklon": 10 }, +{ "label": "23/10", "node": 3099, "naklon": 10 }, +{ "label": "23/11", "node": 3103, "naklon": 10 }, +{ "label": "23/12", "node": 3093, "naklon": 10 }, +{ "label": "23/13", "node": 3098, "naklon": 10 }, +{ "label": "23/14", "node": 3092, "naklon": 10 }, +{ "label": "23/15", "node": 3233, "naklon": 0 }, +{ "label": "23/16", "node": 3095, "naklon": 0 }, +{ "label": "23/17", "node": 4074, "naklon": 0 }, +{ "label": "23/18", "node": 2729, "naklon": 0 }, +{ "label": "23/19", "node": 3234, "naklon": 0 }, +{ "label": "23/20", "node": 3094, "naklon": 0 }, +{ "label": "23/21", "node": 2817, "naklon": 0 }, +{ "label": "23/22", "node": 3226, "naklon": 0 }, +{ "label": "23/23", "node": 3225, "naklon": 0 }, +{ "label": "23/24", "node": 3237, "naklon": 0 }, +{ "label": "23/25", "node": 4250, "naklon": 0 }, +{ "label": "23/26", "node": 3059, "naklon": 10 }, +{ "label": "23/27", "node": 3238, "naklon": 10 }, +{ "label": "23/28", "node": 3242, "naklon": 10 }, +{ "label": "23/29", "node": 3236, "naklon": 10 }, +{ "label": "23/30", "node": 3112, "naklon": 10 }, +{ "label": "23/31", "node": 3224, "naklon": 0 }, +{ "label": "23/32", "node": 4298, "naklon": 10 }, +{ "label": "23/33", "node": 4150, "naklon": 10 }, +{ "label": "23/34", "node": 3091, "naklon": 10 }, +{ "label": "25/1", "node": 3771, "naklon": 5 }, +{ "label": "25/2", "node": 3777, "naklon": 5 }, +{ "label": "25/3", "node": 3749, "naklon": 5 }, +{ "label": "25/4", "node": 3769, "naklon": 5 }, +{ "label": "25/5", "node": 3765, "naklon": 5 }, +{ "label": "25/6", "node": 3785, "naklon": 5 }, +{ "label": "25/7", "node": 3761, "naklon": 5 }, +{ "label": "25/8", "node": 3758, "naklon": 5 }, +{ "label": "25/9", "node": 3766, "naklon": 5 }, +{ "label": "25/10", "node": 3779, "naklon": 5 }, +{ "label": "25/11", "node": 3899, "naklon": 10 }, +{ "label": "25/12", "node": 3922, "naklon": 10 }, +{ "label": "25/13", "node": 3912, "naklon": 10 }, +{ "label": "25/14", "node": 3933, "naklon": 10 }, +{ "label": "25/15", "node": 3921, "naklon": 10 }, +{ "label": "25/16", "node": 4300, "naklon": 10 }, +{ "label": "25/17", "node": 3927, "naklon": 10 }, +{ "label": "25/18", "node": 3212, "naklon": 10 }, +{ "label": "25/19", "node": 3208, "naklon": 10 }, +{ "label": "25/20", "node": 3207, "naklon": 10 }, +{ "label": "25/21", "node": 4294, "naklon": 10 }, +{ "label": "25/22", "node": 3209, "naklon": 10 }, +{ "label": "25/23", "node": 3745, "naklon": 10 }, +{ "label": "25/24", "node": 3762, "naklon": 10 }, +{ "label": "25/25", "node": 3215, "naklon": 10 }, +{ "label": "25/26", "node": 3210, "naklon": 10 }, +{ "label": "25/27", "node": 3211, "naklon": 10 }, +{ "label": "25/28", "node": 3206, "naklon": 10 }, +{ "label": "25/29", "node": 3918, "naklon": 5 }, +{ "label": "25/30", "node": 3928, "naklon": 5 }, +{ "label": "25/31", "node": 3917, "naklon": 5 }, +{ "label": "25/32", "node": 4029, "naklon": 0 }, +{ "label": "25/33", "node": 4038, "naklon": 0 }, +{ "label": "25/34", "node": 4022, "naklon": 0 }, +{ "label": "25/35", "node": 3937, "naklon": 0 }, +{ "label": "25/36", "node": 3190, "naklon": 0 }, +{ "label": "25/37", "node": 3835, "naklon": 0 }, +{ "label": "25/38", "node": 3201, "naklon": 0 }, +{ "label": "25/39", "node": 3193, "naklon": 0 }, +{ "label": "25/40", "node": 3191, "naklon": 0 }, +{ "label": "25/41", "node": 3203, "naklon": 0 }, +{ "label": "25/42", "node": 4301, "naklon": 0 }, +{ "label": "25/43", "node": 3223, "naklon": 0 }, +{ "label": "25/44", "node": 3202, "naklon": 0 }, +{ "label": "25/45", "node": 3205, "naklon": 0 }, +{ "label": "25/46", "node": 3194, "naklon": 0 }, +{ "label": "25/47", "node": 3198, "naklon": 0 }, +{ "label": "25/48", "node": 3204, "naklon": 0 }, +{ "label": "25/49", "node": 3200, "naklon": 0 }, +{ "label": "25/50", "node": 3216, "naklon": 0 }, +{ "label": "25/51", "node": 3932, "naklon": 5 }, +{ "label": "25/52", "node": 3923, "naklon": 5 }, +{ "label": "25/53", "node": 3913, "naklon": 5 }, +{ "label": "25/54", "node": 3900, "naklon": 5 }, +{ "label": "25/55", "node": 4189, "naklon": 10 }, +{ "label": "25/56", "node": 4191, "naklon": 10 }, +{ "label": "25/57", "node": 3790, "naklon": 10 }, +{ "label": "25/58", "node": 4190, "naklon": 10 }, +{ "label": "25/59", "node": 4302, "naklon": 0 }, +{ "label": "25/60", "node": 4351, "naklon": 0 }, +{ "label": "25/61", "node": 4075, "naklon": 0 }, +{ "label": "25/62", "node": 4071, "naklon": 0 }, +{ "label": "25/63", "node": 3784, "naklon": 0 }, +{ "label": "25/64", "node": 4065, "naklon": 0 }, +{ "label": "25/65", "node": 4297, "naklon": 0 }, +{ "label": "25/66", "node": 4295, "naklon": 0 }, +{ "label": "25/67", "node": 4299, "naklon": 0 }, +{ "label": "25/68", "node": 3772, "naklon": 0 }, +{ "label": "25/69", "node": 3941, "naklon": 0 }, +{ "label": "25/70", "node": 3782, "naklon": 0 }, +{ "label": "25/71", "node": 4068, "naklon": 0 }, +{ "label": "25/72", "node": 4073, "naklon": 0 }, +{ "label": "25/73", "node": 3901, "naklon": 5 }, +{ "label": "25/74", "node": 4296, "naklon": 5 }, +{ "label": "25/75", "node": 3910, "naklon": 5 }, +{ "label": "25/76", "node": 4293, "naklon": 5 }, +{ "label": "25/77", "node": 3919, "naklon": 5 }, +{ "label": "25/78", "node": 3924, "naklon": 5 }, +{ "label": "25/79", "node": 3909, "naklon": 5 }, +{ "label": "25/80", "node": 3896, "naklon": 5 }, +{ "label": "25/81", "node": 3911, "naklon": 5 }, +{ "label": "25/82", "node": 2819, "naklon": 15 }, +{ "label": "25/83", "node": 3776, "naklon": 15 }, +{ "label": "25/84", "node": 3752, "naklon": 15 }, +{ "label": "25/85", "node": 4353, "naklon": 15 }, +{ "label": "25/86", "node": 3791, "naklon": 0 }, +{ "label": "25/87", "node": 3770, "naklon": 0 }, +{ "label": "25/88", "node": 3760, "naklon": 0 }, +{ "label": "25/89", "node": 3115, "naklon": 0 }, +{ "label": "25/90", "node": 3738, "naklon": 0 }, +{ "label": "25/91", "node": 3748, "naklon": 0 }, +{ "label": "25/92", "node": 3753, "naklon": 0 }, +{ "label": "25/93", "node": 3775, "naklon": 0 }, +{ "label": "25/94", "node": 3778, "naklon": 5 }, +{ "label": "25/95", "node": 4078, "naklon": 5 }, +{ "label": "25/96", "node": 4088, "naklon": 5 }, +{ "label": "25/97", "node": 3856, "naklon": 5 }, +{ "label": "25/98", "node": 4084, "naklon": 5 }, +{ "label": "25/99", "node": 4069, "naklon": 5 }, +{ "label": "25/100", "node": 4188, "naklon": 5 }, +{ "label": "25/101", "node": 4064, "naklon": 5 }, +{ "label": "25/102", "node": 3792, "naklon": 5 }, +{ "label": "25/103", "node": 3780, "naklon": 5 }, +{ "label": "25/104", "node": 4034, "naklon": 5 }, +{ "label": "25/105", "node": 4072, "naklon": 5 }, +{ "label": "25/106", "node": 3884, "naklon": 5 }, +{ "label": "25/107", "node": 3793, "naklon": 5 }, +{ "label": "25/108", "node": 3863, "naklon": 5 }, +{ "label": "25/109", "node": 3855, "naklon": 5 }, +{ "label": "33/1", "node": 3846, "naklon": 0 }, +{ "label": "33/2", "node": 3943, "naklon": 0 }, +{ "label": "33/3", "node": 3903, "naklon": 0 }, +{ "label": "33/4", "node": 3982, "naklon": 0 }, +{ "label": "33/5", "node": 3879, "naklon": 0 }, +{ "label": "33/6", "node": 3887, "naklon": 0 }, +{ "label": "33/7", "node": 3920, "naklon": 5 }, +{ "label": "33/8", "node": 3942, "naklon": 5 }, +{ "label": "33/9", "node": 3829, "naklon": null }, +{ "label": "34/79A", "node": 3452, "naklon": 6 }, +{ "label": "34/79B", "node": 3460, "naklon": 6 }, +{ "label": "34/90A", "node": 3443, "naklon": 6 }, +{ "label": "34/90B", "node": 3445, "naklon": 6 }, +{ "label": "34/90C", "node": 3457, "naklon": 6 }, +{ "label": "34/97A", "node": 3461, "naklon": 6 }, +{ "label": "34/97B", "node": 3463, "naklon": 6 }, +{ "label": "34/98A", "node": 3426, "naklon": 6 }, +{ "label": "34/98B", "node": 3444, "naklon": 6 }, +{ "label": "34/99A", "node": 3453, "naklon": 6 }, +{ "label": "34/99B", "node": 3455, "naklon": 6 }, +{ "label": "34/1", "node": 4009, "naklon": 0 }, +{ "label": "34/2", "node": 3602, "naklon": 0 }, +{ "label": "34/3", "node": 3441, "naklon": 0 }, +{ "label": "34/4", "node": 3464, "naklon": 0 }, +{ "label": "34/5", "node": 3883, "naklon": 0 }, +{ "label": "34/6", "node": 4098, "naklon": 0 }, +{ "label": "34/7", "node": 4003, "naklon": 0 }, +{ "label": "34/8", "node": 4004, "naklon": 0 }, +{ "label": "34/9", "node": 3888, "naklon": 0 }, +{ "label": "34/10", "node": 3997, "naklon": 0 }, +{ "label": "34/11", "node": 4006, "naklon": 0 }, +{ "label": "34/12", "node": 4000, "naklon": 0 }, +{ "label": "34/13", "node": 4011, "naklon": 0 }, +{ "label": "34/14", "node": 3999, "naklon": 0 }, +{ "label": "34/15", "node": 3981, "naklon": 0 }, +{ "label": "34/16", "node": 3988, "naklon": 0 }, +{ "label": "34/17", "node": 3986, "naklon": 0 }, +{ "label": "34/18", "node": 3998, "naklon": 0 }, +{ "label": "34/19", "node": 3983, "naklon": 0 }, +{ "label": "34/20", "node": 4005, "naklon": 0 }, +{ "label": "34/21", "node": 4001, "naklon": 0 }, +{ "label": "34/22", "node": 4008, "naklon": 0 }, +{ "label": "34/23", "node": 4002, "naklon": 0 }, +{ "label": "34/24", "node": 3996, "naklon": 0 }, +{ "label": "34/25", "node": 4007, "naklon": 0 }, +{ "label": "34/26", "node": 4113, "naklon": 15 }, +{ "label": "34/27", "node": 3595, "naklon": 5 }, +{ "label": "34/28", "node": 3599, "naklon": 5 }, +{ "label": "34/29", "node": 3601, "naklon": 5 }, +{ "label": "34/30", "node": 4205, "naklon": 0 }, +{ "label": "34/31", "node": 3987, "naklon": null }, +{ "label": "34/32", "node": 4214, "naklon": 0 }, +{ "label": "34/33", "node": 4226, "naklon": 0 }, +{ "label": "34/34", "node": 4209, "naklon": 0 }, +{ "label": "34/35", "node": 4201, "naklon": 0 }, +{ "label": "34/36", "node": 3440, "naklon": 0 }, +{ "label": "34/37", "node": 3465, "naklon": 0 }, +{ "label": "34/38", "node": 3446, "naklon": 0 }, +{ "label": "34/39", "node": 4039, "naklon": 5 }, +{ "label": "34/40", "node": 4057, "naklon": 5 }, +{ "label": "34/41", "node": 3985, "naklon": 0 }, +{ "label": "34/42", "node": 3882, "naklon": 0 }, +{ "label": "34/43", "node": 4040, "naklon": 5 }, +{ "label": "34/44", "node": 3231, "naklon": 0 }, +{ "label": "34/45", "node": 3227, "naklon": 0 }, +{ "label": "34/46", "node": 3431, "naklon": 0 }, +{ "label": "34/47", "node": 4013, "naklon": 0 }, +{ "label": "34/48", "node": 4045, "naklon": 0 }, +{ "label": "34/49", "node": 3949, "naklon": 0 }, +{ "label": "34/50", "node": 3953, "naklon": 0 }, +{ "label": "34/51", "node": 3952, "naklon": 0 }, +{ "label": "34/52", "node": 3995, "naklon": 0 }, +{ "label": "34/53", "node": 3992, "naklon": 0 }, +{ "label": "34/54", "node": 4198, "naklon": 0 }, +{ "label": "34/55", "node": 3935, "naklon": 0 }, +{ "label": "34/56", "node": 4050, "naklon": 0 }, +{ "label": "34/57", "node": 4049, "naklon": 0 }, +{ "label": "34/58", "node": 4054, "naklon": 0 }, +{ "label": "34/59", "node": 3663, "naklon": 6 }, +{ "label": "34/60", "node": 3661, "naklon": 6 }, +{ "label": "34/61", "node": 3664, "naklon": 6 }, +{ "label": "34/62", "node": 3660, "naklon": 6 }, +{ "label": "34/63", "node": 3662, "naklon": 6 }, +{ "label": "34/65", "node": 3665, "naklon": 6 }, +{ "label": "34/66", "node": 3667, "naklon": 6 }, +{ "label": "34/67", "node": 3675, "naklon": 6 }, +{ "label": "34/68", "node": 3666, "naklon": 6 }, +{ "label": "34/69", "node": 3652, "naklon": 6 }, +{ "label": "34/70", "node": 3458, "naklon": 6 }, +{ "label": "34/70/1", "node": 4425, "naklon": 6 }, +{ "label": "34/71", "node": 3459, "naklon": 6 }, +{ "label": "34/72", "node": 3435, "naklon": 6 }, +{ "label": "34/73", "node": 3448, "naklon": 6 }, +{ "label": "34/74", "node": 3451, "naklon": 6 }, +{ "label": "34/75", "node": 3442, "naklon": 6 }, +{ "label": "34/76", "node": 3449, "naklon": 6 }, +{ "label": "34/77", "node": 3450, "naklon": 6 }, +{ "label": "34/78", "node": 3433, "naklon": 6 }, +{ "label": "34/80", "node": 3432, "naklon": 12 }, +{ "label": "34/81", "node": 3470, "naklon": 12 }, +{ "label": "34/82", "node": 3438, "naklon": 12 }, +{ "label": "34/83", "node": 3439, "naklon": 12 }, +{ "label": "34/84", "node": 4028, "naklon": 5 }, +{ "label": "34/85", "node": 3596, "naklon": 5 }, +{ "label": "34/86", "node": 4021, "naklon": 5 }, +{ "label": "34/87", "node": 3437, "naklon": 12 }, +{ "label": "34/88", "node": 3428, "naklon": 12 }, +{ "label": "34/89", "node": 3430, "naklon": 12 }, +{ "label": "34/91", "node": 3454, "naklon": 6 }, +{ "label": "34/92", "node": 3492, "naklon": 6 }, +{ "label": "34/93", "node": 3462, "naklon": 6 }, +{ "label": "34/94", "node": 3427, "naklon": 6 }, +{ "label": "34/95", "node": 3434, "naklon": 6 }, +{ "label": "34/96", "node": 3456, "naklon": 6 }, +{ "label": "34/98/1", "node": 4307, "naklon": 6 }, +{ "label": "35/1", "node": 3968, "naklon": 0 }, +{ "label": "35/2", "node": 3969, "naklon": 0 }, +{ "label": "35/3", "node": 3947, "naklon": 0 }, +{ "label": "35/4", "node": 3979, "naklon": 0 }, +{ "label": "35/5", "node": 3959, "naklon": 0 }, +{ "label": "35/6", "node": 3948, "naklon": 0 }, +{ "label": "35/7", "node": 3961, "naklon": 0 }, +{ "label": "35/8", "node": 3956, "naklon": 0 }, +{ "label": "35/9", "node": 3604, "naklon": 0 }, +{ "label": "35/10", "node": 3944, "naklon": 0 }, +{ "label": "35/11", "node": 3960, "naklon": 0 }, +{ "label": "35/12", "node": 3958, "naklon": 0 }, +{ "label": "35/13", "node": 4036, "naklon": 5 }, +{ "label": "35/18", "node": 3893, "naklon": 5 }, +{ "label": "35/19", "node": 4108, "naklon": 5 }, +{ "label": "35/20", "node": 4017, "naklon": 5 }, +{ "label": "35/21", "node": 3963, "naklon": 0 }, +{ "label": "35/22", "node": 3658, "naklon": 0 }, +{ "label": "35/23", "node": 3975, "naklon": 0 }, +{ "label": "35/24", "node": 3980, "naklon": 0 }, +{ "label": "35/25", "node": 4012, "naklon": 0 }, +{ "label": "35/26", "node": 3655, "naklon": 0 }, +{ "label": "35/27", "node": 3962, "naklon": 0 }, +{ "label": "35/28", "node": 3945, "naklon": 0 }, +{ "label": "35/29", "node": 3569, "naklon": 0 }, +{ "label": "35/30", "node": 3429, "naklon": 0 }, +{ "label": "35/31", "node": 3657, "naklon": 0 }, +{ "label": "35/32", "node": 3646, "naklon": 0 }, +{ "label": "35/33", "node": 3622, "naklon": 0 }, +{ "label": "35/34", "node": 3612, "naklon": 0 }, +{ "label": "35/35", "node": 3955, "naklon": 0 }, +{ "label": "35/37", "node": 3878, "naklon": 0 }, +{ "label": "35/38", "node": 3965, "naklon": 0 }, +{ "label": "35/39", "node": 3970, "naklon": 0 }, +{ "label": "35/40", "node": 3611, "naklon": 0 }, +{ "label": "35/41", "node": 2635, "naklon": 0 }, +{ "label": "35/42", "node": 3978, "naklon": 0 }, +{ "label": "35/43", "node": 4213, "naklon": 0 }, +{ "label": "35/44", "node": 3984, "naklon": 0 }, +{ "label": "35/45", "node": 4218, "naklon": 0 }, +{ "label": "35/46", "node": 3973, "naklon": 0 }, +{ "label": "35/47", "node": 3974, "naklon": 0 }, +{ "label": "35/48", "node": 3759, "naklon": 0 }, +{ "label": "35/49", "node": 3844, "naklon": 0 }, +{ "label": "35/50", "node": 3804, "naklon": 0 }, +{ "label": "35/51", "node": 3831, "naklon": 0 }, +{ "label": "35/52", "node": 3643, "naklon": 0 }, +{ "label": "35/53", "node": 3966, "naklon": 0 }, +{ "label": "35/54", "node": 3971, "naklon": 0 }, +{ "label": "35/55", "node": 3650, "naklon": 6 }, +{ "label": "35/56", "node": 3651, "naklon": 6 }, +{ "label": "35/57", "node": 3669, "naklon": 6 }, +{ "label": "35/58", "node": 3648, "naklon": 6 }, +{ "label": "35/59", "node": 3645, "naklon": 6 }, +{ "label": "35/60", "node": 3659, "naklon": 6 }, +{ "label": "35/61", "node": 3647, "naklon": 6 }, +{ "label": "35/62", "node": 3644, "naklon": 6 }, +{ "label": "35/63", "node": 3671, "naklon": 6 }, +{ "label": "35/64", "node": 3682, "naklon": 6 }, +{ "label": "35/65", "node": 3672, "naklon": 6 }, +{ "label": "35/66", "node": 3683, "naklon": 6 }, +{ "label": "35/67", "node": 3673, "naklon": 6 }, +{ "label": "35/68", "node": 3674, "naklon": 6 }, +{ "label": "35/69", "node": 3679, "naklon": 6 }, +{ "label": "35/70", "node": 3649, "naklon": 6 }, +{ "label": "35/71", "node": 3687, "naklon": 6 }, +{ "label": "35/72", "node": 3677, "naklon": 6 }, +{ "label": "35/73", "node": 3690, "naklon": 6 }, +{ "label": "35/74", "node": 3691, "naklon": 6 }, +{ "label": "35/75", "node": 3676, "naklon": 6 }, +{ "label": "35/76", "node": 3680, "naklon": 6 }, +{ "label": "35/77", "node": 3668, "naklon": 6 }, +{ "label": "35/78", "node": 3681, "naklon": 6 }, +{ "label": "35/79", "node": 3670, "naklon": 6 }, +{ "label": "35/80", "node": 3689, "naklon": 6 }, +{ "label": "35/81", "node": 3678, "naklon": 6 }, +{ "label": "35/82", "node": 3693, "naklon": 6 }, +{ "label": "35/83", "node": 3654, "naklon": null }, +{ "label": "36/1", "node": 4086, "naklon": 0 }, +{ "label": "36/2", "node": 4085, "naklon": 0 }, +{ "label": "36/3", "node": 4083, "naklon": 0 }, +{ "label": "36/4", "node": 4087, "naklon": 0 }, +{ "label": "36/5", "node": 4077, "naklon": 0 }, +{ "label": "36/6", "node": 4082, "naklon": 0 }, +{ "label": "36/7", "node": 4186, "naklon": 0 }, +{ "label": "36/8", "node": 4206, "naklon": 0 }, +{ "label": "36/9", "node": 4080, "naklon": 0 }, +{ "label": "36/10", "node": 4081, "naklon": 0 }, +{ "label": "36/11", "node": 4210, "naklon": 0 }, +{ "label": "36/12", "node": 4079, "naklon": 0 }, +{ "label": "36/13", "node": 4076, "naklon": 0 }, +{ "label": "36/14", "node": 3852, "naklon": 0 }, +{ "label": "36/15", "node": 2813, "naklon": 0 }, +{ "label": "36/16", "node": 4219, "naklon": 0 }, +{ "label": "37/1A", "node": 3104, "naklon": 15 }, +{ "label": "37/1B", "node": 3121, "naklon": 15 }, +{ "label": "37/2", "node": 3113, "naklon": 10 }, +{ "label": "37/3", "node": 3118, "naklon": 10 }, +{ "label": "37/4", "node": 3111, "naklon": 10 }, +{ "label": "37/5", "node": 4020, "naklon": 10 }, +{ "label": "37/6", "node": 3119, "naklon": 10 }, +{ "label": "37/7", "node": 3110, "naklon": 10 }, +{ "label": "37/8", "node": 3108, "naklon": 10 }, +{ "label": "37/12", "node": 3107, "naklon": 0 }, +{ "label": "37/13", "node": 3199, "naklon": 0 }, +{ "label": "37/14", "node": 3120, "naklon": 0 }, +{ "label": "37/15", "node": 3122, "naklon": 0 }, +{ "label": "37/16", "node": 3908, "naklon": 0 }, +{ "label": "37/17", "node": 3114, "naklon": 0 }, +{ "label": "37/18", "node": 3105, "naklon": 0 }, +{ "label": "37/19", "node": 3116, "naklon": 0 }, +{ "label": "37/20", "node": 3106, "naklon": 0 }, +{ "label": "37/21", "node": 2887, "naklon": 5 }, +{ "label": "37/22", "node": 2888, "naklon": 5 }, +{ "label": "37/23", "node": 2877, "naklon": 5 }, +{ "label": "37/24", "node": 2891, "naklon": 5 }, +{ "label": "37/25", "node": 2886, "naklon": 5 }, +{ "label": "37/26", "node": 2892, "naklon": 5 }, +{ "label": "37/27", "node": 2882, "naklon": 5 }, +{ "label": "37/28", "node": 2883, "naklon": 5 }, +{ "label": "37/29", "node": 2876, "naklon": 5 }, +{ "label": "37/30", "node": 3109, "naklon": 5 }, +{ "label": "37/31", "node": 4152, "naklon": 5 }, +{ "label": "37/32", "node": 3117, "naklon": 5 }, +{ "label": "37/33", "node": 2870, "naklon": 5 }, +{ "label": "37/34", "node": 2867, "naklon": 0 }, +{ "label": "37/35", "node": 2865, "naklon": 0 }, +{ "label": "37/36", "node": 3096, "naklon": 0 }, +{ "label": "37/37", "node": 2871, "naklon": 0 }, +{ "label": "37/38", "node": 2884, "naklon": 0 }, +{ "label": "37/39", "node": 2855, "naklon": 0 }, +{ "label": "37/40", "node": 2878, "naklon": 0 }, +{ "label": "37/41", "node": 2889, "naklon": 0 }, +{ "label": "37/42", "node": 2879, "naklon": 0 }, +{ "label": "37/43", "node": 2850, "naklon": 0 }, +{ "label": "37/44", "node": 2894, "naklon": 0 }, +{ "label": "37/45", "node": 2880, "naklon": 0 }, +{ "label": "37/46", "node": 2893, "naklon": 0 }, +{ "label": "37/47", "node": 2890, "naklon": 0 }, +{ "label": "37/48", "node": 4355, "naklon": 0 }, +{ "label": "37/49", "node": 2885, "naklon": 0 }, +{ "label": "37/50", "node": 2875, "naklon": 0 }, +{ "label": "38/30A", "node": 3486, "naklon": 5 }, +{ "label": "38/30B", "node": 3714, "naklon": 0 }, +{ "label": "38/32A", "node": 3483, "naklon": 5 }, +{ "label": "38/32B", "node": 3496, "naklon": 0 }, +{ "label": "38/35A", "node": 3487, "naklon": 5 }, +{ "label": "38/35B", "node": 3498, "naklon": 5 }, +{ "label": "38/38A", "node": 3578, "naklon": 5 }, +{ "label": "38/38B", "node": 3508, "naklon": 5 }, +{ "label": "38/59A", "node": 3787, "naklon": 5 }, +{ "label": "38/59B", "node": 3491, "naklon": 5 }, +{ "label": "38/1", "node": 3568, "naklon": null }, +{ "label": "38/2", "node": 3502, "naklon": 0 }, +{ "label": "38/3", "node": 3836, "naklon": 0 }, +{ "label": "38/4", "node": 3588, "naklon": 0 }, +{ "label": "38/5", "node": 3493, "naklon": 0 }, +{ "label": "38/6", "node": 3580, "naklon": 0 }, +{ "label": "38/7", "node": 3572, "naklon": 0 }, +{ "label": "38/8", "node": 3506, "naklon": 0 }, +{ "label": "38/9", "node": 3503, "naklon": 0 }, +{ "label": "38/10", "node": 3579, "naklon": 0 }, +{ "label": "38/11", "node": 3586, "naklon": 0 }, +{ "label": "38/12", "node": 3495, "naklon": 5 }, +{ "label": "38/13", "node": 3492, "naklon": 5 }, +{ "label": "38/14", "node": 3532, "naklon": 5 }, +{ "label": "38/15", "node": 3574, "naklon": 5 }, +{ "label": "38/16", "node": 4140, "naklon": 5 }, +{ "label": "38/17", "node": 3795, "naklon": 5 }, +{ "label": "38/18", "node": 3788, "naklon": 5 }, +{ "label": "38/19", "node": 3796, "naklon": 5 }, +{ "label": "38/20", "node": 3797, "naklon": 5 }, +{ "label": "38/21", "node": 3798, "naklon": 5 }, +{ "label": "38/22", "node": 3786, "naklon": 5 }, +{ "label": "38/23", "node": 4067, "naklon": 5 }, +{ "label": "38/24", "node": 3773, "naklon": 5 }, +{ "label": "38/25", "node": 3774, "naklon": 5 }, +{ "label": "38/26", "node": 3789, "naklon": 5 }, +{ "label": "38/27", "node": 3520, "naklon": null }, +{ "label": "38/29", "node": 3577, "naklon": 5 }, +{ "label": "38/31", "node": 3530, "naklon": null }, +{ "label": "38/33", "node": 3488, "naklon": 5 }, +{ "label": "38/34", "node": 3505, "naklon": 5 }, +{ "label": "38/36", "node": 3497, "naklon": 5 }, +{ "label": "38/37", "node": 3490, "naklon": 5 }, +{ "label": "38/39", "node": 3585, "naklon": 5 }, +{ "label": "38/40", "node": 3582, "naklon": 5 }, +{ "label": "38/41", "node": 3507, "naklon": 5 }, +{ "label": "38/42", "node": 3484, "naklon": 5 }, +{ "label": "38/43", "node": 3501, "naklon": 5 }, +{ "label": "38/44", "node": 3581, "naklon": 5 }, +{ "label": "38/45", "node": 4192, "naklon": 5 }, +{ "label": "38/46", "node": 3576, "naklon": 5 }, +{ "label": "38/47", "node": 3489, "naklon": 5 }, +{ "label": "38/48", "node": 3573, "naklon": 5 }, +{ "label": "38/49", "node": 3504, "naklon": 5 }, +{ "label": "38/50", "node": 3794, "naklon": 5 }, +{ "label": "38/51", "node": 3485, "naklon": 5 }, +{ "label": "38/52", "node": 3482, "naklon": 5 }, +{ "label": "38/53", "node": 3575, "naklon": 5 }, +{ "label": "38/54", "node": 3499, "naklon": 5 }, +{ "label": "38/55", "node": 3494, "naklon": 5 }, +{ "label": "38/56", "node": 3583, "naklon": 5 }, +{ "label": "38/57", "node": 3570, "naklon": 5 }, +{ "label": "38/58", "node": 3500, "naklon": 0 }, +{ "label": "38/63", "node": 3510, "naklon": null }, +{ "label": "38/64", "node": 3512, "naklon": null }, +{ "label": "38/67", "node": 3535, "naklon": null }, +{ "label": "38/68", "node": 3531, "naklon": null }, +{ "label": "38/69", "node": 3537, "naklon": null }, +{ "label": "39/1", "node": 3522, "naklon": 10 }, +{ "label": "39/2", "node": 4018, "naklon": 10 }, +{ "label": "39/3", "node": 4019, "naklon": 10 }, +{ "label": "39/4", "node": 4154, "naklon": 5 }, +{ "label": "39/5", "node": 3907, "naklon": 5 }, +{ "label": "39/6", "node": 4148, "naklon": 0 }, +{ "label": "39/7", "node": 4153, "naklon": 0 }, +{ "label": "39/8", "node": 3938, "naklon": 0 }, +{ "label": "39/9", "node": 3802, "naklon": 0 }, +{ "label": "39/10", "node": 4015, "naklon": 0 }, +{ "label": "39/11", "node": 3929, "naklon": 0 }, +{ "label": "39/12", "node": 3946, "naklon": 0 }, +{ "label": "39/13", "node": 4014, "naklon": 0 }, +{ "label": "39/14", "node": 4155, "naklon": 0 }, +{ "label": "39/15", "node": 4149, "naklon": 0 }, +{ "label": "39/16", "node": 3642, "naklon": 0 }, +{ "label": "39/17", "node": 3636, "naklon": 5 }, +{ "label": "39/18", "node": 3991, "naklon": 0 }, +{ "label": "39/19", "node": 3994, "naklon": 0 }, +{ "label": "39/20", "node": 3990, "naklon": 0 }, +{ "label": "39/21", "node": 3967, "naklon": 0 }, +{ "label": "39/22", "node": 3977, "naklon": 0 }, +{ "label": "39/23", "node": 3757, "naklon": 15 }, +{ "label": "39/24", "node": 3633, "naklon": 15 }, +{ "label": "39/25", "node": 3744, "naklon": 15 }, +{ "label": "39/26", "node": 4023, "naklon": 5 }, +{ "label": "39/27", "node": 3720, "naklon": 5 }, +{ "label": "39/28", "node": 3734, "naklon": 5 }, +{ "label": "39/29", "node": 3741, "naklon": 5 }, +{ "label": "39/30", "node": 3721, "naklon": 5 }, +{ "label": "39/31", "node": 3845, "naklon": 0 }, +{ "label": "39/32", "node": 3840, "naklon": 0 }, +{ "label": "39/33", "node": 3837, "naklon": null }, +{ "label": "39/34", "node": 3839, "naklon": 0 }, +{ "label": "41/1", "node": 3542, "naklon": null }, +{ "label": "41/2", "node": 3566, "naklon": null }, +{ "label": "41/3", "node": 3548, "naklon": null }, +{ "label": "41/4", "node": 3515, "naklon": null }, +{ "label": "41/5", "node": 3559, "naklon": null }, +{ "label": "41/6", "node": 3509, "naklon": null }, +{ "label": "41/7", "node": 3524, "naklon": null }, +{ "label": "41/8", "node": 3518, "naklon": null }, +{ "label": "41/9", "node": 3182, "naklon": null }, +{ "label": "41/10", "node": 3187, "naklon": null }, +{ "label": "41/11", "node": 3195, "naklon": 0 }, +{ "label": "41/12", "node": 3857, "naklon": 0 }, +{ "label": "41/13", "node": 3183, "naklon": 0 }, +{ "label": "41/14", "node": 3177, "naklon": 0 }, +{ "label": "41/15", "node": 3189, "naklon": 0 }, +{ "label": "41/16", "node": 3186, "naklon": 0 }, +{ "label": "42/1", "node": 3178, "naklon": 0 }, +{ "label": "42/2", "node": 3219, "naklon": 0 }, +{ "label": "42/3", "node": 3475, "naklon": 0 }, +{ "label": "42/4", "node": 3175, "naklon": 0 }, +{ "label": "42/5", "node": 3222, "naklon": 0 }, +{ "label": "42/6", "node": 3221, "naklon": 0 }, +{ "label": "42/7", "node": 3181, "naklon": 0 }, +{ "label": "42/8", "node": 3180, "naklon": 0 }, +{ "label": "42/9", "node": 3218, "naklon": 0 }, +{ "label": "42/10", "node": 3176, "naklon": 0 }, +{ "label": "42/11", "node": 3174, "naklon": 0 }, +{ "label": "42/12", "node": 3220, "naklon": 0 }, +{ "label": "42/13", "node": 3533, "naklon": null }, +{ "label": "42/14", "node": 3543, "naklon": null }, +{ "label": "42/15", "node": 3554, "naklon": null }, +{ "label": "42/16", "node": 3549, "naklon": null }, +{ "label": "43/1", "node": 2857, "naklon": 5 }, +{ "label": "43/2", "node": 2752, "naklon": 5 }, +{ "label": "43/3", "node": 2753, "naklon": 5 }, +{ "label": "43/4", "node": 3024, "naklon": 5 }, +{ "label": "43/5", "node": 2754, "naklon": 5 }, +{ "label": "43/6", "node": 4423, "naklon": 5 }, +{ "label": "43/7", "node": 4368, "naklon": 5 }, +{ "label": "43/8", "node": 2978, "naklon": 5 }, +{ "label": "43/9", "node": 2868, "naklon": 5 }, +{ "label": "43/10", "node": 4377, "naklon": 5 }, +{ "label": "43/11", "node": 2757, "naklon": 5 }, +{ "label": "43/12", "node": 2970, "naklon": 5 }, +{ "label": "43/13", "node": 2758, "naklon": 5 }, +{ "label": "43/14", "node": 4378, "naklon": 5 }, +{ "label": "43/15", "node": 2759, "naklon": 5 }, +{ "label": "43/16", "node": 4342, "naklon": 5 }, +{ "label": "43/17", "node": 3026, "naklon": null }, +{ "label": "43/18", "node": 2986, "naklon": null }, +{ "label": "43/19", "node": 4343, "naklon": null }, +{ "label": "43/20", "node": 2760, "naklon": null }, +{ "label": "43/21", "node": 4379, "naklon": null }, +{ "label": "43/22", "node": 2971, "naklon": null }, +{ "label": "43/23", "node": 2761, "naklon": null }, +{ "label": "43/24", "node": 2762, "naklon": null }, +{ "label": "43/25", "node": 4339, "naklon": null }, +{ "label": "43/26", "node": 4380, "naklon": null }, +{ "label": "43/27", "node": 2975, "naklon": null }, +{ "label": "43/28", "node": 3003, "naklon": null }, +{ "label": "43/29", "node": 4338, "naklon": null }, +{ "label": "43/30", "node": 3002, "naklon": null }, +{ "label": "43/31", "node": 4345, "naklon": null }, +{ "label": "43/32", "node": 2979, "naklon": null }, +{ "label": "43/33", "node": 2989, "naklon": null }, +{ "label": "43/34", "node": 2996, "naklon": null }, +{ "label": "43/35", "node": 2972, "naklon": null }, +{ "label": "43/36", "node": 2988, "naklon": null }, +{ "label": "43/37", "node": 4344, "naklon": null }, +{ "label": "43/38", "node": 3022, "naklon": null }, +{ "label": "43/39", "node": 4341, "naklon": null }, +{ "label": "43/40", "node": 2983, "naklon": null }, +{ "label": "43/41", "node": 2995, "naklon": null }, +{ "label": "43/42", "node": 2763, "naklon": null }, +{ "label": "43/43", "node": 2764, "naklon": null }, +{ "label": "43/44", "node": 2765, "naklon": null }, +{ "label": "43/45", "node": 2766, "naklon": null }, +{ "label": "43/46", "node": 2767, "naklon": null }, +{ "label": "43/47", "node": 2768, "naklon": null }, +{ "label": "43/48", "node": 3018, "naklon": null }, +{ "label": "43/49", "node": 2982, "naklon": null }, +{ "label": "43/50", "node": 3019, "naklon": 0 }, +{ "label": "43/51", "node": 3013, "naklon": null }, +{ "label": "43/52", "node": 3007, "naklon": null }, +{ "label": "43/53", "node": 2980, "naklon": null }, +{ "label": "43/54", "node": 3011, "naklon": null }, +{ "label": "43/55", "node": 2672, "naklon": null }, +{ "label": "43/56", "node": 2673, "naklon": null }, +{ "label": "43/57", "node": 2674, "naklon": null }, +{ "label": "43/58", "node": 2675, "naklon": null }, +{ "label": "43/59", "node": 2676, "naklon": null }, +{ "label": "43/60", "node": 2677, "naklon": null }, +{ "label": "43/61", "node": 2678, "naklon": null }, +{ "label": "43/62", "node": 2679, "naklon": null }, +{ "label": "43/63", "node": 2680, "naklon": null }, +{ "label": "43/64", "node": 2840, "naklon": null }, +{ "label": "43/65", "node": 2682, "naklon": null }, +{ "label": "43/66", "node": 2683, "naklon": null }, +{ "label": "43/67", "node": 2684, "naklon": 0 }, +{ "label": "43/68", "node": 2685, "naklon": null }, +{ "label": "43/69", "node": 2686, "naklon": null }, +{ "label": "43/70", "node": 2687, "naklon": null }, +{ "label": "43/71", "node": 2688, "naklon": null }, +{ "label": "43/72", "node": 2689, "naklon": null }, +{ "label": "43/73", "node": 2690, "naklon": null }, +{ "label": "43/74", "node": 2691, "naklon": null }, +{ "label": "43/75", "node": 2692, "naklon": null }, +{ "label": "43/76", "node": 2693, "naklon": 0 }, +{ "label": "43/77", "node": 2694, "naklon": null }, +{ "label": "43/78", "node": 2695, "naklon": null }, +{ "label": "43/79", "node": 2696, "naklon": 0 }, +{ "label": "43/80", "node": 2697, "naklon": null }, +{ "label": "43/81", "node": 2698, "naklon": 0 }, +{ "label": "43/82", "node": 2699, "naklon": null }, +{ "label": "43/83", "node": 2700, "naklon": 0 }, +{ "label": "43/84", "node": 2744, "naklon": null }, +{ "label": "43/85", "node": 2745, "naklon": 0 }, +{ "label": "43/86", "node": 2746, "naklon": null }, +{ "label": "43/87", "node": 2747, "naklon": 0 }, +{ "label": "43/88", "node": 2748, "naklon": null }, +{ "label": "43/89", "node": 2749, "naklon": 0 }, +{ "label": "43/90", "node": 2841, "naklon": null }, +{ "label": "45/1", "node": 4237, "naklon": 5 }, +{ "label": "45/2", "node": 4226, "naklon": 5 }, +{ "label": "45/3", "node": 4242, "naklon": 5 }, +{ "label": "45/4", "node": 4179, "naklon": 5 }, +{ "label": "45/5", "node": 4247, "naklon": 5 }, +{ "label": "45/6", "node": 4245, "naklon": 5 }, +{ "label": "45/7", "node": 3872, "naklon": 5 }, +{ "label": "45/8", "node": 4175, "naklon": 5 }, +{ "label": "45/9", "node": 4236, "naklon": 5 }, +{ "label": "45/10", "node": 4170, "naklon": 5 }, +{ "label": "45/11", "node": 4238, "naklon": 5 }, +{ "label": "45/12", "node": 4246, "naklon": 5 }, +{ "label": "45/13", "node": 4166, "naklon": 5 }, +{ "label": "45/14", "node": 4227, "naklon": 5 }, +{ "label": "45/15", "node": 4171, "naklon": 5 }, +{ "label": "45/16", "node": 4180, "naklon": 5 }, +{ "label": "45/17", "node": 4244, "naklon": 5 }, +{ "label": "45/18", "node": 4199, "naklon": 5 }, +{ "label": "45/19", "node": 4239, "naklon": 5 }, +{ "label": "45/20", "node": 4207, "naklon": 5 }, +{ "label": "45/21", "node": 4223, "naklon": 5 }, +{ "label": "45/22", "node": 4230, "naklon": 5 }, +{ "label": "45/23", "node": 4233, "naklon": 5 }, +{ "label": "45/24", "node": 4222, "naklon": 5 }, +{ "label": "45/25", "node": 4217, "naklon": 5 }, +{ "label": "45/26", "node": 4243, "naklon": 5 }, +{ "label": "45/27", "node": 4200, "naklon": 5 }, +{ "label": "45/28", "node": 4228, "naklon": 5 }, +{ "label": "45/29", "node": 4211, "naklon": 5 }, +{ "label": "45/30", "node": 4234, "naklon": 5 }, +{ "label": "45/31", "node": 4235, "naklon": 5 }, +{ "label": "45/32", "node": 4203, "naklon": 5 }, +{ "label": "45/33", "node": 4240, "naklon": 5 }, +{ "label": "45/34", "node": 4224, "naklon": 5 }, +{ "label": "45/35", "node": 4232, "naklon": 5 }, +{ "label": "45/36", "node": 4231, "naklon": 5 }, +{ "label": "45/37", "node": 4161, "naklon": 5 }, +{ "label": "45/38", "node": 4225, "naklon": 5 }, +{ "label": "45/39", "node": 4241, "naklon": 5 }, +{ "label": "45/40", "node": 4229, "naklon": 5 }, +{ "label": "45/41", "node": 4221, "naklon": 5 }, +{ "label": "45/42", "node": 4212, "naklon": 5 }, +{ "label": "45/43", "node": 4216, "naklon": 5 }, +{ "label": "45/44", "node": 3864, "naklon": null }, +{ "label": "46/1", "node": 3806, "naklon": 5 }, +{ "label": "46/2", "node": 3813, "naklon": 5 }, +{ "label": "46/3", "node": 3815, "naklon": 5 }, +{ "label": "46/4", "node": 3807, "naklon": 5 }, +{ "label": "46/5", "node": 3895, "naklon": 5 }, +{ "label": "46/6", "node": 3809, "naklon": 5 }, +{ "label": "46/7", "node": 3820, "naklon": 5 }, +{ "label": "46/8", "node": 3805, "naklon": 5 }, +{ "label": "46/9", "node": 3894, "naklon": 0 }, +{ "label": "46/10", "node": 4055, "naklon": 0 }, +{ "label": "46/11", "node": 3812, "naklon": 5 }, +{ "label": "46/12", "node": 3822, "naklon": 5 }, +{ "label": "46/13", "node": 3821, "naklon": 5 }, +{ "label": "46/14", "node": 3808, "naklon": 5 }, +{ "label": "46/15", "node": 3799, "naklon": 5 }, +{ "label": "46/16", "node": 3816, "naklon": 5 }, +{ "label": "46/17", "node": 3751, "naklon": 5 }, +{ "label": "46/18", "node": 3814, "naklon": 5 }, +{ "label": "46/19", "node": 4044, "naklon": 0 }, +{ "label": "46/20", "node": 3931, "naklon": 0 }, +{ "label": "46/21", "node": 3902, "naklon": 5 }, +{ "label": "46/22", "node": 3916, "naklon": 5 }, +{ "label": "46/23", "node": 3892, "naklon": 5 }, +{ "label": "46/24", "node": 3914, "naklon": 5 }, +{ "label": "46/25", "node": 3898, "naklon": 5 }, +{ "label": "46/26", "node": 3897, "naklon": 5 }, +{ "label": "46/27", "node": 3885, "naklon": 5 }, +{ "label": "46/28", "node": 3906, "naklon": 5 }, +{ "label": "46/29", "node": 3930, "naklon": 0 }, +{ "label": "46/30", "node": 3936, "naklon": 0 }, +{ "label": "46/31", "node": 3860, "naklon": 5 }, +{ "label": "46/32", "node": 3841, "naklon": 5 }, +{ "label": "46/33", "node": 3873, "naklon": 5 }, +{ "label": "46/34", "node": 3854, "naklon": 5 }, +{ "label": "46/35", "node": 3939, "naklon": 5 }, +{ "label": "46/36", "node": 3858, "naklon": 5 }, +{ "label": "46/37", "node": 3940, "naklon": 5 }, +{ "label": "46/38", "node": 4035, "naklon": 5 }, +{ "label": "47/1", "node": 3373, "naklon": 0 }, +{ "label": "47/2", "node": 3374, "naklon": 0 }, +{ "label": "47/3", "node": 3384, "naklon": 0 }, +{ "label": "47/4", "node": 3385, "naklon": 0 }, +{ "label": "48/1", "node": 4051, "naklon": 5 }, +{ "label": "48/2", "node": 4041, "naklon": 5 }, +{ "label": "48/3", "node": 4056, "naklon": 5 }, +{ "label": "48/4", "node": 3875, "naklon": 5 }, +{ "label": "48/5", "node": 4061, "naklon": 5 }, +{ "label": "48/6", "node": 4047, "naklon": 5 }, +{ "label": "48/7", "node": 4060, "naklon": 5 }, +{ "label": "48/8", "node": 4059, "naklon": 5 }, +{ "label": "48/9", "node": 4058, "naklon": 5 }, +{ "label": "48/10", "node": 3635, "naklon": 5 }, +{ "label": "48/11", "node": 3640, "naklon": 5 }, +{ "label": "48/12", "node": 3747, "naklon": 5 }, +{ "label": "48/13", "node": 3629, "naklon": 5 }, +{ "label": "48/14", "node": 4048, "naklon": 5 }, +{ "label": "48/15", "node": 4063, "naklon": 5 }, +{ "label": "48/16", "node": 4062, "naklon": 5 }, +{ "label": "48/17", "node": 4043, "naklon": 5 }, +{ "label": "48/18", "node": 4052, "naklon": 5 }, +{ "label": "48/19", "node": 4042, "naklon": 5 }, +{ "label": "48/20", "node": 4053, "naklon": 5 }, +{ "label": "50/15A", "node": 4167, "naklon": null }, +{ "label": "50/15B", "node": 4159, "naklon": null }, +{ "label": "50/1", "node": 4183, "naklon": 0 }, +{ "label": "50/2", "node": 4157, "naklon": 0 }, +{ "label": "50/3", "node": 4160, "naklon": 0 }, +{ "label": "50/4", "node": 4173, "naklon": 0 }, +{ "label": "50/5", "node": 4177, "naklon": 0 }, +{ "label": "50/6", "node": 4174, "naklon": 0 }, +{ "label": "50/7", "node": 4178, "naklon": 0 }, +{ "label": "50/8", "node": 4195, "naklon": 0 }, +{ "label": "50/9", "node": 4169, "naklon": 0 }, +{ "label": "50/10", "node": 4162, "naklon": 0 }, +{ "label": "50/11", "node": 4158, "naklon": 0 }, +{ "label": "50/12", "node": 4182, "naklon": 0 }, +{ "label": "50/13", "node": 4194, "naklon": 0 }, +{ "label": "50/14", "node": 4184, "naklon": 0 }, +{ "label": "50/16", "node": 4197, "naklon": null }, +{ "label": "50/17", "node": 4164, "naklon": null }, +{ "label": "50/18", "node": 3306, "naklon": null }, +{ "label": "50/19", "node": 4168, "naklon": null }, +{ "label": "50/20", "node": 4193, "naklon": null }, +{ "label": "50/21", "node": 4187, "naklon": null }, +{ "label": "50/22", "node": 4163, "naklon": null }, +{ "label": "50/23", "node": 4165, "naklon": null }, +{ "label": "50/24", "node": 4185, "naklon": null }, +{ "label": "50/25", "node": 3904, "naklon": null }, +{ "label": "53/1", "node": 2619, "naklon": 0 }, +{ "label": "53/2", "node": 2623, "naklon": 0 }, +{ "label": "53/3", "node": 2617, "naklon": 0 }, +{ "label": "53/4", "node": 2622, "naklon": 0 }, +{ "label": "53/5", "node": 2618, "naklon": 0 }, +{ "label": "53/6", "node": 2626, "naklon": 0 }, +{ "label": "53/7", "node": 2869, "naklon": 0 }, +{ "label": "53/8", "node": 2613, "naklon": 0 }, +{ "label": "53/9", "node": 2608, "naklon": 0 }, +{ "label": "53/10", "node": 2611, "naklon": 0 }, +{ "label": "53/11", "node": 2598, "naklon": 0 }, +{ "label": "53/12", "node": 3528, "naklon": 0 }, +{ "label": "53/13", "node": 3545, "naklon": 0 }, +{ "label": "53/14", "node": 2620, "naklon": 0 }, +{ "label": "53/15", "node": 2612, "naklon": 0 }, +{ "label": "53/16", "node": 2615, "naklon": 0 }, +{ "label": "53/17", "node": 3722, "naklon": 0 }, +{ "label": "53/18", "node": 2624, "naklon": 0 }, +{ "label": "53/19", "node": 2609, "naklon": 0 }, +{ "label": "53/20", "node": 2625, "naklon": 0 }, +{ "label": "53/21", "node": 2602, "naklon": 0 }, +{ "label": "53/22", "node": 2610, "naklon": 0 }, +{ "label": "53/23", "node": 2599, "naklon": 0 }, +{ "label": "53/24", "node": 2605, "naklon": 0 }, +{ "label": "53/25", "node": 2593, "naklon": 0 }, +{ "label": "53/26", "node": 3074, "naklon": 0 }, +{ "label": "53/27", "node": 2740, "naklon": 0 }, +{ "label": "53/28", "node": 2614, "naklon": 0 }, +{ "label": "53/29", "node": 2601, "naklon": 0 }, +{ "label": "53/30", "node": 4196, "naklon": 0 }, +{ "label": "53/31", "node": 2607, "naklon": 0 }, +{ "label": "53/32", "node": 2582, "naklon": 0 }, +{ "label": "53/33", "node": 2594, "naklon": 0 }, +{ "label": "53/34", "node": 2589, "naklon": 0 }, +{ "label": "53/35", "node": 2596, "naklon": 0 }, +{ "label": "53/36", "node": 2603, "naklon": 0 }, +{ "label": "53/37", "node": 2597, "naklon": 0 }, +{ "label": "53/38", "node": 2590, "naklon": 0 }, +{ "label": "53/39", "node": 2581, "naklon": 0 }, +{ "label": "53/40", "node": 2583, "naklon": 0 }, +{ "label": "53/41", "node": 2580, "naklon": 0 }, +{ "label": "53/42", "node": 2579, "naklon": 0 }, +{ "label": "53/43", "node": 2797, "naklon": 0 }, +{ "label": "53/44", "node": 2577, "naklon": 0 }, +{ "label": "53/45", "node": 2586, "naklon": 0 }, +{ "label": "53/46", "node": 2588, "naklon": 0 }, +{ "label": "53/47", "node": 2591, "naklon": 0 }, +{ "label": "53/48", "node": 2592, "naklon": 0 }, +{ "label": "53/49", "node": 2573, "naklon": 0 }, +{ "label": "53/50", "node": 2595, "naklon": 0 }, +{ "label": "53/51", "node": 2587, "naklon": 0 }, +{ "label": "53/52", "node": 2578, "naklon": 0 }, +{ "label": "53/53", "node": 2574, "naklon": 0 }, +{ "label": "53/54", "node": 2571, "naklon": 0 }, +{ "label": "53/55", "node": 2570, "naklon": 0 }, +{ "label": "53/56", "node": 2576, "naklon": 0 }, +{ "label": "53/57", "node": 2881, "naklon": 0 }, +{ "label": "53/58", "node": 2575, "naklon": 0 }, +{ "label": "53/59", "node": 2572, "naklon": 0 }, +{ "label": "53/60", "node": 2569, "naklon": 0 }, +{ "label": "55/1", "node": 4324, "naklon": 0 }, +{ "label": "55/2", "node": 4319, "naklon": 0 }, +{ "label": "55/3", "node": 4327, "naklon": 0 }, +{ "label": "55/4", "node": 4333, "naklon": 0 }, +{ "label": "55/5", "node": 4332, "naklon": 0 }, +{ "label": "55/6", "node": 4320, "naklon": 0 }, +{ "label": "55/7", "node": 4317, "naklon": 0 }, +{ "label": "55/8", "node": 4318, "naklon": 0 }, +{ "label": "55/9", "node": 4328, "naklon": 0 }, +{ "label": "55/10", "node": 4323, "naklon": 0 }, +{ "label": "55/11", "node": 4325, "naklon": 0 }, +{ "label": "55/12", "node": 4326, "naklon": 0 }, +{ "label": "55/13", "node": 4316, "naklon": 0 }, +{ "label": "55/14", "node": 4322, "naklon": 0 }, +{ "label": "55/15", "node": 4331, "naklon": 0 }, +{ "label": "55/16", "node": 4321, "naklon": 0 }, +{ "label": "55/17", "node": 4315, "naklon": 0 }, +{ "label": "55/18", "node": 4329, "naklon": 0 }, +{ "label": "55/19", "node": 4334, "naklon": 0 }, +{ "label": "55/20", "node": 4330, "naklon": 0 } +]; + +module.exports = { naklony }; diff --git a/RVO35/databases/modbus_config.js b/RVO35/databases/modbus_config.js new file mode 100755 index 0000000..b73116a --- /dev/null +++ b/RVO35/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/RVO35/databases/nodes.table b/RVO35/databases/nodes.table new file mode 100755 index 0000000..e9a9ebb --- /dev/null +++ b/RVO35/databases/nodes.table @@ -0,0 +1,80 @@ +node:number|pole_number:string|node_type:string|tbname:string|line:number|profile:string|processed:boolean|status:boolean|time_of_last_communication:number ++|3646|32|NENA|zrR51V2ajQ9ZLygPKkEMRakYDq38xOJolENBXGnv|1||1|0|1760287302207|............. ++|3658|22|NEMA|PLBJzmK1r3Gynd6OW0gKBx0e5wV4vx9bDEqNgYR8|1||1|0|1760287333876|............. ++|3671|63|NEMA|EjgWGnXaLy9opPOz20n4Pa786BlYM3w1deVQvbKr|1||1|0|1760287346569|............. ++|3672|65|NEMA|Nzp2OoJlqn6r1ZgvdA3BbL7abBwP5G4eE3RQmyxD|1||1|0|1760287347785|............. ++|3673|67|NEMA|52dD6ZlV1QaOpRBmbAqGpqkKnGzWMLj4eJq38Pgo|1||1|0|1760287300640|............. ++|3674|68|NEMA|rDbQ84xzwgdqEoPm3kbE2y09anOZY1RXyBv2LVM6|1||1|0|1760287302447|............. ++|3677|72|NEMA|ZmRwd93QL4gaezxEbAx2P9k1prn2XjlPvGyqJ6BO|1||1|0|1760287309289|............. ++|3679|69|NEMA|E6Kg9oDnLWyzPRMva7v5NbkJxp4VG58qO2w1lZYe|1||1|0|1760287374706|............. ++|3682|64|NEMA|wvKJdZML6mXP4DzWBAXxnPAjxNloa5g23Ve9Y1ry|1||1|0|1760287318114|............. ++|3683|66|NEMA|PLBJzmK1r3Gynd6OW0gKmx0e5wV4vx9bDEqNgYR8|1||1|0|1760287385641|............. ++|3687|71|NEMA|nJL5lPMwBx23YpqRe0rpz27damXvWVbOrD4gNzy8|1||1|0|1760287322398|............. ++|3980|24|NEMA|rDbQ84xzwgdqEoPm3kbEzy09anOZY1RXyBv2LVM6|1||1|0|1760287435359|............. ++|4012|25|NEMA|E6Kg9oDnLWyzPRMva7v5bbkJxp4VG58qO2w1lZYe|1||1|0|1760287435742|............. ++|3429|30|NEMA|zdQO8GwxDqjRgP4137YVX5ANyKlpem2nL65rvVJY|1||1|0|1760287264511|............. ++|3569|29|NEMA|gYbDLqlyZVoRerQpB72Mq8kWJnwM5z24POKa8Exj|1||1|0|1760287269131|............. ++|3962|27|NEMA|nJL5lPMwBx23YpqRe0rpX27damXvWVbOrD4gNzy8|1||1|0|1760287408757|............. ++|3804|50|NEMA|Z5KyJe9nEg1QNbWlX0w4wzkoDjBLdqzR83VGv624|1||1|1|1760574057919|............. ++|3810|51|NEMA|1JMYvnx2RzKEo4aWQ7DGPvkL8yZV3m9NBePXbrdj|1||1|1|1760574058130|............. ++|3844|49|NEMA|3JjOWdylwgNLzxVab7NaD8kZ2vG64rq8PEB5QmDo|1||1|1|1760574058367|............. ++|3878|37|NEMA|o9vbeQlLMVg8j5dq4keL940NxZpEmnXzwYKO1ar2|1||1|1|1760574058558|............. ++|3944|10|NEMA|B5EoxeMVp4zwr8nqW0GB8YARjvD1PNamOGbLg63Z|1||1|1|1760574061785|............. ++|3945|28|NEMA|XMBbew5z4ELrZa2mRAd3Mw78vPN6gy3DdVYlpKjq|1||1|0|1760287236503|............. ++|3947|3|NEMA|Z5KyJe9nEg1QNbWlX0w4vzkoDjBLdqzR83VGv624|1||1|1|1760574074726|............. ++|3948|6|kamera|dz4ojlpP85JMgDLZWkQJdn7aKYqQexEr62GXRV1y|1||1|1|1760574081004|............. ++|3955|35|NEMA|apKVJBwOyrP35m2lv7KYo10YXbeWNd64En9GxRqg|1||1|1|1760574081164|............. ++|3956|8|NEMA|K94XLav1glVRnyQ6r01PewAme3YJwBxM5oOzdP2j|1||1|1|1760574084407|............. ++|3958|12|NEMA|ZmRwd93QL4gaezxEbAx2jVk1prn2XjlPvGyqJ6BO|1||1|1|1760574090670|............. ++|2617|11|NEMA|aw4eELG2DlPMdn1JW0BMyaAqQXOZRN3xB5yp8VKr|1||1|1|1760574287382|............. ++|3961|7|NEMA|gRoJEyXVx4qD9er287L4qQ7wBzGldaPjLWQKm3Mv|1||1|1|1760574091006|............. ++|3965|38|NEMA|gP1eOZVj3Q9lv5aDEk45vV7rdpqW8yLm2BbKzJxM|1||1|1|1760574125274|............. ++|3966|53|NEMA|dz4ojlpP85JMgDLZWkQJyn7aKYqQexEr62GXRV1y|1||1|1|1760574125450|............. ++|3968|1|NEMA|RO8rjaBDy21qPQJzW7omVL0pK3xmNleVZg9Ed4Gw|1||1|1|1760574125625|............. ++|3969|2|NEMA|3JjOWdylwgNLzxVab7Nav8kZ2vG64rq8PEB5QmDo|1||1|1|1760574128852|............. ++|3970|39|NEMA|2O14VBzl8aDmWdNw3A59jgAGyZ5qLJoEMpj6R9ng|1||1|1|1760574130115|............. ++|3973|46|NEMA|JX1ObgmqGZ54DMyYL7aDdGkEVdve38WKRzwjNrQ9|1||1|1|1760574152784|............. ++|3974|47|NEMA|RvmwNz8QPblKp41GD7lK5QkJrLVYoBO92dMegn6W|1||1|1|1760574155980|............. ++|3076|23|NEMA|52dD6ZlV1QaOpRBmbAqGnqkKnGzWMLj4eJq38Pgo|1||1|0|1760287206416|............. ++|3978|42|NEMA|m6EYyZoJ4gWexdjVPAR5Lv7RDOq9wv2N5XzKGplr|1||1|1|1760574156139|............. ++|3979|4|NEMA|1JMYvnx2RzKEo4aWQ7DG1vkL8yZV3m9NBePXbrdj|1||1|1|1760574159335|............. ++|3984|44|NEMA|g9OxBZ5KRwNznlY6pAppW1AWXvjdEL4eGQobMDy2|1||1|1|1760574331748|............. ++|4213|43|NEMA|JzwxZXOvDj1bVrN4nkW5BbA8qdyBl3MRKLpGPgaQ|1||1|1|1760574277253|............. ++|4218|45|NEMA|OzNMgZ9n43qPbjXmy7zwQbA2DKdYvW5e6pxGRrVa|1||1|1|1760574287222|............. ++|3611|40|NEMA|pE5X8NQPaow6vlOZxk6arX0q42ezGBMyWgDVjR3L|1||1|1|1760573606536|............. ++|3612|34|NEMA|DbQY6zyveZRwK5drV0Z83J7joE4XJM83N9xl2nWq|1||1|1|1760573697007|............. ++|3622|33|NEMA|BaY3Xpy1EbKGjLq2O7ma6w7rx8owgQz9P4dDJRmN|1||1|1|1760573709388|............. ++|3643|52|NEMA|PjLblDgRBO6WQqnxmkJ1lg0Jv3ewZN4p5a89yKdY|1||1|1|1760573709692|............. ++|3644|62|NEMA|3a5oqJN1bgnx4Ol9dk892Q7ByE6jQ8mKDWMpGrLV|1||1|1|1760573621952|............. ++|2650|59|NEMA|aw4eELG2DlPMdn1JW0BM5aAqQXOZRN3xB5yp8VKr|0||1|1|1759206522859|............. ++|3647|61|NEMA|eod9aRWLVl34Gx1Dn7VNVr72rz6qjgmpEXwQJN5Z|1||1|1|1760573640420|............. ++|3648|58|NEMA|B5EoxeMVp4zwr8nqW0GBpYARjvD1PNamOGbLg63Z|1||1|1|1760573643647|............. ++|3649|70|NEMA|roKgWqY95V3mXMRzyAjKee0bLjexpJPvaGDBw826|1||1|0|1760287319440|............. ++|3650|55|NEMA|gRoJEyXVx4qD9er287L4NQ7wBzGldaPjLWQKm3Mv|1||1|1|1760573674705|............. ++|3651|56|NEMA|K94XLav1glVRnyQ6r01PgwAme3YJwBxM5oOzdP2j|1||1|1|1760573674898|............. ++|3654|83|NEMA|roKgWqY95V3mXMRzyAjK1D0bLjexpJPvaGDBw826|1||1|1|1760573678171|............. ++|3655|26|NEMA|roKgWqY95V3mXMRzyAjKQe0bLjexpJPvaGDBw826|1||1|0|1760287333253|............. ++|3657|31|NEMA|5dBNwRp9graYJxZn409NYwklVov1b2QLPDqGm6XK|1||1|0|1760287333477|............. ++|3659|60|NEMA|ZmRwd93QL4gaezxEbAx2DVk1prn2XjlPvGyqJ6BO|1||1|0|1757706655051|............. ++|3659|78|NEMA|ZmRwd93QL4gaezxEbAx2DVk1prn2XjlPvGyqJ6BO|1||1|0|1757706655051|............. ++|3668|77|NEMA|Nzp2OoJlqn6r1ZgvdA3B9d7abBwP5G4eE3RQmyxD|1||1|1|1760573777509|............. ++|3669|57|NEMA|d9x2V5LGYBzXp4mMRAOmJvkPloaqJwnQj6DgrNe3|1||1|1|1760573777701|............. ++|3670|79|NEMA|52dD6ZlV1QaOpRBmbAqGrgkKnGzWMLj4eJq38Pgo|1||1|1|1760573780928|............. ++|3676|75|10-Repeater|EjgWGnXaLy9opPOz20n434786BlYM3w1deVQvbKr|1||1|1|1760573928051|............. ++|3678|81|NEMA|E6Kg9oDnLWyzPRMva7v5eakJxp4VG58qO2w1lZYe|1||1|1|1760573963310|............. ++|3680|76|NEMA|wvKJdZML6mXP4DzWBAXxXWAjxNloa5g23Ve9Y1ry|1||1|1|1760573990980|............. ++|3681|78|NEMA|PLBJzmK1r3Gynd6OW0gKwM0e5wV4vx9bDEqNgYR8|1||1|1|1760573991220|............. ++|3689|80|NEMA|rDbQ84xzwgdqEoPm3kbE6309anOZY1RXyBv2LVM6|1||1|1|1760574047934|............. ++|3690|73|NEMA|eod9aRWLVl34Gx1Dn7VNxa72rz6qjgmpEXwQJN5Z|1||1|1|1760574054165|............. ++|3691|74|NEMA|3a5oqJN1bgnx4Ol9dk89RB7ByE6jQ8mKDWMpGrLV|1||1|1|1760574054308|............. ++|3693|82|NEMA|nJL5lPMwBx23YpqRe0rp2V7damXvWVbOrD4gNzy8|1||1|1|1760574054500|............. ++|4115|21|NEMA|Nzp2OoJlqn6r1ZgvdA3B5L7abBwP5G4eE3RQmyxD|1||1|1|1760574129923|............. ++|3759|48|NEMA|RO8rjaBDy21qPQJzW7omRL0pK3xmNleVZg9Ed4Gw|1||1|1|1760574057712|............. ++|4017|20|NEMA|wvKJdZML6mXP4DzWBAXxZPAjxNloa5g23Ve9Y1ry|1||1|1|1760574236786|............. ++|3959|5|NEMA|PjLblDgRBO6WQqnxmkJ13g0Jv3ewZN4p5a89yKdY|1||1|1|1760574090846|............. ++|3214|18|NEMA|3a5oqJN1bgnx4Ol9dk89pQ7ByE6jQ8mKDWMpGrLV|1||1|1|1760574325453|............. ++|4108|19|NEMA|EjgWGnXaLy9opPOz20n4xa786BlYM3w1deVQvbKr|1||1|1|1760574249807|............. ++|3604|9|NEMA|d9x2V5LGYBzXp4mMRAOmjvkPloaqJwnQj6DgrNe3|1||1|1|1760573597030|............. ++|4000|13|NEMA|eod9aRWLVl34Gx1Dn7VNEr72rz6qjgmpEXwQJN5Z|1||1|1|1760574196543|............. ++|2635|41|NEMA|6lQGaY9RDywdVzObj0PaQWkPg4NBn3exEK51LWZq|1||1|1|1760574293677|............. ++|3971|54|NEMA|d5xjWYMwEJon6rLlK7yEJN7qgV4DaOeNB9ZX3Gzb|1||1|1|1760574134332|............. diff --git a/RVO35/databases/nodes_original/nodes_original.table b/RVO35/databases/nodes_original/nodes_original.table new file mode 100755 index 0000000..7cfabe8 --- /dev/null +++ b/RVO35/databases/nodes_original/nodes_original.table @@ -0,0 +1 @@ +[{"3646": "zrR51V2ajQ9ZLygPKkEMRakYDq38xOJolENBXGnv"}, {"3658": "PLBJzmK1r3Gynd6OW0gKBx0e5wV4vx9bDEqNgYR8"}, {"3671": "EjgWGnXaLy9opPOz20n4Pa786BlYM3w1deVQvbKr"}, {"3672": "Nzp2OoJlqn6r1ZgvdA3BbL7abBwP5G4eE3RQmyxD"}, {"3673": "52dD6ZlV1QaOpRBmbAqGpqkKnGzWMLj4eJq38Pgo"}, {"3674": "rDbQ84xzwgdqEoPm3kbE2y09anOZY1RXyBv2LVM6"}, {"3677": "ZmRwd93QL4gaezxEbAx2P9k1prn2XjlPvGyqJ6BO"}, {"3679": "E6Kg9oDnLWyzPRMva7v5NbkJxp4VG58qO2w1lZYe"}, {"3682": "wvKJdZML6mXP4DzWBAXxnPAjxNloa5g23Ve9Y1ry"}, {"3683": "PLBJzmK1r3Gynd6OW0gKmx0e5wV4vx9bDEqNgYR8"}, {"3687": "nJL5lPMwBx23YpqRe0rpz27damXvWVbOrD4gNzy8"}, {"3980": "rDbQ84xzwgdqEoPm3kbEzy09anOZY1RXyBv2LVM6"}, {"4012": "E6Kg9oDnLWyzPRMva7v5bbkJxp4VG58qO2w1lZYe"}, {"3429": "zdQO8GwxDqjRgP4137YVX5ANyKlpem2nL65rvVJY"}, {"3569": "gYbDLqlyZVoRerQpB72Mq8kWJnwM5z24POKa8Exj"}, {"3962": "nJL5lPMwBx23YpqRe0rpX27damXvWVbOrD4gNzy8"}, {"3804": "Z5KyJe9nEg1QNbWlX0w4wzkoDjBLdqzR83VGv624"}, {"3810": "1JMYvnx2RzKEo4aWQ7DGPvkL8yZV3m9NBePXbrdj"}, {"3844": "3JjOWdylwgNLzxVab7NaD8kZ2vG64rq8PEB5QmDo"}, {"3878": "o9vbeQlLMVg8j5dq4keL940NxZpEmnXzwYKO1ar2"}, {"3944": "B5EoxeMVp4zwr8nqW0GB8YARjvD1PNamOGbLg63Z"}, {"3945": "XMBbew5z4ELrZa2mRAd3Mw78vPN6gy3DdVYlpKjq"}, {"3947": "Z5KyJe9nEg1QNbWlX0w4vzkoDjBLdqzR83VGv624"}, {"3948": "dz4ojlpP85JMgDLZWkQJdn7aKYqQexEr62GXRV1y"}, {"3955": "apKVJBwOyrP35m2lv7KYo10YXbeWNd64En9GxRqg"}, {"3956": "K94XLav1glVRnyQ6r01PewAme3YJwBxM5oOzdP2j"}, {"3958": "ZmRwd93QL4gaezxEbAx2jVk1prn2XjlPvGyqJ6BO"}, {"2617": "aw4eELG2DlPMdn1JW0BMyaAqQXOZRN3xB5yp8VKr"}, {"3961": "gRoJEyXVx4qD9er287L4qQ7wBzGldaPjLWQKm3Mv"}, {"3965": "gP1eOZVj3Q9lv5aDEk45vV7rdpqW8yLm2BbKzJxM"}, {"3966": "dz4ojlpP85JMgDLZWkQJyn7aKYqQexEr62GXRV1y"}, {"3968": "RO8rjaBDy21qPQJzW7omVL0pK3xmNleVZg9Ed4Gw"}, {"3969": "3JjOWdylwgNLzxVab7Nav8kZ2vG64rq8PEB5QmDo"}, {"3970": "2O14VBzl8aDmWdNw3A59jgAGyZ5qLJoEMpj6R9ng"}, {"3973": "JX1ObgmqGZ54DMyYL7aDdGkEVdve38WKRzwjNrQ9"}, {"3974": "RvmwNz8QPblKp41GD7lK5QkJrLVYoBO92dMegn6W"}, {"3076": "52dD6ZlV1QaOpRBmbAqGnqkKnGzWMLj4eJq38Pgo"}, {"3978": "m6EYyZoJ4gWexdjVPAR5Lv7RDOq9wv2N5XzKGplr"}, {"3979": "1JMYvnx2RzKEo4aWQ7DG1vkL8yZV3m9NBePXbrdj"}, {"3984": "g9OxBZ5KRwNznlY6pAppW1AWXvjdEL4eGQobMDy2"}, {"4213": "JzwxZXOvDj1bVrN4nkW5BbA8qdyBl3MRKLpGPgaQ"}, {"4218": "OzNMgZ9n43qPbjXmy7zwQbA2DKdYvW5e6pxGRrVa"}, {"3611": "pE5X8NQPaow6vlOZxk6arX0q42ezGBMyWgDVjR3L"}, {"3612": "DbQY6zyveZRwK5drV0Z83J7joE4XJM83N9xl2nWq"}, {"3622": "BaY3Xpy1EbKGjLq2O7ma6w7rx8owgQz9P4dDJRmN"}, {"3643": "PjLblDgRBO6WQqnxmkJ1lg0Jv3ewZN4p5a89yKdY"}, {"3644": "3a5oqJN1bgnx4Ol9dk892Q7ByE6jQ8mKDWMpGrLV"}, {"3645": "aw4eELG2DlPMdn1JW0BM5aAqQXOZRN3xB5yp8VKr"}, {"3647": "eod9aRWLVl34Gx1Dn7VNVr72rz6qjgmpEXwQJN5Z"}, {"3648": "B5EoxeMVp4zwr8nqW0GBpYARjvD1PNamOGbLg63Z"}, {"3649": "roKgWqY95V3mXMRzyAjKee0bLjexpJPvaGDBw826"}, {"3650": "gRoJEyXVx4qD9er287L4NQ7wBzGldaPjLWQKm3Mv"}, {"3651": "K94XLav1glVRnyQ6r01PgwAme3YJwBxM5oOzdP2j"}, {"3654": "roKgWqY95V3mXMRzyAjK1D0bLjexpJPvaGDBw826"}, {"3655": "roKgWqY95V3mXMRzyAjKQe0bLjexpJPvaGDBw826"}, {"3657": "5dBNwRp9graYJxZn409NYwklVov1b2QLPDqGm6XK"}, {"3659": "ZmRwd93QL4gaezxEbAx2DVk1prn2XjlPvGyqJ6BO"}, {"3668": "Nzp2OoJlqn6r1ZgvdA3B9d7abBwP5G4eE3RQmyxD"}, {"3669": "d9x2V5LGYBzXp4mMRAOmJvkPloaqJwnQj6DgrNe3"}, {"3670": "52dD6ZlV1QaOpRBmbAqGrgkKnGzWMLj4eJq38Pgo"}, {"3676": "EjgWGnXaLy9opPOz20n434786BlYM3w1deVQvbKr"}, {"3678": "E6Kg9oDnLWyzPRMva7v5eakJxp4VG58qO2w1lZYe"}, {"3680": "wvKJdZML6mXP4DzWBAXxXWAjxNloa5g23Ve9Y1ry"}, {"3681": "PLBJzmK1r3Gynd6OW0gKwM0e5wV4vx9bDEqNgYR8"}, {"3689": "rDbQ84xzwgdqEoPm3kbE6309anOZY1RXyBv2LVM6"}, {"3690": "eod9aRWLVl34Gx1Dn7VNxa72rz6qjgmpEXwQJN5Z"}, {"3691": "3a5oqJN1bgnx4Ol9dk89RB7ByE6jQ8mKDWMpGrLV"}, {"3693": "nJL5lPMwBx23YpqRe0rp2V7damXvWVbOrD4gNzy8"}, {"4115": "Nzp2OoJlqn6r1ZgvdA3B5L7abBwP5G4eE3RQmyxD"}, {"3759": "RO8rjaBDy21qPQJzW7omRL0pK3xmNleVZg9Ed4Gw"}, {"4017": "wvKJdZML6mXP4DzWBAXxZPAjxNloa5g23Ve9Y1ry"}, {"3959": "PjLblDgRBO6WQqnxmkJ13g0Jv3ewZN4p5a89yKdY"}, {"3214": "3a5oqJN1bgnx4Ol9dk89pQ7ByE6jQ8mKDWMpGrLV"}, {"4108": "EjgWGnXaLy9opPOz20n4xa786BlYM3w1deVQvbKr"}, {"3604": "d9x2V5LGYBzXp4mMRAOmjvkPloaqJwnQj6DgrNe3"}, {"4000": "eod9aRWLVl34Gx1Dn7VNEr72rz6qjgmpEXwQJN5Z"}, {"2635": "6lQGaY9RDywdVzObj0PaQWkPg4NBn3exEK51LWZq"}, {"3971": "d5xjWYMwEJon6rLlK7yEJN7qgV4DaOeNB9ZX3Gzb"}] \ No newline at end of file diff --git a/RVO35/databases/notifications.table b/RVO35/databases/notifications.table new file mode 100755 index 0000000..f7c96cb --- /dev/null +++ b/RVO35/databases/notifications.table @@ -0,0 +1,41 @@ +key:string|weight:string|sk:string|en:string ++|switching_profile_point_applied_to_line|INFORMATIONAL|Aplikovaný bod spínacieho profilu na línií č. ${line} : ${value}|Switching profile point applied to line no. ${line} : ${value}|............... ++|dusk_has_occured|INFORMATIONAL|Nastal súmrak: ${value}|Dusk has occured: ${value}|............... ++|dawn_has_occured|INFORMATIONAL|Nastal úsvit: ${value}|Dawn has occured: ${value}|............... ++|dimming_profile_was_successfully_received_by_node|NOTICE|Stmievací profil bol úspešne prijatý nodom č. ${node}|Dimming profile was successfully received by node no. ${node}|............... ++|master_node_is_responding_again|NOTICE|Master node začal znovu odpovedať|Master node is responding again|............... ++|command_was_sent_from_terminal_interface|DEBUG|Z terminálu bol odoslaný príkaz|A command was sent from terminal interface|............... ++|master_node_is_not_responding|ALERT|Master node neodpovedá|Master node is not responding|............... ++|configuration_of_dimming_profile_to_node_failed|ALERT|Konfigurácia stmievacieho profilu pre node č. ${node} zlyhala|Configuration of dimming profile to node no. ${node} has failed|............... ++|circuit_breaker_was_turned_on_line|NOTICE|Zapnutie ističa na línii č. ${line}|Circuit breaker was turned on - line no. ${line}|............... ++|circuit_breaker_was_turned_off_line|ERROR|Vypnutie ističa na línií č. ${line}|Circuit breaker was turned off - line no. ${line}|............... ++|dimming_profile_was_processed_for_node|INFORMATIONAL|Stmievací profil bol spracovaný pre node č. ${node}|Dimming profile was processed for node no. ${node}|............... ++|switching_profile_was_processed_for_line|INFORMATIONAL|Spínací profil bol spracovaný pre líniu č. ${line}|Switching profile was processed for line no. ${line}|............... ++|thermometer_is_not_responding|WARNING|Teplomer neodpovedá|Thermometer is not responding|............... ++|thermometer_is_responding_again|NOTICE|Teplomer znovu odpovedá|Thermometer is responding again|............... ++|thermometer_sends_invalid_data|WARNING|Teplomer posiela neplatné hodnoty|Thermometer sends invalid data|............... ++|main_switch_has_been_turned_off|CRITICAL|Hlavný vypínač bol vypnutý|Main switch has been turned off|............... ++|main_switch_has_been_turned_on|NOTICE|Hlavný vypínač bol zapnutý|Main switch has been turned on|............... ++|power_supply_has_disconnected_input|ALERT|Napájací zdroj nemá napätie na vstupe|Power supply has disconnected input|............... ++|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_main_open|NOTICE|Hlavné dvere boli otvorené|Main door has been opened|............... ++|door_em_open|NOTICE|Dvere silovej časti boli otvorené|Power door has been opened|............... ++|door_main_open_without_permission|WARNING|Hlavné dvere boli otvorené bez povolenia - zapnutá siréna|Main door has been opened without permission - alarm is on|............... ++|door_em_open_without_permission|WARNING|Dvere silovej časti boli otvorené bez povolenia|Power door has been opened without permission|............... ++|door_main_close|NOTICE|Hlavné dvere boli zatvorené|Main door has been closed|............... ++|door_em_close|NOTICE|Dvere silovej časti boli zatvorené|Power door has been closed|............... ++|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|............... ++|electrometer_ok|NOTICE|Elektromer znovu odpovedá|Electrometer is responding again|............... ++|no_voltage_on_phase|CRITICAL|Na fáze č. ${phase} nie je napätie|No voltage detected on phase no. ${phase}|............... ++|voltage_on_phase_restored|NOTICE|Napätie na fáze č. ${phase} bolo obnovené|Voltage on phase no. ${phase} has been restored|............... ++|flow_start|NOTICE|FLOW bol spustený|FLOW has been started |............... ++|twilight_sensor_nok|ERROR|Sensor súmraku neodpovedá|Twilight sensor is not responding|............... ++|twilight_sensor_ok|NOTICE|Sensor súmraku znovu odpovedá|Twilight sensor is responding again|............... ++|lamps_have_turned_on|NOTICE|Lampy sa zapli|Lamps have turned on|............... ++|lamps_have_turned_off|NOTICE|Lampy sa vypli|Lamps have turned off|............... ++|flow_restart|NOTICE|FLOW bol reštartovaný|FLOW has been restarted|............... ++|nodes_db_changed|NOTICE|Zmena v node databáze|Node db has changed|............... diff --git a/RVO35/databases/pins.table b/RVO35/databases/pins.table new file mode 100755 index 0000000..f86b8b9 --- /dev/null +++ b/RVO35/databases/pins.table @@ -0,0 +1,17 @@ +pin:string|type:string|line:number +*|input1_01|door_condition|0|........... +*|input1_02|rotary_switch_state|0|........... +*|input1_03|rotary_switch_state|0|........... +*|input1_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|........... +*|relay1_05|state_of_contactor|4|........... +*|relay1_06|state_of_contactor|5|........... +*|relay1_07|state_of_contactor|6|........... +*|28F46E9D0E00008B|temperature|0|........... +*|twilight_sensor|twilight_sensor|0|........... \ No newline at end of file diff --git a/RVO35/databases/relays.table b/RVO35/databases/relays.table new file mode 100755 index 0000000..b82ada5 --- /dev/null +++ b/RVO35/databases/relays.table @@ -0,0 +1,8 @@ +line:number|tbname:string|contactor:number|profile:string ++|0|gP1eOZVj3Q9lv5aDEk45bM7rdpqW8yLm2BbKzJxM|1||........... ++|1|pE5X8NQPaow6vlOZxk6aOE0q42ezGBMyWgDVjR3L|9|{"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|6lQGaY9RDywdVzObj0Pa2okPg4NBn3exEK51LWZq|9|{"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|m6EYyZoJ4gWexdjVPAR5Ma7RDOq9wv2N5XzKGplr|9|{"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}|........... ++|4|apKVJBwOyrP35m2lv7KYev0YXbeWNd64En9GxRqg|9||........................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................... ++|5|o9vbeQlLMVg8j5dq4keLaX0NxZpEmnXzwYKO1ar2|9|{"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}|........... ++|6|gP1eOZVj3Q9lv5aDEk45mZ7rdpqW8yLm2BbKzJxM|9|{"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/RVO35/databases/settings.table b/RVO35/databases/settings.table new file mode 100755 index 0000000..dea6eee --- /dev/null +++ b/RVO35/databases/settings.table @@ -0,0 +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|project_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|cloud_topic:string|has_main_switch:boolean|daily_report:boolean|send_changed_node_numbers:boolean ++|rvo_senica_35_10.0.0.129|en|28.64339D0E0000|48.70826502|17.28455203|192.168.252.1|rvo_senica_35_10.0.0.129|XzLmhOhYVANSqM65h14r|1883|0|65|unipi|ttyUSB0|1|20|5|6|3|u129|0|1|1|................................................... diff --git a/RVO35/databases/tbdata.nosql b/RVO35/databases/tbdata.nosql new file mode 100755 index 0000000..df9d76c --- /dev/null +++ b/RVO35/databases/tbdata.nosql @@ -0,0 +1,4 @@ +-"gP1eOZVj3Q9lv5aDEk45bM7rdpqW8yLm2BbKzJxM":[{"ts":1760519892440,"values":{"_event":{"type":"notice","status":"new","source":{"func":"modbus_reader","component":"1699965957410","component_name":"Modbus reader","edge":"gP1eOZVj3Q9lv5aDEk45bM7rdpqW8yLm2BbKzJxM"},"message":{"sk":"rvo_senica_35_10.0.0.129: FLOW bol reštartovaný","en":"rvo_senica_35_10.0.0.129: FLOW has been restarted"},"message_data":""}}}],"id":"3000138001gn71b"} +-"gP1eOZVj3Q9lv5aDEk45bM7rdpqW8yLm2BbKzJxM":[{"ts":1760519892562,"values":{"edge_fw_version":"2025-10-08","maintenance_mode":false}}],"id":"3000138002gn70b"} +-"gP1eOZVj3Q9lv5aDEk45bM7rdpqW8yLm2BbKzJxM":[{"ts":1760519892575,"values":{"statecode":2,"power_mode":"Automatic"}}],"id":"3000138004gn70b"} +-"gP1eOZVj3Q9lv5aDEk45bM7rdpqW8yLm2BbKzJxM":[{"ts":1760519892627,"values":{"_event":{"type":"notice","status":"new","source":{"func":"rsPort.open()","component":"1699963668903","component_name":"DIDO_Controller","edge":"gP1eOZVj3Q9lv5aDEk45bM7rdpqW8yLm2BbKzJxM"},"message":{"sk":"rvo_senica_35_10.0.0.129: FLOW bol spustený","en":"rvo_senica_35_10.0.0.129: FLOW has been started "},"message_data":""}}}],"id":"3000138006gn70b"} diff --git a/RVO35/databases/tbdatacloud.nosql b/RVO35/databases/tbdatacloud.nosql new file mode 100755 index 0000000..c761406 --- /dev/null +++ b/RVO35/databases/tbdatacloud.nosql @@ -0,0 +1,3 @@ +-"gP1eOZVj3Q9lv5aDEk45bM7rdpqW8yLm2BbKzJxM":[{"ts":1760519892562,"values":{"edge_fw_version":"2025-10-08","maintenance_mode":false}}],"id":"3000138003gn71b"} +-"gP1eOZVj3Q9lv5aDEk45bM7rdpqW8yLm2BbKzJxM":[{"ts":1760519892575,"values":{"statecode":2,"power_mode":"Automatic"}}],"id":"3000138005gn71b"} +-"gP1eOZVj3Q9lv5aDEk45bM7rdpqW8yLm2BbKzJxM":[{"ts":1760519892627,"values":{"_event":{"type":"notice","status":"new","source":{"func":"rsPort.open()","component":"1699963668903","component_name":"DIDO_Controller","edge":"gP1eOZVj3Q9lv5aDEk45bM7rdpqW8yLm2BbKzJxM"},"message":{"sk":"rvo_senica_35_10.0.0.129: FLOW bol spustený","en":"rvo_senica_35_10.0.0.129: FLOW has been started "},"message_data":""}}}],"id":"3000138007gn71b"} diff --git a/RVO35/databases/total_energy.js b/RVO35/databases/total_energy.js new file mode 100755 index 0000000..dde340e --- /dev/null +++ b/RVO35/databases/total_energy.js @@ -0,0 +1,38 @@ +//key is rvo_number, value is max energy when lamps are on +const total_energy = { + 1: 580, + 2: 1100, + 3: 3700, + 4: 4100, + 7: 360, + 12: 1700, + 13: 5400, + 14: 440, + 15: 6100, + 16: 4800, + 20: 1600, + 21: 1000, + 22: 2600, + 23: 1000, + 25: 2600, + 33: 240, + 34: 4000, + 35: 2700, + 36: 820, + 37: 1400, + 35: 3500, + 39: 1170, + 41: 740, + 42: 660, + 43: 4900, + 45: 930, + 46: 700, + 47: 1100, + 48: 1500, + 50: 3200, + 53: 1250, + 55: 1000, + 56: 5500 +} + +module.exports = total_energy; diff --git a/RVO35/debug.js b/RVO35/debug.js new file mode 100755 index 0000000..9818194 --- /dev/null +++ b/RVO35/debug.js @@ -0,0 +1,16 @@ +// =================================================== +// FOR DEVELOPMENT +// Total.js - framework for Node.js platform +// https://www.totaljs.com +// =================================================== + +const options = {}; + +// options.ip = '127.0.0.1'; +// options.port = parseInt(process.argv[2]); +// options.config = { name: 'Total.js' }; +// options.sleep = 3000; +// options.inspector = 9229; +// options.watch = ['private']; + +require('total.js/debug')(options); \ No newline at end of file diff --git a/RVO35/err.txt b/RVO35/err.txt new file mode 100755 index 0000000..9873305 --- /dev/null +++ b/RVO35/err.txt @@ -0,0 +1,107 @@ +[2024-10-25T07:54:54.308] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-25T08:55:23.828] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-25T09:55:51.343] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-25T10:56:18.900] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-25T11:56:56.265] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-25T12:57:06.410] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-25T13:57:37.860] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-25T14:58:15.108] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-25T15:58:42.765] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-25T16:58:58.706] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-25T17:59:18.545] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-25T18:59:53.906] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-25T20:00:19.540] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-25T21:01:00.702] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-25T22:01:34.108] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-25T23:02:15.295] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T00:02:44.853] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T01:03:27.942] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T02:04:05.285] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T03:04:36.753] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T04:05:09.220] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T05:05:36.806] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T06:06:25.746] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T07:06:41.733] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T08:07:42.348] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T09:08:06.029] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T10:08:43.400] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T11:08:53.494] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T12:09:34.586] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T13:10:11.796] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T14:10:54.864] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T15:11:20.439] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T16:11:55.749] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T17:12:25.250] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T18:12:52.879] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T19:13:16.564] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T20:13:46.115] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T21:14:23.399] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-12-21T09:26:51.132] [ERROR] errLogs - uncaughtException: message is not defined +[2024-12-21T09:26:51.132] [ERROR] errLogs - ReferenceError: message is not defined + at turnLine (/home/unipi/flowserver/flow/dido_controller.js:571:150) + at initialSetting (/home/unipi/flowserver/flow/dido_controller.js:215:9) + at WebSocket.open (/home/unipi/flowserver/flow/dido_controller.js:333:7) + at WebSocket.onOpen (/home/unipi/flowserver/node_modules/ws/lib/event-target.js:144:16) + at WebSocket.emit (events.js:400:28) + at WebSocket.setSocket (/home/unipi/flowserver/node_modules/ws/lib/websocket.js:225:10) + at ClientRequest. (/home/unipi/flowserver/node_modules/ws/lib/websocket.js:882:15) + at ClientRequest.emit (events.js:400:28) + at Socket.socketOnData (_http_client.js:553:11) + at Socket.emit (events.js:400:28) +[2024-12-21T09:26:51.133] [ERROR] errLogs - uncaughtException: message is not defined +[2024-12-21T09:26:51.134] [ERROR] errLogs - ReferenceError: message is not defined + at turnLine (/home/unipi/flowserver/flow/dido_controller.js:571:150) + at initialSetting (/home/unipi/flowserver/flow/dido_controller.js:215:9) + at WebSocket.open (/home/unipi/flowserver/flow/dido_controller.js:333:7) + at WebSocket.onOpen (/home/unipi/flowserver/node_modules/ws/lib/event-target.js:144:16) + at WebSocket.emit (events.js:400:28) + at WebSocket.setSocket (/home/unipi/flowserver/node_modules/ws/lib/websocket.js:225:10) + at ClientRequest. (/home/unipi/flowserver/node_modules/ws/lib/websocket.js:882:15) + at ClientRequest.emit (events.js:400:28) + at Socket.socketOnData (_http_client.js:553:11) + at Socket.emit (events.js:400:28) +[2024-12-21T09:26:51.145] [ERROR] errLogs - uncaughtException: message is not defined +[2024-12-21T09:26:51.146] [ERROR] errLogs - ReferenceError: message is not defined + at turnLine (/home/unipi/flowserver/flow/dido_controller.js:571:150) + at initialSetting (/home/unipi/flowserver/flow/dido_controller.js:215:9) + at WebSocket.open (/home/unipi/flowserver/flow/dido_controller.js:333:7) + at WebSocket.onOpen (/home/unipi/flowserver/node_modules/ws/lib/event-target.js:144:16) + at WebSocket.emit (events.js:400:28) + at WebSocket.setSocket (/home/unipi/flowserver/node_modules/ws/lib/websocket.js:225:10) + at ClientRequest. (/home/unipi/flowserver/node_modules/ws/lib/websocket.js:882:15) + at ClientRequest.emit (events.js:400:28) + at Socket.socketOnData (_http_client.js:553:11) + at Socket.emit (events.js:400:28) +[2025-09-23T14:00:16.696] [ERROR] errLogs - uncaughtException: Cannot read property 'getHours' of undefined +[2025-09-23T14:00:16.697] [ERROR] errLogs - TypeError: Cannot read property 'getHours' of undefined + at Timeout.emptyReportToSend [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:00:16.698] [ERROR] errLogs - uncaughtException: Cannot read property 'getHours' of undefined +[2025-09-23T14:00:16.699] [ERROR] errLogs - TypeError: Cannot read property 'getHours' of undefined + at Timeout.emptyReportToSend [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:00:16.707] [ERROR] errLogs - uncaughtException: Cannot read property 'getHours' of undefined +[2025-09-23T14:00:16.708] [ERROR] errLogs - TypeError: Cannot read property 'getHours' of undefined + at Timeout.emptyReportToSend [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:00:23.097] [ERROR] errLogs - uncaughtException: date.getHours is not a function +[2025-09-23T14:00:23.098] [ERROR] errLogs - TypeError: date.getHours is not a function + at emptyReportToSend (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at Timeout.dailyReportCheck [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1351:5) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:00:23.098] [ERROR] errLogs - uncaughtException: date.getHours is not a function +[2025-09-23T14:00:23.099] [ERROR] errLogs - TypeError: date.getHours is not a function + at emptyReportToSend (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at Timeout.dailyReportCheck [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1351:5) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:00:23.104] [ERROR] errLogs - uncaughtException: date.getHours is not a function +[2025-09-23T14:00:23.104] [ERROR] errLogs - TypeError: date.getHours is not a function + at emptyReportToSend (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at Timeout.dailyReportCheck [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1351:5) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) diff --git a/RVO35/flow/cloudmqttconnect.js b/RVO35/flow/cloudmqttconnect.js new file mode 100755 index 0000000..b03491f --- /dev/null +++ b/RVO35/flow/cloudmqttconnect.js @@ -0,0 +1,357 @@ +exports.id = 'cloudmqttconnect'; +exports.title = 'Cloud connect mqtt'; +exports.group = 'MQTT'; +exports.color = '#888600'; +exports.version = '1.0.2'; +exports.icon = 'sign-out'; +exports.input = 2; +exports.output = 2; +exports.options = { host: 'tb-stage.worksys.io', port: 1883, clientid: "", username: "" }; + +exports.html = `
+
+
+
Hostname or IP address (if not empty - setting will override db setting)
+
+
+
Port
+
+
+
+
+
@(Client id)
+
+
+
topic
+
+
+
`; + + + +const { promisifyBuilder } = require('./helper/db_helper'); +const fs = require('fs'); +const mqtt = require('mqtt'); +const nosql = NOSQL('tbdatacloud'); + +const SEND_TO = { + debug: 0, + rpcCall: 1, +} + +//CONFIG +let saveTelemetryOnError = true;//backup_on_failure overrides this value +//------------------------ + +const noSqlFileSizeLimit = 4194304;//use 5MB - 4194304 +let insertNoSqlCounter = 0; +let insertBackupNoSqlCounter = 0; +let processingData = false; + +let backup_on_failure = true;//== saveTelemetryOnError - create backup client send failure +let restore_from_backup = 50; //how many rows process at once? +let restore_backup_wait = 3;//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; + + +exports.install = function(instance) { + + var client; + var opts; + var clientReady = false; + + let o = {}; //options + + function main() { + loadSettings(); + } + + //set opts according to db settings + function loadSettings() { + + o = instance.options; + if (!o.topic) o.topic = FLOW.GLOBALS.settings.cloud_topic; + + opts = { + host: o.host, + port: o.port, + clientId: o.clientid, + username: o.username, + rejectUnauthorized: false, + resubscribe: false + }; + + console.log("wsmqttpublich -> loadSettings from instance.options", o); + + if (!o.topic) { + instance.status("Not configured", "white"); + console.log("Cloud mqtt connect: no topic selected"); + return; + } + + connectToTbServer(); + } + + function connectToTbServer() { + var url = "mqtt://" + opts.host + ":" + opts.port; + console.log("MQTT URL: ", url); + + client = mqtt.connect(url, opts); + + client.on('connect', function() { + client.subscribe(`${o.topic}_backward`, (err) => { + if (!err) { + console.log("MQTT subscribed"); + } + }); + instance.status("Connected", "green"); + clientReady = true; + sendClientError = true; + }); + + client.on('reconnect', function() { + instance.status("Reconnecting", "yellow"); + clientReady = false; + }); + + client.on('message', function(topic, message) { + // message is type of buffer + message = message.toString(); + if (message[0] === '{') { + TRY(function() { + + message = JSON.parse(message); + if (message.hasOwnProperty("device") && message.hasOwnProperty("data") && message.data.hasOwnProperty("id")) { + client.publish(`${o.topic}_forward`, `{"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 } }); + } + + }, () => instance.debug('MQTT: Error parsing data', message)); + } + + instance.send(SEND_TO.rpcCall, { "topic": o.topic, "content": message }); + }); + + client.on('close', function() { + clientReady = false; + + instance.status("Disconnected", "red"); + instance.send(SEND_TO.debug, { "message": "Client CLOSE signal received !" }); + }); + + client.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) { + console.log('MQTT client error', err); + sendClientError = false; + } + clientReady = false; + }); + + } + + + instance.on('0', function(data) { + + if (clientReady) { + //do we have some data in backup file? if any, process data from database + if (saveTelemetryOnError) { + //read telemetry data and send back to server + if (!processingData) processDataFromDatabase(); + } + + let stringifiedJson = JSON.stringify(data.data) + client.publish(`${o.topic}_forward`, stringifiedJson, { qos: 1 }); + } + 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 (saveTelemetryOnError && o.topic) { + //create new file from tbdata.nosql, if file size exceeds given limit, and clear tbdata.nosql + makeBackupFromDbFile(); + + //write to tb + data.data.id = UID(); + nosql.insert(data.data); + } + } + }); + + instance.on("1", _ => { + main(); + }) + + instance.close = function(done) { + if (clientReady) { + client.end(); + } + }; + + + function getDbBackupFileCounter(type) { + var files = fs.readdirSync(__dirname + "/../databases"); + + let counter = 0; + for (var i = 0; i < files.length; i++) { + + if (files[i] == "tbdatacloud.nosql") continue; + + if (files[i].endsWith(".nosql")) { + + let pos = files[i].indexOf("."); + if (pos > -1) { + + let fileCounter = counter; + let firstDigit = files[i].slice(0, pos); + + fileCounter = parseInt(firstDigit); + if (isNaN(fileCounter)) fileCounter = 0; + //console.log("getDbBackupFileCounter digit:", files[i], firstDigit, fileCounter, isNaN(fileCounter), type); + + if (type == "max") { + if (fileCounter > counter) { + counter = fileCounter; + } + } + else if (type == "min") { + if (counter == 0) counter = fileCounter; + + if (fileCounter < counter) { + counter = fileCounter; + } + } + } + } + + } + + if (type == "max") counter++; + + return counter; + } + + const makeBackupFromDbFile = async () => { + + if (!saveTelemetryOnError) return; + + //to avoid large file: tbdata.nosql + + //init value is 0! + if (insertNoSqlCounter > 0) { + --insertNoSqlCounter; + return; + } + + insertNoSqlCounter = 100; + + let source = __dirname + "/../databases/tbdatacloud.nosql"; + + var stats = fs.statSync(source); + var fileSizeInBytes = stats.size; + + if (fileSizeInBytes > noSqlFileSizeLimit) { + + let counter = 1; + counter = getDbBackupFileCounter("max"); + + let destination = __dirname + "/../databases/" + counter + "." + "tbdatacloud.nosql"; + + //make backup file + fs.copyFileSync(source, destination); + //fs.renameSync(p, p + "." + counter); + + //clear tbdata.nosql + fs.writeFileSync(source, ""); + fs.truncateSync(source, 0); + + } + } + + const processDataFromDatabase = async () => { + + if (restore_from_backup <= 0) return; + + //calculate diff + const now = new Date(); + let currentTime = now.getTime(); + let diff = currentTime - lastRestoreTime; + + if ((diff / 1000) < restore_backup_wait) { + //console.log("*********restore_backup_wait", diff, restore_backup_wait); + return; + } + + processingData = true; + + //get filename to process + let counter = getDbBackupFileCounter("min"); + + //we have some backup files + let dataBase = 'tbdata'; + + var nosql; + if (counter == 0) dataBase = 'tbdatacloud'; + else dataBase = counter + "." + 'tbdatacloud'; + + nosql = NOSQL(dataBase); + + //select all data - use limit restore_from_backup + let records = await promisifyBuilder(nosql.find().take(restore_from_backup)); + + for (let i = 0; i < records.length; i++) { + if (clientReady) { + + let item = records[i]; + let id = item.id; + + if (id !== undefined) { + //console.log("------------processDataFromDatabase - remove", id, dataBase, i); + + try { + + let message = JSON.parse(JSON.stringify(item)); + delete message.id; + client.publish(`${o.topic}_forward`, JSON.stringify(message), { qos: 1 }); + + //remove from database + await promisifyBuilder(nosql.remove().where("id", id)); + + } catch (error) { + //process error + console.log("processDataFromDatabase", error); + } + + } + + } + else { + processingData = false; + return; + } + } + + if (records.length > 0) { + //clean backup file + if (counter > 0) nosql.clean(); + } + + //no data in db, remove + if (records.length == 0) { + if (counter > 0) nosql.drop(); + } + + const d = new Date(); + lastRestoreTime = d.getTime(); + + processingData = false; + + } + + instance.on('options', main); + +}; diff --git a/RVO35/flow/cmd_manager.js b/RVO35/flow/cmd_manager.js new file mode 100755 index 0000000..25912df --- /dev/null +++ b/RVO35/flow/cmd_manager.js @@ -0,0 +1,3071 @@ +exports.id = 'cmd_manager'; +exports.title = 'CMD Manager'; +exports.group = 'Worksys'; +exports.color = '#5D9CEC'; +exports.version = '0.0.3'; +exports.output = ['red', 'blue', 'yellow', 'blue', 'white', 'green']; +exports.input = 3; +exports.icon = 'cloud-upload'; + +exports.html = ` +
+
+
+
RPC - run RPC calls

+
+
+
@(User)
+
+
+
@(Password)
+
+
+
@(My edge)
+
+
+
+`; +exports.readme = `Manager for CMD calls`; + + +exports.install = function(instance) { + + 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, isEmptyObject, emptyJsObject, writeToFile, addToArrayIfUnique } = require('./helper/utils'); + const bitwise = require('bitwise'); + + var SunCalc = require('./helper/suncalc'); + const DataToTbHandler = require('./helper/DataToTbHandler'); + const errorHandler = require('./helper/ErrorToServiceHandler'); + const { sendNotification } = require('./helper/notification_reporter'); + const process = require('process'); + const { errLogger, logger, monitor } = require('./helper/logger'); + + //for accelerometer purposes + const { naklony } = require("../databases/accelerometer_db"); + + const dbNodes = TABLE("nodes"); + const dbRelays = TABLE("relays"); + + let GLOBALS; + let SETTINGS; + let rsPort; + let tbHandler; + + // runTasks intervals + const SHORT_INTERVAL = 30; + const LONG_INTERVAL = 300; + + //send data to following instances: + const SEND_TO = { + debug: 0, + tb: 1, + http_response: 2, + dido_controller: 3, + infoSender: 4, + dailyReport: 5 + } + + 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 + } + + 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 sendNodeReadout = null; // interval for sending agregate data from node + + 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["1"] = minutes; // dimming + priorities["76"] = minutes; // power + + minutes = 5; + priorities["75"] = minutes; // current + priorities["79"] = minutes; // energy + priorities["87"] = minutes; // aktualny cas + //priorities["84"] = minutes; //accelerometer + + minutes = 10; + priorities["74"] = minutes; // voltage + priorities["77"] = minutes; // power factor + priorities["78"] = minutes; // frequency + + minutes = 60; + priorities["0"] = minutes; // statecode + priorities["6"] = minutes; // dusk + priorities["7"] = minutes; // dawn + priorities["8"] = minutes; // profile + + minutes = 60 * 24; + priorities["89"] = minutes; // verzia fw + priorities["80"] = minutes; // lifetime + + //prikazy kt sa budu spustat na dany node - see config.js in terminal-oms.app. (1 - dimming) + let listOfCommands = [0, 1, 6, 7, 8, 74, 75, 76, 77, 78, 79, 80, 87, 89]; + + 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; + + // holds dusk, dawn (and more) values + let sunCalcResult; + + //helper container for counting resolved group of commands (commands related to set profile) + let cmdCounter = {};//key is node, value is counter + + //TODO: is this set working?? According to previous checks, sets do not work + //if sending of profile to node fails, we send notification and push node into set, so we do not send notification twice + const nodeProfileSendFail = new Set(); + + //we expect to get current temperature in Senica from senica-prod01 + let temperatureInSenica = null; + let accelerometerInterval = null; + + //NOTE: daily reports senica: + //rvo_is_on status, we monitor all nodes - if true, power and dimming should be not 0, if false, 24/7 nodes should be 0, other rvo should not respond + let rvo_is_on; + let previous_rvo_is_on_value; + let handleDailyReport; //setInterval for dailyReportHandler function + let dailyReport = {}; //data needed for daily report + let reportToSend = {}; //final report which we send to cloud + let breakerCounter = null; // status of breakers after flow starts is not in report + let rvoPeriod; // interval of checking dusk dawn and if rvo_is_on + let initialReportStatus = false; + + const DAILY_REPORT_HANDLER_TIME = 3_600_000; + const SET_SUNCALC_RESULT_TIME = 3_600_000; + const SET_RVO_PERIOD_TIME = 300_000; + const ADD_NODE_TO_REPORT_TIME = 3_600_000; + + //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); + + let now = new Date(); + console.log("Cmd-mngr installed", now.toLocaleString("sk-SK")); + + sunCalcResult = calculateDuskDawn(); + + handleRsPort(); + + customTasksInterval = setInterval(reportEdgeDateTimeAndNumberOfLuminaires, 120_000); + setTimeout(reportEdgeDateTimeAndNumberOfLuminaires, 4000); + + //dailyReport related + emptyReportToSend(); + breakerCounter = Object.keys(relaysData).length - 1; // we get number of lines (breakers) except of line 0 + rvoPeriod = setInterval(setRvoPeriod, SET_RVO_PERIOD_TIME); + setTimeout(setRvoPeriod, 3000); + setInterval(setSunCalcResult, SET_SUNCALC_RESULT_TIME); + handleDailyReport = setInterval(dailyReportHandler, DAILY_REPORT_HANDLER_TIME); + + + setCorrectTime = setInterval(setCorrectPlcTimeOnceADay, 60000 * 60); // 1 hour + setCorrectPlcTimeOnceADay(); + + sendNodeReadout = setInterval(sendNodesData, 150_000); + accelerometerInterval = setInterval(accelerometerData, 60000 * 30); //30 min + } + + + 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" + //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 + // if node regular readout does not respond, we repeat request + params.repeatCounter = 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-mngr: 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.byte4 = 96; + params.recipient = 1; + params.register = 8; + params.rw = 1;//write + params.timestamp = timestamp; + 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.byte4 = 96; + params.recipient = 1; + params.register = 8; + params.rw = 1;//write + params.timestamp = timestamp; + 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). + */ + + 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.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.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 + { + + logger.debug("processNodeProfile: Threshold lux level for DUSK/DAWN", node); + + let params = getParams(); + params.type = "set_node_profile"; + params.address = node; + params.register = 96; + params.recipient = 1; + params.rw = 1;//write + params.timestamp = timestamp; + 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(); + params.type = "set_node_profile"; + params.address = node; + params.register = 97; + params.recipient = 1; + params.rw = 1;//write + params.timestamp = timestamp; + 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.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); + + 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); + + console.log("proces profile finished *********************") + } + + + 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; + }); + } + + + 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) { + for (let k in nodesData) { + 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`); + } + } + } + + + function loadRelaysData(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 (value.contactor == 1) processAllNodeProfilesOnLine(value.line); + } + } + + + function reportOnlineNodeStatus(line) { + //Po zapnutí línie broadcastovo aktualizovať predtým čas a o 3 sek neskor - status, brightness + + logger.debug("Cmd-mngr: ----->reportOnlineNodeStatus for line", line); + + const d = new Date(); + + // broadcast actual time + let params = getParams(); + params.address = 0xffffffff;//Broadcast + params.byte1 = d.getHours(); + params.byte2 = d.getMinutes(); + params.recipient = 2;//2 broadcast, address = 0 + params.register = 87;//Actual time + params.rw = 1;//write + params.type = "node-onetime-write"; + params.timestamp = d.getTime() + 30000; + params.info = "run broadcast: Actual time"; + //params.debug = true; + + tasks.push(params); + + let sec = 3; + setTimeout(function() { + //Po zapnutí línie - spraviť hromadný refresh stavu práve zapnutých svietidiel + + let time = Date.now(); + + for (let k in nodesData) { + + //potrebujem nody k danej linii + 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].node_status_before_offline === true || nodesData[k].status === true) { + status = "OK"; + nodesData[k].time_of_last_communication = time; + } + + nodesData[k].readout.status = status; + + updateNodeStatus(k, status === "OK" ? true : false); + if (nodesData[k].hasOwnProperty("node_status_before_offline")) delete nodesData[k].node_status_before_offline; + sendTelemetry({ status: status }, tbname, time); + + //vyreportovanie dimming, current, input power pre liniu pre vsetky nody + //Prud + { + let params = getParams(); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 75;//prud + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = time + 4000; + params.info = 'read current'; + //params.debug = true; + tasks.push(params); + } + + //vykon + { + let params = getParams(); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 76;//výkon + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = time + 4100; + params.info = 'read power'; + //params.debug = true; + + tasks.push(params); + } + //dimming + { + let params = getParams(); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 1;//dimming + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = time + 4200; + params.info = 'read dimming'; + //params.debug = true; + + tasks.push(params); + } + + } + } + + }, sec * 1000); + } + + + function reportOfflineNodeStatus(line) { + + logger.info("Cmd-mngr: ------>reportOffLineNodeStatus for line ", line); + + values = {}; + values["dimming"] = 0;//brightness + values["power"] = 0;//výkon + values["current"] = 0;//prúd + values["status"] = "OFFLINE"; + + const date = Date.now(); + + Object.keys(nodesData).forEach(node => { + + //potrebujem nody k danej linii + if (line == nodesData[node].line || line == undefined) { + + let tbname = nodesData[node].tbname; + let nodeStatus = nodesData[node].status; + + //in case we have reported offline node status, we return (continue with next node) + if (nodeStatus === "OFFLINE") return; + + nodesData[node].node_status_before_offline = nodeStatus; + nodesData[node].status = "OFFLINE"; + nodesData[node].readout = {}; + + sendTelemetry({ ...values }, tbname, date); + } + }); + + } + + + function turnLine(onOrOff, line, info) { + let obj = { + line: line, + command: onOrOff, + info: info + }; + + //to assure, handleDailyReportFunction do not run before rvo_is_on variable changes. So after every line switch we reset the timer + clearInterval(handleDailyReport); + handleDailyReport = setInterval(dailyReportHandler, DAILY_REPORT_HANDLER_TIME); + + //logger.debug("linia", line, obj); + instance.send(SEND_TO.dido_controller, obj); + } + + + 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"; + 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]) { + //CRC_ERROR + message = "NOK"; + error = "CRC_ERROR c1"; + instance.send(SEND_TO.debug, "CRC_ERROR c1"); + } + + 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") { + instance.send(SEND_TO.debug, bytes); + instance.send(SEND_TO.debug, "RESPONSE " + type + " - " + bytes[4]); + + //logger.debug(SEND_TO.debug, "RESPONSE " + type + " - " + bytes[4], bytes); + + error = "type is: " + type; + + message = "NOK"; + } + + return { message, type, error }; + } + + + //BUILD TASKS// + function buildTasks(params) { + + //return; + console.log("buidTAaasks start ****************", params); + monitor.info("buildTasks - params", params); + + let processLine; //defined line + let init = false; + let processLineProfiles = true; + let processBroadcast = true; + let processNodes = true; + + if (params == undefined) { + init = true; + tasks = []; + logger.debug("-->buildTasks clear tasks"); + } + else { + processLineProfiles = params.processLineProfiles; + processBroadcast = false; + processNodes = false; + + processLine = params.line; + } + + let now = new Date(); + + //process line profiles + if (processLineProfiles) { + + let keys = Object.keys(relaysData); + + for (let i = 0; i < keys.length; i++) { + + let line = parseInt(keys[i]); + let profilestr = relaysData[line].profile; + + if (processLine != undefined) { + if (processLine != line) continue; + } + + try { + + /** + * we process line profiles: timepoints, astro clock, lux_sensor, offsets ... + */ + if (profilestr === "") throw ("Profile is not defined"); + let profile = JSON.parse(profilestr); + 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; + + // add name to regular profile timepoint and delete unused end_time key: + time_points.forEach(point => { + point.name = "profileTimepoint" + delete point.end_time; + }); + + //monitor.info("buildTasks: time_points", time_points); + + + /** + * 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 astro clock true, we remove all regular profile points + time_points = []; + + //TODO: when astro clock == true, is offset calculated ??? + //let duskAstroClockOffset = profile.dusk_astro_clock_offset; + //let dawnAstroClockOffset = profile.dawn_astro_clock_offset; + //console.log("line astro clock offsets dusk a dawn: ", duskAstroClockOffset, dawnAstroClockOffset); + // maybe add dusk dawn offset to calculateDuskDawn ?? what dusk dawn will be if dawn_lux_sensor == true?? + //let sunCalcResult = calculateDuskDawn(new Date(), line, duskAstroClockOffset, dawnAstroClockOffset); + + 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 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); + + 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); + + 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(':'); + + let ad = new Date(); + ad.setHours(parseInt(ahours), parseInt(aminutes), 0); + + let bd = new Date(); + bd.setHours(parseInt(bhours), parseInt(bminutes), 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++) { + + let start_time = new Date(); + let [hours, minutes] = time_points[t].start_time.split(':'); + start_time.setHours(parseInt(hours), parseInt(minutes), 0); + + //task is in 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(); + params.type = "relay"; + params.line = parseInt(line); + params.value = time_points[t].value; + params.tbname = relaysData[line].tbname; + params.timestamp = start_time.getTime(); + + // 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; + + //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)) { + 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; + + params.debug = true; + + //turn on/off line + tasks.push(params); + monitor.info("TimePoint params: ", params.info, start_time); + } + + monitor.info("-->time_points final", line, time_points); + + //ensure to turn on/off according to calculated currentValue + let params = getParams(); + params.type = "relay"; + params.line = parseInt(line); + params.tbname = relaysData[line].tbname; + params.value = currentValue; + params.timestamp = i; + params.debug = true; + + //logger.debug(now.toLocaleString("sk-SK")); + 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; + + tasks.push(params); + + } catch (error) { + if (profilestr !== "") { + //errLogger.error(profilestr, error); + console.log(`Cmd_mngr: Unable to process line profile ${line}. Error: `, error); + errorHandler.sendMessageToService(profilestr + "-" + error, 0, "js_error"); + } else { + turnLine("off", line, "No line profile. Switching it off on startup"); + } + } + + } + //logger.debug("tasks:"); + //logger.debug(tasks); + } + + + //NOTE: PROCESS DEFAULT BROADCASTS - Time of dusk, Time of dawn, Actual Time + if (processBroadcast) { + + let d = new Date(); + let time = d.getTime(); + //let sunCalcResult = calculateDuskDawn(); + + { + let params = getParams(); + + params.address = 0xffffffff;//broadcast + params.byte1 = sunCalcResult["dusk_hours"]; + params.byte2 = sunCalcResult["dusk_minutes"]; + params.recipient = 2;//2 broadcast, + params.register = 6;//Time of dusk + params.rw = 1;//write + params.type = "node-regular-write"; + params.timestamp = time + 60000; + params.addMinutesToTimestamp = 60 * 3; //kazde 3 hodiny zisti novy dusk + params.info = "Broadcast-duskTime"; + + tasks.push(params); + } + + { + let params = getParams(); + + params.address = 0xffffffff;//broadcast + params.byte1 = sunCalcResult["dawn_hours"]; + params.byte2 = sunCalcResult["dawn_minutes"]; + params.recipient = 2; //2 broadcast + params.register = 7;//Time of dawn + params.rw = 1;//write + params.type = "node-regular-write"; + params.timestamp = time + 60001; + params.addMinutesToTimestamp = 60 * 3; //kazde 3 hodiny zisti novy dawn + params.info = "Broadcast-dawnTime"; + + tasks.push(params); + } + + { + let params = getParams(); + + params.address = 0xffffffff;//broadcast + params.byte1 = d.getHours(); + params.byte2 = d.getMinutes(); + params.recipient = 2; //2 broadcast + params.register = 87;//Actual time + params.rw = 1;//write + params.type = "node-regular-write"; + params.timestamp = time + 60002; + params.addMinutesToTimestamp = 5; + params.info = "run broadcast: Actual time"; + + tasks.push(params); + } + + } + + //process nodes & tasks - read node's data + if (processNodes) { + + let time = Date.now(); + + for (let k in nodesData) { + let address = parseInt(k); + let tbname = nodesData[k].tbname; + let register = 0; + + for (let i = 0; i < listOfCommands.length; i++) { + + register = listOfCommands[i]; + let addMinutesToTimestamp = priorities[register]; + + let params = getParams(); + + params.address = address; + params.recipient = 1; + params.register = register; + params.type = register == 1 ? "node-dimming-read" : "node-regular-read"; + params.tbname = tbname; + params.timestamp = time + 5000 + i * 500 + addMinutesToTimestamp * 1000; //to make slight time difference + params.addMinutesToTimestamp = addMinutesToTimestamp; + params.info = "Node regular read command"; + + tasks.push(params); + } + + } + } + + + //niektore ulohy sa vygeneruju iba 1x pri starte!!! + if (!init) return; + + + //Master node FW version - modifies SETTINGS.masterNodeIsResponding + { + let params = getParams(); + params.type = "cmd-master"; + params.register = 4; + params.address = 0; + params.timestamp = 0; + params.addMinutesToTimestamp = 5; + params.tbname = SETTINGS.rvoTbName; + params.info = "Master node FW verzia"; + //params.debug = true; + + tasks.push(params); + } + + //kazdu hodinu skontrolovat nastavenie profilov + { + let params = getParams(); + params.type = "process_profiles"; + params.timestamp = Date.now() + 60001; + params.addMinutesToTimestamp = 60;//60 = every hour + params.info = "detekcia nespracovaných profilov linie a nodov"; + //params.debug = true; + + tasks.push(params); + } + + monitor.info("tasks created:", tasks.length); + } + + + /** + * We process line profile, where "astro_clock": true + * example profile: + * + "dawn_lux_sensor": true, + "dusk_lux_sensor": true, + "dawn_lux_sensor_value": 5, + "dusk_lux_sensor_value": 5, + "dawn_astro_clock_offset": 0, + "dusk_astro_clock_offset": 10, + "dawn_lux_sensor_time_window": 30, + "dusk_lux_sensor_time_window": 30, + "dawn_astro_clock_time_window": 60, + "dusk_astro_clock_time_window": 60 + + * if dawn: if currentTimestamp is in timewindow "dawnTime + and - dawn_lux_sensor_time_window" and lux value >= lux_sensor_value, we switch off the line. + * if dusk: we do oposite + * + * dawn: usvit - lux je nad hranicou - vypnem + * dusk: sumrak - lux je pod hranicou - zapnem + */ + 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++) { + + let line = keys[i]; //line is turned off by default + let profilestr = relaysData[line].profile; + const contactor = relaysData[line].contactor; + + try { + + let profile = JSON.parse(profilestr); + if (Object.keys(profile).length === 0) throw ("turnOnOffLinesAccordingToLuxSensor - profile is not defined"); + + 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 (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"); + } + } + } + + //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 (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"); + } + } + } + + } + + } catch (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) { + //MASTER + if (node == 0) return; + + let nodeObj = nodesData[node]; + if (nodeObj == undefined) return; + + let nodeCurrentStatus = nodeObj.status; + const now = Date.now(); + + let data = null; + + if (nodeCurrentStatus === "OFFLINE") { + data = { status: newStatus }; + nodeDbStatusModify(node, data); + return; + } + else 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; + } + + } + + + 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 }; + } + }); + }); + } + + + function processDailyReport() { + + const now = Date.now(); + + for (const [key, value] of Object.entries(dailyReport)) { + + if (["name", "time", "dusk_and_dawn"].includes(key)) continue; + + let poleNumber = nodesData[key]["pole_number"]; + let line = dailyReport[key].line; + let nodeType = nodesData[key]["node_type"]; + let fullNodeName = key // key == nodeNumber + + if (poleNumber && nodeType) { + fullNodeName = SETTINGS.rvo_number + "/" + poleNumber + "_" + line + "L_" + key + "_" + nodeType; + } else { + fullNodeName = key; + } + + if (rvo_is_on) { + + if (value.initialTs) { + if (value.initialTs + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["night_no_data"], fullNodeName); + console.log('report nedostava ziadne data uz hodinu', fullNodeName); + value.initialTs = now; + } + } + if (value.dimmingIsZeroTime) { + if (value.dimmingIsZeroTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["night_dimming=0"], fullNodeName); + console.log("report node dimming je 0 ale ma svietit", fullNodeName); + value.dimmingIsZeroTime = now; + } + } + if (value.powerIsZeroTime) { + if (value.powerIsZeroTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["night_power=0"], fullNodeName); + console.log("report node power je 0 ale ma svietit", fullNodeName); + value.powerIsZeroTime = now; + } + } + + } else { + + let contactorStatus = relaysData[line].contactor; + if (contactorStatus === 1) { + + if (value.initialTs) { + if (value.initialTs + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["day_24/7_no_data"], fullNodeName); + console.log('node je na 24/7 ale nedostava ziadne data uz hodinu', fullNodeName); + value.initialTs = now; + } + } + if (value.dimmingIsOnButShouldBeOffTime) { + if (value.dimmingIsOnButShouldBeOffTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["day_24/7_dimming>0"], fullNodeName); + console.log("report dimming je > 0 ale nema svietit", fullNodeName); + value.dimmingIsOnButShouldBeOffTime = now; + } + } + if (value.powerIsOnButShouldBeOffTime) { + if (value.powerIsOnButShouldBeOffTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["day_24/7_power>0"], fullNodeName); + console.log("report power je > 0 ale nema svietit", fullNodeName); + value.powerIsOnButShouldBeOffTime = now; + } + } + + } + + } + + } + + let report = {}; + report["name"] = SETTINGS.rvo_name; + report["time"] = new Date(); + report["report"] = reportToSend; + + writeToFile(F.path.root("report_data.log"), report, true); + instance.send(SEND_TO.dailyReport, report); + } + + + function dailyReportHandler() { + + if (!SETTINGS.daily_report) return; + + // after dawn we empty reportToSend and start to get data for a new day + const date = new Date(); + const hour = date.getHours(); + const minute = date.getMinutes(); + + console.log("now: ", hour, minute, "suncalc: ", sunCalcResult.dawn_hours, sunCalcResult.dawn_minutes); + + if (hour === sunCalcResult.dawn_hours) { + + //NOTE: ak je este pred usvitom, spracujeme report a posleme na cloud, ak uz je po usvite, resetujeme report plnime data noveho dna + if (minute >= sunCalcResult.dawn_minutes - 2) { + emptyReportToSend(); + emptyDailyReport(); + console.log("Podmienka 1 v dailyReport handler"); + } else { + processDailyReport(); + emptyReportToSend(); + emptyDailyReport(); + console.log("Podmienka 2 v dailyReport handler"); + } + + initialReportStatus = true; + + // ak sa funkcia spusti o hodinu alebo 2 neskor, ako je usvit (moze sa to stat, kedze kazde zapnutie/vypnutie linii odznova spusti casovac. + } else if (hour === sunCalcResult.dawn_hours + 1 || hour === sunCalcResult.dawn_hours + 2) { + if (!initialReportStatus) { + emptyReportToSend(); + emptyDailyReport(); + initialReportStatus = true; + console.log("Podmienka 3 v dailyReport handler"); + } else { + processDailyReport(); + initialReportStatus = true; + console.log("Podmienka 4 v dailyReport handler"); + } + } else { + processDailyReport(); + initialReportStatus = false; + console.log("Podmienka 5 v dailyReport handler"); + } + + console.log("initialReportStatus: ", initialReportStatus); + + } + + function emptyReportToSend() { + emptyJsObject(reportToSend); + reportToSend["contactor"] = { off: [], on: [] }; + reportToSend["night_no_data"] = []; + reportToSend["night_dimming=0"] = []; + reportToSend["night_power=0"] = []; + reportToSend["day_24/7_no_data"] = []; + reportToSend["day_24/7_dimming>0"] = []; + reportToSend["day_24/7_power>0"] = []; + console.log(`resetuje sa reportToSend`); + } + + + //NOTE: ked je initialTs stale rovnaky a zistime ze linie su vypnute (relaysData.line.contactor) - zistim, ci je node na tej linii. Vieme, ze ak je linia vypnuta je to v poriadku lebo nie je na 24/7 linii + //ak je na 24/7 linii, reportujeme, ze neprijima data + function emptyDailyReport() { + const ts = Date.now(); + emptyJsObject(dailyReport); + + //NOTE: do dailyReport dame vsetky nody a pravidelne kontrolujeme ci maju data + //ked nastane sumrak/usvit a svetla maju zacat/prestat svietit, dailyReport spravime nanovo: + for (const [key, value] of Object.entries(nodesData)) { + dailyReport[value.node] = { line: value.line, initialTs: ts }; + } + + console.log("dailyReport: ", dailyReport); + } + + + async function runTasks() { + + clearInterval(interval); + + let currentTimestamp = Date.now(); + + //sort tasks based on timestamp + 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) { + instance.send(SEND_TO.debug, "no tasks created"); + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + if (!rsPort.isOpen) { + instance.send(SEND_TO.debug, "!rsPort.isOpen"); + //await rsPort.open(); + //console.log("Cmd-mngr: !rsPort.isOpen"); + } + + let currentTask = tasks[0]; + + if (currentTask.debug) { + //logger.debug("--->task to process", currentTask); + } + + if (currentTask.timestamp <= currentTimestamp) { + let params = { ...tasks[0] }; + + //allow terminal commands + if (SETTINGS.maintenance_mode && params.type !== "cmd-terminal") { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + let type = params.type; + let tbname = params.tbname; + let node = params.address; + let register = params.register; + let line = null; + let itIsNodeCommand; + + if (nodesData[node] !== undefined) { + line = nodesData[node].line; + itIsNodeCommand = true; + } + + if (params.line !== undefined) line = params.line; + + if (params.addMinutesToTimestamp > 0 || params.timePointName) { + tasks[0].timestamp = currentTimestamp + tasks[0].addMinutesToTimestamp * 60000; + } else { + tasks.shift(); + } + + //kontrola nespracovanych profilov nodov + //TODO: co ked niektore nody neprijimaju profily? kazdu hodinu zahltuju "tasks" array + if (type == "process_profiles") { + //na vsetky zapnutych liniach sa spracuju nespracovane profily nodov + loadRelaysData(); + interval = setInterval(runTasks, SHORT_INTERVAL); + return; + } + + //relay + if (type == "relay") { + + const timePointName = params.timePointName; + const value = params.value; + + let date = new Date(); + date.setDate(date.getDate() + 1);//next day + + let sunCalcResult; + if (timePointName) sunCalcResult = calculateDuskDawn(date, params.line); + + + if (timePointName == "dawn") { + tasks[0].timestamp = sunCalcResult.dawn_time; + } + else if (timePointName == "dusk") { + tasks[0].timestamp = sunCalcResult.dusk_time; + } + else if (timePointName == "luxOn") { + tasks[0].timestamp = sunCalcResult.dusk_time + params.dusk_lux_sensor_time_window * 60000; + } + else if (timePointName == "luxOff") { + tasks[0].timestamp = sunCalcResult.dawn_time + params.dawn_lux_sensor_time_window * 60000; + } + else if (timePointName == "profileTimepoint") { + tasks[0].timestamp = currentTimestamp + tasks[0].addMinutesToTimestamp * 60000; + } + + let info = "aplikovany bod profilu"; + let onOrOff = ""; + value == 1 ? onOrOff = "on" : onOrOff = "off"; + + turnLine(onOrOff, params.line, info); + + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + if (!SETTINGS.masterNodeIsResponding) { + //ak neodpoveda, nebudeme vykonavat ziadne commands, okrem cmd-terminal cmd-master + errorHandler.sendMessageToService("Master node is not responding"); + + let stop = true; + + if (type === "cmd-terminal" || type === "cmd-master") stop = false; + if (stop) { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + } + + let contactorStatus = 1; + if (relaysData[line] != undefined) contactorStatus = relaysData[line].contactor; + + if (line === 0 || contactorStatus === 0 || FLOW.deviceStatus.state_of_breaker[line] === "Off") { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + // TODO: -> status offline for rvo if rotary_switch_state is OFF, this is source of errors + // check if rotary_switch_state == "Off" + // state_of_braker: disconnected = true? + + if (!rsPort.isOpen) { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + //RE-CALCULATE VALUES + //set actual time for broadcast + if (register == 87 && params.recipient === 2) { + var d = new Date(); + params.byte1 = d.getHours();//h + params.byte2 = d.getMinutes();//m + } + + //SET DUSK/DAWN FOR BROADCAST + //Time of dusk + if (register == 6 && params.recipient === 2) { + + if (type != "cmd-terminal") { + params.byte1 = sunCalcResult["dusk_hours"];//h + params.byte2 = sunCalcResult["dusk_minutes"];//m + } + } + + //Time of dawn + if (register == 7 && params.recipient === 2) { + if (type != "cmd-terminal") { + params.byte1 = sunCalcResult["dawn_hours"];//h + params.byte2 = sunCalcResult["dawn_minutes"];//m + } + } + //----------------------- + + instance.send(SEND_TO.debug, "address: " + node + " register:" + register + "type: " + type); + + var startTime, endTime; + startTime = new Date(); + + let saveToTb = true; + if (!tbname) saveToTb = false; + + let resp = com_generic(node, params.recipient, params.rw, register, params.name, params.byte1, params.byte2, params.byte3, params.byte4); + let readBytes = 11; + let timeout = 4000; + + + // await keyword is important, otherwise incorrect data is returned! + await writeData(rsPort, resp, readBytes, timeout).then(function(data) { + + //sometimes happens, that status of node changes to OK, NOK even if line was turned off and should be status OFFLINE. To prevent this, we return if line contactor is 0: + if (itIsNodeCommand && line && relaysData[line].contactor !== 1) return; + + 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); + + //ak sa odpoved zacina 0 - je to v poriadku, inak je NOK + let message = result.message; // OK, NOK + let message_type = result.type; + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + console.log("detected response:", result); + logger.debug("Cmd-mngr: writeData done " + message_type + " duration: " + timeDiff + " type: " + params.debug, params, result); + } + } + + let values = {}; + + //CMD FINISHED + if (message == "OK") { + + updateNodeStatus(node, true); + + //write + if (type == "set_node_profile") { + let result = cmdCounterResolve(node); + if (result == 0) { + dbNodes.modify({ processed: true }).where("node", node).make(function(builder) { + builder.callback(function(err, response) { + + sendNotification("Cmd-mngr: process cmd", SETTINGS.rvoTbName, "dimming_profile_was_successfully_received_by_node", { node: node }, "", SEND_TO.tb, instance); + + logger.debug("--> profil úspešne odoslaný na node č. " + node); + nodesData[node].processed = true; + nodeProfileSendFail.delete(node); + }); + }); + } + } + + //parse read response + if (params.rw == 0) { + values = processResponse(register, dataBytes); //read + } + + if (itIsNodeCommand) { + values.comm_status = "OK"; + values.status = "OK"; + nodesData[node].readout = { ...nodesData[node].readout, ...values }; + + + if (SETTINGS.daily_report) { + //TODO: co ak nedostavame odpovede z nodu ? Musime vyreportovat!! + //v dailyReport teda musi byt kompletny zoznam nodov a neustale kontrolovat, ci maju data, ak nie report node - neodpoveda + if (register === 1) { + + let now = Date.now(); + + if (rvo_is_on === true) { + + if ("dimmingIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].dimmingIsOnButShouldBeOffTime; + + if (values.dimming > 0) { + if ("dimmingIsZeroTime" in dailyReport[node]) delete dailyReport[node].dimmingIsZeroTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if (!("dimmingIsZeroTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], dimmingIsZeroTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } else { + + if ("dimmingIsZeroTime" in dailyReport[node]) delete dailyReport[node].dimmingIsZeroTime; + + if (values.dimming > 0) { + if (!("dimmingIsOnButShouldBeOffTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], dimmingIsOnButShouldBeOffTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if ("dimmingIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].dimmingIsOnButShouldBeOffTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } + } + + if (register === 76) { + + let now = Date.now(); + + if (rvo_is_on === true) { + + if ("powerIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].powerIsOnButShouldBeOffTime; + + if (values.power > 1) { + if ("powerIsZeroTime" in dailyReport[node]) delete dailyReport[node].powerIsZeroTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if (!("powerIsZeroTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], powerIsZeroTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } else { + + if ("powerIsZeroTime" in dailyReport[node]) delete dailyReport[node].powerIsZeroTime; + + if (values.power > 1) { + if (!("powerIsOnButShouldBeOffTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], powerIsOnButShouldBeOffTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if ("powerIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].powerIsOnButShouldBeOffTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } + } + } + + } + + //master node + if (node == 0) { + sendNotification("Cmd-mngr: 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; + } + + if (params.debug) { + //logger.debug("saveToTb", saveToTb, tbname, values); + } + + if (saveToTb && type != "node-regular-read") { + sendTelemetry(values, tbname); + } + else { + if (type == "cmd-terminal") { + terminalCommandResponse(params, "SUCCESS", data); + } + } + + } + else { + terminalCommandResponse(params, "ERROR", data); + handleNokResponseOnRsPort("handleNOK else block", params, itIsNodeCommand, saveToTb); + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + //logger.debug("writeData err: ", error, result, params); + logger.debug("writeData err: ", tbname, node, register, values); + } + } + + //logger.debug(error, result, params); + } + }).catch(function(reason) { + + //console.log("writeData catch exception", reason); + instance.send(SEND_TO.debug, reason); + + terminalCommandResponse(params, "FAILURE", null, reason); + handleNokResponseOnRsPort("handleNOK catch block", params, itIsNodeCommand, saveToTb); + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + logger.debug("-->WRITE FAILED: " + reason, params.debug, params); + } + } + + }); + + } + 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); + } + + + // if node does not respond to request, we repeat request 3 times: + function repeatCommand(params) { + params.repeatCounter++; + if (params.repeatCounter < 4) { + params.timestamp = 0; + params.addMinutesToTimestamp = 0; + tasks.push(params); + } + } + + function handleNokResponseOnRsPort(message, params, itIsNodeCommand, saveToTb) { + + let node = params.address; + let register = params.register; + let type = params.type; + let tbName = params.tbname; + if (!tbName) return; + + let values = {}; + + let updateStatus = updateNodeStatus(node, false); + + if (itIsNodeCommand) { + values.comm_status = "NOK"; + nodesData[node].readout.comm_status = "NOK"; + repeatCommand(params); + } + + if (updateStatus) { + values.status = "NOK"; + nodesData[node].readout.status = "NOK"; + } + + if (type === "node-regular-read") return; + + //master node + if (node == 0) { + sendNotification("Cmd-mngr: 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; + + if (register == 4) values["master_node_version"] = "NOK"; + } + + if (type == "set_node_profile") { + delete cmdCounter[node]; + logger.debug("profil nebol úspešne odoslaný na node č. ", params); + + if (!nodeProfileSendFail.has(node)) { + sendNotification("Cmd-mngr: process cmd", tbName, "configuration_of_dimming_profile_to_node_failed", { node: node }, "", SEND_TO.tb, instance); + nodeProfileSendFail.add(node); + } + } + + // console.log("------",node, register, type, itIsNodeCommand, updateStatus, saveToTb, values); + if (saveToTb) { + sendTelemetry(values, tbName); + } + + } + + + function sendNodesData() { + Object.keys(nodesData).forEach(node => { + if (nodesData[node]["status"] !== "OFFLINE") { + sendTelemetry(nodesData[node].readout, nodesData[node].tbname); + nodesData[node].readout = {}; + } + }) + } + + + /** + * 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; + } + + 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); + + //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 === "OFFLINE") { + nodeObj.node_status_before_offline === true ? number_of_ok_luminaires++ : number_of_nok_luminaires++; + } + else if (nodeObj.status == true) 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 - ts % 60000 //round to full minute + }; + + sendTelemetry(values, SETTINGS.rvoTbName, ts); + } + + + function setSunCalcResult() { + //if next day, we get new dusk and dawn. To make sure, in local timezone 2:00 means 00:00 in utc (it means next day) + if (new Date().getHours() === 2) { + sunCalcResult = calculateDuskDawn(); + console.log("Novy suncalc: ", sunCalcResult); + } + } + + + function setRvoPeriod() { + + if (!SETTINGS.daily_report) return; + + const ts = Date.now(); + + previous_rvo_is_on_value = rvo_is_on; + + if (ts < sunCalcResult.dawn_time - 1_800_000) { // nodes should be on (00:00 -> 06:00 ( - pol hodina, lebo rvo vypina skor) + rvo_is_on = true; + } else if (sunCalcResult.dawn_time - 1_800_000 < ts && ts < sunCalcResult.dusk_time + 1_800_000) { // nodes should be off 06:00 -> 21:00 + rvo_is_on = false; + } else if (sunCalcResult.dusk_time + 1_800_000 < ts) { // nodes should be on 21:00 -> 00:00 + rvo_is_on = true; + } + + if (previous_rvo_is_on_value !== rvo_is_on) { + emptyDailyReport(); + console.log("rvo_is: ", rvo_is_on, previous_rvo_is_on_value); + } + } + + + function handleRsPort() { + + if (rsPort) { + rsPort.removeAllListeners(); + rsPort = null; + } + + //! 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-mngr: rsPort opened success"); + + 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); + + }).catch(function(reason) { + instance.send(SEND_TO.debug, "Cmd-mngr: RPC runSyncExec - promise rejected:" + reason); + }); + }); + + rsPort.on('error', function(err) { + errorHandler.sendMessageToService([exports.title, "unable to open port", SETTINGS.serial_port, err.message], 0); + monitor.info("Cmd-mngr: Error on rsPort", err.message); + }); + + rsPort.on("close", () => { + monitor.info("Cmd-mngr: rsPort closed, reconnecting..."); + setTimeout(handleRsPort, 1000); + }); + + rsPort.open(); + } + + + instance.on("close", () => { + clearInterval(interval); + clearInterval(customTasksInterval); + clearInterval(setCorrectTime); + clearInterval(sendNodeReadout); + clearInterval(accelerometerInterval); + rsPort.close(); + }); + + instance.on("0", _ => { + main(); + }) + + + instance.on("2", _ => { + console.log("dailyReport, reportToSend, rvo_is_on", dailyReport, reportToSend, rvo_is_on, previous_rvo_is_on_value); + }) + + instance.on("1", 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(); + return; + } + else if (flowdata.data == "close") { + rsPort.close(); + return; + } + else if (flowdata.data == "clean") { + tasks = []; + return; + } + else if (flowdata.data == "buildtasks") { + //build & run + return; + } + else if (flowdata.data == "run") { + //durations = []; + + if (tasks.length == 0) { + + buildTasks(); + + if (rsPort.isOpen) { + interval = setInterval(runTasks, 100); + } + else { + instance.send(SEND_TO.debug, "port is not opened!!!"); + } + } + } + else { + //terminal data - object + //logger.debug("flowdata", flowdata.data); + + if (typeof flowdata.data === 'object') { + //logger.debug("dido", flowdata.data); + if (flowdata.data.hasOwnProperty("sender")) { + //data from dido_controller + if (flowdata.data.sender == "dido_controller") { + + if (flowdata.data.hasOwnProperty("cmd")) { + let cmd = flowdata.data.cmd; + + if (cmd == "buildTasks") { + clearInterval(interval); + + logger.debug("-->Cmd-mngr: BUILD TASKS"); + buildTasks(); + + //logger.debug("tasks:"); + //logger.debug(tasks); + + logger.debug("-->Cmd-mngr: RUN TASKS"); + interval = setInterval(runTasks, 5000); + } + else if (cmd == "reload_relays") { + loadRelaysData(flowdata.data.line); + + if (flowdata.data.dataChanged) { + if (!flowdata.data.value) { + reportOfflineNodeStatus(flowdata.data.line); + } + else { + reportOnlineNodeStatus(flowdata.data.line); + } + } + + } + else if (cmd == "rotary_switch_state") { + let value = flowdata.data.value; + + //state was changed + if (rotary_switch_state != value) { + if (value == "Off") { + //vyreportovat vsetky svietdla + reportOfflineNodeStatus(); + } + + rotary_switch_state = value; + } + } + 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) { + + // we send lux_sensor value to all nodes: + let params = getParams(PRIORITY_TYPES.node_broadcast); + + params.recipient = 2;//2 broadcast, address = 0 + params.address = 0xffffffff;//Broadcast + + let ba = longToByteArray(lux_sensor); + + params.byte3 = ba[1];//msb + params.byte4 = ba[0]; + params.timestamp = PRIORITY_TYPES.node_broadcast; + params.info = "run broadcast: Actual Lux level from cabinet"; + params.register = 95;//Actual Lux level from cabinet + params.rw = 1;//write + + tasks.push(params); + + //process profiles + turnOnOffLinesAccordingToLuxSensor(lux_sensor); + } + } + else if (cmd == "state_of_breaker") { + //istic linie + + breakerCounter--; + + let value = flowdata.data.value; + let line = parseInt(flowdata.data.line); + + let dataChanged = false; + if (state_of_breaker[line] != value) dataChanged = true; + + state_of_breaker[line] = value; + + let status = "OK"; + if (value == "Off") status = "NOK"; + + if (dataChanged) { + + if (relaysData.hasOwnProperty(line)) { + let tbname = relaysData[line].tbname; + + if (value == "Off") { + sendNotification("Cmd-mngr: onData", tbname, "circuit_breaker_was_turned_off_line", { line: line }, "", SEND_TO.tb, instance, "circuit_breaker"); + if (breakerCounter < 0) reportToSend["contactor"]["off"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + else { + sendNotification("Cmd-mngr: onData", tbname, "circuit_breaker_was_turned_on_line", { line: line }, "", SEND_TO.tb, instance, "circuit_breaker"); + if (breakerCounter < 0) reportToSend["contactor"]["on"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + + //report status liniu + sendTelemetry({ status: status }, tbname) + + //current value + if (value == "Off") reportOfflineNodeStatus(line); //vyreportovat vsetky svietidla na linii + } + + } + } + else { + logger.debug("undefined cmd", cmd); + } + } + } + + return; + } + + //data from worksys + if (flowdata.data.hasOwnProperty("topic")) { + + let data = getNested(flowdata.data, "content", "data"); + + //if we get temperature in senica from senica-prod01 + let temperature = getNested(flowdata.data, "content", "senica_temperature"); + + if (temperature !== undefined) { + temperatureInSenica = temperature; + return; + } + + if (data === undefined) { + console.log("Invalid rpc command came from platform"); + return; + } + + let command = data.params.command; + let method = data.method; + let profile = data.params.payload; + if (profile == undefined) profile = ""; + let entity = data.params.entities[0]; + let entity_type = entity.entity_type; + let tbname = entity.tb_name; + + instance.send(SEND_TO.debug, flowdata.data); + 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") { + + //let command = data.params.command; + let value = data.params.payload.value; + + if (command == "dimming") { + + let nodeWasFound = false; + let keys = Object.keys(nodesData); + + //logger.debug("-----", keys); + + 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); + + value = parseInt(value); + if (value > 0) value = value + 128; + + params.type = "node-onetime-write"; + params.tbname = tbname; + params.address = node; + params.register = 1; + params.recipient = 1; + params.byte4 = value; + params.rw = 1; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'set dimming from platform'; + //params.debug = true; + + //debug(params); + logger.debug("dimming", params); + + tasks.push(params); + + 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); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 1; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read dimming (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + //pridame aj vyreportovanie - vykon + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 76; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read Input Power (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + //pridame aj vyreportovanie - prud svietidla + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 75; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read Input Current (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + //pridame aj vyreportovanie - power faktor - ucinnik + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 77; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read power factor (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + }, 4000); + + nodeWasFound = true; + break; + } + } + + if (!nodeWasFound) { + logger.debug("set dimming from platform", "unable to find tbname", tbname); + } + } + else { + instance.send(SEND_TO.debug, "undefined command " + command); + logger.debug("undefined command", command); + } + + return; + } + 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++) { + let node = keys[i]; + if (tbname == nodesData[node].tbname) { + + 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"); + + //profil úspešne prijatý pre node č. xx + sendNotification("Cmd-mngr", tbname, "dimming_profile_was_processed_for_node", { node: node }, profile, SEND_TO.tb, instance); + + nodesData[node].processed = false; + nodesData[node].profile = profile; + + processNodeProfile(node); + }); + }); + } + } + } + else { + + instance.send(SEND_TO.debug, "unknown method " + method); + logger.debug("unknown method", method); + + return; + } + } + + //nastav profil linie z platformy + 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") { + + 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++) { + let line = keys[i]; + if (tbname == relaysData[line].tbname) { + //zmazeme tasky + 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) { + + //update profile + logger.debug("worksys - update relay profile done:", profile); + instance.send(SEND_TO.debug, "worksys - update relay profile done"); + + relaysData[line].profile = profile; + + loadRelaysData(line) + logger.debug("loadRelaysData DONE for line", line); + + buildTasks({ processLineProfiles: true, line: line }); + + sendNotification("Cmd-mngr: set profile from worksys", tbname, "switching_profile_was_processed_for_line", { line: line }, profile, SEND_TO.tb, instance); + }); + }); + break; + } + } + } + else if (method == "set_command") { + let value = data.params.payload.value; + + 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; + + 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"); + if (line != 0) reportToSend["contactor"]["off"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + else { + turnLine("on", line, "command received from platform"); + if (line != 0) reportToSend["contactor"]["on"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + } + } + else { + instance.send(SEND_TO.debug, "undefined method " + method); + logger.debug("undefined method", method); + } + + return; + } + else { + instance.send(SEND_TO.debug, "UNKNOW entity_type " + entity_type); + logger.debug("UNKNOW entity_type", entity_type); + } + return; + } + + //terminal + if (!rsPort.isOpen) await rsPort.open(); + + let params = flowdata.data.body; + if (params == undefined) { + //logger.debug("Cmd-mngr: flowdata.data.body is undefined"); + return; + } + + params.priority = PRIORITY_TYPES.terminal; + params.type = "cmd-terminal"; + params.tbname = ""; + params.timestamp = PRIORITY_TYPES.terminal; + params.addMinutesToTimestamp = 0;// do not repeat task!!! + params.debug = true; + + let timestamp = Date.now(); + params.refFlowdataKey = timestamp; + //params.refFlowdata = flowdata; + //refFlowdata = flowdata; + + //console.log("flowdata", flowdata); + + cleanUpRefFlowdataObj(); + + refFlowdataObj[timestamp] = flowdata; + + //fix + //params.address = params.adress; + logger.debug("received from terminal", params); + logger.debug("date/time:", new Date()); + logger.debug("tasks length:", tasks.length); + + //tasks = []; + + //add to tasks + tasks.push(params); + + } + } + }) + + + //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) + } + + + /** + * 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; + + RESTBuilder.make(function(builder) { + + if (!builder) return; + + builder.method('GET'); + builder.url('http://192.168.252.2:8004/gettime?projects_id=1'); + + builder.callback(function(err, response, output) { + + 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); + } + + }); + } + + } 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); + + } else { + //console.log("Read-only", stdout); + + 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]: [ + { + "ts": date, + "values": values + } + ] + } + + tbHandler.sendToTb(dataToTb, instance); + } + + + function calculateDuskDawn(date, line, duskOffset = 0, dawnOffset = 0) { + + if (date === undefined) date = new Date(); + + 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); + } + + //if(profile.dawn_lux_sensor == false) + { + if (profile.hasOwnProperty("dawn_astro_clock_offset")) dawn_astro_clock_offset = parseInt(profile.dawn_astro_clock_offset); + } + + } + + } catch (error) { + if (profilestr != "") { + logger.debug(profilestr); + logger.debug(error); + } + } + + 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; + } + + //Dimming, CCT + else if (register == 1) { + let brightness = 0; + let dimming = byte0; + if (dimming > 128) { + //dimming = -128; + brightness = dimming - 128; + } + + //cct + //Ak Byte3 == 1: CCT = (Byte2*256)+Byte1 + let cct; + if (byte3 == 1) cct = byte2 * 256 + byte1; + else cct = bytesToInt(bytes.slice(0, 3)); + + //cct podla auditu + + values["dimming"] = brightness; + return values; + } + + // + else if (register == 4) { + values["master_node_version"] = bytes[1] + "." + bytes[2]; + //logger.debug("FW Version", register, bytes); + } + + //Napätie + else if (register == 74) { + let voltage = (bytesToInt(bytes) * 0.1).toFixed(1); + values["voltage"] = Number(voltage); + } + + //Prúd + else if (register == 75) { + let current = bytesToInt(bytes); + values["current"] = current; + } + + //výkon + else if (register == 76) { + let power = (bytesToInt(bytes) * 0.1).toFixed(2); + values["power"] = Number(power); + } + + //účinník + else if (register == 77) { + let power_factor = Math.cos(bytesToInt(bytes) * 0.1 * (Math.PI / 180)).toFixed(2); + values["power_factor"] = Number(power_factor); + } + + //frekvencia + else if (register == 78) { + let frequency = (bytesToInt(bytes) * 0.1).toFixed(2); + values["frequency"] = Number(frequency); + } + + //energia + else if (register == 79) { + let energy = bytesToInt(bytes); + values["energy"] = energy / 1000; //energia v kWh -> delit 1000 + } + + //doba života + else if (register == 80) { + let lifetime = (bytesToInt(bytes) / 60).toFixed(2); + values["lifetime"] = Number(lifetime); + } + + //nastavenie profilu + else if (register == 8) { + let time_schedule_settings = bytesToInt(bytes); + values["time_schedule_settings"] = time_schedule_settings; + } + + //naklon - nateraz sa z nodu nevycitava! kvoli problemom s accelerometrom a vracanymi hodnotami, posielame temp a x y z vo funkcii accelerometerData() + else if (register == 84) { + values["temperature"] = byte3 >= 128 ? (byte3 - 128) * (-1) : byte3; + values["inclination_x"] = byte2 >= 128 ? (byte2 - 128) * (-1) : byte2; + values["inclination_y"] = byte1 >= 128 ? (byte1 - 128) * (-1) : byte1; + values["inclination_z"] = byte0 >= 128 ? (byte0 - 128) * (-1) : byte0; + } + + //FW verzia nodu + else if (register == 89) { + //formát: "Byte3: Byte2.Byte1 (Byte0)" + values["fw_version"] = byte3 + ":" + byte2 + "." + byte1 + "(" + byte0 + ")"; + } + + else if (register == 87 || register == 6 || register == 7) { + var d = new Date(); + d.setHours(byte3, byte2, 0, 0); + let timestamp = d.getTime(); + + //aktuálny čas + if (register == 87) values["actual_time"] = timestamp; + //čas súmraku + else if (register == 6) values["dusk_time"] = timestamp; + //čas úsvitu + else if (register == 7) values["dawn_time"] = timestamp; + } + + 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; + + } + + + function getObjectByTbValue(object, tbname) { + return object[Object.keys(object).find(key => object[key].tbname === tbname)]; + } + + + function isObject(item) { + return (typeof item === "object" && !Array.isArray(item) && item !== null); + } + + + // we fake data, that should be received from accelerometer, as they are a bit unreliable. (temperature, x,y,z) + function accelerometerData() { + + if (temperatureInSenica === null) return; + + //clone nodesData and relaysData objects + let nodesData_clone = JSON.parse(JSON.stringify(nodesData)); + let relaysData_clone = JSON.parse(JSON.stringify(relaysData)); + + for (const key in relaysData_clone) { + + const lineData = relaysData_clone[key]; + const lineNumber = lineData.line; + const contactor = lineData.contactor; + + if (lineNumber === 0) continue; + + if (contactor === 1) { + + let date = Date.now(); + + Object.keys(nodesData_clone).forEach((node, index) => { + + setTimeout(function() { + + if (nodesData_clone[node].line === lineNumber) { + + // NOTE: if status of luminaire is NOK or OFFLINE, we do not send data; + let status = nodesData_clone[node].status; + if (status === "OFFLINE" || !status) return; + + let x = null; + if (naklony.hasOwnProperty(node)) x = naklony[node].naklon; + if (x === null) x = 0; + + sendTelemetry({ temperature: Math.round(temperatureInSenica + 10 + Math.floor(Math.random() * 3)), inclination_x: x, inclination_y: 0, inclination_z: 0 }, nodesData_clone[node].tbname, date); + } + + }, (index + 1) * 500); + }) + + } + } + } + + +} // end of instance.export + diff --git a/RVO35/flow/code.js b/RVO35/flow/code.js new file mode 100755 index 0000000..63b31bf --- /dev/null +++ b/RVO35/flow/code.js @@ -0,0 +1,90 @@ +exports.id = 'code'; +exports.title = 'Code'; +exports.group = 'Common'; +exports.color = '#656D78'; +exports.input = true; +exports.output = 1; +exports.author = 'Peter Širka'; +exports.icon = 'code'; +exports.version = '1.2.0'; +exports.options = { outputs: 1, code: 'send(0, value);', keepmessage: true }; + +exports.html = `
+
+
+
@(Number of outputs)
+
@(Minimum is 1)
+
+
+
@(Code)
+
@(Keep message instance)
+
+`; + +exports.readme = `# Code + +This component executes custom JavaScript code as it is and it doesn't contain any secure scope. + +\`\`\`javascript +// value {Object} contains received data +// send(outputIndex, newValue) sends a new value +// error(value) sends an error +// instance {Object} a current component instance +// flowdata {Object} a current flowdata +// repository {Object} a current repository of flowdata +// Example: + +// send() can be execute multiple times +send(0, value); +\`\`\``; + +exports.install = function(instance) { + + var fn; + + instance.on('data', function(response) { + if (fn) { + try { + fn(response.data, instance, response, instance.options, response.repository, require); + } catch (e) { + response.data = e; + instance.throw(response); + } + } + }); + + instance.reconfigure = function() { + try { + if (instance.options.code) { + instance.status(''); + var code = 'var send = function(index, value) { if (options.keepmessage) { flowdata.data = value; instance.send2(index, flowdata); } else instance.send2(index, value);}; var error = function(err) { instance.throw(err); }; ' + instance.options.code; + fn = new Function('value', 'instance', 'flowdata', 'options', 'repository', 'require', code); + } else { + instance.status('Not configured', 'red'); + fn = null; + } + } catch (e) { + fn = null; + instance.error('Code: ' + e.message); + } + }; + + instance.on('options', instance.reconfigure); + instance.reconfigure(); +}; \ No newline at end of file diff --git a/RVO35/flow/comment.js b/RVO35/flow/comment.js new file mode 100755 index 0000000..1e0cd13 --- /dev/null +++ b/RVO35/flow/comment.js @@ -0,0 +1,11 @@ +exports.id = 'comment'; +exports.title = 'Comment'; +exports.group = 'Common'; +exports.color = '#704cff'; +exports.author = 'Martin Smola'; +exports.icon = 'comment'; +exports.traffic = false; +exports.version = '1.0.0'; +exports.readme = '# Comment'; + +exports.install = function() {}; diff --git a/RVO35/flow/count.js b/RVO35/flow/count.js new file mode 100755 index 0000000..fa92ee9 --- /dev/null +++ b/RVO35/flow/count.js @@ -0,0 +1,60 @@ +exports.id = 'count'; +exports.title = 'Count'; +exports.version = '1.0.1'; +exports.author = 'John Graves'; +exports.color = '#656D78'; +exports.icon = 'plus-square'; +exports.input = 2; +exports.output = 1; +exports.options = { increment: 1, initialvalue: 1 }; +exports.readme = `# Counter + +Counter Number of times called.`; + +exports.html = `
+
@(Initial Value)
+
@(Increment)
+

Example Video

+
`; + +exports.readme = `# Count + +This component counts the number of messages received. + +__Response:__ + +Integer value based on the initial value and increment settings. + +__Arguments:__ +- Initial Value: What number should be output on the receipt of the first message. +- Increment: What should the increment be for each following message received.`; + +exports.install = function(instance) { + + var count = 0; + var initialCall = true; + + instance.on('data', function(flowdata) { + var index = flowdata.index; + if (index) { + instance.debug('Reset Count.'); + count = instance.options.initialvalue; + initialCall = true; + } else { + // If this is the first time, set the value to 'initial value' + if(initialCall) { + initialCall = false; + count = instance.options.initialvalue; + } else + count = count+instance.options.increment; + instance.status('Count:' + count); + instance.send2(count); + } + }); + + instance.on('options', function() { + count = instance.options.initialvalue; + initialCall = true; + }); + +}; diff --git a/RVO35/flow/db_connector.js b/RVO35/flow/db_connector.js new file mode 100755 index 0000000..65ee94b --- /dev/null +++ b/RVO35/flow/db_connector.js @@ -0,0 +1,286 @@ +exports.id = 'db_connector'; +exports.title = 'DbConnector'; +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.html = `
+
+
+
DbConnector
+
+
+
`; + +exports.readme = `# read/write data to tables`; + +const instanceSendTo = { + debug: 0, + http_response: 1, +} + +const { promisifyBuilder, makeMapFromDbResult } = require('./helper/db_helper.js'); + +function extractWhereParams(params) +{ + let name = params[0]; + let operator = '='; + let value = params[1]; + + if(params.length == 3) + { + operator = params[1]; + value = params[2]; + } + + return {name: name, operator: operator, value: value}; +} + +exports.install = function(instance) { + + let refFlowdata = null;//holds reference to httprequest flowdata + + instance.on("close", () => { + + }) + + + instance.on("data", async function(flowdata) { + + let params = flowdata.data.body; + console.log("DbConnector", params); + + refFlowdata = flowdata; + + if(refFlowdata != undefined) + { + //make http response + let responseObj = {}; + responseObj["type"] = "SUCESS"; + + try{ + + let table = params.table; + let action = params.action; + + + if(params.data != undefined) + { + let className = params.data.className; + + if(className == "SqlQueryBuilder") + { + let type = params.data.type; + + console.log("SqlQueryBuilder---->", params.data); + + if(type == "SELECT") + { + let table = params.data.queryData.tables[0].table; + + const db = TABLE(table); + var builder = db.find(); + + let result = await promisifyBuilder(builder); + + let response = {}; + response["result"] = result; + response["success"] = true; + + responseObj["data"] = response; + + //console.log(responseObj); + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + } + + return; + } + } + + + console.log("db_connector---->", table, action); + + //actions: read, replace, insert, delete, update... + + if(action == "read") + { + const db = TABLE(params.table); + + //where builder.where('age', '<', 15); + //builder.where('id', 3403); + + var builder = db.find(); + + //https://docs.totaljs.com/latest/en.html#api~DatabaseBuilder~builder.where + if(params.hasOwnProperty("where")) + { + //optionalCan contain "=", "<=", "<", ">=", ">". + //Default value: '=' + + //1.["production_line", 1] + //2. ["or", ["production_line", 1], ["production_line", 2], "end"] + + if (Array.isArray(params.where)) { + + let multipleConditions = false; + + if(params.where[0] == "or") multipleConditions = true; + if (Array.isArray(params.where[0])) multipleConditions = true; + + if(multipleConditions) + { + + for(var i = 0; i < params.where.length; i++) + { + const item = params.where[i]; + + if(item === "or") builder.or(); + + if (Array.isArray(item)) + { + const { name, operator, value } = extractWhereParams(item); + builder.where(name, operator, value); + } + + if(item === "end") builder.end(); + + } + + } + else + { + const { name, operator, value } = extractWhereParams(params.where); + builder.where(name, operator, value); + } + + } + + /* + if(params.where.length >=2 ) + { + let name = params.where[0]; + let operator = '='; + let value = params.where[1]; + + if(params.where.length == 3) + { + operator = params.where[1]; + value = params.where[2]; + } + + builder.where(name, operator, value); + } + */ + } + + if(params.hasOwnProperty("between")) + { + builder.between(params.between[0], params.between[1], params.between[2]); + } + + let response = await promisifyBuilder(builder); + responseObj["data"] = response; + + //console.log(responseObj); + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + + return; + } + + if(action == "delete") + { + + } + + + if(action == "update") + { + //! data receiving from terminal (params) + // { + // hostname: 'localhost', + // table: 'settings', + // action: 'update', + // body: { + // rvo_name: 'terrrr', + // lang: 'en', + // temperature_adress: '28.427B45920702', + // latitude: 48.70826502, + // longitude: 17.28455203, + // mqtt_host: '192.168.252.4', + // mqtt_clientid: 'showroom_test_panel_led', + // mqtt_username: 'xmRd6RJxW53WZe4vMFLU', + // mqtt_port: 1883, + // maintanace_mode: false + // } + // } + const tableToModify = TABLE(params.table); + const newValues = params.body; + + tableToModify.modify(newValues).make(function(builder) { + + builder.callback(function(err, response) { + + if(!err) + { + responseObj["data"] = response; + responseObj["tableUpdated"] = true; + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + } + }); + }); + + } + + if(action == "replace") + { + //truncate table + const db = TABLE(params.table); + var builder = db.remove(); + db.clean(); + + //insert data + let data = params.data; + + for(let i = 0; i < data.length; i++) + { + //console.log(data[i]); + db.insert(data[i]); + } + + console.log("insert done"); + + let responseObj = {}; + responseObj["type"] = "SUCESS"; + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + + + } + + + + } catch (error) { + //console.log(error); + responseObj["type"] = "ERROR"; + responseObj["message"] = error; + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + } + } + }) +} + + diff --git a/RVO35/flow/db_init.js b/RVO35/flow/db_init.js new file mode 100755 index 0000000..b399878 --- /dev/null +++ b/RVO35/flow/db_init.js @@ -0,0 +1,113 @@ +exports.id = 'db_init'; +exports.title = 'DB Initialization'; +exports.group = 'Worksys'; +exports.color = '#888600'; +exports.version = '1.0.2'; +exports.icon = 'sign-out'; +exports.output = 2; + +exports.readme = ` + # DB initialization +`; + +const { promisifyBuilder, makeMapFromDbResult } = require('./helper/db_helper.js'); +const { initNotification } = require('./helper/notification_reporter'); +const errorHandler = require('./helper/ErrorToServiceHandler'); +const total_energy = require('../databases/total_energy'); + +const SEND_TO = { + db_init: 0, + infoSender: 1 +}; + + +exports.install = async function(instance) { + const dbNodes = TABLE("nodes"); + const dbRelays = TABLE("relays"); + const dbSettings = TABLE("settings"); + 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 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.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"]; + Object.keys(dbs.nodesData).forEach(node => dbs.nodesData[node].readout = {}) + + let rvo_number = responseSettings[0]["rvo_name"].match(/\D+(\d{1,2})_/)[1]; + + dbs.settings = { + edge_fw_version: "2025-10-08", //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"], + phases: responseSettings[0]["phases"], + cloud_topic: responseSettings[0]["cloud_topic"], + has_main_switch: responseSettings[0]["has_main_switch"], + daily_report: responseSettings[0]["daily_report"], + send_changed_node_numbers: responseSettings[0]["send_changed_node_numbers"], + rvo_number: rvo_number, + + //dynamic values + masterNodeIsResponding: true, //cmd_manager + maintenance_mode: false, + } + + + dbs.settings.energy_to_switch_lamps = total_energy[rvo_number]; + if (dbs.settings.energy_to_switch_lamps === undefined) console.log('=============== db_init.js: energy_to_switch_lamps is undefined'); + + FLOW.dbLoaded = true; + errorHandler.setProjectId(dbs.settings.project_id); + initNotification(); + + //APP START - send to data services + const toService = { + id: dbs.settings.project_id, + name: dbs.settings.rvo_name, + fw_version: dbs.settings.edge_fw_version, + startdate: new Date().toISOString().slice(0, 19).replace('T', ' '), + js_error: "", + error_message: "" + }; + + instance.send(SEND_TO.infoSender, toService); + console.log("----------------> START - message send to service", toService); + + setTimeout(() => { + console.log("DB_INIT - data loaded"); + instance.send(SEND_TO.db_init, "_") + }, 5000) + +}; + diff --git a/RVO35/flow/debug.js b/RVO35/flow/debug.js new file mode 100755 index 0000000..00cb259 --- /dev/null +++ b/RVO35/flow/debug.js @@ -0,0 +1,100 @@ +exports.id = 'debug'; +exports.title = 'Debug'; +exports.author = 'Peter Širka'; +exports.color = '#967ADC'; +exports.click = true; +exports.input = true; +exports.icon = 'bug'; +exports.version = '2.0.4'; +exports.options = { enabled: true, repository: false, type: 'data' }; +exports.readme = `# Debug + +Prints data to the debug tab.`; + +exports.html = `
+
+
+
@(Output type)
+
@(Path to the property (leave empty to show the whole data object))
+
@(A group name)
+
@(Enabled)
+
+
+
`; + +exports.install = function(instance) { + + instance.on('data', function(response) { + if (instance.options.enabled) { + + var opt = instance.options; + var rep = response.repository; + var val = response.data; + var id = response.id; + + switch (instance.options.type){ + case 'both': + var data = {}; + data.repository = rep; + data.data = val instanceof Error ? { error: val.message, stack: val.stack } : val; + instance.debug(safeparse(opt.property ? U.get(data, opt.property) : data), undefined, opt.group, id); + break; + case 'repository': + instance.debug(safeparse(opt.property ? U.get(rep, opt.property) : rep), undefined, opt.group, id); + break; + case 'data': + default: + if (val instanceof Error) + instance.debug({ error: val.message, stack: val.stack }, undefined, opt.group, id); + else + instance.debug(safeparse(opt.property ? U.get(val, opt.property) : val), undefined, opt.group, id); + break; + } + } + }); + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + instance.save(); + }); + + instance.on('options', function() { + instance.custom.status(); + }); + + instance.custom.status = function() { + instance.status(instance.options.enabled ? 'Enabled' : 'Disabled'); + }; + + instance.custom.status(); + + function safeparse(o) { + + if (o instanceof Buffer) + return o; + + if (o === undefined) + return 'undefined'; + + if (o === null) + return 'null'; + + var cache = []; + var str = JSON.stringify(o, function(key, value) { + if (typeof value === 'object' && value !== null) { + if (cache.indexOf(value) !== -1) { + try { + return JSON.parse(JSON.stringify(value)); + } catch (error) { + return; + } + } + cache.push(value); + } + return value; + }); + cache = null; + return JSON.parse(str); + } +}; diff --git a/RVO35/flow/designer.json b/RVO35/flow/designer.json new file mode 100755 index 0000000..580f5a3 --- /dev/null +++ b/RVO35/flow/designer.json @@ -0,0 +1,3102 @@ +{ + "tabs": [ + { + "name": "MAIN PUSH", + "linker": "main-push", + "id": "1612772287426", + "index": 0 + }, + { + "name": "CMD manager", + "linker": "cmd-manager", + "id": "1615551125555", + "index": 1 + }, + { + "name": "Devices", + "linker": "devices", + "id": "1611921777196", + "index": 2 + } + ], + "components": [ + { + "id": "1611951142547", + "component": "debug", + "tab": "1611921777196", + "name": "ERROR", + "x": 598, + "y": 60, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#DA4453", + "notes": "" + }, + { + "id": "1612776786008", + "component": "wsmqttpublish", + "tab": "1612772287426", + "name": "WS MQTT publish", + "x": 281.75, + "y": 174, + "connections": { + "0": [ + { + "index": "0", + "id": "1615551060773" + } + ], + "1": [ + { + "index": "0", + "id": "1618300858252" + }, + { + "index": "0", + "id": "1618558465485" + } + ], + "2": [ + { + "index": "0", + "id": "1634303685503" + } + ], + "3": [ + { + "index": "0", + "id": "1731068754606" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Connected", + "color": "green" + }, + "options": { + "username": "", + "clientid": "", + "port": "1883", + "host": "" + }, + "color": "#888600", + "notes": "" + }, + { + "id": "1612778461252", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "tb-push", + "x": 72.75, + "y": 328, + "connections": { + "0": [ + { + "index": "0", + "id": "1612783322136" + }, + { + "index": "1", + "id": "1612776786008" + }, + { + "index": "0", + "id": "1731068754606" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1612783322136", + "component": "debug", + "tab": "1612772287426", + "name": "to TB", + "x": 283.75, + "y": 324, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615551060773", + "component": "debug", + "tab": "1612772287426", + "name": "errors from MQTT Broker", + "x": 594, + "y": 57, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#DA4453", + "notes": "" + }, + { + "id": "1615563373927", + "component": "debug", + "tab": "1615551125555", + "name": "Debug", + "x": 755, + "y": 155, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#DA4453", + "notes": "" + }, + { + "id": "1615566865233", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "tb-push", + "x": 755, + "y": 248, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1615798582262", + "component": "debug", + "tab": "1615551125555", + "name": "CMD_debug", + "x": 755, + "y": 346, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615802995322", + "component": "debug", + "tab": "1611921777196", + "name": "Debug", + "x": 596.8833312988281, + "y": 566.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Disabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": false + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615809128443", + "component": "debug", + "tab": "1611921777196", + "name": "tempToTb", + "x": 595.8833312988281, + "y": 658.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615809595184", + "component": "virtualwireout", + "tab": "1611921777196", + "name": "tb-push", + "x": 597.8833312988281, + "y": 377.25, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1616165795916", + "component": "httproute", + "tab": "1615551125555", + "name": "POST /terminal", + "x": 135, + "y": 547, + "connections": { + "0": [ + { + "index": "0", + "id": "1684060205000" + }, + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Listening", + "color": "green" + }, + "options": { + "timeout": 10, + "cachepolicy": 0, + "cacheexpire": "5 minutes", + "size": 5, + "url": "/terminal", + "method": "POST", + "name": "", + "flags": [ + "id:1616165795916", + "post", + 10000 + ], + "emptyresponse": false + }, + "color": "#5D9CEC", + "notes": "### Configuration\n\n- __POST /terminal__\n- flags: \n- maximum request data length: __5 kB__\n- empty response: __false__\n- cache policy: __no cache__\n- cache expire: __5 minutes__", + "cloning": false + }, + { + "id": "1616165824813", + "component": "httpresponse", + "tab": "1615551125555", + "name": "HTTP Response", + "x": 753, + "y": 423, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "json" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1617104731852", + "component": "debug", + "tab": "1615551125555", + "name": "DIDO_Debug", + "x": 669, + "y": 1040, + "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": "turnOff line", + "x": 133, + "y": 1161, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "object", + "data": "{line: 3, command: \"turnOff\", force: true}" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1617115013095", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "tb-push", + "x": 669, + "y": 1150, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1617284749681", + "component": "trigger", + "tab": "1615551125555", + "name": "update profile / node", + "x": 112, + "y": 208, + "connections": { + "0": [ + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "data": "profile_nodes", + "datatype": "string" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1618235171399", + "component": "trigger", + "tab": "1615551125555", + "name": "tun tasks", + "x": 184, + "y": 279, + "connections": { + "0": [ + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "data": "run" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1618300858252", + "component": "debug", + "tab": "1612772287426", + "name": "wsmqtt-exit1", + "x": 597.8833312988281, + "y": 149, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1618393583970", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "to-cmd-manager", + "x": 668.8833312988281, + "y": 1269, + "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": 132.88333129882812, + "y": 367, + "connections": { + "0": [ + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "platform-rpc-call", + "color": "gray" + }, + "options": { + "wirename": "platform-rpc-call" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1618393759854", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "cmd_to_dido", + "x": 119.88333129882812, + "y": 1007, + "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": 752.8833312988281, + "y": 527, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "cmd_to_dido", + "color": "gray" + }, + "options": { + "wirename": "cmd_to_dido" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1618558465485", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "platform-rpc-call", + "x": 597.8833312988281, + "y": 247, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "platform-rpc-call", + "color": "gray" + }, + "options": { + "wirename": "platform-rpc-call" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1618572059773", + "component": "trigger", + "tab": "1615551125555", + "name": "turnOn line", + "x": 132, + "y": 1085, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "data": "{line: 1, command: \"turnOn\", force: true}", + "datatype": "object" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1619515097737", + "component": "cmd_manager", + "tab": "1615551125555", + "name": "CMD Manager", + "x": 452.1091003417969, + "y": 341.05455017089844, + "connections": { + "0": [ + { + "index": "0", + "id": "1615563373927" + } + ], + "1": [ + { + "index": "0", + "id": "1615566865233" + }, + { + "index": "0", + "id": "1615798582262" + } + ], + "2": [ + { + "index": "0", + "id": "1616165824813" + } + ], + "3": [ + { + "index": "0", + "id": "1618393827655" + } + ], + "4": [ + { + "index": "0", + "id": "1635936391935" + } + ], + "5": [ + { + "index": "0", + "id": "1757006030239" + }, + { + "index": "0", + "id": "1757006060377" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1619605019281", + "component": "httproute", + "tab": "1615551125555", + "name": "GET db", + "x": 173, + "y": 653, + "connections": { + "0": [ + { + "index": "0", + "id": "1684060205000" + }, + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Listening", + "color": "green" + }, + "options": { + "timeout": 5, + "cachepolicy": 0, + "cacheexpire": "5 minutes", + "size": 5, + "url": "/db", + "method": "GET", + "name": "", + "flags": [ + "id:1619605019281", + "get", + 5000 + ] + }, + "color": "#5D9CEC", + "notes": "### Configuration\n\n- __GET /db__\n- flags: undefined\n- maximum request data length: __5 kB__\n- empty response: __undefined__\n- cache policy: __no cache__\n- cache expire: __5 minutes__", + "cloning": false + }, + { + "id": "1619784672383", + "component": "trigger", + "tab": "1615551125555", + "name": "turnOnAlarm", + "x": 120, + "y": 1234, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "object", + "data": "{command: \"turnOnAlarm\"}" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1619784812964", + "component": "trigger", + "tab": "1615551125555", + "name": "turnOffAlarm", + "x": 118, + "y": 1307, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "object", + "data": "{command: \"turnOffAlarm\"}" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1621340721628", + "component": "virtualwireout", + "tab": "1611921777196", + "name": "modbus_to_dido", + "x": 599, + "y": 471, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "modbus_to_dido", + "color": "gray" + }, + "options": { + "wirename": "modbus_to_dido" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1622640022885", + "component": "httproute", + "tab": "1615551125555", + "name": "POST /db_connector", + "x": 98, + "y": 1586, + "connections": { + "0": [ + { + "index": "0", + "id": "1622640073521" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Listening", + "color": "green" + }, + "options": { + "timeout": 5, + "cachepolicy": 0, + "cacheexpire": "5 minutes", + "size": 5, + "url": "/db_connector", + "method": "POST", + "flags": [ + "id:1622640022885", + "post", + 5000 + ] + }, + "color": "#5D9CEC", + "notes": "### Configuration\n\n- __POST /db_connector__\n- flags: \n- maximum request data length: __5 kB__\n- empty response: __undefined__\n- cache policy: __no cache__\n- cache expire: __5 minutes__", + "cloning": false + }, + { + "id": "1622640073521", + "component": "db_connector", + "tab": "1615551125555", + "name": "DbConnector", + "x": 372, + "y": 1572, + "connections": { + "1": [ + { + "index": "0", + "id": "1622641420685" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "edge": "undefined" + }, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1622641420685", + "component": "httpresponse", + "tab": "1615551125555", + "name": "HTTP Response", + "x": 596, + "y": 1586, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1634303504177", + "component": "monitormemory", + "tab": "1612772287426", + "name": "RAM", + "x": 69.88333129882812, + "y": 888.5, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465281992" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "858.88 MB / 985.68 MB", + "color": "gray" + }, + "options": { + "enabled": true, + "interval": 30000 + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1634303533779", + "component": "monitordisk", + "tab": "1612772287426", + "name": "disk", + "x": 70.88333129882812, + "y": 982.5, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465821120" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "5.78 GB / 7.26 GB", + "color": "gray" + }, + "options": { + "enabled": true, + "path": "/", + "interval": 30000 + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1634303595494", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "send-to-services", + "x": 51.883331298828125, + "y": 1400.5, + "connections": { + "0": [ + { + "index": "0", + "id": "1634463186563" + }, + { + "index": "1", + "id": "1634488120710" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1634303602169", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "send-to-services", + "x": 426.8833312988281, + "y": 878.5, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1634303685503", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "send-to-services", + "x": 600.8833312988281, + "y": 341.5, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1634303743260", + "component": "httprequest", + "tab": "1612772287426", + "name": "192.168.252.2:8004/sentmessage", + "reference": "", + "x": 506.8833312988281, + "y": 1331.7333374023438, + "connections": { + "0": [ + { + "index": "0", + "id": "1635327431236" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "url": "http://192.168.252.2:8004/sentmessage", + "method": "POST", + "stringify": "json" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1634463186563", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 305.75, + "y": 1442, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634464580289", + "component": "code", + "tab": "1612772287426", + "name": "Code", + "x": 245, + "y": 787, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465243324" + }, + { + "index": "0", + "id": "1634303602169" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "keepmessage": true, + "code": "let response = {};\nresponse.cpu = value.cpu;\nresponse.uptime = value.uptime;\n\nsend(0, response);", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1634465243324", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 428, + "y": 784, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634465281992", + "component": "code", + "tab": "1612772287426", + "name": "Code", + "x": 245, + "y": 884, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465338103" + }, + { + "index": "0", + "id": "1634303602169" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "keepmessage": true, + "code": "value.sender = \"ram\";\n\nlet response = {};\n\nresponse.memory_total = Math.round(value.total / (1024 ** 2));\nresponse.memory_free = Math.round(value.free / (1024 ** 2));\nresponse.memory_used = Math.round(value.used / (1024 ** 2));\n\nsend(0, response);", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1634465338103", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 429, + "y": 976, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634465821120", + "component": "code", + "tab": "1612772287426", + "name": "Code", + "x": 245, + "y": 978, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465892500" + }, + { + "index": "0", + "id": "1634303602169" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "keepmessage": true, + "code": "value.sender = \"hdd\";\n\nlet response = {};\n\nresponse.hdd_total = Math.round(value.total / (1024 ** 2));\nresponse.hdd_free = Math.round(value.free / (1024 ** 2));\nresponse.hdd_used = Math.round(value.used / (1024 ** 2));\n\nsend(0, response);", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1634465892500", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 432, + "y": 1068, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634484067516", + "component": "debug", + "tab": "1612772287426", + "name": "Send info", + "x": 513, + "y": 1441, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634488120710", + "component": "infosender", + "tab": "1612772287426", + "name": "Info sender", + "x": 301, + "y": 1336, + "connections": { + "0": [ + { + "index": "0", + "id": "1634484067516" + }, + { + "index": "0", + "id": "1634303743260" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "edge": "undefined" + }, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1635327431236", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 837.8833312988281, + "y": 1325.5, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1635936391935", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "send-to-services", + "x": 753, + "y": 623, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1637069803394", + "component": "monitorconsumption", + "tab": "1612772287426", + "name": "CPU", + "x": 69, + "y": 791, + "connections": { + "0": [ + { + "index": "0", + "id": "1634464580289" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "49.2% / 69.91 MB", + "color": "gray" + }, + "options": { + "monitorfiles": true, + "monitorconnections": true, + "monitorsize": true, + "monitorconsumption": true, + "enabled": true, + "interval": 30000 + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1683664161036", + "component": "debug", + "tab": "1615551125555", + "name": "CMDtoDIDO", + "x": 392, + "y": 1012, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1683981346282", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "from-dido-controller", + "x": 112, + "y": 459, + "connections": { + "0": [ + { + "index": "0", + "id": "1684055037116" + }, + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "from-dido-controller", + "color": "gray" + }, + "options": { + "wirename": "from-dido-controller" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1684055037116", + "component": "debug", + "tab": "1615551125555", + "name": "from dido to cmd", + "x": 451, + "y": 532, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1684060205000", + "component": "debug", + "tab": "1615551125555", + "name": "HTTP routes", + "x": 450, + "y": 639, + "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": "MDBToDido", + "x": 598, + "y": 147, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1699963668903", + "component": "dido_controller", + "tab": "1615551125555", + "name": "DIDO_Controller", + "x": 397, + "y": 1131, + "connections": { + "0": [ + { + "index": "0", + "id": "1617104731852" + } + ], + "1": [ + { + "index": "0", + "id": "1617104731852" + }, + { + "index": "0", + "id": "1617115013095" + } + ], + "2": [ + { + "index": "0", + "id": "1618393583970" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "edge": "undefined" + }, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1699964678894", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "modbus_to_dido", + "x": 96, + "y": 924, + "connections": { + "0": [ + { + "index": "0", + "id": "1699963668903" + }, + { + "index": "0", + "id": "1699964793925" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "modbus_to_dido", + "color": "gray" + }, + "options": { + "wirename": "modbus_to_dido" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1699964793925", + "component": "debug", + "tab": "1615551125555", + "name": "modbusToDido", + "x": 388, + "y": 920, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1699965957410", + "component": "modbus_reader", + "tab": "1611921777196", + "name": "Modbus reader", + "x": 232, + "y": 175, + "connections": { + "0": [ + { + "index": "0", + "id": "1611951142547" + } + ], + "1": [ + { + "index": "0", + "id": "1621340721628" + }, + { + "index": "0", + "id": "1684179110403" + }, + { + "index": "0", + "id": "1717441414646" + } + ], + "2": [ + { + "index": "0", + "id": "1615809595184" + }, + { + "index": "0", + "id": "1714752862828" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1700411878636", + "component": "thermometer", + "tab": "1611921777196", + "name": "Thermometer", + "x": 234.75, + "y": 444, + "connections": { + "0": [ + { + "index": "0", + "id": "1615802995322" + } + ], + "1": [ + { + "index": "0", + "id": "1615809595184" + }, + { + "index": "0", + "id": "1615809128443" + } + ], + "2": [ + { + "index": "0", + "id": "1621340721628" + }, + { + "index": "0", + "id": "1732889185927" + }, + { + "index": "0", + "id": "1717441414646" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#5CB36D", + "notes": "" + }, + { + "id": "1714752862828", + "component": "debug", + "tab": "1611921777196", + "name": "MDBToTb", + "x": 766, + "y": 324, + "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": 764.0833282470703, + "y": 222, + "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\telse if(value.status === \"NOK-thermometer\")\n\t{\n\t\tsend(0, {\"thermometer\": \"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\telse if(value.values.hasOwnProperty(\"temperature\"))\n\t{\n\t\tsend(0, {\"thermometer\": \"OK\"});\n\t}\n}", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1717442627834", + "component": "debug", + "tab": "1611921777196", + "name": "modbus service", + "x": 966.0833282470703, + "y": 165, + "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": 968.0833282470703, + "y": 268, + "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": 88.75, + "y": 1685, + "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": 296, + "y": 1671, + "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\", \"Flow has been restarted\", \"Node db has changed\"]", + "types": "[\"emergency\", \"critical\", \"error\", \"alert\"]", + "name": "" + }, + "color": "#30E193", + "notes": "" + }, + { + "id": "1718016073501", + "component": "httprequest", + "tab": "1612772287426", + "name": "http://192.168.252.2:8004/slack", + "x": 495, + "y": 1753, + "connections": { + "0": [ + { + "index": "0", + "id": "1718016086212" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "url": "http://192.168.252.2:8004/slack", + "method": "POST", + "stringify": "json" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1718016086212", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 832, + "y": 1664, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "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": 87, + "y": 1591, + "connections": { + "0": [ + { + "index": "0", + "id": "1718016052341" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "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\": \"\" } } } ] }", + "datatype": "object" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1729855334955", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "platform-rpc-call", + "x": 599.9333343505859, + "y": 541.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "platform-rpc-call", + "color": "gray" + }, + "options": { + "wirename": "platform-rpc-call" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1729855371093", + "component": "debug", + "tab": "1612772287426", + "name": "rpc cloud", + "x": 601.9333343505859, + "y": 440.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1731068658334", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 75.75, + "y": 184, + "connections": { + "0": [ + { + "index": "0", + "id": "1612776786008" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731068754606", + "component": "cloudmqttconnect", + "tab": "1612772287426", + "name": "MQTT to senica-prod01", + "x": 284.75, + "y": 452, + "connections": { + "1": [ + { + "index": "0", + "id": "1729855371093" + }, + { + "index": "0", + "id": "1729855334955" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Connected", + "color": "green" + }, + "options": { + "username": "", + "clientid": "", + "port": "2764", + "host": "192.168.252.2", + "topic": "" + }, + "color": "#888600", + "notes": "" + }, + { + "id": "1731069001548", + "component": "db_init", + "tab": "1612772287426", + "name": "DB Initialization", + "x": 1003.75, + "y": 240.25, + "connections": { + "0": [ + { + "index": "0", + "id": "1731069033416" + } + ], + "1": [ + { + "index": "0", + "id": "1747561603739" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#888600", + "notes": "" + }, + { + "id": "1731069033416", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "db-init", + "x": 1244.75, + "y": 233.25, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069059135", + "component": "showdb", + "tab": "1612772287426", + "name": "Show db data", + "x": 1186.75, + "y": 821.25, + "connections": { + "0": [ + { + "index": "0", + "id": "1731069079243" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#888600", + "notes": "" + }, + { + "id": "1731069079243", + "component": "debug", + "tab": "1612772287426", + "name": "dbData", + "x": 1390.75, + "y": 870.25, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1731069116691", + "component": "trigger", + "tab": "1612772287426", + "name": "settings", + "x": 934.75, + "y": 669.75, + "connections": { + "0": [ + { + "index": "0", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069131637", + "component": "trigger", + "tab": "1612772287426", + "name": "relaysData", + "x": 876.75, + "y": 733.75, + "connections": { + "0": [ + { + "index": "1", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069137374", + "component": "trigger", + "tab": "1612772287426", + "name": "nodesData", + "x": 852.75, + "y": 794.75, + "connections": { + "0": [ + { + "index": "2", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069179846", + "component": "trigger", + "tab": "1612772287426", + "name": "pinsData", + "x": 850.75, + "y": 861.75, + "connections": { + "0": [ + { + "index": "3", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069192937", + "component": "trigger", + "tab": "1612772287426", + "name": "sample data", + "x": 857.75, + "y": 928.75, + "connections": { + "0": [ + { + "index": "4", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069264443", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 63.75, + "y": 1279, + "connections": { + "0": [ + { + "index": "0", + "id": "1634488120710" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069334626", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "db-init", + "x": 172.88333129882812, + "y": 129, + "connections": { + "0": [ + { + "index": "0", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069548145", + "component": "virtualwirein", + "tab": "1611921777196", + "name": "db-init", + "x": 46.75, + "y": 192, + "connections": { + "0": [ + { + "index": "0", + "id": "1699965957410" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069567152", + "component": "virtualwirein", + "tab": "1611921777196", + "name": "db-init", + "x": 44.75, + "y": 465, + "connections": { + "0": [ + { + "index": "0", + "id": "1700411878636" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731070156936", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "db-init", + "x": 126.88333129882812, + "y": 1377, + "connections": { + "0": [ + { + "index": "2", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731234189516", + "component": "trigger", + "tab": "1612772287426", + "name": "monitor.txt", + "x": 882.75, + "y": 991.75, + "connections": { + "0": [ + { + "index": "5", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731234189551", + "component": "trigger", + "tab": "1612772287426", + "name": "err.txt", + "x": 904.75, + "y": 1053.75, + "connections": { + "0": [ + { + "index": "6", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1732700042559", + "component": "nodesdb_change_check", + "tab": "1612772287426", + "name": "Nodes DB change check", + "x": 266.8833312988281, + "y": 1980.2333984375, + "connections": { + "0": [ + { + "index": "0", + "id": "1732700071298" + }, + { + "index": "0", + "id": "1732700642917" + } + ], + "1": [ + { + "index": "0", + "id": "1759958914348" + }, + { + "index": "0", + "id": "1759959003114" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#888600", + "notes": "" + }, + { + "id": "1732700057052", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 76.75, + "y": 1988, + "connections": { + "0": [ + { + "index": "0", + "id": "1732700042559" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1732700071298", + "component": "debug", + "tab": "1612772287426", + "name": "nodesChange", + "x": 571.8833312988281, + "y": 2018.2333984375, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1732700642917", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "tb-push", + "x": 567.8833312988281, + "y": 1933, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1732889185927", + "component": "debug", + "tab": "1611921777196", + "name": "tempToDido", + "x": 594.8833312988281, + "y": 753, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1733574412965", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 72.75, + "y": 474, + "connections": { + "0": [ + { + "index": "1", + "id": "1731068754606" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1747561603739", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "send-to-services", + "x": 1243.8833312988281, + "y": 334.5, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1747562867845", + "component": "comment", + "tab": "1612772287426", + "name": "FLOW STARTING POINT", + "x": 1003.5666656494141, + "y": 178, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#704cff", + "notes": "" + }, + { + "id": "1749211698385", + "component": "trigger", + "tab": "1612772287426", + "name": "deviceStatus", + "x": 911.75, + "y": 1116.75, + "connections": { + "0": [ + { + "index": "7", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1757006030239", + "component": "httprequest", + "tab": "1615551125555", + "name": "192.168.252.2:8015/daily_report", + "x": 756.5666656494141, + "y": 715.4499969482422, + "connections": { + "0": [ + { + "index": "0", + "id": "1757006045804" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "stringify": "json", + "method": "POST", + "url": "http://192.168.252.2:8015/daily_report" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1757006045804", + "component": "debug", + "tab": "1615551125555", + "name": "ddd", + "x": 1091.566665649414, + "y": 711.4499969482422, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1757006060377", + "component": "debug", + "tab": "1615551125555", + "name": "reportDebug", + "x": 749.5666656494141, + "y": 799.4499969482422, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1759958914348", + "component": "httprequest", + "tab": "1612772287426", + "name": "http://192.168.252.2:8015/node_numbers", + "x": 571, + "y": 2111, + "connections": { + "0": [ + { + "index": "0", + "id": "1759958927094" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "stringify": "json", + "method": "POST", + "url": "http://192.168.252.2:8015/node_numbers" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1759958927094", + "component": "debug", + "tab": "1612772287426", + "name": "nodesChangeCloud", + "x": 951.8833312988281, + "y": 2109.2333984375, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1759959003114", + "component": "debug", + "tab": "1612772287426", + "name": "nodeChangeCloud1", + "x": 574, + "y": 2218, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1760020290879", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 84.75, + "y": 1787, + "connections": { + "0": [ + { + "index": "1", + "id": "1718016052341" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + } + ], + "version": 615 +} diff --git a/RVO35/flow/dido_controller.js b/RVO35/flow/dido_controller.js new file mode 100755 index 0000000..d16fb19 --- /dev/null +++ b/RVO35/flow/dido_controller.js @@ -0,0 +1,1486 @@ +exports.id = 'dido_controller'; +exports.title = 'DIDO_Controller'; +exports.version = '2.0.0'; +exports.group = 'Worksys'; +exports.color = '#2134B0'; +exports.input = 3; +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 + +state_of_main_switch - reportovat stav hlaveho istica : 0-> off 1-> on +rotary_switch_state - sem by sa mal reportovat stav vstupov manual a auto pola nasledovnej logiky: Manual = 1 a Auto = 0 -> Manu +Manual = 0 a Auto = 0 -> Off, Manual = 0 a Auto = 1 -> Automatic + +door_condition - pin 6, dverový kontakt -> 1 -> vyreportuje Closed, 0 -> vyreportuje Ope +twilight_sensor - hodnotu, ktoru vracia ten analogovy vstup (17) treba poslat sem ako float number. Zrejme tu potom pridame nejaky koeficient prevodu na luxy + +Na kazdu liniu +state_of_breaker - podla indexu istica sa reportuje jeho stav, teda istic na liniu 1: 0-> off, 1-> on +state_of_contactor - podla indexu stkaca sa reportuje jeho stav, teda stykac 1 na liniu 1: 0-> off, 1-> on +*/ + +const { errLogger, logger, monitor } = require('./helper/logger'); +const SerialPort = require('serialport'); +const WebSocket = require('ws'); +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 errorHandler = require('./helper/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 hasMainSwitch; + +let alarmStatus = "OFF"; + +const SEND_TO = { + debug: 0, + tb: 1, + cmd_manager: 2 +} + + +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 = {}; + let rsPortReceivedData = []; + + //to be able to get proper twilight values + let twilight_sensor_interval = 5;//minutes + let twilight_sensor = []; + const twilight_sensor_array = []; + let twilightError = false; + + monitor.info("DIDO_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-we make it global to see it from outside + FLOW.deviceStatus = { //key is device name: temperature,.... + "state_of_main_switch": "Off", //Hlavny istic (alebo druhy dverovy kontakt) + "rotary_switch_state": "Off", //Prevadzkovy + "door_condition": "closed", //Dverový kontakt + "em": "OK", //elektromer rvo + "temperature": "OK", //templomer + "battery": "OK", //Bateria + "power_supply": "OK", //Zdroj + "master_node": "OK", //MN - GLOBALS.settings.masterNodeIsResponding + "no_voltage": "OK", //GLOBALS.settings.no_voltage - vypadok napatia na faze + "state_of_breaker": {}, //"Off",//Istic + "state_of_contactor": {}, //"Off",//Stykac + "twilight_sensor": "OK" //lux sensor + }; + let deviceStatus = FLOW.deviceStatus; + + + function main() { + + GLOBALS = FLOW.GLOBALS; + SETTINGS = FLOW.GLOBALS.settings; + rvoTbName = SETTINGS.rvoTbName; + pinsData = GLOBALS.pinsData; + relaysData = GLOBALS.relaysData; + + tbHandler = new DataToTbHandler(SEND_TO.tb); + tbHandler.setSender(exports.title); + + controller_type = SETTINGS.controller_type; //"lm" or "unipi" + hasMainSwitch = SETTINGS.has_main_switch; + + if (controller_type == "") controller_type = "lm"; + + 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, "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; + } + } + + //report RVO version relaysData[0].tbname; + let values = {}; + values["edge_fw_version"] = SETTINGS.edge_fw_version; + values["maintenance_mode"] = SETTINGS.maintenance_mode; + + sendTelemetry(values, rvoTbName); + + 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); + } + + + function handleRsPort() { + + if (rsPort) { + rsPort.removeAllListeners(); + rsPort = null; + } + + //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('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) { + if (!err) { + monitor.info(exports.title + "--->Digital in_out has been set (runSyncExec was sucessfull)"); + + turnAlarm("off"); + 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('error', err => { + let message = "Dido: rsPort error: " + err.message; + logger.debug(message); + monitor.info(message); + errorHandler.sendMessageToService(message); + }) + + rsPort.on("close", () => { + let message = "Dido: rsPort closed - reconnecting ..."; + logger.debug(message); + monitor.info(message); + setTimeout(handleRsPort, 1000); + }) + + rsPort.open(); + } + + + function handleWebSocket() { + + if (ws) { + ws.removeAllListeners(); + ws = null; + } + + //to keep websocket opened, we send request every 150 seconds + let startRequests = null; + + console.log("handleWebSocket function called"); + ws = new WebSocket('ws:/0.0.0.0:1234/ws'); + + ws.onopen = function open() { + + instance.send(0, exports.title + " running"); + turnAlarm("off"); + + initialSetting(); + + setTimeout(function() { ws.send(JSON.stringify({ cmd: "all" })) }, 5000); + // we request dev info about neuron device from evok to keep websocket connection alive + // for some reason this request returns no data, but connection keeps alive + startRequests = setInterval(() => { + ws.send(JSON.stringify({ "cmd": "filter", "dev": ["neuron"] })); + }, 150000) + }; + + + // 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 = async 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; + + 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 => { + logger.debug('Dido: websocket error', err); + }) + + ws.onclose = function() { + logger.debug('Dido: websocket onclose, reconnecting...') + clearInterval(startRequests); + setTimeout(handleWebSocket, 1000); + } + } + + 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 turnAlarm(onOrOff) { + let value = 0; + if (onOrOff == "on") value = 1; + + if (value == 1 && SETTINGS.maintenance_mode) return; + + alarmStatus = "OFF"; + if (value == 1) alarmStatus = "ON"; + + if (rsPort) { + let arr = [0x55]; + arr.push(13); + arr.push(0); + arr.push(value); + + rsPort.write(Buffer.from(arr), function(err) { + logger.debug(`sirena - ${onOrOff}`); + }); + } + else if (ws) { + let cmd = { "cmd": "set", "dev": "relay", "circuit": "1_01", "value": value }; + ws.send(JSON.stringify(cmd)); + logger.debug(`sirena - ${onOrOff}`); + } + } + + + 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") { + bits.push(0); + } + else bits.push(1); + + if (deviceStatus["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); + } + + + // turn line on or off + function turnLine(onOrOff, line, pin, force, info) { + //onOrOff => "on" or "off" + let value = 0; + if (onOrOff == "on") value = 1; + + if (force == undefined) force = false; + + if (line == 0) { + if (value == 1 && alarmStatus == "ON") turnAlarm("off"); + SETTINGS.maintenance_mode = value ? true : false; + + 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); + return; + } + + if (pin === undefined) pin = getPin(line); + + if (pin === undefined) { + errLogger.error("pin is undefined!", line); + return; + } + + if (!force) { + if (relaysData[line].contactor == value) { + instance.send(SEND_TO.debug, `line is already ${onOrOff} ` + line); + logger.debug(`Dido: turnLine: line is already ${onOrOff} `, line); + return; + } + } + + // if(!rsPort.isOpen && !ws) + if (!rsPort && !ws) { + errLogger.error("Dido - port or websocket is not opened"); + return; + } + + if (rsPort) { + let arr = [0x55]; + arr.push(pin); + arr.push(0); + arr.push(value); + + rsPort.write(Buffer.from(arr), function(err) { + if (err === undefined) { + monitor.info(`Dido: turnLine ${onOrOff} zapisal do rsPort-u`, line, pin, arr, info); + switchLogic(arr); + } + else { + monitor.info(`Dido: turnLine ${onOrOff} WRITE error`, err); + } + }); + + } + else if (ws) { + //pin = "relay1_03" or "input1_01" ... we must make just "1_01" with slice method + monitor.info(`Dido: turnLine ${onOrOff} - (line, pin, force)`, line, pin, force, info); + let cmd = { "cmd": "set", "dev": "relay", "circuit": pin.slice(5), "value": value }; + ws.send(JSON.stringify(cmd)); + } + + //if rvo is 24/7, it has just one switching profile point at 13:00. we do not want to send notification as it repeats every day. + //const d = new Date(); + //if(d.getHours() != 13) sendNotification("Dido_controller: ", SETTINGS.rvoTbName, "switching_profile_point_applied_to_line", { line: line, value: onOrOff }, "", SEND_TO.tb, instance); + } + + + // 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; + + // 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) { + const status = flowdata.data.status; + if (status == "NOK-twilight_sensor") { + deviceStatus["twilight_sensor"] = "NOK"; + } + else if (status == "NOK-em340" || status == "NOK-em111") { + deviceStatus["em"] = "NOK"; + } + else if (status == "NOK-thermometer") { + deviceStatus["temperature"] = "NOK"; + } + } + else if ("values" in flowdata.data) { + 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" + } + else if (values.hasOwnProperty("temperature")) { + deviceStatus["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"; + } + + sendTelemetry(values, rvoTbName); + } + + sendRvoStatus(); + }) + + + + + // we expect array as flowdata.data + instance.on("1", flowdata => { + + //console.log(flowdata.data); + + if (!flowdata.data instanceof Object) return; + + let obj = flowdata.data; + let line = obj.line; + 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"); + }) + + + function calculateStateCode() { + + let bits = []; + + //Hlavny istic - state_of_main_switch => v rvo senica je to druhy door pre silovu cast (EM) + if (deviceStatus["state_of_main_switch"] === "closed" || deviceStatus["state_of_main_switch"] === "Off") { + bits.push(0); + } + else { + bits.push(1); + } + + //Prevadzkovy mod - Manual, Off, Automatic, maintenance_mode = true/false // DAVA 2 BITY + if (!SETTINGS.maintenance_mode) { + if (deviceStatus["rotary_switch_state"] === "Manual") { + bits.push(0); + bits.push(1); + } + + if (deviceStatus["rotary_switch_state"] === "Automatic") { + bits.push(0); + bits.push(0); + } + + if (deviceStatus["rotary_switch_state"] === "Off") { + bits.push(1); + bits.push(0); + } + } + else { + bits.push(1); + bits.push(1); + } + + //Dverovy kontakt + if (deviceStatus["door_condition"] === "closed") { + bits.push(0); + } + else { + bits.push(1); + } + + //EM + if (deviceStatus["em"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //Teplomer + if (deviceStatus["temperature"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //Batéria + if (deviceStatus["battery"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //Zdroj + if (deviceStatus["power_supply"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //MN + if (deviceStatus["master_node"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //výpadok napätia na fáze + if (deviceStatus["no_voltage"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + if (deviceStatus["twilight_sensor"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + // doplnime do 16 bitov (2 byty) + for (let i = bits.length; i < 16; i++) { + bits.push(0); + } + + // console.log("calculateStateCode - deviceStatus", deviceStatus); + // 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; + } + + + async function sendRvoStatus() { + + if (SETTINGS === undefined) return; + SETTINGS.masterNodeIsResponding ? deviceStatus["master_node"] = "OK" : deviceStatus["master_node"] = "NOK"; + + 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 pinsForRvoStatus(controllerType, hasMainSwitch) { + + let pins = []; + + if (controllerType === "lm") { + pins = [1, 4, 6]; + if (hasMainSwitch === 1) { + pins = [4, 6]; + } + } else if (controllerType === "unipi") { + pins = ["input1_01", "input1_04", "input1_05"]; + if (hasMainSwitch === 1) { + pins = ["input1_01", "input1_04"]; + } + } + + return pins; + } + + + function checkRvoStatus() { + + // 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 + //set RVO state + let status = "OK"; + + for (const [key, value] of Object.entries(deviceStatus)) { + if (["em", "twilight_sensor", "temperature", "master_node"].includes(key) && value === "NOK") status = "NOK"; + } + + if (status === "OK") { + + let pinIndexes = pinsForRvoStatus(controller_type, hasMainSwitch); + + for (const pinIndex of pinIndexes) { + if (previousValues[pinIndex] === 0) { + if ((pinIndex === 6 || pinIndex === 'input1_01' || pinIndex === 'input1_05') && SETTINGS.maintenance_mode) continue; + status = "NOK"; + break; + } + } + } + + // battery status. If value is 1 - battery is NOK + if (previousValues[5] === 1) status = "NOK"; + if (SETTINGS.no_voltage.size > 0) status = "NOK"; + + // console.log("rvo status",status) + return status; + } + + + // we pass array to function in case of rsPort ==> switchLogic([55,3,0,1]) ==> [[55,3,0,1]] + // we pass two values in case of websocket ==> switchLogic("relay1_03",1) ==> ["relay1_03",1] + const switchLogic = (...args) => { + + let values = {}; + let pinIndex, newPinValue, twilight; + + //data from rsPort + if (args.length == 1) { + pinIndex = args[0][1] + 1; + if (pinIndex === 17) pinIndex--; + newPinValue = args[0][3]; + twilight = args[0][2]; + } + //data from websocket + else { + pinIndex = args[0]; + newPinValue = args[1]; + } + + 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; + + //default value + let value = "On"; + if (newPinValue === 0) value = "Off"; + + //Hlavny istic + if (type === "state_of_main_switch" && hasMainSwitch) { + if (newPinValue === 0 && newPinValue !== previousValues[pinIndex]) { + sendNotification("switchLogic", rvoTbName, "main_switch_has_been_turned_off", {}, "", SEND_TO.tb, instance, "state_of_main_switch"); + 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"); + deviceStatus["state_of_main_switch"] = "On"; + } + } + + //Prevadzkovy mod + 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"; + + deviceStatus["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, "power_supply_has_disconnected_input", {}, "", SEND_TO.tb, instance, "power_supply"); + + deviceStatus["power_supply"] = "NOK"; + } + else if (newPinValue === 1 && newPinValue !== previousValues[pinIndex]) { + sendNotification("switchLogic", rvoTbName, "power_supply_works_correctly", {}, "", SEND_TO.tb, instance, "power_supply"); + + deviceStatus["power_supply"] = "OK"; + } + } + + //Bateria - 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"); + + deviceStatus["battery"] = "NOK"; + } + else if (newPinValue === 0 && newPinValue !== previousValues[pinIndex]) { + sendNotification("switchLogic", rvoTbName, "battery_level_is_ok", {}, "", SEND_TO.tb, instance, "battery_level"); + + deviceStatus["battery"] = "OK"; + } + } + + //Dverovy kontakt - pin 6 + //! Ak je rvo s dvoma dverovymi kontaktami, ked pride z evoku signal z input1_05, co bol predytm "state_of_main switch" handlujeme ho teraz ako 'door_condition' + else if (type == "door_condition" || type === "state_of_main_switch") { + newPinValue === 0 ? value = "open" : value = "closed"; + + let door = "door_main"; + if (type === "state_of_main_switch") door = "door_em"; + + if (value === "open") { + if (SETTINGS.maintenance_mode) { + sendNotification("switchLogic", rvoTbName, door + "_open", {}, "", SEND_TO.tb, instance, door); + } else { + sendNotification("switchLogic", rvoTbName, door + "_open_without_permission", {}, "", SEND_TO.tb, instance, door); + + // 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 (value === "closed") { + if (alarmStatus == "ON") turnAlarm("off"); + sendNotification("switchLogic", rvoTbName, door + "_close", {}, "", SEND_TO.tb, instance, door); + } + + deviceStatus[type] = value; + } + + //lux sensor + else if (type == "twilight_sensor") { + //! TODO - to show nok status, if lux value is not changing more then 10 times. + //Daylight is far more than 1000. So most of the day, when it is sunshine comes just value 1000. But lux sensor is not NOK. + //This is not the case in LM. If value from LM is the same 10x, there is 99% possibility, that sensor is NOK. + value = newPinValue; + + if (controller_type === 'lm') { + value = parseFloat(newPinValue + (256 * twilight)); + + 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 && !twilightError) { + twilightError = true; + let value = twilight_sensor_array.shift(); + + newPinValue = 0; + } + else if (set.size !== 1 && twilightError) { + //sendNotification("switchLogic", rvoTbName, 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) { + 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); + } + } + + 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); + } + + deviceStatus["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 (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 }); + + //mame iba 3 istice. vyreportujeme a ohandlujeme liniu na tom istom istici ako paralelna linia (napr linia 1, paralelna s nou je linia 4, key je string "4") + // ak je 7 linii, na 1 istici je linia 1,4,7 + + if (line == 1) { + + const lineOnSameBraker = [4, 7]; + + for (var i = 0; i < lineOnSameBraker.length; i++) { + if (!relaysData.hasOwnProperty(lineOnSameBraker[i])) continue; + + 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; + reportLineStatus(lineOnSameBraker[i]); + + values[type] = value; + const tbname = relaysData[lineOnSameBraker[i]].tbname; + sendTelemetry(values, tbname); + + delete values[type]; + } + + } + else { + const lineOnSameBraker = line + 3 + ""; + + if (relaysData.hasOwnProperty(lineOnSameBraker)) { + 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; + reportLineStatus(line + 3); + + values[type] = value; + const tbname = relaysData[lineOnSameBraker].tbname; + sendTelemetry(values, tbname); + + delete values[type]; + } + } + + } + + if (value == "Off") values["status"] = "NOK"; + deviceStatus["state_of_breaker"][line] = value; + + reportLineStatus(line); + } + else return; + + values[type] = value; + + if (type == "rotary_switch_state") { + if (SETTINGS.maintenance_mode) value = "maintenance"; + value = value.toLowerCase(); + values["power_mode"] = value; + } + + if (newPinValue != previousValues[pinIndex]) previousValues[pinIndex] = newPinValue; + if (Object.keys(values).length > 0 && tbname) sendTelemetry(values, tbname); + } + + + function sendTelemetry(values, tbname, date = Date.now()) { + let dataToTb = { + [tbname]: [ + { + "ts": date, + "values": values + } + ] + }; + + tbHandler.sendToTb(dataToTb, instance); + } + + + function isObject(item) { + return (typeof item === "object" && !Array.isArray(item) && item !== null); + } + +} //end of 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 +// *|input1_01|state_of_main_switch|0|........... +// *|input1_02|rotary_switch_state|0|........... +// *|input1_03|rotary_switch_state|0|........... +// *|intut1_04|power_supply|0|........... +// *|input1_05|door_condition|0|........... +// *|input1_06|state_of_breaker|1|........... +// *|input1_07|state_of_breaker|2|........... +// *|input1_08|state_of_breaker|3|........... +// *|relay1_02|state_of_contactor|1|........... +// *|relay1_03|state_of_contactor|2|........... +// *|relay1_04|state_of_contactor|3|........... +// *|287D8776E0013CE9|temperature|0|........... + + +//! pins_data --> from UNIPI +// { +// 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 } +// } + +//! relays_data +// { +// '0': { +// line: 0, +// tbname: 'KjbN4q7JPZmexgdnz2yKQ98YAWwO0Q3BMX6ERLoV', +// contactor: 1, +// profile: '' +// }, +// '1': { +// line: 1, +// tbname: 'RMgnK93rkoAazbqdQ4yBG95Z1YXGx6pmwBeVEP2O', +// contactor: 0, +// profile: '{"intervals":[{"value":0,"end_time":"20:00","start_time":"13:00"},{"value":1,"end_time":"10:00","start_time":"20:00"},{"value":0,"end_time":"10:20","start_time":"10:00"},{"value":1,"end_time":"10:40","start_time":"10:20"},{"value":0,"end_time":"11:00","start_time":"10:40"},{"value":1,"end_time":"11:30","start_time":"11:00"},{"value":0,"end_time":"11:50","start_time":"11:30"},{"value":1,"end_time":"13:00","start_time":"11:50"}],"astro_clock":false,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' +// }, +// '2': { +// line: 2, +// tbname: 'dlE1VQjYrNx9gZRmb38gG08oLBO4qaAk2M6JPnG7', +// contactor: 0, +// profile: '{"intervals":[{"value":0,"end_time":"20:00","start_time":"13:00"},{"value":1,"end_time":"10:00","start_time":"20:00"},{"value":0,"end_time":"10:20","start_time":"10:00"},{"value":1,"end_time":"10:40","start_time":"10:20"},{"value":0,"end_time":"11:00","start_time":"10:40"},{"value":1,"end_time":"11:30","start_time":"11:00"},{"value":0,"end_time":"11:50","start_time":"11:30"},{"value":1,"end_time":"13:00","start_time":"11:50"}],"astro_clock":false,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' +// }, +// '3': { +// line: 3, +// tbname: 'vnmG4kJxaXWNBgMQq0D7Aj5e9oZzOAlr6LdR3w2V', +// contactor: 0, +// profile: '{"intervals":[{"value":0,"end_time":"20:30","start_time":"13:00"},{"value":1,"end_time":"00:10","start_time":"20:30"},{"value":0,"end_time":"13:00","start_time":"05:40"},{"value":1,"end_time":"05:40","start_time":"00:10"}],"astro_clock":true,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' +// } +// } + + + + + +// { +// "jbN4q7JPZmexgdnz2yKbWGDYAWwO0Q3BMX6ERLoV": [ +// { +// "ts": 1700409326353, +// "values": { +// "_event": { +// "type": "notice", +// "status": "new", +// "source": { +// "func": "rsPort.open()", +// "component": "1700343402190", +// "component_name": "DIDO_Controller", +// "edge": "jbN4q7JPZmexgdnz2yKbWGDYAWwO0Q3BMX6ERLoV" +// }, +// "message": "al_shariff_10.0.0.38: FLOW has been started ", +// "message_data": "" +// } +// } +// } +// ] +// } diff --git a/RVO35/flow/helper/DataToTbHandler.js b/RVO35/flow/helper/DataToTbHandler.js new file mode 100755 index 0000000..716ef7b --- /dev/null +++ b/RVO35/flow/helper/DataToTbHandler.js @@ -0,0 +1,187 @@ +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; + this.itIsNodeReadout = false; + this.sender = ""; + + // if attribute change difference is less than limit value, we do not send to tb. + this.attributeChangeLimit = { + temperature: 0.5, + Phase_1_voltage: 2, + Phase_2_voltage: 2, + Phase_3_voltage: 2, + Phase_1_current: 0.1, + Phase_2_current: 0.1, + Phase_3_current: 0.1, + Phase_1_power: 2, + Phase_2_power: 2, + Phase_3_power: 2, + total_power: 2, + total_energy: 1, + Phase_1_pow_factor: 0.1, + Phase_2_pow_factor: 0.1, + Phase_3_pow_factor: 0.1, + power_factor: 0.1, + lifetime: 2, + voltage: 2, + power: 2, + frequency: 3, + energy: 0.1, + current: 2, + inclination_x: 10, + inclination_y: 10, + inclination_z: 10 + }; + + } + + dump() { + console.log("----------------------------"); + console.log("previousValues", this.previousValues); + console.log("----------------------------"); + } + + setSender(sender) { + this.sender = sender; + } + + isEmptyObject(obj) { + for (var _ in obj) { + return false; + } + return true; + } + + + sendToTb(data, instance) { + + //not to modify data object, we do deep copy: + let dataCopy = JSON.parse(JSON.stringify(data)); + + let keys = Object.keys(dataCopy); + + if (keys.length == 0) { + if (this.debug) console.log("sendToTb received empty object", dataCopy); + return; + } + + let tbname = keys[0]; + let ts; + + let arrayOfValues = dataCopy[tbname]; + let arrayOfValuesToSend = []; + + for (let i = 0; i < arrayOfValues.length; i++) { + + ts = arrayOfValues[i].ts; + let values = this.prepareValuesForTb(tbname, ts, arrayOfValues[i].values); + + if (!this.isEmptyObject(values)) { + arrayOfValuesToSend.push({ ts: ts, values: values }); + } + + } + + if (arrayOfValuesToSend.length == 0) { + //if(this.debug) console.log("data not sent - empty array"); + return; + } + + this.messageCounter++; + + let dataToTbModified = { + [tbname]: arrayOfValuesToSend + } + + //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); + instance.send(this.index, dataToTbModified); + } + + + getDiffTimestamp(key) { + //TODO set different value for given key!!! + //if(key == "status") this.timeToHoldTbValue = 2*60*60;//2h + return this.timeToHoldTbValue * 1000; + } + + + prepareValuesForTb(tbname, timestamp, values) { + + let keys = Object.keys(values); + + if (keys.includes("lifetime")) this.itIsNodeReadout = true; + + if (!this.previousValues.hasOwnProperty(tbname)) { + this.previousValues[tbname] = {}; + } + + //if(this.debug) console.log("prepareValuesForTb", tbname, timestamp, values); + + for (let i = 0; i < keys.length; i++) { + + let key = keys[i]; + let value = values[key]; + + if (!this.previousValues[tbname].hasOwnProperty(key)) { + this.previousValues[tbname][key] = { ts: timestamp, value: value }; + continue; + } + + // attributeData ==> {voltage: {ts:333333, value:5}} + let attributeData = this.previousValues[tbname][key]; + let attributeToChange = false; + if (key in this.attributeChangeLimit) attributeToChange = true; + let limit = this.attributeChangeLimit[key]; + let timestampDiffToRemoveKey; + + //this will ensure "node statecode" will be sent just once an hour + if (this.itIsNodeReadout && key === "statecode") { + attributeData.value = value; + this.itIsNodeReadout = false; + timestampDiffToRemoveKey = 1 * 60 * 60 * 1000; // 1 hour + } + + if (key === "twilight_sensor" && value > 100) { + attributeData.value = value; + } + + //if edge, master or node version do not change, send just once a day: + if (["edge_fw_version", "master_node_version", "fw_version"].includes(key)) { + timestampDiffToRemoveKey = 24 * 60 * 60 * 1000; + } + + if (attributeData.value === value || attributeToChange && Math.abs(attributeData.value - value) < limit) { + + let diff = timestamp - attributeData.ts; + if (!timestampDiffToRemoveKey) timestampDiffToRemoveKey = this.getDiffTimestamp(key); + + if (diff > timestampDiffToRemoveKey) { + attributeData.ts = Date.now(); + //if(this.debug) console.log(this.sender + ": update ts for key", key, "diff is", diff, "messageCounter", this.messageCounter); + } + else { + delete values[key]; + //if(this.debug) console.log(this.sender + ": delete key", key, "diff is", diff, "messageCounter", this.messageCounter, timestampDiffToRemoveKey); + } + } + else { + attributeData.value = value; + attributeData.ts = timestamp; + } + + } + + return values; + } +} + +module.exports = DataToTbHandler; + diff --git a/RVO35/flow/helper/ErrorToServiceHandler.js b/RVO35/flow/helper/ErrorToServiceHandler.js new file mode 100755 index 0000000..2b27c32 --- /dev/null +++ b/RVO35/flow/helper/ErrorToServiceHandler.js @@ -0,0 +1,91 @@ +const { MD5 } = require('./md5.js'); +const { networkInterfaces } = require('os'); + +class ErrorToServiceHandler { + constructor() { + this.previousValues = {}; + + this.project_id = undefined; + + const nets = networkInterfaces(); + this.ipAddresses = {}; + + for (const name of Object.keys(nets)) { + for (const net of nets[name]) { + // Skip over non-IPv4 and internal (i.e. 127.0.0.1) addresses + if (net.family === 'IPv4' && !net.internal) { + if (!this.ipAddresses[name]) { + this.ipAddresses[name] = []; + } + this.ipAddresses[name].push(net.address); + } + } + } + } + + setProjectId(project_id) { + this.project_id = project_id; + } + + processMessage(message, seconds) { + if (Array.isArray(message)) message = message.join(', '); + + let key = MD5(message); + let ts = Date.now(); + + //keep in memory - default value is 1h + if (seconds === undefined) seconds = 60 * 60; + + if (!this.previousValues.hasOwnProperty(key)) { + this.previousValues[key] = { ts: ts, duration: seconds }; + } + + let diff = (ts - this.previousValues[key].ts); + if (diff < this.previousValues[key].duration * 1000) return false; + + this.previousValues[key].ts = ts; + + return message; + } + + sendMessageToService(message, seconds, message_type) { + + // if error occures too early FLOW.GLOBALS.settings.project_id is still undefined + if (this.project_id === undefined) { + console.log("ErrorToServiceHandler.js: no project_id"); + return; + } + + let f = this.processMessage(message, seconds); + if (f === false) return; + + if (message_type === undefined) message_type = "error_message"; + + let toService = { + id: this.project_id, + ipAddresses: this.ipAddresses + }; + + //js_error || error_message + toService[message_type] = message; + + console.log("ErrorToServiceHandler------------------------>send to service", toService); + + RESTBuilder.make(function(builder) { + builder.method('POST'); + builder.post(toService); + builder.url('http://192.168.252.2:8004/sentmessage'); + + builder.callback(function(err, response, output) { + console.log("process.on error send", err, response, output, toService); + }); + }); + + } +} + +const errorHandler = new ErrorToServiceHandler(); + + +module.exports = errorHandler; +//module.exports = ErrorToServiceHandler; diff --git a/RVO35/flow/helper/db_helper.js b/RVO35/flow/helper/db_helper.js new file mode 100755 index 0000000..40e796c --- /dev/null +++ b/RVO35/flow/helper/db_helper.js @@ -0,0 +1,44 @@ +function promisifyBuilder(builder) +{ + return new Promise((resolve, reject) => { + + try{ + + builder.callback(function(err, response) { + + if(err != null) reject(err); + resolve(response); + }); + + } catch (error) { + reject(error); + } + }) +} + +function makeMapFromDbResult(response, ...keys) +{ + let s = "-"; + let data = {}; + + for(let i = 0; i < response.length; i++) + { + let record = response[i]; + + let k = []; + for(let j = 0; j < keys.length; j++) + { + k.push( record[keys[j]] ); + } + + let key = k.join(s); + data[ key ] = record; + } + + return data; +} + +module.exports = { + promisifyBuilder, + makeMapFromDbResult + } \ No newline at end of file diff --git a/RVO35/flow/helper/logger.js b/RVO35/flow/helper/logger.js new file mode 100755 index 0000000..2585639 --- /dev/null +++ b/RVO35/flow/helper/logger.js @@ -0,0 +1,30 @@ +//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/RVO35/flow/helper/md5.js b/RVO35/flow/helper/md5.js new file mode 100755 index 0000000..d3b0480 --- /dev/null +++ b/RVO35/flow/helper/md5.js @@ -0,0 +1,5 @@ +function MD5(d){var r = M(V(Y(X(d),8*d.length)));return r.toLowerCase()};function M(d){for(var _,m="0123456789ABCDEF",f="",r=0;r>>4&15)+m.charAt(15&_);return f}function X(d){for(var _=Array(d.length>>2),m=0;m<_.length;m++)_[m]=0;for(m=0;m<8*d.length;m+=8)_[m>>5]|=(255&d.charCodeAt(m/8))<>5]>>>m%32&255);return _}function Y(d,_){d[_>>5]|=128<<_%32,d[14+(_+64>>>9<<4)]=_;for(var m=1732584193,f=-271733879,r=-1732584194,i=271733878,n=0;n>16)+(_>>16)+(m>>16)<<16|65535&m}function bit_rol(d,_){return d<<_|d>>>32-_} + +module.exports = { + MD5 +} \ No newline at end of file diff --git a/RVO35/flow/helper/notification_reporter.js b/RVO35/flow/helper/notification_reporter.js new file mode 100755 index 0000000..839c12c --- /dev/null +++ b/RVO35/flow/helper/notification_reporter.js @@ -0,0 +1,121 @@ +//key is device, value = message {} +let sentValues = {}; +let notificationsData = null; +let rvoName; + +//sendNotification("CMD Manager: process cmd", SETTINGS.rvoTbName, "dimming_profile_was_successfully_received_by_node", { node: node }, "", SEND_TO.tb, instance); + +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 +}; + +function getKey(map, val) { + return Object.keys(map).findItem(key => map[key] === val); +} + +//https://stackoverflow.com/questions/41117799/string-interpolation-on-variable +var template = (tpl, args) => tpl.replace(/\${(\w+)}/g, (_, v) => args[v]); + + +function initNotification() { + notificationsData = FLOW.GLOBALS.notificationsData; + rvoName = FLOW.GLOBALS.settings.rvo_name; +} + + +function sendNotification(func, device, key, params, extra, tb_output, instance, saveKey) { + + let storeToSendValues = true; + if (saveKey == undefined) storeToSendValues = false; + + let weight = ""; + let message = {}; + + let notification = notificationsData[key]; + + if (notification) { + weight = notification.weight.toLowerCase(); + + Object.keys(notification).forEach(item => { + if (["en", "sk", "de", "cz", "it", "es"].includes(item)) { + message[item] = rvoName + ": " + template(notification[item], params); + } + }) + } + else { + //console.error("sendNotification: Notifications: undefined key", key, func, notificationsData); + console.error("sendNotification: Notifications: undefined key", key, func); + return false; + } + + //detect invalid err weight + if (getKey(ERRWEIGHT, weight) == undefined) { + console.error("sendNotification: Notifications: undefined weight", weight, key, func); + return false; + } + + if (sentValues.hasOwnProperty(saveKey)) { + if (JSON.stringify(sentValues[saveKey]) == JSON.stringify(message)) { + return false; + } + } + + if (sentValues[saveKey] == undefined) { + if (storeToSendValues) { + //do not send - flow is was started + sentValues[saveKey] = message; + return false; + } + } + + if (storeToSendValues) sentValues[saveKey] = message; + + let content = { + "type": weight, + "status": "new", + "source": { + "func": func, + "component": instance.id, + "component_name": instance.name, + "edge": device + }, + "message": message, + "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 + + return true; + +} + +module.exports = { + sendNotification, + ERRWEIGHT, + initNotification +} + diff --git a/RVO35/flow/helper/register.js b/RVO35/flow/helper/register.js new file mode 100755 index 0000000..fc1d008 --- /dev/null +++ b/RVO35/flow/helper/register.js @@ -0,0 +1,144 @@ +/* +0 - cislo registra / prikaz +1 - recepient - 0 = master, 1 = slave (slave je automaticky group a broadcast) +2 - r/rw - read/write +3- register name - nazov registra / prikazu (len pre info - zobrazenie v aplikacii) + +4,5,6,7, - jednotlive byte-y - nazov byte-u +4-7 - RES. a prazdny string "" sa nezobrazia!!! +*/ + +//124 zaznamov +const registers = [ + ["0","1","R","Status","","",""], + ["1","1","RW","Dimming","R-Channel ","G-Channel","B-Channel ","W - Channel"], + ["2","1","R","Device types","","",".",""], + ["3","1","RW","Group addresses 1-4","Groups Add. 4","Groups Add. 3","Groups Add. 2","Groups Add. 1"], + ["4","1","RW","Group addresses 5-8","Groups Add. 8","Groups Add. 7","Groups Add. 6","Groups Add. 5"], + ["5","1","RW","Serial number (MAC)","","","",""], + ["6","1","RW","Time of dusk","HH","MM","SS","EXTRA"], + ["7","1","RW","Time of dawn","HH","MM","SS","EXTRA"], + ["8","1","RW","Time Schedule settings","TBD","TBD","Movement sensor","Time Schedule"], + ["9","1","RW","TS1 Time point 1","HH","MM","SS","Ext. Device"], + ["10","1","RW","TS1 Time point 1 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["11","1","RW","TS1 Time point 2","HH","MM","SS","Ext. Device"], + ["12","1","RW","TS1 Time point 2 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["13","1","RW","TS1 Time point 3","HH","MM","SS","Ext. Device"], + ["14","1","RW","TS1 Time point 3 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["15","1","RW","TS1 Time point 4","HH","MM","SS","Ext. Device"], + ["16","1","RW","TS1 Time point 4 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["17","1","RW","TS1 Time point 5","HH","MM","SS","Ext. Device"], + ["18","1","RW","TS1 Time point 5 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["19","1","RW","TS1 Time point 6","HH","MM","SS","Ext. Device"], + ["20","1","RW","TS1 Time point 6 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["21","1","RW","TS1 Time point 7","HH","MM","SS","Ext. Device"], + ["22","1","RW","TS1 Time point 7 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["23","1","RW","TS1 Time point 8","HH","MM","SS","Ext. Device"], + ["24","1","RW","TS1 Time point 8 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["25","1","RW","TS1 Time point 9","HH","MM","SS","Ext. Device"], + ["26","1","RW","TS1 Time point 9 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["27","1","RW","TS1 Time point 10","HH","MM","SS","Ext. Device"], + ["28","1","RW","TS1 Time point 10 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["29","1","RW","TS1 Time point 11","HH","MM","SS","Ext. Device"], + ["30","1","RW","TS1 Time point 11 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["31","1","RW","TS1 Time point 12","HH","MM","SS","Ext. Device"], + ["32","1","RW","TS1 Time point 12 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["33","1","RW","TS1 Time point 13","HH","MM","SS","Ext. Device"], + ["34","1","RW","TS1 Time point 13 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["35","1","RW","TS1 Time point 14","HH","MM","SS","Ext. Device"], + ["36","1","RW","TS1 Time point 14 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["37","1","RW","TS1 Time point 15","HH","MM","SS","Ext. Device"], + ["38","1","RW","TS1 Time point 15 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["39","1","RW","TS1 Time point 16","HH","MM","SS","Ext. Device"], + ["40","1","RW","TS1 Time point 16 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["41","1","RW","TS2 Time point 1","HH","MM","SS","Ext. Device"], + ["42","1","RW","TS2 Time point 1 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["43","1","RW","TS2 Time point 2","HH","MM","SS","Ext. Device"], + ["44","1","RW","TS2 Time point 2 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["45","1","RW","TS2 Time point 3","HH","MM","SS","Ext. Device"], + ["46","1","RW","TS2 Time point 3 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["47","1","RW","TS2 Time point 4","HH","MM","SS","Ext. Device"], + ["48","1","RW","TS2 Time point 4 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["49","1","RW","TS2 Time point 5","HH","MM","SS","Ext. Device"], + ["50","1","RW","TS2 Time point 5 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["51","1","RW","TS2 Time point 6","HH","MM","SS","Ext. Device"], + ["52","1","RW","TS2 Time point 6 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["53","1","RW","TS2 Time point 7","HH","MM","SS","Ext. Device"], + ["54","1","RW","TS2 Time point 7 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["55","1","RW","TS2 Time point 8","HH","MM","SS","Ext. Device"], + ["56","1","RW","TS2 Time point 8 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["57","1","RW","TS2 Time point 9","HH","MM","SS","Ext. Device"], + ["58","1","RW","TS2 Time point 9 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["59","1","RW","TS2 Time point 10","HH","MM","SS","Ext. Device"], + ["60","1","RW","TS2 Time point 10 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["61","1","RW","TS2 Time point 11","HH","MM","SS","Ext. Device"], + ["62","1","RW","TS2 Time point 11 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["63","1","RW","TS2 Time point 12","HH","MM","SS","Ext. Device"], + ["64","1","RW","TS2 Time point 12 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["65","1","RW","TS2 Time point 13","HH","MM","SS","Ext. Device"], + ["66","1","RW","TS2 Time point 13 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["67","1","RW","TS2 Time point 14","HH","MM","SS","Ext. Device"], + ["68","1","RW","TS2 Time point 14 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["69","1","RW","TS2 Time point 15","HH","MM","SS","Ext. Device"], + ["70","1","RW","TS2 Time point 15 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["71","1","RW","TS2 Time point 16","HH","MM","SS","Ext. Device"], + ["72","1","RW","TS2 Time point 16 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["73","1","RW","Power meter status","TBD","","",""], + ["74","1","R","Input Voltage","","","",""], + ["75","1","R","Input Current","","","",""], + ["76","1","R","Input Power","","","",""], + ["77","1","R","Cos phi","","","",""], + ["78","1","R","Frequency","","","",""], + ["79","1","RW","Energy","","","",""], + ["80","1","RW","Lifetime","","","",""], + ["81","1","RW","Power on cycles (input)","","","",""], + ["82","1","RW","Power on cycles (relay)","","","",""], + ["83","1","R","Time since last power on","","","",""], + ["84","1","R","Accelerometer data","","","",""], + ["85","1","RW","GPS latitude","pos/neg","deg","min ","sec"], + ["86","1","RW","GPS longitude","pos/neg","deg","min ","sec"], + ["87","1","RW","Actual time","HH","MM","SS","RES."], + ["88","1","RW","Actual date","Day of week","Day","Month","Year"], + ["89","1","R","Production data 1","","","",""], + ["90","1","R","Production data 2","","","",""], + ["91","1","RW","Network ID","NID3","NID2","NID1","NID0"], + ["95","1","RW","Actual Lux level from cabinet","RES.","RES.","HB","LB"], + ["96","1","RW","Threshold lux level","Dusk HB","Dusk LB","Dawn HB","Dawn LB"], + ["97","1","RW","Adjust period","Dusk HB","Dusk LB","Dawn HB","Dawn LB"], + ["98","1","RW","Offset","RES.","RES.","Dusk","Dawn"], + ["99","1","RW","CCT min/max range","max-H","max-L","min-H","min-L"], + ["100","1","RW","DALI interface","Cmd ID","Add","Cmd","Resp"], + ["101","1","RW","Module FW ver","v1","v2","v3","v4"], + ["102","1","RW","Module MAC-H","unused","unused","M1","M2"], + ["103","1","RW","Module MAC-L","M3","M4","M5","M6"], + ["122","1","R","FW update status/control register","Byte3","Byte2","Byte1","Byte0"], + ["123","1","R","FW update - data index","Byte3","Byte2","Byte1","Byte0"], + ["124","1","R","FW update - data","Byte3","Byte2","Byte1","Byte0"], + ["0","0","R","Status","","","",""], + ["1","0","RW","Control register","RES.","RES.","RES.","init mode enable"], + ["2","0","R","Device types","","","",""], + ["3","0","R","Serial number (MAC)","","","",""], + ["4","0","R","Production data 1","","","",""], + ["5","0","R","Production data 2","","","",""], + ["6","0","RW","Network ID","NID3","NID2","NID1","NID0"], + ["7","0","RW","RS232 settings","param.","param.","Baudrate H","Baudrate L"], + ["8","0","R","Accelerometer data","","","",""], + ["9","0","RW","Module FW ver","v1","v2","v3","v4"], + ["10","0","RW","Module MAC-H","unused","unused","M1","M2"], + ["11","0","RW","Module MAC-L","M3","M4","M5","M6"], + ["32","0","RW","FW update status/control register","Byte3","Byte2","Byte1","Byte0"], + ["33","0","RW","FW update - data index","Byte3","Byte2","Byte1","Byte0"], + ["34","0","RW","FW update - data","Byte3","Byte2","Byte1","Byte0"], + ["125","0","RW","Debug Register","Byte3","Byte2","Byte1","Byte0"], + ["126","0","RW","Network Control Register","Byte3","Byte2","Byte1","Byte0"], + ["127","0","R","Network Status Register","Byte3","Byte2","Byte1","Byte0"], + ["128","0","RW","Node XX Serial Number Register","SER3","SER2","SER1","SER0"], + ["256","0","R","Node XX Network Status Register","","","",""] +]; + +let register = {}; + +module.exports = { + registers, + register +} \ No newline at end of file diff --git a/RVO35/flow/helper/serialport_helper.js b/RVO35/flow/helper/serialport_helper.js new file mode 100755 index 0000000..7f5920d --- /dev/null +++ b/RVO35/flow/helper/serialport_helper.js @@ -0,0 +1,99 @@ +const { exec } = require('child_process'); + +function openPort(port) { + return new Promise((resolve, reject) => { + + var callbackError = function(err) { + port.removeListener('error', callbackError); + port.removeListener('open', callbackError); + + reject(err.message); + }; + + var callbackOpen = function(data) { + port.removeListener('error', callbackError); + port.removeListener('open', callbackOpen); + + resolve("port open: ok"); + }; + + port.on('error', callbackError); + port.on('open', callbackOpen); + + port.open(); + + }) +} + +function runSyncExec(command) { + return new Promise((resolve, reject) => { + + exec(command, (error, stdout, stderr) => { + if (error == null) resolve(stdout); + reject(error); + }); + + }) +} + +async function writeData(port, data, readbytes, timeout) { + return new Promise((resolve, reject) => { + + // 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) { + + port.write(Buffer.from(data), function(err) { + if (err) { + reject(err.message); + } + }); + + 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 +} diff --git a/RVO35/flow/helper/suncalc.js b/RVO35/flow/helper/suncalc.js new file mode 100755 index 0000000..c9ca56d --- /dev/null +++ b/RVO35/flow/helper/suncalc.js @@ -0,0 +1,317 @@ +/* + (c) 2011-2015, Vladimir Agafonkin + SunCalc is a JavaScript library for calculating sun/moon position and light phases. + https://github.com/mourner/suncalc +*/ + +(function () { 'use strict'; + +// shortcuts for easier to read formulas + +var PI = Math.PI, + sin = Math.sin, + cos = Math.cos, + tan = Math.tan, + asin = Math.asin, + atan = Math.atan2, + acos = Math.acos, + rad = PI / 180; + +// sun calculations are based on http://aa.quae.nl/en/reken/zonpositie.html formulas + + +// date/time constants and conversions + +var dayMs = 1000 * 60 * 60 * 24, + J1970 = 2440588, + J2000 = 2451545; + +function toJulian(date) { return date.valueOf() / dayMs - 0.5 + J1970; } +function fromJulian(j) { return new Date((j + 0.5 - J1970) * dayMs); } +function toDays(date) { return toJulian(date) - J2000; } + + +// general calculations for position + +var e = rad * 23.4397; // obliquity of the Earth + +function rightAscension(l, b) { return atan(sin(l) * cos(e) - tan(b) * sin(e), cos(l)); } +function declination(l, b) { return asin(sin(b) * cos(e) + cos(b) * sin(e) * sin(l)); } + +function azimuth(H, phi, dec) { return atan(sin(H), cos(H) * sin(phi) - tan(dec) * cos(phi)); } +function altitude(H, phi, dec) { return asin(sin(phi) * sin(dec) + cos(phi) * cos(dec) * cos(H)); } + +function siderealTime(d, lw) { return rad * (280.16 + 360.9856235 * d) - lw; } + +function astroRefraction(h) { + if (h < 0) // the following formula works for positive altitudes only. + h = 0; // if h = -0.08901179 a div/0 would occur. + + // formula 16.4 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + // 1.02 / tan(h + 10.26 / (h + 5.10)) h in degrees, result in arc minutes -> converted to rad: + return 0.0002967 / Math.tan(h + 0.00312536 / (h + 0.08901179)); +} + +// general sun calculations + +function solarMeanAnomaly(d) { return rad * (357.5291 + 0.98560028 * d); } + +function eclipticLongitude(M) { + + var C = rad * (1.9148 * sin(M) + 0.02 * sin(2 * M) + 0.0003 * sin(3 * M)), // equation of center + P = rad * 102.9372; // perihelion of the Earth + + return M + C + P + PI; +} + +function sunCoords(d) { + + var M = solarMeanAnomaly(d), + L = eclipticLongitude(M); + + return { + dec: declination(L, 0), + ra: rightAscension(L, 0) + }; +} + + +var SunCalc = {}; + + +// calculates sun position for a given date and latitude/longitude + +SunCalc.getPosition = function (date, lat, lng) { + + var lw = rad * -lng, + phi = rad * lat, + d = toDays(date), + + c = sunCoords(d), + H = siderealTime(d, lw) - c.ra; + + return { + azimuth: azimuth(H, phi, c.dec), + altitude: altitude(H, phi, c.dec) + }; +}; + + +// sun times configuration (angle, morning name, evening name) + +var times = SunCalc.times = [ + [-0.833, 'sunrise', 'sunset' ], + [ -0.3, 'sunriseEnd', 'sunsetStart' ], + [ -6, 'dawn', 'dusk' ], + [ -12, 'nauticalDawn', 'nauticalDusk'], + [ -18, 'nightEnd', 'night' ], + [ 6, 'goldenHourEnd', 'goldenHour' ] +]; + +// adds a custom time to the times config + +SunCalc.addTime = function (angle, riseName, setName) { + times.push([angle, riseName, setName]); +}; + + +// calculations for sun times + +var J0 = 0.0009; + +function julianCycle(d, lw) { return Math.round(d - J0 - lw / (2 * PI)); } + +function approxTransit(Ht, lw, n) { return J0 + (Ht + lw) / (2 * PI) + n; } +function solarTransitJ(ds, M, L) { return J2000 + ds + 0.0053 * sin(M) - 0.0069 * sin(2 * L); } + +function hourAngle(h, phi, d) { return acos((sin(h) - sin(phi) * sin(d)) / (cos(phi) * cos(d))); } +function observerAngle(height) { return -2.076 * Math.sqrt(height) / 60; } + +// returns set time for the given sun altitude +function getSetJ(h, lw, phi, dec, n, M, L) { + + var w = hourAngle(h, phi, dec), + a = approxTransit(w, lw, n); + return solarTransitJ(a, M, L); +} + + +// calculates sun times for a given date, latitude/longitude, and, optionally, +// the observer height (in meters) relative to the horizon + +SunCalc.getTimes = function (date, lat, lng, height) { + + height = height || 0; + + var lw = rad * -lng, + phi = rad * lat, + + dh = observerAngle(height), + + d = toDays(date), + n = julianCycle(d, lw), + ds = approxTransit(0, lw, n), + + M = solarMeanAnomaly(ds), + L = eclipticLongitude(M), + dec = declination(L, 0), + + Jnoon = solarTransitJ(ds, M, L), + + i, len, time, h0, Jset, Jrise; + + + var result = { + solarNoon: fromJulian(Jnoon), + nadir: fromJulian(Jnoon - 0.5) + }; + + for (i = 0, len = times.length; i < len; i += 1) { + time = times[i]; + h0 = (time[0] + dh) * rad; + + Jset = getSetJ(h0, lw, phi, dec, n, M, L); + Jrise = Jnoon - (Jset - Jnoon); + + result[time[1]] = fromJulian(Jrise); + result[time[2]] = fromJulian(Jset); + } + + return result; +}; + + +// moon calculations, based on http://aa.quae.nl/en/reken/hemelpositie.html formulas + +function moonCoords(d) { // geocentric ecliptic coordinates of the moon + + var L = rad * (218.316 + 13.176396 * d), // ecliptic longitude + M = rad * (134.963 + 13.064993 * d), // mean anomaly + F = rad * (93.272 + 13.229350 * d), // mean distance + + l = L + rad * 6.289 * sin(M), // longitude + b = rad * 5.128 * sin(F), // latitude + dt = 385001 - 20905 * cos(M); // distance to the moon in km + + return { + ra: rightAscension(l, b), + dec: declination(l, b), + dist: dt + }; +} + +SunCalc.getMoonPosition = function (date, lat, lng) { + + var lw = rad * -lng, + phi = rad * lat, + d = toDays(date), + + c = moonCoords(d), + H = siderealTime(d, lw) - c.ra, + h = altitude(H, phi, c.dec), + // formula 14.1 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + pa = atan(sin(H), tan(phi) * cos(c.dec) - sin(c.dec) * cos(H)); + + h = h + astroRefraction(h); // altitude correction for refraction + + return { + azimuth: azimuth(H, phi, c.dec), + altitude: h, + distance: c.dist, + parallacticAngle: pa + }; +}; + + +// calculations for illumination parameters of the moon, +// based on http://idlastro.gsfc.nasa.gov/ftp/pro/astro/mphase.pro formulas and +// Chapter 48 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + +SunCalc.getMoonIllumination = function (date) { + + var d = toDays(date || new Date()), + s = sunCoords(d), + m = moonCoords(d), + + sdist = 149598000, // distance from Earth to Sun in km + + phi = acos(sin(s.dec) * sin(m.dec) + cos(s.dec) * cos(m.dec) * cos(s.ra - m.ra)), + inc = atan(sdist * sin(phi), m.dist - sdist * cos(phi)), + angle = atan(cos(s.dec) * sin(s.ra - m.ra), sin(s.dec) * cos(m.dec) - + cos(s.dec) * sin(m.dec) * cos(s.ra - m.ra)); + + return { + fraction: (1 + cos(inc)) / 2, + phase: 0.5 + 0.5 * inc * (angle < 0 ? -1 : 1) / Math.PI, + angle: angle + }; +}; + + +function hoursLater(date, h) { + return new Date(date.valueOf() + h * dayMs / 24); +} + +// calculations for moon rise/set times are based on http://www.stargazing.net/kepler/moonrise.html article + +SunCalc.getMoonTimes = function (date, lat, lng, inUTC) { + var t = new Date(date); + if (inUTC) t.setUTCHours(0, 0, 0, 0); + else t.setHours(0, 0, 0, 0); + + var hc = 0.133 * rad, + h0 = SunCalc.getMoonPosition(t, lat, lng).altitude - hc, + h1, h2, rise, set, a, b, xe, ye, d, roots, x1, x2, dx; + + // go in 2-hour chunks, each time seeing if a 3-point quadratic curve crosses zero (which means rise or set) + for (var i = 1; i <= 24; i += 2) { + h1 = SunCalc.getMoonPosition(hoursLater(t, i), lat, lng).altitude - hc; + h2 = SunCalc.getMoonPosition(hoursLater(t, i + 1), lat, lng).altitude - hc; + + a = (h0 + h2) / 2 - h1; + b = (h2 - h0) / 2; + xe = -b / (2 * a); + ye = (a * xe + b) * xe + h1; + d = b * b - 4 * a * h1; + roots = 0; + + if (d >= 0) { + dx = Math.sqrt(d) / (Math.abs(a) * 2); + x1 = xe - dx; + x2 = xe + dx; + if (Math.abs(x1) <= 1) roots++; + if (Math.abs(x2) <= 1) roots++; + if (x1 < -1) x1 = x2; + } + + if (roots === 1) { + if (h0 < 0) rise = i + x1; + else set = i + x1; + + } else if (roots === 2) { + rise = i + (ye < 0 ? x2 : x1); + set = i + (ye < 0 ? x1 : x2); + } + + if (rise && set) break; + + h0 = h2; + } + + var result = {}; + + if (rise) result.rise = hoursLater(t, rise); + if (set) result.set = hoursLater(t, set); + + if (!rise && !set) result[ye > 0 ? 'alwaysUp' : 'alwaysDown'] = true; + + return result; +}; + + +// export as Node module / AMD module / browser variable +if (typeof exports === 'object' && typeof module !== 'undefined') module.exports = SunCalc; +else if (typeof define === 'function' && define.amd) define(SunCalc); +else window.SunCalc = SunCalc; + +}()); diff --git a/RVO35/flow/helper/utils.js b/RVO35/flow/helper/utils.js new file mode 100755 index 0000000..dbffe45 --- /dev/null +++ b/RVO35/flow/helper/utils.js @@ -0,0 +1,161 @@ +const fs = require('fs').promises; + +function bytesToInt(bytes, numberOfBytes) { + let buffer = []; + if (Array.isArray(bytes)) { + buffer = bytes.slice(0); + if (numberOfBytes != undefined) { + buffer = bytes.slice(bytes.length - numberOfBytes); + } + } + else buffer.push(bytes); + + let result = 0; + for (let i = 0; i < buffer.length; i++) { + result = (result << 8) | buffer[i]; + } + + return result >>> 0; //ensure it's an unsigned 32-bit number +} + +function resizeArray(arr, newSize, defaultValue) { + while (newSize > arr.length) + arr.push(defaultValue); + arr.length = newSize; +} + +longToByteArray = function(/*long*/long) { + // we want to represent the input as a 8-bytes array + var byteArray = [0, 0, 0, 0, 0, 0, 0, 0]; + + for (var index = 0; index < byteArray.length; index++) { + var byte = long & 0xff; + byteArray[index] = byte; + long = (long - byte) / 256; + } + + return byteArray; +}; + +function addDays(date, days) { + var result = new Date(date); + result.setDate(result.getDate() + days); + return result; +} + +/* +sleep(2000).then(() => { + // Do something after the sleep! + + +}); +*/ + +function sleep(time) { + return new Promise((resolve) => setTimeout(resolve, time)); +} + +function isEmptyObject(obj) { + for (var name in obj) { + return false; + } + return true; +} + +function emptyJsObject(jsObject) { + Object.keys(jsObject).forEach(key => delete jsObject[key]); +} + +function convertUTCDateToLocalDate(date) { + var newDate = new Date(date); + newDate.setMinutes(date.getMinutes() + date.getTimezoneOffset()); + return newDate; +} + +function addZeroBefore(n) { + return (n < 10 ? '0' : '') + n; +} + + +/** + * Asynchronously writes data to a file. + * + * @param {string} filePath The path to the file. + * @param {string} data The data to write to the file. + * @param {boolean} [append=false] If true, appends the data to the file. If false, it overwrites the file. + */ +async function writeToFile(filePath, data, append = false) { + if (typeof data !== 'string') data = JSON.stringify(data, null, 2); + try { + if (append) { + // Append the data to the end of the file. This is the simplest way to append. + await fs.appendFile(filePath, data, 'utf8'); + console.log(`Successfully appended data to ${filePath} using fs.appendFile.`); + } else { + // Overwrite the file with the new data. + await fs.writeFile(filePath, data, 'utf8'); + console.log(`Successfully wrote (overwrote) data to ${filePath} using fs.writeFile.`); + } + } catch (error) { + console.error(`Error writing to file ${filePath}:`, error); + } +} + + + /** + * Checks if an item is present in an array and adds it if it's not. + * * @param {Array} arr The array to check. + * @param {*} item The item to add. + * @returns {Array} The modified array. + */ +const addToArrayIfUnique = (arr, item) => { + if (!arr.includes(item)) { + arr.push(item); + } + return arr; +}; + + +var convertBase = function() { + + function convertBase(baseFrom, baseTo) { + return function(num) { + return parseInt(num, baseFrom).toString(baseTo); + + }; + } + + // binary to decimal + convertBase.bin2dec = convertBase(2, 10); + + // binary to hexadecimal + convertBase.bin2hex = convertBase(2, 16); + + // decimal to binary + convertBase.dec2bin = convertBase(10, 2); + + // decimal to hexadecimal + convertBase.dec2hex = convertBase(10, 16); + + // hexadecimal to binary + convertBase.hex2bin = convertBase(16, 2); + + // hexadecimal to decimal + convertBase.hex2dec = convertBase(16, 10); + + return convertBase; +}(); + +module.exports = { + bytesToInt, + longToByteArray, + addDays, + addZeroBefore, + resizeArray, + isEmptyObject, + emptyJsObject, + sleep, + convertUTCDateToLocalDate, + writeToFile, + addToArrayIfUnique +} diff --git a/RVO35/flow/httprequest.js b/RVO35/flow/httprequest.js new file mode 100755 index 0000000..469c8cb --- /dev/null +++ b/RVO35/flow/httprequest.js @@ -0,0 +1,137 @@ +exports.id = 'httprequest'; +exports.title = 'HTTP Request'; +exports.group = 'HTTP'; +exports.color = '#5D9CEC'; +exports.input = true; +exports.version = '2.0.1'; +exports.output = 1; +exports.author = 'Peter Širka'; +exports.icon = 'cloud-upload'; + +exports.html = `
+
@(URL address)
+
+
+
@(HTTP method)
+
+
+
@(Serialization)
+
+
+
@(Download the content in chunks)
+
@(Keep persistent cookies)
+
@(Disable DNS cache)
+
@(Keep alive connection)
+
+
+
+
@(Custom headers)
+
@(Cookies)
+
+
+
+ +
+
+
+
@(User)
+
+
+
@(Password)
+
+
+
+
+
`; + +exports.readme = `# Request + +This component creates a request with received data. + +__Response:__ +\`\`\`javascript +{ + data: String, + headers: Object, + status: Number, + host: String +} +\`\`\` + +__Dynamic arguments__: +Are performed via FlowData repository and can be used for URL address or for custom headers/cookies/auth. Use \`repository\` component for creating of dynamic arguments. Dynamic values are replaced in the form \`{key}\`: + +- url address e.g. \`https://.../{key}/\` +- headers values e.g. \`{token}\` +- cookies values e.g. \`{token}\``; + +exports.install = function(instance) { + + var can = false; + var flags = null; + var cookies2 = null; + + instance.on('data', function(response) { + can && instance.custom.send(response); + }); + + instance.custom.send = function(response) { + var options = instance.options; + + var headers = null; + var cookies = null; + + options.headers && Object.keys(options.headers).forEach(function(key) { + !headers && (headers = {}); + headers[key] = response.arg(options.headers[key]); + }); + + if (options.username && options.userpassword) { + !headers && (headers = {}); + headers['Authorization'] = 'Basic ' + U.createBuffer(response.arg(options.username + ':' + options.userpassword)).toString('base64'); + } + + options.cookies && Object.keys(options.cookies).forEach(function(key) { + !cookies && (cookies = {}); + cookies[key] = response.arg(options.cookies[key]); + }); + + if (options.chunks) { + U.download(response.arg(options.url), flags, options.stringify === 'none' ? null : response.data, function(err, response) { + response.on('data', (chunks) => instance.send2(chunks)); + }, cookies || cookies2, headers); + } else { + U.request(response.arg(options.url), flags, options.stringify === 'none' ? null : response.data, 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) + instance.error(err, response); + }, cookies || cookies2, headers); + } + }; + + instance.reconfigure = function() { + var options = instance.options; + can = options.url && options.url && options.method && options.stringify ? true : false; + instance.status(can ? '' : 'Not configured', can ? undefined : 'red'); + + if (!can) + return; + + flags = []; + flags.push(options.method.toLowerCase()); + options.stringify === 'json' && flags.push('json'); + options.stringify === 'raw' && flags.push('raw'); + options.keepalive && flags.push('keepalive'); + !options.nodns && flags.push('dnscache'); + if (options.persistentcookies) { + flags.push('cookies'); + cookies2 = {}; + } else + cookies2 = null; + }; + + instance.on('options', instance.reconfigure); + instance.reconfigure(); +}; \ No newline at end of file diff --git a/RVO35/flow/httpresponse.js b/RVO35/flow/httpresponse.js new file mode 100755 index 0000000..160a3bb --- /dev/null +++ b/RVO35/flow/httpresponse.js @@ -0,0 +1,76 @@ +exports.id = 'httpresponse'; +exports.title = 'HTTP Response'; +exports.group = 'HTTP'; +exports.color = '#5D9CEC'; +exports.icon = 'arrow-right'; +exports.input = true; +exports.output = ['#666D76']; +exports.version = '2.0.0'; +exports.author = 'Martin Smola'; +exports.readme = `# HTTP response + +HTTP response will respond with data recieved using data-type set in Settings form or plain text if not set. Output is the message duration \`Number\` in seconds.`; + +exports.html = `
+
@(Response data-type)
+
JSON is by default.
+
`; + +exports.install = function(instance) { + + var dursum = 0; + var durcount = 0; + + instance.on('data', function(flowdata) { + + var ctrl = flowdata.repository.controller; + var data = flowdata.data; + + if (!ctrl) { + instance.throw('No controller to use for response!'); + return; + } + + durcount++; + dursum += ((new Date() - flowdata.begin) / 1000).floor(2); + setTimeout2(instance.id, instance.custom.duration, 500, 10); + + ctrl.$flowdata = flowdata; + + var datatype = instance.options.datatype || 'json'; + if (datatype === 'emptyresponse') + return ctrl.plain(''); + + if (datatype !== 'json' && typeof(data) !== 'string') { + instance.throw('Incorect type of data, expected string, got ' + typeof(data)); + ctrl.plain(data == null ? '' : data.toString()); + return; + } + + switch(datatype) { + case 'html': + ctrl.content(data, 'text/html'); + break; + case 'plain': + ctrl.plain(data); + break; + case 'xml': + ctrl.content(data, 'text/xml'); + break; + default: + ctrl.json(data); + break; + } + }); + + instance.on('service', function() { + dursum = 0; + durcount = 0; + }); + + instance.custom.duration = function() { + var avg = (dursum / durcount).floor(2); + instance.status(avg + ' sec.'); + instance.send2(0, avg); + }; +}; diff --git a/RVO35/flow/httproute.js b/RVO35/flow/httproute.js new file mode 100755 index 0000000..583a19d --- /dev/null +++ b/RVO35/flow/httproute.js @@ -0,0 +1,326 @@ +exports.id = 'httproute'; +exports.title = 'HTTP Route'; +exports.group = 'HTTP'; +exports.color = '#5D9CEC'; +exports.icon = 'globe'; +exports.input = false; +exports.output = ['#6CAC5A', '#37BC9B']; +exports.version = '1.2.3'; +exports.author = 'Martin Smola'; +exports.cloning = false; +exports.options = { method: 'GET', url: '', size: 5, cacheexpire: '5 minutes', cachepolicy: 0, timeout: 5 }; +exports.dateupdated = '2021-01-21 18:30d'; +exports.readme = `# HTTP route + +__Outputs__: +- first output: raw data (cache is empty or is disabled) +- second output: cached data + +If one of the outputs is disabled then automatic responce with code "503 service unavailable" is sent. + +When a request comes in bellow object is available at \`flowdata.data\`: + +\`\`\`javascript +{ + params: { id: '1' }, // params for dynamic routes, e.g. /test/{id} + query: { msg: 'Hello' }, // parsed query string, e.g. /test/1?msg=Hello + body: { test: 'OK' }, // object if json requests otherwise string + headers: {}, // headers data + session: {}, // session data + user: {}, // user data + files: [], // uploaded files + url: '/users/', // a relative URL address + referrer: '/', // referrer + mobile: false, // determines mobile device + robot: false, // determines search robots/crawlsers + language: 'en' // determines language +} +\`\`\` + +See [documentation for flags](https://docs.totaljs.com/latest/en.html#api~HttpRouteOptionsFlags~unauthorize). These method flags are set automatically e.g. \`get, post, put, patch or delete\` + +--- + +\`id:ROUTE_ID\` flag cannot be used since it's already used by this component internally`; + +exports.html = `
+
+ +
+ +
+
+
@(HTTP method)
+
+
+
@(URL address)
+
+
+
+
+
@(Additional flags)
+
@(Separate flags by comma e.g. json, authorize)
+
+
+
@(Max. request size)
+
@(In kB kilobytes)
+
+
+
@(Timeout)
+
@(In seconds.)
+
+
+
+
+
+
@(Automatically respond with 200 OK?)
+
@(If not checked you need to use HTTP response component to respond to the request.)
+
+
@(Custom headers)
+
@(Cookies)
+
+
+
+
+
+
@(Cache policy)
+
@(User instance must contain id property.)
+
+
+
@(Expiration)
+
@(E.g. 5 minutes)
+
+
+
+`; + +exports.install = function(instance) { + + var route; + + var uninstall = function(id) { + if (F.is4) { + route && route.remove(); + route = null; + } else + UNINSTALL('route', id); + }; + + instance.custom.emptyresponse = function(self) { + self.plain(); + }; + + instance.reconfigure = function() { + + var options = instance.options; + + if (!options.url) { + instance.status('Not configured', 'red'); + return; + } + + if (typeof(options.flags) === 'string') + options.flags = options.flags.split(',').trim(); + + uninstall('id:' + instance.id); + + var flags = options.flags || []; + + flags.push('id:' + instance.id); + + if (!F.is4) + flags.push(options.method.toLowerCase()); + + options.timeout && flags.push(options.timeout * 1000); + + // Make unique values + flags = flags.filter(function(v, i, a) { + if(F.is4 && v.toString().toLowerCase() === options.method.toLowerCase()) + return false; // remove method + return a.indexOf(v) === i; + }); + + options.flags = flags; + var handler = function() { + + if (instance.paused || (instance.isDisabled && (instance.isDisabled('output', 0) || instance.isDisabled('output', 1)))) { + instance.status('503 Service Unavailable'); + this.status = 503; + this.json(); + return; + } + + var key; + var self = this; + + if (instance.options.emptyresponse) { + instance.status('200 OK'); + setTimeout(instance.custom.emptyresponse, 100, self); + + if (instance.hasConnection(0)) { + var data = instance.make({ + query: self.query, + body: self.body, + session: self.session, + user: self.user, + files: self.files, + headers: self.req.headers, + url: self.url, + params: self.params + }); + instance.send2(0, data); + } + + return; + } + + switch (instance.options.cachepolicy) { + case 1: // URL + key = 'rro' + instance.id + self.url.hash(); + break; + case 2: // URL + query + case 3: // URL + query + user + key = self.url; + var keys = Object.keys(self.query); + keys.sort(); + for (var i = 0, length = keys.length; i < length; i++) + key += keys[i] + self.query[keys[i]] + '&'; + if (instance.options.cachepolicy === 3 && self.user) + key += 'iduser' + self.user.id; + key = 'rro' + instance.id + key.hash(); + break; + } + + if (key && F.cache.get2(key)) { + var data = instance.make(F.cache.get2(key)); + data.repository.controller = self; + instance.send2(1, data); + } else { + + var data = instance.make({ + query: self.query, + body: self.body, + session: self.session, + user: self.user, + files: self.files, + headers: self.req.headers, + url: self.url, + params: self.params, + mobile: self.mobile, + robot: self.robot, + referrer: self.referrer, + language: self.language + }); + + data.repository.controller = self; + instance.send2(0, data); + key && FINISHED(self.res, () => F.cache.set(key, self.$flowdata.data, instance.options.cacheexpire)); + } + }; + + if (F.is4) + route = ROUTE(options.method.toUpperCase() + ' ' + options.url, handler, flags, options.size || 5); + else + F.route(options.url, handler, flags, options.size || 5); + + instance.status('Listening', 'green'); + }; + + instance.reconfigure(); + instance.on('options', instance.reconfigure); + instance.on('close', function(){ + uninstall('id:' + instance.id); + }); +}; + +// check url exists +FLOW.trigger('httproutecheckurl', function(next, data) { + var url = data.url; + var method = data.method; + if (url[url.length - 1] !== '/') + url += '/'; + var exists = F.routes.web.findItem(r => r.urlraw === url && r.method === method); + next(exists != null); +}); + +exports.uninstall = function() { + FLOW.trigger('httproutecheckurl', null); +}; diff --git a/RVO35/flow/infosender.js b/RVO35/flow/infosender.js new file mode 100755 index 0000000..587724f --- /dev/null +++ b/RVO35/flow/infosender.js @@ -0,0 +1,81 @@ +exports.id = 'infosender'; +exports.title = 'Info sender'; +exports.version = '1.0.0'; +exports.group = 'Worksys'; +exports.color = '#2134B0'; +exports.input = 2; +exports.output = 1 +exports.icon = 'bolt'; + +const { networkInterfaces } = require('os'); + +exports.html = `
+
+
+
CSV Import
+
+
+
`; + +exports.readme = `# send all data to projects.worksys.io, required to monitor status of controller(unipi)`; + +exports.install = function(instance) { + + let id; + let allValues = {}; + let sendAllValuesInterval; + let configured = false; + + let now = new Date(); + console.log(exports.title, "INSTALLED", now.toLocaleString("sk-SK")); + + const nets = networkInterfaces(); + let ipAddresses = Object.create(null); // Or just '{}', an empty object + + for (const name of Object.keys(nets)) { + for (const net of nets[name]) { + // Skip over non-IPv4 and internal (i.e. 127.0.0.1) addresses + if (net.family === 'IPv4' && !net.internal) { + if (!ipAddresses[name]) { + ipAddresses[name] = []; + } + ipAddresses[name].push(net.address); + } + } + } + + function sendValues() { + if (!configured) return; + + if (Object.keys(allValues).length > 0) { + let dataToSend = { ...allValues }; + dataToSend.id = id; + dataToSend.ipAddresses = ipAddresses; + + instance.send(0, dataToSend); + + allValues = {}; + } + } + + instance.on("close", () => { + clearInterval(sendAllValuesInterval); + }) + + instance.on("0", _ => { + id = FLOW.GLOBALS.settings.project_id; + if (id) configured = true; + else console.log(exports.title, "InfoSender: Unable to send data, no id"); + }) + + instance.on("1", flowdata => { + allValues = { ...allValues, ...flowdata.data }; + //console.log("DATA RECEIVED", flowdata.data); + }) + + sendAllValuesInterval = setInterval(() => { + sendValues(); + }, 60000 * 3); + +} + diff --git a/RVO35/flow/modbus_reader.js b/RVO35/flow/modbus_reader.js new file mode 100755 index 0000000..d6d9dad --- /dev/null +++ b/RVO35/flow/modbus_reader.js @@ -0,0 +1,346 @@ +exports.id = 'modbus_reader'; +exports.title = 'Modbus reader'; +exports.version = '2.0.0'; +exports.group = 'Worksys'; +exports.color = '#2134B0'; +exports.input = 1; +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; +//number of phases inRVO +let phases; +//phases where voltage is 0 (set) +let noVoltage; +let energyToSwitchLamps; + +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.phases = this.buildPhases(); + + this.startSocket(); + } + + buildPhases = () => { + let a = []; + for (let i = 1; i <= phases; i++) { + a.push(`Phase_${i}_voltage`) + } + return a; + } + + startSocket = () => { + + let obj = this; + + if (this.socket) { + this.socket.removeAllListeners(); + this.socket = null; + } + + 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('Modbus_reader: Socket connection error', e); //'ECONNREFUSED' or 'ECONNRESET' ?? + }); + + this.socket.on('close', function() { + console.log('Modbus_reader: Socket connection closed - Waiting 10 seconds before connecting 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 we just start to loop devices from the beginning, or there is just 1 device in config, we wait whole timeoutInterval + if (this.indexInDeviceConfig == 0 || deviceConfig.length === 1) 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 (this.phases.includes(singleValue)) { + let l = singleValue.split("_"); + let phase = parseInt(l[1]); + + // console.log(values[singleValue], tbName); + + if (values[singleValue] == 0) { + noVoltage.add(phase); + sendNotification("modbus_reader: checkNullVoltage", tbName, "no_voltage_on_phase", { phase: phase }, "", SEND_TO.tb, instance, "voltage" + phase); + // console.log('no voltage') + } + else { + noVoltage.delete(phase); + // console.log('voltage detected') + sendNotification("modbus_reader: checkNullVoltage", tbName, "voltage_on_phase_restored", { phase: phase }, "", SEND_TO.tb, instance, "voltage" + phase); + } + } + }) + } + + /** + * function sends notification to slack and to tb, if EM total_power value changes more than numberOfNodes*15. This should show, that RVO lamps has been switched on or off + */ + lampSwitchNotification = (values) => { + + if (!values.hasOwnProperty("total_power")) return; + + const actualTotalPower = values.total_power; + + if (actualTotalPower > energyToSwitchLamps && 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 <= energyToSwitchLamps && 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; + } + + function main() { + + phases = FLOW.GLOBALS.settings.phases; + tbName = FLOW.GLOBALS.settings.rvoTbName; + noVoltage = FLOW.GLOBALS.settings.no_voltage; + energyToSwitchLamps = FLOW.GLOBALS.settings.energy_to_switch_lamps / 2.5; //half value is enought to show if lamps are turned on or off + if (deviceConfig.length) mainSocket = new SocketWithClients(); + else console.log("Modbus_reader: no modbus device in configuration"); + + // this notification is to show, that flow (unipi) has been restarted + sendNotification("modbus_reader", tbName, "flow_restart", {}, "", SEND_TO.slack, instance); + } + + instance.on("0", function(_) { + main(); + }) + +} + diff --git a/RVO35/flow/monitorconsumption.js b/RVO35/flow/monitorconsumption.js new file mode 100755 index 0000000..64cc58e --- /dev/null +++ b/RVO35/flow/monitorconsumption.js @@ -0,0 +1,156 @@ +exports.id = 'monitorconsumption'; +exports.title = 'Consumption'; +exports.version = '1.0.0'; +exports.author = 'Peter Širka'; +exports.group = 'Monitoring'; +exports.color = '#967ADC'; +exports.input = 0; +exports.output = 1; +exports.icon = 'bug'; +exports.options = { interval: 5000, enabled: true, monitorconsumption: true, monitorsize: true, monitorconnections: true, monitorfiles: true }; +exports.click = true; +exports.readme = `# Consumption monitoring + +This component measure CPU and memory consumption, open files and open connections of this application. It uses these Linux commands: \`ps\`, \`lsof\`, \`netstat\` and \`df\`. + +__Data Example__: + +\`\`\`javascript +{ + cpu: 0, // percentage + memory: 4096, // in bytes + size: 34303, // directory size in bytes + files: 34, // count of open files + connections: 343, // count of connections + uptime: '1-12:34:00' +} +\`\`\``; + +exports.html = `
+
+
+
@(Interval in milliseconds)
+
+
+
+
Monitor: Consumption + uptime
+
Monitor: Count of open files
+
Monitor: Count of open connections
+
Monitor: Directory size
+
`; + +exports.install = function(instance) { + + var current = { cpu: 0, memory: 0, files: 0, connections: 0, size: 0, uptime: '', counter: 0 }; + var tproc = null; + var Exec = require('child_process').exec; + var reg_empty = /\s{2,}/g; + var reg_appdisksize = /^[\d.,]+/; + + instance.custom.run = function() { + + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + + var arr = []; + + // Get CPU and Memory consumption + instance.options.monitorconsumption && arr.push(function(next) { + Exec('ps -p {0} -o %cpu,rss,etime'.format(process.pid), function(err, response) { + + if (err) { + instance.throw(err); + } else { + var line = response.split('\n')[1]; + line = line.trim().replace(reg_empty, ' ').split(' '); + var cpu = line[0].parseFloat(); + current.cpu = cpu.floor(1); + current.memory = line[1].parseInt2() * 1024; // kB to bytes + current.uptime = line[2]; + } + + next(); + }); + }); + + // Get count of open files + instance.options.monitorfiles && arr.push(function(next) { + Exec('lsof -a -p {0} | wc -l'.format(process.pid), function(err, response) { + if (err) + instance.throw(err); + else + current.files = response.trim().parseInt2(); + next(); + }); + }); + + // Get count of opened network connections + instance.options.monitorconnections && arr.push(function(next) { + Exec('netstat -an | grep :{0} | wc -l'.format(F.port), function(err, response) { + if (err) { + instance.throw(err); + } else { + current.connections = response.trim().parseInt2() - 1; + if (current.connections < 0) + current.connections = 0; + } + next(); + }); + }); + + // Get directory size + instance.options.monitorsize && current.counter % 5 !== 0 && arr.push(function(next) { + Exec('du -hsb ' + process.cwd(), function(err, response) { + if (err) { + instance.throw(err); + } else { + var match = response.trim().match(reg_appdisksize); + match && (current.size = match.toString().trim().parseInt2()); + } + next(); + }); + }); + + arr.async(function() { + + tproc && clearTimeout(tproc); + + if (instance.options.enabled) { + tproc = setTimeout(instance.custom.run, instance.options.interval); + instance.send2(current); + } + + instance.custom.status(); + current.counter++; + }); + }; + + instance.custom.status = function() { + if (instance.options.enabled) + instance.status('{0}% / {1}'.format(current.cpu, current.memory.filesize())); + else + instance.status('Disabled', 'red'); + }; + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + + if (instance.options.enabled) { + current.counter = 0; + instance.custom.run(); + } + + }); + + instance.on('close', function() { + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + }); + + setTimeout(instance.custom.run, 1000); +}; \ No newline at end of file diff --git a/RVO35/flow/monitordisk.js b/RVO35/flow/monitordisk.js new file mode 100755 index 0000000..f4fdaa0 --- /dev/null +++ b/RVO35/flow/monitordisk.js @@ -0,0 +1,96 @@ +exports.id = 'monitordisk'; +exports.title = 'Disk'; +exports.version = '1.0.0'; +exports.author = 'Peter Širka'; +exports.group = 'Monitoring'; +exports.color = '#F6BB42'; +exports.output = 1; +exports.icon = 'hdd-o'; +exports.click = true; +exports.options = { interval: 8000, path: '/', enabled: true }; +exports.readme = `# Disk monitoring + +This component monitors disk \`bytes\` consumption in Linux systems. It uses \`df\` command. + +__Data Example__: + +\`\`\`javascript +{ + total: 474549649408, + used: 39125245952, + free: 411294994432 +} +\`\`\``; + +exports.html = `
+
+
+
@(Interval in milliseconds)
+
+
+
@(Path)
+
+
+
`; + +exports.install = function(instance) { + + var current = { total: 0, used: 0, free: 0, path: '', type: '', percentUsed: 0 }; + var tproc = null; + + instance.custom.run = function() { + + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + + if (!instance.options.enabled) + return; + + require('child_process').exec('df -hTB1 ' + instance.options.path, function(err, response) { + + tproc = setTimeout(instance.custom.run, instance.options.interval); + + if (err) { + instance.error(err); + return; + } + + response.parseTerminal(function(line) { + if (line[0][0] !== '/') + return; + current.total = line[2].parseInt(); + current.free = line[4].parseInt(); + current.used = line[3].parseInt(); + current.path = instance.options.path || '/'; + current.type = line[1]; + current.percentUsed = line[5]; + instance.custom.status(); + instance.send2(current); + }); + }); + }; + + instance.custom.status = function() { + if (instance.options.enabled) + instance.status(current.free.filesize() + ' / ' + current.total.filesize()); + else + instance.status('Disabled', 'red'); + }; + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + instance.options.enabled && instance.custom.run(); + }); + + instance.on('close', function() { + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + }); + + setTimeout(instance.custom.run, 1000); +}; \ No newline at end of file diff --git a/RVO35/flow/monitormemory.js b/RVO35/flow/monitormemory.js new file mode 100755 index 0000000..2decbc4 --- /dev/null +++ b/RVO35/flow/monitormemory.js @@ -0,0 +1,87 @@ +exports.id = 'monitormemory'; +exports.title = 'Memory'; +exports.version = '1.0.0'; +exports.author = 'Peter Širka'; +exports.group = 'Monitoring'; +exports.color = '#F6BB42'; +exports.output = 1; +exports.click = true; +exports.icon = 'microchip'; +exports.options = { interval: 8000, enabled: true }; +exports.readme = `# Memory monitoring + +This component monitors memory \`bytes\` consumption in Linux systems. It uses \`free\` command. + +__Data Example__: + +\`\`\`javascript +{ + total: 33558769664, + used: 1998868480, + free: 2653708288 +} +\`\`\``; + +exports.html = `
+
+
+
@(Interval in milliseconds)
+
+
+
`; + +exports.install = function(instance) { + + var current = { total: 0, used: 0, free: 0 }; + var tproc = null; + + instance.custom.run = function() { + + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + + if (!instance.options.enabled) + return; + + require('child_process').exec('free -b -t', function(err, response) { + + tproc = setTimeout(instance.custom.run, instance.options.interval); + + if (err) { + instance.error(err); + return; + } + + var memory = response.split('\n')[1].match(/\d+/g); + current.total = memory[0].parseInt(); + current.used = memory[1].parseInt() - memory[3].parseInt(); + current.free = current.total - current.used; + instance.custom.status(); + instance.send2(current); + }); + }; + + instance.custom.status = function() { + if (instance.options.enabled) + instance.status(current.free.filesize() + ' / ' + current.total.filesize()); + else + instance.status('Disabled', 'red'); + }; + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + instance.options.enabled && instance.custom.run(); + }); + + instance.on('close', function() { + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + }); + + setTimeout(instance.custom.run, 1000); +}; \ No newline at end of file diff --git a/RVO35/flow/nodesdb_changecheck.js b/RVO35/flow/nodesdb_changecheck.js new file mode 100755 index 0000000..9adab62 --- /dev/null +++ b/RVO35/flow/nodesdb_changecheck.js @@ -0,0 +1,77 @@ +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 = 2; +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); + } + } + + //kedze do slacku posielame stringy, na cloud musime previest vsetky stringy spat na objekty: + // Funkcia na parsovanie všetkých reťazcov v poli + const parseArray = (arr) => { + return arr.map(jsonString => JSON.parse(jsonString)); + }; + + 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); + if (FLOW.GLOBALS.settings.send_changed_node_numbers) instance.send(1, { aktualneNody: parseArray(zmenene), originalne: parseArray(Array.from(set2)) }); + } + 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/RVO35/flow/show_dbdata.js b/RVO35/flow/show_dbdata.js new file mode 100755 index 0000000..1e23ff7 --- /dev/null +++ b/RVO35/flow/show_dbdata.js @@ -0,0 +1,243 @@ +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 = 8; +exports.output = 1; + +const { exec } = require('child_process'); + +exports.install = 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 }) + }) + instance.on("5", _ => { + exec("sudo tail -n 25 monitor.txt", (err, stdout, stderr) => { + if (err || stderr) instance.send(0, { err, stderr }); + else instance.send(0, stdout); + }) + }) + instance.on("6", _ => { + exec("sudo tail -n 25 err.txt", (err, stdout, stderr) => { + if (err || stderr) instance.send(0, { err, stderr }); + else instance.send(0, stdout); + }) + }) + instance.on("7", _ => { + instance.send(0, FLOW.deviceStatus); + }) +}; + + +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/RVO35/flow/slack_filter.js b/RVO35/flow/slack_filter.js new file mode 100755 index 0000000..6618523 --- /dev/null +++ b/RVO35/flow/slack_filter.js @@ -0,0 +1,188 @@ +exports.id = 'slack_filter'; +exports.title = 'Slack Filter'; +exports.group = 'Citysys'; +exports.color = '#30E193'; +exports.input = 2; +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 = `
+
+
+
@(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('0', 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']['en']; + 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"] = []; + } + + instance.options.name = FLOW.GLOBALS.settings.rvo_name; + if (instance.options.name) { + instance.status('Running'); + running = true; + } else { + instance.status('Please run options again', 'red'); + running = false; + } + } catch (e) { + instance.error('Citysys connector: ' + e.message); + } + }; + + instance.on('options', instance.reconfigure); + + instance.on("1", _ => { + instance.reconfigure(); + }) +}; diff --git a/RVO35/flow/thermometer.js b/RVO35/flow/thermometer.js new file mode 100755 index 0000000..fa015c6 --- /dev/null +++ b/RVO35/flow/thermometer.js @@ -0,0 +1,98 @@ +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 = 5;//minutes +let NUMBER_OF_FAILURES_TO_SEND_ERROR = 13; + +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) => { + + 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); + setTimeout(main, 20000); + }) +}; diff --git a/RVO35/flow/trigger.js b/RVO35/flow/trigger.js new file mode 100755 index 0000000..27545a8 --- /dev/null +++ b/RVO35/flow/trigger.js @@ -0,0 +1,79 @@ +exports.id = 'trigger'; +exports.title = 'Trigger'; +exports.group = 'Inputs'; +exports.color = '#F6BB42'; +exports.click = true; +exports.output = 1; +exports.version = '1.1.0'; +exports.author = 'Martin Smola'; +exports.icon = 'play'; + +exports.html = `
+
@(Data type (String by default))
+
@(Data)
+
Trigger 5s after initialization.
+
@(Useful when there's a need to run certain flow when the app restarts, etc.)
+
`; + +exports.readme = `# Trigger + +- Clicking on the component starts the chain +- Settings allows to set a data-type and a value`; + +exports.install = function(instance) { + + var value; + + instance.on('click', () => instance.send2(value)); + + instance.reconfigure = function() { + var options = instance.options; + value = null; + switch (options.datatype) { + case 'integer': + value = options.data.parseInt2('error'); + value = value === 'error' ? NaN : value; + break; + case 'float': + value = options.data.parseFloat2('error'); + value = value === 'error' ? NaN : value; + break; + case 'date': + options.data = options.data.toString(); + var num = options.data.parseInt('error'); + num === 'error' && (num = options.data.parseDate('error')); + num === 'error' && (num = null); + value = num ? new Date(num).toUTCString() : num; + break; + case 'object': + try { + value = (new Function('return ' + options.data))(); + } catch (e) { + instance.error(e); + } + break; + case 'boolean': + value = options.data.parseBoolean(); + break; + case 'buffer': + try { + value = U.createBuffer(options.data); + } catch (e) { + instance.error(e); + } + break; + case 'string': + default: + value = '' + (options.data || ''); + break; + } + }; + + instance.on('options', instance.reconfigure); + instance.reconfigure(); + + if (instance.options.restart) + setTimeout(function(){ + instance.send2(value); + }, 5000); +}; diff --git a/RVO35/flow/variables.txt b/RVO35/flow/variables.txt new file mode 100755 index 0000000..e69de29 diff --git a/RVO35/flow/virtualwirein.js b/RVO35/flow/virtualwirein.js new file mode 100755 index 0000000..38a4e42 --- /dev/null +++ b/RVO35/flow/virtualwirein.js @@ -0,0 +1,43 @@ +exports.id = 'virtualwirein'; +exports.title = 'Virtual wire in'; +exports.version = '1.0.0'; +exports.author = 'Martin Smola'; +exports.color = '#303E4D'; +exports.icon = 'sign-in'; +exports.input = false; +exports.output = 1; +exports.options = {}; +exports.readme = `# Virtual wire in + +When the wires between the components are mess it's time to use Virtual wire.`; + +exports.html = `
+
@(Wire name)
+
+`; + +exports.install = function(instance) { + + instance.custom.reconfigure = function(options){ + if (instance.options.wirename) { + instance.status(instance.options.wirename); + } else + instance.status('Not configured', 'red'); + }; + + ON('virtualwire', function(wirename, flowdata){ + if (instance.options.wirename && instance.options.wirename === wirename) + instance.send(flowdata); + }); + + instance.on('options', instance.custom.reconfigure); + instance.custom.reconfigure(); +}; diff --git a/RVO35/flow/virtualwireout.js b/RVO35/flow/virtualwireout.js new file mode 100755 index 0000000..94a1e4f --- /dev/null +++ b/RVO35/flow/virtualwireout.js @@ -0,0 +1,41 @@ +exports.id = 'virtualwireout'; +exports.title = 'Virtual wire out'; +exports.version = '1.0.0'; +exports.author = 'Martin Smola'; +exports.color = '#303E4D'; +exports.icon = 'sign-out'; +exports.input = true; +exports.options = {}; +exports.readme = `# Virtual wire out + +When the wires between the components are mess it's time to use Virtual wire.`; + +exports.html = `
+
@(Wire name)
+
+`; + +exports.install = function(instance) { + + instance.custom.reconfigure = function(){ + if (instance.options.wirename) { + instance.status(instance.options.wirename); + } else + instance.status('Not configured', 'red'); + }; + + instance.on('data', function(flowdata) { + EMIT('virtualwire', instance.options.wirename, flowdata); + }); + + instance.on('options', instance.custom.reconfigure); + instance.custom.reconfigure(); +}; diff --git a/RVO35/flow/wsmqttpublish.js b/RVO35/flow/wsmqttpublish.js new file mode 100755 index 0000000..0eba804 --- /dev/null +++ b/RVO35/flow/wsmqttpublish.js @@ -0,0 +1,448 @@ +exports.id = 'wsmqttpublish'; +exports.title = 'WS MQTT publish'; +exports.group = 'MQTT'; +exports.color = '#888600'; +exports.version = '1.0.2'; +exports.icon = 'sign-out'; +exports.input = 2; +exports.output = 3; +exports.options = { host: 'tb-stage.worksys.io', port: 1883, clientid: "", username: "" }; + +exports.html = `
+
+
+
Hostname or IP address (if not empty - setting will override db setting)
+
+
+
Port
+
+
+
+
+
@(Client id)
+
+
+
@(Username)
+
+
+
`; + + +exports.readme = ` +# WS MQTT Publish + +Version 1.0.3. + +Added: +- database collections, +- 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 = { + debug: 0, + rpcCall: 1, + services: 2 +} + +//CONFIG +let createTelemetryBackup = true; +let saveTelemetryOnError = true;//backup_on_failure overrides this value +//------------------------ + +let rollers; +if (createTelemetryBackup) rollers = require('streamroller'); + +const noSqlFileSizeLimit = 4194304;//use 5MB - 4194304 +let insertNoSqlCounter = 0; +let insertBackupNoSqlCounter = 0; +let processingData = false; + +let backup_on_failure = false;//== saveTelemetryOnError - create backup client 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; + +process.on('uncaughtException', function(err) { + + errLogger.error('uncaughtException:', err.message) + errLogger.error(err.stack); + + //TODO + //send to service + + //process.exit(1); +}) + +const nosql = NOSQL('tbdata'); +const nosqlBackup = NOSQL('/backup/tbdata'); + + +exports.install = function(instance) { + + var client; + var opts; + var clientReady = false; + + // wsmqtt status for notification purposes on projects.worksys.io database + let wsmqttName = null; + let sendWsStatusVar = null; + let wsmqtt_status = 'disconnected'; + + 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'; + } + + function sendWsStatus() { + instance.send(SEND_TO.services, { [wsmqttName]: wsmqtt_status }); + } + + + function main() { + if (!FLOW.dbLoaded) return; + + loadSettings(); + clearInterval(sendWsStatus); + sendWsStatusVar = setInterval(sendWsStatus, 180000); + } + + //set opts according to db settings + function loadSettings() { + + if (instance.options.host !== "") { + //override settings from database + var o = instance.options; + opts = { + host: o.host, + port: o.port, + clientId: o.clientid, + username: o.username, + rejectUnauthorized: false, + resubscribe: false + }; + + wsmqttName = getWsmqttName(o.host); + + console.log("wsmqttpublich -> loadSettings from instance.options", instance.options); + } + else { + + const SETTINGS = FLOW.GLOBALS.settings; + backup_on_failure = SETTINGS.backup_on_failure; + saveTelemetryOnError = backup_on_failure; + + restore_from_backup = SETTINGS.restore_from_backup; + restore_backup_wait = SETTINGS.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; + + opts = { + host: mqtt_host, + port: mqtt_port, + keepalive: 10, + clientId: mqtt_clientid, + username: mqtt_username, + rejectUnauthorized: false, + resubscribe: false + }; + + wsmqttName = getWsmqttName(mqtt_host); + } + + connectToTbServer(); + } + + function connectToTbServer() { + 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"); + //monitor.info("MQTT client connected"); + + sendClientError = true; + clientReady = true; + wsmqtt_status = 'connected'; + }); + + client.on('reconnect', function() { + instance.status("Reconnecting", "yellow"); + clientReady = false; + }); + + client.on('message', function(topic, message) { + // message is type of buffer + message = message.toString(); + if (message[0] === '{') { + TRY(function() { + + message = JSON.parse(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 } }); + } + + }, () => instance.debug('MQTT: Error parsing data', message)); + } + + instance.send(SEND_TO.rpcCall, { "topic": topic, "content": message }); + }); + + client.on('close', function() { + clientReady = false; + wsmqtt_status = 'disconnected'; + + instance.status("Disconnected", "red"); + instance.send(SEND_TO.debug, { "message": "Client CLOSE signal received !" }); + }); + + client.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; + wsmqtt_status = 'disconnected'; + }); + + } + + + instance.on("0", _ => { + main(); + }) + + + instance.on('1', function(data) { + + if (clientReady) { + //do we have some data in backup file? if any, process data from database + if (saveTelemetryOnError) { + //read telemetry data and send back to server + if (!processingData) processDataFromDatabase(); + } + + let stringifiedJson = JSON.stringify(data.data); + client.publish("v1/gateway/telemetry", stringifiedJson, { qos: 1 }); + + //backup telemetry + if (createTelemetryBackup) { + data.data.id = UID(); + nosqlBackup.insert(data.data); + + insertBackupNoSqlCounter++; + if (insertBackupNoSqlCounter > 150) { + let options = { compress: true }; + let path = __dirname + "/../databases/backup/tbdata.nosql"; + var stream = new rollers.RollingFileStream(path, noSqlFileSizeLimit, 150, options); + stream.write(""); + stream.end(); + + insertBackupNoSqlCounter = 0; + } + } + + } + 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 (saveTelemetryOnError) { + //create new file from tbdata.nosql, if file size exceeds given limit, and clear tbdata.nosql + makeBackupFromDbFile(); + + //write to tb + data.data.id = UID(); + nosql.insert(data.data); + } + } + }); + + + instance.close = function(done) { + if (clientReady) { + client.end(); + clearInterval(sendWsStatusVar); + } + }; + + + function getDbBackupFileCounter(type) { + var files = fs.readdirSync(__dirname + "/../databases"); + + let counter = 0; + for (var i = 0; i < files.length; i++) { + + if (files[i] == "tbdata.nosql") continue; + + if (files[i].endsWith(".nosql")) { + + let pos = files[i].indexOf("."); + if (pos > -1) { + + let fileCounter = counter; + let firstDigit = files[i].slice(0, pos); + + fileCounter = parseInt(firstDigit); + if (isNaN(fileCounter)) fileCounter = 0; + //console.log("getDbBackupFileCounter digit:", files[i], firstDigit, fileCounter, isNaN(fileCounter), type); + + if (type == "max") { + if (fileCounter > counter) { + counter = fileCounter; + } + } + else if (type == "min") { + if (counter == 0) counter = fileCounter; + + if (fileCounter < counter) { + counter = fileCounter; + } + } + } + } + + } + + if (type == "max") counter++; + + return counter; + } + + const makeBackupFromDbFile = async () => { + + if (!saveTelemetryOnError) return; + + //to avoid large file: tbdata.nosql + + //init value is 0! + if (insertNoSqlCounter > 0) { + --insertNoSqlCounter; + return; + } + + insertNoSqlCounter = 100; + + let source = __dirname + "/../databases/tbdata.nosql"; + + var stats = fs.statSync(source); + var fileSizeInBytes = stats.size; + + if (fileSizeInBytes > noSqlFileSizeLimit) { + + let counter = 1; + counter = getDbBackupFileCounter("max"); + + let destination = __dirname + "/../databases/" + counter + "." + "tbdata.nosql"; + + //make backup file + fs.copyFileSync(source, destination); + //fs.renameSync(p, p + "." + counter); + + //clear tbdata.nosql + fs.writeFileSync(source, ""); + fs.truncateSync(source, 0); + + } + } + + const processDataFromDatabase = async () => { + + if (restore_from_backup <= 0) return; + + //calculate diff + const now = new Date(); + let currentTime = now.getTime(); + let diff = currentTime - lastRestoreTime; + + if ((diff / 1000) < restore_backup_wait) { + //console.log("*********restore_backup_wait", diff, restore_backup_wait); + return; + } + + processingData = true; + + //get filename to process + let counter = getDbBackupFileCounter("min"); + + //we have some backup files + let dataBase = 'tbdata'; + + var nosql; + if (counter == 0) dataBase = 'tbdata'; + else dataBase = counter + "." + 'tbdata'; + + nosql = NOSQL(dataBase); + + //select all data - use limit restore_from_backup + let records = await promisifyBuilder(nosql.find().take(restore_from_backup)); + + for (let i = 0; i < records.length; i++) { + if (clientReady) { + + let item = records[i]; + let id = item.id; + + if (id !== undefined) { + //console.log("------------processDataFromDatabase - remove", id, dataBase, i); + + try { + + let message = JSON.parse(JSON.stringify(item)); + delete message.id; + + client.publish("v1/gateway/telemetry", JSON.stringify(message), { qos: 1 }); + + //remove from database + await promisifyBuilder(nosql.remove().where("id", id)); + + } catch (error) { + //process error + console.log("processDataFromDatabase", error); + } + + } + + } + else { + processingData = false; + return; + } + } + + if (records.length > 0) { + //clean backup file + if (counter > 0) nosql.clean(); + } + + //no data in db, remove + if (records.length == 0) { + if (counter > 0) nosql.drop(); + } + + const d = new Date(); + lastRestoreTime = d.getTime(); + + processingData = false; + + } + + instance.on('options', main); + //instance.reconfigure(); +}; diff --git a/RVO35/flow_old/audit_test_panel.csv b/RVO35/flow_old/audit_test_panel.csv new file mode 100755 index 0000000..907a6a9 --- /dev/null +++ b/RVO35/flow_old/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/RVO35/flow_old/cloudmqttconnect.js b/RVO35/flow_old/cloudmqttconnect.js new file mode 100755 index 0000000..d619784 --- /dev/null +++ b/RVO35/flow_old/cloudmqttconnect.js @@ -0,0 +1,374 @@ +exports.id = 'cloudmqttconnect'; +exports.title = 'Cloud connect mqtt'; +exports.group = 'MQTT'; +exports.color = '#888600'; +exports.version = '1.0.2'; +exports.icon = 'sign-out'; +exports.input = 2; +exports.output = 2; +exports.options = { host: 'tb-stage.worksys.io', port: 1883, clientid: "", username: "" }; + +exports.html = `
+
+
+
Hostname or IP address (if not empty - setting will override db setting)
+
+
+
Port
+
+
+
+
+
@(Client id)
+
+
+
topic
+
+
+
`; + + + +const { promisifyBuilder } = require('./helper/db_helper'); +const fs = require('fs'); +const mqtt = require('mqtt'); +const nosql = NOSQL('tbdatacloud'); + +const SEND_TO = { + debug: 0, + rpcCall: 1, +} + +//CONFIG +let saveTelemetryOnError = true;//backup_on_failure overrides this value +//------------------------ + +const noSqlFileSizeLimit = 4194304;//use 5MB - 4194304 +let insertNoSqlCounter = 0; +let insertBackupNoSqlCounter = 0; +let processingData = false; + +let backup_on_failure = true;//== saveTelemetryOnError - create backup client send failure +let restore_from_backup = 50; //how many rows process at once? +let restore_backup_wait = 3;//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; + + +exports.install = function(instance) { + + var client; + var opts; + var clientReady = false; + + let o = null; //options + + function main() + { + loadSettings(); + } + + //set opts according to db settings + function loadSettings() + { + + o = instance.options; + if(!o.topic) o.topic = FLOW.GLOBALS.settings.cloud_topic; + + opts = { + host: o.host, + port: o.port, + clientId: o.clientid, + username: o.username, + rejectUnauthorized: false, + resubscribe: false + }; + + console.log("wsmqttpublich -> loadSettings from instance.options",o); + + connectToTbServer(); + } + + function connectToTbServer() + { + var url = "mqtt://" + opts.host + ":" + opts.port; + console.log("MQTT URL: ", url); + + client = mqtt.connect(url, opts); + + client.on('connect', function() { + client.subscribe(`${o.topic}_backward`, (err) => { + if (!err) { + console.log("MQTT subscribed"); + } + }); + instance.status("Connected", "green"); + clientReady = true; + sendClientError = true; + }); + + client.on('reconnect', function() { + instance.status("Reconnecting", "yellow"); + clientReady = false; + }); + + client.on('message', function(topic, message) { + // message is type of buffer + message = message.toString(); + if (message[0] === '{') { + TRY(function() { + + message = JSON.parse(message); + if (message.hasOwnProperty("device") && message.hasOwnProperty("data") && message.data.hasOwnProperty("id")) { + client.publish(`${o.topic}_forward`, `{"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}}); + } + + }, () => instance.debug('MQTT: Error parsing data', message)); + } + + instance.send(SEND_TO.rpcCall, {"topic":o.topic, "content":message }); + }); + + client.on('close', function() { + clientReady = false; + + instance.status("Disconnected", "red"); + instance.send(SEND_TO.debug, {"message":"Client CLOSE signal received !"}); + }); + + client.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) { + console.log('MQTT client error', err); + sendClientError = false; + } + clientReady = false; + }); + + } + + + instance.on('0', function(data) { + + if(clientReady) + { + //do we have some data in backup file? if any, process data from database + if(saveTelemetryOnError) + { + //read telemetry data and send back to server + if(!processingData) processDataFromDatabase(); + } + + let stringifiedJson = JSON.stringify(data.data) + client.publish(`${o.topic}_forward`, stringifiedJson, {qos: 1}); + } + 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(saveTelemetryOnError) + { + //create new file from tbdata.nosql, if file size exceeds given limit, and clear tbdata.nosql + makeBackupFromDbFile(); + + //write to tb + data.data.id = UID(); + nosql.insert(data.data); + } + } + }); + + instance.on("1", _ => { + main(); + }) + + instance.close = function(done) { + if(clientReady){ + client.end(); + } + }; + + + function getDbBackupFileCounter(type) + { + var files = fs.readdirSync(__dirname + "/../databases"); + + let counter = 0; + for(var i = 0; i < files.length; i++) + { + + if(files[i] == "tbdatacloud.nosql") continue; + + if(files[i].endsWith(".nosql")) + { + + let pos = files[i].indexOf("."); + if(pos > -1) + { + + let fileCounter = counter; + let firstDigit = files[i].slice(0, pos); + + fileCounter = parseInt(firstDigit); + if(isNaN(fileCounter)) fileCounter = 0; + //console.log("getDbBackupFileCounter digit:", files[i], firstDigit, fileCounter, isNaN(fileCounter), type); + + if(type == "max") + { + if(fileCounter > counter) + { + counter = fileCounter; + } + } + else if(type == "min") + { + if(counter == 0) counter = fileCounter; + + if(fileCounter < counter) + { + counter = fileCounter; + } + } + } + } + + } + + if(type == "max") counter++; + + return counter; + } + + const makeBackupFromDbFile = async () => { + + if(!saveTelemetryOnError) return; + + //to avoid large file: tbdata.nosql + + //init value is 0! + if(insertNoSqlCounter > 0) + { + --insertNoSqlCounter; + return; + } + + insertNoSqlCounter = 100; + + let source = __dirname + "/../databases/tbdatacloud.nosql"; + + var stats = fs.statSync(source); + var fileSizeInBytes = stats.size; + + if(fileSizeInBytes > noSqlFileSizeLimit) + { + + let counter = 1; + counter = getDbBackupFileCounter("max"); + + let destination = __dirname + "/../databases/" + counter + "." + "tbdatacloud.nosql"; + + //make backup file + fs.copyFileSync(source, destination); + //fs.renameSync(p, p + "." + counter); + + //clear tbdata.nosql + fs.writeFileSync(source, ""); + fs.truncateSync(source, 0); + + } + } + + const processDataFromDatabase = async () => { + + if(restore_from_backup <= 0) return; + + //calculate diff + const now = new Date(); + let currentTime = now.getTime(); + let diff = currentTime - lastRestoreTime; + + if( (diff / 1000) < restore_backup_wait) + { + //console.log("*********restore_backup_wait", diff, restore_backup_wait); + return; + } + + processingData = true; + + //get filename to process + let counter = getDbBackupFileCounter("min"); + + //we have some backup files + let dataBase = 'tbdata'; + + var nosql; + if(counter == 0) dataBase = 'tbdatacloud'; + else dataBase = counter + "." + 'tbdatacloud'; + + nosql = NOSQL(dataBase); + + //select all data - use limit restore_from_backup + let records = await promisifyBuilder(nosql.find().take(restore_from_backup)); + + for(let i = 0; i < records.length; i++) + { + if(clientReady) { + + let item = records[i]; + let id = item.id; + + if(id !== undefined) + { + //console.log("------------processDataFromDatabase - remove", id, dataBase, i); + + try { + + let message = JSON.parse(JSON.stringify(item)); + delete message.id; + client.publish(`${o.topic}_forward`, JSON.stringify(message), {qos:1}); + + //remove from database + await promisifyBuilder(nosql.remove().where("id", id)); + + } catch(error) { + //process error + console.log("processDataFromDatabase", error); + } + + } + + } + else + { + processingData = false; + return; + } + } + + if(records.length > 0) + { + //clean backup file + if(counter > 0) nosql.clean(); + } + + //no data in db, remove + if(records.length == 0) + { + if(counter > 0) nosql.drop(); + } + + const d = new Date(); + lastRestoreTime = d.getTime(); + + processingData = false; + + } + + instance.on('options', main); + +}; diff --git a/RVO35/flow_old/cmd_manager.js b/RVO35/flow_old/cmd_manager.js new file mode 100755 index 0000000..aab6843 --- /dev/null +++ b/RVO35/flow_old/cmd_manager.js @@ -0,0 +1,2890 @@ +exports.id = 'cmd_manager'; +exports.title = 'CMD Manager'; +exports.group = 'Worksys'; +exports.color = '#5D9CEC'; +exports.version = '0.0.3'; +exports.output = ['red', 'blue', 'yellow', 'blue', 'white']; +exports.input = 3; +exports.icon = 'cloud-upload'; + +exports.html = ` +
+
+
+
RPC - run RPC calls

+
+
+
@(User)
+
+
+
@(Password)
+
+
+
@(My edge)
+
+
+
+`; +exports.readme = `Manager for CMD calls`; + + +exports.install = function(instance) { + + 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'); + + 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'); + + const dbNodes = TABLE("nodes"); + const dbRelays = TABLE("relays"); + + let GLOBALS; + let SETTINGS; + let rsPort; + let tbHandler; + + // runTasks intervals + const SHORT_INTERVAL = 30; + const LONG_INTERVAL = 300; + + //send data to following instances: + const SEND_TO = { + debug: 0, + tb: 1, + http_response: 2, + dido_controller: 3, + infoSender: 4 + } + + 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 + } + + 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["89"] = minutes; + + //prikazy kt sa budu spustat na dany node - see config.js in terminal-oms.app. (1 - dimming) + let listOfCommands = [0, 1, 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 sunCalcResult; + let reportDuskDawn; + + //helper container for counting resolved group of commands (commands related to set profile) + let cmdCounter = {};//key is node, value is counter + + //if sending of profile to node fails, we send notification and push node into set, so we do not send notification twice + const nodeProfileSendFail = new Set(); + + //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); + + errorHandler.setProjectsId(SETTINGS.project_id); + + 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(); + } + + + 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" + //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.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.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). + */ + + 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.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.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 + { + + 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); + + 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); + + console.log("proces profile finished *********************") + } + + + 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; + }); + } + + + 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) { + for (let k in nodesData) { + 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`); + } + } + } + + + function loadRelaysData(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 (value.contactor == 1) processAllNodeProfilesOnLine(value.line); + } + } + + + function reportOnlineNodeStatus(line) { + //Po zapnutí línie broadcastovo aktualizovať predtým čas a o 3 sek neskor - status, brightness + + logger.debug("--->reportOnlineNodeStatus for line", line); + + const d = new Date(); + + //run broadcast //Actual time + let params = getParams(); + params.address = 0xffffffff;//Broadcast + params.byte1 = d.getHours(); + params.byte2 = d.getMinutes(); + params.recipient = 2;//2 broadcast, address = 0 + params.register = 87;//Actual time + params.rw = 1;//write + params.type = "cmd"; + params.timestamp = d.getTime() + 30000; + params.addMinutesToTimestamp = 0; + params.info = "run broadcast: Actual time"; + + tasks.push(params); + + let sec = 3; + setTimeout(function() { + //Po zapnutí línie - spraviť hromadný refresh stavu práve zapnutých svietidiel + + let time = Date.now(); + + for (let k in nodesData) { + + //potrebujem nody k danej linii + 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].node_status_before_offline == true || nodesData[k].status === true) { + status = "OK"; + nodesData[k].time_of_last_communication = time; + } + + updateNodeStatus(k, status === "OK" ? true : false); + if (nodesData[k].hasOwnProperty("node_status_before_offline")) delete nodesData[k].node_status_before_offline; + sendTelemetry({ status: status }, tbname, time); + + //vyreportovanie dimming, current, input power pre liniu pre vsetky nody + //Prud + { + let params = getParams(); + + params.type = "cmd"; + params.tbname = tbname; + params.address = node; + params.register = 75;//prud + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = time + 3000; + params.info = 'read current'; + //params.debug = true; + + tasks.push(params); + } + + //vykon + { + let params = getParams(); + + params.type = "cmd"; + params.tbname = tbname; + params.address = node; + params.register = 76;//výkon + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = time + 3100; + params.info = 'read power'; + //params.debug = true; + + tasks.push(params); + } + //dimming + { + let params = getParams(); + + params.type = "cmd"; + params.tbname = tbname; + params.address = node; + params.register = 1;//dimming + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = time + 3200; + params.info = 'read dimming'; + //params.debug = true; + + tasks.push(params); + } + + } + } + + }, sec * 1000); + } + + + 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"; + + const date = Date.now(); + + 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; + let nodeStatus = nodesData[node].status; + + nodesData[node].node_status_before_offline = nodeStatus === true ? true : false; + nodesData[node].status = "OFFLINE"; + + sendTelemetry({ ...values }, tbname, date); + } + + }, (index + 1) * 300); + }) + + } + + + function turnLine(onOrOff, line, info) { + let obj = { + line: line, + command: onOrOff, + info: info + }; + + //logger.debug("linia", line, obj); + instance.send(SEND_TO.dido_controller, obj); + } + + + + 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"; + 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]) { + //CRC_ERROR + message = "NOK"; + error = "CRC_ERROR c1"; + instance.send(SEND_TO.debug, "CRC_ERROR c1"); + } + + 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") { + instance.send(SEND_TO.debug, bytes); + instance.send(SEND_TO.debug, "RESPONSE " + type + " - " + bytes[4]); + + //logger.debug(SEND_TO.debug, "RESPONSE " + type + " - " + bytes[4], bytes); + + error = "type is: " + type; + + message = "NOK"; + } + + return { message, type, error }; + } + + + //BUILD TASKS// + function buildTasks(params) { + //report SETTINGS.edge_fw_version as fw_version + //report date as startdate + + //return; + console.log("buidTAaasks start ****************", params); + + monitor.info("buildTasks - params", params); + + let processLine; //defined line + let init = false; + let processLineProfiles = true; + let processBroadcast = true; + let processNodes = true; + + if (params == undefined) { + init = true; + tasks = []; + logger.debug("-->buildTasks clear tasks"); + } + else { + processLineProfiles = false; + processBroadcast = false; + processNodes = false; + + processLineProfiles = params.processLineProfiles; + processLine = params.line; + } + + let now = new Date(); + + //process line profiles + if (processLineProfiles) { + + let keys = Object.keys(relaysData); + + for (let i = 0; i < keys.length; i++) { + + let line = parseInt(keys[i]); + let profilestr = relaysData[line].profile; + + if (processLine != undefined) { + if (processLine != line) continue; + } + + try { + + /** + * we process line profiles: timepoints, astro clock, lux_sensor, offsets ... + */ + if (profilestr === "") throw ("Profile is not defined"); + let profile = JSON.parse(profilestr); + 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; + + // add name to regular profile timepoint and delete unused end_time key: + time_points.forEach(point => { + point.name = "profileTimepoint" + delete point.end_time; + }); + + //monitor.info("buildTasks: time_points", time_points); + + + /** + * 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 astro clock true, we remove all regular profile points + time_points = []; + + 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 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); + + 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); + + 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(':'); + + let ad = new Date(); + ad.setHours(parseInt(ahours), parseInt(aminutes), 0); + + let bd = new Date(); + bd.setHours(parseInt(bhours), parseInt(bminutes), 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++) { + + let start_time = new Date(); + let [hours, minutes] = time_points[t].start_time.split(':'); + start_time.setHours(parseInt(hours), parseInt(minutes), 0); + + //task is in 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(); + params.type = "relay"; + params.line = parseInt(line); + params.value = time_points[t].value; + params.tbname = relaysData[line].tbname; + params.timestamp = start_time.getTime(); + 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; + + //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)) { + 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; + + params.debug = true; + + //turn on/off line + tasks.push(params); + monitor.info("TimePoint params: ", params.info, start_time); + } + + monitor.info("-->time_points final", line, time_points); + + //ensure to turn on/off according to calculated currentValue + let params = getParams(); + params.type = "relay"; + params.line = parseInt(line); + params.tbname = relaysData[line].tbname; + params.value = currentValue; + + params.timestamp = i; + params.addMinutesToTimestamp = 0; + params.debug = true; + + //logger.debug(now.toLocaleString("sk-SK")); + 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; + + tasks.push(params); + + } catch (error) { + if (profilestr !== "") { + //errLogger.error(profilestr, error); + console.log(`Cmd_manager: Unable to process line profile ${line}. Error: `, error); + errorHandler.sendMessageToService(profilestr + "-" + error, 0, "js_error"); + } else { + turnLine("off", line, "No line profile. Switching it off on startup"); + } + } + + } + //logger.debug("tasks:"); + //logger.debug(tasks); + } + + + //PROCESS DEFAULT BROADCASTS + //Time of dusk, Time of dawn, Actual Time + + if (processBroadcast) { + + let d = new Date(); + let time = d.getTime(); + let sunCalcResult = calculateDuskDawn(); + + { + //run broadcast Time of dusk + let params = getParams(); + + params.address = 0xffffffff;//broadcast + params.byte1 = sunCalcResult["dusk_hours"]; + params.byte2 = sunCalcResult["dusk_minutes"]; + params.recipient = 2;//2 broadcast, + params.register = 6;//Time of dusk - Reg 6 + params.rw = 1;//write + + params.type = "cmd"; + params.timestamp = time + 60000; + params.addMinutesToTimestamp = 60 * 3; //kazde 3 hodiny zisti novy dusk + params.info = "Broadcast-duskTime"; + + tasks.push(params); + } + + { + //run broadcast Time of dawn + let params = getParams(); + + params.address = 0xffffffff;//broadcast + params.byte1 = sunCalcResult["dawn_hours"]; + params.byte2 = sunCalcResult["dawn_minutes"]; + params.recipient = 2; //2 broadcast + params.register = 7;//Time of dawn - Reg 6 + params.rw = 1;//write + + params.type = "cmd"; + params.timestamp = time + 60001; + params.addMinutesToTimestamp = 60 * 3; //kazde 3 hodiny zisti novy dawn + params.info = "Broadcast-dawnTime"; + + tasks.push(params); + } + + { + //run broadcast Actual time + let params = getParams(); + + params.address = 0xffffffff;//broadcast + params.byte1 = d.getHours(); + params.byte2 = d.getMinutes(); + params.recipient = 2; //2 broadcast + params.register = 87;//Actual time + params.rw = 1;//write + + params.type = "cmd"; + params.timestamp = time + 60002; + params.addMinutesToTimestamp = 5; + params.info = "run broadcast: Actual time"; + + tasks.push(params); + } + + } + + //process nodes & tasks + //reportovanie pre platformu + if (processNodes) { + + let time = Date.now(); + + 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++) { + + register = listOfCommands[i]; + let addMinutesToTimestamp = priorities[register]; + + let params = getParams(); + + params.address = address; + params.recipient = 1; + params.register = register; + params.type = "cmd"; + params.tbname = tbname; + params.timestamp = time + 5000 + i * 500 + addMinutesToTimestamp * 1000; //to make slight time difference + params.addMinutesToTimestamp = addMinutesToTimestamp; + params.info = "generated cmd - buildTasks (node)"; + + tasks.push(params); + } + + } + } + + + //niektore ulohy sa vygeneruju iba 1x pri starte!!! + if (!init) return; + + + //Master node FW version + { + let params = getParams(); + params.type = "cmd-master"; + params.register = 4; + params.address = 0; + params.timestamp = Date.now() + 60000; + params.addMinutesToTimestamp = 5; + params.tbname = SETTINGS.rvoTbName; + params.info = "Master node FW verzia"; + //params.debug = true; + //this will set SETTINGS.masterNodeIsResponding + + tasks.push(params); + } + + //kazdu hodinu skontrolovat nastavenie profilov + { + let params = getParams(); + params.type = "process_profiles"; + params.timestamp = Date.now() + 60000; + params.addMinutesToTimestamp = 60;//60 = every hour + params.info = "detekcia nespracovaných profilov linie a nodov"; + //params.debug = true; + + tasks.push(params); + } + + monitor.info("tasks created:", tasks.length); + } + + + /** + * We process line profile, where "astro_clock": true + * example profile: + * + "dawn_lux_sensor": true, + "dusk_lux_sensor": true, + "dawn_lux_sensor_value": 5, + "dusk_lux_sensor_value": 5, + "dawn_astro_clock_offset": 0, + "dusk_astro_clock_offset": 10, + "dawn_lux_sensor_time_window": 30, + "dusk_lux_sensor_time_window": 30, + "dawn_astro_clock_time_window": 60, + "dusk_astro_clock_time_window": 60 + + * if dawn: if currentTimestamp is in timewindow "dawnTime + and - dawn_lux_sensor_time_window" and lux value >= lux_sensor_value, we switch off the line. + * if dusk: we do oposite + * + * dawn: usvit - lux je nad hranicou - vypnem + * dusk: sumrak - lux je pod hranicou - zapnem + */ + 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++) { + + let line = keys[i]; //line is turned off by default + let profilestr = relaysData[line].profile; + const contactor = relaysData[line].contactor; + + try { + + let profile = JSON.parse(profilestr); + if (Object.keys(profile).length === 0) throw ("turnOnOffLinesAccordingToLuxSensor - profile is not defined"); + + 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 (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"); + } + } + } + + //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 (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"); + } + } + } + + } + + } catch (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) { + //MASTER + if (node == 0) return; + + let nodeObj = nodesData[node]; + if (nodeObj == undefined) return; + + let nodeCurrentStatus = nodeObj.status; + const now = Date.now(); + + let data = null; + + if (nodeCurrentStatus === "OFFLINE") { + data = { status: newStatus }; + nodeDbStatusModify(node, data); + return; + } + else 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; + } + + } + + + 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 }; + } + }); + }); + } + + + async function runTasks() { + + clearInterval(interval); + + let currentTimestamp = Date.now(); + + //report dusk, dawn--------------------------------- + if (reportDuskDawn.dusk_time < currentTimestamp) { + //vyreportuj iba ak nie je velky rozdiel napr. 60 sekund + 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); + reportDuskDawn.dusk_time_reported = sunCalcResult.dusk_time; + } + } + + var nextDay = new Date(); + nextDay.setDate(nextDay.getDate() + 1); + + sunCalcResult = calculateDuskDawn(nextDay); + reportDuskDawn.dusk_time = sunCalcResult.dusk_time; + } + + if (reportDuskDawn.dawn_time < currentTimestamp) { + //vyreportuj iba ak nie je velky rozdiel napr. 60 sekund + 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); + reportDuskDawn.dawn_time_reported = sunCalcResult.dawn_time; + } + } + + var nextDay = new Date(); + nextDay.setDate(nextDay.getDate() + 1); + + sunCalcResult = calculateDuskDawn(nextDay); + reportDuskDawn.dawn_time = sunCalcResult.dawn_time; + + } + //-------------------------------------------------------- + + //sort tasks based on timestamp + 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) { + instance.send(SEND_TO.debug, "no tasks created"); + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + 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) { + //logger.debug("--->task to process", currentTask); + } + + if (currentTask.timestamp <= currentTimestamp) { + let params = { ...tasks[0] }; + + //allow terminal commands + if (SETTINGS.maintenance_mode && params.type !== "cmd-terminal") { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + let type = params.type; + let tbname = params.tbname; + let node = params.address; + + let line = null; + + //rpc related + if (nodesData[node] !== undefined) line = nodesData[node].line; + if (params.line !== undefined) line = params.line; + + let repeatTask = false; + if (params.addMinutesToTimestamp > 0 || params.timePointName) repeatTask = true; + + if (repeatTask) { + if (type === "cmd" || type === "cmd-master") { + //set next start time automatically + tasks[0].timestamp = currentTimestamp + tasks[0].addMinutesToTimestamp * 60000; + } + } + else { + tasks.shift(); + } + + //kontrola nespracovanych profilov nodov + if (type == "process_profiles") { + tasks[0].timestamp = currentTimestamp + tasks[0].addMinutesToTimestamp * 60000; + + //na vsetky zapnutych liniach sa spracuju nespracovane profily nodov + loadRelaysData(); + + interval = setInterval(runTasks, SHORT_INTERVAL); + return; + } + + //relay + if (type == "relay") { + + const timePointName = params.timePointName; + const value = params.value; + + let date = new Date(); + date.setDate(date.getDate() + 1);//next day + + let sunCalcResult; + if (timePointName) sunCalcResult = calculateDuskDawn(date, params.line); + + if (timePointName == "dawn") { + tasks[0].timestamp = sunCalcResult.dawn_time; + } + else if (timePointName == "dusk") { + tasks[0].timestamp = sunCalcResult.dusk_time; + } + else if (timePointName == "luxOn") { + tasks[0].timestamp = sunCalcResult.dusk_time + params.dusk_lux_sensor_time_window * 60000; + } + else if (timePointName == "luxOff") { + tasks[0].timestamp = sunCalcResult.dawn_time + params.dawn_lux_sensor_time_window * 60000; + } + else if (timePointName == "profileTimepoint") { + tasks[0].timestamp = currentTimestamp + tasks[0].addMinutesToTimestamp * 60000; + } + + let info = "aplikovany bod profilu"; + let onOrOff = ""; + value == 1 ? onOrOff = "on" : onOrOff = "off"; + + turnLine(onOrOff, params.line, info); + + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + //zhodeny hlavny istic + let disconnected = false; + //if(rotary_switch_state == "Off") disconnected = true; + + //state_of_breaker[line] - alebo istic linie + 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" }; + + 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; + + if (!disconnectedReport[tbname]) { + sendTelemetry(values, tbname) + } + + interval = setInterval(runTasks, SHORT_INTERVAL); + + return; + } + + disconnectedReport[tbname] = false; + + const register = params.register; + + if (!SETTINGS.masterNodeIsResponding) { + //ak neodpoveda, nebudeme vykonavat ziadne commands, okrem cmd-terminal, a fw version + errorHandler.sendMessageToService("Master node is not responding"); + + let stop = true; + + //fw version - register == 4 + if (type == "cmd-terminal" || register == 4) stop = false; + if (stop) { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + } + + let contactorStatus = 1; + if (relaysData[line] != undefined) contactorStatus = relaysData[line].contactor; + + if (line == 0 || contactorStatus == 0) { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + // TODO: -> status offline for rvo if rotary_switch_state is OFF, this is source of errors + // + // let relayStatus = 1; + // if (relaysData[line] != undefined) { + // relayStatus = relaysData[line].contactor; + // } + + // if (line == 0) relayStatus = 0; + // if (type == "cmd-terminal") relayStatus = 1; + + // //check if rotary_switch_state == "Off" + // if (relayStatus == 0) { + // console.log("------------------------------------relayStatus", relayStatus, line); + // let values = { "status": "OFFLINE" }; + + // if(tbname) sendTelemetry(values, tbname) + + // interval = setInterval(runTasks, SHORT_INTERVAL); + // return; + // } + + if (!rsPort.isOpen) { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + //RE-CALCULATE VALUES + //set actual time for broadcast + if (register == 87 && params.recipient === 2) { + var d = new Date(); + params.byte1 = d.getHours();//h + params.byte2 = d.getMinutes();//m + } + + //SET DUSK/DAWN FOR BROADCAST + //Time of dusk + if (register == 6 && params.recipient === 2) { + + if (type != "cmd-terminal") { + let sunCalcResult = calculateDuskDawn(); + params.byte1 = sunCalcResult["dusk_hours"];//h + params.byte2 = sunCalcResult["dusk_minutes"];//m + + //TODO astrohodiny + let dusk = "Time of dusk: " + sunCalcResult["dusk"]; + } + } + + //Time of dawn + if (register == 7 && params.recipient === 2) { + if (type != "cmd-terminal") { + let sunCalcResult = calculateDuskDawn(); + params.byte1 = sunCalcResult["dawn_hours"];//h + params.byte2 = sunCalcResult["dawn_minutes"];//m + + //TODO astrohodiny + let dawn = "Time of dawn: " + sunCalcResult["dawn"]; + } + + } + //----------------------- + + instance.send(SEND_TO.debug, "address: " + node + " register:" + register + "type: " + 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(node, params.recipient, params.rw, register, params.name, params.byte1, params.byte2, params.byte3, params.byte4); + let readBytes = 11; + let timeout = 4000; + + // await keyword is important, otherwise incorrect data is returned! + 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); + + //ak sa odpoved zacina 0 - je to v poriadku, inak je NOK + let message = result.message; // OK, NOK + let message_type = result.type; + let error = result.error; + + if (params.debug != "generated cmd") { + //debug("writeData: done " + message_type + " duration: " + timeDiff + " message_type: " + params.debug, params); + } + + // 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); + // } + // } + + //debug("writeData: done " + message_type + " duration: " + timeDiff + " message_type: " + params.debug); + //debug("writeData done", message_type, "duration", timeDiff, "message_type", params.debug, result); + + let values = {}; + + //CMD FINISHED + if (message == "OK") { + + updateNodeStatus(node, true); + + //write + if (type == "set_node_profile") { + let result = cmdCounterResolve(node); + if (result == 0) { + dbNodes.modify({ processed: true }).where("node", node).make(function(builder) { + builder.callback(function(err, response) { + + sendNotification("CMD Manager: process cmd", SETTINGS.rvoTbName, "dimming_profile_was_successfully_received_by_node", { node: node }, "", SEND_TO.tb, instance); + + logger.debug("--> profil úspešne odoslaný na node č. " + node); + nodesData[node].processed = true; + nodeProfileSendFail.delete(node); + }); + }); + } + } + + //parse read response + if (params.rw == 0) { + values = processResponse(register, dataBytes); //read + } + + if (itIsNodeCommand) { + values.comm_status = "OK"; + values.status = "OK"; + } + + //master node + if (node == 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; + } + + //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.debug) { + //logger.debug("saveToTb", saveToTb, tbname, values); + } + + if (saveToTb) { + sendTelemetry(values, tbname) + } + else { + if (type == "cmd-terminal") { + terminalCommandResponse(params, "SUCCESS", data); + } + } + + } + else { + + terminalCommandResponse(params, "ERROR", data); + handleNokResponseOnRsPort("handleNOK else block", params, itIsNodeCommand, saveToTb); + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + //logger.debug("writeData err: ", error, result, params); + logger.debug("writeData err: ", tbname, node, register, values); + } + } + + //logger.debug(error, result, params); + } + }).catch(function(reason) { + + console.log("writeData catch exception", reason); + instance.send(SEND_TO.debug, reason); + + terminalCommandResponse(params, "FAILURE", null, reason); + handleNokResponseOnRsPort("handleNOK catch block", params, itIsNodeCommand, saveToTb); + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + logger.debug("-->WRITE FAILED: " + reason, params.debug, params); + } + } + + }); + + } + 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); + } + + + function handleNokResponseOnRsPort(message, params, itIsNodeCommand, saveToTb) { + + let node = params.address; + let register = params.register; + let type = params.type; + let tbName = params.tbname; + if (!tbName) return; + + let values = {}; + + let updateStatus = updateNodeStatus(node, false); + + console.log("cmd_man: handleNokRsPort: ", node, register, message); + //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; + + if (register == 4) values["master_node_version"] = "NOK"; + } + + if (type == "set_node_profile") { + delete cmdCounter[node]; + logger.debug("profil nebol úspešne odoslaný na node č. ", params); + + if (!nodeProfileSendFail.has(node)) { + sendNotification("CMD Manager: process cmd", tbName, "configuration_of_dimming_profile_to_node_failed", { node: node }, "", SEND_TO.tb, instance); + nodeProfileSendFail.add(node); + } + } + + if (itIsNodeCommand) { + values.comm_status = "NOK"; + } + + 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 === "OFFLINE") { + nodeObj.node_status_before_offline === true ? number_of_ok_luminaires++ : number_of_nok_luminaires++; + } + else if (nodeObj.status == true) 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"); + + 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); + }); + }); + + 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); + + instance.send(SEND_TO.debug, err.message); + }); + + rsPort.on("close", () => { + setTimeout(() => rsPort.open(), 1000); + }); + + 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.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(); + return; + } + else if (flowdata.data == "close") { + rsPort.close(); + return; + } + else if (flowdata.data == "clean") { + tasks = []; + return; + } + else if (flowdata.data == "buildtasks") { + //build & run + return; + } + else if (flowdata.data == "run") { + //durations = []; + + if (tasks.length == 0) { + + buildTasks(); + + if (rsPort.isOpen) { + interval = setInterval(runTasks, 100); + } + else { + instance.send(SEND_TO.debug, "port is not opened!!!"); + } + } + } + else { + //terminal data - object + //logger.debug("flowdata", flowdata.data); + + if (typeof flowdata.data === 'object') { + //logger.debug("dido", flowdata.data); + if (flowdata.data.hasOwnProperty("sender")) { + //data from dido_controller + if (flowdata.data.sender == "dido_controller") { + + if (flowdata.data.hasOwnProperty("cmd")) { + let cmd = flowdata.data.cmd; + + if (cmd == "buildTasks") { + clearInterval(interval); + + logger.debug("-->CMD MANAGER - BUILD TASKS"); + buildTasks(); + + //logger.debug("tasks:"); + //logger.debug(tasks); + + logger.debug("-->CMD MANAGER - RUN TASKS"); + interval = setInterval(runTasks, LONG_INTERVAL); + } + else if (cmd == "reload_relays") { + loadRelaysData(flowdata.data.line); + + if (flowdata.data.dataChanged) { + if (!flowdata.data.value) { + reportOfflineNodeStatus(flowdata.data.line); + } + else { + reportOnlineNodeStatus(flowdata.data.line); + } + } + + } + else if (cmd == "rotary_switch_state") { + let value = flowdata.data.value; + + //state was changed + if (rotary_switch_state != value) { + if (value == "Off") { + //vyreportovat vsetky svietdla + reportOfflineNodeStatus(); + } + + rotary_switch_state = value; + } + } + 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) { + + // we send lux_sensor value to all nodes: + let params = getParams(PRIORITY_TYPES.node_broadcast); + + params.recipient = 2;//2 broadcast, address = 0 + params.address = 0xffffffff;//Broadcast + + let ba = longToByteArray(lux_sensor); + + params.byte3 = ba[1];//msb + params.byte4 = ba[0]; + params.timestamp = PRIORITY_TYPES.node_broadcast; + params.info = "run broadcast: Actual Lux level from cabinet"; + params.register = 95;//Actual Lux level from cabinet + params.rw = 1;//write + + tasks.push(params); + + //process profiles + turnOnOffLinesAccordingToLuxSensor(lux_sensor); + } + } + else if (cmd == "state_of_breaker") { + //istic linie + let value = flowdata.data.value; + let line = parseInt(flowdata.data.line); + + let dataChanged = false; + if (state_of_breaker[line] != value) dataChanged = true; + + state_of_breaker[line] = value; + + let status = "OK"; + if (value == "Off") status = "NOK"; + + if (dataChanged) { + + 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"); + + //report status liniu + sendTelemetry({ status: status }, tbname) + + //current value + if (value == "Off") reportOfflineNodeStatus(line); //vyreportovat vsetky svietidla na linii + } + + } + } + else { + logger.debug("undefined cmd", cmd); + } + } + } + + return; + } + + //data from worksys + 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 command = data.params.command; + let method = data.method; + let profile = data.params.payload; + if (profile == undefined) profile = ""; + let entity = data.params.entities[0]; + let entity_type = entity.entity_type; + let tbname = entity.tb_name; + + instance.send(SEND_TO.debug, flowdata.data); + 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") { + + //let command = data.params.command; + let value = data.params.payload.value; + + if (command == "dimming") { + + let nodeWasFound = false; + let keys = Object.keys(nodesData); + + //logger.debug("-----", keys); + + 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); + + 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; + + //ak linia je + + //debug(params); + logger.debug("dimming", params); + + tasks.push(params); + + 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); + + 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); + } + + //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; + + tasks.push(params); + } + + //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; + + tasks.push(params); + } + + //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; + + tasks.push(params); + } + + }, 4000); + + + nodeWasFound = true; + + break; + } + } + + if (!nodeWasFound) { + logger.debug("set dimming from platform", "unable to find tbname", tbname); + } + } + else { + instance.send(SEND_TO.debug, "undefined command " + command); + logger.debug("undefined command", command); + } + + return; + } + 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++) { + let node = keys[i]; + if (tbname == nodesData[node].tbname) { + + 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"); + + //profil úspešne prijatý pre node č. xx + 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; + + processNodeProfile(node); + }); + }); + } + } + } + else { + + instance.send(SEND_TO.debug, "unknown method " + method); + logger.debug("unknown method", method); + + return; + } + } + + //nastav profil linie z platformy + 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") { + + 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++) { + let line = keys[i]; + if (tbname == relaysData[line].tbname) { + //zmazeme tasky + 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) { + + //update profile + logger.debug("worksys - update relay profile done:", profile); + instance.send(SEND_TO.debug, "worksys - update relay profile done"); + + relaysData[line].profile = profile; + + loadRelaysData(line) + 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); + }); + }); + break; + } + } + } + else if (method == "set_command") { + let value = data.params.payload.value; + + 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; + + 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"); + } + } + else { + instance.send(SEND_TO.debug, "undefined method " + method); + logger.debug("undefined method", method); + } + + return; + } + else { + instance.send(SEND_TO.debug, "UNKNOW entity_type " + entity_type); + logger.debug("UNKNOW entity_type", entity_type); + } + return; + } + + //terminal + if (!rsPort.isOpen) await rsPort.open(); + + let params = flowdata.data.body; + if (params == undefined) { + //logger.debug("CMD manager flowdata.data.body is undefined"); + return; + } + + params.priority = PRIORITY_TYPES.terminal; + params.type = "cmd-terminal"; + params.tbname = ""; + params.timestamp = PRIORITY_TYPES.terminal; + params.addMinutesToTimestamp = 0;// do not repeat task!!! + params.debug = true; + + let timestamp = Date.now(); + params.refFlowdataKey = timestamp; + //params.refFlowdata = flowdata; + //refFlowdata = flowdata; + + //console.log("flowdata", flowdata); + + cleanUpRefFlowdataObj(); + + refFlowdataObj[timestamp] = flowdata; + + //fix + //params.address = params.adress; + logger.debug("received from terminal", params); + logger.debug("date/time:", new Date()); + logger.debug("tasks length:", tasks.length); + + //tasks = []; + + //add to tasks + tasks.push(params); + + } + } + }) + + + //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) + } + + + /** + * 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; + + RESTBuilder.make(function(builder) { + + if (!builder) return; + + builder.method('GET'); + builder.url('http://192.168.252.2:8004/gettime?projects_id=1'); + + builder.callback(function(err, response, output) { + + 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); + } + + }); + } + + } 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); + + } else { + //console.log("Read-only", stdout); + + 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]: [ + { + "ts": date, + "values": values + } + ] + } + + 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); + } + + //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); + } + } + + 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; + } + + //Dimming, CCT + if (register == 1) { + let brightness = 0; + let dimming = byte0; + if (dimming > 128) { + //dimming = -128; + brightness = dimming - 128; + } + + //cct + //Ak Byte3 == 1: CCT = (Byte2*256)+Byte1 + let cct; + if (byte3 == 1) cct = byte2 * 256 + byte1; + else cct = bytesToInt(bytes.slice(0, 3)); + + //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; + } + + //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, 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 + ")"; + } + + 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; + + } + + function getObjectByTbValue(object, tbname) { + return object[Object.keys(object).find(key => object[key].tbname === tbname)]; + } + + function isObject(item) { + return (typeof item === "object" && !Array.isArray(item) && item !== null); + } + +} // end of instance.export + diff --git a/RVO35/flow_old/code.js b/RVO35/flow_old/code.js new file mode 100755 index 0000000..63b31bf --- /dev/null +++ b/RVO35/flow_old/code.js @@ -0,0 +1,90 @@ +exports.id = 'code'; +exports.title = 'Code'; +exports.group = 'Common'; +exports.color = '#656D78'; +exports.input = true; +exports.output = 1; +exports.author = 'Peter Širka'; +exports.icon = 'code'; +exports.version = '1.2.0'; +exports.options = { outputs: 1, code: 'send(0, value);', keepmessage: true }; + +exports.html = `
+
+
+
@(Number of outputs)
+
@(Minimum is 1)
+
+
+
@(Code)
+
@(Keep message instance)
+
+`; + +exports.readme = `# Code + +This component executes custom JavaScript code as it is and it doesn't contain any secure scope. + +\`\`\`javascript +// value {Object} contains received data +// send(outputIndex, newValue) sends a new value +// error(value) sends an error +// instance {Object} a current component instance +// flowdata {Object} a current flowdata +// repository {Object} a current repository of flowdata +// Example: + +// send() can be execute multiple times +send(0, value); +\`\`\``; + +exports.install = function(instance) { + + var fn; + + instance.on('data', function(response) { + if (fn) { + try { + fn(response.data, instance, response, instance.options, response.repository, require); + } catch (e) { + response.data = e; + instance.throw(response); + } + } + }); + + instance.reconfigure = function() { + try { + if (instance.options.code) { + instance.status(''); + var code = 'var send = function(index, value) { if (options.keepmessage) { flowdata.data = value; instance.send2(index, flowdata); } else instance.send2(index, value);}; var error = function(err) { instance.throw(err); }; ' + instance.options.code; + fn = new Function('value', 'instance', 'flowdata', 'options', 'repository', 'require', code); + } else { + instance.status('Not configured', 'red'); + fn = null; + } + } catch (e) { + fn = null; + instance.error('Code: ' + e.message); + } + }; + + instance.on('options', instance.reconfigure); + instance.reconfigure(); +}; \ No newline at end of file diff --git a/RVO35/flow_old/comment.js b/RVO35/flow_old/comment.js new file mode 100755 index 0000000..1e0cd13 --- /dev/null +++ b/RVO35/flow_old/comment.js @@ -0,0 +1,11 @@ +exports.id = 'comment'; +exports.title = 'Comment'; +exports.group = 'Common'; +exports.color = '#704cff'; +exports.author = 'Martin Smola'; +exports.icon = 'comment'; +exports.traffic = false; +exports.version = '1.0.0'; +exports.readme = '# Comment'; + +exports.install = function() {}; diff --git a/RVO35/flow_old/count.js b/RVO35/flow_old/count.js new file mode 100755 index 0000000..fa92ee9 --- /dev/null +++ b/RVO35/flow_old/count.js @@ -0,0 +1,60 @@ +exports.id = 'count'; +exports.title = 'Count'; +exports.version = '1.0.1'; +exports.author = 'John Graves'; +exports.color = '#656D78'; +exports.icon = 'plus-square'; +exports.input = 2; +exports.output = 1; +exports.options = { increment: 1, initialvalue: 1 }; +exports.readme = `# Counter + +Counter Number of times called.`; + +exports.html = `
+
@(Initial Value)
+
@(Increment)
+

Example Video

+
`; + +exports.readme = `# Count + +This component counts the number of messages received. + +__Response:__ + +Integer value based on the initial value and increment settings. + +__Arguments:__ +- Initial Value: What number should be output on the receipt of the first message. +- Increment: What should the increment be for each following message received.`; + +exports.install = function(instance) { + + var count = 0; + var initialCall = true; + + instance.on('data', function(flowdata) { + var index = flowdata.index; + if (index) { + instance.debug('Reset Count.'); + count = instance.options.initialvalue; + initialCall = true; + } else { + // If this is the first time, set the value to 'initial value' + if(initialCall) { + initialCall = false; + count = instance.options.initialvalue; + } else + count = count+instance.options.increment; + instance.status('Count:' + count); + instance.send2(count); + } + }); + + instance.on('options', function() { + count = instance.options.initialvalue; + initialCall = true; + }); + +}; diff --git a/RVO35/flow_old/csv_import.js b/RVO35/flow_old/csv_import.js new file mode 100755 index 0000000..5ae1e68 --- /dev/null +++ b/RVO35/flow_old/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/RVO35/flow_old/db_connector.js b/RVO35/flow_old/db_connector.js new file mode 100755 index 0000000..65ee94b --- /dev/null +++ b/RVO35/flow_old/db_connector.js @@ -0,0 +1,286 @@ +exports.id = 'db_connector'; +exports.title = 'DbConnector'; +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.html = `
+
+
+
DbConnector
+
+
+
`; + +exports.readme = `# read/write data to tables`; + +const instanceSendTo = { + debug: 0, + http_response: 1, +} + +const { promisifyBuilder, makeMapFromDbResult } = require('./helper/db_helper.js'); + +function extractWhereParams(params) +{ + let name = params[0]; + let operator = '='; + let value = params[1]; + + if(params.length == 3) + { + operator = params[1]; + value = params[2]; + } + + return {name: name, operator: operator, value: value}; +} + +exports.install = function(instance) { + + let refFlowdata = null;//holds reference to httprequest flowdata + + instance.on("close", () => { + + }) + + + instance.on("data", async function(flowdata) { + + let params = flowdata.data.body; + console.log("DbConnector", params); + + refFlowdata = flowdata; + + if(refFlowdata != undefined) + { + //make http response + let responseObj = {}; + responseObj["type"] = "SUCESS"; + + try{ + + let table = params.table; + let action = params.action; + + + if(params.data != undefined) + { + let className = params.data.className; + + if(className == "SqlQueryBuilder") + { + let type = params.data.type; + + console.log("SqlQueryBuilder---->", params.data); + + if(type == "SELECT") + { + let table = params.data.queryData.tables[0].table; + + const db = TABLE(table); + var builder = db.find(); + + let result = await promisifyBuilder(builder); + + let response = {}; + response["result"] = result; + response["success"] = true; + + responseObj["data"] = response; + + //console.log(responseObj); + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + } + + return; + } + } + + + console.log("db_connector---->", table, action); + + //actions: read, replace, insert, delete, update... + + if(action == "read") + { + const db = TABLE(params.table); + + //where builder.where('age', '<', 15); + //builder.where('id', 3403); + + var builder = db.find(); + + //https://docs.totaljs.com/latest/en.html#api~DatabaseBuilder~builder.where + if(params.hasOwnProperty("where")) + { + //optionalCan contain "=", "<=", "<", ">=", ">". + //Default value: '=' + + //1.["production_line", 1] + //2. ["or", ["production_line", 1], ["production_line", 2], "end"] + + if (Array.isArray(params.where)) { + + let multipleConditions = false; + + if(params.where[0] == "or") multipleConditions = true; + if (Array.isArray(params.where[0])) multipleConditions = true; + + if(multipleConditions) + { + + for(var i = 0; i < params.where.length; i++) + { + const item = params.where[i]; + + if(item === "or") builder.or(); + + if (Array.isArray(item)) + { + const { name, operator, value } = extractWhereParams(item); + builder.where(name, operator, value); + } + + if(item === "end") builder.end(); + + } + + } + else + { + const { name, operator, value } = extractWhereParams(params.where); + builder.where(name, operator, value); + } + + } + + /* + if(params.where.length >=2 ) + { + let name = params.where[0]; + let operator = '='; + let value = params.where[1]; + + if(params.where.length == 3) + { + operator = params.where[1]; + value = params.where[2]; + } + + builder.where(name, operator, value); + } + */ + } + + if(params.hasOwnProperty("between")) + { + builder.between(params.between[0], params.between[1], params.between[2]); + } + + let response = await promisifyBuilder(builder); + responseObj["data"] = response; + + //console.log(responseObj); + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + + return; + } + + if(action == "delete") + { + + } + + + if(action == "update") + { + //! data receiving from terminal (params) + // { + // hostname: 'localhost', + // table: 'settings', + // action: 'update', + // body: { + // rvo_name: 'terrrr', + // lang: 'en', + // temperature_adress: '28.427B45920702', + // latitude: 48.70826502, + // longitude: 17.28455203, + // mqtt_host: '192.168.252.4', + // mqtt_clientid: 'showroom_test_panel_led', + // mqtt_username: 'xmRd6RJxW53WZe4vMFLU', + // mqtt_port: 1883, + // maintanace_mode: false + // } + // } + const tableToModify = TABLE(params.table); + const newValues = params.body; + + tableToModify.modify(newValues).make(function(builder) { + + builder.callback(function(err, response) { + + if(!err) + { + responseObj["data"] = response; + responseObj["tableUpdated"] = true; + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + } + }); + }); + + } + + if(action == "replace") + { + //truncate table + const db = TABLE(params.table); + var builder = db.remove(); + db.clean(); + + //insert data + let data = params.data; + + for(let i = 0; i < data.length; i++) + { + //console.log(data[i]); + db.insert(data[i]); + } + + console.log("insert done"); + + let responseObj = {}; + responseObj["type"] = "SUCESS"; + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + + + } + + + + } catch (error) { + //console.log(error); + responseObj["type"] = "ERROR"; + responseObj["message"] = error; + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + } + } + }) +} + + diff --git a/RVO35/flow_old/db_init.js b/RVO35/flow_old/db_init.js new file mode 100755 index 0000000..3c8cc58 --- /dev/null +++ b/RVO35/flow_old/db_init.js @@ -0,0 +1,106 @@ +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 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 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.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: "2025-01-21", //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"], + phases: responseSettings[0]["phases"], + cloud_topic: responseSettings[0]["cloud_topic"], + + //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/RVO35/flow_old/debug.js b/RVO35/flow_old/debug.js new file mode 100755 index 0000000..00cb259 --- /dev/null +++ b/RVO35/flow_old/debug.js @@ -0,0 +1,100 @@ +exports.id = 'debug'; +exports.title = 'Debug'; +exports.author = 'Peter Širka'; +exports.color = '#967ADC'; +exports.click = true; +exports.input = true; +exports.icon = 'bug'; +exports.version = '2.0.4'; +exports.options = { enabled: true, repository: false, type: 'data' }; +exports.readme = `# Debug + +Prints data to the debug tab.`; + +exports.html = `
+
+
+
@(Output type)
+
@(Path to the property (leave empty to show the whole data object))
+
@(A group name)
+
@(Enabled)
+
+
+
`; + +exports.install = function(instance) { + + instance.on('data', function(response) { + if (instance.options.enabled) { + + var opt = instance.options; + var rep = response.repository; + var val = response.data; + var id = response.id; + + switch (instance.options.type){ + case 'both': + var data = {}; + data.repository = rep; + data.data = val instanceof Error ? { error: val.message, stack: val.stack } : val; + instance.debug(safeparse(opt.property ? U.get(data, opt.property) : data), undefined, opt.group, id); + break; + case 'repository': + instance.debug(safeparse(opt.property ? U.get(rep, opt.property) : rep), undefined, opt.group, id); + break; + case 'data': + default: + if (val instanceof Error) + instance.debug({ error: val.message, stack: val.stack }, undefined, opt.group, id); + else + instance.debug(safeparse(opt.property ? U.get(val, opt.property) : val), undefined, opt.group, id); + break; + } + } + }); + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + instance.save(); + }); + + instance.on('options', function() { + instance.custom.status(); + }); + + instance.custom.status = function() { + instance.status(instance.options.enabled ? 'Enabled' : 'Disabled'); + }; + + instance.custom.status(); + + function safeparse(o) { + + if (o instanceof Buffer) + return o; + + if (o === undefined) + return 'undefined'; + + if (o === null) + return 'null'; + + var cache = []; + var str = JSON.stringify(o, function(key, value) { + if (typeof value === 'object' && value !== null) { + if (cache.indexOf(value) !== -1) { + try { + return JSON.parse(JSON.stringify(value)); + } catch (error) { + return; + } + } + cache.push(value); + } + return value; + }); + cache = null; + return JSON.parse(str); + } +}; diff --git a/RVO35/flow_old/designer.json b/RVO35/flow_old/designer.json new file mode 100755 index 0000000..7b903bf --- /dev/null +++ b/RVO35/flow_old/designer.json @@ -0,0 +1,2846 @@ +{ + "tabs": [ + { + "name": "MAIN PUSH", + "linker": "main-push", + "id": "1612772287426", + "index": 0 + }, + { + "name": "CMD manager", + "linker": "cmd-manager", + "id": "1615551125555", + "index": 1 + }, + { + "name": "Devices", + "linker": "devices", + "id": "1611921777196", + "index": 2 + } + ], + "components": [ + { + "id": "1611951142547", + "component": "debug", + "tab": "1611921777196", + "name": "ERROR", + "x": 598, + "y": 60, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#DA4453", + "notes": "" + }, + { + "id": "1612776786008", + "component": "wsmqttpublish", + "tab": "1612772287426", + "name": "WS MQTT publish", + "x": 304.75, + "y": 237, + "connections": { + "0": [ + { + "index": "0", + "id": "1615551060773" + } + ], + "1": [ + { + "index": "0", + "id": "1618300858252" + }, + { + "index": "0", + "id": "1618558465485" + } + ], + "2": [ + { + "index": "0", + "id": "1618300863816" + }, + { + "index": "0", + "id": "1634303685503" + } + ], + "3": [ + { + "index": "0", + "id": "1731068754606" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Connected", + "color": "green" + }, + "options": { + "username": "", + "clientid": "", + "port": "1883", + "host": "" + }, + "color": "#888600", + "notes": "" + }, + { + "id": "1612778461252", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "tb-push", + "x": 86.75, + "y": 375, + "connections": { + "0": [ + { + "index": "0", + "id": "1612783322136" + }, + { + "index": "1", + "id": "1612776786008" + }, + { + "index": "0", + "id": "1731068754606" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1612783322136", + "component": "debug", + "tab": "1612772287426", + "name": "to TB", + "x": 306.75, + "y": 371, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615551060773", + "component": "debug", + "tab": "1612772287426", + "name": "errors from MQTT Broker", + "x": 650, + "y": 76, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#DA4453", + "notes": "" + }, + { + "id": "1615563373927", + "component": "debug", + "tab": "1615551125555", + "name": "Debug", + "x": 753, + "y": 150, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#DA4453", + "notes": "" + }, + { + "id": "1615566865233", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "tb-push", + "x": 761, + "y": 251, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1615798582262", + "component": "debug", + "tab": "1615551125555", + "name": "CMD_debug", + "x": 765, + "y": 350, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615802995322", + "component": "debug", + "tab": "1611921777196", + "name": "Debug", + "x": 595.8833312988281, + "y": 557.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Disabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": false + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615809128443", + "component": "debug", + "tab": "1611921777196", + "name": "tempToTb", + "x": 598.8833312988281, + "y": 654.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615809595184", + "component": "virtualwireout", + "tab": "1611921777196", + "name": "tb-push", + "x": 594.8833312988281, + "y": 350.25, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1616165795916", + "component": "httproute", + "tab": "1615551125555", + "name": "POST /terminal", + "x": 114, + "y": 546, + "connections": { + "0": [ + { + "index": "0", + "id": "1684060205000" + }, + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Listening", + "color": "green" + }, + "options": { + "timeout": 10, + "cachepolicy": 0, + "cacheexpire": "5 minutes", + "size": 5, + "url": "/terminal", + "method": "POST", + "name": "", + "flags": [ + "id:1616165795916", + "post", + 10000 + ], + "emptyresponse": false + }, + "color": "#5D9CEC", + "notes": "### Configuration\n\n- __POST /terminal__\n- flags: \n- maximum request data length: __5 kB__\n- empty response: __false__\n- cache policy: __no cache__\n- cache expire: __5 minutes__", + "cloning": false + }, + { + "id": "1616165824813", + "component": "httpresponse", + "tab": "1615551125555", + "name": "HTTP Response", + "x": 772, + "y": 443, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "json" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1617104731852", + "component": "debug", + "tab": "1615551125555", + "name": "DIDO_Debug", + "x": 669, + "y": 1040, + "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": "turnOff line", + "x": 88, + "y": 1158, + "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": 669, + "y": 1150, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1617284749681", + "component": "trigger", + "tab": "1615551125555", + "name": "update profile / node", + "x": 112, + "y": 215, + "connections": { + "0": [ + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "string", + "data": "profile_nodes" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1618235171399", + "component": "trigger", + "tab": "1615551125555", + "name": "tun tasks", + "x": 119, + "y": 280, + "connections": { + "0": [ + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "data": "run" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1618300858252", + "component": "debug", + "tab": "1612772287426", + "name": "wsmqtt-exit1", + "x": 650.8833312988281, + "y": 160, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1618300863816", + "component": "debug", + "tab": "1612772287426", + "name": "wsmqtt-exit2", + "x": 845.8833312988281, + "y": 320, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1618393583970", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "to-cmd-manager", + "x": 668.8833312988281, + "y": 1269, + "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": 119.88333129882812, + "y": 369, + "connections": { + "0": [ + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "platform-rpc-call", + "color": "gray" + }, + "options": { + "wirename": "platform-rpc-call" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1618393759854", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "cmd_to_dido", + "x": 93.88333129882812, + "y": 1007, + "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": 779.8833312988281, + "y": 552, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "cmd_to_dido", + "color": "gray" + }, + "options": { + "wirename": "cmd_to_dido" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1618558465485", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "platform-rpc-call", + "x": 649.8833312988281, + "y": 246, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "platform-rpc-call", + "color": "gray" + }, + "options": { + "wirename": "platform-rpc-call" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1618572059773", + "component": "trigger", + "tab": "1615551125555", + "name": "turnOn line", + "x": 89, + "y": 1085, + "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": 452.1091003417969, + "y": 341.05455017089844, + "connections": { + "0": [ + { + "index": "0", + "id": "1615563373927" + } + ], + "1": [ + { + "index": "0", + "id": "1615566865233" + }, + { + "index": "0", + "id": "1615798582262" + } + ], + "2": [ + { + "index": "0", + "id": "1616165824813" + } + ], + "3": [ + { + "index": "0", + "id": "1618393827655" + } + ], + "4": [ + { + "index": "0", + "id": "1635936391935" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1619605019281", + "component": "httproute", + "tab": "1615551125555", + "name": "GET db", + "x": 115, + "y": 651, + "connections": { + "0": [ + { + "index": "0", + "id": "1684060205000" + }, + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Listening", + "color": "green" + }, + "options": { + "timeout": 5, + "cachepolicy": 0, + "cacheexpire": "5 minutes", + "size": 5, + "url": "/db", + "method": "GET", + "name": "", + "flags": [ + "id:1619605019281", + "get", + 5000 + ] + }, + "color": "#5D9CEC", + "notes": "### Configuration\n\n- __GET /db__\n- flags: undefined\n- maximum request data length: __5 kB__\n- empty response: __undefined__\n- cache policy: __no cache__\n- cache expire: __5 minutes__", + "cloning": false + }, + { + "id": "1619784672383", + "component": "trigger", + "tab": "1615551125555", + "name": "turnOnAlarm", + "x": 85, + "y": 1231, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "data": "{command: \"turnOnAlarm\"}", + "datatype": "object" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1619784812964", + "component": "trigger", + "tab": "1615551125555", + "name": "turnOffAlarm", + "x": 84, + "y": 1304, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "data": "{command: \"turnOffAlarm\"}", + "datatype": "object" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1621340721628", + "component": "virtualwireout", + "tab": "1611921777196", + "name": "modbus_to_dido", + "x": 596, + "y": 462, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "modbus_to_dido", + "color": "gray" + }, + "options": { + "wirename": "modbus_to_dido" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1622640022885", + "component": "httproute", + "tab": "1615551125555", + "name": "POST /db_connector", + "x": 98, + "y": 1586, + "connections": { + "0": [ + { + "index": "0", + "id": "1622640073521" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Listening", + "color": "green" + }, + "options": { + "timeout": 5, + "cachepolicy": 0, + "cacheexpire": "5 minutes", + "size": 5, + "url": "/db_connector", + "method": "POST", + "flags": [ + "id:1622640022885", + "post", + 5000 + ] + }, + "color": "#5D9CEC", + "notes": "### Configuration\n\n- __POST /db_connector__\n- flags: \n- maximum request data length: __5 kB__\n- empty response: __undefined__\n- cache policy: __no cache__\n- cache expire: __5 minutes__", + "cloning": false + }, + { + "id": "1622640073521", + "component": "db_connector", + "tab": "1615551125555", + "name": "DbConnector", + "x": 372, + "y": 1572, + "connections": { + "1": [ + { + "index": "0", + "id": "1622641420685" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "edge": "undefined" + }, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1622641420685", + "component": "httpresponse", + "tab": "1615551125555", + "name": "HTTP Response", + "x": 596, + "y": 1586, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1634303504177", + "component": "monitormemory", + "tab": "1612772287426", + "name": "RAM", + "x": 69.88333129882812, + "y": 885.5, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465281992" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "850.32 MB / 985.68 MB", + "color": "gray" + }, + "options": { + "enabled": true, + "interval": 30000 + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1634303533779", + "component": "monitordisk", + "tab": "1612772287426", + "name": "disk", + "x": 70.88333129882812, + "y": 982.5, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465821120" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "5.78 GB / 7.26 GB", + "color": "gray" + }, + "options": { + "enabled": true, + "path": "/", + "interval": 30000 + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1634303595494", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "send-to-services", + "x": 51.883331298828125, + "y": 1400.5, + "connections": { + "0": [ + { + "index": "0", + "id": "1634463186563" + }, + { + "index": "1", + "id": "1634488120710" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1634303602169", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "send-to-services", + "x": 426.8833312988281, + "y": 878.5, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1634303685503", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "send-to-services", + "x": 650.8833312988281, + "y": 355.5, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1634303743260", + "component": "httprequest", + "tab": "1612772287426", + "name": "192.168.252.2:8004/sentmessage", + "reference": "", + "x": 480.8833312988281, + "y": 1334.7333374023438, + "connections": { + "0": [ + { + "index": "0", + "id": "1635327431236" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "stringify": "json", + "method": "POST", + "url": "http://192.168.252.2:8004/sentmessage" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1634463186563", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 280.75, + "y": 1446, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634464580289", + "component": "code", + "tab": "1612772287426", + "name": "Code", + "x": 253, + "y": 788, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465243324" + }, + { + "index": "0", + "id": "1634303602169" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "keepmessage": true, + "code": "let response = {};\nresponse.cpu = value.cpu;\nresponse.uptime = value.uptime;\n\nsend(0, response);", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1634465243324", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 428, + "y": 784, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634465281992", + "component": "code", + "tab": "1612772287426", + "name": "Code", + "x": 242, + "y": 884, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465338103" + }, + { + "index": "0", + "id": "1634303602169" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "keepmessage": true, + "code": "value.sender = \"ram\";\n//let total = value.total/1024/1024;\n//let free = value.free/1024/1024;\n//let used = value.used/1024/1024;\nlet response = {};\n//value.memory_total = (total).toFixed(0) + ' MB';\n//value.memory_free = (free).toFixed(0) + ' MB';\n//value.memory_used = (used).toFixed(0) + ' MB';\n\nresponse.memory_total = value.total;\nresponse.memory_free = value.free;\nresponse.memory_used = value.used;\n\nsend(0, response);", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1634465338103", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 429, + "y": 976, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634465821120", + "component": "code", + "tab": "1612772287426", + "name": "Code", + "x": 245, + "y": 978, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465892500" + }, + { + "index": "0", + "id": "1634303602169" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "keepmessage": true, + "code": "value.sender = \"hdd\";\n//let total = value.total/1024/1024;\n//let free = value.free/1024/1024;\n//let used = value.used/1024/1024;\nlet response = {};\n//value.hdd_total = (total).toFixed(0) + ' MB';\n//value.hdd_free = (free).toFixed(0) + ' MB';\n//value.used = (used).toFixed(0) + ' MB';\n\nresponse.hdd_total = value.total;\nresponse.hdd_free = value.free;\nresponse.hdd_used = value.used;\n\nsend(0, response);", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1634465892500", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 432, + "y": 1068, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634484067516", + "component": "debug", + "tab": "1612772287426", + "name": "Send info", + "x": 480, + "y": 1441, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634488120710", + "component": "infosender", + "tab": "1612772287426", + "name": "Info sender", + "x": 285, + "y": 1338, + "connections": { + "0": [ + { + "index": "0", + "id": "1634484067516" + }, + { + "index": "0", + "id": "1634303743260" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "edge": "undefined" + }, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1635327431236", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 795.8833312988281, + "y": 1329.5, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1635936391935", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "send-to-services", + "x": 778, + "y": 656, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1637069803394", + "component": "monitorconsumption", + "tab": "1612772287426", + "name": "CPU", + "x": 69, + "y": 791, + "connections": { + "0": [ + { + "index": "0", + "id": "1634464580289" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "0.8% / 90.87 MB", + "color": "gray" + }, + "options": { + "monitorfiles": true, + "monitorconnections": true, + "monitorsize": true, + "monitorconsumption": true, + "enabled": true, + "interval": 30000 + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1683664161036", + "component": "debug", + "tab": "1615551125555", + "name": "CMDtoDIDO", + "x": 392, + "y": 1012, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1683981346282", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "from-dido-controller", + "x": 113, + "y": 456, + "connections": { + "0": [ + { + "index": "0", + "id": "1684055037116" + }, + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "from-dido-controller", + "color": "gray" + }, + "options": { + "wirename": "from-dido-controller" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1684055037116", + "component": "debug", + "tab": "1615551125555", + "name": "from dido to cmd", + "x": 448, + "y": 519, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1684060205000", + "component": "debug", + "tab": "1615551125555", + "name": "HTTP routes", + "x": 447, + "y": 620, + "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": "MDBToDido", + "x": 598, + "y": 147, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1699963668903", + "component": "dido_controller", + "tab": "1615551125555", + "name": "DIDO_Controller", + "x": 397, + "y": 1131, + "connections": { + "0": [ + { + "index": "0", + "id": "1617104731852" + } + ], + "1": [ + { + "index": "0", + "id": "1617104731852" + }, + { + "index": "0", + "id": "1617115013095" + } + ], + "2": [ + { + "index": "0", + "id": "1618393583970" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "edge": "undefined" + }, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1699964678894", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "modbus_to_dido", + "x": 96, + "y": 924, + "connections": { + "0": [ + { + "index": "0", + "id": "1699963668903" + }, + { + "index": "0", + "id": "1699964793925" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "modbus_to_dido", + "color": "gray" + }, + "options": { + "wirename": "modbus_to_dido" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1699964793925", + "component": "debug", + "tab": "1615551125555", + "name": "modbusToDido", + "x": 388, + "y": 920, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1699965957410", + "component": "modbus_reader", + "tab": "1611921777196", + "name": "Modbus reader", + "x": 232, + "y": 175, + "connections": { + "0": [ + { + "index": "0", + "id": "1611951142547" + } + ], + "1": [ + { + "index": "0", + "id": "1621340721628" + }, + { + "index": "0", + "id": "1684179110403" + }, + { + "index": "0", + "id": "1717441414646" + } + ], + "2": [ + { + "index": "0", + "id": "1615809595184" + }, + { + "index": "0", + "id": "1714752862828" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1700411878636", + "component": "thermometer", + "tab": "1611921777196", + "name": "Thermometer", + "x": 234.75, + "y": 444, + "connections": { + "0": [ + { + "index": "0", + "id": "1615802995322" + } + ], + "1": [ + { + "index": "0", + "id": "1615809595184" + }, + { + "index": "0", + "id": "1615809128443" + } + ], + "2": [ + { + "index": "0", + "id": "1621340721628" + }, + { + "index": "0", + "id": "1732889185927" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#5CB36D", + "notes": "" + }, + { + "id": "1714752862828", + "component": "debug", + "tab": "1611921777196", + "name": "MDBToTb", + "x": 599, + "y": 257, + "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": 755.0833282470703, + "y": 209, + "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": 966.0833282470703, + "y": 152, + "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": 968.0833282470703, + "y": 268, + "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": 77.75, + "y": 1630, + "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": 296, + "y": 1671, + "connections": { + "0": [ + { + "index": "0", + "id": "1718016086212" + }, + { + "index": "0", + "id": "1718016073501" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Running", + "color": "gray" + }, + "options": { + "name": "rvo_senica_35_10.0.0.129", + "types": "[\"emergency\", \"critical\", \"error\", \"alert\"]", + "message_includes": "[\"is responding again\", \"Flow has been restarted\", \"Node db has changed\"]", + "tag_on_include": "[{\"user_id\":\"U072JE5JUQG\", \"includes\":[\"Electrometer\", \"Twilight sensor\"]}]", + "slack_channel": "C071KN2Q8SK" + }, + "color": "#30E193", + "notes": "" + }, + { + "id": "1718016073501", + "component": "httprequest", + "tab": "1612772287426", + "name": "http://192.168.252.2:8004/slack", + "x": 495, + "y": 1753, + "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": 832, + "y": 1664, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "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": 79, + "y": 1723, + "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": "" + }, + { + "id": "1729855334955", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "platform-rpc-call", + "x": 649.9333343505859, + "y": 541.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "platform-rpc-call", + "color": "gray" + }, + "options": { + "wirename": "platform-rpc-call" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1729855371093", + "component": "debug", + "tab": "1612772287426", + "name": "rpc cloud", + "x": 650.9333343505859, + "y": 451.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1731068658334", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 90.75, + "y": 250, + "connections": { + "0": [ + { + "index": "0", + "id": "1612776786008" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731068754606", + "component": "cloudmqttconnect", + "tab": "1612772287426", + "name": "MQTT client - to senica-prod01", + "x": 304.75, + "y": 474, + "connections": { + "1": [ + { + "index": "0", + "id": "1729855371093" + }, + { + "index": "0", + "id": "1729855334955" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Connected", + "color": "green" + }, + "options": { + "username": "", + "clientid": "", + "port": "2764", + "host": "192.168.252.2", + "topic": "u129" + }, + "color": "#888600", + "notes": "" + }, + { + "id": "1731069001548", + "component": "db_init", + "tab": "1612772287426", + "name": "DB Initialization", + "x": 91.75, + "y": 55.25, + "connections": { + "0": [ + { + "index": "0", + "id": "1731069033416" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#888600", + "notes": "" + }, + { + "id": "1731069033416", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "db-init", + "x": 343.75, + "y": 50.25, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069059135", + "component": "showdb", + "tab": "1612772287426", + "name": "Show db data", + "x": 1121.75, + "y": 814.25, + "connections": { + "0": [ + { + "index": "0", + "id": "1731069079243" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#888600", + "notes": "" + }, + { + "id": "1731069079243", + "component": "debug", + "tab": "1612772287426", + "name": "dbData", + "x": 1315.75, + "y": 853.25, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1731069116691", + "component": "trigger", + "tab": "1612772287426", + "name": "settings", + "x": 911.75, + "y": 710.75, + "connections": { + "0": [ + { + "index": "0", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069131637", + "component": "trigger", + "tab": "1612772287426", + "name": "relaysData", + "x": 832.75, + "y": 775.75, + "connections": { + "0": [ + { + "index": "1", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069137374", + "component": "trigger", + "tab": "1612772287426", + "name": "nodesData", + "x": 747.75, + "y": 840.75, + "connections": { + "0": [ + { + "index": "2", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069179846", + "component": "trigger", + "tab": "1612772287426", + "name": "pinsData", + "x": 803.75, + "y": 899.75, + "connections": { + "0": [ + { + "index": "3", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069192937", + "component": "trigger", + "tab": "1612772287426", + "name": "sample data", + "x": 858.75, + "y": 959.75, + "connections": { + "0": [ + { + "index": "4", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069264443", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 63.75, + "y": 1279, + "connections": { + "0": [ + { + "index": "0", + "id": "1634488120710" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069334626", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "db-init", + "x": 151.88333129882812, + "y": 148, + "connections": { + "0": [ + { + "index": "0", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069548145", + "component": "virtualwirein", + "tab": "1611921777196", + "name": "db-init", + "x": 46.75, + "y": 192, + "connections": { + "0": [ + { + "index": "0", + "id": "1699965957410" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069567152", + "component": "virtualwirein", + "tab": "1611921777196", + "name": "db-init", + "x": 44.75, + "y": 465, + "connections": { + "0": [ + { + "index": "0", + "id": "1700411878636" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731070156936", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "db-init", + "x": 89.88333129882812, + "y": 1381, + "connections": { + "0": [ + { + "index": "2", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731234189516", + "component": "trigger", + "tab": "1612772287426", + "name": "monitor.txt", + "x": 915.75, + "y": 1017.75, + "connections": { + "0": [ + { + "index": "5", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731234189551", + "component": "trigger", + "tab": "1612772287426", + "name": "err.txt", + "x": 966.75, + "y": 1080.75, + "connections": { + "0": [ + { + "index": "6", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1732700042559", + "component": "nodesdb_change_check", + "tab": "1612772287426", + "name": "Nodes DB change check", + "x": 263.8833312988281, + "y": 1993.2333984375, + "connections": { + "0": [ + { + "index": "0", + "id": "1732700071298" + }, + { + "index": "0", + "id": "1732700642917" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#888600", + "notes": "" + }, + { + "id": "1732700057052", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 84.75, + "y": 1994, + "connections": { + "0": [ + { + "index": "0", + "id": "1732700042559" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1732700071298", + "component": "debug", + "tab": "1612772287426", + "name": "nodesChange", + "x": 561.8833312988281, + "y": 2055.2333984375, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1732700642917", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "tb-push", + "x": 557.8833312988281, + "y": 1949, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1732889185927", + "component": "debug", + "tab": "1611921777196", + "name": "tempToDido", + "x": 594.8833312988281, + "y": 745, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1733574412965", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 86.75, + "y": 495, + "connections": { + "0": [ + { + "index": "1", + "id": "1731068754606" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + } + ], + "version": 615 +} \ No newline at end of file diff --git a/RVO35/flow_old/dido_controller.js b/RVO35/flow_old/dido_controller.js new file mode 100755 index 0000000..523d39b --- /dev/null +++ b/RVO35/flow_old/dido_controller.js @@ -0,0 +1,1473 @@ +exports.id = 'dido_controller'; +exports.title = 'DIDO_Controller'; +exports.version = '2.0.0'; +exports.group = 'Worksys'; +exports.color = '#2134B0'; +exports.input = 3; +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 + +state_of_main_switch - reportovať stav hlavného ističa : 0-> off 1-> on +rotary_switch_state - sem by sa mal reportovať stav vstupov manual a auto podľa nasledovnej logiky: Manual = 1 a Auto = 0 -> Manual, +Manual = 0 a Auto = 0 -> Off, Manual = 0 a Auto = 1 -> Automatic + +door_condition - 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 + +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 +*/ + +const { errLogger, logger, monitor } = require('./helper/logger'); +const SerialPort = require('serialport'); +const WebSocket = require('ws'); +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 +} + + +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 = {}; + let rsPortReceivedData = []; + + //to be able to get proper twilight values + let twilight_sensor_interval = 5;//minutes + let twilight_sensor = []; + const twilight_sensor_array = []; + let twilightError = false; + + monitor.info("DIDO_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 deviceStatus = { //key is device name: temperature,.... + "state_of_main_switch": "Off", //Hlavný istič (po novom druhy dverovy kontakt) + "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 + }; + + + function main() { + + GLOBALS = FLOW.GLOBALS; + SETTINGS = FLOW.GLOBALS.settings; + rvoTbName = SETTINGS.rvoTbName; + pinsData = GLOBALS.pinsData; + relaysData = GLOBALS.relaysData; + + 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"; + + 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, "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; + } + } + + //report RVO version relaysData[0].tbname; + let values = {}; + values["edge_fw_version"] = SETTINGS.edge_fw_version; + values["maintenance_mode"] = SETTINGS.maintenance_mode; + + sendTelemetry(values, rvoTbName); + + 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); + } + + + 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) { + if (!err) { + monitor.info(exports.title + "--->Digital in_out has been set (runSyncExec was sucessfull)"); + + turnAlarm("off"); + 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() { + + //to keep websocket opened, we send request every 150 seconds + let startRequests = null; + + console.log("handleWebSocket function called"); + ws = new WebSocket('ws:/0.0.0.0:1234/ws'); + + ws.onopen = function open() { + + instance.send(0, exports.title + " running"); + turnAlarm("off"); + + initialSetting(); + + setTimeout(function() { ws.send(JSON.stringify({ cmd: "all" })) }, 5000); + // we request dev info about neuron device from evok to keep websocket connection alive + // for some reason this request returns no data, but connection keeps alive + startRequests = setInterval(() => { + ws.send(JSON.stringify({ "cmd": "filter", "dev": ["neuron"] })); + }, 150000) + }; + + + // 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 = async 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; + + 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) => { + monitor.info('websocket error, reconnect') + instance.send(SEND_TO.debug, err.message); + clearInterval(startRequests); + ws = null; + setTimeout(handleWebSocket, 1000); + }) + + + ws.onclose = function() { + // connection closed, discard old websocket and create a new one in 5s + // stopRequests(); + monitor.info('websocket onclose, reconnect') + clearInterval(startRequests); + ws = null; + console.log("ws is null now, reconnecting..."); + setTimeout(handleWebSocket, 1000); + } + } + + 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 turnAlarm(onOrOff) { + let value = 0; + if (onOrOff == "on") value = 1; + + if (value == 1 && SETTINGS.maintenance_mode) return; + + alarmStatus = "OFF"; + if (value == 1) alarmStatus = "ON"; + + if (rsPort) { + let arr = [0x55]; + arr.push(13); + arr.push(0); + arr.push(value); + + rsPort.write(Buffer.from(arr), function(err) { + logger.debug(`sirena - ${onOrOff}`); + }); + } + else if (ws) { + let cmd = { "cmd": "set", "dev": "relay", "circuit": "1_01", "value": value }; + ws.send(JSON.stringify(cmd)); + logger.debug(`sirena - ${onOrOff}`); + } + } + + + 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") { + bits.push(0); + } + else bits.push(1); + + if (deviceStatus["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); + } + + + // turn line on or off + function turnLine(onOrOff, line, pin, force, info) { + //onOrOff => "on" or "off" + let value = 0; + if (onOrOff == "on") value = 1; + + if (force == undefined) force = false; + + if (line == 0) { + if (value == 1 && alarmStatus == "ON") turnAlarm("off"); + SETTINGS.maintenance_mode = value ? true : false; + + 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); + return; + } + + if (pin === undefined) pin = getPin(line); + + if (pin === undefined) { + errLogger.error("pin is undefined!", line); + return; + } + + if (!force) { + if (relaysData[line].contactor == value) { + instance.send(SEND_TO.debug, `line is already ${onOrOff} ` + line); + logger.debug(`turnLine: line is already ${onOrOff} `, 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(value); + + rsPort.write(Buffer.from(arr), function(err) { + if (err === undefined) { + monitor.info(`turnLine ${onOrOff} zapisal do rsPort-u`, line, pin, arr, info); + switchLogic(arr); + } + else { + monitor.info(`turnLine ${onOrOff} 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 }; + ws.send(JSON.stringify(cmd)); + } + + //if rvo is 24/7, it has just one switching profile point at 13:00. we do not want to send notification as it repeats every day. + //const d = new Date(); + //if(d.getHours() != 13) sendNotification("Dido_controller: ", SETTINGS.rvoTbName, "switching_profile_point_applied_to_line", { line: line, value: onOrOff }, "", SEND_TO.tb, instance); + } + + + // 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; + + // 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) { + const status = flowdata.data.status; + if (status == "NOK-twilight_sensor") { + deviceStatus["twilight_sensor"] = "NOK"; + } + else if (status == "NOK-em340" || status == "NOK-em111") { + deviceStatus["em"] = "NOK"; + } + else if (status == "NOK-thermometer") { + deviceStatus["temperature"] = "NOK"; + } + } + else if ("values" in flowdata.data) { + 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" + } + else if (values.hasOwnProperty("temperature")) { + deviceStatus["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"; + } + + sendTelemetry(values, rvoTbName); + } + + sendRvoStatus(); + }) + + + + + // we expect array as flowdata.data + instance.on("1", flowdata => { + + //console.log(flowdata.data); + + if (!flowdata.data instanceof Object) return; + + let obj = flowdata.data; + let line = obj.line; + 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"); + }) + + + function calculateStateCode() { + + 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") { + bits.push(0); + } + else { + bits.push(1); + } + + //Prevádzkový mód - Manual, Off, Automatic, maintenance_mode = true/false // DAVA 2 BITY + if (!SETTINGS.maintenance_mode) { + if (deviceStatus["rotary_switch_state"] == "Manual") { + bits.push(0); + bits.push(1); + } + + if (deviceStatus["rotary_switch_state"] == "Automatic") { + bits.push(0); + bits.push(0); + } + + if (deviceStatus["rotary_switch_state"] == "Off") { + bits.push(1); + bits.push(0); + } + } + else { + bits.push(1); + bits.push(1); + } + + //Dverový kontakt + if (deviceStatus["door_condition"] == "closed") { + bits.push(0); + } + else { + bits.push(1); + } + + //EM + if (deviceStatus["em"] == "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //Teplomer + if (deviceStatus["temperature"] == "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //Batéria + if (deviceStatus["battery"] == "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //Zdroj + if (deviceStatus["power_supply"] == "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //MN + if (deviceStatus["master_node"] == "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //výpadok napätia na fáze + if (deviceStatus["no_voltage"] == "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + if (deviceStatus["twilight_sensor"] == "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + // doplnime do 16 bitov (2 byty) + for (let i = bits.length; i < 16; i++) { + bits.push(0); + } + + // console.log("calculateStateCode - deviceStatus", deviceStatus); + // 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; + } + + + async function sendRvoStatus() { + + if (SETTINGS === undefined) return; + SETTINGS.masterNodeIsResponding ? deviceStatus["master_node"] = "OK" : deviceStatus["master_node"] = "NOK"; + + 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() { + + // 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 + //set RVO state + let status = "OK"; + + for (const [key, value] of Object.entries(deviceStatus)) { + if (["em", "twilight_sensor", "temperature", "master_node"].includes(key) && value == "NOK") status = "NOK"; + } + + if (status == "OK") { + let pinIndexes = [1, 4, 6]; + if (controller_type == 'unipi') pinIndexes = ['input1_01', 'input1_04', 'input1_05']; + + for (const pinIndex of pinIndexes) { + if (previousValues[pinIndex] === 0) { + if ((pinIndex === 6 || pinIndex === 'input1_01' || pinIndex === 'input1_05') && SETTINGS.maintenance_mode) continue; + status = "NOK"; + break; + } + } + } + + // battery status. If value is 1 - battery is NOK + if (previousValues[5] === 1) status = "NOK"; + if (SETTINGS.no_voltage.size > 0) status = "NOK"; + + // console.log("rvo status",status) + return status; + } + + + // we pass array to function in case of rsPort ==> switchLogic([55,3,0,1]) ==> [[55,3,0,1]] + // we pass two values in case of websocket ==> switchLogic("relay1_03",1) ==> ["relay1_03",1] + const switchLogic = (...args) => { + + let values = {}; + let pinIndex, newPinValue, twilight; + + //data from rsPort + if (args.length == 1) { + pinIndex = args[0][1] + 1; + if (pinIndex === 17) pinIndex--; + newPinValue = args[0][3]; + twilight = args[0][2]; + } + //data from websocket + else { + pinIndex = args[0]; + newPinValue = args[1]; + } + + 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; + + //default value + let value = "On"; + if (newPinValue === 0) value = "Off"; + + //Prevádzkový mód + 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"; + + deviceStatus["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, "power_supply_has_disconnected_input", {}, "", SEND_TO.tb, instance, "power_supply"); + + deviceStatus["power_supply"] = "NOK"; + } + else if (newPinValue === 1 && newPinValue !== previousValues[pinIndex]) { + sendNotification("switchLogic", rvoTbName, "power_supply_works_correctly", {}, "", SEND_TO.tb, instance, "power_supply"); + + deviceStatus["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"); + + deviceStatus["battery"] = "NOK"; + } + else if (newPinValue === 0 && newPinValue !== previousValues[pinIndex]) { + sendNotification("switchLogic", rvoTbName, "battery_level_is_ok", {}, "", SEND_TO.tb, instance, "battery_level"); + + deviceStatus["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' + else if (type == "door_condition" || type === "state_of_main_switch") { + newPinValue === 0 ? value = "open" : value = "closed"; + + 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, "door_opened_without_permission", {}, "", SEND_TO.tb, instance, "rvo_door"); + + // 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 (value === "closed") { + if (alarmStatus == "ON") turnAlarm("off"); + sendNotification("switchLogic", rvoTbName, "door_closed", {}, "", SEND_TO.tb, instance, "rvo_door"); + } + + deviceStatus[type] = value; + } + + //lux sensor + else if (type == "twilight_sensor") { + //! TODO - to show nok status, if lux value is not changing more then 10 times. + //Daylight is far more than 1000. So most of the day, when it is sunshine comes just value 1000. But lux sensor is not NOK. + //This is not the case in LM. If value from LM is the same 10x, there is 99% possibility, that sensor is NOK. + value = newPinValue; + + if (controller_type === 'lm') { + value = parseFloat(newPinValue + (256 * twilight)); + + 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 && !twilightError) { + twilightError = true; + let value = twilight_sensor_array.shift(); + + newPinValue = 0; + } + else if (set.size !== 1 && twilightError) { + //sendNotification("switchLogic", rvoTbName, 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) { + 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); + } + } + + 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); + } + + deviceStatus["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) + // { + // let time = 0; + // if(value) time = 1000 * 10;//10 sekund + + // let dataChanged = false; + // if(relaysData[line].contactor != newPinValue) dataChanged = true; + // relaysData[line].contactor = newPinValue; // 0,1 + + // //ak bola predchadzajuci stav off a novy stav je on, budu sa nastavovat nespracovane node profiles + // //a budu sa odosielat commandy, tie vsak mozu zlyhat, a preto potrebujeme ich spusti trochu neskor + // setTimeout(function(){ + // instance.send(SEND_TO.cmd_manager, {sender: "dido_controller", cmd: "reload_relays", line: line, time: time, value: value, dataChanged: dataChanged}); + // }, time); + + // reportLineStatus(line); + // } + // else + // { + // errLogger.error("modify table relays failed", err); + // } + + // }); + // }); + } + + 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 }); + + //mame iba 3 istice. vyreportujeme a ohandlujeme liniu na tom istom istici ako paralelna linia (napr linia 1, paralelna s nou je linia 4, key je string "4") + // ak je 7 linii, na 1 istici je linia 1,4,7 + + if (line == 1) { + + const lineOnSameBraker = [4, 7]; + + for (var i = 0; i < lineOnSameBraker.length; i++) { + if (!relaysData.hasOwnProperty(lineOnSameBraker[i])) continue; + + 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; + reportLineStatus(lineOnSameBraker[i]); + + values[type] = value; + const tbname = relaysData[lineOnSameBraker[i]].tbname; + sendTelemetry(values, tbname); + + delete values[type]; + } + + } + else { + const lineOnSameBraker = line + 3 + ""; + + if (relaysData.hasOwnProperty(lineOnSameBraker)) { + 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; + reportLineStatus(line + 3); + + values[type] = value; + const tbname = relaysData[lineOnSameBraker].tbname; + sendTelemetry(values, tbname); + + delete values[type]; + } + } + + } + + if (value == "Off") values["status"] = "NOK"; + deviceStatus["state_of_breaker"][line] = value; + + reportLineStatus(line); + } + else return; + + values[type] = value; + + if (type == "rotary_switch_state") { + if (SETTINGS.maintenance_mode) value = "maintenance"; + value = value.toLowerCase(); + values["power_mode"] = value; + } + + if (newPinValue != previousValues[pinIndex]) previousValues[pinIndex] = newPinValue; + if (Object.keys(values).length > 0 && tbname) sendTelemetry(values, tbname); + } + + + function sendTelemetry(values, tbname, date = Date.now()) { + let dataToTb = { + [tbname]: [ + { + "ts": date, + "values": values + } + ] + }; + + tbHandler.sendToTb(dataToTb, instance); + } + + + function isObject(item) { + return (typeof item === "object" && !Array.isArray(item) && item !== null); + } + +} //end of 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 +// *|input1_01|state_of_main_switch|0|........... +// *|input1_02|rotary_switch_state|0|........... +// *|input1_03|rotary_switch_state|0|........... +// *|intut1_04|power_supply|0|........... +// *|input1_05|door_condition|0|........... +// *|input1_06|state_of_breaker|1|........... +// *|input1_07|state_of_breaker|2|........... +// *|input1_08|state_of_breaker|3|........... +// *|relay1_02|state_of_contactor|1|........... +// *|relay1_03|state_of_contactor|2|........... +// *|relay1_04|state_of_contactor|3|........... +// *|287D8776E0013CE9|temperature|0|........... + + +//! pins_data --> from UNIPI +// { +// 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 } +// } + +//! relays_data +// { +// '0': { +// line: 0, +// tbname: 'KjbN4q7JPZmexgdnz2yKQ98YAWwO0Q3BMX6ERLoV', +// contactor: 1, +// profile: '' +// }, +// '1': { +// line: 1, +// tbname: 'RMgnK93rkoAazbqdQ4yBG95Z1YXGx6pmwBeVEP2O', +// contactor: 0, +// profile: '{"intervals":[{"value":0,"end_time":"20:00","start_time":"13:00"},{"value":1,"end_time":"10:00","start_time":"20:00"},{"value":0,"end_time":"10:20","start_time":"10:00"},{"value":1,"end_time":"10:40","start_time":"10:20"},{"value":0,"end_time":"11:00","start_time":"10:40"},{"value":1,"end_time":"11:30","start_time":"11:00"},{"value":0,"end_time":"11:50","start_time":"11:30"},{"value":1,"end_time":"13:00","start_time":"11:50"}],"astro_clock":false,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' +// }, +// '2': { +// line: 2, +// tbname: 'dlE1VQjYrNx9gZRmb38gG08oLBO4qaAk2M6JPnG7', +// contactor: 0, +// profile: '{"intervals":[{"value":0,"end_time":"20:00","start_time":"13:00"},{"value":1,"end_time":"10:00","start_time":"20:00"},{"value":0,"end_time":"10:20","start_time":"10:00"},{"value":1,"end_time":"10:40","start_time":"10:20"},{"value":0,"end_time":"11:00","start_time":"10:40"},{"value":1,"end_time":"11:30","start_time":"11:00"},{"value":0,"end_time":"11:50","start_time":"11:30"},{"value":1,"end_time":"13:00","start_time":"11:50"}],"astro_clock":false,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' +// }, +// '3': { +// line: 3, +// tbname: 'vnmG4kJxaXWNBgMQq0D7Aj5e9oZzOAlr6LdR3w2V', +// contactor: 0, +// profile: '{"intervals":[{"value":0,"end_time":"20:30","start_time":"13:00"},{"value":1,"end_time":"00:10","start_time":"20:30"},{"value":0,"end_time":"13:00","start_time":"05:40"},{"value":1,"end_time":"05:40","start_time":"00:10"}],"astro_clock":true,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' +// } +// } + + + + + +// { +// "jbN4q7JPZmexgdnz2yKbWGDYAWwO0Q3BMX6ERLoV": [ +// { +// "ts": 1700409326353, +// "values": { +// "_event": { +// "type": "notice", +// "status": "new", +// "source": { +// "func": "rsPort.open()", +// "component": "1700343402190", +// "component_name": "DIDO_Controller", +// "edge": "jbN4q7JPZmexgdnz2yKbWGDYAWwO0Q3BMX6ERLoV" +// }, +// "message": "al_shariff_10.0.0.38: FLOW has been started ", +// "message_data": "" +// } +// } +// } +// ] +// } diff --git a/RVO35/flow_old/helper/DataToTbHandler.js b/RVO35/flow_old/helper/DataToTbHandler.js new file mode 100755 index 0000000..7bd93bd --- /dev/null +++ b/RVO35/flow_old/helper/DataToTbHandler.js @@ -0,0 +1,156 @@ +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; + + this.sender = ""; + + // if attribute change difference is less than limit value, we do not send to tb. + this.attributeChangeLimit = { + temperature: 0.5, + Phase_1_voltage: 2, + Phase_2_voltage: 2, + Phase_3_voltage: 2, + Phase_1_current: 0.1, + Phase_2_current: 0.1, + Phase_3_current: 0.1, + Phase_1_power: 2, + Phase_2_power: 2, + Phase_3_power: 2, + total_power: 2, + Phase_1_pow_factor: 0.1, + Phase_2_pow_factor: 0.1, + Phase_3_pow_factor: 0.1, + power_factor: 0.1, + lifetime: 0.5, + voltage: 2, + power: 2, + frequency: 3, + energy: 0.1, + current: 2, + inclination_x: 10, + inclination_y: 10, + inclination_z: 10 + }; + + } + + dump() { + console.log("----------------------------"); + console.log("previousValues", this.previousValues); + console.log("----------------------------"); + } + + setSender(sender) { + this.sender = sender; + } + + isEmptyObject(obj) { + for (var _ in obj) { + return false; + } + return true; + } + + sendToTb(dataToTb, instance) { + + let keys = Object.keys(dataToTb); + + if (keys.length == 0) { + if (this.debug) console.log("sendToTb received empty object", dataToTb); + return; + } + + let tbname = keys[0]; + let ts; + + let arrayOfValues = dataToTb[tbname]; + let arrayOfValuesToSend = []; + + for (let i = 0; i < arrayOfValues.length; i++) { + ts = arrayOfValues[i].ts; + let values = this.prepareValuesForTb(tbname, ts, arrayOfValues[i].values); + + if (!this.isEmptyObject(values)) { + arrayOfValuesToSend.push({ ts: ts, values: values }); + } + } + + if (arrayOfValuesToSend.length == 0) { + //if(this.debug) console.log("data not sent - empty array"); + return; + } + + this.messageCounter++; + + let dataToTbModified = { + [tbname]: arrayOfValuesToSend + } + + //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); + instance.send(this.index, dataToTbModified); + } + + getDiffTimestamp(key) { + //TODO set different value for given key!!! + //if(key == "status") this.timeToHoldTbValue = 2*60*60;//2h + return this.timeToHoldTbValue * 1000; + } + + prepareValuesForTb(tbname, timestamp, values) { + + let keys = Object.keys(values); + if (!this.previousValues.hasOwnProperty(tbname)) { + this.previousValues[tbname] = {}; + } + + //if(this.debug) console.log("prepareValuesForTb", tbname, timestamp, values); + + for (let i = 0; i < keys.length; i++) { + let key = keys[i]; + let value = values[key]; + + if (!this.previousValues[tbname].hasOwnProperty(key)) { + this.previousValues[tbname][key] = { ts: timestamp, value: value }; + continue; + } + + // attributeData ==> voltage: {ts:333333, value:5} + let attributeData = this.previousValues[tbname][key]; + let attributeToChange = false; + if (key in this.attributeChangeLimit) attributeToChange = true; + let limit = this.attributeChangeLimit[key]; + + if (attributeData.value === value || attributeToChange && Math.abs(attributeData.value - value) < limit) { + let diff = timestamp - attributeData.ts; + let timestampDiffToRemoveKey = this.getDiffTimestamp(key); + if (diff > timestampDiffToRemoveKey) { + attributeData.ts = Date.now(); + //if(this.debug) console.log(this.sender + ": update ts for key", key, "diff is", diff, "messageCounter", this.messageCounter); + } + else { + delete values[key]; + //if(this.debug) console.log(this.sender + ": delete key", key, "diff is", diff, "messageCounter", this.messageCounter, timestampDiffToRemoveKey); + } + } + else { + attributeData.value = value; + attributeData.ts = timestamp; + } + + } + + return values; + } +} + +module.exports = DataToTbHandler; + diff --git a/RVO35/flow_old/helper/ErrorToServiceHandler.js b/RVO35/flow_old/helper/ErrorToServiceHandler.js new file mode 100755 index 0000000..110ea8b --- /dev/null +++ b/RVO35/flow_old/helper/ErrorToServiceHandler.js @@ -0,0 +1,126 @@ +const { MD5 } = require('./md5.js'); +const { networkInterfaces } = require('os'); + +class ErrorToServiceHandler +{ + constructor() { + this.previousValues = {}; + + this.projects_id = undefined; + + const nets = networkInterfaces(); + this.ipAddresses = Object.create(null); // Or just '{}', an empty object + + for (const name of Object.keys(nets)) { + for (const net of nets[name]) { + // Skip over non-IPv4 and internal (i.e. 127.0.0.1) addresses + if (net.family === 'IPv4' && !net.internal) { + if (!this.ipAddresses[name]) { + this.ipAddresses[name] = []; + } + this.ipAddresses[name].push(net.address); + } + } + } + + //console.log(this.ipAddresses); + + } + + setProjectsId(projects_id) + { + this.projects_id = projects_id; + } + + processMessage(message, seconds, message_type) + { + if(message_type == undefined) message_type = "error_message"; + if(Array.isArray(message)) message = message.join(', '); + + let key = MD5(message); + let timestamp = new Date().getTime(); + + //keep in memory - default value is 1h + if (seconds === undefined) seconds = 60*60; + + if(!this.previousValues.hasOwnProperty(key)) + { + this.previousValues[key] = {ts: timestamp, duration: seconds}; + } + + let diff = (timestamp - this.previousValues[key].ts); + if(diff < this.previousValues[key].duration*1000) return false; + + this.previousValues[key].ts = timestamp; + + return true; + } + + sendMessageToService(message, seconds, message_type) + { + + let f = this.processMessage(message, seconds, message_type); + if(!f) return; + + /* + //------------- + if(message_type == undefined) message_type = "error_message"; + if(Array.isArray(message)) message = message.join(', '); + + let key = MD5(message); + let timestamp = new Date().getTime(); + + //keep in memory + if (seconds === undefined) seconds = 60*60; + + if(!this.previousValues.hasOwnProperty(key)) + { + this.previousValues[key] = {ts: timestamp, duration: seconds}; + } + + let diff = (timestamp - this.previousValues[key].ts); + if(diff < this.previousValues[key].duration*1000) return; + + this.previousValues[key].ts = timestamp; + */ + + //------------------------- + + //send to service + + let dataToInfoSender = {id: this.projects_id}; + + //js_error || error_message + dataToInfoSender[message_type] = message; + dataToInfoSender.ipAddresses = this.ipAddresses; + + 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) + { + console.log("this.projects_id is undefined"); + return; + } + */ + + RESTBuilder.make(function(builder) { + builder.method('POST'); + builder.post(dataToInfoSender); + builder.url('http://192.168.252.2:8004/sentmessage'); + + builder.callback(function(err, response, output) { + console.log("process.on error send", err, response, output, dataToInfoSender); + }); + }); + + + } +} + +module.exports = ErrorToServiceHandler; \ No newline at end of file diff --git a/RVO35/flow_old/helper/db_helper.js b/RVO35/flow_old/helper/db_helper.js new file mode 100755 index 0000000..40e796c --- /dev/null +++ b/RVO35/flow_old/helper/db_helper.js @@ -0,0 +1,44 @@ +function promisifyBuilder(builder) +{ + return new Promise((resolve, reject) => { + + try{ + + builder.callback(function(err, response) { + + if(err != null) reject(err); + resolve(response); + }); + + } catch (error) { + reject(error); + } + }) +} + +function makeMapFromDbResult(response, ...keys) +{ + let s = "-"; + let data = {}; + + for(let i = 0; i < response.length; i++) + { + let record = response[i]; + + let k = []; + for(let j = 0; j < keys.length; j++) + { + k.push( record[keys[j]] ); + } + + let key = k.join(s); + data[ key ] = record; + } + + return data; +} + +module.exports = { + promisifyBuilder, + makeMapFromDbResult + } \ No newline at end of file diff --git a/RVO35/flow_old/helper/logger.js b/RVO35/flow_old/helper/logger.js new file mode 100755 index 0000000..2585639 --- /dev/null +++ b/RVO35/flow_old/helper/logger.js @@ -0,0 +1,30 @@ +//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/RVO35/flow_old/helper/md5.js b/RVO35/flow_old/helper/md5.js new file mode 100755 index 0000000..d3b0480 --- /dev/null +++ b/RVO35/flow_old/helper/md5.js @@ -0,0 +1,5 @@ +function MD5(d){var r = M(V(Y(X(d),8*d.length)));return r.toLowerCase()};function M(d){for(var _,m="0123456789ABCDEF",f="",r=0;r>>4&15)+m.charAt(15&_);return f}function X(d){for(var _=Array(d.length>>2),m=0;m<_.length;m++)_[m]=0;for(m=0;m<8*d.length;m+=8)_[m>>5]|=(255&d.charCodeAt(m/8))<>5]>>>m%32&255);return _}function Y(d,_){d[_>>5]|=128<<_%32,d[14+(_+64>>>9<<4)]=_;for(var m=1732584193,f=-271733879,r=-1732584194,i=271733878,n=0;n>16)+(_>>16)+(m>>16)<<16|65535&m}function bit_rol(d,_){return d<<_|d>>>32-_} + +module.exports = { + MD5 +} \ No newline at end of file diff --git a/RVO35/flow_old/helper/notification_reporter.js b/RVO35/flow_old/helper/notification_reporter.js new file mode 100755 index 0000000..61c0aef --- /dev/null +++ b/RVO35/flow_old/helper/notification_reporter.js @@ -0,0 +1,131 @@ +//key is device, value = str +let sentValues= {}; +let notificationsData = null; + +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 +}; + +function getKey(map, val) { + return Object.keys(map).findItem(key => map[key] === val); +} + +//https://stackoverflow.com/questions/41117799/string-interpolation-on-variable +var template = (tpl, args) => tpl.replace(/\${(\w+)}/g, (_, v) => args[v]); + + +function initNotification() { + notificationsData = FLOW.GLOBALS.notificationsData; +} + +function sendNotification(func, device, key, params, extra, tb_output, instance, saveKey) { + + // return; + + let storeToSendValues = true; + if(saveKey == undefined) storeToSendValues = false; + + let lang = FLOW.GLOBALS.settings.language; + if(lang != "en" || lang != "sk") lang = "en"; + + let tpl = key; + let weight = ""; + + if(notificationsData[key]) + { + weight = notificationsData[key].weight; + weight = weight.toLowerCase(); + + tpl = notificationsData[key][lang]; + tpl = template(tpl, params); + } + else + { + //console.error("sendNotification: Notifications: undefined key", key, func, notificationsData); + console.error("sendNotification: Notifications: undefined key", key, func ); + return false; + } + + //detect invalid err weight + if(getKey(ERRWEIGHT, weight) == undefined) + { + console.error("sendNotification: Notifications: undefined weight", weight, key, func); + return false; + } + + if(sentValues.hasOwnProperty(saveKey)) + { + if(sentValues[saveKey] == tpl) + { + return false; + } + } + + if(sentValues[saveKey] == undefined) + { + if(storeToSendValues) + { + //do not send - flow is was started + sentValues[saveKey] = tpl; + return false; + } + } + + if(saveKey == "rvo_door") + { + //console.log("******", saveKey, sentValues[saveKey], tpl); + } + + if(storeToSendValues) sentValues[saveKey] = tpl; + + let str = FLOW.GLOBALS.settings.rvo_name; + if(str != "") str = str + ": "; + str = str + tpl; + + 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 + + return true; + +} + +module.exports = { + sendNotification, + ERRWEIGHT, + initNotification +} diff --git a/RVO35/flow_old/helper/register.js b/RVO35/flow_old/helper/register.js new file mode 100755 index 0000000..fc1d008 --- /dev/null +++ b/RVO35/flow_old/helper/register.js @@ -0,0 +1,144 @@ +/* +0 - cislo registra / prikaz +1 - recepient - 0 = master, 1 = slave (slave je automaticky group a broadcast) +2 - r/rw - read/write +3- register name - nazov registra / prikazu (len pre info - zobrazenie v aplikacii) + +4,5,6,7, - jednotlive byte-y - nazov byte-u +4-7 - RES. a prazdny string "" sa nezobrazia!!! +*/ + +//124 zaznamov +const registers = [ + ["0","1","R","Status","","",""], + ["1","1","RW","Dimming","R-Channel ","G-Channel","B-Channel ","W - Channel"], + ["2","1","R","Device types","","",".",""], + ["3","1","RW","Group addresses 1-4","Groups Add. 4","Groups Add. 3","Groups Add. 2","Groups Add. 1"], + ["4","1","RW","Group addresses 5-8","Groups Add. 8","Groups Add. 7","Groups Add. 6","Groups Add. 5"], + ["5","1","RW","Serial number (MAC)","","","",""], + ["6","1","RW","Time of dusk","HH","MM","SS","EXTRA"], + ["7","1","RW","Time of dawn","HH","MM","SS","EXTRA"], + ["8","1","RW","Time Schedule settings","TBD","TBD","Movement sensor","Time Schedule"], + ["9","1","RW","TS1 Time point 1","HH","MM","SS","Ext. Device"], + ["10","1","RW","TS1 Time point 1 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["11","1","RW","TS1 Time point 2","HH","MM","SS","Ext. Device"], + ["12","1","RW","TS1 Time point 2 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["13","1","RW","TS1 Time point 3","HH","MM","SS","Ext. Device"], + ["14","1","RW","TS1 Time point 3 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["15","1","RW","TS1 Time point 4","HH","MM","SS","Ext. Device"], + ["16","1","RW","TS1 Time point 4 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["17","1","RW","TS1 Time point 5","HH","MM","SS","Ext. Device"], + ["18","1","RW","TS1 Time point 5 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["19","1","RW","TS1 Time point 6","HH","MM","SS","Ext. Device"], + ["20","1","RW","TS1 Time point 6 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["21","1","RW","TS1 Time point 7","HH","MM","SS","Ext. Device"], + ["22","1","RW","TS1 Time point 7 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["23","1","RW","TS1 Time point 8","HH","MM","SS","Ext. Device"], + ["24","1","RW","TS1 Time point 8 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["25","1","RW","TS1 Time point 9","HH","MM","SS","Ext. Device"], + ["26","1","RW","TS1 Time point 9 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["27","1","RW","TS1 Time point 10","HH","MM","SS","Ext. Device"], + ["28","1","RW","TS1 Time point 10 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["29","1","RW","TS1 Time point 11","HH","MM","SS","Ext. Device"], + ["30","1","RW","TS1 Time point 11 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["31","1","RW","TS1 Time point 12","HH","MM","SS","Ext. Device"], + ["32","1","RW","TS1 Time point 12 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["33","1","RW","TS1 Time point 13","HH","MM","SS","Ext. Device"], + ["34","1","RW","TS1 Time point 13 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["35","1","RW","TS1 Time point 14","HH","MM","SS","Ext. Device"], + ["36","1","RW","TS1 Time point 14 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["37","1","RW","TS1 Time point 15","HH","MM","SS","Ext. Device"], + ["38","1","RW","TS1 Time point 15 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["39","1","RW","TS1 Time point 16","HH","MM","SS","Ext. Device"], + ["40","1","RW","TS1 Time point 16 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["41","1","RW","TS2 Time point 1","HH","MM","SS","Ext. Device"], + ["42","1","RW","TS2 Time point 1 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["43","1","RW","TS2 Time point 2","HH","MM","SS","Ext. Device"], + ["44","1","RW","TS2 Time point 2 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["45","1","RW","TS2 Time point 3","HH","MM","SS","Ext. Device"], + ["46","1","RW","TS2 Time point 3 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["47","1","RW","TS2 Time point 4","HH","MM","SS","Ext. Device"], + ["48","1","RW","TS2 Time point 4 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["49","1","RW","TS2 Time point 5","HH","MM","SS","Ext. Device"], + ["50","1","RW","TS2 Time point 5 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["51","1","RW","TS2 Time point 6","HH","MM","SS","Ext. Device"], + ["52","1","RW","TS2 Time point 6 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["53","1","RW","TS2 Time point 7","HH","MM","SS","Ext. Device"], + ["54","1","RW","TS2 Time point 7 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["55","1","RW","TS2 Time point 8","HH","MM","SS","Ext. Device"], + ["56","1","RW","TS2 Time point 8 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["57","1","RW","TS2 Time point 9","HH","MM","SS","Ext. Device"], + ["58","1","RW","TS2 Time point 9 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["59","1","RW","TS2 Time point 10","HH","MM","SS","Ext. Device"], + ["60","1","RW","TS2 Time point 10 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["61","1","RW","TS2 Time point 11","HH","MM","SS","Ext. Device"], + ["62","1","RW","TS2 Time point 11 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["63","1","RW","TS2 Time point 12","HH","MM","SS","Ext. Device"], + ["64","1","RW","TS2 Time point 12 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["65","1","RW","TS2 Time point 13","HH","MM","SS","Ext. Device"], + ["66","1","RW","TS2 Time point 13 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["67","1","RW","TS2 Time point 14","HH","MM","SS","Ext. Device"], + ["68","1","RW","TS2 Time point 14 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["69","1","RW","TS2 Time point 15","HH","MM","SS","Ext. Device"], + ["70","1","RW","TS2 Time point 15 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["71","1","RW","TS2 Time point 16","HH","MM","SS","Ext. Device"], + ["72","1","RW","TS2 Time point 16 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["73","1","RW","Power meter status","TBD","","",""], + ["74","1","R","Input Voltage","","","",""], + ["75","1","R","Input Current","","","",""], + ["76","1","R","Input Power","","","",""], + ["77","1","R","Cos phi","","","",""], + ["78","1","R","Frequency","","","",""], + ["79","1","RW","Energy","","","",""], + ["80","1","RW","Lifetime","","","",""], + ["81","1","RW","Power on cycles (input)","","","",""], + ["82","1","RW","Power on cycles (relay)","","","",""], + ["83","1","R","Time since last power on","","","",""], + ["84","1","R","Accelerometer data","","","",""], + ["85","1","RW","GPS latitude","pos/neg","deg","min ","sec"], + ["86","1","RW","GPS longitude","pos/neg","deg","min ","sec"], + ["87","1","RW","Actual time","HH","MM","SS","RES."], + ["88","1","RW","Actual date","Day of week","Day","Month","Year"], + ["89","1","R","Production data 1","","","",""], + ["90","1","R","Production data 2","","","",""], + ["91","1","RW","Network ID","NID3","NID2","NID1","NID0"], + ["95","1","RW","Actual Lux level from cabinet","RES.","RES.","HB","LB"], + ["96","1","RW","Threshold lux level","Dusk HB","Dusk LB","Dawn HB","Dawn LB"], + ["97","1","RW","Adjust period","Dusk HB","Dusk LB","Dawn HB","Dawn LB"], + ["98","1","RW","Offset","RES.","RES.","Dusk","Dawn"], + ["99","1","RW","CCT min/max range","max-H","max-L","min-H","min-L"], + ["100","1","RW","DALI interface","Cmd ID","Add","Cmd","Resp"], + ["101","1","RW","Module FW ver","v1","v2","v3","v4"], + ["102","1","RW","Module MAC-H","unused","unused","M1","M2"], + ["103","1","RW","Module MAC-L","M3","M4","M5","M6"], + ["122","1","R","FW update status/control register","Byte3","Byte2","Byte1","Byte0"], + ["123","1","R","FW update - data index","Byte3","Byte2","Byte1","Byte0"], + ["124","1","R","FW update - data","Byte3","Byte2","Byte1","Byte0"], + ["0","0","R","Status","","","",""], + ["1","0","RW","Control register","RES.","RES.","RES.","init mode enable"], + ["2","0","R","Device types","","","",""], + ["3","0","R","Serial number (MAC)","","","",""], + ["4","0","R","Production data 1","","","",""], + ["5","0","R","Production data 2","","","",""], + ["6","0","RW","Network ID","NID3","NID2","NID1","NID0"], + ["7","0","RW","RS232 settings","param.","param.","Baudrate H","Baudrate L"], + ["8","0","R","Accelerometer data","","","",""], + ["9","0","RW","Module FW ver","v1","v2","v3","v4"], + ["10","0","RW","Module MAC-H","unused","unused","M1","M2"], + ["11","0","RW","Module MAC-L","M3","M4","M5","M6"], + ["32","0","RW","FW update status/control register","Byte3","Byte2","Byte1","Byte0"], + ["33","0","RW","FW update - data index","Byte3","Byte2","Byte1","Byte0"], + ["34","0","RW","FW update - data","Byte3","Byte2","Byte1","Byte0"], + ["125","0","RW","Debug Register","Byte3","Byte2","Byte1","Byte0"], + ["126","0","RW","Network Control Register","Byte3","Byte2","Byte1","Byte0"], + ["127","0","R","Network Status Register","Byte3","Byte2","Byte1","Byte0"], + ["128","0","RW","Node XX Serial Number Register","SER3","SER2","SER1","SER0"], + ["256","0","R","Node XX Network Status Register","","","",""] +]; + +let register = {}; + +module.exports = { + registers, + register +} \ No newline at end of file diff --git a/RVO35/flow_old/helper/serialport_helper.js b/RVO35/flow_old/helper/serialport_helper.js new file mode 100755 index 0000000..8efa6af --- /dev/null +++ b/RVO35/flow_old/helper/serialport_helper.js @@ -0,0 +1,100 @@ +const { exec } = require('child_process'); + +function openPort(port){ + return new Promise((resolve, reject) => { + + var callbackError = function(err) { + port.removeListener('error', callbackError); + port.removeListener('open', callbackError); + + reject(err.message); + }; + + var callbackOpen = function(data) { + port.removeListener('error', callbackError); + port.removeListener('open', callbackOpen); + + resolve("port open: ok"); + }; + + port.on('error', callbackError); + port.on('open', callbackOpen); + + port.open(); + + }) +} + +function runSyncExec(command){ + return new Promise((resolve, reject) => { + + exec(command, (error, stdout, stderr) => { + if(error == null) resolve(stdout); + reject(error); + }); + + }) +} + +async function writeData(port, data, readbytes, timeout){ + return new Promise((resolve, reject) => { + + // 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) { + + port.write(Buffer.from(data), function(err) { + if (err) { + reject(err.message); + } + }); + + 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 +} diff --git a/RVO35/flow_old/helper/suncalc.js b/RVO35/flow_old/helper/suncalc.js new file mode 100755 index 0000000..c9ca56d --- /dev/null +++ b/RVO35/flow_old/helper/suncalc.js @@ -0,0 +1,317 @@ +/* + (c) 2011-2015, Vladimir Agafonkin + SunCalc is a JavaScript library for calculating sun/moon position and light phases. + https://github.com/mourner/suncalc +*/ + +(function () { 'use strict'; + +// shortcuts for easier to read formulas + +var PI = Math.PI, + sin = Math.sin, + cos = Math.cos, + tan = Math.tan, + asin = Math.asin, + atan = Math.atan2, + acos = Math.acos, + rad = PI / 180; + +// sun calculations are based on http://aa.quae.nl/en/reken/zonpositie.html formulas + + +// date/time constants and conversions + +var dayMs = 1000 * 60 * 60 * 24, + J1970 = 2440588, + J2000 = 2451545; + +function toJulian(date) { return date.valueOf() / dayMs - 0.5 + J1970; } +function fromJulian(j) { return new Date((j + 0.5 - J1970) * dayMs); } +function toDays(date) { return toJulian(date) - J2000; } + + +// general calculations for position + +var e = rad * 23.4397; // obliquity of the Earth + +function rightAscension(l, b) { return atan(sin(l) * cos(e) - tan(b) * sin(e), cos(l)); } +function declination(l, b) { return asin(sin(b) * cos(e) + cos(b) * sin(e) * sin(l)); } + +function azimuth(H, phi, dec) { return atan(sin(H), cos(H) * sin(phi) - tan(dec) * cos(phi)); } +function altitude(H, phi, dec) { return asin(sin(phi) * sin(dec) + cos(phi) * cos(dec) * cos(H)); } + +function siderealTime(d, lw) { return rad * (280.16 + 360.9856235 * d) - lw; } + +function astroRefraction(h) { + if (h < 0) // the following formula works for positive altitudes only. + h = 0; // if h = -0.08901179 a div/0 would occur. + + // formula 16.4 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + // 1.02 / tan(h + 10.26 / (h + 5.10)) h in degrees, result in arc minutes -> converted to rad: + return 0.0002967 / Math.tan(h + 0.00312536 / (h + 0.08901179)); +} + +// general sun calculations + +function solarMeanAnomaly(d) { return rad * (357.5291 + 0.98560028 * d); } + +function eclipticLongitude(M) { + + var C = rad * (1.9148 * sin(M) + 0.02 * sin(2 * M) + 0.0003 * sin(3 * M)), // equation of center + P = rad * 102.9372; // perihelion of the Earth + + return M + C + P + PI; +} + +function sunCoords(d) { + + var M = solarMeanAnomaly(d), + L = eclipticLongitude(M); + + return { + dec: declination(L, 0), + ra: rightAscension(L, 0) + }; +} + + +var SunCalc = {}; + + +// calculates sun position for a given date and latitude/longitude + +SunCalc.getPosition = function (date, lat, lng) { + + var lw = rad * -lng, + phi = rad * lat, + d = toDays(date), + + c = sunCoords(d), + H = siderealTime(d, lw) - c.ra; + + return { + azimuth: azimuth(H, phi, c.dec), + altitude: altitude(H, phi, c.dec) + }; +}; + + +// sun times configuration (angle, morning name, evening name) + +var times = SunCalc.times = [ + [-0.833, 'sunrise', 'sunset' ], + [ -0.3, 'sunriseEnd', 'sunsetStart' ], + [ -6, 'dawn', 'dusk' ], + [ -12, 'nauticalDawn', 'nauticalDusk'], + [ -18, 'nightEnd', 'night' ], + [ 6, 'goldenHourEnd', 'goldenHour' ] +]; + +// adds a custom time to the times config + +SunCalc.addTime = function (angle, riseName, setName) { + times.push([angle, riseName, setName]); +}; + + +// calculations for sun times + +var J0 = 0.0009; + +function julianCycle(d, lw) { return Math.round(d - J0 - lw / (2 * PI)); } + +function approxTransit(Ht, lw, n) { return J0 + (Ht + lw) / (2 * PI) + n; } +function solarTransitJ(ds, M, L) { return J2000 + ds + 0.0053 * sin(M) - 0.0069 * sin(2 * L); } + +function hourAngle(h, phi, d) { return acos((sin(h) - sin(phi) * sin(d)) / (cos(phi) * cos(d))); } +function observerAngle(height) { return -2.076 * Math.sqrt(height) / 60; } + +// returns set time for the given sun altitude +function getSetJ(h, lw, phi, dec, n, M, L) { + + var w = hourAngle(h, phi, dec), + a = approxTransit(w, lw, n); + return solarTransitJ(a, M, L); +} + + +// calculates sun times for a given date, latitude/longitude, and, optionally, +// the observer height (in meters) relative to the horizon + +SunCalc.getTimes = function (date, lat, lng, height) { + + height = height || 0; + + var lw = rad * -lng, + phi = rad * lat, + + dh = observerAngle(height), + + d = toDays(date), + n = julianCycle(d, lw), + ds = approxTransit(0, lw, n), + + M = solarMeanAnomaly(ds), + L = eclipticLongitude(M), + dec = declination(L, 0), + + Jnoon = solarTransitJ(ds, M, L), + + i, len, time, h0, Jset, Jrise; + + + var result = { + solarNoon: fromJulian(Jnoon), + nadir: fromJulian(Jnoon - 0.5) + }; + + for (i = 0, len = times.length; i < len; i += 1) { + time = times[i]; + h0 = (time[0] + dh) * rad; + + Jset = getSetJ(h0, lw, phi, dec, n, M, L); + Jrise = Jnoon - (Jset - Jnoon); + + result[time[1]] = fromJulian(Jrise); + result[time[2]] = fromJulian(Jset); + } + + return result; +}; + + +// moon calculations, based on http://aa.quae.nl/en/reken/hemelpositie.html formulas + +function moonCoords(d) { // geocentric ecliptic coordinates of the moon + + var L = rad * (218.316 + 13.176396 * d), // ecliptic longitude + M = rad * (134.963 + 13.064993 * d), // mean anomaly + F = rad * (93.272 + 13.229350 * d), // mean distance + + l = L + rad * 6.289 * sin(M), // longitude + b = rad * 5.128 * sin(F), // latitude + dt = 385001 - 20905 * cos(M); // distance to the moon in km + + return { + ra: rightAscension(l, b), + dec: declination(l, b), + dist: dt + }; +} + +SunCalc.getMoonPosition = function (date, lat, lng) { + + var lw = rad * -lng, + phi = rad * lat, + d = toDays(date), + + c = moonCoords(d), + H = siderealTime(d, lw) - c.ra, + h = altitude(H, phi, c.dec), + // formula 14.1 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + pa = atan(sin(H), tan(phi) * cos(c.dec) - sin(c.dec) * cos(H)); + + h = h + astroRefraction(h); // altitude correction for refraction + + return { + azimuth: azimuth(H, phi, c.dec), + altitude: h, + distance: c.dist, + parallacticAngle: pa + }; +}; + + +// calculations for illumination parameters of the moon, +// based on http://idlastro.gsfc.nasa.gov/ftp/pro/astro/mphase.pro formulas and +// Chapter 48 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + +SunCalc.getMoonIllumination = function (date) { + + var d = toDays(date || new Date()), + s = sunCoords(d), + m = moonCoords(d), + + sdist = 149598000, // distance from Earth to Sun in km + + phi = acos(sin(s.dec) * sin(m.dec) + cos(s.dec) * cos(m.dec) * cos(s.ra - m.ra)), + inc = atan(sdist * sin(phi), m.dist - sdist * cos(phi)), + angle = atan(cos(s.dec) * sin(s.ra - m.ra), sin(s.dec) * cos(m.dec) - + cos(s.dec) * sin(m.dec) * cos(s.ra - m.ra)); + + return { + fraction: (1 + cos(inc)) / 2, + phase: 0.5 + 0.5 * inc * (angle < 0 ? -1 : 1) / Math.PI, + angle: angle + }; +}; + + +function hoursLater(date, h) { + return new Date(date.valueOf() + h * dayMs / 24); +} + +// calculations for moon rise/set times are based on http://www.stargazing.net/kepler/moonrise.html article + +SunCalc.getMoonTimes = function (date, lat, lng, inUTC) { + var t = new Date(date); + if (inUTC) t.setUTCHours(0, 0, 0, 0); + else t.setHours(0, 0, 0, 0); + + var hc = 0.133 * rad, + h0 = SunCalc.getMoonPosition(t, lat, lng).altitude - hc, + h1, h2, rise, set, a, b, xe, ye, d, roots, x1, x2, dx; + + // go in 2-hour chunks, each time seeing if a 3-point quadratic curve crosses zero (which means rise or set) + for (var i = 1; i <= 24; i += 2) { + h1 = SunCalc.getMoonPosition(hoursLater(t, i), lat, lng).altitude - hc; + h2 = SunCalc.getMoonPosition(hoursLater(t, i + 1), lat, lng).altitude - hc; + + a = (h0 + h2) / 2 - h1; + b = (h2 - h0) / 2; + xe = -b / (2 * a); + ye = (a * xe + b) * xe + h1; + d = b * b - 4 * a * h1; + roots = 0; + + if (d >= 0) { + dx = Math.sqrt(d) / (Math.abs(a) * 2); + x1 = xe - dx; + x2 = xe + dx; + if (Math.abs(x1) <= 1) roots++; + if (Math.abs(x2) <= 1) roots++; + if (x1 < -1) x1 = x2; + } + + if (roots === 1) { + if (h0 < 0) rise = i + x1; + else set = i + x1; + + } else if (roots === 2) { + rise = i + (ye < 0 ? x2 : x1); + set = i + (ye < 0 ? x1 : x2); + } + + if (rise && set) break; + + h0 = h2; + } + + var result = {}; + + if (rise) result.rise = hoursLater(t, rise); + if (set) result.set = hoursLater(t, set); + + if (!rise && !set) result[ye > 0 ? 'alwaysUp' : 'alwaysDown'] = true; + + return result; +}; + + +// export as Node module / AMD module / browser variable +if (typeof exports === 'object' && typeof module !== 'undefined') module.exports = SunCalc; +else if (typeof define === 'function' && define.amd) define(SunCalc); +else window.SunCalc = SunCalc; + +}()); diff --git a/RVO35/flow_old/helper/utils.js b/RVO35/flow_old/helper/utils.js new file mode 100755 index 0000000..a16210c --- /dev/null +++ b/RVO35/flow_old/helper/utils.js @@ -0,0 +1,124 @@ +function bytesToInt(bytes, numberOfBytes) +{ + let buffer = []; + if(Array.isArray(bytes)) + { + buffer = bytes.slice(0); + if(numberOfBytes != undefined) + { + buffer = bytes.slice(bytes.length - numberOfBytes); + } + } + else buffer.push(bytes); + + //var decimal = (buffer[0] << 24) + (buffer[1] << 16) + (buffer[2] << 8) + buffer[3]; + let l = (buffer.length - 1) * 8; + + let decimal = 0; + for(let i = 0; i < buffer.length; i++) + { + var s = buffer[i] << l; + if(l < 8) s = buffer[i] + decimal = decimal + s; + + l = l - 8; + + } + + return decimal; +} + +function resizeArray(arr, newSize, defaultValue) { + while(newSize > arr.length) + arr.push(defaultValue); + arr.length = newSize; +} + +longToByteArray = function(/*long*/long) { + // we want to represent the input as a 8-bytes array + var byteArray = [0, 0, 0, 0, 0, 0, 0, 0]; + + for ( var index = 0; index < byteArray.length; index ++ ) { + var byte = long & 0xff; + byteArray [ index ] = byte; + long = (long - byte) / 256 ; + } + + return byteArray; + }; + +function addDays(date, days) { + var result = new Date(date); + result.setDate(result.getDate() + days); + return result; +} + +/* +sleep(2000).then(() => { + // Do something after the sleep! + + +}); +*/ + +function sleep (time) { + return new Promise((resolve) => setTimeout(resolve, time)); +} + +function isEmptyObject( obj ) { + for ( var name in obj ) { + return false; + } + return true; +} + +function convertUTCDateToLocalDate(date) { + var newDate = new Date(date); + newDate.setMinutes(date.getMinutes() + date.getTimezoneOffset()); + return newDate; +} + +function addZeroBefore(n) { + return (n < 10 ? '0' : '') + n; +} + +var convertBase = function () { + + function convertBase(baseFrom, baseTo) { + return function (num) { + return parseInt(num, baseFrom).toString(baseTo); + + }; + } + + // binary to decimal + convertBase.bin2dec = convertBase(2, 10); + + // binary to hexadecimal + convertBase.bin2hex = convertBase(2, 16); + + // decimal to binary + convertBase.dec2bin = convertBase(10, 2); + + // decimal to hexadecimal + convertBase.dec2hex = convertBase(10, 16); + + // hexadecimal to binary + convertBase.hex2bin = convertBase(16, 2); + + // hexadecimal to decimal + convertBase.hex2dec = convertBase(16, 10); + + return convertBase; + }(); + +module.exports = { + bytesToInt, + longToByteArray, + addDays, + addZeroBefore, + resizeArray, + isEmptyObject, + sleep, + convertUTCDateToLocalDate +} \ No newline at end of file diff --git a/RVO35/flow_old/httprequest.js b/RVO35/flow_old/httprequest.js new file mode 100755 index 0000000..469c8cb --- /dev/null +++ b/RVO35/flow_old/httprequest.js @@ -0,0 +1,137 @@ +exports.id = 'httprequest'; +exports.title = 'HTTP Request'; +exports.group = 'HTTP'; +exports.color = '#5D9CEC'; +exports.input = true; +exports.version = '2.0.1'; +exports.output = 1; +exports.author = 'Peter Širka'; +exports.icon = 'cloud-upload'; + +exports.html = `
+
@(URL address)
+
+
+
@(HTTP method)
+
+
+
@(Serialization)
+
+
+
@(Download the content in chunks)
+
@(Keep persistent cookies)
+
@(Disable DNS cache)
+
@(Keep alive connection)
+
+
+
+
@(Custom headers)
+
@(Cookies)
+
+
+
+ +
+
+
+
@(User)
+
+
+
@(Password)
+
+
+
+
+
`; + +exports.readme = `# Request + +This component creates a request with received data. + +__Response:__ +\`\`\`javascript +{ + data: String, + headers: Object, + status: Number, + host: String +} +\`\`\` + +__Dynamic arguments__: +Are performed via FlowData repository and can be used for URL address or for custom headers/cookies/auth. Use \`repository\` component for creating of dynamic arguments. Dynamic values are replaced in the form \`{key}\`: + +- url address e.g. \`https://.../{key}/\` +- headers values e.g. \`{token}\` +- cookies values e.g. \`{token}\``; + +exports.install = function(instance) { + + var can = false; + var flags = null; + var cookies2 = null; + + instance.on('data', function(response) { + can && instance.custom.send(response); + }); + + instance.custom.send = function(response) { + var options = instance.options; + + var headers = null; + var cookies = null; + + options.headers && Object.keys(options.headers).forEach(function(key) { + !headers && (headers = {}); + headers[key] = response.arg(options.headers[key]); + }); + + if (options.username && options.userpassword) { + !headers && (headers = {}); + headers['Authorization'] = 'Basic ' + U.createBuffer(response.arg(options.username + ':' + options.userpassword)).toString('base64'); + } + + options.cookies && Object.keys(options.cookies).forEach(function(key) { + !cookies && (cookies = {}); + cookies[key] = response.arg(options.cookies[key]); + }); + + if (options.chunks) { + U.download(response.arg(options.url), flags, options.stringify === 'none' ? null : response.data, function(err, response) { + response.on('data', (chunks) => instance.send2(chunks)); + }, cookies || cookies2, headers); + } else { + U.request(response.arg(options.url), flags, options.stringify === 'none' ? null : response.data, 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) + instance.error(err, response); + }, cookies || cookies2, headers); + } + }; + + instance.reconfigure = function() { + var options = instance.options; + can = options.url && options.url && options.method && options.stringify ? true : false; + instance.status(can ? '' : 'Not configured', can ? undefined : 'red'); + + if (!can) + return; + + flags = []; + flags.push(options.method.toLowerCase()); + options.stringify === 'json' && flags.push('json'); + options.stringify === 'raw' && flags.push('raw'); + options.keepalive && flags.push('keepalive'); + !options.nodns && flags.push('dnscache'); + if (options.persistentcookies) { + flags.push('cookies'); + cookies2 = {}; + } else + cookies2 = null; + }; + + instance.on('options', instance.reconfigure); + instance.reconfigure(); +}; \ No newline at end of file diff --git a/RVO35/flow_old/httpresponse.js b/RVO35/flow_old/httpresponse.js new file mode 100755 index 0000000..160a3bb --- /dev/null +++ b/RVO35/flow_old/httpresponse.js @@ -0,0 +1,76 @@ +exports.id = 'httpresponse'; +exports.title = 'HTTP Response'; +exports.group = 'HTTP'; +exports.color = '#5D9CEC'; +exports.icon = 'arrow-right'; +exports.input = true; +exports.output = ['#666D76']; +exports.version = '2.0.0'; +exports.author = 'Martin Smola'; +exports.readme = `# HTTP response + +HTTP response will respond with data recieved using data-type set in Settings form or plain text if not set. Output is the message duration \`Number\` in seconds.`; + +exports.html = `
+
@(Response data-type)
+
JSON is by default.
+
`; + +exports.install = function(instance) { + + var dursum = 0; + var durcount = 0; + + instance.on('data', function(flowdata) { + + var ctrl = flowdata.repository.controller; + var data = flowdata.data; + + if (!ctrl) { + instance.throw('No controller to use for response!'); + return; + } + + durcount++; + dursum += ((new Date() - flowdata.begin) / 1000).floor(2); + setTimeout2(instance.id, instance.custom.duration, 500, 10); + + ctrl.$flowdata = flowdata; + + var datatype = instance.options.datatype || 'json'; + if (datatype === 'emptyresponse') + return ctrl.plain(''); + + if (datatype !== 'json' && typeof(data) !== 'string') { + instance.throw('Incorect type of data, expected string, got ' + typeof(data)); + ctrl.plain(data == null ? '' : data.toString()); + return; + } + + switch(datatype) { + case 'html': + ctrl.content(data, 'text/html'); + break; + case 'plain': + ctrl.plain(data); + break; + case 'xml': + ctrl.content(data, 'text/xml'); + break; + default: + ctrl.json(data); + break; + } + }); + + instance.on('service', function() { + dursum = 0; + durcount = 0; + }); + + instance.custom.duration = function() { + var avg = (dursum / durcount).floor(2); + instance.status(avg + ' sec.'); + instance.send2(0, avg); + }; +}; diff --git a/RVO35/flow_old/httproute.js b/RVO35/flow_old/httproute.js new file mode 100755 index 0000000..583a19d --- /dev/null +++ b/RVO35/flow_old/httproute.js @@ -0,0 +1,326 @@ +exports.id = 'httproute'; +exports.title = 'HTTP Route'; +exports.group = 'HTTP'; +exports.color = '#5D9CEC'; +exports.icon = 'globe'; +exports.input = false; +exports.output = ['#6CAC5A', '#37BC9B']; +exports.version = '1.2.3'; +exports.author = 'Martin Smola'; +exports.cloning = false; +exports.options = { method: 'GET', url: '', size: 5, cacheexpire: '5 minutes', cachepolicy: 0, timeout: 5 }; +exports.dateupdated = '2021-01-21 18:30d'; +exports.readme = `# HTTP route + +__Outputs__: +- first output: raw data (cache is empty or is disabled) +- second output: cached data + +If one of the outputs is disabled then automatic responce with code "503 service unavailable" is sent. + +When a request comes in bellow object is available at \`flowdata.data\`: + +\`\`\`javascript +{ + params: { id: '1' }, // params for dynamic routes, e.g. /test/{id} + query: { msg: 'Hello' }, // parsed query string, e.g. /test/1?msg=Hello + body: { test: 'OK' }, // object if json requests otherwise string + headers: {}, // headers data + session: {}, // session data + user: {}, // user data + files: [], // uploaded files + url: '/users/', // a relative URL address + referrer: '/', // referrer + mobile: false, // determines mobile device + robot: false, // determines search robots/crawlsers + language: 'en' // determines language +} +\`\`\` + +See [documentation for flags](https://docs.totaljs.com/latest/en.html#api~HttpRouteOptionsFlags~unauthorize). These method flags are set automatically e.g. \`get, post, put, patch or delete\` + +--- + +\`id:ROUTE_ID\` flag cannot be used since it's already used by this component internally`; + +exports.html = `
+
+ +
+ +
+
+
@(HTTP method)
+
+
+
@(URL address)
+
+
+
+
+
@(Additional flags)
+
@(Separate flags by comma e.g. json, authorize)
+
+
+
@(Max. request size)
+
@(In kB kilobytes)
+
+
+
@(Timeout)
+
@(In seconds.)
+
+
+
+
+
+
@(Automatically respond with 200 OK?)
+
@(If not checked you need to use HTTP response component to respond to the request.)
+
+
@(Custom headers)
+
@(Cookies)
+
+
+
+
+
+
@(Cache policy)
+
@(User instance must contain id property.)
+
+
+
@(Expiration)
+
@(E.g. 5 minutes)
+
+
+
+`; + +exports.install = function(instance) { + + var route; + + var uninstall = function(id) { + if (F.is4) { + route && route.remove(); + route = null; + } else + UNINSTALL('route', id); + }; + + instance.custom.emptyresponse = function(self) { + self.plain(); + }; + + instance.reconfigure = function() { + + var options = instance.options; + + if (!options.url) { + instance.status('Not configured', 'red'); + return; + } + + if (typeof(options.flags) === 'string') + options.flags = options.flags.split(',').trim(); + + uninstall('id:' + instance.id); + + var flags = options.flags || []; + + flags.push('id:' + instance.id); + + if (!F.is4) + flags.push(options.method.toLowerCase()); + + options.timeout && flags.push(options.timeout * 1000); + + // Make unique values + flags = flags.filter(function(v, i, a) { + if(F.is4 && v.toString().toLowerCase() === options.method.toLowerCase()) + return false; // remove method + return a.indexOf(v) === i; + }); + + options.flags = flags; + var handler = function() { + + if (instance.paused || (instance.isDisabled && (instance.isDisabled('output', 0) || instance.isDisabled('output', 1)))) { + instance.status('503 Service Unavailable'); + this.status = 503; + this.json(); + return; + } + + var key; + var self = this; + + if (instance.options.emptyresponse) { + instance.status('200 OK'); + setTimeout(instance.custom.emptyresponse, 100, self); + + if (instance.hasConnection(0)) { + var data = instance.make({ + query: self.query, + body: self.body, + session: self.session, + user: self.user, + files: self.files, + headers: self.req.headers, + url: self.url, + params: self.params + }); + instance.send2(0, data); + } + + return; + } + + switch (instance.options.cachepolicy) { + case 1: // URL + key = 'rro' + instance.id + self.url.hash(); + break; + case 2: // URL + query + case 3: // URL + query + user + key = self.url; + var keys = Object.keys(self.query); + keys.sort(); + for (var i = 0, length = keys.length; i < length; i++) + key += keys[i] + self.query[keys[i]] + '&'; + if (instance.options.cachepolicy === 3 && self.user) + key += 'iduser' + self.user.id; + key = 'rro' + instance.id + key.hash(); + break; + } + + if (key && F.cache.get2(key)) { + var data = instance.make(F.cache.get2(key)); + data.repository.controller = self; + instance.send2(1, data); + } else { + + var data = instance.make({ + query: self.query, + body: self.body, + session: self.session, + user: self.user, + files: self.files, + headers: self.req.headers, + url: self.url, + params: self.params, + mobile: self.mobile, + robot: self.robot, + referrer: self.referrer, + language: self.language + }); + + data.repository.controller = self; + instance.send2(0, data); + key && FINISHED(self.res, () => F.cache.set(key, self.$flowdata.data, instance.options.cacheexpire)); + } + }; + + if (F.is4) + route = ROUTE(options.method.toUpperCase() + ' ' + options.url, handler, flags, options.size || 5); + else + F.route(options.url, handler, flags, options.size || 5); + + instance.status('Listening', 'green'); + }; + + instance.reconfigure(); + instance.on('options', instance.reconfigure); + instance.on('close', function(){ + uninstall('id:' + instance.id); + }); +}; + +// check url exists +FLOW.trigger('httproutecheckurl', function(next, data) { + var url = data.url; + var method = data.method; + if (url[url.length - 1] !== '/') + url += '/'; + var exists = F.routes.web.findItem(r => r.urlraw === url && r.method === method); + next(exists != null); +}); + +exports.uninstall = function() { + FLOW.trigger('httproutecheckurl', null); +}; diff --git a/RVO35/flow_old/infosender.js b/RVO35/flow_old/infosender.js new file mode 100755 index 0000000..c7afd83 --- /dev/null +++ b/RVO35/flow_old/infosender.js @@ -0,0 +1,101 @@ +exports.id = 'infosender'; +exports.title = 'Info sender'; +exports.version = '1.0.0'; +exports.group = 'Worksys'; +exports.color = '#2134B0'; +exports.input = 2; +exports.output = 1 +exports.icon = 'bolt'; + +const { networkInterfaces } = require('os'); + +exports.html = `
+
+
+
CSV Import
+
+
+
`; + +exports.readme = `# send all data to projects.worksys.io, required to monitor status of controller(unipi)`; + +exports.install = function(instance) { + + let id; + let allValues = {}; + let sendAllValuesInterval; + let configured = false; + + let now = new Date(); + console.log(exports.title, "INSTALLED", now.toLocaleString("sk-SK")); + + const nets = networkInterfaces(); + let ipAddresses = Object.create(null); // Or just '{}', an empty object + + for (const name of Object.keys(nets)) { + for (const net of nets[name]) { + // Skip over non-IPv4 and internal (i.e. 127.0.0.1) addresses + if (net.family === 'IPv4' && !net.internal) { + if (!ipAddresses[name]) { + ipAddresses[name] = []; + } + ipAddresses[name].push(net.address); + } + } + } + + function sendValues() + { + if(!configured) return; + + if(Object.keys(allValues).length > 0) + { + if(id) + { + delete allValues.__force__; + let dataToSend = {...allValues}; + dataToSend.id = id; + dataToSend.ipAddresses = ipAddresses; + + instance.send(0, dataToSend); + + allValues = {}; + } + else + { + console.log(exports.title, "unable to send data, no id"); + } + + } + } + + instance.on("close", () => { + clearInterval(sendAllValuesInterval); + }) + + instance.on("0", _ => { + id = FLOW.GLOBALS.settings.project_id; + configured = true; + }) + + instance.on("1", flowdata => { + + allValues = { ...allValues, ...flowdata.data}; + //console.log("DATA RECEIVED", flowdata.data); + + //__force__ + if(flowdata.data.hasOwnProperty("__force__")) + { + if(flowdata.data.__force__) + { + sendValues(); + } + } + }) + + sendAllValuesInterval = setInterval(() => { + sendValues(); + }, 60000*3); + +} + diff --git a/RVO35/flow_old/modbus_reader.js b/RVO35/flow_old/modbus_reader.js new file mode 100755 index 0000000..b907148 --- /dev/null +++ b/RVO35/flow_old/modbus_reader.js @@ -0,0 +1,367 @@ +exports.id = 'modbus_reader'; +exports.title = 'Modbus reader'; +exports.version = '2.0.0'; +exports.group = 'Worksys'; +exports.color = '#2134B0'; +exports.input = 1; +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; +//number of phases inRVO +let phases; +//phases where voltage is 0 (set) +let noVoltage; + +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.phases = this.buildPhases(); + + this.startSocket(); + } + + buildPhases = () => { + let a = []; + for (let i = 1; i<= phases; i++) { + a.push(`Phase_${i}_voltage`) + } + return a; + } + + 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 (this.phases.includes(singleValue)) + { + let l = singleValue.split("_"); + let phase = parseInt(l[1]); + + // console.log(values[singleValue], tbName); + + if(values[singleValue] == 0) + { + noVoltage.add(phase); + sendNotification("modbus_reader: checkNullVoltage", tbName, "no_voltage_on_phase", {phase: phase}, "", SEND_TO.tb, instance, "voltage" + phase ); + // console.log('no voltage') + } + else + { + noVoltage.delete(phase); + // console.log('voltage detected') + sendNotification("modbus_reader: checkNullVoltage", tbName, "voltage_on_phase_restored", {phase: phase}, "", SEND_TO.tb, instance, "voltage" + phase); + } + } + }) + } + + /** + * function sends notification to slack and to tb, if EM total_power value changes more than numberOfNodes*15. This should show, that RVO lamps has been switched on or off + */ + lampSwitchNotification = (values) => { + + if(!values.hasOwnProperty("total_power")) return; + + const actualTotalPower = values.total_power; + + const numberOfNodes = Object.keys(FLOW.GLOBALS.nodesData).length; + if(numberOfNodes == 0) numberOfNodes = 20; // to make sure, we send notification if totalPower is more than 300 + + if(actualTotalPower > numberOfNodes * 15 && this.onNotificationSent == false) + { + sendNotification("modbus_reader: lampSwitchNotification", tbName, "lamps_have_turned_on", {}, "", SEND_TO.tb, instance); + this.onNotificationSent = true; + this.offNotificationSent = false; + } + else if(actualTotalPower <= numberOfNodes * 15 && this.offNotificationSent == false) + { + 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; + } + + function main() { + + phases = FLOW.GLOBALS.settings.phases; + tbName = FLOW.GLOBALS.settings.rvoTbName; + noVoltage = FLOW.GLOBALS.settings.no_voltage; + mainSocket = new SocketWithClients(); + + // this notification is to show, that flow (unipi) has been restarted + sendNotification("modbus_reader", tbName, "flow_restart", {}, "", SEND_TO.slack, instance); + } + + instance.on("0", function(_) { + main(); + }) + +} + diff --git a/RVO35/flow_old/monitorconsumption.js b/RVO35/flow_old/monitorconsumption.js new file mode 100755 index 0000000..64cc58e --- /dev/null +++ b/RVO35/flow_old/monitorconsumption.js @@ -0,0 +1,156 @@ +exports.id = 'monitorconsumption'; +exports.title = 'Consumption'; +exports.version = '1.0.0'; +exports.author = 'Peter Širka'; +exports.group = 'Monitoring'; +exports.color = '#967ADC'; +exports.input = 0; +exports.output = 1; +exports.icon = 'bug'; +exports.options = { interval: 5000, enabled: true, monitorconsumption: true, monitorsize: true, monitorconnections: true, monitorfiles: true }; +exports.click = true; +exports.readme = `# Consumption monitoring + +This component measure CPU and memory consumption, open files and open connections of this application. It uses these Linux commands: \`ps\`, \`lsof\`, \`netstat\` and \`df\`. + +__Data Example__: + +\`\`\`javascript +{ + cpu: 0, // percentage + memory: 4096, // in bytes + size: 34303, // directory size in bytes + files: 34, // count of open files + connections: 343, // count of connections + uptime: '1-12:34:00' +} +\`\`\``; + +exports.html = `
+
+
+
@(Interval in milliseconds)
+
+
+
+
Monitor: Consumption + uptime
+
Monitor: Count of open files
+
Monitor: Count of open connections
+
Monitor: Directory size
+
`; + +exports.install = function(instance) { + + var current = { cpu: 0, memory: 0, files: 0, connections: 0, size: 0, uptime: '', counter: 0 }; + var tproc = null; + var Exec = require('child_process').exec; + var reg_empty = /\s{2,}/g; + var reg_appdisksize = /^[\d.,]+/; + + instance.custom.run = function() { + + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + + var arr = []; + + // Get CPU and Memory consumption + instance.options.monitorconsumption && arr.push(function(next) { + Exec('ps -p {0} -o %cpu,rss,etime'.format(process.pid), function(err, response) { + + if (err) { + instance.throw(err); + } else { + var line = response.split('\n')[1]; + line = line.trim().replace(reg_empty, ' ').split(' '); + var cpu = line[0].parseFloat(); + current.cpu = cpu.floor(1); + current.memory = line[1].parseInt2() * 1024; // kB to bytes + current.uptime = line[2]; + } + + next(); + }); + }); + + // Get count of open files + instance.options.monitorfiles && arr.push(function(next) { + Exec('lsof -a -p {0} | wc -l'.format(process.pid), function(err, response) { + if (err) + instance.throw(err); + else + current.files = response.trim().parseInt2(); + next(); + }); + }); + + // Get count of opened network connections + instance.options.monitorconnections && arr.push(function(next) { + Exec('netstat -an | grep :{0} | wc -l'.format(F.port), function(err, response) { + if (err) { + instance.throw(err); + } else { + current.connections = response.trim().parseInt2() - 1; + if (current.connections < 0) + current.connections = 0; + } + next(); + }); + }); + + // Get directory size + instance.options.monitorsize && current.counter % 5 !== 0 && arr.push(function(next) { + Exec('du -hsb ' + process.cwd(), function(err, response) { + if (err) { + instance.throw(err); + } else { + var match = response.trim().match(reg_appdisksize); + match && (current.size = match.toString().trim().parseInt2()); + } + next(); + }); + }); + + arr.async(function() { + + tproc && clearTimeout(tproc); + + if (instance.options.enabled) { + tproc = setTimeout(instance.custom.run, instance.options.interval); + instance.send2(current); + } + + instance.custom.status(); + current.counter++; + }); + }; + + instance.custom.status = function() { + if (instance.options.enabled) + instance.status('{0}% / {1}'.format(current.cpu, current.memory.filesize())); + else + instance.status('Disabled', 'red'); + }; + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + + if (instance.options.enabled) { + current.counter = 0; + instance.custom.run(); + } + + }); + + instance.on('close', function() { + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + }); + + setTimeout(instance.custom.run, 1000); +}; \ No newline at end of file diff --git a/RVO35/flow_old/monitordisk.js b/RVO35/flow_old/monitordisk.js new file mode 100755 index 0000000..f4fdaa0 --- /dev/null +++ b/RVO35/flow_old/monitordisk.js @@ -0,0 +1,96 @@ +exports.id = 'monitordisk'; +exports.title = 'Disk'; +exports.version = '1.0.0'; +exports.author = 'Peter Širka'; +exports.group = 'Monitoring'; +exports.color = '#F6BB42'; +exports.output = 1; +exports.icon = 'hdd-o'; +exports.click = true; +exports.options = { interval: 8000, path: '/', enabled: true }; +exports.readme = `# Disk monitoring + +This component monitors disk \`bytes\` consumption in Linux systems. It uses \`df\` command. + +__Data Example__: + +\`\`\`javascript +{ + total: 474549649408, + used: 39125245952, + free: 411294994432 +} +\`\`\``; + +exports.html = `
+
+
+
@(Interval in milliseconds)
+
+
+
@(Path)
+
+
+
`; + +exports.install = function(instance) { + + var current = { total: 0, used: 0, free: 0, path: '', type: '', percentUsed: 0 }; + var tproc = null; + + instance.custom.run = function() { + + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + + if (!instance.options.enabled) + return; + + require('child_process').exec('df -hTB1 ' + instance.options.path, function(err, response) { + + tproc = setTimeout(instance.custom.run, instance.options.interval); + + if (err) { + instance.error(err); + return; + } + + response.parseTerminal(function(line) { + if (line[0][0] !== '/') + return; + current.total = line[2].parseInt(); + current.free = line[4].parseInt(); + current.used = line[3].parseInt(); + current.path = instance.options.path || '/'; + current.type = line[1]; + current.percentUsed = line[5]; + instance.custom.status(); + instance.send2(current); + }); + }); + }; + + instance.custom.status = function() { + if (instance.options.enabled) + instance.status(current.free.filesize() + ' / ' + current.total.filesize()); + else + instance.status('Disabled', 'red'); + }; + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + instance.options.enabled && instance.custom.run(); + }); + + instance.on('close', function() { + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + }); + + setTimeout(instance.custom.run, 1000); +}; \ No newline at end of file diff --git a/RVO35/flow_old/monitormemory.js b/RVO35/flow_old/monitormemory.js new file mode 100755 index 0000000..2decbc4 --- /dev/null +++ b/RVO35/flow_old/monitormemory.js @@ -0,0 +1,87 @@ +exports.id = 'monitormemory'; +exports.title = 'Memory'; +exports.version = '1.0.0'; +exports.author = 'Peter Širka'; +exports.group = 'Monitoring'; +exports.color = '#F6BB42'; +exports.output = 1; +exports.click = true; +exports.icon = 'microchip'; +exports.options = { interval: 8000, enabled: true }; +exports.readme = `# Memory monitoring + +This component monitors memory \`bytes\` consumption in Linux systems. It uses \`free\` command. + +__Data Example__: + +\`\`\`javascript +{ + total: 33558769664, + used: 1998868480, + free: 2653708288 +} +\`\`\``; + +exports.html = `
+
+
+
@(Interval in milliseconds)
+
+
+
`; + +exports.install = function(instance) { + + var current = { total: 0, used: 0, free: 0 }; + var tproc = null; + + instance.custom.run = function() { + + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + + if (!instance.options.enabled) + return; + + require('child_process').exec('free -b -t', function(err, response) { + + tproc = setTimeout(instance.custom.run, instance.options.interval); + + if (err) { + instance.error(err); + return; + } + + var memory = response.split('\n')[1].match(/\d+/g); + current.total = memory[0].parseInt(); + current.used = memory[1].parseInt() - memory[3].parseInt(); + current.free = current.total - current.used; + instance.custom.status(); + instance.send2(current); + }); + }; + + instance.custom.status = function() { + if (instance.options.enabled) + instance.status(current.free.filesize() + ' / ' + current.total.filesize()); + else + instance.status('Disabled', 'red'); + }; + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + instance.options.enabled && instance.custom.run(); + }); + + instance.on('close', function() { + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + }); + + setTimeout(instance.custom.run, 1000); +}; \ No newline at end of file diff --git a/RVO35/flow_old/nodesdb_changecheck.js b/RVO35/flow_old/nodesdb_changecheck.js new file mode 100755 index 0000000..be1e700 --- /dev/null +++ b/RVO35/flow_old/nodesdb_changecheck.js @@ -0,0 +1,70 @@ +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/RVO35/flow_old/notifikacie.csv b/RVO35/flow_old/notifikacie.csv new file mode 100755 index 0000000..520c997 --- /dev/null +++ b/RVO35/flow_old/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/RVO35/flow_old/show_dbdata.js b/RVO35/flow_old/show_dbdata.js new file mode 100755 index 0000000..d01eecd --- /dev/null +++ b/RVO35/flow_old/show_dbdata.js @@ -0,0 +1,241 @@ +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 = 7; +exports.output = 1; + +const { exec } = require('child_process'); + +exports.install = 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}) + }) + instance.on("5", _ => { + exec("sudo tail -n 25 monitor.txt" , (err, stdout, stderr) => { + if (err || stderr) instance.send(0,{err, stderr}); + else instance.send(0,stdout); + }) + }) + instance.on("6", _ => { + exec("sudo tail -n 25 err.txt" , (err, stdout, stderr) => { + if (err || stderr) instance.send(0,{err, stderr}); + else instance.send(0,stdout); + }) + }) +}; + + + +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/RVO35/flow_old/slack_filter.js b/RVO35/flow_old/slack_filter.js new file mode 100755 index 0000000..753c24a --- /dev/null +++ b/RVO35/flow_old/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 = `
+
+
+
@(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"] = []; + } + + instance.options.name = FLOW.GLOBALS.settings.rvo_name; + if (instance.options.name) { + instance.status('Running'); + running = true; + } else { + instance.status('Please run options again', 'red'); + running = false; + } + } catch (e) { + instance.error('Citysys connector: ' + e.message); + } + }; + + instance.on('options', instance.reconfigure); + setTimeout(instance.reconfigure, 10000); + + +}; diff --git a/RVO35/flow_old/thermometer.js b/RVO35/flow_old/thermometer.js new file mode 100755 index 0000000..fa015c6 --- /dev/null +++ b/RVO35/flow_old/thermometer.js @@ -0,0 +1,98 @@ +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 = 5;//minutes +let NUMBER_OF_FAILURES_TO_SEND_ERROR = 13; + +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) => { + + 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); + setTimeout(main, 20000); + }) +}; diff --git a/RVO35/flow_old/trigger.js b/RVO35/flow_old/trigger.js new file mode 100755 index 0000000..27545a8 --- /dev/null +++ b/RVO35/flow_old/trigger.js @@ -0,0 +1,79 @@ +exports.id = 'trigger'; +exports.title = 'Trigger'; +exports.group = 'Inputs'; +exports.color = '#F6BB42'; +exports.click = true; +exports.output = 1; +exports.version = '1.1.0'; +exports.author = 'Martin Smola'; +exports.icon = 'play'; + +exports.html = `
+
@(Data type (String by default))
+
@(Data)
+
Trigger 5s after initialization.
+
@(Useful when there's a need to run certain flow when the app restarts, etc.)
+
`; + +exports.readme = `# Trigger + +- Clicking on the component starts the chain +- Settings allows to set a data-type and a value`; + +exports.install = function(instance) { + + var value; + + instance.on('click', () => instance.send2(value)); + + instance.reconfigure = function() { + var options = instance.options; + value = null; + switch (options.datatype) { + case 'integer': + value = options.data.parseInt2('error'); + value = value === 'error' ? NaN : value; + break; + case 'float': + value = options.data.parseFloat2('error'); + value = value === 'error' ? NaN : value; + break; + case 'date': + options.data = options.data.toString(); + var num = options.data.parseInt('error'); + num === 'error' && (num = options.data.parseDate('error')); + num === 'error' && (num = null); + value = num ? new Date(num).toUTCString() : num; + break; + case 'object': + try { + value = (new Function('return ' + options.data))(); + } catch (e) { + instance.error(e); + } + break; + case 'boolean': + value = options.data.parseBoolean(); + break; + case 'buffer': + try { + value = U.createBuffer(options.data); + } catch (e) { + instance.error(e); + } + break; + case 'string': + default: + value = '' + (options.data || ''); + break; + } + }; + + instance.on('options', instance.reconfigure); + instance.reconfigure(); + + if (instance.options.restart) + setTimeout(function(){ + instance.send2(value); + }, 5000); +}; diff --git a/RVO35/flow_old/variables.txt b/RVO35/flow_old/variables.txt new file mode 100755 index 0000000..e69de29 diff --git a/RVO35/flow_old/virtualwirein.js b/RVO35/flow_old/virtualwirein.js new file mode 100755 index 0000000..38a4e42 --- /dev/null +++ b/RVO35/flow_old/virtualwirein.js @@ -0,0 +1,43 @@ +exports.id = 'virtualwirein'; +exports.title = 'Virtual wire in'; +exports.version = '1.0.0'; +exports.author = 'Martin Smola'; +exports.color = '#303E4D'; +exports.icon = 'sign-in'; +exports.input = false; +exports.output = 1; +exports.options = {}; +exports.readme = `# Virtual wire in + +When the wires between the components are mess it's time to use Virtual wire.`; + +exports.html = `
+
@(Wire name)
+
+`; + +exports.install = function(instance) { + + instance.custom.reconfigure = function(options){ + if (instance.options.wirename) { + instance.status(instance.options.wirename); + } else + instance.status('Not configured', 'red'); + }; + + ON('virtualwire', function(wirename, flowdata){ + if (instance.options.wirename && instance.options.wirename === wirename) + instance.send(flowdata); + }); + + instance.on('options', instance.custom.reconfigure); + instance.custom.reconfigure(); +}; diff --git a/RVO35/flow_old/virtualwireout.js b/RVO35/flow_old/virtualwireout.js new file mode 100755 index 0000000..94a1e4f --- /dev/null +++ b/RVO35/flow_old/virtualwireout.js @@ -0,0 +1,41 @@ +exports.id = 'virtualwireout'; +exports.title = 'Virtual wire out'; +exports.version = '1.0.0'; +exports.author = 'Martin Smola'; +exports.color = '#303E4D'; +exports.icon = 'sign-out'; +exports.input = true; +exports.options = {}; +exports.readme = `# Virtual wire out + +When the wires between the components are mess it's time to use Virtual wire.`; + +exports.html = `
+
@(Wire name)
+
+`; + +exports.install = function(instance) { + + instance.custom.reconfigure = function(){ + if (instance.options.wirename) { + instance.status(instance.options.wirename); + } else + instance.status('Not configured', 'red'); + }; + + instance.on('data', function(flowdata) { + EMIT('virtualwire', instance.options.wirename, flowdata); + }); + + instance.on('options', instance.custom.reconfigure); + instance.custom.reconfigure(); +}; diff --git a/RVO35/flow_old/wsmqttpublish.js b/RVO35/flow_old/wsmqttpublish.js new file mode 100755 index 0000000..b2a218d --- /dev/null +++ b/RVO35/flow_old/wsmqttpublish.js @@ -0,0 +1,477 @@ +exports.id = 'wsmqttpublish'; +exports.title = 'WS MQTT publish'; +exports.group = 'MQTT'; +exports.color = '#888600'; +exports.version = '1.0.2'; +exports.icon = 'sign-out'; +exports.input = 2; +exports.output = 3; +exports.options = { host: 'tb-stage.worksys.io', port: 1883, clientid: "", username: "" }; + +exports.html = `
+
+
+
Hostname or IP address (if not empty - setting will override db setting)
+
+
+
Port
+
+
+
+
+
@(Client id)
+
+
+
@(Username)
+
+
+
`; + + +exports.readme = ` +# WS MQTT Publish + +Version 1.0.3. + +Added: +- database collections, +- 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 = { + debug: 0, + rpcCall: 1, + services: 2 +} + +//CONFIG +let createTelemetryBackup = true; +let saveTelemetryOnError = true;//backup_on_failure overrides this value +//------------------------ + +let rollers; +if(createTelemetryBackup) rollers = require('streamroller'); + +const noSqlFileSizeLimit = 4194304;//use 5MB - 4194304 +let insertNoSqlCounter = 0; +let insertBackupNoSqlCounter = 0; +let processingData = false; + +let backup_on_failure = false;//== saveTelemetryOnError - create backup client 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; + +process.on('uncaughtException', function (err) { + + errLogger.error('uncaughtException:', err.message) + errLogger.error(err.stack); + + //TODO + //send to service + + //process.exit(1); +}) + +const nosql = NOSQL('tbdata'); +const nosqlBackup = NOSQL('/backup/tbdata'); + + +exports.install = function(instance) { + + var client; + var opts; + var clientReady = false; + + // wsmqtt status for notification purposes on projects.worksys.io database + let wsmqttName = null; + let sendWsStatusVar = null; + let wsmqtt_status = 'disconnected'; + + 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'; + } + + function sendWsStatus() + { + instance.send(SEND_TO.services, {[wsmqttName]: wsmqtt_status}); + } + + + function main() + { + if(!FLOW.dbLoaded) return; + + loadSettings(); + clearInterval(sendWsStatus); + sendWsStatusVar = setInterval(sendWsStatus, 180000); + } + + //set opts according to db settings + function loadSettings() + { + + if(instance.options.host !== "") + { + //override settings from database + var o = instance.options; + opts = { + host: o.host, + port: o.port, + clientId: o.clientid, + username: o.username, + rejectUnauthorized: false, + resubscribe: false + }; + + wsmqttName = getWsmqttName(o.host); + + console.log("wsmqttpublich -> loadSettings from instance.options", instance.options); + } + else + { + + const SETTINGS = FLOW.GLOBALS.settings; + backup_on_failure = SETTINGS.backup_on_failure; + saveTelemetryOnError = backup_on_failure; + + restore_from_backup = SETTINGS.restore_from_backup; + restore_backup_wait = SETTINGS.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; + + opts = { + host: mqtt_host, + port: mqtt_port, + keepalive: 10, + clientId: mqtt_clientid, + username: mqtt_username, + rejectUnauthorized: false, + resubscribe: false + }; + + wsmqttName = getWsmqttName(mqtt_host); + } + + connectToTbServer(); + } + + function connectToTbServer() + { + 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"); + monitor.info("MQTT client connected"); + + sendClientError = true; + clientReady = true; + wsmqtt_status = 'connected'; + }); + + client.on('reconnect', function() { + instance.status("Reconnecting", "yellow"); + clientReady = false; + }); + + client.on('message', function(topic, message) { + // message is type of buffer + message = message.toString(); + if (message[0] === '{') { + TRY(function() { + + message = JSON.parse(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}}); + } + + }, () => instance.debug('MQTT: Error parsing data', message)); + } + + instance.send(SEND_TO.rpcCall, {"topic":topic, "content":message }); + }); + + client.on('close', function() { + clientReady = false; + wsmqtt_status = 'disconnected'; + + instance.status("Disconnected", "red"); + instance.send(SEND_TO.debug, {"message":"Client CLOSE signal received !"}); + }); + + client.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; + wsmqtt_status = 'disconnected'; + }); + + } + + + instance.on("0", _ => { + main(); + }) + + + instance.on('1', function(data) { + + if(clientReady) + { + //do we have some data in backup file? if any, process data from database + if(saveTelemetryOnError) + { + //read telemetry data and send back to server + if(!processingData) processDataFromDatabase(); + } + + let stringifiedJson = JSON.stringify(data.data); + client.publish("v1/gateway/telemetry", stringifiedJson, {qos: 1}); + + //backup telemetry + if(createTelemetryBackup) + { + data.data.id = UID(); + nosqlBackup.insert(data.data); + + insertBackupNoSqlCounter++; + if(insertBackupNoSqlCounter > 150) + { + let options = {compress: true}; + let path = __dirname + "/../databases/backup/tbdata.nosql"; + var stream = new rollers.RollingFileStream(path, noSqlFileSizeLimit, 150, options); + stream.write(""); + stream.end(); + + insertBackupNoSqlCounter = 0; + } + } + + } + 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(saveTelemetryOnError) + { + //create new file from tbdata.nosql, if file size exceeds given limit, and clear tbdata.nosql + makeBackupFromDbFile(); + + //write to tb + data.data.id = UID(); + nosql.insert(data.data); + } + } + }); + + + instance.close = function(done) { + if(clientReady){ + client.end(); + clearInterval(sendWsStatusVar); + } + }; + + + function getDbBackupFileCounter(type) + { + var files = fs.readdirSync(__dirname + "/../databases"); + + let counter = 0; + for(var i = 0; i < files.length; i++) + { + + if(files[i] == "tbdata.nosql") continue; + + if(files[i].endsWith(".nosql")) + { + + let pos = files[i].indexOf("."); + if(pos > -1) + { + + let fileCounter = counter; + let firstDigit = files[i].slice(0, pos); + + fileCounter = parseInt(firstDigit); + if(isNaN(fileCounter)) fileCounter = 0; + //console.log("getDbBackupFileCounter digit:", files[i], firstDigit, fileCounter, isNaN(fileCounter), type); + + if(type == "max") + { + if(fileCounter > counter) + { + counter = fileCounter; + } + } + else if(type == "min") + { + if(counter == 0) counter = fileCounter; + + if(fileCounter < counter) + { + counter = fileCounter; + } + } + } + } + + } + + if(type == "max") counter++; + + return counter; + } + + const makeBackupFromDbFile = async () => { + + if(!saveTelemetryOnError) return; + + //to avoid large file: tbdata.nosql + + //init value is 0! + if(insertNoSqlCounter > 0) + { + --insertNoSqlCounter; + return; + } + + insertNoSqlCounter = 100; + + let source = __dirname + "/../databases/tbdata.nosql"; + + var stats = fs.statSync(source); + var fileSizeInBytes = stats.size; + + if(fileSizeInBytes > noSqlFileSizeLimit) + { + + let counter = 1; + counter = getDbBackupFileCounter("max"); + + let destination = __dirname + "/../databases/" + counter + "." + "tbdata.nosql"; + + //make backup file + fs.copyFileSync(source, destination); + //fs.renameSync(p, p + "." + counter); + + //clear tbdata.nosql + fs.writeFileSync(source, ""); + fs.truncateSync(source, 0); + + } + } + + const processDataFromDatabase = async () => { + + if(restore_from_backup <= 0) return; + + //calculate diff + const now = new Date(); + let currentTime = now.getTime(); + let diff = currentTime - lastRestoreTime; + + if( (diff / 1000) < restore_backup_wait) + { + //console.log("*********restore_backup_wait", diff, restore_backup_wait); + return; + } + + processingData = true; + + //get filename to process + let counter = getDbBackupFileCounter("min"); + + //we have some backup files + let dataBase = 'tbdata'; + + var nosql; + if(counter == 0) dataBase = 'tbdata'; + else dataBase = counter + "." + 'tbdata'; + + nosql = NOSQL(dataBase); + + //select all data - use limit restore_from_backup + let records = await promisifyBuilder(nosql.find().take(restore_from_backup)); + + for(let i = 0; i < records.length; i++) + { + if(clientReady) { + + let item = records[i]; + let id = item.id; + + if(id !== undefined) + { + //console.log("------------processDataFromDatabase - remove", id, dataBase, i); + + try { + + let message = JSON.parse(JSON.stringify(item)); + delete message.id; + + client.publish("v1/gateway/telemetry", JSON.stringify(message), {qos:1}); + + //remove from database + await promisifyBuilder(nosql.remove().where("id", id)); + + } catch(error) { + //process error + console.log("processDataFromDatabase", error); + } + + } + + } + else + { + processingData = false; + return; + } + } + + if(records.length > 0) + { + //clean backup file + if(counter > 0) nosql.clean(); + } + + //no data in db, remove + if(records.length == 0) + { + if(counter > 0) nosql.drop(); + } + + const d = new Date(); + lastRestoreTime = d.getTime(); + + processingData = false; + + } + + instance.on('options', main); + //instance.reconfigure(); +}; diff --git a/RVO35/monitor.txt b/RVO35/monitor.txt new file mode 100755 index 0000000..16ffafd --- /dev/null +++ b/RVO35/monitor.txt @@ -0,0 +1,1241 @@ +[2025-09-23T14:26:43.281] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-09-23T14:26:48.629] [INFO] monitorLogs - buildTasks - params undefined +[2025-09-23T14:26:48.634] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-09-23T14:26:48.635] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-09-23T14:26:48.635] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-23T14:26:48.639] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-23T14:26:48.641] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-09-24T05:09:00.640Z +[2025-09-23T14:26:48.642] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-09-23T17:19:00.642Z +[2025-09-23T14:26:48.643] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:9', name: 'luxOff' }, + { value: 1, start_time: '19:19', name: 'luxOn' } +] +[2025-09-23T14:26:48.644] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-09-23T14:26:48.645] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-09-23T14:26:48.645] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-23T14:26:48.648] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-23T14:26:48.649] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-09-24T05:09:00.648Z +[2025-09-23T14:26:48.650] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-09-23T17:19:00.649Z +[2025-09-23T14:26:48.650] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:9', name: 'luxOff' }, + { value: 1, start_time: '19:19', name: 'luxOn' } +] +[2025-09-23T14:26:48.651] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-09-23T14:26:48.652] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-09-23T14:26:48.653] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-23T14:26:48.655] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-23T14:26:48.655] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-09-24T05:09:00.655Z +[2025-09-23T14:26:48.656] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-09-23T17:19:00.656Z +[2025-09-23T14:26:48.657] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:9', name: 'luxOff' }, + { value: 1, start_time: '19:19', name: 'luxOn' } +] +[2025-09-23T14:26:48.658] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-09-23T14:26:48.659] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false No line profile. Switching it off on startup +[2025-09-23T14:26:48.661] [INFO] monitorLogs - buildTasks: profile for line 5 +[2025-09-23T14:26:48.662] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-23T14:26:48.665] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-23T14:26:48.665] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 5 2025-09-24T05:09:00.665Z +[2025-09-23T14:26:48.666] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 5 2025-09-23T17:19:00.666Z +[2025-09-23T14:26:48.667] [INFO] monitorLogs - -->time_points final 5 [ + { value: 0, start_time: '7:9', name: 'luxOff' }, + { value: 1, start_time: '19:19', name: 'luxOn' } +] +[2025-09-23T14:26:48.668] [INFO] monitorLogs - -->currentValue for relay 5 0 +[2025-09-23T14:26:48.668] [INFO] monitorLogs - buildTasks: profile for line 6 +[2025-09-23T14:26:48.669] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-23T14:26:48.671] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-23T14:26:48.672] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 6 2025-09-24T05:09:00.671Z +[2025-09-23T14:26:48.672] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 6 2025-09-23T17:19:00.672Z +[2025-09-23T14:26:48.673] [INFO] monitorLogs - -->time_points final 6 [ + { value: 0, start_time: '7:9', name: 'luxOff' }, + { value: 1, start_time: '19:19', name: 'luxOn' } +] +[2025-09-23T14:26:48.674] [INFO] monitorLogs - -->currentValue for relay 6 0 +[2025-09-23T14:26:48.697] [INFO] monitorLogs - tasks created: 1112 +[2025-09-23T14:26:48.700] [INFO] monitorLogs - -->FLOW bol spustený gP1eOZVj3Q9lv5aDEk45bM7rdpqW8yLm2BbKzJxM 2025-08-08 +[2025-09-23T14:26:53.707] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-23T18:54:01.278] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-23T18:54:01.286] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-23T18:54:01.289] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-23T18:54:01.292] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-09-23T18:54:01.294] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 6 relay1_07 false Profile: dusk - turnOn line according to lux sensor +[2025-09-24T03:26:49.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-24 03:26:49 +[2025-09-24T06:39:57.261] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-24T06:39:57.265] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-24T06:39:57.267] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-24T06:39:57.269] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-09-24T06:39:57.271] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 6 relay1_07 false Profile: dawn - turnOff line according to lux sensor +[2025-09-24T18:51:59.742] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-24T18:51:59.748] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-24T18:51:59.750] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-24T18:51:59.752] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-09-24T18:51:59.754] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 6 relay1_07 false Profile: dusk - turnOn line according to lux sensor +[2025-09-25T03:26:49.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-25 03:26:49 +[2025-09-25T06:42:59.762] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-25T06:42:59.766] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-25T06:42:59.768] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-25T06:42:59.771] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-09-25T06:42:59.773] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 6 relay1_07 false Profile: dawn - turnOff line according to lux sensor +[2025-09-25T16:24:58.967] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-09-25T16:25:04.311] [INFO] monitorLogs - buildTasks - params undefined +[2025-09-25T16:25:04.316] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-09-25T16:25:04.318] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-09-25T16:25:04.318] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-25T16:25:04.323] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-25T16:25:04.324] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-09-26T05:12:00.323Z +[2025-09-25T16:25:04.326] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-09-25T17:14:00.325Z +[2025-09-25T16:25:04.326] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:12', name: 'luxOff' }, + { value: 1, start_time: '19:14', name: 'luxOn' } +] +[2025-09-25T16:25:04.328] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-09-25T16:25:04.329] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-09-25T16:25:04.329] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-25T16:25:04.332] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-25T16:25:04.332] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-09-26T05:12:00.332Z +[2025-09-25T16:25:04.333] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-09-25T17:14:00.333Z +[2025-09-25T16:25:04.334] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:12', name: 'luxOff' }, + { value: 1, start_time: '19:14', name: 'luxOn' } +] +[2025-09-25T16:25:04.335] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-09-25T16:25:04.336] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-09-25T16:25:04.336] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-25T16:25:04.339] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-25T16:25:04.340] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-09-26T05:12:00.340Z +[2025-09-25T16:25:04.341] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-09-25T17:14:00.341Z +[2025-09-25T16:25:04.342] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:12', name: 'luxOff' }, + { value: 1, start_time: '19:14', name: 'luxOn' } +] +[2025-09-25T16:25:04.343] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-09-25T16:25:04.345] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false No line profile. Switching it off on startup +[2025-09-25T16:25:04.347] [INFO] monitorLogs - buildTasks: profile for line 5 +[2025-09-25T16:25:04.347] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-25T16:25:04.350] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-25T16:25:04.351] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 5 2025-09-26T05:12:00.351Z +[2025-09-25T16:25:04.352] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 5 2025-09-25T17:14:00.352Z +[2025-09-25T16:25:04.353] [INFO] monitorLogs - -->time_points final 5 [ + { value: 0, start_time: '7:12', name: 'luxOff' }, + { value: 1, start_time: '19:14', name: 'luxOn' } +] +[2025-09-25T16:25:04.354] [INFO] monitorLogs - -->currentValue for relay 5 0 +[2025-09-25T16:25:04.354] [INFO] monitorLogs - buildTasks: profile for line 6 +[2025-09-25T16:25:04.355] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-25T16:25:04.357] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-25T16:25:04.358] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 6 2025-09-26T05:12:00.357Z +[2025-09-25T16:25:04.359] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 6 2025-09-25T17:14:00.358Z +[2025-09-25T16:25:04.359] [INFO] monitorLogs - -->time_points final 6 [ + { value: 0, start_time: '7:12', name: 'luxOff' }, + { value: 1, start_time: '19:14', name: 'luxOn' } +] +[2025-09-25T16:25:04.360] [INFO] monitorLogs - -->currentValue for relay 6 0 +[2025-09-25T16:25:04.383] [INFO] monitorLogs - tasks created: 1112 +[2025-09-25T16:25:04.386] [INFO] monitorLogs - -->FLOW bol spustený gP1eOZVj3Q9lv5aDEk45bM7rdpqW8yLm2BbKzJxM 2025-08-08 +[2025-09-25T16:25:09.394] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-25T18:39:19.635] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-25T18:39:19.642] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-25T18:39:19.644] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-25T18:39:19.647] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-09-25T18:39:19.649] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 6 relay1_07 false Profile: dusk - turnOn line according to lux sensor +[2025-09-26T03:25:06.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-26 03:25:06 +[2025-09-26T06:37:50.352] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-26T06:37:50.356] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-26T06:37:50.358] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-26T06:37:50.360] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-09-26T06:37:50.362] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 6 relay1_07 false Profile: dawn - turnOff line according to lux sensor +[2025-09-26T18:55:32.020] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-26T18:55:32.025] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-26T18:55:32.028] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-26T18:55:32.030] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-09-26T18:55:32.032] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 6 relay1_07 false Profile: dusk - turnOn line according to lux sensor +[2025-09-27T03:25:06.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-27 03:25:06 +[2025-09-27T06:36:27.589] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-27T06:36:27.592] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-27T06:36:27.594] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-27T06:36:27.597] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-09-27T06:36:27.599] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 6 relay1_07 false Profile: dawn - turnOff line according to lux sensor +[2025-09-27T18:54:22.633] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-27T18:54:22.639] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-27T18:54:22.642] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-27T18:54:22.644] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-09-27T18:54:22.646] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 6 relay1_07 false Profile: dusk - turnOn line according to lux sensor +[2025-09-28T03:25:07.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-28 03:25:07 +[2025-09-28T06:36:02.056] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-28T06:36:02.059] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-28T06:36:02.061] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-28T06:36:02.063] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-09-28T06:36:02.065] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 6 relay1_07 false Profile: dawn - turnOff line according to lux sensor +[2025-09-28T18:53:20.615] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-28T18:53:20.618] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-28T18:53:20.620] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-28T18:53:20.622] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-09-28T18:53:20.623] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 6 relay1_07 false Profile: dusk - turnOn line according to lux sensor +[2025-09-29T03:25:08.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-29 03:25:08 +[2025-09-29T06:32:22.671] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-29T06:32:22.674] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-29T06:32:22.677] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-29T06:32:22.679] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-09-29T06:32:22.681] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 6 relay1_07 false Profile: dawn - turnOff line according to lux sensor +[2025-09-29T18:52:34.907] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-29T18:52:34.913] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-29T18:52:34.915] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-29T18:52:34.917] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-09-29T18:52:34.919] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 6 relay1_07 false Profile: dusk - turnOn line according to lux sensor +[2025-09-30T03:25:09.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-30 03:25:09 +[2025-09-30T06:33:29.160] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-30T06:33:29.164] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-30T06:33:29.166] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-30T06:33:29.168] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-09-30T06:33:29.171] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 6 relay1_07 false Profile: dawn - turnOff line according to lux sensor +[2025-09-30T09:30:12.158] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-09-30T09:30:17.511] [INFO] monitorLogs - buildTasks - params undefined +[2025-09-30T09:30:17.516] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-09-30T09:30:17.517] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-09-30T09:30:17.518] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-30T09:30:17.522] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-30T09:30:17.524] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-10-01T05:19:00.523Z +[2025-09-30T09:30:17.525] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-09-30T17:04:00.525Z +[2025-09-30T09:30:17.526] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:19', name: 'luxOff' }, + { value: 1, start_time: '19:4', name: 'luxOn' } +] +[2025-09-30T09:30:17.527] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-09-30T09:30:17.528] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-09-30T09:30:17.529] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-30T09:30:17.531] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-30T09:30:17.532] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-10-01T05:19:00.532Z +[2025-09-30T09:30:17.534] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-09-30T17:04:00.533Z +[2025-09-30T09:30:17.534] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:19', name: 'luxOff' }, + { value: 1, start_time: '19:4', name: 'luxOn' } +] +[2025-09-30T09:30:17.535] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-09-30T09:30:17.536] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-09-30T09:30:17.536] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-30T09:30:17.539] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-30T09:30:17.539] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-10-01T05:19:00.539Z +[2025-09-30T09:30:17.540] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-09-30T17:04:00.540Z +[2025-09-30T09:30:17.541] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:19', name: 'luxOff' }, + { value: 1, start_time: '19:4', name: 'luxOn' } +] +[2025-09-30T09:30:17.542] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-09-30T09:30:17.543] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false No line profile. Switching it off on startup +[2025-09-30T09:30:17.545] [INFO] monitorLogs - buildTasks: profile for line 5 +[2025-09-30T09:30:17.546] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-30T09:30:17.549] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-30T09:30:17.549] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 5 2025-10-01T05:19:00.549Z +[2025-09-30T09:30:17.550] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 5 2025-09-30T17:04:00.550Z +[2025-09-30T09:30:17.551] [INFO] monitorLogs - -->time_points final 5 [ + { value: 0, start_time: '7:19', name: 'luxOff' }, + { value: 1, start_time: '19:4', name: 'luxOn' } +] +[2025-09-30T09:30:17.552] [INFO] monitorLogs - -->currentValue for relay 5 0 +[2025-09-30T09:30:17.553] [INFO] monitorLogs - buildTasks: profile for line 6 +[2025-09-30T09:30:17.553] [INFO] monitorLogs - profile: { + 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 +} +[2025-09-30T09:30:17.555] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-30T09:30:17.556] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 6 2025-10-01T05:19:00.556Z +[2025-09-30T09:30:17.557] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 6 2025-09-30T17:04:00.556Z +[2025-09-30T09:30:17.557] [INFO] monitorLogs - -->time_points final 6 [ + { value: 0, start_time: '7:19', name: 'luxOff' }, + { value: 1, start_time: '19:4', name: 'luxOn' } +] +[2025-09-30T09:30:17.558] [INFO] monitorLogs - -->currentValue for relay 6 0 +[2025-09-30T09:30:17.581] [INFO] monitorLogs - tasks created: 1112 +[2025-09-30T09:30:17.584] [INFO] monitorLogs - -->FLOW bol spustený gP1eOZVj3Q9lv5aDEk45bM7rdpqW8yLm2BbKzJxM 2025-08-08 +[2025-09-30T09:30:22.594] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-30T18:50:20.636] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-30T18:50:20.642] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-30T18:50:20.644] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-30T18:50:20.647] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-09-30T18:50:20.649] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 6 relay1_07 false Profile: dusk - turnOn line according to lux sensor +[2025-10-01T03:30:19.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-01 03:30:19 +[2025-10-01T06:38:59.722] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-01T06:38:59.728] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-01T06:38:59.730] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-01T06:38:59.732] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-10-01T06:38:59.734] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 6 relay1_07 false Profile: dawn - turnOff line according to lux sensor +[2025-10-01T18:48:16.027] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-01T18:48:16.032] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-01T18:48:16.034] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-01T18:48:16.036] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-10-01T18:48:16.038] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 6 relay1_07 false Profile: dusk - turnOn line according to lux sensor +[2025-10-02T03:30:19.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-02 03:30:19 +[2025-10-02T06:38:22.586] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-02T06:38:22.590] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-02T06:38:22.592] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-02T06:38:22.594] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-10-02T06:38:22.597] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 6 relay1_07 false Profile: dawn - turnOff line according to lux sensor +[2025-10-02T18:46:51.922] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-02T18:46:51.928] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-02T18:46:51.930] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-02T18:46:51.932] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-10-02T18:46:51.934] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 6 relay1_07 false Profile: dusk - turnOn line according to lux sensor +[2025-10-03T03:30:20.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-03 03:30:20 +[2025-10-03T06:39:24.319] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-03T06:39:24.323] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-03T06:39:24.325] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-03T06:39:24.327] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-10-03T06:39:24.329] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 6 relay1_07 false Profile: dawn - turnOff line according to lux sensor +[2025-10-03T14:40:43.077] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-03T14:40:48.433] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-03T14:40:48.438] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-03T14:40:48.439] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-03T14:40:48.440] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-03T14:40:48.444] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-03T14:40:48.446] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-10-04T05:24:00.445Z +[2025-10-03T14:40:48.447] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-10-03T16:58:00.447Z +[2025-10-03T14:40:48.448] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:24', name: 'luxOff' }, + { value: 1, start_time: '18:58', name: 'luxOn' } +] +[2025-10-03T14:40:48.449] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-10-03T14:40:48.450] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-03T14:40:48.450] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-03T14:40:48.453] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-03T14:40:48.453] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-10-04T05:24:00.453Z +[2025-10-03T14:40:48.454] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-10-03T16:58:00.454Z +[2025-10-03T14:40:48.455] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:24', name: 'luxOff' }, + { value: 1, start_time: '18:58', name: 'luxOn' } +] +[2025-10-03T14:40:48.456] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-10-03T14:40:48.457] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-03T14:40:48.457] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-03T14:40:48.460] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-03T14:40:48.460] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-10-04T05:24:00.460Z +[2025-10-03T14:40:48.461] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-10-03T16:58:00.461Z +[2025-10-03T14:40:48.462] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:24', name: 'luxOff' }, + { value: 1, start_time: '18:58', name: 'luxOn' } +] +[2025-10-03T14:40:48.463] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-10-03T14:40:48.464] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false No line profile. Switching it off on startup +[2025-10-03T14:40:48.466] [INFO] monitorLogs - buildTasks: profile for line 5 +[2025-10-03T14:40:48.467] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-03T14:40:48.470] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-03T14:40:48.470] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 5 2025-10-04T05:24:00.470Z +[2025-10-03T14:40:48.471] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 5 2025-10-03T16:58:00.471Z +[2025-10-03T14:40:48.472] [INFO] monitorLogs - -->time_points final 5 [ + { value: 0, start_time: '7:24', name: 'luxOff' }, + { value: 1, start_time: '18:58', name: 'luxOn' } +] +[2025-10-03T14:40:48.473] [INFO] monitorLogs - -->currentValue for relay 5 0 +[2025-10-03T14:40:48.474] [INFO] monitorLogs - buildTasks: profile for line 6 +[2025-10-03T14:40:48.474] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-03T14:40:48.476] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-03T14:40:48.477] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 6 2025-10-04T05:24:00.477Z +[2025-10-03T14:40:48.478] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 6 2025-10-03T16:58:00.477Z +[2025-10-03T14:40:48.495] [INFO] monitorLogs - -->time_points final 6 [ + { value: 0, start_time: '7:24', name: 'luxOff' }, + { value: 1, start_time: '18:58', name: 'luxOn' } +] +[2025-10-03T14:40:48.496] [INFO] monitorLogs - -->currentValue for relay 6 0 +[2025-10-03T14:40:48.502] [INFO] monitorLogs - tasks created: 1112 +[2025-10-03T14:40:48.505] [INFO] monitorLogs - -->FLOW bol spustený gP1eOZVj3Q9lv5aDEk45bM7rdpqW8yLm2BbKzJxM 2025-08-08 +[2025-10-03T14:40:53.511] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-03T18:44:20.345] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-03T18:44:20.351] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-03T18:44:20.354] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-03T18:44:20.356] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-10-03T18:44:20.358] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 6 relay1_07 false Profile: dusk - turnOn line according to lux sensor +[2025-10-04T03:40:50.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-04 03:40:50 +[2025-10-04T06:40:44.148] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-04T06:40:44.153] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-04T06:40:44.155] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-04T06:40:44.158] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-10-04T06:40:44.160] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 6 relay1_07 false Profile: dawn - turnOff line according to lux sensor +[2025-10-04T18:33:09.283] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-04T18:33:09.289] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-04T18:33:09.291] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-04T18:33:09.293] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-10-04T18:33:09.295] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 6 relay1_07 false Profile: dusk - turnOn line according to lux sensor +[2025-10-05T03:40:51.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-05 03:40:51 +[2025-10-05T06:43:27.633] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-05T06:43:27.637] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-05T06:43:27.640] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-05T06:43:27.642] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-10-05T06:43:27.644] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 6 relay1_07 false Profile: dawn - turnOff line according to lux sensor +[2025-10-05T18:34:39.481] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-05T18:34:39.484] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-05T18:34:39.486] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-05T18:34:39.488] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-10-05T18:34:39.490] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 6 relay1_07 false Profile: dusk - turnOn line according to lux sensor +[2025-10-06T03:40:51.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-06 03:40:51 +[2025-10-06T06:52:36.762] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-06T06:52:36.765] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-06T06:52:36.767] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-06T06:52:36.770] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-10-06T06:52:36.771] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 6 relay1_07 false Profile: dawn - turnOff line according to lux sensor +[2025-10-06T18:24:59.971] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-06T18:24:59.973] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-06T18:24:59.975] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-06T18:24:59.977] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-10-06T18:24:59.979] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 6 relay1_07 false Profile: dusk - turnOn line according to lux sensor +[2025-10-07T03:40:52.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-07 03:40:52 +[2025-10-07T06:47:38.908] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-07T06:47:38.911] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-07T06:47:38.914] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-07T06:47:38.916] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-10-07T06:47:38.919] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 6 relay1_07 false Profile: dawn - turnOff line according to lux sensor +[2025-10-07T18:33:56.495] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-07T18:33:56.498] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-07T18:33:56.500] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-07T18:33:56.502] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-10-07T18:33:56.504] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 6 relay1_07 false Profile: dusk - turnOn line according to lux sensor +[2025-10-08T03:40:53.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-08 03:40:53 +[2025-10-08T06:46:35.619] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-08T06:46:35.622] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-08T06:46:35.625] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-08T06:46:35.627] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-10-08T06:46:35.629] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 6 relay1_07 false Profile: dawn - turnOff line according to lux sensor +[2025-10-08T18:31:22.745] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-08T18:31:22.748] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-08T18:31:22.749] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-08T18:31:22.752] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-10-08T18:31:22.753] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 6 relay1_07 false Profile: dusk - turnOn line according to lux sensor +[2025-10-09T03:40:54.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-09 03:40:54 +[2025-10-09T06:58:58.040] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-09T06:58:58.043] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-09T06:58:58.045] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-09T06:58:58.048] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-10-09T06:58:58.050] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 6 relay1_07 false Profile: dawn - turnOff line according to lux sensor +[2025-10-09T16:46:18.263] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-09T16:46:23.608] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-09T16:46:23.613] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-09T16:46:23.614] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-09T16:46:23.615] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-09T16:46:23.620] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T16:46:23.621] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-10-10T05:32:00.620Z +[2025-10-09T16:46:23.622] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-10-09T16:45:00.622Z +[2025-10-09T16:46:23.623] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T16:46:23.624] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-10-09T16:46:23.625] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-09T16:46:23.626] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-09T16:46:23.628] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T16:46:23.629] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-10-10T05:32:00.629Z +[2025-10-09T16:46:23.630] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-10-09T16:45:00.630Z +[2025-10-09T16:46:23.630] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T16:46:23.631] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-10-09T16:46:23.632] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-09T16:46:23.633] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-09T16:46:23.635] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T16:46:23.636] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-10-10T05:32:00.635Z +[2025-10-09T16:46:23.636] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-10-09T16:45:00.636Z +[2025-10-09T16:46:23.637] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T16:46:23.638] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-10-09T16:46:23.640] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false No line profile. Switching it off on startup +[2025-10-09T16:46:23.641] [INFO] monitorLogs - buildTasks: profile for line 5 +[2025-10-09T16:46:23.642] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-09T16:46:23.645] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T16:46:23.646] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 5 2025-10-10T05:32:00.645Z +[2025-10-09T16:46:23.646] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 5 2025-10-09T16:45:00.646Z +[2025-10-09T16:46:23.647] [INFO] monitorLogs - -->time_points final 5 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T16:46:23.648] [INFO] monitorLogs - -->currentValue for relay 5 0 +[2025-10-09T16:46:23.649] [INFO] monitorLogs - buildTasks: profile for line 6 +[2025-10-09T16:46:23.649] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-09T16:46:23.651] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T16:46:23.652] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 6 2025-10-10T05:32:00.652Z +[2025-10-09T16:46:23.653] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 6 2025-10-09T16:45:00.653Z +[2025-10-09T16:46:23.654] [INFO] monitorLogs - -->time_points final 6 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T16:46:23.655] [INFO] monitorLogs - -->currentValue for relay 6 0 +[2025-10-09T16:46:23.679] [INFO] monitorLogs - tasks created: 1112 +[2025-10-09T16:46:23.682] [INFO] monitorLogs - -->FLOW bol spustený gP1eOZVj3Q9lv5aDEk45bM7rdpqW8yLm2BbKzJxM 2025-08-08 +[2025-10-09T16:46:28.690] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-09T18:24:21.197] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-09T18:24:21.200] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-09T18:24:21.203] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-09T18:24:21.206] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-10-09T18:24:21.208] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 6 relay1_07 false Profile: dusk - turnOn line according to lux sensor +[2025-10-09T18:58:24.469] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-09T18:58:29.812] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-09T18:58:29.818] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-09T18:58:29.819] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-09T18:58:29.819] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-09T18:58:29.824] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T18:58:29.825] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-10-10T05:32:00.824Z +[2025-10-09T18:58:29.826] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-10-10T16:45:00.826Z +[2025-10-09T18:58:29.827] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T18:58:29.828] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-10-09T18:58:29.829] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-09T18:58:29.830] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-09T18:58:29.832] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T18:58:29.833] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-10-10T05:32:00.833Z +[2025-10-09T18:58:29.834] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-10-10T16:45:00.834Z +[2025-10-09T18:58:29.835] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T18:58:29.836] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-10-09T18:58:29.836] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-09T18:58:29.837] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-09T18:58:29.840] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T18:58:29.841] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-10-10T05:32:00.841Z +[2025-10-09T18:58:29.842] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-10-10T16:45:00.842Z +[2025-10-09T18:58:29.843] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T18:58:29.844] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-10-09T18:58:29.845] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false No line profile. Switching it off on startup +[2025-10-09T18:58:29.847] [INFO] monitorLogs - buildTasks: profile for line 5 +[2025-10-09T18:58:29.847] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-09T18:58:29.851] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T18:58:29.851] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 5 2025-10-10T05:32:00.851Z +[2025-10-09T18:58:29.852] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 5 2025-10-10T16:45:00.852Z +[2025-10-09T18:58:29.853] [INFO] monitorLogs - -->time_points final 5 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T18:58:29.854] [INFO] monitorLogs - -->currentValue for relay 5 1 +[2025-10-09T18:58:29.854] [INFO] monitorLogs - buildTasks: profile for line 6 +[2025-10-09T18:58:29.855] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-09T18:58:29.857] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T18:58:29.858] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 6 2025-10-10T05:32:00.858Z +[2025-10-09T18:58:29.859] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 6 2025-10-10T16:45:00.858Z +[2025-10-09T18:58:29.859] [INFO] monitorLogs - -->time_points final 6 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T18:58:29.860] [INFO] monitorLogs - -->currentValue for relay 6 1 +[2025-10-09T18:58:29.883] [INFO] monitorLogs - tasks created: 1112 +[2025-10-09T18:58:29.886] [INFO] monitorLogs - -->FLOW bol spustený gP1eOZVj3Q9lv5aDEk45bM7rdpqW8yLm2BbKzJxM 2025-08-08 +[2025-10-09T18:58:34.895] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-10T03:58:30.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-10 03:58:30 +[2025-10-10T06:56:38.158] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-10T06:56:38.161] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-10T06:56:38.164] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-10T06:56:38.167] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-10-10T06:56:38.169] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 6 relay1_07 false Profile: dawn - turnOff line according to lux sensor +[2025-10-10T18:19:01.444] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-10T18:19:01.450] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-10T18:19:01.452] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-10T18:19:01.454] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-10-10T18:19:01.456] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 6 relay1_07 false Profile: dusk - turnOn line according to lux sensor +[2025-10-11T03:58:31.018] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-11 03:58:31 +[2025-10-11T06:57:25.928] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-11T06:57:25.931] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-11T06:57:25.934] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-11T06:57:25.937] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-10-11T06:57:25.938] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 6 relay1_07 false Profile: dawn - turnOff line according to lux sensor +[2025-10-11T18:24:34.000] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-11T18:24:34.006] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-11T18:24:34.009] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-11T18:24:34.011] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-10-11T18:24:34.013] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 6 relay1_07 false Profile: dusk - turnOn line according to lux sensor +[2025-10-12T03:58:32.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-12 03:58:32 +[2025-10-12T06:57:19.195] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-12T06:57:19.198] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-12T06:57:19.200] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-12T06:57:19.202] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-10-12T06:57:19.204] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 6 relay1_07 false Profile: dawn - turnOff line according to lux sensor +[2025-10-12T18:19:48.439] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-12T18:19:48.442] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-12T18:19:48.444] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-12T18:19:48.447] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-10-12T18:19:48.448] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 6 relay1_07 false Profile: dusk - turnOn line according to lux sensor +[2025-10-13T03:58:33.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-13 03:58:33 +[2025-10-13T06:53:07.981] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-13T06:53:07.984] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-13T06:53:07.987] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-13T06:53:07.989] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-10-13T06:53:07.992] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 6 relay1_07 false Profile: dawn - turnOff line according to lux sensor +[2025-10-13T18:25:17.873] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-13T18:25:17.875] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-13T18:25:17.877] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-13T18:25:17.879] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-10-13T18:25:17.881] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 6 relay1_07 false Profile: dusk - turnOn line according to lux sensor +[2025-10-14T03:58:33.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-14 03:58:33 +[2025-10-14T06:55:01.115] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-14T06:55:01.118] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-14T06:55:01.120] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-14T06:55:01.123] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-10-14T06:55:01.125] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 6 relay1_07 false Profile: dawn - turnOff line according to lux sensor +[2025-10-14T18:15:58.842] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-14T18:15:58.844] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-14T18:15:58.846] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-14T18:15:58.848] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-10-14T18:15:58.850] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 6 relay1_07 false Profile: dusk - turnOn line according to lux sensor +[2025-10-15T03:58:34.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-15 03:58:34 +[2025-10-15T07:01:20.366] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-15T07:01:20.370] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-15T07:01:20.372] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-15T07:01:20.374] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-10-15T07:01:20.377] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 6 relay1_07 false Profile: dawn - turnOff line according to lux sensor +[2025-10-15T11:18:07.185] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-15T11:18:12.572] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-15T11:18:12.577] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-15T11:18:12.578] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-15T11:18:12.578] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-15T11:18:12.583] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-15T11:18:12.585] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-10-16T05:41:00.584Z +[2025-10-15T11:18:12.586] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-10-15T16:33:00.586Z +[2025-10-15T11:18:12.587] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:41', name: 'luxOff' }, + { value: 1, start_time: '18:33', name: 'luxOn' } +] +[2025-10-15T11:18:12.588] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-10-15T11:18:12.589] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-15T11:18:12.590] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-15T11:18:12.592] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-15T11:18:12.593] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-10-16T05:41:00.593Z +[2025-10-15T11:18:12.594] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-10-15T16:33:00.594Z +[2025-10-15T11:18:12.594] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:41', name: 'luxOff' }, + { value: 1, start_time: '18:33', name: 'luxOn' } +] +[2025-10-15T11:18:12.595] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-10-15T11:18:12.596] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-15T11:18:12.597] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-15T11:18:12.599] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-15T11:18:12.600] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-10-16T05:41:00.600Z +[2025-10-15T11:18:12.600] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-10-15T16:33:00.600Z +[2025-10-15T11:18:12.601] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:41', name: 'luxOff' }, + { value: 1, start_time: '18:33', name: 'luxOn' } +] +[2025-10-15T11:18:12.602] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-10-15T11:18:12.604] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false No line profile. Switching it off on startup +[2025-10-15T11:18:12.605] [INFO] monitorLogs - buildTasks: profile for line 5 +[2025-10-15T11:18:12.606] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-15T11:18:12.609] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-15T11:18:12.610] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 5 2025-10-16T05:41:00.610Z +[2025-10-15T11:18:12.611] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 5 2025-10-15T16:33:00.611Z +[2025-10-15T11:18:12.611] [INFO] monitorLogs - -->time_points final 5 [ + { value: 0, start_time: '7:41', name: 'luxOff' }, + { value: 1, start_time: '18:33', name: 'luxOn' } +] +[2025-10-15T11:18:12.613] [INFO] monitorLogs - -->currentValue for relay 5 0 +[2025-10-15T11:18:12.613] [INFO] monitorLogs - buildTasks: profile for line 6 +[2025-10-15T11:18:12.614] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-15T11:18:12.616] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-15T11:18:12.617] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 6 2025-10-16T05:41:00.616Z +[2025-10-15T11:18:12.617] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 6 2025-10-15T16:33:00.617Z +[2025-10-15T11:18:12.618] [INFO] monitorLogs - -->time_points final 6 [ + { value: 0, start_time: '7:41', name: 'luxOff' }, + { value: 1, start_time: '18:33', name: 'luxOn' } +] +[2025-10-15T11:18:12.619] [INFO] monitorLogs - -->currentValue for relay 6 0 +[2025-10-15T11:18:12.625] [INFO] monitorLogs - tasks created: 1112 +[2025-10-15T11:18:12.628] [INFO] monitorLogs - -->FLOW bol spustený gP1eOZVj3Q9lv5aDEk45bM7rdpqW8yLm2BbKzJxM 2025-10-08 +[2025-10-15T11:18:17.637] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-15T18:16:06.915] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-15T18:16:06.920] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-15T18:16:06.923] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-15T18:16:06.926] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-10-15T18:16:06.929] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 6 relay1_07 false Profile: dusk - turnOn line according to lux sensor diff --git a/RVO35/package-lock.json b/RVO35/package-lock.json new file mode 100755 index 0000000..cc5cfd9 --- /dev/null +++ b/RVO35/package-lock.json @@ -0,0 +1,2125 @@ +{ + "name": "emptyproject", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "emptyproject", + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "bitwise": "^2.1.0", + "easy-crc": "0.0.2", + "jsmodbus": "^4.0.6", + "log4js": "^6.3.0", + "mqtt": "^4.2.6", + "nodemailer": "^6.9.7", + "serialport": "^9.2.8", + "total.js": "^3.4.13" + } + }, + "node_modules/@serialport/binding-abstract": { + "version": "9.2.3", + "resolved": "https://registry.npmjs.org/@serialport/binding-abstract/-/binding-abstract-9.2.3.tgz", + "integrity": "sha512-cQs9tbIlG3P0IrOWyVirqlhWuJ7Ms2Zh9m2108z6Y5UW/iVj6wEOiW8EmK9QX9jmJXYllE7wgGgvVozP5oCj3w==", + "dependencies": { + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/binding-mock": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/binding-mock/-/binding-mock-9.2.4.tgz", + "integrity": "sha512-dpEhACCs44oQhh6ajJfJdvQdK38Vq0N4W6iD/gdplglDCK7qXRQCMUjJIeKdS/HSEiWkC3bwumUhUufdsOyT4g==", + "dependencies": { + "@serialport/binding-abstract": "9.2.3", + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/bindings": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/@serialport/bindings/-/bindings-9.2.8.tgz", + "integrity": "sha512-hSLxTe0tADZ3LMMGwvEJWOC/TaFQTyPeFalUCsJ1lSQ0k6bPF04JwrtB/C81GetmDBTNRY0GlD0SNtKCc7Dr5g==", + "hasInstallScript": true, + "dependencies": { + "@serialport/binding-abstract": "9.2.3", + "@serialport/parser-readline": "9.2.4", + "bindings": "^1.5.0", + "debug": "^4.3.2", + "nan": "^2.15.0", + "prebuild-install": "^7.0.0" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-byte-length": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-byte-length/-/parser-byte-length-9.2.4.tgz", + "integrity": "sha512-sQD/iw4ZMU3xW9PLi0/GlvU6Y623jGeWecbMkO7izUo/6P7gtfv1c9ikd5h0kwL8AoAOpQA1lxdHIKox+umBUg==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-cctalk": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-cctalk/-/parser-cctalk-9.2.4.tgz", + "integrity": "sha512-T4TU5vQMwmo9AB3gQLFDWbfJXlW5jd9guEsB/nqKjFHTv0FXPdZ7DQ2TpSp8RnHWxU3GX6kYTaDO20BKzc8GPQ==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-delimiter": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-delimiter/-/parser-delimiter-9.2.4.tgz", + "integrity": "sha512-4nvTAoYAgkxFiXrkI+3CA49Yd43CODjeszh89EK+I9c8wOZ+etZduRCzINYPiy26g7zO+GRAb9FoPCsY+sYcbQ==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-inter-byte-timeout": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-inter-byte-timeout/-/parser-inter-byte-timeout-9.2.4.tgz", + "integrity": "sha512-SOAdvr0oBQIOCXX198hiTlxs4JTKg9j5piapw5tNq52fwDOWdbYrFneT/wN04UTMKaDrJuEvXq6T4rv4j7nJ5A==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-readline": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-readline/-/parser-readline-9.2.4.tgz", + "integrity": "sha512-Z1/qrZTQUVhNSJP1hd9YfDvq0o7d87rNwAjjRKbVpa7Qi51tG5BnKt43IV3NFMyBlVcRe0rnIb3tJu57E0SOwg==", + "dependencies": { + "@serialport/parser-delimiter": "9.2.4" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-ready": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-ready/-/parser-ready-9.2.4.tgz", + "integrity": "sha512-Pyi94Itjl6qAURwIZr/gmZpMAyTmKXThm6vL5DoAWGQjcRHWB0gwv2TY2v7N+mQLJYUKU3cMnvnATXxHm7xjxw==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-regex": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-regex/-/parser-regex-9.2.4.tgz", + "integrity": "sha512-sI/cVvPOYz+Dbv4ZdnW16qAwvXiFf/1pGASQdbveRTlgJDdz7sRNlCBifzfTN2xljwvCTZYqiudKvDdC1TepRQ==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/stream": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/stream/-/stream-9.2.4.tgz", + "integrity": "sha512-bLye8Ub4vUFQGmkh8qEqehr7SE7EJs2yDs0h9jzuL5oKi+F34CFmWkEErO8GAOQ8YNn7p6b3GxUgs+0BrHHDZQ==", + "dependencies": { + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "node_modules/are-we-there-yet": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", + "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/base64-js": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", + "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==" + }, + "node_modules/bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "dependencies": { + "file-uri-to-path": "1.0.0" + } + }, + "node_modules/bitwise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/bitwise/-/bitwise-2.1.0.tgz", + "integrity": "sha512-XKgAhMXCh4H/3oNwAHAsAO0iC89s9cOiumgYwSHjSobGWxYjv62YhkL9QEdvGP151xypCtMlAfKK79GEcd2eRQ==" + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/bl/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/buffer": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz", + "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==", + "dependencies": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + }, + "node_modules/buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" + }, + "node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, + "node_modules/code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/commist": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/commist/-/commist-1.1.0.tgz", + "integrity": "sha512-rraC8NXWOEjhADbZe9QBNzLAN5Q3fsTPQtBV+fEVj6xKIgDgNiEVE6ZNfHpZOqfQ21YUzfVNUXLOEZquYvQPPg==", + "dependencies": { + "leven": "^2.1.0", + "minimist": "^1.1.0" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "node_modules/concat-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", + "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", + "engines": [ + "node >= 6.0" + ], + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.0.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/concat-stream/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" + }, + "node_modules/core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "node_modules/crc": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/crc/-/crc-3.4.0.tgz", + "integrity": "sha512-ycVC2+4/DLgXXq7QweYi2znhqDuZz6P5TQXnkQo8v15XY/5p/IWeZwsSE31Ifo8w15b8TWLsqhXOjXyilHuQxw==" + }, + "node_modules/date-format": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.11.tgz", + "integrity": "sha512-VS20KRyorrbMCQmpdl2hg5KaOUsda1RbnsJg461FfrcyCUg+pkd0b40BSW4niQyTheww4DBXQnS7HwSrKkipLw==", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" + }, + "node_modules/detect-libc": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz", + "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==", + "engines": { + "node": ">=8" + } + }, + "node_modules/duplexify": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.2.tgz", + "integrity": "sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw==", + "dependencies": { + "end-of-stream": "^1.4.1", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1", + "stream-shift": "^1.0.0" + } + }, + "node_modules/duplexify/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/easy-crc": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/easy-crc/-/easy-crc-0.0.2.tgz", + "integrity": "sha512-h6eqIdhJRe0p271/xZJbM/0klCi13mW5IB7ZEzEGH11yV4QXWAkD4yPErz0fXdhFrd6sZ4Q1k5Iky2kMsMNePw==" + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" + }, + "node_modules/flatted": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", + "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==" + }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, + "node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "node_modules/gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha512-14x4kjc6lkD3ltw589k0NrPD6cCNTD6CWoVUNpB85+DrtONoZn+Rug6xZU5RvSC4+TZPxA5AnBibQYAvZn41Hg==", + "dependencies": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "node_modules/github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==" + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" + }, + "node_modules/has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" + }, + "node_modules/help-me": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/help-me/-/help-me-3.0.0.tgz", + "integrity": "sha512-hx73jClhyk910sidBB7ERlnhMlFsJJIBqSVMFDwPN8o2v9nmp5KgLq1Xz1Bf1fCMMZ6mPrX159iG0VLy/fPMtQ==", + "dependencies": { + "glob": "^7.1.6", + "readable-stream": "^3.6.0" + } + }, + "node_modules/help-me/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, + "node_modules/is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==", + "dependencies": { + "number-is-nan": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "node_modules/js-sdsl": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz", + "integrity": "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/js-sdsl" + } + }, + "node_modules/jsmodbus": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/jsmodbus/-/jsmodbus-4.0.6.tgz", + "integrity": "sha512-gCmjoaERErK5Rn9Lu/BN07fY13MoWV7JKgGzrnkPlQPdPxYcwDhLtYcmpFFpZ4J9NPZZBSezi1UkLZO/DnNppA==", + "dependencies": { + "crc": "3.4.0", + "debug": "^3.1.0" + }, + "bin": { + "jsmodbus": "bin/jsmodbus.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/jsmodbus/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/leven": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", + "integrity": "sha1-wuep93IJTe6dNCAq6KzORoeHVYA=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/log4js": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.5.2.tgz", + "integrity": "sha512-DXtpNtt+KDOMT7RHUDIur/WsSA3rntlUh9Zg4XCdV42wUuMmbFkl38+LZ92Z5QvQA7mD5kAVkLiBSEH/tvUB8A==", + "dependencies": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "flatted": "^3.2.5", + "rfdc": "^1.3.0", + "streamroller": "^3.1.1" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" + }, + "node_modules/mqtt": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/mqtt/-/mqtt-4.3.7.tgz", + "integrity": "sha512-ew3qwG/TJRorTz47eW46vZ5oBw5MEYbQZVaEji44j5lAUSQSqIEoul7Kua/BatBW0H0kKQcC9kwUHa1qzaWHSw==", + "dependencies": { + "commist": "^1.0.0", + "concat-stream": "^2.0.0", + "debug": "^4.1.1", + "duplexify": "^4.1.1", + "help-me": "^3.0.0", + "inherits": "^2.0.3", + "lru-cache": "^6.0.0", + "minimist": "^1.2.5", + "mqtt-packet": "^6.8.0", + "number-allocator": "^1.0.9", + "pump": "^3.0.0", + "readable-stream": "^3.6.0", + "reinterval": "^1.1.0", + "rfdc": "^1.3.0", + "split2": "^3.1.0", + "ws": "^7.5.5", + "xtend": "^4.0.2" + }, + "bin": { + "mqtt": "bin/mqtt.js", + "mqtt_pub": "bin/pub.js", + "mqtt_sub": "bin/sub.js" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/mqtt-packet": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/mqtt-packet/-/mqtt-packet-6.10.0.tgz", + "integrity": "sha512-ja8+mFKIHdB1Tpl6vac+sktqy3gA8t9Mduom1BA75cI+R9AHnZOiaBQwpGiWnaVJLDGRdNhQmFaAqd7tkKSMGA==", + "dependencies": { + "bl": "^4.0.2", + "debug": "^4.1.1", + "process-nextick-args": "^2.0.1" + } + }, + "node_modules/mqtt/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/nan": { + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.16.0.tgz", + "integrity": "sha512-UdAqHyFngu7TfQKsCBgAA6pWDkT8MAO7d0jyOecVhN5354xbLqdn8mV9Tat9gepAupm0bt2DbeaSC8vS52MuFA==" + }, + "node_modules/napi-build-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", + "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==" + }, + "node_modules/node-abi": { + "version": "3.22.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.22.0.tgz", + "integrity": "sha512-u4uAs/4Zzmp/jjsD9cyFYDXeISfUWaAVWshPmDZOFOv4Xl4SbzTXm53I04C2uRueYJ+0t5PEtLH/owbn2Npf/w==", + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/nodemailer": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.7.tgz", + "integrity": "sha512-rUtR77ksqex/eZRLmQ21LKVH5nAAsVicAtAYudK7JgwenEDZ0UIQ1adUGqErz7sMkWYxWTTU1aeP2Jga6WQyJw==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "dependencies": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "node_modules/number-allocator": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/number-allocator/-/number-allocator-1.0.14.tgz", + "integrity": "sha512-OrL44UTVAvkKdOdRQZIJpLkAdjXGTRda052sN4sO77bKEzYYqWKMBjQvrJFzqygI99gL6Z4u2xctPW1tB8ErvA==", + "dependencies": { + "debug": "^4.3.1", + "js-sdsl": "4.3.0" + } + }, + "node_modules/number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/prebuild-install": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.0.tgz", + "integrity": "sha512-CNcMgI1xBypOyGqjp3wOc8AAo1nMhZS3Cwd3iHIxOdAUbb+YxdNuM4Z5iIrZ8RLvOsf3F3bl7b7xGq6DjQoNYA==", + "dependencies": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^1.0.1", + "node-abi": "^3.3.0", + "npmlog": "^4.0.1", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + }, + "bin": { + "prebuild-install": "bin.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/reinterval": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reinterval/-/reinterval-1.1.0.tgz", + "integrity": "sha1-M2Hs+jymwYKDOA3Qu5VG85D17Oc=" + }, + "node_modules/rfdc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==" + }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/serialport": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/serialport/-/serialport-9.2.8.tgz", + "integrity": "sha512-FsWpMQgSJxi93JgWl5xM1f9/Z8IjRJuaUEoHqLf8FPBLw7gMhInuHOBhI2onQufWIYPGTz3H3oGcu1nCaK1EfA==", + "dependencies": { + "@serialport/binding-mock": "9.2.4", + "@serialport/bindings": "9.2.8", + "@serialport/parser-byte-length": "9.2.4", + "@serialport/parser-cctalk": "9.2.4", + "@serialport/parser-delimiter": "9.2.4", + "@serialport/parser-inter-byte-timeout": "9.2.4", + "@serialport/parser-readline": "9.2.4", + "@serialport/parser-ready": "9.2.4", + "@serialport/parser-regex": "9.2.4", + "@serialport/stream": "9.2.4", + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "node_modules/split2": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", + "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", + "dependencies": { + "readable-stream": "^3.0.0" + } + }, + "node_modules/split2/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==" + }, + "node_modules/streamroller": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.1.1.tgz", + "integrity": "sha512-iPhtd9unZ6zKdWgMeYGfSBuqCngyJy1B/GPi/lTpwGpa3bajuX30GjUVd0/Tn/Xhg0mr4DOSENozz9Y06qyonQ==", + "dependencies": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "fs-extra": "^10.1.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dependencies": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/tar-fs": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "dependencies": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tar-stream/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/total.js": { + "version": "3.4.13", + "resolved": "https://registry.npmjs.org/total.js/-/total.js-3.4.13.tgz", + "integrity": "sha512-lAH4gEixlPFbrE3xfKADAcHfO79IFq2wKa9GTsrgRzIR5MTg3mNH7+4IxvX1pK8faoYb/0oYSJ1YTsAa5hIFFQ==", + "bin": { + "total": "bin/totaljs", + "total.js": "bin/totaljs", + "totaljs": "bin/totaljs", + "totalpackage": "bin/tpm", + "tpm": "bin/tpm" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, + "node_modules/universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "node_modules/wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "node_modules/ws": { + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } + }, + "dependencies": { + "@serialport/binding-abstract": { + "version": "9.2.3", + "resolved": "https://registry.npmjs.org/@serialport/binding-abstract/-/binding-abstract-9.2.3.tgz", + "integrity": "sha512-cQs9tbIlG3P0IrOWyVirqlhWuJ7Ms2Zh9m2108z6Y5UW/iVj6wEOiW8EmK9QX9jmJXYllE7wgGgvVozP5oCj3w==", + "requires": { + "debug": "^4.3.2" + } + }, + "@serialport/binding-mock": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/binding-mock/-/binding-mock-9.2.4.tgz", + "integrity": "sha512-dpEhACCs44oQhh6ajJfJdvQdK38Vq0N4W6iD/gdplglDCK7qXRQCMUjJIeKdS/HSEiWkC3bwumUhUufdsOyT4g==", + "requires": { + "@serialport/binding-abstract": "9.2.3", + "debug": "^4.3.2" + } + }, + "@serialport/bindings": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/@serialport/bindings/-/bindings-9.2.8.tgz", + "integrity": "sha512-hSLxTe0tADZ3LMMGwvEJWOC/TaFQTyPeFalUCsJ1lSQ0k6bPF04JwrtB/C81GetmDBTNRY0GlD0SNtKCc7Dr5g==", + "requires": { + "@serialport/binding-abstract": "9.2.3", + "@serialport/parser-readline": "9.2.4", + "bindings": "^1.5.0", + "debug": "^4.3.2", + "nan": "^2.15.0", + "prebuild-install": "^7.0.0" + } + }, + "@serialport/parser-byte-length": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-byte-length/-/parser-byte-length-9.2.4.tgz", + "integrity": "sha512-sQD/iw4ZMU3xW9PLi0/GlvU6Y623jGeWecbMkO7izUo/6P7gtfv1c9ikd5h0kwL8AoAOpQA1lxdHIKox+umBUg==" + }, + "@serialport/parser-cctalk": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-cctalk/-/parser-cctalk-9.2.4.tgz", + "integrity": "sha512-T4TU5vQMwmo9AB3gQLFDWbfJXlW5jd9guEsB/nqKjFHTv0FXPdZ7DQ2TpSp8RnHWxU3GX6kYTaDO20BKzc8GPQ==" + }, + "@serialport/parser-delimiter": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-delimiter/-/parser-delimiter-9.2.4.tgz", + "integrity": "sha512-4nvTAoYAgkxFiXrkI+3CA49Yd43CODjeszh89EK+I9c8wOZ+etZduRCzINYPiy26g7zO+GRAb9FoPCsY+sYcbQ==" + }, + "@serialport/parser-inter-byte-timeout": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-inter-byte-timeout/-/parser-inter-byte-timeout-9.2.4.tgz", + "integrity": "sha512-SOAdvr0oBQIOCXX198hiTlxs4JTKg9j5piapw5tNq52fwDOWdbYrFneT/wN04UTMKaDrJuEvXq6T4rv4j7nJ5A==" + }, + "@serialport/parser-readline": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-readline/-/parser-readline-9.2.4.tgz", + "integrity": "sha512-Z1/qrZTQUVhNSJP1hd9YfDvq0o7d87rNwAjjRKbVpa7Qi51tG5BnKt43IV3NFMyBlVcRe0rnIb3tJu57E0SOwg==", + "requires": { + "@serialport/parser-delimiter": "9.2.4" + } + }, + "@serialport/parser-ready": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-ready/-/parser-ready-9.2.4.tgz", + "integrity": "sha512-Pyi94Itjl6qAURwIZr/gmZpMAyTmKXThm6vL5DoAWGQjcRHWB0gwv2TY2v7N+mQLJYUKU3cMnvnATXxHm7xjxw==" + }, + "@serialport/parser-regex": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-regex/-/parser-regex-9.2.4.tgz", + "integrity": "sha512-sI/cVvPOYz+Dbv4ZdnW16qAwvXiFf/1pGASQdbveRTlgJDdz7sRNlCBifzfTN2xljwvCTZYqiudKvDdC1TepRQ==" + }, + "@serialport/stream": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/stream/-/stream-9.2.4.tgz", + "integrity": "sha512-bLye8Ub4vUFQGmkh8qEqehr7SE7EJs2yDs0h9jzuL5oKi+F34CFmWkEErO8GAOQ8YNn7p6b3GxUgs+0BrHHDZQ==", + "requires": { + "debug": "^4.3.2" + } + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==" + }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "are-we-there-yet": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", + "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "base64-js": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", + "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==" + }, + "bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "requires": { + "file-uri-to-path": "1.0.0" + } + }, + "bitwise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/bitwise/-/bitwise-2.1.0.tgz", + "integrity": "sha512-XKgAhMXCh4H/3oNwAHAsAO0iC89s9cOiumgYwSHjSobGWxYjv62YhkL9QEdvGP151xypCtMlAfKK79GEcd2eRQ==" + }, + "bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "requires": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "buffer": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz", + "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==", + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" + }, + "chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==" + }, + "commist": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/commist/-/commist-1.1.0.tgz", + "integrity": "sha512-rraC8NXWOEjhADbZe9QBNzLAN5Q3fsTPQtBV+fEVj6xKIgDgNiEVE6ZNfHpZOqfQ21YUzfVNUXLOEZquYvQPPg==", + "requires": { + "leven": "^2.1.0", + "minimist": "^1.1.0" + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "concat-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", + "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.0.2", + "typedarray": "^0.0.6" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "crc": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/crc/-/crc-3.4.0.tgz", + "integrity": "sha512-ycVC2+4/DLgXXq7QweYi2znhqDuZz6P5TQXnkQo8v15XY/5p/IWeZwsSE31Ifo8w15b8TWLsqhXOjXyilHuQxw==" + }, + "date-format": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.11.tgz", + "integrity": "sha512-VS20KRyorrbMCQmpdl2hg5KaOUsda1RbnsJg461FfrcyCUg+pkd0b40BSW4niQyTheww4DBXQnS7HwSrKkipLw==" + }, + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "requires": { + "ms": "2.1.2" + } + }, + "decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "requires": { + "mimic-response": "^3.1.0" + } + }, + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==" + }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" + }, + "detect-libc": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz", + "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==" + }, + "duplexify": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.2.tgz", + "integrity": "sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw==", + "requires": { + "end-of-stream": "^1.4.1", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1", + "stream-shift": "^1.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "easy-crc": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/easy-crc/-/easy-crc-0.0.2.tgz", + "integrity": "sha512-h6eqIdhJRe0p271/xZJbM/0klCi13mW5IB7ZEzEGH11yV4QXWAkD4yPErz0fXdhFrd6sZ4Q1k5Iky2kMsMNePw==" + }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "requires": { + "once": "^1.4.0" + } + }, + "expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==" + }, + "file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" + }, + "flatted": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", + "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==" + }, + "fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, + "fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha512-14x4kjc6lkD3ltw589k0NrPD6cCNTD6CWoVUNpB85+DrtONoZn+Rug6xZU5RvSC4+TZPxA5AnBibQYAvZn41Hg==", + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==" + }, + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" + }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" + }, + "help-me": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/help-me/-/help-me-3.0.0.tgz", + "integrity": "sha512-hx73jClhyk910sidBB7ERlnhMlFsJJIBqSVMFDwPN8o2v9nmp5KgLq1Xz1Bf1fCMMZ6mPrX159iG0VLy/fPMtQ==", + "requires": { + "glob": "^7.1.6", + "readable-stream": "^3.6.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==", + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "js-sdsl": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz", + "integrity": "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==" + }, + "jsmodbus": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/jsmodbus/-/jsmodbus-4.0.6.tgz", + "integrity": "sha512-gCmjoaERErK5Rn9Lu/BN07fY13MoWV7JKgGzrnkPlQPdPxYcwDhLtYcmpFFpZ4J9NPZZBSezi1UkLZO/DnNppA==", + "requires": { + "crc": "3.4.0", + "debug": "^3.1.0" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "requires": { + "ms": "^2.1.1" + } + } + } + }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, + "leven": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", + "integrity": "sha1-wuep93IJTe6dNCAq6KzORoeHVYA=" + }, + "log4js": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.5.2.tgz", + "integrity": "sha512-DXtpNtt+KDOMT7RHUDIur/WsSA3rntlUh9Zg4XCdV42wUuMmbFkl38+LZ92Z5QvQA7mD5kAVkLiBSEH/tvUB8A==", + "requires": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "flatted": "^3.2.5", + "rfdc": "^1.3.0", + "streamroller": "^3.1.1" + } + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "requires": { + "yallist": "^4.0.0" + } + }, + "mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==" + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==" + }, + "mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" + }, + "mqtt": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/mqtt/-/mqtt-4.3.7.tgz", + "integrity": "sha512-ew3qwG/TJRorTz47eW46vZ5oBw5MEYbQZVaEji44j5lAUSQSqIEoul7Kua/BatBW0H0kKQcC9kwUHa1qzaWHSw==", + "requires": { + "commist": "^1.0.0", + "concat-stream": "^2.0.0", + "debug": "^4.1.1", + "duplexify": "^4.1.1", + "help-me": "^3.0.0", + "inherits": "^2.0.3", + "lru-cache": "^6.0.0", + "minimist": "^1.2.5", + "mqtt-packet": "^6.8.0", + "number-allocator": "^1.0.9", + "pump": "^3.0.0", + "readable-stream": "^3.6.0", + "reinterval": "^1.1.0", + "rfdc": "^1.3.0", + "split2": "^3.1.0", + "ws": "^7.5.5", + "xtend": "^4.0.2" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "mqtt-packet": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/mqtt-packet/-/mqtt-packet-6.10.0.tgz", + "integrity": "sha512-ja8+mFKIHdB1Tpl6vac+sktqy3gA8t9Mduom1BA75cI+R9AHnZOiaBQwpGiWnaVJLDGRdNhQmFaAqd7tkKSMGA==", + "requires": { + "bl": "^4.0.2", + "debug": "^4.1.1", + "process-nextick-args": "^2.0.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "nan": { + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.16.0.tgz", + "integrity": "sha512-UdAqHyFngu7TfQKsCBgAA6pWDkT8MAO7d0jyOecVhN5354xbLqdn8mV9Tat9gepAupm0bt2DbeaSC8vS52MuFA==" + }, + "napi-build-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", + "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==" + }, + "node-abi": { + "version": "3.22.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.22.0.tgz", + "integrity": "sha512-u4uAs/4Zzmp/jjsD9cyFYDXeISfUWaAVWshPmDZOFOv4Xl4SbzTXm53I04C2uRueYJ+0t5PEtLH/owbn2Npf/w==", + "requires": { + "semver": "^7.3.5" + } + }, + "nodemailer": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.7.tgz", + "integrity": "sha512-rUtR77ksqex/eZRLmQ21LKVH5nAAsVicAtAYudK7JgwenEDZ0UIQ1adUGqErz7sMkWYxWTTU1aeP2Jga6WQyJw==" + }, + "npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "number-allocator": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/number-allocator/-/number-allocator-1.0.14.tgz", + "integrity": "sha512-OrL44UTVAvkKdOdRQZIJpLkAdjXGTRda052sN4sO77bKEzYYqWKMBjQvrJFzqygI99gL6Z4u2xctPW1tB8ErvA==", + "requires": { + "debug": "^4.3.1", + "js-sdsl": "4.3.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==" + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==" + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==" + }, + "prebuild-install": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.0.tgz", + "integrity": "sha512-CNcMgI1xBypOyGqjp3wOc8AAo1nMhZS3Cwd3iHIxOdAUbb+YxdNuM4Z5iIrZ8RLvOsf3F3bl7b7xGq6DjQoNYA==", + "requires": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^1.0.1", + "node-abi": "^3.3.0", + "npmlog": "^4.0.1", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + } + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + } + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "reinterval": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reinterval/-/reinterval-1.1.0.tgz", + "integrity": "sha1-M2Hs+jymwYKDOA3Qu5VG85D17Oc=" + }, + "rfdc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==" + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "requires": { + "lru-cache": "^6.0.0" + } + }, + "serialport": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/serialport/-/serialport-9.2.8.tgz", + "integrity": "sha512-FsWpMQgSJxi93JgWl5xM1f9/Z8IjRJuaUEoHqLf8FPBLw7gMhInuHOBhI2onQufWIYPGTz3H3oGcu1nCaK1EfA==", + "requires": { + "@serialport/binding-mock": "9.2.4", + "@serialport/bindings": "9.2.8", + "@serialport/parser-byte-length": "9.2.4", + "@serialport/parser-cctalk": "9.2.4", + "@serialport/parser-delimiter": "9.2.4", + "@serialport/parser-inter-byte-timeout": "9.2.4", + "@serialport/parser-readline": "9.2.4", + "@serialport/parser-ready": "9.2.4", + "@serialport/parser-regex": "9.2.4", + "@serialport/stream": "9.2.4", + "debug": "^4.3.2" + } + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==" + }, + "simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "requires": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "split2": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", + "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", + "requires": { + "readable-stream": "^3.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==" + }, + "streamroller": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.1.1.tgz", + "integrity": "sha512-iPhtd9unZ6zKdWgMeYGfSBuqCngyJy1B/GPi/lTpwGpa3bajuX30GjUVd0/Tn/Xhg0mr4DOSENozz9Y06qyonQ==", + "requires": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "fs-extra": "^10.1.0" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" + }, + "tar-fs": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "requires": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "requires": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "total.js": { + "version": "3.4.13", + "resolved": "https://registry.npmjs.org/total.js/-/total.js-3.4.13.tgz", + "integrity": "sha512-lAH4gEixlPFbrE3xfKADAcHfO79IFq2wKa9GTsrgRzIR5MTg3mNH7+4IxvX1pK8faoYb/0oYSJ1YTsAa5hIFFQ==" + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, + "universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==" + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "requires": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "ws": { + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "requires": {} + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } + } +} diff --git a/RVO35/package.json b/RVO35/package.json new file mode 100755 index 0000000..e524d7c --- /dev/null +++ b/RVO35/package.json @@ -0,0 +1,29 @@ +{ + "name": "emptyproject", + "description": "Total.js empty project.", + "version": "1.0.0", + "main": "debug.js", + "dependencies": { + "bitwise": "^2.1.0", + "easy-crc": "0.0.2", + "jsmodbus": "^4.0.6", + "log4js": "^6.3.0", + "mqtt": "^4.2.6", + "nodemailer": "^6.9.7", + "serialport": "^9.2.8", + "total.js": "^3.4.13" + }, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "https://github.com/totaljs/emptyproject-flow" + }, + "keywords": [ + "empty", + "project" + ], + "author": "Peter Širka", + "license": "MIT" +} diff --git a/RVO35/release.js b/RVO35/release.js new file mode 100755 index 0000000..02d52ff --- /dev/null +++ b/RVO35/release.js @@ -0,0 +1,15 @@ +// =================================================== +// FOR PRODUCTION +// Total.js - framework for Node.js platform +// https://www.totaljs.com +// =================================================== + +const options = {'ip':'0.0.0.0', 'port':12345}; + +// options.ip = '127.0.0.1'; +// options.port = parseInt(process.argv[2]); +// options.config = { name: 'Total.js' }; +// options.sleep = 3000; + +require('total.js').http('release', options); +// require('total.js').cluster.http(5, 'release', options); diff --git a/RVO35/release.js.json b/RVO35/release.js.json new file mode 100755 index 0000000..94f2ae8 --- /dev/null +++ b/RVO35/release.js.json @@ -0,0 +1,34 @@ +{ + "pid": 397, + "stats": [ + { + "id": null, + "version": { + "node": "v14.18.1", + "total": "3.4.13", + "app": "1.0.0" + }, + "pid": 397, + "thread": "", + "mode": "release", + "overload": 0, + "date": "2025-10-16T00:25:03.493Z", + "memory": 24.26, + "rm": 0, + "fm": 0, + "wm": 0, + "mm": 0, + "om": 7, + "em": 1, + "dbrm": 0, + "dbwm": 0, + "usage": 0, + "requests": 8, + "pending": 0, + "errors": 0, + "timeouts": 0, + "uptime": 908, + "online": 0 + } + ] +} \ No newline at end of file diff --git a/RVO35/report_data.log b/RVO35/report_data.log new file mode 100755 index 0000000..f806024 --- /dev/null +++ b/RVO35/report_data.log @@ -0,0 +1,395 @@ +{ + "name": "rvo_senica_35_10.0.0.129", + "time": "2025-10-15T10:18:18.856Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [ + "35/59_0L_2650_NEMA" + ], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_35_10.0.0.129", + "time": "2025-10-15T11:18:18.853Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [ + "35/59_0L_2650_NEMA" + ], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_35_10.0.0.129", + "time": "2025-10-15T12:18:18.854Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [ + "35/59_0L_2650_NEMA" + ], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_35_10.0.0.129", + "time": "2025-10-15T13:18:18.853Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [ + "35/59_0L_2650_NEMA" + ], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_35_10.0.0.129", + "time": "2025-10-15T14:18:18.854Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [ + "35/59_0L_2650_NEMA" + ], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_35_10.0.0.129", + "time": "2025-10-15T15:18:18.854Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [ + "35/59_0L_2650_NEMA" + ], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_35_10.0.0.129", + "time": "2025-10-15T17:59:06.755Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "35/59_0L_2650_NEMA", + "35/23_1L_3076_NEMA", + "35/30_1L_3429_NEMA", + "35/29_1L_3569_NEMA", + "35/32_1L_3646_NENA", + "35/70_1L_3649_NEMA", + "35/26_1L_3655_NEMA", + "35/31_1L_3657_NEMA", + "35/22_1L_3658_NEMA", + "35/78_1L_3659_NEMA", + "35/63_1L_3671_NEMA", + "35/65_1L_3672_NEMA", + "35/67_1L_3673_NEMA", + "35/68_1L_3674_NEMA", + "35/72_1L_3677_NEMA", + "35/69_1L_3679_NEMA", + "35/64_1L_3682_NEMA", + "35/66_1L_3683_NEMA", + "35/71_1L_3687_NEMA", + "35/28_1L_3945_NEMA", + "35/27_1L_3962_NEMA", + "35/24_1L_3980_NEMA", + "35/25_1L_4012_NEMA" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [ + "35/59_0L_2650_NEMA" + ], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_35_10.0.0.129", + "time": "2025-10-15T18:59:06.756Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "35/59_0L_2650_NEMA", + "35/23_1L_3076_NEMA", + "35/30_1L_3429_NEMA", + "35/29_1L_3569_NEMA", + "35/32_1L_3646_NENA", + "35/70_1L_3649_NEMA", + "35/26_1L_3655_NEMA", + "35/31_1L_3657_NEMA", + "35/22_1L_3658_NEMA", + "35/78_1L_3659_NEMA", + "35/63_1L_3671_NEMA", + "35/65_1L_3672_NEMA", + "35/67_1L_3673_NEMA", + "35/68_1L_3674_NEMA", + "35/72_1L_3677_NEMA", + "35/69_1L_3679_NEMA", + "35/64_1L_3682_NEMA", + "35/66_1L_3683_NEMA", + "35/71_1L_3687_NEMA", + "35/28_1L_3945_NEMA", + "35/27_1L_3962_NEMA", + "35/24_1L_3980_NEMA", + "35/25_1L_4012_NEMA" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [ + "35/59_0L_2650_NEMA" + ], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_35_10.0.0.129", + "time": "2025-10-15T19:59:06.756Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "35/59_0L_2650_NEMA", + "35/23_1L_3076_NEMA", + "35/30_1L_3429_NEMA", + "35/29_1L_3569_NEMA", + "35/32_1L_3646_NENA", + "35/70_1L_3649_NEMA", + "35/26_1L_3655_NEMA", + "35/31_1L_3657_NEMA", + "35/22_1L_3658_NEMA", + "35/78_1L_3659_NEMA", + "35/63_1L_3671_NEMA", + "35/65_1L_3672_NEMA", + "35/67_1L_3673_NEMA", + "35/68_1L_3674_NEMA", + "35/72_1L_3677_NEMA", + "35/69_1L_3679_NEMA", + "35/64_1L_3682_NEMA", + "35/66_1L_3683_NEMA", + "35/71_1L_3687_NEMA", + "35/28_1L_3945_NEMA", + "35/27_1L_3962_NEMA", + "35/24_1L_3980_NEMA", + "35/25_1L_4012_NEMA", + "35/19_1L_4108_NEMA" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [ + "35/59_0L_2650_NEMA" + ], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_35_10.0.0.129", + "time": "2025-10-15T20:59:06.755Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "35/59_0L_2650_NEMA", + "35/23_1L_3076_NEMA", + "35/30_1L_3429_NEMA", + "35/29_1L_3569_NEMA", + "35/32_1L_3646_NENA", + "35/70_1L_3649_NEMA", + "35/26_1L_3655_NEMA", + "35/31_1L_3657_NEMA", + "35/22_1L_3658_NEMA", + "35/78_1L_3659_NEMA", + "35/63_1L_3671_NEMA", + "35/65_1L_3672_NEMA", + "35/67_1L_3673_NEMA", + "35/68_1L_3674_NEMA", + "35/72_1L_3677_NEMA", + "35/69_1L_3679_NEMA", + "35/64_1L_3682_NEMA", + "35/66_1L_3683_NEMA", + "35/71_1L_3687_NEMA", + "35/28_1L_3945_NEMA", + "35/27_1L_3962_NEMA", + "35/24_1L_3980_NEMA", + "35/25_1L_4012_NEMA", + "35/19_1L_4108_NEMA" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [ + "35/59_0L_2650_NEMA" + ], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_35_10.0.0.129", + "time": "2025-10-15T21:59:06.758Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "35/59_0L_2650_NEMA", + "35/23_1L_3076_NEMA", + "35/30_1L_3429_NEMA", + "35/29_1L_3569_NEMA", + "35/32_1L_3646_NENA", + "35/70_1L_3649_NEMA", + "35/26_1L_3655_NEMA", + "35/31_1L_3657_NEMA", + "35/22_1L_3658_NEMA", + "35/78_1L_3659_NEMA", + "35/63_1L_3671_NEMA", + "35/65_1L_3672_NEMA", + "35/67_1L_3673_NEMA", + "35/68_1L_3674_NEMA", + "35/72_1L_3677_NEMA", + "35/69_1L_3679_NEMA", + "35/64_1L_3682_NEMA", + "35/66_1L_3683_NEMA", + "35/71_1L_3687_NEMA", + "35/28_1L_3945_NEMA", + "35/27_1L_3962_NEMA", + "35/24_1L_3980_NEMA", + "35/25_1L_4012_NEMA", + "35/19_1L_4108_NEMA" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [ + "35/59_0L_2650_NEMA" + ], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_35_10.0.0.129", + "time": "2025-10-15T22:59:06.755Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "35/59_0L_2650_NEMA", + "35/23_1L_3076_NEMA", + "35/30_1L_3429_NEMA", + "35/29_1L_3569_NEMA", + "35/32_1L_3646_NENA", + "35/70_1L_3649_NEMA", + "35/26_1L_3655_NEMA", + "35/31_1L_3657_NEMA", + "35/22_1L_3658_NEMA", + "35/78_1L_3659_NEMA", + "35/63_1L_3671_NEMA", + "35/65_1L_3672_NEMA", + "35/67_1L_3673_NEMA", + "35/68_1L_3674_NEMA", + "35/72_1L_3677_NEMA", + "35/69_1L_3679_NEMA", + "35/64_1L_3682_NEMA", + "35/66_1L_3683_NEMA", + "35/71_1L_3687_NEMA", + "35/28_1L_3945_NEMA", + "35/27_1L_3962_NEMA", + "35/24_1L_3980_NEMA", + "35/25_1L_4012_NEMA", + "35/19_1L_4108_NEMA" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [ + "35/59_0L_2650_NEMA" + ], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_35_10.0.0.129", + "time": "2025-10-15T23:59:06.759Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "35/59_0L_2650_NEMA", + "35/23_1L_3076_NEMA", + "35/30_1L_3429_NEMA", + "35/29_1L_3569_NEMA", + "35/32_1L_3646_NENA", + "35/70_1L_3649_NEMA", + "35/26_1L_3655_NEMA", + "35/31_1L_3657_NEMA", + "35/22_1L_3658_NEMA", + "35/78_1L_3659_NEMA", + "35/63_1L_3671_NEMA", + "35/65_1L_3672_NEMA", + "35/67_1L_3673_NEMA", + "35/68_1L_3674_NEMA", + "35/72_1L_3677_NEMA", + "35/69_1L_3679_NEMA", + "35/64_1L_3682_NEMA", + "35/66_1L_3683_NEMA", + "35/71_1L_3687_NEMA", + "35/28_1L_3945_NEMA", + "35/27_1L_3962_NEMA", + "35/24_1L_3980_NEMA", + "35/25_1L_4012_NEMA", + "35/19_1L_4108_NEMA" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [ + "35/59_0L_2650_NEMA" + ], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +} \ No newline at end of file From b62cd9729b3daaf766eb5526453a27802f033e3e Mon Sep 17 00:00:00 2001 From: Jakub Klena Date: Thu, 16 Oct 2025 02:25:55 +0200 Subject: [PATCH 18/30] Backup senica-RVO36 on 16.10.2025 --- RVO36/addSwitch.py | 36 + RVO36/cloud_topic.py | 76 + RVO36/config | 12 + RVO36/createNode.py | 43 + RVO36/databases/accelerometer_db.js | 3055 ++++++++++++++++ RVO36/databases/modbus_config.js | 114 + RVO36/databases/nodes.table | 17 + .../nodes_original/nodes_original.table | 1 + RVO36/databases/notifications.table | 41 + RVO36/databases/pins.table | 14 + RVO36/databases/relays.table | 5 + RVO36/databases/settings.table | 2 + RVO36/databases/tbdata.nosql | 4 + RVO36/databases/tbdatacloud.nosql | 3 + RVO36/databases/total_energy.js | 38 + RVO36/debug.js | 16 + RVO36/err.txt | 249 ++ RVO36/flow/cloudmqttconnect.js | 357 ++ RVO36/flow/cmd_manager.js | 3071 ++++++++++++++++ RVO36/flow/code.js | 90 + RVO36/flow/comment.js | 11 + RVO36/flow/count.js | 60 + RVO36/flow/db_connector.js | 286 ++ RVO36/flow/db_init.js | 113 + RVO36/flow/debug.js | 100 + RVO36/flow/designer.json | 3102 +++++++++++++++++ RVO36/flow/dido_controller.js | 1486 ++++++++ RVO36/flow/helper/DataToTbHandler.js | 187 + RVO36/flow/helper/ErrorToServiceHandler.js | 91 + RVO36/flow/helper/db_helper.js | 44 + RVO36/flow/helper/logger.js | 30 + RVO36/flow/helper/md5.js | 5 + RVO36/flow/helper/notification_reporter.js | 121 + RVO36/flow/helper/register.js | 144 + RVO36/flow/helper/serialport_helper.js | 99 + RVO36/flow/helper/suncalc.js | 317 ++ RVO36/flow/helper/utils.js | 161 + RVO36/flow/httprequest.js | 137 + RVO36/flow/httpresponse.js | 76 + RVO36/flow/httproute.js | 326 ++ RVO36/flow/infosender.js | 81 + RVO36/flow/modbus_reader.js | 346 ++ RVO36/flow/monitorconsumption.js | 156 + RVO36/flow/monitordisk.js | 96 + RVO36/flow/monitormemory.js | 87 + RVO36/flow/nodesdb_changecheck.js | 77 + RVO36/flow/show_dbdata.js | 243 ++ RVO36/flow/slack_filter.js | 188 + RVO36/flow/thermometer.js | 99 + RVO36/flow/trigger.js | 79 + RVO36/flow/variables.txt | 0 RVO36/flow/virtualwirein.js | 43 + RVO36/flow/virtualwireout.js | 41 + RVO36/flow/wsmqttpublish.js | 448 +++ RVO36/monitor.txt | 258 ++ RVO36/package-lock.json | 2125 +++++++++++ RVO36/package.json | 29 + RVO36/release.js | 15 + RVO36/release.js.json | 34 + RVO36/report_data.log | 211 ++ 60 files changed, 18796 insertions(+) create mode 100755 RVO36/addSwitch.py create mode 100755 RVO36/cloud_topic.py create mode 100755 RVO36/config create mode 100755 RVO36/createNode.py create mode 100755 RVO36/databases/accelerometer_db.js create mode 100755 RVO36/databases/modbus_config.js create mode 100755 RVO36/databases/nodes.table create mode 100755 RVO36/databases/nodes_original/nodes_original.table create mode 100755 RVO36/databases/notifications.table create mode 100755 RVO36/databases/pins.table create mode 100755 RVO36/databases/relays.table create mode 100755 RVO36/databases/settings.table create mode 100755 RVO36/databases/tbdata.nosql create mode 100755 RVO36/databases/tbdatacloud.nosql create mode 100755 RVO36/databases/total_energy.js create mode 100755 RVO36/debug.js create mode 100755 RVO36/err.txt create mode 100755 RVO36/flow/cloudmqttconnect.js create mode 100755 RVO36/flow/cmd_manager.js create mode 100755 RVO36/flow/code.js create mode 100755 RVO36/flow/comment.js create mode 100755 RVO36/flow/count.js create mode 100755 RVO36/flow/db_connector.js create mode 100755 RVO36/flow/db_init.js create mode 100755 RVO36/flow/debug.js create mode 100755 RVO36/flow/designer.json create mode 100755 RVO36/flow/dido_controller.js create mode 100755 RVO36/flow/helper/DataToTbHandler.js create mode 100755 RVO36/flow/helper/ErrorToServiceHandler.js create mode 100755 RVO36/flow/helper/db_helper.js create mode 100755 RVO36/flow/helper/logger.js create mode 100755 RVO36/flow/helper/md5.js create mode 100755 RVO36/flow/helper/notification_reporter.js create mode 100755 RVO36/flow/helper/register.js create mode 100755 RVO36/flow/helper/serialport_helper.js create mode 100755 RVO36/flow/helper/suncalc.js create mode 100755 RVO36/flow/helper/utils.js create mode 100755 RVO36/flow/httprequest.js create mode 100755 RVO36/flow/httpresponse.js create mode 100755 RVO36/flow/httproute.js create mode 100755 RVO36/flow/infosender.js create mode 100755 RVO36/flow/modbus_reader.js create mode 100755 RVO36/flow/monitorconsumption.js create mode 100755 RVO36/flow/monitordisk.js create mode 100755 RVO36/flow/monitormemory.js create mode 100755 RVO36/flow/nodesdb_changecheck.js create mode 100755 RVO36/flow/show_dbdata.js create mode 100755 RVO36/flow/slack_filter.js create mode 100755 RVO36/flow/thermometer.js create mode 100755 RVO36/flow/trigger.js create mode 100755 RVO36/flow/variables.txt create mode 100755 RVO36/flow/virtualwirein.js create mode 100755 RVO36/flow/virtualwireout.js create mode 100755 RVO36/flow/wsmqttpublish.js create mode 100755 RVO36/monitor.txt create mode 100755 RVO36/package-lock.json create mode 100755 RVO36/package.json create mode 100755 RVO36/release.js create mode 100755 RVO36/release.js.json create mode 100755 RVO36/report_data.log diff --git a/RVO36/addSwitch.py b/RVO36/addSwitch.py new file mode 100755 index 0000000..c35e96b --- /dev/null +++ b/RVO36/addSwitch.py @@ -0,0 +1,36 @@ +import os + +def process_set_file(): + """ + Checks if /root/flowserver exists, reads set.txt, and modifies the second line. + """ + default_folder = "/root/flowserver" if os.path.exists("/root/flowserver") else "/home/unipi/flowserver" + flag = 1 if default_folder == "/root/flowserver" else 0 + + try: + with open("/home/unipi/flowserver/databases/settings.table", "r") as f: + lines = f.readlines() + + if len(lines) >= 2: + lines[0] = lines[0].rstrip('\n') + "|main_switch:boolean\n" + second_line = lines[1].strip() # remove trailing newline + last_pipe_index = second_line.rfind("|") + + if last_pipe_index != -1: + modified_line = second_line[:last_pipe_index + 1] + str(flag) + "|" + second_line[last_pipe_index + 1:] + lines[1] = modified_line + else: + print("Warning: No '|' character found in the second line of set.txt") + + with open("/home/unipi/flowserver/databases/settings.table", "w") as f: + f.writelines(lines) + else: + print("Warning: settings.table has less than two lines.") + + except FileNotFoundError: + print("Error: settings.table not found.") + except Exception as e: + print(e) + +# if __name__ == "__main__": +process_set_file() diff --git a/RVO36/cloud_topic.py b/RVO36/cloud_topic.py new file mode 100755 index 0000000..77c31f1 --- /dev/null +++ b/RVO36/cloud_topic.py @@ -0,0 +1,76 @@ +# import os +# +# def modify_file(file_path): +# """ +# Modifies the given file by: +# 1. Appending "|cloud_topic" to the first line. +# 2. Inserting the text from the third "." to the first "|" on the second line after the last "|" character. +# +# Args: +# file_path (str): The path to the file to be modified. +# """ +# +# with open(file_path, 'r+') as f: +# lines = f.readlines() +# +# # Modify the first line +# lines[0] += "|cloud_topic:string" +# +# # Modify the second line +# second_line = lines[1].strip() # Remove leading/trailing whitespace +# first_pipe_index = second_line.find('|') +# third_dot_index = second_line.find('.', second_line.find('.', second_line.find('.') + 1) + 1) +# text_to_insert = second_line[third_dot_index:first_pipe_index] +# +# last_pipe_index = second_line.rfind('|') +# lines[1] = second_line[:last_pipe_index + 1] + text_to_insert + "|" + second_line[last_pipe_index + 1:] +# +# print(first_pipe_index, third_dot_index, text_to_insert, last_pipe_index) +# # Write the modified lines back to the file +# # f.seek(0) +# # f.writelines(lines) +# # f.truncate() +# +# # Example usage: +# file_path = "settings.table" # Replace with the actual file path +# modify_file(file_path) +# + + +def modify_file(file_path): + """ + Modifies the given file by: + 1. Appending "|cloud_topic" to the first line. + 2. Inserting the text between the third "." and the second "|" on the second line after the last "|" character. + + Args: + file_path (str): The path to the file to be modified. + """ + + with open(file_path, 'r+') as f: + lines = f.readlines() + + first_line = lines[0].strip() + first_line += "|cloud_topic:string\n" + # Modify the first line + lines[0] = first_line + + # Modify the second line + second_line = lines[1].strip() # Remove leading/trailing whitespace + first_pipe_index = second_line.find('|') + second_pipe_index = second_line.find('|', first_pipe_index + 1) + third_dot_index = second_line.find('.', second_line.find('.', second_line.find('.') + 1) + 1) + text_to_insert = "u" + second_line[third_dot_index+1:second_pipe_index] + + last_pipe_index = second_line.rfind('|') + lines[1] = second_line[:last_pipe_index + 1] + text_to_insert + "|" + second_line[last_pipe_index + 1:] + + print(first_pipe_index, third_dot_index, text_to_insert, last_pipe_index) + # Write the modified lines back to the file + f.seek(0) + f.writelines(lines) + f.truncate() + +# Example usage: +file_path = "/home/unipi/flowserver/databases/settings.table" # Replace with the actual file path +modify_file(file_path) diff --git a/RVO36/config b/RVO36/config new file mode 100755 index 0000000..cd0a8a9 --- /dev/null +++ b/RVO36/config @@ -0,0 +1,12 @@ +name : Total.js Flow +default_timezone : Europe/Bratislava + +// Packages settings +package#flow (Object) : { url: '/' } + + +table.relays : line:number|tbname:string|contactor:number|profile:string +table.nodes : node:number|pole_number:string|node_type:string|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|project_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|cloud_topic:string|has_main_switch:boolean|daily_report:boolean|send_changed_node_numbers:boolean +table.pins : pin:string|type:string|line:number +table.notifications : key:string|weight:string|sk:string|en:string diff --git a/RVO36/createNode.py b/RVO36/createNode.py new file mode 100755 index 0000000..a8cea91 --- /dev/null +++ b/RVO36/createNode.py @@ -0,0 +1,43 @@ +print("zaciname") +import re, json + +search_str = '|' +final = [] +counter = 1 +with open("/home/unipi/flowserver/databases/nodes.table", 'r') as file: +# with open("/home/rasta5man/dev/oms/flowserver/databases/nodes.table", 'r') as file: + # Read each line in the file + for line in file: + # Print each line + line = line.strip() + print(line) + if counter != 1: + i = [m.start() for m in re.finditer(re.escape(search_str), line)] + node = line[ i[0] + 1 : i[1] ] + tbname = line[ i[3] + 1 : i[4] ] + final.append({node:tbname}) + counter += 1 +print(json.dumps(final)) +f = open("/home/unipi/flowserver/databases/nodes_original/nodes_original.table", "w") +f.write(json.dumps(final)) +f.close() + + +# +# # ``d`` has to be replaced with a different character +# old_character = "'" +# +# # ``t`` will replace ``d` +# new_character = '"' +# resultant_string = 0; +# with open("/home/unipi/flowserver/databases/nodes_original/nodes_original.table", 'r') as file: +# for line in file: +# resultant_string = re.sub("'", '"', line) +# +# resultant_string = re.sub(" ", "", resultant_string) +# print(resultant_string) +# +# f = open("/home/unipi/flowserver/databases/nodes_original/nodes_original.table", "w") +# f.write(str(resultant_string)) +# f.close() +# diff --git a/RVO36/databases/accelerometer_db.js b/RVO36/databases/accelerometer_db.js new file mode 100755 index 0000000..fdfc7fd --- /dev/null +++ b/RVO36/databases/accelerometer_db.js @@ -0,0 +1,3055 @@ +let naklony = { + "3993": { "label": "1/3A", "naklon": 0 }, + "3989": { "label": "1/3B", "naklon": 15 }, + "3976": { "label": "1/1", "naklon": 0 }, + "4181": { "label": "1/2", "naklon": 0 }, + "4376": { "label": "1/4", "naklon": 15 }, + "3868": { "label": "1/5", "naklon": 15 }, + "3728": { "label": "1/6", "naklon": 15 }, + "3730": { "label": "1/7", "naklon": 0 }, + "4374": { "label": "1/8", "naklon": 0 }, + "3718": { "label": "1/9", "naklon": 15 }, + "4375": { "label": "1/10", "naklon": 15 }, + "4172": { "label": "1/11", "naklon": 15 }, + "4176": { "label": "1/12", "naklon": 15 }, + "3800": { "label": "2/1", "naklon": 5 }, + "3823": { "label": "2/2", "naklon": 5 }, + "3905": { "label": "2/3", "naklon": 5 }, + "3803": { "label": "2/4", "naklon": 5 }, + "3817": { "label": "2/5", "naklon": 5 }, + "3818": { "label": "2/6", "naklon": 5 }, + "3811": { "label": "2/7", "naklon": 5 }, + "3915": { "label": "2/8", "naklon": 5 }, + "3843": { "label": "2/9", "naklon": 10 }, + "3827": { "label": "2/10", "naklon": 10 }, + "4220": { "label": "2/11", "naklon": 10 }, + "3826": { "label": "2/12", "naklon": 10 }, + "3834": { "label": "2/13", "naklon": 10 }, + "3838": { "label": "2/14", "naklon": 10 }, + "2823": { "label": "2/15", "naklon": 10 }, + "3750": { "label": "2/16", "naklon": 10 }, + "3378": { "label": "2/17", "naklon": 0 }, + "3376": { "label": "2/18", "naklon": 0 }, + "3379": { "label": "2/19", "naklon": 0 }, + "3285": { "label": "2/20", "naklon": 0 }, + "3382": { "label": "2/21", "naklon": 0 }, + "3383": { "label": "2/22", "naklon": 0 }, + "3375": { "label": "2/24", "naklon": 0 }, + "3381": { "label": "2/25", "naklon": 0 }, + "3380": { "label": "2/26", "naklon": 0 }, + "3828": { "label": "2/27", "naklon": 10 }, + "3377": { "label": "2/28", "naklon": 0 }, + "3591": { "label": "7/1", "naklon": 0 }, + "3587": { "label": "7/2", "naklon": 0 }, + "3468": { "label": "7/3", "naklon": 0 }, + "3466": { "label": "7/4", "naklon": 0 }, + "3474": { "label": "7/5", "naklon": 0 }, + "3481": { "label": "7/6", "naklon": 0 }, + "3589": { "label": "7/7", "naklon": 0 }, + "3472": { "label": "7/8", "naklon": 0 }, + "3473": { "label": "7/9", "naklon": 0 }, + "3584": { "label": "7/10", "naklon": 0 }, + "3571": { "label": "7/11", "naklon": 0 }, + "3476": { "label": "7/12", "naklon": 0 }, + "3590": { "label": "7/13", "naklon": 0 }, + "3478": { "label": "7/14", "naklon": 0 }, + "3471": { "label": "7/15", "naklon": 0 }, + "3467": { "label": "7/16", "naklon": 0 }, + "3479": { "label": "7/17", "naklon": 0 }, + "3480": { "label": "7/18", "naklon": 0 }, + "3477": { "label": "7/19", "naklon": 0 }, + "3362": { "label": "12/1", "naklon": 0 }, + "3355": { "label": "12/2", "naklon": 0 }, + "3356": { "label": "12/3", "naklon": 0 }, + "3349": { "label": "12/4", "naklon": 0 }, + "3357": { "label": "12/5", "naklon": 0 }, + "3350": { "label": "12/6", "naklon": 0 }, + "3353": { "label": "12/7", "naklon": 0 }, + "3539": { "label": "12/8", "naklon": 0 }, + "3050": { "label": "12/9", "naklon": 0 }, + "3361": { "label": "12/10", "naklon": 0 }, + "3360": { "label": "12/11", "naklon": 0 }, + "3358": { "label": "12/12", "naklon": 0 }, + "3541": { "label": "12/13", "naklon": 0 }, + "3551": { "label": "12/14", "naklon": 0 }, + "3514": { "label": "12/15", "naklon": 0 }, + "3547": { "label": "12/16", "naklon": 0 }, + "3562": { "label": "12/17", "naklon": 0 }, + "3525": { "label": "12/18", "naklon": 0 }, + "3558": { "label": "12/19", "naklon": 0 }, + "3511": { "label": "12/20", "naklon": 0 }, + "3058": { "label": "12/21", "naklon": 0 }, + "3062": { "label": "12/22", "naklon": 0 }, + "3070": { "label": "12/23", "naklon": 0 }, + "3447": { "label": "12/24", "naklon": 0 }, + "3056": { "label": "12/25", "naklon": 0 }, + "3057": { "label": "12/26", "naklon": 0 }, + "3071": { "label": "12/27", "naklon": 0 }, + "3061": { "label": "12/28", "naklon": 0 }, + "3069": { "label": "12/29", "naklon": 0 }, + "3077": { "label": "12/30", "naklon": 0 }, + "3080": { "label": "12/31", "naklon": 0 }, + "3081": { "label": "12/32", "naklon": 0 }, + "3078": { "label": "12/33", "naklon": 0 }, + "4037": { "label": "12/34", "naklon": 0 }, + "3067": { "label": "12/35", "naklon": 0 }, + "3051": { "label": "12/36", "naklon": 0 }, + "2924": { "label": "12/37", "naklon": 0 }, + "3060": { "label": "12/38", "naklon": 0 }, + "3073": { "label": "12/39", "naklon": 0 }, + "3469": { "label": "12/40", "naklon": 0 }, + "2923": { "label": "12/41", "naklon": 0 }, + "2925": { "label": "12/42", "naklon": 0 }, + "3359": { "label": "12/43", "naklon": 0 }, + "3055": { "label": "12/44", "naklon": 0 }, + "2922": { "label": "12/45", "naklon": 0 }, + "3084": { "label": "12/46", "naklon": 0 }, + "3064": { "label": "12/47", "naklon": 0 }, + "3066": { "label": "12/48", "naklon": 0 }, + "3072": { "label": "12/49", "naklon": 0 }, + "3415": { "label": "13/13A", "naklon": 0 }, + "3409": { "label": "13/13B", "naklon": 0 }, + "3399": { "label": "13/13C", "naklon": 0 }, + "3410": { "label": "13/29A", "naklon": 0 }, + "3407": { "label": "13/29B", "naklon": 0 }, + "3405": { "label": "13/34A", "naklon": 0 }, + "3404": { "label": "13/34B", "naklon": 0 }, + "3392": { "label": "13/45A", "naklon": 0 }, + "3386": { "label": "13/45B", "naklon": 0 }, + "3303": { "label": "13/60A", "naklon": 3 }, + "3302": { "label": "13/60B", "naklon": 3 }, + "3319": { "label": "13/70A", "naklon": 6 }, + "3317": { "label": "13/70B", "naklon": 6 }, + "3326": { "label": "13/70C", "naklon": 6 }, + "3351": { "label": "13/73A", "naklon": 6 }, + "3313": { "label": "13/73B", "naklon": 6 }, + "3316": { "label": "13/83A", "naklon": 0 }, + "3320": { "label": "13/83B", "naklon": 0 }, + "3336": { "label": "13/95A", "naklon": 0 }, + "3323": { "label": "13/95B", "naklon": 0 }, + "3339": { "label": "13/98A", "naklon": 0 }, + "3333": { "label": "13/98B", "naklon": 0 }, + "3425": { "label": "13/1", "naklon": 0 }, + "3419": { "label": "13/2", "naklon": 0 }, + "3416": { "label": "13/3", "naklon": 0 }, + "3332": { "label": "13/4", "naklon": 0 }, + "3422": { "label": "13/5", "naklon": 0 }, + "3417": { "label": "13/6", "naklon": 0 }, + "3418": { "label": "13/7", "naklon": 0 }, + "3424": { "label": "13/8", "naklon": 0 }, + "3334": { "label": "13/9", "naklon": 0 }, + "4363": { "label": "13/10", "naklon": 0 }, + "3423": { "label": "13/11", "naklon": 0 }, + "3406": { "label": "13/12", "naklon": 0 }, + "3411": { "label": "13/14", "naklon": 0 }, + "3412": { "label": "13/15", "naklon": 0 }, + "3413": { "label": "13/16", "naklon": 0 }, + "3414": { "label": "13/17", "naklon": 0 }, + "3391": { "label": "13/18", "naklon": 0 }, + "3370": { "label": "13/19", "naklon": 0 }, + "3369": { "label": "13/20", "naklon": 0 }, + "3408": { "label": "13/21", "naklon": 0 }, + "3393": { "label": "13/22", "naklon": 0 }, + "3128": { "label": "13/23", "naklon": 0 }, + "3197": { "label": "13/24", "naklon": 0 }, + "4364": { "label": "13/25", "naklon": 0 }, + "3155": { "label": "13/26", "naklon": 0 }, + "3196": { "label": "13/27", "naklon": 0 }, + "3144": { "label": "13/28", "naklon": 0 }, + "3150": { "label": "13/30", "naklon": 0 }, + "3390": { "label": "13/31", "naklon": 0 }, + "3401": { "label": "13/32", "naklon": 0 }, + "3275": { "label": "13/33", "naklon": 0 }, + "3371": { "label": "13/35", "naklon": 0 }, + "3389": { "label": "13/36", "naklon": 0 }, + "3388": { "label": "13/37", "naklon": 0 }, + "3365": { "label": "13/38", "naklon": 0 }, + "3363": { "label": "13/39", "naklon": 0 }, + "3397": { "label": "13/40", "naklon": 0 }, + "3567": { "label": "13/40/1", "naklon": 0 }, + "3387": { "label": "13/41", "naklon": 0 }, + "3403": { "label": "13/42", "naklon": 0 }, + "3147": { "label": "13/43", "naklon": 0 }, + "3141": { "label": "13/44", "naklon": 0 }, + "3364": { "label": "13/46", "naklon": 0 }, + "3367": { "label": "13/47", "naklon": 0 }, + "3368": { "label": "13/48", "naklon": 0 }, + "3402": { "label": "13/49", "naklon": 0 }, + "3366": { "label": "13/50", "naklon": 0 }, + "3395": { "label": "13/51", "naklon": 0 }, + "3372": { "label": "13/52", "naklon": 0 }, + "3394": { "label": "13/53", "naklon": 0 }, + "3308": { "label": "13/54", "naklon": 0 }, + "3847": { "label": "13/54/1", "naklon": 0 }, + "3312": { "label": "13/55", "naklon": 3 }, + "3309": { "label": "13/56", "naklon": 3 }, + "3311": { "label": "13/57", "naklon": 3 }, + "3310": { "label": "13/58", "naklon": 3 }, + "4365": { "label": "13/59", "naklon": 3 }, + "4093": { "label": "13/60/1", "naklon": 3 }, + "3304": { "label": "13/61", "naklon": 3 }, + "3307": { "label": "13/62", "naklon": 3 }, + "3271": { "label": "13/63", "naklon": 3 }, + "3301": { "label": "13/64", "naklon": 3 }, + "4366": { "label": "13/65", "naklon": 3 }, + "3300": { "label": "13/66", "naklon": 3 }, + "3185": { "label": "13/67", "naklon": 0 }, + "3184": { "label": "13/68", "naklon": 0 }, + "3188": { "label": "13/69", "naklon": 0 }, + "3343": { "label": "13/71", "naklon": 6 }, + "3819": { "label": "13/71/1", "naklon": 6 }, + "3880": { "label": "13/71/2", "naklon": 6 }, + "3348": { "label": "13/72", "naklon": 6 }, + "3344": { "label": "13/74", "naklon": 6 }, + "3346": { "label": "13/75", "naklon": 6 }, + "3597": { "label": "13/75/1", "naklon": 6 }, + "3345": { "label": "13/76", "naklon": 6 }, + "3322": { "label": "13/77", "naklon": 0 }, + "3325": { "label": "13/78", "naklon": 0 }, + "4310": { "label": "13/78/1", "naklon": 0 }, + "3315": { "label": "13/79", "naklon": 0 }, + "3328": { "label": "13/80", "naklon": 0 }, + "3321": { "label": "13/81", "naklon": 0 }, + "3324": { "label": "13/82", "naklon": 0 }, + "3140": { "label": "13/84", "naklon": 0 }, + "3153": { "label": "13/85", "naklon": 0 }, + "3145": { "label": "13/86", "naklon": 0 }, + "3134": { "label": "13/87", "naklon": 0 }, + "3151": { "label": "13/88", "naklon": 0 }, + "3143": { "label": "13/89", "naklon": 0 }, + "3318": { "label": "13/90", "naklon": 0 }, + "3347": { "label": "13/91", "naklon": 0 }, + "3314": { "label": "13/94", "naklon": 0 }, + "3331": { "label": "13/96", "naklon": 0 }, + "3327": { "label": "13/97", "naklon": 0 }, + "3329": { "label": "13/99", "naklon": 0 }, + "3337": { "label": "13/100", "naklon": 0 }, + "3330": { "label": "13/101", "naklon": 0 }, + "3335": { "label": "13/102", "naklon": 0 }, + "3420": { "label": "13/103", "naklon": 0 }, + "3421": { "label": "13/104", "naklon": 0 }, + "4361": { "label": "13/105", "naklon": 0 }, + "4362": { "label": "13/106", "naklon": 0 }, + "3526": { "label": "13/107", "naklon": 0 }, + "4424": { "label": "13/108", "naklon": null }, + "3561": { "label": "13/109", "naklon": null }, + "3527": { "label": "13/110", "naklon": null }, + "3521": { "label": "13/111", "naklon": null }, + "3552": { "label": "13/112", "naklon": null }, + "3544": { "label": "13/113", "naklon": null }, + "3534": { "label": "13/114", "naklon": null }, + "3516": { "label": "13/115", "naklon": null }, + "3513": { "label": "13/116", "naklon": null }, + "3565": { "label": "13/117", "naklon": null }, + "3866": { "label": "13/118", "naklon": null }, + "3136": { "label": "14/1", "naklon": 0 }, + "3137": { "label": "14/2", "naklon": 0 }, + "3135": { "label": "14/3", "naklon": 0 }, + "3149": { "label": "14/4", "naklon": 0 }, + "3142": { "label": "14/5", "naklon": 0 }, + "3342": { "label": "14/6", "naklon": 0 }, + "3340": { "label": "14/7", "naklon": 0 }, + "3152": { "label": "14/8", "naklon": 0 }, + "3886": { "label": "14/9", "naklon": 0 }, + "3341": { "label": "14/10", "naklon": null }, + "3352": { "label": "14/11", "naklon": null }, + "3396": { "label": "15/1", "naklon": 5 }, + "2784": { "label": "15/2", "naklon": 5 }, + "2788": { "label": "15/3", "naklon": 5 }, + "2801": { "label": "15/4", "naklon": 5 }, + "2815": { "label": "15/5", "naklon": 5 }, + "2829": { "label": "15/6", "naklon": 5 }, + "2796": { "label": "15/7", "naklon": 5 }, + "2803": { "label": "15/8", "naklon": 5 }, + "4304": { "label": "15/8/1", "naklon": 5 }, + "4311": { "label": "15/8/2", "naklon": 5 }, + "2821": { "label": "15/9", "naklon": 5 }, + "3400": { "label": "15/10", "naklon": 5 }, + "2799": { "label": "15/11", "naklon": 5 }, + "2804": { "label": "15/12", "naklon": 5 }, + "4303": { "label": "15/12/1", "naklon": 5 }, + "4309": { "label": "15/12/2", "naklon": 5 }, + "2806": { "label": "15/13", "naklon": 5 }, + "2787": { "label": "15/14", "naklon": 5 }, + "2809": { "label": "15/15", "naklon": 5 }, + "2814": { "label": "15/16", "naklon": 0 }, + "3934": { "label": "15/17", "naklon": 0 }, + "3192": { "label": "15/18", "naklon": 0 }, + "2812": { "label": "15/19", "naklon": 0 }, + "4070": { "label": "15/20", "naklon": 0 }, + "2826": { "label": "15/21", "naklon": 0 }, + "2808": { "label": "15/22", "naklon": 3 }, + "2795": { "label": "15/23", "naklon": 3 }, + "2807": { "label": "15/24", "naklon": 3 }, + "2831": { "label": "15/25", "naklon": 0 }, + "2862": { "label": "15/26", "naklon": null }, + "2861": { "label": "15/27", "naklon": 0 }, + "2866": { "label": "15/28", "naklon": 0 }, + "3546": { "label": "15/28/1", "naklon": 0 }, + "4146": { "label": "15/29", "naklon": 0 }, + "3001": { "label": "15/29/1", "naklon": 0 }, + "2835": { "label": "15/30", "naklon": 0 }, + "2874": { "label": "15/31", "naklon": 0 }, + "2852": { "label": "15/32", "naklon": 0 }, + "2851": { "label": "15/33", "naklon": 0 }, + "3560": { "label": "15/33/1", "naklon": 0 }, + "2858": { "label": "15/34", "naklon": 0 }, + "4306": { "label": "15/34/1", "naklon": 0 }, + "2856": { "label": "15/35", "naklon": 0 }, + "2847": { "label": "15/36", "naklon": 0 }, + "3556": { "label": "15/36/1", "naklon": 0 }, + "3950": { "label": "15/37", "naklon": 0 }, + "2848": { "label": "15/38", "naklon": 0 }, + "2863": { "label": "15/39", "naklon": 0 }, + "4313": { "label": "15/39/1", "naklon": 0 }, + "2873": { "label": "15/40", "naklon": 0 }, + "2984": { "label": "15/40/1", "naklon": 0 }, + "2854": { "label": "15/41", "naklon": 0 }, + "2859": { "label": "15/42", "naklon": 0 }, + "2872": { "label": "15/43", "naklon": 0 }, + "2849": { "label": "15/44", "naklon": 0 }, + "2864": { "label": "15/45", "naklon": 0 }, + "3553": { "label": "15/46", "naklon": null }, + "3021": { "label": "15/47", "naklon": null }, + "3008": { "label": "15/47/1", "naklon": null }, + "3017": { "label": "15/48", "naklon": null }, + "3014": { "label": "15/49", "naklon": null }, + "2981": { "label": "15/50", "naklon": null }, + "3020": { "label": "15/51", "naklon": null }, + "3027": { "label": "15/52", "naklon": null }, + "3006": { "label": "15/53", "naklon": null }, + "3012": { "label": "15/54", "naklon": null }, + "2738": { "label": "15/55", "naklon": 0 }, + "2725": { "label": "15/56", "naklon": 0 }, + "3016": { "label": "15/57", "naklon": null }, + "3005": { "label": "15/58", "naklon": null }, + "3009": { "label": "15/58/1", "naklon": null }, + "3010": { "label": "15/59", "naklon": 0 }, + "3538": { "label": "15/59/1", "naklon": 0 }, + "4145": { "label": "15/59/2", "naklon": 0 }, + "2713": { "label": "15/60", "naklon": 0 }, + "2789": { "label": "15/61", "naklon": 0 }, + "2736": { "label": "15/62", "naklon": 0 }, + "2739": { "label": "15/63", "naklon": 0 }, + "4346": { "label": "15/64", "naklon": 0 }, + "2731": { "label": "15/65", "naklon": 0 }, + "2818": { "label": "15/66", "naklon": 0 }, + "3557": { "label": "15/66/1", "naklon": 0 }, + "2822": { "label": "15/67", "naklon": 0 }, + "2833": { "label": "15/68", "naklon": 0 }, + "2834": { "label": "15/69", "naklon": 0 }, + "3097": { "label": "15/70", "naklon": 0 }, + "2824": { "label": "15/71", "naklon": 0 }, + "2828": { "label": "15/72", "naklon": 0 }, + "2600": { "label": "15/73", "naklon": 0 }, + "4314": { "label": "15/73/1", "naklon": 0 }, + "2832": { "label": "15/74", "naklon": 0 }, + "4360": { "label": "15/75", "naklon": 0 }, + "2846": { "label": "15/76", "naklon": 0 }, + "2584": { "label": "15/77", "naklon": 0 }, + "2843": { "label": "15/78", "naklon": 0 }, + "4308": { "label": "15/78/1", "naklon": 0 }, + "4144": { "label": "15/79", "naklon": null }, + "2844": { "label": "15/80", "naklon": 0 }, + "2842": { "label": "15/81", "naklon": 0 }, + "2838": { "label": "15/82", "naklon": 0 }, + "2837": { "label": "15/83", "naklon": null }, + "3555": { "label": "15/83/1", "naklon": null }, + "2839": { "label": "15/84", "naklon": 0 }, + "2830": { "label": "15/85", "naklon": 0 }, + "4066": { "label": "15/86", "naklon": 0 }, + "2836": { "label": "15/87", "naklon": 0 }, + "2911": { "label": "15/88", "naklon": 0 }, + "2825": { "label": "15/89", "naklon": 0 }, + "2811": { "label": "15/90", "naklon": 0 }, + "3740": { "label": "15/94", "naklon": 15 }, + "2734": { "label": "15/95", "naklon": 15 }, + "3105": { "label": "15/96", "naklon": 15 }, + "2732": { "label": "15/97", "naklon": 15 }, + "2727": { "label": "15/98", "naklon": 15 }, + "2735": { "label": "15/99", "naklon": 15 }, + "3926": { "label": "15/100", "naklon": 15 }, + "2918": { "label": "15/101", "naklon": 0 }, + "2705": { "label": "15/102", "naklon": 10 }, + "2708": { "label": "15/103", "naklon": 10 }, + "2721": { "label": "15/104", "naklon": 10 }, + "2719": { "label": "15/105", "naklon": 10 }, + "2919": { "label": "15/106", "naklon": 10 }, + "3101": { "label": "15/107", "naklon": 10 }, + "2853": { "label": "15/108", "naklon": 10 }, + "2715": { "label": "15/109", "naklon": 10 }, + "2712": { "label": "15/110", "naklon": 0 }, + "2711": { "label": "15/111", "naklon": 0 }, + "2709": { "label": "15/112", "naklon": 0 }, + "2710": { "label": "15/113", "naklon": 0 }, + "2907": { "label": "15/114", "naklon": 0 }, + "2906": { "label": "15/115", "naklon": 0 }, + "2908": { "label": "15/116", "naklon": 0 }, + "2901": { "label": "15/117", "naklon": 0 }, + "2913": { "label": "15/118", "naklon": 0 }, + "3656": { "label": "15/119", "naklon": 0 }, + "2781": { "label": "15/120", "naklon": 0 }, + "2802": { "label": "15/121", "naklon": 0 }, + "2791": { "label": "15/122", "naklon": 0 }, + "2783": { "label": "15/123", "naklon": 0 }, + "2794": { "label": "15/124", "naklon": 0 }, + "3139": { "label": "15/125", "naklon": 0 }, + "3229": { "label": "15/126", "naklon": 5 }, + "3239": { "label": "15/127", "naklon": 5 }, + "3230": { "label": "15/128", "naklon": 5 }, + "4016": { "label": "15/129", "naklon": null }, + "3608": { "label": "16/16A", "naklon": 0 }, + "4151": { "label": "16/16B", "naklon": 0 }, + "3710": { "label": "16/1", "naklon": 0 }, + "3726": { "label": "16/2", "naklon": 0 }, + "3743": { "label": "16/3", "naklon": 0 }, + "3724": { "label": "16/4", "naklon": 0 }, + "3712": { "label": "16/5", "naklon": 0 }, + "3739": { "label": "16/6", "naklon": 0 }, + "3742": { "label": "16/7", "naklon": 0 }, + "3731": { "label": "16/8", "naklon": 0 }, + "3727": { "label": "16/9", "naklon": 0 }, + "3729": { "label": "16/10", "naklon": 0 }, + "3736": { "label": "16/11", "naklon": 0 }, + "3713": { "label": "16/12", "naklon": 0 }, + "3715": { "label": "16/13", "naklon": 0 }, + "3733": { "label": "16/14", "naklon": 0 }, + "3732": { "label": "16/15", "naklon": 0 }, + "3634": { "label": "16/17", "naklon": 0 }, + "3610": { "label": "16/18", "naklon": 0 }, + "3626": { "label": "16/19", "naklon": 0 }, + "3618": { "label": "16/20", "naklon": 0 }, + "3619": { "label": "16/21", "naklon": 0 }, + "3628": { "label": "16/22", "naklon": 0 }, + "3615": { "label": "16/23", "naklon": 0 }, + "3609": { "label": "16/24", "naklon": 0 }, + "3606": { "label": "16/25", "naklon": 0 }, + "3624": { "label": "16/26", "naklon": 0 }, + "3627": { "label": "16/27", "naklon": 0 }, + "3607": { "label": "16/28", "naklon": 0 }, + "4370": { "label": "16/29", "naklon": 0 }, + "3692": { "label": "16/30", "naklon": 0 }, + "3614": { "label": "16/31", "naklon": 0 }, + "3623": { "label": "16/32", "naklon": 0 }, + "4373": { "label": "16/33", "naklon": 0 }, + "3620": { "label": "16/34", "naklon": 0 }, + "3685": { "label": "16/35", "naklon": 0 }, + "3616": { "label": "16/36", "naklon": 0 }, + "3686": { "label": "16/37", "naklon": 0 }, + "3688": { "label": "16/38", "naklon": 0 }, + "3684": { "label": "16/39", "naklon": 0 }, + "3825": { "label": "16/40", "naklon": 0 }, + "3865": { "label": "16/41", "naklon": 0 }, + "3824": { "label": "16/42", "naklon": 0 }, + "3871": { "label": "16/43", "naklon": 0 }, + "3801": { "label": "16/44", "naklon": 0 }, + "3862": { "label": "16/45", "naklon": 0 }, + "3876": { "label": "16/46", "naklon": 0 }, + "3861": { "label": "16/47", "naklon": 0 }, + "4215": { "label": "16/48", "naklon": 0 }, + "3605": { "label": "16/49", "naklon": 10 }, + "3603": { "label": "16/50", "naklon": 10 }, + "3592": { "label": "16/51", "naklon": 10 }, + "3598": { "label": "16/52", "naklon": 10 }, + "3594": { "label": "16/53", "naklon": 10 }, + "3593": { "label": "16/54", "naklon": 10 }, + "3630": { "label": "16/55", "naklon": 10 }, + "3763": { "label": "16/56", "naklon": 10 }, + "3746": { "label": "16/57", "naklon": 10 }, + "3699": { "label": "16/58", "naklon": 0 }, + "3698": { "label": "16/59", "naklon": 0 }, + "3709": { "label": "16/60", "naklon": null }, + "3708": { "label": "16/61", "naklon": 0 }, + "3703": { "label": "16/62", "naklon": null }, + "3700": { "label": "16/63", "naklon": 0 }, + "3701": { "label": "16/64", "naklon": null }, + "3704": { "label": "16/65", "naklon": 0 }, + "3707": { "label": "16/66", "naklon": null }, + "3810": { "label": "16/67", "naklon": 0 }, + "4208": { "label": "16/68", "naklon": null }, + "3867": { "label": "16/69", "naklon": 0 }, + "4372": { "label": "16/70", "naklon": null }, + "3881": { "label": "16/71", "naklon": 0 }, + "4204": { "label": "16/72", "naklon": null }, + "3869": { "label": "16/73", "naklon": 0 }, + "4202": { "label": "16/74", "naklon": null }, + "3830": { "label": "16/75", "naklon": 0 }, + "3870": { "label": "16/76", "naklon": null }, + "3964": { "label": "16/77", "naklon": 0 }, + "3849": { "label": "16/78", "naklon": 0 }, + "3694": { "label": "16/79", "naklon": null }, + "3717": { "label": "16/80", "naklon": 0 }, + "3877": { "label": "16/81", "naklon": null }, + "3755": { "label": "16/82", "naklon": 0 }, + "3725": { "label": "16/83", "naklon": null }, + "3716": { "label": "16/84", "naklon": 0 }, + "3696": { "label": "16/85", "naklon": null }, + "3702": { "label": "16/86", "naklon": 0 }, + "3706": { "label": "16/87", "naklon": null }, + "3850": { "label": "16/88", "naklon": 0 }, + "3848": { "label": "16/89", "naklon": null }, + "3737": { "label": "16/90", "naklon": null }, + "3705": { "label": "16/91", "naklon": 0 }, + "3723": { "label": "16/92", "naklon": null }, + "3842": { "label": "16/93", "naklon": 0 }, + "3735": { "label": "16/94", "naklon": null }, + "3719": { "label": "16/95", "naklon": 0 }, + "3697": { "label": "16/96", "naklon": 0 }, + "3711": { "label": "16/97", "naklon": 0 }, + "4107": { "label": "16/98", "naklon": null }, + "4112": { "label": "16/99", "naklon": 5 }, + "4106": { "label": "16/100", "naklon": 5 }, + "4111": { "label": "16/101", "naklon": 5 }, + "4091": { "label": "16/102", "naklon": null }, + "4104": { "label": "16/103", "naklon": 5 }, + "4094": { "label": "16/104", "naklon": null }, + "4089": { "label": "16/105", "naklon": 5 }, + "4095": { "label": "16/106", "naklon": null }, + "4102": { "label": "16/107", "naklon": 5 }, + "4105": { "label": "16/108", "naklon": null }, + "3859": { "label": "16/109", "naklon": null }, + "4090": { "label": "16/110", "naklon": 5 }, + "4110": { "label": "16/111", "naklon": null }, + "4097": { "label": "16/112", "naklon": 5 }, + "4099": { "label": "16/113", "naklon": null }, + "4096": { "label": "16/114", "naklon": null }, + "4101": { "label": "16/115", "naklon": 5 }, + "4109": { "label": "16/116", "naklon": null }, + "4092": { "label": "16/117", "naklon": 5 }, + "3631": { "label": "16/118", "naklon": null }, + "3632": { "label": "16/119", "naklon": 0 }, + "3641": { "label": "16/120", "naklon": null }, + "3638": { "label": "16/121", "naklon": 0 }, + "3637": { "label": "16/122", "naklon": null }, + "4142": { "label": "16/123", "naklon": null }, + "4147": { "label": "16/124", "naklon": 5 }, + "4139": { "label": "16/125", "naklon": 5 }, + "3172": { "label": "20/30A", "naklon": 2 }, + "3164": { "label": "20/30B", "naklon": 2 }, + "3247": { "label": "20/1", "naklon": 10 }, + "3296": { "label": "20/2", "naklon": 10 }, + "3246": { "label": "20/3", "naklon": 10 }, + "3270": { "label": "20/4", "naklon": 10 }, + "3294": { "label": "20/5", "naklon": 10 }, + "3298": { "label": "20/6", "naklon": 10 }, + "3297": { "label": "20/7", "naklon": 10 }, + "3293": { "label": "20/8", "naklon": 10 }, + "3299": { "label": "20/9", "naklon": 10 }, + "3295": { "label": "20/10", "naklon": 10 }, + "3244": { "label": "20/11", "naklon": 10 }, + "3249": { "label": "20/12", "naklon": 10 }, + "3268": { "label": "20/13", "naklon": 10 }, + "3245": { "label": "20/14", "naklon": 10 }, + "3278": { "label": "20/15", "naklon": 10 }, + "3280": { "label": "20/16", "naklon": 10 }, + "3292": { "label": "20/17", "naklon": 10 }, + "3287": { "label": "20/18", "naklon": 10 }, + "3282": { "label": "20/19", "naklon": 10 }, + "3273": { "label": "20/20", "naklon": 0 }, + "3157": { "label": "20/21", "naklon": 0 }, + "3283": { "label": "20/22", "naklon": 0 }, + "3159": { "label": "20/23", "naklon": 0 }, + "3289": { "label": "20/24", "naklon": 0 }, + "3163": { "label": "20/25", "naklon": 0 }, + "3126": { "label": "20/26", "naklon": 0 }, + "3171": { "label": "20/27", "naklon": 0 }, + "3162": { "label": "20/28", "naklon": 0 }, + "3279": { "label": "20/29", "naklon": 10 }, + "3173": { "label": "20/31", "naklon": 0 }, + "3127": { "label": "20/32", "naklon": 0 }, + "3131": { "label": "20/33", "naklon": 0 }, + "3129": { "label": "20/34", "naklon": 0 }, + "3276": { "label": "20/35", "naklon": 2 }, + "3290": { "label": "20/36", "naklon": 2 }, + "3132": { "label": "20/37", "naklon": 0 }, + "3138": { "label": "20/38", "naklon": 0 }, + "3272": { "label": "20/39", "naklon": 0 }, + "3291": { "label": "20/40", "naklon": 0 }, + "3277": { "label": "20/41", "naklon": 10 }, + "3286": { "label": "20/42", "naklon": 10 }, + "3281": { "label": "20/43", "naklon": 10 }, + "3288": { "label": "20/44", "naklon": 10 }, + "3284": { "label": "20/45", "naklon": 10 }, + "3167": { "label": "20/46", "naklon": 10 }, + "3872": { "label": "20/47", "naklon": 0 }, + "3124": { "label": "20/48", "naklon": 0 }, + "3133": { "label": "20/49", "naklon": 0 }, + "3158": { "label": "20/50", "naklon": 0 }, + "3169": { "label": "20/51", "naklon": 0 }, + "3146": { "label": "20/52", "naklon": 0 }, + "3160": { "label": "20/53", "naklon": 0 }, + "3248": { "label": "20/54", "naklon": 0 }, + "3156": { "label": "20/55", "naklon": 0 }, + "3161": { "label": "20/56", "naklon": 0 }, + "3170": { "label": "20/57", "naklon": 0 }, + "3168": { "label": "20/58", "naklon": 0 }, + "3125": { "label": "20/59", "naklon": 0 }, + "3166": { "label": "20/60", "naklon": 0 }, + "3130": { "label": "20/61", "naklon": 0 }, + "3563": { "label": "20/62", "naklon": 0 }, + "3550": { "label": "20/63", "naklon": null }, + "3269": { "label": "20/67", "naklon": 0 }, + "2921": { "label": "21/1", "naklon": 0 }, + "2707": { "label": "21/2", "naklon": 0 }, + "2723": { "label": "21/3", "naklon": 0 }, + "2716": { "label": "21/4", "naklon": 0 }, + "2717": { "label": "21/5", "naklon": 0 }, + "2720": { "label": "21/6", "naklon": 0 }, + "2722": { "label": "21/7", "naklon": 0 }, + "2718": { "label": "21/8", "naklon": 0 }, + "2724": { "label": "21/9", "naklon": 0 }, + "2742": { "label": "21/10", "naklon": 0 }, + "2743": { "label": "21/11", "naklon": 0 }, + "2733": { "label": "21/12", "naklon": 0 }, + "2903": { "label": "21/14", "naklon": 0 }, + "2917": { "label": "21/15", "naklon": 0 }, + "2897": { "label": "21/16", "naklon": 0 }, + "2914": { "label": "21/17", "naklon": 0 }, + "2898": { "label": "21/18", "naklon": 0 }, + "2773": { "label": "21/19", "naklon": 0 }, + "2895": { "label": "21/20", "naklon": 0 }, + "2896": { "label": "21/21", "naklon": 0 }, + "2771": { "label": "21/22", "naklon": 0 }, + "2772": { "label": "21/23", "naklon": 0 }, + "2793": { "label": "21/24", "naklon": 0 }, + "2902": { "label": "21/25", "naklon": 0 }, + "2910": { "label": "21/26", "naklon": 0 }, + "2909": { "label": "21/27", "naklon": 0 }, + "2920": { "label": "21/28", "naklon": 0 }, + "2916": { "label": "21/29", "naklon": 0 }, + "2904": { "label": "21/30", "naklon": 0 }, + "2915": { "label": "21/31", "naklon": 0 }, + "2905": { "label": "21/32", "naklon": 0 }, + "2900": { "label": "21/33", "naklon": 0 }, + "2899": { "label": "21/34", "naklon": 0 }, + "2741": { "label": "21/36", "naklon": 0 }, + "2714": { "label": "21/37", "naklon": 0 }, + "2701": { "label": "21/38", "naklon": 0 }, + "2703": { "label": "21/39", "naklon": 0 }, + "2704": { "label": "21/40", "naklon": 0 }, + "2702": { "label": "21/41", "naklon": 0 }, + "2706": { "label": "21/42", "naklon": 0 }, + "2776": { "label": "21/43", "naklon": 0 }, + "2770": { "label": "21/44", "naklon": 0 }, + "2786": { "label": "21/45", "naklon": 0 }, + "2779": { "label": "21/46", "naklon": 0 }, + "2782": { "label": "21/47", "naklon": 0 }, + "2785": { "label": "21/48", "naklon": 0 }, + "2769": { "label": "21/49", "naklon": 0 }, + "3354": { "label": "21/50", "naklon": 0 }, + "2778": { "label": "21/51", "naklon": 0 }, + "2775": { "label": "21/52", "naklon": 0 }, + "2780": { "label": "21/53", "naklon": 0 }, + "2790": { "label": "21/54", "naklon": 0 }, + "2792": { "label": "21/55", "naklon": 0 }, + "2774": { "label": "21/56", "naklon": 0 }, + "2630": { "label": "22/1", "naklon": 0 }, + "2631": { "label": "22/2", "naklon": 0 }, + "2632": { "label": "22/3", "naklon": 0 }, + "2633": { "label": "22/4", "naklon": 0 }, + "2634": { "label": "22/5", "naklon": 0 }, + "2636": { "label": "22/6", "naklon": 0 }, + "4367": { "label": "22/7", "naklon": 0 }, + "2637": { "label": "22/8", "naklon": 0 }, + "2638": { "label": "22/9", "naklon": 0 }, + "2639": { "label": "22/10", "naklon": 0 }, + "2640": { "label": "22/11", "naklon": 0 }, + "2641": { "label": "22/12", "naklon": 0 }, + "2642": { "label": "22/13", "naklon": 0 }, + "2643": { "label": "22/14", "naklon": 0 }, + "2644": { "label": "22/15", "naklon": 0 }, + "2645": { "label": "22/16", "naklon": 0 }, + "2646": { "label": "22/17", "naklon": 0 }, + "2647": { "label": "22/18", "naklon": 0 }, + "2648": { "label": "22/19", "naklon": 0 }, + "2649": { "label": "22/20", "naklon": 0 }, + "2650": { "label": "22/21", "naklon": 0 }, + "2651": { "label": "22/22", "naklon": 0 }, + "4103": { "label": "22/23", "naklon": 0 }, + "2653": { "label": "22/24", "naklon": 0 }, + "2654": { "label": "22/25", "naklon": 0 }, + "2655": { "label": "22/26", "naklon": 0 }, + "2656": { "label": "22/27", "naklon": 0 }, + "2657": { "label": "22/28", "naklon": 0 }, + "2658": { "label": "22/29", "naklon": 0 }, + "2659": { "label": "22/30", "naklon": 0 }, + "2660": { "label": "22/31", "naklon": 0 }, + "2661": { "label": "22/32", "naklon": 0 }, + "3015": { "label": "22/32/1", "naklon": 0 }, + "2662": { "label": "22/33", "naklon": 0 }, + "2663": { "label": "22/34", "naklon": 0 }, + "2664": { "label": "22/35", "naklon": 0 }, + "2665": { "label": "22/36", "naklon": 0 }, + "2666": { "label": "22/37", "naklon": 0 }, + "2667": { "label": "22/38", "naklon": 0 }, + "2668": { "label": "22/39", "naklon": 0 }, + "2669": { "label": "22/40", "naklon": null }, + "2670": { "label": "22/41", "naklon": null }, + "2671": { "label": "22/42", "naklon": null }, + "3087": { "label": "23/9A", "naklon": 10 }, + "3090": { "label": "23/9B", "naklon": 10 }, + "3075": { "label": "23/1", "naklon": 0 }, + "3089": { "label": "23/2", "naklon": 0 }, + "3088": { "label": "23/3", "naklon": 0 }, + "3228": { "label": "23/4", "naklon": 10 }, + "2751": { "label": "23/5", "naklon": 10 }, + "3243": { "label": "23/6", "naklon": 10 }, + "4349": { "label": "23/7", "naklon": 10 }, + "3102": { "label": "23/8", "naklon": 10 }, + "3099": { "label": "23/10", "naklon": 10 }, + "3103": { "label": "23/11", "naklon": 10 }, + "3093": { "label": "23/12", "naklon": 10 }, + "3098": { "label": "23/13", "naklon": 10 }, + "3092": { "label": "23/14", "naklon": 10 }, + "3233": { "label": "23/15", "naklon": 0 }, + "3095": { "label": "23/16", "naklon": 0 }, + "4074": { "label": "23/17", "naklon": 0 }, + "2729": { "label": "23/18", "naklon": 0 }, + "3234": { "label": "23/19", "naklon": 0 }, + "3094": { "label": "23/20", "naklon": 0 }, + "2817": { "label": "23/21", "naklon": 0 }, + "3226": { "label": "23/22", "naklon": 0 }, + "3225": { "label": "23/23", "naklon": 0 }, + "3237": { "label": "23/24", "naklon": 0 }, + "4250": { "label": "23/25", "naklon": 0 }, + "3059": { "label": "23/26", "naklon": 10 }, + "3238": { "label": "23/27", "naklon": 10 }, + "3242": { "label": "23/28", "naklon": 10 }, + "3236": { "label": "23/29", "naklon": 10 }, + "3112": { "label": "23/30", "naklon": 10 }, + "3224": { "label": "23/31", "naklon": 0 }, + "4298": { "label": "23/32", "naklon": 10 }, + "4150": { "label": "23/33", "naklon": 10 }, + "3091": { "label": "23/34", "naklon": 10 }, + "3771": { "label": "25/1", "naklon": 5 }, + "3777": { "label": "25/2", "naklon": 5 }, + "3749": { "label": "25/3", "naklon": 5 }, + "3769": { "label": "25/4", "naklon": 5 }, + "3765": { "label": "25/5", "naklon": 5 }, + "3785": { "label": "25/6", "naklon": 5 }, + "3761": { "label": "25/7", "naklon": 5 }, + "3758": { "label": "25/8", "naklon": 5 }, + "3766": { "label": "25/9", "naklon": 5 }, + "3779": { "label": "25/10", "naklon": 5 }, + "3899": { "label": "25/11", "naklon": 10 }, + "3922": { "label": "25/12", "naklon": 10 }, + "3912": { "label": "25/13", "naklon": 10 }, + "3933": { "label": "25/14", "naklon": 10 }, + "3921": { "label": "25/15", "naklon": 10 }, + "4300": { "label": "25/16", "naklon": 10 }, + "3927": { "label": "25/17", "naklon": 10 }, + "3212": { "label": "25/18", "naklon": 10 }, + "3208": { "label": "25/19", "naklon": 10 }, + "3207": { "label": "25/20", "naklon": 10 }, + "4294": { "label": "25/21", "naklon": 10 }, + "3209": { "label": "25/22", "naklon": 10 }, + "3745": { "label": "25/23", "naklon": 10 }, + "3762": { "label": "25/24", "naklon": 10 }, + "3215": { "label": "25/25", "naklon": 10 }, + "3210": { "label": "25/26", "naklon": 10 }, + "3211": { "label": "25/27", "naklon": 10 }, + "3206": { "label": "25/28", "naklon": 10 }, + "3918": { "label": "25/29", "naklon": 5 }, + "3928": { "label": "25/30", "naklon": 5 }, + "3917": { "label": "25/31", "naklon": 5 }, + "4029": { "label": "25/32", "naklon": 0 }, + "4038": { "label": "25/33", "naklon": 0 }, + "4022": { "label": "25/34", "naklon": 0 }, + "3937": { "label": "25/35", "naklon": 0 }, + "3190": { "label": "25/36", "naklon": 0 }, + "3835": { "label": "25/37", "naklon": 0 }, + "3201": { "label": "25/38", "naklon": 0 }, + "3193": { "label": "25/39", "naklon": 0 }, + "3191": { "label": "25/40", "naklon": 0 }, + "3203": { "label": "25/41", "naklon": 0 }, + "4301": { "label": "25/42", "naklon": 0 }, + "3223": { "label": "25/43", "naklon": 0 }, + "3202": { "label": "25/44", "naklon": 0 }, + "3205": { "label": "25/45", "naklon": 0 }, + "3194": { "label": "25/46", "naklon": 0 }, + "3198": { "label": "25/47", "naklon": 0 }, + "3204": { "label": "25/48", "naklon": 0 }, + "3200": { "label": "25/49", "naklon": 0 }, + "3216": { "label": "25/50", "naklon": 0 }, + "3932": { "label": "25/51", "naklon": 5 }, + "3923": { "label": "25/52", "naklon": 5 }, + "3913": { "label": "25/53", "naklon": 5 }, + "3900": { "label": "25/54", "naklon": 5 }, + "4189": { "label": "25/55", "naklon": 10 }, + "4191": { "label": "25/56", "naklon": 10 }, + "3790": { "label": "25/57", "naklon": 10 }, + "4190": { "label": "25/58", "naklon": 10 }, + "4302": { "label": "25/59", "naklon": 0 }, + "4351": { "label": "25/60", "naklon": 0 }, + "4075": { "label": "25/61", "naklon": 0 }, + "4071": { "label": "25/62", "naklon": 0 }, + "3784": { "label": "25/63", "naklon": 0 }, + "4065": { "label": "25/64", "naklon": 0 }, + "4297": { "label": "25/65", "naklon": 0 }, + "4295": { "label": "25/66", "naklon": 0 }, + "4299": { "label": "25/67", "naklon": 0 }, + "3772": { "label": "25/68", "naklon": 0 }, + "3941": { "label": "25/69", "naklon": 0 }, + "3782": { "label": "25/70", "naklon": 0 }, + "4068": { "label": "25/71", "naklon": 0 }, + "4073": { "label": "25/72", "naklon": 0 }, + "3901": { "label": "25/73", "naklon": 5 }, + "4296": { "label": "25/74", "naklon": 5 }, + "3910": { "label": "25/75", "naklon": 5 }, + "4293": { "label": "25/76", "naklon": 5 }, + "3919": { "label": "25/77", "naklon": 5 }, + "3924": { "label": "25/78", "naklon": 5 }, + "3909": { "label": "25/79", "naklon": 5 }, + "3896": { "label": "25/80", "naklon": 5 }, + "3911": { "label": "25/81", "naklon": 5 }, + "2819": { "label": "25/82", "naklon": 15 }, + "3776": { "label": "25/83", "naklon": 15 }, + "3752": { "label": "25/84", "naklon": 15 }, + "4353": { "label": "25/85", "naklon": 15 }, + "3791": { "label": "25/86", "naklon": 0 }, + "3770": { "label": "25/87", "naklon": 0 }, + "3760": { "label": "25/88", "naklon": 0 }, + "3115": { "label": "25/89", "naklon": 0 }, + "3738": { "label": "25/90", "naklon": 0 }, + "3748": { "label": "25/91", "naklon": 0 }, + "3753": { "label": "25/92", "naklon": 0 }, + "3775": { "label": "25/93", "naklon": 0 }, + "3778": { "label": "25/94", "naklon": 5 }, + "4078": { "label": "25/95", "naklon": 5 }, + "4088": { "label": "25/96", "naklon": 5 }, + "3856": { "label": "25/97", "naklon": 5 }, + "4084": { "label": "25/98", "naklon": 5 }, + "4069": { "label": "25/99", "naklon": 5 }, + "4188": { "label": "25/100", "naklon": 5 }, + "4064": { "label": "25/101", "naklon": 5 }, + "3792": { "label": "25/102", "naklon": 5 }, + "3780": { "label": "25/103", "naklon": 5 }, + "4034": { "label": "25/104", "naklon": 5 }, + "4072": { "label": "25/105", "naklon": 5 }, + "3884": { "label": "25/106", "naklon": 5 }, + "3793": { "label": "25/107", "naklon": 5 }, + "3863": { "label": "25/108", "naklon": 5 }, + "3855": { "label": "25/109", "naklon": 5 }, + "3846": { "label": "33/1", "naklon": 0 }, + "3943": { "label": "33/2", "naklon": 0 }, + "3903": { "label": "33/3", "naklon": 0 }, + "3982": { "label": "33/4", "naklon": 0 }, + "3879": { "label": "33/5", "naklon": 0 }, + "3887": { "label": "33/6", "naklon": 0 }, + "3920": { "label": "33/7", "naklon": 5 }, + "3942": { "label": "33/8", "naklon": 5 }, + "3829": { "label": "33/9", "naklon": null }, + "3452": { "label": "34/79A", "naklon": 6 }, + "3460": { "label": "34/79B", "naklon": 6 }, + "3443": { "label": "34/90A", "naklon": 6 }, + "3445": { "label": "34/90B", "naklon": 6 }, + "3457": { "label": "34/90C", "naklon": 6 }, + "3461": { "label": "34/97A", "naklon": 6 }, + "3463": { "label": "34/97B", "naklon": 6 }, + "3426": { "label": "34/98A", "naklon": 6 }, + "3444": { "label": "34/98B", "naklon": 6 }, + "3453": { "label": "34/99A", "naklon": 6 }, + "3455": { "label": "34/99B", "naklon": 6 }, + "4009": { "label": "34/1", "naklon": 0 }, + "3602": { "label": "34/2", "naklon": 0 }, + "3441": { "label": "34/3", "naklon": 0 }, + "3464": { "label": "34/4", "naklon": 0 }, + "3883": { "label": "34/5", "naklon": 0 }, + "4098": { "label": "34/6", "naklon": 0 }, + "4003": { "label": "34/7", "naklon": 0 }, + "4004": { "label": "34/8", "naklon": 0 }, + "3888": { "label": "34/9", "naklon": 0 }, + "3997": { "label": "34/10", "naklon": 0 }, + "4006": { "label": "34/11", "naklon": 0 }, + "4000": { "label": "34/12", "naklon": 0 }, + "4011": { "label": "34/13", "naklon": 0 }, + "3999": { "label": "34/14", "naklon": 0 }, + "3981": { "label": "34/15", "naklon": 0 }, + "3988": { "label": "34/16", "naklon": 0 }, + "3986": { "label": "34/17", "naklon": 0 }, + "3998": { "label": "34/18", "naklon": 0 }, + "3983": { "label": "34/19", "naklon": 0 }, + "4005": { "label": "34/20", "naklon": 0 }, + "4001": { "label": "34/21", "naklon": 0 }, + "4008": { "label": "34/22", "naklon": 0 }, + "4002": { "label": "34/23", "naklon": 0 }, + "3996": { "label": "34/24", "naklon": 0 }, + "4007": { "label": "34/25", "naklon": 0 }, + "4113": { "label": "34/26", "naklon": 15 }, + "3595": { "label": "34/27", "naklon": 5 }, + "3599": { "label": "34/28", "naklon": 5 }, + "3601": { "label": "34/29", "naklon": 5 }, + "4205": { "label": "34/30", "naklon": 0 }, + "3987": { "label": "34/31", "naklon": null }, + "4214": { "label": "34/32", "naklon": 0 }, + "4226": { "label": "34/33", "naklon": 0 }, + "4209": { "label": "34/34", "naklon": 0 }, + "4201": { "label": "34/35", "naklon": 0 }, + "3440": { "label": "34/36", "naklon": 0 }, + "3465": { "label": "34/37", "naklon": 0 }, + "3446": { "label": "34/38", "naklon": 0 }, + "4039": { "label": "34/39", "naklon": 5 }, + "4057": { "label": "34/40", "naklon": 5 }, + "3985": { "label": "34/41", "naklon": 0 }, + "3882": { "label": "34/42", "naklon": 0 }, + "4040": { "label": "34/43", "naklon": 5 }, + "3231": { "label": "34/44", "naklon": 0 }, + "3227": { "label": "34/45", "naklon": 0 }, + "3431": { "label": "34/46", "naklon": 0 }, + "4013": { "label": "34/47", "naklon": 0 }, + "4045": { "label": "34/48", "naklon": 0 }, + "3949": { "label": "34/49", "naklon": 0 }, + "3953": { "label": "34/50", "naklon": 0 }, + "3952": { "label": "34/51", "naklon": 0 }, + "3995": { "label": "34/52", "naklon": 0 }, + "3992": { "label": "34/53", "naklon": 0 }, + "4198": { "label": "34/54", "naklon": 0 }, + "3935": { "label": "34/55", "naklon": 0 }, + "4050": { "label": "34/56", "naklon": 0 }, + "4049": { "label": "34/57", "naklon": 0 }, + "4054": { "label": "34/58", "naklon": 0 }, + "3663": { "label": "34/59", "naklon": 6 }, + "3661": { "label": "34/60", "naklon": 6 }, + "3664": { "label": "34/61", "naklon": 6 }, + "3660": { "label": "34/62", "naklon": 6 }, + "3662": { "label": "34/63", "naklon": 6 }, + "3665": { "label": "34/65", "naklon": 6 }, + "3667": { "label": "34/66", "naklon": 6 }, + "3675": { "label": "34/67", "naklon": 6 }, + "3666": { "label": "34/68", "naklon": 6 }, + "3652": { "label": "34/69", "naklon": 6 }, + "3458": { "label": "34/70", "naklon": 6 }, + "4425": { "label": "34/70/1", "naklon": 6 }, + "3459": { "label": "34/71", "naklon": 6 }, + "3435": { "label": "34/72", "naklon": 6 }, + "3448": { "label": "34/73", "naklon": 6 }, + "3451": { "label": "34/74", "naklon": 6 }, + "3442": { "label": "34/75", "naklon": 6 }, + "3449": { "label": "34/76", "naklon": 6 }, + "3450": { "label": "34/77", "naklon": 6 }, + "3433": { "label": "34/78", "naklon": 6 }, + "3432": { "label": "34/80", "naklon": 12 }, + "3470": { "label": "34/81", "naklon": 12 }, + "3438": { "label": "34/82", "naklon": 12 }, + "3439": { "label": "34/83", "naklon": 12 }, + "4028": { "label": "34/84", "naklon": 5 }, + "3596": { "label": "34/85", "naklon": 5 }, + "4021": { "label": "34/86", "naklon": 5 }, + "3437": { "label": "34/87", "naklon": 12 }, + "3428": { "label": "34/88", "naklon": 12 }, + "3430": { "label": "34/89", "naklon": 12 }, + "3454": { "label": "34/91", "naklon": 6 }, + "3492": { "label": "34/92", "naklon": 6 }, + "3462": { "label": "34/93", "naklon": 6 }, + "3427": { "label": "34/94", "naklon": 6 }, + "3434": { "label": "34/95", "naklon": 6 }, + "3456": { "label": "34/96", "naklon": 6 }, + "4307": { "label": "34/98/1", "naklon": 6 }, + "3968": { "label": "35/1", "naklon": 0 }, + "3969": { "label": "35/2", "naklon": 0 }, + "3947": { "label": "35/3", "naklon": 0 }, + "3979": { "label": "35/4", "naklon": 0 }, + "3959": { "label": "35/5", "naklon": 0 }, + "3948": { "label": "35/6", "naklon": 0 }, + "3961": { "label": "35/7", "naklon": 0 }, + "3956": { "label": "35/8", "naklon": 0 }, + "3604": { "label": "35/9", "naklon": 0 }, + "3944": { "label": "35/10", "naklon": 0 }, + "3960": { "label": "35/11", "naklon": 0 }, + "3958": { "label": "35/12", "naklon": 0 }, + "4036": { "label": "35/13", "naklon": 5 }, + "3893": { "label": "35/18", "naklon": 5 }, + "4108": { "label": "35/19", "naklon": 5 }, + "4017": { "label": "35/20", "naklon": 5 }, + "3963": { "label": "35/21", "naklon": 0 }, + "3658": { "label": "35/22", "naklon": 0 }, + "3975": { "label": "35/23", "naklon": 0 }, + "3980": { "label": "35/24", "naklon": 0 }, + "4012": { "label": "35/25", "naklon": 0 }, + "3655": { "label": "35/26", "naklon": 0 }, + "3962": { "label": "35/27", "naklon": 0 }, + "3945": { "label": "35/28", "naklon": 0 }, + "3569": { "label": "35/29", "naklon": 0 }, + "3429": { "label": "35/30", "naklon": 0 }, + "3657": { "label": "35/31", "naklon": 0 }, + "3646": { "label": "35/32", "naklon": 0 }, + "3622": { "label": "35/33", "naklon": 0 }, + "3612": { "label": "35/34", "naklon": 0 }, + "3955": { "label": "35/35", "naklon": 0 }, + "3878": { "label": "35/37", "naklon": 0 }, + "3965": { "label": "35/38", "naklon": 0 }, + "3970": { "label": "35/39", "naklon": 0 }, + "3611": { "label": "35/40", "naklon": 0 }, + "2635": { "label": "35/41", "naklon": 0 }, + "3978": { "label": "35/42", "naklon": 0 }, + "4213": { "label": "35/43", "naklon": 0 }, + "3984": { "label": "35/44", "naklon": 0 }, + "4218": { "label": "35/45", "naklon": 0 }, + "3973": { "label": "35/46", "naklon": 0 }, + "3974": { "label": "35/47", "naklon": 0 }, + "3759": { "label": "35/48", "naklon": 0 }, + "3844": { "label": "35/49", "naklon": 0 }, + "3804": { "label": "35/50", "naklon": 0 }, + "3831": { "label": "35/51", "naklon": 0 }, + "3643": { "label": "35/52", "naklon": 0 }, + "3966": { "label": "35/53", "naklon": 0 }, + "3971": { "label": "35/54", "naklon": 0 }, + "3650": { "label": "35/55", "naklon": 6 }, + "3651": { "label": "35/56", "naklon": 6 }, + "3669": { "label": "35/57", "naklon": 6 }, + "3648": { "label": "35/58", "naklon": 6 }, + "3645": { "label": "35/59", "naklon": 6 }, + "3659": { "label": "35/60", "naklon": 6 }, + "3647": { "label": "35/61", "naklon": 6 }, + "3644": { "label": "35/62", "naklon": 6 }, + "3671": { "label": "35/63", "naklon": 6 }, + "3682": { "label": "35/64", "naklon": 6 }, + "3672": { "label": "35/65", "naklon": 6 }, + "3683": { "label": "35/66", "naklon": 6 }, + "3673": { "label": "35/67", "naklon": 6 }, + "3674": { "label": "35/68", "naklon": 6 }, + "3679": { "label": "35/69", "naklon": 6 }, + "3649": { "label": "35/70", "naklon": 6 }, + "3687": { "label": "35/71", "naklon": 6 }, + "3677": { "label": "35/72", "naklon": 6 }, + "3690": { "label": "35/73", "naklon": 6 }, + "3691": { "label": "35/74", "naklon": 6 }, + "3676": { "label": "35/75", "naklon": 6 }, + "3680": { "label": "35/76", "naklon": 6 }, + "3668": { "label": "35/77", "naklon": 6 }, + "3681": { "label": "35/78", "naklon": 6 }, + "3670": { "label": "35/79", "naklon": 6 }, + "3689": { "label": "35/80", "naklon": 6 }, + "3678": { "label": "35/81", "naklon": 6 }, + "3693": { "label": "35/82", "naklon": 6 }, + "3654": { "label": "35/83", "naklon": null }, + "4086": { "label": "36/1", "naklon": 0 }, + "4085": { "label": "36/2", "naklon": 0 }, + "4083": { "label": "36/3", "naklon": 0 }, + "4087": { "label": "36/4", "naklon": 0 }, + "4077": { "label": "36/5", "naklon": 0 }, + "4082": { "label": "36/6", "naklon": 0 }, + "4186": { "label": "36/7", "naklon": 0 }, + "4206": { "label": "36/8", "naklon": 0 }, + "4080": { "label": "36/9", "naklon": 0 }, + "4081": { "label": "36/10", "naklon": 0 }, + "4210": { "label": "36/11", "naklon": 0 }, + "4079": { "label": "36/12", "naklon": 0 }, + "4076": { "label": "36/13", "naklon": 0 }, + "3852": { "label": "36/14", "naklon": 0 }, + "2813": { "label": "36/15", "naklon": 0 }, + "4219": { "label": "36/16", "naklon": 0 }, + "3104": { "label": "37/1A", "naklon": 15 }, + "3121": { "label": "37/1B", "naklon": 15 }, + "3113": { "label": "37/2", "naklon": 10 }, + "3118": { "label": "37/3", "naklon": 10 }, + "3111": { "label": "37/4", "naklon": 10 }, + "4020": { "label": "37/5", "naklon": 10 }, + "3119": { "label": "37/6", "naklon": 10 }, + "3110": { "label": "37/7", "naklon": 10 }, + "3108": { "label": "37/8", "naklon": 10 }, + "3107": { "label": "37/12", "naklon": 0 }, + "3199": { "label": "37/13", "naklon": 0 }, + "3120": { "label": "37/14", "naklon": 0 }, + "3122": { "label": "37/15", "naklon": 0 }, + "3908": { "label": "37/16", "naklon": 0 }, + "3114": { "label": "37/17", "naklon": 0 }, + "3105": { "label": "37/18", "naklon": 0 }, + "3116": { "label": "37/19", "naklon": 0 }, + "3106": { "label": "37/20", "naklon": 0 }, + "2887": { "label": "37/21", "naklon": 5 }, + "2888": { "label": "37/22", "naklon": 5 }, + "2877": { "label": "37/23", "naklon": 5 }, + "2891": { "label": "37/24", "naklon": 5 }, + "2886": { "label": "37/25", "naklon": 5 }, + "2892": { "label": "37/26", "naklon": 5 }, + "2882": { "label": "37/27", "naklon": 5 }, + "2883": { "label": "37/28", "naklon": 5 }, + "2876": { "label": "37/29", "naklon": 5 }, + "3109": { "label": "37/30", "naklon": 5 }, + "4152": { "label": "37/31", "naklon": 5 }, + "3117": { "label": "37/32", "naklon": 5 }, + "2870": { "label": "37/33", "naklon": 5 }, + "2867": { "label": "37/34", "naklon": 0 }, + "2865": { "label": "37/35", "naklon": 0 }, + "3096": { "label": "37/36", "naklon": 0 }, + "2871": { "label": "37/37", "naklon": 0 }, + "2884": { "label": "37/38", "naklon": 0 }, + "2855": { "label": "37/39", "naklon": 0 }, + "2878": { "label": "37/40", "naklon": 0 }, + "2889": { "label": "37/41", "naklon": 0 }, + "2879": { "label": "37/42", "naklon": 0 }, + "2850": { "label": "37/43", "naklon": 0 }, + "2894": { "label": "37/44", "naklon": 0 }, + "2880": { "label": "37/45", "naklon": 0 }, + "2893": { "label": "37/46", "naklon": 0 }, + "2890": { "label": "37/47", "naklon": 0 }, + "4355": { "label": "37/48", "naklon": 0 }, + "2885": { "label": "37/49", "naklon": 0 }, + "2875": { "label": "37/50", "naklon": 0 }, + "3486": { "label": "38/30A", "naklon": 5 }, + "3714": { "label": "38/30B", "naklon": 0 }, + "3483": { "label": "38/32A", "naklon": 5 }, + "3496": { "label": "38/32B", "naklon": 0 }, + "3487": { "label": "38/35A", "naklon": 5 }, + "3498": { "label": "38/35B", "naklon": 5 }, + "3578": { "label": "38/38A", "naklon": 5 }, + "3508": { "label": "38/38B", "naklon": 5 }, + "3787": { "label": "38/59A", "naklon": 5 }, + "3491": { "label": "38/59B", "naklon": 5 }, + "3568": { "label": "38/1", "naklon": null }, + "3502": { "label": "38/2", "naklon": 0 }, + "3836": { "label": "38/3", "naklon": 0 }, + "3588": { "label": "38/4", "naklon": 0 }, + "3493": { "label": "38/5", "naklon": 0 }, + "3580": { "label": "38/6", "naklon": 0 }, + "3572": { "label": "38/7", "naklon": 0 }, + "3506": { "label": "38/8", "naklon": 0 }, + "3503": { "label": "38/9", "naklon": 0 }, + "3579": { "label": "38/10", "naklon": 0 }, + "3586": { "label": "38/11", "naklon": 0 }, + "3495": { "label": "38/12", "naklon": 5 }, + "3492": { "label": "38/13", "naklon": 5 }, + "3532": { "label": "38/14", "naklon": 5 }, + "3574": { "label": "38/15", "naklon": 5 }, + "4140": { "label": "38/16", "naklon": 5 }, + "3795": { "label": "38/17", "naklon": 5 }, + "3788": { "label": "38/18", "naklon": 5 }, + "3796": { "label": "38/19", "naklon": 5 }, + "3797": { "label": "38/20", "naklon": 5 }, + "3798": { "label": "38/21", "naklon": 5 }, + "3786": { "label": "38/22", "naklon": 5 }, + "4067": { "label": "38/23", "naklon": 5 }, + "3773": { "label": "38/24", "naklon": 5 }, + "3774": { "label": "38/25", "naklon": 5 }, + "3789": { "label": "38/26", "naklon": 5 }, + "3520": { "label": "38/27", "naklon": null }, + "3577": { "label": "38/29", "naklon": 5 }, + "3530": { "label": "38/31", "naklon": null }, + "3488": { "label": "38/33", "naklon": 5 }, + "3505": { "label": "38/34", "naklon": 5 }, + "3497": { "label": "38/36", "naklon": 5 }, + "3490": { "label": "38/37", "naklon": 5 }, + "3585": { "label": "38/39", "naklon": 5 }, + "3582": { "label": "38/40", "naklon": 5 }, + "3507": { "label": "38/41", "naklon": 5 }, + "3484": { "label": "38/42", "naklon": 5 }, + "3501": { "label": "38/43", "naklon": 5 }, + "3581": { "label": "38/44", "naklon": 5 }, + "4192": { "label": "38/45", "naklon": 5 }, + "3576": { "label": "38/46", "naklon": 5 }, + "3489": { "label": "38/47", "naklon": 5 }, + "3573": { "label": "38/48", "naklon": 5 }, + "3504": { "label": "38/49", "naklon": 5 }, + "3794": { "label": "38/50", "naklon": 5 }, + "3485": { "label": "38/51", "naklon": 5 }, + "3482": { "label": "38/52", "naklon": 5 }, + "3575": { "label": "38/53", "naklon": 5 }, + "3499": { "label": "38/54", "naklon": 5 }, + "3494": { "label": "38/55", "naklon": 5 }, + "3583": { "label": "38/56", "naklon": 5 }, + "3570": { "label": "38/57", "naklon": 5 }, + "3500": { "label": "38/58", "naklon": 0 }, + "3510": { "label": "38/63", "naklon": null }, + "3512": { "label": "38/64", "naklon": null }, + "3535": { "label": "38/67", "naklon": null }, + "3531": { "label": "38/68", "naklon": null }, + "3537": { "label": "38/69", "naklon": null }, + "3522": { "label": "39/1", "naklon": 10 }, + "4018": { "label": "39/2", "naklon": 10 }, + "4019": { "label": "39/3", "naklon": 10 }, + "4154": { "label": "39/4", "naklon": 5 }, + "3907": { "label": "39/5", "naklon": 5 }, + "4148": { "label": "39/6", "naklon": 0 }, + "4153": { "label": "39/7", "naklon": 0 }, + "3938": { "label": "39/8", "naklon": 0 }, + "3802": { "label": "39/9", "naklon": 0 }, + "4015": { "label": "39/10", "naklon": 0 }, + "3929": { "label": "39/11", "naklon": 0 }, + "3946": { "label": "39/12", "naklon": 0 }, + "4014": { "label": "39/13", "naklon": 0 }, + "4155": { "label": "39/14", "naklon": 0 }, + "4149": { "label": "39/15", "naklon": 0 }, + "3642": { "label": "39/16", "naklon": 0 }, + "3636": { "label": "39/17", "naklon": 5 }, + "3991": { "label": "39/18", "naklon": 0 }, + "3994": { "label": "39/19", "naklon": 0 }, + "3990": { "label": "39/20", "naklon": 0 }, + "3967": { "label": "39/21", "naklon": 0 }, + "3977": { "label": "39/22", "naklon": 0 }, + "3757": { "label": "39/23", "naklon": 15 }, + "3633": { "label": "39/24", "naklon": 15 }, + "3744": { "label": "39/25", "naklon": 15 }, + "4023": { "label": "39/26", "naklon": 5 }, + "3720": { "label": "39/27", "naklon": 5 }, + "3734": { "label": "39/28", "naklon": 5 }, + "3741": { "label": "39/29", "naklon": 5 }, + "3721": { "label": "39/30", "naklon": 5 }, + "3845": { "label": "39/31", "naklon": 0 }, + "3840": { "label": "39/32", "naklon": 0 }, + "3837": { "label": "39/33", "naklon": null }, + "3839": { "label": "39/34", "naklon": 0 }, + "3542": { "label": "41/1", "naklon": null }, + "3566": { "label": "41/2", "naklon": null }, + "3548": { "label": "41/3", "naklon": null }, + "3515": { "label": "41/4", "naklon": null }, + "3559": { "label": "41/5", "naklon": null }, + "3509": { "label": "41/6", "naklon": null }, + "3524": { "label": "41/7", "naklon": null }, + "3518": { "label": "41/8", "naklon": null }, + "3182": { "label": "41/9", "naklon": null }, + "3187": { "label": "41/10", "naklon": null }, + "3195": { "label": "41/11", "naklon": 0 }, + "3857": { "label": "41/12", "naklon": 0 }, + "3183": { "label": "41/13", "naklon": 0 }, + "3177": { "label": "41/14", "naklon": 0 }, + "3189": { "label": "41/15", "naklon": 0 }, + "3186": { "label": "41/16", "naklon": 0 }, + "3178": { "label": "42/1", "naklon": 0 }, + "3219": { "label": "42/2", "naklon": 0 }, + "3475": { "label": "42/3", "naklon": 0 }, + "3175": { "label": "42/4", "naklon": 0 }, + "3222": { "label": "42/5", "naklon": 0 }, + "3221": { "label": "42/6", "naklon": 0 }, + "3181": { "label": "42/7", "naklon": 0 }, + "3180": { "label": "42/8", "naklon": 0 }, + "3218": { "label": "42/9", "naklon": 0 }, + "3176": { "label": "42/10", "naklon": 0 }, + "3174": { "label": "42/11", "naklon": 0 }, + "3220": { "label": "42/12", "naklon": 0 }, + "3533": { "label": "42/13", "naklon": null }, + "3543": { "label": "42/14", "naklon": null }, + "3554": { "label": "42/15", "naklon": null }, + "3549": { "label": "42/16", "naklon": null }, + "2857": { "label": "43/1", "naklon": 5 }, + "2752": { "label": "43/2", "naklon": 5 }, + "2753": { "label": "43/3", "naklon": 5 }, + "3024": { "label": "43/4", "naklon": 5 }, + "2754": { "label": "43/5", "naklon": 5 }, + "4423": { "label": "43/6", "naklon": 5 }, + "4368": { "label": "43/7", "naklon": 5 }, + "2978": { "label": "43/8", "naklon": 5 }, + "2868": { "label": "43/9", "naklon": 5 }, + "4377": { "label": "43/10", "naklon": 5 }, + "2757": { "label": "43/11", "naklon": 5 }, + "2970": { "label": "43/12", "naklon": 5 }, + "2758": { "label": "43/13", "naklon": 5 }, + "4378": { "label": "43/14", "naklon": 5 }, + "2759": { "label": "43/15", "naklon": 5 }, + "4342": { "label": "43/16", "naklon": 5 }, + "3026": { "label": "43/17", "naklon": null }, + "2986": { "label": "43/18", "naklon": null }, + "4343": { "label": "43/19", "naklon": null }, + "2760": { "label": "43/20", "naklon": null }, + "4379": { "label": "43/21", "naklon": null }, + "2971": { "label": "43/22", "naklon": null }, + "2761": { "label": "43/23", "naklon": null }, + "2762": { "label": "43/24", "naklon": null }, + "4339": { "label": "43/25", "naklon": null }, + "4380": { "label": "43/26", "naklon": null }, + "2975": { "label": "43/27", "naklon": null }, + "3003": { "label": "43/28", "naklon": null }, + "4338": { "label": "43/29", "naklon": null }, + "3002": { "label": "43/30", "naklon": null }, + "4345": { "label": "43/31", "naklon": null }, + "2979": { "label": "43/32", "naklon": null }, + "2989": { "label": "43/33", "naklon": null }, + "2996": { "label": "43/34", "naklon": null }, + "2972": { "label": "43/35", "naklon": null }, + "2988": { "label": "43/36", "naklon": null }, + "4344": { "label": "43/37", "naklon": null }, + "3022": { "label": "43/38", "naklon": null }, + "4341": { "label": "43/39", "naklon": null }, + "2983": { "label": "43/40", "naklon": null }, + "2995": { "label": "43/41", "naklon": null }, + "2763": { "label": "43/42", "naklon": null }, + "2764": { "label": "43/43", "naklon": null }, + "2765": { "label": "43/44", "naklon": null }, + "2766": { "label": "43/45", "naklon": null }, + "2767": { "label": "43/46", "naklon": null }, + "2768": { "label": "43/47", "naklon": null }, + "3018": { "label": "43/48", "naklon": null }, + "2982": { "label": "43/49", "naklon": null }, + "3019": { "label": "43/50", "naklon": 0 }, + "3013": { "label": "43/51", "naklon": null }, + "3007": { "label": "43/52", "naklon": null }, + "2980": { "label": "43/53", "naklon": null }, + "3011": { "label": "43/54", "naklon": null }, + "2672": { "label": "43/55", "naklon": null }, + "2673": { "label": "43/56", "naklon": null }, + "2674": { "label": "43/57", "naklon": null }, + "2675": { "label": "43/58", "naklon": null }, + "2676": { "label": "43/59", "naklon": null }, + "2677": { "label": "43/60", "naklon": null }, + "2678": { "label": "43/61", "naklon": null }, + "2679": { "label": "43/62", "naklon": null }, + "2680": { "label": "43/63", "naklon": null }, + "2840": { "label": "43/64", "naklon": null }, + "2682": { "label": "43/65", "naklon": null }, + "2683": { "label": "43/66", "naklon": null }, + "2684": { "label": "43/67", "naklon": 0 }, + "2685": { "label": "43/68", "naklon": null }, + "2686": { "label": "43/69", "naklon": null }, + "2687": { "label": "43/70", "naklon": null }, + "2688": { "label": "43/71", "naklon": null }, + "2689": { "label": "43/72", "naklon": null }, + "2690": { "label": "43/73", "naklon": null }, + "2691": { "label": "43/74", "naklon": null }, + "2692": { "label": "43/75", "naklon": null }, + "2693": { "label": "43/76", "naklon": 0 }, + "2694": { "label": "43/77", "naklon": null }, + "2695": { "label": "43/78", "naklon": null }, + "2696": { "label": "43/79", "naklon": 0 }, + "2697": { "label": "43/80", "naklon": null }, + "2698": { "label": "43/81", "naklon": 0 }, + "2699": { "label": "43/82", "naklon": null }, + "2700": { "label": "43/83", "naklon": 0 }, + "2744": { "label": "43/84", "naklon": null }, + "2745": { "label": "43/85", "naklon": 0 }, + "2746": { "label": "43/86", "naklon": null }, + "2747": { "label": "43/87", "naklon": 0 }, + "2748": { "label": "43/88", "naklon": null }, + "2749": { "label": "43/89", "naklon": 0 }, + "2841": { "label": "43/90", "naklon": null }, + "4237": { "label": "45/1", "naklon": 5 }, + "4226": { "label": "45/2", "naklon": 5 }, + "4242": { "label": "45/3", "naklon": 5 }, + "4179": { "label": "45/4", "naklon": 5 }, + "4247": { "label": "45/5", "naklon": 5 }, + "4245": { "label": "45/6", "naklon": 5 }, + "3872": { "label": "45/7", "naklon": 5 }, + "4175": { "label": "45/8", "naklon": 5 }, + "4236": { "label": "45/9", "naklon": 5 }, + "4170": { "label": "45/10", "naklon": 5 }, + "4238": { "label": "45/11", "naklon": 5 }, + "4246": { "label": "45/12", "naklon": 5 }, + "4166": { "label": "45/13", "naklon": 5 }, + "4227": { "label": "45/14", "naklon": 5 }, + "4171": { "label": "45/15", "naklon": 5 }, + "4180": { "label": "45/16", "naklon": 5 }, + "4244": { "label": "45/17", "naklon": 5 }, + "4199": { "label": "45/18", "naklon": 5 }, + "4239": { "label": "45/19", "naklon": 5 }, + "4207": { "label": "45/20", "naklon": 5 }, + "4223": { "label": "45/21", "naklon": 5 }, + "4230": { "label": "45/22", "naklon": 5 }, + "4233": { "label": "45/23", "naklon": 5 }, + "4222": { "label": "45/24", "naklon": 5 }, + "4217": { "label": "45/25", "naklon": 5 }, + "4243": { "label": "45/26", "naklon": 5 }, + "4200": { "label": "45/27", "naklon": 5 }, + "4228": { "label": "45/28", "naklon": 5 }, + "4211": { "label": "45/29", "naklon": 5 }, + "4234": { "label": "45/30", "naklon": 5 }, + "4235": { "label": "45/31", "naklon": 5 }, + "4203": { "label": "45/32", "naklon": 5 }, + "4240": { "label": "45/33", "naklon": 5 }, + "4224": { "label": "45/34", "naklon": 5 }, + "4232": { "label": "45/35", "naklon": 5 }, + "4231": { "label": "45/36", "naklon": 5 }, + "4161": { "label": "45/37", "naklon": 5 }, + "4225": { "label": "45/38", "naklon": 5 }, + "4241": { "label": "45/39", "naklon": 5 }, + "4229": { "label": "45/40", "naklon": 5 }, + "4221": { "label": "45/41", "naklon": 5 }, + "4212": { "label": "45/42", "naklon": 5 }, + "4216": { "label": "45/43", "naklon": 5 }, + "3864": { "label": "45/44", "naklon": null }, + "3806": { "label": "46/1", "naklon": 5 }, + "3813": { "label": "46/2", "naklon": 5 }, + "3815": { "label": "46/3", "naklon": 5 }, + "3807": { "label": "46/4", "naklon": 5 }, + "3895": { "label": "46/5", "naklon": 5 }, + "3809": { "label": "46/6", "naklon": 5 }, + "3820": { "label": "46/7", "naklon": 5 }, + "3805": { "label": "46/8", "naklon": 5 }, + "3894": { "label": "46/9", "naklon": 0 }, + "4055": { "label": "46/10", "naklon": 0 }, + "3812": { "label": "46/11", "naklon": 5 }, + "3822": { "label": "46/12", "naklon": 5 }, + "3821": { "label": "46/13", "naklon": 5 }, + "3808": { "label": "46/14", "naklon": 5 }, + "3799": { "label": "46/15", "naklon": 5 }, + "3816": { "label": "46/16", "naklon": 5 }, + "3751": { "label": "46/17", "naklon": 5 }, + "3814": { "label": "46/18", "naklon": 5 }, + "4044": { "label": "46/19", "naklon": 0 }, + "3931": { "label": "46/20", "naklon": 0 }, + "3902": { "label": "46/21", "naklon": 5 }, + "3916": { "label": "46/22", "naklon": 5 }, + "3892": { "label": "46/23", "naklon": 5 }, + "3914": { "label": "46/24", "naklon": 5 }, + "3898": { "label": "46/25", "naklon": 5 }, + "3897": { "label": "46/26", "naklon": 5 }, + "3885": { "label": "46/27", "naklon": 5 }, + "3906": { "label": "46/28", "naklon": 5 }, + "3930": { "label": "46/29", "naklon": 0 }, + "3936": { "label": "46/30", "naklon": 0 }, + "3860": { "label": "46/31", "naklon": 5 }, + "3841": { "label": "46/32", "naklon": 5 }, + "3873": { "label": "46/33", "naklon": 5 }, + "3854": { "label": "46/34", "naklon": 5 }, + "3939": { "label": "46/35", "naklon": 5 }, + "3858": { "label": "46/36", "naklon": 5 }, + "3940": { "label": "46/37", "naklon": 5 }, + "4035": { "label": "46/38", "naklon": 5 }, + "3373": { "label": "47/1", "naklon": 0 }, + "3374": { "label": "47/2", "naklon": 0 }, + "3384": { "label": "47/3", "naklon": 0 }, + "3385": { "label": "47/4", "naklon": 0 }, + "4051": { "label": "48/1", "naklon": 5 }, + "4041": { "label": "48/2", "naklon": 5 }, + "4056": { "label": "48/3", "naklon": 5 }, + "3875": { "label": "48/4", "naklon": 5 }, + "4061": { "label": "48/5", "naklon": 5 }, + "4047": { "label": "48/6", "naklon": 5 }, + "4060": { "label": "48/7", "naklon": 5 }, + "4059": { "label": "48/8", "naklon": 5 }, + "4058": { "label": "48/9", "naklon": 5 }, + "3635": { "label": "48/10", "naklon": 5 }, + "3640": { "label": "48/11", "naklon": 5 }, + "3747": { "label": "48/12", "naklon": 5 }, + "3629": { "label": "48/13", "naklon": 5 }, + "4048": { "label": "48/14", "naklon": 5 }, + "4063": { "label": "48/15", "naklon": 5 }, + "4062": { "label": "48/16", "naklon": 5 }, + "4043": { "label": "48/17", "naklon": 5 }, + "4052": { "label": "48/18", "naklon": 5 }, + "4042": { "label": "48/19", "naklon": 5 }, + "4053": { "label": "48/20", "naklon": 5 }, + "4167": { "label": "50/15A", "naklon": null }, + "4159": { "label": "50/15B", "naklon": null }, + "4183": { "label": "50/1", "naklon": 0 }, + "4157": { "label": "50/2", "naklon": 0 }, + "4160": { "label": "50/3", "naklon": 0 }, + "4173": { "label": "50/4", "naklon": 0 }, + "4177": { "label": "50/5", "naklon": 0 }, + "4174": { "label": "50/6", "naklon": 0 }, + "4178": { "label": "50/7", "naklon": 0 }, + "4195": { "label": "50/8", "naklon": 0 }, + "4169": { "label": "50/9", "naklon": 0 }, + "4162": { "label": "50/10", "naklon": 0 }, + "4158": { "label": "50/11", "naklon": 0 }, + "4182": { "label": "50/12", "naklon": 0 }, + "4194": { "label": "50/13", "naklon": 0 }, + "4184": { "label": "50/14", "naklon": 0 }, + "4197": { "label": "50/16", "naklon": null }, + "4164": { "label": "50/17", "naklon": null }, + "3306": { "label": "50/18", "naklon": null }, + "4168": { "label": "50/19", "naklon": null }, + "4193": { "label": "50/20", "naklon": null }, + "4187": { "label": "50/21", "naklon": null }, + "4163": { "label": "50/22", "naklon": null }, + "4165": { "label": "50/23", "naklon": null }, + "4185": { "label": "50/24", "naklon": null }, + "3904": { "label": "50/25", "naklon": null }, + "2619": { "label": "53/1", "naklon": 0 }, + "2623": { "label": "53/2", "naklon": 0 }, + "2617": { "label": "53/3", "naklon": 0 }, + "2622": { "label": "53/4", "naklon": 0 }, + "2618": { "label": "53/5", "naklon": 0 }, + "2626": { "label": "53/6", "naklon": 0 }, + "2869": { "label": "53/7", "naklon": 0 }, + "2613": { "label": "53/8", "naklon": 0 }, + "2608": { "label": "53/9", "naklon": 0 }, + "2611": { "label": "53/10", "naklon": 0 }, + "2598": { "label": "53/11", "naklon": 0 }, + "3528": { "label": "53/12", "naklon": 0 }, + "3545": { "label": "53/13", "naklon": 0 }, + "2620": { "label": "53/14", "naklon": 0 }, + "2612": { "label": "53/15", "naklon": 0 }, + "2615": { "label": "53/16", "naklon": 0 }, + "3722": { "label": "53/17", "naklon": 0 }, + "2624": { "label": "53/18", "naklon": 0 }, + "2609": { "label": "53/19", "naklon": 0 }, + "2625": { "label": "53/20", "naklon": 0 }, + "2602": { "label": "53/21", "naklon": 0 }, + "2610": { "label": "53/22", "naklon": 0 }, + "2599": { "label": "53/23", "naklon": 0 }, + "2605": { "label": "53/24", "naklon": 0 }, + "2593": { "label": "53/25", "naklon": 0 }, + "3074": { "label": "53/26", "naklon": 0 }, + "2740": { "label": "53/27", "naklon": 0 }, + "2614": { "label": "53/28", "naklon": 0 }, + "2601": { "label": "53/29", "naklon": 0 }, + "4196": { "label": "53/30", "naklon": 0 }, + "2607": { "label": "53/31", "naklon": 0 }, + "2582": { "label": "53/32", "naklon": 0 }, + "2594": { "label": "53/33", "naklon": 0 }, + "2589": { "label": "53/34", "naklon": 0 }, + "2596": { "label": "53/35", "naklon": 0 }, + "2603": { "label": "53/36", "naklon": 0 }, + "2597": { "label": "53/37", "naklon": 0 }, + "2590": { "label": "53/38", "naklon": 0 }, + "2581": { "label": "53/39", "naklon": 0 }, + "2583": { "label": "53/40", "naklon": 0 }, + "2580": { "label": "53/41", "naklon": 0 }, + "2579": { "label": "53/42", "naklon": 0 }, + "2797": { "label": "53/43", "naklon": 0 }, + "2577": { "label": "53/44", "naklon": 0 }, + "2586": { "label": "53/45", "naklon": 0 }, + "2588": { "label": "53/46", "naklon": 0 }, + "2591": { "label": "53/47", "naklon": 0 }, + "2592": { "label": "53/48", "naklon": 0 }, + "2573": { "label": "53/49", "naklon": 0 }, + "2595": { "label": "53/50", "naklon": 0 }, + "2587": { "label": "53/51", "naklon": 0 }, + "2578": { "label": "53/52", "naklon": 0 }, + "2574": { "label": "53/53", "naklon": 0 }, + "2571": { "label": "53/54", "naklon": 0 }, + "2570": { "label": "53/55", "naklon": 0 }, + "2576": { "label": "53/56", "naklon": 0 }, + "2881": { "label": "53/57", "naklon": 0 }, + "2575": { "label": "53/58", "naklon": 0 }, + "2572": { "label": "53/59", "naklon": 0 }, + "2569": { "label": "53/60", "naklon": 0 }, + "4324": { "label": "55/1", "naklon": 0 }, + "4319": { "label": "55/2", "naklon": 0 }, + "4327": { "label": "55/3", "naklon": 0 }, + "4333": { "label": "55/4", "naklon": 0 }, + "4332": { "label": "55/5", "naklon": 0 }, + "4320": { "label": "55/6", "naklon": 0 }, + "4317": { "label": "55/7", "naklon": 0 }, + "4318": { "label": "55/8", "naklon": 0 }, + "4328": { "label": "55/9", "naklon": 0 }, + "4323": { "label": "55/10", "naklon": 0 }, + "4325": { "label": "55/11", "naklon": 0 }, + "4326": { "label": "55/12", "naklon": 0 }, + "4316": { "label": "55/13", "naklon": 0 }, + "4322": { "label": "55/14", "naklon": 0 }, + "4331": { "label": "55/15", "naklon": 0 }, + "4321": { "label": "55/16", "naklon": 0 }, + "4315": { "label": "55/17", "naklon": 0 }, + "4329": { "label": "55/18", "naklon": 0 }, + "4334": { "label": "55/19", "naklon": 0 }, + "4330": { "label": "55/20", "naklon": 0 } +}; + + +let svetlaSorted = [{ "label": "1/3A", "node": 3993, "naklon": 0 }, +{ "label": "1/3B", "node": 3989, "naklon": 15 }, +{ "label": "1/1", "node": 3976, "naklon": 0 }, +{ "label": "1/2", "node": 4181, "naklon": 0 }, +{ "label": "1/4", "node": 4376, "naklon": 15 }, +{ "label": "1/5", "node": 3868, "naklon": 15 }, +{ "label": "1/6", "node": 3728, "naklon": 15 }, +{ "label": "1/7", "node": 3730, "naklon": 0 }, +{ "label": "1/8", "node": 4374, "naklon": 0 }, +{ "label": "1/9", "node": 3718, "naklon": 15 }, +{ "label": "1/10", "node": 4375, "naklon": 15 }, +{ "label": "1/11", "node": 4172, "naklon": 15 }, +{ "label": "1/12", "node": 4176, "naklon": 15 }, +{ "label": "2/1", "node": 3800, "naklon": 5 }, +{ "label": "2/2", "node": 3823, "naklon": 5 }, +{ "label": "2/3", "node": 3905, "naklon": 5 }, +{ "label": "2/4", "node": 3803, "naklon": 5 }, +{ "label": "2/5", "node": 3817, "naklon": 5 }, +{ "label": "2/6", "node": 3818, "naklon": 5 }, +{ "label": "2/7", "node": 3811, "naklon": 5 }, +{ "label": "2/8", "node": 3915, "naklon": 5 }, +{ "label": "2/9", "node": 3843, "naklon": 10 }, +{ "label": "2/10", "node": 3827, "naklon": 10 }, +{ "label": "2/11", "node": 4220, "naklon": 10 }, +{ "label": "2/12", "node": 3826, "naklon": 10 }, +{ "label": "2/13", "node": 3834, "naklon": 10 }, +{ "label": "2/14", "node": 3838, "naklon": 10 }, +{ "label": "2/15", "node": 2823, "naklon": 10 }, +{ "label": "2/16", "node": 3750, "naklon": 10 }, +{ "label": "2/17", "node": 3378, "naklon": 0 }, +{ "label": "2/18", "node": 3376, "naklon": 0 }, +{ "label": "2/19", "node": 3379, "naklon": 0 }, +{ "label": "2/20", "node": 3285, "naklon": 0 }, +{ "label": "2/21", "node": 3382, "naklon": 0 }, +{ "label": "2/22", "node": 3383, "naklon": 0 }, +{ "label": "2/24", "node": 3375, "naklon": 0 }, +{ "label": "2/25", "node": 3381, "naklon": 0 }, +{ "label": "2/26", "node": 3380, "naklon": 0 }, +{ "label": "2/27", "node": 3828, "naklon": 10 }, +{ "label": "2/28", "node": 3377, "naklon": 0 }, +{ "label": "7/1", "node": 3591, "naklon": 0 }, +{ "label": "7/2", "node": 3587, "naklon": 0 }, +{ "label": "7/3", "node": 3468, "naklon": 0 }, +{ "label": "7/4", "node": 3466, "naklon": 0 }, +{ "label": "7/5", "node": 3474, "naklon": 0 }, +{ "label": "7/6", "node": 3481, "naklon": 0 }, +{ "label": "7/7", "node": 3589, "naklon": 0 }, +{ "label": "7/8", "node": 3472, "naklon": 0 }, +{ "label": "7/9", "node": 3473, "naklon": 0 }, +{ "label": "7/10", "node": 3584, "naklon": 0 }, +{ "label": "7/11", "node": 3571, "naklon": 0 }, +{ "label": "7/12", "node": 3476, "naklon": 0 }, +{ "label": "7/13", "node": 3590, "naklon": 0 }, +{ "label": "7/14", "node": 3478, "naklon": 0 }, +{ "label": "7/15", "node": 3471, "naklon": 0 }, +{ "label": "7/16", "node": 3467, "naklon": 0 }, +{ "label": "7/17", "node": 3479, "naklon": 0 }, +{ "label": "7/18", "node": 3480, "naklon": 0 }, +{ "label": "7/19", "node": 3477, "naklon": 0 }, +{ "label": "12/1", "node": 3362, "naklon": 0 }, +{ "label": "12/2", "node": 3355, "naklon": 0 }, +{ "label": "12/3", "node": 3356, "naklon": 0 }, +{ "label": "12/4", "node": 3349, "naklon": 0 }, +{ "label": "12/5", "node": 3357, "naklon": 0 }, +{ "label": "12/6", "node": 3350, "naklon": 0 }, +{ "label": "12/7", "node": 3353, "naklon": 0 }, +{ "label": "12/8", "node": 3539, "naklon": 0 }, +{ "label": "12/9", "node": 3050, "naklon": 0 }, +{ "label": "12/10", "node": 3361, "naklon": 0 }, +{ "label": "12/11", "node": 3360, "naklon": 0 }, +{ "label": "12/12", "node": 3358, "naklon": 0 }, +{ "label": "12/13", "node": 3541, "naklon": 0 }, +{ "label": "12/14", "node": 3551, "naklon": 0 }, +{ "label": "12/15", "node": 3514, "naklon": 0 }, +{ "label": "12/16", "node": 3547, "naklon": 0 }, +{ "label": "12/17", "node": 3562, "naklon": 0 }, +{ "label": "12/18", "node": 3525, "naklon": 0 }, +{ "label": "12/19", "node": 3558, "naklon": 0 }, +{ "label": "12/20", "node": 3511, "naklon": 0 }, +{ "label": "12/21", "node": 3058, "naklon": 0 }, +{ "label": "12/22", "node": 3062, "naklon": 0 }, +{ "label": "12/23", "node": 3070, "naklon": 0 }, +{ "label": "12/24", "node": 3447, "naklon": 0 }, +{ "label": "12/25", "node": 3056, "naklon": 0 }, +{ "label": "12/26", "node": 3057, "naklon": 0 }, +{ "label": "12/27", "node": 3071, "naklon": 0 }, +{ "label": "12/28", "node": 3061, "naklon": 0 }, +{ "label": "12/29", "node": 3069, "naklon": 0 }, +{ "label": "12/30", "node": 3077, "naklon": 0 }, +{ "label": "12/31", "node": 3080, "naklon": 0 }, +{ "label": "12/32", "node": 3081, "naklon": 0 }, +{ "label": "12/33", "node": 3078, "naklon": 0 }, +{ "label": "12/34", "node": 4037, "naklon": 0 }, +{ "label": "12/35", "node": 3067, "naklon": 0 }, +{ "label": "12/36", "node": 3051, "naklon": 0 }, +{ "label": "12/37", "node": 2924, "naklon": 0 }, +{ "label": "12/38", "node": 3060, "naklon": 0 }, +{ "label": "12/39", "node": 3073, "naklon": 0 }, +{ "label": "12/40", "node": 3469, "naklon": 0 }, +{ "label": "12/41", "node": 2923, "naklon": 0 }, +{ "label": "12/42", "node": 2925, "naklon": 0 }, +{ "label": "12/43", "node": 3359, "naklon": 0 }, +{ "label": "12/44", "node": 3055, "naklon": 0 }, +{ "label": "12/45", "node": 2922, "naklon": 0 }, +{ "label": "12/46", "node": 3084, "naklon": 0 }, +{ "label": "12/47", "node": 3064, "naklon": 0 }, +{ "label": "12/48", "node": 3066, "naklon": 0 }, +{ "label": "12/49", "node": 3072, "naklon": 0 }, +{ "label": "13/13A", "node": 3415, "naklon": 0 }, +{ "label": "13/13B", "node": 3409, "naklon": 0 }, +{ "label": "13/13C", "node": 3399, "naklon": 0 }, +{ "label": "13/29A", "node": 3410, "naklon": 0 }, +{ "label": "13/29B", "node": 3407, "naklon": 0 }, +{ "label": "13/34A", "node": 3405, "naklon": 0 }, +{ "label": "13/34B", "node": 3404, "naklon": 0 }, +{ "label": "13/45A", "node": 3392, "naklon": 0 }, +{ "label": "13/45B", "node": 3386, "naklon": 0 }, +{ "label": "13/60A", "node": 3303, "naklon": 3 }, +{ "label": "13/60B", "node": 3302, "naklon": 3 }, +{ "label": "13/70A", "node": 3319, "naklon": 6 }, +{ "label": "13/70B", "node": 3317, "naklon": 6 }, +{ "label": "13/70C", "node": 3326, "naklon": 6 }, +{ "label": "13/73A", "node": 3351, "naklon": 6 }, +{ "label": "13/73B", "node": 3313, "naklon": 6 }, +{ "label": "13/83A", "node": 3316, "naklon": 0 }, +{ "label": "13/83B", "node": 3320, "naklon": 0 }, +{ "label": "13/95A", "node": 3336, "naklon": 0 }, +{ "label": "13/95B", "node": 3323, "naklon": 0 }, +{ "label": "13/98A", "node": 3339, "naklon": 0 }, +{ "label": "13/98B", "node": 3333, "naklon": 0 }, +{ "label": "13/1", "node": 3425, "naklon": 0 }, +{ "label": "13/2", "node": 3419, "naklon": 0 }, +{ "label": "13/3", "node": 3416, "naklon": 0 }, +{ "label": "13/4", "node": 3332, "naklon": 0 }, +{ "label": "13/5", "node": 3422, "naklon": 0 }, +{ "label": "13/6", "node": 3417, "naklon": 0 }, +{ "label": "13/7", "node": 3418, "naklon": 0 }, +{ "label": "13/8", "node": 3424, "naklon": 0 }, +{ "label": "13/9", "node": 3334, "naklon": 0 }, +{ "label": "13/10", "node": 4363, "naklon": 0 }, +{ "label": "13/11", "node": 3423, "naklon": 0 }, +{ "label": "13/12", "node": 3406, "naklon": 0 }, +{ "label": "13/14", "node": 3411, "naklon": 0 }, +{ "label": "13/15", "node": 3412, "naklon": 0 }, +{ "label": "13/16", "node": 3413, "naklon": 0 }, +{ "label": "13/17", "node": 3414, "naklon": 0 }, +{ "label": "13/18", "node": 3391, "naklon": 0 }, +{ "label": "13/19", "node": 3370, "naklon": 0 }, +{ "label": "13/20", "node": 3369, "naklon": 0 }, +{ "label": "13/21", "node": 3408, "naklon": 0 }, +{ "label": "13/22", "node": 3393, "naklon": 0 }, +{ "label": "13/23", "node": 3128, "naklon": 0 }, +{ "label": "13/24", "node": 3197, "naklon": 0 }, +{ "label": "13/25", "node": 4364, "naklon": 0 }, +{ "label": "13/26", "node": 3155, "naklon": 0 }, +{ "label": "13/27", "node": 3196, "naklon": 0 }, +{ "label": "13/28", "node": 3144, "naklon": 0 }, +{ "label": "13/30", "node": 3150, "naklon": 0 }, +{ "label": "13/31", "node": 3390, "naklon": 0 }, +{ "label": "13/32", "node": 3401, "naklon": 0 }, +{ "label": "13/33", "node": 3275, "naklon": 0 }, +{ "label": "13/35", "node": 3371, "naklon": 0 }, +{ "label": "13/36", "node": 3389, "naklon": 0 }, +{ "label": "13/37", "node": 3388, "naklon": 0 }, +{ "label": "13/38", "node": 3365, "naklon": 0 }, +{ "label": "13/39", "node": 3363, "naklon": 0 }, +{ "label": "13/40", "node": 3397, "naklon": 0 }, +{ "label": "13/40/1", "node": 3567, "naklon": 0 }, +{ "label": "13/41", "node": 3387, "naklon": 0 }, +{ "label": "13/42", "node": 3403, "naklon": 0 }, +{ "label": "13/43", "node": 3147, "naklon": 0 }, +{ "label": "13/44", "node": 3141, "naklon": 0 }, +{ "label": "13/46", "node": 3364, "naklon": 0 }, +{ "label": "13/47", "node": 3367, "naklon": 0 }, +{ "label": "13/48", "node": 3368, "naklon": 0 }, +{ "label": "13/49", "node": 3402, "naklon": 0 }, +{ "label": "13/50", "node": 3366, "naklon": 0 }, +{ "label": "13/51", "node": 3395, "naklon": 0 }, +{ "label": "13/52", "node": 3372, "naklon": 0 }, +{ "label": "13/53", "node": 3394, "naklon": 0 }, +{ "label": "13/54", "node": 3308, "naklon": 0 }, +{ "label": "13/54/1", "node": 3847, "naklon": 0 }, +{ "label": "13/55", "node": 3312, "naklon": 3 }, +{ "label": "13/56", "node": 3309, "naklon": 3 }, +{ "label": "13/57", "node": 3311, "naklon": 3 }, +{ "label": "13/58", "node": 3310, "naklon": 3 }, +{ "label": "13/59", "node": 4365, "naklon": 3 }, +{ "label": "13/60/1", "node": 4093, "naklon": 3 }, +{ "label": "13/61", "node": 3304, "naklon": 3 }, +{ "label": "13/62", "node": 3307, "naklon": 3 }, +{ "label": "13/63", "node": 3271, "naklon": 3 }, +{ "label": "13/64", "node": 3301, "naklon": 3 }, +{ "label": "13/65", "node": 4366, "naklon": 3 }, +{ "label": "13/66", "node": 3300, "naklon": 3 }, +{ "label": "13/67", "node": 3185, "naklon": 0 }, +{ "label": "13/68", "node": 3184, "naklon": 0 }, +{ "label": "13/69", "node": 3188, "naklon": 0 }, +{ "label": "13/71", "node": 3343, "naklon": 6 }, +{ "label": "13/71/1", "node": 3819, "naklon": 6 }, +{ "label": "13/71/2", "node": 3880, "naklon": 6 }, +{ "label": "13/72", "node": 3348, "naklon": 6 }, +{ "label": "13/74", "node": 3344, "naklon": 6 }, +{ "label": "13/75", "node": 3346, "naklon": 6 }, +{ "label": "13/75/1", "node": 3597, "naklon": 6 }, +{ "label": "13/76", "node": 3345, "naklon": 6 }, +{ "label": "13/77", "node": 3322, "naklon": 0 }, +{ "label": "13/78", "node": 3325, "naklon": 0 }, +{ "label": "13/78/1", "node": 4310, "naklon": 0 }, +{ "label": "13/79", "node": 3315, "naklon": 0 }, +{ "label": "13/80", "node": 3328, "naklon": 0 }, +{ "label": "13/81", "node": 3321, "naklon": 0 }, +{ "label": "13/82", "node": 3324, "naklon": 0 }, +{ "label": "13/84", "node": 3140, "naklon": 0 }, +{ "label": "13/85", "node": 3153, "naklon": 0 }, +{ "label": "13/86", "node": 3145, "naklon": 0 }, +{ "label": "13/87", "node": 3134, "naklon": 0 }, +{ "label": "13/88", "node": 3151, "naklon": 0 }, +{ "label": "13/89", "node": 3143, "naklon": 0 }, +{ "label": "13/90", "node": 3318, "naklon": 0 }, +{ "label": "13/91", "node": 3347, "naklon": 0 }, +{ "label": "13/94", "node": 3314, "naklon": 0 }, +{ "label": "13/96", "node": 3331, "naklon": 0 }, +{ "label": "13/97", "node": 3327, "naklon": 0 }, +{ "label": "13/99", "node": 3329, "naklon": 0 }, +{ "label": "13/100", "node": 3337, "naklon": 0 }, +{ "label": "13/101", "node": 3330, "naklon": 0 }, +{ "label": "13/102", "node": 3335, "naklon": 0 }, +{ "label": "13/103", "node": 3420, "naklon": 0 }, +{ "label": "13/104", "node": 3421, "naklon": 0 }, +{ "label": "13/105", "node": 4361, "naklon": 0 }, +{ "label": "13/106", "node": 4362, "naklon": 0 }, +{ "label": "13/107", "node": 3526, "naklon": 0 }, +{ "label": "13/108", "node": 4424, "naklon": null }, +{ "label": "13/109", "node": 3561, "naklon": null }, +{ "label": "13/110", "node": 3527, "naklon": null }, +{ "label": "13/111", "node": 3521, "naklon": null }, +{ "label": "13/112", "node": 3552, "naklon": null }, +{ "label": "13/113", "node": 3544, "naklon": null }, +{ "label": "13/114", "node": 3534, "naklon": null }, +{ "label": "13/115", "node": 3516, "naklon": null }, +{ "label": "13/116", "node": 3513, "naklon": null }, +{ "label": "13/117", "node": 3565, "naklon": null }, +{ "label": "13/118", "node": 3866, "naklon": null }, +{ "label": "14/1", "node": 3136, "naklon": 0 }, +{ "label": "14/2", "node": 3137, "naklon": 0 }, +{ "label": "14/3", "node": 3135, "naklon": 0 }, +{ "label": "14/4", "node": 3149, "naklon": 0 }, +{ "label": "14/5", "node": 3142, "naklon": 0 }, +{ "label": "14/6", "node": 3342, "naklon": 0 }, +{ "label": "14/7", "node": 3340, "naklon": 0 }, +{ "label": "14/8", "node": 3152, "naklon": 0 }, +{ "label": "14/9", "node": 3886, "naklon": 0 }, +{ "label": "14/10", "node": 3341, "naklon": null }, +{ "label": "14/11", "node": 3352, "naklon": null }, +{ "label": "15/1", "node": 3396, "naklon": 5 }, +{ "label": "15/2", "node": 2784, "naklon": 5 }, +{ "label": "15/3", "node": 2788, "naklon": 5 }, +{ "label": "15/4", "node": 2801, "naklon": 5 }, +{ "label": "15/5", "node": 2815, "naklon": 5 }, +{ "label": "15/6", "node": 2829, "naklon": 5 }, +{ "label": "15/7", "node": 2796, "naklon": 5 }, +{ "label": "15/8", "node": 2803, "naklon": 5 }, +{ "label": "15/8/1", "node": 4304, "naklon": 5 }, +{ "label": "15/8/2", "node": 4311, "naklon": 5 }, +{ "label": "15/9", "node": 2821, "naklon": 5 }, +{ "label": "15/10", "node": 3400, "naklon": 5 }, +{ "label": "15/11", "node": 2799, "naklon": 5 }, +{ "label": "15/12", "node": 2804, "naklon": 5 }, +{ "label": "15/12/1", "node": 4303, "naklon": 5 }, +{ "label": "15/12/2", "node": 4309, "naklon": 5 }, +{ "label": "15/13", "node": 2806, "naklon": 5 }, +{ "label": "15/14", "node": 2787, "naklon": 5 }, +{ "label": "15/15", "node": 2809, "naklon": 5 }, +{ "label": "15/16", "node": 2814, "naklon": 0 }, +{ "label": "15/17", "node": 3934, "naklon": 0 }, +{ "label": "15/18", "node": 3192, "naklon": 0 }, +{ "label": "15/19", "node": 2812, "naklon": 0 }, +{ "label": "15/20", "node": 4070, "naklon": 0 }, +{ "label": "15/21", "node": 2826, "naklon": 0 }, +{ "label": "15/22", "node": 2808, "naklon": 3 }, +{ "label": "15/23", "node": 2795, "naklon": 3 }, +{ "label": "15/24", "node": 2807, "naklon": 3 }, +{ "label": "15/25", "node": 2831, "naklon": 0 }, +{ "label": "15/26", "node": 2862, "naklon": null }, +{ "label": "15/27", "node": 2861, "naklon": 0 }, +{ "label": "15/28", "node": 2866, "naklon": 0 }, +{ "label": "15/28/1", "node": 3546, "naklon": 0 }, +{ "label": "15/29", "node": 4146, "naklon": 0 }, +{ "label": "15/29/1", "node": 3001, "naklon": 0 }, +{ "label": "15/30", "node": 2835, "naklon": 0 }, +{ "label": "15/31", "node": 2874, "naklon": 0 }, +{ "label": "15/32", "node": 2852, "naklon": 0 }, +{ "label": "15/33", "node": 2851, "naklon": 0 }, +{ "label": "15/33/1", "node": 3560, "naklon": 0 }, +{ "label": "15/34", "node": 2858, "naklon": 0 }, +{ "label": "15/34/1", "node": 4306, "naklon": 0 }, +{ "label": "15/35", "node": 2856, "naklon": 0 }, +{ "label": "15/36", "node": 2847, "naklon": 0 }, +{ "label": "15/36/1", "node": 3556, "naklon": 0 }, +{ "label": "15/37", "node": 3950, "naklon": 0 }, +{ "label": "15/38", "node": 2848, "naklon": 0 }, +{ "label": "15/39", "node": 2863, "naklon": 0 }, +{ "label": "15/39/1", "node": 4313, "naklon": 0 }, +{ "label": "15/40", "node": 2873, "naklon": 0 }, +{ "label": "15/40/1", "node": 2984, "naklon": 0 }, +{ "label": "15/41", "node": 2854, "naklon": 0 }, +{ "label": "15/42", "node": 2859, "naklon": 0 }, +{ "label": "15/43", "node": 2872, "naklon": 0 }, +{ "label": "15/44", "node": 2849, "naklon": 0 }, +{ "label": "15/45", "node": 2864, "naklon": 0 }, +{ "label": "15/46", "node": 3553, "naklon": null }, +{ "label": "15/47", "node": 3021, "naklon": null }, +{ "label": "15/47/1", "node": 3008, "naklon": null }, +{ "label": "15/48", "node": 3017, "naklon": null }, +{ "label": "15/49", "node": 3014, "naklon": null }, +{ "label": "15/50", "node": 2981, "naklon": null }, +{ "label": "15/51", "node": 3020, "naklon": null }, +{ "label": "15/52", "node": 3027, "naklon": null }, +{ "label": "15/53", "node": 3006, "naklon": null }, +{ "label": "15/54", "node": 3012, "naklon": null }, +{ "label": "15/55", "node": 2738, "naklon": 0 }, +{ "label": "15/56", "node": 2725, "naklon": 0 }, +{ "label": "15/57", "node": 3016, "naklon": null }, +{ "label": "15/58", "node": 3005, "naklon": null }, +{ "label": "15/58/1", "node": 3009, "naklon": null }, +{ "label": "15/59", "node": 3010, "naklon": 0 }, +{ "label": "15/59/1", "node": 3538, "naklon": 0 }, +{ "label": "15/59/2", "node": 4145, "naklon": 0 }, +{ "label": "15/60", "node": 2713, "naklon": 0 }, +{ "label": "15/61", "node": 2789, "naklon": 0 }, +{ "label": "15/62", "node": 2736, "naklon": 0 }, +{ "label": "15/63", "node": 2739, "naklon": 0 }, +{ "label": "15/64", "node": 4346, "naklon": 0 }, +{ "label": "15/65", "node": 2731, "naklon": 0 }, +{ "label": "15/66", "node": 2818, "naklon": 0 }, +{ "label": "15/66/1", "node": 3557, "naklon": 0 }, +{ "label": "15/67", "node": 2822, "naklon": 0 }, +{ "label": "15/68", "node": 2833, "naklon": 0 }, +{ "label": "15/69", "node": 2834, "naklon": 0 }, +{ "label": "15/70", "node": 3097, "naklon": 0 }, +{ "label": "15/71", "node": 2824, "naklon": 0 }, +{ "label": "15/72", "node": 2828, "naklon": 0 }, +{ "label": "15/73", "node": 2600, "naklon": 0 }, +{ "label": "15/73/1", "node": 4314, "naklon": 0 }, +{ "label": "15/74", "node": 2832, "naklon": 0 }, +{ "label": "15/75", "node": 4360, "naklon": 0 }, +{ "label": "15/76", "node": 2846, "naklon": 0 }, +{ "label": "15/77", "node": 2584, "naklon": 0 }, +{ "label": "15/78", "node": 2843, "naklon": 0 }, +{ "label": "15/78/1", "node": 4308, "naklon": 0 }, +{ "label": "15/79", "node": 4144, "naklon": null }, +{ "label": "15/80", "node": 2844, "naklon": 0 }, +{ "label": "15/81", "node": 2842, "naklon": 0 }, +{ "label": "15/82", "node": 2838, "naklon": 0 }, +{ "label": "15/83", "node": 2837, "naklon": null }, +{ "label": "15/83/1", "node": 3555, "naklon": null }, +{ "label": "15/84", "node": 2839, "naklon": 0 }, +{ "label": "15/85", "node": 2830, "naklon": 0 }, +{ "label": "15/86", "node": 4066, "naklon": 0 }, +{ "label": "15/87", "node": 2836, "naklon": 0 }, +{ "label": "15/88", "node": 2911, "naklon": 0 }, +{ "label": "15/89", "node": 2825, "naklon": 0 }, +{ "label": "15/90", "node": 2811, "naklon": 0 }, +{ "label": "15/94", "node": 3740, "naklon": 15 }, +{ "label": "15/95", "node": 2734, "naklon": 15 }, +{ "label": "15/96", "node": 3105, "naklon": 15 }, +{ "label": "15/97", "node": 2732, "naklon": 15 }, +{ "label": "15/98", "node": 2727, "naklon": 15 }, +{ "label": "15/99", "node": 2735, "naklon": 15 }, +{ "label": "15/100", "node": 3926, "naklon": 15 }, +{ "label": "15/101", "node": 2918, "naklon": 0 }, +{ "label": "15/102", "node": 2705, "naklon": 10 }, +{ "label": "15/103", "node": 2708, "naklon": 10 }, +{ "label": "15/104", "node": 2721, "naklon": 10 }, +{ "label": "15/105", "node": 2719, "naklon": 10 }, +{ "label": "15/106", "node": 2919, "naklon": 10 }, +{ "label": "15/107", "node": 3101, "naklon": 10 }, +{ "label": "15/108", "node": 2853, "naklon": 10 }, +{ "label": "15/109", "node": 2715, "naklon": 10 }, +{ "label": "15/110", "node": 2712, "naklon": 0 }, +{ "label": "15/111", "node": 2711, "naklon": 0 }, +{ "label": "15/112", "node": 2709, "naklon": 0 }, +{ "label": "15/113", "node": 2710, "naklon": 0 }, +{ "label": "15/114", "node": 2907, "naklon": 0 }, +{ "label": "15/115", "node": 2906, "naklon": 0 }, +{ "label": "15/116", "node": 2908, "naklon": 0 }, +{ "label": "15/117", "node": 2901, "naklon": 0 }, +{ "label": "15/118", "node": 2913, "naklon": 0 }, +{ "label": "15/119", "node": 3656, "naklon": 0 }, +{ "label": "15/120", "node": 2781, "naklon": 0 }, +{ "label": "15/121", "node": 2802, "naklon": 0 }, +{ "label": "15/122", "node": 2791, "naklon": 0 }, +{ "label": "15/123", "node": 2783, "naklon": 0 }, +{ "label": "15/124", "node": 2794, "naklon": 0 }, +{ "label": "15/125", "node": 3139, "naklon": 0 }, +{ "label": "15/126", "node": 3229, "naklon": 5 }, +{ "label": "15/127", "node": 3239, "naklon": 5 }, +{ "label": "15/128", "node": 3230, "naklon": 5 }, +{ "label": "15/129", "node": 4016, "naklon": null }, +{ "label": "16/16A", "node": 3608, "naklon": 0 }, +{ "label": "16/16B", "node": 4151, "naklon": 0 }, +{ "label": "16/1", "node": 3710, "naklon": 0 }, +{ "label": "16/2", "node": 3726, "naklon": 0 }, +{ "label": "16/3", "node": 3743, "naklon": 0 }, +{ "label": "16/4", "node": 3724, "naklon": 0 }, +{ "label": "16/5", "node": 3712, "naklon": 0 }, +{ "label": "16/6", "node": 3739, "naklon": 0 }, +{ "label": "16/7", "node": 3742, "naklon": 0 }, +{ "label": "16/8", "node": 3731, "naklon": 0 }, +{ "label": "16/9", "node": 3727, "naklon": 0 }, +{ "label": "16/10", "node": 3729, "naklon": 0 }, +{ "label": "16/11", "node": 3736, "naklon": 0 }, +{ "label": "16/12", "node": 3713, "naklon": 0 }, +{ "label": "16/13", "node": 3715, "naklon": 0 }, +{ "label": "16/14", "node": 3733, "naklon": 0 }, +{ "label": "16/15", "node": 3732, "naklon": 0 }, +{ "label": "16/17", "node": 3634, "naklon": 0 }, +{ "label": "16/18", "node": 3610, "naklon": 0 }, +{ "label": "16/19", "node": 3626, "naklon": 0 }, +{ "label": "16/20", "node": 3618, "naklon": 0 }, +{ "label": "16/21", "node": 3619, "naklon": 0 }, +{ "label": "16/22", "node": 3628, "naklon": 0 }, +{ "label": "16/23", "node": 3615, "naklon": 0 }, +{ "label": "16/24", "node": 3609, "naklon": 0 }, +{ "label": "16/25", "node": 3606, "naklon": 0 }, +{ "label": "16/26", "node": 3624, "naklon": 0 }, +{ "label": "16/27", "node": 3627, "naklon": 0 }, +{ "label": "16/28", "node": 3607, "naklon": 0 }, +{ "label": "16/29", "node": 4370, "naklon": 0 }, +{ "label": "16/30", "node": 3692, "naklon": 0 }, +{ "label": "16/31", "node": 3614, "naklon": 0 }, +{ "label": "16/32", "node": 3623, "naklon": 0 }, +{ "label": "16/33", "node": 4373, "naklon": 0 }, +{ "label": "16/34", "node": 3620, "naklon": 0 }, +{ "label": "16/35", "node": 3685, "naklon": 0 }, +{ "label": "16/36", "node": 3616, "naklon": 0 }, +{ "label": "16/37", "node": 3686, "naklon": 0 }, +{ "label": "16/38", "node": 3688, "naklon": 0 }, +{ "label": "16/39", "node": 3684, "naklon": 0 }, +{ "label": "16/40", "node": 3825, "naklon": 0 }, +{ "label": "16/41", "node": 3865, "naklon": 0 }, +{ "label": "16/42", "node": 3824, "naklon": 0 }, +{ "label": "16/43", "node": 3871, "naklon": 0 }, +{ "label": "16/44", "node": 3801, "naklon": 0 }, +{ "label": "16/45", "node": 3862, "naklon": 0 }, +{ "label": "16/46", "node": 3876, "naklon": 0 }, +{ "label": "16/47", "node": 3861, "naklon": 0 }, +{ "label": "16/48", "node": 4215, "naklon": 0 }, +{ "label": "16/49", "node": 3605, "naklon": 10 }, +{ "label": "16/50", "node": 3603, "naklon": 10 }, +{ "label": "16/51", "node": 3592, "naklon": 10 }, +{ "label": "16/52", "node": 3598, "naklon": 10 }, +{ "label": "16/53", "node": 3594, "naklon": 10 }, +{ "label": "16/54", "node": 3593, "naklon": 10 }, +{ "label": "16/55", "node": 3630, "naklon": 10 }, +{ "label": "16/56", "node": 3763, "naklon": 10 }, +{ "label": "16/57", "node": 3746, "naklon": 10 }, +{ "label": "16/58", "node": 3699, "naklon": 0 }, +{ "label": "16/59", "node": 3698, "naklon": 0 }, +{ "label": "16/60", "node": 3709, "naklon": null }, +{ "label": "16/61", "node": 3708, "naklon": 0 }, +{ "label": "16/62", "node": 3703, "naklon": null }, +{ "label": "16/63", "node": 3700, "naklon": 0 }, +{ "label": "16/64", "node": 3701, "naklon": null }, +{ "label": "16/65", "node": 3704, "naklon": 0 }, +{ "label": "16/66", "node": 3707, "naklon": null }, +{ "label": "16/67", "node": 3810, "naklon": 0 }, +{ "label": "16/68", "node": 4208, "naklon": null }, +{ "label": "16/69", "node": 3867, "naklon": 0 }, +{ "label": "16/70", "node": 4372, "naklon": null }, +{ "label": "16/71", "node": 3881, "naklon": 0 }, +{ "label": "16/72", "node": 4204, "naklon": null }, +{ "label": "16/73", "node": 3869, "naklon": 0 }, +{ "label": "16/74", "node": 4202, "naklon": null }, +{ "label": "16/75", "node": 3830, "naklon": 0 }, +{ "label": "16/76", "node": 3870, "naklon": null }, +{ "label": "16/77", "node": 3964, "naklon": 0 }, +{ "label": "16/78", "node": 3849, "naklon": 0 }, +{ "label": "16/79", "node": 3694, "naklon": null }, +{ "label": "16/80", "node": 3717, "naklon": 0 }, +{ "label": "16/81", "node": 3877, "naklon": null }, +{ "label": "16/82", "node": 3755, "naklon": 0 }, +{ "label": "16/83", "node": 3725, "naklon": null }, +{ "label": "16/84", "node": 3716, "naklon": 0 }, +{ "label": "16/85", "node": 3696, "naklon": null }, +{ "label": "16/86", "node": 3702, "naklon": 0 }, +{ "label": "16/87", "node": 3706, "naklon": null }, +{ "label": "16/88", "node": 3850, "naklon": 0 }, +{ "label": "16/89", "node": 3848, "naklon": null }, +{ "label": "16/90", "node": 3737, "naklon": null }, +{ "label": "16/91", "node": 3705, "naklon": 0 }, +{ "label": "16/92", "node": 3723, "naklon": null }, +{ "label": "16/93", "node": 3842, "naklon": 0 }, +{ "label": "16/94", "node": 3735, "naklon": null }, +{ "label": "16/95", "node": 3719, "naklon": 0 }, +{ "label": "16/96", "node": 3697, "naklon": 0 }, +{ "label": "16/97", "node": 3711, "naklon": 0 }, +{ "label": "16/98", "node": 4107, "naklon": null }, +{ "label": "16/99", "node": 4112, "naklon": 5 }, +{ "label": "16/100", "node": 4106, "naklon": 5 }, +{ "label": "16/101", "node": 4111, "naklon": 5 }, +{ "label": "16/102", "node": 4091, "naklon": null }, +{ "label": "16/103", "node": 4104, "naklon": 5 }, +{ "label": "16/104", "node": 4094, "naklon": null }, +{ "label": "16/105", "node": 4089, "naklon": 5 }, +{ "label": "16/106", "node": 4095, "naklon": null }, +{ "label": "16/107", "node": 4102, "naklon": 5 }, +{ "label": "16/108", "node": 4105, "naklon": null }, +{ "label": "16/109", "node": 3859, "naklon": null }, +{ "label": "16/110", "node": 4090, "naklon": 5 }, +{ "label": "16/111", "node": 4110, "naklon": null }, +{ "label": "16/112", "node": 4097, "naklon": 5 }, +{ "label": "16/113", "node": 4099, "naklon": null }, +{ "label": "16/114", "node": 4096, "naklon": null }, +{ "label": "16/115", "node": 4101, "naklon": 5 }, +{ "label": "16/116", "node": 4109, "naklon": null }, +{ "label": "16/117", "node": 4092, "naklon": 5 }, +{ "label": "16/118", "node": 3631, "naklon": null }, +{ "label": "16/119", "node": 3632, "naklon": 0 }, +{ "label": "16/120", "node": 3641, "naklon": null }, +{ "label": "16/121", "node": 3638, "naklon": 0 }, +{ "label": "16/122", "node": 3637, "naklon": null }, +{ "label": "16/123", "node": 4142, "naklon": null }, +{ "label": "16/124", "node": 4147, "naklon": 5 }, +{ "label": "16/125", "node": 4139, "naklon": 5 }, +{ "label": "20/30A", "node": 3172, "naklon": 2 }, +{ "label": "20/30B", "node": 3164, "naklon": 2 }, +{ "label": "20/1", "node": 3247, "naklon": 10 }, +{ "label": "20/2", "node": 3296, "naklon": 10 }, +{ "label": "20/3", "node": 3246, "naklon": 10 }, +{ "label": "20/4", "node": 3270, "naklon": 10 }, +{ "label": "20/5", "node": 3294, "naklon": 10 }, +{ "label": "20/6", "node": 3298, "naklon": 10 }, +{ "label": "20/7", "node": 3297, "naklon": 10 }, +{ "label": "20/8", "node": 3293, "naklon": 10 }, +{ "label": "20/9", "node": 3299, "naklon": 10 }, +{ "label": "20/10", "node": 3295, "naklon": 10 }, +{ "label": "20/11", "node": 3244, "naklon": 10 }, +{ "label": "20/12", "node": 3249, "naklon": 10 }, +{ "label": "20/13", "node": 3268, "naklon": 10 }, +{ "label": "20/14", "node": 3245, "naklon": 10 }, +{ "label": "20/15", "node": 3278, "naklon": 10 }, +{ "label": "20/16", "node": 3280, "naklon": 10 }, +{ "label": "20/17", "node": 3292, "naklon": 10 }, +{ "label": "20/18", "node": 3287, "naklon": 10 }, +{ "label": "20/19", "node": 3282, "naklon": 10 }, +{ "label": "20/20", "node": 3273, "naklon": 0 }, +{ "label": "20/21", "node": 3157, "naklon": 0 }, +{ "label": "20/22", "node": 3283, "naklon": 0 }, +{ "label": "20/23", "node": 3159, "naklon": 0 }, +{ "label": "20/24", "node": 3289, "naklon": 0 }, +{ "label": "20/25", "node": 3163, "naklon": 0 }, +{ "label": "20/26", "node": 3126, "naklon": 0 }, +{ "label": "20/27", "node": 3171, "naklon": 0 }, +{ "label": "20/28", "node": 3162, "naklon": 0 }, +{ "label": "20/29", "node": 3279, "naklon": 10 }, +{ "label": "20/31", "node": 3173, "naklon": 0 }, +{ "label": "20/32", "node": 3127, "naklon": 0 }, +{ "label": "20/33", "node": 3131, "naklon": 0 }, +{ "label": "20/34", "node": 3129, "naklon": 0 }, +{ "label": "20/35", "node": 3276, "naklon": 2 }, +{ "label": "20/36", "node": 3290, "naklon": 2 }, +{ "label": "20/37", "node": 3132, "naklon": 0 }, +{ "label": "20/38", "node": 3138, "naklon": 0 }, +{ "label": "20/39", "node": 3272, "naklon": 0 }, +{ "label": "20/40", "node": 3291, "naklon": 0 }, +{ "label": "20/41", "node": 3277, "naklon": 10 }, +{ "label": "20/42", "node": 3286, "naklon": 10 }, +{ "label": "20/43", "node": 3281, "naklon": 10 }, +{ "label": "20/44", "node": 3288, "naklon": 10 }, +{ "label": "20/45", "node": 3284, "naklon": 10 }, +{ "label": "20/46", "node": 3167, "naklon": 10 }, +{ "label": "20/47", "node": 3872, "naklon": 0 }, +{ "label": "20/48", "node": 3124, "naklon": 0 }, +{ "label": "20/49", "node": 3133, "naklon": 0 }, +{ "label": "20/50", "node": 3158, "naklon": 0 }, +{ "label": "20/51", "node": 3169, "naklon": 0 }, +{ "label": "20/52", "node": 3146, "naklon": 0 }, +{ "label": "20/53", "node": 3160, "naklon": 0 }, +{ "label": "20/54", "node": 3248, "naklon": 0 }, +{ "label": "20/55", "node": 3156, "naklon": 0 }, +{ "label": "20/56", "node": 3161, "naklon": 0 }, +{ "label": "20/57", "node": 3170, "naklon": 0 }, +{ "label": "20/58", "node": 3168, "naklon": 0 }, +{ "label": "20/59", "node": 3125, "naklon": 0 }, +{ "label": "20/60", "node": 3166, "naklon": 0 }, +{ "label": "20/61", "node": 3130, "naklon": 0 }, +{ "label": "20/62", "node": 3563, "naklon": 0 }, +{ "label": "20/63", "node": 3550, "naklon": null }, +{ "label": "20/67", "node": 3269, "naklon": 0 }, +{ "label": "21/1", "node": 2921, "naklon": 0 }, +{ "label": "21/2", "node": 2707, "naklon": 0 }, +{ "label": "21/3", "node": 2723, "naklon": 0 }, +{ "label": "21/4", "node": 2716, "naklon": 0 }, +{ "label": "21/5", "node": 2717, "naklon": 0 }, +{ "label": "21/6", "node": 2720, "naklon": 0 }, +{ "label": "21/7", "node": 2722, "naklon": 0 }, +{ "label": "21/8", "node": 2718, "naklon": 0 }, +{ "label": "21/9", "node": 2724, "naklon": 0 }, +{ "label": "21/10", "node": 2742, "naklon": 0 }, +{ "label": "21/11", "node": 2743, "naklon": 0 }, +{ "label": "21/12", "node": 2733, "naklon": 0 }, +{ "label": "21/14", "node": 2903, "naklon": 0 }, +{ "label": "21/15", "node": 2917, "naklon": 0 }, +{ "label": "21/16", "node": 2897, "naklon": 0 }, +{ "label": "21/17", "node": 2914, "naklon": 0 }, +{ "label": "21/18", "node": 2898, "naklon": 0 }, +{ "label": "21/19", "node": 2773, "naklon": 0 }, +{ "label": "21/20", "node": 2895, "naklon": 0 }, +{ "label": "21/21", "node": 2896, "naklon": 0 }, +{ "label": "21/22", "node": 2771, "naklon": 0 }, +{ "label": "21/23", "node": 2772, "naklon": 0 }, +{ "label": "21/24", "node": 2793, "naklon": 0 }, +{ "label": "21/25", "node": 2902, "naklon": 0 }, +{ "label": "21/26", "node": 2910, "naklon": 0 }, +{ "label": "21/27", "node": 2909, "naklon": 0 }, +{ "label": "21/28", "node": 2920, "naklon": 0 }, +{ "label": "21/29", "node": 2916, "naklon": 0 }, +{ "label": "21/30", "node": 2904, "naklon": 0 }, +{ "label": "21/31", "node": 2915, "naklon": 0 }, +{ "label": "21/32", "node": 2905, "naklon": 0 }, +{ "label": "21/33", "node": 2900, "naklon": 0 }, +{ "label": "21/34", "node": 2899, "naklon": 0 }, +{ "label": "21/36", "node": 2741, "naklon": 0 }, +{ "label": "21/37", "node": 2714, "naklon": 0 }, +{ "label": "21/38", "node": 2701, "naklon": 0 }, +{ "label": "21/39", "node": 2703, "naklon": 0 }, +{ "label": "21/40", "node": 2704, "naklon": 0 }, +{ "label": "21/41", "node": 2702, "naklon": 0 }, +{ "label": "21/42", "node": 2706, "naklon": 0 }, +{ "label": "21/43", "node": 2776, "naklon": 0 }, +{ "label": "21/44", "node": 2770, "naklon": 0 }, +{ "label": "21/45", "node": 2786, "naklon": 0 }, +{ "label": "21/46", "node": 2779, "naklon": 0 }, +{ "label": "21/47", "node": 2782, "naklon": 0 }, +{ "label": "21/48", "node": 2785, "naklon": 0 }, +{ "label": "21/49", "node": 2769, "naklon": 0 }, +{ "label": "21/50", "node": 3354, "naklon": 0 }, +{ "label": "21/51", "node": 2778, "naklon": 0 }, +{ "label": "21/52", "node": 2775, "naklon": 0 }, +{ "label": "21/53", "node": 2780, "naklon": 0 }, +{ "label": "21/54", "node": 2790, "naklon": 0 }, +{ "label": "21/55", "node": 2792, "naklon": 0 }, +{ "label": "21/56", "node": 2774, "naklon": 0 }, +{ "label": "22/1", "node": 2630, "naklon": 0 }, +{ "label": "22/2", "node": 2631, "naklon": 0 }, +{ "label": "22/3", "node": 2632, "naklon": 0 }, +{ "label": "22/4", "node": 2633, "naklon": 0 }, +{ "label": "22/5", "node": 2634, "naklon": 0 }, +{ "label": "22/6", "node": 2636, "naklon": 0 }, +{ "label": "22/7", "node": 4367, "naklon": 0 }, +{ "label": "22/8", "node": 2637, "naklon": 0 }, +{ "label": "22/9", "node": 2638, "naklon": 0 }, +{ "label": "22/10", "node": 2639, "naklon": 0 }, +{ "label": "22/11", "node": 2640, "naklon": 0 }, +{ "label": "22/12", "node": 2641, "naklon": 0 }, +{ "label": "22/13", "node": 2642, "naklon": 0 }, +{ "label": "22/14", "node": 2643, "naklon": 0 }, +{ "label": "22/15", "node": 2644, "naklon": 0 }, +{ "label": "22/16", "node": 2645, "naklon": 0 }, +{ "label": "22/17", "node": 2646, "naklon": 0 }, +{ "label": "22/18", "node": 2647, "naklon": 0 }, +{ "label": "22/19", "node": 2648, "naklon": 0 }, +{ "label": "22/20", "node": 2649, "naklon": 0 }, +{ "label": "22/21", "node": 2650, "naklon": 0 }, +{ "label": "22/22", "node": 2651, "naklon": 0 }, +{ "label": "22/23", "node": 4103, "naklon": 0 }, +{ "label": "22/24", "node": 2653, "naklon": 0 }, +{ "label": "22/25", "node": 2654, "naklon": 0 }, +{ "label": "22/26", "node": 2655, "naklon": 0 }, +{ "label": "22/27", "node": 2656, "naklon": 0 }, +{ "label": "22/28", "node": 2657, "naklon": 0 }, +{ "label": "22/29", "node": 2658, "naklon": 0 }, +{ "label": "22/30", "node": 2659, "naklon": 0 }, +{ "label": "22/31", "node": 2660, "naklon": 0 }, +{ "label": "22/32", "node": 2661, "naklon": 0 }, +{ "label": "22/32/1", "node": 3015, "naklon": 0 }, +{ "label": "22/33", "node": 2662, "naklon": 0 }, +{ "label": "22/34", "node": 2663, "naklon": 0 }, +{ "label": "22/35", "node": 2664, "naklon": 0 }, +{ "label": "22/36", "node": 2665, "naklon": 0 }, +{ "label": "22/37", "node": 2666, "naklon": 0 }, +{ "label": "22/38", "node": 2667, "naklon": 0 }, +{ "label": "22/39", "node": 2668, "naklon": 0 }, +{ "label": "22/40", "node": 2669, "naklon": null }, +{ "label": "22/41", "node": 2670, "naklon": null }, +{ "label": "22/42", "node": 2671, "naklon": null }, +{ "label": "23/9A", "node": 3087, "naklon": 10 }, +{ "label": "23/9B", "node": 3090, "naklon": 10 }, +{ "label": "23/1", "node": 3075, "naklon": 0 }, +{ "label": "23/2", "node": 3089, "naklon": 0 }, +{ "label": "23/3", "node": 3088, "naklon": 0 }, +{ "label": "23/4", "node": 3228, "naklon": 10 }, +{ "label": "23/5", "node": 2751, "naklon": 10 }, +{ "label": "23/6", "node": 3243, "naklon": 10 }, +{ "label": "23/7", "node": 4349, "naklon": 10 }, +{ "label": "23/8", "node": 3102, "naklon": 10 }, +{ "label": "23/10", "node": 3099, "naklon": 10 }, +{ "label": "23/11", "node": 3103, "naklon": 10 }, +{ "label": "23/12", "node": 3093, "naklon": 10 }, +{ "label": "23/13", "node": 3098, "naklon": 10 }, +{ "label": "23/14", "node": 3092, "naklon": 10 }, +{ "label": "23/15", "node": 3233, "naklon": 0 }, +{ "label": "23/16", "node": 3095, "naklon": 0 }, +{ "label": "23/17", "node": 4074, "naklon": 0 }, +{ "label": "23/18", "node": 2729, "naklon": 0 }, +{ "label": "23/19", "node": 3234, "naklon": 0 }, +{ "label": "23/20", "node": 3094, "naklon": 0 }, +{ "label": "23/21", "node": 2817, "naklon": 0 }, +{ "label": "23/22", "node": 3226, "naklon": 0 }, +{ "label": "23/23", "node": 3225, "naklon": 0 }, +{ "label": "23/24", "node": 3237, "naklon": 0 }, +{ "label": "23/25", "node": 4250, "naklon": 0 }, +{ "label": "23/26", "node": 3059, "naklon": 10 }, +{ "label": "23/27", "node": 3238, "naklon": 10 }, +{ "label": "23/28", "node": 3242, "naklon": 10 }, +{ "label": "23/29", "node": 3236, "naklon": 10 }, +{ "label": "23/30", "node": 3112, "naklon": 10 }, +{ "label": "23/31", "node": 3224, "naklon": 0 }, +{ "label": "23/32", "node": 4298, "naklon": 10 }, +{ "label": "23/33", "node": 4150, "naklon": 10 }, +{ "label": "23/34", "node": 3091, "naklon": 10 }, +{ "label": "25/1", "node": 3771, "naklon": 5 }, +{ "label": "25/2", "node": 3777, "naklon": 5 }, +{ "label": "25/3", "node": 3749, "naklon": 5 }, +{ "label": "25/4", "node": 3769, "naklon": 5 }, +{ "label": "25/5", "node": 3765, "naklon": 5 }, +{ "label": "25/6", "node": 3785, "naklon": 5 }, +{ "label": "25/7", "node": 3761, "naklon": 5 }, +{ "label": "25/8", "node": 3758, "naklon": 5 }, +{ "label": "25/9", "node": 3766, "naklon": 5 }, +{ "label": "25/10", "node": 3779, "naklon": 5 }, +{ "label": "25/11", "node": 3899, "naklon": 10 }, +{ "label": "25/12", "node": 3922, "naklon": 10 }, +{ "label": "25/13", "node": 3912, "naklon": 10 }, +{ "label": "25/14", "node": 3933, "naklon": 10 }, +{ "label": "25/15", "node": 3921, "naklon": 10 }, +{ "label": "25/16", "node": 4300, "naklon": 10 }, +{ "label": "25/17", "node": 3927, "naklon": 10 }, +{ "label": "25/18", "node": 3212, "naklon": 10 }, +{ "label": "25/19", "node": 3208, "naklon": 10 }, +{ "label": "25/20", "node": 3207, "naklon": 10 }, +{ "label": "25/21", "node": 4294, "naklon": 10 }, +{ "label": "25/22", "node": 3209, "naklon": 10 }, +{ "label": "25/23", "node": 3745, "naklon": 10 }, +{ "label": "25/24", "node": 3762, "naklon": 10 }, +{ "label": "25/25", "node": 3215, "naklon": 10 }, +{ "label": "25/26", "node": 3210, "naklon": 10 }, +{ "label": "25/27", "node": 3211, "naklon": 10 }, +{ "label": "25/28", "node": 3206, "naklon": 10 }, +{ "label": "25/29", "node": 3918, "naklon": 5 }, +{ "label": "25/30", "node": 3928, "naklon": 5 }, +{ "label": "25/31", "node": 3917, "naklon": 5 }, +{ "label": "25/32", "node": 4029, "naklon": 0 }, +{ "label": "25/33", "node": 4038, "naklon": 0 }, +{ "label": "25/34", "node": 4022, "naklon": 0 }, +{ "label": "25/35", "node": 3937, "naklon": 0 }, +{ "label": "25/36", "node": 3190, "naklon": 0 }, +{ "label": "25/37", "node": 3835, "naklon": 0 }, +{ "label": "25/38", "node": 3201, "naklon": 0 }, +{ "label": "25/39", "node": 3193, "naklon": 0 }, +{ "label": "25/40", "node": 3191, "naklon": 0 }, +{ "label": "25/41", "node": 3203, "naklon": 0 }, +{ "label": "25/42", "node": 4301, "naklon": 0 }, +{ "label": "25/43", "node": 3223, "naklon": 0 }, +{ "label": "25/44", "node": 3202, "naklon": 0 }, +{ "label": "25/45", "node": 3205, "naklon": 0 }, +{ "label": "25/46", "node": 3194, "naklon": 0 }, +{ "label": "25/47", "node": 3198, "naklon": 0 }, +{ "label": "25/48", "node": 3204, "naklon": 0 }, +{ "label": "25/49", "node": 3200, "naklon": 0 }, +{ "label": "25/50", "node": 3216, "naklon": 0 }, +{ "label": "25/51", "node": 3932, "naklon": 5 }, +{ "label": "25/52", "node": 3923, "naklon": 5 }, +{ "label": "25/53", "node": 3913, "naklon": 5 }, +{ "label": "25/54", "node": 3900, "naklon": 5 }, +{ "label": "25/55", "node": 4189, "naklon": 10 }, +{ "label": "25/56", "node": 4191, "naklon": 10 }, +{ "label": "25/57", "node": 3790, "naklon": 10 }, +{ "label": "25/58", "node": 4190, "naklon": 10 }, +{ "label": "25/59", "node": 4302, "naklon": 0 }, +{ "label": "25/60", "node": 4351, "naklon": 0 }, +{ "label": "25/61", "node": 4075, "naklon": 0 }, +{ "label": "25/62", "node": 4071, "naklon": 0 }, +{ "label": "25/63", "node": 3784, "naklon": 0 }, +{ "label": "25/64", "node": 4065, "naklon": 0 }, +{ "label": "25/65", "node": 4297, "naklon": 0 }, +{ "label": "25/66", "node": 4295, "naklon": 0 }, +{ "label": "25/67", "node": 4299, "naklon": 0 }, +{ "label": "25/68", "node": 3772, "naklon": 0 }, +{ "label": "25/69", "node": 3941, "naklon": 0 }, +{ "label": "25/70", "node": 3782, "naklon": 0 }, +{ "label": "25/71", "node": 4068, "naklon": 0 }, +{ "label": "25/72", "node": 4073, "naklon": 0 }, +{ "label": "25/73", "node": 3901, "naklon": 5 }, +{ "label": "25/74", "node": 4296, "naklon": 5 }, +{ "label": "25/75", "node": 3910, "naklon": 5 }, +{ "label": "25/76", "node": 4293, "naklon": 5 }, +{ "label": "25/77", "node": 3919, "naklon": 5 }, +{ "label": "25/78", "node": 3924, "naklon": 5 }, +{ "label": "25/79", "node": 3909, "naklon": 5 }, +{ "label": "25/80", "node": 3896, "naklon": 5 }, +{ "label": "25/81", "node": 3911, "naklon": 5 }, +{ "label": "25/82", "node": 2819, "naklon": 15 }, +{ "label": "25/83", "node": 3776, "naklon": 15 }, +{ "label": "25/84", "node": 3752, "naklon": 15 }, +{ "label": "25/85", "node": 4353, "naklon": 15 }, +{ "label": "25/86", "node": 3791, "naklon": 0 }, +{ "label": "25/87", "node": 3770, "naklon": 0 }, +{ "label": "25/88", "node": 3760, "naklon": 0 }, +{ "label": "25/89", "node": 3115, "naklon": 0 }, +{ "label": "25/90", "node": 3738, "naklon": 0 }, +{ "label": "25/91", "node": 3748, "naklon": 0 }, +{ "label": "25/92", "node": 3753, "naklon": 0 }, +{ "label": "25/93", "node": 3775, "naklon": 0 }, +{ "label": "25/94", "node": 3778, "naklon": 5 }, +{ "label": "25/95", "node": 4078, "naklon": 5 }, +{ "label": "25/96", "node": 4088, "naklon": 5 }, +{ "label": "25/97", "node": 3856, "naklon": 5 }, +{ "label": "25/98", "node": 4084, "naklon": 5 }, +{ "label": "25/99", "node": 4069, "naklon": 5 }, +{ "label": "25/100", "node": 4188, "naklon": 5 }, +{ "label": "25/101", "node": 4064, "naklon": 5 }, +{ "label": "25/102", "node": 3792, "naklon": 5 }, +{ "label": "25/103", "node": 3780, "naklon": 5 }, +{ "label": "25/104", "node": 4034, "naklon": 5 }, +{ "label": "25/105", "node": 4072, "naklon": 5 }, +{ "label": "25/106", "node": 3884, "naklon": 5 }, +{ "label": "25/107", "node": 3793, "naklon": 5 }, +{ "label": "25/108", "node": 3863, "naklon": 5 }, +{ "label": "25/109", "node": 3855, "naklon": 5 }, +{ "label": "33/1", "node": 3846, "naklon": 0 }, +{ "label": "33/2", "node": 3943, "naklon": 0 }, +{ "label": "33/3", "node": 3903, "naklon": 0 }, +{ "label": "33/4", "node": 3982, "naklon": 0 }, +{ "label": "33/5", "node": 3879, "naklon": 0 }, +{ "label": "33/6", "node": 3887, "naklon": 0 }, +{ "label": "33/7", "node": 3920, "naklon": 5 }, +{ "label": "33/8", "node": 3942, "naklon": 5 }, +{ "label": "33/9", "node": 3829, "naklon": null }, +{ "label": "34/79A", "node": 3452, "naklon": 6 }, +{ "label": "34/79B", "node": 3460, "naklon": 6 }, +{ "label": "34/90A", "node": 3443, "naklon": 6 }, +{ "label": "34/90B", "node": 3445, "naklon": 6 }, +{ "label": "34/90C", "node": 3457, "naklon": 6 }, +{ "label": "34/97A", "node": 3461, "naklon": 6 }, +{ "label": "34/97B", "node": 3463, "naklon": 6 }, +{ "label": "34/98A", "node": 3426, "naklon": 6 }, +{ "label": "34/98B", "node": 3444, "naklon": 6 }, +{ "label": "34/99A", "node": 3453, "naklon": 6 }, +{ "label": "34/99B", "node": 3455, "naklon": 6 }, +{ "label": "34/1", "node": 4009, "naklon": 0 }, +{ "label": "34/2", "node": 3602, "naklon": 0 }, +{ "label": "34/3", "node": 3441, "naklon": 0 }, +{ "label": "34/4", "node": 3464, "naklon": 0 }, +{ "label": "34/5", "node": 3883, "naklon": 0 }, +{ "label": "34/6", "node": 4098, "naklon": 0 }, +{ "label": "34/7", "node": 4003, "naklon": 0 }, +{ "label": "34/8", "node": 4004, "naklon": 0 }, +{ "label": "34/9", "node": 3888, "naklon": 0 }, +{ "label": "34/10", "node": 3997, "naklon": 0 }, +{ "label": "34/11", "node": 4006, "naklon": 0 }, +{ "label": "34/12", "node": 4000, "naklon": 0 }, +{ "label": "34/13", "node": 4011, "naklon": 0 }, +{ "label": "34/14", "node": 3999, "naklon": 0 }, +{ "label": "34/15", "node": 3981, "naklon": 0 }, +{ "label": "34/16", "node": 3988, "naklon": 0 }, +{ "label": "34/17", "node": 3986, "naklon": 0 }, +{ "label": "34/18", "node": 3998, "naklon": 0 }, +{ "label": "34/19", "node": 3983, "naklon": 0 }, +{ "label": "34/20", "node": 4005, "naklon": 0 }, +{ "label": "34/21", "node": 4001, "naklon": 0 }, +{ "label": "34/22", "node": 4008, "naklon": 0 }, +{ "label": "34/23", "node": 4002, "naklon": 0 }, +{ "label": "34/24", "node": 3996, "naklon": 0 }, +{ "label": "34/25", "node": 4007, "naklon": 0 }, +{ "label": "34/26", "node": 4113, "naklon": 15 }, +{ "label": "34/27", "node": 3595, "naklon": 5 }, +{ "label": "34/28", "node": 3599, "naklon": 5 }, +{ "label": "34/29", "node": 3601, "naklon": 5 }, +{ "label": "34/30", "node": 4205, "naklon": 0 }, +{ "label": "34/31", "node": 3987, "naklon": null }, +{ "label": "34/32", "node": 4214, "naklon": 0 }, +{ "label": "34/33", "node": 4226, "naklon": 0 }, +{ "label": "34/34", "node": 4209, "naklon": 0 }, +{ "label": "34/35", "node": 4201, "naklon": 0 }, +{ "label": "34/36", "node": 3440, "naklon": 0 }, +{ "label": "34/37", "node": 3465, "naklon": 0 }, +{ "label": "34/38", "node": 3446, "naklon": 0 }, +{ "label": "34/39", "node": 4039, "naklon": 5 }, +{ "label": "34/40", "node": 4057, "naklon": 5 }, +{ "label": "34/41", "node": 3985, "naklon": 0 }, +{ "label": "34/42", "node": 3882, "naklon": 0 }, +{ "label": "34/43", "node": 4040, "naklon": 5 }, +{ "label": "34/44", "node": 3231, "naklon": 0 }, +{ "label": "34/45", "node": 3227, "naklon": 0 }, +{ "label": "34/46", "node": 3431, "naklon": 0 }, +{ "label": "34/47", "node": 4013, "naklon": 0 }, +{ "label": "34/48", "node": 4045, "naklon": 0 }, +{ "label": "34/49", "node": 3949, "naklon": 0 }, +{ "label": "34/50", "node": 3953, "naklon": 0 }, +{ "label": "34/51", "node": 3952, "naklon": 0 }, +{ "label": "34/52", "node": 3995, "naklon": 0 }, +{ "label": "34/53", "node": 3992, "naklon": 0 }, +{ "label": "34/54", "node": 4198, "naklon": 0 }, +{ "label": "34/55", "node": 3935, "naklon": 0 }, +{ "label": "34/56", "node": 4050, "naklon": 0 }, +{ "label": "34/57", "node": 4049, "naklon": 0 }, +{ "label": "34/58", "node": 4054, "naklon": 0 }, +{ "label": "34/59", "node": 3663, "naklon": 6 }, +{ "label": "34/60", "node": 3661, "naklon": 6 }, +{ "label": "34/61", "node": 3664, "naklon": 6 }, +{ "label": "34/62", "node": 3660, "naklon": 6 }, +{ "label": "34/63", "node": 3662, "naklon": 6 }, +{ "label": "34/65", "node": 3665, "naklon": 6 }, +{ "label": "34/66", "node": 3667, "naklon": 6 }, +{ "label": "34/67", "node": 3675, "naklon": 6 }, +{ "label": "34/68", "node": 3666, "naklon": 6 }, +{ "label": "34/69", "node": 3652, "naklon": 6 }, +{ "label": "34/70", "node": 3458, "naklon": 6 }, +{ "label": "34/70/1", "node": 4425, "naklon": 6 }, +{ "label": "34/71", "node": 3459, "naklon": 6 }, +{ "label": "34/72", "node": 3435, "naklon": 6 }, +{ "label": "34/73", "node": 3448, "naklon": 6 }, +{ "label": "34/74", "node": 3451, "naklon": 6 }, +{ "label": "34/75", "node": 3442, "naklon": 6 }, +{ "label": "34/76", "node": 3449, "naklon": 6 }, +{ "label": "34/77", "node": 3450, "naklon": 6 }, +{ "label": "34/78", "node": 3433, "naklon": 6 }, +{ "label": "34/80", "node": 3432, "naklon": 12 }, +{ "label": "34/81", "node": 3470, "naklon": 12 }, +{ "label": "34/82", "node": 3438, "naklon": 12 }, +{ "label": "34/83", "node": 3439, "naklon": 12 }, +{ "label": "34/84", "node": 4028, "naklon": 5 }, +{ "label": "34/85", "node": 3596, "naklon": 5 }, +{ "label": "34/86", "node": 4021, "naklon": 5 }, +{ "label": "34/87", "node": 3437, "naklon": 12 }, +{ "label": "34/88", "node": 3428, "naklon": 12 }, +{ "label": "34/89", "node": 3430, "naklon": 12 }, +{ "label": "34/91", "node": 3454, "naklon": 6 }, +{ "label": "34/92", "node": 3492, "naklon": 6 }, +{ "label": "34/93", "node": 3462, "naklon": 6 }, +{ "label": "34/94", "node": 3427, "naklon": 6 }, +{ "label": "34/95", "node": 3434, "naklon": 6 }, +{ "label": "34/96", "node": 3456, "naklon": 6 }, +{ "label": "34/98/1", "node": 4307, "naklon": 6 }, +{ "label": "35/1", "node": 3968, "naklon": 0 }, +{ "label": "35/2", "node": 3969, "naklon": 0 }, +{ "label": "35/3", "node": 3947, "naklon": 0 }, +{ "label": "35/4", "node": 3979, "naklon": 0 }, +{ "label": "35/5", "node": 3959, "naklon": 0 }, +{ "label": "35/6", "node": 3948, "naklon": 0 }, +{ "label": "35/7", "node": 3961, "naklon": 0 }, +{ "label": "35/8", "node": 3956, "naklon": 0 }, +{ "label": "35/9", "node": 3604, "naklon": 0 }, +{ "label": "35/10", "node": 3944, "naklon": 0 }, +{ "label": "35/11", "node": 3960, "naklon": 0 }, +{ "label": "35/12", "node": 3958, "naklon": 0 }, +{ "label": "35/13", "node": 4036, "naklon": 5 }, +{ "label": "35/18", "node": 3893, "naklon": 5 }, +{ "label": "35/19", "node": 4108, "naklon": 5 }, +{ "label": "35/20", "node": 4017, "naklon": 5 }, +{ "label": "35/21", "node": 3963, "naklon": 0 }, +{ "label": "35/22", "node": 3658, "naklon": 0 }, +{ "label": "35/23", "node": 3975, "naklon": 0 }, +{ "label": "35/24", "node": 3980, "naklon": 0 }, +{ "label": "35/25", "node": 4012, "naklon": 0 }, +{ "label": "35/26", "node": 3655, "naklon": 0 }, +{ "label": "35/27", "node": 3962, "naklon": 0 }, +{ "label": "35/28", "node": 3945, "naklon": 0 }, +{ "label": "35/29", "node": 3569, "naklon": 0 }, +{ "label": "35/30", "node": 3429, "naklon": 0 }, +{ "label": "35/31", "node": 3657, "naklon": 0 }, +{ "label": "35/32", "node": 3646, "naklon": 0 }, +{ "label": "35/33", "node": 3622, "naklon": 0 }, +{ "label": "35/34", "node": 3612, "naklon": 0 }, +{ "label": "35/35", "node": 3955, "naklon": 0 }, +{ "label": "35/37", "node": 3878, "naklon": 0 }, +{ "label": "35/38", "node": 3965, "naklon": 0 }, +{ "label": "35/39", "node": 3970, "naklon": 0 }, +{ "label": "35/40", "node": 3611, "naklon": 0 }, +{ "label": "35/41", "node": 2635, "naklon": 0 }, +{ "label": "35/42", "node": 3978, "naklon": 0 }, +{ "label": "35/43", "node": 4213, "naklon": 0 }, +{ "label": "35/44", "node": 3984, "naklon": 0 }, +{ "label": "35/45", "node": 4218, "naklon": 0 }, +{ "label": "35/46", "node": 3973, "naklon": 0 }, +{ "label": "35/47", "node": 3974, "naklon": 0 }, +{ "label": "35/48", "node": 3759, "naklon": 0 }, +{ "label": "35/49", "node": 3844, "naklon": 0 }, +{ "label": "35/50", "node": 3804, "naklon": 0 }, +{ "label": "35/51", "node": 3831, "naklon": 0 }, +{ "label": "35/52", "node": 3643, "naklon": 0 }, +{ "label": "35/53", "node": 3966, "naklon": 0 }, +{ "label": "35/54", "node": 3971, "naklon": 0 }, +{ "label": "35/55", "node": 3650, "naklon": 6 }, +{ "label": "35/56", "node": 3651, "naklon": 6 }, +{ "label": "35/57", "node": 3669, "naklon": 6 }, +{ "label": "35/58", "node": 3648, "naklon": 6 }, +{ "label": "35/59", "node": 3645, "naklon": 6 }, +{ "label": "35/60", "node": 3659, "naklon": 6 }, +{ "label": "35/61", "node": 3647, "naklon": 6 }, +{ "label": "35/62", "node": 3644, "naklon": 6 }, +{ "label": "35/63", "node": 3671, "naklon": 6 }, +{ "label": "35/64", "node": 3682, "naklon": 6 }, +{ "label": "35/65", "node": 3672, "naklon": 6 }, +{ "label": "35/66", "node": 3683, "naklon": 6 }, +{ "label": "35/67", "node": 3673, "naklon": 6 }, +{ "label": "35/68", "node": 3674, "naklon": 6 }, +{ "label": "35/69", "node": 3679, "naklon": 6 }, +{ "label": "35/70", "node": 3649, "naklon": 6 }, +{ "label": "35/71", "node": 3687, "naklon": 6 }, +{ "label": "35/72", "node": 3677, "naklon": 6 }, +{ "label": "35/73", "node": 3690, "naklon": 6 }, +{ "label": "35/74", "node": 3691, "naklon": 6 }, +{ "label": "35/75", "node": 3676, "naklon": 6 }, +{ "label": "35/76", "node": 3680, "naklon": 6 }, +{ "label": "35/77", "node": 3668, "naklon": 6 }, +{ "label": "35/78", "node": 3681, "naklon": 6 }, +{ "label": "35/79", "node": 3670, "naklon": 6 }, +{ "label": "35/80", "node": 3689, "naklon": 6 }, +{ "label": "35/81", "node": 3678, "naklon": 6 }, +{ "label": "35/82", "node": 3693, "naklon": 6 }, +{ "label": "35/83", "node": 3654, "naklon": null }, +{ "label": "36/1", "node": 4086, "naklon": 0 }, +{ "label": "36/2", "node": 4085, "naklon": 0 }, +{ "label": "36/3", "node": 4083, "naklon": 0 }, +{ "label": "36/4", "node": 4087, "naklon": 0 }, +{ "label": "36/5", "node": 4077, "naklon": 0 }, +{ "label": "36/6", "node": 4082, "naklon": 0 }, +{ "label": "36/7", "node": 4186, "naklon": 0 }, +{ "label": "36/8", "node": 4206, "naklon": 0 }, +{ "label": "36/9", "node": 4080, "naklon": 0 }, +{ "label": "36/10", "node": 4081, "naklon": 0 }, +{ "label": "36/11", "node": 4210, "naklon": 0 }, +{ "label": "36/12", "node": 4079, "naklon": 0 }, +{ "label": "36/13", "node": 4076, "naklon": 0 }, +{ "label": "36/14", "node": 3852, "naklon": 0 }, +{ "label": "36/15", "node": 2813, "naklon": 0 }, +{ "label": "36/16", "node": 4219, "naklon": 0 }, +{ "label": "37/1A", "node": 3104, "naklon": 15 }, +{ "label": "37/1B", "node": 3121, "naklon": 15 }, +{ "label": "37/2", "node": 3113, "naklon": 10 }, +{ "label": "37/3", "node": 3118, "naklon": 10 }, +{ "label": "37/4", "node": 3111, "naklon": 10 }, +{ "label": "37/5", "node": 4020, "naklon": 10 }, +{ "label": "37/6", "node": 3119, "naklon": 10 }, +{ "label": "37/7", "node": 3110, "naklon": 10 }, +{ "label": "37/8", "node": 3108, "naklon": 10 }, +{ "label": "37/12", "node": 3107, "naklon": 0 }, +{ "label": "37/13", "node": 3199, "naklon": 0 }, +{ "label": "37/14", "node": 3120, "naklon": 0 }, +{ "label": "37/15", "node": 3122, "naklon": 0 }, +{ "label": "37/16", "node": 3908, "naklon": 0 }, +{ "label": "37/17", "node": 3114, "naklon": 0 }, +{ "label": "37/18", "node": 3105, "naklon": 0 }, +{ "label": "37/19", "node": 3116, "naklon": 0 }, +{ "label": "37/20", "node": 3106, "naklon": 0 }, +{ "label": "37/21", "node": 2887, "naklon": 5 }, +{ "label": "37/22", "node": 2888, "naklon": 5 }, +{ "label": "37/23", "node": 2877, "naklon": 5 }, +{ "label": "37/24", "node": 2891, "naklon": 5 }, +{ "label": "37/25", "node": 2886, "naklon": 5 }, +{ "label": "37/26", "node": 2892, "naklon": 5 }, +{ "label": "37/27", "node": 2882, "naklon": 5 }, +{ "label": "37/28", "node": 2883, "naklon": 5 }, +{ "label": "37/29", "node": 2876, "naklon": 5 }, +{ "label": "37/30", "node": 3109, "naklon": 5 }, +{ "label": "37/31", "node": 4152, "naklon": 5 }, +{ "label": "37/32", "node": 3117, "naklon": 5 }, +{ "label": "37/33", "node": 2870, "naklon": 5 }, +{ "label": "37/34", "node": 2867, "naklon": 0 }, +{ "label": "37/35", "node": 2865, "naklon": 0 }, +{ "label": "37/36", "node": 3096, "naklon": 0 }, +{ "label": "37/37", "node": 2871, "naklon": 0 }, +{ "label": "37/38", "node": 2884, "naklon": 0 }, +{ "label": "37/39", "node": 2855, "naklon": 0 }, +{ "label": "37/40", "node": 2878, "naklon": 0 }, +{ "label": "37/41", "node": 2889, "naklon": 0 }, +{ "label": "37/42", "node": 2879, "naklon": 0 }, +{ "label": "37/43", "node": 2850, "naklon": 0 }, +{ "label": "37/44", "node": 2894, "naklon": 0 }, +{ "label": "37/45", "node": 2880, "naklon": 0 }, +{ "label": "37/46", "node": 2893, "naklon": 0 }, +{ "label": "37/47", "node": 2890, "naklon": 0 }, +{ "label": "37/48", "node": 4355, "naklon": 0 }, +{ "label": "37/49", "node": 2885, "naklon": 0 }, +{ "label": "37/50", "node": 2875, "naklon": 0 }, +{ "label": "38/30A", "node": 3486, "naklon": 5 }, +{ "label": "38/30B", "node": 3714, "naklon": 0 }, +{ "label": "38/32A", "node": 3483, "naklon": 5 }, +{ "label": "38/32B", "node": 3496, "naklon": 0 }, +{ "label": "38/35A", "node": 3487, "naklon": 5 }, +{ "label": "38/35B", "node": 3498, "naklon": 5 }, +{ "label": "38/38A", "node": 3578, "naklon": 5 }, +{ "label": "38/38B", "node": 3508, "naklon": 5 }, +{ "label": "38/59A", "node": 3787, "naklon": 5 }, +{ "label": "38/59B", "node": 3491, "naklon": 5 }, +{ "label": "38/1", "node": 3568, "naklon": null }, +{ "label": "38/2", "node": 3502, "naklon": 0 }, +{ "label": "38/3", "node": 3836, "naklon": 0 }, +{ "label": "38/4", "node": 3588, "naklon": 0 }, +{ "label": "38/5", "node": 3493, "naklon": 0 }, +{ "label": "38/6", "node": 3580, "naklon": 0 }, +{ "label": "38/7", "node": 3572, "naklon": 0 }, +{ "label": "38/8", "node": 3506, "naklon": 0 }, +{ "label": "38/9", "node": 3503, "naklon": 0 }, +{ "label": "38/10", "node": 3579, "naklon": 0 }, +{ "label": "38/11", "node": 3586, "naklon": 0 }, +{ "label": "38/12", "node": 3495, "naklon": 5 }, +{ "label": "38/13", "node": 3492, "naklon": 5 }, +{ "label": "38/14", "node": 3532, "naklon": 5 }, +{ "label": "38/15", "node": 3574, "naklon": 5 }, +{ "label": "38/16", "node": 4140, "naklon": 5 }, +{ "label": "38/17", "node": 3795, "naklon": 5 }, +{ "label": "38/18", "node": 3788, "naklon": 5 }, +{ "label": "38/19", "node": 3796, "naklon": 5 }, +{ "label": "38/20", "node": 3797, "naklon": 5 }, +{ "label": "38/21", "node": 3798, "naklon": 5 }, +{ "label": "38/22", "node": 3786, "naklon": 5 }, +{ "label": "38/23", "node": 4067, "naklon": 5 }, +{ "label": "38/24", "node": 3773, "naklon": 5 }, +{ "label": "38/25", "node": 3774, "naklon": 5 }, +{ "label": "38/26", "node": 3789, "naklon": 5 }, +{ "label": "38/27", "node": 3520, "naklon": null }, +{ "label": "38/29", "node": 3577, "naklon": 5 }, +{ "label": "38/31", "node": 3530, "naklon": null }, +{ "label": "38/33", "node": 3488, "naklon": 5 }, +{ "label": "38/34", "node": 3505, "naklon": 5 }, +{ "label": "38/36", "node": 3497, "naklon": 5 }, +{ "label": "38/37", "node": 3490, "naklon": 5 }, +{ "label": "38/39", "node": 3585, "naklon": 5 }, +{ "label": "38/40", "node": 3582, "naklon": 5 }, +{ "label": "38/41", "node": 3507, "naklon": 5 }, +{ "label": "38/42", "node": 3484, "naklon": 5 }, +{ "label": "38/43", "node": 3501, "naklon": 5 }, +{ "label": "38/44", "node": 3581, "naklon": 5 }, +{ "label": "38/45", "node": 4192, "naklon": 5 }, +{ "label": "38/46", "node": 3576, "naklon": 5 }, +{ "label": "38/47", "node": 3489, "naklon": 5 }, +{ "label": "38/48", "node": 3573, "naklon": 5 }, +{ "label": "38/49", "node": 3504, "naklon": 5 }, +{ "label": "38/50", "node": 3794, "naklon": 5 }, +{ "label": "38/51", "node": 3485, "naklon": 5 }, +{ "label": "38/52", "node": 3482, "naklon": 5 }, +{ "label": "38/53", "node": 3575, "naklon": 5 }, +{ "label": "38/54", "node": 3499, "naklon": 5 }, +{ "label": "38/55", "node": 3494, "naklon": 5 }, +{ "label": "38/56", "node": 3583, "naklon": 5 }, +{ "label": "38/57", "node": 3570, "naklon": 5 }, +{ "label": "38/58", "node": 3500, "naklon": 0 }, +{ "label": "38/63", "node": 3510, "naklon": null }, +{ "label": "38/64", "node": 3512, "naklon": null }, +{ "label": "38/67", "node": 3535, "naklon": null }, +{ "label": "38/68", "node": 3531, "naklon": null }, +{ "label": "38/69", "node": 3537, "naklon": null }, +{ "label": "39/1", "node": 3522, "naklon": 10 }, +{ "label": "39/2", "node": 4018, "naklon": 10 }, +{ "label": "39/3", "node": 4019, "naklon": 10 }, +{ "label": "39/4", "node": 4154, "naklon": 5 }, +{ "label": "39/5", "node": 3907, "naklon": 5 }, +{ "label": "39/6", "node": 4148, "naklon": 0 }, +{ "label": "39/7", "node": 4153, "naklon": 0 }, +{ "label": "39/8", "node": 3938, "naklon": 0 }, +{ "label": "39/9", "node": 3802, "naklon": 0 }, +{ "label": "39/10", "node": 4015, "naklon": 0 }, +{ "label": "39/11", "node": 3929, "naklon": 0 }, +{ "label": "39/12", "node": 3946, "naklon": 0 }, +{ "label": "39/13", "node": 4014, "naklon": 0 }, +{ "label": "39/14", "node": 4155, "naklon": 0 }, +{ "label": "39/15", "node": 4149, "naklon": 0 }, +{ "label": "39/16", "node": 3642, "naklon": 0 }, +{ "label": "39/17", "node": 3636, "naklon": 5 }, +{ "label": "39/18", "node": 3991, "naklon": 0 }, +{ "label": "39/19", "node": 3994, "naklon": 0 }, +{ "label": "39/20", "node": 3990, "naklon": 0 }, +{ "label": "39/21", "node": 3967, "naklon": 0 }, +{ "label": "39/22", "node": 3977, "naklon": 0 }, +{ "label": "39/23", "node": 3757, "naklon": 15 }, +{ "label": "39/24", "node": 3633, "naklon": 15 }, +{ "label": "39/25", "node": 3744, "naklon": 15 }, +{ "label": "39/26", "node": 4023, "naklon": 5 }, +{ "label": "39/27", "node": 3720, "naklon": 5 }, +{ "label": "39/28", "node": 3734, "naklon": 5 }, +{ "label": "39/29", "node": 3741, "naklon": 5 }, +{ "label": "39/30", "node": 3721, "naklon": 5 }, +{ "label": "39/31", "node": 3845, "naklon": 0 }, +{ "label": "39/32", "node": 3840, "naklon": 0 }, +{ "label": "39/33", "node": 3837, "naklon": null }, +{ "label": "39/34", "node": 3839, "naklon": 0 }, +{ "label": "41/1", "node": 3542, "naklon": null }, +{ "label": "41/2", "node": 3566, "naklon": null }, +{ "label": "41/3", "node": 3548, "naklon": null }, +{ "label": "41/4", "node": 3515, "naklon": null }, +{ "label": "41/5", "node": 3559, "naklon": null }, +{ "label": "41/6", "node": 3509, "naklon": null }, +{ "label": "41/7", "node": 3524, "naklon": null }, +{ "label": "41/8", "node": 3518, "naklon": null }, +{ "label": "41/9", "node": 3182, "naklon": null }, +{ "label": "41/10", "node": 3187, "naklon": null }, +{ "label": "41/11", "node": 3195, "naklon": 0 }, +{ "label": "41/12", "node": 3857, "naklon": 0 }, +{ "label": "41/13", "node": 3183, "naklon": 0 }, +{ "label": "41/14", "node": 3177, "naklon": 0 }, +{ "label": "41/15", "node": 3189, "naklon": 0 }, +{ "label": "41/16", "node": 3186, "naklon": 0 }, +{ "label": "42/1", "node": 3178, "naklon": 0 }, +{ "label": "42/2", "node": 3219, "naklon": 0 }, +{ "label": "42/3", "node": 3475, "naklon": 0 }, +{ "label": "42/4", "node": 3175, "naklon": 0 }, +{ "label": "42/5", "node": 3222, "naklon": 0 }, +{ "label": "42/6", "node": 3221, "naklon": 0 }, +{ "label": "42/7", "node": 3181, "naklon": 0 }, +{ "label": "42/8", "node": 3180, "naklon": 0 }, +{ "label": "42/9", "node": 3218, "naklon": 0 }, +{ "label": "42/10", "node": 3176, "naklon": 0 }, +{ "label": "42/11", "node": 3174, "naklon": 0 }, +{ "label": "42/12", "node": 3220, "naklon": 0 }, +{ "label": "42/13", "node": 3533, "naklon": null }, +{ "label": "42/14", "node": 3543, "naklon": null }, +{ "label": "42/15", "node": 3554, "naklon": null }, +{ "label": "42/16", "node": 3549, "naklon": null }, +{ "label": "43/1", "node": 2857, "naklon": 5 }, +{ "label": "43/2", "node": 2752, "naklon": 5 }, +{ "label": "43/3", "node": 2753, "naklon": 5 }, +{ "label": "43/4", "node": 3024, "naklon": 5 }, +{ "label": "43/5", "node": 2754, "naklon": 5 }, +{ "label": "43/6", "node": 4423, "naklon": 5 }, +{ "label": "43/7", "node": 4368, "naklon": 5 }, +{ "label": "43/8", "node": 2978, "naklon": 5 }, +{ "label": "43/9", "node": 2868, "naklon": 5 }, +{ "label": "43/10", "node": 4377, "naklon": 5 }, +{ "label": "43/11", "node": 2757, "naklon": 5 }, +{ "label": "43/12", "node": 2970, "naklon": 5 }, +{ "label": "43/13", "node": 2758, "naklon": 5 }, +{ "label": "43/14", "node": 4378, "naklon": 5 }, +{ "label": "43/15", "node": 2759, "naklon": 5 }, +{ "label": "43/16", "node": 4342, "naklon": 5 }, +{ "label": "43/17", "node": 3026, "naklon": null }, +{ "label": "43/18", "node": 2986, "naklon": null }, +{ "label": "43/19", "node": 4343, "naklon": null }, +{ "label": "43/20", "node": 2760, "naklon": null }, +{ "label": "43/21", "node": 4379, "naklon": null }, +{ "label": "43/22", "node": 2971, "naklon": null }, +{ "label": "43/23", "node": 2761, "naklon": null }, +{ "label": "43/24", "node": 2762, "naklon": null }, +{ "label": "43/25", "node": 4339, "naklon": null }, +{ "label": "43/26", "node": 4380, "naklon": null }, +{ "label": "43/27", "node": 2975, "naklon": null }, +{ "label": "43/28", "node": 3003, "naklon": null }, +{ "label": "43/29", "node": 4338, "naklon": null }, +{ "label": "43/30", "node": 3002, "naklon": null }, +{ "label": "43/31", "node": 4345, "naklon": null }, +{ "label": "43/32", "node": 2979, "naklon": null }, +{ "label": "43/33", "node": 2989, "naklon": null }, +{ "label": "43/34", "node": 2996, "naklon": null }, +{ "label": "43/35", "node": 2972, "naklon": null }, +{ "label": "43/36", "node": 2988, "naklon": null }, +{ "label": "43/37", "node": 4344, "naklon": null }, +{ "label": "43/38", "node": 3022, "naklon": null }, +{ "label": "43/39", "node": 4341, "naklon": null }, +{ "label": "43/40", "node": 2983, "naklon": null }, +{ "label": "43/41", "node": 2995, "naklon": null }, +{ "label": "43/42", "node": 2763, "naklon": null }, +{ "label": "43/43", "node": 2764, "naklon": null }, +{ "label": "43/44", "node": 2765, "naklon": null }, +{ "label": "43/45", "node": 2766, "naklon": null }, +{ "label": "43/46", "node": 2767, "naklon": null }, +{ "label": "43/47", "node": 2768, "naklon": null }, +{ "label": "43/48", "node": 3018, "naklon": null }, +{ "label": "43/49", "node": 2982, "naklon": null }, +{ "label": "43/50", "node": 3019, "naklon": 0 }, +{ "label": "43/51", "node": 3013, "naklon": null }, +{ "label": "43/52", "node": 3007, "naklon": null }, +{ "label": "43/53", "node": 2980, "naklon": null }, +{ "label": "43/54", "node": 3011, "naklon": null }, +{ "label": "43/55", "node": 2672, "naklon": null }, +{ "label": "43/56", "node": 2673, "naklon": null }, +{ "label": "43/57", "node": 2674, "naklon": null }, +{ "label": "43/58", "node": 2675, "naklon": null }, +{ "label": "43/59", "node": 2676, "naklon": null }, +{ "label": "43/60", "node": 2677, "naklon": null }, +{ "label": "43/61", "node": 2678, "naklon": null }, +{ "label": "43/62", "node": 2679, "naklon": null }, +{ "label": "43/63", "node": 2680, "naklon": null }, +{ "label": "43/64", "node": 2840, "naklon": null }, +{ "label": "43/65", "node": 2682, "naklon": null }, +{ "label": "43/66", "node": 2683, "naklon": null }, +{ "label": "43/67", "node": 2684, "naklon": 0 }, +{ "label": "43/68", "node": 2685, "naklon": null }, +{ "label": "43/69", "node": 2686, "naklon": null }, +{ "label": "43/70", "node": 2687, "naklon": null }, +{ "label": "43/71", "node": 2688, "naklon": null }, +{ "label": "43/72", "node": 2689, "naklon": null }, +{ "label": "43/73", "node": 2690, "naklon": null }, +{ "label": "43/74", "node": 2691, "naklon": null }, +{ "label": "43/75", "node": 2692, "naklon": null }, +{ "label": "43/76", "node": 2693, "naklon": 0 }, +{ "label": "43/77", "node": 2694, "naklon": null }, +{ "label": "43/78", "node": 2695, "naklon": null }, +{ "label": "43/79", "node": 2696, "naklon": 0 }, +{ "label": "43/80", "node": 2697, "naklon": null }, +{ "label": "43/81", "node": 2698, "naklon": 0 }, +{ "label": "43/82", "node": 2699, "naklon": null }, +{ "label": "43/83", "node": 2700, "naklon": 0 }, +{ "label": "43/84", "node": 2744, "naklon": null }, +{ "label": "43/85", "node": 2745, "naklon": 0 }, +{ "label": "43/86", "node": 2746, "naklon": null }, +{ "label": "43/87", "node": 2747, "naklon": 0 }, +{ "label": "43/88", "node": 2748, "naklon": null }, +{ "label": "43/89", "node": 2749, "naklon": 0 }, +{ "label": "43/90", "node": 2841, "naklon": null }, +{ "label": "45/1", "node": 4237, "naklon": 5 }, +{ "label": "45/2", "node": 4226, "naklon": 5 }, +{ "label": "45/3", "node": 4242, "naklon": 5 }, +{ "label": "45/4", "node": 4179, "naklon": 5 }, +{ "label": "45/5", "node": 4247, "naklon": 5 }, +{ "label": "45/6", "node": 4245, "naklon": 5 }, +{ "label": "45/7", "node": 3872, "naklon": 5 }, +{ "label": "45/8", "node": 4175, "naklon": 5 }, +{ "label": "45/9", "node": 4236, "naklon": 5 }, +{ "label": "45/10", "node": 4170, "naklon": 5 }, +{ "label": "45/11", "node": 4238, "naklon": 5 }, +{ "label": "45/12", "node": 4246, "naklon": 5 }, +{ "label": "45/13", "node": 4166, "naklon": 5 }, +{ "label": "45/14", "node": 4227, "naklon": 5 }, +{ "label": "45/15", "node": 4171, "naklon": 5 }, +{ "label": "45/16", "node": 4180, "naklon": 5 }, +{ "label": "45/17", "node": 4244, "naklon": 5 }, +{ "label": "45/18", "node": 4199, "naklon": 5 }, +{ "label": "45/19", "node": 4239, "naklon": 5 }, +{ "label": "45/20", "node": 4207, "naklon": 5 }, +{ "label": "45/21", "node": 4223, "naklon": 5 }, +{ "label": "45/22", "node": 4230, "naklon": 5 }, +{ "label": "45/23", "node": 4233, "naklon": 5 }, +{ "label": "45/24", "node": 4222, "naklon": 5 }, +{ "label": "45/25", "node": 4217, "naklon": 5 }, +{ "label": "45/26", "node": 4243, "naklon": 5 }, +{ "label": "45/27", "node": 4200, "naklon": 5 }, +{ "label": "45/28", "node": 4228, "naklon": 5 }, +{ "label": "45/29", "node": 4211, "naklon": 5 }, +{ "label": "45/30", "node": 4234, "naklon": 5 }, +{ "label": "45/31", "node": 4235, "naklon": 5 }, +{ "label": "45/32", "node": 4203, "naklon": 5 }, +{ "label": "45/33", "node": 4240, "naklon": 5 }, +{ "label": "45/34", "node": 4224, "naklon": 5 }, +{ "label": "45/35", "node": 4232, "naklon": 5 }, +{ "label": "45/36", "node": 4231, "naklon": 5 }, +{ "label": "45/37", "node": 4161, "naklon": 5 }, +{ "label": "45/38", "node": 4225, "naklon": 5 }, +{ "label": "45/39", "node": 4241, "naklon": 5 }, +{ "label": "45/40", "node": 4229, "naklon": 5 }, +{ "label": "45/41", "node": 4221, "naklon": 5 }, +{ "label": "45/42", "node": 4212, "naklon": 5 }, +{ "label": "45/43", "node": 4216, "naklon": 5 }, +{ "label": "45/44", "node": 3864, "naklon": null }, +{ "label": "46/1", "node": 3806, "naklon": 5 }, +{ "label": "46/2", "node": 3813, "naklon": 5 }, +{ "label": "46/3", "node": 3815, "naklon": 5 }, +{ "label": "46/4", "node": 3807, "naklon": 5 }, +{ "label": "46/5", "node": 3895, "naklon": 5 }, +{ "label": "46/6", "node": 3809, "naklon": 5 }, +{ "label": "46/7", "node": 3820, "naklon": 5 }, +{ "label": "46/8", "node": 3805, "naklon": 5 }, +{ "label": "46/9", "node": 3894, "naklon": 0 }, +{ "label": "46/10", "node": 4055, "naklon": 0 }, +{ "label": "46/11", "node": 3812, "naklon": 5 }, +{ "label": "46/12", "node": 3822, "naklon": 5 }, +{ "label": "46/13", "node": 3821, "naklon": 5 }, +{ "label": "46/14", "node": 3808, "naklon": 5 }, +{ "label": "46/15", "node": 3799, "naklon": 5 }, +{ "label": "46/16", "node": 3816, "naklon": 5 }, +{ "label": "46/17", "node": 3751, "naklon": 5 }, +{ "label": "46/18", "node": 3814, "naklon": 5 }, +{ "label": "46/19", "node": 4044, "naklon": 0 }, +{ "label": "46/20", "node": 3931, "naklon": 0 }, +{ "label": "46/21", "node": 3902, "naklon": 5 }, +{ "label": "46/22", "node": 3916, "naklon": 5 }, +{ "label": "46/23", "node": 3892, "naklon": 5 }, +{ "label": "46/24", "node": 3914, "naklon": 5 }, +{ "label": "46/25", "node": 3898, "naklon": 5 }, +{ "label": "46/26", "node": 3897, "naklon": 5 }, +{ "label": "46/27", "node": 3885, "naklon": 5 }, +{ "label": "46/28", "node": 3906, "naklon": 5 }, +{ "label": "46/29", "node": 3930, "naklon": 0 }, +{ "label": "46/30", "node": 3936, "naklon": 0 }, +{ "label": "46/31", "node": 3860, "naklon": 5 }, +{ "label": "46/32", "node": 3841, "naklon": 5 }, +{ "label": "46/33", "node": 3873, "naklon": 5 }, +{ "label": "46/34", "node": 3854, "naklon": 5 }, +{ "label": "46/35", "node": 3939, "naklon": 5 }, +{ "label": "46/36", "node": 3858, "naklon": 5 }, +{ "label": "46/37", "node": 3940, "naklon": 5 }, +{ "label": "46/38", "node": 4035, "naklon": 5 }, +{ "label": "47/1", "node": 3373, "naklon": 0 }, +{ "label": "47/2", "node": 3374, "naklon": 0 }, +{ "label": "47/3", "node": 3384, "naklon": 0 }, +{ "label": "47/4", "node": 3385, "naklon": 0 }, +{ "label": "48/1", "node": 4051, "naklon": 5 }, +{ "label": "48/2", "node": 4041, "naklon": 5 }, +{ "label": "48/3", "node": 4056, "naklon": 5 }, +{ "label": "48/4", "node": 3875, "naklon": 5 }, +{ "label": "48/5", "node": 4061, "naklon": 5 }, +{ "label": "48/6", "node": 4047, "naklon": 5 }, +{ "label": "48/7", "node": 4060, "naklon": 5 }, +{ "label": "48/8", "node": 4059, "naklon": 5 }, +{ "label": "48/9", "node": 4058, "naklon": 5 }, +{ "label": "48/10", "node": 3635, "naklon": 5 }, +{ "label": "48/11", "node": 3640, "naklon": 5 }, +{ "label": "48/12", "node": 3747, "naklon": 5 }, +{ "label": "48/13", "node": 3629, "naklon": 5 }, +{ "label": "48/14", "node": 4048, "naklon": 5 }, +{ "label": "48/15", "node": 4063, "naklon": 5 }, +{ "label": "48/16", "node": 4062, "naklon": 5 }, +{ "label": "48/17", "node": 4043, "naklon": 5 }, +{ "label": "48/18", "node": 4052, "naklon": 5 }, +{ "label": "48/19", "node": 4042, "naklon": 5 }, +{ "label": "48/20", "node": 4053, "naklon": 5 }, +{ "label": "50/15A", "node": 4167, "naklon": null }, +{ "label": "50/15B", "node": 4159, "naklon": null }, +{ "label": "50/1", "node": 4183, "naklon": 0 }, +{ "label": "50/2", "node": 4157, "naklon": 0 }, +{ "label": "50/3", "node": 4160, "naklon": 0 }, +{ "label": "50/4", "node": 4173, "naklon": 0 }, +{ "label": "50/5", "node": 4177, "naklon": 0 }, +{ "label": "50/6", "node": 4174, "naklon": 0 }, +{ "label": "50/7", "node": 4178, "naklon": 0 }, +{ "label": "50/8", "node": 4195, "naklon": 0 }, +{ "label": "50/9", "node": 4169, "naklon": 0 }, +{ "label": "50/10", "node": 4162, "naklon": 0 }, +{ "label": "50/11", "node": 4158, "naklon": 0 }, +{ "label": "50/12", "node": 4182, "naklon": 0 }, +{ "label": "50/13", "node": 4194, "naklon": 0 }, +{ "label": "50/14", "node": 4184, "naklon": 0 }, +{ "label": "50/16", "node": 4197, "naklon": null }, +{ "label": "50/17", "node": 4164, "naklon": null }, +{ "label": "50/18", "node": 3306, "naklon": null }, +{ "label": "50/19", "node": 4168, "naklon": null }, +{ "label": "50/20", "node": 4193, "naklon": null }, +{ "label": "50/21", "node": 4187, "naklon": null }, +{ "label": "50/22", "node": 4163, "naklon": null }, +{ "label": "50/23", "node": 4165, "naklon": null }, +{ "label": "50/24", "node": 4185, "naklon": null }, +{ "label": "50/25", "node": 3904, "naklon": null }, +{ "label": "53/1", "node": 2619, "naklon": 0 }, +{ "label": "53/2", "node": 2623, "naklon": 0 }, +{ "label": "53/3", "node": 2617, "naklon": 0 }, +{ "label": "53/4", "node": 2622, "naklon": 0 }, +{ "label": "53/5", "node": 2618, "naklon": 0 }, +{ "label": "53/6", "node": 2626, "naklon": 0 }, +{ "label": "53/7", "node": 2869, "naklon": 0 }, +{ "label": "53/8", "node": 2613, "naklon": 0 }, +{ "label": "53/9", "node": 2608, "naklon": 0 }, +{ "label": "53/10", "node": 2611, "naklon": 0 }, +{ "label": "53/11", "node": 2598, "naklon": 0 }, +{ "label": "53/12", "node": 3528, "naklon": 0 }, +{ "label": "53/13", "node": 3545, "naklon": 0 }, +{ "label": "53/14", "node": 2620, "naklon": 0 }, +{ "label": "53/15", "node": 2612, "naklon": 0 }, +{ "label": "53/16", "node": 2615, "naklon": 0 }, +{ "label": "53/17", "node": 3722, "naklon": 0 }, +{ "label": "53/18", "node": 2624, "naklon": 0 }, +{ "label": "53/19", "node": 2609, "naklon": 0 }, +{ "label": "53/20", "node": 2625, "naklon": 0 }, +{ "label": "53/21", "node": 2602, "naklon": 0 }, +{ "label": "53/22", "node": 2610, "naklon": 0 }, +{ "label": "53/23", "node": 2599, "naklon": 0 }, +{ "label": "53/24", "node": 2605, "naklon": 0 }, +{ "label": "53/25", "node": 2593, "naklon": 0 }, +{ "label": "53/26", "node": 3074, "naklon": 0 }, +{ "label": "53/27", "node": 2740, "naklon": 0 }, +{ "label": "53/28", "node": 2614, "naklon": 0 }, +{ "label": "53/29", "node": 2601, "naklon": 0 }, +{ "label": "53/30", "node": 4196, "naklon": 0 }, +{ "label": "53/31", "node": 2607, "naklon": 0 }, +{ "label": "53/32", "node": 2582, "naklon": 0 }, +{ "label": "53/33", "node": 2594, "naklon": 0 }, +{ "label": "53/34", "node": 2589, "naklon": 0 }, +{ "label": "53/35", "node": 2596, "naklon": 0 }, +{ "label": "53/36", "node": 2603, "naklon": 0 }, +{ "label": "53/37", "node": 2597, "naklon": 0 }, +{ "label": "53/38", "node": 2590, "naklon": 0 }, +{ "label": "53/39", "node": 2581, "naklon": 0 }, +{ "label": "53/40", "node": 2583, "naklon": 0 }, +{ "label": "53/41", "node": 2580, "naklon": 0 }, +{ "label": "53/42", "node": 2579, "naklon": 0 }, +{ "label": "53/43", "node": 2797, "naklon": 0 }, +{ "label": "53/44", "node": 2577, "naklon": 0 }, +{ "label": "53/45", "node": 2586, "naklon": 0 }, +{ "label": "53/46", "node": 2588, "naklon": 0 }, +{ "label": "53/47", "node": 2591, "naklon": 0 }, +{ "label": "53/48", "node": 2592, "naklon": 0 }, +{ "label": "53/49", "node": 2573, "naklon": 0 }, +{ "label": "53/50", "node": 2595, "naklon": 0 }, +{ "label": "53/51", "node": 2587, "naklon": 0 }, +{ "label": "53/52", "node": 2578, "naklon": 0 }, +{ "label": "53/53", "node": 2574, "naklon": 0 }, +{ "label": "53/54", "node": 2571, "naklon": 0 }, +{ "label": "53/55", "node": 2570, "naklon": 0 }, +{ "label": "53/56", "node": 2576, "naklon": 0 }, +{ "label": "53/57", "node": 2881, "naklon": 0 }, +{ "label": "53/58", "node": 2575, "naklon": 0 }, +{ "label": "53/59", "node": 2572, "naklon": 0 }, +{ "label": "53/60", "node": 2569, "naklon": 0 }, +{ "label": "55/1", "node": 4324, "naklon": 0 }, +{ "label": "55/2", "node": 4319, "naklon": 0 }, +{ "label": "55/3", "node": 4327, "naklon": 0 }, +{ "label": "55/4", "node": 4333, "naklon": 0 }, +{ "label": "55/5", "node": 4332, "naklon": 0 }, +{ "label": "55/6", "node": 4320, "naklon": 0 }, +{ "label": "55/7", "node": 4317, "naklon": 0 }, +{ "label": "55/8", "node": 4318, "naklon": 0 }, +{ "label": "55/9", "node": 4328, "naklon": 0 }, +{ "label": "55/10", "node": 4323, "naklon": 0 }, +{ "label": "55/11", "node": 4325, "naklon": 0 }, +{ "label": "55/12", "node": 4326, "naklon": 0 }, +{ "label": "55/13", "node": 4316, "naklon": 0 }, +{ "label": "55/14", "node": 4322, "naklon": 0 }, +{ "label": "55/15", "node": 4331, "naklon": 0 }, +{ "label": "55/16", "node": 4321, "naklon": 0 }, +{ "label": "55/17", "node": 4315, "naklon": 0 }, +{ "label": "55/18", "node": 4329, "naklon": 0 }, +{ "label": "55/19", "node": 4334, "naklon": 0 }, +{ "label": "55/20", "node": 4330, "naklon": 0 } +]; + +module.exports = { naklony }; diff --git a/RVO36/databases/modbus_config.js b/RVO36/databases/modbus_config.js new file mode 100755 index 0000000..b73116a --- /dev/null +++ b/RVO36/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/RVO36/databases/nodes.table b/RVO36/databases/nodes.table new file mode 100755 index 0000000..0ca34b9 --- /dev/null +++ b/RVO36/databases/nodes.table @@ -0,0 +1,17 @@ +node:number|pole_number:string|node_type:string|tbname:string|line:number|profile:string|processed:boolean|status:boolean|time_of_last_communication:number ++|4219|16|NEMA|DbQY6zyveZRwK5drV0Z9xRAjoE4XJM83N9xl2nWq|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573838297|............. ++|2657|15|NEMA|BaY3Xpy1EbKGjLq2O7mGRD0rx8owgQz9P4dDJRmN|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573825498|............. ++|4086|1|NEMA|2O14VBzl8aDmWdNw3A512MAGyZ5qLJoEMpj6R9ng|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573834941|............. ++|4085|2|NEMA|pE5X8NQPaow6vlOZxk6gz17q42ezGBMyWgDVjR3L|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573834478|............. ++|4083|3|NEMA|6lQGaY9RDywdVzObj0P14jkPg4NBn3exEK51LWZq|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573843602|............. ++|4087|4|NEMA|m6EYyZoJ4gWexdjVPARN1PARDOq9wv2N5XzKGplr|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573835101|............. ++|4077|5|NEMA|JzwxZXOvDj1bVrN4nkWwOLk8qdyBl3MRKLpGPgaQ|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573832305|............. ++|4082|6|NEMA|g9OxBZ5KRwNznlY6pAp6EPkWXvjdEL4eGQobMDy2|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573833184|............. ++|4186|7|NEMA|OzNMgZ9n43qPbjXmy7zWrYA2DKdYvW5e6pxGRrVa|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573835389|............. ++|4206|8|NEMA|JX1ObgmqGZ54DMyYL7a9XV7EVdve38WKRzwjNrQ9|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573835916|............. ++|4080|9|NEMA|RvmwNz8QPblKp41GD7lDwp7JrLVYoBO92dMegn6W|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573806933|............. ++|3852|14|NEMA|PjLblDgRBO6WQqnxmkJ5aY0Jv3ewZN4p5a89yKdY|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573826553|............. ++|4081|10|NEMA|RO8rjaBDy21qPQJzW7oDwdApK3xmNleVZg9Ed4Gw|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573808658|............. ++|4210|11|NEMA|3JjOWdylwgNLzxVab7NERykZ2vG64rq8PEB5QmDo|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573836188|............. ++|4079|12|NEMA|Z5KyJe9nEg1QNbWlX0wWd90oDjBLdqzR83VGv624|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573806789|............. ++|4076|13|NEMA|1JMYvnx2RzKEo4aWQ7DmaVAL8yZV3m9NBePXbrdj|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573831522|............. diff --git a/RVO36/databases/nodes_original/nodes_original.table b/RVO36/databases/nodes_original/nodes_original.table new file mode 100755 index 0000000..4dd490b --- /dev/null +++ b/RVO36/databases/nodes_original/nodes_original.table @@ -0,0 +1 @@ +[{"4219": "DbQY6zyveZRwK5drV0Z9xRAjoE4XJM83N9xl2nWq"}, {"2657": "BaY3Xpy1EbKGjLq2O7mGRD0rx8owgQz9P4dDJRmN"}, {"4086": "2O14VBzl8aDmWdNw3A512MAGyZ5qLJoEMpj6R9ng"}, {"4085": "pE5X8NQPaow6vlOZxk6gz17q42ezGBMyWgDVjR3L"}, {"4083": "6lQGaY9RDywdVzObj0P14jkPg4NBn3exEK51LWZq"}, {"4087": "m6EYyZoJ4gWexdjVPARN1PARDOq9wv2N5XzKGplr"}, {"4077": "JzwxZXOvDj1bVrN4nkWwOLk8qdyBl3MRKLpGPgaQ"}, {"4082": "g9OxBZ5KRwNznlY6pAp6EPkWXvjdEL4eGQobMDy2"}, {"4186": "OzNMgZ9n43qPbjXmy7zWrYA2DKdYvW5e6pxGRrVa"}, {"4206": "JX1ObgmqGZ54DMyYL7a9XV7EVdve38WKRzwjNrQ9"}, {"4080": "RvmwNz8QPblKp41GD7lDwp7JrLVYoBO92dMegn6W"}, {"3852": "PjLblDgRBO6WQqnxmkJ5aY0Jv3ewZN4p5a89yKdY"}, {"4081": "RO8rjaBDy21qPQJzW7oDwdApK3xmNleVZg9Ed4Gw"}, {"4210": "3JjOWdylwgNLzxVab7NERykZ2vG64rq8PEB5QmDo"}, {"4079": "Z5KyJe9nEg1QNbWlX0wWd90oDjBLdqzR83VGv624"}, {"4076": "1JMYvnx2RzKEo4aWQ7DmaVAL8yZV3m9NBePXbrdj"}] \ No newline at end of file diff --git a/RVO36/databases/notifications.table b/RVO36/databases/notifications.table new file mode 100755 index 0000000..f7c96cb --- /dev/null +++ b/RVO36/databases/notifications.table @@ -0,0 +1,41 @@ +key:string|weight:string|sk:string|en:string ++|switching_profile_point_applied_to_line|INFORMATIONAL|Aplikovaný bod spínacieho profilu na línií č. ${line} : ${value}|Switching profile point applied to line no. ${line} : ${value}|............... ++|dusk_has_occured|INFORMATIONAL|Nastal súmrak: ${value}|Dusk has occured: ${value}|............... ++|dawn_has_occured|INFORMATIONAL|Nastal úsvit: ${value}|Dawn has occured: ${value}|............... ++|dimming_profile_was_successfully_received_by_node|NOTICE|Stmievací profil bol úspešne prijatý nodom č. ${node}|Dimming profile was successfully received by node no. ${node}|............... ++|master_node_is_responding_again|NOTICE|Master node začal znovu odpovedať|Master node is responding again|............... ++|command_was_sent_from_terminal_interface|DEBUG|Z terminálu bol odoslaný príkaz|A command was sent from terminal interface|............... ++|master_node_is_not_responding|ALERT|Master node neodpovedá|Master node is not responding|............... ++|configuration_of_dimming_profile_to_node_failed|ALERT|Konfigurácia stmievacieho profilu pre node č. ${node} zlyhala|Configuration of dimming profile to node no. ${node} has failed|............... ++|circuit_breaker_was_turned_on_line|NOTICE|Zapnutie ističa na línii č. ${line}|Circuit breaker was turned on - line no. ${line}|............... ++|circuit_breaker_was_turned_off_line|ERROR|Vypnutie ističa na línií č. ${line}|Circuit breaker was turned off - line no. ${line}|............... ++|dimming_profile_was_processed_for_node|INFORMATIONAL|Stmievací profil bol spracovaný pre node č. ${node}|Dimming profile was processed for node no. ${node}|............... ++|switching_profile_was_processed_for_line|INFORMATIONAL|Spínací profil bol spracovaný pre líniu č. ${line}|Switching profile was processed for line no. ${line}|............... ++|thermometer_is_not_responding|WARNING|Teplomer neodpovedá|Thermometer is not responding|............... ++|thermometer_is_responding_again|NOTICE|Teplomer znovu odpovedá|Thermometer is responding again|............... ++|thermometer_sends_invalid_data|WARNING|Teplomer posiela neplatné hodnoty|Thermometer sends invalid data|............... ++|main_switch_has_been_turned_off|CRITICAL|Hlavný vypínač bol vypnutý|Main switch has been turned off|............... ++|main_switch_has_been_turned_on|NOTICE|Hlavný vypínač bol zapnutý|Main switch has been turned on|............... ++|power_supply_has_disconnected_input|ALERT|Napájací zdroj nemá napätie na vstupe|Power supply has disconnected input|............... ++|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_main_open|NOTICE|Hlavné dvere boli otvorené|Main door has been opened|............... ++|door_em_open|NOTICE|Dvere silovej časti boli otvorené|Power door has been opened|............... ++|door_main_open_without_permission|WARNING|Hlavné dvere boli otvorené bez povolenia - zapnutá siréna|Main door has been opened without permission - alarm is on|............... ++|door_em_open_without_permission|WARNING|Dvere silovej časti boli otvorené bez povolenia|Power door has been opened without permission|............... ++|door_main_close|NOTICE|Hlavné dvere boli zatvorené|Main door has been closed|............... ++|door_em_close|NOTICE|Dvere silovej časti boli zatvorené|Power door has been closed|............... ++|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|............... ++|electrometer_ok|NOTICE|Elektromer znovu odpovedá|Electrometer is responding again|............... ++|no_voltage_on_phase|CRITICAL|Na fáze č. ${phase} nie je napätie|No voltage detected on phase no. ${phase}|............... ++|voltage_on_phase_restored|NOTICE|Napätie na fáze č. ${phase} bolo obnovené|Voltage on phase no. ${phase} has been restored|............... ++|flow_start|NOTICE|FLOW bol spustený|FLOW has been started |............... ++|twilight_sensor_nok|ERROR|Sensor súmraku neodpovedá|Twilight sensor is not responding|............... ++|twilight_sensor_ok|NOTICE|Sensor súmraku znovu odpovedá|Twilight sensor is responding again|............... ++|lamps_have_turned_on|NOTICE|Lampy sa zapli|Lamps have turned on|............... ++|lamps_have_turned_off|NOTICE|Lampy sa vypli|Lamps have turned off|............... ++|flow_restart|NOTICE|FLOW bol reštartovaný|FLOW has been restarted|............... ++|nodes_db_changed|NOTICE|Zmena v node databáze|Node db has changed|............... diff --git a/RVO36/databases/pins.table b/RVO36/databases/pins.table new file mode 100755 index 0000000..0eb3d05 --- /dev/null +++ b/RVO36/databases/pins.table @@ -0,0 +1,14 @@ +pin:string|type:string|line:number +*|input1_01|door_condition|0|........... +*|input1_02|rotary_switch_state|0|........... +*|input1_03|rotary_switch_state|0|........... +*|input1_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/RVO36/databases/relays.table b/RVO36/databases/relays.table new file mode 100755 index 0000000..dcf4f51 --- /dev/null +++ b/RVO36/databases/relays.table @@ -0,0 +1,5 @@ +line:number|tbname:string|contactor:number|profile:string ++|0|2O14VBzl8aDmWdNw3A59v9AGyZ5qLJoEMpj6R9ng|1||........... ++|1|zrR51V2ajQ9ZLygPKkEmr4kYDq38xOJolENBXGnv|9|{"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|BaY3Xpy1EbKGjLq2O7mGMD0rx8owgQz9P4dDJRmN|9|{"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|DbQY6zyveZRwK5drV0Z9mRAjoE4XJM83N9xl2nWq|9|{"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}|.................................................................................................................. diff --git a/RVO36/databases/settings.table b/RVO36/databases/settings.table new file mode 100755 index 0000000..9c1578a --- /dev/null +++ b/RVO36/databases/settings.table @@ -0,0 +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|project_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|cloud_topic:string|has_main_switch:boolean|daily_report:boolean|send_changed_node_numbers:boolean ++|rvo_senica_36_10.0.0.138|en|28.E3519C0E0000|48.70826502|17.28455203|192.168.252.1|rvo_senica_36_10.0.0.138|7U5v3AcFMTZDw4vjEalv|1883|0|76|unipi|ttyUSB0|1|20|5|6|1|u138|0|1|1|................................................... diff --git a/RVO36/databases/tbdata.nosql b/RVO36/databases/tbdata.nosql new file mode 100755 index 0000000..a92d4be --- /dev/null +++ b/RVO36/databases/tbdata.nosql @@ -0,0 +1,4 @@ +-"2O14VBzl8aDmWdNw3A59v9AGyZ5qLJoEMpj6R9ng":[{"ts":1760522145365,"values":{"_event":{"type":"notice","status":"new","source":{"func":"modbus_reader","component":"1699965957410","component_name":"Modbus reader","edge":"2O14VBzl8aDmWdNw3A59v9AGyZ5qLJoEMpj6R9ng"},"message":{"sk":"rvo_senica_36_10.0.0.138: FLOW bol reštartovaný","en":"rvo_senica_36_10.0.0.138: FLOW has been restarted"},"message_data":""}}}],"id":"3000176001lu71b"} +-"2O14VBzl8aDmWdNw3A59v9AGyZ5qLJoEMpj6R9ng":[{"ts":1760522145440,"values":{"edge_fw_version":"2025-10-08","maintenance_mode":false}}],"id":"3000176002lu70b"} +-"2O14VBzl8aDmWdNw3A59v9AGyZ5qLJoEMpj6R9ng":[{"ts":1760522145453,"values":{"statecode":2,"power_mode":"Automatic"}}],"id":"3000176004lu70b"} +-"2O14VBzl8aDmWdNw3A59v9AGyZ5qLJoEMpj6R9ng":[{"ts":1760522145476,"values":{"_event":{"type":"notice","status":"new","source":{"func":"rsPort.open()","component":"1699963668903","component_name":"DIDO_Controller","edge":"2O14VBzl8aDmWdNw3A59v9AGyZ5qLJoEMpj6R9ng"},"message":{"sk":"rvo_senica_36_10.0.0.138: FLOW bol spustený","en":"rvo_senica_36_10.0.0.138: FLOW has been started "},"message_data":""}}}],"id":"3000176006lu70b"} diff --git a/RVO36/databases/tbdatacloud.nosql b/RVO36/databases/tbdatacloud.nosql new file mode 100755 index 0000000..bb1bf53 --- /dev/null +++ b/RVO36/databases/tbdatacloud.nosql @@ -0,0 +1,3 @@ +-"2O14VBzl8aDmWdNw3A59v9AGyZ5qLJoEMpj6R9ng":[{"ts":1760522145440,"values":{"edge_fw_version":"2025-10-08","maintenance_mode":false}}],"id":"3000176003lu71b"} +-"2O14VBzl8aDmWdNw3A59v9AGyZ5qLJoEMpj6R9ng":[{"ts":1760522145453,"values":{"statecode":2,"power_mode":"Automatic"}}],"id":"3000176005lu71b"} +-"2O14VBzl8aDmWdNw3A59v9AGyZ5qLJoEMpj6R9ng":[{"ts":1760522145476,"values":{"_event":{"type":"notice","status":"new","source":{"func":"rsPort.open()","component":"1699963668903","component_name":"DIDO_Controller","edge":"2O14VBzl8aDmWdNw3A59v9AGyZ5qLJoEMpj6R9ng"},"message":{"sk":"rvo_senica_36_10.0.0.138: FLOW bol spustený","en":"rvo_senica_36_10.0.0.138: FLOW has been started "},"message_data":""}}}],"id":"3000176007lu71b"} diff --git a/RVO36/databases/total_energy.js b/RVO36/databases/total_energy.js new file mode 100755 index 0000000..dde340e --- /dev/null +++ b/RVO36/databases/total_energy.js @@ -0,0 +1,38 @@ +//key is rvo_number, value is max energy when lamps are on +const total_energy = { + 1: 580, + 2: 1100, + 3: 3700, + 4: 4100, + 7: 360, + 12: 1700, + 13: 5400, + 14: 440, + 15: 6100, + 16: 4800, + 20: 1600, + 21: 1000, + 22: 2600, + 23: 1000, + 25: 2600, + 33: 240, + 34: 4000, + 35: 2700, + 36: 820, + 37: 1400, + 35: 3500, + 39: 1170, + 41: 740, + 42: 660, + 43: 4900, + 45: 930, + 46: 700, + 47: 1100, + 48: 1500, + 50: 3200, + 53: 1250, + 55: 1000, + 56: 5500 +} + +module.exports = total_energy; diff --git a/RVO36/debug.js b/RVO36/debug.js new file mode 100755 index 0000000..9818194 --- /dev/null +++ b/RVO36/debug.js @@ -0,0 +1,16 @@ +// =================================================== +// FOR DEVELOPMENT +// Total.js - framework for Node.js platform +// https://www.totaljs.com +// =================================================== + +const options = {}; + +// options.ip = '127.0.0.1'; +// options.port = parseInt(process.argv[2]); +// options.config = { name: 'Total.js' }; +// options.sleep = 3000; +// options.inspector = 9229; +// options.watch = ['private']; + +require('total.js/debug')(options); \ No newline at end of file diff --git a/RVO36/err.txt b/RVO36/err.txt new file mode 100755 index 0000000..c6929d8 --- /dev/null +++ b/RVO36/err.txt @@ -0,0 +1,249 @@ +[2024-11-21T12:19:15.020] [ERROR] errLogs - uncaughtException: write EPIPE +[2024-11-21T12:19:15.021] [ERROR] errLogs - Error: write EPIPE + at afterWriteDispatched (internal/stream_base_commons.js:156:25) + at writeGeneric (internal/stream_base_commons.js:147:3) + at Socket._writeGeneric (net.js:798:11) + at Socket._write (net.js:810:8) + at writeOrBuffer (internal/streams/writable.js:358:12) + at Socket.Writable.write (internal/streams/writable.js:303:10) + at /home/unipi/flowserver/node_modules/total.js/index.js:16529:17 + at afterWrite (internal/streams/writable.js:466:5) + at onwrite (internal/streams/writable.js:446:7) + at DeflateRaw.afterTransform (internal/streams/transform.js:103:3) +[2024-11-21T12:19:15.022] [ERROR] errLogs - uncaughtException: write EPIPE +[2024-11-21T12:19:15.023] [ERROR] errLogs - Error: write EPIPE + at afterWriteDispatched (internal/stream_base_commons.js:156:25) + at writeGeneric (internal/stream_base_commons.js:147:3) + at Socket._writeGeneric (net.js:798:11) + at Socket._write (net.js:810:8) + at writeOrBuffer (internal/streams/writable.js:358:12) + at Socket.Writable.write (internal/streams/writable.js:303:10) + at /home/unipi/flowserver/node_modules/total.js/index.js:16529:17 + at afterWrite (internal/streams/writable.js:466:5) + at onwrite (internal/streams/writable.js:446:7) + at DeflateRaw.afterTransform (internal/streams/transform.js:103:3) +[2024-11-21T12:19:15.035] [ERROR] errLogs - uncaughtException: write EPIPE +[2024-11-21T12:19:15.036] [ERROR] errLogs - Error: write EPIPE + at afterWriteDispatched (internal/stream_base_commons.js:156:25) + at writeGeneric (internal/stream_base_commons.js:147:3) + at Socket._writeGeneric (net.js:798:11) + at Socket._write (net.js:810:8) + at writeOrBuffer (internal/streams/writable.js:358:12) + at Socket.Writable.write (internal/streams/writable.js:303:10) + at /home/unipi/flowserver/node_modules/total.js/index.js:16529:17 + at afterWrite (internal/streams/writable.js:466:5) + at onwrite (internal/streams/writable.js:446:7) + at DeflateRaw.afterTransform (internal/streams/transform.js:103:3) +[2024-11-21T12:22:19.111] [ERROR] errLogs - uncaughtException: write EPIPE +[2024-11-21T12:22:19.112] [ERROR] errLogs - Error: write EPIPE + at afterWriteDispatched (internal/stream_base_commons.js:156:25) + at writeGeneric (internal/stream_base_commons.js:147:3) + at Socket._writeGeneric (net.js:798:11) + at Socket._write (net.js:810:8) + at writeOrBuffer (internal/streams/writable.js:358:12) + at Socket.Writable.write (internal/streams/writable.js:303:10) + at /home/unipi/flowserver/node_modules/total.js/index.js:16529:17 + at afterWrite (internal/streams/writable.js:466:5) + at onwrite (internal/streams/writable.js:446:7) + at DeflateRaw.afterTransform (internal/streams/transform.js:103:3) +[2024-11-21T12:22:19.113] [ERROR] errLogs - uncaughtException: write EPIPE +[2024-11-21T12:22:19.113] [ERROR] errLogs - Error: write EPIPE + at afterWriteDispatched (internal/stream_base_commons.js:156:25) + at writeGeneric (internal/stream_base_commons.js:147:3) + at Socket._writeGeneric (net.js:798:11) + at Socket._write (net.js:810:8) + at writeOrBuffer (internal/streams/writable.js:358:12) + at Socket.Writable.write (internal/streams/writable.js:303:10) + at /home/unipi/flowserver/node_modules/total.js/index.js:16529:17 + at afterWrite (internal/streams/writable.js:466:5) + at onwrite (internal/streams/writable.js:446:7) + at DeflateRaw.afterTransform (internal/streams/transform.js:103:3) +[2024-11-21T12:22:19.119] [ERROR] errLogs - uncaughtException: write EPIPE +[2024-11-21T12:22:19.120] [ERROR] errLogs - Error: write EPIPE + at afterWriteDispatched (internal/stream_base_commons.js:156:25) + at writeGeneric (internal/stream_base_commons.js:147:3) + at Socket._writeGeneric (net.js:798:11) + at Socket._write (net.js:810:8) + at writeOrBuffer (internal/streams/writable.js:358:12) + at Socket.Writable.write (internal/streams/writable.js:303:10) + at /home/unipi/flowserver/node_modules/total.js/index.js:16529:17 + at afterWrite (internal/streams/writable.js:466:5) + at onwrite (internal/streams/writable.js:446:7) + at DeflateRaw.afterTransform (internal/streams/transform.js:103:3) +[2024-11-21T12:26:13.050] [ERROR] errLogs - uncaughtException: write EPIPE +[2024-11-21T12:26:13.051] [ERROR] errLogs - Error: write EPIPE + at afterWriteDispatched (internal/stream_base_commons.js:156:25) + at writeGeneric (internal/stream_base_commons.js:147:3) + at Socket._writeGeneric (net.js:798:11) + at Socket._write (net.js:810:8) + at writeOrBuffer (internal/streams/writable.js:358:12) + at Socket.Writable.write (internal/streams/writable.js:303:10) + at /home/unipi/flowserver/node_modules/total.js/index.js:16529:17 + at afterWrite (internal/streams/writable.js:466:5) + at onwrite (internal/streams/writable.js:446:7) + at DeflateRaw.afterTransform (internal/streams/transform.js:103:3) +[2024-11-21T12:26:13.051] [ERROR] errLogs - uncaughtException: write EPIPE +[2024-11-21T12:26:13.052] [ERROR] errLogs - Error: write EPIPE + at afterWriteDispatched (internal/stream_base_commons.js:156:25) + at writeGeneric (internal/stream_base_commons.js:147:3) + at Socket._writeGeneric (net.js:798:11) + at Socket._write (net.js:810:8) + at writeOrBuffer (internal/streams/writable.js:358:12) + at Socket.Writable.write (internal/streams/writable.js:303:10) + at /home/unipi/flowserver/node_modules/total.js/index.js:16529:17 + at afterWrite (internal/streams/writable.js:466:5) + at onwrite (internal/streams/writable.js:446:7) + at DeflateRaw.afterTransform (internal/streams/transform.js:103:3) +[2024-11-21T12:26:13.055] [ERROR] errLogs - uncaughtException: write EPIPE +[2024-11-21T12:26:13.056] [ERROR] errLogs - Error: write EPIPE + at afterWriteDispatched (internal/stream_base_commons.js:156:25) + at writeGeneric (internal/stream_base_commons.js:147:3) + at Socket._writeGeneric (net.js:798:11) + at Socket._write (net.js:810:8) + at writeOrBuffer (internal/streams/writable.js:358:12) + at Socket.Writable.write (internal/streams/writable.js:303:10) + at /home/unipi/flowserver/node_modules/total.js/index.js:16529:17 + at afterWrite (internal/streams/writable.js:466:5) + at onwrite (internal/streams/writable.js:446:7) + at DeflateRaw.afterTransform (internal/streams/transform.js:103:3) +[2024-11-21T12:35:32.409] [ERROR] errLogs - uncaughtException: write EPIPE +[2024-11-21T12:35:32.410] [ERROR] errLogs - Error: write EPIPE + at afterWriteDispatched (internal/stream_base_commons.js:156:25) + at writeGeneric (internal/stream_base_commons.js:147:3) + at Socket._writeGeneric (net.js:798:11) + at Socket._write (net.js:810:8) + at writeOrBuffer (internal/streams/writable.js:358:12) + at Socket.Writable.write (internal/streams/writable.js:303:10) + at /home/unipi/flowserver/node_modules/total.js/index.js:16529:17 + at afterWrite (internal/streams/writable.js:466:5) + at onwrite (internal/streams/writable.js:446:7) + at DeflateRaw.afterTransform (internal/streams/transform.js:103:3) +[2024-11-21T12:35:32.411] [ERROR] errLogs - uncaughtException: write EPIPE +[2024-11-21T12:35:32.411] [ERROR] errLogs - Error: write EPIPE + at afterWriteDispatched (internal/stream_base_commons.js:156:25) + at writeGeneric (internal/stream_base_commons.js:147:3) + at Socket._writeGeneric (net.js:798:11) + at Socket._write (net.js:810:8) + at writeOrBuffer (internal/streams/writable.js:358:12) + at Socket.Writable.write (internal/streams/writable.js:303:10) + at /home/unipi/flowserver/node_modules/total.js/index.js:16529:17 + at afterWrite (internal/streams/writable.js:466:5) + at onwrite (internal/streams/writable.js:446:7) + at DeflateRaw.afterTransform (internal/streams/transform.js:103:3) +[2024-11-21T12:35:32.415] [ERROR] errLogs - uncaughtException: write EPIPE +[2024-11-21T12:35:32.416] [ERROR] errLogs - Error: write EPIPE + at afterWriteDispatched (internal/stream_base_commons.js:156:25) + at writeGeneric (internal/stream_base_commons.js:147:3) + at Socket._writeGeneric (net.js:798:11) + at Socket._write (net.js:810:8) + at writeOrBuffer (internal/streams/writable.js:358:12) + at Socket.Writable.write (internal/streams/writable.js:303:10) + at /home/unipi/flowserver/node_modules/total.js/index.js:16529:17 + at afterWrite (internal/streams/writable.js:466:5) + at onwrite (internal/streams/writable.js:446:7) + at DeflateRaw.afterTransform (internal/streams/transform.js:103:3) +[2024-11-21T12:40:53.936] [ERROR] errLogs - uncaughtException: write EPIPE +[2024-11-21T12:40:53.937] [ERROR] errLogs - Error: write EPIPE + at afterWriteDispatched (internal/stream_base_commons.js:156:25) + at writeGeneric (internal/stream_base_commons.js:147:3) + at Socket._writeGeneric (net.js:798:11) + at Socket._write (net.js:810:8) + at writeOrBuffer (internal/streams/writable.js:358:12) + at Socket.Writable.write (internal/streams/writable.js:303:10) + at /home/unipi/flowserver/node_modules/total.js/index.js:16529:17 + at afterWrite (internal/streams/writable.js:466:5) + at onwrite (internal/streams/writable.js:446:7) + at DeflateRaw.afterTransform (internal/streams/transform.js:103:3) +[2024-11-21T12:40:53.938] [ERROR] errLogs - uncaughtException: write EPIPE +[2024-11-21T12:40:53.938] [ERROR] errLogs - Error: write EPIPE + at afterWriteDispatched (internal/stream_base_commons.js:156:25) + at writeGeneric (internal/stream_base_commons.js:147:3) + at Socket._writeGeneric (net.js:798:11) + at Socket._write (net.js:810:8) + at writeOrBuffer (internal/streams/writable.js:358:12) + at Socket.Writable.write (internal/streams/writable.js:303:10) + at /home/unipi/flowserver/node_modules/total.js/index.js:16529:17 + at afterWrite (internal/streams/writable.js:466:5) + at onwrite (internal/streams/writable.js:446:7) + at DeflateRaw.afterTransform (internal/streams/transform.js:103:3) +[2024-11-21T12:40:53.944] [ERROR] errLogs - uncaughtException: write EPIPE +[2024-11-21T12:40:53.945] [ERROR] errLogs - Error: write EPIPE + at afterWriteDispatched (internal/stream_base_commons.js:156:25) + at writeGeneric (internal/stream_base_commons.js:147:3) + at Socket._writeGeneric (net.js:798:11) + at Socket._write (net.js:810:8) + at writeOrBuffer (internal/streams/writable.js:358:12) + at Socket.Writable.write (internal/streams/writable.js:303:10) + at /home/unipi/flowserver/node_modules/total.js/index.js:16529:17 + at afterWrite (internal/streams/writable.js:466:5) + at onwrite (internal/streams/writable.js:446:7) + at DeflateRaw.afterTransform (internal/streams/transform.js:103:3) +[2024-11-21T12:44:54.954] [ERROR] errLogs - uncaughtException: write EPIPE +[2024-11-21T12:44:54.955] [ERROR] errLogs - Error: write EPIPE + at afterWriteDispatched (internal/stream_base_commons.js:156:25) + at writeGeneric (internal/stream_base_commons.js:147:3) + at Socket._writeGeneric (net.js:798:11) + at Socket._write (net.js:810:8) + at writeOrBuffer (internal/streams/writable.js:358:12) + at Socket.Writable.write (internal/streams/writable.js:303:10) + at /home/unipi/flowserver/node_modules/total.js/index.js:16529:17 + at afterWrite (internal/streams/writable.js:466:5) + at onwrite (internal/streams/writable.js:446:7) + at DeflateRaw.afterTransform (internal/streams/transform.js:103:3) +[2024-11-21T12:44:54.956] [ERROR] errLogs - uncaughtException: write EPIPE +[2024-11-21T12:44:54.956] [ERROR] errLogs - Error: write EPIPE + at afterWriteDispatched (internal/stream_base_commons.js:156:25) + at writeGeneric (internal/stream_base_commons.js:147:3) + at Socket._writeGeneric (net.js:798:11) + at Socket._write (net.js:810:8) + at writeOrBuffer (internal/streams/writable.js:358:12) + at Socket.Writable.write (internal/streams/writable.js:303:10) + at /home/unipi/flowserver/node_modules/total.js/index.js:16529:17 + at afterWrite (internal/streams/writable.js:466:5) + at onwrite (internal/streams/writable.js:446:7) + at DeflateRaw.afterTransform (internal/streams/transform.js:103:3) +[2024-11-21T12:44:54.958] [ERROR] errLogs - uncaughtException: write EPIPE +[2024-11-21T12:44:54.959] [ERROR] errLogs - Error: write EPIPE + at afterWriteDispatched (internal/stream_base_commons.js:156:25) + at writeGeneric (internal/stream_base_commons.js:147:3) + at Socket._writeGeneric (net.js:798:11) + at Socket._write (net.js:810:8) + at writeOrBuffer (internal/streams/writable.js:358:12) + at Socket.Writable.write (internal/streams/writable.js:303:10) + at /home/unipi/flowserver/node_modules/total.js/index.js:16529:17 + at afterWrite (internal/streams/writable.js:466:5) + at onwrite (internal/streams/writable.js:446:7) + at DeflateRaw.afterTransform (internal/streams/transform.js:103:3) +[2025-09-23T14:07:36.660] [ERROR] errLogs - uncaughtException: Cannot read property 'getHours' of undefined +[2025-09-23T14:07:36.662] [ERROR] errLogs - TypeError: Cannot read property 'getHours' of undefined + at Timeout.emptyReportToSend [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:07:36.663] [ERROR] errLogs - uncaughtException: Cannot read property 'getHours' of undefined +[2025-09-23T14:07:36.663] [ERROR] errLogs - TypeError: Cannot read property 'getHours' of undefined + at Timeout.emptyReportToSend [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:07:36.672] [ERROR] errLogs - uncaughtException: Cannot read property 'getHours' of undefined +[2025-09-23T14:07:36.673] [ERROR] errLogs - TypeError: Cannot read property 'getHours' of undefined + at Timeout.emptyReportToSend [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:07:42.398] [ERROR] errLogs - uncaughtException: date.getHours is not a function +[2025-09-23T14:07:42.399] [ERROR] errLogs - TypeError: date.getHours is not a function + at emptyReportToSend (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at Timeout.dailyReportCheck [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1351:5) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:07:42.400] [ERROR] errLogs - uncaughtException: date.getHours is not a function +[2025-09-23T14:07:42.401] [ERROR] errLogs - TypeError: date.getHours is not a function + at emptyReportToSend (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at Timeout.dailyReportCheck [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1351:5) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:07:42.407] [ERROR] errLogs - uncaughtException: date.getHours is not a function +[2025-09-23T14:07:42.408] [ERROR] errLogs - TypeError: date.getHours is not a function + at emptyReportToSend (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at Timeout.dailyReportCheck [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1351:5) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) diff --git a/RVO36/flow/cloudmqttconnect.js b/RVO36/flow/cloudmqttconnect.js new file mode 100755 index 0000000..b03491f --- /dev/null +++ b/RVO36/flow/cloudmqttconnect.js @@ -0,0 +1,357 @@ +exports.id = 'cloudmqttconnect'; +exports.title = 'Cloud connect mqtt'; +exports.group = 'MQTT'; +exports.color = '#888600'; +exports.version = '1.0.2'; +exports.icon = 'sign-out'; +exports.input = 2; +exports.output = 2; +exports.options = { host: 'tb-stage.worksys.io', port: 1883, clientid: "", username: "" }; + +exports.html = `
+
+
+
Hostname or IP address (if not empty - setting will override db setting)
+
+
+
Port
+
+
+
+
+
@(Client id)
+
+
+
topic
+
+
+
`; + + + +const { promisifyBuilder } = require('./helper/db_helper'); +const fs = require('fs'); +const mqtt = require('mqtt'); +const nosql = NOSQL('tbdatacloud'); + +const SEND_TO = { + debug: 0, + rpcCall: 1, +} + +//CONFIG +let saveTelemetryOnError = true;//backup_on_failure overrides this value +//------------------------ + +const noSqlFileSizeLimit = 4194304;//use 5MB - 4194304 +let insertNoSqlCounter = 0; +let insertBackupNoSqlCounter = 0; +let processingData = false; + +let backup_on_failure = true;//== saveTelemetryOnError - create backup client send failure +let restore_from_backup = 50; //how many rows process at once? +let restore_backup_wait = 3;//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; + + +exports.install = function(instance) { + + var client; + var opts; + var clientReady = false; + + let o = {}; //options + + function main() { + loadSettings(); + } + + //set opts according to db settings + function loadSettings() { + + o = instance.options; + if (!o.topic) o.topic = FLOW.GLOBALS.settings.cloud_topic; + + opts = { + host: o.host, + port: o.port, + clientId: o.clientid, + username: o.username, + rejectUnauthorized: false, + resubscribe: false + }; + + console.log("wsmqttpublich -> loadSettings from instance.options", o); + + if (!o.topic) { + instance.status("Not configured", "white"); + console.log("Cloud mqtt connect: no topic selected"); + return; + } + + connectToTbServer(); + } + + function connectToTbServer() { + var url = "mqtt://" + opts.host + ":" + opts.port; + console.log("MQTT URL: ", url); + + client = mqtt.connect(url, opts); + + client.on('connect', function() { + client.subscribe(`${o.topic}_backward`, (err) => { + if (!err) { + console.log("MQTT subscribed"); + } + }); + instance.status("Connected", "green"); + clientReady = true; + sendClientError = true; + }); + + client.on('reconnect', function() { + instance.status("Reconnecting", "yellow"); + clientReady = false; + }); + + client.on('message', function(topic, message) { + // message is type of buffer + message = message.toString(); + if (message[0] === '{') { + TRY(function() { + + message = JSON.parse(message); + if (message.hasOwnProperty("device") && message.hasOwnProperty("data") && message.data.hasOwnProperty("id")) { + client.publish(`${o.topic}_forward`, `{"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 } }); + } + + }, () => instance.debug('MQTT: Error parsing data', message)); + } + + instance.send(SEND_TO.rpcCall, { "topic": o.topic, "content": message }); + }); + + client.on('close', function() { + clientReady = false; + + instance.status("Disconnected", "red"); + instance.send(SEND_TO.debug, { "message": "Client CLOSE signal received !" }); + }); + + client.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) { + console.log('MQTT client error', err); + sendClientError = false; + } + clientReady = false; + }); + + } + + + instance.on('0', function(data) { + + if (clientReady) { + //do we have some data in backup file? if any, process data from database + if (saveTelemetryOnError) { + //read telemetry data and send back to server + if (!processingData) processDataFromDatabase(); + } + + let stringifiedJson = JSON.stringify(data.data) + client.publish(`${o.topic}_forward`, stringifiedJson, { qos: 1 }); + } + 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 (saveTelemetryOnError && o.topic) { + //create new file from tbdata.nosql, if file size exceeds given limit, and clear tbdata.nosql + makeBackupFromDbFile(); + + //write to tb + data.data.id = UID(); + nosql.insert(data.data); + } + } + }); + + instance.on("1", _ => { + main(); + }) + + instance.close = function(done) { + if (clientReady) { + client.end(); + } + }; + + + function getDbBackupFileCounter(type) { + var files = fs.readdirSync(__dirname + "/../databases"); + + let counter = 0; + for (var i = 0; i < files.length; i++) { + + if (files[i] == "tbdatacloud.nosql") continue; + + if (files[i].endsWith(".nosql")) { + + let pos = files[i].indexOf("."); + if (pos > -1) { + + let fileCounter = counter; + let firstDigit = files[i].slice(0, pos); + + fileCounter = parseInt(firstDigit); + if (isNaN(fileCounter)) fileCounter = 0; + //console.log("getDbBackupFileCounter digit:", files[i], firstDigit, fileCounter, isNaN(fileCounter), type); + + if (type == "max") { + if (fileCounter > counter) { + counter = fileCounter; + } + } + else if (type == "min") { + if (counter == 0) counter = fileCounter; + + if (fileCounter < counter) { + counter = fileCounter; + } + } + } + } + + } + + if (type == "max") counter++; + + return counter; + } + + const makeBackupFromDbFile = async () => { + + if (!saveTelemetryOnError) return; + + //to avoid large file: tbdata.nosql + + //init value is 0! + if (insertNoSqlCounter > 0) { + --insertNoSqlCounter; + return; + } + + insertNoSqlCounter = 100; + + let source = __dirname + "/../databases/tbdatacloud.nosql"; + + var stats = fs.statSync(source); + var fileSizeInBytes = stats.size; + + if (fileSizeInBytes > noSqlFileSizeLimit) { + + let counter = 1; + counter = getDbBackupFileCounter("max"); + + let destination = __dirname + "/../databases/" + counter + "." + "tbdatacloud.nosql"; + + //make backup file + fs.copyFileSync(source, destination); + //fs.renameSync(p, p + "." + counter); + + //clear tbdata.nosql + fs.writeFileSync(source, ""); + fs.truncateSync(source, 0); + + } + } + + const processDataFromDatabase = async () => { + + if (restore_from_backup <= 0) return; + + //calculate diff + const now = new Date(); + let currentTime = now.getTime(); + let diff = currentTime - lastRestoreTime; + + if ((diff / 1000) < restore_backup_wait) { + //console.log("*********restore_backup_wait", diff, restore_backup_wait); + return; + } + + processingData = true; + + //get filename to process + let counter = getDbBackupFileCounter("min"); + + //we have some backup files + let dataBase = 'tbdata'; + + var nosql; + if (counter == 0) dataBase = 'tbdatacloud'; + else dataBase = counter + "." + 'tbdatacloud'; + + nosql = NOSQL(dataBase); + + //select all data - use limit restore_from_backup + let records = await promisifyBuilder(nosql.find().take(restore_from_backup)); + + for (let i = 0; i < records.length; i++) { + if (clientReady) { + + let item = records[i]; + let id = item.id; + + if (id !== undefined) { + //console.log("------------processDataFromDatabase - remove", id, dataBase, i); + + try { + + let message = JSON.parse(JSON.stringify(item)); + delete message.id; + client.publish(`${o.topic}_forward`, JSON.stringify(message), { qos: 1 }); + + //remove from database + await promisifyBuilder(nosql.remove().where("id", id)); + + } catch (error) { + //process error + console.log("processDataFromDatabase", error); + } + + } + + } + else { + processingData = false; + return; + } + } + + if (records.length > 0) { + //clean backup file + if (counter > 0) nosql.clean(); + } + + //no data in db, remove + if (records.length == 0) { + if (counter > 0) nosql.drop(); + } + + const d = new Date(); + lastRestoreTime = d.getTime(); + + processingData = false; + + } + + instance.on('options', main); + +}; diff --git a/RVO36/flow/cmd_manager.js b/RVO36/flow/cmd_manager.js new file mode 100755 index 0000000..25912df --- /dev/null +++ b/RVO36/flow/cmd_manager.js @@ -0,0 +1,3071 @@ +exports.id = 'cmd_manager'; +exports.title = 'CMD Manager'; +exports.group = 'Worksys'; +exports.color = '#5D9CEC'; +exports.version = '0.0.3'; +exports.output = ['red', 'blue', 'yellow', 'blue', 'white', 'green']; +exports.input = 3; +exports.icon = 'cloud-upload'; + +exports.html = ` +
+
+
+
RPC - run RPC calls

+
+
+
@(User)
+
+
+
@(Password)
+
+
+
@(My edge)
+
+
+
+`; +exports.readme = `Manager for CMD calls`; + + +exports.install = function(instance) { + + 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, isEmptyObject, emptyJsObject, writeToFile, addToArrayIfUnique } = require('./helper/utils'); + const bitwise = require('bitwise'); + + var SunCalc = require('./helper/suncalc'); + const DataToTbHandler = require('./helper/DataToTbHandler'); + const errorHandler = require('./helper/ErrorToServiceHandler'); + const { sendNotification } = require('./helper/notification_reporter'); + const process = require('process'); + const { errLogger, logger, monitor } = require('./helper/logger'); + + //for accelerometer purposes + const { naklony } = require("../databases/accelerometer_db"); + + const dbNodes = TABLE("nodes"); + const dbRelays = TABLE("relays"); + + let GLOBALS; + let SETTINGS; + let rsPort; + let tbHandler; + + // runTasks intervals + const SHORT_INTERVAL = 30; + const LONG_INTERVAL = 300; + + //send data to following instances: + const SEND_TO = { + debug: 0, + tb: 1, + http_response: 2, + dido_controller: 3, + infoSender: 4, + dailyReport: 5 + } + + 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 + } + + 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 sendNodeReadout = null; // interval for sending agregate data from node + + 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["1"] = minutes; // dimming + priorities["76"] = minutes; // power + + minutes = 5; + priorities["75"] = minutes; // current + priorities["79"] = minutes; // energy + priorities["87"] = minutes; // aktualny cas + //priorities["84"] = minutes; //accelerometer + + minutes = 10; + priorities["74"] = minutes; // voltage + priorities["77"] = minutes; // power factor + priorities["78"] = minutes; // frequency + + minutes = 60; + priorities["0"] = minutes; // statecode + priorities["6"] = minutes; // dusk + priorities["7"] = minutes; // dawn + priorities["8"] = minutes; // profile + + minutes = 60 * 24; + priorities["89"] = minutes; // verzia fw + priorities["80"] = minutes; // lifetime + + //prikazy kt sa budu spustat na dany node - see config.js in terminal-oms.app. (1 - dimming) + let listOfCommands = [0, 1, 6, 7, 8, 74, 75, 76, 77, 78, 79, 80, 87, 89]; + + 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; + + // holds dusk, dawn (and more) values + let sunCalcResult; + + //helper container for counting resolved group of commands (commands related to set profile) + let cmdCounter = {};//key is node, value is counter + + //TODO: is this set working?? According to previous checks, sets do not work + //if sending of profile to node fails, we send notification and push node into set, so we do not send notification twice + const nodeProfileSendFail = new Set(); + + //we expect to get current temperature in Senica from senica-prod01 + let temperatureInSenica = null; + let accelerometerInterval = null; + + //NOTE: daily reports senica: + //rvo_is_on status, we monitor all nodes - if true, power and dimming should be not 0, if false, 24/7 nodes should be 0, other rvo should not respond + let rvo_is_on; + let previous_rvo_is_on_value; + let handleDailyReport; //setInterval for dailyReportHandler function + let dailyReport = {}; //data needed for daily report + let reportToSend = {}; //final report which we send to cloud + let breakerCounter = null; // status of breakers after flow starts is not in report + let rvoPeriod; // interval of checking dusk dawn and if rvo_is_on + let initialReportStatus = false; + + const DAILY_REPORT_HANDLER_TIME = 3_600_000; + const SET_SUNCALC_RESULT_TIME = 3_600_000; + const SET_RVO_PERIOD_TIME = 300_000; + const ADD_NODE_TO_REPORT_TIME = 3_600_000; + + //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); + + let now = new Date(); + console.log("Cmd-mngr installed", now.toLocaleString("sk-SK")); + + sunCalcResult = calculateDuskDawn(); + + handleRsPort(); + + customTasksInterval = setInterval(reportEdgeDateTimeAndNumberOfLuminaires, 120_000); + setTimeout(reportEdgeDateTimeAndNumberOfLuminaires, 4000); + + //dailyReport related + emptyReportToSend(); + breakerCounter = Object.keys(relaysData).length - 1; // we get number of lines (breakers) except of line 0 + rvoPeriod = setInterval(setRvoPeriod, SET_RVO_PERIOD_TIME); + setTimeout(setRvoPeriod, 3000); + setInterval(setSunCalcResult, SET_SUNCALC_RESULT_TIME); + handleDailyReport = setInterval(dailyReportHandler, DAILY_REPORT_HANDLER_TIME); + + + setCorrectTime = setInterval(setCorrectPlcTimeOnceADay, 60000 * 60); // 1 hour + setCorrectPlcTimeOnceADay(); + + sendNodeReadout = setInterval(sendNodesData, 150_000); + accelerometerInterval = setInterval(accelerometerData, 60000 * 30); //30 min + } + + + 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" + //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 + // if node regular readout does not respond, we repeat request + params.repeatCounter = 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-mngr: 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.byte4 = 96; + params.recipient = 1; + params.register = 8; + params.rw = 1;//write + params.timestamp = timestamp; + 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.byte4 = 96; + params.recipient = 1; + params.register = 8; + params.rw = 1;//write + params.timestamp = timestamp; + 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). + */ + + 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.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.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 + { + + logger.debug("processNodeProfile: Threshold lux level for DUSK/DAWN", node); + + let params = getParams(); + params.type = "set_node_profile"; + params.address = node; + params.register = 96; + params.recipient = 1; + params.rw = 1;//write + params.timestamp = timestamp; + 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(); + params.type = "set_node_profile"; + params.address = node; + params.register = 97; + params.recipient = 1; + params.rw = 1;//write + params.timestamp = timestamp; + 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.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); + + 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); + + console.log("proces profile finished *********************") + } + + + 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; + }); + } + + + 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) { + for (let k in nodesData) { + 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`); + } + } + } + + + function loadRelaysData(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 (value.contactor == 1) processAllNodeProfilesOnLine(value.line); + } + } + + + function reportOnlineNodeStatus(line) { + //Po zapnutí línie broadcastovo aktualizovať predtým čas a o 3 sek neskor - status, brightness + + logger.debug("Cmd-mngr: ----->reportOnlineNodeStatus for line", line); + + const d = new Date(); + + // broadcast actual time + let params = getParams(); + params.address = 0xffffffff;//Broadcast + params.byte1 = d.getHours(); + params.byte2 = d.getMinutes(); + params.recipient = 2;//2 broadcast, address = 0 + params.register = 87;//Actual time + params.rw = 1;//write + params.type = "node-onetime-write"; + params.timestamp = d.getTime() + 30000; + params.info = "run broadcast: Actual time"; + //params.debug = true; + + tasks.push(params); + + let sec = 3; + setTimeout(function() { + //Po zapnutí línie - spraviť hromadný refresh stavu práve zapnutých svietidiel + + let time = Date.now(); + + for (let k in nodesData) { + + //potrebujem nody k danej linii + 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].node_status_before_offline === true || nodesData[k].status === true) { + status = "OK"; + nodesData[k].time_of_last_communication = time; + } + + nodesData[k].readout.status = status; + + updateNodeStatus(k, status === "OK" ? true : false); + if (nodesData[k].hasOwnProperty("node_status_before_offline")) delete nodesData[k].node_status_before_offline; + sendTelemetry({ status: status }, tbname, time); + + //vyreportovanie dimming, current, input power pre liniu pre vsetky nody + //Prud + { + let params = getParams(); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 75;//prud + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = time + 4000; + params.info = 'read current'; + //params.debug = true; + tasks.push(params); + } + + //vykon + { + let params = getParams(); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 76;//výkon + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = time + 4100; + params.info = 'read power'; + //params.debug = true; + + tasks.push(params); + } + //dimming + { + let params = getParams(); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 1;//dimming + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = time + 4200; + params.info = 'read dimming'; + //params.debug = true; + + tasks.push(params); + } + + } + } + + }, sec * 1000); + } + + + function reportOfflineNodeStatus(line) { + + logger.info("Cmd-mngr: ------>reportOffLineNodeStatus for line ", line); + + values = {}; + values["dimming"] = 0;//brightness + values["power"] = 0;//výkon + values["current"] = 0;//prúd + values["status"] = "OFFLINE"; + + const date = Date.now(); + + Object.keys(nodesData).forEach(node => { + + //potrebujem nody k danej linii + if (line == nodesData[node].line || line == undefined) { + + let tbname = nodesData[node].tbname; + let nodeStatus = nodesData[node].status; + + //in case we have reported offline node status, we return (continue with next node) + if (nodeStatus === "OFFLINE") return; + + nodesData[node].node_status_before_offline = nodeStatus; + nodesData[node].status = "OFFLINE"; + nodesData[node].readout = {}; + + sendTelemetry({ ...values }, tbname, date); + } + }); + + } + + + function turnLine(onOrOff, line, info) { + let obj = { + line: line, + command: onOrOff, + info: info + }; + + //to assure, handleDailyReportFunction do not run before rvo_is_on variable changes. So after every line switch we reset the timer + clearInterval(handleDailyReport); + handleDailyReport = setInterval(dailyReportHandler, DAILY_REPORT_HANDLER_TIME); + + //logger.debug("linia", line, obj); + instance.send(SEND_TO.dido_controller, obj); + } + + + 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"; + 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]) { + //CRC_ERROR + message = "NOK"; + error = "CRC_ERROR c1"; + instance.send(SEND_TO.debug, "CRC_ERROR c1"); + } + + 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") { + instance.send(SEND_TO.debug, bytes); + instance.send(SEND_TO.debug, "RESPONSE " + type + " - " + bytes[4]); + + //logger.debug(SEND_TO.debug, "RESPONSE " + type + " - " + bytes[4], bytes); + + error = "type is: " + type; + + message = "NOK"; + } + + return { message, type, error }; + } + + + //BUILD TASKS// + function buildTasks(params) { + + //return; + console.log("buidTAaasks start ****************", params); + monitor.info("buildTasks - params", params); + + let processLine; //defined line + let init = false; + let processLineProfiles = true; + let processBroadcast = true; + let processNodes = true; + + if (params == undefined) { + init = true; + tasks = []; + logger.debug("-->buildTasks clear tasks"); + } + else { + processLineProfiles = params.processLineProfiles; + processBroadcast = false; + processNodes = false; + + processLine = params.line; + } + + let now = new Date(); + + //process line profiles + if (processLineProfiles) { + + let keys = Object.keys(relaysData); + + for (let i = 0; i < keys.length; i++) { + + let line = parseInt(keys[i]); + let profilestr = relaysData[line].profile; + + if (processLine != undefined) { + if (processLine != line) continue; + } + + try { + + /** + * we process line profiles: timepoints, astro clock, lux_sensor, offsets ... + */ + if (profilestr === "") throw ("Profile is not defined"); + let profile = JSON.parse(profilestr); + 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; + + // add name to regular profile timepoint and delete unused end_time key: + time_points.forEach(point => { + point.name = "profileTimepoint" + delete point.end_time; + }); + + //monitor.info("buildTasks: time_points", time_points); + + + /** + * 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 astro clock true, we remove all regular profile points + time_points = []; + + //TODO: when astro clock == true, is offset calculated ??? + //let duskAstroClockOffset = profile.dusk_astro_clock_offset; + //let dawnAstroClockOffset = profile.dawn_astro_clock_offset; + //console.log("line astro clock offsets dusk a dawn: ", duskAstroClockOffset, dawnAstroClockOffset); + // maybe add dusk dawn offset to calculateDuskDawn ?? what dusk dawn will be if dawn_lux_sensor == true?? + //let sunCalcResult = calculateDuskDawn(new Date(), line, duskAstroClockOffset, dawnAstroClockOffset); + + 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 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); + + 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); + + 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(':'); + + let ad = new Date(); + ad.setHours(parseInt(ahours), parseInt(aminutes), 0); + + let bd = new Date(); + bd.setHours(parseInt(bhours), parseInt(bminutes), 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++) { + + let start_time = new Date(); + let [hours, minutes] = time_points[t].start_time.split(':'); + start_time.setHours(parseInt(hours), parseInt(minutes), 0); + + //task is in 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(); + params.type = "relay"; + params.line = parseInt(line); + params.value = time_points[t].value; + params.tbname = relaysData[line].tbname; + params.timestamp = start_time.getTime(); + + // 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; + + //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)) { + 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; + + params.debug = true; + + //turn on/off line + tasks.push(params); + monitor.info("TimePoint params: ", params.info, start_time); + } + + monitor.info("-->time_points final", line, time_points); + + //ensure to turn on/off according to calculated currentValue + let params = getParams(); + params.type = "relay"; + params.line = parseInt(line); + params.tbname = relaysData[line].tbname; + params.value = currentValue; + params.timestamp = i; + params.debug = true; + + //logger.debug(now.toLocaleString("sk-SK")); + 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; + + tasks.push(params); + + } catch (error) { + if (profilestr !== "") { + //errLogger.error(profilestr, error); + console.log(`Cmd_mngr: Unable to process line profile ${line}. Error: `, error); + errorHandler.sendMessageToService(profilestr + "-" + error, 0, "js_error"); + } else { + turnLine("off", line, "No line profile. Switching it off on startup"); + } + } + + } + //logger.debug("tasks:"); + //logger.debug(tasks); + } + + + //NOTE: PROCESS DEFAULT BROADCASTS - Time of dusk, Time of dawn, Actual Time + if (processBroadcast) { + + let d = new Date(); + let time = d.getTime(); + //let sunCalcResult = calculateDuskDawn(); + + { + let params = getParams(); + + params.address = 0xffffffff;//broadcast + params.byte1 = sunCalcResult["dusk_hours"]; + params.byte2 = sunCalcResult["dusk_minutes"]; + params.recipient = 2;//2 broadcast, + params.register = 6;//Time of dusk + params.rw = 1;//write + params.type = "node-regular-write"; + params.timestamp = time + 60000; + params.addMinutesToTimestamp = 60 * 3; //kazde 3 hodiny zisti novy dusk + params.info = "Broadcast-duskTime"; + + tasks.push(params); + } + + { + let params = getParams(); + + params.address = 0xffffffff;//broadcast + params.byte1 = sunCalcResult["dawn_hours"]; + params.byte2 = sunCalcResult["dawn_minutes"]; + params.recipient = 2; //2 broadcast + params.register = 7;//Time of dawn + params.rw = 1;//write + params.type = "node-regular-write"; + params.timestamp = time + 60001; + params.addMinutesToTimestamp = 60 * 3; //kazde 3 hodiny zisti novy dawn + params.info = "Broadcast-dawnTime"; + + tasks.push(params); + } + + { + let params = getParams(); + + params.address = 0xffffffff;//broadcast + params.byte1 = d.getHours(); + params.byte2 = d.getMinutes(); + params.recipient = 2; //2 broadcast + params.register = 87;//Actual time + params.rw = 1;//write + params.type = "node-regular-write"; + params.timestamp = time + 60002; + params.addMinutesToTimestamp = 5; + params.info = "run broadcast: Actual time"; + + tasks.push(params); + } + + } + + //process nodes & tasks - read node's data + if (processNodes) { + + let time = Date.now(); + + for (let k in nodesData) { + let address = parseInt(k); + let tbname = nodesData[k].tbname; + let register = 0; + + for (let i = 0; i < listOfCommands.length; i++) { + + register = listOfCommands[i]; + let addMinutesToTimestamp = priorities[register]; + + let params = getParams(); + + params.address = address; + params.recipient = 1; + params.register = register; + params.type = register == 1 ? "node-dimming-read" : "node-regular-read"; + params.tbname = tbname; + params.timestamp = time + 5000 + i * 500 + addMinutesToTimestamp * 1000; //to make slight time difference + params.addMinutesToTimestamp = addMinutesToTimestamp; + params.info = "Node regular read command"; + + tasks.push(params); + } + + } + } + + + //niektore ulohy sa vygeneruju iba 1x pri starte!!! + if (!init) return; + + + //Master node FW version - modifies SETTINGS.masterNodeIsResponding + { + let params = getParams(); + params.type = "cmd-master"; + params.register = 4; + params.address = 0; + params.timestamp = 0; + params.addMinutesToTimestamp = 5; + params.tbname = SETTINGS.rvoTbName; + params.info = "Master node FW verzia"; + //params.debug = true; + + tasks.push(params); + } + + //kazdu hodinu skontrolovat nastavenie profilov + { + let params = getParams(); + params.type = "process_profiles"; + params.timestamp = Date.now() + 60001; + params.addMinutesToTimestamp = 60;//60 = every hour + params.info = "detekcia nespracovaných profilov linie a nodov"; + //params.debug = true; + + tasks.push(params); + } + + monitor.info("tasks created:", tasks.length); + } + + + /** + * We process line profile, where "astro_clock": true + * example profile: + * + "dawn_lux_sensor": true, + "dusk_lux_sensor": true, + "dawn_lux_sensor_value": 5, + "dusk_lux_sensor_value": 5, + "dawn_astro_clock_offset": 0, + "dusk_astro_clock_offset": 10, + "dawn_lux_sensor_time_window": 30, + "dusk_lux_sensor_time_window": 30, + "dawn_astro_clock_time_window": 60, + "dusk_astro_clock_time_window": 60 + + * if dawn: if currentTimestamp is in timewindow "dawnTime + and - dawn_lux_sensor_time_window" and lux value >= lux_sensor_value, we switch off the line. + * if dusk: we do oposite + * + * dawn: usvit - lux je nad hranicou - vypnem + * dusk: sumrak - lux je pod hranicou - zapnem + */ + 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++) { + + let line = keys[i]; //line is turned off by default + let profilestr = relaysData[line].profile; + const contactor = relaysData[line].contactor; + + try { + + let profile = JSON.parse(profilestr); + if (Object.keys(profile).length === 0) throw ("turnOnOffLinesAccordingToLuxSensor - profile is not defined"); + + 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 (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"); + } + } + } + + //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 (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"); + } + } + } + + } + + } catch (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) { + //MASTER + if (node == 0) return; + + let nodeObj = nodesData[node]; + if (nodeObj == undefined) return; + + let nodeCurrentStatus = nodeObj.status; + const now = Date.now(); + + let data = null; + + if (nodeCurrentStatus === "OFFLINE") { + data = { status: newStatus }; + nodeDbStatusModify(node, data); + return; + } + else 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; + } + + } + + + 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 }; + } + }); + }); + } + + + function processDailyReport() { + + const now = Date.now(); + + for (const [key, value] of Object.entries(dailyReport)) { + + if (["name", "time", "dusk_and_dawn"].includes(key)) continue; + + let poleNumber = nodesData[key]["pole_number"]; + let line = dailyReport[key].line; + let nodeType = nodesData[key]["node_type"]; + let fullNodeName = key // key == nodeNumber + + if (poleNumber && nodeType) { + fullNodeName = SETTINGS.rvo_number + "/" + poleNumber + "_" + line + "L_" + key + "_" + nodeType; + } else { + fullNodeName = key; + } + + if (rvo_is_on) { + + if (value.initialTs) { + if (value.initialTs + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["night_no_data"], fullNodeName); + console.log('report nedostava ziadne data uz hodinu', fullNodeName); + value.initialTs = now; + } + } + if (value.dimmingIsZeroTime) { + if (value.dimmingIsZeroTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["night_dimming=0"], fullNodeName); + console.log("report node dimming je 0 ale ma svietit", fullNodeName); + value.dimmingIsZeroTime = now; + } + } + if (value.powerIsZeroTime) { + if (value.powerIsZeroTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["night_power=0"], fullNodeName); + console.log("report node power je 0 ale ma svietit", fullNodeName); + value.powerIsZeroTime = now; + } + } + + } else { + + let contactorStatus = relaysData[line].contactor; + if (contactorStatus === 1) { + + if (value.initialTs) { + if (value.initialTs + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["day_24/7_no_data"], fullNodeName); + console.log('node je na 24/7 ale nedostava ziadne data uz hodinu', fullNodeName); + value.initialTs = now; + } + } + if (value.dimmingIsOnButShouldBeOffTime) { + if (value.dimmingIsOnButShouldBeOffTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["day_24/7_dimming>0"], fullNodeName); + console.log("report dimming je > 0 ale nema svietit", fullNodeName); + value.dimmingIsOnButShouldBeOffTime = now; + } + } + if (value.powerIsOnButShouldBeOffTime) { + if (value.powerIsOnButShouldBeOffTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["day_24/7_power>0"], fullNodeName); + console.log("report power je > 0 ale nema svietit", fullNodeName); + value.powerIsOnButShouldBeOffTime = now; + } + } + + } + + } + + } + + let report = {}; + report["name"] = SETTINGS.rvo_name; + report["time"] = new Date(); + report["report"] = reportToSend; + + writeToFile(F.path.root("report_data.log"), report, true); + instance.send(SEND_TO.dailyReport, report); + } + + + function dailyReportHandler() { + + if (!SETTINGS.daily_report) return; + + // after dawn we empty reportToSend and start to get data for a new day + const date = new Date(); + const hour = date.getHours(); + const minute = date.getMinutes(); + + console.log("now: ", hour, minute, "suncalc: ", sunCalcResult.dawn_hours, sunCalcResult.dawn_minutes); + + if (hour === sunCalcResult.dawn_hours) { + + //NOTE: ak je este pred usvitom, spracujeme report a posleme na cloud, ak uz je po usvite, resetujeme report plnime data noveho dna + if (minute >= sunCalcResult.dawn_minutes - 2) { + emptyReportToSend(); + emptyDailyReport(); + console.log("Podmienka 1 v dailyReport handler"); + } else { + processDailyReport(); + emptyReportToSend(); + emptyDailyReport(); + console.log("Podmienka 2 v dailyReport handler"); + } + + initialReportStatus = true; + + // ak sa funkcia spusti o hodinu alebo 2 neskor, ako je usvit (moze sa to stat, kedze kazde zapnutie/vypnutie linii odznova spusti casovac. + } else if (hour === sunCalcResult.dawn_hours + 1 || hour === sunCalcResult.dawn_hours + 2) { + if (!initialReportStatus) { + emptyReportToSend(); + emptyDailyReport(); + initialReportStatus = true; + console.log("Podmienka 3 v dailyReport handler"); + } else { + processDailyReport(); + initialReportStatus = true; + console.log("Podmienka 4 v dailyReport handler"); + } + } else { + processDailyReport(); + initialReportStatus = false; + console.log("Podmienka 5 v dailyReport handler"); + } + + console.log("initialReportStatus: ", initialReportStatus); + + } + + function emptyReportToSend() { + emptyJsObject(reportToSend); + reportToSend["contactor"] = { off: [], on: [] }; + reportToSend["night_no_data"] = []; + reportToSend["night_dimming=0"] = []; + reportToSend["night_power=0"] = []; + reportToSend["day_24/7_no_data"] = []; + reportToSend["day_24/7_dimming>0"] = []; + reportToSend["day_24/7_power>0"] = []; + console.log(`resetuje sa reportToSend`); + } + + + //NOTE: ked je initialTs stale rovnaky a zistime ze linie su vypnute (relaysData.line.contactor) - zistim, ci je node na tej linii. Vieme, ze ak je linia vypnuta je to v poriadku lebo nie je na 24/7 linii + //ak je na 24/7 linii, reportujeme, ze neprijima data + function emptyDailyReport() { + const ts = Date.now(); + emptyJsObject(dailyReport); + + //NOTE: do dailyReport dame vsetky nody a pravidelne kontrolujeme ci maju data + //ked nastane sumrak/usvit a svetla maju zacat/prestat svietit, dailyReport spravime nanovo: + for (const [key, value] of Object.entries(nodesData)) { + dailyReport[value.node] = { line: value.line, initialTs: ts }; + } + + console.log("dailyReport: ", dailyReport); + } + + + async function runTasks() { + + clearInterval(interval); + + let currentTimestamp = Date.now(); + + //sort tasks based on timestamp + 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) { + instance.send(SEND_TO.debug, "no tasks created"); + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + if (!rsPort.isOpen) { + instance.send(SEND_TO.debug, "!rsPort.isOpen"); + //await rsPort.open(); + //console.log("Cmd-mngr: !rsPort.isOpen"); + } + + let currentTask = tasks[0]; + + if (currentTask.debug) { + //logger.debug("--->task to process", currentTask); + } + + if (currentTask.timestamp <= currentTimestamp) { + let params = { ...tasks[0] }; + + //allow terminal commands + if (SETTINGS.maintenance_mode && params.type !== "cmd-terminal") { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + let type = params.type; + let tbname = params.tbname; + let node = params.address; + let register = params.register; + let line = null; + let itIsNodeCommand; + + if (nodesData[node] !== undefined) { + line = nodesData[node].line; + itIsNodeCommand = true; + } + + if (params.line !== undefined) line = params.line; + + if (params.addMinutesToTimestamp > 0 || params.timePointName) { + tasks[0].timestamp = currentTimestamp + tasks[0].addMinutesToTimestamp * 60000; + } else { + tasks.shift(); + } + + //kontrola nespracovanych profilov nodov + //TODO: co ked niektore nody neprijimaju profily? kazdu hodinu zahltuju "tasks" array + if (type == "process_profiles") { + //na vsetky zapnutych liniach sa spracuju nespracovane profily nodov + loadRelaysData(); + interval = setInterval(runTasks, SHORT_INTERVAL); + return; + } + + //relay + if (type == "relay") { + + const timePointName = params.timePointName; + const value = params.value; + + let date = new Date(); + date.setDate(date.getDate() + 1);//next day + + let sunCalcResult; + if (timePointName) sunCalcResult = calculateDuskDawn(date, params.line); + + + if (timePointName == "dawn") { + tasks[0].timestamp = sunCalcResult.dawn_time; + } + else if (timePointName == "dusk") { + tasks[0].timestamp = sunCalcResult.dusk_time; + } + else if (timePointName == "luxOn") { + tasks[0].timestamp = sunCalcResult.dusk_time + params.dusk_lux_sensor_time_window * 60000; + } + else if (timePointName == "luxOff") { + tasks[0].timestamp = sunCalcResult.dawn_time + params.dawn_lux_sensor_time_window * 60000; + } + else if (timePointName == "profileTimepoint") { + tasks[0].timestamp = currentTimestamp + tasks[0].addMinutesToTimestamp * 60000; + } + + let info = "aplikovany bod profilu"; + let onOrOff = ""; + value == 1 ? onOrOff = "on" : onOrOff = "off"; + + turnLine(onOrOff, params.line, info); + + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + if (!SETTINGS.masterNodeIsResponding) { + //ak neodpoveda, nebudeme vykonavat ziadne commands, okrem cmd-terminal cmd-master + errorHandler.sendMessageToService("Master node is not responding"); + + let stop = true; + + if (type === "cmd-terminal" || type === "cmd-master") stop = false; + if (stop) { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + } + + let contactorStatus = 1; + if (relaysData[line] != undefined) contactorStatus = relaysData[line].contactor; + + if (line === 0 || contactorStatus === 0 || FLOW.deviceStatus.state_of_breaker[line] === "Off") { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + // TODO: -> status offline for rvo if rotary_switch_state is OFF, this is source of errors + // check if rotary_switch_state == "Off" + // state_of_braker: disconnected = true? + + if (!rsPort.isOpen) { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + //RE-CALCULATE VALUES + //set actual time for broadcast + if (register == 87 && params.recipient === 2) { + var d = new Date(); + params.byte1 = d.getHours();//h + params.byte2 = d.getMinutes();//m + } + + //SET DUSK/DAWN FOR BROADCAST + //Time of dusk + if (register == 6 && params.recipient === 2) { + + if (type != "cmd-terminal") { + params.byte1 = sunCalcResult["dusk_hours"];//h + params.byte2 = sunCalcResult["dusk_minutes"];//m + } + } + + //Time of dawn + if (register == 7 && params.recipient === 2) { + if (type != "cmd-terminal") { + params.byte1 = sunCalcResult["dawn_hours"];//h + params.byte2 = sunCalcResult["dawn_minutes"];//m + } + } + //----------------------- + + instance.send(SEND_TO.debug, "address: " + node + " register:" + register + "type: " + type); + + var startTime, endTime; + startTime = new Date(); + + let saveToTb = true; + if (!tbname) saveToTb = false; + + let resp = com_generic(node, params.recipient, params.rw, register, params.name, params.byte1, params.byte2, params.byte3, params.byte4); + let readBytes = 11; + let timeout = 4000; + + + // await keyword is important, otherwise incorrect data is returned! + await writeData(rsPort, resp, readBytes, timeout).then(function(data) { + + //sometimes happens, that status of node changes to OK, NOK even if line was turned off and should be status OFFLINE. To prevent this, we return if line contactor is 0: + if (itIsNodeCommand && line && relaysData[line].contactor !== 1) return; + + 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); + + //ak sa odpoved zacina 0 - je to v poriadku, inak je NOK + let message = result.message; // OK, NOK + let message_type = result.type; + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + console.log("detected response:", result); + logger.debug("Cmd-mngr: writeData done " + message_type + " duration: " + timeDiff + " type: " + params.debug, params, result); + } + } + + let values = {}; + + //CMD FINISHED + if (message == "OK") { + + updateNodeStatus(node, true); + + //write + if (type == "set_node_profile") { + let result = cmdCounterResolve(node); + if (result == 0) { + dbNodes.modify({ processed: true }).where("node", node).make(function(builder) { + builder.callback(function(err, response) { + + sendNotification("Cmd-mngr: process cmd", SETTINGS.rvoTbName, "dimming_profile_was_successfully_received_by_node", { node: node }, "", SEND_TO.tb, instance); + + logger.debug("--> profil úspešne odoslaný na node č. " + node); + nodesData[node].processed = true; + nodeProfileSendFail.delete(node); + }); + }); + } + } + + //parse read response + if (params.rw == 0) { + values = processResponse(register, dataBytes); //read + } + + if (itIsNodeCommand) { + values.comm_status = "OK"; + values.status = "OK"; + nodesData[node].readout = { ...nodesData[node].readout, ...values }; + + + if (SETTINGS.daily_report) { + //TODO: co ak nedostavame odpovede z nodu ? Musime vyreportovat!! + //v dailyReport teda musi byt kompletny zoznam nodov a neustale kontrolovat, ci maju data, ak nie report node - neodpoveda + if (register === 1) { + + let now = Date.now(); + + if (rvo_is_on === true) { + + if ("dimmingIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].dimmingIsOnButShouldBeOffTime; + + if (values.dimming > 0) { + if ("dimmingIsZeroTime" in dailyReport[node]) delete dailyReport[node].dimmingIsZeroTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if (!("dimmingIsZeroTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], dimmingIsZeroTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } else { + + if ("dimmingIsZeroTime" in dailyReport[node]) delete dailyReport[node].dimmingIsZeroTime; + + if (values.dimming > 0) { + if (!("dimmingIsOnButShouldBeOffTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], dimmingIsOnButShouldBeOffTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if ("dimmingIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].dimmingIsOnButShouldBeOffTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } + } + + if (register === 76) { + + let now = Date.now(); + + if (rvo_is_on === true) { + + if ("powerIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].powerIsOnButShouldBeOffTime; + + if (values.power > 1) { + if ("powerIsZeroTime" in dailyReport[node]) delete dailyReport[node].powerIsZeroTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if (!("powerIsZeroTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], powerIsZeroTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } else { + + if ("powerIsZeroTime" in dailyReport[node]) delete dailyReport[node].powerIsZeroTime; + + if (values.power > 1) { + if (!("powerIsOnButShouldBeOffTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], powerIsOnButShouldBeOffTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if ("powerIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].powerIsOnButShouldBeOffTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } + } + } + + } + + //master node + if (node == 0) { + sendNotification("Cmd-mngr: 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; + } + + if (params.debug) { + //logger.debug("saveToTb", saveToTb, tbname, values); + } + + if (saveToTb && type != "node-regular-read") { + sendTelemetry(values, tbname); + } + else { + if (type == "cmd-terminal") { + terminalCommandResponse(params, "SUCCESS", data); + } + } + + } + else { + terminalCommandResponse(params, "ERROR", data); + handleNokResponseOnRsPort("handleNOK else block", params, itIsNodeCommand, saveToTb); + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + //logger.debug("writeData err: ", error, result, params); + logger.debug("writeData err: ", tbname, node, register, values); + } + } + + //logger.debug(error, result, params); + } + }).catch(function(reason) { + + //console.log("writeData catch exception", reason); + instance.send(SEND_TO.debug, reason); + + terminalCommandResponse(params, "FAILURE", null, reason); + handleNokResponseOnRsPort("handleNOK catch block", params, itIsNodeCommand, saveToTb); + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + logger.debug("-->WRITE FAILED: " + reason, params.debug, params); + } + } + + }); + + } + 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); + } + + + // if node does not respond to request, we repeat request 3 times: + function repeatCommand(params) { + params.repeatCounter++; + if (params.repeatCounter < 4) { + params.timestamp = 0; + params.addMinutesToTimestamp = 0; + tasks.push(params); + } + } + + function handleNokResponseOnRsPort(message, params, itIsNodeCommand, saveToTb) { + + let node = params.address; + let register = params.register; + let type = params.type; + let tbName = params.tbname; + if (!tbName) return; + + let values = {}; + + let updateStatus = updateNodeStatus(node, false); + + if (itIsNodeCommand) { + values.comm_status = "NOK"; + nodesData[node].readout.comm_status = "NOK"; + repeatCommand(params); + } + + if (updateStatus) { + values.status = "NOK"; + nodesData[node].readout.status = "NOK"; + } + + if (type === "node-regular-read") return; + + //master node + if (node == 0) { + sendNotification("Cmd-mngr: 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; + + if (register == 4) values["master_node_version"] = "NOK"; + } + + if (type == "set_node_profile") { + delete cmdCounter[node]; + logger.debug("profil nebol úspešne odoslaný na node č. ", params); + + if (!nodeProfileSendFail.has(node)) { + sendNotification("Cmd-mngr: process cmd", tbName, "configuration_of_dimming_profile_to_node_failed", { node: node }, "", SEND_TO.tb, instance); + nodeProfileSendFail.add(node); + } + } + + // console.log("------",node, register, type, itIsNodeCommand, updateStatus, saveToTb, values); + if (saveToTb) { + sendTelemetry(values, tbName); + } + + } + + + function sendNodesData() { + Object.keys(nodesData).forEach(node => { + if (nodesData[node]["status"] !== "OFFLINE") { + sendTelemetry(nodesData[node].readout, nodesData[node].tbname); + nodesData[node].readout = {}; + } + }) + } + + + /** + * 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; + } + + 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); + + //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 === "OFFLINE") { + nodeObj.node_status_before_offline === true ? number_of_ok_luminaires++ : number_of_nok_luminaires++; + } + else if (nodeObj.status == true) 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 - ts % 60000 //round to full minute + }; + + sendTelemetry(values, SETTINGS.rvoTbName, ts); + } + + + function setSunCalcResult() { + //if next day, we get new dusk and dawn. To make sure, in local timezone 2:00 means 00:00 in utc (it means next day) + if (new Date().getHours() === 2) { + sunCalcResult = calculateDuskDawn(); + console.log("Novy suncalc: ", sunCalcResult); + } + } + + + function setRvoPeriod() { + + if (!SETTINGS.daily_report) return; + + const ts = Date.now(); + + previous_rvo_is_on_value = rvo_is_on; + + if (ts < sunCalcResult.dawn_time - 1_800_000) { // nodes should be on (00:00 -> 06:00 ( - pol hodina, lebo rvo vypina skor) + rvo_is_on = true; + } else if (sunCalcResult.dawn_time - 1_800_000 < ts && ts < sunCalcResult.dusk_time + 1_800_000) { // nodes should be off 06:00 -> 21:00 + rvo_is_on = false; + } else if (sunCalcResult.dusk_time + 1_800_000 < ts) { // nodes should be on 21:00 -> 00:00 + rvo_is_on = true; + } + + if (previous_rvo_is_on_value !== rvo_is_on) { + emptyDailyReport(); + console.log("rvo_is: ", rvo_is_on, previous_rvo_is_on_value); + } + } + + + function handleRsPort() { + + if (rsPort) { + rsPort.removeAllListeners(); + rsPort = null; + } + + //! 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-mngr: rsPort opened success"); + + 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); + + }).catch(function(reason) { + instance.send(SEND_TO.debug, "Cmd-mngr: RPC runSyncExec - promise rejected:" + reason); + }); + }); + + rsPort.on('error', function(err) { + errorHandler.sendMessageToService([exports.title, "unable to open port", SETTINGS.serial_port, err.message], 0); + monitor.info("Cmd-mngr: Error on rsPort", err.message); + }); + + rsPort.on("close", () => { + monitor.info("Cmd-mngr: rsPort closed, reconnecting..."); + setTimeout(handleRsPort, 1000); + }); + + rsPort.open(); + } + + + instance.on("close", () => { + clearInterval(interval); + clearInterval(customTasksInterval); + clearInterval(setCorrectTime); + clearInterval(sendNodeReadout); + clearInterval(accelerometerInterval); + rsPort.close(); + }); + + instance.on("0", _ => { + main(); + }) + + + instance.on("2", _ => { + console.log("dailyReport, reportToSend, rvo_is_on", dailyReport, reportToSend, rvo_is_on, previous_rvo_is_on_value); + }) + + instance.on("1", 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(); + return; + } + else if (flowdata.data == "close") { + rsPort.close(); + return; + } + else if (flowdata.data == "clean") { + tasks = []; + return; + } + else if (flowdata.data == "buildtasks") { + //build & run + return; + } + else if (flowdata.data == "run") { + //durations = []; + + if (tasks.length == 0) { + + buildTasks(); + + if (rsPort.isOpen) { + interval = setInterval(runTasks, 100); + } + else { + instance.send(SEND_TO.debug, "port is not opened!!!"); + } + } + } + else { + //terminal data - object + //logger.debug("flowdata", flowdata.data); + + if (typeof flowdata.data === 'object') { + //logger.debug("dido", flowdata.data); + if (flowdata.data.hasOwnProperty("sender")) { + //data from dido_controller + if (flowdata.data.sender == "dido_controller") { + + if (flowdata.data.hasOwnProperty("cmd")) { + let cmd = flowdata.data.cmd; + + if (cmd == "buildTasks") { + clearInterval(interval); + + logger.debug("-->Cmd-mngr: BUILD TASKS"); + buildTasks(); + + //logger.debug("tasks:"); + //logger.debug(tasks); + + logger.debug("-->Cmd-mngr: RUN TASKS"); + interval = setInterval(runTasks, 5000); + } + else if (cmd == "reload_relays") { + loadRelaysData(flowdata.data.line); + + if (flowdata.data.dataChanged) { + if (!flowdata.data.value) { + reportOfflineNodeStatus(flowdata.data.line); + } + else { + reportOnlineNodeStatus(flowdata.data.line); + } + } + + } + else if (cmd == "rotary_switch_state") { + let value = flowdata.data.value; + + //state was changed + if (rotary_switch_state != value) { + if (value == "Off") { + //vyreportovat vsetky svietdla + reportOfflineNodeStatus(); + } + + rotary_switch_state = value; + } + } + 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) { + + // we send lux_sensor value to all nodes: + let params = getParams(PRIORITY_TYPES.node_broadcast); + + params.recipient = 2;//2 broadcast, address = 0 + params.address = 0xffffffff;//Broadcast + + let ba = longToByteArray(lux_sensor); + + params.byte3 = ba[1];//msb + params.byte4 = ba[0]; + params.timestamp = PRIORITY_TYPES.node_broadcast; + params.info = "run broadcast: Actual Lux level from cabinet"; + params.register = 95;//Actual Lux level from cabinet + params.rw = 1;//write + + tasks.push(params); + + //process profiles + turnOnOffLinesAccordingToLuxSensor(lux_sensor); + } + } + else if (cmd == "state_of_breaker") { + //istic linie + + breakerCounter--; + + let value = flowdata.data.value; + let line = parseInt(flowdata.data.line); + + let dataChanged = false; + if (state_of_breaker[line] != value) dataChanged = true; + + state_of_breaker[line] = value; + + let status = "OK"; + if (value == "Off") status = "NOK"; + + if (dataChanged) { + + if (relaysData.hasOwnProperty(line)) { + let tbname = relaysData[line].tbname; + + if (value == "Off") { + sendNotification("Cmd-mngr: onData", tbname, "circuit_breaker_was_turned_off_line", { line: line }, "", SEND_TO.tb, instance, "circuit_breaker"); + if (breakerCounter < 0) reportToSend["contactor"]["off"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + else { + sendNotification("Cmd-mngr: onData", tbname, "circuit_breaker_was_turned_on_line", { line: line }, "", SEND_TO.tb, instance, "circuit_breaker"); + if (breakerCounter < 0) reportToSend["contactor"]["on"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + + //report status liniu + sendTelemetry({ status: status }, tbname) + + //current value + if (value == "Off") reportOfflineNodeStatus(line); //vyreportovat vsetky svietidla na linii + } + + } + } + else { + logger.debug("undefined cmd", cmd); + } + } + } + + return; + } + + //data from worksys + if (flowdata.data.hasOwnProperty("topic")) { + + let data = getNested(flowdata.data, "content", "data"); + + //if we get temperature in senica from senica-prod01 + let temperature = getNested(flowdata.data, "content", "senica_temperature"); + + if (temperature !== undefined) { + temperatureInSenica = temperature; + return; + } + + if (data === undefined) { + console.log("Invalid rpc command came from platform"); + return; + } + + let command = data.params.command; + let method = data.method; + let profile = data.params.payload; + if (profile == undefined) profile = ""; + let entity = data.params.entities[0]; + let entity_type = entity.entity_type; + let tbname = entity.tb_name; + + instance.send(SEND_TO.debug, flowdata.data); + 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") { + + //let command = data.params.command; + let value = data.params.payload.value; + + if (command == "dimming") { + + let nodeWasFound = false; + let keys = Object.keys(nodesData); + + //logger.debug("-----", keys); + + 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); + + value = parseInt(value); + if (value > 0) value = value + 128; + + params.type = "node-onetime-write"; + params.tbname = tbname; + params.address = node; + params.register = 1; + params.recipient = 1; + params.byte4 = value; + params.rw = 1; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'set dimming from platform'; + //params.debug = true; + + //debug(params); + logger.debug("dimming", params); + + tasks.push(params); + + 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); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 1; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read dimming (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + //pridame aj vyreportovanie - vykon + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 76; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read Input Power (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + //pridame aj vyreportovanie - prud svietidla + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 75; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read Input Current (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + //pridame aj vyreportovanie - power faktor - ucinnik + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 77; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read power factor (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + }, 4000); + + nodeWasFound = true; + break; + } + } + + if (!nodeWasFound) { + logger.debug("set dimming from platform", "unable to find tbname", tbname); + } + } + else { + instance.send(SEND_TO.debug, "undefined command " + command); + logger.debug("undefined command", command); + } + + return; + } + 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++) { + let node = keys[i]; + if (tbname == nodesData[node].tbname) { + + 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"); + + //profil úspešne prijatý pre node č. xx + sendNotification("Cmd-mngr", tbname, "dimming_profile_was_processed_for_node", { node: node }, profile, SEND_TO.tb, instance); + + nodesData[node].processed = false; + nodesData[node].profile = profile; + + processNodeProfile(node); + }); + }); + } + } + } + else { + + instance.send(SEND_TO.debug, "unknown method " + method); + logger.debug("unknown method", method); + + return; + } + } + + //nastav profil linie z platformy + 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") { + + 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++) { + let line = keys[i]; + if (tbname == relaysData[line].tbname) { + //zmazeme tasky + 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) { + + //update profile + logger.debug("worksys - update relay profile done:", profile); + instance.send(SEND_TO.debug, "worksys - update relay profile done"); + + relaysData[line].profile = profile; + + loadRelaysData(line) + logger.debug("loadRelaysData DONE for line", line); + + buildTasks({ processLineProfiles: true, line: line }); + + sendNotification("Cmd-mngr: set profile from worksys", tbname, "switching_profile_was_processed_for_line", { line: line }, profile, SEND_TO.tb, instance); + }); + }); + break; + } + } + } + else if (method == "set_command") { + let value = data.params.payload.value; + + 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; + + 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"); + if (line != 0) reportToSend["contactor"]["off"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + else { + turnLine("on", line, "command received from platform"); + if (line != 0) reportToSend["contactor"]["on"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + } + } + else { + instance.send(SEND_TO.debug, "undefined method " + method); + logger.debug("undefined method", method); + } + + return; + } + else { + instance.send(SEND_TO.debug, "UNKNOW entity_type " + entity_type); + logger.debug("UNKNOW entity_type", entity_type); + } + return; + } + + //terminal + if (!rsPort.isOpen) await rsPort.open(); + + let params = flowdata.data.body; + if (params == undefined) { + //logger.debug("Cmd-mngr: flowdata.data.body is undefined"); + return; + } + + params.priority = PRIORITY_TYPES.terminal; + params.type = "cmd-terminal"; + params.tbname = ""; + params.timestamp = PRIORITY_TYPES.terminal; + params.addMinutesToTimestamp = 0;// do not repeat task!!! + params.debug = true; + + let timestamp = Date.now(); + params.refFlowdataKey = timestamp; + //params.refFlowdata = flowdata; + //refFlowdata = flowdata; + + //console.log("flowdata", flowdata); + + cleanUpRefFlowdataObj(); + + refFlowdataObj[timestamp] = flowdata; + + //fix + //params.address = params.adress; + logger.debug("received from terminal", params); + logger.debug("date/time:", new Date()); + logger.debug("tasks length:", tasks.length); + + //tasks = []; + + //add to tasks + tasks.push(params); + + } + } + }) + + + //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) + } + + + /** + * 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; + + RESTBuilder.make(function(builder) { + + if (!builder) return; + + builder.method('GET'); + builder.url('http://192.168.252.2:8004/gettime?projects_id=1'); + + builder.callback(function(err, response, output) { + + 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); + } + + }); + } + + } 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); + + } else { + //console.log("Read-only", stdout); + + 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]: [ + { + "ts": date, + "values": values + } + ] + } + + tbHandler.sendToTb(dataToTb, instance); + } + + + function calculateDuskDawn(date, line, duskOffset = 0, dawnOffset = 0) { + + if (date === undefined) date = new Date(); + + 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); + } + + //if(profile.dawn_lux_sensor == false) + { + if (profile.hasOwnProperty("dawn_astro_clock_offset")) dawn_astro_clock_offset = parseInt(profile.dawn_astro_clock_offset); + } + + } + + } catch (error) { + if (profilestr != "") { + logger.debug(profilestr); + logger.debug(error); + } + } + + 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; + } + + //Dimming, CCT + else if (register == 1) { + let brightness = 0; + let dimming = byte0; + if (dimming > 128) { + //dimming = -128; + brightness = dimming - 128; + } + + //cct + //Ak Byte3 == 1: CCT = (Byte2*256)+Byte1 + let cct; + if (byte3 == 1) cct = byte2 * 256 + byte1; + else cct = bytesToInt(bytes.slice(0, 3)); + + //cct podla auditu + + values["dimming"] = brightness; + return values; + } + + // + else if (register == 4) { + values["master_node_version"] = bytes[1] + "." + bytes[2]; + //logger.debug("FW Version", register, bytes); + } + + //Napätie + else if (register == 74) { + let voltage = (bytesToInt(bytes) * 0.1).toFixed(1); + values["voltage"] = Number(voltage); + } + + //Prúd + else if (register == 75) { + let current = bytesToInt(bytes); + values["current"] = current; + } + + //výkon + else if (register == 76) { + let power = (bytesToInt(bytes) * 0.1).toFixed(2); + values["power"] = Number(power); + } + + //účinník + else if (register == 77) { + let power_factor = Math.cos(bytesToInt(bytes) * 0.1 * (Math.PI / 180)).toFixed(2); + values["power_factor"] = Number(power_factor); + } + + //frekvencia + else if (register == 78) { + let frequency = (bytesToInt(bytes) * 0.1).toFixed(2); + values["frequency"] = Number(frequency); + } + + //energia + else if (register == 79) { + let energy = bytesToInt(bytes); + values["energy"] = energy / 1000; //energia v kWh -> delit 1000 + } + + //doba života + else if (register == 80) { + let lifetime = (bytesToInt(bytes) / 60).toFixed(2); + values["lifetime"] = Number(lifetime); + } + + //nastavenie profilu + else if (register == 8) { + let time_schedule_settings = bytesToInt(bytes); + values["time_schedule_settings"] = time_schedule_settings; + } + + //naklon - nateraz sa z nodu nevycitava! kvoli problemom s accelerometrom a vracanymi hodnotami, posielame temp a x y z vo funkcii accelerometerData() + else if (register == 84) { + values["temperature"] = byte3 >= 128 ? (byte3 - 128) * (-1) : byte3; + values["inclination_x"] = byte2 >= 128 ? (byte2 - 128) * (-1) : byte2; + values["inclination_y"] = byte1 >= 128 ? (byte1 - 128) * (-1) : byte1; + values["inclination_z"] = byte0 >= 128 ? (byte0 - 128) * (-1) : byte0; + } + + //FW verzia nodu + else if (register == 89) { + //formát: "Byte3: Byte2.Byte1 (Byte0)" + values["fw_version"] = byte3 + ":" + byte2 + "." + byte1 + "(" + byte0 + ")"; + } + + else if (register == 87 || register == 6 || register == 7) { + var d = new Date(); + d.setHours(byte3, byte2, 0, 0); + let timestamp = d.getTime(); + + //aktuálny čas + if (register == 87) values["actual_time"] = timestamp; + //čas súmraku + else if (register == 6) values["dusk_time"] = timestamp; + //čas úsvitu + else if (register == 7) values["dawn_time"] = timestamp; + } + + 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; + + } + + + function getObjectByTbValue(object, tbname) { + return object[Object.keys(object).find(key => object[key].tbname === tbname)]; + } + + + function isObject(item) { + return (typeof item === "object" && !Array.isArray(item) && item !== null); + } + + + // we fake data, that should be received from accelerometer, as they are a bit unreliable. (temperature, x,y,z) + function accelerometerData() { + + if (temperatureInSenica === null) return; + + //clone nodesData and relaysData objects + let nodesData_clone = JSON.parse(JSON.stringify(nodesData)); + let relaysData_clone = JSON.parse(JSON.stringify(relaysData)); + + for (const key in relaysData_clone) { + + const lineData = relaysData_clone[key]; + const lineNumber = lineData.line; + const contactor = lineData.contactor; + + if (lineNumber === 0) continue; + + if (contactor === 1) { + + let date = Date.now(); + + Object.keys(nodesData_clone).forEach((node, index) => { + + setTimeout(function() { + + if (nodesData_clone[node].line === lineNumber) { + + // NOTE: if status of luminaire is NOK or OFFLINE, we do not send data; + let status = nodesData_clone[node].status; + if (status === "OFFLINE" || !status) return; + + let x = null; + if (naklony.hasOwnProperty(node)) x = naklony[node].naklon; + if (x === null) x = 0; + + sendTelemetry({ temperature: Math.round(temperatureInSenica + 10 + Math.floor(Math.random() * 3)), inclination_x: x, inclination_y: 0, inclination_z: 0 }, nodesData_clone[node].tbname, date); + } + + }, (index + 1) * 500); + }) + + } + } + } + + +} // end of instance.export + diff --git a/RVO36/flow/code.js b/RVO36/flow/code.js new file mode 100755 index 0000000..63b31bf --- /dev/null +++ b/RVO36/flow/code.js @@ -0,0 +1,90 @@ +exports.id = 'code'; +exports.title = 'Code'; +exports.group = 'Common'; +exports.color = '#656D78'; +exports.input = true; +exports.output = 1; +exports.author = 'Peter Širka'; +exports.icon = 'code'; +exports.version = '1.2.0'; +exports.options = { outputs: 1, code: 'send(0, value);', keepmessage: true }; + +exports.html = `
+
+
+
@(Number of outputs)
+
@(Minimum is 1)
+
+
+
@(Code)
+
@(Keep message instance)
+
+`; + +exports.readme = `# Code + +This component executes custom JavaScript code as it is and it doesn't contain any secure scope. + +\`\`\`javascript +// value {Object} contains received data +// send(outputIndex, newValue) sends a new value +// error(value) sends an error +// instance {Object} a current component instance +// flowdata {Object} a current flowdata +// repository {Object} a current repository of flowdata +// Example: + +// send() can be execute multiple times +send(0, value); +\`\`\``; + +exports.install = function(instance) { + + var fn; + + instance.on('data', function(response) { + if (fn) { + try { + fn(response.data, instance, response, instance.options, response.repository, require); + } catch (e) { + response.data = e; + instance.throw(response); + } + } + }); + + instance.reconfigure = function() { + try { + if (instance.options.code) { + instance.status(''); + var code = 'var send = function(index, value) { if (options.keepmessage) { flowdata.data = value; instance.send2(index, flowdata); } else instance.send2(index, value);}; var error = function(err) { instance.throw(err); }; ' + instance.options.code; + fn = new Function('value', 'instance', 'flowdata', 'options', 'repository', 'require', code); + } else { + instance.status('Not configured', 'red'); + fn = null; + } + } catch (e) { + fn = null; + instance.error('Code: ' + e.message); + } + }; + + instance.on('options', instance.reconfigure); + instance.reconfigure(); +}; \ No newline at end of file diff --git a/RVO36/flow/comment.js b/RVO36/flow/comment.js new file mode 100755 index 0000000..1e0cd13 --- /dev/null +++ b/RVO36/flow/comment.js @@ -0,0 +1,11 @@ +exports.id = 'comment'; +exports.title = 'Comment'; +exports.group = 'Common'; +exports.color = '#704cff'; +exports.author = 'Martin Smola'; +exports.icon = 'comment'; +exports.traffic = false; +exports.version = '1.0.0'; +exports.readme = '# Comment'; + +exports.install = function() {}; diff --git a/RVO36/flow/count.js b/RVO36/flow/count.js new file mode 100755 index 0000000..fa92ee9 --- /dev/null +++ b/RVO36/flow/count.js @@ -0,0 +1,60 @@ +exports.id = 'count'; +exports.title = 'Count'; +exports.version = '1.0.1'; +exports.author = 'John Graves'; +exports.color = '#656D78'; +exports.icon = 'plus-square'; +exports.input = 2; +exports.output = 1; +exports.options = { increment: 1, initialvalue: 1 }; +exports.readme = `# Counter + +Counter Number of times called.`; + +exports.html = `
+
@(Initial Value)
+
@(Increment)
+

Example Video

+
`; + +exports.readme = `# Count + +This component counts the number of messages received. + +__Response:__ + +Integer value based on the initial value and increment settings. + +__Arguments:__ +- Initial Value: What number should be output on the receipt of the first message. +- Increment: What should the increment be for each following message received.`; + +exports.install = function(instance) { + + var count = 0; + var initialCall = true; + + instance.on('data', function(flowdata) { + var index = flowdata.index; + if (index) { + instance.debug('Reset Count.'); + count = instance.options.initialvalue; + initialCall = true; + } else { + // If this is the first time, set the value to 'initial value' + if(initialCall) { + initialCall = false; + count = instance.options.initialvalue; + } else + count = count+instance.options.increment; + instance.status('Count:' + count); + instance.send2(count); + } + }); + + instance.on('options', function() { + count = instance.options.initialvalue; + initialCall = true; + }); + +}; diff --git a/RVO36/flow/db_connector.js b/RVO36/flow/db_connector.js new file mode 100755 index 0000000..65ee94b --- /dev/null +++ b/RVO36/flow/db_connector.js @@ -0,0 +1,286 @@ +exports.id = 'db_connector'; +exports.title = 'DbConnector'; +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.html = `
+
+
+
DbConnector
+
+
+
`; + +exports.readme = `# read/write data to tables`; + +const instanceSendTo = { + debug: 0, + http_response: 1, +} + +const { promisifyBuilder, makeMapFromDbResult } = require('./helper/db_helper.js'); + +function extractWhereParams(params) +{ + let name = params[0]; + let operator = '='; + let value = params[1]; + + if(params.length == 3) + { + operator = params[1]; + value = params[2]; + } + + return {name: name, operator: operator, value: value}; +} + +exports.install = function(instance) { + + let refFlowdata = null;//holds reference to httprequest flowdata + + instance.on("close", () => { + + }) + + + instance.on("data", async function(flowdata) { + + let params = flowdata.data.body; + console.log("DbConnector", params); + + refFlowdata = flowdata; + + if(refFlowdata != undefined) + { + //make http response + let responseObj = {}; + responseObj["type"] = "SUCESS"; + + try{ + + let table = params.table; + let action = params.action; + + + if(params.data != undefined) + { + let className = params.data.className; + + if(className == "SqlQueryBuilder") + { + let type = params.data.type; + + console.log("SqlQueryBuilder---->", params.data); + + if(type == "SELECT") + { + let table = params.data.queryData.tables[0].table; + + const db = TABLE(table); + var builder = db.find(); + + let result = await promisifyBuilder(builder); + + let response = {}; + response["result"] = result; + response["success"] = true; + + responseObj["data"] = response; + + //console.log(responseObj); + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + } + + return; + } + } + + + console.log("db_connector---->", table, action); + + //actions: read, replace, insert, delete, update... + + if(action == "read") + { + const db = TABLE(params.table); + + //where builder.where('age', '<', 15); + //builder.where('id', 3403); + + var builder = db.find(); + + //https://docs.totaljs.com/latest/en.html#api~DatabaseBuilder~builder.where + if(params.hasOwnProperty("where")) + { + //optionalCan contain "=", "<=", "<", ">=", ">". + //Default value: '=' + + //1.["production_line", 1] + //2. ["or", ["production_line", 1], ["production_line", 2], "end"] + + if (Array.isArray(params.where)) { + + let multipleConditions = false; + + if(params.where[0] == "or") multipleConditions = true; + if (Array.isArray(params.where[0])) multipleConditions = true; + + if(multipleConditions) + { + + for(var i = 0; i < params.where.length; i++) + { + const item = params.where[i]; + + if(item === "or") builder.or(); + + if (Array.isArray(item)) + { + const { name, operator, value } = extractWhereParams(item); + builder.where(name, operator, value); + } + + if(item === "end") builder.end(); + + } + + } + else + { + const { name, operator, value } = extractWhereParams(params.where); + builder.where(name, operator, value); + } + + } + + /* + if(params.where.length >=2 ) + { + let name = params.where[0]; + let operator = '='; + let value = params.where[1]; + + if(params.where.length == 3) + { + operator = params.where[1]; + value = params.where[2]; + } + + builder.where(name, operator, value); + } + */ + } + + if(params.hasOwnProperty("between")) + { + builder.between(params.between[0], params.between[1], params.between[2]); + } + + let response = await promisifyBuilder(builder); + responseObj["data"] = response; + + //console.log(responseObj); + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + + return; + } + + if(action == "delete") + { + + } + + + if(action == "update") + { + //! data receiving from terminal (params) + // { + // hostname: 'localhost', + // table: 'settings', + // action: 'update', + // body: { + // rvo_name: 'terrrr', + // lang: 'en', + // temperature_adress: '28.427B45920702', + // latitude: 48.70826502, + // longitude: 17.28455203, + // mqtt_host: '192.168.252.4', + // mqtt_clientid: 'showroom_test_panel_led', + // mqtt_username: 'xmRd6RJxW53WZe4vMFLU', + // mqtt_port: 1883, + // maintanace_mode: false + // } + // } + const tableToModify = TABLE(params.table); + const newValues = params.body; + + tableToModify.modify(newValues).make(function(builder) { + + builder.callback(function(err, response) { + + if(!err) + { + responseObj["data"] = response; + responseObj["tableUpdated"] = true; + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + } + }); + }); + + } + + if(action == "replace") + { + //truncate table + const db = TABLE(params.table); + var builder = db.remove(); + db.clean(); + + //insert data + let data = params.data; + + for(let i = 0; i < data.length; i++) + { + //console.log(data[i]); + db.insert(data[i]); + } + + console.log("insert done"); + + let responseObj = {}; + responseObj["type"] = "SUCESS"; + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + + + } + + + + } catch (error) { + //console.log(error); + responseObj["type"] = "ERROR"; + responseObj["message"] = error; + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + } + } + }) +} + + diff --git a/RVO36/flow/db_init.js b/RVO36/flow/db_init.js new file mode 100755 index 0000000..b399878 --- /dev/null +++ b/RVO36/flow/db_init.js @@ -0,0 +1,113 @@ +exports.id = 'db_init'; +exports.title = 'DB Initialization'; +exports.group = 'Worksys'; +exports.color = '#888600'; +exports.version = '1.0.2'; +exports.icon = 'sign-out'; +exports.output = 2; + +exports.readme = ` + # DB initialization +`; + +const { promisifyBuilder, makeMapFromDbResult } = require('./helper/db_helper.js'); +const { initNotification } = require('./helper/notification_reporter'); +const errorHandler = require('./helper/ErrorToServiceHandler'); +const total_energy = require('../databases/total_energy'); + +const SEND_TO = { + db_init: 0, + infoSender: 1 +}; + + +exports.install = async function(instance) { + const dbNodes = TABLE("nodes"); + const dbRelays = TABLE("relays"); + const dbSettings = TABLE("settings"); + 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 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.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"]; + Object.keys(dbs.nodesData).forEach(node => dbs.nodesData[node].readout = {}) + + let rvo_number = responseSettings[0]["rvo_name"].match(/\D+(\d{1,2})_/)[1]; + + dbs.settings = { + edge_fw_version: "2025-10-08", //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"], + phases: responseSettings[0]["phases"], + cloud_topic: responseSettings[0]["cloud_topic"], + has_main_switch: responseSettings[0]["has_main_switch"], + daily_report: responseSettings[0]["daily_report"], + send_changed_node_numbers: responseSettings[0]["send_changed_node_numbers"], + rvo_number: rvo_number, + + //dynamic values + masterNodeIsResponding: true, //cmd_manager + maintenance_mode: false, + } + + + dbs.settings.energy_to_switch_lamps = total_energy[rvo_number]; + if (dbs.settings.energy_to_switch_lamps === undefined) console.log('=============== db_init.js: energy_to_switch_lamps is undefined'); + + FLOW.dbLoaded = true; + errorHandler.setProjectId(dbs.settings.project_id); + initNotification(); + + //APP START - send to data services + const toService = { + id: dbs.settings.project_id, + name: dbs.settings.rvo_name, + fw_version: dbs.settings.edge_fw_version, + startdate: new Date().toISOString().slice(0, 19).replace('T', ' '), + js_error: "", + error_message: "" + }; + + instance.send(SEND_TO.infoSender, toService); + console.log("----------------> START - message send to service", toService); + + setTimeout(() => { + console.log("DB_INIT - data loaded"); + instance.send(SEND_TO.db_init, "_") + }, 5000) + +}; + diff --git a/RVO36/flow/debug.js b/RVO36/flow/debug.js new file mode 100755 index 0000000..00cb259 --- /dev/null +++ b/RVO36/flow/debug.js @@ -0,0 +1,100 @@ +exports.id = 'debug'; +exports.title = 'Debug'; +exports.author = 'Peter Širka'; +exports.color = '#967ADC'; +exports.click = true; +exports.input = true; +exports.icon = 'bug'; +exports.version = '2.0.4'; +exports.options = { enabled: true, repository: false, type: 'data' }; +exports.readme = `# Debug + +Prints data to the debug tab.`; + +exports.html = `
+
+
+
@(Output type)
+
@(Path to the property (leave empty to show the whole data object))
+
@(A group name)
+
@(Enabled)
+
+
+
`; + +exports.install = function(instance) { + + instance.on('data', function(response) { + if (instance.options.enabled) { + + var opt = instance.options; + var rep = response.repository; + var val = response.data; + var id = response.id; + + switch (instance.options.type){ + case 'both': + var data = {}; + data.repository = rep; + data.data = val instanceof Error ? { error: val.message, stack: val.stack } : val; + instance.debug(safeparse(opt.property ? U.get(data, opt.property) : data), undefined, opt.group, id); + break; + case 'repository': + instance.debug(safeparse(opt.property ? U.get(rep, opt.property) : rep), undefined, opt.group, id); + break; + case 'data': + default: + if (val instanceof Error) + instance.debug({ error: val.message, stack: val.stack }, undefined, opt.group, id); + else + instance.debug(safeparse(opt.property ? U.get(val, opt.property) : val), undefined, opt.group, id); + break; + } + } + }); + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + instance.save(); + }); + + instance.on('options', function() { + instance.custom.status(); + }); + + instance.custom.status = function() { + instance.status(instance.options.enabled ? 'Enabled' : 'Disabled'); + }; + + instance.custom.status(); + + function safeparse(o) { + + if (o instanceof Buffer) + return o; + + if (o === undefined) + return 'undefined'; + + if (o === null) + return 'null'; + + var cache = []; + var str = JSON.stringify(o, function(key, value) { + if (typeof value === 'object' && value !== null) { + if (cache.indexOf(value) !== -1) { + try { + return JSON.parse(JSON.stringify(value)); + } catch (error) { + return; + } + } + cache.push(value); + } + return value; + }); + cache = null; + return JSON.parse(str); + } +}; diff --git a/RVO36/flow/designer.json b/RVO36/flow/designer.json new file mode 100755 index 0000000..580f5a3 --- /dev/null +++ b/RVO36/flow/designer.json @@ -0,0 +1,3102 @@ +{ + "tabs": [ + { + "name": "MAIN PUSH", + "linker": "main-push", + "id": "1612772287426", + "index": 0 + }, + { + "name": "CMD manager", + "linker": "cmd-manager", + "id": "1615551125555", + "index": 1 + }, + { + "name": "Devices", + "linker": "devices", + "id": "1611921777196", + "index": 2 + } + ], + "components": [ + { + "id": "1611951142547", + "component": "debug", + "tab": "1611921777196", + "name": "ERROR", + "x": 598, + "y": 60, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#DA4453", + "notes": "" + }, + { + "id": "1612776786008", + "component": "wsmqttpublish", + "tab": "1612772287426", + "name": "WS MQTT publish", + "x": 281.75, + "y": 174, + "connections": { + "0": [ + { + "index": "0", + "id": "1615551060773" + } + ], + "1": [ + { + "index": "0", + "id": "1618300858252" + }, + { + "index": "0", + "id": "1618558465485" + } + ], + "2": [ + { + "index": "0", + "id": "1634303685503" + } + ], + "3": [ + { + "index": "0", + "id": "1731068754606" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Connected", + "color": "green" + }, + "options": { + "username": "", + "clientid": "", + "port": "1883", + "host": "" + }, + "color": "#888600", + "notes": "" + }, + { + "id": "1612778461252", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "tb-push", + "x": 72.75, + "y": 328, + "connections": { + "0": [ + { + "index": "0", + "id": "1612783322136" + }, + { + "index": "1", + "id": "1612776786008" + }, + { + "index": "0", + "id": "1731068754606" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1612783322136", + "component": "debug", + "tab": "1612772287426", + "name": "to TB", + "x": 283.75, + "y": 324, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615551060773", + "component": "debug", + "tab": "1612772287426", + "name": "errors from MQTT Broker", + "x": 594, + "y": 57, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#DA4453", + "notes": "" + }, + { + "id": "1615563373927", + "component": "debug", + "tab": "1615551125555", + "name": "Debug", + "x": 755, + "y": 155, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#DA4453", + "notes": "" + }, + { + "id": "1615566865233", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "tb-push", + "x": 755, + "y": 248, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1615798582262", + "component": "debug", + "tab": "1615551125555", + "name": "CMD_debug", + "x": 755, + "y": 346, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615802995322", + "component": "debug", + "tab": "1611921777196", + "name": "Debug", + "x": 596.8833312988281, + "y": 566.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Disabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": false + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615809128443", + "component": "debug", + "tab": "1611921777196", + "name": "tempToTb", + "x": 595.8833312988281, + "y": 658.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615809595184", + "component": "virtualwireout", + "tab": "1611921777196", + "name": "tb-push", + "x": 597.8833312988281, + "y": 377.25, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1616165795916", + "component": "httproute", + "tab": "1615551125555", + "name": "POST /terminal", + "x": 135, + "y": 547, + "connections": { + "0": [ + { + "index": "0", + "id": "1684060205000" + }, + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Listening", + "color": "green" + }, + "options": { + "timeout": 10, + "cachepolicy": 0, + "cacheexpire": "5 minutes", + "size": 5, + "url": "/terminal", + "method": "POST", + "name": "", + "flags": [ + "id:1616165795916", + "post", + 10000 + ], + "emptyresponse": false + }, + "color": "#5D9CEC", + "notes": "### Configuration\n\n- __POST /terminal__\n- flags: \n- maximum request data length: __5 kB__\n- empty response: __false__\n- cache policy: __no cache__\n- cache expire: __5 minutes__", + "cloning": false + }, + { + "id": "1616165824813", + "component": "httpresponse", + "tab": "1615551125555", + "name": "HTTP Response", + "x": 753, + "y": 423, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "json" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1617104731852", + "component": "debug", + "tab": "1615551125555", + "name": "DIDO_Debug", + "x": 669, + "y": 1040, + "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": "turnOff line", + "x": 133, + "y": 1161, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "object", + "data": "{line: 3, command: \"turnOff\", force: true}" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1617115013095", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "tb-push", + "x": 669, + "y": 1150, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1617284749681", + "component": "trigger", + "tab": "1615551125555", + "name": "update profile / node", + "x": 112, + "y": 208, + "connections": { + "0": [ + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "data": "profile_nodes", + "datatype": "string" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1618235171399", + "component": "trigger", + "tab": "1615551125555", + "name": "tun tasks", + "x": 184, + "y": 279, + "connections": { + "0": [ + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "data": "run" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1618300858252", + "component": "debug", + "tab": "1612772287426", + "name": "wsmqtt-exit1", + "x": 597.8833312988281, + "y": 149, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1618393583970", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "to-cmd-manager", + "x": 668.8833312988281, + "y": 1269, + "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": 132.88333129882812, + "y": 367, + "connections": { + "0": [ + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "platform-rpc-call", + "color": "gray" + }, + "options": { + "wirename": "platform-rpc-call" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1618393759854", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "cmd_to_dido", + "x": 119.88333129882812, + "y": 1007, + "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": 752.8833312988281, + "y": 527, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "cmd_to_dido", + "color": "gray" + }, + "options": { + "wirename": "cmd_to_dido" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1618558465485", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "platform-rpc-call", + "x": 597.8833312988281, + "y": 247, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "platform-rpc-call", + "color": "gray" + }, + "options": { + "wirename": "platform-rpc-call" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1618572059773", + "component": "trigger", + "tab": "1615551125555", + "name": "turnOn line", + "x": 132, + "y": 1085, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "data": "{line: 1, command: \"turnOn\", force: true}", + "datatype": "object" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1619515097737", + "component": "cmd_manager", + "tab": "1615551125555", + "name": "CMD Manager", + "x": 452.1091003417969, + "y": 341.05455017089844, + "connections": { + "0": [ + { + "index": "0", + "id": "1615563373927" + } + ], + "1": [ + { + "index": "0", + "id": "1615566865233" + }, + { + "index": "0", + "id": "1615798582262" + } + ], + "2": [ + { + "index": "0", + "id": "1616165824813" + } + ], + "3": [ + { + "index": "0", + "id": "1618393827655" + } + ], + "4": [ + { + "index": "0", + "id": "1635936391935" + } + ], + "5": [ + { + "index": "0", + "id": "1757006030239" + }, + { + "index": "0", + "id": "1757006060377" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1619605019281", + "component": "httproute", + "tab": "1615551125555", + "name": "GET db", + "x": 173, + "y": 653, + "connections": { + "0": [ + { + "index": "0", + "id": "1684060205000" + }, + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Listening", + "color": "green" + }, + "options": { + "timeout": 5, + "cachepolicy": 0, + "cacheexpire": "5 minutes", + "size": 5, + "url": "/db", + "method": "GET", + "name": "", + "flags": [ + "id:1619605019281", + "get", + 5000 + ] + }, + "color": "#5D9CEC", + "notes": "### Configuration\n\n- __GET /db__\n- flags: undefined\n- maximum request data length: __5 kB__\n- empty response: __undefined__\n- cache policy: __no cache__\n- cache expire: __5 minutes__", + "cloning": false + }, + { + "id": "1619784672383", + "component": "trigger", + "tab": "1615551125555", + "name": "turnOnAlarm", + "x": 120, + "y": 1234, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "object", + "data": "{command: \"turnOnAlarm\"}" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1619784812964", + "component": "trigger", + "tab": "1615551125555", + "name": "turnOffAlarm", + "x": 118, + "y": 1307, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "object", + "data": "{command: \"turnOffAlarm\"}" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1621340721628", + "component": "virtualwireout", + "tab": "1611921777196", + "name": "modbus_to_dido", + "x": 599, + "y": 471, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "modbus_to_dido", + "color": "gray" + }, + "options": { + "wirename": "modbus_to_dido" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1622640022885", + "component": "httproute", + "tab": "1615551125555", + "name": "POST /db_connector", + "x": 98, + "y": 1586, + "connections": { + "0": [ + { + "index": "0", + "id": "1622640073521" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Listening", + "color": "green" + }, + "options": { + "timeout": 5, + "cachepolicy": 0, + "cacheexpire": "5 minutes", + "size": 5, + "url": "/db_connector", + "method": "POST", + "flags": [ + "id:1622640022885", + "post", + 5000 + ] + }, + "color": "#5D9CEC", + "notes": "### Configuration\n\n- __POST /db_connector__\n- flags: \n- maximum request data length: __5 kB__\n- empty response: __undefined__\n- cache policy: __no cache__\n- cache expire: __5 minutes__", + "cloning": false + }, + { + "id": "1622640073521", + "component": "db_connector", + "tab": "1615551125555", + "name": "DbConnector", + "x": 372, + "y": 1572, + "connections": { + "1": [ + { + "index": "0", + "id": "1622641420685" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "edge": "undefined" + }, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1622641420685", + "component": "httpresponse", + "tab": "1615551125555", + "name": "HTTP Response", + "x": 596, + "y": 1586, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1634303504177", + "component": "monitormemory", + "tab": "1612772287426", + "name": "RAM", + "x": 69.88333129882812, + "y": 888.5, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465281992" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "858.88 MB / 985.68 MB", + "color": "gray" + }, + "options": { + "enabled": true, + "interval": 30000 + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1634303533779", + "component": "monitordisk", + "tab": "1612772287426", + "name": "disk", + "x": 70.88333129882812, + "y": 982.5, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465821120" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "5.78 GB / 7.26 GB", + "color": "gray" + }, + "options": { + "enabled": true, + "path": "/", + "interval": 30000 + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1634303595494", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "send-to-services", + "x": 51.883331298828125, + "y": 1400.5, + "connections": { + "0": [ + { + "index": "0", + "id": "1634463186563" + }, + { + "index": "1", + "id": "1634488120710" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1634303602169", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "send-to-services", + "x": 426.8833312988281, + "y": 878.5, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1634303685503", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "send-to-services", + "x": 600.8833312988281, + "y": 341.5, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1634303743260", + "component": "httprequest", + "tab": "1612772287426", + "name": "192.168.252.2:8004/sentmessage", + "reference": "", + "x": 506.8833312988281, + "y": 1331.7333374023438, + "connections": { + "0": [ + { + "index": "0", + "id": "1635327431236" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "url": "http://192.168.252.2:8004/sentmessage", + "method": "POST", + "stringify": "json" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1634463186563", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 305.75, + "y": 1442, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634464580289", + "component": "code", + "tab": "1612772287426", + "name": "Code", + "x": 245, + "y": 787, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465243324" + }, + { + "index": "0", + "id": "1634303602169" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "keepmessage": true, + "code": "let response = {};\nresponse.cpu = value.cpu;\nresponse.uptime = value.uptime;\n\nsend(0, response);", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1634465243324", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 428, + "y": 784, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634465281992", + "component": "code", + "tab": "1612772287426", + "name": "Code", + "x": 245, + "y": 884, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465338103" + }, + { + "index": "0", + "id": "1634303602169" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "keepmessage": true, + "code": "value.sender = \"ram\";\n\nlet response = {};\n\nresponse.memory_total = Math.round(value.total / (1024 ** 2));\nresponse.memory_free = Math.round(value.free / (1024 ** 2));\nresponse.memory_used = Math.round(value.used / (1024 ** 2));\n\nsend(0, response);", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1634465338103", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 429, + "y": 976, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634465821120", + "component": "code", + "tab": "1612772287426", + "name": "Code", + "x": 245, + "y": 978, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465892500" + }, + { + "index": "0", + "id": "1634303602169" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "keepmessage": true, + "code": "value.sender = \"hdd\";\n\nlet response = {};\n\nresponse.hdd_total = Math.round(value.total / (1024 ** 2));\nresponse.hdd_free = Math.round(value.free / (1024 ** 2));\nresponse.hdd_used = Math.round(value.used / (1024 ** 2));\n\nsend(0, response);", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1634465892500", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 432, + "y": 1068, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634484067516", + "component": "debug", + "tab": "1612772287426", + "name": "Send info", + "x": 513, + "y": 1441, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634488120710", + "component": "infosender", + "tab": "1612772287426", + "name": "Info sender", + "x": 301, + "y": 1336, + "connections": { + "0": [ + { + "index": "0", + "id": "1634484067516" + }, + { + "index": "0", + "id": "1634303743260" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "edge": "undefined" + }, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1635327431236", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 837.8833312988281, + "y": 1325.5, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1635936391935", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "send-to-services", + "x": 753, + "y": 623, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1637069803394", + "component": "monitorconsumption", + "tab": "1612772287426", + "name": "CPU", + "x": 69, + "y": 791, + "connections": { + "0": [ + { + "index": "0", + "id": "1634464580289" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "49.2% / 69.91 MB", + "color": "gray" + }, + "options": { + "monitorfiles": true, + "monitorconnections": true, + "monitorsize": true, + "monitorconsumption": true, + "enabled": true, + "interval": 30000 + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1683664161036", + "component": "debug", + "tab": "1615551125555", + "name": "CMDtoDIDO", + "x": 392, + "y": 1012, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1683981346282", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "from-dido-controller", + "x": 112, + "y": 459, + "connections": { + "0": [ + { + "index": "0", + "id": "1684055037116" + }, + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "from-dido-controller", + "color": "gray" + }, + "options": { + "wirename": "from-dido-controller" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1684055037116", + "component": "debug", + "tab": "1615551125555", + "name": "from dido to cmd", + "x": 451, + "y": 532, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1684060205000", + "component": "debug", + "tab": "1615551125555", + "name": "HTTP routes", + "x": 450, + "y": 639, + "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": "MDBToDido", + "x": 598, + "y": 147, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1699963668903", + "component": "dido_controller", + "tab": "1615551125555", + "name": "DIDO_Controller", + "x": 397, + "y": 1131, + "connections": { + "0": [ + { + "index": "0", + "id": "1617104731852" + } + ], + "1": [ + { + "index": "0", + "id": "1617104731852" + }, + { + "index": "0", + "id": "1617115013095" + } + ], + "2": [ + { + "index": "0", + "id": "1618393583970" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "edge": "undefined" + }, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1699964678894", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "modbus_to_dido", + "x": 96, + "y": 924, + "connections": { + "0": [ + { + "index": "0", + "id": "1699963668903" + }, + { + "index": "0", + "id": "1699964793925" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "modbus_to_dido", + "color": "gray" + }, + "options": { + "wirename": "modbus_to_dido" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1699964793925", + "component": "debug", + "tab": "1615551125555", + "name": "modbusToDido", + "x": 388, + "y": 920, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1699965957410", + "component": "modbus_reader", + "tab": "1611921777196", + "name": "Modbus reader", + "x": 232, + "y": 175, + "connections": { + "0": [ + { + "index": "0", + "id": "1611951142547" + } + ], + "1": [ + { + "index": "0", + "id": "1621340721628" + }, + { + "index": "0", + "id": "1684179110403" + }, + { + "index": "0", + "id": "1717441414646" + } + ], + "2": [ + { + "index": "0", + "id": "1615809595184" + }, + { + "index": "0", + "id": "1714752862828" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1700411878636", + "component": "thermometer", + "tab": "1611921777196", + "name": "Thermometer", + "x": 234.75, + "y": 444, + "connections": { + "0": [ + { + "index": "0", + "id": "1615802995322" + } + ], + "1": [ + { + "index": "0", + "id": "1615809595184" + }, + { + "index": "0", + "id": "1615809128443" + } + ], + "2": [ + { + "index": "0", + "id": "1621340721628" + }, + { + "index": "0", + "id": "1732889185927" + }, + { + "index": "0", + "id": "1717441414646" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#5CB36D", + "notes": "" + }, + { + "id": "1714752862828", + "component": "debug", + "tab": "1611921777196", + "name": "MDBToTb", + "x": 766, + "y": 324, + "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": 764.0833282470703, + "y": 222, + "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\telse if(value.status === \"NOK-thermometer\")\n\t{\n\t\tsend(0, {\"thermometer\": \"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\telse if(value.values.hasOwnProperty(\"temperature\"))\n\t{\n\t\tsend(0, {\"thermometer\": \"OK\"});\n\t}\n}", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1717442627834", + "component": "debug", + "tab": "1611921777196", + "name": "modbus service", + "x": 966.0833282470703, + "y": 165, + "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": 968.0833282470703, + "y": 268, + "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": 88.75, + "y": 1685, + "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": 296, + "y": 1671, + "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\", \"Flow has been restarted\", \"Node db has changed\"]", + "types": "[\"emergency\", \"critical\", \"error\", \"alert\"]", + "name": "" + }, + "color": "#30E193", + "notes": "" + }, + { + "id": "1718016073501", + "component": "httprequest", + "tab": "1612772287426", + "name": "http://192.168.252.2:8004/slack", + "x": 495, + "y": 1753, + "connections": { + "0": [ + { + "index": "0", + "id": "1718016086212" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "url": "http://192.168.252.2:8004/slack", + "method": "POST", + "stringify": "json" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1718016086212", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 832, + "y": 1664, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "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": 87, + "y": 1591, + "connections": { + "0": [ + { + "index": "0", + "id": "1718016052341" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "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\": \"\" } } } ] }", + "datatype": "object" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1729855334955", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "platform-rpc-call", + "x": 599.9333343505859, + "y": 541.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "platform-rpc-call", + "color": "gray" + }, + "options": { + "wirename": "platform-rpc-call" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1729855371093", + "component": "debug", + "tab": "1612772287426", + "name": "rpc cloud", + "x": 601.9333343505859, + "y": 440.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1731068658334", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 75.75, + "y": 184, + "connections": { + "0": [ + { + "index": "0", + "id": "1612776786008" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731068754606", + "component": "cloudmqttconnect", + "tab": "1612772287426", + "name": "MQTT to senica-prod01", + "x": 284.75, + "y": 452, + "connections": { + "1": [ + { + "index": "0", + "id": "1729855371093" + }, + { + "index": "0", + "id": "1729855334955" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Connected", + "color": "green" + }, + "options": { + "username": "", + "clientid": "", + "port": "2764", + "host": "192.168.252.2", + "topic": "" + }, + "color": "#888600", + "notes": "" + }, + { + "id": "1731069001548", + "component": "db_init", + "tab": "1612772287426", + "name": "DB Initialization", + "x": 1003.75, + "y": 240.25, + "connections": { + "0": [ + { + "index": "0", + "id": "1731069033416" + } + ], + "1": [ + { + "index": "0", + "id": "1747561603739" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#888600", + "notes": "" + }, + { + "id": "1731069033416", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "db-init", + "x": 1244.75, + "y": 233.25, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069059135", + "component": "showdb", + "tab": "1612772287426", + "name": "Show db data", + "x": 1186.75, + "y": 821.25, + "connections": { + "0": [ + { + "index": "0", + "id": "1731069079243" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#888600", + "notes": "" + }, + { + "id": "1731069079243", + "component": "debug", + "tab": "1612772287426", + "name": "dbData", + "x": 1390.75, + "y": 870.25, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1731069116691", + "component": "trigger", + "tab": "1612772287426", + "name": "settings", + "x": 934.75, + "y": 669.75, + "connections": { + "0": [ + { + "index": "0", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069131637", + "component": "trigger", + "tab": "1612772287426", + "name": "relaysData", + "x": 876.75, + "y": 733.75, + "connections": { + "0": [ + { + "index": "1", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069137374", + "component": "trigger", + "tab": "1612772287426", + "name": "nodesData", + "x": 852.75, + "y": 794.75, + "connections": { + "0": [ + { + "index": "2", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069179846", + "component": "trigger", + "tab": "1612772287426", + "name": "pinsData", + "x": 850.75, + "y": 861.75, + "connections": { + "0": [ + { + "index": "3", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069192937", + "component": "trigger", + "tab": "1612772287426", + "name": "sample data", + "x": 857.75, + "y": 928.75, + "connections": { + "0": [ + { + "index": "4", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069264443", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 63.75, + "y": 1279, + "connections": { + "0": [ + { + "index": "0", + "id": "1634488120710" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069334626", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "db-init", + "x": 172.88333129882812, + "y": 129, + "connections": { + "0": [ + { + "index": "0", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069548145", + "component": "virtualwirein", + "tab": "1611921777196", + "name": "db-init", + "x": 46.75, + "y": 192, + "connections": { + "0": [ + { + "index": "0", + "id": "1699965957410" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069567152", + "component": "virtualwirein", + "tab": "1611921777196", + "name": "db-init", + "x": 44.75, + "y": 465, + "connections": { + "0": [ + { + "index": "0", + "id": "1700411878636" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731070156936", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "db-init", + "x": 126.88333129882812, + "y": 1377, + "connections": { + "0": [ + { + "index": "2", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731234189516", + "component": "trigger", + "tab": "1612772287426", + "name": "monitor.txt", + "x": 882.75, + "y": 991.75, + "connections": { + "0": [ + { + "index": "5", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731234189551", + "component": "trigger", + "tab": "1612772287426", + "name": "err.txt", + "x": 904.75, + "y": 1053.75, + "connections": { + "0": [ + { + "index": "6", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1732700042559", + "component": "nodesdb_change_check", + "tab": "1612772287426", + "name": "Nodes DB change check", + "x": 266.8833312988281, + "y": 1980.2333984375, + "connections": { + "0": [ + { + "index": "0", + "id": "1732700071298" + }, + { + "index": "0", + "id": "1732700642917" + } + ], + "1": [ + { + "index": "0", + "id": "1759958914348" + }, + { + "index": "0", + "id": "1759959003114" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#888600", + "notes": "" + }, + { + "id": "1732700057052", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 76.75, + "y": 1988, + "connections": { + "0": [ + { + "index": "0", + "id": "1732700042559" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1732700071298", + "component": "debug", + "tab": "1612772287426", + "name": "nodesChange", + "x": 571.8833312988281, + "y": 2018.2333984375, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1732700642917", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "tb-push", + "x": 567.8833312988281, + "y": 1933, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1732889185927", + "component": "debug", + "tab": "1611921777196", + "name": "tempToDido", + "x": 594.8833312988281, + "y": 753, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1733574412965", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 72.75, + "y": 474, + "connections": { + "0": [ + { + "index": "1", + "id": "1731068754606" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1747561603739", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "send-to-services", + "x": 1243.8833312988281, + "y": 334.5, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1747562867845", + "component": "comment", + "tab": "1612772287426", + "name": "FLOW STARTING POINT", + "x": 1003.5666656494141, + "y": 178, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#704cff", + "notes": "" + }, + { + "id": "1749211698385", + "component": "trigger", + "tab": "1612772287426", + "name": "deviceStatus", + "x": 911.75, + "y": 1116.75, + "connections": { + "0": [ + { + "index": "7", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1757006030239", + "component": "httprequest", + "tab": "1615551125555", + "name": "192.168.252.2:8015/daily_report", + "x": 756.5666656494141, + "y": 715.4499969482422, + "connections": { + "0": [ + { + "index": "0", + "id": "1757006045804" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "stringify": "json", + "method": "POST", + "url": "http://192.168.252.2:8015/daily_report" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1757006045804", + "component": "debug", + "tab": "1615551125555", + "name": "ddd", + "x": 1091.566665649414, + "y": 711.4499969482422, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1757006060377", + "component": "debug", + "tab": "1615551125555", + "name": "reportDebug", + "x": 749.5666656494141, + "y": 799.4499969482422, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1759958914348", + "component": "httprequest", + "tab": "1612772287426", + "name": "http://192.168.252.2:8015/node_numbers", + "x": 571, + "y": 2111, + "connections": { + "0": [ + { + "index": "0", + "id": "1759958927094" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "stringify": "json", + "method": "POST", + "url": "http://192.168.252.2:8015/node_numbers" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1759958927094", + "component": "debug", + "tab": "1612772287426", + "name": "nodesChangeCloud", + "x": 951.8833312988281, + "y": 2109.2333984375, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1759959003114", + "component": "debug", + "tab": "1612772287426", + "name": "nodeChangeCloud1", + "x": 574, + "y": 2218, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1760020290879", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 84.75, + "y": 1787, + "connections": { + "0": [ + { + "index": "1", + "id": "1718016052341" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + } + ], + "version": 615 +} diff --git a/RVO36/flow/dido_controller.js b/RVO36/flow/dido_controller.js new file mode 100755 index 0000000..d16fb19 --- /dev/null +++ b/RVO36/flow/dido_controller.js @@ -0,0 +1,1486 @@ +exports.id = 'dido_controller'; +exports.title = 'DIDO_Controller'; +exports.version = '2.0.0'; +exports.group = 'Worksys'; +exports.color = '#2134B0'; +exports.input = 3; +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 + +state_of_main_switch - reportovat stav hlaveho istica : 0-> off 1-> on +rotary_switch_state - sem by sa mal reportovat stav vstupov manual a auto pola nasledovnej logiky: Manual = 1 a Auto = 0 -> Manu +Manual = 0 a Auto = 0 -> Off, Manual = 0 a Auto = 1 -> Automatic + +door_condition - pin 6, dverový kontakt -> 1 -> vyreportuje Closed, 0 -> vyreportuje Ope +twilight_sensor - hodnotu, ktoru vracia ten analogovy vstup (17) treba poslat sem ako float number. Zrejme tu potom pridame nejaky koeficient prevodu na luxy + +Na kazdu liniu +state_of_breaker - podla indexu istica sa reportuje jeho stav, teda istic na liniu 1: 0-> off, 1-> on +state_of_contactor - podla indexu stkaca sa reportuje jeho stav, teda stykac 1 na liniu 1: 0-> off, 1-> on +*/ + +const { errLogger, logger, monitor } = require('./helper/logger'); +const SerialPort = require('serialport'); +const WebSocket = require('ws'); +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 errorHandler = require('./helper/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 hasMainSwitch; + +let alarmStatus = "OFF"; + +const SEND_TO = { + debug: 0, + tb: 1, + cmd_manager: 2 +} + + +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 = {}; + let rsPortReceivedData = []; + + //to be able to get proper twilight values + let twilight_sensor_interval = 5;//minutes + let twilight_sensor = []; + const twilight_sensor_array = []; + let twilightError = false; + + monitor.info("DIDO_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-we make it global to see it from outside + FLOW.deviceStatus = { //key is device name: temperature,.... + "state_of_main_switch": "Off", //Hlavny istic (alebo druhy dverovy kontakt) + "rotary_switch_state": "Off", //Prevadzkovy + "door_condition": "closed", //Dverový kontakt + "em": "OK", //elektromer rvo + "temperature": "OK", //templomer + "battery": "OK", //Bateria + "power_supply": "OK", //Zdroj + "master_node": "OK", //MN - GLOBALS.settings.masterNodeIsResponding + "no_voltage": "OK", //GLOBALS.settings.no_voltage - vypadok napatia na faze + "state_of_breaker": {}, //"Off",//Istic + "state_of_contactor": {}, //"Off",//Stykac + "twilight_sensor": "OK" //lux sensor + }; + let deviceStatus = FLOW.deviceStatus; + + + function main() { + + GLOBALS = FLOW.GLOBALS; + SETTINGS = FLOW.GLOBALS.settings; + rvoTbName = SETTINGS.rvoTbName; + pinsData = GLOBALS.pinsData; + relaysData = GLOBALS.relaysData; + + tbHandler = new DataToTbHandler(SEND_TO.tb); + tbHandler.setSender(exports.title); + + controller_type = SETTINGS.controller_type; //"lm" or "unipi" + hasMainSwitch = SETTINGS.has_main_switch; + + if (controller_type == "") controller_type = "lm"; + + 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, "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; + } + } + + //report RVO version relaysData[0].tbname; + let values = {}; + values["edge_fw_version"] = SETTINGS.edge_fw_version; + values["maintenance_mode"] = SETTINGS.maintenance_mode; + + sendTelemetry(values, rvoTbName); + + 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); + } + + + function handleRsPort() { + + if (rsPort) { + rsPort.removeAllListeners(); + rsPort = null; + } + + //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('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) { + if (!err) { + monitor.info(exports.title + "--->Digital in_out has been set (runSyncExec was sucessfull)"); + + turnAlarm("off"); + 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('error', err => { + let message = "Dido: rsPort error: " + err.message; + logger.debug(message); + monitor.info(message); + errorHandler.sendMessageToService(message); + }) + + rsPort.on("close", () => { + let message = "Dido: rsPort closed - reconnecting ..."; + logger.debug(message); + monitor.info(message); + setTimeout(handleRsPort, 1000); + }) + + rsPort.open(); + } + + + function handleWebSocket() { + + if (ws) { + ws.removeAllListeners(); + ws = null; + } + + //to keep websocket opened, we send request every 150 seconds + let startRequests = null; + + console.log("handleWebSocket function called"); + ws = new WebSocket('ws:/0.0.0.0:1234/ws'); + + ws.onopen = function open() { + + instance.send(0, exports.title + " running"); + turnAlarm("off"); + + initialSetting(); + + setTimeout(function() { ws.send(JSON.stringify({ cmd: "all" })) }, 5000); + // we request dev info about neuron device from evok to keep websocket connection alive + // for some reason this request returns no data, but connection keeps alive + startRequests = setInterval(() => { + ws.send(JSON.stringify({ "cmd": "filter", "dev": ["neuron"] })); + }, 150000) + }; + + + // 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 = async 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; + + 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 => { + logger.debug('Dido: websocket error', err); + }) + + ws.onclose = function() { + logger.debug('Dido: websocket onclose, reconnecting...') + clearInterval(startRequests); + setTimeout(handleWebSocket, 1000); + } + } + + 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 turnAlarm(onOrOff) { + let value = 0; + if (onOrOff == "on") value = 1; + + if (value == 1 && SETTINGS.maintenance_mode) return; + + alarmStatus = "OFF"; + if (value == 1) alarmStatus = "ON"; + + if (rsPort) { + let arr = [0x55]; + arr.push(13); + arr.push(0); + arr.push(value); + + rsPort.write(Buffer.from(arr), function(err) { + logger.debug(`sirena - ${onOrOff}`); + }); + } + else if (ws) { + let cmd = { "cmd": "set", "dev": "relay", "circuit": "1_01", "value": value }; + ws.send(JSON.stringify(cmd)); + logger.debug(`sirena - ${onOrOff}`); + } + } + + + 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") { + bits.push(0); + } + else bits.push(1); + + if (deviceStatus["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); + } + + + // turn line on or off + function turnLine(onOrOff, line, pin, force, info) { + //onOrOff => "on" or "off" + let value = 0; + if (onOrOff == "on") value = 1; + + if (force == undefined) force = false; + + if (line == 0) { + if (value == 1 && alarmStatus == "ON") turnAlarm("off"); + SETTINGS.maintenance_mode = value ? true : false; + + 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); + return; + } + + if (pin === undefined) pin = getPin(line); + + if (pin === undefined) { + errLogger.error("pin is undefined!", line); + return; + } + + if (!force) { + if (relaysData[line].contactor == value) { + instance.send(SEND_TO.debug, `line is already ${onOrOff} ` + line); + logger.debug(`Dido: turnLine: line is already ${onOrOff} `, line); + return; + } + } + + // if(!rsPort.isOpen && !ws) + if (!rsPort && !ws) { + errLogger.error("Dido - port or websocket is not opened"); + return; + } + + if (rsPort) { + let arr = [0x55]; + arr.push(pin); + arr.push(0); + arr.push(value); + + rsPort.write(Buffer.from(arr), function(err) { + if (err === undefined) { + monitor.info(`Dido: turnLine ${onOrOff} zapisal do rsPort-u`, line, pin, arr, info); + switchLogic(arr); + } + else { + monitor.info(`Dido: turnLine ${onOrOff} WRITE error`, err); + } + }); + + } + else if (ws) { + //pin = "relay1_03" or "input1_01" ... we must make just "1_01" with slice method + monitor.info(`Dido: turnLine ${onOrOff} - (line, pin, force)`, line, pin, force, info); + let cmd = { "cmd": "set", "dev": "relay", "circuit": pin.slice(5), "value": value }; + ws.send(JSON.stringify(cmd)); + } + + //if rvo is 24/7, it has just one switching profile point at 13:00. we do not want to send notification as it repeats every day. + //const d = new Date(); + //if(d.getHours() != 13) sendNotification("Dido_controller: ", SETTINGS.rvoTbName, "switching_profile_point_applied_to_line", { line: line, value: onOrOff }, "", SEND_TO.tb, instance); + } + + + // 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; + + // 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) { + const status = flowdata.data.status; + if (status == "NOK-twilight_sensor") { + deviceStatus["twilight_sensor"] = "NOK"; + } + else if (status == "NOK-em340" || status == "NOK-em111") { + deviceStatus["em"] = "NOK"; + } + else if (status == "NOK-thermometer") { + deviceStatus["temperature"] = "NOK"; + } + } + else if ("values" in flowdata.data) { + 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" + } + else if (values.hasOwnProperty("temperature")) { + deviceStatus["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"; + } + + sendTelemetry(values, rvoTbName); + } + + sendRvoStatus(); + }) + + + + + // we expect array as flowdata.data + instance.on("1", flowdata => { + + //console.log(flowdata.data); + + if (!flowdata.data instanceof Object) return; + + let obj = flowdata.data; + let line = obj.line; + 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"); + }) + + + function calculateStateCode() { + + let bits = []; + + //Hlavny istic - state_of_main_switch => v rvo senica je to druhy door pre silovu cast (EM) + if (deviceStatus["state_of_main_switch"] === "closed" || deviceStatus["state_of_main_switch"] === "Off") { + bits.push(0); + } + else { + bits.push(1); + } + + //Prevadzkovy mod - Manual, Off, Automatic, maintenance_mode = true/false // DAVA 2 BITY + if (!SETTINGS.maintenance_mode) { + if (deviceStatus["rotary_switch_state"] === "Manual") { + bits.push(0); + bits.push(1); + } + + if (deviceStatus["rotary_switch_state"] === "Automatic") { + bits.push(0); + bits.push(0); + } + + if (deviceStatus["rotary_switch_state"] === "Off") { + bits.push(1); + bits.push(0); + } + } + else { + bits.push(1); + bits.push(1); + } + + //Dverovy kontakt + if (deviceStatus["door_condition"] === "closed") { + bits.push(0); + } + else { + bits.push(1); + } + + //EM + if (deviceStatus["em"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //Teplomer + if (deviceStatus["temperature"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //Batéria + if (deviceStatus["battery"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //Zdroj + if (deviceStatus["power_supply"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //MN + if (deviceStatus["master_node"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //výpadok napätia na fáze + if (deviceStatus["no_voltage"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + if (deviceStatus["twilight_sensor"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + // doplnime do 16 bitov (2 byty) + for (let i = bits.length; i < 16; i++) { + bits.push(0); + } + + // console.log("calculateStateCode - deviceStatus", deviceStatus); + // 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; + } + + + async function sendRvoStatus() { + + if (SETTINGS === undefined) return; + SETTINGS.masterNodeIsResponding ? deviceStatus["master_node"] = "OK" : deviceStatus["master_node"] = "NOK"; + + 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 pinsForRvoStatus(controllerType, hasMainSwitch) { + + let pins = []; + + if (controllerType === "lm") { + pins = [1, 4, 6]; + if (hasMainSwitch === 1) { + pins = [4, 6]; + } + } else if (controllerType === "unipi") { + pins = ["input1_01", "input1_04", "input1_05"]; + if (hasMainSwitch === 1) { + pins = ["input1_01", "input1_04"]; + } + } + + return pins; + } + + + function checkRvoStatus() { + + // 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 + //set RVO state + let status = "OK"; + + for (const [key, value] of Object.entries(deviceStatus)) { + if (["em", "twilight_sensor", "temperature", "master_node"].includes(key) && value === "NOK") status = "NOK"; + } + + if (status === "OK") { + + let pinIndexes = pinsForRvoStatus(controller_type, hasMainSwitch); + + for (const pinIndex of pinIndexes) { + if (previousValues[pinIndex] === 0) { + if ((pinIndex === 6 || pinIndex === 'input1_01' || pinIndex === 'input1_05') && SETTINGS.maintenance_mode) continue; + status = "NOK"; + break; + } + } + } + + // battery status. If value is 1 - battery is NOK + if (previousValues[5] === 1) status = "NOK"; + if (SETTINGS.no_voltage.size > 0) status = "NOK"; + + // console.log("rvo status",status) + return status; + } + + + // we pass array to function in case of rsPort ==> switchLogic([55,3,0,1]) ==> [[55,3,0,1]] + // we pass two values in case of websocket ==> switchLogic("relay1_03",1) ==> ["relay1_03",1] + const switchLogic = (...args) => { + + let values = {}; + let pinIndex, newPinValue, twilight; + + //data from rsPort + if (args.length == 1) { + pinIndex = args[0][1] + 1; + if (pinIndex === 17) pinIndex--; + newPinValue = args[0][3]; + twilight = args[0][2]; + } + //data from websocket + else { + pinIndex = args[0]; + newPinValue = args[1]; + } + + 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; + + //default value + let value = "On"; + if (newPinValue === 0) value = "Off"; + + //Hlavny istic + if (type === "state_of_main_switch" && hasMainSwitch) { + if (newPinValue === 0 && newPinValue !== previousValues[pinIndex]) { + sendNotification("switchLogic", rvoTbName, "main_switch_has_been_turned_off", {}, "", SEND_TO.tb, instance, "state_of_main_switch"); + 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"); + deviceStatus["state_of_main_switch"] = "On"; + } + } + + //Prevadzkovy mod + 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"; + + deviceStatus["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, "power_supply_has_disconnected_input", {}, "", SEND_TO.tb, instance, "power_supply"); + + deviceStatus["power_supply"] = "NOK"; + } + else if (newPinValue === 1 && newPinValue !== previousValues[pinIndex]) { + sendNotification("switchLogic", rvoTbName, "power_supply_works_correctly", {}, "", SEND_TO.tb, instance, "power_supply"); + + deviceStatus["power_supply"] = "OK"; + } + } + + //Bateria - 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"); + + deviceStatus["battery"] = "NOK"; + } + else if (newPinValue === 0 && newPinValue !== previousValues[pinIndex]) { + sendNotification("switchLogic", rvoTbName, "battery_level_is_ok", {}, "", SEND_TO.tb, instance, "battery_level"); + + deviceStatus["battery"] = "OK"; + } + } + + //Dverovy kontakt - pin 6 + //! Ak je rvo s dvoma dverovymi kontaktami, ked pride z evoku signal z input1_05, co bol predytm "state_of_main switch" handlujeme ho teraz ako 'door_condition' + else if (type == "door_condition" || type === "state_of_main_switch") { + newPinValue === 0 ? value = "open" : value = "closed"; + + let door = "door_main"; + if (type === "state_of_main_switch") door = "door_em"; + + if (value === "open") { + if (SETTINGS.maintenance_mode) { + sendNotification("switchLogic", rvoTbName, door + "_open", {}, "", SEND_TO.tb, instance, door); + } else { + sendNotification("switchLogic", rvoTbName, door + "_open_without_permission", {}, "", SEND_TO.tb, instance, door); + + // 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 (value === "closed") { + if (alarmStatus == "ON") turnAlarm("off"); + sendNotification("switchLogic", rvoTbName, door + "_close", {}, "", SEND_TO.tb, instance, door); + } + + deviceStatus[type] = value; + } + + //lux sensor + else if (type == "twilight_sensor") { + //! TODO - to show nok status, if lux value is not changing more then 10 times. + //Daylight is far more than 1000. So most of the day, when it is sunshine comes just value 1000. But lux sensor is not NOK. + //This is not the case in LM. If value from LM is the same 10x, there is 99% possibility, that sensor is NOK. + value = newPinValue; + + if (controller_type === 'lm') { + value = parseFloat(newPinValue + (256 * twilight)); + + 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 && !twilightError) { + twilightError = true; + let value = twilight_sensor_array.shift(); + + newPinValue = 0; + } + else if (set.size !== 1 && twilightError) { + //sendNotification("switchLogic", rvoTbName, 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) { + 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); + } + } + + 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); + } + + deviceStatus["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 (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 }); + + //mame iba 3 istice. vyreportujeme a ohandlujeme liniu na tom istom istici ako paralelna linia (napr linia 1, paralelna s nou je linia 4, key je string "4") + // ak je 7 linii, na 1 istici je linia 1,4,7 + + if (line == 1) { + + const lineOnSameBraker = [4, 7]; + + for (var i = 0; i < lineOnSameBraker.length; i++) { + if (!relaysData.hasOwnProperty(lineOnSameBraker[i])) continue; + + 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; + reportLineStatus(lineOnSameBraker[i]); + + values[type] = value; + const tbname = relaysData[lineOnSameBraker[i]].tbname; + sendTelemetry(values, tbname); + + delete values[type]; + } + + } + else { + const lineOnSameBraker = line + 3 + ""; + + if (relaysData.hasOwnProperty(lineOnSameBraker)) { + 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; + reportLineStatus(line + 3); + + values[type] = value; + const tbname = relaysData[lineOnSameBraker].tbname; + sendTelemetry(values, tbname); + + delete values[type]; + } + } + + } + + if (value == "Off") values["status"] = "NOK"; + deviceStatus["state_of_breaker"][line] = value; + + reportLineStatus(line); + } + else return; + + values[type] = value; + + if (type == "rotary_switch_state") { + if (SETTINGS.maintenance_mode) value = "maintenance"; + value = value.toLowerCase(); + values["power_mode"] = value; + } + + if (newPinValue != previousValues[pinIndex]) previousValues[pinIndex] = newPinValue; + if (Object.keys(values).length > 0 && tbname) sendTelemetry(values, tbname); + } + + + function sendTelemetry(values, tbname, date = Date.now()) { + let dataToTb = { + [tbname]: [ + { + "ts": date, + "values": values + } + ] + }; + + tbHandler.sendToTb(dataToTb, instance); + } + + + function isObject(item) { + return (typeof item === "object" && !Array.isArray(item) && item !== null); + } + +} //end of 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 +// *|input1_01|state_of_main_switch|0|........... +// *|input1_02|rotary_switch_state|0|........... +// *|input1_03|rotary_switch_state|0|........... +// *|intut1_04|power_supply|0|........... +// *|input1_05|door_condition|0|........... +// *|input1_06|state_of_breaker|1|........... +// *|input1_07|state_of_breaker|2|........... +// *|input1_08|state_of_breaker|3|........... +// *|relay1_02|state_of_contactor|1|........... +// *|relay1_03|state_of_contactor|2|........... +// *|relay1_04|state_of_contactor|3|........... +// *|287D8776E0013CE9|temperature|0|........... + + +//! pins_data --> from UNIPI +// { +// 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 } +// } + +//! relays_data +// { +// '0': { +// line: 0, +// tbname: 'KjbN4q7JPZmexgdnz2yKQ98YAWwO0Q3BMX6ERLoV', +// contactor: 1, +// profile: '' +// }, +// '1': { +// line: 1, +// tbname: 'RMgnK93rkoAazbqdQ4yBG95Z1YXGx6pmwBeVEP2O', +// contactor: 0, +// profile: '{"intervals":[{"value":0,"end_time":"20:00","start_time":"13:00"},{"value":1,"end_time":"10:00","start_time":"20:00"},{"value":0,"end_time":"10:20","start_time":"10:00"},{"value":1,"end_time":"10:40","start_time":"10:20"},{"value":0,"end_time":"11:00","start_time":"10:40"},{"value":1,"end_time":"11:30","start_time":"11:00"},{"value":0,"end_time":"11:50","start_time":"11:30"},{"value":1,"end_time":"13:00","start_time":"11:50"}],"astro_clock":false,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' +// }, +// '2': { +// line: 2, +// tbname: 'dlE1VQjYrNx9gZRmb38gG08oLBO4qaAk2M6JPnG7', +// contactor: 0, +// profile: '{"intervals":[{"value":0,"end_time":"20:00","start_time":"13:00"},{"value":1,"end_time":"10:00","start_time":"20:00"},{"value":0,"end_time":"10:20","start_time":"10:00"},{"value":1,"end_time":"10:40","start_time":"10:20"},{"value":0,"end_time":"11:00","start_time":"10:40"},{"value":1,"end_time":"11:30","start_time":"11:00"},{"value":0,"end_time":"11:50","start_time":"11:30"},{"value":1,"end_time":"13:00","start_time":"11:50"}],"astro_clock":false,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' +// }, +// '3': { +// line: 3, +// tbname: 'vnmG4kJxaXWNBgMQq0D7Aj5e9oZzOAlr6LdR3w2V', +// contactor: 0, +// profile: '{"intervals":[{"value":0,"end_time":"20:30","start_time":"13:00"},{"value":1,"end_time":"00:10","start_time":"20:30"},{"value":0,"end_time":"13:00","start_time":"05:40"},{"value":1,"end_time":"05:40","start_time":"00:10"}],"astro_clock":true,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' +// } +// } + + + + + +// { +// "jbN4q7JPZmexgdnz2yKbWGDYAWwO0Q3BMX6ERLoV": [ +// { +// "ts": 1700409326353, +// "values": { +// "_event": { +// "type": "notice", +// "status": "new", +// "source": { +// "func": "rsPort.open()", +// "component": "1700343402190", +// "component_name": "DIDO_Controller", +// "edge": "jbN4q7JPZmexgdnz2yKbWGDYAWwO0Q3BMX6ERLoV" +// }, +// "message": "al_shariff_10.0.0.38: FLOW has been started ", +// "message_data": "" +// } +// } +// } +// ] +// } diff --git a/RVO36/flow/helper/DataToTbHandler.js b/RVO36/flow/helper/DataToTbHandler.js new file mode 100755 index 0000000..716ef7b --- /dev/null +++ b/RVO36/flow/helper/DataToTbHandler.js @@ -0,0 +1,187 @@ +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; + this.itIsNodeReadout = false; + this.sender = ""; + + // if attribute change difference is less than limit value, we do not send to tb. + this.attributeChangeLimit = { + temperature: 0.5, + Phase_1_voltage: 2, + Phase_2_voltage: 2, + Phase_3_voltage: 2, + Phase_1_current: 0.1, + Phase_2_current: 0.1, + Phase_3_current: 0.1, + Phase_1_power: 2, + Phase_2_power: 2, + Phase_3_power: 2, + total_power: 2, + total_energy: 1, + Phase_1_pow_factor: 0.1, + Phase_2_pow_factor: 0.1, + Phase_3_pow_factor: 0.1, + power_factor: 0.1, + lifetime: 2, + voltage: 2, + power: 2, + frequency: 3, + energy: 0.1, + current: 2, + inclination_x: 10, + inclination_y: 10, + inclination_z: 10 + }; + + } + + dump() { + console.log("----------------------------"); + console.log("previousValues", this.previousValues); + console.log("----------------------------"); + } + + setSender(sender) { + this.sender = sender; + } + + isEmptyObject(obj) { + for (var _ in obj) { + return false; + } + return true; + } + + + sendToTb(data, instance) { + + //not to modify data object, we do deep copy: + let dataCopy = JSON.parse(JSON.stringify(data)); + + let keys = Object.keys(dataCopy); + + if (keys.length == 0) { + if (this.debug) console.log("sendToTb received empty object", dataCopy); + return; + } + + let tbname = keys[0]; + let ts; + + let arrayOfValues = dataCopy[tbname]; + let arrayOfValuesToSend = []; + + for (let i = 0; i < arrayOfValues.length; i++) { + + ts = arrayOfValues[i].ts; + let values = this.prepareValuesForTb(tbname, ts, arrayOfValues[i].values); + + if (!this.isEmptyObject(values)) { + arrayOfValuesToSend.push({ ts: ts, values: values }); + } + + } + + if (arrayOfValuesToSend.length == 0) { + //if(this.debug) console.log("data not sent - empty array"); + return; + } + + this.messageCounter++; + + let dataToTbModified = { + [tbname]: arrayOfValuesToSend + } + + //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); + instance.send(this.index, dataToTbModified); + } + + + getDiffTimestamp(key) { + //TODO set different value for given key!!! + //if(key == "status") this.timeToHoldTbValue = 2*60*60;//2h + return this.timeToHoldTbValue * 1000; + } + + + prepareValuesForTb(tbname, timestamp, values) { + + let keys = Object.keys(values); + + if (keys.includes("lifetime")) this.itIsNodeReadout = true; + + if (!this.previousValues.hasOwnProperty(tbname)) { + this.previousValues[tbname] = {}; + } + + //if(this.debug) console.log("prepareValuesForTb", tbname, timestamp, values); + + for (let i = 0; i < keys.length; i++) { + + let key = keys[i]; + let value = values[key]; + + if (!this.previousValues[tbname].hasOwnProperty(key)) { + this.previousValues[tbname][key] = { ts: timestamp, value: value }; + continue; + } + + // attributeData ==> {voltage: {ts:333333, value:5}} + let attributeData = this.previousValues[tbname][key]; + let attributeToChange = false; + if (key in this.attributeChangeLimit) attributeToChange = true; + let limit = this.attributeChangeLimit[key]; + let timestampDiffToRemoveKey; + + //this will ensure "node statecode" will be sent just once an hour + if (this.itIsNodeReadout && key === "statecode") { + attributeData.value = value; + this.itIsNodeReadout = false; + timestampDiffToRemoveKey = 1 * 60 * 60 * 1000; // 1 hour + } + + if (key === "twilight_sensor" && value > 100) { + attributeData.value = value; + } + + //if edge, master or node version do not change, send just once a day: + if (["edge_fw_version", "master_node_version", "fw_version"].includes(key)) { + timestampDiffToRemoveKey = 24 * 60 * 60 * 1000; + } + + if (attributeData.value === value || attributeToChange && Math.abs(attributeData.value - value) < limit) { + + let diff = timestamp - attributeData.ts; + if (!timestampDiffToRemoveKey) timestampDiffToRemoveKey = this.getDiffTimestamp(key); + + if (diff > timestampDiffToRemoveKey) { + attributeData.ts = Date.now(); + //if(this.debug) console.log(this.sender + ": update ts for key", key, "diff is", diff, "messageCounter", this.messageCounter); + } + else { + delete values[key]; + //if(this.debug) console.log(this.sender + ": delete key", key, "diff is", diff, "messageCounter", this.messageCounter, timestampDiffToRemoveKey); + } + } + else { + attributeData.value = value; + attributeData.ts = timestamp; + } + + } + + return values; + } +} + +module.exports = DataToTbHandler; + diff --git a/RVO36/flow/helper/ErrorToServiceHandler.js b/RVO36/flow/helper/ErrorToServiceHandler.js new file mode 100755 index 0000000..2b27c32 --- /dev/null +++ b/RVO36/flow/helper/ErrorToServiceHandler.js @@ -0,0 +1,91 @@ +const { MD5 } = require('./md5.js'); +const { networkInterfaces } = require('os'); + +class ErrorToServiceHandler { + constructor() { + this.previousValues = {}; + + this.project_id = undefined; + + const nets = networkInterfaces(); + this.ipAddresses = {}; + + for (const name of Object.keys(nets)) { + for (const net of nets[name]) { + // Skip over non-IPv4 and internal (i.e. 127.0.0.1) addresses + if (net.family === 'IPv4' && !net.internal) { + if (!this.ipAddresses[name]) { + this.ipAddresses[name] = []; + } + this.ipAddresses[name].push(net.address); + } + } + } + } + + setProjectId(project_id) { + this.project_id = project_id; + } + + processMessage(message, seconds) { + if (Array.isArray(message)) message = message.join(', '); + + let key = MD5(message); + let ts = Date.now(); + + //keep in memory - default value is 1h + if (seconds === undefined) seconds = 60 * 60; + + if (!this.previousValues.hasOwnProperty(key)) { + this.previousValues[key] = { ts: ts, duration: seconds }; + } + + let diff = (ts - this.previousValues[key].ts); + if (diff < this.previousValues[key].duration * 1000) return false; + + this.previousValues[key].ts = ts; + + return message; + } + + sendMessageToService(message, seconds, message_type) { + + // if error occures too early FLOW.GLOBALS.settings.project_id is still undefined + if (this.project_id === undefined) { + console.log("ErrorToServiceHandler.js: no project_id"); + return; + } + + let f = this.processMessage(message, seconds); + if (f === false) return; + + if (message_type === undefined) message_type = "error_message"; + + let toService = { + id: this.project_id, + ipAddresses: this.ipAddresses + }; + + //js_error || error_message + toService[message_type] = message; + + console.log("ErrorToServiceHandler------------------------>send to service", toService); + + RESTBuilder.make(function(builder) { + builder.method('POST'); + builder.post(toService); + builder.url('http://192.168.252.2:8004/sentmessage'); + + builder.callback(function(err, response, output) { + console.log("process.on error send", err, response, output, toService); + }); + }); + + } +} + +const errorHandler = new ErrorToServiceHandler(); + + +module.exports = errorHandler; +//module.exports = ErrorToServiceHandler; diff --git a/RVO36/flow/helper/db_helper.js b/RVO36/flow/helper/db_helper.js new file mode 100755 index 0000000..40e796c --- /dev/null +++ b/RVO36/flow/helper/db_helper.js @@ -0,0 +1,44 @@ +function promisifyBuilder(builder) +{ + return new Promise((resolve, reject) => { + + try{ + + builder.callback(function(err, response) { + + if(err != null) reject(err); + resolve(response); + }); + + } catch (error) { + reject(error); + } + }) +} + +function makeMapFromDbResult(response, ...keys) +{ + let s = "-"; + let data = {}; + + for(let i = 0; i < response.length; i++) + { + let record = response[i]; + + let k = []; + for(let j = 0; j < keys.length; j++) + { + k.push( record[keys[j]] ); + } + + let key = k.join(s); + data[ key ] = record; + } + + return data; +} + +module.exports = { + promisifyBuilder, + makeMapFromDbResult + } \ No newline at end of file diff --git a/RVO36/flow/helper/logger.js b/RVO36/flow/helper/logger.js new file mode 100755 index 0000000..2585639 --- /dev/null +++ b/RVO36/flow/helper/logger.js @@ -0,0 +1,30 @@ +//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/RVO36/flow/helper/md5.js b/RVO36/flow/helper/md5.js new file mode 100755 index 0000000..d3b0480 --- /dev/null +++ b/RVO36/flow/helper/md5.js @@ -0,0 +1,5 @@ +function MD5(d){var r = M(V(Y(X(d),8*d.length)));return r.toLowerCase()};function M(d){for(var _,m="0123456789ABCDEF",f="",r=0;r>>4&15)+m.charAt(15&_);return f}function X(d){for(var _=Array(d.length>>2),m=0;m<_.length;m++)_[m]=0;for(m=0;m<8*d.length;m+=8)_[m>>5]|=(255&d.charCodeAt(m/8))<>5]>>>m%32&255);return _}function Y(d,_){d[_>>5]|=128<<_%32,d[14+(_+64>>>9<<4)]=_;for(var m=1732584193,f=-271733879,r=-1732584194,i=271733878,n=0;n>16)+(_>>16)+(m>>16)<<16|65535&m}function bit_rol(d,_){return d<<_|d>>>32-_} + +module.exports = { + MD5 +} \ No newline at end of file diff --git a/RVO36/flow/helper/notification_reporter.js b/RVO36/flow/helper/notification_reporter.js new file mode 100755 index 0000000..839c12c --- /dev/null +++ b/RVO36/flow/helper/notification_reporter.js @@ -0,0 +1,121 @@ +//key is device, value = message {} +let sentValues = {}; +let notificationsData = null; +let rvoName; + +//sendNotification("CMD Manager: process cmd", SETTINGS.rvoTbName, "dimming_profile_was_successfully_received_by_node", { node: node }, "", SEND_TO.tb, instance); + +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 +}; + +function getKey(map, val) { + return Object.keys(map).findItem(key => map[key] === val); +} + +//https://stackoverflow.com/questions/41117799/string-interpolation-on-variable +var template = (tpl, args) => tpl.replace(/\${(\w+)}/g, (_, v) => args[v]); + + +function initNotification() { + notificationsData = FLOW.GLOBALS.notificationsData; + rvoName = FLOW.GLOBALS.settings.rvo_name; +} + + +function sendNotification(func, device, key, params, extra, tb_output, instance, saveKey) { + + let storeToSendValues = true; + if (saveKey == undefined) storeToSendValues = false; + + let weight = ""; + let message = {}; + + let notification = notificationsData[key]; + + if (notification) { + weight = notification.weight.toLowerCase(); + + Object.keys(notification).forEach(item => { + if (["en", "sk", "de", "cz", "it", "es"].includes(item)) { + message[item] = rvoName + ": " + template(notification[item], params); + } + }) + } + else { + //console.error("sendNotification: Notifications: undefined key", key, func, notificationsData); + console.error("sendNotification: Notifications: undefined key", key, func); + return false; + } + + //detect invalid err weight + if (getKey(ERRWEIGHT, weight) == undefined) { + console.error("sendNotification: Notifications: undefined weight", weight, key, func); + return false; + } + + if (sentValues.hasOwnProperty(saveKey)) { + if (JSON.stringify(sentValues[saveKey]) == JSON.stringify(message)) { + return false; + } + } + + if (sentValues[saveKey] == undefined) { + if (storeToSendValues) { + //do not send - flow is was started + sentValues[saveKey] = message; + return false; + } + } + + if (storeToSendValues) sentValues[saveKey] = message; + + let content = { + "type": weight, + "status": "new", + "source": { + "func": func, + "component": instance.id, + "component_name": instance.name, + "edge": device + }, + "message": message, + "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 + + return true; + +} + +module.exports = { + sendNotification, + ERRWEIGHT, + initNotification +} + diff --git a/RVO36/flow/helper/register.js b/RVO36/flow/helper/register.js new file mode 100755 index 0000000..fc1d008 --- /dev/null +++ b/RVO36/flow/helper/register.js @@ -0,0 +1,144 @@ +/* +0 - cislo registra / prikaz +1 - recepient - 0 = master, 1 = slave (slave je automaticky group a broadcast) +2 - r/rw - read/write +3- register name - nazov registra / prikazu (len pre info - zobrazenie v aplikacii) + +4,5,6,7, - jednotlive byte-y - nazov byte-u +4-7 - RES. a prazdny string "" sa nezobrazia!!! +*/ + +//124 zaznamov +const registers = [ + ["0","1","R","Status","","",""], + ["1","1","RW","Dimming","R-Channel ","G-Channel","B-Channel ","W - Channel"], + ["2","1","R","Device types","","",".",""], + ["3","1","RW","Group addresses 1-4","Groups Add. 4","Groups Add. 3","Groups Add. 2","Groups Add. 1"], + ["4","1","RW","Group addresses 5-8","Groups Add. 8","Groups Add. 7","Groups Add. 6","Groups Add. 5"], + ["5","1","RW","Serial number (MAC)","","","",""], + ["6","1","RW","Time of dusk","HH","MM","SS","EXTRA"], + ["7","1","RW","Time of dawn","HH","MM","SS","EXTRA"], + ["8","1","RW","Time Schedule settings","TBD","TBD","Movement sensor","Time Schedule"], + ["9","1","RW","TS1 Time point 1","HH","MM","SS","Ext. Device"], + ["10","1","RW","TS1 Time point 1 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["11","1","RW","TS1 Time point 2","HH","MM","SS","Ext. Device"], + ["12","1","RW","TS1 Time point 2 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["13","1","RW","TS1 Time point 3","HH","MM","SS","Ext. Device"], + ["14","1","RW","TS1 Time point 3 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["15","1","RW","TS1 Time point 4","HH","MM","SS","Ext. Device"], + ["16","1","RW","TS1 Time point 4 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["17","1","RW","TS1 Time point 5","HH","MM","SS","Ext. Device"], + ["18","1","RW","TS1 Time point 5 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["19","1","RW","TS1 Time point 6","HH","MM","SS","Ext. Device"], + ["20","1","RW","TS1 Time point 6 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["21","1","RW","TS1 Time point 7","HH","MM","SS","Ext. Device"], + ["22","1","RW","TS1 Time point 7 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["23","1","RW","TS1 Time point 8","HH","MM","SS","Ext. Device"], + ["24","1","RW","TS1 Time point 8 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["25","1","RW","TS1 Time point 9","HH","MM","SS","Ext. Device"], + ["26","1","RW","TS1 Time point 9 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["27","1","RW","TS1 Time point 10","HH","MM","SS","Ext. Device"], + ["28","1","RW","TS1 Time point 10 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["29","1","RW","TS1 Time point 11","HH","MM","SS","Ext. Device"], + ["30","1","RW","TS1 Time point 11 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["31","1","RW","TS1 Time point 12","HH","MM","SS","Ext. Device"], + ["32","1","RW","TS1 Time point 12 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["33","1","RW","TS1 Time point 13","HH","MM","SS","Ext. Device"], + ["34","1","RW","TS1 Time point 13 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["35","1","RW","TS1 Time point 14","HH","MM","SS","Ext. Device"], + ["36","1","RW","TS1 Time point 14 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["37","1","RW","TS1 Time point 15","HH","MM","SS","Ext. Device"], + ["38","1","RW","TS1 Time point 15 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["39","1","RW","TS1 Time point 16","HH","MM","SS","Ext. Device"], + ["40","1","RW","TS1 Time point 16 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["41","1","RW","TS2 Time point 1","HH","MM","SS","Ext. Device"], + ["42","1","RW","TS2 Time point 1 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["43","1","RW","TS2 Time point 2","HH","MM","SS","Ext. Device"], + ["44","1","RW","TS2 Time point 2 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["45","1","RW","TS2 Time point 3","HH","MM","SS","Ext. Device"], + ["46","1","RW","TS2 Time point 3 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["47","1","RW","TS2 Time point 4","HH","MM","SS","Ext. Device"], + ["48","1","RW","TS2 Time point 4 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["49","1","RW","TS2 Time point 5","HH","MM","SS","Ext. Device"], + ["50","1","RW","TS2 Time point 5 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["51","1","RW","TS2 Time point 6","HH","MM","SS","Ext. Device"], + ["52","1","RW","TS2 Time point 6 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["53","1","RW","TS2 Time point 7","HH","MM","SS","Ext. Device"], + ["54","1","RW","TS2 Time point 7 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["55","1","RW","TS2 Time point 8","HH","MM","SS","Ext. Device"], + ["56","1","RW","TS2 Time point 8 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["57","1","RW","TS2 Time point 9","HH","MM","SS","Ext. Device"], + ["58","1","RW","TS2 Time point 9 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["59","1","RW","TS2 Time point 10","HH","MM","SS","Ext. Device"], + ["60","1","RW","TS2 Time point 10 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["61","1","RW","TS2 Time point 11","HH","MM","SS","Ext. Device"], + ["62","1","RW","TS2 Time point 11 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["63","1","RW","TS2 Time point 12","HH","MM","SS","Ext. Device"], + ["64","1","RW","TS2 Time point 12 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["65","1","RW","TS2 Time point 13","HH","MM","SS","Ext. Device"], + ["66","1","RW","TS2 Time point 13 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["67","1","RW","TS2 Time point 14","HH","MM","SS","Ext. Device"], + ["68","1","RW","TS2 Time point 14 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["69","1","RW","TS2 Time point 15","HH","MM","SS","Ext. Device"], + ["70","1","RW","TS2 Time point 15 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["71","1","RW","TS2 Time point 16","HH","MM","SS","Ext. Device"], + ["72","1","RW","TS2 Time point 16 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["73","1","RW","Power meter status","TBD","","",""], + ["74","1","R","Input Voltage","","","",""], + ["75","1","R","Input Current","","","",""], + ["76","1","R","Input Power","","","",""], + ["77","1","R","Cos phi","","","",""], + ["78","1","R","Frequency","","","",""], + ["79","1","RW","Energy","","","",""], + ["80","1","RW","Lifetime","","","",""], + ["81","1","RW","Power on cycles (input)","","","",""], + ["82","1","RW","Power on cycles (relay)","","","",""], + ["83","1","R","Time since last power on","","","",""], + ["84","1","R","Accelerometer data","","","",""], + ["85","1","RW","GPS latitude","pos/neg","deg","min ","sec"], + ["86","1","RW","GPS longitude","pos/neg","deg","min ","sec"], + ["87","1","RW","Actual time","HH","MM","SS","RES."], + ["88","1","RW","Actual date","Day of week","Day","Month","Year"], + ["89","1","R","Production data 1","","","",""], + ["90","1","R","Production data 2","","","",""], + ["91","1","RW","Network ID","NID3","NID2","NID1","NID0"], + ["95","1","RW","Actual Lux level from cabinet","RES.","RES.","HB","LB"], + ["96","1","RW","Threshold lux level","Dusk HB","Dusk LB","Dawn HB","Dawn LB"], + ["97","1","RW","Adjust period","Dusk HB","Dusk LB","Dawn HB","Dawn LB"], + ["98","1","RW","Offset","RES.","RES.","Dusk","Dawn"], + ["99","1","RW","CCT min/max range","max-H","max-L","min-H","min-L"], + ["100","1","RW","DALI interface","Cmd ID","Add","Cmd","Resp"], + ["101","1","RW","Module FW ver","v1","v2","v3","v4"], + ["102","1","RW","Module MAC-H","unused","unused","M1","M2"], + ["103","1","RW","Module MAC-L","M3","M4","M5","M6"], + ["122","1","R","FW update status/control register","Byte3","Byte2","Byte1","Byte0"], + ["123","1","R","FW update - data index","Byte3","Byte2","Byte1","Byte0"], + ["124","1","R","FW update - data","Byte3","Byte2","Byte1","Byte0"], + ["0","0","R","Status","","","",""], + ["1","0","RW","Control register","RES.","RES.","RES.","init mode enable"], + ["2","0","R","Device types","","","",""], + ["3","0","R","Serial number (MAC)","","","",""], + ["4","0","R","Production data 1","","","",""], + ["5","0","R","Production data 2","","","",""], + ["6","0","RW","Network ID","NID3","NID2","NID1","NID0"], + ["7","0","RW","RS232 settings","param.","param.","Baudrate H","Baudrate L"], + ["8","0","R","Accelerometer data","","","",""], + ["9","0","RW","Module FW ver","v1","v2","v3","v4"], + ["10","0","RW","Module MAC-H","unused","unused","M1","M2"], + ["11","0","RW","Module MAC-L","M3","M4","M5","M6"], + ["32","0","RW","FW update status/control register","Byte3","Byte2","Byte1","Byte0"], + ["33","0","RW","FW update - data index","Byte3","Byte2","Byte1","Byte0"], + ["34","0","RW","FW update - data","Byte3","Byte2","Byte1","Byte0"], + ["125","0","RW","Debug Register","Byte3","Byte2","Byte1","Byte0"], + ["126","0","RW","Network Control Register","Byte3","Byte2","Byte1","Byte0"], + ["127","0","R","Network Status Register","Byte3","Byte2","Byte1","Byte0"], + ["128","0","RW","Node XX Serial Number Register","SER3","SER2","SER1","SER0"], + ["256","0","R","Node XX Network Status Register","","","",""] +]; + +let register = {}; + +module.exports = { + registers, + register +} \ No newline at end of file diff --git a/RVO36/flow/helper/serialport_helper.js b/RVO36/flow/helper/serialport_helper.js new file mode 100755 index 0000000..7f5920d --- /dev/null +++ b/RVO36/flow/helper/serialport_helper.js @@ -0,0 +1,99 @@ +const { exec } = require('child_process'); + +function openPort(port) { + return new Promise((resolve, reject) => { + + var callbackError = function(err) { + port.removeListener('error', callbackError); + port.removeListener('open', callbackError); + + reject(err.message); + }; + + var callbackOpen = function(data) { + port.removeListener('error', callbackError); + port.removeListener('open', callbackOpen); + + resolve("port open: ok"); + }; + + port.on('error', callbackError); + port.on('open', callbackOpen); + + port.open(); + + }) +} + +function runSyncExec(command) { + return new Promise((resolve, reject) => { + + exec(command, (error, stdout, stderr) => { + if (error == null) resolve(stdout); + reject(error); + }); + + }) +} + +async function writeData(port, data, readbytes, timeout) { + return new Promise((resolve, reject) => { + + // 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) { + + port.write(Buffer.from(data), function(err) { + if (err) { + reject(err.message); + } + }); + + 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 +} diff --git a/RVO36/flow/helper/suncalc.js b/RVO36/flow/helper/suncalc.js new file mode 100755 index 0000000..c9ca56d --- /dev/null +++ b/RVO36/flow/helper/suncalc.js @@ -0,0 +1,317 @@ +/* + (c) 2011-2015, Vladimir Agafonkin + SunCalc is a JavaScript library for calculating sun/moon position and light phases. + https://github.com/mourner/suncalc +*/ + +(function () { 'use strict'; + +// shortcuts for easier to read formulas + +var PI = Math.PI, + sin = Math.sin, + cos = Math.cos, + tan = Math.tan, + asin = Math.asin, + atan = Math.atan2, + acos = Math.acos, + rad = PI / 180; + +// sun calculations are based on http://aa.quae.nl/en/reken/zonpositie.html formulas + + +// date/time constants and conversions + +var dayMs = 1000 * 60 * 60 * 24, + J1970 = 2440588, + J2000 = 2451545; + +function toJulian(date) { return date.valueOf() / dayMs - 0.5 + J1970; } +function fromJulian(j) { return new Date((j + 0.5 - J1970) * dayMs); } +function toDays(date) { return toJulian(date) - J2000; } + + +// general calculations for position + +var e = rad * 23.4397; // obliquity of the Earth + +function rightAscension(l, b) { return atan(sin(l) * cos(e) - tan(b) * sin(e), cos(l)); } +function declination(l, b) { return asin(sin(b) * cos(e) + cos(b) * sin(e) * sin(l)); } + +function azimuth(H, phi, dec) { return atan(sin(H), cos(H) * sin(phi) - tan(dec) * cos(phi)); } +function altitude(H, phi, dec) { return asin(sin(phi) * sin(dec) + cos(phi) * cos(dec) * cos(H)); } + +function siderealTime(d, lw) { return rad * (280.16 + 360.9856235 * d) - lw; } + +function astroRefraction(h) { + if (h < 0) // the following formula works for positive altitudes only. + h = 0; // if h = -0.08901179 a div/0 would occur. + + // formula 16.4 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + // 1.02 / tan(h + 10.26 / (h + 5.10)) h in degrees, result in arc minutes -> converted to rad: + return 0.0002967 / Math.tan(h + 0.00312536 / (h + 0.08901179)); +} + +// general sun calculations + +function solarMeanAnomaly(d) { return rad * (357.5291 + 0.98560028 * d); } + +function eclipticLongitude(M) { + + var C = rad * (1.9148 * sin(M) + 0.02 * sin(2 * M) + 0.0003 * sin(3 * M)), // equation of center + P = rad * 102.9372; // perihelion of the Earth + + return M + C + P + PI; +} + +function sunCoords(d) { + + var M = solarMeanAnomaly(d), + L = eclipticLongitude(M); + + return { + dec: declination(L, 0), + ra: rightAscension(L, 0) + }; +} + + +var SunCalc = {}; + + +// calculates sun position for a given date and latitude/longitude + +SunCalc.getPosition = function (date, lat, lng) { + + var lw = rad * -lng, + phi = rad * lat, + d = toDays(date), + + c = sunCoords(d), + H = siderealTime(d, lw) - c.ra; + + return { + azimuth: azimuth(H, phi, c.dec), + altitude: altitude(H, phi, c.dec) + }; +}; + + +// sun times configuration (angle, morning name, evening name) + +var times = SunCalc.times = [ + [-0.833, 'sunrise', 'sunset' ], + [ -0.3, 'sunriseEnd', 'sunsetStart' ], + [ -6, 'dawn', 'dusk' ], + [ -12, 'nauticalDawn', 'nauticalDusk'], + [ -18, 'nightEnd', 'night' ], + [ 6, 'goldenHourEnd', 'goldenHour' ] +]; + +// adds a custom time to the times config + +SunCalc.addTime = function (angle, riseName, setName) { + times.push([angle, riseName, setName]); +}; + + +// calculations for sun times + +var J0 = 0.0009; + +function julianCycle(d, lw) { return Math.round(d - J0 - lw / (2 * PI)); } + +function approxTransit(Ht, lw, n) { return J0 + (Ht + lw) / (2 * PI) + n; } +function solarTransitJ(ds, M, L) { return J2000 + ds + 0.0053 * sin(M) - 0.0069 * sin(2 * L); } + +function hourAngle(h, phi, d) { return acos((sin(h) - sin(phi) * sin(d)) / (cos(phi) * cos(d))); } +function observerAngle(height) { return -2.076 * Math.sqrt(height) / 60; } + +// returns set time for the given sun altitude +function getSetJ(h, lw, phi, dec, n, M, L) { + + var w = hourAngle(h, phi, dec), + a = approxTransit(w, lw, n); + return solarTransitJ(a, M, L); +} + + +// calculates sun times for a given date, latitude/longitude, and, optionally, +// the observer height (in meters) relative to the horizon + +SunCalc.getTimes = function (date, lat, lng, height) { + + height = height || 0; + + var lw = rad * -lng, + phi = rad * lat, + + dh = observerAngle(height), + + d = toDays(date), + n = julianCycle(d, lw), + ds = approxTransit(0, lw, n), + + M = solarMeanAnomaly(ds), + L = eclipticLongitude(M), + dec = declination(L, 0), + + Jnoon = solarTransitJ(ds, M, L), + + i, len, time, h0, Jset, Jrise; + + + var result = { + solarNoon: fromJulian(Jnoon), + nadir: fromJulian(Jnoon - 0.5) + }; + + for (i = 0, len = times.length; i < len; i += 1) { + time = times[i]; + h0 = (time[0] + dh) * rad; + + Jset = getSetJ(h0, lw, phi, dec, n, M, L); + Jrise = Jnoon - (Jset - Jnoon); + + result[time[1]] = fromJulian(Jrise); + result[time[2]] = fromJulian(Jset); + } + + return result; +}; + + +// moon calculations, based on http://aa.quae.nl/en/reken/hemelpositie.html formulas + +function moonCoords(d) { // geocentric ecliptic coordinates of the moon + + var L = rad * (218.316 + 13.176396 * d), // ecliptic longitude + M = rad * (134.963 + 13.064993 * d), // mean anomaly + F = rad * (93.272 + 13.229350 * d), // mean distance + + l = L + rad * 6.289 * sin(M), // longitude + b = rad * 5.128 * sin(F), // latitude + dt = 385001 - 20905 * cos(M); // distance to the moon in km + + return { + ra: rightAscension(l, b), + dec: declination(l, b), + dist: dt + }; +} + +SunCalc.getMoonPosition = function (date, lat, lng) { + + var lw = rad * -lng, + phi = rad * lat, + d = toDays(date), + + c = moonCoords(d), + H = siderealTime(d, lw) - c.ra, + h = altitude(H, phi, c.dec), + // formula 14.1 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + pa = atan(sin(H), tan(phi) * cos(c.dec) - sin(c.dec) * cos(H)); + + h = h + astroRefraction(h); // altitude correction for refraction + + return { + azimuth: azimuth(H, phi, c.dec), + altitude: h, + distance: c.dist, + parallacticAngle: pa + }; +}; + + +// calculations for illumination parameters of the moon, +// based on http://idlastro.gsfc.nasa.gov/ftp/pro/astro/mphase.pro formulas and +// Chapter 48 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + +SunCalc.getMoonIllumination = function (date) { + + var d = toDays(date || new Date()), + s = sunCoords(d), + m = moonCoords(d), + + sdist = 149598000, // distance from Earth to Sun in km + + phi = acos(sin(s.dec) * sin(m.dec) + cos(s.dec) * cos(m.dec) * cos(s.ra - m.ra)), + inc = atan(sdist * sin(phi), m.dist - sdist * cos(phi)), + angle = atan(cos(s.dec) * sin(s.ra - m.ra), sin(s.dec) * cos(m.dec) - + cos(s.dec) * sin(m.dec) * cos(s.ra - m.ra)); + + return { + fraction: (1 + cos(inc)) / 2, + phase: 0.5 + 0.5 * inc * (angle < 0 ? -1 : 1) / Math.PI, + angle: angle + }; +}; + + +function hoursLater(date, h) { + return new Date(date.valueOf() + h * dayMs / 24); +} + +// calculations for moon rise/set times are based on http://www.stargazing.net/kepler/moonrise.html article + +SunCalc.getMoonTimes = function (date, lat, lng, inUTC) { + var t = new Date(date); + if (inUTC) t.setUTCHours(0, 0, 0, 0); + else t.setHours(0, 0, 0, 0); + + var hc = 0.133 * rad, + h0 = SunCalc.getMoonPosition(t, lat, lng).altitude - hc, + h1, h2, rise, set, a, b, xe, ye, d, roots, x1, x2, dx; + + // go in 2-hour chunks, each time seeing if a 3-point quadratic curve crosses zero (which means rise or set) + for (var i = 1; i <= 24; i += 2) { + h1 = SunCalc.getMoonPosition(hoursLater(t, i), lat, lng).altitude - hc; + h2 = SunCalc.getMoonPosition(hoursLater(t, i + 1), lat, lng).altitude - hc; + + a = (h0 + h2) / 2 - h1; + b = (h2 - h0) / 2; + xe = -b / (2 * a); + ye = (a * xe + b) * xe + h1; + d = b * b - 4 * a * h1; + roots = 0; + + if (d >= 0) { + dx = Math.sqrt(d) / (Math.abs(a) * 2); + x1 = xe - dx; + x2 = xe + dx; + if (Math.abs(x1) <= 1) roots++; + if (Math.abs(x2) <= 1) roots++; + if (x1 < -1) x1 = x2; + } + + if (roots === 1) { + if (h0 < 0) rise = i + x1; + else set = i + x1; + + } else if (roots === 2) { + rise = i + (ye < 0 ? x2 : x1); + set = i + (ye < 0 ? x1 : x2); + } + + if (rise && set) break; + + h0 = h2; + } + + var result = {}; + + if (rise) result.rise = hoursLater(t, rise); + if (set) result.set = hoursLater(t, set); + + if (!rise && !set) result[ye > 0 ? 'alwaysUp' : 'alwaysDown'] = true; + + return result; +}; + + +// export as Node module / AMD module / browser variable +if (typeof exports === 'object' && typeof module !== 'undefined') module.exports = SunCalc; +else if (typeof define === 'function' && define.amd) define(SunCalc); +else window.SunCalc = SunCalc; + +}()); diff --git a/RVO36/flow/helper/utils.js b/RVO36/flow/helper/utils.js new file mode 100755 index 0000000..dbffe45 --- /dev/null +++ b/RVO36/flow/helper/utils.js @@ -0,0 +1,161 @@ +const fs = require('fs').promises; + +function bytesToInt(bytes, numberOfBytes) { + let buffer = []; + if (Array.isArray(bytes)) { + buffer = bytes.slice(0); + if (numberOfBytes != undefined) { + buffer = bytes.slice(bytes.length - numberOfBytes); + } + } + else buffer.push(bytes); + + let result = 0; + for (let i = 0; i < buffer.length; i++) { + result = (result << 8) | buffer[i]; + } + + return result >>> 0; //ensure it's an unsigned 32-bit number +} + +function resizeArray(arr, newSize, defaultValue) { + while (newSize > arr.length) + arr.push(defaultValue); + arr.length = newSize; +} + +longToByteArray = function(/*long*/long) { + // we want to represent the input as a 8-bytes array + var byteArray = [0, 0, 0, 0, 0, 0, 0, 0]; + + for (var index = 0; index < byteArray.length; index++) { + var byte = long & 0xff; + byteArray[index] = byte; + long = (long - byte) / 256; + } + + return byteArray; +}; + +function addDays(date, days) { + var result = new Date(date); + result.setDate(result.getDate() + days); + return result; +} + +/* +sleep(2000).then(() => { + // Do something after the sleep! + + +}); +*/ + +function sleep(time) { + return new Promise((resolve) => setTimeout(resolve, time)); +} + +function isEmptyObject(obj) { + for (var name in obj) { + return false; + } + return true; +} + +function emptyJsObject(jsObject) { + Object.keys(jsObject).forEach(key => delete jsObject[key]); +} + +function convertUTCDateToLocalDate(date) { + var newDate = new Date(date); + newDate.setMinutes(date.getMinutes() + date.getTimezoneOffset()); + return newDate; +} + +function addZeroBefore(n) { + return (n < 10 ? '0' : '') + n; +} + + +/** + * Asynchronously writes data to a file. + * + * @param {string} filePath The path to the file. + * @param {string} data The data to write to the file. + * @param {boolean} [append=false] If true, appends the data to the file. If false, it overwrites the file. + */ +async function writeToFile(filePath, data, append = false) { + if (typeof data !== 'string') data = JSON.stringify(data, null, 2); + try { + if (append) { + // Append the data to the end of the file. This is the simplest way to append. + await fs.appendFile(filePath, data, 'utf8'); + console.log(`Successfully appended data to ${filePath} using fs.appendFile.`); + } else { + // Overwrite the file with the new data. + await fs.writeFile(filePath, data, 'utf8'); + console.log(`Successfully wrote (overwrote) data to ${filePath} using fs.writeFile.`); + } + } catch (error) { + console.error(`Error writing to file ${filePath}:`, error); + } +} + + + /** + * Checks if an item is present in an array and adds it if it's not. + * * @param {Array} arr The array to check. + * @param {*} item The item to add. + * @returns {Array} The modified array. + */ +const addToArrayIfUnique = (arr, item) => { + if (!arr.includes(item)) { + arr.push(item); + } + return arr; +}; + + +var convertBase = function() { + + function convertBase(baseFrom, baseTo) { + return function(num) { + return parseInt(num, baseFrom).toString(baseTo); + + }; + } + + // binary to decimal + convertBase.bin2dec = convertBase(2, 10); + + // binary to hexadecimal + convertBase.bin2hex = convertBase(2, 16); + + // decimal to binary + convertBase.dec2bin = convertBase(10, 2); + + // decimal to hexadecimal + convertBase.dec2hex = convertBase(10, 16); + + // hexadecimal to binary + convertBase.hex2bin = convertBase(16, 2); + + // hexadecimal to decimal + convertBase.hex2dec = convertBase(16, 10); + + return convertBase; +}(); + +module.exports = { + bytesToInt, + longToByteArray, + addDays, + addZeroBefore, + resizeArray, + isEmptyObject, + emptyJsObject, + sleep, + convertUTCDateToLocalDate, + writeToFile, + addToArrayIfUnique +} diff --git a/RVO36/flow/httprequest.js b/RVO36/flow/httprequest.js new file mode 100755 index 0000000..469c8cb --- /dev/null +++ b/RVO36/flow/httprequest.js @@ -0,0 +1,137 @@ +exports.id = 'httprequest'; +exports.title = 'HTTP Request'; +exports.group = 'HTTP'; +exports.color = '#5D9CEC'; +exports.input = true; +exports.version = '2.0.1'; +exports.output = 1; +exports.author = 'Peter Širka'; +exports.icon = 'cloud-upload'; + +exports.html = `
+
@(URL address)
+
+
+
@(HTTP method)
+
+
+
@(Serialization)
+
+
+
@(Download the content in chunks)
+
@(Keep persistent cookies)
+
@(Disable DNS cache)
+
@(Keep alive connection)
+
+
+
+
@(Custom headers)
+
@(Cookies)
+
+
+
+ +
+
+
+
@(User)
+
+
+
@(Password)
+
+
+
+
+
`; + +exports.readme = `# Request + +This component creates a request with received data. + +__Response:__ +\`\`\`javascript +{ + data: String, + headers: Object, + status: Number, + host: String +} +\`\`\` + +__Dynamic arguments__: +Are performed via FlowData repository and can be used for URL address or for custom headers/cookies/auth. Use \`repository\` component for creating of dynamic arguments. Dynamic values are replaced in the form \`{key}\`: + +- url address e.g. \`https://.../{key}/\` +- headers values e.g. \`{token}\` +- cookies values e.g. \`{token}\``; + +exports.install = function(instance) { + + var can = false; + var flags = null; + var cookies2 = null; + + instance.on('data', function(response) { + can && instance.custom.send(response); + }); + + instance.custom.send = function(response) { + var options = instance.options; + + var headers = null; + var cookies = null; + + options.headers && Object.keys(options.headers).forEach(function(key) { + !headers && (headers = {}); + headers[key] = response.arg(options.headers[key]); + }); + + if (options.username && options.userpassword) { + !headers && (headers = {}); + headers['Authorization'] = 'Basic ' + U.createBuffer(response.arg(options.username + ':' + options.userpassword)).toString('base64'); + } + + options.cookies && Object.keys(options.cookies).forEach(function(key) { + !cookies && (cookies = {}); + cookies[key] = response.arg(options.cookies[key]); + }); + + if (options.chunks) { + U.download(response.arg(options.url), flags, options.stringify === 'none' ? null : response.data, function(err, response) { + response.on('data', (chunks) => instance.send2(chunks)); + }, cookies || cookies2, headers); + } else { + U.request(response.arg(options.url), flags, options.stringify === 'none' ? null : response.data, 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) + instance.error(err, response); + }, cookies || cookies2, headers); + } + }; + + instance.reconfigure = function() { + var options = instance.options; + can = options.url && options.url && options.method && options.stringify ? true : false; + instance.status(can ? '' : 'Not configured', can ? undefined : 'red'); + + if (!can) + return; + + flags = []; + flags.push(options.method.toLowerCase()); + options.stringify === 'json' && flags.push('json'); + options.stringify === 'raw' && flags.push('raw'); + options.keepalive && flags.push('keepalive'); + !options.nodns && flags.push('dnscache'); + if (options.persistentcookies) { + flags.push('cookies'); + cookies2 = {}; + } else + cookies2 = null; + }; + + instance.on('options', instance.reconfigure); + instance.reconfigure(); +}; \ No newline at end of file diff --git a/RVO36/flow/httpresponse.js b/RVO36/flow/httpresponse.js new file mode 100755 index 0000000..160a3bb --- /dev/null +++ b/RVO36/flow/httpresponse.js @@ -0,0 +1,76 @@ +exports.id = 'httpresponse'; +exports.title = 'HTTP Response'; +exports.group = 'HTTP'; +exports.color = '#5D9CEC'; +exports.icon = 'arrow-right'; +exports.input = true; +exports.output = ['#666D76']; +exports.version = '2.0.0'; +exports.author = 'Martin Smola'; +exports.readme = `# HTTP response + +HTTP response will respond with data recieved using data-type set in Settings form or plain text if not set. Output is the message duration \`Number\` in seconds.`; + +exports.html = `
+
@(Response data-type)
+
JSON is by default.
+
`; + +exports.install = function(instance) { + + var dursum = 0; + var durcount = 0; + + instance.on('data', function(flowdata) { + + var ctrl = flowdata.repository.controller; + var data = flowdata.data; + + if (!ctrl) { + instance.throw('No controller to use for response!'); + return; + } + + durcount++; + dursum += ((new Date() - flowdata.begin) / 1000).floor(2); + setTimeout2(instance.id, instance.custom.duration, 500, 10); + + ctrl.$flowdata = flowdata; + + var datatype = instance.options.datatype || 'json'; + if (datatype === 'emptyresponse') + return ctrl.plain(''); + + if (datatype !== 'json' && typeof(data) !== 'string') { + instance.throw('Incorect type of data, expected string, got ' + typeof(data)); + ctrl.plain(data == null ? '' : data.toString()); + return; + } + + switch(datatype) { + case 'html': + ctrl.content(data, 'text/html'); + break; + case 'plain': + ctrl.plain(data); + break; + case 'xml': + ctrl.content(data, 'text/xml'); + break; + default: + ctrl.json(data); + break; + } + }); + + instance.on('service', function() { + dursum = 0; + durcount = 0; + }); + + instance.custom.duration = function() { + var avg = (dursum / durcount).floor(2); + instance.status(avg + ' sec.'); + instance.send2(0, avg); + }; +}; diff --git a/RVO36/flow/httproute.js b/RVO36/flow/httproute.js new file mode 100755 index 0000000..583a19d --- /dev/null +++ b/RVO36/flow/httproute.js @@ -0,0 +1,326 @@ +exports.id = 'httproute'; +exports.title = 'HTTP Route'; +exports.group = 'HTTP'; +exports.color = '#5D9CEC'; +exports.icon = 'globe'; +exports.input = false; +exports.output = ['#6CAC5A', '#37BC9B']; +exports.version = '1.2.3'; +exports.author = 'Martin Smola'; +exports.cloning = false; +exports.options = { method: 'GET', url: '', size: 5, cacheexpire: '5 minutes', cachepolicy: 0, timeout: 5 }; +exports.dateupdated = '2021-01-21 18:30d'; +exports.readme = `# HTTP route + +__Outputs__: +- first output: raw data (cache is empty or is disabled) +- second output: cached data + +If one of the outputs is disabled then automatic responce with code "503 service unavailable" is sent. + +When a request comes in bellow object is available at \`flowdata.data\`: + +\`\`\`javascript +{ + params: { id: '1' }, // params for dynamic routes, e.g. /test/{id} + query: { msg: 'Hello' }, // parsed query string, e.g. /test/1?msg=Hello + body: { test: 'OK' }, // object if json requests otherwise string + headers: {}, // headers data + session: {}, // session data + user: {}, // user data + files: [], // uploaded files + url: '/users/', // a relative URL address + referrer: '/', // referrer + mobile: false, // determines mobile device + robot: false, // determines search robots/crawlsers + language: 'en' // determines language +} +\`\`\` + +See [documentation for flags](https://docs.totaljs.com/latest/en.html#api~HttpRouteOptionsFlags~unauthorize). These method flags are set automatically e.g. \`get, post, put, patch or delete\` + +--- + +\`id:ROUTE_ID\` flag cannot be used since it's already used by this component internally`; + +exports.html = `
+
+ +
+ +
+
+
@(HTTP method)
+
+
+
@(URL address)
+
+
+
+
+
@(Additional flags)
+
@(Separate flags by comma e.g. json, authorize)
+
+
+
@(Max. request size)
+
@(In kB kilobytes)
+
+
+
@(Timeout)
+
@(In seconds.)
+
+
+
+
+
+
@(Automatically respond with 200 OK?)
+
@(If not checked you need to use HTTP response component to respond to the request.)
+
+
@(Custom headers)
+
@(Cookies)
+
+
+
+
+
+
@(Cache policy)
+
@(User instance must contain id property.)
+
+
+
@(Expiration)
+
@(E.g. 5 minutes)
+
+
+
+`; + +exports.install = function(instance) { + + var route; + + var uninstall = function(id) { + if (F.is4) { + route && route.remove(); + route = null; + } else + UNINSTALL('route', id); + }; + + instance.custom.emptyresponse = function(self) { + self.plain(); + }; + + instance.reconfigure = function() { + + var options = instance.options; + + if (!options.url) { + instance.status('Not configured', 'red'); + return; + } + + if (typeof(options.flags) === 'string') + options.flags = options.flags.split(',').trim(); + + uninstall('id:' + instance.id); + + var flags = options.flags || []; + + flags.push('id:' + instance.id); + + if (!F.is4) + flags.push(options.method.toLowerCase()); + + options.timeout && flags.push(options.timeout * 1000); + + // Make unique values + flags = flags.filter(function(v, i, a) { + if(F.is4 && v.toString().toLowerCase() === options.method.toLowerCase()) + return false; // remove method + return a.indexOf(v) === i; + }); + + options.flags = flags; + var handler = function() { + + if (instance.paused || (instance.isDisabled && (instance.isDisabled('output', 0) || instance.isDisabled('output', 1)))) { + instance.status('503 Service Unavailable'); + this.status = 503; + this.json(); + return; + } + + var key; + var self = this; + + if (instance.options.emptyresponse) { + instance.status('200 OK'); + setTimeout(instance.custom.emptyresponse, 100, self); + + if (instance.hasConnection(0)) { + var data = instance.make({ + query: self.query, + body: self.body, + session: self.session, + user: self.user, + files: self.files, + headers: self.req.headers, + url: self.url, + params: self.params + }); + instance.send2(0, data); + } + + return; + } + + switch (instance.options.cachepolicy) { + case 1: // URL + key = 'rro' + instance.id + self.url.hash(); + break; + case 2: // URL + query + case 3: // URL + query + user + key = self.url; + var keys = Object.keys(self.query); + keys.sort(); + for (var i = 0, length = keys.length; i < length; i++) + key += keys[i] + self.query[keys[i]] + '&'; + if (instance.options.cachepolicy === 3 && self.user) + key += 'iduser' + self.user.id; + key = 'rro' + instance.id + key.hash(); + break; + } + + if (key && F.cache.get2(key)) { + var data = instance.make(F.cache.get2(key)); + data.repository.controller = self; + instance.send2(1, data); + } else { + + var data = instance.make({ + query: self.query, + body: self.body, + session: self.session, + user: self.user, + files: self.files, + headers: self.req.headers, + url: self.url, + params: self.params, + mobile: self.mobile, + robot: self.robot, + referrer: self.referrer, + language: self.language + }); + + data.repository.controller = self; + instance.send2(0, data); + key && FINISHED(self.res, () => F.cache.set(key, self.$flowdata.data, instance.options.cacheexpire)); + } + }; + + if (F.is4) + route = ROUTE(options.method.toUpperCase() + ' ' + options.url, handler, flags, options.size || 5); + else + F.route(options.url, handler, flags, options.size || 5); + + instance.status('Listening', 'green'); + }; + + instance.reconfigure(); + instance.on('options', instance.reconfigure); + instance.on('close', function(){ + uninstall('id:' + instance.id); + }); +}; + +// check url exists +FLOW.trigger('httproutecheckurl', function(next, data) { + var url = data.url; + var method = data.method; + if (url[url.length - 1] !== '/') + url += '/'; + var exists = F.routes.web.findItem(r => r.urlraw === url && r.method === method); + next(exists != null); +}); + +exports.uninstall = function() { + FLOW.trigger('httproutecheckurl', null); +}; diff --git a/RVO36/flow/infosender.js b/RVO36/flow/infosender.js new file mode 100755 index 0000000..587724f --- /dev/null +++ b/RVO36/flow/infosender.js @@ -0,0 +1,81 @@ +exports.id = 'infosender'; +exports.title = 'Info sender'; +exports.version = '1.0.0'; +exports.group = 'Worksys'; +exports.color = '#2134B0'; +exports.input = 2; +exports.output = 1 +exports.icon = 'bolt'; + +const { networkInterfaces } = require('os'); + +exports.html = `
+
+
+
CSV Import
+
+
+
`; + +exports.readme = `# send all data to projects.worksys.io, required to monitor status of controller(unipi)`; + +exports.install = function(instance) { + + let id; + let allValues = {}; + let sendAllValuesInterval; + let configured = false; + + let now = new Date(); + console.log(exports.title, "INSTALLED", now.toLocaleString("sk-SK")); + + const nets = networkInterfaces(); + let ipAddresses = Object.create(null); // Or just '{}', an empty object + + for (const name of Object.keys(nets)) { + for (const net of nets[name]) { + // Skip over non-IPv4 and internal (i.e. 127.0.0.1) addresses + if (net.family === 'IPv4' && !net.internal) { + if (!ipAddresses[name]) { + ipAddresses[name] = []; + } + ipAddresses[name].push(net.address); + } + } + } + + function sendValues() { + if (!configured) return; + + if (Object.keys(allValues).length > 0) { + let dataToSend = { ...allValues }; + dataToSend.id = id; + dataToSend.ipAddresses = ipAddresses; + + instance.send(0, dataToSend); + + allValues = {}; + } + } + + instance.on("close", () => { + clearInterval(sendAllValuesInterval); + }) + + instance.on("0", _ => { + id = FLOW.GLOBALS.settings.project_id; + if (id) configured = true; + else console.log(exports.title, "InfoSender: Unable to send data, no id"); + }) + + instance.on("1", flowdata => { + allValues = { ...allValues, ...flowdata.data }; + //console.log("DATA RECEIVED", flowdata.data); + }) + + sendAllValuesInterval = setInterval(() => { + sendValues(); + }, 60000 * 3); + +} + diff --git a/RVO36/flow/modbus_reader.js b/RVO36/flow/modbus_reader.js new file mode 100755 index 0000000..d6d9dad --- /dev/null +++ b/RVO36/flow/modbus_reader.js @@ -0,0 +1,346 @@ +exports.id = 'modbus_reader'; +exports.title = 'Modbus reader'; +exports.version = '2.0.0'; +exports.group = 'Worksys'; +exports.color = '#2134B0'; +exports.input = 1; +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; +//number of phases inRVO +let phases; +//phases where voltage is 0 (set) +let noVoltage; +let energyToSwitchLamps; + +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.phases = this.buildPhases(); + + this.startSocket(); + } + + buildPhases = () => { + let a = []; + for (let i = 1; i <= phases; i++) { + a.push(`Phase_${i}_voltage`) + } + return a; + } + + startSocket = () => { + + let obj = this; + + if (this.socket) { + this.socket.removeAllListeners(); + this.socket = null; + } + + 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('Modbus_reader: Socket connection error', e); //'ECONNREFUSED' or 'ECONNRESET' ?? + }); + + this.socket.on('close', function() { + console.log('Modbus_reader: Socket connection closed - Waiting 10 seconds before connecting 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 we just start to loop devices from the beginning, or there is just 1 device in config, we wait whole timeoutInterval + if (this.indexInDeviceConfig == 0 || deviceConfig.length === 1) 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 (this.phases.includes(singleValue)) { + let l = singleValue.split("_"); + let phase = parseInt(l[1]); + + // console.log(values[singleValue], tbName); + + if (values[singleValue] == 0) { + noVoltage.add(phase); + sendNotification("modbus_reader: checkNullVoltage", tbName, "no_voltage_on_phase", { phase: phase }, "", SEND_TO.tb, instance, "voltage" + phase); + // console.log('no voltage') + } + else { + noVoltage.delete(phase); + // console.log('voltage detected') + sendNotification("modbus_reader: checkNullVoltage", tbName, "voltage_on_phase_restored", { phase: phase }, "", SEND_TO.tb, instance, "voltage" + phase); + } + } + }) + } + + /** + * function sends notification to slack and to tb, if EM total_power value changes more than numberOfNodes*15. This should show, that RVO lamps has been switched on or off + */ + lampSwitchNotification = (values) => { + + if (!values.hasOwnProperty("total_power")) return; + + const actualTotalPower = values.total_power; + + if (actualTotalPower > energyToSwitchLamps && 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 <= energyToSwitchLamps && 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; + } + + function main() { + + phases = FLOW.GLOBALS.settings.phases; + tbName = FLOW.GLOBALS.settings.rvoTbName; + noVoltage = FLOW.GLOBALS.settings.no_voltage; + energyToSwitchLamps = FLOW.GLOBALS.settings.energy_to_switch_lamps / 2.5; //half value is enought to show if lamps are turned on or off + if (deviceConfig.length) mainSocket = new SocketWithClients(); + else console.log("Modbus_reader: no modbus device in configuration"); + + // this notification is to show, that flow (unipi) has been restarted + sendNotification("modbus_reader", tbName, "flow_restart", {}, "", SEND_TO.slack, instance); + } + + instance.on("0", function(_) { + main(); + }) + +} + diff --git a/RVO36/flow/monitorconsumption.js b/RVO36/flow/monitorconsumption.js new file mode 100755 index 0000000..64cc58e --- /dev/null +++ b/RVO36/flow/monitorconsumption.js @@ -0,0 +1,156 @@ +exports.id = 'monitorconsumption'; +exports.title = 'Consumption'; +exports.version = '1.0.0'; +exports.author = 'Peter Širka'; +exports.group = 'Monitoring'; +exports.color = '#967ADC'; +exports.input = 0; +exports.output = 1; +exports.icon = 'bug'; +exports.options = { interval: 5000, enabled: true, monitorconsumption: true, monitorsize: true, monitorconnections: true, monitorfiles: true }; +exports.click = true; +exports.readme = `# Consumption monitoring + +This component measure CPU and memory consumption, open files and open connections of this application. It uses these Linux commands: \`ps\`, \`lsof\`, \`netstat\` and \`df\`. + +__Data Example__: + +\`\`\`javascript +{ + cpu: 0, // percentage + memory: 4096, // in bytes + size: 34303, // directory size in bytes + files: 34, // count of open files + connections: 343, // count of connections + uptime: '1-12:34:00' +} +\`\`\``; + +exports.html = `
+
+
+
@(Interval in milliseconds)
+
+
+
+
Monitor: Consumption + uptime
+
Monitor: Count of open files
+
Monitor: Count of open connections
+
Monitor: Directory size
+
`; + +exports.install = function(instance) { + + var current = { cpu: 0, memory: 0, files: 0, connections: 0, size: 0, uptime: '', counter: 0 }; + var tproc = null; + var Exec = require('child_process').exec; + var reg_empty = /\s{2,}/g; + var reg_appdisksize = /^[\d.,]+/; + + instance.custom.run = function() { + + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + + var arr = []; + + // Get CPU and Memory consumption + instance.options.monitorconsumption && arr.push(function(next) { + Exec('ps -p {0} -o %cpu,rss,etime'.format(process.pid), function(err, response) { + + if (err) { + instance.throw(err); + } else { + var line = response.split('\n')[1]; + line = line.trim().replace(reg_empty, ' ').split(' '); + var cpu = line[0].parseFloat(); + current.cpu = cpu.floor(1); + current.memory = line[1].parseInt2() * 1024; // kB to bytes + current.uptime = line[2]; + } + + next(); + }); + }); + + // Get count of open files + instance.options.monitorfiles && arr.push(function(next) { + Exec('lsof -a -p {0} | wc -l'.format(process.pid), function(err, response) { + if (err) + instance.throw(err); + else + current.files = response.trim().parseInt2(); + next(); + }); + }); + + // Get count of opened network connections + instance.options.monitorconnections && arr.push(function(next) { + Exec('netstat -an | grep :{0} | wc -l'.format(F.port), function(err, response) { + if (err) { + instance.throw(err); + } else { + current.connections = response.trim().parseInt2() - 1; + if (current.connections < 0) + current.connections = 0; + } + next(); + }); + }); + + // Get directory size + instance.options.monitorsize && current.counter % 5 !== 0 && arr.push(function(next) { + Exec('du -hsb ' + process.cwd(), function(err, response) { + if (err) { + instance.throw(err); + } else { + var match = response.trim().match(reg_appdisksize); + match && (current.size = match.toString().trim().parseInt2()); + } + next(); + }); + }); + + arr.async(function() { + + tproc && clearTimeout(tproc); + + if (instance.options.enabled) { + tproc = setTimeout(instance.custom.run, instance.options.interval); + instance.send2(current); + } + + instance.custom.status(); + current.counter++; + }); + }; + + instance.custom.status = function() { + if (instance.options.enabled) + instance.status('{0}% / {1}'.format(current.cpu, current.memory.filesize())); + else + instance.status('Disabled', 'red'); + }; + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + + if (instance.options.enabled) { + current.counter = 0; + instance.custom.run(); + } + + }); + + instance.on('close', function() { + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + }); + + setTimeout(instance.custom.run, 1000); +}; \ No newline at end of file diff --git a/RVO36/flow/monitordisk.js b/RVO36/flow/monitordisk.js new file mode 100755 index 0000000..f4fdaa0 --- /dev/null +++ b/RVO36/flow/monitordisk.js @@ -0,0 +1,96 @@ +exports.id = 'monitordisk'; +exports.title = 'Disk'; +exports.version = '1.0.0'; +exports.author = 'Peter Širka'; +exports.group = 'Monitoring'; +exports.color = '#F6BB42'; +exports.output = 1; +exports.icon = 'hdd-o'; +exports.click = true; +exports.options = { interval: 8000, path: '/', enabled: true }; +exports.readme = `# Disk monitoring + +This component monitors disk \`bytes\` consumption in Linux systems. It uses \`df\` command. + +__Data Example__: + +\`\`\`javascript +{ + total: 474549649408, + used: 39125245952, + free: 411294994432 +} +\`\`\``; + +exports.html = `
+
+
+
@(Interval in milliseconds)
+
+
+
@(Path)
+
+
+
`; + +exports.install = function(instance) { + + var current = { total: 0, used: 0, free: 0, path: '', type: '', percentUsed: 0 }; + var tproc = null; + + instance.custom.run = function() { + + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + + if (!instance.options.enabled) + return; + + require('child_process').exec('df -hTB1 ' + instance.options.path, function(err, response) { + + tproc = setTimeout(instance.custom.run, instance.options.interval); + + if (err) { + instance.error(err); + return; + } + + response.parseTerminal(function(line) { + if (line[0][0] !== '/') + return; + current.total = line[2].parseInt(); + current.free = line[4].parseInt(); + current.used = line[3].parseInt(); + current.path = instance.options.path || '/'; + current.type = line[1]; + current.percentUsed = line[5]; + instance.custom.status(); + instance.send2(current); + }); + }); + }; + + instance.custom.status = function() { + if (instance.options.enabled) + instance.status(current.free.filesize() + ' / ' + current.total.filesize()); + else + instance.status('Disabled', 'red'); + }; + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + instance.options.enabled && instance.custom.run(); + }); + + instance.on('close', function() { + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + }); + + setTimeout(instance.custom.run, 1000); +}; \ No newline at end of file diff --git a/RVO36/flow/monitormemory.js b/RVO36/flow/monitormemory.js new file mode 100755 index 0000000..2decbc4 --- /dev/null +++ b/RVO36/flow/monitormemory.js @@ -0,0 +1,87 @@ +exports.id = 'monitormemory'; +exports.title = 'Memory'; +exports.version = '1.0.0'; +exports.author = 'Peter Širka'; +exports.group = 'Monitoring'; +exports.color = '#F6BB42'; +exports.output = 1; +exports.click = true; +exports.icon = 'microchip'; +exports.options = { interval: 8000, enabled: true }; +exports.readme = `# Memory monitoring + +This component monitors memory \`bytes\` consumption in Linux systems. It uses \`free\` command. + +__Data Example__: + +\`\`\`javascript +{ + total: 33558769664, + used: 1998868480, + free: 2653708288 +} +\`\`\``; + +exports.html = `
+
+
+
@(Interval in milliseconds)
+
+
+
`; + +exports.install = function(instance) { + + var current = { total: 0, used: 0, free: 0 }; + var tproc = null; + + instance.custom.run = function() { + + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + + if (!instance.options.enabled) + return; + + require('child_process').exec('free -b -t', function(err, response) { + + tproc = setTimeout(instance.custom.run, instance.options.interval); + + if (err) { + instance.error(err); + return; + } + + var memory = response.split('\n')[1].match(/\d+/g); + current.total = memory[0].parseInt(); + current.used = memory[1].parseInt() - memory[3].parseInt(); + current.free = current.total - current.used; + instance.custom.status(); + instance.send2(current); + }); + }; + + instance.custom.status = function() { + if (instance.options.enabled) + instance.status(current.free.filesize() + ' / ' + current.total.filesize()); + else + instance.status('Disabled', 'red'); + }; + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + instance.options.enabled && instance.custom.run(); + }); + + instance.on('close', function() { + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + }); + + setTimeout(instance.custom.run, 1000); +}; \ No newline at end of file diff --git a/RVO36/flow/nodesdb_changecheck.js b/RVO36/flow/nodesdb_changecheck.js new file mode 100755 index 0000000..9adab62 --- /dev/null +++ b/RVO36/flow/nodesdb_changecheck.js @@ -0,0 +1,77 @@ +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 = 2; +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); + } + } + + //kedze do slacku posielame stringy, na cloud musime previest vsetky stringy spat na objekty: + // Funkcia na parsovanie všetkých reťazcov v poli + const parseArray = (arr) => { + return arr.map(jsonString => JSON.parse(jsonString)); + }; + + 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); + if (FLOW.GLOBALS.settings.send_changed_node_numbers) instance.send(1, { aktualneNody: parseArray(zmenene), originalne: parseArray(Array.from(set2)) }); + } + 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/RVO36/flow/show_dbdata.js b/RVO36/flow/show_dbdata.js new file mode 100755 index 0000000..1e23ff7 --- /dev/null +++ b/RVO36/flow/show_dbdata.js @@ -0,0 +1,243 @@ +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 = 8; +exports.output = 1; + +const { exec } = require('child_process'); + +exports.install = 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 }) + }) + instance.on("5", _ => { + exec("sudo tail -n 25 monitor.txt", (err, stdout, stderr) => { + if (err || stderr) instance.send(0, { err, stderr }); + else instance.send(0, stdout); + }) + }) + instance.on("6", _ => { + exec("sudo tail -n 25 err.txt", (err, stdout, stderr) => { + if (err || stderr) instance.send(0, { err, stderr }); + else instance.send(0, stdout); + }) + }) + instance.on("7", _ => { + instance.send(0, FLOW.deviceStatus); + }) +}; + + +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/RVO36/flow/slack_filter.js b/RVO36/flow/slack_filter.js new file mode 100755 index 0000000..6618523 --- /dev/null +++ b/RVO36/flow/slack_filter.js @@ -0,0 +1,188 @@ +exports.id = 'slack_filter'; +exports.title = 'Slack Filter'; +exports.group = 'Citysys'; +exports.color = '#30E193'; +exports.input = 2; +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 = `
+
+
+
@(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('0', 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']['en']; + 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"] = []; + } + + instance.options.name = FLOW.GLOBALS.settings.rvo_name; + if (instance.options.name) { + instance.status('Running'); + running = true; + } else { + instance.status('Please run options again', 'red'); + running = false; + } + } catch (e) { + instance.error('Citysys connector: ' + e.message); + } + }; + + instance.on('options', instance.reconfigure); + + instance.on("1", _ => { + instance.reconfigure(); + }) +}; diff --git a/RVO36/flow/thermometer.js b/RVO36/flow/thermometer.js new file mode 100755 index 0000000..fc7074d --- /dev/null +++ b/RVO36/flow/thermometer.js @@ -0,0 +1,99 @@ +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 = 5;//minutes +let NUMBER_OF_FAILURES_TO_SEND_ERROR = 13; + +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) => { + + 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); + setTimeout(main, 20000); + }) +}; diff --git a/RVO36/flow/trigger.js b/RVO36/flow/trigger.js new file mode 100755 index 0000000..27545a8 --- /dev/null +++ b/RVO36/flow/trigger.js @@ -0,0 +1,79 @@ +exports.id = 'trigger'; +exports.title = 'Trigger'; +exports.group = 'Inputs'; +exports.color = '#F6BB42'; +exports.click = true; +exports.output = 1; +exports.version = '1.1.0'; +exports.author = 'Martin Smola'; +exports.icon = 'play'; + +exports.html = `
+
@(Data type (String by default))
+
@(Data)
+
Trigger 5s after initialization.
+
@(Useful when there's a need to run certain flow when the app restarts, etc.)
+
`; + +exports.readme = `# Trigger + +- Clicking on the component starts the chain +- Settings allows to set a data-type and a value`; + +exports.install = function(instance) { + + var value; + + instance.on('click', () => instance.send2(value)); + + instance.reconfigure = function() { + var options = instance.options; + value = null; + switch (options.datatype) { + case 'integer': + value = options.data.parseInt2('error'); + value = value === 'error' ? NaN : value; + break; + case 'float': + value = options.data.parseFloat2('error'); + value = value === 'error' ? NaN : value; + break; + case 'date': + options.data = options.data.toString(); + var num = options.data.parseInt('error'); + num === 'error' && (num = options.data.parseDate('error')); + num === 'error' && (num = null); + value = num ? new Date(num).toUTCString() : num; + break; + case 'object': + try { + value = (new Function('return ' + options.data))(); + } catch (e) { + instance.error(e); + } + break; + case 'boolean': + value = options.data.parseBoolean(); + break; + case 'buffer': + try { + value = U.createBuffer(options.data); + } catch (e) { + instance.error(e); + } + break; + case 'string': + default: + value = '' + (options.data || ''); + break; + } + }; + + instance.on('options', instance.reconfigure); + instance.reconfigure(); + + if (instance.options.restart) + setTimeout(function(){ + instance.send2(value); + }, 5000); +}; diff --git a/RVO36/flow/variables.txt b/RVO36/flow/variables.txt new file mode 100755 index 0000000..e69de29 diff --git a/RVO36/flow/virtualwirein.js b/RVO36/flow/virtualwirein.js new file mode 100755 index 0000000..38a4e42 --- /dev/null +++ b/RVO36/flow/virtualwirein.js @@ -0,0 +1,43 @@ +exports.id = 'virtualwirein'; +exports.title = 'Virtual wire in'; +exports.version = '1.0.0'; +exports.author = 'Martin Smola'; +exports.color = '#303E4D'; +exports.icon = 'sign-in'; +exports.input = false; +exports.output = 1; +exports.options = {}; +exports.readme = `# Virtual wire in + +When the wires between the components are mess it's time to use Virtual wire.`; + +exports.html = `
+
@(Wire name)
+
+`; + +exports.install = function(instance) { + + instance.custom.reconfigure = function(options){ + if (instance.options.wirename) { + instance.status(instance.options.wirename); + } else + instance.status('Not configured', 'red'); + }; + + ON('virtualwire', function(wirename, flowdata){ + if (instance.options.wirename && instance.options.wirename === wirename) + instance.send(flowdata); + }); + + instance.on('options', instance.custom.reconfigure); + instance.custom.reconfigure(); +}; diff --git a/RVO36/flow/virtualwireout.js b/RVO36/flow/virtualwireout.js new file mode 100755 index 0000000..94a1e4f --- /dev/null +++ b/RVO36/flow/virtualwireout.js @@ -0,0 +1,41 @@ +exports.id = 'virtualwireout'; +exports.title = 'Virtual wire out'; +exports.version = '1.0.0'; +exports.author = 'Martin Smola'; +exports.color = '#303E4D'; +exports.icon = 'sign-out'; +exports.input = true; +exports.options = {}; +exports.readme = `# Virtual wire out + +When the wires between the components are mess it's time to use Virtual wire.`; + +exports.html = `
+
@(Wire name)
+
+`; + +exports.install = function(instance) { + + instance.custom.reconfigure = function(){ + if (instance.options.wirename) { + instance.status(instance.options.wirename); + } else + instance.status('Not configured', 'red'); + }; + + instance.on('data', function(flowdata) { + EMIT('virtualwire', instance.options.wirename, flowdata); + }); + + instance.on('options', instance.custom.reconfigure); + instance.custom.reconfigure(); +}; diff --git a/RVO36/flow/wsmqttpublish.js b/RVO36/flow/wsmqttpublish.js new file mode 100755 index 0000000..0eba804 --- /dev/null +++ b/RVO36/flow/wsmqttpublish.js @@ -0,0 +1,448 @@ +exports.id = 'wsmqttpublish'; +exports.title = 'WS MQTT publish'; +exports.group = 'MQTT'; +exports.color = '#888600'; +exports.version = '1.0.2'; +exports.icon = 'sign-out'; +exports.input = 2; +exports.output = 3; +exports.options = { host: 'tb-stage.worksys.io', port: 1883, clientid: "", username: "" }; + +exports.html = `
+
+
+
Hostname or IP address (if not empty - setting will override db setting)
+
+
+
Port
+
+
+
+
+
@(Client id)
+
+
+
@(Username)
+
+
+
`; + + +exports.readme = ` +# WS MQTT Publish + +Version 1.0.3. + +Added: +- database collections, +- 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 = { + debug: 0, + rpcCall: 1, + services: 2 +} + +//CONFIG +let createTelemetryBackup = true; +let saveTelemetryOnError = true;//backup_on_failure overrides this value +//------------------------ + +let rollers; +if (createTelemetryBackup) rollers = require('streamroller'); + +const noSqlFileSizeLimit = 4194304;//use 5MB - 4194304 +let insertNoSqlCounter = 0; +let insertBackupNoSqlCounter = 0; +let processingData = false; + +let backup_on_failure = false;//== saveTelemetryOnError - create backup client 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; + +process.on('uncaughtException', function(err) { + + errLogger.error('uncaughtException:', err.message) + errLogger.error(err.stack); + + //TODO + //send to service + + //process.exit(1); +}) + +const nosql = NOSQL('tbdata'); +const nosqlBackup = NOSQL('/backup/tbdata'); + + +exports.install = function(instance) { + + var client; + var opts; + var clientReady = false; + + // wsmqtt status for notification purposes on projects.worksys.io database + let wsmqttName = null; + let sendWsStatusVar = null; + let wsmqtt_status = 'disconnected'; + + 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'; + } + + function sendWsStatus() { + instance.send(SEND_TO.services, { [wsmqttName]: wsmqtt_status }); + } + + + function main() { + if (!FLOW.dbLoaded) return; + + loadSettings(); + clearInterval(sendWsStatus); + sendWsStatusVar = setInterval(sendWsStatus, 180000); + } + + //set opts according to db settings + function loadSettings() { + + if (instance.options.host !== "") { + //override settings from database + var o = instance.options; + opts = { + host: o.host, + port: o.port, + clientId: o.clientid, + username: o.username, + rejectUnauthorized: false, + resubscribe: false + }; + + wsmqttName = getWsmqttName(o.host); + + console.log("wsmqttpublich -> loadSettings from instance.options", instance.options); + } + else { + + const SETTINGS = FLOW.GLOBALS.settings; + backup_on_failure = SETTINGS.backup_on_failure; + saveTelemetryOnError = backup_on_failure; + + restore_from_backup = SETTINGS.restore_from_backup; + restore_backup_wait = SETTINGS.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; + + opts = { + host: mqtt_host, + port: mqtt_port, + keepalive: 10, + clientId: mqtt_clientid, + username: mqtt_username, + rejectUnauthorized: false, + resubscribe: false + }; + + wsmqttName = getWsmqttName(mqtt_host); + } + + connectToTbServer(); + } + + function connectToTbServer() { + 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"); + //monitor.info("MQTT client connected"); + + sendClientError = true; + clientReady = true; + wsmqtt_status = 'connected'; + }); + + client.on('reconnect', function() { + instance.status("Reconnecting", "yellow"); + clientReady = false; + }); + + client.on('message', function(topic, message) { + // message is type of buffer + message = message.toString(); + if (message[0] === '{') { + TRY(function() { + + message = JSON.parse(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 } }); + } + + }, () => instance.debug('MQTT: Error parsing data', message)); + } + + instance.send(SEND_TO.rpcCall, { "topic": topic, "content": message }); + }); + + client.on('close', function() { + clientReady = false; + wsmqtt_status = 'disconnected'; + + instance.status("Disconnected", "red"); + instance.send(SEND_TO.debug, { "message": "Client CLOSE signal received !" }); + }); + + client.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; + wsmqtt_status = 'disconnected'; + }); + + } + + + instance.on("0", _ => { + main(); + }) + + + instance.on('1', function(data) { + + if (clientReady) { + //do we have some data in backup file? if any, process data from database + if (saveTelemetryOnError) { + //read telemetry data and send back to server + if (!processingData) processDataFromDatabase(); + } + + let stringifiedJson = JSON.stringify(data.data); + client.publish("v1/gateway/telemetry", stringifiedJson, { qos: 1 }); + + //backup telemetry + if (createTelemetryBackup) { + data.data.id = UID(); + nosqlBackup.insert(data.data); + + insertBackupNoSqlCounter++; + if (insertBackupNoSqlCounter > 150) { + let options = { compress: true }; + let path = __dirname + "/../databases/backup/tbdata.nosql"; + var stream = new rollers.RollingFileStream(path, noSqlFileSizeLimit, 150, options); + stream.write(""); + stream.end(); + + insertBackupNoSqlCounter = 0; + } + } + + } + 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 (saveTelemetryOnError) { + //create new file from tbdata.nosql, if file size exceeds given limit, and clear tbdata.nosql + makeBackupFromDbFile(); + + //write to tb + data.data.id = UID(); + nosql.insert(data.data); + } + } + }); + + + instance.close = function(done) { + if (clientReady) { + client.end(); + clearInterval(sendWsStatusVar); + } + }; + + + function getDbBackupFileCounter(type) { + var files = fs.readdirSync(__dirname + "/../databases"); + + let counter = 0; + for (var i = 0; i < files.length; i++) { + + if (files[i] == "tbdata.nosql") continue; + + if (files[i].endsWith(".nosql")) { + + let pos = files[i].indexOf("."); + if (pos > -1) { + + let fileCounter = counter; + let firstDigit = files[i].slice(0, pos); + + fileCounter = parseInt(firstDigit); + if (isNaN(fileCounter)) fileCounter = 0; + //console.log("getDbBackupFileCounter digit:", files[i], firstDigit, fileCounter, isNaN(fileCounter), type); + + if (type == "max") { + if (fileCounter > counter) { + counter = fileCounter; + } + } + else if (type == "min") { + if (counter == 0) counter = fileCounter; + + if (fileCounter < counter) { + counter = fileCounter; + } + } + } + } + + } + + if (type == "max") counter++; + + return counter; + } + + const makeBackupFromDbFile = async () => { + + if (!saveTelemetryOnError) return; + + //to avoid large file: tbdata.nosql + + //init value is 0! + if (insertNoSqlCounter > 0) { + --insertNoSqlCounter; + return; + } + + insertNoSqlCounter = 100; + + let source = __dirname + "/../databases/tbdata.nosql"; + + var stats = fs.statSync(source); + var fileSizeInBytes = stats.size; + + if (fileSizeInBytes > noSqlFileSizeLimit) { + + let counter = 1; + counter = getDbBackupFileCounter("max"); + + let destination = __dirname + "/../databases/" + counter + "." + "tbdata.nosql"; + + //make backup file + fs.copyFileSync(source, destination); + //fs.renameSync(p, p + "." + counter); + + //clear tbdata.nosql + fs.writeFileSync(source, ""); + fs.truncateSync(source, 0); + + } + } + + const processDataFromDatabase = async () => { + + if (restore_from_backup <= 0) return; + + //calculate diff + const now = new Date(); + let currentTime = now.getTime(); + let diff = currentTime - lastRestoreTime; + + if ((diff / 1000) < restore_backup_wait) { + //console.log("*********restore_backup_wait", diff, restore_backup_wait); + return; + } + + processingData = true; + + //get filename to process + let counter = getDbBackupFileCounter("min"); + + //we have some backup files + let dataBase = 'tbdata'; + + var nosql; + if (counter == 0) dataBase = 'tbdata'; + else dataBase = counter + "." + 'tbdata'; + + nosql = NOSQL(dataBase); + + //select all data - use limit restore_from_backup + let records = await promisifyBuilder(nosql.find().take(restore_from_backup)); + + for (let i = 0; i < records.length; i++) { + if (clientReady) { + + let item = records[i]; + let id = item.id; + + if (id !== undefined) { + //console.log("------------processDataFromDatabase - remove", id, dataBase, i); + + try { + + let message = JSON.parse(JSON.stringify(item)); + delete message.id; + + client.publish("v1/gateway/telemetry", JSON.stringify(message), { qos: 1 }); + + //remove from database + await promisifyBuilder(nosql.remove().where("id", id)); + + } catch (error) { + //process error + console.log("processDataFromDatabase", error); + } + + } + + } + else { + processingData = false; + return; + } + } + + if (records.length > 0) { + //clean backup file + if (counter > 0) nosql.clean(); + } + + //no data in db, remove + if (records.length == 0) { + if (counter > 0) nosql.drop(); + } + + const d = new Date(); + lastRestoreTime = d.getTime(); + + processingData = false; + + } + + instance.on('options', main); + //instance.reconfigure(); +}; diff --git a/RVO36/monitor.txt b/RVO36/monitor.txt new file mode 100755 index 0000000..ae6a440 --- /dev/null +++ b/RVO36/monitor.txt @@ -0,0 +1,258 @@ +[2025-10-09T16:54:53.572] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-09T16:54:58.908] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-09T16:54:58.913] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-09T16:54:58.914] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-09T16:54:58.915] [INFO] monitorLogs - 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 +} +[2025-10-09T16:54:58.918] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T16:54:58.919] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-10-10T11:00:00.918Z +[2025-10-09T16:54:58.920] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-09T16:54:58.921] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-10-09T16:54:58.922] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-09T16:54:58.923] [INFO] monitorLogs - 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 +} +[2025-10-09T16:54:58.924] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T16:54:58.925] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-10-10T11:00:00.925Z +[2025-10-09T16:54:58.926] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-09T16:54:58.927] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-10-09T16:54:58.928] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-09T16:54:58.928] [INFO] monitorLogs - 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 +} +[2025-10-09T16:54:58.930] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T16:54:58.930] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-10-10T11:00:00.930Z +[2025-10-09T16:54:58.931] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-09T16:54:58.932] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-10-09T16:54:58.934] [INFO] monitorLogs - tasks created: 235 +[2025-10-09T16:54:58.936] [INFO] monitorLogs - -->FLOW bol spustený 2O14VBzl8aDmWdNw3A59v9AGyZ5qLJoEMpj6R9ng 2025-08-08 +[2025-10-09T16:55:03.939] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-09T19:07:26.450] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-09T19:07:31.797] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-09T19:07:31.802] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-09T19:07:31.803] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-09T19:07:31.803] [INFO] monitorLogs - 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 +} +[2025-10-09T19:07:31.806] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T19:07:31.808] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-10-10T11:00:00.807Z +[2025-10-09T19:07:31.809] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-09T19:07:31.810] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-10-09T19:07:31.811] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-09T19:07:31.812] [INFO] monitorLogs - 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 +} +[2025-10-09T19:07:31.814] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T19:07:31.814] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-10-10T11:00:00.814Z +[2025-10-09T19:07:31.815] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-09T19:07:31.816] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-10-09T19:07:31.817] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-09T19:07:31.818] [INFO] monitorLogs - 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 +} +[2025-10-09T19:07:31.819] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T19:07:31.820] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-10-10T11:00:00.820Z +[2025-10-09T19:07:31.821] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-09T19:07:31.821] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-10-09T19:07:31.824] [INFO] monitorLogs - tasks created: 235 +[2025-10-09T19:07:31.826] [INFO] monitorLogs - -->FLOW bol spustený 2O14VBzl8aDmWdNw3A59v9AGyZ5qLJoEMpj6R9ng 2025-08-08 +[2025-10-09T19:07:36.846] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-10T03:07:32.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-10 03:07:32 +[2025-10-10T10:49:02.177] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-10T10:49:07.517] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-10T10:49:07.523] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-10T10:49:07.524] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-10T10:49:07.525] [INFO] monitorLogs - 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 +} +[2025-10-10T10:49:07.528] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-10T10:49:07.529] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-10-10T11:00:00.528Z +[2025-10-10T10:49:07.530] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-10T10:49:07.531] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-10-10T10:49:07.532] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-10T10:49:07.533] [INFO] monitorLogs - 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 +} +[2025-10-10T10:49:07.534] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-10T10:49:07.535] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-10-10T11:00:00.535Z +[2025-10-10T10:49:07.536] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-10T10:49:07.537] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-10-10T10:49:07.538] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-10T10:49:07.538] [INFO] monitorLogs - 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 +} +[2025-10-10T10:49:07.540] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-10T10:49:07.540] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-10-10T11:00:00.540Z +[2025-10-10T10:49:07.541] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-10T10:49:07.542] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-10-10T10:49:07.544] [INFO] monitorLogs - tasks created: 235 +[2025-10-10T10:49:07.546] [INFO] monitorLogs - -->FLOW bol spustený 2O14VBzl8aDmWdNw3A59v9AGyZ5qLJoEMpj6R9ng 2025-08-08 +[2025-10-10T10:49:12.567] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-11T03:49:08.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-11 03:49:08 +[2025-10-12T03:49:08.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-12 03:49:08 +[2025-10-13T03:49:09.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-13 03:49:09 +[2025-10-14T03:49:09.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-14 03:49:09 +[2025-10-15T03:49:09.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-15 03:49:09 +[2025-10-15T11:55:40.112] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-15T11:55:45.449] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-15T11:55:45.454] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-15T11:55:45.455] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-15T11:55:45.456] [INFO] monitorLogs - 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 +} +[2025-10-15T11:55:45.459] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-15T11:55:45.460] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-10-15T11:00:00.459Z +[2025-10-15T11:55:45.461] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-15T11:55:45.462] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-10-15T11:55:45.463] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-15T11:55:45.464] [INFO] monitorLogs - 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 +} +[2025-10-15T11:55:45.465] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-15T11:55:45.466] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-10-15T11:00:00.466Z +[2025-10-15T11:55:45.467] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-15T11:55:45.468] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-10-15T11:55:45.468] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-15T11:55:45.469] [INFO] monitorLogs - 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 +} +[2025-10-15T11:55:45.470] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-15T11:55:45.471] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-10-15T11:00:00.471Z +[2025-10-15T11:55:45.472] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-15T11:55:45.473] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-10-15T11:55:45.475] [INFO] monitorLogs - tasks created: 235 +[2025-10-15T11:55:45.477] [INFO] monitorLogs - -->FLOW bol spustený 2O14VBzl8aDmWdNw3A59v9AGyZ5qLJoEMpj6R9ng 2025-10-08 +[2025-10-15T11:55:50.481] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu diff --git a/RVO36/package-lock.json b/RVO36/package-lock.json new file mode 100755 index 0000000..cc5cfd9 --- /dev/null +++ b/RVO36/package-lock.json @@ -0,0 +1,2125 @@ +{ + "name": "emptyproject", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "emptyproject", + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "bitwise": "^2.1.0", + "easy-crc": "0.0.2", + "jsmodbus": "^4.0.6", + "log4js": "^6.3.0", + "mqtt": "^4.2.6", + "nodemailer": "^6.9.7", + "serialport": "^9.2.8", + "total.js": "^3.4.13" + } + }, + "node_modules/@serialport/binding-abstract": { + "version": "9.2.3", + "resolved": "https://registry.npmjs.org/@serialport/binding-abstract/-/binding-abstract-9.2.3.tgz", + "integrity": "sha512-cQs9tbIlG3P0IrOWyVirqlhWuJ7Ms2Zh9m2108z6Y5UW/iVj6wEOiW8EmK9QX9jmJXYllE7wgGgvVozP5oCj3w==", + "dependencies": { + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/binding-mock": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/binding-mock/-/binding-mock-9.2.4.tgz", + "integrity": "sha512-dpEhACCs44oQhh6ajJfJdvQdK38Vq0N4W6iD/gdplglDCK7qXRQCMUjJIeKdS/HSEiWkC3bwumUhUufdsOyT4g==", + "dependencies": { + "@serialport/binding-abstract": "9.2.3", + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/bindings": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/@serialport/bindings/-/bindings-9.2.8.tgz", + "integrity": "sha512-hSLxTe0tADZ3LMMGwvEJWOC/TaFQTyPeFalUCsJ1lSQ0k6bPF04JwrtB/C81GetmDBTNRY0GlD0SNtKCc7Dr5g==", + "hasInstallScript": true, + "dependencies": { + "@serialport/binding-abstract": "9.2.3", + "@serialport/parser-readline": "9.2.4", + "bindings": "^1.5.0", + "debug": "^4.3.2", + "nan": "^2.15.0", + "prebuild-install": "^7.0.0" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-byte-length": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-byte-length/-/parser-byte-length-9.2.4.tgz", + "integrity": "sha512-sQD/iw4ZMU3xW9PLi0/GlvU6Y623jGeWecbMkO7izUo/6P7gtfv1c9ikd5h0kwL8AoAOpQA1lxdHIKox+umBUg==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-cctalk": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-cctalk/-/parser-cctalk-9.2.4.tgz", + "integrity": "sha512-T4TU5vQMwmo9AB3gQLFDWbfJXlW5jd9guEsB/nqKjFHTv0FXPdZ7DQ2TpSp8RnHWxU3GX6kYTaDO20BKzc8GPQ==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-delimiter": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-delimiter/-/parser-delimiter-9.2.4.tgz", + "integrity": "sha512-4nvTAoYAgkxFiXrkI+3CA49Yd43CODjeszh89EK+I9c8wOZ+etZduRCzINYPiy26g7zO+GRAb9FoPCsY+sYcbQ==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-inter-byte-timeout": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-inter-byte-timeout/-/parser-inter-byte-timeout-9.2.4.tgz", + "integrity": "sha512-SOAdvr0oBQIOCXX198hiTlxs4JTKg9j5piapw5tNq52fwDOWdbYrFneT/wN04UTMKaDrJuEvXq6T4rv4j7nJ5A==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-readline": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-readline/-/parser-readline-9.2.4.tgz", + "integrity": "sha512-Z1/qrZTQUVhNSJP1hd9YfDvq0o7d87rNwAjjRKbVpa7Qi51tG5BnKt43IV3NFMyBlVcRe0rnIb3tJu57E0SOwg==", + "dependencies": { + "@serialport/parser-delimiter": "9.2.4" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-ready": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-ready/-/parser-ready-9.2.4.tgz", + "integrity": "sha512-Pyi94Itjl6qAURwIZr/gmZpMAyTmKXThm6vL5DoAWGQjcRHWB0gwv2TY2v7N+mQLJYUKU3cMnvnATXxHm7xjxw==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-regex": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-regex/-/parser-regex-9.2.4.tgz", + "integrity": "sha512-sI/cVvPOYz+Dbv4ZdnW16qAwvXiFf/1pGASQdbveRTlgJDdz7sRNlCBifzfTN2xljwvCTZYqiudKvDdC1TepRQ==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/stream": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/stream/-/stream-9.2.4.tgz", + "integrity": "sha512-bLye8Ub4vUFQGmkh8qEqehr7SE7EJs2yDs0h9jzuL5oKi+F34CFmWkEErO8GAOQ8YNn7p6b3GxUgs+0BrHHDZQ==", + "dependencies": { + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "node_modules/are-we-there-yet": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", + "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/base64-js": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", + "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==" + }, + "node_modules/bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "dependencies": { + "file-uri-to-path": "1.0.0" + } + }, + "node_modules/bitwise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/bitwise/-/bitwise-2.1.0.tgz", + "integrity": "sha512-XKgAhMXCh4H/3oNwAHAsAO0iC89s9cOiumgYwSHjSobGWxYjv62YhkL9QEdvGP151xypCtMlAfKK79GEcd2eRQ==" + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/bl/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/buffer": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz", + "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==", + "dependencies": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + }, + "node_modules/buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" + }, + "node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, + "node_modules/code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/commist": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/commist/-/commist-1.1.0.tgz", + "integrity": "sha512-rraC8NXWOEjhADbZe9QBNzLAN5Q3fsTPQtBV+fEVj6xKIgDgNiEVE6ZNfHpZOqfQ21YUzfVNUXLOEZquYvQPPg==", + "dependencies": { + "leven": "^2.1.0", + "minimist": "^1.1.0" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "node_modules/concat-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", + "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", + "engines": [ + "node >= 6.0" + ], + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.0.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/concat-stream/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" + }, + "node_modules/core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "node_modules/crc": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/crc/-/crc-3.4.0.tgz", + "integrity": "sha512-ycVC2+4/DLgXXq7QweYi2znhqDuZz6P5TQXnkQo8v15XY/5p/IWeZwsSE31Ifo8w15b8TWLsqhXOjXyilHuQxw==" + }, + "node_modules/date-format": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.11.tgz", + "integrity": "sha512-VS20KRyorrbMCQmpdl2hg5KaOUsda1RbnsJg461FfrcyCUg+pkd0b40BSW4niQyTheww4DBXQnS7HwSrKkipLw==", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" + }, + "node_modules/detect-libc": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz", + "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==", + "engines": { + "node": ">=8" + } + }, + "node_modules/duplexify": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.2.tgz", + "integrity": "sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw==", + "dependencies": { + "end-of-stream": "^1.4.1", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1", + "stream-shift": "^1.0.0" + } + }, + "node_modules/duplexify/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/easy-crc": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/easy-crc/-/easy-crc-0.0.2.tgz", + "integrity": "sha512-h6eqIdhJRe0p271/xZJbM/0klCi13mW5IB7ZEzEGH11yV4QXWAkD4yPErz0fXdhFrd6sZ4Q1k5Iky2kMsMNePw==" + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" + }, + "node_modules/flatted": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", + "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==" + }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, + "node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "node_modules/gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha512-14x4kjc6lkD3ltw589k0NrPD6cCNTD6CWoVUNpB85+DrtONoZn+Rug6xZU5RvSC4+TZPxA5AnBibQYAvZn41Hg==", + "dependencies": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "node_modules/github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==" + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" + }, + "node_modules/has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" + }, + "node_modules/help-me": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/help-me/-/help-me-3.0.0.tgz", + "integrity": "sha512-hx73jClhyk910sidBB7ERlnhMlFsJJIBqSVMFDwPN8o2v9nmp5KgLq1Xz1Bf1fCMMZ6mPrX159iG0VLy/fPMtQ==", + "dependencies": { + "glob": "^7.1.6", + "readable-stream": "^3.6.0" + } + }, + "node_modules/help-me/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, + "node_modules/is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==", + "dependencies": { + "number-is-nan": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "node_modules/js-sdsl": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz", + "integrity": "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/js-sdsl" + } + }, + "node_modules/jsmodbus": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/jsmodbus/-/jsmodbus-4.0.6.tgz", + "integrity": "sha512-gCmjoaERErK5Rn9Lu/BN07fY13MoWV7JKgGzrnkPlQPdPxYcwDhLtYcmpFFpZ4J9NPZZBSezi1UkLZO/DnNppA==", + "dependencies": { + "crc": "3.4.0", + "debug": "^3.1.0" + }, + "bin": { + "jsmodbus": "bin/jsmodbus.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/jsmodbus/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/leven": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", + "integrity": "sha1-wuep93IJTe6dNCAq6KzORoeHVYA=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/log4js": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.5.2.tgz", + "integrity": "sha512-DXtpNtt+KDOMT7RHUDIur/WsSA3rntlUh9Zg4XCdV42wUuMmbFkl38+LZ92Z5QvQA7mD5kAVkLiBSEH/tvUB8A==", + "dependencies": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "flatted": "^3.2.5", + "rfdc": "^1.3.0", + "streamroller": "^3.1.1" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" + }, + "node_modules/mqtt": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/mqtt/-/mqtt-4.3.7.tgz", + "integrity": "sha512-ew3qwG/TJRorTz47eW46vZ5oBw5MEYbQZVaEji44j5lAUSQSqIEoul7Kua/BatBW0H0kKQcC9kwUHa1qzaWHSw==", + "dependencies": { + "commist": "^1.0.0", + "concat-stream": "^2.0.0", + "debug": "^4.1.1", + "duplexify": "^4.1.1", + "help-me": "^3.0.0", + "inherits": "^2.0.3", + "lru-cache": "^6.0.0", + "minimist": "^1.2.5", + "mqtt-packet": "^6.8.0", + "number-allocator": "^1.0.9", + "pump": "^3.0.0", + "readable-stream": "^3.6.0", + "reinterval": "^1.1.0", + "rfdc": "^1.3.0", + "split2": "^3.1.0", + "ws": "^7.5.5", + "xtend": "^4.0.2" + }, + "bin": { + "mqtt": "bin/mqtt.js", + "mqtt_pub": "bin/pub.js", + "mqtt_sub": "bin/sub.js" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/mqtt-packet": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/mqtt-packet/-/mqtt-packet-6.10.0.tgz", + "integrity": "sha512-ja8+mFKIHdB1Tpl6vac+sktqy3gA8t9Mduom1BA75cI+R9AHnZOiaBQwpGiWnaVJLDGRdNhQmFaAqd7tkKSMGA==", + "dependencies": { + "bl": "^4.0.2", + "debug": "^4.1.1", + "process-nextick-args": "^2.0.1" + } + }, + "node_modules/mqtt/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/nan": { + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.16.0.tgz", + "integrity": "sha512-UdAqHyFngu7TfQKsCBgAA6pWDkT8MAO7d0jyOecVhN5354xbLqdn8mV9Tat9gepAupm0bt2DbeaSC8vS52MuFA==" + }, + "node_modules/napi-build-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", + "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==" + }, + "node_modules/node-abi": { + "version": "3.22.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.22.0.tgz", + "integrity": "sha512-u4uAs/4Zzmp/jjsD9cyFYDXeISfUWaAVWshPmDZOFOv4Xl4SbzTXm53I04C2uRueYJ+0t5PEtLH/owbn2Npf/w==", + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/nodemailer": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.7.tgz", + "integrity": "sha512-rUtR77ksqex/eZRLmQ21LKVH5nAAsVicAtAYudK7JgwenEDZ0UIQ1adUGqErz7sMkWYxWTTU1aeP2Jga6WQyJw==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "dependencies": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "node_modules/number-allocator": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/number-allocator/-/number-allocator-1.0.14.tgz", + "integrity": "sha512-OrL44UTVAvkKdOdRQZIJpLkAdjXGTRda052sN4sO77bKEzYYqWKMBjQvrJFzqygI99gL6Z4u2xctPW1tB8ErvA==", + "dependencies": { + "debug": "^4.3.1", + "js-sdsl": "4.3.0" + } + }, + "node_modules/number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/prebuild-install": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.0.tgz", + "integrity": "sha512-CNcMgI1xBypOyGqjp3wOc8AAo1nMhZS3Cwd3iHIxOdAUbb+YxdNuM4Z5iIrZ8RLvOsf3F3bl7b7xGq6DjQoNYA==", + "dependencies": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^1.0.1", + "node-abi": "^3.3.0", + "npmlog": "^4.0.1", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + }, + "bin": { + "prebuild-install": "bin.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/reinterval": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reinterval/-/reinterval-1.1.0.tgz", + "integrity": "sha1-M2Hs+jymwYKDOA3Qu5VG85D17Oc=" + }, + "node_modules/rfdc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==" + }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/serialport": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/serialport/-/serialport-9.2.8.tgz", + "integrity": "sha512-FsWpMQgSJxi93JgWl5xM1f9/Z8IjRJuaUEoHqLf8FPBLw7gMhInuHOBhI2onQufWIYPGTz3H3oGcu1nCaK1EfA==", + "dependencies": { + "@serialport/binding-mock": "9.2.4", + "@serialport/bindings": "9.2.8", + "@serialport/parser-byte-length": "9.2.4", + "@serialport/parser-cctalk": "9.2.4", + "@serialport/parser-delimiter": "9.2.4", + "@serialport/parser-inter-byte-timeout": "9.2.4", + "@serialport/parser-readline": "9.2.4", + "@serialport/parser-ready": "9.2.4", + "@serialport/parser-regex": "9.2.4", + "@serialport/stream": "9.2.4", + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "node_modules/split2": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", + "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", + "dependencies": { + "readable-stream": "^3.0.0" + } + }, + "node_modules/split2/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==" + }, + "node_modules/streamroller": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.1.1.tgz", + "integrity": "sha512-iPhtd9unZ6zKdWgMeYGfSBuqCngyJy1B/GPi/lTpwGpa3bajuX30GjUVd0/Tn/Xhg0mr4DOSENozz9Y06qyonQ==", + "dependencies": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "fs-extra": "^10.1.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dependencies": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/tar-fs": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "dependencies": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tar-stream/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/total.js": { + "version": "3.4.13", + "resolved": "https://registry.npmjs.org/total.js/-/total.js-3.4.13.tgz", + "integrity": "sha512-lAH4gEixlPFbrE3xfKADAcHfO79IFq2wKa9GTsrgRzIR5MTg3mNH7+4IxvX1pK8faoYb/0oYSJ1YTsAa5hIFFQ==", + "bin": { + "total": "bin/totaljs", + "total.js": "bin/totaljs", + "totaljs": "bin/totaljs", + "totalpackage": "bin/tpm", + "tpm": "bin/tpm" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, + "node_modules/universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "node_modules/wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "node_modules/ws": { + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } + }, + "dependencies": { + "@serialport/binding-abstract": { + "version": "9.2.3", + "resolved": "https://registry.npmjs.org/@serialport/binding-abstract/-/binding-abstract-9.2.3.tgz", + "integrity": "sha512-cQs9tbIlG3P0IrOWyVirqlhWuJ7Ms2Zh9m2108z6Y5UW/iVj6wEOiW8EmK9QX9jmJXYllE7wgGgvVozP5oCj3w==", + "requires": { + "debug": "^4.3.2" + } + }, + "@serialport/binding-mock": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/binding-mock/-/binding-mock-9.2.4.tgz", + "integrity": "sha512-dpEhACCs44oQhh6ajJfJdvQdK38Vq0N4W6iD/gdplglDCK7qXRQCMUjJIeKdS/HSEiWkC3bwumUhUufdsOyT4g==", + "requires": { + "@serialport/binding-abstract": "9.2.3", + "debug": "^4.3.2" + } + }, + "@serialport/bindings": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/@serialport/bindings/-/bindings-9.2.8.tgz", + "integrity": "sha512-hSLxTe0tADZ3LMMGwvEJWOC/TaFQTyPeFalUCsJ1lSQ0k6bPF04JwrtB/C81GetmDBTNRY0GlD0SNtKCc7Dr5g==", + "requires": { + "@serialport/binding-abstract": "9.2.3", + "@serialport/parser-readline": "9.2.4", + "bindings": "^1.5.0", + "debug": "^4.3.2", + "nan": "^2.15.0", + "prebuild-install": "^7.0.0" + } + }, + "@serialport/parser-byte-length": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-byte-length/-/parser-byte-length-9.2.4.tgz", + "integrity": "sha512-sQD/iw4ZMU3xW9PLi0/GlvU6Y623jGeWecbMkO7izUo/6P7gtfv1c9ikd5h0kwL8AoAOpQA1lxdHIKox+umBUg==" + }, + "@serialport/parser-cctalk": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-cctalk/-/parser-cctalk-9.2.4.tgz", + "integrity": "sha512-T4TU5vQMwmo9AB3gQLFDWbfJXlW5jd9guEsB/nqKjFHTv0FXPdZ7DQ2TpSp8RnHWxU3GX6kYTaDO20BKzc8GPQ==" + }, + "@serialport/parser-delimiter": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-delimiter/-/parser-delimiter-9.2.4.tgz", + "integrity": "sha512-4nvTAoYAgkxFiXrkI+3CA49Yd43CODjeszh89EK+I9c8wOZ+etZduRCzINYPiy26g7zO+GRAb9FoPCsY+sYcbQ==" + }, + "@serialport/parser-inter-byte-timeout": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-inter-byte-timeout/-/parser-inter-byte-timeout-9.2.4.tgz", + "integrity": "sha512-SOAdvr0oBQIOCXX198hiTlxs4JTKg9j5piapw5tNq52fwDOWdbYrFneT/wN04UTMKaDrJuEvXq6T4rv4j7nJ5A==" + }, + "@serialport/parser-readline": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-readline/-/parser-readline-9.2.4.tgz", + "integrity": "sha512-Z1/qrZTQUVhNSJP1hd9YfDvq0o7d87rNwAjjRKbVpa7Qi51tG5BnKt43IV3NFMyBlVcRe0rnIb3tJu57E0SOwg==", + "requires": { + "@serialport/parser-delimiter": "9.2.4" + } + }, + "@serialport/parser-ready": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-ready/-/parser-ready-9.2.4.tgz", + "integrity": "sha512-Pyi94Itjl6qAURwIZr/gmZpMAyTmKXThm6vL5DoAWGQjcRHWB0gwv2TY2v7N+mQLJYUKU3cMnvnATXxHm7xjxw==" + }, + "@serialport/parser-regex": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-regex/-/parser-regex-9.2.4.tgz", + "integrity": "sha512-sI/cVvPOYz+Dbv4ZdnW16qAwvXiFf/1pGASQdbveRTlgJDdz7sRNlCBifzfTN2xljwvCTZYqiudKvDdC1TepRQ==" + }, + "@serialport/stream": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/stream/-/stream-9.2.4.tgz", + "integrity": "sha512-bLye8Ub4vUFQGmkh8qEqehr7SE7EJs2yDs0h9jzuL5oKi+F34CFmWkEErO8GAOQ8YNn7p6b3GxUgs+0BrHHDZQ==", + "requires": { + "debug": "^4.3.2" + } + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==" + }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "are-we-there-yet": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", + "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "base64-js": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", + "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==" + }, + "bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "requires": { + "file-uri-to-path": "1.0.0" + } + }, + "bitwise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/bitwise/-/bitwise-2.1.0.tgz", + "integrity": "sha512-XKgAhMXCh4H/3oNwAHAsAO0iC89s9cOiumgYwSHjSobGWxYjv62YhkL9QEdvGP151xypCtMlAfKK79GEcd2eRQ==" + }, + "bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "requires": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "buffer": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz", + "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==", + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" + }, + "chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==" + }, + "commist": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/commist/-/commist-1.1.0.tgz", + "integrity": "sha512-rraC8NXWOEjhADbZe9QBNzLAN5Q3fsTPQtBV+fEVj6xKIgDgNiEVE6ZNfHpZOqfQ21YUzfVNUXLOEZquYvQPPg==", + "requires": { + "leven": "^2.1.0", + "minimist": "^1.1.0" + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "concat-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", + "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.0.2", + "typedarray": "^0.0.6" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "crc": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/crc/-/crc-3.4.0.tgz", + "integrity": "sha512-ycVC2+4/DLgXXq7QweYi2znhqDuZz6P5TQXnkQo8v15XY/5p/IWeZwsSE31Ifo8w15b8TWLsqhXOjXyilHuQxw==" + }, + "date-format": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.11.tgz", + "integrity": "sha512-VS20KRyorrbMCQmpdl2hg5KaOUsda1RbnsJg461FfrcyCUg+pkd0b40BSW4niQyTheww4DBXQnS7HwSrKkipLw==" + }, + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "requires": { + "ms": "2.1.2" + } + }, + "decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "requires": { + "mimic-response": "^3.1.0" + } + }, + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==" + }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" + }, + "detect-libc": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz", + "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==" + }, + "duplexify": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.2.tgz", + "integrity": "sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw==", + "requires": { + "end-of-stream": "^1.4.1", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1", + "stream-shift": "^1.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "easy-crc": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/easy-crc/-/easy-crc-0.0.2.tgz", + "integrity": "sha512-h6eqIdhJRe0p271/xZJbM/0klCi13mW5IB7ZEzEGH11yV4QXWAkD4yPErz0fXdhFrd6sZ4Q1k5Iky2kMsMNePw==" + }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "requires": { + "once": "^1.4.0" + } + }, + "expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==" + }, + "file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" + }, + "flatted": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", + "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==" + }, + "fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, + "fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha512-14x4kjc6lkD3ltw589k0NrPD6cCNTD6CWoVUNpB85+DrtONoZn+Rug6xZU5RvSC4+TZPxA5AnBibQYAvZn41Hg==", + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==" + }, + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" + }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" + }, + "help-me": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/help-me/-/help-me-3.0.0.tgz", + "integrity": "sha512-hx73jClhyk910sidBB7ERlnhMlFsJJIBqSVMFDwPN8o2v9nmp5KgLq1Xz1Bf1fCMMZ6mPrX159iG0VLy/fPMtQ==", + "requires": { + "glob": "^7.1.6", + "readable-stream": "^3.6.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==", + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "js-sdsl": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz", + "integrity": "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==" + }, + "jsmodbus": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/jsmodbus/-/jsmodbus-4.0.6.tgz", + "integrity": "sha512-gCmjoaERErK5Rn9Lu/BN07fY13MoWV7JKgGzrnkPlQPdPxYcwDhLtYcmpFFpZ4J9NPZZBSezi1UkLZO/DnNppA==", + "requires": { + "crc": "3.4.0", + "debug": "^3.1.0" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "requires": { + "ms": "^2.1.1" + } + } + } + }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, + "leven": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", + "integrity": "sha1-wuep93IJTe6dNCAq6KzORoeHVYA=" + }, + "log4js": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.5.2.tgz", + "integrity": "sha512-DXtpNtt+KDOMT7RHUDIur/WsSA3rntlUh9Zg4XCdV42wUuMmbFkl38+LZ92Z5QvQA7mD5kAVkLiBSEH/tvUB8A==", + "requires": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "flatted": "^3.2.5", + "rfdc": "^1.3.0", + "streamroller": "^3.1.1" + } + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "requires": { + "yallist": "^4.0.0" + } + }, + "mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==" + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==" + }, + "mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" + }, + "mqtt": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/mqtt/-/mqtt-4.3.7.tgz", + "integrity": "sha512-ew3qwG/TJRorTz47eW46vZ5oBw5MEYbQZVaEji44j5lAUSQSqIEoul7Kua/BatBW0H0kKQcC9kwUHa1qzaWHSw==", + "requires": { + "commist": "^1.0.0", + "concat-stream": "^2.0.0", + "debug": "^4.1.1", + "duplexify": "^4.1.1", + "help-me": "^3.0.0", + "inherits": "^2.0.3", + "lru-cache": "^6.0.0", + "minimist": "^1.2.5", + "mqtt-packet": "^6.8.0", + "number-allocator": "^1.0.9", + "pump": "^3.0.0", + "readable-stream": "^3.6.0", + "reinterval": "^1.1.0", + "rfdc": "^1.3.0", + "split2": "^3.1.0", + "ws": "^7.5.5", + "xtend": "^4.0.2" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "mqtt-packet": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/mqtt-packet/-/mqtt-packet-6.10.0.tgz", + "integrity": "sha512-ja8+mFKIHdB1Tpl6vac+sktqy3gA8t9Mduom1BA75cI+R9AHnZOiaBQwpGiWnaVJLDGRdNhQmFaAqd7tkKSMGA==", + "requires": { + "bl": "^4.0.2", + "debug": "^4.1.1", + "process-nextick-args": "^2.0.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "nan": { + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.16.0.tgz", + "integrity": "sha512-UdAqHyFngu7TfQKsCBgAA6pWDkT8MAO7d0jyOecVhN5354xbLqdn8mV9Tat9gepAupm0bt2DbeaSC8vS52MuFA==" + }, + "napi-build-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", + "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==" + }, + "node-abi": { + "version": "3.22.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.22.0.tgz", + "integrity": "sha512-u4uAs/4Zzmp/jjsD9cyFYDXeISfUWaAVWshPmDZOFOv4Xl4SbzTXm53I04C2uRueYJ+0t5PEtLH/owbn2Npf/w==", + "requires": { + "semver": "^7.3.5" + } + }, + "nodemailer": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.7.tgz", + "integrity": "sha512-rUtR77ksqex/eZRLmQ21LKVH5nAAsVicAtAYudK7JgwenEDZ0UIQ1adUGqErz7sMkWYxWTTU1aeP2Jga6WQyJw==" + }, + "npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "number-allocator": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/number-allocator/-/number-allocator-1.0.14.tgz", + "integrity": "sha512-OrL44UTVAvkKdOdRQZIJpLkAdjXGTRda052sN4sO77bKEzYYqWKMBjQvrJFzqygI99gL6Z4u2xctPW1tB8ErvA==", + "requires": { + "debug": "^4.3.1", + "js-sdsl": "4.3.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==" + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==" + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==" + }, + "prebuild-install": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.0.tgz", + "integrity": "sha512-CNcMgI1xBypOyGqjp3wOc8AAo1nMhZS3Cwd3iHIxOdAUbb+YxdNuM4Z5iIrZ8RLvOsf3F3bl7b7xGq6DjQoNYA==", + "requires": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^1.0.1", + "node-abi": "^3.3.0", + "npmlog": "^4.0.1", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + } + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + } + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "reinterval": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reinterval/-/reinterval-1.1.0.tgz", + "integrity": "sha1-M2Hs+jymwYKDOA3Qu5VG85D17Oc=" + }, + "rfdc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==" + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "requires": { + "lru-cache": "^6.0.0" + } + }, + "serialport": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/serialport/-/serialport-9.2.8.tgz", + "integrity": "sha512-FsWpMQgSJxi93JgWl5xM1f9/Z8IjRJuaUEoHqLf8FPBLw7gMhInuHOBhI2onQufWIYPGTz3H3oGcu1nCaK1EfA==", + "requires": { + "@serialport/binding-mock": "9.2.4", + "@serialport/bindings": "9.2.8", + "@serialport/parser-byte-length": "9.2.4", + "@serialport/parser-cctalk": "9.2.4", + "@serialport/parser-delimiter": "9.2.4", + "@serialport/parser-inter-byte-timeout": "9.2.4", + "@serialport/parser-readline": "9.2.4", + "@serialport/parser-ready": "9.2.4", + "@serialport/parser-regex": "9.2.4", + "@serialport/stream": "9.2.4", + "debug": "^4.3.2" + } + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==" + }, + "simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "requires": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "split2": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", + "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", + "requires": { + "readable-stream": "^3.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==" + }, + "streamroller": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.1.1.tgz", + "integrity": "sha512-iPhtd9unZ6zKdWgMeYGfSBuqCngyJy1B/GPi/lTpwGpa3bajuX30GjUVd0/Tn/Xhg0mr4DOSENozz9Y06qyonQ==", + "requires": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "fs-extra": "^10.1.0" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" + }, + "tar-fs": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "requires": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "requires": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "total.js": { + "version": "3.4.13", + "resolved": "https://registry.npmjs.org/total.js/-/total.js-3.4.13.tgz", + "integrity": "sha512-lAH4gEixlPFbrE3xfKADAcHfO79IFq2wKa9GTsrgRzIR5MTg3mNH7+4IxvX1pK8faoYb/0oYSJ1YTsAa5hIFFQ==" + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, + "universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==" + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "requires": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "ws": { + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "requires": {} + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } + } +} diff --git a/RVO36/package.json b/RVO36/package.json new file mode 100755 index 0000000..e524d7c --- /dev/null +++ b/RVO36/package.json @@ -0,0 +1,29 @@ +{ + "name": "emptyproject", + "description": "Total.js empty project.", + "version": "1.0.0", + "main": "debug.js", + "dependencies": { + "bitwise": "^2.1.0", + "easy-crc": "0.0.2", + "jsmodbus": "^4.0.6", + "log4js": "^6.3.0", + "mqtt": "^4.2.6", + "nodemailer": "^6.9.7", + "serialport": "^9.2.8", + "total.js": "^3.4.13" + }, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "https://github.com/totaljs/emptyproject-flow" + }, + "keywords": [ + "empty", + "project" + ], + "author": "Peter Širka", + "license": "MIT" +} diff --git a/RVO36/release.js b/RVO36/release.js new file mode 100755 index 0000000..02d52ff --- /dev/null +++ b/RVO36/release.js @@ -0,0 +1,15 @@ +// =================================================== +// FOR PRODUCTION +// Total.js - framework for Node.js platform +// https://www.totaljs.com +// =================================================== + +const options = {'ip':'0.0.0.0', 'port':12345}; + +// options.ip = '127.0.0.1'; +// options.port = parseInt(process.argv[2]); +// options.config = { name: 'Total.js' }; +// options.sleep = 3000; + +require('total.js').http('release', options); +// require('total.js').cluster.http(5, 'release', options); diff --git a/RVO36/release.js.json b/RVO36/release.js.json new file mode 100755 index 0000000..6c138e8 --- /dev/null +++ b/RVO36/release.js.json @@ -0,0 +1,34 @@ +{ + "pid": 382, + "stats": [ + { + "id": null, + "version": { + "node": "v14.18.1", + "total": "3.4.13", + "app": "1.0.0" + }, + "pid": 382, + "thread": "", + "mode": "release", + "overload": 0, + "date": "2025-10-16T00:25:36.207Z", + "memory": 23.98, + "rm": 0, + "fm": 0, + "wm": 0, + "mm": 0, + "om": 0, + "em": 0, + "dbrm": 0, + "dbwm": 0, + "usage": 0, + "requests": 7, + "pending": 0, + "errors": 0, + "timeouts": 0, + "uptime": 871, + "online": 0 + } + ] +} \ No newline at end of file diff --git a/RVO36/report_data.log b/RVO36/report_data.log new file mode 100755 index 0000000..5fcc3c8 --- /dev/null +++ b/RVO36/report_data.log @@ -0,0 +1,211 @@ +{ + "name": "rvo_senica_36_10.0.0.138", + "time": "2025-10-15T10:55:51.092Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_36_10.0.0.138", + "time": "2025-10-15T12:00:01.235Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_36_10.0.0.138", + "time": "2025-10-15T13:00:01.235Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_36_10.0.0.138", + "time": "2025-10-15T14:00:01.237Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_36_10.0.0.138", + "time": "2025-10-15T15:00:01.237Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_36_10.0.0.138", + "time": "2025-10-15T16:00:01.237Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_36_10.0.0.138", + "time": "2025-10-15T17:00:01.237Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_36_10.0.0.138", + "time": "2025-10-15T18:00:01.238Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_36_10.0.0.138", + "time": "2025-10-15T19:00:01.238Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_36_10.0.0.138", + "time": "2025-10-15T20:00:01.239Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_36_10.0.0.138", + "time": "2025-10-15T21:00:01.239Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_36_10.0.0.138", + "time": "2025-10-15T22:00:01.239Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_36_10.0.0.138", + "time": "2025-10-15T23:00:01.239Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_36_10.0.0.138", + "time": "2025-10-16T00:00:01.239Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +} \ No newline at end of file From 301ca1d97b121fb728786b700296fc3dc2ae582a Mon Sep 17 00:00:00 2001 From: Jakub Klena Date: Thu, 16 Oct 2025 02:26:04 +0200 Subject: [PATCH 19/30] Backup senica-RVO37 on 16.10.2025 --- RVO37/addSwitch.py | 36 + RVO37/cloud_topic.py | 76 + RVO37/config | 12 + RVO37/createNode.py | 43 + RVO37/databases/accelerometer_db.js | 3055 ++++++++++++++++ RVO37/databases/modbus_config.js | 114 + RVO37/databases/nodes.table | 49 + .../nodes_original/nodes_original.table | 1 + RVO37/databases/notifications.table | 41 + RVO37/databases/pins.table | 14 + RVO37/databases/relays.table | 5 + RVO37/databases/settings.table | 2 + RVO37/databases/tbdata.nosql | 4 + RVO37/databases/tbdatacloud.nosql | 3 + RVO37/databases/total_energy.js | 38 + RVO37/debug.js | 16 + RVO37/err.txt | 0 RVO37/flow/cloudmqttconnect.js | 357 ++ RVO37/flow/cmd_manager.js | 3071 ++++++++++++++++ RVO37/flow/code.js | 90 + RVO37/flow/comment.js | 11 + RVO37/flow/count.js | 60 + RVO37/flow/db_connector.js | 286 ++ RVO37/flow/db_init.js | 113 + RVO37/flow/debug.js | 100 + RVO37/flow/designer.json | 3102 +++++++++++++++++ RVO37/flow/dido_controller.js | 1486 ++++++++ RVO37/flow/helper/DataToTbHandler.js | 187 + RVO37/flow/helper/ErrorToServiceHandler.js | 91 + RVO37/flow/helper/db_helper.js | 44 + RVO37/flow/helper/logger.js | 30 + RVO37/flow/helper/md5.js | 5 + RVO37/flow/helper/notification_reporter.js | 121 + RVO37/flow/helper/register.js | 144 + RVO37/flow/helper/serialport_helper.js | 99 + RVO37/flow/helper/suncalc.js | 317 ++ RVO37/flow/helper/utils.js | 161 + RVO37/flow/httprequest.js | 137 + RVO37/flow/httpresponse.js | 76 + RVO37/flow/httproute.js | 326 ++ RVO37/flow/infosender.js | 81 + RVO37/flow/modbus_reader.js | 346 ++ RVO37/flow/monitorconsumption.js | 156 + RVO37/flow/monitordisk.js | 96 + RVO37/flow/monitormemory.js | 87 + RVO37/flow/nodesdb_changecheck.js | 77 + RVO37/flow/show_dbdata.js | 243 ++ RVO37/flow/slack_filter.js | 188 + RVO37/flow/thermometer.js | 99 + RVO37/flow/trigger.js | 79 + RVO37/flow/variables.txt | 0 RVO37/flow/virtualwirein.js | 43 + RVO37/flow/virtualwireout.js | 41 + RVO37/flow/wsmqttpublish.js | 448 +++ RVO37/monitor.txt | 315 ++ RVO37/package-lock.json | 2139 ++++++++++++ RVO37/package.json | 30 + RVO37/release.js | 15 + RVO37/release.js.json | 34 + RVO37/report_data.log | 165 + 60 files changed, 18605 insertions(+) create mode 100755 RVO37/addSwitch.py create mode 100755 RVO37/cloud_topic.py create mode 100755 RVO37/config create mode 100755 RVO37/createNode.py create mode 100755 RVO37/databases/accelerometer_db.js create mode 100755 RVO37/databases/modbus_config.js create mode 100755 RVO37/databases/nodes.table create mode 100755 RVO37/databases/nodes_original/nodes_original.table create mode 100755 RVO37/databases/notifications.table create mode 100755 RVO37/databases/pins.table create mode 100755 RVO37/databases/relays.table create mode 100755 RVO37/databases/settings.table create mode 100755 RVO37/databases/tbdata.nosql create mode 100755 RVO37/databases/tbdatacloud.nosql create mode 100755 RVO37/databases/total_energy.js create mode 100755 RVO37/debug.js create mode 100755 RVO37/err.txt create mode 100755 RVO37/flow/cloudmqttconnect.js create mode 100755 RVO37/flow/cmd_manager.js create mode 100755 RVO37/flow/code.js create mode 100755 RVO37/flow/comment.js create mode 100755 RVO37/flow/count.js create mode 100755 RVO37/flow/db_connector.js create mode 100755 RVO37/flow/db_init.js create mode 100755 RVO37/flow/debug.js create mode 100755 RVO37/flow/designer.json create mode 100755 RVO37/flow/dido_controller.js create mode 100755 RVO37/flow/helper/DataToTbHandler.js create mode 100755 RVO37/flow/helper/ErrorToServiceHandler.js create mode 100755 RVO37/flow/helper/db_helper.js create mode 100755 RVO37/flow/helper/logger.js create mode 100755 RVO37/flow/helper/md5.js create mode 100755 RVO37/flow/helper/notification_reporter.js create mode 100755 RVO37/flow/helper/register.js create mode 100755 RVO37/flow/helper/serialport_helper.js create mode 100755 RVO37/flow/helper/suncalc.js create mode 100755 RVO37/flow/helper/utils.js create mode 100755 RVO37/flow/httprequest.js create mode 100755 RVO37/flow/httpresponse.js create mode 100755 RVO37/flow/httproute.js create mode 100755 RVO37/flow/infosender.js create mode 100755 RVO37/flow/modbus_reader.js create mode 100755 RVO37/flow/monitorconsumption.js create mode 100755 RVO37/flow/monitordisk.js create mode 100755 RVO37/flow/monitormemory.js create mode 100755 RVO37/flow/nodesdb_changecheck.js create mode 100755 RVO37/flow/show_dbdata.js create mode 100755 RVO37/flow/slack_filter.js create mode 100755 RVO37/flow/thermometer.js create mode 100755 RVO37/flow/trigger.js create mode 100755 RVO37/flow/variables.txt create mode 100755 RVO37/flow/virtualwirein.js create mode 100755 RVO37/flow/virtualwireout.js create mode 100755 RVO37/flow/wsmqttpublish.js create mode 100755 RVO37/monitor.txt create mode 100755 RVO37/package-lock.json create mode 100755 RVO37/package.json create mode 100755 RVO37/release.js create mode 100755 RVO37/release.js.json create mode 100755 RVO37/report_data.log diff --git a/RVO37/addSwitch.py b/RVO37/addSwitch.py new file mode 100755 index 0000000..c35e96b --- /dev/null +++ b/RVO37/addSwitch.py @@ -0,0 +1,36 @@ +import os + +def process_set_file(): + """ + Checks if /root/flowserver exists, reads set.txt, and modifies the second line. + """ + default_folder = "/root/flowserver" if os.path.exists("/root/flowserver") else "/home/unipi/flowserver" + flag = 1 if default_folder == "/root/flowserver" else 0 + + try: + with open("/home/unipi/flowserver/databases/settings.table", "r") as f: + lines = f.readlines() + + if len(lines) >= 2: + lines[0] = lines[0].rstrip('\n') + "|main_switch:boolean\n" + second_line = lines[1].strip() # remove trailing newline + last_pipe_index = second_line.rfind("|") + + if last_pipe_index != -1: + modified_line = second_line[:last_pipe_index + 1] + str(flag) + "|" + second_line[last_pipe_index + 1:] + lines[1] = modified_line + else: + print("Warning: No '|' character found in the second line of set.txt") + + with open("/home/unipi/flowserver/databases/settings.table", "w") as f: + f.writelines(lines) + else: + print("Warning: settings.table has less than two lines.") + + except FileNotFoundError: + print("Error: settings.table not found.") + except Exception as e: + print(e) + +# if __name__ == "__main__": +process_set_file() diff --git a/RVO37/cloud_topic.py b/RVO37/cloud_topic.py new file mode 100755 index 0000000..77c31f1 --- /dev/null +++ b/RVO37/cloud_topic.py @@ -0,0 +1,76 @@ +# import os +# +# def modify_file(file_path): +# """ +# Modifies the given file by: +# 1. Appending "|cloud_topic" to the first line. +# 2. Inserting the text from the third "." to the first "|" on the second line after the last "|" character. +# +# Args: +# file_path (str): The path to the file to be modified. +# """ +# +# with open(file_path, 'r+') as f: +# lines = f.readlines() +# +# # Modify the first line +# lines[0] += "|cloud_topic:string" +# +# # Modify the second line +# second_line = lines[1].strip() # Remove leading/trailing whitespace +# first_pipe_index = second_line.find('|') +# third_dot_index = second_line.find('.', second_line.find('.', second_line.find('.') + 1) + 1) +# text_to_insert = second_line[third_dot_index:first_pipe_index] +# +# last_pipe_index = second_line.rfind('|') +# lines[1] = second_line[:last_pipe_index + 1] + text_to_insert + "|" + second_line[last_pipe_index + 1:] +# +# print(first_pipe_index, third_dot_index, text_to_insert, last_pipe_index) +# # Write the modified lines back to the file +# # f.seek(0) +# # f.writelines(lines) +# # f.truncate() +# +# # Example usage: +# file_path = "settings.table" # Replace with the actual file path +# modify_file(file_path) +# + + +def modify_file(file_path): + """ + Modifies the given file by: + 1. Appending "|cloud_topic" to the first line. + 2. Inserting the text between the third "." and the second "|" on the second line after the last "|" character. + + Args: + file_path (str): The path to the file to be modified. + """ + + with open(file_path, 'r+') as f: + lines = f.readlines() + + first_line = lines[0].strip() + first_line += "|cloud_topic:string\n" + # Modify the first line + lines[0] = first_line + + # Modify the second line + second_line = lines[1].strip() # Remove leading/trailing whitespace + first_pipe_index = second_line.find('|') + second_pipe_index = second_line.find('|', first_pipe_index + 1) + third_dot_index = second_line.find('.', second_line.find('.', second_line.find('.') + 1) + 1) + text_to_insert = "u" + second_line[third_dot_index+1:second_pipe_index] + + last_pipe_index = second_line.rfind('|') + lines[1] = second_line[:last_pipe_index + 1] + text_to_insert + "|" + second_line[last_pipe_index + 1:] + + print(first_pipe_index, third_dot_index, text_to_insert, last_pipe_index) + # Write the modified lines back to the file + f.seek(0) + f.writelines(lines) + f.truncate() + +# Example usage: +file_path = "/home/unipi/flowserver/databases/settings.table" # Replace with the actual file path +modify_file(file_path) diff --git a/RVO37/config b/RVO37/config new file mode 100755 index 0000000..cd0a8a9 --- /dev/null +++ b/RVO37/config @@ -0,0 +1,12 @@ +name : Total.js Flow +default_timezone : Europe/Bratislava + +// Packages settings +package#flow (Object) : { url: '/' } + + +table.relays : line:number|tbname:string|contactor:number|profile:string +table.nodes : node:number|pole_number:string|node_type:string|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|project_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|cloud_topic:string|has_main_switch:boolean|daily_report:boolean|send_changed_node_numbers:boolean +table.pins : pin:string|type:string|line:number +table.notifications : key:string|weight:string|sk:string|en:string diff --git a/RVO37/createNode.py b/RVO37/createNode.py new file mode 100755 index 0000000..a8cea91 --- /dev/null +++ b/RVO37/createNode.py @@ -0,0 +1,43 @@ +print("zaciname") +import re, json + +search_str = '|' +final = [] +counter = 1 +with open("/home/unipi/flowserver/databases/nodes.table", 'r') as file: +# with open("/home/rasta5man/dev/oms/flowserver/databases/nodes.table", 'r') as file: + # Read each line in the file + for line in file: + # Print each line + line = line.strip() + print(line) + if counter != 1: + i = [m.start() for m in re.finditer(re.escape(search_str), line)] + node = line[ i[0] + 1 : i[1] ] + tbname = line[ i[3] + 1 : i[4] ] + final.append({node:tbname}) + counter += 1 +print(json.dumps(final)) +f = open("/home/unipi/flowserver/databases/nodes_original/nodes_original.table", "w") +f.write(json.dumps(final)) +f.close() + + +# +# # ``d`` has to be replaced with a different character +# old_character = "'" +# +# # ``t`` will replace ``d` +# new_character = '"' +# resultant_string = 0; +# with open("/home/unipi/flowserver/databases/nodes_original/nodes_original.table", 'r') as file: +# for line in file: +# resultant_string = re.sub("'", '"', line) +# +# resultant_string = re.sub(" ", "", resultant_string) +# print(resultant_string) +# +# f = open("/home/unipi/flowserver/databases/nodes_original/nodes_original.table", "w") +# f.write(str(resultant_string)) +# f.close() +# diff --git a/RVO37/databases/accelerometer_db.js b/RVO37/databases/accelerometer_db.js new file mode 100755 index 0000000..fdfc7fd --- /dev/null +++ b/RVO37/databases/accelerometer_db.js @@ -0,0 +1,3055 @@ +let naklony = { + "3993": { "label": "1/3A", "naklon": 0 }, + "3989": { "label": "1/3B", "naklon": 15 }, + "3976": { "label": "1/1", "naklon": 0 }, + "4181": { "label": "1/2", "naklon": 0 }, + "4376": { "label": "1/4", "naklon": 15 }, + "3868": { "label": "1/5", "naklon": 15 }, + "3728": { "label": "1/6", "naklon": 15 }, + "3730": { "label": "1/7", "naklon": 0 }, + "4374": { "label": "1/8", "naklon": 0 }, + "3718": { "label": "1/9", "naklon": 15 }, + "4375": { "label": "1/10", "naklon": 15 }, + "4172": { "label": "1/11", "naklon": 15 }, + "4176": { "label": "1/12", "naklon": 15 }, + "3800": { "label": "2/1", "naklon": 5 }, + "3823": { "label": "2/2", "naklon": 5 }, + "3905": { "label": "2/3", "naklon": 5 }, + "3803": { "label": "2/4", "naklon": 5 }, + "3817": { "label": "2/5", "naklon": 5 }, + "3818": { "label": "2/6", "naklon": 5 }, + "3811": { "label": "2/7", "naklon": 5 }, + "3915": { "label": "2/8", "naklon": 5 }, + "3843": { "label": "2/9", "naklon": 10 }, + "3827": { "label": "2/10", "naklon": 10 }, + "4220": { "label": "2/11", "naklon": 10 }, + "3826": { "label": "2/12", "naklon": 10 }, + "3834": { "label": "2/13", "naklon": 10 }, + "3838": { "label": "2/14", "naklon": 10 }, + "2823": { "label": "2/15", "naklon": 10 }, + "3750": { "label": "2/16", "naklon": 10 }, + "3378": { "label": "2/17", "naklon": 0 }, + "3376": { "label": "2/18", "naklon": 0 }, + "3379": { "label": "2/19", "naklon": 0 }, + "3285": { "label": "2/20", "naklon": 0 }, + "3382": { "label": "2/21", "naklon": 0 }, + "3383": { "label": "2/22", "naklon": 0 }, + "3375": { "label": "2/24", "naklon": 0 }, + "3381": { "label": "2/25", "naklon": 0 }, + "3380": { "label": "2/26", "naklon": 0 }, + "3828": { "label": "2/27", "naklon": 10 }, + "3377": { "label": "2/28", "naklon": 0 }, + "3591": { "label": "7/1", "naklon": 0 }, + "3587": { "label": "7/2", "naklon": 0 }, + "3468": { "label": "7/3", "naklon": 0 }, + "3466": { "label": "7/4", "naklon": 0 }, + "3474": { "label": "7/5", "naklon": 0 }, + "3481": { "label": "7/6", "naklon": 0 }, + "3589": { "label": "7/7", "naklon": 0 }, + "3472": { "label": "7/8", "naklon": 0 }, + "3473": { "label": "7/9", "naklon": 0 }, + "3584": { "label": "7/10", "naklon": 0 }, + "3571": { "label": "7/11", "naklon": 0 }, + "3476": { "label": "7/12", "naklon": 0 }, + "3590": { "label": "7/13", "naklon": 0 }, + "3478": { "label": "7/14", "naklon": 0 }, + "3471": { "label": "7/15", "naklon": 0 }, + "3467": { "label": "7/16", "naklon": 0 }, + "3479": { "label": "7/17", "naklon": 0 }, + "3480": { "label": "7/18", "naklon": 0 }, + "3477": { "label": "7/19", "naklon": 0 }, + "3362": { "label": "12/1", "naklon": 0 }, + "3355": { "label": "12/2", "naklon": 0 }, + "3356": { "label": "12/3", "naklon": 0 }, + "3349": { "label": "12/4", "naklon": 0 }, + "3357": { "label": "12/5", "naklon": 0 }, + "3350": { "label": "12/6", "naklon": 0 }, + "3353": { "label": "12/7", "naklon": 0 }, + "3539": { "label": "12/8", "naklon": 0 }, + "3050": { "label": "12/9", "naklon": 0 }, + "3361": { "label": "12/10", "naklon": 0 }, + "3360": { "label": "12/11", "naklon": 0 }, + "3358": { "label": "12/12", "naklon": 0 }, + "3541": { "label": "12/13", "naklon": 0 }, + "3551": { "label": "12/14", "naklon": 0 }, + "3514": { "label": "12/15", "naklon": 0 }, + "3547": { "label": "12/16", "naklon": 0 }, + "3562": { "label": "12/17", "naklon": 0 }, + "3525": { "label": "12/18", "naklon": 0 }, + "3558": { "label": "12/19", "naklon": 0 }, + "3511": { "label": "12/20", "naklon": 0 }, + "3058": { "label": "12/21", "naklon": 0 }, + "3062": { "label": "12/22", "naklon": 0 }, + "3070": { "label": "12/23", "naklon": 0 }, + "3447": { "label": "12/24", "naklon": 0 }, + "3056": { "label": "12/25", "naklon": 0 }, + "3057": { "label": "12/26", "naklon": 0 }, + "3071": { "label": "12/27", "naklon": 0 }, + "3061": { "label": "12/28", "naklon": 0 }, + "3069": { "label": "12/29", "naklon": 0 }, + "3077": { "label": "12/30", "naklon": 0 }, + "3080": { "label": "12/31", "naklon": 0 }, + "3081": { "label": "12/32", "naklon": 0 }, + "3078": { "label": "12/33", "naklon": 0 }, + "4037": { "label": "12/34", "naklon": 0 }, + "3067": { "label": "12/35", "naklon": 0 }, + "3051": { "label": "12/36", "naklon": 0 }, + "2924": { "label": "12/37", "naklon": 0 }, + "3060": { "label": "12/38", "naklon": 0 }, + "3073": { "label": "12/39", "naklon": 0 }, + "3469": { "label": "12/40", "naklon": 0 }, + "2923": { "label": "12/41", "naklon": 0 }, + "2925": { "label": "12/42", "naklon": 0 }, + "3359": { "label": "12/43", "naklon": 0 }, + "3055": { "label": "12/44", "naklon": 0 }, + "2922": { "label": "12/45", "naklon": 0 }, + "3084": { "label": "12/46", "naklon": 0 }, + "3064": { "label": "12/47", "naklon": 0 }, + "3066": { "label": "12/48", "naklon": 0 }, + "3072": { "label": "12/49", "naklon": 0 }, + "3415": { "label": "13/13A", "naklon": 0 }, + "3409": { "label": "13/13B", "naklon": 0 }, + "3399": { "label": "13/13C", "naklon": 0 }, + "3410": { "label": "13/29A", "naklon": 0 }, + "3407": { "label": "13/29B", "naklon": 0 }, + "3405": { "label": "13/34A", "naklon": 0 }, + "3404": { "label": "13/34B", "naklon": 0 }, + "3392": { "label": "13/45A", "naklon": 0 }, + "3386": { "label": "13/45B", "naklon": 0 }, + "3303": { "label": "13/60A", "naklon": 3 }, + "3302": { "label": "13/60B", "naklon": 3 }, + "3319": { "label": "13/70A", "naklon": 6 }, + "3317": { "label": "13/70B", "naklon": 6 }, + "3326": { "label": "13/70C", "naklon": 6 }, + "3351": { "label": "13/73A", "naklon": 6 }, + "3313": { "label": "13/73B", "naklon": 6 }, + "3316": { "label": "13/83A", "naklon": 0 }, + "3320": { "label": "13/83B", "naklon": 0 }, + "3336": { "label": "13/95A", "naklon": 0 }, + "3323": { "label": "13/95B", "naklon": 0 }, + "3339": { "label": "13/98A", "naklon": 0 }, + "3333": { "label": "13/98B", "naklon": 0 }, + "3425": { "label": "13/1", "naklon": 0 }, + "3419": { "label": "13/2", "naklon": 0 }, + "3416": { "label": "13/3", "naklon": 0 }, + "3332": { "label": "13/4", "naklon": 0 }, + "3422": { "label": "13/5", "naklon": 0 }, + "3417": { "label": "13/6", "naklon": 0 }, + "3418": { "label": "13/7", "naklon": 0 }, + "3424": { "label": "13/8", "naklon": 0 }, + "3334": { "label": "13/9", "naklon": 0 }, + "4363": { "label": "13/10", "naklon": 0 }, + "3423": { "label": "13/11", "naklon": 0 }, + "3406": { "label": "13/12", "naklon": 0 }, + "3411": { "label": "13/14", "naklon": 0 }, + "3412": { "label": "13/15", "naklon": 0 }, + "3413": { "label": "13/16", "naklon": 0 }, + "3414": { "label": "13/17", "naklon": 0 }, + "3391": { "label": "13/18", "naklon": 0 }, + "3370": { "label": "13/19", "naklon": 0 }, + "3369": { "label": "13/20", "naklon": 0 }, + "3408": { "label": "13/21", "naklon": 0 }, + "3393": { "label": "13/22", "naklon": 0 }, + "3128": { "label": "13/23", "naklon": 0 }, + "3197": { "label": "13/24", "naklon": 0 }, + "4364": { "label": "13/25", "naklon": 0 }, + "3155": { "label": "13/26", "naklon": 0 }, + "3196": { "label": "13/27", "naklon": 0 }, + "3144": { "label": "13/28", "naklon": 0 }, + "3150": { "label": "13/30", "naklon": 0 }, + "3390": { "label": "13/31", "naklon": 0 }, + "3401": { "label": "13/32", "naklon": 0 }, + "3275": { "label": "13/33", "naklon": 0 }, + "3371": { "label": "13/35", "naklon": 0 }, + "3389": { "label": "13/36", "naklon": 0 }, + "3388": { "label": "13/37", "naklon": 0 }, + "3365": { "label": "13/38", "naklon": 0 }, + "3363": { "label": "13/39", "naklon": 0 }, + "3397": { "label": "13/40", "naklon": 0 }, + "3567": { "label": "13/40/1", "naklon": 0 }, + "3387": { "label": "13/41", "naklon": 0 }, + "3403": { "label": "13/42", "naklon": 0 }, + "3147": { "label": "13/43", "naklon": 0 }, + "3141": { "label": "13/44", "naklon": 0 }, + "3364": { "label": "13/46", "naklon": 0 }, + "3367": { "label": "13/47", "naklon": 0 }, + "3368": { "label": "13/48", "naklon": 0 }, + "3402": { "label": "13/49", "naklon": 0 }, + "3366": { "label": "13/50", "naklon": 0 }, + "3395": { "label": "13/51", "naklon": 0 }, + "3372": { "label": "13/52", "naklon": 0 }, + "3394": { "label": "13/53", "naklon": 0 }, + "3308": { "label": "13/54", "naklon": 0 }, + "3847": { "label": "13/54/1", "naklon": 0 }, + "3312": { "label": "13/55", "naklon": 3 }, + "3309": { "label": "13/56", "naklon": 3 }, + "3311": { "label": "13/57", "naklon": 3 }, + "3310": { "label": "13/58", "naklon": 3 }, + "4365": { "label": "13/59", "naklon": 3 }, + "4093": { "label": "13/60/1", "naklon": 3 }, + "3304": { "label": "13/61", "naklon": 3 }, + "3307": { "label": "13/62", "naklon": 3 }, + "3271": { "label": "13/63", "naklon": 3 }, + "3301": { "label": "13/64", "naklon": 3 }, + "4366": { "label": "13/65", "naklon": 3 }, + "3300": { "label": "13/66", "naklon": 3 }, + "3185": { "label": "13/67", "naklon": 0 }, + "3184": { "label": "13/68", "naklon": 0 }, + "3188": { "label": "13/69", "naklon": 0 }, + "3343": { "label": "13/71", "naklon": 6 }, + "3819": { "label": "13/71/1", "naklon": 6 }, + "3880": { "label": "13/71/2", "naklon": 6 }, + "3348": { "label": "13/72", "naklon": 6 }, + "3344": { "label": "13/74", "naklon": 6 }, + "3346": { "label": "13/75", "naklon": 6 }, + "3597": { "label": "13/75/1", "naklon": 6 }, + "3345": { "label": "13/76", "naklon": 6 }, + "3322": { "label": "13/77", "naklon": 0 }, + "3325": { "label": "13/78", "naklon": 0 }, + "4310": { "label": "13/78/1", "naklon": 0 }, + "3315": { "label": "13/79", "naklon": 0 }, + "3328": { "label": "13/80", "naklon": 0 }, + "3321": { "label": "13/81", "naklon": 0 }, + "3324": { "label": "13/82", "naklon": 0 }, + "3140": { "label": "13/84", "naklon": 0 }, + "3153": { "label": "13/85", "naklon": 0 }, + "3145": { "label": "13/86", "naklon": 0 }, + "3134": { "label": "13/87", "naklon": 0 }, + "3151": { "label": "13/88", "naklon": 0 }, + "3143": { "label": "13/89", "naklon": 0 }, + "3318": { "label": "13/90", "naklon": 0 }, + "3347": { "label": "13/91", "naklon": 0 }, + "3314": { "label": "13/94", "naklon": 0 }, + "3331": { "label": "13/96", "naklon": 0 }, + "3327": { "label": "13/97", "naklon": 0 }, + "3329": { "label": "13/99", "naklon": 0 }, + "3337": { "label": "13/100", "naklon": 0 }, + "3330": { "label": "13/101", "naklon": 0 }, + "3335": { "label": "13/102", "naklon": 0 }, + "3420": { "label": "13/103", "naklon": 0 }, + "3421": { "label": "13/104", "naklon": 0 }, + "4361": { "label": "13/105", "naklon": 0 }, + "4362": { "label": "13/106", "naklon": 0 }, + "3526": { "label": "13/107", "naklon": 0 }, + "4424": { "label": "13/108", "naklon": null }, + "3561": { "label": "13/109", "naklon": null }, + "3527": { "label": "13/110", "naklon": null }, + "3521": { "label": "13/111", "naklon": null }, + "3552": { "label": "13/112", "naklon": null }, + "3544": { "label": "13/113", "naklon": null }, + "3534": { "label": "13/114", "naklon": null }, + "3516": { "label": "13/115", "naklon": null }, + "3513": { "label": "13/116", "naklon": null }, + "3565": { "label": "13/117", "naklon": null }, + "3866": { "label": "13/118", "naklon": null }, + "3136": { "label": "14/1", "naklon": 0 }, + "3137": { "label": "14/2", "naklon": 0 }, + "3135": { "label": "14/3", "naklon": 0 }, + "3149": { "label": "14/4", "naklon": 0 }, + "3142": { "label": "14/5", "naklon": 0 }, + "3342": { "label": "14/6", "naklon": 0 }, + "3340": { "label": "14/7", "naklon": 0 }, + "3152": { "label": "14/8", "naklon": 0 }, + "3886": { "label": "14/9", "naklon": 0 }, + "3341": { "label": "14/10", "naklon": null }, + "3352": { "label": "14/11", "naklon": null }, + "3396": { "label": "15/1", "naklon": 5 }, + "2784": { "label": "15/2", "naklon": 5 }, + "2788": { "label": "15/3", "naklon": 5 }, + "2801": { "label": "15/4", "naklon": 5 }, + "2815": { "label": "15/5", "naklon": 5 }, + "2829": { "label": "15/6", "naklon": 5 }, + "2796": { "label": "15/7", "naklon": 5 }, + "2803": { "label": "15/8", "naklon": 5 }, + "4304": { "label": "15/8/1", "naklon": 5 }, + "4311": { "label": "15/8/2", "naklon": 5 }, + "2821": { "label": "15/9", "naklon": 5 }, + "3400": { "label": "15/10", "naklon": 5 }, + "2799": { "label": "15/11", "naklon": 5 }, + "2804": { "label": "15/12", "naklon": 5 }, + "4303": { "label": "15/12/1", "naklon": 5 }, + "4309": { "label": "15/12/2", "naklon": 5 }, + "2806": { "label": "15/13", "naklon": 5 }, + "2787": { "label": "15/14", "naklon": 5 }, + "2809": { "label": "15/15", "naklon": 5 }, + "2814": { "label": "15/16", "naklon": 0 }, + "3934": { "label": "15/17", "naklon": 0 }, + "3192": { "label": "15/18", "naklon": 0 }, + "2812": { "label": "15/19", "naklon": 0 }, + "4070": { "label": "15/20", "naklon": 0 }, + "2826": { "label": "15/21", "naklon": 0 }, + "2808": { "label": "15/22", "naklon": 3 }, + "2795": { "label": "15/23", "naklon": 3 }, + "2807": { "label": "15/24", "naklon": 3 }, + "2831": { "label": "15/25", "naklon": 0 }, + "2862": { "label": "15/26", "naklon": null }, + "2861": { "label": "15/27", "naklon": 0 }, + "2866": { "label": "15/28", "naklon": 0 }, + "3546": { "label": "15/28/1", "naklon": 0 }, + "4146": { "label": "15/29", "naklon": 0 }, + "3001": { "label": "15/29/1", "naklon": 0 }, + "2835": { "label": "15/30", "naklon": 0 }, + "2874": { "label": "15/31", "naklon": 0 }, + "2852": { "label": "15/32", "naklon": 0 }, + "2851": { "label": "15/33", "naklon": 0 }, + "3560": { "label": "15/33/1", "naklon": 0 }, + "2858": { "label": "15/34", "naklon": 0 }, + "4306": { "label": "15/34/1", "naklon": 0 }, + "2856": { "label": "15/35", "naklon": 0 }, + "2847": { "label": "15/36", "naklon": 0 }, + "3556": { "label": "15/36/1", "naklon": 0 }, + "3950": { "label": "15/37", "naklon": 0 }, + "2848": { "label": "15/38", "naklon": 0 }, + "2863": { "label": "15/39", "naklon": 0 }, + "4313": { "label": "15/39/1", "naklon": 0 }, + "2873": { "label": "15/40", "naklon": 0 }, + "2984": { "label": "15/40/1", "naklon": 0 }, + "2854": { "label": "15/41", "naklon": 0 }, + "2859": { "label": "15/42", "naklon": 0 }, + "2872": { "label": "15/43", "naklon": 0 }, + "2849": { "label": "15/44", "naklon": 0 }, + "2864": { "label": "15/45", "naklon": 0 }, + "3553": { "label": "15/46", "naklon": null }, + "3021": { "label": "15/47", "naklon": null }, + "3008": { "label": "15/47/1", "naklon": null }, + "3017": { "label": "15/48", "naklon": null }, + "3014": { "label": "15/49", "naklon": null }, + "2981": { "label": "15/50", "naklon": null }, + "3020": { "label": "15/51", "naklon": null }, + "3027": { "label": "15/52", "naklon": null }, + "3006": { "label": "15/53", "naklon": null }, + "3012": { "label": "15/54", "naklon": null }, + "2738": { "label": "15/55", "naklon": 0 }, + "2725": { "label": "15/56", "naklon": 0 }, + "3016": { "label": "15/57", "naklon": null }, + "3005": { "label": "15/58", "naklon": null }, + "3009": { "label": "15/58/1", "naklon": null }, + "3010": { "label": "15/59", "naklon": 0 }, + "3538": { "label": "15/59/1", "naklon": 0 }, + "4145": { "label": "15/59/2", "naklon": 0 }, + "2713": { "label": "15/60", "naklon": 0 }, + "2789": { "label": "15/61", "naklon": 0 }, + "2736": { "label": "15/62", "naklon": 0 }, + "2739": { "label": "15/63", "naklon": 0 }, + "4346": { "label": "15/64", "naklon": 0 }, + "2731": { "label": "15/65", "naklon": 0 }, + "2818": { "label": "15/66", "naklon": 0 }, + "3557": { "label": "15/66/1", "naklon": 0 }, + "2822": { "label": "15/67", "naklon": 0 }, + "2833": { "label": "15/68", "naklon": 0 }, + "2834": { "label": "15/69", "naklon": 0 }, + "3097": { "label": "15/70", "naklon": 0 }, + "2824": { "label": "15/71", "naklon": 0 }, + "2828": { "label": "15/72", "naklon": 0 }, + "2600": { "label": "15/73", "naklon": 0 }, + "4314": { "label": "15/73/1", "naklon": 0 }, + "2832": { "label": "15/74", "naklon": 0 }, + "4360": { "label": "15/75", "naklon": 0 }, + "2846": { "label": "15/76", "naklon": 0 }, + "2584": { "label": "15/77", "naklon": 0 }, + "2843": { "label": "15/78", "naklon": 0 }, + "4308": { "label": "15/78/1", "naklon": 0 }, + "4144": { "label": "15/79", "naklon": null }, + "2844": { "label": "15/80", "naklon": 0 }, + "2842": { "label": "15/81", "naklon": 0 }, + "2838": { "label": "15/82", "naklon": 0 }, + "2837": { "label": "15/83", "naklon": null }, + "3555": { "label": "15/83/1", "naklon": null }, + "2839": { "label": "15/84", "naklon": 0 }, + "2830": { "label": "15/85", "naklon": 0 }, + "4066": { "label": "15/86", "naklon": 0 }, + "2836": { "label": "15/87", "naklon": 0 }, + "2911": { "label": "15/88", "naklon": 0 }, + "2825": { "label": "15/89", "naklon": 0 }, + "2811": { "label": "15/90", "naklon": 0 }, + "3740": { "label": "15/94", "naklon": 15 }, + "2734": { "label": "15/95", "naklon": 15 }, + "3105": { "label": "15/96", "naklon": 15 }, + "2732": { "label": "15/97", "naklon": 15 }, + "2727": { "label": "15/98", "naklon": 15 }, + "2735": { "label": "15/99", "naklon": 15 }, + "3926": { "label": "15/100", "naklon": 15 }, + "2918": { "label": "15/101", "naklon": 0 }, + "2705": { "label": "15/102", "naklon": 10 }, + "2708": { "label": "15/103", "naklon": 10 }, + "2721": { "label": "15/104", "naklon": 10 }, + "2719": { "label": "15/105", "naklon": 10 }, + "2919": { "label": "15/106", "naklon": 10 }, + "3101": { "label": "15/107", "naklon": 10 }, + "2853": { "label": "15/108", "naklon": 10 }, + "2715": { "label": "15/109", "naklon": 10 }, + "2712": { "label": "15/110", "naklon": 0 }, + "2711": { "label": "15/111", "naklon": 0 }, + "2709": { "label": "15/112", "naklon": 0 }, + "2710": { "label": "15/113", "naklon": 0 }, + "2907": { "label": "15/114", "naklon": 0 }, + "2906": { "label": "15/115", "naklon": 0 }, + "2908": { "label": "15/116", "naklon": 0 }, + "2901": { "label": "15/117", "naklon": 0 }, + "2913": { "label": "15/118", "naklon": 0 }, + "3656": { "label": "15/119", "naklon": 0 }, + "2781": { "label": "15/120", "naklon": 0 }, + "2802": { "label": "15/121", "naklon": 0 }, + "2791": { "label": "15/122", "naklon": 0 }, + "2783": { "label": "15/123", "naklon": 0 }, + "2794": { "label": "15/124", "naklon": 0 }, + "3139": { "label": "15/125", "naklon": 0 }, + "3229": { "label": "15/126", "naklon": 5 }, + "3239": { "label": "15/127", "naklon": 5 }, + "3230": { "label": "15/128", "naklon": 5 }, + "4016": { "label": "15/129", "naklon": null }, + "3608": { "label": "16/16A", "naklon": 0 }, + "4151": { "label": "16/16B", "naklon": 0 }, + "3710": { "label": "16/1", "naklon": 0 }, + "3726": { "label": "16/2", "naklon": 0 }, + "3743": { "label": "16/3", "naklon": 0 }, + "3724": { "label": "16/4", "naklon": 0 }, + "3712": { "label": "16/5", "naklon": 0 }, + "3739": { "label": "16/6", "naklon": 0 }, + "3742": { "label": "16/7", "naklon": 0 }, + "3731": { "label": "16/8", "naklon": 0 }, + "3727": { "label": "16/9", "naklon": 0 }, + "3729": { "label": "16/10", "naklon": 0 }, + "3736": { "label": "16/11", "naklon": 0 }, + "3713": { "label": "16/12", "naklon": 0 }, + "3715": { "label": "16/13", "naklon": 0 }, + "3733": { "label": "16/14", "naklon": 0 }, + "3732": { "label": "16/15", "naklon": 0 }, + "3634": { "label": "16/17", "naklon": 0 }, + "3610": { "label": "16/18", "naklon": 0 }, + "3626": { "label": "16/19", "naklon": 0 }, + "3618": { "label": "16/20", "naklon": 0 }, + "3619": { "label": "16/21", "naklon": 0 }, + "3628": { "label": "16/22", "naklon": 0 }, + "3615": { "label": "16/23", "naklon": 0 }, + "3609": { "label": "16/24", "naklon": 0 }, + "3606": { "label": "16/25", "naklon": 0 }, + "3624": { "label": "16/26", "naklon": 0 }, + "3627": { "label": "16/27", "naklon": 0 }, + "3607": { "label": "16/28", "naklon": 0 }, + "4370": { "label": "16/29", "naklon": 0 }, + "3692": { "label": "16/30", "naklon": 0 }, + "3614": { "label": "16/31", "naklon": 0 }, + "3623": { "label": "16/32", "naklon": 0 }, + "4373": { "label": "16/33", "naklon": 0 }, + "3620": { "label": "16/34", "naklon": 0 }, + "3685": { "label": "16/35", "naklon": 0 }, + "3616": { "label": "16/36", "naklon": 0 }, + "3686": { "label": "16/37", "naklon": 0 }, + "3688": { "label": "16/38", "naklon": 0 }, + "3684": { "label": "16/39", "naklon": 0 }, + "3825": { "label": "16/40", "naklon": 0 }, + "3865": { "label": "16/41", "naklon": 0 }, + "3824": { "label": "16/42", "naklon": 0 }, + "3871": { "label": "16/43", "naklon": 0 }, + "3801": { "label": "16/44", "naklon": 0 }, + "3862": { "label": "16/45", "naklon": 0 }, + "3876": { "label": "16/46", "naklon": 0 }, + "3861": { "label": "16/47", "naklon": 0 }, + "4215": { "label": "16/48", "naklon": 0 }, + "3605": { "label": "16/49", "naklon": 10 }, + "3603": { "label": "16/50", "naklon": 10 }, + "3592": { "label": "16/51", "naklon": 10 }, + "3598": { "label": "16/52", "naklon": 10 }, + "3594": { "label": "16/53", "naklon": 10 }, + "3593": { "label": "16/54", "naklon": 10 }, + "3630": { "label": "16/55", "naklon": 10 }, + "3763": { "label": "16/56", "naklon": 10 }, + "3746": { "label": "16/57", "naklon": 10 }, + "3699": { "label": "16/58", "naklon": 0 }, + "3698": { "label": "16/59", "naklon": 0 }, + "3709": { "label": "16/60", "naklon": null }, + "3708": { "label": "16/61", "naklon": 0 }, + "3703": { "label": "16/62", "naklon": null }, + "3700": { "label": "16/63", "naklon": 0 }, + "3701": { "label": "16/64", "naklon": null }, + "3704": { "label": "16/65", "naklon": 0 }, + "3707": { "label": "16/66", "naklon": null }, + "3810": { "label": "16/67", "naklon": 0 }, + "4208": { "label": "16/68", "naklon": null }, + "3867": { "label": "16/69", "naklon": 0 }, + "4372": { "label": "16/70", "naklon": null }, + "3881": { "label": "16/71", "naklon": 0 }, + "4204": { "label": "16/72", "naklon": null }, + "3869": { "label": "16/73", "naklon": 0 }, + "4202": { "label": "16/74", "naklon": null }, + "3830": { "label": "16/75", "naklon": 0 }, + "3870": { "label": "16/76", "naklon": null }, + "3964": { "label": "16/77", "naklon": 0 }, + "3849": { "label": "16/78", "naklon": 0 }, + "3694": { "label": "16/79", "naklon": null }, + "3717": { "label": "16/80", "naklon": 0 }, + "3877": { "label": "16/81", "naklon": null }, + "3755": { "label": "16/82", "naklon": 0 }, + "3725": { "label": "16/83", "naklon": null }, + "3716": { "label": "16/84", "naklon": 0 }, + "3696": { "label": "16/85", "naklon": null }, + "3702": { "label": "16/86", "naklon": 0 }, + "3706": { "label": "16/87", "naklon": null }, + "3850": { "label": "16/88", "naklon": 0 }, + "3848": { "label": "16/89", "naklon": null }, + "3737": { "label": "16/90", "naklon": null }, + "3705": { "label": "16/91", "naklon": 0 }, + "3723": { "label": "16/92", "naklon": null }, + "3842": { "label": "16/93", "naklon": 0 }, + "3735": { "label": "16/94", "naklon": null }, + "3719": { "label": "16/95", "naklon": 0 }, + "3697": { "label": "16/96", "naklon": 0 }, + "3711": { "label": "16/97", "naklon": 0 }, + "4107": { "label": "16/98", "naklon": null }, + "4112": { "label": "16/99", "naklon": 5 }, + "4106": { "label": "16/100", "naklon": 5 }, + "4111": { "label": "16/101", "naklon": 5 }, + "4091": { "label": "16/102", "naklon": null }, + "4104": { "label": "16/103", "naklon": 5 }, + "4094": { "label": "16/104", "naklon": null }, + "4089": { "label": "16/105", "naklon": 5 }, + "4095": { "label": "16/106", "naklon": null }, + "4102": { "label": "16/107", "naklon": 5 }, + "4105": { "label": "16/108", "naklon": null }, + "3859": { "label": "16/109", "naklon": null }, + "4090": { "label": "16/110", "naklon": 5 }, + "4110": { "label": "16/111", "naklon": null }, + "4097": { "label": "16/112", "naklon": 5 }, + "4099": { "label": "16/113", "naklon": null }, + "4096": { "label": "16/114", "naklon": null }, + "4101": { "label": "16/115", "naklon": 5 }, + "4109": { "label": "16/116", "naklon": null }, + "4092": { "label": "16/117", "naklon": 5 }, + "3631": { "label": "16/118", "naklon": null }, + "3632": { "label": "16/119", "naklon": 0 }, + "3641": { "label": "16/120", "naklon": null }, + "3638": { "label": "16/121", "naklon": 0 }, + "3637": { "label": "16/122", "naklon": null }, + "4142": { "label": "16/123", "naklon": null }, + "4147": { "label": "16/124", "naklon": 5 }, + "4139": { "label": "16/125", "naklon": 5 }, + "3172": { "label": "20/30A", "naklon": 2 }, + "3164": { "label": "20/30B", "naklon": 2 }, + "3247": { "label": "20/1", "naklon": 10 }, + "3296": { "label": "20/2", "naklon": 10 }, + "3246": { "label": "20/3", "naklon": 10 }, + "3270": { "label": "20/4", "naklon": 10 }, + "3294": { "label": "20/5", "naklon": 10 }, + "3298": { "label": "20/6", "naklon": 10 }, + "3297": { "label": "20/7", "naklon": 10 }, + "3293": { "label": "20/8", "naklon": 10 }, + "3299": { "label": "20/9", "naklon": 10 }, + "3295": { "label": "20/10", "naklon": 10 }, + "3244": { "label": "20/11", "naklon": 10 }, + "3249": { "label": "20/12", "naklon": 10 }, + "3268": { "label": "20/13", "naklon": 10 }, + "3245": { "label": "20/14", "naklon": 10 }, + "3278": { "label": "20/15", "naklon": 10 }, + "3280": { "label": "20/16", "naklon": 10 }, + "3292": { "label": "20/17", "naklon": 10 }, + "3287": { "label": "20/18", "naklon": 10 }, + "3282": { "label": "20/19", "naklon": 10 }, + "3273": { "label": "20/20", "naklon": 0 }, + "3157": { "label": "20/21", "naklon": 0 }, + "3283": { "label": "20/22", "naklon": 0 }, + "3159": { "label": "20/23", "naklon": 0 }, + "3289": { "label": "20/24", "naklon": 0 }, + "3163": { "label": "20/25", "naklon": 0 }, + "3126": { "label": "20/26", "naklon": 0 }, + "3171": { "label": "20/27", "naklon": 0 }, + "3162": { "label": "20/28", "naklon": 0 }, + "3279": { "label": "20/29", "naklon": 10 }, + "3173": { "label": "20/31", "naklon": 0 }, + "3127": { "label": "20/32", "naklon": 0 }, + "3131": { "label": "20/33", "naklon": 0 }, + "3129": { "label": "20/34", "naklon": 0 }, + "3276": { "label": "20/35", "naklon": 2 }, + "3290": { "label": "20/36", "naklon": 2 }, + "3132": { "label": "20/37", "naklon": 0 }, + "3138": { "label": "20/38", "naklon": 0 }, + "3272": { "label": "20/39", "naklon": 0 }, + "3291": { "label": "20/40", "naklon": 0 }, + "3277": { "label": "20/41", "naklon": 10 }, + "3286": { "label": "20/42", "naklon": 10 }, + "3281": { "label": "20/43", "naklon": 10 }, + "3288": { "label": "20/44", "naklon": 10 }, + "3284": { "label": "20/45", "naklon": 10 }, + "3167": { "label": "20/46", "naklon": 10 }, + "3872": { "label": "20/47", "naklon": 0 }, + "3124": { "label": "20/48", "naklon": 0 }, + "3133": { "label": "20/49", "naklon": 0 }, + "3158": { "label": "20/50", "naklon": 0 }, + "3169": { "label": "20/51", "naklon": 0 }, + "3146": { "label": "20/52", "naklon": 0 }, + "3160": { "label": "20/53", "naklon": 0 }, + "3248": { "label": "20/54", "naklon": 0 }, + "3156": { "label": "20/55", "naklon": 0 }, + "3161": { "label": "20/56", "naklon": 0 }, + "3170": { "label": "20/57", "naklon": 0 }, + "3168": { "label": "20/58", "naklon": 0 }, + "3125": { "label": "20/59", "naklon": 0 }, + "3166": { "label": "20/60", "naklon": 0 }, + "3130": { "label": "20/61", "naklon": 0 }, + "3563": { "label": "20/62", "naklon": 0 }, + "3550": { "label": "20/63", "naklon": null }, + "3269": { "label": "20/67", "naklon": 0 }, + "2921": { "label": "21/1", "naklon": 0 }, + "2707": { "label": "21/2", "naklon": 0 }, + "2723": { "label": "21/3", "naklon": 0 }, + "2716": { "label": "21/4", "naklon": 0 }, + "2717": { "label": "21/5", "naklon": 0 }, + "2720": { "label": "21/6", "naklon": 0 }, + "2722": { "label": "21/7", "naklon": 0 }, + "2718": { "label": "21/8", "naklon": 0 }, + "2724": { "label": "21/9", "naklon": 0 }, + "2742": { "label": "21/10", "naklon": 0 }, + "2743": { "label": "21/11", "naklon": 0 }, + "2733": { "label": "21/12", "naklon": 0 }, + "2903": { "label": "21/14", "naklon": 0 }, + "2917": { "label": "21/15", "naklon": 0 }, + "2897": { "label": "21/16", "naklon": 0 }, + "2914": { "label": "21/17", "naklon": 0 }, + "2898": { "label": "21/18", "naklon": 0 }, + "2773": { "label": "21/19", "naklon": 0 }, + "2895": { "label": "21/20", "naklon": 0 }, + "2896": { "label": "21/21", "naklon": 0 }, + "2771": { "label": "21/22", "naklon": 0 }, + "2772": { "label": "21/23", "naklon": 0 }, + "2793": { "label": "21/24", "naklon": 0 }, + "2902": { "label": "21/25", "naklon": 0 }, + "2910": { "label": "21/26", "naklon": 0 }, + "2909": { "label": "21/27", "naklon": 0 }, + "2920": { "label": "21/28", "naklon": 0 }, + "2916": { "label": "21/29", "naklon": 0 }, + "2904": { "label": "21/30", "naklon": 0 }, + "2915": { "label": "21/31", "naklon": 0 }, + "2905": { "label": "21/32", "naklon": 0 }, + "2900": { "label": "21/33", "naklon": 0 }, + "2899": { "label": "21/34", "naklon": 0 }, + "2741": { "label": "21/36", "naklon": 0 }, + "2714": { "label": "21/37", "naklon": 0 }, + "2701": { "label": "21/38", "naklon": 0 }, + "2703": { "label": "21/39", "naklon": 0 }, + "2704": { "label": "21/40", "naklon": 0 }, + "2702": { "label": "21/41", "naklon": 0 }, + "2706": { "label": "21/42", "naklon": 0 }, + "2776": { "label": "21/43", "naklon": 0 }, + "2770": { "label": "21/44", "naklon": 0 }, + "2786": { "label": "21/45", "naklon": 0 }, + "2779": { "label": "21/46", "naklon": 0 }, + "2782": { "label": "21/47", "naklon": 0 }, + "2785": { "label": "21/48", "naklon": 0 }, + "2769": { "label": "21/49", "naklon": 0 }, + "3354": { "label": "21/50", "naklon": 0 }, + "2778": { "label": "21/51", "naklon": 0 }, + "2775": { "label": "21/52", "naklon": 0 }, + "2780": { "label": "21/53", "naklon": 0 }, + "2790": { "label": "21/54", "naklon": 0 }, + "2792": { "label": "21/55", "naklon": 0 }, + "2774": { "label": "21/56", "naklon": 0 }, + "2630": { "label": "22/1", "naklon": 0 }, + "2631": { "label": "22/2", "naklon": 0 }, + "2632": { "label": "22/3", "naklon": 0 }, + "2633": { "label": "22/4", "naklon": 0 }, + "2634": { "label": "22/5", "naklon": 0 }, + "2636": { "label": "22/6", "naklon": 0 }, + "4367": { "label": "22/7", "naklon": 0 }, + "2637": { "label": "22/8", "naklon": 0 }, + "2638": { "label": "22/9", "naklon": 0 }, + "2639": { "label": "22/10", "naklon": 0 }, + "2640": { "label": "22/11", "naklon": 0 }, + "2641": { "label": "22/12", "naklon": 0 }, + "2642": { "label": "22/13", "naklon": 0 }, + "2643": { "label": "22/14", "naklon": 0 }, + "2644": { "label": "22/15", "naklon": 0 }, + "2645": { "label": "22/16", "naklon": 0 }, + "2646": { "label": "22/17", "naklon": 0 }, + "2647": { "label": "22/18", "naklon": 0 }, + "2648": { "label": "22/19", "naklon": 0 }, + "2649": { "label": "22/20", "naklon": 0 }, + "2650": { "label": "22/21", "naklon": 0 }, + "2651": { "label": "22/22", "naklon": 0 }, + "4103": { "label": "22/23", "naklon": 0 }, + "2653": { "label": "22/24", "naklon": 0 }, + "2654": { "label": "22/25", "naklon": 0 }, + "2655": { "label": "22/26", "naklon": 0 }, + "2656": { "label": "22/27", "naklon": 0 }, + "2657": { "label": "22/28", "naklon": 0 }, + "2658": { "label": "22/29", "naklon": 0 }, + "2659": { "label": "22/30", "naklon": 0 }, + "2660": { "label": "22/31", "naklon": 0 }, + "2661": { "label": "22/32", "naklon": 0 }, + "3015": { "label": "22/32/1", "naklon": 0 }, + "2662": { "label": "22/33", "naklon": 0 }, + "2663": { "label": "22/34", "naklon": 0 }, + "2664": { "label": "22/35", "naklon": 0 }, + "2665": { "label": "22/36", "naklon": 0 }, + "2666": { "label": "22/37", "naklon": 0 }, + "2667": { "label": "22/38", "naklon": 0 }, + "2668": { "label": "22/39", "naklon": 0 }, + "2669": { "label": "22/40", "naklon": null }, + "2670": { "label": "22/41", "naklon": null }, + "2671": { "label": "22/42", "naklon": null }, + "3087": { "label": "23/9A", "naklon": 10 }, + "3090": { "label": "23/9B", "naklon": 10 }, + "3075": { "label": "23/1", "naklon": 0 }, + "3089": { "label": "23/2", "naklon": 0 }, + "3088": { "label": "23/3", "naklon": 0 }, + "3228": { "label": "23/4", "naklon": 10 }, + "2751": { "label": "23/5", "naklon": 10 }, + "3243": { "label": "23/6", "naklon": 10 }, + "4349": { "label": "23/7", "naklon": 10 }, + "3102": { "label": "23/8", "naklon": 10 }, + "3099": { "label": "23/10", "naklon": 10 }, + "3103": { "label": "23/11", "naklon": 10 }, + "3093": { "label": "23/12", "naklon": 10 }, + "3098": { "label": "23/13", "naklon": 10 }, + "3092": { "label": "23/14", "naklon": 10 }, + "3233": { "label": "23/15", "naklon": 0 }, + "3095": { "label": "23/16", "naklon": 0 }, + "4074": { "label": "23/17", "naklon": 0 }, + "2729": { "label": "23/18", "naklon": 0 }, + "3234": { "label": "23/19", "naklon": 0 }, + "3094": { "label": "23/20", "naklon": 0 }, + "2817": { "label": "23/21", "naklon": 0 }, + "3226": { "label": "23/22", "naklon": 0 }, + "3225": { "label": "23/23", "naklon": 0 }, + "3237": { "label": "23/24", "naklon": 0 }, + "4250": { "label": "23/25", "naklon": 0 }, + "3059": { "label": "23/26", "naklon": 10 }, + "3238": { "label": "23/27", "naklon": 10 }, + "3242": { "label": "23/28", "naklon": 10 }, + "3236": { "label": "23/29", "naklon": 10 }, + "3112": { "label": "23/30", "naklon": 10 }, + "3224": { "label": "23/31", "naklon": 0 }, + "4298": { "label": "23/32", "naklon": 10 }, + "4150": { "label": "23/33", "naklon": 10 }, + "3091": { "label": "23/34", "naklon": 10 }, + "3771": { "label": "25/1", "naklon": 5 }, + "3777": { "label": "25/2", "naklon": 5 }, + "3749": { "label": "25/3", "naklon": 5 }, + "3769": { "label": "25/4", "naklon": 5 }, + "3765": { "label": "25/5", "naklon": 5 }, + "3785": { "label": "25/6", "naklon": 5 }, + "3761": { "label": "25/7", "naklon": 5 }, + "3758": { "label": "25/8", "naklon": 5 }, + "3766": { "label": "25/9", "naklon": 5 }, + "3779": { "label": "25/10", "naklon": 5 }, + "3899": { "label": "25/11", "naklon": 10 }, + "3922": { "label": "25/12", "naklon": 10 }, + "3912": { "label": "25/13", "naklon": 10 }, + "3933": { "label": "25/14", "naklon": 10 }, + "3921": { "label": "25/15", "naklon": 10 }, + "4300": { "label": "25/16", "naklon": 10 }, + "3927": { "label": "25/17", "naklon": 10 }, + "3212": { "label": "25/18", "naklon": 10 }, + "3208": { "label": "25/19", "naklon": 10 }, + "3207": { "label": "25/20", "naklon": 10 }, + "4294": { "label": "25/21", "naklon": 10 }, + "3209": { "label": "25/22", "naklon": 10 }, + "3745": { "label": "25/23", "naklon": 10 }, + "3762": { "label": "25/24", "naklon": 10 }, + "3215": { "label": "25/25", "naklon": 10 }, + "3210": { "label": "25/26", "naklon": 10 }, + "3211": { "label": "25/27", "naklon": 10 }, + "3206": { "label": "25/28", "naklon": 10 }, + "3918": { "label": "25/29", "naklon": 5 }, + "3928": { "label": "25/30", "naklon": 5 }, + "3917": { "label": "25/31", "naklon": 5 }, + "4029": { "label": "25/32", "naklon": 0 }, + "4038": { "label": "25/33", "naklon": 0 }, + "4022": { "label": "25/34", "naklon": 0 }, + "3937": { "label": "25/35", "naklon": 0 }, + "3190": { "label": "25/36", "naklon": 0 }, + "3835": { "label": "25/37", "naklon": 0 }, + "3201": { "label": "25/38", "naklon": 0 }, + "3193": { "label": "25/39", "naklon": 0 }, + "3191": { "label": "25/40", "naklon": 0 }, + "3203": { "label": "25/41", "naklon": 0 }, + "4301": { "label": "25/42", "naklon": 0 }, + "3223": { "label": "25/43", "naklon": 0 }, + "3202": { "label": "25/44", "naklon": 0 }, + "3205": { "label": "25/45", "naklon": 0 }, + "3194": { "label": "25/46", "naklon": 0 }, + "3198": { "label": "25/47", "naklon": 0 }, + "3204": { "label": "25/48", "naklon": 0 }, + "3200": { "label": "25/49", "naklon": 0 }, + "3216": { "label": "25/50", "naklon": 0 }, + "3932": { "label": "25/51", "naklon": 5 }, + "3923": { "label": "25/52", "naklon": 5 }, + "3913": { "label": "25/53", "naklon": 5 }, + "3900": { "label": "25/54", "naklon": 5 }, + "4189": { "label": "25/55", "naklon": 10 }, + "4191": { "label": "25/56", "naklon": 10 }, + "3790": { "label": "25/57", "naklon": 10 }, + "4190": { "label": "25/58", "naklon": 10 }, + "4302": { "label": "25/59", "naklon": 0 }, + "4351": { "label": "25/60", "naklon": 0 }, + "4075": { "label": "25/61", "naklon": 0 }, + "4071": { "label": "25/62", "naklon": 0 }, + "3784": { "label": "25/63", "naklon": 0 }, + "4065": { "label": "25/64", "naklon": 0 }, + "4297": { "label": "25/65", "naklon": 0 }, + "4295": { "label": "25/66", "naklon": 0 }, + "4299": { "label": "25/67", "naklon": 0 }, + "3772": { "label": "25/68", "naklon": 0 }, + "3941": { "label": "25/69", "naklon": 0 }, + "3782": { "label": "25/70", "naklon": 0 }, + "4068": { "label": "25/71", "naklon": 0 }, + "4073": { "label": "25/72", "naklon": 0 }, + "3901": { "label": "25/73", "naklon": 5 }, + "4296": { "label": "25/74", "naklon": 5 }, + "3910": { "label": "25/75", "naklon": 5 }, + "4293": { "label": "25/76", "naklon": 5 }, + "3919": { "label": "25/77", "naklon": 5 }, + "3924": { "label": "25/78", "naklon": 5 }, + "3909": { "label": "25/79", "naklon": 5 }, + "3896": { "label": "25/80", "naklon": 5 }, + "3911": { "label": "25/81", "naklon": 5 }, + "2819": { "label": "25/82", "naklon": 15 }, + "3776": { "label": "25/83", "naklon": 15 }, + "3752": { "label": "25/84", "naklon": 15 }, + "4353": { "label": "25/85", "naklon": 15 }, + "3791": { "label": "25/86", "naklon": 0 }, + "3770": { "label": "25/87", "naklon": 0 }, + "3760": { "label": "25/88", "naklon": 0 }, + "3115": { "label": "25/89", "naklon": 0 }, + "3738": { "label": "25/90", "naklon": 0 }, + "3748": { "label": "25/91", "naklon": 0 }, + "3753": { "label": "25/92", "naklon": 0 }, + "3775": { "label": "25/93", "naklon": 0 }, + "3778": { "label": "25/94", "naklon": 5 }, + "4078": { "label": "25/95", "naklon": 5 }, + "4088": { "label": "25/96", "naklon": 5 }, + "3856": { "label": "25/97", "naklon": 5 }, + "4084": { "label": "25/98", "naklon": 5 }, + "4069": { "label": "25/99", "naklon": 5 }, + "4188": { "label": "25/100", "naklon": 5 }, + "4064": { "label": "25/101", "naklon": 5 }, + "3792": { "label": "25/102", "naklon": 5 }, + "3780": { "label": "25/103", "naklon": 5 }, + "4034": { "label": "25/104", "naklon": 5 }, + "4072": { "label": "25/105", "naklon": 5 }, + "3884": { "label": "25/106", "naklon": 5 }, + "3793": { "label": "25/107", "naklon": 5 }, + "3863": { "label": "25/108", "naklon": 5 }, + "3855": { "label": "25/109", "naklon": 5 }, + "3846": { "label": "33/1", "naklon": 0 }, + "3943": { "label": "33/2", "naklon": 0 }, + "3903": { "label": "33/3", "naklon": 0 }, + "3982": { "label": "33/4", "naklon": 0 }, + "3879": { "label": "33/5", "naklon": 0 }, + "3887": { "label": "33/6", "naklon": 0 }, + "3920": { "label": "33/7", "naklon": 5 }, + "3942": { "label": "33/8", "naklon": 5 }, + "3829": { "label": "33/9", "naklon": null }, + "3452": { "label": "34/79A", "naklon": 6 }, + "3460": { "label": "34/79B", "naklon": 6 }, + "3443": { "label": "34/90A", "naklon": 6 }, + "3445": { "label": "34/90B", "naklon": 6 }, + "3457": { "label": "34/90C", "naklon": 6 }, + "3461": { "label": "34/97A", "naklon": 6 }, + "3463": { "label": "34/97B", "naklon": 6 }, + "3426": { "label": "34/98A", "naklon": 6 }, + "3444": { "label": "34/98B", "naklon": 6 }, + "3453": { "label": "34/99A", "naklon": 6 }, + "3455": { "label": "34/99B", "naklon": 6 }, + "4009": { "label": "34/1", "naklon": 0 }, + "3602": { "label": "34/2", "naklon": 0 }, + "3441": { "label": "34/3", "naklon": 0 }, + "3464": { "label": "34/4", "naklon": 0 }, + "3883": { "label": "34/5", "naklon": 0 }, + "4098": { "label": "34/6", "naklon": 0 }, + "4003": { "label": "34/7", "naklon": 0 }, + "4004": { "label": "34/8", "naklon": 0 }, + "3888": { "label": "34/9", "naklon": 0 }, + "3997": { "label": "34/10", "naklon": 0 }, + "4006": { "label": "34/11", "naklon": 0 }, + "4000": { "label": "34/12", "naklon": 0 }, + "4011": { "label": "34/13", "naklon": 0 }, + "3999": { "label": "34/14", "naklon": 0 }, + "3981": { "label": "34/15", "naklon": 0 }, + "3988": { "label": "34/16", "naklon": 0 }, + "3986": { "label": "34/17", "naklon": 0 }, + "3998": { "label": "34/18", "naklon": 0 }, + "3983": { "label": "34/19", "naklon": 0 }, + "4005": { "label": "34/20", "naklon": 0 }, + "4001": { "label": "34/21", "naklon": 0 }, + "4008": { "label": "34/22", "naklon": 0 }, + "4002": { "label": "34/23", "naklon": 0 }, + "3996": { "label": "34/24", "naklon": 0 }, + "4007": { "label": "34/25", "naklon": 0 }, + "4113": { "label": "34/26", "naklon": 15 }, + "3595": { "label": "34/27", "naklon": 5 }, + "3599": { "label": "34/28", "naklon": 5 }, + "3601": { "label": "34/29", "naklon": 5 }, + "4205": { "label": "34/30", "naklon": 0 }, + "3987": { "label": "34/31", "naklon": null }, + "4214": { "label": "34/32", "naklon": 0 }, + "4226": { "label": "34/33", "naklon": 0 }, + "4209": { "label": "34/34", "naklon": 0 }, + "4201": { "label": "34/35", "naklon": 0 }, + "3440": { "label": "34/36", "naklon": 0 }, + "3465": { "label": "34/37", "naklon": 0 }, + "3446": { "label": "34/38", "naklon": 0 }, + "4039": { "label": "34/39", "naklon": 5 }, + "4057": { "label": "34/40", "naklon": 5 }, + "3985": { "label": "34/41", "naklon": 0 }, + "3882": { "label": "34/42", "naklon": 0 }, + "4040": { "label": "34/43", "naklon": 5 }, + "3231": { "label": "34/44", "naklon": 0 }, + "3227": { "label": "34/45", "naklon": 0 }, + "3431": { "label": "34/46", "naklon": 0 }, + "4013": { "label": "34/47", "naklon": 0 }, + "4045": { "label": "34/48", "naklon": 0 }, + "3949": { "label": "34/49", "naklon": 0 }, + "3953": { "label": "34/50", "naklon": 0 }, + "3952": { "label": "34/51", "naklon": 0 }, + "3995": { "label": "34/52", "naklon": 0 }, + "3992": { "label": "34/53", "naklon": 0 }, + "4198": { "label": "34/54", "naklon": 0 }, + "3935": { "label": "34/55", "naklon": 0 }, + "4050": { "label": "34/56", "naklon": 0 }, + "4049": { "label": "34/57", "naklon": 0 }, + "4054": { "label": "34/58", "naklon": 0 }, + "3663": { "label": "34/59", "naklon": 6 }, + "3661": { "label": "34/60", "naklon": 6 }, + "3664": { "label": "34/61", "naklon": 6 }, + "3660": { "label": "34/62", "naklon": 6 }, + "3662": { "label": "34/63", "naklon": 6 }, + "3665": { "label": "34/65", "naklon": 6 }, + "3667": { "label": "34/66", "naklon": 6 }, + "3675": { "label": "34/67", "naklon": 6 }, + "3666": { "label": "34/68", "naklon": 6 }, + "3652": { "label": "34/69", "naklon": 6 }, + "3458": { "label": "34/70", "naklon": 6 }, + "4425": { "label": "34/70/1", "naklon": 6 }, + "3459": { "label": "34/71", "naklon": 6 }, + "3435": { "label": "34/72", "naklon": 6 }, + "3448": { "label": "34/73", "naklon": 6 }, + "3451": { "label": "34/74", "naklon": 6 }, + "3442": { "label": "34/75", "naklon": 6 }, + "3449": { "label": "34/76", "naklon": 6 }, + "3450": { "label": "34/77", "naklon": 6 }, + "3433": { "label": "34/78", "naklon": 6 }, + "3432": { "label": "34/80", "naklon": 12 }, + "3470": { "label": "34/81", "naklon": 12 }, + "3438": { "label": "34/82", "naklon": 12 }, + "3439": { "label": "34/83", "naklon": 12 }, + "4028": { "label": "34/84", "naklon": 5 }, + "3596": { "label": "34/85", "naklon": 5 }, + "4021": { "label": "34/86", "naklon": 5 }, + "3437": { "label": "34/87", "naklon": 12 }, + "3428": { "label": "34/88", "naklon": 12 }, + "3430": { "label": "34/89", "naklon": 12 }, + "3454": { "label": "34/91", "naklon": 6 }, + "3492": { "label": "34/92", "naklon": 6 }, + "3462": { "label": "34/93", "naklon": 6 }, + "3427": { "label": "34/94", "naklon": 6 }, + "3434": { "label": "34/95", "naklon": 6 }, + "3456": { "label": "34/96", "naklon": 6 }, + "4307": { "label": "34/98/1", "naklon": 6 }, + "3968": { "label": "35/1", "naklon": 0 }, + "3969": { "label": "35/2", "naklon": 0 }, + "3947": { "label": "35/3", "naklon": 0 }, + "3979": { "label": "35/4", "naklon": 0 }, + "3959": { "label": "35/5", "naklon": 0 }, + "3948": { "label": "35/6", "naklon": 0 }, + "3961": { "label": "35/7", "naklon": 0 }, + "3956": { "label": "35/8", "naklon": 0 }, + "3604": { "label": "35/9", "naklon": 0 }, + "3944": { "label": "35/10", "naklon": 0 }, + "3960": { "label": "35/11", "naklon": 0 }, + "3958": { "label": "35/12", "naklon": 0 }, + "4036": { "label": "35/13", "naklon": 5 }, + "3893": { "label": "35/18", "naklon": 5 }, + "4108": { "label": "35/19", "naklon": 5 }, + "4017": { "label": "35/20", "naklon": 5 }, + "3963": { "label": "35/21", "naklon": 0 }, + "3658": { "label": "35/22", "naklon": 0 }, + "3975": { "label": "35/23", "naklon": 0 }, + "3980": { "label": "35/24", "naklon": 0 }, + "4012": { "label": "35/25", "naklon": 0 }, + "3655": { "label": "35/26", "naklon": 0 }, + "3962": { "label": "35/27", "naklon": 0 }, + "3945": { "label": "35/28", "naklon": 0 }, + "3569": { "label": "35/29", "naklon": 0 }, + "3429": { "label": "35/30", "naklon": 0 }, + "3657": { "label": "35/31", "naklon": 0 }, + "3646": { "label": "35/32", "naklon": 0 }, + "3622": { "label": "35/33", "naklon": 0 }, + "3612": { "label": "35/34", "naklon": 0 }, + "3955": { "label": "35/35", "naklon": 0 }, + "3878": { "label": "35/37", "naklon": 0 }, + "3965": { "label": "35/38", "naklon": 0 }, + "3970": { "label": "35/39", "naklon": 0 }, + "3611": { "label": "35/40", "naklon": 0 }, + "2635": { "label": "35/41", "naklon": 0 }, + "3978": { "label": "35/42", "naklon": 0 }, + "4213": { "label": "35/43", "naklon": 0 }, + "3984": { "label": "35/44", "naklon": 0 }, + "4218": { "label": "35/45", "naklon": 0 }, + "3973": { "label": "35/46", "naklon": 0 }, + "3974": { "label": "35/47", "naklon": 0 }, + "3759": { "label": "35/48", "naklon": 0 }, + "3844": { "label": "35/49", "naklon": 0 }, + "3804": { "label": "35/50", "naklon": 0 }, + "3831": { "label": "35/51", "naklon": 0 }, + "3643": { "label": "35/52", "naklon": 0 }, + "3966": { "label": "35/53", "naklon": 0 }, + "3971": { "label": "35/54", "naklon": 0 }, + "3650": { "label": "35/55", "naklon": 6 }, + "3651": { "label": "35/56", "naklon": 6 }, + "3669": { "label": "35/57", "naklon": 6 }, + "3648": { "label": "35/58", "naklon": 6 }, + "3645": { "label": "35/59", "naklon": 6 }, + "3659": { "label": "35/60", "naklon": 6 }, + "3647": { "label": "35/61", "naklon": 6 }, + "3644": { "label": "35/62", "naklon": 6 }, + "3671": { "label": "35/63", "naklon": 6 }, + "3682": { "label": "35/64", "naklon": 6 }, + "3672": { "label": "35/65", "naklon": 6 }, + "3683": { "label": "35/66", "naklon": 6 }, + "3673": { "label": "35/67", "naklon": 6 }, + "3674": { "label": "35/68", "naklon": 6 }, + "3679": { "label": "35/69", "naklon": 6 }, + "3649": { "label": "35/70", "naklon": 6 }, + "3687": { "label": "35/71", "naklon": 6 }, + "3677": { "label": "35/72", "naklon": 6 }, + "3690": { "label": "35/73", "naklon": 6 }, + "3691": { "label": "35/74", "naklon": 6 }, + "3676": { "label": "35/75", "naklon": 6 }, + "3680": { "label": "35/76", "naklon": 6 }, + "3668": { "label": "35/77", "naklon": 6 }, + "3681": { "label": "35/78", "naklon": 6 }, + "3670": { "label": "35/79", "naklon": 6 }, + "3689": { "label": "35/80", "naklon": 6 }, + "3678": { "label": "35/81", "naklon": 6 }, + "3693": { "label": "35/82", "naklon": 6 }, + "3654": { "label": "35/83", "naklon": null }, + "4086": { "label": "36/1", "naklon": 0 }, + "4085": { "label": "36/2", "naklon": 0 }, + "4083": { "label": "36/3", "naklon": 0 }, + "4087": { "label": "36/4", "naklon": 0 }, + "4077": { "label": "36/5", "naklon": 0 }, + "4082": { "label": "36/6", "naklon": 0 }, + "4186": { "label": "36/7", "naklon": 0 }, + "4206": { "label": "36/8", "naklon": 0 }, + "4080": { "label": "36/9", "naklon": 0 }, + "4081": { "label": "36/10", "naklon": 0 }, + "4210": { "label": "36/11", "naklon": 0 }, + "4079": { "label": "36/12", "naklon": 0 }, + "4076": { "label": "36/13", "naklon": 0 }, + "3852": { "label": "36/14", "naklon": 0 }, + "2813": { "label": "36/15", "naklon": 0 }, + "4219": { "label": "36/16", "naklon": 0 }, + "3104": { "label": "37/1A", "naklon": 15 }, + "3121": { "label": "37/1B", "naklon": 15 }, + "3113": { "label": "37/2", "naklon": 10 }, + "3118": { "label": "37/3", "naklon": 10 }, + "3111": { "label": "37/4", "naklon": 10 }, + "4020": { "label": "37/5", "naklon": 10 }, + "3119": { "label": "37/6", "naklon": 10 }, + "3110": { "label": "37/7", "naklon": 10 }, + "3108": { "label": "37/8", "naklon": 10 }, + "3107": { "label": "37/12", "naklon": 0 }, + "3199": { "label": "37/13", "naklon": 0 }, + "3120": { "label": "37/14", "naklon": 0 }, + "3122": { "label": "37/15", "naklon": 0 }, + "3908": { "label": "37/16", "naklon": 0 }, + "3114": { "label": "37/17", "naklon": 0 }, + "3105": { "label": "37/18", "naklon": 0 }, + "3116": { "label": "37/19", "naklon": 0 }, + "3106": { "label": "37/20", "naklon": 0 }, + "2887": { "label": "37/21", "naklon": 5 }, + "2888": { "label": "37/22", "naklon": 5 }, + "2877": { "label": "37/23", "naklon": 5 }, + "2891": { "label": "37/24", "naklon": 5 }, + "2886": { "label": "37/25", "naklon": 5 }, + "2892": { "label": "37/26", "naklon": 5 }, + "2882": { "label": "37/27", "naklon": 5 }, + "2883": { "label": "37/28", "naklon": 5 }, + "2876": { "label": "37/29", "naklon": 5 }, + "3109": { "label": "37/30", "naklon": 5 }, + "4152": { "label": "37/31", "naklon": 5 }, + "3117": { "label": "37/32", "naklon": 5 }, + "2870": { "label": "37/33", "naklon": 5 }, + "2867": { "label": "37/34", "naklon": 0 }, + "2865": { "label": "37/35", "naklon": 0 }, + "3096": { "label": "37/36", "naklon": 0 }, + "2871": { "label": "37/37", "naklon": 0 }, + "2884": { "label": "37/38", "naklon": 0 }, + "2855": { "label": "37/39", "naklon": 0 }, + "2878": { "label": "37/40", "naklon": 0 }, + "2889": { "label": "37/41", "naklon": 0 }, + "2879": { "label": "37/42", "naklon": 0 }, + "2850": { "label": "37/43", "naklon": 0 }, + "2894": { "label": "37/44", "naklon": 0 }, + "2880": { "label": "37/45", "naklon": 0 }, + "2893": { "label": "37/46", "naklon": 0 }, + "2890": { "label": "37/47", "naklon": 0 }, + "4355": { "label": "37/48", "naklon": 0 }, + "2885": { "label": "37/49", "naklon": 0 }, + "2875": { "label": "37/50", "naklon": 0 }, + "3486": { "label": "38/30A", "naklon": 5 }, + "3714": { "label": "38/30B", "naklon": 0 }, + "3483": { "label": "38/32A", "naklon": 5 }, + "3496": { "label": "38/32B", "naklon": 0 }, + "3487": { "label": "38/35A", "naklon": 5 }, + "3498": { "label": "38/35B", "naklon": 5 }, + "3578": { "label": "38/38A", "naklon": 5 }, + "3508": { "label": "38/38B", "naklon": 5 }, + "3787": { "label": "38/59A", "naklon": 5 }, + "3491": { "label": "38/59B", "naklon": 5 }, + "3568": { "label": "38/1", "naklon": null }, + "3502": { "label": "38/2", "naklon": 0 }, + "3836": { "label": "38/3", "naklon": 0 }, + "3588": { "label": "38/4", "naklon": 0 }, + "3493": { "label": "38/5", "naklon": 0 }, + "3580": { "label": "38/6", "naklon": 0 }, + "3572": { "label": "38/7", "naklon": 0 }, + "3506": { "label": "38/8", "naklon": 0 }, + "3503": { "label": "38/9", "naklon": 0 }, + "3579": { "label": "38/10", "naklon": 0 }, + "3586": { "label": "38/11", "naklon": 0 }, + "3495": { "label": "38/12", "naklon": 5 }, + "3492": { "label": "38/13", "naklon": 5 }, + "3532": { "label": "38/14", "naklon": 5 }, + "3574": { "label": "38/15", "naklon": 5 }, + "4140": { "label": "38/16", "naklon": 5 }, + "3795": { "label": "38/17", "naklon": 5 }, + "3788": { "label": "38/18", "naklon": 5 }, + "3796": { "label": "38/19", "naklon": 5 }, + "3797": { "label": "38/20", "naklon": 5 }, + "3798": { "label": "38/21", "naklon": 5 }, + "3786": { "label": "38/22", "naklon": 5 }, + "4067": { "label": "38/23", "naklon": 5 }, + "3773": { "label": "38/24", "naklon": 5 }, + "3774": { "label": "38/25", "naklon": 5 }, + "3789": { "label": "38/26", "naklon": 5 }, + "3520": { "label": "38/27", "naklon": null }, + "3577": { "label": "38/29", "naklon": 5 }, + "3530": { "label": "38/31", "naklon": null }, + "3488": { "label": "38/33", "naklon": 5 }, + "3505": { "label": "38/34", "naklon": 5 }, + "3497": { "label": "38/36", "naklon": 5 }, + "3490": { "label": "38/37", "naklon": 5 }, + "3585": { "label": "38/39", "naklon": 5 }, + "3582": { "label": "38/40", "naklon": 5 }, + "3507": { "label": "38/41", "naklon": 5 }, + "3484": { "label": "38/42", "naklon": 5 }, + "3501": { "label": "38/43", "naklon": 5 }, + "3581": { "label": "38/44", "naklon": 5 }, + "4192": { "label": "38/45", "naklon": 5 }, + "3576": { "label": "38/46", "naklon": 5 }, + "3489": { "label": "38/47", "naklon": 5 }, + "3573": { "label": "38/48", "naklon": 5 }, + "3504": { "label": "38/49", "naklon": 5 }, + "3794": { "label": "38/50", "naklon": 5 }, + "3485": { "label": "38/51", "naklon": 5 }, + "3482": { "label": "38/52", "naklon": 5 }, + "3575": { "label": "38/53", "naklon": 5 }, + "3499": { "label": "38/54", "naklon": 5 }, + "3494": { "label": "38/55", "naklon": 5 }, + "3583": { "label": "38/56", "naklon": 5 }, + "3570": { "label": "38/57", "naklon": 5 }, + "3500": { "label": "38/58", "naklon": 0 }, + "3510": { "label": "38/63", "naklon": null }, + "3512": { "label": "38/64", "naklon": null }, + "3535": { "label": "38/67", "naklon": null }, + "3531": { "label": "38/68", "naklon": null }, + "3537": { "label": "38/69", "naklon": null }, + "3522": { "label": "39/1", "naklon": 10 }, + "4018": { "label": "39/2", "naklon": 10 }, + "4019": { "label": "39/3", "naklon": 10 }, + "4154": { "label": "39/4", "naklon": 5 }, + "3907": { "label": "39/5", "naklon": 5 }, + "4148": { "label": "39/6", "naklon": 0 }, + "4153": { "label": "39/7", "naklon": 0 }, + "3938": { "label": "39/8", "naklon": 0 }, + "3802": { "label": "39/9", "naklon": 0 }, + "4015": { "label": "39/10", "naklon": 0 }, + "3929": { "label": "39/11", "naklon": 0 }, + "3946": { "label": "39/12", "naklon": 0 }, + "4014": { "label": "39/13", "naklon": 0 }, + "4155": { "label": "39/14", "naklon": 0 }, + "4149": { "label": "39/15", "naklon": 0 }, + "3642": { "label": "39/16", "naklon": 0 }, + "3636": { "label": "39/17", "naklon": 5 }, + "3991": { "label": "39/18", "naklon": 0 }, + "3994": { "label": "39/19", "naklon": 0 }, + "3990": { "label": "39/20", "naklon": 0 }, + "3967": { "label": "39/21", "naklon": 0 }, + "3977": { "label": "39/22", "naklon": 0 }, + "3757": { "label": "39/23", "naklon": 15 }, + "3633": { "label": "39/24", "naklon": 15 }, + "3744": { "label": "39/25", "naklon": 15 }, + "4023": { "label": "39/26", "naklon": 5 }, + "3720": { "label": "39/27", "naklon": 5 }, + "3734": { "label": "39/28", "naklon": 5 }, + "3741": { "label": "39/29", "naklon": 5 }, + "3721": { "label": "39/30", "naklon": 5 }, + "3845": { "label": "39/31", "naklon": 0 }, + "3840": { "label": "39/32", "naklon": 0 }, + "3837": { "label": "39/33", "naklon": null }, + "3839": { "label": "39/34", "naklon": 0 }, + "3542": { "label": "41/1", "naklon": null }, + "3566": { "label": "41/2", "naklon": null }, + "3548": { "label": "41/3", "naklon": null }, + "3515": { "label": "41/4", "naklon": null }, + "3559": { "label": "41/5", "naklon": null }, + "3509": { "label": "41/6", "naklon": null }, + "3524": { "label": "41/7", "naklon": null }, + "3518": { "label": "41/8", "naklon": null }, + "3182": { "label": "41/9", "naklon": null }, + "3187": { "label": "41/10", "naklon": null }, + "3195": { "label": "41/11", "naklon": 0 }, + "3857": { "label": "41/12", "naklon": 0 }, + "3183": { "label": "41/13", "naklon": 0 }, + "3177": { "label": "41/14", "naklon": 0 }, + "3189": { "label": "41/15", "naklon": 0 }, + "3186": { "label": "41/16", "naklon": 0 }, + "3178": { "label": "42/1", "naklon": 0 }, + "3219": { "label": "42/2", "naklon": 0 }, + "3475": { "label": "42/3", "naklon": 0 }, + "3175": { "label": "42/4", "naklon": 0 }, + "3222": { "label": "42/5", "naklon": 0 }, + "3221": { "label": "42/6", "naklon": 0 }, + "3181": { "label": "42/7", "naklon": 0 }, + "3180": { "label": "42/8", "naklon": 0 }, + "3218": { "label": "42/9", "naklon": 0 }, + "3176": { "label": "42/10", "naklon": 0 }, + "3174": { "label": "42/11", "naklon": 0 }, + "3220": { "label": "42/12", "naklon": 0 }, + "3533": { "label": "42/13", "naklon": null }, + "3543": { "label": "42/14", "naklon": null }, + "3554": { "label": "42/15", "naklon": null }, + "3549": { "label": "42/16", "naklon": null }, + "2857": { "label": "43/1", "naklon": 5 }, + "2752": { "label": "43/2", "naklon": 5 }, + "2753": { "label": "43/3", "naklon": 5 }, + "3024": { "label": "43/4", "naklon": 5 }, + "2754": { "label": "43/5", "naklon": 5 }, + "4423": { "label": "43/6", "naklon": 5 }, + "4368": { "label": "43/7", "naklon": 5 }, + "2978": { "label": "43/8", "naklon": 5 }, + "2868": { "label": "43/9", "naklon": 5 }, + "4377": { "label": "43/10", "naklon": 5 }, + "2757": { "label": "43/11", "naklon": 5 }, + "2970": { "label": "43/12", "naklon": 5 }, + "2758": { "label": "43/13", "naklon": 5 }, + "4378": { "label": "43/14", "naklon": 5 }, + "2759": { "label": "43/15", "naklon": 5 }, + "4342": { "label": "43/16", "naklon": 5 }, + "3026": { "label": "43/17", "naklon": null }, + "2986": { "label": "43/18", "naklon": null }, + "4343": { "label": "43/19", "naklon": null }, + "2760": { "label": "43/20", "naklon": null }, + "4379": { "label": "43/21", "naklon": null }, + "2971": { "label": "43/22", "naklon": null }, + "2761": { "label": "43/23", "naklon": null }, + "2762": { "label": "43/24", "naklon": null }, + "4339": { "label": "43/25", "naklon": null }, + "4380": { "label": "43/26", "naklon": null }, + "2975": { "label": "43/27", "naklon": null }, + "3003": { "label": "43/28", "naklon": null }, + "4338": { "label": "43/29", "naklon": null }, + "3002": { "label": "43/30", "naklon": null }, + "4345": { "label": "43/31", "naklon": null }, + "2979": { "label": "43/32", "naklon": null }, + "2989": { "label": "43/33", "naklon": null }, + "2996": { "label": "43/34", "naklon": null }, + "2972": { "label": "43/35", "naklon": null }, + "2988": { "label": "43/36", "naklon": null }, + "4344": { "label": "43/37", "naklon": null }, + "3022": { "label": "43/38", "naklon": null }, + "4341": { "label": "43/39", "naklon": null }, + "2983": { "label": "43/40", "naklon": null }, + "2995": { "label": "43/41", "naklon": null }, + "2763": { "label": "43/42", "naklon": null }, + "2764": { "label": "43/43", "naklon": null }, + "2765": { "label": "43/44", "naklon": null }, + "2766": { "label": "43/45", "naklon": null }, + "2767": { "label": "43/46", "naklon": null }, + "2768": { "label": "43/47", "naklon": null }, + "3018": { "label": "43/48", "naklon": null }, + "2982": { "label": "43/49", "naklon": null }, + "3019": { "label": "43/50", "naklon": 0 }, + "3013": { "label": "43/51", "naklon": null }, + "3007": { "label": "43/52", "naklon": null }, + "2980": { "label": "43/53", "naklon": null }, + "3011": { "label": "43/54", "naklon": null }, + "2672": { "label": "43/55", "naklon": null }, + "2673": { "label": "43/56", "naklon": null }, + "2674": { "label": "43/57", "naklon": null }, + "2675": { "label": "43/58", "naklon": null }, + "2676": { "label": "43/59", "naklon": null }, + "2677": { "label": "43/60", "naklon": null }, + "2678": { "label": "43/61", "naklon": null }, + "2679": { "label": "43/62", "naklon": null }, + "2680": { "label": "43/63", "naklon": null }, + "2840": { "label": "43/64", "naklon": null }, + "2682": { "label": "43/65", "naklon": null }, + "2683": { "label": "43/66", "naklon": null }, + "2684": { "label": "43/67", "naklon": 0 }, + "2685": { "label": "43/68", "naklon": null }, + "2686": { "label": "43/69", "naklon": null }, + "2687": { "label": "43/70", "naklon": null }, + "2688": { "label": "43/71", "naklon": null }, + "2689": { "label": "43/72", "naklon": null }, + "2690": { "label": "43/73", "naklon": null }, + "2691": { "label": "43/74", "naklon": null }, + "2692": { "label": "43/75", "naklon": null }, + "2693": { "label": "43/76", "naklon": 0 }, + "2694": { "label": "43/77", "naklon": null }, + "2695": { "label": "43/78", "naklon": null }, + "2696": { "label": "43/79", "naklon": 0 }, + "2697": { "label": "43/80", "naklon": null }, + "2698": { "label": "43/81", "naklon": 0 }, + "2699": { "label": "43/82", "naklon": null }, + "2700": { "label": "43/83", "naklon": 0 }, + "2744": { "label": "43/84", "naklon": null }, + "2745": { "label": "43/85", "naklon": 0 }, + "2746": { "label": "43/86", "naklon": null }, + "2747": { "label": "43/87", "naklon": 0 }, + "2748": { "label": "43/88", "naklon": null }, + "2749": { "label": "43/89", "naklon": 0 }, + "2841": { "label": "43/90", "naklon": null }, + "4237": { "label": "45/1", "naklon": 5 }, + "4226": { "label": "45/2", "naklon": 5 }, + "4242": { "label": "45/3", "naklon": 5 }, + "4179": { "label": "45/4", "naklon": 5 }, + "4247": { "label": "45/5", "naklon": 5 }, + "4245": { "label": "45/6", "naklon": 5 }, + "3872": { "label": "45/7", "naklon": 5 }, + "4175": { "label": "45/8", "naklon": 5 }, + "4236": { "label": "45/9", "naklon": 5 }, + "4170": { "label": "45/10", "naklon": 5 }, + "4238": { "label": "45/11", "naklon": 5 }, + "4246": { "label": "45/12", "naklon": 5 }, + "4166": { "label": "45/13", "naklon": 5 }, + "4227": { "label": "45/14", "naklon": 5 }, + "4171": { "label": "45/15", "naklon": 5 }, + "4180": { "label": "45/16", "naklon": 5 }, + "4244": { "label": "45/17", "naklon": 5 }, + "4199": { "label": "45/18", "naklon": 5 }, + "4239": { "label": "45/19", "naklon": 5 }, + "4207": { "label": "45/20", "naklon": 5 }, + "4223": { "label": "45/21", "naklon": 5 }, + "4230": { "label": "45/22", "naklon": 5 }, + "4233": { "label": "45/23", "naklon": 5 }, + "4222": { "label": "45/24", "naklon": 5 }, + "4217": { "label": "45/25", "naklon": 5 }, + "4243": { "label": "45/26", "naklon": 5 }, + "4200": { "label": "45/27", "naklon": 5 }, + "4228": { "label": "45/28", "naklon": 5 }, + "4211": { "label": "45/29", "naklon": 5 }, + "4234": { "label": "45/30", "naklon": 5 }, + "4235": { "label": "45/31", "naklon": 5 }, + "4203": { "label": "45/32", "naklon": 5 }, + "4240": { "label": "45/33", "naklon": 5 }, + "4224": { "label": "45/34", "naklon": 5 }, + "4232": { "label": "45/35", "naklon": 5 }, + "4231": { "label": "45/36", "naklon": 5 }, + "4161": { "label": "45/37", "naklon": 5 }, + "4225": { "label": "45/38", "naklon": 5 }, + "4241": { "label": "45/39", "naklon": 5 }, + "4229": { "label": "45/40", "naklon": 5 }, + "4221": { "label": "45/41", "naklon": 5 }, + "4212": { "label": "45/42", "naklon": 5 }, + "4216": { "label": "45/43", "naklon": 5 }, + "3864": { "label": "45/44", "naklon": null }, + "3806": { "label": "46/1", "naklon": 5 }, + "3813": { "label": "46/2", "naklon": 5 }, + "3815": { "label": "46/3", "naklon": 5 }, + "3807": { "label": "46/4", "naklon": 5 }, + "3895": { "label": "46/5", "naklon": 5 }, + "3809": { "label": "46/6", "naklon": 5 }, + "3820": { "label": "46/7", "naklon": 5 }, + "3805": { "label": "46/8", "naklon": 5 }, + "3894": { "label": "46/9", "naklon": 0 }, + "4055": { "label": "46/10", "naklon": 0 }, + "3812": { "label": "46/11", "naklon": 5 }, + "3822": { "label": "46/12", "naklon": 5 }, + "3821": { "label": "46/13", "naklon": 5 }, + "3808": { "label": "46/14", "naklon": 5 }, + "3799": { "label": "46/15", "naklon": 5 }, + "3816": { "label": "46/16", "naklon": 5 }, + "3751": { "label": "46/17", "naklon": 5 }, + "3814": { "label": "46/18", "naklon": 5 }, + "4044": { "label": "46/19", "naklon": 0 }, + "3931": { "label": "46/20", "naklon": 0 }, + "3902": { "label": "46/21", "naklon": 5 }, + "3916": { "label": "46/22", "naklon": 5 }, + "3892": { "label": "46/23", "naklon": 5 }, + "3914": { "label": "46/24", "naklon": 5 }, + "3898": { "label": "46/25", "naklon": 5 }, + "3897": { "label": "46/26", "naklon": 5 }, + "3885": { "label": "46/27", "naklon": 5 }, + "3906": { "label": "46/28", "naklon": 5 }, + "3930": { "label": "46/29", "naklon": 0 }, + "3936": { "label": "46/30", "naklon": 0 }, + "3860": { "label": "46/31", "naklon": 5 }, + "3841": { "label": "46/32", "naklon": 5 }, + "3873": { "label": "46/33", "naklon": 5 }, + "3854": { "label": "46/34", "naklon": 5 }, + "3939": { "label": "46/35", "naklon": 5 }, + "3858": { "label": "46/36", "naklon": 5 }, + "3940": { "label": "46/37", "naklon": 5 }, + "4035": { "label": "46/38", "naklon": 5 }, + "3373": { "label": "47/1", "naklon": 0 }, + "3374": { "label": "47/2", "naklon": 0 }, + "3384": { "label": "47/3", "naklon": 0 }, + "3385": { "label": "47/4", "naklon": 0 }, + "4051": { "label": "48/1", "naklon": 5 }, + "4041": { "label": "48/2", "naklon": 5 }, + "4056": { "label": "48/3", "naklon": 5 }, + "3875": { "label": "48/4", "naklon": 5 }, + "4061": { "label": "48/5", "naklon": 5 }, + "4047": { "label": "48/6", "naklon": 5 }, + "4060": { "label": "48/7", "naklon": 5 }, + "4059": { "label": "48/8", "naklon": 5 }, + "4058": { "label": "48/9", "naklon": 5 }, + "3635": { "label": "48/10", "naklon": 5 }, + "3640": { "label": "48/11", "naklon": 5 }, + "3747": { "label": "48/12", "naklon": 5 }, + "3629": { "label": "48/13", "naklon": 5 }, + "4048": { "label": "48/14", "naklon": 5 }, + "4063": { "label": "48/15", "naklon": 5 }, + "4062": { "label": "48/16", "naklon": 5 }, + "4043": { "label": "48/17", "naklon": 5 }, + "4052": { "label": "48/18", "naklon": 5 }, + "4042": { "label": "48/19", "naklon": 5 }, + "4053": { "label": "48/20", "naklon": 5 }, + "4167": { "label": "50/15A", "naklon": null }, + "4159": { "label": "50/15B", "naklon": null }, + "4183": { "label": "50/1", "naklon": 0 }, + "4157": { "label": "50/2", "naklon": 0 }, + "4160": { "label": "50/3", "naklon": 0 }, + "4173": { "label": "50/4", "naklon": 0 }, + "4177": { "label": "50/5", "naklon": 0 }, + "4174": { "label": "50/6", "naklon": 0 }, + "4178": { "label": "50/7", "naklon": 0 }, + "4195": { "label": "50/8", "naklon": 0 }, + "4169": { "label": "50/9", "naklon": 0 }, + "4162": { "label": "50/10", "naklon": 0 }, + "4158": { "label": "50/11", "naklon": 0 }, + "4182": { "label": "50/12", "naklon": 0 }, + "4194": { "label": "50/13", "naklon": 0 }, + "4184": { "label": "50/14", "naklon": 0 }, + "4197": { "label": "50/16", "naklon": null }, + "4164": { "label": "50/17", "naklon": null }, + "3306": { "label": "50/18", "naklon": null }, + "4168": { "label": "50/19", "naklon": null }, + "4193": { "label": "50/20", "naklon": null }, + "4187": { "label": "50/21", "naklon": null }, + "4163": { "label": "50/22", "naklon": null }, + "4165": { "label": "50/23", "naklon": null }, + "4185": { "label": "50/24", "naklon": null }, + "3904": { "label": "50/25", "naklon": null }, + "2619": { "label": "53/1", "naklon": 0 }, + "2623": { "label": "53/2", "naklon": 0 }, + "2617": { "label": "53/3", "naklon": 0 }, + "2622": { "label": "53/4", "naklon": 0 }, + "2618": { "label": "53/5", "naklon": 0 }, + "2626": { "label": "53/6", "naklon": 0 }, + "2869": { "label": "53/7", "naklon": 0 }, + "2613": { "label": "53/8", "naklon": 0 }, + "2608": { "label": "53/9", "naklon": 0 }, + "2611": { "label": "53/10", "naklon": 0 }, + "2598": { "label": "53/11", "naklon": 0 }, + "3528": { "label": "53/12", "naklon": 0 }, + "3545": { "label": "53/13", "naklon": 0 }, + "2620": { "label": "53/14", "naklon": 0 }, + "2612": { "label": "53/15", "naklon": 0 }, + "2615": { "label": "53/16", "naklon": 0 }, + "3722": { "label": "53/17", "naklon": 0 }, + "2624": { "label": "53/18", "naklon": 0 }, + "2609": { "label": "53/19", "naklon": 0 }, + "2625": { "label": "53/20", "naklon": 0 }, + "2602": { "label": "53/21", "naklon": 0 }, + "2610": { "label": "53/22", "naklon": 0 }, + "2599": { "label": "53/23", "naklon": 0 }, + "2605": { "label": "53/24", "naklon": 0 }, + "2593": { "label": "53/25", "naklon": 0 }, + "3074": { "label": "53/26", "naklon": 0 }, + "2740": { "label": "53/27", "naklon": 0 }, + "2614": { "label": "53/28", "naklon": 0 }, + "2601": { "label": "53/29", "naklon": 0 }, + "4196": { "label": "53/30", "naklon": 0 }, + "2607": { "label": "53/31", "naklon": 0 }, + "2582": { "label": "53/32", "naklon": 0 }, + "2594": { "label": "53/33", "naklon": 0 }, + "2589": { "label": "53/34", "naklon": 0 }, + "2596": { "label": "53/35", "naklon": 0 }, + "2603": { "label": "53/36", "naklon": 0 }, + "2597": { "label": "53/37", "naklon": 0 }, + "2590": { "label": "53/38", "naklon": 0 }, + "2581": { "label": "53/39", "naklon": 0 }, + "2583": { "label": "53/40", "naklon": 0 }, + "2580": { "label": "53/41", "naklon": 0 }, + "2579": { "label": "53/42", "naklon": 0 }, + "2797": { "label": "53/43", "naklon": 0 }, + "2577": { "label": "53/44", "naklon": 0 }, + "2586": { "label": "53/45", "naklon": 0 }, + "2588": { "label": "53/46", "naklon": 0 }, + "2591": { "label": "53/47", "naklon": 0 }, + "2592": { "label": "53/48", "naklon": 0 }, + "2573": { "label": "53/49", "naklon": 0 }, + "2595": { "label": "53/50", "naklon": 0 }, + "2587": { "label": "53/51", "naklon": 0 }, + "2578": { "label": "53/52", "naklon": 0 }, + "2574": { "label": "53/53", "naklon": 0 }, + "2571": { "label": "53/54", "naklon": 0 }, + "2570": { "label": "53/55", "naklon": 0 }, + "2576": { "label": "53/56", "naklon": 0 }, + "2881": { "label": "53/57", "naklon": 0 }, + "2575": { "label": "53/58", "naklon": 0 }, + "2572": { "label": "53/59", "naklon": 0 }, + "2569": { "label": "53/60", "naklon": 0 }, + "4324": { "label": "55/1", "naklon": 0 }, + "4319": { "label": "55/2", "naklon": 0 }, + "4327": { "label": "55/3", "naklon": 0 }, + "4333": { "label": "55/4", "naklon": 0 }, + "4332": { "label": "55/5", "naklon": 0 }, + "4320": { "label": "55/6", "naklon": 0 }, + "4317": { "label": "55/7", "naklon": 0 }, + "4318": { "label": "55/8", "naklon": 0 }, + "4328": { "label": "55/9", "naklon": 0 }, + "4323": { "label": "55/10", "naklon": 0 }, + "4325": { "label": "55/11", "naklon": 0 }, + "4326": { "label": "55/12", "naklon": 0 }, + "4316": { "label": "55/13", "naklon": 0 }, + "4322": { "label": "55/14", "naklon": 0 }, + "4331": { "label": "55/15", "naklon": 0 }, + "4321": { "label": "55/16", "naklon": 0 }, + "4315": { "label": "55/17", "naklon": 0 }, + "4329": { "label": "55/18", "naklon": 0 }, + "4334": { "label": "55/19", "naklon": 0 }, + "4330": { "label": "55/20", "naklon": 0 } +}; + + +let svetlaSorted = [{ "label": "1/3A", "node": 3993, "naklon": 0 }, +{ "label": "1/3B", "node": 3989, "naklon": 15 }, +{ "label": "1/1", "node": 3976, "naklon": 0 }, +{ "label": "1/2", "node": 4181, "naklon": 0 }, +{ "label": "1/4", "node": 4376, "naklon": 15 }, +{ "label": "1/5", "node": 3868, "naklon": 15 }, +{ "label": "1/6", "node": 3728, "naklon": 15 }, +{ "label": "1/7", "node": 3730, "naklon": 0 }, +{ "label": "1/8", "node": 4374, "naklon": 0 }, +{ "label": "1/9", "node": 3718, "naklon": 15 }, +{ "label": "1/10", "node": 4375, "naklon": 15 }, +{ "label": "1/11", "node": 4172, "naklon": 15 }, +{ "label": "1/12", "node": 4176, "naklon": 15 }, +{ "label": "2/1", "node": 3800, "naklon": 5 }, +{ "label": "2/2", "node": 3823, "naklon": 5 }, +{ "label": "2/3", "node": 3905, "naklon": 5 }, +{ "label": "2/4", "node": 3803, "naklon": 5 }, +{ "label": "2/5", "node": 3817, "naklon": 5 }, +{ "label": "2/6", "node": 3818, "naklon": 5 }, +{ "label": "2/7", "node": 3811, "naklon": 5 }, +{ "label": "2/8", "node": 3915, "naklon": 5 }, +{ "label": "2/9", "node": 3843, "naklon": 10 }, +{ "label": "2/10", "node": 3827, "naklon": 10 }, +{ "label": "2/11", "node": 4220, "naklon": 10 }, +{ "label": "2/12", "node": 3826, "naklon": 10 }, +{ "label": "2/13", "node": 3834, "naklon": 10 }, +{ "label": "2/14", "node": 3838, "naklon": 10 }, +{ "label": "2/15", "node": 2823, "naklon": 10 }, +{ "label": "2/16", "node": 3750, "naklon": 10 }, +{ "label": "2/17", "node": 3378, "naklon": 0 }, +{ "label": "2/18", "node": 3376, "naklon": 0 }, +{ "label": "2/19", "node": 3379, "naklon": 0 }, +{ "label": "2/20", "node": 3285, "naklon": 0 }, +{ "label": "2/21", "node": 3382, "naklon": 0 }, +{ "label": "2/22", "node": 3383, "naklon": 0 }, +{ "label": "2/24", "node": 3375, "naklon": 0 }, +{ "label": "2/25", "node": 3381, "naklon": 0 }, +{ "label": "2/26", "node": 3380, "naklon": 0 }, +{ "label": "2/27", "node": 3828, "naklon": 10 }, +{ "label": "2/28", "node": 3377, "naklon": 0 }, +{ "label": "7/1", "node": 3591, "naklon": 0 }, +{ "label": "7/2", "node": 3587, "naklon": 0 }, +{ "label": "7/3", "node": 3468, "naklon": 0 }, +{ "label": "7/4", "node": 3466, "naklon": 0 }, +{ "label": "7/5", "node": 3474, "naklon": 0 }, +{ "label": "7/6", "node": 3481, "naklon": 0 }, +{ "label": "7/7", "node": 3589, "naklon": 0 }, +{ "label": "7/8", "node": 3472, "naklon": 0 }, +{ "label": "7/9", "node": 3473, "naklon": 0 }, +{ "label": "7/10", "node": 3584, "naklon": 0 }, +{ "label": "7/11", "node": 3571, "naklon": 0 }, +{ "label": "7/12", "node": 3476, "naklon": 0 }, +{ "label": "7/13", "node": 3590, "naklon": 0 }, +{ "label": "7/14", "node": 3478, "naklon": 0 }, +{ "label": "7/15", "node": 3471, "naklon": 0 }, +{ "label": "7/16", "node": 3467, "naklon": 0 }, +{ "label": "7/17", "node": 3479, "naklon": 0 }, +{ "label": "7/18", "node": 3480, "naklon": 0 }, +{ "label": "7/19", "node": 3477, "naklon": 0 }, +{ "label": "12/1", "node": 3362, "naklon": 0 }, +{ "label": "12/2", "node": 3355, "naklon": 0 }, +{ "label": "12/3", "node": 3356, "naklon": 0 }, +{ "label": "12/4", "node": 3349, "naklon": 0 }, +{ "label": "12/5", "node": 3357, "naklon": 0 }, +{ "label": "12/6", "node": 3350, "naklon": 0 }, +{ "label": "12/7", "node": 3353, "naklon": 0 }, +{ "label": "12/8", "node": 3539, "naklon": 0 }, +{ "label": "12/9", "node": 3050, "naklon": 0 }, +{ "label": "12/10", "node": 3361, "naklon": 0 }, +{ "label": "12/11", "node": 3360, "naklon": 0 }, +{ "label": "12/12", "node": 3358, "naklon": 0 }, +{ "label": "12/13", "node": 3541, "naklon": 0 }, +{ "label": "12/14", "node": 3551, "naklon": 0 }, +{ "label": "12/15", "node": 3514, "naklon": 0 }, +{ "label": "12/16", "node": 3547, "naklon": 0 }, +{ "label": "12/17", "node": 3562, "naklon": 0 }, +{ "label": "12/18", "node": 3525, "naklon": 0 }, +{ "label": "12/19", "node": 3558, "naklon": 0 }, +{ "label": "12/20", "node": 3511, "naklon": 0 }, +{ "label": "12/21", "node": 3058, "naklon": 0 }, +{ "label": "12/22", "node": 3062, "naklon": 0 }, +{ "label": "12/23", "node": 3070, "naklon": 0 }, +{ "label": "12/24", "node": 3447, "naklon": 0 }, +{ "label": "12/25", "node": 3056, "naklon": 0 }, +{ "label": "12/26", "node": 3057, "naklon": 0 }, +{ "label": "12/27", "node": 3071, "naklon": 0 }, +{ "label": "12/28", "node": 3061, "naklon": 0 }, +{ "label": "12/29", "node": 3069, "naklon": 0 }, +{ "label": "12/30", "node": 3077, "naklon": 0 }, +{ "label": "12/31", "node": 3080, "naklon": 0 }, +{ "label": "12/32", "node": 3081, "naklon": 0 }, +{ "label": "12/33", "node": 3078, "naklon": 0 }, +{ "label": "12/34", "node": 4037, "naklon": 0 }, +{ "label": "12/35", "node": 3067, "naklon": 0 }, +{ "label": "12/36", "node": 3051, "naklon": 0 }, +{ "label": "12/37", "node": 2924, "naklon": 0 }, +{ "label": "12/38", "node": 3060, "naklon": 0 }, +{ "label": "12/39", "node": 3073, "naklon": 0 }, +{ "label": "12/40", "node": 3469, "naklon": 0 }, +{ "label": "12/41", "node": 2923, "naklon": 0 }, +{ "label": "12/42", "node": 2925, "naklon": 0 }, +{ "label": "12/43", "node": 3359, "naklon": 0 }, +{ "label": "12/44", "node": 3055, "naklon": 0 }, +{ "label": "12/45", "node": 2922, "naklon": 0 }, +{ "label": "12/46", "node": 3084, "naklon": 0 }, +{ "label": "12/47", "node": 3064, "naklon": 0 }, +{ "label": "12/48", "node": 3066, "naklon": 0 }, +{ "label": "12/49", "node": 3072, "naklon": 0 }, +{ "label": "13/13A", "node": 3415, "naklon": 0 }, +{ "label": "13/13B", "node": 3409, "naklon": 0 }, +{ "label": "13/13C", "node": 3399, "naklon": 0 }, +{ "label": "13/29A", "node": 3410, "naklon": 0 }, +{ "label": "13/29B", "node": 3407, "naklon": 0 }, +{ "label": "13/34A", "node": 3405, "naklon": 0 }, +{ "label": "13/34B", "node": 3404, "naklon": 0 }, +{ "label": "13/45A", "node": 3392, "naklon": 0 }, +{ "label": "13/45B", "node": 3386, "naklon": 0 }, +{ "label": "13/60A", "node": 3303, "naklon": 3 }, +{ "label": "13/60B", "node": 3302, "naklon": 3 }, +{ "label": "13/70A", "node": 3319, "naklon": 6 }, +{ "label": "13/70B", "node": 3317, "naklon": 6 }, +{ "label": "13/70C", "node": 3326, "naklon": 6 }, +{ "label": "13/73A", "node": 3351, "naklon": 6 }, +{ "label": "13/73B", "node": 3313, "naklon": 6 }, +{ "label": "13/83A", "node": 3316, "naklon": 0 }, +{ "label": "13/83B", "node": 3320, "naklon": 0 }, +{ "label": "13/95A", "node": 3336, "naklon": 0 }, +{ "label": "13/95B", "node": 3323, "naklon": 0 }, +{ "label": "13/98A", "node": 3339, "naklon": 0 }, +{ "label": "13/98B", "node": 3333, "naklon": 0 }, +{ "label": "13/1", "node": 3425, "naklon": 0 }, +{ "label": "13/2", "node": 3419, "naklon": 0 }, +{ "label": "13/3", "node": 3416, "naklon": 0 }, +{ "label": "13/4", "node": 3332, "naklon": 0 }, +{ "label": "13/5", "node": 3422, "naklon": 0 }, +{ "label": "13/6", "node": 3417, "naklon": 0 }, +{ "label": "13/7", "node": 3418, "naklon": 0 }, +{ "label": "13/8", "node": 3424, "naklon": 0 }, +{ "label": "13/9", "node": 3334, "naklon": 0 }, +{ "label": "13/10", "node": 4363, "naklon": 0 }, +{ "label": "13/11", "node": 3423, "naklon": 0 }, +{ "label": "13/12", "node": 3406, "naklon": 0 }, +{ "label": "13/14", "node": 3411, "naklon": 0 }, +{ "label": "13/15", "node": 3412, "naklon": 0 }, +{ "label": "13/16", "node": 3413, "naklon": 0 }, +{ "label": "13/17", "node": 3414, "naklon": 0 }, +{ "label": "13/18", "node": 3391, "naklon": 0 }, +{ "label": "13/19", "node": 3370, "naklon": 0 }, +{ "label": "13/20", "node": 3369, "naklon": 0 }, +{ "label": "13/21", "node": 3408, "naklon": 0 }, +{ "label": "13/22", "node": 3393, "naklon": 0 }, +{ "label": "13/23", "node": 3128, "naklon": 0 }, +{ "label": "13/24", "node": 3197, "naklon": 0 }, +{ "label": "13/25", "node": 4364, "naklon": 0 }, +{ "label": "13/26", "node": 3155, "naklon": 0 }, +{ "label": "13/27", "node": 3196, "naklon": 0 }, +{ "label": "13/28", "node": 3144, "naklon": 0 }, +{ "label": "13/30", "node": 3150, "naklon": 0 }, +{ "label": "13/31", "node": 3390, "naklon": 0 }, +{ "label": "13/32", "node": 3401, "naklon": 0 }, +{ "label": "13/33", "node": 3275, "naklon": 0 }, +{ "label": "13/35", "node": 3371, "naklon": 0 }, +{ "label": "13/36", "node": 3389, "naklon": 0 }, +{ "label": "13/37", "node": 3388, "naklon": 0 }, +{ "label": "13/38", "node": 3365, "naklon": 0 }, +{ "label": "13/39", "node": 3363, "naklon": 0 }, +{ "label": "13/40", "node": 3397, "naklon": 0 }, +{ "label": "13/40/1", "node": 3567, "naklon": 0 }, +{ "label": "13/41", "node": 3387, "naklon": 0 }, +{ "label": "13/42", "node": 3403, "naklon": 0 }, +{ "label": "13/43", "node": 3147, "naklon": 0 }, +{ "label": "13/44", "node": 3141, "naklon": 0 }, +{ "label": "13/46", "node": 3364, "naklon": 0 }, +{ "label": "13/47", "node": 3367, "naklon": 0 }, +{ "label": "13/48", "node": 3368, "naklon": 0 }, +{ "label": "13/49", "node": 3402, "naklon": 0 }, +{ "label": "13/50", "node": 3366, "naklon": 0 }, +{ "label": "13/51", "node": 3395, "naklon": 0 }, +{ "label": "13/52", "node": 3372, "naklon": 0 }, +{ "label": "13/53", "node": 3394, "naklon": 0 }, +{ "label": "13/54", "node": 3308, "naklon": 0 }, +{ "label": "13/54/1", "node": 3847, "naklon": 0 }, +{ "label": "13/55", "node": 3312, "naklon": 3 }, +{ "label": "13/56", "node": 3309, "naklon": 3 }, +{ "label": "13/57", "node": 3311, "naklon": 3 }, +{ "label": "13/58", "node": 3310, "naklon": 3 }, +{ "label": "13/59", "node": 4365, "naklon": 3 }, +{ "label": "13/60/1", "node": 4093, "naklon": 3 }, +{ "label": "13/61", "node": 3304, "naklon": 3 }, +{ "label": "13/62", "node": 3307, "naklon": 3 }, +{ "label": "13/63", "node": 3271, "naklon": 3 }, +{ "label": "13/64", "node": 3301, "naklon": 3 }, +{ "label": "13/65", "node": 4366, "naklon": 3 }, +{ "label": "13/66", "node": 3300, "naklon": 3 }, +{ "label": "13/67", "node": 3185, "naklon": 0 }, +{ "label": "13/68", "node": 3184, "naklon": 0 }, +{ "label": "13/69", "node": 3188, "naklon": 0 }, +{ "label": "13/71", "node": 3343, "naklon": 6 }, +{ "label": "13/71/1", "node": 3819, "naklon": 6 }, +{ "label": "13/71/2", "node": 3880, "naklon": 6 }, +{ "label": "13/72", "node": 3348, "naklon": 6 }, +{ "label": "13/74", "node": 3344, "naklon": 6 }, +{ "label": "13/75", "node": 3346, "naklon": 6 }, +{ "label": "13/75/1", "node": 3597, "naklon": 6 }, +{ "label": "13/76", "node": 3345, "naklon": 6 }, +{ "label": "13/77", "node": 3322, "naklon": 0 }, +{ "label": "13/78", "node": 3325, "naklon": 0 }, +{ "label": "13/78/1", "node": 4310, "naklon": 0 }, +{ "label": "13/79", "node": 3315, "naklon": 0 }, +{ "label": "13/80", "node": 3328, "naklon": 0 }, +{ "label": "13/81", "node": 3321, "naklon": 0 }, +{ "label": "13/82", "node": 3324, "naklon": 0 }, +{ "label": "13/84", "node": 3140, "naklon": 0 }, +{ "label": "13/85", "node": 3153, "naklon": 0 }, +{ "label": "13/86", "node": 3145, "naklon": 0 }, +{ "label": "13/87", "node": 3134, "naklon": 0 }, +{ "label": "13/88", "node": 3151, "naklon": 0 }, +{ "label": "13/89", "node": 3143, "naklon": 0 }, +{ "label": "13/90", "node": 3318, "naklon": 0 }, +{ "label": "13/91", "node": 3347, "naklon": 0 }, +{ "label": "13/94", "node": 3314, "naklon": 0 }, +{ "label": "13/96", "node": 3331, "naklon": 0 }, +{ "label": "13/97", "node": 3327, "naklon": 0 }, +{ "label": "13/99", "node": 3329, "naklon": 0 }, +{ "label": "13/100", "node": 3337, "naklon": 0 }, +{ "label": "13/101", "node": 3330, "naklon": 0 }, +{ "label": "13/102", "node": 3335, "naklon": 0 }, +{ "label": "13/103", "node": 3420, "naklon": 0 }, +{ "label": "13/104", "node": 3421, "naklon": 0 }, +{ "label": "13/105", "node": 4361, "naklon": 0 }, +{ "label": "13/106", "node": 4362, "naklon": 0 }, +{ "label": "13/107", "node": 3526, "naklon": 0 }, +{ "label": "13/108", "node": 4424, "naklon": null }, +{ "label": "13/109", "node": 3561, "naklon": null }, +{ "label": "13/110", "node": 3527, "naklon": null }, +{ "label": "13/111", "node": 3521, "naklon": null }, +{ "label": "13/112", "node": 3552, "naklon": null }, +{ "label": "13/113", "node": 3544, "naklon": null }, +{ "label": "13/114", "node": 3534, "naklon": null }, +{ "label": "13/115", "node": 3516, "naklon": null }, +{ "label": "13/116", "node": 3513, "naklon": null }, +{ "label": "13/117", "node": 3565, "naklon": null }, +{ "label": "13/118", "node": 3866, "naklon": null }, +{ "label": "14/1", "node": 3136, "naklon": 0 }, +{ "label": "14/2", "node": 3137, "naklon": 0 }, +{ "label": "14/3", "node": 3135, "naklon": 0 }, +{ "label": "14/4", "node": 3149, "naklon": 0 }, +{ "label": "14/5", "node": 3142, "naklon": 0 }, +{ "label": "14/6", "node": 3342, "naklon": 0 }, +{ "label": "14/7", "node": 3340, "naklon": 0 }, +{ "label": "14/8", "node": 3152, "naklon": 0 }, +{ "label": "14/9", "node": 3886, "naklon": 0 }, +{ "label": "14/10", "node": 3341, "naklon": null }, +{ "label": "14/11", "node": 3352, "naklon": null }, +{ "label": "15/1", "node": 3396, "naklon": 5 }, +{ "label": "15/2", "node": 2784, "naklon": 5 }, +{ "label": "15/3", "node": 2788, "naklon": 5 }, +{ "label": "15/4", "node": 2801, "naklon": 5 }, +{ "label": "15/5", "node": 2815, "naklon": 5 }, +{ "label": "15/6", "node": 2829, "naklon": 5 }, +{ "label": "15/7", "node": 2796, "naklon": 5 }, +{ "label": "15/8", "node": 2803, "naklon": 5 }, +{ "label": "15/8/1", "node": 4304, "naklon": 5 }, +{ "label": "15/8/2", "node": 4311, "naklon": 5 }, +{ "label": "15/9", "node": 2821, "naklon": 5 }, +{ "label": "15/10", "node": 3400, "naklon": 5 }, +{ "label": "15/11", "node": 2799, "naklon": 5 }, +{ "label": "15/12", "node": 2804, "naklon": 5 }, +{ "label": "15/12/1", "node": 4303, "naklon": 5 }, +{ "label": "15/12/2", "node": 4309, "naklon": 5 }, +{ "label": "15/13", "node": 2806, "naklon": 5 }, +{ "label": "15/14", "node": 2787, "naklon": 5 }, +{ "label": "15/15", "node": 2809, "naklon": 5 }, +{ "label": "15/16", "node": 2814, "naklon": 0 }, +{ "label": "15/17", "node": 3934, "naklon": 0 }, +{ "label": "15/18", "node": 3192, "naklon": 0 }, +{ "label": "15/19", "node": 2812, "naklon": 0 }, +{ "label": "15/20", "node": 4070, "naklon": 0 }, +{ "label": "15/21", "node": 2826, "naklon": 0 }, +{ "label": "15/22", "node": 2808, "naklon": 3 }, +{ "label": "15/23", "node": 2795, "naklon": 3 }, +{ "label": "15/24", "node": 2807, "naklon": 3 }, +{ "label": "15/25", "node": 2831, "naklon": 0 }, +{ "label": "15/26", "node": 2862, "naklon": null }, +{ "label": "15/27", "node": 2861, "naklon": 0 }, +{ "label": "15/28", "node": 2866, "naklon": 0 }, +{ "label": "15/28/1", "node": 3546, "naklon": 0 }, +{ "label": "15/29", "node": 4146, "naklon": 0 }, +{ "label": "15/29/1", "node": 3001, "naklon": 0 }, +{ "label": "15/30", "node": 2835, "naklon": 0 }, +{ "label": "15/31", "node": 2874, "naklon": 0 }, +{ "label": "15/32", "node": 2852, "naklon": 0 }, +{ "label": "15/33", "node": 2851, "naklon": 0 }, +{ "label": "15/33/1", "node": 3560, "naklon": 0 }, +{ "label": "15/34", "node": 2858, "naklon": 0 }, +{ "label": "15/34/1", "node": 4306, "naklon": 0 }, +{ "label": "15/35", "node": 2856, "naklon": 0 }, +{ "label": "15/36", "node": 2847, "naklon": 0 }, +{ "label": "15/36/1", "node": 3556, "naklon": 0 }, +{ "label": "15/37", "node": 3950, "naklon": 0 }, +{ "label": "15/38", "node": 2848, "naklon": 0 }, +{ "label": "15/39", "node": 2863, "naklon": 0 }, +{ "label": "15/39/1", "node": 4313, "naklon": 0 }, +{ "label": "15/40", "node": 2873, "naklon": 0 }, +{ "label": "15/40/1", "node": 2984, "naklon": 0 }, +{ "label": "15/41", "node": 2854, "naklon": 0 }, +{ "label": "15/42", "node": 2859, "naklon": 0 }, +{ "label": "15/43", "node": 2872, "naklon": 0 }, +{ "label": "15/44", "node": 2849, "naklon": 0 }, +{ "label": "15/45", "node": 2864, "naklon": 0 }, +{ "label": "15/46", "node": 3553, "naklon": null }, +{ "label": "15/47", "node": 3021, "naklon": null }, +{ "label": "15/47/1", "node": 3008, "naklon": null }, +{ "label": "15/48", "node": 3017, "naklon": null }, +{ "label": "15/49", "node": 3014, "naklon": null }, +{ "label": "15/50", "node": 2981, "naklon": null }, +{ "label": "15/51", "node": 3020, "naklon": null }, +{ "label": "15/52", "node": 3027, "naklon": null }, +{ "label": "15/53", "node": 3006, "naklon": null }, +{ "label": "15/54", "node": 3012, "naklon": null }, +{ "label": "15/55", "node": 2738, "naklon": 0 }, +{ "label": "15/56", "node": 2725, "naklon": 0 }, +{ "label": "15/57", "node": 3016, "naklon": null }, +{ "label": "15/58", "node": 3005, "naklon": null }, +{ "label": "15/58/1", "node": 3009, "naklon": null }, +{ "label": "15/59", "node": 3010, "naklon": 0 }, +{ "label": "15/59/1", "node": 3538, "naklon": 0 }, +{ "label": "15/59/2", "node": 4145, "naklon": 0 }, +{ "label": "15/60", "node": 2713, "naklon": 0 }, +{ "label": "15/61", "node": 2789, "naklon": 0 }, +{ "label": "15/62", "node": 2736, "naklon": 0 }, +{ "label": "15/63", "node": 2739, "naklon": 0 }, +{ "label": "15/64", "node": 4346, "naklon": 0 }, +{ "label": "15/65", "node": 2731, "naklon": 0 }, +{ "label": "15/66", "node": 2818, "naklon": 0 }, +{ "label": "15/66/1", "node": 3557, "naklon": 0 }, +{ "label": "15/67", "node": 2822, "naklon": 0 }, +{ "label": "15/68", "node": 2833, "naklon": 0 }, +{ "label": "15/69", "node": 2834, "naklon": 0 }, +{ "label": "15/70", "node": 3097, "naklon": 0 }, +{ "label": "15/71", "node": 2824, "naklon": 0 }, +{ "label": "15/72", "node": 2828, "naklon": 0 }, +{ "label": "15/73", "node": 2600, "naklon": 0 }, +{ "label": "15/73/1", "node": 4314, "naklon": 0 }, +{ "label": "15/74", "node": 2832, "naklon": 0 }, +{ "label": "15/75", "node": 4360, "naklon": 0 }, +{ "label": "15/76", "node": 2846, "naklon": 0 }, +{ "label": "15/77", "node": 2584, "naklon": 0 }, +{ "label": "15/78", "node": 2843, "naklon": 0 }, +{ "label": "15/78/1", "node": 4308, "naklon": 0 }, +{ "label": "15/79", "node": 4144, "naklon": null }, +{ "label": "15/80", "node": 2844, "naklon": 0 }, +{ "label": "15/81", "node": 2842, "naklon": 0 }, +{ "label": "15/82", "node": 2838, "naklon": 0 }, +{ "label": "15/83", "node": 2837, "naklon": null }, +{ "label": "15/83/1", "node": 3555, "naklon": null }, +{ "label": "15/84", "node": 2839, "naklon": 0 }, +{ "label": "15/85", "node": 2830, "naklon": 0 }, +{ "label": "15/86", "node": 4066, "naklon": 0 }, +{ "label": "15/87", "node": 2836, "naklon": 0 }, +{ "label": "15/88", "node": 2911, "naklon": 0 }, +{ "label": "15/89", "node": 2825, "naklon": 0 }, +{ "label": "15/90", "node": 2811, "naklon": 0 }, +{ "label": "15/94", "node": 3740, "naklon": 15 }, +{ "label": "15/95", "node": 2734, "naklon": 15 }, +{ "label": "15/96", "node": 3105, "naklon": 15 }, +{ "label": "15/97", "node": 2732, "naklon": 15 }, +{ "label": "15/98", "node": 2727, "naklon": 15 }, +{ "label": "15/99", "node": 2735, "naklon": 15 }, +{ "label": "15/100", "node": 3926, "naklon": 15 }, +{ "label": "15/101", "node": 2918, "naklon": 0 }, +{ "label": "15/102", "node": 2705, "naklon": 10 }, +{ "label": "15/103", "node": 2708, "naklon": 10 }, +{ "label": "15/104", "node": 2721, "naklon": 10 }, +{ "label": "15/105", "node": 2719, "naklon": 10 }, +{ "label": "15/106", "node": 2919, "naklon": 10 }, +{ "label": "15/107", "node": 3101, "naklon": 10 }, +{ "label": "15/108", "node": 2853, "naklon": 10 }, +{ "label": "15/109", "node": 2715, "naklon": 10 }, +{ "label": "15/110", "node": 2712, "naklon": 0 }, +{ "label": "15/111", "node": 2711, "naklon": 0 }, +{ "label": "15/112", "node": 2709, "naklon": 0 }, +{ "label": "15/113", "node": 2710, "naklon": 0 }, +{ "label": "15/114", "node": 2907, "naklon": 0 }, +{ "label": "15/115", "node": 2906, "naklon": 0 }, +{ "label": "15/116", "node": 2908, "naklon": 0 }, +{ "label": "15/117", "node": 2901, "naklon": 0 }, +{ "label": "15/118", "node": 2913, "naklon": 0 }, +{ "label": "15/119", "node": 3656, "naklon": 0 }, +{ "label": "15/120", "node": 2781, "naklon": 0 }, +{ "label": "15/121", "node": 2802, "naklon": 0 }, +{ "label": "15/122", "node": 2791, "naklon": 0 }, +{ "label": "15/123", "node": 2783, "naklon": 0 }, +{ "label": "15/124", "node": 2794, "naklon": 0 }, +{ "label": "15/125", "node": 3139, "naklon": 0 }, +{ "label": "15/126", "node": 3229, "naklon": 5 }, +{ "label": "15/127", "node": 3239, "naklon": 5 }, +{ "label": "15/128", "node": 3230, "naklon": 5 }, +{ "label": "15/129", "node": 4016, "naklon": null }, +{ "label": "16/16A", "node": 3608, "naklon": 0 }, +{ "label": "16/16B", "node": 4151, "naklon": 0 }, +{ "label": "16/1", "node": 3710, "naklon": 0 }, +{ "label": "16/2", "node": 3726, "naklon": 0 }, +{ "label": "16/3", "node": 3743, "naklon": 0 }, +{ "label": "16/4", "node": 3724, "naklon": 0 }, +{ "label": "16/5", "node": 3712, "naklon": 0 }, +{ "label": "16/6", "node": 3739, "naklon": 0 }, +{ "label": "16/7", "node": 3742, "naklon": 0 }, +{ "label": "16/8", "node": 3731, "naklon": 0 }, +{ "label": "16/9", "node": 3727, "naklon": 0 }, +{ "label": "16/10", "node": 3729, "naklon": 0 }, +{ "label": "16/11", "node": 3736, "naklon": 0 }, +{ "label": "16/12", "node": 3713, "naklon": 0 }, +{ "label": "16/13", "node": 3715, "naklon": 0 }, +{ "label": "16/14", "node": 3733, "naklon": 0 }, +{ "label": "16/15", "node": 3732, "naklon": 0 }, +{ "label": "16/17", "node": 3634, "naklon": 0 }, +{ "label": "16/18", "node": 3610, "naklon": 0 }, +{ "label": "16/19", "node": 3626, "naklon": 0 }, +{ "label": "16/20", "node": 3618, "naklon": 0 }, +{ "label": "16/21", "node": 3619, "naklon": 0 }, +{ "label": "16/22", "node": 3628, "naklon": 0 }, +{ "label": "16/23", "node": 3615, "naklon": 0 }, +{ "label": "16/24", "node": 3609, "naklon": 0 }, +{ "label": "16/25", "node": 3606, "naklon": 0 }, +{ "label": "16/26", "node": 3624, "naklon": 0 }, +{ "label": "16/27", "node": 3627, "naklon": 0 }, +{ "label": "16/28", "node": 3607, "naklon": 0 }, +{ "label": "16/29", "node": 4370, "naklon": 0 }, +{ "label": "16/30", "node": 3692, "naklon": 0 }, +{ "label": "16/31", "node": 3614, "naklon": 0 }, +{ "label": "16/32", "node": 3623, "naklon": 0 }, +{ "label": "16/33", "node": 4373, "naklon": 0 }, +{ "label": "16/34", "node": 3620, "naklon": 0 }, +{ "label": "16/35", "node": 3685, "naklon": 0 }, +{ "label": "16/36", "node": 3616, "naklon": 0 }, +{ "label": "16/37", "node": 3686, "naklon": 0 }, +{ "label": "16/38", "node": 3688, "naklon": 0 }, +{ "label": "16/39", "node": 3684, "naklon": 0 }, +{ "label": "16/40", "node": 3825, "naklon": 0 }, +{ "label": "16/41", "node": 3865, "naklon": 0 }, +{ "label": "16/42", "node": 3824, "naklon": 0 }, +{ "label": "16/43", "node": 3871, "naklon": 0 }, +{ "label": "16/44", "node": 3801, "naklon": 0 }, +{ "label": "16/45", "node": 3862, "naklon": 0 }, +{ "label": "16/46", "node": 3876, "naklon": 0 }, +{ "label": "16/47", "node": 3861, "naklon": 0 }, +{ "label": "16/48", "node": 4215, "naklon": 0 }, +{ "label": "16/49", "node": 3605, "naklon": 10 }, +{ "label": "16/50", "node": 3603, "naklon": 10 }, +{ "label": "16/51", "node": 3592, "naklon": 10 }, +{ "label": "16/52", "node": 3598, "naklon": 10 }, +{ "label": "16/53", "node": 3594, "naklon": 10 }, +{ "label": "16/54", "node": 3593, "naklon": 10 }, +{ "label": "16/55", "node": 3630, "naklon": 10 }, +{ "label": "16/56", "node": 3763, "naklon": 10 }, +{ "label": "16/57", "node": 3746, "naklon": 10 }, +{ "label": "16/58", "node": 3699, "naklon": 0 }, +{ "label": "16/59", "node": 3698, "naklon": 0 }, +{ "label": "16/60", "node": 3709, "naklon": null }, +{ "label": "16/61", "node": 3708, "naklon": 0 }, +{ "label": "16/62", "node": 3703, "naklon": null }, +{ "label": "16/63", "node": 3700, "naklon": 0 }, +{ "label": "16/64", "node": 3701, "naklon": null }, +{ "label": "16/65", "node": 3704, "naklon": 0 }, +{ "label": "16/66", "node": 3707, "naklon": null }, +{ "label": "16/67", "node": 3810, "naklon": 0 }, +{ "label": "16/68", "node": 4208, "naklon": null }, +{ "label": "16/69", "node": 3867, "naklon": 0 }, +{ "label": "16/70", "node": 4372, "naklon": null }, +{ "label": "16/71", "node": 3881, "naklon": 0 }, +{ "label": "16/72", "node": 4204, "naklon": null }, +{ "label": "16/73", "node": 3869, "naklon": 0 }, +{ "label": "16/74", "node": 4202, "naklon": null }, +{ "label": "16/75", "node": 3830, "naklon": 0 }, +{ "label": "16/76", "node": 3870, "naklon": null }, +{ "label": "16/77", "node": 3964, "naklon": 0 }, +{ "label": "16/78", "node": 3849, "naklon": 0 }, +{ "label": "16/79", "node": 3694, "naklon": null }, +{ "label": "16/80", "node": 3717, "naklon": 0 }, +{ "label": "16/81", "node": 3877, "naklon": null }, +{ "label": "16/82", "node": 3755, "naklon": 0 }, +{ "label": "16/83", "node": 3725, "naklon": null }, +{ "label": "16/84", "node": 3716, "naklon": 0 }, +{ "label": "16/85", "node": 3696, "naklon": null }, +{ "label": "16/86", "node": 3702, "naklon": 0 }, +{ "label": "16/87", "node": 3706, "naklon": null }, +{ "label": "16/88", "node": 3850, "naklon": 0 }, +{ "label": "16/89", "node": 3848, "naklon": null }, +{ "label": "16/90", "node": 3737, "naklon": null }, +{ "label": "16/91", "node": 3705, "naklon": 0 }, +{ "label": "16/92", "node": 3723, "naklon": null }, +{ "label": "16/93", "node": 3842, "naklon": 0 }, +{ "label": "16/94", "node": 3735, "naklon": null }, +{ "label": "16/95", "node": 3719, "naklon": 0 }, +{ "label": "16/96", "node": 3697, "naklon": 0 }, +{ "label": "16/97", "node": 3711, "naklon": 0 }, +{ "label": "16/98", "node": 4107, "naklon": null }, +{ "label": "16/99", "node": 4112, "naklon": 5 }, +{ "label": "16/100", "node": 4106, "naklon": 5 }, +{ "label": "16/101", "node": 4111, "naklon": 5 }, +{ "label": "16/102", "node": 4091, "naklon": null }, +{ "label": "16/103", "node": 4104, "naklon": 5 }, +{ "label": "16/104", "node": 4094, "naklon": null }, +{ "label": "16/105", "node": 4089, "naklon": 5 }, +{ "label": "16/106", "node": 4095, "naklon": null }, +{ "label": "16/107", "node": 4102, "naklon": 5 }, +{ "label": "16/108", "node": 4105, "naklon": null }, +{ "label": "16/109", "node": 3859, "naklon": null }, +{ "label": "16/110", "node": 4090, "naklon": 5 }, +{ "label": "16/111", "node": 4110, "naklon": null }, +{ "label": "16/112", "node": 4097, "naklon": 5 }, +{ "label": "16/113", "node": 4099, "naklon": null }, +{ "label": "16/114", "node": 4096, "naklon": null }, +{ "label": "16/115", "node": 4101, "naklon": 5 }, +{ "label": "16/116", "node": 4109, "naklon": null }, +{ "label": "16/117", "node": 4092, "naklon": 5 }, +{ "label": "16/118", "node": 3631, "naklon": null }, +{ "label": "16/119", "node": 3632, "naklon": 0 }, +{ "label": "16/120", "node": 3641, "naklon": null }, +{ "label": "16/121", "node": 3638, "naklon": 0 }, +{ "label": "16/122", "node": 3637, "naklon": null }, +{ "label": "16/123", "node": 4142, "naklon": null }, +{ "label": "16/124", "node": 4147, "naklon": 5 }, +{ "label": "16/125", "node": 4139, "naklon": 5 }, +{ "label": "20/30A", "node": 3172, "naklon": 2 }, +{ "label": "20/30B", "node": 3164, "naklon": 2 }, +{ "label": "20/1", "node": 3247, "naklon": 10 }, +{ "label": "20/2", "node": 3296, "naklon": 10 }, +{ "label": "20/3", "node": 3246, "naklon": 10 }, +{ "label": "20/4", "node": 3270, "naklon": 10 }, +{ "label": "20/5", "node": 3294, "naklon": 10 }, +{ "label": "20/6", "node": 3298, "naklon": 10 }, +{ "label": "20/7", "node": 3297, "naklon": 10 }, +{ "label": "20/8", "node": 3293, "naklon": 10 }, +{ "label": "20/9", "node": 3299, "naklon": 10 }, +{ "label": "20/10", "node": 3295, "naklon": 10 }, +{ "label": "20/11", "node": 3244, "naklon": 10 }, +{ "label": "20/12", "node": 3249, "naklon": 10 }, +{ "label": "20/13", "node": 3268, "naklon": 10 }, +{ "label": "20/14", "node": 3245, "naklon": 10 }, +{ "label": "20/15", "node": 3278, "naklon": 10 }, +{ "label": "20/16", "node": 3280, "naklon": 10 }, +{ "label": "20/17", "node": 3292, "naklon": 10 }, +{ "label": "20/18", "node": 3287, "naklon": 10 }, +{ "label": "20/19", "node": 3282, "naklon": 10 }, +{ "label": "20/20", "node": 3273, "naklon": 0 }, +{ "label": "20/21", "node": 3157, "naklon": 0 }, +{ "label": "20/22", "node": 3283, "naklon": 0 }, +{ "label": "20/23", "node": 3159, "naklon": 0 }, +{ "label": "20/24", "node": 3289, "naklon": 0 }, +{ "label": "20/25", "node": 3163, "naklon": 0 }, +{ "label": "20/26", "node": 3126, "naklon": 0 }, +{ "label": "20/27", "node": 3171, "naklon": 0 }, +{ "label": "20/28", "node": 3162, "naklon": 0 }, +{ "label": "20/29", "node": 3279, "naklon": 10 }, +{ "label": "20/31", "node": 3173, "naklon": 0 }, +{ "label": "20/32", "node": 3127, "naklon": 0 }, +{ "label": "20/33", "node": 3131, "naklon": 0 }, +{ "label": "20/34", "node": 3129, "naklon": 0 }, +{ "label": "20/35", "node": 3276, "naklon": 2 }, +{ "label": "20/36", "node": 3290, "naklon": 2 }, +{ "label": "20/37", "node": 3132, "naklon": 0 }, +{ "label": "20/38", "node": 3138, "naklon": 0 }, +{ "label": "20/39", "node": 3272, "naklon": 0 }, +{ "label": "20/40", "node": 3291, "naklon": 0 }, +{ "label": "20/41", "node": 3277, "naklon": 10 }, +{ "label": "20/42", "node": 3286, "naklon": 10 }, +{ "label": "20/43", "node": 3281, "naklon": 10 }, +{ "label": "20/44", "node": 3288, "naklon": 10 }, +{ "label": "20/45", "node": 3284, "naklon": 10 }, +{ "label": "20/46", "node": 3167, "naklon": 10 }, +{ "label": "20/47", "node": 3872, "naklon": 0 }, +{ "label": "20/48", "node": 3124, "naklon": 0 }, +{ "label": "20/49", "node": 3133, "naklon": 0 }, +{ "label": "20/50", "node": 3158, "naklon": 0 }, +{ "label": "20/51", "node": 3169, "naklon": 0 }, +{ "label": "20/52", "node": 3146, "naklon": 0 }, +{ "label": "20/53", "node": 3160, "naklon": 0 }, +{ "label": "20/54", "node": 3248, "naklon": 0 }, +{ "label": "20/55", "node": 3156, "naklon": 0 }, +{ "label": "20/56", "node": 3161, "naklon": 0 }, +{ "label": "20/57", "node": 3170, "naklon": 0 }, +{ "label": "20/58", "node": 3168, "naklon": 0 }, +{ "label": "20/59", "node": 3125, "naklon": 0 }, +{ "label": "20/60", "node": 3166, "naklon": 0 }, +{ "label": "20/61", "node": 3130, "naklon": 0 }, +{ "label": "20/62", "node": 3563, "naklon": 0 }, +{ "label": "20/63", "node": 3550, "naklon": null }, +{ "label": "20/67", "node": 3269, "naklon": 0 }, +{ "label": "21/1", "node": 2921, "naklon": 0 }, +{ "label": "21/2", "node": 2707, "naklon": 0 }, +{ "label": "21/3", "node": 2723, "naklon": 0 }, +{ "label": "21/4", "node": 2716, "naklon": 0 }, +{ "label": "21/5", "node": 2717, "naklon": 0 }, +{ "label": "21/6", "node": 2720, "naklon": 0 }, +{ "label": "21/7", "node": 2722, "naklon": 0 }, +{ "label": "21/8", "node": 2718, "naklon": 0 }, +{ "label": "21/9", "node": 2724, "naklon": 0 }, +{ "label": "21/10", "node": 2742, "naklon": 0 }, +{ "label": "21/11", "node": 2743, "naklon": 0 }, +{ "label": "21/12", "node": 2733, "naklon": 0 }, +{ "label": "21/14", "node": 2903, "naklon": 0 }, +{ "label": "21/15", "node": 2917, "naklon": 0 }, +{ "label": "21/16", "node": 2897, "naklon": 0 }, +{ "label": "21/17", "node": 2914, "naklon": 0 }, +{ "label": "21/18", "node": 2898, "naklon": 0 }, +{ "label": "21/19", "node": 2773, "naklon": 0 }, +{ "label": "21/20", "node": 2895, "naklon": 0 }, +{ "label": "21/21", "node": 2896, "naklon": 0 }, +{ "label": "21/22", "node": 2771, "naklon": 0 }, +{ "label": "21/23", "node": 2772, "naklon": 0 }, +{ "label": "21/24", "node": 2793, "naklon": 0 }, +{ "label": "21/25", "node": 2902, "naklon": 0 }, +{ "label": "21/26", "node": 2910, "naklon": 0 }, +{ "label": "21/27", "node": 2909, "naklon": 0 }, +{ "label": "21/28", "node": 2920, "naklon": 0 }, +{ "label": "21/29", "node": 2916, "naklon": 0 }, +{ "label": "21/30", "node": 2904, "naklon": 0 }, +{ "label": "21/31", "node": 2915, "naklon": 0 }, +{ "label": "21/32", "node": 2905, "naklon": 0 }, +{ "label": "21/33", "node": 2900, "naklon": 0 }, +{ "label": "21/34", "node": 2899, "naklon": 0 }, +{ "label": "21/36", "node": 2741, "naklon": 0 }, +{ "label": "21/37", "node": 2714, "naklon": 0 }, +{ "label": "21/38", "node": 2701, "naklon": 0 }, +{ "label": "21/39", "node": 2703, "naklon": 0 }, +{ "label": "21/40", "node": 2704, "naklon": 0 }, +{ "label": "21/41", "node": 2702, "naklon": 0 }, +{ "label": "21/42", "node": 2706, "naklon": 0 }, +{ "label": "21/43", "node": 2776, "naklon": 0 }, +{ "label": "21/44", "node": 2770, "naklon": 0 }, +{ "label": "21/45", "node": 2786, "naklon": 0 }, +{ "label": "21/46", "node": 2779, "naklon": 0 }, +{ "label": "21/47", "node": 2782, "naklon": 0 }, +{ "label": "21/48", "node": 2785, "naklon": 0 }, +{ "label": "21/49", "node": 2769, "naklon": 0 }, +{ "label": "21/50", "node": 3354, "naklon": 0 }, +{ "label": "21/51", "node": 2778, "naklon": 0 }, +{ "label": "21/52", "node": 2775, "naklon": 0 }, +{ "label": "21/53", "node": 2780, "naklon": 0 }, +{ "label": "21/54", "node": 2790, "naklon": 0 }, +{ "label": "21/55", "node": 2792, "naklon": 0 }, +{ "label": "21/56", "node": 2774, "naklon": 0 }, +{ "label": "22/1", "node": 2630, "naklon": 0 }, +{ "label": "22/2", "node": 2631, "naklon": 0 }, +{ "label": "22/3", "node": 2632, "naklon": 0 }, +{ "label": "22/4", "node": 2633, "naklon": 0 }, +{ "label": "22/5", "node": 2634, "naklon": 0 }, +{ "label": "22/6", "node": 2636, "naklon": 0 }, +{ "label": "22/7", "node": 4367, "naklon": 0 }, +{ "label": "22/8", "node": 2637, "naklon": 0 }, +{ "label": "22/9", "node": 2638, "naklon": 0 }, +{ "label": "22/10", "node": 2639, "naklon": 0 }, +{ "label": "22/11", "node": 2640, "naklon": 0 }, +{ "label": "22/12", "node": 2641, "naklon": 0 }, +{ "label": "22/13", "node": 2642, "naklon": 0 }, +{ "label": "22/14", "node": 2643, "naklon": 0 }, +{ "label": "22/15", "node": 2644, "naklon": 0 }, +{ "label": "22/16", "node": 2645, "naklon": 0 }, +{ "label": "22/17", "node": 2646, "naklon": 0 }, +{ "label": "22/18", "node": 2647, "naklon": 0 }, +{ "label": "22/19", "node": 2648, "naklon": 0 }, +{ "label": "22/20", "node": 2649, "naklon": 0 }, +{ "label": "22/21", "node": 2650, "naklon": 0 }, +{ "label": "22/22", "node": 2651, "naklon": 0 }, +{ "label": "22/23", "node": 4103, "naklon": 0 }, +{ "label": "22/24", "node": 2653, "naklon": 0 }, +{ "label": "22/25", "node": 2654, "naklon": 0 }, +{ "label": "22/26", "node": 2655, "naklon": 0 }, +{ "label": "22/27", "node": 2656, "naklon": 0 }, +{ "label": "22/28", "node": 2657, "naklon": 0 }, +{ "label": "22/29", "node": 2658, "naklon": 0 }, +{ "label": "22/30", "node": 2659, "naklon": 0 }, +{ "label": "22/31", "node": 2660, "naklon": 0 }, +{ "label": "22/32", "node": 2661, "naklon": 0 }, +{ "label": "22/32/1", "node": 3015, "naklon": 0 }, +{ "label": "22/33", "node": 2662, "naklon": 0 }, +{ "label": "22/34", "node": 2663, "naklon": 0 }, +{ "label": "22/35", "node": 2664, "naklon": 0 }, +{ "label": "22/36", "node": 2665, "naklon": 0 }, +{ "label": "22/37", "node": 2666, "naklon": 0 }, +{ "label": "22/38", "node": 2667, "naklon": 0 }, +{ "label": "22/39", "node": 2668, "naklon": 0 }, +{ "label": "22/40", "node": 2669, "naklon": null }, +{ "label": "22/41", "node": 2670, "naklon": null }, +{ "label": "22/42", "node": 2671, "naklon": null }, +{ "label": "23/9A", "node": 3087, "naklon": 10 }, +{ "label": "23/9B", "node": 3090, "naklon": 10 }, +{ "label": "23/1", "node": 3075, "naklon": 0 }, +{ "label": "23/2", "node": 3089, "naklon": 0 }, +{ "label": "23/3", "node": 3088, "naklon": 0 }, +{ "label": "23/4", "node": 3228, "naklon": 10 }, +{ "label": "23/5", "node": 2751, "naklon": 10 }, +{ "label": "23/6", "node": 3243, "naklon": 10 }, +{ "label": "23/7", "node": 4349, "naklon": 10 }, +{ "label": "23/8", "node": 3102, "naklon": 10 }, +{ "label": "23/10", "node": 3099, "naklon": 10 }, +{ "label": "23/11", "node": 3103, "naklon": 10 }, +{ "label": "23/12", "node": 3093, "naklon": 10 }, +{ "label": "23/13", "node": 3098, "naklon": 10 }, +{ "label": "23/14", "node": 3092, "naklon": 10 }, +{ "label": "23/15", "node": 3233, "naklon": 0 }, +{ "label": "23/16", "node": 3095, "naklon": 0 }, +{ "label": "23/17", "node": 4074, "naklon": 0 }, +{ "label": "23/18", "node": 2729, "naklon": 0 }, +{ "label": "23/19", "node": 3234, "naklon": 0 }, +{ "label": "23/20", "node": 3094, "naklon": 0 }, +{ "label": "23/21", "node": 2817, "naklon": 0 }, +{ "label": "23/22", "node": 3226, "naklon": 0 }, +{ "label": "23/23", "node": 3225, "naklon": 0 }, +{ "label": "23/24", "node": 3237, "naklon": 0 }, +{ "label": "23/25", "node": 4250, "naklon": 0 }, +{ "label": "23/26", "node": 3059, "naklon": 10 }, +{ "label": "23/27", "node": 3238, "naklon": 10 }, +{ "label": "23/28", "node": 3242, "naklon": 10 }, +{ "label": "23/29", "node": 3236, "naklon": 10 }, +{ "label": "23/30", "node": 3112, "naklon": 10 }, +{ "label": "23/31", "node": 3224, "naklon": 0 }, +{ "label": "23/32", "node": 4298, "naklon": 10 }, +{ "label": "23/33", "node": 4150, "naklon": 10 }, +{ "label": "23/34", "node": 3091, "naklon": 10 }, +{ "label": "25/1", "node": 3771, "naklon": 5 }, +{ "label": "25/2", "node": 3777, "naklon": 5 }, +{ "label": "25/3", "node": 3749, "naklon": 5 }, +{ "label": "25/4", "node": 3769, "naklon": 5 }, +{ "label": "25/5", "node": 3765, "naklon": 5 }, +{ "label": "25/6", "node": 3785, "naklon": 5 }, +{ "label": "25/7", "node": 3761, "naklon": 5 }, +{ "label": "25/8", "node": 3758, "naklon": 5 }, +{ "label": "25/9", "node": 3766, "naklon": 5 }, +{ "label": "25/10", "node": 3779, "naklon": 5 }, +{ "label": "25/11", "node": 3899, "naklon": 10 }, +{ "label": "25/12", "node": 3922, "naklon": 10 }, +{ "label": "25/13", "node": 3912, "naklon": 10 }, +{ "label": "25/14", "node": 3933, "naklon": 10 }, +{ "label": "25/15", "node": 3921, "naklon": 10 }, +{ "label": "25/16", "node": 4300, "naklon": 10 }, +{ "label": "25/17", "node": 3927, "naklon": 10 }, +{ "label": "25/18", "node": 3212, "naklon": 10 }, +{ "label": "25/19", "node": 3208, "naklon": 10 }, +{ "label": "25/20", "node": 3207, "naklon": 10 }, +{ "label": "25/21", "node": 4294, "naklon": 10 }, +{ "label": "25/22", "node": 3209, "naklon": 10 }, +{ "label": "25/23", "node": 3745, "naklon": 10 }, +{ "label": "25/24", "node": 3762, "naklon": 10 }, +{ "label": "25/25", "node": 3215, "naklon": 10 }, +{ "label": "25/26", "node": 3210, "naklon": 10 }, +{ "label": "25/27", "node": 3211, "naklon": 10 }, +{ "label": "25/28", "node": 3206, "naklon": 10 }, +{ "label": "25/29", "node": 3918, "naklon": 5 }, +{ "label": "25/30", "node": 3928, "naklon": 5 }, +{ "label": "25/31", "node": 3917, "naklon": 5 }, +{ "label": "25/32", "node": 4029, "naklon": 0 }, +{ "label": "25/33", "node": 4038, "naklon": 0 }, +{ "label": "25/34", "node": 4022, "naklon": 0 }, +{ "label": "25/35", "node": 3937, "naklon": 0 }, +{ "label": "25/36", "node": 3190, "naklon": 0 }, +{ "label": "25/37", "node": 3835, "naklon": 0 }, +{ "label": "25/38", "node": 3201, "naklon": 0 }, +{ "label": "25/39", "node": 3193, "naklon": 0 }, +{ "label": "25/40", "node": 3191, "naklon": 0 }, +{ "label": "25/41", "node": 3203, "naklon": 0 }, +{ "label": "25/42", "node": 4301, "naklon": 0 }, +{ "label": "25/43", "node": 3223, "naklon": 0 }, +{ "label": "25/44", "node": 3202, "naklon": 0 }, +{ "label": "25/45", "node": 3205, "naklon": 0 }, +{ "label": "25/46", "node": 3194, "naklon": 0 }, +{ "label": "25/47", "node": 3198, "naklon": 0 }, +{ "label": "25/48", "node": 3204, "naklon": 0 }, +{ "label": "25/49", "node": 3200, "naklon": 0 }, +{ "label": "25/50", "node": 3216, "naklon": 0 }, +{ "label": "25/51", "node": 3932, "naklon": 5 }, +{ "label": "25/52", "node": 3923, "naklon": 5 }, +{ "label": "25/53", "node": 3913, "naklon": 5 }, +{ "label": "25/54", "node": 3900, "naklon": 5 }, +{ "label": "25/55", "node": 4189, "naklon": 10 }, +{ "label": "25/56", "node": 4191, "naklon": 10 }, +{ "label": "25/57", "node": 3790, "naklon": 10 }, +{ "label": "25/58", "node": 4190, "naklon": 10 }, +{ "label": "25/59", "node": 4302, "naklon": 0 }, +{ "label": "25/60", "node": 4351, "naklon": 0 }, +{ "label": "25/61", "node": 4075, "naklon": 0 }, +{ "label": "25/62", "node": 4071, "naklon": 0 }, +{ "label": "25/63", "node": 3784, "naklon": 0 }, +{ "label": "25/64", "node": 4065, "naklon": 0 }, +{ "label": "25/65", "node": 4297, "naklon": 0 }, +{ "label": "25/66", "node": 4295, "naklon": 0 }, +{ "label": "25/67", "node": 4299, "naklon": 0 }, +{ "label": "25/68", "node": 3772, "naklon": 0 }, +{ "label": "25/69", "node": 3941, "naklon": 0 }, +{ "label": "25/70", "node": 3782, "naklon": 0 }, +{ "label": "25/71", "node": 4068, "naklon": 0 }, +{ "label": "25/72", "node": 4073, "naklon": 0 }, +{ "label": "25/73", "node": 3901, "naklon": 5 }, +{ "label": "25/74", "node": 4296, "naklon": 5 }, +{ "label": "25/75", "node": 3910, "naklon": 5 }, +{ "label": "25/76", "node": 4293, "naklon": 5 }, +{ "label": "25/77", "node": 3919, "naklon": 5 }, +{ "label": "25/78", "node": 3924, "naklon": 5 }, +{ "label": "25/79", "node": 3909, "naklon": 5 }, +{ "label": "25/80", "node": 3896, "naklon": 5 }, +{ "label": "25/81", "node": 3911, "naklon": 5 }, +{ "label": "25/82", "node": 2819, "naklon": 15 }, +{ "label": "25/83", "node": 3776, "naklon": 15 }, +{ "label": "25/84", "node": 3752, "naklon": 15 }, +{ "label": "25/85", "node": 4353, "naklon": 15 }, +{ "label": "25/86", "node": 3791, "naklon": 0 }, +{ "label": "25/87", "node": 3770, "naklon": 0 }, +{ "label": "25/88", "node": 3760, "naklon": 0 }, +{ "label": "25/89", "node": 3115, "naklon": 0 }, +{ "label": "25/90", "node": 3738, "naklon": 0 }, +{ "label": "25/91", "node": 3748, "naklon": 0 }, +{ "label": "25/92", "node": 3753, "naklon": 0 }, +{ "label": "25/93", "node": 3775, "naklon": 0 }, +{ "label": "25/94", "node": 3778, "naklon": 5 }, +{ "label": "25/95", "node": 4078, "naklon": 5 }, +{ "label": "25/96", "node": 4088, "naklon": 5 }, +{ "label": "25/97", "node": 3856, "naklon": 5 }, +{ "label": "25/98", "node": 4084, "naklon": 5 }, +{ "label": "25/99", "node": 4069, "naklon": 5 }, +{ "label": "25/100", "node": 4188, "naklon": 5 }, +{ "label": "25/101", "node": 4064, "naklon": 5 }, +{ "label": "25/102", "node": 3792, "naklon": 5 }, +{ "label": "25/103", "node": 3780, "naklon": 5 }, +{ "label": "25/104", "node": 4034, "naklon": 5 }, +{ "label": "25/105", "node": 4072, "naklon": 5 }, +{ "label": "25/106", "node": 3884, "naklon": 5 }, +{ "label": "25/107", "node": 3793, "naklon": 5 }, +{ "label": "25/108", "node": 3863, "naklon": 5 }, +{ "label": "25/109", "node": 3855, "naklon": 5 }, +{ "label": "33/1", "node": 3846, "naklon": 0 }, +{ "label": "33/2", "node": 3943, "naklon": 0 }, +{ "label": "33/3", "node": 3903, "naklon": 0 }, +{ "label": "33/4", "node": 3982, "naklon": 0 }, +{ "label": "33/5", "node": 3879, "naklon": 0 }, +{ "label": "33/6", "node": 3887, "naklon": 0 }, +{ "label": "33/7", "node": 3920, "naklon": 5 }, +{ "label": "33/8", "node": 3942, "naklon": 5 }, +{ "label": "33/9", "node": 3829, "naklon": null }, +{ "label": "34/79A", "node": 3452, "naklon": 6 }, +{ "label": "34/79B", "node": 3460, "naklon": 6 }, +{ "label": "34/90A", "node": 3443, "naklon": 6 }, +{ "label": "34/90B", "node": 3445, "naklon": 6 }, +{ "label": "34/90C", "node": 3457, "naklon": 6 }, +{ "label": "34/97A", "node": 3461, "naklon": 6 }, +{ "label": "34/97B", "node": 3463, "naklon": 6 }, +{ "label": "34/98A", "node": 3426, "naklon": 6 }, +{ "label": "34/98B", "node": 3444, "naklon": 6 }, +{ "label": "34/99A", "node": 3453, "naklon": 6 }, +{ "label": "34/99B", "node": 3455, "naklon": 6 }, +{ "label": "34/1", "node": 4009, "naklon": 0 }, +{ "label": "34/2", "node": 3602, "naklon": 0 }, +{ "label": "34/3", "node": 3441, "naklon": 0 }, +{ "label": "34/4", "node": 3464, "naklon": 0 }, +{ "label": "34/5", "node": 3883, "naklon": 0 }, +{ "label": "34/6", "node": 4098, "naklon": 0 }, +{ "label": "34/7", "node": 4003, "naklon": 0 }, +{ "label": "34/8", "node": 4004, "naklon": 0 }, +{ "label": "34/9", "node": 3888, "naklon": 0 }, +{ "label": "34/10", "node": 3997, "naklon": 0 }, +{ "label": "34/11", "node": 4006, "naklon": 0 }, +{ "label": "34/12", "node": 4000, "naklon": 0 }, +{ "label": "34/13", "node": 4011, "naklon": 0 }, +{ "label": "34/14", "node": 3999, "naklon": 0 }, +{ "label": "34/15", "node": 3981, "naklon": 0 }, +{ "label": "34/16", "node": 3988, "naklon": 0 }, +{ "label": "34/17", "node": 3986, "naklon": 0 }, +{ "label": "34/18", "node": 3998, "naklon": 0 }, +{ "label": "34/19", "node": 3983, "naklon": 0 }, +{ "label": "34/20", "node": 4005, "naklon": 0 }, +{ "label": "34/21", "node": 4001, "naklon": 0 }, +{ "label": "34/22", "node": 4008, "naklon": 0 }, +{ "label": "34/23", "node": 4002, "naklon": 0 }, +{ "label": "34/24", "node": 3996, "naklon": 0 }, +{ "label": "34/25", "node": 4007, "naklon": 0 }, +{ "label": "34/26", "node": 4113, "naklon": 15 }, +{ "label": "34/27", "node": 3595, "naklon": 5 }, +{ "label": "34/28", "node": 3599, "naklon": 5 }, +{ "label": "34/29", "node": 3601, "naklon": 5 }, +{ "label": "34/30", "node": 4205, "naklon": 0 }, +{ "label": "34/31", "node": 3987, "naklon": null }, +{ "label": "34/32", "node": 4214, "naklon": 0 }, +{ "label": "34/33", "node": 4226, "naklon": 0 }, +{ "label": "34/34", "node": 4209, "naklon": 0 }, +{ "label": "34/35", "node": 4201, "naklon": 0 }, +{ "label": "34/36", "node": 3440, "naklon": 0 }, +{ "label": "34/37", "node": 3465, "naklon": 0 }, +{ "label": "34/38", "node": 3446, "naklon": 0 }, +{ "label": "34/39", "node": 4039, "naklon": 5 }, +{ "label": "34/40", "node": 4057, "naklon": 5 }, +{ "label": "34/41", "node": 3985, "naklon": 0 }, +{ "label": "34/42", "node": 3882, "naklon": 0 }, +{ "label": "34/43", "node": 4040, "naklon": 5 }, +{ "label": "34/44", "node": 3231, "naklon": 0 }, +{ "label": "34/45", "node": 3227, "naklon": 0 }, +{ "label": "34/46", "node": 3431, "naklon": 0 }, +{ "label": "34/47", "node": 4013, "naklon": 0 }, +{ "label": "34/48", "node": 4045, "naklon": 0 }, +{ "label": "34/49", "node": 3949, "naklon": 0 }, +{ "label": "34/50", "node": 3953, "naklon": 0 }, +{ "label": "34/51", "node": 3952, "naklon": 0 }, +{ "label": "34/52", "node": 3995, "naklon": 0 }, +{ "label": "34/53", "node": 3992, "naklon": 0 }, +{ "label": "34/54", "node": 4198, "naklon": 0 }, +{ "label": "34/55", "node": 3935, "naklon": 0 }, +{ "label": "34/56", "node": 4050, "naklon": 0 }, +{ "label": "34/57", "node": 4049, "naklon": 0 }, +{ "label": "34/58", "node": 4054, "naklon": 0 }, +{ "label": "34/59", "node": 3663, "naklon": 6 }, +{ "label": "34/60", "node": 3661, "naklon": 6 }, +{ "label": "34/61", "node": 3664, "naklon": 6 }, +{ "label": "34/62", "node": 3660, "naklon": 6 }, +{ "label": "34/63", "node": 3662, "naklon": 6 }, +{ "label": "34/65", "node": 3665, "naklon": 6 }, +{ "label": "34/66", "node": 3667, "naklon": 6 }, +{ "label": "34/67", "node": 3675, "naklon": 6 }, +{ "label": "34/68", "node": 3666, "naklon": 6 }, +{ "label": "34/69", "node": 3652, "naklon": 6 }, +{ "label": "34/70", "node": 3458, "naklon": 6 }, +{ "label": "34/70/1", "node": 4425, "naklon": 6 }, +{ "label": "34/71", "node": 3459, "naklon": 6 }, +{ "label": "34/72", "node": 3435, "naklon": 6 }, +{ "label": "34/73", "node": 3448, "naklon": 6 }, +{ "label": "34/74", "node": 3451, "naklon": 6 }, +{ "label": "34/75", "node": 3442, "naklon": 6 }, +{ "label": "34/76", "node": 3449, "naklon": 6 }, +{ "label": "34/77", "node": 3450, "naklon": 6 }, +{ "label": "34/78", "node": 3433, "naklon": 6 }, +{ "label": "34/80", "node": 3432, "naklon": 12 }, +{ "label": "34/81", "node": 3470, "naklon": 12 }, +{ "label": "34/82", "node": 3438, "naklon": 12 }, +{ "label": "34/83", "node": 3439, "naklon": 12 }, +{ "label": "34/84", "node": 4028, "naklon": 5 }, +{ "label": "34/85", "node": 3596, "naklon": 5 }, +{ "label": "34/86", "node": 4021, "naklon": 5 }, +{ "label": "34/87", "node": 3437, "naklon": 12 }, +{ "label": "34/88", "node": 3428, "naklon": 12 }, +{ "label": "34/89", "node": 3430, "naklon": 12 }, +{ "label": "34/91", "node": 3454, "naklon": 6 }, +{ "label": "34/92", "node": 3492, "naklon": 6 }, +{ "label": "34/93", "node": 3462, "naklon": 6 }, +{ "label": "34/94", "node": 3427, "naklon": 6 }, +{ "label": "34/95", "node": 3434, "naklon": 6 }, +{ "label": "34/96", "node": 3456, "naklon": 6 }, +{ "label": "34/98/1", "node": 4307, "naklon": 6 }, +{ "label": "35/1", "node": 3968, "naklon": 0 }, +{ "label": "35/2", "node": 3969, "naklon": 0 }, +{ "label": "35/3", "node": 3947, "naklon": 0 }, +{ "label": "35/4", "node": 3979, "naklon": 0 }, +{ "label": "35/5", "node": 3959, "naklon": 0 }, +{ "label": "35/6", "node": 3948, "naklon": 0 }, +{ "label": "35/7", "node": 3961, "naklon": 0 }, +{ "label": "35/8", "node": 3956, "naklon": 0 }, +{ "label": "35/9", "node": 3604, "naklon": 0 }, +{ "label": "35/10", "node": 3944, "naklon": 0 }, +{ "label": "35/11", "node": 3960, "naklon": 0 }, +{ "label": "35/12", "node": 3958, "naklon": 0 }, +{ "label": "35/13", "node": 4036, "naklon": 5 }, +{ "label": "35/18", "node": 3893, "naklon": 5 }, +{ "label": "35/19", "node": 4108, "naklon": 5 }, +{ "label": "35/20", "node": 4017, "naklon": 5 }, +{ "label": "35/21", "node": 3963, "naklon": 0 }, +{ "label": "35/22", "node": 3658, "naklon": 0 }, +{ "label": "35/23", "node": 3975, "naklon": 0 }, +{ "label": "35/24", "node": 3980, "naklon": 0 }, +{ "label": "35/25", "node": 4012, "naklon": 0 }, +{ "label": "35/26", "node": 3655, "naklon": 0 }, +{ "label": "35/27", "node": 3962, "naklon": 0 }, +{ "label": "35/28", "node": 3945, "naklon": 0 }, +{ "label": "35/29", "node": 3569, "naklon": 0 }, +{ "label": "35/30", "node": 3429, "naklon": 0 }, +{ "label": "35/31", "node": 3657, "naklon": 0 }, +{ "label": "35/32", "node": 3646, "naklon": 0 }, +{ "label": "35/33", "node": 3622, "naklon": 0 }, +{ "label": "35/34", "node": 3612, "naklon": 0 }, +{ "label": "35/35", "node": 3955, "naklon": 0 }, +{ "label": "35/37", "node": 3878, "naklon": 0 }, +{ "label": "35/38", "node": 3965, "naklon": 0 }, +{ "label": "35/39", "node": 3970, "naklon": 0 }, +{ "label": "35/40", "node": 3611, "naklon": 0 }, +{ "label": "35/41", "node": 2635, "naklon": 0 }, +{ "label": "35/42", "node": 3978, "naklon": 0 }, +{ "label": "35/43", "node": 4213, "naklon": 0 }, +{ "label": "35/44", "node": 3984, "naklon": 0 }, +{ "label": "35/45", "node": 4218, "naklon": 0 }, +{ "label": "35/46", "node": 3973, "naklon": 0 }, +{ "label": "35/47", "node": 3974, "naklon": 0 }, +{ "label": "35/48", "node": 3759, "naklon": 0 }, +{ "label": "35/49", "node": 3844, "naklon": 0 }, +{ "label": "35/50", "node": 3804, "naklon": 0 }, +{ "label": "35/51", "node": 3831, "naklon": 0 }, +{ "label": "35/52", "node": 3643, "naklon": 0 }, +{ "label": "35/53", "node": 3966, "naklon": 0 }, +{ "label": "35/54", "node": 3971, "naklon": 0 }, +{ "label": "35/55", "node": 3650, "naklon": 6 }, +{ "label": "35/56", "node": 3651, "naklon": 6 }, +{ "label": "35/57", "node": 3669, "naklon": 6 }, +{ "label": "35/58", "node": 3648, "naklon": 6 }, +{ "label": "35/59", "node": 3645, "naklon": 6 }, +{ "label": "35/60", "node": 3659, "naklon": 6 }, +{ "label": "35/61", "node": 3647, "naklon": 6 }, +{ "label": "35/62", "node": 3644, "naklon": 6 }, +{ "label": "35/63", "node": 3671, "naklon": 6 }, +{ "label": "35/64", "node": 3682, "naklon": 6 }, +{ "label": "35/65", "node": 3672, "naklon": 6 }, +{ "label": "35/66", "node": 3683, "naklon": 6 }, +{ "label": "35/67", "node": 3673, "naklon": 6 }, +{ "label": "35/68", "node": 3674, "naklon": 6 }, +{ "label": "35/69", "node": 3679, "naklon": 6 }, +{ "label": "35/70", "node": 3649, "naklon": 6 }, +{ "label": "35/71", "node": 3687, "naklon": 6 }, +{ "label": "35/72", "node": 3677, "naklon": 6 }, +{ "label": "35/73", "node": 3690, "naklon": 6 }, +{ "label": "35/74", "node": 3691, "naklon": 6 }, +{ "label": "35/75", "node": 3676, "naklon": 6 }, +{ "label": "35/76", "node": 3680, "naklon": 6 }, +{ "label": "35/77", "node": 3668, "naklon": 6 }, +{ "label": "35/78", "node": 3681, "naklon": 6 }, +{ "label": "35/79", "node": 3670, "naklon": 6 }, +{ "label": "35/80", "node": 3689, "naklon": 6 }, +{ "label": "35/81", "node": 3678, "naklon": 6 }, +{ "label": "35/82", "node": 3693, "naklon": 6 }, +{ "label": "35/83", "node": 3654, "naklon": null }, +{ "label": "36/1", "node": 4086, "naklon": 0 }, +{ "label": "36/2", "node": 4085, "naklon": 0 }, +{ "label": "36/3", "node": 4083, "naklon": 0 }, +{ "label": "36/4", "node": 4087, "naklon": 0 }, +{ "label": "36/5", "node": 4077, "naklon": 0 }, +{ "label": "36/6", "node": 4082, "naklon": 0 }, +{ "label": "36/7", "node": 4186, "naklon": 0 }, +{ "label": "36/8", "node": 4206, "naklon": 0 }, +{ "label": "36/9", "node": 4080, "naklon": 0 }, +{ "label": "36/10", "node": 4081, "naklon": 0 }, +{ "label": "36/11", "node": 4210, "naklon": 0 }, +{ "label": "36/12", "node": 4079, "naklon": 0 }, +{ "label": "36/13", "node": 4076, "naklon": 0 }, +{ "label": "36/14", "node": 3852, "naklon": 0 }, +{ "label": "36/15", "node": 2813, "naklon": 0 }, +{ "label": "36/16", "node": 4219, "naklon": 0 }, +{ "label": "37/1A", "node": 3104, "naklon": 15 }, +{ "label": "37/1B", "node": 3121, "naklon": 15 }, +{ "label": "37/2", "node": 3113, "naklon": 10 }, +{ "label": "37/3", "node": 3118, "naklon": 10 }, +{ "label": "37/4", "node": 3111, "naklon": 10 }, +{ "label": "37/5", "node": 4020, "naklon": 10 }, +{ "label": "37/6", "node": 3119, "naklon": 10 }, +{ "label": "37/7", "node": 3110, "naklon": 10 }, +{ "label": "37/8", "node": 3108, "naklon": 10 }, +{ "label": "37/12", "node": 3107, "naklon": 0 }, +{ "label": "37/13", "node": 3199, "naklon": 0 }, +{ "label": "37/14", "node": 3120, "naklon": 0 }, +{ "label": "37/15", "node": 3122, "naklon": 0 }, +{ "label": "37/16", "node": 3908, "naklon": 0 }, +{ "label": "37/17", "node": 3114, "naklon": 0 }, +{ "label": "37/18", "node": 3105, "naklon": 0 }, +{ "label": "37/19", "node": 3116, "naklon": 0 }, +{ "label": "37/20", "node": 3106, "naklon": 0 }, +{ "label": "37/21", "node": 2887, "naklon": 5 }, +{ "label": "37/22", "node": 2888, "naklon": 5 }, +{ "label": "37/23", "node": 2877, "naklon": 5 }, +{ "label": "37/24", "node": 2891, "naklon": 5 }, +{ "label": "37/25", "node": 2886, "naklon": 5 }, +{ "label": "37/26", "node": 2892, "naklon": 5 }, +{ "label": "37/27", "node": 2882, "naklon": 5 }, +{ "label": "37/28", "node": 2883, "naklon": 5 }, +{ "label": "37/29", "node": 2876, "naklon": 5 }, +{ "label": "37/30", "node": 3109, "naklon": 5 }, +{ "label": "37/31", "node": 4152, "naklon": 5 }, +{ "label": "37/32", "node": 3117, "naklon": 5 }, +{ "label": "37/33", "node": 2870, "naklon": 5 }, +{ "label": "37/34", "node": 2867, "naklon": 0 }, +{ "label": "37/35", "node": 2865, "naklon": 0 }, +{ "label": "37/36", "node": 3096, "naklon": 0 }, +{ "label": "37/37", "node": 2871, "naklon": 0 }, +{ "label": "37/38", "node": 2884, "naklon": 0 }, +{ "label": "37/39", "node": 2855, "naklon": 0 }, +{ "label": "37/40", "node": 2878, "naklon": 0 }, +{ "label": "37/41", "node": 2889, "naklon": 0 }, +{ "label": "37/42", "node": 2879, "naklon": 0 }, +{ "label": "37/43", "node": 2850, "naklon": 0 }, +{ "label": "37/44", "node": 2894, "naklon": 0 }, +{ "label": "37/45", "node": 2880, "naklon": 0 }, +{ "label": "37/46", "node": 2893, "naklon": 0 }, +{ "label": "37/47", "node": 2890, "naklon": 0 }, +{ "label": "37/48", "node": 4355, "naklon": 0 }, +{ "label": "37/49", "node": 2885, "naklon": 0 }, +{ "label": "37/50", "node": 2875, "naklon": 0 }, +{ "label": "38/30A", "node": 3486, "naklon": 5 }, +{ "label": "38/30B", "node": 3714, "naklon": 0 }, +{ "label": "38/32A", "node": 3483, "naklon": 5 }, +{ "label": "38/32B", "node": 3496, "naklon": 0 }, +{ "label": "38/35A", "node": 3487, "naklon": 5 }, +{ "label": "38/35B", "node": 3498, "naklon": 5 }, +{ "label": "38/38A", "node": 3578, "naklon": 5 }, +{ "label": "38/38B", "node": 3508, "naklon": 5 }, +{ "label": "38/59A", "node": 3787, "naklon": 5 }, +{ "label": "38/59B", "node": 3491, "naklon": 5 }, +{ "label": "38/1", "node": 3568, "naklon": null }, +{ "label": "38/2", "node": 3502, "naklon": 0 }, +{ "label": "38/3", "node": 3836, "naklon": 0 }, +{ "label": "38/4", "node": 3588, "naklon": 0 }, +{ "label": "38/5", "node": 3493, "naklon": 0 }, +{ "label": "38/6", "node": 3580, "naklon": 0 }, +{ "label": "38/7", "node": 3572, "naklon": 0 }, +{ "label": "38/8", "node": 3506, "naklon": 0 }, +{ "label": "38/9", "node": 3503, "naklon": 0 }, +{ "label": "38/10", "node": 3579, "naklon": 0 }, +{ "label": "38/11", "node": 3586, "naklon": 0 }, +{ "label": "38/12", "node": 3495, "naklon": 5 }, +{ "label": "38/13", "node": 3492, "naklon": 5 }, +{ "label": "38/14", "node": 3532, "naklon": 5 }, +{ "label": "38/15", "node": 3574, "naklon": 5 }, +{ "label": "38/16", "node": 4140, "naklon": 5 }, +{ "label": "38/17", "node": 3795, "naklon": 5 }, +{ "label": "38/18", "node": 3788, "naklon": 5 }, +{ "label": "38/19", "node": 3796, "naklon": 5 }, +{ "label": "38/20", "node": 3797, "naklon": 5 }, +{ "label": "38/21", "node": 3798, "naklon": 5 }, +{ "label": "38/22", "node": 3786, "naklon": 5 }, +{ "label": "38/23", "node": 4067, "naklon": 5 }, +{ "label": "38/24", "node": 3773, "naklon": 5 }, +{ "label": "38/25", "node": 3774, "naklon": 5 }, +{ "label": "38/26", "node": 3789, "naklon": 5 }, +{ "label": "38/27", "node": 3520, "naklon": null }, +{ "label": "38/29", "node": 3577, "naklon": 5 }, +{ "label": "38/31", "node": 3530, "naklon": null }, +{ "label": "38/33", "node": 3488, "naklon": 5 }, +{ "label": "38/34", "node": 3505, "naklon": 5 }, +{ "label": "38/36", "node": 3497, "naklon": 5 }, +{ "label": "38/37", "node": 3490, "naklon": 5 }, +{ "label": "38/39", "node": 3585, "naklon": 5 }, +{ "label": "38/40", "node": 3582, "naklon": 5 }, +{ "label": "38/41", "node": 3507, "naklon": 5 }, +{ "label": "38/42", "node": 3484, "naklon": 5 }, +{ "label": "38/43", "node": 3501, "naklon": 5 }, +{ "label": "38/44", "node": 3581, "naklon": 5 }, +{ "label": "38/45", "node": 4192, "naklon": 5 }, +{ "label": "38/46", "node": 3576, "naklon": 5 }, +{ "label": "38/47", "node": 3489, "naklon": 5 }, +{ "label": "38/48", "node": 3573, "naklon": 5 }, +{ "label": "38/49", "node": 3504, "naklon": 5 }, +{ "label": "38/50", "node": 3794, "naklon": 5 }, +{ "label": "38/51", "node": 3485, "naklon": 5 }, +{ "label": "38/52", "node": 3482, "naklon": 5 }, +{ "label": "38/53", "node": 3575, "naklon": 5 }, +{ "label": "38/54", "node": 3499, "naklon": 5 }, +{ "label": "38/55", "node": 3494, "naklon": 5 }, +{ "label": "38/56", "node": 3583, "naklon": 5 }, +{ "label": "38/57", "node": 3570, "naklon": 5 }, +{ "label": "38/58", "node": 3500, "naklon": 0 }, +{ "label": "38/63", "node": 3510, "naklon": null }, +{ "label": "38/64", "node": 3512, "naklon": null }, +{ "label": "38/67", "node": 3535, "naklon": null }, +{ "label": "38/68", "node": 3531, "naklon": null }, +{ "label": "38/69", "node": 3537, "naklon": null }, +{ "label": "39/1", "node": 3522, "naklon": 10 }, +{ "label": "39/2", "node": 4018, "naklon": 10 }, +{ "label": "39/3", "node": 4019, "naklon": 10 }, +{ "label": "39/4", "node": 4154, "naklon": 5 }, +{ "label": "39/5", "node": 3907, "naklon": 5 }, +{ "label": "39/6", "node": 4148, "naklon": 0 }, +{ "label": "39/7", "node": 4153, "naklon": 0 }, +{ "label": "39/8", "node": 3938, "naklon": 0 }, +{ "label": "39/9", "node": 3802, "naklon": 0 }, +{ "label": "39/10", "node": 4015, "naklon": 0 }, +{ "label": "39/11", "node": 3929, "naklon": 0 }, +{ "label": "39/12", "node": 3946, "naklon": 0 }, +{ "label": "39/13", "node": 4014, "naklon": 0 }, +{ "label": "39/14", "node": 4155, "naklon": 0 }, +{ "label": "39/15", "node": 4149, "naklon": 0 }, +{ "label": "39/16", "node": 3642, "naklon": 0 }, +{ "label": "39/17", "node": 3636, "naklon": 5 }, +{ "label": "39/18", "node": 3991, "naklon": 0 }, +{ "label": "39/19", "node": 3994, "naklon": 0 }, +{ "label": "39/20", "node": 3990, "naklon": 0 }, +{ "label": "39/21", "node": 3967, "naklon": 0 }, +{ "label": "39/22", "node": 3977, "naklon": 0 }, +{ "label": "39/23", "node": 3757, "naklon": 15 }, +{ "label": "39/24", "node": 3633, "naklon": 15 }, +{ "label": "39/25", "node": 3744, "naklon": 15 }, +{ "label": "39/26", "node": 4023, "naklon": 5 }, +{ "label": "39/27", "node": 3720, "naklon": 5 }, +{ "label": "39/28", "node": 3734, "naklon": 5 }, +{ "label": "39/29", "node": 3741, "naklon": 5 }, +{ "label": "39/30", "node": 3721, "naklon": 5 }, +{ "label": "39/31", "node": 3845, "naklon": 0 }, +{ "label": "39/32", "node": 3840, "naklon": 0 }, +{ "label": "39/33", "node": 3837, "naklon": null }, +{ "label": "39/34", "node": 3839, "naklon": 0 }, +{ "label": "41/1", "node": 3542, "naklon": null }, +{ "label": "41/2", "node": 3566, "naklon": null }, +{ "label": "41/3", "node": 3548, "naklon": null }, +{ "label": "41/4", "node": 3515, "naklon": null }, +{ "label": "41/5", "node": 3559, "naklon": null }, +{ "label": "41/6", "node": 3509, "naklon": null }, +{ "label": "41/7", "node": 3524, "naklon": null }, +{ "label": "41/8", "node": 3518, "naklon": null }, +{ "label": "41/9", "node": 3182, "naklon": null }, +{ "label": "41/10", "node": 3187, "naklon": null }, +{ "label": "41/11", "node": 3195, "naklon": 0 }, +{ "label": "41/12", "node": 3857, "naklon": 0 }, +{ "label": "41/13", "node": 3183, "naklon": 0 }, +{ "label": "41/14", "node": 3177, "naklon": 0 }, +{ "label": "41/15", "node": 3189, "naklon": 0 }, +{ "label": "41/16", "node": 3186, "naklon": 0 }, +{ "label": "42/1", "node": 3178, "naklon": 0 }, +{ "label": "42/2", "node": 3219, "naklon": 0 }, +{ "label": "42/3", "node": 3475, "naklon": 0 }, +{ "label": "42/4", "node": 3175, "naklon": 0 }, +{ "label": "42/5", "node": 3222, "naklon": 0 }, +{ "label": "42/6", "node": 3221, "naklon": 0 }, +{ "label": "42/7", "node": 3181, "naklon": 0 }, +{ "label": "42/8", "node": 3180, "naklon": 0 }, +{ "label": "42/9", "node": 3218, "naklon": 0 }, +{ "label": "42/10", "node": 3176, "naklon": 0 }, +{ "label": "42/11", "node": 3174, "naklon": 0 }, +{ "label": "42/12", "node": 3220, "naklon": 0 }, +{ "label": "42/13", "node": 3533, "naklon": null }, +{ "label": "42/14", "node": 3543, "naklon": null }, +{ "label": "42/15", "node": 3554, "naklon": null }, +{ "label": "42/16", "node": 3549, "naklon": null }, +{ "label": "43/1", "node": 2857, "naklon": 5 }, +{ "label": "43/2", "node": 2752, "naklon": 5 }, +{ "label": "43/3", "node": 2753, "naklon": 5 }, +{ "label": "43/4", "node": 3024, "naklon": 5 }, +{ "label": "43/5", "node": 2754, "naklon": 5 }, +{ "label": "43/6", "node": 4423, "naklon": 5 }, +{ "label": "43/7", "node": 4368, "naklon": 5 }, +{ "label": "43/8", "node": 2978, "naklon": 5 }, +{ "label": "43/9", "node": 2868, "naklon": 5 }, +{ "label": "43/10", "node": 4377, "naklon": 5 }, +{ "label": "43/11", "node": 2757, "naklon": 5 }, +{ "label": "43/12", "node": 2970, "naklon": 5 }, +{ "label": "43/13", "node": 2758, "naklon": 5 }, +{ "label": "43/14", "node": 4378, "naklon": 5 }, +{ "label": "43/15", "node": 2759, "naklon": 5 }, +{ "label": "43/16", "node": 4342, "naklon": 5 }, +{ "label": "43/17", "node": 3026, "naklon": null }, +{ "label": "43/18", "node": 2986, "naklon": null }, +{ "label": "43/19", "node": 4343, "naklon": null }, +{ "label": "43/20", "node": 2760, "naklon": null }, +{ "label": "43/21", "node": 4379, "naklon": null }, +{ "label": "43/22", "node": 2971, "naklon": null }, +{ "label": "43/23", "node": 2761, "naklon": null }, +{ "label": "43/24", "node": 2762, "naklon": null }, +{ "label": "43/25", "node": 4339, "naklon": null }, +{ "label": "43/26", "node": 4380, "naklon": null }, +{ "label": "43/27", "node": 2975, "naklon": null }, +{ "label": "43/28", "node": 3003, "naklon": null }, +{ "label": "43/29", "node": 4338, "naklon": null }, +{ "label": "43/30", "node": 3002, "naklon": null }, +{ "label": "43/31", "node": 4345, "naklon": null }, +{ "label": "43/32", "node": 2979, "naklon": null }, +{ "label": "43/33", "node": 2989, "naklon": null }, +{ "label": "43/34", "node": 2996, "naklon": null }, +{ "label": "43/35", "node": 2972, "naklon": null }, +{ "label": "43/36", "node": 2988, "naklon": null }, +{ "label": "43/37", "node": 4344, "naklon": null }, +{ "label": "43/38", "node": 3022, "naklon": null }, +{ "label": "43/39", "node": 4341, "naklon": null }, +{ "label": "43/40", "node": 2983, "naklon": null }, +{ "label": "43/41", "node": 2995, "naklon": null }, +{ "label": "43/42", "node": 2763, "naklon": null }, +{ "label": "43/43", "node": 2764, "naklon": null }, +{ "label": "43/44", "node": 2765, "naklon": null }, +{ "label": "43/45", "node": 2766, "naklon": null }, +{ "label": "43/46", "node": 2767, "naklon": null }, +{ "label": "43/47", "node": 2768, "naklon": null }, +{ "label": "43/48", "node": 3018, "naklon": null }, +{ "label": "43/49", "node": 2982, "naklon": null }, +{ "label": "43/50", "node": 3019, "naklon": 0 }, +{ "label": "43/51", "node": 3013, "naklon": null }, +{ "label": "43/52", "node": 3007, "naklon": null }, +{ "label": "43/53", "node": 2980, "naklon": null }, +{ "label": "43/54", "node": 3011, "naklon": null }, +{ "label": "43/55", "node": 2672, "naklon": null }, +{ "label": "43/56", "node": 2673, "naklon": null }, +{ "label": "43/57", "node": 2674, "naklon": null }, +{ "label": "43/58", "node": 2675, "naklon": null }, +{ "label": "43/59", "node": 2676, "naklon": null }, +{ "label": "43/60", "node": 2677, "naklon": null }, +{ "label": "43/61", "node": 2678, "naklon": null }, +{ "label": "43/62", "node": 2679, "naklon": null }, +{ "label": "43/63", "node": 2680, "naklon": null }, +{ "label": "43/64", "node": 2840, "naklon": null }, +{ "label": "43/65", "node": 2682, "naklon": null }, +{ "label": "43/66", "node": 2683, "naklon": null }, +{ "label": "43/67", "node": 2684, "naklon": 0 }, +{ "label": "43/68", "node": 2685, "naklon": null }, +{ "label": "43/69", "node": 2686, "naklon": null }, +{ "label": "43/70", "node": 2687, "naklon": null }, +{ "label": "43/71", "node": 2688, "naklon": null }, +{ "label": "43/72", "node": 2689, "naklon": null }, +{ "label": "43/73", "node": 2690, "naklon": null }, +{ "label": "43/74", "node": 2691, "naklon": null }, +{ "label": "43/75", "node": 2692, "naklon": null }, +{ "label": "43/76", "node": 2693, "naklon": 0 }, +{ "label": "43/77", "node": 2694, "naklon": null }, +{ "label": "43/78", "node": 2695, "naklon": null }, +{ "label": "43/79", "node": 2696, "naklon": 0 }, +{ "label": "43/80", "node": 2697, "naklon": null }, +{ "label": "43/81", "node": 2698, "naklon": 0 }, +{ "label": "43/82", "node": 2699, "naklon": null }, +{ "label": "43/83", "node": 2700, "naklon": 0 }, +{ "label": "43/84", "node": 2744, "naklon": null }, +{ "label": "43/85", "node": 2745, "naklon": 0 }, +{ "label": "43/86", "node": 2746, "naklon": null }, +{ "label": "43/87", "node": 2747, "naklon": 0 }, +{ "label": "43/88", "node": 2748, "naklon": null }, +{ "label": "43/89", "node": 2749, "naklon": 0 }, +{ "label": "43/90", "node": 2841, "naklon": null }, +{ "label": "45/1", "node": 4237, "naklon": 5 }, +{ "label": "45/2", "node": 4226, "naklon": 5 }, +{ "label": "45/3", "node": 4242, "naklon": 5 }, +{ "label": "45/4", "node": 4179, "naklon": 5 }, +{ "label": "45/5", "node": 4247, "naklon": 5 }, +{ "label": "45/6", "node": 4245, "naklon": 5 }, +{ "label": "45/7", "node": 3872, "naklon": 5 }, +{ "label": "45/8", "node": 4175, "naklon": 5 }, +{ "label": "45/9", "node": 4236, "naklon": 5 }, +{ "label": "45/10", "node": 4170, "naklon": 5 }, +{ "label": "45/11", "node": 4238, "naklon": 5 }, +{ "label": "45/12", "node": 4246, "naklon": 5 }, +{ "label": "45/13", "node": 4166, "naklon": 5 }, +{ "label": "45/14", "node": 4227, "naklon": 5 }, +{ "label": "45/15", "node": 4171, "naklon": 5 }, +{ "label": "45/16", "node": 4180, "naklon": 5 }, +{ "label": "45/17", "node": 4244, "naklon": 5 }, +{ "label": "45/18", "node": 4199, "naklon": 5 }, +{ "label": "45/19", "node": 4239, "naklon": 5 }, +{ "label": "45/20", "node": 4207, "naklon": 5 }, +{ "label": "45/21", "node": 4223, "naklon": 5 }, +{ "label": "45/22", "node": 4230, "naklon": 5 }, +{ "label": "45/23", "node": 4233, "naklon": 5 }, +{ "label": "45/24", "node": 4222, "naklon": 5 }, +{ "label": "45/25", "node": 4217, "naklon": 5 }, +{ "label": "45/26", "node": 4243, "naklon": 5 }, +{ "label": "45/27", "node": 4200, "naklon": 5 }, +{ "label": "45/28", "node": 4228, "naklon": 5 }, +{ "label": "45/29", "node": 4211, "naklon": 5 }, +{ "label": "45/30", "node": 4234, "naklon": 5 }, +{ "label": "45/31", "node": 4235, "naklon": 5 }, +{ "label": "45/32", "node": 4203, "naklon": 5 }, +{ "label": "45/33", "node": 4240, "naklon": 5 }, +{ "label": "45/34", "node": 4224, "naklon": 5 }, +{ "label": "45/35", "node": 4232, "naklon": 5 }, +{ "label": "45/36", "node": 4231, "naklon": 5 }, +{ "label": "45/37", "node": 4161, "naklon": 5 }, +{ "label": "45/38", "node": 4225, "naklon": 5 }, +{ "label": "45/39", "node": 4241, "naklon": 5 }, +{ "label": "45/40", "node": 4229, "naklon": 5 }, +{ "label": "45/41", "node": 4221, "naklon": 5 }, +{ "label": "45/42", "node": 4212, "naklon": 5 }, +{ "label": "45/43", "node": 4216, "naklon": 5 }, +{ "label": "45/44", "node": 3864, "naklon": null }, +{ "label": "46/1", "node": 3806, "naklon": 5 }, +{ "label": "46/2", "node": 3813, "naklon": 5 }, +{ "label": "46/3", "node": 3815, "naklon": 5 }, +{ "label": "46/4", "node": 3807, "naklon": 5 }, +{ "label": "46/5", "node": 3895, "naklon": 5 }, +{ "label": "46/6", "node": 3809, "naklon": 5 }, +{ "label": "46/7", "node": 3820, "naklon": 5 }, +{ "label": "46/8", "node": 3805, "naklon": 5 }, +{ "label": "46/9", "node": 3894, "naklon": 0 }, +{ "label": "46/10", "node": 4055, "naklon": 0 }, +{ "label": "46/11", "node": 3812, "naklon": 5 }, +{ "label": "46/12", "node": 3822, "naklon": 5 }, +{ "label": "46/13", "node": 3821, "naklon": 5 }, +{ "label": "46/14", "node": 3808, "naklon": 5 }, +{ "label": "46/15", "node": 3799, "naklon": 5 }, +{ "label": "46/16", "node": 3816, "naklon": 5 }, +{ "label": "46/17", "node": 3751, "naklon": 5 }, +{ "label": "46/18", "node": 3814, "naklon": 5 }, +{ "label": "46/19", "node": 4044, "naklon": 0 }, +{ "label": "46/20", "node": 3931, "naklon": 0 }, +{ "label": "46/21", "node": 3902, "naklon": 5 }, +{ "label": "46/22", "node": 3916, "naklon": 5 }, +{ "label": "46/23", "node": 3892, "naklon": 5 }, +{ "label": "46/24", "node": 3914, "naklon": 5 }, +{ "label": "46/25", "node": 3898, "naklon": 5 }, +{ "label": "46/26", "node": 3897, "naklon": 5 }, +{ "label": "46/27", "node": 3885, "naklon": 5 }, +{ "label": "46/28", "node": 3906, "naklon": 5 }, +{ "label": "46/29", "node": 3930, "naklon": 0 }, +{ "label": "46/30", "node": 3936, "naklon": 0 }, +{ "label": "46/31", "node": 3860, "naklon": 5 }, +{ "label": "46/32", "node": 3841, "naklon": 5 }, +{ "label": "46/33", "node": 3873, "naklon": 5 }, +{ "label": "46/34", "node": 3854, "naklon": 5 }, +{ "label": "46/35", "node": 3939, "naklon": 5 }, +{ "label": "46/36", "node": 3858, "naklon": 5 }, +{ "label": "46/37", "node": 3940, "naklon": 5 }, +{ "label": "46/38", "node": 4035, "naklon": 5 }, +{ "label": "47/1", "node": 3373, "naklon": 0 }, +{ "label": "47/2", "node": 3374, "naklon": 0 }, +{ "label": "47/3", "node": 3384, "naklon": 0 }, +{ "label": "47/4", "node": 3385, "naklon": 0 }, +{ "label": "48/1", "node": 4051, "naklon": 5 }, +{ "label": "48/2", "node": 4041, "naklon": 5 }, +{ "label": "48/3", "node": 4056, "naklon": 5 }, +{ "label": "48/4", "node": 3875, "naklon": 5 }, +{ "label": "48/5", "node": 4061, "naklon": 5 }, +{ "label": "48/6", "node": 4047, "naklon": 5 }, +{ "label": "48/7", "node": 4060, "naklon": 5 }, +{ "label": "48/8", "node": 4059, "naklon": 5 }, +{ "label": "48/9", "node": 4058, "naklon": 5 }, +{ "label": "48/10", "node": 3635, "naklon": 5 }, +{ "label": "48/11", "node": 3640, "naklon": 5 }, +{ "label": "48/12", "node": 3747, "naklon": 5 }, +{ "label": "48/13", "node": 3629, "naklon": 5 }, +{ "label": "48/14", "node": 4048, "naklon": 5 }, +{ "label": "48/15", "node": 4063, "naklon": 5 }, +{ "label": "48/16", "node": 4062, "naklon": 5 }, +{ "label": "48/17", "node": 4043, "naklon": 5 }, +{ "label": "48/18", "node": 4052, "naklon": 5 }, +{ "label": "48/19", "node": 4042, "naklon": 5 }, +{ "label": "48/20", "node": 4053, "naklon": 5 }, +{ "label": "50/15A", "node": 4167, "naklon": null }, +{ "label": "50/15B", "node": 4159, "naklon": null }, +{ "label": "50/1", "node": 4183, "naklon": 0 }, +{ "label": "50/2", "node": 4157, "naklon": 0 }, +{ "label": "50/3", "node": 4160, "naklon": 0 }, +{ "label": "50/4", "node": 4173, "naklon": 0 }, +{ "label": "50/5", "node": 4177, "naklon": 0 }, +{ "label": "50/6", "node": 4174, "naklon": 0 }, +{ "label": "50/7", "node": 4178, "naklon": 0 }, +{ "label": "50/8", "node": 4195, "naklon": 0 }, +{ "label": "50/9", "node": 4169, "naklon": 0 }, +{ "label": "50/10", "node": 4162, "naklon": 0 }, +{ "label": "50/11", "node": 4158, "naklon": 0 }, +{ "label": "50/12", "node": 4182, "naklon": 0 }, +{ "label": "50/13", "node": 4194, "naklon": 0 }, +{ "label": "50/14", "node": 4184, "naklon": 0 }, +{ "label": "50/16", "node": 4197, "naklon": null }, +{ "label": "50/17", "node": 4164, "naklon": null }, +{ "label": "50/18", "node": 3306, "naklon": null }, +{ "label": "50/19", "node": 4168, "naklon": null }, +{ "label": "50/20", "node": 4193, "naklon": null }, +{ "label": "50/21", "node": 4187, "naklon": null }, +{ "label": "50/22", "node": 4163, "naklon": null }, +{ "label": "50/23", "node": 4165, "naklon": null }, +{ "label": "50/24", "node": 4185, "naklon": null }, +{ "label": "50/25", "node": 3904, "naklon": null }, +{ "label": "53/1", "node": 2619, "naklon": 0 }, +{ "label": "53/2", "node": 2623, "naklon": 0 }, +{ "label": "53/3", "node": 2617, "naklon": 0 }, +{ "label": "53/4", "node": 2622, "naklon": 0 }, +{ "label": "53/5", "node": 2618, "naklon": 0 }, +{ "label": "53/6", "node": 2626, "naklon": 0 }, +{ "label": "53/7", "node": 2869, "naklon": 0 }, +{ "label": "53/8", "node": 2613, "naklon": 0 }, +{ "label": "53/9", "node": 2608, "naklon": 0 }, +{ "label": "53/10", "node": 2611, "naklon": 0 }, +{ "label": "53/11", "node": 2598, "naklon": 0 }, +{ "label": "53/12", "node": 3528, "naklon": 0 }, +{ "label": "53/13", "node": 3545, "naklon": 0 }, +{ "label": "53/14", "node": 2620, "naklon": 0 }, +{ "label": "53/15", "node": 2612, "naklon": 0 }, +{ "label": "53/16", "node": 2615, "naklon": 0 }, +{ "label": "53/17", "node": 3722, "naklon": 0 }, +{ "label": "53/18", "node": 2624, "naklon": 0 }, +{ "label": "53/19", "node": 2609, "naklon": 0 }, +{ "label": "53/20", "node": 2625, "naklon": 0 }, +{ "label": "53/21", "node": 2602, "naklon": 0 }, +{ "label": "53/22", "node": 2610, "naklon": 0 }, +{ "label": "53/23", "node": 2599, "naklon": 0 }, +{ "label": "53/24", "node": 2605, "naklon": 0 }, +{ "label": "53/25", "node": 2593, "naklon": 0 }, +{ "label": "53/26", "node": 3074, "naklon": 0 }, +{ "label": "53/27", "node": 2740, "naklon": 0 }, +{ "label": "53/28", "node": 2614, "naklon": 0 }, +{ "label": "53/29", "node": 2601, "naklon": 0 }, +{ "label": "53/30", "node": 4196, "naklon": 0 }, +{ "label": "53/31", "node": 2607, "naklon": 0 }, +{ "label": "53/32", "node": 2582, "naklon": 0 }, +{ "label": "53/33", "node": 2594, "naklon": 0 }, +{ "label": "53/34", "node": 2589, "naklon": 0 }, +{ "label": "53/35", "node": 2596, "naklon": 0 }, +{ "label": "53/36", "node": 2603, "naklon": 0 }, +{ "label": "53/37", "node": 2597, "naklon": 0 }, +{ "label": "53/38", "node": 2590, "naklon": 0 }, +{ "label": "53/39", "node": 2581, "naklon": 0 }, +{ "label": "53/40", "node": 2583, "naklon": 0 }, +{ "label": "53/41", "node": 2580, "naklon": 0 }, +{ "label": "53/42", "node": 2579, "naklon": 0 }, +{ "label": "53/43", "node": 2797, "naklon": 0 }, +{ "label": "53/44", "node": 2577, "naklon": 0 }, +{ "label": "53/45", "node": 2586, "naklon": 0 }, +{ "label": "53/46", "node": 2588, "naklon": 0 }, +{ "label": "53/47", "node": 2591, "naklon": 0 }, +{ "label": "53/48", "node": 2592, "naklon": 0 }, +{ "label": "53/49", "node": 2573, "naklon": 0 }, +{ "label": "53/50", "node": 2595, "naklon": 0 }, +{ "label": "53/51", "node": 2587, "naklon": 0 }, +{ "label": "53/52", "node": 2578, "naklon": 0 }, +{ "label": "53/53", "node": 2574, "naklon": 0 }, +{ "label": "53/54", "node": 2571, "naklon": 0 }, +{ "label": "53/55", "node": 2570, "naklon": 0 }, +{ "label": "53/56", "node": 2576, "naklon": 0 }, +{ "label": "53/57", "node": 2881, "naklon": 0 }, +{ "label": "53/58", "node": 2575, "naklon": 0 }, +{ "label": "53/59", "node": 2572, "naklon": 0 }, +{ "label": "53/60", "node": 2569, "naklon": 0 }, +{ "label": "55/1", "node": 4324, "naklon": 0 }, +{ "label": "55/2", "node": 4319, "naklon": 0 }, +{ "label": "55/3", "node": 4327, "naklon": 0 }, +{ "label": "55/4", "node": 4333, "naklon": 0 }, +{ "label": "55/5", "node": 4332, "naklon": 0 }, +{ "label": "55/6", "node": 4320, "naklon": 0 }, +{ "label": "55/7", "node": 4317, "naklon": 0 }, +{ "label": "55/8", "node": 4318, "naklon": 0 }, +{ "label": "55/9", "node": 4328, "naklon": 0 }, +{ "label": "55/10", "node": 4323, "naklon": 0 }, +{ "label": "55/11", "node": 4325, "naklon": 0 }, +{ "label": "55/12", "node": 4326, "naklon": 0 }, +{ "label": "55/13", "node": 4316, "naklon": 0 }, +{ "label": "55/14", "node": 4322, "naklon": 0 }, +{ "label": "55/15", "node": 4331, "naklon": 0 }, +{ "label": "55/16", "node": 4321, "naklon": 0 }, +{ "label": "55/17", "node": 4315, "naklon": 0 }, +{ "label": "55/18", "node": 4329, "naklon": 0 }, +{ "label": "55/19", "node": 4334, "naklon": 0 }, +{ "label": "55/20", "node": 4330, "naklon": 0 } +]; + +module.exports = { naklony }; diff --git a/RVO37/databases/modbus_config.js b/RVO37/databases/modbus_config.js new file mode 100755 index 0000000..b73116a --- /dev/null +++ b/RVO37/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/RVO37/databases/nodes.table b/RVO37/databases/nodes.table new file mode 100755 index 0000000..4444c13 --- /dev/null +++ b/RVO37/databases/nodes.table @@ -0,0 +1,49 @@ +node:number|pole_number:string|node_type:string|tbname:string|line:number|profile:string|processed:boolean|status:boolean|time_of_last_communication:number ++|3104|1A|NEMA|zdQO8GwxDqjRgP4137YV2qANyKlpem2nL65rvVJY|1||1|1|1760574203645|............. ++|3106|20|NEMA|3JjOWdylwgNLzxVab7NaVBkZ2vG64rq8PEB5QmDo|1||1|1|1760574203789|............. ++|4127|31|NEMA|ZmRwd93QL4gaezxEbAx2zOk1prn2XjlPvGyqJ6BO|1||1|1|1760574148302|............. ++|3117|32|NEMA|eod9aRWLVl34Gx1Dn7VNvM72rz6qjgmpEXwQJN5Z|1||1|1|1760574110401|............. ++|2879|42|NEMA|nJL5lPMwBx23YpqRe0rpGv7damXvWVbOrD4gNzy8|1||1|1|1760574154611|............. ++|2850|43|NEMA|ZmRwd93QL4gaezxEbAx2zXk1prn2XjlPvGyqJ6BO|1||1|1|1760574129982|............. ++|2894|44|NEMA|eod9aRWLVl34Gx1Dn7VNvb72rz6qjgmpEXwQJN5Z|1||1|1|1760574203118|............. ++|3107|12|NEMA|6lQGaY9RDywdVzObj0PaXykPg4NBn3exEK51LWZq|1||1|1|1760574092959|............. ++|3330|8|NEMA|o9vbeQlLMVg8j5dq4keLXR0NxZpEmnXzwYKO1ar2|1||1|1|1760574201824|............. ++|4120|27|NEMA|K94XLav1glVRnyQ6r01P9aAme3YJwBxM5oOzdP2j|1||1|1|1760574129311|............. ++|2883|28|NEMA|d9x2V5LGYBzXp4mMRAOm8qkPloaqJwnQj6DgrNe3|1||1|1|1760574183904|............. ++|2884|38|NEMA|52dD6ZlV1QaOpRBmbAqGzQkKnGzWMLj4eJq38Pgo|1||1|1|1760574184239|............. ++|2885|49|NEMA|52dD6ZlV1QaOpRBmbAqGzMkKnGzWMLj4eJq38Pgo|1||1|1|1760574187530|............. ++|2886|25|NEMA|d5xjWYMwEJon6rLlK7yExK7qgV4DaOeNB9ZX3Gzb|1||1|1|1760574187689|............. ++|4125|21|NEMA|Z5KyJe9nEg1QNbWlX0w4zmkoDjBLdqzR83VGv624|1||1|1|1760574148111|............. ++|2888|22|NEMA|1JMYvnx2RzKEo4aWQ7DGoGkL8yZV3m9NBePXbrdj|1||1|1|1760574187833|............. ++|2889|41|NEMA|roKgWqY95V3mXMRzyAjKzz0bLjexpJPvaGDBw826|1||1|1|1760574188009|............. ++|2890|47|NEMA|wvKJdZML6mXP4DzWBAXxrBAjxNloa5g23Ve9Y1ry|1||1|1|1760574201489|............. ++|2882|30|NEMA|aw4eELG2DlPMdn1JW0BMobAqQXOZRN3xB5yp8VKr|1||1|0|1760287310955|............. ++|3110|7|NEMA|apKVJBwOyrP35m2lv7KYPK0YXbeWNd64En9GxRqg|1||1|1|1760574093135|............. ++|3111|4|NEMA|zrR51V2ajQ9ZLygPKkEM4pkYDq38xOJolENBXGnv|1||1|1|1760574093310|............. ++|3431|2|NEMA|WlVJBygjDZMeKX3vnAMRVQ08NqdmG2x1Y69LQ4P5|1||1|1|1760574202016|............. ++|2891|24|NEMA|dz4ojlpP85JMgDLZWkQJXz7aKYqQexEr62GXRV1y|1||1|1|1760574202655|............. ++|3114|17|NEMA|JX1ObgmqGZ54DMyYL7aDxdkEVdve38WKRzwjNrQ9|1||1|1|1760574093454|............. ++|3116|19|NEMA|RO8rjaBDy21qPQJzW7omz90pK3xmNleVZg9Ed4Gw|1||1|1|1760574093582|............. ++|2892|26|NEMA|gRoJEyXVx4qD9er287L4om7wBzGldaPjLWQKm3Mv|1||1|1|1760574202815|............. ++|3118|3|NEMA|5dBNwRp9graYJxZn409N4VklVov1b2QLPDqGm6XK|1||1|1|1760574205402|............. ++|3119|6|NEMA|DbQY6zyveZRwK5drV0Z8YL7joE4XJM83N9xl2nWq|1||1|1|1760574205562|............. ++|3120|14|NEMA|JzwxZXOvDj1bVrN4nkW5rKA8qdyBl3MRKLpGPgaQ|1||1|1|1760574206345|............. ++|3121|1B|NEMA|DbQY6zyveZRwK5drV0Z82b7joE4XJM83N9xl2nWq|1||1|1|1760574206664|............. ++|3122|15|NEMA|g9OxBZ5KRwNznlY6pAppMdAWXvjdEL4eGQobMDy2|1||1|1|1760574206808|............. ++|4020|5|NEMA|BaY3Xpy1EbKGjLq2O7mado7rx8owgQz9P4dDJRmN|1||1|1|1760574125526|............. ++|3199|13|NEMA|m6EYyZoJ4gWexdjVPAR5gE7RDOq9wv2N5XzKGplr|1||1|1|1760574201329|............. ++|3213|||RvmwNz8QPblKp41GD7lKrVkJrLVYoBO92dMegn6W|1||1|1|1760574201649|............. ++|3908|16|NEMA|OzNMgZ9n43qPbjXmy7zwXdA2DKdYvW5e6pxGRrVa|1||1|1|1760574125131|............. ++|4355|48|NEMA|PLBJzmK1r3Gynd6OW0gKzo0e5wV4vx9bDEqNgYR8|1||1|1|1760574148542|............. ++|2855|39|NEMA|rDbQ84xzwgdqEoPm3kbEed09anOZY1RXyBv2LVM6|1||1|1|1760574130126|............. ++|2867|34|NEMA|EjgWGnXaLy9opPOz20n4zV786BlYM3w1deVQvbKr|1||1|1|1760574153461|............. ++|3445|33|NEMA|3a5oqJN1bgnx4Ol9dk89oZ7ByE6jQ8mKDWMpGrLV|1||1|1|1760574124408|............. ++|3482|37|NEMA|PLBJzmK1r3Gynd6OW0gKzP0e5wV4vx9bDEqNgYR8|1||1|1|1760574124743|............. ++|2875|50|NEMA|rDbQ84xzwgdqEoPm3kbEer09anOZY1RXyBv2LVM6|1||1|1|1760574153637|............. ++|2893|46|NEMA|EjgWGnXaLy9opPOz20n4zm786BlYM3w1deVQvbKr|1||1|1|1760574202958|............. ++|2876|29|NEMA|B5EoxeMVp4zwr8nqW0GBoxARjvD1PNamOGbLg63Z|1||1|1|1760574153781|............. ++|2877|23|NEMA|PjLblDgRBO6WQqnxmkJ1N50Jv3ewZN4p5a89yKdY|1||1|1|1760574154084|............. ++|2878|40|NEMA|E6Kg9oDnLWyzPRMva7v5zxkJxp4VG58qO2w1lZYe|1||1|1|1760574154212|............. ++|2880|45|NEMA|3a5oqJN1bgnx4Ol9dk89ow7ByE6jQ8mKDWMpGrLV|1||1|1|1760574159403|............. ++|3096|36|NEMA|Nzp2OoJlqn6r1ZgvdA3BmK7abBwP5G4eE3RQmyxD|1||1|1|1760574203454|............. ++|2865|35|NEMA|wvKJdZML6mXP4DzWBAXxr1AjxNloa5g23Ve9Y1ry|1||1|1|1760574149245|............. diff --git a/RVO37/databases/nodes_original/nodes_original.table b/RVO37/databases/nodes_original/nodes_original.table new file mode 100755 index 0000000..0aff13d --- /dev/null +++ b/RVO37/databases/nodes_original/nodes_original.table @@ -0,0 +1 @@ +[{"3104": "zdQO8GwxDqjRgP4137YV2qANyKlpem2nL65rvVJY"}, {"3106": "3JjOWdylwgNLzxVab7NaVBkZ2vG64rq8PEB5QmDo"}, {"4127": "ZmRwd93QL4gaezxEbAx2zOk1prn2XjlPvGyqJ6BO"}, {"3117": "eod9aRWLVl34Gx1Dn7VNvM72rz6qjgmpEXwQJN5Z"}, {"2879": "nJL5lPMwBx23YpqRe0rpGv7damXvWVbOrD4gNzy8"}, {"2850": "ZmRwd93QL4gaezxEbAx2zXk1prn2XjlPvGyqJ6BO"}, {"2894": "eod9aRWLVl34Gx1Dn7VNvb72rz6qjgmpEXwQJN5Z"}, {"3107": "6lQGaY9RDywdVzObj0PaXykPg4NBn3exEK51LWZq"}, {"3330": "o9vbeQlLMVg8j5dq4keLXR0NxZpEmnXzwYKO1ar2"}, {"4120": "K94XLav1glVRnyQ6r01P9aAme3YJwBxM5oOzdP2j"}, {"2883": "d9x2V5LGYBzXp4mMRAOm8qkPloaqJwnQj6DgrNe3"}, {"2884": "52dD6ZlV1QaOpRBmbAqGzQkKnGzWMLj4eJq38Pgo"}, {"2885": "52dD6ZlV1QaOpRBmbAqGzMkKnGzWMLj4eJq38Pgo"}, {"2886": "d5xjWYMwEJon6rLlK7yExK7qgV4DaOeNB9ZX3Gzb"}, {"4125": "Z5KyJe9nEg1QNbWlX0w4zmkoDjBLdqzR83VGv624"}, {"2888": "1JMYvnx2RzKEo4aWQ7DGoGkL8yZV3m9NBePXbrdj"}, {"2889": "roKgWqY95V3mXMRzyAjKzz0bLjexpJPvaGDBw826"}, {"2890": "wvKJdZML6mXP4DzWBAXxrBAjxNloa5g23Ve9Y1ry"}, {"2882": "aw4eELG2DlPMdn1JW0BMobAqQXOZRN3xB5yp8VKr"}, {"3110": "apKVJBwOyrP35m2lv7KYPK0YXbeWNd64En9GxRqg"}, {"3111": "zrR51V2ajQ9ZLygPKkEM4pkYDq38xOJolENBXGnv"}, {"3431": "WlVJBygjDZMeKX3vnAMRVQ08NqdmG2x1Y69LQ4P5"}, {"2891": "dz4ojlpP85JMgDLZWkQJXz7aKYqQexEr62GXRV1y"}, {"3114": "JX1ObgmqGZ54DMyYL7aDxdkEVdve38WKRzwjNrQ9"}, {"3116": "RO8rjaBDy21qPQJzW7omz90pK3xmNleVZg9Ed4Gw"}, {"2892": "gRoJEyXVx4qD9er287L4om7wBzGldaPjLWQKm3Mv"}, {"3118": "5dBNwRp9graYJxZn409N4VklVov1b2QLPDqGm6XK"}, {"3119": "DbQY6zyveZRwK5drV0Z8YL7joE4XJM83N9xl2nWq"}, {"3120": "JzwxZXOvDj1bVrN4nkW5rKA8qdyBl3MRKLpGPgaQ"}, {"3121": "DbQY6zyveZRwK5drV0Z82b7joE4XJM83N9xl2nWq"}, {"3122": "g9OxBZ5KRwNznlY6pAppMdAWXvjdEL4eGQobMDy2"}, {"4020": "BaY3Xpy1EbKGjLq2O7mado7rx8owgQz9P4dDJRmN"}, {"3199": "m6EYyZoJ4gWexdjVPAR5gE7RDOq9wv2N5XzKGplr"}, {"3213": "RvmwNz8QPblKp41GD7lKrVkJrLVYoBO92dMegn6W"}, {"3908": "OzNMgZ9n43qPbjXmy7zwXdA2DKdYvW5e6pxGRrVa"}, {"4355": "PLBJzmK1r3Gynd6OW0gKzo0e5wV4vx9bDEqNgYR8"}, {"2855": "rDbQ84xzwgdqEoPm3kbEed09anOZY1RXyBv2LVM6"}, {"2867": "EjgWGnXaLy9opPOz20n4zV786BlYM3w1deVQvbKr"}, {"3445": "3a5oqJN1bgnx4Ol9dk89oZ7ByE6jQ8mKDWMpGrLV"}, {"3482": "PLBJzmK1r3Gynd6OW0gKzP0e5wV4vx9bDEqNgYR8"}, {"2875": "rDbQ84xzwgdqEoPm3kbEer09anOZY1RXyBv2LVM6"}, {"2893": "EjgWGnXaLy9opPOz20n4zm786BlYM3w1deVQvbKr"}, {"2876": "B5EoxeMVp4zwr8nqW0GBoxARjvD1PNamOGbLg63Z"}, {"2877": "PjLblDgRBO6WQqnxmkJ1N50Jv3ewZN4p5a89yKdY"}, {"2878": "E6Kg9oDnLWyzPRMva7v5zxkJxp4VG58qO2w1lZYe"}, {"2880": "3a5oqJN1bgnx4Ol9dk89ow7ByE6jQ8mKDWMpGrLV"}, {"3096": "Nzp2OoJlqn6r1ZgvdA3BmK7abBwP5G4eE3RQmyxD"}, {"2865": "wvKJdZML6mXP4DzWBAXxr1AjxNloa5g23Ve9Y1ry"}] \ No newline at end of file diff --git a/RVO37/databases/notifications.table b/RVO37/databases/notifications.table new file mode 100755 index 0000000..f7c96cb --- /dev/null +++ b/RVO37/databases/notifications.table @@ -0,0 +1,41 @@ +key:string|weight:string|sk:string|en:string ++|switching_profile_point_applied_to_line|INFORMATIONAL|Aplikovaný bod spínacieho profilu na línií č. ${line} : ${value}|Switching profile point applied to line no. ${line} : ${value}|............... ++|dusk_has_occured|INFORMATIONAL|Nastal súmrak: ${value}|Dusk has occured: ${value}|............... ++|dawn_has_occured|INFORMATIONAL|Nastal úsvit: ${value}|Dawn has occured: ${value}|............... ++|dimming_profile_was_successfully_received_by_node|NOTICE|Stmievací profil bol úspešne prijatý nodom č. ${node}|Dimming profile was successfully received by node no. ${node}|............... ++|master_node_is_responding_again|NOTICE|Master node začal znovu odpovedať|Master node is responding again|............... ++|command_was_sent_from_terminal_interface|DEBUG|Z terminálu bol odoslaný príkaz|A command was sent from terminal interface|............... ++|master_node_is_not_responding|ALERT|Master node neodpovedá|Master node is not responding|............... ++|configuration_of_dimming_profile_to_node_failed|ALERT|Konfigurácia stmievacieho profilu pre node č. ${node} zlyhala|Configuration of dimming profile to node no. ${node} has failed|............... ++|circuit_breaker_was_turned_on_line|NOTICE|Zapnutie ističa na línii č. ${line}|Circuit breaker was turned on - line no. ${line}|............... ++|circuit_breaker_was_turned_off_line|ERROR|Vypnutie ističa na línií č. ${line}|Circuit breaker was turned off - line no. ${line}|............... ++|dimming_profile_was_processed_for_node|INFORMATIONAL|Stmievací profil bol spracovaný pre node č. ${node}|Dimming profile was processed for node no. ${node}|............... ++|switching_profile_was_processed_for_line|INFORMATIONAL|Spínací profil bol spracovaný pre líniu č. ${line}|Switching profile was processed for line no. ${line}|............... ++|thermometer_is_not_responding|WARNING|Teplomer neodpovedá|Thermometer is not responding|............... ++|thermometer_is_responding_again|NOTICE|Teplomer znovu odpovedá|Thermometer is responding again|............... ++|thermometer_sends_invalid_data|WARNING|Teplomer posiela neplatné hodnoty|Thermometer sends invalid data|............... ++|main_switch_has_been_turned_off|CRITICAL|Hlavný vypínač bol vypnutý|Main switch has been turned off|............... ++|main_switch_has_been_turned_on|NOTICE|Hlavný vypínač bol zapnutý|Main switch has been turned on|............... ++|power_supply_has_disconnected_input|ALERT|Napájací zdroj nemá napätie na vstupe|Power supply has disconnected input|............... ++|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_main_open|NOTICE|Hlavné dvere boli otvorené|Main door has been opened|............... ++|door_em_open|NOTICE|Dvere silovej časti boli otvorené|Power door has been opened|............... ++|door_main_open_without_permission|WARNING|Hlavné dvere boli otvorené bez povolenia - zapnutá siréna|Main door has been opened without permission - alarm is on|............... ++|door_em_open_without_permission|WARNING|Dvere silovej časti boli otvorené bez povolenia|Power door has been opened without permission|............... ++|door_main_close|NOTICE|Hlavné dvere boli zatvorené|Main door has been closed|............... ++|door_em_close|NOTICE|Dvere silovej časti boli zatvorené|Power door has been closed|............... ++|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|............... ++|electrometer_ok|NOTICE|Elektromer znovu odpovedá|Electrometer is responding again|............... ++|no_voltage_on_phase|CRITICAL|Na fáze č. ${phase} nie je napätie|No voltage detected on phase no. ${phase}|............... ++|voltage_on_phase_restored|NOTICE|Napätie na fáze č. ${phase} bolo obnovené|Voltage on phase no. ${phase} has been restored|............... ++|flow_start|NOTICE|FLOW bol spustený|FLOW has been started |............... ++|twilight_sensor_nok|ERROR|Sensor súmraku neodpovedá|Twilight sensor is not responding|............... ++|twilight_sensor_ok|NOTICE|Sensor súmraku znovu odpovedá|Twilight sensor is responding again|............... ++|lamps_have_turned_on|NOTICE|Lampy sa zapli|Lamps have turned on|............... ++|lamps_have_turned_off|NOTICE|Lampy sa vypli|Lamps have turned off|............... ++|flow_restart|NOTICE|FLOW bol reštartovaný|FLOW has been restarted|............... ++|nodes_db_changed|NOTICE|Zmena v node databáze|Node db has changed|............... diff --git a/RVO37/databases/pins.table b/RVO37/databases/pins.table new file mode 100755 index 0000000..0eb3d05 --- /dev/null +++ b/RVO37/databases/pins.table @@ -0,0 +1,14 @@ +pin:string|type:string|line:number +*|input1_01|door_condition|0|........... +*|input1_02|rotary_switch_state|0|........... +*|input1_03|rotary_switch_state|0|........... +*|input1_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/RVO37/databases/relays.table b/RVO37/databases/relays.table new file mode 100755 index 0000000..68daa22 --- /dev/null +++ b/RVO37/databases/relays.table @@ -0,0 +1,5 @@ +line:number|tbname:string|contactor:number|profile:string ++|0|5dBNwRp9graYJxZn409NrVklVov1b2QLPDqGm6XK|1||........... ++|3|gP1eOZVj3Q9lv5aDEk45gQ7rdpqW8yLm2BbKzJxM|9|{"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":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|apKVJBwOyrP35m2lv7KYvK0YXbeWNd64En9GxRqg|9|{"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":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|o9vbeQlLMVg8j5dq4keLMR0NxZpEmnXzwYKO1ar2|9|{"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":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/RVO37/databases/settings.table b/RVO37/databases/settings.table new file mode 100755 index 0000000..1a1d681 --- /dev/null +++ b/RVO37/databases/settings.table @@ -0,0 +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|project_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|cloud_topic:string|has_main_switch:boolean|daily_report:boolean|send_changed_node_numbers:boolean ++|rvo_senica_37_ip111|en|28.7C46950E0000|48.679371932|17.363406038|192.168.252.1|rvo_senica_37_ip111|KZ56BXU2Dsn96YLJwfgE|1883|0|52|unipi|ttyUSB0|1|20|5|6|3|u111|0|1|1|................................................... diff --git a/RVO37/databases/tbdata.nosql b/RVO37/databases/tbdata.nosql new file mode 100755 index 0000000..4063e92 --- /dev/null +++ b/RVO37/databases/tbdata.nosql @@ -0,0 +1,4 @@ +-"5dBNwRp9graYJxZn409NrVklVov1b2QLPDqGm6XK":[{"ts":1760531317832,"values":{"_event":{"type":"notice","status":"new","source":{"func":"modbus_reader","component":"1699965957410","component_name":"Modbus reader","edge":"5dBNwRp9graYJxZn409NrVklVov1b2QLPDqGm6XK"},"message":{"sk":"rvo_senica_37_ip111: FLOW bol reštartovaný","en":"rvo_senica_37_ip111: FLOW has been restarted"},"message_data":""}}}],"id":"3000328001no71b"} +-"5dBNwRp9graYJxZn409NrVklVov1b2QLPDqGm6XK":[{"ts":1760531317962,"values":{"edge_fw_version":"2025-10-08","maintenance_mode":false}}],"id":"3000328002no70b"} +-"5dBNwRp9graYJxZn409NrVklVov1b2QLPDqGm6XK":[{"ts":1760531317975,"values":{"statecode":2,"power_mode":"Automatic"}}],"id":"3000328004no70b"} +-"5dBNwRp9graYJxZn409NrVklVov1b2QLPDqGm6XK":[{"ts":1760531318025,"values":{"_event":{"type":"notice","status":"new","source":{"func":"rsPort.open()","component":"1699963668903","component_name":"DIDO_Controller","edge":"5dBNwRp9graYJxZn409NrVklVov1b2QLPDqGm6XK"},"message":{"sk":"rvo_senica_37_ip111: FLOW bol spustený","en":"rvo_senica_37_ip111: FLOW has been started "},"message_data":""}}}],"id":"3000328006no70b"} diff --git a/RVO37/databases/tbdatacloud.nosql b/RVO37/databases/tbdatacloud.nosql new file mode 100755 index 0000000..612c099 --- /dev/null +++ b/RVO37/databases/tbdatacloud.nosql @@ -0,0 +1,3 @@ +-"5dBNwRp9graYJxZn409NrVklVov1b2QLPDqGm6XK":[{"ts":1760531317962,"values":{"edge_fw_version":"2025-10-08","maintenance_mode":false}}],"id":"3000328003no71b"} +-"5dBNwRp9graYJxZn409NrVklVov1b2QLPDqGm6XK":[{"ts":1760531317975,"values":{"statecode":2,"power_mode":"Automatic"}}],"id":"3000328005no71b"} +-"5dBNwRp9graYJxZn409NrVklVov1b2QLPDqGm6XK":[{"ts":1760531318025,"values":{"_event":{"type":"notice","status":"new","source":{"func":"rsPort.open()","component":"1699963668903","component_name":"DIDO_Controller","edge":"5dBNwRp9graYJxZn409NrVklVov1b2QLPDqGm6XK"},"message":{"sk":"rvo_senica_37_ip111: FLOW bol spustený","en":"rvo_senica_37_ip111: FLOW has been started "},"message_data":""}}}],"id":"3000328007no71b"} diff --git a/RVO37/databases/total_energy.js b/RVO37/databases/total_energy.js new file mode 100755 index 0000000..dde340e --- /dev/null +++ b/RVO37/databases/total_energy.js @@ -0,0 +1,38 @@ +//key is rvo_number, value is max energy when lamps are on +const total_energy = { + 1: 580, + 2: 1100, + 3: 3700, + 4: 4100, + 7: 360, + 12: 1700, + 13: 5400, + 14: 440, + 15: 6100, + 16: 4800, + 20: 1600, + 21: 1000, + 22: 2600, + 23: 1000, + 25: 2600, + 33: 240, + 34: 4000, + 35: 2700, + 36: 820, + 37: 1400, + 35: 3500, + 39: 1170, + 41: 740, + 42: 660, + 43: 4900, + 45: 930, + 46: 700, + 47: 1100, + 48: 1500, + 50: 3200, + 53: 1250, + 55: 1000, + 56: 5500 +} + +module.exports = total_energy; diff --git a/RVO37/debug.js b/RVO37/debug.js new file mode 100755 index 0000000..9818194 --- /dev/null +++ b/RVO37/debug.js @@ -0,0 +1,16 @@ +// =================================================== +// FOR DEVELOPMENT +// Total.js - framework for Node.js platform +// https://www.totaljs.com +// =================================================== + +const options = {}; + +// options.ip = '127.0.0.1'; +// options.port = parseInt(process.argv[2]); +// options.config = { name: 'Total.js' }; +// options.sleep = 3000; +// options.inspector = 9229; +// options.watch = ['private']; + +require('total.js/debug')(options); \ No newline at end of file diff --git a/RVO37/err.txt b/RVO37/err.txt new file mode 100755 index 0000000..e69de29 diff --git a/RVO37/flow/cloudmqttconnect.js b/RVO37/flow/cloudmqttconnect.js new file mode 100755 index 0000000..b03491f --- /dev/null +++ b/RVO37/flow/cloudmqttconnect.js @@ -0,0 +1,357 @@ +exports.id = 'cloudmqttconnect'; +exports.title = 'Cloud connect mqtt'; +exports.group = 'MQTT'; +exports.color = '#888600'; +exports.version = '1.0.2'; +exports.icon = 'sign-out'; +exports.input = 2; +exports.output = 2; +exports.options = { host: 'tb-stage.worksys.io', port: 1883, clientid: "", username: "" }; + +exports.html = `
+
+
+
Hostname or IP address (if not empty - setting will override db setting)
+
+
+
Port
+
+
+
+
+
@(Client id)
+
+
+
topic
+
+
+
`; + + + +const { promisifyBuilder } = require('./helper/db_helper'); +const fs = require('fs'); +const mqtt = require('mqtt'); +const nosql = NOSQL('tbdatacloud'); + +const SEND_TO = { + debug: 0, + rpcCall: 1, +} + +//CONFIG +let saveTelemetryOnError = true;//backup_on_failure overrides this value +//------------------------ + +const noSqlFileSizeLimit = 4194304;//use 5MB - 4194304 +let insertNoSqlCounter = 0; +let insertBackupNoSqlCounter = 0; +let processingData = false; + +let backup_on_failure = true;//== saveTelemetryOnError - create backup client send failure +let restore_from_backup = 50; //how many rows process at once? +let restore_backup_wait = 3;//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; + + +exports.install = function(instance) { + + var client; + var opts; + var clientReady = false; + + let o = {}; //options + + function main() { + loadSettings(); + } + + //set opts according to db settings + function loadSettings() { + + o = instance.options; + if (!o.topic) o.topic = FLOW.GLOBALS.settings.cloud_topic; + + opts = { + host: o.host, + port: o.port, + clientId: o.clientid, + username: o.username, + rejectUnauthorized: false, + resubscribe: false + }; + + console.log("wsmqttpublich -> loadSettings from instance.options", o); + + if (!o.topic) { + instance.status("Not configured", "white"); + console.log("Cloud mqtt connect: no topic selected"); + return; + } + + connectToTbServer(); + } + + function connectToTbServer() { + var url = "mqtt://" + opts.host + ":" + opts.port; + console.log("MQTT URL: ", url); + + client = mqtt.connect(url, opts); + + client.on('connect', function() { + client.subscribe(`${o.topic}_backward`, (err) => { + if (!err) { + console.log("MQTT subscribed"); + } + }); + instance.status("Connected", "green"); + clientReady = true; + sendClientError = true; + }); + + client.on('reconnect', function() { + instance.status("Reconnecting", "yellow"); + clientReady = false; + }); + + client.on('message', function(topic, message) { + // message is type of buffer + message = message.toString(); + if (message[0] === '{') { + TRY(function() { + + message = JSON.parse(message); + if (message.hasOwnProperty("device") && message.hasOwnProperty("data") && message.data.hasOwnProperty("id")) { + client.publish(`${o.topic}_forward`, `{"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 } }); + } + + }, () => instance.debug('MQTT: Error parsing data', message)); + } + + instance.send(SEND_TO.rpcCall, { "topic": o.topic, "content": message }); + }); + + client.on('close', function() { + clientReady = false; + + instance.status("Disconnected", "red"); + instance.send(SEND_TO.debug, { "message": "Client CLOSE signal received !" }); + }); + + client.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) { + console.log('MQTT client error', err); + sendClientError = false; + } + clientReady = false; + }); + + } + + + instance.on('0', function(data) { + + if (clientReady) { + //do we have some data in backup file? if any, process data from database + if (saveTelemetryOnError) { + //read telemetry data and send back to server + if (!processingData) processDataFromDatabase(); + } + + let stringifiedJson = JSON.stringify(data.data) + client.publish(`${o.topic}_forward`, stringifiedJson, { qos: 1 }); + } + 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 (saveTelemetryOnError && o.topic) { + //create new file from tbdata.nosql, if file size exceeds given limit, and clear tbdata.nosql + makeBackupFromDbFile(); + + //write to tb + data.data.id = UID(); + nosql.insert(data.data); + } + } + }); + + instance.on("1", _ => { + main(); + }) + + instance.close = function(done) { + if (clientReady) { + client.end(); + } + }; + + + function getDbBackupFileCounter(type) { + var files = fs.readdirSync(__dirname + "/../databases"); + + let counter = 0; + for (var i = 0; i < files.length; i++) { + + if (files[i] == "tbdatacloud.nosql") continue; + + if (files[i].endsWith(".nosql")) { + + let pos = files[i].indexOf("."); + if (pos > -1) { + + let fileCounter = counter; + let firstDigit = files[i].slice(0, pos); + + fileCounter = parseInt(firstDigit); + if (isNaN(fileCounter)) fileCounter = 0; + //console.log("getDbBackupFileCounter digit:", files[i], firstDigit, fileCounter, isNaN(fileCounter), type); + + if (type == "max") { + if (fileCounter > counter) { + counter = fileCounter; + } + } + else if (type == "min") { + if (counter == 0) counter = fileCounter; + + if (fileCounter < counter) { + counter = fileCounter; + } + } + } + } + + } + + if (type == "max") counter++; + + return counter; + } + + const makeBackupFromDbFile = async () => { + + if (!saveTelemetryOnError) return; + + //to avoid large file: tbdata.nosql + + //init value is 0! + if (insertNoSqlCounter > 0) { + --insertNoSqlCounter; + return; + } + + insertNoSqlCounter = 100; + + let source = __dirname + "/../databases/tbdatacloud.nosql"; + + var stats = fs.statSync(source); + var fileSizeInBytes = stats.size; + + if (fileSizeInBytes > noSqlFileSizeLimit) { + + let counter = 1; + counter = getDbBackupFileCounter("max"); + + let destination = __dirname + "/../databases/" + counter + "." + "tbdatacloud.nosql"; + + //make backup file + fs.copyFileSync(source, destination); + //fs.renameSync(p, p + "." + counter); + + //clear tbdata.nosql + fs.writeFileSync(source, ""); + fs.truncateSync(source, 0); + + } + } + + const processDataFromDatabase = async () => { + + if (restore_from_backup <= 0) return; + + //calculate diff + const now = new Date(); + let currentTime = now.getTime(); + let diff = currentTime - lastRestoreTime; + + if ((diff / 1000) < restore_backup_wait) { + //console.log("*********restore_backup_wait", diff, restore_backup_wait); + return; + } + + processingData = true; + + //get filename to process + let counter = getDbBackupFileCounter("min"); + + //we have some backup files + let dataBase = 'tbdata'; + + var nosql; + if (counter == 0) dataBase = 'tbdatacloud'; + else dataBase = counter + "." + 'tbdatacloud'; + + nosql = NOSQL(dataBase); + + //select all data - use limit restore_from_backup + let records = await promisifyBuilder(nosql.find().take(restore_from_backup)); + + for (let i = 0; i < records.length; i++) { + if (clientReady) { + + let item = records[i]; + let id = item.id; + + if (id !== undefined) { + //console.log("------------processDataFromDatabase - remove", id, dataBase, i); + + try { + + let message = JSON.parse(JSON.stringify(item)); + delete message.id; + client.publish(`${o.topic}_forward`, JSON.stringify(message), { qos: 1 }); + + //remove from database + await promisifyBuilder(nosql.remove().where("id", id)); + + } catch (error) { + //process error + console.log("processDataFromDatabase", error); + } + + } + + } + else { + processingData = false; + return; + } + } + + if (records.length > 0) { + //clean backup file + if (counter > 0) nosql.clean(); + } + + //no data in db, remove + if (records.length == 0) { + if (counter > 0) nosql.drop(); + } + + const d = new Date(); + lastRestoreTime = d.getTime(); + + processingData = false; + + } + + instance.on('options', main); + +}; diff --git a/RVO37/flow/cmd_manager.js b/RVO37/flow/cmd_manager.js new file mode 100755 index 0000000..25912df --- /dev/null +++ b/RVO37/flow/cmd_manager.js @@ -0,0 +1,3071 @@ +exports.id = 'cmd_manager'; +exports.title = 'CMD Manager'; +exports.group = 'Worksys'; +exports.color = '#5D9CEC'; +exports.version = '0.0.3'; +exports.output = ['red', 'blue', 'yellow', 'blue', 'white', 'green']; +exports.input = 3; +exports.icon = 'cloud-upload'; + +exports.html = ` +
+
+
+
RPC - run RPC calls

+
+
+
@(User)
+
+
+
@(Password)
+
+
+
@(My edge)
+
+
+
+`; +exports.readme = `Manager for CMD calls`; + + +exports.install = function(instance) { + + 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, isEmptyObject, emptyJsObject, writeToFile, addToArrayIfUnique } = require('./helper/utils'); + const bitwise = require('bitwise'); + + var SunCalc = require('./helper/suncalc'); + const DataToTbHandler = require('./helper/DataToTbHandler'); + const errorHandler = require('./helper/ErrorToServiceHandler'); + const { sendNotification } = require('./helper/notification_reporter'); + const process = require('process'); + const { errLogger, logger, monitor } = require('./helper/logger'); + + //for accelerometer purposes + const { naklony } = require("../databases/accelerometer_db"); + + const dbNodes = TABLE("nodes"); + const dbRelays = TABLE("relays"); + + let GLOBALS; + let SETTINGS; + let rsPort; + let tbHandler; + + // runTasks intervals + const SHORT_INTERVAL = 30; + const LONG_INTERVAL = 300; + + //send data to following instances: + const SEND_TO = { + debug: 0, + tb: 1, + http_response: 2, + dido_controller: 3, + infoSender: 4, + dailyReport: 5 + } + + 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 + } + + 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 sendNodeReadout = null; // interval for sending agregate data from node + + 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["1"] = minutes; // dimming + priorities["76"] = minutes; // power + + minutes = 5; + priorities["75"] = minutes; // current + priorities["79"] = minutes; // energy + priorities["87"] = minutes; // aktualny cas + //priorities["84"] = minutes; //accelerometer + + minutes = 10; + priorities["74"] = minutes; // voltage + priorities["77"] = minutes; // power factor + priorities["78"] = minutes; // frequency + + minutes = 60; + priorities["0"] = minutes; // statecode + priorities["6"] = minutes; // dusk + priorities["7"] = minutes; // dawn + priorities["8"] = minutes; // profile + + minutes = 60 * 24; + priorities["89"] = minutes; // verzia fw + priorities["80"] = minutes; // lifetime + + //prikazy kt sa budu spustat na dany node - see config.js in terminal-oms.app. (1 - dimming) + let listOfCommands = [0, 1, 6, 7, 8, 74, 75, 76, 77, 78, 79, 80, 87, 89]; + + 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; + + // holds dusk, dawn (and more) values + let sunCalcResult; + + //helper container for counting resolved group of commands (commands related to set profile) + let cmdCounter = {};//key is node, value is counter + + //TODO: is this set working?? According to previous checks, sets do not work + //if sending of profile to node fails, we send notification and push node into set, so we do not send notification twice + const nodeProfileSendFail = new Set(); + + //we expect to get current temperature in Senica from senica-prod01 + let temperatureInSenica = null; + let accelerometerInterval = null; + + //NOTE: daily reports senica: + //rvo_is_on status, we monitor all nodes - if true, power and dimming should be not 0, if false, 24/7 nodes should be 0, other rvo should not respond + let rvo_is_on; + let previous_rvo_is_on_value; + let handleDailyReport; //setInterval for dailyReportHandler function + let dailyReport = {}; //data needed for daily report + let reportToSend = {}; //final report which we send to cloud + let breakerCounter = null; // status of breakers after flow starts is not in report + let rvoPeriod; // interval of checking dusk dawn and if rvo_is_on + let initialReportStatus = false; + + const DAILY_REPORT_HANDLER_TIME = 3_600_000; + const SET_SUNCALC_RESULT_TIME = 3_600_000; + const SET_RVO_PERIOD_TIME = 300_000; + const ADD_NODE_TO_REPORT_TIME = 3_600_000; + + //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); + + let now = new Date(); + console.log("Cmd-mngr installed", now.toLocaleString("sk-SK")); + + sunCalcResult = calculateDuskDawn(); + + handleRsPort(); + + customTasksInterval = setInterval(reportEdgeDateTimeAndNumberOfLuminaires, 120_000); + setTimeout(reportEdgeDateTimeAndNumberOfLuminaires, 4000); + + //dailyReport related + emptyReportToSend(); + breakerCounter = Object.keys(relaysData).length - 1; // we get number of lines (breakers) except of line 0 + rvoPeriod = setInterval(setRvoPeriod, SET_RVO_PERIOD_TIME); + setTimeout(setRvoPeriod, 3000); + setInterval(setSunCalcResult, SET_SUNCALC_RESULT_TIME); + handleDailyReport = setInterval(dailyReportHandler, DAILY_REPORT_HANDLER_TIME); + + + setCorrectTime = setInterval(setCorrectPlcTimeOnceADay, 60000 * 60); // 1 hour + setCorrectPlcTimeOnceADay(); + + sendNodeReadout = setInterval(sendNodesData, 150_000); + accelerometerInterval = setInterval(accelerometerData, 60000 * 30); //30 min + } + + + 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" + //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 + // if node regular readout does not respond, we repeat request + params.repeatCounter = 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-mngr: 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.byte4 = 96; + params.recipient = 1; + params.register = 8; + params.rw = 1;//write + params.timestamp = timestamp; + 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.byte4 = 96; + params.recipient = 1; + params.register = 8; + params.rw = 1;//write + params.timestamp = timestamp; + 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). + */ + + 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.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.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 + { + + logger.debug("processNodeProfile: Threshold lux level for DUSK/DAWN", node); + + let params = getParams(); + params.type = "set_node_profile"; + params.address = node; + params.register = 96; + params.recipient = 1; + params.rw = 1;//write + params.timestamp = timestamp; + 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(); + params.type = "set_node_profile"; + params.address = node; + params.register = 97; + params.recipient = 1; + params.rw = 1;//write + params.timestamp = timestamp; + 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.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); + + 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); + + console.log("proces profile finished *********************") + } + + + 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; + }); + } + + + 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) { + for (let k in nodesData) { + 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`); + } + } + } + + + function loadRelaysData(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 (value.contactor == 1) processAllNodeProfilesOnLine(value.line); + } + } + + + function reportOnlineNodeStatus(line) { + //Po zapnutí línie broadcastovo aktualizovať predtým čas a o 3 sek neskor - status, brightness + + logger.debug("Cmd-mngr: ----->reportOnlineNodeStatus for line", line); + + const d = new Date(); + + // broadcast actual time + let params = getParams(); + params.address = 0xffffffff;//Broadcast + params.byte1 = d.getHours(); + params.byte2 = d.getMinutes(); + params.recipient = 2;//2 broadcast, address = 0 + params.register = 87;//Actual time + params.rw = 1;//write + params.type = "node-onetime-write"; + params.timestamp = d.getTime() + 30000; + params.info = "run broadcast: Actual time"; + //params.debug = true; + + tasks.push(params); + + let sec = 3; + setTimeout(function() { + //Po zapnutí línie - spraviť hromadný refresh stavu práve zapnutých svietidiel + + let time = Date.now(); + + for (let k in nodesData) { + + //potrebujem nody k danej linii + 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].node_status_before_offline === true || nodesData[k].status === true) { + status = "OK"; + nodesData[k].time_of_last_communication = time; + } + + nodesData[k].readout.status = status; + + updateNodeStatus(k, status === "OK" ? true : false); + if (nodesData[k].hasOwnProperty("node_status_before_offline")) delete nodesData[k].node_status_before_offline; + sendTelemetry({ status: status }, tbname, time); + + //vyreportovanie dimming, current, input power pre liniu pre vsetky nody + //Prud + { + let params = getParams(); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 75;//prud + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = time + 4000; + params.info = 'read current'; + //params.debug = true; + tasks.push(params); + } + + //vykon + { + let params = getParams(); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 76;//výkon + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = time + 4100; + params.info = 'read power'; + //params.debug = true; + + tasks.push(params); + } + //dimming + { + let params = getParams(); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 1;//dimming + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = time + 4200; + params.info = 'read dimming'; + //params.debug = true; + + tasks.push(params); + } + + } + } + + }, sec * 1000); + } + + + function reportOfflineNodeStatus(line) { + + logger.info("Cmd-mngr: ------>reportOffLineNodeStatus for line ", line); + + values = {}; + values["dimming"] = 0;//brightness + values["power"] = 0;//výkon + values["current"] = 0;//prúd + values["status"] = "OFFLINE"; + + const date = Date.now(); + + Object.keys(nodesData).forEach(node => { + + //potrebujem nody k danej linii + if (line == nodesData[node].line || line == undefined) { + + let tbname = nodesData[node].tbname; + let nodeStatus = nodesData[node].status; + + //in case we have reported offline node status, we return (continue with next node) + if (nodeStatus === "OFFLINE") return; + + nodesData[node].node_status_before_offline = nodeStatus; + nodesData[node].status = "OFFLINE"; + nodesData[node].readout = {}; + + sendTelemetry({ ...values }, tbname, date); + } + }); + + } + + + function turnLine(onOrOff, line, info) { + let obj = { + line: line, + command: onOrOff, + info: info + }; + + //to assure, handleDailyReportFunction do not run before rvo_is_on variable changes. So after every line switch we reset the timer + clearInterval(handleDailyReport); + handleDailyReport = setInterval(dailyReportHandler, DAILY_REPORT_HANDLER_TIME); + + //logger.debug("linia", line, obj); + instance.send(SEND_TO.dido_controller, obj); + } + + + 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"; + 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]) { + //CRC_ERROR + message = "NOK"; + error = "CRC_ERROR c1"; + instance.send(SEND_TO.debug, "CRC_ERROR c1"); + } + + 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") { + instance.send(SEND_TO.debug, bytes); + instance.send(SEND_TO.debug, "RESPONSE " + type + " - " + bytes[4]); + + //logger.debug(SEND_TO.debug, "RESPONSE " + type + " - " + bytes[4], bytes); + + error = "type is: " + type; + + message = "NOK"; + } + + return { message, type, error }; + } + + + //BUILD TASKS// + function buildTasks(params) { + + //return; + console.log("buidTAaasks start ****************", params); + monitor.info("buildTasks - params", params); + + let processLine; //defined line + let init = false; + let processLineProfiles = true; + let processBroadcast = true; + let processNodes = true; + + if (params == undefined) { + init = true; + tasks = []; + logger.debug("-->buildTasks clear tasks"); + } + else { + processLineProfiles = params.processLineProfiles; + processBroadcast = false; + processNodes = false; + + processLine = params.line; + } + + let now = new Date(); + + //process line profiles + if (processLineProfiles) { + + let keys = Object.keys(relaysData); + + for (let i = 0; i < keys.length; i++) { + + let line = parseInt(keys[i]); + let profilestr = relaysData[line].profile; + + if (processLine != undefined) { + if (processLine != line) continue; + } + + try { + + /** + * we process line profiles: timepoints, astro clock, lux_sensor, offsets ... + */ + if (profilestr === "") throw ("Profile is not defined"); + let profile = JSON.parse(profilestr); + 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; + + // add name to regular profile timepoint and delete unused end_time key: + time_points.forEach(point => { + point.name = "profileTimepoint" + delete point.end_time; + }); + + //monitor.info("buildTasks: time_points", time_points); + + + /** + * 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 astro clock true, we remove all regular profile points + time_points = []; + + //TODO: when astro clock == true, is offset calculated ??? + //let duskAstroClockOffset = profile.dusk_astro_clock_offset; + //let dawnAstroClockOffset = profile.dawn_astro_clock_offset; + //console.log("line astro clock offsets dusk a dawn: ", duskAstroClockOffset, dawnAstroClockOffset); + // maybe add dusk dawn offset to calculateDuskDawn ?? what dusk dawn will be if dawn_lux_sensor == true?? + //let sunCalcResult = calculateDuskDawn(new Date(), line, duskAstroClockOffset, dawnAstroClockOffset); + + 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 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); + + 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); + + 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(':'); + + let ad = new Date(); + ad.setHours(parseInt(ahours), parseInt(aminutes), 0); + + let bd = new Date(); + bd.setHours(parseInt(bhours), parseInt(bminutes), 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++) { + + let start_time = new Date(); + let [hours, minutes] = time_points[t].start_time.split(':'); + start_time.setHours(parseInt(hours), parseInt(minutes), 0); + + //task is in 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(); + params.type = "relay"; + params.line = parseInt(line); + params.value = time_points[t].value; + params.tbname = relaysData[line].tbname; + params.timestamp = start_time.getTime(); + + // 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; + + //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)) { + 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; + + params.debug = true; + + //turn on/off line + tasks.push(params); + monitor.info("TimePoint params: ", params.info, start_time); + } + + monitor.info("-->time_points final", line, time_points); + + //ensure to turn on/off according to calculated currentValue + let params = getParams(); + params.type = "relay"; + params.line = parseInt(line); + params.tbname = relaysData[line].tbname; + params.value = currentValue; + params.timestamp = i; + params.debug = true; + + //logger.debug(now.toLocaleString("sk-SK")); + 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; + + tasks.push(params); + + } catch (error) { + if (profilestr !== "") { + //errLogger.error(profilestr, error); + console.log(`Cmd_mngr: Unable to process line profile ${line}. Error: `, error); + errorHandler.sendMessageToService(profilestr + "-" + error, 0, "js_error"); + } else { + turnLine("off", line, "No line profile. Switching it off on startup"); + } + } + + } + //logger.debug("tasks:"); + //logger.debug(tasks); + } + + + //NOTE: PROCESS DEFAULT BROADCASTS - Time of dusk, Time of dawn, Actual Time + if (processBroadcast) { + + let d = new Date(); + let time = d.getTime(); + //let sunCalcResult = calculateDuskDawn(); + + { + let params = getParams(); + + params.address = 0xffffffff;//broadcast + params.byte1 = sunCalcResult["dusk_hours"]; + params.byte2 = sunCalcResult["dusk_minutes"]; + params.recipient = 2;//2 broadcast, + params.register = 6;//Time of dusk + params.rw = 1;//write + params.type = "node-regular-write"; + params.timestamp = time + 60000; + params.addMinutesToTimestamp = 60 * 3; //kazde 3 hodiny zisti novy dusk + params.info = "Broadcast-duskTime"; + + tasks.push(params); + } + + { + let params = getParams(); + + params.address = 0xffffffff;//broadcast + params.byte1 = sunCalcResult["dawn_hours"]; + params.byte2 = sunCalcResult["dawn_minutes"]; + params.recipient = 2; //2 broadcast + params.register = 7;//Time of dawn + params.rw = 1;//write + params.type = "node-regular-write"; + params.timestamp = time + 60001; + params.addMinutesToTimestamp = 60 * 3; //kazde 3 hodiny zisti novy dawn + params.info = "Broadcast-dawnTime"; + + tasks.push(params); + } + + { + let params = getParams(); + + params.address = 0xffffffff;//broadcast + params.byte1 = d.getHours(); + params.byte2 = d.getMinutes(); + params.recipient = 2; //2 broadcast + params.register = 87;//Actual time + params.rw = 1;//write + params.type = "node-regular-write"; + params.timestamp = time + 60002; + params.addMinutesToTimestamp = 5; + params.info = "run broadcast: Actual time"; + + tasks.push(params); + } + + } + + //process nodes & tasks - read node's data + if (processNodes) { + + let time = Date.now(); + + for (let k in nodesData) { + let address = parseInt(k); + let tbname = nodesData[k].tbname; + let register = 0; + + for (let i = 0; i < listOfCommands.length; i++) { + + register = listOfCommands[i]; + let addMinutesToTimestamp = priorities[register]; + + let params = getParams(); + + params.address = address; + params.recipient = 1; + params.register = register; + params.type = register == 1 ? "node-dimming-read" : "node-regular-read"; + params.tbname = tbname; + params.timestamp = time + 5000 + i * 500 + addMinutesToTimestamp * 1000; //to make slight time difference + params.addMinutesToTimestamp = addMinutesToTimestamp; + params.info = "Node regular read command"; + + tasks.push(params); + } + + } + } + + + //niektore ulohy sa vygeneruju iba 1x pri starte!!! + if (!init) return; + + + //Master node FW version - modifies SETTINGS.masterNodeIsResponding + { + let params = getParams(); + params.type = "cmd-master"; + params.register = 4; + params.address = 0; + params.timestamp = 0; + params.addMinutesToTimestamp = 5; + params.tbname = SETTINGS.rvoTbName; + params.info = "Master node FW verzia"; + //params.debug = true; + + tasks.push(params); + } + + //kazdu hodinu skontrolovat nastavenie profilov + { + let params = getParams(); + params.type = "process_profiles"; + params.timestamp = Date.now() + 60001; + params.addMinutesToTimestamp = 60;//60 = every hour + params.info = "detekcia nespracovaných profilov linie a nodov"; + //params.debug = true; + + tasks.push(params); + } + + monitor.info("tasks created:", tasks.length); + } + + + /** + * We process line profile, where "astro_clock": true + * example profile: + * + "dawn_lux_sensor": true, + "dusk_lux_sensor": true, + "dawn_lux_sensor_value": 5, + "dusk_lux_sensor_value": 5, + "dawn_astro_clock_offset": 0, + "dusk_astro_clock_offset": 10, + "dawn_lux_sensor_time_window": 30, + "dusk_lux_sensor_time_window": 30, + "dawn_astro_clock_time_window": 60, + "dusk_astro_clock_time_window": 60 + + * if dawn: if currentTimestamp is in timewindow "dawnTime + and - dawn_lux_sensor_time_window" and lux value >= lux_sensor_value, we switch off the line. + * if dusk: we do oposite + * + * dawn: usvit - lux je nad hranicou - vypnem + * dusk: sumrak - lux je pod hranicou - zapnem + */ + 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++) { + + let line = keys[i]; //line is turned off by default + let profilestr = relaysData[line].profile; + const contactor = relaysData[line].contactor; + + try { + + let profile = JSON.parse(profilestr); + if (Object.keys(profile).length === 0) throw ("turnOnOffLinesAccordingToLuxSensor - profile is not defined"); + + 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 (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"); + } + } + } + + //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 (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"); + } + } + } + + } + + } catch (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) { + //MASTER + if (node == 0) return; + + let nodeObj = nodesData[node]; + if (nodeObj == undefined) return; + + let nodeCurrentStatus = nodeObj.status; + const now = Date.now(); + + let data = null; + + if (nodeCurrentStatus === "OFFLINE") { + data = { status: newStatus }; + nodeDbStatusModify(node, data); + return; + } + else 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; + } + + } + + + 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 }; + } + }); + }); + } + + + function processDailyReport() { + + const now = Date.now(); + + for (const [key, value] of Object.entries(dailyReport)) { + + if (["name", "time", "dusk_and_dawn"].includes(key)) continue; + + let poleNumber = nodesData[key]["pole_number"]; + let line = dailyReport[key].line; + let nodeType = nodesData[key]["node_type"]; + let fullNodeName = key // key == nodeNumber + + if (poleNumber && nodeType) { + fullNodeName = SETTINGS.rvo_number + "/" + poleNumber + "_" + line + "L_" + key + "_" + nodeType; + } else { + fullNodeName = key; + } + + if (rvo_is_on) { + + if (value.initialTs) { + if (value.initialTs + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["night_no_data"], fullNodeName); + console.log('report nedostava ziadne data uz hodinu', fullNodeName); + value.initialTs = now; + } + } + if (value.dimmingIsZeroTime) { + if (value.dimmingIsZeroTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["night_dimming=0"], fullNodeName); + console.log("report node dimming je 0 ale ma svietit", fullNodeName); + value.dimmingIsZeroTime = now; + } + } + if (value.powerIsZeroTime) { + if (value.powerIsZeroTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["night_power=0"], fullNodeName); + console.log("report node power je 0 ale ma svietit", fullNodeName); + value.powerIsZeroTime = now; + } + } + + } else { + + let contactorStatus = relaysData[line].contactor; + if (contactorStatus === 1) { + + if (value.initialTs) { + if (value.initialTs + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["day_24/7_no_data"], fullNodeName); + console.log('node je na 24/7 ale nedostava ziadne data uz hodinu', fullNodeName); + value.initialTs = now; + } + } + if (value.dimmingIsOnButShouldBeOffTime) { + if (value.dimmingIsOnButShouldBeOffTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["day_24/7_dimming>0"], fullNodeName); + console.log("report dimming je > 0 ale nema svietit", fullNodeName); + value.dimmingIsOnButShouldBeOffTime = now; + } + } + if (value.powerIsOnButShouldBeOffTime) { + if (value.powerIsOnButShouldBeOffTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["day_24/7_power>0"], fullNodeName); + console.log("report power je > 0 ale nema svietit", fullNodeName); + value.powerIsOnButShouldBeOffTime = now; + } + } + + } + + } + + } + + let report = {}; + report["name"] = SETTINGS.rvo_name; + report["time"] = new Date(); + report["report"] = reportToSend; + + writeToFile(F.path.root("report_data.log"), report, true); + instance.send(SEND_TO.dailyReport, report); + } + + + function dailyReportHandler() { + + if (!SETTINGS.daily_report) return; + + // after dawn we empty reportToSend and start to get data for a new day + const date = new Date(); + const hour = date.getHours(); + const minute = date.getMinutes(); + + console.log("now: ", hour, minute, "suncalc: ", sunCalcResult.dawn_hours, sunCalcResult.dawn_minutes); + + if (hour === sunCalcResult.dawn_hours) { + + //NOTE: ak je este pred usvitom, spracujeme report a posleme na cloud, ak uz je po usvite, resetujeme report plnime data noveho dna + if (minute >= sunCalcResult.dawn_minutes - 2) { + emptyReportToSend(); + emptyDailyReport(); + console.log("Podmienka 1 v dailyReport handler"); + } else { + processDailyReport(); + emptyReportToSend(); + emptyDailyReport(); + console.log("Podmienka 2 v dailyReport handler"); + } + + initialReportStatus = true; + + // ak sa funkcia spusti o hodinu alebo 2 neskor, ako je usvit (moze sa to stat, kedze kazde zapnutie/vypnutie linii odznova spusti casovac. + } else if (hour === sunCalcResult.dawn_hours + 1 || hour === sunCalcResult.dawn_hours + 2) { + if (!initialReportStatus) { + emptyReportToSend(); + emptyDailyReport(); + initialReportStatus = true; + console.log("Podmienka 3 v dailyReport handler"); + } else { + processDailyReport(); + initialReportStatus = true; + console.log("Podmienka 4 v dailyReport handler"); + } + } else { + processDailyReport(); + initialReportStatus = false; + console.log("Podmienka 5 v dailyReport handler"); + } + + console.log("initialReportStatus: ", initialReportStatus); + + } + + function emptyReportToSend() { + emptyJsObject(reportToSend); + reportToSend["contactor"] = { off: [], on: [] }; + reportToSend["night_no_data"] = []; + reportToSend["night_dimming=0"] = []; + reportToSend["night_power=0"] = []; + reportToSend["day_24/7_no_data"] = []; + reportToSend["day_24/7_dimming>0"] = []; + reportToSend["day_24/7_power>0"] = []; + console.log(`resetuje sa reportToSend`); + } + + + //NOTE: ked je initialTs stale rovnaky a zistime ze linie su vypnute (relaysData.line.contactor) - zistim, ci je node na tej linii. Vieme, ze ak je linia vypnuta je to v poriadku lebo nie je na 24/7 linii + //ak je na 24/7 linii, reportujeme, ze neprijima data + function emptyDailyReport() { + const ts = Date.now(); + emptyJsObject(dailyReport); + + //NOTE: do dailyReport dame vsetky nody a pravidelne kontrolujeme ci maju data + //ked nastane sumrak/usvit a svetla maju zacat/prestat svietit, dailyReport spravime nanovo: + for (const [key, value] of Object.entries(nodesData)) { + dailyReport[value.node] = { line: value.line, initialTs: ts }; + } + + console.log("dailyReport: ", dailyReport); + } + + + async function runTasks() { + + clearInterval(interval); + + let currentTimestamp = Date.now(); + + //sort tasks based on timestamp + 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) { + instance.send(SEND_TO.debug, "no tasks created"); + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + if (!rsPort.isOpen) { + instance.send(SEND_TO.debug, "!rsPort.isOpen"); + //await rsPort.open(); + //console.log("Cmd-mngr: !rsPort.isOpen"); + } + + let currentTask = tasks[0]; + + if (currentTask.debug) { + //logger.debug("--->task to process", currentTask); + } + + if (currentTask.timestamp <= currentTimestamp) { + let params = { ...tasks[0] }; + + //allow terminal commands + if (SETTINGS.maintenance_mode && params.type !== "cmd-terminal") { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + let type = params.type; + let tbname = params.tbname; + let node = params.address; + let register = params.register; + let line = null; + let itIsNodeCommand; + + if (nodesData[node] !== undefined) { + line = nodesData[node].line; + itIsNodeCommand = true; + } + + if (params.line !== undefined) line = params.line; + + if (params.addMinutesToTimestamp > 0 || params.timePointName) { + tasks[0].timestamp = currentTimestamp + tasks[0].addMinutesToTimestamp * 60000; + } else { + tasks.shift(); + } + + //kontrola nespracovanych profilov nodov + //TODO: co ked niektore nody neprijimaju profily? kazdu hodinu zahltuju "tasks" array + if (type == "process_profiles") { + //na vsetky zapnutych liniach sa spracuju nespracovane profily nodov + loadRelaysData(); + interval = setInterval(runTasks, SHORT_INTERVAL); + return; + } + + //relay + if (type == "relay") { + + const timePointName = params.timePointName; + const value = params.value; + + let date = new Date(); + date.setDate(date.getDate() + 1);//next day + + let sunCalcResult; + if (timePointName) sunCalcResult = calculateDuskDawn(date, params.line); + + + if (timePointName == "dawn") { + tasks[0].timestamp = sunCalcResult.dawn_time; + } + else if (timePointName == "dusk") { + tasks[0].timestamp = sunCalcResult.dusk_time; + } + else if (timePointName == "luxOn") { + tasks[0].timestamp = sunCalcResult.dusk_time + params.dusk_lux_sensor_time_window * 60000; + } + else if (timePointName == "luxOff") { + tasks[0].timestamp = sunCalcResult.dawn_time + params.dawn_lux_sensor_time_window * 60000; + } + else if (timePointName == "profileTimepoint") { + tasks[0].timestamp = currentTimestamp + tasks[0].addMinutesToTimestamp * 60000; + } + + let info = "aplikovany bod profilu"; + let onOrOff = ""; + value == 1 ? onOrOff = "on" : onOrOff = "off"; + + turnLine(onOrOff, params.line, info); + + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + if (!SETTINGS.masterNodeIsResponding) { + //ak neodpoveda, nebudeme vykonavat ziadne commands, okrem cmd-terminal cmd-master + errorHandler.sendMessageToService("Master node is not responding"); + + let stop = true; + + if (type === "cmd-terminal" || type === "cmd-master") stop = false; + if (stop) { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + } + + let contactorStatus = 1; + if (relaysData[line] != undefined) contactorStatus = relaysData[line].contactor; + + if (line === 0 || contactorStatus === 0 || FLOW.deviceStatus.state_of_breaker[line] === "Off") { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + // TODO: -> status offline for rvo if rotary_switch_state is OFF, this is source of errors + // check if rotary_switch_state == "Off" + // state_of_braker: disconnected = true? + + if (!rsPort.isOpen) { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + //RE-CALCULATE VALUES + //set actual time for broadcast + if (register == 87 && params.recipient === 2) { + var d = new Date(); + params.byte1 = d.getHours();//h + params.byte2 = d.getMinutes();//m + } + + //SET DUSK/DAWN FOR BROADCAST + //Time of dusk + if (register == 6 && params.recipient === 2) { + + if (type != "cmd-terminal") { + params.byte1 = sunCalcResult["dusk_hours"];//h + params.byte2 = sunCalcResult["dusk_minutes"];//m + } + } + + //Time of dawn + if (register == 7 && params.recipient === 2) { + if (type != "cmd-terminal") { + params.byte1 = sunCalcResult["dawn_hours"];//h + params.byte2 = sunCalcResult["dawn_minutes"];//m + } + } + //----------------------- + + instance.send(SEND_TO.debug, "address: " + node + " register:" + register + "type: " + type); + + var startTime, endTime; + startTime = new Date(); + + let saveToTb = true; + if (!tbname) saveToTb = false; + + let resp = com_generic(node, params.recipient, params.rw, register, params.name, params.byte1, params.byte2, params.byte3, params.byte4); + let readBytes = 11; + let timeout = 4000; + + + // await keyword is important, otherwise incorrect data is returned! + await writeData(rsPort, resp, readBytes, timeout).then(function(data) { + + //sometimes happens, that status of node changes to OK, NOK even if line was turned off and should be status OFFLINE. To prevent this, we return if line contactor is 0: + if (itIsNodeCommand && line && relaysData[line].contactor !== 1) return; + + 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); + + //ak sa odpoved zacina 0 - je to v poriadku, inak je NOK + let message = result.message; // OK, NOK + let message_type = result.type; + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + console.log("detected response:", result); + logger.debug("Cmd-mngr: writeData done " + message_type + " duration: " + timeDiff + " type: " + params.debug, params, result); + } + } + + let values = {}; + + //CMD FINISHED + if (message == "OK") { + + updateNodeStatus(node, true); + + //write + if (type == "set_node_profile") { + let result = cmdCounterResolve(node); + if (result == 0) { + dbNodes.modify({ processed: true }).where("node", node).make(function(builder) { + builder.callback(function(err, response) { + + sendNotification("Cmd-mngr: process cmd", SETTINGS.rvoTbName, "dimming_profile_was_successfully_received_by_node", { node: node }, "", SEND_TO.tb, instance); + + logger.debug("--> profil úspešne odoslaný na node č. " + node); + nodesData[node].processed = true; + nodeProfileSendFail.delete(node); + }); + }); + } + } + + //parse read response + if (params.rw == 0) { + values = processResponse(register, dataBytes); //read + } + + if (itIsNodeCommand) { + values.comm_status = "OK"; + values.status = "OK"; + nodesData[node].readout = { ...nodesData[node].readout, ...values }; + + + if (SETTINGS.daily_report) { + //TODO: co ak nedostavame odpovede z nodu ? Musime vyreportovat!! + //v dailyReport teda musi byt kompletny zoznam nodov a neustale kontrolovat, ci maju data, ak nie report node - neodpoveda + if (register === 1) { + + let now = Date.now(); + + if (rvo_is_on === true) { + + if ("dimmingIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].dimmingIsOnButShouldBeOffTime; + + if (values.dimming > 0) { + if ("dimmingIsZeroTime" in dailyReport[node]) delete dailyReport[node].dimmingIsZeroTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if (!("dimmingIsZeroTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], dimmingIsZeroTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } else { + + if ("dimmingIsZeroTime" in dailyReport[node]) delete dailyReport[node].dimmingIsZeroTime; + + if (values.dimming > 0) { + if (!("dimmingIsOnButShouldBeOffTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], dimmingIsOnButShouldBeOffTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if ("dimmingIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].dimmingIsOnButShouldBeOffTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } + } + + if (register === 76) { + + let now = Date.now(); + + if (rvo_is_on === true) { + + if ("powerIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].powerIsOnButShouldBeOffTime; + + if (values.power > 1) { + if ("powerIsZeroTime" in dailyReport[node]) delete dailyReport[node].powerIsZeroTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if (!("powerIsZeroTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], powerIsZeroTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } else { + + if ("powerIsZeroTime" in dailyReport[node]) delete dailyReport[node].powerIsZeroTime; + + if (values.power > 1) { + if (!("powerIsOnButShouldBeOffTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], powerIsOnButShouldBeOffTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if ("powerIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].powerIsOnButShouldBeOffTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } + } + } + + } + + //master node + if (node == 0) { + sendNotification("Cmd-mngr: 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; + } + + if (params.debug) { + //logger.debug("saveToTb", saveToTb, tbname, values); + } + + if (saveToTb && type != "node-regular-read") { + sendTelemetry(values, tbname); + } + else { + if (type == "cmd-terminal") { + terminalCommandResponse(params, "SUCCESS", data); + } + } + + } + else { + terminalCommandResponse(params, "ERROR", data); + handleNokResponseOnRsPort("handleNOK else block", params, itIsNodeCommand, saveToTb); + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + //logger.debug("writeData err: ", error, result, params); + logger.debug("writeData err: ", tbname, node, register, values); + } + } + + //logger.debug(error, result, params); + } + }).catch(function(reason) { + + //console.log("writeData catch exception", reason); + instance.send(SEND_TO.debug, reason); + + terminalCommandResponse(params, "FAILURE", null, reason); + handleNokResponseOnRsPort("handleNOK catch block", params, itIsNodeCommand, saveToTb); + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + logger.debug("-->WRITE FAILED: " + reason, params.debug, params); + } + } + + }); + + } + 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); + } + + + // if node does not respond to request, we repeat request 3 times: + function repeatCommand(params) { + params.repeatCounter++; + if (params.repeatCounter < 4) { + params.timestamp = 0; + params.addMinutesToTimestamp = 0; + tasks.push(params); + } + } + + function handleNokResponseOnRsPort(message, params, itIsNodeCommand, saveToTb) { + + let node = params.address; + let register = params.register; + let type = params.type; + let tbName = params.tbname; + if (!tbName) return; + + let values = {}; + + let updateStatus = updateNodeStatus(node, false); + + if (itIsNodeCommand) { + values.comm_status = "NOK"; + nodesData[node].readout.comm_status = "NOK"; + repeatCommand(params); + } + + if (updateStatus) { + values.status = "NOK"; + nodesData[node].readout.status = "NOK"; + } + + if (type === "node-regular-read") return; + + //master node + if (node == 0) { + sendNotification("Cmd-mngr: 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; + + if (register == 4) values["master_node_version"] = "NOK"; + } + + if (type == "set_node_profile") { + delete cmdCounter[node]; + logger.debug("profil nebol úspešne odoslaný na node č. ", params); + + if (!nodeProfileSendFail.has(node)) { + sendNotification("Cmd-mngr: process cmd", tbName, "configuration_of_dimming_profile_to_node_failed", { node: node }, "", SEND_TO.tb, instance); + nodeProfileSendFail.add(node); + } + } + + // console.log("------",node, register, type, itIsNodeCommand, updateStatus, saveToTb, values); + if (saveToTb) { + sendTelemetry(values, tbName); + } + + } + + + function sendNodesData() { + Object.keys(nodesData).forEach(node => { + if (nodesData[node]["status"] !== "OFFLINE") { + sendTelemetry(nodesData[node].readout, nodesData[node].tbname); + nodesData[node].readout = {}; + } + }) + } + + + /** + * 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; + } + + 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); + + //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 === "OFFLINE") { + nodeObj.node_status_before_offline === true ? number_of_ok_luminaires++ : number_of_nok_luminaires++; + } + else if (nodeObj.status == true) 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 - ts % 60000 //round to full minute + }; + + sendTelemetry(values, SETTINGS.rvoTbName, ts); + } + + + function setSunCalcResult() { + //if next day, we get new dusk and dawn. To make sure, in local timezone 2:00 means 00:00 in utc (it means next day) + if (new Date().getHours() === 2) { + sunCalcResult = calculateDuskDawn(); + console.log("Novy suncalc: ", sunCalcResult); + } + } + + + function setRvoPeriod() { + + if (!SETTINGS.daily_report) return; + + const ts = Date.now(); + + previous_rvo_is_on_value = rvo_is_on; + + if (ts < sunCalcResult.dawn_time - 1_800_000) { // nodes should be on (00:00 -> 06:00 ( - pol hodina, lebo rvo vypina skor) + rvo_is_on = true; + } else if (sunCalcResult.dawn_time - 1_800_000 < ts && ts < sunCalcResult.dusk_time + 1_800_000) { // nodes should be off 06:00 -> 21:00 + rvo_is_on = false; + } else if (sunCalcResult.dusk_time + 1_800_000 < ts) { // nodes should be on 21:00 -> 00:00 + rvo_is_on = true; + } + + if (previous_rvo_is_on_value !== rvo_is_on) { + emptyDailyReport(); + console.log("rvo_is: ", rvo_is_on, previous_rvo_is_on_value); + } + } + + + function handleRsPort() { + + if (rsPort) { + rsPort.removeAllListeners(); + rsPort = null; + } + + //! 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-mngr: rsPort opened success"); + + 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); + + }).catch(function(reason) { + instance.send(SEND_TO.debug, "Cmd-mngr: RPC runSyncExec - promise rejected:" + reason); + }); + }); + + rsPort.on('error', function(err) { + errorHandler.sendMessageToService([exports.title, "unable to open port", SETTINGS.serial_port, err.message], 0); + monitor.info("Cmd-mngr: Error on rsPort", err.message); + }); + + rsPort.on("close", () => { + monitor.info("Cmd-mngr: rsPort closed, reconnecting..."); + setTimeout(handleRsPort, 1000); + }); + + rsPort.open(); + } + + + instance.on("close", () => { + clearInterval(interval); + clearInterval(customTasksInterval); + clearInterval(setCorrectTime); + clearInterval(sendNodeReadout); + clearInterval(accelerometerInterval); + rsPort.close(); + }); + + instance.on("0", _ => { + main(); + }) + + + instance.on("2", _ => { + console.log("dailyReport, reportToSend, rvo_is_on", dailyReport, reportToSend, rvo_is_on, previous_rvo_is_on_value); + }) + + instance.on("1", 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(); + return; + } + else if (flowdata.data == "close") { + rsPort.close(); + return; + } + else if (flowdata.data == "clean") { + tasks = []; + return; + } + else if (flowdata.data == "buildtasks") { + //build & run + return; + } + else if (flowdata.data == "run") { + //durations = []; + + if (tasks.length == 0) { + + buildTasks(); + + if (rsPort.isOpen) { + interval = setInterval(runTasks, 100); + } + else { + instance.send(SEND_TO.debug, "port is not opened!!!"); + } + } + } + else { + //terminal data - object + //logger.debug("flowdata", flowdata.data); + + if (typeof flowdata.data === 'object') { + //logger.debug("dido", flowdata.data); + if (flowdata.data.hasOwnProperty("sender")) { + //data from dido_controller + if (flowdata.data.sender == "dido_controller") { + + if (flowdata.data.hasOwnProperty("cmd")) { + let cmd = flowdata.data.cmd; + + if (cmd == "buildTasks") { + clearInterval(interval); + + logger.debug("-->Cmd-mngr: BUILD TASKS"); + buildTasks(); + + //logger.debug("tasks:"); + //logger.debug(tasks); + + logger.debug("-->Cmd-mngr: RUN TASKS"); + interval = setInterval(runTasks, 5000); + } + else if (cmd == "reload_relays") { + loadRelaysData(flowdata.data.line); + + if (flowdata.data.dataChanged) { + if (!flowdata.data.value) { + reportOfflineNodeStatus(flowdata.data.line); + } + else { + reportOnlineNodeStatus(flowdata.data.line); + } + } + + } + else if (cmd == "rotary_switch_state") { + let value = flowdata.data.value; + + //state was changed + if (rotary_switch_state != value) { + if (value == "Off") { + //vyreportovat vsetky svietdla + reportOfflineNodeStatus(); + } + + rotary_switch_state = value; + } + } + 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) { + + // we send lux_sensor value to all nodes: + let params = getParams(PRIORITY_TYPES.node_broadcast); + + params.recipient = 2;//2 broadcast, address = 0 + params.address = 0xffffffff;//Broadcast + + let ba = longToByteArray(lux_sensor); + + params.byte3 = ba[1];//msb + params.byte4 = ba[0]; + params.timestamp = PRIORITY_TYPES.node_broadcast; + params.info = "run broadcast: Actual Lux level from cabinet"; + params.register = 95;//Actual Lux level from cabinet + params.rw = 1;//write + + tasks.push(params); + + //process profiles + turnOnOffLinesAccordingToLuxSensor(lux_sensor); + } + } + else if (cmd == "state_of_breaker") { + //istic linie + + breakerCounter--; + + let value = flowdata.data.value; + let line = parseInt(flowdata.data.line); + + let dataChanged = false; + if (state_of_breaker[line] != value) dataChanged = true; + + state_of_breaker[line] = value; + + let status = "OK"; + if (value == "Off") status = "NOK"; + + if (dataChanged) { + + if (relaysData.hasOwnProperty(line)) { + let tbname = relaysData[line].tbname; + + if (value == "Off") { + sendNotification("Cmd-mngr: onData", tbname, "circuit_breaker_was_turned_off_line", { line: line }, "", SEND_TO.tb, instance, "circuit_breaker"); + if (breakerCounter < 0) reportToSend["contactor"]["off"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + else { + sendNotification("Cmd-mngr: onData", tbname, "circuit_breaker_was_turned_on_line", { line: line }, "", SEND_TO.tb, instance, "circuit_breaker"); + if (breakerCounter < 0) reportToSend["contactor"]["on"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + + //report status liniu + sendTelemetry({ status: status }, tbname) + + //current value + if (value == "Off") reportOfflineNodeStatus(line); //vyreportovat vsetky svietidla na linii + } + + } + } + else { + logger.debug("undefined cmd", cmd); + } + } + } + + return; + } + + //data from worksys + if (flowdata.data.hasOwnProperty("topic")) { + + let data = getNested(flowdata.data, "content", "data"); + + //if we get temperature in senica from senica-prod01 + let temperature = getNested(flowdata.data, "content", "senica_temperature"); + + if (temperature !== undefined) { + temperatureInSenica = temperature; + return; + } + + if (data === undefined) { + console.log("Invalid rpc command came from platform"); + return; + } + + let command = data.params.command; + let method = data.method; + let profile = data.params.payload; + if (profile == undefined) profile = ""; + let entity = data.params.entities[0]; + let entity_type = entity.entity_type; + let tbname = entity.tb_name; + + instance.send(SEND_TO.debug, flowdata.data); + 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") { + + //let command = data.params.command; + let value = data.params.payload.value; + + if (command == "dimming") { + + let nodeWasFound = false; + let keys = Object.keys(nodesData); + + //logger.debug("-----", keys); + + 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); + + value = parseInt(value); + if (value > 0) value = value + 128; + + params.type = "node-onetime-write"; + params.tbname = tbname; + params.address = node; + params.register = 1; + params.recipient = 1; + params.byte4 = value; + params.rw = 1; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'set dimming from platform'; + //params.debug = true; + + //debug(params); + logger.debug("dimming", params); + + tasks.push(params); + + 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); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 1; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read dimming (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + //pridame aj vyreportovanie - vykon + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 76; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read Input Power (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + //pridame aj vyreportovanie - prud svietidla + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 75; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read Input Current (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + //pridame aj vyreportovanie - power faktor - ucinnik + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 77; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read power factor (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + }, 4000); + + nodeWasFound = true; + break; + } + } + + if (!nodeWasFound) { + logger.debug("set dimming from platform", "unable to find tbname", tbname); + } + } + else { + instance.send(SEND_TO.debug, "undefined command " + command); + logger.debug("undefined command", command); + } + + return; + } + 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++) { + let node = keys[i]; + if (tbname == nodesData[node].tbname) { + + 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"); + + //profil úspešne prijatý pre node č. xx + sendNotification("Cmd-mngr", tbname, "dimming_profile_was_processed_for_node", { node: node }, profile, SEND_TO.tb, instance); + + nodesData[node].processed = false; + nodesData[node].profile = profile; + + processNodeProfile(node); + }); + }); + } + } + } + else { + + instance.send(SEND_TO.debug, "unknown method " + method); + logger.debug("unknown method", method); + + return; + } + } + + //nastav profil linie z platformy + 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") { + + 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++) { + let line = keys[i]; + if (tbname == relaysData[line].tbname) { + //zmazeme tasky + 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) { + + //update profile + logger.debug("worksys - update relay profile done:", profile); + instance.send(SEND_TO.debug, "worksys - update relay profile done"); + + relaysData[line].profile = profile; + + loadRelaysData(line) + logger.debug("loadRelaysData DONE for line", line); + + buildTasks({ processLineProfiles: true, line: line }); + + sendNotification("Cmd-mngr: set profile from worksys", tbname, "switching_profile_was_processed_for_line", { line: line }, profile, SEND_TO.tb, instance); + }); + }); + break; + } + } + } + else if (method == "set_command") { + let value = data.params.payload.value; + + 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; + + 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"); + if (line != 0) reportToSend["contactor"]["off"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + else { + turnLine("on", line, "command received from platform"); + if (line != 0) reportToSend["contactor"]["on"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + } + } + else { + instance.send(SEND_TO.debug, "undefined method " + method); + logger.debug("undefined method", method); + } + + return; + } + else { + instance.send(SEND_TO.debug, "UNKNOW entity_type " + entity_type); + logger.debug("UNKNOW entity_type", entity_type); + } + return; + } + + //terminal + if (!rsPort.isOpen) await rsPort.open(); + + let params = flowdata.data.body; + if (params == undefined) { + //logger.debug("Cmd-mngr: flowdata.data.body is undefined"); + return; + } + + params.priority = PRIORITY_TYPES.terminal; + params.type = "cmd-terminal"; + params.tbname = ""; + params.timestamp = PRIORITY_TYPES.terminal; + params.addMinutesToTimestamp = 0;// do not repeat task!!! + params.debug = true; + + let timestamp = Date.now(); + params.refFlowdataKey = timestamp; + //params.refFlowdata = flowdata; + //refFlowdata = flowdata; + + //console.log("flowdata", flowdata); + + cleanUpRefFlowdataObj(); + + refFlowdataObj[timestamp] = flowdata; + + //fix + //params.address = params.adress; + logger.debug("received from terminal", params); + logger.debug("date/time:", new Date()); + logger.debug("tasks length:", tasks.length); + + //tasks = []; + + //add to tasks + tasks.push(params); + + } + } + }) + + + //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) + } + + + /** + * 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; + + RESTBuilder.make(function(builder) { + + if (!builder) return; + + builder.method('GET'); + builder.url('http://192.168.252.2:8004/gettime?projects_id=1'); + + builder.callback(function(err, response, output) { + + 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); + } + + }); + } + + } 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); + + } else { + //console.log("Read-only", stdout); + + 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]: [ + { + "ts": date, + "values": values + } + ] + } + + tbHandler.sendToTb(dataToTb, instance); + } + + + function calculateDuskDawn(date, line, duskOffset = 0, dawnOffset = 0) { + + if (date === undefined) date = new Date(); + + 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); + } + + //if(profile.dawn_lux_sensor == false) + { + if (profile.hasOwnProperty("dawn_astro_clock_offset")) dawn_astro_clock_offset = parseInt(profile.dawn_astro_clock_offset); + } + + } + + } catch (error) { + if (profilestr != "") { + logger.debug(profilestr); + logger.debug(error); + } + } + + 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; + } + + //Dimming, CCT + else if (register == 1) { + let brightness = 0; + let dimming = byte0; + if (dimming > 128) { + //dimming = -128; + brightness = dimming - 128; + } + + //cct + //Ak Byte3 == 1: CCT = (Byte2*256)+Byte1 + let cct; + if (byte3 == 1) cct = byte2 * 256 + byte1; + else cct = bytesToInt(bytes.slice(0, 3)); + + //cct podla auditu + + values["dimming"] = brightness; + return values; + } + + // + else if (register == 4) { + values["master_node_version"] = bytes[1] + "." + bytes[2]; + //logger.debug("FW Version", register, bytes); + } + + //Napätie + else if (register == 74) { + let voltage = (bytesToInt(bytes) * 0.1).toFixed(1); + values["voltage"] = Number(voltage); + } + + //Prúd + else if (register == 75) { + let current = bytesToInt(bytes); + values["current"] = current; + } + + //výkon + else if (register == 76) { + let power = (bytesToInt(bytes) * 0.1).toFixed(2); + values["power"] = Number(power); + } + + //účinník + else if (register == 77) { + let power_factor = Math.cos(bytesToInt(bytes) * 0.1 * (Math.PI / 180)).toFixed(2); + values["power_factor"] = Number(power_factor); + } + + //frekvencia + else if (register == 78) { + let frequency = (bytesToInt(bytes) * 0.1).toFixed(2); + values["frequency"] = Number(frequency); + } + + //energia + else if (register == 79) { + let energy = bytesToInt(bytes); + values["energy"] = energy / 1000; //energia v kWh -> delit 1000 + } + + //doba života + else if (register == 80) { + let lifetime = (bytesToInt(bytes) / 60).toFixed(2); + values["lifetime"] = Number(lifetime); + } + + //nastavenie profilu + else if (register == 8) { + let time_schedule_settings = bytesToInt(bytes); + values["time_schedule_settings"] = time_schedule_settings; + } + + //naklon - nateraz sa z nodu nevycitava! kvoli problemom s accelerometrom a vracanymi hodnotami, posielame temp a x y z vo funkcii accelerometerData() + else if (register == 84) { + values["temperature"] = byte3 >= 128 ? (byte3 - 128) * (-1) : byte3; + values["inclination_x"] = byte2 >= 128 ? (byte2 - 128) * (-1) : byte2; + values["inclination_y"] = byte1 >= 128 ? (byte1 - 128) * (-1) : byte1; + values["inclination_z"] = byte0 >= 128 ? (byte0 - 128) * (-1) : byte0; + } + + //FW verzia nodu + else if (register == 89) { + //formát: "Byte3: Byte2.Byte1 (Byte0)" + values["fw_version"] = byte3 + ":" + byte2 + "." + byte1 + "(" + byte0 + ")"; + } + + else if (register == 87 || register == 6 || register == 7) { + var d = new Date(); + d.setHours(byte3, byte2, 0, 0); + let timestamp = d.getTime(); + + //aktuálny čas + if (register == 87) values["actual_time"] = timestamp; + //čas súmraku + else if (register == 6) values["dusk_time"] = timestamp; + //čas úsvitu + else if (register == 7) values["dawn_time"] = timestamp; + } + + 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; + + } + + + function getObjectByTbValue(object, tbname) { + return object[Object.keys(object).find(key => object[key].tbname === tbname)]; + } + + + function isObject(item) { + return (typeof item === "object" && !Array.isArray(item) && item !== null); + } + + + // we fake data, that should be received from accelerometer, as they are a bit unreliable. (temperature, x,y,z) + function accelerometerData() { + + if (temperatureInSenica === null) return; + + //clone nodesData and relaysData objects + let nodesData_clone = JSON.parse(JSON.stringify(nodesData)); + let relaysData_clone = JSON.parse(JSON.stringify(relaysData)); + + for (const key in relaysData_clone) { + + const lineData = relaysData_clone[key]; + const lineNumber = lineData.line; + const contactor = lineData.contactor; + + if (lineNumber === 0) continue; + + if (contactor === 1) { + + let date = Date.now(); + + Object.keys(nodesData_clone).forEach((node, index) => { + + setTimeout(function() { + + if (nodesData_clone[node].line === lineNumber) { + + // NOTE: if status of luminaire is NOK or OFFLINE, we do not send data; + let status = nodesData_clone[node].status; + if (status === "OFFLINE" || !status) return; + + let x = null; + if (naklony.hasOwnProperty(node)) x = naklony[node].naklon; + if (x === null) x = 0; + + sendTelemetry({ temperature: Math.round(temperatureInSenica + 10 + Math.floor(Math.random() * 3)), inclination_x: x, inclination_y: 0, inclination_z: 0 }, nodesData_clone[node].tbname, date); + } + + }, (index + 1) * 500); + }) + + } + } + } + + +} // end of instance.export + diff --git a/RVO37/flow/code.js b/RVO37/flow/code.js new file mode 100755 index 0000000..63b31bf --- /dev/null +++ b/RVO37/flow/code.js @@ -0,0 +1,90 @@ +exports.id = 'code'; +exports.title = 'Code'; +exports.group = 'Common'; +exports.color = '#656D78'; +exports.input = true; +exports.output = 1; +exports.author = 'Peter Širka'; +exports.icon = 'code'; +exports.version = '1.2.0'; +exports.options = { outputs: 1, code: 'send(0, value);', keepmessage: true }; + +exports.html = `
+
+
+
@(Number of outputs)
+
@(Minimum is 1)
+
+
+
@(Code)
+
@(Keep message instance)
+
+`; + +exports.readme = `# Code + +This component executes custom JavaScript code as it is and it doesn't contain any secure scope. + +\`\`\`javascript +// value {Object} contains received data +// send(outputIndex, newValue) sends a new value +// error(value) sends an error +// instance {Object} a current component instance +// flowdata {Object} a current flowdata +// repository {Object} a current repository of flowdata +// Example: + +// send() can be execute multiple times +send(0, value); +\`\`\``; + +exports.install = function(instance) { + + var fn; + + instance.on('data', function(response) { + if (fn) { + try { + fn(response.data, instance, response, instance.options, response.repository, require); + } catch (e) { + response.data = e; + instance.throw(response); + } + } + }); + + instance.reconfigure = function() { + try { + if (instance.options.code) { + instance.status(''); + var code = 'var send = function(index, value) { if (options.keepmessage) { flowdata.data = value; instance.send2(index, flowdata); } else instance.send2(index, value);}; var error = function(err) { instance.throw(err); }; ' + instance.options.code; + fn = new Function('value', 'instance', 'flowdata', 'options', 'repository', 'require', code); + } else { + instance.status('Not configured', 'red'); + fn = null; + } + } catch (e) { + fn = null; + instance.error('Code: ' + e.message); + } + }; + + instance.on('options', instance.reconfigure); + instance.reconfigure(); +}; \ No newline at end of file diff --git a/RVO37/flow/comment.js b/RVO37/flow/comment.js new file mode 100755 index 0000000..1e0cd13 --- /dev/null +++ b/RVO37/flow/comment.js @@ -0,0 +1,11 @@ +exports.id = 'comment'; +exports.title = 'Comment'; +exports.group = 'Common'; +exports.color = '#704cff'; +exports.author = 'Martin Smola'; +exports.icon = 'comment'; +exports.traffic = false; +exports.version = '1.0.0'; +exports.readme = '# Comment'; + +exports.install = function() {}; diff --git a/RVO37/flow/count.js b/RVO37/flow/count.js new file mode 100755 index 0000000..fa92ee9 --- /dev/null +++ b/RVO37/flow/count.js @@ -0,0 +1,60 @@ +exports.id = 'count'; +exports.title = 'Count'; +exports.version = '1.0.1'; +exports.author = 'John Graves'; +exports.color = '#656D78'; +exports.icon = 'plus-square'; +exports.input = 2; +exports.output = 1; +exports.options = { increment: 1, initialvalue: 1 }; +exports.readme = `# Counter + +Counter Number of times called.`; + +exports.html = `
+
@(Initial Value)
+
@(Increment)
+

Example Video

+
`; + +exports.readme = `# Count + +This component counts the number of messages received. + +__Response:__ + +Integer value based on the initial value and increment settings. + +__Arguments:__ +- Initial Value: What number should be output on the receipt of the first message. +- Increment: What should the increment be for each following message received.`; + +exports.install = function(instance) { + + var count = 0; + var initialCall = true; + + instance.on('data', function(flowdata) { + var index = flowdata.index; + if (index) { + instance.debug('Reset Count.'); + count = instance.options.initialvalue; + initialCall = true; + } else { + // If this is the first time, set the value to 'initial value' + if(initialCall) { + initialCall = false; + count = instance.options.initialvalue; + } else + count = count+instance.options.increment; + instance.status('Count:' + count); + instance.send2(count); + } + }); + + instance.on('options', function() { + count = instance.options.initialvalue; + initialCall = true; + }); + +}; diff --git a/RVO37/flow/db_connector.js b/RVO37/flow/db_connector.js new file mode 100755 index 0000000..65ee94b --- /dev/null +++ b/RVO37/flow/db_connector.js @@ -0,0 +1,286 @@ +exports.id = 'db_connector'; +exports.title = 'DbConnector'; +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.html = `
+
+
+
DbConnector
+
+
+
`; + +exports.readme = `# read/write data to tables`; + +const instanceSendTo = { + debug: 0, + http_response: 1, +} + +const { promisifyBuilder, makeMapFromDbResult } = require('./helper/db_helper.js'); + +function extractWhereParams(params) +{ + let name = params[0]; + let operator = '='; + let value = params[1]; + + if(params.length == 3) + { + operator = params[1]; + value = params[2]; + } + + return {name: name, operator: operator, value: value}; +} + +exports.install = function(instance) { + + let refFlowdata = null;//holds reference to httprequest flowdata + + instance.on("close", () => { + + }) + + + instance.on("data", async function(flowdata) { + + let params = flowdata.data.body; + console.log("DbConnector", params); + + refFlowdata = flowdata; + + if(refFlowdata != undefined) + { + //make http response + let responseObj = {}; + responseObj["type"] = "SUCESS"; + + try{ + + let table = params.table; + let action = params.action; + + + if(params.data != undefined) + { + let className = params.data.className; + + if(className == "SqlQueryBuilder") + { + let type = params.data.type; + + console.log("SqlQueryBuilder---->", params.data); + + if(type == "SELECT") + { + let table = params.data.queryData.tables[0].table; + + const db = TABLE(table); + var builder = db.find(); + + let result = await promisifyBuilder(builder); + + let response = {}; + response["result"] = result; + response["success"] = true; + + responseObj["data"] = response; + + //console.log(responseObj); + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + } + + return; + } + } + + + console.log("db_connector---->", table, action); + + //actions: read, replace, insert, delete, update... + + if(action == "read") + { + const db = TABLE(params.table); + + //where builder.where('age', '<', 15); + //builder.where('id', 3403); + + var builder = db.find(); + + //https://docs.totaljs.com/latest/en.html#api~DatabaseBuilder~builder.where + if(params.hasOwnProperty("where")) + { + //optionalCan contain "=", "<=", "<", ">=", ">". + //Default value: '=' + + //1.["production_line", 1] + //2. ["or", ["production_line", 1], ["production_line", 2], "end"] + + if (Array.isArray(params.where)) { + + let multipleConditions = false; + + if(params.where[0] == "or") multipleConditions = true; + if (Array.isArray(params.where[0])) multipleConditions = true; + + if(multipleConditions) + { + + for(var i = 0; i < params.where.length; i++) + { + const item = params.where[i]; + + if(item === "or") builder.or(); + + if (Array.isArray(item)) + { + const { name, operator, value } = extractWhereParams(item); + builder.where(name, operator, value); + } + + if(item === "end") builder.end(); + + } + + } + else + { + const { name, operator, value } = extractWhereParams(params.where); + builder.where(name, operator, value); + } + + } + + /* + if(params.where.length >=2 ) + { + let name = params.where[0]; + let operator = '='; + let value = params.where[1]; + + if(params.where.length == 3) + { + operator = params.where[1]; + value = params.where[2]; + } + + builder.where(name, operator, value); + } + */ + } + + if(params.hasOwnProperty("between")) + { + builder.between(params.between[0], params.between[1], params.between[2]); + } + + let response = await promisifyBuilder(builder); + responseObj["data"] = response; + + //console.log(responseObj); + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + + return; + } + + if(action == "delete") + { + + } + + + if(action == "update") + { + //! data receiving from terminal (params) + // { + // hostname: 'localhost', + // table: 'settings', + // action: 'update', + // body: { + // rvo_name: 'terrrr', + // lang: 'en', + // temperature_adress: '28.427B45920702', + // latitude: 48.70826502, + // longitude: 17.28455203, + // mqtt_host: '192.168.252.4', + // mqtt_clientid: 'showroom_test_panel_led', + // mqtt_username: 'xmRd6RJxW53WZe4vMFLU', + // mqtt_port: 1883, + // maintanace_mode: false + // } + // } + const tableToModify = TABLE(params.table); + const newValues = params.body; + + tableToModify.modify(newValues).make(function(builder) { + + builder.callback(function(err, response) { + + if(!err) + { + responseObj["data"] = response; + responseObj["tableUpdated"] = true; + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + } + }); + }); + + } + + if(action == "replace") + { + //truncate table + const db = TABLE(params.table); + var builder = db.remove(); + db.clean(); + + //insert data + let data = params.data; + + for(let i = 0; i < data.length; i++) + { + //console.log(data[i]); + db.insert(data[i]); + } + + console.log("insert done"); + + let responseObj = {}; + responseObj["type"] = "SUCESS"; + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + + + } + + + + } catch (error) { + //console.log(error); + responseObj["type"] = "ERROR"; + responseObj["message"] = error; + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + } + } + }) +} + + diff --git a/RVO37/flow/db_init.js b/RVO37/flow/db_init.js new file mode 100755 index 0000000..b399878 --- /dev/null +++ b/RVO37/flow/db_init.js @@ -0,0 +1,113 @@ +exports.id = 'db_init'; +exports.title = 'DB Initialization'; +exports.group = 'Worksys'; +exports.color = '#888600'; +exports.version = '1.0.2'; +exports.icon = 'sign-out'; +exports.output = 2; + +exports.readme = ` + # DB initialization +`; + +const { promisifyBuilder, makeMapFromDbResult } = require('./helper/db_helper.js'); +const { initNotification } = require('./helper/notification_reporter'); +const errorHandler = require('./helper/ErrorToServiceHandler'); +const total_energy = require('../databases/total_energy'); + +const SEND_TO = { + db_init: 0, + infoSender: 1 +}; + + +exports.install = async function(instance) { + const dbNodes = TABLE("nodes"); + const dbRelays = TABLE("relays"); + const dbSettings = TABLE("settings"); + 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 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.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"]; + Object.keys(dbs.nodesData).forEach(node => dbs.nodesData[node].readout = {}) + + let rvo_number = responseSettings[0]["rvo_name"].match(/\D+(\d{1,2})_/)[1]; + + dbs.settings = { + edge_fw_version: "2025-10-08", //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"], + phases: responseSettings[0]["phases"], + cloud_topic: responseSettings[0]["cloud_topic"], + has_main_switch: responseSettings[0]["has_main_switch"], + daily_report: responseSettings[0]["daily_report"], + send_changed_node_numbers: responseSettings[0]["send_changed_node_numbers"], + rvo_number: rvo_number, + + //dynamic values + masterNodeIsResponding: true, //cmd_manager + maintenance_mode: false, + } + + + dbs.settings.energy_to_switch_lamps = total_energy[rvo_number]; + if (dbs.settings.energy_to_switch_lamps === undefined) console.log('=============== db_init.js: energy_to_switch_lamps is undefined'); + + FLOW.dbLoaded = true; + errorHandler.setProjectId(dbs.settings.project_id); + initNotification(); + + //APP START - send to data services + const toService = { + id: dbs.settings.project_id, + name: dbs.settings.rvo_name, + fw_version: dbs.settings.edge_fw_version, + startdate: new Date().toISOString().slice(0, 19).replace('T', ' '), + js_error: "", + error_message: "" + }; + + instance.send(SEND_TO.infoSender, toService); + console.log("----------------> START - message send to service", toService); + + setTimeout(() => { + console.log("DB_INIT - data loaded"); + instance.send(SEND_TO.db_init, "_") + }, 5000) + +}; + diff --git a/RVO37/flow/debug.js b/RVO37/flow/debug.js new file mode 100755 index 0000000..00cb259 --- /dev/null +++ b/RVO37/flow/debug.js @@ -0,0 +1,100 @@ +exports.id = 'debug'; +exports.title = 'Debug'; +exports.author = 'Peter Širka'; +exports.color = '#967ADC'; +exports.click = true; +exports.input = true; +exports.icon = 'bug'; +exports.version = '2.0.4'; +exports.options = { enabled: true, repository: false, type: 'data' }; +exports.readme = `# Debug + +Prints data to the debug tab.`; + +exports.html = `
+
+
+
@(Output type)
+
@(Path to the property (leave empty to show the whole data object))
+
@(A group name)
+
@(Enabled)
+
+
+
`; + +exports.install = function(instance) { + + instance.on('data', function(response) { + if (instance.options.enabled) { + + var opt = instance.options; + var rep = response.repository; + var val = response.data; + var id = response.id; + + switch (instance.options.type){ + case 'both': + var data = {}; + data.repository = rep; + data.data = val instanceof Error ? { error: val.message, stack: val.stack } : val; + instance.debug(safeparse(opt.property ? U.get(data, opt.property) : data), undefined, opt.group, id); + break; + case 'repository': + instance.debug(safeparse(opt.property ? U.get(rep, opt.property) : rep), undefined, opt.group, id); + break; + case 'data': + default: + if (val instanceof Error) + instance.debug({ error: val.message, stack: val.stack }, undefined, opt.group, id); + else + instance.debug(safeparse(opt.property ? U.get(val, opt.property) : val), undefined, opt.group, id); + break; + } + } + }); + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + instance.save(); + }); + + instance.on('options', function() { + instance.custom.status(); + }); + + instance.custom.status = function() { + instance.status(instance.options.enabled ? 'Enabled' : 'Disabled'); + }; + + instance.custom.status(); + + function safeparse(o) { + + if (o instanceof Buffer) + return o; + + if (o === undefined) + return 'undefined'; + + if (o === null) + return 'null'; + + var cache = []; + var str = JSON.stringify(o, function(key, value) { + if (typeof value === 'object' && value !== null) { + if (cache.indexOf(value) !== -1) { + try { + return JSON.parse(JSON.stringify(value)); + } catch (error) { + return; + } + } + cache.push(value); + } + return value; + }); + cache = null; + return JSON.parse(str); + } +}; diff --git a/RVO37/flow/designer.json b/RVO37/flow/designer.json new file mode 100755 index 0000000..580f5a3 --- /dev/null +++ b/RVO37/flow/designer.json @@ -0,0 +1,3102 @@ +{ + "tabs": [ + { + "name": "MAIN PUSH", + "linker": "main-push", + "id": "1612772287426", + "index": 0 + }, + { + "name": "CMD manager", + "linker": "cmd-manager", + "id": "1615551125555", + "index": 1 + }, + { + "name": "Devices", + "linker": "devices", + "id": "1611921777196", + "index": 2 + } + ], + "components": [ + { + "id": "1611951142547", + "component": "debug", + "tab": "1611921777196", + "name": "ERROR", + "x": 598, + "y": 60, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#DA4453", + "notes": "" + }, + { + "id": "1612776786008", + "component": "wsmqttpublish", + "tab": "1612772287426", + "name": "WS MQTT publish", + "x": 281.75, + "y": 174, + "connections": { + "0": [ + { + "index": "0", + "id": "1615551060773" + } + ], + "1": [ + { + "index": "0", + "id": "1618300858252" + }, + { + "index": "0", + "id": "1618558465485" + } + ], + "2": [ + { + "index": "0", + "id": "1634303685503" + } + ], + "3": [ + { + "index": "0", + "id": "1731068754606" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Connected", + "color": "green" + }, + "options": { + "username": "", + "clientid": "", + "port": "1883", + "host": "" + }, + "color": "#888600", + "notes": "" + }, + { + "id": "1612778461252", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "tb-push", + "x": 72.75, + "y": 328, + "connections": { + "0": [ + { + "index": "0", + "id": "1612783322136" + }, + { + "index": "1", + "id": "1612776786008" + }, + { + "index": "0", + "id": "1731068754606" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1612783322136", + "component": "debug", + "tab": "1612772287426", + "name": "to TB", + "x": 283.75, + "y": 324, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615551060773", + "component": "debug", + "tab": "1612772287426", + "name": "errors from MQTT Broker", + "x": 594, + "y": 57, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#DA4453", + "notes": "" + }, + { + "id": "1615563373927", + "component": "debug", + "tab": "1615551125555", + "name": "Debug", + "x": 755, + "y": 155, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#DA4453", + "notes": "" + }, + { + "id": "1615566865233", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "tb-push", + "x": 755, + "y": 248, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1615798582262", + "component": "debug", + "tab": "1615551125555", + "name": "CMD_debug", + "x": 755, + "y": 346, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615802995322", + "component": "debug", + "tab": "1611921777196", + "name": "Debug", + "x": 596.8833312988281, + "y": 566.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Disabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": false + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615809128443", + "component": "debug", + "tab": "1611921777196", + "name": "tempToTb", + "x": 595.8833312988281, + "y": 658.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615809595184", + "component": "virtualwireout", + "tab": "1611921777196", + "name": "tb-push", + "x": 597.8833312988281, + "y": 377.25, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1616165795916", + "component": "httproute", + "tab": "1615551125555", + "name": "POST /terminal", + "x": 135, + "y": 547, + "connections": { + "0": [ + { + "index": "0", + "id": "1684060205000" + }, + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Listening", + "color": "green" + }, + "options": { + "timeout": 10, + "cachepolicy": 0, + "cacheexpire": "5 minutes", + "size": 5, + "url": "/terminal", + "method": "POST", + "name": "", + "flags": [ + "id:1616165795916", + "post", + 10000 + ], + "emptyresponse": false + }, + "color": "#5D9CEC", + "notes": "### Configuration\n\n- __POST /terminal__\n- flags: \n- maximum request data length: __5 kB__\n- empty response: __false__\n- cache policy: __no cache__\n- cache expire: __5 minutes__", + "cloning": false + }, + { + "id": "1616165824813", + "component": "httpresponse", + "tab": "1615551125555", + "name": "HTTP Response", + "x": 753, + "y": 423, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "json" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1617104731852", + "component": "debug", + "tab": "1615551125555", + "name": "DIDO_Debug", + "x": 669, + "y": 1040, + "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": "turnOff line", + "x": 133, + "y": 1161, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "object", + "data": "{line: 3, command: \"turnOff\", force: true}" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1617115013095", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "tb-push", + "x": 669, + "y": 1150, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1617284749681", + "component": "trigger", + "tab": "1615551125555", + "name": "update profile / node", + "x": 112, + "y": 208, + "connections": { + "0": [ + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "data": "profile_nodes", + "datatype": "string" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1618235171399", + "component": "trigger", + "tab": "1615551125555", + "name": "tun tasks", + "x": 184, + "y": 279, + "connections": { + "0": [ + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "data": "run" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1618300858252", + "component": "debug", + "tab": "1612772287426", + "name": "wsmqtt-exit1", + "x": 597.8833312988281, + "y": 149, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1618393583970", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "to-cmd-manager", + "x": 668.8833312988281, + "y": 1269, + "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": 132.88333129882812, + "y": 367, + "connections": { + "0": [ + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "platform-rpc-call", + "color": "gray" + }, + "options": { + "wirename": "platform-rpc-call" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1618393759854", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "cmd_to_dido", + "x": 119.88333129882812, + "y": 1007, + "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": 752.8833312988281, + "y": 527, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "cmd_to_dido", + "color": "gray" + }, + "options": { + "wirename": "cmd_to_dido" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1618558465485", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "platform-rpc-call", + "x": 597.8833312988281, + "y": 247, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "platform-rpc-call", + "color": "gray" + }, + "options": { + "wirename": "platform-rpc-call" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1618572059773", + "component": "trigger", + "tab": "1615551125555", + "name": "turnOn line", + "x": 132, + "y": 1085, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "data": "{line: 1, command: \"turnOn\", force: true}", + "datatype": "object" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1619515097737", + "component": "cmd_manager", + "tab": "1615551125555", + "name": "CMD Manager", + "x": 452.1091003417969, + "y": 341.05455017089844, + "connections": { + "0": [ + { + "index": "0", + "id": "1615563373927" + } + ], + "1": [ + { + "index": "0", + "id": "1615566865233" + }, + { + "index": "0", + "id": "1615798582262" + } + ], + "2": [ + { + "index": "0", + "id": "1616165824813" + } + ], + "3": [ + { + "index": "0", + "id": "1618393827655" + } + ], + "4": [ + { + "index": "0", + "id": "1635936391935" + } + ], + "5": [ + { + "index": "0", + "id": "1757006030239" + }, + { + "index": "0", + "id": "1757006060377" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1619605019281", + "component": "httproute", + "tab": "1615551125555", + "name": "GET db", + "x": 173, + "y": 653, + "connections": { + "0": [ + { + "index": "0", + "id": "1684060205000" + }, + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Listening", + "color": "green" + }, + "options": { + "timeout": 5, + "cachepolicy": 0, + "cacheexpire": "5 minutes", + "size": 5, + "url": "/db", + "method": "GET", + "name": "", + "flags": [ + "id:1619605019281", + "get", + 5000 + ] + }, + "color": "#5D9CEC", + "notes": "### Configuration\n\n- __GET /db__\n- flags: undefined\n- maximum request data length: __5 kB__\n- empty response: __undefined__\n- cache policy: __no cache__\n- cache expire: __5 minutes__", + "cloning": false + }, + { + "id": "1619784672383", + "component": "trigger", + "tab": "1615551125555", + "name": "turnOnAlarm", + "x": 120, + "y": 1234, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "object", + "data": "{command: \"turnOnAlarm\"}" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1619784812964", + "component": "trigger", + "tab": "1615551125555", + "name": "turnOffAlarm", + "x": 118, + "y": 1307, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "object", + "data": "{command: \"turnOffAlarm\"}" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1621340721628", + "component": "virtualwireout", + "tab": "1611921777196", + "name": "modbus_to_dido", + "x": 599, + "y": 471, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "modbus_to_dido", + "color": "gray" + }, + "options": { + "wirename": "modbus_to_dido" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1622640022885", + "component": "httproute", + "tab": "1615551125555", + "name": "POST /db_connector", + "x": 98, + "y": 1586, + "connections": { + "0": [ + { + "index": "0", + "id": "1622640073521" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Listening", + "color": "green" + }, + "options": { + "timeout": 5, + "cachepolicy": 0, + "cacheexpire": "5 minutes", + "size": 5, + "url": "/db_connector", + "method": "POST", + "flags": [ + "id:1622640022885", + "post", + 5000 + ] + }, + "color": "#5D9CEC", + "notes": "### Configuration\n\n- __POST /db_connector__\n- flags: \n- maximum request data length: __5 kB__\n- empty response: __undefined__\n- cache policy: __no cache__\n- cache expire: __5 minutes__", + "cloning": false + }, + { + "id": "1622640073521", + "component": "db_connector", + "tab": "1615551125555", + "name": "DbConnector", + "x": 372, + "y": 1572, + "connections": { + "1": [ + { + "index": "0", + "id": "1622641420685" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "edge": "undefined" + }, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1622641420685", + "component": "httpresponse", + "tab": "1615551125555", + "name": "HTTP Response", + "x": 596, + "y": 1586, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1634303504177", + "component": "monitormemory", + "tab": "1612772287426", + "name": "RAM", + "x": 69.88333129882812, + "y": 888.5, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465281992" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "858.88 MB / 985.68 MB", + "color": "gray" + }, + "options": { + "enabled": true, + "interval": 30000 + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1634303533779", + "component": "monitordisk", + "tab": "1612772287426", + "name": "disk", + "x": 70.88333129882812, + "y": 982.5, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465821120" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "5.78 GB / 7.26 GB", + "color": "gray" + }, + "options": { + "enabled": true, + "path": "/", + "interval": 30000 + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1634303595494", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "send-to-services", + "x": 51.883331298828125, + "y": 1400.5, + "connections": { + "0": [ + { + "index": "0", + "id": "1634463186563" + }, + { + "index": "1", + "id": "1634488120710" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1634303602169", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "send-to-services", + "x": 426.8833312988281, + "y": 878.5, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1634303685503", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "send-to-services", + "x": 600.8833312988281, + "y": 341.5, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1634303743260", + "component": "httprequest", + "tab": "1612772287426", + "name": "192.168.252.2:8004/sentmessage", + "reference": "", + "x": 506.8833312988281, + "y": 1331.7333374023438, + "connections": { + "0": [ + { + "index": "0", + "id": "1635327431236" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "url": "http://192.168.252.2:8004/sentmessage", + "method": "POST", + "stringify": "json" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1634463186563", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 305.75, + "y": 1442, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634464580289", + "component": "code", + "tab": "1612772287426", + "name": "Code", + "x": 245, + "y": 787, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465243324" + }, + { + "index": "0", + "id": "1634303602169" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "keepmessage": true, + "code": "let response = {};\nresponse.cpu = value.cpu;\nresponse.uptime = value.uptime;\n\nsend(0, response);", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1634465243324", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 428, + "y": 784, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634465281992", + "component": "code", + "tab": "1612772287426", + "name": "Code", + "x": 245, + "y": 884, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465338103" + }, + { + "index": "0", + "id": "1634303602169" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "keepmessage": true, + "code": "value.sender = \"ram\";\n\nlet response = {};\n\nresponse.memory_total = Math.round(value.total / (1024 ** 2));\nresponse.memory_free = Math.round(value.free / (1024 ** 2));\nresponse.memory_used = Math.round(value.used / (1024 ** 2));\n\nsend(0, response);", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1634465338103", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 429, + "y": 976, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634465821120", + "component": "code", + "tab": "1612772287426", + "name": "Code", + "x": 245, + "y": 978, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465892500" + }, + { + "index": "0", + "id": "1634303602169" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "keepmessage": true, + "code": "value.sender = \"hdd\";\n\nlet response = {};\n\nresponse.hdd_total = Math.round(value.total / (1024 ** 2));\nresponse.hdd_free = Math.round(value.free / (1024 ** 2));\nresponse.hdd_used = Math.round(value.used / (1024 ** 2));\n\nsend(0, response);", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1634465892500", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 432, + "y": 1068, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634484067516", + "component": "debug", + "tab": "1612772287426", + "name": "Send info", + "x": 513, + "y": 1441, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634488120710", + "component": "infosender", + "tab": "1612772287426", + "name": "Info sender", + "x": 301, + "y": 1336, + "connections": { + "0": [ + { + "index": "0", + "id": "1634484067516" + }, + { + "index": "0", + "id": "1634303743260" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "edge": "undefined" + }, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1635327431236", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 837.8833312988281, + "y": 1325.5, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1635936391935", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "send-to-services", + "x": 753, + "y": 623, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1637069803394", + "component": "monitorconsumption", + "tab": "1612772287426", + "name": "CPU", + "x": 69, + "y": 791, + "connections": { + "0": [ + { + "index": "0", + "id": "1634464580289" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "49.2% / 69.91 MB", + "color": "gray" + }, + "options": { + "monitorfiles": true, + "monitorconnections": true, + "monitorsize": true, + "monitorconsumption": true, + "enabled": true, + "interval": 30000 + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1683664161036", + "component": "debug", + "tab": "1615551125555", + "name": "CMDtoDIDO", + "x": 392, + "y": 1012, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1683981346282", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "from-dido-controller", + "x": 112, + "y": 459, + "connections": { + "0": [ + { + "index": "0", + "id": "1684055037116" + }, + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "from-dido-controller", + "color": "gray" + }, + "options": { + "wirename": "from-dido-controller" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1684055037116", + "component": "debug", + "tab": "1615551125555", + "name": "from dido to cmd", + "x": 451, + "y": 532, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1684060205000", + "component": "debug", + "tab": "1615551125555", + "name": "HTTP routes", + "x": 450, + "y": 639, + "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": "MDBToDido", + "x": 598, + "y": 147, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1699963668903", + "component": "dido_controller", + "tab": "1615551125555", + "name": "DIDO_Controller", + "x": 397, + "y": 1131, + "connections": { + "0": [ + { + "index": "0", + "id": "1617104731852" + } + ], + "1": [ + { + "index": "0", + "id": "1617104731852" + }, + { + "index": "0", + "id": "1617115013095" + } + ], + "2": [ + { + "index": "0", + "id": "1618393583970" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "edge": "undefined" + }, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1699964678894", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "modbus_to_dido", + "x": 96, + "y": 924, + "connections": { + "0": [ + { + "index": "0", + "id": "1699963668903" + }, + { + "index": "0", + "id": "1699964793925" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "modbus_to_dido", + "color": "gray" + }, + "options": { + "wirename": "modbus_to_dido" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1699964793925", + "component": "debug", + "tab": "1615551125555", + "name": "modbusToDido", + "x": 388, + "y": 920, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1699965957410", + "component": "modbus_reader", + "tab": "1611921777196", + "name": "Modbus reader", + "x": 232, + "y": 175, + "connections": { + "0": [ + { + "index": "0", + "id": "1611951142547" + } + ], + "1": [ + { + "index": "0", + "id": "1621340721628" + }, + { + "index": "0", + "id": "1684179110403" + }, + { + "index": "0", + "id": "1717441414646" + } + ], + "2": [ + { + "index": "0", + "id": "1615809595184" + }, + { + "index": "0", + "id": "1714752862828" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1700411878636", + "component": "thermometer", + "tab": "1611921777196", + "name": "Thermometer", + "x": 234.75, + "y": 444, + "connections": { + "0": [ + { + "index": "0", + "id": "1615802995322" + } + ], + "1": [ + { + "index": "0", + "id": "1615809595184" + }, + { + "index": "0", + "id": "1615809128443" + } + ], + "2": [ + { + "index": "0", + "id": "1621340721628" + }, + { + "index": "0", + "id": "1732889185927" + }, + { + "index": "0", + "id": "1717441414646" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#5CB36D", + "notes": "" + }, + { + "id": "1714752862828", + "component": "debug", + "tab": "1611921777196", + "name": "MDBToTb", + "x": 766, + "y": 324, + "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": 764.0833282470703, + "y": 222, + "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\telse if(value.status === \"NOK-thermometer\")\n\t{\n\t\tsend(0, {\"thermometer\": \"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\telse if(value.values.hasOwnProperty(\"temperature\"))\n\t{\n\t\tsend(0, {\"thermometer\": \"OK\"});\n\t}\n}", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1717442627834", + "component": "debug", + "tab": "1611921777196", + "name": "modbus service", + "x": 966.0833282470703, + "y": 165, + "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": 968.0833282470703, + "y": 268, + "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": 88.75, + "y": 1685, + "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": 296, + "y": 1671, + "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\", \"Flow has been restarted\", \"Node db has changed\"]", + "types": "[\"emergency\", \"critical\", \"error\", \"alert\"]", + "name": "" + }, + "color": "#30E193", + "notes": "" + }, + { + "id": "1718016073501", + "component": "httprequest", + "tab": "1612772287426", + "name": "http://192.168.252.2:8004/slack", + "x": 495, + "y": 1753, + "connections": { + "0": [ + { + "index": "0", + "id": "1718016086212" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "url": "http://192.168.252.2:8004/slack", + "method": "POST", + "stringify": "json" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1718016086212", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 832, + "y": 1664, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "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": 87, + "y": 1591, + "connections": { + "0": [ + { + "index": "0", + "id": "1718016052341" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "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\": \"\" } } } ] }", + "datatype": "object" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1729855334955", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "platform-rpc-call", + "x": 599.9333343505859, + "y": 541.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "platform-rpc-call", + "color": "gray" + }, + "options": { + "wirename": "platform-rpc-call" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1729855371093", + "component": "debug", + "tab": "1612772287426", + "name": "rpc cloud", + "x": 601.9333343505859, + "y": 440.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1731068658334", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 75.75, + "y": 184, + "connections": { + "0": [ + { + "index": "0", + "id": "1612776786008" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731068754606", + "component": "cloudmqttconnect", + "tab": "1612772287426", + "name": "MQTT to senica-prod01", + "x": 284.75, + "y": 452, + "connections": { + "1": [ + { + "index": "0", + "id": "1729855371093" + }, + { + "index": "0", + "id": "1729855334955" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Connected", + "color": "green" + }, + "options": { + "username": "", + "clientid": "", + "port": "2764", + "host": "192.168.252.2", + "topic": "" + }, + "color": "#888600", + "notes": "" + }, + { + "id": "1731069001548", + "component": "db_init", + "tab": "1612772287426", + "name": "DB Initialization", + "x": 1003.75, + "y": 240.25, + "connections": { + "0": [ + { + "index": "0", + "id": "1731069033416" + } + ], + "1": [ + { + "index": "0", + "id": "1747561603739" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#888600", + "notes": "" + }, + { + "id": "1731069033416", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "db-init", + "x": 1244.75, + "y": 233.25, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069059135", + "component": "showdb", + "tab": "1612772287426", + "name": "Show db data", + "x": 1186.75, + "y": 821.25, + "connections": { + "0": [ + { + "index": "0", + "id": "1731069079243" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#888600", + "notes": "" + }, + { + "id": "1731069079243", + "component": "debug", + "tab": "1612772287426", + "name": "dbData", + "x": 1390.75, + "y": 870.25, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1731069116691", + "component": "trigger", + "tab": "1612772287426", + "name": "settings", + "x": 934.75, + "y": 669.75, + "connections": { + "0": [ + { + "index": "0", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069131637", + "component": "trigger", + "tab": "1612772287426", + "name": "relaysData", + "x": 876.75, + "y": 733.75, + "connections": { + "0": [ + { + "index": "1", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069137374", + "component": "trigger", + "tab": "1612772287426", + "name": "nodesData", + "x": 852.75, + "y": 794.75, + "connections": { + "0": [ + { + "index": "2", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069179846", + "component": "trigger", + "tab": "1612772287426", + "name": "pinsData", + "x": 850.75, + "y": 861.75, + "connections": { + "0": [ + { + "index": "3", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069192937", + "component": "trigger", + "tab": "1612772287426", + "name": "sample data", + "x": 857.75, + "y": 928.75, + "connections": { + "0": [ + { + "index": "4", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069264443", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 63.75, + "y": 1279, + "connections": { + "0": [ + { + "index": "0", + "id": "1634488120710" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069334626", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "db-init", + "x": 172.88333129882812, + "y": 129, + "connections": { + "0": [ + { + "index": "0", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069548145", + "component": "virtualwirein", + "tab": "1611921777196", + "name": "db-init", + "x": 46.75, + "y": 192, + "connections": { + "0": [ + { + "index": "0", + "id": "1699965957410" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069567152", + "component": "virtualwirein", + "tab": "1611921777196", + "name": "db-init", + "x": 44.75, + "y": 465, + "connections": { + "0": [ + { + "index": "0", + "id": "1700411878636" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731070156936", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "db-init", + "x": 126.88333129882812, + "y": 1377, + "connections": { + "0": [ + { + "index": "2", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731234189516", + "component": "trigger", + "tab": "1612772287426", + "name": "monitor.txt", + "x": 882.75, + "y": 991.75, + "connections": { + "0": [ + { + "index": "5", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731234189551", + "component": "trigger", + "tab": "1612772287426", + "name": "err.txt", + "x": 904.75, + "y": 1053.75, + "connections": { + "0": [ + { + "index": "6", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1732700042559", + "component": "nodesdb_change_check", + "tab": "1612772287426", + "name": "Nodes DB change check", + "x": 266.8833312988281, + "y": 1980.2333984375, + "connections": { + "0": [ + { + "index": "0", + "id": "1732700071298" + }, + { + "index": "0", + "id": "1732700642917" + } + ], + "1": [ + { + "index": "0", + "id": "1759958914348" + }, + { + "index": "0", + "id": "1759959003114" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#888600", + "notes": "" + }, + { + "id": "1732700057052", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 76.75, + "y": 1988, + "connections": { + "0": [ + { + "index": "0", + "id": "1732700042559" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1732700071298", + "component": "debug", + "tab": "1612772287426", + "name": "nodesChange", + "x": 571.8833312988281, + "y": 2018.2333984375, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1732700642917", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "tb-push", + "x": 567.8833312988281, + "y": 1933, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1732889185927", + "component": "debug", + "tab": "1611921777196", + "name": "tempToDido", + "x": 594.8833312988281, + "y": 753, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1733574412965", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 72.75, + "y": 474, + "connections": { + "0": [ + { + "index": "1", + "id": "1731068754606" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1747561603739", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "send-to-services", + "x": 1243.8833312988281, + "y": 334.5, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1747562867845", + "component": "comment", + "tab": "1612772287426", + "name": "FLOW STARTING POINT", + "x": 1003.5666656494141, + "y": 178, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#704cff", + "notes": "" + }, + { + "id": "1749211698385", + "component": "trigger", + "tab": "1612772287426", + "name": "deviceStatus", + "x": 911.75, + "y": 1116.75, + "connections": { + "0": [ + { + "index": "7", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1757006030239", + "component": "httprequest", + "tab": "1615551125555", + "name": "192.168.252.2:8015/daily_report", + "x": 756.5666656494141, + "y": 715.4499969482422, + "connections": { + "0": [ + { + "index": "0", + "id": "1757006045804" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "stringify": "json", + "method": "POST", + "url": "http://192.168.252.2:8015/daily_report" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1757006045804", + "component": "debug", + "tab": "1615551125555", + "name": "ddd", + "x": 1091.566665649414, + "y": 711.4499969482422, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1757006060377", + "component": "debug", + "tab": "1615551125555", + "name": "reportDebug", + "x": 749.5666656494141, + "y": 799.4499969482422, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1759958914348", + "component": "httprequest", + "tab": "1612772287426", + "name": "http://192.168.252.2:8015/node_numbers", + "x": 571, + "y": 2111, + "connections": { + "0": [ + { + "index": "0", + "id": "1759958927094" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "stringify": "json", + "method": "POST", + "url": "http://192.168.252.2:8015/node_numbers" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1759958927094", + "component": "debug", + "tab": "1612772287426", + "name": "nodesChangeCloud", + "x": 951.8833312988281, + "y": 2109.2333984375, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1759959003114", + "component": "debug", + "tab": "1612772287426", + "name": "nodeChangeCloud1", + "x": 574, + "y": 2218, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1760020290879", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 84.75, + "y": 1787, + "connections": { + "0": [ + { + "index": "1", + "id": "1718016052341" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + } + ], + "version": 615 +} diff --git a/RVO37/flow/dido_controller.js b/RVO37/flow/dido_controller.js new file mode 100755 index 0000000..d16fb19 --- /dev/null +++ b/RVO37/flow/dido_controller.js @@ -0,0 +1,1486 @@ +exports.id = 'dido_controller'; +exports.title = 'DIDO_Controller'; +exports.version = '2.0.0'; +exports.group = 'Worksys'; +exports.color = '#2134B0'; +exports.input = 3; +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 + +state_of_main_switch - reportovat stav hlaveho istica : 0-> off 1-> on +rotary_switch_state - sem by sa mal reportovat stav vstupov manual a auto pola nasledovnej logiky: Manual = 1 a Auto = 0 -> Manu +Manual = 0 a Auto = 0 -> Off, Manual = 0 a Auto = 1 -> Automatic + +door_condition - pin 6, dverový kontakt -> 1 -> vyreportuje Closed, 0 -> vyreportuje Ope +twilight_sensor - hodnotu, ktoru vracia ten analogovy vstup (17) treba poslat sem ako float number. Zrejme tu potom pridame nejaky koeficient prevodu na luxy + +Na kazdu liniu +state_of_breaker - podla indexu istica sa reportuje jeho stav, teda istic na liniu 1: 0-> off, 1-> on +state_of_contactor - podla indexu stkaca sa reportuje jeho stav, teda stykac 1 na liniu 1: 0-> off, 1-> on +*/ + +const { errLogger, logger, monitor } = require('./helper/logger'); +const SerialPort = require('serialport'); +const WebSocket = require('ws'); +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 errorHandler = require('./helper/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 hasMainSwitch; + +let alarmStatus = "OFF"; + +const SEND_TO = { + debug: 0, + tb: 1, + cmd_manager: 2 +} + + +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 = {}; + let rsPortReceivedData = []; + + //to be able to get proper twilight values + let twilight_sensor_interval = 5;//minutes + let twilight_sensor = []; + const twilight_sensor_array = []; + let twilightError = false; + + monitor.info("DIDO_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-we make it global to see it from outside + FLOW.deviceStatus = { //key is device name: temperature,.... + "state_of_main_switch": "Off", //Hlavny istic (alebo druhy dverovy kontakt) + "rotary_switch_state": "Off", //Prevadzkovy + "door_condition": "closed", //Dverový kontakt + "em": "OK", //elektromer rvo + "temperature": "OK", //templomer + "battery": "OK", //Bateria + "power_supply": "OK", //Zdroj + "master_node": "OK", //MN - GLOBALS.settings.masterNodeIsResponding + "no_voltage": "OK", //GLOBALS.settings.no_voltage - vypadok napatia na faze + "state_of_breaker": {}, //"Off",//Istic + "state_of_contactor": {}, //"Off",//Stykac + "twilight_sensor": "OK" //lux sensor + }; + let deviceStatus = FLOW.deviceStatus; + + + function main() { + + GLOBALS = FLOW.GLOBALS; + SETTINGS = FLOW.GLOBALS.settings; + rvoTbName = SETTINGS.rvoTbName; + pinsData = GLOBALS.pinsData; + relaysData = GLOBALS.relaysData; + + tbHandler = new DataToTbHandler(SEND_TO.tb); + tbHandler.setSender(exports.title); + + controller_type = SETTINGS.controller_type; //"lm" or "unipi" + hasMainSwitch = SETTINGS.has_main_switch; + + if (controller_type == "") controller_type = "lm"; + + 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, "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; + } + } + + //report RVO version relaysData[0].tbname; + let values = {}; + values["edge_fw_version"] = SETTINGS.edge_fw_version; + values["maintenance_mode"] = SETTINGS.maintenance_mode; + + sendTelemetry(values, rvoTbName); + + 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); + } + + + function handleRsPort() { + + if (rsPort) { + rsPort.removeAllListeners(); + rsPort = null; + } + + //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('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) { + if (!err) { + monitor.info(exports.title + "--->Digital in_out has been set (runSyncExec was sucessfull)"); + + turnAlarm("off"); + 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('error', err => { + let message = "Dido: rsPort error: " + err.message; + logger.debug(message); + monitor.info(message); + errorHandler.sendMessageToService(message); + }) + + rsPort.on("close", () => { + let message = "Dido: rsPort closed - reconnecting ..."; + logger.debug(message); + monitor.info(message); + setTimeout(handleRsPort, 1000); + }) + + rsPort.open(); + } + + + function handleWebSocket() { + + if (ws) { + ws.removeAllListeners(); + ws = null; + } + + //to keep websocket opened, we send request every 150 seconds + let startRequests = null; + + console.log("handleWebSocket function called"); + ws = new WebSocket('ws:/0.0.0.0:1234/ws'); + + ws.onopen = function open() { + + instance.send(0, exports.title + " running"); + turnAlarm("off"); + + initialSetting(); + + setTimeout(function() { ws.send(JSON.stringify({ cmd: "all" })) }, 5000); + // we request dev info about neuron device from evok to keep websocket connection alive + // for some reason this request returns no data, but connection keeps alive + startRequests = setInterval(() => { + ws.send(JSON.stringify({ "cmd": "filter", "dev": ["neuron"] })); + }, 150000) + }; + + + // 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 = async 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; + + 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 => { + logger.debug('Dido: websocket error', err); + }) + + ws.onclose = function() { + logger.debug('Dido: websocket onclose, reconnecting...') + clearInterval(startRequests); + setTimeout(handleWebSocket, 1000); + } + } + + 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 turnAlarm(onOrOff) { + let value = 0; + if (onOrOff == "on") value = 1; + + if (value == 1 && SETTINGS.maintenance_mode) return; + + alarmStatus = "OFF"; + if (value == 1) alarmStatus = "ON"; + + if (rsPort) { + let arr = [0x55]; + arr.push(13); + arr.push(0); + arr.push(value); + + rsPort.write(Buffer.from(arr), function(err) { + logger.debug(`sirena - ${onOrOff}`); + }); + } + else if (ws) { + let cmd = { "cmd": "set", "dev": "relay", "circuit": "1_01", "value": value }; + ws.send(JSON.stringify(cmd)); + logger.debug(`sirena - ${onOrOff}`); + } + } + + + 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") { + bits.push(0); + } + else bits.push(1); + + if (deviceStatus["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); + } + + + // turn line on or off + function turnLine(onOrOff, line, pin, force, info) { + //onOrOff => "on" or "off" + let value = 0; + if (onOrOff == "on") value = 1; + + if (force == undefined) force = false; + + if (line == 0) { + if (value == 1 && alarmStatus == "ON") turnAlarm("off"); + SETTINGS.maintenance_mode = value ? true : false; + + 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); + return; + } + + if (pin === undefined) pin = getPin(line); + + if (pin === undefined) { + errLogger.error("pin is undefined!", line); + return; + } + + if (!force) { + if (relaysData[line].contactor == value) { + instance.send(SEND_TO.debug, `line is already ${onOrOff} ` + line); + logger.debug(`Dido: turnLine: line is already ${onOrOff} `, line); + return; + } + } + + // if(!rsPort.isOpen && !ws) + if (!rsPort && !ws) { + errLogger.error("Dido - port or websocket is not opened"); + return; + } + + if (rsPort) { + let arr = [0x55]; + arr.push(pin); + arr.push(0); + arr.push(value); + + rsPort.write(Buffer.from(arr), function(err) { + if (err === undefined) { + monitor.info(`Dido: turnLine ${onOrOff} zapisal do rsPort-u`, line, pin, arr, info); + switchLogic(arr); + } + else { + monitor.info(`Dido: turnLine ${onOrOff} WRITE error`, err); + } + }); + + } + else if (ws) { + //pin = "relay1_03" or "input1_01" ... we must make just "1_01" with slice method + monitor.info(`Dido: turnLine ${onOrOff} - (line, pin, force)`, line, pin, force, info); + let cmd = { "cmd": "set", "dev": "relay", "circuit": pin.slice(5), "value": value }; + ws.send(JSON.stringify(cmd)); + } + + //if rvo is 24/7, it has just one switching profile point at 13:00. we do not want to send notification as it repeats every day. + //const d = new Date(); + //if(d.getHours() != 13) sendNotification("Dido_controller: ", SETTINGS.rvoTbName, "switching_profile_point_applied_to_line", { line: line, value: onOrOff }, "", SEND_TO.tb, instance); + } + + + // 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; + + // 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) { + const status = flowdata.data.status; + if (status == "NOK-twilight_sensor") { + deviceStatus["twilight_sensor"] = "NOK"; + } + else if (status == "NOK-em340" || status == "NOK-em111") { + deviceStatus["em"] = "NOK"; + } + else if (status == "NOK-thermometer") { + deviceStatus["temperature"] = "NOK"; + } + } + else if ("values" in flowdata.data) { + 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" + } + else if (values.hasOwnProperty("temperature")) { + deviceStatus["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"; + } + + sendTelemetry(values, rvoTbName); + } + + sendRvoStatus(); + }) + + + + + // we expect array as flowdata.data + instance.on("1", flowdata => { + + //console.log(flowdata.data); + + if (!flowdata.data instanceof Object) return; + + let obj = flowdata.data; + let line = obj.line; + 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"); + }) + + + function calculateStateCode() { + + let bits = []; + + //Hlavny istic - state_of_main_switch => v rvo senica je to druhy door pre silovu cast (EM) + if (deviceStatus["state_of_main_switch"] === "closed" || deviceStatus["state_of_main_switch"] === "Off") { + bits.push(0); + } + else { + bits.push(1); + } + + //Prevadzkovy mod - Manual, Off, Automatic, maintenance_mode = true/false // DAVA 2 BITY + if (!SETTINGS.maintenance_mode) { + if (deviceStatus["rotary_switch_state"] === "Manual") { + bits.push(0); + bits.push(1); + } + + if (deviceStatus["rotary_switch_state"] === "Automatic") { + bits.push(0); + bits.push(0); + } + + if (deviceStatus["rotary_switch_state"] === "Off") { + bits.push(1); + bits.push(0); + } + } + else { + bits.push(1); + bits.push(1); + } + + //Dverovy kontakt + if (deviceStatus["door_condition"] === "closed") { + bits.push(0); + } + else { + bits.push(1); + } + + //EM + if (deviceStatus["em"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //Teplomer + if (deviceStatus["temperature"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //Batéria + if (deviceStatus["battery"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //Zdroj + if (deviceStatus["power_supply"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //MN + if (deviceStatus["master_node"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //výpadok napätia na fáze + if (deviceStatus["no_voltage"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + if (deviceStatus["twilight_sensor"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + // doplnime do 16 bitov (2 byty) + for (let i = bits.length; i < 16; i++) { + bits.push(0); + } + + // console.log("calculateStateCode - deviceStatus", deviceStatus); + // 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; + } + + + async function sendRvoStatus() { + + if (SETTINGS === undefined) return; + SETTINGS.masterNodeIsResponding ? deviceStatus["master_node"] = "OK" : deviceStatus["master_node"] = "NOK"; + + 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 pinsForRvoStatus(controllerType, hasMainSwitch) { + + let pins = []; + + if (controllerType === "lm") { + pins = [1, 4, 6]; + if (hasMainSwitch === 1) { + pins = [4, 6]; + } + } else if (controllerType === "unipi") { + pins = ["input1_01", "input1_04", "input1_05"]; + if (hasMainSwitch === 1) { + pins = ["input1_01", "input1_04"]; + } + } + + return pins; + } + + + function checkRvoStatus() { + + // 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 + //set RVO state + let status = "OK"; + + for (const [key, value] of Object.entries(deviceStatus)) { + if (["em", "twilight_sensor", "temperature", "master_node"].includes(key) && value === "NOK") status = "NOK"; + } + + if (status === "OK") { + + let pinIndexes = pinsForRvoStatus(controller_type, hasMainSwitch); + + for (const pinIndex of pinIndexes) { + if (previousValues[pinIndex] === 0) { + if ((pinIndex === 6 || pinIndex === 'input1_01' || pinIndex === 'input1_05') && SETTINGS.maintenance_mode) continue; + status = "NOK"; + break; + } + } + } + + // battery status. If value is 1 - battery is NOK + if (previousValues[5] === 1) status = "NOK"; + if (SETTINGS.no_voltage.size > 0) status = "NOK"; + + // console.log("rvo status",status) + return status; + } + + + // we pass array to function in case of rsPort ==> switchLogic([55,3,0,1]) ==> [[55,3,0,1]] + // we pass two values in case of websocket ==> switchLogic("relay1_03",1) ==> ["relay1_03",1] + const switchLogic = (...args) => { + + let values = {}; + let pinIndex, newPinValue, twilight; + + //data from rsPort + if (args.length == 1) { + pinIndex = args[0][1] + 1; + if (pinIndex === 17) pinIndex--; + newPinValue = args[0][3]; + twilight = args[0][2]; + } + //data from websocket + else { + pinIndex = args[0]; + newPinValue = args[1]; + } + + 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; + + //default value + let value = "On"; + if (newPinValue === 0) value = "Off"; + + //Hlavny istic + if (type === "state_of_main_switch" && hasMainSwitch) { + if (newPinValue === 0 && newPinValue !== previousValues[pinIndex]) { + sendNotification("switchLogic", rvoTbName, "main_switch_has_been_turned_off", {}, "", SEND_TO.tb, instance, "state_of_main_switch"); + 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"); + deviceStatus["state_of_main_switch"] = "On"; + } + } + + //Prevadzkovy mod + 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"; + + deviceStatus["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, "power_supply_has_disconnected_input", {}, "", SEND_TO.tb, instance, "power_supply"); + + deviceStatus["power_supply"] = "NOK"; + } + else if (newPinValue === 1 && newPinValue !== previousValues[pinIndex]) { + sendNotification("switchLogic", rvoTbName, "power_supply_works_correctly", {}, "", SEND_TO.tb, instance, "power_supply"); + + deviceStatus["power_supply"] = "OK"; + } + } + + //Bateria - 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"); + + deviceStatus["battery"] = "NOK"; + } + else if (newPinValue === 0 && newPinValue !== previousValues[pinIndex]) { + sendNotification("switchLogic", rvoTbName, "battery_level_is_ok", {}, "", SEND_TO.tb, instance, "battery_level"); + + deviceStatus["battery"] = "OK"; + } + } + + //Dverovy kontakt - pin 6 + //! Ak je rvo s dvoma dverovymi kontaktami, ked pride z evoku signal z input1_05, co bol predytm "state_of_main switch" handlujeme ho teraz ako 'door_condition' + else if (type == "door_condition" || type === "state_of_main_switch") { + newPinValue === 0 ? value = "open" : value = "closed"; + + let door = "door_main"; + if (type === "state_of_main_switch") door = "door_em"; + + if (value === "open") { + if (SETTINGS.maintenance_mode) { + sendNotification("switchLogic", rvoTbName, door + "_open", {}, "", SEND_TO.tb, instance, door); + } else { + sendNotification("switchLogic", rvoTbName, door + "_open_without_permission", {}, "", SEND_TO.tb, instance, door); + + // 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 (value === "closed") { + if (alarmStatus == "ON") turnAlarm("off"); + sendNotification("switchLogic", rvoTbName, door + "_close", {}, "", SEND_TO.tb, instance, door); + } + + deviceStatus[type] = value; + } + + //lux sensor + else if (type == "twilight_sensor") { + //! TODO - to show nok status, if lux value is not changing more then 10 times. + //Daylight is far more than 1000. So most of the day, when it is sunshine comes just value 1000. But lux sensor is not NOK. + //This is not the case in LM. If value from LM is the same 10x, there is 99% possibility, that sensor is NOK. + value = newPinValue; + + if (controller_type === 'lm') { + value = parseFloat(newPinValue + (256 * twilight)); + + 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 && !twilightError) { + twilightError = true; + let value = twilight_sensor_array.shift(); + + newPinValue = 0; + } + else if (set.size !== 1 && twilightError) { + //sendNotification("switchLogic", rvoTbName, 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) { + 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); + } + } + + 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); + } + + deviceStatus["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 (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 }); + + //mame iba 3 istice. vyreportujeme a ohandlujeme liniu na tom istom istici ako paralelna linia (napr linia 1, paralelna s nou je linia 4, key je string "4") + // ak je 7 linii, na 1 istici je linia 1,4,7 + + if (line == 1) { + + const lineOnSameBraker = [4, 7]; + + for (var i = 0; i < lineOnSameBraker.length; i++) { + if (!relaysData.hasOwnProperty(lineOnSameBraker[i])) continue; + + 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; + reportLineStatus(lineOnSameBraker[i]); + + values[type] = value; + const tbname = relaysData[lineOnSameBraker[i]].tbname; + sendTelemetry(values, tbname); + + delete values[type]; + } + + } + else { + const lineOnSameBraker = line + 3 + ""; + + if (relaysData.hasOwnProperty(lineOnSameBraker)) { + 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; + reportLineStatus(line + 3); + + values[type] = value; + const tbname = relaysData[lineOnSameBraker].tbname; + sendTelemetry(values, tbname); + + delete values[type]; + } + } + + } + + if (value == "Off") values["status"] = "NOK"; + deviceStatus["state_of_breaker"][line] = value; + + reportLineStatus(line); + } + else return; + + values[type] = value; + + if (type == "rotary_switch_state") { + if (SETTINGS.maintenance_mode) value = "maintenance"; + value = value.toLowerCase(); + values["power_mode"] = value; + } + + if (newPinValue != previousValues[pinIndex]) previousValues[pinIndex] = newPinValue; + if (Object.keys(values).length > 0 && tbname) sendTelemetry(values, tbname); + } + + + function sendTelemetry(values, tbname, date = Date.now()) { + let dataToTb = { + [tbname]: [ + { + "ts": date, + "values": values + } + ] + }; + + tbHandler.sendToTb(dataToTb, instance); + } + + + function isObject(item) { + return (typeof item === "object" && !Array.isArray(item) && item !== null); + } + +} //end of 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 +// *|input1_01|state_of_main_switch|0|........... +// *|input1_02|rotary_switch_state|0|........... +// *|input1_03|rotary_switch_state|0|........... +// *|intut1_04|power_supply|0|........... +// *|input1_05|door_condition|0|........... +// *|input1_06|state_of_breaker|1|........... +// *|input1_07|state_of_breaker|2|........... +// *|input1_08|state_of_breaker|3|........... +// *|relay1_02|state_of_contactor|1|........... +// *|relay1_03|state_of_contactor|2|........... +// *|relay1_04|state_of_contactor|3|........... +// *|287D8776E0013CE9|temperature|0|........... + + +//! pins_data --> from UNIPI +// { +// 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 } +// } + +//! relays_data +// { +// '0': { +// line: 0, +// tbname: 'KjbN4q7JPZmexgdnz2yKQ98YAWwO0Q3BMX6ERLoV', +// contactor: 1, +// profile: '' +// }, +// '1': { +// line: 1, +// tbname: 'RMgnK93rkoAazbqdQ4yBG95Z1YXGx6pmwBeVEP2O', +// contactor: 0, +// profile: '{"intervals":[{"value":0,"end_time":"20:00","start_time":"13:00"},{"value":1,"end_time":"10:00","start_time":"20:00"},{"value":0,"end_time":"10:20","start_time":"10:00"},{"value":1,"end_time":"10:40","start_time":"10:20"},{"value":0,"end_time":"11:00","start_time":"10:40"},{"value":1,"end_time":"11:30","start_time":"11:00"},{"value":0,"end_time":"11:50","start_time":"11:30"},{"value":1,"end_time":"13:00","start_time":"11:50"}],"astro_clock":false,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' +// }, +// '2': { +// line: 2, +// tbname: 'dlE1VQjYrNx9gZRmb38gG08oLBO4qaAk2M6JPnG7', +// contactor: 0, +// profile: '{"intervals":[{"value":0,"end_time":"20:00","start_time":"13:00"},{"value":1,"end_time":"10:00","start_time":"20:00"},{"value":0,"end_time":"10:20","start_time":"10:00"},{"value":1,"end_time":"10:40","start_time":"10:20"},{"value":0,"end_time":"11:00","start_time":"10:40"},{"value":1,"end_time":"11:30","start_time":"11:00"},{"value":0,"end_time":"11:50","start_time":"11:30"},{"value":1,"end_time":"13:00","start_time":"11:50"}],"astro_clock":false,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' +// }, +// '3': { +// line: 3, +// tbname: 'vnmG4kJxaXWNBgMQq0D7Aj5e9oZzOAlr6LdR3w2V', +// contactor: 0, +// profile: '{"intervals":[{"value":0,"end_time":"20:30","start_time":"13:00"},{"value":1,"end_time":"00:10","start_time":"20:30"},{"value":0,"end_time":"13:00","start_time":"05:40"},{"value":1,"end_time":"05:40","start_time":"00:10"}],"astro_clock":true,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' +// } +// } + + + + + +// { +// "jbN4q7JPZmexgdnz2yKbWGDYAWwO0Q3BMX6ERLoV": [ +// { +// "ts": 1700409326353, +// "values": { +// "_event": { +// "type": "notice", +// "status": "new", +// "source": { +// "func": "rsPort.open()", +// "component": "1700343402190", +// "component_name": "DIDO_Controller", +// "edge": "jbN4q7JPZmexgdnz2yKbWGDYAWwO0Q3BMX6ERLoV" +// }, +// "message": "al_shariff_10.0.0.38: FLOW has been started ", +// "message_data": "" +// } +// } +// } +// ] +// } diff --git a/RVO37/flow/helper/DataToTbHandler.js b/RVO37/flow/helper/DataToTbHandler.js new file mode 100755 index 0000000..716ef7b --- /dev/null +++ b/RVO37/flow/helper/DataToTbHandler.js @@ -0,0 +1,187 @@ +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; + this.itIsNodeReadout = false; + this.sender = ""; + + // if attribute change difference is less than limit value, we do not send to tb. + this.attributeChangeLimit = { + temperature: 0.5, + Phase_1_voltage: 2, + Phase_2_voltage: 2, + Phase_3_voltage: 2, + Phase_1_current: 0.1, + Phase_2_current: 0.1, + Phase_3_current: 0.1, + Phase_1_power: 2, + Phase_2_power: 2, + Phase_3_power: 2, + total_power: 2, + total_energy: 1, + Phase_1_pow_factor: 0.1, + Phase_2_pow_factor: 0.1, + Phase_3_pow_factor: 0.1, + power_factor: 0.1, + lifetime: 2, + voltage: 2, + power: 2, + frequency: 3, + energy: 0.1, + current: 2, + inclination_x: 10, + inclination_y: 10, + inclination_z: 10 + }; + + } + + dump() { + console.log("----------------------------"); + console.log("previousValues", this.previousValues); + console.log("----------------------------"); + } + + setSender(sender) { + this.sender = sender; + } + + isEmptyObject(obj) { + for (var _ in obj) { + return false; + } + return true; + } + + + sendToTb(data, instance) { + + //not to modify data object, we do deep copy: + let dataCopy = JSON.parse(JSON.stringify(data)); + + let keys = Object.keys(dataCopy); + + if (keys.length == 0) { + if (this.debug) console.log("sendToTb received empty object", dataCopy); + return; + } + + let tbname = keys[0]; + let ts; + + let arrayOfValues = dataCopy[tbname]; + let arrayOfValuesToSend = []; + + for (let i = 0; i < arrayOfValues.length; i++) { + + ts = arrayOfValues[i].ts; + let values = this.prepareValuesForTb(tbname, ts, arrayOfValues[i].values); + + if (!this.isEmptyObject(values)) { + arrayOfValuesToSend.push({ ts: ts, values: values }); + } + + } + + if (arrayOfValuesToSend.length == 0) { + //if(this.debug) console.log("data not sent - empty array"); + return; + } + + this.messageCounter++; + + let dataToTbModified = { + [tbname]: arrayOfValuesToSend + } + + //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); + instance.send(this.index, dataToTbModified); + } + + + getDiffTimestamp(key) { + //TODO set different value for given key!!! + //if(key == "status") this.timeToHoldTbValue = 2*60*60;//2h + return this.timeToHoldTbValue * 1000; + } + + + prepareValuesForTb(tbname, timestamp, values) { + + let keys = Object.keys(values); + + if (keys.includes("lifetime")) this.itIsNodeReadout = true; + + if (!this.previousValues.hasOwnProperty(tbname)) { + this.previousValues[tbname] = {}; + } + + //if(this.debug) console.log("prepareValuesForTb", tbname, timestamp, values); + + for (let i = 0; i < keys.length; i++) { + + let key = keys[i]; + let value = values[key]; + + if (!this.previousValues[tbname].hasOwnProperty(key)) { + this.previousValues[tbname][key] = { ts: timestamp, value: value }; + continue; + } + + // attributeData ==> {voltage: {ts:333333, value:5}} + let attributeData = this.previousValues[tbname][key]; + let attributeToChange = false; + if (key in this.attributeChangeLimit) attributeToChange = true; + let limit = this.attributeChangeLimit[key]; + let timestampDiffToRemoveKey; + + //this will ensure "node statecode" will be sent just once an hour + if (this.itIsNodeReadout && key === "statecode") { + attributeData.value = value; + this.itIsNodeReadout = false; + timestampDiffToRemoveKey = 1 * 60 * 60 * 1000; // 1 hour + } + + if (key === "twilight_sensor" && value > 100) { + attributeData.value = value; + } + + //if edge, master or node version do not change, send just once a day: + if (["edge_fw_version", "master_node_version", "fw_version"].includes(key)) { + timestampDiffToRemoveKey = 24 * 60 * 60 * 1000; + } + + if (attributeData.value === value || attributeToChange && Math.abs(attributeData.value - value) < limit) { + + let diff = timestamp - attributeData.ts; + if (!timestampDiffToRemoveKey) timestampDiffToRemoveKey = this.getDiffTimestamp(key); + + if (diff > timestampDiffToRemoveKey) { + attributeData.ts = Date.now(); + //if(this.debug) console.log(this.sender + ": update ts for key", key, "diff is", diff, "messageCounter", this.messageCounter); + } + else { + delete values[key]; + //if(this.debug) console.log(this.sender + ": delete key", key, "diff is", diff, "messageCounter", this.messageCounter, timestampDiffToRemoveKey); + } + } + else { + attributeData.value = value; + attributeData.ts = timestamp; + } + + } + + return values; + } +} + +module.exports = DataToTbHandler; + diff --git a/RVO37/flow/helper/ErrorToServiceHandler.js b/RVO37/flow/helper/ErrorToServiceHandler.js new file mode 100755 index 0000000..2b27c32 --- /dev/null +++ b/RVO37/flow/helper/ErrorToServiceHandler.js @@ -0,0 +1,91 @@ +const { MD5 } = require('./md5.js'); +const { networkInterfaces } = require('os'); + +class ErrorToServiceHandler { + constructor() { + this.previousValues = {}; + + this.project_id = undefined; + + const nets = networkInterfaces(); + this.ipAddresses = {}; + + for (const name of Object.keys(nets)) { + for (const net of nets[name]) { + // Skip over non-IPv4 and internal (i.e. 127.0.0.1) addresses + if (net.family === 'IPv4' && !net.internal) { + if (!this.ipAddresses[name]) { + this.ipAddresses[name] = []; + } + this.ipAddresses[name].push(net.address); + } + } + } + } + + setProjectId(project_id) { + this.project_id = project_id; + } + + processMessage(message, seconds) { + if (Array.isArray(message)) message = message.join(', '); + + let key = MD5(message); + let ts = Date.now(); + + //keep in memory - default value is 1h + if (seconds === undefined) seconds = 60 * 60; + + if (!this.previousValues.hasOwnProperty(key)) { + this.previousValues[key] = { ts: ts, duration: seconds }; + } + + let diff = (ts - this.previousValues[key].ts); + if (diff < this.previousValues[key].duration * 1000) return false; + + this.previousValues[key].ts = ts; + + return message; + } + + sendMessageToService(message, seconds, message_type) { + + // if error occures too early FLOW.GLOBALS.settings.project_id is still undefined + if (this.project_id === undefined) { + console.log("ErrorToServiceHandler.js: no project_id"); + return; + } + + let f = this.processMessage(message, seconds); + if (f === false) return; + + if (message_type === undefined) message_type = "error_message"; + + let toService = { + id: this.project_id, + ipAddresses: this.ipAddresses + }; + + //js_error || error_message + toService[message_type] = message; + + console.log("ErrorToServiceHandler------------------------>send to service", toService); + + RESTBuilder.make(function(builder) { + builder.method('POST'); + builder.post(toService); + builder.url('http://192.168.252.2:8004/sentmessage'); + + builder.callback(function(err, response, output) { + console.log("process.on error send", err, response, output, toService); + }); + }); + + } +} + +const errorHandler = new ErrorToServiceHandler(); + + +module.exports = errorHandler; +//module.exports = ErrorToServiceHandler; diff --git a/RVO37/flow/helper/db_helper.js b/RVO37/flow/helper/db_helper.js new file mode 100755 index 0000000..40e796c --- /dev/null +++ b/RVO37/flow/helper/db_helper.js @@ -0,0 +1,44 @@ +function promisifyBuilder(builder) +{ + return new Promise((resolve, reject) => { + + try{ + + builder.callback(function(err, response) { + + if(err != null) reject(err); + resolve(response); + }); + + } catch (error) { + reject(error); + } + }) +} + +function makeMapFromDbResult(response, ...keys) +{ + let s = "-"; + let data = {}; + + for(let i = 0; i < response.length; i++) + { + let record = response[i]; + + let k = []; + for(let j = 0; j < keys.length; j++) + { + k.push( record[keys[j]] ); + } + + let key = k.join(s); + data[ key ] = record; + } + + return data; +} + +module.exports = { + promisifyBuilder, + makeMapFromDbResult + } \ No newline at end of file diff --git a/RVO37/flow/helper/logger.js b/RVO37/flow/helper/logger.js new file mode 100755 index 0000000..2585639 --- /dev/null +++ b/RVO37/flow/helper/logger.js @@ -0,0 +1,30 @@ +//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/RVO37/flow/helper/md5.js b/RVO37/flow/helper/md5.js new file mode 100755 index 0000000..d3b0480 --- /dev/null +++ b/RVO37/flow/helper/md5.js @@ -0,0 +1,5 @@ +function MD5(d){var r = M(V(Y(X(d),8*d.length)));return r.toLowerCase()};function M(d){for(var _,m="0123456789ABCDEF",f="",r=0;r>>4&15)+m.charAt(15&_);return f}function X(d){for(var _=Array(d.length>>2),m=0;m<_.length;m++)_[m]=0;for(m=0;m<8*d.length;m+=8)_[m>>5]|=(255&d.charCodeAt(m/8))<>5]>>>m%32&255);return _}function Y(d,_){d[_>>5]|=128<<_%32,d[14+(_+64>>>9<<4)]=_;for(var m=1732584193,f=-271733879,r=-1732584194,i=271733878,n=0;n>16)+(_>>16)+(m>>16)<<16|65535&m}function bit_rol(d,_){return d<<_|d>>>32-_} + +module.exports = { + MD5 +} \ No newline at end of file diff --git a/RVO37/flow/helper/notification_reporter.js b/RVO37/flow/helper/notification_reporter.js new file mode 100755 index 0000000..839c12c --- /dev/null +++ b/RVO37/flow/helper/notification_reporter.js @@ -0,0 +1,121 @@ +//key is device, value = message {} +let sentValues = {}; +let notificationsData = null; +let rvoName; + +//sendNotification("CMD Manager: process cmd", SETTINGS.rvoTbName, "dimming_profile_was_successfully_received_by_node", { node: node }, "", SEND_TO.tb, instance); + +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 +}; + +function getKey(map, val) { + return Object.keys(map).findItem(key => map[key] === val); +} + +//https://stackoverflow.com/questions/41117799/string-interpolation-on-variable +var template = (tpl, args) => tpl.replace(/\${(\w+)}/g, (_, v) => args[v]); + + +function initNotification() { + notificationsData = FLOW.GLOBALS.notificationsData; + rvoName = FLOW.GLOBALS.settings.rvo_name; +} + + +function sendNotification(func, device, key, params, extra, tb_output, instance, saveKey) { + + let storeToSendValues = true; + if (saveKey == undefined) storeToSendValues = false; + + let weight = ""; + let message = {}; + + let notification = notificationsData[key]; + + if (notification) { + weight = notification.weight.toLowerCase(); + + Object.keys(notification).forEach(item => { + if (["en", "sk", "de", "cz", "it", "es"].includes(item)) { + message[item] = rvoName + ": " + template(notification[item], params); + } + }) + } + else { + //console.error("sendNotification: Notifications: undefined key", key, func, notificationsData); + console.error("sendNotification: Notifications: undefined key", key, func); + return false; + } + + //detect invalid err weight + if (getKey(ERRWEIGHT, weight) == undefined) { + console.error("sendNotification: Notifications: undefined weight", weight, key, func); + return false; + } + + if (sentValues.hasOwnProperty(saveKey)) { + if (JSON.stringify(sentValues[saveKey]) == JSON.stringify(message)) { + return false; + } + } + + if (sentValues[saveKey] == undefined) { + if (storeToSendValues) { + //do not send - flow is was started + sentValues[saveKey] = message; + return false; + } + } + + if (storeToSendValues) sentValues[saveKey] = message; + + let content = { + "type": weight, + "status": "new", + "source": { + "func": func, + "component": instance.id, + "component_name": instance.name, + "edge": device + }, + "message": message, + "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 + + return true; + +} + +module.exports = { + sendNotification, + ERRWEIGHT, + initNotification +} + diff --git a/RVO37/flow/helper/register.js b/RVO37/flow/helper/register.js new file mode 100755 index 0000000..fc1d008 --- /dev/null +++ b/RVO37/flow/helper/register.js @@ -0,0 +1,144 @@ +/* +0 - cislo registra / prikaz +1 - recepient - 0 = master, 1 = slave (slave je automaticky group a broadcast) +2 - r/rw - read/write +3- register name - nazov registra / prikazu (len pre info - zobrazenie v aplikacii) + +4,5,6,7, - jednotlive byte-y - nazov byte-u +4-7 - RES. a prazdny string "" sa nezobrazia!!! +*/ + +//124 zaznamov +const registers = [ + ["0","1","R","Status","","",""], + ["1","1","RW","Dimming","R-Channel ","G-Channel","B-Channel ","W - Channel"], + ["2","1","R","Device types","","",".",""], + ["3","1","RW","Group addresses 1-4","Groups Add. 4","Groups Add. 3","Groups Add. 2","Groups Add. 1"], + ["4","1","RW","Group addresses 5-8","Groups Add. 8","Groups Add. 7","Groups Add. 6","Groups Add. 5"], + ["5","1","RW","Serial number (MAC)","","","",""], + ["6","1","RW","Time of dusk","HH","MM","SS","EXTRA"], + ["7","1","RW","Time of dawn","HH","MM","SS","EXTRA"], + ["8","1","RW","Time Schedule settings","TBD","TBD","Movement sensor","Time Schedule"], + ["9","1","RW","TS1 Time point 1","HH","MM","SS","Ext. Device"], + ["10","1","RW","TS1 Time point 1 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["11","1","RW","TS1 Time point 2","HH","MM","SS","Ext. Device"], + ["12","1","RW","TS1 Time point 2 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["13","1","RW","TS1 Time point 3","HH","MM","SS","Ext. Device"], + ["14","1","RW","TS1 Time point 3 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["15","1","RW","TS1 Time point 4","HH","MM","SS","Ext. Device"], + ["16","1","RW","TS1 Time point 4 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["17","1","RW","TS1 Time point 5","HH","MM","SS","Ext. Device"], + ["18","1","RW","TS1 Time point 5 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["19","1","RW","TS1 Time point 6","HH","MM","SS","Ext. Device"], + ["20","1","RW","TS1 Time point 6 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["21","1","RW","TS1 Time point 7","HH","MM","SS","Ext. Device"], + ["22","1","RW","TS1 Time point 7 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["23","1","RW","TS1 Time point 8","HH","MM","SS","Ext. Device"], + ["24","1","RW","TS1 Time point 8 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["25","1","RW","TS1 Time point 9","HH","MM","SS","Ext. Device"], + ["26","1","RW","TS1 Time point 9 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["27","1","RW","TS1 Time point 10","HH","MM","SS","Ext. Device"], + ["28","1","RW","TS1 Time point 10 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["29","1","RW","TS1 Time point 11","HH","MM","SS","Ext. Device"], + ["30","1","RW","TS1 Time point 11 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["31","1","RW","TS1 Time point 12","HH","MM","SS","Ext. Device"], + ["32","1","RW","TS1 Time point 12 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["33","1","RW","TS1 Time point 13","HH","MM","SS","Ext. Device"], + ["34","1","RW","TS1 Time point 13 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["35","1","RW","TS1 Time point 14","HH","MM","SS","Ext. Device"], + ["36","1","RW","TS1 Time point 14 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["37","1","RW","TS1 Time point 15","HH","MM","SS","Ext. Device"], + ["38","1","RW","TS1 Time point 15 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["39","1","RW","TS1 Time point 16","HH","MM","SS","Ext. Device"], + ["40","1","RW","TS1 Time point 16 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["41","1","RW","TS2 Time point 1","HH","MM","SS","Ext. Device"], + ["42","1","RW","TS2 Time point 1 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["43","1","RW","TS2 Time point 2","HH","MM","SS","Ext. Device"], + ["44","1","RW","TS2 Time point 2 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["45","1","RW","TS2 Time point 3","HH","MM","SS","Ext. Device"], + ["46","1","RW","TS2 Time point 3 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["47","1","RW","TS2 Time point 4","HH","MM","SS","Ext. Device"], + ["48","1","RW","TS2 Time point 4 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["49","1","RW","TS2 Time point 5","HH","MM","SS","Ext. Device"], + ["50","1","RW","TS2 Time point 5 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["51","1","RW","TS2 Time point 6","HH","MM","SS","Ext. Device"], + ["52","1","RW","TS2 Time point 6 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["53","1","RW","TS2 Time point 7","HH","MM","SS","Ext. Device"], + ["54","1","RW","TS2 Time point 7 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["55","1","RW","TS2 Time point 8","HH","MM","SS","Ext. Device"], + ["56","1","RW","TS2 Time point 8 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["57","1","RW","TS2 Time point 9","HH","MM","SS","Ext. Device"], + ["58","1","RW","TS2 Time point 9 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["59","1","RW","TS2 Time point 10","HH","MM","SS","Ext. Device"], + ["60","1","RW","TS2 Time point 10 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["61","1","RW","TS2 Time point 11","HH","MM","SS","Ext. Device"], + ["62","1","RW","TS2 Time point 11 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["63","1","RW","TS2 Time point 12","HH","MM","SS","Ext. Device"], + ["64","1","RW","TS2 Time point 12 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["65","1","RW","TS2 Time point 13","HH","MM","SS","Ext. Device"], + ["66","1","RW","TS2 Time point 13 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["67","1","RW","TS2 Time point 14","HH","MM","SS","Ext. Device"], + ["68","1","RW","TS2 Time point 14 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["69","1","RW","TS2 Time point 15","HH","MM","SS","Ext. Device"], + ["70","1","RW","TS2 Time point 15 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["71","1","RW","TS2 Time point 16","HH","MM","SS","Ext. Device"], + ["72","1","RW","TS2 Time point 16 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["73","1","RW","Power meter status","TBD","","",""], + ["74","1","R","Input Voltage","","","",""], + ["75","1","R","Input Current","","","",""], + ["76","1","R","Input Power","","","",""], + ["77","1","R","Cos phi","","","",""], + ["78","1","R","Frequency","","","",""], + ["79","1","RW","Energy","","","",""], + ["80","1","RW","Lifetime","","","",""], + ["81","1","RW","Power on cycles (input)","","","",""], + ["82","1","RW","Power on cycles (relay)","","","",""], + ["83","1","R","Time since last power on","","","",""], + ["84","1","R","Accelerometer data","","","",""], + ["85","1","RW","GPS latitude","pos/neg","deg","min ","sec"], + ["86","1","RW","GPS longitude","pos/neg","deg","min ","sec"], + ["87","1","RW","Actual time","HH","MM","SS","RES."], + ["88","1","RW","Actual date","Day of week","Day","Month","Year"], + ["89","1","R","Production data 1","","","",""], + ["90","1","R","Production data 2","","","",""], + ["91","1","RW","Network ID","NID3","NID2","NID1","NID0"], + ["95","1","RW","Actual Lux level from cabinet","RES.","RES.","HB","LB"], + ["96","1","RW","Threshold lux level","Dusk HB","Dusk LB","Dawn HB","Dawn LB"], + ["97","1","RW","Adjust period","Dusk HB","Dusk LB","Dawn HB","Dawn LB"], + ["98","1","RW","Offset","RES.","RES.","Dusk","Dawn"], + ["99","1","RW","CCT min/max range","max-H","max-L","min-H","min-L"], + ["100","1","RW","DALI interface","Cmd ID","Add","Cmd","Resp"], + ["101","1","RW","Module FW ver","v1","v2","v3","v4"], + ["102","1","RW","Module MAC-H","unused","unused","M1","M2"], + ["103","1","RW","Module MAC-L","M3","M4","M5","M6"], + ["122","1","R","FW update status/control register","Byte3","Byte2","Byte1","Byte0"], + ["123","1","R","FW update - data index","Byte3","Byte2","Byte1","Byte0"], + ["124","1","R","FW update - data","Byte3","Byte2","Byte1","Byte0"], + ["0","0","R","Status","","","",""], + ["1","0","RW","Control register","RES.","RES.","RES.","init mode enable"], + ["2","0","R","Device types","","","",""], + ["3","0","R","Serial number (MAC)","","","",""], + ["4","0","R","Production data 1","","","",""], + ["5","0","R","Production data 2","","","",""], + ["6","0","RW","Network ID","NID3","NID2","NID1","NID0"], + ["7","0","RW","RS232 settings","param.","param.","Baudrate H","Baudrate L"], + ["8","0","R","Accelerometer data","","","",""], + ["9","0","RW","Module FW ver","v1","v2","v3","v4"], + ["10","0","RW","Module MAC-H","unused","unused","M1","M2"], + ["11","0","RW","Module MAC-L","M3","M4","M5","M6"], + ["32","0","RW","FW update status/control register","Byte3","Byte2","Byte1","Byte0"], + ["33","0","RW","FW update - data index","Byte3","Byte2","Byte1","Byte0"], + ["34","0","RW","FW update - data","Byte3","Byte2","Byte1","Byte0"], + ["125","0","RW","Debug Register","Byte3","Byte2","Byte1","Byte0"], + ["126","0","RW","Network Control Register","Byte3","Byte2","Byte1","Byte0"], + ["127","0","R","Network Status Register","Byte3","Byte2","Byte1","Byte0"], + ["128","0","RW","Node XX Serial Number Register","SER3","SER2","SER1","SER0"], + ["256","0","R","Node XX Network Status Register","","","",""] +]; + +let register = {}; + +module.exports = { + registers, + register +} \ No newline at end of file diff --git a/RVO37/flow/helper/serialport_helper.js b/RVO37/flow/helper/serialport_helper.js new file mode 100755 index 0000000..7f5920d --- /dev/null +++ b/RVO37/flow/helper/serialport_helper.js @@ -0,0 +1,99 @@ +const { exec } = require('child_process'); + +function openPort(port) { + return new Promise((resolve, reject) => { + + var callbackError = function(err) { + port.removeListener('error', callbackError); + port.removeListener('open', callbackError); + + reject(err.message); + }; + + var callbackOpen = function(data) { + port.removeListener('error', callbackError); + port.removeListener('open', callbackOpen); + + resolve("port open: ok"); + }; + + port.on('error', callbackError); + port.on('open', callbackOpen); + + port.open(); + + }) +} + +function runSyncExec(command) { + return new Promise((resolve, reject) => { + + exec(command, (error, stdout, stderr) => { + if (error == null) resolve(stdout); + reject(error); + }); + + }) +} + +async function writeData(port, data, readbytes, timeout) { + return new Promise((resolve, reject) => { + + // 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) { + + port.write(Buffer.from(data), function(err) { + if (err) { + reject(err.message); + } + }); + + 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 +} diff --git a/RVO37/flow/helper/suncalc.js b/RVO37/flow/helper/suncalc.js new file mode 100755 index 0000000..c9ca56d --- /dev/null +++ b/RVO37/flow/helper/suncalc.js @@ -0,0 +1,317 @@ +/* + (c) 2011-2015, Vladimir Agafonkin + SunCalc is a JavaScript library for calculating sun/moon position and light phases. + https://github.com/mourner/suncalc +*/ + +(function () { 'use strict'; + +// shortcuts for easier to read formulas + +var PI = Math.PI, + sin = Math.sin, + cos = Math.cos, + tan = Math.tan, + asin = Math.asin, + atan = Math.atan2, + acos = Math.acos, + rad = PI / 180; + +// sun calculations are based on http://aa.quae.nl/en/reken/zonpositie.html formulas + + +// date/time constants and conversions + +var dayMs = 1000 * 60 * 60 * 24, + J1970 = 2440588, + J2000 = 2451545; + +function toJulian(date) { return date.valueOf() / dayMs - 0.5 + J1970; } +function fromJulian(j) { return new Date((j + 0.5 - J1970) * dayMs); } +function toDays(date) { return toJulian(date) - J2000; } + + +// general calculations for position + +var e = rad * 23.4397; // obliquity of the Earth + +function rightAscension(l, b) { return atan(sin(l) * cos(e) - tan(b) * sin(e), cos(l)); } +function declination(l, b) { return asin(sin(b) * cos(e) + cos(b) * sin(e) * sin(l)); } + +function azimuth(H, phi, dec) { return atan(sin(H), cos(H) * sin(phi) - tan(dec) * cos(phi)); } +function altitude(H, phi, dec) { return asin(sin(phi) * sin(dec) + cos(phi) * cos(dec) * cos(H)); } + +function siderealTime(d, lw) { return rad * (280.16 + 360.9856235 * d) - lw; } + +function astroRefraction(h) { + if (h < 0) // the following formula works for positive altitudes only. + h = 0; // if h = -0.08901179 a div/0 would occur. + + // formula 16.4 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + // 1.02 / tan(h + 10.26 / (h + 5.10)) h in degrees, result in arc minutes -> converted to rad: + return 0.0002967 / Math.tan(h + 0.00312536 / (h + 0.08901179)); +} + +// general sun calculations + +function solarMeanAnomaly(d) { return rad * (357.5291 + 0.98560028 * d); } + +function eclipticLongitude(M) { + + var C = rad * (1.9148 * sin(M) + 0.02 * sin(2 * M) + 0.0003 * sin(3 * M)), // equation of center + P = rad * 102.9372; // perihelion of the Earth + + return M + C + P + PI; +} + +function sunCoords(d) { + + var M = solarMeanAnomaly(d), + L = eclipticLongitude(M); + + return { + dec: declination(L, 0), + ra: rightAscension(L, 0) + }; +} + + +var SunCalc = {}; + + +// calculates sun position for a given date and latitude/longitude + +SunCalc.getPosition = function (date, lat, lng) { + + var lw = rad * -lng, + phi = rad * lat, + d = toDays(date), + + c = sunCoords(d), + H = siderealTime(d, lw) - c.ra; + + return { + azimuth: azimuth(H, phi, c.dec), + altitude: altitude(H, phi, c.dec) + }; +}; + + +// sun times configuration (angle, morning name, evening name) + +var times = SunCalc.times = [ + [-0.833, 'sunrise', 'sunset' ], + [ -0.3, 'sunriseEnd', 'sunsetStart' ], + [ -6, 'dawn', 'dusk' ], + [ -12, 'nauticalDawn', 'nauticalDusk'], + [ -18, 'nightEnd', 'night' ], + [ 6, 'goldenHourEnd', 'goldenHour' ] +]; + +// adds a custom time to the times config + +SunCalc.addTime = function (angle, riseName, setName) { + times.push([angle, riseName, setName]); +}; + + +// calculations for sun times + +var J0 = 0.0009; + +function julianCycle(d, lw) { return Math.round(d - J0 - lw / (2 * PI)); } + +function approxTransit(Ht, lw, n) { return J0 + (Ht + lw) / (2 * PI) + n; } +function solarTransitJ(ds, M, L) { return J2000 + ds + 0.0053 * sin(M) - 0.0069 * sin(2 * L); } + +function hourAngle(h, phi, d) { return acos((sin(h) - sin(phi) * sin(d)) / (cos(phi) * cos(d))); } +function observerAngle(height) { return -2.076 * Math.sqrt(height) / 60; } + +// returns set time for the given sun altitude +function getSetJ(h, lw, phi, dec, n, M, L) { + + var w = hourAngle(h, phi, dec), + a = approxTransit(w, lw, n); + return solarTransitJ(a, M, L); +} + + +// calculates sun times for a given date, latitude/longitude, and, optionally, +// the observer height (in meters) relative to the horizon + +SunCalc.getTimes = function (date, lat, lng, height) { + + height = height || 0; + + var lw = rad * -lng, + phi = rad * lat, + + dh = observerAngle(height), + + d = toDays(date), + n = julianCycle(d, lw), + ds = approxTransit(0, lw, n), + + M = solarMeanAnomaly(ds), + L = eclipticLongitude(M), + dec = declination(L, 0), + + Jnoon = solarTransitJ(ds, M, L), + + i, len, time, h0, Jset, Jrise; + + + var result = { + solarNoon: fromJulian(Jnoon), + nadir: fromJulian(Jnoon - 0.5) + }; + + for (i = 0, len = times.length; i < len; i += 1) { + time = times[i]; + h0 = (time[0] + dh) * rad; + + Jset = getSetJ(h0, lw, phi, dec, n, M, L); + Jrise = Jnoon - (Jset - Jnoon); + + result[time[1]] = fromJulian(Jrise); + result[time[2]] = fromJulian(Jset); + } + + return result; +}; + + +// moon calculations, based on http://aa.quae.nl/en/reken/hemelpositie.html formulas + +function moonCoords(d) { // geocentric ecliptic coordinates of the moon + + var L = rad * (218.316 + 13.176396 * d), // ecliptic longitude + M = rad * (134.963 + 13.064993 * d), // mean anomaly + F = rad * (93.272 + 13.229350 * d), // mean distance + + l = L + rad * 6.289 * sin(M), // longitude + b = rad * 5.128 * sin(F), // latitude + dt = 385001 - 20905 * cos(M); // distance to the moon in km + + return { + ra: rightAscension(l, b), + dec: declination(l, b), + dist: dt + }; +} + +SunCalc.getMoonPosition = function (date, lat, lng) { + + var lw = rad * -lng, + phi = rad * lat, + d = toDays(date), + + c = moonCoords(d), + H = siderealTime(d, lw) - c.ra, + h = altitude(H, phi, c.dec), + // formula 14.1 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + pa = atan(sin(H), tan(phi) * cos(c.dec) - sin(c.dec) * cos(H)); + + h = h + astroRefraction(h); // altitude correction for refraction + + return { + azimuth: azimuth(H, phi, c.dec), + altitude: h, + distance: c.dist, + parallacticAngle: pa + }; +}; + + +// calculations for illumination parameters of the moon, +// based on http://idlastro.gsfc.nasa.gov/ftp/pro/astro/mphase.pro formulas and +// Chapter 48 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + +SunCalc.getMoonIllumination = function (date) { + + var d = toDays(date || new Date()), + s = sunCoords(d), + m = moonCoords(d), + + sdist = 149598000, // distance from Earth to Sun in km + + phi = acos(sin(s.dec) * sin(m.dec) + cos(s.dec) * cos(m.dec) * cos(s.ra - m.ra)), + inc = atan(sdist * sin(phi), m.dist - sdist * cos(phi)), + angle = atan(cos(s.dec) * sin(s.ra - m.ra), sin(s.dec) * cos(m.dec) - + cos(s.dec) * sin(m.dec) * cos(s.ra - m.ra)); + + return { + fraction: (1 + cos(inc)) / 2, + phase: 0.5 + 0.5 * inc * (angle < 0 ? -1 : 1) / Math.PI, + angle: angle + }; +}; + + +function hoursLater(date, h) { + return new Date(date.valueOf() + h * dayMs / 24); +} + +// calculations for moon rise/set times are based on http://www.stargazing.net/kepler/moonrise.html article + +SunCalc.getMoonTimes = function (date, lat, lng, inUTC) { + var t = new Date(date); + if (inUTC) t.setUTCHours(0, 0, 0, 0); + else t.setHours(0, 0, 0, 0); + + var hc = 0.133 * rad, + h0 = SunCalc.getMoonPosition(t, lat, lng).altitude - hc, + h1, h2, rise, set, a, b, xe, ye, d, roots, x1, x2, dx; + + // go in 2-hour chunks, each time seeing if a 3-point quadratic curve crosses zero (which means rise or set) + for (var i = 1; i <= 24; i += 2) { + h1 = SunCalc.getMoonPosition(hoursLater(t, i), lat, lng).altitude - hc; + h2 = SunCalc.getMoonPosition(hoursLater(t, i + 1), lat, lng).altitude - hc; + + a = (h0 + h2) / 2 - h1; + b = (h2 - h0) / 2; + xe = -b / (2 * a); + ye = (a * xe + b) * xe + h1; + d = b * b - 4 * a * h1; + roots = 0; + + if (d >= 0) { + dx = Math.sqrt(d) / (Math.abs(a) * 2); + x1 = xe - dx; + x2 = xe + dx; + if (Math.abs(x1) <= 1) roots++; + if (Math.abs(x2) <= 1) roots++; + if (x1 < -1) x1 = x2; + } + + if (roots === 1) { + if (h0 < 0) rise = i + x1; + else set = i + x1; + + } else if (roots === 2) { + rise = i + (ye < 0 ? x2 : x1); + set = i + (ye < 0 ? x1 : x2); + } + + if (rise && set) break; + + h0 = h2; + } + + var result = {}; + + if (rise) result.rise = hoursLater(t, rise); + if (set) result.set = hoursLater(t, set); + + if (!rise && !set) result[ye > 0 ? 'alwaysUp' : 'alwaysDown'] = true; + + return result; +}; + + +// export as Node module / AMD module / browser variable +if (typeof exports === 'object' && typeof module !== 'undefined') module.exports = SunCalc; +else if (typeof define === 'function' && define.amd) define(SunCalc); +else window.SunCalc = SunCalc; + +}()); diff --git a/RVO37/flow/helper/utils.js b/RVO37/flow/helper/utils.js new file mode 100755 index 0000000..dbffe45 --- /dev/null +++ b/RVO37/flow/helper/utils.js @@ -0,0 +1,161 @@ +const fs = require('fs').promises; + +function bytesToInt(bytes, numberOfBytes) { + let buffer = []; + if (Array.isArray(bytes)) { + buffer = bytes.slice(0); + if (numberOfBytes != undefined) { + buffer = bytes.slice(bytes.length - numberOfBytes); + } + } + else buffer.push(bytes); + + let result = 0; + for (let i = 0; i < buffer.length; i++) { + result = (result << 8) | buffer[i]; + } + + return result >>> 0; //ensure it's an unsigned 32-bit number +} + +function resizeArray(arr, newSize, defaultValue) { + while (newSize > arr.length) + arr.push(defaultValue); + arr.length = newSize; +} + +longToByteArray = function(/*long*/long) { + // we want to represent the input as a 8-bytes array + var byteArray = [0, 0, 0, 0, 0, 0, 0, 0]; + + for (var index = 0; index < byteArray.length; index++) { + var byte = long & 0xff; + byteArray[index] = byte; + long = (long - byte) / 256; + } + + return byteArray; +}; + +function addDays(date, days) { + var result = new Date(date); + result.setDate(result.getDate() + days); + return result; +} + +/* +sleep(2000).then(() => { + // Do something after the sleep! + + +}); +*/ + +function sleep(time) { + return new Promise((resolve) => setTimeout(resolve, time)); +} + +function isEmptyObject(obj) { + for (var name in obj) { + return false; + } + return true; +} + +function emptyJsObject(jsObject) { + Object.keys(jsObject).forEach(key => delete jsObject[key]); +} + +function convertUTCDateToLocalDate(date) { + var newDate = new Date(date); + newDate.setMinutes(date.getMinutes() + date.getTimezoneOffset()); + return newDate; +} + +function addZeroBefore(n) { + return (n < 10 ? '0' : '') + n; +} + + +/** + * Asynchronously writes data to a file. + * + * @param {string} filePath The path to the file. + * @param {string} data The data to write to the file. + * @param {boolean} [append=false] If true, appends the data to the file. If false, it overwrites the file. + */ +async function writeToFile(filePath, data, append = false) { + if (typeof data !== 'string') data = JSON.stringify(data, null, 2); + try { + if (append) { + // Append the data to the end of the file. This is the simplest way to append. + await fs.appendFile(filePath, data, 'utf8'); + console.log(`Successfully appended data to ${filePath} using fs.appendFile.`); + } else { + // Overwrite the file with the new data. + await fs.writeFile(filePath, data, 'utf8'); + console.log(`Successfully wrote (overwrote) data to ${filePath} using fs.writeFile.`); + } + } catch (error) { + console.error(`Error writing to file ${filePath}:`, error); + } +} + + + /** + * Checks if an item is present in an array and adds it if it's not. + * * @param {Array} arr The array to check. + * @param {*} item The item to add. + * @returns {Array} The modified array. + */ +const addToArrayIfUnique = (arr, item) => { + if (!arr.includes(item)) { + arr.push(item); + } + return arr; +}; + + +var convertBase = function() { + + function convertBase(baseFrom, baseTo) { + return function(num) { + return parseInt(num, baseFrom).toString(baseTo); + + }; + } + + // binary to decimal + convertBase.bin2dec = convertBase(2, 10); + + // binary to hexadecimal + convertBase.bin2hex = convertBase(2, 16); + + // decimal to binary + convertBase.dec2bin = convertBase(10, 2); + + // decimal to hexadecimal + convertBase.dec2hex = convertBase(10, 16); + + // hexadecimal to binary + convertBase.hex2bin = convertBase(16, 2); + + // hexadecimal to decimal + convertBase.hex2dec = convertBase(16, 10); + + return convertBase; +}(); + +module.exports = { + bytesToInt, + longToByteArray, + addDays, + addZeroBefore, + resizeArray, + isEmptyObject, + emptyJsObject, + sleep, + convertUTCDateToLocalDate, + writeToFile, + addToArrayIfUnique +} diff --git a/RVO37/flow/httprequest.js b/RVO37/flow/httprequest.js new file mode 100755 index 0000000..469c8cb --- /dev/null +++ b/RVO37/flow/httprequest.js @@ -0,0 +1,137 @@ +exports.id = 'httprequest'; +exports.title = 'HTTP Request'; +exports.group = 'HTTP'; +exports.color = '#5D9CEC'; +exports.input = true; +exports.version = '2.0.1'; +exports.output = 1; +exports.author = 'Peter Širka'; +exports.icon = 'cloud-upload'; + +exports.html = `
+
@(URL address)
+
+
+
@(HTTP method)
+
+
+
@(Serialization)
+
+
+
@(Download the content in chunks)
+
@(Keep persistent cookies)
+
@(Disable DNS cache)
+
@(Keep alive connection)
+
+
+
+
@(Custom headers)
+
@(Cookies)
+
+
+
+ +
+
+
+
@(User)
+
+
+
@(Password)
+
+
+
+
+
`; + +exports.readme = `# Request + +This component creates a request with received data. + +__Response:__ +\`\`\`javascript +{ + data: String, + headers: Object, + status: Number, + host: String +} +\`\`\` + +__Dynamic arguments__: +Are performed via FlowData repository and can be used for URL address or for custom headers/cookies/auth. Use \`repository\` component for creating of dynamic arguments. Dynamic values are replaced in the form \`{key}\`: + +- url address e.g. \`https://.../{key}/\` +- headers values e.g. \`{token}\` +- cookies values e.g. \`{token}\``; + +exports.install = function(instance) { + + var can = false; + var flags = null; + var cookies2 = null; + + instance.on('data', function(response) { + can && instance.custom.send(response); + }); + + instance.custom.send = function(response) { + var options = instance.options; + + var headers = null; + var cookies = null; + + options.headers && Object.keys(options.headers).forEach(function(key) { + !headers && (headers = {}); + headers[key] = response.arg(options.headers[key]); + }); + + if (options.username && options.userpassword) { + !headers && (headers = {}); + headers['Authorization'] = 'Basic ' + U.createBuffer(response.arg(options.username + ':' + options.userpassword)).toString('base64'); + } + + options.cookies && Object.keys(options.cookies).forEach(function(key) { + !cookies && (cookies = {}); + cookies[key] = response.arg(options.cookies[key]); + }); + + if (options.chunks) { + U.download(response.arg(options.url), flags, options.stringify === 'none' ? null : response.data, function(err, response) { + response.on('data', (chunks) => instance.send2(chunks)); + }, cookies || cookies2, headers); + } else { + U.request(response.arg(options.url), flags, options.stringify === 'none' ? null : response.data, 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) + instance.error(err, response); + }, cookies || cookies2, headers); + } + }; + + instance.reconfigure = function() { + var options = instance.options; + can = options.url && options.url && options.method && options.stringify ? true : false; + instance.status(can ? '' : 'Not configured', can ? undefined : 'red'); + + if (!can) + return; + + flags = []; + flags.push(options.method.toLowerCase()); + options.stringify === 'json' && flags.push('json'); + options.stringify === 'raw' && flags.push('raw'); + options.keepalive && flags.push('keepalive'); + !options.nodns && flags.push('dnscache'); + if (options.persistentcookies) { + flags.push('cookies'); + cookies2 = {}; + } else + cookies2 = null; + }; + + instance.on('options', instance.reconfigure); + instance.reconfigure(); +}; \ No newline at end of file diff --git a/RVO37/flow/httpresponse.js b/RVO37/flow/httpresponse.js new file mode 100755 index 0000000..160a3bb --- /dev/null +++ b/RVO37/flow/httpresponse.js @@ -0,0 +1,76 @@ +exports.id = 'httpresponse'; +exports.title = 'HTTP Response'; +exports.group = 'HTTP'; +exports.color = '#5D9CEC'; +exports.icon = 'arrow-right'; +exports.input = true; +exports.output = ['#666D76']; +exports.version = '2.0.0'; +exports.author = 'Martin Smola'; +exports.readme = `# HTTP response + +HTTP response will respond with data recieved using data-type set in Settings form or plain text if not set. Output is the message duration \`Number\` in seconds.`; + +exports.html = `
+
@(Response data-type)
+
JSON is by default.
+
`; + +exports.install = function(instance) { + + var dursum = 0; + var durcount = 0; + + instance.on('data', function(flowdata) { + + var ctrl = flowdata.repository.controller; + var data = flowdata.data; + + if (!ctrl) { + instance.throw('No controller to use for response!'); + return; + } + + durcount++; + dursum += ((new Date() - flowdata.begin) / 1000).floor(2); + setTimeout2(instance.id, instance.custom.duration, 500, 10); + + ctrl.$flowdata = flowdata; + + var datatype = instance.options.datatype || 'json'; + if (datatype === 'emptyresponse') + return ctrl.plain(''); + + if (datatype !== 'json' && typeof(data) !== 'string') { + instance.throw('Incorect type of data, expected string, got ' + typeof(data)); + ctrl.plain(data == null ? '' : data.toString()); + return; + } + + switch(datatype) { + case 'html': + ctrl.content(data, 'text/html'); + break; + case 'plain': + ctrl.plain(data); + break; + case 'xml': + ctrl.content(data, 'text/xml'); + break; + default: + ctrl.json(data); + break; + } + }); + + instance.on('service', function() { + dursum = 0; + durcount = 0; + }); + + instance.custom.duration = function() { + var avg = (dursum / durcount).floor(2); + instance.status(avg + ' sec.'); + instance.send2(0, avg); + }; +}; diff --git a/RVO37/flow/httproute.js b/RVO37/flow/httproute.js new file mode 100755 index 0000000..583a19d --- /dev/null +++ b/RVO37/flow/httproute.js @@ -0,0 +1,326 @@ +exports.id = 'httproute'; +exports.title = 'HTTP Route'; +exports.group = 'HTTP'; +exports.color = '#5D9CEC'; +exports.icon = 'globe'; +exports.input = false; +exports.output = ['#6CAC5A', '#37BC9B']; +exports.version = '1.2.3'; +exports.author = 'Martin Smola'; +exports.cloning = false; +exports.options = { method: 'GET', url: '', size: 5, cacheexpire: '5 minutes', cachepolicy: 0, timeout: 5 }; +exports.dateupdated = '2021-01-21 18:30d'; +exports.readme = `# HTTP route + +__Outputs__: +- first output: raw data (cache is empty or is disabled) +- second output: cached data + +If one of the outputs is disabled then automatic responce with code "503 service unavailable" is sent. + +When a request comes in bellow object is available at \`flowdata.data\`: + +\`\`\`javascript +{ + params: { id: '1' }, // params for dynamic routes, e.g. /test/{id} + query: { msg: 'Hello' }, // parsed query string, e.g. /test/1?msg=Hello + body: { test: 'OK' }, // object if json requests otherwise string + headers: {}, // headers data + session: {}, // session data + user: {}, // user data + files: [], // uploaded files + url: '/users/', // a relative URL address + referrer: '/', // referrer + mobile: false, // determines mobile device + robot: false, // determines search robots/crawlsers + language: 'en' // determines language +} +\`\`\` + +See [documentation for flags](https://docs.totaljs.com/latest/en.html#api~HttpRouteOptionsFlags~unauthorize). These method flags are set automatically e.g. \`get, post, put, patch or delete\` + +--- + +\`id:ROUTE_ID\` flag cannot be used since it's already used by this component internally`; + +exports.html = `
+
+ +
+ +
+
+
@(HTTP method)
+
+
+
@(URL address)
+
+
+
+
+
@(Additional flags)
+
@(Separate flags by comma e.g. json, authorize)
+
+
+
@(Max. request size)
+
@(In kB kilobytes)
+
+
+
@(Timeout)
+
@(In seconds.)
+
+
+
+
+
+
@(Automatically respond with 200 OK?)
+
@(If not checked you need to use HTTP response component to respond to the request.)
+
+
@(Custom headers)
+
@(Cookies)
+
+
+
+
+
+
@(Cache policy)
+
@(User instance must contain id property.)
+
+
+
@(Expiration)
+
@(E.g. 5 minutes)
+
+
+
+`; + +exports.install = function(instance) { + + var route; + + var uninstall = function(id) { + if (F.is4) { + route && route.remove(); + route = null; + } else + UNINSTALL('route', id); + }; + + instance.custom.emptyresponse = function(self) { + self.plain(); + }; + + instance.reconfigure = function() { + + var options = instance.options; + + if (!options.url) { + instance.status('Not configured', 'red'); + return; + } + + if (typeof(options.flags) === 'string') + options.flags = options.flags.split(',').trim(); + + uninstall('id:' + instance.id); + + var flags = options.flags || []; + + flags.push('id:' + instance.id); + + if (!F.is4) + flags.push(options.method.toLowerCase()); + + options.timeout && flags.push(options.timeout * 1000); + + // Make unique values + flags = flags.filter(function(v, i, a) { + if(F.is4 && v.toString().toLowerCase() === options.method.toLowerCase()) + return false; // remove method + return a.indexOf(v) === i; + }); + + options.flags = flags; + var handler = function() { + + if (instance.paused || (instance.isDisabled && (instance.isDisabled('output', 0) || instance.isDisabled('output', 1)))) { + instance.status('503 Service Unavailable'); + this.status = 503; + this.json(); + return; + } + + var key; + var self = this; + + if (instance.options.emptyresponse) { + instance.status('200 OK'); + setTimeout(instance.custom.emptyresponse, 100, self); + + if (instance.hasConnection(0)) { + var data = instance.make({ + query: self.query, + body: self.body, + session: self.session, + user: self.user, + files: self.files, + headers: self.req.headers, + url: self.url, + params: self.params + }); + instance.send2(0, data); + } + + return; + } + + switch (instance.options.cachepolicy) { + case 1: // URL + key = 'rro' + instance.id + self.url.hash(); + break; + case 2: // URL + query + case 3: // URL + query + user + key = self.url; + var keys = Object.keys(self.query); + keys.sort(); + for (var i = 0, length = keys.length; i < length; i++) + key += keys[i] + self.query[keys[i]] + '&'; + if (instance.options.cachepolicy === 3 && self.user) + key += 'iduser' + self.user.id; + key = 'rro' + instance.id + key.hash(); + break; + } + + if (key && F.cache.get2(key)) { + var data = instance.make(F.cache.get2(key)); + data.repository.controller = self; + instance.send2(1, data); + } else { + + var data = instance.make({ + query: self.query, + body: self.body, + session: self.session, + user: self.user, + files: self.files, + headers: self.req.headers, + url: self.url, + params: self.params, + mobile: self.mobile, + robot: self.robot, + referrer: self.referrer, + language: self.language + }); + + data.repository.controller = self; + instance.send2(0, data); + key && FINISHED(self.res, () => F.cache.set(key, self.$flowdata.data, instance.options.cacheexpire)); + } + }; + + if (F.is4) + route = ROUTE(options.method.toUpperCase() + ' ' + options.url, handler, flags, options.size || 5); + else + F.route(options.url, handler, flags, options.size || 5); + + instance.status('Listening', 'green'); + }; + + instance.reconfigure(); + instance.on('options', instance.reconfigure); + instance.on('close', function(){ + uninstall('id:' + instance.id); + }); +}; + +// check url exists +FLOW.trigger('httproutecheckurl', function(next, data) { + var url = data.url; + var method = data.method; + if (url[url.length - 1] !== '/') + url += '/'; + var exists = F.routes.web.findItem(r => r.urlraw === url && r.method === method); + next(exists != null); +}); + +exports.uninstall = function() { + FLOW.trigger('httproutecheckurl', null); +}; diff --git a/RVO37/flow/infosender.js b/RVO37/flow/infosender.js new file mode 100755 index 0000000..587724f --- /dev/null +++ b/RVO37/flow/infosender.js @@ -0,0 +1,81 @@ +exports.id = 'infosender'; +exports.title = 'Info sender'; +exports.version = '1.0.0'; +exports.group = 'Worksys'; +exports.color = '#2134B0'; +exports.input = 2; +exports.output = 1 +exports.icon = 'bolt'; + +const { networkInterfaces } = require('os'); + +exports.html = `
+
+
+
CSV Import
+
+
+
`; + +exports.readme = `# send all data to projects.worksys.io, required to monitor status of controller(unipi)`; + +exports.install = function(instance) { + + let id; + let allValues = {}; + let sendAllValuesInterval; + let configured = false; + + let now = new Date(); + console.log(exports.title, "INSTALLED", now.toLocaleString("sk-SK")); + + const nets = networkInterfaces(); + let ipAddresses = Object.create(null); // Or just '{}', an empty object + + for (const name of Object.keys(nets)) { + for (const net of nets[name]) { + // Skip over non-IPv4 and internal (i.e. 127.0.0.1) addresses + if (net.family === 'IPv4' && !net.internal) { + if (!ipAddresses[name]) { + ipAddresses[name] = []; + } + ipAddresses[name].push(net.address); + } + } + } + + function sendValues() { + if (!configured) return; + + if (Object.keys(allValues).length > 0) { + let dataToSend = { ...allValues }; + dataToSend.id = id; + dataToSend.ipAddresses = ipAddresses; + + instance.send(0, dataToSend); + + allValues = {}; + } + } + + instance.on("close", () => { + clearInterval(sendAllValuesInterval); + }) + + instance.on("0", _ => { + id = FLOW.GLOBALS.settings.project_id; + if (id) configured = true; + else console.log(exports.title, "InfoSender: Unable to send data, no id"); + }) + + instance.on("1", flowdata => { + allValues = { ...allValues, ...flowdata.data }; + //console.log("DATA RECEIVED", flowdata.data); + }) + + sendAllValuesInterval = setInterval(() => { + sendValues(); + }, 60000 * 3); + +} + diff --git a/RVO37/flow/modbus_reader.js b/RVO37/flow/modbus_reader.js new file mode 100755 index 0000000..d6d9dad --- /dev/null +++ b/RVO37/flow/modbus_reader.js @@ -0,0 +1,346 @@ +exports.id = 'modbus_reader'; +exports.title = 'Modbus reader'; +exports.version = '2.0.0'; +exports.group = 'Worksys'; +exports.color = '#2134B0'; +exports.input = 1; +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; +//number of phases inRVO +let phases; +//phases where voltage is 0 (set) +let noVoltage; +let energyToSwitchLamps; + +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.phases = this.buildPhases(); + + this.startSocket(); + } + + buildPhases = () => { + let a = []; + for (let i = 1; i <= phases; i++) { + a.push(`Phase_${i}_voltage`) + } + return a; + } + + startSocket = () => { + + let obj = this; + + if (this.socket) { + this.socket.removeAllListeners(); + this.socket = null; + } + + 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('Modbus_reader: Socket connection error', e); //'ECONNREFUSED' or 'ECONNRESET' ?? + }); + + this.socket.on('close', function() { + console.log('Modbus_reader: Socket connection closed - Waiting 10 seconds before connecting 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 we just start to loop devices from the beginning, or there is just 1 device in config, we wait whole timeoutInterval + if (this.indexInDeviceConfig == 0 || deviceConfig.length === 1) 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 (this.phases.includes(singleValue)) { + let l = singleValue.split("_"); + let phase = parseInt(l[1]); + + // console.log(values[singleValue], tbName); + + if (values[singleValue] == 0) { + noVoltage.add(phase); + sendNotification("modbus_reader: checkNullVoltage", tbName, "no_voltage_on_phase", { phase: phase }, "", SEND_TO.tb, instance, "voltage" + phase); + // console.log('no voltage') + } + else { + noVoltage.delete(phase); + // console.log('voltage detected') + sendNotification("modbus_reader: checkNullVoltage", tbName, "voltage_on_phase_restored", { phase: phase }, "", SEND_TO.tb, instance, "voltage" + phase); + } + } + }) + } + + /** + * function sends notification to slack and to tb, if EM total_power value changes more than numberOfNodes*15. This should show, that RVO lamps has been switched on or off + */ + lampSwitchNotification = (values) => { + + if (!values.hasOwnProperty("total_power")) return; + + const actualTotalPower = values.total_power; + + if (actualTotalPower > energyToSwitchLamps && 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 <= energyToSwitchLamps && 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; + } + + function main() { + + phases = FLOW.GLOBALS.settings.phases; + tbName = FLOW.GLOBALS.settings.rvoTbName; + noVoltage = FLOW.GLOBALS.settings.no_voltage; + energyToSwitchLamps = FLOW.GLOBALS.settings.energy_to_switch_lamps / 2.5; //half value is enought to show if lamps are turned on or off + if (deviceConfig.length) mainSocket = new SocketWithClients(); + else console.log("Modbus_reader: no modbus device in configuration"); + + // this notification is to show, that flow (unipi) has been restarted + sendNotification("modbus_reader", tbName, "flow_restart", {}, "", SEND_TO.slack, instance); + } + + instance.on("0", function(_) { + main(); + }) + +} + diff --git a/RVO37/flow/monitorconsumption.js b/RVO37/flow/monitorconsumption.js new file mode 100755 index 0000000..64cc58e --- /dev/null +++ b/RVO37/flow/monitorconsumption.js @@ -0,0 +1,156 @@ +exports.id = 'monitorconsumption'; +exports.title = 'Consumption'; +exports.version = '1.0.0'; +exports.author = 'Peter Širka'; +exports.group = 'Monitoring'; +exports.color = '#967ADC'; +exports.input = 0; +exports.output = 1; +exports.icon = 'bug'; +exports.options = { interval: 5000, enabled: true, monitorconsumption: true, monitorsize: true, monitorconnections: true, monitorfiles: true }; +exports.click = true; +exports.readme = `# Consumption monitoring + +This component measure CPU and memory consumption, open files and open connections of this application. It uses these Linux commands: \`ps\`, \`lsof\`, \`netstat\` and \`df\`. + +__Data Example__: + +\`\`\`javascript +{ + cpu: 0, // percentage + memory: 4096, // in bytes + size: 34303, // directory size in bytes + files: 34, // count of open files + connections: 343, // count of connections + uptime: '1-12:34:00' +} +\`\`\``; + +exports.html = `
+
+
+
@(Interval in milliseconds)
+
+
+
+
Monitor: Consumption + uptime
+
Monitor: Count of open files
+
Monitor: Count of open connections
+
Monitor: Directory size
+
`; + +exports.install = function(instance) { + + var current = { cpu: 0, memory: 0, files: 0, connections: 0, size: 0, uptime: '', counter: 0 }; + var tproc = null; + var Exec = require('child_process').exec; + var reg_empty = /\s{2,}/g; + var reg_appdisksize = /^[\d.,]+/; + + instance.custom.run = function() { + + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + + var arr = []; + + // Get CPU and Memory consumption + instance.options.monitorconsumption && arr.push(function(next) { + Exec('ps -p {0} -o %cpu,rss,etime'.format(process.pid), function(err, response) { + + if (err) { + instance.throw(err); + } else { + var line = response.split('\n')[1]; + line = line.trim().replace(reg_empty, ' ').split(' '); + var cpu = line[0].parseFloat(); + current.cpu = cpu.floor(1); + current.memory = line[1].parseInt2() * 1024; // kB to bytes + current.uptime = line[2]; + } + + next(); + }); + }); + + // Get count of open files + instance.options.monitorfiles && arr.push(function(next) { + Exec('lsof -a -p {0} | wc -l'.format(process.pid), function(err, response) { + if (err) + instance.throw(err); + else + current.files = response.trim().parseInt2(); + next(); + }); + }); + + // Get count of opened network connections + instance.options.monitorconnections && arr.push(function(next) { + Exec('netstat -an | grep :{0} | wc -l'.format(F.port), function(err, response) { + if (err) { + instance.throw(err); + } else { + current.connections = response.trim().parseInt2() - 1; + if (current.connections < 0) + current.connections = 0; + } + next(); + }); + }); + + // Get directory size + instance.options.monitorsize && current.counter % 5 !== 0 && arr.push(function(next) { + Exec('du -hsb ' + process.cwd(), function(err, response) { + if (err) { + instance.throw(err); + } else { + var match = response.trim().match(reg_appdisksize); + match && (current.size = match.toString().trim().parseInt2()); + } + next(); + }); + }); + + arr.async(function() { + + tproc && clearTimeout(tproc); + + if (instance.options.enabled) { + tproc = setTimeout(instance.custom.run, instance.options.interval); + instance.send2(current); + } + + instance.custom.status(); + current.counter++; + }); + }; + + instance.custom.status = function() { + if (instance.options.enabled) + instance.status('{0}% / {1}'.format(current.cpu, current.memory.filesize())); + else + instance.status('Disabled', 'red'); + }; + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + + if (instance.options.enabled) { + current.counter = 0; + instance.custom.run(); + } + + }); + + instance.on('close', function() { + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + }); + + setTimeout(instance.custom.run, 1000); +}; \ No newline at end of file diff --git a/RVO37/flow/monitordisk.js b/RVO37/flow/monitordisk.js new file mode 100755 index 0000000..f4fdaa0 --- /dev/null +++ b/RVO37/flow/monitordisk.js @@ -0,0 +1,96 @@ +exports.id = 'monitordisk'; +exports.title = 'Disk'; +exports.version = '1.0.0'; +exports.author = 'Peter Širka'; +exports.group = 'Monitoring'; +exports.color = '#F6BB42'; +exports.output = 1; +exports.icon = 'hdd-o'; +exports.click = true; +exports.options = { interval: 8000, path: '/', enabled: true }; +exports.readme = `# Disk monitoring + +This component monitors disk \`bytes\` consumption in Linux systems. It uses \`df\` command. + +__Data Example__: + +\`\`\`javascript +{ + total: 474549649408, + used: 39125245952, + free: 411294994432 +} +\`\`\``; + +exports.html = `
+
+
+
@(Interval in milliseconds)
+
+
+
@(Path)
+
+
+
`; + +exports.install = function(instance) { + + var current = { total: 0, used: 0, free: 0, path: '', type: '', percentUsed: 0 }; + var tproc = null; + + instance.custom.run = function() { + + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + + if (!instance.options.enabled) + return; + + require('child_process').exec('df -hTB1 ' + instance.options.path, function(err, response) { + + tproc = setTimeout(instance.custom.run, instance.options.interval); + + if (err) { + instance.error(err); + return; + } + + response.parseTerminal(function(line) { + if (line[0][0] !== '/') + return; + current.total = line[2].parseInt(); + current.free = line[4].parseInt(); + current.used = line[3].parseInt(); + current.path = instance.options.path || '/'; + current.type = line[1]; + current.percentUsed = line[5]; + instance.custom.status(); + instance.send2(current); + }); + }); + }; + + instance.custom.status = function() { + if (instance.options.enabled) + instance.status(current.free.filesize() + ' / ' + current.total.filesize()); + else + instance.status('Disabled', 'red'); + }; + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + instance.options.enabled && instance.custom.run(); + }); + + instance.on('close', function() { + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + }); + + setTimeout(instance.custom.run, 1000); +}; \ No newline at end of file diff --git a/RVO37/flow/monitormemory.js b/RVO37/flow/monitormemory.js new file mode 100755 index 0000000..2decbc4 --- /dev/null +++ b/RVO37/flow/monitormemory.js @@ -0,0 +1,87 @@ +exports.id = 'monitormemory'; +exports.title = 'Memory'; +exports.version = '1.0.0'; +exports.author = 'Peter Širka'; +exports.group = 'Monitoring'; +exports.color = '#F6BB42'; +exports.output = 1; +exports.click = true; +exports.icon = 'microchip'; +exports.options = { interval: 8000, enabled: true }; +exports.readme = `# Memory monitoring + +This component monitors memory \`bytes\` consumption in Linux systems. It uses \`free\` command. + +__Data Example__: + +\`\`\`javascript +{ + total: 33558769664, + used: 1998868480, + free: 2653708288 +} +\`\`\``; + +exports.html = `
+
+
+
@(Interval in milliseconds)
+
+
+
`; + +exports.install = function(instance) { + + var current = { total: 0, used: 0, free: 0 }; + var tproc = null; + + instance.custom.run = function() { + + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + + if (!instance.options.enabled) + return; + + require('child_process').exec('free -b -t', function(err, response) { + + tproc = setTimeout(instance.custom.run, instance.options.interval); + + if (err) { + instance.error(err); + return; + } + + var memory = response.split('\n')[1].match(/\d+/g); + current.total = memory[0].parseInt(); + current.used = memory[1].parseInt() - memory[3].parseInt(); + current.free = current.total - current.used; + instance.custom.status(); + instance.send2(current); + }); + }; + + instance.custom.status = function() { + if (instance.options.enabled) + instance.status(current.free.filesize() + ' / ' + current.total.filesize()); + else + instance.status('Disabled', 'red'); + }; + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + instance.options.enabled && instance.custom.run(); + }); + + instance.on('close', function() { + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + }); + + setTimeout(instance.custom.run, 1000); +}; \ No newline at end of file diff --git a/RVO37/flow/nodesdb_changecheck.js b/RVO37/flow/nodesdb_changecheck.js new file mode 100755 index 0000000..9adab62 --- /dev/null +++ b/RVO37/flow/nodesdb_changecheck.js @@ -0,0 +1,77 @@ +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 = 2; +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); + } + } + + //kedze do slacku posielame stringy, na cloud musime previest vsetky stringy spat na objekty: + // Funkcia na parsovanie všetkých reťazcov v poli + const parseArray = (arr) => { + return arr.map(jsonString => JSON.parse(jsonString)); + }; + + 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); + if (FLOW.GLOBALS.settings.send_changed_node_numbers) instance.send(1, { aktualneNody: parseArray(zmenene), originalne: parseArray(Array.from(set2)) }); + } + 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/RVO37/flow/show_dbdata.js b/RVO37/flow/show_dbdata.js new file mode 100755 index 0000000..1e23ff7 --- /dev/null +++ b/RVO37/flow/show_dbdata.js @@ -0,0 +1,243 @@ +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 = 8; +exports.output = 1; + +const { exec } = require('child_process'); + +exports.install = 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 }) + }) + instance.on("5", _ => { + exec("sudo tail -n 25 monitor.txt", (err, stdout, stderr) => { + if (err || stderr) instance.send(0, { err, stderr }); + else instance.send(0, stdout); + }) + }) + instance.on("6", _ => { + exec("sudo tail -n 25 err.txt", (err, stdout, stderr) => { + if (err || stderr) instance.send(0, { err, stderr }); + else instance.send(0, stdout); + }) + }) + instance.on("7", _ => { + instance.send(0, FLOW.deviceStatus); + }) +}; + + +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/RVO37/flow/slack_filter.js b/RVO37/flow/slack_filter.js new file mode 100755 index 0000000..6618523 --- /dev/null +++ b/RVO37/flow/slack_filter.js @@ -0,0 +1,188 @@ +exports.id = 'slack_filter'; +exports.title = 'Slack Filter'; +exports.group = 'Citysys'; +exports.color = '#30E193'; +exports.input = 2; +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 = `
+
+
+
@(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('0', 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']['en']; + 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"] = []; + } + + instance.options.name = FLOW.GLOBALS.settings.rvo_name; + if (instance.options.name) { + instance.status('Running'); + running = true; + } else { + instance.status('Please run options again', 'red'); + running = false; + } + } catch (e) { + instance.error('Citysys connector: ' + e.message); + } + }; + + instance.on('options', instance.reconfigure); + + instance.on("1", _ => { + instance.reconfigure(); + }) +}; diff --git a/RVO37/flow/thermometer.js b/RVO37/flow/thermometer.js new file mode 100755 index 0000000..fc7074d --- /dev/null +++ b/RVO37/flow/thermometer.js @@ -0,0 +1,99 @@ +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 = 5;//minutes +let NUMBER_OF_FAILURES_TO_SEND_ERROR = 13; + +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) => { + + 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); + setTimeout(main, 20000); + }) +}; diff --git a/RVO37/flow/trigger.js b/RVO37/flow/trigger.js new file mode 100755 index 0000000..27545a8 --- /dev/null +++ b/RVO37/flow/trigger.js @@ -0,0 +1,79 @@ +exports.id = 'trigger'; +exports.title = 'Trigger'; +exports.group = 'Inputs'; +exports.color = '#F6BB42'; +exports.click = true; +exports.output = 1; +exports.version = '1.1.0'; +exports.author = 'Martin Smola'; +exports.icon = 'play'; + +exports.html = `
+
@(Data type (String by default))
+
@(Data)
+
Trigger 5s after initialization.
+
@(Useful when there's a need to run certain flow when the app restarts, etc.)
+
`; + +exports.readme = `# Trigger + +- Clicking on the component starts the chain +- Settings allows to set a data-type and a value`; + +exports.install = function(instance) { + + var value; + + instance.on('click', () => instance.send2(value)); + + instance.reconfigure = function() { + var options = instance.options; + value = null; + switch (options.datatype) { + case 'integer': + value = options.data.parseInt2('error'); + value = value === 'error' ? NaN : value; + break; + case 'float': + value = options.data.parseFloat2('error'); + value = value === 'error' ? NaN : value; + break; + case 'date': + options.data = options.data.toString(); + var num = options.data.parseInt('error'); + num === 'error' && (num = options.data.parseDate('error')); + num === 'error' && (num = null); + value = num ? new Date(num).toUTCString() : num; + break; + case 'object': + try { + value = (new Function('return ' + options.data))(); + } catch (e) { + instance.error(e); + } + break; + case 'boolean': + value = options.data.parseBoolean(); + break; + case 'buffer': + try { + value = U.createBuffer(options.data); + } catch (e) { + instance.error(e); + } + break; + case 'string': + default: + value = '' + (options.data || ''); + break; + } + }; + + instance.on('options', instance.reconfigure); + instance.reconfigure(); + + if (instance.options.restart) + setTimeout(function(){ + instance.send2(value); + }, 5000); +}; diff --git a/RVO37/flow/variables.txt b/RVO37/flow/variables.txt new file mode 100755 index 0000000..e69de29 diff --git a/RVO37/flow/virtualwirein.js b/RVO37/flow/virtualwirein.js new file mode 100755 index 0000000..38a4e42 --- /dev/null +++ b/RVO37/flow/virtualwirein.js @@ -0,0 +1,43 @@ +exports.id = 'virtualwirein'; +exports.title = 'Virtual wire in'; +exports.version = '1.0.0'; +exports.author = 'Martin Smola'; +exports.color = '#303E4D'; +exports.icon = 'sign-in'; +exports.input = false; +exports.output = 1; +exports.options = {}; +exports.readme = `# Virtual wire in + +When the wires between the components are mess it's time to use Virtual wire.`; + +exports.html = `
+
@(Wire name)
+
+`; + +exports.install = function(instance) { + + instance.custom.reconfigure = function(options){ + if (instance.options.wirename) { + instance.status(instance.options.wirename); + } else + instance.status('Not configured', 'red'); + }; + + ON('virtualwire', function(wirename, flowdata){ + if (instance.options.wirename && instance.options.wirename === wirename) + instance.send(flowdata); + }); + + instance.on('options', instance.custom.reconfigure); + instance.custom.reconfigure(); +}; diff --git a/RVO37/flow/virtualwireout.js b/RVO37/flow/virtualwireout.js new file mode 100755 index 0000000..94a1e4f --- /dev/null +++ b/RVO37/flow/virtualwireout.js @@ -0,0 +1,41 @@ +exports.id = 'virtualwireout'; +exports.title = 'Virtual wire out'; +exports.version = '1.0.0'; +exports.author = 'Martin Smola'; +exports.color = '#303E4D'; +exports.icon = 'sign-out'; +exports.input = true; +exports.options = {}; +exports.readme = `# Virtual wire out + +When the wires between the components are mess it's time to use Virtual wire.`; + +exports.html = `
+
@(Wire name)
+
+`; + +exports.install = function(instance) { + + instance.custom.reconfigure = function(){ + if (instance.options.wirename) { + instance.status(instance.options.wirename); + } else + instance.status('Not configured', 'red'); + }; + + instance.on('data', function(flowdata) { + EMIT('virtualwire', instance.options.wirename, flowdata); + }); + + instance.on('options', instance.custom.reconfigure); + instance.custom.reconfigure(); +}; diff --git a/RVO37/flow/wsmqttpublish.js b/RVO37/flow/wsmqttpublish.js new file mode 100755 index 0000000..0eba804 --- /dev/null +++ b/RVO37/flow/wsmqttpublish.js @@ -0,0 +1,448 @@ +exports.id = 'wsmqttpublish'; +exports.title = 'WS MQTT publish'; +exports.group = 'MQTT'; +exports.color = '#888600'; +exports.version = '1.0.2'; +exports.icon = 'sign-out'; +exports.input = 2; +exports.output = 3; +exports.options = { host: 'tb-stage.worksys.io', port: 1883, clientid: "", username: "" }; + +exports.html = `
+
+
+
Hostname or IP address (if not empty - setting will override db setting)
+
+
+
Port
+
+
+
+
+
@(Client id)
+
+
+
@(Username)
+
+
+
`; + + +exports.readme = ` +# WS MQTT Publish + +Version 1.0.3. + +Added: +- database collections, +- 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 = { + debug: 0, + rpcCall: 1, + services: 2 +} + +//CONFIG +let createTelemetryBackup = true; +let saveTelemetryOnError = true;//backup_on_failure overrides this value +//------------------------ + +let rollers; +if (createTelemetryBackup) rollers = require('streamroller'); + +const noSqlFileSizeLimit = 4194304;//use 5MB - 4194304 +let insertNoSqlCounter = 0; +let insertBackupNoSqlCounter = 0; +let processingData = false; + +let backup_on_failure = false;//== saveTelemetryOnError - create backup client 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; + +process.on('uncaughtException', function(err) { + + errLogger.error('uncaughtException:', err.message) + errLogger.error(err.stack); + + //TODO + //send to service + + //process.exit(1); +}) + +const nosql = NOSQL('tbdata'); +const nosqlBackup = NOSQL('/backup/tbdata'); + + +exports.install = function(instance) { + + var client; + var opts; + var clientReady = false; + + // wsmqtt status for notification purposes on projects.worksys.io database + let wsmqttName = null; + let sendWsStatusVar = null; + let wsmqtt_status = 'disconnected'; + + 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'; + } + + function sendWsStatus() { + instance.send(SEND_TO.services, { [wsmqttName]: wsmqtt_status }); + } + + + function main() { + if (!FLOW.dbLoaded) return; + + loadSettings(); + clearInterval(sendWsStatus); + sendWsStatusVar = setInterval(sendWsStatus, 180000); + } + + //set opts according to db settings + function loadSettings() { + + if (instance.options.host !== "") { + //override settings from database + var o = instance.options; + opts = { + host: o.host, + port: o.port, + clientId: o.clientid, + username: o.username, + rejectUnauthorized: false, + resubscribe: false + }; + + wsmqttName = getWsmqttName(o.host); + + console.log("wsmqttpublich -> loadSettings from instance.options", instance.options); + } + else { + + const SETTINGS = FLOW.GLOBALS.settings; + backup_on_failure = SETTINGS.backup_on_failure; + saveTelemetryOnError = backup_on_failure; + + restore_from_backup = SETTINGS.restore_from_backup; + restore_backup_wait = SETTINGS.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; + + opts = { + host: mqtt_host, + port: mqtt_port, + keepalive: 10, + clientId: mqtt_clientid, + username: mqtt_username, + rejectUnauthorized: false, + resubscribe: false + }; + + wsmqttName = getWsmqttName(mqtt_host); + } + + connectToTbServer(); + } + + function connectToTbServer() { + 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"); + //monitor.info("MQTT client connected"); + + sendClientError = true; + clientReady = true; + wsmqtt_status = 'connected'; + }); + + client.on('reconnect', function() { + instance.status("Reconnecting", "yellow"); + clientReady = false; + }); + + client.on('message', function(topic, message) { + // message is type of buffer + message = message.toString(); + if (message[0] === '{') { + TRY(function() { + + message = JSON.parse(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 } }); + } + + }, () => instance.debug('MQTT: Error parsing data', message)); + } + + instance.send(SEND_TO.rpcCall, { "topic": topic, "content": message }); + }); + + client.on('close', function() { + clientReady = false; + wsmqtt_status = 'disconnected'; + + instance.status("Disconnected", "red"); + instance.send(SEND_TO.debug, { "message": "Client CLOSE signal received !" }); + }); + + client.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; + wsmqtt_status = 'disconnected'; + }); + + } + + + instance.on("0", _ => { + main(); + }) + + + instance.on('1', function(data) { + + if (clientReady) { + //do we have some data in backup file? if any, process data from database + if (saveTelemetryOnError) { + //read telemetry data and send back to server + if (!processingData) processDataFromDatabase(); + } + + let stringifiedJson = JSON.stringify(data.data); + client.publish("v1/gateway/telemetry", stringifiedJson, { qos: 1 }); + + //backup telemetry + if (createTelemetryBackup) { + data.data.id = UID(); + nosqlBackup.insert(data.data); + + insertBackupNoSqlCounter++; + if (insertBackupNoSqlCounter > 150) { + let options = { compress: true }; + let path = __dirname + "/../databases/backup/tbdata.nosql"; + var stream = new rollers.RollingFileStream(path, noSqlFileSizeLimit, 150, options); + stream.write(""); + stream.end(); + + insertBackupNoSqlCounter = 0; + } + } + + } + 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 (saveTelemetryOnError) { + //create new file from tbdata.nosql, if file size exceeds given limit, and clear tbdata.nosql + makeBackupFromDbFile(); + + //write to tb + data.data.id = UID(); + nosql.insert(data.data); + } + } + }); + + + instance.close = function(done) { + if (clientReady) { + client.end(); + clearInterval(sendWsStatusVar); + } + }; + + + function getDbBackupFileCounter(type) { + var files = fs.readdirSync(__dirname + "/../databases"); + + let counter = 0; + for (var i = 0; i < files.length; i++) { + + if (files[i] == "tbdata.nosql") continue; + + if (files[i].endsWith(".nosql")) { + + let pos = files[i].indexOf("."); + if (pos > -1) { + + let fileCounter = counter; + let firstDigit = files[i].slice(0, pos); + + fileCounter = parseInt(firstDigit); + if (isNaN(fileCounter)) fileCounter = 0; + //console.log("getDbBackupFileCounter digit:", files[i], firstDigit, fileCounter, isNaN(fileCounter), type); + + if (type == "max") { + if (fileCounter > counter) { + counter = fileCounter; + } + } + else if (type == "min") { + if (counter == 0) counter = fileCounter; + + if (fileCounter < counter) { + counter = fileCounter; + } + } + } + } + + } + + if (type == "max") counter++; + + return counter; + } + + const makeBackupFromDbFile = async () => { + + if (!saveTelemetryOnError) return; + + //to avoid large file: tbdata.nosql + + //init value is 0! + if (insertNoSqlCounter > 0) { + --insertNoSqlCounter; + return; + } + + insertNoSqlCounter = 100; + + let source = __dirname + "/../databases/tbdata.nosql"; + + var stats = fs.statSync(source); + var fileSizeInBytes = stats.size; + + if (fileSizeInBytes > noSqlFileSizeLimit) { + + let counter = 1; + counter = getDbBackupFileCounter("max"); + + let destination = __dirname + "/../databases/" + counter + "." + "tbdata.nosql"; + + //make backup file + fs.copyFileSync(source, destination); + //fs.renameSync(p, p + "." + counter); + + //clear tbdata.nosql + fs.writeFileSync(source, ""); + fs.truncateSync(source, 0); + + } + } + + const processDataFromDatabase = async () => { + + if (restore_from_backup <= 0) return; + + //calculate diff + const now = new Date(); + let currentTime = now.getTime(); + let diff = currentTime - lastRestoreTime; + + if ((diff / 1000) < restore_backup_wait) { + //console.log("*********restore_backup_wait", diff, restore_backup_wait); + return; + } + + processingData = true; + + //get filename to process + let counter = getDbBackupFileCounter("min"); + + //we have some backup files + let dataBase = 'tbdata'; + + var nosql; + if (counter == 0) dataBase = 'tbdata'; + else dataBase = counter + "." + 'tbdata'; + + nosql = NOSQL(dataBase); + + //select all data - use limit restore_from_backup + let records = await promisifyBuilder(nosql.find().take(restore_from_backup)); + + for (let i = 0; i < records.length; i++) { + if (clientReady) { + + let item = records[i]; + let id = item.id; + + if (id !== undefined) { + //console.log("------------processDataFromDatabase - remove", id, dataBase, i); + + try { + + let message = JSON.parse(JSON.stringify(item)); + delete message.id; + + client.publish("v1/gateway/telemetry", JSON.stringify(message), { qos: 1 }); + + //remove from database + await promisifyBuilder(nosql.remove().where("id", id)); + + } catch (error) { + //process error + console.log("processDataFromDatabase", error); + } + + } + + } + else { + processingData = false; + return; + } + } + + if (records.length > 0) { + //clean backup file + if (counter > 0) nosql.clean(); + } + + //no data in db, remove + if (records.length == 0) { + if (counter > 0) nosql.drop(); + } + + const d = new Date(); + lastRestoreTime = d.getTime(); + + processingData = false; + + } + + instance.on('options', main); + //instance.reconfigure(); +}; diff --git a/RVO37/monitor.txt b/RVO37/monitor.txt new file mode 100755 index 0000000..be887cd --- /dev/null +++ b/RVO37/monitor.txt @@ -0,0 +1,315 @@ +[2025-10-09T19:11:55.159] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-09T19:12:00.518] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-09T19:12:00.523] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-09T19:12:00.524] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-09T19:12:00.525] [INFO] monitorLogs - profile: { + 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: 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 +} +[2025-10-09T19:12:00.529] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T19:12:00.530] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-10-10T05:32:00.530Z +[2025-10-09T19:12:00.532] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-10-10T16:45:00.532Z +[2025-10-09T19:12:00.533] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T19:12:00.534] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-10-09T19:12:00.535] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-09T19:12:00.535] [INFO] monitorLogs - profile: { + 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: 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 +} +[2025-10-09T19:12:00.538] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T19:12:00.538] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-10-10T05:32:00.538Z +[2025-10-09T19:12:00.539] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-10-10T16:45:00.539Z +[2025-10-09T19:12:00.540] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T19:12:00.541] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-10-09T19:12:00.541] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-09T19:12:00.542] [INFO] monitorLogs - profile: { + 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: 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 +} +[2025-10-09T19:12:00.545] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T19:12:00.546] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-10-10T05:32:00.546Z +[2025-10-09T19:12:00.547] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-10-10T16:45:00.547Z +[2025-10-09T19:12:00.547] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T19:12:00.549] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-10-09T19:12:00.571] [INFO] monitorLogs - tasks created: 686 +[2025-10-09T19:12:00.573] [INFO] monitorLogs - -->FLOW bol spustený 5dBNwRp9graYJxZn409NrVklVov1b2QLPDqGm6XK 2025-08-08 +[2025-10-09T19:12:05.580] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-10T03:12:03.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-10 03:12:03 +[2025-10-10T06:49:39.945] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-10T06:49:39.949] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-10T06:49:39.951] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-10T18:27:00.198] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-10T18:27:00.201] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-10T18:27:00.203] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-11T03:12:04.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-11 03:12:04 +[2025-10-11T06:49:31.589] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-11T06:49:31.602] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-11T06:49:31.605] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-11T18:31:53.593] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-11T18:31:53.599] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-11T18:31:53.601] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-12T03:12:05.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-12 03:12:05 +[2025-10-12T06:46:52.779] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-12T06:46:52.785] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-12T06:46:52.787] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-12T18:31:45.278] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-12T18:31:45.284] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-12T18:31:45.286] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-13T03:12:06.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-13 03:12:06 +[2025-10-13T06:46:44.321] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-13T06:46:44.327] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-13T06:46:44.329] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-13T14:28:51.354] [INFO] monitorLogs - turnLine on - (line, SETTINGS.maintenance_mode) 0 true command received from platform +[2025-10-13T14:29:06.009] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false command received from platform +[2025-10-13T14:29:13.689] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false command received from platform +[2025-10-13T14:38:52.243] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false command received from platform +[2025-10-13T14:39:02.801] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false command received from platform +[2025-10-13T14:39:09.851] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false command received from platform +[2025-10-13T18:36:38.158] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-13T18:36:38.160] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-13T18:36:38.162] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-14T03:12:07.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-14 03:12:07 +[2025-10-14T06:49:07.331] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-14T06:49:07.336] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-14T06:49:07.339] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-14T10:59:17.156] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-14T10:59:22.520] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-14T10:59:22.525] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-14T10:59:22.526] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-14T10:59:22.526] [INFO] monitorLogs - profile: { + 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: 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 +} +[2025-10-14T10:59:22.531] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-14T10:59:22.532] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-10-15T05:40:00.531Z +[2025-10-14T10:59:22.533] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-10-14T16:35:00.533Z +[2025-10-14T10:59:22.534] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:40', name: 'luxOff' }, + { value: 1, start_time: '18:35', name: 'luxOn' } +] +[2025-10-14T10:59:22.535] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-10-14T10:59:22.536] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-14T10:59:22.537] [INFO] monitorLogs - profile: { + 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: 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 +} +[2025-10-14T10:59:22.539] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-14T10:59:22.540] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-10-15T05:40:00.540Z +[2025-10-14T10:59:22.541] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-10-14T16:35:00.541Z +[2025-10-14T10:59:22.541] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:40', name: 'luxOff' }, + { value: 1, start_time: '18:35', name: 'luxOn' } +] +[2025-10-14T10:59:22.542] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-10-14T10:59:22.543] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-14T10:59:22.543] [INFO] monitorLogs - profile: { + 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: 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 +} +[2025-10-14T10:59:22.546] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-14T10:59:22.546] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-10-15T05:40:00.546Z +[2025-10-14T10:59:22.547] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-10-14T16:35:00.547Z +[2025-10-14T10:59:22.548] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:40', name: 'luxOff' }, + { value: 1, start_time: '18:35', name: 'luxOn' } +] +[2025-10-14T10:59:22.549] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-10-14T10:59:22.553] [INFO] monitorLogs - tasks created: 686 +[2025-10-14T10:59:22.555] [INFO] monitorLogs - -->FLOW bol spustený 5dBNwRp9graYJxZn409NrVklVov1b2QLPDqGm6XK 2025-08-08 +[2025-10-14T10:59:27.562] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-14T18:26:09.574] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-14T18:26:09.590] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-14T18:26:09.592] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-15T03:59:24.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-15 03:59:24 +[2025-10-15T06:51:11.697] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-15T06:51:11.701] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-15T06:51:11.703] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-15T08:01:29.148] [INFO] monitorLogs - turnLine on - (line, SETTINGS.maintenance_mode) 0 true command received from platform +[2025-10-15T08:01:36.184] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false command received from platform +[2025-10-15T08:01:44.815] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false command received from platform +[2025-10-15T08:02:05.936] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false command received from platform +[2025-10-15T08:04:27.063] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false command received from platform +[2025-10-15T08:04:40.185] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false command received from platform +[2025-10-15T14:28:32.545] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-15T14:28:37.971] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-15T14:28:37.976] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-15T14:28:37.977] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-15T14:28:37.978] [INFO] monitorLogs - profile: { + 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: 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 +} +[2025-10-15T14:28:37.982] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-15T14:28:37.983] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-10-16T05:41:00.982Z +[2025-10-15T14:28:37.985] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-10-15T16:33:00.984Z +[2025-10-15T14:28:37.985] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:41', name: 'luxOff' }, + { value: 1, start_time: '18:33', name: 'luxOn' } +] +[2025-10-15T14:28:37.986] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-10-15T14:28:37.987] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-15T14:28:37.988] [INFO] monitorLogs - profile: { + 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: 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 +} +[2025-10-15T14:28:37.991] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-15T14:28:37.992] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-10-16T05:41:00.991Z +[2025-10-15T14:28:37.993] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-10-15T16:33:00.993Z +[2025-10-15T14:28:37.993] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:41', name: 'luxOff' }, + { value: 1, start_time: '18:33', name: 'luxOn' } +] +[2025-10-15T14:28:37.995] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-10-15T14:28:37.996] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-15T14:28:37.996] [INFO] monitorLogs - profile: { + 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: 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 +} +[2025-10-15T14:28:37.999] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-15T14:28:37.999] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-10-16T05:41:00.999Z +[2025-10-15T14:28:38.000] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-10-15T16:33:00.000Z +[2025-10-15T14:28:38.001] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:41', name: 'luxOff' }, + { value: 1, start_time: '18:33', name: 'luxOn' } +] +[2025-10-15T14:28:38.002] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-10-15T14:28:38.023] [INFO] monitorLogs - tasks created: 686 +[2025-10-15T14:28:38.026] [INFO] monitorLogs - -->FLOW bol spustený 5dBNwRp9graYJxZn409NrVklVov1b2QLPDqGm6XK 2025-10-08 +[2025-10-15T14:28:43.032] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-15T18:24:42.049] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-15T18:24:42.055] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-15T18:24:42.058] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor diff --git a/RVO37/package-lock.json b/RVO37/package-lock.json new file mode 100755 index 0000000..3c5c1ba --- /dev/null +++ b/RVO37/package-lock.json @@ -0,0 +1,2139 @@ +{ + "name": "emptyproject", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "emptyproject", + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "bitwise": "^2.1.0", + "easy-crc": "0.0.2", + "jsmodbus": "^4.0.6", + "log4js": "^6.3.0", + "moment": "^2.30.1", + "mqtt": "^4.2.6", + "nodemailer": "^6.9.7", + "serialport": "^9.2.8", + "total.js": "^3.4.13" + } + }, + "node_modules/@serialport/binding-abstract": { + "version": "9.2.3", + "resolved": "https://registry.npmjs.org/@serialport/binding-abstract/-/binding-abstract-9.2.3.tgz", + "integrity": "sha512-cQs9tbIlG3P0IrOWyVirqlhWuJ7Ms2Zh9m2108z6Y5UW/iVj6wEOiW8EmK9QX9jmJXYllE7wgGgvVozP5oCj3w==", + "dependencies": { + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/binding-mock": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/binding-mock/-/binding-mock-9.2.4.tgz", + "integrity": "sha512-dpEhACCs44oQhh6ajJfJdvQdK38Vq0N4W6iD/gdplglDCK7qXRQCMUjJIeKdS/HSEiWkC3bwumUhUufdsOyT4g==", + "dependencies": { + "@serialport/binding-abstract": "9.2.3", + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/bindings": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/@serialport/bindings/-/bindings-9.2.8.tgz", + "integrity": "sha512-hSLxTe0tADZ3LMMGwvEJWOC/TaFQTyPeFalUCsJ1lSQ0k6bPF04JwrtB/C81GetmDBTNRY0GlD0SNtKCc7Dr5g==", + "hasInstallScript": true, + "dependencies": { + "@serialport/binding-abstract": "9.2.3", + "@serialport/parser-readline": "9.2.4", + "bindings": "^1.5.0", + "debug": "^4.3.2", + "nan": "^2.15.0", + "prebuild-install": "^7.0.0" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-byte-length": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-byte-length/-/parser-byte-length-9.2.4.tgz", + "integrity": "sha512-sQD/iw4ZMU3xW9PLi0/GlvU6Y623jGeWecbMkO7izUo/6P7gtfv1c9ikd5h0kwL8AoAOpQA1lxdHIKox+umBUg==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-cctalk": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-cctalk/-/parser-cctalk-9.2.4.tgz", + "integrity": "sha512-T4TU5vQMwmo9AB3gQLFDWbfJXlW5jd9guEsB/nqKjFHTv0FXPdZ7DQ2TpSp8RnHWxU3GX6kYTaDO20BKzc8GPQ==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-delimiter": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-delimiter/-/parser-delimiter-9.2.4.tgz", + "integrity": "sha512-4nvTAoYAgkxFiXrkI+3CA49Yd43CODjeszh89EK+I9c8wOZ+etZduRCzINYPiy26g7zO+GRAb9FoPCsY+sYcbQ==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-inter-byte-timeout": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-inter-byte-timeout/-/parser-inter-byte-timeout-9.2.4.tgz", + "integrity": "sha512-SOAdvr0oBQIOCXX198hiTlxs4JTKg9j5piapw5tNq52fwDOWdbYrFneT/wN04UTMKaDrJuEvXq6T4rv4j7nJ5A==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-readline": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-readline/-/parser-readline-9.2.4.tgz", + "integrity": "sha512-Z1/qrZTQUVhNSJP1hd9YfDvq0o7d87rNwAjjRKbVpa7Qi51tG5BnKt43IV3NFMyBlVcRe0rnIb3tJu57E0SOwg==", + "dependencies": { + "@serialport/parser-delimiter": "9.2.4" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-ready": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-ready/-/parser-ready-9.2.4.tgz", + "integrity": "sha512-Pyi94Itjl6qAURwIZr/gmZpMAyTmKXThm6vL5DoAWGQjcRHWB0gwv2TY2v7N+mQLJYUKU3cMnvnATXxHm7xjxw==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-regex": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-regex/-/parser-regex-9.2.4.tgz", + "integrity": "sha512-sI/cVvPOYz+Dbv4ZdnW16qAwvXiFf/1pGASQdbveRTlgJDdz7sRNlCBifzfTN2xljwvCTZYqiudKvDdC1TepRQ==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/stream": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/stream/-/stream-9.2.4.tgz", + "integrity": "sha512-bLye8Ub4vUFQGmkh8qEqehr7SE7EJs2yDs0h9jzuL5oKi+F34CFmWkEErO8GAOQ8YNn7p6b3GxUgs+0BrHHDZQ==", + "dependencies": { + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "node_modules/are-we-there-yet": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", + "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/base64-js": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", + "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==" + }, + "node_modules/bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "dependencies": { + "file-uri-to-path": "1.0.0" + } + }, + "node_modules/bitwise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/bitwise/-/bitwise-2.1.0.tgz", + "integrity": "sha512-XKgAhMXCh4H/3oNwAHAsAO0iC89s9cOiumgYwSHjSobGWxYjv62YhkL9QEdvGP151xypCtMlAfKK79GEcd2eRQ==" + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/bl/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/buffer": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz", + "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==", + "dependencies": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + }, + "node_modules/buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" + }, + "node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, + "node_modules/code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/commist": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/commist/-/commist-1.1.0.tgz", + "integrity": "sha512-rraC8NXWOEjhADbZe9QBNzLAN5Q3fsTPQtBV+fEVj6xKIgDgNiEVE6ZNfHpZOqfQ21YUzfVNUXLOEZquYvQPPg==", + "dependencies": { + "leven": "^2.1.0", + "minimist": "^1.1.0" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "node_modules/concat-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", + "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", + "engines": [ + "node >= 6.0" + ], + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.0.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/concat-stream/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" + }, + "node_modules/core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "node_modules/crc": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/crc/-/crc-3.4.0.tgz", + "integrity": "sha512-ycVC2+4/DLgXXq7QweYi2znhqDuZz6P5TQXnkQo8v15XY/5p/IWeZwsSE31Ifo8w15b8TWLsqhXOjXyilHuQxw==" + }, + "node_modules/date-format": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.11.tgz", + "integrity": "sha512-VS20KRyorrbMCQmpdl2hg5KaOUsda1RbnsJg461FfrcyCUg+pkd0b40BSW4niQyTheww4DBXQnS7HwSrKkipLw==", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" + }, + "node_modules/detect-libc": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz", + "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==", + "engines": { + "node": ">=8" + } + }, + "node_modules/duplexify": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.2.tgz", + "integrity": "sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw==", + "dependencies": { + "end-of-stream": "^1.4.1", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1", + "stream-shift": "^1.0.0" + } + }, + "node_modules/duplexify/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/easy-crc": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/easy-crc/-/easy-crc-0.0.2.tgz", + "integrity": "sha512-h6eqIdhJRe0p271/xZJbM/0klCi13mW5IB7ZEzEGH11yV4QXWAkD4yPErz0fXdhFrd6sZ4Q1k5Iky2kMsMNePw==" + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" + }, + "node_modules/flatted": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", + "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==" + }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, + "node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "node_modules/gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha512-14x4kjc6lkD3ltw589k0NrPD6cCNTD6CWoVUNpB85+DrtONoZn+Rug6xZU5RvSC4+TZPxA5AnBibQYAvZn41Hg==", + "dependencies": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "node_modules/github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==" + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" + }, + "node_modules/has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" + }, + "node_modules/help-me": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/help-me/-/help-me-3.0.0.tgz", + "integrity": "sha512-hx73jClhyk910sidBB7ERlnhMlFsJJIBqSVMFDwPN8o2v9nmp5KgLq1Xz1Bf1fCMMZ6mPrX159iG0VLy/fPMtQ==", + "dependencies": { + "glob": "^7.1.6", + "readable-stream": "^3.6.0" + } + }, + "node_modules/help-me/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, + "node_modules/is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==", + "dependencies": { + "number-is-nan": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "node_modules/js-sdsl": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz", + "integrity": "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/js-sdsl" + } + }, + "node_modules/jsmodbus": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/jsmodbus/-/jsmodbus-4.0.6.tgz", + "integrity": "sha512-gCmjoaERErK5Rn9Lu/BN07fY13MoWV7JKgGzrnkPlQPdPxYcwDhLtYcmpFFpZ4J9NPZZBSezi1UkLZO/DnNppA==", + "dependencies": { + "crc": "3.4.0", + "debug": "^3.1.0" + }, + "bin": { + "jsmodbus": "bin/jsmodbus.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/jsmodbus/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/leven": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", + "integrity": "sha1-wuep93IJTe6dNCAq6KzORoeHVYA=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/log4js": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.5.2.tgz", + "integrity": "sha512-DXtpNtt+KDOMT7RHUDIur/WsSA3rntlUh9Zg4XCdV42wUuMmbFkl38+LZ92Z5QvQA7mD5kAVkLiBSEH/tvUB8A==", + "dependencies": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "flatted": "^3.2.5", + "rfdc": "^1.3.0", + "streamroller": "^3.1.1" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" + }, + "node_modules/moment": { + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", + "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==", + "engines": { + "node": "*" + } + }, + "node_modules/mqtt": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/mqtt/-/mqtt-4.3.7.tgz", + "integrity": "sha512-ew3qwG/TJRorTz47eW46vZ5oBw5MEYbQZVaEji44j5lAUSQSqIEoul7Kua/BatBW0H0kKQcC9kwUHa1qzaWHSw==", + "dependencies": { + "commist": "^1.0.0", + "concat-stream": "^2.0.0", + "debug": "^4.1.1", + "duplexify": "^4.1.1", + "help-me": "^3.0.0", + "inherits": "^2.0.3", + "lru-cache": "^6.0.0", + "minimist": "^1.2.5", + "mqtt-packet": "^6.8.0", + "number-allocator": "^1.0.9", + "pump": "^3.0.0", + "readable-stream": "^3.6.0", + "reinterval": "^1.1.0", + "rfdc": "^1.3.0", + "split2": "^3.1.0", + "ws": "^7.5.5", + "xtend": "^4.0.2" + }, + "bin": { + "mqtt": "bin/mqtt.js", + "mqtt_pub": "bin/pub.js", + "mqtt_sub": "bin/sub.js" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/mqtt-packet": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/mqtt-packet/-/mqtt-packet-6.10.0.tgz", + "integrity": "sha512-ja8+mFKIHdB1Tpl6vac+sktqy3gA8t9Mduom1BA75cI+R9AHnZOiaBQwpGiWnaVJLDGRdNhQmFaAqd7tkKSMGA==", + "dependencies": { + "bl": "^4.0.2", + "debug": "^4.1.1", + "process-nextick-args": "^2.0.1" + } + }, + "node_modules/mqtt/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/nan": { + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.16.0.tgz", + "integrity": "sha512-UdAqHyFngu7TfQKsCBgAA6pWDkT8MAO7d0jyOecVhN5354xbLqdn8mV9Tat9gepAupm0bt2DbeaSC8vS52MuFA==" + }, + "node_modules/napi-build-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", + "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==" + }, + "node_modules/node-abi": { + "version": "3.22.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.22.0.tgz", + "integrity": "sha512-u4uAs/4Zzmp/jjsD9cyFYDXeISfUWaAVWshPmDZOFOv4Xl4SbzTXm53I04C2uRueYJ+0t5PEtLH/owbn2Npf/w==", + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/nodemailer": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.7.tgz", + "integrity": "sha512-rUtR77ksqex/eZRLmQ21LKVH5nAAsVicAtAYudK7JgwenEDZ0UIQ1adUGqErz7sMkWYxWTTU1aeP2Jga6WQyJw==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "dependencies": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "node_modules/number-allocator": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/number-allocator/-/number-allocator-1.0.14.tgz", + "integrity": "sha512-OrL44UTVAvkKdOdRQZIJpLkAdjXGTRda052sN4sO77bKEzYYqWKMBjQvrJFzqygI99gL6Z4u2xctPW1tB8ErvA==", + "dependencies": { + "debug": "^4.3.1", + "js-sdsl": "4.3.0" + } + }, + "node_modules/number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/prebuild-install": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.0.tgz", + "integrity": "sha512-CNcMgI1xBypOyGqjp3wOc8AAo1nMhZS3Cwd3iHIxOdAUbb+YxdNuM4Z5iIrZ8RLvOsf3F3bl7b7xGq6DjQoNYA==", + "dependencies": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^1.0.1", + "node-abi": "^3.3.0", + "npmlog": "^4.0.1", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + }, + "bin": { + "prebuild-install": "bin.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/reinterval": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reinterval/-/reinterval-1.1.0.tgz", + "integrity": "sha1-M2Hs+jymwYKDOA3Qu5VG85D17Oc=" + }, + "node_modules/rfdc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==" + }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/serialport": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/serialport/-/serialport-9.2.8.tgz", + "integrity": "sha512-FsWpMQgSJxi93JgWl5xM1f9/Z8IjRJuaUEoHqLf8FPBLw7gMhInuHOBhI2onQufWIYPGTz3H3oGcu1nCaK1EfA==", + "dependencies": { + "@serialport/binding-mock": "9.2.4", + "@serialport/bindings": "9.2.8", + "@serialport/parser-byte-length": "9.2.4", + "@serialport/parser-cctalk": "9.2.4", + "@serialport/parser-delimiter": "9.2.4", + "@serialport/parser-inter-byte-timeout": "9.2.4", + "@serialport/parser-readline": "9.2.4", + "@serialport/parser-ready": "9.2.4", + "@serialport/parser-regex": "9.2.4", + "@serialport/stream": "9.2.4", + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "node_modules/split2": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", + "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", + "dependencies": { + "readable-stream": "^3.0.0" + } + }, + "node_modules/split2/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==" + }, + "node_modules/streamroller": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.1.1.tgz", + "integrity": "sha512-iPhtd9unZ6zKdWgMeYGfSBuqCngyJy1B/GPi/lTpwGpa3bajuX30GjUVd0/Tn/Xhg0mr4DOSENozz9Y06qyonQ==", + "dependencies": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "fs-extra": "^10.1.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dependencies": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/tar-fs": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "dependencies": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tar-stream/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/total.js": { + "version": "3.4.13", + "resolved": "https://registry.npmjs.org/total.js/-/total.js-3.4.13.tgz", + "integrity": "sha512-lAH4gEixlPFbrE3xfKADAcHfO79IFq2wKa9GTsrgRzIR5MTg3mNH7+4IxvX1pK8faoYb/0oYSJ1YTsAa5hIFFQ==", + "bin": { + "total": "bin/totaljs", + "total.js": "bin/totaljs", + "totaljs": "bin/totaljs", + "totalpackage": "bin/tpm", + "tpm": "bin/tpm" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, + "node_modules/universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "node_modules/wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "node_modules/ws": { + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } + }, + "dependencies": { + "@serialport/binding-abstract": { + "version": "9.2.3", + "resolved": "https://registry.npmjs.org/@serialport/binding-abstract/-/binding-abstract-9.2.3.tgz", + "integrity": "sha512-cQs9tbIlG3P0IrOWyVirqlhWuJ7Ms2Zh9m2108z6Y5UW/iVj6wEOiW8EmK9QX9jmJXYllE7wgGgvVozP5oCj3w==", + "requires": { + "debug": "^4.3.2" + } + }, + "@serialport/binding-mock": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/binding-mock/-/binding-mock-9.2.4.tgz", + "integrity": "sha512-dpEhACCs44oQhh6ajJfJdvQdK38Vq0N4W6iD/gdplglDCK7qXRQCMUjJIeKdS/HSEiWkC3bwumUhUufdsOyT4g==", + "requires": { + "@serialport/binding-abstract": "9.2.3", + "debug": "^4.3.2" + } + }, + "@serialport/bindings": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/@serialport/bindings/-/bindings-9.2.8.tgz", + "integrity": "sha512-hSLxTe0tADZ3LMMGwvEJWOC/TaFQTyPeFalUCsJ1lSQ0k6bPF04JwrtB/C81GetmDBTNRY0GlD0SNtKCc7Dr5g==", + "requires": { + "@serialport/binding-abstract": "9.2.3", + "@serialport/parser-readline": "9.2.4", + "bindings": "^1.5.0", + "debug": "^4.3.2", + "nan": "^2.15.0", + "prebuild-install": "^7.0.0" + } + }, + "@serialport/parser-byte-length": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-byte-length/-/parser-byte-length-9.2.4.tgz", + "integrity": "sha512-sQD/iw4ZMU3xW9PLi0/GlvU6Y623jGeWecbMkO7izUo/6P7gtfv1c9ikd5h0kwL8AoAOpQA1lxdHIKox+umBUg==" + }, + "@serialport/parser-cctalk": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-cctalk/-/parser-cctalk-9.2.4.tgz", + "integrity": "sha512-T4TU5vQMwmo9AB3gQLFDWbfJXlW5jd9guEsB/nqKjFHTv0FXPdZ7DQ2TpSp8RnHWxU3GX6kYTaDO20BKzc8GPQ==" + }, + "@serialport/parser-delimiter": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-delimiter/-/parser-delimiter-9.2.4.tgz", + "integrity": "sha512-4nvTAoYAgkxFiXrkI+3CA49Yd43CODjeszh89EK+I9c8wOZ+etZduRCzINYPiy26g7zO+GRAb9FoPCsY+sYcbQ==" + }, + "@serialport/parser-inter-byte-timeout": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-inter-byte-timeout/-/parser-inter-byte-timeout-9.2.4.tgz", + "integrity": "sha512-SOAdvr0oBQIOCXX198hiTlxs4JTKg9j5piapw5tNq52fwDOWdbYrFneT/wN04UTMKaDrJuEvXq6T4rv4j7nJ5A==" + }, + "@serialport/parser-readline": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-readline/-/parser-readline-9.2.4.tgz", + "integrity": "sha512-Z1/qrZTQUVhNSJP1hd9YfDvq0o7d87rNwAjjRKbVpa7Qi51tG5BnKt43IV3NFMyBlVcRe0rnIb3tJu57E0SOwg==", + "requires": { + "@serialport/parser-delimiter": "9.2.4" + } + }, + "@serialport/parser-ready": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-ready/-/parser-ready-9.2.4.tgz", + "integrity": "sha512-Pyi94Itjl6qAURwIZr/gmZpMAyTmKXThm6vL5DoAWGQjcRHWB0gwv2TY2v7N+mQLJYUKU3cMnvnATXxHm7xjxw==" + }, + "@serialport/parser-regex": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-regex/-/parser-regex-9.2.4.tgz", + "integrity": "sha512-sI/cVvPOYz+Dbv4ZdnW16qAwvXiFf/1pGASQdbveRTlgJDdz7sRNlCBifzfTN2xljwvCTZYqiudKvDdC1TepRQ==" + }, + "@serialport/stream": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/stream/-/stream-9.2.4.tgz", + "integrity": "sha512-bLye8Ub4vUFQGmkh8qEqehr7SE7EJs2yDs0h9jzuL5oKi+F34CFmWkEErO8GAOQ8YNn7p6b3GxUgs+0BrHHDZQ==", + "requires": { + "debug": "^4.3.2" + } + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==" + }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "are-we-there-yet": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", + "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "base64-js": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", + "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==" + }, + "bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "requires": { + "file-uri-to-path": "1.0.0" + } + }, + "bitwise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/bitwise/-/bitwise-2.1.0.tgz", + "integrity": "sha512-XKgAhMXCh4H/3oNwAHAsAO0iC89s9cOiumgYwSHjSobGWxYjv62YhkL9QEdvGP151xypCtMlAfKK79GEcd2eRQ==" + }, + "bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "requires": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "buffer": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz", + "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==", + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" + }, + "chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==" + }, + "commist": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/commist/-/commist-1.1.0.tgz", + "integrity": "sha512-rraC8NXWOEjhADbZe9QBNzLAN5Q3fsTPQtBV+fEVj6xKIgDgNiEVE6ZNfHpZOqfQ21YUzfVNUXLOEZquYvQPPg==", + "requires": { + "leven": "^2.1.0", + "minimist": "^1.1.0" + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "concat-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", + "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.0.2", + "typedarray": "^0.0.6" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "crc": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/crc/-/crc-3.4.0.tgz", + "integrity": "sha512-ycVC2+4/DLgXXq7QweYi2znhqDuZz6P5TQXnkQo8v15XY/5p/IWeZwsSE31Ifo8w15b8TWLsqhXOjXyilHuQxw==" + }, + "date-format": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.11.tgz", + "integrity": "sha512-VS20KRyorrbMCQmpdl2hg5KaOUsda1RbnsJg461FfrcyCUg+pkd0b40BSW4niQyTheww4DBXQnS7HwSrKkipLw==" + }, + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "requires": { + "ms": "2.1.2" + } + }, + "decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "requires": { + "mimic-response": "^3.1.0" + } + }, + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==" + }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" + }, + "detect-libc": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz", + "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==" + }, + "duplexify": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.2.tgz", + "integrity": "sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw==", + "requires": { + "end-of-stream": "^1.4.1", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1", + "stream-shift": "^1.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "easy-crc": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/easy-crc/-/easy-crc-0.0.2.tgz", + "integrity": "sha512-h6eqIdhJRe0p271/xZJbM/0klCi13mW5IB7ZEzEGH11yV4QXWAkD4yPErz0fXdhFrd6sZ4Q1k5Iky2kMsMNePw==" + }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "requires": { + "once": "^1.4.0" + } + }, + "expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==" + }, + "file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" + }, + "flatted": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", + "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==" + }, + "fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, + "fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha512-14x4kjc6lkD3ltw589k0NrPD6cCNTD6CWoVUNpB85+DrtONoZn+Rug6xZU5RvSC4+TZPxA5AnBibQYAvZn41Hg==", + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==" + }, + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" + }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" + }, + "help-me": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/help-me/-/help-me-3.0.0.tgz", + "integrity": "sha512-hx73jClhyk910sidBB7ERlnhMlFsJJIBqSVMFDwPN8o2v9nmp5KgLq1Xz1Bf1fCMMZ6mPrX159iG0VLy/fPMtQ==", + "requires": { + "glob": "^7.1.6", + "readable-stream": "^3.6.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==", + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "js-sdsl": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz", + "integrity": "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==" + }, + "jsmodbus": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/jsmodbus/-/jsmodbus-4.0.6.tgz", + "integrity": "sha512-gCmjoaERErK5Rn9Lu/BN07fY13MoWV7JKgGzrnkPlQPdPxYcwDhLtYcmpFFpZ4J9NPZZBSezi1UkLZO/DnNppA==", + "requires": { + "crc": "3.4.0", + "debug": "^3.1.0" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "requires": { + "ms": "^2.1.1" + } + } + } + }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, + "leven": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", + "integrity": "sha1-wuep93IJTe6dNCAq6KzORoeHVYA=" + }, + "log4js": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.5.2.tgz", + "integrity": "sha512-DXtpNtt+KDOMT7RHUDIur/WsSA3rntlUh9Zg4XCdV42wUuMmbFkl38+LZ92Z5QvQA7mD5kAVkLiBSEH/tvUB8A==", + "requires": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "flatted": "^3.2.5", + "rfdc": "^1.3.0", + "streamroller": "^3.1.1" + } + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "requires": { + "yallist": "^4.0.0" + } + }, + "mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==" + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==" + }, + "mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" + }, + "moment": { + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", + "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==" + }, + "mqtt": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/mqtt/-/mqtt-4.3.7.tgz", + "integrity": "sha512-ew3qwG/TJRorTz47eW46vZ5oBw5MEYbQZVaEji44j5lAUSQSqIEoul7Kua/BatBW0H0kKQcC9kwUHa1qzaWHSw==", + "requires": { + "commist": "^1.0.0", + "concat-stream": "^2.0.0", + "debug": "^4.1.1", + "duplexify": "^4.1.1", + "help-me": "^3.0.0", + "inherits": "^2.0.3", + "lru-cache": "^6.0.0", + "minimist": "^1.2.5", + "mqtt-packet": "^6.8.0", + "number-allocator": "^1.0.9", + "pump": "^3.0.0", + "readable-stream": "^3.6.0", + "reinterval": "^1.1.0", + "rfdc": "^1.3.0", + "split2": "^3.1.0", + "ws": "^7.5.5", + "xtend": "^4.0.2" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "mqtt-packet": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/mqtt-packet/-/mqtt-packet-6.10.0.tgz", + "integrity": "sha512-ja8+mFKIHdB1Tpl6vac+sktqy3gA8t9Mduom1BA75cI+R9AHnZOiaBQwpGiWnaVJLDGRdNhQmFaAqd7tkKSMGA==", + "requires": { + "bl": "^4.0.2", + "debug": "^4.1.1", + "process-nextick-args": "^2.0.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "nan": { + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.16.0.tgz", + "integrity": "sha512-UdAqHyFngu7TfQKsCBgAA6pWDkT8MAO7d0jyOecVhN5354xbLqdn8mV9Tat9gepAupm0bt2DbeaSC8vS52MuFA==" + }, + "napi-build-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", + "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==" + }, + "node-abi": { + "version": "3.22.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.22.0.tgz", + "integrity": "sha512-u4uAs/4Zzmp/jjsD9cyFYDXeISfUWaAVWshPmDZOFOv4Xl4SbzTXm53I04C2uRueYJ+0t5PEtLH/owbn2Npf/w==", + "requires": { + "semver": "^7.3.5" + } + }, + "nodemailer": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.7.tgz", + "integrity": "sha512-rUtR77ksqex/eZRLmQ21LKVH5nAAsVicAtAYudK7JgwenEDZ0UIQ1adUGqErz7sMkWYxWTTU1aeP2Jga6WQyJw==" + }, + "npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "number-allocator": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/number-allocator/-/number-allocator-1.0.14.tgz", + "integrity": "sha512-OrL44UTVAvkKdOdRQZIJpLkAdjXGTRda052sN4sO77bKEzYYqWKMBjQvrJFzqygI99gL6Z4u2xctPW1tB8ErvA==", + "requires": { + "debug": "^4.3.1", + "js-sdsl": "4.3.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==" + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==" + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==" + }, + "prebuild-install": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.0.tgz", + "integrity": "sha512-CNcMgI1xBypOyGqjp3wOc8AAo1nMhZS3Cwd3iHIxOdAUbb+YxdNuM4Z5iIrZ8RLvOsf3F3bl7b7xGq6DjQoNYA==", + "requires": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^1.0.1", + "node-abi": "^3.3.0", + "npmlog": "^4.0.1", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + } + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + } + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "reinterval": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reinterval/-/reinterval-1.1.0.tgz", + "integrity": "sha1-M2Hs+jymwYKDOA3Qu5VG85D17Oc=" + }, + "rfdc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==" + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "requires": { + "lru-cache": "^6.0.0" + } + }, + "serialport": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/serialport/-/serialport-9.2.8.tgz", + "integrity": "sha512-FsWpMQgSJxi93JgWl5xM1f9/Z8IjRJuaUEoHqLf8FPBLw7gMhInuHOBhI2onQufWIYPGTz3H3oGcu1nCaK1EfA==", + "requires": { + "@serialport/binding-mock": "9.2.4", + "@serialport/bindings": "9.2.8", + "@serialport/parser-byte-length": "9.2.4", + "@serialport/parser-cctalk": "9.2.4", + "@serialport/parser-delimiter": "9.2.4", + "@serialport/parser-inter-byte-timeout": "9.2.4", + "@serialport/parser-readline": "9.2.4", + "@serialport/parser-ready": "9.2.4", + "@serialport/parser-regex": "9.2.4", + "@serialport/stream": "9.2.4", + "debug": "^4.3.2" + } + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==" + }, + "simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "requires": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "split2": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", + "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", + "requires": { + "readable-stream": "^3.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==" + }, + "streamroller": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.1.1.tgz", + "integrity": "sha512-iPhtd9unZ6zKdWgMeYGfSBuqCngyJy1B/GPi/lTpwGpa3bajuX30GjUVd0/Tn/Xhg0mr4DOSENozz9Y06qyonQ==", + "requires": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "fs-extra": "^10.1.0" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" + }, + "tar-fs": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "requires": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "requires": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "total.js": { + "version": "3.4.13", + "resolved": "https://registry.npmjs.org/total.js/-/total.js-3.4.13.tgz", + "integrity": "sha512-lAH4gEixlPFbrE3xfKADAcHfO79IFq2wKa9GTsrgRzIR5MTg3mNH7+4IxvX1pK8faoYb/0oYSJ1YTsAa5hIFFQ==" + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, + "universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==" + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "requires": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "ws": { + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "requires": {} + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } + } +} diff --git a/RVO37/package.json b/RVO37/package.json new file mode 100755 index 0000000..7f7c795 --- /dev/null +++ b/RVO37/package.json @@ -0,0 +1,30 @@ +{ + "name": "emptyproject", + "description": "Total.js empty project.", + "version": "1.0.0", + "main": "debug.js", + "dependencies": { + "bitwise": "^2.1.0", + "easy-crc": "0.0.2", + "jsmodbus": "^4.0.6", + "log4js": "^6.3.0", + "moment": "^2.30.1", + "mqtt": "^4.2.6", + "nodemailer": "^6.9.7", + "serialport": "^9.2.8", + "total.js": "^3.4.13" + }, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "https://github.com/totaljs/emptyproject-flow" + }, + "keywords": [ + "empty", + "project" + ], + "author": "Peter Širka", + "license": "MIT" +} diff --git a/RVO37/release.js b/RVO37/release.js new file mode 100755 index 0000000..02d52ff --- /dev/null +++ b/RVO37/release.js @@ -0,0 +1,15 @@ +// =================================================== +// FOR PRODUCTION +// Total.js - framework for Node.js platform +// https://www.totaljs.com +// =================================================== + +const options = {'ip':'0.0.0.0', 'port':12345}; + +// options.ip = '127.0.0.1'; +// options.port = parseInt(process.argv[2]); +// options.config = { name: 'Total.js' }; +// options.sleep = 3000; + +require('total.js').http('release', options); +// require('total.js').cluster.http(5, 'release', options); diff --git a/RVO37/release.js.json b/RVO37/release.js.json new file mode 100755 index 0000000..056e031 --- /dev/null +++ b/RVO37/release.js.json @@ -0,0 +1,34 @@ +{ + "pid": 409, + "stats": [ + { + "id": null, + "version": { + "node": "v14.18.1", + "total": "3.4.13", + "app": "1.0.0" + }, + "pid": 409, + "thread": "", + "mode": "release", + "overload": 0, + "date": "2025-10-16T00:25:28.520Z", + "memory": 24.3, + "rm": 0, + "fm": 0, + "wm": 0, + "mm": 0, + "om": 2, + "em": 0, + "dbrm": 0, + "dbwm": 0, + "usage": 0, + "requests": 0, + "pending": 0, + "errors": 0, + "timeouts": 0, + "uptime": 718, + "online": 0 + } + ] +} \ No newline at end of file diff --git a/RVO37/report_data.log b/RVO37/report_data.log new file mode 100755 index 0000000..9808902 --- /dev/null +++ b/RVO37/report_data.log @@ -0,0 +1,165 @@ +{ + "name": "rvo_senica_37_ip111", + "time": "2025-10-15T13:28:43.642Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_37_ip111", + "time": "2025-10-15T14:28:43.641Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_37_ip111", + "time": "2025-10-15T15:28:43.641Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_37_ip111", + "time": "2025-10-15T17:33:39.646Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "37/30_1L_2882_NEMA" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_37_ip111", + "time": "2025-10-15T18:33:39.646Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "37/30_1L_2882_NEMA" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_37_ip111", + "time": "2025-10-15T19:33:39.648Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "37/30_1L_2882_NEMA" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_37_ip111", + "time": "2025-10-15T20:33:39.648Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "37/30_1L_2882_NEMA" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_37_ip111", + "time": "2025-10-15T21:33:39.649Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "37/30_1L_2882_NEMA" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_37_ip111", + "time": "2025-10-15T22:33:39.649Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "37/30_1L_2882_NEMA" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_37_ip111", + "time": "2025-10-15T23:33:39.649Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "37/30_1L_2882_NEMA" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +} \ No newline at end of file From c6805a48f574d13a37c60f3b75f06332bfc3f37b Mon Sep 17 00:00:00 2001 From: Jakub Klena Date: Thu, 16 Oct 2025 02:26:13 +0200 Subject: [PATCH 20/30] Backup senica-RVO38 on 16.10.2025 --- RVO38/addSwitch.py | 36 + RVO38/cloud_topic.py | 76 + RVO38/config | 12 + RVO38/createNode.py | 43 + RVO38/databases/accelerometer_db.js | 3055 ++++++++++++++++ RVO38/databases/modbus_config.js | 114 + RVO38/databases/nodes.table | 67 + .../nodes_original/nodes_original.table | 1 + RVO38/databases/notifications.table | 41 + RVO38/databases/pins.table | 15 + RVO38/databases/relays.table | 6 + RVO38/databases/settings.table | 2 + RVO38/databases/tbdata.nosql | 4 + RVO38/databases/tbdatacloud.nosql | 3 + RVO38/databases/total_energy.js | 38 + RVO38/debug.js | 16 + RVO38/err.txt | 66 + RVO38/flow/cloudmqttconnect.js | 357 ++ RVO38/flow/cmd_manager.js | 3071 ++++++++++++++++ RVO38/flow/code.js | 90 + RVO38/flow/comment.js | 11 + RVO38/flow/count.js | 60 + RVO38/flow/db_connector.js | 286 ++ RVO38/flow/db_init.js | 113 + RVO38/flow/debug.js | 100 + RVO38/flow/designer.json | 3102 +++++++++++++++++ RVO38/flow/dido_controller.js | 1486 ++++++++ RVO38/flow/helper/DataToTbHandler.js | 187 + RVO38/flow/helper/ErrorToServiceHandler.js | 91 + RVO38/flow/helper/db_helper.js | 44 + RVO38/flow/helper/logger.js | 30 + RVO38/flow/helper/md5.js | 5 + RVO38/flow/helper/notification_reporter.js | 121 + RVO38/flow/helper/register.js | 144 + RVO38/flow/helper/serialport_helper.js | 99 + RVO38/flow/helper/suncalc.js | 317 ++ RVO38/flow/helper/utils.js | 161 + RVO38/flow/httprequest.js | 137 + RVO38/flow/httpresponse.js | 76 + RVO38/flow/httproute.js | 326 ++ RVO38/flow/infosender.js | 81 + RVO38/flow/modbus_reader.js | 346 ++ RVO38/flow/monitorconsumption.js | 156 + RVO38/flow/monitordisk.js | 96 + RVO38/flow/monitormemory.js | 87 + RVO38/flow/nodesdb_changecheck.js | 77 + RVO38/flow/show_dbdata.js | 243 ++ RVO38/flow/slack_filter.js | 188 + RVO38/flow/thermometer.js | 99 + RVO38/flow/trigger.js | 79 + RVO38/flow/variables.txt | 0 RVO38/flow/virtualwirein.js | 43 + RVO38/flow/virtualwireout.js | 41 + RVO38/flow/wsmqttpublish.js | 448 +++ RVO38/monitor.txt | 282 ++ RVO38/package-lock.json | 2139 ++++++++++++ RVO38/package.json | 30 + RVO38/release.js | 15 + RVO38/release.js.json | 34 + RVO38/report_data.log | 163 + 60 files changed, 18656 insertions(+) create mode 100755 RVO38/addSwitch.py create mode 100755 RVO38/cloud_topic.py create mode 100755 RVO38/config create mode 100755 RVO38/createNode.py create mode 100755 RVO38/databases/accelerometer_db.js create mode 100755 RVO38/databases/modbus_config.js create mode 100755 RVO38/databases/nodes.table create mode 100755 RVO38/databases/nodes_original/nodes_original.table create mode 100755 RVO38/databases/notifications.table create mode 100755 RVO38/databases/pins.table create mode 100755 RVO38/databases/relays.table create mode 100755 RVO38/databases/settings.table create mode 100755 RVO38/databases/tbdata.nosql create mode 100755 RVO38/databases/tbdatacloud.nosql create mode 100755 RVO38/databases/total_energy.js create mode 100755 RVO38/debug.js create mode 100755 RVO38/err.txt create mode 100755 RVO38/flow/cloudmqttconnect.js create mode 100755 RVO38/flow/cmd_manager.js create mode 100755 RVO38/flow/code.js create mode 100755 RVO38/flow/comment.js create mode 100755 RVO38/flow/count.js create mode 100755 RVO38/flow/db_connector.js create mode 100755 RVO38/flow/db_init.js create mode 100755 RVO38/flow/debug.js create mode 100755 RVO38/flow/designer.json create mode 100755 RVO38/flow/dido_controller.js create mode 100755 RVO38/flow/helper/DataToTbHandler.js create mode 100755 RVO38/flow/helper/ErrorToServiceHandler.js create mode 100755 RVO38/flow/helper/db_helper.js create mode 100755 RVO38/flow/helper/logger.js create mode 100755 RVO38/flow/helper/md5.js create mode 100755 RVO38/flow/helper/notification_reporter.js create mode 100755 RVO38/flow/helper/register.js create mode 100755 RVO38/flow/helper/serialport_helper.js create mode 100755 RVO38/flow/helper/suncalc.js create mode 100755 RVO38/flow/helper/utils.js create mode 100755 RVO38/flow/httprequest.js create mode 100755 RVO38/flow/httpresponse.js create mode 100755 RVO38/flow/httproute.js create mode 100755 RVO38/flow/infosender.js create mode 100755 RVO38/flow/modbus_reader.js create mode 100755 RVO38/flow/monitorconsumption.js create mode 100755 RVO38/flow/monitordisk.js create mode 100755 RVO38/flow/monitormemory.js create mode 100755 RVO38/flow/nodesdb_changecheck.js create mode 100755 RVO38/flow/show_dbdata.js create mode 100755 RVO38/flow/slack_filter.js create mode 100755 RVO38/flow/thermometer.js create mode 100755 RVO38/flow/trigger.js create mode 100755 RVO38/flow/variables.txt create mode 100755 RVO38/flow/virtualwirein.js create mode 100755 RVO38/flow/virtualwireout.js create mode 100755 RVO38/flow/wsmqttpublish.js create mode 100755 RVO38/monitor.txt create mode 100755 RVO38/package-lock.json create mode 100755 RVO38/package.json create mode 100755 RVO38/release.js create mode 100755 RVO38/release.js.json create mode 100755 RVO38/report_data.log diff --git a/RVO38/addSwitch.py b/RVO38/addSwitch.py new file mode 100755 index 0000000..c35e96b --- /dev/null +++ b/RVO38/addSwitch.py @@ -0,0 +1,36 @@ +import os + +def process_set_file(): + """ + Checks if /root/flowserver exists, reads set.txt, and modifies the second line. + """ + default_folder = "/root/flowserver" if os.path.exists("/root/flowserver") else "/home/unipi/flowserver" + flag = 1 if default_folder == "/root/flowserver" else 0 + + try: + with open("/home/unipi/flowserver/databases/settings.table", "r") as f: + lines = f.readlines() + + if len(lines) >= 2: + lines[0] = lines[0].rstrip('\n') + "|main_switch:boolean\n" + second_line = lines[1].strip() # remove trailing newline + last_pipe_index = second_line.rfind("|") + + if last_pipe_index != -1: + modified_line = second_line[:last_pipe_index + 1] + str(flag) + "|" + second_line[last_pipe_index + 1:] + lines[1] = modified_line + else: + print("Warning: No '|' character found in the second line of set.txt") + + with open("/home/unipi/flowserver/databases/settings.table", "w") as f: + f.writelines(lines) + else: + print("Warning: settings.table has less than two lines.") + + except FileNotFoundError: + print("Error: settings.table not found.") + except Exception as e: + print(e) + +# if __name__ == "__main__": +process_set_file() diff --git a/RVO38/cloud_topic.py b/RVO38/cloud_topic.py new file mode 100755 index 0000000..77c31f1 --- /dev/null +++ b/RVO38/cloud_topic.py @@ -0,0 +1,76 @@ +# import os +# +# def modify_file(file_path): +# """ +# Modifies the given file by: +# 1. Appending "|cloud_topic" to the first line. +# 2. Inserting the text from the third "." to the first "|" on the second line after the last "|" character. +# +# Args: +# file_path (str): The path to the file to be modified. +# """ +# +# with open(file_path, 'r+') as f: +# lines = f.readlines() +# +# # Modify the first line +# lines[0] += "|cloud_topic:string" +# +# # Modify the second line +# second_line = lines[1].strip() # Remove leading/trailing whitespace +# first_pipe_index = second_line.find('|') +# third_dot_index = second_line.find('.', second_line.find('.', second_line.find('.') + 1) + 1) +# text_to_insert = second_line[third_dot_index:first_pipe_index] +# +# last_pipe_index = second_line.rfind('|') +# lines[1] = second_line[:last_pipe_index + 1] + text_to_insert + "|" + second_line[last_pipe_index + 1:] +# +# print(first_pipe_index, third_dot_index, text_to_insert, last_pipe_index) +# # Write the modified lines back to the file +# # f.seek(0) +# # f.writelines(lines) +# # f.truncate() +# +# # Example usage: +# file_path = "settings.table" # Replace with the actual file path +# modify_file(file_path) +# + + +def modify_file(file_path): + """ + Modifies the given file by: + 1. Appending "|cloud_topic" to the first line. + 2. Inserting the text between the third "." and the second "|" on the second line after the last "|" character. + + Args: + file_path (str): The path to the file to be modified. + """ + + with open(file_path, 'r+') as f: + lines = f.readlines() + + first_line = lines[0].strip() + first_line += "|cloud_topic:string\n" + # Modify the first line + lines[0] = first_line + + # Modify the second line + second_line = lines[1].strip() # Remove leading/trailing whitespace + first_pipe_index = second_line.find('|') + second_pipe_index = second_line.find('|', first_pipe_index + 1) + third_dot_index = second_line.find('.', second_line.find('.', second_line.find('.') + 1) + 1) + text_to_insert = "u" + second_line[third_dot_index+1:second_pipe_index] + + last_pipe_index = second_line.rfind('|') + lines[1] = second_line[:last_pipe_index + 1] + text_to_insert + "|" + second_line[last_pipe_index + 1:] + + print(first_pipe_index, third_dot_index, text_to_insert, last_pipe_index) + # Write the modified lines back to the file + f.seek(0) + f.writelines(lines) + f.truncate() + +# Example usage: +file_path = "/home/unipi/flowserver/databases/settings.table" # Replace with the actual file path +modify_file(file_path) diff --git a/RVO38/config b/RVO38/config new file mode 100755 index 0000000..cd0a8a9 --- /dev/null +++ b/RVO38/config @@ -0,0 +1,12 @@ +name : Total.js Flow +default_timezone : Europe/Bratislava + +// Packages settings +package#flow (Object) : { url: '/' } + + +table.relays : line:number|tbname:string|contactor:number|profile:string +table.nodes : node:number|pole_number:string|node_type:string|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|project_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|cloud_topic:string|has_main_switch:boolean|daily_report:boolean|send_changed_node_numbers:boolean +table.pins : pin:string|type:string|line:number +table.notifications : key:string|weight:string|sk:string|en:string diff --git a/RVO38/createNode.py b/RVO38/createNode.py new file mode 100755 index 0000000..a8cea91 --- /dev/null +++ b/RVO38/createNode.py @@ -0,0 +1,43 @@ +print("zaciname") +import re, json + +search_str = '|' +final = [] +counter = 1 +with open("/home/unipi/flowserver/databases/nodes.table", 'r') as file: +# with open("/home/rasta5man/dev/oms/flowserver/databases/nodes.table", 'r') as file: + # Read each line in the file + for line in file: + # Print each line + line = line.strip() + print(line) + if counter != 1: + i = [m.start() for m in re.finditer(re.escape(search_str), line)] + node = line[ i[0] + 1 : i[1] ] + tbname = line[ i[3] + 1 : i[4] ] + final.append({node:tbname}) + counter += 1 +print(json.dumps(final)) +f = open("/home/unipi/flowserver/databases/nodes_original/nodes_original.table", "w") +f.write(json.dumps(final)) +f.close() + + +# +# # ``d`` has to be replaced with a different character +# old_character = "'" +# +# # ``t`` will replace ``d` +# new_character = '"' +# resultant_string = 0; +# with open("/home/unipi/flowserver/databases/nodes_original/nodes_original.table", 'r') as file: +# for line in file: +# resultant_string = re.sub("'", '"', line) +# +# resultant_string = re.sub(" ", "", resultant_string) +# print(resultant_string) +# +# f = open("/home/unipi/flowserver/databases/nodes_original/nodes_original.table", "w") +# f.write(str(resultant_string)) +# f.close() +# diff --git a/RVO38/databases/accelerometer_db.js b/RVO38/databases/accelerometer_db.js new file mode 100755 index 0000000..fdfc7fd --- /dev/null +++ b/RVO38/databases/accelerometer_db.js @@ -0,0 +1,3055 @@ +let naklony = { + "3993": { "label": "1/3A", "naklon": 0 }, + "3989": { "label": "1/3B", "naklon": 15 }, + "3976": { "label": "1/1", "naklon": 0 }, + "4181": { "label": "1/2", "naklon": 0 }, + "4376": { "label": "1/4", "naklon": 15 }, + "3868": { "label": "1/5", "naklon": 15 }, + "3728": { "label": "1/6", "naklon": 15 }, + "3730": { "label": "1/7", "naklon": 0 }, + "4374": { "label": "1/8", "naklon": 0 }, + "3718": { "label": "1/9", "naklon": 15 }, + "4375": { "label": "1/10", "naklon": 15 }, + "4172": { "label": "1/11", "naklon": 15 }, + "4176": { "label": "1/12", "naklon": 15 }, + "3800": { "label": "2/1", "naklon": 5 }, + "3823": { "label": "2/2", "naklon": 5 }, + "3905": { "label": "2/3", "naklon": 5 }, + "3803": { "label": "2/4", "naklon": 5 }, + "3817": { "label": "2/5", "naklon": 5 }, + "3818": { "label": "2/6", "naklon": 5 }, + "3811": { "label": "2/7", "naklon": 5 }, + "3915": { "label": "2/8", "naklon": 5 }, + "3843": { "label": "2/9", "naklon": 10 }, + "3827": { "label": "2/10", "naklon": 10 }, + "4220": { "label": "2/11", "naklon": 10 }, + "3826": { "label": "2/12", "naklon": 10 }, + "3834": { "label": "2/13", "naklon": 10 }, + "3838": { "label": "2/14", "naklon": 10 }, + "2823": { "label": "2/15", "naklon": 10 }, + "3750": { "label": "2/16", "naklon": 10 }, + "3378": { "label": "2/17", "naklon": 0 }, + "3376": { "label": "2/18", "naklon": 0 }, + "3379": { "label": "2/19", "naklon": 0 }, + "3285": { "label": "2/20", "naklon": 0 }, + "3382": { "label": "2/21", "naklon": 0 }, + "3383": { "label": "2/22", "naklon": 0 }, + "3375": { "label": "2/24", "naklon": 0 }, + "3381": { "label": "2/25", "naklon": 0 }, + "3380": { "label": "2/26", "naklon": 0 }, + "3828": { "label": "2/27", "naklon": 10 }, + "3377": { "label": "2/28", "naklon": 0 }, + "3591": { "label": "7/1", "naklon": 0 }, + "3587": { "label": "7/2", "naklon": 0 }, + "3468": { "label": "7/3", "naklon": 0 }, + "3466": { "label": "7/4", "naklon": 0 }, + "3474": { "label": "7/5", "naklon": 0 }, + "3481": { "label": "7/6", "naklon": 0 }, + "3589": { "label": "7/7", "naklon": 0 }, + "3472": { "label": "7/8", "naklon": 0 }, + "3473": { "label": "7/9", "naklon": 0 }, + "3584": { "label": "7/10", "naklon": 0 }, + "3571": { "label": "7/11", "naklon": 0 }, + "3476": { "label": "7/12", "naklon": 0 }, + "3590": { "label": "7/13", "naklon": 0 }, + "3478": { "label": "7/14", "naklon": 0 }, + "3471": { "label": "7/15", "naklon": 0 }, + "3467": { "label": "7/16", "naklon": 0 }, + "3479": { "label": "7/17", "naklon": 0 }, + "3480": { "label": "7/18", "naklon": 0 }, + "3477": { "label": "7/19", "naklon": 0 }, + "3362": { "label": "12/1", "naklon": 0 }, + "3355": { "label": "12/2", "naklon": 0 }, + "3356": { "label": "12/3", "naklon": 0 }, + "3349": { "label": "12/4", "naklon": 0 }, + "3357": { "label": "12/5", "naklon": 0 }, + "3350": { "label": "12/6", "naklon": 0 }, + "3353": { "label": "12/7", "naklon": 0 }, + "3539": { "label": "12/8", "naklon": 0 }, + "3050": { "label": "12/9", "naklon": 0 }, + "3361": { "label": "12/10", "naklon": 0 }, + "3360": { "label": "12/11", "naklon": 0 }, + "3358": { "label": "12/12", "naklon": 0 }, + "3541": { "label": "12/13", "naklon": 0 }, + "3551": { "label": "12/14", "naklon": 0 }, + "3514": { "label": "12/15", "naklon": 0 }, + "3547": { "label": "12/16", "naklon": 0 }, + "3562": { "label": "12/17", "naklon": 0 }, + "3525": { "label": "12/18", "naklon": 0 }, + "3558": { "label": "12/19", "naklon": 0 }, + "3511": { "label": "12/20", "naklon": 0 }, + "3058": { "label": "12/21", "naklon": 0 }, + "3062": { "label": "12/22", "naklon": 0 }, + "3070": { "label": "12/23", "naklon": 0 }, + "3447": { "label": "12/24", "naklon": 0 }, + "3056": { "label": "12/25", "naklon": 0 }, + "3057": { "label": "12/26", "naklon": 0 }, + "3071": { "label": "12/27", "naklon": 0 }, + "3061": { "label": "12/28", "naklon": 0 }, + "3069": { "label": "12/29", "naklon": 0 }, + "3077": { "label": "12/30", "naklon": 0 }, + "3080": { "label": "12/31", "naklon": 0 }, + "3081": { "label": "12/32", "naklon": 0 }, + "3078": { "label": "12/33", "naklon": 0 }, + "4037": { "label": "12/34", "naklon": 0 }, + "3067": { "label": "12/35", "naklon": 0 }, + "3051": { "label": "12/36", "naklon": 0 }, + "2924": { "label": "12/37", "naklon": 0 }, + "3060": { "label": "12/38", "naklon": 0 }, + "3073": { "label": "12/39", "naklon": 0 }, + "3469": { "label": "12/40", "naklon": 0 }, + "2923": { "label": "12/41", "naklon": 0 }, + "2925": { "label": "12/42", "naklon": 0 }, + "3359": { "label": "12/43", "naklon": 0 }, + "3055": { "label": "12/44", "naklon": 0 }, + "2922": { "label": "12/45", "naklon": 0 }, + "3084": { "label": "12/46", "naklon": 0 }, + "3064": { "label": "12/47", "naklon": 0 }, + "3066": { "label": "12/48", "naklon": 0 }, + "3072": { "label": "12/49", "naklon": 0 }, + "3415": { "label": "13/13A", "naklon": 0 }, + "3409": { "label": "13/13B", "naklon": 0 }, + "3399": { "label": "13/13C", "naklon": 0 }, + "3410": { "label": "13/29A", "naklon": 0 }, + "3407": { "label": "13/29B", "naklon": 0 }, + "3405": { "label": "13/34A", "naklon": 0 }, + "3404": { "label": "13/34B", "naklon": 0 }, + "3392": { "label": "13/45A", "naklon": 0 }, + "3386": { "label": "13/45B", "naklon": 0 }, + "3303": { "label": "13/60A", "naklon": 3 }, + "3302": { "label": "13/60B", "naklon": 3 }, + "3319": { "label": "13/70A", "naklon": 6 }, + "3317": { "label": "13/70B", "naklon": 6 }, + "3326": { "label": "13/70C", "naklon": 6 }, + "3351": { "label": "13/73A", "naklon": 6 }, + "3313": { "label": "13/73B", "naklon": 6 }, + "3316": { "label": "13/83A", "naklon": 0 }, + "3320": { "label": "13/83B", "naklon": 0 }, + "3336": { "label": "13/95A", "naklon": 0 }, + "3323": { "label": "13/95B", "naklon": 0 }, + "3339": { "label": "13/98A", "naklon": 0 }, + "3333": { "label": "13/98B", "naklon": 0 }, + "3425": { "label": "13/1", "naklon": 0 }, + "3419": { "label": "13/2", "naklon": 0 }, + "3416": { "label": "13/3", "naklon": 0 }, + "3332": { "label": "13/4", "naklon": 0 }, + "3422": { "label": "13/5", "naklon": 0 }, + "3417": { "label": "13/6", "naklon": 0 }, + "3418": { "label": "13/7", "naklon": 0 }, + "3424": { "label": "13/8", "naklon": 0 }, + "3334": { "label": "13/9", "naklon": 0 }, + "4363": { "label": "13/10", "naklon": 0 }, + "3423": { "label": "13/11", "naklon": 0 }, + "3406": { "label": "13/12", "naklon": 0 }, + "3411": { "label": "13/14", "naklon": 0 }, + "3412": { "label": "13/15", "naklon": 0 }, + "3413": { "label": "13/16", "naklon": 0 }, + "3414": { "label": "13/17", "naklon": 0 }, + "3391": { "label": "13/18", "naklon": 0 }, + "3370": { "label": "13/19", "naklon": 0 }, + "3369": { "label": "13/20", "naklon": 0 }, + "3408": { "label": "13/21", "naklon": 0 }, + "3393": { "label": "13/22", "naklon": 0 }, + "3128": { "label": "13/23", "naklon": 0 }, + "3197": { "label": "13/24", "naklon": 0 }, + "4364": { "label": "13/25", "naklon": 0 }, + "3155": { "label": "13/26", "naklon": 0 }, + "3196": { "label": "13/27", "naklon": 0 }, + "3144": { "label": "13/28", "naklon": 0 }, + "3150": { "label": "13/30", "naklon": 0 }, + "3390": { "label": "13/31", "naklon": 0 }, + "3401": { "label": "13/32", "naklon": 0 }, + "3275": { "label": "13/33", "naklon": 0 }, + "3371": { "label": "13/35", "naklon": 0 }, + "3389": { "label": "13/36", "naklon": 0 }, + "3388": { "label": "13/37", "naklon": 0 }, + "3365": { "label": "13/38", "naklon": 0 }, + "3363": { "label": "13/39", "naklon": 0 }, + "3397": { "label": "13/40", "naklon": 0 }, + "3567": { "label": "13/40/1", "naklon": 0 }, + "3387": { "label": "13/41", "naklon": 0 }, + "3403": { "label": "13/42", "naklon": 0 }, + "3147": { "label": "13/43", "naklon": 0 }, + "3141": { "label": "13/44", "naklon": 0 }, + "3364": { "label": "13/46", "naklon": 0 }, + "3367": { "label": "13/47", "naklon": 0 }, + "3368": { "label": "13/48", "naklon": 0 }, + "3402": { "label": "13/49", "naklon": 0 }, + "3366": { "label": "13/50", "naklon": 0 }, + "3395": { "label": "13/51", "naklon": 0 }, + "3372": { "label": "13/52", "naklon": 0 }, + "3394": { "label": "13/53", "naklon": 0 }, + "3308": { "label": "13/54", "naklon": 0 }, + "3847": { "label": "13/54/1", "naklon": 0 }, + "3312": { "label": "13/55", "naklon": 3 }, + "3309": { "label": "13/56", "naklon": 3 }, + "3311": { "label": "13/57", "naklon": 3 }, + "3310": { "label": "13/58", "naklon": 3 }, + "4365": { "label": "13/59", "naklon": 3 }, + "4093": { "label": "13/60/1", "naklon": 3 }, + "3304": { "label": "13/61", "naklon": 3 }, + "3307": { "label": "13/62", "naklon": 3 }, + "3271": { "label": "13/63", "naklon": 3 }, + "3301": { "label": "13/64", "naklon": 3 }, + "4366": { "label": "13/65", "naklon": 3 }, + "3300": { "label": "13/66", "naklon": 3 }, + "3185": { "label": "13/67", "naklon": 0 }, + "3184": { "label": "13/68", "naklon": 0 }, + "3188": { "label": "13/69", "naklon": 0 }, + "3343": { "label": "13/71", "naklon": 6 }, + "3819": { "label": "13/71/1", "naklon": 6 }, + "3880": { "label": "13/71/2", "naklon": 6 }, + "3348": { "label": "13/72", "naklon": 6 }, + "3344": { "label": "13/74", "naklon": 6 }, + "3346": { "label": "13/75", "naklon": 6 }, + "3597": { "label": "13/75/1", "naklon": 6 }, + "3345": { "label": "13/76", "naklon": 6 }, + "3322": { "label": "13/77", "naklon": 0 }, + "3325": { "label": "13/78", "naklon": 0 }, + "4310": { "label": "13/78/1", "naklon": 0 }, + "3315": { "label": "13/79", "naklon": 0 }, + "3328": { "label": "13/80", "naklon": 0 }, + "3321": { "label": "13/81", "naklon": 0 }, + "3324": { "label": "13/82", "naklon": 0 }, + "3140": { "label": "13/84", "naklon": 0 }, + "3153": { "label": "13/85", "naklon": 0 }, + "3145": { "label": "13/86", "naklon": 0 }, + "3134": { "label": "13/87", "naklon": 0 }, + "3151": { "label": "13/88", "naklon": 0 }, + "3143": { "label": "13/89", "naklon": 0 }, + "3318": { "label": "13/90", "naklon": 0 }, + "3347": { "label": "13/91", "naklon": 0 }, + "3314": { "label": "13/94", "naklon": 0 }, + "3331": { "label": "13/96", "naklon": 0 }, + "3327": { "label": "13/97", "naklon": 0 }, + "3329": { "label": "13/99", "naklon": 0 }, + "3337": { "label": "13/100", "naklon": 0 }, + "3330": { "label": "13/101", "naklon": 0 }, + "3335": { "label": "13/102", "naklon": 0 }, + "3420": { "label": "13/103", "naklon": 0 }, + "3421": { "label": "13/104", "naklon": 0 }, + "4361": { "label": "13/105", "naklon": 0 }, + "4362": { "label": "13/106", "naklon": 0 }, + "3526": { "label": "13/107", "naklon": 0 }, + "4424": { "label": "13/108", "naklon": null }, + "3561": { "label": "13/109", "naklon": null }, + "3527": { "label": "13/110", "naklon": null }, + "3521": { "label": "13/111", "naklon": null }, + "3552": { "label": "13/112", "naklon": null }, + "3544": { "label": "13/113", "naklon": null }, + "3534": { "label": "13/114", "naklon": null }, + "3516": { "label": "13/115", "naklon": null }, + "3513": { "label": "13/116", "naklon": null }, + "3565": { "label": "13/117", "naklon": null }, + "3866": { "label": "13/118", "naklon": null }, + "3136": { "label": "14/1", "naklon": 0 }, + "3137": { "label": "14/2", "naklon": 0 }, + "3135": { "label": "14/3", "naklon": 0 }, + "3149": { "label": "14/4", "naklon": 0 }, + "3142": { "label": "14/5", "naklon": 0 }, + "3342": { "label": "14/6", "naklon": 0 }, + "3340": { "label": "14/7", "naklon": 0 }, + "3152": { "label": "14/8", "naklon": 0 }, + "3886": { "label": "14/9", "naklon": 0 }, + "3341": { "label": "14/10", "naklon": null }, + "3352": { "label": "14/11", "naklon": null }, + "3396": { "label": "15/1", "naklon": 5 }, + "2784": { "label": "15/2", "naklon": 5 }, + "2788": { "label": "15/3", "naklon": 5 }, + "2801": { "label": "15/4", "naklon": 5 }, + "2815": { "label": "15/5", "naklon": 5 }, + "2829": { "label": "15/6", "naklon": 5 }, + "2796": { "label": "15/7", "naklon": 5 }, + "2803": { "label": "15/8", "naklon": 5 }, + "4304": { "label": "15/8/1", "naklon": 5 }, + "4311": { "label": "15/8/2", "naklon": 5 }, + "2821": { "label": "15/9", "naklon": 5 }, + "3400": { "label": "15/10", "naklon": 5 }, + "2799": { "label": "15/11", "naklon": 5 }, + "2804": { "label": "15/12", "naklon": 5 }, + "4303": { "label": "15/12/1", "naklon": 5 }, + "4309": { "label": "15/12/2", "naklon": 5 }, + "2806": { "label": "15/13", "naklon": 5 }, + "2787": { "label": "15/14", "naklon": 5 }, + "2809": { "label": "15/15", "naklon": 5 }, + "2814": { "label": "15/16", "naklon": 0 }, + "3934": { "label": "15/17", "naklon": 0 }, + "3192": { "label": "15/18", "naklon": 0 }, + "2812": { "label": "15/19", "naklon": 0 }, + "4070": { "label": "15/20", "naklon": 0 }, + "2826": { "label": "15/21", "naklon": 0 }, + "2808": { "label": "15/22", "naklon": 3 }, + "2795": { "label": "15/23", "naklon": 3 }, + "2807": { "label": "15/24", "naklon": 3 }, + "2831": { "label": "15/25", "naklon": 0 }, + "2862": { "label": "15/26", "naklon": null }, + "2861": { "label": "15/27", "naklon": 0 }, + "2866": { "label": "15/28", "naklon": 0 }, + "3546": { "label": "15/28/1", "naklon": 0 }, + "4146": { "label": "15/29", "naklon": 0 }, + "3001": { "label": "15/29/1", "naklon": 0 }, + "2835": { "label": "15/30", "naklon": 0 }, + "2874": { "label": "15/31", "naklon": 0 }, + "2852": { "label": "15/32", "naklon": 0 }, + "2851": { "label": "15/33", "naklon": 0 }, + "3560": { "label": "15/33/1", "naklon": 0 }, + "2858": { "label": "15/34", "naklon": 0 }, + "4306": { "label": "15/34/1", "naklon": 0 }, + "2856": { "label": "15/35", "naklon": 0 }, + "2847": { "label": "15/36", "naklon": 0 }, + "3556": { "label": "15/36/1", "naklon": 0 }, + "3950": { "label": "15/37", "naklon": 0 }, + "2848": { "label": "15/38", "naklon": 0 }, + "2863": { "label": "15/39", "naklon": 0 }, + "4313": { "label": "15/39/1", "naklon": 0 }, + "2873": { "label": "15/40", "naklon": 0 }, + "2984": { "label": "15/40/1", "naklon": 0 }, + "2854": { "label": "15/41", "naklon": 0 }, + "2859": { "label": "15/42", "naklon": 0 }, + "2872": { "label": "15/43", "naklon": 0 }, + "2849": { "label": "15/44", "naklon": 0 }, + "2864": { "label": "15/45", "naklon": 0 }, + "3553": { "label": "15/46", "naklon": null }, + "3021": { "label": "15/47", "naklon": null }, + "3008": { "label": "15/47/1", "naklon": null }, + "3017": { "label": "15/48", "naklon": null }, + "3014": { "label": "15/49", "naklon": null }, + "2981": { "label": "15/50", "naklon": null }, + "3020": { "label": "15/51", "naklon": null }, + "3027": { "label": "15/52", "naklon": null }, + "3006": { "label": "15/53", "naklon": null }, + "3012": { "label": "15/54", "naklon": null }, + "2738": { "label": "15/55", "naklon": 0 }, + "2725": { "label": "15/56", "naklon": 0 }, + "3016": { "label": "15/57", "naklon": null }, + "3005": { "label": "15/58", "naklon": null }, + "3009": { "label": "15/58/1", "naklon": null }, + "3010": { "label": "15/59", "naklon": 0 }, + "3538": { "label": "15/59/1", "naklon": 0 }, + "4145": { "label": "15/59/2", "naklon": 0 }, + "2713": { "label": "15/60", "naklon": 0 }, + "2789": { "label": "15/61", "naklon": 0 }, + "2736": { "label": "15/62", "naklon": 0 }, + "2739": { "label": "15/63", "naklon": 0 }, + "4346": { "label": "15/64", "naklon": 0 }, + "2731": { "label": "15/65", "naklon": 0 }, + "2818": { "label": "15/66", "naklon": 0 }, + "3557": { "label": "15/66/1", "naklon": 0 }, + "2822": { "label": "15/67", "naklon": 0 }, + "2833": { "label": "15/68", "naklon": 0 }, + "2834": { "label": "15/69", "naklon": 0 }, + "3097": { "label": "15/70", "naklon": 0 }, + "2824": { "label": "15/71", "naklon": 0 }, + "2828": { "label": "15/72", "naklon": 0 }, + "2600": { "label": "15/73", "naklon": 0 }, + "4314": { "label": "15/73/1", "naklon": 0 }, + "2832": { "label": "15/74", "naklon": 0 }, + "4360": { "label": "15/75", "naklon": 0 }, + "2846": { "label": "15/76", "naklon": 0 }, + "2584": { "label": "15/77", "naklon": 0 }, + "2843": { "label": "15/78", "naklon": 0 }, + "4308": { "label": "15/78/1", "naklon": 0 }, + "4144": { "label": "15/79", "naklon": null }, + "2844": { "label": "15/80", "naklon": 0 }, + "2842": { "label": "15/81", "naklon": 0 }, + "2838": { "label": "15/82", "naklon": 0 }, + "2837": { "label": "15/83", "naklon": null }, + "3555": { "label": "15/83/1", "naklon": null }, + "2839": { "label": "15/84", "naklon": 0 }, + "2830": { "label": "15/85", "naklon": 0 }, + "4066": { "label": "15/86", "naklon": 0 }, + "2836": { "label": "15/87", "naklon": 0 }, + "2911": { "label": "15/88", "naklon": 0 }, + "2825": { "label": "15/89", "naklon": 0 }, + "2811": { "label": "15/90", "naklon": 0 }, + "3740": { "label": "15/94", "naklon": 15 }, + "2734": { "label": "15/95", "naklon": 15 }, + "3105": { "label": "15/96", "naklon": 15 }, + "2732": { "label": "15/97", "naklon": 15 }, + "2727": { "label": "15/98", "naklon": 15 }, + "2735": { "label": "15/99", "naklon": 15 }, + "3926": { "label": "15/100", "naklon": 15 }, + "2918": { "label": "15/101", "naklon": 0 }, + "2705": { "label": "15/102", "naklon": 10 }, + "2708": { "label": "15/103", "naklon": 10 }, + "2721": { "label": "15/104", "naklon": 10 }, + "2719": { "label": "15/105", "naklon": 10 }, + "2919": { "label": "15/106", "naklon": 10 }, + "3101": { "label": "15/107", "naklon": 10 }, + "2853": { "label": "15/108", "naklon": 10 }, + "2715": { "label": "15/109", "naklon": 10 }, + "2712": { "label": "15/110", "naklon": 0 }, + "2711": { "label": "15/111", "naklon": 0 }, + "2709": { "label": "15/112", "naklon": 0 }, + "2710": { "label": "15/113", "naklon": 0 }, + "2907": { "label": "15/114", "naklon": 0 }, + "2906": { "label": "15/115", "naklon": 0 }, + "2908": { "label": "15/116", "naklon": 0 }, + "2901": { "label": "15/117", "naklon": 0 }, + "2913": { "label": "15/118", "naklon": 0 }, + "3656": { "label": "15/119", "naklon": 0 }, + "2781": { "label": "15/120", "naklon": 0 }, + "2802": { "label": "15/121", "naklon": 0 }, + "2791": { "label": "15/122", "naklon": 0 }, + "2783": { "label": "15/123", "naklon": 0 }, + "2794": { "label": "15/124", "naklon": 0 }, + "3139": { "label": "15/125", "naklon": 0 }, + "3229": { "label": "15/126", "naklon": 5 }, + "3239": { "label": "15/127", "naklon": 5 }, + "3230": { "label": "15/128", "naklon": 5 }, + "4016": { "label": "15/129", "naklon": null }, + "3608": { "label": "16/16A", "naklon": 0 }, + "4151": { "label": "16/16B", "naklon": 0 }, + "3710": { "label": "16/1", "naklon": 0 }, + "3726": { "label": "16/2", "naklon": 0 }, + "3743": { "label": "16/3", "naklon": 0 }, + "3724": { "label": "16/4", "naklon": 0 }, + "3712": { "label": "16/5", "naklon": 0 }, + "3739": { "label": "16/6", "naklon": 0 }, + "3742": { "label": "16/7", "naklon": 0 }, + "3731": { "label": "16/8", "naklon": 0 }, + "3727": { "label": "16/9", "naklon": 0 }, + "3729": { "label": "16/10", "naklon": 0 }, + "3736": { "label": "16/11", "naklon": 0 }, + "3713": { "label": "16/12", "naklon": 0 }, + "3715": { "label": "16/13", "naklon": 0 }, + "3733": { "label": "16/14", "naklon": 0 }, + "3732": { "label": "16/15", "naklon": 0 }, + "3634": { "label": "16/17", "naklon": 0 }, + "3610": { "label": "16/18", "naklon": 0 }, + "3626": { "label": "16/19", "naklon": 0 }, + "3618": { "label": "16/20", "naklon": 0 }, + "3619": { "label": "16/21", "naklon": 0 }, + "3628": { "label": "16/22", "naklon": 0 }, + "3615": { "label": "16/23", "naklon": 0 }, + "3609": { "label": "16/24", "naklon": 0 }, + "3606": { "label": "16/25", "naklon": 0 }, + "3624": { "label": "16/26", "naklon": 0 }, + "3627": { "label": "16/27", "naklon": 0 }, + "3607": { "label": "16/28", "naklon": 0 }, + "4370": { "label": "16/29", "naklon": 0 }, + "3692": { "label": "16/30", "naklon": 0 }, + "3614": { "label": "16/31", "naklon": 0 }, + "3623": { "label": "16/32", "naklon": 0 }, + "4373": { "label": "16/33", "naklon": 0 }, + "3620": { "label": "16/34", "naklon": 0 }, + "3685": { "label": "16/35", "naklon": 0 }, + "3616": { "label": "16/36", "naklon": 0 }, + "3686": { "label": "16/37", "naklon": 0 }, + "3688": { "label": "16/38", "naklon": 0 }, + "3684": { "label": "16/39", "naklon": 0 }, + "3825": { "label": "16/40", "naklon": 0 }, + "3865": { "label": "16/41", "naklon": 0 }, + "3824": { "label": "16/42", "naklon": 0 }, + "3871": { "label": "16/43", "naklon": 0 }, + "3801": { "label": "16/44", "naklon": 0 }, + "3862": { "label": "16/45", "naklon": 0 }, + "3876": { "label": "16/46", "naklon": 0 }, + "3861": { "label": "16/47", "naklon": 0 }, + "4215": { "label": "16/48", "naklon": 0 }, + "3605": { "label": "16/49", "naklon": 10 }, + "3603": { "label": "16/50", "naklon": 10 }, + "3592": { "label": "16/51", "naklon": 10 }, + "3598": { "label": "16/52", "naklon": 10 }, + "3594": { "label": "16/53", "naklon": 10 }, + "3593": { "label": "16/54", "naklon": 10 }, + "3630": { "label": "16/55", "naklon": 10 }, + "3763": { "label": "16/56", "naklon": 10 }, + "3746": { "label": "16/57", "naklon": 10 }, + "3699": { "label": "16/58", "naklon": 0 }, + "3698": { "label": "16/59", "naklon": 0 }, + "3709": { "label": "16/60", "naklon": null }, + "3708": { "label": "16/61", "naklon": 0 }, + "3703": { "label": "16/62", "naklon": null }, + "3700": { "label": "16/63", "naklon": 0 }, + "3701": { "label": "16/64", "naklon": null }, + "3704": { "label": "16/65", "naklon": 0 }, + "3707": { "label": "16/66", "naklon": null }, + "3810": { "label": "16/67", "naklon": 0 }, + "4208": { "label": "16/68", "naklon": null }, + "3867": { "label": "16/69", "naklon": 0 }, + "4372": { "label": "16/70", "naklon": null }, + "3881": { "label": "16/71", "naklon": 0 }, + "4204": { "label": "16/72", "naklon": null }, + "3869": { "label": "16/73", "naklon": 0 }, + "4202": { "label": "16/74", "naklon": null }, + "3830": { "label": "16/75", "naklon": 0 }, + "3870": { "label": "16/76", "naklon": null }, + "3964": { "label": "16/77", "naklon": 0 }, + "3849": { "label": "16/78", "naklon": 0 }, + "3694": { "label": "16/79", "naklon": null }, + "3717": { "label": "16/80", "naklon": 0 }, + "3877": { "label": "16/81", "naklon": null }, + "3755": { "label": "16/82", "naklon": 0 }, + "3725": { "label": "16/83", "naklon": null }, + "3716": { "label": "16/84", "naklon": 0 }, + "3696": { "label": "16/85", "naklon": null }, + "3702": { "label": "16/86", "naklon": 0 }, + "3706": { "label": "16/87", "naklon": null }, + "3850": { "label": "16/88", "naklon": 0 }, + "3848": { "label": "16/89", "naklon": null }, + "3737": { "label": "16/90", "naklon": null }, + "3705": { "label": "16/91", "naklon": 0 }, + "3723": { "label": "16/92", "naklon": null }, + "3842": { "label": "16/93", "naklon": 0 }, + "3735": { "label": "16/94", "naklon": null }, + "3719": { "label": "16/95", "naklon": 0 }, + "3697": { "label": "16/96", "naklon": 0 }, + "3711": { "label": "16/97", "naklon": 0 }, + "4107": { "label": "16/98", "naklon": null }, + "4112": { "label": "16/99", "naklon": 5 }, + "4106": { "label": "16/100", "naklon": 5 }, + "4111": { "label": "16/101", "naklon": 5 }, + "4091": { "label": "16/102", "naklon": null }, + "4104": { "label": "16/103", "naklon": 5 }, + "4094": { "label": "16/104", "naklon": null }, + "4089": { "label": "16/105", "naklon": 5 }, + "4095": { "label": "16/106", "naklon": null }, + "4102": { "label": "16/107", "naklon": 5 }, + "4105": { "label": "16/108", "naklon": null }, + "3859": { "label": "16/109", "naklon": null }, + "4090": { "label": "16/110", "naklon": 5 }, + "4110": { "label": "16/111", "naklon": null }, + "4097": { "label": "16/112", "naklon": 5 }, + "4099": { "label": "16/113", "naklon": null }, + "4096": { "label": "16/114", "naklon": null }, + "4101": { "label": "16/115", "naklon": 5 }, + "4109": { "label": "16/116", "naklon": null }, + "4092": { "label": "16/117", "naklon": 5 }, + "3631": { "label": "16/118", "naklon": null }, + "3632": { "label": "16/119", "naklon": 0 }, + "3641": { "label": "16/120", "naklon": null }, + "3638": { "label": "16/121", "naklon": 0 }, + "3637": { "label": "16/122", "naklon": null }, + "4142": { "label": "16/123", "naklon": null }, + "4147": { "label": "16/124", "naklon": 5 }, + "4139": { "label": "16/125", "naklon": 5 }, + "3172": { "label": "20/30A", "naklon": 2 }, + "3164": { "label": "20/30B", "naklon": 2 }, + "3247": { "label": "20/1", "naklon": 10 }, + "3296": { "label": "20/2", "naklon": 10 }, + "3246": { "label": "20/3", "naklon": 10 }, + "3270": { "label": "20/4", "naklon": 10 }, + "3294": { "label": "20/5", "naklon": 10 }, + "3298": { "label": "20/6", "naklon": 10 }, + "3297": { "label": "20/7", "naklon": 10 }, + "3293": { "label": "20/8", "naklon": 10 }, + "3299": { "label": "20/9", "naklon": 10 }, + "3295": { "label": "20/10", "naklon": 10 }, + "3244": { "label": "20/11", "naklon": 10 }, + "3249": { "label": "20/12", "naklon": 10 }, + "3268": { "label": "20/13", "naklon": 10 }, + "3245": { "label": "20/14", "naklon": 10 }, + "3278": { "label": "20/15", "naklon": 10 }, + "3280": { "label": "20/16", "naklon": 10 }, + "3292": { "label": "20/17", "naklon": 10 }, + "3287": { "label": "20/18", "naklon": 10 }, + "3282": { "label": "20/19", "naklon": 10 }, + "3273": { "label": "20/20", "naklon": 0 }, + "3157": { "label": "20/21", "naklon": 0 }, + "3283": { "label": "20/22", "naklon": 0 }, + "3159": { "label": "20/23", "naklon": 0 }, + "3289": { "label": "20/24", "naklon": 0 }, + "3163": { "label": "20/25", "naklon": 0 }, + "3126": { "label": "20/26", "naklon": 0 }, + "3171": { "label": "20/27", "naklon": 0 }, + "3162": { "label": "20/28", "naklon": 0 }, + "3279": { "label": "20/29", "naklon": 10 }, + "3173": { "label": "20/31", "naklon": 0 }, + "3127": { "label": "20/32", "naklon": 0 }, + "3131": { "label": "20/33", "naklon": 0 }, + "3129": { "label": "20/34", "naklon": 0 }, + "3276": { "label": "20/35", "naklon": 2 }, + "3290": { "label": "20/36", "naklon": 2 }, + "3132": { "label": "20/37", "naklon": 0 }, + "3138": { "label": "20/38", "naklon": 0 }, + "3272": { "label": "20/39", "naklon": 0 }, + "3291": { "label": "20/40", "naklon": 0 }, + "3277": { "label": "20/41", "naklon": 10 }, + "3286": { "label": "20/42", "naklon": 10 }, + "3281": { "label": "20/43", "naklon": 10 }, + "3288": { "label": "20/44", "naklon": 10 }, + "3284": { "label": "20/45", "naklon": 10 }, + "3167": { "label": "20/46", "naklon": 10 }, + "3872": { "label": "20/47", "naklon": 0 }, + "3124": { "label": "20/48", "naklon": 0 }, + "3133": { "label": "20/49", "naklon": 0 }, + "3158": { "label": "20/50", "naklon": 0 }, + "3169": { "label": "20/51", "naklon": 0 }, + "3146": { "label": "20/52", "naklon": 0 }, + "3160": { "label": "20/53", "naklon": 0 }, + "3248": { "label": "20/54", "naklon": 0 }, + "3156": { "label": "20/55", "naklon": 0 }, + "3161": { "label": "20/56", "naklon": 0 }, + "3170": { "label": "20/57", "naklon": 0 }, + "3168": { "label": "20/58", "naklon": 0 }, + "3125": { "label": "20/59", "naklon": 0 }, + "3166": { "label": "20/60", "naklon": 0 }, + "3130": { "label": "20/61", "naklon": 0 }, + "3563": { "label": "20/62", "naklon": 0 }, + "3550": { "label": "20/63", "naklon": null }, + "3269": { "label": "20/67", "naklon": 0 }, + "2921": { "label": "21/1", "naklon": 0 }, + "2707": { "label": "21/2", "naklon": 0 }, + "2723": { "label": "21/3", "naklon": 0 }, + "2716": { "label": "21/4", "naklon": 0 }, + "2717": { "label": "21/5", "naklon": 0 }, + "2720": { "label": "21/6", "naklon": 0 }, + "2722": { "label": "21/7", "naklon": 0 }, + "2718": { "label": "21/8", "naklon": 0 }, + "2724": { "label": "21/9", "naklon": 0 }, + "2742": { "label": "21/10", "naklon": 0 }, + "2743": { "label": "21/11", "naklon": 0 }, + "2733": { "label": "21/12", "naklon": 0 }, + "2903": { "label": "21/14", "naklon": 0 }, + "2917": { "label": "21/15", "naklon": 0 }, + "2897": { "label": "21/16", "naklon": 0 }, + "2914": { "label": "21/17", "naklon": 0 }, + "2898": { "label": "21/18", "naklon": 0 }, + "2773": { "label": "21/19", "naklon": 0 }, + "2895": { "label": "21/20", "naklon": 0 }, + "2896": { "label": "21/21", "naklon": 0 }, + "2771": { "label": "21/22", "naklon": 0 }, + "2772": { "label": "21/23", "naklon": 0 }, + "2793": { "label": "21/24", "naklon": 0 }, + "2902": { "label": "21/25", "naklon": 0 }, + "2910": { "label": "21/26", "naklon": 0 }, + "2909": { "label": "21/27", "naklon": 0 }, + "2920": { "label": "21/28", "naklon": 0 }, + "2916": { "label": "21/29", "naklon": 0 }, + "2904": { "label": "21/30", "naklon": 0 }, + "2915": { "label": "21/31", "naklon": 0 }, + "2905": { "label": "21/32", "naklon": 0 }, + "2900": { "label": "21/33", "naklon": 0 }, + "2899": { "label": "21/34", "naklon": 0 }, + "2741": { "label": "21/36", "naklon": 0 }, + "2714": { "label": "21/37", "naklon": 0 }, + "2701": { "label": "21/38", "naklon": 0 }, + "2703": { "label": "21/39", "naklon": 0 }, + "2704": { "label": "21/40", "naklon": 0 }, + "2702": { "label": "21/41", "naklon": 0 }, + "2706": { "label": "21/42", "naklon": 0 }, + "2776": { "label": "21/43", "naklon": 0 }, + "2770": { "label": "21/44", "naklon": 0 }, + "2786": { "label": "21/45", "naklon": 0 }, + "2779": { "label": "21/46", "naklon": 0 }, + "2782": { "label": "21/47", "naklon": 0 }, + "2785": { "label": "21/48", "naklon": 0 }, + "2769": { "label": "21/49", "naklon": 0 }, + "3354": { "label": "21/50", "naklon": 0 }, + "2778": { "label": "21/51", "naklon": 0 }, + "2775": { "label": "21/52", "naklon": 0 }, + "2780": { "label": "21/53", "naklon": 0 }, + "2790": { "label": "21/54", "naklon": 0 }, + "2792": { "label": "21/55", "naklon": 0 }, + "2774": { "label": "21/56", "naklon": 0 }, + "2630": { "label": "22/1", "naklon": 0 }, + "2631": { "label": "22/2", "naklon": 0 }, + "2632": { "label": "22/3", "naklon": 0 }, + "2633": { "label": "22/4", "naklon": 0 }, + "2634": { "label": "22/5", "naklon": 0 }, + "2636": { "label": "22/6", "naklon": 0 }, + "4367": { "label": "22/7", "naklon": 0 }, + "2637": { "label": "22/8", "naklon": 0 }, + "2638": { "label": "22/9", "naklon": 0 }, + "2639": { "label": "22/10", "naklon": 0 }, + "2640": { "label": "22/11", "naklon": 0 }, + "2641": { "label": "22/12", "naklon": 0 }, + "2642": { "label": "22/13", "naklon": 0 }, + "2643": { "label": "22/14", "naklon": 0 }, + "2644": { "label": "22/15", "naklon": 0 }, + "2645": { "label": "22/16", "naklon": 0 }, + "2646": { "label": "22/17", "naklon": 0 }, + "2647": { "label": "22/18", "naklon": 0 }, + "2648": { "label": "22/19", "naklon": 0 }, + "2649": { "label": "22/20", "naklon": 0 }, + "2650": { "label": "22/21", "naklon": 0 }, + "2651": { "label": "22/22", "naklon": 0 }, + "4103": { "label": "22/23", "naklon": 0 }, + "2653": { "label": "22/24", "naklon": 0 }, + "2654": { "label": "22/25", "naklon": 0 }, + "2655": { "label": "22/26", "naklon": 0 }, + "2656": { "label": "22/27", "naklon": 0 }, + "2657": { "label": "22/28", "naklon": 0 }, + "2658": { "label": "22/29", "naklon": 0 }, + "2659": { "label": "22/30", "naklon": 0 }, + "2660": { "label": "22/31", "naklon": 0 }, + "2661": { "label": "22/32", "naklon": 0 }, + "3015": { "label": "22/32/1", "naklon": 0 }, + "2662": { "label": "22/33", "naklon": 0 }, + "2663": { "label": "22/34", "naklon": 0 }, + "2664": { "label": "22/35", "naklon": 0 }, + "2665": { "label": "22/36", "naklon": 0 }, + "2666": { "label": "22/37", "naklon": 0 }, + "2667": { "label": "22/38", "naklon": 0 }, + "2668": { "label": "22/39", "naklon": 0 }, + "2669": { "label": "22/40", "naklon": null }, + "2670": { "label": "22/41", "naklon": null }, + "2671": { "label": "22/42", "naklon": null }, + "3087": { "label": "23/9A", "naklon": 10 }, + "3090": { "label": "23/9B", "naklon": 10 }, + "3075": { "label": "23/1", "naklon": 0 }, + "3089": { "label": "23/2", "naklon": 0 }, + "3088": { "label": "23/3", "naklon": 0 }, + "3228": { "label": "23/4", "naklon": 10 }, + "2751": { "label": "23/5", "naklon": 10 }, + "3243": { "label": "23/6", "naklon": 10 }, + "4349": { "label": "23/7", "naklon": 10 }, + "3102": { "label": "23/8", "naklon": 10 }, + "3099": { "label": "23/10", "naklon": 10 }, + "3103": { "label": "23/11", "naklon": 10 }, + "3093": { "label": "23/12", "naklon": 10 }, + "3098": { "label": "23/13", "naklon": 10 }, + "3092": { "label": "23/14", "naklon": 10 }, + "3233": { "label": "23/15", "naklon": 0 }, + "3095": { "label": "23/16", "naklon": 0 }, + "4074": { "label": "23/17", "naklon": 0 }, + "2729": { "label": "23/18", "naklon": 0 }, + "3234": { "label": "23/19", "naklon": 0 }, + "3094": { "label": "23/20", "naklon": 0 }, + "2817": { "label": "23/21", "naklon": 0 }, + "3226": { "label": "23/22", "naklon": 0 }, + "3225": { "label": "23/23", "naklon": 0 }, + "3237": { "label": "23/24", "naklon": 0 }, + "4250": { "label": "23/25", "naklon": 0 }, + "3059": { "label": "23/26", "naklon": 10 }, + "3238": { "label": "23/27", "naklon": 10 }, + "3242": { "label": "23/28", "naklon": 10 }, + "3236": { "label": "23/29", "naklon": 10 }, + "3112": { "label": "23/30", "naklon": 10 }, + "3224": { "label": "23/31", "naklon": 0 }, + "4298": { "label": "23/32", "naklon": 10 }, + "4150": { "label": "23/33", "naklon": 10 }, + "3091": { "label": "23/34", "naklon": 10 }, + "3771": { "label": "25/1", "naklon": 5 }, + "3777": { "label": "25/2", "naklon": 5 }, + "3749": { "label": "25/3", "naklon": 5 }, + "3769": { "label": "25/4", "naklon": 5 }, + "3765": { "label": "25/5", "naklon": 5 }, + "3785": { "label": "25/6", "naklon": 5 }, + "3761": { "label": "25/7", "naklon": 5 }, + "3758": { "label": "25/8", "naklon": 5 }, + "3766": { "label": "25/9", "naklon": 5 }, + "3779": { "label": "25/10", "naklon": 5 }, + "3899": { "label": "25/11", "naklon": 10 }, + "3922": { "label": "25/12", "naklon": 10 }, + "3912": { "label": "25/13", "naklon": 10 }, + "3933": { "label": "25/14", "naklon": 10 }, + "3921": { "label": "25/15", "naklon": 10 }, + "4300": { "label": "25/16", "naklon": 10 }, + "3927": { "label": "25/17", "naklon": 10 }, + "3212": { "label": "25/18", "naklon": 10 }, + "3208": { "label": "25/19", "naklon": 10 }, + "3207": { "label": "25/20", "naklon": 10 }, + "4294": { "label": "25/21", "naklon": 10 }, + "3209": { "label": "25/22", "naklon": 10 }, + "3745": { "label": "25/23", "naklon": 10 }, + "3762": { "label": "25/24", "naklon": 10 }, + "3215": { "label": "25/25", "naklon": 10 }, + "3210": { "label": "25/26", "naklon": 10 }, + "3211": { "label": "25/27", "naklon": 10 }, + "3206": { "label": "25/28", "naklon": 10 }, + "3918": { "label": "25/29", "naklon": 5 }, + "3928": { "label": "25/30", "naklon": 5 }, + "3917": { "label": "25/31", "naklon": 5 }, + "4029": { "label": "25/32", "naklon": 0 }, + "4038": { "label": "25/33", "naklon": 0 }, + "4022": { "label": "25/34", "naklon": 0 }, + "3937": { "label": "25/35", "naklon": 0 }, + "3190": { "label": "25/36", "naklon": 0 }, + "3835": { "label": "25/37", "naklon": 0 }, + "3201": { "label": "25/38", "naklon": 0 }, + "3193": { "label": "25/39", "naklon": 0 }, + "3191": { "label": "25/40", "naklon": 0 }, + "3203": { "label": "25/41", "naklon": 0 }, + "4301": { "label": "25/42", "naklon": 0 }, + "3223": { "label": "25/43", "naklon": 0 }, + "3202": { "label": "25/44", "naklon": 0 }, + "3205": { "label": "25/45", "naklon": 0 }, + "3194": { "label": "25/46", "naklon": 0 }, + "3198": { "label": "25/47", "naklon": 0 }, + "3204": { "label": "25/48", "naklon": 0 }, + "3200": { "label": "25/49", "naklon": 0 }, + "3216": { "label": "25/50", "naklon": 0 }, + "3932": { "label": "25/51", "naklon": 5 }, + "3923": { "label": "25/52", "naklon": 5 }, + "3913": { "label": "25/53", "naklon": 5 }, + "3900": { "label": "25/54", "naklon": 5 }, + "4189": { "label": "25/55", "naklon": 10 }, + "4191": { "label": "25/56", "naklon": 10 }, + "3790": { "label": "25/57", "naklon": 10 }, + "4190": { "label": "25/58", "naklon": 10 }, + "4302": { "label": "25/59", "naklon": 0 }, + "4351": { "label": "25/60", "naklon": 0 }, + "4075": { "label": "25/61", "naklon": 0 }, + "4071": { "label": "25/62", "naklon": 0 }, + "3784": { "label": "25/63", "naklon": 0 }, + "4065": { "label": "25/64", "naklon": 0 }, + "4297": { "label": "25/65", "naklon": 0 }, + "4295": { "label": "25/66", "naklon": 0 }, + "4299": { "label": "25/67", "naklon": 0 }, + "3772": { "label": "25/68", "naklon": 0 }, + "3941": { "label": "25/69", "naklon": 0 }, + "3782": { "label": "25/70", "naklon": 0 }, + "4068": { "label": "25/71", "naklon": 0 }, + "4073": { "label": "25/72", "naklon": 0 }, + "3901": { "label": "25/73", "naklon": 5 }, + "4296": { "label": "25/74", "naklon": 5 }, + "3910": { "label": "25/75", "naklon": 5 }, + "4293": { "label": "25/76", "naklon": 5 }, + "3919": { "label": "25/77", "naklon": 5 }, + "3924": { "label": "25/78", "naklon": 5 }, + "3909": { "label": "25/79", "naklon": 5 }, + "3896": { "label": "25/80", "naklon": 5 }, + "3911": { "label": "25/81", "naklon": 5 }, + "2819": { "label": "25/82", "naklon": 15 }, + "3776": { "label": "25/83", "naklon": 15 }, + "3752": { "label": "25/84", "naklon": 15 }, + "4353": { "label": "25/85", "naklon": 15 }, + "3791": { "label": "25/86", "naklon": 0 }, + "3770": { "label": "25/87", "naklon": 0 }, + "3760": { "label": "25/88", "naklon": 0 }, + "3115": { "label": "25/89", "naklon": 0 }, + "3738": { "label": "25/90", "naklon": 0 }, + "3748": { "label": "25/91", "naklon": 0 }, + "3753": { "label": "25/92", "naklon": 0 }, + "3775": { "label": "25/93", "naklon": 0 }, + "3778": { "label": "25/94", "naklon": 5 }, + "4078": { "label": "25/95", "naklon": 5 }, + "4088": { "label": "25/96", "naklon": 5 }, + "3856": { "label": "25/97", "naklon": 5 }, + "4084": { "label": "25/98", "naklon": 5 }, + "4069": { "label": "25/99", "naklon": 5 }, + "4188": { "label": "25/100", "naklon": 5 }, + "4064": { "label": "25/101", "naklon": 5 }, + "3792": { "label": "25/102", "naklon": 5 }, + "3780": { "label": "25/103", "naklon": 5 }, + "4034": { "label": "25/104", "naklon": 5 }, + "4072": { "label": "25/105", "naklon": 5 }, + "3884": { "label": "25/106", "naklon": 5 }, + "3793": { "label": "25/107", "naklon": 5 }, + "3863": { "label": "25/108", "naklon": 5 }, + "3855": { "label": "25/109", "naklon": 5 }, + "3846": { "label": "33/1", "naklon": 0 }, + "3943": { "label": "33/2", "naklon": 0 }, + "3903": { "label": "33/3", "naklon": 0 }, + "3982": { "label": "33/4", "naklon": 0 }, + "3879": { "label": "33/5", "naklon": 0 }, + "3887": { "label": "33/6", "naklon": 0 }, + "3920": { "label": "33/7", "naklon": 5 }, + "3942": { "label": "33/8", "naklon": 5 }, + "3829": { "label": "33/9", "naklon": null }, + "3452": { "label": "34/79A", "naklon": 6 }, + "3460": { "label": "34/79B", "naklon": 6 }, + "3443": { "label": "34/90A", "naklon": 6 }, + "3445": { "label": "34/90B", "naklon": 6 }, + "3457": { "label": "34/90C", "naklon": 6 }, + "3461": { "label": "34/97A", "naklon": 6 }, + "3463": { "label": "34/97B", "naklon": 6 }, + "3426": { "label": "34/98A", "naklon": 6 }, + "3444": { "label": "34/98B", "naklon": 6 }, + "3453": { "label": "34/99A", "naklon": 6 }, + "3455": { "label": "34/99B", "naklon": 6 }, + "4009": { "label": "34/1", "naklon": 0 }, + "3602": { "label": "34/2", "naklon": 0 }, + "3441": { "label": "34/3", "naklon": 0 }, + "3464": { "label": "34/4", "naklon": 0 }, + "3883": { "label": "34/5", "naklon": 0 }, + "4098": { "label": "34/6", "naklon": 0 }, + "4003": { "label": "34/7", "naklon": 0 }, + "4004": { "label": "34/8", "naklon": 0 }, + "3888": { "label": "34/9", "naklon": 0 }, + "3997": { "label": "34/10", "naklon": 0 }, + "4006": { "label": "34/11", "naklon": 0 }, + "4000": { "label": "34/12", "naklon": 0 }, + "4011": { "label": "34/13", "naklon": 0 }, + "3999": { "label": "34/14", "naklon": 0 }, + "3981": { "label": "34/15", "naklon": 0 }, + "3988": { "label": "34/16", "naklon": 0 }, + "3986": { "label": "34/17", "naklon": 0 }, + "3998": { "label": "34/18", "naklon": 0 }, + "3983": { "label": "34/19", "naklon": 0 }, + "4005": { "label": "34/20", "naklon": 0 }, + "4001": { "label": "34/21", "naklon": 0 }, + "4008": { "label": "34/22", "naklon": 0 }, + "4002": { "label": "34/23", "naklon": 0 }, + "3996": { "label": "34/24", "naklon": 0 }, + "4007": { "label": "34/25", "naklon": 0 }, + "4113": { "label": "34/26", "naklon": 15 }, + "3595": { "label": "34/27", "naklon": 5 }, + "3599": { "label": "34/28", "naklon": 5 }, + "3601": { "label": "34/29", "naklon": 5 }, + "4205": { "label": "34/30", "naklon": 0 }, + "3987": { "label": "34/31", "naklon": null }, + "4214": { "label": "34/32", "naklon": 0 }, + "4226": { "label": "34/33", "naklon": 0 }, + "4209": { "label": "34/34", "naklon": 0 }, + "4201": { "label": "34/35", "naklon": 0 }, + "3440": { "label": "34/36", "naklon": 0 }, + "3465": { "label": "34/37", "naklon": 0 }, + "3446": { "label": "34/38", "naklon": 0 }, + "4039": { "label": "34/39", "naklon": 5 }, + "4057": { "label": "34/40", "naklon": 5 }, + "3985": { "label": "34/41", "naklon": 0 }, + "3882": { "label": "34/42", "naklon": 0 }, + "4040": { "label": "34/43", "naklon": 5 }, + "3231": { "label": "34/44", "naklon": 0 }, + "3227": { "label": "34/45", "naklon": 0 }, + "3431": { "label": "34/46", "naklon": 0 }, + "4013": { "label": "34/47", "naklon": 0 }, + "4045": { "label": "34/48", "naklon": 0 }, + "3949": { "label": "34/49", "naklon": 0 }, + "3953": { "label": "34/50", "naklon": 0 }, + "3952": { "label": "34/51", "naklon": 0 }, + "3995": { "label": "34/52", "naklon": 0 }, + "3992": { "label": "34/53", "naklon": 0 }, + "4198": { "label": "34/54", "naklon": 0 }, + "3935": { "label": "34/55", "naklon": 0 }, + "4050": { "label": "34/56", "naklon": 0 }, + "4049": { "label": "34/57", "naklon": 0 }, + "4054": { "label": "34/58", "naklon": 0 }, + "3663": { "label": "34/59", "naklon": 6 }, + "3661": { "label": "34/60", "naklon": 6 }, + "3664": { "label": "34/61", "naklon": 6 }, + "3660": { "label": "34/62", "naklon": 6 }, + "3662": { "label": "34/63", "naklon": 6 }, + "3665": { "label": "34/65", "naklon": 6 }, + "3667": { "label": "34/66", "naklon": 6 }, + "3675": { "label": "34/67", "naklon": 6 }, + "3666": { "label": "34/68", "naklon": 6 }, + "3652": { "label": "34/69", "naklon": 6 }, + "3458": { "label": "34/70", "naklon": 6 }, + "4425": { "label": "34/70/1", "naklon": 6 }, + "3459": { "label": "34/71", "naklon": 6 }, + "3435": { "label": "34/72", "naklon": 6 }, + "3448": { "label": "34/73", "naklon": 6 }, + "3451": { "label": "34/74", "naklon": 6 }, + "3442": { "label": "34/75", "naklon": 6 }, + "3449": { "label": "34/76", "naklon": 6 }, + "3450": { "label": "34/77", "naklon": 6 }, + "3433": { "label": "34/78", "naklon": 6 }, + "3432": { "label": "34/80", "naklon": 12 }, + "3470": { "label": "34/81", "naklon": 12 }, + "3438": { "label": "34/82", "naklon": 12 }, + "3439": { "label": "34/83", "naklon": 12 }, + "4028": { "label": "34/84", "naklon": 5 }, + "3596": { "label": "34/85", "naklon": 5 }, + "4021": { "label": "34/86", "naklon": 5 }, + "3437": { "label": "34/87", "naklon": 12 }, + "3428": { "label": "34/88", "naklon": 12 }, + "3430": { "label": "34/89", "naklon": 12 }, + "3454": { "label": "34/91", "naklon": 6 }, + "3492": { "label": "34/92", "naklon": 6 }, + "3462": { "label": "34/93", "naklon": 6 }, + "3427": { "label": "34/94", "naklon": 6 }, + "3434": { "label": "34/95", "naklon": 6 }, + "3456": { "label": "34/96", "naklon": 6 }, + "4307": { "label": "34/98/1", "naklon": 6 }, + "3968": { "label": "35/1", "naklon": 0 }, + "3969": { "label": "35/2", "naklon": 0 }, + "3947": { "label": "35/3", "naklon": 0 }, + "3979": { "label": "35/4", "naklon": 0 }, + "3959": { "label": "35/5", "naklon": 0 }, + "3948": { "label": "35/6", "naklon": 0 }, + "3961": { "label": "35/7", "naklon": 0 }, + "3956": { "label": "35/8", "naklon": 0 }, + "3604": { "label": "35/9", "naklon": 0 }, + "3944": { "label": "35/10", "naklon": 0 }, + "3960": { "label": "35/11", "naklon": 0 }, + "3958": { "label": "35/12", "naklon": 0 }, + "4036": { "label": "35/13", "naklon": 5 }, + "3893": { "label": "35/18", "naklon": 5 }, + "4108": { "label": "35/19", "naklon": 5 }, + "4017": { "label": "35/20", "naklon": 5 }, + "3963": { "label": "35/21", "naklon": 0 }, + "3658": { "label": "35/22", "naklon": 0 }, + "3975": { "label": "35/23", "naklon": 0 }, + "3980": { "label": "35/24", "naklon": 0 }, + "4012": { "label": "35/25", "naklon": 0 }, + "3655": { "label": "35/26", "naklon": 0 }, + "3962": { "label": "35/27", "naklon": 0 }, + "3945": { "label": "35/28", "naklon": 0 }, + "3569": { "label": "35/29", "naklon": 0 }, + "3429": { "label": "35/30", "naklon": 0 }, + "3657": { "label": "35/31", "naklon": 0 }, + "3646": { "label": "35/32", "naklon": 0 }, + "3622": { "label": "35/33", "naklon": 0 }, + "3612": { "label": "35/34", "naklon": 0 }, + "3955": { "label": "35/35", "naklon": 0 }, + "3878": { "label": "35/37", "naklon": 0 }, + "3965": { "label": "35/38", "naklon": 0 }, + "3970": { "label": "35/39", "naklon": 0 }, + "3611": { "label": "35/40", "naklon": 0 }, + "2635": { "label": "35/41", "naklon": 0 }, + "3978": { "label": "35/42", "naklon": 0 }, + "4213": { "label": "35/43", "naklon": 0 }, + "3984": { "label": "35/44", "naklon": 0 }, + "4218": { "label": "35/45", "naklon": 0 }, + "3973": { "label": "35/46", "naklon": 0 }, + "3974": { "label": "35/47", "naklon": 0 }, + "3759": { "label": "35/48", "naklon": 0 }, + "3844": { "label": "35/49", "naklon": 0 }, + "3804": { "label": "35/50", "naklon": 0 }, + "3831": { "label": "35/51", "naklon": 0 }, + "3643": { "label": "35/52", "naklon": 0 }, + "3966": { "label": "35/53", "naklon": 0 }, + "3971": { "label": "35/54", "naklon": 0 }, + "3650": { "label": "35/55", "naklon": 6 }, + "3651": { "label": "35/56", "naklon": 6 }, + "3669": { "label": "35/57", "naklon": 6 }, + "3648": { "label": "35/58", "naklon": 6 }, + "3645": { "label": "35/59", "naklon": 6 }, + "3659": { "label": "35/60", "naklon": 6 }, + "3647": { "label": "35/61", "naklon": 6 }, + "3644": { "label": "35/62", "naklon": 6 }, + "3671": { "label": "35/63", "naklon": 6 }, + "3682": { "label": "35/64", "naklon": 6 }, + "3672": { "label": "35/65", "naklon": 6 }, + "3683": { "label": "35/66", "naklon": 6 }, + "3673": { "label": "35/67", "naklon": 6 }, + "3674": { "label": "35/68", "naklon": 6 }, + "3679": { "label": "35/69", "naklon": 6 }, + "3649": { "label": "35/70", "naklon": 6 }, + "3687": { "label": "35/71", "naklon": 6 }, + "3677": { "label": "35/72", "naklon": 6 }, + "3690": { "label": "35/73", "naklon": 6 }, + "3691": { "label": "35/74", "naklon": 6 }, + "3676": { "label": "35/75", "naklon": 6 }, + "3680": { "label": "35/76", "naklon": 6 }, + "3668": { "label": "35/77", "naklon": 6 }, + "3681": { "label": "35/78", "naklon": 6 }, + "3670": { "label": "35/79", "naklon": 6 }, + "3689": { "label": "35/80", "naklon": 6 }, + "3678": { "label": "35/81", "naklon": 6 }, + "3693": { "label": "35/82", "naklon": 6 }, + "3654": { "label": "35/83", "naklon": null }, + "4086": { "label": "36/1", "naklon": 0 }, + "4085": { "label": "36/2", "naklon": 0 }, + "4083": { "label": "36/3", "naklon": 0 }, + "4087": { "label": "36/4", "naklon": 0 }, + "4077": { "label": "36/5", "naklon": 0 }, + "4082": { "label": "36/6", "naklon": 0 }, + "4186": { "label": "36/7", "naklon": 0 }, + "4206": { "label": "36/8", "naklon": 0 }, + "4080": { "label": "36/9", "naklon": 0 }, + "4081": { "label": "36/10", "naklon": 0 }, + "4210": { "label": "36/11", "naklon": 0 }, + "4079": { "label": "36/12", "naklon": 0 }, + "4076": { "label": "36/13", "naklon": 0 }, + "3852": { "label": "36/14", "naklon": 0 }, + "2813": { "label": "36/15", "naklon": 0 }, + "4219": { "label": "36/16", "naklon": 0 }, + "3104": { "label": "37/1A", "naklon": 15 }, + "3121": { "label": "37/1B", "naklon": 15 }, + "3113": { "label": "37/2", "naklon": 10 }, + "3118": { "label": "37/3", "naklon": 10 }, + "3111": { "label": "37/4", "naklon": 10 }, + "4020": { "label": "37/5", "naklon": 10 }, + "3119": { "label": "37/6", "naklon": 10 }, + "3110": { "label": "37/7", "naklon": 10 }, + "3108": { "label": "37/8", "naklon": 10 }, + "3107": { "label": "37/12", "naklon": 0 }, + "3199": { "label": "37/13", "naklon": 0 }, + "3120": { "label": "37/14", "naklon": 0 }, + "3122": { "label": "37/15", "naklon": 0 }, + "3908": { "label": "37/16", "naklon": 0 }, + "3114": { "label": "37/17", "naklon": 0 }, + "3105": { "label": "37/18", "naklon": 0 }, + "3116": { "label": "37/19", "naklon": 0 }, + "3106": { "label": "37/20", "naklon": 0 }, + "2887": { "label": "37/21", "naklon": 5 }, + "2888": { "label": "37/22", "naklon": 5 }, + "2877": { "label": "37/23", "naklon": 5 }, + "2891": { "label": "37/24", "naklon": 5 }, + "2886": { "label": "37/25", "naklon": 5 }, + "2892": { "label": "37/26", "naklon": 5 }, + "2882": { "label": "37/27", "naklon": 5 }, + "2883": { "label": "37/28", "naklon": 5 }, + "2876": { "label": "37/29", "naklon": 5 }, + "3109": { "label": "37/30", "naklon": 5 }, + "4152": { "label": "37/31", "naklon": 5 }, + "3117": { "label": "37/32", "naklon": 5 }, + "2870": { "label": "37/33", "naklon": 5 }, + "2867": { "label": "37/34", "naklon": 0 }, + "2865": { "label": "37/35", "naklon": 0 }, + "3096": { "label": "37/36", "naklon": 0 }, + "2871": { "label": "37/37", "naklon": 0 }, + "2884": { "label": "37/38", "naklon": 0 }, + "2855": { "label": "37/39", "naklon": 0 }, + "2878": { "label": "37/40", "naklon": 0 }, + "2889": { "label": "37/41", "naklon": 0 }, + "2879": { "label": "37/42", "naklon": 0 }, + "2850": { "label": "37/43", "naklon": 0 }, + "2894": { "label": "37/44", "naklon": 0 }, + "2880": { "label": "37/45", "naklon": 0 }, + "2893": { "label": "37/46", "naklon": 0 }, + "2890": { "label": "37/47", "naklon": 0 }, + "4355": { "label": "37/48", "naklon": 0 }, + "2885": { "label": "37/49", "naklon": 0 }, + "2875": { "label": "37/50", "naklon": 0 }, + "3486": { "label": "38/30A", "naklon": 5 }, + "3714": { "label": "38/30B", "naklon": 0 }, + "3483": { "label": "38/32A", "naklon": 5 }, + "3496": { "label": "38/32B", "naklon": 0 }, + "3487": { "label": "38/35A", "naklon": 5 }, + "3498": { "label": "38/35B", "naklon": 5 }, + "3578": { "label": "38/38A", "naklon": 5 }, + "3508": { "label": "38/38B", "naklon": 5 }, + "3787": { "label": "38/59A", "naklon": 5 }, + "3491": { "label": "38/59B", "naklon": 5 }, + "3568": { "label": "38/1", "naklon": null }, + "3502": { "label": "38/2", "naklon": 0 }, + "3836": { "label": "38/3", "naklon": 0 }, + "3588": { "label": "38/4", "naklon": 0 }, + "3493": { "label": "38/5", "naklon": 0 }, + "3580": { "label": "38/6", "naklon": 0 }, + "3572": { "label": "38/7", "naklon": 0 }, + "3506": { "label": "38/8", "naklon": 0 }, + "3503": { "label": "38/9", "naklon": 0 }, + "3579": { "label": "38/10", "naklon": 0 }, + "3586": { "label": "38/11", "naklon": 0 }, + "3495": { "label": "38/12", "naklon": 5 }, + "3492": { "label": "38/13", "naklon": 5 }, + "3532": { "label": "38/14", "naklon": 5 }, + "3574": { "label": "38/15", "naklon": 5 }, + "4140": { "label": "38/16", "naklon": 5 }, + "3795": { "label": "38/17", "naklon": 5 }, + "3788": { "label": "38/18", "naklon": 5 }, + "3796": { "label": "38/19", "naklon": 5 }, + "3797": { "label": "38/20", "naklon": 5 }, + "3798": { "label": "38/21", "naklon": 5 }, + "3786": { "label": "38/22", "naklon": 5 }, + "4067": { "label": "38/23", "naklon": 5 }, + "3773": { "label": "38/24", "naklon": 5 }, + "3774": { "label": "38/25", "naklon": 5 }, + "3789": { "label": "38/26", "naklon": 5 }, + "3520": { "label": "38/27", "naklon": null }, + "3577": { "label": "38/29", "naklon": 5 }, + "3530": { "label": "38/31", "naklon": null }, + "3488": { "label": "38/33", "naklon": 5 }, + "3505": { "label": "38/34", "naklon": 5 }, + "3497": { "label": "38/36", "naklon": 5 }, + "3490": { "label": "38/37", "naklon": 5 }, + "3585": { "label": "38/39", "naklon": 5 }, + "3582": { "label": "38/40", "naklon": 5 }, + "3507": { "label": "38/41", "naklon": 5 }, + "3484": { "label": "38/42", "naklon": 5 }, + "3501": { "label": "38/43", "naklon": 5 }, + "3581": { "label": "38/44", "naklon": 5 }, + "4192": { "label": "38/45", "naklon": 5 }, + "3576": { "label": "38/46", "naklon": 5 }, + "3489": { "label": "38/47", "naklon": 5 }, + "3573": { "label": "38/48", "naklon": 5 }, + "3504": { "label": "38/49", "naklon": 5 }, + "3794": { "label": "38/50", "naklon": 5 }, + "3485": { "label": "38/51", "naklon": 5 }, + "3482": { "label": "38/52", "naklon": 5 }, + "3575": { "label": "38/53", "naklon": 5 }, + "3499": { "label": "38/54", "naklon": 5 }, + "3494": { "label": "38/55", "naklon": 5 }, + "3583": { "label": "38/56", "naklon": 5 }, + "3570": { "label": "38/57", "naklon": 5 }, + "3500": { "label": "38/58", "naklon": 0 }, + "3510": { "label": "38/63", "naklon": null }, + "3512": { "label": "38/64", "naklon": null }, + "3535": { "label": "38/67", "naklon": null }, + "3531": { "label": "38/68", "naklon": null }, + "3537": { "label": "38/69", "naklon": null }, + "3522": { "label": "39/1", "naklon": 10 }, + "4018": { "label": "39/2", "naklon": 10 }, + "4019": { "label": "39/3", "naklon": 10 }, + "4154": { "label": "39/4", "naklon": 5 }, + "3907": { "label": "39/5", "naklon": 5 }, + "4148": { "label": "39/6", "naklon": 0 }, + "4153": { "label": "39/7", "naklon": 0 }, + "3938": { "label": "39/8", "naklon": 0 }, + "3802": { "label": "39/9", "naklon": 0 }, + "4015": { "label": "39/10", "naklon": 0 }, + "3929": { "label": "39/11", "naklon": 0 }, + "3946": { "label": "39/12", "naklon": 0 }, + "4014": { "label": "39/13", "naklon": 0 }, + "4155": { "label": "39/14", "naklon": 0 }, + "4149": { "label": "39/15", "naklon": 0 }, + "3642": { "label": "39/16", "naklon": 0 }, + "3636": { "label": "39/17", "naklon": 5 }, + "3991": { "label": "39/18", "naklon": 0 }, + "3994": { "label": "39/19", "naklon": 0 }, + "3990": { "label": "39/20", "naklon": 0 }, + "3967": { "label": "39/21", "naklon": 0 }, + "3977": { "label": "39/22", "naklon": 0 }, + "3757": { "label": "39/23", "naklon": 15 }, + "3633": { "label": "39/24", "naklon": 15 }, + "3744": { "label": "39/25", "naklon": 15 }, + "4023": { "label": "39/26", "naklon": 5 }, + "3720": { "label": "39/27", "naklon": 5 }, + "3734": { "label": "39/28", "naklon": 5 }, + "3741": { "label": "39/29", "naklon": 5 }, + "3721": { "label": "39/30", "naklon": 5 }, + "3845": { "label": "39/31", "naklon": 0 }, + "3840": { "label": "39/32", "naklon": 0 }, + "3837": { "label": "39/33", "naklon": null }, + "3839": { "label": "39/34", "naklon": 0 }, + "3542": { "label": "41/1", "naklon": null }, + "3566": { "label": "41/2", "naklon": null }, + "3548": { "label": "41/3", "naklon": null }, + "3515": { "label": "41/4", "naklon": null }, + "3559": { "label": "41/5", "naklon": null }, + "3509": { "label": "41/6", "naklon": null }, + "3524": { "label": "41/7", "naklon": null }, + "3518": { "label": "41/8", "naklon": null }, + "3182": { "label": "41/9", "naklon": null }, + "3187": { "label": "41/10", "naklon": null }, + "3195": { "label": "41/11", "naklon": 0 }, + "3857": { "label": "41/12", "naklon": 0 }, + "3183": { "label": "41/13", "naklon": 0 }, + "3177": { "label": "41/14", "naklon": 0 }, + "3189": { "label": "41/15", "naklon": 0 }, + "3186": { "label": "41/16", "naklon": 0 }, + "3178": { "label": "42/1", "naklon": 0 }, + "3219": { "label": "42/2", "naklon": 0 }, + "3475": { "label": "42/3", "naklon": 0 }, + "3175": { "label": "42/4", "naklon": 0 }, + "3222": { "label": "42/5", "naklon": 0 }, + "3221": { "label": "42/6", "naklon": 0 }, + "3181": { "label": "42/7", "naklon": 0 }, + "3180": { "label": "42/8", "naklon": 0 }, + "3218": { "label": "42/9", "naklon": 0 }, + "3176": { "label": "42/10", "naklon": 0 }, + "3174": { "label": "42/11", "naklon": 0 }, + "3220": { "label": "42/12", "naklon": 0 }, + "3533": { "label": "42/13", "naklon": null }, + "3543": { "label": "42/14", "naklon": null }, + "3554": { "label": "42/15", "naklon": null }, + "3549": { "label": "42/16", "naklon": null }, + "2857": { "label": "43/1", "naklon": 5 }, + "2752": { "label": "43/2", "naklon": 5 }, + "2753": { "label": "43/3", "naklon": 5 }, + "3024": { "label": "43/4", "naklon": 5 }, + "2754": { "label": "43/5", "naklon": 5 }, + "4423": { "label": "43/6", "naklon": 5 }, + "4368": { "label": "43/7", "naklon": 5 }, + "2978": { "label": "43/8", "naklon": 5 }, + "2868": { "label": "43/9", "naklon": 5 }, + "4377": { "label": "43/10", "naklon": 5 }, + "2757": { "label": "43/11", "naklon": 5 }, + "2970": { "label": "43/12", "naklon": 5 }, + "2758": { "label": "43/13", "naklon": 5 }, + "4378": { "label": "43/14", "naklon": 5 }, + "2759": { "label": "43/15", "naklon": 5 }, + "4342": { "label": "43/16", "naklon": 5 }, + "3026": { "label": "43/17", "naklon": null }, + "2986": { "label": "43/18", "naklon": null }, + "4343": { "label": "43/19", "naklon": null }, + "2760": { "label": "43/20", "naklon": null }, + "4379": { "label": "43/21", "naklon": null }, + "2971": { "label": "43/22", "naklon": null }, + "2761": { "label": "43/23", "naklon": null }, + "2762": { "label": "43/24", "naklon": null }, + "4339": { "label": "43/25", "naklon": null }, + "4380": { "label": "43/26", "naklon": null }, + "2975": { "label": "43/27", "naklon": null }, + "3003": { "label": "43/28", "naklon": null }, + "4338": { "label": "43/29", "naklon": null }, + "3002": { "label": "43/30", "naklon": null }, + "4345": { "label": "43/31", "naklon": null }, + "2979": { "label": "43/32", "naklon": null }, + "2989": { "label": "43/33", "naklon": null }, + "2996": { "label": "43/34", "naklon": null }, + "2972": { "label": "43/35", "naklon": null }, + "2988": { "label": "43/36", "naklon": null }, + "4344": { "label": "43/37", "naklon": null }, + "3022": { "label": "43/38", "naklon": null }, + "4341": { "label": "43/39", "naklon": null }, + "2983": { "label": "43/40", "naklon": null }, + "2995": { "label": "43/41", "naklon": null }, + "2763": { "label": "43/42", "naklon": null }, + "2764": { "label": "43/43", "naklon": null }, + "2765": { "label": "43/44", "naklon": null }, + "2766": { "label": "43/45", "naklon": null }, + "2767": { "label": "43/46", "naklon": null }, + "2768": { "label": "43/47", "naklon": null }, + "3018": { "label": "43/48", "naklon": null }, + "2982": { "label": "43/49", "naklon": null }, + "3019": { "label": "43/50", "naklon": 0 }, + "3013": { "label": "43/51", "naklon": null }, + "3007": { "label": "43/52", "naklon": null }, + "2980": { "label": "43/53", "naklon": null }, + "3011": { "label": "43/54", "naklon": null }, + "2672": { "label": "43/55", "naklon": null }, + "2673": { "label": "43/56", "naklon": null }, + "2674": { "label": "43/57", "naklon": null }, + "2675": { "label": "43/58", "naklon": null }, + "2676": { "label": "43/59", "naklon": null }, + "2677": { "label": "43/60", "naklon": null }, + "2678": { "label": "43/61", "naklon": null }, + "2679": { "label": "43/62", "naklon": null }, + "2680": { "label": "43/63", "naklon": null }, + "2840": { "label": "43/64", "naklon": null }, + "2682": { "label": "43/65", "naklon": null }, + "2683": { "label": "43/66", "naklon": null }, + "2684": { "label": "43/67", "naklon": 0 }, + "2685": { "label": "43/68", "naklon": null }, + "2686": { "label": "43/69", "naklon": null }, + "2687": { "label": "43/70", "naklon": null }, + "2688": { "label": "43/71", "naklon": null }, + "2689": { "label": "43/72", "naklon": null }, + "2690": { "label": "43/73", "naklon": null }, + "2691": { "label": "43/74", "naklon": null }, + "2692": { "label": "43/75", "naklon": null }, + "2693": { "label": "43/76", "naklon": 0 }, + "2694": { "label": "43/77", "naklon": null }, + "2695": { "label": "43/78", "naklon": null }, + "2696": { "label": "43/79", "naklon": 0 }, + "2697": { "label": "43/80", "naklon": null }, + "2698": { "label": "43/81", "naklon": 0 }, + "2699": { "label": "43/82", "naklon": null }, + "2700": { "label": "43/83", "naklon": 0 }, + "2744": { "label": "43/84", "naklon": null }, + "2745": { "label": "43/85", "naklon": 0 }, + "2746": { "label": "43/86", "naklon": null }, + "2747": { "label": "43/87", "naklon": 0 }, + "2748": { "label": "43/88", "naklon": null }, + "2749": { "label": "43/89", "naklon": 0 }, + "2841": { "label": "43/90", "naklon": null }, + "4237": { "label": "45/1", "naklon": 5 }, + "4226": { "label": "45/2", "naklon": 5 }, + "4242": { "label": "45/3", "naklon": 5 }, + "4179": { "label": "45/4", "naklon": 5 }, + "4247": { "label": "45/5", "naklon": 5 }, + "4245": { "label": "45/6", "naklon": 5 }, + "3872": { "label": "45/7", "naklon": 5 }, + "4175": { "label": "45/8", "naklon": 5 }, + "4236": { "label": "45/9", "naklon": 5 }, + "4170": { "label": "45/10", "naklon": 5 }, + "4238": { "label": "45/11", "naklon": 5 }, + "4246": { "label": "45/12", "naklon": 5 }, + "4166": { "label": "45/13", "naklon": 5 }, + "4227": { "label": "45/14", "naklon": 5 }, + "4171": { "label": "45/15", "naklon": 5 }, + "4180": { "label": "45/16", "naklon": 5 }, + "4244": { "label": "45/17", "naklon": 5 }, + "4199": { "label": "45/18", "naklon": 5 }, + "4239": { "label": "45/19", "naklon": 5 }, + "4207": { "label": "45/20", "naklon": 5 }, + "4223": { "label": "45/21", "naklon": 5 }, + "4230": { "label": "45/22", "naklon": 5 }, + "4233": { "label": "45/23", "naklon": 5 }, + "4222": { "label": "45/24", "naklon": 5 }, + "4217": { "label": "45/25", "naklon": 5 }, + "4243": { "label": "45/26", "naklon": 5 }, + "4200": { "label": "45/27", "naklon": 5 }, + "4228": { "label": "45/28", "naklon": 5 }, + "4211": { "label": "45/29", "naklon": 5 }, + "4234": { "label": "45/30", "naklon": 5 }, + "4235": { "label": "45/31", "naklon": 5 }, + "4203": { "label": "45/32", "naklon": 5 }, + "4240": { "label": "45/33", "naklon": 5 }, + "4224": { "label": "45/34", "naklon": 5 }, + "4232": { "label": "45/35", "naklon": 5 }, + "4231": { "label": "45/36", "naklon": 5 }, + "4161": { "label": "45/37", "naklon": 5 }, + "4225": { "label": "45/38", "naklon": 5 }, + "4241": { "label": "45/39", "naklon": 5 }, + "4229": { "label": "45/40", "naklon": 5 }, + "4221": { "label": "45/41", "naklon": 5 }, + "4212": { "label": "45/42", "naklon": 5 }, + "4216": { "label": "45/43", "naklon": 5 }, + "3864": { "label": "45/44", "naklon": null }, + "3806": { "label": "46/1", "naklon": 5 }, + "3813": { "label": "46/2", "naklon": 5 }, + "3815": { "label": "46/3", "naklon": 5 }, + "3807": { "label": "46/4", "naklon": 5 }, + "3895": { "label": "46/5", "naklon": 5 }, + "3809": { "label": "46/6", "naklon": 5 }, + "3820": { "label": "46/7", "naklon": 5 }, + "3805": { "label": "46/8", "naklon": 5 }, + "3894": { "label": "46/9", "naklon": 0 }, + "4055": { "label": "46/10", "naklon": 0 }, + "3812": { "label": "46/11", "naklon": 5 }, + "3822": { "label": "46/12", "naklon": 5 }, + "3821": { "label": "46/13", "naklon": 5 }, + "3808": { "label": "46/14", "naklon": 5 }, + "3799": { "label": "46/15", "naklon": 5 }, + "3816": { "label": "46/16", "naklon": 5 }, + "3751": { "label": "46/17", "naklon": 5 }, + "3814": { "label": "46/18", "naklon": 5 }, + "4044": { "label": "46/19", "naklon": 0 }, + "3931": { "label": "46/20", "naklon": 0 }, + "3902": { "label": "46/21", "naklon": 5 }, + "3916": { "label": "46/22", "naklon": 5 }, + "3892": { "label": "46/23", "naklon": 5 }, + "3914": { "label": "46/24", "naklon": 5 }, + "3898": { "label": "46/25", "naklon": 5 }, + "3897": { "label": "46/26", "naklon": 5 }, + "3885": { "label": "46/27", "naklon": 5 }, + "3906": { "label": "46/28", "naklon": 5 }, + "3930": { "label": "46/29", "naklon": 0 }, + "3936": { "label": "46/30", "naklon": 0 }, + "3860": { "label": "46/31", "naklon": 5 }, + "3841": { "label": "46/32", "naklon": 5 }, + "3873": { "label": "46/33", "naklon": 5 }, + "3854": { "label": "46/34", "naklon": 5 }, + "3939": { "label": "46/35", "naklon": 5 }, + "3858": { "label": "46/36", "naklon": 5 }, + "3940": { "label": "46/37", "naklon": 5 }, + "4035": { "label": "46/38", "naklon": 5 }, + "3373": { "label": "47/1", "naklon": 0 }, + "3374": { "label": "47/2", "naklon": 0 }, + "3384": { "label": "47/3", "naklon": 0 }, + "3385": { "label": "47/4", "naklon": 0 }, + "4051": { "label": "48/1", "naklon": 5 }, + "4041": { "label": "48/2", "naklon": 5 }, + "4056": { "label": "48/3", "naklon": 5 }, + "3875": { "label": "48/4", "naklon": 5 }, + "4061": { "label": "48/5", "naklon": 5 }, + "4047": { "label": "48/6", "naklon": 5 }, + "4060": { "label": "48/7", "naklon": 5 }, + "4059": { "label": "48/8", "naklon": 5 }, + "4058": { "label": "48/9", "naklon": 5 }, + "3635": { "label": "48/10", "naklon": 5 }, + "3640": { "label": "48/11", "naklon": 5 }, + "3747": { "label": "48/12", "naklon": 5 }, + "3629": { "label": "48/13", "naklon": 5 }, + "4048": { "label": "48/14", "naklon": 5 }, + "4063": { "label": "48/15", "naklon": 5 }, + "4062": { "label": "48/16", "naklon": 5 }, + "4043": { "label": "48/17", "naklon": 5 }, + "4052": { "label": "48/18", "naklon": 5 }, + "4042": { "label": "48/19", "naklon": 5 }, + "4053": { "label": "48/20", "naklon": 5 }, + "4167": { "label": "50/15A", "naklon": null }, + "4159": { "label": "50/15B", "naklon": null }, + "4183": { "label": "50/1", "naklon": 0 }, + "4157": { "label": "50/2", "naklon": 0 }, + "4160": { "label": "50/3", "naklon": 0 }, + "4173": { "label": "50/4", "naklon": 0 }, + "4177": { "label": "50/5", "naklon": 0 }, + "4174": { "label": "50/6", "naklon": 0 }, + "4178": { "label": "50/7", "naklon": 0 }, + "4195": { "label": "50/8", "naklon": 0 }, + "4169": { "label": "50/9", "naklon": 0 }, + "4162": { "label": "50/10", "naklon": 0 }, + "4158": { "label": "50/11", "naklon": 0 }, + "4182": { "label": "50/12", "naklon": 0 }, + "4194": { "label": "50/13", "naklon": 0 }, + "4184": { "label": "50/14", "naklon": 0 }, + "4197": { "label": "50/16", "naklon": null }, + "4164": { "label": "50/17", "naklon": null }, + "3306": { "label": "50/18", "naklon": null }, + "4168": { "label": "50/19", "naklon": null }, + "4193": { "label": "50/20", "naklon": null }, + "4187": { "label": "50/21", "naklon": null }, + "4163": { "label": "50/22", "naklon": null }, + "4165": { "label": "50/23", "naklon": null }, + "4185": { "label": "50/24", "naklon": null }, + "3904": { "label": "50/25", "naklon": null }, + "2619": { "label": "53/1", "naklon": 0 }, + "2623": { "label": "53/2", "naklon": 0 }, + "2617": { "label": "53/3", "naklon": 0 }, + "2622": { "label": "53/4", "naklon": 0 }, + "2618": { "label": "53/5", "naklon": 0 }, + "2626": { "label": "53/6", "naklon": 0 }, + "2869": { "label": "53/7", "naklon": 0 }, + "2613": { "label": "53/8", "naklon": 0 }, + "2608": { "label": "53/9", "naklon": 0 }, + "2611": { "label": "53/10", "naklon": 0 }, + "2598": { "label": "53/11", "naklon": 0 }, + "3528": { "label": "53/12", "naklon": 0 }, + "3545": { "label": "53/13", "naklon": 0 }, + "2620": { "label": "53/14", "naklon": 0 }, + "2612": { "label": "53/15", "naklon": 0 }, + "2615": { "label": "53/16", "naklon": 0 }, + "3722": { "label": "53/17", "naklon": 0 }, + "2624": { "label": "53/18", "naklon": 0 }, + "2609": { "label": "53/19", "naklon": 0 }, + "2625": { "label": "53/20", "naklon": 0 }, + "2602": { "label": "53/21", "naklon": 0 }, + "2610": { "label": "53/22", "naklon": 0 }, + "2599": { "label": "53/23", "naklon": 0 }, + "2605": { "label": "53/24", "naklon": 0 }, + "2593": { "label": "53/25", "naklon": 0 }, + "3074": { "label": "53/26", "naklon": 0 }, + "2740": { "label": "53/27", "naklon": 0 }, + "2614": { "label": "53/28", "naklon": 0 }, + "2601": { "label": "53/29", "naklon": 0 }, + "4196": { "label": "53/30", "naklon": 0 }, + "2607": { "label": "53/31", "naklon": 0 }, + "2582": { "label": "53/32", "naklon": 0 }, + "2594": { "label": "53/33", "naklon": 0 }, + "2589": { "label": "53/34", "naklon": 0 }, + "2596": { "label": "53/35", "naklon": 0 }, + "2603": { "label": "53/36", "naklon": 0 }, + "2597": { "label": "53/37", "naklon": 0 }, + "2590": { "label": "53/38", "naklon": 0 }, + "2581": { "label": "53/39", "naklon": 0 }, + "2583": { "label": "53/40", "naklon": 0 }, + "2580": { "label": "53/41", "naklon": 0 }, + "2579": { "label": "53/42", "naklon": 0 }, + "2797": { "label": "53/43", "naklon": 0 }, + "2577": { "label": "53/44", "naklon": 0 }, + "2586": { "label": "53/45", "naklon": 0 }, + "2588": { "label": "53/46", "naklon": 0 }, + "2591": { "label": "53/47", "naklon": 0 }, + "2592": { "label": "53/48", "naklon": 0 }, + "2573": { "label": "53/49", "naklon": 0 }, + "2595": { "label": "53/50", "naklon": 0 }, + "2587": { "label": "53/51", "naklon": 0 }, + "2578": { "label": "53/52", "naklon": 0 }, + "2574": { "label": "53/53", "naklon": 0 }, + "2571": { "label": "53/54", "naklon": 0 }, + "2570": { "label": "53/55", "naklon": 0 }, + "2576": { "label": "53/56", "naklon": 0 }, + "2881": { "label": "53/57", "naklon": 0 }, + "2575": { "label": "53/58", "naklon": 0 }, + "2572": { "label": "53/59", "naklon": 0 }, + "2569": { "label": "53/60", "naklon": 0 }, + "4324": { "label": "55/1", "naklon": 0 }, + "4319": { "label": "55/2", "naklon": 0 }, + "4327": { "label": "55/3", "naklon": 0 }, + "4333": { "label": "55/4", "naklon": 0 }, + "4332": { "label": "55/5", "naklon": 0 }, + "4320": { "label": "55/6", "naklon": 0 }, + "4317": { "label": "55/7", "naklon": 0 }, + "4318": { "label": "55/8", "naklon": 0 }, + "4328": { "label": "55/9", "naklon": 0 }, + "4323": { "label": "55/10", "naklon": 0 }, + "4325": { "label": "55/11", "naklon": 0 }, + "4326": { "label": "55/12", "naklon": 0 }, + "4316": { "label": "55/13", "naklon": 0 }, + "4322": { "label": "55/14", "naklon": 0 }, + "4331": { "label": "55/15", "naklon": 0 }, + "4321": { "label": "55/16", "naklon": 0 }, + "4315": { "label": "55/17", "naklon": 0 }, + "4329": { "label": "55/18", "naklon": 0 }, + "4334": { "label": "55/19", "naklon": 0 }, + "4330": { "label": "55/20", "naklon": 0 } +}; + + +let svetlaSorted = [{ "label": "1/3A", "node": 3993, "naklon": 0 }, +{ "label": "1/3B", "node": 3989, "naklon": 15 }, +{ "label": "1/1", "node": 3976, "naklon": 0 }, +{ "label": "1/2", "node": 4181, "naklon": 0 }, +{ "label": "1/4", "node": 4376, "naklon": 15 }, +{ "label": "1/5", "node": 3868, "naklon": 15 }, +{ "label": "1/6", "node": 3728, "naklon": 15 }, +{ "label": "1/7", "node": 3730, "naklon": 0 }, +{ "label": "1/8", "node": 4374, "naklon": 0 }, +{ "label": "1/9", "node": 3718, "naklon": 15 }, +{ "label": "1/10", "node": 4375, "naklon": 15 }, +{ "label": "1/11", "node": 4172, "naklon": 15 }, +{ "label": "1/12", "node": 4176, "naklon": 15 }, +{ "label": "2/1", "node": 3800, "naklon": 5 }, +{ "label": "2/2", "node": 3823, "naklon": 5 }, +{ "label": "2/3", "node": 3905, "naklon": 5 }, +{ "label": "2/4", "node": 3803, "naklon": 5 }, +{ "label": "2/5", "node": 3817, "naklon": 5 }, +{ "label": "2/6", "node": 3818, "naklon": 5 }, +{ "label": "2/7", "node": 3811, "naklon": 5 }, +{ "label": "2/8", "node": 3915, "naklon": 5 }, +{ "label": "2/9", "node": 3843, "naklon": 10 }, +{ "label": "2/10", "node": 3827, "naklon": 10 }, +{ "label": "2/11", "node": 4220, "naklon": 10 }, +{ "label": "2/12", "node": 3826, "naklon": 10 }, +{ "label": "2/13", "node": 3834, "naklon": 10 }, +{ "label": "2/14", "node": 3838, "naklon": 10 }, +{ "label": "2/15", "node": 2823, "naklon": 10 }, +{ "label": "2/16", "node": 3750, "naklon": 10 }, +{ "label": "2/17", "node": 3378, "naklon": 0 }, +{ "label": "2/18", "node": 3376, "naklon": 0 }, +{ "label": "2/19", "node": 3379, "naklon": 0 }, +{ "label": "2/20", "node": 3285, "naklon": 0 }, +{ "label": "2/21", "node": 3382, "naklon": 0 }, +{ "label": "2/22", "node": 3383, "naklon": 0 }, +{ "label": "2/24", "node": 3375, "naklon": 0 }, +{ "label": "2/25", "node": 3381, "naklon": 0 }, +{ "label": "2/26", "node": 3380, "naklon": 0 }, +{ "label": "2/27", "node": 3828, "naklon": 10 }, +{ "label": "2/28", "node": 3377, "naklon": 0 }, +{ "label": "7/1", "node": 3591, "naklon": 0 }, +{ "label": "7/2", "node": 3587, "naklon": 0 }, +{ "label": "7/3", "node": 3468, "naklon": 0 }, +{ "label": "7/4", "node": 3466, "naklon": 0 }, +{ "label": "7/5", "node": 3474, "naklon": 0 }, +{ "label": "7/6", "node": 3481, "naklon": 0 }, +{ "label": "7/7", "node": 3589, "naklon": 0 }, +{ "label": "7/8", "node": 3472, "naklon": 0 }, +{ "label": "7/9", "node": 3473, "naklon": 0 }, +{ "label": "7/10", "node": 3584, "naklon": 0 }, +{ "label": "7/11", "node": 3571, "naklon": 0 }, +{ "label": "7/12", "node": 3476, "naklon": 0 }, +{ "label": "7/13", "node": 3590, "naklon": 0 }, +{ "label": "7/14", "node": 3478, "naklon": 0 }, +{ "label": "7/15", "node": 3471, "naklon": 0 }, +{ "label": "7/16", "node": 3467, "naklon": 0 }, +{ "label": "7/17", "node": 3479, "naklon": 0 }, +{ "label": "7/18", "node": 3480, "naklon": 0 }, +{ "label": "7/19", "node": 3477, "naklon": 0 }, +{ "label": "12/1", "node": 3362, "naklon": 0 }, +{ "label": "12/2", "node": 3355, "naklon": 0 }, +{ "label": "12/3", "node": 3356, "naklon": 0 }, +{ "label": "12/4", "node": 3349, "naklon": 0 }, +{ "label": "12/5", "node": 3357, "naklon": 0 }, +{ "label": "12/6", "node": 3350, "naklon": 0 }, +{ "label": "12/7", "node": 3353, "naklon": 0 }, +{ "label": "12/8", "node": 3539, "naklon": 0 }, +{ "label": "12/9", "node": 3050, "naklon": 0 }, +{ "label": "12/10", "node": 3361, "naklon": 0 }, +{ "label": "12/11", "node": 3360, "naklon": 0 }, +{ "label": "12/12", "node": 3358, "naklon": 0 }, +{ "label": "12/13", "node": 3541, "naklon": 0 }, +{ "label": "12/14", "node": 3551, "naklon": 0 }, +{ "label": "12/15", "node": 3514, "naklon": 0 }, +{ "label": "12/16", "node": 3547, "naklon": 0 }, +{ "label": "12/17", "node": 3562, "naklon": 0 }, +{ "label": "12/18", "node": 3525, "naklon": 0 }, +{ "label": "12/19", "node": 3558, "naklon": 0 }, +{ "label": "12/20", "node": 3511, "naklon": 0 }, +{ "label": "12/21", "node": 3058, "naklon": 0 }, +{ "label": "12/22", "node": 3062, "naklon": 0 }, +{ "label": "12/23", "node": 3070, "naklon": 0 }, +{ "label": "12/24", "node": 3447, "naklon": 0 }, +{ "label": "12/25", "node": 3056, "naklon": 0 }, +{ "label": "12/26", "node": 3057, "naklon": 0 }, +{ "label": "12/27", "node": 3071, "naklon": 0 }, +{ "label": "12/28", "node": 3061, "naklon": 0 }, +{ "label": "12/29", "node": 3069, "naklon": 0 }, +{ "label": "12/30", "node": 3077, "naklon": 0 }, +{ "label": "12/31", "node": 3080, "naklon": 0 }, +{ "label": "12/32", "node": 3081, "naklon": 0 }, +{ "label": "12/33", "node": 3078, "naklon": 0 }, +{ "label": "12/34", "node": 4037, "naklon": 0 }, +{ "label": "12/35", "node": 3067, "naklon": 0 }, +{ "label": "12/36", "node": 3051, "naklon": 0 }, +{ "label": "12/37", "node": 2924, "naklon": 0 }, +{ "label": "12/38", "node": 3060, "naklon": 0 }, +{ "label": "12/39", "node": 3073, "naklon": 0 }, +{ "label": "12/40", "node": 3469, "naklon": 0 }, +{ "label": "12/41", "node": 2923, "naklon": 0 }, +{ "label": "12/42", "node": 2925, "naklon": 0 }, +{ "label": "12/43", "node": 3359, "naklon": 0 }, +{ "label": "12/44", "node": 3055, "naklon": 0 }, +{ "label": "12/45", "node": 2922, "naklon": 0 }, +{ "label": "12/46", "node": 3084, "naklon": 0 }, +{ "label": "12/47", "node": 3064, "naklon": 0 }, +{ "label": "12/48", "node": 3066, "naklon": 0 }, +{ "label": "12/49", "node": 3072, "naklon": 0 }, +{ "label": "13/13A", "node": 3415, "naklon": 0 }, +{ "label": "13/13B", "node": 3409, "naklon": 0 }, +{ "label": "13/13C", "node": 3399, "naklon": 0 }, +{ "label": "13/29A", "node": 3410, "naklon": 0 }, +{ "label": "13/29B", "node": 3407, "naklon": 0 }, +{ "label": "13/34A", "node": 3405, "naklon": 0 }, +{ "label": "13/34B", "node": 3404, "naklon": 0 }, +{ "label": "13/45A", "node": 3392, "naklon": 0 }, +{ "label": "13/45B", "node": 3386, "naklon": 0 }, +{ "label": "13/60A", "node": 3303, "naklon": 3 }, +{ "label": "13/60B", "node": 3302, "naklon": 3 }, +{ "label": "13/70A", "node": 3319, "naklon": 6 }, +{ "label": "13/70B", "node": 3317, "naklon": 6 }, +{ "label": "13/70C", "node": 3326, "naklon": 6 }, +{ "label": "13/73A", "node": 3351, "naklon": 6 }, +{ "label": "13/73B", "node": 3313, "naklon": 6 }, +{ "label": "13/83A", "node": 3316, "naklon": 0 }, +{ "label": "13/83B", "node": 3320, "naklon": 0 }, +{ "label": "13/95A", "node": 3336, "naklon": 0 }, +{ "label": "13/95B", "node": 3323, "naklon": 0 }, +{ "label": "13/98A", "node": 3339, "naklon": 0 }, +{ "label": "13/98B", "node": 3333, "naklon": 0 }, +{ "label": "13/1", "node": 3425, "naklon": 0 }, +{ "label": "13/2", "node": 3419, "naklon": 0 }, +{ "label": "13/3", "node": 3416, "naklon": 0 }, +{ "label": "13/4", "node": 3332, "naklon": 0 }, +{ "label": "13/5", "node": 3422, "naklon": 0 }, +{ "label": "13/6", "node": 3417, "naklon": 0 }, +{ "label": "13/7", "node": 3418, "naklon": 0 }, +{ "label": "13/8", "node": 3424, "naklon": 0 }, +{ "label": "13/9", "node": 3334, "naklon": 0 }, +{ "label": "13/10", "node": 4363, "naklon": 0 }, +{ "label": "13/11", "node": 3423, "naklon": 0 }, +{ "label": "13/12", "node": 3406, "naklon": 0 }, +{ "label": "13/14", "node": 3411, "naklon": 0 }, +{ "label": "13/15", "node": 3412, "naklon": 0 }, +{ "label": "13/16", "node": 3413, "naklon": 0 }, +{ "label": "13/17", "node": 3414, "naklon": 0 }, +{ "label": "13/18", "node": 3391, "naklon": 0 }, +{ "label": "13/19", "node": 3370, "naklon": 0 }, +{ "label": "13/20", "node": 3369, "naklon": 0 }, +{ "label": "13/21", "node": 3408, "naklon": 0 }, +{ "label": "13/22", "node": 3393, "naklon": 0 }, +{ "label": "13/23", "node": 3128, "naklon": 0 }, +{ "label": "13/24", "node": 3197, "naklon": 0 }, +{ "label": "13/25", "node": 4364, "naklon": 0 }, +{ "label": "13/26", "node": 3155, "naklon": 0 }, +{ "label": "13/27", "node": 3196, "naklon": 0 }, +{ "label": "13/28", "node": 3144, "naklon": 0 }, +{ "label": "13/30", "node": 3150, "naklon": 0 }, +{ "label": "13/31", "node": 3390, "naklon": 0 }, +{ "label": "13/32", "node": 3401, "naklon": 0 }, +{ "label": "13/33", "node": 3275, "naklon": 0 }, +{ "label": "13/35", "node": 3371, "naklon": 0 }, +{ "label": "13/36", "node": 3389, "naklon": 0 }, +{ "label": "13/37", "node": 3388, "naklon": 0 }, +{ "label": "13/38", "node": 3365, "naklon": 0 }, +{ "label": "13/39", "node": 3363, "naklon": 0 }, +{ "label": "13/40", "node": 3397, "naklon": 0 }, +{ "label": "13/40/1", "node": 3567, "naklon": 0 }, +{ "label": "13/41", "node": 3387, "naklon": 0 }, +{ "label": "13/42", "node": 3403, "naklon": 0 }, +{ "label": "13/43", "node": 3147, "naklon": 0 }, +{ "label": "13/44", "node": 3141, "naklon": 0 }, +{ "label": "13/46", "node": 3364, "naklon": 0 }, +{ "label": "13/47", "node": 3367, "naklon": 0 }, +{ "label": "13/48", "node": 3368, "naklon": 0 }, +{ "label": "13/49", "node": 3402, "naklon": 0 }, +{ "label": "13/50", "node": 3366, "naklon": 0 }, +{ "label": "13/51", "node": 3395, "naklon": 0 }, +{ "label": "13/52", "node": 3372, "naklon": 0 }, +{ "label": "13/53", "node": 3394, "naklon": 0 }, +{ "label": "13/54", "node": 3308, "naklon": 0 }, +{ "label": "13/54/1", "node": 3847, "naklon": 0 }, +{ "label": "13/55", "node": 3312, "naklon": 3 }, +{ "label": "13/56", "node": 3309, "naklon": 3 }, +{ "label": "13/57", "node": 3311, "naklon": 3 }, +{ "label": "13/58", "node": 3310, "naklon": 3 }, +{ "label": "13/59", "node": 4365, "naklon": 3 }, +{ "label": "13/60/1", "node": 4093, "naklon": 3 }, +{ "label": "13/61", "node": 3304, "naklon": 3 }, +{ "label": "13/62", "node": 3307, "naklon": 3 }, +{ "label": "13/63", "node": 3271, "naklon": 3 }, +{ "label": "13/64", "node": 3301, "naklon": 3 }, +{ "label": "13/65", "node": 4366, "naklon": 3 }, +{ "label": "13/66", "node": 3300, "naklon": 3 }, +{ "label": "13/67", "node": 3185, "naklon": 0 }, +{ "label": "13/68", "node": 3184, "naklon": 0 }, +{ "label": "13/69", "node": 3188, "naklon": 0 }, +{ "label": "13/71", "node": 3343, "naklon": 6 }, +{ "label": "13/71/1", "node": 3819, "naklon": 6 }, +{ "label": "13/71/2", "node": 3880, "naklon": 6 }, +{ "label": "13/72", "node": 3348, "naklon": 6 }, +{ "label": "13/74", "node": 3344, "naklon": 6 }, +{ "label": "13/75", "node": 3346, "naklon": 6 }, +{ "label": "13/75/1", "node": 3597, "naklon": 6 }, +{ "label": "13/76", "node": 3345, "naklon": 6 }, +{ "label": "13/77", "node": 3322, "naklon": 0 }, +{ "label": "13/78", "node": 3325, "naklon": 0 }, +{ "label": "13/78/1", "node": 4310, "naklon": 0 }, +{ "label": "13/79", "node": 3315, "naklon": 0 }, +{ "label": "13/80", "node": 3328, "naklon": 0 }, +{ "label": "13/81", "node": 3321, "naklon": 0 }, +{ "label": "13/82", "node": 3324, "naklon": 0 }, +{ "label": "13/84", "node": 3140, "naklon": 0 }, +{ "label": "13/85", "node": 3153, "naklon": 0 }, +{ "label": "13/86", "node": 3145, "naklon": 0 }, +{ "label": "13/87", "node": 3134, "naklon": 0 }, +{ "label": "13/88", "node": 3151, "naklon": 0 }, +{ "label": "13/89", "node": 3143, "naklon": 0 }, +{ "label": "13/90", "node": 3318, "naklon": 0 }, +{ "label": "13/91", "node": 3347, "naklon": 0 }, +{ "label": "13/94", "node": 3314, "naklon": 0 }, +{ "label": "13/96", "node": 3331, "naklon": 0 }, +{ "label": "13/97", "node": 3327, "naklon": 0 }, +{ "label": "13/99", "node": 3329, "naklon": 0 }, +{ "label": "13/100", "node": 3337, "naklon": 0 }, +{ "label": "13/101", "node": 3330, "naklon": 0 }, +{ "label": "13/102", "node": 3335, "naklon": 0 }, +{ "label": "13/103", "node": 3420, "naklon": 0 }, +{ "label": "13/104", "node": 3421, "naklon": 0 }, +{ "label": "13/105", "node": 4361, "naklon": 0 }, +{ "label": "13/106", "node": 4362, "naklon": 0 }, +{ "label": "13/107", "node": 3526, "naklon": 0 }, +{ "label": "13/108", "node": 4424, "naklon": null }, +{ "label": "13/109", "node": 3561, "naklon": null }, +{ "label": "13/110", "node": 3527, "naklon": null }, +{ "label": "13/111", "node": 3521, "naklon": null }, +{ "label": "13/112", "node": 3552, "naklon": null }, +{ "label": "13/113", "node": 3544, "naklon": null }, +{ "label": "13/114", "node": 3534, "naklon": null }, +{ "label": "13/115", "node": 3516, "naklon": null }, +{ "label": "13/116", "node": 3513, "naklon": null }, +{ "label": "13/117", "node": 3565, "naklon": null }, +{ "label": "13/118", "node": 3866, "naklon": null }, +{ "label": "14/1", "node": 3136, "naklon": 0 }, +{ "label": "14/2", "node": 3137, "naklon": 0 }, +{ "label": "14/3", "node": 3135, "naklon": 0 }, +{ "label": "14/4", "node": 3149, "naklon": 0 }, +{ "label": "14/5", "node": 3142, "naklon": 0 }, +{ "label": "14/6", "node": 3342, "naklon": 0 }, +{ "label": "14/7", "node": 3340, "naklon": 0 }, +{ "label": "14/8", "node": 3152, "naklon": 0 }, +{ "label": "14/9", "node": 3886, "naklon": 0 }, +{ "label": "14/10", "node": 3341, "naklon": null }, +{ "label": "14/11", "node": 3352, "naklon": null }, +{ "label": "15/1", "node": 3396, "naklon": 5 }, +{ "label": "15/2", "node": 2784, "naklon": 5 }, +{ "label": "15/3", "node": 2788, "naklon": 5 }, +{ "label": "15/4", "node": 2801, "naklon": 5 }, +{ "label": "15/5", "node": 2815, "naklon": 5 }, +{ "label": "15/6", "node": 2829, "naklon": 5 }, +{ "label": "15/7", "node": 2796, "naklon": 5 }, +{ "label": "15/8", "node": 2803, "naklon": 5 }, +{ "label": "15/8/1", "node": 4304, "naklon": 5 }, +{ "label": "15/8/2", "node": 4311, "naklon": 5 }, +{ "label": "15/9", "node": 2821, "naklon": 5 }, +{ "label": "15/10", "node": 3400, "naklon": 5 }, +{ "label": "15/11", "node": 2799, "naklon": 5 }, +{ "label": "15/12", "node": 2804, "naklon": 5 }, +{ "label": "15/12/1", "node": 4303, "naklon": 5 }, +{ "label": "15/12/2", "node": 4309, "naklon": 5 }, +{ "label": "15/13", "node": 2806, "naklon": 5 }, +{ "label": "15/14", "node": 2787, "naklon": 5 }, +{ "label": "15/15", "node": 2809, "naklon": 5 }, +{ "label": "15/16", "node": 2814, "naklon": 0 }, +{ "label": "15/17", "node": 3934, "naklon": 0 }, +{ "label": "15/18", "node": 3192, "naklon": 0 }, +{ "label": "15/19", "node": 2812, "naklon": 0 }, +{ "label": "15/20", "node": 4070, "naklon": 0 }, +{ "label": "15/21", "node": 2826, "naklon": 0 }, +{ "label": "15/22", "node": 2808, "naklon": 3 }, +{ "label": "15/23", "node": 2795, "naklon": 3 }, +{ "label": "15/24", "node": 2807, "naklon": 3 }, +{ "label": "15/25", "node": 2831, "naklon": 0 }, +{ "label": "15/26", "node": 2862, "naklon": null }, +{ "label": "15/27", "node": 2861, "naklon": 0 }, +{ "label": "15/28", "node": 2866, "naklon": 0 }, +{ "label": "15/28/1", "node": 3546, "naklon": 0 }, +{ "label": "15/29", "node": 4146, "naklon": 0 }, +{ "label": "15/29/1", "node": 3001, "naklon": 0 }, +{ "label": "15/30", "node": 2835, "naklon": 0 }, +{ "label": "15/31", "node": 2874, "naklon": 0 }, +{ "label": "15/32", "node": 2852, "naklon": 0 }, +{ "label": "15/33", "node": 2851, "naklon": 0 }, +{ "label": "15/33/1", "node": 3560, "naklon": 0 }, +{ "label": "15/34", "node": 2858, "naklon": 0 }, +{ "label": "15/34/1", "node": 4306, "naklon": 0 }, +{ "label": "15/35", "node": 2856, "naklon": 0 }, +{ "label": "15/36", "node": 2847, "naklon": 0 }, +{ "label": "15/36/1", "node": 3556, "naklon": 0 }, +{ "label": "15/37", "node": 3950, "naklon": 0 }, +{ "label": "15/38", "node": 2848, "naklon": 0 }, +{ "label": "15/39", "node": 2863, "naklon": 0 }, +{ "label": "15/39/1", "node": 4313, "naklon": 0 }, +{ "label": "15/40", "node": 2873, "naklon": 0 }, +{ "label": "15/40/1", "node": 2984, "naklon": 0 }, +{ "label": "15/41", "node": 2854, "naklon": 0 }, +{ "label": "15/42", "node": 2859, "naklon": 0 }, +{ "label": "15/43", "node": 2872, "naklon": 0 }, +{ "label": "15/44", "node": 2849, "naklon": 0 }, +{ "label": "15/45", "node": 2864, "naklon": 0 }, +{ "label": "15/46", "node": 3553, "naklon": null }, +{ "label": "15/47", "node": 3021, "naklon": null }, +{ "label": "15/47/1", "node": 3008, "naklon": null }, +{ "label": "15/48", "node": 3017, "naklon": null }, +{ "label": "15/49", "node": 3014, "naklon": null }, +{ "label": "15/50", "node": 2981, "naklon": null }, +{ "label": "15/51", "node": 3020, "naklon": null }, +{ "label": "15/52", "node": 3027, "naklon": null }, +{ "label": "15/53", "node": 3006, "naklon": null }, +{ "label": "15/54", "node": 3012, "naklon": null }, +{ "label": "15/55", "node": 2738, "naklon": 0 }, +{ "label": "15/56", "node": 2725, "naklon": 0 }, +{ "label": "15/57", "node": 3016, "naklon": null }, +{ "label": "15/58", "node": 3005, "naklon": null }, +{ "label": "15/58/1", "node": 3009, "naklon": null }, +{ "label": "15/59", "node": 3010, "naklon": 0 }, +{ "label": "15/59/1", "node": 3538, "naklon": 0 }, +{ "label": "15/59/2", "node": 4145, "naklon": 0 }, +{ "label": "15/60", "node": 2713, "naklon": 0 }, +{ "label": "15/61", "node": 2789, "naklon": 0 }, +{ "label": "15/62", "node": 2736, "naklon": 0 }, +{ "label": "15/63", "node": 2739, "naklon": 0 }, +{ "label": "15/64", "node": 4346, "naklon": 0 }, +{ "label": "15/65", "node": 2731, "naklon": 0 }, +{ "label": "15/66", "node": 2818, "naklon": 0 }, +{ "label": "15/66/1", "node": 3557, "naklon": 0 }, +{ "label": "15/67", "node": 2822, "naklon": 0 }, +{ "label": "15/68", "node": 2833, "naklon": 0 }, +{ "label": "15/69", "node": 2834, "naklon": 0 }, +{ "label": "15/70", "node": 3097, "naklon": 0 }, +{ "label": "15/71", "node": 2824, "naklon": 0 }, +{ "label": "15/72", "node": 2828, "naklon": 0 }, +{ "label": "15/73", "node": 2600, "naklon": 0 }, +{ "label": "15/73/1", "node": 4314, "naklon": 0 }, +{ "label": "15/74", "node": 2832, "naklon": 0 }, +{ "label": "15/75", "node": 4360, "naklon": 0 }, +{ "label": "15/76", "node": 2846, "naklon": 0 }, +{ "label": "15/77", "node": 2584, "naklon": 0 }, +{ "label": "15/78", "node": 2843, "naklon": 0 }, +{ "label": "15/78/1", "node": 4308, "naklon": 0 }, +{ "label": "15/79", "node": 4144, "naklon": null }, +{ "label": "15/80", "node": 2844, "naklon": 0 }, +{ "label": "15/81", "node": 2842, "naklon": 0 }, +{ "label": "15/82", "node": 2838, "naklon": 0 }, +{ "label": "15/83", "node": 2837, "naklon": null }, +{ "label": "15/83/1", "node": 3555, "naklon": null }, +{ "label": "15/84", "node": 2839, "naklon": 0 }, +{ "label": "15/85", "node": 2830, "naklon": 0 }, +{ "label": "15/86", "node": 4066, "naklon": 0 }, +{ "label": "15/87", "node": 2836, "naklon": 0 }, +{ "label": "15/88", "node": 2911, "naklon": 0 }, +{ "label": "15/89", "node": 2825, "naklon": 0 }, +{ "label": "15/90", "node": 2811, "naklon": 0 }, +{ "label": "15/94", "node": 3740, "naklon": 15 }, +{ "label": "15/95", "node": 2734, "naklon": 15 }, +{ "label": "15/96", "node": 3105, "naklon": 15 }, +{ "label": "15/97", "node": 2732, "naklon": 15 }, +{ "label": "15/98", "node": 2727, "naklon": 15 }, +{ "label": "15/99", "node": 2735, "naklon": 15 }, +{ "label": "15/100", "node": 3926, "naklon": 15 }, +{ "label": "15/101", "node": 2918, "naklon": 0 }, +{ "label": "15/102", "node": 2705, "naklon": 10 }, +{ "label": "15/103", "node": 2708, "naklon": 10 }, +{ "label": "15/104", "node": 2721, "naklon": 10 }, +{ "label": "15/105", "node": 2719, "naklon": 10 }, +{ "label": "15/106", "node": 2919, "naklon": 10 }, +{ "label": "15/107", "node": 3101, "naklon": 10 }, +{ "label": "15/108", "node": 2853, "naklon": 10 }, +{ "label": "15/109", "node": 2715, "naklon": 10 }, +{ "label": "15/110", "node": 2712, "naklon": 0 }, +{ "label": "15/111", "node": 2711, "naklon": 0 }, +{ "label": "15/112", "node": 2709, "naklon": 0 }, +{ "label": "15/113", "node": 2710, "naklon": 0 }, +{ "label": "15/114", "node": 2907, "naklon": 0 }, +{ "label": "15/115", "node": 2906, "naklon": 0 }, +{ "label": "15/116", "node": 2908, "naklon": 0 }, +{ "label": "15/117", "node": 2901, "naklon": 0 }, +{ "label": "15/118", "node": 2913, "naklon": 0 }, +{ "label": "15/119", "node": 3656, "naklon": 0 }, +{ "label": "15/120", "node": 2781, "naklon": 0 }, +{ "label": "15/121", "node": 2802, "naklon": 0 }, +{ "label": "15/122", "node": 2791, "naklon": 0 }, +{ "label": "15/123", "node": 2783, "naklon": 0 }, +{ "label": "15/124", "node": 2794, "naklon": 0 }, +{ "label": "15/125", "node": 3139, "naklon": 0 }, +{ "label": "15/126", "node": 3229, "naklon": 5 }, +{ "label": "15/127", "node": 3239, "naklon": 5 }, +{ "label": "15/128", "node": 3230, "naklon": 5 }, +{ "label": "15/129", "node": 4016, "naklon": null }, +{ "label": "16/16A", "node": 3608, "naklon": 0 }, +{ "label": "16/16B", "node": 4151, "naklon": 0 }, +{ "label": "16/1", "node": 3710, "naklon": 0 }, +{ "label": "16/2", "node": 3726, "naklon": 0 }, +{ "label": "16/3", "node": 3743, "naklon": 0 }, +{ "label": "16/4", "node": 3724, "naklon": 0 }, +{ "label": "16/5", "node": 3712, "naklon": 0 }, +{ "label": "16/6", "node": 3739, "naklon": 0 }, +{ "label": "16/7", "node": 3742, "naklon": 0 }, +{ "label": "16/8", "node": 3731, "naklon": 0 }, +{ "label": "16/9", "node": 3727, "naklon": 0 }, +{ "label": "16/10", "node": 3729, "naklon": 0 }, +{ "label": "16/11", "node": 3736, "naklon": 0 }, +{ "label": "16/12", "node": 3713, "naklon": 0 }, +{ "label": "16/13", "node": 3715, "naklon": 0 }, +{ "label": "16/14", "node": 3733, "naklon": 0 }, +{ "label": "16/15", "node": 3732, "naklon": 0 }, +{ "label": "16/17", "node": 3634, "naklon": 0 }, +{ "label": "16/18", "node": 3610, "naklon": 0 }, +{ "label": "16/19", "node": 3626, "naklon": 0 }, +{ "label": "16/20", "node": 3618, "naklon": 0 }, +{ "label": "16/21", "node": 3619, "naklon": 0 }, +{ "label": "16/22", "node": 3628, "naklon": 0 }, +{ "label": "16/23", "node": 3615, "naklon": 0 }, +{ "label": "16/24", "node": 3609, "naklon": 0 }, +{ "label": "16/25", "node": 3606, "naklon": 0 }, +{ "label": "16/26", "node": 3624, "naklon": 0 }, +{ "label": "16/27", "node": 3627, "naklon": 0 }, +{ "label": "16/28", "node": 3607, "naklon": 0 }, +{ "label": "16/29", "node": 4370, "naklon": 0 }, +{ "label": "16/30", "node": 3692, "naklon": 0 }, +{ "label": "16/31", "node": 3614, "naklon": 0 }, +{ "label": "16/32", "node": 3623, "naklon": 0 }, +{ "label": "16/33", "node": 4373, "naklon": 0 }, +{ "label": "16/34", "node": 3620, "naklon": 0 }, +{ "label": "16/35", "node": 3685, "naklon": 0 }, +{ "label": "16/36", "node": 3616, "naklon": 0 }, +{ "label": "16/37", "node": 3686, "naklon": 0 }, +{ "label": "16/38", "node": 3688, "naklon": 0 }, +{ "label": "16/39", "node": 3684, "naklon": 0 }, +{ "label": "16/40", "node": 3825, "naklon": 0 }, +{ "label": "16/41", "node": 3865, "naklon": 0 }, +{ "label": "16/42", "node": 3824, "naklon": 0 }, +{ "label": "16/43", "node": 3871, "naklon": 0 }, +{ "label": "16/44", "node": 3801, "naklon": 0 }, +{ "label": "16/45", "node": 3862, "naklon": 0 }, +{ "label": "16/46", "node": 3876, "naklon": 0 }, +{ "label": "16/47", "node": 3861, "naklon": 0 }, +{ "label": "16/48", "node": 4215, "naklon": 0 }, +{ "label": "16/49", "node": 3605, "naklon": 10 }, +{ "label": "16/50", "node": 3603, "naklon": 10 }, +{ "label": "16/51", "node": 3592, "naklon": 10 }, +{ "label": "16/52", "node": 3598, "naklon": 10 }, +{ "label": "16/53", "node": 3594, "naklon": 10 }, +{ "label": "16/54", "node": 3593, "naklon": 10 }, +{ "label": "16/55", "node": 3630, "naklon": 10 }, +{ "label": "16/56", "node": 3763, "naklon": 10 }, +{ "label": "16/57", "node": 3746, "naklon": 10 }, +{ "label": "16/58", "node": 3699, "naklon": 0 }, +{ "label": "16/59", "node": 3698, "naklon": 0 }, +{ "label": "16/60", "node": 3709, "naklon": null }, +{ "label": "16/61", "node": 3708, "naklon": 0 }, +{ "label": "16/62", "node": 3703, "naklon": null }, +{ "label": "16/63", "node": 3700, "naklon": 0 }, +{ "label": "16/64", "node": 3701, "naklon": null }, +{ "label": "16/65", "node": 3704, "naklon": 0 }, +{ "label": "16/66", "node": 3707, "naklon": null }, +{ "label": "16/67", "node": 3810, "naklon": 0 }, +{ "label": "16/68", "node": 4208, "naklon": null }, +{ "label": "16/69", "node": 3867, "naklon": 0 }, +{ "label": "16/70", "node": 4372, "naklon": null }, +{ "label": "16/71", "node": 3881, "naklon": 0 }, +{ "label": "16/72", "node": 4204, "naklon": null }, +{ "label": "16/73", "node": 3869, "naklon": 0 }, +{ "label": "16/74", "node": 4202, "naklon": null }, +{ "label": "16/75", "node": 3830, "naklon": 0 }, +{ "label": "16/76", "node": 3870, "naklon": null }, +{ "label": "16/77", "node": 3964, "naklon": 0 }, +{ "label": "16/78", "node": 3849, "naklon": 0 }, +{ "label": "16/79", "node": 3694, "naklon": null }, +{ "label": "16/80", "node": 3717, "naklon": 0 }, +{ "label": "16/81", "node": 3877, "naklon": null }, +{ "label": "16/82", "node": 3755, "naklon": 0 }, +{ "label": "16/83", "node": 3725, "naklon": null }, +{ "label": "16/84", "node": 3716, "naklon": 0 }, +{ "label": "16/85", "node": 3696, "naklon": null }, +{ "label": "16/86", "node": 3702, "naklon": 0 }, +{ "label": "16/87", "node": 3706, "naklon": null }, +{ "label": "16/88", "node": 3850, "naklon": 0 }, +{ "label": "16/89", "node": 3848, "naklon": null }, +{ "label": "16/90", "node": 3737, "naklon": null }, +{ "label": "16/91", "node": 3705, "naklon": 0 }, +{ "label": "16/92", "node": 3723, "naklon": null }, +{ "label": "16/93", "node": 3842, "naklon": 0 }, +{ "label": "16/94", "node": 3735, "naklon": null }, +{ "label": "16/95", "node": 3719, "naklon": 0 }, +{ "label": "16/96", "node": 3697, "naklon": 0 }, +{ "label": "16/97", "node": 3711, "naklon": 0 }, +{ "label": "16/98", "node": 4107, "naklon": null }, +{ "label": "16/99", "node": 4112, "naklon": 5 }, +{ "label": "16/100", "node": 4106, "naklon": 5 }, +{ "label": "16/101", "node": 4111, "naklon": 5 }, +{ "label": "16/102", "node": 4091, "naklon": null }, +{ "label": "16/103", "node": 4104, "naklon": 5 }, +{ "label": "16/104", "node": 4094, "naklon": null }, +{ "label": "16/105", "node": 4089, "naklon": 5 }, +{ "label": "16/106", "node": 4095, "naklon": null }, +{ "label": "16/107", "node": 4102, "naklon": 5 }, +{ "label": "16/108", "node": 4105, "naklon": null }, +{ "label": "16/109", "node": 3859, "naklon": null }, +{ "label": "16/110", "node": 4090, "naklon": 5 }, +{ "label": "16/111", "node": 4110, "naklon": null }, +{ "label": "16/112", "node": 4097, "naklon": 5 }, +{ "label": "16/113", "node": 4099, "naklon": null }, +{ "label": "16/114", "node": 4096, "naklon": null }, +{ "label": "16/115", "node": 4101, "naklon": 5 }, +{ "label": "16/116", "node": 4109, "naklon": null }, +{ "label": "16/117", "node": 4092, "naklon": 5 }, +{ "label": "16/118", "node": 3631, "naklon": null }, +{ "label": "16/119", "node": 3632, "naklon": 0 }, +{ "label": "16/120", "node": 3641, "naklon": null }, +{ "label": "16/121", "node": 3638, "naklon": 0 }, +{ "label": "16/122", "node": 3637, "naklon": null }, +{ "label": "16/123", "node": 4142, "naklon": null }, +{ "label": "16/124", "node": 4147, "naklon": 5 }, +{ "label": "16/125", "node": 4139, "naklon": 5 }, +{ "label": "20/30A", "node": 3172, "naklon": 2 }, +{ "label": "20/30B", "node": 3164, "naklon": 2 }, +{ "label": "20/1", "node": 3247, "naklon": 10 }, +{ "label": "20/2", "node": 3296, "naklon": 10 }, +{ "label": "20/3", "node": 3246, "naklon": 10 }, +{ "label": "20/4", "node": 3270, "naklon": 10 }, +{ "label": "20/5", "node": 3294, "naklon": 10 }, +{ "label": "20/6", "node": 3298, "naklon": 10 }, +{ "label": "20/7", "node": 3297, "naklon": 10 }, +{ "label": "20/8", "node": 3293, "naklon": 10 }, +{ "label": "20/9", "node": 3299, "naklon": 10 }, +{ "label": "20/10", "node": 3295, "naklon": 10 }, +{ "label": "20/11", "node": 3244, "naklon": 10 }, +{ "label": "20/12", "node": 3249, "naklon": 10 }, +{ "label": "20/13", "node": 3268, "naklon": 10 }, +{ "label": "20/14", "node": 3245, "naklon": 10 }, +{ "label": "20/15", "node": 3278, "naklon": 10 }, +{ "label": "20/16", "node": 3280, "naklon": 10 }, +{ "label": "20/17", "node": 3292, "naklon": 10 }, +{ "label": "20/18", "node": 3287, "naklon": 10 }, +{ "label": "20/19", "node": 3282, "naklon": 10 }, +{ "label": "20/20", "node": 3273, "naklon": 0 }, +{ "label": "20/21", "node": 3157, "naklon": 0 }, +{ "label": "20/22", "node": 3283, "naklon": 0 }, +{ "label": "20/23", "node": 3159, "naklon": 0 }, +{ "label": "20/24", "node": 3289, "naklon": 0 }, +{ "label": "20/25", "node": 3163, "naklon": 0 }, +{ "label": "20/26", "node": 3126, "naklon": 0 }, +{ "label": "20/27", "node": 3171, "naklon": 0 }, +{ "label": "20/28", "node": 3162, "naklon": 0 }, +{ "label": "20/29", "node": 3279, "naklon": 10 }, +{ "label": "20/31", "node": 3173, "naklon": 0 }, +{ "label": "20/32", "node": 3127, "naklon": 0 }, +{ "label": "20/33", "node": 3131, "naklon": 0 }, +{ "label": "20/34", "node": 3129, "naklon": 0 }, +{ "label": "20/35", "node": 3276, "naklon": 2 }, +{ "label": "20/36", "node": 3290, "naklon": 2 }, +{ "label": "20/37", "node": 3132, "naklon": 0 }, +{ "label": "20/38", "node": 3138, "naklon": 0 }, +{ "label": "20/39", "node": 3272, "naklon": 0 }, +{ "label": "20/40", "node": 3291, "naklon": 0 }, +{ "label": "20/41", "node": 3277, "naklon": 10 }, +{ "label": "20/42", "node": 3286, "naklon": 10 }, +{ "label": "20/43", "node": 3281, "naklon": 10 }, +{ "label": "20/44", "node": 3288, "naklon": 10 }, +{ "label": "20/45", "node": 3284, "naklon": 10 }, +{ "label": "20/46", "node": 3167, "naklon": 10 }, +{ "label": "20/47", "node": 3872, "naklon": 0 }, +{ "label": "20/48", "node": 3124, "naklon": 0 }, +{ "label": "20/49", "node": 3133, "naklon": 0 }, +{ "label": "20/50", "node": 3158, "naklon": 0 }, +{ "label": "20/51", "node": 3169, "naklon": 0 }, +{ "label": "20/52", "node": 3146, "naklon": 0 }, +{ "label": "20/53", "node": 3160, "naklon": 0 }, +{ "label": "20/54", "node": 3248, "naklon": 0 }, +{ "label": "20/55", "node": 3156, "naklon": 0 }, +{ "label": "20/56", "node": 3161, "naklon": 0 }, +{ "label": "20/57", "node": 3170, "naklon": 0 }, +{ "label": "20/58", "node": 3168, "naklon": 0 }, +{ "label": "20/59", "node": 3125, "naklon": 0 }, +{ "label": "20/60", "node": 3166, "naklon": 0 }, +{ "label": "20/61", "node": 3130, "naklon": 0 }, +{ "label": "20/62", "node": 3563, "naklon": 0 }, +{ "label": "20/63", "node": 3550, "naklon": null }, +{ "label": "20/67", "node": 3269, "naklon": 0 }, +{ "label": "21/1", "node": 2921, "naklon": 0 }, +{ "label": "21/2", "node": 2707, "naklon": 0 }, +{ "label": "21/3", "node": 2723, "naklon": 0 }, +{ "label": "21/4", "node": 2716, "naklon": 0 }, +{ "label": "21/5", "node": 2717, "naklon": 0 }, +{ "label": "21/6", "node": 2720, "naklon": 0 }, +{ "label": "21/7", "node": 2722, "naklon": 0 }, +{ "label": "21/8", "node": 2718, "naklon": 0 }, +{ "label": "21/9", "node": 2724, "naklon": 0 }, +{ "label": "21/10", "node": 2742, "naklon": 0 }, +{ "label": "21/11", "node": 2743, "naklon": 0 }, +{ "label": "21/12", "node": 2733, "naklon": 0 }, +{ "label": "21/14", "node": 2903, "naklon": 0 }, +{ "label": "21/15", "node": 2917, "naklon": 0 }, +{ "label": "21/16", "node": 2897, "naklon": 0 }, +{ "label": "21/17", "node": 2914, "naklon": 0 }, +{ "label": "21/18", "node": 2898, "naklon": 0 }, +{ "label": "21/19", "node": 2773, "naklon": 0 }, +{ "label": "21/20", "node": 2895, "naklon": 0 }, +{ "label": "21/21", "node": 2896, "naklon": 0 }, +{ "label": "21/22", "node": 2771, "naklon": 0 }, +{ "label": "21/23", "node": 2772, "naklon": 0 }, +{ "label": "21/24", "node": 2793, "naklon": 0 }, +{ "label": "21/25", "node": 2902, "naklon": 0 }, +{ "label": "21/26", "node": 2910, "naklon": 0 }, +{ "label": "21/27", "node": 2909, "naklon": 0 }, +{ "label": "21/28", "node": 2920, "naklon": 0 }, +{ "label": "21/29", "node": 2916, "naklon": 0 }, +{ "label": "21/30", "node": 2904, "naklon": 0 }, +{ "label": "21/31", "node": 2915, "naklon": 0 }, +{ "label": "21/32", "node": 2905, "naklon": 0 }, +{ "label": "21/33", "node": 2900, "naklon": 0 }, +{ "label": "21/34", "node": 2899, "naklon": 0 }, +{ "label": "21/36", "node": 2741, "naklon": 0 }, +{ "label": "21/37", "node": 2714, "naklon": 0 }, +{ "label": "21/38", "node": 2701, "naklon": 0 }, +{ "label": "21/39", "node": 2703, "naklon": 0 }, +{ "label": "21/40", "node": 2704, "naklon": 0 }, +{ "label": "21/41", "node": 2702, "naklon": 0 }, +{ "label": "21/42", "node": 2706, "naklon": 0 }, +{ "label": "21/43", "node": 2776, "naklon": 0 }, +{ "label": "21/44", "node": 2770, "naklon": 0 }, +{ "label": "21/45", "node": 2786, "naklon": 0 }, +{ "label": "21/46", "node": 2779, "naklon": 0 }, +{ "label": "21/47", "node": 2782, "naklon": 0 }, +{ "label": "21/48", "node": 2785, "naklon": 0 }, +{ "label": "21/49", "node": 2769, "naklon": 0 }, +{ "label": "21/50", "node": 3354, "naklon": 0 }, +{ "label": "21/51", "node": 2778, "naklon": 0 }, +{ "label": "21/52", "node": 2775, "naklon": 0 }, +{ "label": "21/53", "node": 2780, "naklon": 0 }, +{ "label": "21/54", "node": 2790, "naklon": 0 }, +{ "label": "21/55", "node": 2792, "naklon": 0 }, +{ "label": "21/56", "node": 2774, "naklon": 0 }, +{ "label": "22/1", "node": 2630, "naklon": 0 }, +{ "label": "22/2", "node": 2631, "naklon": 0 }, +{ "label": "22/3", "node": 2632, "naklon": 0 }, +{ "label": "22/4", "node": 2633, "naklon": 0 }, +{ "label": "22/5", "node": 2634, "naklon": 0 }, +{ "label": "22/6", "node": 2636, "naklon": 0 }, +{ "label": "22/7", "node": 4367, "naklon": 0 }, +{ "label": "22/8", "node": 2637, "naklon": 0 }, +{ "label": "22/9", "node": 2638, "naklon": 0 }, +{ "label": "22/10", "node": 2639, "naklon": 0 }, +{ "label": "22/11", "node": 2640, "naklon": 0 }, +{ "label": "22/12", "node": 2641, "naklon": 0 }, +{ "label": "22/13", "node": 2642, "naklon": 0 }, +{ "label": "22/14", "node": 2643, "naklon": 0 }, +{ "label": "22/15", "node": 2644, "naklon": 0 }, +{ "label": "22/16", "node": 2645, "naklon": 0 }, +{ "label": "22/17", "node": 2646, "naklon": 0 }, +{ "label": "22/18", "node": 2647, "naklon": 0 }, +{ "label": "22/19", "node": 2648, "naklon": 0 }, +{ "label": "22/20", "node": 2649, "naklon": 0 }, +{ "label": "22/21", "node": 2650, "naklon": 0 }, +{ "label": "22/22", "node": 2651, "naklon": 0 }, +{ "label": "22/23", "node": 4103, "naklon": 0 }, +{ "label": "22/24", "node": 2653, "naklon": 0 }, +{ "label": "22/25", "node": 2654, "naklon": 0 }, +{ "label": "22/26", "node": 2655, "naklon": 0 }, +{ "label": "22/27", "node": 2656, "naklon": 0 }, +{ "label": "22/28", "node": 2657, "naklon": 0 }, +{ "label": "22/29", "node": 2658, "naklon": 0 }, +{ "label": "22/30", "node": 2659, "naklon": 0 }, +{ "label": "22/31", "node": 2660, "naklon": 0 }, +{ "label": "22/32", "node": 2661, "naklon": 0 }, +{ "label": "22/32/1", "node": 3015, "naklon": 0 }, +{ "label": "22/33", "node": 2662, "naklon": 0 }, +{ "label": "22/34", "node": 2663, "naklon": 0 }, +{ "label": "22/35", "node": 2664, "naklon": 0 }, +{ "label": "22/36", "node": 2665, "naklon": 0 }, +{ "label": "22/37", "node": 2666, "naklon": 0 }, +{ "label": "22/38", "node": 2667, "naklon": 0 }, +{ "label": "22/39", "node": 2668, "naklon": 0 }, +{ "label": "22/40", "node": 2669, "naklon": null }, +{ "label": "22/41", "node": 2670, "naklon": null }, +{ "label": "22/42", "node": 2671, "naklon": null }, +{ "label": "23/9A", "node": 3087, "naklon": 10 }, +{ "label": "23/9B", "node": 3090, "naklon": 10 }, +{ "label": "23/1", "node": 3075, "naklon": 0 }, +{ "label": "23/2", "node": 3089, "naklon": 0 }, +{ "label": "23/3", "node": 3088, "naklon": 0 }, +{ "label": "23/4", "node": 3228, "naklon": 10 }, +{ "label": "23/5", "node": 2751, "naklon": 10 }, +{ "label": "23/6", "node": 3243, "naklon": 10 }, +{ "label": "23/7", "node": 4349, "naklon": 10 }, +{ "label": "23/8", "node": 3102, "naklon": 10 }, +{ "label": "23/10", "node": 3099, "naklon": 10 }, +{ "label": "23/11", "node": 3103, "naklon": 10 }, +{ "label": "23/12", "node": 3093, "naklon": 10 }, +{ "label": "23/13", "node": 3098, "naklon": 10 }, +{ "label": "23/14", "node": 3092, "naklon": 10 }, +{ "label": "23/15", "node": 3233, "naklon": 0 }, +{ "label": "23/16", "node": 3095, "naklon": 0 }, +{ "label": "23/17", "node": 4074, "naklon": 0 }, +{ "label": "23/18", "node": 2729, "naklon": 0 }, +{ "label": "23/19", "node": 3234, "naklon": 0 }, +{ "label": "23/20", "node": 3094, "naklon": 0 }, +{ "label": "23/21", "node": 2817, "naklon": 0 }, +{ "label": "23/22", "node": 3226, "naklon": 0 }, +{ "label": "23/23", "node": 3225, "naklon": 0 }, +{ "label": "23/24", "node": 3237, "naklon": 0 }, +{ "label": "23/25", "node": 4250, "naklon": 0 }, +{ "label": "23/26", "node": 3059, "naklon": 10 }, +{ "label": "23/27", "node": 3238, "naklon": 10 }, +{ "label": "23/28", "node": 3242, "naklon": 10 }, +{ "label": "23/29", "node": 3236, "naklon": 10 }, +{ "label": "23/30", "node": 3112, "naklon": 10 }, +{ "label": "23/31", "node": 3224, "naklon": 0 }, +{ "label": "23/32", "node": 4298, "naklon": 10 }, +{ "label": "23/33", "node": 4150, "naklon": 10 }, +{ "label": "23/34", "node": 3091, "naklon": 10 }, +{ "label": "25/1", "node": 3771, "naklon": 5 }, +{ "label": "25/2", "node": 3777, "naklon": 5 }, +{ "label": "25/3", "node": 3749, "naklon": 5 }, +{ "label": "25/4", "node": 3769, "naklon": 5 }, +{ "label": "25/5", "node": 3765, "naklon": 5 }, +{ "label": "25/6", "node": 3785, "naklon": 5 }, +{ "label": "25/7", "node": 3761, "naklon": 5 }, +{ "label": "25/8", "node": 3758, "naklon": 5 }, +{ "label": "25/9", "node": 3766, "naklon": 5 }, +{ "label": "25/10", "node": 3779, "naklon": 5 }, +{ "label": "25/11", "node": 3899, "naklon": 10 }, +{ "label": "25/12", "node": 3922, "naklon": 10 }, +{ "label": "25/13", "node": 3912, "naklon": 10 }, +{ "label": "25/14", "node": 3933, "naklon": 10 }, +{ "label": "25/15", "node": 3921, "naklon": 10 }, +{ "label": "25/16", "node": 4300, "naklon": 10 }, +{ "label": "25/17", "node": 3927, "naklon": 10 }, +{ "label": "25/18", "node": 3212, "naklon": 10 }, +{ "label": "25/19", "node": 3208, "naklon": 10 }, +{ "label": "25/20", "node": 3207, "naklon": 10 }, +{ "label": "25/21", "node": 4294, "naklon": 10 }, +{ "label": "25/22", "node": 3209, "naklon": 10 }, +{ "label": "25/23", "node": 3745, "naklon": 10 }, +{ "label": "25/24", "node": 3762, "naklon": 10 }, +{ "label": "25/25", "node": 3215, "naklon": 10 }, +{ "label": "25/26", "node": 3210, "naklon": 10 }, +{ "label": "25/27", "node": 3211, "naklon": 10 }, +{ "label": "25/28", "node": 3206, "naklon": 10 }, +{ "label": "25/29", "node": 3918, "naklon": 5 }, +{ "label": "25/30", "node": 3928, "naklon": 5 }, +{ "label": "25/31", "node": 3917, "naklon": 5 }, +{ "label": "25/32", "node": 4029, "naklon": 0 }, +{ "label": "25/33", "node": 4038, "naklon": 0 }, +{ "label": "25/34", "node": 4022, "naklon": 0 }, +{ "label": "25/35", "node": 3937, "naklon": 0 }, +{ "label": "25/36", "node": 3190, "naklon": 0 }, +{ "label": "25/37", "node": 3835, "naklon": 0 }, +{ "label": "25/38", "node": 3201, "naklon": 0 }, +{ "label": "25/39", "node": 3193, "naklon": 0 }, +{ "label": "25/40", "node": 3191, "naklon": 0 }, +{ "label": "25/41", "node": 3203, "naklon": 0 }, +{ "label": "25/42", "node": 4301, "naklon": 0 }, +{ "label": "25/43", "node": 3223, "naklon": 0 }, +{ "label": "25/44", "node": 3202, "naklon": 0 }, +{ "label": "25/45", "node": 3205, "naklon": 0 }, +{ "label": "25/46", "node": 3194, "naklon": 0 }, +{ "label": "25/47", "node": 3198, "naklon": 0 }, +{ "label": "25/48", "node": 3204, "naklon": 0 }, +{ "label": "25/49", "node": 3200, "naklon": 0 }, +{ "label": "25/50", "node": 3216, "naklon": 0 }, +{ "label": "25/51", "node": 3932, "naklon": 5 }, +{ "label": "25/52", "node": 3923, "naklon": 5 }, +{ "label": "25/53", "node": 3913, "naklon": 5 }, +{ "label": "25/54", "node": 3900, "naklon": 5 }, +{ "label": "25/55", "node": 4189, "naklon": 10 }, +{ "label": "25/56", "node": 4191, "naklon": 10 }, +{ "label": "25/57", "node": 3790, "naklon": 10 }, +{ "label": "25/58", "node": 4190, "naklon": 10 }, +{ "label": "25/59", "node": 4302, "naklon": 0 }, +{ "label": "25/60", "node": 4351, "naklon": 0 }, +{ "label": "25/61", "node": 4075, "naklon": 0 }, +{ "label": "25/62", "node": 4071, "naklon": 0 }, +{ "label": "25/63", "node": 3784, "naklon": 0 }, +{ "label": "25/64", "node": 4065, "naklon": 0 }, +{ "label": "25/65", "node": 4297, "naklon": 0 }, +{ "label": "25/66", "node": 4295, "naklon": 0 }, +{ "label": "25/67", "node": 4299, "naklon": 0 }, +{ "label": "25/68", "node": 3772, "naklon": 0 }, +{ "label": "25/69", "node": 3941, "naklon": 0 }, +{ "label": "25/70", "node": 3782, "naklon": 0 }, +{ "label": "25/71", "node": 4068, "naklon": 0 }, +{ "label": "25/72", "node": 4073, "naklon": 0 }, +{ "label": "25/73", "node": 3901, "naklon": 5 }, +{ "label": "25/74", "node": 4296, "naklon": 5 }, +{ "label": "25/75", "node": 3910, "naklon": 5 }, +{ "label": "25/76", "node": 4293, "naklon": 5 }, +{ "label": "25/77", "node": 3919, "naklon": 5 }, +{ "label": "25/78", "node": 3924, "naklon": 5 }, +{ "label": "25/79", "node": 3909, "naklon": 5 }, +{ "label": "25/80", "node": 3896, "naklon": 5 }, +{ "label": "25/81", "node": 3911, "naklon": 5 }, +{ "label": "25/82", "node": 2819, "naklon": 15 }, +{ "label": "25/83", "node": 3776, "naklon": 15 }, +{ "label": "25/84", "node": 3752, "naklon": 15 }, +{ "label": "25/85", "node": 4353, "naklon": 15 }, +{ "label": "25/86", "node": 3791, "naklon": 0 }, +{ "label": "25/87", "node": 3770, "naklon": 0 }, +{ "label": "25/88", "node": 3760, "naklon": 0 }, +{ "label": "25/89", "node": 3115, "naklon": 0 }, +{ "label": "25/90", "node": 3738, "naklon": 0 }, +{ "label": "25/91", "node": 3748, "naklon": 0 }, +{ "label": "25/92", "node": 3753, "naklon": 0 }, +{ "label": "25/93", "node": 3775, "naklon": 0 }, +{ "label": "25/94", "node": 3778, "naklon": 5 }, +{ "label": "25/95", "node": 4078, "naklon": 5 }, +{ "label": "25/96", "node": 4088, "naklon": 5 }, +{ "label": "25/97", "node": 3856, "naklon": 5 }, +{ "label": "25/98", "node": 4084, "naklon": 5 }, +{ "label": "25/99", "node": 4069, "naklon": 5 }, +{ "label": "25/100", "node": 4188, "naklon": 5 }, +{ "label": "25/101", "node": 4064, "naklon": 5 }, +{ "label": "25/102", "node": 3792, "naklon": 5 }, +{ "label": "25/103", "node": 3780, "naklon": 5 }, +{ "label": "25/104", "node": 4034, "naklon": 5 }, +{ "label": "25/105", "node": 4072, "naklon": 5 }, +{ "label": "25/106", "node": 3884, "naklon": 5 }, +{ "label": "25/107", "node": 3793, "naklon": 5 }, +{ "label": "25/108", "node": 3863, "naklon": 5 }, +{ "label": "25/109", "node": 3855, "naklon": 5 }, +{ "label": "33/1", "node": 3846, "naklon": 0 }, +{ "label": "33/2", "node": 3943, "naklon": 0 }, +{ "label": "33/3", "node": 3903, "naklon": 0 }, +{ "label": "33/4", "node": 3982, "naklon": 0 }, +{ "label": "33/5", "node": 3879, "naklon": 0 }, +{ "label": "33/6", "node": 3887, "naklon": 0 }, +{ "label": "33/7", "node": 3920, "naklon": 5 }, +{ "label": "33/8", "node": 3942, "naklon": 5 }, +{ "label": "33/9", "node": 3829, "naklon": null }, +{ "label": "34/79A", "node": 3452, "naklon": 6 }, +{ "label": "34/79B", "node": 3460, "naklon": 6 }, +{ "label": "34/90A", "node": 3443, "naklon": 6 }, +{ "label": "34/90B", "node": 3445, "naklon": 6 }, +{ "label": "34/90C", "node": 3457, "naklon": 6 }, +{ "label": "34/97A", "node": 3461, "naklon": 6 }, +{ "label": "34/97B", "node": 3463, "naklon": 6 }, +{ "label": "34/98A", "node": 3426, "naklon": 6 }, +{ "label": "34/98B", "node": 3444, "naklon": 6 }, +{ "label": "34/99A", "node": 3453, "naklon": 6 }, +{ "label": "34/99B", "node": 3455, "naklon": 6 }, +{ "label": "34/1", "node": 4009, "naklon": 0 }, +{ "label": "34/2", "node": 3602, "naklon": 0 }, +{ "label": "34/3", "node": 3441, "naklon": 0 }, +{ "label": "34/4", "node": 3464, "naklon": 0 }, +{ "label": "34/5", "node": 3883, "naklon": 0 }, +{ "label": "34/6", "node": 4098, "naklon": 0 }, +{ "label": "34/7", "node": 4003, "naklon": 0 }, +{ "label": "34/8", "node": 4004, "naklon": 0 }, +{ "label": "34/9", "node": 3888, "naklon": 0 }, +{ "label": "34/10", "node": 3997, "naklon": 0 }, +{ "label": "34/11", "node": 4006, "naklon": 0 }, +{ "label": "34/12", "node": 4000, "naklon": 0 }, +{ "label": "34/13", "node": 4011, "naklon": 0 }, +{ "label": "34/14", "node": 3999, "naklon": 0 }, +{ "label": "34/15", "node": 3981, "naklon": 0 }, +{ "label": "34/16", "node": 3988, "naklon": 0 }, +{ "label": "34/17", "node": 3986, "naklon": 0 }, +{ "label": "34/18", "node": 3998, "naklon": 0 }, +{ "label": "34/19", "node": 3983, "naklon": 0 }, +{ "label": "34/20", "node": 4005, "naklon": 0 }, +{ "label": "34/21", "node": 4001, "naklon": 0 }, +{ "label": "34/22", "node": 4008, "naklon": 0 }, +{ "label": "34/23", "node": 4002, "naklon": 0 }, +{ "label": "34/24", "node": 3996, "naklon": 0 }, +{ "label": "34/25", "node": 4007, "naklon": 0 }, +{ "label": "34/26", "node": 4113, "naklon": 15 }, +{ "label": "34/27", "node": 3595, "naklon": 5 }, +{ "label": "34/28", "node": 3599, "naklon": 5 }, +{ "label": "34/29", "node": 3601, "naklon": 5 }, +{ "label": "34/30", "node": 4205, "naklon": 0 }, +{ "label": "34/31", "node": 3987, "naklon": null }, +{ "label": "34/32", "node": 4214, "naklon": 0 }, +{ "label": "34/33", "node": 4226, "naklon": 0 }, +{ "label": "34/34", "node": 4209, "naklon": 0 }, +{ "label": "34/35", "node": 4201, "naklon": 0 }, +{ "label": "34/36", "node": 3440, "naklon": 0 }, +{ "label": "34/37", "node": 3465, "naklon": 0 }, +{ "label": "34/38", "node": 3446, "naklon": 0 }, +{ "label": "34/39", "node": 4039, "naklon": 5 }, +{ "label": "34/40", "node": 4057, "naklon": 5 }, +{ "label": "34/41", "node": 3985, "naklon": 0 }, +{ "label": "34/42", "node": 3882, "naklon": 0 }, +{ "label": "34/43", "node": 4040, "naklon": 5 }, +{ "label": "34/44", "node": 3231, "naklon": 0 }, +{ "label": "34/45", "node": 3227, "naklon": 0 }, +{ "label": "34/46", "node": 3431, "naklon": 0 }, +{ "label": "34/47", "node": 4013, "naklon": 0 }, +{ "label": "34/48", "node": 4045, "naklon": 0 }, +{ "label": "34/49", "node": 3949, "naklon": 0 }, +{ "label": "34/50", "node": 3953, "naklon": 0 }, +{ "label": "34/51", "node": 3952, "naklon": 0 }, +{ "label": "34/52", "node": 3995, "naklon": 0 }, +{ "label": "34/53", "node": 3992, "naklon": 0 }, +{ "label": "34/54", "node": 4198, "naklon": 0 }, +{ "label": "34/55", "node": 3935, "naklon": 0 }, +{ "label": "34/56", "node": 4050, "naklon": 0 }, +{ "label": "34/57", "node": 4049, "naklon": 0 }, +{ "label": "34/58", "node": 4054, "naklon": 0 }, +{ "label": "34/59", "node": 3663, "naklon": 6 }, +{ "label": "34/60", "node": 3661, "naklon": 6 }, +{ "label": "34/61", "node": 3664, "naklon": 6 }, +{ "label": "34/62", "node": 3660, "naklon": 6 }, +{ "label": "34/63", "node": 3662, "naklon": 6 }, +{ "label": "34/65", "node": 3665, "naklon": 6 }, +{ "label": "34/66", "node": 3667, "naklon": 6 }, +{ "label": "34/67", "node": 3675, "naklon": 6 }, +{ "label": "34/68", "node": 3666, "naklon": 6 }, +{ "label": "34/69", "node": 3652, "naklon": 6 }, +{ "label": "34/70", "node": 3458, "naklon": 6 }, +{ "label": "34/70/1", "node": 4425, "naklon": 6 }, +{ "label": "34/71", "node": 3459, "naklon": 6 }, +{ "label": "34/72", "node": 3435, "naklon": 6 }, +{ "label": "34/73", "node": 3448, "naklon": 6 }, +{ "label": "34/74", "node": 3451, "naklon": 6 }, +{ "label": "34/75", "node": 3442, "naklon": 6 }, +{ "label": "34/76", "node": 3449, "naklon": 6 }, +{ "label": "34/77", "node": 3450, "naklon": 6 }, +{ "label": "34/78", "node": 3433, "naklon": 6 }, +{ "label": "34/80", "node": 3432, "naklon": 12 }, +{ "label": "34/81", "node": 3470, "naklon": 12 }, +{ "label": "34/82", "node": 3438, "naklon": 12 }, +{ "label": "34/83", "node": 3439, "naklon": 12 }, +{ "label": "34/84", "node": 4028, "naklon": 5 }, +{ "label": "34/85", "node": 3596, "naklon": 5 }, +{ "label": "34/86", "node": 4021, "naklon": 5 }, +{ "label": "34/87", "node": 3437, "naklon": 12 }, +{ "label": "34/88", "node": 3428, "naklon": 12 }, +{ "label": "34/89", "node": 3430, "naklon": 12 }, +{ "label": "34/91", "node": 3454, "naklon": 6 }, +{ "label": "34/92", "node": 3492, "naklon": 6 }, +{ "label": "34/93", "node": 3462, "naklon": 6 }, +{ "label": "34/94", "node": 3427, "naklon": 6 }, +{ "label": "34/95", "node": 3434, "naklon": 6 }, +{ "label": "34/96", "node": 3456, "naklon": 6 }, +{ "label": "34/98/1", "node": 4307, "naklon": 6 }, +{ "label": "35/1", "node": 3968, "naklon": 0 }, +{ "label": "35/2", "node": 3969, "naklon": 0 }, +{ "label": "35/3", "node": 3947, "naklon": 0 }, +{ "label": "35/4", "node": 3979, "naklon": 0 }, +{ "label": "35/5", "node": 3959, "naklon": 0 }, +{ "label": "35/6", "node": 3948, "naklon": 0 }, +{ "label": "35/7", "node": 3961, "naklon": 0 }, +{ "label": "35/8", "node": 3956, "naklon": 0 }, +{ "label": "35/9", "node": 3604, "naklon": 0 }, +{ "label": "35/10", "node": 3944, "naklon": 0 }, +{ "label": "35/11", "node": 3960, "naklon": 0 }, +{ "label": "35/12", "node": 3958, "naklon": 0 }, +{ "label": "35/13", "node": 4036, "naklon": 5 }, +{ "label": "35/18", "node": 3893, "naklon": 5 }, +{ "label": "35/19", "node": 4108, "naklon": 5 }, +{ "label": "35/20", "node": 4017, "naklon": 5 }, +{ "label": "35/21", "node": 3963, "naklon": 0 }, +{ "label": "35/22", "node": 3658, "naklon": 0 }, +{ "label": "35/23", "node": 3975, "naklon": 0 }, +{ "label": "35/24", "node": 3980, "naklon": 0 }, +{ "label": "35/25", "node": 4012, "naklon": 0 }, +{ "label": "35/26", "node": 3655, "naklon": 0 }, +{ "label": "35/27", "node": 3962, "naklon": 0 }, +{ "label": "35/28", "node": 3945, "naklon": 0 }, +{ "label": "35/29", "node": 3569, "naklon": 0 }, +{ "label": "35/30", "node": 3429, "naklon": 0 }, +{ "label": "35/31", "node": 3657, "naklon": 0 }, +{ "label": "35/32", "node": 3646, "naklon": 0 }, +{ "label": "35/33", "node": 3622, "naklon": 0 }, +{ "label": "35/34", "node": 3612, "naklon": 0 }, +{ "label": "35/35", "node": 3955, "naklon": 0 }, +{ "label": "35/37", "node": 3878, "naklon": 0 }, +{ "label": "35/38", "node": 3965, "naklon": 0 }, +{ "label": "35/39", "node": 3970, "naklon": 0 }, +{ "label": "35/40", "node": 3611, "naklon": 0 }, +{ "label": "35/41", "node": 2635, "naklon": 0 }, +{ "label": "35/42", "node": 3978, "naklon": 0 }, +{ "label": "35/43", "node": 4213, "naklon": 0 }, +{ "label": "35/44", "node": 3984, "naklon": 0 }, +{ "label": "35/45", "node": 4218, "naklon": 0 }, +{ "label": "35/46", "node": 3973, "naklon": 0 }, +{ "label": "35/47", "node": 3974, "naklon": 0 }, +{ "label": "35/48", "node": 3759, "naklon": 0 }, +{ "label": "35/49", "node": 3844, "naklon": 0 }, +{ "label": "35/50", "node": 3804, "naklon": 0 }, +{ "label": "35/51", "node": 3831, "naklon": 0 }, +{ "label": "35/52", "node": 3643, "naklon": 0 }, +{ "label": "35/53", "node": 3966, "naklon": 0 }, +{ "label": "35/54", "node": 3971, "naklon": 0 }, +{ "label": "35/55", "node": 3650, "naklon": 6 }, +{ "label": "35/56", "node": 3651, "naklon": 6 }, +{ "label": "35/57", "node": 3669, "naklon": 6 }, +{ "label": "35/58", "node": 3648, "naklon": 6 }, +{ "label": "35/59", "node": 3645, "naklon": 6 }, +{ "label": "35/60", "node": 3659, "naklon": 6 }, +{ "label": "35/61", "node": 3647, "naklon": 6 }, +{ "label": "35/62", "node": 3644, "naklon": 6 }, +{ "label": "35/63", "node": 3671, "naklon": 6 }, +{ "label": "35/64", "node": 3682, "naklon": 6 }, +{ "label": "35/65", "node": 3672, "naklon": 6 }, +{ "label": "35/66", "node": 3683, "naklon": 6 }, +{ "label": "35/67", "node": 3673, "naklon": 6 }, +{ "label": "35/68", "node": 3674, "naklon": 6 }, +{ "label": "35/69", "node": 3679, "naklon": 6 }, +{ "label": "35/70", "node": 3649, "naklon": 6 }, +{ "label": "35/71", "node": 3687, "naklon": 6 }, +{ "label": "35/72", "node": 3677, "naklon": 6 }, +{ "label": "35/73", "node": 3690, "naklon": 6 }, +{ "label": "35/74", "node": 3691, "naklon": 6 }, +{ "label": "35/75", "node": 3676, "naklon": 6 }, +{ "label": "35/76", "node": 3680, "naklon": 6 }, +{ "label": "35/77", "node": 3668, "naklon": 6 }, +{ "label": "35/78", "node": 3681, "naklon": 6 }, +{ "label": "35/79", "node": 3670, "naklon": 6 }, +{ "label": "35/80", "node": 3689, "naklon": 6 }, +{ "label": "35/81", "node": 3678, "naklon": 6 }, +{ "label": "35/82", "node": 3693, "naklon": 6 }, +{ "label": "35/83", "node": 3654, "naklon": null }, +{ "label": "36/1", "node": 4086, "naklon": 0 }, +{ "label": "36/2", "node": 4085, "naklon": 0 }, +{ "label": "36/3", "node": 4083, "naklon": 0 }, +{ "label": "36/4", "node": 4087, "naklon": 0 }, +{ "label": "36/5", "node": 4077, "naklon": 0 }, +{ "label": "36/6", "node": 4082, "naklon": 0 }, +{ "label": "36/7", "node": 4186, "naklon": 0 }, +{ "label": "36/8", "node": 4206, "naklon": 0 }, +{ "label": "36/9", "node": 4080, "naklon": 0 }, +{ "label": "36/10", "node": 4081, "naklon": 0 }, +{ "label": "36/11", "node": 4210, "naklon": 0 }, +{ "label": "36/12", "node": 4079, "naklon": 0 }, +{ "label": "36/13", "node": 4076, "naklon": 0 }, +{ "label": "36/14", "node": 3852, "naklon": 0 }, +{ "label": "36/15", "node": 2813, "naklon": 0 }, +{ "label": "36/16", "node": 4219, "naklon": 0 }, +{ "label": "37/1A", "node": 3104, "naklon": 15 }, +{ "label": "37/1B", "node": 3121, "naklon": 15 }, +{ "label": "37/2", "node": 3113, "naklon": 10 }, +{ "label": "37/3", "node": 3118, "naklon": 10 }, +{ "label": "37/4", "node": 3111, "naklon": 10 }, +{ "label": "37/5", "node": 4020, "naklon": 10 }, +{ "label": "37/6", "node": 3119, "naklon": 10 }, +{ "label": "37/7", "node": 3110, "naklon": 10 }, +{ "label": "37/8", "node": 3108, "naklon": 10 }, +{ "label": "37/12", "node": 3107, "naklon": 0 }, +{ "label": "37/13", "node": 3199, "naklon": 0 }, +{ "label": "37/14", "node": 3120, "naklon": 0 }, +{ "label": "37/15", "node": 3122, "naklon": 0 }, +{ "label": "37/16", "node": 3908, "naklon": 0 }, +{ "label": "37/17", "node": 3114, "naklon": 0 }, +{ "label": "37/18", "node": 3105, "naklon": 0 }, +{ "label": "37/19", "node": 3116, "naklon": 0 }, +{ "label": "37/20", "node": 3106, "naklon": 0 }, +{ "label": "37/21", "node": 2887, "naklon": 5 }, +{ "label": "37/22", "node": 2888, "naklon": 5 }, +{ "label": "37/23", "node": 2877, "naklon": 5 }, +{ "label": "37/24", "node": 2891, "naklon": 5 }, +{ "label": "37/25", "node": 2886, "naklon": 5 }, +{ "label": "37/26", "node": 2892, "naklon": 5 }, +{ "label": "37/27", "node": 2882, "naklon": 5 }, +{ "label": "37/28", "node": 2883, "naklon": 5 }, +{ "label": "37/29", "node": 2876, "naklon": 5 }, +{ "label": "37/30", "node": 3109, "naklon": 5 }, +{ "label": "37/31", "node": 4152, "naklon": 5 }, +{ "label": "37/32", "node": 3117, "naklon": 5 }, +{ "label": "37/33", "node": 2870, "naklon": 5 }, +{ "label": "37/34", "node": 2867, "naklon": 0 }, +{ "label": "37/35", "node": 2865, "naklon": 0 }, +{ "label": "37/36", "node": 3096, "naklon": 0 }, +{ "label": "37/37", "node": 2871, "naklon": 0 }, +{ "label": "37/38", "node": 2884, "naklon": 0 }, +{ "label": "37/39", "node": 2855, "naklon": 0 }, +{ "label": "37/40", "node": 2878, "naklon": 0 }, +{ "label": "37/41", "node": 2889, "naklon": 0 }, +{ "label": "37/42", "node": 2879, "naklon": 0 }, +{ "label": "37/43", "node": 2850, "naklon": 0 }, +{ "label": "37/44", "node": 2894, "naklon": 0 }, +{ "label": "37/45", "node": 2880, "naklon": 0 }, +{ "label": "37/46", "node": 2893, "naklon": 0 }, +{ "label": "37/47", "node": 2890, "naklon": 0 }, +{ "label": "37/48", "node": 4355, "naklon": 0 }, +{ "label": "37/49", "node": 2885, "naklon": 0 }, +{ "label": "37/50", "node": 2875, "naklon": 0 }, +{ "label": "38/30A", "node": 3486, "naklon": 5 }, +{ "label": "38/30B", "node": 3714, "naklon": 0 }, +{ "label": "38/32A", "node": 3483, "naklon": 5 }, +{ "label": "38/32B", "node": 3496, "naklon": 0 }, +{ "label": "38/35A", "node": 3487, "naklon": 5 }, +{ "label": "38/35B", "node": 3498, "naklon": 5 }, +{ "label": "38/38A", "node": 3578, "naklon": 5 }, +{ "label": "38/38B", "node": 3508, "naklon": 5 }, +{ "label": "38/59A", "node": 3787, "naklon": 5 }, +{ "label": "38/59B", "node": 3491, "naklon": 5 }, +{ "label": "38/1", "node": 3568, "naklon": null }, +{ "label": "38/2", "node": 3502, "naklon": 0 }, +{ "label": "38/3", "node": 3836, "naklon": 0 }, +{ "label": "38/4", "node": 3588, "naklon": 0 }, +{ "label": "38/5", "node": 3493, "naklon": 0 }, +{ "label": "38/6", "node": 3580, "naklon": 0 }, +{ "label": "38/7", "node": 3572, "naklon": 0 }, +{ "label": "38/8", "node": 3506, "naklon": 0 }, +{ "label": "38/9", "node": 3503, "naklon": 0 }, +{ "label": "38/10", "node": 3579, "naklon": 0 }, +{ "label": "38/11", "node": 3586, "naklon": 0 }, +{ "label": "38/12", "node": 3495, "naklon": 5 }, +{ "label": "38/13", "node": 3492, "naklon": 5 }, +{ "label": "38/14", "node": 3532, "naklon": 5 }, +{ "label": "38/15", "node": 3574, "naklon": 5 }, +{ "label": "38/16", "node": 4140, "naklon": 5 }, +{ "label": "38/17", "node": 3795, "naklon": 5 }, +{ "label": "38/18", "node": 3788, "naklon": 5 }, +{ "label": "38/19", "node": 3796, "naklon": 5 }, +{ "label": "38/20", "node": 3797, "naklon": 5 }, +{ "label": "38/21", "node": 3798, "naklon": 5 }, +{ "label": "38/22", "node": 3786, "naklon": 5 }, +{ "label": "38/23", "node": 4067, "naklon": 5 }, +{ "label": "38/24", "node": 3773, "naklon": 5 }, +{ "label": "38/25", "node": 3774, "naklon": 5 }, +{ "label": "38/26", "node": 3789, "naklon": 5 }, +{ "label": "38/27", "node": 3520, "naklon": null }, +{ "label": "38/29", "node": 3577, "naklon": 5 }, +{ "label": "38/31", "node": 3530, "naklon": null }, +{ "label": "38/33", "node": 3488, "naklon": 5 }, +{ "label": "38/34", "node": 3505, "naklon": 5 }, +{ "label": "38/36", "node": 3497, "naklon": 5 }, +{ "label": "38/37", "node": 3490, "naklon": 5 }, +{ "label": "38/39", "node": 3585, "naklon": 5 }, +{ "label": "38/40", "node": 3582, "naklon": 5 }, +{ "label": "38/41", "node": 3507, "naklon": 5 }, +{ "label": "38/42", "node": 3484, "naklon": 5 }, +{ "label": "38/43", "node": 3501, "naklon": 5 }, +{ "label": "38/44", "node": 3581, "naklon": 5 }, +{ "label": "38/45", "node": 4192, "naklon": 5 }, +{ "label": "38/46", "node": 3576, "naklon": 5 }, +{ "label": "38/47", "node": 3489, "naklon": 5 }, +{ "label": "38/48", "node": 3573, "naklon": 5 }, +{ "label": "38/49", "node": 3504, "naklon": 5 }, +{ "label": "38/50", "node": 3794, "naklon": 5 }, +{ "label": "38/51", "node": 3485, "naklon": 5 }, +{ "label": "38/52", "node": 3482, "naklon": 5 }, +{ "label": "38/53", "node": 3575, "naklon": 5 }, +{ "label": "38/54", "node": 3499, "naklon": 5 }, +{ "label": "38/55", "node": 3494, "naklon": 5 }, +{ "label": "38/56", "node": 3583, "naklon": 5 }, +{ "label": "38/57", "node": 3570, "naklon": 5 }, +{ "label": "38/58", "node": 3500, "naklon": 0 }, +{ "label": "38/63", "node": 3510, "naklon": null }, +{ "label": "38/64", "node": 3512, "naklon": null }, +{ "label": "38/67", "node": 3535, "naklon": null }, +{ "label": "38/68", "node": 3531, "naklon": null }, +{ "label": "38/69", "node": 3537, "naklon": null }, +{ "label": "39/1", "node": 3522, "naklon": 10 }, +{ "label": "39/2", "node": 4018, "naklon": 10 }, +{ "label": "39/3", "node": 4019, "naklon": 10 }, +{ "label": "39/4", "node": 4154, "naklon": 5 }, +{ "label": "39/5", "node": 3907, "naklon": 5 }, +{ "label": "39/6", "node": 4148, "naklon": 0 }, +{ "label": "39/7", "node": 4153, "naklon": 0 }, +{ "label": "39/8", "node": 3938, "naklon": 0 }, +{ "label": "39/9", "node": 3802, "naklon": 0 }, +{ "label": "39/10", "node": 4015, "naklon": 0 }, +{ "label": "39/11", "node": 3929, "naklon": 0 }, +{ "label": "39/12", "node": 3946, "naklon": 0 }, +{ "label": "39/13", "node": 4014, "naklon": 0 }, +{ "label": "39/14", "node": 4155, "naklon": 0 }, +{ "label": "39/15", "node": 4149, "naklon": 0 }, +{ "label": "39/16", "node": 3642, "naklon": 0 }, +{ "label": "39/17", "node": 3636, "naklon": 5 }, +{ "label": "39/18", "node": 3991, "naklon": 0 }, +{ "label": "39/19", "node": 3994, "naklon": 0 }, +{ "label": "39/20", "node": 3990, "naklon": 0 }, +{ "label": "39/21", "node": 3967, "naklon": 0 }, +{ "label": "39/22", "node": 3977, "naklon": 0 }, +{ "label": "39/23", "node": 3757, "naklon": 15 }, +{ "label": "39/24", "node": 3633, "naklon": 15 }, +{ "label": "39/25", "node": 3744, "naklon": 15 }, +{ "label": "39/26", "node": 4023, "naklon": 5 }, +{ "label": "39/27", "node": 3720, "naklon": 5 }, +{ "label": "39/28", "node": 3734, "naklon": 5 }, +{ "label": "39/29", "node": 3741, "naklon": 5 }, +{ "label": "39/30", "node": 3721, "naklon": 5 }, +{ "label": "39/31", "node": 3845, "naklon": 0 }, +{ "label": "39/32", "node": 3840, "naklon": 0 }, +{ "label": "39/33", "node": 3837, "naklon": null }, +{ "label": "39/34", "node": 3839, "naklon": 0 }, +{ "label": "41/1", "node": 3542, "naklon": null }, +{ "label": "41/2", "node": 3566, "naklon": null }, +{ "label": "41/3", "node": 3548, "naklon": null }, +{ "label": "41/4", "node": 3515, "naklon": null }, +{ "label": "41/5", "node": 3559, "naklon": null }, +{ "label": "41/6", "node": 3509, "naklon": null }, +{ "label": "41/7", "node": 3524, "naklon": null }, +{ "label": "41/8", "node": 3518, "naklon": null }, +{ "label": "41/9", "node": 3182, "naklon": null }, +{ "label": "41/10", "node": 3187, "naklon": null }, +{ "label": "41/11", "node": 3195, "naklon": 0 }, +{ "label": "41/12", "node": 3857, "naklon": 0 }, +{ "label": "41/13", "node": 3183, "naklon": 0 }, +{ "label": "41/14", "node": 3177, "naklon": 0 }, +{ "label": "41/15", "node": 3189, "naklon": 0 }, +{ "label": "41/16", "node": 3186, "naklon": 0 }, +{ "label": "42/1", "node": 3178, "naklon": 0 }, +{ "label": "42/2", "node": 3219, "naklon": 0 }, +{ "label": "42/3", "node": 3475, "naklon": 0 }, +{ "label": "42/4", "node": 3175, "naklon": 0 }, +{ "label": "42/5", "node": 3222, "naklon": 0 }, +{ "label": "42/6", "node": 3221, "naklon": 0 }, +{ "label": "42/7", "node": 3181, "naklon": 0 }, +{ "label": "42/8", "node": 3180, "naklon": 0 }, +{ "label": "42/9", "node": 3218, "naklon": 0 }, +{ "label": "42/10", "node": 3176, "naklon": 0 }, +{ "label": "42/11", "node": 3174, "naklon": 0 }, +{ "label": "42/12", "node": 3220, "naklon": 0 }, +{ "label": "42/13", "node": 3533, "naklon": null }, +{ "label": "42/14", "node": 3543, "naklon": null }, +{ "label": "42/15", "node": 3554, "naklon": null }, +{ "label": "42/16", "node": 3549, "naklon": null }, +{ "label": "43/1", "node": 2857, "naklon": 5 }, +{ "label": "43/2", "node": 2752, "naklon": 5 }, +{ "label": "43/3", "node": 2753, "naklon": 5 }, +{ "label": "43/4", "node": 3024, "naklon": 5 }, +{ "label": "43/5", "node": 2754, "naklon": 5 }, +{ "label": "43/6", "node": 4423, "naklon": 5 }, +{ "label": "43/7", "node": 4368, "naklon": 5 }, +{ "label": "43/8", "node": 2978, "naklon": 5 }, +{ "label": "43/9", "node": 2868, "naklon": 5 }, +{ "label": "43/10", "node": 4377, "naklon": 5 }, +{ "label": "43/11", "node": 2757, "naklon": 5 }, +{ "label": "43/12", "node": 2970, "naklon": 5 }, +{ "label": "43/13", "node": 2758, "naklon": 5 }, +{ "label": "43/14", "node": 4378, "naklon": 5 }, +{ "label": "43/15", "node": 2759, "naklon": 5 }, +{ "label": "43/16", "node": 4342, "naklon": 5 }, +{ "label": "43/17", "node": 3026, "naklon": null }, +{ "label": "43/18", "node": 2986, "naklon": null }, +{ "label": "43/19", "node": 4343, "naklon": null }, +{ "label": "43/20", "node": 2760, "naklon": null }, +{ "label": "43/21", "node": 4379, "naklon": null }, +{ "label": "43/22", "node": 2971, "naklon": null }, +{ "label": "43/23", "node": 2761, "naklon": null }, +{ "label": "43/24", "node": 2762, "naklon": null }, +{ "label": "43/25", "node": 4339, "naklon": null }, +{ "label": "43/26", "node": 4380, "naklon": null }, +{ "label": "43/27", "node": 2975, "naklon": null }, +{ "label": "43/28", "node": 3003, "naklon": null }, +{ "label": "43/29", "node": 4338, "naklon": null }, +{ "label": "43/30", "node": 3002, "naklon": null }, +{ "label": "43/31", "node": 4345, "naklon": null }, +{ "label": "43/32", "node": 2979, "naklon": null }, +{ "label": "43/33", "node": 2989, "naklon": null }, +{ "label": "43/34", "node": 2996, "naklon": null }, +{ "label": "43/35", "node": 2972, "naklon": null }, +{ "label": "43/36", "node": 2988, "naklon": null }, +{ "label": "43/37", "node": 4344, "naklon": null }, +{ "label": "43/38", "node": 3022, "naklon": null }, +{ "label": "43/39", "node": 4341, "naklon": null }, +{ "label": "43/40", "node": 2983, "naklon": null }, +{ "label": "43/41", "node": 2995, "naklon": null }, +{ "label": "43/42", "node": 2763, "naklon": null }, +{ "label": "43/43", "node": 2764, "naklon": null }, +{ "label": "43/44", "node": 2765, "naklon": null }, +{ "label": "43/45", "node": 2766, "naklon": null }, +{ "label": "43/46", "node": 2767, "naklon": null }, +{ "label": "43/47", "node": 2768, "naklon": null }, +{ "label": "43/48", "node": 3018, "naklon": null }, +{ "label": "43/49", "node": 2982, "naklon": null }, +{ "label": "43/50", "node": 3019, "naklon": 0 }, +{ "label": "43/51", "node": 3013, "naklon": null }, +{ "label": "43/52", "node": 3007, "naklon": null }, +{ "label": "43/53", "node": 2980, "naklon": null }, +{ "label": "43/54", "node": 3011, "naklon": null }, +{ "label": "43/55", "node": 2672, "naklon": null }, +{ "label": "43/56", "node": 2673, "naklon": null }, +{ "label": "43/57", "node": 2674, "naklon": null }, +{ "label": "43/58", "node": 2675, "naklon": null }, +{ "label": "43/59", "node": 2676, "naklon": null }, +{ "label": "43/60", "node": 2677, "naklon": null }, +{ "label": "43/61", "node": 2678, "naklon": null }, +{ "label": "43/62", "node": 2679, "naklon": null }, +{ "label": "43/63", "node": 2680, "naklon": null }, +{ "label": "43/64", "node": 2840, "naklon": null }, +{ "label": "43/65", "node": 2682, "naklon": null }, +{ "label": "43/66", "node": 2683, "naklon": null }, +{ "label": "43/67", "node": 2684, "naklon": 0 }, +{ "label": "43/68", "node": 2685, "naklon": null }, +{ "label": "43/69", "node": 2686, "naklon": null }, +{ "label": "43/70", "node": 2687, "naklon": null }, +{ "label": "43/71", "node": 2688, "naklon": null }, +{ "label": "43/72", "node": 2689, "naklon": null }, +{ "label": "43/73", "node": 2690, "naklon": null }, +{ "label": "43/74", "node": 2691, "naklon": null }, +{ "label": "43/75", "node": 2692, "naklon": null }, +{ "label": "43/76", "node": 2693, "naklon": 0 }, +{ "label": "43/77", "node": 2694, "naklon": null }, +{ "label": "43/78", "node": 2695, "naklon": null }, +{ "label": "43/79", "node": 2696, "naklon": 0 }, +{ "label": "43/80", "node": 2697, "naklon": null }, +{ "label": "43/81", "node": 2698, "naklon": 0 }, +{ "label": "43/82", "node": 2699, "naklon": null }, +{ "label": "43/83", "node": 2700, "naklon": 0 }, +{ "label": "43/84", "node": 2744, "naklon": null }, +{ "label": "43/85", "node": 2745, "naklon": 0 }, +{ "label": "43/86", "node": 2746, "naklon": null }, +{ "label": "43/87", "node": 2747, "naklon": 0 }, +{ "label": "43/88", "node": 2748, "naklon": null }, +{ "label": "43/89", "node": 2749, "naklon": 0 }, +{ "label": "43/90", "node": 2841, "naklon": null }, +{ "label": "45/1", "node": 4237, "naklon": 5 }, +{ "label": "45/2", "node": 4226, "naklon": 5 }, +{ "label": "45/3", "node": 4242, "naklon": 5 }, +{ "label": "45/4", "node": 4179, "naklon": 5 }, +{ "label": "45/5", "node": 4247, "naklon": 5 }, +{ "label": "45/6", "node": 4245, "naklon": 5 }, +{ "label": "45/7", "node": 3872, "naklon": 5 }, +{ "label": "45/8", "node": 4175, "naklon": 5 }, +{ "label": "45/9", "node": 4236, "naklon": 5 }, +{ "label": "45/10", "node": 4170, "naklon": 5 }, +{ "label": "45/11", "node": 4238, "naklon": 5 }, +{ "label": "45/12", "node": 4246, "naklon": 5 }, +{ "label": "45/13", "node": 4166, "naklon": 5 }, +{ "label": "45/14", "node": 4227, "naklon": 5 }, +{ "label": "45/15", "node": 4171, "naklon": 5 }, +{ "label": "45/16", "node": 4180, "naklon": 5 }, +{ "label": "45/17", "node": 4244, "naklon": 5 }, +{ "label": "45/18", "node": 4199, "naklon": 5 }, +{ "label": "45/19", "node": 4239, "naklon": 5 }, +{ "label": "45/20", "node": 4207, "naklon": 5 }, +{ "label": "45/21", "node": 4223, "naklon": 5 }, +{ "label": "45/22", "node": 4230, "naklon": 5 }, +{ "label": "45/23", "node": 4233, "naklon": 5 }, +{ "label": "45/24", "node": 4222, "naklon": 5 }, +{ "label": "45/25", "node": 4217, "naklon": 5 }, +{ "label": "45/26", "node": 4243, "naklon": 5 }, +{ "label": "45/27", "node": 4200, "naklon": 5 }, +{ "label": "45/28", "node": 4228, "naklon": 5 }, +{ "label": "45/29", "node": 4211, "naklon": 5 }, +{ "label": "45/30", "node": 4234, "naklon": 5 }, +{ "label": "45/31", "node": 4235, "naklon": 5 }, +{ "label": "45/32", "node": 4203, "naklon": 5 }, +{ "label": "45/33", "node": 4240, "naklon": 5 }, +{ "label": "45/34", "node": 4224, "naklon": 5 }, +{ "label": "45/35", "node": 4232, "naklon": 5 }, +{ "label": "45/36", "node": 4231, "naklon": 5 }, +{ "label": "45/37", "node": 4161, "naklon": 5 }, +{ "label": "45/38", "node": 4225, "naklon": 5 }, +{ "label": "45/39", "node": 4241, "naklon": 5 }, +{ "label": "45/40", "node": 4229, "naklon": 5 }, +{ "label": "45/41", "node": 4221, "naklon": 5 }, +{ "label": "45/42", "node": 4212, "naklon": 5 }, +{ "label": "45/43", "node": 4216, "naklon": 5 }, +{ "label": "45/44", "node": 3864, "naklon": null }, +{ "label": "46/1", "node": 3806, "naklon": 5 }, +{ "label": "46/2", "node": 3813, "naklon": 5 }, +{ "label": "46/3", "node": 3815, "naklon": 5 }, +{ "label": "46/4", "node": 3807, "naklon": 5 }, +{ "label": "46/5", "node": 3895, "naklon": 5 }, +{ "label": "46/6", "node": 3809, "naklon": 5 }, +{ "label": "46/7", "node": 3820, "naklon": 5 }, +{ "label": "46/8", "node": 3805, "naklon": 5 }, +{ "label": "46/9", "node": 3894, "naklon": 0 }, +{ "label": "46/10", "node": 4055, "naklon": 0 }, +{ "label": "46/11", "node": 3812, "naklon": 5 }, +{ "label": "46/12", "node": 3822, "naklon": 5 }, +{ "label": "46/13", "node": 3821, "naklon": 5 }, +{ "label": "46/14", "node": 3808, "naklon": 5 }, +{ "label": "46/15", "node": 3799, "naklon": 5 }, +{ "label": "46/16", "node": 3816, "naklon": 5 }, +{ "label": "46/17", "node": 3751, "naklon": 5 }, +{ "label": "46/18", "node": 3814, "naklon": 5 }, +{ "label": "46/19", "node": 4044, "naklon": 0 }, +{ "label": "46/20", "node": 3931, "naklon": 0 }, +{ "label": "46/21", "node": 3902, "naklon": 5 }, +{ "label": "46/22", "node": 3916, "naklon": 5 }, +{ "label": "46/23", "node": 3892, "naklon": 5 }, +{ "label": "46/24", "node": 3914, "naklon": 5 }, +{ "label": "46/25", "node": 3898, "naklon": 5 }, +{ "label": "46/26", "node": 3897, "naklon": 5 }, +{ "label": "46/27", "node": 3885, "naklon": 5 }, +{ "label": "46/28", "node": 3906, "naklon": 5 }, +{ "label": "46/29", "node": 3930, "naklon": 0 }, +{ "label": "46/30", "node": 3936, "naklon": 0 }, +{ "label": "46/31", "node": 3860, "naklon": 5 }, +{ "label": "46/32", "node": 3841, "naklon": 5 }, +{ "label": "46/33", "node": 3873, "naklon": 5 }, +{ "label": "46/34", "node": 3854, "naklon": 5 }, +{ "label": "46/35", "node": 3939, "naklon": 5 }, +{ "label": "46/36", "node": 3858, "naklon": 5 }, +{ "label": "46/37", "node": 3940, "naklon": 5 }, +{ "label": "46/38", "node": 4035, "naklon": 5 }, +{ "label": "47/1", "node": 3373, "naklon": 0 }, +{ "label": "47/2", "node": 3374, "naklon": 0 }, +{ "label": "47/3", "node": 3384, "naklon": 0 }, +{ "label": "47/4", "node": 3385, "naklon": 0 }, +{ "label": "48/1", "node": 4051, "naklon": 5 }, +{ "label": "48/2", "node": 4041, "naklon": 5 }, +{ "label": "48/3", "node": 4056, "naklon": 5 }, +{ "label": "48/4", "node": 3875, "naklon": 5 }, +{ "label": "48/5", "node": 4061, "naklon": 5 }, +{ "label": "48/6", "node": 4047, "naklon": 5 }, +{ "label": "48/7", "node": 4060, "naklon": 5 }, +{ "label": "48/8", "node": 4059, "naklon": 5 }, +{ "label": "48/9", "node": 4058, "naklon": 5 }, +{ "label": "48/10", "node": 3635, "naklon": 5 }, +{ "label": "48/11", "node": 3640, "naklon": 5 }, +{ "label": "48/12", "node": 3747, "naklon": 5 }, +{ "label": "48/13", "node": 3629, "naklon": 5 }, +{ "label": "48/14", "node": 4048, "naklon": 5 }, +{ "label": "48/15", "node": 4063, "naklon": 5 }, +{ "label": "48/16", "node": 4062, "naklon": 5 }, +{ "label": "48/17", "node": 4043, "naklon": 5 }, +{ "label": "48/18", "node": 4052, "naklon": 5 }, +{ "label": "48/19", "node": 4042, "naklon": 5 }, +{ "label": "48/20", "node": 4053, "naklon": 5 }, +{ "label": "50/15A", "node": 4167, "naklon": null }, +{ "label": "50/15B", "node": 4159, "naklon": null }, +{ "label": "50/1", "node": 4183, "naklon": 0 }, +{ "label": "50/2", "node": 4157, "naklon": 0 }, +{ "label": "50/3", "node": 4160, "naklon": 0 }, +{ "label": "50/4", "node": 4173, "naklon": 0 }, +{ "label": "50/5", "node": 4177, "naklon": 0 }, +{ "label": "50/6", "node": 4174, "naklon": 0 }, +{ "label": "50/7", "node": 4178, "naklon": 0 }, +{ "label": "50/8", "node": 4195, "naklon": 0 }, +{ "label": "50/9", "node": 4169, "naklon": 0 }, +{ "label": "50/10", "node": 4162, "naklon": 0 }, +{ "label": "50/11", "node": 4158, "naklon": 0 }, +{ "label": "50/12", "node": 4182, "naklon": 0 }, +{ "label": "50/13", "node": 4194, "naklon": 0 }, +{ "label": "50/14", "node": 4184, "naklon": 0 }, +{ "label": "50/16", "node": 4197, "naklon": null }, +{ "label": "50/17", "node": 4164, "naklon": null }, +{ "label": "50/18", "node": 3306, "naklon": null }, +{ "label": "50/19", "node": 4168, "naklon": null }, +{ "label": "50/20", "node": 4193, "naklon": null }, +{ "label": "50/21", "node": 4187, "naklon": null }, +{ "label": "50/22", "node": 4163, "naklon": null }, +{ "label": "50/23", "node": 4165, "naklon": null }, +{ "label": "50/24", "node": 4185, "naklon": null }, +{ "label": "50/25", "node": 3904, "naklon": null }, +{ "label": "53/1", "node": 2619, "naklon": 0 }, +{ "label": "53/2", "node": 2623, "naklon": 0 }, +{ "label": "53/3", "node": 2617, "naklon": 0 }, +{ "label": "53/4", "node": 2622, "naklon": 0 }, +{ "label": "53/5", "node": 2618, "naklon": 0 }, +{ "label": "53/6", "node": 2626, "naklon": 0 }, +{ "label": "53/7", "node": 2869, "naklon": 0 }, +{ "label": "53/8", "node": 2613, "naklon": 0 }, +{ "label": "53/9", "node": 2608, "naklon": 0 }, +{ "label": "53/10", "node": 2611, "naklon": 0 }, +{ "label": "53/11", "node": 2598, "naklon": 0 }, +{ "label": "53/12", "node": 3528, "naklon": 0 }, +{ "label": "53/13", "node": 3545, "naklon": 0 }, +{ "label": "53/14", "node": 2620, "naklon": 0 }, +{ "label": "53/15", "node": 2612, "naklon": 0 }, +{ "label": "53/16", "node": 2615, "naklon": 0 }, +{ "label": "53/17", "node": 3722, "naklon": 0 }, +{ "label": "53/18", "node": 2624, "naklon": 0 }, +{ "label": "53/19", "node": 2609, "naklon": 0 }, +{ "label": "53/20", "node": 2625, "naklon": 0 }, +{ "label": "53/21", "node": 2602, "naklon": 0 }, +{ "label": "53/22", "node": 2610, "naklon": 0 }, +{ "label": "53/23", "node": 2599, "naklon": 0 }, +{ "label": "53/24", "node": 2605, "naklon": 0 }, +{ "label": "53/25", "node": 2593, "naklon": 0 }, +{ "label": "53/26", "node": 3074, "naklon": 0 }, +{ "label": "53/27", "node": 2740, "naklon": 0 }, +{ "label": "53/28", "node": 2614, "naklon": 0 }, +{ "label": "53/29", "node": 2601, "naklon": 0 }, +{ "label": "53/30", "node": 4196, "naklon": 0 }, +{ "label": "53/31", "node": 2607, "naklon": 0 }, +{ "label": "53/32", "node": 2582, "naklon": 0 }, +{ "label": "53/33", "node": 2594, "naklon": 0 }, +{ "label": "53/34", "node": 2589, "naklon": 0 }, +{ "label": "53/35", "node": 2596, "naklon": 0 }, +{ "label": "53/36", "node": 2603, "naklon": 0 }, +{ "label": "53/37", "node": 2597, "naklon": 0 }, +{ "label": "53/38", "node": 2590, "naklon": 0 }, +{ "label": "53/39", "node": 2581, "naklon": 0 }, +{ "label": "53/40", "node": 2583, "naklon": 0 }, +{ "label": "53/41", "node": 2580, "naklon": 0 }, +{ "label": "53/42", "node": 2579, "naklon": 0 }, +{ "label": "53/43", "node": 2797, "naklon": 0 }, +{ "label": "53/44", "node": 2577, "naklon": 0 }, +{ "label": "53/45", "node": 2586, "naklon": 0 }, +{ "label": "53/46", "node": 2588, "naklon": 0 }, +{ "label": "53/47", "node": 2591, "naklon": 0 }, +{ "label": "53/48", "node": 2592, "naklon": 0 }, +{ "label": "53/49", "node": 2573, "naklon": 0 }, +{ "label": "53/50", "node": 2595, "naklon": 0 }, +{ "label": "53/51", "node": 2587, "naklon": 0 }, +{ "label": "53/52", "node": 2578, "naklon": 0 }, +{ "label": "53/53", "node": 2574, "naklon": 0 }, +{ "label": "53/54", "node": 2571, "naklon": 0 }, +{ "label": "53/55", "node": 2570, "naklon": 0 }, +{ "label": "53/56", "node": 2576, "naklon": 0 }, +{ "label": "53/57", "node": 2881, "naklon": 0 }, +{ "label": "53/58", "node": 2575, "naklon": 0 }, +{ "label": "53/59", "node": 2572, "naklon": 0 }, +{ "label": "53/60", "node": 2569, "naklon": 0 }, +{ "label": "55/1", "node": 4324, "naklon": 0 }, +{ "label": "55/2", "node": 4319, "naklon": 0 }, +{ "label": "55/3", "node": 4327, "naklon": 0 }, +{ "label": "55/4", "node": 4333, "naklon": 0 }, +{ "label": "55/5", "node": 4332, "naklon": 0 }, +{ "label": "55/6", "node": 4320, "naklon": 0 }, +{ "label": "55/7", "node": 4317, "naklon": 0 }, +{ "label": "55/8", "node": 4318, "naklon": 0 }, +{ "label": "55/9", "node": 4328, "naklon": 0 }, +{ "label": "55/10", "node": 4323, "naklon": 0 }, +{ "label": "55/11", "node": 4325, "naklon": 0 }, +{ "label": "55/12", "node": 4326, "naklon": 0 }, +{ "label": "55/13", "node": 4316, "naklon": 0 }, +{ "label": "55/14", "node": 4322, "naklon": 0 }, +{ "label": "55/15", "node": 4331, "naklon": 0 }, +{ "label": "55/16", "node": 4321, "naklon": 0 }, +{ "label": "55/17", "node": 4315, "naklon": 0 }, +{ "label": "55/18", "node": 4329, "naklon": 0 }, +{ "label": "55/19", "node": 4334, "naklon": 0 }, +{ "label": "55/20", "node": 4330, "naklon": 0 } +]; + +module.exports = { naklony }; diff --git a/RVO38/databases/modbus_config.js b/RVO38/databases/modbus_config.js new file mode 100755 index 0000000..b73116a --- /dev/null +++ b/RVO38/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/RVO38/databases/nodes.table b/RVO38/databases/nodes.table new file mode 100755 index 0000000..7b27066 --- /dev/null +++ b/RVO38/databases/nodes.table @@ -0,0 +1,67 @@ +node:number|pole_number:string|node_type:string|tbname:string|line:number|profile:string|processed:boolean|status:boolean|time_of_last_communication:number ++|3577|29|NEMA|eod9aRWLVl34Gx1Dn7VNyW72rz6qjgmpEXwQJN5Z|1||1|1|1760574069140|............. ++|4140|16|NEMA|3JjOWdylwgNLzxVab7NaMvkZ2vG64rq8PEB5QmDo|1||1|1|1760574177186|............. ++|4192|45|NEMA|apKVJBwOyrP35m2lv7KYyZ0YXbeWNd64En9GxRqg|1||1|1|1760573988469|............. ++|3507|41|NEMA|5dBNwRp9graYJxZn409NL2klVov1b2QLPDqGm6XK|1||1|1|1760574050437|............. ++|3508|||gYbDLqlyZVoRerQpB72ML9kWJnwM5z24POKa8Exj|1||1|1|1760574094869|............. ++|3512|64|IP65|dz4ojlpP85JMgDLZWkQJ9B7aKYqQexEr62GXRV1y|1||1|1|1760574052769|............. ++|3520|27|IP65|ZmRwd93QL4gaezxEbAx2mRk1prn2XjlPvGyqJ6BO|1||1|1|1760574102232|............. ++|3530|31|IP65|d9x2V5LGYBzXp4mMRAOmYWkPloaqJwnQj6DgrNe3|1||1|1|1760574101593|............. ++|3531|68|IP65|gRoJEyXVx4qD9er287L4r47wBzGldaPjLWQKm3Mv|1||1|1|1760574101737|............. ++|3532|14|IP65|RvmwNz8QPblKp41GD7lKv8kJrLVYoBO92dMegn6W|1||1|1|1760574101897|............. ++|3535|67|IP65|d5xjWYMwEJon6rLlK7yEml7qgV4DaOeNB9ZX3Gzb|1||1|1|1760574102073|............. ++|3537|69|IP65|K94XLav1glVRnyQ6r01P4BAme3YJwBxM5oOzdP2j|1||1|1|1760574102552|............. ++|3568|1|IP65|zrR51V2ajQ9ZLygPKkEMg9kYDq38xOJolENBXGnv|1||1|1|1760574103015|............. ++|3233|57|NEMA|RO8rjaBDy21qPQJzW7omvr0pK3xmNleVZg9Ed4Gw|1||1|1|1760574040839|............. ++|3572|7|NEMA|pE5X8NQPaow6vlOZxk6ayl0q42ezGBMyWgDVjR3L|1||1|1|1760574065450|............. ++|3573|48|NEMA|2O14VBzl8aDmWdNw3A59LEAGyZ5qLJoEMpj6R9ng|1||1|1|1760574068645|............. ++|3574|15|NEMA|RO8rjaBDy21qPQJzW7omdr0pK3xmNleVZg9Ed4Gw|1||1|1|1760574068836|............. ++|3234|46|NEMA|o9vbeQlLMVg8j5dq4keLyQ0NxZpEmnXzwYKO1ar2|1||1|1|1760573952038|............. ++|3578|38A|NEMA|XMBbew5z4ELrZa2mRAd3yY78vPN6gy3DdVYlpKjq|1||1|1|1760574069395|............. ++|4111|6|NEMA|2O14VBzl8aDmWdNw3A59yEAGyZ5qLJoEMpj6R9ng|1||1|1|1760574177042|............. ++|3582|40|NEMA|WlVJBygjDZMeKX3vnAMRym08NqdmG2x1Y69LQ4P5|1||1|1|1760574159857|............. ++|3583|56|NEMA|RvmwNz8QPblKp41GD7lKg8kJrLVYoBO92dMegn6W|1||1|1|1760574070721|............. ++|3585|39|NEMA|zdQO8GwxDqjRgP4137YVydANyKlpem2nL65rvVJY|1||1|1|1760574070913|............. ++|3586|11|NEMA|g9OxBZ5KRwNznlY6pApp22AWXvjdEL4eGQobMDy2|1||1|1|1760574071472|............. ++|4171|30B|NEMA|EjgWGnXaLy9opPOz20n4bZ786BlYM3w1deVQvbKr|1||1|1|1760573988293|............. ++|3773|24|NEMA|d9x2V5LGYBzXp4mMRAOmyWkPloaqJwnQj6DgrNe3|1||1|1|1760574072366|............. ++|3786|22|NEMA|gRoJEyXVx4qD9er287L4y47wBzGldaPjLWQKm3Mv|1||1|1|1760573979174|............. ++|3787|59A|NEMA|Z5KyJe9nEg1QNbWlX0w4EwkoDjBLdqzR83VGv624|1||1|0|1757216680785|............. ++|3788|18|NEMA|1JMYvnx2RzKEo4aWQ7DG3qkL8yZV3m9NBePXbrdj|1||1|1|1760574307975|............. ++|3789|26|NEMA|aw4eELG2DlPMdn1JW0BMLWAqQXOZRN3xB5yp8VKr|1||1|1|1760574124097|............. ++|3794|50|NEMA|6lQGaY9RDywdVzObj0Pay3kPg4NBn3exEK51LWZq|1||1|1|1760574124241|............. ++|3796|19|NEMA|PjLblDgRBO6WQqnxmkJ1y90Jv3ewZN4p5a89yKdY|1||1|1|1760574124608|............. ++|3797|20|NEMA|dz4ojlpP85JMgDLZWkQJGB7aKYqQexEr62GXRV1y|1||1|1|1760574124816|............. ++|3836|3|NEMA|DbQY6zyveZRwK5drV0Z8WQ7joE4XJM83N9xl2nWq|1||1|1|1760574171436|............. ++|4067|23|NEMA|K94XLav1glVRnyQ6r01PLBAme3YJwBxM5oOzdP2j|1||1|1|1760574172793|............. ++|3348|52|NEMA|JzwxZXOvDj1bVrN4nkW5yqA8qdyBl3MRKLpGPgaQ|1||1|1|1760573953811|............. ++|3483|32A|NEMA|wvKJdZML6mXP4DzWBAXxy6AjxNloa5g23Ve9Y1ry|1||1|1|1760573862726|............. ++|3484|42|NEMA|zrR51V2ajQ9ZLygPKkEMy9kYDq38xOJolENBXGnv|1||1|1|1760573862918|............. ++|3720|51|NEMA|m6EYyZoJ4gWexdjVPAR5yK7RDOq9wv2N5XzKGplr|1||1|1|1760574072110|............. ++|3486|30A|NEMA|3a5oqJN1bgnx4Ol9dk89L37ByE6jQ8mKDWMpGrLV|1||1|1|1760573863094|............. ++|3488|33|NEMA|PLBJzmK1r3Gynd6OW0gKV80e5wV4vx9bDEqNgYR8|1||1|1|1760573863413|............. ++|3489|47|NEMA|gP1eOZVj3Q9lv5aDEk45LJ7rdpqW8yLm2BbKzJxM|1||1|1|1760573863780|............. ++|4426|37|NEMA|nJL5lPMwBx23YpqRe0rpdQ7damXvWVbOrD4gNzy8|1||1|1|1760574040631|............. ++|3491|59B|NEMA|1JMYvnx2RzKEo4aWQ7DGyqkL8yZV3m9NBePXbrdj|1||1|1|1760574042883|............. ++|3379|5|NEMA|gP1eOZVj3Q9lv5aDEk45yJ7rdpqW8yLm2BbKzJxM|1||1|1|1760574041893|............. ++|3816|55|NEMA|JX1ObgmqGZ54DMyYL7aDyokEVdve38WKRzwjNrQ9|1||1|1|1760574171260|............. ++|3495|12|NEMA|OzNMgZ9n43qPbjXmy7zw5KA2DKdYvW5e6pxGRrVa|1||1|1|1760574043091|............. ++|3641|32B|NEMA|Nzp2OoJlqn6r1ZgvdA3BLr7abBwP5G4eE3RQmyxD|1||1|1|1760574071951|............. ++|3497|36|NEMA|roKgWqY95V3mXMRzyAjKXP0bLjexpJPvaGDBw826|1||1|1|1760574046317|............. ++|3498|35|NEMA|E6Kg9oDnLWyzPRMva7v59XkJxp4VG58qO2w1lZYe|1||1|1|1760574046493|............. ++|3811|54|NEMA|OzNMgZ9n43qPbjXmy7zwKKA2DKdYvW5e6pxGRrVa|1||1|1|1760574125215|............. ++|3893|58|NEMA|3JjOWdylwgNLzxVab7NayvkZ2vG64rq8PEB5QmDo|1||1|1|1760574171595|............. ++|3501|43|NEMA|BaY3Xpy1EbKGjLq2O7maqN7rx8owgQz9P4dDJRmN|1||1|1|1760574047499|............. ++|3502|2|NEMA|BaY3Xpy1EbKGjLq2O7majN7rx8owgQz9P4dDJRmN|1||1|1|1760574048888|............. ++|3503|9|NEMA|m6EYyZoJ4gWexdjVPAR5ZK7RDOq9wv2N5XzKGplr|1||1|1|1760574049575|............. ++|3504|49|NEMA|pE5X8NQPaow6vlOZxk6aLl0q42ezGBMyWgDVjR3L|1||1|1|1760574049719|............. ++|3506|8|NEMA|6lQGaY9RDywdVzObj0PaE3kPg4NBn3exEK51LWZq|1||1|1|1760574098830|............. ++|3798|21|NEMA|d5xjWYMwEJon6rLlK7yEZl7qgV4DaOeNB9ZX3Gzb|1||1|1|1760574125087|............. ++|3510|63|IP65|PjLblDgRBO6WQqnxmkJ1v90Jv3ewZN4p5a89yKdY|1||1|1|1760574052354|............. ++|3575|53|NEMA|g9OxBZ5KRwNznlY6pAppj2AWXvjdEL4eGQobMDy2|1||1|1|1760574068980|............. ++|3579|10|NEMA|JzwxZXOvDj1bVrN4nkW56qA8qdyBl3MRKLpGPgaQ|1||1|1|1760574069747|............. ++|3581|44|NEMA|DbQY6zyveZRwK5drV0Z8yQ7joE4XJM83N9xl2nWq|1||1|1|1760574202788|............. ++|3774|25|NEMA|B5EoxeMVp4zwr8nqW0GByaARjvD1PNamOGbLg63Z|1||1|1|1760573978966|............. ++|3795|17|NEMA|Z5KyJe9nEg1QNbWlX0w4KwkoDjBLdqzR83VGv624|1||1|1|1760574124416|............. ++|3588|4|NEMA|apKVJBwOyrP35m2lv7KYdZ0YXbeWNd64En9GxRqg|1||1|1|1760574071631|............. ++|3505|34|NEMA|52dD6ZlV1QaOpRBmbAqGBXkKnGzWMLj4eJq38Pgo|1||1|1|1760574139941|............. diff --git a/RVO38/databases/nodes_original/nodes_original.table b/RVO38/databases/nodes_original/nodes_original.table new file mode 100755 index 0000000..59f5d36 --- /dev/null +++ b/RVO38/databases/nodes_original/nodes_original.table @@ -0,0 +1 @@ +[{"3577": "eod9aRWLVl34Gx1Dn7VNyW72rz6qjgmpEXwQJN5Z"}, {"4140": "3JjOWdylwgNLzxVab7NaMvkZ2vG64rq8PEB5QmDo"}, {"4192": "apKVJBwOyrP35m2lv7KYyZ0YXbeWNd64En9GxRqg"}, {"3507": "5dBNwRp9graYJxZn409NL2klVov1b2QLPDqGm6XK"}, {"3508": "gYbDLqlyZVoRerQpB72ML9kWJnwM5z24POKa8Exj"}, {"3512": "dz4ojlpP85JMgDLZWkQJ9B7aKYqQexEr62GXRV1y"}, {"3520": "ZmRwd93QL4gaezxEbAx2mRk1prn2XjlPvGyqJ6BO"}, {"3530": "d9x2V5LGYBzXp4mMRAOmYWkPloaqJwnQj6DgrNe3"}, {"3531": "gRoJEyXVx4qD9er287L4r47wBzGldaPjLWQKm3Mv"}, {"3532": "RvmwNz8QPblKp41GD7lKv8kJrLVYoBO92dMegn6W"}, {"3535": "d5xjWYMwEJon6rLlK7yEml7qgV4DaOeNB9ZX3Gzb"}, {"3537": "K94XLav1glVRnyQ6r01P4BAme3YJwBxM5oOzdP2j"}, {"3568": "zrR51V2ajQ9ZLygPKkEMg9kYDq38xOJolENBXGnv"}, {"3233": "RO8rjaBDy21qPQJzW7omvr0pK3xmNleVZg9Ed4Gw"}, {"3572": "pE5X8NQPaow6vlOZxk6ayl0q42ezGBMyWgDVjR3L"}, {"3573": "2O14VBzl8aDmWdNw3A59LEAGyZ5qLJoEMpj6R9ng"}, {"3574": "RO8rjaBDy21qPQJzW7omdr0pK3xmNleVZg9Ed4Gw"}, {"3234": "o9vbeQlLMVg8j5dq4keLyQ0NxZpEmnXzwYKO1ar2"}, {"3578": "XMBbew5z4ELrZa2mRAd3yY78vPN6gy3DdVYlpKjq"}, {"4111": "2O14VBzl8aDmWdNw3A59yEAGyZ5qLJoEMpj6R9ng"}, {"3582": "WlVJBygjDZMeKX3vnAMRym08NqdmG2x1Y69LQ4P5"}, {"3583": "RvmwNz8QPblKp41GD7lKg8kJrLVYoBO92dMegn6W"}, {"3585": "zdQO8GwxDqjRgP4137YVydANyKlpem2nL65rvVJY"}, {"3586": "g9OxBZ5KRwNznlY6pApp22AWXvjdEL4eGQobMDy2"}, {"4171": "EjgWGnXaLy9opPOz20n4bZ786BlYM3w1deVQvbKr"}, {"3773": "d9x2V5LGYBzXp4mMRAOmyWkPloaqJwnQj6DgrNe3"}, {"3786": "gRoJEyXVx4qD9er287L4y47wBzGldaPjLWQKm3Mv"}, {"3787": "Z5KyJe9nEg1QNbWlX0w4EwkoDjBLdqzR83VGv624"}, {"3788": "1JMYvnx2RzKEo4aWQ7DG3qkL8yZV3m9NBePXbrdj"}, {"3789": "aw4eELG2DlPMdn1JW0BMLWAqQXOZRN3xB5yp8VKr"}, {"3794": "6lQGaY9RDywdVzObj0Pay3kPg4NBn3exEK51LWZq"}, {"3796": "PjLblDgRBO6WQqnxmkJ1y90Jv3ewZN4p5a89yKdY"}, {"3797": "dz4ojlpP85JMgDLZWkQJGB7aKYqQexEr62GXRV1y"}, {"3836": "DbQY6zyveZRwK5drV0Z8WQ7joE4XJM83N9xl2nWq"}, {"4067": "K94XLav1glVRnyQ6r01PLBAme3YJwBxM5oOzdP2j"}, {"3348": "JzwxZXOvDj1bVrN4nkW5yqA8qdyBl3MRKLpGPgaQ"}, {"3483": "wvKJdZML6mXP4DzWBAXxy6AjxNloa5g23Ve9Y1ry"}, {"3484": "zrR51V2ajQ9ZLygPKkEMy9kYDq38xOJolENBXGnv"}, {"3720": "m6EYyZoJ4gWexdjVPAR5yK7RDOq9wv2N5XzKGplr"}, {"3486": "3a5oqJN1bgnx4Ol9dk89L37ByE6jQ8mKDWMpGrLV"}, {"3488": "PLBJzmK1r3Gynd6OW0gKV80e5wV4vx9bDEqNgYR8"}, {"3489": "gP1eOZVj3Q9lv5aDEk45LJ7rdpqW8yLm2BbKzJxM"}, {"4426": "nJL5lPMwBx23YpqRe0rpdQ7damXvWVbOrD4gNzy8"}, {"3491": "1JMYvnx2RzKEo4aWQ7DGyqkL8yZV3m9NBePXbrdj"}, {"3379": "gP1eOZVj3Q9lv5aDEk45yJ7rdpqW8yLm2BbKzJxM"}, {"3816": "JX1ObgmqGZ54DMyYL7aDyokEVdve38WKRzwjNrQ9"}, {"3495": "OzNMgZ9n43qPbjXmy7zw5KA2DKdYvW5e6pxGRrVa"}, {"3641": "Nzp2OoJlqn6r1ZgvdA3BLr7abBwP5G4eE3RQmyxD"}, {"3497": "roKgWqY95V3mXMRzyAjKXP0bLjexpJPvaGDBw826"}, {"3498": "E6Kg9oDnLWyzPRMva7v59XkJxp4VG58qO2w1lZYe"}, {"3811": "OzNMgZ9n43qPbjXmy7zwKKA2DKdYvW5e6pxGRrVa"}, {"3893": "3JjOWdylwgNLzxVab7NayvkZ2vG64rq8PEB5QmDo"}, {"3501": "BaY3Xpy1EbKGjLq2O7maqN7rx8owgQz9P4dDJRmN"}, {"3502": "BaY3Xpy1EbKGjLq2O7majN7rx8owgQz9P4dDJRmN"}, {"3503": "m6EYyZoJ4gWexdjVPAR5ZK7RDOq9wv2N5XzKGplr"}, {"3504": "pE5X8NQPaow6vlOZxk6aLl0q42ezGBMyWgDVjR3L"}, {"3506": "6lQGaY9RDywdVzObj0PaE3kPg4NBn3exEK51LWZq"}, {"3798": "d5xjWYMwEJon6rLlK7yEZl7qgV4DaOeNB9ZX3Gzb"}, {"3510": "PjLblDgRBO6WQqnxmkJ1v90Jv3ewZN4p5a89yKdY"}, {"3575": "g9OxBZ5KRwNznlY6pAppj2AWXvjdEL4eGQobMDy2"}, {"3579": "JzwxZXOvDj1bVrN4nkW56qA8qdyBl3MRKLpGPgaQ"}, {"3581": "DbQY6zyveZRwK5drV0Z8yQ7joE4XJM83N9xl2nWq"}, {"3774": "B5EoxeMVp4zwr8nqW0GByaARjvD1PNamOGbLg63Z"}, {"3795": "Z5KyJe9nEg1QNbWlX0w4KwkoDjBLdqzR83VGv624"}, {"3588": "apKVJBwOyrP35m2lv7KYdZ0YXbeWNd64En9GxRqg"}, {"3505": "52dD6ZlV1QaOpRBmbAqGBXkKnGzWMLj4eJq38Pgo"}] \ No newline at end of file diff --git a/RVO38/databases/notifications.table b/RVO38/databases/notifications.table new file mode 100755 index 0000000..f7c96cb --- /dev/null +++ b/RVO38/databases/notifications.table @@ -0,0 +1,41 @@ +key:string|weight:string|sk:string|en:string ++|switching_profile_point_applied_to_line|INFORMATIONAL|Aplikovaný bod spínacieho profilu na línií č. ${line} : ${value}|Switching profile point applied to line no. ${line} : ${value}|............... ++|dusk_has_occured|INFORMATIONAL|Nastal súmrak: ${value}|Dusk has occured: ${value}|............... ++|dawn_has_occured|INFORMATIONAL|Nastal úsvit: ${value}|Dawn has occured: ${value}|............... ++|dimming_profile_was_successfully_received_by_node|NOTICE|Stmievací profil bol úspešne prijatý nodom č. ${node}|Dimming profile was successfully received by node no. ${node}|............... ++|master_node_is_responding_again|NOTICE|Master node začal znovu odpovedať|Master node is responding again|............... ++|command_was_sent_from_terminal_interface|DEBUG|Z terminálu bol odoslaný príkaz|A command was sent from terminal interface|............... ++|master_node_is_not_responding|ALERT|Master node neodpovedá|Master node is not responding|............... ++|configuration_of_dimming_profile_to_node_failed|ALERT|Konfigurácia stmievacieho profilu pre node č. ${node} zlyhala|Configuration of dimming profile to node no. ${node} has failed|............... ++|circuit_breaker_was_turned_on_line|NOTICE|Zapnutie ističa na línii č. ${line}|Circuit breaker was turned on - line no. ${line}|............... ++|circuit_breaker_was_turned_off_line|ERROR|Vypnutie ističa na línií č. ${line}|Circuit breaker was turned off - line no. ${line}|............... ++|dimming_profile_was_processed_for_node|INFORMATIONAL|Stmievací profil bol spracovaný pre node č. ${node}|Dimming profile was processed for node no. ${node}|............... ++|switching_profile_was_processed_for_line|INFORMATIONAL|Spínací profil bol spracovaný pre líniu č. ${line}|Switching profile was processed for line no. ${line}|............... ++|thermometer_is_not_responding|WARNING|Teplomer neodpovedá|Thermometer is not responding|............... ++|thermometer_is_responding_again|NOTICE|Teplomer znovu odpovedá|Thermometer is responding again|............... ++|thermometer_sends_invalid_data|WARNING|Teplomer posiela neplatné hodnoty|Thermometer sends invalid data|............... ++|main_switch_has_been_turned_off|CRITICAL|Hlavný vypínač bol vypnutý|Main switch has been turned off|............... ++|main_switch_has_been_turned_on|NOTICE|Hlavný vypínač bol zapnutý|Main switch has been turned on|............... ++|power_supply_has_disconnected_input|ALERT|Napájací zdroj nemá napätie na vstupe|Power supply has disconnected input|............... ++|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_main_open|NOTICE|Hlavné dvere boli otvorené|Main door has been opened|............... ++|door_em_open|NOTICE|Dvere silovej časti boli otvorené|Power door has been opened|............... ++|door_main_open_without_permission|WARNING|Hlavné dvere boli otvorené bez povolenia - zapnutá siréna|Main door has been opened without permission - alarm is on|............... ++|door_em_open_without_permission|WARNING|Dvere silovej časti boli otvorené bez povolenia|Power door has been opened without permission|............... ++|door_main_close|NOTICE|Hlavné dvere boli zatvorené|Main door has been closed|............... ++|door_em_close|NOTICE|Dvere silovej časti boli zatvorené|Power door has been closed|............... ++|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|............... ++|electrometer_ok|NOTICE|Elektromer znovu odpovedá|Electrometer is responding again|............... ++|no_voltage_on_phase|CRITICAL|Na fáze č. ${phase} nie je napätie|No voltage detected on phase no. ${phase}|............... ++|voltage_on_phase_restored|NOTICE|Napätie na fáze č. ${phase} bolo obnovené|Voltage on phase no. ${phase} has been restored|............... ++|flow_start|NOTICE|FLOW bol spustený|FLOW has been started |............... ++|twilight_sensor_nok|ERROR|Sensor súmraku neodpovedá|Twilight sensor is not responding|............... ++|twilight_sensor_ok|NOTICE|Sensor súmraku znovu odpovedá|Twilight sensor is responding again|............... ++|lamps_have_turned_on|NOTICE|Lampy sa zapli|Lamps have turned on|............... ++|lamps_have_turned_off|NOTICE|Lampy sa vypli|Lamps have turned off|............... ++|flow_restart|NOTICE|FLOW bol reštartovaný|FLOW has been restarted|............... ++|nodes_db_changed|NOTICE|Zmena v node databáze|Node db has changed|............... diff --git a/RVO38/databases/pins.table b/RVO38/databases/pins.table new file mode 100755 index 0000000..6417b40 --- /dev/null +++ b/RVO38/databases/pins.table @@ -0,0 +1,15 @@ +pin:string|type:string|line:number +*|input1_01|door_condition|0|........... +*|input1_02|rotary_switch_state|0|........... +*|input1_03|rotary_switch_state|0|........... +*|input1_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|........... +*|relay1_05|state_of_contactor|4|........... +*|28F46E9D0E00008B|temperature|0|........... +*|twilight_sensor|twilight_sensor|0|........... diff --git a/RVO38/databases/relays.table b/RVO38/databases/relays.table new file mode 100755 index 0000000..8d71f3b --- /dev/null +++ b/RVO38/databases/relays.table @@ -0,0 +1,6 @@ +line:number|tbname:string|contactor:number|profile:string ++|0|pE5X8NQPaow6vlOZxk6ajg0q42ezGBMyWgDVjR3L|1||........... ++|1|eod9aRWLVl34Gx1Dn7VNgE72rz6qjgmpEXwQJN5Z|9|{"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":11,"dusk_lux_sensor_value":11,"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|3a5oqJN1bgnx4Ol9dk89r27ByE6jQ8mKDWMpGrLV|9|{"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":11,"dusk_lux_sensor_value":11,"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|EjgWGnXaLy9opPOz20n4a3786BlYM3w1deVQvbKr|9|{"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":11,"dusk_lux_sensor_value":11,"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}|................ ++|4|wvKJdZML6mXP4DzWBAXxP9AjxNloa5g23Ve9Y1ry|9|{"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":11,"dusk_lux_sensor_value":11,"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/RVO38/databases/settings.table b/RVO38/databases/settings.table new file mode 100755 index 0000000..48b7d91 --- /dev/null +++ b/RVO38/databases/settings.table @@ -0,0 +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|project_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|cloud_topic:string|has_main_switch:boolean|daily_report:boolean|send_changed_node_numbers:boolean ++|rvo_senica_38_ip122|en|28.2C469D0E0000|48.70826502|17.28455203|192.168.252.1|rvo_senica_38_ip122|iDSe648ORviiliuUA6lu|1883|0|57|unipi|ttyUSB0|1|20|5|6|3|u122|0|1|1|................................................... diff --git a/RVO38/databases/tbdata.nosql b/RVO38/databases/tbdata.nosql new file mode 100755 index 0000000..5201c20 --- /dev/null +++ b/RVO38/databases/tbdata.nosql @@ -0,0 +1,4 @@ +-"pE5X8NQPaow6vlOZxk6ajg0q42ezGBMyWgDVjR3L":[{"ts":1760531454778,"values":{"_event":{"type":"notice","status":"new","source":{"func":"modbus_reader","component":"1699965957410","component_name":"Modbus reader","edge":"pE5X8NQPaow6vlOZxk6ajg0q42ezGBMyWgDVjR3L"},"message":{"sk":"rvo_senica_38_ip122: FLOW bol reštartovaný","en":"rvo_senica_38_ip122: FLOW has been restarted"},"message_data":""}}}],"id":"3000331001xb71b"} +-"pE5X8NQPaow6vlOZxk6ajg0q42ezGBMyWgDVjR3L":[{"ts":1760531454877,"values":{"edge_fw_version":"2025-10-08","maintenance_mode":false}}],"id":"3000331002xb70b"} +-"pE5X8NQPaow6vlOZxk6ajg0q42ezGBMyWgDVjR3L":[{"ts":1760531454890,"values":{"statecode":2,"power_mode":"Automatic"}}],"id":"3000331004xb70b"} +-"pE5X8NQPaow6vlOZxk6ajg0q42ezGBMyWgDVjR3L":[{"ts":1760531454945,"values":{"_event":{"type":"notice","status":"new","source":{"func":"rsPort.open()","component":"1699963668903","component_name":"DIDO_Controller","edge":"pE5X8NQPaow6vlOZxk6ajg0q42ezGBMyWgDVjR3L"},"message":{"sk":"rvo_senica_38_ip122: FLOW bol spustený","en":"rvo_senica_38_ip122: FLOW has been started "},"message_data":""}}}],"id":"3000331006xb70b"} diff --git a/RVO38/databases/tbdatacloud.nosql b/RVO38/databases/tbdatacloud.nosql new file mode 100755 index 0000000..863baa8 --- /dev/null +++ b/RVO38/databases/tbdatacloud.nosql @@ -0,0 +1,3 @@ +-"pE5X8NQPaow6vlOZxk6ajg0q42ezGBMyWgDVjR3L":[{"ts":1760531454877,"values":{"edge_fw_version":"2025-10-08","maintenance_mode":false}}],"id":"3000331003xb71b"} +-"pE5X8NQPaow6vlOZxk6ajg0q42ezGBMyWgDVjR3L":[{"ts":1760531454890,"values":{"statecode":2,"power_mode":"Automatic"}}],"id":"3000331005xb71b"} +-"pE5X8NQPaow6vlOZxk6ajg0q42ezGBMyWgDVjR3L":[{"ts":1760531454945,"values":{"_event":{"type":"notice","status":"new","source":{"func":"rsPort.open()","component":"1699963668903","component_name":"DIDO_Controller","edge":"pE5X8NQPaow6vlOZxk6ajg0q42ezGBMyWgDVjR3L"},"message":{"sk":"rvo_senica_38_ip122: FLOW bol spustený","en":"rvo_senica_38_ip122: FLOW has been started "},"message_data":""}}}],"id":"3000331007xb71b"} diff --git a/RVO38/databases/total_energy.js b/RVO38/databases/total_energy.js new file mode 100755 index 0000000..dde340e --- /dev/null +++ b/RVO38/databases/total_energy.js @@ -0,0 +1,38 @@ +//key is rvo_number, value is max energy when lamps are on +const total_energy = { + 1: 580, + 2: 1100, + 3: 3700, + 4: 4100, + 7: 360, + 12: 1700, + 13: 5400, + 14: 440, + 15: 6100, + 16: 4800, + 20: 1600, + 21: 1000, + 22: 2600, + 23: 1000, + 25: 2600, + 33: 240, + 34: 4000, + 35: 2700, + 36: 820, + 37: 1400, + 35: 3500, + 39: 1170, + 41: 740, + 42: 660, + 43: 4900, + 45: 930, + 46: 700, + 47: 1100, + 48: 1500, + 50: 3200, + 53: 1250, + 55: 1000, + 56: 5500 +} + +module.exports = total_energy; diff --git a/RVO38/debug.js b/RVO38/debug.js new file mode 100755 index 0000000..9818194 --- /dev/null +++ b/RVO38/debug.js @@ -0,0 +1,16 @@ +// =================================================== +// FOR DEVELOPMENT +// Total.js - framework for Node.js platform +// https://www.totaljs.com +// =================================================== + +const options = {}; + +// options.ip = '127.0.0.1'; +// options.port = parseInt(process.argv[2]); +// options.config = { name: 'Total.js' }; +// options.sleep = 3000; +// options.inspector = 9229; +// options.watch = ['private']; + +require('total.js/debug')(options); \ No newline at end of file diff --git a/RVO38/err.txt b/RVO38/err.txt new file mode 100755 index 0000000..8ee2b22 --- /dev/null +++ b/RVO38/err.txt @@ -0,0 +1,66 @@ +[2024-10-26T08:27:08.596] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T09:27:20.756] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T10:27:32.858] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T11:27:44.976] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T12:27:57.097] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T13:28:09.201] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T14:28:21.314] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T15:28:33.403] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T16:28:45.517] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T17:28:57.621] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T18:29:09.771] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T19:29:21.929] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T20:29:34.161] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T21:29:46.404] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T22:29:58.646] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T23:30:10.894] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T00:30:23.089] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T01:30:35.281] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T02:30:47.453] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T02:30:59.585] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T03:31:12.835] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T04:31:24.968] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T05:31:37.134] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T06:31:49.250] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T07:32:01.384] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T08:32:13.562] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T09:32:25.672] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T10:32:37.797] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T11:32:49.929] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T12:33:02.033] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T13:33:14.129] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T14:33:26.206] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T15:33:38.367] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2025-09-23T14:03:32.877] [ERROR] errLogs - uncaughtException: Cannot read property 'getHours' of undefined +[2025-09-23T14:03:32.878] [ERROR] errLogs - TypeError: Cannot read property 'getHours' of undefined + at Timeout.emptyReportToSend [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:03:32.879] [ERROR] errLogs - uncaughtException: Cannot read property 'getHours' of undefined +[2025-09-23T14:03:32.880] [ERROR] errLogs - TypeError: Cannot read property 'getHours' of undefined + at Timeout.emptyReportToSend [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:03:32.889] [ERROR] errLogs - uncaughtException: Cannot read property 'getHours' of undefined +[2025-09-23T14:03:32.889] [ERROR] errLogs - TypeError: Cannot read property 'getHours' of undefined + at Timeout.emptyReportToSend [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:03:38.977] [ERROR] errLogs - uncaughtException: date.getHours is not a function +[2025-09-23T14:03:38.978] [ERROR] errLogs - TypeError: date.getHours is not a function + at emptyReportToSend (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at Timeout.dailyReportCheck [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1351:5) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:03:38.978] [ERROR] errLogs - uncaughtException: date.getHours is not a function +[2025-09-23T14:03:38.979] [ERROR] errLogs - TypeError: date.getHours is not a function + at emptyReportToSend (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at Timeout.dailyReportCheck [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1351:5) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:03:38.984] [ERROR] errLogs - uncaughtException: date.getHours is not a function +[2025-09-23T14:03:38.985] [ERROR] errLogs - TypeError: date.getHours is not a function + at emptyReportToSend (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at Timeout.dailyReportCheck [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1351:5) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) diff --git a/RVO38/flow/cloudmqttconnect.js b/RVO38/flow/cloudmqttconnect.js new file mode 100755 index 0000000..b03491f --- /dev/null +++ b/RVO38/flow/cloudmqttconnect.js @@ -0,0 +1,357 @@ +exports.id = 'cloudmqttconnect'; +exports.title = 'Cloud connect mqtt'; +exports.group = 'MQTT'; +exports.color = '#888600'; +exports.version = '1.0.2'; +exports.icon = 'sign-out'; +exports.input = 2; +exports.output = 2; +exports.options = { host: 'tb-stage.worksys.io', port: 1883, clientid: "", username: "" }; + +exports.html = `
+
+
+
Hostname or IP address (if not empty - setting will override db setting)
+
+
+
Port
+
+
+
+
+
@(Client id)
+
+
+
topic
+
+
+
`; + + + +const { promisifyBuilder } = require('./helper/db_helper'); +const fs = require('fs'); +const mqtt = require('mqtt'); +const nosql = NOSQL('tbdatacloud'); + +const SEND_TO = { + debug: 0, + rpcCall: 1, +} + +//CONFIG +let saveTelemetryOnError = true;//backup_on_failure overrides this value +//------------------------ + +const noSqlFileSizeLimit = 4194304;//use 5MB - 4194304 +let insertNoSqlCounter = 0; +let insertBackupNoSqlCounter = 0; +let processingData = false; + +let backup_on_failure = true;//== saveTelemetryOnError - create backup client send failure +let restore_from_backup = 50; //how many rows process at once? +let restore_backup_wait = 3;//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; + + +exports.install = function(instance) { + + var client; + var opts; + var clientReady = false; + + let o = {}; //options + + function main() { + loadSettings(); + } + + //set opts according to db settings + function loadSettings() { + + o = instance.options; + if (!o.topic) o.topic = FLOW.GLOBALS.settings.cloud_topic; + + opts = { + host: o.host, + port: o.port, + clientId: o.clientid, + username: o.username, + rejectUnauthorized: false, + resubscribe: false + }; + + console.log("wsmqttpublich -> loadSettings from instance.options", o); + + if (!o.topic) { + instance.status("Not configured", "white"); + console.log("Cloud mqtt connect: no topic selected"); + return; + } + + connectToTbServer(); + } + + function connectToTbServer() { + var url = "mqtt://" + opts.host + ":" + opts.port; + console.log("MQTT URL: ", url); + + client = mqtt.connect(url, opts); + + client.on('connect', function() { + client.subscribe(`${o.topic}_backward`, (err) => { + if (!err) { + console.log("MQTT subscribed"); + } + }); + instance.status("Connected", "green"); + clientReady = true; + sendClientError = true; + }); + + client.on('reconnect', function() { + instance.status("Reconnecting", "yellow"); + clientReady = false; + }); + + client.on('message', function(topic, message) { + // message is type of buffer + message = message.toString(); + if (message[0] === '{') { + TRY(function() { + + message = JSON.parse(message); + if (message.hasOwnProperty("device") && message.hasOwnProperty("data") && message.data.hasOwnProperty("id")) { + client.publish(`${o.topic}_forward`, `{"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 } }); + } + + }, () => instance.debug('MQTT: Error parsing data', message)); + } + + instance.send(SEND_TO.rpcCall, { "topic": o.topic, "content": message }); + }); + + client.on('close', function() { + clientReady = false; + + instance.status("Disconnected", "red"); + instance.send(SEND_TO.debug, { "message": "Client CLOSE signal received !" }); + }); + + client.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) { + console.log('MQTT client error', err); + sendClientError = false; + } + clientReady = false; + }); + + } + + + instance.on('0', function(data) { + + if (clientReady) { + //do we have some data in backup file? if any, process data from database + if (saveTelemetryOnError) { + //read telemetry data and send back to server + if (!processingData) processDataFromDatabase(); + } + + let stringifiedJson = JSON.stringify(data.data) + client.publish(`${o.topic}_forward`, stringifiedJson, { qos: 1 }); + } + 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 (saveTelemetryOnError && o.topic) { + //create new file from tbdata.nosql, if file size exceeds given limit, and clear tbdata.nosql + makeBackupFromDbFile(); + + //write to tb + data.data.id = UID(); + nosql.insert(data.data); + } + } + }); + + instance.on("1", _ => { + main(); + }) + + instance.close = function(done) { + if (clientReady) { + client.end(); + } + }; + + + function getDbBackupFileCounter(type) { + var files = fs.readdirSync(__dirname + "/../databases"); + + let counter = 0; + for (var i = 0; i < files.length; i++) { + + if (files[i] == "tbdatacloud.nosql") continue; + + if (files[i].endsWith(".nosql")) { + + let pos = files[i].indexOf("."); + if (pos > -1) { + + let fileCounter = counter; + let firstDigit = files[i].slice(0, pos); + + fileCounter = parseInt(firstDigit); + if (isNaN(fileCounter)) fileCounter = 0; + //console.log("getDbBackupFileCounter digit:", files[i], firstDigit, fileCounter, isNaN(fileCounter), type); + + if (type == "max") { + if (fileCounter > counter) { + counter = fileCounter; + } + } + else if (type == "min") { + if (counter == 0) counter = fileCounter; + + if (fileCounter < counter) { + counter = fileCounter; + } + } + } + } + + } + + if (type == "max") counter++; + + return counter; + } + + const makeBackupFromDbFile = async () => { + + if (!saveTelemetryOnError) return; + + //to avoid large file: tbdata.nosql + + //init value is 0! + if (insertNoSqlCounter > 0) { + --insertNoSqlCounter; + return; + } + + insertNoSqlCounter = 100; + + let source = __dirname + "/../databases/tbdatacloud.nosql"; + + var stats = fs.statSync(source); + var fileSizeInBytes = stats.size; + + if (fileSizeInBytes > noSqlFileSizeLimit) { + + let counter = 1; + counter = getDbBackupFileCounter("max"); + + let destination = __dirname + "/../databases/" + counter + "." + "tbdatacloud.nosql"; + + //make backup file + fs.copyFileSync(source, destination); + //fs.renameSync(p, p + "." + counter); + + //clear tbdata.nosql + fs.writeFileSync(source, ""); + fs.truncateSync(source, 0); + + } + } + + const processDataFromDatabase = async () => { + + if (restore_from_backup <= 0) return; + + //calculate diff + const now = new Date(); + let currentTime = now.getTime(); + let diff = currentTime - lastRestoreTime; + + if ((diff / 1000) < restore_backup_wait) { + //console.log("*********restore_backup_wait", diff, restore_backup_wait); + return; + } + + processingData = true; + + //get filename to process + let counter = getDbBackupFileCounter("min"); + + //we have some backup files + let dataBase = 'tbdata'; + + var nosql; + if (counter == 0) dataBase = 'tbdatacloud'; + else dataBase = counter + "." + 'tbdatacloud'; + + nosql = NOSQL(dataBase); + + //select all data - use limit restore_from_backup + let records = await promisifyBuilder(nosql.find().take(restore_from_backup)); + + for (let i = 0; i < records.length; i++) { + if (clientReady) { + + let item = records[i]; + let id = item.id; + + if (id !== undefined) { + //console.log("------------processDataFromDatabase - remove", id, dataBase, i); + + try { + + let message = JSON.parse(JSON.stringify(item)); + delete message.id; + client.publish(`${o.topic}_forward`, JSON.stringify(message), { qos: 1 }); + + //remove from database + await promisifyBuilder(nosql.remove().where("id", id)); + + } catch (error) { + //process error + console.log("processDataFromDatabase", error); + } + + } + + } + else { + processingData = false; + return; + } + } + + if (records.length > 0) { + //clean backup file + if (counter > 0) nosql.clean(); + } + + //no data in db, remove + if (records.length == 0) { + if (counter > 0) nosql.drop(); + } + + const d = new Date(); + lastRestoreTime = d.getTime(); + + processingData = false; + + } + + instance.on('options', main); + +}; diff --git a/RVO38/flow/cmd_manager.js b/RVO38/flow/cmd_manager.js new file mode 100755 index 0000000..25912df --- /dev/null +++ b/RVO38/flow/cmd_manager.js @@ -0,0 +1,3071 @@ +exports.id = 'cmd_manager'; +exports.title = 'CMD Manager'; +exports.group = 'Worksys'; +exports.color = '#5D9CEC'; +exports.version = '0.0.3'; +exports.output = ['red', 'blue', 'yellow', 'blue', 'white', 'green']; +exports.input = 3; +exports.icon = 'cloud-upload'; + +exports.html = ` +
+
+
+
RPC - run RPC calls

+
+
+
@(User)
+
+
+
@(Password)
+
+
+
@(My edge)
+
+
+
+`; +exports.readme = `Manager for CMD calls`; + + +exports.install = function(instance) { + + 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, isEmptyObject, emptyJsObject, writeToFile, addToArrayIfUnique } = require('./helper/utils'); + const bitwise = require('bitwise'); + + var SunCalc = require('./helper/suncalc'); + const DataToTbHandler = require('./helper/DataToTbHandler'); + const errorHandler = require('./helper/ErrorToServiceHandler'); + const { sendNotification } = require('./helper/notification_reporter'); + const process = require('process'); + const { errLogger, logger, monitor } = require('./helper/logger'); + + //for accelerometer purposes + const { naklony } = require("../databases/accelerometer_db"); + + const dbNodes = TABLE("nodes"); + const dbRelays = TABLE("relays"); + + let GLOBALS; + let SETTINGS; + let rsPort; + let tbHandler; + + // runTasks intervals + const SHORT_INTERVAL = 30; + const LONG_INTERVAL = 300; + + //send data to following instances: + const SEND_TO = { + debug: 0, + tb: 1, + http_response: 2, + dido_controller: 3, + infoSender: 4, + dailyReport: 5 + } + + 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 + } + + 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 sendNodeReadout = null; // interval for sending agregate data from node + + 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["1"] = minutes; // dimming + priorities["76"] = minutes; // power + + minutes = 5; + priorities["75"] = minutes; // current + priorities["79"] = minutes; // energy + priorities["87"] = minutes; // aktualny cas + //priorities["84"] = minutes; //accelerometer + + minutes = 10; + priorities["74"] = minutes; // voltage + priorities["77"] = minutes; // power factor + priorities["78"] = minutes; // frequency + + minutes = 60; + priorities["0"] = minutes; // statecode + priorities["6"] = minutes; // dusk + priorities["7"] = minutes; // dawn + priorities["8"] = minutes; // profile + + minutes = 60 * 24; + priorities["89"] = minutes; // verzia fw + priorities["80"] = minutes; // lifetime + + //prikazy kt sa budu spustat na dany node - see config.js in terminal-oms.app. (1 - dimming) + let listOfCommands = [0, 1, 6, 7, 8, 74, 75, 76, 77, 78, 79, 80, 87, 89]; + + 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; + + // holds dusk, dawn (and more) values + let sunCalcResult; + + //helper container for counting resolved group of commands (commands related to set profile) + let cmdCounter = {};//key is node, value is counter + + //TODO: is this set working?? According to previous checks, sets do not work + //if sending of profile to node fails, we send notification and push node into set, so we do not send notification twice + const nodeProfileSendFail = new Set(); + + //we expect to get current temperature in Senica from senica-prod01 + let temperatureInSenica = null; + let accelerometerInterval = null; + + //NOTE: daily reports senica: + //rvo_is_on status, we monitor all nodes - if true, power and dimming should be not 0, if false, 24/7 nodes should be 0, other rvo should not respond + let rvo_is_on; + let previous_rvo_is_on_value; + let handleDailyReport; //setInterval for dailyReportHandler function + let dailyReport = {}; //data needed for daily report + let reportToSend = {}; //final report which we send to cloud + let breakerCounter = null; // status of breakers after flow starts is not in report + let rvoPeriod; // interval of checking dusk dawn and if rvo_is_on + let initialReportStatus = false; + + const DAILY_REPORT_HANDLER_TIME = 3_600_000; + const SET_SUNCALC_RESULT_TIME = 3_600_000; + const SET_RVO_PERIOD_TIME = 300_000; + const ADD_NODE_TO_REPORT_TIME = 3_600_000; + + //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); + + let now = new Date(); + console.log("Cmd-mngr installed", now.toLocaleString("sk-SK")); + + sunCalcResult = calculateDuskDawn(); + + handleRsPort(); + + customTasksInterval = setInterval(reportEdgeDateTimeAndNumberOfLuminaires, 120_000); + setTimeout(reportEdgeDateTimeAndNumberOfLuminaires, 4000); + + //dailyReport related + emptyReportToSend(); + breakerCounter = Object.keys(relaysData).length - 1; // we get number of lines (breakers) except of line 0 + rvoPeriod = setInterval(setRvoPeriod, SET_RVO_PERIOD_TIME); + setTimeout(setRvoPeriod, 3000); + setInterval(setSunCalcResult, SET_SUNCALC_RESULT_TIME); + handleDailyReport = setInterval(dailyReportHandler, DAILY_REPORT_HANDLER_TIME); + + + setCorrectTime = setInterval(setCorrectPlcTimeOnceADay, 60000 * 60); // 1 hour + setCorrectPlcTimeOnceADay(); + + sendNodeReadout = setInterval(sendNodesData, 150_000); + accelerometerInterval = setInterval(accelerometerData, 60000 * 30); //30 min + } + + + 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" + //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 + // if node regular readout does not respond, we repeat request + params.repeatCounter = 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-mngr: 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.byte4 = 96; + params.recipient = 1; + params.register = 8; + params.rw = 1;//write + params.timestamp = timestamp; + 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.byte4 = 96; + params.recipient = 1; + params.register = 8; + params.rw = 1;//write + params.timestamp = timestamp; + 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). + */ + + 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.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.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 + { + + logger.debug("processNodeProfile: Threshold lux level for DUSK/DAWN", node); + + let params = getParams(); + params.type = "set_node_profile"; + params.address = node; + params.register = 96; + params.recipient = 1; + params.rw = 1;//write + params.timestamp = timestamp; + 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(); + params.type = "set_node_profile"; + params.address = node; + params.register = 97; + params.recipient = 1; + params.rw = 1;//write + params.timestamp = timestamp; + 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.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); + + 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); + + console.log("proces profile finished *********************") + } + + + 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; + }); + } + + + 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) { + for (let k in nodesData) { + 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`); + } + } + } + + + function loadRelaysData(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 (value.contactor == 1) processAllNodeProfilesOnLine(value.line); + } + } + + + function reportOnlineNodeStatus(line) { + //Po zapnutí línie broadcastovo aktualizovať predtým čas a o 3 sek neskor - status, brightness + + logger.debug("Cmd-mngr: ----->reportOnlineNodeStatus for line", line); + + const d = new Date(); + + // broadcast actual time + let params = getParams(); + params.address = 0xffffffff;//Broadcast + params.byte1 = d.getHours(); + params.byte2 = d.getMinutes(); + params.recipient = 2;//2 broadcast, address = 0 + params.register = 87;//Actual time + params.rw = 1;//write + params.type = "node-onetime-write"; + params.timestamp = d.getTime() + 30000; + params.info = "run broadcast: Actual time"; + //params.debug = true; + + tasks.push(params); + + let sec = 3; + setTimeout(function() { + //Po zapnutí línie - spraviť hromadný refresh stavu práve zapnutých svietidiel + + let time = Date.now(); + + for (let k in nodesData) { + + //potrebujem nody k danej linii + 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].node_status_before_offline === true || nodesData[k].status === true) { + status = "OK"; + nodesData[k].time_of_last_communication = time; + } + + nodesData[k].readout.status = status; + + updateNodeStatus(k, status === "OK" ? true : false); + if (nodesData[k].hasOwnProperty("node_status_before_offline")) delete nodesData[k].node_status_before_offline; + sendTelemetry({ status: status }, tbname, time); + + //vyreportovanie dimming, current, input power pre liniu pre vsetky nody + //Prud + { + let params = getParams(); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 75;//prud + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = time + 4000; + params.info = 'read current'; + //params.debug = true; + tasks.push(params); + } + + //vykon + { + let params = getParams(); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 76;//výkon + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = time + 4100; + params.info = 'read power'; + //params.debug = true; + + tasks.push(params); + } + //dimming + { + let params = getParams(); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 1;//dimming + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = time + 4200; + params.info = 'read dimming'; + //params.debug = true; + + tasks.push(params); + } + + } + } + + }, sec * 1000); + } + + + function reportOfflineNodeStatus(line) { + + logger.info("Cmd-mngr: ------>reportOffLineNodeStatus for line ", line); + + values = {}; + values["dimming"] = 0;//brightness + values["power"] = 0;//výkon + values["current"] = 0;//prúd + values["status"] = "OFFLINE"; + + const date = Date.now(); + + Object.keys(nodesData).forEach(node => { + + //potrebujem nody k danej linii + if (line == nodesData[node].line || line == undefined) { + + let tbname = nodesData[node].tbname; + let nodeStatus = nodesData[node].status; + + //in case we have reported offline node status, we return (continue with next node) + if (nodeStatus === "OFFLINE") return; + + nodesData[node].node_status_before_offline = nodeStatus; + nodesData[node].status = "OFFLINE"; + nodesData[node].readout = {}; + + sendTelemetry({ ...values }, tbname, date); + } + }); + + } + + + function turnLine(onOrOff, line, info) { + let obj = { + line: line, + command: onOrOff, + info: info + }; + + //to assure, handleDailyReportFunction do not run before rvo_is_on variable changes. So after every line switch we reset the timer + clearInterval(handleDailyReport); + handleDailyReport = setInterval(dailyReportHandler, DAILY_REPORT_HANDLER_TIME); + + //logger.debug("linia", line, obj); + instance.send(SEND_TO.dido_controller, obj); + } + + + 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"; + 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]) { + //CRC_ERROR + message = "NOK"; + error = "CRC_ERROR c1"; + instance.send(SEND_TO.debug, "CRC_ERROR c1"); + } + + 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") { + instance.send(SEND_TO.debug, bytes); + instance.send(SEND_TO.debug, "RESPONSE " + type + " - " + bytes[4]); + + //logger.debug(SEND_TO.debug, "RESPONSE " + type + " - " + bytes[4], bytes); + + error = "type is: " + type; + + message = "NOK"; + } + + return { message, type, error }; + } + + + //BUILD TASKS// + function buildTasks(params) { + + //return; + console.log("buidTAaasks start ****************", params); + monitor.info("buildTasks - params", params); + + let processLine; //defined line + let init = false; + let processLineProfiles = true; + let processBroadcast = true; + let processNodes = true; + + if (params == undefined) { + init = true; + tasks = []; + logger.debug("-->buildTasks clear tasks"); + } + else { + processLineProfiles = params.processLineProfiles; + processBroadcast = false; + processNodes = false; + + processLine = params.line; + } + + let now = new Date(); + + //process line profiles + if (processLineProfiles) { + + let keys = Object.keys(relaysData); + + for (let i = 0; i < keys.length; i++) { + + let line = parseInt(keys[i]); + let profilestr = relaysData[line].profile; + + if (processLine != undefined) { + if (processLine != line) continue; + } + + try { + + /** + * we process line profiles: timepoints, astro clock, lux_sensor, offsets ... + */ + if (profilestr === "") throw ("Profile is not defined"); + let profile = JSON.parse(profilestr); + 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; + + // add name to regular profile timepoint and delete unused end_time key: + time_points.forEach(point => { + point.name = "profileTimepoint" + delete point.end_time; + }); + + //monitor.info("buildTasks: time_points", time_points); + + + /** + * 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 astro clock true, we remove all regular profile points + time_points = []; + + //TODO: when astro clock == true, is offset calculated ??? + //let duskAstroClockOffset = profile.dusk_astro_clock_offset; + //let dawnAstroClockOffset = profile.dawn_astro_clock_offset; + //console.log("line astro clock offsets dusk a dawn: ", duskAstroClockOffset, dawnAstroClockOffset); + // maybe add dusk dawn offset to calculateDuskDawn ?? what dusk dawn will be if dawn_lux_sensor == true?? + //let sunCalcResult = calculateDuskDawn(new Date(), line, duskAstroClockOffset, dawnAstroClockOffset); + + 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 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); + + 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); + + 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(':'); + + let ad = new Date(); + ad.setHours(parseInt(ahours), parseInt(aminutes), 0); + + let bd = new Date(); + bd.setHours(parseInt(bhours), parseInt(bminutes), 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++) { + + let start_time = new Date(); + let [hours, minutes] = time_points[t].start_time.split(':'); + start_time.setHours(parseInt(hours), parseInt(minutes), 0); + + //task is in 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(); + params.type = "relay"; + params.line = parseInt(line); + params.value = time_points[t].value; + params.tbname = relaysData[line].tbname; + params.timestamp = start_time.getTime(); + + // 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; + + //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)) { + 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; + + params.debug = true; + + //turn on/off line + tasks.push(params); + monitor.info("TimePoint params: ", params.info, start_time); + } + + monitor.info("-->time_points final", line, time_points); + + //ensure to turn on/off according to calculated currentValue + let params = getParams(); + params.type = "relay"; + params.line = parseInt(line); + params.tbname = relaysData[line].tbname; + params.value = currentValue; + params.timestamp = i; + params.debug = true; + + //logger.debug(now.toLocaleString("sk-SK")); + 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; + + tasks.push(params); + + } catch (error) { + if (profilestr !== "") { + //errLogger.error(profilestr, error); + console.log(`Cmd_mngr: Unable to process line profile ${line}. Error: `, error); + errorHandler.sendMessageToService(profilestr + "-" + error, 0, "js_error"); + } else { + turnLine("off", line, "No line profile. Switching it off on startup"); + } + } + + } + //logger.debug("tasks:"); + //logger.debug(tasks); + } + + + //NOTE: PROCESS DEFAULT BROADCASTS - Time of dusk, Time of dawn, Actual Time + if (processBroadcast) { + + let d = new Date(); + let time = d.getTime(); + //let sunCalcResult = calculateDuskDawn(); + + { + let params = getParams(); + + params.address = 0xffffffff;//broadcast + params.byte1 = sunCalcResult["dusk_hours"]; + params.byte2 = sunCalcResult["dusk_minutes"]; + params.recipient = 2;//2 broadcast, + params.register = 6;//Time of dusk + params.rw = 1;//write + params.type = "node-regular-write"; + params.timestamp = time + 60000; + params.addMinutesToTimestamp = 60 * 3; //kazde 3 hodiny zisti novy dusk + params.info = "Broadcast-duskTime"; + + tasks.push(params); + } + + { + let params = getParams(); + + params.address = 0xffffffff;//broadcast + params.byte1 = sunCalcResult["dawn_hours"]; + params.byte2 = sunCalcResult["dawn_minutes"]; + params.recipient = 2; //2 broadcast + params.register = 7;//Time of dawn + params.rw = 1;//write + params.type = "node-regular-write"; + params.timestamp = time + 60001; + params.addMinutesToTimestamp = 60 * 3; //kazde 3 hodiny zisti novy dawn + params.info = "Broadcast-dawnTime"; + + tasks.push(params); + } + + { + let params = getParams(); + + params.address = 0xffffffff;//broadcast + params.byte1 = d.getHours(); + params.byte2 = d.getMinutes(); + params.recipient = 2; //2 broadcast + params.register = 87;//Actual time + params.rw = 1;//write + params.type = "node-regular-write"; + params.timestamp = time + 60002; + params.addMinutesToTimestamp = 5; + params.info = "run broadcast: Actual time"; + + tasks.push(params); + } + + } + + //process nodes & tasks - read node's data + if (processNodes) { + + let time = Date.now(); + + for (let k in nodesData) { + let address = parseInt(k); + let tbname = nodesData[k].tbname; + let register = 0; + + for (let i = 0; i < listOfCommands.length; i++) { + + register = listOfCommands[i]; + let addMinutesToTimestamp = priorities[register]; + + let params = getParams(); + + params.address = address; + params.recipient = 1; + params.register = register; + params.type = register == 1 ? "node-dimming-read" : "node-regular-read"; + params.tbname = tbname; + params.timestamp = time + 5000 + i * 500 + addMinutesToTimestamp * 1000; //to make slight time difference + params.addMinutesToTimestamp = addMinutesToTimestamp; + params.info = "Node regular read command"; + + tasks.push(params); + } + + } + } + + + //niektore ulohy sa vygeneruju iba 1x pri starte!!! + if (!init) return; + + + //Master node FW version - modifies SETTINGS.masterNodeIsResponding + { + let params = getParams(); + params.type = "cmd-master"; + params.register = 4; + params.address = 0; + params.timestamp = 0; + params.addMinutesToTimestamp = 5; + params.tbname = SETTINGS.rvoTbName; + params.info = "Master node FW verzia"; + //params.debug = true; + + tasks.push(params); + } + + //kazdu hodinu skontrolovat nastavenie profilov + { + let params = getParams(); + params.type = "process_profiles"; + params.timestamp = Date.now() + 60001; + params.addMinutesToTimestamp = 60;//60 = every hour + params.info = "detekcia nespracovaných profilov linie a nodov"; + //params.debug = true; + + tasks.push(params); + } + + monitor.info("tasks created:", tasks.length); + } + + + /** + * We process line profile, where "astro_clock": true + * example profile: + * + "dawn_lux_sensor": true, + "dusk_lux_sensor": true, + "dawn_lux_sensor_value": 5, + "dusk_lux_sensor_value": 5, + "dawn_astro_clock_offset": 0, + "dusk_astro_clock_offset": 10, + "dawn_lux_sensor_time_window": 30, + "dusk_lux_sensor_time_window": 30, + "dawn_astro_clock_time_window": 60, + "dusk_astro_clock_time_window": 60 + + * if dawn: if currentTimestamp is in timewindow "dawnTime + and - dawn_lux_sensor_time_window" and lux value >= lux_sensor_value, we switch off the line. + * if dusk: we do oposite + * + * dawn: usvit - lux je nad hranicou - vypnem + * dusk: sumrak - lux je pod hranicou - zapnem + */ + 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++) { + + let line = keys[i]; //line is turned off by default + let profilestr = relaysData[line].profile; + const contactor = relaysData[line].contactor; + + try { + + let profile = JSON.parse(profilestr); + if (Object.keys(profile).length === 0) throw ("turnOnOffLinesAccordingToLuxSensor - profile is not defined"); + + 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 (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"); + } + } + } + + //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 (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"); + } + } + } + + } + + } catch (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) { + //MASTER + if (node == 0) return; + + let nodeObj = nodesData[node]; + if (nodeObj == undefined) return; + + let nodeCurrentStatus = nodeObj.status; + const now = Date.now(); + + let data = null; + + if (nodeCurrentStatus === "OFFLINE") { + data = { status: newStatus }; + nodeDbStatusModify(node, data); + return; + } + else 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; + } + + } + + + 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 }; + } + }); + }); + } + + + function processDailyReport() { + + const now = Date.now(); + + for (const [key, value] of Object.entries(dailyReport)) { + + if (["name", "time", "dusk_and_dawn"].includes(key)) continue; + + let poleNumber = nodesData[key]["pole_number"]; + let line = dailyReport[key].line; + let nodeType = nodesData[key]["node_type"]; + let fullNodeName = key // key == nodeNumber + + if (poleNumber && nodeType) { + fullNodeName = SETTINGS.rvo_number + "/" + poleNumber + "_" + line + "L_" + key + "_" + nodeType; + } else { + fullNodeName = key; + } + + if (rvo_is_on) { + + if (value.initialTs) { + if (value.initialTs + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["night_no_data"], fullNodeName); + console.log('report nedostava ziadne data uz hodinu', fullNodeName); + value.initialTs = now; + } + } + if (value.dimmingIsZeroTime) { + if (value.dimmingIsZeroTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["night_dimming=0"], fullNodeName); + console.log("report node dimming je 0 ale ma svietit", fullNodeName); + value.dimmingIsZeroTime = now; + } + } + if (value.powerIsZeroTime) { + if (value.powerIsZeroTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["night_power=0"], fullNodeName); + console.log("report node power je 0 ale ma svietit", fullNodeName); + value.powerIsZeroTime = now; + } + } + + } else { + + let contactorStatus = relaysData[line].contactor; + if (contactorStatus === 1) { + + if (value.initialTs) { + if (value.initialTs + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["day_24/7_no_data"], fullNodeName); + console.log('node je na 24/7 ale nedostava ziadne data uz hodinu', fullNodeName); + value.initialTs = now; + } + } + if (value.dimmingIsOnButShouldBeOffTime) { + if (value.dimmingIsOnButShouldBeOffTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["day_24/7_dimming>0"], fullNodeName); + console.log("report dimming je > 0 ale nema svietit", fullNodeName); + value.dimmingIsOnButShouldBeOffTime = now; + } + } + if (value.powerIsOnButShouldBeOffTime) { + if (value.powerIsOnButShouldBeOffTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["day_24/7_power>0"], fullNodeName); + console.log("report power je > 0 ale nema svietit", fullNodeName); + value.powerIsOnButShouldBeOffTime = now; + } + } + + } + + } + + } + + let report = {}; + report["name"] = SETTINGS.rvo_name; + report["time"] = new Date(); + report["report"] = reportToSend; + + writeToFile(F.path.root("report_data.log"), report, true); + instance.send(SEND_TO.dailyReport, report); + } + + + function dailyReportHandler() { + + if (!SETTINGS.daily_report) return; + + // after dawn we empty reportToSend and start to get data for a new day + const date = new Date(); + const hour = date.getHours(); + const minute = date.getMinutes(); + + console.log("now: ", hour, minute, "suncalc: ", sunCalcResult.dawn_hours, sunCalcResult.dawn_minutes); + + if (hour === sunCalcResult.dawn_hours) { + + //NOTE: ak je este pred usvitom, spracujeme report a posleme na cloud, ak uz je po usvite, resetujeme report plnime data noveho dna + if (minute >= sunCalcResult.dawn_minutes - 2) { + emptyReportToSend(); + emptyDailyReport(); + console.log("Podmienka 1 v dailyReport handler"); + } else { + processDailyReport(); + emptyReportToSend(); + emptyDailyReport(); + console.log("Podmienka 2 v dailyReport handler"); + } + + initialReportStatus = true; + + // ak sa funkcia spusti o hodinu alebo 2 neskor, ako je usvit (moze sa to stat, kedze kazde zapnutie/vypnutie linii odznova spusti casovac. + } else if (hour === sunCalcResult.dawn_hours + 1 || hour === sunCalcResult.dawn_hours + 2) { + if (!initialReportStatus) { + emptyReportToSend(); + emptyDailyReport(); + initialReportStatus = true; + console.log("Podmienka 3 v dailyReport handler"); + } else { + processDailyReport(); + initialReportStatus = true; + console.log("Podmienka 4 v dailyReport handler"); + } + } else { + processDailyReport(); + initialReportStatus = false; + console.log("Podmienka 5 v dailyReport handler"); + } + + console.log("initialReportStatus: ", initialReportStatus); + + } + + function emptyReportToSend() { + emptyJsObject(reportToSend); + reportToSend["contactor"] = { off: [], on: [] }; + reportToSend["night_no_data"] = []; + reportToSend["night_dimming=0"] = []; + reportToSend["night_power=0"] = []; + reportToSend["day_24/7_no_data"] = []; + reportToSend["day_24/7_dimming>0"] = []; + reportToSend["day_24/7_power>0"] = []; + console.log(`resetuje sa reportToSend`); + } + + + //NOTE: ked je initialTs stale rovnaky a zistime ze linie su vypnute (relaysData.line.contactor) - zistim, ci je node na tej linii. Vieme, ze ak je linia vypnuta je to v poriadku lebo nie je na 24/7 linii + //ak je na 24/7 linii, reportujeme, ze neprijima data + function emptyDailyReport() { + const ts = Date.now(); + emptyJsObject(dailyReport); + + //NOTE: do dailyReport dame vsetky nody a pravidelne kontrolujeme ci maju data + //ked nastane sumrak/usvit a svetla maju zacat/prestat svietit, dailyReport spravime nanovo: + for (const [key, value] of Object.entries(nodesData)) { + dailyReport[value.node] = { line: value.line, initialTs: ts }; + } + + console.log("dailyReport: ", dailyReport); + } + + + async function runTasks() { + + clearInterval(interval); + + let currentTimestamp = Date.now(); + + //sort tasks based on timestamp + 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) { + instance.send(SEND_TO.debug, "no tasks created"); + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + if (!rsPort.isOpen) { + instance.send(SEND_TO.debug, "!rsPort.isOpen"); + //await rsPort.open(); + //console.log("Cmd-mngr: !rsPort.isOpen"); + } + + let currentTask = tasks[0]; + + if (currentTask.debug) { + //logger.debug("--->task to process", currentTask); + } + + if (currentTask.timestamp <= currentTimestamp) { + let params = { ...tasks[0] }; + + //allow terminal commands + if (SETTINGS.maintenance_mode && params.type !== "cmd-terminal") { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + let type = params.type; + let tbname = params.tbname; + let node = params.address; + let register = params.register; + let line = null; + let itIsNodeCommand; + + if (nodesData[node] !== undefined) { + line = nodesData[node].line; + itIsNodeCommand = true; + } + + if (params.line !== undefined) line = params.line; + + if (params.addMinutesToTimestamp > 0 || params.timePointName) { + tasks[0].timestamp = currentTimestamp + tasks[0].addMinutesToTimestamp * 60000; + } else { + tasks.shift(); + } + + //kontrola nespracovanych profilov nodov + //TODO: co ked niektore nody neprijimaju profily? kazdu hodinu zahltuju "tasks" array + if (type == "process_profiles") { + //na vsetky zapnutych liniach sa spracuju nespracovane profily nodov + loadRelaysData(); + interval = setInterval(runTasks, SHORT_INTERVAL); + return; + } + + //relay + if (type == "relay") { + + const timePointName = params.timePointName; + const value = params.value; + + let date = new Date(); + date.setDate(date.getDate() + 1);//next day + + let sunCalcResult; + if (timePointName) sunCalcResult = calculateDuskDawn(date, params.line); + + + if (timePointName == "dawn") { + tasks[0].timestamp = sunCalcResult.dawn_time; + } + else if (timePointName == "dusk") { + tasks[0].timestamp = sunCalcResult.dusk_time; + } + else if (timePointName == "luxOn") { + tasks[0].timestamp = sunCalcResult.dusk_time + params.dusk_lux_sensor_time_window * 60000; + } + else if (timePointName == "luxOff") { + tasks[0].timestamp = sunCalcResult.dawn_time + params.dawn_lux_sensor_time_window * 60000; + } + else if (timePointName == "profileTimepoint") { + tasks[0].timestamp = currentTimestamp + tasks[0].addMinutesToTimestamp * 60000; + } + + let info = "aplikovany bod profilu"; + let onOrOff = ""; + value == 1 ? onOrOff = "on" : onOrOff = "off"; + + turnLine(onOrOff, params.line, info); + + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + if (!SETTINGS.masterNodeIsResponding) { + //ak neodpoveda, nebudeme vykonavat ziadne commands, okrem cmd-terminal cmd-master + errorHandler.sendMessageToService("Master node is not responding"); + + let stop = true; + + if (type === "cmd-terminal" || type === "cmd-master") stop = false; + if (stop) { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + } + + let contactorStatus = 1; + if (relaysData[line] != undefined) contactorStatus = relaysData[line].contactor; + + if (line === 0 || contactorStatus === 0 || FLOW.deviceStatus.state_of_breaker[line] === "Off") { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + // TODO: -> status offline for rvo if rotary_switch_state is OFF, this is source of errors + // check if rotary_switch_state == "Off" + // state_of_braker: disconnected = true? + + if (!rsPort.isOpen) { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + //RE-CALCULATE VALUES + //set actual time for broadcast + if (register == 87 && params.recipient === 2) { + var d = new Date(); + params.byte1 = d.getHours();//h + params.byte2 = d.getMinutes();//m + } + + //SET DUSK/DAWN FOR BROADCAST + //Time of dusk + if (register == 6 && params.recipient === 2) { + + if (type != "cmd-terminal") { + params.byte1 = sunCalcResult["dusk_hours"];//h + params.byte2 = sunCalcResult["dusk_minutes"];//m + } + } + + //Time of dawn + if (register == 7 && params.recipient === 2) { + if (type != "cmd-terminal") { + params.byte1 = sunCalcResult["dawn_hours"];//h + params.byte2 = sunCalcResult["dawn_minutes"];//m + } + } + //----------------------- + + instance.send(SEND_TO.debug, "address: " + node + " register:" + register + "type: " + type); + + var startTime, endTime; + startTime = new Date(); + + let saveToTb = true; + if (!tbname) saveToTb = false; + + let resp = com_generic(node, params.recipient, params.rw, register, params.name, params.byte1, params.byte2, params.byte3, params.byte4); + let readBytes = 11; + let timeout = 4000; + + + // await keyword is important, otherwise incorrect data is returned! + await writeData(rsPort, resp, readBytes, timeout).then(function(data) { + + //sometimes happens, that status of node changes to OK, NOK even if line was turned off and should be status OFFLINE. To prevent this, we return if line contactor is 0: + if (itIsNodeCommand && line && relaysData[line].contactor !== 1) return; + + 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); + + //ak sa odpoved zacina 0 - je to v poriadku, inak je NOK + let message = result.message; // OK, NOK + let message_type = result.type; + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + console.log("detected response:", result); + logger.debug("Cmd-mngr: writeData done " + message_type + " duration: " + timeDiff + " type: " + params.debug, params, result); + } + } + + let values = {}; + + //CMD FINISHED + if (message == "OK") { + + updateNodeStatus(node, true); + + //write + if (type == "set_node_profile") { + let result = cmdCounterResolve(node); + if (result == 0) { + dbNodes.modify({ processed: true }).where("node", node).make(function(builder) { + builder.callback(function(err, response) { + + sendNotification("Cmd-mngr: process cmd", SETTINGS.rvoTbName, "dimming_profile_was_successfully_received_by_node", { node: node }, "", SEND_TO.tb, instance); + + logger.debug("--> profil úspešne odoslaný na node č. " + node); + nodesData[node].processed = true; + nodeProfileSendFail.delete(node); + }); + }); + } + } + + //parse read response + if (params.rw == 0) { + values = processResponse(register, dataBytes); //read + } + + if (itIsNodeCommand) { + values.comm_status = "OK"; + values.status = "OK"; + nodesData[node].readout = { ...nodesData[node].readout, ...values }; + + + if (SETTINGS.daily_report) { + //TODO: co ak nedostavame odpovede z nodu ? Musime vyreportovat!! + //v dailyReport teda musi byt kompletny zoznam nodov a neustale kontrolovat, ci maju data, ak nie report node - neodpoveda + if (register === 1) { + + let now = Date.now(); + + if (rvo_is_on === true) { + + if ("dimmingIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].dimmingIsOnButShouldBeOffTime; + + if (values.dimming > 0) { + if ("dimmingIsZeroTime" in dailyReport[node]) delete dailyReport[node].dimmingIsZeroTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if (!("dimmingIsZeroTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], dimmingIsZeroTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } else { + + if ("dimmingIsZeroTime" in dailyReport[node]) delete dailyReport[node].dimmingIsZeroTime; + + if (values.dimming > 0) { + if (!("dimmingIsOnButShouldBeOffTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], dimmingIsOnButShouldBeOffTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if ("dimmingIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].dimmingIsOnButShouldBeOffTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } + } + + if (register === 76) { + + let now = Date.now(); + + if (rvo_is_on === true) { + + if ("powerIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].powerIsOnButShouldBeOffTime; + + if (values.power > 1) { + if ("powerIsZeroTime" in dailyReport[node]) delete dailyReport[node].powerIsZeroTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if (!("powerIsZeroTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], powerIsZeroTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } else { + + if ("powerIsZeroTime" in dailyReport[node]) delete dailyReport[node].powerIsZeroTime; + + if (values.power > 1) { + if (!("powerIsOnButShouldBeOffTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], powerIsOnButShouldBeOffTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if ("powerIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].powerIsOnButShouldBeOffTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } + } + } + + } + + //master node + if (node == 0) { + sendNotification("Cmd-mngr: 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; + } + + if (params.debug) { + //logger.debug("saveToTb", saveToTb, tbname, values); + } + + if (saveToTb && type != "node-regular-read") { + sendTelemetry(values, tbname); + } + else { + if (type == "cmd-terminal") { + terminalCommandResponse(params, "SUCCESS", data); + } + } + + } + else { + terminalCommandResponse(params, "ERROR", data); + handleNokResponseOnRsPort("handleNOK else block", params, itIsNodeCommand, saveToTb); + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + //logger.debug("writeData err: ", error, result, params); + logger.debug("writeData err: ", tbname, node, register, values); + } + } + + //logger.debug(error, result, params); + } + }).catch(function(reason) { + + //console.log("writeData catch exception", reason); + instance.send(SEND_TO.debug, reason); + + terminalCommandResponse(params, "FAILURE", null, reason); + handleNokResponseOnRsPort("handleNOK catch block", params, itIsNodeCommand, saveToTb); + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + logger.debug("-->WRITE FAILED: " + reason, params.debug, params); + } + } + + }); + + } + 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); + } + + + // if node does not respond to request, we repeat request 3 times: + function repeatCommand(params) { + params.repeatCounter++; + if (params.repeatCounter < 4) { + params.timestamp = 0; + params.addMinutesToTimestamp = 0; + tasks.push(params); + } + } + + function handleNokResponseOnRsPort(message, params, itIsNodeCommand, saveToTb) { + + let node = params.address; + let register = params.register; + let type = params.type; + let tbName = params.tbname; + if (!tbName) return; + + let values = {}; + + let updateStatus = updateNodeStatus(node, false); + + if (itIsNodeCommand) { + values.comm_status = "NOK"; + nodesData[node].readout.comm_status = "NOK"; + repeatCommand(params); + } + + if (updateStatus) { + values.status = "NOK"; + nodesData[node].readout.status = "NOK"; + } + + if (type === "node-regular-read") return; + + //master node + if (node == 0) { + sendNotification("Cmd-mngr: 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; + + if (register == 4) values["master_node_version"] = "NOK"; + } + + if (type == "set_node_profile") { + delete cmdCounter[node]; + logger.debug("profil nebol úspešne odoslaný na node č. ", params); + + if (!nodeProfileSendFail.has(node)) { + sendNotification("Cmd-mngr: process cmd", tbName, "configuration_of_dimming_profile_to_node_failed", { node: node }, "", SEND_TO.tb, instance); + nodeProfileSendFail.add(node); + } + } + + // console.log("------",node, register, type, itIsNodeCommand, updateStatus, saveToTb, values); + if (saveToTb) { + sendTelemetry(values, tbName); + } + + } + + + function sendNodesData() { + Object.keys(nodesData).forEach(node => { + if (nodesData[node]["status"] !== "OFFLINE") { + sendTelemetry(nodesData[node].readout, nodesData[node].tbname); + nodesData[node].readout = {}; + } + }) + } + + + /** + * 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; + } + + 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); + + //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 === "OFFLINE") { + nodeObj.node_status_before_offline === true ? number_of_ok_luminaires++ : number_of_nok_luminaires++; + } + else if (nodeObj.status == true) 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 - ts % 60000 //round to full minute + }; + + sendTelemetry(values, SETTINGS.rvoTbName, ts); + } + + + function setSunCalcResult() { + //if next day, we get new dusk and dawn. To make sure, in local timezone 2:00 means 00:00 in utc (it means next day) + if (new Date().getHours() === 2) { + sunCalcResult = calculateDuskDawn(); + console.log("Novy suncalc: ", sunCalcResult); + } + } + + + function setRvoPeriod() { + + if (!SETTINGS.daily_report) return; + + const ts = Date.now(); + + previous_rvo_is_on_value = rvo_is_on; + + if (ts < sunCalcResult.dawn_time - 1_800_000) { // nodes should be on (00:00 -> 06:00 ( - pol hodina, lebo rvo vypina skor) + rvo_is_on = true; + } else if (sunCalcResult.dawn_time - 1_800_000 < ts && ts < sunCalcResult.dusk_time + 1_800_000) { // nodes should be off 06:00 -> 21:00 + rvo_is_on = false; + } else if (sunCalcResult.dusk_time + 1_800_000 < ts) { // nodes should be on 21:00 -> 00:00 + rvo_is_on = true; + } + + if (previous_rvo_is_on_value !== rvo_is_on) { + emptyDailyReport(); + console.log("rvo_is: ", rvo_is_on, previous_rvo_is_on_value); + } + } + + + function handleRsPort() { + + if (rsPort) { + rsPort.removeAllListeners(); + rsPort = null; + } + + //! 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-mngr: rsPort opened success"); + + 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); + + }).catch(function(reason) { + instance.send(SEND_TO.debug, "Cmd-mngr: RPC runSyncExec - promise rejected:" + reason); + }); + }); + + rsPort.on('error', function(err) { + errorHandler.sendMessageToService([exports.title, "unable to open port", SETTINGS.serial_port, err.message], 0); + monitor.info("Cmd-mngr: Error on rsPort", err.message); + }); + + rsPort.on("close", () => { + monitor.info("Cmd-mngr: rsPort closed, reconnecting..."); + setTimeout(handleRsPort, 1000); + }); + + rsPort.open(); + } + + + instance.on("close", () => { + clearInterval(interval); + clearInterval(customTasksInterval); + clearInterval(setCorrectTime); + clearInterval(sendNodeReadout); + clearInterval(accelerometerInterval); + rsPort.close(); + }); + + instance.on("0", _ => { + main(); + }) + + + instance.on("2", _ => { + console.log("dailyReport, reportToSend, rvo_is_on", dailyReport, reportToSend, rvo_is_on, previous_rvo_is_on_value); + }) + + instance.on("1", 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(); + return; + } + else if (flowdata.data == "close") { + rsPort.close(); + return; + } + else if (flowdata.data == "clean") { + tasks = []; + return; + } + else if (flowdata.data == "buildtasks") { + //build & run + return; + } + else if (flowdata.data == "run") { + //durations = []; + + if (tasks.length == 0) { + + buildTasks(); + + if (rsPort.isOpen) { + interval = setInterval(runTasks, 100); + } + else { + instance.send(SEND_TO.debug, "port is not opened!!!"); + } + } + } + else { + //terminal data - object + //logger.debug("flowdata", flowdata.data); + + if (typeof flowdata.data === 'object') { + //logger.debug("dido", flowdata.data); + if (flowdata.data.hasOwnProperty("sender")) { + //data from dido_controller + if (flowdata.data.sender == "dido_controller") { + + if (flowdata.data.hasOwnProperty("cmd")) { + let cmd = flowdata.data.cmd; + + if (cmd == "buildTasks") { + clearInterval(interval); + + logger.debug("-->Cmd-mngr: BUILD TASKS"); + buildTasks(); + + //logger.debug("tasks:"); + //logger.debug(tasks); + + logger.debug("-->Cmd-mngr: RUN TASKS"); + interval = setInterval(runTasks, 5000); + } + else if (cmd == "reload_relays") { + loadRelaysData(flowdata.data.line); + + if (flowdata.data.dataChanged) { + if (!flowdata.data.value) { + reportOfflineNodeStatus(flowdata.data.line); + } + else { + reportOnlineNodeStatus(flowdata.data.line); + } + } + + } + else if (cmd == "rotary_switch_state") { + let value = flowdata.data.value; + + //state was changed + if (rotary_switch_state != value) { + if (value == "Off") { + //vyreportovat vsetky svietdla + reportOfflineNodeStatus(); + } + + rotary_switch_state = value; + } + } + 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) { + + // we send lux_sensor value to all nodes: + let params = getParams(PRIORITY_TYPES.node_broadcast); + + params.recipient = 2;//2 broadcast, address = 0 + params.address = 0xffffffff;//Broadcast + + let ba = longToByteArray(lux_sensor); + + params.byte3 = ba[1];//msb + params.byte4 = ba[0]; + params.timestamp = PRIORITY_TYPES.node_broadcast; + params.info = "run broadcast: Actual Lux level from cabinet"; + params.register = 95;//Actual Lux level from cabinet + params.rw = 1;//write + + tasks.push(params); + + //process profiles + turnOnOffLinesAccordingToLuxSensor(lux_sensor); + } + } + else if (cmd == "state_of_breaker") { + //istic linie + + breakerCounter--; + + let value = flowdata.data.value; + let line = parseInt(flowdata.data.line); + + let dataChanged = false; + if (state_of_breaker[line] != value) dataChanged = true; + + state_of_breaker[line] = value; + + let status = "OK"; + if (value == "Off") status = "NOK"; + + if (dataChanged) { + + if (relaysData.hasOwnProperty(line)) { + let tbname = relaysData[line].tbname; + + if (value == "Off") { + sendNotification("Cmd-mngr: onData", tbname, "circuit_breaker_was_turned_off_line", { line: line }, "", SEND_TO.tb, instance, "circuit_breaker"); + if (breakerCounter < 0) reportToSend["contactor"]["off"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + else { + sendNotification("Cmd-mngr: onData", tbname, "circuit_breaker_was_turned_on_line", { line: line }, "", SEND_TO.tb, instance, "circuit_breaker"); + if (breakerCounter < 0) reportToSend["contactor"]["on"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + + //report status liniu + sendTelemetry({ status: status }, tbname) + + //current value + if (value == "Off") reportOfflineNodeStatus(line); //vyreportovat vsetky svietidla na linii + } + + } + } + else { + logger.debug("undefined cmd", cmd); + } + } + } + + return; + } + + //data from worksys + if (flowdata.data.hasOwnProperty("topic")) { + + let data = getNested(flowdata.data, "content", "data"); + + //if we get temperature in senica from senica-prod01 + let temperature = getNested(flowdata.data, "content", "senica_temperature"); + + if (temperature !== undefined) { + temperatureInSenica = temperature; + return; + } + + if (data === undefined) { + console.log("Invalid rpc command came from platform"); + return; + } + + let command = data.params.command; + let method = data.method; + let profile = data.params.payload; + if (profile == undefined) profile = ""; + let entity = data.params.entities[0]; + let entity_type = entity.entity_type; + let tbname = entity.tb_name; + + instance.send(SEND_TO.debug, flowdata.data); + 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") { + + //let command = data.params.command; + let value = data.params.payload.value; + + if (command == "dimming") { + + let nodeWasFound = false; + let keys = Object.keys(nodesData); + + //logger.debug("-----", keys); + + 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); + + value = parseInt(value); + if (value > 0) value = value + 128; + + params.type = "node-onetime-write"; + params.tbname = tbname; + params.address = node; + params.register = 1; + params.recipient = 1; + params.byte4 = value; + params.rw = 1; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'set dimming from platform'; + //params.debug = true; + + //debug(params); + logger.debug("dimming", params); + + tasks.push(params); + + 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); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 1; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read dimming (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + //pridame aj vyreportovanie - vykon + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 76; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read Input Power (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + //pridame aj vyreportovanie - prud svietidla + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 75; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read Input Current (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + //pridame aj vyreportovanie - power faktor - ucinnik + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 77; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read power factor (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + }, 4000); + + nodeWasFound = true; + break; + } + } + + if (!nodeWasFound) { + logger.debug("set dimming from platform", "unable to find tbname", tbname); + } + } + else { + instance.send(SEND_TO.debug, "undefined command " + command); + logger.debug("undefined command", command); + } + + return; + } + 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++) { + let node = keys[i]; + if (tbname == nodesData[node].tbname) { + + 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"); + + //profil úspešne prijatý pre node č. xx + sendNotification("Cmd-mngr", tbname, "dimming_profile_was_processed_for_node", { node: node }, profile, SEND_TO.tb, instance); + + nodesData[node].processed = false; + nodesData[node].profile = profile; + + processNodeProfile(node); + }); + }); + } + } + } + else { + + instance.send(SEND_TO.debug, "unknown method " + method); + logger.debug("unknown method", method); + + return; + } + } + + //nastav profil linie z platformy + 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") { + + 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++) { + let line = keys[i]; + if (tbname == relaysData[line].tbname) { + //zmazeme tasky + 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) { + + //update profile + logger.debug("worksys - update relay profile done:", profile); + instance.send(SEND_TO.debug, "worksys - update relay profile done"); + + relaysData[line].profile = profile; + + loadRelaysData(line) + logger.debug("loadRelaysData DONE for line", line); + + buildTasks({ processLineProfiles: true, line: line }); + + sendNotification("Cmd-mngr: set profile from worksys", tbname, "switching_profile_was_processed_for_line", { line: line }, profile, SEND_TO.tb, instance); + }); + }); + break; + } + } + } + else if (method == "set_command") { + let value = data.params.payload.value; + + 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; + + 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"); + if (line != 0) reportToSend["contactor"]["off"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + else { + turnLine("on", line, "command received from platform"); + if (line != 0) reportToSend["contactor"]["on"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + } + } + else { + instance.send(SEND_TO.debug, "undefined method " + method); + logger.debug("undefined method", method); + } + + return; + } + else { + instance.send(SEND_TO.debug, "UNKNOW entity_type " + entity_type); + logger.debug("UNKNOW entity_type", entity_type); + } + return; + } + + //terminal + if (!rsPort.isOpen) await rsPort.open(); + + let params = flowdata.data.body; + if (params == undefined) { + //logger.debug("Cmd-mngr: flowdata.data.body is undefined"); + return; + } + + params.priority = PRIORITY_TYPES.terminal; + params.type = "cmd-terminal"; + params.tbname = ""; + params.timestamp = PRIORITY_TYPES.terminal; + params.addMinutesToTimestamp = 0;// do not repeat task!!! + params.debug = true; + + let timestamp = Date.now(); + params.refFlowdataKey = timestamp; + //params.refFlowdata = flowdata; + //refFlowdata = flowdata; + + //console.log("flowdata", flowdata); + + cleanUpRefFlowdataObj(); + + refFlowdataObj[timestamp] = flowdata; + + //fix + //params.address = params.adress; + logger.debug("received from terminal", params); + logger.debug("date/time:", new Date()); + logger.debug("tasks length:", tasks.length); + + //tasks = []; + + //add to tasks + tasks.push(params); + + } + } + }) + + + //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) + } + + + /** + * 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; + + RESTBuilder.make(function(builder) { + + if (!builder) return; + + builder.method('GET'); + builder.url('http://192.168.252.2:8004/gettime?projects_id=1'); + + builder.callback(function(err, response, output) { + + 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); + } + + }); + } + + } 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); + + } else { + //console.log("Read-only", stdout); + + 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]: [ + { + "ts": date, + "values": values + } + ] + } + + tbHandler.sendToTb(dataToTb, instance); + } + + + function calculateDuskDawn(date, line, duskOffset = 0, dawnOffset = 0) { + + if (date === undefined) date = new Date(); + + 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); + } + + //if(profile.dawn_lux_sensor == false) + { + if (profile.hasOwnProperty("dawn_astro_clock_offset")) dawn_astro_clock_offset = parseInt(profile.dawn_astro_clock_offset); + } + + } + + } catch (error) { + if (profilestr != "") { + logger.debug(profilestr); + logger.debug(error); + } + } + + 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; + } + + //Dimming, CCT + else if (register == 1) { + let brightness = 0; + let dimming = byte0; + if (dimming > 128) { + //dimming = -128; + brightness = dimming - 128; + } + + //cct + //Ak Byte3 == 1: CCT = (Byte2*256)+Byte1 + let cct; + if (byte3 == 1) cct = byte2 * 256 + byte1; + else cct = bytesToInt(bytes.slice(0, 3)); + + //cct podla auditu + + values["dimming"] = brightness; + return values; + } + + // + else if (register == 4) { + values["master_node_version"] = bytes[1] + "." + bytes[2]; + //logger.debug("FW Version", register, bytes); + } + + //Napätie + else if (register == 74) { + let voltage = (bytesToInt(bytes) * 0.1).toFixed(1); + values["voltage"] = Number(voltage); + } + + //Prúd + else if (register == 75) { + let current = bytesToInt(bytes); + values["current"] = current; + } + + //výkon + else if (register == 76) { + let power = (bytesToInt(bytes) * 0.1).toFixed(2); + values["power"] = Number(power); + } + + //účinník + else if (register == 77) { + let power_factor = Math.cos(bytesToInt(bytes) * 0.1 * (Math.PI / 180)).toFixed(2); + values["power_factor"] = Number(power_factor); + } + + //frekvencia + else if (register == 78) { + let frequency = (bytesToInt(bytes) * 0.1).toFixed(2); + values["frequency"] = Number(frequency); + } + + //energia + else if (register == 79) { + let energy = bytesToInt(bytes); + values["energy"] = energy / 1000; //energia v kWh -> delit 1000 + } + + //doba života + else if (register == 80) { + let lifetime = (bytesToInt(bytes) / 60).toFixed(2); + values["lifetime"] = Number(lifetime); + } + + //nastavenie profilu + else if (register == 8) { + let time_schedule_settings = bytesToInt(bytes); + values["time_schedule_settings"] = time_schedule_settings; + } + + //naklon - nateraz sa z nodu nevycitava! kvoli problemom s accelerometrom a vracanymi hodnotami, posielame temp a x y z vo funkcii accelerometerData() + else if (register == 84) { + values["temperature"] = byte3 >= 128 ? (byte3 - 128) * (-1) : byte3; + values["inclination_x"] = byte2 >= 128 ? (byte2 - 128) * (-1) : byte2; + values["inclination_y"] = byte1 >= 128 ? (byte1 - 128) * (-1) : byte1; + values["inclination_z"] = byte0 >= 128 ? (byte0 - 128) * (-1) : byte0; + } + + //FW verzia nodu + else if (register == 89) { + //formát: "Byte3: Byte2.Byte1 (Byte0)" + values["fw_version"] = byte3 + ":" + byte2 + "." + byte1 + "(" + byte0 + ")"; + } + + else if (register == 87 || register == 6 || register == 7) { + var d = new Date(); + d.setHours(byte3, byte2, 0, 0); + let timestamp = d.getTime(); + + //aktuálny čas + if (register == 87) values["actual_time"] = timestamp; + //čas súmraku + else if (register == 6) values["dusk_time"] = timestamp; + //čas úsvitu + else if (register == 7) values["dawn_time"] = timestamp; + } + + 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; + + } + + + function getObjectByTbValue(object, tbname) { + return object[Object.keys(object).find(key => object[key].tbname === tbname)]; + } + + + function isObject(item) { + return (typeof item === "object" && !Array.isArray(item) && item !== null); + } + + + // we fake data, that should be received from accelerometer, as they are a bit unreliable. (temperature, x,y,z) + function accelerometerData() { + + if (temperatureInSenica === null) return; + + //clone nodesData and relaysData objects + let nodesData_clone = JSON.parse(JSON.stringify(nodesData)); + let relaysData_clone = JSON.parse(JSON.stringify(relaysData)); + + for (const key in relaysData_clone) { + + const lineData = relaysData_clone[key]; + const lineNumber = lineData.line; + const contactor = lineData.contactor; + + if (lineNumber === 0) continue; + + if (contactor === 1) { + + let date = Date.now(); + + Object.keys(nodesData_clone).forEach((node, index) => { + + setTimeout(function() { + + if (nodesData_clone[node].line === lineNumber) { + + // NOTE: if status of luminaire is NOK or OFFLINE, we do not send data; + let status = nodesData_clone[node].status; + if (status === "OFFLINE" || !status) return; + + let x = null; + if (naklony.hasOwnProperty(node)) x = naklony[node].naklon; + if (x === null) x = 0; + + sendTelemetry({ temperature: Math.round(temperatureInSenica + 10 + Math.floor(Math.random() * 3)), inclination_x: x, inclination_y: 0, inclination_z: 0 }, nodesData_clone[node].tbname, date); + } + + }, (index + 1) * 500); + }) + + } + } + } + + +} // end of instance.export + diff --git a/RVO38/flow/code.js b/RVO38/flow/code.js new file mode 100755 index 0000000..63b31bf --- /dev/null +++ b/RVO38/flow/code.js @@ -0,0 +1,90 @@ +exports.id = 'code'; +exports.title = 'Code'; +exports.group = 'Common'; +exports.color = '#656D78'; +exports.input = true; +exports.output = 1; +exports.author = 'Peter Širka'; +exports.icon = 'code'; +exports.version = '1.2.0'; +exports.options = { outputs: 1, code: 'send(0, value);', keepmessage: true }; + +exports.html = `
+
+
+
@(Number of outputs)
+
@(Minimum is 1)
+
+
+
@(Code)
+
@(Keep message instance)
+
+`; + +exports.readme = `# Code + +This component executes custom JavaScript code as it is and it doesn't contain any secure scope. + +\`\`\`javascript +// value {Object} contains received data +// send(outputIndex, newValue) sends a new value +// error(value) sends an error +// instance {Object} a current component instance +// flowdata {Object} a current flowdata +// repository {Object} a current repository of flowdata +// Example: + +// send() can be execute multiple times +send(0, value); +\`\`\``; + +exports.install = function(instance) { + + var fn; + + instance.on('data', function(response) { + if (fn) { + try { + fn(response.data, instance, response, instance.options, response.repository, require); + } catch (e) { + response.data = e; + instance.throw(response); + } + } + }); + + instance.reconfigure = function() { + try { + if (instance.options.code) { + instance.status(''); + var code = 'var send = function(index, value) { if (options.keepmessage) { flowdata.data = value; instance.send2(index, flowdata); } else instance.send2(index, value);}; var error = function(err) { instance.throw(err); }; ' + instance.options.code; + fn = new Function('value', 'instance', 'flowdata', 'options', 'repository', 'require', code); + } else { + instance.status('Not configured', 'red'); + fn = null; + } + } catch (e) { + fn = null; + instance.error('Code: ' + e.message); + } + }; + + instance.on('options', instance.reconfigure); + instance.reconfigure(); +}; \ No newline at end of file diff --git a/RVO38/flow/comment.js b/RVO38/flow/comment.js new file mode 100755 index 0000000..1e0cd13 --- /dev/null +++ b/RVO38/flow/comment.js @@ -0,0 +1,11 @@ +exports.id = 'comment'; +exports.title = 'Comment'; +exports.group = 'Common'; +exports.color = '#704cff'; +exports.author = 'Martin Smola'; +exports.icon = 'comment'; +exports.traffic = false; +exports.version = '1.0.0'; +exports.readme = '# Comment'; + +exports.install = function() {}; diff --git a/RVO38/flow/count.js b/RVO38/flow/count.js new file mode 100755 index 0000000..fa92ee9 --- /dev/null +++ b/RVO38/flow/count.js @@ -0,0 +1,60 @@ +exports.id = 'count'; +exports.title = 'Count'; +exports.version = '1.0.1'; +exports.author = 'John Graves'; +exports.color = '#656D78'; +exports.icon = 'plus-square'; +exports.input = 2; +exports.output = 1; +exports.options = { increment: 1, initialvalue: 1 }; +exports.readme = `# Counter + +Counter Number of times called.`; + +exports.html = `
+
@(Initial Value)
+
@(Increment)
+

Example Video

+
`; + +exports.readme = `# Count + +This component counts the number of messages received. + +__Response:__ + +Integer value based on the initial value and increment settings. + +__Arguments:__ +- Initial Value: What number should be output on the receipt of the first message. +- Increment: What should the increment be for each following message received.`; + +exports.install = function(instance) { + + var count = 0; + var initialCall = true; + + instance.on('data', function(flowdata) { + var index = flowdata.index; + if (index) { + instance.debug('Reset Count.'); + count = instance.options.initialvalue; + initialCall = true; + } else { + // If this is the first time, set the value to 'initial value' + if(initialCall) { + initialCall = false; + count = instance.options.initialvalue; + } else + count = count+instance.options.increment; + instance.status('Count:' + count); + instance.send2(count); + } + }); + + instance.on('options', function() { + count = instance.options.initialvalue; + initialCall = true; + }); + +}; diff --git a/RVO38/flow/db_connector.js b/RVO38/flow/db_connector.js new file mode 100755 index 0000000..65ee94b --- /dev/null +++ b/RVO38/flow/db_connector.js @@ -0,0 +1,286 @@ +exports.id = 'db_connector'; +exports.title = 'DbConnector'; +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.html = `
+
+
+
DbConnector
+
+
+
`; + +exports.readme = `# read/write data to tables`; + +const instanceSendTo = { + debug: 0, + http_response: 1, +} + +const { promisifyBuilder, makeMapFromDbResult } = require('./helper/db_helper.js'); + +function extractWhereParams(params) +{ + let name = params[0]; + let operator = '='; + let value = params[1]; + + if(params.length == 3) + { + operator = params[1]; + value = params[2]; + } + + return {name: name, operator: operator, value: value}; +} + +exports.install = function(instance) { + + let refFlowdata = null;//holds reference to httprequest flowdata + + instance.on("close", () => { + + }) + + + instance.on("data", async function(flowdata) { + + let params = flowdata.data.body; + console.log("DbConnector", params); + + refFlowdata = flowdata; + + if(refFlowdata != undefined) + { + //make http response + let responseObj = {}; + responseObj["type"] = "SUCESS"; + + try{ + + let table = params.table; + let action = params.action; + + + if(params.data != undefined) + { + let className = params.data.className; + + if(className == "SqlQueryBuilder") + { + let type = params.data.type; + + console.log("SqlQueryBuilder---->", params.data); + + if(type == "SELECT") + { + let table = params.data.queryData.tables[0].table; + + const db = TABLE(table); + var builder = db.find(); + + let result = await promisifyBuilder(builder); + + let response = {}; + response["result"] = result; + response["success"] = true; + + responseObj["data"] = response; + + //console.log(responseObj); + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + } + + return; + } + } + + + console.log("db_connector---->", table, action); + + //actions: read, replace, insert, delete, update... + + if(action == "read") + { + const db = TABLE(params.table); + + //where builder.where('age', '<', 15); + //builder.where('id', 3403); + + var builder = db.find(); + + //https://docs.totaljs.com/latest/en.html#api~DatabaseBuilder~builder.where + if(params.hasOwnProperty("where")) + { + //optionalCan contain "=", "<=", "<", ">=", ">". + //Default value: '=' + + //1.["production_line", 1] + //2. ["or", ["production_line", 1], ["production_line", 2], "end"] + + if (Array.isArray(params.where)) { + + let multipleConditions = false; + + if(params.where[0] == "or") multipleConditions = true; + if (Array.isArray(params.where[0])) multipleConditions = true; + + if(multipleConditions) + { + + for(var i = 0; i < params.where.length; i++) + { + const item = params.where[i]; + + if(item === "or") builder.or(); + + if (Array.isArray(item)) + { + const { name, operator, value } = extractWhereParams(item); + builder.where(name, operator, value); + } + + if(item === "end") builder.end(); + + } + + } + else + { + const { name, operator, value } = extractWhereParams(params.where); + builder.where(name, operator, value); + } + + } + + /* + if(params.where.length >=2 ) + { + let name = params.where[0]; + let operator = '='; + let value = params.where[1]; + + if(params.where.length == 3) + { + operator = params.where[1]; + value = params.where[2]; + } + + builder.where(name, operator, value); + } + */ + } + + if(params.hasOwnProperty("between")) + { + builder.between(params.between[0], params.between[1], params.between[2]); + } + + let response = await promisifyBuilder(builder); + responseObj["data"] = response; + + //console.log(responseObj); + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + + return; + } + + if(action == "delete") + { + + } + + + if(action == "update") + { + //! data receiving from terminal (params) + // { + // hostname: 'localhost', + // table: 'settings', + // action: 'update', + // body: { + // rvo_name: 'terrrr', + // lang: 'en', + // temperature_adress: '28.427B45920702', + // latitude: 48.70826502, + // longitude: 17.28455203, + // mqtt_host: '192.168.252.4', + // mqtt_clientid: 'showroom_test_panel_led', + // mqtt_username: 'xmRd6RJxW53WZe4vMFLU', + // mqtt_port: 1883, + // maintanace_mode: false + // } + // } + const tableToModify = TABLE(params.table); + const newValues = params.body; + + tableToModify.modify(newValues).make(function(builder) { + + builder.callback(function(err, response) { + + if(!err) + { + responseObj["data"] = response; + responseObj["tableUpdated"] = true; + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + } + }); + }); + + } + + if(action == "replace") + { + //truncate table + const db = TABLE(params.table); + var builder = db.remove(); + db.clean(); + + //insert data + let data = params.data; + + for(let i = 0; i < data.length; i++) + { + //console.log(data[i]); + db.insert(data[i]); + } + + console.log("insert done"); + + let responseObj = {}; + responseObj["type"] = "SUCESS"; + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + + + } + + + + } catch (error) { + //console.log(error); + responseObj["type"] = "ERROR"; + responseObj["message"] = error; + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + } + } + }) +} + + diff --git a/RVO38/flow/db_init.js b/RVO38/flow/db_init.js new file mode 100755 index 0000000..b399878 --- /dev/null +++ b/RVO38/flow/db_init.js @@ -0,0 +1,113 @@ +exports.id = 'db_init'; +exports.title = 'DB Initialization'; +exports.group = 'Worksys'; +exports.color = '#888600'; +exports.version = '1.0.2'; +exports.icon = 'sign-out'; +exports.output = 2; + +exports.readme = ` + # DB initialization +`; + +const { promisifyBuilder, makeMapFromDbResult } = require('./helper/db_helper.js'); +const { initNotification } = require('./helper/notification_reporter'); +const errorHandler = require('./helper/ErrorToServiceHandler'); +const total_energy = require('../databases/total_energy'); + +const SEND_TO = { + db_init: 0, + infoSender: 1 +}; + + +exports.install = async function(instance) { + const dbNodes = TABLE("nodes"); + const dbRelays = TABLE("relays"); + const dbSettings = TABLE("settings"); + 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 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.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"]; + Object.keys(dbs.nodesData).forEach(node => dbs.nodesData[node].readout = {}) + + let rvo_number = responseSettings[0]["rvo_name"].match(/\D+(\d{1,2})_/)[1]; + + dbs.settings = { + edge_fw_version: "2025-10-08", //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"], + phases: responseSettings[0]["phases"], + cloud_topic: responseSettings[0]["cloud_topic"], + has_main_switch: responseSettings[0]["has_main_switch"], + daily_report: responseSettings[0]["daily_report"], + send_changed_node_numbers: responseSettings[0]["send_changed_node_numbers"], + rvo_number: rvo_number, + + //dynamic values + masterNodeIsResponding: true, //cmd_manager + maintenance_mode: false, + } + + + dbs.settings.energy_to_switch_lamps = total_energy[rvo_number]; + if (dbs.settings.energy_to_switch_lamps === undefined) console.log('=============== db_init.js: energy_to_switch_lamps is undefined'); + + FLOW.dbLoaded = true; + errorHandler.setProjectId(dbs.settings.project_id); + initNotification(); + + //APP START - send to data services + const toService = { + id: dbs.settings.project_id, + name: dbs.settings.rvo_name, + fw_version: dbs.settings.edge_fw_version, + startdate: new Date().toISOString().slice(0, 19).replace('T', ' '), + js_error: "", + error_message: "" + }; + + instance.send(SEND_TO.infoSender, toService); + console.log("----------------> START - message send to service", toService); + + setTimeout(() => { + console.log("DB_INIT - data loaded"); + instance.send(SEND_TO.db_init, "_") + }, 5000) + +}; + diff --git a/RVO38/flow/debug.js b/RVO38/flow/debug.js new file mode 100755 index 0000000..00cb259 --- /dev/null +++ b/RVO38/flow/debug.js @@ -0,0 +1,100 @@ +exports.id = 'debug'; +exports.title = 'Debug'; +exports.author = 'Peter Širka'; +exports.color = '#967ADC'; +exports.click = true; +exports.input = true; +exports.icon = 'bug'; +exports.version = '2.0.4'; +exports.options = { enabled: true, repository: false, type: 'data' }; +exports.readme = `# Debug + +Prints data to the debug tab.`; + +exports.html = `
+
+
+
@(Output type)
+
@(Path to the property (leave empty to show the whole data object))
+
@(A group name)
+
@(Enabled)
+
+
+
`; + +exports.install = function(instance) { + + instance.on('data', function(response) { + if (instance.options.enabled) { + + var opt = instance.options; + var rep = response.repository; + var val = response.data; + var id = response.id; + + switch (instance.options.type){ + case 'both': + var data = {}; + data.repository = rep; + data.data = val instanceof Error ? { error: val.message, stack: val.stack } : val; + instance.debug(safeparse(opt.property ? U.get(data, opt.property) : data), undefined, opt.group, id); + break; + case 'repository': + instance.debug(safeparse(opt.property ? U.get(rep, opt.property) : rep), undefined, opt.group, id); + break; + case 'data': + default: + if (val instanceof Error) + instance.debug({ error: val.message, stack: val.stack }, undefined, opt.group, id); + else + instance.debug(safeparse(opt.property ? U.get(val, opt.property) : val), undefined, opt.group, id); + break; + } + } + }); + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + instance.save(); + }); + + instance.on('options', function() { + instance.custom.status(); + }); + + instance.custom.status = function() { + instance.status(instance.options.enabled ? 'Enabled' : 'Disabled'); + }; + + instance.custom.status(); + + function safeparse(o) { + + if (o instanceof Buffer) + return o; + + if (o === undefined) + return 'undefined'; + + if (o === null) + return 'null'; + + var cache = []; + var str = JSON.stringify(o, function(key, value) { + if (typeof value === 'object' && value !== null) { + if (cache.indexOf(value) !== -1) { + try { + return JSON.parse(JSON.stringify(value)); + } catch (error) { + return; + } + } + cache.push(value); + } + return value; + }); + cache = null; + return JSON.parse(str); + } +}; diff --git a/RVO38/flow/designer.json b/RVO38/flow/designer.json new file mode 100755 index 0000000..580f5a3 --- /dev/null +++ b/RVO38/flow/designer.json @@ -0,0 +1,3102 @@ +{ + "tabs": [ + { + "name": "MAIN PUSH", + "linker": "main-push", + "id": "1612772287426", + "index": 0 + }, + { + "name": "CMD manager", + "linker": "cmd-manager", + "id": "1615551125555", + "index": 1 + }, + { + "name": "Devices", + "linker": "devices", + "id": "1611921777196", + "index": 2 + } + ], + "components": [ + { + "id": "1611951142547", + "component": "debug", + "tab": "1611921777196", + "name": "ERROR", + "x": 598, + "y": 60, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#DA4453", + "notes": "" + }, + { + "id": "1612776786008", + "component": "wsmqttpublish", + "tab": "1612772287426", + "name": "WS MQTT publish", + "x": 281.75, + "y": 174, + "connections": { + "0": [ + { + "index": "0", + "id": "1615551060773" + } + ], + "1": [ + { + "index": "0", + "id": "1618300858252" + }, + { + "index": "0", + "id": "1618558465485" + } + ], + "2": [ + { + "index": "0", + "id": "1634303685503" + } + ], + "3": [ + { + "index": "0", + "id": "1731068754606" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Connected", + "color": "green" + }, + "options": { + "username": "", + "clientid": "", + "port": "1883", + "host": "" + }, + "color": "#888600", + "notes": "" + }, + { + "id": "1612778461252", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "tb-push", + "x": 72.75, + "y": 328, + "connections": { + "0": [ + { + "index": "0", + "id": "1612783322136" + }, + { + "index": "1", + "id": "1612776786008" + }, + { + "index": "0", + "id": "1731068754606" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1612783322136", + "component": "debug", + "tab": "1612772287426", + "name": "to TB", + "x": 283.75, + "y": 324, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615551060773", + "component": "debug", + "tab": "1612772287426", + "name": "errors from MQTT Broker", + "x": 594, + "y": 57, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#DA4453", + "notes": "" + }, + { + "id": "1615563373927", + "component": "debug", + "tab": "1615551125555", + "name": "Debug", + "x": 755, + "y": 155, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#DA4453", + "notes": "" + }, + { + "id": "1615566865233", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "tb-push", + "x": 755, + "y": 248, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1615798582262", + "component": "debug", + "tab": "1615551125555", + "name": "CMD_debug", + "x": 755, + "y": 346, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615802995322", + "component": "debug", + "tab": "1611921777196", + "name": "Debug", + "x": 596.8833312988281, + "y": 566.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Disabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": false + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615809128443", + "component": "debug", + "tab": "1611921777196", + "name": "tempToTb", + "x": 595.8833312988281, + "y": 658.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615809595184", + "component": "virtualwireout", + "tab": "1611921777196", + "name": "tb-push", + "x": 597.8833312988281, + "y": 377.25, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1616165795916", + "component": "httproute", + "tab": "1615551125555", + "name": "POST /terminal", + "x": 135, + "y": 547, + "connections": { + "0": [ + { + "index": "0", + "id": "1684060205000" + }, + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Listening", + "color": "green" + }, + "options": { + "timeout": 10, + "cachepolicy": 0, + "cacheexpire": "5 minutes", + "size": 5, + "url": "/terminal", + "method": "POST", + "name": "", + "flags": [ + "id:1616165795916", + "post", + 10000 + ], + "emptyresponse": false + }, + "color": "#5D9CEC", + "notes": "### Configuration\n\n- __POST /terminal__\n- flags: \n- maximum request data length: __5 kB__\n- empty response: __false__\n- cache policy: __no cache__\n- cache expire: __5 minutes__", + "cloning": false + }, + { + "id": "1616165824813", + "component": "httpresponse", + "tab": "1615551125555", + "name": "HTTP Response", + "x": 753, + "y": 423, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "json" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1617104731852", + "component": "debug", + "tab": "1615551125555", + "name": "DIDO_Debug", + "x": 669, + "y": 1040, + "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": "turnOff line", + "x": 133, + "y": 1161, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "object", + "data": "{line: 3, command: \"turnOff\", force: true}" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1617115013095", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "tb-push", + "x": 669, + "y": 1150, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1617284749681", + "component": "trigger", + "tab": "1615551125555", + "name": "update profile / node", + "x": 112, + "y": 208, + "connections": { + "0": [ + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "data": "profile_nodes", + "datatype": "string" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1618235171399", + "component": "trigger", + "tab": "1615551125555", + "name": "tun tasks", + "x": 184, + "y": 279, + "connections": { + "0": [ + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "data": "run" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1618300858252", + "component": "debug", + "tab": "1612772287426", + "name": "wsmqtt-exit1", + "x": 597.8833312988281, + "y": 149, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1618393583970", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "to-cmd-manager", + "x": 668.8833312988281, + "y": 1269, + "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": 132.88333129882812, + "y": 367, + "connections": { + "0": [ + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "platform-rpc-call", + "color": "gray" + }, + "options": { + "wirename": "platform-rpc-call" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1618393759854", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "cmd_to_dido", + "x": 119.88333129882812, + "y": 1007, + "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": 752.8833312988281, + "y": 527, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "cmd_to_dido", + "color": "gray" + }, + "options": { + "wirename": "cmd_to_dido" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1618558465485", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "platform-rpc-call", + "x": 597.8833312988281, + "y": 247, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "platform-rpc-call", + "color": "gray" + }, + "options": { + "wirename": "platform-rpc-call" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1618572059773", + "component": "trigger", + "tab": "1615551125555", + "name": "turnOn line", + "x": 132, + "y": 1085, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "data": "{line: 1, command: \"turnOn\", force: true}", + "datatype": "object" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1619515097737", + "component": "cmd_manager", + "tab": "1615551125555", + "name": "CMD Manager", + "x": 452.1091003417969, + "y": 341.05455017089844, + "connections": { + "0": [ + { + "index": "0", + "id": "1615563373927" + } + ], + "1": [ + { + "index": "0", + "id": "1615566865233" + }, + { + "index": "0", + "id": "1615798582262" + } + ], + "2": [ + { + "index": "0", + "id": "1616165824813" + } + ], + "3": [ + { + "index": "0", + "id": "1618393827655" + } + ], + "4": [ + { + "index": "0", + "id": "1635936391935" + } + ], + "5": [ + { + "index": "0", + "id": "1757006030239" + }, + { + "index": "0", + "id": "1757006060377" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1619605019281", + "component": "httproute", + "tab": "1615551125555", + "name": "GET db", + "x": 173, + "y": 653, + "connections": { + "0": [ + { + "index": "0", + "id": "1684060205000" + }, + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Listening", + "color": "green" + }, + "options": { + "timeout": 5, + "cachepolicy": 0, + "cacheexpire": "5 minutes", + "size": 5, + "url": "/db", + "method": "GET", + "name": "", + "flags": [ + "id:1619605019281", + "get", + 5000 + ] + }, + "color": "#5D9CEC", + "notes": "### Configuration\n\n- __GET /db__\n- flags: undefined\n- maximum request data length: __5 kB__\n- empty response: __undefined__\n- cache policy: __no cache__\n- cache expire: __5 minutes__", + "cloning": false + }, + { + "id": "1619784672383", + "component": "trigger", + "tab": "1615551125555", + "name": "turnOnAlarm", + "x": 120, + "y": 1234, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "object", + "data": "{command: \"turnOnAlarm\"}" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1619784812964", + "component": "trigger", + "tab": "1615551125555", + "name": "turnOffAlarm", + "x": 118, + "y": 1307, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "object", + "data": "{command: \"turnOffAlarm\"}" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1621340721628", + "component": "virtualwireout", + "tab": "1611921777196", + "name": "modbus_to_dido", + "x": 599, + "y": 471, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "modbus_to_dido", + "color": "gray" + }, + "options": { + "wirename": "modbus_to_dido" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1622640022885", + "component": "httproute", + "tab": "1615551125555", + "name": "POST /db_connector", + "x": 98, + "y": 1586, + "connections": { + "0": [ + { + "index": "0", + "id": "1622640073521" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Listening", + "color": "green" + }, + "options": { + "timeout": 5, + "cachepolicy": 0, + "cacheexpire": "5 minutes", + "size": 5, + "url": "/db_connector", + "method": "POST", + "flags": [ + "id:1622640022885", + "post", + 5000 + ] + }, + "color": "#5D9CEC", + "notes": "### Configuration\n\n- __POST /db_connector__\n- flags: \n- maximum request data length: __5 kB__\n- empty response: __undefined__\n- cache policy: __no cache__\n- cache expire: __5 minutes__", + "cloning": false + }, + { + "id": "1622640073521", + "component": "db_connector", + "tab": "1615551125555", + "name": "DbConnector", + "x": 372, + "y": 1572, + "connections": { + "1": [ + { + "index": "0", + "id": "1622641420685" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "edge": "undefined" + }, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1622641420685", + "component": "httpresponse", + "tab": "1615551125555", + "name": "HTTP Response", + "x": 596, + "y": 1586, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1634303504177", + "component": "monitormemory", + "tab": "1612772287426", + "name": "RAM", + "x": 69.88333129882812, + "y": 888.5, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465281992" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "858.88 MB / 985.68 MB", + "color": "gray" + }, + "options": { + "enabled": true, + "interval": 30000 + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1634303533779", + "component": "monitordisk", + "tab": "1612772287426", + "name": "disk", + "x": 70.88333129882812, + "y": 982.5, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465821120" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "5.78 GB / 7.26 GB", + "color": "gray" + }, + "options": { + "enabled": true, + "path": "/", + "interval": 30000 + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1634303595494", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "send-to-services", + "x": 51.883331298828125, + "y": 1400.5, + "connections": { + "0": [ + { + "index": "0", + "id": "1634463186563" + }, + { + "index": "1", + "id": "1634488120710" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1634303602169", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "send-to-services", + "x": 426.8833312988281, + "y": 878.5, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1634303685503", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "send-to-services", + "x": 600.8833312988281, + "y": 341.5, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1634303743260", + "component": "httprequest", + "tab": "1612772287426", + "name": "192.168.252.2:8004/sentmessage", + "reference": "", + "x": 506.8833312988281, + "y": 1331.7333374023438, + "connections": { + "0": [ + { + "index": "0", + "id": "1635327431236" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "url": "http://192.168.252.2:8004/sentmessage", + "method": "POST", + "stringify": "json" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1634463186563", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 305.75, + "y": 1442, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634464580289", + "component": "code", + "tab": "1612772287426", + "name": "Code", + "x": 245, + "y": 787, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465243324" + }, + { + "index": "0", + "id": "1634303602169" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "keepmessage": true, + "code": "let response = {};\nresponse.cpu = value.cpu;\nresponse.uptime = value.uptime;\n\nsend(0, response);", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1634465243324", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 428, + "y": 784, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634465281992", + "component": "code", + "tab": "1612772287426", + "name": "Code", + "x": 245, + "y": 884, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465338103" + }, + { + "index": "0", + "id": "1634303602169" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "keepmessage": true, + "code": "value.sender = \"ram\";\n\nlet response = {};\n\nresponse.memory_total = Math.round(value.total / (1024 ** 2));\nresponse.memory_free = Math.round(value.free / (1024 ** 2));\nresponse.memory_used = Math.round(value.used / (1024 ** 2));\n\nsend(0, response);", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1634465338103", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 429, + "y": 976, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634465821120", + "component": "code", + "tab": "1612772287426", + "name": "Code", + "x": 245, + "y": 978, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465892500" + }, + { + "index": "0", + "id": "1634303602169" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "keepmessage": true, + "code": "value.sender = \"hdd\";\n\nlet response = {};\n\nresponse.hdd_total = Math.round(value.total / (1024 ** 2));\nresponse.hdd_free = Math.round(value.free / (1024 ** 2));\nresponse.hdd_used = Math.round(value.used / (1024 ** 2));\n\nsend(0, response);", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1634465892500", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 432, + "y": 1068, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634484067516", + "component": "debug", + "tab": "1612772287426", + "name": "Send info", + "x": 513, + "y": 1441, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634488120710", + "component": "infosender", + "tab": "1612772287426", + "name": "Info sender", + "x": 301, + "y": 1336, + "connections": { + "0": [ + { + "index": "0", + "id": "1634484067516" + }, + { + "index": "0", + "id": "1634303743260" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "edge": "undefined" + }, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1635327431236", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 837.8833312988281, + "y": 1325.5, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1635936391935", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "send-to-services", + "x": 753, + "y": 623, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1637069803394", + "component": "monitorconsumption", + "tab": "1612772287426", + "name": "CPU", + "x": 69, + "y": 791, + "connections": { + "0": [ + { + "index": "0", + "id": "1634464580289" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "49.2% / 69.91 MB", + "color": "gray" + }, + "options": { + "monitorfiles": true, + "monitorconnections": true, + "monitorsize": true, + "monitorconsumption": true, + "enabled": true, + "interval": 30000 + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1683664161036", + "component": "debug", + "tab": "1615551125555", + "name": "CMDtoDIDO", + "x": 392, + "y": 1012, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1683981346282", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "from-dido-controller", + "x": 112, + "y": 459, + "connections": { + "0": [ + { + "index": "0", + "id": "1684055037116" + }, + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "from-dido-controller", + "color": "gray" + }, + "options": { + "wirename": "from-dido-controller" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1684055037116", + "component": "debug", + "tab": "1615551125555", + "name": "from dido to cmd", + "x": 451, + "y": 532, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1684060205000", + "component": "debug", + "tab": "1615551125555", + "name": "HTTP routes", + "x": 450, + "y": 639, + "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": "MDBToDido", + "x": 598, + "y": 147, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1699963668903", + "component": "dido_controller", + "tab": "1615551125555", + "name": "DIDO_Controller", + "x": 397, + "y": 1131, + "connections": { + "0": [ + { + "index": "0", + "id": "1617104731852" + } + ], + "1": [ + { + "index": "0", + "id": "1617104731852" + }, + { + "index": "0", + "id": "1617115013095" + } + ], + "2": [ + { + "index": "0", + "id": "1618393583970" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "edge": "undefined" + }, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1699964678894", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "modbus_to_dido", + "x": 96, + "y": 924, + "connections": { + "0": [ + { + "index": "0", + "id": "1699963668903" + }, + { + "index": "0", + "id": "1699964793925" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "modbus_to_dido", + "color": "gray" + }, + "options": { + "wirename": "modbus_to_dido" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1699964793925", + "component": "debug", + "tab": "1615551125555", + "name": "modbusToDido", + "x": 388, + "y": 920, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1699965957410", + "component": "modbus_reader", + "tab": "1611921777196", + "name": "Modbus reader", + "x": 232, + "y": 175, + "connections": { + "0": [ + { + "index": "0", + "id": "1611951142547" + } + ], + "1": [ + { + "index": "0", + "id": "1621340721628" + }, + { + "index": "0", + "id": "1684179110403" + }, + { + "index": "0", + "id": "1717441414646" + } + ], + "2": [ + { + "index": "0", + "id": "1615809595184" + }, + { + "index": "0", + "id": "1714752862828" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1700411878636", + "component": "thermometer", + "tab": "1611921777196", + "name": "Thermometer", + "x": 234.75, + "y": 444, + "connections": { + "0": [ + { + "index": "0", + "id": "1615802995322" + } + ], + "1": [ + { + "index": "0", + "id": "1615809595184" + }, + { + "index": "0", + "id": "1615809128443" + } + ], + "2": [ + { + "index": "0", + "id": "1621340721628" + }, + { + "index": "0", + "id": "1732889185927" + }, + { + "index": "0", + "id": "1717441414646" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#5CB36D", + "notes": "" + }, + { + "id": "1714752862828", + "component": "debug", + "tab": "1611921777196", + "name": "MDBToTb", + "x": 766, + "y": 324, + "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": 764.0833282470703, + "y": 222, + "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\telse if(value.status === \"NOK-thermometer\")\n\t{\n\t\tsend(0, {\"thermometer\": \"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\telse if(value.values.hasOwnProperty(\"temperature\"))\n\t{\n\t\tsend(0, {\"thermometer\": \"OK\"});\n\t}\n}", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1717442627834", + "component": "debug", + "tab": "1611921777196", + "name": "modbus service", + "x": 966.0833282470703, + "y": 165, + "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": 968.0833282470703, + "y": 268, + "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": 88.75, + "y": 1685, + "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": 296, + "y": 1671, + "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\", \"Flow has been restarted\", \"Node db has changed\"]", + "types": "[\"emergency\", \"critical\", \"error\", \"alert\"]", + "name": "" + }, + "color": "#30E193", + "notes": "" + }, + { + "id": "1718016073501", + "component": "httprequest", + "tab": "1612772287426", + "name": "http://192.168.252.2:8004/slack", + "x": 495, + "y": 1753, + "connections": { + "0": [ + { + "index": "0", + "id": "1718016086212" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "url": "http://192.168.252.2:8004/slack", + "method": "POST", + "stringify": "json" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1718016086212", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 832, + "y": 1664, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "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": 87, + "y": 1591, + "connections": { + "0": [ + { + "index": "0", + "id": "1718016052341" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "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\": \"\" } } } ] }", + "datatype": "object" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1729855334955", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "platform-rpc-call", + "x": 599.9333343505859, + "y": 541.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "platform-rpc-call", + "color": "gray" + }, + "options": { + "wirename": "platform-rpc-call" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1729855371093", + "component": "debug", + "tab": "1612772287426", + "name": "rpc cloud", + "x": 601.9333343505859, + "y": 440.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1731068658334", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 75.75, + "y": 184, + "connections": { + "0": [ + { + "index": "0", + "id": "1612776786008" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731068754606", + "component": "cloudmqttconnect", + "tab": "1612772287426", + "name": "MQTT to senica-prod01", + "x": 284.75, + "y": 452, + "connections": { + "1": [ + { + "index": "0", + "id": "1729855371093" + }, + { + "index": "0", + "id": "1729855334955" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Connected", + "color": "green" + }, + "options": { + "username": "", + "clientid": "", + "port": "2764", + "host": "192.168.252.2", + "topic": "" + }, + "color": "#888600", + "notes": "" + }, + { + "id": "1731069001548", + "component": "db_init", + "tab": "1612772287426", + "name": "DB Initialization", + "x": 1003.75, + "y": 240.25, + "connections": { + "0": [ + { + "index": "0", + "id": "1731069033416" + } + ], + "1": [ + { + "index": "0", + "id": "1747561603739" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#888600", + "notes": "" + }, + { + "id": "1731069033416", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "db-init", + "x": 1244.75, + "y": 233.25, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069059135", + "component": "showdb", + "tab": "1612772287426", + "name": "Show db data", + "x": 1186.75, + "y": 821.25, + "connections": { + "0": [ + { + "index": "0", + "id": "1731069079243" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#888600", + "notes": "" + }, + { + "id": "1731069079243", + "component": "debug", + "tab": "1612772287426", + "name": "dbData", + "x": 1390.75, + "y": 870.25, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1731069116691", + "component": "trigger", + "tab": "1612772287426", + "name": "settings", + "x": 934.75, + "y": 669.75, + "connections": { + "0": [ + { + "index": "0", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069131637", + "component": "trigger", + "tab": "1612772287426", + "name": "relaysData", + "x": 876.75, + "y": 733.75, + "connections": { + "0": [ + { + "index": "1", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069137374", + "component": "trigger", + "tab": "1612772287426", + "name": "nodesData", + "x": 852.75, + "y": 794.75, + "connections": { + "0": [ + { + "index": "2", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069179846", + "component": "trigger", + "tab": "1612772287426", + "name": "pinsData", + "x": 850.75, + "y": 861.75, + "connections": { + "0": [ + { + "index": "3", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069192937", + "component": "trigger", + "tab": "1612772287426", + "name": "sample data", + "x": 857.75, + "y": 928.75, + "connections": { + "0": [ + { + "index": "4", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069264443", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 63.75, + "y": 1279, + "connections": { + "0": [ + { + "index": "0", + "id": "1634488120710" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069334626", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "db-init", + "x": 172.88333129882812, + "y": 129, + "connections": { + "0": [ + { + "index": "0", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069548145", + "component": "virtualwirein", + "tab": "1611921777196", + "name": "db-init", + "x": 46.75, + "y": 192, + "connections": { + "0": [ + { + "index": "0", + "id": "1699965957410" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069567152", + "component": "virtualwirein", + "tab": "1611921777196", + "name": "db-init", + "x": 44.75, + "y": 465, + "connections": { + "0": [ + { + "index": "0", + "id": "1700411878636" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731070156936", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "db-init", + "x": 126.88333129882812, + "y": 1377, + "connections": { + "0": [ + { + "index": "2", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731234189516", + "component": "trigger", + "tab": "1612772287426", + "name": "monitor.txt", + "x": 882.75, + "y": 991.75, + "connections": { + "0": [ + { + "index": "5", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731234189551", + "component": "trigger", + "tab": "1612772287426", + "name": "err.txt", + "x": 904.75, + "y": 1053.75, + "connections": { + "0": [ + { + "index": "6", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1732700042559", + "component": "nodesdb_change_check", + "tab": "1612772287426", + "name": "Nodes DB change check", + "x": 266.8833312988281, + "y": 1980.2333984375, + "connections": { + "0": [ + { + "index": "0", + "id": "1732700071298" + }, + { + "index": "0", + "id": "1732700642917" + } + ], + "1": [ + { + "index": "0", + "id": "1759958914348" + }, + { + "index": "0", + "id": "1759959003114" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#888600", + "notes": "" + }, + { + "id": "1732700057052", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 76.75, + "y": 1988, + "connections": { + "0": [ + { + "index": "0", + "id": "1732700042559" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1732700071298", + "component": "debug", + "tab": "1612772287426", + "name": "nodesChange", + "x": 571.8833312988281, + "y": 2018.2333984375, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1732700642917", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "tb-push", + "x": 567.8833312988281, + "y": 1933, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1732889185927", + "component": "debug", + "tab": "1611921777196", + "name": "tempToDido", + "x": 594.8833312988281, + "y": 753, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1733574412965", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 72.75, + "y": 474, + "connections": { + "0": [ + { + "index": "1", + "id": "1731068754606" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1747561603739", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "send-to-services", + "x": 1243.8833312988281, + "y": 334.5, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1747562867845", + "component": "comment", + "tab": "1612772287426", + "name": "FLOW STARTING POINT", + "x": 1003.5666656494141, + "y": 178, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#704cff", + "notes": "" + }, + { + "id": "1749211698385", + "component": "trigger", + "tab": "1612772287426", + "name": "deviceStatus", + "x": 911.75, + "y": 1116.75, + "connections": { + "0": [ + { + "index": "7", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1757006030239", + "component": "httprequest", + "tab": "1615551125555", + "name": "192.168.252.2:8015/daily_report", + "x": 756.5666656494141, + "y": 715.4499969482422, + "connections": { + "0": [ + { + "index": "0", + "id": "1757006045804" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "stringify": "json", + "method": "POST", + "url": "http://192.168.252.2:8015/daily_report" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1757006045804", + "component": "debug", + "tab": "1615551125555", + "name": "ddd", + "x": 1091.566665649414, + "y": 711.4499969482422, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1757006060377", + "component": "debug", + "tab": "1615551125555", + "name": "reportDebug", + "x": 749.5666656494141, + "y": 799.4499969482422, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1759958914348", + "component": "httprequest", + "tab": "1612772287426", + "name": "http://192.168.252.2:8015/node_numbers", + "x": 571, + "y": 2111, + "connections": { + "0": [ + { + "index": "0", + "id": "1759958927094" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "stringify": "json", + "method": "POST", + "url": "http://192.168.252.2:8015/node_numbers" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1759958927094", + "component": "debug", + "tab": "1612772287426", + "name": "nodesChangeCloud", + "x": 951.8833312988281, + "y": 2109.2333984375, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1759959003114", + "component": "debug", + "tab": "1612772287426", + "name": "nodeChangeCloud1", + "x": 574, + "y": 2218, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1760020290879", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 84.75, + "y": 1787, + "connections": { + "0": [ + { + "index": "1", + "id": "1718016052341" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + } + ], + "version": 615 +} diff --git a/RVO38/flow/dido_controller.js b/RVO38/flow/dido_controller.js new file mode 100755 index 0000000..d16fb19 --- /dev/null +++ b/RVO38/flow/dido_controller.js @@ -0,0 +1,1486 @@ +exports.id = 'dido_controller'; +exports.title = 'DIDO_Controller'; +exports.version = '2.0.0'; +exports.group = 'Worksys'; +exports.color = '#2134B0'; +exports.input = 3; +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 + +state_of_main_switch - reportovat stav hlaveho istica : 0-> off 1-> on +rotary_switch_state - sem by sa mal reportovat stav vstupov manual a auto pola nasledovnej logiky: Manual = 1 a Auto = 0 -> Manu +Manual = 0 a Auto = 0 -> Off, Manual = 0 a Auto = 1 -> Automatic + +door_condition - pin 6, dverový kontakt -> 1 -> vyreportuje Closed, 0 -> vyreportuje Ope +twilight_sensor - hodnotu, ktoru vracia ten analogovy vstup (17) treba poslat sem ako float number. Zrejme tu potom pridame nejaky koeficient prevodu na luxy + +Na kazdu liniu +state_of_breaker - podla indexu istica sa reportuje jeho stav, teda istic na liniu 1: 0-> off, 1-> on +state_of_contactor - podla indexu stkaca sa reportuje jeho stav, teda stykac 1 na liniu 1: 0-> off, 1-> on +*/ + +const { errLogger, logger, monitor } = require('./helper/logger'); +const SerialPort = require('serialport'); +const WebSocket = require('ws'); +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 errorHandler = require('./helper/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 hasMainSwitch; + +let alarmStatus = "OFF"; + +const SEND_TO = { + debug: 0, + tb: 1, + cmd_manager: 2 +} + + +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 = {}; + let rsPortReceivedData = []; + + //to be able to get proper twilight values + let twilight_sensor_interval = 5;//minutes + let twilight_sensor = []; + const twilight_sensor_array = []; + let twilightError = false; + + monitor.info("DIDO_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-we make it global to see it from outside + FLOW.deviceStatus = { //key is device name: temperature,.... + "state_of_main_switch": "Off", //Hlavny istic (alebo druhy dverovy kontakt) + "rotary_switch_state": "Off", //Prevadzkovy + "door_condition": "closed", //Dverový kontakt + "em": "OK", //elektromer rvo + "temperature": "OK", //templomer + "battery": "OK", //Bateria + "power_supply": "OK", //Zdroj + "master_node": "OK", //MN - GLOBALS.settings.masterNodeIsResponding + "no_voltage": "OK", //GLOBALS.settings.no_voltage - vypadok napatia na faze + "state_of_breaker": {}, //"Off",//Istic + "state_of_contactor": {}, //"Off",//Stykac + "twilight_sensor": "OK" //lux sensor + }; + let deviceStatus = FLOW.deviceStatus; + + + function main() { + + GLOBALS = FLOW.GLOBALS; + SETTINGS = FLOW.GLOBALS.settings; + rvoTbName = SETTINGS.rvoTbName; + pinsData = GLOBALS.pinsData; + relaysData = GLOBALS.relaysData; + + tbHandler = new DataToTbHandler(SEND_TO.tb); + tbHandler.setSender(exports.title); + + controller_type = SETTINGS.controller_type; //"lm" or "unipi" + hasMainSwitch = SETTINGS.has_main_switch; + + if (controller_type == "") controller_type = "lm"; + + 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, "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; + } + } + + //report RVO version relaysData[0].tbname; + let values = {}; + values["edge_fw_version"] = SETTINGS.edge_fw_version; + values["maintenance_mode"] = SETTINGS.maintenance_mode; + + sendTelemetry(values, rvoTbName); + + 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); + } + + + function handleRsPort() { + + if (rsPort) { + rsPort.removeAllListeners(); + rsPort = null; + } + + //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('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) { + if (!err) { + monitor.info(exports.title + "--->Digital in_out has been set (runSyncExec was sucessfull)"); + + turnAlarm("off"); + 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('error', err => { + let message = "Dido: rsPort error: " + err.message; + logger.debug(message); + monitor.info(message); + errorHandler.sendMessageToService(message); + }) + + rsPort.on("close", () => { + let message = "Dido: rsPort closed - reconnecting ..."; + logger.debug(message); + monitor.info(message); + setTimeout(handleRsPort, 1000); + }) + + rsPort.open(); + } + + + function handleWebSocket() { + + if (ws) { + ws.removeAllListeners(); + ws = null; + } + + //to keep websocket opened, we send request every 150 seconds + let startRequests = null; + + console.log("handleWebSocket function called"); + ws = new WebSocket('ws:/0.0.0.0:1234/ws'); + + ws.onopen = function open() { + + instance.send(0, exports.title + " running"); + turnAlarm("off"); + + initialSetting(); + + setTimeout(function() { ws.send(JSON.stringify({ cmd: "all" })) }, 5000); + // we request dev info about neuron device from evok to keep websocket connection alive + // for some reason this request returns no data, but connection keeps alive + startRequests = setInterval(() => { + ws.send(JSON.stringify({ "cmd": "filter", "dev": ["neuron"] })); + }, 150000) + }; + + + // 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 = async 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; + + 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 => { + logger.debug('Dido: websocket error', err); + }) + + ws.onclose = function() { + logger.debug('Dido: websocket onclose, reconnecting...') + clearInterval(startRequests); + setTimeout(handleWebSocket, 1000); + } + } + + 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 turnAlarm(onOrOff) { + let value = 0; + if (onOrOff == "on") value = 1; + + if (value == 1 && SETTINGS.maintenance_mode) return; + + alarmStatus = "OFF"; + if (value == 1) alarmStatus = "ON"; + + if (rsPort) { + let arr = [0x55]; + arr.push(13); + arr.push(0); + arr.push(value); + + rsPort.write(Buffer.from(arr), function(err) { + logger.debug(`sirena - ${onOrOff}`); + }); + } + else if (ws) { + let cmd = { "cmd": "set", "dev": "relay", "circuit": "1_01", "value": value }; + ws.send(JSON.stringify(cmd)); + logger.debug(`sirena - ${onOrOff}`); + } + } + + + 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") { + bits.push(0); + } + else bits.push(1); + + if (deviceStatus["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); + } + + + // turn line on or off + function turnLine(onOrOff, line, pin, force, info) { + //onOrOff => "on" or "off" + let value = 0; + if (onOrOff == "on") value = 1; + + if (force == undefined) force = false; + + if (line == 0) { + if (value == 1 && alarmStatus == "ON") turnAlarm("off"); + SETTINGS.maintenance_mode = value ? true : false; + + 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); + return; + } + + if (pin === undefined) pin = getPin(line); + + if (pin === undefined) { + errLogger.error("pin is undefined!", line); + return; + } + + if (!force) { + if (relaysData[line].contactor == value) { + instance.send(SEND_TO.debug, `line is already ${onOrOff} ` + line); + logger.debug(`Dido: turnLine: line is already ${onOrOff} `, line); + return; + } + } + + // if(!rsPort.isOpen && !ws) + if (!rsPort && !ws) { + errLogger.error("Dido - port or websocket is not opened"); + return; + } + + if (rsPort) { + let arr = [0x55]; + arr.push(pin); + arr.push(0); + arr.push(value); + + rsPort.write(Buffer.from(arr), function(err) { + if (err === undefined) { + monitor.info(`Dido: turnLine ${onOrOff} zapisal do rsPort-u`, line, pin, arr, info); + switchLogic(arr); + } + else { + monitor.info(`Dido: turnLine ${onOrOff} WRITE error`, err); + } + }); + + } + else if (ws) { + //pin = "relay1_03" or "input1_01" ... we must make just "1_01" with slice method + monitor.info(`Dido: turnLine ${onOrOff} - (line, pin, force)`, line, pin, force, info); + let cmd = { "cmd": "set", "dev": "relay", "circuit": pin.slice(5), "value": value }; + ws.send(JSON.stringify(cmd)); + } + + //if rvo is 24/7, it has just one switching profile point at 13:00. we do not want to send notification as it repeats every day. + //const d = new Date(); + //if(d.getHours() != 13) sendNotification("Dido_controller: ", SETTINGS.rvoTbName, "switching_profile_point_applied_to_line", { line: line, value: onOrOff }, "", SEND_TO.tb, instance); + } + + + // 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; + + // 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) { + const status = flowdata.data.status; + if (status == "NOK-twilight_sensor") { + deviceStatus["twilight_sensor"] = "NOK"; + } + else if (status == "NOK-em340" || status == "NOK-em111") { + deviceStatus["em"] = "NOK"; + } + else if (status == "NOK-thermometer") { + deviceStatus["temperature"] = "NOK"; + } + } + else if ("values" in flowdata.data) { + 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" + } + else if (values.hasOwnProperty("temperature")) { + deviceStatus["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"; + } + + sendTelemetry(values, rvoTbName); + } + + sendRvoStatus(); + }) + + + + + // we expect array as flowdata.data + instance.on("1", flowdata => { + + //console.log(flowdata.data); + + if (!flowdata.data instanceof Object) return; + + let obj = flowdata.data; + let line = obj.line; + 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"); + }) + + + function calculateStateCode() { + + let bits = []; + + //Hlavny istic - state_of_main_switch => v rvo senica je to druhy door pre silovu cast (EM) + if (deviceStatus["state_of_main_switch"] === "closed" || deviceStatus["state_of_main_switch"] === "Off") { + bits.push(0); + } + else { + bits.push(1); + } + + //Prevadzkovy mod - Manual, Off, Automatic, maintenance_mode = true/false // DAVA 2 BITY + if (!SETTINGS.maintenance_mode) { + if (deviceStatus["rotary_switch_state"] === "Manual") { + bits.push(0); + bits.push(1); + } + + if (deviceStatus["rotary_switch_state"] === "Automatic") { + bits.push(0); + bits.push(0); + } + + if (deviceStatus["rotary_switch_state"] === "Off") { + bits.push(1); + bits.push(0); + } + } + else { + bits.push(1); + bits.push(1); + } + + //Dverovy kontakt + if (deviceStatus["door_condition"] === "closed") { + bits.push(0); + } + else { + bits.push(1); + } + + //EM + if (deviceStatus["em"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //Teplomer + if (deviceStatus["temperature"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //Batéria + if (deviceStatus["battery"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //Zdroj + if (deviceStatus["power_supply"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //MN + if (deviceStatus["master_node"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //výpadok napätia na fáze + if (deviceStatus["no_voltage"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + if (deviceStatus["twilight_sensor"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + // doplnime do 16 bitov (2 byty) + for (let i = bits.length; i < 16; i++) { + bits.push(0); + } + + // console.log("calculateStateCode - deviceStatus", deviceStatus); + // 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; + } + + + async function sendRvoStatus() { + + if (SETTINGS === undefined) return; + SETTINGS.masterNodeIsResponding ? deviceStatus["master_node"] = "OK" : deviceStatus["master_node"] = "NOK"; + + 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 pinsForRvoStatus(controllerType, hasMainSwitch) { + + let pins = []; + + if (controllerType === "lm") { + pins = [1, 4, 6]; + if (hasMainSwitch === 1) { + pins = [4, 6]; + } + } else if (controllerType === "unipi") { + pins = ["input1_01", "input1_04", "input1_05"]; + if (hasMainSwitch === 1) { + pins = ["input1_01", "input1_04"]; + } + } + + return pins; + } + + + function checkRvoStatus() { + + // 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 + //set RVO state + let status = "OK"; + + for (const [key, value] of Object.entries(deviceStatus)) { + if (["em", "twilight_sensor", "temperature", "master_node"].includes(key) && value === "NOK") status = "NOK"; + } + + if (status === "OK") { + + let pinIndexes = pinsForRvoStatus(controller_type, hasMainSwitch); + + for (const pinIndex of pinIndexes) { + if (previousValues[pinIndex] === 0) { + if ((pinIndex === 6 || pinIndex === 'input1_01' || pinIndex === 'input1_05') && SETTINGS.maintenance_mode) continue; + status = "NOK"; + break; + } + } + } + + // battery status. If value is 1 - battery is NOK + if (previousValues[5] === 1) status = "NOK"; + if (SETTINGS.no_voltage.size > 0) status = "NOK"; + + // console.log("rvo status",status) + return status; + } + + + // we pass array to function in case of rsPort ==> switchLogic([55,3,0,1]) ==> [[55,3,0,1]] + // we pass two values in case of websocket ==> switchLogic("relay1_03",1) ==> ["relay1_03",1] + const switchLogic = (...args) => { + + let values = {}; + let pinIndex, newPinValue, twilight; + + //data from rsPort + if (args.length == 1) { + pinIndex = args[0][1] + 1; + if (pinIndex === 17) pinIndex--; + newPinValue = args[0][3]; + twilight = args[0][2]; + } + //data from websocket + else { + pinIndex = args[0]; + newPinValue = args[1]; + } + + 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; + + //default value + let value = "On"; + if (newPinValue === 0) value = "Off"; + + //Hlavny istic + if (type === "state_of_main_switch" && hasMainSwitch) { + if (newPinValue === 0 && newPinValue !== previousValues[pinIndex]) { + sendNotification("switchLogic", rvoTbName, "main_switch_has_been_turned_off", {}, "", SEND_TO.tb, instance, "state_of_main_switch"); + 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"); + deviceStatus["state_of_main_switch"] = "On"; + } + } + + //Prevadzkovy mod + 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"; + + deviceStatus["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, "power_supply_has_disconnected_input", {}, "", SEND_TO.tb, instance, "power_supply"); + + deviceStatus["power_supply"] = "NOK"; + } + else if (newPinValue === 1 && newPinValue !== previousValues[pinIndex]) { + sendNotification("switchLogic", rvoTbName, "power_supply_works_correctly", {}, "", SEND_TO.tb, instance, "power_supply"); + + deviceStatus["power_supply"] = "OK"; + } + } + + //Bateria - 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"); + + deviceStatus["battery"] = "NOK"; + } + else if (newPinValue === 0 && newPinValue !== previousValues[pinIndex]) { + sendNotification("switchLogic", rvoTbName, "battery_level_is_ok", {}, "", SEND_TO.tb, instance, "battery_level"); + + deviceStatus["battery"] = "OK"; + } + } + + //Dverovy kontakt - pin 6 + //! Ak je rvo s dvoma dverovymi kontaktami, ked pride z evoku signal z input1_05, co bol predytm "state_of_main switch" handlujeme ho teraz ako 'door_condition' + else if (type == "door_condition" || type === "state_of_main_switch") { + newPinValue === 0 ? value = "open" : value = "closed"; + + let door = "door_main"; + if (type === "state_of_main_switch") door = "door_em"; + + if (value === "open") { + if (SETTINGS.maintenance_mode) { + sendNotification("switchLogic", rvoTbName, door + "_open", {}, "", SEND_TO.tb, instance, door); + } else { + sendNotification("switchLogic", rvoTbName, door + "_open_without_permission", {}, "", SEND_TO.tb, instance, door); + + // 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 (value === "closed") { + if (alarmStatus == "ON") turnAlarm("off"); + sendNotification("switchLogic", rvoTbName, door + "_close", {}, "", SEND_TO.tb, instance, door); + } + + deviceStatus[type] = value; + } + + //lux sensor + else if (type == "twilight_sensor") { + //! TODO - to show nok status, if lux value is not changing more then 10 times. + //Daylight is far more than 1000. So most of the day, when it is sunshine comes just value 1000. But lux sensor is not NOK. + //This is not the case in LM. If value from LM is the same 10x, there is 99% possibility, that sensor is NOK. + value = newPinValue; + + if (controller_type === 'lm') { + value = parseFloat(newPinValue + (256 * twilight)); + + 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 && !twilightError) { + twilightError = true; + let value = twilight_sensor_array.shift(); + + newPinValue = 0; + } + else if (set.size !== 1 && twilightError) { + //sendNotification("switchLogic", rvoTbName, 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) { + 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); + } + } + + 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); + } + + deviceStatus["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 (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 }); + + //mame iba 3 istice. vyreportujeme a ohandlujeme liniu na tom istom istici ako paralelna linia (napr linia 1, paralelna s nou je linia 4, key je string "4") + // ak je 7 linii, na 1 istici je linia 1,4,7 + + if (line == 1) { + + const lineOnSameBraker = [4, 7]; + + for (var i = 0; i < lineOnSameBraker.length; i++) { + if (!relaysData.hasOwnProperty(lineOnSameBraker[i])) continue; + + 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; + reportLineStatus(lineOnSameBraker[i]); + + values[type] = value; + const tbname = relaysData[lineOnSameBraker[i]].tbname; + sendTelemetry(values, tbname); + + delete values[type]; + } + + } + else { + const lineOnSameBraker = line + 3 + ""; + + if (relaysData.hasOwnProperty(lineOnSameBraker)) { + 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; + reportLineStatus(line + 3); + + values[type] = value; + const tbname = relaysData[lineOnSameBraker].tbname; + sendTelemetry(values, tbname); + + delete values[type]; + } + } + + } + + if (value == "Off") values["status"] = "NOK"; + deviceStatus["state_of_breaker"][line] = value; + + reportLineStatus(line); + } + else return; + + values[type] = value; + + if (type == "rotary_switch_state") { + if (SETTINGS.maintenance_mode) value = "maintenance"; + value = value.toLowerCase(); + values["power_mode"] = value; + } + + if (newPinValue != previousValues[pinIndex]) previousValues[pinIndex] = newPinValue; + if (Object.keys(values).length > 0 && tbname) sendTelemetry(values, tbname); + } + + + function sendTelemetry(values, tbname, date = Date.now()) { + let dataToTb = { + [tbname]: [ + { + "ts": date, + "values": values + } + ] + }; + + tbHandler.sendToTb(dataToTb, instance); + } + + + function isObject(item) { + return (typeof item === "object" && !Array.isArray(item) && item !== null); + } + +} //end of 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 +// *|input1_01|state_of_main_switch|0|........... +// *|input1_02|rotary_switch_state|0|........... +// *|input1_03|rotary_switch_state|0|........... +// *|intut1_04|power_supply|0|........... +// *|input1_05|door_condition|0|........... +// *|input1_06|state_of_breaker|1|........... +// *|input1_07|state_of_breaker|2|........... +// *|input1_08|state_of_breaker|3|........... +// *|relay1_02|state_of_contactor|1|........... +// *|relay1_03|state_of_contactor|2|........... +// *|relay1_04|state_of_contactor|3|........... +// *|287D8776E0013CE9|temperature|0|........... + + +//! pins_data --> from UNIPI +// { +// 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 } +// } + +//! relays_data +// { +// '0': { +// line: 0, +// tbname: 'KjbN4q7JPZmexgdnz2yKQ98YAWwO0Q3BMX6ERLoV', +// contactor: 1, +// profile: '' +// }, +// '1': { +// line: 1, +// tbname: 'RMgnK93rkoAazbqdQ4yBG95Z1YXGx6pmwBeVEP2O', +// contactor: 0, +// profile: '{"intervals":[{"value":0,"end_time":"20:00","start_time":"13:00"},{"value":1,"end_time":"10:00","start_time":"20:00"},{"value":0,"end_time":"10:20","start_time":"10:00"},{"value":1,"end_time":"10:40","start_time":"10:20"},{"value":0,"end_time":"11:00","start_time":"10:40"},{"value":1,"end_time":"11:30","start_time":"11:00"},{"value":0,"end_time":"11:50","start_time":"11:30"},{"value":1,"end_time":"13:00","start_time":"11:50"}],"astro_clock":false,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' +// }, +// '2': { +// line: 2, +// tbname: 'dlE1VQjYrNx9gZRmb38gG08oLBO4qaAk2M6JPnG7', +// contactor: 0, +// profile: '{"intervals":[{"value":0,"end_time":"20:00","start_time":"13:00"},{"value":1,"end_time":"10:00","start_time":"20:00"},{"value":0,"end_time":"10:20","start_time":"10:00"},{"value":1,"end_time":"10:40","start_time":"10:20"},{"value":0,"end_time":"11:00","start_time":"10:40"},{"value":1,"end_time":"11:30","start_time":"11:00"},{"value":0,"end_time":"11:50","start_time":"11:30"},{"value":1,"end_time":"13:00","start_time":"11:50"}],"astro_clock":false,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' +// }, +// '3': { +// line: 3, +// tbname: 'vnmG4kJxaXWNBgMQq0D7Aj5e9oZzOAlr6LdR3w2V', +// contactor: 0, +// profile: '{"intervals":[{"value":0,"end_time":"20:30","start_time":"13:00"},{"value":1,"end_time":"00:10","start_time":"20:30"},{"value":0,"end_time":"13:00","start_time":"05:40"},{"value":1,"end_time":"05:40","start_time":"00:10"}],"astro_clock":true,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' +// } +// } + + + + + +// { +// "jbN4q7JPZmexgdnz2yKbWGDYAWwO0Q3BMX6ERLoV": [ +// { +// "ts": 1700409326353, +// "values": { +// "_event": { +// "type": "notice", +// "status": "new", +// "source": { +// "func": "rsPort.open()", +// "component": "1700343402190", +// "component_name": "DIDO_Controller", +// "edge": "jbN4q7JPZmexgdnz2yKbWGDYAWwO0Q3BMX6ERLoV" +// }, +// "message": "al_shariff_10.0.0.38: FLOW has been started ", +// "message_data": "" +// } +// } +// } +// ] +// } diff --git a/RVO38/flow/helper/DataToTbHandler.js b/RVO38/flow/helper/DataToTbHandler.js new file mode 100755 index 0000000..716ef7b --- /dev/null +++ b/RVO38/flow/helper/DataToTbHandler.js @@ -0,0 +1,187 @@ +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; + this.itIsNodeReadout = false; + this.sender = ""; + + // if attribute change difference is less than limit value, we do not send to tb. + this.attributeChangeLimit = { + temperature: 0.5, + Phase_1_voltage: 2, + Phase_2_voltage: 2, + Phase_3_voltage: 2, + Phase_1_current: 0.1, + Phase_2_current: 0.1, + Phase_3_current: 0.1, + Phase_1_power: 2, + Phase_2_power: 2, + Phase_3_power: 2, + total_power: 2, + total_energy: 1, + Phase_1_pow_factor: 0.1, + Phase_2_pow_factor: 0.1, + Phase_3_pow_factor: 0.1, + power_factor: 0.1, + lifetime: 2, + voltage: 2, + power: 2, + frequency: 3, + energy: 0.1, + current: 2, + inclination_x: 10, + inclination_y: 10, + inclination_z: 10 + }; + + } + + dump() { + console.log("----------------------------"); + console.log("previousValues", this.previousValues); + console.log("----------------------------"); + } + + setSender(sender) { + this.sender = sender; + } + + isEmptyObject(obj) { + for (var _ in obj) { + return false; + } + return true; + } + + + sendToTb(data, instance) { + + //not to modify data object, we do deep copy: + let dataCopy = JSON.parse(JSON.stringify(data)); + + let keys = Object.keys(dataCopy); + + if (keys.length == 0) { + if (this.debug) console.log("sendToTb received empty object", dataCopy); + return; + } + + let tbname = keys[0]; + let ts; + + let arrayOfValues = dataCopy[tbname]; + let arrayOfValuesToSend = []; + + for (let i = 0; i < arrayOfValues.length; i++) { + + ts = arrayOfValues[i].ts; + let values = this.prepareValuesForTb(tbname, ts, arrayOfValues[i].values); + + if (!this.isEmptyObject(values)) { + arrayOfValuesToSend.push({ ts: ts, values: values }); + } + + } + + if (arrayOfValuesToSend.length == 0) { + //if(this.debug) console.log("data not sent - empty array"); + return; + } + + this.messageCounter++; + + let dataToTbModified = { + [tbname]: arrayOfValuesToSend + } + + //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); + instance.send(this.index, dataToTbModified); + } + + + getDiffTimestamp(key) { + //TODO set different value for given key!!! + //if(key == "status") this.timeToHoldTbValue = 2*60*60;//2h + return this.timeToHoldTbValue * 1000; + } + + + prepareValuesForTb(tbname, timestamp, values) { + + let keys = Object.keys(values); + + if (keys.includes("lifetime")) this.itIsNodeReadout = true; + + if (!this.previousValues.hasOwnProperty(tbname)) { + this.previousValues[tbname] = {}; + } + + //if(this.debug) console.log("prepareValuesForTb", tbname, timestamp, values); + + for (let i = 0; i < keys.length; i++) { + + let key = keys[i]; + let value = values[key]; + + if (!this.previousValues[tbname].hasOwnProperty(key)) { + this.previousValues[tbname][key] = { ts: timestamp, value: value }; + continue; + } + + // attributeData ==> {voltage: {ts:333333, value:5}} + let attributeData = this.previousValues[tbname][key]; + let attributeToChange = false; + if (key in this.attributeChangeLimit) attributeToChange = true; + let limit = this.attributeChangeLimit[key]; + let timestampDiffToRemoveKey; + + //this will ensure "node statecode" will be sent just once an hour + if (this.itIsNodeReadout && key === "statecode") { + attributeData.value = value; + this.itIsNodeReadout = false; + timestampDiffToRemoveKey = 1 * 60 * 60 * 1000; // 1 hour + } + + if (key === "twilight_sensor" && value > 100) { + attributeData.value = value; + } + + //if edge, master or node version do not change, send just once a day: + if (["edge_fw_version", "master_node_version", "fw_version"].includes(key)) { + timestampDiffToRemoveKey = 24 * 60 * 60 * 1000; + } + + if (attributeData.value === value || attributeToChange && Math.abs(attributeData.value - value) < limit) { + + let diff = timestamp - attributeData.ts; + if (!timestampDiffToRemoveKey) timestampDiffToRemoveKey = this.getDiffTimestamp(key); + + if (diff > timestampDiffToRemoveKey) { + attributeData.ts = Date.now(); + //if(this.debug) console.log(this.sender + ": update ts for key", key, "diff is", diff, "messageCounter", this.messageCounter); + } + else { + delete values[key]; + //if(this.debug) console.log(this.sender + ": delete key", key, "diff is", diff, "messageCounter", this.messageCounter, timestampDiffToRemoveKey); + } + } + else { + attributeData.value = value; + attributeData.ts = timestamp; + } + + } + + return values; + } +} + +module.exports = DataToTbHandler; + diff --git a/RVO38/flow/helper/ErrorToServiceHandler.js b/RVO38/flow/helper/ErrorToServiceHandler.js new file mode 100755 index 0000000..2b27c32 --- /dev/null +++ b/RVO38/flow/helper/ErrorToServiceHandler.js @@ -0,0 +1,91 @@ +const { MD5 } = require('./md5.js'); +const { networkInterfaces } = require('os'); + +class ErrorToServiceHandler { + constructor() { + this.previousValues = {}; + + this.project_id = undefined; + + const nets = networkInterfaces(); + this.ipAddresses = {}; + + for (const name of Object.keys(nets)) { + for (const net of nets[name]) { + // Skip over non-IPv4 and internal (i.e. 127.0.0.1) addresses + if (net.family === 'IPv4' && !net.internal) { + if (!this.ipAddresses[name]) { + this.ipAddresses[name] = []; + } + this.ipAddresses[name].push(net.address); + } + } + } + } + + setProjectId(project_id) { + this.project_id = project_id; + } + + processMessage(message, seconds) { + if (Array.isArray(message)) message = message.join(', '); + + let key = MD5(message); + let ts = Date.now(); + + //keep in memory - default value is 1h + if (seconds === undefined) seconds = 60 * 60; + + if (!this.previousValues.hasOwnProperty(key)) { + this.previousValues[key] = { ts: ts, duration: seconds }; + } + + let diff = (ts - this.previousValues[key].ts); + if (diff < this.previousValues[key].duration * 1000) return false; + + this.previousValues[key].ts = ts; + + return message; + } + + sendMessageToService(message, seconds, message_type) { + + // if error occures too early FLOW.GLOBALS.settings.project_id is still undefined + if (this.project_id === undefined) { + console.log("ErrorToServiceHandler.js: no project_id"); + return; + } + + let f = this.processMessage(message, seconds); + if (f === false) return; + + if (message_type === undefined) message_type = "error_message"; + + let toService = { + id: this.project_id, + ipAddresses: this.ipAddresses + }; + + //js_error || error_message + toService[message_type] = message; + + console.log("ErrorToServiceHandler------------------------>send to service", toService); + + RESTBuilder.make(function(builder) { + builder.method('POST'); + builder.post(toService); + builder.url('http://192.168.252.2:8004/sentmessage'); + + builder.callback(function(err, response, output) { + console.log("process.on error send", err, response, output, toService); + }); + }); + + } +} + +const errorHandler = new ErrorToServiceHandler(); + + +module.exports = errorHandler; +//module.exports = ErrorToServiceHandler; diff --git a/RVO38/flow/helper/db_helper.js b/RVO38/flow/helper/db_helper.js new file mode 100755 index 0000000..40e796c --- /dev/null +++ b/RVO38/flow/helper/db_helper.js @@ -0,0 +1,44 @@ +function promisifyBuilder(builder) +{ + return new Promise((resolve, reject) => { + + try{ + + builder.callback(function(err, response) { + + if(err != null) reject(err); + resolve(response); + }); + + } catch (error) { + reject(error); + } + }) +} + +function makeMapFromDbResult(response, ...keys) +{ + let s = "-"; + let data = {}; + + for(let i = 0; i < response.length; i++) + { + let record = response[i]; + + let k = []; + for(let j = 0; j < keys.length; j++) + { + k.push( record[keys[j]] ); + } + + let key = k.join(s); + data[ key ] = record; + } + + return data; +} + +module.exports = { + promisifyBuilder, + makeMapFromDbResult + } \ No newline at end of file diff --git a/RVO38/flow/helper/logger.js b/RVO38/flow/helper/logger.js new file mode 100755 index 0000000..2585639 --- /dev/null +++ b/RVO38/flow/helper/logger.js @@ -0,0 +1,30 @@ +//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/RVO38/flow/helper/md5.js b/RVO38/flow/helper/md5.js new file mode 100755 index 0000000..d3b0480 --- /dev/null +++ b/RVO38/flow/helper/md5.js @@ -0,0 +1,5 @@ +function MD5(d){var r = M(V(Y(X(d),8*d.length)));return r.toLowerCase()};function M(d){for(var _,m="0123456789ABCDEF",f="",r=0;r>>4&15)+m.charAt(15&_);return f}function X(d){for(var _=Array(d.length>>2),m=0;m<_.length;m++)_[m]=0;for(m=0;m<8*d.length;m+=8)_[m>>5]|=(255&d.charCodeAt(m/8))<>5]>>>m%32&255);return _}function Y(d,_){d[_>>5]|=128<<_%32,d[14+(_+64>>>9<<4)]=_;for(var m=1732584193,f=-271733879,r=-1732584194,i=271733878,n=0;n>16)+(_>>16)+(m>>16)<<16|65535&m}function bit_rol(d,_){return d<<_|d>>>32-_} + +module.exports = { + MD5 +} \ No newline at end of file diff --git a/RVO38/flow/helper/notification_reporter.js b/RVO38/flow/helper/notification_reporter.js new file mode 100755 index 0000000..839c12c --- /dev/null +++ b/RVO38/flow/helper/notification_reporter.js @@ -0,0 +1,121 @@ +//key is device, value = message {} +let sentValues = {}; +let notificationsData = null; +let rvoName; + +//sendNotification("CMD Manager: process cmd", SETTINGS.rvoTbName, "dimming_profile_was_successfully_received_by_node", { node: node }, "", SEND_TO.tb, instance); + +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 +}; + +function getKey(map, val) { + return Object.keys(map).findItem(key => map[key] === val); +} + +//https://stackoverflow.com/questions/41117799/string-interpolation-on-variable +var template = (tpl, args) => tpl.replace(/\${(\w+)}/g, (_, v) => args[v]); + + +function initNotification() { + notificationsData = FLOW.GLOBALS.notificationsData; + rvoName = FLOW.GLOBALS.settings.rvo_name; +} + + +function sendNotification(func, device, key, params, extra, tb_output, instance, saveKey) { + + let storeToSendValues = true; + if (saveKey == undefined) storeToSendValues = false; + + let weight = ""; + let message = {}; + + let notification = notificationsData[key]; + + if (notification) { + weight = notification.weight.toLowerCase(); + + Object.keys(notification).forEach(item => { + if (["en", "sk", "de", "cz", "it", "es"].includes(item)) { + message[item] = rvoName + ": " + template(notification[item], params); + } + }) + } + else { + //console.error("sendNotification: Notifications: undefined key", key, func, notificationsData); + console.error("sendNotification: Notifications: undefined key", key, func); + return false; + } + + //detect invalid err weight + if (getKey(ERRWEIGHT, weight) == undefined) { + console.error("sendNotification: Notifications: undefined weight", weight, key, func); + return false; + } + + if (sentValues.hasOwnProperty(saveKey)) { + if (JSON.stringify(sentValues[saveKey]) == JSON.stringify(message)) { + return false; + } + } + + if (sentValues[saveKey] == undefined) { + if (storeToSendValues) { + //do not send - flow is was started + sentValues[saveKey] = message; + return false; + } + } + + if (storeToSendValues) sentValues[saveKey] = message; + + let content = { + "type": weight, + "status": "new", + "source": { + "func": func, + "component": instance.id, + "component_name": instance.name, + "edge": device + }, + "message": message, + "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 + + return true; + +} + +module.exports = { + sendNotification, + ERRWEIGHT, + initNotification +} + diff --git a/RVO38/flow/helper/register.js b/RVO38/flow/helper/register.js new file mode 100755 index 0000000..fc1d008 --- /dev/null +++ b/RVO38/flow/helper/register.js @@ -0,0 +1,144 @@ +/* +0 - cislo registra / prikaz +1 - recepient - 0 = master, 1 = slave (slave je automaticky group a broadcast) +2 - r/rw - read/write +3- register name - nazov registra / prikazu (len pre info - zobrazenie v aplikacii) + +4,5,6,7, - jednotlive byte-y - nazov byte-u +4-7 - RES. a prazdny string "" sa nezobrazia!!! +*/ + +//124 zaznamov +const registers = [ + ["0","1","R","Status","","",""], + ["1","1","RW","Dimming","R-Channel ","G-Channel","B-Channel ","W - Channel"], + ["2","1","R","Device types","","",".",""], + ["3","1","RW","Group addresses 1-4","Groups Add. 4","Groups Add. 3","Groups Add. 2","Groups Add. 1"], + ["4","1","RW","Group addresses 5-8","Groups Add. 8","Groups Add. 7","Groups Add. 6","Groups Add. 5"], + ["5","1","RW","Serial number (MAC)","","","",""], + ["6","1","RW","Time of dusk","HH","MM","SS","EXTRA"], + ["7","1","RW","Time of dawn","HH","MM","SS","EXTRA"], + ["8","1","RW","Time Schedule settings","TBD","TBD","Movement sensor","Time Schedule"], + ["9","1","RW","TS1 Time point 1","HH","MM","SS","Ext. Device"], + ["10","1","RW","TS1 Time point 1 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["11","1","RW","TS1 Time point 2","HH","MM","SS","Ext. Device"], + ["12","1","RW","TS1 Time point 2 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["13","1","RW","TS1 Time point 3","HH","MM","SS","Ext. Device"], + ["14","1","RW","TS1 Time point 3 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["15","1","RW","TS1 Time point 4","HH","MM","SS","Ext. Device"], + ["16","1","RW","TS1 Time point 4 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["17","1","RW","TS1 Time point 5","HH","MM","SS","Ext. Device"], + ["18","1","RW","TS1 Time point 5 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["19","1","RW","TS1 Time point 6","HH","MM","SS","Ext. Device"], + ["20","1","RW","TS1 Time point 6 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["21","1","RW","TS1 Time point 7","HH","MM","SS","Ext. Device"], + ["22","1","RW","TS1 Time point 7 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["23","1","RW","TS1 Time point 8","HH","MM","SS","Ext. Device"], + ["24","1","RW","TS1 Time point 8 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["25","1","RW","TS1 Time point 9","HH","MM","SS","Ext. Device"], + ["26","1","RW","TS1 Time point 9 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["27","1","RW","TS1 Time point 10","HH","MM","SS","Ext. Device"], + ["28","1","RW","TS1 Time point 10 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["29","1","RW","TS1 Time point 11","HH","MM","SS","Ext. Device"], + ["30","1","RW","TS1 Time point 11 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["31","1","RW","TS1 Time point 12","HH","MM","SS","Ext. Device"], + ["32","1","RW","TS1 Time point 12 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["33","1","RW","TS1 Time point 13","HH","MM","SS","Ext. Device"], + ["34","1","RW","TS1 Time point 13 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["35","1","RW","TS1 Time point 14","HH","MM","SS","Ext. Device"], + ["36","1","RW","TS1 Time point 14 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["37","1","RW","TS1 Time point 15","HH","MM","SS","Ext. Device"], + ["38","1","RW","TS1 Time point 15 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["39","1","RW","TS1 Time point 16","HH","MM","SS","Ext. Device"], + ["40","1","RW","TS1 Time point 16 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["41","1","RW","TS2 Time point 1","HH","MM","SS","Ext. Device"], + ["42","1","RW","TS2 Time point 1 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["43","1","RW","TS2 Time point 2","HH","MM","SS","Ext. Device"], + ["44","1","RW","TS2 Time point 2 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["45","1","RW","TS2 Time point 3","HH","MM","SS","Ext. Device"], + ["46","1","RW","TS2 Time point 3 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["47","1","RW","TS2 Time point 4","HH","MM","SS","Ext. Device"], + ["48","1","RW","TS2 Time point 4 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["49","1","RW","TS2 Time point 5","HH","MM","SS","Ext. Device"], + ["50","1","RW","TS2 Time point 5 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["51","1","RW","TS2 Time point 6","HH","MM","SS","Ext. Device"], + ["52","1","RW","TS2 Time point 6 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["53","1","RW","TS2 Time point 7","HH","MM","SS","Ext. Device"], + ["54","1","RW","TS2 Time point 7 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["55","1","RW","TS2 Time point 8","HH","MM","SS","Ext. Device"], + ["56","1","RW","TS2 Time point 8 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["57","1","RW","TS2 Time point 9","HH","MM","SS","Ext. Device"], + ["58","1","RW","TS2 Time point 9 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["59","1","RW","TS2 Time point 10","HH","MM","SS","Ext. Device"], + ["60","1","RW","TS2 Time point 10 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["61","1","RW","TS2 Time point 11","HH","MM","SS","Ext. Device"], + ["62","1","RW","TS2 Time point 11 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["63","1","RW","TS2 Time point 12","HH","MM","SS","Ext. Device"], + ["64","1","RW","TS2 Time point 12 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["65","1","RW","TS2 Time point 13","HH","MM","SS","Ext. Device"], + ["66","1","RW","TS2 Time point 13 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["67","1","RW","TS2 Time point 14","HH","MM","SS","Ext. Device"], + ["68","1","RW","TS2 Time point 14 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["69","1","RW","TS2 Time point 15","HH","MM","SS","Ext. Device"], + ["70","1","RW","TS2 Time point 15 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["71","1","RW","TS2 Time point 16","HH","MM","SS","Ext. Device"], + ["72","1","RW","TS2 Time point 16 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["73","1","RW","Power meter status","TBD","","",""], + ["74","1","R","Input Voltage","","","",""], + ["75","1","R","Input Current","","","",""], + ["76","1","R","Input Power","","","",""], + ["77","1","R","Cos phi","","","",""], + ["78","1","R","Frequency","","","",""], + ["79","1","RW","Energy","","","",""], + ["80","1","RW","Lifetime","","","",""], + ["81","1","RW","Power on cycles (input)","","","",""], + ["82","1","RW","Power on cycles (relay)","","","",""], + ["83","1","R","Time since last power on","","","",""], + ["84","1","R","Accelerometer data","","","",""], + ["85","1","RW","GPS latitude","pos/neg","deg","min ","sec"], + ["86","1","RW","GPS longitude","pos/neg","deg","min ","sec"], + ["87","1","RW","Actual time","HH","MM","SS","RES."], + ["88","1","RW","Actual date","Day of week","Day","Month","Year"], + ["89","1","R","Production data 1","","","",""], + ["90","1","R","Production data 2","","","",""], + ["91","1","RW","Network ID","NID3","NID2","NID1","NID0"], + ["95","1","RW","Actual Lux level from cabinet","RES.","RES.","HB","LB"], + ["96","1","RW","Threshold lux level","Dusk HB","Dusk LB","Dawn HB","Dawn LB"], + ["97","1","RW","Adjust period","Dusk HB","Dusk LB","Dawn HB","Dawn LB"], + ["98","1","RW","Offset","RES.","RES.","Dusk","Dawn"], + ["99","1","RW","CCT min/max range","max-H","max-L","min-H","min-L"], + ["100","1","RW","DALI interface","Cmd ID","Add","Cmd","Resp"], + ["101","1","RW","Module FW ver","v1","v2","v3","v4"], + ["102","1","RW","Module MAC-H","unused","unused","M1","M2"], + ["103","1","RW","Module MAC-L","M3","M4","M5","M6"], + ["122","1","R","FW update status/control register","Byte3","Byte2","Byte1","Byte0"], + ["123","1","R","FW update - data index","Byte3","Byte2","Byte1","Byte0"], + ["124","1","R","FW update - data","Byte3","Byte2","Byte1","Byte0"], + ["0","0","R","Status","","","",""], + ["1","0","RW","Control register","RES.","RES.","RES.","init mode enable"], + ["2","0","R","Device types","","","",""], + ["3","0","R","Serial number (MAC)","","","",""], + ["4","0","R","Production data 1","","","",""], + ["5","0","R","Production data 2","","","",""], + ["6","0","RW","Network ID","NID3","NID2","NID1","NID0"], + ["7","0","RW","RS232 settings","param.","param.","Baudrate H","Baudrate L"], + ["8","0","R","Accelerometer data","","","",""], + ["9","0","RW","Module FW ver","v1","v2","v3","v4"], + ["10","0","RW","Module MAC-H","unused","unused","M1","M2"], + ["11","0","RW","Module MAC-L","M3","M4","M5","M6"], + ["32","0","RW","FW update status/control register","Byte3","Byte2","Byte1","Byte0"], + ["33","0","RW","FW update - data index","Byte3","Byte2","Byte1","Byte0"], + ["34","0","RW","FW update - data","Byte3","Byte2","Byte1","Byte0"], + ["125","0","RW","Debug Register","Byte3","Byte2","Byte1","Byte0"], + ["126","0","RW","Network Control Register","Byte3","Byte2","Byte1","Byte0"], + ["127","0","R","Network Status Register","Byte3","Byte2","Byte1","Byte0"], + ["128","0","RW","Node XX Serial Number Register","SER3","SER2","SER1","SER0"], + ["256","0","R","Node XX Network Status Register","","","",""] +]; + +let register = {}; + +module.exports = { + registers, + register +} \ No newline at end of file diff --git a/RVO38/flow/helper/serialport_helper.js b/RVO38/flow/helper/serialport_helper.js new file mode 100755 index 0000000..7f5920d --- /dev/null +++ b/RVO38/flow/helper/serialport_helper.js @@ -0,0 +1,99 @@ +const { exec } = require('child_process'); + +function openPort(port) { + return new Promise((resolve, reject) => { + + var callbackError = function(err) { + port.removeListener('error', callbackError); + port.removeListener('open', callbackError); + + reject(err.message); + }; + + var callbackOpen = function(data) { + port.removeListener('error', callbackError); + port.removeListener('open', callbackOpen); + + resolve("port open: ok"); + }; + + port.on('error', callbackError); + port.on('open', callbackOpen); + + port.open(); + + }) +} + +function runSyncExec(command) { + return new Promise((resolve, reject) => { + + exec(command, (error, stdout, stderr) => { + if (error == null) resolve(stdout); + reject(error); + }); + + }) +} + +async function writeData(port, data, readbytes, timeout) { + return new Promise((resolve, reject) => { + + // 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) { + + port.write(Buffer.from(data), function(err) { + if (err) { + reject(err.message); + } + }); + + 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 +} diff --git a/RVO38/flow/helper/suncalc.js b/RVO38/flow/helper/suncalc.js new file mode 100755 index 0000000..c9ca56d --- /dev/null +++ b/RVO38/flow/helper/suncalc.js @@ -0,0 +1,317 @@ +/* + (c) 2011-2015, Vladimir Agafonkin + SunCalc is a JavaScript library for calculating sun/moon position and light phases. + https://github.com/mourner/suncalc +*/ + +(function () { 'use strict'; + +// shortcuts for easier to read formulas + +var PI = Math.PI, + sin = Math.sin, + cos = Math.cos, + tan = Math.tan, + asin = Math.asin, + atan = Math.atan2, + acos = Math.acos, + rad = PI / 180; + +// sun calculations are based on http://aa.quae.nl/en/reken/zonpositie.html formulas + + +// date/time constants and conversions + +var dayMs = 1000 * 60 * 60 * 24, + J1970 = 2440588, + J2000 = 2451545; + +function toJulian(date) { return date.valueOf() / dayMs - 0.5 + J1970; } +function fromJulian(j) { return new Date((j + 0.5 - J1970) * dayMs); } +function toDays(date) { return toJulian(date) - J2000; } + + +// general calculations for position + +var e = rad * 23.4397; // obliquity of the Earth + +function rightAscension(l, b) { return atan(sin(l) * cos(e) - tan(b) * sin(e), cos(l)); } +function declination(l, b) { return asin(sin(b) * cos(e) + cos(b) * sin(e) * sin(l)); } + +function azimuth(H, phi, dec) { return atan(sin(H), cos(H) * sin(phi) - tan(dec) * cos(phi)); } +function altitude(H, phi, dec) { return asin(sin(phi) * sin(dec) + cos(phi) * cos(dec) * cos(H)); } + +function siderealTime(d, lw) { return rad * (280.16 + 360.9856235 * d) - lw; } + +function astroRefraction(h) { + if (h < 0) // the following formula works for positive altitudes only. + h = 0; // if h = -0.08901179 a div/0 would occur. + + // formula 16.4 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + // 1.02 / tan(h + 10.26 / (h + 5.10)) h in degrees, result in arc minutes -> converted to rad: + return 0.0002967 / Math.tan(h + 0.00312536 / (h + 0.08901179)); +} + +// general sun calculations + +function solarMeanAnomaly(d) { return rad * (357.5291 + 0.98560028 * d); } + +function eclipticLongitude(M) { + + var C = rad * (1.9148 * sin(M) + 0.02 * sin(2 * M) + 0.0003 * sin(3 * M)), // equation of center + P = rad * 102.9372; // perihelion of the Earth + + return M + C + P + PI; +} + +function sunCoords(d) { + + var M = solarMeanAnomaly(d), + L = eclipticLongitude(M); + + return { + dec: declination(L, 0), + ra: rightAscension(L, 0) + }; +} + + +var SunCalc = {}; + + +// calculates sun position for a given date and latitude/longitude + +SunCalc.getPosition = function (date, lat, lng) { + + var lw = rad * -lng, + phi = rad * lat, + d = toDays(date), + + c = sunCoords(d), + H = siderealTime(d, lw) - c.ra; + + return { + azimuth: azimuth(H, phi, c.dec), + altitude: altitude(H, phi, c.dec) + }; +}; + + +// sun times configuration (angle, morning name, evening name) + +var times = SunCalc.times = [ + [-0.833, 'sunrise', 'sunset' ], + [ -0.3, 'sunriseEnd', 'sunsetStart' ], + [ -6, 'dawn', 'dusk' ], + [ -12, 'nauticalDawn', 'nauticalDusk'], + [ -18, 'nightEnd', 'night' ], + [ 6, 'goldenHourEnd', 'goldenHour' ] +]; + +// adds a custom time to the times config + +SunCalc.addTime = function (angle, riseName, setName) { + times.push([angle, riseName, setName]); +}; + + +// calculations for sun times + +var J0 = 0.0009; + +function julianCycle(d, lw) { return Math.round(d - J0 - lw / (2 * PI)); } + +function approxTransit(Ht, lw, n) { return J0 + (Ht + lw) / (2 * PI) + n; } +function solarTransitJ(ds, M, L) { return J2000 + ds + 0.0053 * sin(M) - 0.0069 * sin(2 * L); } + +function hourAngle(h, phi, d) { return acos((sin(h) - sin(phi) * sin(d)) / (cos(phi) * cos(d))); } +function observerAngle(height) { return -2.076 * Math.sqrt(height) / 60; } + +// returns set time for the given sun altitude +function getSetJ(h, lw, phi, dec, n, M, L) { + + var w = hourAngle(h, phi, dec), + a = approxTransit(w, lw, n); + return solarTransitJ(a, M, L); +} + + +// calculates sun times for a given date, latitude/longitude, and, optionally, +// the observer height (in meters) relative to the horizon + +SunCalc.getTimes = function (date, lat, lng, height) { + + height = height || 0; + + var lw = rad * -lng, + phi = rad * lat, + + dh = observerAngle(height), + + d = toDays(date), + n = julianCycle(d, lw), + ds = approxTransit(0, lw, n), + + M = solarMeanAnomaly(ds), + L = eclipticLongitude(M), + dec = declination(L, 0), + + Jnoon = solarTransitJ(ds, M, L), + + i, len, time, h0, Jset, Jrise; + + + var result = { + solarNoon: fromJulian(Jnoon), + nadir: fromJulian(Jnoon - 0.5) + }; + + for (i = 0, len = times.length; i < len; i += 1) { + time = times[i]; + h0 = (time[0] + dh) * rad; + + Jset = getSetJ(h0, lw, phi, dec, n, M, L); + Jrise = Jnoon - (Jset - Jnoon); + + result[time[1]] = fromJulian(Jrise); + result[time[2]] = fromJulian(Jset); + } + + return result; +}; + + +// moon calculations, based on http://aa.quae.nl/en/reken/hemelpositie.html formulas + +function moonCoords(d) { // geocentric ecliptic coordinates of the moon + + var L = rad * (218.316 + 13.176396 * d), // ecliptic longitude + M = rad * (134.963 + 13.064993 * d), // mean anomaly + F = rad * (93.272 + 13.229350 * d), // mean distance + + l = L + rad * 6.289 * sin(M), // longitude + b = rad * 5.128 * sin(F), // latitude + dt = 385001 - 20905 * cos(M); // distance to the moon in km + + return { + ra: rightAscension(l, b), + dec: declination(l, b), + dist: dt + }; +} + +SunCalc.getMoonPosition = function (date, lat, lng) { + + var lw = rad * -lng, + phi = rad * lat, + d = toDays(date), + + c = moonCoords(d), + H = siderealTime(d, lw) - c.ra, + h = altitude(H, phi, c.dec), + // formula 14.1 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + pa = atan(sin(H), tan(phi) * cos(c.dec) - sin(c.dec) * cos(H)); + + h = h + astroRefraction(h); // altitude correction for refraction + + return { + azimuth: azimuth(H, phi, c.dec), + altitude: h, + distance: c.dist, + parallacticAngle: pa + }; +}; + + +// calculations for illumination parameters of the moon, +// based on http://idlastro.gsfc.nasa.gov/ftp/pro/astro/mphase.pro formulas and +// Chapter 48 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + +SunCalc.getMoonIllumination = function (date) { + + var d = toDays(date || new Date()), + s = sunCoords(d), + m = moonCoords(d), + + sdist = 149598000, // distance from Earth to Sun in km + + phi = acos(sin(s.dec) * sin(m.dec) + cos(s.dec) * cos(m.dec) * cos(s.ra - m.ra)), + inc = atan(sdist * sin(phi), m.dist - sdist * cos(phi)), + angle = atan(cos(s.dec) * sin(s.ra - m.ra), sin(s.dec) * cos(m.dec) - + cos(s.dec) * sin(m.dec) * cos(s.ra - m.ra)); + + return { + fraction: (1 + cos(inc)) / 2, + phase: 0.5 + 0.5 * inc * (angle < 0 ? -1 : 1) / Math.PI, + angle: angle + }; +}; + + +function hoursLater(date, h) { + return new Date(date.valueOf() + h * dayMs / 24); +} + +// calculations for moon rise/set times are based on http://www.stargazing.net/kepler/moonrise.html article + +SunCalc.getMoonTimes = function (date, lat, lng, inUTC) { + var t = new Date(date); + if (inUTC) t.setUTCHours(0, 0, 0, 0); + else t.setHours(0, 0, 0, 0); + + var hc = 0.133 * rad, + h0 = SunCalc.getMoonPosition(t, lat, lng).altitude - hc, + h1, h2, rise, set, a, b, xe, ye, d, roots, x1, x2, dx; + + // go in 2-hour chunks, each time seeing if a 3-point quadratic curve crosses zero (which means rise or set) + for (var i = 1; i <= 24; i += 2) { + h1 = SunCalc.getMoonPosition(hoursLater(t, i), lat, lng).altitude - hc; + h2 = SunCalc.getMoonPosition(hoursLater(t, i + 1), lat, lng).altitude - hc; + + a = (h0 + h2) / 2 - h1; + b = (h2 - h0) / 2; + xe = -b / (2 * a); + ye = (a * xe + b) * xe + h1; + d = b * b - 4 * a * h1; + roots = 0; + + if (d >= 0) { + dx = Math.sqrt(d) / (Math.abs(a) * 2); + x1 = xe - dx; + x2 = xe + dx; + if (Math.abs(x1) <= 1) roots++; + if (Math.abs(x2) <= 1) roots++; + if (x1 < -1) x1 = x2; + } + + if (roots === 1) { + if (h0 < 0) rise = i + x1; + else set = i + x1; + + } else if (roots === 2) { + rise = i + (ye < 0 ? x2 : x1); + set = i + (ye < 0 ? x1 : x2); + } + + if (rise && set) break; + + h0 = h2; + } + + var result = {}; + + if (rise) result.rise = hoursLater(t, rise); + if (set) result.set = hoursLater(t, set); + + if (!rise && !set) result[ye > 0 ? 'alwaysUp' : 'alwaysDown'] = true; + + return result; +}; + + +// export as Node module / AMD module / browser variable +if (typeof exports === 'object' && typeof module !== 'undefined') module.exports = SunCalc; +else if (typeof define === 'function' && define.amd) define(SunCalc); +else window.SunCalc = SunCalc; + +}()); diff --git a/RVO38/flow/helper/utils.js b/RVO38/flow/helper/utils.js new file mode 100755 index 0000000..dbffe45 --- /dev/null +++ b/RVO38/flow/helper/utils.js @@ -0,0 +1,161 @@ +const fs = require('fs').promises; + +function bytesToInt(bytes, numberOfBytes) { + let buffer = []; + if (Array.isArray(bytes)) { + buffer = bytes.slice(0); + if (numberOfBytes != undefined) { + buffer = bytes.slice(bytes.length - numberOfBytes); + } + } + else buffer.push(bytes); + + let result = 0; + for (let i = 0; i < buffer.length; i++) { + result = (result << 8) | buffer[i]; + } + + return result >>> 0; //ensure it's an unsigned 32-bit number +} + +function resizeArray(arr, newSize, defaultValue) { + while (newSize > arr.length) + arr.push(defaultValue); + arr.length = newSize; +} + +longToByteArray = function(/*long*/long) { + // we want to represent the input as a 8-bytes array + var byteArray = [0, 0, 0, 0, 0, 0, 0, 0]; + + for (var index = 0; index < byteArray.length; index++) { + var byte = long & 0xff; + byteArray[index] = byte; + long = (long - byte) / 256; + } + + return byteArray; +}; + +function addDays(date, days) { + var result = new Date(date); + result.setDate(result.getDate() + days); + return result; +} + +/* +sleep(2000).then(() => { + // Do something after the sleep! + + +}); +*/ + +function sleep(time) { + return new Promise((resolve) => setTimeout(resolve, time)); +} + +function isEmptyObject(obj) { + for (var name in obj) { + return false; + } + return true; +} + +function emptyJsObject(jsObject) { + Object.keys(jsObject).forEach(key => delete jsObject[key]); +} + +function convertUTCDateToLocalDate(date) { + var newDate = new Date(date); + newDate.setMinutes(date.getMinutes() + date.getTimezoneOffset()); + return newDate; +} + +function addZeroBefore(n) { + return (n < 10 ? '0' : '') + n; +} + + +/** + * Asynchronously writes data to a file. + * + * @param {string} filePath The path to the file. + * @param {string} data The data to write to the file. + * @param {boolean} [append=false] If true, appends the data to the file. If false, it overwrites the file. + */ +async function writeToFile(filePath, data, append = false) { + if (typeof data !== 'string') data = JSON.stringify(data, null, 2); + try { + if (append) { + // Append the data to the end of the file. This is the simplest way to append. + await fs.appendFile(filePath, data, 'utf8'); + console.log(`Successfully appended data to ${filePath} using fs.appendFile.`); + } else { + // Overwrite the file with the new data. + await fs.writeFile(filePath, data, 'utf8'); + console.log(`Successfully wrote (overwrote) data to ${filePath} using fs.writeFile.`); + } + } catch (error) { + console.error(`Error writing to file ${filePath}:`, error); + } +} + + + /** + * Checks if an item is present in an array and adds it if it's not. + * * @param {Array} arr The array to check. + * @param {*} item The item to add. + * @returns {Array} The modified array. + */ +const addToArrayIfUnique = (arr, item) => { + if (!arr.includes(item)) { + arr.push(item); + } + return arr; +}; + + +var convertBase = function() { + + function convertBase(baseFrom, baseTo) { + return function(num) { + return parseInt(num, baseFrom).toString(baseTo); + + }; + } + + // binary to decimal + convertBase.bin2dec = convertBase(2, 10); + + // binary to hexadecimal + convertBase.bin2hex = convertBase(2, 16); + + // decimal to binary + convertBase.dec2bin = convertBase(10, 2); + + // decimal to hexadecimal + convertBase.dec2hex = convertBase(10, 16); + + // hexadecimal to binary + convertBase.hex2bin = convertBase(16, 2); + + // hexadecimal to decimal + convertBase.hex2dec = convertBase(16, 10); + + return convertBase; +}(); + +module.exports = { + bytesToInt, + longToByteArray, + addDays, + addZeroBefore, + resizeArray, + isEmptyObject, + emptyJsObject, + sleep, + convertUTCDateToLocalDate, + writeToFile, + addToArrayIfUnique +} diff --git a/RVO38/flow/httprequest.js b/RVO38/flow/httprequest.js new file mode 100755 index 0000000..469c8cb --- /dev/null +++ b/RVO38/flow/httprequest.js @@ -0,0 +1,137 @@ +exports.id = 'httprequest'; +exports.title = 'HTTP Request'; +exports.group = 'HTTP'; +exports.color = '#5D9CEC'; +exports.input = true; +exports.version = '2.0.1'; +exports.output = 1; +exports.author = 'Peter Širka'; +exports.icon = 'cloud-upload'; + +exports.html = `
+
@(URL address)
+
+
+
@(HTTP method)
+
+
+
@(Serialization)
+
+
+
@(Download the content in chunks)
+
@(Keep persistent cookies)
+
@(Disable DNS cache)
+
@(Keep alive connection)
+
+
+
+
@(Custom headers)
+
@(Cookies)
+
+
+
+ +
+
+
+
@(User)
+
+
+
@(Password)
+
+
+
+
+
`; + +exports.readme = `# Request + +This component creates a request with received data. + +__Response:__ +\`\`\`javascript +{ + data: String, + headers: Object, + status: Number, + host: String +} +\`\`\` + +__Dynamic arguments__: +Are performed via FlowData repository and can be used for URL address or for custom headers/cookies/auth. Use \`repository\` component for creating of dynamic arguments. Dynamic values are replaced in the form \`{key}\`: + +- url address e.g. \`https://.../{key}/\` +- headers values e.g. \`{token}\` +- cookies values e.g. \`{token}\``; + +exports.install = function(instance) { + + var can = false; + var flags = null; + var cookies2 = null; + + instance.on('data', function(response) { + can && instance.custom.send(response); + }); + + instance.custom.send = function(response) { + var options = instance.options; + + var headers = null; + var cookies = null; + + options.headers && Object.keys(options.headers).forEach(function(key) { + !headers && (headers = {}); + headers[key] = response.arg(options.headers[key]); + }); + + if (options.username && options.userpassword) { + !headers && (headers = {}); + headers['Authorization'] = 'Basic ' + U.createBuffer(response.arg(options.username + ':' + options.userpassword)).toString('base64'); + } + + options.cookies && Object.keys(options.cookies).forEach(function(key) { + !cookies && (cookies = {}); + cookies[key] = response.arg(options.cookies[key]); + }); + + if (options.chunks) { + U.download(response.arg(options.url), flags, options.stringify === 'none' ? null : response.data, function(err, response) { + response.on('data', (chunks) => instance.send2(chunks)); + }, cookies || cookies2, headers); + } else { + U.request(response.arg(options.url), flags, options.stringify === 'none' ? null : response.data, 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) + instance.error(err, response); + }, cookies || cookies2, headers); + } + }; + + instance.reconfigure = function() { + var options = instance.options; + can = options.url && options.url && options.method && options.stringify ? true : false; + instance.status(can ? '' : 'Not configured', can ? undefined : 'red'); + + if (!can) + return; + + flags = []; + flags.push(options.method.toLowerCase()); + options.stringify === 'json' && flags.push('json'); + options.stringify === 'raw' && flags.push('raw'); + options.keepalive && flags.push('keepalive'); + !options.nodns && flags.push('dnscache'); + if (options.persistentcookies) { + flags.push('cookies'); + cookies2 = {}; + } else + cookies2 = null; + }; + + instance.on('options', instance.reconfigure); + instance.reconfigure(); +}; \ No newline at end of file diff --git a/RVO38/flow/httpresponse.js b/RVO38/flow/httpresponse.js new file mode 100755 index 0000000..160a3bb --- /dev/null +++ b/RVO38/flow/httpresponse.js @@ -0,0 +1,76 @@ +exports.id = 'httpresponse'; +exports.title = 'HTTP Response'; +exports.group = 'HTTP'; +exports.color = '#5D9CEC'; +exports.icon = 'arrow-right'; +exports.input = true; +exports.output = ['#666D76']; +exports.version = '2.0.0'; +exports.author = 'Martin Smola'; +exports.readme = `# HTTP response + +HTTP response will respond with data recieved using data-type set in Settings form or plain text if not set. Output is the message duration \`Number\` in seconds.`; + +exports.html = `
+
@(Response data-type)
+
JSON is by default.
+
`; + +exports.install = function(instance) { + + var dursum = 0; + var durcount = 0; + + instance.on('data', function(flowdata) { + + var ctrl = flowdata.repository.controller; + var data = flowdata.data; + + if (!ctrl) { + instance.throw('No controller to use for response!'); + return; + } + + durcount++; + dursum += ((new Date() - flowdata.begin) / 1000).floor(2); + setTimeout2(instance.id, instance.custom.duration, 500, 10); + + ctrl.$flowdata = flowdata; + + var datatype = instance.options.datatype || 'json'; + if (datatype === 'emptyresponse') + return ctrl.plain(''); + + if (datatype !== 'json' && typeof(data) !== 'string') { + instance.throw('Incorect type of data, expected string, got ' + typeof(data)); + ctrl.plain(data == null ? '' : data.toString()); + return; + } + + switch(datatype) { + case 'html': + ctrl.content(data, 'text/html'); + break; + case 'plain': + ctrl.plain(data); + break; + case 'xml': + ctrl.content(data, 'text/xml'); + break; + default: + ctrl.json(data); + break; + } + }); + + instance.on('service', function() { + dursum = 0; + durcount = 0; + }); + + instance.custom.duration = function() { + var avg = (dursum / durcount).floor(2); + instance.status(avg + ' sec.'); + instance.send2(0, avg); + }; +}; diff --git a/RVO38/flow/httproute.js b/RVO38/flow/httproute.js new file mode 100755 index 0000000..583a19d --- /dev/null +++ b/RVO38/flow/httproute.js @@ -0,0 +1,326 @@ +exports.id = 'httproute'; +exports.title = 'HTTP Route'; +exports.group = 'HTTP'; +exports.color = '#5D9CEC'; +exports.icon = 'globe'; +exports.input = false; +exports.output = ['#6CAC5A', '#37BC9B']; +exports.version = '1.2.3'; +exports.author = 'Martin Smola'; +exports.cloning = false; +exports.options = { method: 'GET', url: '', size: 5, cacheexpire: '5 minutes', cachepolicy: 0, timeout: 5 }; +exports.dateupdated = '2021-01-21 18:30d'; +exports.readme = `# HTTP route + +__Outputs__: +- first output: raw data (cache is empty or is disabled) +- second output: cached data + +If one of the outputs is disabled then automatic responce with code "503 service unavailable" is sent. + +When a request comes in bellow object is available at \`flowdata.data\`: + +\`\`\`javascript +{ + params: { id: '1' }, // params for dynamic routes, e.g. /test/{id} + query: { msg: 'Hello' }, // parsed query string, e.g. /test/1?msg=Hello + body: { test: 'OK' }, // object if json requests otherwise string + headers: {}, // headers data + session: {}, // session data + user: {}, // user data + files: [], // uploaded files + url: '/users/', // a relative URL address + referrer: '/', // referrer + mobile: false, // determines mobile device + robot: false, // determines search robots/crawlsers + language: 'en' // determines language +} +\`\`\` + +See [documentation for flags](https://docs.totaljs.com/latest/en.html#api~HttpRouteOptionsFlags~unauthorize). These method flags are set automatically e.g. \`get, post, put, patch or delete\` + +--- + +\`id:ROUTE_ID\` flag cannot be used since it's already used by this component internally`; + +exports.html = `
+
+ +
+ +
+
+
@(HTTP method)
+
+
+
@(URL address)
+
+
+
+
+
@(Additional flags)
+
@(Separate flags by comma e.g. json, authorize)
+
+
+
@(Max. request size)
+
@(In kB kilobytes)
+
+
+
@(Timeout)
+
@(In seconds.)
+
+
+
+
+
+
@(Automatically respond with 200 OK?)
+
@(If not checked you need to use HTTP response component to respond to the request.)
+
+
@(Custom headers)
+
@(Cookies)
+
+
+
+
+
+
@(Cache policy)
+
@(User instance must contain id property.)
+
+
+
@(Expiration)
+
@(E.g. 5 minutes)
+
+
+
+`; + +exports.install = function(instance) { + + var route; + + var uninstall = function(id) { + if (F.is4) { + route && route.remove(); + route = null; + } else + UNINSTALL('route', id); + }; + + instance.custom.emptyresponse = function(self) { + self.plain(); + }; + + instance.reconfigure = function() { + + var options = instance.options; + + if (!options.url) { + instance.status('Not configured', 'red'); + return; + } + + if (typeof(options.flags) === 'string') + options.flags = options.flags.split(',').trim(); + + uninstall('id:' + instance.id); + + var flags = options.flags || []; + + flags.push('id:' + instance.id); + + if (!F.is4) + flags.push(options.method.toLowerCase()); + + options.timeout && flags.push(options.timeout * 1000); + + // Make unique values + flags = flags.filter(function(v, i, a) { + if(F.is4 && v.toString().toLowerCase() === options.method.toLowerCase()) + return false; // remove method + return a.indexOf(v) === i; + }); + + options.flags = flags; + var handler = function() { + + if (instance.paused || (instance.isDisabled && (instance.isDisabled('output', 0) || instance.isDisabled('output', 1)))) { + instance.status('503 Service Unavailable'); + this.status = 503; + this.json(); + return; + } + + var key; + var self = this; + + if (instance.options.emptyresponse) { + instance.status('200 OK'); + setTimeout(instance.custom.emptyresponse, 100, self); + + if (instance.hasConnection(0)) { + var data = instance.make({ + query: self.query, + body: self.body, + session: self.session, + user: self.user, + files: self.files, + headers: self.req.headers, + url: self.url, + params: self.params + }); + instance.send2(0, data); + } + + return; + } + + switch (instance.options.cachepolicy) { + case 1: // URL + key = 'rro' + instance.id + self.url.hash(); + break; + case 2: // URL + query + case 3: // URL + query + user + key = self.url; + var keys = Object.keys(self.query); + keys.sort(); + for (var i = 0, length = keys.length; i < length; i++) + key += keys[i] + self.query[keys[i]] + '&'; + if (instance.options.cachepolicy === 3 && self.user) + key += 'iduser' + self.user.id; + key = 'rro' + instance.id + key.hash(); + break; + } + + if (key && F.cache.get2(key)) { + var data = instance.make(F.cache.get2(key)); + data.repository.controller = self; + instance.send2(1, data); + } else { + + var data = instance.make({ + query: self.query, + body: self.body, + session: self.session, + user: self.user, + files: self.files, + headers: self.req.headers, + url: self.url, + params: self.params, + mobile: self.mobile, + robot: self.robot, + referrer: self.referrer, + language: self.language + }); + + data.repository.controller = self; + instance.send2(0, data); + key && FINISHED(self.res, () => F.cache.set(key, self.$flowdata.data, instance.options.cacheexpire)); + } + }; + + if (F.is4) + route = ROUTE(options.method.toUpperCase() + ' ' + options.url, handler, flags, options.size || 5); + else + F.route(options.url, handler, flags, options.size || 5); + + instance.status('Listening', 'green'); + }; + + instance.reconfigure(); + instance.on('options', instance.reconfigure); + instance.on('close', function(){ + uninstall('id:' + instance.id); + }); +}; + +// check url exists +FLOW.trigger('httproutecheckurl', function(next, data) { + var url = data.url; + var method = data.method; + if (url[url.length - 1] !== '/') + url += '/'; + var exists = F.routes.web.findItem(r => r.urlraw === url && r.method === method); + next(exists != null); +}); + +exports.uninstall = function() { + FLOW.trigger('httproutecheckurl', null); +}; diff --git a/RVO38/flow/infosender.js b/RVO38/flow/infosender.js new file mode 100755 index 0000000..587724f --- /dev/null +++ b/RVO38/flow/infosender.js @@ -0,0 +1,81 @@ +exports.id = 'infosender'; +exports.title = 'Info sender'; +exports.version = '1.0.0'; +exports.group = 'Worksys'; +exports.color = '#2134B0'; +exports.input = 2; +exports.output = 1 +exports.icon = 'bolt'; + +const { networkInterfaces } = require('os'); + +exports.html = `
+
+
+
CSV Import
+
+
+
`; + +exports.readme = `# send all data to projects.worksys.io, required to monitor status of controller(unipi)`; + +exports.install = function(instance) { + + let id; + let allValues = {}; + let sendAllValuesInterval; + let configured = false; + + let now = new Date(); + console.log(exports.title, "INSTALLED", now.toLocaleString("sk-SK")); + + const nets = networkInterfaces(); + let ipAddresses = Object.create(null); // Or just '{}', an empty object + + for (const name of Object.keys(nets)) { + for (const net of nets[name]) { + // Skip over non-IPv4 and internal (i.e. 127.0.0.1) addresses + if (net.family === 'IPv4' && !net.internal) { + if (!ipAddresses[name]) { + ipAddresses[name] = []; + } + ipAddresses[name].push(net.address); + } + } + } + + function sendValues() { + if (!configured) return; + + if (Object.keys(allValues).length > 0) { + let dataToSend = { ...allValues }; + dataToSend.id = id; + dataToSend.ipAddresses = ipAddresses; + + instance.send(0, dataToSend); + + allValues = {}; + } + } + + instance.on("close", () => { + clearInterval(sendAllValuesInterval); + }) + + instance.on("0", _ => { + id = FLOW.GLOBALS.settings.project_id; + if (id) configured = true; + else console.log(exports.title, "InfoSender: Unable to send data, no id"); + }) + + instance.on("1", flowdata => { + allValues = { ...allValues, ...flowdata.data }; + //console.log("DATA RECEIVED", flowdata.data); + }) + + sendAllValuesInterval = setInterval(() => { + sendValues(); + }, 60000 * 3); + +} + diff --git a/RVO38/flow/modbus_reader.js b/RVO38/flow/modbus_reader.js new file mode 100755 index 0000000..d6d9dad --- /dev/null +++ b/RVO38/flow/modbus_reader.js @@ -0,0 +1,346 @@ +exports.id = 'modbus_reader'; +exports.title = 'Modbus reader'; +exports.version = '2.0.0'; +exports.group = 'Worksys'; +exports.color = '#2134B0'; +exports.input = 1; +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; +//number of phases inRVO +let phases; +//phases where voltage is 0 (set) +let noVoltage; +let energyToSwitchLamps; + +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.phases = this.buildPhases(); + + this.startSocket(); + } + + buildPhases = () => { + let a = []; + for (let i = 1; i <= phases; i++) { + a.push(`Phase_${i}_voltage`) + } + return a; + } + + startSocket = () => { + + let obj = this; + + if (this.socket) { + this.socket.removeAllListeners(); + this.socket = null; + } + + 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('Modbus_reader: Socket connection error', e); //'ECONNREFUSED' or 'ECONNRESET' ?? + }); + + this.socket.on('close', function() { + console.log('Modbus_reader: Socket connection closed - Waiting 10 seconds before connecting 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 we just start to loop devices from the beginning, or there is just 1 device in config, we wait whole timeoutInterval + if (this.indexInDeviceConfig == 0 || deviceConfig.length === 1) 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 (this.phases.includes(singleValue)) { + let l = singleValue.split("_"); + let phase = parseInt(l[1]); + + // console.log(values[singleValue], tbName); + + if (values[singleValue] == 0) { + noVoltage.add(phase); + sendNotification("modbus_reader: checkNullVoltage", tbName, "no_voltage_on_phase", { phase: phase }, "", SEND_TO.tb, instance, "voltage" + phase); + // console.log('no voltage') + } + else { + noVoltage.delete(phase); + // console.log('voltage detected') + sendNotification("modbus_reader: checkNullVoltage", tbName, "voltage_on_phase_restored", { phase: phase }, "", SEND_TO.tb, instance, "voltage" + phase); + } + } + }) + } + + /** + * function sends notification to slack and to tb, if EM total_power value changes more than numberOfNodes*15. This should show, that RVO lamps has been switched on or off + */ + lampSwitchNotification = (values) => { + + if (!values.hasOwnProperty("total_power")) return; + + const actualTotalPower = values.total_power; + + if (actualTotalPower > energyToSwitchLamps && 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 <= energyToSwitchLamps && 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; + } + + function main() { + + phases = FLOW.GLOBALS.settings.phases; + tbName = FLOW.GLOBALS.settings.rvoTbName; + noVoltage = FLOW.GLOBALS.settings.no_voltage; + energyToSwitchLamps = FLOW.GLOBALS.settings.energy_to_switch_lamps / 2.5; //half value is enought to show if lamps are turned on or off + if (deviceConfig.length) mainSocket = new SocketWithClients(); + else console.log("Modbus_reader: no modbus device in configuration"); + + // this notification is to show, that flow (unipi) has been restarted + sendNotification("modbus_reader", tbName, "flow_restart", {}, "", SEND_TO.slack, instance); + } + + instance.on("0", function(_) { + main(); + }) + +} + diff --git a/RVO38/flow/monitorconsumption.js b/RVO38/flow/monitorconsumption.js new file mode 100755 index 0000000..64cc58e --- /dev/null +++ b/RVO38/flow/monitorconsumption.js @@ -0,0 +1,156 @@ +exports.id = 'monitorconsumption'; +exports.title = 'Consumption'; +exports.version = '1.0.0'; +exports.author = 'Peter Širka'; +exports.group = 'Monitoring'; +exports.color = '#967ADC'; +exports.input = 0; +exports.output = 1; +exports.icon = 'bug'; +exports.options = { interval: 5000, enabled: true, monitorconsumption: true, monitorsize: true, monitorconnections: true, monitorfiles: true }; +exports.click = true; +exports.readme = `# Consumption monitoring + +This component measure CPU and memory consumption, open files and open connections of this application. It uses these Linux commands: \`ps\`, \`lsof\`, \`netstat\` and \`df\`. + +__Data Example__: + +\`\`\`javascript +{ + cpu: 0, // percentage + memory: 4096, // in bytes + size: 34303, // directory size in bytes + files: 34, // count of open files + connections: 343, // count of connections + uptime: '1-12:34:00' +} +\`\`\``; + +exports.html = `
+
+
+
@(Interval in milliseconds)
+
+
+
+
Monitor: Consumption + uptime
+
Monitor: Count of open files
+
Monitor: Count of open connections
+
Monitor: Directory size
+
`; + +exports.install = function(instance) { + + var current = { cpu: 0, memory: 0, files: 0, connections: 0, size: 0, uptime: '', counter: 0 }; + var tproc = null; + var Exec = require('child_process').exec; + var reg_empty = /\s{2,}/g; + var reg_appdisksize = /^[\d.,]+/; + + instance.custom.run = function() { + + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + + var arr = []; + + // Get CPU and Memory consumption + instance.options.monitorconsumption && arr.push(function(next) { + Exec('ps -p {0} -o %cpu,rss,etime'.format(process.pid), function(err, response) { + + if (err) { + instance.throw(err); + } else { + var line = response.split('\n')[1]; + line = line.trim().replace(reg_empty, ' ').split(' '); + var cpu = line[0].parseFloat(); + current.cpu = cpu.floor(1); + current.memory = line[1].parseInt2() * 1024; // kB to bytes + current.uptime = line[2]; + } + + next(); + }); + }); + + // Get count of open files + instance.options.monitorfiles && arr.push(function(next) { + Exec('lsof -a -p {0} | wc -l'.format(process.pid), function(err, response) { + if (err) + instance.throw(err); + else + current.files = response.trim().parseInt2(); + next(); + }); + }); + + // Get count of opened network connections + instance.options.monitorconnections && arr.push(function(next) { + Exec('netstat -an | grep :{0} | wc -l'.format(F.port), function(err, response) { + if (err) { + instance.throw(err); + } else { + current.connections = response.trim().parseInt2() - 1; + if (current.connections < 0) + current.connections = 0; + } + next(); + }); + }); + + // Get directory size + instance.options.monitorsize && current.counter % 5 !== 0 && arr.push(function(next) { + Exec('du -hsb ' + process.cwd(), function(err, response) { + if (err) { + instance.throw(err); + } else { + var match = response.trim().match(reg_appdisksize); + match && (current.size = match.toString().trim().parseInt2()); + } + next(); + }); + }); + + arr.async(function() { + + tproc && clearTimeout(tproc); + + if (instance.options.enabled) { + tproc = setTimeout(instance.custom.run, instance.options.interval); + instance.send2(current); + } + + instance.custom.status(); + current.counter++; + }); + }; + + instance.custom.status = function() { + if (instance.options.enabled) + instance.status('{0}% / {1}'.format(current.cpu, current.memory.filesize())); + else + instance.status('Disabled', 'red'); + }; + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + + if (instance.options.enabled) { + current.counter = 0; + instance.custom.run(); + } + + }); + + instance.on('close', function() { + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + }); + + setTimeout(instance.custom.run, 1000); +}; \ No newline at end of file diff --git a/RVO38/flow/monitordisk.js b/RVO38/flow/monitordisk.js new file mode 100755 index 0000000..f4fdaa0 --- /dev/null +++ b/RVO38/flow/monitordisk.js @@ -0,0 +1,96 @@ +exports.id = 'monitordisk'; +exports.title = 'Disk'; +exports.version = '1.0.0'; +exports.author = 'Peter Širka'; +exports.group = 'Monitoring'; +exports.color = '#F6BB42'; +exports.output = 1; +exports.icon = 'hdd-o'; +exports.click = true; +exports.options = { interval: 8000, path: '/', enabled: true }; +exports.readme = `# Disk monitoring + +This component monitors disk \`bytes\` consumption in Linux systems. It uses \`df\` command. + +__Data Example__: + +\`\`\`javascript +{ + total: 474549649408, + used: 39125245952, + free: 411294994432 +} +\`\`\``; + +exports.html = `
+
+
+
@(Interval in milliseconds)
+
+
+
@(Path)
+
+
+
`; + +exports.install = function(instance) { + + var current = { total: 0, used: 0, free: 0, path: '', type: '', percentUsed: 0 }; + var tproc = null; + + instance.custom.run = function() { + + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + + if (!instance.options.enabled) + return; + + require('child_process').exec('df -hTB1 ' + instance.options.path, function(err, response) { + + tproc = setTimeout(instance.custom.run, instance.options.interval); + + if (err) { + instance.error(err); + return; + } + + response.parseTerminal(function(line) { + if (line[0][0] !== '/') + return; + current.total = line[2].parseInt(); + current.free = line[4].parseInt(); + current.used = line[3].parseInt(); + current.path = instance.options.path || '/'; + current.type = line[1]; + current.percentUsed = line[5]; + instance.custom.status(); + instance.send2(current); + }); + }); + }; + + instance.custom.status = function() { + if (instance.options.enabled) + instance.status(current.free.filesize() + ' / ' + current.total.filesize()); + else + instance.status('Disabled', 'red'); + }; + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + instance.options.enabled && instance.custom.run(); + }); + + instance.on('close', function() { + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + }); + + setTimeout(instance.custom.run, 1000); +}; \ No newline at end of file diff --git a/RVO38/flow/monitormemory.js b/RVO38/flow/monitormemory.js new file mode 100755 index 0000000..2decbc4 --- /dev/null +++ b/RVO38/flow/monitormemory.js @@ -0,0 +1,87 @@ +exports.id = 'monitormemory'; +exports.title = 'Memory'; +exports.version = '1.0.0'; +exports.author = 'Peter Širka'; +exports.group = 'Monitoring'; +exports.color = '#F6BB42'; +exports.output = 1; +exports.click = true; +exports.icon = 'microchip'; +exports.options = { interval: 8000, enabled: true }; +exports.readme = `# Memory monitoring + +This component monitors memory \`bytes\` consumption in Linux systems. It uses \`free\` command. + +__Data Example__: + +\`\`\`javascript +{ + total: 33558769664, + used: 1998868480, + free: 2653708288 +} +\`\`\``; + +exports.html = `
+
+
+
@(Interval in milliseconds)
+
+
+
`; + +exports.install = function(instance) { + + var current = { total: 0, used: 0, free: 0 }; + var tproc = null; + + instance.custom.run = function() { + + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + + if (!instance.options.enabled) + return; + + require('child_process').exec('free -b -t', function(err, response) { + + tproc = setTimeout(instance.custom.run, instance.options.interval); + + if (err) { + instance.error(err); + return; + } + + var memory = response.split('\n')[1].match(/\d+/g); + current.total = memory[0].parseInt(); + current.used = memory[1].parseInt() - memory[3].parseInt(); + current.free = current.total - current.used; + instance.custom.status(); + instance.send2(current); + }); + }; + + instance.custom.status = function() { + if (instance.options.enabled) + instance.status(current.free.filesize() + ' / ' + current.total.filesize()); + else + instance.status('Disabled', 'red'); + }; + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + instance.options.enabled && instance.custom.run(); + }); + + instance.on('close', function() { + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + }); + + setTimeout(instance.custom.run, 1000); +}; \ No newline at end of file diff --git a/RVO38/flow/nodesdb_changecheck.js b/RVO38/flow/nodesdb_changecheck.js new file mode 100755 index 0000000..9adab62 --- /dev/null +++ b/RVO38/flow/nodesdb_changecheck.js @@ -0,0 +1,77 @@ +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 = 2; +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); + } + } + + //kedze do slacku posielame stringy, na cloud musime previest vsetky stringy spat na objekty: + // Funkcia na parsovanie všetkých reťazcov v poli + const parseArray = (arr) => { + return arr.map(jsonString => JSON.parse(jsonString)); + }; + + 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); + if (FLOW.GLOBALS.settings.send_changed_node_numbers) instance.send(1, { aktualneNody: parseArray(zmenene), originalne: parseArray(Array.from(set2)) }); + } + 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/RVO38/flow/show_dbdata.js b/RVO38/flow/show_dbdata.js new file mode 100755 index 0000000..1e23ff7 --- /dev/null +++ b/RVO38/flow/show_dbdata.js @@ -0,0 +1,243 @@ +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 = 8; +exports.output = 1; + +const { exec } = require('child_process'); + +exports.install = 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 }) + }) + instance.on("5", _ => { + exec("sudo tail -n 25 monitor.txt", (err, stdout, stderr) => { + if (err || stderr) instance.send(0, { err, stderr }); + else instance.send(0, stdout); + }) + }) + instance.on("6", _ => { + exec("sudo tail -n 25 err.txt", (err, stdout, stderr) => { + if (err || stderr) instance.send(0, { err, stderr }); + else instance.send(0, stdout); + }) + }) + instance.on("7", _ => { + instance.send(0, FLOW.deviceStatus); + }) +}; + + +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/RVO38/flow/slack_filter.js b/RVO38/flow/slack_filter.js new file mode 100755 index 0000000..6618523 --- /dev/null +++ b/RVO38/flow/slack_filter.js @@ -0,0 +1,188 @@ +exports.id = 'slack_filter'; +exports.title = 'Slack Filter'; +exports.group = 'Citysys'; +exports.color = '#30E193'; +exports.input = 2; +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 = `
+
+
+
@(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('0', 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']['en']; + 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"] = []; + } + + instance.options.name = FLOW.GLOBALS.settings.rvo_name; + if (instance.options.name) { + instance.status('Running'); + running = true; + } else { + instance.status('Please run options again', 'red'); + running = false; + } + } catch (e) { + instance.error('Citysys connector: ' + e.message); + } + }; + + instance.on('options', instance.reconfigure); + + instance.on("1", _ => { + instance.reconfigure(); + }) +}; diff --git a/RVO38/flow/thermometer.js b/RVO38/flow/thermometer.js new file mode 100755 index 0000000..fc7074d --- /dev/null +++ b/RVO38/flow/thermometer.js @@ -0,0 +1,99 @@ +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 = 5;//minutes +let NUMBER_OF_FAILURES_TO_SEND_ERROR = 13; + +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) => { + + 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); + setTimeout(main, 20000); + }) +}; diff --git a/RVO38/flow/trigger.js b/RVO38/flow/trigger.js new file mode 100755 index 0000000..27545a8 --- /dev/null +++ b/RVO38/flow/trigger.js @@ -0,0 +1,79 @@ +exports.id = 'trigger'; +exports.title = 'Trigger'; +exports.group = 'Inputs'; +exports.color = '#F6BB42'; +exports.click = true; +exports.output = 1; +exports.version = '1.1.0'; +exports.author = 'Martin Smola'; +exports.icon = 'play'; + +exports.html = `
+
@(Data type (String by default))
+
@(Data)
+
Trigger 5s after initialization.
+
@(Useful when there's a need to run certain flow when the app restarts, etc.)
+
`; + +exports.readme = `# Trigger + +- Clicking on the component starts the chain +- Settings allows to set a data-type and a value`; + +exports.install = function(instance) { + + var value; + + instance.on('click', () => instance.send2(value)); + + instance.reconfigure = function() { + var options = instance.options; + value = null; + switch (options.datatype) { + case 'integer': + value = options.data.parseInt2('error'); + value = value === 'error' ? NaN : value; + break; + case 'float': + value = options.data.parseFloat2('error'); + value = value === 'error' ? NaN : value; + break; + case 'date': + options.data = options.data.toString(); + var num = options.data.parseInt('error'); + num === 'error' && (num = options.data.parseDate('error')); + num === 'error' && (num = null); + value = num ? new Date(num).toUTCString() : num; + break; + case 'object': + try { + value = (new Function('return ' + options.data))(); + } catch (e) { + instance.error(e); + } + break; + case 'boolean': + value = options.data.parseBoolean(); + break; + case 'buffer': + try { + value = U.createBuffer(options.data); + } catch (e) { + instance.error(e); + } + break; + case 'string': + default: + value = '' + (options.data || ''); + break; + } + }; + + instance.on('options', instance.reconfigure); + instance.reconfigure(); + + if (instance.options.restart) + setTimeout(function(){ + instance.send2(value); + }, 5000); +}; diff --git a/RVO38/flow/variables.txt b/RVO38/flow/variables.txt new file mode 100755 index 0000000..e69de29 diff --git a/RVO38/flow/virtualwirein.js b/RVO38/flow/virtualwirein.js new file mode 100755 index 0000000..38a4e42 --- /dev/null +++ b/RVO38/flow/virtualwirein.js @@ -0,0 +1,43 @@ +exports.id = 'virtualwirein'; +exports.title = 'Virtual wire in'; +exports.version = '1.0.0'; +exports.author = 'Martin Smola'; +exports.color = '#303E4D'; +exports.icon = 'sign-in'; +exports.input = false; +exports.output = 1; +exports.options = {}; +exports.readme = `# Virtual wire in + +When the wires between the components are mess it's time to use Virtual wire.`; + +exports.html = `
+
@(Wire name)
+
+`; + +exports.install = function(instance) { + + instance.custom.reconfigure = function(options){ + if (instance.options.wirename) { + instance.status(instance.options.wirename); + } else + instance.status('Not configured', 'red'); + }; + + ON('virtualwire', function(wirename, flowdata){ + if (instance.options.wirename && instance.options.wirename === wirename) + instance.send(flowdata); + }); + + instance.on('options', instance.custom.reconfigure); + instance.custom.reconfigure(); +}; diff --git a/RVO38/flow/virtualwireout.js b/RVO38/flow/virtualwireout.js new file mode 100755 index 0000000..94a1e4f --- /dev/null +++ b/RVO38/flow/virtualwireout.js @@ -0,0 +1,41 @@ +exports.id = 'virtualwireout'; +exports.title = 'Virtual wire out'; +exports.version = '1.0.0'; +exports.author = 'Martin Smola'; +exports.color = '#303E4D'; +exports.icon = 'sign-out'; +exports.input = true; +exports.options = {}; +exports.readme = `# Virtual wire out + +When the wires between the components are mess it's time to use Virtual wire.`; + +exports.html = `
+
@(Wire name)
+
+`; + +exports.install = function(instance) { + + instance.custom.reconfigure = function(){ + if (instance.options.wirename) { + instance.status(instance.options.wirename); + } else + instance.status('Not configured', 'red'); + }; + + instance.on('data', function(flowdata) { + EMIT('virtualwire', instance.options.wirename, flowdata); + }); + + instance.on('options', instance.custom.reconfigure); + instance.custom.reconfigure(); +}; diff --git a/RVO38/flow/wsmqttpublish.js b/RVO38/flow/wsmqttpublish.js new file mode 100755 index 0000000..0eba804 --- /dev/null +++ b/RVO38/flow/wsmqttpublish.js @@ -0,0 +1,448 @@ +exports.id = 'wsmqttpublish'; +exports.title = 'WS MQTT publish'; +exports.group = 'MQTT'; +exports.color = '#888600'; +exports.version = '1.0.2'; +exports.icon = 'sign-out'; +exports.input = 2; +exports.output = 3; +exports.options = { host: 'tb-stage.worksys.io', port: 1883, clientid: "", username: "" }; + +exports.html = `
+
+
+
Hostname or IP address (if not empty - setting will override db setting)
+
+
+
Port
+
+
+
+
+
@(Client id)
+
+
+
@(Username)
+
+
+
`; + + +exports.readme = ` +# WS MQTT Publish + +Version 1.0.3. + +Added: +- database collections, +- 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 = { + debug: 0, + rpcCall: 1, + services: 2 +} + +//CONFIG +let createTelemetryBackup = true; +let saveTelemetryOnError = true;//backup_on_failure overrides this value +//------------------------ + +let rollers; +if (createTelemetryBackup) rollers = require('streamroller'); + +const noSqlFileSizeLimit = 4194304;//use 5MB - 4194304 +let insertNoSqlCounter = 0; +let insertBackupNoSqlCounter = 0; +let processingData = false; + +let backup_on_failure = false;//== saveTelemetryOnError - create backup client 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; + +process.on('uncaughtException', function(err) { + + errLogger.error('uncaughtException:', err.message) + errLogger.error(err.stack); + + //TODO + //send to service + + //process.exit(1); +}) + +const nosql = NOSQL('tbdata'); +const nosqlBackup = NOSQL('/backup/tbdata'); + + +exports.install = function(instance) { + + var client; + var opts; + var clientReady = false; + + // wsmqtt status for notification purposes on projects.worksys.io database + let wsmqttName = null; + let sendWsStatusVar = null; + let wsmqtt_status = 'disconnected'; + + 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'; + } + + function sendWsStatus() { + instance.send(SEND_TO.services, { [wsmqttName]: wsmqtt_status }); + } + + + function main() { + if (!FLOW.dbLoaded) return; + + loadSettings(); + clearInterval(sendWsStatus); + sendWsStatusVar = setInterval(sendWsStatus, 180000); + } + + //set opts according to db settings + function loadSettings() { + + if (instance.options.host !== "") { + //override settings from database + var o = instance.options; + opts = { + host: o.host, + port: o.port, + clientId: o.clientid, + username: o.username, + rejectUnauthorized: false, + resubscribe: false + }; + + wsmqttName = getWsmqttName(o.host); + + console.log("wsmqttpublich -> loadSettings from instance.options", instance.options); + } + else { + + const SETTINGS = FLOW.GLOBALS.settings; + backup_on_failure = SETTINGS.backup_on_failure; + saveTelemetryOnError = backup_on_failure; + + restore_from_backup = SETTINGS.restore_from_backup; + restore_backup_wait = SETTINGS.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; + + opts = { + host: mqtt_host, + port: mqtt_port, + keepalive: 10, + clientId: mqtt_clientid, + username: mqtt_username, + rejectUnauthorized: false, + resubscribe: false + }; + + wsmqttName = getWsmqttName(mqtt_host); + } + + connectToTbServer(); + } + + function connectToTbServer() { + 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"); + //monitor.info("MQTT client connected"); + + sendClientError = true; + clientReady = true; + wsmqtt_status = 'connected'; + }); + + client.on('reconnect', function() { + instance.status("Reconnecting", "yellow"); + clientReady = false; + }); + + client.on('message', function(topic, message) { + // message is type of buffer + message = message.toString(); + if (message[0] === '{') { + TRY(function() { + + message = JSON.parse(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 } }); + } + + }, () => instance.debug('MQTT: Error parsing data', message)); + } + + instance.send(SEND_TO.rpcCall, { "topic": topic, "content": message }); + }); + + client.on('close', function() { + clientReady = false; + wsmqtt_status = 'disconnected'; + + instance.status("Disconnected", "red"); + instance.send(SEND_TO.debug, { "message": "Client CLOSE signal received !" }); + }); + + client.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; + wsmqtt_status = 'disconnected'; + }); + + } + + + instance.on("0", _ => { + main(); + }) + + + instance.on('1', function(data) { + + if (clientReady) { + //do we have some data in backup file? if any, process data from database + if (saveTelemetryOnError) { + //read telemetry data and send back to server + if (!processingData) processDataFromDatabase(); + } + + let stringifiedJson = JSON.stringify(data.data); + client.publish("v1/gateway/telemetry", stringifiedJson, { qos: 1 }); + + //backup telemetry + if (createTelemetryBackup) { + data.data.id = UID(); + nosqlBackup.insert(data.data); + + insertBackupNoSqlCounter++; + if (insertBackupNoSqlCounter > 150) { + let options = { compress: true }; + let path = __dirname + "/../databases/backup/tbdata.nosql"; + var stream = new rollers.RollingFileStream(path, noSqlFileSizeLimit, 150, options); + stream.write(""); + stream.end(); + + insertBackupNoSqlCounter = 0; + } + } + + } + 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 (saveTelemetryOnError) { + //create new file from tbdata.nosql, if file size exceeds given limit, and clear tbdata.nosql + makeBackupFromDbFile(); + + //write to tb + data.data.id = UID(); + nosql.insert(data.data); + } + } + }); + + + instance.close = function(done) { + if (clientReady) { + client.end(); + clearInterval(sendWsStatusVar); + } + }; + + + function getDbBackupFileCounter(type) { + var files = fs.readdirSync(__dirname + "/../databases"); + + let counter = 0; + for (var i = 0; i < files.length; i++) { + + if (files[i] == "tbdata.nosql") continue; + + if (files[i].endsWith(".nosql")) { + + let pos = files[i].indexOf("."); + if (pos > -1) { + + let fileCounter = counter; + let firstDigit = files[i].slice(0, pos); + + fileCounter = parseInt(firstDigit); + if (isNaN(fileCounter)) fileCounter = 0; + //console.log("getDbBackupFileCounter digit:", files[i], firstDigit, fileCounter, isNaN(fileCounter), type); + + if (type == "max") { + if (fileCounter > counter) { + counter = fileCounter; + } + } + else if (type == "min") { + if (counter == 0) counter = fileCounter; + + if (fileCounter < counter) { + counter = fileCounter; + } + } + } + } + + } + + if (type == "max") counter++; + + return counter; + } + + const makeBackupFromDbFile = async () => { + + if (!saveTelemetryOnError) return; + + //to avoid large file: tbdata.nosql + + //init value is 0! + if (insertNoSqlCounter > 0) { + --insertNoSqlCounter; + return; + } + + insertNoSqlCounter = 100; + + let source = __dirname + "/../databases/tbdata.nosql"; + + var stats = fs.statSync(source); + var fileSizeInBytes = stats.size; + + if (fileSizeInBytes > noSqlFileSizeLimit) { + + let counter = 1; + counter = getDbBackupFileCounter("max"); + + let destination = __dirname + "/../databases/" + counter + "." + "tbdata.nosql"; + + //make backup file + fs.copyFileSync(source, destination); + //fs.renameSync(p, p + "." + counter); + + //clear tbdata.nosql + fs.writeFileSync(source, ""); + fs.truncateSync(source, 0); + + } + } + + const processDataFromDatabase = async () => { + + if (restore_from_backup <= 0) return; + + //calculate diff + const now = new Date(); + let currentTime = now.getTime(); + let diff = currentTime - lastRestoreTime; + + if ((diff / 1000) < restore_backup_wait) { + //console.log("*********restore_backup_wait", diff, restore_backup_wait); + return; + } + + processingData = true; + + //get filename to process + let counter = getDbBackupFileCounter("min"); + + //we have some backup files + let dataBase = 'tbdata'; + + var nosql; + if (counter == 0) dataBase = 'tbdata'; + else dataBase = counter + "." + 'tbdata'; + + nosql = NOSQL(dataBase); + + //select all data - use limit restore_from_backup + let records = await promisifyBuilder(nosql.find().take(restore_from_backup)); + + for (let i = 0; i < records.length; i++) { + if (clientReady) { + + let item = records[i]; + let id = item.id; + + if (id !== undefined) { + //console.log("------------processDataFromDatabase - remove", id, dataBase, i); + + try { + + let message = JSON.parse(JSON.stringify(item)); + delete message.id; + + client.publish("v1/gateway/telemetry", JSON.stringify(message), { qos: 1 }); + + //remove from database + await promisifyBuilder(nosql.remove().where("id", id)); + + } catch (error) { + //process error + console.log("processDataFromDatabase", error); + } + + } + + } + else { + processingData = false; + return; + } + } + + if (records.length > 0) { + //clean backup file + if (counter > 0) nosql.clean(); + } + + //no data in db, remove + if (records.length == 0) { + if (counter > 0) nosql.drop(); + } + + const d = new Date(); + lastRestoreTime = d.getTime(); + + processingData = false; + + } + + instance.on('options', main); + //instance.reconfigure(); +}; diff --git a/RVO38/monitor.txt b/RVO38/monitor.txt new file mode 100755 index 0000000..ee84c92 --- /dev/null +++ b/RVO38/monitor.txt @@ -0,0 +1,282 @@ +[2025-10-09T19:02:27.504] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-09T19:02:32.908] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-09T19:02:32.915] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-09T19:02:32.917] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-09T19:02:32.917] [INFO] monitorLogs - profile: { + 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: 11, + dusk_lux_sensor_value: 11, + 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 +} +[2025-10-09T19:02:32.923] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T19:02:32.924] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-10-10T05:32:00.923Z +[2025-10-09T19:02:32.926] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-10-10T16:45:00.926Z +[2025-10-09T19:02:32.927] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T19:02:32.929] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-10-09T19:02:32.930] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-09T19:02:32.930] [INFO] monitorLogs - profile: { + 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: 11, + dusk_lux_sensor_value: 11, + 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 +} +[2025-10-09T19:02:32.933] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T19:02:32.934] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-10-10T05:32:00.934Z +[2025-10-09T19:02:32.936] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-10-10T16:45:00.935Z +[2025-10-09T19:02:32.936] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T19:02:32.938] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-10-09T19:02:32.939] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-09T19:02:32.939] [INFO] monitorLogs - profile: { + 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: 11, + dusk_lux_sensor_value: 11, + 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 +} +[2025-10-09T19:02:32.942] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T19:02:32.943] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-10-10T05:32:00.943Z +[2025-10-09T19:02:32.945] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-10-10T16:45:00.944Z +[2025-10-09T19:02:32.946] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T19:02:32.947] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-10-09T19:02:32.948] [INFO] monitorLogs - buildTasks: profile for line 4 +[2025-10-09T19:02:32.949] [INFO] monitorLogs - profile: { + 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: 11, + dusk_lux_sensor_value: 11, + 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 +} +[2025-10-09T19:02:32.952] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T19:02:32.952] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 4 2025-10-10T05:32:00.952Z +[2025-10-09T19:02:32.953] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 4 2025-10-10T16:45:00.953Z +[2025-10-09T19:02:32.954] [INFO] monitorLogs - -->time_points final 4 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T19:02:32.956] [INFO] monitorLogs - -->currentValue for relay 4 1 +[2025-10-09T19:02:32.979] [INFO] monitorLogs - tasks created: 941 +[2025-10-09T19:02:32.982] [INFO] monitorLogs - -->FLOW bol spustený pE5X8NQPaow6vlOZxk6ajg0q42ezGBMyWgDVjR3L 2025-08-08 +[2025-10-09T19:02:37.989] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-10T03:02:35.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-10 03:02:35 +[2025-10-10T06:50:15.588] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-10T06:50:15.593] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-10T06:50:15.595] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-10T06:50:15.597] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-10-10T18:22:36.664] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-10T18:22:36.694] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-10T18:22:36.696] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-10T18:22:36.698] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-10-11T03:02:36.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-11 03:02:36 +[2025-10-11T06:52:41.048] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-11T06:52:41.054] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-11T06:52:41.056] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-11T06:52:41.057] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-10-11T18:25:01.043] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-11T18:25:01.046] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-11T18:25:01.049] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-11T18:25:01.051] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-10-12T03:02:38.044] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-12 03:02:38 +[2025-10-12T06:50:04.048] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-12T06:50:04.052] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-12T06:50:04.054] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-12T06:50:04.056] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-10-12T18:22:23.978] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-12T18:22:23.981] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-12T18:22:23.983] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-12T18:22:23.984] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-10-13T03:02:40.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-13 03:02:40 +[2025-10-13T06:44:57.462] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-13T06:44:57.468] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-13T06:44:57.470] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-13T06:44:57.472] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-10-13T18:24:50.081] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-13T18:24:50.090] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-13T18:24:50.093] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-13T18:24:50.096] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-10-14T03:02:41.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-14 03:02:41 +[2025-10-14T06:47:21.770] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-14T06:47:21.776] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-14T06:47:21.778] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-14T06:47:21.781] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-10-14T18:19:42.608] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-14T18:19:42.615] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-14T18:19:42.617] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-14T18:19:42.619] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-10-15T03:02:42.013] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-15 03:02:42 +[2025-10-15T06:52:17.475] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-15T06:52:17.480] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-15T06:52:17.482] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-15T06:52:17.484] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-10-15T14:30:49.528] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-15T14:30:54.886] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-15T14:30:54.891] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-15T14:30:54.892] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-15T14:30:54.892] [INFO] monitorLogs - profile: { + 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: 11, + dusk_lux_sensor_value: 11, + 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 +} +[2025-10-15T14:30:54.897] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-15T14:30:54.898] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-10-16T05:41:00.897Z +[2025-10-15T14:30:54.899] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-10-15T16:33:00.899Z +[2025-10-15T14:30:54.900] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:41', name: 'luxOff' }, + { value: 1, start_time: '18:33', name: 'luxOn' } +] +[2025-10-15T14:30:54.901] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-10-15T14:30:54.902] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-15T14:30:54.903] [INFO] monitorLogs - profile: { + 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: 11, + dusk_lux_sensor_value: 11, + 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 +} +[2025-10-15T14:30:54.905] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-15T14:30:54.906] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-10-16T05:41:00.906Z +[2025-10-15T14:30:54.907] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-10-15T16:33:00.906Z +[2025-10-15T14:30:54.907] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:41', name: 'luxOff' }, + { value: 1, start_time: '18:33', name: 'luxOn' } +] +[2025-10-15T14:30:54.908] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-10-15T14:30:54.909] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-15T14:30:54.909] [INFO] monitorLogs - profile: { + 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: 11, + dusk_lux_sensor_value: 11, + 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 +} +[2025-10-15T14:30:54.912] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-15T14:30:54.912] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-10-16T05:41:00.912Z +[2025-10-15T14:30:54.913] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-10-15T16:33:00.913Z +[2025-10-15T14:30:54.914] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:41', name: 'luxOff' }, + { value: 1, start_time: '18:33', name: 'luxOn' } +] +[2025-10-15T14:30:54.915] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-10-15T14:30:54.915] [INFO] monitorLogs - buildTasks: profile for line 4 +[2025-10-15T14:30:54.916] [INFO] monitorLogs - profile: { + 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: 11, + dusk_lux_sensor_value: 11, + 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 +} +[2025-10-15T14:30:54.918] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-15T14:30:54.919] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 4 2025-10-16T05:41:00.919Z +[2025-10-15T14:30:54.920] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 4 2025-10-15T16:33:00.919Z +[2025-10-15T14:30:54.920] [INFO] monitorLogs - -->time_points final 4 [ + { value: 0, start_time: '7:41', name: 'luxOff' }, + { value: 1, start_time: '18:33', name: 'luxOn' } +] +[2025-10-15T14:30:54.921] [INFO] monitorLogs - -->currentValue for relay 4 0 +[2025-10-15T14:30:54.944] [INFO] monitorLogs - tasks created: 941 +[2025-10-15T14:30:54.946] [INFO] monitorLogs - -->FLOW bol spustený pE5X8NQPaow6vlOZxk6ajg0q42ezGBMyWgDVjR3L 2025-10-08 +[2025-10-15T14:30:59.954] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-15T18:16:57.104] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-15T18:16:57.110] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-15T18:16:57.112] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-15T18:16:57.115] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor diff --git a/RVO38/package-lock.json b/RVO38/package-lock.json new file mode 100755 index 0000000..3c5c1ba --- /dev/null +++ b/RVO38/package-lock.json @@ -0,0 +1,2139 @@ +{ + "name": "emptyproject", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "emptyproject", + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "bitwise": "^2.1.0", + "easy-crc": "0.0.2", + "jsmodbus": "^4.0.6", + "log4js": "^6.3.0", + "moment": "^2.30.1", + "mqtt": "^4.2.6", + "nodemailer": "^6.9.7", + "serialport": "^9.2.8", + "total.js": "^3.4.13" + } + }, + "node_modules/@serialport/binding-abstract": { + "version": "9.2.3", + "resolved": "https://registry.npmjs.org/@serialport/binding-abstract/-/binding-abstract-9.2.3.tgz", + "integrity": "sha512-cQs9tbIlG3P0IrOWyVirqlhWuJ7Ms2Zh9m2108z6Y5UW/iVj6wEOiW8EmK9QX9jmJXYllE7wgGgvVozP5oCj3w==", + "dependencies": { + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/binding-mock": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/binding-mock/-/binding-mock-9.2.4.tgz", + "integrity": "sha512-dpEhACCs44oQhh6ajJfJdvQdK38Vq0N4W6iD/gdplglDCK7qXRQCMUjJIeKdS/HSEiWkC3bwumUhUufdsOyT4g==", + "dependencies": { + "@serialport/binding-abstract": "9.2.3", + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/bindings": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/@serialport/bindings/-/bindings-9.2.8.tgz", + "integrity": "sha512-hSLxTe0tADZ3LMMGwvEJWOC/TaFQTyPeFalUCsJ1lSQ0k6bPF04JwrtB/C81GetmDBTNRY0GlD0SNtKCc7Dr5g==", + "hasInstallScript": true, + "dependencies": { + "@serialport/binding-abstract": "9.2.3", + "@serialport/parser-readline": "9.2.4", + "bindings": "^1.5.0", + "debug": "^4.3.2", + "nan": "^2.15.0", + "prebuild-install": "^7.0.0" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-byte-length": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-byte-length/-/parser-byte-length-9.2.4.tgz", + "integrity": "sha512-sQD/iw4ZMU3xW9PLi0/GlvU6Y623jGeWecbMkO7izUo/6P7gtfv1c9ikd5h0kwL8AoAOpQA1lxdHIKox+umBUg==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-cctalk": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-cctalk/-/parser-cctalk-9.2.4.tgz", + "integrity": "sha512-T4TU5vQMwmo9AB3gQLFDWbfJXlW5jd9guEsB/nqKjFHTv0FXPdZ7DQ2TpSp8RnHWxU3GX6kYTaDO20BKzc8GPQ==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-delimiter": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-delimiter/-/parser-delimiter-9.2.4.tgz", + "integrity": "sha512-4nvTAoYAgkxFiXrkI+3CA49Yd43CODjeszh89EK+I9c8wOZ+etZduRCzINYPiy26g7zO+GRAb9FoPCsY+sYcbQ==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-inter-byte-timeout": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-inter-byte-timeout/-/parser-inter-byte-timeout-9.2.4.tgz", + "integrity": "sha512-SOAdvr0oBQIOCXX198hiTlxs4JTKg9j5piapw5tNq52fwDOWdbYrFneT/wN04UTMKaDrJuEvXq6T4rv4j7nJ5A==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-readline": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-readline/-/parser-readline-9.2.4.tgz", + "integrity": "sha512-Z1/qrZTQUVhNSJP1hd9YfDvq0o7d87rNwAjjRKbVpa7Qi51tG5BnKt43IV3NFMyBlVcRe0rnIb3tJu57E0SOwg==", + "dependencies": { + "@serialport/parser-delimiter": "9.2.4" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-ready": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-ready/-/parser-ready-9.2.4.tgz", + "integrity": "sha512-Pyi94Itjl6qAURwIZr/gmZpMAyTmKXThm6vL5DoAWGQjcRHWB0gwv2TY2v7N+mQLJYUKU3cMnvnATXxHm7xjxw==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-regex": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-regex/-/parser-regex-9.2.4.tgz", + "integrity": "sha512-sI/cVvPOYz+Dbv4ZdnW16qAwvXiFf/1pGASQdbveRTlgJDdz7sRNlCBifzfTN2xljwvCTZYqiudKvDdC1TepRQ==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/stream": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/stream/-/stream-9.2.4.tgz", + "integrity": "sha512-bLye8Ub4vUFQGmkh8qEqehr7SE7EJs2yDs0h9jzuL5oKi+F34CFmWkEErO8GAOQ8YNn7p6b3GxUgs+0BrHHDZQ==", + "dependencies": { + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "node_modules/are-we-there-yet": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", + "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/base64-js": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", + "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==" + }, + "node_modules/bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "dependencies": { + "file-uri-to-path": "1.0.0" + } + }, + "node_modules/bitwise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/bitwise/-/bitwise-2.1.0.tgz", + "integrity": "sha512-XKgAhMXCh4H/3oNwAHAsAO0iC89s9cOiumgYwSHjSobGWxYjv62YhkL9QEdvGP151xypCtMlAfKK79GEcd2eRQ==" + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/bl/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/buffer": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz", + "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==", + "dependencies": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + }, + "node_modules/buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" + }, + "node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, + "node_modules/code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/commist": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/commist/-/commist-1.1.0.tgz", + "integrity": "sha512-rraC8NXWOEjhADbZe9QBNzLAN5Q3fsTPQtBV+fEVj6xKIgDgNiEVE6ZNfHpZOqfQ21YUzfVNUXLOEZquYvQPPg==", + "dependencies": { + "leven": "^2.1.0", + "minimist": "^1.1.0" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "node_modules/concat-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", + "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", + "engines": [ + "node >= 6.0" + ], + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.0.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/concat-stream/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" + }, + "node_modules/core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "node_modules/crc": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/crc/-/crc-3.4.0.tgz", + "integrity": "sha512-ycVC2+4/DLgXXq7QweYi2znhqDuZz6P5TQXnkQo8v15XY/5p/IWeZwsSE31Ifo8w15b8TWLsqhXOjXyilHuQxw==" + }, + "node_modules/date-format": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.11.tgz", + "integrity": "sha512-VS20KRyorrbMCQmpdl2hg5KaOUsda1RbnsJg461FfrcyCUg+pkd0b40BSW4niQyTheww4DBXQnS7HwSrKkipLw==", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" + }, + "node_modules/detect-libc": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz", + "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==", + "engines": { + "node": ">=8" + } + }, + "node_modules/duplexify": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.2.tgz", + "integrity": "sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw==", + "dependencies": { + "end-of-stream": "^1.4.1", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1", + "stream-shift": "^1.0.0" + } + }, + "node_modules/duplexify/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/easy-crc": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/easy-crc/-/easy-crc-0.0.2.tgz", + "integrity": "sha512-h6eqIdhJRe0p271/xZJbM/0klCi13mW5IB7ZEzEGH11yV4QXWAkD4yPErz0fXdhFrd6sZ4Q1k5Iky2kMsMNePw==" + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" + }, + "node_modules/flatted": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", + "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==" + }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, + "node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "node_modules/gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha512-14x4kjc6lkD3ltw589k0NrPD6cCNTD6CWoVUNpB85+DrtONoZn+Rug6xZU5RvSC4+TZPxA5AnBibQYAvZn41Hg==", + "dependencies": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "node_modules/github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==" + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" + }, + "node_modules/has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" + }, + "node_modules/help-me": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/help-me/-/help-me-3.0.0.tgz", + "integrity": "sha512-hx73jClhyk910sidBB7ERlnhMlFsJJIBqSVMFDwPN8o2v9nmp5KgLq1Xz1Bf1fCMMZ6mPrX159iG0VLy/fPMtQ==", + "dependencies": { + "glob": "^7.1.6", + "readable-stream": "^3.6.0" + } + }, + "node_modules/help-me/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, + "node_modules/is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==", + "dependencies": { + "number-is-nan": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "node_modules/js-sdsl": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz", + "integrity": "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/js-sdsl" + } + }, + "node_modules/jsmodbus": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/jsmodbus/-/jsmodbus-4.0.6.tgz", + "integrity": "sha512-gCmjoaERErK5Rn9Lu/BN07fY13MoWV7JKgGzrnkPlQPdPxYcwDhLtYcmpFFpZ4J9NPZZBSezi1UkLZO/DnNppA==", + "dependencies": { + "crc": "3.4.0", + "debug": "^3.1.0" + }, + "bin": { + "jsmodbus": "bin/jsmodbus.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/jsmodbus/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/leven": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", + "integrity": "sha1-wuep93IJTe6dNCAq6KzORoeHVYA=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/log4js": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.5.2.tgz", + "integrity": "sha512-DXtpNtt+KDOMT7RHUDIur/WsSA3rntlUh9Zg4XCdV42wUuMmbFkl38+LZ92Z5QvQA7mD5kAVkLiBSEH/tvUB8A==", + "dependencies": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "flatted": "^3.2.5", + "rfdc": "^1.3.0", + "streamroller": "^3.1.1" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" + }, + "node_modules/moment": { + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", + "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==", + "engines": { + "node": "*" + } + }, + "node_modules/mqtt": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/mqtt/-/mqtt-4.3.7.tgz", + "integrity": "sha512-ew3qwG/TJRorTz47eW46vZ5oBw5MEYbQZVaEji44j5lAUSQSqIEoul7Kua/BatBW0H0kKQcC9kwUHa1qzaWHSw==", + "dependencies": { + "commist": "^1.0.0", + "concat-stream": "^2.0.0", + "debug": "^4.1.1", + "duplexify": "^4.1.1", + "help-me": "^3.0.0", + "inherits": "^2.0.3", + "lru-cache": "^6.0.0", + "minimist": "^1.2.5", + "mqtt-packet": "^6.8.0", + "number-allocator": "^1.0.9", + "pump": "^3.0.0", + "readable-stream": "^3.6.0", + "reinterval": "^1.1.0", + "rfdc": "^1.3.0", + "split2": "^3.1.0", + "ws": "^7.5.5", + "xtend": "^4.0.2" + }, + "bin": { + "mqtt": "bin/mqtt.js", + "mqtt_pub": "bin/pub.js", + "mqtt_sub": "bin/sub.js" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/mqtt-packet": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/mqtt-packet/-/mqtt-packet-6.10.0.tgz", + "integrity": "sha512-ja8+mFKIHdB1Tpl6vac+sktqy3gA8t9Mduom1BA75cI+R9AHnZOiaBQwpGiWnaVJLDGRdNhQmFaAqd7tkKSMGA==", + "dependencies": { + "bl": "^4.0.2", + "debug": "^4.1.1", + "process-nextick-args": "^2.0.1" + } + }, + "node_modules/mqtt/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/nan": { + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.16.0.tgz", + "integrity": "sha512-UdAqHyFngu7TfQKsCBgAA6pWDkT8MAO7d0jyOecVhN5354xbLqdn8mV9Tat9gepAupm0bt2DbeaSC8vS52MuFA==" + }, + "node_modules/napi-build-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", + "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==" + }, + "node_modules/node-abi": { + "version": "3.22.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.22.0.tgz", + "integrity": "sha512-u4uAs/4Zzmp/jjsD9cyFYDXeISfUWaAVWshPmDZOFOv4Xl4SbzTXm53I04C2uRueYJ+0t5PEtLH/owbn2Npf/w==", + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/nodemailer": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.7.tgz", + "integrity": "sha512-rUtR77ksqex/eZRLmQ21LKVH5nAAsVicAtAYudK7JgwenEDZ0UIQ1adUGqErz7sMkWYxWTTU1aeP2Jga6WQyJw==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "dependencies": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "node_modules/number-allocator": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/number-allocator/-/number-allocator-1.0.14.tgz", + "integrity": "sha512-OrL44UTVAvkKdOdRQZIJpLkAdjXGTRda052sN4sO77bKEzYYqWKMBjQvrJFzqygI99gL6Z4u2xctPW1tB8ErvA==", + "dependencies": { + "debug": "^4.3.1", + "js-sdsl": "4.3.0" + } + }, + "node_modules/number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/prebuild-install": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.0.tgz", + "integrity": "sha512-CNcMgI1xBypOyGqjp3wOc8AAo1nMhZS3Cwd3iHIxOdAUbb+YxdNuM4Z5iIrZ8RLvOsf3F3bl7b7xGq6DjQoNYA==", + "dependencies": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^1.0.1", + "node-abi": "^3.3.0", + "npmlog": "^4.0.1", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + }, + "bin": { + "prebuild-install": "bin.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/reinterval": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reinterval/-/reinterval-1.1.0.tgz", + "integrity": "sha1-M2Hs+jymwYKDOA3Qu5VG85D17Oc=" + }, + "node_modules/rfdc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==" + }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/serialport": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/serialport/-/serialport-9.2.8.tgz", + "integrity": "sha512-FsWpMQgSJxi93JgWl5xM1f9/Z8IjRJuaUEoHqLf8FPBLw7gMhInuHOBhI2onQufWIYPGTz3H3oGcu1nCaK1EfA==", + "dependencies": { + "@serialport/binding-mock": "9.2.4", + "@serialport/bindings": "9.2.8", + "@serialport/parser-byte-length": "9.2.4", + "@serialport/parser-cctalk": "9.2.4", + "@serialport/parser-delimiter": "9.2.4", + "@serialport/parser-inter-byte-timeout": "9.2.4", + "@serialport/parser-readline": "9.2.4", + "@serialport/parser-ready": "9.2.4", + "@serialport/parser-regex": "9.2.4", + "@serialport/stream": "9.2.4", + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "node_modules/split2": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", + "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", + "dependencies": { + "readable-stream": "^3.0.0" + } + }, + "node_modules/split2/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==" + }, + "node_modules/streamroller": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.1.1.tgz", + "integrity": "sha512-iPhtd9unZ6zKdWgMeYGfSBuqCngyJy1B/GPi/lTpwGpa3bajuX30GjUVd0/Tn/Xhg0mr4DOSENozz9Y06qyonQ==", + "dependencies": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "fs-extra": "^10.1.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dependencies": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/tar-fs": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "dependencies": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tar-stream/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/total.js": { + "version": "3.4.13", + "resolved": "https://registry.npmjs.org/total.js/-/total.js-3.4.13.tgz", + "integrity": "sha512-lAH4gEixlPFbrE3xfKADAcHfO79IFq2wKa9GTsrgRzIR5MTg3mNH7+4IxvX1pK8faoYb/0oYSJ1YTsAa5hIFFQ==", + "bin": { + "total": "bin/totaljs", + "total.js": "bin/totaljs", + "totaljs": "bin/totaljs", + "totalpackage": "bin/tpm", + "tpm": "bin/tpm" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, + "node_modules/universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "node_modules/wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "node_modules/ws": { + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } + }, + "dependencies": { + "@serialport/binding-abstract": { + "version": "9.2.3", + "resolved": "https://registry.npmjs.org/@serialport/binding-abstract/-/binding-abstract-9.2.3.tgz", + "integrity": "sha512-cQs9tbIlG3P0IrOWyVirqlhWuJ7Ms2Zh9m2108z6Y5UW/iVj6wEOiW8EmK9QX9jmJXYllE7wgGgvVozP5oCj3w==", + "requires": { + "debug": "^4.3.2" + } + }, + "@serialport/binding-mock": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/binding-mock/-/binding-mock-9.2.4.tgz", + "integrity": "sha512-dpEhACCs44oQhh6ajJfJdvQdK38Vq0N4W6iD/gdplglDCK7qXRQCMUjJIeKdS/HSEiWkC3bwumUhUufdsOyT4g==", + "requires": { + "@serialport/binding-abstract": "9.2.3", + "debug": "^4.3.2" + } + }, + "@serialport/bindings": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/@serialport/bindings/-/bindings-9.2.8.tgz", + "integrity": "sha512-hSLxTe0tADZ3LMMGwvEJWOC/TaFQTyPeFalUCsJ1lSQ0k6bPF04JwrtB/C81GetmDBTNRY0GlD0SNtKCc7Dr5g==", + "requires": { + "@serialport/binding-abstract": "9.2.3", + "@serialport/parser-readline": "9.2.4", + "bindings": "^1.5.0", + "debug": "^4.3.2", + "nan": "^2.15.0", + "prebuild-install": "^7.0.0" + } + }, + "@serialport/parser-byte-length": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-byte-length/-/parser-byte-length-9.2.4.tgz", + "integrity": "sha512-sQD/iw4ZMU3xW9PLi0/GlvU6Y623jGeWecbMkO7izUo/6P7gtfv1c9ikd5h0kwL8AoAOpQA1lxdHIKox+umBUg==" + }, + "@serialport/parser-cctalk": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-cctalk/-/parser-cctalk-9.2.4.tgz", + "integrity": "sha512-T4TU5vQMwmo9AB3gQLFDWbfJXlW5jd9guEsB/nqKjFHTv0FXPdZ7DQ2TpSp8RnHWxU3GX6kYTaDO20BKzc8GPQ==" + }, + "@serialport/parser-delimiter": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-delimiter/-/parser-delimiter-9.2.4.tgz", + "integrity": "sha512-4nvTAoYAgkxFiXrkI+3CA49Yd43CODjeszh89EK+I9c8wOZ+etZduRCzINYPiy26g7zO+GRAb9FoPCsY+sYcbQ==" + }, + "@serialport/parser-inter-byte-timeout": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-inter-byte-timeout/-/parser-inter-byte-timeout-9.2.4.tgz", + "integrity": "sha512-SOAdvr0oBQIOCXX198hiTlxs4JTKg9j5piapw5tNq52fwDOWdbYrFneT/wN04UTMKaDrJuEvXq6T4rv4j7nJ5A==" + }, + "@serialport/parser-readline": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-readline/-/parser-readline-9.2.4.tgz", + "integrity": "sha512-Z1/qrZTQUVhNSJP1hd9YfDvq0o7d87rNwAjjRKbVpa7Qi51tG5BnKt43IV3NFMyBlVcRe0rnIb3tJu57E0SOwg==", + "requires": { + "@serialport/parser-delimiter": "9.2.4" + } + }, + "@serialport/parser-ready": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-ready/-/parser-ready-9.2.4.tgz", + "integrity": "sha512-Pyi94Itjl6qAURwIZr/gmZpMAyTmKXThm6vL5DoAWGQjcRHWB0gwv2TY2v7N+mQLJYUKU3cMnvnATXxHm7xjxw==" + }, + "@serialport/parser-regex": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-regex/-/parser-regex-9.2.4.tgz", + "integrity": "sha512-sI/cVvPOYz+Dbv4ZdnW16qAwvXiFf/1pGASQdbveRTlgJDdz7sRNlCBifzfTN2xljwvCTZYqiudKvDdC1TepRQ==" + }, + "@serialport/stream": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/stream/-/stream-9.2.4.tgz", + "integrity": "sha512-bLye8Ub4vUFQGmkh8qEqehr7SE7EJs2yDs0h9jzuL5oKi+F34CFmWkEErO8GAOQ8YNn7p6b3GxUgs+0BrHHDZQ==", + "requires": { + "debug": "^4.3.2" + } + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==" + }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "are-we-there-yet": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", + "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "base64-js": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", + "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==" + }, + "bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "requires": { + "file-uri-to-path": "1.0.0" + } + }, + "bitwise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/bitwise/-/bitwise-2.1.0.tgz", + "integrity": "sha512-XKgAhMXCh4H/3oNwAHAsAO0iC89s9cOiumgYwSHjSobGWxYjv62YhkL9QEdvGP151xypCtMlAfKK79GEcd2eRQ==" + }, + "bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "requires": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "buffer": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz", + "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==", + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" + }, + "chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==" + }, + "commist": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/commist/-/commist-1.1.0.tgz", + "integrity": "sha512-rraC8NXWOEjhADbZe9QBNzLAN5Q3fsTPQtBV+fEVj6xKIgDgNiEVE6ZNfHpZOqfQ21YUzfVNUXLOEZquYvQPPg==", + "requires": { + "leven": "^2.1.0", + "minimist": "^1.1.0" + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "concat-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", + "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.0.2", + "typedarray": "^0.0.6" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "crc": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/crc/-/crc-3.4.0.tgz", + "integrity": "sha512-ycVC2+4/DLgXXq7QweYi2znhqDuZz6P5TQXnkQo8v15XY/5p/IWeZwsSE31Ifo8w15b8TWLsqhXOjXyilHuQxw==" + }, + "date-format": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.11.tgz", + "integrity": "sha512-VS20KRyorrbMCQmpdl2hg5KaOUsda1RbnsJg461FfrcyCUg+pkd0b40BSW4niQyTheww4DBXQnS7HwSrKkipLw==" + }, + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "requires": { + "ms": "2.1.2" + } + }, + "decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "requires": { + "mimic-response": "^3.1.0" + } + }, + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==" + }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" + }, + "detect-libc": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz", + "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==" + }, + "duplexify": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.2.tgz", + "integrity": "sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw==", + "requires": { + "end-of-stream": "^1.4.1", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1", + "stream-shift": "^1.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "easy-crc": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/easy-crc/-/easy-crc-0.0.2.tgz", + "integrity": "sha512-h6eqIdhJRe0p271/xZJbM/0klCi13mW5IB7ZEzEGH11yV4QXWAkD4yPErz0fXdhFrd6sZ4Q1k5Iky2kMsMNePw==" + }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "requires": { + "once": "^1.4.0" + } + }, + "expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==" + }, + "file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" + }, + "flatted": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", + "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==" + }, + "fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, + "fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha512-14x4kjc6lkD3ltw589k0NrPD6cCNTD6CWoVUNpB85+DrtONoZn+Rug6xZU5RvSC4+TZPxA5AnBibQYAvZn41Hg==", + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==" + }, + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" + }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" + }, + "help-me": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/help-me/-/help-me-3.0.0.tgz", + "integrity": "sha512-hx73jClhyk910sidBB7ERlnhMlFsJJIBqSVMFDwPN8o2v9nmp5KgLq1Xz1Bf1fCMMZ6mPrX159iG0VLy/fPMtQ==", + "requires": { + "glob": "^7.1.6", + "readable-stream": "^3.6.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==", + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "js-sdsl": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz", + "integrity": "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==" + }, + "jsmodbus": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/jsmodbus/-/jsmodbus-4.0.6.tgz", + "integrity": "sha512-gCmjoaERErK5Rn9Lu/BN07fY13MoWV7JKgGzrnkPlQPdPxYcwDhLtYcmpFFpZ4J9NPZZBSezi1UkLZO/DnNppA==", + "requires": { + "crc": "3.4.0", + "debug": "^3.1.0" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "requires": { + "ms": "^2.1.1" + } + } + } + }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, + "leven": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", + "integrity": "sha1-wuep93IJTe6dNCAq6KzORoeHVYA=" + }, + "log4js": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.5.2.tgz", + "integrity": "sha512-DXtpNtt+KDOMT7RHUDIur/WsSA3rntlUh9Zg4XCdV42wUuMmbFkl38+LZ92Z5QvQA7mD5kAVkLiBSEH/tvUB8A==", + "requires": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "flatted": "^3.2.5", + "rfdc": "^1.3.0", + "streamroller": "^3.1.1" + } + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "requires": { + "yallist": "^4.0.0" + } + }, + "mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==" + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==" + }, + "mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" + }, + "moment": { + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", + "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==" + }, + "mqtt": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/mqtt/-/mqtt-4.3.7.tgz", + "integrity": "sha512-ew3qwG/TJRorTz47eW46vZ5oBw5MEYbQZVaEji44j5lAUSQSqIEoul7Kua/BatBW0H0kKQcC9kwUHa1qzaWHSw==", + "requires": { + "commist": "^1.0.0", + "concat-stream": "^2.0.0", + "debug": "^4.1.1", + "duplexify": "^4.1.1", + "help-me": "^3.0.0", + "inherits": "^2.0.3", + "lru-cache": "^6.0.0", + "minimist": "^1.2.5", + "mqtt-packet": "^6.8.0", + "number-allocator": "^1.0.9", + "pump": "^3.0.0", + "readable-stream": "^3.6.0", + "reinterval": "^1.1.0", + "rfdc": "^1.3.0", + "split2": "^3.1.0", + "ws": "^7.5.5", + "xtend": "^4.0.2" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "mqtt-packet": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/mqtt-packet/-/mqtt-packet-6.10.0.tgz", + "integrity": "sha512-ja8+mFKIHdB1Tpl6vac+sktqy3gA8t9Mduom1BA75cI+R9AHnZOiaBQwpGiWnaVJLDGRdNhQmFaAqd7tkKSMGA==", + "requires": { + "bl": "^4.0.2", + "debug": "^4.1.1", + "process-nextick-args": "^2.0.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "nan": { + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.16.0.tgz", + "integrity": "sha512-UdAqHyFngu7TfQKsCBgAA6pWDkT8MAO7d0jyOecVhN5354xbLqdn8mV9Tat9gepAupm0bt2DbeaSC8vS52MuFA==" + }, + "napi-build-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", + "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==" + }, + "node-abi": { + "version": "3.22.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.22.0.tgz", + "integrity": "sha512-u4uAs/4Zzmp/jjsD9cyFYDXeISfUWaAVWshPmDZOFOv4Xl4SbzTXm53I04C2uRueYJ+0t5PEtLH/owbn2Npf/w==", + "requires": { + "semver": "^7.3.5" + } + }, + "nodemailer": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.7.tgz", + "integrity": "sha512-rUtR77ksqex/eZRLmQ21LKVH5nAAsVicAtAYudK7JgwenEDZ0UIQ1adUGqErz7sMkWYxWTTU1aeP2Jga6WQyJw==" + }, + "npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "number-allocator": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/number-allocator/-/number-allocator-1.0.14.tgz", + "integrity": "sha512-OrL44UTVAvkKdOdRQZIJpLkAdjXGTRda052sN4sO77bKEzYYqWKMBjQvrJFzqygI99gL6Z4u2xctPW1tB8ErvA==", + "requires": { + "debug": "^4.3.1", + "js-sdsl": "4.3.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==" + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==" + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==" + }, + "prebuild-install": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.0.tgz", + "integrity": "sha512-CNcMgI1xBypOyGqjp3wOc8AAo1nMhZS3Cwd3iHIxOdAUbb+YxdNuM4Z5iIrZ8RLvOsf3F3bl7b7xGq6DjQoNYA==", + "requires": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^1.0.1", + "node-abi": "^3.3.0", + "npmlog": "^4.0.1", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + } + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + } + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "reinterval": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reinterval/-/reinterval-1.1.0.tgz", + "integrity": "sha1-M2Hs+jymwYKDOA3Qu5VG85D17Oc=" + }, + "rfdc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==" + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "requires": { + "lru-cache": "^6.0.0" + } + }, + "serialport": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/serialport/-/serialport-9.2.8.tgz", + "integrity": "sha512-FsWpMQgSJxi93JgWl5xM1f9/Z8IjRJuaUEoHqLf8FPBLw7gMhInuHOBhI2onQufWIYPGTz3H3oGcu1nCaK1EfA==", + "requires": { + "@serialport/binding-mock": "9.2.4", + "@serialport/bindings": "9.2.8", + "@serialport/parser-byte-length": "9.2.4", + "@serialport/parser-cctalk": "9.2.4", + "@serialport/parser-delimiter": "9.2.4", + "@serialport/parser-inter-byte-timeout": "9.2.4", + "@serialport/parser-readline": "9.2.4", + "@serialport/parser-ready": "9.2.4", + "@serialport/parser-regex": "9.2.4", + "@serialport/stream": "9.2.4", + "debug": "^4.3.2" + } + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==" + }, + "simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "requires": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "split2": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", + "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", + "requires": { + "readable-stream": "^3.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==" + }, + "streamroller": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.1.1.tgz", + "integrity": "sha512-iPhtd9unZ6zKdWgMeYGfSBuqCngyJy1B/GPi/lTpwGpa3bajuX30GjUVd0/Tn/Xhg0mr4DOSENozz9Y06qyonQ==", + "requires": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "fs-extra": "^10.1.0" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" + }, + "tar-fs": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "requires": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "requires": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "total.js": { + "version": "3.4.13", + "resolved": "https://registry.npmjs.org/total.js/-/total.js-3.4.13.tgz", + "integrity": "sha512-lAH4gEixlPFbrE3xfKADAcHfO79IFq2wKa9GTsrgRzIR5MTg3mNH7+4IxvX1pK8faoYb/0oYSJ1YTsAa5hIFFQ==" + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, + "universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==" + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "requires": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "ws": { + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "requires": {} + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } + } +} diff --git a/RVO38/package.json b/RVO38/package.json new file mode 100755 index 0000000..7f7c795 --- /dev/null +++ b/RVO38/package.json @@ -0,0 +1,30 @@ +{ + "name": "emptyproject", + "description": "Total.js empty project.", + "version": "1.0.0", + "main": "debug.js", + "dependencies": { + "bitwise": "^2.1.0", + "easy-crc": "0.0.2", + "jsmodbus": "^4.0.6", + "log4js": "^6.3.0", + "moment": "^2.30.1", + "mqtt": "^4.2.6", + "nodemailer": "^6.9.7", + "serialport": "^9.2.8", + "total.js": "^3.4.13" + }, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "https://github.com/totaljs/emptyproject-flow" + }, + "keywords": [ + "empty", + "project" + ], + "author": "Peter Širka", + "license": "MIT" +} diff --git a/RVO38/release.js b/RVO38/release.js new file mode 100755 index 0000000..02d52ff --- /dev/null +++ b/RVO38/release.js @@ -0,0 +1,15 @@ +// =================================================== +// FOR PRODUCTION +// Total.js - framework for Node.js platform +// https://www.totaljs.com +// =================================================== + +const options = {'ip':'0.0.0.0', 'port':12345}; + +// options.ip = '127.0.0.1'; +// options.port = parseInt(process.argv[2]); +// options.config = { name: 'Total.js' }; +// options.sleep = 3000; + +require('total.js').http('release', options); +// require('total.js').cluster.http(5, 'release', options); diff --git a/RVO38/release.js.json b/RVO38/release.js.json new file mode 100755 index 0000000..97aab8f --- /dev/null +++ b/RVO38/release.js.json @@ -0,0 +1,34 @@ +{ + "pid": 412, + "stats": [ + { + "id": null, + "version": { + "node": "v14.18.1", + "total": "3.4.13", + "app": "1.0.0" + }, + "pid": 412, + "thread": "", + "mode": "release", + "overload": 0, + "date": "2025-10-16T00:25:45.522Z", + "memory": 25.74, + "rm": 0, + "fm": 0, + "wm": 0, + "mm": 0, + "om": 3, + "em": 1, + "dbrm": 0, + "dbwm": 0, + "usage": 0, + "requests": 0, + "pending": 0, + "errors": 0, + "timeouts": 0, + "uptime": 716, + "online": 0 + } + ] +} \ No newline at end of file diff --git a/RVO38/report_data.log b/RVO38/report_data.log new file mode 100755 index 0000000..6ae940b --- /dev/null +++ b/RVO38/report_data.log @@ -0,0 +1,163 @@ +{ + "name": "rvo_senica_38_ip122", + "time": "2025-10-15T13:31:00.867Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_38_ip122", + "time": "2025-10-15T14:31:00.865Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_38_ip122", + "time": "2025-10-15T15:31:00.866Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_38_ip122", + "time": "2025-10-15T17:33:54.273Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_38_ip122", + "time": "2025-10-15T18:33:54.273Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "38/59A_1L_3787_NEMA" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_38_ip122", + "time": "2025-10-15T19:33:54.274Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "38/59A_1L_3787_NEMA" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_38_ip122", + "time": "2025-10-15T20:33:54.276Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "38/59A_1L_3787_NEMA" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_38_ip122", + "time": "2025-10-15T21:33:54.277Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "38/59A_1L_3787_NEMA" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_38_ip122", + "time": "2025-10-15T22:33:54.277Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "38/59A_1L_3787_NEMA" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_38_ip122", + "time": "2025-10-15T23:33:54.277Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "38/59A_1L_3787_NEMA" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +} \ No newline at end of file From 7ecac6b3199d3a8257ee2b0f8f518bfe2f5525db Mon Sep 17 00:00:00 2001 From: Jakub Klena Date: Thu, 16 Oct 2025 02:26:22 +0200 Subject: [PATCH 21/30] Backup senica-RVO39 on 16.10.2025 --- RVO39/addSwitch.py | 36 + RVO39/cloud_topic.py | 76 + RVO39/config | 12 + RVO39/createNode.py | 43 + RVO39/databases/accelerometer_db.js | 3055 +++++++ RVO39/databases/modbus_config.js | 114 + RVO39/databases/nodes.table | 35 + .../nodes_original/nodes_original.table | 1 + RVO39/databases/notifications.table | 41 + RVO39/databases/pins.table | 14 + RVO39/databases/relays.table | 5 + RVO39/databases/settings.table | 2 + RVO39/databases/tbdata.nosql | 4 + RVO39/databases/tbdatacloud.nosql | 3 + RVO39/databases/total_energy.js | 38 + RVO39/debug.js | 16 + RVO39/err.txt | 61 + RVO39/flow/cloudmqttconnect.js | 357 + RVO39/flow/cmd_manager.js | 3071 +++++++ .../cmd_manager_before_dailyReportHandler.txt | 2984 +++++++ RVO39/flow/cmd_manager_orig.txt | 2800 ++++++ RVO39/flow/code.js | 90 + RVO39/flow/comment.js | 11 + RVO39/flow/count.js | 60 + RVO39/flow/db_connector.js | 286 + RVO39/flow/db_init.js | 113 + RVO39/flow/debug.js | 100 + RVO39/flow/designer.json | 3102 +++++++ RVO39/flow/dido_controller.js | 1486 ++++ RVO39/flow/helper/DataToTbHandler.js | 187 + RVO39/flow/helper/ErrorToServiceHandler.js | 91 + RVO39/flow/helper/db_helper.js | 44 + RVO39/flow/helper/logger.js | 30 + RVO39/flow/helper/md5.js | 5 + RVO39/flow/helper/notification_reporter.js | 121 + RVO39/flow/helper/register.js | 144 + RVO39/flow/helper/serialport_helper.js | 99 + RVO39/flow/helper/suncalc.js | 317 + RVO39/flow/helper/utils.js | 161 + RVO39/flow/httprequest.js | 137 + RVO39/flow/httpresponse.js | 76 + RVO39/flow/httproute.js | 326 + RVO39/flow/infosender.js | 81 + RVO39/flow/modbus_reader.js | 346 + RVO39/flow/monitorconsumption.js | 156 + RVO39/flow/monitordisk.js | 96 + RVO39/flow/monitormemory.js | 87 + RVO39/flow/nodesdb_changecheck.js | 77 + RVO39/flow/show_dbdata.js | 243 + RVO39/flow/slack_filter.js | 188 + RVO39/flow/thermometer.js | 99 + RVO39/flow/trigger.js | 79 + RVO39/flow/variables.txt | 0 RVO39/flow/virtualwirein.js | 43 + RVO39/flow/virtualwireout.js | 41 + RVO39/flow/wsmqttpublish.js | 448 + RVO39/monitor.txt | 216 + RVO39/package-lock.json | 7470 +++++++++++++++++ RVO39/package.json | 31 + RVO39/release.js | 15 + RVO39/release.js.json | 34 + RVO39/report_data.log | 151 + 62 files changed, 29655 insertions(+) create mode 100755 RVO39/addSwitch.py create mode 100755 RVO39/cloud_topic.py create mode 100755 RVO39/config create mode 100755 RVO39/createNode.py create mode 100755 RVO39/databases/accelerometer_db.js create mode 100755 RVO39/databases/modbus_config.js create mode 100755 RVO39/databases/nodes.table create mode 100755 RVO39/databases/nodes_original/nodes_original.table create mode 100755 RVO39/databases/notifications.table create mode 100755 RVO39/databases/pins.table create mode 100755 RVO39/databases/relays.table create mode 100755 RVO39/databases/settings.table create mode 100755 RVO39/databases/tbdata.nosql create mode 100755 RVO39/databases/tbdatacloud.nosql create mode 100755 RVO39/databases/total_energy.js create mode 100755 RVO39/debug.js create mode 100755 RVO39/err.txt create mode 100755 RVO39/flow/cloudmqttconnect.js create mode 100755 RVO39/flow/cmd_manager.js create mode 100755 RVO39/flow/cmd_manager_before_dailyReportHandler.txt create mode 100755 RVO39/flow/cmd_manager_orig.txt create mode 100755 RVO39/flow/code.js create mode 100755 RVO39/flow/comment.js create mode 100755 RVO39/flow/count.js create mode 100755 RVO39/flow/db_connector.js create mode 100755 RVO39/flow/db_init.js create mode 100755 RVO39/flow/debug.js create mode 100755 RVO39/flow/designer.json create mode 100755 RVO39/flow/dido_controller.js create mode 100755 RVO39/flow/helper/DataToTbHandler.js create mode 100755 RVO39/flow/helper/ErrorToServiceHandler.js create mode 100755 RVO39/flow/helper/db_helper.js create mode 100755 RVO39/flow/helper/logger.js create mode 100755 RVO39/flow/helper/md5.js create mode 100755 RVO39/flow/helper/notification_reporter.js create mode 100755 RVO39/flow/helper/register.js create mode 100755 RVO39/flow/helper/serialport_helper.js create mode 100755 RVO39/flow/helper/suncalc.js create mode 100755 RVO39/flow/helper/utils.js create mode 100755 RVO39/flow/httprequest.js create mode 100755 RVO39/flow/httpresponse.js create mode 100755 RVO39/flow/httproute.js create mode 100755 RVO39/flow/infosender.js create mode 100755 RVO39/flow/modbus_reader.js create mode 100755 RVO39/flow/monitorconsumption.js create mode 100755 RVO39/flow/monitordisk.js create mode 100755 RVO39/flow/monitormemory.js create mode 100755 RVO39/flow/nodesdb_changecheck.js create mode 100755 RVO39/flow/show_dbdata.js create mode 100755 RVO39/flow/slack_filter.js create mode 100755 RVO39/flow/thermometer.js create mode 100755 RVO39/flow/trigger.js create mode 100755 RVO39/flow/variables.txt create mode 100755 RVO39/flow/virtualwirein.js create mode 100755 RVO39/flow/virtualwireout.js create mode 100755 RVO39/flow/wsmqttpublish.js create mode 100755 RVO39/monitor.txt create mode 100755 RVO39/package-lock.json create mode 100755 RVO39/package.json create mode 100755 RVO39/release.js create mode 100755 RVO39/release.js.json create mode 100755 RVO39/report_data.log diff --git a/RVO39/addSwitch.py b/RVO39/addSwitch.py new file mode 100755 index 0000000..c35e96b --- /dev/null +++ b/RVO39/addSwitch.py @@ -0,0 +1,36 @@ +import os + +def process_set_file(): + """ + Checks if /root/flowserver exists, reads set.txt, and modifies the second line. + """ + default_folder = "/root/flowserver" if os.path.exists("/root/flowserver") else "/home/unipi/flowserver" + flag = 1 if default_folder == "/root/flowserver" else 0 + + try: + with open("/home/unipi/flowserver/databases/settings.table", "r") as f: + lines = f.readlines() + + if len(lines) >= 2: + lines[0] = lines[0].rstrip('\n') + "|main_switch:boolean\n" + second_line = lines[1].strip() # remove trailing newline + last_pipe_index = second_line.rfind("|") + + if last_pipe_index != -1: + modified_line = second_line[:last_pipe_index + 1] + str(flag) + "|" + second_line[last_pipe_index + 1:] + lines[1] = modified_line + else: + print("Warning: No '|' character found in the second line of set.txt") + + with open("/home/unipi/flowserver/databases/settings.table", "w") as f: + f.writelines(lines) + else: + print("Warning: settings.table has less than two lines.") + + except FileNotFoundError: + print("Error: settings.table not found.") + except Exception as e: + print(e) + +# if __name__ == "__main__": +process_set_file() diff --git a/RVO39/cloud_topic.py b/RVO39/cloud_topic.py new file mode 100755 index 0000000..77c31f1 --- /dev/null +++ b/RVO39/cloud_topic.py @@ -0,0 +1,76 @@ +# import os +# +# def modify_file(file_path): +# """ +# Modifies the given file by: +# 1. Appending "|cloud_topic" to the first line. +# 2. Inserting the text from the third "." to the first "|" on the second line after the last "|" character. +# +# Args: +# file_path (str): The path to the file to be modified. +# """ +# +# with open(file_path, 'r+') as f: +# lines = f.readlines() +# +# # Modify the first line +# lines[0] += "|cloud_topic:string" +# +# # Modify the second line +# second_line = lines[1].strip() # Remove leading/trailing whitespace +# first_pipe_index = second_line.find('|') +# third_dot_index = second_line.find('.', second_line.find('.', second_line.find('.') + 1) + 1) +# text_to_insert = second_line[third_dot_index:first_pipe_index] +# +# last_pipe_index = second_line.rfind('|') +# lines[1] = second_line[:last_pipe_index + 1] + text_to_insert + "|" + second_line[last_pipe_index + 1:] +# +# print(first_pipe_index, third_dot_index, text_to_insert, last_pipe_index) +# # Write the modified lines back to the file +# # f.seek(0) +# # f.writelines(lines) +# # f.truncate() +# +# # Example usage: +# file_path = "settings.table" # Replace with the actual file path +# modify_file(file_path) +# + + +def modify_file(file_path): + """ + Modifies the given file by: + 1. Appending "|cloud_topic" to the first line. + 2. Inserting the text between the third "." and the second "|" on the second line after the last "|" character. + + Args: + file_path (str): The path to the file to be modified. + """ + + with open(file_path, 'r+') as f: + lines = f.readlines() + + first_line = lines[0].strip() + first_line += "|cloud_topic:string\n" + # Modify the first line + lines[0] = first_line + + # Modify the second line + second_line = lines[1].strip() # Remove leading/trailing whitespace + first_pipe_index = second_line.find('|') + second_pipe_index = second_line.find('|', first_pipe_index + 1) + third_dot_index = second_line.find('.', second_line.find('.', second_line.find('.') + 1) + 1) + text_to_insert = "u" + second_line[third_dot_index+1:second_pipe_index] + + last_pipe_index = second_line.rfind('|') + lines[1] = second_line[:last_pipe_index + 1] + text_to_insert + "|" + second_line[last_pipe_index + 1:] + + print(first_pipe_index, third_dot_index, text_to_insert, last_pipe_index) + # Write the modified lines back to the file + f.seek(0) + f.writelines(lines) + f.truncate() + +# Example usage: +file_path = "/home/unipi/flowserver/databases/settings.table" # Replace with the actual file path +modify_file(file_path) diff --git a/RVO39/config b/RVO39/config new file mode 100755 index 0000000..cd0a8a9 --- /dev/null +++ b/RVO39/config @@ -0,0 +1,12 @@ +name : Total.js Flow +default_timezone : Europe/Bratislava + +// Packages settings +package#flow (Object) : { url: '/' } + + +table.relays : line:number|tbname:string|contactor:number|profile:string +table.nodes : node:number|pole_number:string|node_type:string|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|project_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|cloud_topic:string|has_main_switch:boolean|daily_report:boolean|send_changed_node_numbers:boolean +table.pins : pin:string|type:string|line:number +table.notifications : key:string|weight:string|sk:string|en:string diff --git a/RVO39/createNode.py b/RVO39/createNode.py new file mode 100755 index 0000000..a8cea91 --- /dev/null +++ b/RVO39/createNode.py @@ -0,0 +1,43 @@ +print("zaciname") +import re, json + +search_str = '|' +final = [] +counter = 1 +with open("/home/unipi/flowserver/databases/nodes.table", 'r') as file: +# with open("/home/rasta5man/dev/oms/flowserver/databases/nodes.table", 'r') as file: + # Read each line in the file + for line in file: + # Print each line + line = line.strip() + print(line) + if counter != 1: + i = [m.start() for m in re.finditer(re.escape(search_str), line)] + node = line[ i[0] + 1 : i[1] ] + tbname = line[ i[3] + 1 : i[4] ] + final.append({node:tbname}) + counter += 1 +print(json.dumps(final)) +f = open("/home/unipi/flowserver/databases/nodes_original/nodes_original.table", "w") +f.write(json.dumps(final)) +f.close() + + +# +# # ``d`` has to be replaced with a different character +# old_character = "'" +# +# # ``t`` will replace ``d` +# new_character = '"' +# resultant_string = 0; +# with open("/home/unipi/flowserver/databases/nodes_original/nodes_original.table", 'r') as file: +# for line in file: +# resultant_string = re.sub("'", '"', line) +# +# resultant_string = re.sub(" ", "", resultant_string) +# print(resultant_string) +# +# f = open("/home/unipi/flowserver/databases/nodes_original/nodes_original.table", "w") +# f.write(str(resultant_string)) +# f.close() +# diff --git a/RVO39/databases/accelerometer_db.js b/RVO39/databases/accelerometer_db.js new file mode 100755 index 0000000..fdfc7fd --- /dev/null +++ b/RVO39/databases/accelerometer_db.js @@ -0,0 +1,3055 @@ +let naklony = { + "3993": { "label": "1/3A", "naklon": 0 }, + "3989": { "label": "1/3B", "naklon": 15 }, + "3976": { "label": "1/1", "naklon": 0 }, + "4181": { "label": "1/2", "naklon": 0 }, + "4376": { "label": "1/4", "naklon": 15 }, + "3868": { "label": "1/5", "naklon": 15 }, + "3728": { "label": "1/6", "naklon": 15 }, + "3730": { "label": "1/7", "naklon": 0 }, + "4374": { "label": "1/8", "naklon": 0 }, + "3718": { "label": "1/9", "naklon": 15 }, + "4375": { "label": "1/10", "naklon": 15 }, + "4172": { "label": "1/11", "naklon": 15 }, + "4176": { "label": "1/12", "naklon": 15 }, + "3800": { "label": "2/1", "naklon": 5 }, + "3823": { "label": "2/2", "naklon": 5 }, + "3905": { "label": "2/3", "naklon": 5 }, + "3803": { "label": "2/4", "naklon": 5 }, + "3817": { "label": "2/5", "naklon": 5 }, + "3818": { "label": "2/6", "naklon": 5 }, + "3811": { "label": "2/7", "naklon": 5 }, + "3915": { "label": "2/8", "naklon": 5 }, + "3843": { "label": "2/9", "naklon": 10 }, + "3827": { "label": "2/10", "naklon": 10 }, + "4220": { "label": "2/11", "naklon": 10 }, + "3826": { "label": "2/12", "naklon": 10 }, + "3834": { "label": "2/13", "naklon": 10 }, + "3838": { "label": "2/14", "naklon": 10 }, + "2823": { "label": "2/15", "naklon": 10 }, + "3750": { "label": "2/16", "naklon": 10 }, + "3378": { "label": "2/17", "naklon": 0 }, + "3376": { "label": "2/18", "naklon": 0 }, + "3379": { "label": "2/19", "naklon": 0 }, + "3285": { "label": "2/20", "naklon": 0 }, + "3382": { "label": "2/21", "naklon": 0 }, + "3383": { "label": "2/22", "naklon": 0 }, + "3375": { "label": "2/24", "naklon": 0 }, + "3381": { "label": "2/25", "naklon": 0 }, + "3380": { "label": "2/26", "naklon": 0 }, + "3828": { "label": "2/27", "naklon": 10 }, + "3377": { "label": "2/28", "naklon": 0 }, + "3591": { "label": "7/1", "naklon": 0 }, + "3587": { "label": "7/2", "naklon": 0 }, + "3468": { "label": "7/3", "naklon": 0 }, + "3466": { "label": "7/4", "naklon": 0 }, + "3474": { "label": "7/5", "naklon": 0 }, + "3481": { "label": "7/6", "naklon": 0 }, + "3589": { "label": "7/7", "naklon": 0 }, + "3472": { "label": "7/8", "naklon": 0 }, + "3473": { "label": "7/9", "naklon": 0 }, + "3584": { "label": "7/10", "naklon": 0 }, + "3571": { "label": "7/11", "naklon": 0 }, + "3476": { "label": "7/12", "naklon": 0 }, + "3590": { "label": "7/13", "naklon": 0 }, + "3478": { "label": "7/14", "naklon": 0 }, + "3471": { "label": "7/15", "naklon": 0 }, + "3467": { "label": "7/16", "naklon": 0 }, + "3479": { "label": "7/17", "naklon": 0 }, + "3480": { "label": "7/18", "naklon": 0 }, + "3477": { "label": "7/19", "naklon": 0 }, + "3362": { "label": "12/1", "naklon": 0 }, + "3355": { "label": "12/2", "naklon": 0 }, + "3356": { "label": "12/3", "naklon": 0 }, + "3349": { "label": "12/4", "naklon": 0 }, + "3357": { "label": "12/5", "naklon": 0 }, + "3350": { "label": "12/6", "naklon": 0 }, + "3353": { "label": "12/7", "naklon": 0 }, + "3539": { "label": "12/8", "naklon": 0 }, + "3050": { "label": "12/9", "naklon": 0 }, + "3361": { "label": "12/10", "naklon": 0 }, + "3360": { "label": "12/11", "naklon": 0 }, + "3358": { "label": "12/12", "naklon": 0 }, + "3541": { "label": "12/13", "naklon": 0 }, + "3551": { "label": "12/14", "naklon": 0 }, + "3514": { "label": "12/15", "naklon": 0 }, + "3547": { "label": "12/16", "naklon": 0 }, + "3562": { "label": "12/17", "naklon": 0 }, + "3525": { "label": "12/18", "naklon": 0 }, + "3558": { "label": "12/19", "naklon": 0 }, + "3511": { "label": "12/20", "naklon": 0 }, + "3058": { "label": "12/21", "naklon": 0 }, + "3062": { "label": "12/22", "naklon": 0 }, + "3070": { "label": "12/23", "naklon": 0 }, + "3447": { "label": "12/24", "naklon": 0 }, + "3056": { "label": "12/25", "naklon": 0 }, + "3057": { "label": "12/26", "naklon": 0 }, + "3071": { "label": "12/27", "naklon": 0 }, + "3061": { "label": "12/28", "naklon": 0 }, + "3069": { "label": "12/29", "naklon": 0 }, + "3077": { "label": "12/30", "naklon": 0 }, + "3080": { "label": "12/31", "naklon": 0 }, + "3081": { "label": "12/32", "naklon": 0 }, + "3078": { "label": "12/33", "naklon": 0 }, + "4037": { "label": "12/34", "naklon": 0 }, + "3067": { "label": "12/35", "naklon": 0 }, + "3051": { "label": "12/36", "naklon": 0 }, + "2924": { "label": "12/37", "naklon": 0 }, + "3060": { "label": "12/38", "naklon": 0 }, + "3073": { "label": "12/39", "naklon": 0 }, + "3469": { "label": "12/40", "naklon": 0 }, + "2923": { "label": "12/41", "naklon": 0 }, + "2925": { "label": "12/42", "naklon": 0 }, + "3359": { "label": "12/43", "naklon": 0 }, + "3055": { "label": "12/44", "naklon": 0 }, + "2922": { "label": "12/45", "naklon": 0 }, + "3084": { "label": "12/46", "naklon": 0 }, + "3064": { "label": "12/47", "naklon": 0 }, + "3066": { "label": "12/48", "naklon": 0 }, + "3072": { "label": "12/49", "naklon": 0 }, + "3415": { "label": "13/13A", "naklon": 0 }, + "3409": { "label": "13/13B", "naklon": 0 }, + "3399": { "label": "13/13C", "naklon": 0 }, + "3410": { "label": "13/29A", "naklon": 0 }, + "3407": { "label": "13/29B", "naklon": 0 }, + "3405": { "label": "13/34A", "naklon": 0 }, + "3404": { "label": "13/34B", "naklon": 0 }, + "3392": { "label": "13/45A", "naklon": 0 }, + "3386": { "label": "13/45B", "naklon": 0 }, + "3303": { "label": "13/60A", "naklon": 3 }, + "3302": { "label": "13/60B", "naklon": 3 }, + "3319": { "label": "13/70A", "naklon": 6 }, + "3317": { "label": "13/70B", "naklon": 6 }, + "3326": { "label": "13/70C", "naklon": 6 }, + "3351": { "label": "13/73A", "naklon": 6 }, + "3313": { "label": "13/73B", "naklon": 6 }, + "3316": { "label": "13/83A", "naklon": 0 }, + "3320": { "label": "13/83B", "naklon": 0 }, + "3336": { "label": "13/95A", "naklon": 0 }, + "3323": { "label": "13/95B", "naklon": 0 }, + "3339": { "label": "13/98A", "naklon": 0 }, + "3333": { "label": "13/98B", "naklon": 0 }, + "3425": { "label": "13/1", "naklon": 0 }, + "3419": { "label": "13/2", "naklon": 0 }, + "3416": { "label": "13/3", "naklon": 0 }, + "3332": { "label": "13/4", "naklon": 0 }, + "3422": { "label": "13/5", "naklon": 0 }, + "3417": { "label": "13/6", "naklon": 0 }, + "3418": { "label": "13/7", "naklon": 0 }, + "3424": { "label": "13/8", "naklon": 0 }, + "3334": { "label": "13/9", "naklon": 0 }, + "4363": { "label": "13/10", "naklon": 0 }, + "3423": { "label": "13/11", "naklon": 0 }, + "3406": { "label": "13/12", "naklon": 0 }, + "3411": { "label": "13/14", "naklon": 0 }, + "3412": { "label": "13/15", "naklon": 0 }, + "3413": { "label": "13/16", "naklon": 0 }, + "3414": { "label": "13/17", "naklon": 0 }, + "3391": { "label": "13/18", "naklon": 0 }, + "3370": { "label": "13/19", "naklon": 0 }, + "3369": { "label": "13/20", "naklon": 0 }, + "3408": { "label": "13/21", "naklon": 0 }, + "3393": { "label": "13/22", "naklon": 0 }, + "3128": { "label": "13/23", "naklon": 0 }, + "3197": { "label": "13/24", "naklon": 0 }, + "4364": { "label": "13/25", "naklon": 0 }, + "3155": { "label": "13/26", "naklon": 0 }, + "3196": { "label": "13/27", "naklon": 0 }, + "3144": { "label": "13/28", "naklon": 0 }, + "3150": { "label": "13/30", "naklon": 0 }, + "3390": { "label": "13/31", "naklon": 0 }, + "3401": { "label": "13/32", "naklon": 0 }, + "3275": { "label": "13/33", "naklon": 0 }, + "3371": { "label": "13/35", "naklon": 0 }, + "3389": { "label": "13/36", "naklon": 0 }, + "3388": { "label": "13/37", "naklon": 0 }, + "3365": { "label": "13/38", "naklon": 0 }, + "3363": { "label": "13/39", "naklon": 0 }, + "3397": { "label": "13/40", "naklon": 0 }, + "3567": { "label": "13/40/1", "naklon": 0 }, + "3387": { "label": "13/41", "naklon": 0 }, + "3403": { "label": "13/42", "naklon": 0 }, + "3147": { "label": "13/43", "naklon": 0 }, + "3141": { "label": "13/44", "naklon": 0 }, + "3364": { "label": "13/46", "naklon": 0 }, + "3367": { "label": "13/47", "naklon": 0 }, + "3368": { "label": "13/48", "naklon": 0 }, + "3402": { "label": "13/49", "naklon": 0 }, + "3366": { "label": "13/50", "naklon": 0 }, + "3395": { "label": "13/51", "naklon": 0 }, + "3372": { "label": "13/52", "naklon": 0 }, + "3394": { "label": "13/53", "naklon": 0 }, + "3308": { "label": "13/54", "naklon": 0 }, + "3847": { "label": "13/54/1", "naklon": 0 }, + "3312": { "label": "13/55", "naklon": 3 }, + "3309": { "label": "13/56", "naklon": 3 }, + "3311": { "label": "13/57", "naklon": 3 }, + "3310": { "label": "13/58", "naklon": 3 }, + "4365": { "label": "13/59", "naklon": 3 }, + "4093": { "label": "13/60/1", "naklon": 3 }, + "3304": { "label": "13/61", "naklon": 3 }, + "3307": { "label": "13/62", "naklon": 3 }, + "3271": { "label": "13/63", "naklon": 3 }, + "3301": { "label": "13/64", "naklon": 3 }, + "4366": { "label": "13/65", "naklon": 3 }, + "3300": { "label": "13/66", "naklon": 3 }, + "3185": { "label": "13/67", "naklon": 0 }, + "3184": { "label": "13/68", "naklon": 0 }, + "3188": { "label": "13/69", "naklon": 0 }, + "3343": { "label": "13/71", "naklon": 6 }, + "3819": { "label": "13/71/1", "naklon": 6 }, + "3880": { "label": "13/71/2", "naklon": 6 }, + "3348": { "label": "13/72", "naklon": 6 }, + "3344": { "label": "13/74", "naklon": 6 }, + "3346": { "label": "13/75", "naklon": 6 }, + "3597": { "label": "13/75/1", "naklon": 6 }, + "3345": { "label": "13/76", "naklon": 6 }, + "3322": { "label": "13/77", "naklon": 0 }, + "3325": { "label": "13/78", "naklon": 0 }, + "4310": { "label": "13/78/1", "naklon": 0 }, + "3315": { "label": "13/79", "naklon": 0 }, + "3328": { "label": "13/80", "naklon": 0 }, + "3321": { "label": "13/81", "naklon": 0 }, + "3324": { "label": "13/82", "naklon": 0 }, + "3140": { "label": "13/84", "naklon": 0 }, + "3153": { "label": "13/85", "naklon": 0 }, + "3145": { "label": "13/86", "naklon": 0 }, + "3134": { "label": "13/87", "naklon": 0 }, + "3151": { "label": "13/88", "naklon": 0 }, + "3143": { "label": "13/89", "naklon": 0 }, + "3318": { "label": "13/90", "naklon": 0 }, + "3347": { "label": "13/91", "naklon": 0 }, + "3314": { "label": "13/94", "naklon": 0 }, + "3331": { "label": "13/96", "naklon": 0 }, + "3327": { "label": "13/97", "naklon": 0 }, + "3329": { "label": "13/99", "naklon": 0 }, + "3337": { "label": "13/100", "naklon": 0 }, + "3330": { "label": "13/101", "naklon": 0 }, + "3335": { "label": "13/102", "naklon": 0 }, + "3420": { "label": "13/103", "naklon": 0 }, + "3421": { "label": "13/104", "naklon": 0 }, + "4361": { "label": "13/105", "naklon": 0 }, + "4362": { "label": "13/106", "naklon": 0 }, + "3526": { "label": "13/107", "naklon": 0 }, + "4424": { "label": "13/108", "naklon": null }, + "3561": { "label": "13/109", "naklon": null }, + "3527": { "label": "13/110", "naklon": null }, + "3521": { "label": "13/111", "naklon": null }, + "3552": { "label": "13/112", "naklon": null }, + "3544": { "label": "13/113", "naklon": null }, + "3534": { "label": "13/114", "naklon": null }, + "3516": { "label": "13/115", "naklon": null }, + "3513": { "label": "13/116", "naklon": null }, + "3565": { "label": "13/117", "naklon": null }, + "3866": { "label": "13/118", "naklon": null }, + "3136": { "label": "14/1", "naklon": 0 }, + "3137": { "label": "14/2", "naklon": 0 }, + "3135": { "label": "14/3", "naklon": 0 }, + "3149": { "label": "14/4", "naklon": 0 }, + "3142": { "label": "14/5", "naklon": 0 }, + "3342": { "label": "14/6", "naklon": 0 }, + "3340": { "label": "14/7", "naklon": 0 }, + "3152": { "label": "14/8", "naklon": 0 }, + "3886": { "label": "14/9", "naklon": 0 }, + "3341": { "label": "14/10", "naklon": null }, + "3352": { "label": "14/11", "naklon": null }, + "3396": { "label": "15/1", "naklon": 5 }, + "2784": { "label": "15/2", "naklon": 5 }, + "2788": { "label": "15/3", "naklon": 5 }, + "2801": { "label": "15/4", "naklon": 5 }, + "2815": { "label": "15/5", "naklon": 5 }, + "2829": { "label": "15/6", "naklon": 5 }, + "2796": { "label": "15/7", "naklon": 5 }, + "2803": { "label": "15/8", "naklon": 5 }, + "4304": { "label": "15/8/1", "naklon": 5 }, + "4311": { "label": "15/8/2", "naklon": 5 }, + "2821": { "label": "15/9", "naklon": 5 }, + "3400": { "label": "15/10", "naklon": 5 }, + "2799": { "label": "15/11", "naklon": 5 }, + "2804": { "label": "15/12", "naklon": 5 }, + "4303": { "label": "15/12/1", "naklon": 5 }, + "4309": { "label": "15/12/2", "naklon": 5 }, + "2806": { "label": "15/13", "naklon": 5 }, + "2787": { "label": "15/14", "naklon": 5 }, + "2809": { "label": "15/15", "naklon": 5 }, + "2814": { "label": "15/16", "naklon": 0 }, + "3934": { "label": "15/17", "naklon": 0 }, + "3192": { "label": "15/18", "naklon": 0 }, + "2812": { "label": "15/19", "naklon": 0 }, + "4070": { "label": "15/20", "naklon": 0 }, + "2826": { "label": "15/21", "naklon": 0 }, + "2808": { "label": "15/22", "naklon": 3 }, + "2795": { "label": "15/23", "naklon": 3 }, + "2807": { "label": "15/24", "naklon": 3 }, + "2831": { "label": "15/25", "naklon": 0 }, + "2862": { "label": "15/26", "naklon": null }, + "2861": { "label": "15/27", "naklon": 0 }, + "2866": { "label": "15/28", "naklon": 0 }, + "3546": { "label": "15/28/1", "naklon": 0 }, + "4146": { "label": "15/29", "naklon": 0 }, + "3001": { "label": "15/29/1", "naklon": 0 }, + "2835": { "label": "15/30", "naklon": 0 }, + "2874": { "label": "15/31", "naklon": 0 }, + "2852": { "label": "15/32", "naklon": 0 }, + "2851": { "label": "15/33", "naklon": 0 }, + "3560": { "label": "15/33/1", "naklon": 0 }, + "2858": { "label": "15/34", "naklon": 0 }, + "4306": { "label": "15/34/1", "naklon": 0 }, + "2856": { "label": "15/35", "naklon": 0 }, + "2847": { "label": "15/36", "naklon": 0 }, + "3556": { "label": "15/36/1", "naklon": 0 }, + "3950": { "label": "15/37", "naklon": 0 }, + "2848": { "label": "15/38", "naklon": 0 }, + "2863": { "label": "15/39", "naklon": 0 }, + "4313": { "label": "15/39/1", "naklon": 0 }, + "2873": { "label": "15/40", "naklon": 0 }, + "2984": { "label": "15/40/1", "naklon": 0 }, + "2854": { "label": "15/41", "naklon": 0 }, + "2859": { "label": "15/42", "naklon": 0 }, + "2872": { "label": "15/43", "naklon": 0 }, + "2849": { "label": "15/44", "naklon": 0 }, + "2864": { "label": "15/45", "naklon": 0 }, + "3553": { "label": "15/46", "naklon": null }, + "3021": { "label": "15/47", "naklon": null }, + "3008": { "label": "15/47/1", "naklon": null }, + "3017": { "label": "15/48", "naklon": null }, + "3014": { "label": "15/49", "naklon": null }, + "2981": { "label": "15/50", "naklon": null }, + "3020": { "label": "15/51", "naklon": null }, + "3027": { "label": "15/52", "naklon": null }, + "3006": { "label": "15/53", "naklon": null }, + "3012": { "label": "15/54", "naklon": null }, + "2738": { "label": "15/55", "naklon": 0 }, + "2725": { "label": "15/56", "naklon": 0 }, + "3016": { "label": "15/57", "naklon": null }, + "3005": { "label": "15/58", "naklon": null }, + "3009": { "label": "15/58/1", "naklon": null }, + "3010": { "label": "15/59", "naklon": 0 }, + "3538": { "label": "15/59/1", "naklon": 0 }, + "4145": { "label": "15/59/2", "naklon": 0 }, + "2713": { "label": "15/60", "naklon": 0 }, + "2789": { "label": "15/61", "naklon": 0 }, + "2736": { "label": "15/62", "naklon": 0 }, + "2739": { "label": "15/63", "naklon": 0 }, + "4346": { "label": "15/64", "naklon": 0 }, + "2731": { "label": "15/65", "naklon": 0 }, + "2818": { "label": "15/66", "naklon": 0 }, + "3557": { "label": "15/66/1", "naklon": 0 }, + "2822": { "label": "15/67", "naklon": 0 }, + "2833": { "label": "15/68", "naklon": 0 }, + "2834": { "label": "15/69", "naklon": 0 }, + "3097": { "label": "15/70", "naklon": 0 }, + "2824": { "label": "15/71", "naklon": 0 }, + "2828": { "label": "15/72", "naklon": 0 }, + "2600": { "label": "15/73", "naklon": 0 }, + "4314": { "label": "15/73/1", "naklon": 0 }, + "2832": { "label": "15/74", "naklon": 0 }, + "4360": { "label": "15/75", "naklon": 0 }, + "2846": { "label": "15/76", "naklon": 0 }, + "2584": { "label": "15/77", "naklon": 0 }, + "2843": { "label": "15/78", "naklon": 0 }, + "4308": { "label": "15/78/1", "naklon": 0 }, + "4144": { "label": "15/79", "naklon": null }, + "2844": { "label": "15/80", "naklon": 0 }, + "2842": { "label": "15/81", "naklon": 0 }, + "2838": { "label": "15/82", "naklon": 0 }, + "2837": { "label": "15/83", "naklon": null }, + "3555": { "label": "15/83/1", "naklon": null }, + "2839": { "label": "15/84", "naklon": 0 }, + "2830": { "label": "15/85", "naklon": 0 }, + "4066": { "label": "15/86", "naklon": 0 }, + "2836": { "label": "15/87", "naklon": 0 }, + "2911": { "label": "15/88", "naklon": 0 }, + "2825": { "label": "15/89", "naklon": 0 }, + "2811": { "label": "15/90", "naklon": 0 }, + "3740": { "label": "15/94", "naklon": 15 }, + "2734": { "label": "15/95", "naklon": 15 }, + "3105": { "label": "15/96", "naklon": 15 }, + "2732": { "label": "15/97", "naklon": 15 }, + "2727": { "label": "15/98", "naklon": 15 }, + "2735": { "label": "15/99", "naklon": 15 }, + "3926": { "label": "15/100", "naklon": 15 }, + "2918": { "label": "15/101", "naklon": 0 }, + "2705": { "label": "15/102", "naklon": 10 }, + "2708": { "label": "15/103", "naklon": 10 }, + "2721": { "label": "15/104", "naklon": 10 }, + "2719": { "label": "15/105", "naklon": 10 }, + "2919": { "label": "15/106", "naklon": 10 }, + "3101": { "label": "15/107", "naklon": 10 }, + "2853": { "label": "15/108", "naklon": 10 }, + "2715": { "label": "15/109", "naklon": 10 }, + "2712": { "label": "15/110", "naklon": 0 }, + "2711": { "label": "15/111", "naklon": 0 }, + "2709": { "label": "15/112", "naklon": 0 }, + "2710": { "label": "15/113", "naklon": 0 }, + "2907": { "label": "15/114", "naklon": 0 }, + "2906": { "label": "15/115", "naklon": 0 }, + "2908": { "label": "15/116", "naklon": 0 }, + "2901": { "label": "15/117", "naklon": 0 }, + "2913": { "label": "15/118", "naklon": 0 }, + "3656": { "label": "15/119", "naklon": 0 }, + "2781": { "label": "15/120", "naklon": 0 }, + "2802": { "label": "15/121", "naklon": 0 }, + "2791": { "label": "15/122", "naklon": 0 }, + "2783": { "label": "15/123", "naklon": 0 }, + "2794": { "label": "15/124", "naklon": 0 }, + "3139": { "label": "15/125", "naklon": 0 }, + "3229": { "label": "15/126", "naklon": 5 }, + "3239": { "label": "15/127", "naklon": 5 }, + "3230": { "label": "15/128", "naklon": 5 }, + "4016": { "label": "15/129", "naklon": null }, + "3608": { "label": "16/16A", "naklon": 0 }, + "4151": { "label": "16/16B", "naklon": 0 }, + "3710": { "label": "16/1", "naklon": 0 }, + "3726": { "label": "16/2", "naklon": 0 }, + "3743": { "label": "16/3", "naklon": 0 }, + "3724": { "label": "16/4", "naklon": 0 }, + "3712": { "label": "16/5", "naklon": 0 }, + "3739": { "label": "16/6", "naklon": 0 }, + "3742": { "label": "16/7", "naklon": 0 }, + "3731": { "label": "16/8", "naklon": 0 }, + "3727": { "label": "16/9", "naklon": 0 }, + "3729": { "label": "16/10", "naklon": 0 }, + "3736": { "label": "16/11", "naklon": 0 }, + "3713": { "label": "16/12", "naklon": 0 }, + "3715": { "label": "16/13", "naklon": 0 }, + "3733": { "label": "16/14", "naklon": 0 }, + "3732": { "label": "16/15", "naklon": 0 }, + "3634": { "label": "16/17", "naklon": 0 }, + "3610": { "label": "16/18", "naklon": 0 }, + "3626": { "label": "16/19", "naklon": 0 }, + "3618": { "label": "16/20", "naklon": 0 }, + "3619": { "label": "16/21", "naklon": 0 }, + "3628": { "label": "16/22", "naklon": 0 }, + "3615": { "label": "16/23", "naklon": 0 }, + "3609": { "label": "16/24", "naklon": 0 }, + "3606": { "label": "16/25", "naklon": 0 }, + "3624": { "label": "16/26", "naklon": 0 }, + "3627": { "label": "16/27", "naklon": 0 }, + "3607": { "label": "16/28", "naklon": 0 }, + "4370": { "label": "16/29", "naklon": 0 }, + "3692": { "label": "16/30", "naklon": 0 }, + "3614": { "label": "16/31", "naklon": 0 }, + "3623": { "label": "16/32", "naklon": 0 }, + "4373": { "label": "16/33", "naklon": 0 }, + "3620": { "label": "16/34", "naklon": 0 }, + "3685": { "label": "16/35", "naklon": 0 }, + "3616": { "label": "16/36", "naklon": 0 }, + "3686": { "label": "16/37", "naklon": 0 }, + "3688": { "label": "16/38", "naklon": 0 }, + "3684": { "label": "16/39", "naklon": 0 }, + "3825": { "label": "16/40", "naklon": 0 }, + "3865": { "label": "16/41", "naklon": 0 }, + "3824": { "label": "16/42", "naklon": 0 }, + "3871": { "label": "16/43", "naklon": 0 }, + "3801": { "label": "16/44", "naklon": 0 }, + "3862": { "label": "16/45", "naklon": 0 }, + "3876": { "label": "16/46", "naklon": 0 }, + "3861": { "label": "16/47", "naklon": 0 }, + "4215": { "label": "16/48", "naklon": 0 }, + "3605": { "label": "16/49", "naklon": 10 }, + "3603": { "label": "16/50", "naklon": 10 }, + "3592": { "label": "16/51", "naklon": 10 }, + "3598": { "label": "16/52", "naklon": 10 }, + "3594": { "label": "16/53", "naklon": 10 }, + "3593": { "label": "16/54", "naklon": 10 }, + "3630": { "label": "16/55", "naklon": 10 }, + "3763": { "label": "16/56", "naklon": 10 }, + "3746": { "label": "16/57", "naklon": 10 }, + "3699": { "label": "16/58", "naklon": 0 }, + "3698": { "label": "16/59", "naklon": 0 }, + "3709": { "label": "16/60", "naklon": null }, + "3708": { "label": "16/61", "naklon": 0 }, + "3703": { "label": "16/62", "naklon": null }, + "3700": { "label": "16/63", "naklon": 0 }, + "3701": { "label": "16/64", "naklon": null }, + "3704": { "label": "16/65", "naklon": 0 }, + "3707": { "label": "16/66", "naklon": null }, + "3810": { "label": "16/67", "naklon": 0 }, + "4208": { "label": "16/68", "naklon": null }, + "3867": { "label": "16/69", "naklon": 0 }, + "4372": { "label": "16/70", "naklon": null }, + "3881": { "label": "16/71", "naklon": 0 }, + "4204": { "label": "16/72", "naklon": null }, + "3869": { "label": "16/73", "naklon": 0 }, + "4202": { "label": "16/74", "naklon": null }, + "3830": { "label": "16/75", "naklon": 0 }, + "3870": { "label": "16/76", "naklon": null }, + "3964": { "label": "16/77", "naklon": 0 }, + "3849": { "label": "16/78", "naklon": 0 }, + "3694": { "label": "16/79", "naklon": null }, + "3717": { "label": "16/80", "naklon": 0 }, + "3877": { "label": "16/81", "naklon": null }, + "3755": { "label": "16/82", "naklon": 0 }, + "3725": { "label": "16/83", "naklon": null }, + "3716": { "label": "16/84", "naklon": 0 }, + "3696": { "label": "16/85", "naklon": null }, + "3702": { "label": "16/86", "naklon": 0 }, + "3706": { "label": "16/87", "naklon": null }, + "3850": { "label": "16/88", "naklon": 0 }, + "3848": { "label": "16/89", "naklon": null }, + "3737": { "label": "16/90", "naklon": null }, + "3705": { "label": "16/91", "naklon": 0 }, + "3723": { "label": "16/92", "naklon": null }, + "3842": { "label": "16/93", "naklon": 0 }, + "3735": { "label": "16/94", "naklon": null }, + "3719": { "label": "16/95", "naklon": 0 }, + "3697": { "label": "16/96", "naklon": 0 }, + "3711": { "label": "16/97", "naklon": 0 }, + "4107": { "label": "16/98", "naklon": null }, + "4112": { "label": "16/99", "naklon": 5 }, + "4106": { "label": "16/100", "naklon": 5 }, + "4111": { "label": "16/101", "naklon": 5 }, + "4091": { "label": "16/102", "naklon": null }, + "4104": { "label": "16/103", "naklon": 5 }, + "4094": { "label": "16/104", "naklon": null }, + "4089": { "label": "16/105", "naklon": 5 }, + "4095": { "label": "16/106", "naklon": null }, + "4102": { "label": "16/107", "naklon": 5 }, + "4105": { "label": "16/108", "naklon": null }, + "3859": { "label": "16/109", "naklon": null }, + "4090": { "label": "16/110", "naklon": 5 }, + "4110": { "label": "16/111", "naklon": null }, + "4097": { "label": "16/112", "naklon": 5 }, + "4099": { "label": "16/113", "naklon": null }, + "4096": { "label": "16/114", "naklon": null }, + "4101": { "label": "16/115", "naklon": 5 }, + "4109": { "label": "16/116", "naklon": null }, + "4092": { "label": "16/117", "naklon": 5 }, + "3631": { "label": "16/118", "naklon": null }, + "3632": { "label": "16/119", "naklon": 0 }, + "3641": { "label": "16/120", "naklon": null }, + "3638": { "label": "16/121", "naklon": 0 }, + "3637": { "label": "16/122", "naklon": null }, + "4142": { "label": "16/123", "naklon": null }, + "4147": { "label": "16/124", "naklon": 5 }, + "4139": { "label": "16/125", "naklon": 5 }, + "3172": { "label": "20/30A", "naklon": 2 }, + "3164": { "label": "20/30B", "naklon": 2 }, + "3247": { "label": "20/1", "naklon": 10 }, + "3296": { "label": "20/2", "naklon": 10 }, + "3246": { "label": "20/3", "naklon": 10 }, + "3270": { "label": "20/4", "naklon": 10 }, + "3294": { "label": "20/5", "naklon": 10 }, + "3298": { "label": "20/6", "naklon": 10 }, + "3297": { "label": "20/7", "naklon": 10 }, + "3293": { "label": "20/8", "naklon": 10 }, + "3299": { "label": "20/9", "naklon": 10 }, + "3295": { "label": "20/10", "naklon": 10 }, + "3244": { "label": "20/11", "naklon": 10 }, + "3249": { "label": "20/12", "naklon": 10 }, + "3268": { "label": "20/13", "naklon": 10 }, + "3245": { "label": "20/14", "naklon": 10 }, + "3278": { "label": "20/15", "naklon": 10 }, + "3280": { "label": "20/16", "naklon": 10 }, + "3292": { "label": "20/17", "naklon": 10 }, + "3287": { "label": "20/18", "naklon": 10 }, + "3282": { "label": "20/19", "naklon": 10 }, + "3273": { "label": "20/20", "naklon": 0 }, + "3157": { "label": "20/21", "naklon": 0 }, + "3283": { "label": "20/22", "naklon": 0 }, + "3159": { "label": "20/23", "naklon": 0 }, + "3289": { "label": "20/24", "naklon": 0 }, + "3163": { "label": "20/25", "naklon": 0 }, + "3126": { "label": "20/26", "naklon": 0 }, + "3171": { "label": "20/27", "naklon": 0 }, + "3162": { "label": "20/28", "naklon": 0 }, + "3279": { "label": "20/29", "naklon": 10 }, + "3173": { "label": "20/31", "naklon": 0 }, + "3127": { "label": "20/32", "naklon": 0 }, + "3131": { "label": "20/33", "naklon": 0 }, + "3129": { "label": "20/34", "naklon": 0 }, + "3276": { "label": "20/35", "naklon": 2 }, + "3290": { "label": "20/36", "naklon": 2 }, + "3132": { "label": "20/37", "naklon": 0 }, + "3138": { "label": "20/38", "naklon": 0 }, + "3272": { "label": "20/39", "naklon": 0 }, + "3291": { "label": "20/40", "naklon": 0 }, + "3277": { "label": "20/41", "naklon": 10 }, + "3286": { "label": "20/42", "naklon": 10 }, + "3281": { "label": "20/43", "naklon": 10 }, + "3288": { "label": "20/44", "naklon": 10 }, + "3284": { "label": "20/45", "naklon": 10 }, + "3167": { "label": "20/46", "naklon": 10 }, + "3872": { "label": "20/47", "naklon": 0 }, + "3124": { "label": "20/48", "naklon": 0 }, + "3133": { "label": "20/49", "naklon": 0 }, + "3158": { "label": "20/50", "naklon": 0 }, + "3169": { "label": "20/51", "naklon": 0 }, + "3146": { "label": "20/52", "naklon": 0 }, + "3160": { "label": "20/53", "naklon": 0 }, + "3248": { "label": "20/54", "naklon": 0 }, + "3156": { "label": "20/55", "naklon": 0 }, + "3161": { "label": "20/56", "naklon": 0 }, + "3170": { "label": "20/57", "naklon": 0 }, + "3168": { "label": "20/58", "naklon": 0 }, + "3125": { "label": "20/59", "naklon": 0 }, + "3166": { "label": "20/60", "naklon": 0 }, + "3130": { "label": "20/61", "naklon": 0 }, + "3563": { "label": "20/62", "naklon": 0 }, + "3550": { "label": "20/63", "naklon": null }, + "3269": { "label": "20/67", "naklon": 0 }, + "2921": { "label": "21/1", "naklon": 0 }, + "2707": { "label": "21/2", "naklon": 0 }, + "2723": { "label": "21/3", "naklon": 0 }, + "2716": { "label": "21/4", "naklon": 0 }, + "2717": { "label": "21/5", "naklon": 0 }, + "2720": { "label": "21/6", "naklon": 0 }, + "2722": { "label": "21/7", "naklon": 0 }, + "2718": { "label": "21/8", "naklon": 0 }, + "2724": { "label": "21/9", "naklon": 0 }, + "2742": { "label": "21/10", "naklon": 0 }, + "2743": { "label": "21/11", "naklon": 0 }, + "2733": { "label": "21/12", "naklon": 0 }, + "2903": { "label": "21/14", "naklon": 0 }, + "2917": { "label": "21/15", "naklon": 0 }, + "2897": { "label": "21/16", "naklon": 0 }, + "2914": { "label": "21/17", "naklon": 0 }, + "2898": { "label": "21/18", "naklon": 0 }, + "2773": { "label": "21/19", "naklon": 0 }, + "2895": { "label": "21/20", "naklon": 0 }, + "2896": { "label": "21/21", "naklon": 0 }, + "2771": { "label": "21/22", "naklon": 0 }, + "2772": { "label": "21/23", "naklon": 0 }, + "2793": { "label": "21/24", "naklon": 0 }, + "2902": { "label": "21/25", "naklon": 0 }, + "2910": { "label": "21/26", "naklon": 0 }, + "2909": { "label": "21/27", "naklon": 0 }, + "2920": { "label": "21/28", "naklon": 0 }, + "2916": { "label": "21/29", "naklon": 0 }, + "2904": { "label": "21/30", "naklon": 0 }, + "2915": { "label": "21/31", "naklon": 0 }, + "2905": { "label": "21/32", "naklon": 0 }, + "2900": { "label": "21/33", "naklon": 0 }, + "2899": { "label": "21/34", "naklon": 0 }, + "2741": { "label": "21/36", "naklon": 0 }, + "2714": { "label": "21/37", "naklon": 0 }, + "2701": { "label": "21/38", "naklon": 0 }, + "2703": { "label": "21/39", "naklon": 0 }, + "2704": { "label": "21/40", "naklon": 0 }, + "2702": { "label": "21/41", "naklon": 0 }, + "2706": { "label": "21/42", "naklon": 0 }, + "2776": { "label": "21/43", "naklon": 0 }, + "2770": { "label": "21/44", "naklon": 0 }, + "2786": { "label": "21/45", "naklon": 0 }, + "2779": { "label": "21/46", "naklon": 0 }, + "2782": { "label": "21/47", "naklon": 0 }, + "2785": { "label": "21/48", "naklon": 0 }, + "2769": { "label": "21/49", "naklon": 0 }, + "3354": { "label": "21/50", "naklon": 0 }, + "2778": { "label": "21/51", "naklon": 0 }, + "2775": { "label": "21/52", "naklon": 0 }, + "2780": { "label": "21/53", "naklon": 0 }, + "2790": { "label": "21/54", "naklon": 0 }, + "2792": { "label": "21/55", "naklon": 0 }, + "2774": { "label": "21/56", "naklon": 0 }, + "2630": { "label": "22/1", "naklon": 0 }, + "2631": { "label": "22/2", "naklon": 0 }, + "2632": { "label": "22/3", "naklon": 0 }, + "2633": { "label": "22/4", "naklon": 0 }, + "2634": { "label": "22/5", "naklon": 0 }, + "2636": { "label": "22/6", "naklon": 0 }, + "4367": { "label": "22/7", "naklon": 0 }, + "2637": { "label": "22/8", "naklon": 0 }, + "2638": { "label": "22/9", "naklon": 0 }, + "2639": { "label": "22/10", "naklon": 0 }, + "2640": { "label": "22/11", "naklon": 0 }, + "2641": { "label": "22/12", "naklon": 0 }, + "2642": { "label": "22/13", "naklon": 0 }, + "2643": { "label": "22/14", "naklon": 0 }, + "2644": { "label": "22/15", "naklon": 0 }, + "2645": { "label": "22/16", "naklon": 0 }, + "2646": { "label": "22/17", "naklon": 0 }, + "2647": { "label": "22/18", "naklon": 0 }, + "2648": { "label": "22/19", "naklon": 0 }, + "2649": { "label": "22/20", "naklon": 0 }, + "2650": { "label": "22/21", "naklon": 0 }, + "2651": { "label": "22/22", "naklon": 0 }, + "4103": { "label": "22/23", "naklon": 0 }, + "2653": { "label": "22/24", "naklon": 0 }, + "2654": { "label": "22/25", "naklon": 0 }, + "2655": { "label": "22/26", "naklon": 0 }, + "2656": { "label": "22/27", "naklon": 0 }, + "2657": { "label": "22/28", "naklon": 0 }, + "2658": { "label": "22/29", "naklon": 0 }, + "2659": { "label": "22/30", "naklon": 0 }, + "2660": { "label": "22/31", "naklon": 0 }, + "2661": { "label": "22/32", "naklon": 0 }, + "3015": { "label": "22/32/1", "naklon": 0 }, + "2662": { "label": "22/33", "naklon": 0 }, + "2663": { "label": "22/34", "naklon": 0 }, + "2664": { "label": "22/35", "naklon": 0 }, + "2665": { "label": "22/36", "naklon": 0 }, + "2666": { "label": "22/37", "naklon": 0 }, + "2667": { "label": "22/38", "naklon": 0 }, + "2668": { "label": "22/39", "naklon": 0 }, + "2669": { "label": "22/40", "naklon": null }, + "2670": { "label": "22/41", "naklon": null }, + "2671": { "label": "22/42", "naklon": null }, + "3087": { "label": "23/9A", "naklon": 10 }, + "3090": { "label": "23/9B", "naklon": 10 }, + "3075": { "label": "23/1", "naklon": 0 }, + "3089": { "label": "23/2", "naklon": 0 }, + "3088": { "label": "23/3", "naklon": 0 }, + "3228": { "label": "23/4", "naklon": 10 }, + "2751": { "label": "23/5", "naklon": 10 }, + "3243": { "label": "23/6", "naklon": 10 }, + "4349": { "label": "23/7", "naklon": 10 }, + "3102": { "label": "23/8", "naklon": 10 }, + "3099": { "label": "23/10", "naklon": 10 }, + "3103": { "label": "23/11", "naklon": 10 }, + "3093": { "label": "23/12", "naklon": 10 }, + "3098": { "label": "23/13", "naklon": 10 }, + "3092": { "label": "23/14", "naklon": 10 }, + "3233": { "label": "23/15", "naklon": 0 }, + "3095": { "label": "23/16", "naklon": 0 }, + "4074": { "label": "23/17", "naklon": 0 }, + "2729": { "label": "23/18", "naklon": 0 }, + "3234": { "label": "23/19", "naklon": 0 }, + "3094": { "label": "23/20", "naklon": 0 }, + "2817": { "label": "23/21", "naklon": 0 }, + "3226": { "label": "23/22", "naklon": 0 }, + "3225": { "label": "23/23", "naklon": 0 }, + "3237": { "label": "23/24", "naklon": 0 }, + "4250": { "label": "23/25", "naklon": 0 }, + "3059": { "label": "23/26", "naklon": 10 }, + "3238": { "label": "23/27", "naklon": 10 }, + "3242": { "label": "23/28", "naklon": 10 }, + "3236": { "label": "23/29", "naklon": 10 }, + "3112": { "label": "23/30", "naklon": 10 }, + "3224": { "label": "23/31", "naklon": 0 }, + "4298": { "label": "23/32", "naklon": 10 }, + "4150": { "label": "23/33", "naklon": 10 }, + "3091": { "label": "23/34", "naklon": 10 }, + "3771": { "label": "25/1", "naklon": 5 }, + "3777": { "label": "25/2", "naklon": 5 }, + "3749": { "label": "25/3", "naklon": 5 }, + "3769": { "label": "25/4", "naklon": 5 }, + "3765": { "label": "25/5", "naklon": 5 }, + "3785": { "label": "25/6", "naklon": 5 }, + "3761": { "label": "25/7", "naklon": 5 }, + "3758": { "label": "25/8", "naklon": 5 }, + "3766": { "label": "25/9", "naklon": 5 }, + "3779": { "label": "25/10", "naklon": 5 }, + "3899": { "label": "25/11", "naklon": 10 }, + "3922": { "label": "25/12", "naklon": 10 }, + "3912": { "label": "25/13", "naklon": 10 }, + "3933": { "label": "25/14", "naklon": 10 }, + "3921": { "label": "25/15", "naklon": 10 }, + "4300": { "label": "25/16", "naklon": 10 }, + "3927": { "label": "25/17", "naklon": 10 }, + "3212": { "label": "25/18", "naklon": 10 }, + "3208": { "label": "25/19", "naklon": 10 }, + "3207": { "label": "25/20", "naklon": 10 }, + "4294": { "label": "25/21", "naklon": 10 }, + "3209": { "label": "25/22", "naklon": 10 }, + "3745": { "label": "25/23", "naklon": 10 }, + "3762": { "label": "25/24", "naklon": 10 }, + "3215": { "label": "25/25", "naklon": 10 }, + "3210": { "label": "25/26", "naklon": 10 }, + "3211": { "label": "25/27", "naklon": 10 }, + "3206": { "label": "25/28", "naklon": 10 }, + "3918": { "label": "25/29", "naklon": 5 }, + "3928": { "label": "25/30", "naklon": 5 }, + "3917": { "label": "25/31", "naklon": 5 }, + "4029": { "label": "25/32", "naklon": 0 }, + "4038": { "label": "25/33", "naklon": 0 }, + "4022": { "label": "25/34", "naklon": 0 }, + "3937": { "label": "25/35", "naklon": 0 }, + "3190": { "label": "25/36", "naklon": 0 }, + "3835": { "label": "25/37", "naklon": 0 }, + "3201": { "label": "25/38", "naklon": 0 }, + "3193": { "label": "25/39", "naklon": 0 }, + "3191": { "label": "25/40", "naklon": 0 }, + "3203": { "label": "25/41", "naklon": 0 }, + "4301": { "label": "25/42", "naklon": 0 }, + "3223": { "label": "25/43", "naklon": 0 }, + "3202": { "label": "25/44", "naklon": 0 }, + "3205": { "label": "25/45", "naklon": 0 }, + "3194": { "label": "25/46", "naklon": 0 }, + "3198": { "label": "25/47", "naklon": 0 }, + "3204": { "label": "25/48", "naklon": 0 }, + "3200": { "label": "25/49", "naklon": 0 }, + "3216": { "label": "25/50", "naklon": 0 }, + "3932": { "label": "25/51", "naklon": 5 }, + "3923": { "label": "25/52", "naklon": 5 }, + "3913": { "label": "25/53", "naklon": 5 }, + "3900": { "label": "25/54", "naklon": 5 }, + "4189": { "label": "25/55", "naklon": 10 }, + "4191": { "label": "25/56", "naklon": 10 }, + "3790": { "label": "25/57", "naklon": 10 }, + "4190": { "label": "25/58", "naklon": 10 }, + "4302": { "label": "25/59", "naklon": 0 }, + "4351": { "label": "25/60", "naklon": 0 }, + "4075": { "label": "25/61", "naklon": 0 }, + "4071": { "label": "25/62", "naklon": 0 }, + "3784": { "label": "25/63", "naklon": 0 }, + "4065": { "label": "25/64", "naklon": 0 }, + "4297": { "label": "25/65", "naklon": 0 }, + "4295": { "label": "25/66", "naklon": 0 }, + "4299": { "label": "25/67", "naklon": 0 }, + "3772": { "label": "25/68", "naklon": 0 }, + "3941": { "label": "25/69", "naklon": 0 }, + "3782": { "label": "25/70", "naklon": 0 }, + "4068": { "label": "25/71", "naklon": 0 }, + "4073": { "label": "25/72", "naklon": 0 }, + "3901": { "label": "25/73", "naklon": 5 }, + "4296": { "label": "25/74", "naklon": 5 }, + "3910": { "label": "25/75", "naklon": 5 }, + "4293": { "label": "25/76", "naklon": 5 }, + "3919": { "label": "25/77", "naklon": 5 }, + "3924": { "label": "25/78", "naklon": 5 }, + "3909": { "label": "25/79", "naklon": 5 }, + "3896": { "label": "25/80", "naklon": 5 }, + "3911": { "label": "25/81", "naklon": 5 }, + "2819": { "label": "25/82", "naklon": 15 }, + "3776": { "label": "25/83", "naklon": 15 }, + "3752": { "label": "25/84", "naklon": 15 }, + "4353": { "label": "25/85", "naklon": 15 }, + "3791": { "label": "25/86", "naklon": 0 }, + "3770": { "label": "25/87", "naklon": 0 }, + "3760": { "label": "25/88", "naklon": 0 }, + "3115": { "label": "25/89", "naklon": 0 }, + "3738": { "label": "25/90", "naklon": 0 }, + "3748": { "label": "25/91", "naklon": 0 }, + "3753": { "label": "25/92", "naklon": 0 }, + "3775": { "label": "25/93", "naklon": 0 }, + "3778": { "label": "25/94", "naklon": 5 }, + "4078": { "label": "25/95", "naklon": 5 }, + "4088": { "label": "25/96", "naklon": 5 }, + "3856": { "label": "25/97", "naklon": 5 }, + "4084": { "label": "25/98", "naklon": 5 }, + "4069": { "label": "25/99", "naklon": 5 }, + "4188": { "label": "25/100", "naklon": 5 }, + "4064": { "label": "25/101", "naklon": 5 }, + "3792": { "label": "25/102", "naklon": 5 }, + "3780": { "label": "25/103", "naklon": 5 }, + "4034": { "label": "25/104", "naklon": 5 }, + "4072": { "label": "25/105", "naklon": 5 }, + "3884": { "label": "25/106", "naklon": 5 }, + "3793": { "label": "25/107", "naklon": 5 }, + "3863": { "label": "25/108", "naklon": 5 }, + "3855": { "label": "25/109", "naklon": 5 }, + "3846": { "label": "33/1", "naklon": 0 }, + "3943": { "label": "33/2", "naklon": 0 }, + "3903": { "label": "33/3", "naklon": 0 }, + "3982": { "label": "33/4", "naklon": 0 }, + "3879": { "label": "33/5", "naklon": 0 }, + "3887": { "label": "33/6", "naklon": 0 }, + "3920": { "label": "33/7", "naklon": 5 }, + "3942": { "label": "33/8", "naklon": 5 }, + "3829": { "label": "33/9", "naklon": null }, + "3452": { "label": "34/79A", "naklon": 6 }, + "3460": { "label": "34/79B", "naklon": 6 }, + "3443": { "label": "34/90A", "naklon": 6 }, + "3445": { "label": "34/90B", "naklon": 6 }, + "3457": { "label": "34/90C", "naklon": 6 }, + "3461": { "label": "34/97A", "naklon": 6 }, + "3463": { "label": "34/97B", "naklon": 6 }, + "3426": { "label": "34/98A", "naklon": 6 }, + "3444": { "label": "34/98B", "naklon": 6 }, + "3453": { "label": "34/99A", "naklon": 6 }, + "3455": { "label": "34/99B", "naklon": 6 }, + "4009": { "label": "34/1", "naklon": 0 }, + "3602": { "label": "34/2", "naklon": 0 }, + "3441": { "label": "34/3", "naklon": 0 }, + "3464": { "label": "34/4", "naklon": 0 }, + "3883": { "label": "34/5", "naklon": 0 }, + "4098": { "label": "34/6", "naklon": 0 }, + "4003": { "label": "34/7", "naklon": 0 }, + "4004": { "label": "34/8", "naklon": 0 }, + "3888": { "label": "34/9", "naklon": 0 }, + "3997": { "label": "34/10", "naklon": 0 }, + "4006": { "label": "34/11", "naklon": 0 }, + "4000": { "label": "34/12", "naklon": 0 }, + "4011": { "label": "34/13", "naklon": 0 }, + "3999": { "label": "34/14", "naklon": 0 }, + "3981": { "label": "34/15", "naklon": 0 }, + "3988": { "label": "34/16", "naklon": 0 }, + "3986": { "label": "34/17", "naklon": 0 }, + "3998": { "label": "34/18", "naklon": 0 }, + "3983": { "label": "34/19", "naklon": 0 }, + "4005": { "label": "34/20", "naklon": 0 }, + "4001": { "label": "34/21", "naklon": 0 }, + "4008": { "label": "34/22", "naklon": 0 }, + "4002": { "label": "34/23", "naklon": 0 }, + "3996": { "label": "34/24", "naklon": 0 }, + "4007": { "label": "34/25", "naklon": 0 }, + "4113": { "label": "34/26", "naklon": 15 }, + "3595": { "label": "34/27", "naklon": 5 }, + "3599": { "label": "34/28", "naklon": 5 }, + "3601": { "label": "34/29", "naklon": 5 }, + "4205": { "label": "34/30", "naklon": 0 }, + "3987": { "label": "34/31", "naklon": null }, + "4214": { "label": "34/32", "naklon": 0 }, + "4226": { "label": "34/33", "naklon": 0 }, + "4209": { "label": "34/34", "naklon": 0 }, + "4201": { "label": "34/35", "naklon": 0 }, + "3440": { "label": "34/36", "naklon": 0 }, + "3465": { "label": "34/37", "naklon": 0 }, + "3446": { "label": "34/38", "naklon": 0 }, + "4039": { "label": "34/39", "naklon": 5 }, + "4057": { "label": "34/40", "naklon": 5 }, + "3985": { "label": "34/41", "naklon": 0 }, + "3882": { "label": "34/42", "naklon": 0 }, + "4040": { "label": "34/43", "naklon": 5 }, + "3231": { "label": "34/44", "naklon": 0 }, + "3227": { "label": "34/45", "naklon": 0 }, + "3431": { "label": "34/46", "naklon": 0 }, + "4013": { "label": "34/47", "naklon": 0 }, + "4045": { "label": "34/48", "naklon": 0 }, + "3949": { "label": "34/49", "naklon": 0 }, + "3953": { "label": "34/50", "naklon": 0 }, + "3952": { "label": "34/51", "naklon": 0 }, + "3995": { "label": "34/52", "naklon": 0 }, + "3992": { "label": "34/53", "naklon": 0 }, + "4198": { "label": "34/54", "naklon": 0 }, + "3935": { "label": "34/55", "naklon": 0 }, + "4050": { "label": "34/56", "naklon": 0 }, + "4049": { "label": "34/57", "naklon": 0 }, + "4054": { "label": "34/58", "naklon": 0 }, + "3663": { "label": "34/59", "naklon": 6 }, + "3661": { "label": "34/60", "naklon": 6 }, + "3664": { "label": "34/61", "naklon": 6 }, + "3660": { "label": "34/62", "naklon": 6 }, + "3662": { "label": "34/63", "naklon": 6 }, + "3665": { "label": "34/65", "naklon": 6 }, + "3667": { "label": "34/66", "naklon": 6 }, + "3675": { "label": "34/67", "naklon": 6 }, + "3666": { "label": "34/68", "naklon": 6 }, + "3652": { "label": "34/69", "naklon": 6 }, + "3458": { "label": "34/70", "naklon": 6 }, + "4425": { "label": "34/70/1", "naklon": 6 }, + "3459": { "label": "34/71", "naklon": 6 }, + "3435": { "label": "34/72", "naklon": 6 }, + "3448": { "label": "34/73", "naklon": 6 }, + "3451": { "label": "34/74", "naklon": 6 }, + "3442": { "label": "34/75", "naklon": 6 }, + "3449": { "label": "34/76", "naklon": 6 }, + "3450": { "label": "34/77", "naklon": 6 }, + "3433": { "label": "34/78", "naklon": 6 }, + "3432": { "label": "34/80", "naklon": 12 }, + "3470": { "label": "34/81", "naklon": 12 }, + "3438": { "label": "34/82", "naklon": 12 }, + "3439": { "label": "34/83", "naklon": 12 }, + "4028": { "label": "34/84", "naklon": 5 }, + "3596": { "label": "34/85", "naklon": 5 }, + "4021": { "label": "34/86", "naklon": 5 }, + "3437": { "label": "34/87", "naklon": 12 }, + "3428": { "label": "34/88", "naklon": 12 }, + "3430": { "label": "34/89", "naklon": 12 }, + "3454": { "label": "34/91", "naklon": 6 }, + "3492": { "label": "34/92", "naklon": 6 }, + "3462": { "label": "34/93", "naklon": 6 }, + "3427": { "label": "34/94", "naklon": 6 }, + "3434": { "label": "34/95", "naklon": 6 }, + "3456": { "label": "34/96", "naklon": 6 }, + "4307": { "label": "34/98/1", "naklon": 6 }, + "3968": { "label": "35/1", "naklon": 0 }, + "3969": { "label": "35/2", "naklon": 0 }, + "3947": { "label": "35/3", "naklon": 0 }, + "3979": { "label": "35/4", "naklon": 0 }, + "3959": { "label": "35/5", "naklon": 0 }, + "3948": { "label": "35/6", "naklon": 0 }, + "3961": { "label": "35/7", "naklon": 0 }, + "3956": { "label": "35/8", "naklon": 0 }, + "3604": { "label": "35/9", "naklon": 0 }, + "3944": { "label": "35/10", "naklon": 0 }, + "3960": { "label": "35/11", "naklon": 0 }, + "3958": { "label": "35/12", "naklon": 0 }, + "4036": { "label": "35/13", "naklon": 5 }, + "3893": { "label": "35/18", "naklon": 5 }, + "4108": { "label": "35/19", "naklon": 5 }, + "4017": { "label": "35/20", "naklon": 5 }, + "3963": { "label": "35/21", "naklon": 0 }, + "3658": { "label": "35/22", "naklon": 0 }, + "3975": { "label": "35/23", "naklon": 0 }, + "3980": { "label": "35/24", "naklon": 0 }, + "4012": { "label": "35/25", "naklon": 0 }, + "3655": { "label": "35/26", "naklon": 0 }, + "3962": { "label": "35/27", "naklon": 0 }, + "3945": { "label": "35/28", "naklon": 0 }, + "3569": { "label": "35/29", "naklon": 0 }, + "3429": { "label": "35/30", "naklon": 0 }, + "3657": { "label": "35/31", "naklon": 0 }, + "3646": { "label": "35/32", "naklon": 0 }, + "3622": { "label": "35/33", "naklon": 0 }, + "3612": { "label": "35/34", "naklon": 0 }, + "3955": { "label": "35/35", "naklon": 0 }, + "3878": { "label": "35/37", "naklon": 0 }, + "3965": { "label": "35/38", "naklon": 0 }, + "3970": { "label": "35/39", "naklon": 0 }, + "3611": { "label": "35/40", "naklon": 0 }, + "2635": { "label": "35/41", "naklon": 0 }, + "3978": { "label": "35/42", "naklon": 0 }, + "4213": { "label": "35/43", "naklon": 0 }, + "3984": { "label": "35/44", "naklon": 0 }, + "4218": { "label": "35/45", "naklon": 0 }, + "3973": { "label": "35/46", "naklon": 0 }, + "3974": { "label": "35/47", "naklon": 0 }, + "3759": { "label": "35/48", "naklon": 0 }, + "3844": { "label": "35/49", "naklon": 0 }, + "3804": { "label": "35/50", "naklon": 0 }, + "3831": { "label": "35/51", "naklon": 0 }, + "3643": { "label": "35/52", "naklon": 0 }, + "3966": { "label": "35/53", "naklon": 0 }, + "3971": { "label": "35/54", "naklon": 0 }, + "3650": { "label": "35/55", "naklon": 6 }, + "3651": { "label": "35/56", "naklon": 6 }, + "3669": { "label": "35/57", "naklon": 6 }, + "3648": { "label": "35/58", "naklon": 6 }, + "3645": { "label": "35/59", "naklon": 6 }, + "3659": { "label": "35/60", "naklon": 6 }, + "3647": { "label": "35/61", "naklon": 6 }, + "3644": { "label": "35/62", "naklon": 6 }, + "3671": { "label": "35/63", "naklon": 6 }, + "3682": { "label": "35/64", "naklon": 6 }, + "3672": { "label": "35/65", "naklon": 6 }, + "3683": { "label": "35/66", "naklon": 6 }, + "3673": { "label": "35/67", "naklon": 6 }, + "3674": { "label": "35/68", "naklon": 6 }, + "3679": { "label": "35/69", "naklon": 6 }, + "3649": { "label": "35/70", "naklon": 6 }, + "3687": { "label": "35/71", "naklon": 6 }, + "3677": { "label": "35/72", "naklon": 6 }, + "3690": { "label": "35/73", "naklon": 6 }, + "3691": { "label": "35/74", "naklon": 6 }, + "3676": { "label": "35/75", "naklon": 6 }, + "3680": { "label": "35/76", "naklon": 6 }, + "3668": { "label": "35/77", "naklon": 6 }, + "3681": { "label": "35/78", "naklon": 6 }, + "3670": { "label": "35/79", "naklon": 6 }, + "3689": { "label": "35/80", "naklon": 6 }, + "3678": { "label": "35/81", "naklon": 6 }, + "3693": { "label": "35/82", "naklon": 6 }, + "3654": { "label": "35/83", "naklon": null }, + "4086": { "label": "36/1", "naklon": 0 }, + "4085": { "label": "36/2", "naklon": 0 }, + "4083": { "label": "36/3", "naklon": 0 }, + "4087": { "label": "36/4", "naklon": 0 }, + "4077": { "label": "36/5", "naklon": 0 }, + "4082": { "label": "36/6", "naklon": 0 }, + "4186": { "label": "36/7", "naklon": 0 }, + "4206": { "label": "36/8", "naklon": 0 }, + "4080": { "label": "36/9", "naklon": 0 }, + "4081": { "label": "36/10", "naklon": 0 }, + "4210": { "label": "36/11", "naklon": 0 }, + "4079": { "label": "36/12", "naklon": 0 }, + "4076": { "label": "36/13", "naklon": 0 }, + "3852": { "label": "36/14", "naklon": 0 }, + "2813": { "label": "36/15", "naklon": 0 }, + "4219": { "label": "36/16", "naklon": 0 }, + "3104": { "label": "37/1A", "naklon": 15 }, + "3121": { "label": "37/1B", "naklon": 15 }, + "3113": { "label": "37/2", "naklon": 10 }, + "3118": { "label": "37/3", "naklon": 10 }, + "3111": { "label": "37/4", "naklon": 10 }, + "4020": { "label": "37/5", "naklon": 10 }, + "3119": { "label": "37/6", "naklon": 10 }, + "3110": { "label": "37/7", "naklon": 10 }, + "3108": { "label": "37/8", "naklon": 10 }, + "3107": { "label": "37/12", "naklon": 0 }, + "3199": { "label": "37/13", "naklon": 0 }, + "3120": { "label": "37/14", "naklon": 0 }, + "3122": { "label": "37/15", "naklon": 0 }, + "3908": { "label": "37/16", "naklon": 0 }, + "3114": { "label": "37/17", "naklon": 0 }, + "3105": { "label": "37/18", "naklon": 0 }, + "3116": { "label": "37/19", "naklon": 0 }, + "3106": { "label": "37/20", "naklon": 0 }, + "2887": { "label": "37/21", "naklon": 5 }, + "2888": { "label": "37/22", "naklon": 5 }, + "2877": { "label": "37/23", "naklon": 5 }, + "2891": { "label": "37/24", "naklon": 5 }, + "2886": { "label": "37/25", "naklon": 5 }, + "2892": { "label": "37/26", "naklon": 5 }, + "2882": { "label": "37/27", "naklon": 5 }, + "2883": { "label": "37/28", "naklon": 5 }, + "2876": { "label": "37/29", "naklon": 5 }, + "3109": { "label": "37/30", "naklon": 5 }, + "4152": { "label": "37/31", "naklon": 5 }, + "3117": { "label": "37/32", "naklon": 5 }, + "2870": { "label": "37/33", "naklon": 5 }, + "2867": { "label": "37/34", "naklon": 0 }, + "2865": { "label": "37/35", "naklon": 0 }, + "3096": { "label": "37/36", "naklon": 0 }, + "2871": { "label": "37/37", "naklon": 0 }, + "2884": { "label": "37/38", "naklon": 0 }, + "2855": { "label": "37/39", "naklon": 0 }, + "2878": { "label": "37/40", "naklon": 0 }, + "2889": { "label": "37/41", "naklon": 0 }, + "2879": { "label": "37/42", "naklon": 0 }, + "2850": { "label": "37/43", "naklon": 0 }, + "2894": { "label": "37/44", "naklon": 0 }, + "2880": { "label": "37/45", "naklon": 0 }, + "2893": { "label": "37/46", "naklon": 0 }, + "2890": { "label": "37/47", "naklon": 0 }, + "4355": { "label": "37/48", "naklon": 0 }, + "2885": { "label": "37/49", "naklon": 0 }, + "2875": { "label": "37/50", "naklon": 0 }, + "3486": { "label": "38/30A", "naklon": 5 }, + "3714": { "label": "38/30B", "naklon": 0 }, + "3483": { "label": "38/32A", "naklon": 5 }, + "3496": { "label": "38/32B", "naklon": 0 }, + "3487": { "label": "38/35A", "naklon": 5 }, + "3498": { "label": "38/35B", "naklon": 5 }, + "3578": { "label": "38/38A", "naklon": 5 }, + "3508": { "label": "38/38B", "naklon": 5 }, + "3787": { "label": "38/59A", "naklon": 5 }, + "3491": { "label": "38/59B", "naklon": 5 }, + "3568": { "label": "38/1", "naklon": null }, + "3502": { "label": "38/2", "naklon": 0 }, + "3836": { "label": "38/3", "naklon": 0 }, + "3588": { "label": "38/4", "naklon": 0 }, + "3493": { "label": "38/5", "naklon": 0 }, + "3580": { "label": "38/6", "naklon": 0 }, + "3572": { "label": "38/7", "naklon": 0 }, + "3506": { "label": "38/8", "naklon": 0 }, + "3503": { "label": "38/9", "naklon": 0 }, + "3579": { "label": "38/10", "naklon": 0 }, + "3586": { "label": "38/11", "naklon": 0 }, + "3495": { "label": "38/12", "naklon": 5 }, + "3492": { "label": "38/13", "naklon": 5 }, + "3532": { "label": "38/14", "naklon": 5 }, + "3574": { "label": "38/15", "naklon": 5 }, + "4140": { "label": "38/16", "naklon": 5 }, + "3795": { "label": "38/17", "naklon": 5 }, + "3788": { "label": "38/18", "naklon": 5 }, + "3796": { "label": "38/19", "naklon": 5 }, + "3797": { "label": "38/20", "naklon": 5 }, + "3798": { "label": "38/21", "naklon": 5 }, + "3786": { "label": "38/22", "naklon": 5 }, + "4067": { "label": "38/23", "naklon": 5 }, + "3773": { "label": "38/24", "naklon": 5 }, + "3774": { "label": "38/25", "naklon": 5 }, + "3789": { "label": "38/26", "naklon": 5 }, + "3520": { "label": "38/27", "naklon": null }, + "3577": { "label": "38/29", "naklon": 5 }, + "3530": { "label": "38/31", "naklon": null }, + "3488": { "label": "38/33", "naklon": 5 }, + "3505": { "label": "38/34", "naklon": 5 }, + "3497": { "label": "38/36", "naklon": 5 }, + "3490": { "label": "38/37", "naklon": 5 }, + "3585": { "label": "38/39", "naklon": 5 }, + "3582": { "label": "38/40", "naklon": 5 }, + "3507": { "label": "38/41", "naklon": 5 }, + "3484": { "label": "38/42", "naklon": 5 }, + "3501": { "label": "38/43", "naklon": 5 }, + "3581": { "label": "38/44", "naklon": 5 }, + "4192": { "label": "38/45", "naklon": 5 }, + "3576": { "label": "38/46", "naklon": 5 }, + "3489": { "label": "38/47", "naklon": 5 }, + "3573": { "label": "38/48", "naklon": 5 }, + "3504": { "label": "38/49", "naklon": 5 }, + "3794": { "label": "38/50", "naklon": 5 }, + "3485": { "label": "38/51", "naklon": 5 }, + "3482": { "label": "38/52", "naklon": 5 }, + "3575": { "label": "38/53", "naklon": 5 }, + "3499": { "label": "38/54", "naklon": 5 }, + "3494": { "label": "38/55", "naklon": 5 }, + "3583": { "label": "38/56", "naklon": 5 }, + "3570": { "label": "38/57", "naklon": 5 }, + "3500": { "label": "38/58", "naklon": 0 }, + "3510": { "label": "38/63", "naklon": null }, + "3512": { "label": "38/64", "naklon": null }, + "3535": { "label": "38/67", "naklon": null }, + "3531": { "label": "38/68", "naklon": null }, + "3537": { "label": "38/69", "naklon": null }, + "3522": { "label": "39/1", "naklon": 10 }, + "4018": { "label": "39/2", "naklon": 10 }, + "4019": { "label": "39/3", "naklon": 10 }, + "4154": { "label": "39/4", "naklon": 5 }, + "3907": { "label": "39/5", "naklon": 5 }, + "4148": { "label": "39/6", "naklon": 0 }, + "4153": { "label": "39/7", "naklon": 0 }, + "3938": { "label": "39/8", "naklon": 0 }, + "3802": { "label": "39/9", "naklon": 0 }, + "4015": { "label": "39/10", "naklon": 0 }, + "3929": { "label": "39/11", "naklon": 0 }, + "3946": { "label": "39/12", "naklon": 0 }, + "4014": { "label": "39/13", "naklon": 0 }, + "4155": { "label": "39/14", "naklon": 0 }, + "4149": { "label": "39/15", "naklon": 0 }, + "3642": { "label": "39/16", "naklon": 0 }, + "3636": { "label": "39/17", "naklon": 5 }, + "3991": { "label": "39/18", "naklon": 0 }, + "3994": { "label": "39/19", "naklon": 0 }, + "3990": { "label": "39/20", "naklon": 0 }, + "3967": { "label": "39/21", "naklon": 0 }, + "3977": { "label": "39/22", "naklon": 0 }, + "3757": { "label": "39/23", "naklon": 15 }, + "3633": { "label": "39/24", "naklon": 15 }, + "3744": { "label": "39/25", "naklon": 15 }, + "4023": { "label": "39/26", "naklon": 5 }, + "3720": { "label": "39/27", "naklon": 5 }, + "3734": { "label": "39/28", "naklon": 5 }, + "3741": { "label": "39/29", "naklon": 5 }, + "3721": { "label": "39/30", "naklon": 5 }, + "3845": { "label": "39/31", "naklon": 0 }, + "3840": { "label": "39/32", "naklon": 0 }, + "3837": { "label": "39/33", "naklon": null }, + "3839": { "label": "39/34", "naklon": 0 }, + "3542": { "label": "41/1", "naklon": null }, + "3566": { "label": "41/2", "naklon": null }, + "3548": { "label": "41/3", "naklon": null }, + "3515": { "label": "41/4", "naklon": null }, + "3559": { "label": "41/5", "naklon": null }, + "3509": { "label": "41/6", "naklon": null }, + "3524": { "label": "41/7", "naklon": null }, + "3518": { "label": "41/8", "naklon": null }, + "3182": { "label": "41/9", "naklon": null }, + "3187": { "label": "41/10", "naklon": null }, + "3195": { "label": "41/11", "naklon": 0 }, + "3857": { "label": "41/12", "naklon": 0 }, + "3183": { "label": "41/13", "naklon": 0 }, + "3177": { "label": "41/14", "naklon": 0 }, + "3189": { "label": "41/15", "naklon": 0 }, + "3186": { "label": "41/16", "naklon": 0 }, + "3178": { "label": "42/1", "naklon": 0 }, + "3219": { "label": "42/2", "naklon": 0 }, + "3475": { "label": "42/3", "naklon": 0 }, + "3175": { "label": "42/4", "naklon": 0 }, + "3222": { "label": "42/5", "naklon": 0 }, + "3221": { "label": "42/6", "naklon": 0 }, + "3181": { "label": "42/7", "naklon": 0 }, + "3180": { "label": "42/8", "naklon": 0 }, + "3218": { "label": "42/9", "naklon": 0 }, + "3176": { "label": "42/10", "naklon": 0 }, + "3174": { "label": "42/11", "naklon": 0 }, + "3220": { "label": "42/12", "naklon": 0 }, + "3533": { "label": "42/13", "naklon": null }, + "3543": { "label": "42/14", "naklon": null }, + "3554": { "label": "42/15", "naklon": null }, + "3549": { "label": "42/16", "naklon": null }, + "2857": { "label": "43/1", "naklon": 5 }, + "2752": { "label": "43/2", "naklon": 5 }, + "2753": { "label": "43/3", "naklon": 5 }, + "3024": { "label": "43/4", "naklon": 5 }, + "2754": { "label": "43/5", "naklon": 5 }, + "4423": { "label": "43/6", "naklon": 5 }, + "4368": { "label": "43/7", "naklon": 5 }, + "2978": { "label": "43/8", "naklon": 5 }, + "2868": { "label": "43/9", "naklon": 5 }, + "4377": { "label": "43/10", "naklon": 5 }, + "2757": { "label": "43/11", "naklon": 5 }, + "2970": { "label": "43/12", "naklon": 5 }, + "2758": { "label": "43/13", "naklon": 5 }, + "4378": { "label": "43/14", "naklon": 5 }, + "2759": { "label": "43/15", "naklon": 5 }, + "4342": { "label": "43/16", "naklon": 5 }, + "3026": { "label": "43/17", "naklon": null }, + "2986": { "label": "43/18", "naklon": null }, + "4343": { "label": "43/19", "naklon": null }, + "2760": { "label": "43/20", "naklon": null }, + "4379": { "label": "43/21", "naklon": null }, + "2971": { "label": "43/22", "naklon": null }, + "2761": { "label": "43/23", "naklon": null }, + "2762": { "label": "43/24", "naklon": null }, + "4339": { "label": "43/25", "naklon": null }, + "4380": { "label": "43/26", "naklon": null }, + "2975": { "label": "43/27", "naklon": null }, + "3003": { "label": "43/28", "naklon": null }, + "4338": { "label": "43/29", "naklon": null }, + "3002": { "label": "43/30", "naklon": null }, + "4345": { "label": "43/31", "naklon": null }, + "2979": { "label": "43/32", "naklon": null }, + "2989": { "label": "43/33", "naklon": null }, + "2996": { "label": "43/34", "naklon": null }, + "2972": { "label": "43/35", "naklon": null }, + "2988": { "label": "43/36", "naklon": null }, + "4344": { "label": "43/37", "naklon": null }, + "3022": { "label": "43/38", "naklon": null }, + "4341": { "label": "43/39", "naklon": null }, + "2983": { "label": "43/40", "naklon": null }, + "2995": { "label": "43/41", "naklon": null }, + "2763": { "label": "43/42", "naklon": null }, + "2764": { "label": "43/43", "naklon": null }, + "2765": { "label": "43/44", "naklon": null }, + "2766": { "label": "43/45", "naklon": null }, + "2767": { "label": "43/46", "naklon": null }, + "2768": { "label": "43/47", "naklon": null }, + "3018": { "label": "43/48", "naklon": null }, + "2982": { "label": "43/49", "naklon": null }, + "3019": { "label": "43/50", "naklon": 0 }, + "3013": { "label": "43/51", "naklon": null }, + "3007": { "label": "43/52", "naklon": null }, + "2980": { "label": "43/53", "naklon": null }, + "3011": { "label": "43/54", "naklon": null }, + "2672": { "label": "43/55", "naklon": null }, + "2673": { "label": "43/56", "naklon": null }, + "2674": { "label": "43/57", "naklon": null }, + "2675": { "label": "43/58", "naklon": null }, + "2676": { "label": "43/59", "naklon": null }, + "2677": { "label": "43/60", "naklon": null }, + "2678": { "label": "43/61", "naklon": null }, + "2679": { "label": "43/62", "naklon": null }, + "2680": { "label": "43/63", "naklon": null }, + "2840": { "label": "43/64", "naklon": null }, + "2682": { "label": "43/65", "naklon": null }, + "2683": { "label": "43/66", "naklon": null }, + "2684": { "label": "43/67", "naklon": 0 }, + "2685": { "label": "43/68", "naklon": null }, + "2686": { "label": "43/69", "naklon": null }, + "2687": { "label": "43/70", "naklon": null }, + "2688": { "label": "43/71", "naklon": null }, + "2689": { "label": "43/72", "naklon": null }, + "2690": { "label": "43/73", "naklon": null }, + "2691": { "label": "43/74", "naklon": null }, + "2692": { "label": "43/75", "naklon": null }, + "2693": { "label": "43/76", "naklon": 0 }, + "2694": { "label": "43/77", "naklon": null }, + "2695": { "label": "43/78", "naklon": null }, + "2696": { "label": "43/79", "naklon": 0 }, + "2697": { "label": "43/80", "naklon": null }, + "2698": { "label": "43/81", "naklon": 0 }, + "2699": { "label": "43/82", "naklon": null }, + "2700": { "label": "43/83", "naklon": 0 }, + "2744": { "label": "43/84", "naklon": null }, + "2745": { "label": "43/85", "naklon": 0 }, + "2746": { "label": "43/86", "naklon": null }, + "2747": { "label": "43/87", "naklon": 0 }, + "2748": { "label": "43/88", "naklon": null }, + "2749": { "label": "43/89", "naklon": 0 }, + "2841": { "label": "43/90", "naklon": null }, + "4237": { "label": "45/1", "naklon": 5 }, + "4226": { "label": "45/2", "naklon": 5 }, + "4242": { "label": "45/3", "naklon": 5 }, + "4179": { "label": "45/4", "naklon": 5 }, + "4247": { "label": "45/5", "naklon": 5 }, + "4245": { "label": "45/6", "naklon": 5 }, + "3872": { "label": "45/7", "naklon": 5 }, + "4175": { "label": "45/8", "naklon": 5 }, + "4236": { "label": "45/9", "naklon": 5 }, + "4170": { "label": "45/10", "naklon": 5 }, + "4238": { "label": "45/11", "naklon": 5 }, + "4246": { "label": "45/12", "naklon": 5 }, + "4166": { "label": "45/13", "naklon": 5 }, + "4227": { "label": "45/14", "naklon": 5 }, + "4171": { "label": "45/15", "naklon": 5 }, + "4180": { "label": "45/16", "naklon": 5 }, + "4244": { "label": "45/17", "naklon": 5 }, + "4199": { "label": "45/18", "naklon": 5 }, + "4239": { "label": "45/19", "naklon": 5 }, + "4207": { "label": "45/20", "naklon": 5 }, + "4223": { "label": "45/21", "naklon": 5 }, + "4230": { "label": "45/22", "naklon": 5 }, + "4233": { "label": "45/23", "naklon": 5 }, + "4222": { "label": "45/24", "naklon": 5 }, + "4217": { "label": "45/25", "naklon": 5 }, + "4243": { "label": "45/26", "naklon": 5 }, + "4200": { "label": "45/27", "naklon": 5 }, + "4228": { "label": "45/28", "naklon": 5 }, + "4211": { "label": "45/29", "naklon": 5 }, + "4234": { "label": "45/30", "naklon": 5 }, + "4235": { "label": "45/31", "naklon": 5 }, + "4203": { "label": "45/32", "naklon": 5 }, + "4240": { "label": "45/33", "naklon": 5 }, + "4224": { "label": "45/34", "naklon": 5 }, + "4232": { "label": "45/35", "naklon": 5 }, + "4231": { "label": "45/36", "naklon": 5 }, + "4161": { "label": "45/37", "naklon": 5 }, + "4225": { "label": "45/38", "naklon": 5 }, + "4241": { "label": "45/39", "naklon": 5 }, + "4229": { "label": "45/40", "naklon": 5 }, + "4221": { "label": "45/41", "naklon": 5 }, + "4212": { "label": "45/42", "naklon": 5 }, + "4216": { "label": "45/43", "naklon": 5 }, + "3864": { "label": "45/44", "naklon": null }, + "3806": { "label": "46/1", "naklon": 5 }, + "3813": { "label": "46/2", "naklon": 5 }, + "3815": { "label": "46/3", "naklon": 5 }, + "3807": { "label": "46/4", "naklon": 5 }, + "3895": { "label": "46/5", "naklon": 5 }, + "3809": { "label": "46/6", "naklon": 5 }, + "3820": { "label": "46/7", "naklon": 5 }, + "3805": { "label": "46/8", "naklon": 5 }, + "3894": { "label": "46/9", "naklon": 0 }, + "4055": { "label": "46/10", "naklon": 0 }, + "3812": { "label": "46/11", "naklon": 5 }, + "3822": { "label": "46/12", "naklon": 5 }, + "3821": { "label": "46/13", "naklon": 5 }, + "3808": { "label": "46/14", "naklon": 5 }, + "3799": { "label": "46/15", "naklon": 5 }, + "3816": { "label": "46/16", "naklon": 5 }, + "3751": { "label": "46/17", "naklon": 5 }, + "3814": { "label": "46/18", "naklon": 5 }, + "4044": { "label": "46/19", "naklon": 0 }, + "3931": { "label": "46/20", "naklon": 0 }, + "3902": { "label": "46/21", "naklon": 5 }, + "3916": { "label": "46/22", "naklon": 5 }, + "3892": { "label": "46/23", "naklon": 5 }, + "3914": { "label": "46/24", "naklon": 5 }, + "3898": { "label": "46/25", "naklon": 5 }, + "3897": { "label": "46/26", "naklon": 5 }, + "3885": { "label": "46/27", "naklon": 5 }, + "3906": { "label": "46/28", "naklon": 5 }, + "3930": { "label": "46/29", "naklon": 0 }, + "3936": { "label": "46/30", "naklon": 0 }, + "3860": { "label": "46/31", "naklon": 5 }, + "3841": { "label": "46/32", "naklon": 5 }, + "3873": { "label": "46/33", "naklon": 5 }, + "3854": { "label": "46/34", "naklon": 5 }, + "3939": { "label": "46/35", "naklon": 5 }, + "3858": { "label": "46/36", "naklon": 5 }, + "3940": { "label": "46/37", "naklon": 5 }, + "4035": { "label": "46/38", "naklon": 5 }, + "3373": { "label": "47/1", "naklon": 0 }, + "3374": { "label": "47/2", "naklon": 0 }, + "3384": { "label": "47/3", "naklon": 0 }, + "3385": { "label": "47/4", "naklon": 0 }, + "4051": { "label": "48/1", "naklon": 5 }, + "4041": { "label": "48/2", "naklon": 5 }, + "4056": { "label": "48/3", "naklon": 5 }, + "3875": { "label": "48/4", "naklon": 5 }, + "4061": { "label": "48/5", "naklon": 5 }, + "4047": { "label": "48/6", "naklon": 5 }, + "4060": { "label": "48/7", "naklon": 5 }, + "4059": { "label": "48/8", "naklon": 5 }, + "4058": { "label": "48/9", "naklon": 5 }, + "3635": { "label": "48/10", "naklon": 5 }, + "3640": { "label": "48/11", "naklon": 5 }, + "3747": { "label": "48/12", "naklon": 5 }, + "3629": { "label": "48/13", "naklon": 5 }, + "4048": { "label": "48/14", "naklon": 5 }, + "4063": { "label": "48/15", "naklon": 5 }, + "4062": { "label": "48/16", "naklon": 5 }, + "4043": { "label": "48/17", "naklon": 5 }, + "4052": { "label": "48/18", "naklon": 5 }, + "4042": { "label": "48/19", "naklon": 5 }, + "4053": { "label": "48/20", "naklon": 5 }, + "4167": { "label": "50/15A", "naklon": null }, + "4159": { "label": "50/15B", "naklon": null }, + "4183": { "label": "50/1", "naklon": 0 }, + "4157": { "label": "50/2", "naklon": 0 }, + "4160": { "label": "50/3", "naklon": 0 }, + "4173": { "label": "50/4", "naklon": 0 }, + "4177": { "label": "50/5", "naklon": 0 }, + "4174": { "label": "50/6", "naklon": 0 }, + "4178": { "label": "50/7", "naklon": 0 }, + "4195": { "label": "50/8", "naklon": 0 }, + "4169": { "label": "50/9", "naklon": 0 }, + "4162": { "label": "50/10", "naklon": 0 }, + "4158": { "label": "50/11", "naklon": 0 }, + "4182": { "label": "50/12", "naklon": 0 }, + "4194": { "label": "50/13", "naklon": 0 }, + "4184": { "label": "50/14", "naklon": 0 }, + "4197": { "label": "50/16", "naklon": null }, + "4164": { "label": "50/17", "naklon": null }, + "3306": { "label": "50/18", "naklon": null }, + "4168": { "label": "50/19", "naklon": null }, + "4193": { "label": "50/20", "naklon": null }, + "4187": { "label": "50/21", "naklon": null }, + "4163": { "label": "50/22", "naklon": null }, + "4165": { "label": "50/23", "naklon": null }, + "4185": { "label": "50/24", "naklon": null }, + "3904": { "label": "50/25", "naklon": null }, + "2619": { "label": "53/1", "naklon": 0 }, + "2623": { "label": "53/2", "naklon": 0 }, + "2617": { "label": "53/3", "naklon": 0 }, + "2622": { "label": "53/4", "naklon": 0 }, + "2618": { "label": "53/5", "naklon": 0 }, + "2626": { "label": "53/6", "naklon": 0 }, + "2869": { "label": "53/7", "naklon": 0 }, + "2613": { "label": "53/8", "naklon": 0 }, + "2608": { "label": "53/9", "naklon": 0 }, + "2611": { "label": "53/10", "naklon": 0 }, + "2598": { "label": "53/11", "naklon": 0 }, + "3528": { "label": "53/12", "naklon": 0 }, + "3545": { "label": "53/13", "naklon": 0 }, + "2620": { "label": "53/14", "naklon": 0 }, + "2612": { "label": "53/15", "naklon": 0 }, + "2615": { "label": "53/16", "naklon": 0 }, + "3722": { "label": "53/17", "naklon": 0 }, + "2624": { "label": "53/18", "naklon": 0 }, + "2609": { "label": "53/19", "naklon": 0 }, + "2625": { "label": "53/20", "naklon": 0 }, + "2602": { "label": "53/21", "naklon": 0 }, + "2610": { "label": "53/22", "naklon": 0 }, + "2599": { "label": "53/23", "naklon": 0 }, + "2605": { "label": "53/24", "naklon": 0 }, + "2593": { "label": "53/25", "naklon": 0 }, + "3074": { "label": "53/26", "naklon": 0 }, + "2740": { "label": "53/27", "naklon": 0 }, + "2614": { "label": "53/28", "naklon": 0 }, + "2601": { "label": "53/29", "naklon": 0 }, + "4196": { "label": "53/30", "naklon": 0 }, + "2607": { "label": "53/31", "naklon": 0 }, + "2582": { "label": "53/32", "naklon": 0 }, + "2594": { "label": "53/33", "naklon": 0 }, + "2589": { "label": "53/34", "naklon": 0 }, + "2596": { "label": "53/35", "naklon": 0 }, + "2603": { "label": "53/36", "naklon": 0 }, + "2597": { "label": "53/37", "naklon": 0 }, + "2590": { "label": "53/38", "naklon": 0 }, + "2581": { "label": "53/39", "naklon": 0 }, + "2583": { "label": "53/40", "naklon": 0 }, + "2580": { "label": "53/41", "naklon": 0 }, + "2579": { "label": "53/42", "naklon": 0 }, + "2797": { "label": "53/43", "naklon": 0 }, + "2577": { "label": "53/44", "naklon": 0 }, + "2586": { "label": "53/45", "naklon": 0 }, + "2588": { "label": "53/46", "naklon": 0 }, + "2591": { "label": "53/47", "naklon": 0 }, + "2592": { "label": "53/48", "naklon": 0 }, + "2573": { "label": "53/49", "naklon": 0 }, + "2595": { "label": "53/50", "naklon": 0 }, + "2587": { "label": "53/51", "naklon": 0 }, + "2578": { "label": "53/52", "naklon": 0 }, + "2574": { "label": "53/53", "naklon": 0 }, + "2571": { "label": "53/54", "naklon": 0 }, + "2570": { "label": "53/55", "naklon": 0 }, + "2576": { "label": "53/56", "naklon": 0 }, + "2881": { "label": "53/57", "naklon": 0 }, + "2575": { "label": "53/58", "naklon": 0 }, + "2572": { "label": "53/59", "naklon": 0 }, + "2569": { "label": "53/60", "naklon": 0 }, + "4324": { "label": "55/1", "naklon": 0 }, + "4319": { "label": "55/2", "naklon": 0 }, + "4327": { "label": "55/3", "naklon": 0 }, + "4333": { "label": "55/4", "naklon": 0 }, + "4332": { "label": "55/5", "naklon": 0 }, + "4320": { "label": "55/6", "naklon": 0 }, + "4317": { "label": "55/7", "naklon": 0 }, + "4318": { "label": "55/8", "naklon": 0 }, + "4328": { "label": "55/9", "naklon": 0 }, + "4323": { "label": "55/10", "naklon": 0 }, + "4325": { "label": "55/11", "naklon": 0 }, + "4326": { "label": "55/12", "naklon": 0 }, + "4316": { "label": "55/13", "naklon": 0 }, + "4322": { "label": "55/14", "naklon": 0 }, + "4331": { "label": "55/15", "naklon": 0 }, + "4321": { "label": "55/16", "naklon": 0 }, + "4315": { "label": "55/17", "naklon": 0 }, + "4329": { "label": "55/18", "naklon": 0 }, + "4334": { "label": "55/19", "naklon": 0 }, + "4330": { "label": "55/20", "naklon": 0 } +}; + + +let svetlaSorted = [{ "label": "1/3A", "node": 3993, "naklon": 0 }, +{ "label": "1/3B", "node": 3989, "naklon": 15 }, +{ "label": "1/1", "node": 3976, "naklon": 0 }, +{ "label": "1/2", "node": 4181, "naklon": 0 }, +{ "label": "1/4", "node": 4376, "naklon": 15 }, +{ "label": "1/5", "node": 3868, "naklon": 15 }, +{ "label": "1/6", "node": 3728, "naklon": 15 }, +{ "label": "1/7", "node": 3730, "naklon": 0 }, +{ "label": "1/8", "node": 4374, "naklon": 0 }, +{ "label": "1/9", "node": 3718, "naklon": 15 }, +{ "label": "1/10", "node": 4375, "naklon": 15 }, +{ "label": "1/11", "node": 4172, "naklon": 15 }, +{ "label": "1/12", "node": 4176, "naklon": 15 }, +{ "label": "2/1", "node": 3800, "naklon": 5 }, +{ "label": "2/2", "node": 3823, "naklon": 5 }, +{ "label": "2/3", "node": 3905, "naklon": 5 }, +{ "label": "2/4", "node": 3803, "naklon": 5 }, +{ "label": "2/5", "node": 3817, "naklon": 5 }, +{ "label": "2/6", "node": 3818, "naklon": 5 }, +{ "label": "2/7", "node": 3811, "naklon": 5 }, +{ "label": "2/8", "node": 3915, "naklon": 5 }, +{ "label": "2/9", "node": 3843, "naklon": 10 }, +{ "label": "2/10", "node": 3827, "naklon": 10 }, +{ "label": "2/11", "node": 4220, "naklon": 10 }, +{ "label": "2/12", "node": 3826, "naklon": 10 }, +{ "label": "2/13", "node": 3834, "naklon": 10 }, +{ "label": "2/14", "node": 3838, "naklon": 10 }, +{ "label": "2/15", "node": 2823, "naklon": 10 }, +{ "label": "2/16", "node": 3750, "naklon": 10 }, +{ "label": "2/17", "node": 3378, "naklon": 0 }, +{ "label": "2/18", "node": 3376, "naklon": 0 }, +{ "label": "2/19", "node": 3379, "naklon": 0 }, +{ "label": "2/20", "node": 3285, "naklon": 0 }, +{ "label": "2/21", "node": 3382, "naklon": 0 }, +{ "label": "2/22", "node": 3383, "naklon": 0 }, +{ "label": "2/24", "node": 3375, "naklon": 0 }, +{ "label": "2/25", "node": 3381, "naklon": 0 }, +{ "label": "2/26", "node": 3380, "naklon": 0 }, +{ "label": "2/27", "node": 3828, "naklon": 10 }, +{ "label": "2/28", "node": 3377, "naklon": 0 }, +{ "label": "7/1", "node": 3591, "naklon": 0 }, +{ "label": "7/2", "node": 3587, "naklon": 0 }, +{ "label": "7/3", "node": 3468, "naklon": 0 }, +{ "label": "7/4", "node": 3466, "naklon": 0 }, +{ "label": "7/5", "node": 3474, "naklon": 0 }, +{ "label": "7/6", "node": 3481, "naklon": 0 }, +{ "label": "7/7", "node": 3589, "naklon": 0 }, +{ "label": "7/8", "node": 3472, "naklon": 0 }, +{ "label": "7/9", "node": 3473, "naklon": 0 }, +{ "label": "7/10", "node": 3584, "naklon": 0 }, +{ "label": "7/11", "node": 3571, "naklon": 0 }, +{ "label": "7/12", "node": 3476, "naklon": 0 }, +{ "label": "7/13", "node": 3590, "naklon": 0 }, +{ "label": "7/14", "node": 3478, "naklon": 0 }, +{ "label": "7/15", "node": 3471, "naklon": 0 }, +{ "label": "7/16", "node": 3467, "naklon": 0 }, +{ "label": "7/17", "node": 3479, "naklon": 0 }, +{ "label": "7/18", "node": 3480, "naklon": 0 }, +{ "label": "7/19", "node": 3477, "naklon": 0 }, +{ "label": "12/1", "node": 3362, "naklon": 0 }, +{ "label": "12/2", "node": 3355, "naklon": 0 }, +{ "label": "12/3", "node": 3356, "naklon": 0 }, +{ "label": "12/4", "node": 3349, "naklon": 0 }, +{ "label": "12/5", "node": 3357, "naklon": 0 }, +{ "label": "12/6", "node": 3350, "naklon": 0 }, +{ "label": "12/7", "node": 3353, "naklon": 0 }, +{ "label": "12/8", "node": 3539, "naklon": 0 }, +{ "label": "12/9", "node": 3050, "naklon": 0 }, +{ "label": "12/10", "node": 3361, "naklon": 0 }, +{ "label": "12/11", "node": 3360, "naklon": 0 }, +{ "label": "12/12", "node": 3358, "naklon": 0 }, +{ "label": "12/13", "node": 3541, "naklon": 0 }, +{ "label": "12/14", "node": 3551, "naklon": 0 }, +{ "label": "12/15", "node": 3514, "naklon": 0 }, +{ "label": "12/16", "node": 3547, "naklon": 0 }, +{ "label": "12/17", "node": 3562, "naklon": 0 }, +{ "label": "12/18", "node": 3525, "naklon": 0 }, +{ "label": "12/19", "node": 3558, "naklon": 0 }, +{ "label": "12/20", "node": 3511, "naklon": 0 }, +{ "label": "12/21", "node": 3058, "naklon": 0 }, +{ "label": "12/22", "node": 3062, "naklon": 0 }, +{ "label": "12/23", "node": 3070, "naklon": 0 }, +{ "label": "12/24", "node": 3447, "naklon": 0 }, +{ "label": "12/25", "node": 3056, "naklon": 0 }, +{ "label": "12/26", "node": 3057, "naklon": 0 }, +{ "label": "12/27", "node": 3071, "naklon": 0 }, +{ "label": "12/28", "node": 3061, "naklon": 0 }, +{ "label": "12/29", "node": 3069, "naklon": 0 }, +{ "label": "12/30", "node": 3077, "naklon": 0 }, +{ "label": "12/31", "node": 3080, "naklon": 0 }, +{ "label": "12/32", "node": 3081, "naklon": 0 }, +{ "label": "12/33", "node": 3078, "naklon": 0 }, +{ "label": "12/34", "node": 4037, "naklon": 0 }, +{ "label": "12/35", "node": 3067, "naklon": 0 }, +{ "label": "12/36", "node": 3051, "naklon": 0 }, +{ "label": "12/37", "node": 2924, "naklon": 0 }, +{ "label": "12/38", "node": 3060, "naklon": 0 }, +{ "label": "12/39", "node": 3073, "naklon": 0 }, +{ "label": "12/40", "node": 3469, "naklon": 0 }, +{ "label": "12/41", "node": 2923, "naklon": 0 }, +{ "label": "12/42", "node": 2925, "naklon": 0 }, +{ "label": "12/43", "node": 3359, "naklon": 0 }, +{ "label": "12/44", "node": 3055, "naklon": 0 }, +{ "label": "12/45", "node": 2922, "naklon": 0 }, +{ "label": "12/46", "node": 3084, "naklon": 0 }, +{ "label": "12/47", "node": 3064, "naklon": 0 }, +{ "label": "12/48", "node": 3066, "naklon": 0 }, +{ "label": "12/49", "node": 3072, "naklon": 0 }, +{ "label": "13/13A", "node": 3415, "naklon": 0 }, +{ "label": "13/13B", "node": 3409, "naklon": 0 }, +{ "label": "13/13C", "node": 3399, "naklon": 0 }, +{ "label": "13/29A", "node": 3410, "naklon": 0 }, +{ "label": "13/29B", "node": 3407, "naklon": 0 }, +{ "label": "13/34A", "node": 3405, "naklon": 0 }, +{ "label": "13/34B", "node": 3404, "naklon": 0 }, +{ "label": "13/45A", "node": 3392, "naklon": 0 }, +{ "label": "13/45B", "node": 3386, "naklon": 0 }, +{ "label": "13/60A", "node": 3303, "naklon": 3 }, +{ "label": "13/60B", "node": 3302, "naklon": 3 }, +{ "label": "13/70A", "node": 3319, "naklon": 6 }, +{ "label": "13/70B", "node": 3317, "naklon": 6 }, +{ "label": "13/70C", "node": 3326, "naklon": 6 }, +{ "label": "13/73A", "node": 3351, "naklon": 6 }, +{ "label": "13/73B", "node": 3313, "naklon": 6 }, +{ "label": "13/83A", "node": 3316, "naklon": 0 }, +{ "label": "13/83B", "node": 3320, "naklon": 0 }, +{ "label": "13/95A", "node": 3336, "naklon": 0 }, +{ "label": "13/95B", "node": 3323, "naklon": 0 }, +{ "label": "13/98A", "node": 3339, "naklon": 0 }, +{ "label": "13/98B", "node": 3333, "naklon": 0 }, +{ "label": "13/1", "node": 3425, "naklon": 0 }, +{ "label": "13/2", "node": 3419, "naklon": 0 }, +{ "label": "13/3", "node": 3416, "naklon": 0 }, +{ "label": "13/4", "node": 3332, "naklon": 0 }, +{ "label": "13/5", "node": 3422, "naklon": 0 }, +{ "label": "13/6", "node": 3417, "naklon": 0 }, +{ "label": "13/7", "node": 3418, "naklon": 0 }, +{ "label": "13/8", "node": 3424, "naklon": 0 }, +{ "label": "13/9", "node": 3334, "naklon": 0 }, +{ "label": "13/10", "node": 4363, "naklon": 0 }, +{ "label": "13/11", "node": 3423, "naklon": 0 }, +{ "label": "13/12", "node": 3406, "naklon": 0 }, +{ "label": "13/14", "node": 3411, "naklon": 0 }, +{ "label": "13/15", "node": 3412, "naklon": 0 }, +{ "label": "13/16", "node": 3413, "naklon": 0 }, +{ "label": "13/17", "node": 3414, "naklon": 0 }, +{ "label": "13/18", "node": 3391, "naklon": 0 }, +{ "label": "13/19", "node": 3370, "naklon": 0 }, +{ "label": "13/20", "node": 3369, "naklon": 0 }, +{ "label": "13/21", "node": 3408, "naklon": 0 }, +{ "label": "13/22", "node": 3393, "naklon": 0 }, +{ "label": "13/23", "node": 3128, "naklon": 0 }, +{ "label": "13/24", "node": 3197, "naklon": 0 }, +{ "label": "13/25", "node": 4364, "naklon": 0 }, +{ "label": "13/26", "node": 3155, "naklon": 0 }, +{ "label": "13/27", "node": 3196, "naklon": 0 }, +{ "label": "13/28", "node": 3144, "naklon": 0 }, +{ "label": "13/30", "node": 3150, "naklon": 0 }, +{ "label": "13/31", "node": 3390, "naklon": 0 }, +{ "label": "13/32", "node": 3401, "naklon": 0 }, +{ "label": "13/33", "node": 3275, "naklon": 0 }, +{ "label": "13/35", "node": 3371, "naklon": 0 }, +{ "label": "13/36", "node": 3389, "naklon": 0 }, +{ "label": "13/37", "node": 3388, "naklon": 0 }, +{ "label": "13/38", "node": 3365, "naklon": 0 }, +{ "label": "13/39", "node": 3363, "naklon": 0 }, +{ "label": "13/40", "node": 3397, "naklon": 0 }, +{ "label": "13/40/1", "node": 3567, "naklon": 0 }, +{ "label": "13/41", "node": 3387, "naklon": 0 }, +{ "label": "13/42", "node": 3403, "naklon": 0 }, +{ "label": "13/43", "node": 3147, "naklon": 0 }, +{ "label": "13/44", "node": 3141, "naklon": 0 }, +{ "label": "13/46", "node": 3364, "naklon": 0 }, +{ "label": "13/47", "node": 3367, "naklon": 0 }, +{ "label": "13/48", "node": 3368, "naklon": 0 }, +{ "label": "13/49", "node": 3402, "naklon": 0 }, +{ "label": "13/50", "node": 3366, "naklon": 0 }, +{ "label": "13/51", "node": 3395, "naklon": 0 }, +{ "label": "13/52", "node": 3372, "naklon": 0 }, +{ "label": "13/53", "node": 3394, "naklon": 0 }, +{ "label": "13/54", "node": 3308, "naklon": 0 }, +{ "label": "13/54/1", "node": 3847, "naklon": 0 }, +{ "label": "13/55", "node": 3312, "naklon": 3 }, +{ "label": "13/56", "node": 3309, "naklon": 3 }, +{ "label": "13/57", "node": 3311, "naklon": 3 }, +{ "label": "13/58", "node": 3310, "naklon": 3 }, +{ "label": "13/59", "node": 4365, "naklon": 3 }, +{ "label": "13/60/1", "node": 4093, "naklon": 3 }, +{ "label": "13/61", "node": 3304, "naklon": 3 }, +{ "label": "13/62", "node": 3307, "naklon": 3 }, +{ "label": "13/63", "node": 3271, "naklon": 3 }, +{ "label": "13/64", "node": 3301, "naklon": 3 }, +{ "label": "13/65", "node": 4366, "naklon": 3 }, +{ "label": "13/66", "node": 3300, "naklon": 3 }, +{ "label": "13/67", "node": 3185, "naklon": 0 }, +{ "label": "13/68", "node": 3184, "naklon": 0 }, +{ "label": "13/69", "node": 3188, "naklon": 0 }, +{ "label": "13/71", "node": 3343, "naklon": 6 }, +{ "label": "13/71/1", "node": 3819, "naklon": 6 }, +{ "label": "13/71/2", "node": 3880, "naklon": 6 }, +{ "label": "13/72", "node": 3348, "naklon": 6 }, +{ "label": "13/74", "node": 3344, "naklon": 6 }, +{ "label": "13/75", "node": 3346, "naklon": 6 }, +{ "label": "13/75/1", "node": 3597, "naklon": 6 }, +{ "label": "13/76", "node": 3345, "naklon": 6 }, +{ "label": "13/77", "node": 3322, "naklon": 0 }, +{ "label": "13/78", "node": 3325, "naklon": 0 }, +{ "label": "13/78/1", "node": 4310, "naklon": 0 }, +{ "label": "13/79", "node": 3315, "naklon": 0 }, +{ "label": "13/80", "node": 3328, "naklon": 0 }, +{ "label": "13/81", "node": 3321, "naklon": 0 }, +{ "label": "13/82", "node": 3324, "naklon": 0 }, +{ "label": "13/84", "node": 3140, "naklon": 0 }, +{ "label": "13/85", "node": 3153, "naklon": 0 }, +{ "label": "13/86", "node": 3145, "naklon": 0 }, +{ "label": "13/87", "node": 3134, "naklon": 0 }, +{ "label": "13/88", "node": 3151, "naklon": 0 }, +{ "label": "13/89", "node": 3143, "naklon": 0 }, +{ "label": "13/90", "node": 3318, "naklon": 0 }, +{ "label": "13/91", "node": 3347, "naklon": 0 }, +{ "label": "13/94", "node": 3314, "naklon": 0 }, +{ "label": "13/96", "node": 3331, "naklon": 0 }, +{ "label": "13/97", "node": 3327, "naklon": 0 }, +{ "label": "13/99", "node": 3329, "naklon": 0 }, +{ "label": "13/100", "node": 3337, "naklon": 0 }, +{ "label": "13/101", "node": 3330, "naklon": 0 }, +{ "label": "13/102", "node": 3335, "naklon": 0 }, +{ "label": "13/103", "node": 3420, "naklon": 0 }, +{ "label": "13/104", "node": 3421, "naklon": 0 }, +{ "label": "13/105", "node": 4361, "naklon": 0 }, +{ "label": "13/106", "node": 4362, "naklon": 0 }, +{ "label": "13/107", "node": 3526, "naklon": 0 }, +{ "label": "13/108", "node": 4424, "naklon": null }, +{ "label": "13/109", "node": 3561, "naklon": null }, +{ "label": "13/110", "node": 3527, "naklon": null }, +{ "label": "13/111", "node": 3521, "naklon": null }, +{ "label": "13/112", "node": 3552, "naklon": null }, +{ "label": "13/113", "node": 3544, "naklon": null }, +{ "label": "13/114", "node": 3534, "naklon": null }, +{ "label": "13/115", "node": 3516, "naklon": null }, +{ "label": "13/116", "node": 3513, "naklon": null }, +{ "label": "13/117", "node": 3565, "naklon": null }, +{ "label": "13/118", "node": 3866, "naklon": null }, +{ "label": "14/1", "node": 3136, "naklon": 0 }, +{ "label": "14/2", "node": 3137, "naklon": 0 }, +{ "label": "14/3", "node": 3135, "naklon": 0 }, +{ "label": "14/4", "node": 3149, "naklon": 0 }, +{ "label": "14/5", "node": 3142, "naklon": 0 }, +{ "label": "14/6", "node": 3342, "naklon": 0 }, +{ "label": "14/7", "node": 3340, "naklon": 0 }, +{ "label": "14/8", "node": 3152, "naklon": 0 }, +{ "label": "14/9", "node": 3886, "naklon": 0 }, +{ "label": "14/10", "node": 3341, "naklon": null }, +{ "label": "14/11", "node": 3352, "naklon": null }, +{ "label": "15/1", "node": 3396, "naklon": 5 }, +{ "label": "15/2", "node": 2784, "naklon": 5 }, +{ "label": "15/3", "node": 2788, "naklon": 5 }, +{ "label": "15/4", "node": 2801, "naklon": 5 }, +{ "label": "15/5", "node": 2815, "naklon": 5 }, +{ "label": "15/6", "node": 2829, "naklon": 5 }, +{ "label": "15/7", "node": 2796, "naklon": 5 }, +{ "label": "15/8", "node": 2803, "naklon": 5 }, +{ "label": "15/8/1", "node": 4304, "naklon": 5 }, +{ "label": "15/8/2", "node": 4311, "naklon": 5 }, +{ "label": "15/9", "node": 2821, "naklon": 5 }, +{ "label": "15/10", "node": 3400, "naklon": 5 }, +{ "label": "15/11", "node": 2799, "naklon": 5 }, +{ "label": "15/12", "node": 2804, "naklon": 5 }, +{ "label": "15/12/1", "node": 4303, "naklon": 5 }, +{ "label": "15/12/2", "node": 4309, "naklon": 5 }, +{ "label": "15/13", "node": 2806, "naklon": 5 }, +{ "label": "15/14", "node": 2787, "naklon": 5 }, +{ "label": "15/15", "node": 2809, "naklon": 5 }, +{ "label": "15/16", "node": 2814, "naklon": 0 }, +{ "label": "15/17", "node": 3934, "naklon": 0 }, +{ "label": "15/18", "node": 3192, "naklon": 0 }, +{ "label": "15/19", "node": 2812, "naklon": 0 }, +{ "label": "15/20", "node": 4070, "naklon": 0 }, +{ "label": "15/21", "node": 2826, "naklon": 0 }, +{ "label": "15/22", "node": 2808, "naklon": 3 }, +{ "label": "15/23", "node": 2795, "naklon": 3 }, +{ "label": "15/24", "node": 2807, "naklon": 3 }, +{ "label": "15/25", "node": 2831, "naklon": 0 }, +{ "label": "15/26", "node": 2862, "naklon": null }, +{ "label": "15/27", "node": 2861, "naklon": 0 }, +{ "label": "15/28", "node": 2866, "naklon": 0 }, +{ "label": "15/28/1", "node": 3546, "naklon": 0 }, +{ "label": "15/29", "node": 4146, "naklon": 0 }, +{ "label": "15/29/1", "node": 3001, "naklon": 0 }, +{ "label": "15/30", "node": 2835, "naklon": 0 }, +{ "label": "15/31", "node": 2874, "naklon": 0 }, +{ "label": "15/32", "node": 2852, "naklon": 0 }, +{ "label": "15/33", "node": 2851, "naklon": 0 }, +{ "label": "15/33/1", "node": 3560, "naklon": 0 }, +{ "label": "15/34", "node": 2858, "naklon": 0 }, +{ "label": "15/34/1", "node": 4306, "naklon": 0 }, +{ "label": "15/35", "node": 2856, "naklon": 0 }, +{ "label": "15/36", "node": 2847, "naklon": 0 }, +{ "label": "15/36/1", "node": 3556, "naklon": 0 }, +{ "label": "15/37", "node": 3950, "naklon": 0 }, +{ "label": "15/38", "node": 2848, "naklon": 0 }, +{ "label": "15/39", "node": 2863, "naklon": 0 }, +{ "label": "15/39/1", "node": 4313, "naklon": 0 }, +{ "label": "15/40", "node": 2873, "naklon": 0 }, +{ "label": "15/40/1", "node": 2984, "naklon": 0 }, +{ "label": "15/41", "node": 2854, "naklon": 0 }, +{ "label": "15/42", "node": 2859, "naklon": 0 }, +{ "label": "15/43", "node": 2872, "naklon": 0 }, +{ "label": "15/44", "node": 2849, "naklon": 0 }, +{ "label": "15/45", "node": 2864, "naklon": 0 }, +{ "label": "15/46", "node": 3553, "naklon": null }, +{ "label": "15/47", "node": 3021, "naklon": null }, +{ "label": "15/47/1", "node": 3008, "naklon": null }, +{ "label": "15/48", "node": 3017, "naklon": null }, +{ "label": "15/49", "node": 3014, "naklon": null }, +{ "label": "15/50", "node": 2981, "naklon": null }, +{ "label": "15/51", "node": 3020, "naklon": null }, +{ "label": "15/52", "node": 3027, "naklon": null }, +{ "label": "15/53", "node": 3006, "naklon": null }, +{ "label": "15/54", "node": 3012, "naklon": null }, +{ "label": "15/55", "node": 2738, "naklon": 0 }, +{ "label": "15/56", "node": 2725, "naklon": 0 }, +{ "label": "15/57", "node": 3016, "naklon": null }, +{ "label": "15/58", "node": 3005, "naklon": null }, +{ "label": "15/58/1", "node": 3009, "naklon": null }, +{ "label": "15/59", "node": 3010, "naklon": 0 }, +{ "label": "15/59/1", "node": 3538, "naklon": 0 }, +{ "label": "15/59/2", "node": 4145, "naklon": 0 }, +{ "label": "15/60", "node": 2713, "naklon": 0 }, +{ "label": "15/61", "node": 2789, "naklon": 0 }, +{ "label": "15/62", "node": 2736, "naklon": 0 }, +{ "label": "15/63", "node": 2739, "naklon": 0 }, +{ "label": "15/64", "node": 4346, "naklon": 0 }, +{ "label": "15/65", "node": 2731, "naklon": 0 }, +{ "label": "15/66", "node": 2818, "naklon": 0 }, +{ "label": "15/66/1", "node": 3557, "naklon": 0 }, +{ "label": "15/67", "node": 2822, "naklon": 0 }, +{ "label": "15/68", "node": 2833, "naklon": 0 }, +{ "label": "15/69", "node": 2834, "naklon": 0 }, +{ "label": "15/70", "node": 3097, "naklon": 0 }, +{ "label": "15/71", "node": 2824, "naklon": 0 }, +{ "label": "15/72", "node": 2828, "naklon": 0 }, +{ "label": "15/73", "node": 2600, "naklon": 0 }, +{ "label": "15/73/1", "node": 4314, "naklon": 0 }, +{ "label": "15/74", "node": 2832, "naklon": 0 }, +{ "label": "15/75", "node": 4360, "naklon": 0 }, +{ "label": "15/76", "node": 2846, "naklon": 0 }, +{ "label": "15/77", "node": 2584, "naklon": 0 }, +{ "label": "15/78", "node": 2843, "naklon": 0 }, +{ "label": "15/78/1", "node": 4308, "naklon": 0 }, +{ "label": "15/79", "node": 4144, "naklon": null }, +{ "label": "15/80", "node": 2844, "naklon": 0 }, +{ "label": "15/81", "node": 2842, "naklon": 0 }, +{ "label": "15/82", "node": 2838, "naklon": 0 }, +{ "label": "15/83", "node": 2837, "naklon": null }, +{ "label": "15/83/1", "node": 3555, "naklon": null }, +{ "label": "15/84", "node": 2839, "naklon": 0 }, +{ "label": "15/85", "node": 2830, "naklon": 0 }, +{ "label": "15/86", "node": 4066, "naklon": 0 }, +{ "label": "15/87", "node": 2836, "naklon": 0 }, +{ "label": "15/88", "node": 2911, "naklon": 0 }, +{ "label": "15/89", "node": 2825, "naklon": 0 }, +{ "label": "15/90", "node": 2811, "naklon": 0 }, +{ "label": "15/94", "node": 3740, "naklon": 15 }, +{ "label": "15/95", "node": 2734, "naklon": 15 }, +{ "label": "15/96", "node": 3105, "naklon": 15 }, +{ "label": "15/97", "node": 2732, "naklon": 15 }, +{ "label": "15/98", "node": 2727, "naklon": 15 }, +{ "label": "15/99", "node": 2735, "naklon": 15 }, +{ "label": "15/100", "node": 3926, "naklon": 15 }, +{ "label": "15/101", "node": 2918, "naklon": 0 }, +{ "label": "15/102", "node": 2705, "naklon": 10 }, +{ "label": "15/103", "node": 2708, "naklon": 10 }, +{ "label": "15/104", "node": 2721, "naklon": 10 }, +{ "label": "15/105", "node": 2719, "naklon": 10 }, +{ "label": "15/106", "node": 2919, "naklon": 10 }, +{ "label": "15/107", "node": 3101, "naklon": 10 }, +{ "label": "15/108", "node": 2853, "naklon": 10 }, +{ "label": "15/109", "node": 2715, "naklon": 10 }, +{ "label": "15/110", "node": 2712, "naklon": 0 }, +{ "label": "15/111", "node": 2711, "naklon": 0 }, +{ "label": "15/112", "node": 2709, "naklon": 0 }, +{ "label": "15/113", "node": 2710, "naklon": 0 }, +{ "label": "15/114", "node": 2907, "naklon": 0 }, +{ "label": "15/115", "node": 2906, "naklon": 0 }, +{ "label": "15/116", "node": 2908, "naklon": 0 }, +{ "label": "15/117", "node": 2901, "naklon": 0 }, +{ "label": "15/118", "node": 2913, "naklon": 0 }, +{ "label": "15/119", "node": 3656, "naklon": 0 }, +{ "label": "15/120", "node": 2781, "naklon": 0 }, +{ "label": "15/121", "node": 2802, "naklon": 0 }, +{ "label": "15/122", "node": 2791, "naklon": 0 }, +{ "label": "15/123", "node": 2783, "naklon": 0 }, +{ "label": "15/124", "node": 2794, "naklon": 0 }, +{ "label": "15/125", "node": 3139, "naklon": 0 }, +{ "label": "15/126", "node": 3229, "naklon": 5 }, +{ "label": "15/127", "node": 3239, "naklon": 5 }, +{ "label": "15/128", "node": 3230, "naklon": 5 }, +{ "label": "15/129", "node": 4016, "naklon": null }, +{ "label": "16/16A", "node": 3608, "naklon": 0 }, +{ "label": "16/16B", "node": 4151, "naklon": 0 }, +{ "label": "16/1", "node": 3710, "naklon": 0 }, +{ "label": "16/2", "node": 3726, "naklon": 0 }, +{ "label": "16/3", "node": 3743, "naklon": 0 }, +{ "label": "16/4", "node": 3724, "naklon": 0 }, +{ "label": "16/5", "node": 3712, "naklon": 0 }, +{ "label": "16/6", "node": 3739, "naklon": 0 }, +{ "label": "16/7", "node": 3742, "naklon": 0 }, +{ "label": "16/8", "node": 3731, "naklon": 0 }, +{ "label": "16/9", "node": 3727, "naklon": 0 }, +{ "label": "16/10", "node": 3729, "naklon": 0 }, +{ "label": "16/11", "node": 3736, "naklon": 0 }, +{ "label": "16/12", "node": 3713, "naklon": 0 }, +{ "label": "16/13", "node": 3715, "naklon": 0 }, +{ "label": "16/14", "node": 3733, "naklon": 0 }, +{ "label": "16/15", "node": 3732, "naklon": 0 }, +{ "label": "16/17", "node": 3634, "naklon": 0 }, +{ "label": "16/18", "node": 3610, "naklon": 0 }, +{ "label": "16/19", "node": 3626, "naklon": 0 }, +{ "label": "16/20", "node": 3618, "naklon": 0 }, +{ "label": "16/21", "node": 3619, "naklon": 0 }, +{ "label": "16/22", "node": 3628, "naklon": 0 }, +{ "label": "16/23", "node": 3615, "naklon": 0 }, +{ "label": "16/24", "node": 3609, "naklon": 0 }, +{ "label": "16/25", "node": 3606, "naklon": 0 }, +{ "label": "16/26", "node": 3624, "naklon": 0 }, +{ "label": "16/27", "node": 3627, "naklon": 0 }, +{ "label": "16/28", "node": 3607, "naklon": 0 }, +{ "label": "16/29", "node": 4370, "naklon": 0 }, +{ "label": "16/30", "node": 3692, "naklon": 0 }, +{ "label": "16/31", "node": 3614, "naklon": 0 }, +{ "label": "16/32", "node": 3623, "naklon": 0 }, +{ "label": "16/33", "node": 4373, "naklon": 0 }, +{ "label": "16/34", "node": 3620, "naklon": 0 }, +{ "label": "16/35", "node": 3685, "naklon": 0 }, +{ "label": "16/36", "node": 3616, "naklon": 0 }, +{ "label": "16/37", "node": 3686, "naklon": 0 }, +{ "label": "16/38", "node": 3688, "naklon": 0 }, +{ "label": "16/39", "node": 3684, "naklon": 0 }, +{ "label": "16/40", "node": 3825, "naklon": 0 }, +{ "label": "16/41", "node": 3865, "naklon": 0 }, +{ "label": "16/42", "node": 3824, "naklon": 0 }, +{ "label": "16/43", "node": 3871, "naklon": 0 }, +{ "label": "16/44", "node": 3801, "naklon": 0 }, +{ "label": "16/45", "node": 3862, "naklon": 0 }, +{ "label": "16/46", "node": 3876, "naklon": 0 }, +{ "label": "16/47", "node": 3861, "naklon": 0 }, +{ "label": "16/48", "node": 4215, "naklon": 0 }, +{ "label": "16/49", "node": 3605, "naklon": 10 }, +{ "label": "16/50", "node": 3603, "naklon": 10 }, +{ "label": "16/51", "node": 3592, "naklon": 10 }, +{ "label": "16/52", "node": 3598, "naklon": 10 }, +{ "label": "16/53", "node": 3594, "naklon": 10 }, +{ "label": "16/54", "node": 3593, "naklon": 10 }, +{ "label": "16/55", "node": 3630, "naklon": 10 }, +{ "label": "16/56", "node": 3763, "naklon": 10 }, +{ "label": "16/57", "node": 3746, "naklon": 10 }, +{ "label": "16/58", "node": 3699, "naklon": 0 }, +{ "label": "16/59", "node": 3698, "naklon": 0 }, +{ "label": "16/60", "node": 3709, "naklon": null }, +{ "label": "16/61", "node": 3708, "naklon": 0 }, +{ "label": "16/62", "node": 3703, "naklon": null }, +{ "label": "16/63", "node": 3700, "naklon": 0 }, +{ "label": "16/64", "node": 3701, "naklon": null }, +{ "label": "16/65", "node": 3704, "naklon": 0 }, +{ "label": "16/66", "node": 3707, "naklon": null }, +{ "label": "16/67", "node": 3810, "naklon": 0 }, +{ "label": "16/68", "node": 4208, "naklon": null }, +{ "label": "16/69", "node": 3867, "naklon": 0 }, +{ "label": "16/70", "node": 4372, "naklon": null }, +{ "label": "16/71", "node": 3881, "naklon": 0 }, +{ "label": "16/72", "node": 4204, "naklon": null }, +{ "label": "16/73", "node": 3869, "naklon": 0 }, +{ "label": "16/74", "node": 4202, "naklon": null }, +{ "label": "16/75", "node": 3830, "naklon": 0 }, +{ "label": "16/76", "node": 3870, "naklon": null }, +{ "label": "16/77", "node": 3964, "naklon": 0 }, +{ "label": "16/78", "node": 3849, "naklon": 0 }, +{ "label": "16/79", "node": 3694, "naklon": null }, +{ "label": "16/80", "node": 3717, "naklon": 0 }, +{ "label": "16/81", "node": 3877, "naklon": null }, +{ "label": "16/82", "node": 3755, "naklon": 0 }, +{ "label": "16/83", "node": 3725, "naklon": null }, +{ "label": "16/84", "node": 3716, "naklon": 0 }, +{ "label": "16/85", "node": 3696, "naklon": null }, +{ "label": "16/86", "node": 3702, "naklon": 0 }, +{ "label": "16/87", "node": 3706, "naklon": null }, +{ "label": "16/88", "node": 3850, "naklon": 0 }, +{ "label": "16/89", "node": 3848, "naklon": null }, +{ "label": "16/90", "node": 3737, "naklon": null }, +{ "label": "16/91", "node": 3705, "naklon": 0 }, +{ "label": "16/92", "node": 3723, "naklon": null }, +{ "label": "16/93", "node": 3842, "naklon": 0 }, +{ "label": "16/94", "node": 3735, "naklon": null }, +{ "label": "16/95", "node": 3719, "naklon": 0 }, +{ "label": "16/96", "node": 3697, "naklon": 0 }, +{ "label": "16/97", "node": 3711, "naklon": 0 }, +{ "label": "16/98", "node": 4107, "naklon": null }, +{ "label": "16/99", "node": 4112, "naklon": 5 }, +{ "label": "16/100", "node": 4106, "naklon": 5 }, +{ "label": "16/101", "node": 4111, "naklon": 5 }, +{ "label": "16/102", "node": 4091, "naklon": null }, +{ "label": "16/103", "node": 4104, "naklon": 5 }, +{ "label": "16/104", "node": 4094, "naklon": null }, +{ "label": "16/105", "node": 4089, "naklon": 5 }, +{ "label": "16/106", "node": 4095, "naklon": null }, +{ "label": "16/107", "node": 4102, "naklon": 5 }, +{ "label": "16/108", "node": 4105, "naklon": null }, +{ "label": "16/109", "node": 3859, "naklon": null }, +{ "label": "16/110", "node": 4090, "naklon": 5 }, +{ "label": "16/111", "node": 4110, "naklon": null }, +{ "label": "16/112", "node": 4097, "naklon": 5 }, +{ "label": "16/113", "node": 4099, "naklon": null }, +{ "label": "16/114", "node": 4096, "naklon": null }, +{ "label": "16/115", "node": 4101, "naklon": 5 }, +{ "label": "16/116", "node": 4109, "naklon": null }, +{ "label": "16/117", "node": 4092, "naklon": 5 }, +{ "label": "16/118", "node": 3631, "naklon": null }, +{ "label": "16/119", "node": 3632, "naklon": 0 }, +{ "label": "16/120", "node": 3641, "naklon": null }, +{ "label": "16/121", "node": 3638, "naklon": 0 }, +{ "label": "16/122", "node": 3637, "naklon": null }, +{ "label": "16/123", "node": 4142, "naklon": null }, +{ "label": "16/124", "node": 4147, "naklon": 5 }, +{ "label": "16/125", "node": 4139, "naklon": 5 }, +{ "label": "20/30A", "node": 3172, "naklon": 2 }, +{ "label": "20/30B", "node": 3164, "naklon": 2 }, +{ "label": "20/1", "node": 3247, "naklon": 10 }, +{ "label": "20/2", "node": 3296, "naklon": 10 }, +{ "label": "20/3", "node": 3246, "naklon": 10 }, +{ "label": "20/4", "node": 3270, "naklon": 10 }, +{ "label": "20/5", "node": 3294, "naklon": 10 }, +{ "label": "20/6", "node": 3298, "naklon": 10 }, +{ "label": "20/7", "node": 3297, "naklon": 10 }, +{ "label": "20/8", "node": 3293, "naklon": 10 }, +{ "label": "20/9", "node": 3299, "naklon": 10 }, +{ "label": "20/10", "node": 3295, "naklon": 10 }, +{ "label": "20/11", "node": 3244, "naklon": 10 }, +{ "label": "20/12", "node": 3249, "naklon": 10 }, +{ "label": "20/13", "node": 3268, "naklon": 10 }, +{ "label": "20/14", "node": 3245, "naklon": 10 }, +{ "label": "20/15", "node": 3278, "naklon": 10 }, +{ "label": "20/16", "node": 3280, "naklon": 10 }, +{ "label": "20/17", "node": 3292, "naklon": 10 }, +{ "label": "20/18", "node": 3287, "naklon": 10 }, +{ "label": "20/19", "node": 3282, "naklon": 10 }, +{ "label": "20/20", "node": 3273, "naklon": 0 }, +{ "label": "20/21", "node": 3157, "naklon": 0 }, +{ "label": "20/22", "node": 3283, "naklon": 0 }, +{ "label": "20/23", "node": 3159, "naklon": 0 }, +{ "label": "20/24", "node": 3289, "naklon": 0 }, +{ "label": "20/25", "node": 3163, "naklon": 0 }, +{ "label": "20/26", "node": 3126, "naklon": 0 }, +{ "label": "20/27", "node": 3171, "naklon": 0 }, +{ "label": "20/28", "node": 3162, "naklon": 0 }, +{ "label": "20/29", "node": 3279, "naklon": 10 }, +{ "label": "20/31", "node": 3173, "naklon": 0 }, +{ "label": "20/32", "node": 3127, "naklon": 0 }, +{ "label": "20/33", "node": 3131, "naklon": 0 }, +{ "label": "20/34", "node": 3129, "naklon": 0 }, +{ "label": "20/35", "node": 3276, "naklon": 2 }, +{ "label": "20/36", "node": 3290, "naklon": 2 }, +{ "label": "20/37", "node": 3132, "naklon": 0 }, +{ "label": "20/38", "node": 3138, "naklon": 0 }, +{ "label": "20/39", "node": 3272, "naklon": 0 }, +{ "label": "20/40", "node": 3291, "naklon": 0 }, +{ "label": "20/41", "node": 3277, "naklon": 10 }, +{ "label": "20/42", "node": 3286, "naklon": 10 }, +{ "label": "20/43", "node": 3281, "naklon": 10 }, +{ "label": "20/44", "node": 3288, "naklon": 10 }, +{ "label": "20/45", "node": 3284, "naklon": 10 }, +{ "label": "20/46", "node": 3167, "naklon": 10 }, +{ "label": "20/47", "node": 3872, "naklon": 0 }, +{ "label": "20/48", "node": 3124, "naklon": 0 }, +{ "label": "20/49", "node": 3133, "naklon": 0 }, +{ "label": "20/50", "node": 3158, "naklon": 0 }, +{ "label": "20/51", "node": 3169, "naklon": 0 }, +{ "label": "20/52", "node": 3146, "naklon": 0 }, +{ "label": "20/53", "node": 3160, "naklon": 0 }, +{ "label": "20/54", "node": 3248, "naklon": 0 }, +{ "label": "20/55", "node": 3156, "naklon": 0 }, +{ "label": "20/56", "node": 3161, "naklon": 0 }, +{ "label": "20/57", "node": 3170, "naklon": 0 }, +{ "label": "20/58", "node": 3168, "naklon": 0 }, +{ "label": "20/59", "node": 3125, "naklon": 0 }, +{ "label": "20/60", "node": 3166, "naklon": 0 }, +{ "label": "20/61", "node": 3130, "naklon": 0 }, +{ "label": "20/62", "node": 3563, "naklon": 0 }, +{ "label": "20/63", "node": 3550, "naklon": null }, +{ "label": "20/67", "node": 3269, "naklon": 0 }, +{ "label": "21/1", "node": 2921, "naklon": 0 }, +{ "label": "21/2", "node": 2707, "naklon": 0 }, +{ "label": "21/3", "node": 2723, "naklon": 0 }, +{ "label": "21/4", "node": 2716, "naklon": 0 }, +{ "label": "21/5", "node": 2717, "naklon": 0 }, +{ "label": "21/6", "node": 2720, "naklon": 0 }, +{ "label": "21/7", "node": 2722, "naklon": 0 }, +{ "label": "21/8", "node": 2718, "naklon": 0 }, +{ "label": "21/9", "node": 2724, "naklon": 0 }, +{ "label": "21/10", "node": 2742, "naklon": 0 }, +{ "label": "21/11", "node": 2743, "naklon": 0 }, +{ "label": "21/12", "node": 2733, "naklon": 0 }, +{ "label": "21/14", "node": 2903, "naklon": 0 }, +{ "label": "21/15", "node": 2917, "naklon": 0 }, +{ "label": "21/16", "node": 2897, "naklon": 0 }, +{ "label": "21/17", "node": 2914, "naklon": 0 }, +{ "label": "21/18", "node": 2898, "naklon": 0 }, +{ "label": "21/19", "node": 2773, "naklon": 0 }, +{ "label": "21/20", "node": 2895, "naklon": 0 }, +{ "label": "21/21", "node": 2896, "naklon": 0 }, +{ "label": "21/22", "node": 2771, "naklon": 0 }, +{ "label": "21/23", "node": 2772, "naklon": 0 }, +{ "label": "21/24", "node": 2793, "naklon": 0 }, +{ "label": "21/25", "node": 2902, "naklon": 0 }, +{ "label": "21/26", "node": 2910, "naklon": 0 }, +{ "label": "21/27", "node": 2909, "naklon": 0 }, +{ "label": "21/28", "node": 2920, "naklon": 0 }, +{ "label": "21/29", "node": 2916, "naklon": 0 }, +{ "label": "21/30", "node": 2904, "naklon": 0 }, +{ "label": "21/31", "node": 2915, "naklon": 0 }, +{ "label": "21/32", "node": 2905, "naklon": 0 }, +{ "label": "21/33", "node": 2900, "naklon": 0 }, +{ "label": "21/34", "node": 2899, "naklon": 0 }, +{ "label": "21/36", "node": 2741, "naklon": 0 }, +{ "label": "21/37", "node": 2714, "naklon": 0 }, +{ "label": "21/38", "node": 2701, "naklon": 0 }, +{ "label": "21/39", "node": 2703, "naklon": 0 }, +{ "label": "21/40", "node": 2704, "naklon": 0 }, +{ "label": "21/41", "node": 2702, "naklon": 0 }, +{ "label": "21/42", "node": 2706, "naklon": 0 }, +{ "label": "21/43", "node": 2776, "naklon": 0 }, +{ "label": "21/44", "node": 2770, "naklon": 0 }, +{ "label": "21/45", "node": 2786, "naklon": 0 }, +{ "label": "21/46", "node": 2779, "naklon": 0 }, +{ "label": "21/47", "node": 2782, "naklon": 0 }, +{ "label": "21/48", "node": 2785, "naklon": 0 }, +{ "label": "21/49", "node": 2769, "naklon": 0 }, +{ "label": "21/50", "node": 3354, "naklon": 0 }, +{ "label": "21/51", "node": 2778, "naklon": 0 }, +{ "label": "21/52", "node": 2775, "naklon": 0 }, +{ "label": "21/53", "node": 2780, "naklon": 0 }, +{ "label": "21/54", "node": 2790, "naklon": 0 }, +{ "label": "21/55", "node": 2792, "naklon": 0 }, +{ "label": "21/56", "node": 2774, "naklon": 0 }, +{ "label": "22/1", "node": 2630, "naklon": 0 }, +{ "label": "22/2", "node": 2631, "naklon": 0 }, +{ "label": "22/3", "node": 2632, "naklon": 0 }, +{ "label": "22/4", "node": 2633, "naklon": 0 }, +{ "label": "22/5", "node": 2634, "naklon": 0 }, +{ "label": "22/6", "node": 2636, "naklon": 0 }, +{ "label": "22/7", "node": 4367, "naklon": 0 }, +{ "label": "22/8", "node": 2637, "naklon": 0 }, +{ "label": "22/9", "node": 2638, "naklon": 0 }, +{ "label": "22/10", "node": 2639, "naklon": 0 }, +{ "label": "22/11", "node": 2640, "naklon": 0 }, +{ "label": "22/12", "node": 2641, "naklon": 0 }, +{ "label": "22/13", "node": 2642, "naklon": 0 }, +{ "label": "22/14", "node": 2643, "naklon": 0 }, +{ "label": "22/15", "node": 2644, "naklon": 0 }, +{ "label": "22/16", "node": 2645, "naklon": 0 }, +{ "label": "22/17", "node": 2646, "naklon": 0 }, +{ "label": "22/18", "node": 2647, "naklon": 0 }, +{ "label": "22/19", "node": 2648, "naklon": 0 }, +{ "label": "22/20", "node": 2649, "naklon": 0 }, +{ "label": "22/21", "node": 2650, "naklon": 0 }, +{ "label": "22/22", "node": 2651, "naklon": 0 }, +{ "label": "22/23", "node": 4103, "naklon": 0 }, +{ "label": "22/24", "node": 2653, "naklon": 0 }, +{ "label": "22/25", "node": 2654, "naklon": 0 }, +{ "label": "22/26", "node": 2655, "naklon": 0 }, +{ "label": "22/27", "node": 2656, "naklon": 0 }, +{ "label": "22/28", "node": 2657, "naklon": 0 }, +{ "label": "22/29", "node": 2658, "naklon": 0 }, +{ "label": "22/30", "node": 2659, "naklon": 0 }, +{ "label": "22/31", "node": 2660, "naklon": 0 }, +{ "label": "22/32", "node": 2661, "naklon": 0 }, +{ "label": "22/32/1", "node": 3015, "naklon": 0 }, +{ "label": "22/33", "node": 2662, "naklon": 0 }, +{ "label": "22/34", "node": 2663, "naklon": 0 }, +{ "label": "22/35", "node": 2664, "naklon": 0 }, +{ "label": "22/36", "node": 2665, "naklon": 0 }, +{ "label": "22/37", "node": 2666, "naklon": 0 }, +{ "label": "22/38", "node": 2667, "naklon": 0 }, +{ "label": "22/39", "node": 2668, "naklon": 0 }, +{ "label": "22/40", "node": 2669, "naklon": null }, +{ "label": "22/41", "node": 2670, "naklon": null }, +{ "label": "22/42", "node": 2671, "naklon": null }, +{ "label": "23/9A", "node": 3087, "naklon": 10 }, +{ "label": "23/9B", "node": 3090, "naklon": 10 }, +{ "label": "23/1", "node": 3075, "naklon": 0 }, +{ "label": "23/2", "node": 3089, "naklon": 0 }, +{ "label": "23/3", "node": 3088, "naklon": 0 }, +{ "label": "23/4", "node": 3228, "naklon": 10 }, +{ "label": "23/5", "node": 2751, "naklon": 10 }, +{ "label": "23/6", "node": 3243, "naklon": 10 }, +{ "label": "23/7", "node": 4349, "naklon": 10 }, +{ "label": "23/8", "node": 3102, "naklon": 10 }, +{ "label": "23/10", "node": 3099, "naklon": 10 }, +{ "label": "23/11", "node": 3103, "naklon": 10 }, +{ "label": "23/12", "node": 3093, "naklon": 10 }, +{ "label": "23/13", "node": 3098, "naklon": 10 }, +{ "label": "23/14", "node": 3092, "naklon": 10 }, +{ "label": "23/15", "node": 3233, "naklon": 0 }, +{ "label": "23/16", "node": 3095, "naklon": 0 }, +{ "label": "23/17", "node": 4074, "naklon": 0 }, +{ "label": "23/18", "node": 2729, "naklon": 0 }, +{ "label": "23/19", "node": 3234, "naklon": 0 }, +{ "label": "23/20", "node": 3094, "naklon": 0 }, +{ "label": "23/21", "node": 2817, "naklon": 0 }, +{ "label": "23/22", "node": 3226, "naklon": 0 }, +{ "label": "23/23", "node": 3225, "naklon": 0 }, +{ "label": "23/24", "node": 3237, "naklon": 0 }, +{ "label": "23/25", "node": 4250, "naklon": 0 }, +{ "label": "23/26", "node": 3059, "naklon": 10 }, +{ "label": "23/27", "node": 3238, "naklon": 10 }, +{ "label": "23/28", "node": 3242, "naklon": 10 }, +{ "label": "23/29", "node": 3236, "naklon": 10 }, +{ "label": "23/30", "node": 3112, "naklon": 10 }, +{ "label": "23/31", "node": 3224, "naklon": 0 }, +{ "label": "23/32", "node": 4298, "naklon": 10 }, +{ "label": "23/33", "node": 4150, "naklon": 10 }, +{ "label": "23/34", "node": 3091, "naklon": 10 }, +{ "label": "25/1", "node": 3771, "naklon": 5 }, +{ "label": "25/2", "node": 3777, "naklon": 5 }, +{ "label": "25/3", "node": 3749, "naklon": 5 }, +{ "label": "25/4", "node": 3769, "naklon": 5 }, +{ "label": "25/5", "node": 3765, "naklon": 5 }, +{ "label": "25/6", "node": 3785, "naklon": 5 }, +{ "label": "25/7", "node": 3761, "naklon": 5 }, +{ "label": "25/8", "node": 3758, "naklon": 5 }, +{ "label": "25/9", "node": 3766, "naklon": 5 }, +{ "label": "25/10", "node": 3779, "naklon": 5 }, +{ "label": "25/11", "node": 3899, "naklon": 10 }, +{ "label": "25/12", "node": 3922, "naklon": 10 }, +{ "label": "25/13", "node": 3912, "naklon": 10 }, +{ "label": "25/14", "node": 3933, "naklon": 10 }, +{ "label": "25/15", "node": 3921, "naklon": 10 }, +{ "label": "25/16", "node": 4300, "naklon": 10 }, +{ "label": "25/17", "node": 3927, "naklon": 10 }, +{ "label": "25/18", "node": 3212, "naklon": 10 }, +{ "label": "25/19", "node": 3208, "naklon": 10 }, +{ "label": "25/20", "node": 3207, "naklon": 10 }, +{ "label": "25/21", "node": 4294, "naklon": 10 }, +{ "label": "25/22", "node": 3209, "naklon": 10 }, +{ "label": "25/23", "node": 3745, "naklon": 10 }, +{ "label": "25/24", "node": 3762, "naklon": 10 }, +{ "label": "25/25", "node": 3215, "naklon": 10 }, +{ "label": "25/26", "node": 3210, "naklon": 10 }, +{ "label": "25/27", "node": 3211, "naklon": 10 }, +{ "label": "25/28", "node": 3206, "naklon": 10 }, +{ "label": "25/29", "node": 3918, "naklon": 5 }, +{ "label": "25/30", "node": 3928, "naklon": 5 }, +{ "label": "25/31", "node": 3917, "naklon": 5 }, +{ "label": "25/32", "node": 4029, "naklon": 0 }, +{ "label": "25/33", "node": 4038, "naklon": 0 }, +{ "label": "25/34", "node": 4022, "naklon": 0 }, +{ "label": "25/35", "node": 3937, "naklon": 0 }, +{ "label": "25/36", "node": 3190, "naklon": 0 }, +{ "label": "25/37", "node": 3835, "naklon": 0 }, +{ "label": "25/38", "node": 3201, "naklon": 0 }, +{ "label": "25/39", "node": 3193, "naklon": 0 }, +{ "label": "25/40", "node": 3191, "naklon": 0 }, +{ "label": "25/41", "node": 3203, "naklon": 0 }, +{ "label": "25/42", "node": 4301, "naklon": 0 }, +{ "label": "25/43", "node": 3223, "naklon": 0 }, +{ "label": "25/44", "node": 3202, "naklon": 0 }, +{ "label": "25/45", "node": 3205, "naklon": 0 }, +{ "label": "25/46", "node": 3194, "naklon": 0 }, +{ "label": "25/47", "node": 3198, "naklon": 0 }, +{ "label": "25/48", "node": 3204, "naklon": 0 }, +{ "label": "25/49", "node": 3200, "naklon": 0 }, +{ "label": "25/50", "node": 3216, "naklon": 0 }, +{ "label": "25/51", "node": 3932, "naklon": 5 }, +{ "label": "25/52", "node": 3923, "naklon": 5 }, +{ "label": "25/53", "node": 3913, "naklon": 5 }, +{ "label": "25/54", "node": 3900, "naklon": 5 }, +{ "label": "25/55", "node": 4189, "naklon": 10 }, +{ "label": "25/56", "node": 4191, "naklon": 10 }, +{ "label": "25/57", "node": 3790, "naklon": 10 }, +{ "label": "25/58", "node": 4190, "naklon": 10 }, +{ "label": "25/59", "node": 4302, "naklon": 0 }, +{ "label": "25/60", "node": 4351, "naklon": 0 }, +{ "label": "25/61", "node": 4075, "naklon": 0 }, +{ "label": "25/62", "node": 4071, "naklon": 0 }, +{ "label": "25/63", "node": 3784, "naklon": 0 }, +{ "label": "25/64", "node": 4065, "naklon": 0 }, +{ "label": "25/65", "node": 4297, "naklon": 0 }, +{ "label": "25/66", "node": 4295, "naklon": 0 }, +{ "label": "25/67", "node": 4299, "naklon": 0 }, +{ "label": "25/68", "node": 3772, "naklon": 0 }, +{ "label": "25/69", "node": 3941, "naklon": 0 }, +{ "label": "25/70", "node": 3782, "naklon": 0 }, +{ "label": "25/71", "node": 4068, "naklon": 0 }, +{ "label": "25/72", "node": 4073, "naklon": 0 }, +{ "label": "25/73", "node": 3901, "naklon": 5 }, +{ "label": "25/74", "node": 4296, "naklon": 5 }, +{ "label": "25/75", "node": 3910, "naklon": 5 }, +{ "label": "25/76", "node": 4293, "naklon": 5 }, +{ "label": "25/77", "node": 3919, "naklon": 5 }, +{ "label": "25/78", "node": 3924, "naklon": 5 }, +{ "label": "25/79", "node": 3909, "naklon": 5 }, +{ "label": "25/80", "node": 3896, "naklon": 5 }, +{ "label": "25/81", "node": 3911, "naklon": 5 }, +{ "label": "25/82", "node": 2819, "naklon": 15 }, +{ "label": "25/83", "node": 3776, "naklon": 15 }, +{ "label": "25/84", "node": 3752, "naklon": 15 }, +{ "label": "25/85", "node": 4353, "naklon": 15 }, +{ "label": "25/86", "node": 3791, "naklon": 0 }, +{ "label": "25/87", "node": 3770, "naklon": 0 }, +{ "label": "25/88", "node": 3760, "naklon": 0 }, +{ "label": "25/89", "node": 3115, "naklon": 0 }, +{ "label": "25/90", "node": 3738, "naklon": 0 }, +{ "label": "25/91", "node": 3748, "naklon": 0 }, +{ "label": "25/92", "node": 3753, "naklon": 0 }, +{ "label": "25/93", "node": 3775, "naklon": 0 }, +{ "label": "25/94", "node": 3778, "naklon": 5 }, +{ "label": "25/95", "node": 4078, "naklon": 5 }, +{ "label": "25/96", "node": 4088, "naklon": 5 }, +{ "label": "25/97", "node": 3856, "naklon": 5 }, +{ "label": "25/98", "node": 4084, "naklon": 5 }, +{ "label": "25/99", "node": 4069, "naklon": 5 }, +{ "label": "25/100", "node": 4188, "naklon": 5 }, +{ "label": "25/101", "node": 4064, "naklon": 5 }, +{ "label": "25/102", "node": 3792, "naklon": 5 }, +{ "label": "25/103", "node": 3780, "naklon": 5 }, +{ "label": "25/104", "node": 4034, "naklon": 5 }, +{ "label": "25/105", "node": 4072, "naklon": 5 }, +{ "label": "25/106", "node": 3884, "naklon": 5 }, +{ "label": "25/107", "node": 3793, "naklon": 5 }, +{ "label": "25/108", "node": 3863, "naklon": 5 }, +{ "label": "25/109", "node": 3855, "naklon": 5 }, +{ "label": "33/1", "node": 3846, "naklon": 0 }, +{ "label": "33/2", "node": 3943, "naklon": 0 }, +{ "label": "33/3", "node": 3903, "naklon": 0 }, +{ "label": "33/4", "node": 3982, "naklon": 0 }, +{ "label": "33/5", "node": 3879, "naklon": 0 }, +{ "label": "33/6", "node": 3887, "naklon": 0 }, +{ "label": "33/7", "node": 3920, "naklon": 5 }, +{ "label": "33/8", "node": 3942, "naklon": 5 }, +{ "label": "33/9", "node": 3829, "naklon": null }, +{ "label": "34/79A", "node": 3452, "naklon": 6 }, +{ "label": "34/79B", "node": 3460, "naklon": 6 }, +{ "label": "34/90A", "node": 3443, "naklon": 6 }, +{ "label": "34/90B", "node": 3445, "naklon": 6 }, +{ "label": "34/90C", "node": 3457, "naklon": 6 }, +{ "label": "34/97A", "node": 3461, "naklon": 6 }, +{ "label": "34/97B", "node": 3463, "naklon": 6 }, +{ "label": "34/98A", "node": 3426, "naklon": 6 }, +{ "label": "34/98B", "node": 3444, "naklon": 6 }, +{ "label": "34/99A", "node": 3453, "naklon": 6 }, +{ "label": "34/99B", "node": 3455, "naklon": 6 }, +{ "label": "34/1", "node": 4009, "naklon": 0 }, +{ "label": "34/2", "node": 3602, "naklon": 0 }, +{ "label": "34/3", "node": 3441, "naklon": 0 }, +{ "label": "34/4", "node": 3464, "naklon": 0 }, +{ "label": "34/5", "node": 3883, "naklon": 0 }, +{ "label": "34/6", "node": 4098, "naklon": 0 }, +{ "label": "34/7", "node": 4003, "naklon": 0 }, +{ "label": "34/8", "node": 4004, "naklon": 0 }, +{ "label": "34/9", "node": 3888, "naklon": 0 }, +{ "label": "34/10", "node": 3997, "naklon": 0 }, +{ "label": "34/11", "node": 4006, "naklon": 0 }, +{ "label": "34/12", "node": 4000, "naklon": 0 }, +{ "label": "34/13", "node": 4011, "naklon": 0 }, +{ "label": "34/14", "node": 3999, "naklon": 0 }, +{ "label": "34/15", "node": 3981, "naklon": 0 }, +{ "label": "34/16", "node": 3988, "naklon": 0 }, +{ "label": "34/17", "node": 3986, "naklon": 0 }, +{ "label": "34/18", "node": 3998, "naklon": 0 }, +{ "label": "34/19", "node": 3983, "naklon": 0 }, +{ "label": "34/20", "node": 4005, "naklon": 0 }, +{ "label": "34/21", "node": 4001, "naklon": 0 }, +{ "label": "34/22", "node": 4008, "naklon": 0 }, +{ "label": "34/23", "node": 4002, "naklon": 0 }, +{ "label": "34/24", "node": 3996, "naklon": 0 }, +{ "label": "34/25", "node": 4007, "naklon": 0 }, +{ "label": "34/26", "node": 4113, "naklon": 15 }, +{ "label": "34/27", "node": 3595, "naklon": 5 }, +{ "label": "34/28", "node": 3599, "naklon": 5 }, +{ "label": "34/29", "node": 3601, "naklon": 5 }, +{ "label": "34/30", "node": 4205, "naklon": 0 }, +{ "label": "34/31", "node": 3987, "naklon": null }, +{ "label": "34/32", "node": 4214, "naklon": 0 }, +{ "label": "34/33", "node": 4226, "naklon": 0 }, +{ "label": "34/34", "node": 4209, "naklon": 0 }, +{ "label": "34/35", "node": 4201, "naklon": 0 }, +{ "label": "34/36", "node": 3440, "naklon": 0 }, +{ "label": "34/37", "node": 3465, "naklon": 0 }, +{ "label": "34/38", "node": 3446, "naklon": 0 }, +{ "label": "34/39", "node": 4039, "naklon": 5 }, +{ "label": "34/40", "node": 4057, "naklon": 5 }, +{ "label": "34/41", "node": 3985, "naklon": 0 }, +{ "label": "34/42", "node": 3882, "naklon": 0 }, +{ "label": "34/43", "node": 4040, "naklon": 5 }, +{ "label": "34/44", "node": 3231, "naklon": 0 }, +{ "label": "34/45", "node": 3227, "naklon": 0 }, +{ "label": "34/46", "node": 3431, "naklon": 0 }, +{ "label": "34/47", "node": 4013, "naklon": 0 }, +{ "label": "34/48", "node": 4045, "naklon": 0 }, +{ "label": "34/49", "node": 3949, "naklon": 0 }, +{ "label": "34/50", "node": 3953, "naklon": 0 }, +{ "label": "34/51", "node": 3952, "naklon": 0 }, +{ "label": "34/52", "node": 3995, "naklon": 0 }, +{ "label": "34/53", "node": 3992, "naklon": 0 }, +{ "label": "34/54", "node": 4198, "naklon": 0 }, +{ "label": "34/55", "node": 3935, "naklon": 0 }, +{ "label": "34/56", "node": 4050, "naklon": 0 }, +{ "label": "34/57", "node": 4049, "naklon": 0 }, +{ "label": "34/58", "node": 4054, "naklon": 0 }, +{ "label": "34/59", "node": 3663, "naklon": 6 }, +{ "label": "34/60", "node": 3661, "naklon": 6 }, +{ "label": "34/61", "node": 3664, "naklon": 6 }, +{ "label": "34/62", "node": 3660, "naklon": 6 }, +{ "label": "34/63", "node": 3662, "naklon": 6 }, +{ "label": "34/65", "node": 3665, "naklon": 6 }, +{ "label": "34/66", "node": 3667, "naklon": 6 }, +{ "label": "34/67", "node": 3675, "naklon": 6 }, +{ "label": "34/68", "node": 3666, "naklon": 6 }, +{ "label": "34/69", "node": 3652, "naklon": 6 }, +{ "label": "34/70", "node": 3458, "naklon": 6 }, +{ "label": "34/70/1", "node": 4425, "naklon": 6 }, +{ "label": "34/71", "node": 3459, "naklon": 6 }, +{ "label": "34/72", "node": 3435, "naklon": 6 }, +{ "label": "34/73", "node": 3448, "naklon": 6 }, +{ "label": "34/74", "node": 3451, "naklon": 6 }, +{ "label": "34/75", "node": 3442, "naklon": 6 }, +{ "label": "34/76", "node": 3449, "naklon": 6 }, +{ "label": "34/77", "node": 3450, "naklon": 6 }, +{ "label": "34/78", "node": 3433, "naklon": 6 }, +{ "label": "34/80", "node": 3432, "naklon": 12 }, +{ "label": "34/81", "node": 3470, "naklon": 12 }, +{ "label": "34/82", "node": 3438, "naklon": 12 }, +{ "label": "34/83", "node": 3439, "naklon": 12 }, +{ "label": "34/84", "node": 4028, "naklon": 5 }, +{ "label": "34/85", "node": 3596, "naklon": 5 }, +{ "label": "34/86", "node": 4021, "naklon": 5 }, +{ "label": "34/87", "node": 3437, "naklon": 12 }, +{ "label": "34/88", "node": 3428, "naklon": 12 }, +{ "label": "34/89", "node": 3430, "naklon": 12 }, +{ "label": "34/91", "node": 3454, "naklon": 6 }, +{ "label": "34/92", "node": 3492, "naklon": 6 }, +{ "label": "34/93", "node": 3462, "naklon": 6 }, +{ "label": "34/94", "node": 3427, "naklon": 6 }, +{ "label": "34/95", "node": 3434, "naklon": 6 }, +{ "label": "34/96", "node": 3456, "naklon": 6 }, +{ "label": "34/98/1", "node": 4307, "naklon": 6 }, +{ "label": "35/1", "node": 3968, "naklon": 0 }, +{ "label": "35/2", "node": 3969, "naklon": 0 }, +{ "label": "35/3", "node": 3947, "naklon": 0 }, +{ "label": "35/4", "node": 3979, "naklon": 0 }, +{ "label": "35/5", "node": 3959, "naklon": 0 }, +{ "label": "35/6", "node": 3948, "naklon": 0 }, +{ "label": "35/7", "node": 3961, "naklon": 0 }, +{ "label": "35/8", "node": 3956, "naklon": 0 }, +{ "label": "35/9", "node": 3604, "naklon": 0 }, +{ "label": "35/10", "node": 3944, "naklon": 0 }, +{ "label": "35/11", "node": 3960, "naklon": 0 }, +{ "label": "35/12", "node": 3958, "naklon": 0 }, +{ "label": "35/13", "node": 4036, "naklon": 5 }, +{ "label": "35/18", "node": 3893, "naklon": 5 }, +{ "label": "35/19", "node": 4108, "naklon": 5 }, +{ "label": "35/20", "node": 4017, "naklon": 5 }, +{ "label": "35/21", "node": 3963, "naklon": 0 }, +{ "label": "35/22", "node": 3658, "naklon": 0 }, +{ "label": "35/23", "node": 3975, "naklon": 0 }, +{ "label": "35/24", "node": 3980, "naklon": 0 }, +{ "label": "35/25", "node": 4012, "naklon": 0 }, +{ "label": "35/26", "node": 3655, "naklon": 0 }, +{ "label": "35/27", "node": 3962, "naklon": 0 }, +{ "label": "35/28", "node": 3945, "naklon": 0 }, +{ "label": "35/29", "node": 3569, "naklon": 0 }, +{ "label": "35/30", "node": 3429, "naklon": 0 }, +{ "label": "35/31", "node": 3657, "naklon": 0 }, +{ "label": "35/32", "node": 3646, "naklon": 0 }, +{ "label": "35/33", "node": 3622, "naklon": 0 }, +{ "label": "35/34", "node": 3612, "naklon": 0 }, +{ "label": "35/35", "node": 3955, "naklon": 0 }, +{ "label": "35/37", "node": 3878, "naklon": 0 }, +{ "label": "35/38", "node": 3965, "naklon": 0 }, +{ "label": "35/39", "node": 3970, "naklon": 0 }, +{ "label": "35/40", "node": 3611, "naklon": 0 }, +{ "label": "35/41", "node": 2635, "naklon": 0 }, +{ "label": "35/42", "node": 3978, "naklon": 0 }, +{ "label": "35/43", "node": 4213, "naklon": 0 }, +{ "label": "35/44", "node": 3984, "naklon": 0 }, +{ "label": "35/45", "node": 4218, "naklon": 0 }, +{ "label": "35/46", "node": 3973, "naklon": 0 }, +{ "label": "35/47", "node": 3974, "naklon": 0 }, +{ "label": "35/48", "node": 3759, "naklon": 0 }, +{ "label": "35/49", "node": 3844, "naklon": 0 }, +{ "label": "35/50", "node": 3804, "naklon": 0 }, +{ "label": "35/51", "node": 3831, "naklon": 0 }, +{ "label": "35/52", "node": 3643, "naklon": 0 }, +{ "label": "35/53", "node": 3966, "naklon": 0 }, +{ "label": "35/54", "node": 3971, "naklon": 0 }, +{ "label": "35/55", "node": 3650, "naklon": 6 }, +{ "label": "35/56", "node": 3651, "naklon": 6 }, +{ "label": "35/57", "node": 3669, "naklon": 6 }, +{ "label": "35/58", "node": 3648, "naklon": 6 }, +{ "label": "35/59", "node": 3645, "naklon": 6 }, +{ "label": "35/60", "node": 3659, "naklon": 6 }, +{ "label": "35/61", "node": 3647, "naklon": 6 }, +{ "label": "35/62", "node": 3644, "naklon": 6 }, +{ "label": "35/63", "node": 3671, "naklon": 6 }, +{ "label": "35/64", "node": 3682, "naklon": 6 }, +{ "label": "35/65", "node": 3672, "naklon": 6 }, +{ "label": "35/66", "node": 3683, "naklon": 6 }, +{ "label": "35/67", "node": 3673, "naklon": 6 }, +{ "label": "35/68", "node": 3674, "naklon": 6 }, +{ "label": "35/69", "node": 3679, "naklon": 6 }, +{ "label": "35/70", "node": 3649, "naklon": 6 }, +{ "label": "35/71", "node": 3687, "naklon": 6 }, +{ "label": "35/72", "node": 3677, "naklon": 6 }, +{ "label": "35/73", "node": 3690, "naklon": 6 }, +{ "label": "35/74", "node": 3691, "naklon": 6 }, +{ "label": "35/75", "node": 3676, "naklon": 6 }, +{ "label": "35/76", "node": 3680, "naklon": 6 }, +{ "label": "35/77", "node": 3668, "naklon": 6 }, +{ "label": "35/78", "node": 3681, "naklon": 6 }, +{ "label": "35/79", "node": 3670, "naklon": 6 }, +{ "label": "35/80", "node": 3689, "naklon": 6 }, +{ "label": "35/81", "node": 3678, "naklon": 6 }, +{ "label": "35/82", "node": 3693, "naklon": 6 }, +{ "label": "35/83", "node": 3654, "naklon": null }, +{ "label": "36/1", "node": 4086, "naklon": 0 }, +{ "label": "36/2", "node": 4085, "naklon": 0 }, +{ "label": "36/3", "node": 4083, "naklon": 0 }, +{ "label": "36/4", "node": 4087, "naklon": 0 }, +{ "label": "36/5", "node": 4077, "naklon": 0 }, +{ "label": "36/6", "node": 4082, "naklon": 0 }, +{ "label": "36/7", "node": 4186, "naklon": 0 }, +{ "label": "36/8", "node": 4206, "naklon": 0 }, +{ "label": "36/9", "node": 4080, "naklon": 0 }, +{ "label": "36/10", "node": 4081, "naklon": 0 }, +{ "label": "36/11", "node": 4210, "naklon": 0 }, +{ "label": "36/12", "node": 4079, "naklon": 0 }, +{ "label": "36/13", "node": 4076, "naklon": 0 }, +{ "label": "36/14", "node": 3852, "naklon": 0 }, +{ "label": "36/15", "node": 2813, "naklon": 0 }, +{ "label": "36/16", "node": 4219, "naklon": 0 }, +{ "label": "37/1A", "node": 3104, "naklon": 15 }, +{ "label": "37/1B", "node": 3121, "naklon": 15 }, +{ "label": "37/2", "node": 3113, "naklon": 10 }, +{ "label": "37/3", "node": 3118, "naklon": 10 }, +{ "label": "37/4", "node": 3111, "naklon": 10 }, +{ "label": "37/5", "node": 4020, "naklon": 10 }, +{ "label": "37/6", "node": 3119, "naklon": 10 }, +{ "label": "37/7", "node": 3110, "naklon": 10 }, +{ "label": "37/8", "node": 3108, "naklon": 10 }, +{ "label": "37/12", "node": 3107, "naklon": 0 }, +{ "label": "37/13", "node": 3199, "naklon": 0 }, +{ "label": "37/14", "node": 3120, "naklon": 0 }, +{ "label": "37/15", "node": 3122, "naklon": 0 }, +{ "label": "37/16", "node": 3908, "naklon": 0 }, +{ "label": "37/17", "node": 3114, "naklon": 0 }, +{ "label": "37/18", "node": 3105, "naklon": 0 }, +{ "label": "37/19", "node": 3116, "naklon": 0 }, +{ "label": "37/20", "node": 3106, "naklon": 0 }, +{ "label": "37/21", "node": 2887, "naklon": 5 }, +{ "label": "37/22", "node": 2888, "naklon": 5 }, +{ "label": "37/23", "node": 2877, "naklon": 5 }, +{ "label": "37/24", "node": 2891, "naklon": 5 }, +{ "label": "37/25", "node": 2886, "naklon": 5 }, +{ "label": "37/26", "node": 2892, "naklon": 5 }, +{ "label": "37/27", "node": 2882, "naklon": 5 }, +{ "label": "37/28", "node": 2883, "naklon": 5 }, +{ "label": "37/29", "node": 2876, "naklon": 5 }, +{ "label": "37/30", "node": 3109, "naklon": 5 }, +{ "label": "37/31", "node": 4152, "naklon": 5 }, +{ "label": "37/32", "node": 3117, "naklon": 5 }, +{ "label": "37/33", "node": 2870, "naklon": 5 }, +{ "label": "37/34", "node": 2867, "naklon": 0 }, +{ "label": "37/35", "node": 2865, "naklon": 0 }, +{ "label": "37/36", "node": 3096, "naklon": 0 }, +{ "label": "37/37", "node": 2871, "naklon": 0 }, +{ "label": "37/38", "node": 2884, "naklon": 0 }, +{ "label": "37/39", "node": 2855, "naklon": 0 }, +{ "label": "37/40", "node": 2878, "naklon": 0 }, +{ "label": "37/41", "node": 2889, "naklon": 0 }, +{ "label": "37/42", "node": 2879, "naklon": 0 }, +{ "label": "37/43", "node": 2850, "naklon": 0 }, +{ "label": "37/44", "node": 2894, "naklon": 0 }, +{ "label": "37/45", "node": 2880, "naklon": 0 }, +{ "label": "37/46", "node": 2893, "naklon": 0 }, +{ "label": "37/47", "node": 2890, "naklon": 0 }, +{ "label": "37/48", "node": 4355, "naklon": 0 }, +{ "label": "37/49", "node": 2885, "naklon": 0 }, +{ "label": "37/50", "node": 2875, "naklon": 0 }, +{ "label": "38/30A", "node": 3486, "naklon": 5 }, +{ "label": "38/30B", "node": 3714, "naklon": 0 }, +{ "label": "38/32A", "node": 3483, "naklon": 5 }, +{ "label": "38/32B", "node": 3496, "naklon": 0 }, +{ "label": "38/35A", "node": 3487, "naklon": 5 }, +{ "label": "38/35B", "node": 3498, "naklon": 5 }, +{ "label": "38/38A", "node": 3578, "naklon": 5 }, +{ "label": "38/38B", "node": 3508, "naklon": 5 }, +{ "label": "38/59A", "node": 3787, "naklon": 5 }, +{ "label": "38/59B", "node": 3491, "naklon": 5 }, +{ "label": "38/1", "node": 3568, "naklon": null }, +{ "label": "38/2", "node": 3502, "naklon": 0 }, +{ "label": "38/3", "node": 3836, "naklon": 0 }, +{ "label": "38/4", "node": 3588, "naklon": 0 }, +{ "label": "38/5", "node": 3493, "naklon": 0 }, +{ "label": "38/6", "node": 3580, "naklon": 0 }, +{ "label": "38/7", "node": 3572, "naklon": 0 }, +{ "label": "38/8", "node": 3506, "naklon": 0 }, +{ "label": "38/9", "node": 3503, "naklon": 0 }, +{ "label": "38/10", "node": 3579, "naklon": 0 }, +{ "label": "38/11", "node": 3586, "naklon": 0 }, +{ "label": "38/12", "node": 3495, "naklon": 5 }, +{ "label": "38/13", "node": 3492, "naklon": 5 }, +{ "label": "38/14", "node": 3532, "naklon": 5 }, +{ "label": "38/15", "node": 3574, "naklon": 5 }, +{ "label": "38/16", "node": 4140, "naklon": 5 }, +{ "label": "38/17", "node": 3795, "naklon": 5 }, +{ "label": "38/18", "node": 3788, "naklon": 5 }, +{ "label": "38/19", "node": 3796, "naklon": 5 }, +{ "label": "38/20", "node": 3797, "naklon": 5 }, +{ "label": "38/21", "node": 3798, "naklon": 5 }, +{ "label": "38/22", "node": 3786, "naklon": 5 }, +{ "label": "38/23", "node": 4067, "naklon": 5 }, +{ "label": "38/24", "node": 3773, "naklon": 5 }, +{ "label": "38/25", "node": 3774, "naklon": 5 }, +{ "label": "38/26", "node": 3789, "naklon": 5 }, +{ "label": "38/27", "node": 3520, "naklon": null }, +{ "label": "38/29", "node": 3577, "naklon": 5 }, +{ "label": "38/31", "node": 3530, "naklon": null }, +{ "label": "38/33", "node": 3488, "naklon": 5 }, +{ "label": "38/34", "node": 3505, "naklon": 5 }, +{ "label": "38/36", "node": 3497, "naklon": 5 }, +{ "label": "38/37", "node": 3490, "naklon": 5 }, +{ "label": "38/39", "node": 3585, "naklon": 5 }, +{ "label": "38/40", "node": 3582, "naklon": 5 }, +{ "label": "38/41", "node": 3507, "naklon": 5 }, +{ "label": "38/42", "node": 3484, "naklon": 5 }, +{ "label": "38/43", "node": 3501, "naklon": 5 }, +{ "label": "38/44", "node": 3581, "naklon": 5 }, +{ "label": "38/45", "node": 4192, "naklon": 5 }, +{ "label": "38/46", "node": 3576, "naklon": 5 }, +{ "label": "38/47", "node": 3489, "naklon": 5 }, +{ "label": "38/48", "node": 3573, "naklon": 5 }, +{ "label": "38/49", "node": 3504, "naklon": 5 }, +{ "label": "38/50", "node": 3794, "naklon": 5 }, +{ "label": "38/51", "node": 3485, "naklon": 5 }, +{ "label": "38/52", "node": 3482, "naklon": 5 }, +{ "label": "38/53", "node": 3575, "naklon": 5 }, +{ "label": "38/54", "node": 3499, "naklon": 5 }, +{ "label": "38/55", "node": 3494, "naklon": 5 }, +{ "label": "38/56", "node": 3583, "naklon": 5 }, +{ "label": "38/57", "node": 3570, "naklon": 5 }, +{ "label": "38/58", "node": 3500, "naklon": 0 }, +{ "label": "38/63", "node": 3510, "naklon": null }, +{ "label": "38/64", "node": 3512, "naklon": null }, +{ "label": "38/67", "node": 3535, "naklon": null }, +{ "label": "38/68", "node": 3531, "naklon": null }, +{ "label": "38/69", "node": 3537, "naklon": null }, +{ "label": "39/1", "node": 3522, "naklon": 10 }, +{ "label": "39/2", "node": 4018, "naklon": 10 }, +{ "label": "39/3", "node": 4019, "naklon": 10 }, +{ "label": "39/4", "node": 4154, "naklon": 5 }, +{ "label": "39/5", "node": 3907, "naklon": 5 }, +{ "label": "39/6", "node": 4148, "naklon": 0 }, +{ "label": "39/7", "node": 4153, "naklon": 0 }, +{ "label": "39/8", "node": 3938, "naklon": 0 }, +{ "label": "39/9", "node": 3802, "naklon": 0 }, +{ "label": "39/10", "node": 4015, "naklon": 0 }, +{ "label": "39/11", "node": 3929, "naklon": 0 }, +{ "label": "39/12", "node": 3946, "naklon": 0 }, +{ "label": "39/13", "node": 4014, "naklon": 0 }, +{ "label": "39/14", "node": 4155, "naklon": 0 }, +{ "label": "39/15", "node": 4149, "naklon": 0 }, +{ "label": "39/16", "node": 3642, "naklon": 0 }, +{ "label": "39/17", "node": 3636, "naklon": 5 }, +{ "label": "39/18", "node": 3991, "naklon": 0 }, +{ "label": "39/19", "node": 3994, "naklon": 0 }, +{ "label": "39/20", "node": 3990, "naklon": 0 }, +{ "label": "39/21", "node": 3967, "naklon": 0 }, +{ "label": "39/22", "node": 3977, "naklon": 0 }, +{ "label": "39/23", "node": 3757, "naklon": 15 }, +{ "label": "39/24", "node": 3633, "naklon": 15 }, +{ "label": "39/25", "node": 3744, "naklon": 15 }, +{ "label": "39/26", "node": 4023, "naklon": 5 }, +{ "label": "39/27", "node": 3720, "naklon": 5 }, +{ "label": "39/28", "node": 3734, "naklon": 5 }, +{ "label": "39/29", "node": 3741, "naklon": 5 }, +{ "label": "39/30", "node": 3721, "naklon": 5 }, +{ "label": "39/31", "node": 3845, "naklon": 0 }, +{ "label": "39/32", "node": 3840, "naklon": 0 }, +{ "label": "39/33", "node": 3837, "naklon": null }, +{ "label": "39/34", "node": 3839, "naklon": 0 }, +{ "label": "41/1", "node": 3542, "naklon": null }, +{ "label": "41/2", "node": 3566, "naklon": null }, +{ "label": "41/3", "node": 3548, "naklon": null }, +{ "label": "41/4", "node": 3515, "naklon": null }, +{ "label": "41/5", "node": 3559, "naklon": null }, +{ "label": "41/6", "node": 3509, "naklon": null }, +{ "label": "41/7", "node": 3524, "naklon": null }, +{ "label": "41/8", "node": 3518, "naklon": null }, +{ "label": "41/9", "node": 3182, "naklon": null }, +{ "label": "41/10", "node": 3187, "naklon": null }, +{ "label": "41/11", "node": 3195, "naklon": 0 }, +{ "label": "41/12", "node": 3857, "naklon": 0 }, +{ "label": "41/13", "node": 3183, "naklon": 0 }, +{ "label": "41/14", "node": 3177, "naklon": 0 }, +{ "label": "41/15", "node": 3189, "naklon": 0 }, +{ "label": "41/16", "node": 3186, "naklon": 0 }, +{ "label": "42/1", "node": 3178, "naklon": 0 }, +{ "label": "42/2", "node": 3219, "naklon": 0 }, +{ "label": "42/3", "node": 3475, "naklon": 0 }, +{ "label": "42/4", "node": 3175, "naklon": 0 }, +{ "label": "42/5", "node": 3222, "naklon": 0 }, +{ "label": "42/6", "node": 3221, "naklon": 0 }, +{ "label": "42/7", "node": 3181, "naklon": 0 }, +{ "label": "42/8", "node": 3180, "naklon": 0 }, +{ "label": "42/9", "node": 3218, "naklon": 0 }, +{ "label": "42/10", "node": 3176, "naklon": 0 }, +{ "label": "42/11", "node": 3174, "naklon": 0 }, +{ "label": "42/12", "node": 3220, "naklon": 0 }, +{ "label": "42/13", "node": 3533, "naklon": null }, +{ "label": "42/14", "node": 3543, "naklon": null }, +{ "label": "42/15", "node": 3554, "naklon": null }, +{ "label": "42/16", "node": 3549, "naklon": null }, +{ "label": "43/1", "node": 2857, "naklon": 5 }, +{ "label": "43/2", "node": 2752, "naklon": 5 }, +{ "label": "43/3", "node": 2753, "naklon": 5 }, +{ "label": "43/4", "node": 3024, "naklon": 5 }, +{ "label": "43/5", "node": 2754, "naklon": 5 }, +{ "label": "43/6", "node": 4423, "naklon": 5 }, +{ "label": "43/7", "node": 4368, "naklon": 5 }, +{ "label": "43/8", "node": 2978, "naklon": 5 }, +{ "label": "43/9", "node": 2868, "naklon": 5 }, +{ "label": "43/10", "node": 4377, "naklon": 5 }, +{ "label": "43/11", "node": 2757, "naklon": 5 }, +{ "label": "43/12", "node": 2970, "naklon": 5 }, +{ "label": "43/13", "node": 2758, "naklon": 5 }, +{ "label": "43/14", "node": 4378, "naklon": 5 }, +{ "label": "43/15", "node": 2759, "naklon": 5 }, +{ "label": "43/16", "node": 4342, "naklon": 5 }, +{ "label": "43/17", "node": 3026, "naklon": null }, +{ "label": "43/18", "node": 2986, "naklon": null }, +{ "label": "43/19", "node": 4343, "naklon": null }, +{ "label": "43/20", "node": 2760, "naklon": null }, +{ "label": "43/21", "node": 4379, "naklon": null }, +{ "label": "43/22", "node": 2971, "naklon": null }, +{ "label": "43/23", "node": 2761, "naklon": null }, +{ "label": "43/24", "node": 2762, "naklon": null }, +{ "label": "43/25", "node": 4339, "naklon": null }, +{ "label": "43/26", "node": 4380, "naklon": null }, +{ "label": "43/27", "node": 2975, "naklon": null }, +{ "label": "43/28", "node": 3003, "naklon": null }, +{ "label": "43/29", "node": 4338, "naklon": null }, +{ "label": "43/30", "node": 3002, "naklon": null }, +{ "label": "43/31", "node": 4345, "naklon": null }, +{ "label": "43/32", "node": 2979, "naklon": null }, +{ "label": "43/33", "node": 2989, "naklon": null }, +{ "label": "43/34", "node": 2996, "naklon": null }, +{ "label": "43/35", "node": 2972, "naklon": null }, +{ "label": "43/36", "node": 2988, "naklon": null }, +{ "label": "43/37", "node": 4344, "naklon": null }, +{ "label": "43/38", "node": 3022, "naklon": null }, +{ "label": "43/39", "node": 4341, "naklon": null }, +{ "label": "43/40", "node": 2983, "naklon": null }, +{ "label": "43/41", "node": 2995, "naklon": null }, +{ "label": "43/42", "node": 2763, "naklon": null }, +{ "label": "43/43", "node": 2764, "naklon": null }, +{ "label": "43/44", "node": 2765, "naklon": null }, +{ "label": "43/45", "node": 2766, "naklon": null }, +{ "label": "43/46", "node": 2767, "naklon": null }, +{ "label": "43/47", "node": 2768, "naklon": null }, +{ "label": "43/48", "node": 3018, "naklon": null }, +{ "label": "43/49", "node": 2982, "naklon": null }, +{ "label": "43/50", "node": 3019, "naklon": 0 }, +{ "label": "43/51", "node": 3013, "naklon": null }, +{ "label": "43/52", "node": 3007, "naklon": null }, +{ "label": "43/53", "node": 2980, "naklon": null }, +{ "label": "43/54", "node": 3011, "naklon": null }, +{ "label": "43/55", "node": 2672, "naklon": null }, +{ "label": "43/56", "node": 2673, "naklon": null }, +{ "label": "43/57", "node": 2674, "naklon": null }, +{ "label": "43/58", "node": 2675, "naklon": null }, +{ "label": "43/59", "node": 2676, "naklon": null }, +{ "label": "43/60", "node": 2677, "naklon": null }, +{ "label": "43/61", "node": 2678, "naklon": null }, +{ "label": "43/62", "node": 2679, "naklon": null }, +{ "label": "43/63", "node": 2680, "naklon": null }, +{ "label": "43/64", "node": 2840, "naklon": null }, +{ "label": "43/65", "node": 2682, "naklon": null }, +{ "label": "43/66", "node": 2683, "naklon": null }, +{ "label": "43/67", "node": 2684, "naklon": 0 }, +{ "label": "43/68", "node": 2685, "naklon": null }, +{ "label": "43/69", "node": 2686, "naklon": null }, +{ "label": "43/70", "node": 2687, "naklon": null }, +{ "label": "43/71", "node": 2688, "naklon": null }, +{ "label": "43/72", "node": 2689, "naklon": null }, +{ "label": "43/73", "node": 2690, "naklon": null }, +{ "label": "43/74", "node": 2691, "naklon": null }, +{ "label": "43/75", "node": 2692, "naklon": null }, +{ "label": "43/76", "node": 2693, "naklon": 0 }, +{ "label": "43/77", "node": 2694, "naklon": null }, +{ "label": "43/78", "node": 2695, "naklon": null }, +{ "label": "43/79", "node": 2696, "naklon": 0 }, +{ "label": "43/80", "node": 2697, "naklon": null }, +{ "label": "43/81", "node": 2698, "naklon": 0 }, +{ "label": "43/82", "node": 2699, "naklon": null }, +{ "label": "43/83", "node": 2700, "naklon": 0 }, +{ "label": "43/84", "node": 2744, "naklon": null }, +{ "label": "43/85", "node": 2745, "naklon": 0 }, +{ "label": "43/86", "node": 2746, "naklon": null }, +{ "label": "43/87", "node": 2747, "naklon": 0 }, +{ "label": "43/88", "node": 2748, "naklon": null }, +{ "label": "43/89", "node": 2749, "naklon": 0 }, +{ "label": "43/90", "node": 2841, "naklon": null }, +{ "label": "45/1", "node": 4237, "naklon": 5 }, +{ "label": "45/2", "node": 4226, "naklon": 5 }, +{ "label": "45/3", "node": 4242, "naklon": 5 }, +{ "label": "45/4", "node": 4179, "naklon": 5 }, +{ "label": "45/5", "node": 4247, "naklon": 5 }, +{ "label": "45/6", "node": 4245, "naklon": 5 }, +{ "label": "45/7", "node": 3872, "naklon": 5 }, +{ "label": "45/8", "node": 4175, "naklon": 5 }, +{ "label": "45/9", "node": 4236, "naklon": 5 }, +{ "label": "45/10", "node": 4170, "naklon": 5 }, +{ "label": "45/11", "node": 4238, "naklon": 5 }, +{ "label": "45/12", "node": 4246, "naklon": 5 }, +{ "label": "45/13", "node": 4166, "naklon": 5 }, +{ "label": "45/14", "node": 4227, "naklon": 5 }, +{ "label": "45/15", "node": 4171, "naklon": 5 }, +{ "label": "45/16", "node": 4180, "naklon": 5 }, +{ "label": "45/17", "node": 4244, "naklon": 5 }, +{ "label": "45/18", "node": 4199, "naklon": 5 }, +{ "label": "45/19", "node": 4239, "naklon": 5 }, +{ "label": "45/20", "node": 4207, "naklon": 5 }, +{ "label": "45/21", "node": 4223, "naklon": 5 }, +{ "label": "45/22", "node": 4230, "naklon": 5 }, +{ "label": "45/23", "node": 4233, "naklon": 5 }, +{ "label": "45/24", "node": 4222, "naklon": 5 }, +{ "label": "45/25", "node": 4217, "naklon": 5 }, +{ "label": "45/26", "node": 4243, "naklon": 5 }, +{ "label": "45/27", "node": 4200, "naklon": 5 }, +{ "label": "45/28", "node": 4228, "naklon": 5 }, +{ "label": "45/29", "node": 4211, "naklon": 5 }, +{ "label": "45/30", "node": 4234, "naklon": 5 }, +{ "label": "45/31", "node": 4235, "naklon": 5 }, +{ "label": "45/32", "node": 4203, "naklon": 5 }, +{ "label": "45/33", "node": 4240, "naklon": 5 }, +{ "label": "45/34", "node": 4224, "naklon": 5 }, +{ "label": "45/35", "node": 4232, "naklon": 5 }, +{ "label": "45/36", "node": 4231, "naklon": 5 }, +{ "label": "45/37", "node": 4161, "naklon": 5 }, +{ "label": "45/38", "node": 4225, "naklon": 5 }, +{ "label": "45/39", "node": 4241, "naklon": 5 }, +{ "label": "45/40", "node": 4229, "naklon": 5 }, +{ "label": "45/41", "node": 4221, "naklon": 5 }, +{ "label": "45/42", "node": 4212, "naklon": 5 }, +{ "label": "45/43", "node": 4216, "naklon": 5 }, +{ "label": "45/44", "node": 3864, "naklon": null }, +{ "label": "46/1", "node": 3806, "naklon": 5 }, +{ "label": "46/2", "node": 3813, "naklon": 5 }, +{ "label": "46/3", "node": 3815, "naklon": 5 }, +{ "label": "46/4", "node": 3807, "naklon": 5 }, +{ "label": "46/5", "node": 3895, "naklon": 5 }, +{ "label": "46/6", "node": 3809, "naklon": 5 }, +{ "label": "46/7", "node": 3820, "naklon": 5 }, +{ "label": "46/8", "node": 3805, "naklon": 5 }, +{ "label": "46/9", "node": 3894, "naklon": 0 }, +{ "label": "46/10", "node": 4055, "naklon": 0 }, +{ "label": "46/11", "node": 3812, "naklon": 5 }, +{ "label": "46/12", "node": 3822, "naklon": 5 }, +{ "label": "46/13", "node": 3821, "naklon": 5 }, +{ "label": "46/14", "node": 3808, "naklon": 5 }, +{ "label": "46/15", "node": 3799, "naklon": 5 }, +{ "label": "46/16", "node": 3816, "naklon": 5 }, +{ "label": "46/17", "node": 3751, "naklon": 5 }, +{ "label": "46/18", "node": 3814, "naklon": 5 }, +{ "label": "46/19", "node": 4044, "naklon": 0 }, +{ "label": "46/20", "node": 3931, "naklon": 0 }, +{ "label": "46/21", "node": 3902, "naklon": 5 }, +{ "label": "46/22", "node": 3916, "naklon": 5 }, +{ "label": "46/23", "node": 3892, "naklon": 5 }, +{ "label": "46/24", "node": 3914, "naklon": 5 }, +{ "label": "46/25", "node": 3898, "naklon": 5 }, +{ "label": "46/26", "node": 3897, "naklon": 5 }, +{ "label": "46/27", "node": 3885, "naklon": 5 }, +{ "label": "46/28", "node": 3906, "naklon": 5 }, +{ "label": "46/29", "node": 3930, "naklon": 0 }, +{ "label": "46/30", "node": 3936, "naklon": 0 }, +{ "label": "46/31", "node": 3860, "naklon": 5 }, +{ "label": "46/32", "node": 3841, "naklon": 5 }, +{ "label": "46/33", "node": 3873, "naklon": 5 }, +{ "label": "46/34", "node": 3854, "naklon": 5 }, +{ "label": "46/35", "node": 3939, "naklon": 5 }, +{ "label": "46/36", "node": 3858, "naklon": 5 }, +{ "label": "46/37", "node": 3940, "naklon": 5 }, +{ "label": "46/38", "node": 4035, "naklon": 5 }, +{ "label": "47/1", "node": 3373, "naklon": 0 }, +{ "label": "47/2", "node": 3374, "naklon": 0 }, +{ "label": "47/3", "node": 3384, "naklon": 0 }, +{ "label": "47/4", "node": 3385, "naklon": 0 }, +{ "label": "48/1", "node": 4051, "naklon": 5 }, +{ "label": "48/2", "node": 4041, "naklon": 5 }, +{ "label": "48/3", "node": 4056, "naklon": 5 }, +{ "label": "48/4", "node": 3875, "naklon": 5 }, +{ "label": "48/5", "node": 4061, "naklon": 5 }, +{ "label": "48/6", "node": 4047, "naklon": 5 }, +{ "label": "48/7", "node": 4060, "naklon": 5 }, +{ "label": "48/8", "node": 4059, "naklon": 5 }, +{ "label": "48/9", "node": 4058, "naklon": 5 }, +{ "label": "48/10", "node": 3635, "naklon": 5 }, +{ "label": "48/11", "node": 3640, "naklon": 5 }, +{ "label": "48/12", "node": 3747, "naklon": 5 }, +{ "label": "48/13", "node": 3629, "naklon": 5 }, +{ "label": "48/14", "node": 4048, "naklon": 5 }, +{ "label": "48/15", "node": 4063, "naklon": 5 }, +{ "label": "48/16", "node": 4062, "naklon": 5 }, +{ "label": "48/17", "node": 4043, "naklon": 5 }, +{ "label": "48/18", "node": 4052, "naklon": 5 }, +{ "label": "48/19", "node": 4042, "naklon": 5 }, +{ "label": "48/20", "node": 4053, "naklon": 5 }, +{ "label": "50/15A", "node": 4167, "naklon": null }, +{ "label": "50/15B", "node": 4159, "naklon": null }, +{ "label": "50/1", "node": 4183, "naklon": 0 }, +{ "label": "50/2", "node": 4157, "naklon": 0 }, +{ "label": "50/3", "node": 4160, "naklon": 0 }, +{ "label": "50/4", "node": 4173, "naklon": 0 }, +{ "label": "50/5", "node": 4177, "naklon": 0 }, +{ "label": "50/6", "node": 4174, "naklon": 0 }, +{ "label": "50/7", "node": 4178, "naklon": 0 }, +{ "label": "50/8", "node": 4195, "naklon": 0 }, +{ "label": "50/9", "node": 4169, "naklon": 0 }, +{ "label": "50/10", "node": 4162, "naklon": 0 }, +{ "label": "50/11", "node": 4158, "naklon": 0 }, +{ "label": "50/12", "node": 4182, "naklon": 0 }, +{ "label": "50/13", "node": 4194, "naklon": 0 }, +{ "label": "50/14", "node": 4184, "naklon": 0 }, +{ "label": "50/16", "node": 4197, "naklon": null }, +{ "label": "50/17", "node": 4164, "naklon": null }, +{ "label": "50/18", "node": 3306, "naklon": null }, +{ "label": "50/19", "node": 4168, "naklon": null }, +{ "label": "50/20", "node": 4193, "naklon": null }, +{ "label": "50/21", "node": 4187, "naklon": null }, +{ "label": "50/22", "node": 4163, "naklon": null }, +{ "label": "50/23", "node": 4165, "naklon": null }, +{ "label": "50/24", "node": 4185, "naklon": null }, +{ "label": "50/25", "node": 3904, "naklon": null }, +{ "label": "53/1", "node": 2619, "naklon": 0 }, +{ "label": "53/2", "node": 2623, "naklon": 0 }, +{ "label": "53/3", "node": 2617, "naklon": 0 }, +{ "label": "53/4", "node": 2622, "naklon": 0 }, +{ "label": "53/5", "node": 2618, "naklon": 0 }, +{ "label": "53/6", "node": 2626, "naklon": 0 }, +{ "label": "53/7", "node": 2869, "naklon": 0 }, +{ "label": "53/8", "node": 2613, "naklon": 0 }, +{ "label": "53/9", "node": 2608, "naklon": 0 }, +{ "label": "53/10", "node": 2611, "naklon": 0 }, +{ "label": "53/11", "node": 2598, "naklon": 0 }, +{ "label": "53/12", "node": 3528, "naklon": 0 }, +{ "label": "53/13", "node": 3545, "naklon": 0 }, +{ "label": "53/14", "node": 2620, "naklon": 0 }, +{ "label": "53/15", "node": 2612, "naklon": 0 }, +{ "label": "53/16", "node": 2615, "naklon": 0 }, +{ "label": "53/17", "node": 3722, "naklon": 0 }, +{ "label": "53/18", "node": 2624, "naklon": 0 }, +{ "label": "53/19", "node": 2609, "naklon": 0 }, +{ "label": "53/20", "node": 2625, "naklon": 0 }, +{ "label": "53/21", "node": 2602, "naklon": 0 }, +{ "label": "53/22", "node": 2610, "naklon": 0 }, +{ "label": "53/23", "node": 2599, "naklon": 0 }, +{ "label": "53/24", "node": 2605, "naklon": 0 }, +{ "label": "53/25", "node": 2593, "naklon": 0 }, +{ "label": "53/26", "node": 3074, "naklon": 0 }, +{ "label": "53/27", "node": 2740, "naklon": 0 }, +{ "label": "53/28", "node": 2614, "naklon": 0 }, +{ "label": "53/29", "node": 2601, "naklon": 0 }, +{ "label": "53/30", "node": 4196, "naklon": 0 }, +{ "label": "53/31", "node": 2607, "naklon": 0 }, +{ "label": "53/32", "node": 2582, "naklon": 0 }, +{ "label": "53/33", "node": 2594, "naklon": 0 }, +{ "label": "53/34", "node": 2589, "naklon": 0 }, +{ "label": "53/35", "node": 2596, "naklon": 0 }, +{ "label": "53/36", "node": 2603, "naklon": 0 }, +{ "label": "53/37", "node": 2597, "naklon": 0 }, +{ "label": "53/38", "node": 2590, "naklon": 0 }, +{ "label": "53/39", "node": 2581, "naklon": 0 }, +{ "label": "53/40", "node": 2583, "naklon": 0 }, +{ "label": "53/41", "node": 2580, "naklon": 0 }, +{ "label": "53/42", "node": 2579, "naklon": 0 }, +{ "label": "53/43", "node": 2797, "naklon": 0 }, +{ "label": "53/44", "node": 2577, "naklon": 0 }, +{ "label": "53/45", "node": 2586, "naklon": 0 }, +{ "label": "53/46", "node": 2588, "naklon": 0 }, +{ "label": "53/47", "node": 2591, "naklon": 0 }, +{ "label": "53/48", "node": 2592, "naklon": 0 }, +{ "label": "53/49", "node": 2573, "naklon": 0 }, +{ "label": "53/50", "node": 2595, "naklon": 0 }, +{ "label": "53/51", "node": 2587, "naklon": 0 }, +{ "label": "53/52", "node": 2578, "naklon": 0 }, +{ "label": "53/53", "node": 2574, "naklon": 0 }, +{ "label": "53/54", "node": 2571, "naklon": 0 }, +{ "label": "53/55", "node": 2570, "naklon": 0 }, +{ "label": "53/56", "node": 2576, "naklon": 0 }, +{ "label": "53/57", "node": 2881, "naklon": 0 }, +{ "label": "53/58", "node": 2575, "naklon": 0 }, +{ "label": "53/59", "node": 2572, "naklon": 0 }, +{ "label": "53/60", "node": 2569, "naklon": 0 }, +{ "label": "55/1", "node": 4324, "naklon": 0 }, +{ "label": "55/2", "node": 4319, "naklon": 0 }, +{ "label": "55/3", "node": 4327, "naklon": 0 }, +{ "label": "55/4", "node": 4333, "naklon": 0 }, +{ "label": "55/5", "node": 4332, "naklon": 0 }, +{ "label": "55/6", "node": 4320, "naklon": 0 }, +{ "label": "55/7", "node": 4317, "naklon": 0 }, +{ "label": "55/8", "node": 4318, "naklon": 0 }, +{ "label": "55/9", "node": 4328, "naklon": 0 }, +{ "label": "55/10", "node": 4323, "naklon": 0 }, +{ "label": "55/11", "node": 4325, "naklon": 0 }, +{ "label": "55/12", "node": 4326, "naklon": 0 }, +{ "label": "55/13", "node": 4316, "naklon": 0 }, +{ "label": "55/14", "node": 4322, "naklon": 0 }, +{ "label": "55/15", "node": 4331, "naklon": 0 }, +{ "label": "55/16", "node": 4321, "naklon": 0 }, +{ "label": "55/17", "node": 4315, "naklon": 0 }, +{ "label": "55/18", "node": 4329, "naklon": 0 }, +{ "label": "55/19", "node": 4334, "naklon": 0 }, +{ "label": "55/20", "node": 4330, "naklon": 0 } +]; + +module.exports = { naklony }; diff --git a/RVO39/databases/modbus_config.js b/RVO39/databases/modbus_config.js new file mode 100755 index 0000000..b73116a --- /dev/null +++ b/RVO39/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/RVO39/databases/nodes.table b/RVO39/databases/nodes.table new file mode 100755 index 0000000..8a67481 --- /dev/null +++ b/RVO39/databases/nodes.table @@ -0,0 +1,35 @@ +node:number|pole_number:string|node_type:string|tbname:string|line:number|profile:string|processed:boolean|status:boolean|time_of_last_communication:number ++|4153|7|NEMA|d5xjWYMwEJon6rLlK7yBYmAqgV4DaOeNB9ZX3Gzb|1||1|1|1760573925545|............. ++|3734|28|NEMA|EjgWGnXaLy9opPOz20n69V086BlYM3w1deVQvbKr|1||1|1|1760573789860|............. ++|4155|14|NEMA|eod9aRWLVl34Gx1Dn7VoaaA2rz6qjgmpEXwQJN5Z|1||1|1|1760573929890|............. ++|3522|1|NEMA|RO8rjaBDy21qPQJzW7oD96ApK3xmNleVZg9Ed4Gw|1||1|1|1760573774187|............. ++|3741|29|NEMA|wvKJdZML6mXP4DzWBAXWN17jxNloa5g23Ve9Y1ry|1||1|1|1760573800325|............. ++|3744|25|NEMA|ZmRwd93QL4gaezxEbAxW5O71prn2XjlPvGyqJ6BO|1||1|1|1760573809303|............. ++|3757|23|NEMA|roKgWqY95V3mXMRzyAjm8D7bLjexpJPvaGDBw826|1||1|1|1760573817355|............. ++|3802|9|NEMA|K94XLav1glVRnyQ6r01BNzkme3YJwBxM5oOzdP2j|1||1|1|1760573950930|............. ++|3636|17|NEMA|wvKJdZML6mXP4DzWBAXWNW7jxNloa5g23Ve9Y1ry|1||1|1|1760573925081|............. ++|3642|16|NEMA|EjgWGnXaLy9opPOz20n694086BlYM3w1deVQvbKr|1||1|1|1760573779540|............. ++|4761|27|NEMA|3a5oqJN1bgnx4Ol9dk86NZAByE6jQ8mKDWMpGrLV|1||1|1|1760573933580|............. ++|3837|33|NEMA|wvKJdZML6mXP4DzWBAXWq87jxNloa5g23Ve9Y1ry|1||1|1|1760573930305|............. ++|3839|34|NEMA|Nzp2OoJlqn6r1ZgvdA3GxEAabBwP5G4eE3RQmyxD|1||1|1|1760573951617|............. ++|3840|32|NEMA|EjgWGnXaLy9opPOz20n6wQ086BlYM3w1deVQvbKr|1||1|1|1760573930689|............. ++|3845|31|NEMA|3a5oqJN1bgnx4Ol9dk863qAByE6jQ8mKDWMpGrLV|1||1|1|1760573864836|............. ++|3907|5|NEMA|PjLblDgRBO6WQqnxmkJ59r0Jv3ewZN4p5a89yKdY|1||1|1|1760573871881|............. ++|3929|11|NEMA|B5EoxeMVp4zwr8nqW0GjDpARjvD1PNamOGbLg63Z|1||1|1|1760573934395|............. ++|3938|8|NEMA|gRoJEyXVx4qD9er287LP1v7wBzGldaPjLWQKm3Mv|1||1|1|1760573907252|............. ++|3946|12|NEMA|aw4eELG2DlPMdn1JW0B1DnAqQXOZRN3xB5yp8VKr|1||1|1|1760573885269|............. ++|3967|21|NEMA|rDbQ84xzwgdqEoPm3kbJw3k9anOZY1RXyBv2LVM6|1||1|1|1760573959845|............. ++|3977|22|NEMA|E6Kg9oDnLWyzPRMva7vrwa7Jxp4VG58qO2w1lZYe|1||1|1|1760573910527|............. ++|3990|20|NEMA|52dD6ZlV1QaOpRBmbAqKZgkKnGzWMLj4eJq38Pgo|1||1|1|1760573962145|............. ++|3991|18|NEMA|Nzp2OoJlqn6r1ZgvdA3GWdAabBwP5G4eE3RQmyxD|1||1|1|1760573886707|............. ++|3994|19|NEMA|PLBJzmK1r3Gynd6OW0gGdM0e5wV4vx9bDEqNgYR8|1||1|1|1760573888880|............. ++|2870|13|NEMA|ZmRwd93QL4gaezxEbAxW5971prn2XjlPvGyqJ6BO|1||1|1|1760573935961|............. ++|4015|10|NEMA|d9x2V5LGYBzXp4mMRAOBDj7PloaqJwnQj6DgrNe3|1||1|1|1760574001511|............. ++|3718|2|NEMA|3JjOWdylwgNLzxVab7NEznkZ2vG64rq8PEB5QmDo|1||1|1|1760573789556|............. ++|4019|3|NEMA|Z5KyJe9nEg1QNbWlX0wWRB0oDjBLdqzR83VGv624|1||1|1|1760573920256|............. ++|4023|26|NEMA|eod9aRWLVl34Gx1Dn7VoaMA2rz6qjgmpEXwQJN5Z|1||1|1|1760573940898|............. ++|4148|6|NEMA|dz4ojlpP85JMgDLZWkQOoGAaKYqQexEr62GXRV1y|1||1|1|1760573920768|............. ++|3721|30|NEMA|Nzp2OoJlqn6r1ZgvdA3GWKAabBwP5G4eE3RQmyxD|1||1|1|1760573928899|............. ++|3633|24|NEMA|nJL5lPMwBx23YpqRe0rlKV7damXvWVbOrD4gNzy8|1||1|1|1760573802976|............. ++|4762|4|NEMA|1JMYvnx2RzKEo4aWQ7DmN5AL8yZV3m9NBePXbrdj|1||1|1|1760573935082|............. ++|4763|15|NEMA|3a5oqJN1bgnx4Ol9dk86NBAByE6jQ8mKDWMpGrLV|1||1|1|1760573935482|............. diff --git a/RVO39/databases/nodes_original/nodes_original.table b/RVO39/databases/nodes_original/nodes_original.table new file mode 100755 index 0000000..46d802e --- /dev/null +++ b/RVO39/databases/nodes_original/nodes_original.table @@ -0,0 +1 @@ +[{"4153": "d5xjWYMwEJon6rLlK7yBYmAqgV4DaOeNB9ZX3Gzb"}, {"3734": "EjgWGnXaLy9opPOz20n69V086BlYM3w1deVQvbKr"}, {"4155": "eod9aRWLVl34Gx1Dn7VoaaA2rz6qjgmpEXwQJN5Z"}, {"3522": "RO8rjaBDy21qPQJzW7oD96ApK3xmNleVZg9Ed4Gw"}, {"3741": "wvKJdZML6mXP4DzWBAXWN17jxNloa5g23Ve9Y1ry"}, {"3744": "ZmRwd93QL4gaezxEbAxW5O71prn2XjlPvGyqJ6BO"}, {"3757": "roKgWqY95V3mXMRzyAjm8D7bLjexpJPvaGDBw826"}, {"3802": "K94XLav1glVRnyQ6r01BNzkme3YJwBxM5oOzdP2j"}, {"3636": "wvKJdZML6mXP4DzWBAXWNW7jxNloa5g23Ve9Y1ry"}, {"3642": "EjgWGnXaLy9opPOz20n694086BlYM3w1deVQvbKr"}, {"4761": "3a5oqJN1bgnx4Ol9dk86NZAByE6jQ8mKDWMpGrLV"}, {"3837": "wvKJdZML6mXP4DzWBAXWq87jxNloa5g23Ve9Y1ry"}, {"3839": "Nzp2OoJlqn6r1ZgvdA3GxEAabBwP5G4eE3RQmyxD"}, {"3840": "EjgWGnXaLy9opPOz20n6wQ086BlYM3w1deVQvbKr"}, {"3845": "3a5oqJN1bgnx4Ol9dk863qAByE6jQ8mKDWMpGrLV"}, {"3907": "PjLblDgRBO6WQqnxmkJ59r0Jv3ewZN4p5a89yKdY"}, {"3929": "B5EoxeMVp4zwr8nqW0GjDpARjvD1PNamOGbLg63Z"}, {"3938": "gRoJEyXVx4qD9er287LP1v7wBzGldaPjLWQKm3Mv"}, {"3946": "aw4eELG2DlPMdn1JW0B1DnAqQXOZRN3xB5yp8VKr"}, {"3967": "rDbQ84xzwgdqEoPm3kbJw3k9anOZY1RXyBv2LVM6"}, {"3977": "E6Kg9oDnLWyzPRMva7vrwa7Jxp4VG58qO2w1lZYe"}, {"3990": "52dD6ZlV1QaOpRBmbAqKZgkKnGzWMLj4eJq38Pgo"}, {"3991": "Nzp2OoJlqn6r1ZgvdA3GWdAabBwP5G4eE3RQmyxD"}, {"3994": "PLBJzmK1r3Gynd6OW0gGdM0e5wV4vx9bDEqNgYR8"}, {"2870": "ZmRwd93QL4gaezxEbAxW5971prn2XjlPvGyqJ6BO"}, {"4015": "d9x2V5LGYBzXp4mMRAOBDj7PloaqJwnQj6DgrNe3"}, {"3718": "3JjOWdylwgNLzxVab7NEznkZ2vG64rq8PEB5QmDo"}, {"4019": "Z5KyJe9nEg1QNbWlX0wWRB0oDjBLdqzR83VGv624"}, {"4023": "eod9aRWLVl34Gx1Dn7VoaMA2rz6qjgmpEXwQJN5Z"}, {"4148": "dz4ojlpP85JMgDLZWkQOoGAaKYqQexEr62GXRV1y"}, {"3721": "Nzp2OoJlqn6r1ZgvdA3GWKAabBwP5G4eE3RQmyxD"}, {"3633": "nJL5lPMwBx23YpqRe0rlKV7damXvWVbOrD4gNzy8"}, {"4762": "1JMYvnx2RzKEo4aWQ7DmN5AL8yZV3m9NBePXbrdj"}, {"4763": "3a5oqJN1bgnx4Ol9dk86NBAByE6jQ8mKDWMpGrLV"}] \ No newline at end of file diff --git a/RVO39/databases/notifications.table b/RVO39/databases/notifications.table new file mode 100755 index 0000000..f7c96cb --- /dev/null +++ b/RVO39/databases/notifications.table @@ -0,0 +1,41 @@ +key:string|weight:string|sk:string|en:string ++|switching_profile_point_applied_to_line|INFORMATIONAL|Aplikovaný bod spínacieho profilu na línií č. ${line} : ${value}|Switching profile point applied to line no. ${line} : ${value}|............... ++|dusk_has_occured|INFORMATIONAL|Nastal súmrak: ${value}|Dusk has occured: ${value}|............... ++|dawn_has_occured|INFORMATIONAL|Nastal úsvit: ${value}|Dawn has occured: ${value}|............... ++|dimming_profile_was_successfully_received_by_node|NOTICE|Stmievací profil bol úspešne prijatý nodom č. ${node}|Dimming profile was successfully received by node no. ${node}|............... ++|master_node_is_responding_again|NOTICE|Master node začal znovu odpovedať|Master node is responding again|............... ++|command_was_sent_from_terminal_interface|DEBUG|Z terminálu bol odoslaný príkaz|A command was sent from terminal interface|............... ++|master_node_is_not_responding|ALERT|Master node neodpovedá|Master node is not responding|............... ++|configuration_of_dimming_profile_to_node_failed|ALERT|Konfigurácia stmievacieho profilu pre node č. ${node} zlyhala|Configuration of dimming profile to node no. ${node} has failed|............... ++|circuit_breaker_was_turned_on_line|NOTICE|Zapnutie ističa na línii č. ${line}|Circuit breaker was turned on - line no. ${line}|............... ++|circuit_breaker_was_turned_off_line|ERROR|Vypnutie ističa na línií č. ${line}|Circuit breaker was turned off - line no. ${line}|............... ++|dimming_profile_was_processed_for_node|INFORMATIONAL|Stmievací profil bol spracovaný pre node č. ${node}|Dimming profile was processed for node no. ${node}|............... ++|switching_profile_was_processed_for_line|INFORMATIONAL|Spínací profil bol spracovaný pre líniu č. ${line}|Switching profile was processed for line no. ${line}|............... ++|thermometer_is_not_responding|WARNING|Teplomer neodpovedá|Thermometer is not responding|............... ++|thermometer_is_responding_again|NOTICE|Teplomer znovu odpovedá|Thermometer is responding again|............... ++|thermometer_sends_invalid_data|WARNING|Teplomer posiela neplatné hodnoty|Thermometer sends invalid data|............... ++|main_switch_has_been_turned_off|CRITICAL|Hlavný vypínač bol vypnutý|Main switch has been turned off|............... ++|main_switch_has_been_turned_on|NOTICE|Hlavný vypínač bol zapnutý|Main switch has been turned on|............... ++|power_supply_has_disconnected_input|ALERT|Napájací zdroj nemá napätie na vstupe|Power supply has disconnected input|............... ++|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_main_open|NOTICE|Hlavné dvere boli otvorené|Main door has been opened|............... ++|door_em_open|NOTICE|Dvere silovej časti boli otvorené|Power door has been opened|............... ++|door_main_open_without_permission|WARNING|Hlavné dvere boli otvorené bez povolenia - zapnutá siréna|Main door has been opened without permission - alarm is on|............... ++|door_em_open_without_permission|WARNING|Dvere silovej časti boli otvorené bez povolenia|Power door has been opened without permission|............... ++|door_main_close|NOTICE|Hlavné dvere boli zatvorené|Main door has been closed|............... ++|door_em_close|NOTICE|Dvere silovej časti boli zatvorené|Power door has been closed|............... ++|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|............... ++|electrometer_ok|NOTICE|Elektromer znovu odpovedá|Electrometer is responding again|............... ++|no_voltage_on_phase|CRITICAL|Na fáze č. ${phase} nie je napätie|No voltage detected on phase no. ${phase}|............... ++|voltage_on_phase_restored|NOTICE|Napätie na fáze č. ${phase} bolo obnovené|Voltage on phase no. ${phase} has been restored|............... ++|flow_start|NOTICE|FLOW bol spustený|FLOW has been started |............... ++|twilight_sensor_nok|ERROR|Sensor súmraku neodpovedá|Twilight sensor is not responding|............... ++|twilight_sensor_ok|NOTICE|Sensor súmraku znovu odpovedá|Twilight sensor is responding again|............... ++|lamps_have_turned_on|NOTICE|Lampy sa zapli|Lamps have turned on|............... ++|lamps_have_turned_off|NOTICE|Lampy sa vypli|Lamps have turned off|............... ++|flow_restart|NOTICE|FLOW bol reštartovaný|FLOW has been restarted|............... ++|nodes_db_changed|NOTICE|Zmena v node databáze|Node db has changed|............... diff --git a/RVO39/databases/pins.table b/RVO39/databases/pins.table new file mode 100755 index 0000000..0eb3d05 --- /dev/null +++ b/RVO39/databases/pins.table @@ -0,0 +1,14 @@ +pin:string|type:string|line:number +*|input1_01|door_condition|0|........... +*|input1_02|rotary_switch_state|0|........... +*|input1_03|rotary_switch_state|0|........... +*|input1_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/RVO39/databases/relays.table b/RVO39/databases/relays.table new file mode 100755 index 0000000..40843b1 --- /dev/null +++ b/RVO39/databases/relays.table @@ -0,0 +1,5 @@ +line:number|tbname:string|contactor:number|profile:string ++|0|6lQGaY9RDywdVzObj0PadOkPg4NBn3exEK51LWZq|1||........... ++|1|JzwxZXOvDj1bVrN4nkWw9Qk8qdyBl3MRKLpGPgaQ|9|{"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|9|{"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|9|{"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/RVO39/databases/settings.table b/RVO39/databases/settings.table new file mode 100755 index 0000000..18c69eb --- /dev/null +++ b/RVO39/databases/settings.table @@ -0,0 +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|project_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|cloud_topic:string|has_main_switch:boolean|daily_report:boolean|send_changed_node_numbers:boolean ++|rvo_senica_39_10.0.0.132|en|28.25119C0E0000|48.70826502|17.28455203|192.168.252.1|rvo_senica_39_10.0.0.132|qzSNuCNrLP4OL1v47YEe|1883|0|68|unipi|ttyUSB0|1|20|5|6|3|u132|0|1|1|................................................... diff --git a/RVO39/databases/tbdata.nosql b/RVO39/databases/tbdata.nosql new file mode 100755 index 0000000..1e9f642 --- /dev/null +++ b/RVO39/databases/tbdata.nosql @@ -0,0 +1,4 @@ +-"6lQGaY9RDywdVzObj0PadOkPg4NBn3exEK51LWZq":[{"ts":1760530798461,"values":{"_event":{"type":"notice","status":"new","source":{"func":"modbus_reader","component":"1699965957410","component_name":"Modbus reader","edge":"6lQGaY9RDywdVzObj0PadOkPg4NBn3exEK51LWZq"},"message":{"sk":"rvo_senica_39_10.0.0.132: FLOW bol reštartovaný","en":"rvo_senica_39_10.0.0.132: FLOW has been restarted"},"message_data":""}}}],"id":"3000320001ji71b"} +-"6lQGaY9RDywdVzObj0PadOkPg4NBn3exEK51LWZq":[{"ts":1760530798537,"values":{"edge_fw_version":"2025-10-08","maintenance_mode":false}}],"id":"3000320002ji70b"} +-"6lQGaY9RDywdVzObj0PadOkPg4NBn3exEK51LWZq":[{"ts":1760530798550,"values":{"statecode":2,"power_mode":"Automatic"}}],"id":"3000320004ji70b"} +-"6lQGaY9RDywdVzObj0PadOkPg4NBn3exEK51LWZq":[{"ts":1760530798581,"values":{"_event":{"type":"notice","status":"new","source":{"func":"rsPort.open()","component":"1699963668903","component_name":"DIDO_Controller","edge":"6lQGaY9RDywdVzObj0PadOkPg4NBn3exEK51LWZq"},"message":{"sk":"rvo_senica_39_10.0.0.132: FLOW bol spustený","en":"rvo_senica_39_10.0.0.132: FLOW has been started "},"message_data":""}}}],"id":"3000320006ji70b"} diff --git a/RVO39/databases/tbdatacloud.nosql b/RVO39/databases/tbdatacloud.nosql new file mode 100755 index 0000000..5b1a172 --- /dev/null +++ b/RVO39/databases/tbdatacloud.nosql @@ -0,0 +1,3 @@ +-"6lQGaY9RDywdVzObj0PadOkPg4NBn3exEK51LWZq":[{"ts":1760530798537,"values":{"edge_fw_version":"2025-10-08","maintenance_mode":false}}],"id":"3000320003ji71b"} +-"6lQGaY9RDywdVzObj0PadOkPg4NBn3exEK51LWZq":[{"ts":1760530798550,"values":{"statecode":2,"power_mode":"Automatic"}}],"id":"3000320005ji71b"} +-"6lQGaY9RDywdVzObj0PadOkPg4NBn3exEK51LWZq":[{"ts":1760530798581,"values":{"_event":{"type":"notice","status":"new","source":{"func":"rsPort.open()","component":"1699963668903","component_name":"DIDO_Controller","edge":"6lQGaY9RDywdVzObj0PadOkPg4NBn3exEK51LWZq"},"message":{"sk":"rvo_senica_39_10.0.0.132: FLOW bol spustený","en":"rvo_senica_39_10.0.0.132: FLOW has been started "},"message_data":""}}}],"id":"3000320007ji71b"} diff --git a/RVO39/databases/total_energy.js b/RVO39/databases/total_energy.js new file mode 100755 index 0000000..dde340e --- /dev/null +++ b/RVO39/databases/total_energy.js @@ -0,0 +1,38 @@ +//key is rvo_number, value is max energy when lamps are on +const total_energy = { + 1: 580, + 2: 1100, + 3: 3700, + 4: 4100, + 7: 360, + 12: 1700, + 13: 5400, + 14: 440, + 15: 6100, + 16: 4800, + 20: 1600, + 21: 1000, + 22: 2600, + 23: 1000, + 25: 2600, + 33: 240, + 34: 4000, + 35: 2700, + 36: 820, + 37: 1400, + 35: 3500, + 39: 1170, + 41: 740, + 42: 660, + 43: 4900, + 45: 930, + 46: 700, + 47: 1100, + 48: 1500, + 50: 3200, + 53: 1250, + 55: 1000, + 56: 5500 +} + +module.exports = total_energy; diff --git a/RVO39/debug.js b/RVO39/debug.js new file mode 100755 index 0000000..9818194 --- /dev/null +++ b/RVO39/debug.js @@ -0,0 +1,16 @@ +// =================================================== +// FOR DEVELOPMENT +// Total.js - framework for Node.js platform +// https://www.totaljs.com +// =================================================== + +const options = {}; + +// options.ip = '127.0.0.1'; +// options.port = parseInt(process.argv[2]); +// options.config = { name: 'Total.js' }; +// options.sleep = 3000; +// options.inspector = 9229; +// options.watch = ['private']; + +require('total.js/debug')(options); \ No newline at end of file diff --git a/RVO39/err.txt b/RVO39/err.txt new file mode 100755 index 0000000..927821e --- /dev/null +++ b/RVO39/err.txt @@ -0,0 +1,61 @@ +[2024-10-25T18:24:57.061] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-25T19:27:05.099] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-25T20:29:20.854] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-25T21:31:23.018] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-25T22:33:44.578] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-25T23:33:48.782] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T00:36:06.434] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T01:36:10.606] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T02:36:28.308] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T03:36:28.645] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T04:36:40.541] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T05:39:05.934] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T06:39:17.811] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T07:39:31.665] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T08:39:33.839] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T09:39:39.856] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T10:39:53.670] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T11:39:55.825] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T12:42:01.733] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T13:44:09.622] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T14:44:29.260] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T15:46:37.173] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T16:48:35.405] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T17:50:53.036] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T18:51:16.613] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T19:51:32.393] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T20:51:34.952] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T21:54:00.031] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2025-09-23T14:09:27.406] [ERROR] errLogs - uncaughtException: Cannot read property 'getHours' of undefined +[2025-09-23T14:09:27.407] [ERROR] errLogs - TypeError: Cannot read property 'getHours' of undefined + at Timeout.emptyReportToSend [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:09:27.408] [ERROR] errLogs - uncaughtException: Cannot read property 'getHours' of undefined +[2025-09-23T14:09:27.409] [ERROR] errLogs - TypeError: Cannot read property 'getHours' of undefined + at Timeout.emptyReportToSend [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:09:27.422] [ERROR] errLogs - uncaughtException: Cannot read property 'getHours' of undefined +[2025-09-23T14:09:27.423] [ERROR] errLogs - TypeError: Cannot read property 'getHours' of undefined + at Timeout.emptyReportToSend [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:09:33.140] [ERROR] errLogs - uncaughtException: date.getHours is not a function +[2025-09-23T14:09:33.140] [ERROR] errLogs - TypeError: date.getHours is not a function + at emptyReportToSend (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at Timeout.dailyReportCheck [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1351:5) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:09:33.141] [ERROR] errLogs - uncaughtException: date.getHours is not a function +[2025-09-23T14:09:33.142] [ERROR] errLogs - TypeError: date.getHours is not a function + at emptyReportToSend (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at Timeout.dailyReportCheck [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1351:5) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:09:33.146] [ERROR] errLogs - uncaughtException: date.getHours is not a function +[2025-09-23T14:09:33.146] [ERROR] errLogs - TypeError: date.getHours is not a function + at emptyReportToSend (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at Timeout.dailyReportCheck [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1351:5) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) diff --git a/RVO39/flow/cloudmqttconnect.js b/RVO39/flow/cloudmqttconnect.js new file mode 100755 index 0000000..b03491f --- /dev/null +++ b/RVO39/flow/cloudmqttconnect.js @@ -0,0 +1,357 @@ +exports.id = 'cloudmqttconnect'; +exports.title = 'Cloud connect mqtt'; +exports.group = 'MQTT'; +exports.color = '#888600'; +exports.version = '1.0.2'; +exports.icon = 'sign-out'; +exports.input = 2; +exports.output = 2; +exports.options = { host: 'tb-stage.worksys.io', port: 1883, clientid: "", username: "" }; + +exports.html = `
+
+
+
Hostname or IP address (if not empty - setting will override db setting)
+
+
+
Port
+
+
+
+
+
@(Client id)
+
+
+
topic
+
+
+
`; + + + +const { promisifyBuilder } = require('./helper/db_helper'); +const fs = require('fs'); +const mqtt = require('mqtt'); +const nosql = NOSQL('tbdatacloud'); + +const SEND_TO = { + debug: 0, + rpcCall: 1, +} + +//CONFIG +let saveTelemetryOnError = true;//backup_on_failure overrides this value +//------------------------ + +const noSqlFileSizeLimit = 4194304;//use 5MB - 4194304 +let insertNoSqlCounter = 0; +let insertBackupNoSqlCounter = 0; +let processingData = false; + +let backup_on_failure = true;//== saveTelemetryOnError - create backup client send failure +let restore_from_backup = 50; //how many rows process at once? +let restore_backup_wait = 3;//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; + + +exports.install = function(instance) { + + var client; + var opts; + var clientReady = false; + + let o = {}; //options + + function main() { + loadSettings(); + } + + //set opts according to db settings + function loadSettings() { + + o = instance.options; + if (!o.topic) o.topic = FLOW.GLOBALS.settings.cloud_topic; + + opts = { + host: o.host, + port: o.port, + clientId: o.clientid, + username: o.username, + rejectUnauthorized: false, + resubscribe: false + }; + + console.log("wsmqttpublich -> loadSettings from instance.options", o); + + if (!o.topic) { + instance.status("Not configured", "white"); + console.log("Cloud mqtt connect: no topic selected"); + return; + } + + connectToTbServer(); + } + + function connectToTbServer() { + var url = "mqtt://" + opts.host + ":" + opts.port; + console.log("MQTT URL: ", url); + + client = mqtt.connect(url, opts); + + client.on('connect', function() { + client.subscribe(`${o.topic}_backward`, (err) => { + if (!err) { + console.log("MQTT subscribed"); + } + }); + instance.status("Connected", "green"); + clientReady = true; + sendClientError = true; + }); + + client.on('reconnect', function() { + instance.status("Reconnecting", "yellow"); + clientReady = false; + }); + + client.on('message', function(topic, message) { + // message is type of buffer + message = message.toString(); + if (message[0] === '{') { + TRY(function() { + + message = JSON.parse(message); + if (message.hasOwnProperty("device") && message.hasOwnProperty("data") && message.data.hasOwnProperty("id")) { + client.publish(`${o.topic}_forward`, `{"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 } }); + } + + }, () => instance.debug('MQTT: Error parsing data', message)); + } + + instance.send(SEND_TO.rpcCall, { "topic": o.topic, "content": message }); + }); + + client.on('close', function() { + clientReady = false; + + instance.status("Disconnected", "red"); + instance.send(SEND_TO.debug, { "message": "Client CLOSE signal received !" }); + }); + + client.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) { + console.log('MQTT client error', err); + sendClientError = false; + } + clientReady = false; + }); + + } + + + instance.on('0', function(data) { + + if (clientReady) { + //do we have some data in backup file? if any, process data from database + if (saveTelemetryOnError) { + //read telemetry data and send back to server + if (!processingData) processDataFromDatabase(); + } + + let stringifiedJson = JSON.stringify(data.data) + client.publish(`${o.topic}_forward`, stringifiedJson, { qos: 1 }); + } + 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 (saveTelemetryOnError && o.topic) { + //create new file from tbdata.nosql, if file size exceeds given limit, and clear tbdata.nosql + makeBackupFromDbFile(); + + //write to tb + data.data.id = UID(); + nosql.insert(data.data); + } + } + }); + + instance.on("1", _ => { + main(); + }) + + instance.close = function(done) { + if (clientReady) { + client.end(); + } + }; + + + function getDbBackupFileCounter(type) { + var files = fs.readdirSync(__dirname + "/../databases"); + + let counter = 0; + for (var i = 0; i < files.length; i++) { + + if (files[i] == "tbdatacloud.nosql") continue; + + if (files[i].endsWith(".nosql")) { + + let pos = files[i].indexOf("."); + if (pos > -1) { + + let fileCounter = counter; + let firstDigit = files[i].slice(0, pos); + + fileCounter = parseInt(firstDigit); + if (isNaN(fileCounter)) fileCounter = 0; + //console.log("getDbBackupFileCounter digit:", files[i], firstDigit, fileCounter, isNaN(fileCounter), type); + + if (type == "max") { + if (fileCounter > counter) { + counter = fileCounter; + } + } + else if (type == "min") { + if (counter == 0) counter = fileCounter; + + if (fileCounter < counter) { + counter = fileCounter; + } + } + } + } + + } + + if (type == "max") counter++; + + return counter; + } + + const makeBackupFromDbFile = async () => { + + if (!saveTelemetryOnError) return; + + //to avoid large file: tbdata.nosql + + //init value is 0! + if (insertNoSqlCounter > 0) { + --insertNoSqlCounter; + return; + } + + insertNoSqlCounter = 100; + + let source = __dirname + "/../databases/tbdatacloud.nosql"; + + var stats = fs.statSync(source); + var fileSizeInBytes = stats.size; + + if (fileSizeInBytes > noSqlFileSizeLimit) { + + let counter = 1; + counter = getDbBackupFileCounter("max"); + + let destination = __dirname + "/../databases/" + counter + "." + "tbdatacloud.nosql"; + + //make backup file + fs.copyFileSync(source, destination); + //fs.renameSync(p, p + "." + counter); + + //clear tbdata.nosql + fs.writeFileSync(source, ""); + fs.truncateSync(source, 0); + + } + } + + const processDataFromDatabase = async () => { + + if (restore_from_backup <= 0) return; + + //calculate diff + const now = new Date(); + let currentTime = now.getTime(); + let diff = currentTime - lastRestoreTime; + + if ((diff / 1000) < restore_backup_wait) { + //console.log("*********restore_backup_wait", diff, restore_backup_wait); + return; + } + + processingData = true; + + //get filename to process + let counter = getDbBackupFileCounter("min"); + + //we have some backup files + let dataBase = 'tbdata'; + + var nosql; + if (counter == 0) dataBase = 'tbdatacloud'; + else dataBase = counter + "." + 'tbdatacloud'; + + nosql = NOSQL(dataBase); + + //select all data - use limit restore_from_backup + let records = await promisifyBuilder(nosql.find().take(restore_from_backup)); + + for (let i = 0; i < records.length; i++) { + if (clientReady) { + + let item = records[i]; + let id = item.id; + + if (id !== undefined) { + //console.log("------------processDataFromDatabase - remove", id, dataBase, i); + + try { + + let message = JSON.parse(JSON.stringify(item)); + delete message.id; + client.publish(`${o.topic}_forward`, JSON.stringify(message), { qos: 1 }); + + //remove from database + await promisifyBuilder(nosql.remove().where("id", id)); + + } catch (error) { + //process error + console.log("processDataFromDatabase", error); + } + + } + + } + else { + processingData = false; + return; + } + } + + if (records.length > 0) { + //clean backup file + if (counter > 0) nosql.clean(); + } + + //no data in db, remove + if (records.length == 0) { + if (counter > 0) nosql.drop(); + } + + const d = new Date(); + lastRestoreTime = d.getTime(); + + processingData = false; + + } + + instance.on('options', main); + +}; diff --git a/RVO39/flow/cmd_manager.js b/RVO39/flow/cmd_manager.js new file mode 100755 index 0000000..25912df --- /dev/null +++ b/RVO39/flow/cmd_manager.js @@ -0,0 +1,3071 @@ +exports.id = 'cmd_manager'; +exports.title = 'CMD Manager'; +exports.group = 'Worksys'; +exports.color = '#5D9CEC'; +exports.version = '0.0.3'; +exports.output = ['red', 'blue', 'yellow', 'blue', 'white', 'green']; +exports.input = 3; +exports.icon = 'cloud-upload'; + +exports.html = ` +
+
+
+
RPC - run RPC calls

+
+
+
@(User)
+
+
+
@(Password)
+
+
+
@(My edge)
+
+
+
+`; +exports.readme = `Manager for CMD calls`; + + +exports.install = function(instance) { + + 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, isEmptyObject, emptyJsObject, writeToFile, addToArrayIfUnique } = require('./helper/utils'); + const bitwise = require('bitwise'); + + var SunCalc = require('./helper/suncalc'); + const DataToTbHandler = require('./helper/DataToTbHandler'); + const errorHandler = require('./helper/ErrorToServiceHandler'); + const { sendNotification } = require('./helper/notification_reporter'); + const process = require('process'); + const { errLogger, logger, monitor } = require('./helper/logger'); + + //for accelerometer purposes + const { naklony } = require("../databases/accelerometer_db"); + + const dbNodes = TABLE("nodes"); + const dbRelays = TABLE("relays"); + + let GLOBALS; + let SETTINGS; + let rsPort; + let tbHandler; + + // runTasks intervals + const SHORT_INTERVAL = 30; + const LONG_INTERVAL = 300; + + //send data to following instances: + const SEND_TO = { + debug: 0, + tb: 1, + http_response: 2, + dido_controller: 3, + infoSender: 4, + dailyReport: 5 + } + + 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 + } + + 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 sendNodeReadout = null; // interval for sending agregate data from node + + 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["1"] = minutes; // dimming + priorities["76"] = minutes; // power + + minutes = 5; + priorities["75"] = minutes; // current + priorities["79"] = minutes; // energy + priorities["87"] = minutes; // aktualny cas + //priorities["84"] = minutes; //accelerometer + + minutes = 10; + priorities["74"] = minutes; // voltage + priorities["77"] = minutes; // power factor + priorities["78"] = minutes; // frequency + + minutes = 60; + priorities["0"] = minutes; // statecode + priorities["6"] = minutes; // dusk + priorities["7"] = minutes; // dawn + priorities["8"] = minutes; // profile + + minutes = 60 * 24; + priorities["89"] = minutes; // verzia fw + priorities["80"] = minutes; // lifetime + + //prikazy kt sa budu spustat na dany node - see config.js in terminal-oms.app. (1 - dimming) + let listOfCommands = [0, 1, 6, 7, 8, 74, 75, 76, 77, 78, 79, 80, 87, 89]; + + 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; + + // holds dusk, dawn (and more) values + let sunCalcResult; + + //helper container for counting resolved group of commands (commands related to set profile) + let cmdCounter = {};//key is node, value is counter + + //TODO: is this set working?? According to previous checks, sets do not work + //if sending of profile to node fails, we send notification and push node into set, so we do not send notification twice + const nodeProfileSendFail = new Set(); + + //we expect to get current temperature in Senica from senica-prod01 + let temperatureInSenica = null; + let accelerometerInterval = null; + + //NOTE: daily reports senica: + //rvo_is_on status, we monitor all nodes - if true, power and dimming should be not 0, if false, 24/7 nodes should be 0, other rvo should not respond + let rvo_is_on; + let previous_rvo_is_on_value; + let handleDailyReport; //setInterval for dailyReportHandler function + let dailyReport = {}; //data needed for daily report + let reportToSend = {}; //final report which we send to cloud + let breakerCounter = null; // status of breakers after flow starts is not in report + let rvoPeriod; // interval of checking dusk dawn and if rvo_is_on + let initialReportStatus = false; + + const DAILY_REPORT_HANDLER_TIME = 3_600_000; + const SET_SUNCALC_RESULT_TIME = 3_600_000; + const SET_RVO_PERIOD_TIME = 300_000; + const ADD_NODE_TO_REPORT_TIME = 3_600_000; + + //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); + + let now = new Date(); + console.log("Cmd-mngr installed", now.toLocaleString("sk-SK")); + + sunCalcResult = calculateDuskDawn(); + + handleRsPort(); + + customTasksInterval = setInterval(reportEdgeDateTimeAndNumberOfLuminaires, 120_000); + setTimeout(reportEdgeDateTimeAndNumberOfLuminaires, 4000); + + //dailyReport related + emptyReportToSend(); + breakerCounter = Object.keys(relaysData).length - 1; // we get number of lines (breakers) except of line 0 + rvoPeriod = setInterval(setRvoPeriod, SET_RVO_PERIOD_TIME); + setTimeout(setRvoPeriod, 3000); + setInterval(setSunCalcResult, SET_SUNCALC_RESULT_TIME); + handleDailyReport = setInterval(dailyReportHandler, DAILY_REPORT_HANDLER_TIME); + + + setCorrectTime = setInterval(setCorrectPlcTimeOnceADay, 60000 * 60); // 1 hour + setCorrectPlcTimeOnceADay(); + + sendNodeReadout = setInterval(sendNodesData, 150_000); + accelerometerInterval = setInterval(accelerometerData, 60000 * 30); //30 min + } + + + 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" + //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 + // if node regular readout does not respond, we repeat request + params.repeatCounter = 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-mngr: 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.byte4 = 96; + params.recipient = 1; + params.register = 8; + params.rw = 1;//write + params.timestamp = timestamp; + 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.byte4 = 96; + params.recipient = 1; + params.register = 8; + params.rw = 1;//write + params.timestamp = timestamp; + 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). + */ + + 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.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.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 + { + + logger.debug("processNodeProfile: Threshold lux level for DUSK/DAWN", node); + + let params = getParams(); + params.type = "set_node_profile"; + params.address = node; + params.register = 96; + params.recipient = 1; + params.rw = 1;//write + params.timestamp = timestamp; + 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(); + params.type = "set_node_profile"; + params.address = node; + params.register = 97; + params.recipient = 1; + params.rw = 1;//write + params.timestamp = timestamp; + 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.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); + + 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); + + console.log("proces profile finished *********************") + } + + + 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; + }); + } + + + 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) { + for (let k in nodesData) { + 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`); + } + } + } + + + function loadRelaysData(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 (value.contactor == 1) processAllNodeProfilesOnLine(value.line); + } + } + + + function reportOnlineNodeStatus(line) { + //Po zapnutí línie broadcastovo aktualizovať predtým čas a o 3 sek neskor - status, brightness + + logger.debug("Cmd-mngr: ----->reportOnlineNodeStatus for line", line); + + const d = new Date(); + + // broadcast actual time + let params = getParams(); + params.address = 0xffffffff;//Broadcast + params.byte1 = d.getHours(); + params.byte2 = d.getMinutes(); + params.recipient = 2;//2 broadcast, address = 0 + params.register = 87;//Actual time + params.rw = 1;//write + params.type = "node-onetime-write"; + params.timestamp = d.getTime() + 30000; + params.info = "run broadcast: Actual time"; + //params.debug = true; + + tasks.push(params); + + let sec = 3; + setTimeout(function() { + //Po zapnutí línie - spraviť hromadný refresh stavu práve zapnutých svietidiel + + let time = Date.now(); + + for (let k in nodesData) { + + //potrebujem nody k danej linii + 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].node_status_before_offline === true || nodesData[k].status === true) { + status = "OK"; + nodesData[k].time_of_last_communication = time; + } + + nodesData[k].readout.status = status; + + updateNodeStatus(k, status === "OK" ? true : false); + if (nodesData[k].hasOwnProperty("node_status_before_offline")) delete nodesData[k].node_status_before_offline; + sendTelemetry({ status: status }, tbname, time); + + //vyreportovanie dimming, current, input power pre liniu pre vsetky nody + //Prud + { + let params = getParams(); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 75;//prud + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = time + 4000; + params.info = 'read current'; + //params.debug = true; + tasks.push(params); + } + + //vykon + { + let params = getParams(); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 76;//výkon + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = time + 4100; + params.info = 'read power'; + //params.debug = true; + + tasks.push(params); + } + //dimming + { + let params = getParams(); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 1;//dimming + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = time + 4200; + params.info = 'read dimming'; + //params.debug = true; + + tasks.push(params); + } + + } + } + + }, sec * 1000); + } + + + function reportOfflineNodeStatus(line) { + + logger.info("Cmd-mngr: ------>reportOffLineNodeStatus for line ", line); + + values = {}; + values["dimming"] = 0;//brightness + values["power"] = 0;//výkon + values["current"] = 0;//prúd + values["status"] = "OFFLINE"; + + const date = Date.now(); + + Object.keys(nodesData).forEach(node => { + + //potrebujem nody k danej linii + if (line == nodesData[node].line || line == undefined) { + + let tbname = nodesData[node].tbname; + let nodeStatus = nodesData[node].status; + + //in case we have reported offline node status, we return (continue with next node) + if (nodeStatus === "OFFLINE") return; + + nodesData[node].node_status_before_offline = nodeStatus; + nodesData[node].status = "OFFLINE"; + nodesData[node].readout = {}; + + sendTelemetry({ ...values }, tbname, date); + } + }); + + } + + + function turnLine(onOrOff, line, info) { + let obj = { + line: line, + command: onOrOff, + info: info + }; + + //to assure, handleDailyReportFunction do not run before rvo_is_on variable changes. So after every line switch we reset the timer + clearInterval(handleDailyReport); + handleDailyReport = setInterval(dailyReportHandler, DAILY_REPORT_HANDLER_TIME); + + //logger.debug("linia", line, obj); + instance.send(SEND_TO.dido_controller, obj); + } + + + 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"; + 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]) { + //CRC_ERROR + message = "NOK"; + error = "CRC_ERROR c1"; + instance.send(SEND_TO.debug, "CRC_ERROR c1"); + } + + 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") { + instance.send(SEND_TO.debug, bytes); + instance.send(SEND_TO.debug, "RESPONSE " + type + " - " + bytes[4]); + + //logger.debug(SEND_TO.debug, "RESPONSE " + type + " - " + bytes[4], bytes); + + error = "type is: " + type; + + message = "NOK"; + } + + return { message, type, error }; + } + + + //BUILD TASKS// + function buildTasks(params) { + + //return; + console.log("buidTAaasks start ****************", params); + monitor.info("buildTasks - params", params); + + let processLine; //defined line + let init = false; + let processLineProfiles = true; + let processBroadcast = true; + let processNodes = true; + + if (params == undefined) { + init = true; + tasks = []; + logger.debug("-->buildTasks clear tasks"); + } + else { + processLineProfiles = params.processLineProfiles; + processBroadcast = false; + processNodes = false; + + processLine = params.line; + } + + let now = new Date(); + + //process line profiles + if (processLineProfiles) { + + let keys = Object.keys(relaysData); + + for (let i = 0; i < keys.length; i++) { + + let line = parseInt(keys[i]); + let profilestr = relaysData[line].profile; + + if (processLine != undefined) { + if (processLine != line) continue; + } + + try { + + /** + * we process line profiles: timepoints, astro clock, lux_sensor, offsets ... + */ + if (profilestr === "") throw ("Profile is not defined"); + let profile = JSON.parse(profilestr); + 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; + + // add name to regular profile timepoint and delete unused end_time key: + time_points.forEach(point => { + point.name = "profileTimepoint" + delete point.end_time; + }); + + //monitor.info("buildTasks: time_points", time_points); + + + /** + * 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 astro clock true, we remove all regular profile points + time_points = []; + + //TODO: when astro clock == true, is offset calculated ??? + //let duskAstroClockOffset = profile.dusk_astro_clock_offset; + //let dawnAstroClockOffset = profile.dawn_astro_clock_offset; + //console.log("line astro clock offsets dusk a dawn: ", duskAstroClockOffset, dawnAstroClockOffset); + // maybe add dusk dawn offset to calculateDuskDawn ?? what dusk dawn will be if dawn_lux_sensor == true?? + //let sunCalcResult = calculateDuskDawn(new Date(), line, duskAstroClockOffset, dawnAstroClockOffset); + + 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 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); + + 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); + + 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(':'); + + let ad = new Date(); + ad.setHours(parseInt(ahours), parseInt(aminutes), 0); + + let bd = new Date(); + bd.setHours(parseInt(bhours), parseInt(bminutes), 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++) { + + let start_time = new Date(); + let [hours, minutes] = time_points[t].start_time.split(':'); + start_time.setHours(parseInt(hours), parseInt(minutes), 0); + + //task is in 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(); + params.type = "relay"; + params.line = parseInt(line); + params.value = time_points[t].value; + params.tbname = relaysData[line].tbname; + params.timestamp = start_time.getTime(); + + // 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; + + //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)) { + 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; + + params.debug = true; + + //turn on/off line + tasks.push(params); + monitor.info("TimePoint params: ", params.info, start_time); + } + + monitor.info("-->time_points final", line, time_points); + + //ensure to turn on/off according to calculated currentValue + let params = getParams(); + params.type = "relay"; + params.line = parseInt(line); + params.tbname = relaysData[line].tbname; + params.value = currentValue; + params.timestamp = i; + params.debug = true; + + //logger.debug(now.toLocaleString("sk-SK")); + 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; + + tasks.push(params); + + } catch (error) { + if (profilestr !== "") { + //errLogger.error(profilestr, error); + console.log(`Cmd_mngr: Unable to process line profile ${line}. Error: `, error); + errorHandler.sendMessageToService(profilestr + "-" + error, 0, "js_error"); + } else { + turnLine("off", line, "No line profile. Switching it off on startup"); + } + } + + } + //logger.debug("tasks:"); + //logger.debug(tasks); + } + + + //NOTE: PROCESS DEFAULT BROADCASTS - Time of dusk, Time of dawn, Actual Time + if (processBroadcast) { + + let d = new Date(); + let time = d.getTime(); + //let sunCalcResult = calculateDuskDawn(); + + { + let params = getParams(); + + params.address = 0xffffffff;//broadcast + params.byte1 = sunCalcResult["dusk_hours"]; + params.byte2 = sunCalcResult["dusk_minutes"]; + params.recipient = 2;//2 broadcast, + params.register = 6;//Time of dusk + params.rw = 1;//write + params.type = "node-regular-write"; + params.timestamp = time + 60000; + params.addMinutesToTimestamp = 60 * 3; //kazde 3 hodiny zisti novy dusk + params.info = "Broadcast-duskTime"; + + tasks.push(params); + } + + { + let params = getParams(); + + params.address = 0xffffffff;//broadcast + params.byte1 = sunCalcResult["dawn_hours"]; + params.byte2 = sunCalcResult["dawn_minutes"]; + params.recipient = 2; //2 broadcast + params.register = 7;//Time of dawn + params.rw = 1;//write + params.type = "node-regular-write"; + params.timestamp = time + 60001; + params.addMinutesToTimestamp = 60 * 3; //kazde 3 hodiny zisti novy dawn + params.info = "Broadcast-dawnTime"; + + tasks.push(params); + } + + { + let params = getParams(); + + params.address = 0xffffffff;//broadcast + params.byte1 = d.getHours(); + params.byte2 = d.getMinutes(); + params.recipient = 2; //2 broadcast + params.register = 87;//Actual time + params.rw = 1;//write + params.type = "node-regular-write"; + params.timestamp = time + 60002; + params.addMinutesToTimestamp = 5; + params.info = "run broadcast: Actual time"; + + tasks.push(params); + } + + } + + //process nodes & tasks - read node's data + if (processNodes) { + + let time = Date.now(); + + for (let k in nodesData) { + let address = parseInt(k); + let tbname = nodesData[k].tbname; + let register = 0; + + for (let i = 0; i < listOfCommands.length; i++) { + + register = listOfCommands[i]; + let addMinutesToTimestamp = priorities[register]; + + let params = getParams(); + + params.address = address; + params.recipient = 1; + params.register = register; + params.type = register == 1 ? "node-dimming-read" : "node-regular-read"; + params.tbname = tbname; + params.timestamp = time + 5000 + i * 500 + addMinutesToTimestamp * 1000; //to make slight time difference + params.addMinutesToTimestamp = addMinutesToTimestamp; + params.info = "Node regular read command"; + + tasks.push(params); + } + + } + } + + + //niektore ulohy sa vygeneruju iba 1x pri starte!!! + if (!init) return; + + + //Master node FW version - modifies SETTINGS.masterNodeIsResponding + { + let params = getParams(); + params.type = "cmd-master"; + params.register = 4; + params.address = 0; + params.timestamp = 0; + params.addMinutesToTimestamp = 5; + params.tbname = SETTINGS.rvoTbName; + params.info = "Master node FW verzia"; + //params.debug = true; + + tasks.push(params); + } + + //kazdu hodinu skontrolovat nastavenie profilov + { + let params = getParams(); + params.type = "process_profiles"; + params.timestamp = Date.now() + 60001; + params.addMinutesToTimestamp = 60;//60 = every hour + params.info = "detekcia nespracovaných profilov linie a nodov"; + //params.debug = true; + + tasks.push(params); + } + + monitor.info("tasks created:", tasks.length); + } + + + /** + * We process line profile, where "astro_clock": true + * example profile: + * + "dawn_lux_sensor": true, + "dusk_lux_sensor": true, + "dawn_lux_sensor_value": 5, + "dusk_lux_sensor_value": 5, + "dawn_astro_clock_offset": 0, + "dusk_astro_clock_offset": 10, + "dawn_lux_sensor_time_window": 30, + "dusk_lux_sensor_time_window": 30, + "dawn_astro_clock_time_window": 60, + "dusk_astro_clock_time_window": 60 + + * if dawn: if currentTimestamp is in timewindow "dawnTime + and - dawn_lux_sensor_time_window" and lux value >= lux_sensor_value, we switch off the line. + * if dusk: we do oposite + * + * dawn: usvit - lux je nad hranicou - vypnem + * dusk: sumrak - lux je pod hranicou - zapnem + */ + 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++) { + + let line = keys[i]; //line is turned off by default + let profilestr = relaysData[line].profile; + const contactor = relaysData[line].contactor; + + try { + + let profile = JSON.parse(profilestr); + if (Object.keys(profile).length === 0) throw ("turnOnOffLinesAccordingToLuxSensor - profile is not defined"); + + 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 (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"); + } + } + } + + //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 (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"); + } + } + } + + } + + } catch (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) { + //MASTER + if (node == 0) return; + + let nodeObj = nodesData[node]; + if (nodeObj == undefined) return; + + let nodeCurrentStatus = nodeObj.status; + const now = Date.now(); + + let data = null; + + if (nodeCurrentStatus === "OFFLINE") { + data = { status: newStatus }; + nodeDbStatusModify(node, data); + return; + } + else 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; + } + + } + + + 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 }; + } + }); + }); + } + + + function processDailyReport() { + + const now = Date.now(); + + for (const [key, value] of Object.entries(dailyReport)) { + + if (["name", "time", "dusk_and_dawn"].includes(key)) continue; + + let poleNumber = nodesData[key]["pole_number"]; + let line = dailyReport[key].line; + let nodeType = nodesData[key]["node_type"]; + let fullNodeName = key // key == nodeNumber + + if (poleNumber && nodeType) { + fullNodeName = SETTINGS.rvo_number + "/" + poleNumber + "_" + line + "L_" + key + "_" + nodeType; + } else { + fullNodeName = key; + } + + if (rvo_is_on) { + + if (value.initialTs) { + if (value.initialTs + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["night_no_data"], fullNodeName); + console.log('report nedostava ziadne data uz hodinu', fullNodeName); + value.initialTs = now; + } + } + if (value.dimmingIsZeroTime) { + if (value.dimmingIsZeroTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["night_dimming=0"], fullNodeName); + console.log("report node dimming je 0 ale ma svietit", fullNodeName); + value.dimmingIsZeroTime = now; + } + } + if (value.powerIsZeroTime) { + if (value.powerIsZeroTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["night_power=0"], fullNodeName); + console.log("report node power je 0 ale ma svietit", fullNodeName); + value.powerIsZeroTime = now; + } + } + + } else { + + let contactorStatus = relaysData[line].contactor; + if (contactorStatus === 1) { + + if (value.initialTs) { + if (value.initialTs + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["day_24/7_no_data"], fullNodeName); + console.log('node je na 24/7 ale nedostava ziadne data uz hodinu', fullNodeName); + value.initialTs = now; + } + } + if (value.dimmingIsOnButShouldBeOffTime) { + if (value.dimmingIsOnButShouldBeOffTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["day_24/7_dimming>0"], fullNodeName); + console.log("report dimming je > 0 ale nema svietit", fullNodeName); + value.dimmingIsOnButShouldBeOffTime = now; + } + } + if (value.powerIsOnButShouldBeOffTime) { + if (value.powerIsOnButShouldBeOffTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["day_24/7_power>0"], fullNodeName); + console.log("report power je > 0 ale nema svietit", fullNodeName); + value.powerIsOnButShouldBeOffTime = now; + } + } + + } + + } + + } + + let report = {}; + report["name"] = SETTINGS.rvo_name; + report["time"] = new Date(); + report["report"] = reportToSend; + + writeToFile(F.path.root("report_data.log"), report, true); + instance.send(SEND_TO.dailyReport, report); + } + + + function dailyReportHandler() { + + if (!SETTINGS.daily_report) return; + + // after dawn we empty reportToSend and start to get data for a new day + const date = new Date(); + const hour = date.getHours(); + const minute = date.getMinutes(); + + console.log("now: ", hour, minute, "suncalc: ", sunCalcResult.dawn_hours, sunCalcResult.dawn_minutes); + + if (hour === sunCalcResult.dawn_hours) { + + //NOTE: ak je este pred usvitom, spracujeme report a posleme na cloud, ak uz je po usvite, resetujeme report plnime data noveho dna + if (minute >= sunCalcResult.dawn_minutes - 2) { + emptyReportToSend(); + emptyDailyReport(); + console.log("Podmienka 1 v dailyReport handler"); + } else { + processDailyReport(); + emptyReportToSend(); + emptyDailyReport(); + console.log("Podmienka 2 v dailyReport handler"); + } + + initialReportStatus = true; + + // ak sa funkcia spusti o hodinu alebo 2 neskor, ako je usvit (moze sa to stat, kedze kazde zapnutie/vypnutie linii odznova spusti casovac. + } else if (hour === sunCalcResult.dawn_hours + 1 || hour === sunCalcResult.dawn_hours + 2) { + if (!initialReportStatus) { + emptyReportToSend(); + emptyDailyReport(); + initialReportStatus = true; + console.log("Podmienka 3 v dailyReport handler"); + } else { + processDailyReport(); + initialReportStatus = true; + console.log("Podmienka 4 v dailyReport handler"); + } + } else { + processDailyReport(); + initialReportStatus = false; + console.log("Podmienka 5 v dailyReport handler"); + } + + console.log("initialReportStatus: ", initialReportStatus); + + } + + function emptyReportToSend() { + emptyJsObject(reportToSend); + reportToSend["contactor"] = { off: [], on: [] }; + reportToSend["night_no_data"] = []; + reportToSend["night_dimming=0"] = []; + reportToSend["night_power=0"] = []; + reportToSend["day_24/7_no_data"] = []; + reportToSend["day_24/7_dimming>0"] = []; + reportToSend["day_24/7_power>0"] = []; + console.log(`resetuje sa reportToSend`); + } + + + //NOTE: ked je initialTs stale rovnaky a zistime ze linie su vypnute (relaysData.line.contactor) - zistim, ci je node na tej linii. Vieme, ze ak je linia vypnuta je to v poriadku lebo nie je na 24/7 linii + //ak je na 24/7 linii, reportujeme, ze neprijima data + function emptyDailyReport() { + const ts = Date.now(); + emptyJsObject(dailyReport); + + //NOTE: do dailyReport dame vsetky nody a pravidelne kontrolujeme ci maju data + //ked nastane sumrak/usvit a svetla maju zacat/prestat svietit, dailyReport spravime nanovo: + for (const [key, value] of Object.entries(nodesData)) { + dailyReport[value.node] = { line: value.line, initialTs: ts }; + } + + console.log("dailyReport: ", dailyReport); + } + + + async function runTasks() { + + clearInterval(interval); + + let currentTimestamp = Date.now(); + + //sort tasks based on timestamp + 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) { + instance.send(SEND_TO.debug, "no tasks created"); + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + if (!rsPort.isOpen) { + instance.send(SEND_TO.debug, "!rsPort.isOpen"); + //await rsPort.open(); + //console.log("Cmd-mngr: !rsPort.isOpen"); + } + + let currentTask = tasks[0]; + + if (currentTask.debug) { + //logger.debug("--->task to process", currentTask); + } + + if (currentTask.timestamp <= currentTimestamp) { + let params = { ...tasks[0] }; + + //allow terminal commands + if (SETTINGS.maintenance_mode && params.type !== "cmd-terminal") { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + let type = params.type; + let tbname = params.tbname; + let node = params.address; + let register = params.register; + let line = null; + let itIsNodeCommand; + + if (nodesData[node] !== undefined) { + line = nodesData[node].line; + itIsNodeCommand = true; + } + + if (params.line !== undefined) line = params.line; + + if (params.addMinutesToTimestamp > 0 || params.timePointName) { + tasks[0].timestamp = currentTimestamp + tasks[0].addMinutesToTimestamp * 60000; + } else { + tasks.shift(); + } + + //kontrola nespracovanych profilov nodov + //TODO: co ked niektore nody neprijimaju profily? kazdu hodinu zahltuju "tasks" array + if (type == "process_profiles") { + //na vsetky zapnutych liniach sa spracuju nespracovane profily nodov + loadRelaysData(); + interval = setInterval(runTasks, SHORT_INTERVAL); + return; + } + + //relay + if (type == "relay") { + + const timePointName = params.timePointName; + const value = params.value; + + let date = new Date(); + date.setDate(date.getDate() + 1);//next day + + let sunCalcResult; + if (timePointName) sunCalcResult = calculateDuskDawn(date, params.line); + + + if (timePointName == "dawn") { + tasks[0].timestamp = sunCalcResult.dawn_time; + } + else if (timePointName == "dusk") { + tasks[0].timestamp = sunCalcResult.dusk_time; + } + else if (timePointName == "luxOn") { + tasks[0].timestamp = sunCalcResult.dusk_time + params.dusk_lux_sensor_time_window * 60000; + } + else if (timePointName == "luxOff") { + tasks[0].timestamp = sunCalcResult.dawn_time + params.dawn_lux_sensor_time_window * 60000; + } + else if (timePointName == "profileTimepoint") { + tasks[0].timestamp = currentTimestamp + tasks[0].addMinutesToTimestamp * 60000; + } + + let info = "aplikovany bod profilu"; + let onOrOff = ""; + value == 1 ? onOrOff = "on" : onOrOff = "off"; + + turnLine(onOrOff, params.line, info); + + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + if (!SETTINGS.masterNodeIsResponding) { + //ak neodpoveda, nebudeme vykonavat ziadne commands, okrem cmd-terminal cmd-master + errorHandler.sendMessageToService("Master node is not responding"); + + let stop = true; + + if (type === "cmd-terminal" || type === "cmd-master") stop = false; + if (stop) { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + } + + let contactorStatus = 1; + if (relaysData[line] != undefined) contactorStatus = relaysData[line].contactor; + + if (line === 0 || contactorStatus === 0 || FLOW.deviceStatus.state_of_breaker[line] === "Off") { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + // TODO: -> status offline for rvo if rotary_switch_state is OFF, this is source of errors + // check if rotary_switch_state == "Off" + // state_of_braker: disconnected = true? + + if (!rsPort.isOpen) { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + //RE-CALCULATE VALUES + //set actual time for broadcast + if (register == 87 && params.recipient === 2) { + var d = new Date(); + params.byte1 = d.getHours();//h + params.byte2 = d.getMinutes();//m + } + + //SET DUSK/DAWN FOR BROADCAST + //Time of dusk + if (register == 6 && params.recipient === 2) { + + if (type != "cmd-terminal") { + params.byte1 = sunCalcResult["dusk_hours"];//h + params.byte2 = sunCalcResult["dusk_minutes"];//m + } + } + + //Time of dawn + if (register == 7 && params.recipient === 2) { + if (type != "cmd-terminal") { + params.byte1 = sunCalcResult["dawn_hours"];//h + params.byte2 = sunCalcResult["dawn_minutes"];//m + } + } + //----------------------- + + instance.send(SEND_TO.debug, "address: " + node + " register:" + register + "type: " + type); + + var startTime, endTime; + startTime = new Date(); + + let saveToTb = true; + if (!tbname) saveToTb = false; + + let resp = com_generic(node, params.recipient, params.rw, register, params.name, params.byte1, params.byte2, params.byte3, params.byte4); + let readBytes = 11; + let timeout = 4000; + + + // await keyword is important, otherwise incorrect data is returned! + await writeData(rsPort, resp, readBytes, timeout).then(function(data) { + + //sometimes happens, that status of node changes to OK, NOK even if line was turned off and should be status OFFLINE. To prevent this, we return if line contactor is 0: + if (itIsNodeCommand && line && relaysData[line].contactor !== 1) return; + + 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); + + //ak sa odpoved zacina 0 - je to v poriadku, inak je NOK + let message = result.message; // OK, NOK + let message_type = result.type; + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + console.log("detected response:", result); + logger.debug("Cmd-mngr: writeData done " + message_type + " duration: " + timeDiff + " type: " + params.debug, params, result); + } + } + + let values = {}; + + //CMD FINISHED + if (message == "OK") { + + updateNodeStatus(node, true); + + //write + if (type == "set_node_profile") { + let result = cmdCounterResolve(node); + if (result == 0) { + dbNodes.modify({ processed: true }).where("node", node).make(function(builder) { + builder.callback(function(err, response) { + + sendNotification("Cmd-mngr: process cmd", SETTINGS.rvoTbName, "dimming_profile_was_successfully_received_by_node", { node: node }, "", SEND_TO.tb, instance); + + logger.debug("--> profil úspešne odoslaný na node č. " + node); + nodesData[node].processed = true; + nodeProfileSendFail.delete(node); + }); + }); + } + } + + //parse read response + if (params.rw == 0) { + values = processResponse(register, dataBytes); //read + } + + if (itIsNodeCommand) { + values.comm_status = "OK"; + values.status = "OK"; + nodesData[node].readout = { ...nodesData[node].readout, ...values }; + + + if (SETTINGS.daily_report) { + //TODO: co ak nedostavame odpovede z nodu ? Musime vyreportovat!! + //v dailyReport teda musi byt kompletny zoznam nodov a neustale kontrolovat, ci maju data, ak nie report node - neodpoveda + if (register === 1) { + + let now = Date.now(); + + if (rvo_is_on === true) { + + if ("dimmingIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].dimmingIsOnButShouldBeOffTime; + + if (values.dimming > 0) { + if ("dimmingIsZeroTime" in dailyReport[node]) delete dailyReport[node].dimmingIsZeroTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if (!("dimmingIsZeroTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], dimmingIsZeroTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } else { + + if ("dimmingIsZeroTime" in dailyReport[node]) delete dailyReport[node].dimmingIsZeroTime; + + if (values.dimming > 0) { + if (!("dimmingIsOnButShouldBeOffTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], dimmingIsOnButShouldBeOffTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if ("dimmingIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].dimmingIsOnButShouldBeOffTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } + } + + if (register === 76) { + + let now = Date.now(); + + if (rvo_is_on === true) { + + if ("powerIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].powerIsOnButShouldBeOffTime; + + if (values.power > 1) { + if ("powerIsZeroTime" in dailyReport[node]) delete dailyReport[node].powerIsZeroTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if (!("powerIsZeroTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], powerIsZeroTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } else { + + if ("powerIsZeroTime" in dailyReport[node]) delete dailyReport[node].powerIsZeroTime; + + if (values.power > 1) { + if (!("powerIsOnButShouldBeOffTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], powerIsOnButShouldBeOffTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if ("powerIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].powerIsOnButShouldBeOffTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } + } + } + + } + + //master node + if (node == 0) { + sendNotification("Cmd-mngr: 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; + } + + if (params.debug) { + //logger.debug("saveToTb", saveToTb, tbname, values); + } + + if (saveToTb && type != "node-regular-read") { + sendTelemetry(values, tbname); + } + else { + if (type == "cmd-terminal") { + terminalCommandResponse(params, "SUCCESS", data); + } + } + + } + else { + terminalCommandResponse(params, "ERROR", data); + handleNokResponseOnRsPort("handleNOK else block", params, itIsNodeCommand, saveToTb); + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + //logger.debug("writeData err: ", error, result, params); + logger.debug("writeData err: ", tbname, node, register, values); + } + } + + //logger.debug(error, result, params); + } + }).catch(function(reason) { + + //console.log("writeData catch exception", reason); + instance.send(SEND_TO.debug, reason); + + terminalCommandResponse(params, "FAILURE", null, reason); + handleNokResponseOnRsPort("handleNOK catch block", params, itIsNodeCommand, saveToTb); + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + logger.debug("-->WRITE FAILED: " + reason, params.debug, params); + } + } + + }); + + } + 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); + } + + + // if node does not respond to request, we repeat request 3 times: + function repeatCommand(params) { + params.repeatCounter++; + if (params.repeatCounter < 4) { + params.timestamp = 0; + params.addMinutesToTimestamp = 0; + tasks.push(params); + } + } + + function handleNokResponseOnRsPort(message, params, itIsNodeCommand, saveToTb) { + + let node = params.address; + let register = params.register; + let type = params.type; + let tbName = params.tbname; + if (!tbName) return; + + let values = {}; + + let updateStatus = updateNodeStatus(node, false); + + if (itIsNodeCommand) { + values.comm_status = "NOK"; + nodesData[node].readout.comm_status = "NOK"; + repeatCommand(params); + } + + if (updateStatus) { + values.status = "NOK"; + nodesData[node].readout.status = "NOK"; + } + + if (type === "node-regular-read") return; + + //master node + if (node == 0) { + sendNotification("Cmd-mngr: 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; + + if (register == 4) values["master_node_version"] = "NOK"; + } + + if (type == "set_node_profile") { + delete cmdCounter[node]; + logger.debug("profil nebol úspešne odoslaný na node č. ", params); + + if (!nodeProfileSendFail.has(node)) { + sendNotification("Cmd-mngr: process cmd", tbName, "configuration_of_dimming_profile_to_node_failed", { node: node }, "", SEND_TO.tb, instance); + nodeProfileSendFail.add(node); + } + } + + // console.log("------",node, register, type, itIsNodeCommand, updateStatus, saveToTb, values); + if (saveToTb) { + sendTelemetry(values, tbName); + } + + } + + + function sendNodesData() { + Object.keys(nodesData).forEach(node => { + if (nodesData[node]["status"] !== "OFFLINE") { + sendTelemetry(nodesData[node].readout, nodesData[node].tbname); + nodesData[node].readout = {}; + } + }) + } + + + /** + * 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; + } + + 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); + + //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 === "OFFLINE") { + nodeObj.node_status_before_offline === true ? number_of_ok_luminaires++ : number_of_nok_luminaires++; + } + else if (nodeObj.status == true) 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 - ts % 60000 //round to full minute + }; + + sendTelemetry(values, SETTINGS.rvoTbName, ts); + } + + + function setSunCalcResult() { + //if next day, we get new dusk and dawn. To make sure, in local timezone 2:00 means 00:00 in utc (it means next day) + if (new Date().getHours() === 2) { + sunCalcResult = calculateDuskDawn(); + console.log("Novy suncalc: ", sunCalcResult); + } + } + + + function setRvoPeriod() { + + if (!SETTINGS.daily_report) return; + + const ts = Date.now(); + + previous_rvo_is_on_value = rvo_is_on; + + if (ts < sunCalcResult.dawn_time - 1_800_000) { // nodes should be on (00:00 -> 06:00 ( - pol hodina, lebo rvo vypina skor) + rvo_is_on = true; + } else if (sunCalcResult.dawn_time - 1_800_000 < ts && ts < sunCalcResult.dusk_time + 1_800_000) { // nodes should be off 06:00 -> 21:00 + rvo_is_on = false; + } else if (sunCalcResult.dusk_time + 1_800_000 < ts) { // nodes should be on 21:00 -> 00:00 + rvo_is_on = true; + } + + if (previous_rvo_is_on_value !== rvo_is_on) { + emptyDailyReport(); + console.log("rvo_is: ", rvo_is_on, previous_rvo_is_on_value); + } + } + + + function handleRsPort() { + + if (rsPort) { + rsPort.removeAllListeners(); + rsPort = null; + } + + //! 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-mngr: rsPort opened success"); + + 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); + + }).catch(function(reason) { + instance.send(SEND_TO.debug, "Cmd-mngr: RPC runSyncExec - promise rejected:" + reason); + }); + }); + + rsPort.on('error', function(err) { + errorHandler.sendMessageToService([exports.title, "unable to open port", SETTINGS.serial_port, err.message], 0); + monitor.info("Cmd-mngr: Error on rsPort", err.message); + }); + + rsPort.on("close", () => { + monitor.info("Cmd-mngr: rsPort closed, reconnecting..."); + setTimeout(handleRsPort, 1000); + }); + + rsPort.open(); + } + + + instance.on("close", () => { + clearInterval(interval); + clearInterval(customTasksInterval); + clearInterval(setCorrectTime); + clearInterval(sendNodeReadout); + clearInterval(accelerometerInterval); + rsPort.close(); + }); + + instance.on("0", _ => { + main(); + }) + + + instance.on("2", _ => { + console.log("dailyReport, reportToSend, rvo_is_on", dailyReport, reportToSend, rvo_is_on, previous_rvo_is_on_value); + }) + + instance.on("1", 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(); + return; + } + else if (flowdata.data == "close") { + rsPort.close(); + return; + } + else if (flowdata.data == "clean") { + tasks = []; + return; + } + else if (flowdata.data == "buildtasks") { + //build & run + return; + } + else if (flowdata.data == "run") { + //durations = []; + + if (tasks.length == 0) { + + buildTasks(); + + if (rsPort.isOpen) { + interval = setInterval(runTasks, 100); + } + else { + instance.send(SEND_TO.debug, "port is not opened!!!"); + } + } + } + else { + //terminal data - object + //logger.debug("flowdata", flowdata.data); + + if (typeof flowdata.data === 'object') { + //logger.debug("dido", flowdata.data); + if (flowdata.data.hasOwnProperty("sender")) { + //data from dido_controller + if (flowdata.data.sender == "dido_controller") { + + if (flowdata.data.hasOwnProperty("cmd")) { + let cmd = flowdata.data.cmd; + + if (cmd == "buildTasks") { + clearInterval(interval); + + logger.debug("-->Cmd-mngr: BUILD TASKS"); + buildTasks(); + + //logger.debug("tasks:"); + //logger.debug(tasks); + + logger.debug("-->Cmd-mngr: RUN TASKS"); + interval = setInterval(runTasks, 5000); + } + else if (cmd == "reload_relays") { + loadRelaysData(flowdata.data.line); + + if (flowdata.data.dataChanged) { + if (!flowdata.data.value) { + reportOfflineNodeStatus(flowdata.data.line); + } + else { + reportOnlineNodeStatus(flowdata.data.line); + } + } + + } + else if (cmd == "rotary_switch_state") { + let value = flowdata.data.value; + + //state was changed + if (rotary_switch_state != value) { + if (value == "Off") { + //vyreportovat vsetky svietdla + reportOfflineNodeStatus(); + } + + rotary_switch_state = value; + } + } + 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) { + + // we send lux_sensor value to all nodes: + let params = getParams(PRIORITY_TYPES.node_broadcast); + + params.recipient = 2;//2 broadcast, address = 0 + params.address = 0xffffffff;//Broadcast + + let ba = longToByteArray(lux_sensor); + + params.byte3 = ba[1];//msb + params.byte4 = ba[0]; + params.timestamp = PRIORITY_TYPES.node_broadcast; + params.info = "run broadcast: Actual Lux level from cabinet"; + params.register = 95;//Actual Lux level from cabinet + params.rw = 1;//write + + tasks.push(params); + + //process profiles + turnOnOffLinesAccordingToLuxSensor(lux_sensor); + } + } + else if (cmd == "state_of_breaker") { + //istic linie + + breakerCounter--; + + let value = flowdata.data.value; + let line = parseInt(flowdata.data.line); + + let dataChanged = false; + if (state_of_breaker[line] != value) dataChanged = true; + + state_of_breaker[line] = value; + + let status = "OK"; + if (value == "Off") status = "NOK"; + + if (dataChanged) { + + if (relaysData.hasOwnProperty(line)) { + let tbname = relaysData[line].tbname; + + if (value == "Off") { + sendNotification("Cmd-mngr: onData", tbname, "circuit_breaker_was_turned_off_line", { line: line }, "", SEND_TO.tb, instance, "circuit_breaker"); + if (breakerCounter < 0) reportToSend["contactor"]["off"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + else { + sendNotification("Cmd-mngr: onData", tbname, "circuit_breaker_was_turned_on_line", { line: line }, "", SEND_TO.tb, instance, "circuit_breaker"); + if (breakerCounter < 0) reportToSend["contactor"]["on"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + + //report status liniu + sendTelemetry({ status: status }, tbname) + + //current value + if (value == "Off") reportOfflineNodeStatus(line); //vyreportovat vsetky svietidla na linii + } + + } + } + else { + logger.debug("undefined cmd", cmd); + } + } + } + + return; + } + + //data from worksys + if (flowdata.data.hasOwnProperty("topic")) { + + let data = getNested(flowdata.data, "content", "data"); + + //if we get temperature in senica from senica-prod01 + let temperature = getNested(flowdata.data, "content", "senica_temperature"); + + if (temperature !== undefined) { + temperatureInSenica = temperature; + return; + } + + if (data === undefined) { + console.log("Invalid rpc command came from platform"); + return; + } + + let command = data.params.command; + let method = data.method; + let profile = data.params.payload; + if (profile == undefined) profile = ""; + let entity = data.params.entities[0]; + let entity_type = entity.entity_type; + let tbname = entity.tb_name; + + instance.send(SEND_TO.debug, flowdata.data); + 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") { + + //let command = data.params.command; + let value = data.params.payload.value; + + if (command == "dimming") { + + let nodeWasFound = false; + let keys = Object.keys(nodesData); + + //logger.debug("-----", keys); + + 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); + + value = parseInt(value); + if (value > 0) value = value + 128; + + params.type = "node-onetime-write"; + params.tbname = tbname; + params.address = node; + params.register = 1; + params.recipient = 1; + params.byte4 = value; + params.rw = 1; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'set dimming from platform'; + //params.debug = true; + + //debug(params); + logger.debug("dimming", params); + + tasks.push(params); + + 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); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 1; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read dimming (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + //pridame aj vyreportovanie - vykon + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 76; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read Input Power (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + //pridame aj vyreportovanie - prud svietidla + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 75; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read Input Current (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + //pridame aj vyreportovanie - power faktor - ucinnik + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 77; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read power factor (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + }, 4000); + + nodeWasFound = true; + break; + } + } + + if (!nodeWasFound) { + logger.debug("set dimming from platform", "unable to find tbname", tbname); + } + } + else { + instance.send(SEND_TO.debug, "undefined command " + command); + logger.debug("undefined command", command); + } + + return; + } + 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++) { + let node = keys[i]; + if (tbname == nodesData[node].tbname) { + + 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"); + + //profil úspešne prijatý pre node č. xx + sendNotification("Cmd-mngr", tbname, "dimming_profile_was_processed_for_node", { node: node }, profile, SEND_TO.tb, instance); + + nodesData[node].processed = false; + nodesData[node].profile = profile; + + processNodeProfile(node); + }); + }); + } + } + } + else { + + instance.send(SEND_TO.debug, "unknown method " + method); + logger.debug("unknown method", method); + + return; + } + } + + //nastav profil linie z platformy + 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") { + + 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++) { + let line = keys[i]; + if (tbname == relaysData[line].tbname) { + //zmazeme tasky + 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) { + + //update profile + logger.debug("worksys - update relay profile done:", profile); + instance.send(SEND_TO.debug, "worksys - update relay profile done"); + + relaysData[line].profile = profile; + + loadRelaysData(line) + logger.debug("loadRelaysData DONE for line", line); + + buildTasks({ processLineProfiles: true, line: line }); + + sendNotification("Cmd-mngr: set profile from worksys", tbname, "switching_profile_was_processed_for_line", { line: line }, profile, SEND_TO.tb, instance); + }); + }); + break; + } + } + } + else if (method == "set_command") { + let value = data.params.payload.value; + + 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; + + 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"); + if (line != 0) reportToSend["contactor"]["off"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + else { + turnLine("on", line, "command received from platform"); + if (line != 0) reportToSend["contactor"]["on"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + } + } + else { + instance.send(SEND_TO.debug, "undefined method " + method); + logger.debug("undefined method", method); + } + + return; + } + else { + instance.send(SEND_TO.debug, "UNKNOW entity_type " + entity_type); + logger.debug("UNKNOW entity_type", entity_type); + } + return; + } + + //terminal + if (!rsPort.isOpen) await rsPort.open(); + + let params = flowdata.data.body; + if (params == undefined) { + //logger.debug("Cmd-mngr: flowdata.data.body is undefined"); + return; + } + + params.priority = PRIORITY_TYPES.terminal; + params.type = "cmd-terminal"; + params.tbname = ""; + params.timestamp = PRIORITY_TYPES.terminal; + params.addMinutesToTimestamp = 0;// do not repeat task!!! + params.debug = true; + + let timestamp = Date.now(); + params.refFlowdataKey = timestamp; + //params.refFlowdata = flowdata; + //refFlowdata = flowdata; + + //console.log("flowdata", flowdata); + + cleanUpRefFlowdataObj(); + + refFlowdataObj[timestamp] = flowdata; + + //fix + //params.address = params.adress; + logger.debug("received from terminal", params); + logger.debug("date/time:", new Date()); + logger.debug("tasks length:", tasks.length); + + //tasks = []; + + //add to tasks + tasks.push(params); + + } + } + }) + + + //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) + } + + + /** + * 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; + + RESTBuilder.make(function(builder) { + + if (!builder) return; + + builder.method('GET'); + builder.url('http://192.168.252.2:8004/gettime?projects_id=1'); + + builder.callback(function(err, response, output) { + + 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); + } + + }); + } + + } 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); + + } else { + //console.log("Read-only", stdout); + + 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]: [ + { + "ts": date, + "values": values + } + ] + } + + tbHandler.sendToTb(dataToTb, instance); + } + + + function calculateDuskDawn(date, line, duskOffset = 0, dawnOffset = 0) { + + if (date === undefined) date = new Date(); + + 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); + } + + //if(profile.dawn_lux_sensor == false) + { + if (profile.hasOwnProperty("dawn_astro_clock_offset")) dawn_astro_clock_offset = parseInt(profile.dawn_astro_clock_offset); + } + + } + + } catch (error) { + if (profilestr != "") { + logger.debug(profilestr); + logger.debug(error); + } + } + + 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; + } + + //Dimming, CCT + else if (register == 1) { + let brightness = 0; + let dimming = byte0; + if (dimming > 128) { + //dimming = -128; + brightness = dimming - 128; + } + + //cct + //Ak Byte3 == 1: CCT = (Byte2*256)+Byte1 + let cct; + if (byte3 == 1) cct = byte2 * 256 + byte1; + else cct = bytesToInt(bytes.slice(0, 3)); + + //cct podla auditu + + values["dimming"] = brightness; + return values; + } + + // + else if (register == 4) { + values["master_node_version"] = bytes[1] + "." + bytes[2]; + //logger.debug("FW Version", register, bytes); + } + + //Napätie + else if (register == 74) { + let voltage = (bytesToInt(bytes) * 0.1).toFixed(1); + values["voltage"] = Number(voltage); + } + + //Prúd + else if (register == 75) { + let current = bytesToInt(bytes); + values["current"] = current; + } + + //výkon + else if (register == 76) { + let power = (bytesToInt(bytes) * 0.1).toFixed(2); + values["power"] = Number(power); + } + + //účinník + else if (register == 77) { + let power_factor = Math.cos(bytesToInt(bytes) * 0.1 * (Math.PI / 180)).toFixed(2); + values["power_factor"] = Number(power_factor); + } + + //frekvencia + else if (register == 78) { + let frequency = (bytesToInt(bytes) * 0.1).toFixed(2); + values["frequency"] = Number(frequency); + } + + //energia + else if (register == 79) { + let energy = bytesToInt(bytes); + values["energy"] = energy / 1000; //energia v kWh -> delit 1000 + } + + //doba života + else if (register == 80) { + let lifetime = (bytesToInt(bytes) / 60).toFixed(2); + values["lifetime"] = Number(lifetime); + } + + //nastavenie profilu + else if (register == 8) { + let time_schedule_settings = bytesToInt(bytes); + values["time_schedule_settings"] = time_schedule_settings; + } + + //naklon - nateraz sa z nodu nevycitava! kvoli problemom s accelerometrom a vracanymi hodnotami, posielame temp a x y z vo funkcii accelerometerData() + else if (register == 84) { + values["temperature"] = byte3 >= 128 ? (byte3 - 128) * (-1) : byte3; + values["inclination_x"] = byte2 >= 128 ? (byte2 - 128) * (-1) : byte2; + values["inclination_y"] = byte1 >= 128 ? (byte1 - 128) * (-1) : byte1; + values["inclination_z"] = byte0 >= 128 ? (byte0 - 128) * (-1) : byte0; + } + + //FW verzia nodu + else if (register == 89) { + //formát: "Byte3: Byte2.Byte1 (Byte0)" + values["fw_version"] = byte3 + ":" + byte2 + "." + byte1 + "(" + byte0 + ")"; + } + + else if (register == 87 || register == 6 || register == 7) { + var d = new Date(); + d.setHours(byte3, byte2, 0, 0); + let timestamp = d.getTime(); + + //aktuálny čas + if (register == 87) values["actual_time"] = timestamp; + //čas súmraku + else if (register == 6) values["dusk_time"] = timestamp; + //čas úsvitu + else if (register == 7) values["dawn_time"] = timestamp; + } + + 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; + + } + + + function getObjectByTbValue(object, tbname) { + return object[Object.keys(object).find(key => object[key].tbname === tbname)]; + } + + + function isObject(item) { + return (typeof item === "object" && !Array.isArray(item) && item !== null); + } + + + // we fake data, that should be received from accelerometer, as they are a bit unreliable. (temperature, x,y,z) + function accelerometerData() { + + if (temperatureInSenica === null) return; + + //clone nodesData and relaysData objects + let nodesData_clone = JSON.parse(JSON.stringify(nodesData)); + let relaysData_clone = JSON.parse(JSON.stringify(relaysData)); + + for (const key in relaysData_clone) { + + const lineData = relaysData_clone[key]; + const lineNumber = lineData.line; + const contactor = lineData.contactor; + + if (lineNumber === 0) continue; + + if (contactor === 1) { + + let date = Date.now(); + + Object.keys(nodesData_clone).forEach((node, index) => { + + setTimeout(function() { + + if (nodesData_clone[node].line === lineNumber) { + + // NOTE: if status of luminaire is NOK or OFFLINE, we do not send data; + let status = nodesData_clone[node].status; + if (status === "OFFLINE" || !status) return; + + let x = null; + if (naklony.hasOwnProperty(node)) x = naklony[node].naklon; + if (x === null) x = 0; + + sendTelemetry({ temperature: Math.round(temperatureInSenica + 10 + Math.floor(Math.random() * 3)), inclination_x: x, inclination_y: 0, inclination_z: 0 }, nodesData_clone[node].tbname, date); + } + + }, (index + 1) * 500); + }) + + } + } + } + + +} // end of instance.export + diff --git a/RVO39/flow/cmd_manager_before_dailyReportHandler.txt b/RVO39/flow/cmd_manager_before_dailyReportHandler.txt new file mode 100755 index 0000000..460679b --- /dev/null +++ b/RVO39/flow/cmd_manager_before_dailyReportHandler.txt @@ -0,0 +1,2984 @@ +exports.id = 'cmd_manager'; +exports.title = 'CMD Manager'; +exports.group = 'Worksys'; +exports.color = '#5D9CEC'; +exports.version = '0.0.3'; +exports.output = ['red', 'blue', 'yellow', 'blue', 'white', 'green']; +exports.input = 3; +exports.icon = 'cloud-upload'; + +exports.html = ` +
+
+
+
RPC - run RPC calls

+
+
+
@(User)
+
+
+
@(Password)
+
+
+
@(My edge)
+
+
+
+`; +exports.readme = `Manager for CMD calls`; + + +exports.install = function(instance) { + + 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, isEmptyObject, emptyJsObject, writeToFile, addToArrayIfUnique } = require('./helper/utils'); + const bitwise = require('bitwise'); + + var SunCalc = require('./helper/suncalc'); + const DataToTbHandler = require('./helper/DataToTbHandler'); + const errorHandler = require('./helper/ErrorToServiceHandler'); + const { sendNotification } = require('./helper/notification_reporter'); + const process = require('process'); + const { errLogger, logger, monitor } = require('./helper/logger'); + + //for accelerometer purposes + const { naklony } = require("../databases/accelerometer_db"); + + const dbNodes = TABLE("nodes"); + const dbRelays = TABLE("relays"); + + let GLOBALS; + let SETTINGS; + let rsPort; + let tbHandler; + + // runTasks intervals + const SHORT_INTERVAL = 30; + const LONG_INTERVAL = 300; + + //send data to following instances: + const SEND_TO = { + debug: 0, + tb: 1, + http_response: 2, + dido_controller: 3, + infoSender: 4, + dailyReport: 5 + } + + 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 + } + + 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 sendNodeReadout = null; // interval for sending agregate data from node + + 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["1"] = minutes; // dimming + priorities["76"] = minutes; // power + + minutes = 5; + priorities["75"] = minutes; // current + priorities["79"] = minutes; // energy + priorities["87"] = minutes; // aktualny cas + //priorities["84"] = minutes; + + minutes = 10; + priorities["74"] = minutes; // voltage + priorities["77"] = minutes; // power factor + priorities["78"] = minutes; // frequency + + minutes = 60; + priorities["0"] = minutes; // statecode + priorities["6"] = minutes; // dusk + priorities["7"] = minutes; // dawn + priorities["8"] = minutes; // profile + + minutes = 60 * 24; + priorities["89"] = minutes; // verzia fw + priorities["80"] = minutes; // lifetime + + //prikazy kt sa budu spustat na dany node - see config.js in terminal-oms.app. (1 - dimming) + let listOfCommands = [0, 1, 6, 7, 8, 74, 75, 76, 77, 78, 79, 80, 87, 89]; + + 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; + + // holds dusk, dawn (and more) values + let sunCalcResult; + + //helper container for counting resolved group of commands (commands related to set profile) + let cmdCounter = {};//key is node, value is counter + + //TODO: is this set working?? According to previous checks, sets do not work + //if sending of profile to node fails, we send notification and push node into set, so we do not send notification twice + const nodeProfileSendFail = new Set(); + + //we expect to get current temperature in Senica from senica-prod01 + let temperatureInSenica = null; + let accelerometerInterval = null; + + //NOTE: daily reports senica: + //rvo_is_on status, we monitor all nodes - if true, power and dimming should be not 0, if false, 24/7 nodes should be 0, other rvo should not respond + let rvo_is_on; + let previous_rvo_is_on_value; + let checkDailyReport; //setInterval for daily report check + let dailyReport = {}; //data needed for daily report + let breakerCounter = null; // status of breakers after flow starts is not in report + let luxSensorValue = -1;//if twilight sensor is working and line profile is set to luxSensor, we set rvo_is_on according to luxSensor value. + let astroClockValue = -1; // if line profile is set to astroclock, we set rvo_is_on according to dusk or dawn with offsets. + let rvoPeriod; // interval of checking dusk dawn and if rvo_is_on + + let reportToSend = {}; + + //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); + + let now = new Date(); + console.log("Cmd-mngr installed", now.toLocaleString("sk-SK")); + + sunCalcResult = calculateDuskDawn(); + + handleRsPort(); + initialReportStatus(); + + breakerCounter = Object.keys(relaysData).length - 1; // we get number of lines (breakers) except of line 0 + + reportToSend["contactor"] = { off: [], on: [] }; + reportToSend["night_no_data"] = []; + reportToSend["night_dimming=0"] = []; + reportToSend["day_24/7_no_data"] = []; + reportToSend["day_24/7_dimming>0"] = []; + console.log("rrrreportTosend", reportToSend) + + customTasksInterval = setInterval(reportEdgeDateTimeAndNumberOfLuminaires, 120_000); + setTimeout(reportEdgeDateTimeAndNumberOfLuminaires, 4000); + + //dailyReport related + rvoPeriod = setInterval(setRvoPeriod, 300_000); + setTimeout(setRvoPeriod, 3000); + setInterval(setSunCalcResult, 3_600_000); + setInterval(emptyReportToSend, 3_600_000); + checkDailyReport = setInterval(dailyReportCheck, 3_600_000); + + setCorrectTime = setInterval(setCorrectPlcTimeOnceADay, 60000 * 60); // 1 hour + setCorrectPlcTimeOnceADay(); + + sendNodeReadout = setInterval(sendNodesData, 150_000); + accelerometerInterval = setInterval(accelerometerData, 60000 * 30); //30 min + } + + + 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" + //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 + // if node regular readout does not respond, we repeat request + params.repeatCounter = 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-mngr: 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.byte4 = 96; + params.recipient = 1; + params.register = 8; + params.rw = 1;//write + params.timestamp = timestamp; + 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.byte4 = 96; + params.recipient = 1; + params.register = 8; + params.rw = 1;//write + params.timestamp = timestamp; + 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). + */ + + 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.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.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 + { + + logger.debug("processNodeProfile: Threshold lux level for DUSK/DAWN", node); + + let params = getParams(); + params.type = "set_node_profile"; + params.address = node; + params.register = 96; + params.recipient = 1; + params.rw = 1;//write + params.timestamp = timestamp; + 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(); + params.type = "set_node_profile"; + params.address = node; + params.register = 97; + params.recipient = 1; + params.rw = 1;//write + params.timestamp = timestamp; + 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.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); + + 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); + + console.log("proces profile finished *********************") + } + + + 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; + }); + } + + + 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) { + for (let k in nodesData) { + 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`); + } + } + } + + + function loadRelaysData(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 (value.contactor == 1) processAllNodeProfilesOnLine(value.line); + } + } + + + function reportOnlineNodeStatus(line) { + //Po zapnutí línie broadcastovo aktualizovať predtým čas a o 3 sek neskor - status, brightness + + logger.debug("Cmd-mngr: ----->reportOnlineNodeStatus for line", line); + + const d = new Date(); + + // broadcast actual time + let params = getParams(); + params.address = 0xffffffff;//Broadcast + params.byte1 = d.getHours(); + params.byte2 = d.getMinutes(); + params.recipient = 2;//2 broadcast, address = 0 + params.register = 87;//Actual time + params.rw = 1;//write + params.type = "node-onetime-write"; + params.timestamp = d.getTime() + 30000; + params.info = "run broadcast: Actual time"; + //params.debug = true; + + tasks.push(params); + + let sec = 3; + setTimeout(function() { + //Po zapnutí línie - spraviť hromadný refresh stavu práve zapnutých svietidiel + + let time = Date.now(); + + for (let k in nodesData) { + + //potrebujem nody k danej linii + 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].node_status_before_offline === true || nodesData[k].status === true) { + status = "OK"; + nodesData[k].time_of_last_communication = time; + } + + nodesData[k].readout.status = status; + + updateNodeStatus(k, status === "OK" ? true : false); + if (nodesData[k].hasOwnProperty("node_status_before_offline")) delete nodesData[k].node_status_before_offline; + sendTelemetry({ status: status }, tbname, time); + + //vyreportovanie dimming, current, input power pre liniu pre vsetky nody + //Prud + { + let params = getParams(); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 75;//prud + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = time + 4000; + params.info = 'read current'; + //params.debug = true; + tasks.push(params); + } + + //vykon + { + let params = getParams(); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 76;//výkon + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = time + 4100; + params.info = 'read power'; + //params.debug = true; + + tasks.push(params); + } + //dimming + { + let params = getParams(); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 1;//dimming + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = time + 4200; + params.info = 'read dimming'; + //params.debug = true; + + tasks.push(params); + } + + } + } + + }, sec * 1000); + } + + + function reportOfflineNodeStatus(line) { + + logger.info("Cmd-mngr: ------>reportOffLineNodeStatus for line ", line); + + values = {}; + values["dimming"] = 0;//brightness + values["power"] = 0;//výkon + values["current"] = 0;//prúd + values["status"] = "OFFLINE"; + + const date = Date.now(); + + Object.keys(nodesData).forEach(node => { + + //potrebujem nody k danej linii + if (line == nodesData[node].line || line == undefined) { + + let tbname = nodesData[node].tbname; + let nodeStatus = nodesData[node].status; + + //in case we have reported offline node status, we return (continue with next node) + if (nodeStatus === "OFFLINE") return; + + nodesData[node].node_status_before_offline = nodeStatus; + nodesData[node].status = "OFFLINE"; + nodesData[node].readout = {}; + + sendTelemetry({ ...values }, tbname, date); + } + }); + + } + + + function turnLine(onOrOff, line, info) { + let obj = { + line: line, + command: onOrOff, + info: info + }; + + //to assure, checkDailyReportFunction do not run before rvo_is_on variable changes. So after every line switch we reset the timer + clearInterval(checkDailyReport); + checkDailyReport = setInterval(dailyReportCheck, 3_600_000); + + //logger.debug("linia", line, obj); + instance.send(SEND_TO.dido_controller, obj); + } + + + 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"; + 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]) { + //CRC_ERROR + message = "NOK"; + error = "CRC_ERROR c1"; + instance.send(SEND_TO.debug, "CRC_ERROR c1"); + } + + 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") { + instance.send(SEND_TO.debug, bytes); + instance.send(SEND_TO.debug, "RESPONSE " + type + " - " + bytes[4]); + + //logger.debug(SEND_TO.debug, "RESPONSE " + type + " - " + bytes[4], bytes); + + error = "type is: " + type; + + message = "NOK"; + } + + return { message, type, error }; + } + + + //BUILD TASKS// + function buildTasks(params) { + + //return; + console.log("buidTAaasks start ****************", params); + monitor.info("buildTasks - params", params); + + let processLine; //defined line + let init = false; + let processLineProfiles = true; + let processBroadcast = true; + let processNodes = true; + + if (params == undefined) { + init = true; + tasks = []; + logger.debug("-->buildTasks clear tasks"); + } + else { + processLineProfiles = params.processLineProfiles; + processBroadcast = false; + processNodes = false; + + processLine = params.line; + } + + let now = new Date(); + + //process line profiles + if (processLineProfiles) { + + let keys = Object.keys(relaysData); + + for (let i = 0; i < keys.length; i++) { + + let line = parseInt(keys[i]); + let profilestr = relaysData[line].profile; + + if (processLine != undefined) { + if (processLine != line) continue; + } + + try { + + /** + * we process line profiles: timepoints, astro clock, lux_sensor, offsets ... + */ + if (profilestr === "") throw ("Profile is not defined"); + let profile = JSON.parse(profilestr); + 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; + + // add name to regular profile timepoint and delete unused end_time key: + time_points.forEach(point => { + point.name = "profileTimepoint" + delete point.end_time; + }); + + //monitor.info("buildTasks: time_points", time_points); + + + /** + * 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 astro clock true, we remove all regular profile points + time_points = []; + + //TODO: when astro clock == true, is offset calculated ??? + //let duskAstroClockOffset = profile.dusk_astro_clock_offset; + //let dawnAstroClockOffset = profile.dawn_astro_clock_offset; + //console.log("line astro clock offsets dusk a dawn: ", duskAstroClockOffset, dawnAstroClockOffset); + // maybe add dusk dawn offset to calculateDuskDawn ?? what dusk dawn will be if dawn_lux_sensor == true?? + //let sunCalcResult = calculateDuskDawn(new Date(), line, duskAstroClockOffset, dawnAstroClockOffset); + + 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 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); + + 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); + + 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(':'); + + let ad = new Date(); + ad.setHours(parseInt(ahours), parseInt(aminutes), 0); + + let bd = new Date(); + bd.setHours(parseInt(bhours), parseInt(bminutes), 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++) { + + let start_time = new Date(); + let [hours, minutes] = time_points[t].start_time.split(':'); + start_time.setHours(parseInt(hours), parseInt(minutes), 0); + + //task is in 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(); + params.type = "relay"; + params.line = parseInt(line); + params.value = time_points[t].value; + params.tbname = relaysData[line].tbname; + params.timestamp = start_time.getTime(); + + // 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; + + //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)) { + 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; + + params.debug = true; + + //turn on/off line + tasks.push(params); + monitor.info("TimePoint params: ", params.info, start_time); + } + + monitor.info("-->time_points final", line, time_points); + + //ensure to turn on/off according to calculated currentValue + let params = getParams(); + params.type = "relay"; + params.line = parseInt(line); + params.tbname = relaysData[line].tbname; + params.value = currentValue; + params.timestamp = i; + params.debug = true; + + //logger.debug(now.toLocaleString("sk-SK")); + 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; + + tasks.push(params); + + } catch (error) { + if (profilestr !== "") { + //errLogger.error(profilestr, error); + console.log(`Cmd_mngr: Unable to process line profile ${line}. Error: `, error); + errorHandler.sendMessageToService(profilestr + "-" + error, 0, "js_error"); + } else { + turnLine("off", line, "No line profile. Switching it off on startup"); + } + } + + } + //logger.debug("tasks:"); + //logger.debug(tasks); + } + + + //NOTE: PROCESS DEFAULT BROADCASTS - Time of dusk, Time of dawn, Actual Time + if (processBroadcast) { + + let d = new Date(); + let time = d.getTime(); + //let sunCalcResult = calculateDuskDawn(); + + { + let params = getParams(); + + params.address = 0xffffffff;//broadcast + params.byte1 = sunCalcResult["dusk_hours"]; + params.byte2 = sunCalcResult["dusk_minutes"]; + params.recipient = 2;//2 broadcast, + params.register = 6;//Time of dusk + params.rw = 1;//write + params.type = "node-regular-write"; + params.timestamp = time + 60000; + params.addMinutesToTimestamp = 60 * 3; //kazde 3 hodiny zisti novy dusk + params.info = "Broadcast-duskTime"; + + tasks.push(params); + } + + { + let params = getParams(); + + params.address = 0xffffffff;//broadcast + params.byte1 = sunCalcResult["dawn_hours"]; + params.byte2 = sunCalcResult["dawn_minutes"]; + params.recipient = 2; //2 broadcast + params.register = 7;//Time of dawn + params.rw = 1;//write + params.type = "node-regular-write"; + params.timestamp = time + 60001; + params.addMinutesToTimestamp = 60 * 3; //kazde 3 hodiny zisti novy dawn + params.info = "Broadcast-dawnTime"; + + tasks.push(params); + } + + { + let params = getParams(); + + params.address = 0xffffffff;//broadcast + params.byte1 = d.getHours(); + params.byte2 = d.getMinutes(); + params.recipient = 2; //2 broadcast + params.register = 87;//Actual time + params.rw = 1;//write + params.type = "node-regular-write"; + params.timestamp = time + 60002; + params.addMinutesToTimestamp = 5; + params.info = "run broadcast: Actual time"; + + tasks.push(params); + } + + } + + //process nodes & tasks - read node's data + if (processNodes) { + + let time = Date.now(); + + for (let k in nodesData) { + let address = parseInt(k); + let tbname = nodesData[k].tbname; + let register = 0; + + for (let i = 0; i < listOfCommands.length; i++) { + + register = listOfCommands[i]; + let addMinutesToTimestamp = priorities[register]; + + let params = getParams(); + + params.address = address; + params.recipient = 1; + params.register = register; + params.type = register == 1 ? "node-dimming-read" : "node-regular-read"; + params.tbname = tbname; + params.timestamp = time + 5000 + i * 500 + addMinutesToTimestamp * 1000; //to make slight time difference + params.addMinutesToTimestamp = addMinutesToTimestamp; + params.info = "Node regular read command"; + + tasks.push(params); + } + + } + } + + + //niektore ulohy sa vygeneruju iba 1x pri starte!!! + if (!init) return; + + + //Master node FW version - modifies SETTINGS.masterNodeIsResponding + { + let params = getParams(); + params.type = "cmd-master"; + params.register = 4; + params.address = 0; + params.timestamp = 0; + params.addMinutesToTimestamp = 5; + params.tbname = SETTINGS.rvoTbName; + params.info = "Master node FW verzia"; + //params.debug = true; + + tasks.push(params); + } + + //kazdu hodinu skontrolovat nastavenie profilov + { + let params = getParams(); + params.type = "process_profiles"; + params.timestamp = Date.now() + 60001; + params.addMinutesToTimestamp = 60;//60 = every hour + params.info = "detekcia nespracovaných profilov linie a nodov"; + //params.debug = true; + + tasks.push(params); + } + + monitor.info("tasks created:", tasks.length); + } + + + /** + * We process line profile, where "astro_clock": true + * example profile: + * + "dawn_lux_sensor": true, + "dusk_lux_sensor": true, + "dawn_lux_sensor_value": 5, + "dusk_lux_sensor_value": 5, + "dawn_astro_clock_offset": 0, + "dusk_astro_clock_offset": 10, + "dawn_lux_sensor_time_window": 30, + "dusk_lux_sensor_time_window": 30, + "dawn_astro_clock_time_window": 60, + "dusk_astro_clock_time_window": 60 + + * if dawn: if currentTimestamp is in timewindow "dawnTime + and - dawn_lux_sensor_time_window" and lux value >= lux_sensor_value, we switch off the line. + * if dusk: we do oposite + * + * dawn: usvit - lux je nad hranicou - vypnem + * dusk: sumrak - lux je pod hranicou - zapnem + */ + 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++) { + + let line = keys[i]; //line is turned off by default + let profilestr = relaysData[line].profile; + const contactor = relaysData[line].contactor; + + try { + + let profile = JSON.parse(profilestr); + if (Object.keys(profile).length === 0) throw ("turnOnOffLinesAccordingToLuxSensor - profile is not defined"); + + 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 (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"); + } + } + } + + //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 (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"); + } + } + } + + } + + } catch (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) { + //MASTER + if (node == 0) return; + + let nodeObj = nodesData[node]; + if (nodeObj == undefined) return; + + let nodeCurrentStatus = nodeObj.status; + const now = Date.now(); + + let data = null; + + if (nodeCurrentStatus === "OFFLINE") { + data = { status: newStatus }; + nodeDbStatusModify(node, data); + return; + } + else 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; + } + + } + + + 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 }; + } + }); + }); + } + + + //TODO: skontrolujeme tu vsetko, ci ma svietit a nesvieti, ci dostava data nedostave, proste vsetky moznosti + function dailyReportCheck() { + + let now = Date.now(); + + emptyReportToSend(); + + if (rvo_is_on) { + + for (const [key, value] of Object.entries(dailyReport)) { + + if (["name", "time", "dusk_and_dawn"].includes(key)) continue; + + if (value.initialTs) { + if (value.initialTs + 3_600_000 < now) { + addToArrayIfUnique(reportToSend["night_no_data"], key); + console.log('report nedostava ziadne data uz hodinu', key); + value.initialTs = now; + } + } + if (value.dimmingAndPowerAreZeroTime) { + if (value.dimmingAndPowerAreZeroTime + 3_600_000 < now) { + addToArrayIfUnique(reportToSend["night_dimming=0"], key); + console.log("report node dimming je 0", key); + value.dimmingAndPowerAreZeroTime = now; + } + } + + } + + } else { + + for (const [key, value] of Object.entries(dailyReport)) { + + if (["name", "time", "dusk_and_dawn"].includes(key)) continue; + + let nodeIsOnLine = dailyReport[key].line; + let contactorStatus = relaysData[nodeIsOnLine].contactor; + if (contactorStatus === 1) { + + if (value.initialTs) { + if (value.initialTs + 3_600_000 < now) { + addToArrayIfUnique(reportToSend["day_24/7_no_data"], key); + console.log('node je na 24/7 ale nedostava ziadne data uz hodinu', key); + value.initialTs = now; + } + } + if (value.nodeIsOnButShouldBeOffTime) { + if (value.nodeIsOnButShouldBeOffTime + 3_600_000 < now) { + addToArrayIfUnique(reportToSend["day_24/7_dimming>0"], key); + console.log("report nema svietit ale svieti viac ako hodinu", key); + value.nodeIsOnButShouldBeOffTime = now; + } + } + + } + + } + + } + + let report = {}; + report["name"] = SETTINGS.rvo_name; + report["time"] = new Date(); + report["report"] = reportToSend; + + writeToFile(F.path.root("report_data.log"), report, true); + instance.send(SEND_TO.dailyReport, report); + } + + + function emptyReportToSend() { + + // after dawn we empty reportToSend and start to get data for a new day + const date = new Date(); + + if (date.getHours() === sunCalcResult.dawn_hours && date.getMinutes() >= sunCalcResult.dawn_minutes - 1) { + + emptyJsObject(reportToSend); + + reportToSend["contactor"] = { off: [], on: [] }; + reportToSend["night_no_data"] = []; + reportToSend["night_dimming=0"] = []; + reportToSend["day_24/7_no_data"] = []; + reportToSend["day_24/7_dimming>0"] = []; + console.log(`je ${sunCalcResult.dawn_hours}:${sunCalcResult.dawn_minutes}, resetuje sa reportToSend: `, reportToSend); + } + } + + //NOTE: ked je initialTs stale rovnaky a zistime ze linie su vypnute (relaysData.line.contactor) - zistim, ci je node na tej linii. Vieme, ze ak je linia vypnuta je to v poriadku lebo nie je na 24/7 linii + //ak je na 24/7 linii, reportujeme, ze neprijima data + function initialReportStatus() { + + if (rvo_is_on !== previous_rvo_is_on_value) { + + const ts = Date.now(); + emptyJsObject(dailyReport); + + //NOTE: do dailyReport dame vsetky nody a pravidelne kontrolujeme ci maju data + //ked nastane sumrak/usvit a svetla maju zacat/prestat svietit, dailyReport spravime nanovo: + for (const [key, value] of Object.entries(nodesData)) { + dailyReport[value.node] = { line: value.line, initialTs: ts }; + } + + console.log("initialDailyReportstatuuus", dailyReport); + } + } + + + async function runTasks() { + + clearInterval(interval); + + let currentTimestamp = Date.now(); + + //sort tasks based on timestamp + 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) { + instance.send(SEND_TO.debug, "no tasks created"); + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + if (!rsPort.isOpen) { + instance.send(SEND_TO.debug, "!rsPort.isOpen"); + //await rsPort.open(); + //console.log("Cmd-mngr: !rsPort.isOpen"); + } + + let currentTask = tasks[0]; + + if (currentTask.debug) { + //logger.debug("--->task to process", currentTask); + } + + if (currentTask.timestamp <= currentTimestamp) { + let params = { ...tasks[0] }; + + //allow terminal commands + if (SETTINGS.maintenance_mode && params.type !== "cmd-terminal") { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + let type = params.type; + let tbname = params.tbname; + let node = params.address; + let register = params.register; + let line = null; + let itIsNodeCommand; + + if (nodesData[node] !== undefined) { + line = nodesData[node].line; + itIsNodeCommand = true; + } + + if (params.line !== undefined) line = params.line; + + if (params.addMinutesToTimestamp > 0 || params.timePointName) { + tasks[0].timestamp = currentTimestamp + tasks[0].addMinutesToTimestamp * 60000; + } else { + tasks.shift(); + } + + //kontrola nespracovanych profilov nodov + if (type == "process_profiles") { + //na vsetky zapnutych liniach sa spracuju nespracovane profily nodov + loadRelaysData(); + interval = setInterval(runTasks, SHORT_INTERVAL); + return; + } + + //relay + if (type == "relay") { + + const timePointName = params.timePointName; + const value = params.value; + + let date = new Date(); + date.setDate(date.getDate() + 1);//next day + + let sunCalcResult; + if (timePointName) { sunCalcResult = calculateDuskDawn(date, params.line); console.log("typee-rellay: ", sunCalcResult.dawn_time, sunCalcResult.dusk_time); } + + + if (timePointName == "dawn") { + tasks[0].timestamp = sunCalcResult.dawn_time; + } + else if (timePointName == "dusk") { + tasks[0].timestamp = sunCalcResult.dusk_time; + } + else if (timePointName == "luxOn") { + tasks[0].timestamp = sunCalcResult.dusk_time + params.dusk_lux_sensor_time_window * 60000; + } + else if (timePointName == "luxOff") { + tasks[0].timestamp = sunCalcResult.dawn_time + params.dawn_lux_sensor_time_window * 60000; + } + else if (timePointName == "profileTimepoint") { + tasks[0].timestamp = currentTimestamp + tasks[0].addMinutesToTimestamp * 60000; + } + + let info = "aplikovany bod profilu"; + let onOrOff = ""; + value == 1 ? onOrOff = "on" : onOrOff = "off"; + + turnLine(onOrOff, params.line, info); + + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + if (!SETTINGS.masterNodeIsResponding) { + //ak neodpoveda, nebudeme vykonavat ziadne commands, okrem cmd-terminal cmd-master + errorHandler.sendMessageToService("Master node is not responding"); + + let stop = true; + + if (type === "cmd-terminal" || type === "cmd-master") stop = false; + if (stop) { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + } + + let contactorStatus = 1; + if (relaysData[line] != undefined) contactorStatus = relaysData[line].contactor; + + if (line === 0 || contactorStatus === 0 || FLOW.deviceStatus.state_of_breaker[line] === "Off") { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + // TODO: -> status offline for rvo if rotary_switch_state is OFF, this is source of errors + // check if rotary_switch_state == "Off" + // state_of_braker: disconnected = true? + + if (!rsPort.isOpen) { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + //RE-CALCULATE VALUES + //set actual time for broadcast + if (register == 87 && params.recipient === 2) { + var d = new Date(); + params.byte1 = d.getHours();//h + params.byte2 = d.getMinutes();//m + } + + //SET DUSK/DAWN FOR BROADCAST + //Time of dusk + if (register == 6 && params.recipient === 2) { + + if (type != "cmd-terminal") { + params.byte1 = sunCalcResult["dusk_hours"];//h + params.byte2 = sunCalcResult["dusk_minutes"];//m + } + } + + //Time of dawn + if (register == 7 && params.recipient === 2) { + if (type != "cmd-terminal") { + params.byte1 = sunCalcResult["dawn_hours"];//h + params.byte2 = sunCalcResult["dawn_minutes"];//m + } + } + //----------------------- + + instance.send(SEND_TO.debug, "address: " + node + " register:" + register + "type: " + type); + + var startTime, endTime; + startTime = new Date(); + + let saveToTb = true; + if (!tbname) saveToTb = false; + + let resp = com_generic(node, params.recipient, params.rw, register, params.name, params.byte1, params.byte2, params.byte3, params.byte4); + let readBytes = 11; + let timeout = 4000; + + + // await keyword is important, otherwise incorrect data is returned! + await writeData(rsPort, resp, readBytes, timeout).then(function(data) { + + //sometimes happens, that status of node changes to OK, NOK even if line was turned off and should be status OFFLINE. To prevent this, we return if line contactor is 0: + if (itIsNodeCommand && line && relaysData[line].contactor !== 1) return; + + 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); + + //ak sa odpoved zacina 0 - je to v poriadku, inak je NOK + let message = result.message; // OK, NOK + let message_type = result.type; + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + console.log("detected response:", result); + logger.debug("Cmd-mngr: writeData done " + message_type + " duration: " + timeDiff + " type: " + params.debug, params, result); + } + } + + let values = {}; + + //CMD FINISHED + if (message == "OK") { + + updateNodeStatus(node, true); + + //write + if (type == "set_node_profile") { + let result = cmdCounterResolve(node); + if (result == 0) { + dbNodes.modify({ processed: true }).where("node", node).make(function(builder) { + builder.callback(function(err, response) { + + sendNotification("Cmd-mngr: process cmd", SETTINGS.rvoTbName, "dimming_profile_was_successfully_received_by_node", { node: node }, "", SEND_TO.tb, instance); + + logger.debug("--> profil úspešne odoslaný na node č. " + node); + nodesData[node].processed = true; + nodeProfileSendFail.delete(node); + }); + }); + } + } + + //parse read response + if (params.rw == 0) { + values = processResponse(register, dataBytes); //read + } + + if (itIsNodeCommand) { + values.comm_status = "OK"; + values.status = "OK"; + nodesData[node].readout = { ...nodesData[node].readout, ...values }; + + //TODO: co ak nedostavame odpovede z nodu ? Musime vyreportovat!! + //v dailyReport teda musi byt kompletny zoznam nodov a neustale kontrolovat, ci maju data, ak nie report node - neodpoveda + if (register === 1 || register === 76) { + + let now = Date.now(); + + if (rvo_is_on === true) { + + if ("nodeIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].nodeIsOnButShouldBeOffTime; + + if (values.dimming > 0 || values.power > 0) { + if ("dimmingAndPowerAreZeroTime" in dailyReport[node]) delete dailyReport[node].dimmingAndPowerAreZeroTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if (!("dimmingAndPowerAreZeroTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], dimmingAndPowerAreZeroTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } else { + + if ("dimmingAndPowerAreZeroTime" in dailyReport[node]) delete dailyReport[node].dimmingAndPowerAreZeroTime; + + if (values.dimming > 0 || values.power > 0) { + if (!("nodeIsOnButShouldBeOffTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], nodeIsOnButShouldBeOffTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if ("nodeIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].nodeIsOnButShouldBeOffTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } + } + + } + + //master node + if (node == 0) { + sendNotification("Cmd-mngr: 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; + } + + if (params.debug) { + //logger.debug("saveToTb", saveToTb, tbname, values); + } + + if (saveToTb && type != "node-regular-read") { + sendTelemetry(values, tbname); + } + else { + if (type == "cmd-terminal") { + terminalCommandResponse(params, "SUCCESS", data); + } + } + + } + else { + terminalCommandResponse(params, "ERROR", data); + handleNokResponseOnRsPort("handleNOK else block", params, itIsNodeCommand, saveToTb); + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + //logger.debug("writeData err: ", error, result, params); + logger.debug("writeData err: ", tbname, node, register, values); + } + } + + //logger.debug(error, result, params); + } + }).catch(function(reason) { + + //console.log("writeData catch exception", reason); + instance.send(SEND_TO.debug, reason); + + terminalCommandResponse(params, "FAILURE", null, reason); + handleNokResponseOnRsPort("handleNOK catch block", params, itIsNodeCommand, saveToTb); + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + logger.debug("-->WRITE FAILED: " + reason, params.debug, params); + } + } + + }); + + } + 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); + } + + + // if node does not respond to request, we repeat request 3 times: + function repeatCommand(params) { + params.repeatCounter++; + if (params.repeatCounter < 4) { + params.timestamp = 0; + params.addMinutesToTimestamp = 0; + tasks.push(params); + } + } + + function handleNokResponseOnRsPort(message, params, itIsNodeCommand, saveToTb) { + + let node = params.address; + let register = params.register; + let type = params.type; + let tbName = params.tbname; + if (!tbName) return; + + let values = {}; + + let updateStatus = updateNodeStatus(node, false); + + if (itIsNodeCommand) { + values.comm_status = "NOK"; + nodesData[node].readout.comm_status = "NOK"; + repeatCommand(params); + } + + if (updateStatus) { + values.status = "NOK"; + nodesData[node].readout.status = "NOK"; + } + + if (type === "node-regular-read") return; + + //master node + if (node == 0) { + sendNotification("Cmd-mngr: 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; + + if (register == 4) values["master_node_version"] = "NOK"; + } + + if (type == "set_node_profile") { + delete cmdCounter[node]; + logger.debug("profil nebol úspešne odoslaný na node č. ", params); + + if (!nodeProfileSendFail.has(node)) { + sendNotification("Cmd-mngr: process cmd", tbName, "configuration_of_dimming_profile_to_node_failed", { node: node }, "", SEND_TO.tb, instance); + nodeProfileSendFail.add(node); + } + } + + // console.log("------",node, register, type, itIsNodeCommand, updateStatus, saveToTb, values); + if (saveToTb) { + sendTelemetry(values, tbName); + } + + } + + + function sendNodesData() { + Object.keys(nodesData).forEach(node => { + if (nodesData[node]["status"] !== "OFFLINE") { + sendTelemetry(nodesData[node].readout, nodesData[node].tbname); + nodesData[node].readout = {}; + } + }) + } + + + /** + * 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; + } + + 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); + + //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 === "OFFLINE") { + nodeObj.node_status_before_offline === true ? number_of_ok_luminaires++ : number_of_nok_luminaires++; + } + else if (nodeObj.status == true) 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 - ts % 60000 //round to full minute + }; + + sendTelemetry(values, SETTINGS.rvoTbName, ts); + } + + + function setSunCalcResult() { + //if next day, we get new dusk and dawn. To make sure, in local timezone 2:00 means 00:00 in utc (it means next day) + if (new Date().getHours() === 2) { + console.log("robi vypocet"); + sunCalcResult = calculateDuskDawn(); + } + } + + + function setRvoPeriod() { + + const ts = Date.now(); + + previous_rvo_is_on_value = rvo_is_on; + + if (ts < sunCalcResult.dawn_time - 1_800_000) { // nodes should be on (00:00 -> 06:00 ( - pol hodina, lebo rvo vypina skor) + rvo_is_on = true; + } else if (sunCalcResult.dawn_time - 1_800_000 < ts && ts < sunCalcResult.dusk_time + 1_800_000) { // nodes should be off 06:00 -> 21:00 + rvo_is_on = false; + } else if (sunCalcResult.dusk_time + 1_800_000 < ts) { // nodes should be on 21:00 -> 00:00 + rvo_is_on = true; + } + + initialReportStatus(); + if (previous_rvo_is_on_value !== rvo_is_on) { + console.log("rvo_is: ", rvo_is_on, previous_rvo_is_on_value); + } + } + + + function handleRsPort() { + + if (rsPort) { + rsPort.removeAllListeners(); + rsPort = null; + } + + //! 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-mngr: rsPort opened success"); + + 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); + + }).catch(function(reason) { + instance.send(SEND_TO.debug, "Cmd-mngr: RPC runSyncExec - promise rejected:" + reason); + }); + }); + + rsPort.on('error', function(err) { + errorHandler.sendMessageToService([exports.title, "unable to open port", SETTINGS.serial_port, err.message], 0); + monitor.info("Cmd-mngr: Error on rsPort", err.message); + }); + + rsPort.on("close", () => { + monitor.info("Cmd-mngr: rsPort closed, reconnecting..."); + setTimeout(handleRsPort, 1000); + }); + + rsPort.open(); + } + + + instance.on("close", () => { + clearInterval(interval); + clearInterval(customTasksInterval); + clearInterval(setCorrectTime); + clearInterval(sendNodeReadout); + clearInterval(accelerometerInterval); + rsPort.close(); + }); + + instance.on("0", _ => { + main(); + }) + + + instance.on("2", _ => { + console.log("dailyReport, reportToSend, rvo_is_on", dailyReport, reportToSend, rvo_is_on, previous_rvo_is_on_value); + }) + + instance.on("1", 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(); + return; + } + else if (flowdata.data == "close") { + rsPort.close(); + return; + } + else if (flowdata.data == "clean") { + tasks = []; + return; + } + else if (flowdata.data == "buildtasks") { + //build & run + return; + } + else if (flowdata.data == "run") { + //durations = []; + + if (tasks.length == 0) { + + buildTasks(); + + if (rsPort.isOpen) { + interval = setInterval(runTasks, 100); + } + else { + instance.send(SEND_TO.debug, "port is not opened!!!"); + } + } + } + else { + //terminal data - object + //logger.debug("flowdata", flowdata.data); + + if (typeof flowdata.data === 'object') { + //logger.debug("dido", flowdata.data); + if (flowdata.data.hasOwnProperty("sender")) { + //data from dido_controller + if (flowdata.data.sender == "dido_controller") { + + if (flowdata.data.hasOwnProperty("cmd")) { + let cmd = flowdata.data.cmd; + + if (cmd == "buildTasks") { + clearInterval(interval); + + logger.debug("-->Cmd-mngr: BUILD TASKS"); + buildTasks(); + + //logger.debug("tasks:"); + //logger.debug(tasks); + + logger.debug("-->Cmd-mngr: RUN TASKS"); + interval = setInterval(runTasks, 5000); + } + else if (cmd == "reload_relays") { + loadRelaysData(flowdata.data.line); + + if (flowdata.data.dataChanged) { + if (!flowdata.data.value) { + reportOfflineNodeStatus(flowdata.data.line); + } + else { + reportOnlineNodeStatus(flowdata.data.line); + } + } + + } + else if (cmd == "rotary_switch_state") { + let value = flowdata.data.value; + + //state was changed + if (rotary_switch_state != value) { + if (value == "Off") { + //vyreportovat vsetky svietdla + reportOfflineNodeStatus(); + } + + rotary_switch_state = value; + } + } + 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) { + + // we send lux_sensor value to all nodes: + let params = getParams(PRIORITY_TYPES.node_broadcast); + + params.recipient = 2;//2 broadcast, address = 0 + params.address = 0xffffffff;//Broadcast + + let ba = longToByteArray(lux_sensor); + + params.byte3 = ba[1];//msb + params.byte4 = ba[0]; + params.timestamp = PRIORITY_TYPES.node_broadcast; + params.info = "run broadcast: Actual Lux level from cabinet"; + params.register = 95;//Actual Lux level from cabinet + params.rw = 1;//write + + tasks.push(params); + + //process profiles + turnOnOffLinesAccordingToLuxSensor(lux_sensor); + } + } + else if (cmd == "state_of_breaker") { + //istic linie + + breakerCounter--; + + let value = flowdata.data.value; + let line = parseInt(flowdata.data.line); + + let dataChanged = false; + if (state_of_breaker[line] != value) dataChanged = true; + + state_of_breaker[line] = value; + + let status = "OK"; + if (value == "Off") status = "NOK"; + + if (dataChanged) { + + if (relaysData.hasOwnProperty(line)) { + let tbname = relaysData[line].tbname; + + if (value == "Off") { + sendNotification("Cmd-mngr: onData", tbname, "circuit_breaker_was_turned_off_line", { line: line }, "", SEND_TO.tb, instance, "circuit_breaker"); + if (breakerCounter < 0) reportToSend["contactor"]["off"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + else { + sendNotification("Cmd-mngr: onData", tbname, "circuit_breaker_was_turned_on_line", { line: line }, "", SEND_TO.tb, instance, "circuit_breaker"); + if (breakerCounter < 0) reportToSend["contactor"]["on"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + + //report status liniu + sendTelemetry({ status: status }, tbname) + + //current value + if (value == "Off") reportOfflineNodeStatus(line); //vyreportovat vsetky svietidla na linii + } + + } + } + else { + logger.debug("undefined cmd", cmd); + } + } + } + + return; + } + + //data from worksys + if (flowdata.data.hasOwnProperty("topic")) { + + let data = getNested(flowdata.data, "content", "data"); + + //if we get temperature in senica from senica-prod01 + let temperature = getNested(flowdata.data, "content", "senica_temperature"); + + if (temperature !== undefined) { + temperatureInSenica = temperature; + return; + } + + if (data === undefined) { + console.log("Invalid rpc command came from platform"); + return; + } + + let command = data.params.command; + let method = data.method; + let profile = data.params.payload; + if (profile == undefined) profile = ""; + let entity = data.params.entities[0]; + let entity_type = entity.entity_type; + let tbname = entity.tb_name; + + instance.send(SEND_TO.debug, flowdata.data); + 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") { + + //let command = data.params.command; + let value = data.params.payload.value; + + if (command == "dimming") { + + let nodeWasFound = false; + let keys = Object.keys(nodesData); + + //logger.debug("-----", keys); + + 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); + + value = parseInt(value); + if (value > 0) value = value + 128; + + params.type = "node-onetime-write"; + params.tbname = tbname; + params.address = node; + params.register = 1; + params.recipient = 1; + params.byte4 = value; + params.rw = 1; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'set dimming from platform'; + //params.debug = true; + + //debug(params); + logger.debug("dimming", params); + + tasks.push(params); + + 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); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 1; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read dimming (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + //pridame aj vyreportovanie - vykon + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 76; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read Input Power (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + //pridame aj vyreportovanie - prud svietidla + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 75; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read Input Current (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + //pridame aj vyreportovanie - power faktor - ucinnik + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 77; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read power factor (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + }, 4000); + + nodeWasFound = true; + break; + } + } + + if (!nodeWasFound) { + logger.debug("set dimming from platform", "unable to find tbname", tbname); + } + } + else { + instance.send(SEND_TO.debug, "undefined command " + command); + logger.debug("undefined command", command); + } + + return; + } + 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++) { + let node = keys[i]; + if (tbname == nodesData[node].tbname) { + + 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"); + + //profil úspešne prijatý pre node č. xx + sendNotification("Cmd-mngr", tbname, "dimming_profile_was_processed_for_node", { node: node }, profile, SEND_TO.tb, instance); + + nodesData[node].processed = false; + nodesData[node].profile = profile; + + processNodeProfile(node); + }); + }); + } + } + } + else { + + instance.send(SEND_TO.debug, "unknown method " + method); + logger.debug("unknown method", method); + + return; + } + } + + //nastav profil linie z platformy + 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") { + + 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++) { + let line = keys[i]; + if (tbname == relaysData[line].tbname) { + //zmazeme tasky + 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) { + + //update profile + logger.debug("worksys - update relay profile done:", profile); + instance.send(SEND_TO.debug, "worksys - update relay profile done"); + + relaysData[line].profile = profile; + + loadRelaysData(line) + logger.debug("loadRelaysData DONE for line", line); + + buildTasks({ processLineProfiles: true, line: line }); + + sendNotification("Cmd-mngr: set profile from worksys", tbname, "switching_profile_was_processed_for_line", { line: line }, profile, SEND_TO.tb, instance); + }); + }); + break; + } + } + } + else if (method == "set_command") { + let value = data.params.payload.value; + + 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; + + 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"); + reportToSend["contactor"]["off"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + else { + turnLine("on", line, "command received from platform"); + reportToSend["contactor"]["on"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + } + } + else { + instance.send(SEND_TO.debug, "undefined method " + method); + logger.debug("undefined method", method); + } + + return; + } + else { + instance.send(SEND_TO.debug, "UNKNOW entity_type " + entity_type); + logger.debug("UNKNOW entity_type", entity_type); + } + return; + } + + //terminal + if (!rsPort.isOpen) await rsPort.open(); + + let params = flowdata.data.body; + if (params == undefined) { + //logger.debug("Cmd-mngr: flowdata.data.body is undefined"); + return; + } + + params.priority = PRIORITY_TYPES.terminal; + params.type = "cmd-terminal"; + params.tbname = ""; + params.timestamp = PRIORITY_TYPES.terminal; + params.addMinutesToTimestamp = 0;// do not repeat task!!! + params.debug = true; + + let timestamp = Date.now(); + params.refFlowdataKey = timestamp; + //params.refFlowdata = flowdata; + //refFlowdata = flowdata; + + //console.log("flowdata", flowdata); + + cleanUpRefFlowdataObj(); + + refFlowdataObj[timestamp] = flowdata; + + //fix + //params.address = params.adress; + logger.debug("received from terminal", params); + logger.debug("date/time:", new Date()); + logger.debug("tasks length:", tasks.length); + + //tasks = []; + + //add to tasks + tasks.push(params); + + } + } + }) + + + //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) + } + + + /** + * 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; + + RESTBuilder.make(function(builder) { + + if (!builder) return; + + builder.method('GET'); + builder.url('http://192.168.252.2:8004/gettime?projects_id=1'); + + builder.callback(function(err, response, output) { + + 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); + } + + }); + } + + } 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); + + } else { + //console.log("Read-only", stdout); + + 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]: [ + { + "ts": date, + "values": values + } + ] + } + + tbHandler.sendToTb(dataToTb, instance); + } + + + function calculateDuskDawn(date, line, duskOffset = 0, dawnOffset = 0) { + + if (date === undefined) date = new Date(); + + 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); + } + + //if(profile.dawn_lux_sensor == false) + { + if (profile.hasOwnProperty("dawn_astro_clock_offset")) dawn_astro_clock_offset = parseInt(profile.dawn_astro_clock_offset); + } + + } + + } catch (error) { + if (profilestr != "") { + logger.debug(profilestr); + logger.debug(error); + } + } + + 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; + } + + //Dimming, CCT + else if (register == 1) { + let brightness = 0; + let dimming = byte0; + if (dimming > 128) { + //dimming = -128; + brightness = dimming - 128; + } + + //cct + //Ak Byte3 == 1: CCT = (Byte2*256)+Byte1 + let cct; + if (byte3 == 1) cct = byte2 * 256 + byte1; + else cct = bytesToInt(bytes.slice(0, 3)); + + //cct podla auditu + + values["dimming"] = brightness; + return values; + } + + // + else if (register == 4) { + values["master_node_version"] = bytes[1] + "." + bytes[2]; + //logger.debug("FW Version", register, bytes); + } + + //Napätie + else if (register == 74) { + let voltage = (bytesToInt(bytes) * 0.1).toFixed(1); + values["voltage"] = Number(voltage); + } + + //Prúd + else if (register == 75) { + let current = bytesToInt(bytes); + values["current"] = current; + } + + //výkon + else if (register == 76) { + let power = (bytesToInt(bytes) * 0.1).toFixed(2); + values["power"] = Number(power); + } + + //účinník + else if (register == 77) { + let power_factor = Math.cos(bytesToInt(bytes) * 0.1 * (Math.PI / 180)).toFixed(2); + values["power_factor"] = Number(power_factor); + } + + //frekvencia + else if (register == 78) { + let frequency = (bytesToInt(bytes) * 0.1).toFixed(2); + values["frequency"] = Number(frequency); + } + + //energia + else if (register == 79) { + let energy = bytesToInt(bytes); + values["energy"] = energy / 1000; //energia v kWh -> delit 1000 + } + + //doba života + else if (register == 80) { + let lifetime = (bytesToInt(bytes) / 60).toFixed(2); + values["lifetime"] = Number(lifetime); + } + + //nastavenie profilu + else if (register == 8) { + let time_schedule_settings = bytesToInt(bytes); + values["time_schedule_settings"] = time_schedule_settings; + } + + //naklon - nateraz sa z nodu nevycitava! kvoli problemom s accelerometrom a vracanymi hodnotami, posielame temp a x y z vo funkcii accelerometerData() + else if (register == 84) { + values["temperature"] = byte3 >= 128 ? (byte3 - 128) * (-1) : byte3; + values["inclination_x"] = byte2 >= 128 ? (byte2 - 128) * (-1) : byte2; + values["inclination_y"] = byte1 >= 128 ? (byte1 - 128) * (-1) : byte1; + values["inclination_z"] = byte0 >= 128 ? (byte0 - 128) * (-1) : byte0; + } + + //FW verzia nodu + else if (register == 89) { + //formát: "Byte3: Byte2.Byte1 (Byte0)" + values["fw_version"] = byte3 + ":" + byte2 + "." + byte1 + "(" + byte0 + ")"; + } + + else if (register == 87 || register == 6 || register == 7) { + var d = new Date(); + d.setHours(byte3, byte2, 0, 0); + let timestamp = d.getTime(); + + //aktuálny čas + if (register == 87) values["actual_time"] = timestamp; + //čas súmraku + else if (register == 6) values["dusk_time"] = timestamp; + //čas úsvitu + else if (register == 7) values["dawn_time"] = timestamp; + } + + 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; + + } + + + function getObjectByTbValue(object, tbname) { + return object[Object.keys(object).find(key => object[key].tbname === tbname)]; + } + + + function isObject(item) { + return (typeof item === "object" && !Array.isArray(item) && item !== null); + } + + + // we fake data, that should be received from accelerometer, as they are a bit unreliable. (temperature, x,y,z) + function accelerometerData() { + + if (temperatureInSenica === null) return; + + //clone nodesData and relaysData objects + let nodesData_clone = JSON.parse(JSON.stringify(nodesData)); + let relaysData_clone = JSON.parse(JSON.stringify(relaysData)); + + for (const key in relaysData_clone) { + + const lineData = relaysData_clone[key]; + const lineNumber = lineData.line; + const contactor = lineData.contactor; + + if (lineNumber === 0) continue; + + if (contactor === 1) { + + let date = Date.now(); + + Object.keys(nodesData_clone).forEach((node, index) => { + + setTimeout(function() { + + if (nodesData_clone[node].line === lineNumber) { + + // NOTE: if status of luminaire is NOK or OFFLINE, we do not send data; + let status = nodesData_clone[node].status; + if (status === "OFFLINE" || !status) return; + + let x = null; + if (naklony.hasOwnProperty(node)) x = naklony[node].naklon; + if (x === null) x = 0; + + sendTelemetry({ temperature: Math.round(temperatureInSenica + 10 + Math.floor(Math.random() * 3)), inclination_x: x, inclination_y: 0, inclination_z: 0 }, nodesData_clone[node].tbname, date); + } + + }, (index + 1) * 500); + }) + + } + } + } + + +} // end of instance.export + diff --git a/RVO39/flow/cmd_manager_orig.txt b/RVO39/flow/cmd_manager_orig.txt new file mode 100755 index 0000000..e92d48f --- /dev/null +++ b/RVO39/flow/cmd_manager_orig.txt @@ -0,0 +1,2800 @@ +exports.id = 'cmd_manager'; +exports.title = 'CMD Manager'; +exports.group = 'Worksys'; +exports.color = '#5D9CEC'; +exports.version = '0.0.3'; +exports.output = ['red', 'blue', 'yellow', 'blue', 'white']; +exports.input = 3; +exports.icon = 'cloud-upload'; + +exports.html = ` +
+
+
+
RPC - run RPC calls

+
+
+
@(User)
+
+
+
@(Password)
+
+
+
@(My edge)
+
+
+
+`; +exports.readme = `Manager for CMD calls`; + + +exports.install = function(instance) { + + 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'); + + var SunCalc = require('./helper/suncalc'); + const DataToTbHandler = require('./helper/DataToTbHandler'); + const errorHandler = require('./helper/ErrorToServiceHandler'); + const { sendNotification } = require('./helper/notification_reporter'); + const process = require('process'); + const { errLogger, logger, monitor } = require('./helper/logger'); + + //for accelerometer purposes + const { naklony } = require("../databases/accelerometer_db"); + + const dbNodes = TABLE("nodes"); + const dbRelays = TABLE("relays"); + + let GLOBALS; + let SETTINGS; + let rsPort; + let tbHandler; + + // runTasks intervals + const SHORT_INTERVAL = 30; + const LONG_INTERVAL = 300; + + //send data to following instances: + const SEND_TO = { + debug: 0, + tb: 1, + http_response: 2, + dido_controller: 3, + infoSender: 4 + } + + 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 + } + + 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 sendNodeReadout = null; // interval for sending agregate data from node + + 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["1"] = minutes; // dimming + priorities["76"] = minutes; // power + + minutes = 5; + priorities["75"] = minutes; // current + priorities["79"] = minutes; // energy + priorities["87"] = minutes; // aktualny cas + //priorities["84"] = minutes; + + minutes = 10; + priorities["74"] = minutes; // voltage + priorities["77"] = minutes; // power factor + priorities["78"] = minutes; // frequency + + minutes = 60; + priorities["0"] = minutes; // statecode + priorities["6"] = minutes; // dusk + priorities["7"] = minutes; // dawn + priorities["8"] = minutes; // profile + + minutes = 60 * 24; + priorities["89"] = minutes; // verzia fw + priorities["80"] = minutes; // lifetime + + //prikazy kt sa budu spustat na dany node - see config.js in terminal-oms.app. (1 - dimming) + let listOfCommands = [0, 1, 6, 7, 8, 74, 75, 76, 77, 78, 79, 80, 87, 89]; + + 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 sunCalcResult; + let reportDuskDawn; + + //helper container for counting resolved group of commands (commands related to set profile) + let cmdCounter = {};//key is node, value is counter + + //if sending of profile to node fails, we send notification and push node into set, so we do not send notification twice + const nodeProfileSendFail = new Set(); + + //we expect to get current temperature in Senica from senica-prod01 + let temperatureInSenica = null; + let accelerometerInterval = null; + + //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); + + let now = new Date(); + console.log("Cmd-mngr 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(); + + customTasksInterval = setInterval(function() { + reportEdgeDateTimeAndNumberOfLuminaires(); + }, 120000); + reportEdgeDateTimeAndNumberOfLuminaires(); + + setCorrectTime = setInterval(setCorrectPlcTimeOnceADay, 60000 * 60); // 1 hour + setCorrectPlcTimeOnceADay(); + + sendNodeReadout = setInterval(sendNodesData, 150000); + accelerometerInterval = setInterval(accelerometerData, 60000 * 30); //30 min + } + + + 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" + //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 + // if node regular readout does not respond, we repeat request + params.repeatCounter = 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-mngr: 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.byte4 = 96; + params.recipient = 1; + params.register = 8; + params.rw = 1;//write + params.timestamp = timestamp; + 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.byte4 = 96; + params.recipient = 1; + params.register = 8; + params.rw = 1;//write + params.timestamp = timestamp; + 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). + */ + + 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.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.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 + { + + logger.debug("processNodeProfile: Threshold lux level for DUSK/DAWN", node); + + let params = getParams(); + params.type = "set_node_profile"; + params.address = node; + params.register = 96; + params.recipient = 1; + params.rw = 1;//write + params.timestamp = timestamp; + 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(); + params.type = "set_node_profile"; + params.address = node; + params.register = 97; + params.recipient = 1; + params.rw = 1;//write + params.timestamp = timestamp; + 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.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); + + 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); + + console.log("proces profile finished *********************") + } + + + 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; + }); + } + + + 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) { + for (let k in nodesData) { + 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`); + } + } + } + + + function loadRelaysData(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 (value.contactor == 1) processAllNodeProfilesOnLine(value.line); + } + } + + + function reportOnlineNodeStatus(line) { + //Po zapnutí línie broadcastovo aktualizovať predtým čas a o 3 sek neskor - status, brightness + + logger.debug("Cmd-mngr: ----->reportOnlineNodeStatus for line", line); + + const d = new Date(); + + // broadcast actual time + let params = getParams(); + params.address = 0xffffffff;//Broadcast + params.byte1 = d.getHours(); + params.byte2 = d.getMinutes(); + params.recipient = 2;//2 broadcast, address = 0 + params.register = 87;//Actual time + params.rw = 1;//write + params.type = "node-onetime-write"; + params.timestamp = d.getTime() + 30000; + params.info = "run broadcast: Actual time"; + //params.debug = true; + + tasks.push(params); + + let sec = 3; + setTimeout(function() { + //Po zapnutí línie - spraviť hromadný refresh stavu práve zapnutých svietidiel + + let time = Date.now(); + + for (let k in nodesData) { + + //potrebujem nody k danej linii + 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].node_status_before_offline === true || nodesData[k].status === true) { + status = "OK"; + nodesData[k].time_of_last_communication = time; + } + + nodesData[k].readout.status = status; + + updateNodeStatus(k, status === "OK" ? true : false); + if (nodesData[k].hasOwnProperty("node_status_before_offline")) delete nodesData[k].node_status_before_offline; + sendTelemetry({ status: status }, tbname, time); + + //vyreportovanie dimming, current, input power pre liniu pre vsetky nody + //Prud + { + let params = getParams(); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 75;//prud + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = time + 4000; + params.info = 'read current'; + //params.debug = true; + tasks.push(params); + } + + //vykon + { + let params = getParams(); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 76;//výkon + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = time + 4100; + params.info = 'read power'; + //params.debug = true; + + tasks.push(params); + } + //dimming + { + let params = getParams(); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 1;//dimming + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = time + 4200; + params.info = 'read dimming'; + //params.debug = true; + + tasks.push(params); + } + + } + } + + }, sec * 1000); + } + + + function reportOfflineNodeStatus(line) { + + logger.info("Cmd-mngr: ------>reportOffLineNodeStatus for line ", line); + + values = {}; + values["dimming"] = 0;//brightness + values["power"] = 0;//výkon + values["current"] = 0;//prúd + values["status"] = "OFFLINE"; + + const date = Date.now(); + + Object.keys(nodesData).forEach(node => { + + //potrebujem nody k danej linii + if (line == nodesData[node].line || line == undefined) { + + let tbname = nodesData[node].tbname; + let nodeStatus = nodesData[node].status; + + //in case we have reported offline node status, we return (continue with next node) + if (nodeStatus === "OFFLINE") return; + + nodesData[node].node_status_before_offline = nodeStatus; + nodesData[node].status = "OFFLINE"; + nodesData[node].readout = {}; + + sendTelemetry({ ...values }, tbname, date); + } + }); + + } + + + function turnLine(onOrOff, line, info) { + let obj = { + line: line, + command: onOrOff, + info: info + }; + + //logger.debug("linia", line, obj); + instance.send(SEND_TO.dido_controller, obj); + } + + + 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"; + 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]) { + //CRC_ERROR + message = "NOK"; + error = "CRC_ERROR c1"; + instance.send(SEND_TO.debug, "CRC_ERROR c1"); + } + + 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") { + instance.send(SEND_TO.debug, bytes); + instance.send(SEND_TO.debug, "RESPONSE " + type + " - " + bytes[4]); + + //logger.debug(SEND_TO.debug, "RESPONSE " + type + " - " + bytes[4], bytes); + + error = "type is: " + type; + + message = "NOK"; + } + + return { message, type, error }; + } + + + //BUILD TASKS// + function buildTasks(params) { + + //return; + console.log("buidTAaasks start ****************", params); + monitor.info("buildTasks - params", params); + + let processLine; //defined line + let init = false; + let processLineProfiles = true; + let processBroadcast = true; + let processNodes = true; + + if (params == undefined) { + init = true; + tasks = []; + logger.debug("-->buildTasks clear tasks"); + } + else { + processLineProfiles = false; + processBroadcast = false; + processNodes = false; + + processLineProfiles = params.processLineProfiles; + processLine = params.line; + } + + let now = new Date(); + + //process line profiles + if (processLineProfiles) { + + let keys = Object.keys(relaysData); + + for (let i = 0; i < keys.length; i++) { + + let line = parseInt(keys[i]); + let profilestr = relaysData[line].profile; + + if (processLine != undefined) { + if (processLine != line) continue; + } + + try { + + /** + * we process line profiles: timepoints, astro clock, lux_sensor, offsets ... + */ + if (profilestr === "") throw ("Profile is not defined"); + let profile = JSON.parse(profilestr); + 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; + + // add name to regular profile timepoint and delete unused end_time key: + time_points.forEach(point => { + point.name = "profileTimepoint" + delete point.end_time; + }); + + //monitor.info("buildTasks: time_points", time_points); + + + /** + * 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 astro clock true, we remove all regular profile points + time_points = []; + + 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 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); + + 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); + + 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(':'); + + let ad = new Date(); + ad.setHours(parseInt(ahours), parseInt(aminutes), 0); + + let bd = new Date(); + bd.setHours(parseInt(bhours), parseInt(bminutes), 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++) { + + let start_time = new Date(); + let [hours, minutes] = time_points[t].start_time.split(':'); + start_time.setHours(parseInt(hours), parseInt(minutes), 0); + + //task is in 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(); + params.type = "relay"; + params.line = parseInt(line); + params.value = time_points[t].value; + params.tbname = relaysData[line].tbname; + params.timestamp = start_time.getTime(); + + // 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; + + //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)) { + 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; + + params.debug = true; + + //turn on/off line + tasks.push(params); + monitor.info("TimePoint params: ", params.info, start_time); + } + + monitor.info("-->time_points final", line, time_points); + + //ensure to turn on/off according to calculated currentValue + let params = getParams(); + params.type = "relay"; + params.line = parseInt(line); + params.tbname = relaysData[line].tbname; + params.value = currentValue; + params.timestamp = i; + params.debug = true; + + //logger.debug(now.toLocaleString("sk-SK")); + 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; + + tasks.push(params); + + } catch (error) { + if (profilestr !== "") { + //errLogger.error(profilestr, error); + console.log(`Cmd_mngr: Unable to process line profile ${line}. Error: `, error); + errorHandler.sendMessageToService(profilestr + "-" + error, 0, "js_error"); + } else { + turnLine("off", line, "No line profile. Switching it off on startup"); + } + } + + } + //logger.debug("tasks:"); + //logger.debug(tasks); + } + + + //NOTE: PROCESS DEFAULT BROADCASTS - Time of dusk, Time of dawn, Actual Time + if (processBroadcast) { + + let d = new Date(); + let time = d.getTime(); + let sunCalcResult = calculateDuskDawn(); + + { + let params = getParams(); + + params.address = 0xffffffff;//broadcast + params.byte1 = sunCalcResult["dusk_hours"]; + params.byte2 = sunCalcResult["dusk_minutes"]; + params.recipient = 2;//2 broadcast, + params.register = 6;//Time of dusk + params.rw = 1;//write + params.type = "node-regular-write"; + params.timestamp = time + 60000; + params.addMinutesToTimestamp = 60 * 3; //kazde 3 hodiny zisti novy dusk + params.info = "Broadcast-duskTime"; + + tasks.push(params); + } + + { + let params = getParams(); + + params.address = 0xffffffff;//broadcast + params.byte1 = sunCalcResult["dawn_hours"]; + params.byte2 = sunCalcResult["dawn_minutes"]; + params.recipient = 2; //2 broadcast + params.register = 7;//Time of dawn + params.rw = 1;//write + params.type = "node-regular-write"; + params.timestamp = time + 60001; + params.addMinutesToTimestamp = 60 * 3; //kazde 3 hodiny zisti novy dawn + params.info = "Broadcast-dawnTime"; + + tasks.push(params); + } + + { + let params = getParams(); + + params.address = 0xffffffff;//broadcast + params.byte1 = d.getHours(); + params.byte2 = d.getMinutes(); + params.recipient = 2; //2 broadcast + params.register = 87;//Actual time + params.rw = 1;//write + params.type = "node-regular-write"; + params.timestamp = time + 60002; + params.addMinutesToTimestamp = 5; + params.info = "run broadcast: Actual time"; + + tasks.push(params); + } + + } + + //process nodes & tasks - read node's data + if (processNodes) { + + let time = Date.now(); + + for (let k in nodesData) { + let address = parseInt(k); + let tbname = nodesData[k].tbname; + let register = 0; + + for (let i = 0; i < listOfCommands.length; i++) { + + register = listOfCommands[i]; + let addMinutesToTimestamp = priorities[register]; + + let params = getParams(); + + params.address = address; + params.recipient = 1; + params.register = register; + params.type = register == 1 ? "node-dimming-read" : "node-regular-read"; + params.tbname = tbname; + params.timestamp = time + 5000 + i * 500 + addMinutesToTimestamp * 1000; //to make slight time difference + params.addMinutesToTimestamp = addMinutesToTimestamp; + params.info = "Node regular read command"; + + tasks.push(params); + } + + } + } + + + //niektore ulohy sa vygeneruju iba 1x pri starte!!! + if (!init) return; + + + //Master node FW version - modifies SETTINGS.masterNodeIsResponding + { + let params = getParams(); + params.type = "cmd-master"; + params.register = 4; + params.address = 0; + params.timestamp = 0; + params.addMinutesToTimestamp = 5; + params.tbname = SETTINGS.rvoTbName; + params.info = "Master node FW verzia"; + //params.debug = true; + + tasks.push(params); + } + + //kazdu hodinu skontrolovat nastavenie profilov + { + let params = getParams(); + params.type = "process_profiles"; + params.timestamp = Date.now() + 60001; + params.addMinutesToTimestamp = 60;//60 = every hour + params.info = "detekcia nespracovaných profilov linie a nodov"; + //params.debug = true; + + tasks.push(params); + } + + monitor.info("tasks created:", tasks.length); + } + + + /** + * We process line profile, where "astro_clock": true + * example profile: + * + "dawn_lux_sensor": true, + "dusk_lux_sensor": true, + "dawn_lux_sensor_value": 5, + "dusk_lux_sensor_value": 5, + "dawn_astro_clock_offset": 0, + "dusk_astro_clock_offset": 10, + "dawn_lux_sensor_time_window": 30, + "dusk_lux_sensor_time_window": 30, + "dawn_astro_clock_time_window": 60, + "dusk_astro_clock_time_window": 60 + + * if dawn: if currentTimestamp is in timewindow "dawnTime + and - dawn_lux_sensor_time_window" and lux value >= lux_sensor_value, we switch off the line. + * if dusk: we do oposite + * + * dawn: usvit - lux je nad hranicou - vypnem + * dusk: sumrak - lux je pod hranicou - zapnem + */ + 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++) { + + let line = keys[i]; //line is turned off by default + let profilestr = relaysData[line].profile; + const contactor = relaysData[line].contactor; + + try { + + let profile = JSON.parse(profilestr); + if (Object.keys(profile).length === 0) throw ("turnOnOffLinesAccordingToLuxSensor - profile is not defined"); + + 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 (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"); + } + } + } + + //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 (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"); + } + } + } + + } + + } catch (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) { + //MASTER + if (node == 0) return; + + let nodeObj = nodesData[node]; + if (nodeObj == undefined) return; + + let nodeCurrentStatus = nodeObj.status; + const now = Date.now(); + + let data = null; + + if (nodeCurrentStatus === "OFFLINE") { + data = { status: newStatus }; + nodeDbStatusModify(node, data); + return; + } + else 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; + } + + } + + + 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 }; + } + }); + }); + } + + + async function runTasks() { + + clearInterval(interval); + + let currentTimestamp = Date.now(); + + //report dusk, dawn--------------------------------- + if (reportDuskDawn.dusk_time < currentTimestamp) { + //vyreportuj iba ak nie je velky rozdiel napr. 60 sekund + if ((currentTimestamp - reportDuskDawn.dusk_time) < 60 * 1000) { + //reportovali sme? + if (reportDuskDawn.dusk_time_reported != sunCalcResult.dusk_time) { + //sendNotification("Cmd-mngr: calculated Time of dusk", SETTINGS.rvoTbName, "dusk_has_occured", { value: sunCalcResult["dusk"] }, "", SEND_TO.tb, instance); + reportDuskDawn.dusk_time_reported = sunCalcResult.dusk_time; + } + } + + var nextDay = new Date(); + nextDay.setDate(nextDay.getDate() + 1); + + sunCalcResult = calculateDuskDawn(nextDay); + reportDuskDawn.dusk_time = sunCalcResult.dusk_time; + } + + if (reportDuskDawn.dawn_time < currentTimestamp) { + //vyreportuj iba ak nie je velky rozdiel napr. 60 sekund + if ((currentTimestamp - reportDuskDawn.dawn_time) < 60 * 1000) { + //reportovali sme? + if (reportDuskDawn.dawn_time_reported != sunCalcResult.dawn_time) { + //sendNotification(": calculated Time of dawn", SETTINGS.rvoTbName, "dawn_has_occured", { value: sunCalcResult["dawn"] }, "", SEND_TO.tb, instance); + reportDuskDawn.dawn_time_reported = sunCalcResult.dawn_time; + } + } + + var nextDay = new Date(); + nextDay.setDate(nextDay.getDate() + 1); + + sunCalcResult = calculateDuskDawn(nextDay); + reportDuskDawn.dawn_time = sunCalcResult.dawn_time; + + } + //-------------------------------------------------------- + + //sort tasks based on timestamp + 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) { + instance.send(SEND_TO.debug, "no tasks created"); + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + if (!rsPort.isOpen) { + instance.send(SEND_TO.debug, "!rsPort.isOpen"); + //await rsPort.open(); + //console.log("Cmd-mngr: !rsPort.isOpen"); + } + + let currentTask = tasks[0]; + + if (currentTask.debug) { + //logger.debug("--->task to process", currentTask); + } + + if (currentTask.timestamp <= currentTimestamp) { + let params = { ...tasks[0] }; + + //allow terminal commands + if (SETTINGS.maintenance_mode && params.type !== "cmd-terminal") { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + let type = params.type; + let tbname = params.tbname; + let node = params.address; + let register = params.register; + let line = null; + let itIsNodeCommand; + + if (nodesData[node] !== undefined) { + line = nodesData[node].line; + itIsNodeCommand = true; + } + + if (params.line !== undefined) line = params.line; + + if (params.addMinutesToTimestamp > 0 || params.timePointName) { + tasks[0].timestamp = currentTimestamp + tasks[0].addMinutesToTimestamp * 60000; + } else { + tasks.shift(); + } + + //kontrola nespracovanych profilov nodov + if (type == "process_profiles") { + //na vsetky zapnutych liniach sa spracuju nespracovane profily nodov + loadRelaysData(); + interval = setInterval(runTasks, SHORT_INTERVAL); + return; + } + + //relay + if (type == "relay") { + + const timePointName = params.timePointName; + const value = params.value; + + let date = new Date(); + date.setDate(date.getDate() + 1);//next day + + let sunCalcResult; + if (timePointName) sunCalcResult = calculateDuskDawn(date, params.line); + + if (timePointName == "dawn") { + tasks[0].timestamp = sunCalcResult.dawn_time; + } + else if (timePointName == "dusk") { + tasks[0].timestamp = sunCalcResult.dusk_time; + } + else if (timePointName == "luxOn") { + tasks[0].timestamp = sunCalcResult.dusk_time + params.dusk_lux_sensor_time_window * 60000; + } + else if (timePointName == "luxOff") { + tasks[0].timestamp = sunCalcResult.dawn_time + params.dawn_lux_sensor_time_window * 60000; + } + else if (timePointName == "profileTimepoint") { + tasks[0].timestamp = currentTimestamp + tasks[0].addMinutesToTimestamp * 60000; + } + + let info = "aplikovany bod profilu"; + let onOrOff = ""; + value == 1 ? onOrOff = "on" : onOrOff = "off"; + + turnLine(onOrOff, params.line, info); + + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + if (!SETTINGS.masterNodeIsResponding) { + //ak neodpoveda, nebudeme vykonavat ziadne commands, okrem cmd-terminal cmd-master + errorHandler.sendMessageToService("Master node is not responding"); + + let stop = true; + + if (type === "cmd-terminal" || type === "cmd-master") stop = false; + if (stop) { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + } + + let contactorStatus = 1; + if (relaysData[line] != undefined) contactorStatus = relaysData[line].contactor; + + if (line === 0 || contactorStatus === 0 || FLOW.deviceStatus.state_of_breaker[line] === "Off") { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + // TODO: -> status offline for rvo if rotary_switch_state is OFF, this is source of errors + // check if rotary_switch_state == "Off" + // state_of_braker: disconnected = true? + + if (!rsPort.isOpen) { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + //RE-CALCULATE VALUES + //set actual time for broadcast + if (register == 87 && params.recipient === 2) { + var d = new Date(); + params.byte1 = d.getHours();//h + params.byte2 = d.getMinutes();//m + } + + //SET DUSK/DAWN FOR BROADCAST + //Time of dusk + if (register == 6 && params.recipient === 2) { + + if (type != "cmd-terminal") { + let sunCalcResult = calculateDuskDawn(); + params.byte1 = sunCalcResult["dusk_hours"];//h + params.byte2 = sunCalcResult["dusk_minutes"];//m + } + } + + //Time of dawn + if (register == 7 && params.recipient === 2) { + if (type != "cmd-terminal") { + let sunCalcResult = calculateDuskDawn(); + params.byte1 = sunCalcResult["dawn_hours"];//h + params.byte2 = sunCalcResult["dawn_minutes"];//m + } + } + //----------------------- + + instance.send(SEND_TO.debug, "address: " + node + " register:" + register + "type: " + type); + + var startTime, endTime; + startTime = new Date(); + + let saveToTb = true; + if (!tbname) saveToTb = false; + + let resp = com_generic(node, params.recipient, params.rw, register, params.name, params.byte1, params.byte2, params.byte3, params.byte4); + let readBytes = 11; + let timeout = 4000; + + + // await keyword is important, otherwise incorrect data is returned! + await writeData(rsPort, resp, readBytes, timeout).then(function(data) { + + //sometimes happens, that status of node changes to OK, NOK even if line was turned off and should be status OFFLINE. To prevent this, we return if line contactor is 0: + if (itIsNodeCommand && line && relaysData[line].contactor !== 1) return; + + 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); + + //ak sa odpoved zacina 0 - je to v poriadku, inak je NOK + let message = result.message; // OK, NOK + let message_type = result.type; + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + console.log("detected response:", result); + logger.debug("Cmd-mngr: writeData done " + message_type + " duration: " + timeDiff + " type: " + params.debug, params, result); + } + } + + let values = {}; + + //CMD FINISHED + if (message == "OK") { + + updateNodeStatus(node, true); + + //write + if (type == "set_node_profile") { + let result = cmdCounterResolve(node); + if (result == 0) { + dbNodes.modify({ processed: true }).where("node", node).make(function(builder) { + builder.callback(function(err, response) { + + sendNotification("Cmd-mngr: process cmd", SETTINGS.rvoTbName, "dimming_profile_was_successfully_received_by_node", { node: node }, "", SEND_TO.tb, instance); + + logger.debug("--> profil úspešne odoslaný na node č. " + node); + nodesData[node].processed = true; + nodeProfileSendFail.delete(node); + }); + }); + } + } + + //parse read response + if (params.rw == 0) { + values = processResponse(register, dataBytes); //read + } + + if (itIsNodeCommand) { + values.comm_status = "OK"; + values.status = "OK"; + nodesData[node].readout = { ...nodesData[node].readout, ...values }; + } + + //master node + if (node == 0) { + sendNotification("Cmd-mngr: 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; + } + + if (params.debug) { + //logger.debug("saveToTb", saveToTb, tbname, values); + } + + if (saveToTb && type != "node-regular-read") { + sendTelemetry(values, tbname); + } + else { + if (type == "cmd-terminal") { + terminalCommandResponse(params, "SUCCESS", data); + } + } + + } + else { + terminalCommandResponse(params, "ERROR", data); + handleNokResponseOnRsPort("handleNOK else block", params, itIsNodeCommand, saveToTb); + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + //logger.debug("writeData err: ", error, result, params); + logger.debug("writeData err: ", tbname, node, register, values); + } + } + + //logger.debug(error, result, params); + } + }).catch(function(reason) { + + //console.log("writeData catch exception", reason); + instance.send(SEND_TO.debug, reason); + + terminalCommandResponse(params, "FAILURE", null, reason); + handleNokResponseOnRsPort("handleNOK catch block", params, itIsNodeCommand, saveToTb); + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + logger.debug("-->WRITE FAILED: " + reason, params.debug, params); + } + } + + }); + + } + 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); + } + + + // if node does not respond to request, we repeat request 3 times: + function repeatCommand(params) { + params.repeatCounter++; + if (params.repeatCounter < 4) { + params.timestamp = 0; + params.addMinutesToTimestamp = 0; + tasks.push(params); + } + } + + function handleNokResponseOnRsPort(message, params, itIsNodeCommand, saveToTb) { + + let node = params.address; + let register = params.register; + let type = params.type; + let tbName = params.tbname; + if (!tbName) return; + + let values = {}; + + let updateStatus = updateNodeStatus(node, false); + + if (itIsNodeCommand) { + values.comm_status = "NOK"; + nodesData[node].readout.comm_status = "NOK"; + repeatCommand(params); + } + + if (updateStatus) { + values.status = "NOK"; + nodesData[node].readout.status = "NOK"; + } + + if (type === "node-regular-read") return; + + //master node + if (node == 0) { + sendNotification("Cmd-mngr: 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; + + if (register == 4) values["master_node_version"] = "NOK"; + } + + if (type == "set_node_profile") { + delete cmdCounter[node]; + logger.debug("profil nebol úspešne odoslaný na node č. ", params); + + if (!nodeProfileSendFail.has(node)) { + sendNotification("Cmd-mngr: process cmd", tbName, "configuration_of_dimming_profile_to_node_failed", { node: node }, "", SEND_TO.tb, instance); + nodeProfileSendFail.add(node); + } + } + + // console.log("------",node, register, type, itIsNodeCommand, updateStatus, saveToTb, values); + if (saveToTb) { + sendTelemetry(values, tbName); + } + + } + + + function sendNodesData() { + Object.keys(nodesData).forEach(node => { + if (nodesData[node]["status"] !== "OFFLINE") { + sendTelemetry(nodesData[node].readout, nodesData[node].tbname); + nodesData[node].readout = {}; + } + }) + } + + + /** + * 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; + } + + 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); + + //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 === "OFFLINE") { + nodeObj.node_status_before_offline === true ? number_of_ok_luminaires++ : number_of_nok_luminaires++; + } + else if (nodeObj.status == true) 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 - ts % 60000 //round to full minute + }; + + sendTelemetry(values, SETTINGS.rvoTbName, ts); + } + + + function handleRsPort() { + + if (rsPort) { + rsPort.removeAllListeners(); + rsPort = null; + } + + //! 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-mngr: rsPort opened success"); + + 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); + + }).catch(function(reason) { + instance.send(SEND_TO.debug, "Cmd-mngr: RPC runSyncExec - promise rejected:" + reason); + }); + }); + + rsPort.on('error', function(err) { + errorHandler.sendMessageToService([exports.title, "unable to open port", SETTINGS.serial_port, err.message], 0); + monitor.info("Cmd-mngr: Error on rsPort", err.message); + }); + + rsPort.on("close", () => { + monitor.info("Cmd-mngr: rsPort closed, reconnecting..."); + setTimeout(handleRsPort, 1000); + }); + + rsPort.open(); + } + + + instance.on("close", () => { + clearInterval(interval); + clearInterval(customTasksInterval); + clearInterval(setCorrectTime); + clearInterval(sendNodeReadout); + clearInterval(accelerometerInterval); + rsPort.close(); + }); + + instance.on("0", _ => { + main(); + }) + + instance.on("1", 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(); + return; + } + else if (flowdata.data == "close") { + rsPort.close(); + return; + } + else if (flowdata.data == "clean") { + tasks = []; + return; + } + else if (flowdata.data == "buildtasks") { + //build & run + return; + } + else if (flowdata.data == "run") { + //durations = []; + + if (tasks.length == 0) { + + buildTasks(); + + if (rsPort.isOpen) { + interval = setInterval(runTasks, 100); + } + else { + instance.send(SEND_TO.debug, "port is not opened!!!"); + } + } + } + else { + //terminal data - object + //logger.debug("flowdata", flowdata.data); + + if (typeof flowdata.data === 'object') { + //logger.debug("dido", flowdata.data); + if (flowdata.data.hasOwnProperty("sender")) { + //data from dido_controller + if (flowdata.data.sender == "dido_controller") { + + if (flowdata.data.hasOwnProperty("cmd")) { + let cmd = flowdata.data.cmd; + + if (cmd == "buildTasks") { + clearInterval(interval); + + logger.debug("-->Cmd-mngr: BUILD TASKS"); + buildTasks(); + + //logger.debug("tasks:"); + //logger.debug(tasks); + + logger.debug("-->Cmd-mngr: RUN TASKS"); + interval = setInterval(runTasks, 5000); + } + else if (cmd == "reload_relays") { + loadRelaysData(flowdata.data.line); + + if (flowdata.data.dataChanged) { + if (!flowdata.data.value) { + reportOfflineNodeStatus(flowdata.data.line); + } + else { + reportOnlineNodeStatus(flowdata.data.line); + } + } + + } + else if (cmd == "rotary_switch_state") { + let value = flowdata.data.value; + + //state was changed + if (rotary_switch_state != value) { + if (value == "Off") { + //vyreportovat vsetky svietdla + reportOfflineNodeStatus(); + } + + rotary_switch_state = value; + } + } + 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) { + + // we send lux_sensor value to all nodes: + let params = getParams(PRIORITY_TYPES.node_broadcast); + + params.recipient = 2;//2 broadcast, address = 0 + params.address = 0xffffffff;//Broadcast + + let ba = longToByteArray(lux_sensor); + + params.byte3 = ba[1];//msb + params.byte4 = ba[0]; + params.timestamp = PRIORITY_TYPES.node_broadcast; + params.info = "run broadcast: Actual Lux level from cabinet"; + params.register = 95;//Actual Lux level from cabinet + params.rw = 1;//write + + tasks.push(params); + + //process profiles + turnOnOffLinesAccordingToLuxSensor(lux_sensor); + } + } + else if (cmd == "state_of_breaker") { + //istic linie + let value = flowdata.data.value; + let line = parseInt(flowdata.data.line); + + let dataChanged = false; + if (state_of_breaker[line] != value) dataChanged = true; + + state_of_breaker[line] = value; + + let status = "OK"; + if (value == "Off") status = "NOK"; + + if (dataChanged) { + + if (relaysData.hasOwnProperty(line)) { + let tbname = relaysData[line].tbname; + + if (value == "Off") sendNotification("Cmd-mngr: onData", tbname, "circuit_breaker_was_turned_off_line", { line: line }, "", SEND_TO.tb, instance, "circuit_breaker"); + else sendNotification("Cmd-mngr: onData", tbname, "circuit_breaker_was_turned_on_line", { line: line }, "", SEND_TO.tb, instance, "circuit_breaker"); + + //report status liniu + sendTelemetry({ status: status }, tbname) + + //current value + if (value == "Off") reportOfflineNodeStatus(line); //vyreportovat vsetky svietidla na linii + } + + } + } + else { + logger.debug("undefined cmd", cmd); + } + } + } + + return; + } + + //data from worksys + if (flowdata.data.hasOwnProperty("topic")) { + + let data = getNested(flowdata.data, "content", "data"); + + //if we get temperature in senica from senica-prod01 + let temperature = getNested(flowdata.data, "content", "senica_temperature"); + + if (temperature !== undefined) { + temperatureInSenica = temperature; + return; + } + + if (data === undefined) { + console.log("Invalid rpc command came from platform"); + return; + } + + let command = data.params.command; + let method = data.method; + let profile = data.params.payload; + if (profile == undefined) profile = ""; + let entity = data.params.entities[0]; + let entity_type = entity.entity_type; + let tbname = entity.tb_name; + + instance.send(SEND_TO.debug, flowdata.data); + 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") { + + //let command = data.params.command; + let value = data.params.payload.value; + + if (command == "dimming") { + + let nodeWasFound = false; + let keys = Object.keys(nodesData); + + //logger.debug("-----", keys); + + 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); + + value = parseInt(value); + if (value > 0) value = value + 128; + + params.type = "node-onetime-write"; + params.tbname = tbname; + params.address = node; + params.register = 1; + params.recipient = 1; + params.byte4 = value; + params.rw = 1; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'set dimming from platform'; + //params.debug = true; + + //debug(params); + logger.debug("dimming", params); + + tasks.push(params); + + 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); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 1; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read dimming (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + //pridame aj vyreportovanie - vykon + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 76; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read Input Power (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + //pridame aj vyreportovanie - prud svietidla + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 75; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read Input Current (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + //pridame aj vyreportovanie - power faktor - ucinnik + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 77; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read power factor (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + }, 4000); + + nodeWasFound = true; + break; + } + } + + if (!nodeWasFound) { + logger.debug("set dimming from platform", "unable to find tbname", tbname); + } + } + else { + instance.send(SEND_TO.debug, "undefined command " + command); + logger.debug("undefined command", command); + } + + return; + } + 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++) { + let node = keys[i]; + if (tbname == nodesData[node].tbname) { + + 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"); + + //profil úspešne prijatý pre node č. xx + sendNotification("Cmd-mngr", tbname, "dimming_profile_was_processed_for_node", { node: node }, profile, SEND_TO.tb, instance); + + nodesData[node].processed = false; + nodesData[node].profile = profile; + + processNodeProfile(node); + }); + }); + } + } + } + else { + + instance.send(SEND_TO.debug, "unknown method " + method); + logger.debug("unknown method", method); + + return; + } + } + + //nastav profil linie z platformy + 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") { + + 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++) { + let line = keys[i]; + if (tbname == relaysData[line].tbname) { + //zmazeme tasky + 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) { + + //update profile + logger.debug("worksys - update relay profile done:", profile); + instance.send(SEND_TO.debug, "worksys - update relay profile done"); + + relaysData[line].profile = profile; + + loadRelaysData(line) + logger.debug("loadRelaysData DONE for line", line); + + buildTasks({ processLineProfiles: true, line: line }); + + sendNotification("Cmd-mngr: set profile from worksys", tbname, "switching_profile_was_processed_for_line", { line: line }, profile, SEND_TO.tb, instance); + }); + }); + break; + } + } + } + else if (method == "set_command") { + let value = data.params.payload.value; + + 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; + + 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"); + } + } + else { + instance.send(SEND_TO.debug, "undefined method " + method); + logger.debug("undefined method", method); + } + + return; + } + else { + instance.send(SEND_TO.debug, "UNKNOW entity_type " + entity_type); + logger.debug("UNKNOW entity_type", entity_type); + } + return; + } + + //terminal + if (!rsPort.isOpen) await rsPort.open(); + + let params = flowdata.data.body; + if (params == undefined) { + //logger.debug("Cmd-mngr: flowdata.data.body is undefined"); + return; + } + + params.priority = PRIORITY_TYPES.terminal; + params.type = "cmd-terminal"; + params.tbname = ""; + params.timestamp = PRIORITY_TYPES.terminal; + params.addMinutesToTimestamp = 0;// do not repeat task!!! + params.debug = true; + + let timestamp = Date.now(); + params.refFlowdataKey = timestamp; + //params.refFlowdata = flowdata; + //refFlowdata = flowdata; + + //console.log("flowdata", flowdata); + + cleanUpRefFlowdataObj(); + + refFlowdataObj[timestamp] = flowdata; + + //fix + //params.address = params.adress; + logger.debug("received from terminal", params); + logger.debug("date/time:", new Date()); + logger.debug("tasks length:", tasks.length); + + //tasks = []; + + //add to tasks + tasks.push(params); + + } + } + }) + + + //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) + } + + + /** + * 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; + + RESTBuilder.make(function(builder) { + + if (!builder) return; + + builder.method('GET'); + builder.url('http://192.168.252.2:8004/gettime?projects_id=1'); + + builder.callback(function(err, response, output) { + + 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); + } + + }); + } + + } 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); + + } else { + //console.log("Read-only", stdout); + + 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]: [ + { + "ts": date, + "values": values + } + ] + } + + 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); + } + + //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); + } + } + + 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; + } + + //Dimming, CCT + else if (register == 1) { + let brightness = 0; + let dimming = byte0; + if (dimming > 128) { + //dimming = -128; + brightness = dimming - 128; + } + + //cct + //Ak Byte3 == 1: CCT = (Byte2*256)+Byte1 + let cct; + if (byte3 == 1) cct = byte2 * 256 + byte1; + else cct = bytesToInt(bytes.slice(0, 3)); + + //cct podla auditu + + values["dimming"] = brightness; + return values; + } + + // + else if (register == 4) { + values["master_node_version"] = bytes[1] + "." + bytes[2]; + //logger.debug("FW Version", register, bytes); + } + + //Napätie + else if (register == 74) { + let voltage = (bytesToInt(bytes) * 0.1).toFixed(1); + values["voltage"] = Number(voltage); + } + + //Prúd + else if (register == 75) { + let current = bytesToInt(bytes); + values["current"] = current; + } + + //výkon + else if (register == 76) { + let power = (bytesToInt(bytes) * 0.1).toFixed(2); + values["power"] = Number(power); + } + + //účinník + else if (register == 77) { + let power_factor = Math.cos(bytesToInt(bytes) * 0.1 * (Math.PI / 180)).toFixed(2); + values["power_factor"] = Number(power_factor); + } + + //frekvencia + else if (register == 78) { + let frequency = (bytesToInt(bytes) * 0.1).toFixed(2); + values["frequency"] = Number(frequency); + } + + //energia + else if (register == 79) { + let energy = bytesToInt(bytes); + values["energy"] = energy / 1000; //energia v kWh -> delit 1000 + } + + //doba života + else if (register == 80) { + let lifetime = (bytesToInt(bytes) / 60).toFixed(2); + values["lifetime"] = Number(lifetime); + } + + //nastavenie profilu + else if (register == 8) { + let time_schedule_settings = bytesToInt(bytes); + values["time_schedule_settings"] = time_schedule_settings; + } + + //naklon - nateraz sa z nodu nevycitava! kvoli problemom s accelerometrom a vracanymi hodnotami, posielame temp a x y z vo funkcii accelerometerData() + else if (register == 84) { + values["temperature"] = byte3 >= 128 ? (byte3 - 128) * (-1) : byte3; + values["inclination_x"] = byte2 >= 128 ? (byte2 - 128) * (-1) : byte2; + values["inclination_y"] = byte1 >= 128 ? (byte1 - 128) * (-1) : byte1; + values["inclination_z"] = byte0 >= 128 ? (byte0 - 128) * (-1) : byte0; + } + + //FW verzia nodu + else if (register == 89) { + //formát: "Byte3: Byte2.Byte1 (Byte0)" + values["fw_version"] = byte3 + ":" + byte2 + "." + byte1 + "(" + byte0 + ")"; + } + + else if (register == 87 || register == 6 || register == 7) { + var d = new Date(); + d.setHours(byte3, byte2, 0, 0); + let timestamp = d.getTime(); + + //aktuálny čas + if (register == 87) values["actual_time"] = timestamp; + //čas súmraku + else if (register == 6) values["dusk_time"] = timestamp; + //čas úsvitu + else if (register == 7) values["dawn_time"] = timestamp; + } + + 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; + + } + + function getObjectByTbValue(object, tbname) { + return object[Object.keys(object).find(key => object[key].tbname === tbname)]; + } + + function isObject(item) { + return (typeof item === "object" && !Array.isArray(item) && item !== null); + } + + + // we fake data, that should be received from accelerometer, as they are a bit unreliable. (temperature, x,y,z) + function accelerometerData() { + + if (temperatureInSenica === null) return; + + //clone nodesData and relaysData objects + let nodesData_clone = JSON.parse(JSON.stringify(nodesData)); + let relaysData_clone = JSON.parse(JSON.stringify(relaysData)); + + for (const key in relaysData_clone) { + + const lineData = relaysData_clone[key]; + const lineNumber = lineData.line; + const contactor = lineData.contactor; + + if (lineNumber === 0) continue; + + if (contactor === 1) { + + let date = Date.now(); + + Object.keys(nodesData_clone).forEach((node, index) => { + + setTimeout(function() { + + if (nodesData_clone[node].line === lineNumber) { + + // NOTE: if status of luminaire is NOK or OFFLINE, we do not send data; + let status = nodesData_clone[node].status; + if (status === "OFFLINE" || !status) return; + + let x = null; + if (naklony.hasOwnProperty(node)) x = naklony[node].naklon; + if (x === null) x = 0; + + sendTelemetry({ temperature: Math.round(temperatureInSenica + 10 + Math.floor(Math.random() * 3)), inclination_x: x, inclination_y: 0, inclination_z: 0 }, nodesData_clone[node].tbname, date); + } + + }, (index + 1) * 500); + }) + + } + } + } + + +} // end of instance.export + diff --git a/RVO39/flow/code.js b/RVO39/flow/code.js new file mode 100755 index 0000000..63b31bf --- /dev/null +++ b/RVO39/flow/code.js @@ -0,0 +1,90 @@ +exports.id = 'code'; +exports.title = 'Code'; +exports.group = 'Common'; +exports.color = '#656D78'; +exports.input = true; +exports.output = 1; +exports.author = 'Peter Širka'; +exports.icon = 'code'; +exports.version = '1.2.0'; +exports.options = { outputs: 1, code: 'send(0, value);', keepmessage: true }; + +exports.html = `
+
+
+
@(Number of outputs)
+
@(Minimum is 1)
+
+
+
@(Code)
+
@(Keep message instance)
+
+`; + +exports.readme = `# Code + +This component executes custom JavaScript code as it is and it doesn't contain any secure scope. + +\`\`\`javascript +// value {Object} contains received data +// send(outputIndex, newValue) sends a new value +// error(value) sends an error +// instance {Object} a current component instance +// flowdata {Object} a current flowdata +// repository {Object} a current repository of flowdata +// Example: + +// send() can be execute multiple times +send(0, value); +\`\`\``; + +exports.install = function(instance) { + + var fn; + + instance.on('data', function(response) { + if (fn) { + try { + fn(response.data, instance, response, instance.options, response.repository, require); + } catch (e) { + response.data = e; + instance.throw(response); + } + } + }); + + instance.reconfigure = function() { + try { + if (instance.options.code) { + instance.status(''); + var code = 'var send = function(index, value) { if (options.keepmessage) { flowdata.data = value; instance.send2(index, flowdata); } else instance.send2(index, value);}; var error = function(err) { instance.throw(err); }; ' + instance.options.code; + fn = new Function('value', 'instance', 'flowdata', 'options', 'repository', 'require', code); + } else { + instance.status('Not configured', 'red'); + fn = null; + } + } catch (e) { + fn = null; + instance.error('Code: ' + e.message); + } + }; + + instance.on('options', instance.reconfigure); + instance.reconfigure(); +}; \ No newline at end of file diff --git a/RVO39/flow/comment.js b/RVO39/flow/comment.js new file mode 100755 index 0000000..1e0cd13 --- /dev/null +++ b/RVO39/flow/comment.js @@ -0,0 +1,11 @@ +exports.id = 'comment'; +exports.title = 'Comment'; +exports.group = 'Common'; +exports.color = '#704cff'; +exports.author = 'Martin Smola'; +exports.icon = 'comment'; +exports.traffic = false; +exports.version = '1.0.0'; +exports.readme = '# Comment'; + +exports.install = function() {}; diff --git a/RVO39/flow/count.js b/RVO39/flow/count.js new file mode 100755 index 0000000..fa92ee9 --- /dev/null +++ b/RVO39/flow/count.js @@ -0,0 +1,60 @@ +exports.id = 'count'; +exports.title = 'Count'; +exports.version = '1.0.1'; +exports.author = 'John Graves'; +exports.color = '#656D78'; +exports.icon = 'plus-square'; +exports.input = 2; +exports.output = 1; +exports.options = { increment: 1, initialvalue: 1 }; +exports.readme = `# Counter + +Counter Number of times called.`; + +exports.html = `
+
@(Initial Value)
+
@(Increment)
+

Example Video

+
`; + +exports.readme = `# Count + +This component counts the number of messages received. + +__Response:__ + +Integer value based on the initial value and increment settings. + +__Arguments:__ +- Initial Value: What number should be output on the receipt of the first message. +- Increment: What should the increment be for each following message received.`; + +exports.install = function(instance) { + + var count = 0; + var initialCall = true; + + instance.on('data', function(flowdata) { + var index = flowdata.index; + if (index) { + instance.debug('Reset Count.'); + count = instance.options.initialvalue; + initialCall = true; + } else { + // If this is the first time, set the value to 'initial value' + if(initialCall) { + initialCall = false; + count = instance.options.initialvalue; + } else + count = count+instance.options.increment; + instance.status('Count:' + count); + instance.send2(count); + } + }); + + instance.on('options', function() { + count = instance.options.initialvalue; + initialCall = true; + }); + +}; diff --git a/RVO39/flow/db_connector.js b/RVO39/flow/db_connector.js new file mode 100755 index 0000000..65ee94b --- /dev/null +++ b/RVO39/flow/db_connector.js @@ -0,0 +1,286 @@ +exports.id = 'db_connector'; +exports.title = 'DbConnector'; +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.html = `
+
+
+
DbConnector
+
+
+
`; + +exports.readme = `# read/write data to tables`; + +const instanceSendTo = { + debug: 0, + http_response: 1, +} + +const { promisifyBuilder, makeMapFromDbResult } = require('./helper/db_helper.js'); + +function extractWhereParams(params) +{ + let name = params[0]; + let operator = '='; + let value = params[1]; + + if(params.length == 3) + { + operator = params[1]; + value = params[2]; + } + + return {name: name, operator: operator, value: value}; +} + +exports.install = function(instance) { + + let refFlowdata = null;//holds reference to httprequest flowdata + + instance.on("close", () => { + + }) + + + instance.on("data", async function(flowdata) { + + let params = flowdata.data.body; + console.log("DbConnector", params); + + refFlowdata = flowdata; + + if(refFlowdata != undefined) + { + //make http response + let responseObj = {}; + responseObj["type"] = "SUCESS"; + + try{ + + let table = params.table; + let action = params.action; + + + if(params.data != undefined) + { + let className = params.data.className; + + if(className == "SqlQueryBuilder") + { + let type = params.data.type; + + console.log("SqlQueryBuilder---->", params.data); + + if(type == "SELECT") + { + let table = params.data.queryData.tables[0].table; + + const db = TABLE(table); + var builder = db.find(); + + let result = await promisifyBuilder(builder); + + let response = {}; + response["result"] = result; + response["success"] = true; + + responseObj["data"] = response; + + //console.log(responseObj); + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + } + + return; + } + } + + + console.log("db_connector---->", table, action); + + //actions: read, replace, insert, delete, update... + + if(action == "read") + { + const db = TABLE(params.table); + + //where builder.where('age', '<', 15); + //builder.where('id', 3403); + + var builder = db.find(); + + //https://docs.totaljs.com/latest/en.html#api~DatabaseBuilder~builder.where + if(params.hasOwnProperty("where")) + { + //optionalCan contain "=", "<=", "<", ">=", ">". + //Default value: '=' + + //1.["production_line", 1] + //2. ["or", ["production_line", 1], ["production_line", 2], "end"] + + if (Array.isArray(params.where)) { + + let multipleConditions = false; + + if(params.where[0] == "or") multipleConditions = true; + if (Array.isArray(params.where[0])) multipleConditions = true; + + if(multipleConditions) + { + + for(var i = 0; i < params.where.length; i++) + { + const item = params.where[i]; + + if(item === "or") builder.or(); + + if (Array.isArray(item)) + { + const { name, operator, value } = extractWhereParams(item); + builder.where(name, operator, value); + } + + if(item === "end") builder.end(); + + } + + } + else + { + const { name, operator, value } = extractWhereParams(params.where); + builder.where(name, operator, value); + } + + } + + /* + if(params.where.length >=2 ) + { + let name = params.where[0]; + let operator = '='; + let value = params.where[1]; + + if(params.where.length == 3) + { + operator = params.where[1]; + value = params.where[2]; + } + + builder.where(name, operator, value); + } + */ + } + + if(params.hasOwnProperty("between")) + { + builder.between(params.between[0], params.between[1], params.between[2]); + } + + let response = await promisifyBuilder(builder); + responseObj["data"] = response; + + //console.log(responseObj); + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + + return; + } + + if(action == "delete") + { + + } + + + if(action == "update") + { + //! data receiving from terminal (params) + // { + // hostname: 'localhost', + // table: 'settings', + // action: 'update', + // body: { + // rvo_name: 'terrrr', + // lang: 'en', + // temperature_adress: '28.427B45920702', + // latitude: 48.70826502, + // longitude: 17.28455203, + // mqtt_host: '192.168.252.4', + // mqtt_clientid: 'showroom_test_panel_led', + // mqtt_username: 'xmRd6RJxW53WZe4vMFLU', + // mqtt_port: 1883, + // maintanace_mode: false + // } + // } + const tableToModify = TABLE(params.table); + const newValues = params.body; + + tableToModify.modify(newValues).make(function(builder) { + + builder.callback(function(err, response) { + + if(!err) + { + responseObj["data"] = response; + responseObj["tableUpdated"] = true; + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + } + }); + }); + + } + + if(action == "replace") + { + //truncate table + const db = TABLE(params.table); + var builder = db.remove(); + db.clean(); + + //insert data + let data = params.data; + + for(let i = 0; i < data.length; i++) + { + //console.log(data[i]); + db.insert(data[i]); + } + + console.log("insert done"); + + let responseObj = {}; + responseObj["type"] = "SUCESS"; + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + + + } + + + + } catch (error) { + //console.log(error); + responseObj["type"] = "ERROR"; + responseObj["message"] = error; + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + } + } + }) +} + + diff --git a/RVO39/flow/db_init.js b/RVO39/flow/db_init.js new file mode 100755 index 0000000..b399878 --- /dev/null +++ b/RVO39/flow/db_init.js @@ -0,0 +1,113 @@ +exports.id = 'db_init'; +exports.title = 'DB Initialization'; +exports.group = 'Worksys'; +exports.color = '#888600'; +exports.version = '1.0.2'; +exports.icon = 'sign-out'; +exports.output = 2; + +exports.readme = ` + # DB initialization +`; + +const { promisifyBuilder, makeMapFromDbResult } = require('./helper/db_helper.js'); +const { initNotification } = require('./helper/notification_reporter'); +const errorHandler = require('./helper/ErrorToServiceHandler'); +const total_energy = require('../databases/total_energy'); + +const SEND_TO = { + db_init: 0, + infoSender: 1 +}; + + +exports.install = async function(instance) { + const dbNodes = TABLE("nodes"); + const dbRelays = TABLE("relays"); + const dbSettings = TABLE("settings"); + 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 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.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"]; + Object.keys(dbs.nodesData).forEach(node => dbs.nodesData[node].readout = {}) + + let rvo_number = responseSettings[0]["rvo_name"].match(/\D+(\d{1,2})_/)[1]; + + dbs.settings = { + edge_fw_version: "2025-10-08", //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"], + phases: responseSettings[0]["phases"], + cloud_topic: responseSettings[0]["cloud_topic"], + has_main_switch: responseSettings[0]["has_main_switch"], + daily_report: responseSettings[0]["daily_report"], + send_changed_node_numbers: responseSettings[0]["send_changed_node_numbers"], + rvo_number: rvo_number, + + //dynamic values + masterNodeIsResponding: true, //cmd_manager + maintenance_mode: false, + } + + + dbs.settings.energy_to_switch_lamps = total_energy[rvo_number]; + if (dbs.settings.energy_to_switch_lamps === undefined) console.log('=============== db_init.js: energy_to_switch_lamps is undefined'); + + FLOW.dbLoaded = true; + errorHandler.setProjectId(dbs.settings.project_id); + initNotification(); + + //APP START - send to data services + const toService = { + id: dbs.settings.project_id, + name: dbs.settings.rvo_name, + fw_version: dbs.settings.edge_fw_version, + startdate: new Date().toISOString().slice(0, 19).replace('T', ' '), + js_error: "", + error_message: "" + }; + + instance.send(SEND_TO.infoSender, toService); + console.log("----------------> START - message send to service", toService); + + setTimeout(() => { + console.log("DB_INIT - data loaded"); + instance.send(SEND_TO.db_init, "_") + }, 5000) + +}; + diff --git a/RVO39/flow/debug.js b/RVO39/flow/debug.js new file mode 100755 index 0000000..00cb259 --- /dev/null +++ b/RVO39/flow/debug.js @@ -0,0 +1,100 @@ +exports.id = 'debug'; +exports.title = 'Debug'; +exports.author = 'Peter Širka'; +exports.color = '#967ADC'; +exports.click = true; +exports.input = true; +exports.icon = 'bug'; +exports.version = '2.0.4'; +exports.options = { enabled: true, repository: false, type: 'data' }; +exports.readme = `# Debug + +Prints data to the debug tab.`; + +exports.html = `
+
+
+
@(Output type)
+
@(Path to the property (leave empty to show the whole data object))
+
@(A group name)
+
@(Enabled)
+
+
+
`; + +exports.install = function(instance) { + + instance.on('data', function(response) { + if (instance.options.enabled) { + + var opt = instance.options; + var rep = response.repository; + var val = response.data; + var id = response.id; + + switch (instance.options.type){ + case 'both': + var data = {}; + data.repository = rep; + data.data = val instanceof Error ? { error: val.message, stack: val.stack } : val; + instance.debug(safeparse(opt.property ? U.get(data, opt.property) : data), undefined, opt.group, id); + break; + case 'repository': + instance.debug(safeparse(opt.property ? U.get(rep, opt.property) : rep), undefined, opt.group, id); + break; + case 'data': + default: + if (val instanceof Error) + instance.debug({ error: val.message, stack: val.stack }, undefined, opt.group, id); + else + instance.debug(safeparse(opt.property ? U.get(val, opt.property) : val), undefined, opt.group, id); + break; + } + } + }); + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + instance.save(); + }); + + instance.on('options', function() { + instance.custom.status(); + }); + + instance.custom.status = function() { + instance.status(instance.options.enabled ? 'Enabled' : 'Disabled'); + }; + + instance.custom.status(); + + function safeparse(o) { + + if (o instanceof Buffer) + return o; + + if (o === undefined) + return 'undefined'; + + if (o === null) + return 'null'; + + var cache = []; + var str = JSON.stringify(o, function(key, value) { + if (typeof value === 'object' && value !== null) { + if (cache.indexOf(value) !== -1) { + try { + return JSON.parse(JSON.stringify(value)); + } catch (error) { + return; + } + } + cache.push(value); + } + return value; + }); + cache = null; + return JSON.parse(str); + } +}; diff --git a/RVO39/flow/designer.json b/RVO39/flow/designer.json new file mode 100755 index 0000000..580f5a3 --- /dev/null +++ b/RVO39/flow/designer.json @@ -0,0 +1,3102 @@ +{ + "tabs": [ + { + "name": "MAIN PUSH", + "linker": "main-push", + "id": "1612772287426", + "index": 0 + }, + { + "name": "CMD manager", + "linker": "cmd-manager", + "id": "1615551125555", + "index": 1 + }, + { + "name": "Devices", + "linker": "devices", + "id": "1611921777196", + "index": 2 + } + ], + "components": [ + { + "id": "1611951142547", + "component": "debug", + "tab": "1611921777196", + "name": "ERROR", + "x": 598, + "y": 60, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#DA4453", + "notes": "" + }, + { + "id": "1612776786008", + "component": "wsmqttpublish", + "tab": "1612772287426", + "name": "WS MQTT publish", + "x": 281.75, + "y": 174, + "connections": { + "0": [ + { + "index": "0", + "id": "1615551060773" + } + ], + "1": [ + { + "index": "0", + "id": "1618300858252" + }, + { + "index": "0", + "id": "1618558465485" + } + ], + "2": [ + { + "index": "0", + "id": "1634303685503" + } + ], + "3": [ + { + "index": "0", + "id": "1731068754606" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Connected", + "color": "green" + }, + "options": { + "username": "", + "clientid": "", + "port": "1883", + "host": "" + }, + "color": "#888600", + "notes": "" + }, + { + "id": "1612778461252", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "tb-push", + "x": 72.75, + "y": 328, + "connections": { + "0": [ + { + "index": "0", + "id": "1612783322136" + }, + { + "index": "1", + "id": "1612776786008" + }, + { + "index": "0", + "id": "1731068754606" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1612783322136", + "component": "debug", + "tab": "1612772287426", + "name": "to TB", + "x": 283.75, + "y": 324, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615551060773", + "component": "debug", + "tab": "1612772287426", + "name": "errors from MQTT Broker", + "x": 594, + "y": 57, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#DA4453", + "notes": "" + }, + { + "id": "1615563373927", + "component": "debug", + "tab": "1615551125555", + "name": "Debug", + "x": 755, + "y": 155, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#DA4453", + "notes": "" + }, + { + "id": "1615566865233", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "tb-push", + "x": 755, + "y": 248, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1615798582262", + "component": "debug", + "tab": "1615551125555", + "name": "CMD_debug", + "x": 755, + "y": 346, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615802995322", + "component": "debug", + "tab": "1611921777196", + "name": "Debug", + "x": 596.8833312988281, + "y": 566.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Disabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": false + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615809128443", + "component": "debug", + "tab": "1611921777196", + "name": "tempToTb", + "x": 595.8833312988281, + "y": 658.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615809595184", + "component": "virtualwireout", + "tab": "1611921777196", + "name": "tb-push", + "x": 597.8833312988281, + "y": 377.25, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1616165795916", + "component": "httproute", + "tab": "1615551125555", + "name": "POST /terminal", + "x": 135, + "y": 547, + "connections": { + "0": [ + { + "index": "0", + "id": "1684060205000" + }, + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Listening", + "color": "green" + }, + "options": { + "timeout": 10, + "cachepolicy": 0, + "cacheexpire": "5 minutes", + "size": 5, + "url": "/terminal", + "method": "POST", + "name": "", + "flags": [ + "id:1616165795916", + "post", + 10000 + ], + "emptyresponse": false + }, + "color": "#5D9CEC", + "notes": "### Configuration\n\n- __POST /terminal__\n- flags: \n- maximum request data length: __5 kB__\n- empty response: __false__\n- cache policy: __no cache__\n- cache expire: __5 minutes__", + "cloning": false + }, + { + "id": "1616165824813", + "component": "httpresponse", + "tab": "1615551125555", + "name": "HTTP Response", + "x": 753, + "y": 423, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "json" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1617104731852", + "component": "debug", + "tab": "1615551125555", + "name": "DIDO_Debug", + "x": 669, + "y": 1040, + "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": "turnOff line", + "x": 133, + "y": 1161, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "object", + "data": "{line: 3, command: \"turnOff\", force: true}" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1617115013095", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "tb-push", + "x": 669, + "y": 1150, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1617284749681", + "component": "trigger", + "tab": "1615551125555", + "name": "update profile / node", + "x": 112, + "y": 208, + "connections": { + "0": [ + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "data": "profile_nodes", + "datatype": "string" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1618235171399", + "component": "trigger", + "tab": "1615551125555", + "name": "tun tasks", + "x": 184, + "y": 279, + "connections": { + "0": [ + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "data": "run" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1618300858252", + "component": "debug", + "tab": "1612772287426", + "name": "wsmqtt-exit1", + "x": 597.8833312988281, + "y": 149, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1618393583970", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "to-cmd-manager", + "x": 668.8833312988281, + "y": 1269, + "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": 132.88333129882812, + "y": 367, + "connections": { + "0": [ + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "platform-rpc-call", + "color": "gray" + }, + "options": { + "wirename": "platform-rpc-call" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1618393759854", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "cmd_to_dido", + "x": 119.88333129882812, + "y": 1007, + "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": 752.8833312988281, + "y": 527, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "cmd_to_dido", + "color": "gray" + }, + "options": { + "wirename": "cmd_to_dido" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1618558465485", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "platform-rpc-call", + "x": 597.8833312988281, + "y": 247, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "platform-rpc-call", + "color": "gray" + }, + "options": { + "wirename": "platform-rpc-call" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1618572059773", + "component": "trigger", + "tab": "1615551125555", + "name": "turnOn line", + "x": 132, + "y": 1085, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "data": "{line: 1, command: \"turnOn\", force: true}", + "datatype": "object" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1619515097737", + "component": "cmd_manager", + "tab": "1615551125555", + "name": "CMD Manager", + "x": 452.1091003417969, + "y": 341.05455017089844, + "connections": { + "0": [ + { + "index": "0", + "id": "1615563373927" + } + ], + "1": [ + { + "index": "0", + "id": "1615566865233" + }, + { + "index": "0", + "id": "1615798582262" + } + ], + "2": [ + { + "index": "0", + "id": "1616165824813" + } + ], + "3": [ + { + "index": "0", + "id": "1618393827655" + } + ], + "4": [ + { + "index": "0", + "id": "1635936391935" + } + ], + "5": [ + { + "index": "0", + "id": "1757006030239" + }, + { + "index": "0", + "id": "1757006060377" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1619605019281", + "component": "httproute", + "tab": "1615551125555", + "name": "GET db", + "x": 173, + "y": 653, + "connections": { + "0": [ + { + "index": "0", + "id": "1684060205000" + }, + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Listening", + "color": "green" + }, + "options": { + "timeout": 5, + "cachepolicy": 0, + "cacheexpire": "5 minutes", + "size": 5, + "url": "/db", + "method": "GET", + "name": "", + "flags": [ + "id:1619605019281", + "get", + 5000 + ] + }, + "color": "#5D9CEC", + "notes": "### Configuration\n\n- __GET /db__\n- flags: undefined\n- maximum request data length: __5 kB__\n- empty response: __undefined__\n- cache policy: __no cache__\n- cache expire: __5 minutes__", + "cloning": false + }, + { + "id": "1619784672383", + "component": "trigger", + "tab": "1615551125555", + "name": "turnOnAlarm", + "x": 120, + "y": 1234, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "object", + "data": "{command: \"turnOnAlarm\"}" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1619784812964", + "component": "trigger", + "tab": "1615551125555", + "name": "turnOffAlarm", + "x": 118, + "y": 1307, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "object", + "data": "{command: \"turnOffAlarm\"}" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1621340721628", + "component": "virtualwireout", + "tab": "1611921777196", + "name": "modbus_to_dido", + "x": 599, + "y": 471, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "modbus_to_dido", + "color": "gray" + }, + "options": { + "wirename": "modbus_to_dido" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1622640022885", + "component": "httproute", + "tab": "1615551125555", + "name": "POST /db_connector", + "x": 98, + "y": 1586, + "connections": { + "0": [ + { + "index": "0", + "id": "1622640073521" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Listening", + "color": "green" + }, + "options": { + "timeout": 5, + "cachepolicy": 0, + "cacheexpire": "5 minutes", + "size": 5, + "url": "/db_connector", + "method": "POST", + "flags": [ + "id:1622640022885", + "post", + 5000 + ] + }, + "color": "#5D9CEC", + "notes": "### Configuration\n\n- __POST /db_connector__\n- flags: \n- maximum request data length: __5 kB__\n- empty response: __undefined__\n- cache policy: __no cache__\n- cache expire: __5 minutes__", + "cloning": false + }, + { + "id": "1622640073521", + "component": "db_connector", + "tab": "1615551125555", + "name": "DbConnector", + "x": 372, + "y": 1572, + "connections": { + "1": [ + { + "index": "0", + "id": "1622641420685" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "edge": "undefined" + }, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1622641420685", + "component": "httpresponse", + "tab": "1615551125555", + "name": "HTTP Response", + "x": 596, + "y": 1586, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1634303504177", + "component": "monitormemory", + "tab": "1612772287426", + "name": "RAM", + "x": 69.88333129882812, + "y": 888.5, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465281992" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "858.88 MB / 985.68 MB", + "color": "gray" + }, + "options": { + "enabled": true, + "interval": 30000 + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1634303533779", + "component": "monitordisk", + "tab": "1612772287426", + "name": "disk", + "x": 70.88333129882812, + "y": 982.5, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465821120" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "5.78 GB / 7.26 GB", + "color": "gray" + }, + "options": { + "enabled": true, + "path": "/", + "interval": 30000 + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1634303595494", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "send-to-services", + "x": 51.883331298828125, + "y": 1400.5, + "connections": { + "0": [ + { + "index": "0", + "id": "1634463186563" + }, + { + "index": "1", + "id": "1634488120710" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1634303602169", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "send-to-services", + "x": 426.8833312988281, + "y": 878.5, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1634303685503", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "send-to-services", + "x": 600.8833312988281, + "y": 341.5, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1634303743260", + "component": "httprequest", + "tab": "1612772287426", + "name": "192.168.252.2:8004/sentmessage", + "reference": "", + "x": 506.8833312988281, + "y": 1331.7333374023438, + "connections": { + "0": [ + { + "index": "0", + "id": "1635327431236" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "url": "http://192.168.252.2:8004/sentmessage", + "method": "POST", + "stringify": "json" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1634463186563", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 305.75, + "y": 1442, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634464580289", + "component": "code", + "tab": "1612772287426", + "name": "Code", + "x": 245, + "y": 787, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465243324" + }, + { + "index": "0", + "id": "1634303602169" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "keepmessage": true, + "code": "let response = {};\nresponse.cpu = value.cpu;\nresponse.uptime = value.uptime;\n\nsend(0, response);", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1634465243324", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 428, + "y": 784, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634465281992", + "component": "code", + "tab": "1612772287426", + "name": "Code", + "x": 245, + "y": 884, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465338103" + }, + { + "index": "0", + "id": "1634303602169" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "keepmessage": true, + "code": "value.sender = \"ram\";\n\nlet response = {};\n\nresponse.memory_total = Math.round(value.total / (1024 ** 2));\nresponse.memory_free = Math.round(value.free / (1024 ** 2));\nresponse.memory_used = Math.round(value.used / (1024 ** 2));\n\nsend(0, response);", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1634465338103", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 429, + "y": 976, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634465821120", + "component": "code", + "tab": "1612772287426", + "name": "Code", + "x": 245, + "y": 978, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465892500" + }, + { + "index": "0", + "id": "1634303602169" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "keepmessage": true, + "code": "value.sender = \"hdd\";\n\nlet response = {};\n\nresponse.hdd_total = Math.round(value.total / (1024 ** 2));\nresponse.hdd_free = Math.round(value.free / (1024 ** 2));\nresponse.hdd_used = Math.round(value.used / (1024 ** 2));\n\nsend(0, response);", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1634465892500", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 432, + "y": 1068, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634484067516", + "component": "debug", + "tab": "1612772287426", + "name": "Send info", + "x": 513, + "y": 1441, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634488120710", + "component": "infosender", + "tab": "1612772287426", + "name": "Info sender", + "x": 301, + "y": 1336, + "connections": { + "0": [ + { + "index": "0", + "id": "1634484067516" + }, + { + "index": "0", + "id": "1634303743260" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "edge": "undefined" + }, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1635327431236", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 837.8833312988281, + "y": 1325.5, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1635936391935", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "send-to-services", + "x": 753, + "y": 623, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1637069803394", + "component": "monitorconsumption", + "tab": "1612772287426", + "name": "CPU", + "x": 69, + "y": 791, + "connections": { + "0": [ + { + "index": "0", + "id": "1634464580289" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "49.2% / 69.91 MB", + "color": "gray" + }, + "options": { + "monitorfiles": true, + "monitorconnections": true, + "monitorsize": true, + "monitorconsumption": true, + "enabled": true, + "interval": 30000 + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1683664161036", + "component": "debug", + "tab": "1615551125555", + "name": "CMDtoDIDO", + "x": 392, + "y": 1012, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1683981346282", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "from-dido-controller", + "x": 112, + "y": 459, + "connections": { + "0": [ + { + "index": "0", + "id": "1684055037116" + }, + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "from-dido-controller", + "color": "gray" + }, + "options": { + "wirename": "from-dido-controller" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1684055037116", + "component": "debug", + "tab": "1615551125555", + "name": "from dido to cmd", + "x": 451, + "y": 532, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1684060205000", + "component": "debug", + "tab": "1615551125555", + "name": "HTTP routes", + "x": 450, + "y": 639, + "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": "MDBToDido", + "x": 598, + "y": 147, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1699963668903", + "component": "dido_controller", + "tab": "1615551125555", + "name": "DIDO_Controller", + "x": 397, + "y": 1131, + "connections": { + "0": [ + { + "index": "0", + "id": "1617104731852" + } + ], + "1": [ + { + "index": "0", + "id": "1617104731852" + }, + { + "index": "0", + "id": "1617115013095" + } + ], + "2": [ + { + "index": "0", + "id": "1618393583970" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "edge": "undefined" + }, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1699964678894", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "modbus_to_dido", + "x": 96, + "y": 924, + "connections": { + "0": [ + { + "index": "0", + "id": "1699963668903" + }, + { + "index": "0", + "id": "1699964793925" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "modbus_to_dido", + "color": "gray" + }, + "options": { + "wirename": "modbus_to_dido" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1699964793925", + "component": "debug", + "tab": "1615551125555", + "name": "modbusToDido", + "x": 388, + "y": 920, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1699965957410", + "component": "modbus_reader", + "tab": "1611921777196", + "name": "Modbus reader", + "x": 232, + "y": 175, + "connections": { + "0": [ + { + "index": "0", + "id": "1611951142547" + } + ], + "1": [ + { + "index": "0", + "id": "1621340721628" + }, + { + "index": "0", + "id": "1684179110403" + }, + { + "index": "0", + "id": "1717441414646" + } + ], + "2": [ + { + "index": "0", + "id": "1615809595184" + }, + { + "index": "0", + "id": "1714752862828" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1700411878636", + "component": "thermometer", + "tab": "1611921777196", + "name": "Thermometer", + "x": 234.75, + "y": 444, + "connections": { + "0": [ + { + "index": "0", + "id": "1615802995322" + } + ], + "1": [ + { + "index": "0", + "id": "1615809595184" + }, + { + "index": "0", + "id": "1615809128443" + } + ], + "2": [ + { + "index": "0", + "id": "1621340721628" + }, + { + "index": "0", + "id": "1732889185927" + }, + { + "index": "0", + "id": "1717441414646" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#5CB36D", + "notes": "" + }, + { + "id": "1714752862828", + "component": "debug", + "tab": "1611921777196", + "name": "MDBToTb", + "x": 766, + "y": 324, + "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": 764.0833282470703, + "y": 222, + "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\telse if(value.status === \"NOK-thermometer\")\n\t{\n\t\tsend(0, {\"thermometer\": \"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\telse if(value.values.hasOwnProperty(\"temperature\"))\n\t{\n\t\tsend(0, {\"thermometer\": \"OK\"});\n\t}\n}", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1717442627834", + "component": "debug", + "tab": "1611921777196", + "name": "modbus service", + "x": 966.0833282470703, + "y": 165, + "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": 968.0833282470703, + "y": 268, + "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": 88.75, + "y": 1685, + "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": 296, + "y": 1671, + "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\", \"Flow has been restarted\", \"Node db has changed\"]", + "types": "[\"emergency\", \"critical\", \"error\", \"alert\"]", + "name": "" + }, + "color": "#30E193", + "notes": "" + }, + { + "id": "1718016073501", + "component": "httprequest", + "tab": "1612772287426", + "name": "http://192.168.252.2:8004/slack", + "x": 495, + "y": 1753, + "connections": { + "0": [ + { + "index": "0", + "id": "1718016086212" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "url": "http://192.168.252.2:8004/slack", + "method": "POST", + "stringify": "json" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1718016086212", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 832, + "y": 1664, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "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": 87, + "y": 1591, + "connections": { + "0": [ + { + "index": "0", + "id": "1718016052341" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "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\": \"\" } } } ] }", + "datatype": "object" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1729855334955", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "platform-rpc-call", + "x": 599.9333343505859, + "y": 541.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "platform-rpc-call", + "color": "gray" + }, + "options": { + "wirename": "platform-rpc-call" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1729855371093", + "component": "debug", + "tab": "1612772287426", + "name": "rpc cloud", + "x": 601.9333343505859, + "y": 440.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1731068658334", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 75.75, + "y": 184, + "connections": { + "0": [ + { + "index": "0", + "id": "1612776786008" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731068754606", + "component": "cloudmqttconnect", + "tab": "1612772287426", + "name": "MQTT to senica-prod01", + "x": 284.75, + "y": 452, + "connections": { + "1": [ + { + "index": "0", + "id": "1729855371093" + }, + { + "index": "0", + "id": "1729855334955" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Connected", + "color": "green" + }, + "options": { + "username": "", + "clientid": "", + "port": "2764", + "host": "192.168.252.2", + "topic": "" + }, + "color": "#888600", + "notes": "" + }, + { + "id": "1731069001548", + "component": "db_init", + "tab": "1612772287426", + "name": "DB Initialization", + "x": 1003.75, + "y": 240.25, + "connections": { + "0": [ + { + "index": "0", + "id": "1731069033416" + } + ], + "1": [ + { + "index": "0", + "id": "1747561603739" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#888600", + "notes": "" + }, + { + "id": "1731069033416", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "db-init", + "x": 1244.75, + "y": 233.25, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069059135", + "component": "showdb", + "tab": "1612772287426", + "name": "Show db data", + "x": 1186.75, + "y": 821.25, + "connections": { + "0": [ + { + "index": "0", + "id": "1731069079243" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#888600", + "notes": "" + }, + { + "id": "1731069079243", + "component": "debug", + "tab": "1612772287426", + "name": "dbData", + "x": 1390.75, + "y": 870.25, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1731069116691", + "component": "trigger", + "tab": "1612772287426", + "name": "settings", + "x": 934.75, + "y": 669.75, + "connections": { + "0": [ + { + "index": "0", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069131637", + "component": "trigger", + "tab": "1612772287426", + "name": "relaysData", + "x": 876.75, + "y": 733.75, + "connections": { + "0": [ + { + "index": "1", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069137374", + "component": "trigger", + "tab": "1612772287426", + "name": "nodesData", + "x": 852.75, + "y": 794.75, + "connections": { + "0": [ + { + "index": "2", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069179846", + "component": "trigger", + "tab": "1612772287426", + "name": "pinsData", + "x": 850.75, + "y": 861.75, + "connections": { + "0": [ + { + "index": "3", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069192937", + "component": "trigger", + "tab": "1612772287426", + "name": "sample data", + "x": 857.75, + "y": 928.75, + "connections": { + "0": [ + { + "index": "4", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069264443", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 63.75, + "y": 1279, + "connections": { + "0": [ + { + "index": "0", + "id": "1634488120710" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069334626", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "db-init", + "x": 172.88333129882812, + "y": 129, + "connections": { + "0": [ + { + "index": "0", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069548145", + "component": "virtualwirein", + "tab": "1611921777196", + "name": "db-init", + "x": 46.75, + "y": 192, + "connections": { + "0": [ + { + "index": "0", + "id": "1699965957410" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069567152", + "component": "virtualwirein", + "tab": "1611921777196", + "name": "db-init", + "x": 44.75, + "y": 465, + "connections": { + "0": [ + { + "index": "0", + "id": "1700411878636" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731070156936", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "db-init", + "x": 126.88333129882812, + "y": 1377, + "connections": { + "0": [ + { + "index": "2", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731234189516", + "component": "trigger", + "tab": "1612772287426", + "name": "monitor.txt", + "x": 882.75, + "y": 991.75, + "connections": { + "0": [ + { + "index": "5", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731234189551", + "component": "trigger", + "tab": "1612772287426", + "name": "err.txt", + "x": 904.75, + "y": 1053.75, + "connections": { + "0": [ + { + "index": "6", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1732700042559", + "component": "nodesdb_change_check", + "tab": "1612772287426", + "name": "Nodes DB change check", + "x": 266.8833312988281, + "y": 1980.2333984375, + "connections": { + "0": [ + { + "index": "0", + "id": "1732700071298" + }, + { + "index": "0", + "id": "1732700642917" + } + ], + "1": [ + { + "index": "0", + "id": "1759958914348" + }, + { + "index": "0", + "id": "1759959003114" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#888600", + "notes": "" + }, + { + "id": "1732700057052", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 76.75, + "y": 1988, + "connections": { + "0": [ + { + "index": "0", + "id": "1732700042559" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1732700071298", + "component": "debug", + "tab": "1612772287426", + "name": "nodesChange", + "x": 571.8833312988281, + "y": 2018.2333984375, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1732700642917", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "tb-push", + "x": 567.8833312988281, + "y": 1933, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1732889185927", + "component": "debug", + "tab": "1611921777196", + "name": "tempToDido", + "x": 594.8833312988281, + "y": 753, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1733574412965", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 72.75, + "y": 474, + "connections": { + "0": [ + { + "index": "1", + "id": "1731068754606" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1747561603739", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "send-to-services", + "x": 1243.8833312988281, + "y": 334.5, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1747562867845", + "component": "comment", + "tab": "1612772287426", + "name": "FLOW STARTING POINT", + "x": 1003.5666656494141, + "y": 178, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#704cff", + "notes": "" + }, + { + "id": "1749211698385", + "component": "trigger", + "tab": "1612772287426", + "name": "deviceStatus", + "x": 911.75, + "y": 1116.75, + "connections": { + "0": [ + { + "index": "7", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1757006030239", + "component": "httprequest", + "tab": "1615551125555", + "name": "192.168.252.2:8015/daily_report", + "x": 756.5666656494141, + "y": 715.4499969482422, + "connections": { + "0": [ + { + "index": "0", + "id": "1757006045804" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "stringify": "json", + "method": "POST", + "url": "http://192.168.252.2:8015/daily_report" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1757006045804", + "component": "debug", + "tab": "1615551125555", + "name": "ddd", + "x": 1091.566665649414, + "y": 711.4499969482422, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1757006060377", + "component": "debug", + "tab": "1615551125555", + "name": "reportDebug", + "x": 749.5666656494141, + "y": 799.4499969482422, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1759958914348", + "component": "httprequest", + "tab": "1612772287426", + "name": "http://192.168.252.2:8015/node_numbers", + "x": 571, + "y": 2111, + "connections": { + "0": [ + { + "index": "0", + "id": "1759958927094" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "stringify": "json", + "method": "POST", + "url": "http://192.168.252.2:8015/node_numbers" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1759958927094", + "component": "debug", + "tab": "1612772287426", + "name": "nodesChangeCloud", + "x": 951.8833312988281, + "y": 2109.2333984375, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1759959003114", + "component": "debug", + "tab": "1612772287426", + "name": "nodeChangeCloud1", + "x": 574, + "y": 2218, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1760020290879", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 84.75, + "y": 1787, + "connections": { + "0": [ + { + "index": "1", + "id": "1718016052341" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + } + ], + "version": 615 +} diff --git a/RVO39/flow/dido_controller.js b/RVO39/flow/dido_controller.js new file mode 100755 index 0000000..d16fb19 --- /dev/null +++ b/RVO39/flow/dido_controller.js @@ -0,0 +1,1486 @@ +exports.id = 'dido_controller'; +exports.title = 'DIDO_Controller'; +exports.version = '2.0.0'; +exports.group = 'Worksys'; +exports.color = '#2134B0'; +exports.input = 3; +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 + +state_of_main_switch - reportovat stav hlaveho istica : 0-> off 1-> on +rotary_switch_state - sem by sa mal reportovat stav vstupov manual a auto pola nasledovnej logiky: Manual = 1 a Auto = 0 -> Manu +Manual = 0 a Auto = 0 -> Off, Manual = 0 a Auto = 1 -> Automatic + +door_condition - pin 6, dverový kontakt -> 1 -> vyreportuje Closed, 0 -> vyreportuje Ope +twilight_sensor - hodnotu, ktoru vracia ten analogovy vstup (17) treba poslat sem ako float number. Zrejme tu potom pridame nejaky koeficient prevodu na luxy + +Na kazdu liniu +state_of_breaker - podla indexu istica sa reportuje jeho stav, teda istic na liniu 1: 0-> off, 1-> on +state_of_contactor - podla indexu stkaca sa reportuje jeho stav, teda stykac 1 na liniu 1: 0-> off, 1-> on +*/ + +const { errLogger, logger, monitor } = require('./helper/logger'); +const SerialPort = require('serialport'); +const WebSocket = require('ws'); +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 errorHandler = require('./helper/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 hasMainSwitch; + +let alarmStatus = "OFF"; + +const SEND_TO = { + debug: 0, + tb: 1, + cmd_manager: 2 +} + + +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 = {}; + let rsPortReceivedData = []; + + //to be able to get proper twilight values + let twilight_sensor_interval = 5;//minutes + let twilight_sensor = []; + const twilight_sensor_array = []; + let twilightError = false; + + monitor.info("DIDO_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-we make it global to see it from outside + FLOW.deviceStatus = { //key is device name: temperature,.... + "state_of_main_switch": "Off", //Hlavny istic (alebo druhy dverovy kontakt) + "rotary_switch_state": "Off", //Prevadzkovy + "door_condition": "closed", //Dverový kontakt + "em": "OK", //elektromer rvo + "temperature": "OK", //templomer + "battery": "OK", //Bateria + "power_supply": "OK", //Zdroj + "master_node": "OK", //MN - GLOBALS.settings.masterNodeIsResponding + "no_voltage": "OK", //GLOBALS.settings.no_voltage - vypadok napatia na faze + "state_of_breaker": {}, //"Off",//Istic + "state_of_contactor": {}, //"Off",//Stykac + "twilight_sensor": "OK" //lux sensor + }; + let deviceStatus = FLOW.deviceStatus; + + + function main() { + + GLOBALS = FLOW.GLOBALS; + SETTINGS = FLOW.GLOBALS.settings; + rvoTbName = SETTINGS.rvoTbName; + pinsData = GLOBALS.pinsData; + relaysData = GLOBALS.relaysData; + + tbHandler = new DataToTbHandler(SEND_TO.tb); + tbHandler.setSender(exports.title); + + controller_type = SETTINGS.controller_type; //"lm" or "unipi" + hasMainSwitch = SETTINGS.has_main_switch; + + if (controller_type == "") controller_type = "lm"; + + 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, "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; + } + } + + //report RVO version relaysData[0].tbname; + let values = {}; + values["edge_fw_version"] = SETTINGS.edge_fw_version; + values["maintenance_mode"] = SETTINGS.maintenance_mode; + + sendTelemetry(values, rvoTbName); + + 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); + } + + + function handleRsPort() { + + if (rsPort) { + rsPort.removeAllListeners(); + rsPort = null; + } + + //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('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) { + if (!err) { + monitor.info(exports.title + "--->Digital in_out has been set (runSyncExec was sucessfull)"); + + turnAlarm("off"); + 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('error', err => { + let message = "Dido: rsPort error: " + err.message; + logger.debug(message); + monitor.info(message); + errorHandler.sendMessageToService(message); + }) + + rsPort.on("close", () => { + let message = "Dido: rsPort closed - reconnecting ..."; + logger.debug(message); + monitor.info(message); + setTimeout(handleRsPort, 1000); + }) + + rsPort.open(); + } + + + function handleWebSocket() { + + if (ws) { + ws.removeAllListeners(); + ws = null; + } + + //to keep websocket opened, we send request every 150 seconds + let startRequests = null; + + console.log("handleWebSocket function called"); + ws = new WebSocket('ws:/0.0.0.0:1234/ws'); + + ws.onopen = function open() { + + instance.send(0, exports.title + " running"); + turnAlarm("off"); + + initialSetting(); + + setTimeout(function() { ws.send(JSON.stringify({ cmd: "all" })) }, 5000); + // we request dev info about neuron device from evok to keep websocket connection alive + // for some reason this request returns no data, but connection keeps alive + startRequests = setInterval(() => { + ws.send(JSON.stringify({ "cmd": "filter", "dev": ["neuron"] })); + }, 150000) + }; + + + // 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 = async 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; + + 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 => { + logger.debug('Dido: websocket error', err); + }) + + ws.onclose = function() { + logger.debug('Dido: websocket onclose, reconnecting...') + clearInterval(startRequests); + setTimeout(handleWebSocket, 1000); + } + } + + 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 turnAlarm(onOrOff) { + let value = 0; + if (onOrOff == "on") value = 1; + + if (value == 1 && SETTINGS.maintenance_mode) return; + + alarmStatus = "OFF"; + if (value == 1) alarmStatus = "ON"; + + if (rsPort) { + let arr = [0x55]; + arr.push(13); + arr.push(0); + arr.push(value); + + rsPort.write(Buffer.from(arr), function(err) { + logger.debug(`sirena - ${onOrOff}`); + }); + } + else if (ws) { + let cmd = { "cmd": "set", "dev": "relay", "circuit": "1_01", "value": value }; + ws.send(JSON.stringify(cmd)); + logger.debug(`sirena - ${onOrOff}`); + } + } + + + 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") { + bits.push(0); + } + else bits.push(1); + + if (deviceStatus["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); + } + + + // turn line on or off + function turnLine(onOrOff, line, pin, force, info) { + //onOrOff => "on" or "off" + let value = 0; + if (onOrOff == "on") value = 1; + + if (force == undefined) force = false; + + if (line == 0) { + if (value == 1 && alarmStatus == "ON") turnAlarm("off"); + SETTINGS.maintenance_mode = value ? true : false; + + 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); + return; + } + + if (pin === undefined) pin = getPin(line); + + if (pin === undefined) { + errLogger.error("pin is undefined!", line); + return; + } + + if (!force) { + if (relaysData[line].contactor == value) { + instance.send(SEND_TO.debug, `line is already ${onOrOff} ` + line); + logger.debug(`Dido: turnLine: line is already ${onOrOff} `, line); + return; + } + } + + // if(!rsPort.isOpen && !ws) + if (!rsPort && !ws) { + errLogger.error("Dido - port or websocket is not opened"); + return; + } + + if (rsPort) { + let arr = [0x55]; + arr.push(pin); + arr.push(0); + arr.push(value); + + rsPort.write(Buffer.from(arr), function(err) { + if (err === undefined) { + monitor.info(`Dido: turnLine ${onOrOff} zapisal do rsPort-u`, line, pin, arr, info); + switchLogic(arr); + } + else { + monitor.info(`Dido: turnLine ${onOrOff} WRITE error`, err); + } + }); + + } + else if (ws) { + //pin = "relay1_03" or "input1_01" ... we must make just "1_01" with slice method + monitor.info(`Dido: turnLine ${onOrOff} - (line, pin, force)`, line, pin, force, info); + let cmd = { "cmd": "set", "dev": "relay", "circuit": pin.slice(5), "value": value }; + ws.send(JSON.stringify(cmd)); + } + + //if rvo is 24/7, it has just one switching profile point at 13:00. we do not want to send notification as it repeats every day. + //const d = new Date(); + //if(d.getHours() != 13) sendNotification("Dido_controller: ", SETTINGS.rvoTbName, "switching_profile_point_applied_to_line", { line: line, value: onOrOff }, "", SEND_TO.tb, instance); + } + + + // 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; + + // 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) { + const status = flowdata.data.status; + if (status == "NOK-twilight_sensor") { + deviceStatus["twilight_sensor"] = "NOK"; + } + else if (status == "NOK-em340" || status == "NOK-em111") { + deviceStatus["em"] = "NOK"; + } + else if (status == "NOK-thermometer") { + deviceStatus["temperature"] = "NOK"; + } + } + else if ("values" in flowdata.data) { + 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" + } + else if (values.hasOwnProperty("temperature")) { + deviceStatus["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"; + } + + sendTelemetry(values, rvoTbName); + } + + sendRvoStatus(); + }) + + + + + // we expect array as flowdata.data + instance.on("1", flowdata => { + + //console.log(flowdata.data); + + if (!flowdata.data instanceof Object) return; + + let obj = flowdata.data; + let line = obj.line; + 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"); + }) + + + function calculateStateCode() { + + let bits = []; + + //Hlavny istic - state_of_main_switch => v rvo senica je to druhy door pre silovu cast (EM) + if (deviceStatus["state_of_main_switch"] === "closed" || deviceStatus["state_of_main_switch"] === "Off") { + bits.push(0); + } + else { + bits.push(1); + } + + //Prevadzkovy mod - Manual, Off, Automatic, maintenance_mode = true/false // DAVA 2 BITY + if (!SETTINGS.maintenance_mode) { + if (deviceStatus["rotary_switch_state"] === "Manual") { + bits.push(0); + bits.push(1); + } + + if (deviceStatus["rotary_switch_state"] === "Automatic") { + bits.push(0); + bits.push(0); + } + + if (deviceStatus["rotary_switch_state"] === "Off") { + bits.push(1); + bits.push(0); + } + } + else { + bits.push(1); + bits.push(1); + } + + //Dverovy kontakt + if (deviceStatus["door_condition"] === "closed") { + bits.push(0); + } + else { + bits.push(1); + } + + //EM + if (deviceStatus["em"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //Teplomer + if (deviceStatus["temperature"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //Batéria + if (deviceStatus["battery"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //Zdroj + if (deviceStatus["power_supply"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //MN + if (deviceStatus["master_node"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //výpadok napätia na fáze + if (deviceStatus["no_voltage"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + if (deviceStatus["twilight_sensor"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + // doplnime do 16 bitov (2 byty) + for (let i = bits.length; i < 16; i++) { + bits.push(0); + } + + // console.log("calculateStateCode - deviceStatus", deviceStatus); + // 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; + } + + + async function sendRvoStatus() { + + if (SETTINGS === undefined) return; + SETTINGS.masterNodeIsResponding ? deviceStatus["master_node"] = "OK" : deviceStatus["master_node"] = "NOK"; + + 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 pinsForRvoStatus(controllerType, hasMainSwitch) { + + let pins = []; + + if (controllerType === "lm") { + pins = [1, 4, 6]; + if (hasMainSwitch === 1) { + pins = [4, 6]; + } + } else if (controllerType === "unipi") { + pins = ["input1_01", "input1_04", "input1_05"]; + if (hasMainSwitch === 1) { + pins = ["input1_01", "input1_04"]; + } + } + + return pins; + } + + + function checkRvoStatus() { + + // 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 + //set RVO state + let status = "OK"; + + for (const [key, value] of Object.entries(deviceStatus)) { + if (["em", "twilight_sensor", "temperature", "master_node"].includes(key) && value === "NOK") status = "NOK"; + } + + if (status === "OK") { + + let pinIndexes = pinsForRvoStatus(controller_type, hasMainSwitch); + + for (const pinIndex of pinIndexes) { + if (previousValues[pinIndex] === 0) { + if ((pinIndex === 6 || pinIndex === 'input1_01' || pinIndex === 'input1_05') && SETTINGS.maintenance_mode) continue; + status = "NOK"; + break; + } + } + } + + // battery status. If value is 1 - battery is NOK + if (previousValues[5] === 1) status = "NOK"; + if (SETTINGS.no_voltage.size > 0) status = "NOK"; + + // console.log("rvo status",status) + return status; + } + + + // we pass array to function in case of rsPort ==> switchLogic([55,3,0,1]) ==> [[55,3,0,1]] + // we pass two values in case of websocket ==> switchLogic("relay1_03",1) ==> ["relay1_03",1] + const switchLogic = (...args) => { + + let values = {}; + let pinIndex, newPinValue, twilight; + + //data from rsPort + if (args.length == 1) { + pinIndex = args[0][1] + 1; + if (pinIndex === 17) pinIndex--; + newPinValue = args[0][3]; + twilight = args[0][2]; + } + //data from websocket + else { + pinIndex = args[0]; + newPinValue = args[1]; + } + + 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; + + //default value + let value = "On"; + if (newPinValue === 0) value = "Off"; + + //Hlavny istic + if (type === "state_of_main_switch" && hasMainSwitch) { + if (newPinValue === 0 && newPinValue !== previousValues[pinIndex]) { + sendNotification("switchLogic", rvoTbName, "main_switch_has_been_turned_off", {}, "", SEND_TO.tb, instance, "state_of_main_switch"); + 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"); + deviceStatus["state_of_main_switch"] = "On"; + } + } + + //Prevadzkovy mod + 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"; + + deviceStatus["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, "power_supply_has_disconnected_input", {}, "", SEND_TO.tb, instance, "power_supply"); + + deviceStatus["power_supply"] = "NOK"; + } + else if (newPinValue === 1 && newPinValue !== previousValues[pinIndex]) { + sendNotification("switchLogic", rvoTbName, "power_supply_works_correctly", {}, "", SEND_TO.tb, instance, "power_supply"); + + deviceStatus["power_supply"] = "OK"; + } + } + + //Bateria - 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"); + + deviceStatus["battery"] = "NOK"; + } + else if (newPinValue === 0 && newPinValue !== previousValues[pinIndex]) { + sendNotification("switchLogic", rvoTbName, "battery_level_is_ok", {}, "", SEND_TO.tb, instance, "battery_level"); + + deviceStatus["battery"] = "OK"; + } + } + + //Dverovy kontakt - pin 6 + //! Ak je rvo s dvoma dverovymi kontaktami, ked pride z evoku signal z input1_05, co bol predytm "state_of_main switch" handlujeme ho teraz ako 'door_condition' + else if (type == "door_condition" || type === "state_of_main_switch") { + newPinValue === 0 ? value = "open" : value = "closed"; + + let door = "door_main"; + if (type === "state_of_main_switch") door = "door_em"; + + if (value === "open") { + if (SETTINGS.maintenance_mode) { + sendNotification("switchLogic", rvoTbName, door + "_open", {}, "", SEND_TO.tb, instance, door); + } else { + sendNotification("switchLogic", rvoTbName, door + "_open_without_permission", {}, "", SEND_TO.tb, instance, door); + + // 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 (value === "closed") { + if (alarmStatus == "ON") turnAlarm("off"); + sendNotification("switchLogic", rvoTbName, door + "_close", {}, "", SEND_TO.tb, instance, door); + } + + deviceStatus[type] = value; + } + + //lux sensor + else if (type == "twilight_sensor") { + //! TODO - to show nok status, if lux value is not changing more then 10 times. + //Daylight is far more than 1000. So most of the day, when it is sunshine comes just value 1000. But lux sensor is not NOK. + //This is not the case in LM. If value from LM is the same 10x, there is 99% possibility, that sensor is NOK. + value = newPinValue; + + if (controller_type === 'lm') { + value = parseFloat(newPinValue + (256 * twilight)); + + 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 && !twilightError) { + twilightError = true; + let value = twilight_sensor_array.shift(); + + newPinValue = 0; + } + else if (set.size !== 1 && twilightError) { + //sendNotification("switchLogic", rvoTbName, 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) { + 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); + } + } + + 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); + } + + deviceStatus["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 (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 }); + + //mame iba 3 istice. vyreportujeme a ohandlujeme liniu na tom istom istici ako paralelna linia (napr linia 1, paralelna s nou je linia 4, key je string "4") + // ak je 7 linii, na 1 istici je linia 1,4,7 + + if (line == 1) { + + const lineOnSameBraker = [4, 7]; + + for (var i = 0; i < lineOnSameBraker.length; i++) { + if (!relaysData.hasOwnProperty(lineOnSameBraker[i])) continue; + + 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; + reportLineStatus(lineOnSameBraker[i]); + + values[type] = value; + const tbname = relaysData[lineOnSameBraker[i]].tbname; + sendTelemetry(values, tbname); + + delete values[type]; + } + + } + else { + const lineOnSameBraker = line + 3 + ""; + + if (relaysData.hasOwnProperty(lineOnSameBraker)) { + 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; + reportLineStatus(line + 3); + + values[type] = value; + const tbname = relaysData[lineOnSameBraker].tbname; + sendTelemetry(values, tbname); + + delete values[type]; + } + } + + } + + if (value == "Off") values["status"] = "NOK"; + deviceStatus["state_of_breaker"][line] = value; + + reportLineStatus(line); + } + else return; + + values[type] = value; + + if (type == "rotary_switch_state") { + if (SETTINGS.maintenance_mode) value = "maintenance"; + value = value.toLowerCase(); + values["power_mode"] = value; + } + + if (newPinValue != previousValues[pinIndex]) previousValues[pinIndex] = newPinValue; + if (Object.keys(values).length > 0 && tbname) sendTelemetry(values, tbname); + } + + + function sendTelemetry(values, tbname, date = Date.now()) { + let dataToTb = { + [tbname]: [ + { + "ts": date, + "values": values + } + ] + }; + + tbHandler.sendToTb(dataToTb, instance); + } + + + function isObject(item) { + return (typeof item === "object" && !Array.isArray(item) && item !== null); + } + +} //end of 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 +// *|input1_01|state_of_main_switch|0|........... +// *|input1_02|rotary_switch_state|0|........... +// *|input1_03|rotary_switch_state|0|........... +// *|intut1_04|power_supply|0|........... +// *|input1_05|door_condition|0|........... +// *|input1_06|state_of_breaker|1|........... +// *|input1_07|state_of_breaker|2|........... +// *|input1_08|state_of_breaker|3|........... +// *|relay1_02|state_of_contactor|1|........... +// *|relay1_03|state_of_contactor|2|........... +// *|relay1_04|state_of_contactor|3|........... +// *|287D8776E0013CE9|temperature|0|........... + + +//! pins_data --> from UNIPI +// { +// 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 } +// } + +//! relays_data +// { +// '0': { +// line: 0, +// tbname: 'KjbN4q7JPZmexgdnz2yKQ98YAWwO0Q3BMX6ERLoV', +// contactor: 1, +// profile: '' +// }, +// '1': { +// line: 1, +// tbname: 'RMgnK93rkoAazbqdQ4yBG95Z1YXGx6pmwBeVEP2O', +// contactor: 0, +// profile: '{"intervals":[{"value":0,"end_time":"20:00","start_time":"13:00"},{"value":1,"end_time":"10:00","start_time":"20:00"},{"value":0,"end_time":"10:20","start_time":"10:00"},{"value":1,"end_time":"10:40","start_time":"10:20"},{"value":0,"end_time":"11:00","start_time":"10:40"},{"value":1,"end_time":"11:30","start_time":"11:00"},{"value":0,"end_time":"11:50","start_time":"11:30"},{"value":1,"end_time":"13:00","start_time":"11:50"}],"astro_clock":false,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' +// }, +// '2': { +// line: 2, +// tbname: 'dlE1VQjYrNx9gZRmb38gG08oLBO4qaAk2M6JPnG7', +// contactor: 0, +// profile: '{"intervals":[{"value":0,"end_time":"20:00","start_time":"13:00"},{"value":1,"end_time":"10:00","start_time":"20:00"},{"value":0,"end_time":"10:20","start_time":"10:00"},{"value":1,"end_time":"10:40","start_time":"10:20"},{"value":0,"end_time":"11:00","start_time":"10:40"},{"value":1,"end_time":"11:30","start_time":"11:00"},{"value":0,"end_time":"11:50","start_time":"11:30"},{"value":1,"end_time":"13:00","start_time":"11:50"}],"astro_clock":false,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' +// }, +// '3': { +// line: 3, +// tbname: 'vnmG4kJxaXWNBgMQq0D7Aj5e9oZzOAlr6LdR3w2V', +// contactor: 0, +// profile: '{"intervals":[{"value":0,"end_time":"20:30","start_time":"13:00"},{"value":1,"end_time":"00:10","start_time":"20:30"},{"value":0,"end_time":"13:00","start_time":"05:40"},{"value":1,"end_time":"05:40","start_time":"00:10"}],"astro_clock":true,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' +// } +// } + + + + + +// { +// "jbN4q7JPZmexgdnz2yKbWGDYAWwO0Q3BMX6ERLoV": [ +// { +// "ts": 1700409326353, +// "values": { +// "_event": { +// "type": "notice", +// "status": "new", +// "source": { +// "func": "rsPort.open()", +// "component": "1700343402190", +// "component_name": "DIDO_Controller", +// "edge": "jbN4q7JPZmexgdnz2yKbWGDYAWwO0Q3BMX6ERLoV" +// }, +// "message": "al_shariff_10.0.0.38: FLOW has been started ", +// "message_data": "" +// } +// } +// } +// ] +// } diff --git a/RVO39/flow/helper/DataToTbHandler.js b/RVO39/flow/helper/DataToTbHandler.js new file mode 100755 index 0000000..716ef7b --- /dev/null +++ b/RVO39/flow/helper/DataToTbHandler.js @@ -0,0 +1,187 @@ +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; + this.itIsNodeReadout = false; + this.sender = ""; + + // if attribute change difference is less than limit value, we do not send to tb. + this.attributeChangeLimit = { + temperature: 0.5, + Phase_1_voltage: 2, + Phase_2_voltage: 2, + Phase_3_voltage: 2, + Phase_1_current: 0.1, + Phase_2_current: 0.1, + Phase_3_current: 0.1, + Phase_1_power: 2, + Phase_2_power: 2, + Phase_3_power: 2, + total_power: 2, + total_energy: 1, + Phase_1_pow_factor: 0.1, + Phase_2_pow_factor: 0.1, + Phase_3_pow_factor: 0.1, + power_factor: 0.1, + lifetime: 2, + voltage: 2, + power: 2, + frequency: 3, + energy: 0.1, + current: 2, + inclination_x: 10, + inclination_y: 10, + inclination_z: 10 + }; + + } + + dump() { + console.log("----------------------------"); + console.log("previousValues", this.previousValues); + console.log("----------------------------"); + } + + setSender(sender) { + this.sender = sender; + } + + isEmptyObject(obj) { + for (var _ in obj) { + return false; + } + return true; + } + + + sendToTb(data, instance) { + + //not to modify data object, we do deep copy: + let dataCopy = JSON.parse(JSON.stringify(data)); + + let keys = Object.keys(dataCopy); + + if (keys.length == 0) { + if (this.debug) console.log("sendToTb received empty object", dataCopy); + return; + } + + let tbname = keys[0]; + let ts; + + let arrayOfValues = dataCopy[tbname]; + let arrayOfValuesToSend = []; + + for (let i = 0; i < arrayOfValues.length; i++) { + + ts = arrayOfValues[i].ts; + let values = this.prepareValuesForTb(tbname, ts, arrayOfValues[i].values); + + if (!this.isEmptyObject(values)) { + arrayOfValuesToSend.push({ ts: ts, values: values }); + } + + } + + if (arrayOfValuesToSend.length == 0) { + //if(this.debug) console.log("data not sent - empty array"); + return; + } + + this.messageCounter++; + + let dataToTbModified = { + [tbname]: arrayOfValuesToSend + } + + //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); + instance.send(this.index, dataToTbModified); + } + + + getDiffTimestamp(key) { + //TODO set different value for given key!!! + //if(key == "status") this.timeToHoldTbValue = 2*60*60;//2h + return this.timeToHoldTbValue * 1000; + } + + + prepareValuesForTb(tbname, timestamp, values) { + + let keys = Object.keys(values); + + if (keys.includes("lifetime")) this.itIsNodeReadout = true; + + if (!this.previousValues.hasOwnProperty(tbname)) { + this.previousValues[tbname] = {}; + } + + //if(this.debug) console.log("prepareValuesForTb", tbname, timestamp, values); + + for (let i = 0; i < keys.length; i++) { + + let key = keys[i]; + let value = values[key]; + + if (!this.previousValues[tbname].hasOwnProperty(key)) { + this.previousValues[tbname][key] = { ts: timestamp, value: value }; + continue; + } + + // attributeData ==> {voltage: {ts:333333, value:5}} + let attributeData = this.previousValues[tbname][key]; + let attributeToChange = false; + if (key in this.attributeChangeLimit) attributeToChange = true; + let limit = this.attributeChangeLimit[key]; + let timestampDiffToRemoveKey; + + //this will ensure "node statecode" will be sent just once an hour + if (this.itIsNodeReadout && key === "statecode") { + attributeData.value = value; + this.itIsNodeReadout = false; + timestampDiffToRemoveKey = 1 * 60 * 60 * 1000; // 1 hour + } + + if (key === "twilight_sensor" && value > 100) { + attributeData.value = value; + } + + //if edge, master or node version do not change, send just once a day: + if (["edge_fw_version", "master_node_version", "fw_version"].includes(key)) { + timestampDiffToRemoveKey = 24 * 60 * 60 * 1000; + } + + if (attributeData.value === value || attributeToChange && Math.abs(attributeData.value - value) < limit) { + + let diff = timestamp - attributeData.ts; + if (!timestampDiffToRemoveKey) timestampDiffToRemoveKey = this.getDiffTimestamp(key); + + if (diff > timestampDiffToRemoveKey) { + attributeData.ts = Date.now(); + //if(this.debug) console.log(this.sender + ": update ts for key", key, "diff is", diff, "messageCounter", this.messageCounter); + } + else { + delete values[key]; + //if(this.debug) console.log(this.sender + ": delete key", key, "diff is", diff, "messageCounter", this.messageCounter, timestampDiffToRemoveKey); + } + } + else { + attributeData.value = value; + attributeData.ts = timestamp; + } + + } + + return values; + } +} + +module.exports = DataToTbHandler; + diff --git a/RVO39/flow/helper/ErrorToServiceHandler.js b/RVO39/flow/helper/ErrorToServiceHandler.js new file mode 100755 index 0000000..2b27c32 --- /dev/null +++ b/RVO39/flow/helper/ErrorToServiceHandler.js @@ -0,0 +1,91 @@ +const { MD5 } = require('./md5.js'); +const { networkInterfaces } = require('os'); + +class ErrorToServiceHandler { + constructor() { + this.previousValues = {}; + + this.project_id = undefined; + + const nets = networkInterfaces(); + this.ipAddresses = {}; + + for (const name of Object.keys(nets)) { + for (const net of nets[name]) { + // Skip over non-IPv4 and internal (i.e. 127.0.0.1) addresses + if (net.family === 'IPv4' && !net.internal) { + if (!this.ipAddresses[name]) { + this.ipAddresses[name] = []; + } + this.ipAddresses[name].push(net.address); + } + } + } + } + + setProjectId(project_id) { + this.project_id = project_id; + } + + processMessage(message, seconds) { + if (Array.isArray(message)) message = message.join(', '); + + let key = MD5(message); + let ts = Date.now(); + + //keep in memory - default value is 1h + if (seconds === undefined) seconds = 60 * 60; + + if (!this.previousValues.hasOwnProperty(key)) { + this.previousValues[key] = { ts: ts, duration: seconds }; + } + + let diff = (ts - this.previousValues[key].ts); + if (diff < this.previousValues[key].duration * 1000) return false; + + this.previousValues[key].ts = ts; + + return message; + } + + sendMessageToService(message, seconds, message_type) { + + // if error occures too early FLOW.GLOBALS.settings.project_id is still undefined + if (this.project_id === undefined) { + console.log("ErrorToServiceHandler.js: no project_id"); + return; + } + + let f = this.processMessage(message, seconds); + if (f === false) return; + + if (message_type === undefined) message_type = "error_message"; + + let toService = { + id: this.project_id, + ipAddresses: this.ipAddresses + }; + + //js_error || error_message + toService[message_type] = message; + + console.log("ErrorToServiceHandler------------------------>send to service", toService); + + RESTBuilder.make(function(builder) { + builder.method('POST'); + builder.post(toService); + builder.url('http://192.168.252.2:8004/sentmessage'); + + builder.callback(function(err, response, output) { + console.log("process.on error send", err, response, output, toService); + }); + }); + + } +} + +const errorHandler = new ErrorToServiceHandler(); + + +module.exports = errorHandler; +//module.exports = ErrorToServiceHandler; diff --git a/RVO39/flow/helper/db_helper.js b/RVO39/flow/helper/db_helper.js new file mode 100755 index 0000000..40e796c --- /dev/null +++ b/RVO39/flow/helper/db_helper.js @@ -0,0 +1,44 @@ +function promisifyBuilder(builder) +{ + return new Promise((resolve, reject) => { + + try{ + + builder.callback(function(err, response) { + + if(err != null) reject(err); + resolve(response); + }); + + } catch (error) { + reject(error); + } + }) +} + +function makeMapFromDbResult(response, ...keys) +{ + let s = "-"; + let data = {}; + + for(let i = 0; i < response.length; i++) + { + let record = response[i]; + + let k = []; + for(let j = 0; j < keys.length; j++) + { + k.push( record[keys[j]] ); + } + + let key = k.join(s); + data[ key ] = record; + } + + return data; +} + +module.exports = { + promisifyBuilder, + makeMapFromDbResult + } \ No newline at end of file diff --git a/RVO39/flow/helper/logger.js b/RVO39/flow/helper/logger.js new file mode 100755 index 0000000..2585639 --- /dev/null +++ b/RVO39/flow/helper/logger.js @@ -0,0 +1,30 @@ +//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/RVO39/flow/helper/md5.js b/RVO39/flow/helper/md5.js new file mode 100755 index 0000000..d3b0480 --- /dev/null +++ b/RVO39/flow/helper/md5.js @@ -0,0 +1,5 @@ +function MD5(d){var r = M(V(Y(X(d),8*d.length)));return r.toLowerCase()};function M(d){for(var _,m="0123456789ABCDEF",f="",r=0;r>>4&15)+m.charAt(15&_);return f}function X(d){for(var _=Array(d.length>>2),m=0;m<_.length;m++)_[m]=0;for(m=0;m<8*d.length;m+=8)_[m>>5]|=(255&d.charCodeAt(m/8))<>5]>>>m%32&255);return _}function Y(d,_){d[_>>5]|=128<<_%32,d[14+(_+64>>>9<<4)]=_;for(var m=1732584193,f=-271733879,r=-1732584194,i=271733878,n=0;n>16)+(_>>16)+(m>>16)<<16|65535&m}function bit_rol(d,_){return d<<_|d>>>32-_} + +module.exports = { + MD5 +} \ No newline at end of file diff --git a/RVO39/flow/helper/notification_reporter.js b/RVO39/flow/helper/notification_reporter.js new file mode 100755 index 0000000..839c12c --- /dev/null +++ b/RVO39/flow/helper/notification_reporter.js @@ -0,0 +1,121 @@ +//key is device, value = message {} +let sentValues = {}; +let notificationsData = null; +let rvoName; + +//sendNotification("CMD Manager: process cmd", SETTINGS.rvoTbName, "dimming_profile_was_successfully_received_by_node", { node: node }, "", SEND_TO.tb, instance); + +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 +}; + +function getKey(map, val) { + return Object.keys(map).findItem(key => map[key] === val); +} + +//https://stackoverflow.com/questions/41117799/string-interpolation-on-variable +var template = (tpl, args) => tpl.replace(/\${(\w+)}/g, (_, v) => args[v]); + + +function initNotification() { + notificationsData = FLOW.GLOBALS.notificationsData; + rvoName = FLOW.GLOBALS.settings.rvo_name; +} + + +function sendNotification(func, device, key, params, extra, tb_output, instance, saveKey) { + + let storeToSendValues = true; + if (saveKey == undefined) storeToSendValues = false; + + let weight = ""; + let message = {}; + + let notification = notificationsData[key]; + + if (notification) { + weight = notification.weight.toLowerCase(); + + Object.keys(notification).forEach(item => { + if (["en", "sk", "de", "cz", "it", "es"].includes(item)) { + message[item] = rvoName + ": " + template(notification[item], params); + } + }) + } + else { + //console.error("sendNotification: Notifications: undefined key", key, func, notificationsData); + console.error("sendNotification: Notifications: undefined key", key, func); + return false; + } + + //detect invalid err weight + if (getKey(ERRWEIGHT, weight) == undefined) { + console.error("sendNotification: Notifications: undefined weight", weight, key, func); + return false; + } + + if (sentValues.hasOwnProperty(saveKey)) { + if (JSON.stringify(sentValues[saveKey]) == JSON.stringify(message)) { + return false; + } + } + + if (sentValues[saveKey] == undefined) { + if (storeToSendValues) { + //do not send - flow is was started + sentValues[saveKey] = message; + return false; + } + } + + if (storeToSendValues) sentValues[saveKey] = message; + + let content = { + "type": weight, + "status": "new", + "source": { + "func": func, + "component": instance.id, + "component_name": instance.name, + "edge": device + }, + "message": message, + "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 + + return true; + +} + +module.exports = { + sendNotification, + ERRWEIGHT, + initNotification +} + diff --git a/RVO39/flow/helper/register.js b/RVO39/flow/helper/register.js new file mode 100755 index 0000000..fc1d008 --- /dev/null +++ b/RVO39/flow/helper/register.js @@ -0,0 +1,144 @@ +/* +0 - cislo registra / prikaz +1 - recepient - 0 = master, 1 = slave (slave je automaticky group a broadcast) +2 - r/rw - read/write +3- register name - nazov registra / prikazu (len pre info - zobrazenie v aplikacii) + +4,5,6,7, - jednotlive byte-y - nazov byte-u +4-7 - RES. a prazdny string "" sa nezobrazia!!! +*/ + +//124 zaznamov +const registers = [ + ["0","1","R","Status","","",""], + ["1","1","RW","Dimming","R-Channel ","G-Channel","B-Channel ","W - Channel"], + ["2","1","R","Device types","","",".",""], + ["3","1","RW","Group addresses 1-4","Groups Add. 4","Groups Add. 3","Groups Add. 2","Groups Add. 1"], + ["4","1","RW","Group addresses 5-8","Groups Add. 8","Groups Add. 7","Groups Add. 6","Groups Add. 5"], + ["5","1","RW","Serial number (MAC)","","","",""], + ["6","1","RW","Time of dusk","HH","MM","SS","EXTRA"], + ["7","1","RW","Time of dawn","HH","MM","SS","EXTRA"], + ["8","1","RW","Time Schedule settings","TBD","TBD","Movement sensor","Time Schedule"], + ["9","1","RW","TS1 Time point 1","HH","MM","SS","Ext. Device"], + ["10","1","RW","TS1 Time point 1 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["11","1","RW","TS1 Time point 2","HH","MM","SS","Ext. Device"], + ["12","1","RW","TS1 Time point 2 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["13","1","RW","TS1 Time point 3","HH","MM","SS","Ext. Device"], + ["14","1","RW","TS1 Time point 3 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["15","1","RW","TS1 Time point 4","HH","MM","SS","Ext. Device"], + ["16","1","RW","TS1 Time point 4 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["17","1","RW","TS1 Time point 5","HH","MM","SS","Ext. Device"], + ["18","1","RW","TS1 Time point 5 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["19","1","RW","TS1 Time point 6","HH","MM","SS","Ext. Device"], + ["20","1","RW","TS1 Time point 6 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["21","1","RW","TS1 Time point 7","HH","MM","SS","Ext. Device"], + ["22","1","RW","TS1 Time point 7 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["23","1","RW","TS1 Time point 8","HH","MM","SS","Ext. Device"], + ["24","1","RW","TS1 Time point 8 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["25","1","RW","TS1 Time point 9","HH","MM","SS","Ext. Device"], + ["26","1","RW","TS1 Time point 9 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["27","1","RW","TS1 Time point 10","HH","MM","SS","Ext. Device"], + ["28","1","RW","TS1 Time point 10 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["29","1","RW","TS1 Time point 11","HH","MM","SS","Ext. Device"], + ["30","1","RW","TS1 Time point 11 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["31","1","RW","TS1 Time point 12","HH","MM","SS","Ext. Device"], + ["32","1","RW","TS1 Time point 12 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["33","1","RW","TS1 Time point 13","HH","MM","SS","Ext. Device"], + ["34","1","RW","TS1 Time point 13 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["35","1","RW","TS1 Time point 14","HH","MM","SS","Ext. Device"], + ["36","1","RW","TS1 Time point 14 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["37","1","RW","TS1 Time point 15","HH","MM","SS","Ext. Device"], + ["38","1","RW","TS1 Time point 15 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["39","1","RW","TS1 Time point 16","HH","MM","SS","Ext. Device"], + ["40","1","RW","TS1 Time point 16 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["41","1","RW","TS2 Time point 1","HH","MM","SS","Ext. Device"], + ["42","1","RW","TS2 Time point 1 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["43","1","RW","TS2 Time point 2","HH","MM","SS","Ext. Device"], + ["44","1","RW","TS2 Time point 2 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["45","1","RW","TS2 Time point 3","HH","MM","SS","Ext. Device"], + ["46","1","RW","TS2 Time point 3 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["47","1","RW","TS2 Time point 4","HH","MM","SS","Ext. Device"], + ["48","1","RW","TS2 Time point 4 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["49","1","RW","TS2 Time point 5","HH","MM","SS","Ext. Device"], + ["50","1","RW","TS2 Time point 5 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["51","1","RW","TS2 Time point 6","HH","MM","SS","Ext. Device"], + ["52","1","RW","TS2 Time point 6 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["53","1","RW","TS2 Time point 7","HH","MM","SS","Ext. Device"], + ["54","1","RW","TS2 Time point 7 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["55","1","RW","TS2 Time point 8","HH","MM","SS","Ext. Device"], + ["56","1","RW","TS2 Time point 8 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["57","1","RW","TS2 Time point 9","HH","MM","SS","Ext. Device"], + ["58","1","RW","TS2 Time point 9 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["59","1","RW","TS2 Time point 10","HH","MM","SS","Ext. Device"], + ["60","1","RW","TS2 Time point 10 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["61","1","RW","TS2 Time point 11","HH","MM","SS","Ext. Device"], + ["62","1","RW","TS2 Time point 11 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["63","1","RW","TS2 Time point 12","HH","MM","SS","Ext. Device"], + ["64","1","RW","TS2 Time point 12 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["65","1","RW","TS2 Time point 13","HH","MM","SS","Ext. Device"], + ["66","1","RW","TS2 Time point 13 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["67","1","RW","TS2 Time point 14","HH","MM","SS","Ext. Device"], + ["68","1","RW","TS2 Time point 14 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["69","1","RW","TS2 Time point 15","HH","MM","SS","Ext. Device"], + ["70","1","RW","TS2 Time point 15 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["71","1","RW","TS2 Time point 16","HH","MM","SS","Ext. Device"], + ["72","1","RW","TS2 Time point 16 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["73","1","RW","Power meter status","TBD","","",""], + ["74","1","R","Input Voltage","","","",""], + ["75","1","R","Input Current","","","",""], + ["76","1","R","Input Power","","","",""], + ["77","1","R","Cos phi","","","",""], + ["78","1","R","Frequency","","","",""], + ["79","1","RW","Energy","","","",""], + ["80","1","RW","Lifetime","","","",""], + ["81","1","RW","Power on cycles (input)","","","",""], + ["82","1","RW","Power on cycles (relay)","","","",""], + ["83","1","R","Time since last power on","","","",""], + ["84","1","R","Accelerometer data","","","",""], + ["85","1","RW","GPS latitude","pos/neg","deg","min ","sec"], + ["86","1","RW","GPS longitude","pos/neg","deg","min ","sec"], + ["87","1","RW","Actual time","HH","MM","SS","RES."], + ["88","1","RW","Actual date","Day of week","Day","Month","Year"], + ["89","1","R","Production data 1","","","",""], + ["90","1","R","Production data 2","","","",""], + ["91","1","RW","Network ID","NID3","NID2","NID1","NID0"], + ["95","1","RW","Actual Lux level from cabinet","RES.","RES.","HB","LB"], + ["96","1","RW","Threshold lux level","Dusk HB","Dusk LB","Dawn HB","Dawn LB"], + ["97","1","RW","Adjust period","Dusk HB","Dusk LB","Dawn HB","Dawn LB"], + ["98","1","RW","Offset","RES.","RES.","Dusk","Dawn"], + ["99","1","RW","CCT min/max range","max-H","max-L","min-H","min-L"], + ["100","1","RW","DALI interface","Cmd ID","Add","Cmd","Resp"], + ["101","1","RW","Module FW ver","v1","v2","v3","v4"], + ["102","1","RW","Module MAC-H","unused","unused","M1","M2"], + ["103","1","RW","Module MAC-L","M3","M4","M5","M6"], + ["122","1","R","FW update status/control register","Byte3","Byte2","Byte1","Byte0"], + ["123","1","R","FW update - data index","Byte3","Byte2","Byte1","Byte0"], + ["124","1","R","FW update - data","Byte3","Byte2","Byte1","Byte0"], + ["0","0","R","Status","","","",""], + ["1","0","RW","Control register","RES.","RES.","RES.","init mode enable"], + ["2","0","R","Device types","","","",""], + ["3","0","R","Serial number (MAC)","","","",""], + ["4","0","R","Production data 1","","","",""], + ["5","0","R","Production data 2","","","",""], + ["6","0","RW","Network ID","NID3","NID2","NID1","NID0"], + ["7","0","RW","RS232 settings","param.","param.","Baudrate H","Baudrate L"], + ["8","0","R","Accelerometer data","","","",""], + ["9","0","RW","Module FW ver","v1","v2","v3","v4"], + ["10","0","RW","Module MAC-H","unused","unused","M1","M2"], + ["11","0","RW","Module MAC-L","M3","M4","M5","M6"], + ["32","0","RW","FW update status/control register","Byte3","Byte2","Byte1","Byte0"], + ["33","0","RW","FW update - data index","Byte3","Byte2","Byte1","Byte0"], + ["34","0","RW","FW update - data","Byte3","Byte2","Byte1","Byte0"], + ["125","0","RW","Debug Register","Byte3","Byte2","Byte1","Byte0"], + ["126","0","RW","Network Control Register","Byte3","Byte2","Byte1","Byte0"], + ["127","0","R","Network Status Register","Byte3","Byte2","Byte1","Byte0"], + ["128","0","RW","Node XX Serial Number Register","SER3","SER2","SER1","SER0"], + ["256","0","R","Node XX Network Status Register","","","",""] +]; + +let register = {}; + +module.exports = { + registers, + register +} \ No newline at end of file diff --git a/RVO39/flow/helper/serialport_helper.js b/RVO39/flow/helper/serialport_helper.js new file mode 100755 index 0000000..7f5920d --- /dev/null +++ b/RVO39/flow/helper/serialport_helper.js @@ -0,0 +1,99 @@ +const { exec } = require('child_process'); + +function openPort(port) { + return new Promise((resolve, reject) => { + + var callbackError = function(err) { + port.removeListener('error', callbackError); + port.removeListener('open', callbackError); + + reject(err.message); + }; + + var callbackOpen = function(data) { + port.removeListener('error', callbackError); + port.removeListener('open', callbackOpen); + + resolve("port open: ok"); + }; + + port.on('error', callbackError); + port.on('open', callbackOpen); + + port.open(); + + }) +} + +function runSyncExec(command) { + return new Promise((resolve, reject) => { + + exec(command, (error, stdout, stderr) => { + if (error == null) resolve(stdout); + reject(error); + }); + + }) +} + +async function writeData(port, data, readbytes, timeout) { + return new Promise((resolve, reject) => { + + // 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) { + + port.write(Buffer.from(data), function(err) { + if (err) { + reject(err.message); + } + }); + + 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 +} diff --git a/RVO39/flow/helper/suncalc.js b/RVO39/flow/helper/suncalc.js new file mode 100755 index 0000000..c9ca56d --- /dev/null +++ b/RVO39/flow/helper/suncalc.js @@ -0,0 +1,317 @@ +/* + (c) 2011-2015, Vladimir Agafonkin + SunCalc is a JavaScript library for calculating sun/moon position and light phases. + https://github.com/mourner/suncalc +*/ + +(function () { 'use strict'; + +// shortcuts for easier to read formulas + +var PI = Math.PI, + sin = Math.sin, + cos = Math.cos, + tan = Math.tan, + asin = Math.asin, + atan = Math.atan2, + acos = Math.acos, + rad = PI / 180; + +// sun calculations are based on http://aa.quae.nl/en/reken/zonpositie.html formulas + + +// date/time constants and conversions + +var dayMs = 1000 * 60 * 60 * 24, + J1970 = 2440588, + J2000 = 2451545; + +function toJulian(date) { return date.valueOf() / dayMs - 0.5 + J1970; } +function fromJulian(j) { return new Date((j + 0.5 - J1970) * dayMs); } +function toDays(date) { return toJulian(date) - J2000; } + + +// general calculations for position + +var e = rad * 23.4397; // obliquity of the Earth + +function rightAscension(l, b) { return atan(sin(l) * cos(e) - tan(b) * sin(e), cos(l)); } +function declination(l, b) { return asin(sin(b) * cos(e) + cos(b) * sin(e) * sin(l)); } + +function azimuth(H, phi, dec) { return atan(sin(H), cos(H) * sin(phi) - tan(dec) * cos(phi)); } +function altitude(H, phi, dec) { return asin(sin(phi) * sin(dec) + cos(phi) * cos(dec) * cos(H)); } + +function siderealTime(d, lw) { return rad * (280.16 + 360.9856235 * d) - lw; } + +function astroRefraction(h) { + if (h < 0) // the following formula works for positive altitudes only. + h = 0; // if h = -0.08901179 a div/0 would occur. + + // formula 16.4 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + // 1.02 / tan(h + 10.26 / (h + 5.10)) h in degrees, result in arc minutes -> converted to rad: + return 0.0002967 / Math.tan(h + 0.00312536 / (h + 0.08901179)); +} + +// general sun calculations + +function solarMeanAnomaly(d) { return rad * (357.5291 + 0.98560028 * d); } + +function eclipticLongitude(M) { + + var C = rad * (1.9148 * sin(M) + 0.02 * sin(2 * M) + 0.0003 * sin(3 * M)), // equation of center + P = rad * 102.9372; // perihelion of the Earth + + return M + C + P + PI; +} + +function sunCoords(d) { + + var M = solarMeanAnomaly(d), + L = eclipticLongitude(M); + + return { + dec: declination(L, 0), + ra: rightAscension(L, 0) + }; +} + + +var SunCalc = {}; + + +// calculates sun position for a given date and latitude/longitude + +SunCalc.getPosition = function (date, lat, lng) { + + var lw = rad * -lng, + phi = rad * lat, + d = toDays(date), + + c = sunCoords(d), + H = siderealTime(d, lw) - c.ra; + + return { + azimuth: azimuth(H, phi, c.dec), + altitude: altitude(H, phi, c.dec) + }; +}; + + +// sun times configuration (angle, morning name, evening name) + +var times = SunCalc.times = [ + [-0.833, 'sunrise', 'sunset' ], + [ -0.3, 'sunriseEnd', 'sunsetStart' ], + [ -6, 'dawn', 'dusk' ], + [ -12, 'nauticalDawn', 'nauticalDusk'], + [ -18, 'nightEnd', 'night' ], + [ 6, 'goldenHourEnd', 'goldenHour' ] +]; + +// adds a custom time to the times config + +SunCalc.addTime = function (angle, riseName, setName) { + times.push([angle, riseName, setName]); +}; + + +// calculations for sun times + +var J0 = 0.0009; + +function julianCycle(d, lw) { return Math.round(d - J0 - lw / (2 * PI)); } + +function approxTransit(Ht, lw, n) { return J0 + (Ht + lw) / (2 * PI) + n; } +function solarTransitJ(ds, M, L) { return J2000 + ds + 0.0053 * sin(M) - 0.0069 * sin(2 * L); } + +function hourAngle(h, phi, d) { return acos((sin(h) - sin(phi) * sin(d)) / (cos(phi) * cos(d))); } +function observerAngle(height) { return -2.076 * Math.sqrt(height) / 60; } + +// returns set time for the given sun altitude +function getSetJ(h, lw, phi, dec, n, M, L) { + + var w = hourAngle(h, phi, dec), + a = approxTransit(w, lw, n); + return solarTransitJ(a, M, L); +} + + +// calculates sun times for a given date, latitude/longitude, and, optionally, +// the observer height (in meters) relative to the horizon + +SunCalc.getTimes = function (date, lat, lng, height) { + + height = height || 0; + + var lw = rad * -lng, + phi = rad * lat, + + dh = observerAngle(height), + + d = toDays(date), + n = julianCycle(d, lw), + ds = approxTransit(0, lw, n), + + M = solarMeanAnomaly(ds), + L = eclipticLongitude(M), + dec = declination(L, 0), + + Jnoon = solarTransitJ(ds, M, L), + + i, len, time, h0, Jset, Jrise; + + + var result = { + solarNoon: fromJulian(Jnoon), + nadir: fromJulian(Jnoon - 0.5) + }; + + for (i = 0, len = times.length; i < len; i += 1) { + time = times[i]; + h0 = (time[0] + dh) * rad; + + Jset = getSetJ(h0, lw, phi, dec, n, M, L); + Jrise = Jnoon - (Jset - Jnoon); + + result[time[1]] = fromJulian(Jrise); + result[time[2]] = fromJulian(Jset); + } + + return result; +}; + + +// moon calculations, based on http://aa.quae.nl/en/reken/hemelpositie.html formulas + +function moonCoords(d) { // geocentric ecliptic coordinates of the moon + + var L = rad * (218.316 + 13.176396 * d), // ecliptic longitude + M = rad * (134.963 + 13.064993 * d), // mean anomaly + F = rad * (93.272 + 13.229350 * d), // mean distance + + l = L + rad * 6.289 * sin(M), // longitude + b = rad * 5.128 * sin(F), // latitude + dt = 385001 - 20905 * cos(M); // distance to the moon in km + + return { + ra: rightAscension(l, b), + dec: declination(l, b), + dist: dt + }; +} + +SunCalc.getMoonPosition = function (date, lat, lng) { + + var lw = rad * -lng, + phi = rad * lat, + d = toDays(date), + + c = moonCoords(d), + H = siderealTime(d, lw) - c.ra, + h = altitude(H, phi, c.dec), + // formula 14.1 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + pa = atan(sin(H), tan(phi) * cos(c.dec) - sin(c.dec) * cos(H)); + + h = h + astroRefraction(h); // altitude correction for refraction + + return { + azimuth: azimuth(H, phi, c.dec), + altitude: h, + distance: c.dist, + parallacticAngle: pa + }; +}; + + +// calculations for illumination parameters of the moon, +// based on http://idlastro.gsfc.nasa.gov/ftp/pro/astro/mphase.pro formulas and +// Chapter 48 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + +SunCalc.getMoonIllumination = function (date) { + + var d = toDays(date || new Date()), + s = sunCoords(d), + m = moonCoords(d), + + sdist = 149598000, // distance from Earth to Sun in km + + phi = acos(sin(s.dec) * sin(m.dec) + cos(s.dec) * cos(m.dec) * cos(s.ra - m.ra)), + inc = atan(sdist * sin(phi), m.dist - sdist * cos(phi)), + angle = atan(cos(s.dec) * sin(s.ra - m.ra), sin(s.dec) * cos(m.dec) - + cos(s.dec) * sin(m.dec) * cos(s.ra - m.ra)); + + return { + fraction: (1 + cos(inc)) / 2, + phase: 0.5 + 0.5 * inc * (angle < 0 ? -1 : 1) / Math.PI, + angle: angle + }; +}; + + +function hoursLater(date, h) { + return new Date(date.valueOf() + h * dayMs / 24); +} + +// calculations for moon rise/set times are based on http://www.stargazing.net/kepler/moonrise.html article + +SunCalc.getMoonTimes = function (date, lat, lng, inUTC) { + var t = new Date(date); + if (inUTC) t.setUTCHours(0, 0, 0, 0); + else t.setHours(0, 0, 0, 0); + + var hc = 0.133 * rad, + h0 = SunCalc.getMoonPosition(t, lat, lng).altitude - hc, + h1, h2, rise, set, a, b, xe, ye, d, roots, x1, x2, dx; + + // go in 2-hour chunks, each time seeing if a 3-point quadratic curve crosses zero (which means rise or set) + for (var i = 1; i <= 24; i += 2) { + h1 = SunCalc.getMoonPosition(hoursLater(t, i), lat, lng).altitude - hc; + h2 = SunCalc.getMoonPosition(hoursLater(t, i + 1), lat, lng).altitude - hc; + + a = (h0 + h2) / 2 - h1; + b = (h2 - h0) / 2; + xe = -b / (2 * a); + ye = (a * xe + b) * xe + h1; + d = b * b - 4 * a * h1; + roots = 0; + + if (d >= 0) { + dx = Math.sqrt(d) / (Math.abs(a) * 2); + x1 = xe - dx; + x2 = xe + dx; + if (Math.abs(x1) <= 1) roots++; + if (Math.abs(x2) <= 1) roots++; + if (x1 < -1) x1 = x2; + } + + if (roots === 1) { + if (h0 < 0) rise = i + x1; + else set = i + x1; + + } else if (roots === 2) { + rise = i + (ye < 0 ? x2 : x1); + set = i + (ye < 0 ? x1 : x2); + } + + if (rise && set) break; + + h0 = h2; + } + + var result = {}; + + if (rise) result.rise = hoursLater(t, rise); + if (set) result.set = hoursLater(t, set); + + if (!rise && !set) result[ye > 0 ? 'alwaysUp' : 'alwaysDown'] = true; + + return result; +}; + + +// export as Node module / AMD module / browser variable +if (typeof exports === 'object' && typeof module !== 'undefined') module.exports = SunCalc; +else if (typeof define === 'function' && define.amd) define(SunCalc); +else window.SunCalc = SunCalc; + +}()); diff --git a/RVO39/flow/helper/utils.js b/RVO39/flow/helper/utils.js new file mode 100755 index 0000000..dbffe45 --- /dev/null +++ b/RVO39/flow/helper/utils.js @@ -0,0 +1,161 @@ +const fs = require('fs').promises; + +function bytesToInt(bytes, numberOfBytes) { + let buffer = []; + if (Array.isArray(bytes)) { + buffer = bytes.slice(0); + if (numberOfBytes != undefined) { + buffer = bytes.slice(bytes.length - numberOfBytes); + } + } + else buffer.push(bytes); + + let result = 0; + for (let i = 0; i < buffer.length; i++) { + result = (result << 8) | buffer[i]; + } + + return result >>> 0; //ensure it's an unsigned 32-bit number +} + +function resizeArray(arr, newSize, defaultValue) { + while (newSize > arr.length) + arr.push(defaultValue); + arr.length = newSize; +} + +longToByteArray = function(/*long*/long) { + // we want to represent the input as a 8-bytes array + var byteArray = [0, 0, 0, 0, 0, 0, 0, 0]; + + for (var index = 0; index < byteArray.length; index++) { + var byte = long & 0xff; + byteArray[index] = byte; + long = (long - byte) / 256; + } + + return byteArray; +}; + +function addDays(date, days) { + var result = new Date(date); + result.setDate(result.getDate() + days); + return result; +} + +/* +sleep(2000).then(() => { + // Do something after the sleep! + + +}); +*/ + +function sleep(time) { + return new Promise((resolve) => setTimeout(resolve, time)); +} + +function isEmptyObject(obj) { + for (var name in obj) { + return false; + } + return true; +} + +function emptyJsObject(jsObject) { + Object.keys(jsObject).forEach(key => delete jsObject[key]); +} + +function convertUTCDateToLocalDate(date) { + var newDate = new Date(date); + newDate.setMinutes(date.getMinutes() + date.getTimezoneOffset()); + return newDate; +} + +function addZeroBefore(n) { + return (n < 10 ? '0' : '') + n; +} + + +/** + * Asynchronously writes data to a file. + * + * @param {string} filePath The path to the file. + * @param {string} data The data to write to the file. + * @param {boolean} [append=false] If true, appends the data to the file. If false, it overwrites the file. + */ +async function writeToFile(filePath, data, append = false) { + if (typeof data !== 'string') data = JSON.stringify(data, null, 2); + try { + if (append) { + // Append the data to the end of the file. This is the simplest way to append. + await fs.appendFile(filePath, data, 'utf8'); + console.log(`Successfully appended data to ${filePath} using fs.appendFile.`); + } else { + // Overwrite the file with the new data. + await fs.writeFile(filePath, data, 'utf8'); + console.log(`Successfully wrote (overwrote) data to ${filePath} using fs.writeFile.`); + } + } catch (error) { + console.error(`Error writing to file ${filePath}:`, error); + } +} + + + /** + * Checks if an item is present in an array and adds it if it's not. + * * @param {Array} arr The array to check. + * @param {*} item The item to add. + * @returns {Array} The modified array. + */ +const addToArrayIfUnique = (arr, item) => { + if (!arr.includes(item)) { + arr.push(item); + } + return arr; +}; + + +var convertBase = function() { + + function convertBase(baseFrom, baseTo) { + return function(num) { + return parseInt(num, baseFrom).toString(baseTo); + + }; + } + + // binary to decimal + convertBase.bin2dec = convertBase(2, 10); + + // binary to hexadecimal + convertBase.bin2hex = convertBase(2, 16); + + // decimal to binary + convertBase.dec2bin = convertBase(10, 2); + + // decimal to hexadecimal + convertBase.dec2hex = convertBase(10, 16); + + // hexadecimal to binary + convertBase.hex2bin = convertBase(16, 2); + + // hexadecimal to decimal + convertBase.hex2dec = convertBase(16, 10); + + return convertBase; +}(); + +module.exports = { + bytesToInt, + longToByteArray, + addDays, + addZeroBefore, + resizeArray, + isEmptyObject, + emptyJsObject, + sleep, + convertUTCDateToLocalDate, + writeToFile, + addToArrayIfUnique +} diff --git a/RVO39/flow/httprequest.js b/RVO39/flow/httprequest.js new file mode 100755 index 0000000..469c8cb --- /dev/null +++ b/RVO39/flow/httprequest.js @@ -0,0 +1,137 @@ +exports.id = 'httprequest'; +exports.title = 'HTTP Request'; +exports.group = 'HTTP'; +exports.color = '#5D9CEC'; +exports.input = true; +exports.version = '2.0.1'; +exports.output = 1; +exports.author = 'Peter Širka'; +exports.icon = 'cloud-upload'; + +exports.html = `
+
@(URL address)
+
+
+
@(HTTP method)
+
+
+
@(Serialization)
+
+
+
@(Download the content in chunks)
+
@(Keep persistent cookies)
+
@(Disable DNS cache)
+
@(Keep alive connection)
+
+
+
+
@(Custom headers)
+
@(Cookies)
+
+
+
+ +
+
+
+
@(User)
+
+
+
@(Password)
+
+
+
+
+
`; + +exports.readme = `# Request + +This component creates a request with received data. + +__Response:__ +\`\`\`javascript +{ + data: String, + headers: Object, + status: Number, + host: String +} +\`\`\` + +__Dynamic arguments__: +Are performed via FlowData repository and can be used for URL address or for custom headers/cookies/auth. Use \`repository\` component for creating of dynamic arguments. Dynamic values are replaced in the form \`{key}\`: + +- url address e.g. \`https://.../{key}/\` +- headers values e.g. \`{token}\` +- cookies values e.g. \`{token}\``; + +exports.install = function(instance) { + + var can = false; + var flags = null; + var cookies2 = null; + + instance.on('data', function(response) { + can && instance.custom.send(response); + }); + + instance.custom.send = function(response) { + var options = instance.options; + + var headers = null; + var cookies = null; + + options.headers && Object.keys(options.headers).forEach(function(key) { + !headers && (headers = {}); + headers[key] = response.arg(options.headers[key]); + }); + + if (options.username && options.userpassword) { + !headers && (headers = {}); + headers['Authorization'] = 'Basic ' + U.createBuffer(response.arg(options.username + ':' + options.userpassword)).toString('base64'); + } + + options.cookies && Object.keys(options.cookies).forEach(function(key) { + !cookies && (cookies = {}); + cookies[key] = response.arg(options.cookies[key]); + }); + + if (options.chunks) { + U.download(response.arg(options.url), flags, options.stringify === 'none' ? null : response.data, function(err, response) { + response.on('data', (chunks) => instance.send2(chunks)); + }, cookies || cookies2, headers); + } else { + U.request(response.arg(options.url), flags, options.stringify === 'none' ? null : response.data, 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) + instance.error(err, response); + }, cookies || cookies2, headers); + } + }; + + instance.reconfigure = function() { + var options = instance.options; + can = options.url && options.url && options.method && options.stringify ? true : false; + instance.status(can ? '' : 'Not configured', can ? undefined : 'red'); + + if (!can) + return; + + flags = []; + flags.push(options.method.toLowerCase()); + options.stringify === 'json' && flags.push('json'); + options.stringify === 'raw' && flags.push('raw'); + options.keepalive && flags.push('keepalive'); + !options.nodns && flags.push('dnscache'); + if (options.persistentcookies) { + flags.push('cookies'); + cookies2 = {}; + } else + cookies2 = null; + }; + + instance.on('options', instance.reconfigure); + instance.reconfigure(); +}; \ No newline at end of file diff --git a/RVO39/flow/httpresponse.js b/RVO39/flow/httpresponse.js new file mode 100755 index 0000000..160a3bb --- /dev/null +++ b/RVO39/flow/httpresponse.js @@ -0,0 +1,76 @@ +exports.id = 'httpresponse'; +exports.title = 'HTTP Response'; +exports.group = 'HTTP'; +exports.color = '#5D9CEC'; +exports.icon = 'arrow-right'; +exports.input = true; +exports.output = ['#666D76']; +exports.version = '2.0.0'; +exports.author = 'Martin Smola'; +exports.readme = `# HTTP response + +HTTP response will respond with data recieved using data-type set in Settings form or plain text if not set. Output is the message duration \`Number\` in seconds.`; + +exports.html = `
+
@(Response data-type)
+
JSON is by default.
+
`; + +exports.install = function(instance) { + + var dursum = 0; + var durcount = 0; + + instance.on('data', function(flowdata) { + + var ctrl = flowdata.repository.controller; + var data = flowdata.data; + + if (!ctrl) { + instance.throw('No controller to use for response!'); + return; + } + + durcount++; + dursum += ((new Date() - flowdata.begin) / 1000).floor(2); + setTimeout2(instance.id, instance.custom.duration, 500, 10); + + ctrl.$flowdata = flowdata; + + var datatype = instance.options.datatype || 'json'; + if (datatype === 'emptyresponse') + return ctrl.plain(''); + + if (datatype !== 'json' && typeof(data) !== 'string') { + instance.throw('Incorect type of data, expected string, got ' + typeof(data)); + ctrl.plain(data == null ? '' : data.toString()); + return; + } + + switch(datatype) { + case 'html': + ctrl.content(data, 'text/html'); + break; + case 'plain': + ctrl.plain(data); + break; + case 'xml': + ctrl.content(data, 'text/xml'); + break; + default: + ctrl.json(data); + break; + } + }); + + instance.on('service', function() { + dursum = 0; + durcount = 0; + }); + + instance.custom.duration = function() { + var avg = (dursum / durcount).floor(2); + instance.status(avg + ' sec.'); + instance.send2(0, avg); + }; +}; diff --git a/RVO39/flow/httproute.js b/RVO39/flow/httproute.js new file mode 100755 index 0000000..583a19d --- /dev/null +++ b/RVO39/flow/httproute.js @@ -0,0 +1,326 @@ +exports.id = 'httproute'; +exports.title = 'HTTP Route'; +exports.group = 'HTTP'; +exports.color = '#5D9CEC'; +exports.icon = 'globe'; +exports.input = false; +exports.output = ['#6CAC5A', '#37BC9B']; +exports.version = '1.2.3'; +exports.author = 'Martin Smola'; +exports.cloning = false; +exports.options = { method: 'GET', url: '', size: 5, cacheexpire: '5 minutes', cachepolicy: 0, timeout: 5 }; +exports.dateupdated = '2021-01-21 18:30d'; +exports.readme = `# HTTP route + +__Outputs__: +- first output: raw data (cache is empty or is disabled) +- second output: cached data + +If one of the outputs is disabled then automatic responce with code "503 service unavailable" is sent. + +When a request comes in bellow object is available at \`flowdata.data\`: + +\`\`\`javascript +{ + params: { id: '1' }, // params for dynamic routes, e.g. /test/{id} + query: { msg: 'Hello' }, // parsed query string, e.g. /test/1?msg=Hello + body: { test: 'OK' }, // object if json requests otherwise string + headers: {}, // headers data + session: {}, // session data + user: {}, // user data + files: [], // uploaded files + url: '/users/', // a relative URL address + referrer: '/', // referrer + mobile: false, // determines mobile device + robot: false, // determines search robots/crawlsers + language: 'en' // determines language +} +\`\`\` + +See [documentation for flags](https://docs.totaljs.com/latest/en.html#api~HttpRouteOptionsFlags~unauthorize). These method flags are set automatically e.g. \`get, post, put, patch or delete\` + +--- + +\`id:ROUTE_ID\` flag cannot be used since it's already used by this component internally`; + +exports.html = `
+
+ +
+ +
+
+
@(HTTP method)
+
+
+
@(URL address)
+
+
+
+
+
@(Additional flags)
+
@(Separate flags by comma e.g. json, authorize)
+
+
+
@(Max. request size)
+
@(In kB kilobytes)
+
+
+
@(Timeout)
+
@(In seconds.)
+
+
+
+
+
+
@(Automatically respond with 200 OK?)
+
@(If not checked you need to use HTTP response component to respond to the request.)
+
+
@(Custom headers)
+
@(Cookies)
+
+
+
+
+
+
@(Cache policy)
+
@(User instance must contain id property.)
+
+
+
@(Expiration)
+
@(E.g. 5 minutes)
+
+
+
+`; + +exports.install = function(instance) { + + var route; + + var uninstall = function(id) { + if (F.is4) { + route && route.remove(); + route = null; + } else + UNINSTALL('route', id); + }; + + instance.custom.emptyresponse = function(self) { + self.plain(); + }; + + instance.reconfigure = function() { + + var options = instance.options; + + if (!options.url) { + instance.status('Not configured', 'red'); + return; + } + + if (typeof(options.flags) === 'string') + options.flags = options.flags.split(',').trim(); + + uninstall('id:' + instance.id); + + var flags = options.flags || []; + + flags.push('id:' + instance.id); + + if (!F.is4) + flags.push(options.method.toLowerCase()); + + options.timeout && flags.push(options.timeout * 1000); + + // Make unique values + flags = flags.filter(function(v, i, a) { + if(F.is4 && v.toString().toLowerCase() === options.method.toLowerCase()) + return false; // remove method + return a.indexOf(v) === i; + }); + + options.flags = flags; + var handler = function() { + + if (instance.paused || (instance.isDisabled && (instance.isDisabled('output', 0) || instance.isDisabled('output', 1)))) { + instance.status('503 Service Unavailable'); + this.status = 503; + this.json(); + return; + } + + var key; + var self = this; + + if (instance.options.emptyresponse) { + instance.status('200 OK'); + setTimeout(instance.custom.emptyresponse, 100, self); + + if (instance.hasConnection(0)) { + var data = instance.make({ + query: self.query, + body: self.body, + session: self.session, + user: self.user, + files: self.files, + headers: self.req.headers, + url: self.url, + params: self.params + }); + instance.send2(0, data); + } + + return; + } + + switch (instance.options.cachepolicy) { + case 1: // URL + key = 'rro' + instance.id + self.url.hash(); + break; + case 2: // URL + query + case 3: // URL + query + user + key = self.url; + var keys = Object.keys(self.query); + keys.sort(); + for (var i = 0, length = keys.length; i < length; i++) + key += keys[i] + self.query[keys[i]] + '&'; + if (instance.options.cachepolicy === 3 && self.user) + key += 'iduser' + self.user.id; + key = 'rro' + instance.id + key.hash(); + break; + } + + if (key && F.cache.get2(key)) { + var data = instance.make(F.cache.get2(key)); + data.repository.controller = self; + instance.send2(1, data); + } else { + + var data = instance.make({ + query: self.query, + body: self.body, + session: self.session, + user: self.user, + files: self.files, + headers: self.req.headers, + url: self.url, + params: self.params, + mobile: self.mobile, + robot: self.robot, + referrer: self.referrer, + language: self.language + }); + + data.repository.controller = self; + instance.send2(0, data); + key && FINISHED(self.res, () => F.cache.set(key, self.$flowdata.data, instance.options.cacheexpire)); + } + }; + + if (F.is4) + route = ROUTE(options.method.toUpperCase() + ' ' + options.url, handler, flags, options.size || 5); + else + F.route(options.url, handler, flags, options.size || 5); + + instance.status('Listening', 'green'); + }; + + instance.reconfigure(); + instance.on('options', instance.reconfigure); + instance.on('close', function(){ + uninstall('id:' + instance.id); + }); +}; + +// check url exists +FLOW.trigger('httproutecheckurl', function(next, data) { + var url = data.url; + var method = data.method; + if (url[url.length - 1] !== '/') + url += '/'; + var exists = F.routes.web.findItem(r => r.urlraw === url && r.method === method); + next(exists != null); +}); + +exports.uninstall = function() { + FLOW.trigger('httproutecheckurl', null); +}; diff --git a/RVO39/flow/infosender.js b/RVO39/flow/infosender.js new file mode 100755 index 0000000..587724f --- /dev/null +++ b/RVO39/flow/infosender.js @@ -0,0 +1,81 @@ +exports.id = 'infosender'; +exports.title = 'Info sender'; +exports.version = '1.0.0'; +exports.group = 'Worksys'; +exports.color = '#2134B0'; +exports.input = 2; +exports.output = 1 +exports.icon = 'bolt'; + +const { networkInterfaces } = require('os'); + +exports.html = `
+
+
+
CSV Import
+
+
+
`; + +exports.readme = `# send all data to projects.worksys.io, required to monitor status of controller(unipi)`; + +exports.install = function(instance) { + + let id; + let allValues = {}; + let sendAllValuesInterval; + let configured = false; + + let now = new Date(); + console.log(exports.title, "INSTALLED", now.toLocaleString("sk-SK")); + + const nets = networkInterfaces(); + let ipAddresses = Object.create(null); // Or just '{}', an empty object + + for (const name of Object.keys(nets)) { + for (const net of nets[name]) { + // Skip over non-IPv4 and internal (i.e. 127.0.0.1) addresses + if (net.family === 'IPv4' && !net.internal) { + if (!ipAddresses[name]) { + ipAddresses[name] = []; + } + ipAddresses[name].push(net.address); + } + } + } + + function sendValues() { + if (!configured) return; + + if (Object.keys(allValues).length > 0) { + let dataToSend = { ...allValues }; + dataToSend.id = id; + dataToSend.ipAddresses = ipAddresses; + + instance.send(0, dataToSend); + + allValues = {}; + } + } + + instance.on("close", () => { + clearInterval(sendAllValuesInterval); + }) + + instance.on("0", _ => { + id = FLOW.GLOBALS.settings.project_id; + if (id) configured = true; + else console.log(exports.title, "InfoSender: Unable to send data, no id"); + }) + + instance.on("1", flowdata => { + allValues = { ...allValues, ...flowdata.data }; + //console.log("DATA RECEIVED", flowdata.data); + }) + + sendAllValuesInterval = setInterval(() => { + sendValues(); + }, 60000 * 3); + +} + diff --git a/RVO39/flow/modbus_reader.js b/RVO39/flow/modbus_reader.js new file mode 100755 index 0000000..d6d9dad --- /dev/null +++ b/RVO39/flow/modbus_reader.js @@ -0,0 +1,346 @@ +exports.id = 'modbus_reader'; +exports.title = 'Modbus reader'; +exports.version = '2.0.0'; +exports.group = 'Worksys'; +exports.color = '#2134B0'; +exports.input = 1; +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; +//number of phases inRVO +let phases; +//phases where voltage is 0 (set) +let noVoltage; +let energyToSwitchLamps; + +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.phases = this.buildPhases(); + + this.startSocket(); + } + + buildPhases = () => { + let a = []; + for (let i = 1; i <= phases; i++) { + a.push(`Phase_${i}_voltage`) + } + return a; + } + + startSocket = () => { + + let obj = this; + + if (this.socket) { + this.socket.removeAllListeners(); + this.socket = null; + } + + 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('Modbus_reader: Socket connection error', e); //'ECONNREFUSED' or 'ECONNRESET' ?? + }); + + this.socket.on('close', function() { + console.log('Modbus_reader: Socket connection closed - Waiting 10 seconds before connecting 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 we just start to loop devices from the beginning, or there is just 1 device in config, we wait whole timeoutInterval + if (this.indexInDeviceConfig == 0 || deviceConfig.length === 1) 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 (this.phases.includes(singleValue)) { + let l = singleValue.split("_"); + let phase = parseInt(l[1]); + + // console.log(values[singleValue], tbName); + + if (values[singleValue] == 0) { + noVoltage.add(phase); + sendNotification("modbus_reader: checkNullVoltage", tbName, "no_voltage_on_phase", { phase: phase }, "", SEND_TO.tb, instance, "voltage" + phase); + // console.log('no voltage') + } + else { + noVoltage.delete(phase); + // console.log('voltage detected') + sendNotification("modbus_reader: checkNullVoltage", tbName, "voltage_on_phase_restored", { phase: phase }, "", SEND_TO.tb, instance, "voltage" + phase); + } + } + }) + } + + /** + * function sends notification to slack and to tb, if EM total_power value changes more than numberOfNodes*15. This should show, that RVO lamps has been switched on or off + */ + lampSwitchNotification = (values) => { + + if (!values.hasOwnProperty("total_power")) return; + + const actualTotalPower = values.total_power; + + if (actualTotalPower > energyToSwitchLamps && 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 <= energyToSwitchLamps && 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; + } + + function main() { + + phases = FLOW.GLOBALS.settings.phases; + tbName = FLOW.GLOBALS.settings.rvoTbName; + noVoltage = FLOW.GLOBALS.settings.no_voltage; + energyToSwitchLamps = FLOW.GLOBALS.settings.energy_to_switch_lamps / 2.5; //half value is enought to show if lamps are turned on or off + if (deviceConfig.length) mainSocket = new SocketWithClients(); + else console.log("Modbus_reader: no modbus device in configuration"); + + // this notification is to show, that flow (unipi) has been restarted + sendNotification("modbus_reader", tbName, "flow_restart", {}, "", SEND_TO.slack, instance); + } + + instance.on("0", function(_) { + main(); + }) + +} + diff --git a/RVO39/flow/monitorconsumption.js b/RVO39/flow/monitorconsumption.js new file mode 100755 index 0000000..64cc58e --- /dev/null +++ b/RVO39/flow/monitorconsumption.js @@ -0,0 +1,156 @@ +exports.id = 'monitorconsumption'; +exports.title = 'Consumption'; +exports.version = '1.0.0'; +exports.author = 'Peter Širka'; +exports.group = 'Monitoring'; +exports.color = '#967ADC'; +exports.input = 0; +exports.output = 1; +exports.icon = 'bug'; +exports.options = { interval: 5000, enabled: true, monitorconsumption: true, monitorsize: true, monitorconnections: true, monitorfiles: true }; +exports.click = true; +exports.readme = `# Consumption monitoring + +This component measure CPU and memory consumption, open files and open connections of this application. It uses these Linux commands: \`ps\`, \`lsof\`, \`netstat\` and \`df\`. + +__Data Example__: + +\`\`\`javascript +{ + cpu: 0, // percentage + memory: 4096, // in bytes + size: 34303, // directory size in bytes + files: 34, // count of open files + connections: 343, // count of connections + uptime: '1-12:34:00' +} +\`\`\``; + +exports.html = `
+
+
+
@(Interval in milliseconds)
+
+
+
+
Monitor: Consumption + uptime
+
Monitor: Count of open files
+
Monitor: Count of open connections
+
Monitor: Directory size
+
`; + +exports.install = function(instance) { + + var current = { cpu: 0, memory: 0, files: 0, connections: 0, size: 0, uptime: '', counter: 0 }; + var tproc = null; + var Exec = require('child_process').exec; + var reg_empty = /\s{2,}/g; + var reg_appdisksize = /^[\d.,]+/; + + instance.custom.run = function() { + + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + + var arr = []; + + // Get CPU and Memory consumption + instance.options.monitorconsumption && arr.push(function(next) { + Exec('ps -p {0} -o %cpu,rss,etime'.format(process.pid), function(err, response) { + + if (err) { + instance.throw(err); + } else { + var line = response.split('\n')[1]; + line = line.trim().replace(reg_empty, ' ').split(' '); + var cpu = line[0].parseFloat(); + current.cpu = cpu.floor(1); + current.memory = line[1].parseInt2() * 1024; // kB to bytes + current.uptime = line[2]; + } + + next(); + }); + }); + + // Get count of open files + instance.options.monitorfiles && arr.push(function(next) { + Exec('lsof -a -p {0} | wc -l'.format(process.pid), function(err, response) { + if (err) + instance.throw(err); + else + current.files = response.trim().parseInt2(); + next(); + }); + }); + + // Get count of opened network connections + instance.options.monitorconnections && arr.push(function(next) { + Exec('netstat -an | grep :{0} | wc -l'.format(F.port), function(err, response) { + if (err) { + instance.throw(err); + } else { + current.connections = response.trim().parseInt2() - 1; + if (current.connections < 0) + current.connections = 0; + } + next(); + }); + }); + + // Get directory size + instance.options.monitorsize && current.counter % 5 !== 0 && arr.push(function(next) { + Exec('du -hsb ' + process.cwd(), function(err, response) { + if (err) { + instance.throw(err); + } else { + var match = response.trim().match(reg_appdisksize); + match && (current.size = match.toString().trim().parseInt2()); + } + next(); + }); + }); + + arr.async(function() { + + tproc && clearTimeout(tproc); + + if (instance.options.enabled) { + tproc = setTimeout(instance.custom.run, instance.options.interval); + instance.send2(current); + } + + instance.custom.status(); + current.counter++; + }); + }; + + instance.custom.status = function() { + if (instance.options.enabled) + instance.status('{0}% / {1}'.format(current.cpu, current.memory.filesize())); + else + instance.status('Disabled', 'red'); + }; + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + + if (instance.options.enabled) { + current.counter = 0; + instance.custom.run(); + } + + }); + + instance.on('close', function() { + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + }); + + setTimeout(instance.custom.run, 1000); +}; \ No newline at end of file diff --git a/RVO39/flow/monitordisk.js b/RVO39/flow/monitordisk.js new file mode 100755 index 0000000..f4fdaa0 --- /dev/null +++ b/RVO39/flow/monitordisk.js @@ -0,0 +1,96 @@ +exports.id = 'monitordisk'; +exports.title = 'Disk'; +exports.version = '1.0.0'; +exports.author = 'Peter Širka'; +exports.group = 'Monitoring'; +exports.color = '#F6BB42'; +exports.output = 1; +exports.icon = 'hdd-o'; +exports.click = true; +exports.options = { interval: 8000, path: '/', enabled: true }; +exports.readme = `# Disk monitoring + +This component monitors disk \`bytes\` consumption in Linux systems. It uses \`df\` command. + +__Data Example__: + +\`\`\`javascript +{ + total: 474549649408, + used: 39125245952, + free: 411294994432 +} +\`\`\``; + +exports.html = `
+
+
+
@(Interval in milliseconds)
+
+
+
@(Path)
+
+
+
`; + +exports.install = function(instance) { + + var current = { total: 0, used: 0, free: 0, path: '', type: '', percentUsed: 0 }; + var tproc = null; + + instance.custom.run = function() { + + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + + if (!instance.options.enabled) + return; + + require('child_process').exec('df -hTB1 ' + instance.options.path, function(err, response) { + + tproc = setTimeout(instance.custom.run, instance.options.interval); + + if (err) { + instance.error(err); + return; + } + + response.parseTerminal(function(line) { + if (line[0][0] !== '/') + return; + current.total = line[2].parseInt(); + current.free = line[4].parseInt(); + current.used = line[3].parseInt(); + current.path = instance.options.path || '/'; + current.type = line[1]; + current.percentUsed = line[5]; + instance.custom.status(); + instance.send2(current); + }); + }); + }; + + instance.custom.status = function() { + if (instance.options.enabled) + instance.status(current.free.filesize() + ' / ' + current.total.filesize()); + else + instance.status('Disabled', 'red'); + }; + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + instance.options.enabled && instance.custom.run(); + }); + + instance.on('close', function() { + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + }); + + setTimeout(instance.custom.run, 1000); +}; \ No newline at end of file diff --git a/RVO39/flow/monitormemory.js b/RVO39/flow/monitormemory.js new file mode 100755 index 0000000..2decbc4 --- /dev/null +++ b/RVO39/flow/monitormemory.js @@ -0,0 +1,87 @@ +exports.id = 'monitormemory'; +exports.title = 'Memory'; +exports.version = '1.0.0'; +exports.author = 'Peter Širka'; +exports.group = 'Monitoring'; +exports.color = '#F6BB42'; +exports.output = 1; +exports.click = true; +exports.icon = 'microchip'; +exports.options = { interval: 8000, enabled: true }; +exports.readme = `# Memory monitoring + +This component monitors memory \`bytes\` consumption in Linux systems. It uses \`free\` command. + +__Data Example__: + +\`\`\`javascript +{ + total: 33558769664, + used: 1998868480, + free: 2653708288 +} +\`\`\``; + +exports.html = `
+
+
+
@(Interval in milliseconds)
+
+
+
`; + +exports.install = function(instance) { + + var current = { total: 0, used: 0, free: 0 }; + var tproc = null; + + instance.custom.run = function() { + + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + + if (!instance.options.enabled) + return; + + require('child_process').exec('free -b -t', function(err, response) { + + tproc = setTimeout(instance.custom.run, instance.options.interval); + + if (err) { + instance.error(err); + return; + } + + var memory = response.split('\n')[1].match(/\d+/g); + current.total = memory[0].parseInt(); + current.used = memory[1].parseInt() - memory[3].parseInt(); + current.free = current.total - current.used; + instance.custom.status(); + instance.send2(current); + }); + }; + + instance.custom.status = function() { + if (instance.options.enabled) + instance.status(current.free.filesize() + ' / ' + current.total.filesize()); + else + instance.status('Disabled', 'red'); + }; + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + instance.options.enabled && instance.custom.run(); + }); + + instance.on('close', function() { + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + }); + + setTimeout(instance.custom.run, 1000); +}; \ No newline at end of file diff --git a/RVO39/flow/nodesdb_changecheck.js b/RVO39/flow/nodesdb_changecheck.js new file mode 100755 index 0000000..9adab62 --- /dev/null +++ b/RVO39/flow/nodesdb_changecheck.js @@ -0,0 +1,77 @@ +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 = 2; +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); + } + } + + //kedze do slacku posielame stringy, na cloud musime previest vsetky stringy spat na objekty: + // Funkcia na parsovanie všetkých reťazcov v poli + const parseArray = (arr) => { + return arr.map(jsonString => JSON.parse(jsonString)); + }; + + 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); + if (FLOW.GLOBALS.settings.send_changed_node_numbers) instance.send(1, { aktualneNody: parseArray(zmenene), originalne: parseArray(Array.from(set2)) }); + } + 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/RVO39/flow/show_dbdata.js b/RVO39/flow/show_dbdata.js new file mode 100755 index 0000000..1e23ff7 --- /dev/null +++ b/RVO39/flow/show_dbdata.js @@ -0,0 +1,243 @@ +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 = 8; +exports.output = 1; + +const { exec } = require('child_process'); + +exports.install = 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 }) + }) + instance.on("5", _ => { + exec("sudo tail -n 25 monitor.txt", (err, stdout, stderr) => { + if (err || stderr) instance.send(0, { err, stderr }); + else instance.send(0, stdout); + }) + }) + instance.on("6", _ => { + exec("sudo tail -n 25 err.txt", (err, stdout, stderr) => { + if (err || stderr) instance.send(0, { err, stderr }); + else instance.send(0, stdout); + }) + }) + instance.on("7", _ => { + instance.send(0, FLOW.deviceStatus); + }) +}; + + +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/RVO39/flow/slack_filter.js b/RVO39/flow/slack_filter.js new file mode 100755 index 0000000..6618523 --- /dev/null +++ b/RVO39/flow/slack_filter.js @@ -0,0 +1,188 @@ +exports.id = 'slack_filter'; +exports.title = 'Slack Filter'; +exports.group = 'Citysys'; +exports.color = '#30E193'; +exports.input = 2; +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 = `
+
+
+
@(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('0', 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']['en']; + 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"] = []; + } + + instance.options.name = FLOW.GLOBALS.settings.rvo_name; + if (instance.options.name) { + instance.status('Running'); + running = true; + } else { + instance.status('Please run options again', 'red'); + running = false; + } + } catch (e) { + instance.error('Citysys connector: ' + e.message); + } + }; + + instance.on('options', instance.reconfigure); + + instance.on("1", _ => { + instance.reconfigure(); + }) +}; diff --git a/RVO39/flow/thermometer.js b/RVO39/flow/thermometer.js new file mode 100755 index 0000000..fc7074d --- /dev/null +++ b/RVO39/flow/thermometer.js @@ -0,0 +1,99 @@ +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 = 5;//minutes +let NUMBER_OF_FAILURES_TO_SEND_ERROR = 13; + +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) => { + + 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); + setTimeout(main, 20000); + }) +}; diff --git a/RVO39/flow/trigger.js b/RVO39/flow/trigger.js new file mode 100755 index 0000000..27545a8 --- /dev/null +++ b/RVO39/flow/trigger.js @@ -0,0 +1,79 @@ +exports.id = 'trigger'; +exports.title = 'Trigger'; +exports.group = 'Inputs'; +exports.color = '#F6BB42'; +exports.click = true; +exports.output = 1; +exports.version = '1.1.0'; +exports.author = 'Martin Smola'; +exports.icon = 'play'; + +exports.html = `
+
@(Data type (String by default))
+
@(Data)
+
Trigger 5s after initialization.
+
@(Useful when there's a need to run certain flow when the app restarts, etc.)
+
`; + +exports.readme = `# Trigger + +- Clicking on the component starts the chain +- Settings allows to set a data-type and a value`; + +exports.install = function(instance) { + + var value; + + instance.on('click', () => instance.send2(value)); + + instance.reconfigure = function() { + var options = instance.options; + value = null; + switch (options.datatype) { + case 'integer': + value = options.data.parseInt2('error'); + value = value === 'error' ? NaN : value; + break; + case 'float': + value = options.data.parseFloat2('error'); + value = value === 'error' ? NaN : value; + break; + case 'date': + options.data = options.data.toString(); + var num = options.data.parseInt('error'); + num === 'error' && (num = options.data.parseDate('error')); + num === 'error' && (num = null); + value = num ? new Date(num).toUTCString() : num; + break; + case 'object': + try { + value = (new Function('return ' + options.data))(); + } catch (e) { + instance.error(e); + } + break; + case 'boolean': + value = options.data.parseBoolean(); + break; + case 'buffer': + try { + value = U.createBuffer(options.data); + } catch (e) { + instance.error(e); + } + break; + case 'string': + default: + value = '' + (options.data || ''); + break; + } + }; + + instance.on('options', instance.reconfigure); + instance.reconfigure(); + + if (instance.options.restart) + setTimeout(function(){ + instance.send2(value); + }, 5000); +}; diff --git a/RVO39/flow/variables.txt b/RVO39/flow/variables.txt new file mode 100755 index 0000000..e69de29 diff --git a/RVO39/flow/virtualwirein.js b/RVO39/flow/virtualwirein.js new file mode 100755 index 0000000..38a4e42 --- /dev/null +++ b/RVO39/flow/virtualwirein.js @@ -0,0 +1,43 @@ +exports.id = 'virtualwirein'; +exports.title = 'Virtual wire in'; +exports.version = '1.0.0'; +exports.author = 'Martin Smola'; +exports.color = '#303E4D'; +exports.icon = 'sign-in'; +exports.input = false; +exports.output = 1; +exports.options = {}; +exports.readme = `# Virtual wire in + +When the wires between the components are mess it's time to use Virtual wire.`; + +exports.html = `
+
@(Wire name)
+
+`; + +exports.install = function(instance) { + + instance.custom.reconfigure = function(options){ + if (instance.options.wirename) { + instance.status(instance.options.wirename); + } else + instance.status('Not configured', 'red'); + }; + + ON('virtualwire', function(wirename, flowdata){ + if (instance.options.wirename && instance.options.wirename === wirename) + instance.send(flowdata); + }); + + instance.on('options', instance.custom.reconfigure); + instance.custom.reconfigure(); +}; diff --git a/RVO39/flow/virtualwireout.js b/RVO39/flow/virtualwireout.js new file mode 100755 index 0000000..94a1e4f --- /dev/null +++ b/RVO39/flow/virtualwireout.js @@ -0,0 +1,41 @@ +exports.id = 'virtualwireout'; +exports.title = 'Virtual wire out'; +exports.version = '1.0.0'; +exports.author = 'Martin Smola'; +exports.color = '#303E4D'; +exports.icon = 'sign-out'; +exports.input = true; +exports.options = {}; +exports.readme = `# Virtual wire out + +When the wires between the components are mess it's time to use Virtual wire.`; + +exports.html = `
+
@(Wire name)
+
+`; + +exports.install = function(instance) { + + instance.custom.reconfigure = function(){ + if (instance.options.wirename) { + instance.status(instance.options.wirename); + } else + instance.status('Not configured', 'red'); + }; + + instance.on('data', function(flowdata) { + EMIT('virtualwire', instance.options.wirename, flowdata); + }); + + instance.on('options', instance.custom.reconfigure); + instance.custom.reconfigure(); +}; diff --git a/RVO39/flow/wsmqttpublish.js b/RVO39/flow/wsmqttpublish.js new file mode 100755 index 0000000..0eba804 --- /dev/null +++ b/RVO39/flow/wsmqttpublish.js @@ -0,0 +1,448 @@ +exports.id = 'wsmqttpublish'; +exports.title = 'WS MQTT publish'; +exports.group = 'MQTT'; +exports.color = '#888600'; +exports.version = '1.0.2'; +exports.icon = 'sign-out'; +exports.input = 2; +exports.output = 3; +exports.options = { host: 'tb-stage.worksys.io', port: 1883, clientid: "", username: "" }; + +exports.html = `
+
+
+
Hostname or IP address (if not empty - setting will override db setting)
+
+
+
Port
+
+
+
+
+
@(Client id)
+
+
+
@(Username)
+
+
+
`; + + +exports.readme = ` +# WS MQTT Publish + +Version 1.0.3. + +Added: +- database collections, +- 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 = { + debug: 0, + rpcCall: 1, + services: 2 +} + +//CONFIG +let createTelemetryBackup = true; +let saveTelemetryOnError = true;//backup_on_failure overrides this value +//------------------------ + +let rollers; +if (createTelemetryBackup) rollers = require('streamroller'); + +const noSqlFileSizeLimit = 4194304;//use 5MB - 4194304 +let insertNoSqlCounter = 0; +let insertBackupNoSqlCounter = 0; +let processingData = false; + +let backup_on_failure = false;//== saveTelemetryOnError - create backup client 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; + +process.on('uncaughtException', function(err) { + + errLogger.error('uncaughtException:', err.message) + errLogger.error(err.stack); + + //TODO + //send to service + + //process.exit(1); +}) + +const nosql = NOSQL('tbdata'); +const nosqlBackup = NOSQL('/backup/tbdata'); + + +exports.install = function(instance) { + + var client; + var opts; + var clientReady = false; + + // wsmqtt status for notification purposes on projects.worksys.io database + let wsmqttName = null; + let sendWsStatusVar = null; + let wsmqtt_status = 'disconnected'; + + 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'; + } + + function sendWsStatus() { + instance.send(SEND_TO.services, { [wsmqttName]: wsmqtt_status }); + } + + + function main() { + if (!FLOW.dbLoaded) return; + + loadSettings(); + clearInterval(sendWsStatus); + sendWsStatusVar = setInterval(sendWsStatus, 180000); + } + + //set opts according to db settings + function loadSettings() { + + if (instance.options.host !== "") { + //override settings from database + var o = instance.options; + opts = { + host: o.host, + port: o.port, + clientId: o.clientid, + username: o.username, + rejectUnauthorized: false, + resubscribe: false + }; + + wsmqttName = getWsmqttName(o.host); + + console.log("wsmqttpublich -> loadSettings from instance.options", instance.options); + } + else { + + const SETTINGS = FLOW.GLOBALS.settings; + backup_on_failure = SETTINGS.backup_on_failure; + saveTelemetryOnError = backup_on_failure; + + restore_from_backup = SETTINGS.restore_from_backup; + restore_backup_wait = SETTINGS.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; + + opts = { + host: mqtt_host, + port: mqtt_port, + keepalive: 10, + clientId: mqtt_clientid, + username: mqtt_username, + rejectUnauthorized: false, + resubscribe: false + }; + + wsmqttName = getWsmqttName(mqtt_host); + } + + connectToTbServer(); + } + + function connectToTbServer() { + 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"); + //monitor.info("MQTT client connected"); + + sendClientError = true; + clientReady = true; + wsmqtt_status = 'connected'; + }); + + client.on('reconnect', function() { + instance.status("Reconnecting", "yellow"); + clientReady = false; + }); + + client.on('message', function(topic, message) { + // message is type of buffer + message = message.toString(); + if (message[0] === '{') { + TRY(function() { + + message = JSON.parse(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 } }); + } + + }, () => instance.debug('MQTT: Error parsing data', message)); + } + + instance.send(SEND_TO.rpcCall, { "topic": topic, "content": message }); + }); + + client.on('close', function() { + clientReady = false; + wsmqtt_status = 'disconnected'; + + instance.status("Disconnected", "red"); + instance.send(SEND_TO.debug, { "message": "Client CLOSE signal received !" }); + }); + + client.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; + wsmqtt_status = 'disconnected'; + }); + + } + + + instance.on("0", _ => { + main(); + }) + + + instance.on('1', function(data) { + + if (clientReady) { + //do we have some data in backup file? if any, process data from database + if (saveTelemetryOnError) { + //read telemetry data and send back to server + if (!processingData) processDataFromDatabase(); + } + + let stringifiedJson = JSON.stringify(data.data); + client.publish("v1/gateway/telemetry", stringifiedJson, { qos: 1 }); + + //backup telemetry + if (createTelemetryBackup) { + data.data.id = UID(); + nosqlBackup.insert(data.data); + + insertBackupNoSqlCounter++; + if (insertBackupNoSqlCounter > 150) { + let options = { compress: true }; + let path = __dirname + "/../databases/backup/tbdata.nosql"; + var stream = new rollers.RollingFileStream(path, noSqlFileSizeLimit, 150, options); + stream.write(""); + stream.end(); + + insertBackupNoSqlCounter = 0; + } + } + + } + 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 (saveTelemetryOnError) { + //create new file from tbdata.nosql, if file size exceeds given limit, and clear tbdata.nosql + makeBackupFromDbFile(); + + //write to tb + data.data.id = UID(); + nosql.insert(data.data); + } + } + }); + + + instance.close = function(done) { + if (clientReady) { + client.end(); + clearInterval(sendWsStatusVar); + } + }; + + + function getDbBackupFileCounter(type) { + var files = fs.readdirSync(__dirname + "/../databases"); + + let counter = 0; + for (var i = 0; i < files.length; i++) { + + if (files[i] == "tbdata.nosql") continue; + + if (files[i].endsWith(".nosql")) { + + let pos = files[i].indexOf("."); + if (pos > -1) { + + let fileCounter = counter; + let firstDigit = files[i].slice(0, pos); + + fileCounter = parseInt(firstDigit); + if (isNaN(fileCounter)) fileCounter = 0; + //console.log("getDbBackupFileCounter digit:", files[i], firstDigit, fileCounter, isNaN(fileCounter), type); + + if (type == "max") { + if (fileCounter > counter) { + counter = fileCounter; + } + } + else if (type == "min") { + if (counter == 0) counter = fileCounter; + + if (fileCounter < counter) { + counter = fileCounter; + } + } + } + } + + } + + if (type == "max") counter++; + + return counter; + } + + const makeBackupFromDbFile = async () => { + + if (!saveTelemetryOnError) return; + + //to avoid large file: tbdata.nosql + + //init value is 0! + if (insertNoSqlCounter > 0) { + --insertNoSqlCounter; + return; + } + + insertNoSqlCounter = 100; + + let source = __dirname + "/../databases/tbdata.nosql"; + + var stats = fs.statSync(source); + var fileSizeInBytes = stats.size; + + if (fileSizeInBytes > noSqlFileSizeLimit) { + + let counter = 1; + counter = getDbBackupFileCounter("max"); + + let destination = __dirname + "/../databases/" + counter + "." + "tbdata.nosql"; + + //make backup file + fs.copyFileSync(source, destination); + //fs.renameSync(p, p + "." + counter); + + //clear tbdata.nosql + fs.writeFileSync(source, ""); + fs.truncateSync(source, 0); + + } + } + + const processDataFromDatabase = async () => { + + if (restore_from_backup <= 0) return; + + //calculate diff + const now = new Date(); + let currentTime = now.getTime(); + let diff = currentTime - lastRestoreTime; + + if ((diff / 1000) < restore_backup_wait) { + //console.log("*********restore_backup_wait", diff, restore_backup_wait); + return; + } + + processingData = true; + + //get filename to process + let counter = getDbBackupFileCounter("min"); + + //we have some backup files + let dataBase = 'tbdata'; + + var nosql; + if (counter == 0) dataBase = 'tbdata'; + else dataBase = counter + "." + 'tbdata'; + + nosql = NOSQL(dataBase); + + //select all data - use limit restore_from_backup + let records = await promisifyBuilder(nosql.find().take(restore_from_backup)); + + for (let i = 0; i < records.length; i++) { + if (clientReady) { + + let item = records[i]; + let id = item.id; + + if (id !== undefined) { + //console.log("------------processDataFromDatabase - remove", id, dataBase, i); + + try { + + let message = JSON.parse(JSON.stringify(item)); + delete message.id; + + client.publish("v1/gateway/telemetry", JSON.stringify(message), { qos: 1 }); + + //remove from database + await promisifyBuilder(nosql.remove().where("id", id)); + + } catch (error) { + //process error + console.log("processDataFromDatabase", error); + } + + } + + } + else { + processingData = false; + return; + } + } + + if (records.length > 0) { + //clean backup file + if (counter > 0) nosql.clean(); + } + + //no data in db, remove + if (records.length == 0) { + if (counter > 0) nosql.drop(); + } + + const d = new Date(); + lastRestoreTime = d.getTime(); + + processingData = false; + + } + + instance.on('options', main); + //instance.reconfigure(); +}; diff --git a/RVO39/monitor.txt b/RVO39/monitor.txt new file mode 100755 index 0000000..8586106 --- /dev/null +++ b/RVO39/monitor.txt @@ -0,0 +1,216 @@ +[2025-10-09T19:09:41.005] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-09T19:09:46.347] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-09T19:09:46.352] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-09T19:09:46.353] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-09T19:09:46.354] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-09T19:09:46.358] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T19:09:46.360] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-10-10T05:32:00.359Z +[2025-10-09T19:09:46.361] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-10-10T16:45:00.361Z +[2025-10-09T19:09:46.362] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T19:09:46.363] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-10-09T19:09:46.364] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-09T19:09:46.365] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-09T19:09:46.367] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T19:09:46.368] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-10-10T05:32:00.368Z +[2025-10-09T19:09:46.369] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-10-10T16:45:00.368Z +[2025-10-09T19:09:46.369] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T19:09:46.371] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-10-09T19:09:46.371] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-09T19:09:46.372] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-09T19:09:46.374] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T19:09:46.375] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-10-10T05:32:00.375Z +[2025-10-09T19:09:46.376] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-10-10T16:45:00.376Z +[2025-10-09T19:09:46.376] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T19:09:46.377] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-10-09T19:09:46.381] [INFO] monitorLogs - tasks created: 490 +[2025-10-09T19:09:46.383] [INFO] monitorLogs - -->FLOW bol spustený 6lQGaY9RDywdVzObj0PadOkPg4NBn3exEK51LWZq 2025-08-08 +[2025-10-09T19:09:51.388] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-10T03:09:48.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-10 03:09:48 +[2025-10-10T06:54:29.588] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-10T06:54:29.591] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-10T06:54:29.594] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-10T18:21:13.647] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-10T18:21:13.650] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-10T18:21:13.652] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-11T03:09:49.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-11 03:09:49 +[2025-10-11T06:56:24.797] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-11T06:56:24.801] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-11T06:56:24.803] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-11T18:24:44.072] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-11T18:24:44.074] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-11T18:24:44.077] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-12T03:09:51.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-12 03:09:51 +[2025-10-12T06:53:55.786] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-12T06:53:55.792] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-12T06:53:55.794] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-12T18:22:05.084] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-12T18:22:05.087] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-12T18:22:05.089] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-13T03:09:52.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-13 03:09:52 +[2025-10-13T06:51:56.095] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-13T06:51:56.098] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-13T06:51:56.100] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-13T18:26:27.507] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-13T18:26:27.510] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-13T18:26:27.512] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-14T03:09:53.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-14 03:09:53 +[2025-10-14T06:53:46.148] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-14T06:53:46.152] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-14T06:53:46.154] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-14T18:17:24.357] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-14T18:17:24.359] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-14T18:17:24.361] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-15T03:09:55.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-15 03:09:55 +[2025-10-15T06:58:14.691] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-15T06:58:14.694] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-15T06:58:14.697] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-15T14:19:53.206] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-15T14:19:58.547] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-15T14:19:58.552] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-15T14:19:58.553] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-15T14:19:58.553] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-15T14:19:58.558] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-15T14:19:58.559] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-10-16T05:41:00.558Z +[2025-10-15T14:19:58.560] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-10-15T16:33:00.560Z +[2025-10-15T14:19:58.561] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:41', name: 'luxOff' }, + { value: 1, start_time: '18:33', name: 'luxOn' } +] +[2025-10-15T14:19:58.562] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-10-15T14:19:58.563] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-15T14:19:58.564] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-15T14:19:58.566] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-15T14:19:58.567] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-10-16T05:41:00.567Z +[2025-10-15T14:19:58.568] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-10-15T16:33:00.568Z +[2025-10-15T14:19:58.568] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:41', name: 'luxOff' }, + { value: 1, start_time: '18:33', name: 'luxOn' } +] +[2025-10-15T14:19:58.569] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-10-15T14:19:58.570] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-15T14:19:58.571] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-15T14:19:58.573] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-15T14:19:58.574] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-10-16T05:41:00.573Z +[2025-10-15T14:19:58.574] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-10-15T16:33:00.574Z +[2025-10-15T14:19:58.575] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:41', name: 'luxOff' }, + { value: 1, start_time: '18:33', name: 'luxOn' } +] +[2025-10-15T14:19:58.576] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-10-15T14:19:58.579] [INFO] monitorLogs - tasks created: 490 +[2025-10-15T14:19:58.582] [INFO] monitorLogs - -->FLOW bol spustený 6lQGaY9RDywdVzObj0PadOkPg4NBn3exEK51LWZq 2025-10-08 +[2025-10-15T14:20:03.588] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-15T18:15:40.935] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-15T18:15:40.942] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-15T18:15:40.944] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor diff --git a/RVO39/package-lock.json b/RVO39/package-lock.json new file mode 100755 index 0000000..39bad07 --- /dev/null +++ b/RVO39/package-lock.json @@ -0,0 +1,7470 @@ +{ + "name": "emptyproject", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "emptyproject", + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "bitwise": "^2.1.0", + "easy-crc": "0.0.2", + "jest": "^29.7.0", + "jsmodbus": "^4.0.6", + "log4js": "^6.3.0", + "moment": "^2.30.1", + "mqtt": "^4.2.6", + "nodemailer": "^6.9.7", + "serialport": "^9.2.8", + "total.js": "^3.4.13" + } + }, + "node_modules/@ampproject/remapping": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", + "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", + "dependencies": { + "@babel/helper-validator-identifier": "^7.25.9", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.26.3", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.3.tgz", + "integrity": "sha512-nHIxvKPniQXpmQLb0vhY3VaFb3S0YrTAwpOWJZh1wn3oJPjJk9Asva204PsBdmAE8vpzfHudT8DB0scYvy9q0g==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.0.tgz", + "integrity": "sha512-i1SLeK+DzNnQ3LL/CswPCa/E5u4lh1k6IAEphON8F+cXt0t9euTshDru0q7/IqMa1PMPz5RnHuHscF8/ZJsStg==", + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.26.0", + "@babel/generator": "^7.26.0", + "@babel/helper-compilation-targets": "^7.25.9", + "@babel/helper-module-transforms": "^7.26.0", + "@babel/helpers": "^7.26.0", + "@babel/parser": "^7.26.0", + "@babel/template": "^7.25.9", + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.26.0", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/generator": { + "version": "7.26.3", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.3.tgz", + "integrity": "sha512-6FF/urZvD0sTeO7k6/B15pMLC4CHUv1426lzr3N01aHJTl046uCAh9LXW/fzeXXjPNCJ6iABW5XaWOsIZB93aQ==", + "dependencies": { + "@babel/parser": "^7.26.3", + "@babel/types": "^7.26.3", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.9.tgz", + "integrity": "sha512-j9Db8Suy6yV/VHa4qzrj9yZfZxhLWQdVnRlXxmKLYlhWUVB1sB2G5sxuWYXk/whHD9iW76PmNzxZ4UCnTQTVEQ==", + "dependencies": { + "@babel/compat-data": "^7.25.9", + "@babel/helper-validator-option": "^7.25.9", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz", + "integrity": "sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==", + "dependencies": { + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz", + "integrity": "sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==", + "dependencies": { + "@babel/helper-module-imports": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9", + "@babel/traverse": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.25.9.tgz", + "integrity": "sha512-kSMlyUVdWe25rEsRGviIgOWnoT/nfABVWlqt9N19/dIPWViAOW2s9wznP5tURbs/IDuNk4gPy3YdYRgH3uxhBw==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", + "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", + "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz", + "integrity": "sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.26.0.tgz", + "integrity": "sha512-tbhNuIxNcVb21pInl3ZSjksLCvgdZy9KwJ8brv993QtIVKJBBkYXz4q4ZbAv31GdnC+R90np23L5FbEBlthAEw==", + "dependencies": { + "@babel/template": "^7.25.9", + "@babel/types": "^7.26.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.26.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.3.tgz", + "integrity": "sha512-WJ/CvmY8Mea8iDXo6a7RK2wbmJITT5fN3BEkRuFlxVyNx8jOKIIhmC4fSkTcPcf8JyavbBwIe6OpiCOBXt/IcA==", + "dependencies": { + "@babel/types": "^7.26.3" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-bigint": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", + "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.12.13" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", + "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-attributes": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.26.0.tgz", + "integrity": "sha512-e2dttdsJ1ZTpi3B9UYGLw41hifAubg19AtCu/2I/F1QNVclOBr1dYpTdmdyZ84Xiz43BS/tCUkMAZNLv12Pi+A==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.25.9.tgz", + "integrity": "sha512-ld6oezHQMZsZfp6pWtbjaNDF2tiiCYYDqQszHt5VV437lewP9aSi2Of99CK0D0XB21k7FLgnLcmQKyKzynfeAA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.25.9.tgz", + "integrity": "sha512-hjMgRy5hb8uJJjUcdWunWVcoi9bGpJp8p5Ol1229PoN6aytsLwNMgmdftO23wnCLMfVmTwZDWMPNq/D1SY60JQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/template": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.9.tgz", + "integrity": "sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg==", + "dependencies": { + "@babel/code-frame": "^7.25.9", + "@babel/parser": "^7.25.9", + "@babel/types": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.26.4", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.26.4.tgz", + "integrity": "sha512-fH+b7Y4p3yqvApJALCPJcwb0/XaOSgtK4pzV6WVjPR5GLFQBRI7pfoX2V2iM48NXvX07NUxxm1Vw98YjqTcU5w==", + "dependencies": { + "@babel/code-frame": "^7.26.2", + "@babel/generator": "^7.26.3", + "@babel/parser": "^7.26.3", + "@babel/template": "^7.25.9", + "@babel/types": "^7.26.3", + "debug": "^4.3.1", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.26.3", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.3.tgz", + "integrity": "sha512-vN5p+1kl59GVKMvTHt55NzzmYVxprfJD+ql7U9NFIfKCBkYE55LYtS+WtPlaYOyzydrKI8Nezd+aZextrd+FMA==", + "dependencies": { + "@babel/helper-string-parser": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@bcoe/v8-coverage": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==" + }, + "node_modules/@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "dependencies": { + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/console": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", + "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/core": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz", + "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==", + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/reporters": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-changed-files": "^29.7.0", + "jest-config": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-resolve-dependencies": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "jest-watcher": "^29.7.0", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/core/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/core/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/environment": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", + "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", + "dependencies": { + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", + "dependencies": { + "expect": "^29.7.0", + "jest-snapshot": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/expect-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", + "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", + "dependencies": { + "jest-get-type": "^29.6.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/fake-timers": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", + "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", + "dependencies": { + "@jest/types": "^29.6.3", + "@sinonjs/fake-timers": "^10.0.2", + "@types/node": "*", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/globals": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", + "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/types": "^29.6.3", + "jest-mock": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/reporters": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz", + "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", + "dependencies": { + "@bcoe/v8-coverage": "^0.2.3", + "@jest/console": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "@types/node": "*", + "chalk": "^4.0.0", + "collect-v8-coverage": "^1.0.0", + "exit": "^0.1.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-instrument": "^6.0.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.1.3", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "slash": "^3.0.0", + "string-length": "^4.0.1", + "strip-ansi": "^6.0.0", + "v8-to-istanbul": "^9.0.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/reporters/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/reporters/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/source-map": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", + "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.18", + "callsites": "^3.0.0", + "graceful-fs": "^4.2.9" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/test-result": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", + "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/test-sequencer": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz", + "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", + "dependencies": { + "@jest/test-result": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/transform": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", + "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", + "dependencies": { + "@babel/core": "^7.11.6", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "write-file-atomic": "^4.0.2" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "dependencies": { + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "dependencies": { + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@serialport/binding-abstract": { + "version": "9.2.3", + "resolved": "https://registry.npmjs.org/@serialport/binding-abstract/-/binding-abstract-9.2.3.tgz", + "integrity": "sha512-cQs9tbIlG3P0IrOWyVirqlhWuJ7Ms2Zh9m2108z6Y5UW/iVj6wEOiW8EmK9QX9jmJXYllE7wgGgvVozP5oCj3w==", + "dependencies": { + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/binding-mock": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/binding-mock/-/binding-mock-9.2.4.tgz", + "integrity": "sha512-dpEhACCs44oQhh6ajJfJdvQdK38Vq0N4W6iD/gdplglDCK7qXRQCMUjJIeKdS/HSEiWkC3bwumUhUufdsOyT4g==", + "dependencies": { + "@serialport/binding-abstract": "9.2.3", + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/bindings": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/@serialport/bindings/-/bindings-9.2.8.tgz", + "integrity": "sha512-hSLxTe0tADZ3LMMGwvEJWOC/TaFQTyPeFalUCsJ1lSQ0k6bPF04JwrtB/C81GetmDBTNRY0GlD0SNtKCc7Dr5g==", + "hasInstallScript": true, + "dependencies": { + "@serialport/binding-abstract": "9.2.3", + "@serialport/parser-readline": "9.2.4", + "bindings": "^1.5.0", + "debug": "^4.3.2", + "nan": "^2.15.0", + "prebuild-install": "^7.0.0" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-byte-length": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-byte-length/-/parser-byte-length-9.2.4.tgz", + "integrity": "sha512-sQD/iw4ZMU3xW9PLi0/GlvU6Y623jGeWecbMkO7izUo/6P7gtfv1c9ikd5h0kwL8AoAOpQA1lxdHIKox+umBUg==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-cctalk": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-cctalk/-/parser-cctalk-9.2.4.tgz", + "integrity": "sha512-T4TU5vQMwmo9AB3gQLFDWbfJXlW5jd9guEsB/nqKjFHTv0FXPdZ7DQ2TpSp8RnHWxU3GX6kYTaDO20BKzc8GPQ==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-delimiter": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-delimiter/-/parser-delimiter-9.2.4.tgz", + "integrity": "sha512-4nvTAoYAgkxFiXrkI+3CA49Yd43CODjeszh89EK+I9c8wOZ+etZduRCzINYPiy26g7zO+GRAb9FoPCsY+sYcbQ==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-inter-byte-timeout": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-inter-byte-timeout/-/parser-inter-byte-timeout-9.2.4.tgz", + "integrity": "sha512-SOAdvr0oBQIOCXX198hiTlxs4JTKg9j5piapw5tNq52fwDOWdbYrFneT/wN04UTMKaDrJuEvXq6T4rv4j7nJ5A==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-readline": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-readline/-/parser-readline-9.2.4.tgz", + "integrity": "sha512-Z1/qrZTQUVhNSJP1hd9YfDvq0o7d87rNwAjjRKbVpa7Qi51tG5BnKt43IV3NFMyBlVcRe0rnIb3tJu57E0SOwg==", + "dependencies": { + "@serialport/parser-delimiter": "9.2.4" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-ready": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-ready/-/parser-ready-9.2.4.tgz", + "integrity": "sha512-Pyi94Itjl6qAURwIZr/gmZpMAyTmKXThm6vL5DoAWGQjcRHWB0gwv2TY2v7N+mQLJYUKU3cMnvnATXxHm7xjxw==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-regex": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-regex/-/parser-regex-9.2.4.tgz", + "integrity": "sha512-sI/cVvPOYz+Dbv4ZdnW16qAwvXiFf/1pGASQdbveRTlgJDdz7sRNlCBifzfTN2xljwvCTZYqiudKvDdC1TepRQ==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/stream": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/stream/-/stream-9.2.4.tgz", + "integrity": "sha512-bLye8Ub4vUFQGmkh8qEqehr7SE7EJs2yDs0h9jzuL5oKi+F34CFmWkEErO8GAOQ8YNn7p6b3GxUgs+0BrHHDZQ==", + "dependencies": { + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==" + }, + "node_modules/@sinonjs/commons": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", + "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/@sinonjs/fake-timers": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", + "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", + "dependencies": { + "@sinonjs/commons": "^3.0.0" + } + }, + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.6.8", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", + "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.20.6", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.6.tgz", + "integrity": "sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==", + "dependencies": { + "@babel/types": "^7.20.7" + } + }, + "node_modules/@types/graceful-fs": { + "version": "4.1.9", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz", + "integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", + "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==" + }, + "node_modules/@types/istanbul-lib-report": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", + "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", + "dependencies": { + "@types/istanbul-lib-coverage": "*" + } + }, + "node_modules/@types/istanbul-reports": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", + "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", + "dependencies": { + "@types/istanbul-lib-report": "*" + } + }, + "node_modules/@types/node": { + "version": "22.10.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.2.tgz", + "integrity": "sha512-Xxr6BBRCAOQixvonOye19wnzyDiUtTeqldOOmj3CkeblonbccA12PFwlufvRdrpjXxqnmUaeiU5EOA+7s5diUQ==", + "dependencies": { + "undici-types": "~6.20.0" + } + }, + "node_modules/@types/stack-utils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", + "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==" + }, + "node_modules/@types/yargs": { + "version": "17.0.33", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz", + "integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@types/yargs-parser": { + "version": "21.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", + "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==" + }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "node_modules/are-we-there-yet": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", + "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/babel-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", + "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", + "dependencies": { + "@jest/transform": "^29.7.0", + "@types/babel__core": "^7.1.14", + "babel-plugin-istanbul": "^6.1.1", + "babel-preset-jest": "^29.6.3", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.8.0" + } + }, + "node_modules/babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-istanbul/node_modules/istanbul-lib-instrument": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", + "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", + "dependencies": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-istanbul/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/babel-plugin-jest-hoist": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", + "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", + "dependencies": { + "@babel/template": "^7.3.3", + "@babel/types": "^7.3.3", + "@types/babel__core": "^7.1.14", + "@types/babel__traverse": "^7.0.6" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/babel-preset-current-node-syntax": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.1.0.tgz", + "integrity": "sha512-ldYss8SbBlWva1bs28q78Ju5Zq1F+8BrqBZZ0VFhLBvhh6lCpC2o3gDJi/5DRLs9FgYZCnmPYIVFU4lRXCkyUw==", + "dependencies": { + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-bigint": "^7.8.3", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-import-attributes": "^7.24.7", + "@babel/plugin-syntax-import-meta": "^7.10.4", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/babel-preset-jest": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", + "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", + "dependencies": { + "babel-plugin-jest-hoist": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/base64-js": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", + "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==" + }, + "node_modules/bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "dependencies": { + "file-uri-to-path": "1.0.0" + } + }, + "node_modules/bitwise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/bitwise/-/bitwise-2.1.0.tgz", + "integrity": "sha512-XKgAhMXCh4H/3oNwAHAsAO0iC89s9cOiumgYwSHjSobGWxYjv62YhkL9QEdvGP151xypCtMlAfKK79GEcd2eRQ==" + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/bl/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.24.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.2.tgz", + "integrity": "sha512-ZIc+Q62revdMcqC6aChtW4jz3My3klmCO1fEmINZY/8J3EpBg5/A/D0AKmBveUh6pgoeycoMkVMko84tuYS+Gg==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "caniuse-lite": "^1.0.30001669", + "electron-to-chromium": "^1.5.41", + "node-releases": "^2.0.18", + "update-browserslist-db": "^1.1.1" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/bser": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", + "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", + "dependencies": { + "node-int64": "^0.4.0" + } + }, + "node_modules/buffer": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz", + "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==", + "dependencies": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + }, + "node_modules/buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001687", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001687.tgz", + "integrity": "sha512-0S/FDhf4ZiqrTUiQ39dKeUjYRjkv7lOZU1Dgif2rIqrTzX/1wV2hfKu9TOm1IHkdSijfLswxTFzl/cvir+SLSQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ] + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/char-regex": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", + "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", + "engines": { + "node": ">=10" + } + }, + "node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, + "node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "engines": { + "node": ">=8" + } + }, + "node_modules/cjs-module-lexer": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.1.tgz", + "integrity": "sha512-cuSVIHi9/9E/+821Qjdvngor+xpnlwnuwIyZOaLmHBVdXL+gP+I6QQB9VkO7RI77YIcTV+S1W9AreJ5eN63JBA==" + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/cliui/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", + "engines": { + "iojs": ">= 1.0.0", + "node": ">= 0.12.0" + } + }, + "node_modules/code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/collect-v8-coverage": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz", + "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==" + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/commist": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/commist/-/commist-1.1.0.tgz", + "integrity": "sha512-rraC8NXWOEjhADbZe9QBNzLAN5Q3fsTPQtBV+fEVj6xKIgDgNiEVE6ZNfHpZOqfQ21YUzfVNUXLOEZquYvQPPg==", + "dependencies": { + "leven": "^2.1.0", + "minimist": "^1.1.0" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "node_modules/concat-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", + "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", + "engines": [ + "node >= 6.0" + ], + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.0.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/concat-stream/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==" + }, + "node_modules/core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "node_modules/crc": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/crc/-/crc-3.4.0.tgz", + "integrity": "sha512-ycVC2+4/DLgXXq7QweYi2znhqDuZz6P5TQXnkQo8v15XY/5p/IWeZwsSE31Ifo8w15b8TWLsqhXOjXyilHuQxw==" + }, + "node_modules/create-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", + "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==", + "dependencies": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "prompts": "^2.0.1" + }, + "bin": { + "create-jest": "bin/create-jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/date-format": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.11.tgz", + "integrity": "sha512-VS20KRyorrbMCQmpdl2hg5KaOUsda1RbnsJg461FfrcyCUg+pkd0b40BSW4niQyTheww4DBXQnS7HwSrKkipLw==", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/dedent": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.3.tgz", + "integrity": "sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==", + "peerDependencies": { + "babel-plugin-macros": "^3.1.0" + }, + "peerDependenciesMeta": { + "babel-plugin-macros": { + "optional": true + } + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" + }, + "node_modules/detect-libc": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz", + "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==", + "engines": { + "node": ">=8" + } + }, + "node_modules/detect-newline": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", + "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/diff-sequences": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/duplexify": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.2.tgz", + "integrity": "sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw==", + "dependencies": { + "end-of-stream": "^1.4.1", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1", + "stream-shift": "^1.0.0" + } + }, + "node_modules/duplexify/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/easy-crc": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/easy-crc/-/easy-crc-0.0.2.tgz", + "integrity": "sha512-h6eqIdhJRe0p271/xZJbM/0klCi13mW5IB7ZEzEGH11yV4QXWAkD4yPErz0fXdhFrd6sZ4Q1k5Iky2kMsMNePw==" + }, + "node_modules/electron-to-chromium": { + "version": "1.5.72", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.72.tgz", + "integrity": "sha512-ZpSAUOZ2Izby7qnZluSrAlGgGQzucmFbN0n64dYzocYxnxV5ufurpj3VgEe4cUp7ir9LmeLxNYo8bVnlM8bQHw==" + }, + "node_modules/emittery": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", + "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sindresorhus/emittery?sponsor=1" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "engines": { + "node": ">=8" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", + "dependencies": { + "@jest/expect-utils": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" + }, + "node_modules/fb-watchman": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", + "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", + "dependencies": { + "bser": "2.1.1" + } + }, + "node_modules/file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/flatted": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", + "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==" + }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, + "node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha512-14x4kjc6lkD3ltw589k0NrPD6cCNTD6CWoVUNpB85+DrtONoZn+Rug6xZU5RvSC4+TZPxA5AnBibQYAvZn41Hg==", + "dependencies": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==" + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "engines": { + "node": ">=4" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/help-me": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/help-me/-/help-me-3.0.0.tgz", + "integrity": "sha512-hx73jClhyk910sidBB7ERlnhMlFsJJIBqSVMFDwPN8o2v9nmp5KgLq1Xz1Bf1fCMMZ6mPrX159iG0VLy/fPMtQ==", + "dependencies": { + "glob": "^7.1.6", + "readable-stream": "^3.6.0" + } + }, + "node_modules/help-me/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==" + }, + "node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + }, + "node_modules/import-local": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz", + "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==", + "dependencies": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + }, + "bin": { + "import-local-fixture": "fixtures/cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==" + }, + "node_modules/is-core-module": { + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz", + "integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==", + "dependencies": { + "number-is-nan": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-generator-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", + "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" + }, + "node_modules/istanbul-lib-coverage": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-instrument": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz", + "integrity": "sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==", + "dependencies": { + "@babel/core": "^7.23.9", + "@babel/parser": "^7.23.9", + "@istanbuljs/schema": "^0.1.3", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", + "dependencies": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-source-maps": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", + "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", + "dependencies": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-reports": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz", + "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==", + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", + "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", + "dependencies": { + "@jest/core": "^29.7.0", + "@jest/types": "^29.6.3", + "import-local": "^3.0.2", + "jest-cli": "^29.7.0" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/jest-changed-files": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz", + "integrity": "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==", + "dependencies": { + "execa": "^5.0.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-circus": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz", + "integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==", + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "dedent": "^1.0.0", + "is-generator-fn": "^2.0.0", + "jest-each": "^29.7.0", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0", + "pretty-format": "^29.7.0", + "pure-rand": "^6.0.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-cli": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz", + "integrity": "sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==", + "dependencies": { + "@jest/core": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "create-jest": "^29.7.0", + "exit": "^0.1.2", + "import-local": "^3.0.2", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "yargs": "^17.3.1" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/jest-config": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", + "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", + "dependencies": { + "@babel/core": "^7.11.6", + "@jest/test-sequencer": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-jest": "^29.7.0", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "deepmerge": "^4.2.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-circus": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "micromatch": "^4.0.4", + "parse-json": "^5.2.0", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@types/node": "*", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "ts-node": { + "optional": true + } + } + }, + "node_modules/jest-config/node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jest-diff": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", + "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", + "dependencies": { + "chalk": "^4.0.0", + "diff-sequences": "^29.6.3", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-docblock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz", + "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==", + "dependencies": { + "detect-newline": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-each": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz", + "integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==", + "dependencies": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "jest-util": "^29.7.0", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-environment-node": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", + "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-get-type": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-haste-map": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", + "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/graceful-fs": "^4.1.3", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "micromatch": "^4.0.4", + "walker": "^1.0.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "optionalDependencies": { + "fsevents": "^2.3.2" + } + }, + "node_modules/jest-leak-detector": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz", + "integrity": "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==", + "dependencies": { + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-matcher-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", + "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", + "dependencies": { + "chalk": "^4.0.0", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-message-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", + "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^29.6.3", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-mock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", + "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-pnp-resolver": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", + "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", + "engines": { + "node": ">=6" + }, + "peerDependencies": { + "jest-resolve": "*" + }, + "peerDependenciesMeta": { + "jest-resolve": { + "optional": true + } + } + }, + "node_modules/jest-regex-util": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", + "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-resolve": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz", + "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==", + "dependencies": { + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-pnp-resolver": "^1.2.2", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "resolve": "^1.20.0", + "resolve.exports": "^2.0.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-resolve-dependencies": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz", + "integrity": "sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==", + "dependencies": { + "jest-regex-util": "^29.6.3", + "jest-snapshot": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-runner": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz", + "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==", + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/environment": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "graceful-fs": "^4.2.9", + "jest-docblock": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-leak-detector": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-resolve": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-util": "^29.7.0", + "jest-watcher": "^29.7.0", + "jest-worker": "^29.7.0", + "p-limit": "^3.1.0", + "source-map-support": "0.5.13" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-runtime": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz", + "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==", + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/globals": "^29.7.0", + "@jest/source-map": "^29.6.3", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "cjs-module-lexer": "^1.0.0", + "collect-v8-coverage": "^1.0.0", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0", + "strip-bom": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-snapshot": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz", + "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==", + "dependencies": { + "@babel/core": "^7.11.6", + "@babel/generator": "^7.7.2", + "@babel/plugin-syntax-jsx": "^7.7.2", + "@babel/plugin-syntax-typescript": "^7.7.2", + "@babel/types": "^7.3.3", + "@jest/expect-utils": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0", + "chalk": "^4.0.0", + "expect": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "natural-compare": "^1.4.0", + "pretty-format": "^29.7.0", + "semver": "^7.5.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-validate": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", + "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", + "dependencies": { + "@jest/types": "^29.6.3", + "camelcase": "^6.2.0", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "leven": "^3.1.0", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-validate/node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jest-validate/node_modules/leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "engines": { + "node": ">=6" + } + }, + "node_modules/jest-watcher": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz", + "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==", + "dependencies": { + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "jest-util": "^29.7.0", + "string-length": "^4.0.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-worker": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", + "dependencies": { + "@types/node": "*", + "jest-util": "^29.7.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/js-sdsl": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz", + "integrity": "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/js-sdsl" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, + "node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsmodbus": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/jsmodbus/-/jsmodbus-4.0.6.tgz", + "integrity": "sha512-gCmjoaERErK5Rn9Lu/BN07fY13MoWV7JKgGzrnkPlQPdPxYcwDhLtYcmpFFpZ4J9NPZZBSezi1UkLZO/DnNppA==", + "dependencies": { + "crc": "3.4.0", + "debug": "^3.1.0" + }, + "bin": { + "jsmodbus": "bin/jsmodbus.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/jsmodbus/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "engines": { + "node": ">=6" + } + }, + "node_modules/leven": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", + "integrity": "sha1-wuep93IJTe6dNCAq6KzORoeHVYA=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" + }, + "node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/log4js": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.5.2.tgz", + "integrity": "sha512-DXtpNtt+KDOMT7RHUDIur/WsSA3rntlUh9Zg4XCdV42wUuMmbFkl38+LZ92Z5QvQA7mD5kAVkLiBSEH/tvUB8A==", + "dependencies": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "flatted": "^3.2.5", + "rfdc": "^1.3.0", + "streamroller": "^3.1.1" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/make-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/makeerror": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", + "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", + "dependencies": { + "tmpl": "1.0.5" + } + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==" + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" + }, + "node_modules/moment": { + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", + "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==", + "engines": { + "node": "*" + } + }, + "node_modules/mqtt": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/mqtt/-/mqtt-4.3.7.tgz", + "integrity": "sha512-ew3qwG/TJRorTz47eW46vZ5oBw5MEYbQZVaEji44j5lAUSQSqIEoul7Kua/BatBW0H0kKQcC9kwUHa1qzaWHSw==", + "dependencies": { + "commist": "^1.0.0", + "concat-stream": "^2.0.0", + "debug": "^4.1.1", + "duplexify": "^4.1.1", + "help-me": "^3.0.0", + "inherits": "^2.0.3", + "lru-cache": "^6.0.0", + "minimist": "^1.2.5", + "mqtt-packet": "^6.8.0", + "number-allocator": "^1.0.9", + "pump": "^3.0.0", + "readable-stream": "^3.6.0", + "reinterval": "^1.1.0", + "rfdc": "^1.3.0", + "split2": "^3.1.0", + "ws": "^7.5.5", + "xtend": "^4.0.2" + }, + "bin": { + "mqtt": "bin/mqtt.js", + "mqtt_pub": "bin/pub.js", + "mqtt_sub": "bin/sub.js" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/mqtt-packet": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/mqtt-packet/-/mqtt-packet-6.10.0.tgz", + "integrity": "sha512-ja8+mFKIHdB1Tpl6vac+sktqy3gA8t9Mduom1BA75cI+R9AHnZOiaBQwpGiWnaVJLDGRdNhQmFaAqd7tkKSMGA==", + "dependencies": { + "bl": "^4.0.2", + "debug": "^4.1.1", + "process-nextick-args": "^2.0.1" + } + }, + "node_modules/mqtt/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/nan": { + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.16.0.tgz", + "integrity": "sha512-UdAqHyFngu7TfQKsCBgAA6pWDkT8MAO7d0jyOecVhN5354xbLqdn8mV9Tat9gepAupm0bt2DbeaSC8vS52MuFA==" + }, + "node_modules/napi-build-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", + "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==" + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==" + }, + "node_modules/node-abi": { + "version": "3.22.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.22.0.tgz", + "integrity": "sha512-u4uAs/4Zzmp/jjsD9cyFYDXeISfUWaAVWshPmDZOFOv4Xl4SbzTXm53I04C2uRueYJ+0t5PEtLH/owbn2Npf/w==", + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/node-int64": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==" + }, + "node_modules/node-releases": { + "version": "2.0.19", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", + "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==" + }, + "node_modules/nodemailer": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.7.tgz", + "integrity": "sha512-rUtR77ksqex/eZRLmQ21LKVH5nAAsVicAtAYudK7JgwenEDZ0UIQ1adUGqErz7sMkWYxWTTU1aeP2Jga6WQyJw==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "dependencies": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "node_modules/number-allocator": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/number-allocator/-/number-allocator-1.0.14.tgz", + "integrity": "sha512-OrL44UTVAvkKdOdRQZIJpLkAdjXGTRda052sN4sO77bKEzYYqWKMBjQvrJFzqygI99gL6Z4u2xctPW1tB8ErvA==", + "dependencies": { + "debug": "^4.3.1", + "js-sdsl": "4.3.0" + } + }, + "node_modules/number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-locate/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pirates": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", + "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/prebuild-install": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.0.tgz", + "integrity": "sha512-CNcMgI1xBypOyGqjp3wOc8AAo1nMhZS3Cwd3iHIxOdAUbb+YxdNuM4Z5iIrZ8RLvOsf3F3bl7b7xGq6DjQoNYA==", + "dependencies": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^1.0.1", + "node-abi": "^3.3.0", + "npmlog": "^4.0.1", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + }, + "bin": { + "prebuild-install": "bin.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "node_modules/prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "dependencies": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/pure-rand": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz", + "integrity": "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ] + }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==" + }, + "node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/reinterval": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reinterval/-/reinterval-1.1.0.tgz", + "integrity": "sha1-M2Hs+jymwYKDOA3Qu5VG85D17Oc=" + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve": { + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "dependencies": { + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve.exports": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.3.tgz", + "integrity": "sha512-OcXjMsGdhL4XnbShKpAcSqPMzQoYkYyhbEaeSko47MjRP9NfEQMhZkXL1DoFlt9LWQn4YttrdnV6X2OiyzBi+A==", + "engines": { + "node": ">=10" + } + }, + "node_modules/rfdc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==" + }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/serialport": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/serialport/-/serialport-9.2.8.tgz", + "integrity": "sha512-FsWpMQgSJxi93JgWl5xM1f9/Z8IjRJuaUEoHqLf8FPBLw7gMhInuHOBhI2onQufWIYPGTz3H3oGcu1nCaK1EfA==", + "dependencies": { + "@serialport/binding-mock": "9.2.4", + "@serialport/bindings": "9.2.8", + "@serialport/parser-byte-length": "9.2.4", + "@serialport/parser-cctalk": "9.2.4", + "@serialport/parser-delimiter": "9.2.4", + "@serialport/parser-inter-byte-timeout": "9.2.4", + "@serialport/parser-readline": "9.2.4", + "@serialport/parser-ready": "9.2.4", + "@serialport/parser-regex": "9.2.4", + "@serialport/stream": "9.2.4", + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "engines": { + "node": ">=8" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==" + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "engines": { + "node": ">=8" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.13", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", + "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/split2": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", + "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", + "dependencies": { + "readable-stream": "^3.0.0" + } + }, + "node_modules/split2/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==" + }, + "node_modules/stack-utils": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", + "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", + "dependencies": { + "escape-string-regexp": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==" + }, + "node_modules/streamroller": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.1.1.tgz", + "integrity": "sha512-iPhtd9unZ6zKdWgMeYGfSBuqCngyJy1B/GPi/lTpwGpa3bajuX30GjUVd0/Tn/Xhg0mr4DOSENozz9Y06qyonQ==", + "dependencies": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "fs-extra": "^10.1.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/string-length": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", + "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", + "dependencies": { + "char-regex": "^1.0.2", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/string-length/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/string-length/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dependencies": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-bom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/tar-fs": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "dependencies": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tar-stream/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "dependencies": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/tmpl": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", + "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==" + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/total.js": { + "version": "3.4.13", + "resolved": "https://registry.npmjs.org/total.js/-/total.js-3.4.13.tgz", + "integrity": "sha512-lAH4gEixlPFbrE3xfKADAcHfO79IFq2wKa9GTsrgRzIR5MTg3mNH7+4IxvX1pK8faoYb/0oYSJ1YTsAa5hIFFQ==", + "bin": { + "total": "bin/totaljs", + "total.js": "bin/totaljs", + "totaljs": "bin/totaljs", + "totalpackage": "bin/tpm", + "tpm": "bin/tpm" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "engines": { + "node": ">=4" + } + }, + "node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, + "node_modules/undici-types": { + "version": "6.20.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", + "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==" + }, + "node_modules/universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz", + "integrity": "sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.0" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "node_modules/v8-to-istanbul": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz", + "integrity": "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.12", + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^2.0.0" + }, + "engines": { + "node": ">=10.12.0" + } + }, + "node_modules/walker": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", + "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", + "dependencies": { + "makeerror": "1.0.12" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "node_modules/write-file-atomic": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", + "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.7" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/ws": { + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + }, + "dependencies": { + "@ampproject/remapping": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", + "requires": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "@babel/code-frame": { + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", + "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", + "requires": { + "@babel/helper-validator-identifier": "^7.25.9", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" + } + }, + "@babel/compat-data": { + "version": "7.26.3", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.3.tgz", + "integrity": "sha512-nHIxvKPniQXpmQLb0vhY3VaFb3S0YrTAwpOWJZh1wn3oJPjJk9Asva204PsBdmAE8vpzfHudT8DB0scYvy9q0g==" + }, + "@babel/core": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.0.tgz", + "integrity": "sha512-i1SLeK+DzNnQ3LL/CswPCa/E5u4lh1k6IAEphON8F+cXt0t9euTshDru0q7/IqMa1PMPz5RnHuHscF8/ZJsStg==", + "requires": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.26.0", + "@babel/generator": "^7.26.0", + "@babel/helper-compilation-targets": "^7.25.9", + "@babel/helper-module-transforms": "^7.26.0", + "@babel/helpers": "^7.26.0", + "@babel/parser": "^7.26.0", + "@babel/template": "^7.25.9", + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.26.0", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "dependencies": { + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" + } + } + }, + "@babel/generator": { + "version": "7.26.3", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.3.tgz", + "integrity": "sha512-6FF/urZvD0sTeO7k6/B15pMLC4CHUv1426lzr3N01aHJTl046uCAh9LXW/fzeXXjPNCJ6iABW5XaWOsIZB93aQ==", + "requires": { + "@babel/parser": "^7.26.3", + "@babel/types": "^7.26.3", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", + "jsesc": "^3.0.2" + } + }, + "@babel/helper-compilation-targets": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.9.tgz", + "integrity": "sha512-j9Db8Suy6yV/VHa4qzrj9yZfZxhLWQdVnRlXxmKLYlhWUVB1sB2G5sxuWYXk/whHD9iW76PmNzxZ4UCnTQTVEQ==", + "requires": { + "@babel/compat-data": "^7.25.9", + "@babel/helper-validator-option": "^7.25.9", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "dependencies": { + "lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "requires": { + "yallist": "^3.0.2" + } + }, + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" + }, + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + } + } + }, + "@babel/helper-module-imports": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz", + "integrity": "sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==", + "requires": { + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" + } + }, + "@babel/helper-module-transforms": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz", + "integrity": "sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==", + "requires": { + "@babel/helper-module-imports": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9", + "@babel/traverse": "^7.25.9" + } + }, + "@babel/helper-plugin-utils": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.25.9.tgz", + "integrity": "sha512-kSMlyUVdWe25rEsRGviIgOWnoT/nfABVWlqt9N19/dIPWViAOW2s9wznP5tURbs/IDuNk4gPy3YdYRgH3uxhBw==" + }, + "@babel/helper-string-parser": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", + "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==" + }, + "@babel/helper-validator-identifier": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", + "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==" + }, + "@babel/helper-validator-option": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz", + "integrity": "sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==" + }, + "@babel/helpers": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.26.0.tgz", + "integrity": "sha512-tbhNuIxNcVb21pInl3ZSjksLCvgdZy9KwJ8brv993QtIVKJBBkYXz4q4ZbAv31GdnC+R90np23L5FbEBlthAEw==", + "requires": { + "@babel/template": "^7.25.9", + "@babel/types": "^7.26.0" + } + }, + "@babel/parser": { + "version": "7.26.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.3.tgz", + "integrity": "sha512-WJ/CvmY8Mea8iDXo6a7RK2wbmJITT5fN3BEkRuFlxVyNx8jOKIIhmC4fSkTcPcf8JyavbBwIe6OpiCOBXt/IcA==", + "requires": { + "@babel/types": "^7.26.3" + } + }, + "@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-bigint": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", + "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "requires": { + "@babel/helper-plugin-utils": "^7.12.13" + } + }, + "@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", + "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-syntax-import-attributes": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.26.0.tgz", + "integrity": "sha512-e2dttdsJ1ZTpi3B9UYGLw41hifAubg19AtCu/2I/F1QNVclOBr1dYpTdmdyZ84Xiz43BS/tCUkMAZNLv12Pi+A==", + "requires": { + "@babel/helper-plugin-utils": "^7.25.9" + } + }, + "@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-jsx": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.25.9.tgz", + "integrity": "sha512-ld6oezHQMZsZfp6pWtbjaNDF2tiiCYYDqQszHt5VV437lewP9aSi2Of99CK0D0XB21k7FLgnLcmQKyKzynfeAA==", + "requires": { + "@babel/helper-plugin-utils": "^7.25.9" + } + }, + "@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-syntax-typescript": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.25.9.tgz", + "integrity": "sha512-hjMgRy5hb8uJJjUcdWunWVcoi9bGpJp8p5Ol1229PoN6aytsLwNMgmdftO23wnCLMfVmTwZDWMPNq/D1SY60JQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.25.9" + } + }, + "@babel/template": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.9.tgz", + "integrity": "sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg==", + "requires": { + "@babel/code-frame": "^7.25.9", + "@babel/parser": "^7.25.9", + "@babel/types": "^7.25.9" + } + }, + "@babel/traverse": { + "version": "7.26.4", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.26.4.tgz", + "integrity": "sha512-fH+b7Y4p3yqvApJALCPJcwb0/XaOSgtK4pzV6WVjPR5GLFQBRI7pfoX2V2iM48NXvX07NUxxm1Vw98YjqTcU5w==", + "requires": { + "@babel/code-frame": "^7.26.2", + "@babel/generator": "^7.26.3", + "@babel/parser": "^7.26.3", + "@babel/template": "^7.25.9", + "@babel/types": "^7.26.3", + "debug": "^4.3.1", + "globals": "^11.1.0" + } + }, + "@babel/types": { + "version": "7.26.3", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.3.tgz", + "integrity": "sha512-vN5p+1kl59GVKMvTHt55NzzmYVxprfJD+ql7U9NFIfKCBkYE55LYtS+WtPlaYOyzydrKI8Nezd+aZextrd+FMA==", + "requires": { + "@babel/helper-string-parser": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9" + } + }, + "@bcoe/v8-coverage": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==" + }, + "@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "requires": { + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" + } + }, + "@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==" + }, + "@jest/console": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", + "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", + "requires": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0" + } + }, + "@jest/core": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz", + "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==", + "requires": { + "@jest/console": "^29.7.0", + "@jest/reporters": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-changed-files": "^29.7.0", + "jest-config": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-resolve-dependencies": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "jest-watcher": "^29.7.0", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "requires": { + "ansi-regex": "^5.0.1" + } + } + } + }, + "@jest/environment": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", + "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", + "requires": { + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0" + } + }, + "@jest/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", + "requires": { + "expect": "^29.7.0", + "jest-snapshot": "^29.7.0" + } + }, + "@jest/expect-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", + "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", + "requires": { + "jest-get-type": "^29.6.3" + } + }, + "@jest/fake-timers": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", + "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", + "requires": { + "@jest/types": "^29.6.3", + "@sinonjs/fake-timers": "^10.0.2", + "@types/node": "*", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + } + }, + "@jest/globals": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", + "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", + "requires": { + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/types": "^29.6.3", + "jest-mock": "^29.7.0" + } + }, + "@jest/reporters": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz", + "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", + "requires": { + "@bcoe/v8-coverage": "^0.2.3", + "@jest/console": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "@types/node": "*", + "chalk": "^4.0.0", + "collect-v8-coverage": "^1.0.0", + "exit": "^0.1.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-instrument": "^6.0.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.1.3", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "slash": "^3.0.0", + "string-length": "^4.0.1", + "strip-ansi": "^6.0.0", + "v8-to-istanbul": "^9.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "requires": { + "ansi-regex": "^5.0.1" + } + } + } + }, + "@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "requires": { + "@sinclair/typebox": "^0.27.8" + } + }, + "@jest/source-map": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", + "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", + "requires": { + "@jridgewell/trace-mapping": "^0.3.18", + "callsites": "^3.0.0", + "graceful-fs": "^4.2.9" + } + }, + "@jest/test-result": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", + "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", + "requires": { + "@jest/console": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + } + }, + "@jest/test-sequencer": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz", + "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", + "requires": { + "@jest/test-result": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "slash": "^3.0.0" + } + }, + "@jest/transform": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", + "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", + "requires": { + "@babel/core": "^7.11.6", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "write-file-atomic": "^4.0.2" + } + }, + "@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "requires": { + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + } + }, + "@jridgewell/gen-mapping": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "requires": { + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==" + }, + "@jridgewell/set-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==" + }, + "@jridgewell/sourcemap-codec": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==" + }, + "@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "requires": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "@serialport/binding-abstract": { + "version": "9.2.3", + "resolved": "https://registry.npmjs.org/@serialport/binding-abstract/-/binding-abstract-9.2.3.tgz", + "integrity": "sha512-cQs9tbIlG3P0IrOWyVirqlhWuJ7Ms2Zh9m2108z6Y5UW/iVj6wEOiW8EmK9QX9jmJXYllE7wgGgvVozP5oCj3w==", + "requires": { + "debug": "^4.3.2" + } + }, + "@serialport/binding-mock": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/binding-mock/-/binding-mock-9.2.4.tgz", + "integrity": "sha512-dpEhACCs44oQhh6ajJfJdvQdK38Vq0N4W6iD/gdplglDCK7qXRQCMUjJIeKdS/HSEiWkC3bwumUhUufdsOyT4g==", + "requires": { + "@serialport/binding-abstract": "9.2.3", + "debug": "^4.3.2" + } + }, + "@serialport/bindings": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/@serialport/bindings/-/bindings-9.2.8.tgz", + "integrity": "sha512-hSLxTe0tADZ3LMMGwvEJWOC/TaFQTyPeFalUCsJ1lSQ0k6bPF04JwrtB/C81GetmDBTNRY0GlD0SNtKCc7Dr5g==", + "requires": { + "@serialport/binding-abstract": "9.2.3", + "@serialport/parser-readline": "9.2.4", + "bindings": "^1.5.0", + "debug": "^4.3.2", + "nan": "^2.15.0", + "prebuild-install": "^7.0.0" + } + }, + "@serialport/parser-byte-length": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-byte-length/-/parser-byte-length-9.2.4.tgz", + "integrity": "sha512-sQD/iw4ZMU3xW9PLi0/GlvU6Y623jGeWecbMkO7izUo/6P7gtfv1c9ikd5h0kwL8AoAOpQA1lxdHIKox+umBUg==" + }, + "@serialport/parser-cctalk": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-cctalk/-/parser-cctalk-9.2.4.tgz", + "integrity": "sha512-T4TU5vQMwmo9AB3gQLFDWbfJXlW5jd9guEsB/nqKjFHTv0FXPdZ7DQ2TpSp8RnHWxU3GX6kYTaDO20BKzc8GPQ==" + }, + "@serialport/parser-delimiter": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-delimiter/-/parser-delimiter-9.2.4.tgz", + "integrity": "sha512-4nvTAoYAgkxFiXrkI+3CA49Yd43CODjeszh89EK+I9c8wOZ+etZduRCzINYPiy26g7zO+GRAb9FoPCsY+sYcbQ==" + }, + "@serialport/parser-inter-byte-timeout": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-inter-byte-timeout/-/parser-inter-byte-timeout-9.2.4.tgz", + "integrity": "sha512-SOAdvr0oBQIOCXX198hiTlxs4JTKg9j5piapw5tNq52fwDOWdbYrFneT/wN04UTMKaDrJuEvXq6T4rv4j7nJ5A==" + }, + "@serialport/parser-readline": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-readline/-/parser-readline-9.2.4.tgz", + "integrity": "sha512-Z1/qrZTQUVhNSJP1hd9YfDvq0o7d87rNwAjjRKbVpa7Qi51tG5BnKt43IV3NFMyBlVcRe0rnIb3tJu57E0SOwg==", + "requires": { + "@serialport/parser-delimiter": "9.2.4" + } + }, + "@serialport/parser-ready": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-ready/-/parser-ready-9.2.4.tgz", + "integrity": "sha512-Pyi94Itjl6qAURwIZr/gmZpMAyTmKXThm6vL5DoAWGQjcRHWB0gwv2TY2v7N+mQLJYUKU3cMnvnATXxHm7xjxw==" + }, + "@serialport/parser-regex": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-regex/-/parser-regex-9.2.4.tgz", + "integrity": "sha512-sI/cVvPOYz+Dbv4ZdnW16qAwvXiFf/1pGASQdbveRTlgJDdz7sRNlCBifzfTN2xljwvCTZYqiudKvDdC1TepRQ==" + }, + "@serialport/stream": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/stream/-/stream-9.2.4.tgz", + "integrity": "sha512-bLye8Ub4vUFQGmkh8qEqehr7SE7EJs2yDs0h9jzuL5oKi+F34CFmWkEErO8GAOQ8YNn7p6b3GxUgs+0BrHHDZQ==", + "requires": { + "debug": "^4.3.2" + } + }, + "@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==" + }, + "@sinonjs/commons": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", + "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", + "requires": { + "type-detect": "4.0.8" + } + }, + "@sinonjs/fake-timers": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", + "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", + "requires": { + "@sinonjs/commons": "^3.0.0" + } + }, + "@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "requires": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "@types/babel__generator": { + "version": "7.6.8", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", + "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "requires": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "@types/babel__traverse": { + "version": "7.20.6", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.6.tgz", + "integrity": "sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==", + "requires": { + "@babel/types": "^7.20.7" + } + }, + "@types/graceful-fs": { + "version": "4.1.9", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz", + "integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==", + "requires": { + "@types/node": "*" + } + }, + "@types/istanbul-lib-coverage": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", + "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==" + }, + "@types/istanbul-lib-report": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", + "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", + "requires": { + "@types/istanbul-lib-coverage": "*" + } + }, + "@types/istanbul-reports": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", + "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", + "requires": { + "@types/istanbul-lib-report": "*" + } + }, + "@types/node": { + "version": "22.10.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.2.tgz", + "integrity": "sha512-Xxr6BBRCAOQixvonOye19wnzyDiUtTeqldOOmj3CkeblonbccA12PFwlufvRdrpjXxqnmUaeiU5EOA+7s5diUQ==", + "requires": { + "undici-types": "~6.20.0" + } + }, + "@types/stack-utils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", + "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==" + }, + "@types/yargs": { + "version": "17.0.33", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz", + "integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==", + "requires": { + "@types/yargs-parser": "*" + } + }, + "@types/yargs-parser": { + "version": "21.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", + "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==" + }, + "ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "requires": { + "type-fest": "^0.21.3" + } + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==" + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "are-we-there-yet": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", + "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "babel-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", + "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", + "requires": { + "@jest/transform": "^29.7.0", + "@types/babel__core": "^7.1.14", + "babel-plugin-istanbul": "^6.1.1", + "babel-preset-jest": "^29.6.3", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "slash": "^3.0.0" + } + }, + "babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" + }, + "dependencies": { + "istanbul-lib-instrument": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", + "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", + "requires": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" + } + }, + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" + } + } + }, + "babel-plugin-jest-hoist": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", + "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", + "requires": { + "@babel/template": "^7.3.3", + "@babel/types": "^7.3.3", + "@types/babel__core": "^7.1.14", + "@types/babel__traverse": "^7.0.6" + } + }, + "babel-preset-current-node-syntax": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.1.0.tgz", + "integrity": "sha512-ldYss8SbBlWva1bs28q78Ju5Zq1F+8BrqBZZ0VFhLBvhh6lCpC2o3gDJi/5DRLs9FgYZCnmPYIVFU4lRXCkyUw==", + "requires": { + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-bigint": "^7.8.3", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-import-attributes": "^7.24.7", + "@babel/plugin-syntax-import-meta": "^7.10.4", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5" + } + }, + "babel-preset-jest": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", + "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", + "requires": { + "babel-plugin-jest-hoist": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0" + } + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "base64-js": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", + "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==" + }, + "bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "requires": { + "file-uri-to-path": "1.0.0" + } + }, + "bitwise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/bitwise/-/bitwise-2.1.0.tgz", + "integrity": "sha512-XKgAhMXCh4H/3oNwAHAsAO0iC89s9cOiumgYwSHjSobGWxYjv62YhkL9QEdvGP151xypCtMlAfKK79GEcd2eRQ==" + }, + "bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "requires": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "requires": { + "fill-range": "^7.1.1" + } + }, + "browserslist": { + "version": "4.24.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.2.tgz", + "integrity": "sha512-ZIc+Q62revdMcqC6aChtW4jz3My3klmCO1fEmINZY/8J3EpBg5/A/D0AKmBveUh6pgoeycoMkVMko84tuYS+Gg==", + "requires": { + "caniuse-lite": "^1.0.30001669", + "electron-to-chromium": "^1.5.41", + "node-releases": "^2.0.18", + "update-browserslist-db": "^1.1.1" + } + }, + "bser": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", + "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", + "requires": { + "node-int64": "^0.4.0" + } + }, + "buffer": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz", + "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==", + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" + }, + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==" + }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==" + }, + "caniuse-lite": { + "version": "1.0.30001687", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001687.tgz", + "integrity": "sha512-0S/FDhf4ZiqrTUiQ39dKeUjYRjkv7lOZU1Dgif2rIqrTzX/1wV2hfKu9TOm1IHkdSijfLswxTFzl/cvir+SLSQ==" + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "char-regex": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", + "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==" + }, + "chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, + "ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==" + }, + "cjs-module-lexer": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.1.tgz", + "integrity": "sha512-cuSVIHi9/9E/+821Qjdvngor+xpnlwnuwIyZOaLmHBVdXL+gP+I6QQB9VkO7RI77YIcTV+S1W9AreJ5eN63JBA==" + }, + "cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "requires": { + "ansi-regex": "^5.0.1" + } + } + } + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==" + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==" + }, + "collect-v8-coverage": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz", + "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==" + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "commist": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/commist/-/commist-1.1.0.tgz", + "integrity": "sha512-rraC8NXWOEjhADbZe9QBNzLAN5Q3fsTPQtBV+fEVj6xKIgDgNiEVE6ZNfHpZOqfQ21YUzfVNUXLOEZquYvQPPg==", + "requires": { + "leven": "^2.1.0", + "minimist": "^1.1.0" + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "concat-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", + "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.0.2", + "typedarray": "^0.0.6" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" + }, + "convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==" + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "crc": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/crc/-/crc-3.4.0.tgz", + "integrity": "sha512-ycVC2+4/DLgXXq7QweYi2znhqDuZz6P5TQXnkQo8v15XY/5p/IWeZwsSE31Ifo8w15b8TWLsqhXOjXyilHuQxw==" + }, + "create-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", + "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==", + "requires": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "prompts": "^2.0.1" + } + }, + "cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "date-format": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.11.tgz", + "integrity": "sha512-VS20KRyorrbMCQmpdl2hg5KaOUsda1RbnsJg461FfrcyCUg+pkd0b40BSW4niQyTheww4DBXQnS7HwSrKkipLw==" + }, + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "requires": { + "ms": "2.1.2" + } + }, + "decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "requires": { + "mimic-response": "^3.1.0" + } + }, + "dedent": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.3.tgz", + "integrity": "sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==", + "requires": {} + }, + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==" + }, + "deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==" + }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" + }, + "detect-libc": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz", + "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==" + }, + "detect-newline": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", + "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==" + }, + "diff-sequences": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==" + }, + "duplexify": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.2.tgz", + "integrity": "sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw==", + "requires": { + "end-of-stream": "^1.4.1", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1", + "stream-shift": "^1.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "easy-crc": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/easy-crc/-/easy-crc-0.0.2.tgz", + "integrity": "sha512-h6eqIdhJRe0p271/xZJbM/0klCi13mW5IB7ZEzEGH11yV4QXWAkD4yPErz0fXdhFrd6sZ4Q1k5Iky2kMsMNePw==" + }, + "electron-to-chromium": { + "version": "1.5.72", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.72.tgz", + "integrity": "sha512-ZpSAUOZ2Izby7qnZluSrAlGgGQzucmFbN0n64dYzocYxnxV5ufurpj3VgEe4cUp7ir9LmeLxNYo8bVnlM8bQHw==" + }, + "emittery": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", + "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==" + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "requires": { + "once": "^1.4.0" + } + }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==" + }, + "escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==" + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" + }, + "execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "requires": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + } + }, + "exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==" + }, + "expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==" + }, + "expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", + "requires": { + "@jest/expect-utils": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0" + } + }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" + }, + "fb-watchman": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", + "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", + "requires": { + "bser": "2.1.1" + } + }, + "file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" + }, + "fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "flatted": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", + "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==" + }, + "fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, + "fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "optional": true + }, + "function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==" + }, + "gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha512-14x4kjc6lkD3ltw589k0NrPD6cCNTD6CWoVUNpB85+DrtONoZn+Rug6xZU5RvSC4+TZPxA5AnBibQYAvZn41Hg==", + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==" + }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" + }, + "get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==" + }, + "get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==" + }, + "github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==" + }, + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==" + }, + "graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" + }, + "hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "requires": { + "function-bind": "^1.1.2" + } + }, + "help-me": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/help-me/-/help-me-3.0.0.tgz", + "integrity": "sha512-hx73jClhyk910sidBB7ERlnhMlFsJJIBqSVMFDwPN8o2v9nmp5KgLq1Xz1Bf1fCMMZ6mPrX159iG0VLy/fPMtQ==", + "requires": { + "glob": "^7.1.6", + "readable-stream": "^3.6.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==" + }, + "human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==" + }, + "ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + }, + "import-local": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz", + "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==", + "requires": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + } + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==" + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==" + }, + "is-core-module": { + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz", + "integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==", + "requires": { + "hasown": "^2.0.2" + } + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==", + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "is-generator-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", + "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==" + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" + }, + "is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==" + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" + }, + "istanbul-lib-coverage": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==" + }, + "istanbul-lib-instrument": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz", + "integrity": "sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==", + "requires": { + "@babel/core": "^7.23.9", + "@babel/parser": "^7.23.9", + "@istanbuljs/schema": "^0.1.3", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^7.5.4" + } + }, + "istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", + "requires": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" + } + }, + "istanbul-lib-source-maps": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", + "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", + "requires": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" + } + }, + "istanbul-reports": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz", + "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==", + "requires": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + } + }, + "jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", + "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", + "requires": { + "@jest/core": "^29.7.0", + "@jest/types": "^29.6.3", + "import-local": "^3.0.2", + "jest-cli": "^29.7.0" + } + }, + "jest-changed-files": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz", + "integrity": "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==", + "requires": { + "execa": "^5.0.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0" + } + }, + "jest-circus": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz", + "integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==", + "requires": { + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "dedent": "^1.0.0", + "is-generator-fn": "^2.0.0", + "jest-each": "^29.7.0", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0", + "pretty-format": "^29.7.0", + "pure-rand": "^6.0.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + } + }, + "jest-cli": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz", + "integrity": "sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==", + "requires": { + "@jest/core": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "create-jest": "^29.7.0", + "exit": "^0.1.2", + "import-local": "^3.0.2", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "yargs": "^17.3.1" + } + }, + "jest-config": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", + "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", + "requires": { + "@babel/core": "^7.11.6", + "@jest/test-sequencer": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-jest": "^29.7.0", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "deepmerge": "^4.2.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-circus": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "micromatch": "^4.0.4", + "parse-json": "^5.2.0", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-json-comments": "^3.1.1" + }, + "dependencies": { + "strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==" + } + } + }, + "jest-diff": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", + "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", + "requires": { + "chalk": "^4.0.0", + "diff-sequences": "^29.6.3", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + } + }, + "jest-docblock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz", + "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==", + "requires": { + "detect-newline": "^3.0.0" + } + }, + "jest-each": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz", + "integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==", + "requires": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "jest-util": "^29.7.0", + "pretty-format": "^29.7.0" + } + }, + "jest-environment-node": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", + "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", + "requires": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + } + }, + "jest-get-type": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==" + }, + "jest-haste-map": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", + "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", + "requires": { + "@jest/types": "^29.6.3", + "@types/graceful-fs": "^4.1.3", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "fsevents": "^2.3.2", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "micromatch": "^4.0.4", + "walker": "^1.0.8" + } + }, + "jest-leak-detector": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz", + "integrity": "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==", + "requires": { + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + } + }, + "jest-matcher-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", + "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", + "requires": { + "chalk": "^4.0.0", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + } + }, + "jest-message-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", + "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", + "requires": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^29.6.3", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + } + }, + "jest-mock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", + "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", + "requires": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-util": "^29.7.0" + } + }, + "jest-pnp-resolver": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", + "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", + "requires": {} + }, + "jest-regex-util": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", + "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==" + }, + "jest-resolve": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz", + "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==", + "requires": { + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-pnp-resolver": "^1.2.2", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "resolve": "^1.20.0", + "resolve.exports": "^2.0.0", + "slash": "^3.0.0" + } + }, + "jest-resolve-dependencies": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz", + "integrity": "sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==", + "requires": { + "jest-regex-util": "^29.6.3", + "jest-snapshot": "^29.7.0" + } + }, + "jest-runner": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz", + "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==", + "requires": { + "@jest/console": "^29.7.0", + "@jest/environment": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "graceful-fs": "^4.2.9", + "jest-docblock": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-leak-detector": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-resolve": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-util": "^29.7.0", + "jest-watcher": "^29.7.0", + "jest-worker": "^29.7.0", + "p-limit": "^3.1.0", + "source-map-support": "0.5.13" + } + }, + "jest-runtime": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz", + "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==", + "requires": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/globals": "^29.7.0", + "@jest/source-map": "^29.6.3", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "cjs-module-lexer": "^1.0.0", + "collect-v8-coverage": "^1.0.0", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0", + "strip-bom": "^4.0.0" + } + }, + "jest-snapshot": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz", + "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==", + "requires": { + "@babel/core": "^7.11.6", + "@babel/generator": "^7.7.2", + "@babel/plugin-syntax-jsx": "^7.7.2", + "@babel/plugin-syntax-typescript": "^7.7.2", + "@babel/types": "^7.3.3", + "@jest/expect-utils": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0", + "chalk": "^4.0.0", + "expect": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "natural-compare": "^1.4.0", + "pretty-format": "^29.7.0", + "semver": "^7.5.3" + } + }, + "jest-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "requires": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + } + }, + "jest-validate": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", + "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", + "requires": { + "@jest/types": "^29.6.3", + "camelcase": "^6.2.0", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "leven": "^3.1.0", + "pretty-format": "^29.7.0" + }, + "dependencies": { + "camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==" + }, + "leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==" + } + } + }, + "jest-watcher": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz", + "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==", + "requires": { + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "jest-util": "^29.7.0", + "string-length": "^4.0.1" + } + }, + "jest-worker": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", + "requires": { + "@types/node": "*", + "jest-util": "^29.7.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "dependencies": { + "supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "js-sdsl": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz", + "integrity": "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==" + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, + "js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==" + }, + "jsmodbus": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/jsmodbus/-/jsmodbus-4.0.6.tgz", + "integrity": "sha512-gCmjoaERErK5Rn9Lu/BN07fY13MoWV7JKgGzrnkPlQPdPxYcwDhLtYcmpFFpZ4J9NPZZBSezi1UkLZO/DnNppA==", + "requires": { + "crc": "3.4.0", + "debug": "^3.1.0" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "requires": { + "ms": "^2.1.1" + } + } + } + }, + "json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" + }, + "json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==" + }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, + "kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==" + }, + "leven": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", + "integrity": "sha1-wuep93IJTe6dNCAq6KzORoeHVYA=" + }, + "lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "requires": { + "p-locate": "^4.1.0" + } + }, + "log4js": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.5.2.tgz", + "integrity": "sha512-DXtpNtt+KDOMT7RHUDIur/WsSA3rntlUh9Zg4XCdV42wUuMmbFkl38+LZ92Z5QvQA7mD5kAVkLiBSEH/tvUB8A==", + "requires": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "flatted": "^3.2.5", + "rfdc": "^1.3.0", + "streamroller": "^3.1.1" + } + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "requires": { + "yallist": "^4.0.0" + } + }, + "make-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", + "requires": { + "semver": "^7.5.3" + } + }, + "makeerror": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", + "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", + "requires": { + "tmpl": "1.0.5" + } + }, + "merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==" + }, + "micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "requires": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + } + }, + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==" + }, + "mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==" + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==" + }, + "mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" + }, + "moment": { + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", + "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==" + }, + "mqtt": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/mqtt/-/mqtt-4.3.7.tgz", + "integrity": "sha512-ew3qwG/TJRorTz47eW46vZ5oBw5MEYbQZVaEji44j5lAUSQSqIEoul7Kua/BatBW0H0kKQcC9kwUHa1qzaWHSw==", + "requires": { + "commist": "^1.0.0", + "concat-stream": "^2.0.0", + "debug": "^4.1.1", + "duplexify": "^4.1.1", + "help-me": "^3.0.0", + "inherits": "^2.0.3", + "lru-cache": "^6.0.0", + "minimist": "^1.2.5", + "mqtt-packet": "^6.8.0", + "number-allocator": "^1.0.9", + "pump": "^3.0.0", + "readable-stream": "^3.6.0", + "reinterval": "^1.1.0", + "rfdc": "^1.3.0", + "split2": "^3.1.0", + "ws": "^7.5.5", + "xtend": "^4.0.2" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "mqtt-packet": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/mqtt-packet/-/mqtt-packet-6.10.0.tgz", + "integrity": "sha512-ja8+mFKIHdB1Tpl6vac+sktqy3gA8t9Mduom1BA75cI+R9AHnZOiaBQwpGiWnaVJLDGRdNhQmFaAqd7tkKSMGA==", + "requires": { + "bl": "^4.0.2", + "debug": "^4.1.1", + "process-nextick-args": "^2.0.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "nan": { + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.16.0.tgz", + "integrity": "sha512-UdAqHyFngu7TfQKsCBgAA6pWDkT8MAO7d0jyOecVhN5354xbLqdn8mV9Tat9gepAupm0bt2DbeaSC8vS52MuFA==" + }, + "napi-build-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", + "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==" + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==" + }, + "node-abi": { + "version": "3.22.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.22.0.tgz", + "integrity": "sha512-u4uAs/4Zzmp/jjsD9cyFYDXeISfUWaAVWshPmDZOFOv4Xl4SbzTXm53I04C2uRueYJ+0t5PEtLH/owbn2Npf/w==", + "requires": { + "semver": "^7.3.5" + } + }, + "node-int64": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==" + }, + "node-releases": { + "version": "2.0.19", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", + "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==" + }, + "nodemailer": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.7.tgz", + "integrity": "sha512-rUtR77ksqex/eZRLmQ21LKVH5nAAsVicAtAYudK7JgwenEDZ0UIQ1adUGqErz7sMkWYxWTTU1aeP2Jga6WQyJw==" + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" + }, + "npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "requires": { + "path-key": "^3.0.0" + } + }, + "npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "number-allocator": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/number-allocator/-/number-allocator-1.0.14.tgz", + "integrity": "sha512-OrL44UTVAvkKdOdRQZIJpLkAdjXGTRda052sN4sO77bKEzYYqWKMBjQvrJFzqygI99gL6Z4u2xctPW1tB8ErvA==", + "requires": { + "debug": "^4.3.1", + "js-sdsl": "4.3.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==" + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==" + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1" + } + }, + "onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "requires": { + "mimic-fn": "^2.1.0" + } + }, + "p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "requires": { + "yocto-queue": "^0.1.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "requires": { + "p-limit": "^2.2.0" + }, + "dependencies": { + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "requires": { + "p-try": "^2.0.0" + } + } + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" + }, + "parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "requires": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + } + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==" + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==" + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==" + }, + "path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" + }, + "picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==" + }, + "picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==" + }, + "pirates": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", + "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==" + }, + "pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "requires": { + "find-up": "^4.0.0" + } + }, + "prebuild-install": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.0.tgz", + "integrity": "sha512-CNcMgI1xBypOyGqjp3wOc8AAo1nMhZS3Cwd3iHIxOdAUbb+YxdNuM4Z5iIrZ8RLvOsf3F3bl7b7xGq6DjQoNYA==", + "requires": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^1.0.1", + "node-abi": "^3.3.0", + "npmlog": "^4.0.1", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + } + }, + "pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "requires": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==" + } + } + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "requires": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + } + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "pure-rand": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz", + "integrity": "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==" + }, + "rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + } + }, + "react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==" + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "reinterval": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reinterval/-/reinterval-1.1.0.tgz", + "integrity": "sha1-M2Hs+jymwYKDOA3Qu5VG85D17Oc=" + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==" + }, + "resolve": { + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "requires": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + } + }, + "resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "requires": { + "resolve-from": "^5.0.0" + } + }, + "resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==" + }, + "resolve.exports": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.3.tgz", + "integrity": "sha512-OcXjMsGdhL4XnbShKpAcSqPMzQoYkYyhbEaeSko47MjRP9NfEQMhZkXL1DoFlt9LWQn4YttrdnV6X2OiyzBi+A==" + }, + "rfdc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==" + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "requires": { + "lru-cache": "^6.0.0" + } + }, + "serialport": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/serialport/-/serialport-9.2.8.tgz", + "integrity": "sha512-FsWpMQgSJxi93JgWl5xM1f9/Z8IjRJuaUEoHqLf8FPBLw7gMhInuHOBhI2onQufWIYPGTz3H3oGcu1nCaK1EfA==", + "requires": { + "@serialport/binding-mock": "9.2.4", + "@serialport/bindings": "9.2.8", + "@serialport/parser-byte-length": "9.2.4", + "@serialport/parser-cctalk": "9.2.4", + "@serialport/parser-delimiter": "9.2.4", + "@serialport/parser-inter-byte-timeout": "9.2.4", + "@serialport/parser-readline": "9.2.4", + "@serialport/parser-ready": "9.2.4", + "@serialport/parser-regex": "9.2.4", + "@serialport/stream": "9.2.4", + "debug": "^4.3.2" + } + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==" + }, + "signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==" + }, + "simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "requires": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==" + }, + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==" + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + }, + "source-map-support": { + "version": "0.5.13", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", + "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "split2": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", + "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", + "requires": { + "readable-stream": "^3.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==" + }, + "stack-utils": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", + "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", + "requires": { + "escape-string-regexp": "^2.0.0" + } + }, + "stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==" + }, + "streamroller": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.1.1.tgz", + "integrity": "sha512-iPhtd9unZ6zKdWgMeYGfSBuqCngyJy1B/GPi/lTpwGpa3bajuX30GjUVd0/Tn/Xhg0mr4DOSENozz9Y06qyonQ==", + "requires": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "fs-extra": "^10.1.0" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "string-length": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", + "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", + "requires": { + "char-regex": "^1.0.2", + "strip-ansi": "^6.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "requires": { + "ansi-regex": "^5.0.1" + } + } + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-bom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==" + }, + "strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==" + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "requires": { + "has-flag": "^4.0.0" + } + }, + "supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==" + }, + "tar-fs": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "requires": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "requires": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "requires": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + } + }, + "tmpl": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", + "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==" + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "requires": { + "is-number": "^7.0.0" + } + }, + "total.js": { + "version": "3.4.13", + "resolved": "https://registry.npmjs.org/total.js/-/total.js-3.4.13.tgz", + "integrity": "sha512-lAH4gEixlPFbrE3xfKADAcHfO79IFq2wKa9GTsrgRzIR5MTg3mNH7+4IxvX1pK8faoYb/0oYSJ1YTsAa5hIFFQ==" + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==" + }, + "type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==" + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, + "undici-types": { + "version": "6.20.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", + "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==" + }, + "universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==" + }, + "update-browserslist-db": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz", + "integrity": "sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==", + "requires": { + "escalade": "^3.2.0", + "picocolors": "^1.1.0" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "v8-to-istanbul": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz", + "integrity": "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==", + "requires": { + "@jridgewell/trace-mapping": "^0.3.12", + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^2.0.0" + } + }, + "walker": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", + "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", + "requires": { + "makeerror": "1.0.12" + } + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "requires": { + "isexe": "^2.0.0" + } + }, + "wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "requires": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "requires": { + "ansi-regex": "^5.0.1" + } + } + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "write-file-atomic": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", + "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", + "requires": { + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.7" + } + }, + "ws": { + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "requires": {} + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + }, + "y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==" + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "requires": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "requires": { + "ansi-regex": "^5.0.1" + } + } + } + }, + "yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==" + }, + "yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==" + } + } +} diff --git a/RVO39/package.json b/RVO39/package.json new file mode 100755 index 0000000..72e31b1 --- /dev/null +++ b/RVO39/package.json @@ -0,0 +1,31 @@ +{ + "name": "emptyproject", + "description": "Total.js empty project.", + "version": "1.0.0", + "main": "debug.js", + "dependencies": { + "bitwise": "^2.1.0", + "easy-crc": "0.0.2", + "jest": "^29.7.0", + "jsmodbus": "^4.0.6", + "log4js": "^6.3.0", + "moment": "^2.30.1", + "mqtt": "^4.2.6", + "nodemailer": "^6.9.7", + "serialport": "^9.2.8", + "total.js": "^3.4.13" + }, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "https://github.com/totaljs/emptyproject-flow" + }, + "keywords": [ + "empty", + "project" + ], + "author": "Peter Širka", + "license": "MIT" +} diff --git a/RVO39/release.js b/RVO39/release.js new file mode 100755 index 0000000..02d52ff --- /dev/null +++ b/RVO39/release.js @@ -0,0 +1,15 @@ +// =================================================== +// FOR PRODUCTION +// Total.js - framework for Node.js platform +// https://www.totaljs.com +// =================================================== + +const options = {'ip':'0.0.0.0', 'port':12345}; + +// options.ip = '127.0.0.1'; +// options.port = parseInt(process.argv[2]); +// options.config = { name: 'Total.js' }; +// options.sleep = 3000; + +require('total.js').http('release', options); +// require('total.js').cluster.http(5, 'release', options); diff --git a/RVO39/release.js.json b/RVO39/release.js.json new file mode 100755 index 0000000..d501cb8 --- /dev/null +++ b/RVO39/release.js.json @@ -0,0 +1,34 @@ +{ + "pid": 391, + "stats": [ + { + "id": null, + "version": { + "node": "v14.18.1", + "total": "3.4.13", + "app": "1.0.0" + }, + "pid": 391, + "thread": "", + "mode": "release", + "overload": 0, + "date": "2025-10-16T00:25:49.264Z", + "memory": 24.02, + "rm": 0, + "fm": 0, + "wm": 0, + "mm": 0, + "om": 2, + "em": 0, + "dbrm": 0, + "dbwm": 0, + "usage": 0, + "requests": 0, + "pending": 0, + "errors": 0, + "timeouts": 0, + "uptime": 727, + "online": 0 + } + ] +} \ No newline at end of file diff --git a/RVO39/report_data.log b/RVO39/report_data.log new file mode 100755 index 0000000..3faabc5 --- /dev/null +++ b/RVO39/report_data.log @@ -0,0 +1,151 @@ +{ + "name": "rvo_senica_39_10.0.0.132", + "time": "2025-10-15T13:20:04.198Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_39_10.0.0.132", + "time": "2025-10-15T14:20:04.196Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_39_10.0.0.132", + "time": "2025-10-15T15:20:04.196Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_39_10.0.0.132", + "time": "2025-10-15T17:33:19.819Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_39_10.0.0.132", + "time": "2025-10-15T18:33:19.820Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_39_10.0.0.132", + "time": "2025-10-15T19:33:19.820Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_39_10.0.0.132", + "time": "2025-10-15T20:33:19.820Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_39_10.0.0.132", + "time": "2025-10-15T21:33:19.820Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_39_10.0.0.132", + "time": "2025-10-15T22:33:19.820Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_39_10.0.0.132", + "time": "2025-10-15T23:33:19.821Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +} \ No newline at end of file From a7fe10c7b2596c1311f20fbe40c0ab87fe0b4029 Mon Sep 17 00:00:00 2001 From: Jakub Klena Date: Thu, 16 Oct 2025 02:26:31 +0200 Subject: [PATCH 22/30] Backup senica-RVO41 on 16.10.2025 --- RVO41/addSwitch.py | 36 + RVO41/cloud_topic.py | 76 + RVO41/config | 12 + RVO41/createNode.py | 43 + RVO41/databases/accelerometer_db.js | 3055 ++++++++++++++++ RVO41/databases/modbus_config.js | 114 + RVO41/databases/nodes.table | 17 + .../nodes_original/nodes_original.table | 1 + RVO41/databases/notifications.table | 41 + RVO41/databases/pins.table | 14 + RVO41/databases/relays.table | 5 + RVO41/databases/settings.table | 2 + RVO41/databases/tbdata.nosql | 4 + RVO41/databases/tbdatacloud.nosql | 3 + RVO41/databases/total_energy.js | 38 + RVO41/debug.js | 16 + RVO41/err.txt | 123 + RVO41/flow/cloudmqttconnect.js | 357 ++ RVO41/flow/cmd_manager.js | 3071 ++++++++++++++++ RVO41/flow/code.js | 90 + RVO41/flow/comment.js | 11 + RVO41/flow/count.js | 60 + RVO41/flow/db_connector.js | 286 ++ RVO41/flow/db_init.js | 113 + RVO41/flow/debug.js | 100 + RVO41/flow/designer.json | 3102 +++++++++++++++++ RVO41/flow/dido_controller.js | 1486 ++++++++ RVO41/flow/helper/DataToTbHandler.js | 187 + RVO41/flow/helper/ErrorToServiceHandler.js | 91 + RVO41/flow/helper/db_helper.js | 44 + RVO41/flow/helper/logger.js | 30 + RVO41/flow/helper/md5.js | 5 + RVO41/flow/helper/notification_reporter.js | 121 + RVO41/flow/helper/register.js | 144 + RVO41/flow/helper/serialport_helper.js | 99 + RVO41/flow/helper/suncalc.js | 317 ++ RVO41/flow/helper/utils.js | 161 + RVO41/flow/httprequest.js | 137 + RVO41/flow/httpresponse.js | 76 + RVO41/flow/httproute.js | 326 ++ RVO41/flow/infosender.js | 81 + RVO41/flow/modbus_reader.js | 346 ++ RVO41/flow/monitorconsumption.js | 156 + RVO41/flow/monitordisk.js | 96 + RVO41/flow/monitormemory.js | 87 + RVO41/flow/nodesdb_changecheck.js | 77 + RVO41/flow/show_dbdata.js | 243 ++ RVO41/flow/slack_filter.js | 188 + RVO41/flow/thermometer.js | 99 + RVO41/flow/trigger.js | 79 + RVO41/flow/variables.txt | 0 RVO41/flow/virtualwirein.js | 43 + RVO41/flow/virtualwireout.js | 41 + RVO41/flow/wsmqttpublish.js | 448 +++ RVO41/monitor.txt | 435 +++ RVO41/package-lock.json | 2125 +++++++++++ RVO41/package.json | 29 + RVO41/release.js | 15 + RVO41/release.js.json | 34 + RVO41/report_data.log | 238 ++ 60 files changed, 18874 insertions(+) create mode 100755 RVO41/addSwitch.py create mode 100755 RVO41/cloud_topic.py create mode 100755 RVO41/config create mode 100755 RVO41/createNode.py create mode 100755 RVO41/databases/accelerometer_db.js create mode 100755 RVO41/databases/modbus_config.js create mode 100755 RVO41/databases/nodes.table create mode 100755 RVO41/databases/nodes_original/nodes_original.table create mode 100755 RVO41/databases/notifications.table create mode 100755 RVO41/databases/pins.table create mode 100755 RVO41/databases/relays.table create mode 100755 RVO41/databases/settings.table create mode 100755 RVO41/databases/tbdata.nosql create mode 100755 RVO41/databases/tbdatacloud.nosql create mode 100755 RVO41/databases/total_energy.js create mode 100755 RVO41/debug.js create mode 100755 RVO41/err.txt create mode 100755 RVO41/flow/cloudmqttconnect.js create mode 100755 RVO41/flow/cmd_manager.js create mode 100755 RVO41/flow/code.js create mode 100755 RVO41/flow/comment.js create mode 100755 RVO41/flow/count.js create mode 100755 RVO41/flow/db_connector.js create mode 100755 RVO41/flow/db_init.js create mode 100755 RVO41/flow/debug.js create mode 100755 RVO41/flow/designer.json create mode 100755 RVO41/flow/dido_controller.js create mode 100755 RVO41/flow/helper/DataToTbHandler.js create mode 100755 RVO41/flow/helper/ErrorToServiceHandler.js create mode 100755 RVO41/flow/helper/db_helper.js create mode 100755 RVO41/flow/helper/logger.js create mode 100755 RVO41/flow/helper/md5.js create mode 100755 RVO41/flow/helper/notification_reporter.js create mode 100755 RVO41/flow/helper/register.js create mode 100755 RVO41/flow/helper/serialport_helper.js create mode 100755 RVO41/flow/helper/suncalc.js create mode 100755 RVO41/flow/helper/utils.js create mode 100755 RVO41/flow/httprequest.js create mode 100755 RVO41/flow/httpresponse.js create mode 100755 RVO41/flow/httproute.js create mode 100755 RVO41/flow/infosender.js create mode 100755 RVO41/flow/modbus_reader.js create mode 100755 RVO41/flow/monitorconsumption.js create mode 100755 RVO41/flow/monitordisk.js create mode 100755 RVO41/flow/monitormemory.js create mode 100755 RVO41/flow/nodesdb_changecheck.js create mode 100755 RVO41/flow/show_dbdata.js create mode 100755 RVO41/flow/slack_filter.js create mode 100755 RVO41/flow/thermometer.js create mode 100755 RVO41/flow/trigger.js create mode 100755 RVO41/flow/variables.txt create mode 100755 RVO41/flow/virtualwirein.js create mode 100755 RVO41/flow/virtualwireout.js create mode 100755 RVO41/flow/wsmqttpublish.js create mode 100755 RVO41/monitor.txt create mode 100755 RVO41/package-lock.json create mode 100755 RVO41/package.json create mode 100755 RVO41/release.js create mode 100755 RVO41/release.js.json create mode 100755 RVO41/report_data.log diff --git a/RVO41/addSwitch.py b/RVO41/addSwitch.py new file mode 100755 index 0000000..c35e96b --- /dev/null +++ b/RVO41/addSwitch.py @@ -0,0 +1,36 @@ +import os + +def process_set_file(): + """ + Checks if /root/flowserver exists, reads set.txt, and modifies the second line. + """ + default_folder = "/root/flowserver" if os.path.exists("/root/flowserver") else "/home/unipi/flowserver" + flag = 1 if default_folder == "/root/flowserver" else 0 + + try: + with open("/home/unipi/flowserver/databases/settings.table", "r") as f: + lines = f.readlines() + + if len(lines) >= 2: + lines[0] = lines[0].rstrip('\n') + "|main_switch:boolean\n" + second_line = lines[1].strip() # remove trailing newline + last_pipe_index = second_line.rfind("|") + + if last_pipe_index != -1: + modified_line = second_line[:last_pipe_index + 1] + str(flag) + "|" + second_line[last_pipe_index + 1:] + lines[1] = modified_line + else: + print("Warning: No '|' character found in the second line of set.txt") + + with open("/home/unipi/flowserver/databases/settings.table", "w") as f: + f.writelines(lines) + else: + print("Warning: settings.table has less than two lines.") + + except FileNotFoundError: + print("Error: settings.table not found.") + except Exception as e: + print(e) + +# if __name__ == "__main__": +process_set_file() diff --git a/RVO41/cloud_topic.py b/RVO41/cloud_topic.py new file mode 100755 index 0000000..77c31f1 --- /dev/null +++ b/RVO41/cloud_topic.py @@ -0,0 +1,76 @@ +# import os +# +# def modify_file(file_path): +# """ +# Modifies the given file by: +# 1. Appending "|cloud_topic" to the first line. +# 2. Inserting the text from the third "." to the first "|" on the second line after the last "|" character. +# +# Args: +# file_path (str): The path to the file to be modified. +# """ +# +# with open(file_path, 'r+') as f: +# lines = f.readlines() +# +# # Modify the first line +# lines[0] += "|cloud_topic:string" +# +# # Modify the second line +# second_line = lines[1].strip() # Remove leading/trailing whitespace +# first_pipe_index = second_line.find('|') +# third_dot_index = second_line.find('.', second_line.find('.', second_line.find('.') + 1) + 1) +# text_to_insert = second_line[third_dot_index:first_pipe_index] +# +# last_pipe_index = second_line.rfind('|') +# lines[1] = second_line[:last_pipe_index + 1] + text_to_insert + "|" + second_line[last_pipe_index + 1:] +# +# print(first_pipe_index, third_dot_index, text_to_insert, last_pipe_index) +# # Write the modified lines back to the file +# # f.seek(0) +# # f.writelines(lines) +# # f.truncate() +# +# # Example usage: +# file_path = "settings.table" # Replace with the actual file path +# modify_file(file_path) +# + + +def modify_file(file_path): + """ + Modifies the given file by: + 1. Appending "|cloud_topic" to the first line. + 2. Inserting the text between the third "." and the second "|" on the second line after the last "|" character. + + Args: + file_path (str): The path to the file to be modified. + """ + + with open(file_path, 'r+') as f: + lines = f.readlines() + + first_line = lines[0].strip() + first_line += "|cloud_topic:string\n" + # Modify the first line + lines[0] = first_line + + # Modify the second line + second_line = lines[1].strip() # Remove leading/trailing whitespace + first_pipe_index = second_line.find('|') + second_pipe_index = second_line.find('|', first_pipe_index + 1) + third_dot_index = second_line.find('.', second_line.find('.', second_line.find('.') + 1) + 1) + text_to_insert = "u" + second_line[third_dot_index+1:second_pipe_index] + + last_pipe_index = second_line.rfind('|') + lines[1] = second_line[:last_pipe_index + 1] + text_to_insert + "|" + second_line[last_pipe_index + 1:] + + print(first_pipe_index, third_dot_index, text_to_insert, last_pipe_index) + # Write the modified lines back to the file + f.seek(0) + f.writelines(lines) + f.truncate() + +# Example usage: +file_path = "/home/unipi/flowserver/databases/settings.table" # Replace with the actual file path +modify_file(file_path) diff --git a/RVO41/config b/RVO41/config new file mode 100755 index 0000000..cd0a8a9 --- /dev/null +++ b/RVO41/config @@ -0,0 +1,12 @@ +name : Total.js Flow +default_timezone : Europe/Bratislava + +// Packages settings +package#flow (Object) : { url: '/' } + + +table.relays : line:number|tbname:string|contactor:number|profile:string +table.nodes : node:number|pole_number:string|node_type:string|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|project_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|cloud_topic:string|has_main_switch:boolean|daily_report:boolean|send_changed_node_numbers:boolean +table.pins : pin:string|type:string|line:number +table.notifications : key:string|weight:string|sk:string|en:string diff --git a/RVO41/createNode.py b/RVO41/createNode.py new file mode 100755 index 0000000..a8cea91 --- /dev/null +++ b/RVO41/createNode.py @@ -0,0 +1,43 @@ +print("zaciname") +import re, json + +search_str = '|' +final = [] +counter = 1 +with open("/home/unipi/flowserver/databases/nodes.table", 'r') as file: +# with open("/home/rasta5man/dev/oms/flowserver/databases/nodes.table", 'r') as file: + # Read each line in the file + for line in file: + # Print each line + line = line.strip() + print(line) + if counter != 1: + i = [m.start() for m in re.finditer(re.escape(search_str), line)] + node = line[ i[0] + 1 : i[1] ] + tbname = line[ i[3] + 1 : i[4] ] + final.append({node:tbname}) + counter += 1 +print(json.dumps(final)) +f = open("/home/unipi/flowserver/databases/nodes_original/nodes_original.table", "w") +f.write(json.dumps(final)) +f.close() + + +# +# # ``d`` has to be replaced with a different character +# old_character = "'" +# +# # ``t`` will replace ``d` +# new_character = '"' +# resultant_string = 0; +# with open("/home/unipi/flowserver/databases/nodes_original/nodes_original.table", 'r') as file: +# for line in file: +# resultant_string = re.sub("'", '"', line) +# +# resultant_string = re.sub(" ", "", resultant_string) +# print(resultant_string) +# +# f = open("/home/unipi/flowserver/databases/nodes_original/nodes_original.table", "w") +# f.write(str(resultant_string)) +# f.close() +# diff --git a/RVO41/databases/accelerometer_db.js b/RVO41/databases/accelerometer_db.js new file mode 100755 index 0000000..fdfc7fd --- /dev/null +++ b/RVO41/databases/accelerometer_db.js @@ -0,0 +1,3055 @@ +let naklony = { + "3993": { "label": "1/3A", "naklon": 0 }, + "3989": { "label": "1/3B", "naklon": 15 }, + "3976": { "label": "1/1", "naklon": 0 }, + "4181": { "label": "1/2", "naklon": 0 }, + "4376": { "label": "1/4", "naklon": 15 }, + "3868": { "label": "1/5", "naklon": 15 }, + "3728": { "label": "1/6", "naklon": 15 }, + "3730": { "label": "1/7", "naklon": 0 }, + "4374": { "label": "1/8", "naklon": 0 }, + "3718": { "label": "1/9", "naklon": 15 }, + "4375": { "label": "1/10", "naklon": 15 }, + "4172": { "label": "1/11", "naklon": 15 }, + "4176": { "label": "1/12", "naklon": 15 }, + "3800": { "label": "2/1", "naklon": 5 }, + "3823": { "label": "2/2", "naklon": 5 }, + "3905": { "label": "2/3", "naklon": 5 }, + "3803": { "label": "2/4", "naklon": 5 }, + "3817": { "label": "2/5", "naklon": 5 }, + "3818": { "label": "2/6", "naklon": 5 }, + "3811": { "label": "2/7", "naklon": 5 }, + "3915": { "label": "2/8", "naklon": 5 }, + "3843": { "label": "2/9", "naklon": 10 }, + "3827": { "label": "2/10", "naklon": 10 }, + "4220": { "label": "2/11", "naklon": 10 }, + "3826": { "label": "2/12", "naklon": 10 }, + "3834": { "label": "2/13", "naklon": 10 }, + "3838": { "label": "2/14", "naklon": 10 }, + "2823": { "label": "2/15", "naklon": 10 }, + "3750": { "label": "2/16", "naklon": 10 }, + "3378": { "label": "2/17", "naklon": 0 }, + "3376": { "label": "2/18", "naklon": 0 }, + "3379": { "label": "2/19", "naklon": 0 }, + "3285": { "label": "2/20", "naklon": 0 }, + "3382": { "label": "2/21", "naklon": 0 }, + "3383": { "label": "2/22", "naklon": 0 }, + "3375": { "label": "2/24", "naklon": 0 }, + "3381": { "label": "2/25", "naklon": 0 }, + "3380": { "label": "2/26", "naklon": 0 }, + "3828": { "label": "2/27", "naklon": 10 }, + "3377": { "label": "2/28", "naklon": 0 }, + "3591": { "label": "7/1", "naklon": 0 }, + "3587": { "label": "7/2", "naklon": 0 }, + "3468": { "label": "7/3", "naklon": 0 }, + "3466": { "label": "7/4", "naklon": 0 }, + "3474": { "label": "7/5", "naklon": 0 }, + "3481": { "label": "7/6", "naklon": 0 }, + "3589": { "label": "7/7", "naklon": 0 }, + "3472": { "label": "7/8", "naklon": 0 }, + "3473": { "label": "7/9", "naklon": 0 }, + "3584": { "label": "7/10", "naklon": 0 }, + "3571": { "label": "7/11", "naklon": 0 }, + "3476": { "label": "7/12", "naklon": 0 }, + "3590": { "label": "7/13", "naklon": 0 }, + "3478": { "label": "7/14", "naklon": 0 }, + "3471": { "label": "7/15", "naklon": 0 }, + "3467": { "label": "7/16", "naklon": 0 }, + "3479": { "label": "7/17", "naklon": 0 }, + "3480": { "label": "7/18", "naklon": 0 }, + "3477": { "label": "7/19", "naklon": 0 }, + "3362": { "label": "12/1", "naklon": 0 }, + "3355": { "label": "12/2", "naklon": 0 }, + "3356": { "label": "12/3", "naklon": 0 }, + "3349": { "label": "12/4", "naklon": 0 }, + "3357": { "label": "12/5", "naklon": 0 }, + "3350": { "label": "12/6", "naklon": 0 }, + "3353": { "label": "12/7", "naklon": 0 }, + "3539": { "label": "12/8", "naklon": 0 }, + "3050": { "label": "12/9", "naklon": 0 }, + "3361": { "label": "12/10", "naklon": 0 }, + "3360": { "label": "12/11", "naklon": 0 }, + "3358": { "label": "12/12", "naklon": 0 }, + "3541": { "label": "12/13", "naklon": 0 }, + "3551": { "label": "12/14", "naklon": 0 }, + "3514": { "label": "12/15", "naklon": 0 }, + "3547": { "label": "12/16", "naklon": 0 }, + "3562": { "label": "12/17", "naklon": 0 }, + "3525": { "label": "12/18", "naklon": 0 }, + "3558": { "label": "12/19", "naklon": 0 }, + "3511": { "label": "12/20", "naklon": 0 }, + "3058": { "label": "12/21", "naklon": 0 }, + "3062": { "label": "12/22", "naklon": 0 }, + "3070": { "label": "12/23", "naklon": 0 }, + "3447": { "label": "12/24", "naklon": 0 }, + "3056": { "label": "12/25", "naklon": 0 }, + "3057": { "label": "12/26", "naklon": 0 }, + "3071": { "label": "12/27", "naklon": 0 }, + "3061": { "label": "12/28", "naklon": 0 }, + "3069": { "label": "12/29", "naklon": 0 }, + "3077": { "label": "12/30", "naklon": 0 }, + "3080": { "label": "12/31", "naklon": 0 }, + "3081": { "label": "12/32", "naklon": 0 }, + "3078": { "label": "12/33", "naklon": 0 }, + "4037": { "label": "12/34", "naklon": 0 }, + "3067": { "label": "12/35", "naklon": 0 }, + "3051": { "label": "12/36", "naklon": 0 }, + "2924": { "label": "12/37", "naklon": 0 }, + "3060": { "label": "12/38", "naklon": 0 }, + "3073": { "label": "12/39", "naklon": 0 }, + "3469": { "label": "12/40", "naklon": 0 }, + "2923": { "label": "12/41", "naklon": 0 }, + "2925": { "label": "12/42", "naklon": 0 }, + "3359": { "label": "12/43", "naklon": 0 }, + "3055": { "label": "12/44", "naklon": 0 }, + "2922": { "label": "12/45", "naklon": 0 }, + "3084": { "label": "12/46", "naklon": 0 }, + "3064": { "label": "12/47", "naklon": 0 }, + "3066": { "label": "12/48", "naklon": 0 }, + "3072": { "label": "12/49", "naklon": 0 }, + "3415": { "label": "13/13A", "naklon": 0 }, + "3409": { "label": "13/13B", "naklon": 0 }, + "3399": { "label": "13/13C", "naklon": 0 }, + "3410": { "label": "13/29A", "naklon": 0 }, + "3407": { "label": "13/29B", "naklon": 0 }, + "3405": { "label": "13/34A", "naklon": 0 }, + "3404": { "label": "13/34B", "naklon": 0 }, + "3392": { "label": "13/45A", "naklon": 0 }, + "3386": { "label": "13/45B", "naklon": 0 }, + "3303": { "label": "13/60A", "naklon": 3 }, + "3302": { "label": "13/60B", "naklon": 3 }, + "3319": { "label": "13/70A", "naklon": 6 }, + "3317": { "label": "13/70B", "naklon": 6 }, + "3326": { "label": "13/70C", "naklon": 6 }, + "3351": { "label": "13/73A", "naklon": 6 }, + "3313": { "label": "13/73B", "naklon": 6 }, + "3316": { "label": "13/83A", "naklon": 0 }, + "3320": { "label": "13/83B", "naklon": 0 }, + "3336": { "label": "13/95A", "naklon": 0 }, + "3323": { "label": "13/95B", "naklon": 0 }, + "3339": { "label": "13/98A", "naklon": 0 }, + "3333": { "label": "13/98B", "naklon": 0 }, + "3425": { "label": "13/1", "naklon": 0 }, + "3419": { "label": "13/2", "naklon": 0 }, + "3416": { "label": "13/3", "naklon": 0 }, + "3332": { "label": "13/4", "naklon": 0 }, + "3422": { "label": "13/5", "naklon": 0 }, + "3417": { "label": "13/6", "naklon": 0 }, + "3418": { "label": "13/7", "naklon": 0 }, + "3424": { "label": "13/8", "naklon": 0 }, + "3334": { "label": "13/9", "naklon": 0 }, + "4363": { "label": "13/10", "naklon": 0 }, + "3423": { "label": "13/11", "naklon": 0 }, + "3406": { "label": "13/12", "naklon": 0 }, + "3411": { "label": "13/14", "naklon": 0 }, + "3412": { "label": "13/15", "naklon": 0 }, + "3413": { "label": "13/16", "naklon": 0 }, + "3414": { "label": "13/17", "naklon": 0 }, + "3391": { "label": "13/18", "naklon": 0 }, + "3370": { "label": "13/19", "naklon": 0 }, + "3369": { "label": "13/20", "naklon": 0 }, + "3408": { "label": "13/21", "naklon": 0 }, + "3393": { "label": "13/22", "naklon": 0 }, + "3128": { "label": "13/23", "naklon": 0 }, + "3197": { "label": "13/24", "naklon": 0 }, + "4364": { "label": "13/25", "naklon": 0 }, + "3155": { "label": "13/26", "naklon": 0 }, + "3196": { "label": "13/27", "naklon": 0 }, + "3144": { "label": "13/28", "naklon": 0 }, + "3150": { "label": "13/30", "naklon": 0 }, + "3390": { "label": "13/31", "naklon": 0 }, + "3401": { "label": "13/32", "naklon": 0 }, + "3275": { "label": "13/33", "naklon": 0 }, + "3371": { "label": "13/35", "naklon": 0 }, + "3389": { "label": "13/36", "naklon": 0 }, + "3388": { "label": "13/37", "naklon": 0 }, + "3365": { "label": "13/38", "naklon": 0 }, + "3363": { "label": "13/39", "naklon": 0 }, + "3397": { "label": "13/40", "naklon": 0 }, + "3567": { "label": "13/40/1", "naklon": 0 }, + "3387": { "label": "13/41", "naklon": 0 }, + "3403": { "label": "13/42", "naklon": 0 }, + "3147": { "label": "13/43", "naklon": 0 }, + "3141": { "label": "13/44", "naklon": 0 }, + "3364": { "label": "13/46", "naklon": 0 }, + "3367": { "label": "13/47", "naklon": 0 }, + "3368": { "label": "13/48", "naklon": 0 }, + "3402": { "label": "13/49", "naklon": 0 }, + "3366": { "label": "13/50", "naklon": 0 }, + "3395": { "label": "13/51", "naklon": 0 }, + "3372": { "label": "13/52", "naklon": 0 }, + "3394": { "label": "13/53", "naklon": 0 }, + "3308": { "label": "13/54", "naklon": 0 }, + "3847": { "label": "13/54/1", "naklon": 0 }, + "3312": { "label": "13/55", "naklon": 3 }, + "3309": { "label": "13/56", "naklon": 3 }, + "3311": { "label": "13/57", "naklon": 3 }, + "3310": { "label": "13/58", "naklon": 3 }, + "4365": { "label": "13/59", "naklon": 3 }, + "4093": { "label": "13/60/1", "naklon": 3 }, + "3304": { "label": "13/61", "naklon": 3 }, + "3307": { "label": "13/62", "naklon": 3 }, + "3271": { "label": "13/63", "naklon": 3 }, + "3301": { "label": "13/64", "naklon": 3 }, + "4366": { "label": "13/65", "naklon": 3 }, + "3300": { "label": "13/66", "naklon": 3 }, + "3185": { "label": "13/67", "naklon": 0 }, + "3184": { "label": "13/68", "naklon": 0 }, + "3188": { "label": "13/69", "naklon": 0 }, + "3343": { "label": "13/71", "naklon": 6 }, + "3819": { "label": "13/71/1", "naklon": 6 }, + "3880": { "label": "13/71/2", "naklon": 6 }, + "3348": { "label": "13/72", "naklon": 6 }, + "3344": { "label": "13/74", "naklon": 6 }, + "3346": { "label": "13/75", "naklon": 6 }, + "3597": { "label": "13/75/1", "naklon": 6 }, + "3345": { "label": "13/76", "naklon": 6 }, + "3322": { "label": "13/77", "naklon": 0 }, + "3325": { "label": "13/78", "naklon": 0 }, + "4310": { "label": "13/78/1", "naklon": 0 }, + "3315": { "label": "13/79", "naklon": 0 }, + "3328": { "label": "13/80", "naklon": 0 }, + "3321": { "label": "13/81", "naklon": 0 }, + "3324": { "label": "13/82", "naklon": 0 }, + "3140": { "label": "13/84", "naklon": 0 }, + "3153": { "label": "13/85", "naklon": 0 }, + "3145": { "label": "13/86", "naklon": 0 }, + "3134": { "label": "13/87", "naklon": 0 }, + "3151": { "label": "13/88", "naklon": 0 }, + "3143": { "label": "13/89", "naklon": 0 }, + "3318": { "label": "13/90", "naklon": 0 }, + "3347": { "label": "13/91", "naklon": 0 }, + "3314": { "label": "13/94", "naklon": 0 }, + "3331": { "label": "13/96", "naklon": 0 }, + "3327": { "label": "13/97", "naklon": 0 }, + "3329": { "label": "13/99", "naklon": 0 }, + "3337": { "label": "13/100", "naklon": 0 }, + "3330": { "label": "13/101", "naklon": 0 }, + "3335": { "label": "13/102", "naklon": 0 }, + "3420": { "label": "13/103", "naklon": 0 }, + "3421": { "label": "13/104", "naklon": 0 }, + "4361": { "label": "13/105", "naklon": 0 }, + "4362": { "label": "13/106", "naklon": 0 }, + "3526": { "label": "13/107", "naklon": 0 }, + "4424": { "label": "13/108", "naklon": null }, + "3561": { "label": "13/109", "naklon": null }, + "3527": { "label": "13/110", "naklon": null }, + "3521": { "label": "13/111", "naklon": null }, + "3552": { "label": "13/112", "naklon": null }, + "3544": { "label": "13/113", "naklon": null }, + "3534": { "label": "13/114", "naklon": null }, + "3516": { "label": "13/115", "naklon": null }, + "3513": { "label": "13/116", "naklon": null }, + "3565": { "label": "13/117", "naklon": null }, + "3866": { "label": "13/118", "naklon": null }, + "3136": { "label": "14/1", "naklon": 0 }, + "3137": { "label": "14/2", "naklon": 0 }, + "3135": { "label": "14/3", "naklon": 0 }, + "3149": { "label": "14/4", "naklon": 0 }, + "3142": { "label": "14/5", "naklon": 0 }, + "3342": { "label": "14/6", "naklon": 0 }, + "3340": { "label": "14/7", "naklon": 0 }, + "3152": { "label": "14/8", "naklon": 0 }, + "3886": { "label": "14/9", "naklon": 0 }, + "3341": { "label": "14/10", "naklon": null }, + "3352": { "label": "14/11", "naklon": null }, + "3396": { "label": "15/1", "naklon": 5 }, + "2784": { "label": "15/2", "naklon": 5 }, + "2788": { "label": "15/3", "naklon": 5 }, + "2801": { "label": "15/4", "naklon": 5 }, + "2815": { "label": "15/5", "naklon": 5 }, + "2829": { "label": "15/6", "naklon": 5 }, + "2796": { "label": "15/7", "naklon": 5 }, + "2803": { "label": "15/8", "naklon": 5 }, + "4304": { "label": "15/8/1", "naklon": 5 }, + "4311": { "label": "15/8/2", "naklon": 5 }, + "2821": { "label": "15/9", "naklon": 5 }, + "3400": { "label": "15/10", "naklon": 5 }, + "2799": { "label": "15/11", "naklon": 5 }, + "2804": { "label": "15/12", "naklon": 5 }, + "4303": { "label": "15/12/1", "naklon": 5 }, + "4309": { "label": "15/12/2", "naklon": 5 }, + "2806": { "label": "15/13", "naklon": 5 }, + "2787": { "label": "15/14", "naklon": 5 }, + "2809": { "label": "15/15", "naklon": 5 }, + "2814": { "label": "15/16", "naklon": 0 }, + "3934": { "label": "15/17", "naklon": 0 }, + "3192": { "label": "15/18", "naklon": 0 }, + "2812": { "label": "15/19", "naklon": 0 }, + "4070": { "label": "15/20", "naklon": 0 }, + "2826": { "label": "15/21", "naklon": 0 }, + "2808": { "label": "15/22", "naklon": 3 }, + "2795": { "label": "15/23", "naklon": 3 }, + "2807": { "label": "15/24", "naklon": 3 }, + "2831": { "label": "15/25", "naklon": 0 }, + "2862": { "label": "15/26", "naklon": null }, + "2861": { "label": "15/27", "naklon": 0 }, + "2866": { "label": "15/28", "naklon": 0 }, + "3546": { "label": "15/28/1", "naklon": 0 }, + "4146": { "label": "15/29", "naklon": 0 }, + "3001": { "label": "15/29/1", "naklon": 0 }, + "2835": { "label": "15/30", "naklon": 0 }, + "2874": { "label": "15/31", "naklon": 0 }, + "2852": { "label": "15/32", "naklon": 0 }, + "2851": { "label": "15/33", "naklon": 0 }, + "3560": { "label": "15/33/1", "naklon": 0 }, + "2858": { "label": "15/34", "naklon": 0 }, + "4306": { "label": "15/34/1", "naklon": 0 }, + "2856": { "label": "15/35", "naklon": 0 }, + "2847": { "label": "15/36", "naklon": 0 }, + "3556": { "label": "15/36/1", "naklon": 0 }, + "3950": { "label": "15/37", "naklon": 0 }, + "2848": { "label": "15/38", "naklon": 0 }, + "2863": { "label": "15/39", "naklon": 0 }, + "4313": { "label": "15/39/1", "naklon": 0 }, + "2873": { "label": "15/40", "naklon": 0 }, + "2984": { "label": "15/40/1", "naklon": 0 }, + "2854": { "label": "15/41", "naklon": 0 }, + "2859": { "label": "15/42", "naklon": 0 }, + "2872": { "label": "15/43", "naklon": 0 }, + "2849": { "label": "15/44", "naklon": 0 }, + "2864": { "label": "15/45", "naklon": 0 }, + "3553": { "label": "15/46", "naklon": null }, + "3021": { "label": "15/47", "naklon": null }, + "3008": { "label": "15/47/1", "naklon": null }, + "3017": { "label": "15/48", "naklon": null }, + "3014": { "label": "15/49", "naklon": null }, + "2981": { "label": "15/50", "naklon": null }, + "3020": { "label": "15/51", "naklon": null }, + "3027": { "label": "15/52", "naklon": null }, + "3006": { "label": "15/53", "naklon": null }, + "3012": { "label": "15/54", "naklon": null }, + "2738": { "label": "15/55", "naklon": 0 }, + "2725": { "label": "15/56", "naklon": 0 }, + "3016": { "label": "15/57", "naklon": null }, + "3005": { "label": "15/58", "naklon": null }, + "3009": { "label": "15/58/1", "naklon": null }, + "3010": { "label": "15/59", "naklon": 0 }, + "3538": { "label": "15/59/1", "naklon": 0 }, + "4145": { "label": "15/59/2", "naklon": 0 }, + "2713": { "label": "15/60", "naklon": 0 }, + "2789": { "label": "15/61", "naklon": 0 }, + "2736": { "label": "15/62", "naklon": 0 }, + "2739": { "label": "15/63", "naklon": 0 }, + "4346": { "label": "15/64", "naklon": 0 }, + "2731": { "label": "15/65", "naklon": 0 }, + "2818": { "label": "15/66", "naklon": 0 }, + "3557": { "label": "15/66/1", "naklon": 0 }, + "2822": { "label": "15/67", "naklon": 0 }, + "2833": { "label": "15/68", "naklon": 0 }, + "2834": { "label": "15/69", "naklon": 0 }, + "3097": { "label": "15/70", "naklon": 0 }, + "2824": { "label": "15/71", "naklon": 0 }, + "2828": { "label": "15/72", "naklon": 0 }, + "2600": { "label": "15/73", "naklon": 0 }, + "4314": { "label": "15/73/1", "naklon": 0 }, + "2832": { "label": "15/74", "naklon": 0 }, + "4360": { "label": "15/75", "naklon": 0 }, + "2846": { "label": "15/76", "naklon": 0 }, + "2584": { "label": "15/77", "naklon": 0 }, + "2843": { "label": "15/78", "naklon": 0 }, + "4308": { "label": "15/78/1", "naklon": 0 }, + "4144": { "label": "15/79", "naklon": null }, + "2844": { "label": "15/80", "naklon": 0 }, + "2842": { "label": "15/81", "naklon": 0 }, + "2838": { "label": "15/82", "naklon": 0 }, + "2837": { "label": "15/83", "naklon": null }, + "3555": { "label": "15/83/1", "naklon": null }, + "2839": { "label": "15/84", "naklon": 0 }, + "2830": { "label": "15/85", "naklon": 0 }, + "4066": { "label": "15/86", "naklon": 0 }, + "2836": { "label": "15/87", "naklon": 0 }, + "2911": { "label": "15/88", "naklon": 0 }, + "2825": { "label": "15/89", "naklon": 0 }, + "2811": { "label": "15/90", "naklon": 0 }, + "3740": { "label": "15/94", "naklon": 15 }, + "2734": { "label": "15/95", "naklon": 15 }, + "3105": { "label": "15/96", "naklon": 15 }, + "2732": { "label": "15/97", "naklon": 15 }, + "2727": { "label": "15/98", "naklon": 15 }, + "2735": { "label": "15/99", "naklon": 15 }, + "3926": { "label": "15/100", "naklon": 15 }, + "2918": { "label": "15/101", "naklon": 0 }, + "2705": { "label": "15/102", "naklon": 10 }, + "2708": { "label": "15/103", "naklon": 10 }, + "2721": { "label": "15/104", "naklon": 10 }, + "2719": { "label": "15/105", "naklon": 10 }, + "2919": { "label": "15/106", "naklon": 10 }, + "3101": { "label": "15/107", "naklon": 10 }, + "2853": { "label": "15/108", "naklon": 10 }, + "2715": { "label": "15/109", "naklon": 10 }, + "2712": { "label": "15/110", "naklon": 0 }, + "2711": { "label": "15/111", "naklon": 0 }, + "2709": { "label": "15/112", "naklon": 0 }, + "2710": { "label": "15/113", "naklon": 0 }, + "2907": { "label": "15/114", "naklon": 0 }, + "2906": { "label": "15/115", "naklon": 0 }, + "2908": { "label": "15/116", "naklon": 0 }, + "2901": { "label": "15/117", "naklon": 0 }, + "2913": { "label": "15/118", "naklon": 0 }, + "3656": { "label": "15/119", "naklon": 0 }, + "2781": { "label": "15/120", "naklon": 0 }, + "2802": { "label": "15/121", "naklon": 0 }, + "2791": { "label": "15/122", "naklon": 0 }, + "2783": { "label": "15/123", "naklon": 0 }, + "2794": { "label": "15/124", "naklon": 0 }, + "3139": { "label": "15/125", "naklon": 0 }, + "3229": { "label": "15/126", "naklon": 5 }, + "3239": { "label": "15/127", "naklon": 5 }, + "3230": { "label": "15/128", "naklon": 5 }, + "4016": { "label": "15/129", "naklon": null }, + "3608": { "label": "16/16A", "naklon": 0 }, + "4151": { "label": "16/16B", "naklon": 0 }, + "3710": { "label": "16/1", "naklon": 0 }, + "3726": { "label": "16/2", "naklon": 0 }, + "3743": { "label": "16/3", "naklon": 0 }, + "3724": { "label": "16/4", "naklon": 0 }, + "3712": { "label": "16/5", "naklon": 0 }, + "3739": { "label": "16/6", "naklon": 0 }, + "3742": { "label": "16/7", "naklon": 0 }, + "3731": { "label": "16/8", "naklon": 0 }, + "3727": { "label": "16/9", "naklon": 0 }, + "3729": { "label": "16/10", "naklon": 0 }, + "3736": { "label": "16/11", "naklon": 0 }, + "3713": { "label": "16/12", "naklon": 0 }, + "3715": { "label": "16/13", "naklon": 0 }, + "3733": { "label": "16/14", "naklon": 0 }, + "3732": { "label": "16/15", "naklon": 0 }, + "3634": { "label": "16/17", "naklon": 0 }, + "3610": { "label": "16/18", "naklon": 0 }, + "3626": { "label": "16/19", "naklon": 0 }, + "3618": { "label": "16/20", "naklon": 0 }, + "3619": { "label": "16/21", "naklon": 0 }, + "3628": { "label": "16/22", "naklon": 0 }, + "3615": { "label": "16/23", "naklon": 0 }, + "3609": { "label": "16/24", "naklon": 0 }, + "3606": { "label": "16/25", "naklon": 0 }, + "3624": { "label": "16/26", "naklon": 0 }, + "3627": { "label": "16/27", "naklon": 0 }, + "3607": { "label": "16/28", "naklon": 0 }, + "4370": { "label": "16/29", "naklon": 0 }, + "3692": { "label": "16/30", "naklon": 0 }, + "3614": { "label": "16/31", "naklon": 0 }, + "3623": { "label": "16/32", "naklon": 0 }, + "4373": { "label": "16/33", "naklon": 0 }, + "3620": { "label": "16/34", "naklon": 0 }, + "3685": { "label": "16/35", "naklon": 0 }, + "3616": { "label": "16/36", "naklon": 0 }, + "3686": { "label": "16/37", "naklon": 0 }, + "3688": { "label": "16/38", "naklon": 0 }, + "3684": { "label": "16/39", "naklon": 0 }, + "3825": { "label": "16/40", "naklon": 0 }, + "3865": { "label": "16/41", "naklon": 0 }, + "3824": { "label": "16/42", "naklon": 0 }, + "3871": { "label": "16/43", "naklon": 0 }, + "3801": { "label": "16/44", "naklon": 0 }, + "3862": { "label": "16/45", "naklon": 0 }, + "3876": { "label": "16/46", "naklon": 0 }, + "3861": { "label": "16/47", "naklon": 0 }, + "4215": { "label": "16/48", "naklon": 0 }, + "3605": { "label": "16/49", "naklon": 10 }, + "3603": { "label": "16/50", "naklon": 10 }, + "3592": { "label": "16/51", "naklon": 10 }, + "3598": { "label": "16/52", "naklon": 10 }, + "3594": { "label": "16/53", "naklon": 10 }, + "3593": { "label": "16/54", "naklon": 10 }, + "3630": { "label": "16/55", "naklon": 10 }, + "3763": { "label": "16/56", "naklon": 10 }, + "3746": { "label": "16/57", "naklon": 10 }, + "3699": { "label": "16/58", "naklon": 0 }, + "3698": { "label": "16/59", "naklon": 0 }, + "3709": { "label": "16/60", "naklon": null }, + "3708": { "label": "16/61", "naklon": 0 }, + "3703": { "label": "16/62", "naklon": null }, + "3700": { "label": "16/63", "naklon": 0 }, + "3701": { "label": "16/64", "naklon": null }, + "3704": { "label": "16/65", "naklon": 0 }, + "3707": { "label": "16/66", "naklon": null }, + "3810": { "label": "16/67", "naklon": 0 }, + "4208": { "label": "16/68", "naklon": null }, + "3867": { "label": "16/69", "naklon": 0 }, + "4372": { "label": "16/70", "naklon": null }, + "3881": { "label": "16/71", "naklon": 0 }, + "4204": { "label": "16/72", "naklon": null }, + "3869": { "label": "16/73", "naklon": 0 }, + "4202": { "label": "16/74", "naklon": null }, + "3830": { "label": "16/75", "naklon": 0 }, + "3870": { "label": "16/76", "naklon": null }, + "3964": { "label": "16/77", "naklon": 0 }, + "3849": { "label": "16/78", "naklon": 0 }, + "3694": { "label": "16/79", "naklon": null }, + "3717": { "label": "16/80", "naklon": 0 }, + "3877": { "label": "16/81", "naklon": null }, + "3755": { "label": "16/82", "naklon": 0 }, + "3725": { "label": "16/83", "naklon": null }, + "3716": { "label": "16/84", "naklon": 0 }, + "3696": { "label": "16/85", "naklon": null }, + "3702": { "label": "16/86", "naklon": 0 }, + "3706": { "label": "16/87", "naklon": null }, + "3850": { "label": "16/88", "naklon": 0 }, + "3848": { "label": "16/89", "naklon": null }, + "3737": { "label": "16/90", "naklon": null }, + "3705": { "label": "16/91", "naklon": 0 }, + "3723": { "label": "16/92", "naklon": null }, + "3842": { "label": "16/93", "naklon": 0 }, + "3735": { "label": "16/94", "naklon": null }, + "3719": { "label": "16/95", "naklon": 0 }, + "3697": { "label": "16/96", "naklon": 0 }, + "3711": { "label": "16/97", "naklon": 0 }, + "4107": { "label": "16/98", "naklon": null }, + "4112": { "label": "16/99", "naklon": 5 }, + "4106": { "label": "16/100", "naklon": 5 }, + "4111": { "label": "16/101", "naklon": 5 }, + "4091": { "label": "16/102", "naklon": null }, + "4104": { "label": "16/103", "naklon": 5 }, + "4094": { "label": "16/104", "naklon": null }, + "4089": { "label": "16/105", "naklon": 5 }, + "4095": { "label": "16/106", "naklon": null }, + "4102": { "label": "16/107", "naklon": 5 }, + "4105": { "label": "16/108", "naklon": null }, + "3859": { "label": "16/109", "naklon": null }, + "4090": { "label": "16/110", "naklon": 5 }, + "4110": { "label": "16/111", "naklon": null }, + "4097": { "label": "16/112", "naklon": 5 }, + "4099": { "label": "16/113", "naklon": null }, + "4096": { "label": "16/114", "naklon": null }, + "4101": { "label": "16/115", "naklon": 5 }, + "4109": { "label": "16/116", "naklon": null }, + "4092": { "label": "16/117", "naklon": 5 }, + "3631": { "label": "16/118", "naklon": null }, + "3632": { "label": "16/119", "naklon": 0 }, + "3641": { "label": "16/120", "naklon": null }, + "3638": { "label": "16/121", "naklon": 0 }, + "3637": { "label": "16/122", "naklon": null }, + "4142": { "label": "16/123", "naklon": null }, + "4147": { "label": "16/124", "naklon": 5 }, + "4139": { "label": "16/125", "naklon": 5 }, + "3172": { "label": "20/30A", "naklon": 2 }, + "3164": { "label": "20/30B", "naklon": 2 }, + "3247": { "label": "20/1", "naklon": 10 }, + "3296": { "label": "20/2", "naklon": 10 }, + "3246": { "label": "20/3", "naklon": 10 }, + "3270": { "label": "20/4", "naklon": 10 }, + "3294": { "label": "20/5", "naklon": 10 }, + "3298": { "label": "20/6", "naklon": 10 }, + "3297": { "label": "20/7", "naklon": 10 }, + "3293": { "label": "20/8", "naklon": 10 }, + "3299": { "label": "20/9", "naklon": 10 }, + "3295": { "label": "20/10", "naklon": 10 }, + "3244": { "label": "20/11", "naklon": 10 }, + "3249": { "label": "20/12", "naklon": 10 }, + "3268": { "label": "20/13", "naklon": 10 }, + "3245": { "label": "20/14", "naklon": 10 }, + "3278": { "label": "20/15", "naklon": 10 }, + "3280": { "label": "20/16", "naklon": 10 }, + "3292": { "label": "20/17", "naklon": 10 }, + "3287": { "label": "20/18", "naklon": 10 }, + "3282": { "label": "20/19", "naklon": 10 }, + "3273": { "label": "20/20", "naklon": 0 }, + "3157": { "label": "20/21", "naklon": 0 }, + "3283": { "label": "20/22", "naklon": 0 }, + "3159": { "label": "20/23", "naklon": 0 }, + "3289": { "label": "20/24", "naklon": 0 }, + "3163": { "label": "20/25", "naklon": 0 }, + "3126": { "label": "20/26", "naklon": 0 }, + "3171": { "label": "20/27", "naklon": 0 }, + "3162": { "label": "20/28", "naklon": 0 }, + "3279": { "label": "20/29", "naklon": 10 }, + "3173": { "label": "20/31", "naklon": 0 }, + "3127": { "label": "20/32", "naklon": 0 }, + "3131": { "label": "20/33", "naklon": 0 }, + "3129": { "label": "20/34", "naklon": 0 }, + "3276": { "label": "20/35", "naklon": 2 }, + "3290": { "label": "20/36", "naklon": 2 }, + "3132": { "label": "20/37", "naklon": 0 }, + "3138": { "label": "20/38", "naklon": 0 }, + "3272": { "label": "20/39", "naklon": 0 }, + "3291": { "label": "20/40", "naklon": 0 }, + "3277": { "label": "20/41", "naklon": 10 }, + "3286": { "label": "20/42", "naklon": 10 }, + "3281": { "label": "20/43", "naklon": 10 }, + "3288": { "label": "20/44", "naklon": 10 }, + "3284": { "label": "20/45", "naklon": 10 }, + "3167": { "label": "20/46", "naklon": 10 }, + "3872": { "label": "20/47", "naklon": 0 }, + "3124": { "label": "20/48", "naklon": 0 }, + "3133": { "label": "20/49", "naklon": 0 }, + "3158": { "label": "20/50", "naklon": 0 }, + "3169": { "label": "20/51", "naklon": 0 }, + "3146": { "label": "20/52", "naklon": 0 }, + "3160": { "label": "20/53", "naklon": 0 }, + "3248": { "label": "20/54", "naklon": 0 }, + "3156": { "label": "20/55", "naklon": 0 }, + "3161": { "label": "20/56", "naklon": 0 }, + "3170": { "label": "20/57", "naklon": 0 }, + "3168": { "label": "20/58", "naklon": 0 }, + "3125": { "label": "20/59", "naklon": 0 }, + "3166": { "label": "20/60", "naklon": 0 }, + "3130": { "label": "20/61", "naklon": 0 }, + "3563": { "label": "20/62", "naklon": 0 }, + "3550": { "label": "20/63", "naklon": null }, + "3269": { "label": "20/67", "naklon": 0 }, + "2921": { "label": "21/1", "naklon": 0 }, + "2707": { "label": "21/2", "naklon": 0 }, + "2723": { "label": "21/3", "naklon": 0 }, + "2716": { "label": "21/4", "naklon": 0 }, + "2717": { "label": "21/5", "naklon": 0 }, + "2720": { "label": "21/6", "naklon": 0 }, + "2722": { "label": "21/7", "naklon": 0 }, + "2718": { "label": "21/8", "naklon": 0 }, + "2724": { "label": "21/9", "naklon": 0 }, + "2742": { "label": "21/10", "naklon": 0 }, + "2743": { "label": "21/11", "naklon": 0 }, + "2733": { "label": "21/12", "naklon": 0 }, + "2903": { "label": "21/14", "naklon": 0 }, + "2917": { "label": "21/15", "naklon": 0 }, + "2897": { "label": "21/16", "naklon": 0 }, + "2914": { "label": "21/17", "naklon": 0 }, + "2898": { "label": "21/18", "naklon": 0 }, + "2773": { "label": "21/19", "naklon": 0 }, + "2895": { "label": "21/20", "naklon": 0 }, + "2896": { "label": "21/21", "naklon": 0 }, + "2771": { "label": "21/22", "naklon": 0 }, + "2772": { "label": "21/23", "naklon": 0 }, + "2793": { "label": "21/24", "naklon": 0 }, + "2902": { "label": "21/25", "naklon": 0 }, + "2910": { "label": "21/26", "naklon": 0 }, + "2909": { "label": "21/27", "naklon": 0 }, + "2920": { "label": "21/28", "naklon": 0 }, + "2916": { "label": "21/29", "naklon": 0 }, + "2904": { "label": "21/30", "naklon": 0 }, + "2915": { "label": "21/31", "naklon": 0 }, + "2905": { "label": "21/32", "naklon": 0 }, + "2900": { "label": "21/33", "naklon": 0 }, + "2899": { "label": "21/34", "naklon": 0 }, + "2741": { "label": "21/36", "naklon": 0 }, + "2714": { "label": "21/37", "naklon": 0 }, + "2701": { "label": "21/38", "naklon": 0 }, + "2703": { "label": "21/39", "naklon": 0 }, + "2704": { "label": "21/40", "naklon": 0 }, + "2702": { "label": "21/41", "naklon": 0 }, + "2706": { "label": "21/42", "naklon": 0 }, + "2776": { "label": "21/43", "naklon": 0 }, + "2770": { "label": "21/44", "naklon": 0 }, + "2786": { "label": "21/45", "naklon": 0 }, + "2779": { "label": "21/46", "naklon": 0 }, + "2782": { "label": "21/47", "naklon": 0 }, + "2785": { "label": "21/48", "naklon": 0 }, + "2769": { "label": "21/49", "naklon": 0 }, + "3354": { "label": "21/50", "naklon": 0 }, + "2778": { "label": "21/51", "naklon": 0 }, + "2775": { "label": "21/52", "naklon": 0 }, + "2780": { "label": "21/53", "naklon": 0 }, + "2790": { "label": "21/54", "naklon": 0 }, + "2792": { "label": "21/55", "naklon": 0 }, + "2774": { "label": "21/56", "naklon": 0 }, + "2630": { "label": "22/1", "naklon": 0 }, + "2631": { "label": "22/2", "naklon": 0 }, + "2632": { "label": "22/3", "naklon": 0 }, + "2633": { "label": "22/4", "naklon": 0 }, + "2634": { "label": "22/5", "naklon": 0 }, + "2636": { "label": "22/6", "naklon": 0 }, + "4367": { "label": "22/7", "naklon": 0 }, + "2637": { "label": "22/8", "naklon": 0 }, + "2638": { "label": "22/9", "naklon": 0 }, + "2639": { "label": "22/10", "naklon": 0 }, + "2640": { "label": "22/11", "naklon": 0 }, + "2641": { "label": "22/12", "naklon": 0 }, + "2642": { "label": "22/13", "naklon": 0 }, + "2643": { "label": "22/14", "naklon": 0 }, + "2644": { "label": "22/15", "naklon": 0 }, + "2645": { "label": "22/16", "naklon": 0 }, + "2646": { "label": "22/17", "naklon": 0 }, + "2647": { "label": "22/18", "naklon": 0 }, + "2648": { "label": "22/19", "naklon": 0 }, + "2649": { "label": "22/20", "naklon": 0 }, + "2650": { "label": "22/21", "naklon": 0 }, + "2651": { "label": "22/22", "naklon": 0 }, + "4103": { "label": "22/23", "naklon": 0 }, + "2653": { "label": "22/24", "naklon": 0 }, + "2654": { "label": "22/25", "naklon": 0 }, + "2655": { "label": "22/26", "naklon": 0 }, + "2656": { "label": "22/27", "naklon": 0 }, + "2657": { "label": "22/28", "naklon": 0 }, + "2658": { "label": "22/29", "naklon": 0 }, + "2659": { "label": "22/30", "naklon": 0 }, + "2660": { "label": "22/31", "naklon": 0 }, + "2661": { "label": "22/32", "naklon": 0 }, + "3015": { "label": "22/32/1", "naklon": 0 }, + "2662": { "label": "22/33", "naklon": 0 }, + "2663": { "label": "22/34", "naklon": 0 }, + "2664": { "label": "22/35", "naklon": 0 }, + "2665": { "label": "22/36", "naklon": 0 }, + "2666": { "label": "22/37", "naklon": 0 }, + "2667": { "label": "22/38", "naklon": 0 }, + "2668": { "label": "22/39", "naklon": 0 }, + "2669": { "label": "22/40", "naklon": null }, + "2670": { "label": "22/41", "naklon": null }, + "2671": { "label": "22/42", "naklon": null }, + "3087": { "label": "23/9A", "naklon": 10 }, + "3090": { "label": "23/9B", "naklon": 10 }, + "3075": { "label": "23/1", "naklon": 0 }, + "3089": { "label": "23/2", "naklon": 0 }, + "3088": { "label": "23/3", "naklon": 0 }, + "3228": { "label": "23/4", "naklon": 10 }, + "2751": { "label": "23/5", "naklon": 10 }, + "3243": { "label": "23/6", "naklon": 10 }, + "4349": { "label": "23/7", "naklon": 10 }, + "3102": { "label": "23/8", "naklon": 10 }, + "3099": { "label": "23/10", "naklon": 10 }, + "3103": { "label": "23/11", "naklon": 10 }, + "3093": { "label": "23/12", "naklon": 10 }, + "3098": { "label": "23/13", "naklon": 10 }, + "3092": { "label": "23/14", "naklon": 10 }, + "3233": { "label": "23/15", "naklon": 0 }, + "3095": { "label": "23/16", "naklon": 0 }, + "4074": { "label": "23/17", "naklon": 0 }, + "2729": { "label": "23/18", "naklon": 0 }, + "3234": { "label": "23/19", "naklon": 0 }, + "3094": { "label": "23/20", "naklon": 0 }, + "2817": { "label": "23/21", "naklon": 0 }, + "3226": { "label": "23/22", "naklon": 0 }, + "3225": { "label": "23/23", "naklon": 0 }, + "3237": { "label": "23/24", "naklon": 0 }, + "4250": { "label": "23/25", "naklon": 0 }, + "3059": { "label": "23/26", "naklon": 10 }, + "3238": { "label": "23/27", "naklon": 10 }, + "3242": { "label": "23/28", "naklon": 10 }, + "3236": { "label": "23/29", "naklon": 10 }, + "3112": { "label": "23/30", "naklon": 10 }, + "3224": { "label": "23/31", "naklon": 0 }, + "4298": { "label": "23/32", "naklon": 10 }, + "4150": { "label": "23/33", "naklon": 10 }, + "3091": { "label": "23/34", "naklon": 10 }, + "3771": { "label": "25/1", "naklon": 5 }, + "3777": { "label": "25/2", "naklon": 5 }, + "3749": { "label": "25/3", "naklon": 5 }, + "3769": { "label": "25/4", "naklon": 5 }, + "3765": { "label": "25/5", "naklon": 5 }, + "3785": { "label": "25/6", "naklon": 5 }, + "3761": { "label": "25/7", "naklon": 5 }, + "3758": { "label": "25/8", "naklon": 5 }, + "3766": { "label": "25/9", "naklon": 5 }, + "3779": { "label": "25/10", "naklon": 5 }, + "3899": { "label": "25/11", "naklon": 10 }, + "3922": { "label": "25/12", "naklon": 10 }, + "3912": { "label": "25/13", "naklon": 10 }, + "3933": { "label": "25/14", "naklon": 10 }, + "3921": { "label": "25/15", "naklon": 10 }, + "4300": { "label": "25/16", "naklon": 10 }, + "3927": { "label": "25/17", "naklon": 10 }, + "3212": { "label": "25/18", "naklon": 10 }, + "3208": { "label": "25/19", "naklon": 10 }, + "3207": { "label": "25/20", "naklon": 10 }, + "4294": { "label": "25/21", "naklon": 10 }, + "3209": { "label": "25/22", "naklon": 10 }, + "3745": { "label": "25/23", "naklon": 10 }, + "3762": { "label": "25/24", "naklon": 10 }, + "3215": { "label": "25/25", "naklon": 10 }, + "3210": { "label": "25/26", "naklon": 10 }, + "3211": { "label": "25/27", "naklon": 10 }, + "3206": { "label": "25/28", "naklon": 10 }, + "3918": { "label": "25/29", "naklon": 5 }, + "3928": { "label": "25/30", "naklon": 5 }, + "3917": { "label": "25/31", "naklon": 5 }, + "4029": { "label": "25/32", "naklon": 0 }, + "4038": { "label": "25/33", "naklon": 0 }, + "4022": { "label": "25/34", "naklon": 0 }, + "3937": { "label": "25/35", "naklon": 0 }, + "3190": { "label": "25/36", "naklon": 0 }, + "3835": { "label": "25/37", "naklon": 0 }, + "3201": { "label": "25/38", "naklon": 0 }, + "3193": { "label": "25/39", "naklon": 0 }, + "3191": { "label": "25/40", "naklon": 0 }, + "3203": { "label": "25/41", "naklon": 0 }, + "4301": { "label": "25/42", "naklon": 0 }, + "3223": { "label": "25/43", "naklon": 0 }, + "3202": { "label": "25/44", "naklon": 0 }, + "3205": { "label": "25/45", "naklon": 0 }, + "3194": { "label": "25/46", "naklon": 0 }, + "3198": { "label": "25/47", "naklon": 0 }, + "3204": { "label": "25/48", "naklon": 0 }, + "3200": { "label": "25/49", "naklon": 0 }, + "3216": { "label": "25/50", "naklon": 0 }, + "3932": { "label": "25/51", "naklon": 5 }, + "3923": { "label": "25/52", "naklon": 5 }, + "3913": { "label": "25/53", "naklon": 5 }, + "3900": { "label": "25/54", "naklon": 5 }, + "4189": { "label": "25/55", "naklon": 10 }, + "4191": { "label": "25/56", "naklon": 10 }, + "3790": { "label": "25/57", "naklon": 10 }, + "4190": { "label": "25/58", "naklon": 10 }, + "4302": { "label": "25/59", "naklon": 0 }, + "4351": { "label": "25/60", "naklon": 0 }, + "4075": { "label": "25/61", "naklon": 0 }, + "4071": { "label": "25/62", "naklon": 0 }, + "3784": { "label": "25/63", "naklon": 0 }, + "4065": { "label": "25/64", "naklon": 0 }, + "4297": { "label": "25/65", "naklon": 0 }, + "4295": { "label": "25/66", "naklon": 0 }, + "4299": { "label": "25/67", "naklon": 0 }, + "3772": { "label": "25/68", "naklon": 0 }, + "3941": { "label": "25/69", "naklon": 0 }, + "3782": { "label": "25/70", "naklon": 0 }, + "4068": { "label": "25/71", "naklon": 0 }, + "4073": { "label": "25/72", "naklon": 0 }, + "3901": { "label": "25/73", "naklon": 5 }, + "4296": { "label": "25/74", "naklon": 5 }, + "3910": { "label": "25/75", "naklon": 5 }, + "4293": { "label": "25/76", "naklon": 5 }, + "3919": { "label": "25/77", "naklon": 5 }, + "3924": { "label": "25/78", "naklon": 5 }, + "3909": { "label": "25/79", "naklon": 5 }, + "3896": { "label": "25/80", "naklon": 5 }, + "3911": { "label": "25/81", "naklon": 5 }, + "2819": { "label": "25/82", "naklon": 15 }, + "3776": { "label": "25/83", "naklon": 15 }, + "3752": { "label": "25/84", "naklon": 15 }, + "4353": { "label": "25/85", "naklon": 15 }, + "3791": { "label": "25/86", "naklon": 0 }, + "3770": { "label": "25/87", "naklon": 0 }, + "3760": { "label": "25/88", "naklon": 0 }, + "3115": { "label": "25/89", "naklon": 0 }, + "3738": { "label": "25/90", "naklon": 0 }, + "3748": { "label": "25/91", "naklon": 0 }, + "3753": { "label": "25/92", "naklon": 0 }, + "3775": { "label": "25/93", "naklon": 0 }, + "3778": { "label": "25/94", "naklon": 5 }, + "4078": { "label": "25/95", "naklon": 5 }, + "4088": { "label": "25/96", "naklon": 5 }, + "3856": { "label": "25/97", "naklon": 5 }, + "4084": { "label": "25/98", "naklon": 5 }, + "4069": { "label": "25/99", "naklon": 5 }, + "4188": { "label": "25/100", "naklon": 5 }, + "4064": { "label": "25/101", "naklon": 5 }, + "3792": { "label": "25/102", "naklon": 5 }, + "3780": { "label": "25/103", "naklon": 5 }, + "4034": { "label": "25/104", "naklon": 5 }, + "4072": { "label": "25/105", "naklon": 5 }, + "3884": { "label": "25/106", "naklon": 5 }, + "3793": { "label": "25/107", "naklon": 5 }, + "3863": { "label": "25/108", "naklon": 5 }, + "3855": { "label": "25/109", "naklon": 5 }, + "3846": { "label": "33/1", "naklon": 0 }, + "3943": { "label": "33/2", "naklon": 0 }, + "3903": { "label": "33/3", "naklon": 0 }, + "3982": { "label": "33/4", "naklon": 0 }, + "3879": { "label": "33/5", "naklon": 0 }, + "3887": { "label": "33/6", "naklon": 0 }, + "3920": { "label": "33/7", "naklon": 5 }, + "3942": { "label": "33/8", "naklon": 5 }, + "3829": { "label": "33/9", "naklon": null }, + "3452": { "label": "34/79A", "naklon": 6 }, + "3460": { "label": "34/79B", "naklon": 6 }, + "3443": { "label": "34/90A", "naklon": 6 }, + "3445": { "label": "34/90B", "naklon": 6 }, + "3457": { "label": "34/90C", "naklon": 6 }, + "3461": { "label": "34/97A", "naklon": 6 }, + "3463": { "label": "34/97B", "naklon": 6 }, + "3426": { "label": "34/98A", "naklon": 6 }, + "3444": { "label": "34/98B", "naklon": 6 }, + "3453": { "label": "34/99A", "naklon": 6 }, + "3455": { "label": "34/99B", "naklon": 6 }, + "4009": { "label": "34/1", "naklon": 0 }, + "3602": { "label": "34/2", "naklon": 0 }, + "3441": { "label": "34/3", "naklon": 0 }, + "3464": { "label": "34/4", "naklon": 0 }, + "3883": { "label": "34/5", "naklon": 0 }, + "4098": { "label": "34/6", "naklon": 0 }, + "4003": { "label": "34/7", "naklon": 0 }, + "4004": { "label": "34/8", "naklon": 0 }, + "3888": { "label": "34/9", "naklon": 0 }, + "3997": { "label": "34/10", "naklon": 0 }, + "4006": { "label": "34/11", "naklon": 0 }, + "4000": { "label": "34/12", "naklon": 0 }, + "4011": { "label": "34/13", "naklon": 0 }, + "3999": { "label": "34/14", "naklon": 0 }, + "3981": { "label": "34/15", "naklon": 0 }, + "3988": { "label": "34/16", "naklon": 0 }, + "3986": { "label": "34/17", "naklon": 0 }, + "3998": { "label": "34/18", "naklon": 0 }, + "3983": { "label": "34/19", "naklon": 0 }, + "4005": { "label": "34/20", "naklon": 0 }, + "4001": { "label": "34/21", "naklon": 0 }, + "4008": { "label": "34/22", "naklon": 0 }, + "4002": { "label": "34/23", "naklon": 0 }, + "3996": { "label": "34/24", "naklon": 0 }, + "4007": { "label": "34/25", "naklon": 0 }, + "4113": { "label": "34/26", "naklon": 15 }, + "3595": { "label": "34/27", "naklon": 5 }, + "3599": { "label": "34/28", "naklon": 5 }, + "3601": { "label": "34/29", "naklon": 5 }, + "4205": { "label": "34/30", "naklon": 0 }, + "3987": { "label": "34/31", "naklon": null }, + "4214": { "label": "34/32", "naklon": 0 }, + "4226": { "label": "34/33", "naklon": 0 }, + "4209": { "label": "34/34", "naklon": 0 }, + "4201": { "label": "34/35", "naklon": 0 }, + "3440": { "label": "34/36", "naklon": 0 }, + "3465": { "label": "34/37", "naklon": 0 }, + "3446": { "label": "34/38", "naklon": 0 }, + "4039": { "label": "34/39", "naklon": 5 }, + "4057": { "label": "34/40", "naklon": 5 }, + "3985": { "label": "34/41", "naklon": 0 }, + "3882": { "label": "34/42", "naklon": 0 }, + "4040": { "label": "34/43", "naklon": 5 }, + "3231": { "label": "34/44", "naklon": 0 }, + "3227": { "label": "34/45", "naklon": 0 }, + "3431": { "label": "34/46", "naklon": 0 }, + "4013": { "label": "34/47", "naklon": 0 }, + "4045": { "label": "34/48", "naklon": 0 }, + "3949": { "label": "34/49", "naklon": 0 }, + "3953": { "label": "34/50", "naklon": 0 }, + "3952": { "label": "34/51", "naklon": 0 }, + "3995": { "label": "34/52", "naklon": 0 }, + "3992": { "label": "34/53", "naklon": 0 }, + "4198": { "label": "34/54", "naklon": 0 }, + "3935": { "label": "34/55", "naklon": 0 }, + "4050": { "label": "34/56", "naklon": 0 }, + "4049": { "label": "34/57", "naklon": 0 }, + "4054": { "label": "34/58", "naklon": 0 }, + "3663": { "label": "34/59", "naklon": 6 }, + "3661": { "label": "34/60", "naklon": 6 }, + "3664": { "label": "34/61", "naklon": 6 }, + "3660": { "label": "34/62", "naklon": 6 }, + "3662": { "label": "34/63", "naklon": 6 }, + "3665": { "label": "34/65", "naklon": 6 }, + "3667": { "label": "34/66", "naklon": 6 }, + "3675": { "label": "34/67", "naklon": 6 }, + "3666": { "label": "34/68", "naklon": 6 }, + "3652": { "label": "34/69", "naklon": 6 }, + "3458": { "label": "34/70", "naklon": 6 }, + "4425": { "label": "34/70/1", "naklon": 6 }, + "3459": { "label": "34/71", "naklon": 6 }, + "3435": { "label": "34/72", "naklon": 6 }, + "3448": { "label": "34/73", "naklon": 6 }, + "3451": { "label": "34/74", "naklon": 6 }, + "3442": { "label": "34/75", "naklon": 6 }, + "3449": { "label": "34/76", "naklon": 6 }, + "3450": { "label": "34/77", "naklon": 6 }, + "3433": { "label": "34/78", "naklon": 6 }, + "3432": { "label": "34/80", "naklon": 12 }, + "3470": { "label": "34/81", "naklon": 12 }, + "3438": { "label": "34/82", "naklon": 12 }, + "3439": { "label": "34/83", "naklon": 12 }, + "4028": { "label": "34/84", "naklon": 5 }, + "3596": { "label": "34/85", "naklon": 5 }, + "4021": { "label": "34/86", "naklon": 5 }, + "3437": { "label": "34/87", "naklon": 12 }, + "3428": { "label": "34/88", "naklon": 12 }, + "3430": { "label": "34/89", "naklon": 12 }, + "3454": { "label": "34/91", "naklon": 6 }, + "3492": { "label": "34/92", "naklon": 6 }, + "3462": { "label": "34/93", "naklon": 6 }, + "3427": { "label": "34/94", "naklon": 6 }, + "3434": { "label": "34/95", "naklon": 6 }, + "3456": { "label": "34/96", "naklon": 6 }, + "4307": { "label": "34/98/1", "naklon": 6 }, + "3968": { "label": "35/1", "naklon": 0 }, + "3969": { "label": "35/2", "naklon": 0 }, + "3947": { "label": "35/3", "naklon": 0 }, + "3979": { "label": "35/4", "naklon": 0 }, + "3959": { "label": "35/5", "naklon": 0 }, + "3948": { "label": "35/6", "naklon": 0 }, + "3961": { "label": "35/7", "naklon": 0 }, + "3956": { "label": "35/8", "naklon": 0 }, + "3604": { "label": "35/9", "naklon": 0 }, + "3944": { "label": "35/10", "naklon": 0 }, + "3960": { "label": "35/11", "naklon": 0 }, + "3958": { "label": "35/12", "naklon": 0 }, + "4036": { "label": "35/13", "naklon": 5 }, + "3893": { "label": "35/18", "naklon": 5 }, + "4108": { "label": "35/19", "naklon": 5 }, + "4017": { "label": "35/20", "naklon": 5 }, + "3963": { "label": "35/21", "naklon": 0 }, + "3658": { "label": "35/22", "naklon": 0 }, + "3975": { "label": "35/23", "naklon": 0 }, + "3980": { "label": "35/24", "naklon": 0 }, + "4012": { "label": "35/25", "naklon": 0 }, + "3655": { "label": "35/26", "naklon": 0 }, + "3962": { "label": "35/27", "naklon": 0 }, + "3945": { "label": "35/28", "naklon": 0 }, + "3569": { "label": "35/29", "naklon": 0 }, + "3429": { "label": "35/30", "naklon": 0 }, + "3657": { "label": "35/31", "naklon": 0 }, + "3646": { "label": "35/32", "naklon": 0 }, + "3622": { "label": "35/33", "naklon": 0 }, + "3612": { "label": "35/34", "naklon": 0 }, + "3955": { "label": "35/35", "naklon": 0 }, + "3878": { "label": "35/37", "naklon": 0 }, + "3965": { "label": "35/38", "naklon": 0 }, + "3970": { "label": "35/39", "naklon": 0 }, + "3611": { "label": "35/40", "naklon": 0 }, + "2635": { "label": "35/41", "naklon": 0 }, + "3978": { "label": "35/42", "naklon": 0 }, + "4213": { "label": "35/43", "naklon": 0 }, + "3984": { "label": "35/44", "naklon": 0 }, + "4218": { "label": "35/45", "naklon": 0 }, + "3973": { "label": "35/46", "naklon": 0 }, + "3974": { "label": "35/47", "naklon": 0 }, + "3759": { "label": "35/48", "naklon": 0 }, + "3844": { "label": "35/49", "naklon": 0 }, + "3804": { "label": "35/50", "naklon": 0 }, + "3831": { "label": "35/51", "naklon": 0 }, + "3643": { "label": "35/52", "naklon": 0 }, + "3966": { "label": "35/53", "naklon": 0 }, + "3971": { "label": "35/54", "naklon": 0 }, + "3650": { "label": "35/55", "naklon": 6 }, + "3651": { "label": "35/56", "naklon": 6 }, + "3669": { "label": "35/57", "naklon": 6 }, + "3648": { "label": "35/58", "naklon": 6 }, + "3645": { "label": "35/59", "naklon": 6 }, + "3659": { "label": "35/60", "naklon": 6 }, + "3647": { "label": "35/61", "naklon": 6 }, + "3644": { "label": "35/62", "naklon": 6 }, + "3671": { "label": "35/63", "naklon": 6 }, + "3682": { "label": "35/64", "naklon": 6 }, + "3672": { "label": "35/65", "naklon": 6 }, + "3683": { "label": "35/66", "naklon": 6 }, + "3673": { "label": "35/67", "naklon": 6 }, + "3674": { "label": "35/68", "naklon": 6 }, + "3679": { "label": "35/69", "naklon": 6 }, + "3649": { "label": "35/70", "naklon": 6 }, + "3687": { "label": "35/71", "naklon": 6 }, + "3677": { "label": "35/72", "naklon": 6 }, + "3690": { "label": "35/73", "naklon": 6 }, + "3691": { "label": "35/74", "naklon": 6 }, + "3676": { "label": "35/75", "naklon": 6 }, + "3680": { "label": "35/76", "naklon": 6 }, + "3668": { "label": "35/77", "naklon": 6 }, + "3681": { "label": "35/78", "naklon": 6 }, + "3670": { "label": "35/79", "naklon": 6 }, + "3689": { "label": "35/80", "naklon": 6 }, + "3678": { "label": "35/81", "naklon": 6 }, + "3693": { "label": "35/82", "naklon": 6 }, + "3654": { "label": "35/83", "naklon": null }, + "4086": { "label": "36/1", "naklon": 0 }, + "4085": { "label": "36/2", "naklon": 0 }, + "4083": { "label": "36/3", "naklon": 0 }, + "4087": { "label": "36/4", "naklon": 0 }, + "4077": { "label": "36/5", "naklon": 0 }, + "4082": { "label": "36/6", "naklon": 0 }, + "4186": { "label": "36/7", "naklon": 0 }, + "4206": { "label": "36/8", "naklon": 0 }, + "4080": { "label": "36/9", "naklon": 0 }, + "4081": { "label": "36/10", "naklon": 0 }, + "4210": { "label": "36/11", "naklon": 0 }, + "4079": { "label": "36/12", "naklon": 0 }, + "4076": { "label": "36/13", "naklon": 0 }, + "3852": { "label": "36/14", "naklon": 0 }, + "2813": { "label": "36/15", "naklon": 0 }, + "4219": { "label": "36/16", "naklon": 0 }, + "3104": { "label": "37/1A", "naklon": 15 }, + "3121": { "label": "37/1B", "naklon": 15 }, + "3113": { "label": "37/2", "naklon": 10 }, + "3118": { "label": "37/3", "naklon": 10 }, + "3111": { "label": "37/4", "naklon": 10 }, + "4020": { "label": "37/5", "naklon": 10 }, + "3119": { "label": "37/6", "naklon": 10 }, + "3110": { "label": "37/7", "naklon": 10 }, + "3108": { "label": "37/8", "naklon": 10 }, + "3107": { "label": "37/12", "naklon": 0 }, + "3199": { "label": "37/13", "naklon": 0 }, + "3120": { "label": "37/14", "naklon": 0 }, + "3122": { "label": "37/15", "naklon": 0 }, + "3908": { "label": "37/16", "naklon": 0 }, + "3114": { "label": "37/17", "naklon": 0 }, + "3105": { "label": "37/18", "naklon": 0 }, + "3116": { "label": "37/19", "naklon": 0 }, + "3106": { "label": "37/20", "naklon": 0 }, + "2887": { "label": "37/21", "naklon": 5 }, + "2888": { "label": "37/22", "naklon": 5 }, + "2877": { "label": "37/23", "naklon": 5 }, + "2891": { "label": "37/24", "naklon": 5 }, + "2886": { "label": "37/25", "naklon": 5 }, + "2892": { "label": "37/26", "naklon": 5 }, + "2882": { "label": "37/27", "naklon": 5 }, + "2883": { "label": "37/28", "naklon": 5 }, + "2876": { "label": "37/29", "naklon": 5 }, + "3109": { "label": "37/30", "naklon": 5 }, + "4152": { "label": "37/31", "naklon": 5 }, + "3117": { "label": "37/32", "naklon": 5 }, + "2870": { "label": "37/33", "naklon": 5 }, + "2867": { "label": "37/34", "naklon": 0 }, + "2865": { "label": "37/35", "naklon": 0 }, + "3096": { "label": "37/36", "naklon": 0 }, + "2871": { "label": "37/37", "naklon": 0 }, + "2884": { "label": "37/38", "naklon": 0 }, + "2855": { "label": "37/39", "naklon": 0 }, + "2878": { "label": "37/40", "naklon": 0 }, + "2889": { "label": "37/41", "naklon": 0 }, + "2879": { "label": "37/42", "naklon": 0 }, + "2850": { "label": "37/43", "naklon": 0 }, + "2894": { "label": "37/44", "naklon": 0 }, + "2880": { "label": "37/45", "naklon": 0 }, + "2893": { "label": "37/46", "naklon": 0 }, + "2890": { "label": "37/47", "naklon": 0 }, + "4355": { "label": "37/48", "naklon": 0 }, + "2885": { "label": "37/49", "naklon": 0 }, + "2875": { "label": "37/50", "naklon": 0 }, + "3486": { "label": "38/30A", "naklon": 5 }, + "3714": { "label": "38/30B", "naklon": 0 }, + "3483": { "label": "38/32A", "naklon": 5 }, + "3496": { "label": "38/32B", "naklon": 0 }, + "3487": { "label": "38/35A", "naklon": 5 }, + "3498": { "label": "38/35B", "naklon": 5 }, + "3578": { "label": "38/38A", "naklon": 5 }, + "3508": { "label": "38/38B", "naklon": 5 }, + "3787": { "label": "38/59A", "naklon": 5 }, + "3491": { "label": "38/59B", "naklon": 5 }, + "3568": { "label": "38/1", "naklon": null }, + "3502": { "label": "38/2", "naklon": 0 }, + "3836": { "label": "38/3", "naklon": 0 }, + "3588": { "label": "38/4", "naklon": 0 }, + "3493": { "label": "38/5", "naklon": 0 }, + "3580": { "label": "38/6", "naklon": 0 }, + "3572": { "label": "38/7", "naklon": 0 }, + "3506": { "label": "38/8", "naklon": 0 }, + "3503": { "label": "38/9", "naklon": 0 }, + "3579": { "label": "38/10", "naklon": 0 }, + "3586": { "label": "38/11", "naklon": 0 }, + "3495": { "label": "38/12", "naklon": 5 }, + "3492": { "label": "38/13", "naklon": 5 }, + "3532": { "label": "38/14", "naklon": 5 }, + "3574": { "label": "38/15", "naklon": 5 }, + "4140": { "label": "38/16", "naklon": 5 }, + "3795": { "label": "38/17", "naklon": 5 }, + "3788": { "label": "38/18", "naklon": 5 }, + "3796": { "label": "38/19", "naklon": 5 }, + "3797": { "label": "38/20", "naklon": 5 }, + "3798": { "label": "38/21", "naklon": 5 }, + "3786": { "label": "38/22", "naklon": 5 }, + "4067": { "label": "38/23", "naklon": 5 }, + "3773": { "label": "38/24", "naklon": 5 }, + "3774": { "label": "38/25", "naklon": 5 }, + "3789": { "label": "38/26", "naklon": 5 }, + "3520": { "label": "38/27", "naklon": null }, + "3577": { "label": "38/29", "naklon": 5 }, + "3530": { "label": "38/31", "naklon": null }, + "3488": { "label": "38/33", "naklon": 5 }, + "3505": { "label": "38/34", "naklon": 5 }, + "3497": { "label": "38/36", "naklon": 5 }, + "3490": { "label": "38/37", "naklon": 5 }, + "3585": { "label": "38/39", "naklon": 5 }, + "3582": { "label": "38/40", "naklon": 5 }, + "3507": { "label": "38/41", "naklon": 5 }, + "3484": { "label": "38/42", "naklon": 5 }, + "3501": { "label": "38/43", "naklon": 5 }, + "3581": { "label": "38/44", "naklon": 5 }, + "4192": { "label": "38/45", "naklon": 5 }, + "3576": { "label": "38/46", "naklon": 5 }, + "3489": { "label": "38/47", "naklon": 5 }, + "3573": { "label": "38/48", "naklon": 5 }, + "3504": { "label": "38/49", "naklon": 5 }, + "3794": { "label": "38/50", "naklon": 5 }, + "3485": { "label": "38/51", "naklon": 5 }, + "3482": { "label": "38/52", "naklon": 5 }, + "3575": { "label": "38/53", "naklon": 5 }, + "3499": { "label": "38/54", "naklon": 5 }, + "3494": { "label": "38/55", "naklon": 5 }, + "3583": { "label": "38/56", "naklon": 5 }, + "3570": { "label": "38/57", "naklon": 5 }, + "3500": { "label": "38/58", "naklon": 0 }, + "3510": { "label": "38/63", "naklon": null }, + "3512": { "label": "38/64", "naklon": null }, + "3535": { "label": "38/67", "naklon": null }, + "3531": { "label": "38/68", "naklon": null }, + "3537": { "label": "38/69", "naklon": null }, + "3522": { "label": "39/1", "naklon": 10 }, + "4018": { "label": "39/2", "naklon": 10 }, + "4019": { "label": "39/3", "naklon": 10 }, + "4154": { "label": "39/4", "naklon": 5 }, + "3907": { "label": "39/5", "naklon": 5 }, + "4148": { "label": "39/6", "naklon": 0 }, + "4153": { "label": "39/7", "naklon": 0 }, + "3938": { "label": "39/8", "naklon": 0 }, + "3802": { "label": "39/9", "naklon": 0 }, + "4015": { "label": "39/10", "naklon": 0 }, + "3929": { "label": "39/11", "naklon": 0 }, + "3946": { "label": "39/12", "naklon": 0 }, + "4014": { "label": "39/13", "naklon": 0 }, + "4155": { "label": "39/14", "naklon": 0 }, + "4149": { "label": "39/15", "naklon": 0 }, + "3642": { "label": "39/16", "naklon": 0 }, + "3636": { "label": "39/17", "naklon": 5 }, + "3991": { "label": "39/18", "naklon": 0 }, + "3994": { "label": "39/19", "naklon": 0 }, + "3990": { "label": "39/20", "naklon": 0 }, + "3967": { "label": "39/21", "naklon": 0 }, + "3977": { "label": "39/22", "naklon": 0 }, + "3757": { "label": "39/23", "naklon": 15 }, + "3633": { "label": "39/24", "naklon": 15 }, + "3744": { "label": "39/25", "naklon": 15 }, + "4023": { "label": "39/26", "naklon": 5 }, + "3720": { "label": "39/27", "naklon": 5 }, + "3734": { "label": "39/28", "naklon": 5 }, + "3741": { "label": "39/29", "naklon": 5 }, + "3721": { "label": "39/30", "naklon": 5 }, + "3845": { "label": "39/31", "naklon": 0 }, + "3840": { "label": "39/32", "naklon": 0 }, + "3837": { "label": "39/33", "naklon": null }, + "3839": { "label": "39/34", "naklon": 0 }, + "3542": { "label": "41/1", "naklon": null }, + "3566": { "label": "41/2", "naklon": null }, + "3548": { "label": "41/3", "naklon": null }, + "3515": { "label": "41/4", "naklon": null }, + "3559": { "label": "41/5", "naklon": null }, + "3509": { "label": "41/6", "naklon": null }, + "3524": { "label": "41/7", "naklon": null }, + "3518": { "label": "41/8", "naklon": null }, + "3182": { "label": "41/9", "naklon": null }, + "3187": { "label": "41/10", "naklon": null }, + "3195": { "label": "41/11", "naklon": 0 }, + "3857": { "label": "41/12", "naklon": 0 }, + "3183": { "label": "41/13", "naklon": 0 }, + "3177": { "label": "41/14", "naklon": 0 }, + "3189": { "label": "41/15", "naklon": 0 }, + "3186": { "label": "41/16", "naklon": 0 }, + "3178": { "label": "42/1", "naklon": 0 }, + "3219": { "label": "42/2", "naklon": 0 }, + "3475": { "label": "42/3", "naklon": 0 }, + "3175": { "label": "42/4", "naklon": 0 }, + "3222": { "label": "42/5", "naklon": 0 }, + "3221": { "label": "42/6", "naklon": 0 }, + "3181": { "label": "42/7", "naklon": 0 }, + "3180": { "label": "42/8", "naklon": 0 }, + "3218": { "label": "42/9", "naklon": 0 }, + "3176": { "label": "42/10", "naklon": 0 }, + "3174": { "label": "42/11", "naklon": 0 }, + "3220": { "label": "42/12", "naklon": 0 }, + "3533": { "label": "42/13", "naklon": null }, + "3543": { "label": "42/14", "naklon": null }, + "3554": { "label": "42/15", "naklon": null }, + "3549": { "label": "42/16", "naklon": null }, + "2857": { "label": "43/1", "naklon": 5 }, + "2752": { "label": "43/2", "naklon": 5 }, + "2753": { "label": "43/3", "naklon": 5 }, + "3024": { "label": "43/4", "naklon": 5 }, + "2754": { "label": "43/5", "naklon": 5 }, + "4423": { "label": "43/6", "naklon": 5 }, + "4368": { "label": "43/7", "naklon": 5 }, + "2978": { "label": "43/8", "naklon": 5 }, + "2868": { "label": "43/9", "naklon": 5 }, + "4377": { "label": "43/10", "naklon": 5 }, + "2757": { "label": "43/11", "naklon": 5 }, + "2970": { "label": "43/12", "naklon": 5 }, + "2758": { "label": "43/13", "naklon": 5 }, + "4378": { "label": "43/14", "naklon": 5 }, + "2759": { "label": "43/15", "naklon": 5 }, + "4342": { "label": "43/16", "naklon": 5 }, + "3026": { "label": "43/17", "naklon": null }, + "2986": { "label": "43/18", "naklon": null }, + "4343": { "label": "43/19", "naklon": null }, + "2760": { "label": "43/20", "naklon": null }, + "4379": { "label": "43/21", "naklon": null }, + "2971": { "label": "43/22", "naklon": null }, + "2761": { "label": "43/23", "naklon": null }, + "2762": { "label": "43/24", "naklon": null }, + "4339": { "label": "43/25", "naklon": null }, + "4380": { "label": "43/26", "naklon": null }, + "2975": { "label": "43/27", "naklon": null }, + "3003": { "label": "43/28", "naklon": null }, + "4338": { "label": "43/29", "naklon": null }, + "3002": { "label": "43/30", "naklon": null }, + "4345": { "label": "43/31", "naklon": null }, + "2979": { "label": "43/32", "naklon": null }, + "2989": { "label": "43/33", "naklon": null }, + "2996": { "label": "43/34", "naklon": null }, + "2972": { "label": "43/35", "naklon": null }, + "2988": { "label": "43/36", "naklon": null }, + "4344": { "label": "43/37", "naklon": null }, + "3022": { "label": "43/38", "naklon": null }, + "4341": { "label": "43/39", "naklon": null }, + "2983": { "label": "43/40", "naklon": null }, + "2995": { "label": "43/41", "naklon": null }, + "2763": { "label": "43/42", "naklon": null }, + "2764": { "label": "43/43", "naklon": null }, + "2765": { "label": "43/44", "naklon": null }, + "2766": { "label": "43/45", "naklon": null }, + "2767": { "label": "43/46", "naklon": null }, + "2768": { "label": "43/47", "naklon": null }, + "3018": { "label": "43/48", "naklon": null }, + "2982": { "label": "43/49", "naklon": null }, + "3019": { "label": "43/50", "naklon": 0 }, + "3013": { "label": "43/51", "naklon": null }, + "3007": { "label": "43/52", "naklon": null }, + "2980": { "label": "43/53", "naklon": null }, + "3011": { "label": "43/54", "naklon": null }, + "2672": { "label": "43/55", "naklon": null }, + "2673": { "label": "43/56", "naklon": null }, + "2674": { "label": "43/57", "naklon": null }, + "2675": { "label": "43/58", "naklon": null }, + "2676": { "label": "43/59", "naklon": null }, + "2677": { "label": "43/60", "naklon": null }, + "2678": { "label": "43/61", "naklon": null }, + "2679": { "label": "43/62", "naklon": null }, + "2680": { "label": "43/63", "naklon": null }, + "2840": { "label": "43/64", "naklon": null }, + "2682": { "label": "43/65", "naklon": null }, + "2683": { "label": "43/66", "naklon": null }, + "2684": { "label": "43/67", "naklon": 0 }, + "2685": { "label": "43/68", "naklon": null }, + "2686": { "label": "43/69", "naklon": null }, + "2687": { "label": "43/70", "naklon": null }, + "2688": { "label": "43/71", "naklon": null }, + "2689": { "label": "43/72", "naklon": null }, + "2690": { "label": "43/73", "naklon": null }, + "2691": { "label": "43/74", "naklon": null }, + "2692": { "label": "43/75", "naklon": null }, + "2693": { "label": "43/76", "naklon": 0 }, + "2694": { "label": "43/77", "naklon": null }, + "2695": { "label": "43/78", "naklon": null }, + "2696": { "label": "43/79", "naklon": 0 }, + "2697": { "label": "43/80", "naklon": null }, + "2698": { "label": "43/81", "naklon": 0 }, + "2699": { "label": "43/82", "naklon": null }, + "2700": { "label": "43/83", "naklon": 0 }, + "2744": { "label": "43/84", "naklon": null }, + "2745": { "label": "43/85", "naklon": 0 }, + "2746": { "label": "43/86", "naklon": null }, + "2747": { "label": "43/87", "naklon": 0 }, + "2748": { "label": "43/88", "naklon": null }, + "2749": { "label": "43/89", "naklon": 0 }, + "2841": { "label": "43/90", "naklon": null }, + "4237": { "label": "45/1", "naklon": 5 }, + "4226": { "label": "45/2", "naklon": 5 }, + "4242": { "label": "45/3", "naklon": 5 }, + "4179": { "label": "45/4", "naklon": 5 }, + "4247": { "label": "45/5", "naklon": 5 }, + "4245": { "label": "45/6", "naklon": 5 }, + "3872": { "label": "45/7", "naklon": 5 }, + "4175": { "label": "45/8", "naklon": 5 }, + "4236": { "label": "45/9", "naklon": 5 }, + "4170": { "label": "45/10", "naklon": 5 }, + "4238": { "label": "45/11", "naklon": 5 }, + "4246": { "label": "45/12", "naklon": 5 }, + "4166": { "label": "45/13", "naklon": 5 }, + "4227": { "label": "45/14", "naklon": 5 }, + "4171": { "label": "45/15", "naklon": 5 }, + "4180": { "label": "45/16", "naklon": 5 }, + "4244": { "label": "45/17", "naklon": 5 }, + "4199": { "label": "45/18", "naklon": 5 }, + "4239": { "label": "45/19", "naklon": 5 }, + "4207": { "label": "45/20", "naklon": 5 }, + "4223": { "label": "45/21", "naklon": 5 }, + "4230": { "label": "45/22", "naklon": 5 }, + "4233": { "label": "45/23", "naklon": 5 }, + "4222": { "label": "45/24", "naklon": 5 }, + "4217": { "label": "45/25", "naklon": 5 }, + "4243": { "label": "45/26", "naklon": 5 }, + "4200": { "label": "45/27", "naklon": 5 }, + "4228": { "label": "45/28", "naklon": 5 }, + "4211": { "label": "45/29", "naklon": 5 }, + "4234": { "label": "45/30", "naklon": 5 }, + "4235": { "label": "45/31", "naklon": 5 }, + "4203": { "label": "45/32", "naklon": 5 }, + "4240": { "label": "45/33", "naklon": 5 }, + "4224": { "label": "45/34", "naklon": 5 }, + "4232": { "label": "45/35", "naklon": 5 }, + "4231": { "label": "45/36", "naklon": 5 }, + "4161": { "label": "45/37", "naklon": 5 }, + "4225": { "label": "45/38", "naklon": 5 }, + "4241": { "label": "45/39", "naklon": 5 }, + "4229": { "label": "45/40", "naklon": 5 }, + "4221": { "label": "45/41", "naklon": 5 }, + "4212": { "label": "45/42", "naklon": 5 }, + "4216": { "label": "45/43", "naklon": 5 }, + "3864": { "label": "45/44", "naklon": null }, + "3806": { "label": "46/1", "naklon": 5 }, + "3813": { "label": "46/2", "naklon": 5 }, + "3815": { "label": "46/3", "naklon": 5 }, + "3807": { "label": "46/4", "naklon": 5 }, + "3895": { "label": "46/5", "naklon": 5 }, + "3809": { "label": "46/6", "naklon": 5 }, + "3820": { "label": "46/7", "naklon": 5 }, + "3805": { "label": "46/8", "naklon": 5 }, + "3894": { "label": "46/9", "naklon": 0 }, + "4055": { "label": "46/10", "naklon": 0 }, + "3812": { "label": "46/11", "naklon": 5 }, + "3822": { "label": "46/12", "naklon": 5 }, + "3821": { "label": "46/13", "naklon": 5 }, + "3808": { "label": "46/14", "naklon": 5 }, + "3799": { "label": "46/15", "naklon": 5 }, + "3816": { "label": "46/16", "naklon": 5 }, + "3751": { "label": "46/17", "naklon": 5 }, + "3814": { "label": "46/18", "naklon": 5 }, + "4044": { "label": "46/19", "naklon": 0 }, + "3931": { "label": "46/20", "naklon": 0 }, + "3902": { "label": "46/21", "naklon": 5 }, + "3916": { "label": "46/22", "naklon": 5 }, + "3892": { "label": "46/23", "naklon": 5 }, + "3914": { "label": "46/24", "naklon": 5 }, + "3898": { "label": "46/25", "naklon": 5 }, + "3897": { "label": "46/26", "naklon": 5 }, + "3885": { "label": "46/27", "naklon": 5 }, + "3906": { "label": "46/28", "naklon": 5 }, + "3930": { "label": "46/29", "naklon": 0 }, + "3936": { "label": "46/30", "naklon": 0 }, + "3860": { "label": "46/31", "naklon": 5 }, + "3841": { "label": "46/32", "naklon": 5 }, + "3873": { "label": "46/33", "naklon": 5 }, + "3854": { "label": "46/34", "naklon": 5 }, + "3939": { "label": "46/35", "naklon": 5 }, + "3858": { "label": "46/36", "naklon": 5 }, + "3940": { "label": "46/37", "naklon": 5 }, + "4035": { "label": "46/38", "naklon": 5 }, + "3373": { "label": "47/1", "naklon": 0 }, + "3374": { "label": "47/2", "naklon": 0 }, + "3384": { "label": "47/3", "naklon": 0 }, + "3385": { "label": "47/4", "naklon": 0 }, + "4051": { "label": "48/1", "naklon": 5 }, + "4041": { "label": "48/2", "naklon": 5 }, + "4056": { "label": "48/3", "naklon": 5 }, + "3875": { "label": "48/4", "naklon": 5 }, + "4061": { "label": "48/5", "naklon": 5 }, + "4047": { "label": "48/6", "naklon": 5 }, + "4060": { "label": "48/7", "naklon": 5 }, + "4059": { "label": "48/8", "naklon": 5 }, + "4058": { "label": "48/9", "naklon": 5 }, + "3635": { "label": "48/10", "naklon": 5 }, + "3640": { "label": "48/11", "naklon": 5 }, + "3747": { "label": "48/12", "naklon": 5 }, + "3629": { "label": "48/13", "naklon": 5 }, + "4048": { "label": "48/14", "naklon": 5 }, + "4063": { "label": "48/15", "naklon": 5 }, + "4062": { "label": "48/16", "naklon": 5 }, + "4043": { "label": "48/17", "naklon": 5 }, + "4052": { "label": "48/18", "naklon": 5 }, + "4042": { "label": "48/19", "naklon": 5 }, + "4053": { "label": "48/20", "naklon": 5 }, + "4167": { "label": "50/15A", "naklon": null }, + "4159": { "label": "50/15B", "naklon": null }, + "4183": { "label": "50/1", "naklon": 0 }, + "4157": { "label": "50/2", "naklon": 0 }, + "4160": { "label": "50/3", "naklon": 0 }, + "4173": { "label": "50/4", "naklon": 0 }, + "4177": { "label": "50/5", "naklon": 0 }, + "4174": { "label": "50/6", "naklon": 0 }, + "4178": { "label": "50/7", "naklon": 0 }, + "4195": { "label": "50/8", "naklon": 0 }, + "4169": { "label": "50/9", "naklon": 0 }, + "4162": { "label": "50/10", "naklon": 0 }, + "4158": { "label": "50/11", "naklon": 0 }, + "4182": { "label": "50/12", "naklon": 0 }, + "4194": { "label": "50/13", "naklon": 0 }, + "4184": { "label": "50/14", "naklon": 0 }, + "4197": { "label": "50/16", "naklon": null }, + "4164": { "label": "50/17", "naklon": null }, + "3306": { "label": "50/18", "naklon": null }, + "4168": { "label": "50/19", "naklon": null }, + "4193": { "label": "50/20", "naklon": null }, + "4187": { "label": "50/21", "naklon": null }, + "4163": { "label": "50/22", "naklon": null }, + "4165": { "label": "50/23", "naklon": null }, + "4185": { "label": "50/24", "naklon": null }, + "3904": { "label": "50/25", "naklon": null }, + "2619": { "label": "53/1", "naklon": 0 }, + "2623": { "label": "53/2", "naklon": 0 }, + "2617": { "label": "53/3", "naklon": 0 }, + "2622": { "label": "53/4", "naklon": 0 }, + "2618": { "label": "53/5", "naklon": 0 }, + "2626": { "label": "53/6", "naklon": 0 }, + "2869": { "label": "53/7", "naklon": 0 }, + "2613": { "label": "53/8", "naklon": 0 }, + "2608": { "label": "53/9", "naklon": 0 }, + "2611": { "label": "53/10", "naklon": 0 }, + "2598": { "label": "53/11", "naklon": 0 }, + "3528": { "label": "53/12", "naklon": 0 }, + "3545": { "label": "53/13", "naklon": 0 }, + "2620": { "label": "53/14", "naklon": 0 }, + "2612": { "label": "53/15", "naklon": 0 }, + "2615": { "label": "53/16", "naklon": 0 }, + "3722": { "label": "53/17", "naklon": 0 }, + "2624": { "label": "53/18", "naklon": 0 }, + "2609": { "label": "53/19", "naklon": 0 }, + "2625": { "label": "53/20", "naklon": 0 }, + "2602": { "label": "53/21", "naklon": 0 }, + "2610": { "label": "53/22", "naklon": 0 }, + "2599": { "label": "53/23", "naklon": 0 }, + "2605": { "label": "53/24", "naklon": 0 }, + "2593": { "label": "53/25", "naklon": 0 }, + "3074": { "label": "53/26", "naklon": 0 }, + "2740": { "label": "53/27", "naklon": 0 }, + "2614": { "label": "53/28", "naklon": 0 }, + "2601": { "label": "53/29", "naklon": 0 }, + "4196": { "label": "53/30", "naklon": 0 }, + "2607": { "label": "53/31", "naklon": 0 }, + "2582": { "label": "53/32", "naklon": 0 }, + "2594": { "label": "53/33", "naklon": 0 }, + "2589": { "label": "53/34", "naklon": 0 }, + "2596": { "label": "53/35", "naklon": 0 }, + "2603": { "label": "53/36", "naklon": 0 }, + "2597": { "label": "53/37", "naklon": 0 }, + "2590": { "label": "53/38", "naklon": 0 }, + "2581": { "label": "53/39", "naklon": 0 }, + "2583": { "label": "53/40", "naklon": 0 }, + "2580": { "label": "53/41", "naklon": 0 }, + "2579": { "label": "53/42", "naklon": 0 }, + "2797": { "label": "53/43", "naklon": 0 }, + "2577": { "label": "53/44", "naklon": 0 }, + "2586": { "label": "53/45", "naklon": 0 }, + "2588": { "label": "53/46", "naklon": 0 }, + "2591": { "label": "53/47", "naklon": 0 }, + "2592": { "label": "53/48", "naklon": 0 }, + "2573": { "label": "53/49", "naklon": 0 }, + "2595": { "label": "53/50", "naklon": 0 }, + "2587": { "label": "53/51", "naklon": 0 }, + "2578": { "label": "53/52", "naklon": 0 }, + "2574": { "label": "53/53", "naklon": 0 }, + "2571": { "label": "53/54", "naklon": 0 }, + "2570": { "label": "53/55", "naklon": 0 }, + "2576": { "label": "53/56", "naklon": 0 }, + "2881": { "label": "53/57", "naklon": 0 }, + "2575": { "label": "53/58", "naklon": 0 }, + "2572": { "label": "53/59", "naklon": 0 }, + "2569": { "label": "53/60", "naklon": 0 }, + "4324": { "label": "55/1", "naklon": 0 }, + "4319": { "label": "55/2", "naklon": 0 }, + "4327": { "label": "55/3", "naklon": 0 }, + "4333": { "label": "55/4", "naklon": 0 }, + "4332": { "label": "55/5", "naklon": 0 }, + "4320": { "label": "55/6", "naklon": 0 }, + "4317": { "label": "55/7", "naklon": 0 }, + "4318": { "label": "55/8", "naklon": 0 }, + "4328": { "label": "55/9", "naklon": 0 }, + "4323": { "label": "55/10", "naklon": 0 }, + "4325": { "label": "55/11", "naklon": 0 }, + "4326": { "label": "55/12", "naklon": 0 }, + "4316": { "label": "55/13", "naklon": 0 }, + "4322": { "label": "55/14", "naklon": 0 }, + "4331": { "label": "55/15", "naklon": 0 }, + "4321": { "label": "55/16", "naklon": 0 }, + "4315": { "label": "55/17", "naklon": 0 }, + "4329": { "label": "55/18", "naklon": 0 }, + "4334": { "label": "55/19", "naklon": 0 }, + "4330": { "label": "55/20", "naklon": 0 } +}; + + +let svetlaSorted = [{ "label": "1/3A", "node": 3993, "naklon": 0 }, +{ "label": "1/3B", "node": 3989, "naklon": 15 }, +{ "label": "1/1", "node": 3976, "naklon": 0 }, +{ "label": "1/2", "node": 4181, "naklon": 0 }, +{ "label": "1/4", "node": 4376, "naklon": 15 }, +{ "label": "1/5", "node": 3868, "naklon": 15 }, +{ "label": "1/6", "node": 3728, "naklon": 15 }, +{ "label": "1/7", "node": 3730, "naklon": 0 }, +{ "label": "1/8", "node": 4374, "naklon": 0 }, +{ "label": "1/9", "node": 3718, "naklon": 15 }, +{ "label": "1/10", "node": 4375, "naklon": 15 }, +{ "label": "1/11", "node": 4172, "naklon": 15 }, +{ "label": "1/12", "node": 4176, "naklon": 15 }, +{ "label": "2/1", "node": 3800, "naklon": 5 }, +{ "label": "2/2", "node": 3823, "naklon": 5 }, +{ "label": "2/3", "node": 3905, "naklon": 5 }, +{ "label": "2/4", "node": 3803, "naklon": 5 }, +{ "label": "2/5", "node": 3817, "naklon": 5 }, +{ "label": "2/6", "node": 3818, "naklon": 5 }, +{ "label": "2/7", "node": 3811, "naklon": 5 }, +{ "label": "2/8", "node": 3915, "naklon": 5 }, +{ "label": "2/9", "node": 3843, "naklon": 10 }, +{ "label": "2/10", "node": 3827, "naklon": 10 }, +{ "label": "2/11", "node": 4220, "naklon": 10 }, +{ "label": "2/12", "node": 3826, "naklon": 10 }, +{ "label": "2/13", "node": 3834, "naklon": 10 }, +{ "label": "2/14", "node": 3838, "naklon": 10 }, +{ "label": "2/15", "node": 2823, "naklon": 10 }, +{ "label": "2/16", "node": 3750, "naklon": 10 }, +{ "label": "2/17", "node": 3378, "naklon": 0 }, +{ "label": "2/18", "node": 3376, "naklon": 0 }, +{ "label": "2/19", "node": 3379, "naklon": 0 }, +{ "label": "2/20", "node": 3285, "naklon": 0 }, +{ "label": "2/21", "node": 3382, "naklon": 0 }, +{ "label": "2/22", "node": 3383, "naklon": 0 }, +{ "label": "2/24", "node": 3375, "naklon": 0 }, +{ "label": "2/25", "node": 3381, "naklon": 0 }, +{ "label": "2/26", "node": 3380, "naklon": 0 }, +{ "label": "2/27", "node": 3828, "naklon": 10 }, +{ "label": "2/28", "node": 3377, "naklon": 0 }, +{ "label": "7/1", "node": 3591, "naklon": 0 }, +{ "label": "7/2", "node": 3587, "naklon": 0 }, +{ "label": "7/3", "node": 3468, "naklon": 0 }, +{ "label": "7/4", "node": 3466, "naklon": 0 }, +{ "label": "7/5", "node": 3474, "naklon": 0 }, +{ "label": "7/6", "node": 3481, "naklon": 0 }, +{ "label": "7/7", "node": 3589, "naklon": 0 }, +{ "label": "7/8", "node": 3472, "naklon": 0 }, +{ "label": "7/9", "node": 3473, "naklon": 0 }, +{ "label": "7/10", "node": 3584, "naklon": 0 }, +{ "label": "7/11", "node": 3571, "naklon": 0 }, +{ "label": "7/12", "node": 3476, "naklon": 0 }, +{ "label": "7/13", "node": 3590, "naklon": 0 }, +{ "label": "7/14", "node": 3478, "naklon": 0 }, +{ "label": "7/15", "node": 3471, "naklon": 0 }, +{ "label": "7/16", "node": 3467, "naklon": 0 }, +{ "label": "7/17", "node": 3479, "naklon": 0 }, +{ "label": "7/18", "node": 3480, "naklon": 0 }, +{ "label": "7/19", "node": 3477, "naklon": 0 }, +{ "label": "12/1", "node": 3362, "naklon": 0 }, +{ "label": "12/2", "node": 3355, "naklon": 0 }, +{ "label": "12/3", "node": 3356, "naklon": 0 }, +{ "label": "12/4", "node": 3349, "naklon": 0 }, +{ "label": "12/5", "node": 3357, "naklon": 0 }, +{ "label": "12/6", "node": 3350, "naklon": 0 }, +{ "label": "12/7", "node": 3353, "naklon": 0 }, +{ "label": "12/8", "node": 3539, "naklon": 0 }, +{ "label": "12/9", "node": 3050, "naklon": 0 }, +{ "label": "12/10", "node": 3361, "naklon": 0 }, +{ "label": "12/11", "node": 3360, "naklon": 0 }, +{ "label": "12/12", "node": 3358, "naklon": 0 }, +{ "label": "12/13", "node": 3541, "naklon": 0 }, +{ "label": "12/14", "node": 3551, "naklon": 0 }, +{ "label": "12/15", "node": 3514, "naklon": 0 }, +{ "label": "12/16", "node": 3547, "naklon": 0 }, +{ "label": "12/17", "node": 3562, "naklon": 0 }, +{ "label": "12/18", "node": 3525, "naklon": 0 }, +{ "label": "12/19", "node": 3558, "naklon": 0 }, +{ "label": "12/20", "node": 3511, "naklon": 0 }, +{ "label": "12/21", "node": 3058, "naklon": 0 }, +{ "label": "12/22", "node": 3062, "naklon": 0 }, +{ "label": "12/23", "node": 3070, "naklon": 0 }, +{ "label": "12/24", "node": 3447, "naklon": 0 }, +{ "label": "12/25", "node": 3056, "naklon": 0 }, +{ "label": "12/26", "node": 3057, "naklon": 0 }, +{ "label": "12/27", "node": 3071, "naklon": 0 }, +{ "label": "12/28", "node": 3061, "naklon": 0 }, +{ "label": "12/29", "node": 3069, "naklon": 0 }, +{ "label": "12/30", "node": 3077, "naklon": 0 }, +{ "label": "12/31", "node": 3080, "naklon": 0 }, +{ "label": "12/32", "node": 3081, "naklon": 0 }, +{ "label": "12/33", "node": 3078, "naklon": 0 }, +{ "label": "12/34", "node": 4037, "naklon": 0 }, +{ "label": "12/35", "node": 3067, "naklon": 0 }, +{ "label": "12/36", "node": 3051, "naklon": 0 }, +{ "label": "12/37", "node": 2924, "naklon": 0 }, +{ "label": "12/38", "node": 3060, "naklon": 0 }, +{ "label": "12/39", "node": 3073, "naklon": 0 }, +{ "label": "12/40", "node": 3469, "naklon": 0 }, +{ "label": "12/41", "node": 2923, "naklon": 0 }, +{ "label": "12/42", "node": 2925, "naklon": 0 }, +{ "label": "12/43", "node": 3359, "naklon": 0 }, +{ "label": "12/44", "node": 3055, "naklon": 0 }, +{ "label": "12/45", "node": 2922, "naklon": 0 }, +{ "label": "12/46", "node": 3084, "naklon": 0 }, +{ "label": "12/47", "node": 3064, "naklon": 0 }, +{ "label": "12/48", "node": 3066, "naklon": 0 }, +{ "label": "12/49", "node": 3072, "naklon": 0 }, +{ "label": "13/13A", "node": 3415, "naklon": 0 }, +{ "label": "13/13B", "node": 3409, "naklon": 0 }, +{ "label": "13/13C", "node": 3399, "naklon": 0 }, +{ "label": "13/29A", "node": 3410, "naklon": 0 }, +{ "label": "13/29B", "node": 3407, "naklon": 0 }, +{ "label": "13/34A", "node": 3405, "naklon": 0 }, +{ "label": "13/34B", "node": 3404, "naklon": 0 }, +{ "label": "13/45A", "node": 3392, "naklon": 0 }, +{ "label": "13/45B", "node": 3386, "naklon": 0 }, +{ "label": "13/60A", "node": 3303, "naklon": 3 }, +{ "label": "13/60B", "node": 3302, "naklon": 3 }, +{ "label": "13/70A", "node": 3319, "naklon": 6 }, +{ "label": "13/70B", "node": 3317, "naklon": 6 }, +{ "label": "13/70C", "node": 3326, "naklon": 6 }, +{ "label": "13/73A", "node": 3351, "naklon": 6 }, +{ "label": "13/73B", "node": 3313, "naklon": 6 }, +{ "label": "13/83A", "node": 3316, "naklon": 0 }, +{ "label": "13/83B", "node": 3320, "naklon": 0 }, +{ "label": "13/95A", "node": 3336, "naklon": 0 }, +{ "label": "13/95B", "node": 3323, "naklon": 0 }, +{ "label": "13/98A", "node": 3339, "naklon": 0 }, +{ "label": "13/98B", "node": 3333, "naklon": 0 }, +{ "label": "13/1", "node": 3425, "naklon": 0 }, +{ "label": "13/2", "node": 3419, "naklon": 0 }, +{ "label": "13/3", "node": 3416, "naklon": 0 }, +{ "label": "13/4", "node": 3332, "naklon": 0 }, +{ "label": "13/5", "node": 3422, "naklon": 0 }, +{ "label": "13/6", "node": 3417, "naklon": 0 }, +{ "label": "13/7", "node": 3418, "naklon": 0 }, +{ "label": "13/8", "node": 3424, "naklon": 0 }, +{ "label": "13/9", "node": 3334, "naklon": 0 }, +{ "label": "13/10", "node": 4363, "naklon": 0 }, +{ "label": "13/11", "node": 3423, "naklon": 0 }, +{ "label": "13/12", "node": 3406, "naklon": 0 }, +{ "label": "13/14", "node": 3411, "naklon": 0 }, +{ "label": "13/15", "node": 3412, "naklon": 0 }, +{ "label": "13/16", "node": 3413, "naklon": 0 }, +{ "label": "13/17", "node": 3414, "naklon": 0 }, +{ "label": "13/18", "node": 3391, "naklon": 0 }, +{ "label": "13/19", "node": 3370, "naklon": 0 }, +{ "label": "13/20", "node": 3369, "naklon": 0 }, +{ "label": "13/21", "node": 3408, "naklon": 0 }, +{ "label": "13/22", "node": 3393, "naklon": 0 }, +{ "label": "13/23", "node": 3128, "naklon": 0 }, +{ "label": "13/24", "node": 3197, "naklon": 0 }, +{ "label": "13/25", "node": 4364, "naklon": 0 }, +{ "label": "13/26", "node": 3155, "naklon": 0 }, +{ "label": "13/27", "node": 3196, "naklon": 0 }, +{ "label": "13/28", "node": 3144, "naklon": 0 }, +{ "label": "13/30", "node": 3150, "naklon": 0 }, +{ "label": "13/31", "node": 3390, "naklon": 0 }, +{ "label": "13/32", "node": 3401, "naklon": 0 }, +{ "label": "13/33", "node": 3275, "naklon": 0 }, +{ "label": "13/35", "node": 3371, "naklon": 0 }, +{ "label": "13/36", "node": 3389, "naklon": 0 }, +{ "label": "13/37", "node": 3388, "naklon": 0 }, +{ "label": "13/38", "node": 3365, "naklon": 0 }, +{ "label": "13/39", "node": 3363, "naklon": 0 }, +{ "label": "13/40", "node": 3397, "naklon": 0 }, +{ "label": "13/40/1", "node": 3567, "naklon": 0 }, +{ "label": "13/41", "node": 3387, "naklon": 0 }, +{ "label": "13/42", "node": 3403, "naklon": 0 }, +{ "label": "13/43", "node": 3147, "naklon": 0 }, +{ "label": "13/44", "node": 3141, "naklon": 0 }, +{ "label": "13/46", "node": 3364, "naklon": 0 }, +{ "label": "13/47", "node": 3367, "naklon": 0 }, +{ "label": "13/48", "node": 3368, "naklon": 0 }, +{ "label": "13/49", "node": 3402, "naklon": 0 }, +{ "label": "13/50", "node": 3366, "naklon": 0 }, +{ "label": "13/51", "node": 3395, "naklon": 0 }, +{ "label": "13/52", "node": 3372, "naklon": 0 }, +{ "label": "13/53", "node": 3394, "naklon": 0 }, +{ "label": "13/54", "node": 3308, "naklon": 0 }, +{ "label": "13/54/1", "node": 3847, "naklon": 0 }, +{ "label": "13/55", "node": 3312, "naklon": 3 }, +{ "label": "13/56", "node": 3309, "naklon": 3 }, +{ "label": "13/57", "node": 3311, "naklon": 3 }, +{ "label": "13/58", "node": 3310, "naklon": 3 }, +{ "label": "13/59", "node": 4365, "naklon": 3 }, +{ "label": "13/60/1", "node": 4093, "naklon": 3 }, +{ "label": "13/61", "node": 3304, "naklon": 3 }, +{ "label": "13/62", "node": 3307, "naklon": 3 }, +{ "label": "13/63", "node": 3271, "naklon": 3 }, +{ "label": "13/64", "node": 3301, "naklon": 3 }, +{ "label": "13/65", "node": 4366, "naklon": 3 }, +{ "label": "13/66", "node": 3300, "naklon": 3 }, +{ "label": "13/67", "node": 3185, "naklon": 0 }, +{ "label": "13/68", "node": 3184, "naklon": 0 }, +{ "label": "13/69", "node": 3188, "naklon": 0 }, +{ "label": "13/71", "node": 3343, "naklon": 6 }, +{ "label": "13/71/1", "node": 3819, "naklon": 6 }, +{ "label": "13/71/2", "node": 3880, "naklon": 6 }, +{ "label": "13/72", "node": 3348, "naklon": 6 }, +{ "label": "13/74", "node": 3344, "naklon": 6 }, +{ "label": "13/75", "node": 3346, "naklon": 6 }, +{ "label": "13/75/1", "node": 3597, "naklon": 6 }, +{ "label": "13/76", "node": 3345, "naklon": 6 }, +{ "label": "13/77", "node": 3322, "naklon": 0 }, +{ "label": "13/78", "node": 3325, "naklon": 0 }, +{ "label": "13/78/1", "node": 4310, "naklon": 0 }, +{ "label": "13/79", "node": 3315, "naklon": 0 }, +{ "label": "13/80", "node": 3328, "naklon": 0 }, +{ "label": "13/81", "node": 3321, "naklon": 0 }, +{ "label": "13/82", "node": 3324, "naklon": 0 }, +{ "label": "13/84", "node": 3140, "naklon": 0 }, +{ "label": "13/85", "node": 3153, "naklon": 0 }, +{ "label": "13/86", "node": 3145, "naklon": 0 }, +{ "label": "13/87", "node": 3134, "naklon": 0 }, +{ "label": "13/88", "node": 3151, "naklon": 0 }, +{ "label": "13/89", "node": 3143, "naklon": 0 }, +{ "label": "13/90", "node": 3318, "naklon": 0 }, +{ "label": "13/91", "node": 3347, "naklon": 0 }, +{ "label": "13/94", "node": 3314, "naklon": 0 }, +{ "label": "13/96", "node": 3331, "naklon": 0 }, +{ "label": "13/97", "node": 3327, "naklon": 0 }, +{ "label": "13/99", "node": 3329, "naklon": 0 }, +{ "label": "13/100", "node": 3337, "naklon": 0 }, +{ "label": "13/101", "node": 3330, "naklon": 0 }, +{ "label": "13/102", "node": 3335, "naklon": 0 }, +{ "label": "13/103", "node": 3420, "naklon": 0 }, +{ "label": "13/104", "node": 3421, "naklon": 0 }, +{ "label": "13/105", "node": 4361, "naklon": 0 }, +{ "label": "13/106", "node": 4362, "naklon": 0 }, +{ "label": "13/107", "node": 3526, "naklon": 0 }, +{ "label": "13/108", "node": 4424, "naklon": null }, +{ "label": "13/109", "node": 3561, "naklon": null }, +{ "label": "13/110", "node": 3527, "naklon": null }, +{ "label": "13/111", "node": 3521, "naklon": null }, +{ "label": "13/112", "node": 3552, "naklon": null }, +{ "label": "13/113", "node": 3544, "naklon": null }, +{ "label": "13/114", "node": 3534, "naklon": null }, +{ "label": "13/115", "node": 3516, "naklon": null }, +{ "label": "13/116", "node": 3513, "naklon": null }, +{ "label": "13/117", "node": 3565, "naklon": null }, +{ "label": "13/118", "node": 3866, "naklon": null }, +{ "label": "14/1", "node": 3136, "naklon": 0 }, +{ "label": "14/2", "node": 3137, "naklon": 0 }, +{ "label": "14/3", "node": 3135, "naklon": 0 }, +{ "label": "14/4", "node": 3149, "naklon": 0 }, +{ "label": "14/5", "node": 3142, "naklon": 0 }, +{ "label": "14/6", "node": 3342, "naklon": 0 }, +{ "label": "14/7", "node": 3340, "naklon": 0 }, +{ "label": "14/8", "node": 3152, "naklon": 0 }, +{ "label": "14/9", "node": 3886, "naklon": 0 }, +{ "label": "14/10", "node": 3341, "naklon": null }, +{ "label": "14/11", "node": 3352, "naklon": null }, +{ "label": "15/1", "node": 3396, "naklon": 5 }, +{ "label": "15/2", "node": 2784, "naklon": 5 }, +{ "label": "15/3", "node": 2788, "naklon": 5 }, +{ "label": "15/4", "node": 2801, "naklon": 5 }, +{ "label": "15/5", "node": 2815, "naklon": 5 }, +{ "label": "15/6", "node": 2829, "naklon": 5 }, +{ "label": "15/7", "node": 2796, "naklon": 5 }, +{ "label": "15/8", "node": 2803, "naklon": 5 }, +{ "label": "15/8/1", "node": 4304, "naklon": 5 }, +{ "label": "15/8/2", "node": 4311, "naklon": 5 }, +{ "label": "15/9", "node": 2821, "naklon": 5 }, +{ "label": "15/10", "node": 3400, "naklon": 5 }, +{ "label": "15/11", "node": 2799, "naklon": 5 }, +{ "label": "15/12", "node": 2804, "naklon": 5 }, +{ "label": "15/12/1", "node": 4303, "naklon": 5 }, +{ "label": "15/12/2", "node": 4309, "naklon": 5 }, +{ "label": "15/13", "node": 2806, "naklon": 5 }, +{ "label": "15/14", "node": 2787, "naklon": 5 }, +{ "label": "15/15", "node": 2809, "naklon": 5 }, +{ "label": "15/16", "node": 2814, "naklon": 0 }, +{ "label": "15/17", "node": 3934, "naklon": 0 }, +{ "label": "15/18", "node": 3192, "naklon": 0 }, +{ "label": "15/19", "node": 2812, "naklon": 0 }, +{ "label": "15/20", "node": 4070, "naklon": 0 }, +{ "label": "15/21", "node": 2826, "naklon": 0 }, +{ "label": "15/22", "node": 2808, "naklon": 3 }, +{ "label": "15/23", "node": 2795, "naklon": 3 }, +{ "label": "15/24", "node": 2807, "naklon": 3 }, +{ "label": "15/25", "node": 2831, "naklon": 0 }, +{ "label": "15/26", "node": 2862, "naklon": null }, +{ "label": "15/27", "node": 2861, "naklon": 0 }, +{ "label": "15/28", "node": 2866, "naklon": 0 }, +{ "label": "15/28/1", "node": 3546, "naklon": 0 }, +{ "label": "15/29", "node": 4146, "naklon": 0 }, +{ "label": "15/29/1", "node": 3001, "naklon": 0 }, +{ "label": "15/30", "node": 2835, "naklon": 0 }, +{ "label": "15/31", "node": 2874, "naklon": 0 }, +{ "label": "15/32", "node": 2852, "naklon": 0 }, +{ "label": "15/33", "node": 2851, "naklon": 0 }, +{ "label": "15/33/1", "node": 3560, "naklon": 0 }, +{ "label": "15/34", "node": 2858, "naklon": 0 }, +{ "label": "15/34/1", "node": 4306, "naklon": 0 }, +{ "label": "15/35", "node": 2856, "naklon": 0 }, +{ "label": "15/36", "node": 2847, "naklon": 0 }, +{ "label": "15/36/1", "node": 3556, "naklon": 0 }, +{ "label": "15/37", "node": 3950, "naklon": 0 }, +{ "label": "15/38", "node": 2848, "naklon": 0 }, +{ "label": "15/39", "node": 2863, "naklon": 0 }, +{ "label": "15/39/1", "node": 4313, "naklon": 0 }, +{ "label": "15/40", "node": 2873, "naklon": 0 }, +{ "label": "15/40/1", "node": 2984, "naklon": 0 }, +{ "label": "15/41", "node": 2854, "naklon": 0 }, +{ "label": "15/42", "node": 2859, "naklon": 0 }, +{ "label": "15/43", "node": 2872, "naklon": 0 }, +{ "label": "15/44", "node": 2849, "naklon": 0 }, +{ "label": "15/45", "node": 2864, "naklon": 0 }, +{ "label": "15/46", "node": 3553, "naklon": null }, +{ "label": "15/47", "node": 3021, "naklon": null }, +{ "label": "15/47/1", "node": 3008, "naklon": null }, +{ "label": "15/48", "node": 3017, "naklon": null }, +{ "label": "15/49", "node": 3014, "naklon": null }, +{ "label": "15/50", "node": 2981, "naklon": null }, +{ "label": "15/51", "node": 3020, "naklon": null }, +{ "label": "15/52", "node": 3027, "naklon": null }, +{ "label": "15/53", "node": 3006, "naklon": null }, +{ "label": "15/54", "node": 3012, "naklon": null }, +{ "label": "15/55", "node": 2738, "naklon": 0 }, +{ "label": "15/56", "node": 2725, "naklon": 0 }, +{ "label": "15/57", "node": 3016, "naklon": null }, +{ "label": "15/58", "node": 3005, "naklon": null }, +{ "label": "15/58/1", "node": 3009, "naklon": null }, +{ "label": "15/59", "node": 3010, "naklon": 0 }, +{ "label": "15/59/1", "node": 3538, "naklon": 0 }, +{ "label": "15/59/2", "node": 4145, "naklon": 0 }, +{ "label": "15/60", "node": 2713, "naklon": 0 }, +{ "label": "15/61", "node": 2789, "naklon": 0 }, +{ "label": "15/62", "node": 2736, "naklon": 0 }, +{ "label": "15/63", "node": 2739, "naklon": 0 }, +{ "label": "15/64", "node": 4346, "naklon": 0 }, +{ "label": "15/65", "node": 2731, "naklon": 0 }, +{ "label": "15/66", "node": 2818, "naklon": 0 }, +{ "label": "15/66/1", "node": 3557, "naklon": 0 }, +{ "label": "15/67", "node": 2822, "naklon": 0 }, +{ "label": "15/68", "node": 2833, "naklon": 0 }, +{ "label": "15/69", "node": 2834, "naklon": 0 }, +{ "label": "15/70", "node": 3097, "naklon": 0 }, +{ "label": "15/71", "node": 2824, "naklon": 0 }, +{ "label": "15/72", "node": 2828, "naklon": 0 }, +{ "label": "15/73", "node": 2600, "naklon": 0 }, +{ "label": "15/73/1", "node": 4314, "naklon": 0 }, +{ "label": "15/74", "node": 2832, "naklon": 0 }, +{ "label": "15/75", "node": 4360, "naklon": 0 }, +{ "label": "15/76", "node": 2846, "naklon": 0 }, +{ "label": "15/77", "node": 2584, "naklon": 0 }, +{ "label": "15/78", "node": 2843, "naklon": 0 }, +{ "label": "15/78/1", "node": 4308, "naklon": 0 }, +{ "label": "15/79", "node": 4144, "naklon": null }, +{ "label": "15/80", "node": 2844, "naklon": 0 }, +{ "label": "15/81", "node": 2842, "naklon": 0 }, +{ "label": "15/82", "node": 2838, "naklon": 0 }, +{ "label": "15/83", "node": 2837, "naklon": null }, +{ "label": "15/83/1", "node": 3555, "naklon": null }, +{ "label": "15/84", "node": 2839, "naklon": 0 }, +{ "label": "15/85", "node": 2830, "naklon": 0 }, +{ "label": "15/86", "node": 4066, "naklon": 0 }, +{ "label": "15/87", "node": 2836, "naklon": 0 }, +{ "label": "15/88", "node": 2911, "naklon": 0 }, +{ "label": "15/89", "node": 2825, "naklon": 0 }, +{ "label": "15/90", "node": 2811, "naklon": 0 }, +{ "label": "15/94", "node": 3740, "naklon": 15 }, +{ "label": "15/95", "node": 2734, "naklon": 15 }, +{ "label": "15/96", "node": 3105, "naklon": 15 }, +{ "label": "15/97", "node": 2732, "naklon": 15 }, +{ "label": "15/98", "node": 2727, "naklon": 15 }, +{ "label": "15/99", "node": 2735, "naklon": 15 }, +{ "label": "15/100", "node": 3926, "naklon": 15 }, +{ "label": "15/101", "node": 2918, "naklon": 0 }, +{ "label": "15/102", "node": 2705, "naklon": 10 }, +{ "label": "15/103", "node": 2708, "naklon": 10 }, +{ "label": "15/104", "node": 2721, "naklon": 10 }, +{ "label": "15/105", "node": 2719, "naklon": 10 }, +{ "label": "15/106", "node": 2919, "naklon": 10 }, +{ "label": "15/107", "node": 3101, "naklon": 10 }, +{ "label": "15/108", "node": 2853, "naklon": 10 }, +{ "label": "15/109", "node": 2715, "naklon": 10 }, +{ "label": "15/110", "node": 2712, "naklon": 0 }, +{ "label": "15/111", "node": 2711, "naklon": 0 }, +{ "label": "15/112", "node": 2709, "naklon": 0 }, +{ "label": "15/113", "node": 2710, "naklon": 0 }, +{ "label": "15/114", "node": 2907, "naklon": 0 }, +{ "label": "15/115", "node": 2906, "naklon": 0 }, +{ "label": "15/116", "node": 2908, "naklon": 0 }, +{ "label": "15/117", "node": 2901, "naklon": 0 }, +{ "label": "15/118", "node": 2913, "naklon": 0 }, +{ "label": "15/119", "node": 3656, "naklon": 0 }, +{ "label": "15/120", "node": 2781, "naklon": 0 }, +{ "label": "15/121", "node": 2802, "naklon": 0 }, +{ "label": "15/122", "node": 2791, "naklon": 0 }, +{ "label": "15/123", "node": 2783, "naklon": 0 }, +{ "label": "15/124", "node": 2794, "naklon": 0 }, +{ "label": "15/125", "node": 3139, "naklon": 0 }, +{ "label": "15/126", "node": 3229, "naklon": 5 }, +{ "label": "15/127", "node": 3239, "naklon": 5 }, +{ "label": "15/128", "node": 3230, "naklon": 5 }, +{ "label": "15/129", "node": 4016, "naklon": null }, +{ "label": "16/16A", "node": 3608, "naklon": 0 }, +{ "label": "16/16B", "node": 4151, "naklon": 0 }, +{ "label": "16/1", "node": 3710, "naklon": 0 }, +{ "label": "16/2", "node": 3726, "naklon": 0 }, +{ "label": "16/3", "node": 3743, "naklon": 0 }, +{ "label": "16/4", "node": 3724, "naklon": 0 }, +{ "label": "16/5", "node": 3712, "naklon": 0 }, +{ "label": "16/6", "node": 3739, "naklon": 0 }, +{ "label": "16/7", "node": 3742, "naklon": 0 }, +{ "label": "16/8", "node": 3731, "naklon": 0 }, +{ "label": "16/9", "node": 3727, "naklon": 0 }, +{ "label": "16/10", "node": 3729, "naklon": 0 }, +{ "label": "16/11", "node": 3736, "naklon": 0 }, +{ "label": "16/12", "node": 3713, "naklon": 0 }, +{ "label": "16/13", "node": 3715, "naklon": 0 }, +{ "label": "16/14", "node": 3733, "naklon": 0 }, +{ "label": "16/15", "node": 3732, "naklon": 0 }, +{ "label": "16/17", "node": 3634, "naklon": 0 }, +{ "label": "16/18", "node": 3610, "naklon": 0 }, +{ "label": "16/19", "node": 3626, "naklon": 0 }, +{ "label": "16/20", "node": 3618, "naklon": 0 }, +{ "label": "16/21", "node": 3619, "naklon": 0 }, +{ "label": "16/22", "node": 3628, "naklon": 0 }, +{ "label": "16/23", "node": 3615, "naklon": 0 }, +{ "label": "16/24", "node": 3609, "naklon": 0 }, +{ "label": "16/25", "node": 3606, "naklon": 0 }, +{ "label": "16/26", "node": 3624, "naklon": 0 }, +{ "label": "16/27", "node": 3627, "naklon": 0 }, +{ "label": "16/28", "node": 3607, "naklon": 0 }, +{ "label": "16/29", "node": 4370, "naklon": 0 }, +{ "label": "16/30", "node": 3692, "naklon": 0 }, +{ "label": "16/31", "node": 3614, "naklon": 0 }, +{ "label": "16/32", "node": 3623, "naklon": 0 }, +{ "label": "16/33", "node": 4373, "naklon": 0 }, +{ "label": "16/34", "node": 3620, "naklon": 0 }, +{ "label": "16/35", "node": 3685, "naklon": 0 }, +{ "label": "16/36", "node": 3616, "naklon": 0 }, +{ "label": "16/37", "node": 3686, "naklon": 0 }, +{ "label": "16/38", "node": 3688, "naklon": 0 }, +{ "label": "16/39", "node": 3684, "naklon": 0 }, +{ "label": "16/40", "node": 3825, "naklon": 0 }, +{ "label": "16/41", "node": 3865, "naklon": 0 }, +{ "label": "16/42", "node": 3824, "naklon": 0 }, +{ "label": "16/43", "node": 3871, "naklon": 0 }, +{ "label": "16/44", "node": 3801, "naklon": 0 }, +{ "label": "16/45", "node": 3862, "naklon": 0 }, +{ "label": "16/46", "node": 3876, "naklon": 0 }, +{ "label": "16/47", "node": 3861, "naklon": 0 }, +{ "label": "16/48", "node": 4215, "naklon": 0 }, +{ "label": "16/49", "node": 3605, "naklon": 10 }, +{ "label": "16/50", "node": 3603, "naklon": 10 }, +{ "label": "16/51", "node": 3592, "naklon": 10 }, +{ "label": "16/52", "node": 3598, "naklon": 10 }, +{ "label": "16/53", "node": 3594, "naklon": 10 }, +{ "label": "16/54", "node": 3593, "naklon": 10 }, +{ "label": "16/55", "node": 3630, "naklon": 10 }, +{ "label": "16/56", "node": 3763, "naklon": 10 }, +{ "label": "16/57", "node": 3746, "naklon": 10 }, +{ "label": "16/58", "node": 3699, "naklon": 0 }, +{ "label": "16/59", "node": 3698, "naklon": 0 }, +{ "label": "16/60", "node": 3709, "naklon": null }, +{ "label": "16/61", "node": 3708, "naklon": 0 }, +{ "label": "16/62", "node": 3703, "naklon": null }, +{ "label": "16/63", "node": 3700, "naklon": 0 }, +{ "label": "16/64", "node": 3701, "naklon": null }, +{ "label": "16/65", "node": 3704, "naklon": 0 }, +{ "label": "16/66", "node": 3707, "naklon": null }, +{ "label": "16/67", "node": 3810, "naklon": 0 }, +{ "label": "16/68", "node": 4208, "naklon": null }, +{ "label": "16/69", "node": 3867, "naklon": 0 }, +{ "label": "16/70", "node": 4372, "naklon": null }, +{ "label": "16/71", "node": 3881, "naklon": 0 }, +{ "label": "16/72", "node": 4204, "naklon": null }, +{ "label": "16/73", "node": 3869, "naklon": 0 }, +{ "label": "16/74", "node": 4202, "naklon": null }, +{ "label": "16/75", "node": 3830, "naklon": 0 }, +{ "label": "16/76", "node": 3870, "naklon": null }, +{ "label": "16/77", "node": 3964, "naklon": 0 }, +{ "label": "16/78", "node": 3849, "naklon": 0 }, +{ "label": "16/79", "node": 3694, "naklon": null }, +{ "label": "16/80", "node": 3717, "naklon": 0 }, +{ "label": "16/81", "node": 3877, "naklon": null }, +{ "label": "16/82", "node": 3755, "naklon": 0 }, +{ "label": "16/83", "node": 3725, "naklon": null }, +{ "label": "16/84", "node": 3716, "naklon": 0 }, +{ "label": "16/85", "node": 3696, "naklon": null }, +{ "label": "16/86", "node": 3702, "naklon": 0 }, +{ "label": "16/87", "node": 3706, "naklon": null }, +{ "label": "16/88", "node": 3850, "naklon": 0 }, +{ "label": "16/89", "node": 3848, "naklon": null }, +{ "label": "16/90", "node": 3737, "naklon": null }, +{ "label": "16/91", "node": 3705, "naklon": 0 }, +{ "label": "16/92", "node": 3723, "naklon": null }, +{ "label": "16/93", "node": 3842, "naklon": 0 }, +{ "label": "16/94", "node": 3735, "naklon": null }, +{ "label": "16/95", "node": 3719, "naklon": 0 }, +{ "label": "16/96", "node": 3697, "naklon": 0 }, +{ "label": "16/97", "node": 3711, "naklon": 0 }, +{ "label": "16/98", "node": 4107, "naklon": null }, +{ "label": "16/99", "node": 4112, "naklon": 5 }, +{ "label": "16/100", "node": 4106, "naklon": 5 }, +{ "label": "16/101", "node": 4111, "naklon": 5 }, +{ "label": "16/102", "node": 4091, "naklon": null }, +{ "label": "16/103", "node": 4104, "naklon": 5 }, +{ "label": "16/104", "node": 4094, "naklon": null }, +{ "label": "16/105", "node": 4089, "naklon": 5 }, +{ "label": "16/106", "node": 4095, "naklon": null }, +{ "label": "16/107", "node": 4102, "naklon": 5 }, +{ "label": "16/108", "node": 4105, "naklon": null }, +{ "label": "16/109", "node": 3859, "naklon": null }, +{ "label": "16/110", "node": 4090, "naklon": 5 }, +{ "label": "16/111", "node": 4110, "naklon": null }, +{ "label": "16/112", "node": 4097, "naklon": 5 }, +{ "label": "16/113", "node": 4099, "naklon": null }, +{ "label": "16/114", "node": 4096, "naklon": null }, +{ "label": "16/115", "node": 4101, "naklon": 5 }, +{ "label": "16/116", "node": 4109, "naklon": null }, +{ "label": "16/117", "node": 4092, "naklon": 5 }, +{ "label": "16/118", "node": 3631, "naklon": null }, +{ "label": "16/119", "node": 3632, "naklon": 0 }, +{ "label": "16/120", "node": 3641, "naklon": null }, +{ "label": "16/121", "node": 3638, "naklon": 0 }, +{ "label": "16/122", "node": 3637, "naklon": null }, +{ "label": "16/123", "node": 4142, "naklon": null }, +{ "label": "16/124", "node": 4147, "naklon": 5 }, +{ "label": "16/125", "node": 4139, "naklon": 5 }, +{ "label": "20/30A", "node": 3172, "naklon": 2 }, +{ "label": "20/30B", "node": 3164, "naklon": 2 }, +{ "label": "20/1", "node": 3247, "naklon": 10 }, +{ "label": "20/2", "node": 3296, "naklon": 10 }, +{ "label": "20/3", "node": 3246, "naklon": 10 }, +{ "label": "20/4", "node": 3270, "naklon": 10 }, +{ "label": "20/5", "node": 3294, "naklon": 10 }, +{ "label": "20/6", "node": 3298, "naklon": 10 }, +{ "label": "20/7", "node": 3297, "naklon": 10 }, +{ "label": "20/8", "node": 3293, "naklon": 10 }, +{ "label": "20/9", "node": 3299, "naklon": 10 }, +{ "label": "20/10", "node": 3295, "naklon": 10 }, +{ "label": "20/11", "node": 3244, "naklon": 10 }, +{ "label": "20/12", "node": 3249, "naklon": 10 }, +{ "label": "20/13", "node": 3268, "naklon": 10 }, +{ "label": "20/14", "node": 3245, "naklon": 10 }, +{ "label": "20/15", "node": 3278, "naklon": 10 }, +{ "label": "20/16", "node": 3280, "naklon": 10 }, +{ "label": "20/17", "node": 3292, "naklon": 10 }, +{ "label": "20/18", "node": 3287, "naklon": 10 }, +{ "label": "20/19", "node": 3282, "naklon": 10 }, +{ "label": "20/20", "node": 3273, "naklon": 0 }, +{ "label": "20/21", "node": 3157, "naklon": 0 }, +{ "label": "20/22", "node": 3283, "naklon": 0 }, +{ "label": "20/23", "node": 3159, "naklon": 0 }, +{ "label": "20/24", "node": 3289, "naklon": 0 }, +{ "label": "20/25", "node": 3163, "naklon": 0 }, +{ "label": "20/26", "node": 3126, "naklon": 0 }, +{ "label": "20/27", "node": 3171, "naklon": 0 }, +{ "label": "20/28", "node": 3162, "naklon": 0 }, +{ "label": "20/29", "node": 3279, "naklon": 10 }, +{ "label": "20/31", "node": 3173, "naklon": 0 }, +{ "label": "20/32", "node": 3127, "naklon": 0 }, +{ "label": "20/33", "node": 3131, "naklon": 0 }, +{ "label": "20/34", "node": 3129, "naklon": 0 }, +{ "label": "20/35", "node": 3276, "naklon": 2 }, +{ "label": "20/36", "node": 3290, "naklon": 2 }, +{ "label": "20/37", "node": 3132, "naklon": 0 }, +{ "label": "20/38", "node": 3138, "naklon": 0 }, +{ "label": "20/39", "node": 3272, "naklon": 0 }, +{ "label": "20/40", "node": 3291, "naklon": 0 }, +{ "label": "20/41", "node": 3277, "naklon": 10 }, +{ "label": "20/42", "node": 3286, "naklon": 10 }, +{ "label": "20/43", "node": 3281, "naklon": 10 }, +{ "label": "20/44", "node": 3288, "naklon": 10 }, +{ "label": "20/45", "node": 3284, "naklon": 10 }, +{ "label": "20/46", "node": 3167, "naklon": 10 }, +{ "label": "20/47", "node": 3872, "naklon": 0 }, +{ "label": "20/48", "node": 3124, "naklon": 0 }, +{ "label": "20/49", "node": 3133, "naklon": 0 }, +{ "label": "20/50", "node": 3158, "naklon": 0 }, +{ "label": "20/51", "node": 3169, "naklon": 0 }, +{ "label": "20/52", "node": 3146, "naklon": 0 }, +{ "label": "20/53", "node": 3160, "naklon": 0 }, +{ "label": "20/54", "node": 3248, "naklon": 0 }, +{ "label": "20/55", "node": 3156, "naklon": 0 }, +{ "label": "20/56", "node": 3161, "naklon": 0 }, +{ "label": "20/57", "node": 3170, "naklon": 0 }, +{ "label": "20/58", "node": 3168, "naklon": 0 }, +{ "label": "20/59", "node": 3125, "naklon": 0 }, +{ "label": "20/60", "node": 3166, "naklon": 0 }, +{ "label": "20/61", "node": 3130, "naklon": 0 }, +{ "label": "20/62", "node": 3563, "naklon": 0 }, +{ "label": "20/63", "node": 3550, "naklon": null }, +{ "label": "20/67", "node": 3269, "naklon": 0 }, +{ "label": "21/1", "node": 2921, "naklon": 0 }, +{ "label": "21/2", "node": 2707, "naklon": 0 }, +{ "label": "21/3", "node": 2723, "naklon": 0 }, +{ "label": "21/4", "node": 2716, "naklon": 0 }, +{ "label": "21/5", "node": 2717, "naklon": 0 }, +{ "label": "21/6", "node": 2720, "naklon": 0 }, +{ "label": "21/7", "node": 2722, "naklon": 0 }, +{ "label": "21/8", "node": 2718, "naklon": 0 }, +{ "label": "21/9", "node": 2724, "naklon": 0 }, +{ "label": "21/10", "node": 2742, "naklon": 0 }, +{ "label": "21/11", "node": 2743, "naklon": 0 }, +{ "label": "21/12", "node": 2733, "naklon": 0 }, +{ "label": "21/14", "node": 2903, "naklon": 0 }, +{ "label": "21/15", "node": 2917, "naklon": 0 }, +{ "label": "21/16", "node": 2897, "naklon": 0 }, +{ "label": "21/17", "node": 2914, "naklon": 0 }, +{ "label": "21/18", "node": 2898, "naklon": 0 }, +{ "label": "21/19", "node": 2773, "naklon": 0 }, +{ "label": "21/20", "node": 2895, "naklon": 0 }, +{ "label": "21/21", "node": 2896, "naklon": 0 }, +{ "label": "21/22", "node": 2771, "naklon": 0 }, +{ "label": "21/23", "node": 2772, "naklon": 0 }, +{ "label": "21/24", "node": 2793, "naklon": 0 }, +{ "label": "21/25", "node": 2902, "naklon": 0 }, +{ "label": "21/26", "node": 2910, "naklon": 0 }, +{ "label": "21/27", "node": 2909, "naklon": 0 }, +{ "label": "21/28", "node": 2920, "naklon": 0 }, +{ "label": "21/29", "node": 2916, "naklon": 0 }, +{ "label": "21/30", "node": 2904, "naklon": 0 }, +{ "label": "21/31", "node": 2915, "naklon": 0 }, +{ "label": "21/32", "node": 2905, "naklon": 0 }, +{ "label": "21/33", "node": 2900, "naklon": 0 }, +{ "label": "21/34", "node": 2899, "naklon": 0 }, +{ "label": "21/36", "node": 2741, "naklon": 0 }, +{ "label": "21/37", "node": 2714, "naklon": 0 }, +{ "label": "21/38", "node": 2701, "naklon": 0 }, +{ "label": "21/39", "node": 2703, "naklon": 0 }, +{ "label": "21/40", "node": 2704, "naklon": 0 }, +{ "label": "21/41", "node": 2702, "naklon": 0 }, +{ "label": "21/42", "node": 2706, "naklon": 0 }, +{ "label": "21/43", "node": 2776, "naklon": 0 }, +{ "label": "21/44", "node": 2770, "naklon": 0 }, +{ "label": "21/45", "node": 2786, "naklon": 0 }, +{ "label": "21/46", "node": 2779, "naklon": 0 }, +{ "label": "21/47", "node": 2782, "naklon": 0 }, +{ "label": "21/48", "node": 2785, "naklon": 0 }, +{ "label": "21/49", "node": 2769, "naklon": 0 }, +{ "label": "21/50", "node": 3354, "naklon": 0 }, +{ "label": "21/51", "node": 2778, "naklon": 0 }, +{ "label": "21/52", "node": 2775, "naklon": 0 }, +{ "label": "21/53", "node": 2780, "naklon": 0 }, +{ "label": "21/54", "node": 2790, "naklon": 0 }, +{ "label": "21/55", "node": 2792, "naklon": 0 }, +{ "label": "21/56", "node": 2774, "naklon": 0 }, +{ "label": "22/1", "node": 2630, "naklon": 0 }, +{ "label": "22/2", "node": 2631, "naklon": 0 }, +{ "label": "22/3", "node": 2632, "naklon": 0 }, +{ "label": "22/4", "node": 2633, "naklon": 0 }, +{ "label": "22/5", "node": 2634, "naklon": 0 }, +{ "label": "22/6", "node": 2636, "naklon": 0 }, +{ "label": "22/7", "node": 4367, "naklon": 0 }, +{ "label": "22/8", "node": 2637, "naklon": 0 }, +{ "label": "22/9", "node": 2638, "naklon": 0 }, +{ "label": "22/10", "node": 2639, "naklon": 0 }, +{ "label": "22/11", "node": 2640, "naklon": 0 }, +{ "label": "22/12", "node": 2641, "naklon": 0 }, +{ "label": "22/13", "node": 2642, "naklon": 0 }, +{ "label": "22/14", "node": 2643, "naklon": 0 }, +{ "label": "22/15", "node": 2644, "naklon": 0 }, +{ "label": "22/16", "node": 2645, "naklon": 0 }, +{ "label": "22/17", "node": 2646, "naklon": 0 }, +{ "label": "22/18", "node": 2647, "naklon": 0 }, +{ "label": "22/19", "node": 2648, "naklon": 0 }, +{ "label": "22/20", "node": 2649, "naklon": 0 }, +{ "label": "22/21", "node": 2650, "naklon": 0 }, +{ "label": "22/22", "node": 2651, "naklon": 0 }, +{ "label": "22/23", "node": 4103, "naklon": 0 }, +{ "label": "22/24", "node": 2653, "naklon": 0 }, +{ "label": "22/25", "node": 2654, "naklon": 0 }, +{ "label": "22/26", "node": 2655, "naklon": 0 }, +{ "label": "22/27", "node": 2656, "naklon": 0 }, +{ "label": "22/28", "node": 2657, "naklon": 0 }, +{ "label": "22/29", "node": 2658, "naklon": 0 }, +{ "label": "22/30", "node": 2659, "naklon": 0 }, +{ "label": "22/31", "node": 2660, "naklon": 0 }, +{ "label": "22/32", "node": 2661, "naklon": 0 }, +{ "label": "22/32/1", "node": 3015, "naklon": 0 }, +{ "label": "22/33", "node": 2662, "naklon": 0 }, +{ "label": "22/34", "node": 2663, "naklon": 0 }, +{ "label": "22/35", "node": 2664, "naklon": 0 }, +{ "label": "22/36", "node": 2665, "naklon": 0 }, +{ "label": "22/37", "node": 2666, "naklon": 0 }, +{ "label": "22/38", "node": 2667, "naklon": 0 }, +{ "label": "22/39", "node": 2668, "naklon": 0 }, +{ "label": "22/40", "node": 2669, "naklon": null }, +{ "label": "22/41", "node": 2670, "naklon": null }, +{ "label": "22/42", "node": 2671, "naklon": null }, +{ "label": "23/9A", "node": 3087, "naklon": 10 }, +{ "label": "23/9B", "node": 3090, "naklon": 10 }, +{ "label": "23/1", "node": 3075, "naklon": 0 }, +{ "label": "23/2", "node": 3089, "naklon": 0 }, +{ "label": "23/3", "node": 3088, "naklon": 0 }, +{ "label": "23/4", "node": 3228, "naklon": 10 }, +{ "label": "23/5", "node": 2751, "naklon": 10 }, +{ "label": "23/6", "node": 3243, "naklon": 10 }, +{ "label": "23/7", "node": 4349, "naklon": 10 }, +{ "label": "23/8", "node": 3102, "naklon": 10 }, +{ "label": "23/10", "node": 3099, "naklon": 10 }, +{ "label": "23/11", "node": 3103, "naklon": 10 }, +{ "label": "23/12", "node": 3093, "naklon": 10 }, +{ "label": "23/13", "node": 3098, "naklon": 10 }, +{ "label": "23/14", "node": 3092, "naklon": 10 }, +{ "label": "23/15", "node": 3233, "naklon": 0 }, +{ "label": "23/16", "node": 3095, "naklon": 0 }, +{ "label": "23/17", "node": 4074, "naklon": 0 }, +{ "label": "23/18", "node": 2729, "naklon": 0 }, +{ "label": "23/19", "node": 3234, "naklon": 0 }, +{ "label": "23/20", "node": 3094, "naklon": 0 }, +{ "label": "23/21", "node": 2817, "naklon": 0 }, +{ "label": "23/22", "node": 3226, "naklon": 0 }, +{ "label": "23/23", "node": 3225, "naklon": 0 }, +{ "label": "23/24", "node": 3237, "naklon": 0 }, +{ "label": "23/25", "node": 4250, "naklon": 0 }, +{ "label": "23/26", "node": 3059, "naklon": 10 }, +{ "label": "23/27", "node": 3238, "naklon": 10 }, +{ "label": "23/28", "node": 3242, "naklon": 10 }, +{ "label": "23/29", "node": 3236, "naklon": 10 }, +{ "label": "23/30", "node": 3112, "naklon": 10 }, +{ "label": "23/31", "node": 3224, "naklon": 0 }, +{ "label": "23/32", "node": 4298, "naklon": 10 }, +{ "label": "23/33", "node": 4150, "naklon": 10 }, +{ "label": "23/34", "node": 3091, "naklon": 10 }, +{ "label": "25/1", "node": 3771, "naklon": 5 }, +{ "label": "25/2", "node": 3777, "naklon": 5 }, +{ "label": "25/3", "node": 3749, "naklon": 5 }, +{ "label": "25/4", "node": 3769, "naklon": 5 }, +{ "label": "25/5", "node": 3765, "naklon": 5 }, +{ "label": "25/6", "node": 3785, "naklon": 5 }, +{ "label": "25/7", "node": 3761, "naklon": 5 }, +{ "label": "25/8", "node": 3758, "naklon": 5 }, +{ "label": "25/9", "node": 3766, "naklon": 5 }, +{ "label": "25/10", "node": 3779, "naklon": 5 }, +{ "label": "25/11", "node": 3899, "naklon": 10 }, +{ "label": "25/12", "node": 3922, "naklon": 10 }, +{ "label": "25/13", "node": 3912, "naklon": 10 }, +{ "label": "25/14", "node": 3933, "naklon": 10 }, +{ "label": "25/15", "node": 3921, "naklon": 10 }, +{ "label": "25/16", "node": 4300, "naklon": 10 }, +{ "label": "25/17", "node": 3927, "naklon": 10 }, +{ "label": "25/18", "node": 3212, "naklon": 10 }, +{ "label": "25/19", "node": 3208, "naklon": 10 }, +{ "label": "25/20", "node": 3207, "naklon": 10 }, +{ "label": "25/21", "node": 4294, "naklon": 10 }, +{ "label": "25/22", "node": 3209, "naklon": 10 }, +{ "label": "25/23", "node": 3745, "naklon": 10 }, +{ "label": "25/24", "node": 3762, "naklon": 10 }, +{ "label": "25/25", "node": 3215, "naklon": 10 }, +{ "label": "25/26", "node": 3210, "naklon": 10 }, +{ "label": "25/27", "node": 3211, "naklon": 10 }, +{ "label": "25/28", "node": 3206, "naklon": 10 }, +{ "label": "25/29", "node": 3918, "naklon": 5 }, +{ "label": "25/30", "node": 3928, "naklon": 5 }, +{ "label": "25/31", "node": 3917, "naklon": 5 }, +{ "label": "25/32", "node": 4029, "naklon": 0 }, +{ "label": "25/33", "node": 4038, "naklon": 0 }, +{ "label": "25/34", "node": 4022, "naklon": 0 }, +{ "label": "25/35", "node": 3937, "naklon": 0 }, +{ "label": "25/36", "node": 3190, "naklon": 0 }, +{ "label": "25/37", "node": 3835, "naklon": 0 }, +{ "label": "25/38", "node": 3201, "naklon": 0 }, +{ "label": "25/39", "node": 3193, "naklon": 0 }, +{ "label": "25/40", "node": 3191, "naklon": 0 }, +{ "label": "25/41", "node": 3203, "naklon": 0 }, +{ "label": "25/42", "node": 4301, "naklon": 0 }, +{ "label": "25/43", "node": 3223, "naklon": 0 }, +{ "label": "25/44", "node": 3202, "naklon": 0 }, +{ "label": "25/45", "node": 3205, "naklon": 0 }, +{ "label": "25/46", "node": 3194, "naklon": 0 }, +{ "label": "25/47", "node": 3198, "naklon": 0 }, +{ "label": "25/48", "node": 3204, "naklon": 0 }, +{ "label": "25/49", "node": 3200, "naklon": 0 }, +{ "label": "25/50", "node": 3216, "naklon": 0 }, +{ "label": "25/51", "node": 3932, "naklon": 5 }, +{ "label": "25/52", "node": 3923, "naklon": 5 }, +{ "label": "25/53", "node": 3913, "naklon": 5 }, +{ "label": "25/54", "node": 3900, "naklon": 5 }, +{ "label": "25/55", "node": 4189, "naklon": 10 }, +{ "label": "25/56", "node": 4191, "naklon": 10 }, +{ "label": "25/57", "node": 3790, "naklon": 10 }, +{ "label": "25/58", "node": 4190, "naklon": 10 }, +{ "label": "25/59", "node": 4302, "naklon": 0 }, +{ "label": "25/60", "node": 4351, "naklon": 0 }, +{ "label": "25/61", "node": 4075, "naklon": 0 }, +{ "label": "25/62", "node": 4071, "naklon": 0 }, +{ "label": "25/63", "node": 3784, "naklon": 0 }, +{ "label": "25/64", "node": 4065, "naklon": 0 }, +{ "label": "25/65", "node": 4297, "naklon": 0 }, +{ "label": "25/66", "node": 4295, "naklon": 0 }, +{ "label": "25/67", "node": 4299, "naklon": 0 }, +{ "label": "25/68", "node": 3772, "naklon": 0 }, +{ "label": "25/69", "node": 3941, "naklon": 0 }, +{ "label": "25/70", "node": 3782, "naklon": 0 }, +{ "label": "25/71", "node": 4068, "naklon": 0 }, +{ "label": "25/72", "node": 4073, "naklon": 0 }, +{ "label": "25/73", "node": 3901, "naklon": 5 }, +{ "label": "25/74", "node": 4296, "naklon": 5 }, +{ "label": "25/75", "node": 3910, "naklon": 5 }, +{ "label": "25/76", "node": 4293, "naklon": 5 }, +{ "label": "25/77", "node": 3919, "naklon": 5 }, +{ "label": "25/78", "node": 3924, "naklon": 5 }, +{ "label": "25/79", "node": 3909, "naklon": 5 }, +{ "label": "25/80", "node": 3896, "naklon": 5 }, +{ "label": "25/81", "node": 3911, "naklon": 5 }, +{ "label": "25/82", "node": 2819, "naklon": 15 }, +{ "label": "25/83", "node": 3776, "naklon": 15 }, +{ "label": "25/84", "node": 3752, "naklon": 15 }, +{ "label": "25/85", "node": 4353, "naklon": 15 }, +{ "label": "25/86", "node": 3791, "naklon": 0 }, +{ "label": "25/87", "node": 3770, "naklon": 0 }, +{ "label": "25/88", "node": 3760, "naklon": 0 }, +{ "label": "25/89", "node": 3115, "naklon": 0 }, +{ "label": "25/90", "node": 3738, "naklon": 0 }, +{ "label": "25/91", "node": 3748, "naklon": 0 }, +{ "label": "25/92", "node": 3753, "naklon": 0 }, +{ "label": "25/93", "node": 3775, "naklon": 0 }, +{ "label": "25/94", "node": 3778, "naklon": 5 }, +{ "label": "25/95", "node": 4078, "naklon": 5 }, +{ "label": "25/96", "node": 4088, "naklon": 5 }, +{ "label": "25/97", "node": 3856, "naklon": 5 }, +{ "label": "25/98", "node": 4084, "naklon": 5 }, +{ "label": "25/99", "node": 4069, "naklon": 5 }, +{ "label": "25/100", "node": 4188, "naklon": 5 }, +{ "label": "25/101", "node": 4064, "naklon": 5 }, +{ "label": "25/102", "node": 3792, "naklon": 5 }, +{ "label": "25/103", "node": 3780, "naklon": 5 }, +{ "label": "25/104", "node": 4034, "naklon": 5 }, +{ "label": "25/105", "node": 4072, "naklon": 5 }, +{ "label": "25/106", "node": 3884, "naklon": 5 }, +{ "label": "25/107", "node": 3793, "naklon": 5 }, +{ "label": "25/108", "node": 3863, "naklon": 5 }, +{ "label": "25/109", "node": 3855, "naklon": 5 }, +{ "label": "33/1", "node": 3846, "naklon": 0 }, +{ "label": "33/2", "node": 3943, "naklon": 0 }, +{ "label": "33/3", "node": 3903, "naklon": 0 }, +{ "label": "33/4", "node": 3982, "naklon": 0 }, +{ "label": "33/5", "node": 3879, "naklon": 0 }, +{ "label": "33/6", "node": 3887, "naklon": 0 }, +{ "label": "33/7", "node": 3920, "naklon": 5 }, +{ "label": "33/8", "node": 3942, "naklon": 5 }, +{ "label": "33/9", "node": 3829, "naklon": null }, +{ "label": "34/79A", "node": 3452, "naklon": 6 }, +{ "label": "34/79B", "node": 3460, "naklon": 6 }, +{ "label": "34/90A", "node": 3443, "naklon": 6 }, +{ "label": "34/90B", "node": 3445, "naklon": 6 }, +{ "label": "34/90C", "node": 3457, "naklon": 6 }, +{ "label": "34/97A", "node": 3461, "naklon": 6 }, +{ "label": "34/97B", "node": 3463, "naklon": 6 }, +{ "label": "34/98A", "node": 3426, "naklon": 6 }, +{ "label": "34/98B", "node": 3444, "naklon": 6 }, +{ "label": "34/99A", "node": 3453, "naklon": 6 }, +{ "label": "34/99B", "node": 3455, "naklon": 6 }, +{ "label": "34/1", "node": 4009, "naklon": 0 }, +{ "label": "34/2", "node": 3602, "naklon": 0 }, +{ "label": "34/3", "node": 3441, "naklon": 0 }, +{ "label": "34/4", "node": 3464, "naklon": 0 }, +{ "label": "34/5", "node": 3883, "naklon": 0 }, +{ "label": "34/6", "node": 4098, "naklon": 0 }, +{ "label": "34/7", "node": 4003, "naklon": 0 }, +{ "label": "34/8", "node": 4004, "naklon": 0 }, +{ "label": "34/9", "node": 3888, "naklon": 0 }, +{ "label": "34/10", "node": 3997, "naklon": 0 }, +{ "label": "34/11", "node": 4006, "naklon": 0 }, +{ "label": "34/12", "node": 4000, "naklon": 0 }, +{ "label": "34/13", "node": 4011, "naklon": 0 }, +{ "label": "34/14", "node": 3999, "naklon": 0 }, +{ "label": "34/15", "node": 3981, "naklon": 0 }, +{ "label": "34/16", "node": 3988, "naklon": 0 }, +{ "label": "34/17", "node": 3986, "naklon": 0 }, +{ "label": "34/18", "node": 3998, "naklon": 0 }, +{ "label": "34/19", "node": 3983, "naklon": 0 }, +{ "label": "34/20", "node": 4005, "naklon": 0 }, +{ "label": "34/21", "node": 4001, "naklon": 0 }, +{ "label": "34/22", "node": 4008, "naklon": 0 }, +{ "label": "34/23", "node": 4002, "naklon": 0 }, +{ "label": "34/24", "node": 3996, "naklon": 0 }, +{ "label": "34/25", "node": 4007, "naklon": 0 }, +{ "label": "34/26", "node": 4113, "naklon": 15 }, +{ "label": "34/27", "node": 3595, "naklon": 5 }, +{ "label": "34/28", "node": 3599, "naklon": 5 }, +{ "label": "34/29", "node": 3601, "naklon": 5 }, +{ "label": "34/30", "node": 4205, "naklon": 0 }, +{ "label": "34/31", "node": 3987, "naklon": null }, +{ "label": "34/32", "node": 4214, "naklon": 0 }, +{ "label": "34/33", "node": 4226, "naklon": 0 }, +{ "label": "34/34", "node": 4209, "naklon": 0 }, +{ "label": "34/35", "node": 4201, "naklon": 0 }, +{ "label": "34/36", "node": 3440, "naklon": 0 }, +{ "label": "34/37", "node": 3465, "naklon": 0 }, +{ "label": "34/38", "node": 3446, "naklon": 0 }, +{ "label": "34/39", "node": 4039, "naklon": 5 }, +{ "label": "34/40", "node": 4057, "naklon": 5 }, +{ "label": "34/41", "node": 3985, "naklon": 0 }, +{ "label": "34/42", "node": 3882, "naklon": 0 }, +{ "label": "34/43", "node": 4040, "naklon": 5 }, +{ "label": "34/44", "node": 3231, "naklon": 0 }, +{ "label": "34/45", "node": 3227, "naklon": 0 }, +{ "label": "34/46", "node": 3431, "naklon": 0 }, +{ "label": "34/47", "node": 4013, "naklon": 0 }, +{ "label": "34/48", "node": 4045, "naklon": 0 }, +{ "label": "34/49", "node": 3949, "naklon": 0 }, +{ "label": "34/50", "node": 3953, "naklon": 0 }, +{ "label": "34/51", "node": 3952, "naklon": 0 }, +{ "label": "34/52", "node": 3995, "naklon": 0 }, +{ "label": "34/53", "node": 3992, "naklon": 0 }, +{ "label": "34/54", "node": 4198, "naklon": 0 }, +{ "label": "34/55", "node": 3935, "naklon": 0 }, +{ "label": "34/56", "node": 4050, "naklon": 0 }, +{ "label": "34/57", "node": 4049, "naklon": 0 }, +{ "label": "34/58", "node": 4054, "naklon": 0 }, +{ "label": "34/59", "node": 3663, "naklon": 6 }, +{ "label": "34/60", "node": 3661, "naklon": 6 }, +{ "label": "34/61", "node": 3664, "naklon": 6 }, +{ "label": "34/62", "node": 3660, "naklon": 6 }, +{ "label": "34/63", "node": 3662, "naklon": 6 }, +{ "label": "34/65", "node": 3665, "naklon": 6 }, +{ "label": "34/66", "node": 3667, "naklon": 6 }, +{ "label": "34/67", "node": 3675, "naklon": 6 }, +{ "label": "34/68", "node": 3666, "naklon": 6 }, +{ "label": "34/69", "node": 3652, "naklon": 6 }, +{ "label": "34/70", "node": 3458, "naklon": 6 }, +{ "label": "34/70/1", "node": 4425, "naklon": 6 }, +{ "label": "34/71", "node": 3459, "naklon": 6 }, +{ "label": "34/72", "node": 3435, "naklon": 6 }, +{ "label": "34/73", "node": 3448, "naklon": 6 }, +{ "label": "34/74", "node": 3451, "naklon": 6 }, +{ "label": "34/75", "node": 3442, "naklon": 6 }, +{ "label": "34/76", "node": 3449, "naklon": 6 }, +{ "label": "34/77", "node": 3450, "naklon": 6 }, +{ "label": "34/78", "node": 3433, "naklon": 6 }, +{ "label": "34/80", "node": 3432, "naklon": 12 }, +{ "label": "34/81", "node": 3470, "naklon": 12 }, +{ "label": "34/82", "node": 3438, "naklon": 12 }, +{ "label": "34/83", "node": 3439, "naklon": 12 }, +{ "label": "34/84", "node": 4028, "naklon": 5 }, +{ "label": "34/85", "node": 3596, "naklon": 5 }, +{ "label": "34/86", "node": 4021, "naklon": 5 }, +{ "label": "34/87", "node": 3437, "naklon": 12 }, +{ "label": "34/88", "node": 3428, "naklon": 12 }, +{ "label": "34/89", "node": 3430, "naklon": 12 }, +{ "label": "34/91", "node": 3454, "naklon": 6 }, +{ "label": "34/92", "node": 3492, "naklon": 6 }, +{ "label": "34/93", "node": 3462, "naklon": 6 }, +{ "label": "34/94", "node": 3427, "naklon": 6 }, +{ "label": "34/95", "node": 3434, "naklon": 6 }, +{ "label": "34/96", "node": 3456, "naklon": 6 }, +{ "label": "34/98/1", "node": 4307, "naklon": 6 }, +{ "label": "35/1", "node": 3968, "naklon": 0 }, +{ "label": "35/2", "node": 3969, "naklon": 0 }, +{ "label": "35/3", "node": 3947, "naklon": 0 }, +{ "label": "35/4", "node": 3979, "naklon": 0 }, +{ "label": "35/5", "node": 3959, "naklon": 0 }, +{ "label": "35/6", "node": 3948, "naklon": 0 }, +{ "label": "35/7", "node": 3961, "naklon": 0 }, +{ "label": "35/8", "node": 3956, "naklon": 0 }, +{ "label": "35/9", "node": 3604, "naklon": 0 }, +{ "label": "35/10", "node": 3944, "naklon": 0 }, +{ "label": "35/11", "node": 3960, "naklon": 0 }, +{ "label": "35/12", "node": 3958, "naklon": 0 }, +{ "label": "35/13", "node": 4036, "naklon": 5 }, +{ "label": "35/18", "node": 3893, "naklon": 5 }, +{ "label": "35/19", "node": 4108, "naklon": 5 }, +{ "label": "35/20", "node": 4017, "naklon": 5 }, +{ "label": "35/21", "node": 3963, "naklon": 0 }, +{ "label": "35/22", "node": 3658, "naklon": 0 }, +{ "label": "35/23", "node": 3975, "naklon": 0 }, +{ "label": "35/24", "node": 3980, "naklon": 0 }, +{ "label": "35/25", "node": 4012, "naklon": 0 }, +{ "label": "35/26", "node": 3655, "naklon": 0 }, +{ "label": "35/27", "node": 3962, "naklon": 0 }, +{ "label": "35/28", "node": 3945, "naklon": 0 }, +{ "label": "35/29", "node": 3569, "naklon": 0 }, +{ "label": "35/30", "node": 3429, "naklon": 0 }, +{ "label": "35/31", "node": 3657, "naklon": 0 }, +{ "label": "35/32", "node": 3646, "naklon": 0 }, +{ "label": "35/33", "node": 3622, "naklon": 0 }, +{ "label": "35/34", "node": 3612, "naklon": 0 }, +{ "label": "35/35", "node": 3955, "naklon": 0 }, +{ "label": "35/37", "node": 3878, "naklon": 0 }, +{ "label": "35/38", "node": 3965, "naklon": 0 }, +{ "label": "35/39", "node": 3970, "naklon": 0 }, +{ "label": "35/40", "node": 3611, "naklon": 0 }, +{ "label": "35/41", "node": 2635, "naklon": 0 }, +{ "label": "35/42", "node": 3978, "naklon": 0 }, +{ "label": "35/43", "node": 4213, "naklon": 0 }, +{ "label": "35/44", "node": 3984, "naklon": 0 }, +{ "label": "35/45", "node": 4218, "naklon": 0 }, +{ "label": "35/46", "node": 3973, "naklon": 0 }, +{ "label": "35/47", "node": 3974, "naklon": 0 }, +{ "label": "35/48", "node": 3759, "naklon": 0 }, +{ "label": "35/49", "node": 3844, "naklon": 0 }, +{ "label": "35/50", "node": 3804, "naklon": 0 }, +{ "label": "35/51", "node": 3831, "naklon": 0 }, +{ "label": "35/52", "node": 3643, "naklon": 0 }, +{ "label": "35/53", "node": 3966, "naklon": 0 }, +{ "label": "35/54", "node": 3971, "naklon": 0 }, +{ "label": "35/55", "node": 3650, "naklon": 6 }, +{ "label": "35/56", "node": 3651, "naklon": 6 }, +{ "label": "35/57", "node": 3669, "naklon": 6 }, +{ "label": "35/58", "node": 3648, "naklon": 6 }, +{ "label": "35/59", "node": 3645, "naklon": 6 }, +{ "label": "35/60", "node": 3659, "naklon": 6 }, +{ "label": "35/61", "node": 3647, "naklon": 6 }, +{ "label": "35/62", "node": 3644, "naklon": 6 }, +{ "label": "35/63", "node": 3671, "naklon": 6 }, +{ "label": "35/64", "node": 3682, "naklon": 6 }, +{ "label": "35/65", "node": 3672, "naklon": 6 }, +{ "label": "35/66", "node": 3683, "naklon": 6 }, +{ "label": "35/67", "node": 3673, "naklon": 6 }, +{ "label": "35/68", "node": 3674, "naklon": 6 }, +{ "label": "35/69", "node": 3679, "naklon": 6 }, +{ "label": "35/70", "node": 3649, "naklon": 6 }, +{ "label": "35/71", "node": 3687, "naklon": 6 }, +{ "label": "35/72", "node": 3677, "naklon": 6 }, +{ "label": "35/73", "node": 3690, "naklon": 6 }, +{ "label": "35/74", "node": 3691, "naklon": 6 }, +{ "label": "35/75", "node": 3676, "naklon": 6 }, +{ "label": "35/76", "node": 3680, "naklon": 6 }, +{ "label": "35/77", "node": 3668, "naklon": 6 }, +{ "label": "35/78", "node": 3681, "naklon": 6 }, +{ "label": "35/79", "node": 3670, "naklon": 6 }, +{ "label": "35/80", "node": 3689, "naklon": 6 }, +{ "label": "35/81", "node": 3678, "naklon": 6 }, +{ "label": "35/82", "node": 3693, "naklon": 6 }, +{ "label": "35/83", "node": 3654, "naklon": null }, +{ "label": "36/1", "node": 4086, "naklon": 0 }, +{ "label": "36/2", "node": 4085, "naklon": 0 }, +{ "label": "36/3", "node": 4083, "naklon": 0 }, +{ "label": "36/4", "node": 4087, "naklon": 0 }, +{ "label": "36/5", "node": 4077, "naklon": 0 }, +{ "label": "36/6", "node": 4082, "naklon": 0 }, +{ "label": "36/7", "node": 4186, "naklon": 0 }, +{ "label": "36/8", "node": 4206, "naklon": 0 }, +{ "label": "36/9", "node": 4080, "naklon": 0 }, +{ "label": "36/10", "node": 4081, "naklon": 0 }, +{ "label": "36/11", "node": 4210, "naklon": 0 }, +{ "label": "36/12", "node": 4079, "naklon": 0 }, +{ "label": "36/13", "node": 4076, "naklon": 0 }, +{ "label": "36/14", "node": 3852, "naklon": 0 }, +{ "label": "36/15", "node": 2813, "naklon": 0 }, +{ "label": "36/16", "node": 4219, "naklon": 0 }, +{ "label": "37/1A", "node": 3104, "naklon": 15 }, +{ "label": "37/1B", "node": 3121, "naklon": 15 }, +{ "label": "37/2", "node": 3113, "naklon": 10 }, +{ "label": "37/3", "node": 3118, "naklon": 10 }, +{ "label": "37/4", "node": 3111, "naklon": 10 }, +{ "label": "37/5", "node": 4020, "naklon": 10 }, +{ "label": "37/6", "node": 3119, "naklon": 10 }, +{ "label": "37/7", "node": 3110, "naklon": 10 }, +{ "label": "37/8", "node": 3108, "naklon": 10 }, +{ "label": "37/12", "node": 3107, "naklon": 0 }, +{ "label": "37/13", "node": 3199, "naklon": 0 }, +{ "label": "37/14", "node": 3120, "naklon": 0 }, +{ "label": "37/15", "node": 3122, "naklon": 0 }, +{ "label": "37/16", "node": 3908, "naklon": 0 }, +{ "label": "37/17", "node": 3114, "naklon": 0 }, +{ "label": "37/18", "node": 3105, "naklon": 0 }, +{ "label": "37/19", "node": 3116, "naklon": 0 }, +{ "label": "37/20", "node": 3106, "naklon": 0 }, +{ "label": "37/21", "node": 2887, "naklon": 5 }, +{ "label": "37/22", "node": 2888, "naklon": 5 }, +{ "label": "37/23", "node": 2877, "naklon": 5 }, +{ "label": "37/24", "node": 2891, "naklon": 5 }, +{ "label": "37/25", "node": 2886, "naklon": 5 }, +{ "label": "37/26", "node": 2892, "naklon": 5 }, +{ "label": "37/27", "node": 2882, "naklon": 5 }, +{ "label": "37/28", "node": 2883, "naklon": 5 }, +{ "label": "37/29", "node": 2876, "naklon": 5 }, +{ "label": "37/30", "node": 3109, "naklon": 5 }, +{ "label": "37/31", "node": 4152, "naklon": 5 }, +{ "label": "37/32", "node": 3117, "naklon": 5 }, +{ "label": "37/33", "node": 2870, "naklon": 5 }, +{ "label": "37/34", "node": 2867, "naklon": 0 }, +{ "label": "37/35", "node": 2865, "naklon": 0 }, +{ "label": "37/36", "node": 3096, "naklon": 0 }, +{ "label": "37/37", "node": 2871, "naklon": 0 }, +{ "label": "37/38", "node": 2884, "naklon": 0 }, +{ "label": "37/39", "node": 2855, "naklon": 0 }, +{ "label": "37/40", "node": 2878, "naklon": 0 }, +{ "label": "37/41", "node": 2889, "naklon": 0 }, +{ "label": "37/42", "node": 2879, "naklon": 0 }, +{ "label": "37/43", "node": 2850, "naklon": 0 }, +{ "label": "37/44", "node": 2894, "naklon": 0 }, +{ "label": "37/45", "node": 2880, "naklon": 0 }, +{ "label": "37/46", "node": 2893, "naklon": 0 }, +{ "label": "37/47", "node": 2890, "naklon": 0 }, +{ "label": "37/48", "node": 4355, "naklon": 0 }, +{ "label": "37/49", "node": 2885, "naklon": 0 }, +{ "label": "37/50", "node": 2875, "naklon": 0 }, +{ "label": "38/30A", "node": 3486, "naklon": 5 }, +{ "label": "38/30B", "node": 3714, "naklon": 0 }, +{ "label": "38/32A", "node": 3483, "naklon": 5 }, +{ "label": "38/32B", "node": 3496, "naklon": 0 }, +{ "label": "38/35A", "node": 3487, "naklon": 5 }, +{ "label": "38/35B", "node": 3498, "naklon": 5 }, +{ "label": "38/38A", "node": 3578, "naklon": 5 }, +{ "label": "38/38B", "node": 3508, "naklon": 5 }, +{ "label": "38/59A", "node": 3787, "naklon": 5 }, +{ "label": "38/59B", "node": 3491, "naklon": 5 }, +{ "label": "38/1", "node": 3568, "naklon": null }, +{ "label": "38/2", "node": 3502, "naklon": 0 }, +{ "label": "38/3", "node": 3836, "naklon": 0 }, +{ "label": "38/4", "node": 3588, "naklon": 0 }, +{ "label": "38/5", "node": 3493, "naklon": 0 }, +{ "label": "38/6", "node": 3580, "naklon": 0 }, +{ "label": "38/7", "node": 3572, "naklon": 0 }, +{ "label": "38/8", "node": 3506, "naklon": 0 }, +{ "label": "38/9", "node": 3503, "naklon": 0 }, +{ "label": "38/10", "node": 3579, "naklon": 0 }, +{ "label": "38/11", "node": 3586, "naklon": 0 }, +{ "label": "38/12", "node": 3495, "naklon": 5 }, +{ "label": "38/13", "node": 3492, "naklon": 5 }, +{ "label": "38/14", "node": 3532, "naklon": 5 }, +{ "label": "38/15", "node": 3574, "naklon": 5 }, +{ "label": "38/16", "node": 4140, "naklon": 5 }, +{ "label": "38/17", "node": 3795, "naklon": 5 }, +{ "label": "38/18", "node": 3788, "naklon": 5 }, +{ "label": "38/19", "node": 3796, "naklon": 5 }, +{ "label": "38/20", "node": 3797, "naklon": 5 }, +{ "label": "38/21", "node": 3798, "naklon": 5 }, +{ "label": "38/22", "node": 3786, "naklon": 5 }, +{ "label": "38/23", "node": 4067, "naklon": 5 }, +{ "label": "38/24", "node": 3773, "naklon": 5 }, +{ "label": "38/25", "node": 3774, "naklon": 5 }, +{ "label": "38/26", "node": 3789, "naklon": 5 }, +{ "label": "38/27", "node": 3520, "naklon": null }, +{ "label": "38/29", "node": 3577, "naklon": 5 }, +{ "label": "38/31", "node": 3530, "naklon": null }, +{ "label": "38/33", "node": 3488, "naklon": 5 }, +{ "label": "38/34", "node": 3505, "naklon": 5 }, +{ "label": "38/36", "node": 3497, "naklon": 5 }, +{ "label": "38/37", "node": 3490, "naklon": 5 }, +{ "label": "38/39", "node": 3585, "naklon": 5 }, +{ "label": "38/40", "node": 3582, "naklon": 5 }, +{ "label": "38/41", "node": 3507, "naklon": 5 }, +{ "label": "38/42", "node": 3484, "naklon": 5 }, +{ "label": "38/43", "node": 3501, "naklon": 5 }, +{ "label": "38/44", "node": 3581, "naklon": 5 }, +{ "label": "38/45", "node": 4192, "naklon": 5 }, +{ "label": "38/46", "node": 3576, "naklon": 5 }, +{ "label": "38/47", "node": 3489, "naklon": 5 }, +{ "label": "38/48", "node": 3573, "naklon": 5 }, +{ "label": "38/49", "node": 3504, "naklon": 5 }, +{ "label": "38/50", "node": 3794, "naklon": 5 }, +{ "label": "38/51", "node": 3485, "naklon": 5 }, +{ "label": "38/52", "node": 3482, "naklon": 5 }, +{ "label": "38/53", "node": 3575, "naklon": 5 }, +{ "label": "38/54", "node": 3499, "naklon": 5 }, +{ "label": "38/55", "node": 3494, "naklon": 5 }, +{ "label": "38/56", "node": 3583, "naklon": 5 }, +{ "label": "38/57", "node": 3570, "naklon": 5 }, +{ "label": "38/58", "node": 3500, "naklon": 0 }, +{ "label": "38/63", "node": 3510, "naklon": null }, +{ "label": "38/64", "node": 3512, "naklon": null }, +{ "label": "38/67", "node": 3535, "naklon": null }, +{ "label": "38/68", "node": 3531, "naklon": null }, +{ "label": "38/69", "node": 3537, "naklon": null }, +{ "label": "39/1", "node": 3522, "naklon": 10 }, +{ "label": "39/2", "node": 4018, "naklon": 10 }, +{ "label": "39/3", "node": 4019, "naklon": 10 }, +{ "label": "39/4", "node": 4154, "naklon": 5 }, +{ "label": "39/5", "node": 3907, "naklon": 5 }, +{ "label": "39/6", "node": 4148, "naklon": 0 }, +{ "label": "39/7", "node": 4153, "naklon": 0 }, +{ "label": "39/8", "node": 3938, "naklon": 0 }, +{ "label": "39/9", "node": 3802, "naklon": 0 }, +{ "label": "39/10", "node": 4015, "naklon": 0 }, +{ "label": "39/11", "node": 3929, "naklon": 0 }, +{ "label": "39/12", "node": 3946, "naklon": 0 }, +{ "label": "39/13", "node": 4014, "naklon": 0 }, +{ "label": "39/14", "node": 4155, "naklon": 0 }, +{ "label": "39/15", "node": 4149, "naklon": 0 }, +{ "label": "39/16", "node": 3642, "naklon": 0 }, +{ "label": "39/17", "node": 3636, "naklon": 5 }, +{ "label": "39/18", "node": 3991, "naklon": 0 }, +{ "label": "39/19", "node": 3994, "naklon": 0 }, +{ "label": "39/20", "node": 3990, "naklon": 0 }, +{ "label": "39/21", "node": 3967, "naklon": 0 }, +{ "label": "39/22", "node": 3977, "naklon": 0 }, +{ "label": "39/23", "node": 3757, "naklon": 15 }, +{ "label": "39/24", "node": 3633, "naklon": 15 }, +{ "label": "39/25", "node": 3744, "naklon": 15 }, +{ "label": "39/26", "node": 4023, "naklon": 5 }, +{ "label": "39/27", "node": 3720, "naklon": 5 }, +{ "label": "39/28", "node": 3734, "naklon": 5 }, +{ "label": "39/29", "node": 3741, "naklon": 5 }, +{ "label": "39/30", "node": 3721, "naklon": 5 }, +{ "label": "39/31", "node": 3845, "naklon": 0 }, +{ "label": "39/32", "node": 3840, "naklon": 0 }, +{ "label": "39/33", "node": 3837, "naklon": null }, +{ "label": "39/34", "node": 3839, "naklon": 0 }, +{ "label": "41/1", "node": 3542, "naklon": null }, +{ "label": "41/2", "node": 3566, "naklon": null }, +{ "label": "41/3", "node": 3548, "naklon": null }, +{ "label": "41/4", "node": 3515, "naklon": null }, +{ "label": "41/5", "node": 3559, "naklon": null }, +{ "label": "41/6", "node": 3509, "naklon": null }, +{ "label": "41/7", "node": 3524, "naklon": null }, +{ "label": "41/8", "node": 3518, "naklon": null }, +{ "label": "41/9", "node": 3182, "naklon": null }, +{ "label": "41/10", "node": 3187, "naklon": null }, +{ "label": "41/11", "node": 3195, "naklon": 0 }, +{ "label": "41/12", "node": 3857, "naklon": 0 }, +{ "label": "41/13", "node": 3183, "naklon": 0 }, +{ "label": "41/14", "node": 3177, "naklon": 0 }, +{ "label": "41/15", "node": 3189, "naklon": 0 }, +{ "label": "41/16", "node": 3186, "naklon": 0 }, +{ "label": "42/1", "node": 3178, "naklon": 0 }, +{ "label": "42/2", "node": 3219, "naklon": 0 }, +{ "label": "42/3", "node": 3475, "naklon": 0 }, +{ "label": "42/4", "node": 3175, "naklon": 0 }, +{ "label": "42/5", "node": 3222, "naklon": 0 }, +{ "label": "42/6", "node": 3221, "naklon": 0 }, +{ "label": "42/7", "node": 3181, "naklon": 0 }, +{ "label": "42/8", "node": 3180, "naklon": 0 }, +{ "label": "42/9", "node": 3218, "naklon": 0 }, +{ "label": "42/10", "node": 3176, "naklon": 0 }, +{ "label": "42/11", "node": 3174, "naklon": 0 }, +{ "label": "42/12", "node": 3220, "naklon": 0 }, +{ "label": "42/13", "node": 3533, "naklon": null }, +{ "label": "42/14", "node": 3543, "naklon": null }, +{ "label": "42/15", "node": 3554, "naklon": null }, +{ "label": "42/16", "node": 3549, "naklon": null }, +{ "label": "43/1", "node": 2857, "naklon": 5 }, +{ "label": "43/2", "node": 2752, "naklon": 5 }, +{ "label": "43/3", "node": 2753, "naklon": 5 }, +{ "label": "43/4", "node": 3024, "naklon": 5 }, +{ "label": "43/5", "node": 2754, "naklon": 5 }, +{ "label": "43/6", "node": 4423, "naklon": 5 }, +{ "label": "43/7", "node": 4368, "naklon": 5 }, +{ "label": "43/8", "node": 2978, "naklon": 5 }, +{ "label": "43/9", "node": 2868, "naklon": 5 }, +{ "label": "43/10", "node": 4377, "naklon": 5 }, +{ "label": "43/11", "node": 2757, "naklon": 5 }, +{ "label": "43/12", "node": 2970, "naklon": 5 }, +{ "label": "43/13", "node": 2758, "naklon": 5 }, +{ "label": "43/14", "node": 4378, "naklon": 5 }, +{ "label": "43/15", "node": 2759, "naklon": 5 }, +{ "label": "43/16", "node": 4342, "naklon": 5 }, +{ "label": "43/17", "node": 3026, "naklon": null }, +{ "label": "43/18", "node": 2986, "naklon": null }, +{ "label": "43/19", "node": 4343, "naklon": null }, +{ "label": "43/20", "node": 2760, "naklon": null }, +{ "label": "43/21", "node": 4379, "naklon": null }, +{ "label": "43/22", "node": 2971, "naklon": null }, +{ "label": "43/23", "node": 2761, "naklon": null }, +{ "label": "43/24", "node": 2762, "naklon": null }, +{ "label": "43/25", "node": 4339, "naklon": null }, +{ "label": "43/26", "node": 4380, "naklon": null }, +{ "label": "43/27", "node": 2975, "naklon": null }, +{ "label": "43/28", "node": 3003, "naklon": null }, +{ "label": "43/29", "node": 4338, "naklon": null }, +{ "label": "43/30", "node": 3002, "naklon": null }, +{ "label": "43/31", "node": 4345, "naklon": null }, +{ "label": "43/32", "node": 2979, "naklon": null }, +{ "label": "43/33", "node": 2989, "naklon": null }, +{ "label": "43/34", "node": 2996, "naklon": null }, +{ "label": "43/35", "node": 2972, "naklon": null }, +{ "label": "43/36", "node": 2988, "naklon": null }, +{ "label": "43/37", "node": 4344, "naklon": null }, +{ "label": "43/38", "node": 3022, "naklon": null }, +{ "label": "43/39", "node": 4341, "naklon": null }, +{ "label": "43/40", "node": 2983, "naklon": null }, +{ "label": "43/41", "node": 2995, "naklon": null }, +{ "label": "43/42", "node": 2763, "naklon": null }, +{ "label": "43/43", "node": 2764, "naklon": null }, +{ "label": "43/44", "node": 2765, "naklon": null }, +{ "label": "43/45", "node": 2766, "naklon": null }, +{ "label": "43/46", "node": 2767, "naklon": null }, +{ "label": "43/47", "node": 2768, "naklon": null }, +{ "label": "43/48", "node": 3018, "naklon": null }, +{ "label": "43/49", "node": 2982, "naklon": null }, +{ "label": "43/50", "node": 3019, "naklon": 0 }, +{ "label": "43/51", "node": 3013, "naklon": null }, +{ "label": "43/52", "node": 3007, "naklon": null }, +{ "label": "43/53", "node": 2980, "naklon": null }, +{ "label": "43/54", "node": 3011, "naklon": null }, +{ "label": "43/55", "node": 2672, "naklon": null }, +{ "label": "43/56", "node": 2673, "naklon": null }, +{ "label": "43/57", "node": 2674, "naklon": null }, +{ "label": "43/58", "node": 2675, "naklon": null }, +{ "label": "43/59", "node": 2676, "naklon": null }, +{ "label": "43/60", "node": 2677, "naklon": null }, +{ "label": "43/61", "node": 2678, "naklon": null }, +{ "label": "43/62", "node": 2679, "naklon": null }, +{ "label": "43/63", "node": 2680, "naklon": null }, +{ "label": "43/64", "node": 2840, "naklon": null }, +{ "label": "43/65", "node": 2682, "naklon": null }, +{ "label": "43/66", "node": 2683, "naklon": null }, +{ "label": "43/67", "node": 2684, "naklon": 0 }, +{ "label": "43/68", "node": 2685, "naklon": null }, +{ "label": "43/69", "node": 2686, "naklon": null }, +{ "label": "43/70", "node": 2687, "naklon": null }, +{ "label": "43/71", "node": 2688, "naklon": null }, +{ "label": "43/72", "node": 2689, "naklon": null }, +{ "label": "43/73", "node": 2690, "naklon": null }, +{ "label": "43/74", "node": 2691, "naklon": null }, +{ "label": "43/75", "node": 2692, "naklon": null }, +{ "label": "43/76", "node": 2693, "naklon": 0 }, +{ "label": "43/77", "node": 2694, "naklon": null }, +{ "label": "43/78", "node": 2695, "naklon": null }, +{ "label": "43/79", "node": 2696, "naklon": 0 }, +{ "label": "43/80", "node": 2697, "naklon": null }, +{ "label": "43/81", "node": 2698, "naklon": 0 }, +{ "label": "43/82", "node": 2699, "naklon": null }, +{ "label": "43/83", "node": 2700, "naklon": 0 }, +{ "label": "43/84", "node": 2744, "naklon": null }, +{ "label": "43/85", "node": 2745, "naklon": 0 }, +{ "label": "43/86", "node": 2746, "naklon": null }, +{ "label": "43/87", "node": 2747, "naklon": 0 }, +{ "label": "43/88", "node": 2748, "naklon": null }, +{ "label": "43/89", "node": 2749, "naklon": 0 }, +{ "label": "43/90", "node": 2841, "naklon": null }, +{ "label": "45/1", "node": 4237, "naklon": 5 }, +{ "label": "45/2", "node": 4226, "naklon": 5 }, +{ "label": "45/3", "node": 4242, "naklon": 5 }, +{ "label": "45/4", "node": 4179, "naklon": 5 }, +{ "label": "45/5", "node": 4247, "naklon": 5 }, +{ "label": "45/6", "node": 4245, "naklon": 5 }, +{ "label": "45/7", "node": 3872, "naklon": 5 }, +{ "label": "45/8", "node": 4175, "naklon": 5 }, +{ "label": "45/9", "node": 4236, "naklon": 5 }, +{ "label": "45/10", "node": 4170, "naklon": 5 }, +{ "label": "45/11", "node": 4238, "naklon": 5 }, +{ "label": "45/12", "node": 4246, "naklon": 5 }, +{ "label": "45/13", "node": 4166, "naklon": 5 }, +{ "label": "45/14", "node": 4227, "naklon": 5 }, +{ "label": "45/15", "node": 4171, "naklon": 5 }, +{ "label": "45/16", "node": 4180, "naklon": 5 }, +{ "label": "45/17", "node": 4244, "naklon": 5 }, +{ "label": "45/18", "node": 4199, "naklon": 5 }, +{ "label": "45/19", "node": 4239, "naklon": 5 }, +{ "label": "45/20", "node": 4207, "naklon": 5 }, +{ "label": "45/21", "node": 4223, "naklon": 5 }, +{ "label": "45/22", "node": 4230, "naklon": 5 }, +{ "label": "45/23", "node": 4233, "naklon": 5 }, +{ "label": "45/24", "node": 4222, "naklon": 5 }, +{ "label": "45/25", "node": 4217, "naklon": 5 }, +{ "label": "45/26", "node": 4243, "naklon": 5 }, +{ "label": "45/27", "node": 4200, "naklon": 5 }, +{ "label": "45/28", "node": 4228, "naklon": 5 }, +{ "label": "45/29", "node": 4211, "naklon": 5 }, +{ "label": "45/30", "node": 4234, "naklon": 5 }, +{ "label": "45/31", "node": 4235, "naklon": 5 }, +{ "label": "45/32", "node": 4203, "naklon": 5 }, +{ "label": "45/33", "node": 4240, "naklon": 5 }, +{ "label": "45/34", "node": 4224, "naklon": 5 }, +{ "label": "45/35", "node": 4232, "naklon": 5 }, +{ "label": "45/36", "node": 4231, "naklon": 5 }, +{ "label": "45/37", "node": 4161, "naklon": 5 }, +{ "label": "45/38", "node": 4225, "naklon": 5 }, +{ "label": "45/39", "node": 4241, "naklon": 5 }, +{ "label": "45/40", "node": 4229, "naklon": 5 }, +{ "label": "45/41", "node": 4221, "naklon": 5 }, +{ "label": "45/42", "node": 4212, "naklon": 5 }, +{ "label": "45/43", "node": 4216, "naklon": 5 }, +{ "label": "45/44", "node": 3864, "naklon": null }, +{ "label": "46/1", "node": 3806, "naklon": 5 }, +{ "label": "46/2", "node": 3813, "naklon": 5 }, +{ "label": "46/3", "node": 3815, "naklon": 5 }, +{ "label": "46/4", "node": 3807, "naklon": 5 }, +{ "label": "46/5", "node": 3895, "naklon": 5 }, +{ "label": "46/6", "node": 3809, "naklon": 5 }, +{ "label": "46/7", "node": 3820, "naklon": 5 }, +{ "label": "46/8", "node": 3805, "naklon": 5 }, +{ "label": "46/9", "node": 3894, "naklon": 0 }, +{ "label": "46/10", "node": 4055, "naklon": 0 }, +{ "label": "46/11", "node": 3812, "naklon": 5 }, +{ "label": "46/12", "node": 3822, "naklon": 5 }, +{ "label": "46/13", "node": 3821, "naklon": 5 }, +{ "label": "46/14", "node": 3808, "naklon": 5 }, +{ "label": "46/15", "node": 3799, "naklon": 5 }, +{ "label": "46/16", "node": 3816, "naklon": 5 }, +{ "label": "46/17", "node": 3751, "naklon": 5 }, +{ "label": "46/18", "node": 3814, "naklon": 5 }, +{ "label": "46/19", "node": 4044, "naklon": 0 }, +{ "label": "46/20", "node": 3931, "naklon": 0 }, +{ "label": "46/21", "node": 3902, "naklon": 5 }, +{ "label": "46/22", "node": 3916, "naklon": 5 }, +{ "label": "46/23", "node": 3892, "naklon": 5 }, +{ "label": "46/24", "node": 3914, "naklon": 5 }, +{ "label": "46/25", "node": 3898, "naklon": 5 }, +{ "label": "46/26", "node": 3897, "naklon": 5 }, +{ "label": "46/27", "node": 3885, "naklon": 5 }, +{ "label": "46/28", "node": 3906, "naklon": 5 }, +{ "label": "46/29", "node": 3930, "naklon": 0 }, +{ "label": "46/30", "node": 3936, "naklon": 0 }, +{ "label": "46/31", "node": 3860, "naklon": 5 }, +{ "label": "46/32", "node": 3841, "naklon": 5 }, +{ "label": "46/33", "node": 3873, "naklon": 5 }, +{ "label": "46/34", "node": 3854, "naklon": 5 }, +{ "label": "46/35", "node": 3939, "naklon": 5 }, +{ "label": "46/36", "node": 3858, "naklon": 5 }, +{ "label": "46/37", "node": 3940, "naklon": 5 }, +{ "label": "46/38", "node": 4035, "naklon": 5 }, +{ "label": "47/1", "node": 3373, "naklon": 0 }, +{ "label": "47/2", "node": 3374, "naklon": 0 }, +{ "label": "47/3", "node": 3384, "naklon": 0 }, +{ "label": "47/4", "node": 3385, "naklon": 0 }, +{ "label": "48/1", "node": 4051, "naklon": 5 }, +{ "label": "48/2", "node": 4041, "naklon": 5 }, +{ "label": "48/3", "node": 4056, "naklon": 5 }, +{ "label": "48/4", "node": 3875, "naklon": 5 }, +{ "label": "48/5", "node": 4061, "naklon": 5 }, +{ "label": "48/6", "node": 4047, "naklon": 5 }, +{ "label": "48/7", "node": 4060, "naklon": 5 }, +{ "label": "48/8", "node": 4059, "naklon": 5 }, +{ "label": "48/9", "node": 4058, "naklon": 5 }, +{ "label": "48/10", "node": 3635, "naklon": 5 }, +{ "label": "48/11", "node": 3640, "naklon": 5 }, +{ "label": "48/12", "node": 3747, "naklon": 5 }, +{ "label": "48/13", "node": 3629, "naklon": 5 }, +{ "label": "48/14", "node": 4048, "naklon": 5 }, +{ "label": "48/15", "node": 4063, "naklon": 5 }, +{ "label": "48/16", "node": 4062, "naklon": 5 }, +{ "label": "48/17", "node": 4043, "naklon": 5 }, +{ "label": "48/18", "node": 4052, "naklon": 5 }, +{ "label": "48/19", "node": 4042, "naklon": 5 }, +{ "label": "48/20", "node": 4053, "naklon": 5 }, +{ "label": "50/15A", "node": 4167, "naklon": null }, +{ "label": "50/15B", "node": 4159, "naklon": null }, +{ "label": "50/1", "node": 4183, "naklon": 0 }, +{ "label": "50/2", "node": 4157, "naklon": 0 }, +{ "label": "50/3", "node": 4160, "naklon": 0 }, +{ "label": "50/4", "node": 4173, "naklon": 0 }, +{ "label": "50/5", "node": 4177, "naklon": 0 }, +{ "label": "50/6", "node": 4174, "naklon": 0 }, +{ "label": "50/7", "node": 4178, "naklon": 0 }, +{ "label": "50/8", "node": 4195, "naklon": 0 }, +{ "label": "50/9", "node": 4169, "naklon": 0 }, +{ "label": "50/10", "node": 4162, "naklon": 0 }, +{ "label": "50/11", "node": 4158, "naklon": 0 }, +{ "label": "50/12", "node": 4182, "naklon": 0 }, +{ "label": "50/13", "node": 4194, "naklon": 0 }, +{ "label": "50/14", "node": 4184, "naklon": 0 }, +{ "label": "50/16", "node": 4197, "naklon": null }, +{ "label": "50/17", "node": 4164, "naklon": null }, +{ "label": "50/18", "node": 3306, "naklon": null }, +{ "label": "50/19", "node": 4168, "naklon": null }, +{ "label": "50/20", "node": 4193, "naklon": null }, +{ "label": "50/21", "node": 4187, "naklon": null }, +{ "label": "50/22", "node": 4163, "naklon": null }, +{ "label": "50/23", "node": 4165, "naklon": null }, +{ "label": "50/24", "node": 4185, "naklon": null }, +{ "label": "50/25", "node": 3904, "naklon": null }, +{ "label": "53/1", "node": 2619, "naklon": 0 }, +{ "label": "53/2", "node": 2623, "naklon": 0 }, +{ "label": "53/3", "node": 2617, "naklon": 0 }, +{ "label": "53/4", "node": 2622, "naklon": 0 }, +{ "label": "53/5", "node": 2618, "naklon": 0 }, +{ "label": "53/6", "node": 2626, "naklon": 0 }, +{ "label": "53/7", "node": 2869, "naklon": 0 }, +{ "label": "53/8", "node": 2613, "naklon": 0 }, +{ "label": "53/9", "node": 2608, "naklon": 0 }, +{ "label": "53/10", "node": 2611, "naklon": 0 }, +{ "label": "53/11", "node": 2598, "naklon": 0 }, +{ "label": "53/12", "node": 3528, "naklon": 0 }, +{ "label": "53/13", "node": 3545, "naklon": 0 }, +{ "label": "53/14", "node": 2620, "naklon": 0 }, +{ "label": "53/15", "node": 2612, "naklon": 0 }, +{ "label": "53/16", "node": 2615, "naklon": 0 }, +{ "label": "53/17", "node": 3722, "naklon": 0 }, +{ "label": "53/18", "node": 2624, "naklon": 0 }, +{ "label": "53/19", "node": 2609, "naklon": 0 }, +{ "label": "53/20", "node": 2625, "naklon": 0 }, +{ "label": "53/21", "node": 2602, "naklon": 0 }, +{ "label": "53/22", "node": 2610, "naklon": 0 }, +{ "label": "53/23", "node": 2599, "naklon": 0 }, +{ "label": "53/24", "node": 2605, "naklon": 0 }, +{ "label": "53/25", "node": 2593, "naklon": 0 }, +{ "label": "53/26", "node": 3074, "naklon": 0 }, +{ "label": "53/27", "node": 2740, "naklon": 0 }, +{ "label": "53/28", "node": 2614, "naklon": 0 }, +{ "label": "53/29", "node": 2601, "naklon": 0 }, +{ "label": "53/30", "node": 4196, "naklon": 0 }, +{ "label": "53/31", "node": 2607, "naklon": 0 }, +{ "label": "53/32", "node": 2582, "naklon": 0 }, +{ "label": "53/33", "node": 2594, "naklon": 0 }, +{ "label": "53/34", "node": 2589, "naklon": 0 }, +{ "label": "53/35", "node": 2596, "naklon": 0 }, +{ "label": "53/36", "node": 2603, "naklon": 0 }, +{ "label": "53/37", "node": 2597, "naklon": 0 }, +{ "label": "53/38", "node": 2590, "naklon": 0 }, +{ "label": "53/39", "node": 2581, "naklon": 0 }, +{ "label": "53/40", "node": 2583, "naklon": 0 }, +{ "label": "53/41", "node": 2580, "naklon": 0 }, +{ "label": "53/42", "node": 2579, "naklon": 0 }, +{ "label": "53/43", "node": 2797, "naklon": 0 }, +{ "label": "53/44", "node": 2577, "naklon": 0 }, +{ "label": "53/45", "node": 2586, "naklon": 0 }, +{ "label": "53/46", "node": 2588, "naklon": 0 }, +{ "label": "53/47", "node": 2591, "naklon": 0 }, +{ "label": "53/48", "node": 2592, "naklon": 0 }, +{ "label": "53/49", "node": 2573, "naklon": 0 }, +{ "label": "53/50", "node": 2595, "naklon": 0 }, +{ "label": "53/51", "node": 2587, "naklon": 0 }, +{ "label": "53/52", "node": 2578, "naklon": 0 }, +{ "label": "53/53", "node": 2574, "naklon": 0 }, +{ "label": "53/54", "node": 2571, "naklon": 0 }, +{ "label": "53/55", "node": 2570, "naklon": 0 }, +{ "label": "53/56", "node": 2576, "naklon": 0 }, +{ "label": "53/57", "node": 2881, "naklon": 0 }, +{ "label": "53/58", "node": 2575, "naklon": 0 }, +{ "label": "53/59", "node": 2572, "naklon": 0 }, +{ "label": "53/60", "node": 2569, "naklon": 0 }, +{ "label": "55/1", "node": 4324, "naklon": 0 }, +{ "label": "55/2", "node": 4319, "naklon": 0 }, +{ "label": "55/3", "node": 4327, "naklon": 0 }, +{ "label": "55/4", "node": 4333, "naklon": 0 }, +{ "label": "55/5", "node": 4332, "naklon": 0 }, +{ "label": "55/6", "node": 4320, "naklon": 0 }, +{ "label": "55/7", "node": 4317, "naklon": 0 }, +{ "label": "55/8", "node": 4318, "naklon": 0 }, +{ "label": "55/9", "node": 4328, "naklon": 0 }, +{ "label": "55/10", "node": 4323, "naklon": 0 }, +{ "label": "55/11", "node": 4325, "naklon": 0 }, +{ "label": "55/12", "node": 4326, "naklon": 0 }, +{ "label": "55/13", "node": 4316, "naklon": 0 }, +{ "label": "55/14", "node": 4322, "naklon": 0 }, +{ "label": "55/15", "node": 4331, "naklon": 0 }, +{ "label": "55/16", "node": 4321, "naklon": 0 }, +{ "label": "55/17", "node": 4315, "naklon": 0 }, +{ "label": "55/18", "node": 4329, "naklon": 0 }, +{ "label": "55/19", "node": 4334, "naklon": 0 }, +{ "label": "55/20", "node": 4330, "naklon": 0 } +]; + +module.exports = { naklony }; diff --git a/RVO41/databases/modbus_config.js b/RVO41/databases/modbus_config.js new file mode 100755 index 0000000..b73116a --- /dev/null +++ b/RVO41/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/RVO41/databases/nodes.table b/RVO41/databases/nodes.table new file mode 100755 index 0000000..df43b95 --- /dev/null +++ b/RVO41/databases/nodes.table @@ -0,0 +1,17 @@ +node:number|pole_number:string|node_type:string|tbname:string|line:number|profile:string|processed:boolean|status:boolean|time_of_last_communication:number ++|3177|14|NEMA|RO8rjaBDy21qPQJzW7omn10pK3xmNleVZg9Ed4Gw|1||1|1|1760574029614|............. ++|3189|15|NEMA|3JjOWdylwgNLzxVab7NanJkZ2vG64rq8PEB5QmDo|1||1|1|1760574115784|............. ++|3548|3|IP65|o9vbeQlLMVg8j5dq4keLRK0NxZpEmnXzwYKO1ar2|1||1|1|1760574177663|............. ++|3182|9|NEMA|JzwxZXOvDj1bVrN4nkW5dzA8qdyBl3MRKLpGPgaQ|1||1|1|1760574112588|............. ++|3187|10|NEMA|g9OxBZ5KRwNznlY6pAppXOAWXvjdEL4eGQobMDy2|1||1|1|1760574218079|............. ++|3195|11|NEMA|OzNMgZ9n43qPbjXmy7zwYeA2DKdYvW5e6pxGRrVa|1||1|1|1760574124094|............. ++|3509|6|IP65|pE5X8NQPaow6vlOZxk6adz0q42ezGBMyWgDVjR3L|1||1|1|1760574127306|............. ++|3524|7|IP65|6lQGaY9RDywdVzObj0Pa3bkPg4NBn3exEK51LWZq|1||1|1|1760572490872|............. ++|3559|5|IP65|2O14VBzl8aDmWdNw3A59rGAGyZ5qLJoEMpj6R9ng|1||1|1|1760574075688|............. ++|3542|1|IP65|d5xjWYMwEJon6rLlK7yE2x7qgV4DaOeNB9ZX3Gzb|1||1|1|1760573167139|............. ++|3515|4|IP65|gP1eOZVj3Q9lv5aDEk45ja7rdpqW8yLm2BbKzJxM|1||1|1|1760574214659|............. ++|3518|8|IP65|m6EYyZoJ4gWexdjVPAR5qV7RDOq9wv2N5XzKGplr|1||1|1|1760574106020|............. ++|3566|2|IP65|apKVJBwOyrP35m2lv7KYxz0YXbeWNd64En9GxRqg|1||1|1|1760574240660|............. ++|3186|16|NEMA|dz4ojlpP85JMgDLZWkQJg37aKYqQexEr62GXRV1y|1||1|1|1760574087242|............. ++|3227|12|NEMA|JX1ObgmqGZ54DMyYL7aDBlkEVdve38WKRzwjNrQ9|1||1|1|1760574101672|............. ++|3183|13|NEMA|RvmwNz8QPblKp41GD7lKxYkJrLVYoBO92dMegn6W|1||1|1|1760574080945|............. diff --git a/RVO41/databases/nodes_original/nodes_original.table b/RVO41/databases/nodes_original/nodes_original.table new file mode 100755 index 0000000..09869e9 --- /dev/null +++ b/RVO41/databases/nodes_original/nodes_original.table @@ -0,0 +1 @@ +[{"3177": "RO8rjaBDy21qPQJzW7omn10pK3xmNleVZg9Ed4Gw"}, {"3189": "3JjOWdylwgNLzxVab7NanJkZ2vG64rq8PEB5QmDo"}, {"3548": "o9vbeQlLMVg8j5dq4keLRK0NxZpEmnXzwYKO1ar2"}, {"3182": "JzwxZXOvDj1bVrN4nkW5dzA8qdyBl3MRKLpGPgaQ"}, {"3187": "g9OxBZ5KRwNznlY6pAppXOAWXvjdEL4eGQobMDy2"}, {"3195": "OzNMgZ9n43qPbjXmy7zwYeA2DKdYvW5e6pxGRrVa"}, {"3509": "pE5X8NQPaow6vlOZxk6adz0q42ezGBMyWgDVjR3L"}, {"3524": "6lQGaY9RDywdVzObj0Pa3bkPg4NBn3exEK51LWZq"}, {"3559": "2O14VBzl8aDmWdNw3A59rGAGyZ5qLJoEMpj6R9ng"}, {"3542": "d5xjWYMwEJon6rLlK7yE2x7qgV4DaOeNB9ZX3Gzb"}, {"3515": "gP1eOZVj3Q9lv5aDEk45ja7rdpqW8yLm2BbKzJxM"}, {"3518": "m6EYyZoJ4gWexdjVPAR5qV7RDOq9wv2N5XzKGplr"}, {"3566": "apKVJBwOyrP35m2lv7KYxz0YXbeWNd64En9GxRqg"}, {"3186": "dz4ojlpP85JMgDLZWkQJg37aKYqQexEr62GXRV1y"}, {"3227": "JX1ObgmqGZ54DMyYL7aDBlkEVdve38WKRzwjNrQ9"}, {"3183": "RvmwNz8QPblKp41GD7lKxYkJrLVYoBO92dMegn6W"}] \ No newline at end of file diff --git a/RVO41/databases/notifications.table b/RVO41/databases/notifications.table new file mode 100755 index 0000000..f7c96cb --- /dev/null +++ b/RVO41/databases/notifications.table @@ -0,0 +1,41 @@ +key:string|weight:string|sk:string|en:string ++|switching_profile_point_applied_to_line|INFORMATIONAL|Aplikovaný bod spínacieho profilu na línií č. ${line} : ${value}|Switching profile point applied to line no. ${line} : ${value}|............... ++|dusk_has_occured|INFORMATIONAL|Nastal súmrak: ${value}|Dusk has occured: ${value}|............... ++|dawn_has_occured|INFORMATIONAL|Nastal úsvit: ${value}|Dawn has occured: ${value}|............... ++|dimming_profile_was_successfully_received_by_node|NOTICE|Stmievací profil bol úspešne prijatý nodom č. ${node}|Dimming profile was successfully received by node no. ${node}|............... ++|master_node_is_responding_again|NOTICE|Master node začal znovu odpovedať|Master node is responding again|............... ++|command_was_sent_from_terminal_interface|DEBUG|Z terminálu bol odoslaný príkaz|A command was sent from terminal interface|............... ++|master_node_is_not_responding|ALERT|Master node neodpovedá|Master node is not responding|............... ++|configuration_of_dimming_profile_to_node_failed|ALERT|Konfigurácia stmievacieho profilu pre node č. ${node} zlyhala|Configuration of dimming profile to node no. ${node} has failed|............... ++|circuit_breaker_was_turned_on_line|NOTICE|Zapnutie ističa na línii č. ${line}|Circuit breaker was turned on - line no. ${line}|............... ++|circuit_breaker_was_turned_off_line|ERROR|Vypnutie ističa na línií č. ${line}|Circuit breaker was turned off - line no. ${line}|............... ++|dimming_profile_was_processed_for_node|INFORMATIONAL|Stmievací profil bol spracovaný pre node č. ${node}|Dimming profile was processed for node no. ${node}|............... ++|switching_profile_was_processed_for_line|INFORMATIONAL|Spínací profil bol spracovaný pre líniu č. ${line}|Switching profile was processed for line no. ${line}|............... ++|thermometer_is_not_responding|WARNING|Teplomer neodpovedá|Thermometer is not responding|............... ++|thermometer_is_responding_again|NOTICE|Teplomer znovu odpovedá|Thermometer is responding again|............... ++|thermometer_sends_invalid_data|WARNING|Teplomer posiela neplatné hodnoty|Thermometer sends invalid data|............... ++|main_switch_has_been_turned_off|CRITICAL|Hlavný vypínač bol vypnutý|Main switch has been turned off|............... ++|main_switch_has_been_turned_on|NOTICE|Hlavný vypínač bol zapnutý|Main switch has been turned on|............... ++|power_supply_has_disconnected_input|ALERT|Napájací zdroj nemá napätie na vstupe|Power supply has disconnected input|............... ++|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_main_open|NOTICE|Hlavné dvere boli otvorené|Main door has been opened|............... ++|door_em_open|NOTICE|Dvere silovej časti boli otvorené|Power door has been opened|............... ++|door_main_open_without_permission|WARNING|Hlavné dvere boli otvorené bez povolenia - zapnutá siréna|Main door has been opened without permission - alarm is on|............... ++|door_em_open_without_permission|WARNING|Dvere silovej časti boli otvorené bez povolenia|Power door has been opened without permission|............... ++|door_main_close|NOTICE|Hlavné dvere boli zatvorené|Main door has been closed|............... ++|door_em_close|NOTICE|Dvere silovej časti boli zatvorené|Power door has been closed|............... ++|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|............... ++|electrometer_ok|NOTICE|Elektromer znovu odpovedá|Electrometer is responding again|............... ++|no_voltage_on_phase|CRITICAL|Na fáze č. ${phase} nie je napätie|No voltage detected on phase no. ${phase}|............... ++|voltage_on_phase_restored|NOTICE|Napätie na fáze č. ${phase} bolo obnovené|Voltage on phase no. ${phase} has been restored|............... ++|flow_start|NOTICE|FLOW bol spustený|FLOW has been started |............... ++|twilight_sensor_nok|ERROR|Sensor súmraku neodpovedá|Twilight sensor is not responding|............... ++|twilight_sensor_ok|NOTICE|Sensor súmraku znovu odpovedá|Twilight sensor is responding again|............... ++|lamps_have_turned_on|NOTICE|Lampy sa zapli|Lamps have turned on|............... ++|lamps_have_turned_off|NOTICE|Lampy sa vypli|Lamps have turned off|............... ++|flow_restart|NOTICE|FLOW bol reštartovaný|FLOW has been restarted|............... ++|nodes_db_changed|NOTICE|Zmena v node databáze|Node db has changed|............... diff --git a/RVO41/databases/pins.table b/RVO41/databases/pins.table new file mode 100755 index 0000000..0eb3d05 --- /dev/null +++ b/RVO41/databases/pins.table @@ -0,0 +1,14 @@ +pin:string|type:string|line:number +*|input1_01|door_condition|0|........... +*|input1_02|rotary_switch_state|0|........... +*|input1_03|rotary_switch_state|0|........... +*|input1_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/RVO41/databases/relays.table b/RVO41/databases/relays.table new file mode 100755 index 0000000..9a379b8 --- /dev/null +++ b/RVO41/databases/relays.table @@ -0,0 +1,5 @@ +line:number|tbname:string|contactor:number|profile:string ++|0|JzwxZXOvDj1bVrN4nkW5ZNA8qdyBl3MRKLpGPgaQ|1||........... ++|3|roKgWqY95V3mXMRzyAjKq20bLjexpJPvaGDBw826|9|{"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}|................................................................................................................................................................................................................................................................................................................................... ++|1|ZmRwd93QL4gaezxEbAx2eRk1prn2XjlPvGyqJ6BO|9|{"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|E6Kg9oDnLWyzPRMva7v5ZYkJxp4VG58qO2w1lZYe|9|{"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/RVO41/databases/settings.table b/RVO41/databases/settings.table new file mode 100755 index 0000000..60802cc --- /dev/null +++ b/RVO41/databases/settings.table @@ -0,0 +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|project_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|cloud_topic:string|has_main_switch:boolean|daily_report:boolean|send_changed_node_numbers:boolean ++|rvo_senica_41_ip117|en|28.F8F9940E0000|48.70826502|17.28455203|192.168.252.1|rvo_senica_41_ip117|b89KnIz2aYtmrygJv184|1883|0|50|unipi|ttyUSB0|1|20|5|6|3|u117|0|1|1|................................................... diff --git a/RVO41/databases/tbdata.nosql b/RVO41/databases/tbdata.nosql new file mode 100755 index 0000000..47b6fc7 --- /dev/null +++ b/RVO41/databases/tbdata.nosql @@ -0,0 +1,4 @@ +-"JzwxZXOvDj1bVrN4nkW5ZNA8qdyBl3MRKLpGPgaQ":[{"ts":1760520421817,"values":{"_event":{"type":"notice","status":"new","source":{"func":"modbus_reader","component":"1699965957410","component_name":"Modbus reader","edge":"JzwxZXOvDj1bVrN4nkW5ZNA8qdyBl3MRKLpGPgaQ"},"message":{"sk":"rvo_senica_41_ip117: FLOW bol reštartovaný","en":"rvo_senica_41_ip117: FLOW has been restarted"},"message_data":""}}}],"id":"3000147001wg71b"} +-"JzwxZXOvDj1bVrN4nkW5ZNA8qdyBl3MRKLpGPgaQ":[{"ts":1760520421902,"values":{"edge_fw_version":"2025-10-08","maintenance_mode":false}}],"id":"3000147002wg70b"} +-"JzwxZXOvDj1bVrN4nkW5ZNA8qdyBl3MRKLpGPgaQ":[{"ts":1760520421915,"values":{"statecode":2,"power_mode":"Automatic"}}],"id":"3000147004wg70b"} +-"JzwxZXOvDj1bVrN4nkW5ZNA8qdyBl3MRKLpGPgaQ":[{"ts":1760520421944,"values":{"_event":{"type":"notice","status":"new","source":{"func":"rsPort.open()","component":"1699963668903","component_name":"DIDO_Controller","edge":"JzwxZXOvDj1bVrN4nkW5ZNA8qdyBl3MRKLpGPgaQ"},"message":{"sk":"rvo_senica_41_ip117: FLOW bol spustený","en":"rvo_senica_41_ip117: FLOW has been started "},"message_data":""}}}],"id":"3000147006wg70b"} diff --git a/RVO41/databases/tbdatacloud.nosql b/RVO41/databases/tbdatacloud.nosql new file mode 100755 index 0000000..7107dee --- /dev/null +++ b/RVO41/databases/tbdatacloud.nosql @@ -0,0 +1,3 @@ +-"JzwxZXOvDj1bVrN4nkW5ZNA8qdyBl3MRKLpGPgaQ":[{"ts":1760520421902,"values":{"edge_fw_version":"2025-10-08","maintenance_mode":false}}],"id":"3000147003wg71b"} +-"JzwxZXOvDj1bVrN4nkW5ZNA8qdyBl3MRKLpGPgaQ":[{"ts":1760520421915,"values":{"statecode":2,"power_mode":"Automatic"}}],"id":"3000147005wg71b"} +-"JzwxZXOvDj1bVrN4nkW5ZNA8qdyBl3MRKLpGPgaQ":[{"ts":1760520421944,"values":{"_event":{"type":"notice","status":"new","source":{"func":"rsPort.open()","component":"1699963668903","component_name":"DIDO_Controller","edge":"JzwxZXOvDj1bVrN4nkW5ZNA8qdyBl3MRKLpGPgaQ"},"message":{"sk":"rvo_senica_41_ip117: FLOW bol spustený","en":"rvo_senica_41_ip117: FLOW has been started "},"message_data":""}}}],"id":"3000147007wg71b"} diff --git a/RVO41/databases/total_energy.js b/RVO41/databases/total_energy.js new file mode 100755 index 0000000..dde340e --- /dev/null +++ b/RVO41/databases/total_energy.js @@ -0,0 +1,38 @@ +//key is rvo_number, value is max energy when lamps are on +const total_energy = { + 1: 580, + 2: 1100, + 3: 3700, + 4: 4100, + 7: 360, + 12: 1700, + 13: 5400, + 14: 440, + 15: 6100, + 16: 4800, + 20: 1600, + 21: 1000, + 22: 2600, + 23: 1000, + 25: 2600, + 33: 240, + 34: 4000, + 35: 2700, + 36: 820, + 37: 1400, + 35: 3500, + 39: 1170, + 41: 740, + 42: 660, + 43: 4900, + 45: 930, + 46: 700, + 47: 1100, + 48: 1500, + 50: 3200, + 53: 1250, + 55: 1000, + 56: 5500 +} + +module.exports = total_energy; diff --git a/RVO41/debug.js b/RVO41/debug.js new file mode 100755 index 0000000..9818194 --- /dev/null +++ b/RVO41/debug.js @@ -0,0 +1,16 @@ +// =================================================== +// FOR DEVELOPMENT +// Total.js - framework for Node.js platform +// https://www.totaljs.com +// =================================================== + +const options = {}; + +// options.ip = '127.0.0.1'; +// options.port = parseInt(process.argv[2]); +// options.config = { name: 'Total.js' }; +// options.sleep = 3000; +// options.inspector = 9229; +// options.watch = ['private']; + +require('total.js/debug')(options); \ No newline at end of file diff --git a/RVO41/err.txt b/RVO41/err.txt new file mode 100755 index 0000000..34103bd --- /dev/null +++ b/RVO41/err.txt @@ -0,0 +1,123 @@ +[2024-10-25T16:19:29.438] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-25T17:19:41.537] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-25T17:49:47.590] [ERROR] errLogs - checkFinalRVOStatus: value is 0 state_of_main_switch +[2024-10-25T18:19:53.663] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-25T18:49:59.736] [ERROR] errLogs - checkFinalRVOStatus: value is 0 state_of_main_switch +[2024-10-25T19:20:05.815] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-25T19:55:12.908] [ERROR] errLogs - checkFinalRVOStatus: value is 0 state_of_main_switch +[2024-10-25T20:20:17.966] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-25T21:05:27.072] [ERROR] errLogs - checkFinalRVOStatus: value is 0 state_of_main_switch +[2024-10-25T21:23:00.610] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-25T22:10:40.217] [ERROR] errLogs - checkFinalRVOStatus: value is 0 state_of_main_switch +[2024-10-25T22:25:43.251] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-25T23:10:52.350] [ERROR] errLogs - checkFinalRVOStatus: value is 0 state_of_main_switch +[2024-10-25T23:25:55.366] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T00:21:06.507] [ERROR] errLogs - checkFinalRVOStatus: value is 0 state_of_main_switch +[2024-10-26T00:26:07.513] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T01:26:19.626] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T01:58:56.190] [ERROR] errLogs - checkFinalRVOStatus: value is 0 state_of_main_switch +[2024-10-26T02:26:31.749] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T03:09:10.369] [ERROR] errLogs - checkFinalRVOStatus: value is 0 state_of_main_switch +[2024-10-26T03:26:43.918] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T04:14:34.661] [ERROR] errLogs - checkFinalRVOStatus: value is 0 state_of_main_switch +[2024-10-26T04:26:57.147] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T05:14:36.739] [ERROR] errLogs - checkFinalRVOStatus: value is 0 state_of_main_switch +[2024-10-26T05:27:09.249] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T06:19:49.866] [ERROR] errLogs - checkFinalRVOStatus: value is 0 state_of_main_switch +[2024-10-26T06:27:21.389] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T07:20:02.011] [ERROR] errLogs - checkFinalRVOStatus: value is 0 state_of_main_switch +[2024-10-26T07:27:33.560] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T08:27:45.656] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T08:42:48.713] [ERROR] errLogs - checkFinalRVOStatus: value is 0 state_of_main_switch +[2024-10-26T09:27:57.891] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T09:50:32.439] [ERROR] errLogs - checkFinalRVOStatus: value is 0 state_of_main_switch +[2024-10-26T10:28:10.001] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T10:50:44.571] [ERROR] errLogs - checkFinalRVOStatus: value is 0 state_of_main_switch +[2024-10-26T11:28:22.122] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T11:55:57.679] [ERROR] errLogs - checkFinalRVOStatus: value is 0 state_of_main_switch +[2024-10-26T12:28:34.224] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T13:11:12.798] [ERROR] errLogs - checkFinalRVOStatus: value is 0 state_of_main_switch +[2024-10-26T13:28:46.322] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T14:11:24.892] [ERROR] errLogs - checkFinalRVOStatus: value is 0 state_of_main_switch +[2024-10-26T14:28:58.431] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T15:11:36.993] [ERROR] errLogs - checkFinalRVOStatus: value is 0 state_of_main_switch +[2024-10-26T15:29:10.519] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T16:14:19.605] [ERROR] errLogs - checkFinalRVOStatus: value is 0 state_of_main_switch +[2024-10-26T16:29:22.631] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T17:29:34.743] [ERROR] errLogs - checkFinalRVOStatus: value is 0 state_of_main_switch +[2024-10-26T17:32:05.248] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T18:29:46.951] [ERROR] errLogs - checkFinalRVOStatus: value is 0 state_of_main_switch +[2024-10-26T18:34:47.966] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T19:32:29.586] [ERROR] errLogs - checkFinalRVOStatus: value is 0 state_of_main_switch +[2024-10-26T19:35:00.091] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T20:32:41.715] [ERROR] errLogs - checkFinalRVOStatus: value is 0 state_of_main_switch +[2024-10-26T20:35:12.219] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T21:35:24.363] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T21:37:54.875] [ERROR] errLogs - checkFinalRVOStatus: value is 0 state_of_main_switch +[2024-10-26T22:38:07.041] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T22:50:39.568] [ERROR] errLogs - checkFinalRVOStatus: value is 0 state_of_main_switch +[2024-10-26T23:38:19.157] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T23:53:22.189] [ERROR] errLogs - checkFinalRVOStatus: value is 0 state_of_main_switch +[2024-10-27T00:38:31.271] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T01:01:05.833] [ERROR] errLogs - checkFinalRVOStatus: value is 0 state_of_main_switch +[2024-10-27T01:38:43.460] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T02:23:52.566] [ERROR] errLogs - checkFinalRVOStatus: value is 0 state_of_main_switch +[2024-10-27T02:43:56.607] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T02:41:38.212] [ERROR] errLogs - checkFinalRVOStatus: value is 0 state_of_main_switch +[2024-10-27T02:44:08.714] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T03:44:22.855] [ERROR] errLogs - checkFinalRVOStatus: value is 0 state_of_main_switch +[2024-10-27T03:46:53.360] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T04:47:05.523] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T05:12:10.592] [ERROR] errLogs - checkFinalRVOStatus: value is 0 state_of_main_switch +[2024-10-27T05:47:17.680] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T06:19:54.278] [ERROR] errLogs - checkFinalRVOStatus: value is 0 state_of_main_switch +[2024-10-27T06:47:29.843] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T07:32:38.899] [ERROR] errLogs - checkFinalRVOStatus: value is 0 state_of_main_switch +[2024-10-27T07:47:41.938] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T08:35:21.502] [ERROR] errLogs - checkFinalRVOStatus: value is 0 state_of_main_switch +[2024-10-27T08:47:54.025] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T09:40:34.624] [ERROR] errLogs - checkFinalRVOStatus: value is 0 state_of_main_switch +[2024-10-27T09:50:36.643] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T10:50:48.786] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T10:53:19.296] [ERROR] errLogs - checkFinalRVOStatus: value is 0 state_of_main_switch +[2024-10-27T11:53:31.382] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T11:56:01.884] [ERROR] errLogs - checkFinalRVOStatus: value is 0 state_of_main_switch +[2024-10-27T12:53:43.504] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T12:56:14.012] [ERROR] errLogs - checkFinalRVOStatus: value is 0 state_of_main_switch +[2024-10-27T13:53:55.760] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T14:19:00.904] [ERROR] errLogs - checkFinalRVOStatus: value is 0 state_of_main_switch +[2024-10-27T14:54:08.052] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T15:26:44.672] [ERROR] errLogs - checkFinalRVOStatus: value is 0 state_of_main_switch +[2025-09-23T14:04:59.438] [ERROR] errLogs - uncaughtException: Cannot read property 'getHours' of undefined +[2025-09-23T14:04:59.439] [ERROR] errLogs - TypeError: Cannot read property 'getHours' of undefined + at Timeout.emptyReportToSend [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:04:59.440] [ERROR] errLogs - uncaughtException: Cannot read property 'getHours' of undefined +[2025-09-23T14:04:59.440] [ERROR] errLogs - TypeError: Cannot read property 'getHours' of undefined + at Timeout.emptyReportToSend [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:04:59.449] [ERROR] errLogs - uncaughtException: Cannot read property 'getHours' of undefined +[2025-09-23T14:04:59.450] [ERROR] errLogs - TypeError: Cannot read property 'getHours' of undefined + at Timeout.emptyReportToSend [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:05:05.187] [ERROR] errLogs - uncaughtException: date.getHours is not a function +[2025-09-23T14:05:05.188] [ERROR] errLogs - TypeError: date.getHours is not a function + at emptyReportToSend (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at Timeout.dailyReportCheck [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1351:5) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:05:05.188] [ERROR] errLogs - uncaughtException: date.getHours is not a function +[2025-09-23T14:05:05.189] [ERROR] errLogs - TypeError: date.getHours is not a function + at emptyReportToSend (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at Timeout.dailyReportCheck [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1351:5) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:05:05.192] [ERROR] errLogs - uncaughtException: date.getHours is not a function +[2025-09-23T14:05:05.193] [ERROR] errLogs - TypeError: date.getHours is not a function + at emptyReportToSend (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at Timeout.dailyReportCheck [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1351:5) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) diff --git a/RVO41/flow/cloudmqttconnect.js b/RVO41/flow/cloudmqttconnect.js new file mode 100755 index 0000000..b03491f --- /dev/null +++ b/RVO41/flow/cloudmqttconnect.js @@ -0,0 +1,357 @@ +exports.id = 'cloudmqttconnect'; +exports.title = 'Cloud connect mqtt'; +exports.group = 'MQTT'; +exports.color = '#888600'; +exports.version = '1.0.2'; +exports.icon = 'sign-out'; +exports.input = 2; +exports.output = 2; +exports.options = { host: 'tb-stage.worksys.io', port: 1883, clientid: "", username: "" }; + +exports.html = `
+
+
+
Hostname or IP address (if not empty - setting will override db setting)
+
+
+
Port
+
+
+
+
+
@(Client id)
+
+
+
topic
+
+
+
`; + + + +const { promisifyBuilder } = require('./helper/db_helper'); +const fs = require('fs'); +const mqtt = require('mqtt'); +const nosql = NOSQL('tbdatacloud'); + +const SEND_TO = { + debug: 0, + rpcCall: 1, +} + +//CONFIG +let saveTelemetryOnError = true;//backup_on_failure overrides this value +//------------------------ + +const noSqlFileSizeLimit = 4194304;//use 5MB - 4194304 +let insertNoSqlCounter = 0; +let insertBackupNoSqlCounter = 0; +let processingData = false; + +let backup_on_failure = true;//== saveTelemetryOnError - create backup client send failure +let restore_from_backup = 50; //how many rows process at once? +let restore_backup_wait = 3;//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; + + +exports.install = function(instance) { + + var client; + var opts; + var clientReady = false; + + let o = {}; //options + + function main() { + loadSettings(); + } + + //set opts according to db settings + function loadSettings() { + + o = instance.options; + if (!o.topic) o.topic = FLOW.GLOBALS.settings.cloud_topic; + + opts = { + host: o.host, + port: o.port, + clientId: o.clientid, + username: o.username, + rejectUnauthorized: false, + resubscribe: false + }; + + console.log("wsmqttpublich -> loadSettings from instance.options", o); + + if (!o.topic) { + instance.status("Not configured", "white"); + console.log("Cloud mqtt connect: no topic selected"); + return; + } + + connectToTbServer(); + } + + function connectToTbServer() { + var url = "mqtt://" + opts.host + ":" + opts.port; + console.log("MQTT URL: ", url); + + client = mqtt.connect(url, opts); + + client.on('connect', function() { + client.subscribe(`${o.topic}_backward`, (err) => { + if (!err) { + console.log("MQTT subscribed"); + } + }); + instance.status("Connected", "green"); + clientReady = true; + sendClientError = true; + }); + + client.on('reconnect', function() { + instance.status("Reconnecting", "yellow"); + clientReady = false; + }); + + client.on('message', function(topic, message) { + // message is type of buffer + message = message.toString(); + if (message[0] === '{') { + TRY(function() { + + message = JSON.parse(message); + if (message.hasOwnProperty("device") && message.hasOwnProperty("data") && message.data.hasOwnProperty("id")) { + client.publish(`${o.topic}_forward`, `{"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 } }); + } + + }, () => instance.debug('MQTT: Error parsing data', message)); + } + + instance.send(SEND_TO.rpcCall, { "topic": o.topic, "content": message }); + }); + + client.on('close', function() { + clientReady = false; + + instance.status("Disconnected", "red"); + instance.send(SEND_TO.debug, { "message": "Client CLOSE signal received !" }); + }); + + client.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) { + console.log('MQTT client error', err); + sendClientError = false; + } + clientReady = false; + }); + + } + + + instance.on('0', function(data) { + + if (clientReady) { + //do we have some data in backup file? if any, process data from database + if (saveTelemetryOnError) { + //read telemetry data and send back to server + if (!processingData) processDataFromDatabase(); + } + + let stringifiedJson = JSON.stringify(data.data) + client.publish(`${o.topic}_forward`, stringifiedJson, { qos: 1 }); + } + 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 (saveTelemetryOnError && o.topic) { + //create new file from tbdata.nosql, if file size exceeds given limit, and clear tbdata.nosql + makeBackupFromDbFile(); + + //write to tb + data.data.id = UID(); + nosql.insert(data.data); + } + } + }); + + instance.on("1", _ => { + main(); + }) + + instance.close = function(done) { + if (clientReady) { + client.end(); + } + }; + + + function getDbBackupFileCounter(type) { + var files = fs.readdirSync(__dirname + "/../databases"); + + let counter = 0; + for (var i = 0; i < files.length; i++) { + + if (files[i] == "tbdatacloud.nosql") continue; + + if (files[i].endsWith(".nosql")) { + + let pos = files[i].indexOf("."); + if (pos > -1) { + + let fileCounter = counter; + let firstDigit = files[i].slice(0, pos); + + fileCounter = parseInt(firstDigit); + if (isNaN(fileCounter)) fileCounter = 0; + //console.log("getDbBackupFileCounter digit:", files[i], firstDigit, fileCounter, isNaN(fileCounter), type); + + if (type == "max") { + if (fileCounter > counter) { + counter = fileCounter; + } + } + else if (type == "min") { + if (counter == 0) counter = fileCounter; + + if (fileCounter < counter) { + counter = fileCounter; + } + } + } + } + + } + + if (type == "max") counter++; + + return counter; + } + + const makeBackupFromDbFile = async () => { + + if (!saveTelemetryOnError) return; + + //to avoid large file: tbdata.nosql + + //init value is 0! + if (insertNoSqlCounter > 0) { + --insertNoSqlCounter; + return; + } + + insertNoSqlCounter = 100; + + let source = __dirname + "/../databases/tbdatacloud.nosql"; + + var stats = fs.statSync(source); + var fileSizeInBytes = stats.size; + + if (fileSizeInBytes > noSqlFileSizeLimit) { + + let counter = 1; + counter = getDbBackupFileCounter("max"); + + let destination = __dirname + "/../databases/" + counter + "." + "tbdatacloud.nosql"; + + //make backup file + fs.copyFileSync(source, destination); + //fs.renameSync(p, p + "." + counter); + + //clear tbdata.nosql + fs.writeFileSync(source, ""); + fs.truncateSync(source, 0); + + } + } + + const processDataFromDatabase = async () => { + + if (restore_from_backup <= 0) return; + + //calculate diff + const now = new Date(); + let currentTime = now.getTime(); + let diff = currentTime - lastRestoreTime; + + if ((diff / 1000) < restore_backup_wait) { + //console.log("*********restore_backup_wait", diff, restore_backup_wait); + return; + } + + processingData = true; + + //get filename to process + let counter = getDbBackupFileCounter("min"); + + //we have some backup files + let dataBase = 'tbdata'; + + var nosql; + if (counter == 0) dataBase = 'tbdatacloud'; + else dataBase = counter + "." + 'tbdatacloud'; + + nosql = NOSQL(dataBase); + + //select all data - use limit restore_from_backup + let records = await promisifyBuilder(nosql.find().take(restore_from_backup)); + + for (let i = 0; i < records.length; i++) { + if (clientReady) { + + let item = records[i]; + let id = item.id; + + if (id !== undefined) { + //console.log("------------processDataFromDatabase - remove", id, dataBase, i); + + try { + + let message = JSON.parse(JSON.stringify(item)); + delete message.id; + client.publish(`${o.topic}_forward`, JSON.stringify(message), { qos: 1 }); + + //remove from database + await promisifyBuilder(nosql.remove().where("id", id)); + + } catch (error) { + //process error + console.log("processDataFromDatabase", error); + } + + } + + } + else { + processingData = false; + return; + } + } + + if (records.length > 0) { + //clean backup file + if (counter > 0) nosql.clean(); + } + + //no data in db, remove + if (records.length == 0) { + if (counter > 0) nosql.drop(); + } + + const d = new Date(); + lastRestoreTime = d.getTime(); + + processingData = false; + + } + + instance.on('options', main); + +}; diff --git a/RVO41/flow/cmd_manager.js b/RVO41/flow/cmd_manager.js new file mode 100755 index 0000000..25912df --- /dev/null +++ b/RVO41/flow/cmd_manager.js @@ -0,0 +1,3071 @@ +exports.id = 'cmd_manager'; +exports.title = 'CMD Manager'; +exports.group = 'Worksys'; +exports.color = '#5D9CEC'; +exports.version = '0.0.3'; +exports.output = ['red', 'blue', 'yellow', 'blue', 'white', 'green']; +exports.input = 3; +exports.icon = 'cloud-upload'; + +exports.html = ` +
+
+
+
RPC - run RPC calls

+
+
+
@(User)
+
+
+
@(Password)
+
+
+
@(My edge)
+
+
+
+`; +exports.readme = `Manager for CMD calls`; + + +exports.install = function(instance) { + + 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, isEmptyObject, emptyJsObject, writeToFile, addToArrayIfUnique } = require('./helper/utils'); + const bitwise = require('bitwise'); + + var SunCalc = require('./helper/suncalc'); + const DataToTbHandler = require('./helper/DataToTbHandler'); + const errorHandler = require('./helper/ErrorToServiceHandler'); + const { sendNotification } = require('./helper/notification_reporter'); + const process = require('process'); + const { errLogger, logger, monitor } = require('./helper/logger'); + + //for accelerometer purposes + const { naklony } = require("../databases/accelerometer_db"); + + const dbNodes = TABLE("nodes"); + const dbRelays = TABLE("relays"); + + let GLOBALS; + let SETTINGS; + let rsPort; + let tbHandler; + + // runTasks intervals + const SHORT_INTERVAL = 30; + const LONG_INTERVAL = 300; + + //send data to following instances: + const SEND_TO = { + debug: 0, + tb: 1, + http_response: 2, + dido_controller: 3, + infoSender: 4, + dailyReport: 5 + } + + 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 + } + + 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 sendNodeReadout = null; // interval for sending agregate data from node + + 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["1"] = minutes; // dimming + priorities["76"] = minutes; // power + + minutes = 5; + priorities["75"] = minutes; // current + priorities["79"] = minutes; // energy + priorities["87"] = minutes; // aktualny cas + //priorities["84"] = minutes; //accelerometer + + minutes = 10; + priorities["74"] = minutes; // voltage + priorities["77"] = minutes; // power factor + priorities["78"] = minutes; // frequency + + minutes = 60; + priorities["0"] = minutes; // statecode + priorities["6"] = minutes; // dusk + priorities["7"] = minutes; // dawn + priorities["8"] = minutes; // profile + + minutes = 60 * 24; + priorities["89"] = minutes; // verzia fw + priorities["80"] = minutes; // lifetime + + //prikazy kt sa budu spustat na dany node - see config.js in terminal-oms.app. (1 - dimming) + let listOfCommands = [0, 1, 6, 7, 8, 74, 75, 76, 77, 78, 79, 80, 87, 89]; + + 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; + + // holds dusk, dawn (and more) values + let sunCalcResult; + + //helper container for counting resolved group of commands (commands related to set profile) + let cmdCounter = {};//key is node, value is counter + + //TODO: is this set working?? According to previous checks, sets do not work + //if sending of profile to node fails, we send notification and push node into set, so we do not send notification twice + const nodeProfileSendFail = new Set(); + + //we expect to get current temperature in Senica from senica-prod01 + let temperatureInSenica = null; + let accelerometerInterval = null; + + //NOTE: daily reports senica: + //rvo_is_on status, we monitor all nodes - if true, power and dimming should be not 0, if false, 24/7 nodes should be 0, other rvo should not respond + let rvo_is_on; + let previous_rvo_is_on_value; + let handleDailyReport; //setInterval for dailyReportHandler function + let dailyReport = {}; //data needed for daily report + let reportToSend = {}; //final report which we send to cloud + let breakerCounter = null; // status of breakers after flow starts is not in report + let rvoPeriod; // interval of checking dusk dawn and if rvo_is_on + let initialReportStatus = false; + + const DAILY_REPORT_HANDLER_TIME = 3_600_000; + const SET_SUNCALC_RESULT_TIME = 3_600_000; + const SET_RVO_PERIOD_TIME = 300_000; + const ADD_NODE_TO_REPORT_TIME = 3_600_000; + + //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); + + let now = new Date(); + console.log("Cmd-mngr installed", now.toLocaleString("sk-SK")); + + sunCalcResult = calculateDuskDawn(); + + handleRsPort(); + + customTasksInterval = setInterval(reportEdgeDateTimeAndNumberOfLuminaires, 120_000); + setTimeout(reportEdgeDateTimeAndNumberOfLuminaires, 4000); + + //dailyReport related + emptyReportToSend(); + breakerCounter = Object.keys(relaysData).length - 1; // we get number of lines (breakers) except of line 0 + rvoPeriod = setInterval(setRvoPeriod, SET_RVO_PERIOD_TIME); + setTimeout(setRvoPeriod, 3000); + setInterval(setSunCalcResult, SET_SUNCALC_RESULT_TIME); + handleDailyReport = setInterval(dailyReportHandler, DAILY_REPORT_HANDLER_TIME); + + + setCorrectTime = setInterval(setCorrectPlcTimeOnceADay, 60000 * 60); // 1 hour + setCorrectPlcTimeOnceADay(); + + sendNodeReadout = setInterval(sendNodesData, 150_000); + accelerometerInterval = setInterval(accelerometerData, 60000 * 30); //30 min + } + + + 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" + //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 + // if node regular readout does not respond, we repeat request + params.repeatCounter = 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-mngr: 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.byte4 = 96; + params.recipient = 1; + params.register = 8; + params.rw = 1;//write + params.timestamp = timestamp; + 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.byte4 = 96; + params.recipient = 1; + params.register = 8; + params.rw = 1;//write + params.timestamp = timestamp; + 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). + */ + + 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.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.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 + { + + logger.debug("processNodeProfile: Threshold lux level for DUSK/DAWN", node); + + let params = getParams(); + params.type = "set_node_profile"; + params.address = node; + params.register = 96; + params.recipient = 1; + params.rw = 1;//write + params.timestamp = timestamp; + 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(); + params.type = "set_node_profile"; + params.address = node; + params.register = 97; + params.recipient = 1; + params.rw = 1;//write + params.timestamp = timestamp; + 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.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); + + 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); + + console.log("proces profile finished *********************") + } + + + 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; + }); + } + + + 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) { + for (let k in nodesData) { + 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`); + } + } + } + + + function loadRelaysData(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 (value.contactor == 1) processAllNodeProfilesOnLine(value.line); + } + } + + + function reportOnlineNodeStatus(line) { + //Po zapnutí línie broadcastovo aktualizovať predtým čas a o 3 sek neskor - status, brightness + + logger.debug("Cmd-mngr: ----->reportOnlineNodeStatus for line", line); + + const d = new Date(); + + // broadcast actual time + let params = getParams(); + params.address = 0xffffffff;//Broadcast + params.byte1 = d.getHours(); + params.byte2 = d.getMinutes(); + params.recipient = 2;//2 broadcast, address = 0 + params.register = 87;//Actual time + params.rw = 1;//write + params.type = "node-onetime-write"; + params.timestamp = d.getTime() + 30000; + params.info = "run broadcast: Actual time"; + //params.debug = true; + + tasks.push(params); + + let sec = 3; + setTimeout(function() { + //Po zapnutí línie - spraviť hromadný refresh stavu práve zapnutých svietidiel + + let time = Date.now(); + + for (let k in nodesData) { + + //potrebujem nody k danej linii + 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].node_status_before_offline === true || nodesData[k].status === true) { + status = "OK"; + nodesData[k].time_of_last_communication = time; + } + + nodesData[k].readout.status = status; + + updateNodeStatus(k, status === "OK" ? true : false); + if (nodesData[k].hasOwnProperty("node_status_before_offline")) delete nodesData[k].node_status_before_offline; + sendTelemetry({ status: status }, tbname, time); + + //vyreportovanie dimming, current, input power pre liniu pre vsetky nody + //Prud + { + let params = getParams(); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 75;//prud + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = time + 4000; + params.info = 'read current'; + //params.debug = true; + tasks.push(params); + } + + //vykon + { + let params = getParams(); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 76;//výkon + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = time + 4100; + params.info = 'read power'; + //params.debug = true; + + tasks.push(params); + } + //dimming + { + let params = getParams(); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 1;//dimming + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = time + 4200; + params.info = 'read dimming'; + //params.debug = true; + + tasks.push(params); + } + + } + } + + }, sec * 1000); + } + + + function reportOfflineNodeStatus(line) { + + logger.info("Cmd-mngr: ------>reportOffLineNodeStatus for line ", line); + + values = {}; + values["dimming"] = 0;//brightness + values["power"] = 0;//výkon + values["current"] = 0;//prúd + values["status"] = "OFFLINE"; + + const date = Date.now(); + + Object.keys(nodesData).forEach(node => { + + //potrebujem nody k danej linii + if (line == nodesData[node].line || line == undefined) { + + let tbname = nodesData[node].tbname; + let nodeStatus = nodesData[node].status; + + //in case we have reported offline node status, we return (continue with next node) + if (nodeStatus === "OFFLINE") return; + + nodesData[node].node_status_before_offline = nodeStatus; + nodesData[node].status = "OFFLINE"; + nodesData[node].readout = {}; + + sendTelemetry({ ...values }, tbname, date); + } + }); + + } + + + function turnLine(onOrOff, line, info) { + let obj = { + line: line, + command: onOrOff, + info: info + }; + + //to assure, handleDailyReportFunction do not run before rvo_is_on variable changes. So after every line switch we reset the timer + clearInterval(handleDailyReport); + handleDailyReport = setInterval(dailyReportHandler, DAILY_REPORT_HANDLER_TIME); + + //logger.debug("linia", line, obj); + instance.send(SEND_TO.dido_controller, obj); + } + + + 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"; + 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]) { + //CRC_ERROR + message = "NOK"; + error = "CRC_ERROR c1"; + instance.send(SEND_TO.debug, "CRC_ERROR c1"); + } + + 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") { + instance.send(SEND_TO.debug, bytes); + instance.send(SEND_TO.debug, "RESPONSE " + type + " - " + bytes[4]); + + //logger.debug(SEND_TO.debug, "RESPONSE " + type + " - " + bytes[4], bytes); + + error = "type is: " + type; + + message = "NOK"; + } + + return { message, type, error }; + } + + + //BUILD TASKS// + function buildTasks(params) { + + //return; + console.log("buidTAaasks start ****************", params); + monitor.info("buildTasks - params", params); + + let processLine; //defined line + let init = false; + let processLineProfiles = true; + let processBroadcast = true; + let processNodes = true; + + if (params == undefined) { + init = true; + tasks = []; + logger.debug("-->buildTasks clear tasks"); + } + else { + processLineProfiles = params.processLineProfiles; + processBroadcast = false; + processNodes = false; + + processLine = params.line; + } + + let now = new Date(); + + //process line profiles + if (processLineProfiles) { + + let keys = Object.keys(relaysData); + + for (let i = 0; i < keys.length; i++) { + + let line = parseInt(keys[i]); + let profilestr = relaysData[line].profile; + + if (processLine != undefined) { + if (processLine != line) continue; + } + + try { + + /** + * we process line profiles: timepoints, astro clock, lux_sensor, offsets ... + */ + if (profilestr === "") throw ("Profile is not defined"); + let profile = JSON.parse(profilestr); + 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; + + // add name to regular profile timepoint and delete unused end_time key: + time_points.forEach(point => { + point.name = "profileTimepoint" + delete point.end_time; + }); + + //monitor.info("buildTasks: time_points", time_points); + + + /** + * 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 astro clock true, we remove all regular profile points + time_points = []; + + //TODO: when astro clock == true, is offset calculated ??? + //let duskAstroClockOffset = profile.dusk_astro_clock_offset; + //let dawnAstroClockOffset = profile.dawn_astro_clock_offset; + //console.log("line astro clock offsets dusk a dawn: ", duskAstroClockOffset, dawnAstroClockOffset); + // maybe add dusk dawn offset to calculateDuskDawn ?? what dusk dawn will be if dawn_lux_sensor == true?? + //let sunCalcResult = calculateDuskDawn(new Date(), line, duskAstroClockOffset, dawnAstroClockOffset); + + 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 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); + + 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); + + 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(':'); + + let ad = new Date(); + ad.setHours(parseInt(ahours), parseInt(aminutes), 0); + + let bd = new Date(); + bd.setHours(parseInt(bhours), parseInt(bminutes), 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++) { + + let start_time = new Date(); + let [hours, minutes] = time_points[t].start_time.split(':'); + start_time.setHours(parseInt(hours), parseInt(minutes), 0); + + //task is in 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(); + params.type = "relay"; + params.line = parseInt(line); + params.value = time_points[t].value; + params.tbname = relaysData[line].tbname; + params.timestamp = start_time.getTime(); + + // 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; + + //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)) { + 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; + + params.debug = true; + + //turn on/off line + tasks.push(params); + monitor.info("TimePoint params: ", params.info, start_time); + } + + monitor.info("-->time_points final", line, time_points); + + //ensure to turn on/off according to calculated currentValue + let params = getParams(); + params.type = "relay"; + params.line = parseInt(line); + params.tbname = relaysData[line].tbname; + params.value = currentValue; + params.timestamp = i; + params.debug = true; + + //logger.debug(now.toLocaleString("sk-SK")); + 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; + + tasks.push(params); + + } catch (error) { + if (profilestr !== "") { + //errLogger.error(profilestr, error); + console.log(`Cmd_mngr: Unable to process line profile ${line}. Error: `, error); + errorHandler.sendMessageToService(profilestr + "-" + error, 0, "js_error"); + } else { + turnLine("off", line, "No line profile. Switching it off on startup"); + } + } + + } + //logger.debug("tasks:"); + //logger.debug(tasks); + } + + + //NOTE: PROCESS DEFAULT BROADCASTS - Time of dusk, Time of dawn, Actual Time + if (processBroadcast) { + + let d = new Date(); + let time = d.getTime(); + //let sunCalcResult = calculateDuskDawn(); + + { + let params = getParams(); + + params.address = 0xffffffff;//broadcast + params.byte1 = sunCalcResult["dusk_hours"]; + params.byte2 = sunCalcResult["dusk_minutes"]; + params.recipient = 2;//2 broadcast, + params.register = 6;//Time of dusk + params.rw = 1;//write + params.type = "node-regular-write"; + params.timestamp = time + 60000; + params.addMinutesToTimestamp = 60 * 3; //kazde 3 hodiny zisti novy dusk + params.info = "Broadcast-duskTime"; + + tasks.push(params); + } + + { + let params = getParams(); + + params.address = 0xffffffff;//broadcast + params.byte1 = sunCalcResult["dawn_hours"]; + params.byte2 = sunCalcResult["dawn_minutes"]; + params.recipient = 2; //2 broadcast + params.register = 7;//Time of dawn + params.rw = 1;//write + params.type = "node-regular-write"; + params.timestamp = time + 60001; + params.addMinutesToTimestamp = 60 * 3; //kazde 3 hodiny zisti novy dawn + params.info = "Broadcast-dawnTime"; + + tasks.push(params); + } + + { + let params = getParams(); + + params.address = 0xffffffff;//broadcast + params.byte1 = d.getHours(); + params.byte2 = d.getMinutes(); + params.recipient = 2; //2 broadcast + params.register = 87;//Actual time + params.rw = 1;//write + params.type = "node-regular-write"; + params.timestamp = time + 60002; + params.addMinutesToTimestamp = 5; + params.info = "run broadcast: Actual time"; + + tasks.push(params); + } + + } + + //process nodes & tasks - read node's data + if (processNodes) { + + let time = Date.now(); + + for (let k in nodesData) { + let address = parseInt(k); + let tbname = nodesData[k].tbname; + let register = 0; + + for (let i = 0; i < listOfCommands.length; i++) { + + register = listOfCommands[i]; + let addMinutesToTimestamp = priorities[register]; + + let params = getParams(); + + params.address = address; + params.recipient = 1; + params.register = register; + params.type = register == 1 ? "node-dimming-read" : "node-regular-read"; + params.tbname = tbname; + params.timestamp = time + 5000 + i * 500 + addMinutesToTimestamp * 1000; //to make slight time difference + params.addMinutesToTimestamp = addMinutesToTimestamp; + params.info = "Node regular read command"; + + tasks.push(params); + } + + } + } + + + //niektore ulohy sa vygeneruju iba 1x pri starte!!! + if (!init) return; + + + //Master node FW version - modifies SETTINGS.masterNodeIsResponding + { + let params = getParams(); + params.type = "cmd-master"; + params.register = 4; + params.address = 0; + params.timestamp = 0; + params.addMinutesToTimestamp = 5; + params.tbname = SETTINGS.rvoTbName; + params.info = "Master node FW verzia"; + //params.debug = true; + + tasks.push(params); + } + + //kazdu hodinu skontrolovat nastavenie profilov + { + let params = getParams(); + params.type = "process_profiles"; + params.timestamp = Date.now() + 60001; + params.addMinutesToTimestamp = 60;//60 = every hour + params.info = "detekcia nespracovaných profilov linie a nodov"; + //params.debug = true; + + tasks.push(params); + } + + monitor.info("tasks created:", tasks.length); + } + + + /** + * We process line profile, where "astro_clock": true + * example profile: + * + "dawn_lux_sensor": true, + "dusk_lux_sensor": true, + "dawn_lux_sensor_value": 5, + "dusk_lux_sensor_value": 5, + "dawn_astro_clock_offset": 0, + "dusk_astro_clock_offset": 10, + "dawn_lux_sensor_time_window": 30, + "dusk_lux_sensor_time_window": 30, + "dawn_astro_clock_time_window": 60, + "dusk_astro_clock_time_window": 60 + + * if dawn: if currentTimestamp is in timewindow "dawnTime + and - dawn_lux_sensor_time_window" and lux value >= lux_sensor_value, we switch off the line. + * if dusk: we do oposite + * + * dawn: usvit - lux je nad hranicou - vypnem + * dusk: sumrak - lux je pod hranicou - zapnem + */ + 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++) { + + let line = keys[i]; //line is turned off by default + let profilestr = relaysData[line].profile; + const contactor = relaysData[line].contactor; + + try { + + let profile = JSON.parse(profilestr); + if (Object.keys(profile).length === 0) throw ("turnOnOffLinesAccordingToLuxSensor - profile is not defined"); + + 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 (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"); + } + } + } + + //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 (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"); + } + } + } + + } + + } catch (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) { + //MASTER + if (node == 0) return; + + let nodeObj = nodesData[node]; + if (nodeObj == undefined) return; + + let nodeCurrentStatus = nodeObj.status; + const now = Date.now(); + + let data = null; + + if (nodeCurrentStatus === "OFFLINE") { + data = { status: newStatus }; + nodeDbStatusModify(node, data); + return; + } + else 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; + } + + } + + + 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 }; + } + }); + }); + } + + + function processDailyReport() { + + const now = Date.now(); + + for (const [key, value] of Object.entries(dailyReport)) { + + if (["name", "time", "dusk_and_dawn"].includes(key)) continue; + + let poleNumber = nodesData[key]["pole_number"]; + let line = dailyReport[key].line; + let nodeType = nodesData[key]["node_type"]; + let fullNodeName = key // key == nodeNumber + + if (poleNumber && nodeType) { + fullNodeName = SETTINGS.rvo_number + "/" + poleNumber + "_" + line + "L_" + key + "_" + nodeType; + } else { + fullNodeName = key; + } + + if (rvo_is_on) { + + if (value.initialTs) { + if (value.initialTs + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["night_no_data"], fullNodeName); + console.log('report nedostava ziadne data uz hodinu', fullNodeName); + value.initialTs = now; + } + } + if (value.dimmingIsZeroTime) { + if (value.dimmingIsZeroTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["night_dimming=0"], fullNodeName); + console.log("report node dimming je 0 ale ma svietit", fullNodeName); + value.dimmingIsZeroTime = now; + } + } + if (value.powerIsZeroTime) { + if (value.powerIsZeroTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["night_power=0"], fullNodeName); + console.log("report node power je 0 ale ma svietit", fullNodeName); + value.powerIsZeroTime = now; + } + } + + } else { + + let contactorStatus = relaysData[line].contactor; + if (contactorStatus === 1) { + + if (value.initialTs) { + if (value.initialTs + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["day_24/7_no_data"], fullNodeName); + console.log('node je na 24/7 ale nedostava ziadne data uz hodinu', fullNodeName); + value.initialTs = now; + } + } + if (value.dimmingIsOnButShouldBeOffTime) { + if (value.dimmingIsOnButShouldBeOffTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["day_24/7_dimming>0"], fullNodeName); + console.log("report dimming je > 0 ale nema svietit", fullNodeName); + value.dimmingIsOnButShouldBeOffTime = now; + } + } + if (value.powerIsOnButShouldBeOffTime) { + if (value.powerIsOnButShouldBeOffTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["day_24/7_power>0"], fullNodeName); + console.log("report power je > 0 ale nema svietit", fullNodeName); + value.powerIsOnButShouldBeOffTime = now; + } + } + + } + + } + + } + + let report = {}; + report["name"] = SETTINGS.rvo_name; + report["time"] = new Date(); + report["report"] = reportToSend; + + writeToFile(F.path.root("report_data.log"), report, true); + instance.send(SEND_TO.dailyReport, report); + } + + + function dailyReportHandler() { + + if (!SETTINGS.daily_report) return; + + // after dawn we empty reportToSend and start to get data for a new day + const date = new Date(); + const hour = date.getHours(); + const minute = date.getMinutes(); + + console.log("now: ", hour, minute, "suncalc: ", sunCalcResult.dawn_hours, sunCalcResult.dawn_minutes); + + if (hour === sunCalcResult.dawn_hours) { + + //NOTE: ak je este pred usvitom, spracujeme report a posleme na cloud, ak uz je po usvite, resetujeme report plnime data noveho dna + if (minute >= sunCalcResult.dawn_minutes - 2) { + emptyReportToSend(); + emptyDailyReport(); + console.log("Podmienka 1 v dailyReport handler"); + } else { + processDailyReport(); + emptyReportToSend(); + emptyDailyReport(); + console.log("Podmienka 2 v dailyReport handler"); + } + + initialReportStatus = true; + + // ak sa funkcia spusti o hodinu alebo 2 neskor, ako je usvit (moze sa to stat, kedze kazde zapnutie/vypnutie linii odznova spusti casovac. + } else if (hour === sunCalcResult.dawn_hours + 1 || hour === sunCalcResult.dawn_hours + 2) { + if (!initialReportStatus) { + emptyReportToSend(); + emptyDailyReport(); + initialReportStatus = true; + console.log("Podmienka 3 v dailyReport handler"); + } else { + processDailyReport(); + initialReportStatus = true; + console.log("Podmienka 4 v dailyReport handler"); + } + } else { + processDailyReport(); + initialReportStatus = false; + console.log("Podmienka 5 v dailyReport handler"); + } + + console.log("initialReportStatus: ", initialReportStatus); + + } + + function emptyReportToSend() { + emptyJsObject(reportToSend); + reportToSend["contactor"] = { off: [], on: [] }; + reportToSend["night_no_data"] = []; + reportToSend["night_dimming=0"] = []; + reportToSend["night_power=0"] = []; + reportToSend["day_24/7_no_data"] = []; + reportToSend["day_24/7_dimming>0"] = []; + reportToSend["day_24/7_power>0"] = []; + console.log(`resetuje sa reportToSend`); + } + + + //NOTE: ked je initialTs stale rovnaky a zistime ze linie su vypnute (relaysData.line.contactor) - zistim, ci je node na tej linii. Vieme, ze ak je linia vypnuta je to v poriadku lebo nie je na 24/7 linii + //ak je na 24/7 linii, reportujeme, ze neprijima data + function emptyDailyReport() { + const ts = Date.now(); + emptyJsObject(dailyReport); + + //NOTE: do dailyReport dame vsetky nody a pravidelne kontrolujeme ci maju data + //ked nastane sumrak/usvit a svetla maju zacat/prestat svietit, dailyReport spravime nanovo: + for (const [key, value] of Object.entries(nodesData)) { + dailyReport[value.node] = { line: value.line, initialTs: ts }; + } + + console.log("dailyReport: ", dailyReport); + } + + + async function runTasks() { + + clearInterval(interval); + + let currentTimestamp = Date.now(); + + //sort tasks based on timestamp + 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) { + instance.send(SEND_TO.debug, "no tasks created"); + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + if (!rsPort.isOpen) { + instance.send(SEND_TO.debug, "!rsPort.isOpen"); + //await rsPort.open(); + //console.log("Cmd-mngr: !rsPort.isOpen"); + } + + let currentTask = tasks[0]; + + if (currentTask.debug) { + //logger.debug("--->task to process", currentTask); + } + + if (currentTask.timestamp <= currentTimestamp) { + let params = { ...tasks[0] }; + + //allow terminal commands + if (SETTINGS.maintenance_mode && params.type !== "cmd-terminal") { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + let type = params.type; + let tbname = params.tbname; + let node = params.address; + let register = params.register; + let line = null; + let itIsNodeCommand; + + if (nodesData[node] !== undefined) { + line = nodesData[node].line; + itIsNodeCommand = true; + } + + if (params.line !== undefined) line = params.line; + + if (params.addMinutesToTimestamp > 0 || params.timePointName) { + tasks[0].timestamp = currentTimestamp + tasks[0].addMinutesToTimestamp * 60000; + } else { + tasks.shift(); + } + + //kontrola nespracovanych profilov nodov + //TODO: co ked niektore nody neprijimaju profily? kazdu hodinu zahltuju "tasks" array + if (type == "process_profiles") { + //na vsetky zapnutych liniach sa spracuju nespracovane profily nodov + loadRelaysData(); + interval = setInterval(runTasks, SHORT_INTERVAL); + return; + } + + //relay + if (type == "relay") { + + const timePointName = params.timePointName; + const value = params.value; + + let date = new Date(); + date.setDate(date.getDate() + 1);//next day + + let sunCalcResult; + if (timePointName) sunCalcResult = calculateDuskDawn(date, params.line); + + + if (timePointName == "dawn") { + tasks[0].timestamp = sunCalcResult.dawn_time; + } + else if (timePointName == "dusk") { + tasks[0].timestamp = sunCalcResult.dusk_time; + } + else if (timePointName == "luxOn") { + tasks[0].timestamp = sunCalcResult.dusk_time + params.dusk_lux_sensor_time_window * 60000; + } + else if (timePointName == "luxOff") { + tasks[0].timestamp = sunCalcResult.dawn_time + params.dawn_lux_sensor_time_window * 60000; + } + else if (timePointName == "profileTimepoint") { + tasks[0].timestamp = currentTimestamp + tasks[0].addMinutesToTimestamp * 60000; + } + + let info = "aplikovany bod profilu"; + let onOrOff = ""; + value == 1 ? onOrOff = "on" : onOrOff = "off"; + + turnLine(onOrOff, params.line, info); + + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + if (!SETTINGS.masterNodeIsResponding) { + //ak neodpoveda, nebudeme vykonavat ziadne commands, okrem cmd-terminal cmd-master + errorHandler.sendMessageToService("Master node is not responding"); + + let stop = true; + + if (type === "cmd-terminal" || type === "cmd-master") stop = false; + if (stop) { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + } + + let contactorStatus = 1; + if (relaysData[line] != undefined) contactorStatus = relaysData[line].contactor; + + if (line === 0 || contactorStatus === 0 || FLOW.deviceStatus.state_of_breaker[line] === "Off") { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + // TODO: -> status offline for rvo if rotary_switch_state is OFF, this is source of errors + // check if rotary_switch_state == "Off" + // state_of_braker: disconnected = true? + + if (!rsPort.isOpen) { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + //RE-CALCULATE VALUES + //set actual time for broadcast + if (register == 87 && params.recipient === 2) { + var d = new Date(); + params.byte1 = d.getHours();//h + params.byte2 = d.getMinutes();//m + } + + //SET DUSK/DAWN FOR BROADCAST + //Time of dusk + if (register == 6 && params.recipient === 2) { + + if (type != "cmd-terminal") { + params.byte1 = sunCalcResult["dusk_hours"];//h + params.byte2 = sunCalcResult["dusk_minutes"];//m + } + } + + //Time of dawn + if (register == 7 && params.recipient === 2) { + if (type != "cmd-terminal") { + params.byte1 = sunCalcResult["dawn_hours"];//h + params.byte2 = sunCalcResult["dawn_minutes"];//m + } + } + //----------------------- + + instance.send(SEND_TO.debug, "address: " + node + " register:" + register + "type: " + type); + + var startTime, endTime; + startTime = new Date(); + + let saveToTb = true; + if (!tbname) saveToTb = false; + + let resp = com_generic(node, params.recipient, params.rw, register, params.name, params.byte1, params.byte2, params.byte3, params.byte4); + let readBytes = 11; + let timeout = 4000; + + + // await keyword is important, otherwise incorrect data is returned! + await writeData(rsPort, resp, readBytes, timeout).then(function(data) { + + //sometimes happens, that status of node changes to OK, NOK even if line was turned off and should be status OFFLINE. To prevent this, we return if line contactor is 0: + if (itIsNodeCommand && line && relaysData[line].contactor !== 1) return; + + 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); + + //ak sa odpoved zacina 0 - je to v poriadku, inak je NOK + let message = result.message; // OK, NOK + let message_type = result.type; + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + console.log("detected response:", result); + logger.debug("Cmd-mngr: writeData done " + message_type + " duration: " + timeDiff + " type: " + params.debug, params, result); + } + } + + let values = {}; + + //CMD FINISHED + if (message == "OK") { + + updateNodeStatus(node, true); + + //write + if (type == "set_node_profile") { + let result = cmdCounterResolve(node); + if (result == 0) { + dbNodes.modify({ processed: true }).where("node", node).make(function(builder) { + builder.callback(function(err, response) { + + sendNotification("Cmd-mngr: process cmd", SETTINGS.rvoTbName, "dimming_profile_was_successfully_received_by_node", { node: node }, "", SEND_TO.tb, instance); + + logger.debug("--> profil úspešne odoslaný na node č. " + node); + nodesData[node].processed = true; + nodeProfileSendFail.delete(node); + }); + }); + } + } + + //parse read response + if (params.rw == 0) { + values = processResponse(register, dataBytes); //read + } + + if (itIsNodeCommand) { + values.comm_status = "OK"; + values.status = "OK"; + nodesData[node].readout = { ...nodesData[node].readout, ...values }; + + + if (SETTINGS.daily_report) { + //TODO: co ak nedostavame odpovede z nodu ? Musime vyreportovat!! + //v dailyReport teda musi byt kompletny zoznam nodov a neustale kontrolovat, ci maju data, ak nie report node - neodpoveda + if (register === 1) { + + let now = Date.now(); + + if (rvo_is_on === true) { + + if ("dimmingIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].dimmingIsOnButShouldBeOffTime; + + if (values.dimming > 0) { + if ("dimmingIsZeroTime" in dailyReport[node]) delete dailyReport[node].dimmingIsZeroTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if (!("dimmingIsZeroTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], dimmingIsZeroTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } else { + + if ("dimmingIsZeroTime" in dailyReport[node]) delete dailyReport[node].dimmingIsZeroTime; + + if (values.dimming > 0) { + if (!("dimmingIsOnButShouldBeOffTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], dimmingIsOnButShouldBeOffTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if ("dimmingIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].dimmingIsOnButShouldBeOffTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } + } + + if (register === 76) { + + let now = Date.now(); + + if (rvo_is_on === true) { + + if ("powerIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].powerIsOnButShouldBeOffTime; + + if (values.power > 1) { + if ("powerIsZeroTime" in dailyReport[node]) delete dailyReport[node].powerIsZeroTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if (!("powerIsZeroTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], powerIsZeroTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } else { + + if ("powerIsZeroTime" in dailyReport[node]) delete dailyReport[node].powerIsZeroTime; + + if (values.power > 1) { + if (!("powerIsOnButShouldBeOffTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], powerIsOnButShouldBeOffTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if ("powerIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].powerIsOnButShouldBeOffTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } + } + } + + } + + //master node + if (node == 0) { + sendNotification("Cmd-mngr: 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; + } + + if (params.debug) { + //logger.debug("saveToTb", saveToTb, tbname, values); + } + + if (saveToTb && type != "node-regular-read") { + sendTelemetry(values, tbname); + } + else { + if (type == "cmd-terminal") { + terminalCommandResponse(params, "SUCCESS", data); + } + } + + } + else { + terminalCommandResponse(params, "ERROR", data); + handleNokResponseOnRsPort("handleNOK else block", params, itIsNodeCommand, saveToTb); + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + //logger.debug("writeData err: ", error, result, params); + logger.debug("writeData err: ", tbname, node, register, values); + } + } + + //logger.debug(error, result, params); + } + }).catch(function(reason) { + + //console.log("writeData catch exception", reason); + instance.send(SEND_TO.debug, reason); + + terminalCommandResponse(params, "FAILURE", null, reason); + handleNokResponseOnRsPort("handleNOK catch block", params, itIsNodeCommand, saveToTb); + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + logger.debug("-->WRITE FAILED: " + reason, params.debug, params); + } + } + + }); + + } + 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); + } + + + // if node does not respond to request, we repeat request 3 times: + function repeatCommand(params) { + params.repeatCounter++; + if (params.repeatCounter < 4) { + params.timestamp = 0; + params.addMinutesToTimestamp = 0; + tasks.push(params); + } + } + + function handleNokResponseOnRsPort(message, params, itIsNodeCommand, saveToTb) { + + let node = params.address; + let register = params.register; + let type = params.type; + let tbName = params.tbname; + if (!tbName) return; + + let values = {}; + + let updateStatus = updateNodeStatus(node, false); + + if (itIsNodeCommand) { + values.comm_status = "NOK"; + nodesData[node].readout.comm_status = "NOK"; + repeatCommand(params); + } + + if (updateStatus) { + values.status = "NOK"; + nodesData[node].readout.status = "NOK"; + } + + if (type === "node-regular-read") return; + + //master node + if (node == 0) { + sendNotification("Cmd-mngr: 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; + + if (register == 4) values["master_node_version"] = "NOK"; + } + + if (type == "set_node_profile") { + delete cmdCounter[node]; + logger.debug("profil nebol úspešne odoslaný na node č. ", params); + + if (!nodeProfileSendFail.has(node)) { + sendNotification("Cmd-mngr: process cmd", tbName, "configuration_of_dimming_profile_to_node_failed", { node: node }, "", SEND_TO.tb, instance); + nodeProfileSendFail.add(node); + } + } + + // console.log("------",node, register, type, itIsNodeCommand, updateStatus, saveToTb, values); + if (saveToTb) { + sendTelemetry(values, tbName); + } + + } + + + function sendNodesData() { + Object.keys(nodesData).forEach(node => { + if (nodesData[node]["status"] !== "OFFLINE") { + sendTelemetry(nodesData[node].readout, nodesData[node].tbname); + nodesData[node].readout = {}; + } + }) + } + + + /** + * 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; + } + + 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); + + //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 === "OFFLINE") { + nodeObj.node_status_before_offline === true ? number_of_ok_luminaires++ : number_of_nok_luminaires++; + } + else if (nodeObj.status == true) 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 - ts % 60000 //round to full minute + }; + + sendTelemetry(values, SETTINGS.rvoTbName, ts); + } + + + function setSunCalcResult() { + //if next day, we get new dusk and dawn. To make sure, in local timezone 2:00 means 00:00 in utc (it means next day) + if (new Date().getHours() === 2) { + sunCalcResult = calculateDuskDawn(); + console.log("Novy suncalc: ", sunCalcResult); + } + } + + + function setRvoPeriod() { + + if (!SETTINGS.daily_report) return; + + const ts = Date.now(); + + previous_rvo_is_on_value = rvo_is_on; + + if (ts < sunCalcResult.dawn_time - 1_800_000) { // nodes should be on (00:00 -> 06:00 ( - pol hodina, lebo rvo vypina skor) + rvo_is_on = true; + } else if (sunCalcResult.dawn_time - 1_800_000 < ts && ts < sunCalcResult.dusk_time + 1_800_000) { // nodes should be off 06:00 -> 21:00 + rvo_is_on = false; + } else if (sunCalcResult.dusk_time + 1_800_000 < ts) { // nodes should be on 21:00 -> 00:00 + rvo_is_on = true; + } + + if (previous_rvo_is_on_value !== rvo_is_on) { + emptyDailyReport(); + console.log("rvo_is: ", rvo_is_on, previous_rvo_is_on_value); + } + } + + + function handleRsPort() { + + if (rsPort) { + rsPort.removeAllListeners(); + rsPort = null; + } + + //! 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-mngr: rsPort opened success"); + + 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); + + }).catch(function(reason) { + instance.send(SEND_TO.debug, "Cmd-mngr: RPC runSyncExec - promise rejected:" + reason); + }); + }); + + rsPort.on('error', function(err) { + errorHandler.sendMessageToService([exports.title, "unable to open port", SETTINGS.serial_port, err.message], 0); + monitor.info("Cmd-mngr: Error on rsPort", err.message); + }); + + rsPort.on("close", () => { + monitor.info("Cmd-mngr: rsPort closed, reconnecting..."); + setTimeout(handleRsPort, 1000); + }); + + rsPort.open(); + } + + + instance.on("close", () => { + clearInterval(interval); + clearInterval(customTasksInterval); + clearInterval(setCorrectTime); + clearInterval(sendNodeReadout); + clearInterval(accelerometerInterval); + rsPort.close(); + }); + + instance.on("0", _ => { + main(); + }) + + + instance.on("2", _ => { + console.log("dailyReport, reportToSend, rvo_is_on", dailyReport, reportToSend, rvo_is_on, previous_rvo_is_on_value); + }) + + instance.on("1", 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(); + return; + } + else if (flowdata.data == "close") { + rsPort.close(); + return; + } + else if (flowdata.data == "clean") { + tasks = []; + return; + } + else if (flowdata.data == "buildtasks") { + //build & run + return; + } + else if (flowdata.data == "run") { + //durations = []; + + if (tasks.length == 0) { + + buildTasks(); + + if (rsPort.isOpen) { + interval = setInterval(runTasks, 100); + } + else { + instance.send(SEND_TO.debug, "port is not opened!!!"); + } + } + } + else { + //terminal data - object + //logger.debug("flowdata", flowdata.data); + + if (typeof flowdata.data === 'object') { + //logger.debug("dido", flowdata.data); + if (flowdata.data.hasOwnProperty("sender")) { + //data from dido_controller + if (flowdata.data.sender == "dido_controller") { + + if (flowdata.data.hasOwnProperty("cmd")) { + let cmd = flowdata.data.cmd; + + if (cmd == "buildTasks") { + clearInterval(interval); + + logger.debug("-->Cmd-mngr: BUILD TASKS"); + buildTasks(); + + //logger.debug("tasks:"); + //logger.debug(tasks); + + logger.debug("-->Cmd-mngr: RUN TASKS"); + interval = setInterval(runTasks, 5000); + } + else if (cmd == "reload_relays") { + loadRelaysData(flowdata.data.line); + + if (flowdata.data.dataChanged) { + if (!flowdata.data.value) { + reportOfflineNodeStatus(flowdata.data.line); + } + else { + reportOnlineNodeStatus(flowdata.data.line); + } + } + + } + else if (cmd == "rotary_switch_state") { + let value = flowdata.data.value; + + //state was changed + if (rotary_switch_state != value) { + if (value == "Off") { + //vyreportovat vsetky svietdla + reportOfflineNodeStatus(); + } + + rotary_switch_state = value; + } + } + 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) { + + // we send lux_sensor value to all nodes: + let params = getParams(PRIORITY_TYPES.node_broadcast); + + params.recipient = 2;//2 broadcast, address = 0 + params.address = 0xffffffff;//Broadcast + + let ba = longToByteArray(lux_sensor); + + params.byte3 = ba[1];//msb + params.byte4 = ba[0]; + params.timestamp = PRIORITY_TYPES.node_broadcast; + params.info = "run broadcast: Actual Lux level from cabinet"; + params.register = 95;//Actual Lux level from cabinet + params.rw = 1;//write + + tasks.push(params); + + //process profiles + turnOnOffLinesAccordingToLuxSensor(lux_sensor); + } + } + else if (cmd == "state_of_breaker") { + //istic linie + + breakerCounter--; + + let value = flowdata.data.value; + let line = parseInt(flowdata.data.line); + + let dataChanged = false; + if (state_of_breaker[line] != value) dataChanged = true; + + state_of_breaker[line] = value; + + let status = "OK"; + if (value == "Off") status = "NOK"; + + if (dataChanged) { + + if (relaysData.hasOwnProperty(line)) { + let tbname = relaysData[line].tbname; + + if (value == "Off") { + sendNotification("Cmd-mngr: onData", tbname, "circuit_breaker_was_turned_off_line", { line: line }, "", SEND_TO.tb, instance, "circuit_breaker"); + if (breakerCounter < 0) reportToSend["contactor"]["off"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + else { + sendNotification("Cmd-mngr: onData", tbname, "circuit_breaker_was_turned_on_line", { line: line }, "", SEND_TO.tb, instance, "circuit_breaker"); + if (breakerCounter < 0) reportToSend["contactor"]["on"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + + //report status liniu + sendTelemetry({ status: status }, tbname) + + //current value + if (value == "Off") reportOfflineNodeStatus(line); //vyreportovat vsetky svietidla na linii + } + + } + } + else { + logger.debug("undefined cmd", cmd); + } + } + } + + return; + } + + //data from worksys + if (flowdata.data.hasOwnProperty("topic")) { + + let data = getNested(flowdata.data, "content", "data"); + + //if we get temperature in senica from senica-prod01 + let temperature = getNested(flowdata.data, "content", "senica_temperature"); + + if (temperature !== undefined) { + temperatureInSenica = temperature; + return; + } + + if (data === undefined) { + console.log("Invalid rpc command came from platform"); + return; + } + + let command = data.params.command; + let method = data.method; + let profile = data.params.payload; + if (profile == undefined) profile = ""; + let entity = data.params.entities[0]; + let entity_type = entity.entity_type; + let tbname = entity.tb_name; + + instance.send(SEND_TO.debug, flowdata.data); + 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") { + + //let command = data.params.command; + let value = data.params.payload.value; + + if (command == "dimming") { + + let nodeWasFound = false; + let keys = Object.keys(nodesData); + + //logger.debug("-----", keys); + + 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); + + value = parseInt(value); + if (value > 0) value = value + 128; + + params.type = "node-onetime-write"; + params.tbname = tbname; + params.address = node; + params.register = 1; + params.recipient = 1; + params.byte4 = value; + params.rw = 1; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'set dimming from platform'; + //params.debug = true; + + //debug(params); + logger.debug("dimming", params); + + tasks.push(params); + + 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); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 1; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read dimming (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + //pridame aj vyreportovanie - vykon + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 76; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read Input Power (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + //pridame aj vyreportovanie - prud svietidla + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 75; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read Input Current (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + //pridame aj vyreportovanie - power faktor - ucinnik + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 77; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read power factor (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + }, 4000); + + nodeWasFound = true; + break; + } + } + + if (!nodeWasFound) { + logger.debug("set dimming from platform", "unable to find tbname", tbname); + } + } + else { + instance.send(SEND_TO.debug, "undefined command " + command); + logger.debug("undefined command", command); + } + + return; + } + 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++) { + let node = keys[i]; + if (tbname == nodesData[node].tbname) { + + 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"); + + //profil úspešne prijatý pre node č. xx + sendNotification("Cmd-mngr", tbname, "dimming_profile_was_processed_for_node", { node: node }, profile, SEND_TO.tb, instance); + + nodesData[node].processed = false; + nodesData[node].profile = profile; + + processNodeProfile(node); + }); + }); + } + } + } + else { + + instance.send(SEND_TO.debug, "unknown method " + method); + logger.debug("unknown method", method); + + return; + } + } + + //nastav profil linie z platformy + 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") { + + 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++) { + let line = keys[i]; + if (tbname == relaysData[line].tbname) { + //zmazeme tasky + 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) { + + //update profile + logger.debug("worksys - update relay profile done:", profile); + instance.send(SEND_TO.debug, "worksys - update relay profile done"); + + relaysData[line].profile = profile; + + loadRelaysData(line) + logger.debug("loadRelaysData DONE for line", line); + + buildTasks({ processLineProfiles: true, line: line }); + + sendNotification("Cmd-mngr: set profile from worksys", tbname, "switching_profile_was_processed_for_line", { line: line }, profile, SEND_TO.tb, instance); + }); + }); + break; + } + } + } + else if (method == "set_command") { + let value = data.params.payload.value; + + 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; + + 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"); + if (line != 0) reportToSend["contactor"]["off"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + else { + turnLine("on", line, "command received from platform"); + if (line != 0) reportToSend["contactor"]["on"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + } + } + else { + instance.send(SEND_TO.debug, "undefined method " + method); + logger.debug("undefined method", method); + } + + return; + } + else { + instance.send(SEND_TO.debug, "UNKNOW entity_type " + entity_type); + logger.debug("UNKNOW entity_type", entity_type); + } + return; + } + + //terminal + if (!rsPort.isOpen) await rsPort.open(); + + let params = flowdata.data.body; + if (params == undefined) { + //logger.debug("Cmd-mngr: flowdata.data.body is undefined"); + return; + } + + params.priority = PRIORITY_TYPES.terminal; + params.type = "cmd-terminal"; + params.tbname = ""; + params.timestamp = PRIORITY_TYPES.terminal; + params.addMinutesToTimestamp = 0;// do not repeat task!!! + params.debug = true; + + let timestamp = Date.now(); + params.refFlowdataKey = timestamp; + //params.refFlowdata = flowdata; + //refFlowdata = flowdata; + + //console.log("flowdata", flowdata); + + cleanUpRefFlowdataObj(); + + refFlowdataObj[timestamp] = flowdata; + + //fix + //params.address = params.adress; + logger.debug("received from terminal", params); + logger.debug("date/time:", new Date()); + logger.debug("tasks length:", tasks.length); + + //tasks = []; + + //add to tasks + tasks.push(params); + + } + } + }) + + + //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) + } + + + /** + * 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; + + RESTBuilder.make(function(builder) { + + if (!builder) return; + + builder.method('GET'); + builder.url('http://192.168.252.2:8004/gettime?projects_id=1'); + + builder.callback(function(err, response, output) { + + 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); + } + + }); + } + + } 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); + + } else { + //console.log("Read-only", stdout); + + 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]: [ + { + "ts": date, + "values": values + } + ] + } + + tbHandler.sendToTb(dataToTb, instance); + } + + + function calculateDuskDawn(date, line, duskOffset = 0, dawnOffset = 0) { + + if (date === undefined) date = new Date(); + + 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); + } + + //if(profile.dawn_lux_sensor == false) + { + if (profile.hasOwnProperty("dawn_astro_clock_offset")) dawn_astro_clock_offset = parseInt(profile.dawn_astro_clock_offset); + } + + } + + } catch (error) { + if (profilestr != "") { + logger.debug(profilestr); + logger.debug(error); + } + } + + 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; + } + + //Dimming, CCT + else if (register == 1) { + let brightness = 0; + let dimming = byte0; + if (dimming > 128) { + //dimming = -128; + brightness = dimming - 128; + } + + //cct + //Ak Byte3 == 1: CCT = (Byte2*256)+Byte1 + let cct; + if (byte3 == 1) cct = byte2 * 256 + byte1; + else cct = bytesToInt(bytes.slice(0, 3)); + + //cct podla auditu + + values["dimming"] = brightness; + return values; + } + + // + else if (register == 4) { + values["master_node_version"] = bytes[1] + "." + bytes[2]; + //logger.debug("FW Version", register, bytes); + } + + //Napätie + else if (register == 74) { + let voltage = (bytesToInt(bytes) * 0.1).toFixed(1); + values["voltage"] = Number(voltage); + } + + //Prúd + else if (register == 75) { + let current = bytesToInt(bytes); + values["current"] = current; + } + + //výkon + else if (register == 76) { + let power = (bytesToInt(bytes) * 0.1).toFixed(2); + values["power"] = Number(power); + } + + //účinník + else if (register == 77) { + let power_factor = Math.cos(bytesToInt(bytes) * 0.1 * (Math.PI / 180)).toFixed(2); + values["power_factor"] = Number(power_factor); + } + + //frekvencia + else if (register == 78) { + let frequency = (bytesToInt(bytes) * 0.1).toFixed(2); + values["frequency"] = Number(frequency); + } + + //energia + else if (register == 79) { + let energy = bytesToInt(bytes); + values["energy"] = energy / 1000; //energia v kWh -> delit 1000 + } + + //doba života + else if (register == 80) { + let lifetime = (bytesToInt(bytes) / 60).toFixed(2); + values["lifetime"] = Number(lifetime); + } + + //nastavenie profilu + else if (register == 8) { + let time_schedule_settings = bytesToInt(bytes); + values["time_schedule_settings"] = time_schedule_settings; + } + + //naklon - nateraz sa z nodu nevycitava! kvoli problemom s accelerometrom a vracanymi hodnotami, posielame temp a x y z vo funkcii accelerometerData() + else if (register == 84) { + values["temperature"] = byte3 >= 128 ? (byte3 - 128) * (-1) : byte3; + values["inclination_x"] = byte2 >= 128 ? (byte2 - 128) * (-1) : byte2; + values["inclination_y"] = byte1 >= 128 ? (byte1 - 128) * (-1) : byte1; + values["inclination_z"] = byte0 >= 128 ? (byte0 - 128) * (-1) : byte0; + } + + //FW verzia nodu + else if (register == 89) { + //formát: "Byte3: Byte2.Byte1 (Byte0)" + values["fw_version"] = byte3 + ":" + byte2 + "." + byte1 + "(" + byte0 + ")"; + } + + else if (register == 87 || register == 6 || register == 7) { + var d = new Date(); + d.setHours(byte3, byte2, 0, 0); + let timestamp = d.getTime(); + + //aktuálny čas + if (register == 87) values["actual_time"] = timestamp; + //čas súmraku + else if (register == 6) values["dusk_time"] = timestamp; + //čas úsvitu + else if (register == 7) values["dawn_time"] = timestamp; + } + + 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; + + } + + + function getObjectByTbValue(object, tbname) { + return object[Object.keys(object).find(key => object[key].tbname === tbname)]; + } + + + function isObject(item) { + return (typeof item === "object" && !Array.isArray(item) && item !== null); + } + + + // we fake data, that should be received from accelerometer, as they are a bit unreliable. (temperature, x,y,z) + function accelerometerData() { + + if (temperatureInSenica === null) return; + + //clone nodesData and relaysData objects + let nodesData_clone = JSON.parse(JSON.stringify(nodesData)); + let relaysData_clone = JSON.parse(JSON.stringify(relaysData)); + + for (const key in relaysData_clone) { + + const lineData = relaysData_clone[key]; + const lineNumber = lineData.line; + const contactor = lineData.contactor; + + if (lineNumber === 0) continue; + + if (contactor === 1) { + + let date = Date.now(); + + Object.keys(nodesData_clone).forEach((node, index) => { + + setTimeout(function() { + + if (nodesData_clone[node].line === lineNumber) { + + // NOTE: if status of luminaire is NOK or OFFLINE, we do not send data; + let status = nodesData_clone[node].status; + if (status === "OFFLINE" || !status) return; + + let x = null; + if (naklony.hasOwnProperty(node)) x = naklony[node].naklon; + if (x === null) x = 0; + + sendTelemetry({ temperature: Math.round(temperatureInSenica + 10 + Math.floor(Math.random() * 3)), inclination_x: x, inclination_y: 0, inclination_z: 0 }, nodesData_clone[node].tbname, date); + } + + }, (index + 1) * 500); + }) + + } + } + } + + +} // end of instance.export + diff --git a/RVO41/flow/code.js b/RVO41/flow/code.js new file mode 100755 index 0000000..63b31bf --- /dev/null +++ b/RVO41/flow/code.js @@ -0,0 +1,90 @@ +exports.id = 'code'; +exports.title = 'Code'; +exports.group = 'Common'; +exports.color = '#656D78'; +exports.input = true; +exports.output = 1; +exports.author = 'Peter Širka'; +exports.icon = 'code'; +exports.version = '1.2.0'; +exports.options = { outputs: 1, code: 'send(0, value);', keepmessage: true }; + +exports.html = `
+
+
+
@(Number of outputs)
+
@(Minimum is 1)
+
+
+
@(Code)
+
@(Keep message instance)
+
+`; + +exports.readme = `# Code + +This component executes custom JavaScript code as it is and it doesn't contain any secure scope. + +\`\`\`javascript +// value {Object} contains received data +// send(outputIndex, newValue) sends a new value +// error(value) sends an error +// instance {Object} a current component instance +// flowdata {Object} a current flowdata +// repository {Object} a current repository of flowdata +// Example: + +// send() can be execute multiple times +send(0, value); +\`\`\``; + +exports.install = function(instance) { + + var fn; + + instance.on('data', function(response) { + if (fn) { + try { + fn(response.data, instance, response, instance.options, response.repository, require); + } catch (e) { + response.data = e; + instance.throw(response); + } + } + }); + + instance.reconfigure = function() { + try { + if (instance.options.code) { + instance.status(''); + var code = 'var send = function(index, value) { if (options.keepmessage) { flowdata.data = value; instance.send2(index, flowdata); } else instance.send2(index, value);}; var error = function(err) { instance.throw(err); }; ' + instance.options.code; + fn = new Function('value', 'instance', 'flowdata', 'options', 'repository', 'require', code); + } else { + instance.status('Not configured', 'red'); + fn = null; + } + } catch (e) { + fn = null; + instance.error('Code: ' + e.message); + } + }; + + instance.on('options', instance.reconfigure); + instance.reconfigure(); +}; \ No newline at end of file diff --git a/RVO41/flow/comment.js b/RVO41/flow/comment.js new file mode 100755 index 0000000..1e0cd13 --- /dev/null +++ b/RVO41/flow/comment.js @@ -0,0 +1,11 @@ +exports.id = 'comment'; +exports.title = 'Comment'; +exports.group = 'Common'; +exports.color = '#704cff'; +exports.author = 'Martin Smola'; +exports.icon = 'comment'; +exports.traffic = false; +exports.version = '1.0.0'; +exports.readme = '# Comment'; + +exports.install = function() {}; diff --git a/RVO41/flow/count.js b/RVO41/flow/count.js new file mode 100755 index 0000000..fa92ee9 --- /dev/null +++ b/RVO41/flow/count.js @@ -0,0 +1,60 @@ +exports.id = 'count'; +exports.title = 'Count'; +exports.version = '1.0.1'; +exports.author = 'John Graves'; +exports.color = '#656D78'; +exports.icon = 'plus-square'; +exports.input = 2; +exports.output = 1; +exports.options = { increment: 1, initialvalue: 1 }; +exports.readme = `# Counter + +Counter Number of times called.`; + +exports.html = `
+
@(Initial Value)
+
@(Increment)
+

Example Video

+
`; + +exports.readme = `# Count + +This component counts the number of messages received. + +__Response:__ + +Integer value based on the initial value and increment settings. + +__Arguments:__ +- Initial Value: What number should be output on the receipt of the first message. +- Increment: What should the increment be for each following message received.`; + +exports.install = function(instance) { + + var count = 0; + var initialCall = true; + + instance.on('data', function(flowdata) { + var index = flowdata.index; + if (index) { + instance.debug('Reset Count.'); + count = instance.options.initialvalue; + initialCall = true; + } else { + // If this is the first time, set the value to 'initial value' + if(initialCall) { + initialCall = false; + count = instance.options.initialvalue; + } else + count = count+instance.options.increment; + instance.status('Count:' + count); + instance.send2(count); + } + }); + + instance.on('options', function() { + count = instance.options.initialvalue; + initialCall = true; + }); + +}; diff --git a/RVO41/flow/db_connector.js b/RVO41/flow/db_connector.js new file mode 100755 index 0000000..65ee94b --- /dev/null +++ b/RVO41/flow/db_connector.js @@ -0,0 +1,286 @@ +exports.id = 'db_connector'; +exports.title = 'DbConnector'; +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.html = `
+
+
+
DbConnector
+
+
+
`; + +exports.readme = `# read/write data to tables`; + +const instanceSendTo = { + debug: 0, + http_response: 1, +} + +const { promisifyBuilder, makeMapFromDbResult } = require('./helper/db_helper.js'); + +function extractWhereParams(params) +{ + let name = params[0]; + let operator = '='; + let value = params[1]; + + if(params.length == 3) + { + operator = params[1]; + value = params[2]; + } + + return {name: name, operator: operator, value: value}; +} + +exports.install = function(instance) { + + let refFlowdata = null;//holds reference to httprequest flowdata + + instance.on("close", () => { + + }) + + + instance.on("data", async function(flowdata) { + + let params = flowdata.data.body; + console.log("DbConnector", params); + + refFlowdata = flowdata; + + if(refFlowdata != undefined) + { + //make http response + let responseObj = {}; + responseObj["type"] = "SUCESS"; + + try{ + + let table = params.table; + let action = params.action; + + + if(params.data != undefined) + { + let className = params.data.className; + + if(className == "SqlQueryBuilder") + { + let type = params.data.type; + + console.log("SqlQueryBuilder---->", params.data); + + if(type == "SELECT") + { + let table = params.data.queryData.tables[0].table; + + const db = TABLE(table); + var builder = db.find(); + + let result = await promisifyBuilder(builder); + + let response = {}; + response["result"] = result; + response["success"] = true; + + responseObj["data"] = response; + + //console.log(responseObj); + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + } + + return; + } + } + + + console.log("db_connector---->", table, action); + + //actions: read, replace, insert, delete, update... + + if(action == "read") + { + const db = TABLE(params.table); + + //where builder.where('age', '<', 15); + //builder.where('id', 3403); + + var builder = db.find(); + + //https://docs.totaljs.com/latest/en.html#api~DatabaseBuilder~builder.where + if(params.hasOwnProperty("where")) + { + //optionalCan contain "=", "<=", "<", ">=", ">". + //Default value: '=' + + //1.["production_line", 1] + //2. ["or", ["production_line", 1], ["production_line", 2], "end"] + + if (Array.isArray(params.where)) { + + let multipleConditions = false; + + if(params.where[0] == "or") multipleConditions = true; + if (Array.isArray(params.where[0])) multipleConditions = true; + + if(multipleConditions) + { + + for(var i = 0; i < params.where.length; i++) + { + const item = params.where[i]; + + if(item === "or") builder.or(); + + if (Array.isArray(item)) + { + const { name, operator, value } = extractWhereParams(item); + builder.where(name, operator, value); + } + + if(item === "end") builder.end(); + + } + + } + else + { + const { name, operator, value } = extractWhereParams(params.where); + builder.where(name, operator, value); + } + + } + + /* + if(params.where.length >=2 ) + { + let name = params.where[0]; + let operator = '='; + let value = params.where[1]; + + if(params.where.length == 3) + { + operator = params.where[1]; + value = params.where[2]; + } + + builder.where(name, operator, value); + } + */ + } + + if(params.hasOwnProperty("between")) + { + builder.between(params.between[0], params.between[1], params.between[2]); + } + + let response = await promisifyBuilder(builder); + responseObj["data"] = response; + + //console.log(responseObj); + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + + return; + } + + if(action == "delete") + { + + } + + + if(action == "update") + { + //! data receiving from terminal (params) + // { + // hostname: 'localhost', + // table: 'settings', + // action: 'update', + // body: { + // rvo_name: 'terrrr', + // lang: 'en', + // temperature_adress: '28.427B45920702', + // latitude: 48.70826502, + // longitude: 17.28455203, + // mqtt_host: '192.168.252.4', + // mqtt_clientid: 'showroom_test_panel_led', + // mqtt_username: 'xmRd6RJxW53WZe4vMFLU', + // mqtt_port: 1883, + // maintanace_mode: false + // } + // } + const tableToModify = TABLE(params.table); + const newValues = params.body; + + tableToModify.modify(newValues).make(function(builder) { + + builder.callback(function(err, response) { + + if(!err) + { + responseObj["data"] = response; + responseObj["tableUpdated"] = true; + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + } + }); + }); + + } + + if(action == "replace") + { + //truncate table + const db = TABLE(params.table); + var builder = db.remove(); + db.clean(); + + //insert data + let data = params.data; + + for(let i = 0; i < data.length; i++) + { + //console.log(data[i]); + db.insert(data[i]); + } + + console.log("insert done"); + + let responseObj = {}; + responseObj["type"] = "SUCESS"; + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + + + } + + + + } catch (error) { + //console.log(error); + responseObj["type"] = "ERROR"; + responseObj["message"] = error; + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + } + } + }) +} + + diff --git a/RVO41/flow/db_init.js b/RVO41/flow/db_init.js new file mode 100755 index 0000000..b399878 --- /dev/null +++ b/RVO41/flow/db_init.js @@ -0,0 +1,113 @@ +exports.id = 'db_init'; +exports.title = 'DB Initialization'; +exports.group = 'Worksys'; +exports.color = '#888600'; +exports.version = '1.0.2'; +exports.icon = 'sign-out'; +exports.output = 2; + +exports.readme = ` + # DB initialization +`; + +const { promisifyBuilder, makeMapFromDbResult } = require('./helper/db_helper.js'); +const { initNotification } = require('./helper/notification_reporter'); +const errorHandler = require('./helper/ErrorToServiceHandler'); +const total_energy = require('../databases/total_energy'); + +const SEND_TO = { + db_init: 0, + infoSender: 1 +}; + + +exports.install = async function(instance) { + const dbNodes = TABLE("nodes"); + const dbRelays = TABLE("relays"); + const dbSettings = TABLE("settings"); + 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 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.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"]; + Object.keys(dbs.nodesData).forEach(node => dbs.nodesData[node].readout = {}) + + let rvo_number = responseSettings[0]["rvo_name"].match(/\D+(\d{1,2})_/)[1]; + + dbs.settings = { + edge_fw_version: "2025-10-08", //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"], + phases: responseSettings[0]["phases"], + cloud_topic: responseSettings[0]["cloud_topic"], + has_main_switch: responseSettings[0]["has_main_switch"], + daily_report: responseSettings[0]["daily_report"], + send_changed_node_numbers: responseSettings[0]["send_changed_node_numbers"], + rvo_number: rvo_number, + + //dynamic values + masterNodeIsResponding: true, //cmd_manager + maintenance_mode: false, + } + + + dbs.settings.energy_to_switch_lamps = total_energy[rvo_number]; + if (dbs.settings.energy_to_switch_lamps === undefined) console.log('=============== db_init.js: energy_to_switch_lamps is undefined'); + + FLOW.dbLoaded = true; + errorHandler.setProjectId(dbs.settings.project_id); + initNotification(); + + //APP START - send to data services + const toService = { + id: dbs.settings.project_id, + name: dbs.settings.rvo_name, + fw_version: dbs.settings.edge_fw_version, + startdate: new Date().toISOString().slice(0, 19).replace('T', ' '), + js_error: "", + error_message: "" + }; + + instance.send(SEND_TO.infoSender, toService); + console.log("----------------> START - message send to service", toService); + + setTimeout(() => { + console.log("DB_INIT - data loaded"); + instance.send(SEND_TO.db_init, "_") + }, 5000) + +}; + diff --git a/RVO41/flow/debug.js b/RVO41/flow/debug.js new file mode 100755 index 0000000..00cb259 --- /dev/null +++ b/RVO41/flow/debug.js @@ -0,0 +1,100 @@ +exports.id = 'debug'; +exports.title = 'Debug'; +exports.author = 'Peter Širka'; +exports.color = '#967ADC'; +exports.click = true; +exports.input = true; +exports.icon = 'bug'; +exports.version = '2.0.4'; +exports.options = { enabled: true, repository: false, type: 'data' }; +exports.readme = `# Debug + +Prints data to the debug tab.`; + +exports.html = `
+
+
+
@(Output type)
+
@(Path to the property (leave empty to show the whole data object))
+
@(A group name)
+
@(Enabled)
+
+
+
`; + +exports.install = function(instance) { + + instance.on('data', function(response) { + if (instance.options.enabled) { + + var opt = instance.options; + var rep = response.repository; + var val = response.data; + var id = response.id; + + switch (instance.options.type){ + case 'both': + var data = {}; + data.repository = rep; + data.data = val instanceof Error ? { error: val.message, stack: val.stack } : val; + instance.debug(safeparse(opt.property ? U.get(data, opt.property) : data), undefined, opt.group, id); + break; + case 'repository': + instance.debug(safeparse(opt.property ? U.get(rep, opt.property) : rep), undefined, opt.group, id); + break; + case 'data': + default: + if (val instanceof Error) + instance.debug({ error: val.message, stack: val.stack }, undefined, opt.group, id); + else + instance.debug(safeparse(opt.property ? U.get(val, opt.property) : val), undefined, opt.group, id); + break; + } + } + }); + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + instance.save(); + }); + + instance.on('options', function() { + instance.custom.status(); + }); + + instance.custom.status = function() { + instance.status(instance.options.enabled ? 'Enabled' : 'Disabled'); + }; + + instance.custom.status(); + + function safeparse(o) { + + if (o instanceof Buffer) + return o; + + if (o === undefined) + return 'undefined'; + + if (o === null) + return 'null'; + + var cache = []; + var str = JSON.stringify(o, function(key, value) { + if (typeof value === 'object' && value !== null) { + if (cache.indexOf(value) !== -1) { + try { + return JSON.parse(JSON.stringify(value)); + } catch (error) { + return; + } + } + cache.push(value); + } + return value; + }); + cache = null; + return JSON.parse(str); + } +}; diff --git a/RVO41/flow/designer.json b/RVO41/flow/designer.json new file mode 100755 index 0000000..580f5a3 --- /dev/null +++ b/RVO41/flow/designer.json @@ -0,0 +1,3102 @@ +{ + "tabs": [ + { + "name": "MAIN PUSH", + "linker": "main-push", + "id": "1612772287426", + "index": 0 + }, + { + "name": "CMD manager", + "linker": "cmd-manager", + "id": "1615551125555", + "index": 1 + }, + { + "name": "Devices", + "linker": "devices", + "id": "1611921777196", + "index": 2 + } + ], + "components": [ + { + "id": "1611951142547", + "component": "debug", + "tab": "1611921777196", + "name": "ERROR", + "x": 598, + "y": 60, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#DA4453", + "notes": "" + }, + { + "id": "1612776786008", + "component": "wsmqttpublish", + "tab": "1612772287426", + "name": "WS MQTT publish", + "x": 281.75, + "y": 174, + "connections": { + "0": [ + { + "index": "0", + "id": "1615551060773" + } + ], + "1": [ + { + "index": "0", + "id": "1618300858252" + }, + { + "index": "0", + "id": "1618558465485" + } + ], + "2": [ + { + "index": "0", + "id": "1634303685503" + } + ], + "3": [ + { + "index": "0", + "id": "1731068754606" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Connected", + "color": "green" + }, + "options": { + "username": "", + "clientid": "", + "port": "1883", + "host": "" + }, + "color": "#888600", + "notes": "" + }, + { + "id": "1612778461252", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "tb-push", + "x": 72.75, + "y": 328, + "connections": { + "0": [ + { + "index": "0", + "id": "1612783322136" + }, + { + "index": "1", + "id": "1612776786008" + }, + { + "index": "0", + "id": "1731068754606" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1612783322136", + "component": "debug", + "tab": "1612772287426", + "name": "to TB", + "x": 283.75, + "y": 324, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615551060773", + "component": "debug", + "tab": "1612772287426", + "name": "errors from MQTT Broker", + "x": 594, + "y": 57, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#DA4453", + "notes": "" + }, + { + "id": "1615563373927", + "component": "debug", + "tab": "1615551125555", + "name": "Debug", + "x": 755, + "y": 155, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#DA4453", + "notes": "" + }, + { + "id": "1615566865233", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "tb-push", + "x": 755, + "y": 248, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1615798582262", + "component": "debug", + "tab": "1615551125555", + "name": "CMD_debug", + "x": 755, + "y": 346, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615802995322", + "component": "debug", + "tab": "1611921777196", + "name": "Debug", + "x": 596.8833312988281, + "y": 566.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Disabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": false + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615809128443", + "component": "debug", + "tab": "1611921777196", + "name": "tempToTb", + "x": 595.8833312988281, + "y": 658.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615809595184", + "component": "virtualwireout", + "tab": "1611921777196", + "name": "tb-push", + "x": 597.8833312988281, + "y": 377.25, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1616165795916", + "component": "httproute", + "tab": "1615551125555", + "name": "POST /terminal", + "x": 135, + "y": 547, + "connections": { + "0": [ + { + "index": "0", + "id": "1684060205000" + }, + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Listening", + "color": "green" + }, + "options": { + "timeout": 10, + "cachepolicy": 0, + "cacheexpire": "5 minutes", + "size": 5, + "url": "/terminal", + "method": "POST", + "name": "", + "flags": [ + "id:1616165795916", + "post", + 10000 + ], + "emptyresponse": false + }, + "color": "#5D9CEC", + "notes": "### Configuration\n\n- __POST /terminal__\n- flags: \n- maximum request data length: __5 kB__\n- empty response: __false__\n- cache policy: __no cache__\n- cache expire: __5 minutes__", + "cloning": false + }, + { + "id": "1616165824813", + "component": "httpresponse", + "tab": "1615551125555", + "name": "HTTP Response", + "x": 753, + "y": 423, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "json" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1617104731852", + "component": "debug", + "tab": "1615551125555", + "name": "DIDO_Debug", + "x": 669, + "y": 1040, + "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": "turnOff line", + "x": 133, + "y": 1161, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "object", + "data": "{line: 3, command: \"turnOff\", force: true}" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1617115013095", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "tb-push", + "x": 669, + "y": 1150, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1617284749681", + "component": "trigger", + "tab": "1615551125555", + "name": "update profile / node", + "x": 112, + "y": 208, + "connections": { + "0": [ + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "data": "profile_nodes", + "datatype": "string" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1618235171399", + "component": "trigger", + "tab": "1615551125555", + "name": "tun tasks", + "x": 184, + "y": 279, + "connections": { + "0": [ + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "data": "run" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1618300858252", + "component": "debug", + "tab": "1612772287426", + "name": "wsmqtt-exit1", + "x": 597.8833312988281, + "y": 149, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1618393583970", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "to-cmd-manager", + "x": 668.8833312988281, + "y": 1269, + "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": 132.88333129882812, + "y": 367, + "connections": { + "0": [ + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "platform-rpc-call", + "color": "gray" + }, + "options": { + "wirename": "platform-rpc-call" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1618393759854", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "cmd_to_dido", + "x": 119.88333129882812, + "y": 1007, + "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": 752.8833312988281, + "y": 527, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "cmd_to_dido", + "color": "gray" + }, + "options": { + "wirename": "cmd_to_dido" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1618558465485", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "platform-rpc-call", + "x": 597.8833312988281, + "y": 247, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "platform-rpc-call", + "color": "gray" + }, + "options": { + "wirename": "platform-rpc-call" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1618572059773", + "component": "trigger", + "tab": "1615551125555", + "name": "turnOn line", + "x": 132, + "y": 1085, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "data": "{line: 1, command: \"turnOn\", force: true}", + "datatype": "object" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1619515097737", + "component": "cmd_manager", + "tab": "1615551125555", + "name": "CMD Manager", + "x": 452.1091003417969, + "y": 341.05455017089844, + "connections": { + "0": [ + { + "index": "0", + "id": "1615563373927" + } + ], + "1": [ + { + "index": "0", + "id": "1615566865233" + }, + { + "index": "0", + "id": "1615798582262" + } + ], + "2": [ + { + "index": "0", + "id": "1616165824813" + } + ], + "3": [ + { + "index": "0", + "id": "1618393827655" + } + ], + "4": [ + { + "index": "0", + "id": "1635936391935" + } + ], + "5": [ + { + "index": "0", + "id": "1757006030239" + }, + { + "index": "0", + "id": "1757006060377" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1619605019281", + "component": "httproute", + "tab": "1615551125555", + "name": "GET db", + "x": 173, + "y": 653, + "connections": { + "0": [ + { + "index": "0", + "id": "1684060205000" + }, + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Listening", + "color": "green" + }, + "options": { + "timeout": 5, + "cachepolicy": 0, + "cacheexpire": "5 minutes", + "size": 5, + "url": "/db", + "method": "GET", + "name": "", + "flags": [ + "id:1619605019281", + "get", + 5000 + ] + }, + "color": "#5D9CEC", + "notes": "### Configuration\n\n- __GET /db__\n- flags: undefined\n- maximum request data length: __5 kB__\n- empty response: __undefined__\n- cache policy: __no cache__\n- cache expire: __5 minutes__", + "cloning": false + }, + { + "id": "1619784672383", + "component": "trigger", + "tab": "1615551125555", + "name": "turnOnAlarm", + "x": 120, + "y": 1234, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "object", + "data": "{command: \"turnOnAlarm\"}" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1619784812964", + "component": "trigger", + "tab": "1615551125555", + "name": "turnOffAlarm", + "x": 118, + "y": 1307, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "object", + "data": "{command: \"turnOffAlarm\"}" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1621340721628", + "component": "virtualwireout", + "tab": "1611921777196", + "name": "modbus_to_dido", + "x": 599, + "y": 471, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "modbus_to_dido", + "color": "gray" + }, + "options": { + "wirename": "modbus_to_dido" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1622640022885", + "component": "httproute", + "tab": "1615551125555", + "name": "POST /db_connector", + "x": 98, + "y": 1586, + "connections": { + "0": [ + { + "index": "0", + "id": "1622640073521" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Listening", + "color": "green" + }, + "options": { + "timeout": 5, + "cachepolicy": 0, + "cacheexpire": "5 minutes", + "size": 5, + "url": "/db_connector", + "method": "POST", + "flags": [ + "id:1622640022885", + "post", + 5000 + ] + }, + "color": "#5D9CEC", + "notes": "### Configuration\n\n- __POST /db_connector__\n- flags: \n- maximum request data length: __5 kB__\n- empty response: __undefined__\n- cache policy: __no cache__\n- cache expire: __5 minutes__", + "cloning": false + }, + { + "id": "1622640073521", + "component": "db_connector", + "tab": "1615551125555", + "name": "DbConnector", + "x": 372, + "y": 1572, + "connections": { + "1": [ + { + "index": "0", + "id": "1622641420685" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "edge": "undefined" + }, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1622641420685", + "component": "httpresponse", + "tab": "1615551125555", + "name": "HTTP Response", + "x": 596, + "y": 1586, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1634303504177", + "component": "monitormemory", + "tab": "1612772287426", + "name": "RAM", + "x": 69.88333129882812, + "y": 888.5, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465281992" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "858.88 MB / 985.68 MB", + "color": "gray" + }, + "options": { + "enabled": true, + "interval": 30000 + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1634303533779", + "component": "monitordisk", + "tab": "1612772287426", + "name": "disk", + "x": 70.88333129882812, + "y": 982.5, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465821120" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "5.78 GB / 7.26 GB", + "color": "gray" + }, + "options": { + "enabled": true, + "path": "/", + "interval": 30000 + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1634303595494", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "send-to-services", + "x": 51.883331298828125, + "y": 1400.5, + "connections": { + "0": [ + { + "index": "0", + "id": "1634463186563" + }, + { + "index": "1", + "id": "1634488120710" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1634303602169", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "send-to-services", + "x": 426.8833312988281, + "y": 878.5, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1634303685503", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "send-to-services", + "x": 600.8833312988281, + "y": 341.5, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1634303743260", + "component": "httprequest", + "tab": "1612772287426", + "name": "192.168.252.2:8004/sentmessage", + "reference": "", + "x": 506.8833312988281, + "y": 1331.7333374023438, + "connections": { + "0": [ + { + "index": "0", + "id": "1635327431236" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "url": "http://192.168.252.2:8004/sentmessage", + "method": "POST", + "stringify": "json" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1634463186563", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 305.75, + "y": 1442, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634464580289", + "component": "code", + "tab": "1612772287426", + "name": "Code", + "x": 245, + "y": 787, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465243324" + }, + { + "index": "0", + "id": "1634303602169" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "keepmessage": true, + "code": "let response = {};\nresponse.cpu = value.cpu;\nresponse.uptime = value.uptime;\n\nsend(0, response);", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1634465243324", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 428, + "y": 784, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634465281992", + "component": "code", + "tab": "1612772287426", + "name": "Code", + "x": 245, + "y": 884, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465338103" + }, + { + "index": "0", + "id": "1634303602169" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "keepmessage": true, + "code": "value.sender = \"ram\";\n\nlet response = {};\n\nresponse.memory_total = Math.round(value.total / (1024 ** 2));\nresponse.memory_free = Math.round(value.free / (1024 ** 2));\nresponse.memory_used = Math.round(value.used / (1024 ** 2));\n\nsend(0, response);", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1634465338103", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 429, + "y": 976, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634465821120", + "component": "code", + "tab": "1612772287426", + "name": "Code", + "x": 245, + "y": 978, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465892500" + }, + { + "index": "0", + "id": "1634303602169" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "keepmessage": true, + "code": "value.sender = \"hdd\";\n\nlet response = {};\n\nresponse.hdd_total = Math.round(value.total / (1024 ** 2));\nresponse.hdd_free = Math.round(value.free / (1024 ** 2));\nresponse.hdd_used = Math.round(value.used / (1024 ** 2));\n\nsend(0, response);", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1634465892500", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 432, + "y": 1068, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634484067516", + "component": "debug", + "tab": "1612772287426", + "name": "Send info", + "x": 513, + "y": 1441, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634488120710", + "component": "infosender", + "tab": "1612772287426", + "name": "Info sender", + "x": 301, + "y": 1336, + "connections": { + "0": [ + { + "index": "0", + "id": "1634484067516" + }, + { + "index": "0", + "id": "1634303743260" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "edge": "undefined" + }, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1635327431236", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 837.8833312988281, + "y": 1325.5, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1635936391935", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "send-to-services", + "x": 753, + "y": 623, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1637069803394", + "component": "monitorconsumption", + "tab": "1612772287426", + "name": "CPU", + "x": 69, + "y": 791, + "connections": { + "0": [ + { + "index": "0", + "id": "1634464580289" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "49.2% / 69.91 MB", + "color": "gray" + }, + "options": { + "monitorfiles": true, + "monitorconnections": true, + "monitorsize": true, + "monitorconsumption": true, + "enabled": true, + "interval": 30000 + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1683664161036", + "component": "debug", + "tab": "1615551125555", + "name": "CMDtoDIDO", + "x": 392, + "y": 1012, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1683981346282", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "from-dido-controller", + "x": 112, + "y": 459, + "connections": { + "0": [ + { + "index": "0", + "id": "1684055037116" + }, + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "from-dido-controller", + "color": "gray" + }, + "options": { + "wirename": "from-dido-controller" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1684055037116", + "component": "debug", + "tab": "1615551125555", + "name": "from dido to cmd", + "x": 451, + "y": 532, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1684060205000", + "component": "debug", + "tab": "1615551125555", + "name": "HTTP routes", + "x": 450, + "y": 639, + "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": "MDBToDido", + "x": 598, + "y": 147, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1699963668903", + "component": "dido_controller", + "tab": "1615551125555", + "name": "DIDO_Controller", + "x": 397, + "y": 1131, + "connections": { + "0": [ + { + "index": "0", + "id": "1617104731852" + } + ], + "1": [ + { + "index": "0", + "id": "1617104731852" + }, + { + "index": "0", + "id": "1617115013095" + } + ], + "2": [ + { + "index": "0", + "id": "1618393583970" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "edge": "undefined" + }, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1699964678894", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "modbus_to_dido", + "x": 96, + "y": 924, + "connections": { + "0": [ + { + "index": "0", + "id": "1699963668903" + }, + { + "index": "0", + "id": "1699964793925" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "modbus_to_dido", + "color": "gray" + }, + "options": { + "wirename": "modbus_to_dido" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1699964793925", + "component": "debug", + "tab": "1615551125555", + "name": "modbusToDido", + "x": 388, + "y": 920, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1699965957410", + "component": "modbus_reader", + "tab": "1611921777196", + "name": "Modbus reader", + "x": 232, + "y": 175, + "connections": { + "0": [ + { + "index": "0", + "id": "1611951142547" + } + ], + "1": [ + { + "index": "0", + "id": "1621340721628" + }, + { + "index": "0", + "id": "1684179110403" + }, + { + "index": "0", + "id": "1717441414646" + } + ], + "2": [ + { + "index": "0", + "id": "1615809595184" + }, + { + "index": "0", + "id": "1714752862828" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1700411878636", + "component": "thermometer", + "tab": "1611921777196", + "name": "Thermometer", + "x": 234.75, + "y": 444, + "connections": { + "0": [ + { + "index": "0", + "id": "1615802995322" + } + ], + "1": [ + { + "index": "0", + "id": "1615809595184" + }, + { + "index": "0", + "id": "1615809128443" + } + ], + "2": [ + { + "index": "0", + "id": "1621340721628" + }, + { + "index": "0", + "id": "1732889185927" + }, + { + "index": "0", + "id": "1717441414646" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#5CB36D", + "notes": "" + }, + { + "id": "1714752862828", + "component": "debug", + "tab": "1611921777196", + "name": "MDBToTb", + "x": 766, + "y": 324, + "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": 764.0833282470703, + "y": 222, + "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\telse if(value.status === \"NOK-thermometer\")\n\t{\n\t\tsend(0, {\"thermometer\": \"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\telse if(value.values.hasOwnProperty(\"temperature\"))\n\t{\n\t\tsend(0, {\"thermometer\": \"OK\"});\n\t}\n}", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1717442627834", + "component": "debug", + "tab": "1611921777196", + "name": "modbus service", + "x": 966.0833282470703, + "y": 165, + "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": 968.0833282470703, + "y": 268, + "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": 88.75, + "y": 1685, + "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": 296, + "y": 1671, + "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\", \"Flow has been restarted\", \"Node db has changed\"]", + "types": "[\"emergency\", \"critical\", \"error\", \"alert\"]", + "name": "" + }, + "color": "#30E193", + "notes": "" + }, + { + "id": "1718016073501", + "component": "httprequest", + "tab": "1612772287426", + "name": "http://192.168.252.2:8004/slack", + "x": 495, + "y": 1753, + "connections": { + "0": [ + { + "index": "0", + "id": "1718016086212" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "url": "http://192.168.252.2:8004/slack", + "method": "POST", + "stringify": "json" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1718016086212", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 832, + "y": 1664, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "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": 87, + "y": 1591, + "connections": { + "0": [ + { + "index": "0", + "id": "1718016052341" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "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\": \"\" } } } ] }", + "datatype": "object" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1729855334955", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "platform-rpc-call", + "x": 599.9333343505859, + "y": 541.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "platform-rpc-call", + "color": "gray" + }, + "options": { + "wirename": "platform-rpc-call" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1729855371093", + "component": "debug", + "tab": "1612772287426", + "name": "rpc cloud", + "x": 601.9333343505859, + "y": 440.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1731068658334", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 75.75, + "y": 184, + "connections": { + "0": [ + { + "index": "0", + "id": "1612776786008" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731068754606", + "component": "cloudmqttconnect", + "tab": "1612772287426", + "name": "MQTT to senica-prod01", + "x": 284.75, + "y": 452, + "connections": { + "1": [ + { + "index": "0", + "id": "1729855371093" + }, + { + "index": "0", + "id": "1729855334955" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Connected", + "color": "green" + }, + "options": { + "username": "", + "clientid": "", + "port": "2764", + "host": "192.168.252.2", + "topic": "" + }, + "color": "#888600", + "notes": "" + }, + { + "id": "1731069001548", + "component": "db_init", + "tab": "1612772287426", + "name": "DB Initialization", + "x": 1003.75, + "y": 240.25, + "connections": { + "0": [ + { + "index": "0", + "id": "1731069033416" + } + ], + "1": [ + { + "index": "0", + "id": "1747561603739" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#888600", + "notes": "" + }, + { + "id": "1731069033416", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "db-init", + "x": 1244.75, + "y": 233.25, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069059135", + "component": "showdb", + "tab": "1612772287426", + "name": "Show db data", + "x": 1186.75, + "y": 821.25, + "connections": { + "0": [ + { + "index": "0", + "id": "1731069079243" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#888600", + "notes": "" + }, + { + "id": "1731069079243", + "component": "debug", + "tab": "1612772287426", + "name": "dbData", + "x": 1390.75, + "y": 870.25, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1731069116691", + "component": "trigger", + "tab": "1612772287426", + "name": "settings", + "x": 934.75, + "y": 669.75, + "connections": { + "0": [ + { + "index": "0", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069131637", + "component": "trigger", + "tab": "1612772287426", + "name": "relaysData", + "x": 876.75, + "y": 733.75, + "connections": { + "0": [ + { + "index": "1", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069137374", + "component": "trigger", + "tab": "1612772287426", + "name": "nodesData", + "x": 852.75, + "y": 794.75, + "connections": { + "0": [ + { + "index": "2", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069179846", + "component": "trigger", + "tab": "1612772287426", + "name": "pinsData", + "x": 850.75, + "y": 861.75, + "connections": { + "0": [ + { + "index": "3", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069192937", + "component": "trigger", + "tab": "1612772287426", + "name": "sample data", + "x": 857.75, + "y": 928.75, + "connections": { + "0": [ + { + "index": "4", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069264443", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 63.75, + "y": 1279, + "connections": { + "0": [ + { + "index": "0", + "id": "1634488120710" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069334626", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "db-init", + "x": 172.88333129882812, + "y": 129, + "connections": { + "0": [ + { + "index": "0", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069548145", + "component": "virtualwirein", + "tab": "1611921777196", + "name": "db-init", + "x": 46.75, + "y": 192, + "connections": { + "0": [ + { + "index": "0", + "id": "1699965957410" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069567152", + "component": "virtualwirein", + "tab": "1611921777196", + "name": "db-init", + "x": 44.75, + "y": 465, + "connections": { + "0": [ + { + "index": "0", + "id": "1700411878636" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731070156936", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "db-init", + "x": 126.88333129882812, + "y": 1377, + "connections": { + "0": [ + { + "index": "2", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731234189516", + "component": "trigger", + "tab": "1612772287426", + "name": "monitor.txt", + "x": 882.75, + "y": 991.75, + "connections": { + "0": [ + { + "index": "5", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731234189551", + "component": "trigger", + "tab": "1612772287426", + "name": "err.txt", + "x": 904.75, + "y": 1053.75, + "connections": { + "0": [ + { + "index": "6", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1732700042559", + "component": "nodesdb_change_check", + "tab": "1612772287426", + "name": "Nodes DB change check", + "x": 266.8833312988281, + "y": 1980.2333984375, + "connections": { + "0": [ + { + "index": "0", + "id": "1732700071298" + }, + { + "index": "0", + "id": "1732700642917" + } + ], + "1": [ + { + "index": "0", + "id": "1759958914348" + }, + { + "index": "0", + "id": "1759959003114" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#888600", + "notes": "" + }, + { + "id": "1732700057052", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 76.75, + "y": 1988, + "connections": { + "0": [ + { + "index": "0", + "id": "1732700042559" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1732700071298", + "component": "debug", + "tab": "1612772287426", + "name": "nodesChange", + "x": 571.8833312988281, + "y": 2018.2333984375, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1732700642917", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "tb-push", + "x": 567.8833312988281, + "y": 1933, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1732889185927", + "component": "debug", + "tab": "1611921777196", + "name": "tempToDido", + "x": 594.8833312988281, + "y": 753, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1733574412965", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 72.75, + "y": 474, + "connections": { + "0": [ + { + "index": "1", + "id": "1731068754606" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1747561603739", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "send-to-services", + "x": 1243.8833312988281, + "y": 334.5, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1747562867845", + "component": "comment", + "tab": "1612772287426", + "name": "FLOW STARTING POINT", + "x": 1003.5666656494141, + "y": 178, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#704cff", + "notes": "" + }, + { + "id": "1749211698385", + "component": "trigger", + "tab": "1612772287426", + "name": "deviceStatus", + "x": 911.75, + "y": 1116.75, + "connections": { + "0": [ + { + "index": "7", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1757006030239", + "component": "httprequest", + "tab": "1615551125555", + "name": "192.168.252.2:8015/daily_report", + "x": 756.5666656494141, + "y": 715.4499969482422, + "connections": { + "0": [ + { + "index": "0", + "id": "1757006045804" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "stringify": "json", + "method": "POST", + "url": "http://192.168.252.2:8015/daily_report" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1757006045804", + "component": "debug", + "tab": "1615551125555", + "name": "ddd", + "x": 1091.566665649414, + "y": 711.4499969482422, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1757006060377", + "component": "debug", + "tab": "1615551125555", + "name": "reportDebug", + "x": 749.5666656494141, + "y": 799.4499969482422, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1759958914348", + "component": "httprequest", + "tab": "1612772287426", + "name": "http://192.168.252.2:8015/node_numbers", + "x": 571, + "y": 2111, + "connections": { + "0": [ + { + "index": "0", + "id": "1759958927094" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "stringify": "json", + "method": "POST", + "url": "http://192.168.252.2:8015/node_numbers" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1759958927094", + "component": "debug", + "tab": "1612772287426", + "name": "nodesChangeCloud", + "x": 951.8833312988281, + "y": 2109.2333984375, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1759959003114", + "component": "debug", + "tab": "1612772287426", + "name": "nodeChangeCloud1", + "x": 574, + "y": 2218, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1760020290879", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 84.75, + "y": 1787, + "connections": { + "0": [ + { + "index": "1", + "id": "1718016052341" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + } + ], + "version": 615 +} diff --git a/RVO41/flow/dido_controller.js b/RVO41/flow/dido_controller.js new file mode 100755 index 0000000..d16fb19 --- /dev/null +++ b/RVO41/flow/dido_controller.js @@ -0,0 +1,1486 @@ +exports.id = 'dido_controller'; +exports.title = 'DIDO_Controller'; +exports.version = '2.0.0'; +exports.group = 'Worksys'; +exports.color = '#2134B0'; +exports.input = 3; +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 + +state_of_main_switch - reportovat stav hlaveho istica : 0-> off 1-> on +rotary_switch_state - sem by sa mal reportovat stav vstupov manual a auto pola nasledovnej logiky: Manual = 1 a Auto = 0 -> Manu +Manual = 0 a Auto = 0 -> Off, Manual = 0 a Auto = 1 -> Automatic + +door_condition - pin 6, dverový kontakt -> 1 -> vyreportuje Closed, 0 -> vyreportuje Ope +twilight_sensor - hodnotu, ktoru vracia ten analogovy vstup (17) treba poslat sem ako float number. Zrejme tu potom pridame nejaky koeficient prevodu na luxy + +Na kazdu liniu +state_of_breaker - podla indexu istica sa reportuje jeho stav, teda istic na liniu 1: 0-> off, 1-> on +state_of_contactor - podla indexu stkaca sa reportuje jeho stav, teda stykac 1 na liniu 1: 0-> off, 1-> on +*/ + +const { errLogger, logger, monitor } = require('./helper/logger'); +const SerialPort = require('serialport'); +const WebSocket = require('ws'); +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 errorHandler = require('./helper/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 hasMainSwitch; + +let alarmStatus = "OFF"; + +const SEND_TO = { + debug: 0, + tb: 1, + cmd_manager: 2 +} + + +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 = {}; + let rsPortReceivedData = []; + + //to be able to get proper twilight values + let twilight_sensor_interval = 5;//minutes + let twilight_sensor = []; + const twilight_sensor_array = []; + let twilightError = false; + + monitor.info("DIDO_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-we make it global to see it from outside + FLOW.deviceStatus = { //key is device name: temperature,.... + "state_of_main_switch": "Off", //Hlavny istic (alebo druhy dverovy kontakt) + "rotary_switch_state": "Off", //Prevadzkovy + "door_condition": "closed", //Dverový kontakt + "em": "OK", //elektromer rvo + "temperature": "OK", //templomer + "battery": "OK", //Bateria + "power_supply": "OK", //Zdroj + "master_node": "OK", //MN - GLOBALS.settings.masterNodeIsResponding + "no_voltage": "OK", //GLOBALS.settings.no_voltage - vypadok napatia na faze + "state_of_breaker": {}, //"Off",//Istic + "state_of_contactor": {}, //"Off",//Stykac + "twilight_sensor": "OK" //lux sensor + }; + let deviceStatus = FLOW.deviceStatus; + + + function main() { + + GLOBALS = FLOW.GLOBALS; + SETTINGS = FLOW.GLOBALS.settings; + rvoTbName = SETTINGS.rvoTbName; + pinsData = GLOBALS.pinsData; + relaysData = GLOBALS.relaysData; + + tbHandler = new DataToTbHandler(SEND_TO.tb); + tbHandler.setSender(exports.title); + + controller_type = SETTINGS.controller_type; //"lm" or "unipi" + hasMainSwitch = SETTINGS.has_main_switch; + + if (controller_type == "") controller_type = "lm"; + + 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, "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; + } + } + + //report RVO version relaysData[0].tbname; + let values = {}; + values["edge_fw_version"] = SETTINGS.edge_fw_version; + values["maintenance_mode"] = SETTINGS.maintenance_mode; + + sendTelemetry(values, rvoTbName); + + 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); + } + + + function handleRsPort() { + + if (rsPort) { + rsPort.removeAllListeners(); + rsPort = null; + } + + //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('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) { + if (!err) { + monitor.info(exports.title + "--->Digital in_out has been set (runSyncExec was sucessfull)"); + + turnAlarm("off"); + 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('error', err => { + let message = "Dido: rsPort error: " + err.message; + logger.debug(message); + monitor.info(message); + errorHandler.sendMessageToService(message); + }) + + rsPort.on("close", () => { + let message = "Dido: rsPort closed - reconnecting ..."; + logger.debug(message); + monitor.info(message); + setTimeout(handleRsPort, 1000); + }) + + rsPort.open(); + } + + + function handleWebSocket() { + + if (ws) { + ws.removeAllListeners(); + ws = null; + } + + //to keep websocket opened, we send request every 150 seconds + let startRequests = null; + + console.log("handleWebSocket function called"); + ws = new WebSocket('ws:/0.0.0.0:1234/ws'); + + ws.onopen = function open() { + + instance.send(0, exports.title + " running"); + turnAlarm("off"); + + initialSetting(); + + setTimeout(function() { ws.send(JSON.stringify({ cmd: "all" })) }, 5000); + // we request dev info about neuron device from evok to keep websocket connection alive + // for some reason this request returns no data, but connection keeps alive + startRequests = setInterval(() => { + ws.send(JSON.stringify({ "cmd": "filter", "dev": ["neuron"] })); + }, 150000) + }; + + + // 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 = async 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; + + 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 => { + logger.debug('Dido: websocket error', err); + }) + + ws.onclose = function() { + logger.debug('Dido: websocket onclose, reconnecting...') + clearInterval(startRequests); + setTimeout(handleWebSocket, 1000); + } + } + + 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 turnAlarm(onOrOff) { + let value = 0; + if (onOrOff == "on") value = 1; + + if (value == 1 && SETTINGS.maintenance_mode) return; + + alarmStatus = "OFF"; + if (value == 1) alarmStatus = "ON"; + + if (rsPort) { + let arr = [0x55]; + arr.push(13); + arr.push(0); + arr.push(value); + + rsPort.write(Buffer.from(arr), function(err) { + logger.debug(`sirena - ${onOrOff}`); + }); + } + else if (ws) { + let cmd = { "cmd": "set", "dev": "relay", "circuit": "1_01", "value": value }; + ws.send(JSON.stringify(cmd)); + logger.debug(`sirena - ${onOrOff}`); + } + } + + + 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") { + bits.push(0); + } + else bits.push(1); + + if (deviceStatus["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); + } + + + // turn line on or off + function turnLine(onOrOff, line, pin, force, info) { + //onOrOff => "on" or "off" + let value = 0; + if (onOrOff == "on") value = 1; + + if (force == undefined) force = false; + + if (line == 0) { + if (value == 1 && alarmStatus == "ON") turnAlarm("off"); + SETTINGS.maintenance_mode = value ? true : false; + + 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); + return; + } + + if (pin === undefined) pin = getPin(line); + + if (pin === undefined) { + errLogger.error("pin is undefined!", line); + return; + } + + if (!force) { + if (relaysData[line].contactor == value) { + instance.send(SEND_TO.debug, `line is already ${onOrOff} ` + line); + logger.debug(`Dido: turnLine: line is already ${onOrOff} `, line); + return; + } + } + + // if(!rsPort.isOpen && !ws) + if (!rsPort && !ws) { + errLogger.error("Dido - port or websocket is not opened"); + return; + } + + if (rsPort) { + let arr = [0x55]; + arr.push(pin); + arr.push(0); + arr.push(value); + + rsPort.write(Buffer.from(arr), function(err) { + if (err === undefined) { + monitor.info(`Dido: turnLine ${onOrOff} zapisal do rsPort-u`, line, pin, arr, info); + switchLogic(arr); + } + else { + monitor.info(`Dido: turnLine ${onOrOff} WRITE error`, err); + } + }); + + } + else if (ws) { + //pin = "relay1_03" or "input1_01" ... we must make just "1_01" with slice method + monitor.info(`Dido: turnLine ${onOrOff} - (line, pin, force)`, line, pin, force, info); + let cmd = { "cmd": "set", "dev": "relay", "circuit": pin.slice(5), "value": value }; + ws.send(JSON.stringify(cmd)); + } + + //if rvo is 24/7, it has just one switching profile point at 13:00. we do not want to send notification as it repeats every day. + //const d = new Date(); + //if(d.getHours() != 13) sendNotification("Dido_controller: ", SETTINGS.rvoTbName, "switching_profile_point_applied_to_line", { line: line, value: onOrOff }, "", SEND_TO.tb, instance); + } + + + // 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; + + // 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) { + const status = flowdata.data.status; + if (status == "NOK-twilight_sensor") { + deviceStatus["twilight_sensor"] = "NOK"; + } + else if (status == "NOK-em340" || status == "NOK-em111") { + deviceStatus["em"] = "NOK"; + } + else if (status == "NOK-thermometer") { + deviceStatus["temperature"] = "NOK"; + } + } + else if ("values" in flowdata.data) { + 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" + } + else if (values.hasOwnProperty("temperature")) { + deviceStatus["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"; + } + + sendTelemetry(values, rvoTbName); + } + + sendRvoStatus(); + }) + + + + + // we expect array as flowdata.data + instance.on("1", flowdata => { + + //console.log(flowdata.data); + + if (!flowdata.data instanceof Object) return; + + let obj = flowdata.data; + let line = obj.line; + 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"); + }) + + + function calculateStateCode() { + + let bits = []; + + //Hlavny istic - state_of_main_switch => v rvo senica je to druhy door pre silovu cast (EM) + if (deviceStatus["state_of_main_switch"] === "closed" || deviceStatus["state_of_main_switch"] === "Off") { + bits.push(0); + } + else { + bits.push(1); + } + + //Prevadzkovy mod - Manual, Off, Automatic, maintenance_mode = true/false // DAVA 2 BITY + if (!SETTINGS.maintenance_mode) { + if (deviceStatus["rotary_switch_state"] === "Manual") { + bits.push(0); + bits.push(1); + } + + if (deviceStatus["rotary_switch_state"] === "Automatic") { + bits.push(0); + bits.push(0); + } + + if (deviceStatus["rotary_switch_state"] === "Off") { + bits.push(1); + bits.push(0); + } + } + else { + bits.push(1); + bits.push(1); + } + + //Dverovy kontakt + if (deviceStatus["door_condition"] === "closed") { + bits.push(0); + } + else { + bits.push(1); + } + + //EM + if (deviceStatus["em"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //Teplomer + if (deviceStatus["temperature"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //Batéria + if (deviceStatus["battery"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //Zdroj + if (deviceStatus["power_supply"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //MN + if (deviceStatus["master_node"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //výpadok napätia na fáze + if (deviceStatus["no_voltage"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + if (deviceStatus["twilight_sensor"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + // doplnime do 16 bitov (2 byty) + for (let i = bits.length; i < 16; i++) { + bits.push(0); + } + + // console.log("calculateStateCode - deviceStatus", deviceStatus); + // 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; + } + + + async function sendRvoStatus() { + + if (SETTINGS === undefined) return; + SETTINGS.masterNodeIsResponding ? deviceStatus["master_node"] = "OK" : deviceStatus["master_node"] = "NOK"; + + 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 pinsForRvoStatus(controllerType, hasMainSwitch) { + + let pins = []; + + if (controllerType === "lm") { + pins = [1, 4, 6]; + if (hasMainSwitch === 1) { + pins = [4, 6]; + } + } else if (controllerType === "unipi") { + pins = ["input1_01", "input1_04", "input1_05"]; + if (hasMainSwitch === 1) { + pins = ["input1_01", "input1_04"]; + } + } + + return pins; + } + + + function checkRvoStatus() { + + // 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 + //set RVO state + let status = "OK"; + + for (const [key, value] of Object.entries(deviceStatus)) { + if (["em", "twilight_sensor", "temperature", "master_node"].includes(key) && value === "NOK") status = "NOK"; + } + + if (status === "OK") { + + let pinIndexes = pinsForRvoStatus(controller_type, hasMainSwitch); + + for (const pinIndex of pinIndexes) { + if (previousValues[pinIndex] === 0) { + if ((pinIndex === 6 || pinIndex === 'input1_01' || pinIndex === 'input1_05') && SETTINGS.maintenance_mode) continue; + status = "NOK"; + break; + } + } + } + + // battery status. If value is 1 - battery is NOK + if (previousValues[5] === 1) status = "NOK"; + if (SETTINGS.no_voltage.size > 0) status = "NOK"; + + // console.log("rvo status",status) + return status; + } + + + // we pass array to function in case of rsPort ==> switchLogic([55,3,0,1]) ==> [[55,3,0,1]] + // we pass two values in case of websocket ==> switchLogic("relay1_03",1) ==> ["relay1_03",1] + const switchLogic = (...args) => { + + let values = {}; + let pinIndex, newPinValue, twilight; + + //data from rsPort + if (args.length == 1) { + pinIndex = args[0][1] + 1; + if (pinIndex === 17) pinIndex--; + newPinValue = args[0][3]; + twilight = args[0][2]; + } + //data from websocket + else { + pinIndex = args[0]; + newPinValue = args[1]; + } + + 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; + + //default value + let value = "On"; + if (newPinValue === 0) value = "Off"; + + //Hlavny istic + if (type === "state_of_main_switch" && hasMainSwitch) { + if (newPinValue === 0 && newPinValue !== previousValues[pinIndex]) { + sendNotification("switchLogic", rvoTbName, "main_switch_has_been_turned_off", {}, "", SEND_TO.tb, instance, "state_of_main_switch"); + 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"); + deviceStatus["state_of_main_switch"] = "On"; + } + } + + //Prevadzkovy mod + 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"; + + deviceStatus["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, "power_supply_has_disconnected_input", {}, "", SEND_TO.tb, instance, "power_supply"); + + deviceStatus["power_supply"] = "NOK"; + } + else if (newPinValue === 1 && newPinValue !== previousValues[pinIndex]) { + sendNotification("switchLogic", rvoTbName, "power_supply_works_correctly", {}, "", SEND_TO.tb, instance, "power_supply"); + + deviceStatus["power_supply"] = "OK"; + } + } + + //Bateria - 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"); + + deviceStatus["battery"] = "NOK"; + } + else if (newPinValue === 0 && newPinValue !== previousValues[pinIndex]) { + sendNotification("switchLogic", rvoTbName, "battery_level_is_ok", {}, "", SEND_TO.tb, instance, "battery_level"); + + deviceStatus["battery"] = "OK"; + } + } + + //Dverovy kontakt - pin 6 + //! Ak je rvo s dvoma dverovymi kontaktami, ked pride z evoku signal z input1_05, co bol predytm "state_of_main switch" handlujeme ho teraz ako 'door_condition' + else if (type == "door_condition" || type === "state_of_main_switch") { + newPinValue === 0 ? value = "open" : value = "closed"; + + let door = "door_main"; + if (type === "state_of_main_switch") door = "door_em"; + + if (value === "open") { + if (SETTINGS.maintenance_mode) { + sendNotification("switchLogic", rvoTbName, door + "_open", {}, "", SEND_TO.tb, instance, door); + } else { + sendNotification("switchLogic", rvoTbName, door + "_open_without_permission", {}, "", SEND_TO.tb, instance, door); + + // 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 (value === "closed") { + if (alarmStatus == "ON") turnAlarm("off"); + sendNotification("switchLogic", rvoTbName, door + "_close", {}, "", SEND_TO.tb, instance, door); + } + + deviceStatus[type] = value; + } + + //lux sensor + else if (type == "twilight_sensor") { + //! TODO - to show nok status, if lux value is not changing more then 10 times. + //Daylight is far more than 1000. So most of the day, when it is sunshine comes just value 1000. But lux sensor is not NOK. + //This is not the case in LM. If value from LM is the same 10x, there is 99% possibility, that sensor is NOK. + value = newPinValue; + + if (controller_type === 'lm') { + value = parseFloat(newPinValue + (256 * twilight)); + + 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 && !twilightError) { + twilightError = true; + let value = twilight_sensor_array.shift(); + + newPinValue = 0; + } + else if (set.size !== 1 && twilightError) { + //sendNotification("switchLogic", rvoTbName, 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) { + 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); + } + } + + 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); + } + + deviceStatus["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 (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 }); + + //mame iba 3 istice. vyreportujeme a ohandlujeme liniu na tom istom istici ako paralelna linia (napr linia 1, paralelna s nou je linia 4, key je string "4") + // ak je 7 linii, na 1 istici je linia 1,4,7 + + if (line == 1) { + + const lineOnSameBraker = [4, 7]; + + for (var i = 0; i < lineOnSameBraker.length; i++) { + if (!relaysData.hasOwnProperty(lineOnSameBraker[i])) continue; + + 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; + reportLineStatus(lineOnSameBraker[i]); + + values[type] = value; + const tbname = relaysData[lineOnSameBraker[i]].tbname; + sendTelemetry(values, tbname); + + delete values[type]; + } + + } + else { + const lineOnSameBraker = line + 3 + ""; + + if (relaysData.hasOwnProperty(lineOnSameBraker)) { + 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; + reportLineStatus(line + 3); + + values[type] = value; + const tbname = relaysData[lineOnSameBraker].tbname; + sendTelemetry(values, tbname); + + delete values[type]; + } + } + + } + + if (value == "Off") values["status"] = "NOK"; + deviceStatus["state_of_breaker"][line] = value; + + reportLineStatus(line); + } + else return; + + values[type] = value; + + if (type == "rotary_switch_state") { + if (SETTINGS.maintenance_mode) value = "maintenance"; + value = value.toLowerCase(); + values["power_mode"] = value; + } + + if (newPinValue != previousValues[pinIndex]) previousValues[pinIndex] = newPinValue; + if (Object.keys(values).length > 0 && tbname) sendTelemetry(values, tbname); + } + + + function sendTelemetry(values, tbname, date = Date.now()) { + let dataToTb = { + [tbname]: [ + { + "ts": date, + "values": values + } + ] + }; + + tbHandler.sendToTb(dataToTb, instance); + } + + + function isObject(item) { + return (typeof item === "object" && !Array.isArray(item) && item !== null); + } + +} //end of 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 +// *|input1_01|state_of_main_switch|0|........... +// *|input1_02|rotary_switch_state|0|........... +// *|input1_03|rotary_switch_state|0|........... +// *|intut1_04|power_supply|0|........... +// *|input1_05|door_condition|0|........... +// *|input1_06|state_of_breaker|1|........... +// *|input1_07|state_of_breaker|2|........... +// *|input1_08|state_of_breaker|3|........... +// *|relay1_02|state_of_contactor|1|........... +// *|relay1_03|state_of_contactor|2|........... +// *|relay1_04|state_of_contactor|3|........... +// *|287D8776E0013CE9|temperature|0|........... + + +//! pins_data --> from UNIPI +// { +// 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 } +// } + +//! relays_data +// { +// '0': { +// line: 0, +// tbname: 'KjbN4q7JPZmexgdnz2yKQ98YAWwO0Q3BMX6ERLoV', +// contactor: 1, +// profile: '' +// }, +// '1': { +// line: 1, +// tbname: 'RMgnK93rkoAazbqdQ4yBG95Z1YXGx6pmwBeVEP2O', +// contactor: 0, +// profile: '{"intervals":[{"value":0,"end_time":"20:00","start_time":"13:00"},{"value":1,"end_time":"10:00","start_time":"20:00"},{"value":0,"end_time":"10:20","start_time":"10:00"},{"value":1,"end_time":"10:40","start_time":"10:20"},{"value":0,"end_time":"11:00","start_time":"10:40"},{"value":1,"end_time":"11:30","start_time":"11:00"},{"value":0,"end_time":"11:50","start_time":"11:30"},{"value":1,"end_time":"13:00","start_time":"11:50"}],"astro_clock":false,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' +// }, +// '2': { +// line: 2, +// tbname: 'dlE1VQjYrNx9gZRmb38gG08oLBO4qaAk2M6JPnG7', +// contactor: 0, +// profile: '{"intervals":[{"value":0,"end_time":"20:00","start_time":"13:00"},{"value":1,"end_time":"10:00","start_time":"20:00"},{"value":0,"end_time":"10:20","start_time":"10:00"},{"value":1,"end_time":"10:40","start_time":"10:20"},{"value":0,"end_time":"11:00","start_time":"10:40"},{"value":1,"end_time":"11:30","start_time":"11:00"},{"value":0,"end_time":"11:50","start_time":"11:30"},{"value":1,"end_time":"13:00","start_time":"11:50"}],"astro_clock":false,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' +// }, +// '3': { +// line: 3, +// tbname: 'vnmG4kJxaXWNBgMQq0D7Aj5e9oZzOAlr6LdR3w2V', +// contactor: 0, +// profile: '{"intervals":[{"value":0,"end_time":"20:30","start_time":"13:00"},{"value":1,"end_time":"00:10","start_time":"20:30"},{"value":0,"end_time":"13:00","start_time":"05:40"},{"value":1,"end_time":"05:40","start_time":"00:10"}],"astro_clock":true,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' +// } +// } + + + + + +// { +// "jbN4q7JPZmexgdnz2yKbWGDYAWwO0Q3BMX6ERLoV": [ +// { +// "ts": 1700409326353, +// "values": { +// "_event": { +// "type": "notice", +// "status": "new", +// "source": { +// "func": "rsPort.open()", +// "component": "1700343402190", +// "component_name": "DIDO_Controller", +// "edge": "jbN4q7JPZmexgdnz2yKbWGDYAWwO0Q3BMX6ERLoV" +// }, +// "message": "al_shariff_10.0.0.38: FLOW has been started ", +// "message_data": "" +// } +// } +// } +// ] +// } diff --git a/RVO41/flow/helper/DataToTbHandler.js b/RVO41/flow/helper/DataToTbHandler.js new file mode 100755 index 0000000..716ef7b --- /dev/null +++ b/RVO41/flow/helper/DataToTbHandler.js @@ -0,0 +1,187 @@ +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; + this.itIsNodeReadout = false; + this.sender = ""; + + // if attribute change difference is less than limit value, we do not send to tb. + this.attributeChangeLimit = { + temperature: 0.5, + Phase_1_voltage: 2, + Phase_2_voltage: 2, + Phase_3_voltage: 2, + Phase_1_current: 0.1, + Phase_2_current: 0.1, + Phase_3_current: 0.1, + Phase_1_power: 2, + Phase_2_power: 2, + Phase_3_power: 2, + total_power: 2, + total_energy: 1, + Phase_1_pow_factor: 0.1, + Phase_2_pow_factor: 0.1, + Phase_3_pow_factor: 0.1, + power_factor: 0.1, + lifetime: 2, + voltage: 2, + power: 2, + frequency: 3, + energy: 0.1, + current: 2, + inclination_x: 10, + inclination_y: 10, + inclination_z: 10 + }; + + } + + dump() { + console.log("----------------------------"); + console.log("previousValues", this.previousValues); + console.log("----------------------------"); + } + + setSender(sender) { + this.sender = sender; + } + + isEmptyObject(obj) { + for (var _ in obj) { + return false; + } + return true; + } + + + sendToTb(data, instance) { + + //not to modify data object, we do deep copy: + let dataCopy = JSON.parse(JSON.stringify(data)); + + let keys = Object.keys(dataCopy); + + if (keys.length == 0) { + if (this.debug) console.log("sendToTb received empty object", dataCopy); + return; + } + + let tbname = keys[0]; + let ts; + + let arrayOfValues = dataCopy[tbname]; + let arrayOfValuesToSend = []; + + for (let i = 0; i < arrayOfValues.length; i++) { + + ts = arrayOfValues[i].ts; + let values = this.prepareValuesForTb(tbname, ts, arrayOfValues[i].values); + + if (!this.isEmptyObject(values)) { + arrayOfValuesToSend.push({ ts: ts, values: values }); + } + + } + + if (arrayOfValuesToSend.length == 0) { + //if(this.debug) console.log("data not sent - empty array"); + return; + } + + this.messageCounter++; + + let dataToTbModified = { + [tbname]: arrayOfValuesToSend + } + + //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); + instance.send(this.index, dataToTbModified); + } + + + getDiffTimestamp(key) { + //TODO set different value for given key!!! + //if(key == "status") this.timeToHoldTbValue = 2*60*60;//2h + return this.timeToHoldTbValue * 1000; + } + + + prepareValuesForTb(tbname, timestamp, values) { + + let keys = Object.keys(values); + + if (keys.includes("lifetime")) this.itIsNodeReadout = true; + + if (!this.previousValues.hasOwnProperty(tbname)) { + this.previousValues[tbname] = {}; + } + + //if(this.debug) console.log("prepareValuesForTb", tbname, timestamp, values); + + for (let i = 0; i < keys.length; i++) { + + let key = keys[i]; + let value = values[key]; + + if (!this.previousValues[tbname].hasOwnProperty(key)) { + this.previousValues[tbname][key] = { ts: timestamp, value: value }; + continue; + } + + // attributeData ==> {voltage: {ts:333333, value:5}} + let attributeData = this.previousValues[tbname][key]; + let attributeToChange = false; + if (key in this.attributeChangeLimit) attributeToChange = true; + let limit = this.attributeChangeLimit[key]; + let timestampDiffToRemoveKey; + + //this will ensure "node statecode" will be sent just once an hour + if (this.itIsNodeReadout && key === "statecode") { + attributeData.value = value; + this.itIsNodeReadout = false; + timestampDiffToRemoveKey = 1 * 60 * 60 * 1000; // 1 hour + } + + if (key === "twilight_sensor" && value > 100) { + attributeData.value = value; + } + + //if edge, master or node version do not change, send just once a day: + if (["edge_fw_version", "master_node_version", "fw_version"].includes(key)) { + timestampDiffToRemoveKey = 24 * 60 * 60 * 1000; + } + + if (attributeData.value === value || attributeToChange && Math.abs(attributeData.value - value) < limit) { + + let diff = timestamp - attributeData.ts; + if (!timestampDiffToRemoveKey) timestampDiffToRemoveKey = this.getDiffTimestamp(key); + + if (diff > timestampDiffToRemoveKey) { + attributeData.ts = Date.now(); + //if(this.debug) console.log(this.sender + ": update ts for key", key, "diff is", diff, "messageCounter", this.messageCounter); + } + else { + delete values[key]; + //if(this.debug) console.log(this.sender + ": delete key", key, "diff is", diff, "messageCounter", this.messageCounter, timestampDiffToRemoveKey); + } + } + else { + attributeData.value = value; + attributeData.ts = timestamp; + } + + } + + return values; + } +} + +module.exports = DataToTbHandler; + diff --git a/RVO41/flow/helper/ErrorToServiceHandler.js b/RVO41/flow/helper/ErrorToServiceHandler.js new file mode 100755 index 0000000..2b27c32 --- /dev/null +++ b/RVO41/flow/helper/ErrorToServiceHandler.js @@ -0,0 +1,91 @@ +const { MD5 } = require('./md5.js'); +const { networkInterfaces } = require('os'); + +class ErrorToServiceHandler { + constructor() { + this.previousValues = {}; + + this.project_id = undefined; + + const nets = networkInterfaces(); + this.ipAddresses = {}; + + for (const name of Object.keys(nets)) { + for (const net of nets[name]) { + // Skip over non-IPv4 and internal (i.e. 127.0.0.1) addresses + if (net.family === 'IPv4' && !net.internal) { + if (!this.ipAddresses[name]) { + this.ipAddresses[name] = []; + } + this.ipAddresses[name].push(net.address); + } + } + } + } + + setProjectId(project_id) { + this.project_id = project_id; + } + + processMessage(message, seconds) { + if (Array.isArray(message)) message = message.join(', '); + + let key = MD5(message); + let ts = Date.now(); + + //keep in memory - default value is 1h + if (seconds === undefined) seconds = 60 * 60; + + if (!this.previousValues.hasOwnProperty(key)) { + this.previousValues[key] = { ts: ts, duration: seconds }; + } + + let diff = (ts - this.previousValues[key].ts); + if (diff < this.previousValues[key].duration * 1000) return false; + + this.previousValues[key].ts = ts; + + return message; + } + + sendMessageToService(message, seconds, message_type) { + + // if error occures too early FLOW.GLOBALS.settings.project_id is still undefined + if (this.project_id === undefined) { + console.log("ErrorToServiceHandler.js: no project_id"); + return; + } + + let f = this.processMessage(message, seconds); + if (f === false) return; + + if (message_type === undefined) message_type = "error_message"; + + let toService = { + id: this.project_id, + ipAddresses: this.ipAddresses + }; + + //js_error || error_message + toService[message_type] = message; + + console.log("ErrorToServiceHandler------------------------>send to service", toService); + + RESTBuilder.make(function(builder) { + builder.method('POST'); + builder.post(toService); + builder.url('http://192.168.252.2:8004/sentmessage'); + + builder.callback(function(err, response, output) { + console.log("process.on error send", err, response, output, toService); + }); + }); + + } +} + +const errorHandler = new ErrorToServiceHandler(); + + +module.exports = errorHandler; +//module.exports = ErrorToServiceHandler; diff --git a/RVO41/flow/helper/db_helper.js b/RVO41/flow/helper/db_helper.js new file mode 100755 index 0000000..40e796c --- /dev/null +++ b/RVO41/flow/helper/db_helper.js @@ -0,0 +1,44 @@ +function promisifyBuilder(builder) +{ + return new Promise((resolve, reject) => { + + try{ + + builder.callback(function(err, response) { + + if(err != null) reject(err); + resolve(response); + }); + + } catch (error) { + reject(error); + } + }) +} + +function makeMapFromDbResult(response, ...keys) +{ + let s = "-"; + let data = {}; + + for(let i = 0; i < response.length; i++) + { + let record = response[i]; + + let k = []; + for(let j = 0; j < keys.length; j++) + { + k.push( record[keys[j]] ); + } + + let key = k.join(s); + data[ key ] = record; + } + + return data; +} + +module.exports = { + promisifyBuilder, + makeMapFromDbResult + } \ No newline at end of file diff --git a/RVO41/flow/helper/logger.js b/RVO41/flow/helper/logger.js new file mode 100755 index 0000000..2585639 --- /dev/null +++ b/RVO41/flow/helper/logger.js @@ -0,0 +1,30 @@ +//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/RVO41/flow/helper/md5.js b/RVO41/flow/helper/md5.js new file mode 100755 index 0000000..d3b0480 --- /dev/null +++ b/RVO41/flow/helper/md5.js @@ -0,0 +1,5 @@ +function MD5(d){var r = M(V(Y(X(d),8*d.length)));return r.toLowerCase()};function M(d){for(var _,m="0123456789ABCDEF",f="",r=0;r>>4&15)+m.charAt(15&_);return f}function X(d){for(var _=Array(d.length>>2),m=0;m<_.length;m++)_[m]=0;for(m=0;m<8*d.length;m+=8)_[m>>5]|=(255&d.charCodeAt(m/8))<>5]>>>m%32&255);return _}function Y(d,_){d[_>>5]|=128<<_%32,d[14+(_+64>>>9<<4)]=_;for(var m=1732584193,f=-271733879,r=-1732584194,i=271733878,n=0;n>16)+(_>>16)+(m>>16)<<16|65535&m}function bit_rol(d,_){return d<<_|d>>>32-_} + +module.exports = { + MD5 +} \ No newline at end of file diff --git a/RVO41/flow/helper/notification_reporter.js b/RVO41/flow/helper/notification_reporter.js new file mode 100755 index 0000000..839c12c --- /dev/null +++ b/RVO41/flow/helper/notification_reporter.js @@ -0,0 +1,121 @@ +//key is device, value = message {} +let sentValues = {}; +let notificationsData = null; +let rvoName; + +//sendNotification("CMD Manager: process cmd", SETTINGS.rvoTbName, "dimming_profile_was_successfully_received_by_node", { node: node }, "", SEND_TO.tb, instance); + +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 +}; + +function getKey(map, val) { + return Object.keys(map).findItem(key => map[key] === val); +} + +//https://stackoverflow.com/questions/41117799/string-interpolation-on-variable +var template = (tpl, args) => tpl.replace(/\${(\w+)}/g, (_, v) => args[v]); + + +function initNotification() { + notificationsData = FLOW.GLOBALS.notificationsData; + rvoName = FLOW.GLOBALS.settings.rvo_name; +} + + +function sendNotification(func, device, key, params, extra, tb_output, instance, saveKey) { + + let storeToSendValues = true; + if (saveKey == undefined) storeToSendValues = false; + + let weight = ""; + let message = {}; + + let notification = notificationsData[key]; + + if (notification) { + weight = notification.weight.toLowerCase(); + + Object.keys(notification).forEach(item => { + if (["en", "sk", "de", "cz", "it", "es"].includes(item)) { + message[item] = rvoName + ": " + template(notification[item], params); + } + }) + } + else { + //console.error("sendNotification: Notifications: undefined key", key, func, notificationsData); + console.error("sendNotification: Notifications: undefined key", key, func); + return false; + } + + //detect invalid err weight + if (getKey(ERRWEIGHT, weight) == undefined) { + console.error("sendNotification: Notifications: undefined weight", weight, key, func); + return false; + } + + if (sentValues.hasOwnProperty(saveKey)) { + if (JSON.stringify(sentValues[saveKey]) == JSON.stringify(message)) { + return false; + } + } + + if (sentValues[saveKey] == undefined) { + if (storeToSendValues) { + //do not send - flow is was started + sentValues[saveKey] = message; + return false; + } + } + + if (storeToSendValues) sentValues[saveKey] = message; + + let content = { + "type": weight, + "status": "new", + "source": { + "func": func, + "component": instance.id, + "component_name": instance.name, + "edge": device + }, + "message": message, + "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 + + return true; + +} + +module.exports = { + sendNotification, + ERRWEIGHT, + initNotification +} + diff --git a/RVO41/flow/helper/register.js b/RVO41/flow/helper/register.js new file mode 100755 index 0000000..fc1d008 --- /dev/null +++ b/RVO41/flow/helper/register.js @@ -0,0 +1,144 @@ +/* +0 - cislo registra / prikaz +1 - recepient - 0 = master, 1 = slave (slave je automaticky group a broadcast) +2 - r/rw - read/write +3- register name - nazov registra / prikazu (len pre info - zobrazenie v aplikacii) + +4,5,6,7, - jednotlive byte-y - nazov byte-u +4-7 - RES. a prazdny string "" sa nezobrazia!!! +*/ + +//124 zaznamov +const registers = [ + ["0","1","R","Status","","",""], + ["1","1","RW","Dimming","R-Channel ","G-Channel","B-Channel ","W - Channel"], + ["2","1","R","Device types","","",".",""], + ["3","1","RW","Group addresses 1-4","Groups Add. 4","Groups Add. 3","Groups Add. 2","Groups Add. 1"], + ["4","1","RW","Group addresses 5-8","Groups Add. 8","Groups Add. 7","Groups Add. 6","Groups Add. 5"], + ["5","1","RW","Serial number (MAC)","","","",""], + ["6","1","RW","Time of dusk","HH","MM","SS","EXTRA"], + ["7","1","RW","Time of dawn","HH","MM","SS","EXTRA"], + ["8","1","RW","Time Schedule settings","TBD","TBD","Movement sensor","Time Schedule"], + ["9","1","RW","TS1 Time point 1","HH","MM","SS","Ext. Device"], + ["10","1","RW","TS1 Time point 1 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["11","1","RW","TS1 Time point 2","HH","MM","SS","Ext. Device"], + ["12","1","RW","TS1 Time point 2 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["13","1","RW","TS1 Time point 3","HH","MM","SS","Ext. Device"], + ["14","1","RW","TS1 Time point 3 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["15","1","RW","TS1 Time point 4","HH","MM","SS","Ext. Device"], + ["16","1","RW","TS1 Time point 4 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["17","1","RW","TS1 Time point 5","HH","MM","SS","Ext. Device"], + ["18","1","RW","TS1 Time point 5 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["19","1","RW","TS1 Time point 6","HH","MM","SS","Ext. Device"], + ["20","1","RW","TS1 Time point 6 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["21","1","RW","TS1 Time point 7","HH","MM","SS","Ext. Device"], + ["22","1","RW","TS1 Time point 7 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["23","1","RW","TS1 Time point 8","HH","MM","SS","Ext. Device"], + ["24","1","RW","TS1 Time point 8 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["25","1","RW","TS1 Time point 9","HH","MM","SS","Ext. Device"], + ["26","1","RW","TS1 Time point 9 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["27","1","RW","TS1 Time point 10","HH","MM","SS","Ext. Device"], + ["28","1","RW","TS1 Time point 10 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["29","1","RW","TS1 Time point 11","HH","MM","SS","Ext. Device"], + ["30","1","RW","TS1 Time point 11 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["31","1","RW","TS1 Time point 12","HH","MM","SS","Ext. Device"], + ["32","1","RW","TS1 Time point 12 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["33","1","RW","TS1 Time point 13","HH","MM","SS","Ext. Device"], + ["34","1","RW","TS1 Time point 13 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["35","1","RW","TS1 Time point 14","HH","MM","SS","Ext. Device"], + ["36","1","RW","TS1 Time point 14 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["37","1","RW","TS1 Time point 15","HH","MM","SS","Ext. Device"], + ["38","1","RW","TS1 Time point 15 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["39","1","RW","TS1 Time point 16","HH","MM","SS","Ext. Device"], + ["40","1","RW","TS1 Time point 16 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["41","1","RW","TS2 Time point 1","HH","MM","SS","Ext. Device"], + ["42","1","RW","TS2 Time point 1 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["43","1","RW","TS2 Time point 2","HH","MM","SS","Ext. Device"], + ["44","1","RW","TS2 Time point 2 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["45","1","RW","TS2 Time point 3","HH","MM","SS","Ext. Device"], + ["46","1","RW","TS2 Time point 3 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["47","1","RW","TS2 Time point 4","HH","MM","SS","Ext. Device"], + ["48","1","RW","TS2 Time point 4 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["49","1","RW","TS2 Time point 5","HH","MM","SS","Ext. Device"], + ["50","1","RW","TS2 Time point 5 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["51","1","RW","TS2 Time point 6","HH","MM","SS","Ext. Device"], + ["52","1","RW","TS2 Time point 6 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["53","1","RW","TS2 Time point 7","HH","MM","SS","Ext. Device"], + ["54","1","RW","TS2 Time point 7 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["55","1","RW","TS2 Time point 8","HH","MM","SS","Ext. Device"], + ["56","1","RW","TS2 Time point 8 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["57","1","RW","TS2 Time point 9","HH","MM","SS","Ext. Device"], + ["58","1","RW","TS2 Time point 9 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["59","1","RW","TS2 Time point 10","HH","MM","SS","Ext. Device"], + ["60","1","RW","TS2 Time point 10 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["61","1","RW","TS2 Time point 11","HH","MM","SS","Ext. Device"], + ["62","1","RW","TS2 Time point 11 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["63","1","RW","TS2 Time point 12","HH","MM","SS","Ext. Device"], + ["64","1","RW","TS2 Time point 12 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["65","1","RW","TS2 Time point 13","HH","MM","SS","Ext. Device"], + ["66","1","RW","TS2 Time point 13 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["67","1","RW","TS2 Time point 14","HH","MM","SS","Ext. Device"], + ["68","1","RW","TS2 Time point 14 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["69","1","RW","TS2 Time point 15","HH","MM","SS","Ext. Device"], + ["70","1","RW","TS2 Time point 15 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["71","1","RW","TS2 Time point 16","HH","MM","SS","Ext. Device"], + ["72","1","RW","TS2 Time point 16 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["73","1","RW","Power meter status","TBD","","",""], + ["74","1","R","Input Voltage","","","",""], + ["75","1","R","Input Current","","","",""], + ["76","1","R","Input Power","","","",""], + ["77","1","R","Cos phi","","","",""], + ["78","1","R","Frequency","","","",""], + ["79","1","RW","Energy","","","",""], + ["80","1","RW","Lifetime","","","",""], + ["81","1","RW","Power on cycles (input)","","","",""], + ["82","1","RW","Power on cycles (relay)","","","",""], + ["83","1","R","Time since last power on","","","",""], + ["84","1","R","Accelerometer data","","","",""], + ["85","1","RW","GPS latitude","pos/neg","deg","min ","sec"], + ["86","1","RW","GPS longitude","pos/neg","deg","min ","sec"], + ["87","1","RW","Actual time","HH","MM","SS","RES."], + ["88","1","RW","Actual date","Day of week","Day","Month","Year"], + ["89","1","R","Production data 1","","","",""], + ["90","1","R","Production data 2","","","",""], + ["91","1","RW","Network ID","NID3","NID2","NID1","NID0"], + ["95","1","RW","Actual Lux level from cabinet","RES.","RES.","HB","LB"], + ["96","1","RW","Threshold lux level","Dusk HB","Dusk LB","Dawn HB","Dawn LB"], + ["97","1","RW","Adjust period","Dusk HB","Dusk LB","Dawn HB","Dawn LB"], + ["98","1","RW","Offset","RES.","RES.","Dusk","Dawn"], + ["99","1","RW","CCT min/max range","max-H","max-L","min-H","min-L"], + ["100","1","RW","DALI interface","Cmd ID","Add","Cmd","Resp"], + ["101","1","RW","Module FW ver","v1","v2","v3","v4"], + ["102","1","RW","Module MAC-H","unused","unused","M1","M2"], + ["103","1","RW","Module MAC-L","M3","M4","M5","M6"], + ["122","1","R","FW update status/control register","Byte3","Byte2","Byte1","Byte0"], + ["123","1","R","FW update - data index","Byte3","Byte2","Byte1","Byte0"], + ["124","1","R","FW update - data","Byte3","Byte2","Byte1","Byte0"], + ["0","0","R","Status","","","",""], + ["1","0","RW","Control register","RES.","RES.","RES.","init mode enable"], + ["2","0","R","Device types","","","",""], + ["3","0","R","Serial number (MAC)","","","",""], + ["4","0","R","Production data 1","","","",""], + ["5","0","R","Production data 2","","","",""], + ["6","0","RW","Network ID","NID3","NID2","NID1","NID0"], + ["7","0","RW","RS232 settings","param.","param.","Baudrate H","Baudrate L"], + ["8","0","R","Accelerometer data","","","",""], + ["9","0","RW","Module FW ver","v1","v2","v3","v4"], + ["10","0","RW","Module MAC-H","unused","unused","M1","M2"], + ["11","0","RW","Module MAC-L","M3","M4","M5","M6"], + ["32","0","RW","FW update status/control register","Byte3","Byte2","Byte1","Byte0"], + ["33","0","RW","FW update - data index","Byte3","Byte2","Byte1","Byte0"], + ["34","0","RW","FW update - data","Byte3","Byte2","Byte1","Byte0"], + ["125","0","RW","Debug Register","Byte3","Byte2","Byte1","Byte0"], + ["126","0","RW","Network Control Register","Byte3","Byte2","Byte1","Byte0"], + ["127","0","R","Network Status Register","Byte3","Byte2","Byte1","Byte0"], + ["128","0","RW","Node XX Serial Number Register","SER3","SER2","SER1","SER0"], + ["256","0","R","Node XX Network Status Register","","","",""] +]; + +let register = {}; + +module.exports = { + registers, + register +} \ No newline at end of file diff --git a/RVO41/flow/helper/serialport_helper.js b/RVO41/flow/helper/serialport_helper.js new file mode 100755 index 0000000..7f5920d --- /dev/null +++ b/RVO41/flow/helper/serialport_helper.js @@ -0,0 +1,99 @@ +const { exec } = require('child_process'); + +function openPort(port) { + return new Promise((resolve, reject) => { + + var callbackError = function(err) { + port.removeListener('error', callbackError); + port.removeListener('open', callbackError); + + reject(err.message); + }; + + var callbackOpen = function(data) { + port.removeListener('error', callbackError); + port.removeListener('open', callbackOpen); + + resolve("port open: ok"); + }; + + port.on('error', callbackError); + port.on('open', callbackOpen); + + port.open(); + + }) +} + +function runSyncExec(command) { + return new Promise((resolve, reject) => { + + exec(command, (error, stdout, stderr) => { + if (error == null) resolve(stdout); + reject(error); + }); + + }) +} + +async function writeData(port, data, readbytes, timeout) { + return new Promise((resolve, reject) => { + + // 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) { + + port.write(Buffer.from(data), function(err) { + if (err) { + reject(err.message); + } + }); + + 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 +} diff --git a/RVO41/flow/helper/suncalc.js b/RVO41/flow/helper/suncalc.js new file mode 100755 index 0000000..c9ca56d --- /dev/null +++ b/RVO41/flow/helper/suncalc.js @@ -0,0 +1,317 @@ +/* + (c) 2011-2015, Vladimir Agafonkin + SunCalc is a JavaScript library for calculating sun/moon position and light phases. + https://github.com/mourner/suncalc +*/ + +(function () { 'use strict'; + +// shortcuts for easier to read formulas + +var PI = Math.PI, + sin = Math.sin, + cos = Math.cos, + tan = Math.tan, + asin = Math.asin, + atan = Math.atan2, + acos = Math.acos, + rad = PI / 180; + +// sun calculations are based on http://aa.quae.nl/en/reken/zonpositie.html formulas + + +// date/time constants and conversions + +var dayMs = 1000 * 60 * 60 * 24, + J1970 = 2440588, + J2000 = 2451545; + +function toJulian(date) { return date.valueOf() / dayMs - 0.5 + J1970; } +function fromJulian(j) { return new Date((j + 0.5 - J1970) * dayMs); } +function toDays(date) { return toJulian(date) - J2000; } + + +// general calculations for position + +var e = rad * 23.4397; // obliquity of the Earth + +function rightAscension(l, b) { return atan(sin(l) * cos(e) - tan(b) * sin(e), cos(l)); } +function declination(l, b) { return asin(sin(b) * cos(e) + cos(b) * sin(e) * sin(l)); } + +function azimuth(H, phi, dec) { return atan(sin(H), cos(H) * sin(phi) - tan(dec) * cos(phi)); } +function altitude(H, phi, dec) { return asin(sin(phi) * sin(dec) + cos(phi) * cos(dec) * cos(H)); } + +function siderealTime(d, lw) { return rad * (280.16 + 360.9856235 * d) - lw; } + +function astroRefraction(h) { + if (h < 0) // the following formula works for positive altitudes only. + h = 0; // if h = -0.08901179 a div/0 would occur. + + // formula 16.4 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + // 1.02 / tan(h + 10.26 / (h + 5.10)) h in degrees, result in arc minutes -> converted to rad: + return 0.0002967 / Math.tan(h + 0.00312536 / (h + 0.08901179)); +} + +// general sun calculations + +function solarMeanAnomaly(d) { return rad * (357.5291 + 0.98560028 * d); } + +function eclipticLongitude(M) { + + var C = rad * (1.9148 * sin(M) + 0.02 * sin(2 * M) + 0.0003 * sin(3 * M)), // equation of center + P = rad * 102.9372; // perihelion of the Earth + + return M + C + P + PI; +} + +function sunCoords(d) { + + var M = solarMeanAnomaly(d), + L = eclipticLongitude(M); + + return { + dec: declination(L, 0), + ra: rightAscension(L, 0) + }; +} + + +var SunCalc = {}; + + +// calculates sun position for a given date and latitude/longitude + +SunCalc.getPosition = function (date, lat, lng) { + + var lw = rad * -lng, + phi = rad * lat, + d = toDays(date), + + c = sunCoords(d), + H = siderealTime(d, lw) - c.ra; + + return { + azimuth: azimuth(H, phi, c.dec), + altitude: altitude(H, phi, c.dec) + }; +}; + + +// sun times configuration (angle, morning name, evening name) + +var times = SunCalc.times = [ + [-0.833, 'sunrise', 'sunset' ], + [ -0.3, 'sunriseEnd', 'sunsetStart' ], + [ -6, 'dawn', 'dusk' ], + [ -12, 'nauticalDawn', 'nauticalDusk'], + [ -18, 'nightEnd', 'night' ], + [ 6, 'goldenHourEnd', 'goldenHour' ] +]; + +// adds a custom time to the times config + +SunCalc.addTime = function (angle, riseName, setName) { + times.push([angle, riseName, setName]); +}; + + +// calculations for sun times + +var J0 = 0.0009; + +function julianCycle(d, lw) { return Math.round(d - J0 - lw / (2 * PI)); } + +function approxTransit(Ht, lw, n) { return J0 + (Ht + lw) / (2 * PI) + n; } +function solarTransitJ(ds, M, L) { return J2000 + ds + 0.0053 * sin(M) - 0.0069 * sin(2 * L); } + +function hourAngle(h, phi, d) { return acos((sin(h) - sin(phi) * sin(d)) / (cos(phi) * cos(d))); } +function observerAngle(height) { return -2.076 * Math.sqrt(height) / 60; } + +// returns set time for the given sun altitude +function getSetJ(h, lw, phi, dec, n, M, L) { + + var w = hourAngle(h, phi, dec), + a = approxTransit(w, lw, n); + return solarTransitJ(a, M, L); +} + + +// calculates sun times for a given date, latitude/longitude, and, optionally, +// the observer height (in meters) relative to the horizon + +SunCalc.getTimes = function (date, lat, lng, height) { + + height = height || 0; + + var lw = rad * -lng, + phi = rad * lat, + + dh = observerAngle(height), + + d = toDays(date), + n = julianCycle(d, lw), + ds = approxTransit(0, lw, n), + + M = solarMeanAnomaly(ds), + L = eclipticLongitude(M), + dec = declination(L, 0), + + Jnoon = solarTransitJ(ds, M, L), + + i, len, time, h0, Jset, Jrise; + + + var result = { + solarNoon: fromJulian(Jnoon), + nadir: fromJulian(Jnoon - 0.5) + }; + + for (i = 0, len = times.length; i < len; i += 1) { + time = times[i]; + h0 = (time[0] + dh) * rad; + + Jset = getSetJ(h0, lw, phi, dec, n, M, L); + Jrise = Jnoon - (Jset - Jnoon); + + result[time[1]] = fromJulian(Jrise); + result[time[2]] = fromJulian(Jset); + } + + return result; +}; + + +// moon calculations, based on http://aa.quae.nl/en/reken/hemelpositie.html formulas + +function moonCoords(d) { // geocentric ecliptic coordinates of the moon + + var L = rad * (218.316 + 13.176396 * d), // ecliptic longitude + M = rad * (134.963 + 13.064993 * d), // mean anomaly + F = rad * (93.272 + 13.229350 * d), // mean distance + + l = L + rad * 6.289 * sin(M), // longitude + b = rad * 5.128 * sin(F), // latitude + dt = 385001 - 20905 * cos(M); // distance to the moon in km + + return { + ra: rightAscension(l, b), + dec: declination(l, b), + dist: dt + }; +} + +SunCalc.getMoonPosition = function (date, lat, lng) { + + var lw = rad * -lng, + phi = rad * lat, + d = toDays(date), + + c = moonCoords(d), + H = siderealTime(d, lw) - c.ra, + h = altitude(H, phi, c.dec), + // formula 14.1 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + pa = atan(sin(H), tan(phi) * cos(c.dec) - sin(c.dec) * cos(H)); + + h = h + astroRefraction(h); // altitude correction for refraction + + return { + azimuth: azimuth(H, phi, c.dec), + altitude: h, + distance: c.dist, + parallacticAngle: pa + }; +}; + + +// calculations for illumination parameters of the moon, +// based on http://idlastro.gsfc.nasa.gov/ftp/pro/astro/mphase.pro formulas and +// Chapter 48 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + +SunCalc.getMoonIllumination = function (date) { + + var d = toDays(date || new Date()), + s = sunCoords(d), + m = moonCoords(d), + + sdist = 149598000, // distance from Earth to Sun in km + + phi = acos(sin(s.dec) * sin(m.dec) + cos(s.dec) * cos(m.dec) * cos(s.ra - m.ra)), + inc = atan(sdist * sin(phi), m.dist - sdist * cos(phi)), + angle = atan(cos(s.dec) * sin(s.ra - m.ra), sin(s.dec) * cos(m.dec) - + cos(s.dec) * sin(m.dec) * cos(s.ra - m.ra)); + + return { + fraction: (1 + cos(inc)) / 2, + phase: 0.5 + 0.5 * inc * (angle < 0 ? -1 : 1) / Math.PI, + angle: angle + }; +}; + + +function hoursLater(date, h) { + return new Date(date.valueOf() + h * dayMs / 24); +} + +// calculations for moon rise/set times are based on http://www.stargazing.net/kepler/moonrise.html article + +SunCalc.getMoonTimes = function (date, lat, lng, inUTC) { + var t = new Date(date); + if (inUTC) t.setUTCHours(0, 0, 0, 0); + else t.setHours(0, 0, 0, 0); + + var hc = 0.133 * rad, + h0 = SunCalc.getMoonPosition(t, lat, lng).altitude - hc, + h1, h2, rise, set, a, b, xe, ye, d, roots, x1, x2, dx; + + // go in 2-hour chunks, each time seeing if a 3-point quadratic curve crosses zero (which means rise or set) + for (var i = 1; i <= 24; i += 2) { + h1 = SunCalc.getMoonPosition(hoursLater(t, i), lat, lng).altitude - hc; + h2 = SunCalc.getMoonPosition(hoursLater(t, i + 1), lat, lng).altitude - hc; + + a = (h0 + h2) / 2 - h1; + b = (h2 - h0) / 2; + xe = -b / (2 * a); + ye = (a * xe + b) * xe + h1; + d = b * b - 4 * a * h1; + roots = 0; + + if (d >= 0) { + dx = Math.sqrt(d) / (Math.abs(a) * 2); + x1 = xe - dx; + x2 = xe + dx; + if (Math.abs(x1) <= 1) roots++; + if (Math.abs(x2) <= 1) roots++; + if (x1 < -1) x1 = x2; + } + + if (roots === 1) { + if (h0 < 0) rise = i + x1; + else set = i + x1; + + } else if (roots === 2) { + rise = i + (ye < 0 ? x2 : x1); + set = i + (ye < 0 ? x1 : x2); + } + + if (rise && set) break; + + h0 = h2; + } + + var result = {}; + + if (rise) result.rise = hoursLater(t, rise); + if (set) result.set = hoursLater(t, set); + + if (!rise && !set) result[ye > 0 ? 'alwaysUp' : 'alwaysDown'] = true; + + return result; +}; + + +// export as Node module / AMD module / browser variable +if (typeof exports === 'object' && typeof module !== 'undefined') module.exports = SunCalc; +else if (typeof define === 'function' && define.amd) define(SunCalc); +else window.SunCalc = SunCalc; + +}()); diff --git a/RVO41/flow/helper/utils.js b/RVO41/flow/helper/utils.js new file mode 100755 index 0000000..dbffe45 --- /dev/null +++ b/RVO41/flow/helper/utils.js @@ -0,0 +1,161 @@ +const fs = require('fs').promises; + +function bytesToInt(bytes, numberOfBytes) { + let buffer = []; + if (Array.isArray(bytes)) { + buffer = bytes.slice(0); + if (numberOfBytes != undefined) { + buffer = bytes.slice(bytes.length - numberOfBytes); + } + } + else buffer.push(bytes); + + let result = 0; + for (let i = 0; i < buffer.length; i++) { + result = (result << 8) | buffer[i]; + } + + return result >>> 0; //ensure it's an unsigned 32-bit number +} + +function resizeArray(arr, newSize, defaultValue) { + while (newSize > arr.length) + arr.push(defaultValue); + arr.length = newSize; +} + +longToByteArray = function(/*long*/long) { + // we want to represent the input as a 8-bytes array + var byteArray = [0, 0, 0, 0, 0, 0, 0, 0]; + + for (var index = 0; index < byteArray.length; index++) { + var byte = long & 0xff; + byteArray[index] = byte; + long = (long - byte) / 256; + } + + return byteArray; +}; + +function addDays(date, days) { + var result = new Date(date); + result.setDate(result.getDate() + days); + return result; +} + +/* +sleep(2000).then(() => { + // Do something after the sleep! + + +}); +*/ + +function sleep(time) { + return new Promise((resolve) => setTimeout(resolve, time)); +} + +function isEmptyObject(obj) { + for (var name in obj) { + return false; + } + return true; +} + +function emptyJsObject(jsObject) { + Object.keys(jsObject).forEach(key => delete jsObject[key]); +} + +function convertUTCDateToLocalDate(date) { + var newDate = new Date(date); + newDate.setMinutes(date.getMinutes() + date.getTimezoneOffset()); + return newDate; +} + +function addZeroBefore(n) { + return (n < 10 ? '0' : '') + n; +} + + +/** + * Asynchronously writes data to a file. + * + * @param {string} filePath The path to the file. + * @param {string} data The data to write to the file. + * @param {boolean} [append=false] If true, appends the data to the file. If false, it overwrites the file. + */ +async function writeToFile(filePath, data, append = false) { + if (typeof data !== 'string') data = JSON.stringify(data, null, 2); + try { + if (append) { + // Append the data to the end of the file. This is the simplest way to append. + await fs.appendFile(filePath, data, 'utf8'); + console.log(`Successfully appended data to ${filePath} using fs.appendFile.`); + } else { + // Overwrite the file with the new data. + await fs.writeFile(filePath, data, 'utf8'); + console.log(`Successfully wrote (overwrote) data to ${filePath} using fs.writeFile.`); + } + } catch (error) { + console.error(`Error writing to file ${filePath}:`, error); + } +} + + + /** + * Checks if an item is present in an array and adds it if it's not. + * * @param {Array} arr The array to check. + * @param {*} item The item to add. + * @returns {Array} The modified array. + */ +const addToArrayIfUnique = (arr, item) => { + if (!arr.includes(item)) { + arr.push(item); + } + return arr; +}; + + +var convertBase = function() { + + function convertBase(baseFrom, baseTo) { + return function(num) { + return parseInt(num, baseFrom).toString(baseTo); + + }; + } + + // binary to decimal + convertBase.bin2dec = convertBase(2, 10); + + // binary to hexadecimal + convertBase.bin2hex = convertBase(2, 16); + + // decimal to binary + convertBase.dec2bin = convertBase(10, 2); + + // decimal to hexadecimal + convertBase.dec2hex = convertBase(10, 16); + + // hexadecimal to binary + convertBase.hex2bin = convertBase(16, 2); + + // hexadecimal to decimal + convertBase.hex2dec = convertBase(16, 10); + + return convertBase; +}(); + +module.exports = { + bytesToInt, + longToByteArray, + addDays, + addZeroBefore, + resizeArray, + isEmptyObject, + emptyJsObject, + sleep, + convertUTCDateToLocalDate, + writeToFile, + addToArrayIfUnique +} diff --git a/RVO41/flow/httprequest.js b/RVO41/flow/httprequest.js new file mode 100755 index 0000000..469c8cb --- /dev/null +++ b/RVO41/flow/httprequest.js @@ -0,0 +1,137 @@ +exports.id = 'httprequest'; +exports.title = 'HTTP Request'; +exports.group = 'HTTP'; +exports.color = '#5D9CEC'; +exports.input = true; +exports.version = '2.0.1'; +exports.output = 1; +exports.author = 'Peter Širka'; +exports.icon = 'cloud-upload'; + +exports.html = `
+
@(URL address)
+
+
+
@(HTTP method)
+
+
+
@(Serialization)
+
+
+
@(Download the content in chunks)
+
@(Keep persistent cookies)
+
@(Disable DNS cache)
+
@(Keep alive connection)
+
+
+
+
@(Custom headers)
+
@(Cookies)
+
+
+
+ +
+
+
+
@(User)
+
+
+
@(Password)
+
+
+
+
+
`; + +exports.readme = `# Request + +This component creates a request with received data. + +__Response:__ +\`\`\`javascript +{ + data: String, + headers: Object, + status: Number, + host: String +} +\`\`\` + +__Dynamic arguments__: +Are performed via FlowData repository and can be used for URL address or for custom headers/cookies/auth. Use \`repository\` component for creating of dynamic arguments. Dynamic values are replaced in the form \`{key}\`: + +- url address e.g. \`https://.../{key}/\` +- headers values e.g. \`{token}\` +- cookies values e.g. \`{token}\``; + +exports.install = function(instance) { + + var can = false; + var flags = null; + var cookies2 = null; + + instance.on('data', function(response) { + can && instance.custom.send(response); + }); + + instance.custom.send = function(response) { + var options = instance.options; + + var headers = null; + var cookies = null; + + options.headers && Object.keys(options.headers).forEach(function(key) { + !headers && (headers = {}); + headers[key] = response.arg(options.headers[key]); + }); + + if (options.username && options.userpassword) { + !headers && (headers = {}); + headers['Authorization'] = 'Basic ' + U.createBuffer(response.arg(options.username + ':' + options.userpassword)).toString('base64'); + } + + options.cookies && Object.keys(options.cookies).forEach(function(key) { + !cookies && (cookies = {}); + cookies[key] = response.arg(options.cookies[key]); + }); + + if (options.chunks) { + U.download(response.arg(options.url), flags, options.stringify === 'none' ? null : response.data, function(err, response) { + response.on('data', (chunks) => instance.send2(chunks)); + }, cookies || cookies2, headers); + } else { + U.request(response.arg(options.url), flags, options.stringify === 'none' ? null : response.data, 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) + instance.error(err, response); + }, cookies || cookies2, headers); + } + }; + + instance.reconfigure = function() { + var options = instance.options; + can = options.url && options.url && options.method && options.stringify ? true : false; + instance.status(can ? '' : 'Not configured', can ? undefined : 'red'); + + if (!can) + return; + + flags = []; + flags.push(options.method.toLowerCase()); + options.stringify === 'json' && flags.push('json'); + options.stringify === 'raw' && flags.push('raw'); + options.keepalive && flags.push('keepalive'); + !options.nodns && flags.push('dnscache'); + if (options.persistentcookies) { + flags.push('cookies'); + cookies2 = {}; + } else + cookies2 = null; + }; + + instance.on('options', instance.reconfigure); + instance.reconfigure(); +}; \ No newline at end of file diff --git a/RVO41/flow/httpresponse.js b/RVO41/flow/httpresponse.js new file mode 100755 index 0000000..160a3bb --- /dev/null +++ b/RVO41/flow/httpresponse.js @@ -0,0 +1,76 @@ +exports.id = 'httpresponse'; +exports.title = 'HTTP Response'; +exports.group = 'HTTP'; +exports.color = '#5D9CEC'; +exports.icon = 'arrow-right'; +exports.input = true; +exports.output = ['#666D76']; +exports.version = '2.0.0'; +exports.author = 'Martin Smola'; +exports.readme = `# HTTP response + +HTTP response will respond with data recieved using data-type set in Settings form or plain text if not set. Output is the message duration \`Number\` in seconds.`; + +exports.html = `
+
@(Response data-type)
+
JSON is by default.
+
`; + +exports.install = function(instance) { + + var dursum = 0; + var durcount = 0; + + instance.on('data', function(flowdata) { + + var ctrl = flowdata.repository.controller; + var data = flowdata.data; + + if (!ctrl) { + instance.throw('No controller to use for response!'); + return; + } + + durcount++; + dursum += ((new Date() - flowdata.begin) / 1000).floor(2); + setTimeout2(instance.id, instance.custom.duration, 500, 10); + + ctrl.$flowdata = flowdata; + + var datatype = instance.options.datatype || 'json'; + if (datatype === 'emptyresponse') + return ctrl.plain(''); + + if (datatype !== 'json' && typeof(data) !== 'string') { + instance.throw('Incorect type of data, expected string, got ' + typeof(data)); + ctrl.plain(data == null ? '' : data.toString()); + return; + } + + switch(datatype) { + case 'html': + ctrl.content(data, 'text/html'); + break; + case 'plain': + ctrl.plain(data); + break; + case 'xml': + ctrl.content(data, 'text/xml'); + break; + default: + ctrl.json(data); + break; + } + }); + + instance.on('service', function() { + dursum = 0; + durcount = 0; + }); + + instance.custom.duration = function() { + var avg = (dursum / durcount).floor(2); + instance.status(avg + ' sec.'); + instance.send2(0, avg); + }; +}; diff --git a/RVO41/flow/httproute.js b/RVO41/flow/httproute.js new file mode 100755 index 0000000..583a19d --- /dev/null +++ b/RVO41/flow/httproute.js @@ -0,0 +1,326 @@ +exports.id = 'httproute'; +exports.title = 'HTTP Route'; +exports.group = 'HTTP'; +exports.color = '#5D9CEC'; +exports.icon = 'globe'; +exports.input = false; +exports.output = ['#6CAC5A', '#37BC9B']; +exports.version = '1.2.3'; +exports.author = 'Martin Smola'; +exports.cloning = false; +exports.options = { method: 'GET', url: '', size: 5, cacheexpire: '5 minutes', cachepolicy: 0, timeout: 5 }; +exports.dateupdated = '2021-01-21 18:30d'; +exports.readme = `# HTTP route + +__Outputs__: +- first output: raw data (cache is empty or is disabled) +- second output: cached data + +If one of the outputs is disabled then automatic responce with code "503 service unavailable" is sent. + +When a request comes in bellow object is available at \`flowdata.data\`: + +\`\`\`javascript +{ + params: { id: '1' }, // params for dynamic routes, e.g. /test/{id} + query: { msg: 'Hello' }, // parsed query string, e.g. /test/1?msg=Hello + body: { test: 'OK' }, // object if json requests otherwise string + headers: {}, // headers data + session: {}, // session data + user: {}, // user data + files: [], // uploaded files + url: '/users/', // a relative URL address + referrer: '/', // referrer + mobile: false, // determines mobile device + robot: false, // determines search robots/crawlsers + language: 'en' // determines language +} +\`\`\` + +See [documentation for flags](https://docs.totaljs.com/latest/en.html#api~HttpRouteOptionsFlags~unauthorize). These method flags are set automatically e.g. \`get, post, put, patch or delete\` + +--- + +\`id:ROUTE_ID\` flag cannot be used since it's already used by this component internally`; + +exports.html = `
+
+ +
+ +
+
+
@(HTTP method)
+
+
+
@(URL address)
+
+
+
+
+
@(Additional flags)
+
@(Separate flags by comma e.g. json, authorize)
+
+
+
@(Max. request size)
+
@(In kB kilobytes)
+
+
+
@(Timeout)
+
@(In seconds.)
+
+
+
+
+
+
@(Automatically respond with 200 OK?)
+
@(If not checked you need to use HTTP response component to respond to the request.)
+
+
@(Custom headers)
+
@(Cookies)
+
+
+
+
+
+
@(Cache policy)
+
@(User instance must contain id property.)
+
+
+
@(Expiration)
+
@(E.g. 5 minutes)
+
+
+
+`; + +exports.install = function(instance) { + + var route; + + var uninstall = function(id) { + if (F.is4) { + route && route.remove(); + route = null; + } else + UNINSTALL('route', id); + }; + + instance.custom.emptyresponse = function(self) { + self.plain(); + }; + + instance.reconfigure = function() { + + var options = instance.options; + + if (!options.url) { + instance.status('Not configured', 'red'); + return; + } + + if (typeof(options.flags) === 'string') + options.flags = options.flags.split(',').trim(); + + uninstall('id:' + instance.id); + + var flags = options.flags || []; + + flags.push('id:' + instance.id); + + if (!F.is4) + flags.push(options.method.toLowerCase()); + + options.timeout && flags.push(options.timeout * 1000); + + // Make unique values + flags = flags.filter(function(v, i, a) { + if(F.is4 && v.toString().toLowerCase() === options.method.toLowerCase()) + return false; // remove method + return a.indexOf(v) === i; + }); + + options.flags = flags; + var handler = function() { + + if (instance.paused || (instance.isDisabled && (instance.isDisabled('output', 0) || instance.isDisabled('output', 1)))) { + instance.status('503 Service Unavailable'); + this.status = 503; + this.json(); + return; + } + + var key; + var self = this; + + if (instance.options.emptyresponse) { + instance.status('200 OK'); + setTimeout(instance.custom.emptyresponse, 100, self); + + if (instance.hasConnection(0)) { + var data = instance.make({ + query: self.query, + body: self.body, + session: self.session, + user: self.user, + files: self.files, + headers: self.req.headers, + url: self.url, + params: self.params + }); + instance.send2(0, data); + } + + return; + } + + switch (instance.options.cachepolicy) { + case 1: // URL + key = 'rro' + instance.id + self.url.hash(); + break; + case 2: // URL + query + case 3: // URL + query + user + key = self.url; + var keys = Object.keys(self.query); + keys.sort(); + for (var i = 0, length = keys.length; i < length; i++) + key += keys[i] + self.query[keys[i]] + '&'; + if (instance.options.cachepolicy === 3 && self.user) + key += 'iduser' + self.user.id; + key = 'rro' + instance.id + key.hash(); + break; + } + + if (key && F.cache.get2(key)) { + var data = instance.make(F.cache.get2(key)); + data.repository.controller = self; + instance.send2(1, data); + } else { + + var data = instance.make({ + query: self.query, + body: self.body, + session: self.session, + user: self.user, + files: self.files, + headers: self.req.headers, + url: self.url, + params: self.params, + mobile: self.mobile, + robot: self.robot, + referrer: self.referrer, + language: self.language + }); + + data.repository.controller = self; + instance.send2(0, data); + key && FINISHED(self.res, () => F.cache.set(key, self.$flowdata.data, instance.options.cacheexpire)); + } + }; + + if (F.is4) + route = ROUTE(options.method.toUpperCase() + ' ' + options.url, handler, flags, options.size || 5); + else + F.route(options.url, handler, flags, options.size || 5); + + instance.status('Listening', 'green'); + }; + + instance.reconfigure(); + instance.on('options', instance.reconfigure); + instance.on('close', function(){ + uninstall('id:' + instance.id); + }); +}; + +// check url exists +FLOW.trigger('httproutecheckurl', function(next, data) { + var url = data.url; + var method = data.method; + if (url[url.length - 1] !== '/') + url += '/'; + var exists = F.routes.web.findItem(r => r.urlraw === url && r.method === method); + next(exists != null); +}); + +exports.uninstall = function() { + FLOW.trigger('httproutecheckurl', null); +}; diff --git a/RVO41/flow/infosender.js b/RVO41/flow/infosender.js new file mode 100755 index 0000000..587724f --- /dev/null +++ b/RVO41/flow/infosender.js @@ -0,0 +1,81 @@ +exports.id = 'infosender'; +exports.title = 'Info sender'; +exports.version = '1.0.0'; +exports.group = 'Worksys'; +exports.color = '#2134B0'; +exports.input = 2; +exports.output = 1 +exports.icon = 'bolt'; + +const { networkInterfaces } = require('os'); + +exports.html = `
+
+
+
CSV Import
+
+
+
`; + +exports.readme = `# send all data to projects.worksys.io, required to monitor status of controller(unipi)`; + +exports.install = function(instance) { + + let id; + let allValues = {}; + let sendAllValuesInterval; + let configured = false; + + let now = new Date(); + console.log(exports.title, "INSTALLED", now.toLocaleString("sk-SK")); + + const nets = networkInterfaces(); + let ipAddresses = Object.create(null); // Or just '{}', an empty object + + for (const name of Object.keys(nets)) { + for (const net of nets[name]) { + // Skip over non-IPv4 and internal (i.e. 127.0.0.1) addresses + if (net.family === 'IPv4' && !net.internal) { + if (!ipAddresses[name]) { + ipAddresses[name] = []; + } + ipAddresses[name].push(net.address); + } + } + } + + function sendValues() { + if (!configured) return; + + if (Object.keys(allValues).length > 0) { + let dataToSend = { ...allValues }; + dataToSend.id = id; + dataToSend.ipAddresses = ipAddresses; + + instance.send(0, dataToSend); + + allValues = {}; + } + } + + instance.on("close", () => { + clearInterval(sendAllValuesInterval); + }) + + instance.on("0", _ => { + id = FLOW.GLOBALS.settings.project_id; + if (id) configured = true; + else console.log(exports.title, "InfoSender: Unable to send data, no id"); + }) + + instance.on("1", flowdata => { + allValues = { ...allValues, ...flowdata.data }; + //console.log("DATA RECEIVED", flowdata.data); + }) + + sendAllValuesInterval = setInterval(() => { + sendValues(); + }, 60000 * 3); + +} + diff --git a/RVO41/flow/modbus_reader.js b/RVO41/flow/modbus_reader.js new file mode 100755 index 0000000..d6d9dad --- /dev/null +++ b/RVO41/flow/modbus_reader.js @@ -0,0 +1,346 @@ +exports.id = 'modbus_reader'; +exports.title = 'Modbus reader'; +exports.version = '2.0.0'; +exports.group = 'Worksys'; +exports.color = '#2134B0'; +exports.input = 1; +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; +//number of phases inRVO +let phases; +//phases where voltage is 0 (set) +let noVoltage; +let energyToSwitchLamps; + +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.phases = this.buildPhases(); + + this.startSocket(); + } + + buildPhases = () => { + let a = []; + for (let i = 1; i <= phases; i++) { + a.push(`Phase_${i}_voltage`) + } + return a; + } + + startSocket = () => { + + let obj = this; + + if (this.socket) { + this.socket.removeAllListeners(); + this.socket = null; + } + + 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('Modbus_reader: Socket connection error', e); //'ECONNREFUSED' or 'ECONNRESET' ?? + }); + + this.socket.on('close', function() { + console.log('Modbus_reader: Socket connection closed - Waiting 10 seconds before connecting 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 we just start to loop devices from the beginning, or there is just 1 device in config, we wait whole timeoutInterval + if (this.indexInDeviceConfig == 0 || deviceConfig.length === 1) 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 (this.phases.includes(singleValue)) { + let l = singleValue.split("_"); + let phase = parseInt(l[1]); + + // console.log(values[singleValue], tbName); + + if (values[singleValue] == 0) { + noVoltage.add(phase); + sendNotification("modbus_reader: checkNullVoltage", tbName, "no_voltage_on_phase", { phase: phase }, "", SEND_TO.tb, instance, "voltage" + phase); + // console.log('no voltage') + } + else { + noVoltage.delete(phase); + // console.log('voltage detected') + sendNotification("modbus_reader: checkNullVoltage", tbName, "voltage_on_phase_restored", { phase: phase }, "", SEND_TO.tb, instance, "voltage" + phase); + } + } + }) + } + + /** + * function sends notification to slack and to tb, if EM total_power value changes more than numberOfNodes*15. This should show, that RVO lamps has been switched on or off + */ + lampSwitchNotification = (values) => { + + if (!values.hasOwnProperty("total_power")) return; + + const actualTotalPower = values.total_power; + + if (actualTotalPower > energyToSwitchLamps && 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 <= energyToSwitchLamps && 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; + } + + function main() { + + phases = FLOW.GLOBALS.settings.phases; + tbName = FLOW.GLOBALS.settings.rvoTbName; + noVoltage = FLOW.GLOBALS.settings.no_voltage; + energyToSwitchLamps = FLOW.GLOBALS.settings.energy_to_switch_lamps / 2.5; //half value is enought to show if lamps are turned on or off + if (deviceConfig.length) mainSocket = new SocketWithClients(); + else console.log("Modbus_reader: no modbus device in configuration"); + + // this notification is to show, that flow (unipi) has been restarted + sendNotification("modbus_reader", tbName, "flow_restart", {}, "", SEND_TO.slack, instance); + } + + instance.on("0", function(_) { + main(); + }) + +} + diff --git a/RVO41/flow/monitorconsumption.js b/RVO41/flow/monitorconsumption.js new file mode 100755 index 0000000..64cc58e --- /dev/null +++ b/RVO41/flow/monitorconsumption.js @@ -0,0 +1,156 @@ +exports.id = 'monitorconsumption'; +exports.title = 'Consumption'; +exports.version = '1.0.0'; +exports.author = 'Peter Širka'; +exports.group = 'Monitoring'; +exports.color = '#967ADC'; +exports.input = 0; +exports.output = 1; +exports.icon = 'bug'; +exports.options = { interval: 5000, enabled: true, monitorconsumption: true, monitorsize: true, monitorconnections: true, monitorfiles: true }; +exports.click = true; +exports.readme = `# Consumption monitoring + +This component measure CPU and memory consumption, open files and open connections of this application. It uses these Linux commands: \`ps\`, \`lsof\`, \`netstat\` and \`df\`. + +__Data Example__: + +\`\`\`javascript +{ + cpu: 0, // percentage + memory: 4096, // in bytes + size: 34303, // directory size in bytes + files: 34, // count of open files + connections: 343, // count of connections + uptime: '1-12:34:00' +} +\`\`\``; + +exports.html = `
+
+
+
@(Interval in milliseconds)
+
+
+
+
Monitor: Consumption + uptime
+
Monitor: Count of open files
+
Monitor: Count of open connections
+
Monitor: Directory size
+
`; + +exports.install = function(instance) { + + var current = { cpu: 0, memory: 0, files: 0, connections: 0, size: 0, uptime: '', counter: 0 }; + var tproc = null; + var Exec = require('child_process').exec; + var reg_empty = /\s{2,}/g; + var reg_appdisksize = /^[\d.,]+/; + + instance.custom.run = function() { + + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + + var arr = []; + + // Get CPU and Memory consumption + instance.options.monitorconsumption && arr.push(function(next) { + Exec('ps -p {0} -o %cpu,rss,etime'.format(process.pid), function(err, response) { + + if (err) { + instance.throw(err); + } else { + var line = response.split('\n')[1]; + line = line.trim().replace(reg_empty, ' ').split(' '); + var cpu = line[0].parseFloat(); + current.cpu = cpu.floor(1); + current.memory = line[1].parseInt2() * 1024; // kB to bytes + current.uptime = line[2]; + } + + next(); + }); + }); + + // Get count of open files + instance.options.monitorfiles && arr.push(function(next) { + Exec('lsof -a -p {0} | wc -l'.format(process.pid), function(err, response) { + if (err) + instance.throw(err); + else + current.files = response.trim().parseInt2(); + next(); + }); + }); + + // Get count of opened network connections + instance.options.monitorconnections && arr.push(function(next) { + Exec('netstat -an | grep :{0} | wc -l'.format(F.port), function(err, response) { + if (err) { + instance.throw(err); + } else { + current.connections = response.trim().parseInt2() - 1; + if (current.connections < 0) + current.connections = 0; + } + next(); + }); + }); + + // Get directory size + instance.options.monitorsize && current.counter % 5 !== 0 && arr.push(function(next) { + Exec('du -hsb ' + process.cwd(), function(err, response) { + if (err) { + instance.throw(err); + } else { + var match = response.trim().match(reg_appdisksize); + match && (current.size = match.toString().trim().parseInt2()); + } + next(); + }); + }); + + arr.async(function() { + + tproc && clearTimeout(tproc); + + if (instance.options.enabled) { + tproc = setTimeout(instance.custom.run, instance.options.interval); + instance.send2(current); + } + + instance.custom.status(); + current.counter++; + }); + }; + + instance.custom.status = function() { + if (instance.options.enabled) + instance.status('{0}% / {1}'.format(current.cpu, current.memory.filesize())); + else + instance.status('Disabled', 'red'); + }; + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + + if (instance.options.enabled) { + current.counter = 0; + instance.custom.run(); + } + + }); + + instance.on('close', function() { + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + }); + + setTimeout(instance.custom.run, 1000); +}; \ No newline at end of file diff --git a/RVO41/flow/monitordisk.js b/RVO41/flow/monitordisk.js new file mode 100755 index 0000000..f4fdaa0 --- /dev/null +++ b/RVO41/flow/monitordisk.js @@ -0,0 +1,96 @@ +exports.id = 'monitordisk'; +exports.title = 'Disk'; +exports.version = '1.0.0'; +exports.author = 'Peter Širka'; +exports.group = 'Monitoring'; +exports.color = '#F6BB42'; +exports.output = 1; +exports.icon = 'hdd-o'; +exports.click = true; +exports.options = { interval: 8000, path: '/', enabled: true }; +exports.readme = `# Disk monitoring + +This component monitors disk \`bytes\` consumption in Linux systems. It uses \`df\` command. + +__Data Example__: + +\`\`\`javascript +{ + total: 474549649408, + used: 39125245952, + free: 411294994432 +} +\`\`\``; + +exports.html = `
+
+
+
@(Interval in milliseconds)
+
+
+
@(Path)
+
+
+
`; + +exports.install = function(instance) { + + var current = { total: 0, used: 0, free: 0, path: '', type: '', percentUsed: 0 }; + var tproc = null; + + instance.custom.run = function() { + + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + + if (!instance.options.enabled) + return; + + require('child_process').exec('df -hTB1 ' + instance.options.path, function(err, response) { + + tproc = setTimeout(instance.custom.run, instance.options.interval); + + if (err) { + instance.error(err); + return; + } + + response.parseTerminal(function(line) { + if (line[0][0] !== '/') + return; + current.total = line[2].parseInt(); + current.free = line[4].parseInt(); + current.used = line[3].parseInt(); + current.path = instance.options.path || '/'; + current.type = line[1]; + current.percentUsed = line[5]; + instance.custom.status(); + instance.send2(current); + }); + }); + }; + + instance.custom.status = function() { + if (instance.options.enabled) + instance.status(current.free.filesize() + ' / ' + current.total.filesize()); + else + instance.status('Disabled', 'red'); + }; + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + instance.options.enabled && instance.custom.run(); + }); + + instance.on('close', function() { + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + }); + + setTimeout(instance.custom.run, 1000); +}; \ No newline at end of file diff --git a/RVO41/flow/monitormemory.js b/RVO41/flow/monitormemory.js new file mode 100755 index 0000000..2decbc4 --- /dev/null +++ b/RVO41/flow/monitormemory.js @@ -0,0 +1,87 @@ +exports.id = 'monitormemory'; +exports.title = 'Memory'; +exports.version = '1.0.0'; +exports.author = 'Peter Širka'; +exports.group = 'Monitoring'; +exports.color = '#F6BB42'; +exports.output = 1; +exports.click = true; +exports.icon = 'microchip'; +exports.options = { interval: 8000, enabled: true }; +exports.readme = `# Memory monitoring + +This component monitors memory \`bytes\` consumption in Linux systems. It uses \`free\` command. + +__Data Example__: + +\`\`\`javascript +{ + total: 33558769664, + used: 1998868480, + free: 2653708288 +} +\`\`\``; + +exports.html = `
+
+
+
@(Interval in milliseconds)
+
+
+
`; + +exports.install = function(instance) { + + var current = { total: 0, used: 0, free: 0 }; + var tproc = null; + + instance.custom.run = function() { + + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + + if (!instance.options.enabled) + return; + + require('child_process').exec('free -b -t', function(err, response) { + + tproc = setTimeout(instance.custom.run, instance.options.interval); + + if (err) { + instance.error(err); + return; + } + + var memory = response.split('\n')[1].match(/\d+/g); + current.total = memory[0].parseInt(); + current.used = memory[1].parseInt() - memory[3].parseInt(); + current.free = current.total - current.used; + instance.custom.status(); + instance.send2(current); + }); + }; + + instance.custom.status = function() { + if (instance.options.enabled) + instance.status(current.free.filesize() + ' / ' + current.total.filesize()); + else + instance.status('Disabled', 'red'); + }; + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + instance.options.enabled && instance.custom.run(); + }); + + instance.on('close', function() { + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + }); + + setTimeout(instance.custom.run, 1000); +}; \ No newline at end of file diff --git a/RVO41/flow/nodesdb_changecheck.js b/RVO41/flow/nodesdb_changecheck.js new file mode 100755 index 0000000..9adab62 --- /dev/null +++ b/RVO41/flow/nodesdb_changecheck.js @@ -0,0 +1,77 @@ +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 = 2; +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); + } + } + + //kedze do slacku posielame stringy, na cloud musime previest vsetky stringy spat na objekty: + // Funkcia na parsovanie všetkých reťazcov v poli + const parseArray = (arr) => { + return arr.map(jsonString => JSON.parse(jsonString)); + }; + + 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); + if (FLOW.GLOBALS.settings.send_changed_node_numbers) instance.send(1, { aktualneNody: parseArray(zmenene), originalne: parseArray(Array.from(set2)) }); + } + 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/RVO41/flow/show_dbdata.js b/RVO41/flow/show_dbdata.js new file mode 100755 index 0000000..1e23ff7 --- /dev/null +++ b/RVO41/flow/show_dbdata.js @@ -0,0 +1,243 @@ +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 = 8; +exports.output = 1; + +const { exec } = require('child_process'); + +exports.install = 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 }) + }) + instance.on("5", _ => { + exec("sudo tail -n 25 monitor.txt", (err, stdout, stderr) => { + if (err || stderr) instance.send(0, { err, stderr }); + else instance.send(0, stdout); + }) + }) + instance.on("6", _ => { + exec("sudo tail -n 25 err.txt", (err, stdout, stderr) => { + if (err || stderr) instance.send(0, { err, stderr }); + else instance.send(0, stdout); + }) + }) + instance.on("7", _ => { + instance.send(0, FLOW.deviceStatus); + }) +}; + + +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/RVO41/flow/slack_filter.js b/RVO41/flow/slack_filter.js new file mode 100755 index 0000000..6618523 --- /dev/null +++ b/RVO41/flow/slack_filter.js @@ -0,0 +1,188 @@ +exports.id = 'slack_filter'; +exports.title = 'Slack Filter'; +exports.group = 'Citysys'; +exports.color = '#30E193'; +exports.input = 2; +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 = `
+
+
+
@(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('0', 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']['en']; + 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"] = []; + } + + instance.options.name = FLOW.GLOBALS.settings.rvo_name; + if (instance.options.name) { + instance.status('Running'); + running = true; + } else { + instance.status('Please run options again', 'red'); + running = false; + } + } catch (e) { + instance.error('Citysys connector: ' + e.message); + } + }; + + instance.on('options', instance.reconfigure); + + instance.on("1", _ => { + instance.reconfigure(); + }) +}; diff --git a/RVO41/flow/thermometer.js b/RVO41/flow/thermometer.js new file mode 100755 index 0000000..fc7074d --- /dev/null +++ b/RVO41/flow/thermometer.js @@ -0,0 +1,99 @@ +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 = 5;//minutes +let NUMBER_OF_FAILURES_TO_SEND_ERROR = 13; + +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) => { + + 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); + setTimeout(main, 20000); + }) +}; diff --git a/RVO41/flow/trigger.js b/RVO41/flow/trigger.js new file mode 100755 index 0000000..27545a8 --- /dev/null +++ b/RVO41/flow/trigger.js @@ -0,0 +1,79 @@ +exports.id = 'trigger'; +exports.title = 'Trigger'; +exports.group = 'Inputs'; +exports.color = '#F6BB42'; +exports.click = true; +exports.output = 1; +exports.version = '1.1.0'; +exports.author = 'Martin Smola'; +exports.icon = 'play'; + +exports.html = `
+
@(Data type (String by default))
+
@(Data)
+
Trigger 5s after initialization.
+
@(Useful when there's a need to run certain flow when the app restarts, etc.)
+
`; + +exports.readme = `# Trigger + +- Clicking on the component starts the chain +- Settings allows to set a data-type and a value`; + +exports.install = function(instance) { + + var value; + + instance.on('click', () => instance.send2(value)); + + instance.reconfigure = function() { + var options = instance.options; + value = null; + switch (options.datatype) { + case 'integer': + value = options.data.parseInt2('error'); + value = value === 'error' ? NaN : value; + break; + case 'float': + value = options.data.parseFloat2('error'); + value = value === 'error' ? NaN : value; + break; + case 'date': + options.data = options.data.toString(); + var num = options.data.parseInt('error'); + num === 'error' && (num = options.data.parseDate('error')); + num === 'error' && (num = null); + value = num ? new Date(num).toUTCString() : num; + break; + case 'object': + try { + value = (new Function('return ' + options.data))(); + } catch (e) { + instance.error(e); + } + break; + case 'boolean': + value = options.data.parseBoolean(); + break; + case 'buffer': + try { + value = U.createBuffer(options.data); + } catch (e) { + instance.error(e); + } + break; + case 'string': + default: + value = '' + (options.data || ''); + break; + } + }; + + instance.on('options', instance.reconfigure); + instance.reconfigure(); + + if (instance.options.restart) + setTimeout(function(){ + instance.send2(value); + }, 5000); +}; diff --git a/RVO41/flow/variables.txt b/RVO41/flow/variables.txt new file mode 100755 index 0000000..e69de29 diff --git a/RVO41/flow/virtualwirein.js b/RVO41/flow/virtualwirein.js new file mode 100755 index 0000000..38a4e42 --- /dev/null +++ b/RVO41/flow/virtualwirein.js @@ -0,0 +1,43 @@ +exports.id = 'virtualwirein'; +exports.title = 'Virtual wire in'; +exports.version = '1.0.0'; +exports.author = 'Martin Smola'; +exports.color = '#303E4D'; +exports.icon = 'sign-in'; +exports.input = false; +exports.output = 1; +exports.options = {}; +exports.readme = `# Virtual wire in + +When the wires between the components are mess it's time to use Virtual wire.`; + +exports.html = `
+
@(Wire name)
+
+`; + +exports.install = function(instance) { + + instance.custom.reconfigure = function(options){ + if (instance.options.wirename) { + instance.status(instance.options.wirename); + } else + instance.status('Not configured', 'red'); + }; + + ON('virtualwire', function(wirename, flowdata){ + if (instance.options.wirename && instance.options.wirename === wirename) + instance.send(flowdata); + }); + + instance.on('options', instance.custom.reconfigure); + instance.custom.reconfigure(); +}; diff --git a/RVO41/flow/virtualwireout.js b/RVO41/flow/virtualwireout.js new file mode 100755 index 0000000..94a1e4f --- /dev/null +++ b/RVO41/flow/virtualwireout.js @@ -0,0 +1,41 @@ +exports.id = 'virtualwireout'; +exports.title = 'Virtual wire out'; +exports.version = '1.0.0'; +exports.author = 'Martin Smola'; +exports.color = '#303E4D'; +exports.icon = 'sign-out'; +exports.input = true; +exports.options = {}; +exports.readme = `# Virtual wire out + +When the wires between the components are mess it's time to use Virtual wire.`; + +exports.html = `
+
@(Wire name)
+
+`; + +exports.install = function(instance) { + + instance.custom.reconfigure = function(){ + if (instance.options.wirename) { + instance.status(instance.options.wirename); + } else + instance.status('Not configured', 'red'); + }; + + instance.on('data', function(flowdata) { + EMIT('virtualwire', instance.options.wirename, flowdata); + }); + + instance.on('options', instance.custom.reconfigure); + instance.custom.reconfigure(); +}; diff --git a/RVO41/flow/wsmqttpublish.js b/RVO41/flow/wsmqttpublish.js new file mode 100755 index 0000000..0eba804 --- /dev/null +++ b/RVO41/flow/wsmqttpublish.js @@ -0,0 +1,448 @@ +exports.id = 'wsmqttpublish'; +exports.title = 'WS MQTT publish'; +exports.group = 'MQTT'; +exports.color = '#888600'; +exports.version = '1.0.2'; +exports.icon = 'sign-out'; +exports.input = 2; +exports.output = 3; +exports.options = { host: 'tb-stage.worksys.io', port: 1883, clientid: "", username: "" }; + +exports.html = `
+
+
+
Hostname or IP address (if not empty - setting will override db setting)
+
+
+
Port
+
+
+
+
+
@(Client id)
+
+
+
@(Username)
+
+
+
`; + + +exports.readme = ` +# WS MQTT Publish + +Version 1.0.3. + +Added: +- database collections, +- 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 = { + debug: 0, + rpcCall: 1, + services: 2 +} + +//CONFIG +let createTelemetryBackup = true; +let saveTelemetryOnError = true;//backup_on_failure overrides this value +//------------------------ + +let rollers; +if (createTelemetryBackup) rollers = require('streamroller'); + +const noSqlFileSizeLimit = 4194304;//use 5MB - 4194304 +let insertNoSqlCounter = 0; +let insertBackupNoSqlCounter = 0; +let processingData = false; + +let backup_on_failure = false;//== saveTelemetryOnError - create backup client 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; + +process.on('uncaughtException', function(err) { + + errLogger.error('uncaughtException:', err.message) + errLogger.error(err.stack); + + //TODO + //send to service + + //process.exit(1); +}) + +const nosql = NOSQL('tbdata'); +const nosqlBackup = NOSQL('/backup/tbdata'); + + +exports.install = function(instance) { + + var client; + var opts; + var clientReady = false; + + // wsmqtt status for notification purposes on projects.worksys.io database + let wsmqttName = null; + let sendWsStatusVar = null; + let wsmqtt_status = 'disconnected'; + + 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'; + } + + function sendWsStatus() { + instance.send(SEND_TO.services, { [wsmqttName]: wsmqtt_status }); + } + + + function main() { + if (!FLOW.dbLoaded) return; + + loadSettings(); + clearInterval(sendWsStatus); + sendWsStatusVar = setInterval(sendWsStatus, 180000); + } + + //set opts according to db settings + function loadSettings() { + + if (instance.options.host !== "") { + //override settings from database + var o = instance.options; + opts = { + host: o.host, + port: o.port, + clientId: o.clientid, + username: o.username, + rejectUnauthorized: false, + resubscribe: false + }; + + wsmqttName = getWsmqttName(o.host); + + console.log("wsmqttpublich -> loadSettings from instance.options", instance.options); + } + else { + + const SETTINGS = FLOW.GLOBALS.settings; + backup_on_failure = SETTINGS.backup_on_failure; + saveTelemetryOnError = backup_on_failure; + + restore_from_backup = SETTINGS.restore_from_backup; + restore_backup_wait = SETTINGS.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; + + opts = { + host: mqtt_host, + port: mqtt_port, + keepalive: 10, + clientId: mqtt_clientid, + username: mqtt_username, + rejectUnauthorized: false, + resubscribe: false + }; + + wsmqttName = getWsmqttName(mqtt_host); + } + + connectToTbServer(); + } + + function connectToTbServer() { + 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"); + //monitor.info("MQTT client connected"); + + sendClientError = true; + clientReady = true; + wsmqtt_status = 'connected'; + }); + + client.on('reconnect', function() { + instance.status("Reconnecting", "yellow"); + clientReady = false; + }); + + client.on('message', function(topic, message) { + // message is type of buffer + message = message.toString(); + if (message[0] === '{') { + TRY(function() { + + message = JSON.parse(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 } }); + } + + }, () => instance.debug('MQTT: Error parsing data', message)); + } + + instance.send(SEND_TO.rpcCall, { "topic": topic, "content": message }); + }); + + client.on('close', function() { + clientReady = false; + wsmqtt_status = 'disconnected'; + + instance.status("Disconnected", "red"); + instance.send(SEND_TO.debug, { "message": "Client CLOSE signal received !" }); + }); + + client.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; + wsmqtt_status = 'disconnected'; + }); + + } + + + instance.on("0", _ => { + main(); + }) + + + instance.on('1', function(data) { + + if (clientReady) { + //do we have some data in backup file? if any, process data from database + if (saveTelemetryOnError) { + //read telemetry data and send back to server + if (!processingData) processDataFromDatabase(); + } + + let stringifiedJson = JSON.stringify(data.data); + client.publish("v1/gateway/telemetry", stringifiedJson, { qos: 1 }); + + //backup telemetry + if (createTelemetryBackup) { + data.data.id = UID(); + nosqlBackup.insert(data.data); + + insertBackupNoSqlCounter++; + if (insertBackupNoSqlCounter > 150) { + let options = { compress: true }; + let path = __dirname + "/../databases/backup/tbdata.nosql"; + var stream = new rollers.RollingFileStream(path, noSqlFileSizeLimit, 150, options); + stream.write(""); + stream.end(); + + insertBackupNoSqlCounter = 0; + } + } + + } + 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 (saveTelemetryOnError) { + //create new file from tbdata.nosql, if file size exceeds given limit, and clear tbdata.nosql + makeBackupFromDbFile(); + + //write to tb + data.data.id = UID(); + nosql.insert(data.data); + } + } + }); + + + instance.close = function(done) { + if (clientReady) { + client.end(); + clearInterval(sendWsStatusVar); + } + }; + + + function getDbBackupFileCounter(type) { + var files = fs.readdirSync(__dirname + "/../databases"); + + let counter = 0; + for (var i = 0; i < files.length; i++) { + + if (files[i] == "tbdata.nosql") continue; + + if (files[i].endsWith(".nosql")) { + + let pos = files[i].indexOf("."); + if (pos > -1) { + + let fileCounter = counter; + let firstDigit = files[i].slice(0, pos); + + fileCounter = parseInt(firstDigit); + if (isNaN(fileCounter)) fileCounter = 0; + //console.log("getDbBackupFileCounter digit:", files[i], firstDigit, fileCounter, isNaN(fileCounter), type); + + if (type == "max") { + if (fileCounter > counter) { + counter = fileCounter; + } + } + else if (type == "min") { + if (counter == 0) counter = fileCounter; + + if (fileCounter < counter) { + counter = fileCounter; + } + } + } + } + + } + + if (type == "max") counter++; + + return counter; + } + + const makeBackupFromDbFile = async () => { + + if (!saveTelemetryOnError) return; + + //to avoid large file: tbdata.nosql + + //init value is 0! + if (insertNoSqlCounter > 0) { + --insertNoSqlCounter; + return; + } + + insertNoSqlCounter = 100; + + let source = __dirname + "/../databases/tbdata.nosql"; + + var stats = fs.statSync(source); + var fileSizeInBytes = stats.size; + + if (fileSizeInBytes > noSqlFileSizeLimit) { + + let counter = 1; + counter = getDbBackupFileCounter("max"); + + let destination = __dirname + "/../databases/" + counter + "." + "tbdata.nosql"; + + //make backup file + fs.copyFileSync(source, destination); + //fs.renameSync(p, p + "." + counter); + + //clear tbdata.nosql + fs.writeFileSync(source, ""); + fs.truncateSync(source, 0); + + } + } + + const processDataFromDatabase = async () => { + + if (restore_from_backup <= 0) return; + + //calculate diff + const now = new Date(); + let currentTime = now.getTime(); + let diff = currentTime - lastRestoreTime; + + if ((diff / 1000) < restore_backup_wait) { + //console.log("*********restore_backup_wait", diff, restore_backup_wait); + return; + } + + processingData = true; + + //get filename to process + let counter = getDbBackupFileCounter("min"); + + //we have some backup files + let dataBase = 'tbdata'; + + var nosql; + if (counter == 0) dataBase = 'tbdata'; + else dataBase = counter + "." + 'tbdata'; + + nosql = NOSQL(dataBase); + + //select all data - use limit restore_from_backup + let records = await promisifyBuilder(nosql.find().take(restore_from_backup)); + + for (let i = 0; i < records.length; i++) { + if (clientReady) { + + let item = records[i]; + let id = item.id; + + if (id !== undefined) { + //console.log("------------processDataFromDatabase - remove", id, dataBase, i); + + try { + + let message = JSON.parse(JSON.stringify(item)); + delete message.id; + + client.publish("v1/gateway/telemetry", JSON.stringify(message), { qos: 1 }); + + //remove from database + await promisifyBuilder(nosql.remove().where("id", id)); + + } catch (error) { + //process error + console.log("processDataFromDatabase", error); + } + + } + + } + else { + processingData = false; + return; + } + } + + if (records.length > 0) { + //clean backup file + if (counter > 0) nosql.clean(); + } + + //no data in db, remove + if (records.length == 0) { + if (counter > 0) nosql.drop(); + } + + const d = new Date(); + lastRestoreTime = d.getTime(); + + processingData = false; + + } + + instance.on('options', main); + //instance.reconfigure(); +}; diff --git a/RVO41/monitor.txt b/RVO41/monitor.txt new file mode 100755 index 0000000..572ff49 --- /dev/null +++ b/RVO41/monitor.txt @@ -0,0 +1,435 @@ +[2025-10-03T14:46:35.581] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-03T14:46:40.931] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-03T14:46:40.936] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-03T14:46:40.937] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-03T14:46:40.938] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-03T14:46:40.942] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-03T14:46:40.943] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-10-04T05:24:00.943Z +[2025-10-03T14:46:40.945] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-10-03T16:58:00.945Z +[2025-10-03T14:46:40.945] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:24', name: 'luxOff' }, + { value: 1, start_time: '18:58', name: 'luxOn' } +] +[2025-10-03T14:46:40.947] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-10-03T14:46:40.948] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-03T14:46:40.948] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-03T14:46:40.951] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-03T14:46:40.951] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-10-04T05:24:00.951Z +[2025-10-03T14:46:40.952] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-10-03T16:58:00.952Z +[2025-10-03T14:46:40.953] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:24', name: 'luxOff' }, + { value: 1, start_time: '18:58', name: 'luxOn' } +] +[2025-10-03T14:46:40.954] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-10-03T14:46:40.955] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-03T14:46:40.955] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-03T14:46:40.957] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-03T14:46:40.958] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-10-04T05:24:00.958Z +[2025-10-03T14:46:40.959] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-10-03T16:58:00.959Z +[2025-10-03T14:46:40.959] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:24', name: 'luxOff' }, + { value: 1, start_time: '18:58', name: 'luxOn' } +] +[2025-10-03T14:46:40.960] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-10-03T14:46:40.963] [INFO] monitorLogs - tasks created: 238 +[2025-10-03T14:46:40.965] [INFO] monitorLogs - -->FLOW bol spustený JzwxZXOvDj1bVrN4nkW5ZNA8qdyBl3MRKLpGPgaQ 2025-08-08 +[2025-10-03T14:46:45.984] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-03T18:45:15.443] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-03T18:45:15.448] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-03T18:45:15.452] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-04T03:46:42.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-04 03:46:42 +[2025-10-04T06:37:40.299] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-04T06:37:40.303] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-04T06:37:40.305] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-04T18:37:35.420] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-04T18:37:35.422] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-04T18:37:35.424] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-05T03:46:44.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-05 03:46:44 +[2025-10-05T06:40:05.567] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-05T06:40:05.573] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-05T06:40:05.575] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-05T18:40:01.066] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-05T18:40:01.084] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-05T18:40:01.086] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-06T03:46:45.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-06 03:46:45 +[2025-10-06T06:47:28.564] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-06T06:47:28.568] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-06T06:47:28.570] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-06T18:29:51.733] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-06T18:29:51.736] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-06T18:29:51.738] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-07T03:46:46.027] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-07 03:46:46 +[2025-10-07T06:44:53.747] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-07T06:44:53.750] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-07T06:44:53.752] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-07T18:34:46.429] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-07T18:34:46.431] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-07T18:34:46.433] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-08T03:46:47.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-08 03:46:47 +[2025-10-08T06:44:44.808] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-08T06:44:44.811] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-08T06:44:44.813] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-08T18:32:06.848] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-08T18:32:06.850] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-08T18:32:06.852] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-09T03:46:49.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-09 03:46:49 +[2025-10-09T06:54:38.373] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-09T06:54:38.376] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-09T06:54:38.378] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-09T16:51:44.301] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-09T16:51:49.658] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-09T16:51:49.663] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-09T16:51:49.664] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-09T16:51:49.664] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-09T16:51:49.669] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T16:51:49.670] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-10-10T05:32:00.669Z +[2025-10-09T16:51:49.671] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-10-09T16:45:00.671Z +[2025-10-09T16:51:49.672] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T16:51:49.673] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-10-09T16:51:49.674] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-09T16:51:49.675] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-09T16:51:49.677] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T16:51:49.678] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-10-10T05:32:00.678Z +[2025-10-09T16:51:49.679] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-10-09T16:45:00.679Z +[2025-10-09T16:51:49.679] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T16:51:49.680] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-10-09T16:51:49.681] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-09T16:51:49.682] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-09T16:51:49.684] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T16:51:49.685] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-10-10T05:32:00.684Z +[2025-10-09T16:51:49.685] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-10-09T16:45:00.685Z +[2025-10-09T16:51:49.686] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T16:51:49.687] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-10-09T16:51:49.689] [INFO] monitorLogs - tasks created: 238 +[2025-10-09T16:51:49.692] [INFO] monitorLogs - -->FLOW bol spustený JzwxZXOvDj1bVrN4nkW5ZNA8qdyBl3MRKLpGPgaQ 2025-08-08 +[2025-10-09T16:51:54.711] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-09T18:27:24.964] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-09T18:27:24.968] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-09T18:27:24.970] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-09T19:04:16.541] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-09T19:04:21.886] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-09T19:04:21.891] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-09T19:04:21.892] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-09T19:04:21.893] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-09T19:04:21.897] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T19:04:21.898] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-10-10T05:32:00.897Z +[2025-10-09T19:04:21.900] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-10-10T16:45:00.899Z +[2025-10-09T19:04:21.900] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T19:04:21.902] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-10-09T19:04:21.903] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-09T19:04:21.904] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-09T19:04:21.906] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T19:04:21.907] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-10-10T05:32:00.907Z +[2025-10-09T19:04:21.908] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-10-10T16:45:00.908Z +[2025-10-09T19:04:21.909] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T19:04:21.910] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-10-09T19:04:21.910] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-09T19:04:21.911] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-09T19:04:21.913] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T19:04:21.914] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-10-10T05:32:00.914Z +[2025-10-09T19:04:21.915] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-10-10T16:45:00.914Z +[2025-10-09T19:04:21.915] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T19:04:21.916] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-10-09T19:04:21.918] [INFO] monitorLogs - tasks created: 238 +[2025-10-09T19:04:21.921] [INFO] monitorLogs - -->FLOW bol spustený JzwxZXOvDj1bVrN4nkW5ZNA8qdyBl3MRKLpGPgaQ 2025-08-08 +[2025-10-09T19:04:26.924] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-10T03:04:23.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-10 03:04:23 +[2025-10-10T06:54:32.653] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-10T06:54:32.657] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-10T06:54:32.659] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-10T18:24:21.133] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-10T18:24:21.136] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-10T18:24:21.138] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-11T03:04:24.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-11 03:04:24 +[2025-10-11T06:54:23.268] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-11T06:54:23.270] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-11T06:54:23.273] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-11T18:26:42.471] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-11T18:26:42.473] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-11T18:26:42.475] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-12T03:04:26.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-12 03:04:26 +[2025-10-12T06:51:45.002] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-12T06:51:45.005] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-12T06:51:45.007] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-12T18:24:04.208] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-12T18:24:04.211] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-12T18:24:04.213] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-13T03:04:27.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-13 03:04:27 +[2025-10-13T06:51:35.551] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-13T06:51:35.553] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-13T06:51:35.555] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-13T18:26:26.304] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-13T18:26:26.310] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-13T18:26:26.312] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-14T03:04:28.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-14 03:04:28 +[2025-10-14T06:53:57.988] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-14T06:53:57.992] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-14T06:53:57.994] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-14T18:18:45.578] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-14T18:18:45.580] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-14T18:18:45.582] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-15T03:04:30.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-15 03:04:30 +[2025-10-15T06:58:50.761] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-15T06:58:50.763] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-15T06:58:50.765] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-15T11:26:56.541] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-15T11:27:01.911] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-15T11:27:01.916] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-15T11:27:01.917] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-15T11:27:01.918] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-15T11:27:01.922] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-15T11:27:01.924] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-10-16T05:41:00.923Z +[2025-10-15T11:27:01.925] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-10-15T16:33:00.925Z +[2025-10-15T11:27:01.926] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:41', name: 'luxOff' }, + { value: 1, start_time: '18:33', name: 'luxOn' } +] +[2025-10-15T11:27:01.927] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-10-15T11:27:01.928] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-15T11:27:01.928] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-15T11:27:01.931] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-15T11:27:01.931] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-10-16T05:41:00.931Z +[2025-10-15T11:27:01.932] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-10-15T16:33:00.932Z +[2025-10-15T11:27:01.933] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:41', name: 'luxOff' }, + { value: 1, start_time: '18:33', name: 'luxOn' } +] +[2025-10-15T11:27:01.934] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-10-15T11:27:01.935] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-15T11:27:01.935] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-15T11:27:01.937] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-15T11:27:01.938] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-10-16T05:41:00.938Z +[2025-10-15T11:27:01.939] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-10-15T16:33:00.939Z +[2025-10-15T11:27:01.940] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:41', name: 'luxOff' }, + { value: 1, start_time: '18:33', name: 'luxOn' } +] +[2025-10-15T11:27:01.941] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-10-15T11:27:01.943] [INFO] monitorLogs - tasks created: 238 +[2025-10-15T11:27:01.945] [INFO] monitorLogs - -->FLOW bol spustený JzwxZXOvDj1bVrN4nkW5ZNA8qdyBl3MRKLpGPgaQ 2025-10-08 +[2025-10-15T11:27:06.949] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-15T18:18:41.739] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-15T18:18:41.744] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-15T18:18:41.747] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor diff --git a/RVO41/package-lock.json b/RVO41/package-lock.json new file mode 100755 index 0000000..cc5cfd9 --- /dev/null +++ b/RVO41/package-lock.json @@ -0,0 +1,2125 @@ +{ + "name": "emptyproject", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "emptyproject", + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "bitwise": "^2.1.0", + "easy-crc": "0.0.2", + "jsmodbus": "^4.0.6", + "log4js": "^6.3.0", + "mqtt": "^4.2.6", + "nodemailer": "^6.9.7", + "serialport": "^9.2.8", + "total.js": "^3.4.13" + } + }, + "node_modules/@serialport/binding-abstract": { + "version": "9.2.3", + "resolved": "https://registry.npmjs.org/@serialport/binding-abstract/-/binding-abstract-9.2.3.tgz", + "integrity": "sha512-cQs9tbIlG3P0IrOWyVirqlhWuJ7Ms2Zh9m2108z6Y5UW/iVj6wEOiW8EmK9QX9jmJXYllE7wgGgvVozP5oCj3w==", + "dependencies": { + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/binding-mock": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/binding-mock/-/binding-mock-9.2.4.tgz", + "integrity": "sha512-dpEhACCs44oQhh6ajJfJdvQdK38Vq0N4W6iD/gdplglDCK7qXRQCMUjJIeKdS/HSEiWkC3bwumUhUufdsOyT4g==", + "dependencies": { + "@serialport/binding-abstract": "9.2.3", + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/bindings": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/@serialport/bindings/-/bindings-9.2.8.tgz", + "integrity": "sha512-hSLxTe0tADZ3LMMGwvEJWOC/TaFQTyPeFalUCsJ1lSQ0k6bPF04JwrtB/C81GetmDBTNRY0GlD0SNtKCc7Dr5g==", + "hasInstallScript": true, + "dependencies": { + "@serialport/binding-abstract": "9.2.3", + "@serialport/parser-readline": "9.2.4", + "bindings": "^1.5.0", + "debug": "^4.3.2", + "nan": "^2.15.0", + "prebuild-install": "^7.0.0" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-byte-length": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-byte-length/-/parser-byte-length-9.2.4.tgz", + "integrity": "sha512-sQD/iw4ZMU3xW9PLi0/GlvU6Y623jGeWecbMkO7izUo/6P7gtfv1c9ikd5h0kwL8AoAOpQA1lxdHIKox+umBUg==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-cctalk": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-cctalk/-/parser-cctalk-9.2.4.tgz", + "integrity": "sha512-T4TU5vQMwmo9AB3gQLFDWbfJXlW5jd9guEsB/nqKjFHTv0FXPdZ7DQ2TpSp8RnHWxU3GX6kYTaDO20BKzc8GPQ==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-delimiter": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-delimiter/-/parser-delimiter-9.2.4.tgz", + "integrity": "sha512-4nvTAoYAgkxFiXrkI+3CA49Yd43CODjeszh89EK+I9c8wOZ+etZduRCzINYPiy26g7zO+GRAb9FoPCsY+sYcbQ==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-inter-byte-timeout": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-inter-byte-timeout/-/parser-inter-byte-timeout-9.2.4.tgz", + "integrity": "sha512-SOAdvr0oBQIOCXX198hiTlxs4JTKg9j5piapw5tNq52fwDOWdbYrFneT/wN04UTMKaDrJuEvXq6T4rv4j7nJ5A==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-readline": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-readline/-/parser-readline-9.2.4.tgz", + "integrity": "sha512-Z1/qrZTQUVhNSJP1hd9YfDvq0o7d87rNwAjjRKbVpa7Qi51tG5BnKt43IV3NFMyBlVcRe0rnIb3tJu57E0SOwg==", + "dependencies": { + "@serialport/parser-delimiter": "9.2.4" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-ready": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-ready/-/parser-ready-9.2.4.tgz", + "integrity": "sha512-Pyi94Itjl6qAURwIZr/gmZpMAyTmKXThm6vL5DoAWGQjcRHWB0gwv2TY2v7N+mQLJYUKU3cMnvnATXxHm7xjxw==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-regex": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-regex/-/parser-regex-9.2.4.tgz", + "integrity": "sha512-sI/cVvPOYz+Dbv4ZdnW16qAwvXiFf/1pGASQdbveRTlgJDdz7sRNlCBifzfTN2xljwvCTZYqiudKvDdC1TepRQ==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/stream": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/stream/-/stream-9.2.4.tgz", + "integrity": "sha512-bLye8Ub4vUFQGmkh8qEqehr7SE7EJs2yDs0h9jzuL5oKi+F34CFmWkEErO8GAOQ8YNn7p6b3GxUgs+0BrHHDZQ==", + "dependencies": { + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "node_modules/are-we-there-yet": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", + "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/base64-js": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", + "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==" + }, + "node_modules/bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "dependencies": { + "file-uri-to-path": "1.0.0" + } + }, + "node_modules/bitwise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/bitwise/-/bitwise-2.1.0.tgz", + "integrity": "sha512-XKgAhMXCh4H/3oNwAHAsAO0iC89s9cOiumgYwSHjSobGWxYjv62YhkL9QEdvGP151xypCtMlAfKK79GEcd2eRQ==" + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/bl/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/buffer": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz", + "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==", + "dependencies": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + }, + "node_modules/buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" + }, + "node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, + "node_modules/code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/commist": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/commist/-/commist-1.1.0.tgz", + "integrity": "sha512-rraC8NXWOEjhADbZe9QBNzLAN5Q3fsTPQtBV+fEVj6xKIgDgNiEVE6ZNfHpZOqfQ21YUzfVNUXLOEZquYvQPPg==", + "dependencies": { + "leven": "^2.1.0", + "minimist": "^1.1.0" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "node_modules/concat-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", + "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", + "engines": [ + "node >= 6.0" + ], + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.0.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/concat-stream/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" + }, + "node_modules/core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "node_modules/crc": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/crc/-/crc-3.4.0.tgz", + "integrity": "sha512-ycVC2+4/DLgXXq7QweYi2znhqDuZz6P5TQXnkQo8v15XY/5p/IWeZwsSE31Ifo8w15b8TWLsqhXOjXyilHuQxw==" + }, + "node_modules/date-format": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.11.tgz", + "integrity": "sha512-VS20KRyorrbMCQmpdl2hg5KaOUsda1RbnsJg461FfrcyCUg+pkd0b40BSW4niQyTheww4DBXQnS7HwSrKkipLw==", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" + }, + "node_modules/detect-libc": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz", + "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==", + "engines": { + "node": ">=8" + } + }, + "node_modules/duplexify": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.2.tgz", + "integrity": "sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw==", + "dependencies": { + "end-of-stream": "^1.4.1", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1", + "stream-shift": "^1.0.0" + } + }, + "node_modules/duplexify/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/easy-crc": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/easy-crc/-/easy-crc-0.0.2.tgz", + "integrity": "sha512-h6eqIdhJRe0p271/xZJbM/0klCi13mW5IB7ZEzEGH11yV4QXWAkD4yPErz0fXdhFrd6sZ4Q1k5Iky2kMsMNePw==" + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" + }, + "node_modules/flatted": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", + "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==" + }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, + "node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "node_modules/gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha512-14x4kjc6lkD3ltw589k0NrPD6cCNTD6CWoVUNpB85+DrtONoZn+Rug6xZU5RvSC4+TZPxA5AnBibQYAvZn41Hg==", + "dependencies": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "node_modules/github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==" + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" + }, + "node_modules/has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" + }, + "node_modules/help-me": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/help-me/-/help-me-3.0.0.tgz", + "integrity": "sha512-hx73jClhyk910sidBB7ERlnhMlFsJJIBqSVMFDwPN8o2v9nmp5KgLq1Xz1Bf1fCMMZ6mPrX159iG0VLy/fPMtQ==", + "dependencies": { + "glob": "^7.1.6", + "readable-stream": "^3.6.0" + } + }, + "node_modules/help-me/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, + "node_modules/is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==", + "dependencies": { + "number-is-nan": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "node_modules/js-sdsl": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz", + "integrity": "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/js-sdsl" + } + }, + "node_modules/jsmodbus": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/jsmodbus/-/jsmodbus-4.0.6.tgz", + "integrity": "sha512-gCmjoaERErK5Rn9Lu/BN07fY13MoWV7JKgGzrnkPlQPdPxYcwDhLtYcmpFFpZ4J9NPZZBSezi1UkLZO/DnNppA==", + "dependencies": { + "crc": "3.4.0", + "debug": "^3.1.0" + }, + "bin": { + "jsmodbus": "bin/jsmodbus.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/jsmodbus/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/leven": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", + "integrity": "sha1-wuep93IJTe6dNCAq6KzORoeHVYA=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/log4js": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.5.2.tgz", + "integrity": "sha512-DXtpNtt+KDOMT7RHUDIur/WsSA3rntlUh9Zg4XCdV42wUuMmbFkl38+LZ92Z5QvQA7mD5kAVkLiBSEH/tvUB8A==", + "dependencies": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "flatted": "^3.2.5", + "rfdc": "^1.3.0", + "streamroller": "^3.1.1" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" + }, + "node_modules/mqtt": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/mqtt/-/mqtt-4.3.7.tgz", + "integrity": "sha512-ew3qwG/TJRorTz47eW46vZ5oBw5MEYbQZVaEji44j5lAUSQSqIEoul7Kua/BatBW0H0kKQcC9kwUHa1qzaWHSw==", + "dependencies": { + "commist": "^1.0.0", + "concat-stream": "^2.0.0", + "debug": "^4.1.1", + "duplexify": "^4.1.1", + "help-me": "^3.0.0", + "inherits": "^2.0.3", + "lru-cache": "^6.0.0", + "minimist": "^1.2.5", + "mqtt-packet": "^6.8.0", + "number-allocator": "^1.0.9", + "pump": "^3.0.0", + "readable-stream": "^3.6.0", + "reinterval": "^1.1.0", + "rfdc": "^1.3.0", + "split2": "^3.1.0", + "ws": "^7.5.5", + "xtend": "^4.0.2" + }, + "bin": { + "mqtt": "bin/mqtt.js", + "mqtt_pub": "bin/pub.js", + "mqtt_sub": "bin/sub.js" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/mqtt-packet": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/mqtt-packet/-/mqtt-packet-6.10.0.tgz", + "integrity": "sha512-ja8+mFKIHdB1Tpl6vac+sktqy3gA8t9Mduom1BA75cI+R9AHnZOiaBQwpGiWnaVJLDGRdNhQmFaAqd7tkKSMGA==", + "dependencies": { + "bl": "^4.0.2", + "debug": "^4.1.1", + "process-nextick-args": "^2.0.1" + } + }, + "node_modules/mqtt/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/nan": { + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.16.0.tgz", + "integrity": "sha512-UdAqHyFngu7TfQKsCBgAA6pWDkT8MAO7d0jyOecVhN5354xbLqdn8mV9Tat9gepAupm0bt2DbeaSC8vS52MuFA==" + }, + "node_modules/napi-build-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", + "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==" + }, + "node_modules/node-abi": { + "version": "3.22.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.22.0.tgz", + "integrity": "sha512-u4uAs/4Zzmp/jjsD9cyFYDXeISfUWaAVWshPmDZOFOv4Xl4SbzTXm53I04C2uRueYJ+0t5PEtLH/owbn2Npf/w==", + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/nodemailer": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.7.tgz", + "integrity": "sha512-rUtR77ksqex/eZRLmQ21LKVH5nAAsVicAtAYudK7JgwenEDZ0UIQ1adUGqErz7sMkWYxWTTU1aeP2Jga6WQyJw==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "dependencies": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "node_modules/number-allocator": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/number-allocator/-/number-allocator-1.0.14.tgz", + "integrity": "sha512-OrL44UTVAvkKdOdRQZIJpLkAdjXGTRda052sN4sO77bKEzYYqWKMBjQvrJFzqygI99gL6Z4u2xctPW1tB8ErvA==", + "dependencies": { + "debug": "^4.3.1", + "js-sdsl": "4.3.0" + } + }, + "node_modules/number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/prebuild-install": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.0.tgz", + "integrity": "sha512-CNcMgI1xBypOyGqjp3wOc8AAo1nMhZS3Cwd3iHIxOdAUbb+YxdNuM4Z5iIrZ8RLvOsf3F3bl7b7xGq6DjQoNYA==", + "dependencies": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^1.0.1", + "node-abi": "^3.3.0", + "npmlog": "^4.0.1", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + }, + "bin": { + "prebuild-install": "bin.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/reinterval": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reinterval/-/reinterval-1.1.0.tgz", + "integrity": "sha1-M2Hs+jymwYKDOA3Qu5VG85D17Oc=" + }, + "node_modules/rfdc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==" + }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/serialport": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/serialport/-/serialport-9.2.8.tgz", + "integrity": "sha512-FsWpMQgSJxi93JgWl5xM1f9/Z8IjRJuaUEoHqLf8FPBLw7gMhInuHOBhI2onQufWIYPGTz3H3oGcu1nCaK1EfA==", + "dependencies": { + "@serialport/binding-mock": "9.2.4", + "@serialport/bindings": "9.2.8", + "@serialport/parser-byte-length": "9.2.4", + "@serialport/parser-cctalk": "9.2.4", + "@serialport/parser-delimiter": "9.2.4", + "@serialport/parser-inter-byte-timeout": "9.2.4", + "@serialport/parser-readline": "9.2.4", + "@serialport/parser-ready": "9.2.4", + "@serialport/parser-regex": "9.2.4", + "@serialport/stream": "9.2.4", + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "node_modules/split2": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", + "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", + "dependencies": { + "readable-stream": "^3.0.0" + } + }, + "node_modules/split2/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==" + }, + "node_modules/streamroller": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.1.1.tgz", + "integrity": "sha512-iPhtd9unZ6zKdWgMeYGfSBuqCngyJy1B/GPi/lTpwGpa3bajuX30GjUVd0/Tn/Xhg0mr4DOSENozz9Y06qyonQ==", + "dependencies": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "fs-extra": "^10.1.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dependencies": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/tar-fs": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "dependencies": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tar-stream/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/total.js": { + "version": "3.4.13", + "resolved": "https://registry.npmjs.org/total.js/-/total.js-3.4.13.tgz", + "integrity": "sha512-lAH4gEixlPFbrE3xfKADAcHfO79IFq2wKa9GTsrgRzIR5MTg3mNH7+4IxvX1pK8faoYb/0oYSJ1YTsAa5hIFFQ==", + "bin": { + "total": "bin/totaljs", + "total.js": "bin/totaljs", + "totaljs": "bin/totaljs", + "totalpackage": "bin/tpm", + "tpm": "bin/tpm" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, + "node_modules/universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "node_modules/wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "node_modules/ws": { + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } + }, + "dependencies": { + "@serialport/binding-abstract": { + "version": "9.2.3", + "resolved": "https://registry.npmjs.org/@serialport/binding-abstract/-/binding-abstract-9.2.3.tgz", + "integrity": "sha512-cQs9tbIlG3P0IrOWyVirqlhWuJ7Ms2Zh9m2108z6Y5UW/iVj6wEOiW8EmK9QX9jmJXYllE7wgGgvVozP5oCj3w==", + "requires": { + "debug": "^4.3.2" + } + }, + "@serialport/binding-mock": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/binding-mock/-/binding-mock-9.2.4.tgz", + "integrity": "sha512-dpEhACCs44oQhh6ajJfJdvQdK38Vq0N4W6iD/gdplglDCK7qXRQCMUjJIeKdS/HSEiWkC3bwumUhUufdsOyT4g==", + "requires": { + "@serialport/binding-abstract": "9.2.3", + "debug": "^4.3.2" + } + }, + "@serialport/bindings": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/@serialport/bindings/-/bindings-9.2.8.tgz", + "integrity": "sha512-hSLxTe0tADZ3LMMGwvEJWOC/TaFQTyPeFalUCsJ1lSQ0k6bPF04JwrtB/C81GetmDBTNRY0GlD0SNtKCc7Dr5g==", + "requires": { + "@serialport/binding-abstract": "9.2.3", + "@serialport/parser-readline": "9.2.4", + "bindings": "^1.5.0", + "debug": "^4.3.2", + "nan": "^2.15.0", + "prebuild-install": "^7.0.0" + } + }, + "@serialport/parser-byte-length": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-byte-length/-/parser-byte-length-9.2.4.tgz", + "integrity": "sha512-sQD/iw4ZMU3xW9PLi0/GlvU6Y623jGeWecbMkO7izUo/6P7gtfv1c9ikd5h0kwL8AoAOpQA1lxdHIKox+umBUg==" + }, + "@serialport/parser-cctalk": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-cctalk/-/parser-cctalk-9.2.4.tgz", + "integrity": "sha512-T4TU5vQMwmo9AB3gQLFDWbfJXlW5jd9guEsB/nqKjFHTv0FXPdZ7DQ2TpSp8RnHWxU3GX6kYTaDO20BKzc8GPQ==" + }, + "@serialport/parser-delimiter": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-delimiter/-/parser-delimiter-9.2.4.tgz", + "integrity": "sha512-4nvTAoYAgkxFiXrkI+3CA49Yd43CODjeszh89EK+I9c8wOZ+etZduRCzINYPiy26g7zO+GRAb9FoPCsY+sYcbQ==" + }, + "@serialport/parser-inter-byte-timeout": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-inter-byte-timeout/-/parser-inter-byte-timeout-9.2.4.tgz", + "integrity": "sha512-SOAdvr0oBQIOCXX198hiTlxs4JTKg9j5piapw5tNq52fwDOWdbYrFneT/wN04UTMKaDrJuEvXq6T4rv4j7nJ5A==" + }, + "@serialport/parser-readline": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-readline/-/parser-readline-9.2.4.tgz", + "integrity": "sha512-Z1/qrZTQUVhNSJP1hd9YfDvq0o7d87rNwAjjRKbVpa7Qi51tG5BnKt43IV3NFMyBlVcRe0rnIb3tJu57E0SOwg==", + "requires": { + "@serialport/parser-delimiter": "9.2.4" + } + }, + "@serialport/parser-ready": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-ready/-/parser-ready-9.2.4.tgz", + "integrity": "sha512-Pyi94Itjl6qAURwIZr/gmZpMAyTmKXThm6vL5DoAWGQjcRHWB0gwv2TY2v7N+mQLJYUKU3cMnvnATXxHm7xjxw==" + }, + "@serialport/parser-regex": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-regex/-/parser-regex-9.2.4.tgz", + "integrity": "sha512-sI/cVvPOYz+Dbv4ZdnW16qAwvXiFf/1pGASQdbveRTlgJDdz7sRNlCBifzfTN2xljwvCTZYqiudKvDdC1TepRQ==" + }, + "@serialport/stream": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/stream/-/stream-9.2.4.tgz", + "integrity": "sha512-bLye8Ub4vUFQGmkh8qEqehr7SE7EJs2yDs0h9jzuL5oKi+F34CFmWkEErO8GAOQ8YNn7p6b3GxUgs+0BrHHDZQ==", + "requires": { + "debug": "^4.3.2" + } + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==" + }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "are-we-there-yet": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", + "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "base64-js": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", + "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==" + }, + "bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "requires": { + "file-uri-to-path": "1.0.0" + } + }, + "bitwise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/bitwise/-/bitwise-2.1.0.tgz", + "integrity": "sha512-XKgAhMXCh4H/3oNwAHAsAO0iC89s9cOiumgYwSHjSobGWxYjv62YhkL9QEdvGP151xypCtMlAfKK79GEcd2eRQ==" + }, + "bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "requires": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "buffer": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz", + "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==", + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" + }, + "chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==" + }, + "commist": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/commist/-/commist-1.1.0.tgz", + "integrity": "sha512-rraC8NXWOEjhADbZe9QBNzLAN5Q3fsTPQtBV+fEVj6xKIgDgNiEVE6ZNfHpZOqfQ21YUzfVNUXLOEZquYvQPPg==", + "requires": { + "leven": "^2.1.0", + "minimist": "^1.1.0" + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "concat-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", + "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.0.2", + "typedarray": "^0.0.6" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "crc": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/crc/-/crc-3.4.0.tgz", + "integrity": "sha512-ycVC2+4/DLgXXq7QweYi2znhqDuZz6P5TQXnkQo8v15XY/5p/IWeZwsSE31Ifo8w15b8TWLsqhXOjXyilHuQxw==" + }, + "date-format": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.11.tgz", + "integrity": "sha512-VS20KRyorrbMCQmpdl2hg5KaOUsda1RbnsJg461FfrcyCUg+pkd0b40BSW4niQyTheww4DBXQnS7HwSrKkipLw==" + }, + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "requires": { + "ms": "2.1.2" + } + }, + "decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "requires": { + "mimic-response": "^3.1.0" + } + }, + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==" + }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" + }, + "detect-libc": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz", + "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==" + }, + "duplexify": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.2.tgz", + "integrity": "sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw==", + "requires": { + "end-of-stream": "^1.4.1", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1", + "stream-shift": "^1.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "easy-crc": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/easy-crc/-/easy-crc-0.0.2.tgz", + "integrity": "sha512-h6eqIdhJRe0p271/xZJbM/0klCi13mW5IB7ZEzEGH11yV4QXWAkD4yPErz0fXdhFrd6sZ4Q1k5Iky2kMsMNePw==" + }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "requires": { + "once": "^1.4.0" + } + }, + "expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==" + }, + "file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" + }, + "flatted": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", + "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==" + }, + "fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, + "fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha512-14x4kjc6lkD3ltw589k0NrPD6cCNTD6CWoVUNpB85+DrtONoZn+Rug6xZU5RvSC4+TZPxA5AnBibQYAvZn41Hg==", + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==" + }, + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" + }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" + }, + "help-me": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/help-me/-/help-me-3.0.0.tgz", + "integrity": "sha512-hx73jClhyk910sidBB7ERlnhMlFsJJIBqSVMFDwPN8o2v9nmp5KgLq1Xz1Bf1fCMMZ6mPrX159iG0VLy/fPMtQ==", + "requires": { + "glob": "^7.1.6", + "readable-stream": "^3.6.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==", + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "js-sdsl": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz", + "integrity": "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==" + }, + "jsmodbus": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/jsmodbus/-/jsmodbus-4.0.6.tgz", + "integrity": "sha512-gCmjoaERErK5Rn9Lu/BN07fY13MoWV7JKgGzrnkPlQPdPxYcwDhLtYcmpFFpZ4J9NPZZBSezi1UkLZO/DnNppA==", + "requires": { + "crc": "3.4.0", + "debug": "^3.1.0" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "requires": { + "ms": "^2.1.1" + } + } + } + }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, + "leven": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", + "integrity": "sha1-wuep93IJTe6dNCAq6KzORoeHVYA=" + }, + "log4js": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.5.2.tgz", + "integrity": "sha512-DXtpNtt+KDOMT7RHUDIur/WsSA3rntlUh9Zg4XCdV42wUuMmbFkl38+LZ92Z5QvQA7mD5kAVkLiBSEH/tvUB8A==", + "requires": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "flatted": "^3.2.5", + "rfdc": "^1.3.0", + "streamroller": "^3.1.1" + } + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "requires": { + "yallist": "^4.0.0" + } + }, + "mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==" + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==" + }, + "mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" + }, + "mqtt": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/mqtt/-/mqtt-4.3.7.tgz", + "integrity": "sha512-ew3qwG/TJRorTz47eW46vZ5oBw5MEYbQZVaEji44j5lAUSQSqIEoul7Kua/BatBW0H0kKQcC9kwUHa1qzaWHSw==", + "requires": { + "commist": "^1.0.0", + "concat-stream": "^2.0.0", + "debug": "^4.1.1", + "duplexify": "^4.1.1", + "help-me": "^3.0.0", + "inherits": "^2.0.3", + "lru-cache": "^6.0.0", + "minimist": "^1.2.5", + "mqtt-packet": "^6.8.0", + "number-allocator": "^1.0.9", + "pump": "^3.0.0", + "readable-stream": "^3.6.0", + "reinterval": "^1.1.0", + "rfdc": "^1.3.0", + "split2": "^3.1.0", + "ws": "^7.5.5", + "xtend": "^4.0.2" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "mqtt-packet": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/mqtt-packet/-/mqtt-packet-6.10.0.tgz", + "integrity": "sha512-ja8+mFKIHdB1Tpl6vac+sktqy3gA8t9Mduom1BA75cI+R9AHnZOiaBQwpGiWnaVJLDGRdNhQmFaAqd7tkKSMGA==", + "requires": { + "bl": "^4.0.2", + "debug": "^4.1.1", + "process-nextick-args": "^2.0.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "nan": { + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.16.0.tgz", + "integrity": "sha512-UdAqHyFngu7TfQKsCBgAA6pWDkT8MAO7d0jyOecVhN5354xbLqdn8mV9Tat9gepAupm0bt2DbeaSC8vS52MuFA==" + }, + "napi-build-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", + "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==" + }, + "node-abi": { + "version": "3.22.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.22.0.tgz", + "integrity": "sha512-u4uAs/4Zzmp/jjsD9cyFYDXeISfUWaAVWshPmDZOFOv4Xl4SbzTXm53I04C2uRueYJ+0t5PEtLH/owbn2Npf/w==", + "requires": { + "semver": "^7.3.5" + } + }, + "nodemailer": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.7.tgz", + "integrity": "sha512-rUtR77ksqex/eZRLmQ21LKVH5nAAsVicAtAYudK7JgwenEDZ0UIQ1adUGqErz7sMkWYxWTTU1aeP2Jga6WQyJw==" + }, + "npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "number-allocator": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/number-allocator/-/number-allocator-1.0.14.tgz", + "integrity": "sha512-OrL44UTVAvkKdOdRQZIJpLkAdjXGTRda052sN4sO77bKEzYYqWKMBjQvrJFzqygI99gL6Z4u2xctPW1tB8ErvA==", + "requires": { + "debug": "^4.3.1", + "js-sdsl": "4.3.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==" + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==" + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==" + }, + "prebuild-install": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.0.tgz", + "integrity": "sha512-CNcMgI1xBypOyGqjp3wOc8AAo1nMhZS3Cwd3iHIxOdAUbb+YxdNuM4Z5iIrZ8RLvOsf3F3bl7b7xGq6DjQoNYA==", + "requires": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^1.0.1", + "node-abi": "^3.3.0", + "npmlog": "^4.0.1", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + } + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + } + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "reinterval": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reinterval/-/reinterval-1.1.0.tgz", + "integrity": "sha1-M2Hs+jymwYKDOA3Qu5VG85D17Oc=" + }, + "rfdc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==" + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "requires": { + "lru-cache": "^6.0.0" + } + }, + "serialport": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/serialport/-/serialport-9.2.8.tgz", + "integrity": "sha512-FsWpMQgSJxi93JgWl5xM1f9/Z8IjRJuaUEoHqLf8FPBLw7gMhInuHOBhI2onQufWIYPGTz3H3oGcu1nCaK1EfA==", + "requires": { + "@serialport/binding-mock": "9.2.4", + "@serialport/bindings": "9.2.8", + "@serialport/parser-byte-length": "9.2.4", + "@serialport/parser-cctalk": "9.2.4", + "@serialport/parser-delimiter": "9.2.4", + "@serialport/parser-inter-byte-timeout": "9.2.4", + "@serialport/parser-readline": "9.2.4", + "@serialport/parser-ready": "9.2.4", + "@serialport/parser-regex": "9.2.4", + "@serialport/stream": "9.2.4", + "debug": "^4.3.2" + } + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==" + }, + "simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "requires": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "split2": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", + "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", + "requires": { + "readable-stream": "^3.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==" + }, + "streamroller": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.1.1.tgz", + "integrity": "sha512-iPhtd9unZ6zKdWgMeYGfSBuqCngyJy1B/GPi/lTpwGpa3bajuX30GjUVd0/Tn/Xhg0mr4DOSENozz9Y06qyonQ==", + "requires": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "fs-extra": "^10.1.0" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" + }, + "tar-fs": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "requires": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "requires": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "total.js": { + "version": "3.4.13", + "resolved": "https://registry.npmjs.org/total.js/-/total.js-3.4.13.tgz", + "integrity": "sha512-lAH4gEixlPFbrE3xfKADAcHfO79IFq2wKa9GTsrgRzIR5MTg3mNH7+4IxvX1pK8faoYb/0oYSJ1YTsAa5hIFFQ==" + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, + "universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==" + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "requires": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "ws": { + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "requires": {} + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } + } +} diff --git a/RVO41/package.json b/RVO41/package.json new file mode 100755 index 0000000..e524d7c --- /dev/null +++ b/RVO41/package.json @@ -0,0 +1,29 @@ +{ + "name": "emptyproject", + "description": "Total.js empty project.", + "version": "1.0.0", + "main": "debug.js", + "dependencies": { + "bitwise": "^2.1.0", + "easy-crc": "0.0.2", + "jsmodbus": "^4.0.6", + "log4js": "^6.3.0", + "mqtt": "^4.2.6", + "nodemailer": "^6.9.7", + "serialport": "^9.2.8", + "total.js": "^3.4.13" + }, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "https://github.com/totaljs/emptyproject-flow" + }, + "keywords": [ + "empty", + "project" + ], + "author": "Peter Širka", + "license": "MIT" +} diff --git a/RVO41/release.js b/RVO41/release.js new file mode 100755 index 0000000..02d52ff --- /dev/null +++ b/RVO41/release.js @@ -0,0 +1,15 @@ +// =================================================== +// FOR PRODUCTION +// Total.js - framework for Node.js platform +// https://www.totaljs.com +// =================================================== + +const options = {'ip':'0.0.0.0', 'port':12345}; + +// options.ip = '127.0.0.1'; +// options.port = parseInt(process.argv[2]); +// options.config = { name: 'Total.js' }; +// options.sleep = 3000; + +require('total.js').http('release', options); +// require('total.js').cluster.http(5, 'release', options); diff --git a/RVO41/release.js.json b/RVO41/release.js.json new file mode 100755 index 0000000..8532e53 --- /dev/null +++ b/RVO41/release.js.json @@ -0,0 +1,34 @@ +{ + "pid": 416, + "stats": [ + { + "id": null, + "version": { + "node": "v14.18.1", + "total": "3.4.13", + "app": "1.0.0" + }, + "pid": 416, + "thread": "", + "mode": "release", + "overload": 0, + "date": "2025-10-16T00:25:52.722Z", + "memory": 24.27, + "rm": 0, + "fm": 0, + "wm": 0, + "mm": 0, + "om": 4, + "em": 0, + "dbrm": 0, + "dbwm": 0, + "usage": 0, + "requests": 8, + "pending": 0, + "errors": 0, + "timeouts": 0, + "uptime": 900, + "online": 0 + } + ] +} \ No newline at end of file diff --git a/RVO41/report_data.log b/RVO41/report_data.log new file mode 100755 index 0000000..87a02a6 --- /dev/null +++ b/RVO41/report_data.log @@ -0,0 +1,238 @@ +{ + "name": "rvo_senica_41_ip117", + "time": "2025-10-15T10:27:07.559Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_41_ip117", + "time": "2025-10-15T11:27:07.555Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_41_ip117", + "time": "2025-10-15T12:27:07.556Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_41_ip117", + "time": "2025-10-15T13:27:07.556Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_41_ip117", + "time": "2025-10-15T14:27:07.556Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_41_ip117", + "time": "2025-10-15T15:27:07.556Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_41_ip117", + "time": "2025-10-15T17:46:08.111Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "41/9_1L_3182_NEMA", + "41/13_1L_3183_NEMA", + "41/8_1L_3518_IP65", + "41/3_1L_3548_IP65", + "41/5_1L_3559_IP65" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_41_ip117", + "time": "2025-10-15T18:46:08.111Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "41/9_1L_3182_NEMA", + "41/13_1L_3183_NEMA", + "41/8_1L_3518_IP65", + "41/3_1L_3548_IP65", + "41/5_1L_3559_IP65" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_41_ip117", + "time": "2025-10-15T19:46:08.112Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "41/9_1L_3182_NEMA", + "41/13_1L_3183_NEMA", + "41/8_1L_3518_IP65", + "41/3_1L_3548_IP65", + "41/5_1L_3559_IP65" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_41_ip117", + "time": "2025-10-15T20:46:08.112Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "41/9_1L_3182_NEMA", + "41/13_1L_3183_NEMA", + "41/8_1L_3518_IP65", + "41/3_1L_3548_IP65", + "41/5_1L_3559_IP65" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_41_ip117", + "time": "2025-10-15T21:46:08.114Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "41/9_1L_3182_NEMA", + "41/13_1L_3183_NEMA", + "41/8_1L_3518_IP65", + "41/3_1L_3548_IP65", + "41/5_1L_3559_IP65" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_41_ip117", + "time": "2025-10-15T22:46:08.115Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "41/9_1L_3182_NEMA", + "41/13_1L_3183_NEMA", + "41/8_1L_3518_IP65", + "41/3_1L_3548_IP65", + "41/5_1L_3559_IP65" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_41_ip117", + "time": "2025-10-15T23:46:08.115Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "41/9_1L_3182_NEMA", + "41/13_1L_3183_NEMA", + "41/8_1L_3518_IP65", + "41/3_1L_3548_IP65", + "41/5_1L_3559_IP65" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +} \ No newline at end of file From 1b29cafd5f02dc70208de318495a2e6300ff8d43 Mon Sep 17 00:00:00 2001 From: Jakub Klena Date: Thu, 16 Oct 2025 02:26:41 +0200 Subject: [PATCH 23/30] Backup senica-RVO42 on 16.10.2025 --- RVO42/addSwitch.py | 36 + RVO42/cloud_topic.py | 76 + RVO42/config | 12 + RVO42/createNode.py | 43 + RVO42/databases/accelerometer_db.js | 3055 ++++++++++++++++ RVO42/databases/modbus_config.js | 114 + RVO42/databases/nodes.table | 17 + .../nodes_original/nodes_original.table | 1 + RVO42/databases/notifications.table | 41 + RVO42/databases/pins.table | 15 + RVO42/databases/relays.table | 6 + RVO42/databases/settings.table | 2 + RVO42/databases/tbdata.nosql | 4 + RVO42/databases/tbdatacloud.nosql | 3 + RVO42/databases/total_energy.js | 38 + RVO42/debug.js | 16 + RVO42/err.txt | 77 + RVO42/flow/audit_test_panel.csv | 48 + RVO42/flow/cloudmqttconnect.js | 357 ++ RVO42/flow/cmd_manager.js | 3071 ++++++++++++++++ RVO42/flow/code.js | 90 + RVO42/flow/comment.js | 11 + RVO42/flow/count.js | 60 + RVO42/flow/csv_import.js | 175 + RVO42/flow/db_connector.js | 286 ++ RVO42/flow/db_init.js | 113 + RVO42/flow/debug.js | 100 + RVO42/flow/designer.json | 3102 +++++++++++++++++ RVO42/flow/dido_controller.js | 1486 ++++++++ RVO42/flow/helper/DataToTbHandler.js | 187 + RVO42/flow/helper/ErrorToServiceHandler.js | 91 + RVO42/flow/helper/db_helper.js | 44 + RVO42/flow/helper/logger.js | 30 + RVO42/flow/helper/md5.js | 5 + RVO42/flow/helper/notification_reporter.js | 121 + RVO42/flow/helper/register.js | 144 + RVO42/flow/helper/serialport_helper.js | 99 + RVO42/flow/helper/suncalc.js | 317 ++ RVO42/flow/helper/utils.js | 161 + RVO42/flow/httprequest.js | 137 + RVO42/flow/httpresponse.js | 76 + RVO42/flow/httproute.js | 326 ++ RVO42/flow/infosender.js | 81 + RVO42/flow/modbus_reader.js | 346 ++ RVO42/flow/monitorconsumption.js | 156 + RVO42/flow/monitordisk.js | 96 + RVO42/flow/monitormemory.js | 87 + RVO42/flow/nodesdb_changecheck.js | 77 + RVO42/flow/notifikacie.csv | 31 + RVO42/flow/show_dbdata.js | 243 ++ RVO42/flow/slack_filter.js | 188 + RVO42/flow/thermometer.js | 99 + RVO42/flow/trigger.js | 79 + RVO42/flow/variables.txt | 0 RVO42/flow/virtualwirein.js | 43 + RVO42/flow/virtualwireout.js | 41 + RVO42/flow/wsmqttpublish.js | 448 +++ RVO42/monitor.txt | 400 +++ RVO42/package-lock.json | 2125 +++++++++++ RVO42/package.json | 29 + RVO42/release.js | 15 + RVO42/release.js.json | 34 + RVO42/report_data.log | 196 ++ 63 files changed, 19007 insertions(+) create mode 100755 RVO42/addSwitch.py create mode 100755 RVO42/cloud_topic.py create mode 100755 RVO42/config create mode 100755 RVO42/createNode.py create mode 100755 RVO42/databases/accelerometer_db.js create mode 100755 RVO42/databases/modbus_config.js create mode 100755 RVO42/databases/nodes.table create mode 100755 RVO42/databases/nodes_original/nodes_original.table create mode 100755 RVO42/databases/notifications.table create mode 100755 RVO42/databases/pins.table create mode 100755 RVO42/databases/relays.table create mode 100755 RVO42/databases/settings.table create mode 100755 RVO42/databases/tbdata.nosql create mode 100755 RVO42/databases/tbdatacloud.nosql create mode 100755 RVO42/databases/total_energy.js create mode 100755 RVO42/debug.js create mode 100755 RVO42/err.txt create mode 100755 RVO42/flow/audit_test_panel.csv create mode 100755 RVO42/flow/cloudmqttconnect.js create mode 100755 RVO42/flow/cmd_manager.js create mode 100755 RVO42/flow/code.js create mode 100755 RVO42/flow/comment.js create mode 100755 RVO42/flow/count.js create mode 100755 RVO42/flow/csv_import.js create mode 100755 RVO42/flow/db_connector.js create mode 100755 RVO42/flow/db_init.js create mode 100755 RVO42/flow/debug.js create mode 100755 RVO42/flow/designer.json create mode 100755 RVO42/flow/dido_controller.js create mode 100755 RVO42/flow/helper/DataToTbHandler.js create mode 100755 RVO42/flow/helper/ErrorToServiceHandler.js create mode 100755 RVO42/flow/helper/db_helper.js create mode 100755 RVO42/flow/helper/logger.js create mode 100755 RVO42/flow/helper/md5.js create mode 100755 RVO42/flow/helper/notification_reporter.js create mode 100755 RVO42/flow/helper/register.js create mode 100755 RVO42/flow/helper/serialport_helper.js create mode 100755 RVO42/flow/helper/suncalc.js create mode 100755 RVO42/flow/helper/utils.js create mode 100755 RVO42/flow/httprequest.js create mode 100755 RVO42/flow/httpresponse.js create mode 100755 RVO42/flow/httproute.js create mode 100755 RVO42/flow/infosender.js create mode 100755 RVO42/flow/modbus_reader.js create mode 100755 RVO42/flow/monitorconsumption.js create mode 100755 RVO42/flow/monitordisk.js create mode 100755 RVO42/flow/monitormemory.js create mode 100755 RVO42/flow/nodesdb_changecheck.js create mode 100755 RVO42/flow/notifikacie.csv create mode 100755 RVO42/flow/show_dbdata.js create mode 100755 RVO42/flow/slack_filter.js create mode 100755 RVO42/flow/thermometer.js create mode 100755 RVO42/flow/trigger.js create mode 100755 RVO42/flow/variables.txt create mode 100755 RVO42/flow/virtualwirein.js create mode 100755 RVO42/flow/virtualwireout.js create mode 100755 RVO42/flow/wsmqttpublish.js create mode 100755 RVO42/monitor.txt create mode 100755 RVO42/package-lock.json create mode 100755 RVO42/package.json create mode 100755 RVO42/release.js create mode 100755 RVO42/release.js.json create mode 100755 RVO42/report_data.log diff --git a/RVO42/addSwitch.py b/RVO42/addSwitch.py new file mode 100755 index 0000000..c35e96b --- /dev/null +++ b/RVO42/addSwitch.py @@ -0,0 +1,36 @@ +import os + +def process_set_file(): + """ + Checks if /root/flowserver exists, reads set.txt, and modifies the second line. + """ + default_folder = "/root/flowserver" if os.path.exists("/root/flowserver") else "/home/unipi/flowserver" + flag = 1 if default_folder == "/root/flowserver" else 0 + + try: + with open("/home/unipi/flowserver/databases/settings.table", "r") as f: + lines = f.readlines() + + if len(lines) >= 2: + lines[0] = lines[0].rstrip('\n') + "|main_switch:boolean\n" + second_line = lines[1].strip() # remove trailing newline + last_pipe_index = second_line.rfind("|") + + if last_pipe_index != -1: + modified_line = second_line[:last_pipe_index + 1] + str(flag) + "|" + second_line[last_pipe_index + 1:] + lines[1] = modified_line + else: + print("Warning: No '|' character found in the second line of set.txt") + + with open("/home/unipi/flowserver/databases/settings.table", "w") as f: + f.writelines(lines) + else: + print("Warning: settings.table has less than two lines.") + + except FileNotFoundError: + print("Error: settings.table not found.") + except Exception as e: + print(e) + +# if __name__ == "__main__": +process_set_file() diff --git a/RVO42/cloud_topic.py b/RVO42/cloud_topic.py new file mode 100755 index 0000000..77c31f1 --- /dev/null +++ b/RVO42/cloud_topic.py @@ -0,0 +1,76 @@ +# import os +# +# def modify_file(file_path): +# """ +# Modifies the given file by: +# 1. Appending "|cloud_topic" to the first line. +# 2. Inserting the text from the third "." to the first "|" on the second line after the last "|" character. +# +# Args: +# file_path (str): The path to the file to be modified. +# """ +# +# with open(file_path, 'r+') as f: +# lines = f.readlines() +# +# # Modify the first line +# lines[0] += "|cloud_topic:string" +# +# # Modify the second line +# second_line = lines[1].strip() # Remove leading/trailing whitespace +# first_pipe_index = second_line.find('|') +# third_dot_index = second_line.find('.', second_line.find('.', second_line.find('.') + 1) + 1) +# text_to_insert = second_line[third_dot_index:first_pipe_index] +# +# last_pipe_index = second_line.rfind('|') +# lines[1] = second_line[:last_pipe_index + 1] + text_to_insert + "|" + second_line[last_pipe_index + 1:] +# +# print(first_pipe_index, third_dot_index, text_to_insert, last_pipe_index) +# # Write the modified lines back to the file +# # f.seek(0) +# # f.writelines(lines) +# # f.truncate() +# +# # Example usage: +# file_path = "settings.table" # Replace with the actual file path +# modify_file(file_path) +# + + +def modify_file(file_path): + """ + Modifies the given file by: + 1. Appending "|cloud_topic" to the first line. + 2. Inserting the text between the third "." and the second "|" on the second line after the last "|" character. + + Args: + file_path (str): The path to the file to be modified. + """ + + with open(file_path, 'r+') as f: + lines = f.readlines() + + first_line = lines[0].strip() + first_line += "|cloud_topic:string\n" + # Modify the first line + lines[0] = first_line + + # Modify the second line + second_line = lines[1].strip() # Remove leading/trailing whitespace + first_pipe_index = second_line.find('|') + second_pipe_index = second_line.find('|', first_pipe_index + 1) + third_dot_index = second_line.find('.', second_line.find('.', second_line.find('.') + 1) + 1) + text_to_insert = "u" + second_line[third_dot_index+1:second_pipe_index] + + last_pipe_index = second_line.rfind('|') + lines[1] = second_line[:last_pipe_index + 1] + text_to_insert + "|" + second_line[last_pipe_index + 1:] + + print(first_pipe_index, third_dot_index, text_to_insert, last_pipe_index) + # Write the modified lines back to the file + f.seek(0) + f.writelines(lines) + f.truncate() + +# Example usage: +file_path = "/home/unipi/flowserver/databases/settings.table" # Replace with the actual file path +modify_file(file_path) diff --git a/RVO42/config b/RVO42/config new file mode 100755 index 0000000..cd0a8a9 --- /dev/null +++ b/RVO42/config @@ -0,0 +1,12 @@ +name : Total.js Flow +default_timezone : Europe/Bratislava + +// Packages settings +package#flow (Object) : { url: '/' } + + +table.relays : line:number|tbname:string|contactor:number|profile:string +table.nodes : node:number|pole_number:string|node_type:string|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|project_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|cloud_topic:string|has_main_switch:boolean|daily_report:boolean|send_changed_node_numbers:boolean +table.pins : pin:string|type:string|line:number +table.notifications : key:string|weight:string|sk:string|en:string diff --git a/RVO42/createNode.py b/RVO42/createNode.py new file mode 100755 index 0000000..a8cea91 --- /dev/null +++ b/RVO42/createNode.py @@ -0,0 +1,43 @@ +print("zaciname") +import re, json + +search_str = '|' +final = [] +counter = 1 +with open("/home/unipi/flowserver/databases/nodes.table", 'r') as file: +# with open("/home/rasta5man/dev/oms/flowserver/databases/nodes.table", 'r') as file: + # Read each line in the file + for line in file: + # Print each line + line = line.strip() + print(line) + if counter != 1: + i = [m.start() for m in re.finditer(re.escape(search_str), line)] + node = line[ i[0] + 1 : i[1] ] + tbname = line[ i[3] + 1 : i[4] ] + final.append({node:tbname}) + counter += 1 +print(json.dumps(final)) +f = open("/home/unipi/flowserver/databases/nodes_original/nodes_original.table", "w") +f.write(json.dumps(final)) +f.close() + + +# +# # ``d`` has to be replaced with a different character +# old_character = "'" +# +# # ``t`` will replace ``d` +# new_character = '"' +# resultant_string = 0; +# with open("/home/unipi/flowserver/databases/nodes_original/nodes_original.table", 'r') as file: +# for line in file: +# resultant_string = re.sub("'", '"', line) +# +# resultant_string = re.sub(" ", "", resultant_string) +# print(resultant_string) +# +# f = open("/home/unipi/flowserver/databases/nodes_original/nodes_original.table", "w") +# f.write(str(resultant_string)) +# f.close() +# diff --git a/RVO42/databases/accelerometer_db.js b/RVO42/databases/accelerometer_db.js new file mode 100755 index 0000000..fdfc7fd --- /dev/null +++ b/RVO42/databases/accelerometer_db.js @@ -0,0 +1,3055 @@ +let naklony = { + "3993": { "label": "1/3A", "naklon": 0 }, + "3989": { "label": "1/3B", "naklon": 15 }, + "3976": { "label": "1/1", "naklon": 0 }, + "4181": { "label": "1/2", "naklon": 0 }, + "4376": { "label": "1/4", "naklon": 15 }, + "3868": { "label": "1/5", "naklon": 15 }, + "3728": { "label": "1/6", "naklon": 15 }, + "3730": { "label": "1/7", "naklon": 0 }, + "4374": { "label": "1/8", "naklon": 0 }, + "3718": { "label": "1/9", "naklon": 15 }, + "4375": { "label": "1/10", "naklon": 15 }, + "4172": { "label": "1/11", "naklon": 15 }, + "4176": { "label": "1/12", "naklon": 15 }, + "3800": { "label": "2/1", "naklon": 5 }, + "3823": { "label": "2/2", "naklon": 5 }, + "3905": { "label": "2/3", "naklon": 5 }, + "3803": { "label": "2/4", "naklon": 5 }, + "3817": { "label": "2/5", "naklon": 5 }, + "3818": { "label": "2/6", "naklon": 5 }, + "3811": { "label": "2/7", "naklon": 5 }, + "3915": { "label": "2/8", "naklon": 5 }, + "3843": { "label": "2/9", "naklon": 10 }, + "3827": { "label": "2/10", "naklon": 10 }, + "4220": { "label": "2/11", "naklon": 10 }, + "3826": { "label": "2/12", "naklon": 10 }, + "3834": { "label": "2/13", "naklon": 10 }, + "3838": { "label": "2/14", "naklon": 10 }, + "2823": { "label": "2/15", "naklon": 10 }, + "3750": { "label": "2/16", "naklon": 10 }, + "3378": { "label": "2/17", "naklon": 0 }, + "3376": { "label": "2/18", "naklon": 0 }, + "3379": { "label": "2/19", "naklon": 0 }, + "3285": { "label": "2/20", "naklon": 0 }, + "3382": { "label": "2/21", "naklon": 0 }, + "3383": { "label": "2/22", "naklon": 0 }, + "3375": { "label": "2/24", "naklon": 0 }, + "3381": { "label": "2/25", "naklon": 0 }, + "3380": { "label": "2/26", "naklon": 0 }, + "3828": { "label": "2/27", "naklon": 10 }, + "3377": { "label": "2/28", "naklon": 0 }, + "3591": { "label": "7/1", "naklon": 0 }, + "3587": { "label": "7/2", "naklon": 0 }, + "3468": { "label": "7/3", "naklon": 0 }, + "3466": { "label": "7/4", "naklon": 0 }, + "3474": { "label": "7/5", "naklon": 0 }, + "3481": { "label": "7/6", "naklon": 0 }, + "3589": { "label": "7/7", "naklon": 0 }, + "3472": { "label": "7/8", "naklon": 0 }, + "3473": { "label": "7/9", "naklon": 0 }, + "3584": { "label": "7/10", "naklon": 0 }, + "3571": { "label": "7/11", "naklon": 0 }, + "3476": { "label": "7/12", "naklon": 0 }, + "3590": { "label": "7/13", "naklon": 0 }, + "3478": { "label": "7/14", "naklon": 0 }, + "3471": { "label": "7/15", "naklon": 0 }, + "3467": { "label": "7/16", "naklon": 0 }, + "3479": { "label": "7/17", "naklon": 0 }, + "3480": { "label": "7/18", "naklon": 0 }, + "3477": { "label": "7/19", "naklon": 0 }, + "3362": { "label": "12/1", "naklon": 0 }, + "3355": { "label": "12/2", "naklon": 0 }, + "3356": { "label": "12/3", "naklon": 0 }, + "3349": { "label": "12/4", "naklon": 0 }, + "3357": { "label": "12/5", "naklon": 0 }, + "3350": { "label": "12/6", "naklon": 0 }, + "3353": { "label": "12/7", "naklon": 0 }, + "3539": { "label": "12/8", "naklon": 0 }, + "3050": { "label": "12/9", "naklon": 0 }, + "3361": { "label": "12/10", "naklon": 0 }, + "3360": { "label": "12/11", "naklon": 0 }, + "3358": { "label": "12/12", "naklon": 0 }, + "3541": { "label": "12/13", "naklon": 0 }, + "3551": { "label": "12/14", "naklon": 0 }, + "3514": { "label": "12/15", "naklon": 0 }, + "3547": { "label": "12/16", "naklon": 0 }, + "3562": { "label": "12/17", "naklon": 0 }, + "3525": { "label": "12/18", "naklon": 0 }, + "3558": { "label": "12/19", "naklon": 0 }, + "3511": { "label": "12/20", "naklon": 0 }, + "3058": { "label": "12/21", "naklon": 0 }, + "3062": { "label": "12/22", "naklon": 0 }, + "3070": { "label": "12/23", "naklon": 0 }, + "3447": { "label": "12/24", "naklon": 0 }, + "3056": { "label": "12/25", "naklon": 0 }, + "3057": { "label": "12/26", "naklon": 0 }, + "3071": { "label": "12/27", "naklon": 0 }, + "3061": { "label": "12/28", "naklon": 0 }, + "3069": { "label": "12/29", "naklon": 0 }, + "3077": { "label": "12/30", "naklon": 0 }, + "3080": { "label": "12/31", "naklon": 0 }, + "3081": { "label": "12/32", "naklon": 0 }, + "3078": { "label": "12/33", "naklon": 0 }, + "4037": { "label": "12/34", "naklon": 0 }, + "3067": { "label": "12/35", "naklon": 0 }, + "3051": { "label": "12/36", "naklon": 0 }, + "2924": { "label": "12/37", "naklon": 0 }, + "3060": { "label": "12/38", "naklon": 0 }, + "3073": { "label": "12/39", "naklon": 0 }, + "3469": { "label": "12/40", "naklon": 0 }, + "2923": { "label": "12/41", "naklon": 0 }, + "2925": { "label": "12/42", "naklon": 0 }, + "3359": { "label": "12/43", "naklon": 0 }, + "3055": { "label": "12/44", "naklon": 0 }, + "2922": { "label": "12/45", "naklon": 0 }, + "3084": { "label": "12/46", "naklon": 0 }, + "3064": { "label": "12/47", "naklon": 0 }, + "3066": { "label": "12/48", "naklon": 0 }, + "3072": { "label": "12/49", "naklon": 0 }, + "3415": { "label": "13/13A", "naklon": 0 }, + "3409": { "label": "13/13B", "naklon": 0 }, + "3399": { "label": "13/13C", "naklon": 0 }, + "3410": { "label": "13/29A", "naklon": 0 }, + "3407": { "label": "13/29B", "naklon": 0 }, + "3405": { "label": "13/34A", "naklon": 0 }, + "3404": { "label": "13/34B", "naklon": 0 }, + "3392": { "label": "13/45A", "naklon": 0 }, + "3386": { "label": "13/45B", "naklon": 0 }, + "3303": { "label": "13/60A", "naklon": 3 }, + "3302": { "label": "13/60B", "naklon": 3 }, + "3319": { "label": "13/70A", "naklon": 6 }, + "3317": { "label": "13/70B", "naklon": 6 }, + "3326": { "label": "13/70C", "naklon": 6 }, + "3351": { "label": "13/73A", "naklon": 6 }, + "3313": { "label": "13/73B", "naklon": 6 }, + "3316": { "label": "13/83A", "naklon": 0 }, + "3320": { "label": "13/83B", "naklon": 0 }, + "3336": { "label": "13/95A", "naklon": 0 }, + "3323": { "label": "13/95B", "naklon": 0 }, + "3339": { "label": "13/98A", "naklon": 0 }, + "3333": { "label": "13/98B", "naklon": 0 }, + "3425": { "label": "13/1", "naklon": 0 }, + "3419": { "label": "13/2", "naklon": 0 }, + "3416": { "label": "13/3", "naklon": 0 }, + "3332": { "label": "13/4", "naklon": 0 }, + "3422": { "label": "13/5", "naklon": 0 }, + "3417": { "label": "13/6", "naklon": 0 }, + "3418": { "label": "13/7", "naklon": 0 }, + "3424": { "label": "13/8", "naklon": 0 }, + "3334": { "label": "13/9", "naklon": 0 }, + "4363": { "label": "13/10", "naklon": 0 }, + "3423": { "label": "13/11", "naklon": 0 }, + "3406": { "label": "13/12", "naklon": 0 }, + "3411": { "label": "13/14", "naklon": 0 }, + "3412": { "label": "13/15", "naklon": 0 }, + "3413": { "label": "13/16", "naklon": 0 }, + "3414": { "label": "13/17", "naklon": 0 }, + "3391": { "label": "13/18", "naklon": 0 }, + "3370": { "label": "13/19", "naklon": 0 }, + "3369": { "label": "13/20", "naklon": 0 }, + "3408": { "label": "13/21", "naklon": 0 }, + "3393": { "label": "13/22", "naklon": 0 }, + "3128": { "label": "13/23", "naklon": 0 }, + "3197": { "label": "13/24", "naklon": 0 }, + "4364": { "label": "13/25", "naklon": 0 }, + "3155": { "label": "13/26", "naklon": 0 }, + "3196": { "label": "13/27", "naklon": 0 }, + "3144": { "label": "13/28", "naklon": 0 }, + "3150": { "label": "13/30", "naklon": 0 }, + "3390": { "label": "13/31", "naklon": 0 }, + "3401": { "label": "13/32", "naklon": 0 }, + "3275": { "label": "13/33", "naklon": 0 }, + "3371": { "label": "13/35", "naklon": 0 }, + "3389": { "label": "13/36", "naklon": 0 }, + "3388": { "label": "13/37", "naklon": 0 }, + "3365": { "label": "13/38", "naklon": 0 }, + "3363": { "label": "13/39", "naklon": 0 }, + "3397": { "label": "13/40", "naklon": 0 }, + "3567": { "label": "13/40/1", "naklon": 0 }, + "3387": { "label": "13/41", "naklon": 0 }, + "3403": { "label": "13/42", "naklon": 0 }, + "3147": { "label": "13/43", "naklon": 0 }, + "3141": { "label": "13/44", "naklon": 0 }, + "3364": { "label": "13/46", "naklon": 0 }, + "3367": { "label": "13/47", "naklon": 0 }, + "3368": { "label": "13/48", "naklon": 0 }, + "3402": { "label": "13/49", "naklon": 0 }, + "3366": { "label": "13/50", "naklon": 0 }, + "3395": { "label": "13/51", "naklon": 0 }, + "3372": { "label": "13/52", "naklon": 0 }, + "3394": { "label": "13/53", "naklon": 0 }, + "3308": { "label": "13/54", "naklon": 0 }, + "3847": { "label": "13/54/1", "naklon": 0 }, + "3312": { "label": "13/55", "naklon": 3 }, + "3309": { "label": "13/56", "naklon": 3 }, + "3311": { "label": "13/57", "naklon": 3 }, + "3310": { "label": "13/58", "naklon": 3 }, + "4365": { "label": "13/59", "naklon": 3 }, + "4093": { "label": "13/60/1", "naklon": 3 }, + "3304": { "label": "13/61", "naklon": 3 }, + "3307": { "label": "13/62", "naklon": 3 }, + "3271": { "label": "13/63", "naklon": 3 }, + "3301": { "label": "13/64", "naklon": 3 }, + "4366": { "label": "13/65", "naklon": 3 }, + "3300": { "label": "13/66", "naklon": 3 }, + "3185": { "label": "13/67", "naklon": 0 }, + "3184": { "label": "13/68", "naklon": 0 }, + "3188": { "label": "13/69", "naklon": 0 }, + "3343": { "label": "13/71", "naklon": 6 }, + "3819": { "label": "13/71/1", "naklon": 6 }, + "3880": { "label": "13/71/2", "naklon": 6 }, + "3348": { "label": "13/72", "naklon": 6 }, + "3344": { "label": "13/74", "naklon": 6 }, + "3346": { "label": "13/75", "naklon": 6 }, + "3597": { "label": "13/75/1", "naklon": 6 }, + "3345": { "label": "13/76", "naklon": 6 }, + "3322": { "label": "13/77", "naklon": 0 }, + "3325": { "label": "13/78", "naklon": 0 }, + "4310": { "label": "13/78/1", "naklon": 0 }, + "3315": { "label": "13/79", "naklon": 0 }, + "3328": { "label": "13/80", "naklon": 0 }, + "3321": { "label": "13/81", "naklon": 0 }, + "3324": { "label": "13/82", "naklon": 0 }, + "3140": { "label": "13/84", "naklon": 0 }, + "3153": { "label": "13/85", "naklon": 0 }, + "3145": { "label": "13/86", "naklon": 0 }, + "3134": { "label": "13/87", "naklon": 0 }, + "3151": { "label": "13/88", "naklon": 0 }, + "3143": { "label": "13/89", "naklon": 0 }, + "3318": { "label": "13/90", "naklon": 0 }, + "3347": { "label": "13/91", "naklon": 0 }, + "3314": { "label": "13/94", "naklon": 0 }, + "3331": { "label": "13/96", "naklon": 0 }, + "3327": { "label": "13/97", "naklon": 0 }, + "3329": { "label": "13/99", "naklon": 0 }, + "3337": { "label": "13/100", "naklon": 0 }, + "3330": { "label": "13/101", "naklon": 0 }, + "3335": { "label": "13/102", "naklon": 0 }, + "3420": { "label": "13/103", "naklon": 0 }, + "3421": { "label": "13/104", "naklon": 0 }, + "4361": { "label": "13/105", "naklon": 0 }, + "4362": { "label": "13/106", "naklon": 0 }, + "3526": { "label": "13/107", "naklon": 0 }, + "4424": { "label": "13/108", "naklon": null }, + "3561": { "label": "13/109", "naklon": null }, + "3527": { "label": "13/110", "naklon": null }, + "3521": { "label": "13/111", "naklon": null }, + "3552": { "label": "13/112", "naklon": null }, + "3544": { "label": "13/113", "naklon": null }, + "3534": { "label": "13/114", "naklon": null }, + "3516": { "label": "13/115", "naklon": null }, + "3513": { "label": "13/116", "naklon": null }, + "3565": { "label": "13/117", "naklon": null }, + "3866": { "label": "13/118", "naklon": null }, + "3136": { "label": "14/1", "naklon": 0 }, + "3137": { "label": "14/2", "naklon": 0 }, + "3135": { "label": "14/3", "naklon": 0 }, + "3149": { "label": "14/4", "naklon": 0 }, + "3142": { "label": "14/5", "naklon": 0 }, + "3342": { "label": "14/6", "naklon": 0 }, + "3340": { "label": "14/7", "naklon": 0 }, + "3152": { "label": "14/8", "naklon": 0 }, + "3886": { "label": "14/9", "naklon": 0 }, + "3341": { "label": "14/10", "naklon": null }, + "3352": { "label": "14/11", "naklon": null }, + "3396": { "label": "15/1", "naklon": 5 }, + "2784": { "label": "15/2", "naklon": 5 }, + "2788": { "label": "15/3", "naklon": 5 }, + "2801": { "label": "15/4", "naklon": 5 }, + "2815": { "label": "15/5", "naklon": 5 }, + "2829": { "label": "15/6", "naklon": 5 }, + "2796": { "label": "15/7", "naklon": 5 }, + "2803": { "label": "15/8", "naklon": 5 }, + "4304": { "label": "15/8/1", "naklon": 5 }, + "4311": { "label": "15/8/2", "naklon": 5 }, + "2821": { "label": "15/9", "naklon": 5 }, + "3400": { "label": "15/10", "naklon": 5 }, + "2799": { "label": "15/11", "naklon": 5 }, + "2804": { "label": "15/12", "naklon": 5 }, + "4303": { "label": "15/12/1", "naklon": 5 }, + "4309": { "label": "15/12/2", "naklon": 5 }, + "2806": { "label": "15/13", "naklon": 5 }, + "2787": { "label": "15/14", "naklon": 5 }, + "2809": { "label": "15/15", "naklon": 5 }, + "2814": { "label": "15/16", "naklon": 0 }, + "3934": { "label": "15/17", "naklon": 0 }, + "3192": { "label": "15/18", "naklon": 0 }, + "2812": { "label": "15/19", "naklon": 0 }, + "4070": { "label": "15/20", "naklon": 0 }, + "2826": { "label": "15/21", "naklon": 0 }, + "2808": { "label": "15/22", "naklon": 3 }, + "2795": { "label": "15/23", "naklon": 3 }, + "2807": { "label": "15/24", "naklon": 3 }, + "2831": { "label": "15/25", "naklon": 0 }, + "2862": { "label": "15/26", "naklon": null }, + "2861": { "label": "15/27", "naklon": 0 }, + "2866": { "label": "15/28", "naklon": 0 }, + "3546": { "label": "15/28/1", "naklon": 0 }, + "4146": { "label": "15/29", "naklon": 0 }, + "3001": { "label": "15/29/1", "naklon": 0 }, + "2835": { "label": "15/30", "naklon": 0 }, + "2874": { "label": "15/31", "naklon": 0 }, + "2852": { "label": "15/32", "naklon": 0 }, + "2851": { "label": "15/33", "naklon": 0 }, + "3560": { "label": "15/33/1", "naklon": 0 }, + "2858": { "label": "15/34", "naklon": 0 }, + "4306": { "label": "15/34/1", "naklon": 0 }, + "2856": { "label": "15/35", "naklon": 0 }, + "2847": { "label": "15/36", "naklon": 0 }, + "3556": { "label": "15/36/1", "naklon": 0 }, + "3950": { "label": "15/37", "naklon": 0 }, + "2848": { "label": "15/38", "naklon": 0 }, + "2863": { "label": "15/39", "naklon": 0 }, + "4313": { "label": "15/39/1", "naklon": 0 }, + "2873": { "label": "15/40", "naklon": 0 }, + "2984": { "label": "15/40/1", "naklon": 0 }, + "2854": { "label": "15/41", "naklon": 0 }, + "2859": { "label": "15/42", "naklon": 0 }, + "2872": { "label": "15/43", "naklon": 0 }, + "2849": { "label": "15/44", "naklon": 0 }, + "2864": { "label": "15/45", "naklon": 0 }, + "3553": { "label": "15/46", "naklon": null }, + "3021": { "label": "15/47", "naklon": null }, + "3008": { "label": "15/47/1", "naklon": null }, + "3017": { "label": "15/48", "naklon": null }, + "3014": { "label": "15/49", "naklon": null }, + "2981": { "label": "15/50", "naklon": null }, + "3020": { "label": "15/51", "naklon": null }, + "3027": { "label": "15/52", "naklon": null }, + "3006": { "label": "15/53", "naklon": null }, + "3012": { "label": "15/54", "naklon": null }, + "2738": { "label": "15/55", "naklon": 0 }, + "2725": { "label": "15/56", "naklon": 0 }, + "3016": { "label": "15/57", "naklon": null }, + "3005": { "label": "15/58", "naklon": null }, + "3009": { "label": "15/58/1", "naklon": null }, + "3010": { "label": "15/59", "naklon": 0 }, + "3538": { "label": "15/59/1", "naklon": 0 }, + "4145": { "label": "15/59/2", "naklon": 0 }, + "2713": { "label": "15/60", "naklon": 0 }, + "2789": { "label": "15/61", "naklon": 0 }, + "2736": { "label": "15/62", "naklon": 0 }, + "2739": { "label": "15/63", "naklon": 0 }, + "4346": { "label": "15/64", "naklon": 0 }, + "2731": { "label": "15/65", "naklon": 0 }, + "2818": { "label": "15/66", "naklon": 0 }, + "3557": { "label": "15/66/1", "naklon": 0 }, + "2822": { "label": "15/67", "naklon": 0 }, + "2833": { "label": "15/68", "naklon": 0 }, + "2834": { "label": "15/69", "naklon": 0 }, + "3097": { "label": "15/70", "naklon": 0 }, + "2824": { "label": "15/71", "naklon": 0 }, + "2828": { "label": "15/72", "naklon": 0 }, + "2600": { "label": "15/73", "naklon": 0 }, + "4314": { "label": "15/73/1", "naklon": 0 }, + "2832": { "label": "15/74", "naklon": 0 }, + "4360": { "label": "15/75", "naklon": 0 }, + "2846": { "label": "15/76", "naklon": 0 }, + "2584": { "label": "15/77", "naklon": 0 }, + "2843": { "label": "15/78", "naklon": 0 }, + "4308": { "label": "15/78/1", "naklon": 0 }, + "4144": { "label": "15/79", "naklon": null }, + "2844": { "label": "15/80", "naklon": 0 }, + "2842": { "label": "15/81", "naklon": 0 }, + "2838": { "label": "15/82", "naklon": 0 }, + "2837": { "label": "15/83", "naklon": null }, + "3555": { "label": "15/83/1", "naklon": null }, + "2839": { "label": "15/84", "naklon": 0 }, + "2830": { "label": "15/85", "naklon": 0 }, + "4066": { "label": "15/86", "naklon": 0 }, + "2836": { "label": "15/87", "naklon": 0 }, + "2911": { "label": "15/88", "naklon": 0 }, + "2825": { "label": "15/89", "naklon": 0 }, + "2811": { "label": "15/90", "naklon": 0 }, + "3740": { "label": "15/94", "naklon": 15 }, + "2734": { "label": "15/95", "naklon": 15 }, + "3105": { "label": "15/96", "naklon": 15 }, + "2732": { "label": "15/97", "naklon": 15 }, + "2727": { "label": "15/98", "naklon": 15 }, + "2735": { "label": "15/99", "naklon": 15 }, + "3926": { "label": "15/100", "naklon": 15 }, + "2918": { "label": "15/101", "naklon": 0 }, + "2705": { "label": "15/102", "naklon": 10 }, + "2708": { "label": "15/103", "naklon": 10 }, + "2721": { "label": "15/104", "naklon": 10 }, + "2719": { "label": "15/105", "naklon": 10 }, + "2919": { "label": "15/106", "naklon": 10 }, + "3101": { "label": "15/107", "naklon": 10 }, + "2853": { "label": "15/108", "naklon": 10 }, + "2715": { "label": "15/109", "naklon": 10 }, + "2712": { "label": "15/110", "naklon": 0 }, + "2711": { "label": "15/111", "naklon": 0 }, + "2709": { "label": "15/112", "naklon": 0 }, + "2710": { "label": "15/113", "naklon": 0 }, + "2907": { "label": "15/114", "naklon": 0 }, + "2906": { "label": "15/115", "naklon": 0 }, + "2908": { "label": "15/116", "naklon": 0 }, + "2901": { "label": "15/117", "naklon": 0 }, + "2913": { "label": "15/118", "naklon": 0 }, + "3656": { "label": "15/119", "naklon": 0 }, + "2781": { "label": "15/120", "naklon": 0 }, + "2802": { "label": "15/121", "naklon": 0 }, + "2791": { "label": "15/122", "naklon": 0 }, + "2783": { "label": "15/123", "naklon": 0 }, + "2794": { "label": "15/124", "naklon": 0 }, + "3139": { "label": "15/125", "naklon": 0 }, + "3229": { "label": "15/126", "naklon": 5 }, + "3239": { "label": "15/127", "naklon": 5 }, + "3230": { "label": "15/128", "naklon": 5 }, + "4016": { "label": "15/129", "naklon": null }, + "3608": { "label": "16/16A", "naklon": 0 }, + "4151": { "label": "16/16B", "naklon": 0 }, + "3710": { "label": "16/1", "naklon": 0 }, + "3726": { "label": "16/2", "naklon": 0 }, + "3743": { "label": "16/3", "naklon": 0 }, + "3724": { "label": "16/4", "naklon": 0 }, + "3712": { "label": "16/5", "naklon": 0 }, + "3739": { "label": "16/6", "naklon": 0 }, + "3742": { "label": "16/7", "naklon": 0 }, + "3731": { "label": "16/8", "naklon": 0 }, + "3727": { "label": "16/9", "naklon": 0 }, + "3729": { "label": "16/10", "naklon": 0 }, + "3736": { "label": "16/11", "naklon": 0 }, + "3713": { "label": "16/12", "naklon": 0 }, + "3715": { "label": "16/13", "naklon": 0 }, + "3733": { "label": "16/14", "naklon": 0 }, + "3732": { "label": "16/15", "naklon": 0 }, + "3634": { "label": "16/17", "naklon": 0 }, + "3610": { "label": "16/18", "naklon": 0 }, + "3626": { "label": "16/19", "naklon": 0 }, + "3618": { "label": "16/20", "naklon": 0 }, + "3619": { "label": "16/21", "naklon": 0 }, + "3628": { "label": "16/22", "naklon": 0 }, + "3615": { "label": "16/23", "naklon": 0 }, + "3609": { "label": "16/24", "naklon": 0 }, + "3606": { "label": "16/25", "naklon": 0 }, + "3624": { "label": "16/26", "naklon": 0 }, + "3627": { "label": "16/27", "naklon": 0 }, + "3607": { "label": "16/28", "naklon": 0 }, + "4370": { "label": "16/29", "naklon": 0 }, + "3692": { "label": "16/30", "naklon": 0 }, + "3614": { "label": "16/31", "naklon": 0 }, + "3623": { "label": "16/32", "naklon": 0 }, + "4373": { "label": "16/33", "naklon": 0 }, + "3620": { "label": "16/34", "naklon": 0 }, + "3685": { "label": "16/35", "naklon": 0 }, + "3616": { "label": "16/36", "naklon": 0 }, + "3686": { "label": "16/37", "naklon": 0 }, + "3688": { "label": "16/38", "naklon": 0 }, + "3684": { "label": "16/39", "naklon": 0 }, + "3825": { "label": "16/40", "naklon": 0 }, + "3865": { "label": "16/41", "naklon": 0 }, + "3824": { "label": "16/42", "naklon": 0 }, + "3871": { "label": "16/43", "naklon": 0 }, + "3801": { "label": "16/44", "naklon": 0 }, + "3862": { "label": "16/45", "naklon": 0 }, + "3876": { "label": "16/46", "naklon": 0 }, + "3861": { "label": "16/47", "naklon": 0 }, + "4215": { "label": "16/48", "naklon": 0 }, + "3605": { "label": "16/49", "naklon": 10 }, + "3603": { "label": "16/50", "naklon": 10 }, + "3592": { "label": "16/51", "naklon": 10 }, + "3598": { "label": "16/52", "naklon": 10 }, + "3594": { "label": "16/53", "naklon": 10 }, + "3593": { "label": "16/54", "naklon": 10 }, + "3630": { "label": "16/55", "naklon": 10 }, + "3763": { "label": "16/56", "naklon": 10 }, + "3746": { "label": "16/57", "naklon": 10 }, + "3699": { "label": "16/58", "naklon": 0 }, + "3698": { "label": "16/59", "naklon": 0 }, + "3709": { "label": "16/60", "naklon": null }, + "3708": { "label": "16/61", "naklon": 0 }, + "3703": { "label": "16/62", "naklon": null }, + "3700": { "label": "16/63", "naklon": 0 }, + "3701": { "label": "16/64", "naklon": null }, + "3704": { "label": "16/65", "naklon": 0 }, + "3707": { "label": "16/66", "naklon": null }, + "3810": { "label": "16/67", "naklon": 0 }, + "4208": { "label": "16/68", "naklon": null }, + "3867": { "label": "16/69", "naklon": 0 }, + "4372": { "label": "16/70", "naklon": null }, + "3881": { "label": "16/71", "naklon": 0 }, + "4204": { "label": "16/72", "naklon": null }, + "3869": { "label": "16/73", "naklon": 0 }, + "4202": { "label": "16/74", "naklon": null }, + "3830": { "label": "16/75", "naklon": 0 }, + "3870": { "label": "16/76", "naklon": null }, + "3964": { "label": "16/77", "naklon": 0 }, + "3849": { "label": "16/78", "naklon": 0 }, + "3694": { "label": "16/79", "naklon": null }, + "3717": { "label": "16/80", "naklon": 0 }, + "3877": { "label": "16/81", "naklon": null }, + "3755": { "label": "16/82", "naklon": 0 }, + "3725": { "label": "16/83", "naklon": null }, + "3716": { "label": "16/84", "naklon": 0 }, + "3696": { "label": "16/85", "naklon": null }, + "3702": { "label": "16/86", "naklon": 0 }, + "3706": { "label": "16/87", "naklon": null }, + "3850": { "label": "16/88", "naklon": 0 }, + "3848": { "label": "16/89", "naklon": null }, + "3737": { "label": "16/90", "naklon": null }, + "3705": { "label": "16/91", "naklon": 0 }, + "3723": { "label": "16/92", "naklon": null }, + "3842": { "label": "16/93", "naklon": 0 }, + "3735": { "label": "16/94", "naklon": null }, + "3719": { "label": "16/95", "naklon": 0 }, + "3697": { "label": "16/96", "naklon": 0 }, + "3711": { "label": "16/97", "naklon": 0 }, + "4107": { "label": "16/98", "naklon": null }, + "4112": { "label": "16/99", "naklon": 5 }, + "4106": { "label": "16/100", "naklon": 5 }, + "4111": { "label": "16/101", "naklon": 5 }, + "4091": { "label": "16/102", "naklon": null }, + "4104": { "label": "16/103", "naklon": 5 }, + "4094": { "label": "16/104", "naklon": null }, + "4089": { "label": "16/105", "naklon": 5 }, + "4095": { "label": "16/106", "naklon": null }, + "4102": { "label": "16/107", "naklon": 5 }, + "4105": { "label": "16/108", "naklon": null }, + "3859": { "label": "16/109", "naklon": null }, + "4090": { "label": "16/110", "naklon": 5 }, + "4110": { "label": "16/111", "naklon": null }, + "4097": { "label": "16/112", "naklon": 5 }, + "4099": { "label": "16/113", "naklon": null }, + "4096": { "label": "16/114", "naklon": null }, + "4101": { "label": "16/115", "naklon": 5 }, + "4109": { "label": "16/116", "naklon": null }, + "4092": { "label": "16/117", "naklon": 5 }, + "3631": { "label": "16/118", "naklon": null }, + "3632": { "label": "16/119", "naklon": 0 }, + "3641": { "label": "16/120", "naklon": null }, + "3638": { "label": "16/121", "naklon": 0 }, + "3637": { "label": "16/122", "naklon": null }, + "4142": { "label": "16/123", "naklon": null }, + "4147": { "label": "16/124", "naklon": 5 }, + "4139": { "label": "16/125", "naklon": 5 }, + "3172": { "label": "20/30A", "naklon": 2 }, + "3164": { "label": "20/30B", "naklon": 2 }, + "3247": { "label": "20/1", "naklon": 10 }, + "3296": { "label": "20/2", "naklon": 10 }, + "3246": { "label": "20/3", "naklon": 10 }, + "3270": { "label": "20/4", "naklon": 10 }, + "3294": { "label": "20/5", "naklon": 10 }, + "3298": { "label": "20/6", "naklon": 10 }, + "3297": { "label": "20/7", "naklon": 10 }, + "3293": { "label": "20/8", "naklon": 10 }, + "3299": { "label": "20/9", "naklon": 10 }, + "3295": { "label": "20/10", "naklon": 10 }, + "3244": { "label": "20/11", "naklon": 10 }, + "3249": { "label": "20/12", "naklon": 10 }, + "3268": { "label": "20/13", "naklon": 10 }, + "3245": { "label": "20/14", "naklon": 10 }, + "3278": { "label": "20/15", "naklon": 10 }, + "3280": { "label": "20/16", "naklon": 10 }, + "3292": { "label": "20/17", "naklon": 10 }, + "3287": { "label": "20/18", "naklon": 10 }, + "3282": { "label": "20/19", "naklon": 10 }, + "3273": { "label": "20/20", "naklon": 0 }, + "3157": { "label": "20/21", "naklon": 0 }, + "3283": { "label": "20/22", "naklon": 0 }, + "3159": { "label": "20/23", "naklon": 0 }, + "3289": { "label": "20/24", "naklon": 0 }, + "3163": { "label": "20/25", "naklon": 0 }, + "3126": { "label": "20/26", "naklon": 0 }, + "3171": { "label": "20/27", "naklon": 0 }, + "3162": { "label": "20/28", "naklon": 0 }, + "3279": { "label": "20/29", "naklon": 10 }, + "3173": { "label": "20/31", "naklon": 0 }, + "3127": { "label": "20/32", "naklon": 0 }, + "3131": { "label": "20/33", "naklon": 0 }, + "3129": { "label": "20/34", "naklon": 0 }, + "3276": { "label": "20/35", "naklon": 2 }, + "3290": { "label": "20/36", "naklon": 2 }, + "3132": { "label": "20/37", "naklon": 0 }, + "3138": { "label": "20/38", "naklon": 0 }, + "3272": { "label": "20/39", "naklon": 0 }, + "3291": { "label": "20/40", "naklon": 0 }, + "3277": { "label": "20/41", "naklon": 10 }, + "3286": { "label": "20/42", "naklon": 10 }, + "3281": { "label": "20/43", "naklon": 10 }, + "3288": { "label": "20/44", "naklon": 10 }, + "3284": { "label": "20/45", "naklon": 10 }, + "3167": { "label": "20/46", "naklon": 10 }, + "3872": { "label": "20/47", "naklon": 0 }, + "3124": { "label": "20/48", "naklon": 0 }, + "3133": { "label": "20/49", "naklon": 0 }, + "3158": { "label": "20/50", "naklon": 0 }, + "3169": { "label": "20/51", "naklon": 0 }, + "3146": { "label": "20/52", "naklon": 0 }, + "3160": { "label": "20/53", "naklon": 0 }, + "3248": { "label": "20/54", "naklon": 0 }, + "3156": { "label": "20/55", "naklon": 0 }, + "3161": { "label": "20/56", "naklon": 0 }, + "3170": { "label": "20/57", "naklon": 0 }, + "3168": { "label": "20/58", "naklon": 0 }, + "3125": { "label": "20/59", "naklon": 0 }, + "3166": { "label": "20/60", "naklon": 0 }, + "3130": { "label": "20/61", "naklon": 0 }, + "3563": { "label": "20/62", "naklon": 0 }, + "3550": { "label": "20/63", "naklon": null }, + "3269": { "label": "20/67", "naklon": 0 }, + "2921": { "label": "21/1", "naklon": 0 }, + "2707": { "label": "21/2", "naklon": 0 }, + "2723": { "label": "21/3", "naklon": 0 }, + "2716": { "label": "21/4", "naklon": 0 }, + "2717": { "label": "21/5", "naklon": 0 }, + "2720": { "label": "21/6", "naklon": 0 }, + "2722": { "label": "21/7", "naklon": 0 }, + "2718": { "label": "21/8", "naklon": 0 }, + "2724": { "label": "21/9", "naklon": 0 }, + "2742": { "label": "21/10", "naklon": 0 }, + "2743": { "label": "21/11", "naklon": 0 }, + "2733": { "label": "21/12", "naklon": 0 }, + "2903": { "label": "21/14", "naklon": 0 }, + "2917": { "label": "21/15", "naklon": 0 }, + "2897": { "label": "21/16", "naklon": 0 }, + "2914": { "label": "21/17", "naklon": 0 }, + "2898": { "label": "21/18", "naklon": 0 }, + "2773": { "label": "21/19", "naklon": 0 }, + "2895": { "label": "21/20", "naklon": 0 }, + "2896": { "label": "21/21", "naklon": 0 }, + "2771": { "label": "21/22", "naklon": 0 }, + "2772": { "label": "21/23", "naklon": 0 }, + "2793": { "label": "21/24", "naklon": 0 }, + "2902": { "label": "21/25", "naklon": 0 }, + "2910": { "label": "21/26", "naklon": 0 }, + "2909": { "label": "21/27", "naklon": 0 }, + "2920": { "label": "21/28", "naklon": 0 }, + "2916": { "label": "21/29", "naklon": 0 }, + "2904": { "label": "21/30", "naklon": 0 }, + "2915": { "label": "21/31", "naklon": 0 }, + "2905": { "label": "21/32", "naklon": 0 }, + "2900": { "label": "21/33", "naklon": 0 }, + "2899": { "label": "21/34", "naklon": 0 }, + "2741": { "label": "21/36", "naklon": 0 }, + "2714": { "label": "21/37", "naklon": 0 }, + "2701": { "label": "21/38", "naklon": 0 }, + "2703": { "label": "21/39", "naklon": 0 }, + "2704": { "label": "21/40", "naklon": 0 }, + "2702": { "label": "21/41", "naklon": 0 }, + "2706": { "label": "21/42", "naklon": 0 }, + "2776": { "label": "21/43", "naklon": 0 }, + "2770": { "label": "21/44", "naklon": 0 }, + "2786": { "label": "21/45", "naklon": 0 }, + "2779": { "label": "21/46", "naklon": 0 }, + "2782": { "label": "21/47", "naklon": 0 }, + "2785": { "label": "21/48", "naklon": 0 }, + "2769": { "label": "21/49", "naklon": 0 }, + "3354": { "label": "21/50", "naklon": 0 }, + "2778": { "label": "21/51", "naklon": 0 }, + "2775": { "label": "21/52", "naklon": 0 }, + "2780": { "label": "21/53", "naklon": 0 }, + "2790": { "label": "21/54", "naklon": 0 }, + "2792": { "label": "21/55", "naklon": 0 }, + "2774": { "label": "21/56", "naklon": 0 }, + "2630": { "label": "22/1", "naklon": 0 }, + "2631": { "label": "22/2", "naklon": 0 }, + "2632": { "label": "22/3", "naklon": 0 }, + "2633": { "label": "22/4", "naklon": 0 }, + "2634": { "label": "22/5", "naklon": 0 }, + "2636": { "label": "22/6", "naklon": 0 }, + "4367": { "label": "22/7", "naklon": 0 }, + "2637": { "label": "22/8", "naklon": 0 }, + "2638": { "label": "22/9", "naklon": 0 }, + "2639": { "label": "22/10", "naklon": 0 }, + "2640": { "label": "22/11", "naklon": 0 }, + "2641": { "label": "22/12", "naklon": 0 }, + "2642": { "label": "22/13", "naklon": 0 }, + "2643": { "label": "22/14", "naklon": 0 }, + "2644": { "label": "22/15", "naklon": 0 }, + "2645": { "label": "22/16", "naklon": 0 }, + "2646": { "label": "22/17", "naklon": 0 }, + "2647": { "label": "22/18", "naklon": 0 }, + "2648": { "label": "22/19", "naklon": 0 }, + "2649": { "label": "22/20", "naklon": 0 }, + "2650": { "label": "22/21", "naklon": 0 }, + "2651": { "label": "22/22", "naklon": 0 }, + "4103": { "label": "22/23", "naklon": 0 }, + "2653": { "label": "22/24", "naklon": 0 }, + "2654": { "label": "22/25", "naklon": 0 }, + "2655": { "label": "22/26", "naklon": 0 }, + "2656": { "label": "22/27", "naklon": 0 }, + "2657": { "label": "22/28", "naklon": 0 }, + "2658": { "label": "22/29", "naklon": 0 }, + "2659": { "label": "22/30", "naklon": 0 }, + "2660": { "label": "22/31", "naklon": 0 }, + "2661": { "label": "22/32", "naklon": 0 }, + "3015": { "label": "22/32/1", "naklon": 0 }, + "2662": { "label": "22/33", "naklon": 0 }, + "2663": { "label": "22/34", "naklon": 0 }, + "2664": { "label": "22/35", "naklon": 0 }, + "2665": { "label": "22/36", "naklon": 0 }, + "2666": { "label": "22/37", "naklon": 0 }, + "2667": { "label": "22/38", "naklon": 0 }, + "2668": { "label": "22/39", "naklon": 0 }, + "2669": { "label": "22/40", "naklon": null }, + "2670": { "label": "22/41", "naklon": null }, + "2671": { "label": "22/42", "naklon": null }, + "3087": { "label": "23/9A", "naklon": 10 }, + "3090": { "label": "23/9B", "naklon": 10 }, + "3075": { "label": "23/1", "naklon": 0 }, + "3089": { "label": "23/2", "naklon": 0 }, + "3088": { "label": "23/3", "naklon": 0 }, + "3228": { "label": "23/4", "naklon": 10 }, + "2751": { "label": "23/5", "naklon": 10 }, + "3243": { "label": "23/6", "naklon": 10 }, + "4349": { "label": "23/7", "naklon": 10 }, + "3102": { "label": "23/8", "naklon": 10 }, + "3099": { "label": "23/10", "naklon": 10 }, + "3103": { "label": "23/11", "naklon": 10 }, + "3093": { "label": "23/12", "naklon": 10 }, + "3098": { "label": "23/13", "naklon": 10 }, + "3092": { "label": "23/14", "naklon": 10 }, + "3233": { "label": "23/15", "naklon": 0 }, + "3095": { "label": "23/16", "naklon": 0 }, + "4074": { "label": "23/17", "naklon": 0 }, + "2729": { "label": "23/18", "naklon": 0 }, + "3234": { "label": "23/19", "naklon": 0 }, + "3094": { "label": "23/20", "naklon": 0 }, + "2817": { "label": "23/21", "naklon": 0 }, + "3226": { "label": "23/22", "naklon": 0 }, + "3225": { "label": "23/23", "naklon": 0 }, + "3237": { "label": "23/24", "naklon": 0 }, + "4250": { "label": "23/25", "naklon": 0 }, + "3059": { "label": "23/26", "naklon": 10 }, + "3238": { "label": "23/27", "naklon": 10 }, + "3242": { "label": "23/28", "naklon": 10 }, + "3236": { "label": "23/29", "naklon": 10 }, + "3112": { "label": "23/30", "naklon": 10 }, + "3224": { "label": "23/31", "naklon": 0 }, + "4298": { "label": "23/32", "naklon": 10 }, + "4150": { "label": "23/33", "naklon": 10 }, + "3091": { "label": "23/34", "naklon": 10 }, + "3771": { "label": "25/1", "naklon": 5 }, + "3777": { "label": "25/2", "naklon": 5 }, + "3749": { "label": "25/3", "naklon": 5 }, + "3769": { "label": "25/4", "naklon": 5 }, + "3765": { "label": "25/5", "naklon": 5 }, + "3785": { "label": "25/6", "naklon": 5 }, + "3761": { "label": "25/7", "naklon": 5 }, + "3758": { "label": "25/8", "naklon": 5 }, + "3766": { "label": "25/9", "naklon": 5 }, + "3779": { "label": "25/10", "naklon": 5 }, + "3899": { "label": "25/11", "naklon": 10 }, + "3922": { "label": "25/12", "naklon": 10 }, + "3912": { "label": "25/13", "naklon": 10 }, + "3933": { "label": "25/14", "naklon": 10 }, + "3921": { "label": "25/15", "naklon": 10 }, + "4300": { "label": "25/16", "naklon": 10 }, + "3927": { "label": "25/17", "naklon": 10 }, + "3212": { "label": "25/18", "naklon": 10 }, + "3208": { "label": "25/19", "naklon": 10 }, + "3207": { "label": "25/20", "naklon": 10 }, + "4294": { "label": "25/21", "naklon": 10 }, + "3209": { "label": "25/22", "naklon": 10 }, + "3745": { "label": "25/23", "naklon": 10 }, + "3762": { "label": "25/24", "naklon": 10 }, + "3215": { "label": "25/25", "naklon": 10 }, + "3210": { "label": "25/26", "naklon": 10 }, + "3211": { "label": "25/27", "naklon": 10 }, + "3206": { "label": "25/28", "naklon": 10 }, + "3918": { "label": "25/29", "naklon": 5 }, + "3928": { "label": "25/30", "naklon": 5 }, + "3917": { "label": "25/31", "naklon": 5 }, + "4029": { "label": "25/32", "naklon": 0 }, + "4038": { "label": "25/33", "naklon": 0 }, + "4022": { "label": "25/34", "naklon": 0 }, + "3937": { "label": "25/35", "naklon": 0 }, + "3190": { "label": "25/36", "naklon": 0 }, + "3835": { "label": "25/37", "naklon": 0 }, + "3201": { "label": "25/38", "naklon": 0 }, + "3193": { "label": "25/39", "naklon": 0 }, + "3191": { "label": "25/40", "naklon": 0 }, + "3203": { "label": "25/41", "naklon": 0 }, + "4301": { "label": "25/42", "naklon": 0 }, + "3223": { "label": "25/43", "naklon": 0 }, + "3202": { "label": "25/44", "naklon": 0 }, + "3205": { "label": "25/45", "naklon": 0 }, + "3194": { "label": "25/46", "naklon": 0 }, + "3198": { "label": "25/47", "naklon": 0 }, + "3204": { "label": "25/48", "naklon": 0 }, + "3200": { "label": "25/49", "naklon": 0 }, + "3216": { "label": "25/50", "naklon": 0 }, + "3932": { "label": "25/51", "naklon": 5 }, + "3923": { "label": "25/52", "naklon": 5 }, + "3913": { "label": "25/53", "naklon": 5 }, + "3900": { "label": "25/54", "naklon": 5 }, + "4189": { "label": "25/55", "naklon": 10 }, + "4191": { "label": "25/56", "naklon": 10 }, + "3790": { "label": "25/57", "naklon": 10 }, + "4190": { "label": "25/58", "naklon": 10 }, + "4302": { "label": "25/59", "naklon": 0 }, + "4351": { "label": "25/60", "naklon": 0 }, + "4075": { "label": "25/61", "naklon": 0 }, + "4071": { "label": "25/62", "naklon": 0 }, + "3784": { "label": "25/63", "naklon": 0 }, + "4065": { "label": "25/64", "naklon": 0 }, + "4297": { "label": "25/65", "naklon": 0 }, + "4295": { "label": "25/66", "naklon": 0 }, + "4299": { "label": "25/67", "naklon": 0 }, + "3772": { "label": "25/68", "naklon": 0 }, + "3941": { "label": "25/69", "naklon": 0 }, + "3782": { "label": "25/70", "naklon": 0 }, + "4068": { "label": "25/71", "naklon": 0 }, + "4073": { "label": "25/72", "naklon": 0 }, + "3901": { "label": "25/73", "naklon": 5 }, + "4296": { "label": "25/74", "naklon": 5 }, + "3910": { "label": "25/75", "naklon": 5 }, + "4293": { "label": "25/76", "naklon": 5 }, + "3919": { "label": "25/77", "naklon": 5 }, + "3924": { "label": "25/78", "naklon": 5 }, + "3909": { "label": "25/79", "naklon": 5 }, + "3896": { "label": "25/80", "naklon": 5 }, + "3911": { "label": "25/81", "naklon": 5 }, + "2819": { "label": "25/82", "naklon": 15 }, + "3776": { "label": "25/83", "naklon": 15 }, + "3752": { "label": "25/84", "naklon": 15 }, + "4353": { "label": "25/85", "naklon": 15 }, + "3791": { "label": "25/86", "naklon": 0 }, + "3770": { "label": "25/87", "naklon": 0 }, + "3760": { "label": "25/88", "naklon": 0 }, + "3115": { "label": "25/89", "naklon": 0 }, + "3738": { "label": "25/90", "naklon": 0 }, + "3748": { "label": "25/91", "naklon": 0 }, + "3753": { "label": "25/92", "naklon": 0 }, + "3775": { "label": "25/93", "naklon": 0 }, + "3778": { "label": "25/94", "naklon": 5 }, + "4078": { "label": "25/95", "naklon": 5 }, + "4088": { "label": "25/96", "naklon": 5 }, + "3856": { "label": "25/97", "naklon": 5 }, + "4084": { "label": "25/98", "naklon": 5 }, + "4069": { "label": "25/99", "naklon": 5 }, + "4188": { "label": "25/100", "naklon": 5 }, + "4064": { "label": "25/101", "naklon": 5 }, + "3792": { "label": "25/102", "naklon": 5 }, + "3780": { "label": "25/103", "naklon": 5 }, + "4034": { "label": "25/104", "naklon": 5 }, + "4072": { "label": "25/105", "naklon": 5 }, + "3884": { "label": "25/106", "naklon": 5 }, + "3793": { "label": "25/107", "naklon": 5 }, + "3863": { "label": "25/108", "naklon": 5 }, + "3855": { "label": "25/109", "naklon": 5 }, + "3846": { "label": "33/1", "naklon": 0 }, + "3943": { "label": "33/2", "naklon": 0 }, + "3903": { "label": "33/3", "naklon": 0 }, + "3982": { "label": "33/4", "naklon": 0 }, + "3879": { "label": "33/5", "naklon": 0 }, + "3887": { "label": "33/6", "naklon": 0 }, + "3920": { "label": "33/7", "naklon": 5 }, + "3942": { "label": "33/8", "naklon": 5 }, + "3829": { "label": "33/9", "naklon": null }, + "3452": { "label": "34/79A", "naklon": 6 }, + "3460": { "label": "34/79B", "naklon": 6 }, + "3443": { "label": "34/90A", "naklon": 6 }, + "3445": { "label": "34/90B", "naklon": 6 }, + "3457": { "label": "34/90C", "naklon": 6 }, + "3461": { "label": "34/97A", "naklon": 6 }, + "3463": { "label": "34/97B", "naklon": 6 }, + "3426": { "label": "34/98A", "naklon": 6 }, + "3444": { "label": "34/98B", "naklon": 6 }, + "3453": { "label": "34/99A", "naklon": 6 }, + "3455": { "label": "34/99B", "naklon": 6 }, + "4009": { "label": "34/1", "naklon": 0 }, + "3602": { "label": "34/2", "naklon": 0 }, + "3441": { "label": "34/3", "naklon": 0 }, + "3464": { "label": "34/4", "naklon": 0 }, + "3883": { "label": "34/5", "naklon": 0 }, + "4098": { "label": "34/6", "naklon": 0 }, + "4003": { "label": "34/7", "naklon": 0 }, + "4004": { "label": "34/8", "naklon": 0 }, + "3888": { "label": "34/9", "naklon": 0 }, + "3997": { "label": "34/10", "naklon": 0 }, + "4006": { "label": "34/11", "naklon": 0 }, + "4000": { "label": "34/12", "naklon": 0 }, + "4011": { "label": "34/13", "naklon": 0 }, + "3999": { "label": "34/14", "naklon": 0 }, + "3981": { "label": "34/15", "naklon": 0 }, + "3988": { "label": "34/16", "naklon": 0 }, + "3986": { "label": "34/17", "naklon": 0 }, + "3998": { "label": "34/18", "naklon": 0 }, + "3983": { "label": "34/19", "naklon": 0 }, + "4005": { "label": "34/20", "naklon": 0 }, + "4001": { "label": "34/21", "naklon": 0 }, + "4008": { "label": "34/22", "naklon": 0 }, + "4002": { "label": "34/23", "naklon": 0 }, + "3996": { "label": "34/24", "naklon": 0 }, + "4007": { "label": "34/25", "naklon": 0 }, + "4113": { "label": "34/26", "naklon": 15 }, + "3595": { "label": "34/27", "naklon": 5 }, + "3599": { "label": "34/28", "naklon": 5 }, + "3601": { "label": "34/29", "naklon": 5 }, + "4205": { "label": "34/30", "naklon": 0 }, + "3987": { "label": "34/31", "naklon": null }, + "4214": { "label": "34/32", "naklon": 0 }, + "4226": { "label": "34/33", "naklon": 0 }, + "4209": { "label": "34/34", "naklon": 0 }, + "4201": { "label": "34/35", "naklon": 0 }, + "3440": { "label": "34/36", "naklon": 0 }, + "3465": { "label": "34/37", "naklon": 0 }, + "3446": { "label": "34/38", "naklon": 0 }, + "4039": { "label": "34/39", "naklon": 5 }, + "4057": { "label": "34/40", "naklon": 5 }, + "3985": { "label": "34/41", "naklon": 0 }, + "3882": { "label": "34/42", "naklon": 0 }, + "4040": { "label": "34/43", "naklon": 5 }, + "3231": { "label": "34/44", "naklon": 0 }, + "3227": { "label": "34/45", "naklon": 0 }, + "3431": { "label": "34/46", "naklon": 0 }, + "4013": { "label": "34/47", "naklon": 0 }, + "4045": { "label": "34/48", "naklon": 0 }, + "3949": { "label": "34/49", "naklon": 0 }, + "3953": { "label": "34/50", "naklon": 0 }, + "3952": { "label": "34/51", "naklon": 0 }, + "3995": { "label": "34/52", "naklon": 0 }, + "3992": { "label": "34/53", "naklon": 0 }, + "4198": { "label": "34/54", "naklon": 0 }, + "3935": { "label": "34/55", "naklon": 0 }, + "4050": { "label": "34/56", "naklon": 0 }, + "4049": { "label": "34/57", "naklon": 0 }, + "4054": { "label": "34/58", "naklon": 0 }, + "3663": { "label": "34/59", "naklon": 6 }, + "3661": { "label": "34/60", "naklon": 6 }, + "3664": { "label": "34/61", "naklon": 6 }, + "3660": { "label": "34/62", "naklon": 6 }, + "3662": { "label": "34/63", "naklon": 6 }, + "3665": { "label": "34/65", "naklon": 6 }, + "3667": { "label": "34/66", "naklon": 6 }, + "3675": { "label": "34/67", "naklon": 6 }, + "3666": { "label": "34/68", "naklon": 6 }, + "3652": { "label": "34/69", "naklon": 6 }, + "3458": { "label": "34/70", "naklon": 6 }, + "4425": { "label": "34/70/1", "naklon": 6 }, + "3459": { "label": "34/71", "naklon": 6 }, + "3435": { "label": "34/72", "naklon": 6 }, + "3448": { "label": "34/73", "naklon": 6 }, + "3451": { "label": "34/74", "naklon": 6 }, + "3442": { "label": "34/75", "naklon": 6 }, + "3449": { "label": "34/76", "naklon": 6 }, + "3450": { "label": "34/77", "naklon": 6 }, + "3433": { "label": "34/78", "naklon": 6 }, + "3432": { "label": "34/80", "naklon": 12 }, + "3470": { "label": "34/81", "naklon": 12 }, + "3438": { "label": "34/82", "naklon": 12 }, + "3439": { "label": "34/83", "naklon": 12 }, + "4028": { "label": "34/84", "naklon": 5 }, + "3596": { "label": "34/85", "naklon": 5 }, + "4021": { "label": "34/86", "naklon": 5 }, + "3437": { "label": "34/87", "naklon": 12 }, + "3428": { "label": "34/88", "naklon": 12 }, + "3430": { "label": "34/89", "naklon": 12 }, + "3454": { "label": "34/91", "naklon": 6 }, + "3492": { "label": "34/92", "naklon": 6 }, + "3462": { "label": "34/93", "naklon": 6 }, + "3427": { "label": "34/94", "naklon": 6 }, + "3434": { "label": "34/95", "naklon": 6 }, + "3456": { "label": "34/96", "naklon": 6 }, + "4307": { "label": "34/98/1", "naklon": 6 }, + "3968": { "label": "35/1", "naklon": 0 }, + "3969": { "label": "35/2", "naklon": 0 }, + "3947": { "label": "35/3", "naklon": 0 }, + "3979": { "label": "35/4", "naklon": 0 }, + "3959": { "label": "35/5", "naklon": 0 }, + "3948": { "label": "35/6", "naklon": 0 }, + "3961": { "label": "35/7", "naklon": 0 }, + "3956": { "label": "35/8", "naklon": 0 }, + "3604": { "label": "35/9", "naklon": 0 }, + "3944": { "label": "35/10", "naklon": 0 }, + "3960": { "label": "35/11", "naklon": 0 }, + "3958": { "label": "35/12", "naklon": 0 }, + "4036": { "label": "35/13", "naklon": 5 }, + "3893": { "label": "35/18", "naklon": 5 }, + "4108": { "label": "35/19", "naklon": 5 }, + "4017": { "label": "35/20", "naklon": 5 }, + "3963": { "label": "35/21", "naklon": 0 }, + "3658": { "label": "35/22", "naklon": 0 }, + "3975": { "label": "35/23", "naklon": 0 }, + "3980": { "label": "35/24", "naklon": 0 }, + "4012": { "label": "35/25", "naklon": 0 }, + "3655": { "label": "35/26", "naklon": 0 }, + "3962": { "label": "35/27", "naklon": 0 }, + "3945": { "label": "35/28", "naklon": 0 }, + "3569": { "label": "35/29", "naklon": 0 }, + "3429": { "label": "35/30", "naklon": 0 }, + "3657": { "label": "35/31", "naklon": 0 }, + "3646": { "label": "35/32", "naklon": 0 }, + "3622": { "label": "35/33", "naklon": 0 }, + "3612": { "label": "35/34", "naklon": 0 }, + "3955": { "label": "35/35", "naklon": 0 }, + "3878": { "label": "35/37", "naklon": 0 }, + "3965": { "label": "35/38", "naklon": 0 }, + "3970": { "label": "35/39", "naklon": 0 }, + "3611": { "label": "35/40", "naklon": 0 }, + "2635": { "label": "35/41", "naklon": 0 }, + "3978": { "label": "35/42", "naklon": 0 }, + "4213": { "label": "35/43", "naklon": 0 }, + "3984": { "label": "35/44", "naklon": 0 }, + "4218": { "label": "35/45", "naklon": 0 }, + "3973": { "label": "35/46", "naklon": 0 }, + "3974": { "label": "35/47", "naklon": 0 }, + "3759": { "label": "35/48", "naklon": 0 }, + "3844": { "label": "35/49", "naklon": 0 }, + "3804": { "label": "35/50", "naklon": 0 }, + "3831": { "label": "35/51", "naklon": 0 }, + "3643": { "label": "35/52", "naklon": 0 }, + "3966": { "label": "35/53", "naklon": 0 }, + "3971": { "label": "35/54", "naklon": 0 }, + "3650": { "label": "35/55", "naklon": 6 }, + "3651": { "label": "35/56", "naklon": 6 }, + "3669": { "label": "35/57", "naklon": 6 }, + "3648": { "label": "35/58", "naklon": 6 }, + "3645": { "label": "35/59", "naklon": 6 }, + "3659": { "label": "35/60", "naklon": 6 }, + "3647": { "label": "35/61", "naklon": 6 }, + "3644": { "label": "35/62", "naklon": 6 }, + "3671": { "label": "35/63", "naklon": 6 }, + "3682": { "label": "35/64", "naklon": 6 }, + "3672": { "label": "35/65", "naklon": 6 }, + "3683": { "label": "35/66", "naklon": 6 }, + "3673": { "label": "35/67", "naklon": 6 }, + "3674": { "label": "35/68", "naklon": 6 }, + "3679": { "label": "35/69", "naklon": 6 }, + "3649": { "label": "35/70", "naklon": 6 }, + "3687": { "label": "35/71", "naklon": 6 }, + "3677": { "label": "35/72", "naklon": 6 }, + "3690": { "label": "35/73", "naklon": 6 }, + "3691": { "label": "35/74", "naklon": 6 }, + "3676": { "label": "35/75", "naklon": 6 }, + "3680": { "label": "35/76", "naklon": 6 }, + "3668": { "label": "35/77", "naklon": 6 }, + "3681": { "label": "35/78", "naklon": 6 }, + "3670": { "label": "35/79", "naklon": 6 }, + "3689": { "label": "35/80", "naklon": 6 }, + "3678": { "label": "35/81", "naklon": 6 }, + "3693": { "label": "35/82", "naklon": 6 }, + "3654": { "label": "35/83", "naklon": null }, + "4086": { "label": "36/1", "naklon": 0 }, + "4085": { "label": "36/2", "naklon": 0 }, + "4083": { "label": "36/3", "naklon": 0 }, + "4087": { "label": "36/4", "naklon": 0 }, + "4077": { "label": "36/5", "naklon": 0 }, + "4082": { "label": "36/6", "naklon": 0 }, + "4186": { "label": "36/7", "naklon": 0 }, + "4206": { "label": "36/8", "naklon": 0 }, + "4080": { "label": "36/9", "naklon": 0 }, + "4081": { "label": "36/10", "naklon": 0 }, + "4210": { "label": "36/11", "naklon": 0 }, + "4079": { "label": "36/12", "naklon": 0 }, + "4076": { "label": "36/13", "naklon": 0 }, + "3852": { "label": "36/14", "naklon": 0 }, + "2813": { "label": "36/15", "naklon": 0 }, + "4219": { "label": "36/16", "naklon": 0 }, + "3104": { "label": "37/1A", "naklon": 15 }, + "3121": { "label": "37/1B", "naklon": 15 }, + "3113": { "label": "37/2", "naklon": 10 }, + "3118": { "label": "37/3", "naklon": 10 }, + "3111": { "label": "37/4", "naklon": 10 }, + "4020": { "label": "37/5", "naklon": 10 }, + "3119": { "label": "37/6", "naklon": 10 }, + "3110": { "label": "37/7", "naklon": 10 }, + "3108": { "label": "37/8", "naklon": 10 }, + "3107": { "label": "37/12", "naklon": 0 }, + "3199": { "label": "37/13", "naklon": 0 }, + "3120": { "label": "37/14", "naklon": 0 }, + "3122": { "label": "37/15", "naklon": 0 }, + "3908": { "label": "37/16", "naklon": 0 }, + "3114": { "label": "37/17", "naklon": 0 }, + "3105": { "label": "37/18", "naklon": 0 }, + "3116": { "label": "37/19", "naklon": 0 }, + "3106": { "label": "37/20", "naklon": 0 }, + "2887": { "label": "37/21", "naklon": 5 }, + "2888": { "label": "37/22", "naklon": 5 }, + "2877": { "label": "37/23", "naklon": 5 }, + "2891": { "label": "37/24", "naklon": 5 }, + "2886": { "label": "37/25", "naklon": 5 }, + "2892": { "label": "37/26", "naklon": 5 }, + "2882": { "label": "37/27", "naklon": 5 }, + "2883": { "label": "37/28", "naklon": 5 }, + "2876": { "label": "37/29", "naklon": 5 }, + "3109": { "label": "37/30", "naklon": 5 }, + "4152": { "label": "37/31", "naklon": 5 }, + "3117": { "label": "37/32", "naklon": 5 }, + "2870": { "label": "37/33", "naklon": 5 }, + "2867": { "label": "37/34", "naklon": 0 }, + "2865": { "label": "37/35", "naklon": 0 }, + "3096": { "label": "37/36", "naklon": 0 }, + "2871": { "label": "37/37", "naklon": 0 }, + "2884": { "label": "37/38", "naklon": 0 }, + "2855": { "label": "37/39", "naklon": 0 }, + "2878": { "label": "37/40", "naklon": 0 }, + "2889": { "label": "37/41", "naklon": 0 }, + "2879": { "label": "37/42", "naklon": 0 }, + "2850": { "label": "37/43", "naklon": 0 }, + "2894": { "label": "37/44", "naklon": 0 }, + "2880": { "label": "37/45", "naklon": 0 }, + "2893": { "label": "37/46", "naklon": 0 }, + "2890": { "label": "37/47", "naklon": 0 }, + "4355": { "label": "37/48", "naklon": 0 }, + "2885": { "label": "37/49", "naklon": 0 }, + "2875": { "label": "37/50", "naklon": 0 }, + "3486": { "label": "38/30A", "naklon": 5 }, + "3714": { "label": "38/30B", "naklon": 0 }, + "3483": { "label": "38/32A", "naklon": 5 }, + "3496": { "label": "38/32B", "naklon": 0 }, + "3487": { "label": "38/35A", "naklon": 5 }, + "3498": { "label": "38/35B", "naklon": 5 }, + "3578": { "label": "38/38A", "naklon": 5 }, + "3508": { "label": "38/38B", "naklon": 5 }, + "3787": { "label": "38/59A", "naklon": 5 }, + "3491": { "label": "38/59B", "naklon": 5 }, + "3568": { "label": "38/1", "naklon": null }, + "3502": { "label": "38/2", "naklon": 0 }, + "3836": { "label": "38/3", "naklon": 0 }, + "3588": { "label": "38/4", "naklon": 0 }, + "3493": { "label": "38/5", "naklon": 0 }, + "3580": { "label": "38/6", "naklon": 0 }, + "3572": { "label": "38/7", "naklon": 0 }, + "3506": { "label": "38/8", "naklon": 0 }, + "3503": { "label": "38/9", "naklon": 0 }, + "3579": { "label": "38/10", "naklon": 0 }, + "3586": { "label": "38/11", "naklon": 0 }, + "3495": { "label": "38/12", "naklon": 5 }, + "3492": { "label": "38/13", "naklon": 5 }, + "3532": { "label": "38/14", "naklon": 5 }, + "3574": { "label": "38/15", "naklon": 5 }, + "4140": { "label": "38/16", "naklon": 5 }, + "3795": { "label": "38/17", "naklon": 5 }, + "3788": { "label": "38/18", "naklon": 5 }, + "3796": { "label": "38/19", "naklon": 5 }, + "3797": { "label": "38/20", "naklon": 5 }, + "3798": { "label": "38/21", "naklon": 5 }, + "3786": { "label": "38/22", "naklon": 5 }, + "4067": { "label": "38/23", "naklon": 5 }, + "3773": { "label": "38/24", "naklon": 5 }, + "3774": { "label": "38/25", "naklon": 5 }, + "3789": { "label": "38/26", "naklon": 5 }, + "3520": { "label": "38/27", "naklon": null }, + "3577": { "label": "38/29", "naklon": 5 }, + "3530": { "label": "38/31", "naklon": null }, + "3488": { "label": "38/33", "naklon": 5 }, + "3505": { "label": "38/34", "naklon": 5 }, + "3497": { "label": "38/36", "naklon": 5 }, + "3490": { "label": "38/37", "naklon": 5 }, + "3585": { "label": "38/39", "naklon": 5 }, + "3582": { "label": "38/40", "naklon": 5 }, + "3507": { "label": "38/41", "naklon": 5 }, + "3484": { "label": "38/42", "naklon": 5 }, + "3501": { "label": "38/43", "naklon": 5 }, + "3581": { "label": "38/44", "naklon": 5 }, + "4192": { "label": "38/45", "naklon": 5 }, + "3576": { "label": "38/46", "naklon": 5 }, + "3489": { "label": "38/47", "naklon": 5 }, + "3573": { "label": "38/48", "naklon": 5 }, + "3504": { "label": "38/49", "naklon": 5 }, + "3794": { "label": "38/50", "naklon": 5 }, + "3485": { "label": "38/51", "naklon": 5 }, + "3482": { "label": "38/52", "naklon": 5 }, + "3575": { "label": "38/53", "naklon": 5 }, + "3499": { "label": "38/54", "naklon": 5 }, + "3494": { "label": "38/55", "naklon": 5 }, + "3583": { "label": "38/56", "naklon": 5 }, + "3570": { "label": "38/57", "naklon": 5 }, + "3500": { "label": "38/58", "naklon": 0 }, + "3510": { "label": "38/63", "naklon": null }, + "3512": { "label": "38/64", "naklon": null }, + "3535": { "label": "38/67", "naklon": null }, + "3531": { "label": "38/68", "naklon": null }, + "3537": { "label": "38/69", "naklon": null }, + "3522": { "label": "39/1", "naklon": 10 }, + "4018": { "label": "39/2", "naklon": 10 }, + "4019": { "label": "39/3", "naklon": 10 }, + "4154": { "label": "39/4", "naklon": 5 }, + "3907": { "label": "39/5", "naklon": 5 }, + "4148": { "label": "39/6", "naklon": 0 }, + "4153": { "label": "39/7", "naklon": 0 }, + "3938": { "label": "39/8", "naklon": 0 }, + "3802": { "label": "39/9", "naklon": 0 }, + "4015": { "label": "39/10", "naklon": 0 }, + "3929": { "label": "39/11", "naklon": 0 }, + "3946": { "label": "39/12", "naklon": 0 }, + "4014": { "label": "39/13", "naklon": 0 }, + "4155": { "label": "39/14", "naklon": 0 }, + "4149": { "label": "39/15", "naklon": 0 }, + "3642": { "label": "39/16", "naklon": 0 }, + "3636": { "label": "39/17", "naklon": 5 }, + "3991": { "label": "39/18", "naklon": 0 }, + "3994": { "label": "39/19", "naklon": 0 }, + "3990": { "label": "39/20", "naklon": 0 }, + "3967": { "label": "39/21", "naklon": 0 }, + "3977": { "label": "39/22", "naklon": 0 }, + "3757": { "label": "39/23", "naklon": 15 }, + "3633": { "label": "39/24", "naklon": 15 }, + "3744": { "label": "39/25", "naklon": 15 }, + "4023": { "label": "39/26", "naklon": 5 }, + "3720": { "label": "39/27", "naklon": 5 }, + "3734": { "label": "39/28", "naklon": 5 }, + "3741": { "label": "39/29", "naklon": 5 }, + "3721": { "label": "39/30", "naklon": 5 }, + "3845": { "label": "39/31", "naklon": 0 }, + "3840": { "label": "39/32", "naklon": 0 }, + "3837": { "label": "39/33", "naklon": null }, + "3839": { "label": "39/34", "naklon": 0 }, + "3542": { "label": "41/1", "naklon": null }, + "3566": { "label": "41/2", "naklon": null }, + "3548": { "label": "41/3", "naklon": null }, + "3515": { "label": "41/4", "naklon": null }, + "3559": { "label": "41/5", "naklon": null }, + "3509": { "label": "41/6", "naklon": null }, + "3524": { "label": "41/7", "naklon": null }, + "3518": { "label": "41/8", "naklon": null }, + "3182": { "label": "41/9", "naklon": null }, + "3187": { "label": "41/10", "naklon": null }, + "3195": { "label": "41/11", "naklon": 0 }, + "3857": { "label": "41/12", "naklon": 0 }, + "3183": { "label": "41/13", "naklon": 0 }, + "3177": { "label": "41/14", "naklon": 0 }, + "3189": { "label": "41/15", "naklon": 0 }, + "3186": { "label": "41/16", "naklon": 0 }, + "3178": { "label": "42/1", "naklon": 0 }, + "3219": { "label": "42/2", "naklon": 0 }, + "3475": { "label": "42/3", "naklon": 0 }, + "3175": { "label": "42/4", "naklon": 0 }, + "3222": { "label": "42/5", "naklon": 0 }, + "3221": { "label": "42/6", "naklon": 0 }, + "3181": { "label": "42/7", "naklon": 0 }, + "3180": { "label": "42/8", "naklon": 0 }, + "3218": { "label": "42/9", "naklon": 0 }, + "3176": { "label": "42/10", "naklon": 0 }, + "3174": { "label": "42/11", "naklon": 0 }, + "3220": { "label": "42/12", "naklon": 0 }, + "3533": { "label": "42/13", "naklon": null }, + "3543": { "label": "42/14", "naklon": null }, + "3554": { "label": "42/15", "naklon": null }, + "3549": { "label": "42/16", "naklon": null }, + "2857": { "label": "43/1", "naklon": 5 }, + "2752": { "label": "43/2", "naklon": 5 }, + "2753": { "label": "43/3", "naklon": 5 }, + "3024": { "label": "43/4", "naklon": 5 }, + "2754": { "label": "43/5", "naklon": 5 }, + "4423": { "label": "43/6", "naklon": 5 }, + "4368": { "label": "43/7", "naklon": 5 }, + "2978": { "label": "43/8", "naklon": 5 }, + "2868": { "label": "43/9", "naklon": 5 }, + "4377": { "label": "43/10", "naklon": 5 }, + "2757": { "label": "43/11", "naklon": 5 }, + "2970": { "label": "43/12", "naklon": 5 }, + "2758": { "label": "43/13", "naklon": 5 }, + "4378": { "label": "43/14", "naklon": 5 }, + "2759": { "label": "43/15", "naklon": 5 }, + "4342": { "label": "43/16", "naklon": 5 }, + "3026": { "label": "43/17", "naklon": null }, + "2986": { "label": "43/18", "naklon": null }, + "4343": { "label": "43/19", "naklon": null }, + "2760": { "label": "43/20", "naklon": null }, + "4379": { "label": "43/21", "naklon": null }, + "2971": { "label": "43/22", "naklon": null }, + "2761": { "label": "43/23", "naklon": null }, + "2762": { "label": "43/24", "naklon": null }, + "4339": { "label": "43/25", "naklon": null }, + "4380": { "label": "43/26", "naklon": null }, + "2975": { "label": "43/27", "naklon": null }, + "3003": { "label": "43/28", "naklon": null }, + "4338": { "label": "43/29", "naklon": null }, + "3002": { "label": "43/30", "naklon": null }, + "4345": { "label": "43/31", "naklon": null }, + "2979": { "label": "43/32", "naklon": null }, + "2989": { "label": "43/33", "naklon": null }, + "2996": { "label": "43/34", "naklon": null }, + "2972": { "label": "43/35", "naklon": null }, + "2988": { "label": "43/36", "naklon": null }, + "4344": { "label": "43/37", "naklon": null }, + "3022": { "label": "43/38", "naklon": null }, + "4341": { "label": "43/39", "naklon": null }, + "2983": { "label": "43/40", "naklon": null }, + "2995": { "label": "43/41", "naklon": null }, + "2763": { "label": "43/42", "naklon": null }, + "2764": { "label": "43/43", "naklon": null }, + "2765": { "label": "43/44", "naklon": null }, + "2766": { "label": "43/45", "naklon": null }, + "2767": { "label": "43/46", "naklon": null }, + "2768": { "label": "43/47", "naklon": null }, + "3018": { "label": "43/48", "naklon": null }, + "2982": { "label": "43/49", "naklon": null }, + "3019": { "label": "43/50", "naklon": 0 }, + "3013": { "label": "43/51", "naklon": null }, + "3007": { "label": "43/52", "naklon": null }, + "2980": { "label": "43/53", "naklon": null }, + "3011": { "label": "43/54", "naklon": null }, + "2672": { "label": "43/55", "naklon": null }, + "2673": { "label": "43/56", "naklon": null }, + "2674": { "label": "43/57", "naklon": null }, + "2675": { "label": "43/58", "naklon": null }, + "2676": { "label": "43/59", "naklon": null }, + "2677": { "label": "43/60", "naklon": null }, + "2678": { "label": "43/61", "naklon": null }, + "2679": { "label": "43/62", "naklon": null }, + "2680": { "label": "43/63", "naklon": null }, + "2840": { "label": "43/64", "naklon": null }, + "2682": { "label": "43/65", "naklon": null }, + "2683": { "label": "43/66", "naklon": null }, + "2684": { "label": "43/67", "naklon": 0 }, + "2685": { "label": "43/68", "naklon": null }, + "2686": { "label": "43/69", "naklon": null }, + "2687": { "label": "43/70", "naklon": null }, + "2688": { "label": "43/71", "naklon": null }, + "2689": { "label": "43/72", "naklon": null }, + "2690": { "label": "43/73", "naklon": null }, + "2691": { "label": "43/74", "naklon": null }, + "2692": { "label": "43/75", "naklon": null }, + "2693": { "label": "43/76", "naklon": 0 }, + "2694": { "label": "43/77", "naklon": null }, + "2695": { "label": "43/78", "naklon": null }, + "2696": { "label": "43/79", "naklon": 0 }, + "2697": { "label": "43/80", "naklon": null }, + "2698": { "label": "43/81", "naklon": 0 }, + "2699": { "label": "43/82", "naklon": null }, + "2700": { "label": "43/83", "naklon": 0 }, + "2744": { "label": "43/84", "naklon": null }, + "2745": { "label": "43/85", "naklon": 0 }, + "2746": { "label": "43/86", "naklon": null }, + "2747": { "label": "43/87", "naklon": 0 }, + "2748": { "label": "43/88", "naklon": null }, + "2749": { "label": "43/89", "naklon": 0 }, + "2841": { "label": "43/90", "naklon": null }, + "4237": { "label": "45/1", "naklon": 5 }, + "4226": { "label": "45/2", "naklon": 5 }, + "4242": { "label": "45/3", "naklon": 5 }, + "4179": { "label": "45/4", "naklon": 5 }, + "4247": { "label": "45/5", "naklon": 5 }, + "4245": { "label": "45/6", "naklon": 5 }, + "3872": { "label": "45/7", "naklon": 5 }, + "4175": { "label": "45/8", "naklon": 5 }, + "4236": { "label": "45/9", "naklon": 5 }, + "4170": { "label": "45/10", "naklon": 5 }, + "4238": { "label": "45/11", "naklon": 5 }, + "4246": { "label": "45/12", "naklon": 5 }, + "4166": { "label": "45/13", "naklon": 5 }, + "4227": { "label": "45/14", "naklon": 5 }, + "4171": { "label": "45/15", "naklon": 5 }, + "4180": { "label": "45/16", "naklon": 5 }, + "4244": { "label": "45/17", "naklon": 5 }, + "4199": { "label": "45/18", "naklon": 5 }, + "4239": { "label": "45/19", "naklon": 5 }, + "4207": { "label": "45/20", "naklon": 5 }, + "4223": { "label": "45/21", "naklon": 5 }, + "4230": { "label": "45/22", "naklon": 5 }, + "4233": { "label": "45/23", "naklon": 5 }, + "4222": { "label": "45/24", "naklon": 5 }, + "4217": { "label": "45/25", "naklon": 5 }, + "4243": { "label": "45/26", "naklon": 5 }, + "4200": { "label": "45/27", "naklon": 5 }, + "4228": { "label": "45/28", "naklon": 5 }, + "4211": { "label": "45/29", "naklon": 5 }, + "4234": { "label": "45/30", "naklon": 5 }, + "4235": { "label": "45/31", "naklon": 5 }, + "4203": { "label": "45/32", "naklon": 5 }, + "4240": { "label": "45/33", "naklon": 5 }, + "4224": { "label": "45/34", "naklon": 5 }, + "4232": { "label": "45/35", "naklon": 5 }, + "4231": { "label": "45/36", "naklon": 5 }, + "4161": { "label": "45/37", "naklon": 5 }, + "4225": { "label": "45/38", "naklon": 5 }, + "4241": { "label": "45/39", "naklon": 5 }, + "4229": { "label": "45/40", "naklon": 5 }, + "4221": { "label": "45/41", "naklon": 5 }, + "4212": { "label": "45/42", "naklon": 5 }, + "4216": { "label": "45/43", "naklon": 5 }, + "3864": { "label": "45/44", "naklon": null }, + "3806": { "label": "46/1", "naklon": 5 }, + "3813": { "label": "46/2", "naklon": 5 }, + "3815": { "label": "46/3", "naklon": 5 }, + "3807": { "label": "46/4", "naklon": 5 }, + "3895": { "label": "46/5", "naklon": 5 }, + "3809": { "label": "46/6", "naklon": 5 }, + "3820": { "label": "46/7", "naklon": 5 }, + "3805": { "label": "46/8", "naklon": 5 }, + "3894": { "label": "46/9", "naklon": 0 }, + "4055": { "label": "46/10", "naklon": 0 }, + "3812": { "label": "46/11", "naklon": 5 }, + "3822": { "label": "46/12", "naklon": 5 }, + "3821": { "label": "46/13", "naklon": 5 }, + "3808": { "label": "46/14", "naklon": 5 }, + "3799": { "label": "46/15", "naklon": 5 }, + "3816": { "label": "46/16", "naklon": 5 }, + "3751": { "label": "46/17", "naklon": 5 }, + "3814": { "label": "46/18", "naklon": 5 }, + "4044": { "label": "46/19", "naklon": 0 }, + "3931": { "label": "46/20", "naklon": 0 }, + "3902": { "label": "46/21", "naklon": 5 }, + "3916": { "label": "46/22", "naklon": 5 }, + "3892": { "label": "46/23", "naklon": 5 }, + "3914": { "label": "46/24", "naklon": 5 }, + "3898": { "label": "46/25", "naklon": 5 }, + "3897": { "label": "46/26", "naklon": 5 }, + "3885": { "label": "46/27", "naklon": 5 }, + "3906": { "label": "46/28", "naklon": 5 }, + "3930": { "label": "46/29", "naklon": 0 }, + "3936": { "label": "46/30", "naklon": 0 }, + "3860": { "label": "46/31", "naklon": 5 }, + "3841": { "label": "46/32", "naklon": 5 }, + "3873": { "label": "46/33", "naklon": 5 }, + "3854": { "label": "46/34", "naklon": 5 }, + "3939": { "label": "46/35", "naklon": 5 }, + "3858": { "label": "46/36", "naklon": 5 }, + "3940": { "label": "46/37", "naklon": 5 }, + "4035": { "label": "46/38", "naklon": 5 }, + "3373": { "label": "47/1", "naklon": 0 }, + "3374": { "label": "47/2", "naklon": 0 }, + "3384": { "label": "47/3", "naklon": 0 }, + "3385": { "label": "47/4", "naklon": 0 }, + "4051": { "label": "48/1", "naklon": 5 }, + "4041": { "label": "48/2", "naklon": 5 }, + "4056": { "label": "48/3", "naklon": 5 }, + "3875": { "label": "48/4", "naklon": 5 }, + "4061": { "label": "48/5", "naklon": 5 }, + "4047": { "label": "48/6", "naklon": 5 }, + "4060": { "label": "48/7", "naklon": 5 }, + "4059": { "label": "48/8", "naklon": 5 }, + "4058": { "label": "48/9", "naklon": 5 }, + "3635": { "label": "48/10", "naklon": 5 }, + "3640": { "label": "48/11", "naklon": 5 }, + "3747": { "label": "48/12", "naklon": 5 }, + "3629": { "label": "48/13", "naklon": 5 }, + "4048": { "label": "48/14", "naklon": 5 }, + "4063": { "label": "48/15", "naklon": 5 }, + "4062": { "label": "48/16", "naklon": 5 }, + "4043": { "label": "48/17", "naklon": 5 }, + "4052": { "label": "48/18", "naklon": 5 }, + "4042": { "label": "48/19", "naklon": 5 }, + "4053": { "label": "48/20", "naklon": 5 }, + "4167": { "label": "50/15A", "naklon": null }, + "4159": { "label": "50/15B", "naklon": null }, + "4183": { "label": "50/1", "naklon": 0 }, + "4157": { "label": "50/2", "naklon": 0 }, + "4160": { "label": "50/3", "naklon": 0 }, + "4173": { "label": "50/4", "naklon": 0 }, + "4177": { "label": "50/5", "naklon": 0 }, + "4174": { "label": "50/6", "naklon": 0 }, + "4178": { "label": "50/7", "naklon": 0 }, + "4195": { "label": "50/8", "naklon": 0 }, + "4169": { "label": "50/9", "naklon": 0 }, + "4162": { "label": "50/10", "naklon": 0 }, + "4158": { "label": "50/11", "naklon": 0 }, + "4182": { "label": "50/12", "naklon": 0 }, + "4194": { "label": "50/13", "naklon": 0 }, + "4184": { "label": "50/14", "naklon": 0 }, + "4197": { "label": "50/16", "naklon": null }, + "4164": { "label": "50/17", "naklon": null }, + "3306": { "label": "50/18", "naklon": null }, + "4168": { "label": "50/19", "naklon": null }, + "4193": { "label": "50/20", "naklon": null }, + "4187": { "label": "50/21", "naklon": null }, + "4163": { "label": "50/22", "naklon": null }, + "4165": { "label": "50/23", "naklon": null }, + "4185": { "label": "50/24", "naklon": null }, + "3904": { "label": "50/25", "naklon": null }, + "2619": { "label": "53/1", "naklon": 0 }, + "2623": { "label": "53/2", "naklon": 0 }, + "2617": { "label": "53/3", "naklon": 0 }, + "2622": { "label": "53/4", "naklon": 0 }, + "2618": { "label": "53/5", "naklon": 0 }, + "2626": { "label": "53/6", "naklon": 0 }, + "2869": { "label": "53/7", "naklon": 0 }, + "2613": { "label": "53/8", "naklon": 0 }, + "2608": { "label": "53/9", "naklon": 0 }, + "2611": { "label": "53/10", "naklon": 0 }, + "2598": { "label": "53/11", "naklon": 0 }, + "3528": { "label": "53/12", "naklon": 0 }, + "3545": { "label": "53/13", "naklon": 0 }, + "2620": { "label": "53/14", "naklon": 0 }, + "2612": { "label": "53/15", "naklon": 0 }, + "2615": { "label": "53/16", "naklon": 0 }, + "3722": { "label": "53/17", "naklon": 0 }, + "2624": { "label": "53/18", "naklon": 0 }, + "2609": { "label": "53/19", "naklon": 0 }, + "2625": { "label": "53/20", "naklon": 0 }, + "2602": { "label": "53/21", "naklon": 0 }, + "2610": { "label": "53/22", "naklon": 0 }, + "2599": { "label": "53/23", "naklon": 0 }, + "2605": { "label": "53/24", "naklon": 0 }, + "2593": { "label": "53/25", "naklon": 0 }, + "3074": { "label": "53/26", "naklon": 0 }, + "2740": { "label": "53/27", "naklon": 0 }, + "2614": { "label": "53/28", "naklon": 0 }, + "2601": { "label": "53/29", "naklon": 0 }, + "4196": { "label": "53/30", "naklon": 0 }, + "2607": { "label": "53/31", "naklon": 0 }, + "2582": { "label": "53/32", "naklon": 0 }, + "2594": { "label": "53/33", "naklon": 0 }, + "2589": { "label": "53/34", "naklon": 0 }, + "2596": { "label": "53/35", "naklon": 0 }, + "2603": { "label": "53/36", "naklon": 0 }, + "2597": { "label": "53/37", "naklon": 0 }, + "2590": { "label": "53/38", "naklon": 0 }, + "2581": { "label": "53/39", "naklon": 0 }, + "2583": { "label": "53/40", "naklon": 0 }, + "2580": { "label": "53/41", "naklon": 0 }, + "2579": { "label": "53/42", "naklon": 0 }, + "2797": { "label": "53/43", "naklon": 0 }, + "2577": { "label": "53/44", "naklon": 0 }, + "2586": { "label": "53/45", "naklon": 0 }, + "2588": { "label": "53/46", "naklon": 0 }, + "2591": { "label": "53/47", "naklon": 0 }, + "2592": { "label": "53/48", "naklon": 0 }, + "2573": { "label": "53/49", "naklon": 0 }, + "2595": { "label": "53/50", "naklon": 0 }, + "2587": { "label": "53/51", "naklon": 0 }, + "2578": { "label": "53/52", "naklon": 0 }, + "2574": { "label": "53/53", "naklon": 0 }, + "2571": { "label": "53/54", "naklon": 0 }, + "2570": { "label": "53/55", "naklon": 0 }, + "2576": { "label": "53/56", "naklon": 0 }, + "2881": { "label": "53/57", "naklon": 0 }, + "2575": { "label": "53/58", "naklon": 0 }, + "2572": { "label": "53/59", "naklon": 0 }, + "2569": { "label": "53/60", "naklon": 0 }, + "4324": { "label": "55/1", "naklon": 0 }, + "4319": { "label": "55/2", "naklon": 0 }, + "4327": { "label": "55/3", "naklon": 0 }, + "4333": { "label": "55/4", "naklon": 0 }, + "4332": { "label": "55/5", "naklon": 0 }, + "4320": { "label": "55/6", "naklon": 0 }, + "4317": { "label": "55/7", "naklon": 0 }, + "4318": { "label": "55/8", "naklon": 0 }, + "4328": { "label": "55/9", "naklon": 0 }, + "4323": { "label": "55/10", "naklon": 0 }, + "4325": { "label": "55/11", "naklon": 0 }, + "4326": { "label": "55/12", "naklon": 0 }, + "4316": { "label": "55/13", "naklon": 0 }, + "4322": { "label": "55/14", "naklon": 0 }, + "4331": { "label": "55/15", "naklon": 0 }, + "4321": { "label": "55/16", "naklon": 0 }, + "4315": { "label": "55/17", "naklon": 0 }, + "4329": { "label": "55/18", "naklon": 0 }, + "4334": { "label": "55/19", "naklon": 0 }, + "4330": { "label": "55/20", "naklon": 0 } +}; + + +let svetlaSorted = [{ "label": "1/3A", "node": 3993, "naklon": 0 }, +{ "label": "1/3B", "node": 3989, "naklon": 15 }, +{ "label": "1/1", "node": 3976, "naklon": 0 }, +{ "label": "1/2", "node": 4181, "naklon": 0 }, +{ "label": "1/4", "node": 4376, "naklon": 15 }, +{ "label": "1/5", "node": 3868, "naklon": 15 }, +{ "label": "1/6", "node": 3728, "naklon": 15 }, +{ "label": "1/7", "node": 3730, "naklon": 0 }, +{ "label": "1/8", "node": 4374, "naklon": 0 }, +{ "label": "1/9", "node": 3718, "naklon": 15 }, +{ "label": "1/10", "node": 4375, "naklon": 15 }, +{ "label": "1/11", "node": 4172, "naklon": 15 }, +{ "label": "1/12", "node": 4176, "naklon": 15 }, +{ "label": "2/1", "node": 3800, "naklon": 5 }, +{ "label": "2/2", "node": 3823, "naklon": 5 }, +{ "label": "2/3", "node": 3905, "naklon": 5 }, +{ "label": "2/4", "node": 3803, "naklon": 5 }, +{ "label": "2/5", "node": 3817, "naklon": 5 }, +{ "label": "2/6", "node": 3818, "naklon": 5 }, +{ "label": "2/7", "node": 3811, "naklon": 5 }, +{ "label": "2/8", "node": 3915, "naklon": 5 }, +{ "label": "2/9", "node": 3843, "naklon": 10 }, +{ "label": "2/10", "node": 3827, "naklon": 10 }, +{ "label": "2/11", "node": 4220, "naklon": 10 }, +{ "label": "2/12", "node": 3826, "naklon": 10 }, +{ "label": "2/13", "node": 3834, "naklon": 10 }, +{ "label": "2/14", "node": 3838, "naklon": 10 }, +{ "label": "2/15", "node": 2823, "naklon": 10 }, +{ "label": "2/16", "node": 3750, "naklon": 10 }, +{ "label": "2/17", "node": 3378, "naklon": 0 }, +{ "label": "2/18", "node": 3376, "naklon": 0 }, +{ "label": "2/19", "node": 3379, "naklon": 0 }, +{ "label": "2/20", "node": 3285, "naklon": 0 }, +{ "label": "2/21", "node": 3382, "naklon": 0 }, +{ "label": "2/22", "node": 3383, "naklon": 0 }, +{ "label": "2/24", "node": 3375, "naklon": 0 }, +{ "label": "2/25", "node": 3381, "naklon": 0 }, +{ "label": "2/26", "node": 3380, "naklon": 0 }, +{ "label": "2/27", "node": 3828, "naklon": 10 }, +{ "label": "2/28", "node": 3377, "naklon": 0 }, +{ "label": "7/1", "node": 3591, "naklon": 0 }, +{ "label": "7/2", "node": 3587, "naklon": 0 }, +{ "label": "7/3", "node": 3468, "naklon": 0 }, +{ "label": "7/4", "node": 3466, "naklon": 0 }, +{ "label": "7/5", "node": 3474, "naklon": 0 }, +{ "label": "7/6", "node": 3481, "naklon": 0 }, +{ "label": "7/7", "node": 3589, "naklon": 0 }, +{ "label": "7/8", "node": 3472, "naklon": 0 }, +{ "label": "7/9", "node": 3473, "naklon": 0 }, +{ "label": "7/10", "node": 3584, "naklon": 0 }, +{ "label": "7/11", "node": 3571, "naklon": 0 }, +{ "label": "7/12", "node": 3476, "naklon": 0 }, +{ "label": "7/13", "node": 3590, "naklon": 0 }, +{ "label": "7/14", "node": 3478, "naklon": 0 }, +{ "label": "7/15", "node": 3471, "naklon": 0 }, +{ "label": "7/16", "node": 3467, "naklon": 0 }, +{ "label": "7/17", "node": 3479, "naklon": 0 }, +{ "label": "7/18", "node": 3480, "naklon": 0 }, +{ "label": "7/19", "node": 3477, "naklon": 0 }, +{ "label": "12/1", "node": 3362, "naklon": 0 }, +{ "label": "12/2", "node": 3355, "naklon": 0 }, +{ "label": "12/3", "node": 3356, "naklon": 0 }, +{ "label": "12/4", "node": 3349, "naklon": 0 }, +{ "label": "12/5", "node": 3357, "naklon": 0 }, +{ "label": "12/6", "node": 3350, "naklon": 0 }, +{ "label": "12/7", "node": 3353, "naklon": 0 }, +{ "label": "12/8", "node": 3539, "naklon": 0 }, +{ "label": "12/9", "node": 3050, "naklon": 0 }, +{ "label": "12/10", "node": 3361, "naklon": 0 }, +{ "label": "12/11", "node": 3360, "naklon": 0 }, +{ "label": "12/12", "node": 3358, "naklon": 0 }, +{ "label": "12/13", "node": 3541, "naklon": 0 }, +{ "label": "12/14", "node": 3551, "naklon": 0 }, +{ "label": "12/15", "node": 3514, "naklon": 0 }, +{ "label": "12/16", "node": 3547, "naklon": 0 }, +{ "label": "12/17", "node": 3562, "naklon": 0 }, +{ "label": "12/18", "node": 3525, "naklon": 0 }, +{ "label": "12/19", "node": 3558, "naklon": 0 }, +{ "label": "12/20", "node": 3511, "naklon": 0 }, +{ "label": "12/21", "node": 3058, "naklon": 0 }, +{ "label": "12/22", "node": 3062, "naklon": 0 }, +{ "label": "12/23", "node": 3070, "naklon": 0 }, +{ "label": "12/24", "node": 3447, "naklon": 0 }, +{ "label": "12/25", "node": 3056, "naklon": 0 }, +{ "label": "12/26", "node": 3057, "naklon": 0 }, +{ "label": "12/27", "node": 3071, "naklon": 0 }, +{ "label": "12/28", "node": 3061, "naklon": 0 }, +{ "label": "12/29", "node": 3069, "naklon": 0 }, +{ "label": "12/30", "node": 3077, "naklon": 0 }, +{ "label": "12/31", "node": 3080, "naklon": 0 }, +{ "label": "12/32", "node": 3081, "naklon": 0 }, +{ "label": "12/33", "node": 3078, "naklon": 0 }, +{ "label": "12/34", "node": 4037, "naklon": 0 }, +{ "label": "12/35", "node": 3067, "naklon": 0 }, +{ "label": "12/36", "node": 3051, "naklon": 0 }, +{ "label": "12/37", "node": 2924, "naklon": 0 }, +{ "label": "12/38", "node": 3060, "naklon": 0 }, +{ "label": "12/39", "node": 3073, "naklon": 0 }, +{ "label": "12/40", "node": 3469, "naklon": 0 }, +{ "label": "12/41", "node": 2923, "naklon": 0 }, +{ "label": "12/42", "node": 2925, "naklon": 0 }, +{ "label": "12/43", "node": 3359, "naklon": 0 }, +{ "label": "12/44", "node": 3055, "naklon": 0 }, +{ "label": "12/45", "node": 2922, "naklon": 0 }, +{ "label": "12/46", "node": 3084, "naklon": 0 }, +{ "label": "12/47", "node": 3064, "naklon": 0 }, +{ "label": "12/48", "node": 3066, "naklon": 0 }, +{ "label": "12/49", "node": 3072, "naklon": 0 }, +{ "label": "13/13A", "node": 3415, "naklon": 0 }, +{ "label": "13/13B", "node": 3409, "naklon": 0 }, +{ "label": "13/13C", "node": 3399, "naklon": 0 }, +{ "label": "13/29A", "node": 3410, "naklon": 0 }, +{ "label": "13/29B", "node": 3407, "naklon": 0 }, +{ "label": "13/34A", "node": 3405, "naklon": 0 }, +{ "label": "13/34B", "node": 3404, "naklon": 0 }, +{ "label": "13/45A", "node": 3392, "naklon": 0 }, +{ "label": "13/45B", "node": 3386, "naklon": 0 }, +{ "label": "13/60A", "node": 3303, "naklon": 3 }, +{ "label": "13/60B", "node": 3302, "naklon": 3 }, +{ "label": "13/70A", "node": 3319, "naklon": 6 }, +{ "label": "13/70B", "node": 3317, "naklon": 6 }, +{ "label": "13/70C", "node": 3326, "naklon": 6 }, +{ "label": "13/73A", "node": 3351, "naklon": 6 }, +{ "label": "13/73B", "node": 3313, "naklon": 6 }, +{ "label": "13/83A", "node": 3316, "naklon": 0 }, +{ "label": "13/83B", "node": 3320, "naklon": 0 }, +{ "label": "13/95A", "node": 3336, "naklon": 0 }, +{ "label": "13/95B", "node": 3323, "naklon": 0 }, +{ "label": "13/98A", "node": 3339, "naklon": 0 }, +{ "label": "13/98B", "node": 3333, "naklon": 0 }, +{ "label": "13/1", "node": 3425, "naklon": 0 }, +{ "label": "13/2", "node": 3419, "naklon": 0 }, +{ "label": "13/3", "node": 3416, "naklon": 0 }, +{ "label": "13/4", "node": 3332, "naklon": 0 }, +{ "label": "13/5", "node": 3422, "naklon": 0 }, +{ "label": "13/6", "node": 3417, "naklon": 0 }, +{ "label": "13/7", "node": 3418, "naklon": 0 }, +{ "label": "13/8", "node": 3424, "naklon": 0 }, +{ "label": "13/9", "node": 3334, "naklon": 0 }, +{ "label": "13/10", "node": 4363, "naklon": 0 }, +{ "label": "13/11", "node": 3423, "naklon": 0 }, +{ "label": "13/12", "node": 3406, "naklon": 0 }, +{ "label": "13/14", "node": 3411, "naklon": 0 }, +{ "label": "13/15", "node": 3412, "naklon": 0 }, +{ "label": "13/16", "node": 3413, "naklon": 0 }, +{ "label": "13/17", "node": 3414, "naklon": 0 }, +{ "label": "13/18", "node": 3391, "naklon": 0 }, +{ "label": "13/19", "node": 3370, "naklon": 0 }, +{ "label": "13/20", "node": 3369, "naklon": 0 }, +{ "label": "13/21", "node": 3408, "naklon": 0 }, +{ "label": "13/22", "node": 3393, "naklon": 0 }, +{ "label": "13/23", "node": 3128, "naklon": 0 }, +{ "label": "13/24", "node": 3197, "naklon": 0 }, +{ "label": "13/25", "node": 4364, "naklon": 0 }, +{ "label": "13/26", "node": 3155, "naklon": 0 }, +{ "label": "13/27", "node": 3196, "naklon": 0 }, +{ "label": "13/28", "node": 3144, "naklon": 0 }, +{ "label": "13/30", "node": 3150, "naklon": 0 }, +{ "label": "13/31", "node": 3390, "naklon": 0 }, +{ "label": "13/32", "node": 3401, "naklon": 0 }, +{ "label": "13/33", "node": 3275, "naklon": 0 }, +{ "label": "13/35", "node": 3371, "naklon": 0 }, +{ "label": "13/36", "node": 3389, "naklon": 0 }, +{ "label": "13/37", "node": 3388, "naklon": 0 }, +{ "label": "13/38", "node": 3365, "naklon": 0 }, +{ "label": "13/39", "node": 3363, "naklon": 0 }, +{ "label": "13/40", "node": 3397, "naklon": 0 }, +{ "label": "13/40/1", "node": 3567, "naklon": 0 }, +{ "label": "13/41", "node": 3387, "naklon": 0 }, +{ "label": "13/42", "node": 3403, "naklon": 0 }, +{ "label": "13/43", "node": 3147, "naklon": 0 }, +{ "label": "13/44", "node": 3141, "naklon": 0 }, +{ "label": "13/46", "node": 3364, "naklon": 0 }, +{ "label": "13/47", "node": 3367, "naklon": 0 }, +{ "label": "13/48", "node": 3368, "naklon": 0 }, +{ "label": "13/49", "node": 3402, "naklon": 0 }, +{ "label": "13/50", "node": 3366, "naklon": 0 }, +{ "label": "13/51", "node": 3395, "naklon": 0 }, +{ "label": "13/52", "node": 3372, "naklon": 0 }, +{ "label": "13/53", "node": 3394, "naklon": 0 }, +{ "label": "13/54", "node": 3308, "naklon": 0 }, +{ "label": "13/54/1", "node": 3847, "naklon": 0 }, +{ "label": "13/55", "node": 3312, "naklon": 3 }, +{ "label": "13/56", "node": 3309, "naklon": 3 }, +{ "label": "13/57", "node": 3311, "naklon": 3 }, +{ "label": "13/58", "node": 3310, "naklon": 3 }, +{ "label": "13/59", "node": 4365, "naklon": 3 }, +{ "label": "13/60/1", "node": 4093, "naklon": 3 }, +{ "label": "13/61", "node": 3304, "naklon": 3 }, +{ "label": "13/62", "node": 3307, "naklon": 3 }, +{ "label": "13/63", "node": 3271, "naklon": 3 }, +{ "label": "13/64", "node": 3301, "naklon": 3 }, +{ "label": "13/65", "node": 4366, "naklon": 3 }, +{ "label": "13/66", "node": 3300, "naklon": 3 }, +{ "label": "13/67", "node": 3185, "naklon": 0 }, +{ "label": "13/68", "node": 3184, "naklon": 0 }, +{ "label": "13/69", "node": 3188, "naklon": 0 }, +{ "label": "13/71", "node": 3343, "naklon": 6 }, +{ "label": "13/71/1", "node": 3819, "naklon": 6 }, +{ "label": "13/71/2", "node": 3880, "naklon": 6 }, +{ "label": "13/72", "node": 3348, "naklon": 6 }, +{ "label": "13/74", "node": 3344, "naklon": 6 }, +{ "label": "13/75", "node": 3346, "naklon": 6 }, +{ "label": "13/75/1", "node": 3597, "naklon": 6 }, +{ "label": "13/76", "node": 3345, "naklon": 6 }, +{ "label": "13/77", "node": 3322, "naklon": 0 }, +{ "label": "13/78", "node": 3325, "naklon": 0 }, +{ "label": "13/78/1", "node": 4310, "naklon": 0 }, +{ "label": "13/79", "node": 3315, "naklon": 0 }, +{ "label": "13/80", "node": 3328, "naklon": 0 }, +{ "label": "13/81", "node": 3321, "naklon": 0 }, +{ "label": "13/82", "node": 3324, "naklon": 0 }, +{ "label": "13/84", "node": 3140, "naklon": 0 }, +{ "label": "13/85", "node": 3153, "naklon": 0 }, +{ "label": "13/86", "node": 3145, "naklon": 0 }, +{ "label": "13/87", "node": 3134, "naklon": 0 }, +{ "label": "13/88", "node": 3151, "naklon": 0 }, +{ "label": "13/89", "node": 3143, "naklon": 0 }, +{ "label": "13/90", "node": 3318, "naklon": 0 }, +{ "label": "13/91", "node": 3347, "naklon": 0 }, +{ "label": "13/94", "node": 3314, "naklon": 0 }, +{ "label": "13/96", "node": 3331, "naklon": 0 }, +{ "label": "13/97", "node": 3327, "naklon": 0 }, +{ "label": "13/99", "node": 3329, "naklon": 0 }, +{ "label": "13/100", "node": 3337, "naklon": 0 }, +{ "label": "13/101", "node": 3330, "naklon": 0 }, +{ "label": "13/102", "node": 3335, "naklon": 0 }, +{ "label": "13/103", "node": 3420, "naklon": 0 }, +{ "label": "13/104", "node": 3421, "naklon": 0 }, +{ "label": "13/105", "node": 4361, "naklon": 0 }, +{ "label": "13/106", "node": 4362, "naklon": 0 }, +{ "label": "13/107", "node": 3526, "naklon": 0 }, +{ "label": "13/108", "node": 4424, "naklon": null }, +{ "label": "13/109", "node": 3561, "naklon": null }, +{ "label": "13/110", "node": 3527, "naklon": null }, +{ "label": "13/111", "node": 3521, "naklon": null }, +{ "label": "13/112", "node": 3552, "naklon": null }, +{ "label": "13/113", "node": 3544, "naklon": null }, +{ "label": "13/114", "node": 3534, "naklon": null }, +{ "label": "13/115", "node": 3516, "naklon": null }, +{ "label": "13/116", "node": 3513, "naklon": null }, +{ "label": "13/117", "node": 3565, "naklon": null }, +{ "label": "13/118", "node": 3866, "naklon": null }, +{ "label": "14/1", "node": 3136, "naklon": 0 }, +{ "label": "14/2", "node": 3137, "naklon": 0 }, +{ "label": "14/3", "node": 3135, "naklon": 0 }, +{ "label": "14/4", "node": 3149, "naklon": 0 }, +{ "label": "14/5", "node": 3142, "naklon": 0 }, +{ "label": "14/6", "node": 3342, "naklon": 0 }, +{ "label": "14/7", "node": 3340, "naklon": 0 }, +{ "label": "14/8", "node": 3152, "naklon": 0 }, +{ "label": "14/9", "node": 3886, "naklon": 0 }, +{ "label": "14/10", "node": 3341, "naklon": null }, +{ "label": "14/11", "node": 3352, "naklon": null }, +{ "label": "15/1", "node": 3396, "naklon": 5 }, +{ "label": "15/2", "node": 2784, "naklon": 5 }, +{ "label": "15/3", "node": 2788, "naklon": 5 }, +{ "label": "15/4", "node": 2801, "naklon": 5 }, +{ "label": "15/5", "node": 2815, "naklon": 5 }, +{ "label": "15/6", "node": 2829, "naklon": 5 }, +{ "label": "15/7", "node": 2796, "naklon": 5 }, +{ "label": "15/8", "node": 2803, "naklon": 5 }, +{ "label": "15/8/1", "node": 4304, "naklon": 5 }, +{ "label": "15/8/2", "node": 4311, "naklon": 5 }, +{ "label": "15/9", "node": 2821, "naklon": 5 }, +{ "label": "15/10", "node": 3400, "naklon": 5 }, +{ "label": "15/11", "node": 2799, "naklon": 5 }, +{ "label": "15/12", "node": 2804, "naklon": 5 }, +{ "label": "15/12/1", "node": 4303, "naklon": 5 }, +{ "label": "15/12/2", "node": 4309, "naklon": 5 }, +{ "label": "15/13", "node": 2806, "naklon": 5 }, +{ "label": "15/14", "node": 2787, "naklon": 5 }, +{ "label": "15/15", "node": 2809, "naklon": 5 }, +{ "label": "15/16", "node": 2814, "naklon": 0 }, +{ "label": "15/17", "node": 3934, "naklon": 0 }, +{ "label": "15/18", "node": 3192, "naklon": 0 }, +{ "label": "15/19", "node": 2812, "naklon": 0 }, +{ "label": "15/20", "node": 4070, "naklon": 0 }, +{ "label": "15/21", "node": 2826, "naklon": 0 }, +{ "label": "15/22", "node": 2808, "naklon": 3 }, +{ "label": "15/23", "node": 2795, "naklon": 3 }, +{ "label": "15/24", "node": 2807, "naklon": 3 }, +{ "label": "15/25", "node": 2831, "naklon": 0 }, +{ "label": "15/26", "node": 2862, "naklon": null }, +{ "label": "15/27", "node": 2861, "naklon": 0 }, +{ "label": "15/28", "node": 2866, "naklon": 0 }, +{ "label": "15/28/1", "node": 3546, "naklon": 0 }, +{ "label": "15/29", "node": 4146, "naklon": 0 }, +{ "label": "15/29/1", "node": 3001, "naklon": 0 }, +{ "label": "15/30", "node": 2835, "naklon": 0 }, +{ "label": "15/31", "node": 2874, "naklon": 0 }, +{ "label": "15/32", "node": 2852, "naklon": 0 }, +{ "label": "15/33", "node": 2851, "naklon": 0 }, +{ "label": "15/33/1", "node": 3560, "naklon": 0 }, +{ "label": "15/34", "node": 2858, "naklon": 0 }, +{ "label": "15/34/1", "node": 4306, "naklon": 0 }, +{ "label": "15/35", "node": 2856, "naklon": 0 }, +{ "label": "15/36", "node": 2847, "naklon": 0 }, +{ "label": "15/36/1", "node": 3556, "naklon": 0 }, +{ "label": "15/37", "node": 3950, "naklon": 0 }, +{ "label": "15/38", "node": 2848, "naklon": 0 }, +{ "label": "15/39", "node": 2863, "naklon": 0 }, +{ "label": "15/39/1", "node": 4313, "naklon": 0 }, +{ "label": "15/40", "node": 2873, "naklon": 0 }, +{ "label": "15/40/1", "node": 2984, "naklon": 0 }, +{ "label": "15/41", "node": 2854, "naklon": 0 }, +{ "label": "15/42", "node": 2859, "naklon": 0 }, +{ "label": "15/43", "node": 2872, "naklon": 0 }, +{ "label": "15/44", "node": 2849, "naklon": 0 }, +{ "label": "15/45", "node": 2864, "naklon": 0 }, +{ "label": "15/46", "node": 3553, "naklon": null }, +{ "label": "15/47", "node": 3021, "naklon": null }, +{ "label": "15/47/1", "node": 3008, "naklon": null }, +{ "label": "15/48", "node": 3017, "naklon": null }, +{ "label": "15/49", "node": 3014, "naklon": null }, +{ "label": "15/50", "node": 2981, "naklon": null }, +{ "label": "15/51", "node": 3020, "naklon": null }, +{ "label": "15/52", "node": 3027, "naklon": null }, +{ "label": "15/53", "node": 3006, "naklon": null }, +{ "label": "15/54", "node": 3012, "naklon": null }, +{ "label": "15/55", "node": 2738, "naklon": 0 }, +{ "label": "15/56", "node": 2725, "naklon": 0 }, +{ "label": "15/57", "node": 3016, "naklon": null }, +{ "label": "15/58", "node": 3005, "naklon": null }, +{ "label": "15/58/1", "node": 3009, "naklon": null }, +{ "label": "15/59", "node": 3010, "naklon": 0 }, +{ "label": "15/59/1", "node": 3538, "naklon": 0 }, +{ "label": "15/59/2", "node": 4145, "naklon": 0 }, +{ "label": "15/60", "node": 2713, "naklon": 0 }, +{ "label": "15/61", "node": 2789, "naklon": 0 }, +{ "label": "15/62", "node": 2736, "naklon": 0 }, +{ "label": "15/63", "node": 2739, "naklon": 0 }, +{ "label": "15/64", "node": 4346, "naklon": 0 }, +{ "label": "15/65", "node": 2731, "naklon": 0 }, +{ "label": "15/66", "node": 2818, "naklon": 0 }, +{ "label": "15/66/1", "node": 3557, "naklon": 0 }, +{ "label": "15/67", "node": 2822, "naklon": 0 }, +{ "label": "15/68", "node": 2833, "naklon": 0 }, +{ "label": "15/69", "node": 2834, "naklon": 0 }, +{ "label": "15/70", "node": 3097, "naklon": 0 }, +{ "label": "15/71", "node": 2824, "naklon": 0 }, +{ "label": "15/72", "node": 2828, "naklon": 0 }, +{ "label": "15/73", "node": 2600, "naklon": 0 }, +{ "label": "15/73/1", "node": 4314, "naklon": 0 }, +{ "label": "15/74", "node": 2832, "naklon": 0 }, +{ "label": "15/75", "node": 4360, "naklon": 0 }, +{ "label": "15/76", "node": 2846, "naklon": 0 }, +{ "label": "15/77", "node": 2584, "naklon": 0 }, +{ "label": "15/78", "node": 2843, "naklon": 0 }, +{ "label": "15/78/1", "node": 4308, "naklon": 0 }, +{ "label": "15/79", "node": 4144, "naklon": null }, +{ "label": "15/80", "node": 2844, "naklon": 0 }, +{ "label": "15/81", "node": 2842, "naklon": 0 }, +{ "label": "15/82", "node": 2838, "naklon": 0 }, +{ "label": "15/83", "node": 2837, "naklon": null }, +{ "label": "15/83/1", "node": 3555, "naklon": null }, +{ "label": "15/84", "node": 2839, "naklon": 0 }, +{ "label": "15/85", "node": 2830, "naklon": 0 }, +{ "label": "15/86", "node": 4066, "naklon": 0 }, +{ "label": "15/87", "node": 2836, "naklon": 0 }, +{ "label": "15/88", "node": 2911, "naklon": 0 }, +{ "label": "15/89", "node": 2825, "naklon": 0 }, +{ "label": "15/90", "node": 2811, "naklon": 0 }, +{ "label": "15/94", "node": 3740, "naklon": 15 }, +{ "label": "15/95", "node": 2734, "naklon": 15 }, +{ "label": "15/96", "node": 3105, "naklon": 15 }, +{ "label": "15/97", "node": 2732, "naklon": 15 }, +{ "label": "15/98", "node": 2727, "naklon": 15 }, +{ "label": "15/99", "node": 2735, "naklon": 15 }, +{ "label": "15/100", "node": 3926, "naklon": 15 }, +{ "label": "15/101", "node": 2918, "naklon": 0 }, +{ "label": "15/102", "node": 2705, "naklon": 10 }, +{ "label": "15/103", "node": 2708, "naklon": 10 }, +{ "label": "15/104", "node": 2721, "naklon": 10 }, +{ "label": "15/105", "node": 2719, "naklon": 10 }, +{ "label": "15/106", "node": 2919, "naklon": 10 }, +{ "label": "15/107", "node": 3101, "naklon": 10 }, +{ "label": "15/108", "node": 2853, "naklon": 10 }, +{ "label": "15/109", "node": 2715, "naklon": 10 }, +{ "label": "15/110", "node": 2712, "naklon": 0 }, +{ "label": "15/111", "node": 2711, "naklon": 0 }, +{ "label": "15/112", "node": 2709, "naklon": 0 }, +{ "label": "15/113", "node": 2710, "naklon": 0 }, +{ "label": "15/114", "node": 2907, "naklon": 0 }, +{ "label": "15/115", "node": 2906, "naklon": 0 }, +{ "label": "15/116", "node": 2908, "naklon": 0 }, +{ "label": "15/117", "node": 2901, "naklon": 0 }, +{ "label": "15/118", "node": 2913, "naklon": 0 }, +{ "label": "15/119", "node": 3656, "naklon": 0 }, +{ "label": "15/120", "node": 2781, "naklon": 0 }, +{ "label": "15/121", "node": 2802, "naklon": 0 }, +{ "label": "15/122", "node": 2791, "naklon": 0 }, +{ "label": "15/123", "node": 2783, "naklon": 0 }, +{ "label": "15/124", "node": 2794, "naklon": 0 }, +{ "label": "15/125", "node": 3139, "naklon": 0 }, +{ "label": "15/126", "node": 3229, "naklon": 5 }, +{ "label": "15/127", "node": 3239, "naklon": 5 }, +{ "label": "15/128", "node": 3230, "naklon": 5 }, +{ "label": "15/129", "node": 4016, "naklon": null }, +{ "label": "16/16A", "node": 3608, "naklon": 0 }, +{ "label": "16/16B", "node": 4151, "naklon": 0 }, +{ "label": "16/1", "node": 3710, "naklon": 0 }, +{ "label": "16/2", "node": 3726, "naklon": 0 }, +{ "label": "16/3", "node": 3743, "naklon": 0 }, +{ "label": "16/4", "node": 3724, "naklon": 0 }, +{ "label": "16/5", "node": 3712, "naklon": 0 }, +{ "label": "16/6", "node": 3739, "naklon": 0 }, +{ "label": "16/7", "node": 3742, "naklon": 0 }, +{ "label": "16/8", "node": 3731, "naklon": 0 }, +{ "label": "16/9", "node": 3727, "naklon": 0 }, +{ "label": "16/10", "node": 3729, "naklon": 0 }, +{ "label": "16/11", "node": 3736, "naklon": 0 }, +{ "label": "16/12", "node": 3713, "naklon": 0 }, +{ "label": "16/13", "node": 3715, "naklon": 0 }, +{ "label": "16/14", "node": 3733, "naklon": 0 }, +{ "label": "16/15", "node": 3732, "naklon": 0 }, +{ "label": "16/17", "node": 3634, "naklon": 0 }, +{ "label": "16/18", "node": 3610, "naklon": 0 }, +{ "label": "16/19", "node": 3626, "naklon": 0 }, +{ "label": "16/20", "node": 3618, "naklon": 0 }, +{ "label": "16/21", "node": 3619, "naklon": 0 }, +{ "label": "16/22", "node": 3628, "naklon": 0 }, +{ "label": "16/23", "node": 3615, "naklon": 0 }, +{ "label": "16/24", "node": 3609, "naklon": 0 }, +{ "label": "16/25", "node": 3606, "naklon": 0 }, +{ "label": "16/26", "node": 3624, "naklon": 0 }, +{ "label": "16/27", "node": 3627, "naklon": 0 }, +{ "label": "16/28", "node": 3607, "naklon": 0 }, +{ "label": "16/29", "node": 4370, "naklon": 0 }, +{ "label": "16/30", "node": 3692, "naklon": 0 }, +{ "label": "16/31", "node": 3614, "naklon": 0 }, +{ "label": "16/32", "node": 3623, "naklon": 0 }, +{ "label": "16/33", "node": 4373, "naklon": 0 }, +{ "label": "16/34", "node": 3620, "naklon": 0 }, +{ "label": "16/35", "node": 3685, "naklon": 0 }, +{ "label": "16/36", "node": 3616, "naklon": 0 }, +{ "label": "16/37", "node": 3686, "naklon": 0 }, +{ "label": "16/38", "node": 3688, "naklon": 0 }, +{ "label": "16/39", "node": 3684, "naklon": 0 }, +{ "label": "16/40", "node": 3825, "naklon": 0 }, +{ "label": "16/41", "node": 3865, "naklon": 0 }, +{ "label": "16/42", "node": 3824, "naklon": 0 }, +{ "label": "16/43", "node": 3871, "naklon": 0 }, +{ "label": "16/44", "node": 3801, "naklon": 0 }, +{ "label": "16/45", "node": 3862, "naklon": 0 }, +{ "label": "16/46", "node": 3876, "naklon": 0 }, +{ "label": "16/47", "node": 3861, "naklon": 0 }, +{ "label": "16/48", "node": 4215, "naklon": 0 }, +{ "label": "16/49", "node": 3605, "naklon": 10 }, +{ "label": "16/50", "node": 3603, "naklon": 10 }, +{ "label": "16/51", "node": 3592, "naklon": 10 }, +{ "label": "16/52", "node": 3598, "naklon": 10 }, +{ "label": "16/53", "node": 3594, "naklon": 10 }, +{ "label": "16/54", "node": 3593, "naklon": 10 }, +{ "label": "16/55", "node": 3630, "naklon": 10 }, +{ "label": "16/56", "node": 3763, "naklon": 10 }, +{ "label": "16/57", "node": 3746, "naklon": 10 }, +{ "label": "16/58", "node": 3699, "naklon": 0 }, +{ "label": "16/59", "node": 3698, "naklon": 0 }, +{ "label": "16/60", "node": 3709, "naklon": null }, +{ "label": "16/61", "node": 3708, "naklon": 0 }, +{ "label": "16/62", "node": 3703, "naklon": null }, +{ "label": "16/63", "node": 3700, "naklon": 0 }, +{ "label": "16/64", "node": 3701, "naklon": null }, +{ "label": "16/65", "node": 3704, "naklon": 0 }, +{ "label": "16/66", "node": 3707, "naklon": null }, +{ "label": "16/67", "node": 3810, "naklon": 0 }, +{ "label": "16/68", "node": 4208, "naklon": null }, +{ "label": "16/69", "node": 3867, "naklon": 0 }, +{ "label": "16/70", "node": 4372, "naklon": null }, +{ "label": "16/71", "node": 3881, "naklon": 0 }, +{ "label": "16/72", "node": 4204, "naklon": null }, +{ "label": "16/73", "node": 3869, "naklon": 0 }, +{ "label": "16/74", "node": 4202, "naklon": null }, +{ "label": "16/75", "node": 3830, "naklon": 0 }, +{ "label": "16/76", "node": 3870, "naklon": null }, +{ "label": "16/77", "node": 3964, "naklon": 0 }, +{ "label": "16/78", "node": 3849, "naklon": 0 }, +{ "label": "16/79", "node": 3694, "naklon": null }, +{ "label": "16/80", "node": 3717, "naklon": 0 }, +{ "label": "16/81", "node": 3877, "naklon": null }, +{ "label": "16/82", "node": 3755, "naklon": 0 }, +{ "label": "16/83", "node": 3725, "naklon": null }, +{ "label": "16/84", "node": 3716, "naklon": 0 }, +{ "label": "16/85", "node": 3696, "naklon": null }, +{ "label": "16/86", "node": 3702, "naklon": 0 }, +{ "label": "16/87", "node": 3706, "naklon": null }, +{ "label": "16/88", "node": 3850, "naklon": 0 }, +{ "label": "16/89", "node": 3848, "naklon": null }, +{ "label": "16/90", "node": 3737, "naklon": null }, +{ "label": "16/91", "node": 3705, "naklon": 0 }, +{ "label": "16/92", "node": 3723, "naklon": null }, +{ "label": "16/93", "node": 3842, "naklon": 0 }, +{ "label": "16/94", "node": 3735, "naklon": null }, +{ "label": "16/95", "node": 3719, "naklon": 0 }, +{ "label": "16/96", "node": 3697, "naklon": 0 }, +{ "label": "16/97", "node": 3711, "naklon": 0 }, +{ "label": "16/98", "node": 4107, "naklon": null }, +{ "label": "16/99", "node": 4112, "naklon": 5 }, +{ "label": "16/100", "node": 4106, "naklon": 5 }, +{ "label": "16/101", "node": 4111, "naklon": 5 }, +{ "label": "16/102", "node": 4091, "naklon": null }, +{ "label": "16/103", "node": 4104, "naklon": 5 }, +{ "label": "16/104", "node": 4094, "naklon": null }, +{ "label": "16/105", "node": 4089, "naklon": 5 }, +{ "label": "16/106", "node": 4095, "naklon": null }, +{ "label": "16/107", "node": 4102, "naklon": 5 }, +{ "label": "16/108", "node": 4105, "naklon": null }, +{ "label": "16/109", "node": 3859, "naklon": null }, +{ "label": "16/110", "node": 4090, "naklon": 5 }, +{ "label": "16/111", "node": 4110, "naklon": null }, +{ "label": "16/112", "node": 4097, "naklon": 5 }, +{ "label": "16/113", "node": 4099, "naklon": null }, +{ "label": "16/114", "node": 4096, "naklon": null }, +{ "label": "16/115", "node": 4101, "naklon": 5 }, +{ "label": "16/116", "node": 4109, "naklon": null }, +{ "label": "16/117", "node": 4092, "naklon": 5 }, +{ "label": "16/118", "node": 3631, "naklon": null }, +{ "label": "16/119", "node": 3632, "naklon": 0 }, +{ "label": "16/120", "node": 3641, "naklon": null }, +{ "label": "16/121", "node": 3638, "naklon": 0 }, +{ "label": "16/122", "node": 3637, "naklon": null }, +{ "label": "16/123", "node": 4142, "naklon": null }, +{ "label": "16/124", "node": 4147, "naklon": 5 }, +{ "label": "16/125", "node": 4139, "naklon": 5 }, +{ "label": "20/30A", "node": 3172, "naklon": 2 }, +{ "label": "20/30B", "node": 3164, "naklon": 2 }, +{ "label": "20/1", "node": 3247, "naklon": 10 }, +{ "label": "20/2", "node": 3296, "naklon": 10 }, +{ "label": "20/3", "node": 3246, "naklon": 10 }, +{ "label": "20/4", "node": 3270, "naklon": 10 }, +{ "label": "20/5", "node": 3294, "naklon": 10 }, +{ "label": "20/6", "node": 3298, "naklon": 10 }, +{ "label": "20/7", "node": 3297, "naklon": 10 }, +{ "label": "20/8", "node": 3293, "naklon": 10 }, +{ "label": "20/9", "node": 3299, "naklon": 10 }, +{ "label": "20/10", "node": 3295, "naklon": 10 }, +{ "label": "20/11", "node": 3244, "naklon": 10 }, +{ "label": "20/12", "node": 3249, "naklon": 10 }, +{ "label": "20/13", "node": 3268, "naklon": 10 }, +{ "label": "20/14", "node": 3245, "naklon": 10 }, +{ "label": "20/15", "node": 3278, "naklon": 10 }, +{ "label": "20/16", "node": 3280, "naklon": 10 }, +{ "label": "20/17", "node": 3292, "naklon": 10 }, +{ "label": "20/18", "node": 3287, "naklon": 10 }, +{ "label": "20/19", "node": 3282, "naklon": 10 }, +{ "label": "20/20", "node": 3273, "naklon": 0 }, +{ "label": "20/21", "node": 3157, "naklon": 0 }, +{ "label": "20/22", "node": 3283, "naklon": 0 }, +{ "label": "20/23", "node": 3159, "naklon": 0 }, +{ "label": "20/24", "node": 3289, "naklon": 0 }, +{ "label": "20/25", "node": 3163, "naklon": 0 }, +{ "label": "20/26", "node": 3126, "naklon": 0 }, +{ "label": "20/27", "node": 3171, "naklon": 0 }, +{ "label": "20/28", "node": 3162, "naklon": 0 }, +{ "label": "20/29", "node": 3279, "naklon": 10 }, +{ "label": "20/31", "node": 3173, "naklon": 0 }, +{ "label": "20/32", "node": 3127, "naklon": 0 }, +{ "label": "20/33", "node": 3131, "naklon": 0 }, +{ "label": "20/34", "node": 3129, "naklon": 0 }, +{ "label": "20/35", "node": 3276, "naklon": 2 }, +{ "label": "20/36", "node": 3290, "naklon": 2 }, +{ "label": "20/37", "node": 3132, "naklon": 0 }, +{ "label": "20/38", "node": 3138, "naklon": 0 }, +{ "label": "20/39", "node": 3272, "naklon": 0 }, +{ "label": "20/40", "node": 3291, "naklon": 0 }, +{ "label": "20/41", "node": 3277, "naklon": 10 }, +{ "label": "20/42", "node": 3286, "naklon": 10 }, +{ "label": "20/43", "node": 3281, "naklon": 10 }, +{ "label": "20/44", "node": 3288, "naklon": 10 }, +{ "label": "20/45", "node": 3284, "naklon": 10 }, +{ "label": "20/46", "node": 3167, "naklon": 10 }, +{ "label": "20/47", "node": 3872, "naklon": 0 }, +{ "label": "20/48", "node": 3124, "naklon": 0 }, +{ "label": "20/49", "node": 3133, "naklon": 0 }, +{ "label": "20/50", "node": 3158, "naklon": 0 }, +{ "label": "20/51", "node": 3169, "naklon": 0 }, +{ "label": "20/52", "node": 3146, "naklon": 0 }, +{ "label": "20/53", "node": 3160, "naklon": 0 }, +{ "label": "20/54", "node": 3248, "naklon": 0 }, +{ "label": "20/55", "node": 3156, "naklon": 0 }, +{ "label": "20/56", "node": 3161, "naklon": 0 }, +{ "label": "20/57", "node": 3170, "naklon": 0 }, +{ "label": "20/58", "node": 3168, "naklon": 0 }, +{ "label": "20/59", "node": 3125, "naklon": 0 }, +{ "label": "20/60", "node": 3166, "naklon": 0 }, +{ "label": "20/61", "node": 3130, "naklon": 0 }, +{ "label": "20/62", "node": 3563, "naklon": 0 }, +{ "label": "20/63", "node": 3550, "naklon": null }, +{ "label": "20/67", "node": 3269, "naklon": 0 }, +{ "label": "21/1", "node": 2921, "naklon": 0 }, +{ "label": "21/2", "node": 2707, "naklon": 0 }, +{ "label": "21/3", "node": 2723, "naklon": 0 }, +{ "label": "21/4", "node": 2716, "naklon": 0 }, +{ "label": "21/5", "node": 2717, "naklon": 0 }, +{ "label": "21/6", "node": 2720, "naklon": 0 }, +{ "label": "21/7", "node": 2722, "naklon": 0 }, +{ "label": "21/8", "node": 2718, "naklon": 0 }, +{ "label": "21/9", "node": 2724, "naklon": 0 }, +{ "label": "21/10", "node": 2742, "naklon": 0 }, +{ "label": "21/11", "node": 2743, "naklon": 0 }, +{ "label": "21/12", "node": 2733, "naklon": 0 }, +{ "label": "21/14", "node": 2903, "naklon": 0 }, +{ "label": "21/15", "node": 2917, "naklon": 0 }, +{ "label": "21/16", "node": 2897, "naklon": 0 }, +{ "label": "21/17", "node": 2914, "naklon": 0 }, +{ "label": "21/18", "node": 2898, "naklon": 0 }, +{ "label": "21/19", "node": 2773, "naklon": 0 }, +{ "label": "21/20", "node": 2895, "naklon": 0 }, +{ "label": "21/21", "node": 2896, "naklon": 0 }, +{ "label": "21/22", "node": 2771, "naklon": 0 }, +{ "label": "21/23", "node": 2772, "naklon": 0 }, +{ "label": "21/24", "node": 2793, "naklon": 0 }, +{ "label": "21/25", "node": 2902, "naklon": 0 }, +{ "label": "21/26", "node": 2910, "naklon": 0 }, +{ "label": "21/27", "node": 2909, "naklon": 0 }, +{ "label": "21/28", "node": 2920, "naklon": 0 }, +{ "label": "21/29", "node": 2916, "naklon": 0 }, +{ "label": "21/30", "node": 2904, "naklon": 0 }, +{ "label": "21/31", "node": 2915, "naklon": 0 }, +{ "label": "21/32", "node": 2905, "naklon": 0 }, +{ "label": "21/33", "node": 2900, "naklon": 0 }, +{ "label": "21/34", "node": 2899, "naklon": 0 }, +{ "label": "21/36", "node": 2741, "naklon": 0 }, +{ "label": "21/37", "node": 2714, "naklon": 0 }, +{ "label": "21/38", "node": 2701, "naklon": 0 }, +{ "label": "21/39", "node": 2703, "naklon": 0 }, +{ "label": "21/40", "node": 2704, "naklon": 0 }, +{ "label": "21/41", "node": 2702, "naklon": 0 }, +{ "label": "21/42", "node": 2706, "naklon": 0 }, +{ "label": "21/43", "node": 2776, "naklon": 0 }, +{ "label": "21/44", "node": 2770, "naklon": 0 }, +{ "label": "21/45", "node": 2786, "naklon": 0 }, +{ "label": "21/46", "node": 2779, "naklon": 0 }, +{ "label": "21/47", "node": 2782, "naklon": 0 }, +{ "label": "21/48", "node": 2785, "naklon": 0 }, +{ "label": "21/49", "node": 2769, "naklon": 0 }, +{ "label": "21/50", "node": 3354, "naklon": 0 }, +{ "label": "21/51", "node": 2778, "naklon": 0 }, +{ "label": "21/52", "node": 2775, "naklon": 0 }, +{ "label": "21/53", "node": 2780, "naklon": 0 }, +{ "label": "21/54", "node": 2790, "naklon": 0 }, +{ "label": "21/55", "node": 2792, "naklon": 0 }, +{ "label": "21/56", "node": 2774, "naklon": 0 }, +{ "label": "22/1", "node": 2630, "naklon": 0 }, +{ "label": "22/2", "node": 2631, "naklon": 0 }, +{ "label": "22/3", "node": 2632, "naklon": 0 }, +{ "label": "22/4", "node": 2633, "naklon": 0 }, +{ "label": "22/5", "node": 2634, "naklon": 0 }, +{ "label": "22/6", "node": 2636, "naklon": 0 }, +{ "label": "22/7", "node": 4367, "naklon": 0 }, +{ "label": "22/8", "node": 2637, "naklon": 0 }, +{ "label": "22/9", "node": 2638, "naklon": 0 }, +{ "label": "22/10", "node": 2639, "naklon": 0 }, +{ "label": "22/11", "node": 2640, "naklon": 0 }, +{ "label": "22/12", "node": 2641, "naklon": 0 }, +{ "label": "22/13", "node": 2642, "naklon": 0 }, +{ "label": "22/14", "node": 2643, "naklon": 0 }, +{ "label": "22/15", "node": 2644, "naklon": 0 }, +{ "label": "22/16", "node": 2645, "naklon": 0 }, +{ "label": "22/17", "node": 2646, "naklon": 0 }, +{ "label": "22/18", "node": 2647, "naklon": 0 }, +{ "label": "22/19", "node": 2648, "naklon": 0 }, +{ "label": "22/20", "node": 2649, "naklon": 0 }, +{ "label": "22/21", "node": 2650, "naklon": 0 }, +{ "label": "22/22", "node": 2651, "naklon": 0 }, +{ "label": "22/23", "node": 4103, "naklon": 0 }, +{ "label": "22/24", "node": 2653, "naklon": 0 }, +{ "label": "22/25", "node": 2654, "naklon": 0 }, +{ "label": "22/26", "node": 2655, "naklon": 0 }, +{ "label": "22/27", "node": 2656, "naklon": 0 }, +{ "label": "22/28", "node": 2657, "naklon": 0 }, +{ "label": "22/29", "node": 2658, "naklon": 0 }, +{ "label": "22/30", "node": 2659, "naklon": 0 }, +{ "label": "22/31", "node": 2660, "naklon": 0 }, +{ "label": "22/32", "node": 2661, "naklon": 0 }, +{ "label": "22/32/1", "node": 3015, "naklon": 0 }, +{ "label": "22/33", "node": 2662, "naklon": 0 }, +{ "label": "22/34", "node": 2663, "naklon": 0 }, +{ "label": "22/35", "node": 2664, "naklon": 0 }, +{ "label": "22/36", "node": 2665, "naklon": 0 }, +{ "label": "22/37", "node": 2666, "naklon": 0 }, +{ "label": "22/38", "node": 2667, "naklon": 0 }, +{ "label": "22/39", "node": 2668, "naklon": 0 }, +{ "label": "22/40", "node": 2669, "naklon": null }, +{ "label": "22/41", "node": 2670, "naklon": null }, +{ "label": "22/42", "node": 2671, "naklon": null }, +{ "label": "23/9A", "node": 3087, "naklon": 10 }, +{ "label": "23/9B", "node": 3090, "naklon": 10 }, +{ "label": "23/1", "node": 3075, "naklon": 0 }, +{ "label": "23/2", "node": 3089, "naklon": 0 }, +{ "label": "23/3", "node": 3088, "naklon": 0 }, +{ "label": "23/4", "node": 3228, "naklon": 10 }, +{ "label": "23/5", "node": 2751, "naklon": 10 }, +{ "label": "23/6", "node": 3243, "naklon": 10 }, +{ "label": "23/7", "node": 4349, "naklon": 10 }, +{ "label": "23/8", "node": 3102, "naklon": 10 }, +{ "label": "23/10", "node": 3099, "naklon": 10 }, +{ "label": "23/11", "node": 3103, "naklon": 10 }, +{ "label": "23/12", "node": 3093, "naklon": 10 }, +{ "label": "23/13", "node": 3098, "naklon": 10 }, +{ "label": "23/14", "node": 3092, "naklon": 10 }, +{ "label": "23/15", "node": 3233, "naklon": 0 }, +{ "label": "23/16", "node": 3095, "naklon": 0 }, +{ "label": "23/17", "node": 4074, "naklon": 0 }, +{ "label": "23/18", "node": 2729, "naklon": 0 }, +{ "label": "23/19", "node": 3234, "naklon": 0 }, +{ "label": "23/20", "node": 3094, "naklon": 0 }, +{ "label": "23/21", "node": 2817, "naklon": 0 }, +{ "label": "23/22", "node": 3226, "naklon": 0 }, +{ "label": "23/23", "node": 3225, "naklon": 0 }, +{ "label": "23/24", "node": 3237, "naklon": 0 }, +{ "label": "23/25", "node": 4250, "naklon": 0 }, +{ "label": "23/26", "node": 3059, "naklon": 10 }, +{ "label": "23/27", "node": 3238, "naklon": 10 }, +{ "label": "23/28", "node": 3242, "naklon": 10 }, +{ "label": "23/29", "node": 3236, "naklon": 10 }, +{ "label": "23/30", "node": 3112, "naklon": 10 }, +{ "label": "23/31", "node": 3224, "naklon": 0 }, +{ "label": "23/32", "node": 4298, "naklon": 10 }, +{ "label": "23/33", "node": 4150, "naklon": 10 }, +{ "label": "23/34", "node": 3091, "naklon": 10 }, +{ "label": "25/1", "node": 3771, "naklon": 5 }, +{ "label": "25/2", "node": 3777, "naklon": 5 }, +{ "label": "25/3", "node": 3749, "naklon": 5 }, +{ "label": "25/4", "node": 3769, "naklon": 5 }, +{ "label": "25/5", "node": 3765, "naklon": 5 }, +{ "label": "25/6", "node": 3785, "naklon": 5 }, +{ "label": "25/7", "node": 3761, "naklon": 5 }, +{ "label": "25/8", "node": 3758, "naklon": 5 }, +{ "label": "25/9", "node": 3766, "naklon": 5 }, +{ "label": "25/10", "node": 3779, "naklon": 5 }, +{ "label": "25/11", "node": 3899, "naklon": 10 }, +{ "label": "25/12", "node": 3922, "naklon": 10 }, +{ "label": "25/13", "node": 3912, "naklon": 10 }, +{ "label": "25/14", "node": 3933, "naklon": 10 }, +{ "label": "25/15", "node": 3921, "naklon": 10 }, +{ "label": "25/16", "node": 4300, "naklon": 10 }, +{ "label": "25/17", "node": 3927, "naklon": 10 }, +{ "label": "25/18", "node": 3212, "naklon": 10 }, +{ "label": "25/19", "node": 3208, "naklon": 10 }, +{ "label": "25/20", "node": 3207, "naklon": 10 }, +{ "label": "25/21", "node": 4294, "naklon": 10 }, +{ "label": "25/22", "node": 3209, "naklon": 10 }, +{ "label": "25/23", "node": 3745, "naklon": 10 }, +{ "label": "25/24", "node": 3762, "naklon": 10 }, +{ "label": "25/25", "node": 3215, "naklon": 10 }, +{ "label": "25/26", "node": 3210, "naklon": 10 }, +{ "label": "25/27", "node": 3211, "naklon": 10 }, +{ "label": "25/28", "node": 3206, "naklon": 10 }, +{ "label": "25/29", "node": 3918, "naklon": 5 }, +{ "label": "25/30", "node": 3928, "naklon": 5 }, +{ "label": "25/31", "node": 3917, "naklon": 5 }, +{ "label": "25/32", "node": 4029, "naklon": 0 }, +{ "label": "25/33", "node": 4038, "naklon": 0 }, +{ "label": "25/34", "node": 4022, "naklon": 0 }, +{ "label": "25/35", "node": 3937, "naklon": 0 }, +{ "label": "25/36", "node": 3190, "naklon": 0 }, +{ "label": "25/37", "node": 3835, "naklon": 0 }, +{ "label": "25/38", "node": 3201, "naklon": 0 }, +{ "label": "25/39", "node": 3193, "naklon": 0 }, +{ "label": "25/40", "node": 3191, "naklon": 0 }, +{ "label": "25/41", "node": 3203, "naklon": 0 }, +{ "label": "25/42", "node": 4301, "naklon": 0 }, +{ "label": "25/43", "node": 3223, "naklon": 0 }, +{ "label": "25/44", "node": 3202, "naklon": 0 }, +{ "label": "25/45", "node": 3205, "naklon": 0 }, +{ "label": "25/46", "node": 3194, "naklon": 0 }, +{ "label": "25/47", "node": 3198, "naklon": 0 }, +{ "label": "25/48", "node": 3204, "naklon": 0 }, +{ "label": "25/49", "node": 3200, "naklon": 0 }, +{ "label": "25/50", "node": 3216, "naklon": 0 }, +{ "label": "25/51", "node": 3932, "naklon": 5 }, +{ "label": "25/52", "node": 3923, "naklon": 5 }, +{ "label": "25/53", "node": 3913, "naklon": 5 }, +{ "label": "25/54", "node": 3900, "naklon": 5 }, +{ "label": "25/55", "node": 4189, "naklon": 10 }, +{ "label": "25/56", "node": 4191, "naklon": 10 }, +{ "label": "25/57", "node": 3790, "naklon": 10 }, +{ "label": "25/58", "node": 4190, "naklon": 10 }, +{ "label": "25/59", "node": 4302, "naklon": 0 }, +{ "label": "25/60", "node": 4351, "naklon": 0 }, +{ "label": "25/61", "node": 4075, "naklon": 0 }, +{ "label": "25/62", "node": 4071, "naklon": 0 }, +{ "label": "25/63", "node": 3784, "naklon": 0 }, +{ "label": "25/64", "node": 4065, "naklon": 0 }, +{ "label": "25/65", "node": 4297, "naklon": 0 }, +{ "label": "25/66", "node": 4295, "naklon": 0 }, +{ "label": "25/67", "node": 4299, "naklon": 0 }, +{ "label": "25/68", "node": 3772, "naklon": 0 }, +{ "label": "25/69", "node": 3941, "naklon": 0 }, +{ "label": "25/70", "node": 3782, "naklon": 0 }, +{ "label": "25/71", "node": 4068, "naklon": 0 }, +{ "label": "25/72", "node": 4073, "naklon": 0 }, +{ "label": "25/73", "node": 3901, "naklon": 5 }, +{ "label": "25/74", "node": 4296, "naklon": 5 }, +{ "label": "25/75", "node": 3910, "naklon": 5 }, +{ "label": "25/76", "node": 4293, "naklon": 5 }, +{ "label": "25/77", "node": 3919, "naklon": 5 }, +{ "label": "25/78", "node": 3924, "naklon": 5 }, +{ "label": "25/79", "node": 3909, "naklon": 5 }, +{ "label": "25/80", "node": 3896, "naklon": 5 }, +{ "label": "25/81", "node": 3911, "naklon": 5 }, +{ "label": "25/82", "node": 2819, "naklon": 15 }, +{ "label": "25/83", "node": 3776, "naklon": 15 }, +{ "label": "25/84", "node": 3752, "naklon": 15 }, +{ "label": "25/85", "node": 4353, "naklon": 15 }, +{ "label": "25/86", "node": 3791, "naklon": 0 }, +{ "label": "25/87", "node": 3770, "naklon": 0 }, +{ "label": "25/88", "node": 3760, "naklon": 0 }, +{ "label": "25/89", "node": 3115, "naklon": 0 }, +{ "label": "25/90", "node": 3738, "naklon": 0 }, +{ "label": "25/91", "node": 3748, "naklon": 0 }, +{ "label": "25/92", "node": 3753, "naklon": 0 }, +{ "label": "25/93", "node": 3775, "naklon": 0 }, +{ "label": "25/94", "node": 3778, "naklon": 5 }, +{ "label": "25/95", "node": 4078, "naklon": 5 }, +{ "label": "25/96", "node": 4088, "naklon": 5 }, +{ "label": "25/97", "node": 3856, "naklon": 5 }, +{ "label": "25/98", "node": 4084, "naklon": 5 }, +{ "label": "25/99", "node": 4069, "naklon": 5 }, +{ "label": "25/100", "node": 4188, "naklon": 5 }, +{ "label": "25/101", "node": 4064, "naklon": 5 }, +{ "label": "25/102", "node": 3792, "naklon": 5 }, +{ "label": "25/103", "node": 3780, "naklon": 5 }, +{ "label": "25/104", "node": 4034, "naklon": 5 }, +{ "label": "25/105", "node": 4072, "naklon": 5 }, +{ "label": "25/106", "node": 3884, "naklon": 5 }, +{ "label": "25/107", "node": 3793, "naklon": 5 }, +{ "label": "25/108", "node": 3863, "naklon": 5 }, +{ "label": "25/109", "node": 3855, "naklon": 5 }, +{ "label": "33/1", "node": 3846, "naklon": 0 }, +{ "label": "33/2", "node": 3943, "naklon": 0 }, +{ "label": "33/3", "node": 3903, "naklon": 0 }, +{ "label": "33/4", "node": 3982, "naklon": 0 }, +{ "label": "33/5", "node": 3879, "naklon": 0 }, +{ "label": "33/6", "node": 3887, "naklon": 0 }, +{ "label": "33/7", "node": 3920, "naklon": 5 }, +{ "label": "33/8", "node": 3942, "naklon": 5 }, +{ "label": "33/9", "node": 3829, "naklon": null }, +{ "label": "34/79A", "node": 3452, "naklon": 6 }, +{ "label": "34/79B", "node": 3460, "naklon": 6 }, +{ "label": "34/90A", "node": 3443, "naklon": 6 }, +{ "label": "34/90B", "node": 3445, "naklon": 6 }, +{ "label": "34/90C", "node": 3457, "naklon": 6 }, +{ "label": "34/97A", "node": 3461, "naklon": 6 }, +{ "label": "34/97B", "node": 3463, "naklon": 6 }, +{ "label": "34/98A", "node": 3426, "naklon": 6 }, +{ "label": "34/98B", "node": 3444, "naklon": 6 }, +{ "label": "34/99A", "node": 3453, "naklon": 6 }, +{ "label": "34/99B", "node": 3455, "naklon": 6 }, +{ "label": "34/1", "node": 4009, "naklon": 0 }, +{ "label": "34/2", "node": 3602, "naklon": 0 }, +{ "label": "34/3", "node": 3441, "naklon": 0 }, +{ "label": "34/4", "node": 3464, "naklon": 0 }, +{ "label": "34/5", "node": 3883, "naklon": 0 }, +{ "label": "34/6", "node": 4098, "naklon": 0 }, +{ "label": "34/7", "node": 4003, "naklon": 0 }, +{ "label": "34/8", "node": 4004, "naklon": 0 }, +{ "label": "34/9", "node": 3888, "naklon": 0 }, +{ "label": "34/10", "node": 3997, "naklon": 0 }, +{ "label": "34/11", "node": 4006, "naklon": 0 }, +{ "label": "34/12", "node": 4000, "naklon": 0 }, +{ "label": "34/13", "node": 4011, "naklon": 0 }, +{ "label": "34/14", "node": 3999, "naklon": 0 }, +{ "label": "34/15", "node": 3981, "naklon": 0 }, +{ "label": "34/16", "node": 3988, "naklon": 0 }, +{ "label": "34/17", "node": 3986, "naklon": 0 }, +{ "label": "34/18", "node": 3998, "naklon": 0 }, +{ "label": "34/19", "node": 3983, "naklon": 0 }, +{ "label": "34/20", "node": 4005, "naklon": 0 }, +{ "label": "34/21", "node": 4001, "naklon": 0 }, +{ "label": "34/22", "node": 4008, "naklon": 0 }, +{ "label": "34/23", "node": 4002, "naklon": 0 }, +{ "label": "34/24", "node": 3996, "naklon": 0 }, +{ "label": "34/25", "node": 4007, "naklon": 0 }, +{ "label": "34/26", "node": 4113, "naklon": 15 }, +{ "label": "34/27", "node": 3595, "naklon": 5 }, +{ "label": "34/28", "node": 3599, "naklon": 5 }, +{ "label": "34/29", "node": 3601, "naklon": 5 }, +{ "label": "34/30", "node": 4205, "naklon": 0 }, +{ "label": "34/31", "node": 3987, "naklon": null }, +{ "label": "34/32", "node": 4214, "naklon": 0 }, +{ "label": "34/33", "node": 4226, "naklon": 0 }, +{ "label": "34/34", "node": 4209, "naklon": 0 }, +{ "label": "34/35", "node": 4201, "naklon": 0 }, +{ "label": "34/36", "node": 3440, "naklon": 0 }, +{ "label": "34/37", "node": 3465, "naklon": 0 }, +{ "label": "34/38", "node": 3446, "naklon": 0 }, +{ "label": "34/39", "node": 4039, "naklon": 5 }, +{ "label": "34/40", "node": 4057, "naklon": 5 }, +{ "label": "34/41", "node": 3985, "naklon": 0 }, +{ "label": "34/42", "node": 3882, "naklon": 0 }, +{ "label": "34/43", "node": 4040, "naklon": 5 }, +{ "label": "34/44", "node": 3231, "naklon": 0 }, +{ "label": "34/45", "node": 3227, "naklon": 0 }, +{ "label": "34/46", "node": 3431, "naklon": 0 }, +{ "label": "34/47", "node": 4013, "naklon": 0 }, +{ "label": "34/48", "node": 4045, "naklon": 0 }, +{ "label": "34/49", "node": 3949, "naklon": 0 }, +{ "label": "34/50", "node": 3953, "naklon": 0 }, +{ "label": "34/51", "node": 3952, "naklon": 0 }, +{ "label": "34/52", "node": 3995, "naklon": 0 }, +{ "label": "34/53", "node": 3992, "naklon": 0 }, +{ "label": "34/54", "node": 4198, "naklon": 0 }, +{ "label": "34/55", "node": 3935, "naklon": 0 }, +{ "label": "34/56", "node": 4050, "naklon": 0 }, +{ "label": "34/57", "node": 4049, "naklon": 0 }, +{ "label": "34/58", "node": 4054, "naklon": 0 }, +{ "label": "34/59", "node": 3663, "naklon": 6 }, +{ "label": "34/60", "node": 3661, "naklon": 6 }, +{ "label": "34/61", "node": 3664, "naklon": 6 }, +{ "label": "34/62", "node": 3660, "naklon": 6 }, +{ "label": "34/63", "node": 3662, "naklon": 6 }, +{ "label": "34/65", "node": 3665, "naklon": 6 }, +{ "label": "34/66", "node": 3667, "naklon": 6 }, +{ "label": "34/67", "node": 3675, "naklon": 6 }, +{ "label": "34/68", "node": 3666, "naklon": 6 }, +{ "label": "34/69", "node": 3652, "naklon": 6 }, +{ "label": "34/70", "node": 3458, "naklon": 6 }, +{ "label": "34/70/1", "node": 4425, "naklon": 6 }, +{ "label": "34/71", "node": 3459, "naklon": 6 }, +{ "label": "34/72", "node": 3435, "naklon": 6 }, +{ "label": "34/73", "node": 3448, "naklon": 6 }, +{ "label": "34/74", "node": 3451, "naklon": 6 }, +{ "label": "34/75", "node": 3442, "naklon": 6 }, +{ "label": "34/76", "node": 3449, "naklon": 6 }, +{ "label": "34/77", "node": 3450, "naklon": 6 }, +{ "label": "34/78", "node": 3433, "naklon": 6 }, +{ "label": "34/80", "node": 3432, "naklon": 12 }, +{ "label": "34/81", "node": 3470, "naklon": 12 }, +{ "label": "34/82", "node": 3438, "naklon": 12 }, +{ "label": "34/83", "node": 3439, "naklon": 12 }, +{ "label": "34/84", "node": 4028, "naklon": 5 }, +{ "label": "34/85", "node": 3596, "naklon": 5 }, +{ "label": "34/86", "node": 4021, "naklon": 5 }, +{ "label": "34/87", "node": 3437, "naklon": 12 }, +{ "label": "34/88", "node": 3428, "naklon": 12 }, +{ "label": "34/89", "node": 3430, "naklon": 12 }, +{ "label": "34/91", "node": 3454, "naklon": 6 }, +{ "label": "34/92", "node": 3492, "naklon": 6 }, +{ "label": "34/93", "node": 3462, "naklon": 6 }, +{ "label": "34/94", "node": 3427, "naklon": 6 }, +{ "label": "34/95", "node": 3434, "naklon": 6 }, +{ "label": "34/96", "node": 3456, "naklon": 6 }, +{ "label": "34/98/1", "node": 4307, "naklon": 6 }, +{ "label": "35/1", "node": 3968, "naklon": 0 }, +{ "label": "35/2", "node": 3969, "naklon": 0 }, +{ "label": "35/3", "node": 3947, "naklon": 0 }, +{ "label": "35/4", "node": 3979, "naklon": 0 }, +{ "label": "35/5", "node": 3959, "naklon": 0 }, +{ "label": "35/6", "node": 3948, "naklon": 0 }, +{ "label": "35/7", "node": 3961, "naklon": 0 }, +{ "label": "35/8", "node": 3956, "naklon": 0 }, +{ "label": "35/9", "node": 3604, "naklon": 0 }, +{ "label": "35/10", "node": 3944, "naklon": 0 }, +{ "label": "35/11", "node": 3960, "naklon": 0 }, +{ "label": "35/12", "node": 3958, "naklon": 0 }, +{ "label": "35/13", "node": 4036, "naklon": 5 }, +{ "label": "35/18", "node": 3893, "naklon": 5 }, +{ "label": "35/19", "node": 4108, "naklon": 5 }, +{ "label": "35/20", "node": 4017, "naklon": 5 }, +{ "label": "35/21", "node": 3963, "naklon": 0 }, +{ "label": "35/22", "node": 3658, "naklon": 0 }, +{ "label": "35/23", "node": 3975, "naklon": 0 }, +{ "label": "35/24", "node": 3980, "naklon": 0 }, +{ "label": "35/25", "node": 4012, "naklon": 0 }, +{ "label": "35/26", "node": 3655, "naklon": 0 }, +{ "label": "35/27", "node": 3962, "naklon": 0 }, +{ "label": "35/28", "node": 3945, "naklon": 0 }, +{ "label": "35/29", "node": 3569, "naklon": 0 }, +{ "label": "35/30", "node": 3429, "naklon": 0 }, +{ "label": "35/31", "node": 3657, "naklon": 0 }, +{ "label": "35/32", "node": 3646, "naklon": 0 }, +{ "label": "35/33", "node": 3622, "naklon": 0 }, +{ "label": "35/34", "node": 3612, "naklon": 0 }, +{ "label": "35/35", "node": 3955, "naklon": 0 }, +{ "label": "35/37", "node": 3878, "naklon": 0 }, +{ "label": "35/38", "node": 3965, "naklon": 0 }, +{ "label": "35/39", "node": 3970, "naklon": 0 }, +{ "label": "35/40", "node": 3611, "naklon": 0 }, +{ "label": "35/41", "node": 2635, "naklon": 0 }, +{ "label": "35/42", "node": 3978, "naklon": 0 }, +{ "label": "35/43", "node": 4213, "naklon": 0 }, +{ "label": "35/44", "node": 3984, "naklon": 0 }, +{ "label": "35/45", "node": 4218, "naklon": 0 }, +{ "label": "35/46", "node": 3973, "naklon": 0 }, +{ "label": "35/47", "node": 3974, "naklon": 0 }, +{ "label": "35/48", "node": 3759, "naklon": 0 }, +{ "label": "35/49", "node": 3844, "naklon": 0 }, +{ "label": "35/50", "node": 3804, "naklon": 0 }, +{ "label": "35/51", "node": 3831, "naklon": 0 }, +{ "label": "35/52", "node": 3643, "naklon": 0 }, +{ "label": "35/53", "node": 3966, "naklon": 0 }, +{ "label": "35/54", "node": 3971, "naklon": 0 }, +{ "label": "35/55", "node": 3650, "naklon": 6 }, +{ "label": "35/56", "node": 3651, "naklon": 6 }, +{ "label": "35/57", "node": 3669, "naklon": 6 }, +{ "label": "35/58", "node": 3648, "naklon": 6 }, +{ "label": "35/59", "node": 3645, "naklon": 6 }, +{ "label": "35/60", "node": 3659, "naklon": 6 }, +{ "label": "35/61", "node": 3647, "naklon": 6 }, +{ "label": "35/62", "node": 3644, "naklon": 6 }, +{ "label": "35/63", "node": 3671, "naklon": 6 }, +{ "label": "35/64", "node": 3682, "naklon": 6 }, +{ "label": "35/65", "node": 3672, "naklon": 6 }, +{ "label": "35/66", "node": 3683, "naklon": 6 }, +{ "label": "35/67", "node": 3673, "naklon": 6 }, +{ "label": "35/68", "node": 3674, "naklon": 6 }, +{ "label": "35/69", "node": 3679, "naklon": 6 }, +{ "label": "35/70", "node": 3649, "naklon": 6 }, +{ "label": "35/71", "node": 3687, "naklon": 6 }, +{ "label": "35/72", "node": 3677, "naklon": 6 }, +{ "label": "35/73", "node": 3690, "naklon": 6 }, +{ "label": "35/74", "node": 3691, "naklon": 6 }, +{ "label": "35/75", "node": 3676, "naklon": 6 }, +{ "label": "35/76", "node": 3680, "naklon": 6 }, +{ "label": "35/77", "node": 3668, "naklon": 6 }, +{ "label": "35/78", "node": 3681, "naklon": 6 }, +{ "label": "35/79", "node": 3670, "naklon": 6 }, +{ "label": "35/80", "node": 3689, "naklon": 6 }, +{ "label": "35/81", "node": 3678, "naklon": 6 }, +{ "label": "35/82", "node": 3693, "naklon": 6 }, +{ "label": "35/83", "node": 3654, "naklon": null }, +{ "label": "36/1", "node": 4086, "naklon": 0 }, +{ "label": "36/2", "node": 4085, "naklon": 0 }, +{ "label": "36/3", "node": 4083, "naklon": 0 }, +{ "label": "36/4", "node": 4087, "naklon": 0 }, +{ "label": "36/5", "node": 4077, "naklon": 0 }, +{ "label": "36/6", "node": 4082, "naklon": 0 }, +{ "label": "36/7", "node": 4186, "naklon": 0 }, +{ "label": "36/8", "node": 4206, "naklon": 0 }, +{ "label": "36/9", "node": 4080, "naklon": 0 }, +{ "label": "36/10", "node": 4081, "naklon": 0 }, +{ "label": "36/11", "node": 4210, "naklon": 0 }, +{ "label": "36/12", "node": 4079, "naklon": 0 }, +{ "label": "36/13", "node": 4076, "naklon": 0 }, +{ "label": "36/14", "node": 3852, "naklon": 0 }, +{ "label": "36/15", "node": 2813, "naklon": 0 }, +{ "label": "36/16", "node": 4219, "naklon": 0 }, +{ "label": "37/1A", "node": 3104, "naklon": 15 }, +{ "label": "37/1B", "node": 3121, "naklon": 15 }, +{ "label": "37/2", "node": 3113, "naklon": 10 }, +{ "label": "37/3", "node": 3118, "naklon": 10 }, +{ "label": "37/4", "node": 3111, "naklon": 10 }, +{ "label": "37/5", "node": 4020, "naklon": 10 }, +{ "label": "37/6", "node": 3119, "naklon": 10 }, +{ "label": "37/7", "node": 3110, "naklon": 10 }, +{ "label": "37/8", "node": 3108, "naklon": 10 }, +{ "label": "37/12", "node": 3107, "naklon": 0 }, +{ "label": "37/13", "node": 3199, "naklon": 0 }, +{ "label": "37/14", "node": 3120, "naklon": 0 }, +{ "label": "37/15", "node": 3122, "naklon": 0 }, +{ "label": "37/16", "node": 3908, "naklon": 0 }, +{ "label": "37/17", "node": 3114, "naklon": 0 }, +{ "label": "37/18", "node": 3105, "naklon": 0 }, +{ "label": "37/19", "node": 3116, "naklon": 0 }, +{ "label": "37/20", "node": 3106, "naklon": 0 }, +{ "label": "37/21", "node": 2887, "naklon": 5 }, +{ "label": "37/22", "node": 2888, "naklon": 5 }, +{ "label": "37/23", "node": 2877, "naklon": 5 }, +{ "label": "37/24", "node": 2891, "naklon": 5 }, +{ "label": "37/25", "node": 2886, "naklon": 5 }, +{ "label": "37/26", "node": 2892, "naklon": 5 }, +{ "label": "37/27", "node": 2882, "naklon": 5 }, +{ "label": "37/28", "node": 2883, "naklon": 5 }, +{ "label": "37/29", "node": 2876, "naklon": 5 }, +{ "label": "37/30", "node": 3109, "naklon": 5 }, +{ "label": "37/31", "node": 4152, "naklon": 5 }, +{ "label": "37/32", "node": 3117, "naklon": 5 }, +{ "label": "37/33", "node": 2870, "naklon": 5 }, +{ "label": "37/34", "node": 2867, "naklon": 0 }, +{ "label": "37/35", "node": 2865, "naklon": 0 }, +{ "label": "37/36", "node": 3096, "naklon": 0 }, +{ "label": "37/37", "node": 2871, "naklon": 0 }, +{ "label": "37/38", "node": 2884, "naklon": 0 }, +{ "label": "37/39", "node": 2855, "naklon": 0 }, +{ "label": "37/40", "node": 2878, "naklon": 0 }, +{ "label": "37/41", "node": 2889, "naklon": 0 }, +{ "label": "37/42", "node": 2879, "naklon": 0 }, +{ "label": "37/43", "node": 2850, "naklon": 0 }, +{ "label": "37/44", "node": 2894, "naklon": 0 }, +{ "label": "37/45", "node": 2880, "naklon": 0 }, +{ "label": "37/46", "node": 2893, "naklon": 0 }, +{ "label": "37/47", "node": 2890, "naklon": 0 }, +{ "label": "37/48", "node": 4355, "naklon": 0 }, +{ "label": "37/49", "node": 2885, "naklon": 0 }, +{ "label": "37/50", "node": 2875, "naklon": 0 }, +{ "label": "38/30A", "node": 3486, "naklon": 5 }, +{ "label": "38/30B", "node": 3714, "naklon": 0 }, +{ "label": "38/32A", "node": 3483, "naklon": 5 }, +{ "label": "38/32B", "node": 3496, "naklon": 0 }, +{ "label": "38/35A", "node": 3487, "naklon": 5 }, +{ "label": "38/35B", "node": 3498, "naklon": 5 }, +{ "label": "38/38A", "node": 3578, "naklon": 5 }, +{ "label": "38/38B", "node": 3508, "naklon": 5 }, +{ "label": "38/59A", "node": 3787, "naklon": 5 }, +{ "label": "38/59B", "node": 3491, "naklon": 5 }, +{ "label": "38/1", "node": 3568, "naklon": null }, +{ "label": "38/2", "node": 3502, "naklon": 0 }, +{ "label": "38/3", "node": 3836, "naklon": 0 }, +{ "label": "38/4", "node": 3588, "naklon": 0 }, +{ "label": "38/5", "node": 3493, "naklon": 0 }, +{ "label": "38/6", "node": 3580, "naklon": 0 }, +{ "label": "38/7", "node": 3572, "naklon": 0 }, +{ "label": "38/8", "node": 3506, "naklon": 0 }, +{ "label": "38/9", "node": 3503, "naklon": 0 }, +{ "label": "38/10", "node": 3579, "naklon": 0 }, +{ "label": "38/11", "node": 3586, "naklon": 0 }, +{ "label": "38/12", "node": 3495, "naklon": 5 }, +{ "label": "38/13", "node": 3492, "naklon": 5 }, +{ "label": "38/14", "node": 3532, "naklon": 5 }, +{ "label": "38/15", "node": 3574, "naklon": 5 }, +{ "label": "38/16", "node": 4140, "naklon": 5 }, +{ "label": "38/17", "node": 3795, "naklon": 5 }, +{ "label": "38/18", "node": 3788, "naklon": 5 }, +{ "label": "38/19", "node": 3796, "naklon": 5 }, +{ "label": "38/20", "node": 3797, "naklon": 5 }, +{ "label": "38/21", "node": 3798, "naklon": 5 }, +{ "label": "38/22", "node": 3786, "naklon": 5 }, +{ "label": "38/23", "node": 4067, "naklon": 5 }, +{ "label": "38/24", "node": 3773, "naklon": 5 }, +{ "label": "38/25", "node": 3774, "naklon": 5 }, +{ "label": "38/26", "node": 3789, "naklon": 5 }, +{ "label": "38/27", "node": 3520, "naklon": null }, +{ "label": "38/29", "node": 3577, "naklon": 5 }, +{ "label": "38/31", "node": 3530, "naklon": null }, +{ "label": "38/33", "node": 3488, "naklon": 5 }, +{ "label": "38/34", "node": 3505, "naklon": 5 }, +{ "label": "38/36", "node": 3497, "naklon": 5 }, +{ "label": "38/37", "node": 3490, "naklon": 5 }, +{ "label": "38/39", "node": 3585, "naklon": 5 }, +{ "label": "38/40", "node": 3582, "naklon": 5 }, +{ "label": "38/41", "node": 3507, "naklon": 5 }, +{ "label": "38/42", "node": 3484, "naklon": 5 }, +{ "label": "38/43", "node": 3501, "naklon": 5 }, +{ "label": "38/44", "node": 3581, "naklon": 5 }, +{ "label": "38/45", "node": 4192, "naklon": 5 }, +{ "label": "38/46", "node": 3576, "naklon": 5 }, +{ "label": "38/47", "node": 3489, "naklon": 5 }, +{ "label": "38/48", "node": 3573, "naklon": 5 }, +{ "label": "38/49", "node": 3504, "naklon": 5 }, +{ "label": "38/50", "node": 3794, "naklon": 5 }, +{ "label": "38/51", "node": 3485, "naklon": 5 }, +{ "label": "38/52", "node": 3482, "naklon": 5 }, +{ "label": "38/53", "node": 3575, "naklon": 5 }, +{ "label": "38/54", "node": 3499, "naklon": 5 }, +{ "label": "38/55", "node": 3494, "naklon": 5 }, +{ "label": "38/56", "node": 3583, "naklon": 5 }, +{ "label": "38/57", "node": 3570, "naklon": 5 }, +{ "label": "38/58", "node": 3500, "naklon": 0 }, +{ "label": "38/63", "node": 3510, "naklon": null }, +{ "label": "38/64", "node": 3512, "naklon": null }, +{ "label": "38/67", "node": 3535, "naklon": null }, +{ "label": "38/68", "node": 3531, "naklon": null }, +{ "label": "38/69", "node": 3537, "naklon": null }, +{ "label": "39/1", "node": 3522, "naklon": 10 }, +{ "label": "39/2", "node": 4018, "naklon": 10 }, +{ "label": "39/3", "node": 4019, "naklon": 10 }, +{ "label": "39/4", "node": 4154, "naklon": 5 }, +{ "label": "39/5", "node": 3907, "naklon": 5 }, +{ "label": "39/6", "node": 4148, "naklon": 0 }, +{ "label": "39/7", "node": 4153, "naklon": 0 }, +{ "label": "39/8", "node": 3938, "naklon": 0 }, +{ "label": "39/9", "node": 3802, "naklon": 0 }, +{ "label": "39/10", "node": 4015, "naklon": 0 }, +{ "label": "39/11", "node": 3929, "naklon": 0 }, +{ "label": "39/12", "node": 3946, "naklon": 0 }, +{ "label": "39/13", "node": 4014, "naklon": 0 }, +{ "label": "39/14", "node": 4155, "naklon": 0 }, +{ "label": "39/15", "node": 4149, "naklon": 0 }, +{ "label": "39/16", "node": 3642, "naklon": 0 }, +{ "label": "39/17", "node": 3636, "naklon": 5 }, +{ "label": "39/18", "node": 3991, "naklon": 0 }, +{ "label": "39/19", "node": 3994, "naklon": 0 }, +{ "label": "39/20", "node": 3990, "naklon": 0 }, +{ "label": "39/21", "node": 3967, "naklon": 0 }, +{ "label": "39/22", "node": 3977, "naklon": 0 }, +{ "label": "39/23", "node": 3757, "naklon": 15 }, +{ "label": "39/24", "node": 3633, "naklon": 15 }, +{ "label": "39/25", "node": 3744, "naklon": 15 }, +{ "label": "39/26", "node": 4023, "naklon": 5 }, +{ "label": "39/27", "node": 3720, "naklon": 5 }, +{ "label": "39/28", "node": 3734, "naklon": 5 }, +{ "label": "39/29", "node": 3741, "naklon": 5 }, +{ "label": "39/30", "node": 3721, "naklon": 5 }, +{ "label": "39/31", "node": 3845, "naklon": 0 }, +{ "label": "39/32", "node": 3840, "naklon": 0 }, +{ "label": "39/33", "node": 3837, "naklon": null }, +{ "label": "39/34", "node": 3839, "naklon": 0 }, +{ "label": "41/1", "node": 3542, "naklon": null }, +{ "label": "41/2", "node": 3566, "naklon": null }, +{ "label": "41/3", "node": 3548, "naklon": null }, +{ "label": "41/4", "node": 3515, "naklon": null }, +{ "label": "41/5", "node": 3559, "naklon": null }, +{ "label": "41/6", "node": 3509, "naklon": null }, +{ "label": "41/7", "node": 3524, "naklon": null }, +{ "label": "41/8", "node": 3518, "naklon": null }, +{ "label": "41/9", "node": 3182, "naklon": null }, +{ "label": "41/10", "node": 3187, "naklon": null }, +{ "label": "41/11", "node": 3195, "naklon": 0 }, +{ "label": "41/12", "node": 3857, "naklon": 0 }, +{ "label": "41/13", "node": 3183, "naklon": 0 }, +{ "label": "41/14", "node": 3177, "naklon": 0 }, +{ "label": "41/15", "node": 3189, "naklon": 0 }, +{ "label": "41/16", "node": 3186, "naklon": 0 }, +{ "label": "42/1", "node": 3178, "naklon": 0 }, +{ "label": "42/2", "node": 3219, "naklon": 0 }, +{ "label": "42/3", "node": 3475, "naklon": 0 }, +{ "label": "42/4", "node": 3175, "naklon": 0 }, +{ "label": "42/5", "node": 3222, "naklon": 0 }, +{ "label": "42/6", "node": 3221, "naklon": 0 }, +{ "label": "42/7", "node": 3181, "naklon": 0 }, +{ "label": "42/8", "node": 3180, "naklon": 0 }, +{ "label": "42/9", "node": 3218, "naklon": 0 }, +{ "label": "42/10", "node": 3176, "naklon": 0 }, +{ "label": "42/11", "node": 3174, "naklon": 0 }, +{ "label": "42/12", "node": 3220, "naklon": 0 }, +{ "label": "42/13", "node": 3533, "naklon": null }, +{ "label": "42/14", "node": 3543, "naklon": null }, +{ "label": "42/15", "node": 3554, "naklon": null }, +{ "label": "42/16", "node": 3549, "naklon": null }, +{ "label": "43/1", "node": 2857, "naklon": 5 }, +{ "label": "43/2", "node": 2752, "naklon": 5 }, +{ "label": "43/3", "node": 2753, "naklon": 5 }, +{ "label": "43/4", "node": 3024, "naklon": 5 }, +{ "label": "43/5", "node": 2754, "naklon": 5 }, +{ "label": "43/6", "node": 4423, "naklon": 5 }, +{ "label": "43/7", "node": 4368, "naklon": 5 }, +{ "label": "43/8", "node": 2978, "naklon": 5 }, +{ "label": "43/9", "node": 2868, "naklon": 5 }, +{ "label": "43/10", "node": 4377, "naklon": 5 }, +{ "label": "43/11", "node": 2757, "naklon": 5 }, +{ "label": "43/12", "node": 2970, "naklon": 5 }, +{ "label": "43/13", "node": 2758, "naklon": 5 }, +{ "label": "43/14", "node": 4378, "naklon": 5 }, +{ "label": "43/15", "node": 2759, "naklon": 5 }, +{ "label": "43/16", "node": 4342, "naklon": 5 }, +{ "label": "43/17", "node": 3026, "naklon": null }, +{ "label": "43/18", "node": 2986, "naklon": null }, +{ "label": "43/19", "node": 4343, "naklon": null }, +{ "label": "43/20", "node": 2760, "naklon": null }, +{ "label": "43/21", "node": 4379, "naklon": null }, +{ "label": "43/22", "node": 2971, "naklon": null }, +{ "label": "43/23", "node": 2761, "naklon": null }, +{ "label": "43/24", "node": 2762, "naklon": null }, +{ "label": "43/25", "node": 4339, "naklon": null }, +{ "label": "43/26", "node": 4380, "naklon": null }, +{ "label": "43/27", "node": 2975, "naklon": null }, +{ "label": "43/28", "node": 3003, "naklon": null }, +{ "label": "43/29", "node": 4338, "naklon": null }, +{ "label": "43/30", "node": 3002, "naklon": null }, +{ "label": "43/31", "node": 4345, "naklon": null }, +{ "label": "43/32", "node": 2979, "naklon": null }, +{ "label": "43/33", "node": 2989, "naklon": null }, +{ "label": "43/34", "node": 2996, "naklon": null }, +{ "label": "43/35", "node": 2972, "naklon": null }, +{ "label": "43/36", "node": 2988, "naklon": null }, +{ "label": "43/37", "node": 4344, "naklon": null }, +{ "label": "43/38", "node": 3022, "naklon": null }, +{ "label": "43/39", "node": 4341, "naklon": null }, +{ "label": "43/40", "node": 2983, "naklon": null }, +{ "label": "43/41", "node": 2995, "naklon": null }, +{ "label": "43/42", "node": 2763, "naklon": null }, +{ "label": "43/43", "node": 2764, "naklon": null }, +{ "label": "43/44", "node": 2765, "naklon": null }, +{ "label": "43/45", "node": 2766, "naklon": null }, +{ "label": "43/46", "node": 2767, "naklon": null }, +{ "label": "43/47", "node": 2768, "naklon": null }, +{ "label": "43/48", "node": 3018, "naklon": null }, +{ "label": "43/49", "node": 2982, "naklon": null }, +{ "label": "43/50", "node": 3019, "naklon": 0 }, +{ "label": "43/51", "node": 3013, "naklon": null }, +{ "label": "43/52", "node": 3007, "naklon": null }, +{ "label": "43/53", "node": 2980, "naklon": null }, +{ "label": "43/54", "node": 3011, "naklon": null }, +{ "label": "43/55", "node": 2672, "naklon": null }, +{ "label": "43/56", "node": 2673, "naklon": null }, +{ "label": "43/57", "node": 2674, "naklon": null }, +{ "label": "43/58", "node": 2675, "naklon": null }, +{ "label": "43/59", "node": 2676, "naklon": null }, +{ "label": "43/60", "node": 2677, "naklon": null }, +{ "label": "43/61", "node": 2678, "naklon": null }, +{ "label": "43/62", "node": 2679, "naklon": null }, +{ "label": "43/63", "node": 2680, "naklon": null }, +{ "label": "43/64", "node": 2840, "naklon": null }, +{ "label": "43/65", "node": 2682, "naklon": null }, +{ "label": "43/66", "node": 2683, "naklon": null }, +{ "label": "43/67", "node": 2684, "naklon": 0 }, +{ "label": "43/68", "node": 2685, "naklon": null }, +{ "label": "43/69", "node": 2686, "naklon": null }, +{ "label": "43/70", "node": 2687, "naklon": null }, +{ "label": "43/71", "node": 2688, "naklon": null }, +{ "label": "43/72", "node": 2689, "naklon": null }, +{ "label": "43/73", "node": 2690, "naklon": null }, +{ "label": "43/74", "node": 2691, "naklon": null }, +{ "label": "43/75", "node": 2692, "naklon": null }, +{ "label": "43/76", "node": 2693, "naklon": 0 }, +{ "label": "43/77", "node": 2694, "naklon": null }, +{ "label": "43/78", "node": 2695, "naklon": null }, +{ "label": "43/79", "node": 2696, "naklon": 0 }, +{ "label": "43/80", "node": 2697, "naklon": null }, +{ "label": "43/81", "node": 2698, "naklon": 0 }, +{ "label": "43/82", "node": 2699, "naklon": null }, +{ "label": "43/83", "node": 2700, "naklon": 0 }, +{ "label": "43/84", "node": 2744, "naklon": null }, +{ "label": "43/85", "node": 2745, "naklon": 0 }, +{ "label": "43/86", "node": 2746, "naklon": null }, +{ "label": "43/87", "node": 2747, "naklon": 0 }, +{ "label": "43/88", "node": 2748, "naklon": null }, +{ "label": "43/89", "node": 2749, "naklon": 0 }, +{ "label": "43/90", "node": 2841, "naklon": null }, +{ "label": "45/1", "node": 4237, "naklon": 5 }, +{ "label": "45/2", "node": 4226, "naklon": 5 }, +{ "label": "45/3", "node": 4242, "naklon": 5 }, +{ "label": "45/4", "node": 4179, "naklon": 5 }, +{ "label": "45/5", "node": 4247, "naklon": 5 }, +{ "label": "45/6", "node": 4245, "naklon": 5 }, +{ "label": "45/7", "node": 3872, "naklon": 5 }, +{ "label": "45/8", "node": 4175, "naklon": 5 }, +{ "label": "45/9", "node": 4236, "naklon": 5 }, +{ "label": "45/10", "node": 4170, "naklon": 5 }, +{ "label": "45/11", "node": 4238, "naklon": 5 }, +{ "label": "45/12", "node": 4246, "naklon": 5 }, +{ "label": "45/13", "node": 4166, "naklon": 5 }, +{ "label": "45/14", "node": 4227, "naklon": 5 }, +{ "label": "45/15", "node": 4171, "naklon": 5 }, +{ "label": "45/16", "node": 4180, "naklon": 5 }, +{ "label": "45/17", "node": 4244, "naklon": 5 }, +{ "label": "45/18", "node": 4199, "naklon": 5 }, +{ "label": "45/19", "node": 4239, "naklon": 5 }, +{ "label": "45/20", "node": 4207, "naklon": 5 }, +{ "label": "45/21", "node": 4223, "naklon": 5 }, +{ "label": "45/22", "node": 4230, "naklon": 5 }, +{ "label": "45/23", "node": 4233, "naklon": 5 }, +{ "label": "45/24", "node": 4222, "naklon": 5 }, +{ "label": "45/25", "node": 4217, "naklon": 5 }, +{ "label": "45/26", "node": 4243, "naklon": 5 }, +{ "label": "45/27", "node": 4200, "naklon": 5 }, +{ "label": "45/28", "node": 4228, "naklon": 5 }, +{ "label": "45/29", "node": 4211, "naklon": 5 }, +{ "label": "45/30", "node": 4234, "naklon": 5 }, +{ "label": "45/31", "node": 4235, "naklon": 5 }, +{ "label": "45/32", "node": 4203, "naklon": 5 }, +{ "label": "45/33", "node": 4240, "naklon": 5 }, +{ "label": "45/34", "node": 4224, "naklon": 5 }, +{ "label": "45/35", "node": 4232, "naklon": 5 }, +{ "label": "45/36", "node": 4231, "naklon": 5 }, +{ "label": "45/37", "node": 4161, "naklon": 5 }, +{ "label": "45/38", "node": 4225, "naklon": 5 }, +{ "label": "45/39", "node": 4241, "naklon": 5 }, +{ "label": "45/40", "node": 4229, "naklon": 5 }, +{ "label": "45/41", "node": 4221, "naklon": 5 }, +{ "label": "45/42", "node": 4212, "naklon": 5 }, +{ "label": "45/43", "node": 4216, "naklon": 5 }, +{ "label": "45/44", "node": 3864, "naklon": null }, +{ "label": "46/1", "node": 3806, "naklon": 5 }, +{ "label": "46/2", "node": 3813, "naklon": 5 }, +{ "label": "46/3", "node": 3815, "naklon": 5 }, +{ "label": "46/4", "node": 3807, "naklon": 5 }, +{ "label": "46/5", "node": 3895, "naklon": 5 }, +{ "label": "46/6", "node": 3809, "naklon": 5 }, +{ "label": "46/7", "node": 3820, "naklon": 5 }, +{ "label": "46/8", "node": 3805, "naklon": 5 }, +{ "label": "46/9", "node": 3894, "naklon": 0 }, +{ "label": "46/10", "node": 4055, "naklon": 0 }, +{ "label": "46/11", "node": 3812, "naklon": 5 }, +{ "label": "46/12", "node": 3822, "naklon": 5 }, +{ "label": "46/13", "node": 3821, "naklon": 5 }, +{ "label": "46/14", "node": 3808, "naklon": 5 }, +{ "label": "46/15", "node": 3799, "naklon": 5 }, +{ "label": "46/16", "node": 3816, "naklon": 5 }, +{ "label": "46/17", "node": 3751, "naklon": 5 }, +{ "label": "46/18", "node": 3814, "naklon": 5 }, +{ "label": "46/19", "node": 4044, "naklon": 0 }, +{ "label": "46/20", "node": 3931, "naklon": 0 }, +{ "label": "46/21", "node": 3902, "naklon": 5 }, +{ "label": "46/22", "node": 3916, "naklon": 5 }, +{ "label": "46/23", "node": 3892, "naklon": 5 }, +{ "label": "46/24", "node": 3914, "naklon": 5 }, +{ "label": "46/25", "node": 3898, "naklon": 5 }, +{ "label": "46/26", "node": 3897, "naklon": 5 }, +{ "label": "46/27", "node": 3885, "naklon": 5 }, +{ "label": "46/28", "node": 3906, "naklon": 5 }, +{ "label": "46/29", "node": 3930, "naklon": 0 }, +{ "label": "46/30", "node": 3936, "naklon": 0 }, +{ "label": "46/31", "node": 3860, "naklon": 5 }, +{ "label": "46/32", "node": 3841, "naklon": 5 }, +{ "label": "46/33", "node": 3873, "naklon": 5 }, +{ "label": "46/34", "node": 3854, "naklon": 5 }, +{ "label": "46/35", "node": 3939, "naklon": 5 }, +{ "label": "46/36", "node": 3858, "naklon": 5 }, +{ "label": "46/37", "node": 3940, "naklon": 5 }, +{ "label": "46/38", "node": 4035, "naklon": 5 }, +{ "label": "47/1", "node": 3373, "naklon": 0 }, +{ "label": "47/2", "node": 3374, "naklon": 0 }, +{ "label": "47/3", "node": 3384, "naklon": 0 }, +{ "label": "47/4", "node": 3385, "naklon": 0 }, +{ "label": "48/1", "node": 4051, "naklon": 5 }, +{ "label": "48/2", "node": 4041, "naklon": 5 }, +{ "label": "48/3", "node": 4056, "naklon": 5 }, +{ "label": "48/4", "node": 3875, "naklon": 5 }, +{ "label": "48/5", "node": 4061, "naklon": 5 }, +{ "label": "48/6", "node": 4047, "naklon": 5 }, +{ "label": "48/7", "node": 4060, "naklon": 5 }, +{ "label": "48/8", "node": 4059, "naklon": 5 }, +{ "label": "48/9", "node": 4058, "naklon": 5 }, +{ "label": "48/10", "node": 3635, "naklon": 5 }, +{ "label": "48/11", "node": 3640, "naklon": 5 }, +{ "label": "48/12", "node": 3747, "naklon": 5 }, +{ "label": "48/13", "node": 3629, "naklon": 5 }, +{ "label": "48/14", "node": 4048, "naklon": 5 }, +{ "label": "48/15", "node": 4063, "naklon": 5 }, +{ "label": "48/16", "node": 4062, "naklon": 5 }, +{ "label": "48/17", "node": 4043, "naklon": 5 }, +{ "label": "48/18", "node": 4052, "naklon": 5 }, +{ "label": "48/19", "node": 4042, "naklon": 5 }, +{ "label": "48/20", "node": 4053, "naklon": 5 }, +{ "label": "50/15A", "node": 4167, "naklon": null }, +{ "label": "50/15B", "node": 4159, "naklon": null }, +{ "label": "50/1", "node": 4183, "naklon": 0 }, +{ "label": "50/2", "node": 4157, "naklon": 0 }, +{ "label": "50/3", "node": 4160, "naklon": 0 }, +{ "label": "50/4", "node": 4173, "naklon": 0 }, +{ "label": "50/5", "node": 4177, "naklon": 0 }, +{ "label": "50/6", "node": 4174, "naklon": 0 }, +{ "label": "50/7", "node": 4178, "naklon": 0 }, +{ "label": "50/8", "node": 4195, "naklon": 0 }, +{ "label": "50/9", "node": 4169, "naklon": 0 }, +{ "label": "50/10", "node": 4162, "naklon": 0 }, +{ "label": "50/11", "node": 4158, "naklon": 0 }, +{ "label": "50/12", "node": 4182, "naklon": 0 }, +{ "label": "50/13", "node": 4194, "naklon": 0 }, +{ "label": "50/14", "node": 4184, "naklon": 0 }, +{ "label": "50/16", "node": 4197, "naklon": null }, +{ "label": "50/17", "node": 4164, "naklon": null }, +{ "label": "50/18", "node": 3306, "naklon": null }, +{ "label": "50/19", "node": 4168, "naklon": null }, +{ "label": "50/20", "node": 4193, "naklon": null }, +{ "label": "50/21", "node": 4187, "naklon": null }, +{ "label": "50/22", "node": 4163, "naklon": null }, +{ "label": "50/23", "node": 4165, "naklon": null }, +{ "label": "50/24", "node": 4185, "naklon": null }, +{ "label": "50/25", "node": 3904, "naklon": null }, +{ "label": "53/1", "node": 2619, "naklon": 0 }, +{ "label": "53/2", "node": 2623, "naklon": 0 }, +{ "label": "53/3", "node": 2617, "naklon": 0 }, +{ "label": "53/4", "node": 2622, "naklon": 0 }, +{ "label": "53/5", "node": 2618, "naklon": 0 }, +{ "label": "53/6", "node": 2626, "naklon": 0 }, +{ "label": "53/7", "node": 2869, "naklon": 0 }, +{ "label": "53/8", "node": 2613, "naklon": 0 }, +{ "label": "53/9", "node": 2608, "naklon": 0 }, +{ "label": "53/10", "node": 2611, "naklon": 0 }, +{ "label": "53/11", "node": 2598, "naklon": 0 }, +{ "label": "53/12", "node": 3528, "naklon": 0 }, +{ "label": "53/13", "node": 3545, "naklon": 0 }, +{ "label": "53/14", "node": 2620, "naklon": 0 }, +{ "label": "53/15", "node": 2612, "naklon": 0 }, +{ "label": "53/16", "node": 2615, "naklon": 0 }, +{ "label": "53/17", "node": 3722, "naklon": 0 }, +{ "label": "53/18", "node": 2624, "naklon": 0 }, +{ "label": "53/19", "node": 2609, "naklon": 0 }, +{ "label": "53/20", "node": 2625, "naklon": 0 }, +{ "label": "53/21", "node": 2602, "naklon": 0 }, +{ "label": "53/22", "node": 2610, "naklon": 0 }, +{ "label": "53/23", "node": 2599, "naklon": 0 }, +{ "label": "53/24", "node": 2605, "naklon": 0 }, +{ "label": "53/25", "node": 2593, "naklon": 0 }, +{ "label": "53/26", "node": 3074, "naklon": 0 }, +{ "label": "53/27", "node": 2740, "naklon": 0 }, +{ "label": "53/28", "node": 2614, "naklon": 0 }, +{ "label": "53/29", "node": 2601, "naklon": 0 }, +{ "label": "53/30", "node": 4196, "naklon": 0 }, +{ "label": "53/31", "node": 2607, "naklon": 0 }, +{ "label": "53/32", "node": 2582, "naklon": 0 }, +{ "label": "53/33", "node": 2594, "naklon": 0 }, +{ "label": "53/34", "node": 2589, "naklon": 0 }, +{ "label": "53/35", "node": 2596, "naklon": 0 }, +{ "label": "53/36", "node": 2603, "naklon": 0 }, +{ "label": "53/37", "node": 2597, "naklon": 0 }, +{ "label": "53/38", "node": 2590, "naklon": 0 }, +{ "label": "53/39", "node": 2581, "naklon": 0 }, +{ "label": "53/40", "node": 2583, "naklon": 0 }, +{ "label": "53/41", "node": 2580, "naklon": 0 }, +{ "label": "53/42", "node": 2579, "naklon": 0 }, +{ "label": "53/43", "node": 2797, "naklon": 0 }, +{ "label": "53/44", "node": 2577, "naklon": 0 }, +{ "label": "53/45", "node": 2586, "naklon": 0 }, +{ "label": "53/46", "node": 2588, "naklon": 0 }, +{ "label": "53/47", "node": 2591, "naklon": 0 }, +{ "label": "53/48", "node": 2592, "naklon": 0 }, +{ "label": "53/49", "node": 2573, "naklon": 0 }, +{ "label": "53/50", "node": 2595, "naklon": 0 }, +{ "label": "53/51", "node": 2587, "naklon": 0 }, +{ "label": "53/52", "node": 2578, "naklon": 0 }, +{ "label": "53/53", "node": 2574, "naklon": 0 }, +{ "label": "53/54", "node": 2571, "naklon": 0 }, +{ "label": "53/55", "node": 2570, "naklon": 0 }, +{ "label": "53/56", "node": 2576, "naklon": 0 }, +{ "label": "53/57", "node": 2881, "naklon": 0 }, +{ "label": "53/58", "node": 2575, "naklon": 0 }, +{ "label": "53/59", "node": 2572, "naklon": 0 }, +{ "label": "53/60", "node": 2569, "naklon": 0 }, +{ "label": "55/1", "node": 4324, "naklon": 0 }, +{ "label": "55/2", "node": 4319, "naklon": 0 }, +{ "label": "55/3", "node": 4327, "naklon": 0 }, +{ "label": "55/4", "node": 4333, "naklon": 0 }, +{ "label": "55/5", "node": 4332, "naklon": 0 }, +{ "label": "55/6", "node": 4320, "naklon": 0 }, +{ "label": "55/7", "node": 4317, "naklon": 0 }, +{ "label": "55/8", "node": 4318, "naklon": 0 }, +{ "label": "55/9", "node": 4328, "naklon": 0 }, +{ "label": "55/10", "node": 4323, "naklon": 0 }, +{ "label": "55/11", "node": 4325, "naklon": 0 }, +{ "label": "55/12", "node": 4326, "naklon": 0 }, +{ "label": "55/13", "node": 4316, "naklon": 0 }, +{ "label": "55/14", "node": 4322, "naklon": 0 }, +{ "label": "55/15", "node": 4331, "naklon": 0 }, +{ "label": "55/16", "node": 4321, "naklon": 0 }, +{ "label": "55/17", "node": 4315, "naklon": 0 }, +{ "label": "55/18", "node": 4329, "naklon": 0 }, +{ "label": "55/19", "node": 4334, "naklon": 0 }, +{ "label": "55/20", "node": 4330, "naklon": 0 } +]; + +module.exports = { naklony }; diff --git a/RVO42/databases/modbus_config.js b/RVO42/databases/modbus_config.js new file mode 100755 index 0000000..b73116a --- /dev/null +++ b/RVO42/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/RVO42/databases/nodes.table b/RVO42/databases/nodes.table new file mode 100755 index 0000000..8886f4c --- /dev/null +++ b/RVO42/databases/nodes.table @@ -0,0 +1,17 @@ +node:number|pole_number:string|node_type:string|tbname:string|line:number|profile:string|processed:boolean|status:boolean|time_of_last_communication:number ++|3220|12|NEMA|roKgWqY95V3mXMRzyAjKln0bLjexpJPvaGDBw826|1||1|1|1760574009420|............. ++|3221|6|NEMA|wvKJdZML6mXP4DzWBAXx2VAjxNloa5g23Ve9Y1ry|1||1|1|1760574010187|............. ++|3222|5|NEMA|EjgWGnXaLy9opPOz20n48d786BlYM3w1deVQvbKr|1||1|1|1760574010315|............. ++|3475|3|NEMA|eod9aRWLVl34Gx1Dn7VNr972rz6qjgmpEXwQJN5Z|1||1|1|1760574010762|............. ++|3533|13|IP65|nJL5lPMwBx23YpqRe0rpgb7damXvWVbOrD4gNzy8|1||1|1|1760574013078|............. ++|3543|14|IP65|ZmRwd93QL4gaezxEbAx2dKk1prn2XjlPvGyqJ6BO|1||1|1|1760574013270|............. ++|3549|16|IP65|3a5oqJN1bgnx4Ol9dk89Y27ByE6jQ8mKDWMpGrLV|1||1|1|1760574014692|............. ++|3554|15|IP65|eod9aRWLVl34Gx1Dn7VNrE72rz6qjgmpEXwQJN5Z|1||1|1|1760574015826|............. ++|3174|11|NEMA|E6Kg9oDnLWyzPRMva7v5j9kJxp4VG58qO2w1lZYe|1||1|1|1760573987632|............. ++|3175|4|NEMA|3a5oqJN1bgnx4Ol9dk89Y17ByE6jQ8mKDWMpGrLV|1||1|1|1760573991689|............. ++|3176|10|NEMA|rDbQ84xzwgdqEoPm3kbE5D09anOZY1RXyBv2LVM6|1||1|1|1760573992440|............. ++|3178|1|NEMA|aw4eELG2DlPMdn1JW0BM6QAqQXOZRN3xB5yp8VKr|1||1|1|1760573992887|............. ++|3180|8|NEMA|PLBJzmK1r3Gynd6OW0gKpq0e5wV4vx9bDEqNgYR8|1||1|1|1760573996641|............. ++|3181|7|NEMA|Nzp2OoJlqn6r1ZgvdA3Bvv7abBwP5G4eE3RQmyxD|1||1|1|1760574008813|............. ++|3695|2|NEMA|ZmRwd93QL4gaezxEbAx2dbk1prn2XjlPvGyqJ6BO|1||1|1|1760574016353|............. ++|3218|9|NEMA|52dD6ZlV1QaOpRBmbAqG3NkKnGzWMLj4eJq38Pgo|1||1|1|1760574009260|............. diff --git a/RVO42/databases/nodes_original/nodes_original.table b/RVO42/databases/nodes_original/nodes_original.table new file mode 100755 index 0000000..ada9e02 --- /dev/null +++ b/RVO42/databases/nodes_original/nodes_original.table @@ -0,0 +1 @@ +[{"3220": "roKgWqY95V3mXMRzyAjKln0bLjexpJPvaGDBw826"}, {"3221": "wvKJdZML6mXP4DzWBAXx2VAjxNloa5g23Ve9Y1ry"}, {"3222": "EjgWGnXaLy9opPOz20n48d786BlYM3w1deVQvbKr"}, {"3475": "eod9aRWLVl34Gx1Dn7VNr972rz6qjgmpEXwQJN5Z"}, {"3533": "nJL5lPMwBx23YpqRe0rpgb7damXvWVbOrD4gNzy8"}, {"3543": "ZmRwd93QL4gaezxEbAx2dKk1prn2XjlPvGyqJ6BO"}, {"3549": "3a5oqJN1bgnx4Ol9dk89Y27ByE6jQ8mKDWMpGrLV"}, {"3554": "eod9aRWLVl34Gx1Dn7VNrE72rz6qjgmpEXwQJN5Z"}, {"3174": "E6Kg9oDnLWyzPRMva7v5j9kJxp4VG58qO2w1lZYe"}, {"3175": "3a5oqJN1bgnx4Ol9dk89Y17ByE6jQ8mKDWMpGrLV"}, {"3176": "rDbQ84xzwgdqEoPm3kbE5D09anOZY1RXyBv2LVM6"}, {"3178": "aw4eELG2DlPMdn1JW0BM6QAqQXOZRN3xB5yp8VKr"}, {"3180": "PLBJzmK1r3Gynd6OW0gKpq0e5wV4vx9bDEqNgYR8"}, {"3181": "Nzp2OoJlqn6r1ZgvdA3Bvv7abBwP5G4eE3RQmyxD"}, {"3695": "ZmRwd93QL4gaezxEbAx2dbk1prn2XjlPvGyqJ6BO"}, {"3218": "52dD6ZlV1QaOpRBmbAqG3NkKnGzWMLj4eJq38Pgo"}] \ No newline at end of file diff --git a/RVO42/databases/notifications.table b/RVO42/databases/notifications.table new file mode 100755 index 0000000..f7c96cb --- /dev/null +++ b/RVO42/databases/notifications.table @@ -0,0 +1,41 @@ +key:string|weight:string|sk:string|en:string ++|switching_profile_point_applied_to_line|INFORMATIONAL|Aplikovaný bod spínacieho profilu na línií č. ${line} : ${value}|Switching profile point applied to line no. ${line} : ${value}|............... ++|dusk_has_occured|INFORMATIONAL|Nastal súmrak: ${value}|Dusk has occured: ${value}|............... ++|dawn_has_occured|INFORMATIONAL|Nastal úsvit: ${value}|Dawn has occured: ${value}|............... ++|dimming_profile_was_successfully_received_by_node|NOTICE|Stmievací profil bol úspešne prijatý nodom č. ${node}|Dimming profile was successfully received by node no. ${node}|............... ++|master_node_is_responding_again|NOTICE|Master node začal znovu odpovedať|Master node is responding again|............... ++|command_was_sent_from_terminal_interface|DEBUG|Z terminálu bol odoslaný príkaz|A command was sent from terminal interface|............... ++|master_node_is_not_responding|ALERT|Master node neodpovedá|Master node is not responding|............... ++|configuration_of_dimming_profile_to_node_failed|ALERT|Konfigurácia stmievacieho profilu pre node č. ${node} zlyhala|Configuration of dimming profile to node no. ${node} has failed|............... ++|circuit_breaker_was_turned_on_line|NOTICE|Zapnutie ističa na línii č. ${line}|Circuit breaker was turned on - line no. ${line}|............... ++|circuit_breaker_was_turned_off_line|ERROR|Vypnutie ističa na línií č. ${line}|Circuit breaker was turned off - line no. ${line}|............... ++|dimming_profile_was_processed_for_node|INFORMATIONAL|Stmievací profil bol spracovaný pre node č. ${node}|Dimming profile was processed for node no. ${node}|............... ++|switching_profile_was_processed_for_line|INFORMATIONAL|Spínací profil bol spracovaný pre líniu č. ${line}|Switching profile was processed for line no. ${line}|............... ++|thermometer_is_not_responding|WARNING|Teplomer neodpovedá|Thermometer is not responding|............... ++|thermometer_is_responding_again|NOTICE|Teplomer znovu odpovedá|Thermometer is responding again|............... ++|thermometer_sends_invalid_data|WARNING|Teplomer posiela neplatné hodnoty|Thermometer sends invalid data|............... ++|main_switch_has_been_turned_off|CRITICAL|Hlavný vypínač bol vypnutý|Main switch has been turned off|............... ++|main_switch_has_been_turned_on|NOTICE|Hlavný vypínač bol zapnutý|Main switch has been turned on|............... ++|power_supply_has_disconnected_input|ALERT|Napájací zdroj nemá napätie na vstupe|Power supply has disconnected input|............... ++|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_main_open|NOTICE|Hlavné dvere boli otvorené|Main door has been opened|............... ++|door_em_open|NOTICE|Dvere silovej časti boli otvorené|Power door has been opened|............... ++|door_main_open_without_permission|WARNING|Hlavné dvere boli otvorené bez povolenia - zapnutá siréna|Main door has been opened without permission - alarm is on|............... ++|door_em_open_without_permission|WARNING|Dvere silovej časti boli otvorené bez povolenia|Power door has been opened without permission|............... ++|door_main_close|NOTICE|Hlavné dvere boli zatvorené|Main door has been closed|............... ++|door_em_close|NOTICE|Dvere silovej časti boli zatvorené|Power door has been closed|............... ++|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|............... ++|electrometer_ok|NOTICE|Elektromer znovu odpovedá|Electrometer is responding again|............... ++|no_voltage_on_phase|CRITICAL|Na fáze č. ${phase} nie je napätie|No voltage detected on phase no. ${phase}|............... ++|voltage_on_phase_restored|NOTICE|Napätie na fáze č. ${phase} bolo obnovené|Voltage on phase no. ${phase} has been restored|............... ++|flow_start|NOTICE|FLOW bol spustený|FLOW has been started |............... ++|twilight_sensor_nok|ERROR|Sensor súmraku neodpovedá|Twilight sensor is not responding|............... ++|twilight_sensor_ok|NOTICE|Sensor súmraku znovu odpovedá|Twilight sensor is responding again|............... ++|lamps_have_turned_on|NOTICE|Lampy sa zapli|Lamps have turned on|............... ++|lamps_have_turned_off|NOTICE|Lampy sa vypli|Lamps have turned off|............... ++|flow_restart|NOTICE|FLOW bol reštartovaný|FLOW has been restarted|............... ++|nodes_db_changed|NOTICE|Zmena v node databáze|Node db has changed|............... diff --git a/RVO42/databases/pins.table b/RVO42/databases/pins.table new file mode 100755 index 0000000..6417b40 --- /dev/null +++ b/RVO42/databases/pins.table @@ -0,0 +1,15 @@ +pin:string|type:string|line:number +*|input1_01|door_condition|0|........... +*|input1_02|rotary_switch_state|0|........... +*|input1_03|rotary_switch_state|0|........... +*|input1_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|........... +*|relay1_05|state_of_contactor|4|........... +*|28F46E9D0E00008B|temperature|0|........... +*|twilight_sensor|twilight_sensor|0|........... diff --git a/RVO42/databases/relays.table b/RVO42/databases/relays.table new file mode 100755 index 0000000..630d384 --- /dev/null +++ b/RVO42/databases/relays.table @@ -0,0 +1,6 @@ +line:number|tbname:string|contactor:number|profile:string ++|0|g9OxBZ5KRwNznlY6pAppGEAWXvjdEL4eGQobMDy2|1||........... ++|3|B5EoxeMVp4zwr8nqW0GBzGARjvD1PNamOGbLg63Z|9|{"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}|................................................................................................................................................................................................................................................................................................................................... ++|1|K94XLav1glVRnyQ6r01Pq3Ame3YJwBxM5oOzdP2j|9|{"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|d9x2V5LGYBzXp4mMRAOmXVkPloaqJwnQj6DgrNe3|9|{"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}|................................................................................................................................................................................................................................................................................ ++|4|m6EYyZoJ4gWexdjVPAR5K37RDOq9wv2N5XzKGplr|9|{"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/RVO42/databases/settings.table b/RVO42/databases/settings.table new file mode 100755 index 0000000..cbaad08 --- /dev/null +++ b/RVO42/databases/settings.table @@ -0,0 +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|project_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|cloud_topic:string|has_main_switch:boolean|daily_report:boolean|send_changed_node_numbers:boolean ++|rvo_senica_42_ip118|en|28.1EF4940E0000|48.70826502|17.28455203|192.168.252.1|rvo_senica_42_ip118|QMvF7etEvbYMMr8Q6baP|1883|0|59|unipi|ttyUSB0|1|20|5|6|3|u118|0|1|1|................................................... diff --git a/RVO42/databases/tbdata.nosql b/RVO42/databases/tbdata.nosql new file mode 100755 index 0000000..b26f0bf --- /dev/null +++ b/RVO42/databases/tbdata.nosql @@ -0,0 +1,4 @@ +-"g9OxBZ5KRwNznlY6pAppGEAWXvjdEL4eGQobMDy2":[{"ts":1760521818496,"values":{"_event":{"type":"notice","status":"new","source":{"func":"modbus_reader","component":"1699965957410","component_name":"Modbus reader","edge":"g9OxBZ5KRwNznlY6pAppGEAWXvjdEL4eGQobMDy2"},"message":{"sk":"rvo_senica_42_ip118: FLOW bol reštartovaný","en":"rvo_senica_42_ip118: FLOW has been restarted"},"message_data":""}}}],"id":"3000170001mp71b"} +-"g9OxBZ5KRwNznlY6pAppGEAWXvjdEL4eGQobMDy2":[{"ts":1760521818572,"values":{"edge_fw_version":"2025-10-08","maintenance_mode":false}}],"id":"3000170002mp70b"} +-"g9OxBZ5KRwNznlY6pAppGEAWXvjdEL4eGQobMDy2":[{"ts":1760521818585,"values":{"statecode":2,"power_mode":"Automatic"}}],"id":"3000170004mp70b"} +-"g9OxBZ5KRwNznlY6pAppGEAWXvjdEL4eGQobMDy2":[{"ts":1760521818620,"values":{"_event":{"type":"notice","status":"new","source":{"func":"rsPort.open()","component":"1699963668903","component_name":"DIDO_Controller","edge":"g9OxBZ5KRwNznlY6pAppGEAWXvjdEL4eGQobMDy2"},"message":{"sk":"rvo_senica_42_ip118: FLOW bol spustený","en":"rvo_senica_42_ip118: FLOW has been started "},"message_data":""}}}],"id":"3000170006mp70b"} diff --git a/RVO42/databases/tbdatacloud.nosql b/RVO42/databases/tbdatacloud.nosql new file mode 100755 index 0000000..9415583 --- /dev/null +++ b/RVO42/databases/tbdatacloud.nosql @@ -0,0 +1,3 @@ +-"g9OxBZ5KRwNznlY6pAppGEAWXvjdEL4eGQobMDy2":[{"ts":1760521818572,"values":{"edge_fw_version":"2025-10-08","maintenance_mode":false}}],"id":"3000170003mp71b"} +-"g9OxBZ5KRwNznlY6pAppGEAWXvjdEL4eGQobMDy2":[{"ts":1760521818585,"values":{"statecode":2,"power_mode":"Automatic"}}],"id":"3000170005mp71b"} +-"g9OxBZ5KRwNznlY6pAppGEAWXvjdEL4eGQobMDy2":[{"ts":1760521818620,"values":{"_event":{"type":"notice","status":"new","source":{"func":"rsPort.open()","component":"1699963668903","component_name":"DIDO_Controller","edge":"g9OxBZ5KRwNznlY6pAppGEAWXvjdEL4eGQobMDy2"},"message":{"sk":"rvo_senica_42_ip118: FLOW bol spustený","en":"rvo_senica_42_ip118: FLOW has been started "},"message_data":""}}}],"id":"3000170007mp71b"} diff --git a/RVO42/databases/total_energy.js b/RVO42/databases/total_energy.js new file mode 100755 index 0000000..dde340e --- /dev/null +++ b/RVO42/databases/total_energy.js @@ -0,0 +1,38 @@ +//key is rvo_number, value is max energy when lamps are on +const total_energy = { + 1: 580, + 2: 1100, + 3: 3700, + 4: 4100, + 7: 360, + 12: 1700, + 13: 5400, + 14: 440, + 15: 6100, + 16: 4800, + 20: 1600, + 21: 1000, + 22: 2600, + 23: 1000, + 25: 2600, + 33: 240, + 34: 4000, + 35: 2700, + 36: 820, + 37: 1400, + 35: 3500, + 39: 1170, + 41: 740, + 42: 660, + 43: 4900, + 45: 930, + 46: 700, + 47: 1100, + 48: 1500, + 50: 3200, + 53: 1250, + 55: 1000, + 56: 5500 +} + +module.exports = total_energy; diff --git a/RVO42/debug.js b/RVO42/debug.js new file mode 100755 index 0000000..9818194 --- /dev/null +++ b/RVO42/debug.js @@ -0,0 +1,16 @@ +// =================================================== +// FOR DEVELOPMENT +// Total.js - framework for Node.js platform +// https://www.totaljs.com +// =================================================== + +const options = {}; + +// options.ip = '127.0.0.1'; +// options.port = parseInt(process.argv[2]); +// options.config = { name: 'Total.js' }; +// options.sleep = 3000; +// options.inspector = 9229; +// options.watch = ['private']; + +require('total.js/debug')(options); \ No newline at end of file diff --git a/RVO42/err.txt b/RVO42/err.txt new file mode 100755 index 0000000..c4025f0 --- /dev/null +++ b/RVO42/err.txt @@ -0,0 +1,77 @@ +[2024-10-25T21:49:41.604] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-25T22:50:18.878] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-25T23:51:15.567] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T00:52:04.502] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T01:52:45.665] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T02:53:48.159] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T03:54:28.378] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T04:55:21.180] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T05:56:17.872] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T06:57:33.941] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T07:58:18.997] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T08:59:09.825] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T10:00:27.840] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T11:01:07.021] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T12:01:55.946] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T13:02:54.576] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T14:04:02.881] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T15:05:05.422] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T16:06:07.934] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T17:07:08.498] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T18:07:49.706] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T19:08:34.770] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T20:09:33.398] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T21:10:14.565] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T22:11:03.473] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T23:12:02.128] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T00:12:39.438] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T01:13:28.369] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T02:14:25.101] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T02:15:15.977] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T03:16:26.267] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T04:17:29.821] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T05:18:20.739] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T06:19:09.695] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T07:19:52.778] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T08:20:39.725] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T09:21:32.519] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T10:22:21.440] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T11:23:18.091] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T12:24:08.923] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T13:25:25.014] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T14:26:46.939] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T15:27:47.501] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-12-08T10:56:10.414] [ERROR] errLogs - Thermometer Thermometer: temperatureAddress is not defined +[2025-09-23T14:04:38.431] [ERROR] errLogs - uncaughtException: Cannot read property 'getHours' of undefined +[2025-09-23T14:04:38.432] [ERROR] errLogs - TypeError: Cannot read property 'getHours' of undefined + at Timeout.emptyReportToSend [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:04:38.433] [ERROR] errLogs - uncaughtException: Cannot read property 'getHours' of undefined +[2025-09-23T14:04:38.434] [ERROR] errLogs - TypeError: Cannot read property 'getHours' of undefined + at Timeout.emptyReportToSend [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:04:38.448] [ERROR] errLogs - uncaughtException: Cannot read property 'getHours' of undefined +[2025-09-23T14:04:38.449] [ERROR] errLogs - TypeError: Cannot read property 'getHours' of undefined + at Timeout.emptyReportToSend [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:04:44.468] [ERROR] errLogs - uncaughtException: date.getHours is not a function +[2025-09-23T14:04:44.469] [ERROR] errLogs - TypeError: date.getHours is not a function + at emptyReportToSend (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at Timeout.dailyReportCheck [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1351:5) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:04:44.469] [ERROR] errLogs - uncaughtException: date.getHours is not a function +[2025-09-23T14:04:44.470] [ERROR] errLogs - TypeError: date.getHours is not a function + at emptyReportToSend (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at Timeout.dailyReportCheck [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1351:5) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:04:44.475] [ERROR] errLogs - uncaughtException: date.getHours is not a function +[2025-09-23T14:04:44.475] [ERROR] errLogs - TypeError: date.getHours is not a function + at emptyReportToSend (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at Timeout.dailyReportCheck [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1351:5) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) diff --git a/RVO42/flow/audit_test_panel.csv b/RVO42/flow/audit_test_panel.csv new file mode 100755 index 0000000..907a6a9 --- /dev/null +++ b/RVO42/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/RVO42/flow/cloudmqttconnect.js b/RVO42/flow/cloudmqttconnect.js new file mode 100755 index 0000000..b03491f --- /dev/null +++ b/RVO42/flow/cloudmqttconnect.js @@ -0,0 +1,357 @@ +exports.id = 'cloudmqttconnect'; +exports.title = 'Cloud connect mqtt'; +exports.group = 'MQTT'; +exports.color = '#888600'; +exports.version = '1.0.2'; +exports.icon = 'sign-out'; +exports.input = 2; +exports.output = 2; +exports.options = { host: 'tb-stage.worksys.io', port: 1883, clientid: "", username: "" }; + +exports.html = `
+
+
+
Hostname or IP address (if not empty - setting will override db setting)
+
+
+
Port
+
+
+
+
+
@(Client id)
+
+
+
topic
+
+
+
`; + + + +const { promisifyBuilder } = require('./helper/db_helper'); +const fs = require('fs'); +const mqtt = require('mqtt'); +const nosql = NOSQL('tbdatacloud'); + +const SEND_TO = { + debug: 0, + rpcCall: 1, +} + +//CONFIG +let saveTelemetryOnError = true;//backup_on_failure overrides this value +//------------------------ + +const noSqlFileSizeLimit = 4194304;//use 5MB - 4194304 +let insertNoSqlCounter = 0; +let insertBackupNoSqlCounter = 0; +let processingData = false; + +let backup_on_failure = true;//== saveTelemetryOnError - create backup client send failure +let restore_from_backup = 50; //how many rows process at once? +let restore_backup_wait = 3;//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; + + +exports.install = function(instance) { + + var client; + var opts; + var clientReady = false; + + let o = {}; //options + + function main() { + loadSettings(); + } + + //set opts according to db settings + function loadSettings() { + + o = instance.options; + if (!o.topic) o.topic = FLOW.GLOBALS.settings.cloud_topic; + + opts = { + host: o.host, + port: o.port, + clientId: o.clientid, + username: o.username, + rejectUnauthorized: false, + resubscribe: false + }; + + console.log("wsmqttpublich -> loadSettings from instance.options", o); + + if (!o.topic) { + instance.status("Not configured", "white"); + console.log("Cloud mqtt connect: no topic selected"); + return; + } + + connectToTbServer(); + } + + function connectToTbServer() { + var url = "mqtt://" + opts.host + ":" + opts.port; + console.log("MQTT URL: ", url); + + client = mqtt.connect(url, opts); + + client.on('connect', function() { + client.subscribe(`${o.topic}_backward`, (err) => { + if (!err) { + console.log("MQTT subscribed"); + } + }); + instance.status("Connected", "green"); + clientReady = true; + sendClientError = true; + }); + + client.on('reconnect', function() { + instance.status("Reconnecting", "yellow"); + clientReady = false; + }); + + client.on('message', function(topic, message) { + // message is type of buffer + message = message.toString(); + if (message[0] === '{') { + TRY(function() { + + message = JSON.parse(message); + if (message.hasOwnProperty("device") && message.hasOwnProperty("data") && message.data.hasOwnProperty("id")) { + client.publish(`${o.topic}_forward`, `{"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 } }); + } + + }, () => instance.debug('MQTT: Error parsing data', message)); + } + + instance.send(SEND_TO.rpcCall, { "topic": o.topic, "content": message }); + }); + + client.on('close', function() { + clientReady = false; + + instance.status("Disconnected", "red"); + instance.send(SEND_TO.debug, { "message": "Client CLOSE signal received !" }); + }); + + client.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) { + console.log('MQTT client error', err); + sendClientError = false; + } + clientReady = false; + }); + + } + + + instance.on('0', function(data) { + + if (clientReady) { + //do we have some data in backup file? if any, process data from database + if (saveTelemetryOnError) { + //read telemetry data and send back to server + if (!processingData) processDataFromDatabase(); + } + + let stringifiedJson = JSON.stringify(data.data) + client.publish(`${o.topic}_forward`, stringifiedJson, { qos: 1 }); + } + 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 (saveTelemetryOnError && o.topic) { + //create new file from tbdata.nosql, if file size exceeds given limit, and clear tbdata.nosql + makeBackupFromDbFile(); + + //write to tb + data.data.id = UID(); + nosql.insert(data.data); + } + } + }); + + instance.on("1", _ => { + main(); + }) + + instance.close = function(done) { + if (clientReady) { + client.end(); + } + }; + + + function getDbBackupFileCounter(type) { + var files = fs.readdirSync(__dirname + "/../databases"); + + let counter = 0; + for (var i = 0; i < files.length; i++) { + + if (files[i] == "tbdatacloud.nosql") continue; + + if (files[i].endsWith(".nosql")) { + + let pos = files[i].indexOf("."); + if (pos > -1) { + + let fileCounter = counter; + let firstDigit = files[i].slice(0, pos); + + fileCounter = parseInt(firstDigit); + if (isNaN(fileCounter)) fileCounter = 0; + //console.log("getDbBackupFileCounter digit:", files[i], firstDigit, fileCounter, isNaN(fileCounter), type); + + if (type == "max") { + if (fileCounter > counter) { + counter = fileCounter; + } + } + else if (type == "min") { + if (counter == 0) counter = fileCounter; + + if (fileCounter < counter) { + counter = fileCounter; + } + } + } + } + + } + + if (type == "max") counter++; + + return counter; + } + + const makeBackupFromDbFile = async () => { + + if (!saveTelemetryOnError) return; + + //to avoid large file: tbdata.nosql + + //init value is 0! + if (insertNoSqlCounter > 0) { + --insertNoSqlCounter; + return; + } + + insertNoSqlCounter = 100; + + let source = __dirname + "/../databases/tbdatacloud.nosql"; + + var stats = fs.statSync(source); + var fileSizeInBytes = stats.size; + + if (fileSizeInBytes > noSqlFileSizeLimit) { + + let counter = 1; + counter = getDbBackupFileCounter("max"); + + let destination = __dirname + "/../databases/" + counter + "." + "tbdatacloud.nosql"; + + //make backup file + fs.copyFileSync(source, destination); + //fs.renameSync(p, p + "." + counter); + + //clear tbdata.nosql + fs.writeFileSync(source, ""); + fs.truncateSync(source, 0); + + } + } + + const processDataFromDatabase = async () => { + + if (restore_from_backup <= 0) return; + + //calculate diff + const now = new Date(); + let currentTime = now.getTime(); + let diff = currentTime - lastRestoreTime; + + if ((diff / 1000) < restore_backup_wait) { + //console.log("*********restore_backup_wait", diff, restore_backup_wait); + return; + } + + processingData = true; + + //get filename to process + let counter = getDbBackupFileCounter("min"); + + //we have some backup files + let dataBase = 'tbdata'; + + var nosql; + if (counter == 0) dataBase = 'tbdatacloud'; + else dataBase = counter + "." + 'tbdatacloud'; + + nosql = NOSQL(dataBase); + + //select all data - use limit restore_from_backup + let records = await promisifyBuilder(nosql.find().take(restore_from_backup)); + + for (let i = 0; i < records.length; i++) { + if (clientReady) { + + let item = records[i]; + let id = item.id; + + if (id !== undefined) { + //console.log("------------processDataFromDatabase - remove", id, dataBase, i); + + try { + + let message = JSON.parse(JSON.stringify(item)); + delete message.id; + client.publish(`${o.topic}_forward`, JSON.stringify(message), { qos: 1 }); + + //remove from database + await promisifyBuilder(nosql.remove().where("id", id)); + + } catch (error) { + //process error + console.log("processDataFromDatabase", error); + } + + } + + } + else { + processingData = false; + return; + } + } + + if (records.length > 0) { + //clean backup file + if (counter > 0) nosql.clean(); + } + + //no data in db, remove + if (records.length == 0) { + if (counter > 0) nosql.drop(); + } + + const d = new Date(); + lastRestoreTime = d.getTime(); + + processingData = false; + + } + + instance.on('options', main); + +}; diff --git a/RVO42/flow/cmd_manager.js b/RVO42/flow/cmd_manager.js new file mode 100755 index 0000000..25912df --- /dev/null +++ b/RVO42/flow/cmd_manager.js @@ -0,0 +1,3071 @@ +exports.id = 'cmd_manager'; +exports.title = 'CMD Manager'; +exports.group = 'Worksys'; +exports.color = '#5D9CEC'; +exports.version = '0.0.3'; +exports.output = ['red', 'blue', 'yellow', 'blue', 'white', 'green']; +exports.input = 3; +exports.icon = 'cloud-upload'; + +exports.html = ` +
+
+
+
RPC - run RPC calls

+
+
+
@(User)
+
+
+
@(Password)
+
+
+
@(My edge)
+
+
+
+`; +exports.readme = `Manager for CMD calls`; + + +exports.install = function(instance) { + + 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, isEmptyObject, emptyJsObject, writeToFile, addToArrayIfUnique } = require('./helper/utils'); + const bitwise = require('bitwise'); + + var SunCalc = require('./helper/suncalc'); + const DataToTbHandler = require('./helper/DataToTbHandler'); + const errorHandler = require('./helper/ErrorToServiceHandler'); + const { sendNotification } = require('./helper/notification_reporter'); + const process = require('process'); + const { errLogger, logger, monitor } = require('./helper/logger'); + + //for accelerometer purposes + const { naklony } = require("../databases/accelerometer_db"); + + const dbNodes = TABLE("nodes"); + const dbRelays = TABLE("relays"); + + let GLOBALS; + let SETTINGS; + let rsPort; + let tbHandler; + + // runTasks intervals + const SHORT_INTERVAL = 30; + const LONG_INTERVAL = 300; + + //send data to following instances: + const SEND_TO = { + debug: 0, + tb: 1, + http_response: 2, + dido_controller: 3, + infoSender: 4, + dailyReport: 5 + } + + 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 + } + + 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 sendNodeReadout = null; // interval for sending agregate data from node + + 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["1"] = minutes; // dimming + priorities["76"] = minutes; // power + + minutes = 5; + priorities["75"] = minutes; // current + priorities["79"] = minutes; // energy + priorities["87"] = minutes; // aktualny cas + //priorities["84"] = minutes; //accelerometer + + minutes = 10; + priorities["74"] = minutes; // voltage + priorities["77"] = minutes; // power factor + priorities["78"] = minutes; // frequency + + minutes = 60; + priorities["0"] = minutes; // statecode + priorities["6"] = minutes; // dusk + priorities["7"] = minutes; // dawn + priorities["8"] = minutes; // profile + + minutes = 60 * 24; + priorities["89"] = minutes; // verzia fw + priorities["80"] = minutes; // lifetime + + //prikazy kt sa budu spustat na dany node - see config.js in terminal-oms.app. (1 - dimming) + let listOfCommands = [0, 1, 6, 7, 8, 74, 75, 76, 77, 78, 79, 80, 87, 89]; + + 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; + + // holds dusk, dawn (and more) values + let sunCalcResult; + + //helper container for counting resolved group of commands (commands related to set profile) + let cmdCounter = {};//key is node, value is counter + + //TODO: is this set working?? According to previous checks, sets do not work + //if sending of profile to node fails, we send notification and push node into set, so we do not send notification twice + const nodeProfileSendFail = new Set(); + + //we expect to get current temperature in Senica from senica-prod01 + let temperatureInSenica = null; + let accelerometerInterval = null; + + //NOTE: daily reports senica: + //rvo_is_on status, we monitor all nodes - if true, power and dimming should be not 0, if false, 24/7 nodes should be 0, other rvo should not respond + let rvo_is_on; + let previous_rvo_is_on_value; + let handleDailyReport; //setInterval for dailyReportHandler function + let dailyReport = {}; //data needed for daily report + let reportToSend = {}; //final report which we send to cloud + let breakerCounter = null; // status of breakers after flow starts is not in report + let rvoPeriod; // interval of checking dusk dawn and if rvo_is_on + let initialReportStatus = false; + + const DAILY_REPORT_HANDLER_TIME = 3_600_000; + const SET_SUNCALC_RESULT_TIME = 3_600_000; + const SET_RVO_PERIOD_TIME = 300_000; + const ADD_NODE_TO_REPORT_TIME = 3_600_000; + + //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); + + let now = new Date(); + console.log("Cmd-mngr installed", now.toLocaleString("sk-SK")); + + sunCalcResult = calculateDuskDawn(); + + handleRsPort(); + + customTasksInterval = setInterval(reportEdgeDateTimeAndNumberOfLuminaires, 120_000); + setTimeout(reportEdgeDateTimeAndNumberOfLuminaires, 4000); + + //dailyReport related + emptyReportToSend(); + breakerCounter = Object.keys(relaysData).length - 1; // we get number of lines (breakers) except of line 0 + rvoPeriod = setInterval(setRvoPeriod, SET_RVO_PERIOD_TIME); + setTimeout(setRvoPeriod, 3000); + setInterval(setSunCalcResult, SET_SUNCALC_RESULT_TIME); + handleDailyReport = setInterval(dailyReportHandler, DAILY_REPORT_HANDLER_TIME); + + + setCorrectTime = setInterval(setCorrectPlcTimeOnceADay, 60000 * 60); // 1 hour + setCorrectPlcTimeOnceADay(); + + sendNodeReadout = setInterval(sendNodesData, 150_000); + accelerometerInterval = setInterval(accelerometerData, 60000 * 30); //30 min + } + + + 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" + //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 + // if node regular readout does not respond, we repeat request + params.repeatCounter = 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-mngr: 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.byte4 = 96; + params.recipient = 1; + params.register = 8; + params.rw = 1;//write + params.timestamp = timestamp; + 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.byte4 = 96; + params.recipient = 1; + params.register = 8; + params.rw = 1;//write + params.timestamp = timestamp; + 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). + */ + + 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.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.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 + { + + logger.debug("processNodeProfile: Threshold lux level for DUSK/DAWN", node); + + let params = getParams(); + params.type = "set_node_profile"; + params.address = node; + params.register = 96; + params.recipient = 1; + params.rw = 1;//write + params.timestamp = timestamp; + 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(); + params.type = "set_node_profile"; + params.address = node; + params.register = 97; + params.recipient = 1; + params.rw = 1;//write + params.timestamp = timestamp; + 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.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); + + 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); + + console.log("proces profile finished *********************") + } + + + 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; + }); + } + + + 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) { + for (let k in nodesData) { + 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`); + } + } + } + + + function loadRelaysData(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 (value.contactor == 1) processAllNodeProfilesOnLine(value.line); + } + } + + + function reportOnlineNodeStatus(line) { + //Po zapnutí línie broadcastovo aktualizovať predtým čas a o 3 sek neskor - status, brightness + + logger.debug("Cmd-mngr: ----->reportOnlineNodeStatus for line", line); + + const d = new Date(); + + // broadcast actual time + let params = getParams(); + params.address = 0xffffffff;//Broadcast + params.byte1 = d.getHours(); + params.byte2 = d.getMinutes(); + params.recipient = 2;//2 broadcast, address = 0 + params.register = 87;//Actual time + params.rw = 1;//write + params.type = "node-onetime-write"; + params.timestamp = d.getTime() + 30000; + params.info = "run broadcast: Actual time"; + //params.debug = true; + + tasks.push(params); + + let sec = 3; + setTimeout(function() { + //Po zapnutí línie - spraviť hromadný refresh stavu práve zapnutých svietidiel + + let time = Date.now(); + + for (let k in nodesData) { + + //potrebujem nody k danej linii + 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].node_status_before_offline === true || nodesData[k].status === true) { + status = "OK"; + nodesData[k].time_of_last_communication = time; + } + + nodesData[k].readout.status = status; + + updateNodeStatus(k, status === "OK" ? true : false); + if (nodesData[k].hasOwnProperty("node_status_before_offline")) delete nodesData[k].node_status_before_offline; + sendTelemetry({ status: status }, tbname, time); + + //vyreportovanie dimming, current, input power pre liniu pre vsetky nody + //Prud + { + let params = getParams(); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 75;//prud + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = time + 4000; + params.info = 'read current'; + //params.debug = true; + tasks.push(params); + } + + //vykon + { + let params = getParams(); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 76;//výkon + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = time + 4100; + params.info = 'read power'; + //params.debug = true; + + tasks.push(params); + } + //dimming + { + let params = getParams(); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 1;//dimming + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = time + 4200; + params.info = 'read dimming'; + //params.debug = true; + + tasks.push(params); + } + + } + } + + }, sec * 1000); + } + + + function reportOfflineNodeStatus(line) { + + logger.info("Cmd-mngr: ------>reportOffLineNodeStatus for line ", line); + + values = {}; + values["dimming"] = 0;//brightness + values["power"] = 0;//výkon + values["current"] = 0;//prúd + values["status"] = "OFFLINE"; + + const date = Date.now(); + + Object.keys(nodesData).forEach(node => { + + //potrebujem nody k danej linii + if (line == nodesData[node].line || line == undefined) { + + let tbname = nodesData[node].tbname; + let nodeStatus = nodesData[node].status; + + //in case we have reported offline node status, we return (continue with next node) + if (nodeStatus === "OFFLINE") return; + + nodesData[node].node_status_before_offline = nodeStatus; + nodesData[node].status = "OFFLINE"; + nodesData[node].readout = {}; + + sendTelemetry({ ...values }, tbname, date); + } + }); + + } + + + function turnLine(onOrOff, line, info) { + let obj = { + line: line, + command: onOrOff, + info: info + }; + + //to assure, handleDailyReportFunction do not run before rvo_is_on variable changes. So after every line switch we reset the timer + clearInterval(handleDailyReport); + handleDailyReport = setInterval(dailyReportHandler, DAILY_REPORT_HANDLER_TIME); + + //logger.debug("linia", line, obj); + instance.send(SEND_TO.dido_controller, obj); + } + + + 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"; + 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]) { + //CRC_ERROR + message = "NOK"; + error = "CRC_ERROR c1"; + instance.send(SEND_TO.debug, "CRC_ERROR c1"); + } + + 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") { + instance.send(SEND_TO.debug, bytes); + instance.send(SEND_TO.debug, "RESPONSE " + type + " - " + bytes[4]); + + //logger.debug(SEND_TO.debug, "RESPONSE " + type + " - " + bytes[4], bytes); + + error = "type is: " + type; + + message = "NOK"; + } + + return { message, type, error }; + } + + + //BUILD TASKS// + function buildTasks(params) { + + //return; + console.log("buidTAaasks start ****************", params); + monitor.info("buildTasks - params", params); + + let processLine; //defined line + let init = false; + let processLineProfiles = true; + let processBroadcast = true; + let processNodes = true; + + if (params == undefined) { + init = true; + tasks = []; + logger.debug("-->buildTasks clear tasks"); + } + else { + processLineProfiles = params.processLineProfiles; + processBroadcast = false; + processNodes = false; + + processLine = params.line; + } + + let now = new Date(); + + //process line profiles + if (processLineProfiles) { + + let keys = Object.keys(relaysData); + + for (let i = 0; i < keys.length; i++) { + + let line = parseInt(keys[i]); + let profilestr = relaysData[line].profile; + + if (processLine != undefined) { + if (processLine != line) continue; + } + + try { + + /** + * we process line profiles: timepoints, astro clock, lux_sensor, offsets ... + */ + if (profilestr === "") throw ("Profile is not defined"); + let profile = JSON.parse(profilestr); + 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; + + // add name to regular profile timepoint and delete unused end_time key: + time_points.forEach(point => { + point.name = "profileTimepoint" + delete point.end_time; + }); + + //monitor.info("buildTasks: time_points", time_points); + + + /** + * 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 astro clock true, we remove all regular profile points + time_points = []; + + //TODO: when astro clock == true, is offset calculated ??? + //let duskAstroClockOffset = profile.dusk_astro_clock_offset; + //let dawnAstroClockOffset = profile.dawn_astro_clock_offset; + //console.log("line astro clock offsets dusk a dawn: ", duskAstroClockOffset, dawnAstroClockOffset); + // maybe add dusk dawn offset to calculateDuskDawn ?? what dusk dawn will be if dawn_lux_sensor == true?? + //let sunCalcResult = calculateDuskDawn(new Date(), line, duskAstroClockOffset, dawnAstroClockOffset); + + 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 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); + + 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); + + 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(':'); + + let ad = new Date(); + ad.setHours(parseInt(ahours), parseInt(aminutes), 0); + + let bd = new Date(); + bd.setHours(parseInt(bhours), parseInt(bminutes), 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++) { + + let start_time = new Date(); + let [hours, minutes] = time_points[t].start_time.split(':'); + start_time.setHours(parseInt(hours), parseInt(minutes), 0); + + //task is in 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(); + params.type = "relay"; + params.line = parseInt(line); + params.value = time_points[t].value; + params.tbname = relaysData[line].tbname; + params.timestamp = start_time.getTime(); + + // 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; + + //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)) { + 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; + + params.debug = true; + + //turn on/off line + tasks.push(params); + monitor.info("TimePoint params: ", params.info, start_time); + } + + monitor.info("-->time_points final", line, time_points); + + //ensure to turn on/off according to calculated currentValue + let params = getParams(); + params.type = "relay"; + params.line = parseInt(line); + params.tbname = relaysData[line].tbname; + params.value = currentValue; + params.timestamp = i; + params.debug = true; + + //logger.debug(now.toLocaleString("sk-SK")); + 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; + + tasks.push(params); + + } catch (error) { + if (profilestr !== "") { + //errLogger.error(profilestr, error); + console.log(`Cmd_mngr: Unable to process line profile ${line}. Error: `, error); + errorHandler.sendMessageToService(profilestr + "-" + error, 0, "js_error"); + } else { + turnLine("off", line, "No line profile. Switching it off on startup"); + } + } + + } + //logger.debug("tasks:"); + //logger.debug(tasks); + } + + + //NOTE: PROCESS DEFAULT BROADCASTS - Time of dusk, Time of dawn, Actual Time + if (processBroadcast) { + + let d = new Date(); + let time = d.getTime(); + //let sunCalcResult = calculateDuskDawn(); + + { + let params = getParams(); + + params.address = 0xffffffff;//broadcast + params.byte1 = sunCalcResult["dusk_hours"]; + params.byte2 = sunCalcResult["dusk_minutes"]; + params.recipient = 2;//2 broadcast, + params.register = 6;//Time of dusk + params.rw = 1;//write + params.type = "node-regular-write"; + params.timestamp = time + 60000; + params.addMinutesToTimestamp = 60 * 3; //kazde 3 hodiny zisti novy dusk + params.info = "Broadcast-duskTime"; + + tasks.push(params); + } + + { + let params = getParams(); + + params.address = 0xffffffff;//broadcast + params.byte1 = sunCalcResult["dawn_hours"]; + params.byte2 = sunCalcResult["dawn_minutes"]; + params.recipient = 2; //2 broadcast + params.register = 7;//Time of dawn + params.rw = 1;//write + params.type = "node-regular-write"; + params.timestamp = time + 60001; + params.addMinutesToTimestamp = 60 * 3; //kazde 3 hodiny zisti novy dawn + params.info = "Broadcast-dawnTime"; + + tasks.push(params); + } + + { + let params = getParams(); + + params.address = 0xffffffff;//broadcast + params.byte1 = d.getHours(); + params.byte2 = d.getMinutes(); + params.recipient = 2; //2 broadcast + params.register = 87;//Actual time + params.rw = 1;//write + params.type = "node-regular-write"; + params.timestamp = time + 60002; + params.addMinutesToTimestamp = 5; + params.info = "run broadcast: Actual time"; + + tasks.push(params); + } + + } + + //process nodes & tasks - read node's data + if (processNodes) { + + let time = Date.now(); + + for (let k in nodesData) { + let address = parseInt(k); + let tbname = nodesData[k].tbname; + let register = 0; + + for (let i = 0; i < listOfCommands.length; i++) { + + register = listOfCommands[i]; + let addMinutesToTimestamp = priorities[register]; + + let params = getParams(); + + params.address = address; + params.recipient = 1; + params.register = register; + params.type = register == 1 ? "node-dimming-read" : "node-regular-read"; + params.tbname = tbname; + params.timestamp = time + 5000 + i * 500 + addMinutesToTimestamp * 1000; //to make slight time difference + params.addMinutesToTimestamp = addMinutesToTimestamp; + params.info = "Node regular read command"; + + tasks.push(params); + } + + } + } + + + //niektore ulohy sa vygeneruju iba 1x pri starte!!! + if (!init) return; + + + //Master node FW version - modifies SETTINGS.masterNodeIsResponding + { + let params = getParams(); + params.type = "cmd-master"; + params.register = 4; + params.address = 0; + params.timestamp = 0; + params.addMinutesToTimestamp = 5; + params.tbname = SETTINGS.rvoTbName; + params.info = "Master node FW verzia"; + //params.debug = true; + + tasks.push(params); + } + + //kazdu hodinu skontrolovat nastavenie profilov + { + let params = getParams(); + params.type = "process_profiles"; + params.timestamp = Date.now() + 60001; + params.addMinutesToTimestamp = 60;//60 = every hour + params.info = "detekcia nespracovaných profilov linie a nodov"; + //params.debug = true; + + tasks.push(params); + } + + monitor.info("tasks created:", tasks.length); + } + + + /** + * We process line profile, where "astro_clock": true + * example profile: + * + "dawn_lux_sensor": true, + "dusk_lux_sensor": true, + "dawn_lux_sensor_value": 5, + "dusk_lux_sensor_value": 5, + "dawn_astro_clock_offset": 0, + "dusk_astro_clock_offset": 10, + "dawn_lux_sensor_time_window": 30, + "dusk_lux_sensor_time_window": 30, + "dawn_astro_clock_time_window": 60, + "dusk_astro_clock_time_window": 60 + + * if dawn: if currentTimestamp is in timewindow "dawnTime + and - dawn_lux_sensor_time_window" and lux value >= lux_sensor_value, we switch off the line. + * if dusk: we do oposite + * + * dawn: usvit - lux je nad hranicou - vypnem + * dusk: sumrak - lux je pod hranicou - zapnem + */ + 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++) { + + let line = keys[i]; //line is turned off by default + let profilestr = relaysData[line].profile; + const contactor = relaysData[line].contactor; + + try { + + let profile = JSON.parse(profilestr); + if (Object.keys(profile).length === 0) throw ("turnOnOffLinesAccordingToLuxSensor - profile is not defined"); + + 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 (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"); + } + } + } + + //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 (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"); + } + } + } + + } + + } catch (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) { + //MASTER + if (node == 0) return; + + let nodeObj = nodesData[node]; + if (nodeObj == undefined) return; + + let nodeCurrentStatus = nodeObj.status; + const now = Date.now(); + + let data = null; + + if (nodeCurrentStatus === "OFFLINE") { + data = { status: newStatus }; + nodeDbStatusModify(node, data); + return; + } + else 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; + } + + } + + + 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 }; + } + }); + }); + } + + + function processDailyReport() { + + const now = Date.now(); + + for (const [key, value] of Object.entries(dailyReport)) { + + if (["name", "time", "dusk_and_dawn"].includes(key)) continue; + + let poleNumber = nodesData[key]["pole_number"]; + let line = dailyReport[key].line; + let nodeType = nodesData[key]["node_type"]; + let fullNodeName = key // key == nodeNumber + + if (poleNumber && nodeType) { + fullNodeName = SETTINGS.rvo_number + "/" + poleNumber + "_" + line + "L_" + key + "_" + nodeType; + } else { + fullNodeName = key; + } + + if (rvo_is_on) { + + if (value.initialTs) { + if (value.initialTs + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["night_no_data"], fullNodeName); + console.log('report nedostava ziadne data uz hodinu', fullNodeName); + value.initialTs = now; + } + } + if (value.dimmingIsZeroTime) { + if (value.dimmingIsZeroTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["night_dimming=0"], fullNodeName); + console.log("report node dimming je 0 ale ma svietit", fullNodeName); + value.dimmingIsZeroTime = now; + } + } + if (value.powerIsZeroTime) { + if (value.powerIsZeroTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["night_power=0"], fullNodeName); + console.log("report node power je 0 ale ma svietit", fullNodeName); + value.powerIsZeroTime = now; + } + } + + } else { + + let contactorStatus = relaysData[line].contactor; + if (contactorStatus === 1) { + + if (value.initialTs) { + if (value.initialTs + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["day_24/7_no_data"], fullNodeName); + console.log('node je na 24/7 ale nedostava ziadne data uz hodinu', fullNodeName); + value.initialTs = now; + } + } + if (value.dimmingIsOnButShouldBeOffTime) { + if (value.dimmingIsOnButShouldBeOffTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["day_24/7_dimming>0"], fullNodeName); + console.log("report dimming je > 0 ale nema svietit", fullNodeName); + value.dimmingIsOnButShouldBeOffTime = now; + } + } + if (value.powerIsOnButShouldBeOffTime) { + if (value.powerIsOnButShouldBeOffTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["day_24/7_power>0"], fullNodeName); + console.log("report power je > 0 ale nema svietit", fullNodeName); + value.powerIsOnButShouldBeOffTime = now; + } + } + + } + + } + + } + + let report = {}; + report["name"] = SETTINGS.rvo_name; + report["time"] = new Date(); + report["report"] = reportToSend; + + writeToFile(F.path.root("report_data.log"), report, true); + instance.send(SEND_TO.dailyReport, report); + } + + + function dailyReportHandler() { + + if (!SETTINGS.daily_report) return; + + // after dawn we empty reportToSend and start to get data for a new day + const date = new Date(); + const hour = date.getHours(); + const minute = date.getMinutes(); + + console.log("now: ", hour, minute, "suncalc: ", sunCalcResult.dawn_hours, sunCalcResult.dawn_minutes); + + if (hour === sunCalcResult.dawn_hours) { + + //NOTE: ak je este pred usvitom, spracujeme report a posleme na cloud, ak uz je po usvite, resetujeme report plnime data noveho dna + if (minute >= sunCalcResult.dawn_minutes - 2) { + emptyReportToSend(); + emptyDailyReport(); + console.log("Podmienka 1 v dailyReport handler"); + } else { + processDailyReport(); + emptyReportToSend(); + emptyDailyReport(); + console.log("Podmienka 2 v dailyReport handler"); + } + + initialReportStatus = true; + + // ak sa funkcia spusti o hodinu alebo 2 neskor, ako je usvit (moze sa to stat, kedze kazde zapnutie/vypnutie linii odznova spusti casovac. + } else if (hour === sunCalcResult.dawn_hours + 1 || hour === sunCalcResult.dawn_hours + 2) { + if (!initialReportStatus) { + emptyReportToSend(); + emptyDailyReport(); + initialReportStatus = true; + console.log("Podmienka 3 v dailyReport handler"); + } else { + processDailyReport(); + initialReportStatus = true; + console.log("Podmienka 4 v dailyReport handler"); + } + } else { + processDailyReport(); + initialReportStatus = false; + console.log("Podmienka 5 v dailyReport handler"); + } + + console.log("initialReportStatus: ", initialReportStatus); + + } + + function emptyReportToSend() { + emptyJsObject(reportToSend); + reportToSend["contactor"] = { off: [], on: [] }; + reportToSend["night_no_data"] = []; + reportToSend["night_dimming=0"] = []; + reportToSend["night_power=0"] = []; + reportToSend["day_24/7_no_data"] = []; + reportToSend["day_24/7_dimming>0"] = []; + reportToSend["day_24/7_power>0"] = []; + console.log(`resetuje sa reportToSend`); + } + + + //NOTE: ked je initialTs stale rovnaky a zistime ze linie su vypnute (relaysData.line.contactor) - zistim, ci je node na tej linii. Vieme, ze ak je linia vypnuta je to v poriadku lebo nie je na 24/7 linii + //ak je na 24/7 linii, reportujeme, ze neprijima data + function emptyDailyReport() { + const ts = Date.now(); + emptyJsObject(dailyReport); + + //NOTE: do dailyReport dame vsetky nody a pravidelne kontrolujeme ci maju data + //ked nastane sumrak/usvit a svetla maju zacat/prestat svietit, dailyReport spravime nanovo: + for (const [key, value] of Object.entries(nodesData)) { + dailyReport[value.node] = { line: value.line, initialTs: ts }; + } + + console.log("dailyReport: ", dailyReport); + } + + + async function runTasks() { + + clearInterval(interval); + + let currentTimestamp = Date.now(); + + //sort tasks based on timestamp + 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) { + instance.send(SEND_TO.debug, "no tasks created"); + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + if (!rsPort.isOpen) { + instance.send(SEND_TO.debug, "!rsPort.isOpen"); + //await rsPort.open(); + //console.log("Cmd-mngr: !rsPort.isOpen"); + } + + let currentTask = tasks[0]; + + if (currentTask.debug) { + //logger.debug("--->task to process", currentTask); + } + + if (currentTask.timestamp <= currentTimestamp) { + let params = { ...tasks[0] }; + + //allow terminal commands + if (SETTINGS.maintenance_mode && params.type !== "cmd-terminal") { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + let type = params.type; + let tbname = params.tbname; + let node = params.address; + let register = params.register; + let line = null; + let itIsNodeCommand; + + if (nodesData[node] !== undefined) { + line = nodesData[node].line; + itIsNodeCommand = true; + } + + if (params.line !== undefined) line = params.line; + + if (params.addMinutesToTimestamp > 0 || params.timePointName) { + tasks[0].timestamp = currentTimestamp + tasks[0].addMinutesToTimestamp * 60000; + } else { + tasks.shift(); + } + + //kontrola nespracovanych profilov nodov + //TODO: co ked niektore nody neprijimaju profily? kazdu hodinu zahltuju "tasks" array + if (type == "process_profiles") { + //na vsetky zapnutych liniach sa spracuju nespracovane profily nodov + loadRelaysData(); + interval = setInterval(runTasks, SHORT_INTERVAL); + return; + } + + //relay + if (type == "relay") { + + const timePointName = params.timePointName; + const value = params.value; + + let date = new Date(); + date.setDate(date.getDate() + 1);//next day + + let sunCalcResult; + if (timePointName) sunCalcResult = calculateDuskDawn(date, params.line); + + + if (timePointName == "dawn") { + tasks[0].timestamp = sunCalcResult.dawn_time; + } + else if (timePointName == "dusk") { + tasks[0].timestamp = sunCalcResult.dusk_time; + } + else if (timePointName == "luxOn") { + tasks[0].timestamp = sunCalcResult.dusk_time + params.dusk_lux_sensor_time_window * 60000; + } + else if (timePointName == "luxOff") { + tasks[0].timestamp = sunCalcResult.dawn_time + params.dawn_lux_sensor_time_window * 60000; + } + else if (timePointName == "profileTimepoint") { + tasks[0].timestamp = currentTimestamp + tasks[0].addMinutesToTimestamp * 60000; + } + + let info = "aplikovany bod profilu"; + let onOrOff = ""; + value == 1 ? onOrOff = "on" : onOrOff = "off"; + + turnLine(onOrOff, params.line, info); + + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + if (!SETTINGS.masterNodeIsResponding) { + //ak neodpoveda, nebudeme vykonavat ziadne commands, okrem cmd-terminal cmd-master + errorHandler.sendMessageToService("Master node is not responding"); + + let stop = true; + + if (type === "cmd-terminal" || type === "cmd-master") stop = false; + if (stop) { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + } + + let contactorStatus = 1; + if (relaysData[line] != undefined) contactorStatus = relaysData[line].contactor; + + if (line === 0 || contactorStatus === 0 || FLOW.deviceStatus.state_of_breaker[line] === "Off") { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + // TODO: -> status offline for rvo if rotary_switch_state is OFF, this is source of errors + // check if rotary_switch_state == "Off" + // state_of_braker: disconnected = true? + + if (!rsPort.isOpen) { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + //RE-CALCULATE VALUES + //set actual time for broadcast + if (register == 87 && params.recipient === 2) { + var d = new Date(); + params.byte1 = d.getHours();//h + params.byte2 = d.getMinutes();//m + } + + //SET DUSK/DAWN FOR BROADCAST + //Time of dusk + if (register == 6 && params.recipient === 2) { + + if (type != "cmd-terminal") { + params.byte1 = sunCalcResult["dusk_hours"];//h + params.byte2 = sunCalcResult["dusk_minutes"];//m + } + } + + //Time of dawn + if (register == 7 && params.recipient === 2) { + if (type != "cmd-terminal") { + params.byte1 = sunCalcResult["dawn_hours"];//h + params.byte2 = sunCalcResult["dawn_minutes"];//m + } + } + //----------------------- + + instance.send(SEND_TO.debug, "address: " + node + " register:" + register + "type: " + type); + + var startTime, endTime; + startTime = new Date(); + + let saveToTb = true; + if (!tbname) saveToTb = false; + + let resp = com_generic(node, params.recipient, params.rw, register, params.name, params.byte1, params.byte2, params.byte3, params.byte4); + let readBytes = 11; + let timeout = 4000; + + + // await keyword is important, otherwise incorrect data is returned! + await writeData(rsPort, resp, readBytes, timeout).then(function(data) { + + //sometimes happens, that status of node changes to OK, NOK even if line was turned off and should be status OFFLINE. To prevent this, we return if line contactor is 0: + if (itIsNodeCommand && line && relaysData[line].contactor !== 1) return; + + 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); + + //ak sa odpoved zacina 0 - je to v poriadku, inak je NOK + let message = result.message; // OK, NOK + let message_type = result.type; + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + console.log("detected response:", result); + logger.debug("Cmd-mngr: writeData done " + message_type + " duration: " + timeDiff + " type: " + params.debug, params, result); + } + } + + let values = {}; + + //CMD FINISHED + if (message == "OK") { + + updateNodeStatus(node, true); + + //write + if (type == "set_node_profile") { + let result = cmdCounterResolve(node); + if (result == 0) { + dbNodes.modify({ processed: true }).where("node", node).make(function(builder) { + builder.callback(function(err, response) { + + sendNotification("Cmd-mngr: process cmd", SETTINGS.rvoTbName, "dimming_profile_was_successfully_received_by_node", { node: node }, "", SEND_TO.tb, instance); + + logger.debug("--> profil úspešne odoslaný na node č. " + node); + nodesData[node].processed = true; + nodeProfileSendFail.delete(node); + }); + }); + } + } + + //parse read response + if (params.rw == 0) { + values = processResponse(register, dataBytes); //read + } + + if (itIsNodeCommand) { + values.comm_status = "OK"; + values.status = "OK"; + nodesData[node].readout = { ...nodesData[node].readout, ...values }; + + + if (SETTINGS.daily_report) { + //TODO: co ak nedostavame odpovede z nodu ? Musime vyreportovat!! + //v dailyReport teda musi byt kompletny zoznam nodov a neustale kontrolovat, ci maju data, ak nie report node - neodpoveda + if (register === 1) { + + let now = Date.now(); + + if (rvo_is_on === true) { + + if ("dimmingIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].dimmingIsOnButShouldBeOffTime; + + if (values.dimming > 0) { + if ("dimmingIsZeroTime" in dailyReport[node]) delete dailyReport[node].dimmingIsZeroTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if (!("dimmingIsZeroTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], dimmingIsZeroTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } else { + + if ("dimmingIsZeroTime" in dailyReport[node]) delete dailyReport[node].dimmingIsZeroTime; + + if (values.dimming > 0) { + if (!("dimmingIsOnButShouldBeOffTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], dimmingIsOnButShouldBeOffTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if ("dimmingIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].dimmingIsOnButShouldBeOffTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } + } + + if (register === 76) { + + let now = Date.now(); + + if (rvo_is_on === true) { + + if ("powerIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].powerIsOnButShouldBeOffTime; + + if (values.power > 1) { + if ("powerIsZeroTime" in dailyReport[node]) delete dailyReport[node].powerIsZeroTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if (!("powerIsZeroTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], powerIsZeroTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } else { + + if ("powerIsZeroTime" in dailyReport[node]) delete dailyReport[node].powerIsZeroTime; + + if (values.power > 1) { + if (!("powerIsOnButShouldBeOffTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], powerIsOnButShouldBeOffTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if ("powerIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].powerIsOnButShouldBeOffTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } + } + } + + } + + //master node + if (node == 0) { + sendNotification("Cmd-mngr: 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; + } + + if (params.debug) { + //logger.debug("saveToTb", saveToTb, tbname, values); + } + + if (saveToTb && type != "node-regular-read") { + sendTelemetry(values, tbname); + } + else { + if (type == "cmd-terminal") { + terminalCommandResponse(params, "SUCCESS", data); + } + } + + } + else { + terminalCommandResponse(params, "ERROR", data); + handleNokResponseOnRsPort("handleNOK else block", params, itIsNodeCommand, saveToTb); + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + //logger.debug("writeData err: ", error, result, params); + logger.debug("writeData err: ", tbname, node, register, values); + } + } + + //logger.debug(error, result, params); + } + }).catch(function(reason) { + + //console.log("writeData catch exception", reason); + instance.send(SEND_TO.debug, reason); + + terminalCommandResponse(params, "FAILURE", null, reason); + handleNokResponseOnRsPort("handleNOK catch block", params, itIsNodeCommand, saveToTb); + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + logger.debug("-->WRITE FAILED: " + reason, params.debug, params); + } + } + + }); + + } + 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); + } + + + // if node does not respond to request, we repeat request 3 times: + function repeatCommand(params) { + params.repeatCounter++; + if (params.repeatCounter < 4) { + params.timestamp = 0; + params.addMinutesToTimestamp = 0; + tasks.push(params); + } + } + + function handleNokResponseOnRsPort(message, params, itIsNodeCommand, saveToTb) { + + let node = params.address; + let register = params.register; + let type = params.type; + let tbName = params.tbname; + if (!tbName) return; + + let values = {}; + + let updateStatus = updateNodeStatus(node, false); + + if (itIsNodeCommand) { + values.comm_status = "NOK"; + nodesData[node].readout.comm_status = "NOK"; + repeatCommand(params); + } + + if (updateStatus) { + values.status = "NOK"; + nodesData[node].readout.status = "NOK"; + } + + if (type === "node-regular-read") return; + + //master node + if (node == 0) { + sendNotification("Cmd-mngr: 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; + + if (register == 4) values["master_node_version"] = "NOK"; + } + + if (type == "set_node_profile") { + delete cmdCounter[node]; + logger.debug("profil nebol úspešne odoslaný na node č. ", params); + + if (!nodeProfileSendFail.has(node)) { + sendNotification("Cmd-mngr: process cmd", tbName, "configuration_of_dimming_profile_to_node_failed", { node: node }, "", SEND_TO.tb, instance); + nodeProfileSendFail.add(node); + } + } + + // console.log("------",node, register, type, itIsNodeCommand, updateStatus, saveToTb, values); + if (saveToTb) { + sendTelemetry(values, tbName); + } + + } + + + function sendNodesData() { + Object.keys(nodesData).forEach(node => { + if (nodesData[node]["status"] !== "OFFLINE") { + sendTelemetry(nodesData[node].readout, nodesData[node].tbname); + nodesData[node].readout = {}; + } + }) + } + + + /** + * 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; + } + + 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); + + //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 === "OFFLINE") { + nodeObj.node_status_before_offline === true ? number_of_ok_luminaires++ : number_of_nok_luminaires++; + } + else if (nodeObj.status == true) 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 - ts % 60000 //round to full minute + }; + + sendTelemetry(values, SETTINGS.rvoTbName, ts); + } + + + function setSunCalcResult() { + //if next day, we get new dusk and dawn. To make sure, in local timezone 2:00 means 00:00 in utc (it means next day) + if (new Date().getHours() === 2) { + sunCalcResult = calculateDuskDawn(); + console.log("Novy suncalc: ", sunCalcResult); + } + } + + + function setRvoPeriod() { + + if (!SETTINGS.daily_report) return; + + const ts = Date.now(); + + previous_rvo_is_on_value = rvo_is_on; + + if (ts < sunCalcResult.dawn_time - 1_800_000) { // nodes should be on (00:00 -> 06:00 ( - pol hodina, lebo rvo vypina skor) + rvo_is_on = true; + } else if (sunCalcResult.dawn_time - 1_800_000 < ts && ts < sunCalcResult.dusk_time + 1_800_000) { // nodes should be off 06:00 -> 21:00 + rvo_is_on = false; + } else if (sunCalcResult.dusk_time + 1_800_000 < ts) { // nodes should be on 21:00 -> 00:00 + rvo_is_on = true; + } + + if (previous_rvo_is_on_value !== rvo_is_on) { + emptyDailyReport(); + console.log("rvo_is: ", rvo_is_on, previous_rvo_is_on_value); + } + } + + + function handleRsPort() { + + if (rsPort) { + rsPort.removeAllListeners(); + rsPort = null; + } + + //! 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-mngr: rsPort opened success"); + + 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); + + }).catch(function(reason) { + instance.send(SEND_TO.debug, "Cmd-mngr: RPC runSyncExec - promise rejected:" + reason); + }); + }); + + rsPort.on('error', function(err) { + errorHandler.sendMessageToService([exports.title, "unable to open port", SETTINGS.serial_port, err.message], 0); + monitor.info("Cmd-mngr: Error on rsPort", err.message); + }); + + rsPort.on("close", () => { + monitor.info("Cmd-mngr: rsPort closed, reconnecting..."); + setTimeout(handleRsPort, 1000); + }); + + rsPort.open(); + } + + + instance.on("close", () => { + clearInterval(interval); + clearInterval(customTasksInterval); + clearInterval(setCorrectTime); + clearInterval(sendNodeReadout); + clearInterval(accelerometerInterval); + rsPort.close(); + }); + + instance.on("0", _ => { + main(); + }) + + + instance.on("2", _ => { + console.log("dailyReport, reportToSend, rvo_is_on", dailyReport, reportToSend, rvo_is_on, previous_rvo_is_on_value); + }) + + instance.on("1", 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(); + return; + } + else if (flowdata.data == "close") { + rsPort.close(); + return; + } + else if (flowdata.data == "clean") { + tasks = []; + return; + } + else if (flowdata.data == "buildtasks") { + //build & run + return; + } + else if (flowdata.data == "run") { + //durations = []; + + if (tasks.length == 0) { + + buildTasks(); + + if (rsPort.isOpen) { + interval = setInterval(runTasks, 100); + } + else { + instance.send(SEND_TO.debug, "port is not opened!!!"); + } + } + } + else { + //terminal data - object + //logger.debug("flowdata", flowdata.data); + + if (typeof flowdata.data === 'object') { + //logger.debug("dido", flowdata.data); + if (flowdata.data.hasOwnProperty("sender")) { + //data from dido_controller + if (flowdata.data.sender == "dido_controller") { + + if (flowdata.data.hasOwnProperty("cmd")) { + let cmd = flowdata.data.cmd; + + if (cmd == "buildTasks") { + clearInterval(interval); + + logger.debug("-->Cmd-mngr: BUILD TASKS"); + buildTasks(); + + //logger.debug("tasks:"); + //logger.debug(tasks); + + logger.debug("-->Cmd-mngr: RUN TASKS"); + interval = setInterval(runTasks, 5000); + } + else if (cmd == "reload_relays") { + loadRelaysData(flowdata.data.line); + + if (flowdata.data.dataChanged) { + if (!flowdata.data.value) { + reportOfflineNodeStatus(flowdata.data.line); + } + else { + reportOnlineNodeStatus(flowdata.data.line); + } + } + + } + else if (cmd == "rotary_switch_state") { + let value = flowdata.data.value; + + //state was changed + if (rotary_switch_state != value) { + if (value == "Off") { + //vyreportovat vsetky svietdla + reportOfflineNodeStatus(); + } + + rotary_switch_state = value; + } + } + 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) { + + // we send lux_sensor value to all nodes: + let params = getParams(PRIORITY_TYPES.node_broadcast); + + params.recipient = 2;//2 broadcast, address = 0 + params.address = 0xffffffff;//Broadcast + + let ba = longToByteArray(lux_sensor); + + params.byte3 = ba[1];//msb + params.byte4 = ba[0]; + params.timestamp = PRIORITY_TYPES.node_broadcast; + params.info = "run broadcast: Actual Lux level from cabinet"; + params.register = 95;//Actual Lux level from cabinet + params.rw = 1;//write + + tasks.push(params); + + //process profiles + turnOnOffLinesAccordingToLuxSensor(lux_sensor); + } + } + else if (cmd == "state_of_breaker") { + //istic linie + + breakerCounter--; + + let value = flowdata.data.value; + let line = parseInt(flowdata.data.line); + + let dataChanged = false; + if (state_of_breaker[line] != value) dataChanged = true; + + state_of_breaker[line] = value; + + let status = "OK"; + if (value == "Off") status = "NOK"; + + if (dataChanged) { + + if (relaysData.hasOwnProperty(line)) { + let tbname = relaysData[line].tbname; + + if (value == "Off") { + sendNotification("Cmd-mngr: onData", tbname, "circuit_breaker_was_turned_off_line", { line: line }, "", SEND_TO.tb, instance, "circuit_breaker"); + if (breakerCounter < 0) reportToSend["contactor"]["off"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + else { + sendNotification("Cmd-mngr: onData", tbname, "circuit_breaker_was_turned_on_line", { line: line }, "", SEND_TO.tb, instance, "circuit_breaker"); + if (breakerCounter < 0) reportToSend["contactor"]["on"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + + //report status liniu + sendTelemetry({ status: status }, tbname) + + //current value + if (value == "Off") reportOfflineNodeStatus(line); //vyreportovat vsetky svietidla na linii + } + + } + } + else { + logger.debug("undefined cmd", cmd); + } + } + } + + return; + } + + //data from worksys + if (flowdata.data.hasOwnProperty("topic")) { + + let data = getNested(flowdata.data, "content", "data"); + + //if we get temperature in senica from senica-prod01 + let temperature = getNested(flowdata.data, "content", "senica_temperature"); + + if (temperature !== undefined) { + temperatureInSenica = temperature; + return; + } + + if (data === undefined) { + console.log("Invalid rpc command came from platform"); + return; + } + + let command = data.params.command; + let method = data.method; + let profile = data.params.payload; + if (profile == undefined) profile = ""; + let entity = data.params.entities[0]; + let entity_type = entity.entity_type; + let tbname = entity.tb_name; + + instance.send(SEND_TO.debug, flowdata.data); + 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") { + + //let command = data.params.command; + let value = data.params.payload.value; + + if (command == "dimming") { + + let nodeWasFound = false; + let keys = Object.keys(nodesData); + + //logger.debug("-----", keys); + + 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); + + value = parseInt(value); + if (value > 0) value = value + 128; + + params.type = "node-onetime-write"; + params.tbname = tbname; + params.address = node; + params.register = 1; + params.recipient = 1; + params.byte4 = value; + params.rw = 1; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'set dimming from platform'; + //params.debug = true; + + //debug(params); + logger.debug("dimming", params); + + tasks.push(params); + + 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); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 1; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read dimming (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + //pridame aj vyreportovanie - vykon + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 76; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read Input Power (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + //pridame aj vyreportovanie - prud svietidla + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 75; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read Input Current (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + //pridame aj vyreportovanie - power faktor - ucinnik + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 77; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read power factor (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + }, 4000); + + nodeWasFound = true; + break; + } + } + + if (!nodeWasFound) { + logger.debug("set dimming from platform", "unable to find tbname", tbname); + } + } + else { + instance.send(SEND_TO.debug, "undefined command " + command); + logger.debug("undefined command", command); + } + + return; + } + 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++) { + let node = keys[i]; + if (tbname == nodesData[node].tbname) { + + 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"); + + //profil úspešne prijatý pre node č. xx + sendNotification("Cmd-mngr", tbname, "dimming_profile_was_processed_for_node", { node: node }, profile, SEND_TO.tb, instance); + + nodesData[node].processed = false; + nodesData[node].profile = profile; + + processNodeProfile(node); + }); + }); + } + } + } + else { + + instance.send(SEND_TO.debug, "unknown method " + method); + logger.debug("unknown method", method); + + return; + } + } + + //nastav profil linie z platformy + 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") { + + 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++) { + let line = keys[i]; + if (tbname == relaysData[line].tbname) { + //zmazeme tasky + 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) { + + //update profile + logger.debug("worksys - update relay profile done:", profile); + instance.send(SEND_TO.debug, "worksys - update relay profile done"); + + relaysData[line].profile = profile; + + loadRelaysData(line) + logger.debug("loadRelaysData DONE for line", line); + + buildTasks({ processLineProfiles: true, line: line }); + + sendNotification("Cmd-mngr: set profile from worksys", tbname, "switching_profile_was_processed_for_line", { line: line }, profile, SEND_TO.tb, instance); + }); + }); + break; + } + } + } + else if (method == "set_command") { + let value = data.params.payload.value; + + 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; + + 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"); + if (line != 0) reportToSend["contactor"]["off"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + else { + turnLine("on", line, "command received from platform"); + if (line != 0) reportToSend["contactor"]["on"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + } + } + else { + instance.send(SEND_TO.debug, "undefined method " + method); + logger.debug("undefined method", method); + } + + return; + } + else { + instance.send(SEND_TO.debug, "UNKNOW entity_type " + entity_type); + logger.debug("UNKNOW entity_type", entity_type); + } + return; + } + + //terminal + if (!rsPort.isOpen) await rsPort.open(); + + let params = flowdata.data.body; + if (params == undefined) { + //logger.debug("Cmd-mngr: flowdata.data.body is undefined"); + return; + } + + params.priority = PRIORITY_TYPES.terminal; + params.type = "cmd-terminal"; + params.tbname = ""; + params.timestamp = PRIORITY_TYPES.terminal; + params.addMinutesToTimestamp = 0;// do not repeat task!!! + params.debug = true; + + let timestamp = Date.now(); + params.refFlowdataKey = timestamp; + //params.refFlowdata = flowdata; + //refFlowdata = flowdata; + + //console.log("flowdata", flowdata); + + cleanUpRefFlowdataObj(); + + refFlowdataObj[timestamp] = flowdata; + + //fix + //params.address = params.adress; + logger.debug("received from terminal", params); + logger.debug("date/time:", new Date()); + logger.debug("tasks length:", tasks.length); + + //tasks = []; + + //add to tasks + tasks.push(params); + + } + } + }) + + + //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) + } + + + /** + * 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; + + RESTBuilder.make(function(builder) { + + if (!builder) return; + + builder.method('GET'); + builder.url('http://192.168.252.2:8004/gettime?projects_id=1'); + + builder.callback(function(err, response, output) { + + 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); + } + + }); + } + + } 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); + + } else { + //console.log("Read-only", stdout); + + 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]: [ + { + "ts": date, + "values": values + } + ] + } + + tbHandler.sendToTb(dataToTb, instance); + } + + + function calculateDuskDawn(date, line, duskOffset = 0, dawnOffset = 0) { + + if (date === undefined) date = new Date(); + + 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); + } + + //if(profile.dawn_lux_sensor == false) + { + if (profile.hasOwnProperty("dawn_astro_clock_offset")) dawn_astro_clock_offset = parseInt(profile.dawn_astro_clock_offset); + } + + } + + } catch (error) { + if (profilestr != "") { + logger.debug(profilestr); + logger.debug(error); + } + } + + 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; + } + + //Dimming, CCT + else if (register == 1) { + let brightness = 0; + let dimming = byte0; + if (dimming > 128) { + //dimming = -128; + brightness = dimming - 128; + } + + //cct + //Ak Byte3 == 1: CCT = (Byte2*256)+Byte1 + let cct; + if (byte3 == 1) cct = byte2 * 256 + byte1; + else cct = bytesToInt(bytes.slice(0, 3)); + + //cct podla auditu + + values["dimming"] = brightness; + return values; + } + + // + else if (register == 4) { + values["master_node_version"] = bytes[1] + "." + bytes[2]; + //logger.debug("FW Version", register, bytes); + } + + //Napätie + else if (register == 74) { + let voltage = (bytesToInt(bytes) * 0.1).toFixed(1); + values["voltage"] = Number(voltage); + } + + //Prúd + else if (register == 75) { + let current = bytesToInt(bytes); + values["current"] = current; + } + + //výkon + else if (register == 76) { + let power = (bytesToInt(bytes) * 0.1).toFixed(2); + values["power"] = Number(power); + } + + //účinník + else if (register == 77) { + let power_factor = Math.cos(bytesToInt(bytes) * 0.1 * (Math.PI / 180)).toFixed(2); + values["power_factor"] = Number(power_factor); + } + + //frekvencia + else if (register == 78) { + let frequency = (bytesToInt(bytes) * 0.1).toFixed(2); + values["frequency"] = Number(frequency); + } + + //energia + else if (register == 79) { + let energy = bytesToInt(bytes); + values["energy"] = energy / 1000; //energia v kWh -> delit 1000 + } + + //doba života + else if (register == 80) { + let lifetime = (bytesToInt(bytes) / 60).toFixed(2); + values["lifetime"] = Number(lifetime); + } + + //nastavenie profilu + else if (register == 8) { + let time_schedule_settings = bytesToInt(bytes); + values["time_schedule_settings"] = time_schedule_settings; + } + + //naklon - nateraz sa z nodu nevycitava! kvoli problemom s accelerometrom a vracanymi hodnotami, posielame temp a x y z vo funkcii accelerometerData() + else if (register == 84) { + values["temperature"] = byte3 >= 128 ? (byte3 - 128) * (-1) : byte3; + values["inclination_x"] = byte2 >= 128 ? (byte2 - 128) * (-1) : byte2; + values["inclination_y"] = byte1 >= 128 ? (byte1 - 128) * (-1) : byte1; + values["inclination_z"] = byte0 >= 128 ? (byte0 - 128) * (-1) : byte0; + } + + //FW verzia nodu + else if (register == 89) { + //formát: "Byte3: Byte2.Byte1 (Byte0)" + values["fw_version"] = byte3 + ":" + byte2 + "." + byte1 + "(" + byte0 + ")"; + } + + else if (register == 87 || register == 6 || register == 7) { + var d = new Date(); + d.setHours(byte3, byte2, 0, 0); + let timestamp = d.getTime(); + + //aktuálny čas + if (register == 87) values["actual_time"] = timestamp; + //čas súmraku + else if (register == 6) values["dusk_time"] = timestamp; + //čas úsvitu + else if (register == 7) values["dawn_time"] = timestamp; + } + + 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; + + } + + + function getObjectByTbValue(object, tbname) { + return object[Object.keys(object).find(key => object[key].tbname === tbname)]; + } + + + function isObject(item) { + return (typeof item === "object" && !Array.isArray(item) && item !== null); + } + + + // we fake data, that should be received from accelerometer, as they are a bit unreliable. (temperature, x,y,z) + function accelerometerData() { + + if (temperatureInSenica === null) return; + + //clone nodesData and relaysData objects + let nodesData_clone = JSON.parse(JSON.stringify(nodesData)); + let relaysData_clone = JSON.parse(JSON.stringify(relaysData)); + + for (const key in relaysData_clone) { + + const lineData = relaysData_clone[key]; + const lineNumber = lineData.line; + const contactor = lineData.contactor; + + if (lineNumber === 0) continue; + + if (contactor === 1) { + + let date = Date.now(); + + Object.keys(nodesData_clone).forEach((node, index) => { + + setTimeout(function() { + + if (nodesData_clone[node].line === lineNumber) { + + // NOTE: if status of luminaire is NOK or OFFLINE, we do not send data; + let status = nodesData_clone[node].status; + if (status === "OFFLINE" || !status) return; + + let x = null; + if (naklony.hasOwnProperty(node)) x = naklony[node].naklon; + if (x === null) x = 0; + + sendTelemetry({ temperature: Math.round(temperatureInSenica + 10 + Math.floor(Math.random() * 3)), inclination_x: x, inclination_y: 0, inclination_z: 0 }, nodesData_clone[node].tbname, date); + } + + }, (index + 1) * 500); + }) + + } + } + } + + +} // end of instance.export + diff --git a/RVO42/flow/code.js b/RVO42/flow/code.js new file mode 100755 index 0000000..63b31bf --- /dev/null +++ b/RVO42/flow/code.js @@ -0,0 +1,90 @@ +exports.id = 'code'; +exports.title = 'Code'; +exports.group = 'Common'; +exports.color = '#656D78'; +exports.input = true; +exports.output = 1; +exports.author = 'Peter Širka'; +exports.icon = 'code'; +exports.version = '1.2.0'; +exports.options = { outputs: 1, code: 'send(0, value);', keepmessage: true }; + +exports.html = `
+
+
+
@(Number of outputs)
+
@(Minimum is 1)
+
+
+
@(Code)
+
@(Keep message instance)
+
+`; + +exports.readme = `# Code + +This component executes custom JavaScript code as it is and it doesn't contain any secure scope. + +\`\`\`javascript +// value {Object} contains received data +// send(outputIndex, newValue) sends a new value +// error(value) sends an error +// instance {Object} a current component instance +// flowdata {Object} a current flowdata +// repository {Object} a current repository of flowdata +// Example: + +// send() can be execute multiple times +send(0, value); +\`\`\``; + +exports.install = function(instance) { + + var fn; + + instance.on('data', function(response) { + if (fn) { + try { + fn(response.data, instance, response, instance.options, response.repository, require); + } catch (e) { + response.data = e; + instance.throw(response); + } + } + }); + + instance.reconfigure = function() { + try { + if (instance.options.code) { + instance.status(''); + var code = 'var send = function(index, value) { if (options.keepmessage) { flowdata.data = value; instance.send2(index, flowdata); } else instance.send2(index, value);}; var error = function(err) { instance.throw(err); }; ' + instance.options.code; + fn = new Function('value', 'instance', 'flowdata', 'options', 'repository', 'require', code); + } else { + instance.status('Not configured', 'red'); + fn = null; + } + } catch (e) { + fn = null; + instance.error('Code: ' + e.message); + } + }; + + instance.on('options', instance.reconfigure); + instance.reconfigure(); +}; \ No newline at end of file diff --git a/RVO42/flow/comment.js b/RVO42/flow/comment.js new file mode 100755 index 0000000..1e0cd13 --- /dev/null +++ b/RVO42/flow/comment.js @@ -0,0 +1,11 @@ +exports.id = 'comment'; +exports.title = 'Comment'; +exports.group = 'Common'; +exports.color = '#704cff'; +exports.author = 'Martin Smola'; +exports.icon = 'comment'; +exports.traffic = false; +exports.version = '1.0.0'; +exports.readme = '# Comment'; + +exports.install = function() {}; diff --git a/RVO42/flow/count.js b/RVO42/flow/count.js new file mode 100755 index 0000000..fa92ee9 --- /dev/null +++ b/RVO42/flow/count.js @@ -0,0 +1,60 @@ +exports.id = 'count'; +exports.title = 'Count'; +exports.version = '1.0.1'; +exports.author = 'John Graves'; +exports.color = '#656D78'; +exports.icon = 'plus-square'; +exports.input = 2; +exports.output = 1; +exports.options = { increment: 1, initialvalue: 1 }; +exports.readme = `# Counter + +Counter Number of times called.`; + +exports.html = `
+
@(Initial Value)
+
@(Increment)
+

Example Video

+
`; + +exports.readme = `# Count + +This component counts the number of messages received. + +__Response:__ + +Integer value based on the initial value and increment settings. + +__Arguments:__ +- Initial Value: What number should be output on the receipt of the first message. +- Increment: What should the increment be for each following message received.`; + +exports.install = function(instance) { + + var count = 0; + var initialCall = true; + + instance.on('data', function(flowdata) { + var index = flowdata.index; + if (index) { + instance.debug('Reset Count.'); + count = instance.options.initialvalue; + initialCall = true; + } else { + // If this is the first time, set the value to 'initial value' + if(initialCall) { + initialCall = false; + count = instance.options.initialvalue; + } else + count = count+instance.options.increment; + instance.status('Count:' + count); + instance.send2(count); + } + }); + + instance.on('options', function() { + count = instance.options.initialvalue; + initialCall = true; + }); + +}; diff --git a/RVO42/flow/csv_import.js b/RVO42/flow/csv_import.js new file mode 100755 index 0000000..5ae1e68 --- /dev/null +++ b/RVO42/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/RVO42/flow/db_connector.js b/RVO42/flow/db_connector.js new file mode 100755 index 0000000..65ee94b --- /dev/null +++ b/RVO42/flow/db_connector.js @@ -0,0 +1,286 @@ +exports.id = 'db_connector'; +exports.title = 'DbConnector'; +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.html = `
+
+
+
DbConnector
+
+
+
`; + +exports.readme = `# read/write data to tables`; + +const instanceSendTo = { + debug: 0, + http_response: 1, +} + +const { promisifyBuilder, makeMapFromDbResult } = require('./helper/db_helper.js'); + +function extractWhereParams(params) +{ + let name = params[0]; + let operator = '='; + let value = params[1]; + + if(params.length == 3) + { + operator = params[1]; + value = params[2]; + } + + return {name: name, operator: operator, value: value}; +} + +exports.install = function(instance) { + + let refFlowdata = null;//holds reference to httprequest flowdata + + instance.on("close", () => { + + }) + + + instance.on("data", async function(flowdata) { + + let params = flowdata.data.body; + console.log("DbConnector", params); + + refFlowdata = flowdata; + + if(refFlowdata != undefined) + { + //make http response + let responseObj = {}; + responseObj["type"] = "SUCESS"; + + try{ + + let table = params.table; + let action = params.action; + + + if(params.data != undefined) + { + let className = params.data.className; + + if(className == "SqlQueryBuilder") + { + let type = params.data.type; + + console.log("SqlQueryBuilder---->", params.data); + + if(type == "SELECT") + { + let table = params.data.queryData.tables[0].table; + + const db = TABLE(table); + var builder = db.find(); + + let result = await promisifyBuilder(builder); + + let response = {}; + response["result"] = result; + response["success"] = true; + + responseObj["data"] = response; + + //console.log(responseObj); + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + } + + return; + } + } + + + console.log("db_connector---->", table, action); + + //actions: read, replace, insert, delete, update... + + if(action == "read") + { + const db = TABLE(params.table); + + //where builder.where('age', '<', 15); + //builder.where('id', 3403); + + var builder = db.find(); + + //https://docs.totaljs.com/latest/en.html#api~DatabaseBuilder~builder.where + if(params.hasOwnProperty("where")) + { + //optionalCan contain "=", "<=", "<", ">=", ">". + //Default value: '=' + + //1.["production_line", 1] + //2. ["or", ["production_line", 1], ["production_line", 2], "end"] + + if (Array.isArray(params.where)) { + + let multipleConditions = false; + + if(params.where[0] == "or") multipleConditions = true; + if (Array.isArray(params.where[0])) multipleConditions = true; + + if(multipleConditions) + { + + for(var i = 0; i < params.where.length; i++) + { + const item = params.where[i]; + + if(item === "or") builder.or(); + + if (Array.isArray(item)) + { + const { name, operator, value } = extractWhereParams(item); + builder.where(name, operator, value); + } + + if(item === "end") builder.end(); + + } + + } + else + { + const { name, operator, value } = extractWhereParams(params.where); + builder.where(name, operator, value); + } + + } + + /* + if(params.where.length >=2 ) + { + let name = params.where[0]; + let operator = '='; + let value = params.where[1]; + + if(params.where.length == 3) + { + operator = params.where[1]; + value = params.where[2]; + } + + builder.where(name, operator, value); + } + */ + } + + if(params.hasOwnProperty("between")) + { + builder.between(params.between[0], params.between[1], params.between[2]); + } + + let response = await promisifyBuilder(builder); + responseObj["data"] = response; + + //console.log(responseObj); + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + + return; + } + + if(action == "delete") + { + + } + + + if(action == "update") + { + //! data receiving from terminal (params) + // { + // hostname: 'localhost', + // table: 'settings', + // action: 'update', + // body: { + // rvo_name: 'terrrr', + // lang: 'en', + // temperature_adress: '28.427B45920702', + // latitude: 48.70826502, + // longitude: 17.28455203, + // mqtt_host: '192.168.252.4', + // mqtt_clientid: 'showroom_test_panel_led', + // mqtt_username: 'xmRd6RJxW53WZe4vMFLU', + // mqtt_port: 1883, + // maintanace_mode: false + // } + // } + const tableToModify = TABLE(params.table); + const newValues = params.body; + + tableToModify.modify(newValues).make(function(builder) { + + builder.callback(function(err, response) { + + if(!err) + { + responseObj["data"] = response; + responseObj["tableUpdated"] = true; + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + } + }); + }); + + } + + if(action == "replace") + { + //truncate table + const db = TABLE(params.table); + var builder = db.remove(); + db.clean(); + + //insert data + let data = params.data; + + for(let i = 0; i < data.length; i++) + { + //console.log(data[i]); + db.insert(data[i]); + } + + console.log("insert done"); + + let responseObj = {}; + responseObj["type"] = "SUCESS"; + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + + + } + + + + } catch (error) { + //console.log(error); + responseObj["type"] = "ERROR"; + responseObj["message"] = error; + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + } + } + }) +} + + diff --git a/RVO42/flow/db_init.js b/RVO42/flow/db_init.js new file mode 100755 index 0000000..b399878 --- /dev/null +++ b/RVO42/flow/db_init.js @@ -0,0 +1,113 @@ +exports.id = 'db_init'; +exports.title = 'DB Initialization'; +exports.group = 'Worksys'; +exports.color = '#888600'; +exports.version = '1.0.2'; +exports.icon = 'sign-out'; +exports.output = 2; + +exports.readme = ` + # DB initialization +`; + +const { promisifyBuilder, makeMapFromDbResult } = require('./helper/db_helper.js'); +const { initNotification } = require('./helper/notification_reporter'); +const errorHandler = require('./helper/ErrorToServiceHandler'); +const total_energy = require('../databases/total_energy'); + +const SEND_TO = { + db_init: 0, + infoSender: 1 +}; + + +exports.install = async function(instance) { + const dbNodes = TABLE("nodes"); + const dbRelays = TABLE("relays"); + const dbSettings = TABLE("settings"); + 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 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.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"]; + Object.keys(dbs.nodesData).forEach(node => dbs.nodesData[node].readout = {}) + + let rvo_number = responseSettings[0]["rvo_name"].match(/\D+(\d{1,2})_/)[1]; + + dbs.settings = { + edge_fw_version: "2025-10-08", //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"], + phases: responseSettings[0]["phases"], + cloud_topic: responseSettings[0]["cloud_topic"], + has_main_switch: responseSettings[0]["has_main_switch"], + daily_report: responseSettings[0]["daily_report"], + send_changed_node_numbers: responseSettings[0]["send_changed_node_numbers"], + rvo_number: rvo_number, + + //dynamic values + masterNodeIsResponding: true, //cmd_manager + maintenance_mode: false, + } + + + dbs.settings.energy_to_switch_lamps = total_energy[rvo_number]; + if (dbs.settings.energy_to_switch_lamps === undefined) console.log('=============== db_init.js: energy_to_switch_lamps is undefined'); + + FLOW.dbLoaded = true; + errorHandler.setProjectId(dbs.settings.project_id); + initNotification(); + + //APP START - send to data services + const toService = { + id: dbs.settings.project_id, + name: dbs.settings.rvo_name, + fw_version: dbs.settings.edge_fw_version, + startdate: new Date().toISOString().slice(0, 19).replace('T', ' '), + js_error: "", + error_message: "" + }; + + instance.send(SEND_TO.infoSender, toService); + console.log("----------------> START - message send to service", toService); + + setTimeout(() => { + console.log("DB_INIT - data loaded"); + instance.send(SEND_TO.db_init, "_") + }, 5000) + +}; + diff --git a/RVO42/flow/debug.js b/RVO42/flow/debug.js new file mode 100755 index 0000000..00cb259 --- /dev/null +++ b/RVO42/flow/debug.js @@ -0,0 +1,100 @@ +exports.id = 'debug'; +exports.title = 'Debug'; +exports.author = 'Peter Širka'; +exports.color = '#967ADC'; +exports.click = true; +exports.input = true; +exports.icon = 'bug'; +exports.version = '2.0.4'; +exports.options = { enabled: true, repository: false, type: 'data' }; +exports.readme = `# Debug + +Prints data to the debug tab.`; + +exports.html = `
+
+
+
@(Output type)
+
@(Path to the property (leave empty to show the whole data object))
+
@(A group name)
+
@(Enabled)
+
+
+
`; + +exports.install = function(instance) { + + instance.on('data', function(response) { + if (instance.options.enabled) { + + var opt = instance.options; + var rep = response.repository; + var val = response.data; + var id = response.id; + + switch (instance.options.type){ + case 'both': + var data = {}; + data.repository = rep; + data.data = val instanceof Error ? { error: val.message, stack: val.stack } : val; + instance.debug(safeparse(opt.property ? U.get(data, opt.property) : data), undefined, opt.group, id); + break; + case 'repository': + instance.debug(safeparse(opt.property ? U.get(rep, opt.property) : rep), undefined, opt.group, id); + break; + case 'data': + default: + if (val instanceof Error) + instance.debug({ error: val.message, stack: val.stack }, undefined, opt.group, id); + else + instance.debug(safeparse(opt.property ? U.get(val, opt.property) : val), undefined, opt.group, id); + break; + } + } + }); + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + instance.save(); + }); + + instance.on('options', function() { + instance.custom.status(); + }); + + instance.custom.status = function() { + instance.status(instance.options.enabled ? 'Enabled' : 'Disabled'); + }; + + instance.custom.status(); + + function safeparse(o) { + + if (o instanceof Buffer) + return o; + + if (o === undefined) + return 'undefined'; + + if (o === null) + return 'null'; + + var cache = []; + var str = JSON.stringify(o, function(key, value) { + if (typeof value === 'object' && value !== null) { + if (cache.indexOf(value) !== -1) { + try { + return JSON.parse(JSON.stringify(value)); + } catch (error) { + return; + } + } + cache.push(value); + } + return value; + }); + cache = null; + return JSON.parse(str); + } +}; diff --git a/RVO42/flow/designer.json b/RVO42/flow/designer.json new file mode 100755 index 0000000..580f5a3 --- /dev/null +++ b/RVO42/flow/designer.json @@ -0,0 +1,3102 @@ +{ + "tabs": [ + { + "name": "MAIN PUSH", + "linker": "main-push", + "id": "1612772287426", + "index": 0 + }, + { + "name": "CMD manager", + "linker": "cmd-manager", + "id": "1615551125555", + "index": 1 + }, + { + "name": "Devices", + "linker": "devices", + "id": "1611921777196", + "index": 2 + } + ], + "components": [ + { + "id": "1611951142547", + "component": "debug", + "tab": "1611921777196", + "name": "ERROR", + "x": 598, + "y": 60, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#DA4453", + "notes": "" + }, + { + "id": "1612776786008", + "component": "wsmqttpublish", + "tab": "1612772287426", + "name": "WS MQTT publish", + "x": 281.75, + "y": 174, + "connections": { + "0": [ + { + "index": "0", + "id": "1615551060773" + } + ], + "1": [ + { + "index": "0", + "id": "1618300858252" + }, + { + "index": "0", + "id": "1618558465485" + } + ], + "2": [ + { + "index": "0", + "id": "1634303685503" + } + ], + "3": [ + { + "index": "0", + "id": "1731068754606" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Connected", + "color": "green" + }, + "options": { + "username": "", + "clientid": "", + "port": "1883", + "host": "" + }, + "color": "#888600", + "notes": "" + }, + { + "id": "1612778461252", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "tb-push", + "x": 72.75, + "y": 328, + "connections": { + "0": [ + { + "index": "0", + "id": "1612783322136" + }, + { + "index": "1", + "id": "1612776786008" + }, + { + "index": "0", + "id": "1731068754606" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1612783322136", + "component": "debug", + "tab": "1612772287426", + "name": "to TB", + "x": 283.75, + "y": 324, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615551060773", + "component": "debug", + "tab": "1612772287426", + "name": "errors from MQTT Broker", + "x": 594, + "y": 57, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#DA4453", + "notes": "" + }, + { + "id": "1615563373927", + "component": "debug", + "tab": "1615551125555", + "name": "Debug", + "x": 755, + "y": 155, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#DA4453", + "notes": "" + }, + { + "id": "1615566865233", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "tb-push", + "x": 755, + "y": 248, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1615798582262", + "component": "debug", + "tab": "1615551125555", + "name": "CMD_debug", + "x": 755, + "y": 346, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615802995322", + "component": "debug", + "tab": "1611921777196", + "name": "Debug", + "x": 596.8833312988281, + "y": 566.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Disabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": false + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615809128443", + "component": "debug", + "tab": "1611921777196", + "name": "tempToTb", + "x": 595.8833312988281, + "y": 658.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615809595184", + "component": "virtualwireout", + "tab": "1611921777196", + "name": "tb-push", + "x": 597.8833312988281, + "y": 377.25, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1616165795916", + "component": "httproute", + "tab": "1615551125555", + "name": "POST /terminal", + "x": 135, + "y": 547, + "connections": { + "0": [ + { + "index": "0", + "id": "1684060205000" + }, + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Listening", + "color": "green" + }, + "options": { + "timeout": 10, + "cachepolicy": 0, + "cacheexpire": "5 minutes", + "size": 5, + "url": "/terminal", + "method": "POST", + "name": "", + "flags": [ + "id:1616165795916", + "post", + 10000 + ], + "emptyresponse": false + }, + "color": "#5D9CEC", + "notes": "### Configuration\n\n- __POST /terminal__\n- flags: \n- maximum request data length: __5 kB__\n- empty response: __false__\n- cache policy: __no cache__\n- cache expire: __5 minutes__", + "cloning": false + }, + { + "id": "1616165824813", + "component": "httpresponse", + "tab": "1615551125555", + "name": "HTTP Response", + "x": 753, + "y": 423, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "json" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1617104731852", + "component": "debug", + "tab": "1615551125555", + "name": "DIDO_Debug", + "x": 669, + "y": 1040, + "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": "turnOff line", + "x": 133, + "y": 1161, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "object", + "data": "{line: 3, command: \"turnOff\", force: true}" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1617115013095", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "tb-push", + "x": 669, + "y": 1150, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1617284749681", + "component": "trigger", + "tab": "1615551125555", + "name": "update profile / node", + "x": 112, + "y": 208, + "connections": { + "0": [ + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "data": "profile_nodes", + "datatype": "string" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1618235171399", + "component": "trigger", + "tab": "1615551125555", + "name": "tun tasks", + "x": 184, + "y": 279, + "connections": { + "0": [ + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "data": "run" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1618300858252", + "component": "debug", + "tab": "1612772287426", + "name": "wsmqtt-exit1", + "x": 597.8833312988281, + "y": 149, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1618393583970", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "to-cmd-manager", + "x": 668.8833312988281, + "y": 1269, + "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": 132.88333129882812, + "y": 367, + "connections": { + "0": [ + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "platform-rpc-call", + "color": "gray" + }, + "options": { + "wirename": "platform-rpc-call" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1618393759854", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "cmd_to_dido", + "x": 119.88333129882812, + "y": 1007, + "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": 752.8833312988281, + "y": 527, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "cmd_to_dido", + "color": "gray" + }, + "options": { + "wirename": "cmd_to_dido" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1618558465485", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "platform-rpc-call", + "x": 597.8833312988281, + "y": 247, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "platform-rpc-call", + "color": "gray" + }, + "options": { + "wirename": "platform-rpc-call" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1618572059773", + "component": "trigger", + "tab": "1615551125555", + "name": "turnOn line", + "x": 132, + "y": 1085, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "data": "{line: 1, command: \"turnOn\", force: true}", + "datatype": "object" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1619515097737", + "component": "cmd_manager", + "tab": "1615551125555", + "name": "CMD Manager", + "x": 452.1091003417969, + "y": 341.05455017089844, + "connections": { + "0": [ + { + "index": "0", + "id": "1615563373927" + } + ], + "1": [ + { + "index": "0", + "id": "1615566865233" + }, + { + "index": "0", + "id": "1615798582262" + } + ], + "2": [ + { + "index": "0", + "id": "1616165824813" + } + ], + "3": [ + { + "index": "0", + "id": "1618393827655" + } + ], + "4": [ + { + "index": "0", + "id": "1635936391935" + } + ], + "5": [ + { + "index": "0", + "id": "1757006030239" + }, + { + "index": "0", + "id": "1757006060377" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1619605019281", + "component": "httproute", + "tab": "1615551125555", + "name": "GET db", + "x": 173, + "y": 653, + "connections": { + "0": [ + { + "index": "0", + "id": "1684060205000" + }, + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Listening", + "color": "green" + }, + "options": { + "timeout": 5, + "cachepolicy": 0, + "cacheexpire": "5 minutes", + "size": 5, + "url": "/db", + "method": "GET", + "name": "", + "flags": [ + "id:1619605019281", + "get", + 5000 + ] + }, + "color": "#5D9CEC", + "notes": "### Configuration\n\n- __GET /db__\n- flags: undefined\n- maximum request data length: __5 kB__\n- empty response: __undefined__\n- cache policy: __no cache__\n- cache expire: __5 minutes__", + "cloning": false + }, + { + "id": "1619784672383", + "component": "trigger", + "tab": "1615551125555", + "name": "turnOnAlarm", + "x": 120, + "y": 1234, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "object", + "data": "{command: \"turnOnAlarm\"}" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1619784812964", + "component": "trigger", + "tab": "1615551125555", + "name": "turnOffAlarm", + "x": 118, + "y": 1307, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "object", + "data": "{command: \"turnOffAlarm\"}" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1621340721628", + "component": "virtualwireout", + "tab": "1611921777196", + "name": "modbus_to_dido", + "x": 599, + "y": 471, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "modbus_to_dido", + "color": "gray" + }, + "options": { + "wirename": "modbus_to_dido" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1622640022885", + "component": "httproute", + "tab": "1615551125555", + "name": "POST /db_connector", + "x": 98, + "y": 1586, + "connections": { + "0": [ + { + "index": "0", + "id": "1622640073521" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Listening", + "color": "green" + }, + "options": { + "timeout": 5, + "cachepolicy": 0, + "cacheexpire": "5 minutes", + "size": 5, + "url": "/db_connector", + "method": "POST", + "flags": [ + "id:1622640022885", + "post", + 5000 + ] + }, + "color": "#5D9CEC", + "notes": "### Configuration\n\n- __POST /db_connector__\n- flags: \n- maximum request data length: __5 kB__\n- empty response: __undefined__\n- cache policy: __no cache__\n- cache expire: __5 minutes__", + "cloning": false + }, + { + "id": "1622640073521", + "component": "db_connector", + "tab": "1615551125555", + "name": "DbConnector", + "x": 372, + "y": 1572, + "connections": { + "1": [ + { + "index": "0", + "id": "1622641420685" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "edge": "undefined" + }, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1622641420685", + "component": "httpresponse", + "tab": "1615551125555", + "name": "HTTP Response", + "x": 596, + "y": 1586, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1634303504177", + "component": "monitormemory", + "tab": "1612772287426", + "name": "RAM", + "x": 69.88333129882812, + "y": 888.5, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465281992" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "858.88 MB / 985.68 MB", + "color": "gray" + }, + "options": { + "enabled": true, + "interval": 30000 + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1634303533779", + "component": "monitordisk", + "tab": "1612772287426", + "name": "disk", + "x": 70.88333129882812, + "y": 982.5, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465821120" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "5.78 GB / 7.26 GB", + "color": "gray" + }, + "options": { + "enabled": true, + "path": "/", + "interval": 30000 + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1634303595494", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "send-to-services", + "x": 51.883331298828125, + "y": 1400.5, + "connections": { + "0": [ + { + "index": "0", + "id": "1634463186563" + }, + { + "index": "1", + "id": "1634488120710" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1634303602169", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "send-to-services", + "x": 426.8833312988281, + "y": 878.5, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1634303685503", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "send-to-services", + "x": 600.8833312988281, + "y": 341.5, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1634303743260", + "component": "httprequest", + "tab": "1612772287426", + "name": "192.168.252.2:8004/sentmessage", + "reference": "", + "x": 506.8833312988281, + "y": 1331.7333374023438, + "connections": { + "0": [ + { + "index": "0", + "id": "1635327431236" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "url": "http://192.168.252.2:8004/sentmessage", + "method": "POST", + "stringify": "json" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1634463186563", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 305.75, + "y": 1442, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634464580289", + "component": "code", + "tab": "1612772287426", + "name": "Code", + "x": 245, + "y": 787, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465243324" + }, + { + "index": "0", + "id": "1634303602169" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "keepmessage": true, + "code": "let response = {};\nresponse.cpu = value.cpu;\nresponse.uptime = value.uptime;\n\nsend(0, response);", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1634465243324", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 428, + "y": 784, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634465281992", + "component": "code", + "tab": "1612772287426", + "name": "Code", + "x": 245, + "y": 884, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465338103" + }, + { + "index": "0", + "id": "1634303602169" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "keepmessage": true, + "code": "value.sender = \"ram\";\n\nlet response = {};\n\nresponse.memory_total = Math.round(value.total / (1024 ** 2));\nresponse.memory_free = Math.round(value.free / (1024 ** 2));\nresponse.memory_used = Math.round(value.used / (1024 ** 2));\n\nsend(0, response);", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1634465338103", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 429, + "y": 976, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634465821120", + "component": "code", + "tab": "1612772287426", + "name": "Code", + "x": 245, + "y": 978, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465892500" + }, + { + "index": "0", + "id": "1634303602169" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "keepmessage": true, + "code": "value.sender = \"hdd\";\n\nlet response = {};\n\nresponse.hdd_total = Math.round(value.total / (1024 ** 2));\nresponse.hdd_free = Math.round(value.free / (1024 ** 2));\nresponse.hdd_used = Math.round(value.used / (1024 ** 2));\n\nsend(0, response);", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1634465892500", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 432, + "y": 1068, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634484067516", + "component": "debug", + "tab": "1612772287426", + "name": "Send info", + "x": 513, + "y": 1441, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634488120710", + "component": "infosender", + "tab": "1612772287426", + "name": "Info sender", + "x": 301, + "y": 1336, + "connections": { + "0": [ + { + "index": "0", + "id": "1634484067516" + }, + { + "index": "0", + "id": "1634303743260" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "edge": "undefined" + }, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1635327431236", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 837.8833312988281, + "y": 1325.5, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1635936391935", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "send-to-services", + "x": 753, + "y": 623, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1637069803394", + "component": "monitorconsumption", + "tab": "1612772287426", + "name": "CPU", + "x": 69, + "y": 791, + "connections": { + "0": [ + { + "index": "0", + "id": "1634464580289" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "49.2% / 69.91 MB", + "color": "gray" + }, + "options": { + "monitorfiles": true, + "monitorconnections": true, + "monitorsize": true, + "monitorconsumption": true, + "enabled": true, + "interval": 30000 + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1683664161036", + "component": "debug", + "tab": "1615551125555", + "name": "CMDtoDIDO", + "x": 392, + "y": 1012, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1683981346282", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "from-dido-controller", + "x": 112, + "y": 459, + "connections": { + "0": [ + { + "index": "0", + "id": "1684055037116" + }, + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "from-dido-controller", + "color": "gray" + }, + "options": { + "wirename": "from-dido-controller" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1684055037116", + "component": "debug", + "tab": "1615551125555", + "name": "from dido to cmd", + "x": 451, + "y": 532, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1684060205000", + "component": "debug", + "tab": "1615551125555", + "name": "HTTP routes", + "x": 450, + "y": 639, + "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": "MDBToDido", + "x": 598, + "y": 147, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1699963668903", + "component": "dido_controller", + "tab": "1615551125555", + "name": "DIDO_Controller", + "x": 397, + "y": 1131, + "connections": { + "0": [ + { + "index": "0", + "id": "1617104731852" + } + ], + "1": [ + { + "index": "0", + "id": "1617104731852" + }, + { + "index": "0", + "id": "1617115013095" + } + ], + "2": [ + { + "index": "0", + "id": "1618393583970" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "edge": "undefined" + }, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1699964678894", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "modbus_to_dido", + "x": 96, + "y": 924, + "connections": { + "0": [ + { + "index": "0", + "id": "1699963668903" + }, + { + "index": "0", + "id": "1699964793925" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "modbus_to_dido", + "color": "gray" + }, + "options": { + "wirename": "modbus_to_dido" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1699964793925", + "component": "debug", + "tab": "1615551125555", + "name": "modbusToDido", + "x": 388, + "y": 920, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1699965957410", + "component": "modbus_reader", + "tab": "1611921777196", + "name": "Modbus reader", + "x": 232, + "y": 175, + "connections": { + "0": [ + { + "index": "0", + "id": "1611951142547" + } + ], + "1": [ + { + "index": "0", + "id": "1621340721628" + }, + { + "index": "0", + "id": "1684179110403" + }, + { + "index": "0", + "id": "1717441414646" + } + ], + "2": [ + { + "index": "0", + "id": "1615809595184" + }, + { + "index": "0", + "id": "1714752862828" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1700411878636", + "component": "thermometer", + "tab": "1611921777196", + "name": "Thermometer", + "x": 234.75, + "y": 444, + "connections": { + "0": [ + { + "index": "0", + "id": "1615802995322" + } + ], + "1": [ + { + "index": "0", + "id": "1615809595184" + }, + { + "index": "0", + "id": "1615809128443" + } + ], + "2": [ + { + "index": "0", + "id": "1621340721628" + }, + { + "index": "0", + "id": "1732889185927" + }, + { + "index": "0", + "id": "1717441414646" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#5CB36D", + "notes": "" + }, + { + "id": "1714752862828", + "component": "debug", + "tab": "1611921777196", + "name": "MDBToTb", + "x": 766, + "y": 324, + "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": 764.0833282470703, + "y": 222, + "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\telse if(value.status === \"NOK-thermometer\")\n\t{\n\t\tsend(0, {\"thermometer\": \"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\telse if(value.values.hasOwnProperty(\"temperature\"))\n\t{\n\t\tsend(0, {\"thermometer\": \"OK\"});\n\t}\n}", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1717442627834", + "component": "debug", + "tab": "1611921777196", + "name": "modbus service", + "x": 966.0833282470703, + "y": 165, + "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": 968.0833282470703, + "y": 268, + "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": 88.75, + "y": 1685, + "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": 296, + "y": 1671, + "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\", \"Flow has been restarted\", \"Node db has changed\"]", + "types": "[\"emergency\", \"critical\", \"error\", \"alert\"]", + "name": "" + }, + "color": "#30E193", + "notes": "" + }, + { + "id": "1718016073501", + "component": "httprequest", + "tab": "1612772287426", + "name": "http://192.168.252.2:8004/slack", + "x": 495, + "y": 1753, + "connections": { + "0": [ + { + "index": "0", + "id": "1718016086212" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "url": "http://192.168.252.2:8004/slack", + "method": "POST", + "stringify": "json" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1718016086212", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 832, + "y": 1664, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "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": 87, + "y": 1591, + "connections": { + "0": [ + { + "index": "0", + "id": "1718016052341" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "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\": \"\" } } } ] }", + "datatype": "object" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1729855334955", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "platform-rpc-call", + "x": 599.9333343505859, + "y": 541.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "platform-rpc-call", + "color": "gray" + }, + "options": { + "wirename": "platform-rpc-call" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1729855371093", + "component": "debug", + "tab": "1612772287426", + "name": "rpc cloud", + "x": 601.9333343505859, + "y": 440.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1731068658334", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 75.75, + "y": 184, + "connections": { + "0": [ + { + "index": "0", + "id": "1612776786008" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731068754606", + "component": "cloudmqttconnect", + "tab": "1612772287426", + "name": "MQTT to senica-prod01", + "x": 284.75, + "y": 452, + "connections": { + "1": [ + { + "index": "0", + "id": "1729855371093" + }, + { + "index": "0", + "id": "1729855334955" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Connected", + "color": "green" + }, + "options": { + "username": "", + "clientid": "", + "port": "2764", + "host": "192.168.252.2", + "topic": "" + }, + "color": "#888600", + "notes": "" + }, + { + "id": "1731069001548", + "component": "db_init", + "tab": "1612772287426", + "name": "DB Initialization", + "x": 1003.75, + "y": 240.25, + "connections": { + "0": [ + { + "index": "0", + "id": "1731069033416" + } + ], + "1": [ + { + "index": "0", + "id": "1747561603739" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#888600", + "notes": "" + }, + { + "id": "1731069033416", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "db-init", + "x": 1244.75, + "y": 233.25, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069059135", + "component": "showdb", + "tab": "1612772287426", + "name": "Show db data", + "x": 1186.75, + "y": 821.25, + "connections": { + "0": [ + { + "index": "0", + "id": "1731069079243" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#888600", + "notes": "" + }, + { + "id": "1731069079243", + "component": "debug", + "tab": "1612772287426", + "name": "dbData", + "x": 1390.75, + "y": 870.25, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1731069116691", + "component": "trigger", + "tab": "1612772287426", + "name": "settings", + "x": 934.75, + "y": 669.75, + "connections": { + "0": [ + { + "index": "0", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069131637", + "component": "trigger", + "tab": "1612772287426", + "name": "relaysData", + "x": 876.75, + "y": 733.75, + "connections": { + "0": [ + { + "index": "1", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069137374", + "component": "trigger", + "tab": "1612772287426", + "name": "nodesData", + "x": 852.75, + "y": 794.75, + "connections": { + "0": [ + { + "index": "2", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069179846", + "component": "trigger", + "tab": "1612772287426", + "name": "pinsData", + "x": 850.75, + "y": 861.75, + "connections": { + "0": [ + { + "index": "3", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069192937", + "component": "trigger", + "tab": "1612772287426", + "name": "sample data", + "x": 857.75, + "y": 928.75, + "connections": { + "0": [ + { + "index": "4", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069264443", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 63.75, + "y": 1279, + "connections": { + "0": [ + { + "index": "0", + "id": "1634488120710" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069334626", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "db-init", + "x": 172.88333129882812, + "y": 129, + "connections": { + "0": [ + { + "index": "0", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069548145", + "component": "virtualwirein", + "tab": "1611921777196", + "name": "db-init", + "x": 46.75, + "y": 192, + "connections": { + "0": [ + { + "index": "0", + "id": "1699965957410" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069567152", + "component": "virtualwirein", + "tab": "1611921777196", + "name": "db-init", + "x": 44.75, + "y": 465, + "connections": { + "0": [ + { + "index": "0", + "id": "1700411878636" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731070156936", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "db-init", + "x": 126.88333129882812, + "y": 1377, + "connections": { + "0": [ + { + "index": "2", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731234189516", + "component": "trigger", + "tab": "1612772287426", + "name": "monitor.txt", + "x": 882.75, + "y": 991.75, + "connections": { + "0": [ + { + "index": "5", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731234189551", + "component": "trigger", + "tab": "1612772287426", + "name": "err.txt", + "x": 904.75, + "y": 1053.75, + "connections": { + "0": [ + { + "index": "6", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1732700042559", + "component": "nodesdb_change_check", + "tab": "1612772287426", + "name": "Nodes DB change check", + "x": 266.8833312988281, + "y": 1980.2333984375, + "connections": { + "0": [ + { + "index": "0", + "id": "1732700071298" + }, + { + "index": "0", + "id": "1732700642917" + } + ], + "1": [ + { + "index": "0", + "id": "1759958914348" + }, + { + "index": "0", + "id": "1759959003114" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#888600", + "notes": "" + }, + { + "id": "1732700057052", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 76.75, + "y": 1988, + "connections": { + "0": [ + { + "index": "0", + "id": "1732700042559" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1732700071298", + "component": "debug", + "tab": "1612772287426", + "name": "nodesChange", + "x": 571.8833312988281, + "y": 2018.2333984375, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1732700642917", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "tb-push", + "x": 567.8833312988281, + "y": 1933, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1732889185927", + "component": "debug", + "tab": "1611921777196", + "name": "tempToDido", + "x": 594.8833312988281, + "y": 753, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1733574412965", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 72.75, + "y": 474, + "connections": { + "0": [ + { + "index": "1", + "id": "1731068754606" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1747561603739", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "send-to-services", + "x": 1243.8833312988281, + "y": 334.5, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1747562867845", + "component": "comment", + "tab": "1612772287426", + "name": "FLOW STARTING POINT", + "x": 1003.5666656494141, + "y": 178, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#704cff", + "notes": "" + }, + { + "id": "1749211698385", + "component": "trigger", + "tab": "1612772287426", + "name": "deviceStatus", + "x": 911.75, + "y": 1116.75, + "connections": { + "0": [ + { + "index": "7", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1757006030239", + "component": "httprequest", + "tab": "1615551125555", + "name": "192.168.252.2:8015/daily_report", + "x": 756.5666656494141, + "y": 715.4499969482422, + "connections": { + "0": [ + { + "index": "0", + "id": "1757006045804" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "stringify": "json", + "method": "POST", + "url": "http://192.168.252.2:8015/daily_report" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1757006045804", + "component": "debug", + "tab": "1615551125555", + "name": "ddd", + "x": 1091.566665649414, + "y": 711.4499969482422, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1757006060377", + "component": "debug", + "tab": "1615551125555", + "name": "reportDebug", + "x": 749.5666656494141, + "y": 799.4499969482422, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1759958914348", + "component": "httprequest", + "tab": "1612772287426", + "name": "http://192.168.252.2:8015/node_numbers", + "x": 571, + "y": 2111, + "connections": { + "0": [ + { + "index": "0", + "id": "1759958927094" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "stringify": "json", + "method": "POST", + "url": "http://192.168.252.2:8015/node_numbers" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1759958927094", + "component": "debug", + "tab": "1612772287426", + "name": "nodesChangeCloud", + "x": 951.8833312988281, + "y": 2109.2333984375, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1759959003114", + "component": "debug", + "tab": "1612772287426", + "name": "nodeChangeCloud1", + "x": 574, + "y": 2218, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1760020290879", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 84.75, + "y": 1787, + "connections": { + "0": [ + { + "index": "1", + "id": "1718016052341" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + } + ], + "version": 615 +} diff --git a/RVO42/flow/dido_controller.js b/RVO42/flow/dido_controller.js new file mode 100755 index 0000000..d16fb19 --- /dev/null +++ b/RVO42/flow/dido_controller.js @@ -0,0 +1,1486 @@ +exports.id = 'dido_controller'; +exports.title = 'DIDO_Controller'; +exports.version = '2.0.0'; +exports.group = 'Worksys'; +exports.color = '#2134B0'; +exports.input = 3; +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 + +state_of_main_switch - reportovat stav hlaveho istica : 0-> off 1-> on +rotary_switch_state - sem by sa mal reportovat stav vstupov manual a auto pola nasledovnej logiky: Manual = 1 a Auto = 0 -> Manu +Manual = 0 a Auto = 0 -> Off, Manual = 0 a Auto = 1 -> Automatic + +door_condition - pin 6, dverový kontakt -> 1 -> vyreportuje Closed, 0 -> vyreportuje Ope +twilight_sensor - hodnotu, ktoru vracia ten analogovy vstup (17) treba poslat sem ako float number. Zrejme tu potom pridame nejaky koeficient prevodu na luxy + +Na kazdu liniu +state_of_breaker - podla indexu istica sa reportuje jeho stav, teda istic na liniu 1: 0-> off, 1-> on +state_of_contactor - podla indexu stkaca sa reportuje jeho stav, teda stykac 1 na liniu 1: 0-> off, 1-> on +*/ + +const { errLogger, logger, monitor } = require('./helper/logger'); +const SerialPort = require('serialport'); +const WebSocket = require('ws'); +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 errorHandler = require('./helper/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 hasMainSwitch; + +let alarmStatus = "OFF"; + +const SEND_TO = { + debug: 0, + tb: 1, + cmd_manager: 2 +} + + +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 = {}; + let rsPortReceivedData = []; + + //to be able to get proper twilight values + let twilight_sensor_interval = 5;//minutes + let twilight_sensor = []; + const twilight_sensor_array = []; + let twilightError = false; + + monitor.info("DIDO_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-we make it global to see it from outside + FLOW.deviceStatus = { //key is device name: temperature,.... + "state_of_main_switch": "Off", //Hlavny istic (alebo druhy dverovy kontakt) + "rotary_switch_state": "Off", //Prevadzkovy + "door_condition": "closed", //Dverový kontakt + "em": "OK", //elektromer rvo + "temperature": "OK", //templomer + "battery": "OK", //Bateria + "power_supply": "OK", //Zdroj + "master_node": "OK", //MN - GLOBALS.settings.masterNodeIsResponding + "no_voltage": "OK", //GLOBALS.settings.no_voltage - vypadok napatia na faze + "state_of_breaker": {}, //"Off",//Istic + "state_of_contactor": {}, //"Off",//Stykac + "twilight_sensor": "OK" //lux sensor + }; + let deviceStatus = FLOW.deviceStatus; + + + function main() { + + GLOBALS = FLOW.GLOBALS; + SETTINGS = FLOW.GLOBALS.settings; + rvoTbName = SETTINGS.rvoTbName; + pinsData = GLOBALS.pinsData; + relaysData = GLOBALS.relaysData; + + tbHandler = new DataToTbHandler(SEND_TO.tb); + tbHandler.setSender(exports.title); + + controller_type = SETTINGS.controller_type; //"lm" or "unipi" + hasMainSwitch = SETTINGS.has_main_switch; + + if (controller_type == "") controller_type = "lm"; + + 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, "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; + } + } + + //report RVO version relaysData[0].tbname; + let values = {}; + values["edge_fw_version"] = SETTINGS.edge_fw_version; + values["maintenance_mode"] = SETTINGS.maintenance_mode; + + sendTelemetry(values, rvoTbName); + + 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); + } + + + function handleRsPort() { + + if (rsPort) { + rsPort.removeAllListeners(); + rsPort = null; + } + + //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('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) { + if (!err) { + monitor.info(exports.title + "--->Digital in_out has been set (runSyncExec was sucessfull)"); + + turnAlarm("off"); + 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('error', err => { + let message = "Dido: rsPort error: " + err.message; + logger.debug(message); + monitor.info(message); + errorHandler.sendMessageToService(message); + }) + + rsPort.on("close", () => { + let message = "Dido: rsPort closed - reconnecting ..."; + logger.debug(message); + monitor.info(message); + setTimeout(handleRsPort, 1000); + }) + + rsPort.open(); + } + + + function handleWebSocket() { + + if (ws) { + ws.removeAllListeners(); + ws = null; + } + + //to keep websocket opened, we send request every 150 seconds + let startRequests = null; + + console.log("handleWebSocket function called"); + ws = new WebSocket('ws:/0.0.0.0:1234/ws'); + + ws.onopen = function open() { + + instance.send(0, exports.title + " running"); + turnAlarm("off"); + + initialSetting(); + + setTimeout(function() { ws.send(JSON.stringify({ cmd: "all" })) }, 5000); + // we request dev info about neuron device from evok to keep websocket connection alive + // for some reason this request returns no data, but connection keeps alive + startRequests = setInterval(() => { + ws.send(JSON.stringify({ "cmd": "filter", "dev": ["neuron"] })); + }, 150000) + }; + + + // 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 = async 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; + + 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 => { + logger.debug('Dido: websocket error', err); + }) + + ws.onclose = function() { + logger.debug('Dido: websocket onclose, reconnecting...') + clearInterval(startRequests); + setTimeout(handleWebSocket, 1000); + } + } + + 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 turnAlarm(onOrOff) { + let value = 0; + if (onOrOff == "on") value = 1; + + if (value == 1 && SETTINGS.maintenance_mode) return; + + alarmStatus = "OFF"; + if (value == 1) alarmStatus = "ON"; + + if (rsPort) { + let arr = [0x55]; + arr.push(13); + arr.push(0); + arr.push(value); + + rsPort.write(Buffer.from(arr), function(err) { + logger.debug(`sirena - ${onOrOff}`); + }); + } + else if (ws) { + let cmd = { "cmd": "set", "dev": "relay", "circuit": "1_01", "value": value }; + ws.send(JSON.stringify(cmd)); + logger.debug(`sirena - ${onOrOff}`); + } + } + + + 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") { + bits.push(0); + } + else bits.push(1); + + if (deviceStatus["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); + } + + + // turn line on or off + function turnLine(onOrOff, line, pin, force, info) { + //onOrOff => "on" or "off" + let value = 0; + if (onOrOff == "on") value = 1; + + if (force == undefined) force = false; + + if (line == 0) { + if (value == 1 && alarmStatus == "ON") turnAlarm("off"); + SETTINGS.maintenance_mode = value ? true : false; + + 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); + return; + } + + if (pin === undefined) pin = getPin(line); + + if (pin === undefined) { + errLogger.error("pin is undefined!", line); + return; + } + + if (!force) { + if (relaysData[line].contactor == value) { + instance.send(SEND_TO.debug, `line is already ${onOrOff} ` + line); + logger.debug(`Dido: turnLine: line is already ${onOrOff} `, line); + return; + } + } + + // if(!rsPort.isOpen && !ws) + if (!rsPort && !ws) { + errLogger.error("Dido - port or websocket is not opened"); + return; + } + + if (rsPort) { + let arr = [0x55]; + arr.push(pin); + arr.push(0); + arr.push(value); + + rsPort.write(Buffer.from(arr), function(err) { + if (err === undefined) { + monitor.info(`Dido: turnLine ${onOrOff} zapisal do rsPort-u`, line, pin, arr, info); + switchLogic(arr); + } + else { + monitor.info(`Dido: turnLine ${onOrOff} WRITE error`, err); + } + }); + + } + else if (ws) { + //pin = "relay1_03" or "input1_01" ... we must make just "1_01" with slice method + monitor.info(`Dido: turnLine ${onOrOff} - (line, pin, force)`, line, pin, force, info); + let cmd = { "cmd": "set", "dev": "relay", "circuit": pin.slice(5), "value": value }; + ws.send(JSON.stringify(cmd)); + } + + //if rvo is 24/7, it has just one switching profile point at 13:00. we do not want to send notification as it repeats every day. + //const d = new Date(); + //if(d.getHours() != 13) sendNotification("Dido_controller: ", SETTINGS.rvoTbName, "switching_profile_point_applied_to_line", { line: line, value: onOrOff }, "", SEND_TO.tb, instance); + } + + + // 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; + + // 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) { + const status = flowdata.data.status; + if (status == "NOK-twilight_sensor") { + deviceStatus["twilight_sensor"] = "NOK"; + } + else if (status == "NOK-em340" || status == "NOK-em111") { + deviceStatus["em"] = "NOK"; + } + else if (status == "NOK-thermometer") { + deviceStatus["temperature"] = "NOK"; + } + } + else if ("values" in flowdata.data) { + 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" + } + else if (values.hasOwnProperty("temperature")) { + deviceStatus["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"; + } + + sendTelemetry(values, rvoTbName); + } + + sendRvoStatus(); + }) + + + + + // we expect array as flowdata.data + instance.on("1", flowdata => { + + //console.log(flowdata.data); + + if (!flowdata.data instanceof Object) return; + + let obj = flowdata.data; + let line = obj.line; + 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"); + }) + + + function calculateStateCode() { + + let bits = []; + + //Hlavny istic - state_of_main_switch => v rvo senica je to druhy door pre silovu cast (EM) + if (deviceStatus["state_of_main_switch"] === "closed" || deviceStatus["state_of_main_switch"] === "Off") { + bits.push(0); + } + else { + bits.push(1); + } + + //Prevadzkovy mod - Manual, Off, Automatic, maintenance_mode = true/false // DAVA 2 BITY + if (!SETTINGS.maintenance_mode) { + if (deviceStatus["rotary_switch_state"] === "Manual") { + bits.push(0); + bits.push(1); + } + + if (deviceStatus["rotary_switch_state"] === "Automatic") { + bits.push(0); + bits.push(0); + } + + if (deviceStatus["rotary_switch_state"] === "Off") { + bits.push(1); + bits.push(0); + } + } + else { + bits.push(1); + bits.push(1); + } + + //Dverovy kontakt + if (deviceStatus["door_condition"] === "closed") { + bits.push(0); + } + else { + bits.push(1); + } + + //EM + if (deviceStatus["em"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //Teplomer + if (deviceStatus["temperature"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //Batéria + if (deviceStatus["battery"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //Zdroj + if (deviceStatus["power_supply"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //MN + if (deviceStatus["master_node"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //výpadok napätia na fáze + if (deviceStatus["no_voltage"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + if (deviceStatus["twilight_sensor"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + // doplnime do 16 bitov (2 byty) + for (let i = bits.length; i < 16; i++) { + bits.push(0); + } + + // console.log("calculateStateCode - deviceStatus", deviceStatus); + // 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; + } + + + async function sendRvoStatus() { + + if (SETTINGS === undefined) return; + SETTINGS.masterNodeIsResponding ? deviceStatus["master_node"] = "OK" : deviceStatus["master_node"] = "NOK"; + + 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 pinsForRvoStatus(controllerType, hasMainSwitch) { + + let pins = []; + + if (controllerType === "lm") { + pins = [1, 4, 6]; + if (hasMainSwitch === 1) { + pins = [4, 6]; + } + } else if (controllerType === "unipi") { + pins = ["input1_01", "input1_04", "input1_05"]; + if (hasMainSwitch === 1) { + pins = ["input1_01", "input1_04"]; + } + } + + return pins; + } + + + function checkRvoStatus() { + + // 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 + //set RVO state + let status = "OK"; + + for (const [key, value] of Object.entries(deviceStatus)) { + if (["em", "twilight_sensor", "temperature", "master_node"].includes(key) && value === "NOK") status = "NOK"; + } + + if (status === "OK") { + + let pinIndexes = pinsForRvoStatus(controller_type, hasMainSwitch); + + for (const pinIndex of pinIndexes) { + if (previousValues[pinIndex] === 0) { + if ((pinIndex === 6 || pinIndex === 'input1_01' || pinIndex === 'input1_05') && SETTINGS.maintenance_mode) continue; + status = "NOK"; + break; + } + } + } + + // battery status. If value is 1 - battery is NOK + if (previousValues[5] === 1) status = "NOK"; + if (SETTINGS.no_voltage.size > 0) status = "NOK"; + + // console.log("rvo status",status) + return status; + } + + + // we pass array to function in case of rsPort ==> switchLogic([55,3,0,1]) ==> [[55,3,0,1]] + // we pass two values in case of websocket ==> switchLogic("relay1_03",1) ==> ["relay1_03",1] + const switchLogic = (...args) => { + + let values = {}; + let pinIndex, newPinValue, twilight; + + //data from rsPort + if (args.length == 1) { + pinIndex = args[0][1] + 1; + if (pinIndex === 17) pinIndex--; + newPinValue = args[0][3]; + twilight = args[0][2]; + } + //data from websocket + else { + pinIndex = args[0]; + newPinValue = args[1]; + } + + 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; + + //default value + let value = "On"; + if (newPinValue === 0) value = "Off"; + + //Hlavny istic + if (type === "state_of_main_switch" && hasMainSwitch) { + if (newPinValue === 0 && newPinValue !== previousValues[pinIndex]) { + sendNotification("switchLogic", rvoTbName, "main_switch_has_been_turned_off", {}, "", SEND_TO.tb, instance, "state_of_main_switch"); + 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"); + deviceStatus["state_of_main_switch"] = "On"; + } + } + + //Prevadzkovy mod + 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"; + + deviceStatus["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, "power_supply_has_disconnected_input", {}, "", SEND_TO.tb, instance, "power_supply"); + + deviceStatus["power_supply"] = "NOK"; + } + else if (newPinValue === 1 && newPinValue !== previousValues[pinIndex]) { + sendNotification("switchLogic", rvoTbName, "power_supply_works_correctly", {}, "", SEND_TO.tb, instance, "power_supply"); + + deviceStatus["power_supply"] = "OK"; + } + } + + //Bateria - 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"); + + deviceStatus["battery"] = "NOK"; + } + else if (newPinValue === 0 && newPinValue !== previousValues[pinIndex]) { + sendNotification("switchLogic", rvoTbName, "battery_level_is_ok", {}, "", SEND_TO.tb, instance, "battery_level"); + + deviceStatus["battery"] = "OK"; + } + } + + //Dverovy kontakt - pin 6 + //! Ak je rvo s dvoma dverovymi kontaktami, ked pride z evoku signal z input1_05, co bol predytm "state_of_main switch" handlujeme ho teraz ako 'door_condition' + else if (type == "door_condition" || type === "state_of_main_switch") { + newPinValue === 0 ? value = "open" : value = "closed"; + + let door = "door_main"; + if (type === "state_of_main_switch") door = "door_em"; + + if (value === "open") { + if (SETTINGS.maintenance_mode) { + sendNotification("switchLogic", rvoTbName, door + "_open", {}, "", SEND_TO.tb, instance, door); + } else { + sendNotification("switchLogic", rvoTbName, door + "_open_without_permission", {}, "", SEND_TO.tb, instance, door); + + // 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 (value === "closed") { + if (alarmStatus == "ON") turnAlarm("off"); + sendNotification("switchLogic", rvoTbName, door + "_close", {}, "", SEND_TO.tb, instance, door); + } + + deviceStatus[type] = value; + } + + //lux sensor + else if (type == "twilight_sensor") { + //! TODO - to show nok status, if lux value is not changing more then 10 times. + //Daylight is far more than 1000. So most of the day, when it is sunshine comes just value 1000. But lux sensor is not NOK. + //This is not the case in LM. If value from LM is the same 10x, there is 99% possibility, that sensor is NOK. + value = newPinValue; + + if (controller_type === 'lm') { + value = parseFloat(newPinValue + (256 * twilight)); + + 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 && !twilightError) { + twilightError = true; + let value = twilight_sensor_array.shift(); + + newPinValue = 0; + } + else if (set.size !== 1 && twilightError) { + //sendNotification("switchLogic", rvoTbName, 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) { + 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); + } + } + + 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); + } + + deviceStatus["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 (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 }); + + //mame iba 3 istice. vyreportujeme a ohandlujeme liniu na tom istom istici ako paralelna linia (napr linia 1, paralelna s nou je linia 4, key je string "4") + // ak je 7 linii, na 1 istici je linia 1,4,7 + + if (line == 1) { + + const lineOnSameBraker = [4, 7]; + + for (var i = 0; i < lineOnSameBraker.length; i++) { + if (!relaysData.hasOwnProperty(lineOnSameBraker[i])) continue; + + 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; + reportLineStatus(lineOnSameBraker[i]); + + values[type] = value; + const tbname = relaysData[lineOnSameBraker[i]].tbname; + sendTelemetry(values, tbname); + + delete values[type]; + } + + } + else { + const lineOnSameBraker = line + 3 + ""; + + if (relaysData.hasOwnProperty(lineOnSameBraker)) { + 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; + reportLineStatus(line + 3); + + values[type] = value; + const tbname = relaysData[lineOnSameBraker].tbname; + sendTelemetry(values, tbname); + + delete values[type]; + } + } + + } + + if (value == "Off") values["status"] = "NOK"; + deviceStatus["state_of_breaker"][line] = value; + + reportLineStatus(line); + } + else return; + + values[type] = value; + + if (type == "rotary_switch_state") { + if (SETTINGS.maintenance_mode) value = "maintenance"; + value = value.toLowerCase(); + values["power_mode"] = value; + } + + if (newPinValue != previousValues[pinIndex]) previousValues[pinIndex] = newPinValue; + if (Object.keys(values).length > 0 && tbname) sendTelemetry(values, tbname); + } + + + function sendTelemetry(values, tbname, date = Date.now()) { + let dataToTb = { + [tbname]: [ + { + "ts": date, + "values": values + } + ] + }; + + tbHandler.sendToTb(dataToTb, instance); + } + + + function isObject(item) { + return (typeof item === "object" && !Array.isArray(item) && item !== null); + } + +} //end of 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 +// *|input1_01|state_of_main_switch|0|........... +// *|input1_02|rotary_switch_state|0|........... +// *|input1_03|rotary_switch_state|0|........... +// *|intut1_04|power_supply|0|........... +// *|input1_05|door_condition|0|........... +// *|input1_06|state_of_breaker|1|........... +// *|input1_07|state_of_breaker|2|........... +// *|input1_08|state_of_breaker|3|........... +// *|relay1_02|state_of_contactor|1|........... +// *|relay1_03|state_of_contactor|2|........... +// *|relay1_04|state_of_contactor|3|........... +// *|287D8776E0013CE9|temperature|0|........... + + +//! pins_data --> from UNIPI +// { +// 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 } +// } + +//! relays_data +// { +// '0': { +// line: 0, +// tbname: 'KjbN4q7JPZmexgdnz2yKQ98YAWwO0Q3BMX6ERLoV', +// contactor: 1, +// profile: '' +// }, +// '1': { +// line: 1, +// tbname: 'RMgnK93rkoAazbqdQ4yBG95Z1YXGx6pmwBeVEP2O', +// contactor: 0, +// profile: '{"intervals":[{"value":0,"end_time":"20:00","start_time":"13:00"},{"value":1,"end_time":"10:00","start_time":"20:00"},{"value":0,"end_time":"10:20","start_time":"10:00"},{"value":1,"end_time":"10:40","start_time":"10:20"},{"value":0,"end_time":"11:00","start_time":"10:40"},{"value":1,"end_time":"11:30","start_time":"11:00"},{"value":0,"end_time":"11:50","start_time":"11:30"},{"value":1,"end_time":"13:00","start_time":"11:50"}],"astro_clock":false,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' +// }, +// '2': { +// line: 2, +// tbname: 'dlE1VQjYrNx9gZRmb38gG08oLBO4qaAk2M6JPnG7', +// contactor: 0, +// profile: '{"intervals":[{"value":0,"end_time":"20:00","start_time":"13:00"},{"value":1,"end_time":"10:00","start_time":"20:00"},{"value":0,"end_time":"10:20","start_time":"10:00"},{"value":1,"end_time":"10:40","start_time":"10:20"},{"value":0,"end_time":"11:00","start_time":"10:40"},{"value":1,"end_time":"11:30","start_time":"11:00"},{"value":0,"end_time":"11:50","start_time":"11:30"},{"value":1,"end_time":"13:00","start_time":"11:50"}],"astro_clock":false,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' +// }, +// '3': { +// line: 3, +// tbname: 'vnmG4kJxaXWNBgMQq0D7Aj5e9oZzOAlr6LdR3w2V', +// contactor: 0, +// profile: '{"intervals":[{"value":0,"end_time":"20:30","start_time":"13:00"},{"value":1,"end_time":"00:10","start_time":"20:30"},{"value":0,"end_time":"13:00","start_time":"05:40"},{"value":1,"end_time":"05:40","start_time":"00:10"}],"astro_clock":true,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' +// } +// } + + + + + +// { +// "jbN4q7JPZmexgdnz2yKbWGDYAWwO0Q3BMX6ERLoV": [ +// { +// "ts": 1700409326353, +// "values": { +// "_event": { +// "type": "notice", +// "status": "new", +// "source": { +// "func": "rsPort.open()", +// "component": "1700343402190", +// "component_name": "DIDO_Controller", +// "edge": "jbN4q7JPZmexgdnz2yKbWGDYAWwO0Q3BMX6ERLoV" +// }, +// "message": "al_shariff_10.0.0.38: FLOW has been started ", +// "message_data": "" +// } +// } +// } +// ] +// } diff --git a/RVO42/flow/helper/DataToTbHandler.js b/RVO42/flow/helper/DataToTbHandler.js new file mode 100755 index 0000000..716ef7b --- /dev/null +++ b/RVO42/flow/helper/DataToTbHandler.js @@ -0,0 +1,187 @@ +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; + this.itIsNodeReadout = false; + this.sender = ""; + + // if attribute change difference is less than limit value, we do not send to tb. + this.attributeChangeLimit = { + temperature: 0.5, + Phase_1_voltage: 2, + Phase_2_voltage: 2, + Phase_3_voltage: 2, + Phase_1_current: 0.1, + Phase_2_current: 0.1, + Phase_3_current: 0.1, + Phase_1_power: 2, + Phase_2_power: 2, + Phase_3_power: 2, + total_power: 2, + total_energy: 1, + Phase_1_pow_factor: 0.1, + Phase_2_pow_factor: 0.1, + Phase_3_pow_factor: 0.1, + power_factor: 0.1, + lifetime: 2, + voltage: 2, + power: 2, + frequency: 3, + energy: 0.1, + current: 2, + inclination_x: 10, + inclination_y: 10, + inclination_z: 10 + }; + + } + + dump() { + console.log("----------------------------"); + console.log("previousValues", this.previousValues); + console.log("----------------------------"); + } + + setSender(sender) { + this.sender = sender; + } + + isEmptyObject(obj) { + for (var _ in obj) { + return false; + } + return true; + } + + + sendToTb(data, instance) { + + //not to modify data object, we do deep copy: + let dataCopy = JSON.parse(JSON.stringify(data)); + + let keys = Object.keys(dataCopy); + + if (keys.length == 0) { + if (this.debug) console.log("sendToTb received empty object", dataCopy); + return; + } + + let tbname = keys[0]; + let ts; + + let arrayOfValues = dataCopy[tbname]; + let arrayOfValuesToSend = []; + + for (let i = 0; i < arrayOfValues.length; i++) { + + ts = arrayOfValues[i].ts; + let values = this.prepareValuesForTb(tbname, ts, arrayOfValues[i].values); + + if (!this.isEmptyObject(values)) { + arrayOfValuesToSend.push({ ts: ts, values: values }); + } + + } + + if (arrayOfValuesToSend.length == 0) { + //if(this.debug) console.log("data not sent - empty array"); + return; + } + + this.messageCounter++; + + let dataToTbModified = { + [tbname]: arrayOfValuesToSend + } + + //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); + instance.send(this.index, dataToTbModified); + } + + + getDiffTimestamp(key) { + //TODO set different value for given key!!! + //if(key == "status") this.timeToHoldTbValue = 2*60*60;//2h + return this.timeToHoldTbValue * 1000; + } + + + prepareValuesForTb(tbname, timestamp, values) { + + let keys = Object.keys(values); + + if (keys.includes("lifetime")) this.itIsNodeReadout = true; + + if (!this.previousValues.hasOwnProperty(tbname)) { + this.previousValues[tbname] = {}; + } + + //if(this.debug) console.log("prepareValuesForTb", tbname, timestamp, values); + + for (let i = 0; i < keys.length; i++) { + + let key = keys[i]; + let value = values[key]; + + if (!this.previousValues[tbname].hasOwnProperty(key)) { + this.previousValues[tbname][key] = { ts: timestamp, value: value }; + continue; + } + + // attributeData ==> {voltage: {ts:333333, value:5}} + let attributeData = this.previousValues[tbname][key]; + let attributeToChange = false; + if (key in this.attributeChangeLimit) attributeToChange = true; + let limit = this.attributeChangeLimit[key]; + let timestampDiffToRemoveKey; + + //this will ensure "node statecode" will be sent just once an hour + if (this.itIsNodeReadout && key === "statecode") { + attributeData.value = value; + this.itIsNodeReadout = false; + timestampDiffToRemoveKey = 1 * 60 * 60 * 1000; // 1 hour + } + + if (key === "twilight_sensor" && value > 100) { + attributeData.value = value; + } + + //if edge, master or node version do not change, send just once a day: + if (["edge_fw_version", "master_node_version", "fw_version"].includes(key)) { + timestampDiffToRemoveKey = 24 * 60 * 60 * 1000; + } + + if (attributeData.value === value || attributeToChange && Math.abs(attributeData.value - value) < limit) { + + let diff = timestamp - attributeData.ts; + if (!timestampDiffToRemoveKey) timestampDiffToRemoveKey = this.getDiffTimestamp(key); + + if (diff > timestampDiffToRemoveKey) { + attributeData.ts = Date.now(); + //if(this.debug) console.log(this.sender + ": update ts for key", key, "diff is", diff, "messageCounter", this.messageCounter); + } + else { + delete values[key]; + //if(this.debug) console.log(this.sender + ": delete key", key, "diff is", diff, "messageCounter", this.messageCounter, timestampDiffToRemoveKey); + } + } + else { + attributeData.value = value; + attributeData.ts = timestamp; + } + + } + + return values; + } +} + +module.exports = DataToTbHandler; + diff --git a/RVO42/flow/helper/ErrorToServiceHandler.js b/RVO42/flow/helper/ErrorToServiceHandler.js new file mode 100755 index 0000000..2b27c32 --- /dev/null +++ b/RVO42/flow/helper/ErrorToServiceHandler.js @@ -0,0 +1,91 @@ +const { MD5 } = require('./md5.js'); +const { networkInterfaces } = require('os'); + +class ErrorToServiceHandler { + constructor() { + this.previousValues = {}; + + this.project_id = undefined; + + const nets = networkInterfaces(); + this.ipAddresses = {}; + + for (const name of Object.keys(nets)) { + for (const net of nets[name]) { + // Skip over non-IPv4 and internal (i.e. 127.0.0.1) addresses + if (net.family === 'IPv4' && !net.internal) { + if (!this.ipAddresses[name]) { + this.ipAddresses[name] = []; + } + this.ipAddresses[name].push(net.address); + } + } + } + } + + setProjectId(project_id) { + this.project_id = project_id; + } + + processMessage(message, seconds) { + if (Array.isArray(message)) message = message.join(', '); + + let key = MD5(message); + let ts = Date.now(); + + //keep in memory - default value is 1h + if (seconds === undefined) seconds = 60 * 60; + + if (!this.previousValues.hasOwnProperty(key)) { + this.previousValues[key] = { ts: ts, duration: seconds }; + } + + let diff = (ts - this.previousValues[key].ts); + if (diff < this.previousValues[key].duration * 1000) return false; + + this.previousValues[key].ts = ts; + + return message; + } + + sendMessageToService(message, seconds, message_type) { + + // if error occures too early FLOW.GLOBALS.settings.project_id is still undefined + if (this.project_id === undefined) { + console.log("ErrorToServiceHandler.js: no project_id"); + return; + } + + let f = this.processMessage(message, seconds); + if (f === false) return; + + if (message_type === undefined) message_type = "error_message"; + + let toService = { + id: this.project_id, + ipAddresses: this.ipAddresses + }; + + //js_error || error_message + toService[message_type] = message; + + console.log("ErrorToServiceHandler------------------------>send to service", toService); + + RESTBuilder.make(function(builder) { + builder.method('POST'); + builder.post(toService); + builder.url('http://192.168.252.2:8004/sentmessage'); + + builder.callback(function(err, response, output) { + console.log("process.on error send", err, response, output, toService); + }); + }); + + } +} + +const errorHandler = new ErrorToServiceHandler(); + + +module.exports = errorHandler; +//module.exports = ErrorToServiceHandler; diff --git a/RVO42/flow/helper/db_helper.js b/RVO42/flow/helper/db_helper.js new file mode 100755 index 0000000..40e796c --- /dev/null +++ b/RVO42/flow/helper/db_helper.js @@ -0,0 +1,44 @@ +function promisifyBuilder(builder) +{ + return new Promise((resolve, reject) => { + + try{ + + builder.callback(function(err, response) { + + if(err != null) reject(err); + resolve(response); + }); + + } catch (error) { + reject(error); + } + }) +} + +function makeMapFromDbResult(response, ...keys) +{ + let s = "-"; + let data = {}; + + for(let i = 0; i < response.length; i++) + { + let record = response[i]; + + let k = []; + for(let j = 0; j < keys.length; j++) + { + k.push( record[keys[j]] ); + } + + let key = k.join(s); + data[ key ] = record; + } + + return data; +} + +module.exports = { + promisifyBuilder, + makeMapFromDbResult + } \ No newline at end of file diff --git a/RVO42/flow/helper/logger.js b/RVO42/flow/helper/logger.js new file mode 100755 index 0000000..2585639 --- /dev/null +++ b/RVO42/flow/helper/logger.js @@ -0,0 +1,30 @@ +//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/RVO42/flow/helper/md5.js b/RVO42/flow/helper/md5.js new file mode 100755 index 0000000..d3b0480 --- /dev/null +++ b/RVO42/flow/helper/md5.js @@ -0,0 +1,5 @@ +function MD5(d){var r = M(V(Y(X(d),8*d.length)));return r.toLowerCase()};function M(d){for(var _,m="0123456789ABCDEF",f="",r=0;r>>4&15)+m.charAt(15&_);return f}function X(d){for(var _=Array(d.length>>2),m=0;m<_.length;m++)_[m]=0;for(m=0;m<8*d.length;m+=8)_[m>>5]|=(255&d.charCodeAt(m/8))<>5]>>>m%32&255);return _}function Y(d,_){d[_>>5]|=128<<_%32,d[14+(_+64>>>9<<4)]=_;for(var m=1732584193,f=-271733879,r=-1732584194,i=271733878,n=0;n>16)+(_>>16)+(m>>16)<<16|65535&m}function bit_rol(d,_){return d<<_|d>>>32-_} + +module.exports = { + MD5 +} \ No newline at end of file diff --git a/RVO42/flow/helper/notification_reporter.js b/RVO42/flow/helper/notification_reporter.js new file mode 100755 index 0000000..839c12c --- /dev/null +++ b/RVO42/flow/helper/notification_reporter.js @@ -0,0 +1,121 @@ +//key is device, value = message {} +let sentValues = {}; +let notificationsData = null; +let rvoName; + +//sendNotification("CMD Manager: process cmd", SETTINGS.rvoTbName, "dimming_profile_was_successfully_received_by_node", { node: node }, "", SEND_TO.tb, instance); + +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 +}; + +function getKey(map, val) { + return Object.keys(map).findItem(key => map[key] === val); +} + +//https://stackoverflow.com/questions/41117799/string-interpolation-on-variable +var template = (tpl, args) => tpl.replace(/\${(\w+)}/g, (_, v) => args[v]); + + +function initNotification() { + notificationsData = FLOW.GLOBALS.notificationsData; + rvoName = FLOW.GLOBALS.settings.rvo_name; +} + + +function sendNotification(func, device, key, params, extra, tb_output, instance, saveKey) { + + let storeToSendValues = true; + if (saveKey == undefined) storeToSendValues = false; + + let weight = ""; + let message = {}; + + let notification = notificationsData[key]; + + if (notification) { + weight = notification.weight.toLowerCase(); + + Object.keys(notification).forEach(item => { + if (["en", "sk", "de", "cz", "it", "es"].includes(item)) { + message[item] = rvoName + ": " + template(notification[item], params); + } + }) + } + else { + //console.error("sendNotification: Notifications: undefined key", key, func, notificationsData); + console.error("sendNotification: Notifications: undefined key", key, func); + return false; + } + + //detect invalid err weight + if (getKey(ERRWEIGHT, weight) == undefined) { + console.error("sendNotification: Notifications: undefined weight", weight, key, func); + return false; + } + + if (sentValues.hasOwnProperty(saveKey)) { + if (JSON.stringify(sentValues[saveKey]) == JSON.stringify(message)) { + return false; + } + } + + if (sentValues[saveKey] == undefined) { + if (storeToSendValues) { + //do not send - flow is was started + sentValues[saveKey] = message; + return false; + } + } + + if (storeToSendValues) sentValues[saveKey] = message; + + let content = { + "type": weight, + "status": "new", + "source": { + "func": func, + "component": instance.id, + "component_name": instance.name, + "edge": device + }, + "message": message, + "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 + + return true; + +} + +module.exports = { + sendNotification, + ERRWEIGHT, + initNotification +} + diff --git a/RVO42/flow/helper/register.js b/RVO42/flow/helper/register.js new file mode 100755 index 0000000..fc1d008 --- /dev/null +++ b/RVO42/flow/helper/register.js @@ -0,0 +1,144 @@ +/* +0 - cislo registra / prikaz +1 - recepient - 0 = master, 1 = slave (slave je automaticky group a broadcast) +2 - r/rw - read/write +3- register name - nazov registra / prikazu (len pre info - zobrazenie v aplikacii) + +4,5,6,7, - jednotlive byte-y - nazov byte-u +4-7 - RES. a prazdny string "" sa nezobrazia!!! +*/ + +//124 zaznamov +const registers = [ + ["0","1","R","Status","","",""], + ["1","1","RW","Dimming","R-Channel ","G-Channel","B-Channel ","W - Channel"], + ["2","1","R","Device types","","",".",""], + ["3","1","RW","Group addresses 1-4","Groups Add. 4","Groups Add. 3","Groups Add. 2","Groups Add. 1"], + ["4","1","RW","Group addresses 5-8","Groups Add. 8","Groups Add. 7","Groups Add. 6","Groups Add. 5"], + ["5","1","RW","Serial number (MAC)","","","",""], + ["6","1","RW","Time of dusk","HH","MM","SS","EXTRA"], + ["7","1","RW","Time of dawn","HH","MM","SS","EXTRA"], + ["8","1","RW","Time Schedule settings","TBD","TBD","Movement sensor","Time Schedule"], + ["9","1","RW","TS1 Time point 1","HH","MM","SS","Ext. Device"], + ["10","1","RW","TS1 Time point 1 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["11","1","RW","TS1 Time point 2","HH","MM","SS","Ext. Device"], + ["12","1","RW","TS1 Time point 2 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["13","1","RW","TS1 Time point 3","HH","MM","SS","Ext. Device"], + ["14","1","RW","TS1 Time point 3 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["15","1","RW","TS1 Time point 4","HH","MM","SS","Ext. Device"], + ["16","1","RW","TS1 Time point 4 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["17","1","RW","TS1 Time point 5","HH","MM","SS","Ext. Device"], + ["18","1","RW","TS1 Time point 5 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["19","1","RW","TS1 Time point 6","HH","MM","SS","Ext. Device"], + ["20","1","RW","TS1 Time point 6 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["21","1","RW","TS1 Time point 7","HH","MM","SS","Ext. Device"], + ["22","1","RW","TS1 Time point 7 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["23","1","RW","TS1 Time point 8","HH","MM","SS","Ext. Device"], + ["24","1","RW","TS1 Time point 8 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["25","1","RW","TS1 Time point 9","HH","MM","SS","Ext. Device"], + ["26","1","RW","TS1 Time point 9 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["27","1","RW","TS1 Time point 10","HH","MM","SS","Ext. Device"], + ["28","1","RW","TS1 Time point 10 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["29","1","RW","TS1 Time point 11","HH","MM","SS","Ext. Device"], + ["30","1","RW","TS1 Time point 11 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["31","1","RW","TS1 Time point 12","HH","MM","SS","Ext. Device"], + ["32","1","RW","TS1 Time point 12 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["33","1","RW","TS1 Time point 13","HH","MM","SS","Ext. Device"], + ["34","1","RW","TS1 Time point 13 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["35","1","RW","TS1 Time point 14","HH","MM","SS","Ext. Device"], + ["36","1","RW","TS1 Time point 14 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["37","1","RW","TS1 Time point 15","HH","MM","SS","Ext. Device"], + ["38","1","RW","TS1 Time point 15 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["39","1","RW","TS1 Time point 16","HH","MM","SS","Ext. Device"], + ["40","1","RW","TS1 Time point 16 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["41","1","RW","TS2 Time point 1","HH","MM","SS","Ext. Device"], + ["42","1","RW","TS2 Time point 1 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["43","1","RW","TS2 Time point 2","HH","MM","SS","Ext. Device"], + ["44","1","RW","TS2 Time point 2 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["45","1","RW","TS2 Time point 3","HH","MM","SS","Ext. Device"], + ["46","1","RW","TS2 Time point 3 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["47","1","RW","TS2 Time point 4","HH","MM","SS","Ext. Device"], + ["48","1","RW","TS2 Time point 4 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["49","1","RW","TS2 Time point 5","HH","MM","SS","Ext. Device"], + ["50","1","RW","TS2 Time point 5 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["51","1","RW","TS2 Time point 6","HH","MM","SS","Ext. Device"], + ["52","1","RW","TS2 Time point 6 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["53","1","RW","TS2 Time point 7","HH","MM","SS","Ext. Device"], + ["54","1","RW","TS2 Time point 7 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["55","1","RW","TS2 Time point 8","HH","MM","SS","Ext. Device"], + ["56","1","RW","TS2 Time point 8 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["57","1","RW","TS2 Time point 9","HH","MM","SS","Ext. Device"], + ["58","1","RW","TS2 Time point 9 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["59","1","RW","TS2 Time point 10","HH","MM","SS","Ext. Device"], + ["60","1","RW","TS2 Time point 10 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["61","1","RW","TS2 Time point 11","HH","MM","SS","Ext. Device"], + ["62","1","RW","TS2 Time point 11 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["63","1","RW","TS2 Time point 12","HH","MM","SS","Ext. Device"], + ["64","1","RW","TS2 Time point 12 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["65","1","RW","TS2 Time point 13","HH","MM","SS","Ext. Device"], + ["66","1","RW","TS2 Time point 13 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["67","1","RW","TS2 Time point 14","HH","MM","SS","Ext. Device"], + ["68","1","RW","TS2 Time point 14 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["69","1","RW","TS2 Time point 15","HH","MM","SS","Ext. Device"], + ["70","1","RW","TS2 Time point 15 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["71","1","RW","TS2 Time point 16","HH","MM","SS","Ext. Device"], + ["72","1","RW","TS2 Time point 16 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["73","1","RW","Power meter status","TBD","","",""], + ["74","1","R","Input Voltage","","","",""], + ["75","1","R","Input Current","","","",""], + ["76","1","R","Input Power","","","",""], + ["77","1","R","Cos phi","","","",""], + ["78","1","R","Frequency","","","",""], + ["79","1","RW","Energy","","","",""], + ["80","1","RW","Lifetime","","","",""], + ["81","1","RW","Power on cycles (input)","","","",""], + ["82","1","RW","Power on cycles (relay)","","","",""], + ["83","1","R","Time since last power on","","","",""], + ["84","1","R","Accelerometer data","","","",""], + ["85","1","RW","GPS latitude","pos/neg","deg","min ","sec"], + ["86","1","RW","GPS longitude","pos/neg","deg","min ","sec"], + ["87","1","RW","Actual time","HH","MM","SS","RES."], + ["88","1","RW","Actual date","Day of week","Day","Month","Year"], + ["89","1","R","Production data 1","","","",""], + ["90","1","R","Production data 2","","","",""], + ["91","1","RW","Network ID","NID3","NID2","NID1","NID0"], + ["95","1","RW","Actual Lux level from cabinet","RES.","RES.","HB","LB"], + ["96","1","RW","Threshold lux level","Dusk HB","Dusk LB","Dawn HB","Dawn LB"], + ["97","1","RW","Adjust period","Dusk HB","Dusk LB","Dawn HB","Dawn LB"], + ["98","1","RW","Offset","RES.","RES.","Dusk","Dawn"], + ["99","1","RW","CCT min/max range","max-H","max-L","min-H","min-L"], + ["100","1","RW","DALI interface","Cmd ID","Add","Cmd","Resp"], + ["101","1","RW","Module FW ver","v1","v2","v3","v4"], + ["102","1","RW","Module MAC-H","unused","unused","M1","M2"], + ["103","1","RW","Module MAC-L","M3","M4","M5","M6"], + ["122","1","R","FW update status/control register","Byte3","Byte2","Byte1","Byte0"], + ["123","1","R","FW update - data index","Byte3","Byte2","Byte1","Byte0"], + ["124","1","R","FW update - data","Byte3","Byte2","Byte1","Byte0"], + ["0","0","R","Status","","","",""], + ["1","0","RW","Control register","RES.","RES.","RES.","init mode enable"], + ["2","0","R","Device types","","","",""], + ["3","0","R","Serial number (MAC)","","","",""], + ["4","0","R","Production data 1","","","",""], + ["5","0","R","Production data 2","","","",""], + ["6","0","RW","Network ID","NID3","NID2","NID1","NID0"], + ["7","0","RW","RS232 settings","param.","param.","Baudrate H","Baudrate L"], + ["8","0","R","Accelerometer data","","","",""], + ["9","0","RW","Module FW ver","v1","v2","v3","v4"], + ["10","0","RW","Module MAC-H","unused","unused","M1","M2"], + ["11","0","RW","Module MAC-L","M3","M4","M5","M6"], + ["32","0","RW","FW update status/control register","Byte3","Byte2","Byte1","Byte0"], + ["33","0","RW","FW update - data index","Byte3","Byte2","Byte1","Byte0"], + ["34","0","RW","FW update - data","Byte3","Byte2","Byte1","Byte0"], + ["125","0","RW","Debug Register","Byte3","Byte2","Byte1","Byte0"], + ["126","0","RW","Network Control Register","Byte3","Byte2","Byte1","Byte0"], + ["127","0","R","Network Status Register","Byte3","Byte2","Byte1","Byte0"], + ["128","0","RW","Node XX Serial Number Register","SER3","SER2","SER1","SER0"], + ["256","0","R","Node XX Network Status Register","","","",""] +]; + +let register = {}; + +module.exports = { + registers, + register +} \ No newline at end of file diff --git a/RVO42/flow/helper/serialport_helper.js b/RVO42/flow/helper/serialport_helper.js new file mode 100755 index 0000000..7f5920d --- /dev/null +++ b/RVO42/flow/helper/serialport_helper.js @@ -0,0 +1,99 @@ +const { exec } = require('child_process'); + +function openPort(port) { + return new Promise((resolve, reject) => { + + var callbackError = function(err) { + port.removeListener('error', callbackError); + port.removeListener('open', callbackError); + + reject(err.message); + }; + + var callbackOpen = function(data) { + port.removeListener('error', callbackError); + port.removeListener('open', callbackOpen); + + resolve("port open: ok"); + }; + + port.on('error', callbackError); + port.on('open', callbackOpen); + + port.open(); + + }) +} + +function runSyncExec(command) { + return new Promise((resolve, reject) => { + + exec(command, (error, stdout, stderr) => { + if (error == null) resolve(stdout); + reject(error); + }); + + }) +} + +async function writeData(port, data, readbytes, timeout) { + return new Promise((resolve, reject) => { + + // 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) { + + port.write(Buffer.from(data), function(err) { + if (err) { + reject(err.message); + } + }); + + 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 +} diff --git a/RVO42/flow/helper/suncalc.js b/RVO42/flow/helper/suncalc.js new file mode 100755 index 0000000..c9ca56d --- /dev/null +++ b/RVO42/flow/helper/suncalc.js @@ -0,0 +1,317 @@ +/* + (c) 2011-2015, Vladimir Agafonkin + SunCalc is a JavaScript library for calculating sun/moon position and light phases. + https://github.com/mourner/suncalc +*/ + +(function () { 'use strict'; + +// shortcuts for easier to read formulas + +var PI = Math.PI, + sin = Math.sin, + cos = Math.cos, + tan = Math.tan, + asin = Math.asin, + atan = Math.atan2, + acos = Math.acos, + rad = PI / 180; + +// sun calculations are based on http://aa.quae.nl/en/reken/zonpositie.html formulas + + +// date/time constants and conversions + +var dayMs = 1000 * 60 * 60 * 24, + J1970 = 2440588, + J2000 = 2451545; + +function toJulian(date) { return date.valueOf() / dayMs - 0.5 + J1970; } +function fromJulian(j) { return new Date((j + 0.5 - J1970) * dayMs); } +function toDays(date) { return toJulian(date) - J2000; } + + +// general calculations for position + +var e = rad * 23.4397; // obliquity of the Earth + +function rightAscension(l, b) { return atan(sin(l) * cos(e) - tan(b) * sin(e), cos(l)); } +function declination(l, b) { return asin(sin(b) * cos(e) + cos(b) * sin(e) * sin(l)); } + +function azimuth(H, phi, dec) { return atan(sin(H), cos(H) * sin(phi) - tan(dec) * cos(phi)); } +function altitude(H, phi, dec) { return asin(sin(phi) * sin(dec) + cos(phi) * cos(dec) * cos(H)); } + +function siderealTime(d, lw) { return rad * (280.16 + 360.9856235 * d) - lw; } + +function astroRefraction(h) { + if (h < 0) // the following formula works for positive altitudes only. + h = 0; // if h = -0.08901179 a div/0 would occur. + + // formula 16.4 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + // 1.02 / tan(h + 10.26 / (h + 5.10)) h in degrees, result in arc minutes -> converted to rad: + return 0.0002967 / Math.tan(h + 0.00312536 / (h + 0.08901179)); +} + +// general sun calculations + +function solarMeanAnomaly(d) { return rad * (357.5291 + 0.98560028 * d); } + +function eclipticLongitude(M) { + + var C = rad * (1.9148 * sin(M) + 0.02 * sin(2 * M) + 0.0003 * sin(3 * M)), // equation of center + P = rad * 102.9372; // perihelion of the Earth + + return M + C + P + PI; +} + +function sunCoords(d) { + + var M = solarMeanAnomaly(d), + L = eclipticLongitude(M); + + return { + dec: declination(L, 0), + ra: rightAscension(L, 0) + }; +} + + +var SunCalc = {}; + + +// calculates sun position for a given date and latitude/longitude + +SunCalc.getPosition = function (date, lat, lng) { + + var lw = rad * -lng, + phi = rad * lat, + d = toDays(date), + + c = sunCoords(d), + H = siderealTime(d, lw) - c.ra; + + return { + azimuth: azimuth(H, phi, c.dec), + altitude: altitude(H, phi, c.dec) + }; +}; + + +// sun times configuration (angle, morning name, evening name) + +var times = SunCalc.times = [ + [-0.833, 'sunrise', 'sunset' ], + [ -0.3, 'sunriseEnd', 'sunsetStart' ], + [ -6, 'dawn', 'dusk' ], + [ -12, 'nauticalDawn', 'nauticalDusk'], + [ -18, 'nightEnd', 'night' ], + [ 6, 'goldenHourEnd', 'goldenHour' ] +]; + +// adds a custom time to the times config + +SunCalc.addTime = function (angle, riseName, setName) { + times.push([angle, riseName, setName]); +}; + + +// calculations for sun times + +var J0 = 0.0009; + +function julianCycle(d, lw) { return Math.round(d - J0 - lw / (2 * PI)); } + +function approxTransit(Ht, lw, n) { return J0 + (Ht + lw) / (2 * PI) + n; } +function solarTransitJ(ds, M, L) { return J2000 + ds + 0.0053 * sin(M) - 0.0069 * sin(2 * L); } + +function hourAngle(h, phi, d) { return acos((sin(h) - sin(phi) * sin(d)) / (cos(phi) * cos(d))); } +function observerAngle(height) { return -2.076 * Math.sqrt(height) / 60; } + +// returns set time for the given sun altitude +function getSetJ(h, lw, phi, dec, n, M, L) { + + var w = hourAngle(h, phi, dec), + a = approxTransit(w, lw, n); + return solarTransitJ(a, M, L); +} + + +// calculates sun times for a given date, latitude/longitude, and, optionally, +// the observer height (in meters) relative to the horizon + +SunCalc.getTimes = function (date, lat, lng, height) { + + height = height || 0; + + var lw = rad * -lng, + phi = rad * lat, + + dh = observerAngle(height), + + d = toDays(date), + n = julianCycle(d, lw), + ds = approxTransit(0, lw, n), + + M = solarMeanAnomaly(ds), + L = eclipticLongitude(M), + dec = declination(L, 0), + + Jnoon = solarTransitJ(ds, M, L), + + i, len, time, h0, Jset, Jrise; + + + var result = { + solarNoon: fromJulian(Jnoon), + nadir: fromJulian(Jnoon - 0.5) + }; + + for (i = 0, len = times.length; i < len; i += 1) { + time = times[i]; + h0 = (time[0] + dh) * rad; + + Jset = getSetJ(h0, lw, phi, dec, n, M, L); + Jrise = Jnoon - (Jset - Jnoon); + + result[time[1]] = fromJulian(Jrise); + result[time[2]] = fromJulian(Jset); + } + + return result; +}; + + +// moon calculations, based on http://aa.quae.nl/en/reken/hemelpositie.html formulas + +function moonCoords(d) { // geocentric ecliptic coordinates of the moon + + var L = rad * (218.316 + 13.176396 * d), // ecliptic longitude + M = rad * (134.963 + 13.064993 * d), // mean anomaly + F = rad * (93.272 + 13.229350 * d), // mean distance + + l = L + rad * 6.289 * sin(M), // longitude + b = rad * 5.128 * sin(F), // latitude + dt = 385001 - 20905 * cos(M); // distance to the moon in km + + return { + ra: rightAscension(l, b), + dec: declination(l, b), + dist: dt + }; +} + +SunCalc.getMoonPosition = function (date, lat, lng) { + + var lw = rad * -lng, + phi = rad * lat, + d = toDays(date), + + c = moonCoords(d), + H = siderealTime(d, lw) - c.ra, + h = altitude(H, phi, c.dec), + // formula 14.1 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + pa = atan(sin(H), tan(phi) * cos(c.dec) - sin(c.dec) * cos(H)); + + h = h + astroRefraction(h); // altitude correction for refraction + + return { + azimuth: azimuth(H, phi, c.dec), + altitude: h, + distance: c.dist, + parallacticAngle: pa + }; +}; + + +// calculations for illumination parameters of the moon, +// based on http://idlastro.gsfc.nasa.gov/ftp/pro/astro/mphase.pro formulas and +// Chapter 48 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + +SunCalc.getMoonIllumination = function (date) { + + var d = toDays(date || new Date()), + s = sunCoords(d), + m = moonCoords(d), + + sdist = 149598000, // distance from Earth to Sun in km + + phi = acos(sin(s.dec) * sin(m.dec) + cos(s.dec) * cos(m.dec) * cos(s.ra - m.ra)), + inc = atan(sdist * sin(phi), m.dist - sdist * cos(phi)), + angle = atan(cos(s.dec) * sin(s.ra - m.ra), sin(s.dec) * cos(m.dec) - + cos(s.dec) * sin(m.dec) * cos(s.ra - m.ra)); + + return { + fraction: (1 + cos(inc)) / 2, + phase: 0.5 + 0.5 * inc * (angle < 0 ? -1 : 1) / Math.PI, + angle: angle + }; +}; + + +function hoursLater(date, h) { + return new Date(date.valueOf() + h * dayMs / 24); +} + +// calculations for moon rise/set times are based on http://www.stargazing.net/kepler/moonrise.html article + +SunCalc.getMoonTimes = function (date, lat, lng, inUTC) { + var t = new Date(date); + if (inUTC) t.setUTCHours(0, 0, 0, 0); + else t.setHours(0, 0, 0, 0); + + var hc = 0.133 * rad, + h0 = SunCalc.getMoonPosition(t, lat, lng).altitude - hc, + h1, h2, rise, set, a, b, xe, ye, d, roots, x1, x2, dx; + + // go in 2-hour chunks, each time seeing if a 3-point quadratic curve crosses zero (which means rise or set) + for (var i = 1; i <= 24; i += 2) { + h1 = SunCalc.getMoonPosition(hoursLater(t, i), lat, lng).altitude - hc; + h2 = SunCalc.getMoonPosition(hoursLater(t, i + 1), lat, lng).altitude - hc; + + a = (h0 + h2) / 2 - h1; + b = (h2 - h0) / 2; + xe = -b / (2 * a); + ye = (a * xe + b) * xe + h1; + d = b * b - 4 * a * h1; + roots = 0; + + if (d >= 0) { + dx = Math.sqrt(d) / (Math.abs(a) * 2); + x1 = xe - dx; + x2 = xe + dx; + if (Math.abs(x1) <= 1) roots++; + if (Math.abs(x2) <= 1) roots++; + if (x1 < -1) x1 = x2; + } + + if (roots === 1) { + if (h0 < 0) rise = i + x1; + else set = i + x1; + + } else if (roots === 2) { + rise = i + (ye < 0 ? x2 : x1); + set = i + (ye < 0 ? x1 : x2); + } + + if (rise && set) break; + + h0 = h2; + } + + var result = {}; + + if (rise) result.rise = hoursLater(t, rise); + if (set) result.set = hoursLater(t, set); + + if (!rise && !set) result[ye > 0 ? 'alwaysUp' : 'alwaysDown'] = true; + + return result; +}; + + +// export as Node module / AMD module / browser variable +if (typeof exports === 'object' && typeof module !== 'undefined') module.exports = SunCalc; +else if (typeof define === 'function' && define.amd) define(SunCalc); +else window.SunCalc = SunCalc; + +}()); diff --git a/RVO42/flow/helper/utils.js b/RVO42/flow/helper/utils.js new file mode 100755 index 0000000..dbffe45 --- /dev/null +++ b/RVO42/flow/helper/utils.js @@ -0,0 +1,161 @@ +const fs = require('fs').promises; + +function bytesToInt(bytes, numberOfBytes) { + let buffer = []; + if (Array.isArray(bytes)) { + buffer = bytes.slice(0); + if (numberOfBytes != undefined) { + buffer = bytes.slice(bytes.length - numberOfBytes); + } + } + else buffer.push(bytes); + + let result = 0; + for (let i = 0; i < buffer.length; i++) { + result = (result << 8) | buffer[i]; + } + + return result >>> 0; //ensure it's an unsigned 32-bit number +} + +function resizeArray(arr, newSize, defaultValue) { + while (newSize > arr.length) + arr.push(defaultValue); + arr.length = newSize; +} + +longToByteArray = function(/*long*/long) { + // we want to represent the input as a 8-bytes array + var byteArray = [0, 0, 0, 0, 0, 0, 0, 0]; + + for (var index = 0; index < byteArray.length; index++) { + var byte = long & 0xff; + byteArray[index] = byte; + long = (long - byte) / 256; + } + + return byteArray; +}; + +function addDays(date, days) { + var result = new Date(date); + result.setDate(result.getDate() + days); + return result; +} + +/* +sleep(2000).then(() => { + // Do something after the sleep! + + +}); +*/ + +function sleep(time) { + return new Promise((resolve) => setTimeout(resolve, time)); +} + +function isEmptyObject(obj) { + for (var name in obj) { + return false; + } + return true; +} + +function emptyJsObject(jsObject) { + Object.keys(jsObject).forEach(key => delete jsObject[key]); +} + +function convertUTCDateToLocalDate(date) { + var newDate = new Date(date); + newDate.setMinutes(date.getMinutes() + date.getTimezoneOffset()); + return newDate; +} + +function addZeroBefore(n) { + return (n < 10 ? '0' : '') + n; +} + + +/** + * Asynchronously writes data to a file. + * + * @param {string} filePath The path to the file. + * @param {string} data The data to write to the file. + * @param {boolean} [append=false] If true, appends the data to the file. If false, it overwrites the file. + */ +async function writeToFile(filePath, data, append = false) { + if (typeof data !== 'string') data = JSON.stringify(data, null, 2); + try { + if (append) { + // Append the data to the end of the file. This is the simplest way to append. + await fs.appendFile(filePath, data, 'utf8'); + console.log(`Successfully appended data to ${filePath} using fs.appendFile.`); + } else { + // Overwrite the file with the new data. + await fs.writeFile(filePath, data, 'utf8'); + console.log(`Successfully wrote (overwrote) data to ${filePath} using fs.writeFile.`); + } + } catch (error) { + console.error(`Error writing to file ${filePath}:`, error); + } +} + + + /** + * Checks if an item is present in an array and adds it if it's not. + * * @param {Array} arr The array to check. + * @param {*} item The item to add. + * @returns {Array} The modified array. + */ +const addToArrayIfUnique = (arr, item) => { + if (!arr.includes(item)) { + arr.push(item); + } + return arr; +}; + + +var convertBase = function() { + + function convertBase(baseFrom, baseTo) { + return function(num) { + return parseInt(num, baseFrom).toString(baseTo); + + }; + } + + // binary to decimal + convertBase.bin2dec = convertBase(2, 10); + + // binary to hexadecimal + convertBase.bin2hex = convertBase(2, 16); + + // decimal to binary + convertBase.dec2bin = convertBase(10, 2); + + // decimal to hexadecimal + convertBase.dec2hex = convertBase(10, 16); + + // hexadecimal to binary + convertBase.hex2bin = convertBase(16, 2); + + // hexadecimal to decimal + convertBase.hex2dec = convertBase(16, 10); + + return convertBase; +}(); + +module.exports = { + bytesToInt, + longToByteArray, + addDays, + addZeroBefore, + resizeArray, + isEmptyObject, + emptyJsObject, + sleep, + convertUTCDateToLocalDate, + writeToFile, + addToArrayIfUnique +} diff --git a/RVO42/flow/httprequest.js b/RVO42/flow/httprequest.js new file mode 100755 index 0000000..469c8cb --- /dev/null +++ b/RVO42/flow/httprequest.js @@ -0,0 +1,137 @@ +exports.id = 'httprequest'; +exports.title = 'HTTP Request'; +exports.group = 'HTTP'; +exports.color = '#5D9CEC'; +exports.input = true; +exports.version = '2.0.1'; +exports.output = 1; +exports.author = 'Peter Širka'; +exports.icon = 'cloud-upload'; + +exports.html = `
+
@(URL address)
+
+
+
@(HTTP method)
+
+
+
@(Serialization)
+
+
+
@(Download the content in chunks)
+
@(Keep persistent cookies)
+
@(Disable DNS cache)
+
@(Keep alive connection)
+
+
+
+
@(Custom headers)
+
@(Cookies)
+
+
+
+ +
+
+
+
@(User)
+
+
+
@(Password)
+
+
+
+
+
`; + +exports.readme = `# Request + +This component creates a request with received data. + +__Response:__ +\`\`\`javascript +{ + data: String, + headers: Object, + status: Number, + host: String +} +\`\`\` + +__Dynamic arguments__: +Are performed via FlowData repository and can be used for URL address or for custom headers/cookies/auth. Use \`repository\` component for creating of dynamic arguments. Dynamic values are replaced in the form \`{key}\`: + +- url address e.g. \`https://.../{key}/\` +- headers values e.g. \`{token}\` +- cookies values e.g. \`{token}\``; + +exports.install = function(instance) { + + var can = false; + var flags = null; + var cookies2 = null; + + instance.on('data', function(response) { + can && instance.custom.send(response); + }); + + instance.custom.send = function(response) { + var options = instance.options; + + var headers = null; + var cookies = null; + + options.headers && Object.keys(options.headers).forEach(function(key) { + !headers && (headers = {}); + headers[key] = response.arg(options.headers[key]); + }); + + if (options.username && options.userpassword) { + !headers && (headers = {}); + headers['Authorization'] = 'Basic ' + U.createBuffer(response.arg(options.username + ':' + options.userpassword)).toString('base64'); + } + + options.cookies && Object.keys(options.cookies).forEach(function(key) { + !cookies && (cookies = {}); + cookies[key] = response.arg(options.cookies[key]); + }); + + if (options.chunks) { + U.download(response.arg(options.url), flags, options.stringify === 'none' ? null : response.data, function(err, response) { + response.on('data', (chunks) => instance.send2(chunks)); + }, cookies || cookies2, headers); + } else { + U.request(response.arg(options.url), flags, options.stringify === 'none' ? null : response.data, 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) + instance.error(err, response); + }, cookies || cookies2, headers); + } + }; + + instance.reconfigure = function() { + var options = instance.options; + can = options.url && options.url && options.method && options.stringify ? true : false; + instance.status(can ? '' : 'Not configured', can ? undefined : 'red'); + + if (!can) + return; + + flags = []; + flags.push(options.method.toLowerCase()); + options.stringify === 'json' && flags.push('json'); + options.stringify === 'raw' && flags.push('raw'); + options.keepalive && flags.push('keepalive'); + !options.nodns && flags.push('dnscache'); + if (options.persistentcookies) { + flags.push('cookies'); + cookies2 = {}; + } else + cookies2 = null; + }; + + instance.on('options', instance.reconfigure); + instance.reconfigure(); +}; \ No newline at end of file diff --git a/RVO42/flow/httpresponse.js b/RVO42/flow/httpresponse.js new file mode 100755 index 0000000..160a3bb --- /dev/null +++ b/RVO42/flow/httpresponse.js @@ -0,0 +1,76 @@ +exports.id = 'httpresponse'; +exports.title = 'HTTP Response'; +exports.group = 'HTTP'; +exports.color = '#5D9CEC'; +exports.icon = 'arrow-right'; +exports.input = true; +exports.output = ['#666D76']; +exports.version = '2.0.0'; +exports.author = 'Martin Smola'; +exports.readme = `# HTTP response + +HTTP response will respond with data recieved using data-type set in Settings form or plain text if not set. Output is the message duration \`Number\` in seconds.`; + +exports.html = `
+
@(Response data-type)
+
JSON is by default.
+
`; + +exports.install = function(instance) { + + var dursum = 0; + var durcount = 0; + + instance.on('data', function(flowdata) { + + var ctrl = flowdata.repository.controller; + var data = flowdata.data; + + if (!ctrl) { + instance.throw('No controller to use for response!'); + return; + } + + durcount++; + dursum += ((new Date() - flowdata.begin) / 1000).floor(2); + setTimeout2(instance.id, instance.custom.duration, 500, 10); + + ctrl.$flowdata = flowdata; + + var datatype = instance.options.datatype || 'json'; + if (datatype === 'emptyresponse') + return ctrl.plain(''); + + if (datatype !== 'json' && typeof(data) !== 'string') { + instance.throw('Incorect type of data, expected string, got ' + typeof(data)); + ctrl.plain(data == null ? '' : data.toString()); + return; + } + + switch(datatype) { + case 'html': + ctrl.content(data, 'text/html'); + break; + case 'plain': + ctrl.plain(data); + break; + case 'xml': + ctrl.content(data, 'text/xml'); + break; + default: + ctrl.json(data); + break; + } + }); + + instance.on('service', function() { + dursum = 0; + durcount = 0; + }); + + instance.custom.duration = function() { + var avg = (dursum / durcount).floor(2); + instance.status(avg + ' sec.'); + instance.send2(0, avg); + }; +}; diff --git a/RVO42/flow/httproute.js b/RVO42/flow/httproute.js new file mode 100755 index 0000000..583a19d --- /dev/null +++ b/RVO42/flow/httproute.js @@ -0,0 +1,326 @@ +exports.id = 'httproute'; +exports.title = 'HTTP Route'; +exports.group = 'HTTP'; +exports.color = '#5D9CEC'; +exports.icon = 'globe'; +exports.input = false; +exports.output = ['#6CAC5A', '#37BC9B']; +exports.version = '1.2.3'; +exports.author = 'Martin Smola'; +exports.cloning = false; +exports.options = { method: 'GET', url: '', size: 5, cacheexpire: '5 minutes', cachepolicy: 0, timeout: 5 }; +exports.dateupdated = '2021-01-21 18:30d'; +exports.readme = `# HTTP route + +__Outputs__: +- first output: raw data (cache is empty or is disabled) +- second output: cached data + +If one of the outputs is disabled then automatic responce with code "503 service unavailable" is sent. + +When a request comes in bellow object is available at \`flowdata.data\`: + +\`\`\`javascript +{ + params: { id: '1' }, // params for dynamic routes, e.g. /test/{id} + query: { msg: 'Hello' }, // parsed query string, e.g. /test/1?msg=Hello + body: { test: 'OK' }, // object if json requests otherwise string + headers: {}, // headers data + session: {}, // session data + user: {}, // user data + files: [], // uploaded files + url: '/users/', // a relative URL address + referrer: '/', // referrer + mobile: false, // determines mobile device + robot: false, // determines search robots/crawlsers + language: 'en' // determines language +} +\`\`\` + +See [documentation for flags](https://docs.totaljs.com/latest/en.html#api~HttpRouteOptionsFlags~unauthorize). These method flags are set automatically e.g. \`get, post, put, patch or delete\` + +--- + +\`id:ROUTE_ID\` flag cannot be used since it's already used by this component internally`; + +exports.html = `
+
+ +
+ +
+
+
@(HTTP method)
+
+
+
@(URL address)
+
+
+
+
+
@(Additional flags)
+
@(Separate flags by comma e.g. json, authorize)
+
+
+
@(Max. request size)
+
@(In kB kilobytes)
+
+
+
@(Timeout)
+
@(In seconds.)
+
+
+
+
+
+
@(Automatically respond with 200 OK?)
+
@(If not checked you need to use HTTP response component to respond to the request.)
+
+
@(Custom headers)
+
@(Cookies)
+
+
+
+
+
+
@(Cache policy)
+
@(User instance must contain id property.)
+
+
+
@(Expiration)
+
@(E.g. 5 minutes)
+
+
+
+`; + +exports.install = function(instance) { + + var route; + + var uninstall = function(id) { + if (F.is4) { + route && route.remove(); + route = null; + } else + UNINSTALL('route', id); + }; + + instance.custom.emptyresponse = function(self) { + self.plain(); + }; + + instance.reconfigure = function() { + + var options = instance.options; + + if (!options.url) { + instance.status('Not configured', 'red'); + return; + } + + if (typeof(options.flags) === 'string') + options.flags = options.flags.split(',').trim(); + + uninstall('id:' + instance.id); + + var flags = options.flags || []; + + flags.push('id:' + instance.id); + + if (!F.is4) + flags.push(options.method.toLowerCase()); + + options.timeout && flags.push(options.timeout * 1000); + + // Make unique values + flags = flags.filter(function(v, i, a) { + if(F.is4 && v.toString().toLowerCase() === options.method.toLowerCase()) + return false; // remove method + return a.indexOf(v) === i; + }); + + options.flags = flags; + var handler = function() { + + if (instance.paused || (instance.isDisabled && (instance.isDisabled('output', 0) || instance.isDisabled('output', 1)))) { + instance.status('503 Service Unavailable'); + this.status = 503; + this.json(); + return; + } + + var key; + var self = this; + + if (instance.options.emptyresponse) { + instance.status('200 OK'); + setTimeout(instance.custom.emptyresponse, 100, self); + + if (instance.hasConnection(0)) { + var data = instance.make({ + query: self.query, + body: self.body, + session: self.session, + user: self.user, + files: self.files, + headers: self.req.headers, + url: self.url, + params: self.params + }); + instance.send2(0, data); + } + + return; + } + + switch (instance.options.cachepolicy) { + case 1: // URL + key = 'rro' + instance.id + self.url.hash(); + break; + case 2: // URL + query + case 3: // URL + query + user + key = self.url; + var keys = Object.keys(self.query); + keys.sort(); + for (var i = 0, length = keys.length; i < length; i++) + key += keys[i] + self.query[keys[i]] + '&'; + if (instance.options.cachepolicy === 3 && self.user) + key += 'iduser' + self.user.id; + key = 'rro' + instance.id + key.hash(); + break; + } + + if (key && F.cache.get2(key)) { + var data = instance.make(F.cache.get2(key)); + data.repository.controller = self; + instance.send2(1, data); + } else { + + var data = instance.make({ + query: self.query, + body: self.body, + session: self.session, + user: self.user, + files: self.files, + headers: self.req.headers, + url: self.url, + params: self.params, + mobile: self.mobile, + robot: self.robot, + referrer: self.referrer, + language: self.language + }); + + data.repository.controller = self; + instance.send2(0, data); + key && FINISHED(self.res, () => F.cache.set(key, self.$flowdata.data, instance.options.cacheexpire)); + } + }; + + if (F.is4) + route = ROUTE(options.method.toUpperCase() + ' ' + options.url, handler, flags, options.size || 5); + else + F.route(options.url, handler, flags, options.size || 5); + + instance.status('Listening', 'green'); + }; + + instance.reconfigure(); + instance.on('options', instance.reconfigure); + instance.on('close', function(){ + uninstall('id:' + instance.id); + }); +}; + +// check url exists +FLOW.trigger('httproutecheckurl', function(next, data) { + var url = data.url; + var method = data.method; + if (url[url.length - 1] !== '/') + url += '/'; + var exists = F.routes.web.findItem(r => r.urlraw === url && r.method === method); + next(exists != null); +}); + +exports.uninstall = function() { + FLOW.trigger('httproutecheckurl', null); +}; diff --git a/RVO42/flow/infosender.js b/RVO42/flow/infosender.js new file mode 100755 index 0000000..587724f --- /dev/null +++ b/RVO42/flow/infosender.js @@ -0,0 +1,81 @@ +exports.id = 'infosender'; +exports.title = 'Info sender'; +exports.version = '1.0.0'; +exports.group = 'Worksys'; +exports.color = '#2134B0'; +exports.input = 2; +exports.output = 1 +exports.icon = 'bolt'; + +const { networkInterfaces } = require('os'); + +exports.html = `
+
+
+
CSV Import
+
+
+
`; + +exports.readme = `# send all data to projects.worksys.io, required to monitor status of controller(unipi)`; + +exports.install = function(instance) { + + let id; + let allValues = {}; + let sendAllValuesInterval; + let configured = false; + + let now = new Date(); + console.log(exports.title, "INSTALLED", now.toLocaleString("sk-SK")); + + const nets = networkInterfaces(); + let ipAddresses = Object.create(null); // Or just '{}', an empty object + + for (const name of Object.keys(nets)) { + for (const net of nets[name]) { + // Skip over non-IPv4 and internal (i.e. 127.0.0.1) addresses + if (net.family === 'IPv4' && !net.internal) { + if (!ipAddresses[name]) { + ipAddresses[name] = []; + } + ipAddresses[name].push(net.address); + } + } + } + + function sendValues() { + if (!configured) return; + + if (Object.keys(allValues).length > 0) { + let dataToSend = { ...allValues }; + dataToSend.id = id; + dataToSend.ipAddresses = ipAddresses; + + instance.send(0, dataToSend); + + allValues = {}; + } + } + + instance.on("close", () => { + clearInterval(sendAllValuesInterval); + }) + + instance.on("0", _ => { + id = FLOW.GLOBALS.settings.project_id; + if (id) configured = true; + else console.log(exports.title, "InfoSender: Unable to send data, no id"); + }) + + instance.on("1", flowdata => { + allValues = { ...allValues, ...flowdata.data }; + //console.log("DATA RECEIVED", flowdata.data); + }) + + sendAllValuesInterval = setInterval(() => { + sendValues(); + }, 60000 * 3); + +} + diff --git a/RVO42/flow/modbus_reader.js b/RVO42/flow/modbus_reader.js new file mode 100755 index 0000000..d6d9dad --- /dev/null +++ b/RVO42/flow/modbus_reader.js @@ -0,0 +1,346 @@ +exports.id = 'modbus_reader'; +exports.title = 'Modbus reader'; +exports.version = '2.0.0'; +exports.group = 'Worksys'; +exports.color = '#2134B0'; +exports.input = 1; +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; +//number of phases inRVO +let phases; +//phases where voltage is 0 (set) +let noVoltage; +let energyToSwitchLamps; + +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.phases = this.buildPhases(); + + this.startSocket(); + } + + buildPhases = () => { + let a = []; + for (let i = 1; i <= phases; i++) { + a.push(`Phase_${i}_voltage`) + } + return a; + } + + startSocket = () => { + + let obj = this; + + if (this.socket) { + this.socket.removeAllListeners(); + this.socket = null; + } + + 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('Modbus_reader: Socket connection error', e); //'ECONNREFUSED' or 'ECONNRESET' ?? + }); + + this.socket.on('close', function() { + console.log('Modbus_reader: Socket connection closed - Waiting 10 seconds before connecting 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 we just start to loop devices from the beginning, or there is just 1 device in config, we wait whole timeoutInterval + if (this.indexInDeviceConfig == 0 || deviceConfig.length === 1) 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 (this.phases.includes(singleValue)) { + let l = singleValue.split("_"); + let phase = parseInt(l[1]); + + // console.log(values[singleValue], tbName); + + if (values[singleValue] == 0) { + noVoltage.add(phase); + sendNotification("modbus_reader: checkNullVoltage", tbName, "no_voltage_on_phase", { phase: phase }, "", SEND_TO.tb, instance, "voltage" + phase); + // console.log('no voltage') + } + else { + noVoltage.delete(phase); + // console.log('voltage detected') + sendNotification("modbus_reader: checkNullVoltage", tbName, "voltage_on_phase_restored", { phase: phase }, "", SEND_TO.tb, instance, "voltage" + phase); + } + } + }) + } + + /** + * function sends notification to slack and to tb, if EM total_power value changes more than numberOfNodes*15. This should show, that RVO lamps has been switched on or off + */ + lampSwitchNotification = (values) => { + + if (!values.hasOwnProperty("total_power")) return; + + const actualTotalPower = values.total_power; + + if (actualTotalPower > energyToSwitchLamps && 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 <= energyToSwitchLamps && 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; + } + + function main() { + + phases = FLOW.GLOBALS.settings.phases; + tbName = FLOW.GLOBALS.settings.rvoTbName; + noVoltage = FLOW.GLOBALS.settings.no_voltage; + energyToSwitchLamps = FLOW.GLOBALS.settings.energy_to_switch_lamps / 2.5; //half value is enought to show if lamps are turned on or off + if (deviceConfig.length) mainSocket = new SocketWithClients(); + else console.log("Modbus_reader: no modbus device in configuration"); + + // this notification is to show, that flow (unipi) has been restarted + sendNotification("modbus_reader", tbName, "flow_restart", {}, "", SEND_TO.slack, instance); + } + + instance.on("0", function(_) { + main(); + }) + +} + diff --git a/RVO42/flow/monitorconsumption.js b/RVO42/flow/monitorconsumption.js new file mode 100755 index 0000000..64cc58e --- /dev/null +++ b/RVO42/flow/monitorconsumption.js @@ -0,0 +1,156 @@ +exports.id = 'monitorconsumption'; +exports.title = 'Consumption'; +exports.version = '1.0.0'; +exports.author = 'Peter Širka'; +exports.group = 'Monitoring'; +exports.color = '#967ADC'; +exports.input = 0; +exports.output = 1; +exports.icon = 'bug'; +exports.options = { interval: 5000, enabled: true, monitorconsumption: true, monitorsize: true, monitorconnections: true, monitorfiles: true }; +exports.click = true; +exports.readme = `# Consumption monitoring + +This component measure CPU and memory consumption, open files and open connections of this application. It uses these Linux commands: \`ps\`, \`lsof\`, \`netstat\` and \`df\`. + +__Data Example__: + +\`\`\`javascript +{ + cpu: 0, // percentage + memory: 4096, // in bytes + size: 34303, // directory size in bytes + files: 34, // count of open files + connections: 343, // count of connections + uptime: '1-12:34:00' +} +\`\`\``; + +exports.html = `
+
+
+
@(Interval in milliseconds)
+
+
+
+
Monitor: Consumption + uptime
+
Monitor: Count of open files
+
Monitor: Count of open connections
+
Monitor: Directory size
+
`; + +exports.install = function(instance) { + + var current = { cpu: 0, memory: 0, files: 0, connections: 0, size: 0, uptime: '', counter: 0 }; + var tproc = null; + var Exec = require('child_process').exec; + var reg_empty = /\s{2,}/g; + var reg_appdisksize = /^[\d.,]+/; + + instance.custom.run = function() { + + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + + var arr = []; + + // Get CPU and Memory consumption + instance.options.monitorconsumption && arr.push(function(next) { + Exec('ps -p {0} -o %cpu,rss,etime'.format(process.pid), function(err, response) { + + if (err) { + instance.throw(err); + } else { + var line = response.split('\n')[1]; + line = line.trim().replace(reg_empty, ' ').split(' '); + var cpu = line[0].parseFloat(); + current.cpu = cpu.floor(1); + current.memory = line[1].parseInt2() * 1024; // kB to bytes + current.uptime = line[2]; + } + + next(); + }); + }); + + // Get count of open files + instance.options.monitorfiles && arr.push(function(next) { + Exec('lsof -a -p {0} | wc -l'.format(process.pid), function(err, response) { + if (err) + instance.throw(err); + else + current.files = response.trim().parseInt2(); + next(); + }); + }); + + // Get count of opened network connections + instance.options.monitorconnections && arr.push(function(next) { + Exec('netstat -an | grep :{0} | wc -l'.format(F.port), function(err, response) { + if (err) { + instance.throw(err); + } else { + current.connections = response.trim().parseInt2() - 1; + if (current.connections < 0) + current.connections = 0; + } + next(); + }); + }); + + // Get directory size + instance.options.monitorsize && current.counter % 5 !== 0 && arr.push(function(next) { + Exec('du -hsb ' + process.cwd(), function(err, response) { + if (err) { + instance.throw(err); + } else { + var match = response.trim().match(reg_appdisksize); + match && (current.size = match.toString().trim().parseInt2()); + } + next(); + }); + }); + + arr.async(function() { + + tproc && clearTimeout(tproc); + + if (instance.options.enabled) { + tproc = setTimeout(instance.custom.run, instance.options.interval); + instance.send2(current); + } + + instance.custom.status(); + current.counter++; + }); + }; + + instance.custom.status = function() { + if (instance.options.enabled) + instance.status('{0}% / {1}'.format(current.cpu, current.memory.filesize())); + else + instance.status('Disabled', 'red'); + }; + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + + if (instance.options.enabled) { + current.counter = 0; + instance.custom.run(); + } + + }); + + instance.on('close', function() { + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + }); + + setTimeout(instance.custom.run, 1000); +}; \ No newline at end of file diff --git a/RVO42/flow/monitordisk.js b/RVO42/flow/monitordisk.js new file mode 100755 index 0000000..f4fdaa0 --- /dev/null +++ b/RVO42/flow/monitordisk.js @@ -0,0 +1,96 @@ +exports.id = 'monitordisk'; +exports.title = 'Disk'; +exports.version = '1.0.0'; +exports.author = 'Peter Širka'; +exports.group = 'Monitoring'; +exports.color = '#F6BB42'; +exports.output = 1; +exports.icon = 'hdd-o'; +exports.click = true; +exports.options = { interval: 8000, path: '/', enabled: true }; +exports.readme = `# Disk monitoring + +This component monitors disk \`bytes\` consumption in Linux systems. It uses \`df\` command. + +__Data Example__: + +\`\`\`javascript +{ + total: 474549649408, + used: 39125245952, + free: 411294994432 +} +\`\`\``; + +exports.html = `
+
+
+
@(Interval in milliseconds)
+
+
+
@(Path)
+
+
+
`; + +exports.install = function(instance) { + + var current = { total: 0, used: 0, free: 0, path: '', type: '', percentUsed: 0 }; + var tproc = null; + + instance.custom.run = function() { + + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + + if (!instance.options.enabled) + return; + + require('child_process').exec('df -hTB1 ' + instance.options.path, function(err, response) { + + tproc = setTimeout(instance.custom.run, instance.options.interval); + + if (err) { + instance.error(err); + return; + } + + response.parseTerminal(function(line) { + if (line[0][0] !== '/') + return; + current.total = line[2].parseInt(); + current.free = line[4].parseInt(); + current.used = line[3].parseInt(); + current.path = instance.options.path || '/'; + current.type = line[1]; + current.percentUsed = line[5]; + instance.custom.status(); + instance.send2(current); + }); + }); + }; + + instance.custom.status = function() { + if (instance.options.enabled) + instance.status(current.free.filesize() + ' / ' + current.total.filesize()); + else + instance.status('Disabled', 'red'); + }; + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + instance.options.enabled && instance.custom.run(); + }); + + instance.on('close', function() { + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + }); + + setTimeout(instance.custom.run, 1000); +}; \ No newline at end of file diff --git a/RVO42/flow/monitormemory.js b/RVO42/flow/monitormemory.js new file mode 100755 index 0000000..2decbc4 --- /dev/null +++ b/RVO42/flow/monitormemory.js @@ -0,0 +1,87 @@ +exports.id = 'monitormemory'; +exports.title = 'Memory'; +exports.version = '1.0.0'; +exports.author = 'Peter Širka'; +exports.group = 'Monitoring'; +exports.color = '#F6BB42'; +exports.output = 1; +exports.click = true; +exports.icon = 'microchip'; +exports.options = { interval: 8000, enabled: true }; +exports.readme = `# Memory monitoring + +This component monitors memory \`bytes\` consumption in Linux systems. It uses \`free\` command. + +__Data Example__: + +\`\`\`javascript +{ + total: 33558769664, + used: 1998868480, + free: 2653708288 +} +\`\`\``; + +exports.html = `
+
+
+
@(Interval in milliseconds)
+
+
+
`; + +exports.install = function(instance) { + + var current = { total: 0, used: 0, free: 0 }; + var tproc = null; + + instance.custom.run = function() { + + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + + if (!instance.options.enabled) + return; + + require('child_process').exec('free -b -t', function(err, response) { + + tproc = setTimeout(instance.custom.run, instance.options.interval); + + if (err) { + instance.error(err); + return; + } + + var memory = response.split('\n')[1].match(/\d+/g); + current.total = memory[0].parseInt(); + current.used = memory[1].parseInt() - memory[3].parseInt(); + current.free = current.total - current.used; + instance.custom.status(); + instance.send2(current); + }); + }; + + instance.custom.status = function() { + if (instance.options.enabled) + instance.status(current.free.filesize() + ' / ' + current.total.filesize()); + else + instance.status('Disabled', 'red'); + }; + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + instance.options.enabled && instance.custom.run(); + }); + + instance.on('close', function() { + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + }); + + setTimeout(instance.custom.run, 1000); +}; \ No newline at end of file diff --git a/RVO42/flow/nodesdb_changecheck.js b/RVO42/flow/nodesdb_changecheck.js new file mode 100755 index 0000000..9adab62 --- /dev/null +++ b/RVO42/flow/nodesdb_changecheck.js @@ -0,0 +1,77 @@ +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 = 2; +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); + } + } + + //kedze do slacku posielame stringy, na cloud musime previest vsetky stringy spat na objekty: + // Funkcia na parsovanie všetkých reťazcov v poli + const parseArray = (arr) => { + return arr.map(jsonString => JSON.parse(jsonString)); + }; + + 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); + if (FLOW.GLOBALS.settings.send_changed_node_numbers) instance.send(1, { aktualneNody: parseArray(zmenene), originalne: parseArray(Array.from(set2)) }); + } + 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/RVO42/flow/notifikacie.csv b/RVO42/flow/notifikacie.csv new file mode 100755 index 0000000..520c997 --- /dev/null +++ b/RVO42/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/RVO42/flow/show_dbdata.js b/RVO42/flow/show_dbdata.js new file mode 100755 index 0000000..1e23ff7 --- /dev/null +++ b/RVO42/flow/show_dbdata.js @@ -0,0 +1,243 @@ +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 = 8; +exports.output = 1; + +const { exec } = require('child_process'); + +exports.install = 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 }) + }) + instance.on("5", _ => { + exec("sudo tail -n 25 monitor.txt", (err, stdout, stderr) => { + if (err || stderr) instance.send(0, { err, stderr }); + else instance.send(0, stdout); + }) + }) + instance.on("6", _ => { + exec("sudo tail -n 25 err.txt", (err, stdout, stderr) => { + if (err || stderr) instance.send(0, { err, stderr }); + else instance.send(0, stdout); + }) + }) + instance.on("7", _ => { + instance.send(0, FLOW.deviceStatus); + }) +}; + + +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/RVO42/flow/slack_filter.js b/RVO42/flow/slack_filter.js new file mode 100755 index 0000000..6618523 --- /dev/null +++ b/RVO42/flow/slack_filter.js @@ -0,0 +1,188 @@ +exports.id = 'slack_filter'; +exports.title = 'Slack Filter'; +exports.group = 'Citysys'; +exports.color = '#30E193'; +exports.input = 2; +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 = `
+
+
+
@(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('0', 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']['en']; + 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"] = []; + } + + instance.options.name = FLOW.GLOBALS.settings.rvo_name; + if (instance.options.name) { + instance.status('Running'); + running = true; + } else { + instance.status('Please run options again', 'red'); + running = false; + } + } catch (e) { + instance.error('Citysys connector: ' + e.message); + } + }; + + instance.on('options', instance.reconfigure); + + instance.on("1", _ => { + instance.reconfigure(); + }) +}; diff --git a/RVO42/flow/thermometer.js b/RVO42/flow/thermometer.js new file mode 100755 index 0000000..fc7074d --- /dev/null +++ b/RVO42/flow/thermometer.js @@ -0,0 +1,99 @@ +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 = 5;//minutes +let NUMBER_OF_FAILURES_TO_SEND_ERROR = 13; + +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) => { + + 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); + setTimeout(main, 20000); + }) +}; diff --git a/RVO42/flow/trigger.js b/RVO42/flow/trigger.js new file mode 100755 index 0000000..27545a8 --- /dev/null +++ b/RVO42/flow/trigger.js @@ -0,0 +1,79 @@ +exports.id = 'trigger'; +exports.title = 'Trigger'; +exports.group = 'Inputs'; +exports.color = '#F6BB42'; +exports.click = true; +exports.output = 1; +exports.version = '1.1.0'; +exports.author = 'Martin Smola'; +exports.icon = 'play'; + +exports.html = `
+
@(Data type (String by default))
+
@(Data)
+
Trigger 5s after initialization.
+
@(Useful when there's a need to run certain flow when the app restarts, etc.)
+
`; + +exports.readme = `# Trigger + +- Clicking on the component starts the chain +- Settings allows to set a data-type and a value`; + +exports.install = function(instance) { + + var value; + + instance.on('click', () => instance.send2(value)); + + instance.reconfigure = function() { + var options = instance.options; + value = null; + switch (options.datatype) { + case 'integer': + value = options.data.parseInt2('error'); + value = value === 'error' ? NaN : value; + break; + case 'float': + value = options.data.parseFloat2('error'); + value = value === 'error' ? NaN : value; + break; + case 'date': + options.data = options.data.toString(); + var num = options.data.parseInt('error'); + num === 'error' && (num = options.data.parseDate('error')); + num === 'error' && (num = null); + value = num ? new Date(num).toUTCString() : num; + break; + case 'object': + try { + value = (new Function('return ' + options.data))(); + } catch (e) { + instance.error(e); + } + break; + case 'boolean': + value = options.data.parseBoolean(); + break; + case 'buffer': + try { + value = U.createBuffer(options.data); + } catch (e) { + instance.error(e); + } + break; + case 'string': + default: + value = '' + (options.data || ''); + break; + } + }; + + instance.on('options', instance.reconfigure); + instance.reconfigure(); + + if (instance.options.restart) + setTimeout(function(){ + instance.send2(value); + }, 5000); +}; diff --git a/RVO42/flow/variables.txt b/RVO42/flow/variables.txt new file mode 100755 index 0000000..e69de29 diff --git a/RVO42/flow/virtualwirein.js b/RVO42/flow/virtualwirein.js new file mode 100755 index 0000000..38a4e42 --- /dev/null +++ b/RVO42/flow/virtualwirein.js @@ -0,0 +1,43 @@ +exports.id = 'virtualwirein'; +exports.title = 'Virtual wire in'; +exports.version = '1.0.0'; +exports.author = 'Martin Smola'; +exports.color = '#303E4D'; +exports.icon = 'sign-in'; +exports.input = false; +exports.output = 1; +exports.options = {}; +exports.readme = `# Virtual wire in + +When the wires between the components are mess it's time to use Virtual wire.`; + +exports.html = `
+
@(Wire name)
+
+`; + +exports.install = function(instance) { + + instance.custom.reconfigure = function(options){ + if (instance.options.wirename) { + instance.status(instance.options.wirename); + } else + instance.status('Not configured', 'red'); + }; + + ON('virtualwire', function(wirename, flowdata){ + if (instance.options.wirename && instance.options.wirename === wirename) + instance.send(flowdata); + }); + + instance.on('options', instance.custom.reconfigure); + instance.custom.reconfigure(); +}; diff --git a/RVO42/flow/virtualwireout.js b/RVO42/flow/virtualwireout.js new file mode 100755 index 0000000..94a1e4f --- /dev/null +++ b/RVO42/flow/virtualwireout.js @@ -0,0 +1,41 @@ +exports.id = 'virtualwireout'; +exports.title = 'Virtual wire out'; +exports.version = '1.0.0'; +exports.author = 'Martin Smola'; +exports.color = '#303E4D'; +exports.icon = 'sign-out'; +exports.input = true; +exports.options = {}; +exports.readme = `# Virtual wire out + +When the wires between the components are mess it's time to use Virtual wire.`; + +exports.html = `
+
@(Wire name)
+
+`; + +exports.install = function(instance) { + + instance.custom.reconfigure = function(){ + if (instance.options.wirename) { + instance.status(instance.options.wirename); + } else + instance.status('Not configured', 'red'); + }; + + instance.on('data', function(flowdata) { + EMIT('virtualwire', instance.options.wirename, flowdata); + }); + + instance.on('options', instance.custom.reconfigure); + instance.custom.reconfigure(); +}; diff --git a/RVO42/flow/wsmqttpublish.js b/RVO42/flow/wsmqttpublish.js new file mode 100755 index 0000000..0eba804 --- /dev/null +++ b/RVO42/flow/wsmqttpublish.js @@ -0,0 +1,448 @@ +exports.id = 'wsmqttpublish'; +exports.title = 'WS MQTT publish'; +exports.group = 'MQTT'; +exports.color = '#888600'; +exports.version = '1.0.2'; +exports.icon = 'sign-out'; +exports.input = 2; +exports.output = 3; +exports.options = { host: 'tb-stage.worksys.io', port: 1883, clientid: "", username: "" }; + +exports.html = `
+
+
+
Hostname or IP address (if not empty - setting will override db setting)
+
+
+
Port
+
+
+
+
+
@(Client id)
+
+
+
@(Username)
+
+
+
`; + + +exports.readme = ` +# WS MQTT Publish + +Version 1.0.3. + +Added: +- database collections, +- 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 = { + debug: 0, + rpcCall: 1, + services: 2 +} + +//CONFIG +let createTelemetryBackup = true; +let saveTelemetryOnError = true;//backup_on_failure overrides this value +//------------------------ + +let rollers; +if (createTelemetryBackup) rollers = require('streamroller'); + +const noSqlFileSizeLimit = 4194304;//use 5MB - 4194304 +let insertNoSqlCounter = 0; +let insertBackupNoSqlCounter = 0; +let processingData = false; + +let backup_on_failure = false;//== saveTelemetryOnError - create backup client 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; + +process.on('uncaughtException', function(err) { + + errLogger.error('uncaughtException:', err.message) + errLogger.error(err.stack); + + //TODO + //send to service + + //process.exit(1); +}) + +const nosql = NOSQL('tbdata'); +const nosqlBackup = NOSQL('/backup/tbdata'); + + +exports.install = function(instance) { + + var client; + var opts; + var clientReady = false; + + // wsmqtt status for notification purposes on projects.worksys.io database + let wsmqttName = null; + let sendWsStatusVar = null; + let wsmqtt_status = 'disconnected'; + + 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'; + } + + function sendWsStatus() { + instance.send(SEND_TO.services, { [wsmqttName]: wsmqtt_status }); + } + + + function main() { + if (!FLOW.dbLoaded) return; + + loadSettings(); + clearInterval(sendWsStatus); + sendWsStatusVar = setInterval(sendWsStatus, 180000); + } + + //set opts according to db settings + function loadSettings() { + + if (instance.options.host !== "") { + //override settings from database + var o = instance.options; + opts = { + host: o.host, + port: o.port, + clientId: o.clientid, + username: o.username, + rejectUnauthorized: false, + resubscribe: false + }; + + wsmqttName = getWsmqttName(o.host); + + console.log("wsmqttpublich -> loadSettings from instance.options", instance.options); + } + else { + + const SETTINGS = FLOW.GLOBALS.settings; + backup_on_failure = SETTINGS.backup_on_failure; + saveTelemetryOnError = backup_on_failure; + + restore_from_backup = SETTINGS.restore_from_backup; + restore_backup_wait = SETTINGS.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; + + opts = { + host: mqtt_host, + port: mqtt_port, + keepalive: 10, + clientId: mqtt_clientid, + username: mqtt_username, + rejectUnauthorized: false, + resubscribe: false + }; + + wsmqttName = getWsmqttName(mqtt_host); + } + + connectToTbServer(); + } + + function connectToTbServer() { + 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"); + //monitor.info("MQTT client connected"); + + sendClientError = true; + clientReady = true; + wsmqtt_status = 'connected'; + }); + + client.on('reconnect', function() { + instance.status("Reconnecting", "yellow"); + clientReady = false; + }); + + client.on('message', function(topic, message) { + // message is type of buffer + message = message.toString(); + if (message[0] === '{') { + TRY(function() { + + message = JSON.parse(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 } }); + } + + }, () => instance.debug('MQTT: Error parsing data', message)); + } + + instance.send(SEND_TO.rpcCall, { "topic": topic, "content": message }); + }); + + client.on('close', function() { + clientReady = false; + wsmqtt_status = 'disconnected'; + + instance.status("Disconnected", "red"); + instance.send(SEND_TO.debug, { "message": "Client CLOSE signal received !" }); + }); + + client.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; + wsmqtt_status = 'disconnected'; + }); + + } + + + instance.on("0", _ => { + main(); + }) + + + instance.on('1', function(data) { + + if (clientReady) { + //do we have some data in backup file? if any, process data from database + if (saveTelemetryOnError) { + //read telemetry data and send back to server + if (!processingData) processDataFromDatabase(); + } + + let stringifiedJson = JSON.stringify(data.data); + client.publish("v1/gateway/telemetry", stringifiedJson, { qos: 1 }); + + //backup telemetry + if (createTelemetryBackup) { + data.data.id = UID(); + nosqlBackup.insert(data.data); + + insertBackupNoSqlCounter++; + if (insertBackupNoSqlCounter > 150) { + let options = { compress: true }; + let path = __dirname + "/../databases/backup/tbdata.nosql"; + var stream = new rollers.RollingFileStream(path, noSqlFileSizeLimit, 150, options); + stream.write(""); + stream.end(); + + insertBackupNoSqlCounter = 0; + } + } + + } + 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 (saveTelemetryOnError) { + //create new file from tbdata.nosql, if file size exceeds given limit, and clear tbdata.nosql + makeBackupFromDbFile(); + + //write to tb + data.data.id = UID(); + nosql.insert(data.data); + } + } + }); + + + instance.close = function(done) { + if (clientReady) { + client.end(); + clearInterval(sendWsStatusVar); + } + }; + + + function getDbBackupFileCounter(type) { + var files = fs.readdirSync(__dirname + "/../databases"); + + let counter = 0; + for (var i = 0; i < files.length; i++) { + + if (files[i] == "tbdata.nosql") continue; + + if (files[i].endsWith(".nosql")) { + + let pos = files[i].indexOf("."); + if (pos > -1) { + + let fileCounter = counter; + let firstDigit = files[i].slice(0, pos); + + fileCounter = parseInt(firstDigit); + if (isNaN(fileCounter)) fileCounter = 0; + //console.log("getDbBackupFileCounter digit:", files[i], firstDigit, fileCounter, isNaN(fileCounter), type); + + if (type == "max") { + if (fileCounter > counter) { + counter = fileCounter; + } + } + else if (type == "min") { + if (counter == 0) counter = fileCounter; + + if (fileCounter < counter) { + counter = fileCounter; + } + } + } + } + + } + + if (type == "max") counter++; + + return counter; + } + + const makeBackupFromDbFile = async () => { + + if (!saveTelemetryOnError) return; + + //to avoid large file: tbdata.nosql + + //init value is 0! + if (insertNoSqlCounter > 0) { + --insertNoSqlCounter; + return; + } + + insertNoSqlCounter = 100; + + let source = __dirname + "/../databases/tbdata.nosql"; + + var stats = fs.statSync(source); + var fileSizeInBytes = stats.size; + + if (fileSizeInBytes > noSqlFileSizeLimit) { + + let counter = 1; + counter = getDbBackupFileCounter("max"); + + let destination = __dirname + "/../databases/" + counter + "." + "tbdata.nosql"; + + //make backup file + fs.copyFileSync(source, destination); + //fs.renameSync(p, p + "." + counter); + + //clear tbdata.nosql + fs.writeFileSync(source, ""); + fs.truncateSync(source, 0); + + } + } + + const processDataFromDatabase = async () => { + + if (restore_from_backup <= 0) return; + + //calculate diff + const now = new Date(); + let currentTime = now.getTime(); + let diff = currentTime - lastRestoreTime; + + if ((diff / 1000) < restore_backup_wait) { + //console.log("*********restore_backup_wait", diff, restore_backup_wait); + return; + } + + processingData = true; + + //get filename to process + let counter = getDbBackupFileCounter("min"); + + //we have some backup files + let dataBase = 'tbdata'; + + var nosql; + if (counter == 0) dataBase = 'tbdata'; + else dataBase = counter + "." + 'tbdata'; + + nosql = NOSQL(dataBase); + + //select all data - use limit restore_from_backup + let records = await promisifyBuilder(nosql.find().take(restore_from_backup)); + + for (let i = 0; i < records.length; i++) { + if (clientReady) { + + let item = records[i]; + let id = item.id; + + if (id !== undefined) { + //console.log("------------processDataFromDatabase - remove", id, dataBase, i); + + try { + + let message = JSON.parse(JSON.stringify(item)); + delete message.id; + + client.publish("v1/gateway/telemetry", JSON.stringify(message), { qos: 1 }); + + //remove from database + await promisifyBuilder(nosql.remove().where("id", id)); + + } catch (error) { + //process error + console.log("processDataFromDatabase", error); + } + + } + + } + else { + processingData = false; + return; + } + } + + if (records.length > 0) { + //clean backup file + if (counter > 0) nosql.clean(); + } + + //no data in db, remove + if (records.length == 0) { + if (counter > 0) nosql.drop(); + } + + const d = new Date(); + lastRestoreTime = d.getTime(); + + processingData = false; + + } + + instance.on('options', main); + //instance.reconfigure(); +}; diff --git a/RVO42/monitor.txt b/RVO42/monitor.txt new file mode 100755 index 0000000..d71e0a5 --- /dev/null +++ b/RVO42/monitor.txt @@ -0,0 +1,400 @@ +[2025-10-09T16:51:17.413] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-09T16:51:22.754] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-09T16:51:22.759] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-09T16:51:22.760] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-09T16:51:22.761] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-09T16:51:22.765] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T16:51:22.767] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-10-10T05:32:00.766Z +[2025-10-09T16:51:22.768] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-10-09T16:45:00.768Z +[2025-10-09T16:51:22.769] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T16:51:22.770] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-10-09T16:51:22.771] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-09T16:51:22.771] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-09T16:51:22.773] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T16:51:22.774] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-10-10T05:32:00.774Z +[2025-10-09T16:51:22.775] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-10-09T16:45:00.775Z +[2025-10-09T16:51:22.776] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T16:51:22.777] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-10-09T16:51:22.777] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-09T16:51:22.778] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-09T16:51:22.780] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T16:51:22.781] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-10-10T05:32:00.781Z +[2025-10-09T16:51:22.782] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-10-09T16:45:00.782Z +[2025-10-09T16:51:22.782] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T16:51:22.783] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-10-09T16:51:22.784] [INFO] monitorLogs - buildTasks: profile for line 4 +[2025-10-09T16:51:22.785] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-09T16:51:22.787] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T16:51:22.787] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 4 2025-10-10T05:32:00.787Z +[2025-10-09T16:51:22.788] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 4 2025-10-09T16:45:00.788Z +[2025-10-09T16:51:22.789] [INFO] monitorLogs - -->time_points final 4 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T16:51:22.790] [INFO] monitorLogs - -->currentValue for relay 4 0 +[2025-10-09T16:51:22.792] [INFO] monitorLogs - tasks created: 241 +[2025-10-09T16:51:22.795] [INFO] monitorLogs - -->FLOW bol spustený g9OxBZ5KRwNznlY6pAppGEAWXvjdEL4eGQobMDy2 2025-08-08 +[2025-10-09T16:51:27.798] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-09T18:27:41.502] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-09T18:27:41.505] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-09T18:27:41.507] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-09T18:27:41.510] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-10-09T19:03:49.324] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-09T19:03:54.659] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-09T19:03:54.664] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-09T19:03:54.666] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-09T19:03:54.666] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-09T19:03:54.670] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T19:03:54.672] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-10-10T05:32:00.671Z +[2025-10-09T19:03:54.673] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-10-10T16:45:00.673Z +[2025-10-09T19:03:54.674] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T19:03:54.675] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-10-09T19:03:54.676] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-09T19:03:54.676] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-09T19:03:54.679] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T19:03:54.680] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-10-10T05:32:00.679Z +[2025-10-09T19:03:54.680] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-10-10T16:45:00.680Z +[2025-10-09T19:03:54.681] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T19:03:54.682] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-10-09T19:03:54.683] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-09T19:03:54.683] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-09T19:03:54.686] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T19:03:54.686] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-10-10T05:32:00.686Z +[2025-10-09T19:03:54.688] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-10-10T16:45:00.687Z +[2025-10-09T19:03:54.689] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T19:03:54.690] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-10-09T19:03:54.691] [INFO] monitorLogs - buildTasks: profile for line 4 +[2025-10-09T19:03:54.691] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-09T19:03:54.693] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T19:03:54.694] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 4 2025-10-10T05:32:00.694Z +[2025-10-09T19:03:54.695] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 4 2025-10-10T16:45:00.694Z +[2025-10-09T19:03:54.695] [INFO] monitorLogs - -->time_points final 4 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T19:03:54.696] [INFO] monitorLogs - -->currentValue for relay 4 1 +[2025-10-09T19:03:54.698] [INFO] monitorLogs - tasks created: 241 +[2025-10-09T19:03:54.701] [INFO] monitorLogs - -->FLOW bol spustený g9OxBZ5KRwNznlY6pAppGEAWXvjdEL4eGQobMDy2 2025-08-08 +[2025-10-09T19:03:59.704] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-10T03:03:56.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-10 03:03:56 +[2025-10-10T06:52:03.075] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-10T06:52:03.080] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-10T06:52:03.082] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-10T06:52:03.084] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-10-10T18:24:38.197] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-10T18:24:38.199] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-10T18:24:38.202] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-10T18:24:38.204] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-10-11T03:03:57.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-11 03:03:57 +[2025-10-11T06:54:16.556] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-11T06:54:16.561] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-11T06:54:16.563] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-11T06:54:16.565] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-10-11T18:27:48.275] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-11T18:27:48.285] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-11T18:27:48.288] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-11T18:27:48.289] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-10-12T03:03:59.015] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-12 03:03:59 +[2025-10-12T06:50:49.175] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-12T06:50:49.178] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-12T06:50:49.180] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-12T06:50:49.183] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-10-12T18:23:16.513] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-12T18:23:16.515] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-12T18:23:16.518] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-12T18:23:16.519] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-10-13T03:04:00.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-13 03:04:00 +[2025-10-13T06:48:25.905] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-13T06:48:25.908] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-13T06:48:25.911] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-13T06:48:25.913] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-10-13T18:25:06.933] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-13T18:25:06.935] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-13T18:25:06.937] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-13T18:25:06.939] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-10-14T03:04:02.018] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-14 03:04:02 +[2025-10-14T06:50:23.391] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-14T06:50:23.394] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-14T06:50:23.396] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-14T06:50:23.398] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-10-14T18:19:41.096] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-14T18:19:41.098] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-14T18:19:41.100] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-14T18:19:41.102] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-10-15T03:04:03.013] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-15 03:04:03 +[2025-10-15T06:55:51.091] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-15T06:55:51.094] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-15T06:55:51.096] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-15T06:55:51.098] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-10-15T11:50:13.236] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-15T11:50:18.581] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-15T11:50:18.586] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-15T11:50:18.587] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-15T11:50:18.588] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-15T11:50:18.592] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-15T11:50:18.593] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-10-16T05:41:00.593Z +[2025-10-15T11:50:18.595] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-10-15T16:33:00.595Z +[2025-10-15T11:50:18.595] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:41', name: 'luxOff' }, + { value: 1, start_time: '18:33', name: 'luxOn' } +] +[2025-10-15T11:50:18.597] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-10-15T11:50:18.597] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-15T11:50:18.598] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-15T11:50:18.600] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-15T11:50:18.601] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-10-16T05:41:00.601Z +[2025-10-15T11:50:18.602] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-10-15T16:33:00.602Z +[2025-10-15T11:50:18.603] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:41', name: 'luxOff' }, + { value: 1, start_time: '18:33', name: 'luxOn' } +] +[2025-10-15T11:50:18.604] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-10-15T11:50:18.604] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-15T11:50:18.605] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-15T11:50:18.607] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-15T11:50:18.608] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-10-16T05:41:00.608Z +[2025-10-15T11:50:18.609] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-10-15T16:33:00.608Z +[2025-10-15T11:50:18.609] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:41', name: 'luxOff' }, + { value: 1, start_time: '18:33', name: 'luxOn' } +] +[2025-10-15T11:50:18.610] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-10-15T11:50:18.611] [INFO] monitorLogs - buildTasks: profile for line 4 +[2025-10-15T11:50:18.611] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-15T11:50:18.614] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-15T11:50:18.614] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 4 2025-10-16T05:41:00.614Z +[2025-10-15T11:50:18.615] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 4 2025-10-15T16:33:00.615Z +[2025-10-15T11:50:18.616] [INFO] monitorLogs - -->time_points final 4 [ + { value: 0, start_time: '7:41', name: 'luxOff' }, + { value: 1, start_time: '18:33', name: 'luxOn' } +] +[2025-10-15T11:50:18.617] [INFO] monitorLogs - -->currentValue for relay 4 0 +[2025-10-15T11:50:18.619] [INFO] monitorLogs - tasks created: 241 +[2025-10-15T11:50:18.621] [INFO] monitorLogs - -->FLOW bol spustený g9OxBZ5KRwNznlY6pAppGEAWXvjdEL4eGQobMDy2 2025-10-08 +[2025-10-15T11:50:23.624] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-15T18:17:41.797] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-15T18:17:41.802] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-15T18:17:41.805] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-15T18:17:41.808] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor diff --git a/RVO42/package-lock.json b/RVO42/package-lock.json new file mode 100755 index 0000000..cc5cfd9 --- /dev/null +++ b/RVO42/package-lock.json @@ -0,0 +1,2125 @@ +{ + "name": "emptyproject", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "emptyproject", + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "bitwise": "^2.1.0", + "easy-crc": "0.0.2", + "jsmodbus": "^4.0.6", + "log4js": "^6.3.0", + "mqtt": "^4.2.6", + "nodemailer": "^6.9.7", + "serialport": "^9.2.8", + "total.js": "^3.4.13" + } + }, + "node_modules/@serialport/binding-abstract": { + "version": "9.2.3", + "resolved": "https://registry.npmjs.org/@serialport/binding-abstract/-/binding-abstract-9.2.3.tgz", + "integrity": "sha512-cQs9tbIlG3P0IrOWyVirqlhWuJ7Ms2Zh9m2108z6Y5UW/iVj6wEOiW8EmK9QX9jmJXYllE7wgGgvVozP5oCj3w==", + "dependencies": { + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/binding-mock": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/binding-mock/-/binding-mock-9.2.4.tgz", + "integrity": "sha512-dpEhACCs44oQhh6ajJfJdvQdK38Vq0N4W6iD/gdplglDCK7qXRQCMUjJIeKdS/HSEiWkC3bwumUhUufdsOyT4g==", + "dependencies": { + "@serialport/binding-abstract": "9.2.3", + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/bindings": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/@serialport/bindings/-/bindings-9.2.8.tgz", + "integrity": "sha512-hSLxTe0tADZ3LMMGwvEJWOC/TaFQTyPeFalUCsJ1lSQ0k6bPF04JwrtB/C81GetmDBTNRY0GlD0SNtKCc7Dr5g==", + "hasInstallScript": true, + "dependencies": { + "@serialport/binding-abstract": "9.2.3", + "@serialport/parser-readline": "9.2.4", + "bindings": "^1.5.0", + "debug": "^4.3.2", + "nan": "^2.15.0", + "prebuild-install": "^7.0.0" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-byte-length": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-byte-length/-/parser-byte-length-9.2.4.tgz", + "integrity": "sha512-sQD/iw4ZMU3xW9PLi0/GlvU6Y623jGeWecbMkO7izUo/6P7gtfv1c9ikd5h0kwL8AoAOpQA1lxdHIKox+umBUg==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-cctalk": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-cctalk/-/parser-cctalk-9.2.4.tgz", + "integrity": "sha512-T4TU5vQMwmo9AB3gQLFDWbfJXlW5jd9guEsB/nqKjFHTv0FXPdZ7DQ2TpSp8RnHWxU3GX6kYTaDO20BKzc8GPQ==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-delimiter": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-delimiter/-/parser-delimiter-9.2.4.tgz", + "integrity": "sha512-4nvTAoYAgkxFiXrkI+3CA49Yd43CODjeszh89EK+I9c8wOZ+etZduRCzINYPiy26g7zO+GRAb9FoPCsY+sYcbQ==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-inter-byte-timeout": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-inter-byte-timeout/-/parser-inter-byte-timeout-9.2.4.tgz", + "integrity": "sha512-SOAdvr0oBQIOCXX198hiTlxs4JTKg9j5piapw5tNq52fwDOWdbYrFneT/wN04UTMKaDrJuEvXq6T4rv4j7nJ5A==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-readline": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-readline/-/parser-readline-9.2.4.tgz", + "integrity": "sha512-Z1/qrZTQUVhNSJP1hd9YfDvq0o7d87rNwAjjRKbVpa7Qi51tG5BnKt43IV3NFMyBlVcRe0rnIb3tJu57E0SOwg==", + "dependencies": { + "@serialport/parser-delimiter": "9.2.4" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-ready": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-ready/-/parser-ready-9.2.4.tgz", + "integrity": "sha512-Pyi94Itjl6qAURwIZr/gmZpMAyTmKXThm6vL5DoAWGQjcRHWB0gwv2TY2v7N+mQLJYUKU3cMnvnATXxHm7xjxw==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-regex": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-regex/-/parser-regex-9.2.4.tgz", + "integrity": "sha512-sI/cVvPOYz+Dbv4ZdnW16qAwvXiFf/1pGASQdbveRTlgJDdz7sRNlCBifzfTN2xljwvCTZYqiudKvDdC1TepRQ==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/stream": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/stream/-/stream-9.2.4.tgz", + "integrity": "sha512-bLye8Ub4vUFQGmkh8qEqehr7SE7EJs2yDs0h9jzuL5oKi+F34CFmWkEErO8GAOQ8YNn7p6b3GxUgs+0BrHHDZQ==", + "dependencies": { + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "node_modules/are-we-there-yet": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", + "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/base64-js": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", + "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==" + }, + "node_modules/bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "dependencies": { + "file-uri-to-path": "1.0.0" + } + }, + "node_modules/bitwise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/bitwise/-/bitwise-2.1.0.tgz", + "integrity": "sha512-XKgAhMXCh4H/3oNwAHAsAO0iC89s9cOiumgYwSHjSobGWxYjv62YhkL9QEdvGP151xypCtMlAfKK79GEcd2eRQ==" + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/bl/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/buffer": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz", + "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==", + "dependencies": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + }, + "node_modules/buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" + }, + "node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, + "node_modules/code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/commist": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/commist/-/commist-1.1.0.tgz", + "integrity": "sha512-rraC8NXWOEjhADbZe9QBNzLAN5Q3fsTPQtBV+fEVj6xKIgDgNiEVE6ZNfHpZOqfQ21YUzfVNUXLOEZquYvQPPg==", + "dependencies": { + "leven": "^2.1.0", + "minimist": "^1.1.0" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "node_modules/concat-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", + "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", + "engines": [ + "node >= 6.0" + ], + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.0.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/concat-stream/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" + }, + "node_modules/core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "node_modules/crc": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/crc/-/crc-3.4.0.tgz", + "integrity": "sha512-ycVC2+4/DLgXXq7QweYi2znhqDuZz6P5TQXnkQo8v15XY/5p/IWeZwsSE31Ifo8w15b8TWLsqhXOjXyilHuQxw==" + }, + "node_modules/date-format": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.11.tgz", + "integrity": "sha512-VS20KRyorrbMCQmpdl2hg5KaOUsda1RbnsJg461FfrcyCUg+pkd0b40BSW4niQyTheww4DBXQnS7HwSrKkipLw==", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" + }, + "node_modules/detect-libc": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz", + "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==", + "engines": { + "node": ">=8" + } + }, + "node_modules/duplexify": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.2.tgz", + "integrity": "sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw==", + "dependencies": { + "end-of-stream": "^1.4.1", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1", + "stream-shift": "^1.0.0" + } + }, + "node_modules/duplexify/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/easy-crc": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/easy-crc/-/easy-crc-0.0.2.tgz", + "integrity": "sha512-h6eqIdhJRe0p271/xZJbM/0klCi13mW5IB7ZEzEGH11yV4QXWAkD4yPErz0fXdhFrd6sZ4Q1k5Iky2kMsMNePw==" + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" + }, + "node_modules/flatted": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", + "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==" + }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, + "node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "node_modules/gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha512-14x4kjc6lkD3ltw589k0NrPD6cCNTD6CWoVUNpB85+DrtONoZn+Rug6xZU5RvSC4+TZPxA5AnBibQYAvZn41Hg==", + "dependencies": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "node_modules/github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==" + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" + }, + "node_modules/has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" + }, + "node_modules/help-me": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/help-me/-/help-me-3.0.0.tgz", + "integrity": "sha512-hx73jClhyk910sidBB7ERlnhMlFsJJIBqSVMFDwPN8o2v9nmp5KgLq1Xz1Bf1fCMMZ6mPrX159iG0VLy/fPMtQ==", + "dependencies": { + "glob": "^7.1.6", + "readable-stream": "^3.6.0" + } + }, + "node_modules/help-me/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, + "node_modules/is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==", + "dependencies": { + "number-is-nan": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "node_modules/js-sdsl": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz", + "integrity": "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/js-sdsl" + } + }, + "node_modules/jsmodbus": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/jsmodbus/-/jsmodbus-4.0.6.tgz", + "integrity": "sha512-gCmjoaERErK5Rn9Lu/BN07fY13MoWV7JKgGzrnkPlQPdPxYcwDhLtYcmpFFpZ4J9NPZZBSezi1UkLZO/DnNppA==", + "dependencies": { + "crc": "3.4.0", + "debug": "^3.1.0" + }, + "bin": { + "jsmodbus": "bin/jsmodbus.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/jsmodbus/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/leven": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", + "integrity": "sha1-wuep93IJTe6dNCAq6KzORoeHVYA=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/log4js": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.5.2.tgz", + "integrity": "sha512-DXtpNtt+KDOMT7RHUDIur/WsSA3rntlUh9Zg4XCdV42wUuMmbFkl38+LZ92Z5QvQA7mD5kAVkLiBSEH/tvUB8A==", + "dependencies": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "flatted": "^3.2.5", + "rfdc": "^1.3.0", + "streamroller": "^3.1.1" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" + }, + "node_modules/mqtt": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/mqtt/-/mqtt-4.3.7.tgz", + "integrity": "sha512-ew3qwG/TJRorTz47eW46vZ5oBw5MEYbQZVaEji44j5lAUSQSqIEoul7Kua/BatBW0H0kKQcC9kwUHa1qzaWHSw==", + "dependencies": { + "commist": "^1.0.0", + "concat-stream": "^2.0.0", + "debug": "^4.1.1", + "duplexify": "^4.1.1", + "help-me": "^3.0.0", + "inherits": "^2.0.3", + "lru-cache": "^6.0.0", + "minimist": "^1.2.5", + "mqtt-packet": "^6.8.0", + "number-allocator": "^1.0.9", + "pump": "^3.0.0", + "readable-stream": "^3.6.0", + "reinterval": "^1.1.0", + "rfdc": "^1.3.0", + "split2": "^3.1.0", + "ws": "^7.5.5", + "xtend": "^4.0.2" + }, + "bin": { + "mqtt": "bin/mqtt.js", + "mqtt_pub": "bin/pub.js", + "mqtt_sub": "bin/sub.js" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/mqtt-packet": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/mqtt-packet/-/mqtt-packet-6.10.0.tgz", + "integrity": "sha512-ja8+mFKIHdB1Tpl6vac+sktqy3gA8t9Mduom1BA75cI+R9AHnZOiaBQwpGiWnaVJLDGRdNhQmFaAqd7tkKSMGA==", + "dependencies": { + "bl": "^4.0.2", + "debug": "^4.1.1", + "process-nextick-args": "^2.0.1" + } + }, + "node_modules/mqtt/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/nan": { + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.16.0.tgz", + "integrity": "sha512-UdAqHyFngu7TfQKsCBgAA6pWDkT8MAO7d0jyOecVhN5354xbLqdn8mV9Tat9gepAupm0bt2DbeaSC8vS52MuFA==" + }, + "node_modules/napi-build-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", + "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==" + }, + "node_modules/node-abi": { + "version": "3.22.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.22.0.tgz", + "integrity": "sha512-u4uAs/4Zzmp/jjsD9cyFYDXeISfUWaAVWshPmDZOFOv4Xl4SbzTXm53I04C2uRueYJ+0t5PEtLH/owbn2Npf/w==", + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/nodemailer": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.7.tgz", + "integrity": "sha512-rUtR77ksqex/eZRLmQ21LKVH5nAAsVicAtAYudK7JgwenEDZ0UIQ1adUGqErz7sMkWYxWTTU1aeP2Jga6WQyJw==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "dependencies": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "node_modules/number-allocator": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/number-allocator/-/number-allocator-1.0.14.tgz", + "integrity": "sha512-OrL44UTVAvkKdOdRQZIJpLkAdjXGTRda052sN4sO77bKEzYYqWKMBjQvrJFzqygI99gL6Z4u2xctPW1tB8ErvA==", + "dependencies": { + "debug": "^4.3.1", + "js-sdsl": "4.3.0" + } + }, + "node_modules/number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/prebuild-install": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.0.tgz", + "integrity": "sha512-CNcMgI1xBypOyGqjp3wOc8AAo1nMhZS3Cwd3iHIxOdAUbb+YxdNuM4Z5iIrZ8RLvOsf3F3bl7b7xGq6DjQoNYA==", + "dependencies": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^1.0.1", + "node-abi": "^3.3.0", + "npmlog": "^4.0.1", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + }, + "bin": { + "prebuild-install": "bin.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/reinterval": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reinterval/-/reinterval-1.1.0.tgz", + "integrity": "sha1-M2Hs+jymwYKDOA3Qu5VG85D17Oc=" + }, + "node_modules/rfdc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==" + }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/serialport": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/serialport/-/serialport-9.2.8.tgz", + "integrity": "sha512-FsWpMQgSJxi93JgWl5xM1f9/Z8IjRJuaUEoHqLf8FPBLw7gMhInuHOBhI2onQufWIYPGTz3H3oGcu1nCaK1EfA==", + "dependencies": { + "@serialport/binding-mock": "9.2.4", + "@serialport/bindings": "9.2.8", + "@serialport/parser-byte-length": "9.2.4", + "@serialport/parser-cctalk": "9.2.4", + "@serialport/parser-delimiter": "9.2.4", + "@serialport/parser-inter-byte-timeout": "9.2.4", + "@serialport/parser-readline": "9.2.4", + "@serialport/parser-ready": "9.2.4", + "@serialport/parser-regex": "9.2.4", + "@serialport/stream": "9.2.4", + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "node_modules/split2": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", + "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", + "dependencies": { + "readable-stream": "^3.0.0" + } + }, + "node_modules/split2/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==" + }, + "node_modules/streamroller": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.1.1.tgz", + "integrity": "sha512-iPhtd9unZ6zKdWgMeYGfSBuqCngyJy1B/GPi/lTpwGpa3bajuX30GjUVd0/Tn/Xhg0mr4DOSENozz9Y06qyonQ==", + "dependencies": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "fs-extra": "^10.1.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dependencies": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/tar-fs": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "dependencies": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tar-stream/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/total.js": { + "version": "3.4.13", + "resolved": "https://registry.npmjs.org/total.js/-/total.js-3.4.13.tgz", + "integrity": "sha512-lAH4gEixlPFbrE3xfKADAcHfO79IFq2wKa9GTsrgRzIR5MTg3mNH7+4IxvX1pK8faoYb/0oYSJ1YTsAa5hIFFQ==", + "bin": { + "total": "bin/totaljs", + "total.js": "bin/totaljs", + "totaljs": "bin/totaljs", + "totalpackage": "bin/tpm", + "tpm": "bin/tpm" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, + "node_modules/universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "node_modules/wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "node_modules/ws": { + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } + }, + "dependencies": { + "@serialport/binding-abstract": { + "version": "9.2.3", + "resolved": "https://registry.npmjs.org/@serialport/binding-abstract/-/binding-abstract-9.2.3.tgz", + "integrity": "sha512-cQs9tbIlG3P0IrOWyVirqlhWuJ7Ms2Zh9m2108z6Y5UW/iVj6wEOiW8EmK9QX9jmJXYllE7wgGgvVozP5oCj3w==", + "requires": { + "debug": "^4.3.2" + } + }, + "@serialport/binding-mock": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/binding-mock/-/binding-mock-9.2.4.tgz", + "integrity": "sha512-dpEhACCs44oQhh6ajJfJdvQdK38Vq0N4W6iD/gdplglDCK7qXRQCMUjJIeKdS/HSEiWkC3bwumUhUufdsOyT4g==", + "requires": { + "@serialport/binding-abstract": "9.2.3", + "debug": "^4.3.2" + } + }, + "@serialport/bindings": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/@serialport/bindings/-/bindings-9.2.8.tgz", + "integrity": "sha512-hSLxTe0tADZ3LMMGwvEJWOC/TaFQTyPeFalUCsJ1lSQ0k6bPF04JwrtB/C81GetmDBTNRY0GlD0SNtKCc7Dr5g==", + "requires": { + "@serialport/binding-abstract": "9.2.3", + "@serialport/parser-readline": "9.2.4", + "bindings": "^1.5.0", + "debug": "^4.3.2", + "nan": "^2.15.0", + "prebuild-install": "^7.0.0" + } + }, + "@serialport/parser-byte-length": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-byte-length/-/parser-byte-length-9.2.4.tgz", + "integrity": "sha512-sQD/iw4ZMU3xW9PLi0/GlvU6Y623jGeWecbMkO7izUo/6P7gtfv1c9ikd5h0kwL8AoAOpQA1lxdHIKox+umBUg==" + }, + "@serialport/parser-cctalk": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-cctalk/-/parser-cctalk-9.2.4.tgz", + "integrity": "sha512-T4TU5vQMwmo9AB3gQLFDWbfJXlW5jd9guEsB/nqKjFHTv0FXPdZ7DQ2TpSp8RnHWxU3GX6kYTaDO20BKzc8GPQ==" + }, + "@serialport/parser-delimiter": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-delimiter/-/parser-delimiter-9.2.4.tgz", + "integrity": "sha512-4nvTAoYAgkxFiXrkI+3CA49Yd43CODjeszh89EK+I9c8wOZ+etZduRCzINYPiy26g7zO+GRAb9FoPCsY+sYcbQ==" + }, + "@serialport/parser-inter-byte-timeout": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-inter-byte-timeout/-/parser-inter-byte-timeout-9.2.4.tgz", + "integrity": "sha512-SOAdvr0oBQIOCXX198hiTlxs4JTKg9j5piapw5tNq52fwDOWdbYrFneT/wN04UTMKaDrJuEvXq6T4rv4j7nJ5A==" + }, + "@serialport/parser-readline": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-readline/-/parser-readline-9.2.4.tgz", + "integrity": "sha512-Z1/qrZTQUVhNSJP1hd9YfDvq0o7d87rNwAjjRKbVpa7Qi51tG5BnKt43IV3NFMyBlVcRe0rnIb3tJu57E0SOwg==", + "requires": { + "@serialport/parser-delimiter": "9.2.4" + } + }, + "@serialport/parser-ready": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-ready/-/parser-ready-9.2.4.tgz", + "integrity": "sha512-Pyi94Itjl6qAURwIZr/gmZpMAyTmKXThm6vL5DoAWGQjcRHWB0gwv2TY2v7N+mQLJYUKU3cMnvnATXxHm7xjxw==" + }, + "@serialport/parser-regex": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-regex/-/parser-regex-9.2.4.tgz", + "integrity": "sha512-sI/cVvPOYz+Dbv4ZdnW16qAwvXiFf/1pGASQdbveRTlgJDdz7sRNlCBifzfTN2xljwvCTZYqiudKvDdC1TepRQ==" + }, + "@serialport/stream": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/stream/-/stream-9.2.4.tgz", + "integrity": "sha512-bLye8Ub4vUFQGmkh8qEqehr7SE7EJs2yDs0h9jzuL5oKi+F34CFmWkEErO8GAOQ8YNn7p6b3GxUgs+0BrHHDZQ==", + "requires": { + "debug": "^4.3.2" + } + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==" + }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "are-we-there-yet": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", + "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "base64-js": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", + "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==" + }, + "bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "requires": { + "file-uri-to-path": "1.0.0" + } + }, + "bitwise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/bitwise/-/bitwise-2.1.0.tgz", + "integrity": "sha512-XKgAhMXCh4H/3oNwAHAsAO0iC89s9cOiumgYwSHjSobGWxYjv62YhkL9QEdvGP151xypCtMlAfKK79GEcd2eRQ==" + }, + "bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "requires": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "buffer": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz", + "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==", + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" + }, + "chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==" + }, + "commist": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/commist/-/commist-1.1.0.tgz", + "integrity": "sha512-rraC8NXWOEjhADbZe9QBNzLAN5Q3fsTPQtBV+fEVj6xKIgDgNiEVE6ZNfHpZOqfQ21YUzfVNUXLOEZquYvQPPg==", + "requires": { + "leven": "^2.1.0", + "minimist": "^1.1.0" + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "concat-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", + "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.0.2", + "typedarray": "^0.0.6" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "crc": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/crc/-/crc-3.4.0.tgz", + "integrity": "sha512-ycVC2+4/DLgXXq7QweYi2znhqDuZz6P5TQXnkQo8v15XY/5p/IWeZwsSE31Ifo8w15b8TWLsqhXOjXyilHuQxw==" + }, + "date-format": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.11.tgz", + "integrity": "sha512-VS20KRyorrbMCQmpdl2hg5KaOUsda1RbnsJg461FfrcyCUg+pkd0b40BSW4niQyTheww4DBXQnS7HwSrKkipLw==" + }, + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "requires": { + "ms": "2.1.2" + } + }, + "decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "requires": { + "mimic-response": "^3.1.0" + } + }, + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==" + }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" + }, + "detect-libc": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz", + "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==" + }, + "duplexify": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.2.tgz", + "integrity": "sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw==", + "requires": { + "end-of-stream": "^1.4.1", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1", + "stream-shift": "^1.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "easy-crc": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/easy-crc/-/easy-crc-0.0.2.tgz", + "integrity": "sha512-h6eqIdhJRe0p271/xZJbM/0klCi13mW5IB7ZEzEGH11yV4QXWAkD4yPErz0fXdhFrd6sZ4Q1k5Iky2kMsMNePw==" + }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "requires": { + "once": "^1.4.0" + } + }, + "expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==" + }, + "file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" + }, + "flatted": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", + "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==" + }, + "fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, + "fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha512-14x4kjc6lkD3ltw589k0NrPD6cCNTD6CWoVUNpB85+DrtONoZn+Rug6xZU5RvSC4+TZPxA5AnBibQYAvZn41Hg==", + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==" + }, + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" + }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" + }, + "help-me": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/help-me/-/help-me-3.0.0.tgz", + "integrity": "sha512-hx73jClhyk910sidBB7ERlnhMlFsJJIBqSVMFDwPN8o2v9nmp5KgLq1Xz1Bf1fCMMZ6mPrX159iG0VLy/fPMtQ==", + "requires": { + "glob": "^7.1.6", + "readable-stream": "^3.6.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==", + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "js-sdsl": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz", + "integrity": "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==" + }, + "jsmodbus": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/jsmodbus/-/jsmodbus-4.0.6.tgz", + "integrity": "sha512-gCmjoaERErK5Rn9Lu/BN07fY13MoWV7JKgGzrnkPlQPdPxYcwDhLtYcmpFFpZ4J9NPZZBSezi1UkLZO/DnNppA==", + "requires": { + "crc": "3.4.0", + "debug": "^3.1.0" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "requires": { + "ms": "^2.1.1" + } + } + } + }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, + "leven": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", + "integrity": "sha1-wuep93IJTe6dNCAq6KzORoeHVYA=" + }, + "log4js": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.5.2.tgz", + "integrity": "sha512-DXtpNtt+KDOMT7RHUDIur/WsSA3rntlUh9Zg4XCdV42wUuMmbFkl38+LZ92Z5QvQA7mD5kAVkLiBSEH/tvUB8A==", + "requires": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "flatted": "^3.2.5", + "rfdc": "^1.3.0", + "streamroller": "^3.1.1" + } + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "requires": { + "yallist": "^4.0.0" + } + }, + "mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==" + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==" + }, + "mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" + }, + "mqtt": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/mqtt/-/mqtt-4.3.7.tgz", + "integrity": "sha512-ew3qwG/TJRorTz47eW46vZ5oBw5MEYbQZVaEji44j5lAUSQSqIEoul7Kua/BatBW0H0kKQcC9kwUHa1qzaWHSw==", + "requires": { + "commist": "^1.0.0", + "concat-stream": "^2.0.0", + "debug": "^4.1.1", + "duplexify": "^4.1.1", + "help-me": "^3.0.0", + "inherits": "^2.0.3", + "lru-cache": "^6.0.0", + "minimist": "^1.2.5", + "mqtt-packet": "^6.8.0", + "number-allocator": "^1.0.9", + "pump": "^3.0.0", + "readable-stream": "^3.6.0", + "reinterval": "^1.1.0", + "rfdc": "^1.3.0", + "split2": "^3.1.0", + "ws": "^7.5.5", + "xtend": "^4.0.2" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "mqtt-packet": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/mqtt-packet/-/mqtt-packet-6.10.0.tgz", + "integrity": "sha512-ja8+mFKIHdB1Tpl6vac+sktqy3gA8t9Mduom1BA75cI+R9AHnZOiaBQwpGiWnaVJLDGRdNhQmFaAqd7tkKSMGA==", + "requires": { + "bl": "^4.0.2", + "debug": "^4.1.1", + "process-nextick-args": "^2.0.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "nan": { + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.16.0.tgz", + "integrity": "sha512-UdAqHyFngu7TfQKsCBgAA6pWDkT8MAO7d0jyOecVhN5354xbLqdn8mV9Tat9gepAupm0bt2DbeaSC8vS52MuFA==" + }, + "napi-build-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", + "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==" + }, + "node-abi": { + "version": "3.22.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.22.0.tgz", + "integrity": "sha512-u4uAs/4Zzmp/jjsD9cyFYDXeISfUWaAVWshPmDZOFOv4Xl4SbzTXm53I04C2uRueYJ+0t5PEtLH/owbn2Npf/w==", + "requires": { + "semver": "^7.3.5" + } + }, + "nodemailer": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.7.tgz", + "integrity": "sha512-rUtR77ksqex/eZRLmQ21LKVH5nAAsVicAtAYudK7JgwenEDZ0UIQ1adUGqErz7sMkWYxWTTU1aeP2Jga6WQyJw==" + }, + "npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "number-allocator": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/number-allocator/-/number-allocator-1.0.14.tgz", + "integrity": "sha512-OrL44UTVAvkKdOdRQZIJpLkAdjXGTRda052sN4sO77bKEzYYqWKMBjQvrJFzqygI99gL6Z4u2xctPW1tB8ErvA==", + "requires": { + "debug": "^4.3.1", + "js-sdsl": "4.3.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==" + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==" + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==" + }, + "prebuild-install": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.0.tgz", + "integrity": "sha512-CNcMgI1xBypOyGqjp3wOc8AAo1nMhZS3Cwd3iHIxOdAUbb+YxdNuM4Z5iIrZ8RLvOsf3F3bl7b7xGq6DjQoNYA==", + "requires": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^1.0.1", + "node-abi": "^3.3.0", + "npmlog": "^4.0.1", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + } + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + } + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "reinterval": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reinterval/-/reinterval-1.1.0.tgz", + "integrity": "sha1-M2Hs+jymwYKDOA3Qu5VG85D17Oc=" + }, + "rfdc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==" + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "requires": { + "lru-cache": "^6.0.0" + } + }, + "serialport": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/serialport/-/serialport-9.2.8.tgz", + "integrity": "sha512-FsWpMQgSJxi93JgWl5xM1f9/Z8IjRJuaUEoHqLf8FPBLw7gMhInuHOBhI2onQufWIYPGTz3H3oGcu1nCaK1EfA==", + "requires": { + "@serialport/binding-mock": "9.2.4", + "@serialport/bindings": "9.2.8", + "@serialport/parser-byte-length": "9.2.4", + "@serialport/parser-cctalk": "9.2.4", + "@serialport/parser-delimiter": "9.2.4", + "@serialport/parser-inter-byte-timeout": "9.2.4", + "@serialport/parser-readline": "9.2.4", + "@serialport/parser-ready": "9.2.4", + "@serialport/parser-regex": "9.2.4", + "@serialport/stream": "9.2.4", + "debug": "^4.3.2" + } + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==" + }, + "simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "requires": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "split2": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", + "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", + "requires": { + "readable-stream": "^3.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==" + }, + "streamroller": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.1.1.tgz", + "integrity": "sha512-iPhtd9unZ6zKdWgMeYGfSBuqCngyJy1B/GPi/lTpwGpa3bajuX30GjUVd0/Tn/Xhg0mr4DOSENozz9Y06qyonQ==", + "requires": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "fs-extra": "^10.1.0" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" + }, + "tar-fs": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "requires": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "requires": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "total.js": { + "version": "3.4.13", + "resolved": "https://registry.npmjs.org/total.js/-/total.js-3.4.13.tgz", + "integrity": "sha512-lAH4gEixlPFbrE3xfKADAcHfO79IFq2wKa9GTsrgRzIR5MTg3mNH7+4IxvX1pK8faoYb/0oYSJ1YTsAa5hIFFQ==" + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, + "universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==" + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "requires": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "ws": { + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "requires": {} + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } + } +} diff --git a/RVO42/package.json b/RVO42/package.json new file mode 100755 index 0000000..e524d7c --- /dev/null +++ b/RVO42/package.json @@ -0,0 +1,29 @@ +{ + "name": "emptyproject", + "description": "Total.js empty project.", + "version": "1.0.0", + "main": "debug.js", + "dependencies": { + "bitwise": "^2.1.0", + "easy-crc": "0.0.2", + "jsmodbus": "^4.0.6", + "log4js": "^6.3.0", + "mqtt": "^4.2.6", + "nodemailer": "^6.9.7", + "serialport": "^9.2.8", + "total.js": "^3.4.13" + }, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "https://github.com/totaljs/emptyproject-flow" + }, + "keywords": [ + "empty", + "project" + ], + "author": "Peter Širka", + "license": "MIT" +} diff --git a/RVO42/release.js b/RVO42/release.js new file mode 100755 index 0000000..02d52ff --- /dev/null +++ b/RVO42/release.js @@ -0,0 +1,15 @@ +// =================================================== +// FOR PRODUCTION +// Total.js - framework for Node.js platform +// https://www.totaljs.com +// =================================================== + +const options = {'ip':'0.0.0.0', 'port':12345}; + +// options.ip = '127.0.0.1'; +// options.port = parseInt(process.argv[2]); +// options.config = { name: 'Total.js' }; +// options.sleep = 3000; + +require('total.js').http('release', options); +// require('total.js').cluster.http(5, 'release', options); diff --git a/RVO42/release.js.json b/RVO42/release.js.json new file mode 100755 index 0000000..07d8329 --- /dev/null +++ b/RVO42/release.js.json @@ -0,0 +1,34 @@ +{ + "pid": 409, + "stats": [ + { + "id": null, + "version": { + "node": "v14.18.1", + "total": "3.4.13", + "app": "1.0.0" + }, + "pid": 409, + "thread": "", + "mode": "release", + "overload": 0, + "date": "2025-10-16T00:26:09.306Z", + "memory": 22.23, + "rm": 0, + "fm": 0, + "wm": 0, + "mm": 0, + "om": 2, + "em": 0, + "dbrm": 0, + "dbwm": 0, + "usage": 0, + "requests": 7, + "pending": 0, + "errors": 0, + "timeouts": 0, + "uptime": 877, + "online": 0 + } + ] +} \ No newline at end of file diff --git a/RVO42/report_data.log b/RVO42/report_data.log new file mode 100755 index 0000000..2f5a769 --- /dev/null +++ b/RVO42/report_data.log @@ -0,0 +1,196 @@ +{ + "name": "rvo_senica_42_ip118", + "time": "2025-10-15T10:50:24.534Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_42_ip118", + "time": "2025-10-15T11:50:24.532Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_42_ip118", + "time": "2025-10-15T12:50:24.532Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_42_ip118", + "time": "2025-10-15T13:50:24.532Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_42_ip118", + "time": "2025-10-15T14:50:24.533Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_42_ip118", + "time": "2025-10-15T15:50:24.533Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_42_ip118", + "time": "2025-10-15T17:33:01.711Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_42_ip118", + "time": "2025-10-15T18:33:01.712Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_42_ip118", + "time": "2025-10-15T19:33:01.711Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_42_ip118", + "time": "2025-10-15T20:33:01.712Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_42_ip118", + "time": "2025-10-15T21:33:01.712Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_42_ip118", + "time": "2025-10-15T22:33:01.712Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_42_ip118", + "time": "2025-10-15T23:33:01.712Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +} \ No newline at end of file From df0fe9a732618aa41e978e7747d78964f2b4f1ae Mon Sep 17 00:00:00 2001 From: Jakub Klena Date: Thu, 16 Oct 2025 02:26:50 +0200 Subject: [PATCH 24/30] Backup senica-RVO43 on 16.10.2025 --- RVO43/addSwitch.py | 36 + RVO43/cloud_topic.py | 76 + RVO43/config | 12 + RVO43/createNode.py | 43 + RVO43/databases/accelerometer_db.js | 3055 ++++++++++++++++ RVO43/databases/modbus_config.js | 114 + RVO43/databases/nodes.table | 91 + .../nodes_original/nodes_original.table | 1 + RVO43/databases/notifications.table | 41 + RVO43/databases/pins.table | 14 + RVO43/databases/relays.table | 5 + RVO43/databases/settings.table | 2 + RVO43/databases/tbdata.nosql | 4 + RVO43/databases/tbdatacloud.nosql | 3 + RVO43/databases/total_energy.js | 38 + RVO43/debug.js | 16 + RVO43/err.txt | 67 + RVO43/flow/cloudmqttconnect.js | 357 ++ RVO43/flow/cmd_manager.js | 3071 ++++++++++++++++ RVO43/flow/code.js | 90 + RVO43/flow/comment.js | 11 + RVO43/flow/count.js | 60 + RVO43/flow/db_connector.js | 286 ++ RVO43/flow/db_init.js | 113 + RVO43/flow/debug.js | 100 + RVO43/flow/designer.json | 3102 +++++++++++++++++ RVO43/flow/dido_controller.js | 1486 ++++++++ RVO43/flow/helper/DataToTbHandler.js | 187 + RVO43/flow/helper/ErrorToServiceHandler.js | 91 + RVO43/flow/helper/db_helper.js | 44 + RVO43/flow/helper/logger.js | 30 + RVO43/flow/helper/md5.js | 5 + RVO43/flow/helper/notification_reporter.js | 121 + RVO43/flow/helper/register.js | 144 + RVO43/flow/helper/serialport_helper.js | 99 + RVO43/flow/helper/suncalc.js | 317 ++ RVO43/flow/helper/utils.js | 161 + RVO43/flow/httprequest.js | 137 + RVO43/flow/httpresponse.js | 76 + RVO43/flow/httproute.js | 326 ++ RVO43/flow/infosender.js | 81 + RVO43/flow/modbus_reader.js | 346 ++ RVO43/flow/monitorconsumption.js | 156 + RVO43/flow/monitordisk.js | 96 + RVO43/flow/monitormemory.js | 87 + RVO43/flow/nodesdb_changecheck.js | 77 + RVO43/flow/show_dbdata.js | 243 ++ RVO43/flow/slack_filter.js | 188 + RVO43/flow/thermometer.js | 99 + RVO43/flow/trigger.js | 79 + RVO43/flow/variables.txt | 0 RVO43/flow/virtualwirein.js | 43 + RVO43/flow/virtualwireout.js | 41 + RVO43/flow/wsmqttpublish.js | 448 +++ RVO43/monitor.txt | 269 ++ RVO43/package-lock.json | 2139 ++++++++++++ RVO43/package.json | 30 + RVO43/release.js | 15 + RVO43/release.js.json | 34 + RVO43/report_data.log | 136 + 60 files changed, 18639 insertions(+) create mode 100755 RVO43/addSwitch.py create mode 100755 RVO43/cloud_topic.py create mode 100755 RVO43/config create mode 100755 RVO43/createNode.py create mode 100755 RVO43/databases/accelerometer_db.js create mode 100755 RVO43/databases/modbus_config.js create mode 100755 RVO43/databases/nodes.table create mode 100755 RVO43/databases/nodes_original/nodes_original.table create mode 100755 RVO43/databases/notifications.table create mode 100755 RVO43/databases/pins.table create mode 100755 RVO43/databases/relays.table create mode 100755 RVO43/databases/settings.table create mode 100755 RVO43/databases/tbdata.nosql create mode 100755 RVO43/databases/tbdatacloud.nosql create mode 100755 RVO43/databases/total_energy.js create mode 100755 RVO43/debug.js create mode 100755 RVO43/err.txt create mode 100755 RVO43/flow/cloudmqttconnect.js create mode 100755 RVO43/flow/cmd_manager.js create mode 100755 RVO43/flow/code.js create mode 100755 RVO43/flow/comment.js create mode 100755 RVO43/flow/count.js create mode 100755 RVO43/flow/db_connector.js create mode 100755 RVO43/flow/db_init.js create mode 100755 RVO43/flow/debug.js create mode 100755 RVO43/flow/designer.json create mode 100755 RVO43/flow/dido_controller.js create mode 100755 RVO43/flow/helper/DataToTbHandler.js create mode 100755 RVO43/flow/helper/ErrorToServiceHandler.js create mode 100755 RVO43/flow/helper/db_helper.js create mode 100755 RVO43/flow/helper/logger.js create mode 100755 RVO43/flow/helper/md5.js create mode 100755 RVO43/flow/helper/notification_reporter.js create mode 100755 RVO43/flow/helper/register.js create mode 100755 RVO43/flow/helper/serialport_helper.js create mode 100755 RVO43/flow/helper/suncalc.js create mode 100755 RVO43/flow/helper/utils.js create mode 100755 RVO43/flow/httprequest.js create mode 100755 RVO43/flow/httpresponse.js create mode 100755 RVO43/flow/httproute.js create mode 100755 RVO43/flow/infosender.js create mode 100755 RVO43/flow/modbus_reader.js create mode 100755 RVO43/flow/monitorconsumption.js create mode 100755 RVO43/flow/monitordisk.js create mode 100755 RVO43/flow/monitormemory.js create mode 100755 RVO43/flow/nodesdb_changecheck.js create mode 100755 RVO43/flow/show_dbdata.js create mode 100755 RVO43/flow/slack_filter.js create mode 100755 RVO43/flow/thermometer.js create mode 100755 RVO43/flow/trigger.js create mode 100755 RVO43/flow/variables.txt create mode 100755 RVO43/flow/virtualwirein.js create mode 100755 RVO43/flow/virtualwireout.js create mode 100755 RVO43/flow/wsmqttpublish.js create mode 100755 RVO43/monitor.txt create mode 100755 RVO43/package-lock.json create mode 100755 RVO43/package.json create mode 100755 RVO43/release.js create mode 100755 RVO43/release.js.json create mode 100755 RVO43/report_data.log diff --git a/RVO43/addSwitch.py b/RVO43/addSwitch.py new file mode 100755 index 0000000..c35e96b --- /dev/null +++ b/RVO43/addSwitch.py @@ -0,0 +1,36 @@ +import os + +def process_set_file(): + """ + Checks if /root/flowserver exists, reads set.txt, and modifies the second line. + """ + default_folder = "/root/flowserver" if os.path.exists("/root/flowserver") else "/home/unipi/flowserver" + flag = 1 if default_folder == "/root/flowserver" else 0 + + try: + with open("/home/unipi/flowserver/databases/settings.table", "r") as f: + lines = f.readlines() + + if len(lines) >= 2: + lines[0] = lines[0].rstrip('\n') + "|main_switch:boolean\n" + second_line = lines[1].strip() # remove trailing newline + last_pipe_index = second_line.rfind("|") + + if last_pipe_index != -1: + modified_line = second_line[:last_pipe_index + 1] + str(flag) + "|" + second_line[last_pipe_index + 1:] + lines[1] = modified_line + else: + print("Warning: No '|' character found in the second line of set.txt") + + with open("/home/unipi/flowserver/databases/settings.table", "w") as f: + f.writelines(lines) + else: + print("Warning: settings.table has less than two lines.") + + except FileNotFoundError: + print("Error: settings.table not found.") + except Exception as e: + print(e) + +# if __name__ == "__main__": +process_set_file() diff --git a/RVO43/cloud_topic.py b/RVO43/cloud_topic.py new file mode 100755 index 0000000..77c31f1 --- /dev/null +++ b/RVO43/cloud_topic.py @@ -0,0 +1,76 @@ +# import os +# +# def modify_file(file_path): +# """ +# Modifies the given file by: +# 1. Appending "|cloud_topic" to the first line. +# 2. Inserting the text from the third "." to the first "|" on the second line after the last "|" character. +# +# Args: +# file_path (str): The path to the file to be modified. +# """ +# +# with open(file_path, 'r+') as f: +# lines = f.readlines() +# +# # Modify the first line +# lines[0] += "|cloud_topic:string" +# +# # Modify the second line +# second_line = lines[1].strip() # Remove leading/trailing whitespace +# first_pipe_index = second_line.find('|') +# third_dot_index = second_line.find('.', second_line.find('.', second_line.find('.') + 1) + 1) +# text_to_insert = second_line[third_dot_index:first_pipe_index] +# +# last_pipe_index = second_line.rfind('|') +# lines[1] = second_line[:last_pipe_index + 1] + text_to_insert + "|" + second_line[last_pipe_index + 1:] +# +# print(first_pipe_index, third_dot_index, text_to_insert, last_pipe_index) +# # Write the modified lines back to the file +# # f.seek(0) +# # f.writelines(lines) +# # f.truncate() +# +# # Example usage: +# file_path = "settings.table" # Replace with the actual file path +# modify_file(file_path) +# + + +def modify_file(file_path): + """ + Modifies the given file by: + 1. Appending "|cloud_topic" to the first line. + 2. Inserting the text between the third "." and the second "|" on the second line after the last "|" character. + + Args: + file_path (str): The path to the file to be modified. + """ + + with open(file_path, 'r+') as f: + lines = f.readlines() + + first_line = lines[0].strip() + first_line += "|cloud_topic:string\n" + # Modify the first line + lines[0] = first_line + + # Modify the second line + second_line = lines[1].strip() # Remove leading/trailing whitespace + first_pipe_index = second_line.find('|') + second_pipe_index = second_line.find('|', first_pipe_index + 1) + third_dot_index = second_line.find('.', second_line.find('.', second_line.find('.') + 1) + 1) + text_to_insert = "u" + second_line[third_dot_index+1:second_pipe_index] + + last_pipe_index = second_line.rfind('|') + lines[1] = second_line[:last_pipe_index + 1] + text_to_insert + "|" + second_line[last_pipe_index + 1:] + + print(first_pipe_index, third_dot_index, text_to_insert, last_pipe_index) + # Write the modified lines back to the file + f.seek(0) + f.writelines(lines) + f.truncate() + +# Example usage: +file_path = "/home/unipi/flowserver/databases/settings.table" # Replace with the actual file path +modify_file(file_path) diff --git a/RVO43/config b/RVO43/config new file mode 100755 index 0000000..cd0a8a9 --- /dev/null +++ b/RVO43/config @@ -0,0 +1,12 @@ +name : Total.js Flow +default_timezone : Europe/Bratislava + +// Packages settings +package#flow (Object) : { url: '/' } + + +table.relays : line:number|tbname:string|contactor:number|profile:string +table.nodes : node:number|pole_number:string|node_type:string|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|project_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|cloud_topic:string|has_main_switch:boolean|daily_report:boolean|send_changed_node_numbers:boolean +table.pins : pin:string|type:string|line:number +table.notifications : key:string|weight:string|sk:string|en:string diff --git a/RVO43/createNode.py b/RVO43/createNode.py new file mode 100755 index 0000000..a8cea91 --- /dev/null +++ b/RVO43/createNode.py @@ -0,0 +1,43 @@ +print("zaciname") +import re, json + +search_str = '|' +final = [] +counter = 1 +with open("/home/unipi/flowserver/databases/nodes.table", 'r') as file: +# with open("/home/rasta5man/dev/oms/flowserver/databases/nodes.table", 'r') as file: + # Read each line in the file + for line in file: + # Print each line + line = line.strip() + print(line) + if counter != 1: + i = [m.start() for m in re.finditer(re.escape(search_str), line)] + node = line[ i[0] + 1 : i[1] ] + tbname = line[ i[3] + 1 : i[4] ] + final.append({node:tbname}) + counter += 1 +print(json.dumps(final)) +f = open("/home/unipi/flowserver/databases/nodes_original/nodes_original.table", "w") +f.write(json.dumps(final)) +f.close() + + +# +# # ``d`` has to be replaced with a different character +# old_character = "'" +# +# # ``t`` will replace ``d` +# new_character = '"' +# resultant_string = 0; +# with open("/home/unipi/flowserver/databases/nodes_original/nodes_original.table", 'r') as file: +# for line in file: +# resultant_string = re.sub("'", '"', line) +# +# resultant_string = re.sub(" ", "", resultant_string) +# print(resultant_string) +# +# f = open("/home/unipi/flowserver/databases/nodes_original/nodes_original.table", "w") +# f.write(str(resultant_string)) +# f.close() +# diff --git a/RVO43/databases/accelerometer_db.js b/RVO43/databases/accelerometer_db.js new file mode 100755 index 0000000..fdfc7fd --- /dev/null +++ b/RVO43/databases/accelerometer_db.js @@ -0,0 +1,3055 @@ +let naklony = { + "3993": { "label": "1/3A", "naklon": 0 }, + "3989": { "label": "1/3B", "naklon": 15 }, + "3976": { "label": "1/1", "naklon": 0 }, + "4181": { "label": "1/2", "naklon": 0 }, + "4376": { "label": "1/4", "naklon": 15 }, + "3868": { "label": "1/5", "naklon": 15 }, + "3728": { "label": "1/6", "naklon": 15 }, + "3730": { "label": "1/7", "naklon": 0 }, + "4374": { "label": "1/8", "naklon": 0 }, + "3718": { "label": "1/9", "naklon": 15 }, + "4375": { "label": "1/10", "naklon": 15 }, + "4172": { "label": "1/11", "naklon": 15 }, + "4176": { "label": "1/12", "naklon": 15 }, + "3800": { "label": "2/1", "naklon": 5 }, + "3823": { "label": "2/2", "naklon": 5 }, + "3905": { "label": "2/3", "naklon": 5 }, + "3803": { "label": "2/4", "naklon": 5 }, + "3817": { "label": "2/5", "naklon": 5 }, + "3818": { "label": "2/6", "naklon": 5 }, + "3811": { "label": "2/7", "naklon": 5 }, + "3915": { "label": "2/8", "naklon": 5 }, + "3843": { "label": "2/9", "naklon": 10 }, + "3827": { "label": "2/10", "naklon": 10 }, + "4220": { "label": "2/11", "naklon": 10 }, + "3826": { "label": "2/12", "naklon": 10 }, + "3834": { "label": "2/13", "naklon": 10 }, + "3838": { "label": "2/14", "naklon": 10 }, + "2823": { "label": "2/15", "naklon": 10 }, + "3750": { "label": "2/16", "naklon": 10 }, + "3378": { "label": "2/17", "naklon": 0 }, + "3376": { "label": "2/18", "naklon": 0 }, + "3379": { "label": "2/19", "naklon": 0 }, + "3285": { "label": "2/20", "naklon": 0 }, + "3382": { "label": "2/21", "naklon": 0 }, + "3383": { "label": "2/22", "naklon": 0 }, + "3375": { "label": "2/24", "naklon": 0 }, + "3381": { "label": "2/25", "naklon": 0 }, + "3380": { "label": "2/26", "naklon": 0 }, + "3828": { "label": "2/27", "naklon": 10 }, + "3377": { "label": "2/28", "naklon": 0 }, + "3591": { "label": "7/1", "naklon": 0 }, + "3587": { "label": "7/2", "naklon": 0 }, + "3468": { "label": "7/3", "naklon": 0 }, + "3466": { "label": "7/4", "naklon": 0 }, + "3474": { "label": "7/5", "naklon": 0 }, + "3481": { "label": "7/6", "naklon": 0 }, + "3589": { "label": "7/7", "naklon": 0 }, + "3472": { "label": "7/8", "naklon": 0 }, + "3473": { "label": "7/9", "naklon": 0 }, + "3584": { "label": "7/10", "naklon": 0 }, + "3571": { "label": "7/11", "naklon": 0 }, + "3476": { "label": "7/12", "naklon": 0 }, + "3590": { "label": "7/13", "naklon": 0 }, + "3478": { "label": "7/14", "naklon": 0 }, + "3471": { "label": "7/15", "naklon": 0 }, + "3467": { "label": "7/16", "naklon": 0 }, + "3479": { "label": "7/17", "naklon": 0 }, + "3480": { "label": "7/18", "naklon": 0 }, + "3477": { "label": "7/19", "naklon": 0 }, + "3362": { "label": "12/1", "naklon": 0 }, + "3355": { "label": "12/2", "naklon": 0 }, + "3356": { "label": "12/3", "naklon": 0 }, + "3349": { "label": "12/4", "naklon": 0 }, + "3357": { "label": "12/5", "naklon": 0 }, + "3350": { "label": "12/6", "naklon": 0 }, + "3353": { "label": "12/7", "naklon": 0 }, + "3539": { "label": "12/8", "naklon": 0 }, + "3050": { "label": "12/9", "naklon": 0 }, + "3361": { "label": "12/10", "naklon": 0 }, + "3360": { "label": "12/11", "naklon": 0 }, + "3358": { "label": "12/12", "naklon": 0 }, + "3541": { "label": "12/13", "naklon": 0 }, + "3551": { "label": "12/14", "naklon": 0 }, + "3514": { "label": "12/15", "naklon": 0 }, + "3547": { "label": "12/16", "naklon": 0 }, + "3562": { "label": "12/17", "naklon": 0 }, + "3525": { "label": "12/18", "naklon": 0 }, + "3558": { "label": "12/19", "naklon": 0 }, + "3511": { "label": "12/20", "naklon": 0 }, + "3058": { "label": "12/21", "naklon": 0 }, + "3062": { "label": "12/22", "naklon": 0 }, + "3070": { "label": "12/23", "naklon": 0 }, + "3447": { "label": "12/24", "naklon": 0 }, + "3056": { "label": "12/25", "naklon": 0 }, + "3057": { "label": "12/26", "naklon": 0 }, + "3071": { "label": "12/27", "naklon": 0 }, + "3061": { "label": "12/28", "naklon": 0 }, + "3069": { "label": "12/29", "naklon": 0 }, + "3077": { "label": "12/30", "naklon": 0 }, + "3080": { "label": "12/31", "naklon": 0 }, + "3081": { "label": "12/32", "naklon": 0 }, + "3078": { "label": "12/33", "naklon": 0 }, + "4037": { "label": "12/34", "naklon": 0 }, + "3067": { "label": "12/35", "naklon": 0 }, + "3051": { "label": "12/36", "naklon": 0 }, + "2924": { "label": "12/37", "naklon": 0 }, + "3060": { "label": "12/38", "naklon": 0 }, + "3073": { "label": "12/39", "naklon": 0 }, + "3469": { "label": "12/40", "naklon": 0 }, + "2923": { "label": "12/41", "naklon": 0 }, + "2925": { "label": "12/42", "naklon": 0 }, + "3359": { "label": "12/43", "naklon": 0 }, + "3055": { "label": "12/44", "naklon": 0 }, + "2922": { "label": "12/45", "naklon": 0 }, + "3084": { "label": "12/46", "naklon": 0 }, + "3064": { "label": "12/47", "naklon": 0 }, + "3066": { "label": "12/48", "naklon": 0 }, + "3072": { "label": "12/49", "naklon": 0 }, + "3415": { "label": "13/13A", "naklon": 0 }, + "3409": { "label": "13/13B", "naklon": 0 }, + "3399": { "label": "13/13C", "naklon": 0 }, + "3410": { "label": "13/29A", "naklon": 0 }, + "3407": { "label": "13/29B", "naklon": 0 }, + "3405": { "label": "13/34A", "naklon": 0 }, + "3404": { "label": "13/34B", "naklon": 0 }, + "3392": { "label": "13/45A", "naklon": 0 }, + "3386": { "label": "13/45B", "naklon": 0 }, + "3303": { "label": "13/60A", "naklon": 3 }, + "3302": { "label": "13/60B", "naklon": 3 }, + "3319": { "label": "13/70A", "naklon": 6 }, + "3317": { "label": "13/70B", "naklon": 6 }, + "3326": { "label": "13/70C", "naklon": 6 }, + "3351": { "label": "13/73A", "naklon": 6 }, + "3313": { "label": "13/73B", "naklon": 6 }, + "3316": { "label": "13/83A", "naklon": 0 }, + "3320": { "label": "13/83B", "naklon": 0 }, + "3336": { "label": "13/95A", "naklon": 0 }, + "3323": { "label": "13/95B", "naklon": 0 }, + "3339": { "label": "13/98A", "naklon": 0 }, + "3333": { "label": "13/98B", "naklon": 0 }, + "3425": { "label": "13/1", "naklon": 0 }, + "3419": { "label": "13/2", "naklon": 0 }, + "3416": { "label": "13/3", "naklon": 0 }, + "3332": { "label": "13/4", "naklon": 0 }, + "3422": { "label": "13/5", "naklon": 0 }, + "3417": { "label": "13/6", "naklon": 0 }, + "3418": { "label": "13/7", "naklon": 0 }, + "3424": { "label": "13/8", "naklon": 0 }, + "3334": { "label": "13/9", "naklon": 0 }, + "4363": { "label": "13/10", "naklon": 0 }, + "3423": { "label": "13/11", "naklon": 0 }, + "3406": { "label": "13/12", "naklon": 0 }, + "3411": { "label": "13/14", "naklon": 0 }, + "3412": { "label": "13/15", "naklon": 0 }, + "3413": { "label": "13/16", "naklon": 0 }, + "3414": { "label": "13/17", "naklon": 0 }, + "3391": { "label": "13/18", "naklon": 0 }, + "3370": { "label": "13/19", "naklon": 0 }, + "3369": { "label": "13/20", "naklon": 0 }, + "3408": { "label": "13/21", "naklon": 0 }, + "3393": { "label": "13/22", "naklon": 0 }, + "3128": { "label": "13/23", "naklon": 0 }, + "3197": { "label": "13/24", "naklon": 0 }, + "4364": { "label": "13/25", "naklon": 0 }, + "3155": { "label": "13/26", "naklon": 0 }, + "3196": { "label": "13/27", "naklon": 0 }, + "3144": { "label": "13/28", "naklon": 0 }, + "3150": { "label": "13/30", "naklon": 0 }, + "3390": { "label": "13/31", "naklon": 0 }, + "3401": { "label": "13/32", "naklon": 0 }, + "3275": { "label": "13/33", "naklon": 0 }, + "3371": { "label": "13/35", "naklon": 0 }, + "3389": { "label": "13/36", "naklon": 0 }, + "3388": { "label": "13/37", "naklon": 0 }, + "3365": { "label": "13/38", "naklon": 0 }, + "3363": { "label": "13/39", "naklon": 0 }, + "3397": { "label": "13/40", "naklon": 0 }, + "3567": { "label": "13/40/1", "naklon": 0 }, + "3387": { "label": "13/41", "naklon": 0 }, + "3403": { "label": "13/42", "naklon": 0 }, + "3147": { "label": "13/43", "naklon": 0 }, + "3141": { "label": "13/44", "naklon": 0 }, + "3364": { "label": "13/46", "naklon": 0 }, + "3367": { "label": "13/47", "naklon": 0 }, + "3368": { "label": "13/48", "naklon": 0 }, + "3402": { "label": "13/49", "naklon": 0 }, + "3366": { "label": "13/50", "naklon": 0 }, + "3395": { "label": "13/51", "naklon": 0 }, + "3372": { "label": "13/52", "naklon": 0 }, + "3394": { "label": "13/53", "naklon": 0 }, + "3308": { "label": "13/54", "naklon": 0 }, + "3847": { "label": "13/54/1", "naklon": 0 }, + "3312": { "label": "13/55", "naklon": 3 }, + "3309": { "label": "13/56", "naklon": 3 }, + "3311": { "label": "13/57", "naklon": 3 }, + "3310": { "label": "13/58", "naklon": 3 }, + "4365": { "label": "13/59", "naklon": 3 }, + "4093": { "label": "13/60/1", "naklon": 3 }, + "3304": { "label": "13/61", "naklon": 3 }, + "3307": { "label": "13/62", "naklon": 3 }, + "3271": { "label": "13/63", "naklon": 3 }, + "3301": { "label": "13/64", "naklon": 3 }, + "4366": { "label": "13/65", "naklon": 3 }, + "3300": { "label": "13/66", "naklon": 3 }, + "3185": { "label": "13/67", "naklon": 0 }, + "3184": { "label": "13/68", "naklon": 0 }, + "3188": { "label": "13/69", "naklon": 0 }, + "3343": { "label": "13/71", "naklon": 6 }, + "3819": { "label": "13/71/1", "naklon": 6 }, + "3880": { "label": "13/71/2", "naklon": 6 }, + "3348": { "label": "13/72", "naklon": 6 }, + "3344": { "label": "13/74", "naklon": 6 }, + "3346": { "label": "13/75", "naklon": 6 }, + "3597": { "label": "13/75/1", "naklon": 6 }, + "3345": { "label": "13/76", "naklon": 6 }, + "3322": { "label": "13/77", "naklon": 0 }, + "3325": { "label": "13/78", "naklon": 0 }, + "4310": { "label": "13/78/1", "naklon": 0 }, + "3315": { "label": "13/79", "naklon": 0 }, + "3328": { "label": "13/80", "naklon": 0 }, + "3321": { "label": "13/81", "naklon": 0 }, + "3324": { "label": "13/82", "naklon": 0 }, + "3140": { "label": "13/84", "naklon": 0 }, + "3153": { "label": "13/85", "naklon": 0 }, + "3145": { "label": "13/86", "naklon": 0 }, + "3134": { "label": "13/87", "naklon": 0 }, + "3151": { "label": "13/88", "naklon": 0 }, + "3143": { "label": "13/89", "naklon": 0 }, + "3318": { "label": "13/90", "naklon": 0 }, + "3347": { "label": "13/91", "naklon": 0 }, + "3314": { "label": "13/94", "naklon": 0 }, + "3331": { "label": "13/96", "naklon": 0 }, + "3327": { "label": "13/97", "naklon": 0 }, + "3329": { "label": "13/99", "naklon": 0 }, + "3337": { "label": "13/100", "naklon": 0 }, + "3330": { "label": "13/101", "naklon": 0 }, + "3335": { "label": "13/102", "naklon": 0 }, + "3420": { "label": "13/103", "naklon": 0 }, + "3421": { "label": "13/104", "naklon": 0 }, + "4361": { "label": "13/105", "naklon": 0 }, + "4362": { "label": "13/106", "naklon": 0 }, + "3526": { "label": "13/107", "naklon": 0 }, + "4424": { "label": "13/108", "naklon": null }, + "3561": { "label": "13/109", "naklon": null }, + "3527": { "label": "13/110", "naklon": null }, + "3521": { "label": "13/111", "naklon": null }, + "3552": { "label": "13/112", "naklon": null }, + "3544": { "label": "13/113", "naklon": null }, + "3534": { "label": "13/114", "naklon": null }, + "3516": { "label": "13/115", "naklon": null }, + "3513": { "label": "13/116", "naklon": null }, + "3565": { "label": "13/117", "naklon": null }, + "3866": { "label": "13/118", "naklon": null }, + "3136": { "label": "14/1", "naklon": 0 }, + "3137": { "label": "14/2", "naklon": 0 }, + "3135": { "label": "14/3", "naklon": 0 }, + "3149": { "label": "14/4", "naklon": 0 }, + "3142": { "label": "14/5", "naklon": 0 }, + "3342": { "label": "14/6", "naklon": 0 }, + "3340": { "label": "14/7", "naklon": 0 }, + "3152": { "label": "14/8", "naklon": 0 }, + "3886": { "label": "14/9", "naklon": 0 }, + "3341": { "label": "14/10", "naklon": null }, + "3352": { "label": "14/11", "naklon": null }, + "3396": { "label": "15/1", "naklon": 5 }, + "2784": { "label": "15/2", "naklon": 5 }, + "2788": { "label": "15/3", "naklon": 5 }, + "2801": { "label": "15/4", "naklon": 5 }, + "2815": { "label": "15/5", "naklon": 5 }, + "2829": { "label": "15/6", "naklon": 5 }, + "2796": { "label": "15/7", "naklon": 5 }, + "2803": { "label": "15/8", "naklon": 5 }, + "4304": { "label": "15/8/1", "naklon": 5 }, + "4311": { "label": "15/8/2", "naklon": 5 }, + "2821": { "label": "15/9", "naklon": 5 }, + "3400": { "label": "15/10", "naklon": 5 }, + "2799": { "label": "15/11", "naklon": 5 }, + "2804": { "label": "15/12", "naklon": 5 }, + "4303": { "label": "15/12/1", "naklon": 5 }, + "4309": { "label": "15/12/2", "naklon": 5 }, + "2806": { "label": "15/13", "naklon": 5 }, + "2787": { "label": "15/14", "naklon": 5 }, + "2809": { "label": "15/15", "naklon": 5 }, + "2814": { "label": "15/16", "naklon": 0 }, + "3934": { "label": "15/17", "naklon": 0 }, + "3192": { "label": "15/18", "naklon": 0 }, + "2812": { "label": "15/19", "naklon": 0 }, + "4070": { "label": "15/20", "naklon": 0 }, + "2826": { "label": "15/21", "naklon": 0 }, + "2808": { "label": "15/22", "naklon": 3 }, + "2795": { "label": "15/23", "naklon": 3 }, + "2807": { "label": "15/24", "naklon": 3 }, + "2831": { "label": "15/25", "naklon": 0 }, + "2862": { "label": "15/26", "naklon": null }, + "2861": { "label": "15/27", "naklon": 0 }, + "2866": { "label": "15/28", "naklon": 0 }, + "3546": { "label": "15/28/1", "naklon": 0 }, + "4146": { "label": "15/29", "naklon": 0 }, + "3001": { "label": "15/29/1", "naklon": 0 }, + "2835": { "label": "15/30", "naklon": 0 }, + "2874": { "label": "15/31", "naklon": 0 }, + "2852": { "label": "15/32", "naklon": 0 }, + "2851": { "label": "15/33", "naklon": 0 }, + "3560": { "label": "15/33/1", "naklon": 0 }, + "2858": { "label": "15/34", "naklon": 0 }, + "4306": { "label": "15/34/1", "naklon": 0 }, + "2856": { "label": "15/35", "naklon": 0 }, + "2847": { "label": "15/36", "naklon": 0 }, + "3556": { "label": "15/36/1", "naklon": 0 }, + "3950": { "label": "15/37", "naklon": 0 }, + "2848": { "label": "15/38", "naklon": 0 }, + "2863": { "label": "15/39", "naklon": 0 }, + "4313": { "label": "15/39/1", "naklon": 0 }, + "2873": { "label": "15/40", "naklon": 0 }, + "2984": { "label": "15/40/1", "naklon": 0 }, + "2854": { "label": "15/41", "naklon": 0 }, + "2859": { "label": "15/42", "naklon": 0 }, + "2872": { "label": "15/43", "naklon": 0 }, + "2849": { "label": "15/44", "naklon": 0 }, + "2864": { "label": "15/45", "naklon": 0 }, + "3553": { "label": "15/46", "naklon": null }, + "3021": { "label": "15/47", "naklon": null }, + "3008": { "label": "15/47/1", "naklon": null }, + "3017": { "label": "15/48", "naklon": null }, + "3014": { "label": "15/49", "naklon": null }, + "2981": { "label": "15/50", "naklon": null }, + "3020": { "label": "15/51", "naklon": null }, + "3027": { "label": "15/52", "naklon": null }, + "3006": { "label": "15/53", "naklon": null }, + "3012": { "label": "15/54", "naklon": null }, + "2738": { "label": "15/55", "naklon": 0 }, + "2725": { "label": "15/56", "naklon": 0 }, + "3016": { "label": "15/57", "naklon": null }, + "3005": { "label": "15/58", "naklon": null }, + "3009": { "label": "15/58/1", "naklon": null }, + "3010": { "label": "15/59", "naklon": 0 }, + "3538": { "label": "15/59/1", "naklon": 0 }, + "4145": { "label": "15/59/2", "naklon": 0 }, + "2713": { "label": "15/60", "naklon": 0 }, + "2789": { "label": "15/61", "naklon": 0 }, + "2736": { "label": "15/62", "naklon": 0 }, + "2739": { "label": "15/63", "naklon": 0 }, + "4346": { "label": "15/64", "naklon": 0 }, + "2731": { "label": "15/65", "naklon": 0 }, + "2818": { "label": "15/66", "naklon": 0 }, + "3557": { "label": "15/66/1", "naklon": 0 }, + "2822": { "label": "15/67", "naklon": 0 }, + "2833": { "label": "15/68", "naklon": 0 }, + "2834": { "label": "15/69", "naklon": 0 }, + "3097": { "label": "15/70", "naklon": 0 }, + "2824": { "label": "15/71", "naklon": 0 }, + "2828": { "label": "15/72", "naklon": 0 }, + "2600": { "label": "15/73", "naklon": 0 }, + "4314": { "label": "15/73/1", "naklon": 0 }, + "2832": { "label": "15/74", "naklon": 0 }, + "4360": { "label": "15/75", "naklon": 0 }, + "2846": { "label": "15/76", "naklon": 0 }, + "2584": { "label": "15/77", "naklon": 0 }, + "2843": { "label": "15/78", "naklon": 0 }, + "4308": { "label": "15/78/1", "naklon": 0 }, + "4144": { "label": "15/79", "naklon": null }, + "2844": { "label": "15/80", "naklon": 0 }, + "2842": { "label": "15/81", "naklon": 0 }, + "2838": { "label": "15/82", "naklon": 0 }, + "2837": { "label": "15/83", "naklon": null }, + "3555": { "label": "15/83/1", "naklon": null }, + "2839": { "label": "15/84", "naklon": 0 }, + "2830": { "label": "15/85", "naklon": 0 }, + "4066": { "label": "15/86", "naklon": 0 }, + "2836": { "label": "15/87", "naklon": 0 }, + "2911": { "label": "15/88", "naklon": 0 }, + "2825": { "label": "15/89", "naklon": 0 }, + "2811": { "label": "15/90", "naklon": 0 }, + "3740": { "label": "15/94", "naklon": 15 }, + "2734": { "label": "15/95", "naklon": 15 }, + "3105": { "label": "15/96", "naklon": 15 }, + "2732": { "label": "15/97", "naklon": 15 }, + "2727": { "label": "15/98", "naklon": 15 }, + "2735": { "label": "15/99", "naklon": 15 }, + "3926": { "label": "15/100", "naklon": 15 }, + "2918": { "label": "15/101", "naklon": 0 }, + "2705": { "label": "15/102", "naklon": 10 }, + "2708": { "label": "15/103", "naklon": 10 }, + "2721": { "label": "15/104", "naklon": 10 }, + "2719": { "label": "15/105", "naklon": 10 }, + "2919": { "label": "15/106", "naklon": 10 }, + "3101": { "label": "15/107", "naklon": 10 }, + "2853": { "label": "15/108", "naklon": 10 }, + "2715": { "label": "15/109", "naklon": 10 }, + "2712": { "label": "15/110", "naklon": 0 }, + "2711": { "label": "15/111", "naklon": 0 }, + "2709": { "label": "15/112", "naklon": 0 }, + "2710": { "label": "15/113", "naklon": 0 }, + "2907": { "label": "15/114", "naklon": 0 }, + "2906": { "label": "15/115", "naklon": 0 }, + "2908": { "label": "15/116", "naklon": 0 }, + "2901": { "label": "15/117", "naklon": 0 }, + "2913": { "label": "15/118", "naklon": 0 }, + "3656": { "label": "15/119", "naklon": 0 }, + "2781": { "label": "15/120", "naklon": 0 }, + "2802": { "label": "15/121", "naklon": 0 }, + "2791": { "label": "15/122", "naklon": 0 }, + "2783": { "label": "15/123", "naklon": 0 }, + "2794": { "label": "15/124", "naklon": 0 }, + "3139": { "label": "15/125", "naklon": 0 }, + "3229": { "label": "15/126", "naklon": 5 }, + "3239": { "label": "15/127", "naklon": 5 }, + "3230": { "label": "15/128", "naklon": 5 }, + "4016": { "label": "15/129", "naklon": null }, + "3608": { "label": "16/16A", "naklon": 0 }, + "4151": { "label": "16/16B", "naklon": 0 }, + "3710": { "label": "16/1", "naklon": 0 }, + "3726": { "label": "16/2", "naklon": 0 }, + "3743": { "label": "16/3", "naklon": 0 }, + "3724": { "label": "16/4", "naklon": 0 }, + "3712": { "label": "16/5", "naklon": 0 }, + "3739": { "label": "16/6", "naklon": 0 }, + "3742": { "label": "16/7", "naklon": 0 }, + "3731": { "label": "16/8", "naklon": 0 }, + "3727": { "label": "16/9", "naklon": 0 }, + "3729": { "label": "16/10", "naklon": 0 }, + "3736": { "label": "16/11", "naklon": 0 }, + "3713": { "label": "16/12", "naklon": 0 }, + "3715": { "label": "16/13", "naklon": 0 }, + "3733": { "label": "16/14", "naklon": 0 }, + "3732": { "label": "16/15", "naklon": 0 }, + "3634": { "label": "16/17", "naklon": 0 }, + "3610": { "label": "16/18", "naklon": 0 }, + "3626": { "label": "16/19", "naklon": 0 }, + "3618": { "label": "16/20", "naklon": 0 }, + "3619": { "label": "16/21", "naklon": 0 }, + "3628": { "label": "16/22", "naklon": 0 }, + "3615": { "label": "16/23", "naklon": 0 }, + "3609": { "label": "16/24", "naklon": 0 }, + "3606": { "label": "16/25", "naklon": 0 }, + "3624": { "label": "16/26", "naklon": 0 }, + "3627": { "label": "16/27", "naklon": 0 }, + "3607": { "label": "16/28", "naklon": 0 }, + "4370": { "label": "16/29", "naklon": 0 }, + "3692": { "label": "16/30", "naklon": 0 }, + "3614": { "label": "16/31", "naklon": 0 }, + "3623": { "label": "16/32", "naklon": 0 }, + "4373": { "label": "16/33", "naklon": 0 }, + "3620": { "label": "16/34", "naklon": 0 }, + "3685": { "label": "16/35", "naklon": 0 }, + "3616": { "label": "16/36", "naklon": 0 }, + "3686": { "label": "16/37", "naklon": 0 }, + "3688": { "label": "16/38", "naklon": 0 }, + "3684": { "label": "16/39", "naklon": 0 }, + "3825": { "label": "16/40", "naklon": 0 }, + "3865": { "label": "16/41", "naklon": 0 }, + "3824": { "label": "16/42", "naklon": 0 }, + "3871": { "label": "16/43", "naklon": 0 }, + "3801": { "label": "16/44", "naklon": 0 }, + "3862": { "label": "16/45", "naklon": 0 }, + "3876": { "label": "16/46", "naklon": 0 }, + "3861": { "label": "16/47", "naklon": 0 }, + "4215": { "label": "16/48", "naklon": 0 }, + "3605": { "label": "16/49", "naklon": 10 }, + "3603": { "label": "16/50", "naklon": 10 }, + "3592": { "label": "16/51", "naklon": 10 }, + "3598": { "label": "16/52", "naklon": 10 }, + "3594": { "label": "16/53", "naklon": 10 }, + "3593": { "label": "16/54", "naklon": 10 }, + "3630": { "label": "16/55", "naklon": 10 }, + "3763": { "label": "16/56", "naklon": 10 }, + "3746": { "label": "16/57", "naklon": 10 }, + "3699": { "label": "16/58", "naklon": 0 }, + "3698": { "label": "16/59", "naklon": 0 }, + "3709": { "label": "16/60", "naklon": null }, + "3708": { "label": "16/61", "naklon": 0 }, + "3703": { "label": "16/62", "naklon": null }, + "3700": { "label": "16/63", "naklon": 0 }, + "3701": { "label": "16/64", "naklon": null }, + "3704": { "label": "16/65", "naklon": 0 }, + "3707": { "label": "16/66", "naklon": null }, + "3810": { "label": "16/67", "naklon": 0 }, + "4208": { "label": "16/68", "naklon": null }, + "3867": { "label": "16/69", "naklon": 0 }, + "4372": { "label": "16/70", "naklon": null }, + "3881": { "label": "16/71", "naklon": 0 }, + "4204": { "label": "16/72", "naklon": null }, + "3869": { "label": "16/73", "naklon": 0 }, + "4202": { "label": "16/74", "naklon": null }, + "3830": { "label": "16/75", "naklon": 0 }, + "3870": { "label": "16/76", "naklon": null }, + "3964": { "label": "16/77", "naklon": 0 }, + "3849": { "label": "16/78", "naklon": 0 }, + "3694": { "label": "16/79", "naklon": null }, + "3717": { "label": "16/80", "naklon": 0 }, + "3877": { "label": "16/81", "naklon": null }, + "3755": { "label": "16/82", "naklon": 0 }, + "3725": { "label": "16/83", "naklon": null }, + "3716": { "label": "16/84", "naklon": 0 }, + "3696": { "label": "16/85", "naklon": null }, + "3702": { "label": "16/86", "naklon": 0 }, + "3706": { "label": "16/87", "naklon": null }, + "3850": { "label": "16/88", "naklon": 0 }, + "3848": { "label": "16/89", "naklon": null }, + "3737": { "label": "16/90", "naklon": null }, + "3705": { "label": "16/91", "naklon": 0 }, + "3723": { "label": "16/92", "naklon": null }, + "3842": { "label": "16/93", "naklon": 0 }, + "3735": { "label": "16/94", "naklon": null }, + "3719": { "label": "16/95", "naklon": 0 }, + "3697": { "label": "16/96", "naklon": 0 }, + "3711": { "label": "16/97", "naklon": 0 }, + "4107": { "label": "16/98", "naklon": null }, + "4112": { "label": "16/99", "naklon": 5 }, + "4106": { "label": "16/100", "naklon": 5 }, + "4111": { "label": "16/101", "naklon": 5 }, + "4091": { "label": "16/102", "naklon": null }, + "4104": { "label": "16/103", "naklon": 5 }, + "4094": { "label": "16/104", "naklon": null }, + "4089": { "label": "16/105", "naklon": 5 }, + "4095": { "label": "16/106", "naklon": null }, + "4102": { "label": "16/107", "naklon": 5 }, + "4105": { "label": "16/108", "naklon": null }, + "3859": { "label": "16/109", "naklon": null }, + "4090": { "label": "16/110", "naklon": 5 }, + "4110": { "label": "16/111", "naklon": null }, + "4097": { "label": "16/112", "naklon": 5 }, + "4099": { "label": "16/113", "naklon": null }, + "4096": { "label": "16/114", "naklon": null }, + "4101": { "label": "16/115", "naklon": 5 }, + "4109": { "label": "16/116", "naklon": null }, + "4092": { "label": "16/117", "naklon": 5 }, + "3631": { "label": "16/118", "naklon": null }, + "3632": { "label": "16/119", "naklon": 0 }, + "3641": { "label": "16/120", "naklon": null }, + "3638": { "label": "16/121", "naklon": 0 }, + "3637": { "label": "16/122", "naklon": null }, + "4142": { "label": "16/123", "naklon": null }, + "4147": { "label": "16/124", "naklon": 5 }, + "4139": { "label": "16/125", "naklon": 5 }, + "3172": { "label": "20/30A", "naklon": 2 }, + "3164": { "label": "20/30B", "naklon": 2 }, + "3247": { "label": "20/1", "naklon": 10 }, + "3296": { "label": "20/2", "naklon": 10 }, + "3246": { "label": "20/3", "naklon": 10 }, + "3270": { "label": "20/4", "naklon": 10 }, + "3294": { "label": "20/5", "naklon": 10 }, + "3298": { "label": "20/6", "naklon": 10 }, + "3297": { "label": "20/7", "naklon": 10 }, + "3293": { "label": "20/8", "naklon": 10 }, + "3299": { "label": "20/9", "naklon": 10 }, + "3295": { "label": "20/10", "naklon": 10 }, + "3244": { "label": "20/11", "naklon": 10 }, + "3249": { "label": "20/12", "naklon": 10 }, + "3268": { "label": "20/13", "naklon": 10 }, + "3245": { "label": "20/14", "naklon": 10 }, + "3278": { "label": "20/15", "naklon": 10 }, + "3280": { "label": "20/16", "naklon": 10 }, + "3292": { "label": "20/17", "naklon": 10 }, + "3287": { "label": "20/18", "naklon": 10 }, + "3282": { "label": "20/19", "naklon": 10 }, + "3273": { "label": "20/20", "naklon": 0 }, + "3157": { "label": "20/21", "naklon": 0 }, + "3283": { "label": "20/22", "naklon": 0 }, + "3159": { "label": "20/23", "naklon": 0 }, + "3289": { "label": "20/24", "naklon": 0 }, + "3163": { "label": "20/25", "naklon": 0 }, + "3126": { "label": "20/26", "naklon": 0 }, + "3171": { "label": "20/27", "naklon": 0 }, + "3162": { "label": "20/28", "naklon": 0 }, + "3279": { "label": "20/29", "naklon": 10 }, + "3173": { "label": "20/31", "naklon": 0 }, + "3127": { "label": "20/32", "naklon": 0 }, + "3131": { "label": "20/33", "naklon": 0 }, + "3129": { "label": "20/34", "naklon": 0 }, + "3276": { "label": "20/35", "naklon": 2 }, + "3290": { "label": "20/36", "naklon": 2 }, + "3132": { "label": "20/37", "naklon": 0 }, + "3138": { "label": "20/38", "naklon": 0 }, + "3272": { "label": "20/39", "naklon": 0 }, + "3291": { "label": "20/40", "naklon": 0 }, + "3277": { "label": "20/41", "naklon": 10 }, + "3286": { "label": "20/42", "naklon": 10 }, + "3281": { "label": "20/43", "naklon": 10 }, + "3288": { "label": "20/44", "naklon": 10 }, + "3284": { "label": "20/45", "naklon": 10 }, + "3167": { "label": "20/46", "naklon": 10 }, + "3872": { "label": "20/47", "naklon": 0 }, + "3124": { "label": "20/48", "naklon": 0 }, + "3133": { "label": "20/49", "naklon": 0 }, + "3158": { "label": "20/50", "naklon": 0 }, + "3169": { "label": "20/51", "naklon": 0 }, + "3146": { "label": "20/52", "naklon": 0 }, + "3160": { "label": "20/53", "naklon": 0 }, + "3248": { "label": "20/54", "naklon": 0 }, + "3156": { "label": "20/55", "naklon": 0 }, + "3161": { "label": "20/56", "naklon": 0 }, + "3170": { "label": "20/57", "naklon": 0 }, + "3168": { "label": "20/58", "naklon": 0 }, + "3125": { "label": "20/59", "naklon": 0 }, + "3166": { "label": "20/60", "naklon": 0 }, + "3130": { "label": "20/61", "naklon": 0 }, + "3563": { "label": "20/62", "naklon": 0 }, + "3550": { "label": "20/63", "naklon": null }, + "3269": { "label": "20/67", "naklon": 0 }, + "2921": { "label": "21/1", "naklon": 0 }, + "2707": { "label": "21/2", "naklon": 0 }, + "2723": { "label": "21/3", "naklon": 0 }, + "2716": { "label": "21/4", "naklon": 0 }, + "2717": { "label": "21/5", "naklon": 0 }, + "2720": { "label": "21/6", "naklon": 0 }, + "2722": { "label": "21/7", "naklon": 0 }, + "2718": { "label": "21/8", "naklon": 0 }, + "2724": { "label": "21/9", "naklon": 0 }, + "2742": { "label": "21/10", "naklon": 0 }, + "2743": { "label": "21/11", "naklon": 0 }, + "2733": { "label": "21/12", "naklon": 0 }, + "2903": { "label": "21/14", "naklon": 0 }, + "2917": { "label": "21/15", "naklon": 0 }, + "2897": { "label": "21/16", "naklon": 0 }, + "2914": { "label": "21/17", "naklon": 0 }, + "2898": { "label": "21/18", "naklon": 0 }, + "2773": { "label": "21/19", "naklon": 0 }, + "2895": { "label": "21/20", "naklon": 0 }, + "2896": { "label": "21/21", "naklon": 0 }, + "2771": { "label": "21/22", "naklon": 0 }, + "2772": { "label": "21/23", "naklon": 0 }, + "2793": { "label": "21/24", "naklon": 0 }, + "2902": { "label": "21/25", "naklon": 0 }, + "2910": { "label": "21/26", "naklon": 0 }, + "2909": { "label": "21/27", "naklon": 0 }, + "2920": { "label": "21/28", "naklon": 0 }, + "2916": { "label": "21/29", "naklon": 0 }, + "2904": { "label": "21/30", "naklon": 0 }, + "2915": { "label": "21/31", "naklon": 0 }, + "2905": { "label": "21/32", "naklon": 0 }, + "2900": { "label": "21/33", "naklon": 0 }, + "2899": { "label": "21/34", "naklon": 0 }, + "2741": { "label": "21/36", "naklon": 0 }, + "2714": { "label": "21/37", "naklon": 0 }, + "2701": { "label": "21/38", "naklon": 0 }, + "2703": { "label": "21/39", "naklon": 0 }, + "2704": { "label": "21/40", "naklon": 0 }, + "2702": { "label": "21/41", "naklon": 0 }, + "2706": { "label": "21/42", "naklon": 0 }, + "2776": { "label": "21/43", "naklon": 0 }, + "2770": { "label": "21/44", "naklon": 0 }, + "2786": { "label": "21/45", "naklon": 0 }, + "2779": { "label": "21/46", "naklon": 0 }, + "2782": { "label": "21/47", "naklon": 0 }, + "2785": { "label": "21/48", "naklon": 0 }, + "2769": { "label": "21/49", "naklon": 0 }, + "3354": { "label": "21/50", "naklon": 0 }, + "2778": { "label": "21/51", "naklon": 0 }, + "2775": { "label": "21/52", "naklon": 0 }, + "2780": { "label": "21/53", "naklon": 0 }, + "2790": { "label": "21/54", "naklon": 0 }, + "2792": { "label": "21/55", "naklon": 0 }, + "2774": { "label": "21/56", "naklon": 0 }, + "2630": { "label": "22/1", "naklon": 0 }, + "2631": { "label": "22/2", "naklon": 0 }, + "2632": { "label": "22/3", "naklon": 0 }, + "2633": { "label": "22/4", "naklon": 0 }, + "2634": { "label": "22/5", "naklon": 0 }, + "2636": { "label": "22/6", "naklon": 0 }, + "4367": { "label": "22/7", "naklon": 0 }, + "2637": { "label": "22/8", "naklon": 0 }, + "2638": { "label": "22/9", "naklon": 0 }, + "2639": { "label": "22/10", "naklon": 0 }, + "2640": { "label": "22/11", "naklon": 0 }, + "2641": { "label": "22/12", "naklon": 0 }, + "2642": { "label": "22/13", "naklon": 0 }, + "2643": { "label": "22/14", "naklon": 0 }, + "2644": { "label": "22/15", "naklon": 0 }, + "2645": { "label": "22/16", "naklon": 0 }, + "2646": { "label": "22/17", "naklon": 0 }, + "2647": { "label": "22/18", "naklon": 0 }, + "2648": { "label": "22/19", "naklon": 0 }, + "2649": { "label": "22/20", "naklon": 0 }, + "2650": { "label": "22/21", "naklon": 0 }, + "2651": { "label": "22/22", "naklon": 0 }, + "4103": { "label": "22/23", "naklon": 0 }, + "2653": { "label": "22/24", "naklon": 0 }, + "2654": { "label": "22/25", "naklon": 0 }, + "2655": { "label": "22/26", "naklon": 0 }, + "2656": { "label": "22/27", "naklon": 0 }, + "2657": { "label": "22/28", "naklon": 0 }, + "2658": { "label": "22/29", "naklon": 0 }, + "2659": { "label": "22/30", "naklon": 0 }, + "2660": { "label": "22/31", "naklon": 0 }, + "2661": { "label": "22/32", "naklon": 0 }, + "3015": { "label": "22/32/1", "naklon": 0 }, + "2662": { "label": "22/33", "naklon": 0 }, + "2663": { "label": "22/34", "naklon": 0 }, + "2664": { "label": "22/35", "naklon": 0 }, + "2665": { "label": "22/36", "naklon": 0 }, + "2666": { "label": "22/37", "naklon": 0 }, + "2667": { "label": "22/38", "naklon": 0 }, + "2668": { "label": "22/39", "naklon": 0 }, + "2669": { "label": "22/40", "naklon": null }, + "2670": { "label": "22/41", "naklon": null }, + "2671": { "label": "22/42", "naklon": null }, + "3087": { "label": "23/9A", "naklon": 10 }, + "3090": { "label": "23/9B", "naklon": 10 }, + "3075": { "label": "23/1", "naklon": 0 }, + "3089": { "label": "23/2", "naklon": 0 }, + "3088": { "label": "23/3", "naklon": 0 }, + "3228": { "label": "23/4", "naklon": 10 }, + "2751": { "label": "23/5", "naklon": 10 }, + "3243": { "label": "23/6", "naklon": 10 }, + "4349": { "label": "23/7", "naklon": 10 }, + "3102": { "label": "23/8", "naklon": 10 }, + "3099": { "label": "23/10", "naklon": 10 }, + "3103": { "label": "23/11", "naklon": 10 }, + "3093": { "label": "23/12", "naklon": 10 }, + "3098": { "label": "23/13", "naklon": 10 }, + "3092": { "label": "23/14", "naklon": 10 }, + "3233": { "label": "23/15", "naklon": 0 }, + "3095": { "label": "23/16", "naklon": 0 }, + "4074": { "label": "23/17", "naklon": 0 }, + "2729": { "label": "23/18", "naklon": 0 }, + "3234": { "label": "23/19", "naklon": 0 }, + "3094": { "label": "23/20", "naklon": 0 }, + "2817": { "label": "23/21", "naklon": 0 }, + "3226": { "label": "23/22", "naklon": 0 }, + "3225": { "label": "23/23", "naklon": 0 }, + "3237": { "label": "23/24", "naklon": 0 }, + "4250": { "label": "23/25", "naklon": 0 }, + "3059": { "label": "23/26", "naklon": 10 }, + "3238": { "label": "23/27", "naklon": 10 }, + "3242": { "label": "23/28", "naklon": 10 }, + "3236": { "label": "23/29", "naklon": 10 }, + "3112": { "label": "23/30", "naklon": 10 }, + "3224": { "label": "23/31", "naklon": 0 }, + "4298": { "label": "23/32", "naklon": 10 }, + "4150": { "label": "23/33", "naklon": 10 }, + "3091": { "label": "23/34", "naklon": 10 }, + "3771": { "label": "25/1", "naklon": 5 }, + "3777": { "label": "25/2", "naklon": 5 }, + "3749": { "label": "25/3", "naklon": 5 }, + "3769": { "label": "25/4", "naklon": 5 }, + "3765": { "label": "25/5", "naklon": 5 }, + "3785": { "label": "25/6", "naklon": 5 }, + "3761": { "label": "25/7", "naklon": 5 }, + "3758": { "label": "25/8", "naklon": 5 }, + "3766": { "label": "25/9", "naklon": 5 }, + "3779": { "label": "25/10", "naklon": 5 }, + "3899": { "label": "25/11", "naklon": 10 }, + "3922": { "label": "25/12", "naklon": 10 }, + "3912": { "label": "25/13", "naklon": 10 }, + "3933": { "label": "25/14", "naklon": 10 }, + "3921": { "label": "25/15", "naklon": 10 }, + "4300": { "label": "25/16", "naklon": 10 }, + "3927": { "label": "25/17", "naklon": 10 }, + "3212": { "label": "25/18", "naklon": 10 }, + "3208": { "label": "25/19", "naklon": 10 }, + "3207": { "label": "25/20", "naklon": 10 }, + "4294": { "label": "25/21", "naklon": 10 }, + "3209": { "label": "25/22", "naklon": 10 }, + "3745": { "label": "25/23", "naklon": 10 }, + "3762": { "label": "25/24", "naklon": 10 }, + "3215": { "label": "25/25", "naklon": 10 }, + "3210": { "label": "25/26", "naklon": 10 }, + "3211": { "label": "25/27", "naklon": 10 }, + "3206": { "label": "25/28", "naklon": 10 }, + "3918": { "label": "25/29", "naklon": 5 }, + "3928": { "label": "25/30", "naklon": 5 }, + "3917": { "label": "25/31", "naklon": 5 }, + "4029": { "label": "25/32", "naklon": 0 }, + "4038": { "label": "25/33", "naklon": 0 }, + "4022": { "label": "25/34", "naklon": 0 }, + "3937": { "label": "25/35", "naklon": 0 }, + "3190": { "label": "25/36", "naklon": 0 }, + "3835": { "label": "25/37", "naklon": 0 }, + "3201": { "label": "25/38", "naklon": 0 }, + "3193": { "label": "25/39", "naklon": 0 }, + "3191": { "label": "25/40", "naklon": 0 }, + "3203": { "label": "25/41", "naklon": 0 }, + "4301": { "label": "25/42", "naklon": 0 }, + "3223": { "label": "25/43", "naklon": 0 }, + "3202": { "label": "25/44", "naklon": 0 }, + "3205": { "label": "25/45", "naklon": 0 }, + "3194": { "label": "25/46", "naklon": 0 }, + "3198": { "label": "25/47", "naklon": 0 }, + "3204": { "label": "25/48", "naklon": 0 }, + "3200": { "label": "25/49", "naklon": 0 }, + "3216": { "label": "25/50", "naklon": 0 }, + "3932": { "label": "25/51", "naklon": 5 }, + "3923": { "label": "25/52", "naklon": 5 }, + "3913": { "label": "25/53", "naklon": 5 }, + "3900": { "label": "25/54", "naklon": 5 }, + "4189": { "label": "25/55", "naklon": 10 }, + "4191": { "label": "25/56", "naklon": 10 }, + "3790": { "label": "25/57", "naklon": 10 }, + "4190": { "label": "25/58", "naklon": 10 }, + "4302": { "label": "25/59", "naklon": 0 }, + "4351": { "label": "25/60", "naklon": 0 }, + "4075": { "label": "25/61", "naklon": 0 }, + "4071": { "label": "25/62", "naklon": 0 }, + "3784": { "label": "25/63", "naklon": 0 }, + "4065": { "label": "25/64", "naklon": 0 }, + "4297": { "label": "25/65", "naklon": 0 }, + "4295": { "label": "25/66", "naklon": 0 }, + "4299": { "label": "25/67", "naklon": 0 }, + "3772": { "label": "25/68", "naklon": 0 }, + "3941": { "label": "25/69", "naklon": 0 }, + "3782": { "label": "25/70", "naklon": 0 }, + "4068": { "label": "25/71", "naklon": 0 }, + "4073": { "label": "25/72", "naklon": 0 }, + "3901": { "label": "25/73", "naklon": 5 }, + "4296": { "label": "25/74", "naklon": 5 }, + "3910": { "label": "25/75", "naklon": 5 }, + "4293": { "label": "25/76", "naklon": 5 }, + "3919": { "label": "25/77", "naklon": 5 }, + "3924": { "label": "25/78", "naklon": 5 }, + "3909": { "label": "25/79", "naklon": 5 }, + "3896": { "label": "25/80", "naklon": 5 }, + "3911": { "label": "25/81", "naklon": 5 }, + "2819": { "label": "25/82", "naklon": 15 }, + "3776": { "label": "25/83", "naklon": 15 }, + "3752": { "label": "25/84", "naklon": 15 }, + "4353": { "label": "25/85", "naklon": 15 }, + "3791": { "label": "25/86", "naklon": 0 }, + "3770": { "label": "25/87", "naklon": 0 }, + "3760": { "label": "25/88", "naklon": 0 }, + "3115": { "label": "25/89", "naklon": 0 }, + "3738": { "label": "25/90", "naklon": 0 }, + "3748": { "label": "25/91", "naklon": 0 }, + "3753": { "label": "25/92", "naklon": 0 }, + "3775": { "label": "25/93", "naklon": 0 }, + "3778": { "label": "25/94", "naklon": 5 }, + "4078": { "label": "25/95", "naklon": 5 }, + "4088": { "label": "25/96", "naklon": 5 }, + "3856": { "label": "25/97", "naklon": 5 }, + "4084": { "label": "25/98", "naklon": 5 }, + "4069": { "label": "25/99", "naklon": 5 }, + "4188": { "label": "25/100", "naklon": 5 }, + "4064": { "label": "25/101", "naklon": 5 }, + "3792": { "label": "25/102", "naklon": 5 }, + "3780": { "label": "25/103", "naklon": 5 }, + "4034": { "label": "25/104", "naklon": 5 }, + "4072": { "label": "25/105", "naklon": 5 }, + "3884": { "label": "25/106", "naklon": 5 }, + "3793": { "label": "25/107", "naklon": 5 }, + "3863": { "label": "25/108", "naklon": 5 }, + "3855": { "label": "25/109", "naklon": 5 }, + "3846": { "label": "33/1", "naklon": 0 }, + "3943": { "label": "33/2", "naklon": 0 }, + "3903": { "label": "33/3", "naklon": 0 }, + "3982": { "label": "33/4", "naklon": 0 }, + "3879": { "label": "33/5", "naklon": 0 }, + "3887": { "label": "33/6", "naklon": 0 }, + "3920": { "label": "33/7", "naklon": 5 }, + "3942": { "label": "33/8", "naklon": 5 }, + "3829": { "label": "33/9", "naklon": null }, + "3452": { "label": "34/79A", "naklon": 6 }, + "3460": { "label": "34/79B", "naklon": 6 }, + "3443": { "label": "34/90A", "naklon": 6 }, + "3445": { "label": "34/90B", "naklon": 6 }, + "3457": { "label": "34/90C", "naklon": 6 }, + "3461": { "label": "34/97A", "naklon": 6 }, + "3463": { "label": "34/97B", "naklon": 6 }, + "3426": { "label": "34/98A", "naklon": 6 }, + "3444": { "label": "34/98B", "naklon": 6 }, + "3453": { "label": "34/99A", "naklon": 6 }, + "3455": { "label": "34/99B", "naklon": 6 }, + "4009": { "label": "34/1", "naklon": 0 }, + "3602": { "label": "34/2", "naklon": 0 }, + "3441": { "label": "34/3", "naklon": 0 }, + "3464": { "label": "34/4", "naklon": 0 }, + "3883": { "label": "34/5", "naklon": 0 }, + "4098": { "label": "34/6", "naklon": 0 }, + "4003": { "label": "34/7", "naklon": 0 }, + "4004": { "label": "34/8", "naklon": 0 }, + "3888": { "label": "34/9", "naklon": 0 }, + "3997": { "label": "34/10", "naklon": 0 }, + "4006": { "label": "34/11", "naklon": 0 }, + "4000": { "label": "34/12", "naklon": 0 }, + "4011": { "label": "34/13", "naklon": 0 }, + "3999": { "label": "34/14", "naklon": 0 }, + "3981": { "label": "34/15", "naklon": 0 }, + "3988": { "label": "34/16", "naklon": 0 }, + "3986": { "label": "34/17", "naklon": 0 }, + "3998": { "label": "34/18", "naklon": 0 }, + "3983": { "label": "34/19", "naklon": 0 }, + "4005": { "label": "34/20", "naklon": 0 }, + "4001": { "label": "34/21", "naklon": 0 }, + "4008": { "label": "34/22", "naklon": 0 }, + "4002": { "label": "34/23", "naklon": 0 }, + "3996": { "label": "34/24", "naklon": 0 }, + "4007": { "label": "34/25", "naklon": 0 }, + "4113": { "label": "34/26", "naklon": 15 }, + "3595": { "label": "34/27", "naklon": 5 }, + "3599": { "label": "34/28", "naklon": 5 }, + "3601": { "label": "34/29", "naklon": 5 }, + "4205": { "label": "34/30", "naklon": 0 }, + "3987": { "label": "34/31", "naklon": null }, + "4214": { "label": "34/32", "naklon": 0 }, + "4226": { "label": "34/33", "naklon": 0 }, + "4209": { "label": "34/34", "naklon": 0 }, + "4201": { "label": "34/35", "naklon": 0 }, + "3440": { "label": "34/36", "naklon": 0 }, + "3465": { "label": "34/37", "naklon": 0 }, + "3446": { "label": "34/38", "naklon": 0 }, + "4039": { "label": "34/39", "naklon": 5 }, + "4057": { "label": "34/40", "naklon": 5 }, + "3985": { "label": "34/41", "naklon": 0 }, + "3882": { "label": "34/42", "naklon": 0 }, + "4040": { "label": "34/43", "naklon": 5 }, + "3231": { "label": "34/44", "naklon": 0 }, + "3227": { "label": "34/45", "naklon": 0 }, + "3431": { "label": "34/46", "naklon": 0 }, + "4013": { "label": "34/47", "naklon": 0 }, + "4045": { "label": "34/48", "naklon": 0 }, + "3949": { "label": "34/49", "naklon": 0 }, + "3953": { "label": "34/50", "naklon": 0 }, + "3952": { "label": "34/51", "naklon": 0 }, + "3995": { "label": "34/52", "naklon": 0 }, + "3992": { "label": "34/53", "naklon": 0 }, + "4198": { "label": "34/54", "naklon": 0 }, + "3935": { "label": "34/55", "naklon": 0 }, + "4050": { "label": "34/56", "naklon": 0 }, + "4049": { "label": "34/57", "naklon": 0 }, + "4054": { "label": "34/58", "naklon": 0 }, + "3663": { "label": "34/59", "naklon": 6 }, + "3661": { "label": "34/60", "naklon": 6 }, + "3664": { "label": "34/61", "naklon": 6 }, + "3660": { "label": "34/62", "naklon": 6 }, + "3662": { "label": "34/63", "naklon": 6 }, + "3665": { "label": "34/65", "naklon": 6 }, + "3667": { "label": "34/66", "naklon": 6 }, + "3675": { "label": "34/67", "naklon": 6 }, + "3666": { "label": "34/68", "naklon": 6 }, + "3652": { "label": "34/69", "naklon": 6 }, + "3458": { "label": "34/70", "naklon": 6 }, + "4425": { "label": "34/70/1", "naklon": 6 }, + "3459": { "label": "34/71", "naklon": 6 }, + "3435": { "label": "34/72", "naklon": 6 }, + "3448": { "label": "34/73", "naklon": 6 }, + "3451": { "label": "34/74", "naklon": 6 }, + "3442": { "label": "34/75", "naklon": 6 }, + "3449": { "label": "34/76", "naklon": 6 }, + "3450": { "label": "34/77", "naklon": 6 }, + "3433": { "label": "34/78", "naklon": 6 }, + "3432": { "label": "34/80", "naklon": 12 }, + "3470": { "label": "34/81", "naklon": 12 }, + "3438": { "label": "34/82", "naklon": 12 }, + "3439": { "label": "34/83", "naklon": 12 }, + "4028": { "label": "34/84", "naklon": 5 }, + "3596": { "label": "34/85", "naklon": 5 }, + "4021": { "label": "34/86", "naklon": 5 }, + "3437": { "label": "34/87", "naklon": 12 }, + "3428": { "label": "34/88", "naklon": 12 }, + "3430": { "label": "34/89", "naklon": 12 }, + "3454": { "label": "34/91", "naklon": 6 }, + "3492": { "label": "34/92", "naklon": 6 }, + "3462": { "label": "34/93", "naklon": 6 }, + "3427": { "label": "34/94", "naklon": 6 }, + "3434": { "label": "34/95", "naklon": 6 }, + "3456": { "label": "34/96", "naklon": 6 }, + "4307": { "label": "34/98/1", "naklon": 6 }, + "3968": { "label": "35/1", "naklon": 0 }, + "3969": { "label": "35/2", "naklon": 0 }, + "3947": { "label": "35/3", "naklon": 0 }, + "3979": { "label": "35/4", "naklon": 0 }, + "3959": { "label": "35/5", "naklon": 0 }, + "3948": { "label": "35/6", "naklon": 0 }, + "3961": { "label": "35/7", "naklon": 0 }, + "3956": { "label": "35/8", "naklon": 0 }, + "3604": { "label": "35/9", "naklon": 0 }, + "3944": { "label": "35/10", "naklon": 0 }, + "3960": { "label": "35/11", "naklon": 0 }, + "3958": { "label": "35/12", "naklon": 0 }, + "4036": { "label": "35/13", "naklon": 5 }, + "3893": { "label": "35/18", "naklon": 5 }, + "4108": { "label": "35/19", "naklon": 5 }, + "4017": { "label": "35/20", "naklon": 5 }, + "3963": { "label": "35/21", "naklon": 0 }, + "3658": { "label": "35/22", "naklon": 0 }, + "3975": { "label": "35/23", "naklon": 0 }, + "3980": { "label": "35/24", "naklon": 0 }, + "4012": { "label": "35/25", "naklon": 0 }, + "3655": { "label": "35/26", "naklon": 0 }, + "3962": { "label": "35/27", "naklon": 0 }, + "3945": { "label": "35/28", "naklon": 0 }, + "3569": { "label": "35/29", "naklon": 0 }, + "3429": { "label": "35/30", "naklon": 0 }, + "3657": { "label": "35/31", "naklon": 0 }, + "3646": { "label": "35/32", "naklon": 0 }, + "3622": { "label": "35/33", "naklon": 0 }, + "3612": { "label": "35/34", "naklon": 0 }, + "3955": { "label": "35/35", "naklon": 0 }, + "3878": { "label": "35/37", "naklon": 0 }, + "3965": { "label": "35/38", "naklon": 0 }, + "3970": { "label": "35/39", "naklon": 0 }, + "3611": { "label": "35/40", "naklon": 0 }, + "2635": { "label": "35/41", "naklon": 0 }, + "3978": { "label": "35/42", "naklon": 0 }, + "4213": { "label": "35/43", "naklon": 0 }, + "3984": { "label": "35/44", "naklon": 0 }, + "4218": { "label": "35/45", "naklon": 0 }, + "3973": { "label": "35/46", "naklon": 0 }, + "3974": { "label": "35/47", "naklon": 0 }, + "3759": { "label": "35/48", "naklon": 0 }, + "3844": { "label": "35/49", "naklon": 0 }, + "3804": { "label": "35/50", "naklon": 0 }, + "3831": { "label": "35/51", "naklon": 0 }, + "3643": { "label": "35/52", "naklon": 0 }, + "3966": { "label": "35/53", "naklon": 0 }, + "3971": { "label": "35/54", "naklon": 0 }, + "3650": { "label": "35/55", "naklon": 6 }, + "3651": { "label": "35/56", "naklon": 6 }, + "3669": { "label": "35/57", "naklon": 6 }, + "3648": { "label": "35/58", "naklon": 6 }, + "3645": { "label": "35/59", "naklon": 6 }, + "3659": { "label": "35/60", "naklon": 6 }, + "3647": { "label": "35/61", "naklon": 6 }, + "3644": { "label": "35/62", "naklon": 6 }, + "3671": { "label": "35/63", "naklon": 6 }, + "3682": { "label": "35/64", "naklon": 6 }, + "3672": { "label": "35/65", "naklon": 6 }, + "3683": { "label": "35/66", "naklon": 6 }, + "3673": { "label": "35/67", "naklon": 6 }, + "3674": { "label": "35/68", "naklon": 6 }, + "3679": { "label": "35/69", "naklon": 6 }, + "3649": { "label": "35/70", "naklon": 6 }, + "3687": { "label": "35/71", "naklon": 6 }, + "3677": { "label": "35/72", "naklon": 6 }, + "3690": { "label": "35/73", "naklon": 6 }, + "3691": { "label": "35/74", "naklon": 6 }, + "3676": { "label": "35/75", "naklon": 6 }, + "3680": { "label": "35/76", "naklon": 6 }, + "3668": { "label": "35/77", "naklon": 6 }, + "3681": { "label": "35/78", "naklon": 6 }, + "3670": { "label": "35/79", "naklon": 6 }, + "3689": { "label": "35/80", "naklon": 6 }, + "3678": { "label": "35/81", "naklon": 6 }, + "3693": { "label": "35/82", "naklon": 6 }, + "3654": { "label": "35/83", "naklon": null }, + "4086": { "label": "36/1", "naklon": 0 }, + "4085": { "label": "36/2", "naklon": 0 }, + "4083": { "label": "36/3", "naklon": 0 }, + "4087": { "label": "36/4", "naklon": 0 }, + "4077": { "label": "36/5", "naklon": 0 }, + "4082": { "label": "36/6", "naklon": 0 }, + "4186": { "label": "36/7", "naklon": 0 }, + "4206": { "label": "36/8", "naklon": 0 }, + "4080": { "label": "36/9", "naklon": 0 }, + "4081": { "label": "36/10", "naklon": 0 }, + "4210": { "label": "36/11", "naklon": 0 }, + "4079": { "label": "36/12", "naklon": 0 }, + "4076": { "label": "36/13", "naklon": 0 }, + "3852": { "label": "36/14", "naklon": 0 }, + "2813": { "label": "36/15", "naklon": 0 }, + "4219": { "label": "36/16", "naklon": 0 }, + "3104": { "label": "37/1A", "naklon": 15 }, + "3121": { "label": "37/1B", "naklon": 15 }, + "3113": { "label": "37/2", "naklon": 10 }, + "3118": { "label": "37/3", "naklon": 10 }, + "3111": { "label": "37/4", "naklon": 10 }, + "4020": { "label": "37/5", "naklon": 10 }, + "3119": { "label": "37/6", "naklon": 10 }, + "3110": { "label": "37/7", "naklon": 10 }, + "3108": { "label": "37/8", "naklon": 10 }, + "3107": { "label": "37/12", "naklon": 0 }, + "3199": { "label": "37/13", "naklon": 0 }, + "3120": { "label": "37/14", "naklon": 0 }, + "3122": { "label": "37/15", "naklon": 0 }, + "3908": { "label": "37/16", "naklon": 0 }, + "3114": { "label": "37/17", "naklon": 0 }, + "3105": { "label": "37/18", "naklon": 0 }, + "3116": { "label": "37/19", "naklon": 0 }, + "3106": { "label": "37/20", "naklon": 0 }, + "2887": { "label": "37/21", "naklon": 5 }, + "2888": { "label": "37/22", "naklon": 5 }, + "2877": { "label": "37/23", "naklon": 5 }, + "2891": { "label": "37/24", "naklon": 5 }, + "2886": { "label": "37/25", "naklon": 5 }, + "2892": { "label": "37/26", "naklon": 5 }, + "2882": { "label": "37/27", "naklon": 5 }, + "2883": { "label": "37/28", "naklon": 5 }, + "2876": { "label": "37/29", "naklon": 5 }, + "3109": { "label": "37/30", "naklon": 5 }, + "4152": { "label": "37/31", "naklon": 5 }, + "3117": { "label": "37/32", "naklon": 5 }, + "2870": { "label": "37/33", "naklon": 5 }, + "2867": { "label": "37/34", "naklon": 0 }, + "2865": { "label": "37/35", "naklon": 0 }, + "3096": { "label": "37/36", "naklon": 0 }, + "2871": { "label": "37/37", "naklon": 0 }, + "2884": { "label": "37/38", "naklon": 0 }, + "2855": { "label": "37/39", "naklon": 0 }, + "2878": { "label": "37/40", "naklon": 0 }, + "2889": { "label": "37/41", "naklon": 0 }, + "2879": { "label": "37/42", "naklon": 0 }, + "2850": { "label": "37/43", "naklon": 0 }, + "2894": { "label": "37/44", "naklon": 0 }, + "2880": { "label": "37/45", "naklon": 0 }, + "2893": { "label": "37/46", "naklon": 0 }, + "2890": { "label": "37/47", "naklon": 0 }, + "4355": { "label": "37/48", "naklon": 0 }, + "2885": { "label": "37/49", "naklon": 0 }, + "2875": { "label": "37/50", "naklon": 0 }, + "3486": { "label": "38/30A", "naklon": 5 }, + "3714": { "label": "38/30B", "naklon": 0 }, + "3483": { "label": "38/32A", "naklon": 5 }, + "3496": { "label": "38/32B", "naklon": 0 }, + "3487": { "label": "38/35A", "naklon": 5 }, + "3498": { "label": "38/35B", "naklon": 5 }, + "3578": { "label": "38/38A", "naklon": 5 }, + "3508": { "label": "38/38B", "naklon": 5 }, + "3787": { "label": "38/59A", "naklon": 5 }, + "3491": { "label": "38/59B", "naklon": 5 }, + "3568": { "label": "38/1", "naklon": null }, + "3502": { "label": "38/2", "naklon": 0 }, + "3836": { "label": "38/3", "naklon": 0 }, + "3588": { "label": "38/4", "naklon": 0 }, + "3493": { "label": "38/5", "naklon": 0 }, + "3580": { "label": "38/6", "naklon": 0 }, + "3572": { "label": "38/7", "naklon": 0 }, + "3506": { "label": "38/8", "naklon": 0 }, + "3503": { "label": "38/9", "naklon": 0 }, + "3579": { "label": "38/10", "naklon": 0 }, + "3586": { "label": "38/11", "naklon": 0 }, + "3495": { "label": "38/12", "naklon": 5 }, + "3492": { "label": "38/13", "naklon": 5 }, + "3532": { "label": "38/14", "naklon": 5 }, + "3574": { "label": "38/15", "naklon": 5 }, + "4140": { "label": "38/16", "naklon": 5 }, + "3795": { "label": "38/17", "naklon": 5 }, + "3788": { "label": "38/18", "naklon": 5 }, + "3796": { "label": "38/19", "naklon": 5 }, + "3797": { "label": "38/20", "naklon": 5 }, + "3798": { "label": "38/21", "naklon": 5 }, + "3786": { "label": "38/22", "naklon": 5 }, + "4067": { "label": "38/23", "naklon": 5 }, + "3773": { "label": "38/24", "naklon": 5 }, + "3774": { "label": "38/25", "naklon": 5 }, + "3789": { "label": "38/26", "naklon": 5 }, + "3520": { "label": "38/27", "naklon": null }, + "3577": { "label": "38/29", "naklon": 5 }, + "3530": { "label": "38/31", "naklon": null }, + "3488": { "label": "38/33", "naklon": 5 }, + "3505": { "label": "38/34", "naklon": 5 }, + "3497": { "label": "38/36", "naklon": 5 }, + "3490": { "label": "38/37", "naklon": 5 }, + "3585": { "label": "38/39", "naklon": 5 }, + "3582": { "label": "38/40", "naklon": 5 }, + "3507": { "label": "38/41", "naklon": 5 }, + "3484": { "label": "38/42", "naklon": 5 }, + "3501": { "label": "38/43", "naklon": 5 }, + "3581": { "label": "38/44", "naklon": 5 }, + "4192": { "label": "38/45", "naklon": 5 }, + "3576": { "label": "38/46", "naklon": 5 }, + "3489": { "label": "38/47", "naklon": 5 }, + "3573": { "label": "38/48", "naklon": 5 }, + "3504": { "label": "38/49", "naklon": 5 }, + "3794": { "label": "38/50", "naklon": 5 }, + "3485": { "label": "38/51", "naklon": 5 }, + "3482": { "label": "38/52", "naklon": 5 }, + "3575": { "label": "38/53", "naklon": 5 }, + "3499": { "label": "38/54", "naklon": 5 }, + "3494": { "label": "38/55", "naklon": 5 }, + "3583": { "label": "38/56", "naklon": 5 }, + "3570": { "label": "38/57", "naklon": 5 }, + "3500": { "label": "38/58", "naklon": 0 }, + "3510": { "label": "38/63", "naklon": null }, + "3512": { "label": "38/64", "naklon": null }, + "3535": { "label": "38/67", "naklon": null }, + "3531": { "label": "38/68", "naklon": null }, + "3537": { "label": "38/69", "naklon": null }, + "3522": { "label": "39/1", "naklon": 10 }, + "4018": { "label": "39/2", "naklon": 10 }, + "4019": { "label": "39/3", "naklon": 10 }, + "4154": { "label": "39/4", "naklon": 5 }, + "3907": { "label": "39/5", "naklon": 5 }, + "4148": { "label": "39/6", "naklon": 0 }, + "4153": { "label": "39/7", "naklon": 0 }, + "3938": { "label": "39/8", "naklon": 0 }, + "3802": { "label": "39/9", "naklon": 0 }, + "4015": { "label": "39/10", "naklon": 0 }, + "3929": { "label": "39/11", "naklon": 0 }, + "3946": { "label": "39/12", "naklon": 0 }, + "4014": { "label": "39/13", "naklon": 0 }, + "4155": { "label": "39/14", "naklon": 0 }, + "4149": { "label": "39/15", "naklon": 0 }, + "3642": { "label": "39/16", "naklon": 0 }, + "3636": { "label": "39/17", "naklon": 5 }, + "3991": { "label": "39/18", "naklon": 0 }, + "3994": { "label": "39/19", "naklon": 0 }, + "3990": { "label": "39/20", "naklon": 0 }, + "3967": { "label": "39/21", "naklon": 0 }, + "3977": { "label": "39/22", "naklon": 0 }, + "3757": { "label": "39/23", "naklon": 15 }, + "3633": { "label": "39/24", "naklon": 15 }, + "3744": { "label": "39/25", "naklon": 15 }, + "4023": { "label": "39/26", "naklon": 5 }, + "3720": { "label": "39/27", "naklon": 5 }, + "3734": { "label": "39/28", "naklon": 5 }, + "3741": { "label": "39/29", "naklon": 5 }, + "3721": { "label": "39/30", "naklon": 5 }, + "3845": { "label": "39/31", "naklon": 0 }, + "3840": { "label": "39/32", "naklon": 0 }, + "3837": { "label": "39/33", "naklon": null }, + "3839": { "label": "39/34", "naklon": 0 }, + "3542": { "label": "41/1", "naklon": null }, + "3566": { "label": "41/2", "naklon": null }, + "3548": { "label": "41/3", "naklon": null }, + "3515": { "label": "41/4", "naklon": null }, + "3559": { "label": "41/5", "naklon": null }, + "3509": { "label": "41/6", "naklon": null }, + "3524": { "label": "41/7", "naklon": null }, + "3518": { "label": "41/8", "naklon": null }, + "3182": { "label": "41/9", "naklon": null }, + "3187": { "label": "41/10", "naklon": null }, + "3195": { "label": "41/11", "naklon": 0 }, + "3857": { "label": "41/12", "naklon": 0 }, + "3183": { "label": "41/13", "naklon": 0 }, + "3177": { "label": "41/14", "naklon": 0 }, + "3189": { "label": "41/15", "naklon": 0 }, + "3186": { "label": "41/16", "naklon": 0 }, + "3178": { "label": "42/1", "naklon": 0 }, + "3219": { "label": "42/2", "naklon": 0 }, + "3475": { "label": "42/3", "naklon": 0 }, + "3175": { "label": "42/4", "naklon": 0 }, + "3222": { "label": "42/5", "naklon": 0 }, + "3221": { "label": "42/6", "naklon": 0 }, + "3181": { "label": "42/7", "naklon": 0 }, + "3180": { "label": "42/8", "naklon": 0 }, + "3218": { "label": "42/9", "naklon": 0 }, + "3176": { "label": "42/10", "naklon": 0 }, + "3174": { "label": "42/11", "naklon": 0 }, + "3220": { "label": "42/12", "naklon": 0 }, + "3533": { "label": "42/13", "naklon": null }, + "3543": { "label": "42/14", "naklon": null }, + "3554": { "label": "42/15", "naklon": null }, + "3549": { "label": "42/16", "naklon": null }, + "2857": { "label": "43/1", "naklon": 5 }, + "2752": { "label": "43/2", "naklon": 5 }, + "2753": { "label": "43/3", "naklon": 5 }, + "3024": { "label": "43/4", "naklon": 5 }, + "2754": { "label": "43/5", "naklon": 5 }, + "4423": { "label": "43/6", "naklon": 5 }, + "4368": { "label": "43/7", "naklon": 5 }, + "2978": { "label": "43/8", "naklon": 5 }, + "2868": { "label": "43/9", "naklon": 5 }, + "4377": { "label": "43/10", "naklon": 5 }, + "2757": { "label": "43/11", "naklon": 5 }, + "2970": { "label": "43/12", "naklon": 5 }, + "2758": { "label": "43/13", "naklon": 5 }, + "4378": { "label": "43/14", "naklon": 5 }, + "2759": { "label": "43/15", "naklon": 5 }, + "4342": { "label": "43/16", "naklon": 5 }, + "3026": { "label": "43/17", "naklon": null }, + "2986": { "label": "43/18", "naklon": null }, + "4343": { "label": "43/19", "naklon": null }, + "2760": { "label": "43/20", "naklon": null }, + "4379": { "label": "43/21", "naklon": null }, + "2971": { "label": "43/22", "naklon": null }, + "2761": { "label": "43/23", "naklon": null }, + "2762": { "label": "43/24", "naklon": null }, + "4339": { "label": "43/25", "naklon": null }, + "4380": { "label": "43/26", "naklon": null }, + "2975": { "label": "43/27", "naklon": null }, + "3003": { "label": "43/28", "naklon": null }, + "4338": { "label": "43/29", "naklon": null }, + "3002": { "label": "43/30", "naklon": null }, + "4345": { "label": "43/31", "naklon": null }, + "2979": { "label": "43/32", "naklon": null }, + "2989": { "label": "43/33", "naklon": null }, + "2996": { "label": "43/34", "naklon": null }, + "2972": { "label": "43/35", "naklon": null }, + "2988": { "label": "43/36", "naklon": null }, + "4344": { "label": "43/37", "naklon": null }, + "3022": { "label": "43/38", "naklon": null }, + "4341": { "label": "43/39", "naklon": null }, + "2983": { "label": "43/40", "naklon": null }, + "2995": { "label": "43/41", "naklon": null }, + "2763": { "label": "43/42", "naklon": null }, + "2764": { "label": "43/43", "naklon": null }, + "2765": { "label": "43/44", "naklon": null }, + "2766": { "label": "43/45", "naklon": null }, + "2767": { "label": "43/46", "naklon": null }, + "2768": { "label": "43/47", "naklon": null }, + "3018": { "label": "43/48", "naklon": null }, + "2982": { "label": "43/49", "naklon": null }, + "3019": { "label": "43/50", "naklon": 0 }, + "3013": { "label": "43/51", "naklon": null }, + "3007": { "label": "43/52", "naklon": null }, + "2980": { "label": "43/53", "naklon": null }, + "3011": { "label": "43/54", "naklon": null }, + "2672": { "label": "43/55", "naklon": null }, + "2673": { "label": "43/56", "naklon": null }, + "2674": { "label": "43/57", "naklon": null }, + "2675": { "label": "43/58", "naklon": null }, + "2676": { "label": "43/59", "naklon": null }, + "2677": { "label": "43/60", "naklon": null }, + "2678": { "label": "43/61", "naklon": null }, + "2679": { "label": "43/62", "naklon": null }, + "2680": { "label": "43/63", "naklon": null }, + "2840": { "label": "43/64", "naklon": null }, + "2682": { "label": "43/65", "naklon": null }, + "2683": { "label": "43/66", "naklon": null }, + "2684": { "label": "43/67", "naklon": 0 }, + "2685": { "label": "43/68", "naklon": null }, + "2686": { "label": "43/69", "naklon": null }, + "2687": { "label": "43/70", "naklon": null }, + "2688": { "label": "43/71", "naklon": null }, + "2689": { "label": "43/72", "naklon": null }, + "2690": { "label": "43/73", "naklon": null }, + "2691": { "label": "43/74", "naklon": null }, + "2692": { "label": "43/75", "naklon": null }, + "2693": { "label": "43/76", "naklon": 0 }, + "2694": { "label": "43/77", "naklon": null }, + "2695": { "label": "43/78", "naklon": null }, + "2696": { "label": "43/79", "naklon": 0 }, + "2697": { "label": "43/80", "naklon": null }, + "2698": { "label": "43/81", "naklon": 0 }, + "2699": { "label": "43/82", "naklon": null }, + "2700": { "label": "43/83", "naklon": 0 }, + "2744": { "label": "43/84", "naklon": null }, + "2745": { "label": "43/85", "naklon": 0 }, + "2746": { "label": "43/86", "naklon": null }, + "2747": { "label": "43/87", "naklon": 0 }, + "2748": { "label": "43/88", "naklon": null }, + "2749": { "label": "43/89", "naklon": 0 }, + "2841": { "label": "43/90", "naklon": null }, + "4237": { "label": "45/1", "naklon": 5 }, + "4226": { "label": "45/2", "naklon": 5 }, + "4242": { "label": "45/3", "naklon": 5 }, + "4179": { "label": "45/4", "naklon": 5 }, + "4247": { "label": "45/5", "naklon": 5 }, + "4245": { "label": "45/6", "naklon": 5 }, + "3872": { "label": "45/7", "naklon": 5 }, + "4175": { "label": "45/8", "naklon": 5 }, + "4236": { "label": "45/9", "naklon": 5 }, + "4170": { "label": "45/10", "naklon": 5 }, + "4238": { "label": "45/11", "naklon": 5 }, + "4246": { "label": "45/12", "naklon": 5 }, + "4166": { "label": "45/13", "naklon": 5 }, + "4227": { "label": "45/14", "naklon": 5 }, + "4171": { "label": "45/15", "naklon": 5 }, + "4180": { "label": "45/16", "naklon": 5 }, + "4244": { "label": "45/17", "naklon": 5 }, + "4199": { "label": "45/18", "naklon": 5 }, + "4239": { "label": "45/19", "naklon": 5 }, + "4207": { "label": "45/20", "naklon": 5 }, + "4223": { "label": "45/21", "naklon": 5 }, + "4230": { "label": "45/22", "naklon": 5 }, + "4233": { "label": "45/23", "naklon": 5 }, + "4222": { "label": "45/24", "naklon": 5 }, + "4217": { "label": "45/25", "naklon": 5 }, + "4243": { "label": "45/26", "naklon": 5 }, + "4200": { "label": "45/27", "naklon": 5 }, + "4228": { "label": "45/28", "naklon": 5 }, + "4211": { "label": "45/29", "naklon": 5 }, + "4234": { "label": "45/30", "naklon": 5 }, + "4235": { "label": "45/31", "naklon": 5 }, + "4203": { "label": "45/32", "naklon": 5 }, + "4240": { "label": "45/33", "naklon": 5 }, + "4224": { "label": "45/34", "naklon": 5 }, + "4232": { "label": "45/35", "naklon": 5 }, + "4231": { "label": "45/36", "naklon": 5 }, + "4161": { "label": "45/37", "naklon": 5 }, + "4225": { "label": "45/38", "naklon": 5 }, + "4241": { "label": "45/39", "naklon": 5 }, + "4229": { "label": "45/40", "naklon": 5 }, + "4221": { "label": "45/41", "naklon": 5 }, + "4212": { "label": "45/42", "naklon": 5 }, + "4216": { "label": "45/43", "naklon": 5 }, + "3864": { "label": "45/44", "naklon": null }, + "3806": { "label": "46/1", "naklon": 5 }, + "3813": { "label": "46/2", "naklon": 5 }, + "3815": { "label": "46/3", "naklon": 5 }, + "3807": { "label": "46/4", "naklon": 5 }, + "3895": { "label": "46/5", "naklon": 5 }, + "3809": { "label": "46/6", "naklon": 5 }, + "3820": { "label": "46/7", "naklon": 5 }, + "3805": { "label": "46/8", "naklon": 5 }, + "3894": { "label": "46/9", "naklon": 0 }, + "4055": { "label": "46/10", "naklon": 0 }, + "3812": { "label": "46/11", "naklon": 5 }, + "3822": { "label": "46/12", "naklon": 5 }, + "3821": { "label": "46/13", "naklon": 5 }, + "3808": { "label": "46/14", "naklon": 5 }, + "3799": { "label": "46/15", "naklon": 5 }, + "3816": { "label": "46/16", "naklon": 5 }, + "3751": { "label": "46/17", "naklon": 5 }, + "3814": { "label": "46/18", "naklon": 5 }, + "4044": { "label": "46/19", "naklon": 0 }, + "3931": { "label": "46/20", "naklon": 0 }, + "3902": { "label": "46/21", "naklon": 5 }, + "3916": { "label": "46/22", "naklon": 5 }, + "3892": { "label": "46/23", "naklon": 5 }, + "3914": { "label": "46/24", "naklon": 5 }, + "3898": { "label": "46/25", "naklon": 5 }, + "3897": { "label": "46/26", "naklon": 5 }, + "3885": { "label": "46/27", "naklon": 5 }, + "3906": { "label": "46/28", "naklon": 5 }, + "3930": { "label": "46/29", "naklon": 0 }, + "3936": { "label": "46/30", "naklon": 0 }, + "3860": { "label": "46/31", "naklon": 5 }, + "3841": { "label": "46/32", "naklon": 5 }, + "3873": { "label": "46/33", "naklon": 5 }, + "3854": { "label": "46/34", "naklon": 5 }, + "3939": { "label": "46/35", "naklon": 5 }, + "3858": { "label": "46/36", "naklon": 5 }, + "3940": { "label": "46/37", "naklon": 5 }, + "4035": { "label": "46/38", "naklon": 5 }, + "3373": { "label": "47/1", "naklon": 0 }, + "3374": { "label": "47/2", "naklon": 0 }, + "3384": { "label": "47/3", "naklon": 0 }, + "3385": { "label": "47/4", "naklon": 0 }, + "4051": { "label": "48/1", "naklon": 5 }, + "4041": { "label": "48/2", "naklon": 5 }, + "4056": { "label": "48/3", "naklon": 5 }, + "3875": { "label": "48/4", "naklon": 5 }, + "4061": { "label": "48/5", "naklon": 5 }, + "4047": { "label": "48/6", "naklon": 5 }, + "4060": { "label": "48/7", "naklon": 5 }, + "4059": { "label": "48/8", "naklon": 5 }, + "4058": { "label": "48/9", "naklon": 5 }, + "3635": { "label": "48/10", "naklon": 5 }, + "3640": { "label": "48/11", "naklon": 5 }, + "3747": { "label": "48/12", "naklon": 5 }, + "3629": { "label": "48/13", "naklon": 5 }, + "4048": { "label": "48/14", "naklon": 5 }, + "4063": { "label": "48/15", "naklon": 5 }, + "4062": { "label": "48/16", "naklon": 5 }, + "4043": { "label": "48/17", "naklon": 5 }, + "4052": { "label": "48/18", "naklon": 5 }, + "4042": { "label": "48/19", "naklon": 5 }, + "4053": { "label": "48/20", "naklon": 5 }, + "4167": { "label": "50/15A", "naklon": null }, + "4159": { "label": "50/15B", "naklon": null }, + "4183": { "label": "50/1", "naklon": 0 }, + "4157": { "label": "50/2", "naklon": 0 }, + "4160": { "label": "50/3", "naklon": 0 }, + "4173": { "label": "50/4", "naklon": 0 }, + "4177": { "label": "50/5", "naklon": 0 }, + "4174": { "label": "50/6", "naklon": 0 }, + "4178": { "label": "50/7", "naklon": 0 }, + "4195": { "label": "50/8", "naklon": 0 }, + "4169": { "label": "50/9", "naklon": 0 }, + "4162": { "label": "50/10", "naklon": 0 }, + "4158": { "label": "50/11", "naklon": 0 }, + "4182": { "label": "50/12", "naklon": 0 }, + "4194": { "label": "50/13", "naklon": 0 }, + "4184": { "label": "50/14", "naklon": 0 }, + "4197": { "label": "50/16", "naklon": null }, + "4164": { "label": "50/17", "naklon": null }, + "3306": { "label": "50/18", "naklon": null }, + "4168": { "label": "50/19", "naklon": null }, + "4193": { "label": "50/20", "naklon": null }, + "4187": { "label": "50/21", "naklon": null }, + "4163": { "label": "50/22", "naklon": null }, + "4165": { "label": "50/23", "naklon": null }, + "4185": { "label": "50/24", "naklon": null }, + "3904": { "label": "50/25", "naklon": null }, + "2619": { "label": "53/1", "naklon": 0 }, + "2623": { "label": "53/2", "naklon": 0 }, + "2617": { "label": "53/3", "naklon": 0 }, + "2622": { "label": "53/4", "naklon": 0 }, + "2618": { "label": "53/5", "naklon": 0 }, + "2626": { "label": "53/6", "naklon": 0 }, + "2869": { "label": "53/7", "naklon": 0 }, + "2613": { "label": "53/8", "naklon": 0 }, + "2608": { "label": "53/9", "naklon": 0 }, + "2611": { "label": "53/10", "naklon": 0 }, + "2598": { "label": "53/11", "naklon": 0 }, + "3528": { "label": "53/12", "naklon": 0 }, + "3545": { "label": "53/13", "naklon": 0 }, + "2620": { "label": "53/14", "naklon": 0 }, + "2612": { "label": "53/15", "naklon": 0 }, + "2615": { "label": "53/16", "naklon": 0 }, + "3722": { "label": "53/17", "naklon": 0 }, + "2624": { "label": "53/18", "naklon": 0 }, + "2609": { "label": "53/19", "naklon": 0 }, + "2625": { "label": "53/20", "naklon": 0 }, + "2602": { "label": "53/21", "naklon": 0 }, + "2610": { "label": "53/22", "naklon": 0 }, + "2599": { "label": "53/23", "naklon": 0 }, + "2605": { "label": "53/24", "naklon": 0 }, + "2593": { "label": "53/25", "naklon": 0 }, + "3074": { "label": "53/26", "naklon": 0 }, + "2740": { "label": "53/27", "naklon": 0 }, + "2614": { "label": "53/28", "naklon": 0 }, + "2601": { "label": "53/29", "naklon": 0 }, + "4196": { "label": "53/30", "naklon": 0 }, + "2607": { "label": "53/31", "naklon": 0 }, + "2582": { "label": "53/32", "naklon": 0 }, + "2594": { "label": "53/33", "naklon": 0 }, + "2589": { "label": "53/34", "naklon": 0 }, + "2596": { "label": "53/35", "naklon": 0 }, + "2603": { "label": "53/36", "naklon": 0 }, + "2597": { "label": "53/37", "naklon": 0 }, + "2590": { "label": "53/38", "naklon": 0 }, + "2581": { "label": "53/39", "naklon": 0 }, + "2583": { "label": "53/40", "naklon": 0 }, + "2580": { "label": "53/41", "naklon": 0 }, + "2579": { "label": "53/42", "naklon": 0 }, + "2797": { "label": "53/43", "naklon": 0 }, + "2577": { "label": "53/44", "naklon": 0 }, + "2586": { "label": "53/45", "naklon": 0 }, + "2588": { "label": "53/46", "naklon": 0 }, + "2591": { "label": "53/47", "naklon": 0 }, + "2592": { "label": "53/48", "naklon": 0 }, + "2573": { "label": "53/49", "naklon": 0 }, + "2595": { "label": "53/50", "naklon": 0 }, + "2587": { "label": "53/51", "naklon": 0 }, + "2578": { "label": "53/52", "naklon": 0 }, + "2574": { "label": "53/53", "naklon": 0 }, + "2571": { "label": "53/54", "naklon": 0 }, + "2570": { "label": "53/55", "naklon": 0 }, + "2576": { "label": "53/56", "naklon": 0 }, + "2881": { "label": "53/57", "naklon": 0 }, + "2575": { "label": "53/58", "naklon": 0 }, + "2572": { "label": "53/59", "naklon": 0 }, + "2569": { "label": "53/60", "naklon": 0 }, + "4324": { "label": "55/1", "naklon": 0 }, + "4319": { "label": "55/2", "naklon": 0 }, + "4327": { "label": "55/3", "naklon": 0 }, + "4333": { "label": "55/4", "naklon": 0 }, + "4332": { "label": "55/5", "naklon": 0 }, + "4320": { "label": "55/6", "naklon": 0 }, + "4317": { "label": "55/7", "naklon": 0 }, + "4318": { "label": "55/8", "naklon": 0 }, + "4328": { "label": "55/9", "naklon": 0 }, + "4323": { "label": "55/10", "naklon": 0 }, + "4325": { "label": "55/11", "naklon": 0 }, + "4326": { "label": "55/12", "naklon": 0 }, + "4316": { "label": "55/13", "naklon": 0 }, + "4322": { "label": "55/14", "naklon": 0 }, + "4331": { "label": "55/15", "naklon": 0 }, + "4321": { "label": "55/16", "naklon": 0 }, + "4315": { "label": "55/17", "naklon": 0 }, + "4329": { "label": "55/18", "naklon": 0 }, + "4334": { "label": "55/19", "naklon": 0 }, + "4330": { "label": "55/20", "naklon": 0 } +}; + + +let svetlaSorted = [{ "label": "1/3A", "node": 3993, "naklon": 0 }, +{ "label": "1/3B", "node": 3989, "naklon": 15 }, +{ "label": "1/1", "node": 3976, "naklon": 0 }, +{ "label": "1/2", "node": 4181, "naklon": 0 }, +{ "label": "1/4", "node": 4376, "naklon": 15 }, +{ "label": "1/5", "node": 3868, "naklon": 15 }, +{ "label": "1/6", "node": 3728, "naklon": 15 }, +{ "label": "1/7", "node": 3730, "naklon": 0 }, +{ "label": "1/8", "node": 4374, "naklon": 0 }, +{ "label": "1/9", "node": 3718, "naklon": 15 }, +{ "label": "1/10", "node": 4375, "naklon": 15 }, +{ "label": "1/11", "node": 4172, "naklon": 15 }, +{ "label": "1/12", "node": 4176, "naklon": 15 }, +{ "label": "2/1", "node": 3800, "naklon": 5 }, +{ "label": "2/2", "node": 3823, "naklon": 5 }, +{ "label": "2/3", "node": 3905, "naklon": 5 }, +{ "label": "2/4", "node": 3803, "naklon": 5 }, +{ "label": "2/5", "node": 3817, "naklon": 5 }, +{ "label": "2/6", "node": 3818, "naklon": 5 }, +{ "label": "2/7", "node": 3811, "naklon": 5 }, +{ "label": "2/8", "node": 3915, "naklon": 5 }, +{ "label": "2/9", "node": 3843, "naklon": 10 }, +{ "label": "2/10", "node": 3827, "naklon": 10 }, +{ "label": "2/11", "node": 4220, "naklon": 10 }, +{ "label": "2/12", "node": 3826, "naklon": 10 }, +{ "label": "2/13", "node": 3834, "naklon": 10 }, +{ "label": "2/14", "node": 3838, "naklon": 10 }, +{ "label": "2/15", "node": 2823, "naklon": 10 }, +{ "label": "2/16", "node": 3750, "naklon": 10 }, +{ "label": "2/17", "node": 3378, "naklon": 0 }, +{ "label": "2/18", "node": 3376, "naklon": 0 }, +{ "label": "2/19", "node": 3379, "naklon": 0 }, +{ "label": "2/20", "node": 3285, "naklon": 0 }, +{ "label": "2/21", "node": 3382, "naklon": 0 }, +{ "label": "2/22", "node": 3383, "naklon": 0 }, +{ "label": "2/24", "node": 3375, "naklon": 0 }, +{ "label": "2/25", "node": 3381, "naklon": 0 }, +{ "label": "2/26", "node": 3380, "naklon": 0 }, +{ "label": "2/27", "node": 3828, "naklon": 10 }, +{ "label": "2/28", "node": 3377, "naklon": 0 }, +{ "label": "7/1", "node": 3591, "naklon": 0 }, +{ "label": "7/2", "node": 3587, "naklon": 0 }, +{ "label": "7/3", "node": 3468, "naklon": 0 }, +{ "label": "7/4", "node": 3466, "naklon": 0 }, +{ "label": "7/5", "node": 3474, "naklon": 0 }, +{ "label": "7/6", "node": 3481, "naklon": 0 }, +{ "label": "7/7", "node": 3589, "naklon": 0 }, +{ "label": "7/8", "node": 3472, "naklon": 0 }, +{ "label": "7/9", "node": 3473, "naklon": 0 }, +{ "label": "7/10", "node": 3584, "naklon": 0 }, +{ "label": "7/11", "node": 3571, "naklon": 0 }, +{ "label": "7/12", "node": 3476, "naklon": 0 }, +{ "label": "7/13", "node": 3590, "naklon": 0 }, +{ "label": "7/14", "node": 3478, "naklon": 0 }, +{ "label": "7/15", "node": 3471, "naklon": 0 }, +{ "label": "7/16", "node": 3467, "naklon": 0 }, +{ "label": "7/17", "node": 3479, "naklon": 0 }, +{ "label": "7/18", "node": 3480, "naklon": 0 }, +{ "label": "7/19", "node": 3477, "naklon": 0 }, +{ "label": "12/1", "node": 3362, "naklon": 0 }, +{ "label": "12/2", "node": 3355, "naklon": 0 }, +{ "label": "12/3", "node": 3356, "naklon": 0 }, +{ "label": "12/4", "node": 3349, "naklon": 0 }, +{ "label": "12/5", "node": 3357, "naklon": 0 }, +{ "label": "12/6", "node": 3350, "naklon": 0 }, +{ "label": "12/7", "node": 3353, "naklon": 0 }, +{ "label": "12/8", "node": 3539, "naklon": 0 }, +{ "label": "12/9", "node": 3050, "naklon": 0 }, +{ "label": "12/10", "node": 3361, "naklon": 0 }, +{ "label": "12/11", "node": 3360, "naklon": 0 }, +{ "label": "12/12", "node": 3358, "naklon": 0 }, +{ "label": "12/13", "node": 3541, "naklon": 0 }, +{ "label": "12/14", "node": 3551, "naklon": 0 }, +{ "label": "12/15", "node": 3514, "naklon": 0 }, +{ "label": "12/16", "node": 3547, "naklon": 0 }, +{ "label": "12/17", "node": 3562, "naklon": 0 }, +{ "label": "12/18", "node": 3525, "naklon": 0 }, +{ "label": "12/19", "node": 3558, "naklon": 0 }, +{ "label": "12/20", "node": 3511, "naklon": 0 }, +{ "label": "12/21", "node": 3058, "naklon": 0 }, +{ "label": "12/22", "node": 3062, "naklon": 0 }, +{ "label": "12/23", "node": 3070, "naklon": 0 }, +{ "label": "12/24", "node": 3447, "naklon": 0 }, +{ "label": "12/25", "node": 3056, "naklon": 0 }, +{ "label": "12/26", "node": 3057, "naklon": 0 }, +{ "label": "12/27", "node": 3071, "naklon": 0 }, +{ "label": "12/28", "node": 3061, "naklon": 0 }, +{ "label": "12/29", "node": 3069, "naklon": 0 }, +{ "label": "12/30", "node": 3077, "naklon": 0 }, +{ "label": "12/31", "node": 3080, "naklon": 0 }, +{ "label": "12/32", "node": 3081, "naklon": 0 }, +{ "label": "12/33", "node": 3078, "naklon": 0 }, +{ "label": "12/34", "node": 4037, "naklon": 0 }, +{ "label": "12/35", "node": 3067, "naklon": 0 }, +{ "label": "12/36", "node": 3051, "naklon": 0 }, +{ "label": "12/37", "node": 2924, "naklon": 0 }, +{ "label": "12/38", "node": 3060, "naklon": 0 }, +{ "label": "12/39", "node": 3073, "naklon": 0 }, +{ "label": "12/40", "node": 3469, "naklon": 0 }, +{ "label": "12/41", "node": 2923, "naklon": 0 }, +{ "label": "12/42", "node": 2925, "naklon": 0 }, +{ "label": "12/43", "node": 3359, "naklon": 0 }, +{ "label": "12/44", "node": 3055, "naklon": 0 }, +{ "label": "12/45", "node": 2922, "naklon": 0 }, +{ "label": "12/46", "node": 3084, "naklon": 0 }, +{ "label": "12/47", "node": 3064, "naklon": 0 }, +{ "label": "12/48", "node": 3066, "naklon": 0 }, +{ "label": "12/49", "node": 3072, "naklon": 0 }, +{ "label": "13/13A", "node": 3415, "naklon": 0 }, +{ "label": "13/13B", "node": 3409, "naklon": 0 }, +{ "label": "13/13C", "node": 3399, "naklon": 0 }, +{ "label": "13/29A", "node": 3410, "naklon": 0 }, +{ "label": "13/29B", "node": 3407, "naklon": 0 }, +{ "label": "13/34A", "node": 3405, "naklon": 0 }, +{ "label": "13/34B", "node": 3404, "naklon": 0 }, +{ "label": "13/45A", "node": 3392, "naklon": 0 }, +{ "label": "13/45B", "node": 3386, "naklon": 0 }, +{ "label": "13/60A", "node": 3303, "naklon": 3 }, +{ "label": "13/60B", "node": 3302, "naklon": 3 }, +{ "label": "13/70A", "node": 3319, "naklon": 6 }, +{ "label": "13/70B", "node": 3317, "naklon": 6 }, +{ "label": "13/70C", "node": 3326, "naklon": 6 }, +{ "label": "13/73A", "node": 3351, "naklon": 6 }, +{ "label": "13/73B", "node": 3313, "naklon": 6 }, +{ "label": "13/83A", "node": 3316, "naklon": 0 }, +{ "label": "13/83B", "node": 3320, "naklon": 0 }, +{ "label": "13/95A", "node": 3336, "naklon": 0 }, +{ "label": "13/95B", "node": 3323, "naklon": 0 }, +{ "label": "13/98A", "node": 3339, "naklon": 0 }, +{ "label": "13/98B", "node": 3333, "naklon": 0 }, +{ "label": "13/1", "node": 3425, "naklon": 0 }, +{ "label": "13/2", "node": 3419, "naklon": 0 }, +{ "label": "13/3", "node": 3416, "naklon": 0 }, +{ "label": "13/4", "node": 3332, "naklon": 0 }, +{ "label": "13/5", "node": 3422, "naklon": 0 }, +{ "label": "13/6", "node": 3417, "naklon": 0 }, +{ "label": "13/7", "node": 3418, "naklon": 0 }, +{ "label": "13/8", "node": 3424, "naklon": 0 }, +{ "label": "13/9", "node": 3334, "naklon": 0 }, +{ "label": "13/10", "node": 4363, "naklon": 0 }, +{ "label": "13/11", "node": 3423, "naklon": 0 }, +{ "label": "13/12", "node": 3406, "naklon": 0 }, +{ "label": "13/14", "node": 3411, "naklon": 0 }, +{ "label": "13/15", "node": 3412, "naklon": 0 }, +{ "label": "13/16", "node": 3413, "naklon": 0 }, +{ "label": "13/17", "node": 3414, "naklon": 0 }, +{ "label": "13/18", "node": 3391, "naklon": 0 }, +{ "label": "13/19", "node": 3370, "naklon": 0 }, +{ "label": "13/20", "node": 3369, "naklon": 0 }, +{ "label": "13/21", "node": 3408, "naklon": 0 }, +{ "label": "13/22", "node": 3393, "naklon": 0 }, +{ "label": "13/23", "node": 3128, "naklon": 0 }, +{ "label": "13/24", "node": 3197, "naklon": 0 }, +{ "label": "13/25", "node": 4364, "naklon": 0 }, +{ "label": "13/26", "node": 3155, "naklon": 0 }, +{ "label": "13/27", "node": 3196, "naklon": 0 }, +{ "label": "13/28", "node": 3144, "naklon": 0 }, +{ "label": "13/30", "node": 3150, "naklon": 0 }, +{ "label": "13/31", "node": 3390, "naklon": 0 }, +{ "label": "13/32", "node": 3401, "naklon": 0 }, +{ "label": "13/33", "node": 3275, "naklon": 0 }, +{ "label": "13/35", "node": 3371, "naklon": 0 }, +{ "label": "13/36", "node": 3389, "naklon": 0 }, +{ "label": "13/37", "node": 3388, "naklon": 0 }, +{ "label": "13/38", "node": 3365, "naklon": 0 }, +{ "label": "13/39", "node": 3363, "naklon": 0 }, +{ "label": "13/40", "node": 3397, "naklon": 0 }, +{ "label": "13/40/1", "node": 3567, "naklon": 0 }, +{ "label": "13/41", "node": 3387, "naklon": 0 }, +{ "label": "13/42", "node": 3403, "naklon": 0 }, +{ "label": "13/43", "node": 3147, "naklon": 0 }, +{ "label": "13/44", "node": 3141, "naklon": 0 }, +{ "label": "13/46", "node": 3364, "naklon": 0 }, +{ "label": "13/47", "node": 3367, "naklon": 0 }, +{ "label": "13/48", "node": 3368, "naklon": 0 }, +{ "label": "13/49", "node": 3402, "naklon": 0 }, +{ "label": "13/50", "node": 3366, "naklon": 0 }, +{ "label": "13/51", "node": 3395, "naklon": 0 }, +{ "label": "13/52", "node": 3372, "naklon": 0 }, +{ "label": "13/53", "node": 3394, "naklon": 0 }, +{ "label": "13/54", "node": 3308, "naklon": 0 }, +{ "label": "13/54/1", "node": 3847, "naklon": 0 }, +{ "label": "13/55", "node": 3312, "naklon": 3 }, +{ "label": "13/56", "node": 3309, "naklon": 3 }, +{ "label": "13/57", "node": 3311, "naklon": 3 }, +{ "label": "13/58", "node": 3310, "naklon": 3 }, +{ "label": "13/59", "node": 4365, "naklon": 3 }, +{ "label": "13/60/1", "node": 4093, "naklon": 3 }, +{ "label": "13/61", "node": 3304, "naklon": 3 }, +{ "label": "13/62", "node": 3307, "naklon": 3 }, +{ "label": "13/63", "node": 3271, "naklon": 3 }, +{ "label": "13/64", "node": 3301, "naklon": 3 }, +{ "label": "13/65", "node": 4366, "naklon": 3 }, +{ "label": "13/66", "node": 3300, "naklon": 3 }, +{ "label": "13/67", "node": 3185, "naklon": 0 }, +{ "label": "13/68", "node": 3184, "naklon": 0 }, +{ "label": "13/69", "node": 3188, "naklon": 0 }, +{ "label": "13/71", "node": 3343, "naklon": 6 }, +{ "label": "13/71/1", "node": 3819, "naklon": 6 }, +{ "label": "13/71/2", "node": 3880, "naklon": 6 }, +{ "label": "13/72", "node": 3348, "naklon": 6 }, +{ "label": "13/74", "node": 3344, "naklon": 6 }, +{ "label": "13/75", "node": 3346, "naklon": 6 }, +{ "label": "13/75/1", "node": 3597, "naklon": 6 }, +{ "label": "13/76", "node": 3345, "naklon": 6 }, +{ "label": "13/77", "node": 3322, "naklon": 0 }, +{ "label": "13/78", "node": 3325, "naklon": 0 }, +{ "label": "13/78/1", "node": 4310, "naklon": 0 }, +{ "label": "13/79", "node": 3315, "naklon": 0 }, +{ "label": "13/80", "node": 3328, "naklon": 0 }, +{ "label": "13/81", "node": 3321, "naklon": 0 }, +{ "label": "13/82", "node": 3324, "naklon": 0 }, +{ "label": "13/84", "node": 3140, "naklon": 0 }, +{ "label": "13/85", "node": 3153, "naklon": 0 }, +{ "label": "13/86", "node": 3145, "naklon": 0 }, +{ "label": "13/87", "node": 3134, "naklon": 0 }, +{ "label": "13/88", "node": 3151, "naklon": 0 }, +{ "label": "13/89", "node": 3143, "naklon": 0 }, +{ "label": "13/90", "node": 3318, "naklon": 0 }, +{ "label": "13/91", "node": 3347, "naklon": 0 }, +{ "label": "13/94", "node": 3314, "naklon": 0 }, +{ "label": "13/96", "node": 3331, "naklon": 0 }, +{ "label": "13/97", "node": 3327, "naklon": 0 }, +{ "label": "13/99", "node": 3329, "naklon": 0 }, +{ "label": "13/100", "node": 3337, "naklon": 0 }, +{ "label": "13/101", "node": 3330, "naklon": 0 }, +{ "label": "13/102", "node": 3335, "naklon": 0 }, +{ "label": "13/103", "node": 3420, "naklon": 0 }, +{ "label": "13/104", "node": 3421, "naklon": 0 }, +{ "label": "13/105", "node": 4361, "naklon": 0 }, +{ "label": "13/106", "node": 4362, "naklon": 0 }, +{ "label": "13/107", "node": 3526, "naklon": 0 }, +{ "label": "13/108", "node": 4424, "naklon": null }, +{ "label": "13/109", "node": 3561, "naklon": null }, +{ "label": "13/110", "node": 3527, "naklon": null }, +{ "label": "13/111", "node": 3521, "naklon": null }, +{ "label": "13/112", "node": 3552, "naklon": null }, +{ "label": "13/113", "node": 3544, "naklon": null }, +{ "label": "13/114", "node": 3534, "naklon": null }, +{ "label": "13/115", "node": 3516, "naklon": null }, +{ "label": "13/116", "node": 3513, "naklon": null }, +{ "label": "13/117", "node": 3565, "naklon": null }, +{ "label": "13/118", "node": 3866, "naklon": null }, +{ "label": "14/1", "node": 3136, "naklon": 0 }, +{ "label": "14/2", "node": 3137, "naklon": 0 }, +{ "label": "14/3", "node": 3135, "naklon": 0 }, +{ "label": "14/4", "node": 3149, "naklon": 0 }, +{ "label": "14/5", "node": 3142, "naklon": 0 }, +{ "label": "14/6", "node": 3342, "naklon": 0 }, +{ "label": "14/7", "node": 3340, "naklon": 0 }, +{ "label": "14/8", "node": 3152, "naklon": 0 }, +{ "label": "14/9", "node": 3886, "naklon": 0 }, +{ "label": "14/10", "node": 3341, "naklon": null }, +{ "label": "14/11", "node": 3352, "naklon": null }, +{ "label": "15/1", "node": 3396, "naklon": 5 }, +{ "label": "15/2", "node": 2784, "naklon": 5 }, +{ "label": "15/3", "node": 2788, "naklon": 5 }, +{ "label": "15/4", "node": 2801, "naklon": 5 }, +{ "label": "15/5", "node": 2815, "naklon": 5 }, +{ "label": "15/6", "node": 2829, "naklon": 5 }, +{ "label": "15/7", "node": 2796, "naklon": 5 }, +{ "label": "15/8", "node": 2803, "naklon": 5 }, +{ "label": "15/8/1", "node": 4304, "naklon": 5 }, +{ "label": "15/8/2", "node": 4311, "naklon": 5 }, +{ "label": "15/9", "node": 2821, "naklon": 5 }, +{ "label": "15/10", "node": 3400, "naklon": 5 }, +{ "label": "15/11", "node": 2799, "naklon": 5 }, +{ "label": "15/12", "node": 2804, "naklon": 5 }, +{ "label": "15/12/1", "node": 4303, "naklon": 5 }, +{ "label": "15/12/2", "node": 4309, "naklon": 5 }, +{ "label": "15/13", "node": 2806, "naklon": 5 }, +{ "label": "15/14", "node": 2787, "naklon": 5 }, +{ "label": "15/15", "node": 2809, "naklon": 5 }, +{ "label": "15/16", "node": 2814, "naklon": 0 }, +{ "label": "15/17", "node": 3934, "naklon": 0 }, +{ "label": "15/18", "node": 3192, "naklon": 0 }, +{ "label": "15/19", "node": 2812, "naklon": 0 }, +{ "label": "15/20", "node": 4070, "naklon": 0 }, +{ "label": "15/21", "node": 2826, "naklon": 0 }, +{ "label": "15/22", "node": 2808, "naklon": 3 }, +{ "label": "15/23", "node": 2795, "naklon": 3 }, +{ "label": "15/24", "node": 2807, "naklon": 3 }, +{ "label": "15/25", "node": 2831, "naklon": 0 }, +{ "label": "15/26", "node": 2862, "naklon": null }, +{ "label": "15/27", "node": 2861, "naklon": 0 }, +{ "label": "15/28", "node": 2866, "naklon": 0 }, +{ "label": "15/28/1", "node": 3546, "naklon": 0 }, +{ "label": "15/29", "node": 4146, "naklon": 0 }, +{ "label": "15/29/1", "node": 3001, "naklon": 0 }, +{ "label": "15/30", "node": 2835, "naklon": 0 }, +{ "label": "15/31", "node": 2874, "naklon": 0 }, +{ "label": "15/32", "node": 2852, "naklon": 0 }, +{ "label": "15/33", "node": 2851, "naklon": 0 }, +{ "label": "15/33/1", "node": 3560, "naklon": 0 }, +{ "label": "15/34", "node": 2858, "naklon": 0 }, +{ "label": "15/34/1", "node": 4306, "naklon": 0 }, +{ "label": "15/35", "node": 2856, "naklon": 0 }, +{ "label": "15/36", "node": 2847, "naklon": 0 }, +{ "label": "15/36/1", "node": 3556, "naklon": 0 }, +{ "label": "15/37", "node": 3950, "naklon": 0 }, +{ "label": "15/38", "node": 2848, "naklon": 0 }, +{ "label": "15/39", "node": 2863, "naklon": 0 }, +{ "label": "15/39/1", "node": 4313, "naklon": 0 }, +{ "label": "15/40", "node": 2873, "naklon": 0 }, +{ "label": "15/40/1", "node": 2984, "naklon": 0 }, +{ "label": "15/41", "node": 2854, "naklon": 0 }, +{ "label": "15/42", "node": 2859, "naklon": 0 }, +{ "label": "15/43", "node": 2872, "naklon": 0 }, +{ "label": "15/44", "node": 2849, "naklon": 0 }, +{ "label": "15/45", "node": 2864, "naklon": 0 }, +{ "label": "15/46", "node": 3553, "naklon": null }, +{ "label": "15/47", "node": 3021, "naklon": null }, +{ "label": "15/47/1", "node": 3008, "naklon": null }, +{ "label": "15/48", "node": 3017, "naklon": null }, +{ "label": "15/49", "node": 3014, "naklon": null }, +{ "label": "15/50", "node": 2981, "naklon": null }, +{ "label": "15/51", "node": 3020, "naklon": null }, +{ "label": "15/52", "node": 3027, "naklon": null }, +{ "label": "15/53", "node": 3006, "naklon": null }, +{ "label": "15/54", "node": 3012, "naklon": null }, +{ "label": "15/55", "node": 2738, "naklon": 0 }, +{ "label": "15/56", "node": 2725, "naklon": 0 }, +{ "label": "15/57", "node": 3016, "naklon": null }, +{ "label": "15/58", "node": 3005, "naklon": null }, +{ "label": "15/58/1", "node": 3009, "naklon": null }, +{ "label": "15/59", "node": 3010, "naklon": 0 }, +{ "label": "15/59/1", "node": 3538, "naklon": 0 }, +{ "label": "15/59/2", "node": 4145, "naklon": 0 }, +{ "label": "15/60", "node": 2713, "naklon": 0 }, +{ "label": "15/61", "node": 2789, "naklon": 0 }, +{ "label": "15/62", "node": 2736, "naklon": 0 }, +{ "label": "15/63", "node": 2739, "naklon": 0 }, +{ "label": "15/64", "node": 4346, "naklon": 0 }, +{ "label": "15/65", "node": 2731, "naklon": 0 }, +{ "label": "15/66", "node": 2818, "naklon": 0 }, +{ "label": "15/66/1", "node": 3557, "naklon": 0 }, +{ "label": "15/67", "node": 2822, "naklon": 0 }, +{ "label": "15/68", "node": 2833, "naklon": 0 }, +{ "label": "15/69", "node": 2834, "naklon": 0 }, +{ "label": "15/70", "node": 3097, "naklon": 0 }, +{ "label": "15/71", "node": 2824, "naklon": 0 }, +{ "label": "15/72", "node": 2828, "naklon": 0 }, +{ "label": "15/73", "node": 2600, "naklon": 0 }, +{ "label": "15/73/1", "node": 4314, "naklon": 0 }, +{ "label": "15/74", "node": 2832, "naklon": 0 }, +{ "label": "15/75", "node": 4360, "naklon": 0 }, +{ "label": "15/76", "node": 2846, "naklon": 0 }, +{ "label": "15/77", "node": 2584, "naklon": 0 }, +{ "label": "15/78", "node": 2843, "naklon": 0 }, +{ "label": "15/78/1", "node": 4308, "naklon": 0 }, +{ "label": "15/79", "node": 4144, "naklon": null }, +{ "label": "15/80", "node": 2844, "naklon": 0 }, +{ "label": "15/81", "node": 2842, "naklon": 0 }, +{ "label": "15/82", "node": 2838, "naklon": 0 }, +{ "label": "15/83", "node": 2837, "naklon": null }, +{ "label": "15/83/1", "node": 3555, "naklon": null }, +{ "label": "15/84", "node": 2839, "naklon": 0 }, +{ "label": "15/85", "node": 2830, "naklon": 0 }, +{ "label": "15/86", "node": 4066, "naklon": 0 }, +{ "label": "15/87", "node": 2836, "naklon": 0 }, +{ "label": "15/88", "node": 2911, "naklon": 0 }, +{ "label": "15/89", "node": 2825, "naklon": 0 }, +{ "label": "15/90", "node": 2811, "naklon": 0 }, +{ "label": "15/94", "node": 3740, "naklon": 15 }, +{ "label": "15/95", "node": 2734, "naklon": 15 }, +{ "label": "15/96", "node": 3105, "naklon": 15 }, +{ "label": "15/97", "node": 2732, "naklon": 15 }, +{ "label": "15/98", "node": 2727, "naklon": 15 }, +{ "label": "15/99", "node": 2735, "naklon": 15 }, +{ "label": "15/100", "node": 3926, "naklon": 15 }, +{ "label": "15/101", "node": 2918, "naklon": 0 }, +{ "label": "15/102", "node": 2705, "naklon": 10 }, +{ "label": "15/103", "node": 2708, "naklon": 10 }, +{ "label": "15/104", "node": 2721, "naklon": 10 }, +{ "label": "15/105", "node": 2719, "naklon": 10 }, +{ "label": "15/106", "node": 2919, "naklon": 10 }, +{ "label": "15/107", "node": 3101, "naklon": 10 }, +{ "label": "15/108", "node": 2853, "naklon": 10 }, +{ "label": "15/109", "node": 2715, "naklon": 10 }, +{ "label": "15/110", "node": 2712, "naklon": 0 }, +{ "label": "15/111", "node": 2711, "naklon": 0 }, +{ "label": "15/112", "node": 2709, "naklon": 0 }, +{ "label": "15/113", "node": 2710, "naklon": 0 }, +{ "label": "15/114", "node": 2907, "naklon": 0 }, +{ "label": "15/115", "node": 2906, "naklon": 0 }, +{ "label": "15/116", "node": 2908, "naklon": 0 }, +{ "label": "15/117", "node": 2901, "naklon": 0 }, +{ "label": "15/118", "node": 2913, "naklon": 0 }, +{ "label": "15/119", "node": 3656, "naklon": 0 }, +{ "label": "15/120", "node": 2781, "naklon": 0 }, +{ "label": "15/121", "node": 2802, "naklon": 0 }, +{ "label": "15/122", "node": 2791, "naklon": 0 }, +{ "label": "15/123", "node": 2783, "naklon": 0 }, +{ "label": "15/124", "node": 2794, "naklon": 0 }, +{ "label": "15/125", "node": 3139, "naklon": 0 }, +{ "label": "15/126", "node": 3229, "naklon": 5 }, +{ "label": "15/127", "node": 3239, "naklon": 5 }, +{ "label": "15/128", "node": 3230, "naklon": 5 }, +{ "label": "15/129", "node": 4016, "naklon": null }, +{ "label": "16/16A", "node": 3608, "naklon": 0 }, +{ "label": "16/16B", "node": 4151, "naklon": 0 }, +{ "label": "16/1", "node": 3710, "naklon": 0 }, +{ "label": "16/2", "node": 3726, "naklon": 0 }, +{ "label": "16/3", "node": 3743, "naklon": 0 }, +{ "label": "16/4", "node": 3724, "naklon": 0 }, +{ "label": "16/5", "node": 3712, "naklon": 0 }, +{ "label": "16/6", "node": 3739, "naklon": 0 }, +{ "label": "16/7", "node": 3742, "naklon": 0 }, +{ "label": "16/8", "node": 3731, "naklon": 0 }, +{ "label": "16/9", "node": 3727, "naklon": 0 }, +{ "label": "16/10", "node": 3729, "naklon": 0 }, +{ "label": "16/11", "node": 3736, "naklon": 0 }, +{ "label": "16/12", "node": 3713, "naklon": 0 }, +{ "label": "16/13", "node": 3715, "naklon": 0 }, +{ "label": "16/14", "node": 3733, "naklon": 0 }, +{ "label": "16/15", "node": 3732, "naklon": 0 }, +{ "label": "16/17", "node": 3634, "naklon": 0 }, +{ "label": "16/18", "node": 3610, "naklon": 0 }, +{ "label": "16/19", "node": 3626, "naklon": 0 }, +{ "label": "16/20", "node": 3618, "naklon": 0 }, +{ "label": "16/21", "node": 3619, "naklon": 0 }, +{ "label": "16/22", "node": 3628, "naklon": 0 }, +{ "label": "16/23", "node": 3615, "naklon": 0 }, +{ "label": "16/24", "node": 3609, "naklon": 0 }, +{ "label": "16/25", "node": 3606, "naklon": 0 }, +{ "label": "16/26", "node": 3624, "naklon": 0 }, +{ "label": "16/27", "node": 3627, "naklon": 0 }, +{ "label": "16/28", "node": 3607, "naklon": 0 }, +{ "label": "16/29", "node": 4370, "naklon": 0 }, +{ "label": "16/30", "node": 3692, "naklon": 0 }, +{ "label": "16/31", "node": 3614, "naklon": 0 }, +{ "label": "16/32", "node": 3623, "naklon": 0 }, +{ "label": "16/33", "node": 4373, "naklon": 0 }, +{ "label": "16/34", "node": 3620, "naklon": 0 }, +{ "label": "16/35", "node": 3685, "naklon": 0 }, +{ "label": "16/36", "node": 3616, "naklon": 0 }, +{ "label": "16/37", "node": 3686, "naklon": 0 }, +{ "label": "16/38", "node": 3688, "naklon": 0 }, +{ "label": "16/39", "node": 3684, "naklon": 0 }, +{ "label": "16/40", "node": 3825, "naklon": 0 }, +{ "label": "16/41", "node": 3865, "naklon": 0 }, +{ "label": "16/42", "node": 3824, "naklon": 0 }, +{ "label": "16/43", "node": 3871, "naklon": 0 }, +{ "label": "16/44", "node": 3801, "naklon": 0 }, +{ "label": "16/45", "node": 3862, "naklon": 0 }, +{ "label": "16/46", "node": 3876, "naklon": 0 }, +{ "label": "16/47", "node": 3861, "naklon": 0 }, +{ "label": "16/48", "node": 4215, "naklon": 0 }, +{ "label": "16/49", "node": 3605, "naklon": 10 }, +{ "label": "16/50", "node": 3603, "naklon": 10 }, +{ "label": "16/51", "node": 3592, "naklon": 10 }, +{ "label": "16/52", "node": 3598, "naklon": 10 }, +{ "label": "16/53", "node": 3594, "naklon": 10 }, +{ "label": "16/54", "node": 3593, "naklon": 10 }, +{ "label": "16/55", "node": 3630, "naklon": 10 }, +{ "label": "16/56", "node": 3763, "naklon": 10 }, +{ "label": "16/57", "node": 3746, "naklon": 10 }, +{ "label": "16/58", "node": 3699, "naklon": 0 }, +{ "label": "16/59", "node": 3698, "naklon": 0 }, +{ "label": "16/60", "node": 3709, "naklon": null }, +{ "label": "16/61", "node": 3708, "naklon": 0 }, +{ "label": "16/62", "node": 3703, "naklon": null }, +{ "label": "16/63", "node": 3700, "naklon": 0 }, +{ "label": "16/64", "node": 3701, "naklon": null }, +{ "label": "16/65", "node": 3704, "naklon": 0 }, +{ "label": "16/66", "node": 3707, "naklon": null }, +{ "label": "16/67", "node": 3810, "naklon": 0 }, +{ "label": "16/68", "node": 4208, "naklon": null }, +{ "label": "16/69", "node": 3867, "naklon": 0 }, +{ "label": "16/70", "node": 4372, "naklon": null }, +{ "label": "16/71", "node": 3881, "naklon": 0 }, +{ "label": "16/72", "node": 4204, "naklon": null }, +{ "label": "16/73", "node": 3869, "naklon": 0 }, +{ "label": "16/74", "node": 4202, "naklon": null }, +{ "label": "16/75", "node": 3830, "naklon": 0 }, +{ "label": "16/76", "node": 3870, "naklon": null }, +{ "label": "16/77", "node": 3964, "naklon": 0 }, +{ "label": "16/78", "node": 3849, "naklon": 0 }, +{ "label": "16/79", "node": 3694, "naklon": null }, +{ "label": "16/80", "node": 3717, "naklon": 0 }, +{ "label": "16/81", "node": 3877, "naklon": null }, +{ "label": "16/82", "node": 3755, "naklon": 0 }, +{ "label": "16/83", "node": 3725, "naklon": null }, +{ "label": "16/84", "node": 3716, "naklon": 0 }, +{ "label": "16/85", "node": 3696, "naklon": null }, +{ "label": "16/86", "node": 3702, "naklon": 0 }, +{ "label": "16/87", "node": 3706, "naklon": null }, +{ "label": "16/88", "node": 3850, "naklon": 0 }, +{ "label": "16/89", "node": 3848, "naklon": null }, +{ "label": "16/90", "node": 3737, "naklon": null }, +{ "label": "16/91", "node": 3705, "naklon": 0 }, +{ "label": "16/92", "node": 3723, "naklon": null }, +{ "label": "16/93", "node": 3842, "naklon": 0 }, +{ "label": "16/94", "node": 3735, "naklon": null }, +{ "label": "16/95", "node": 3719, "naklon": 0 }, +{ "label": "16/96", "node": 3697, "naklon": 0 }, +{ "label": "16/97", "node": 3711, "naklon": 0 }, +{ "label": "16/98", "node": 4107, "naklon": null }, +{ "label": "16/99", "node": 4112, "naklon": 5 }, +{ "label": "16/100", "node": 4106, "naklon": 5 }, +{ "label": "16/101", "node": 4111, "naklon": 5 }, +{ "label": "16/102", "node": 4091, "naklon": null }, +{ "label": "16/103", "node": 4104, "naklon": 5 }, +{ "label": "16/104", "node": 4094, "naklon": null }, +{ "label": "16/105", "node": 4089, "naklon": 5 }, +{ "label": "16/106", "node": 4095, "naklon": null }, +{ "label": "16/107", "node": 4102, "naklon": 5 }, +{ "label": "16/108", "node": 4105, "naklon": null }, +{ "label": "16/109", "node": 3859, "naklon": null }, +{ "label": "16/110", "node": 4090, "naklon": 5 }, +{ "label": "16/111", "node": 4110, "naklon": null }, +{ "label": "16/112", "node": 4097, "naklon": 5 }, +{ "label": "16/113", "node": 4099, "naklon": null }, +{ "label": "16/114", "node": 4096, "naklon": null }, +{ "label": "16/115", "node": 4101, "naklon": 5 }, +{ "label": "16/116", "node": 4109, "naklon": null }, +{ "label": "16/117", "node": 4092, "naklon": 5 }, +{ "label": "16/118", "node": 3631, "naklon": null }, +{ "label": "16/119", "node": 3632, "naklon": 0 }, +{ "label": "16/120", "node": 3641, "naklon": null }, +{ "label": "16/121", "node": 3638, "naklon": 0 }, +{ "label": "16/122", "node": 3637, "naklon": null }, +{ "label": "16/123", "node": 4142, "naklon": null }, +{ "label": "16/124", "node": 4147, "naklon": 5 }, +{ "label": "16/125", "node": 4139, "naklon": 5 }, +{ "label": "20/30A", "node": 3172, "naklon": 2 }, +{ "label": "20/30B", "node": 3164, "naklon": 2 }, +{ "label": "20/1", "node": 3247, "naklon": 10 }, +{ "label": "20/2", "node": 3296, "naklon": 10 }, +{ "label": "20/3", "node": 3246, "naklon": 10 }, +{ "label": "20/4", "node": 3270, "naklon": 10 }, +{ "label": "20/5", "node": 3294, "naklon": 10 }, +{ "label": "20/6", "node": 3298, "naklon": 10 }, +{ "label": "20/7", "node": 3297, "naklon": 10 }, +{ "label": "20/8", "node": 3293, "naklon": 10 }, +{ "label": "20/9", "node": 3299, "naklon": 10 }, +{ "label": "20/10", "node": 3295, "naklon": 10 }, +{ "label": "20/11", "node": 3244, "naklon": 10 }, +{ "label": "20/12", "node": 3249, "naklon": 10 }, +{ "label": "20/13", "node": 3268, "naklon": 10 }, +{ "label": "20/14", "node": 3245, "naklon": 10 }, +{ "label": "20/15", "node": 3278, "naklon": 10 }, +{ "label": "20/16", "node": 3280, "naklon": 10 }, +{ "label": "20/17", "node": 3292, "naklon": 10 }, +{ "label": "20/18", "node": 3287, "naklon": 10 }, +{ "label": "20/19", "node": 3282, "naklon": 10 }, +{ "label": "20/20", "node": 3273, "naklon": 0 }, +{ "label": "20/21", "node": 3157, "naklon": 0 }, +{ "label": "20/22", "node": 3283, "naklon": 0 }, +{ "label": "20/23", "node": 3159, "naklon": 0 }, +{ "label": "20/24", "node": 3289, "naklon": 0 }, +{ "label": "20/25", "node": 3163, "naklon": 0 }, +{ "label": "20/26", "node": 3126, "naklon": 0 }, +{ "label": "20/27", "node": 3171, "naklon": 0 }, +{ "label": "20/28", "node": 3162, "naklon": 0 }, +{ "label": "20/29", "node": 3279, "naklon": 10 }, +{ "label": "20/31", "node": 3173, "naklon": 0 }, +{ "label": "20/32", "node": 3127, "naklon": 0 }, +{ "label": "20/33", "node": 3131, "naklon": 0 }, +{ "label": "20/34", "node": 3129, "naklon": 0 }, +{ "label": "20/35", "node": 3276, "naklon": 2 }, +{ "label": "20/36", "node": 3290, "naklon": 2 }, +{ "label": "20/37", "node": 3132, "naklon": 0 }, +{ "label": "20/38", "node": 3138, "naklon": 0 }, +{ "label": "20/39", "node": 3272, "naklon": 0 }, +{ "label": "20/40", "node": 3291, "naklon": 0 }, +{ "label": "20/41", "node": 3277, "naklon": 10 }, +{ "label": "20/42", "node": 3286, "naklon": 10 }, +{ "label": "20/43", "node": 3281, "naklon": 10 }, +{ "label": "20/44", "node": 3288, "naklon": 10 }, +{ "label": "20/45", "node": 3284, "naklon": 10 }, +{ "label": "20/46", "node": 3167, "naklon": 10 }, +{ "label": "20/47", "node": 3872, "naklon": 0 }, +{ "label": "20/48", "node": 3124, "naklon": 0 }, +{ "label": "20/49", "node": 3133, "naklon": 0 }, +{ "label": "20/50", "node": 3158, "naklon": 0 }, +{ "label": "20/51", "node": 3169, "naklon": 0 }, +{ "label": "20/52", "node": 3146, "naklon": 0 }, +{ "label": "20/53", "node": 3160, "naklon": 0 }, +{ "label": "20/54", "node": 3248, "naklon": 0 }, +{ "label": "20/55", "node": 3156, "naklon": 0 }, +{ "label": "20/56", "node": 3161, "naklon": 0 }, +{ "label": "20/57", "node": 3170, "naklon": 0 }, +{ "label": "20/58", "node": 3168, "naklon": 0 }, +{ "label": "20/59", "node": 3125, "naklon": 0 }, +{ "label": "20/60", "node": 3166, "naklon": 0 }, +{ "label": "20/61", "node": 3130, "naklon": 0 }, +{ "label": "20/62", "node": 3563, "naklon": 0 }, +{ "label": "20/63", "node": 3550, "naklon": null }, +{ "label": "20/67", "node": 3269, "naklon": 0 }, +{ "label": "21/1", "node": 2921, "naklon": 0 }, +{ "label": "21/2", "node": 2707, "naklon": 0 }, +{ "label": "21/3", "node": 2723, "naklon": 0 }, +{ "label": "21/4", "node": 2716, "naklon": 0 }, +{ "label": "21/5", "node": 2717, "naklon": 0 }, +{ "label": "21/6", "node": 2720, "naklon": 0 }, +{ "label": "21/7", "node": 2722, "naklon": 0 }, +{ "label": "21/8", "node": 2718, "naklon": 0 }, +{ "label": "21/9", "node": 2724, "naklon": 0 }, +{ "label": "21/10", "node": 2742, "naklon": 0 }, +{ "label": "21/11", "node": 2743, "naklon": 0 }, +{ "label": "21/12", "node": 2733, "naklon": 0 }, +{ "label": "21/14", "node": 2903, "naklon": 0 }, +{ "label": "21/15", "node": 2917, "naklon": 0 }, +{ "label": "21/16", "node": 2897, "naklon": 0 }, +{ "label": "21/17", "node": 2914, "naklon": 0 }, +{ "label": "21/18", "node": 2898, "naklon": 0 }, +{ "label": "21/19", "node": 2773, "naklon": 0 }, +{ "label": "21/20", "node": 2895, "naklon": 0 }, +{ "label": "21/21", "node": 2896, "naklon": 0 }, +{ "label": "21/22", "node": 2771, "naklon": 0 }, +{ "label": "21/23", "node": 2772, "naklon": 0 }, +{ "label": "21/24", "node": 2793, "naklon": 0 }, +{ "label": "21/25", "node": 2902, "naklon": 0 }, +{ "label": "21/26", "node": 2910, "naklon": 0 }, +{ "label": "21/27", "node": 2909, "naklon": 0 }, +{ "label": "21/28", "node": 2920, "naklon": 0 }, +{ "label": "21/29", "node": 2916, "naklon": 0 }, +{ "label": "21/30", "node": 2904, "naklon": 0 }, +{ "label": "21/31", "node": 2915, "naklon": 0 }, +{ "label": "21/32", "node": 2905, "naklon": 0 }, +{ "label": "21/33", "node": 2900, "naklon": 0 }, +{ "label": "21/34", "node": 2899, "naklon": 0 }, +{ "label": "21/36", "node": 2741, "naklon": 0 }, +{ "label": "21/37", "node": 2714, "naklon": 0 }, +{ "label": "21/38", "node": 2701, "naklon": 0 }, +{ "label": "21/39", "node": 2703, "naklon": 0 }, +{ "label": "21/40", "node": 2704, "naklon": 0 }, +{ "label": "21/41", "node": 2702, "naklon": 0 }, +{ "label": "21/42", "node": 2706, "naklon": 0 }, +{ "label": "21/43", "node": 2776, "naklon": 0 }, +{ "label": "21/44", "node": 2770, "naklon": 0 }, +{ "label": "21/45", "node": 2786, "naklon": 0 }, +{ "label": "21/46", "node": 2779, "naklon": 0 }, +{ "label": "21/47", "node": 2782, "naklon": 0 }, +{ "label": "21/48", "node": 2785, "naklon": 0 }, +{ "label": "21/49", "node": 2769, "naklon": 0 }, +{ "label": "21/50", "node": 3354, "naklon": 0 }, +{ "label": "21/51", "node": 2778, "naklon": 0 }, +{ "label": "21/52", "node": 2775, "naklon": 0 }, +{ "label": "21/53", "node": 2780, "naklon": 0 }, +{ "label": "21/54", "node": 2790, "naklon": 0 }, +{ "label": "21/55", "node": 2792, "naklon": 0 }, +{ "label": "21/56", "node": 2774, "naklon": 0 }, +{ "label": "22/1", "node": 2630, "naklon": 0 }, +{ "label": "22/2", "node": 2631, "naklon": 0 }, +{ "label": "22/3", "node": 2632, "naklon": 0 }, +{ "label": "22/4", "node": 2633, "naklon": 0 }, +{ "label": "22/5", "node": 2634, "naklon": 0 }, +{ "label": "22/6", "node": 2636, "naklon": 0 }, +{ "label": "22/7", "node": 4367, "naklon": 0 }, +{ "label": "22/8", "node": 2637, "naklon": 0 }, +{ "label": "22/9", "node": 2638, "naklon": 0 }, +{ "label": "22/10", "node": 2639, "naklon": 0 }, +{ "label": "22/11", "node": 2640, "naklon": 0 }, +{ "label": "22/12", "node": 2641, "naklon": 0 }, +{ "label": "22/13", "node": 2642, "naklon": 0 }, +{ "label": "22/14", "node": 2643, "naklon": 0 }, +{ "label": "22/15", "node": 2644, "naklon": 0 }, +{ "label": "22/16", "node": 2645, "naklon": 0 }, +{ "label": "22/17", "node": 2646, "naklon": 0 }, +{ "label": "22/18", "node": 2647, "naklon": 0 }, +{ "label": "22/19", "node": 2648, "naklon": 0 }, +{ "label": "22/20", "node": 2649, "naklon": 0 }, +{ "label": "22/21", "node": 2650, "naklon": 0 }, +{ "label": "22/22", "node": 2651, "naklon": 0 }, +{ "label": "22/23", "node": 4103, "naklon": 0 }, +{ "label": "22/24", "node": 2653, "naklon": 0 }, +{ "label": "22/25", "node": 2654, "naklon": 0 }, +{ "label": "22/26", "node": 2655, "naklon": 0 }, +{ "label": "22/27", "node": 2656, "naklon": 0 }, +{ "label": "22/28", "node": 2657, "naklon": 0 }, +{ "label": "22/29", "node": 2658, "naklon": 0 }, +{ "label": "22/30", "node": 2659, "naklon": 0 }, +{ "label": "22/31", "node": 2660, "naklon": 0 }, +{ "label": "22/32", "node": 2661, "naklon": 0 }, +{ "label": "22/32/1", "node": 3015, "naklon": 0 }, +{ "label": "22/33", "node": 2662, "naklon": 0 }, +{ "label": "22/34", "node": 2663, "naklon": 0 }, +{ "label": "22/35", "node": 2664, "naklon": 0 }, +{ "label": "22/36", "node": 2665, "naklon": 0 }, +{ "label": "22/37", "node": 2666, "naklon": 0 }, +{ "label": "22/38", "node": 2667, "naklon": 0 }, +{ "label": "22/39", "node": 2668, "naklon": 0 }, +{ "label": "22/40", "node": 2669, "naklon": null }, +{ "label": "22/41", "node": 2670, "naklon": null }, +{ "label": "22/42", "node": 2671, "naklon": null }, +{ "label": "23/9A", "node": 3087, "naklon": 10 }, +{ "label": "23/9B", "node": 3090, "naklon": 10 }, +{ "label": "23/1", "node": 3075, "naklon": 0 }, +{ "label": "23/2", "node": 3089, "naklon": 0 }, +{ "label": "23/3", "node": 3088, "naklon": 0 }, +{ "label": "23/4", "node": 3228, "naklon": 10 }, +{ "label": "23/5", "node": 2751, "naklon": 10 }, +{ "label": "23/6", "node": 3243, "naklon": 10 }, +{ "label": "23/7", "node": 4349, "naklon": 10 }, +{ "label": "23/8", "node": 3102, "naklon": 10 }, +{ "label": "23/10", "node": 3099, "naklon": 10 }, +{ "label": "23/11", "node": 3103, "naklon": 10 }, +{ "label": "23/12", "node": 3093, "naklon": 10 }, +{ "label": "23/13", "node": 3098, "naklon": 10 }, +{ "label": "23/14", "node": 3092, "naklon": 10 }, +{ "label": "23/15", "node": 3233, "naklon": 0 }, +{ "label": "23/16", "node": 3095, "naklon": 0 }, +{ "label": "23/17", "node": 4074, "naklon": 0 }, +{ "label": "23/18", "node": 2729, "naklon": 0 }, +{ "label": "23/19", "node": 3234, "naklon": 0 }, +{ "label": "23/20", "node": 3094, "naklon": 0 }, +{ "label": "23/21", "node": 2817, "naklon": 0 }, +{ "label": "23/22", "node": 3226, "naklon": 0 }, +{ "label": "23/23", "node": 3225, "naklon": 0 }, +{ "label": "23/24", "node": 3237, "naklon": 0 }, +{ "label": "23/25", "node": 4250, "naklon": 0 }, +{ "label": "23/26", "node": 3059, "naklon": 10 }, +{ "label": "23/27", "node": 3238, "naklon": 10 }, +{ "label": "23/28", "node": 3242, "naklon": 10 }, +{ "label": "23/29", "node": 3236, "naklon": 10 }, +{ "label": "23/30", "node": 3112, "naklon": 10 }, +{ "label": "23/31", "node": 3224, "naklon": 0 }, +{ "label": "23/32", "node": 4298, "naklon": 10 }, +{ "label": "23/33", "node": 4150, "naklon": 10 }, +{ "label": "23/34", "node": 3091, "naklon": 10 }, +{ "label": "25/1", "node": 3771, "naklon": 5 }, +{ "label": "25/2", "node": 3777, "naklon": 5 }, +{ "label": "25/3", "node": 3749, "naklon": 5 }, +{ "label": "25/4", "node": 3769, "naklon": 5 }, +{ "label": "25/5", "node": 3765, "naklon": 5 }, +{ "label": "25/6", "node": 3785, "naklon": 5 }, +{ "label": "25/7", "node": 3761, "naklon": 5 }, +{ "label": "25/8", "node": 3758, "naklon": 5 }, +{ "label": "25/9", "node": 3766, "naklon": 5 }, +{ "label": "25/10", "node": 3779, "naklon": 5 }, +{ "label": "25/11", "node": 3899, "naklon": 10 }, +{ "label": "25/12", "node": 3922, "naklon": 10 }, +{ "label": "25/13", "node": 3912, "naklon": 10 }, +{ "label": "25/14", "node": 3933, "naklon": 10 }, +{ "label": "25/15", "node": 3921, "naklon": 10 }, +{ "label": "25/16", "node": 4300, "naklon": 10 }, +{ "label": "25/17", "node": 3927, "naklon": 10 }, +{ "label": "25/18", "node": 3212, "naklon": 10 }, +{ "label": "25/19", "node": 3208, "naklon": 10 }, +{ "label": "25/20", "node": 3207, "naklon": 10 }, +{ "label": "25/21", "node": 4294, "naklon": 10 }, +{ "label": "25/22", "node": 3209, "naklon": 10 }, +{ "label": "25/23", "node": 3745, "naklon": 10 }, +{ "label": "25/24", "node": 3762, "naklon": 10 }, +{ "label": "25/25", "node": 3215, "naklon": 10 }, +{ "label": "25/26", "node": 3210, "naklon": 10 }, +{ "label": "25/27", "node": 3211, "naklon": 10 }, +{ "label": "25/28", "node": 3206, "naklon": 10 }, +{ "label": "25/29", "node": 3918, "naklon": 5 }, +{ "label": "25/30", "node": 3928, "naklon": 5 }, +{ "label": "25/31", "node": 3917, "naklon": 5 }, +{ "label": "25/32", "node": 4029, "naklon": 0 }, +{ "label": "25/33", "node": 4038, "naklon": 0 }, +{ "label": "25/34", "node": 4022, "naklon": 0 }, +{ "label": "25/35", "node": 3937, "naklon": 0 }, +{ "label": "25/36", "node": 3190, "naklon": 0 }, +{ "label": "25/37", "node": 3835, "naklon": 0 }, +{ "label": "25/38", "node": 3201, "naklon": 0 }, +{ "label": "25/39", "node": 3193, "naklon": 0 }, +{ "label": "25/40", "node": 3191, "naklon": 0 }, +{ "label": "25/41", "node": 3203, "naklon": 0 }, +{ "label": "25/42", "node": 4301, "naklon": 0 }, +{ "label": "25/43", "node": 3223, "naklon": 0 }, +{ "label": "25/44", "node": 3202, "naklon": 0 }, +{ "label": "25/45", "node": 3205, "naklon": 0 }, +{ "label": "25/46", "node": 3194, "naklon": 0 }, +{ "label": "25/47", "node": 3198, "naklon": 0 }, +{ "label": "25/48", "node": 3204, "naklon": 0 }, +{ "label": "25/49", "node": 3200, "naklon": 0 }, +{ "label": "25/50", "node": 3216, "naklon": 0 }, +{ "label": "25/51", "node": 3932, "naklon": 5 }, +{ "label": "25/52", "node": 3923, "naklon": 5 }, +{ "label": "25/53", "node": 3913, "naklon": 5 }, +{ "label": "25/54", "node": 3900, "naklon": 5 }, +{ "label": "25/55", "node": 4189, "naklon": 10 }, +{ "label": "25/56", "node": 4191, "naklon": 10 }, +{ "label": "25/57", "node": 3790, "naklon": 10 }, +{ "label": "25/58", "node": 4190, "naklon": 10 }, +{ "label": "25/59", "node": 4302, "naklon": 0 }, +{ "label": "25/60", "node": 4351, "naklon": 0 }, +{ "label": "25/61", "node": 4075, "naklon": 0 }, +{ "label": "25/62", "node": 4071, "naklon": 0 }, +{ "label": "25/63", "node": 3784, "naklon": 0 }, +{ "label": "25/64", "node": 4065, "naklon": 0 }, +{ "label": "25/65", "node": 4297, "naklon": 0 }, +{ "label": "25/66", "node": 4295, "naklon": 0 }, +{ "label": "25/67", "node": 4299, "naklon": 0 }, +{ "label": "25/68", "node": 3772, "naklon": 0 }, +{ "label": "25/69", "node": 3941, "naklon": 0 }, +{ "label": "25/70", "node": 3782, "naklon": 0 }, +{ "label": "25/71", "node": 4068, "naklon": 0 }, +{ "label": "25/72", "node": 4073, "naklon": 0 }, +{ "label": "25/73", "node": 3901, "naklon": 5 }, +{ "label": "25/74", "node": 4296, "naklon": 5 }, +{ "label": "25/75", "node": 3910, "naklon": 5 }, +{ "label": "25/76", "node": 4293, "naklon": 5 }, +{ "label": "25/77", "node": 3919, "naklon": 5 }, +{ "label": "25/78", "node": 3924, "naklon": 5 }, +{ "label": "25/79", "node": 3909, "naklon": 5 }, +{ "label": "25/80", "node": 3896, "naklon": 5 }, +{ "label": "25/81", "node": 3911, "naklon": 5 }, +{ "label": "25/82", "node": 2819, "naklon": 15 }, +{ "label": "25/83", "node": 3776, "naklon": 15 }, +{ "label": "25/84", "node": 3752, "naklon": 15 }, +{ "label": "25/85", "node": 4353, "naklon": 15 }, +{ "label": "25/86", "node": 3791, "naklon": 0 }, +{ "label": "25/87", "node": 3770, "naklon": 0 }, +{ "label": "25/88", "node": 3760, "naklon": 0 }, +{ "label": "25/89", "node": 3115, "naklon": 0 }, +{ "label": "25/90", "node": 3738, "naklon": 0 }, +{ "label": "25/91", "node": 3748, "naklon": 0 }, +{ "label": "25/92", "node": 3753, "naklon": 0 }, +{ "label": "25/93", "node": 3775, "naklon": 0 }, +{ "label": "25/94", "node": 3778, "naklon": 5 }, +{ "label": "25/95", "node": 4078, "naklon": 5 }, +{ "label": "25/96", "node": 4088, "naklon": 5 }, +{ "label": "25/97", "node": 3856, "naklon": 5 }, +{ "label": "25/98", "node": 4084, "naklon": 5 }, +{ "label": "25/99", "node": 4069, "naklon": 5 }, +{ "label": "25/100", "node": 4188, "naklon": 5 }, +{ "label": "25/101", "node": 4064, "naklon": 5 }, +{ "label": "25/102", "node": 3792, "naklon": 5 }, +{ "label": "25/103", "node": 3780, "naklon": 5 }, +{ "label": "25/104", "node": 4034, "naklon": 5 }, +{ "label": "25/105", "node": 4072, "naklon": 5 }, +{ "label": "25/106", "node": 3884, "naklon": 5 }, +{ "label": "25/107", "node": 3793, "naklon": 5 }, +{ "label": "25/108", "node": 3863, "naklon": 5 }, +{ "label": "25/109", "node": 3855, "naklon": 5 }, +{ "label": "33/1", "node": 3846, "naklon": 0 }, +{ "label": "33/2", "node": 3943, "naklon": 0 }, +{ "label": "33/3", "node": 3903, "naklon": 0 }, +{ "label": "33/4", "node": 3982, "naklon": 0 }, +{ "label": "33/5", "node": 3879, "naklon": 0 }, +{ "label": "33/6", "node": 3887, "naklon": 0 }, +{ "label": "33/7", "node": 3920, "naklon": 5 }, +{ "label": "33/8", "node": 3942, "naklon": 5 }, +{ "label": "33/9", "node": 3829, "naklon": null }, +{ "label": "34/79A", "node": 3452, "naklon": 6 }, +{ "label": "34/79B", "node": 3460, "naklon": 6 }, +{ "label": "34/90A", "node": 3443, "naklon": 6 }, +{ "label": "34/90B", "node": 3445, "naklon": 6 }, +{ "label": "34/90C", "node": 3457, "naklon": 6 }, +{ "label": "34/97A", "node": 3461, "naklon": 6 }, +{ "label": "34/97B", "node": 3463, "naklon": 6 }, +{ "label": "34/98A", "node": 3426, "naklon": 6 }, +{ "label": "34/98B", "node": 3444, "naklon": 6 }, +{ "label": "34/99A", "node": 3453, "naklon": 6 }, +{ "label": "34/99B", "node": 3455, "naklon": 6 }, +{ "label": "34/1", "node": 4009, "naklon": 0 }, +{ "label": "34/2", "node": 3602, "naklon": 0 }, +{ "label": "34/3", "node": 3441, "naklon": 0 }, +{ "label": "34/4", "node": 3464, "naklon": 0 }, +{ "label": "34/5", "node": 3883, "naklon": 0 }, +{ "label": "34/6", "node": 4098, "naklon": 0 }, +{ "label": "34/7", "node": 4003, "naklon": 0 }, +{ "label": "34/8", "node": 4004, "naklon": 0 }, +{ "label": "34/9", "node": 3888, "naklon": 0 }, +{ "label": "34/10", "node": 3997, "naklon": 0 }, +{ "label": "34/11", "node": 4006, "naklon": 0 }, +{ "label": "34/12", "node": 4000, "naklon": 0 }, +{ "label": "34/13", "node": 4011, "naklon": 0 }, +{ "label": "34/14", "node": 3999, "naklon": 0 }, +{ "label": "34/15", "node": 3981, "naklon": 0 }, +{ "label": "34/16", "node": 3988, "naklon": 0 }, +{ "label": "34/17", "node": 3986, "naklon": 0 }, +{ "label": "34/18", "node": 3998, "naklon": 0 }, +{ "label": "34/19", "node": 3983, "naklon": 0 }, +{ "label": "34/20", "node": 4005, "naklon": 0 }, +{ "label": "34/21", "node": 4001, "naklon": 0 }, +{ "label": "34/22", "node": 4008, "naklon": 0 }, +{ "label": "34/23", "node": 4002, "naklon": 0 }, +{ "label": "34/24", "node": 3996, "naklon": 0 }, +{ "label": "34/25", "node": 4007, "naklon": 0 }, +{ "label": "34/26", "node": 4113, "naklon": 15 }, +{ "label": "34/27", "node": 3595, "naklon": 5 }, +{ "label": "34/28", "node": 3599, "naklon": 5 }, +{ "label": "34/29", "node": 3601, "naklon": 5 }, +{ "label": "34/30", "node": 4205, "naklon": 0 }, +{ "label": "34/31", "node": 3987, "naklon": null }, +{ "label": "34/32", "node": 4214, "naklon": 0 }, +{ "label": "34/33", "node": 4226, "naklon": 0 }, +{ "label": "34/34", "node": 4209, "naklon": 0 }, +{ "label": "34/35", "node": 4201, "naklon": 0 }, +{ "label": "34/36", "node": 3440, "naklon": 0 }, +{ "label": "34/37", "node": 3465, "naklon": 0 }, +{ "label": "34/38", "node": 3446, "naklon": 0 }, +{ "label": "34/39", "node": 4039, "naklon": 5 }, +{ "label": "34/40", "node": 4057, "naklon": 5 }, +{ "label": "34/41", "node": 3985, "naklon": 0 }, +{ "label": "34/42", "node": 3882, "naklon": 0 }, +{ "label": "34/43", "node": 4040, "naklon": 5 }, +{ "label": "34/44", "node": 3231, "naklon": 0 }, +{ "label": "34/45", "node": 3227, "naklon": 0 }, +{ "label": "34/46", "node": 3431, "naklon": 0 }, +{ "label": "34/47", "node": 4013, "naklon": 0 }, +{ "label": "34/48", "node": 4045, "naklon": 0 }, +{ "label": "34/49", "node": 3949, "naklon": 0 }, +{ "label": "34/50", "node": 3953, "naklon": 0 }, +{ "label": "34/51", "node": 3952, "naklon": 0 }, +{ "label": "34/52", "node": 3995, "naklon": 0 }, +{ "label": "34/53", "node": 3992, "naklon": 0 }, +{ "label": "34/54", "node": 4198, "naklon": 0 }, +{ "label": "34/55", "node": 3935, "naklon": 0 }, +{ "label": "34/56", "node": 4050, "naklon": 0 }, +{ "label": "34/57", "node": 4049, "naklon": 0 }, +{ "label": "34/58", "node": 4054, "naklon": 0 }, +{ "label": "34/59", "node": 3663, "naklon": 6 }, +{ "label": "34/60", "node": 3661, "naklon": 6 }, +{ "label": "34/61", "node": 3664, "naklon": 6 }, +{ "label": "34/62", "node": 3660, "naklon": 6 }, +{ "label": "34/63", "node": 3662, "naklon": 6 }, +{ "label": "34/65", "node": 3665, "naklon": 6 }, +{ "label": "34/66", "node": 3667, "naklon": 6 }, +{ "label": "34/67", "node": 3675, "naklon": 6 }, +{ "label": "34/68", "node": 3666, "naklon": 6 }, +{ "label": "34/69", "node": 3652, "naklon": 6 }, +{ "label": "34/70", "node": 3458, "naklon": 6 }, +{ "label": "34/70/1", "node": 4425, "naklon": 6 }, +{ "label": "34/71", "node": 3459, "naklon": 6 }, +{ "label": "34/72", "node": 3435, "naklon": 6 }, +{ "label": "34/73", "node": 3448, "naklon": 6 }, +{ "label": "34/74", "node": 3451, "naklon": 6 }, +{ "label": "34/75", "node": 3442, "naklon": 6 }, +{ "label": "34/76", "node": 3449, "naklon": 6 }, +{ "label": "34/77", "node": 3450, "naklon": 6 }, +{ "label": "34/78", "node": 3433, "naklon": 6 }, +{ "label": "34/80", "node": 3432, "naklon": 12 }, +{ "label": "34/81", "node": 3470, "naklon": 12 }, +{ "label": "34/82", "node": 3438, "naklon": 12 }, +{ "label": "34/83", "node": 3439, "naklon": 12 }, +{ "label": "34/84", "node": 4028, "naklon": 5 }, +{ "label": "34/85", "node": 3596, "naklon": 5 }, +{ "label": "34/86", "node": 4021, "naklon": 5 }, +{ "label": "34/87", "node": 3437, "naklon": 12 }, +{ "label": "34/88", "node": 3428, "naklon": 12 }, +{ "label": "34/89", "node": 3430, "naklon": 12 }, +{ "label": "34/91", "node": 3454, "naklon": 6 }, +{ "label": "34/92", "node": 3492, "naklon": 6 }, +{ "label": "34/93", "node": 3462, "naklon": 6 }, +{ "label": "34/94", "node": 3427, "naklon": 6 }, +{ "label": "34/95", "node": 3434, "naklon": 6 }, +{ "label": "34/96", "node": 3456, "naklon": 6 }, +{ "label": "34/98/1", "node": 4307, "naklon": 6 }, +{ "label": "35/1", "node": 3968, "naklon": 0 }, +{ "label": "35/2", "node": 3969, "naklon": 0 }, +{ "label": "35/3", "node": 3947, "naklon": 0 }, +{ "label": "35/4", "node": 3979, "naklon": 0 }, +{ "label": "35/5", "node": 3959, "naklon": 0 }, +{ "label": "35/6", "node": 3948, "naklon": 0 }, +{ "label": "35/7", "node": 3961, "naklon": 0 }, +{ "label": "35/8", "node": 3956, "naklon": 0 }, +{ "label": "35/9", "node": 3604, "naklon": 0 }, +{ "label": "35/10", "node": 3944, "naklon": 0 }, +{ "label": "35/11", "node": 3960, "naklon": 0 }, +{ "label": "35/12", "node": 3958, "naklon": 0 }, +{ "label": "35/13", "node": 4036, "naklon": 5 }, +{ "label": "35/18", "node": 3893, "naklon": 5 }, +{ "label": "35/19", "node": 4108, "naklon": 5 }, +{ "label": "35/20", "node": 4017, "naklon": 5 }, +{ "label": "35/21", "node": 3963, "naklon": 0 }, +{ "label": "35/22", "node": 3658, "naklon": 0 }, +{ "label": "35/23", "node": 3975, "naklon": 0 }, +{ "label": "35/24", "node": 3980, "naklon": 0 }, +{ "label": "35/25", "node": 4012, "naklon": 0 }, +{ "label": "35/26", "node": 3655, "naklon": 0 }, +{ "label": "35/27", "node": 3962, "naklon": 0 }, +{ "label": "35/28", "node": 3945, "naklon": 0 }, +{ "label": "35/29", "node": 3569, "naklon": 0 }, +{ "label": "35/30", "node": 3429, "naklon": 0 }, +{ "label": "35/31", "node": 3657, "naklon": 0 }, +{ "label": "35/32", "node": 3646, "naklon": 0 }, +{ "label": "35/33", "node": 3622, "naklon": 0 }, +{ "label": "35/34", "node": 3612, "naklon": 0 }, +{ "label": "35/35", "node": 3955, "naklon": 0 }, +{ "label": "35/37", "node": 3878, "naklon": 0 }, +{ "label": "35/38", "node": 3965, "naklon": 0 }, +{ "label": "35/39", "node": 3970, "naklon": 0 }, +{ "label": "35/40", "node": 3611, "naklon": 0 }, +{ "label": "35/41", "node": 2635, "naklon": 0 }, +{ "label": "35/42", "node": 3978, "naklon": 0 }, +{ "label": "35/43", "node": 4213, "naklon": 0 }, +{ "label": "35/44", "node": 3984, "naklon": 0 }, +{ "label": "35/45", "node": 4218, "naklon": 0 }, +{ "label": "35/46", "node": 3973, "naklon": 0 }, +{ "label": "35/47", "node": 3974, "naklon": 0 }, +{ "label": "35/48", "node": 3759, "naklon": 0 }, +{ "label": "35/49", "node": 3844, "naklon": 0 }, +{ "label": "35/50", "node": 3804, "naklon": 0 }, +{ "label": "35/51", "node": 3831, "naklon": 0 }, +{ "label": "35/52", "node": 3643, "naklon": 0 }, +{ "label": "35/53", "node": 3966, "naklon": 0 }, +{ "label": "35/54", "node": 3971, "naklon": 0 }, +{ "label": "35/55", "node": 3650, "naklon": 6 }, +{ "label": "35/56", "node": 3651, "naklon": 6 }, +{ "label": "35/57", "node": 3669, "naklon": 6 }, +{ "label": "35/58", "node": 3648, "naklon": 6 }, +{ "label": "35/59", "node": 3645, "naklon": 6 }, +{ "label": "35/60", "node": 3659, "naklon": 6 }, +{ "label": "35/61", "node": 3647, "naklon": 6 }, +{ "label": "35/62", "node": 3644, "naklon": 6 }, +{ "label": "35/63", "node": 3671, "naklon": 6 }, +{ "label": "35/64", "node": 3682, "naklon": 6 }, +{ "label": "35/65", "node": 3672, "naklon": 6 }, +{ "label": "35/66", "node": 3683, "naklon": 6 }, +{ "label": "35/67", "node": 3673, "naklon": 6 }, +{ "label": "35/68", "node": 3674, "naklon": 6 }, +{ "label": "35/69", "node": 3679, "naklon": 6 }, +{ "label": "35/70", "node": 3649, "naklon": 6 }, +{ "label": "35/71", "node": 3687, "naklon": 6 }, +{ "label": "35/72", "node": 3677, "naklon": 6 }, +{ "label": "35/73", "node": 3690, "naklon": 6 }, +{ "label": "35/74", "node": 3691, "naklon": 6 }, +{ "label": "35/75", "node": 3676, "naklon": 6 }, +{ "label": "35/76", "node": 3680, "naklon": 6 }, +{ "label": "35/77", "node": 3668, "naklon": 6 }, +{ "label": "35/78", "node": 3681, "naklon": 6 }, +{ "label": "35/79", "node": 3670, "naklon": 6 }, +{ "label": "35/80", "node": 3689, "naklon": 6 }, +{ "label": "35/81", "node": 3678, "naklon": 6 }, +{ "label": "35/82", "node": 3693, "naklon": 6 }, +{ "label": "35/83", "node": 3654, "naklon": null }, +{ "label": "36/1", "node": 4086, "naklon": 0 }, +{ "label": "36/2", "node": 4085, "naklon": 0 }, +{ "label": "36/3", "node": 4083, "naklon": 0 }, +{ "label": "36/4", "node": 4087, "naklon": 0 }, +{ "label": "36/5", "node": 4077, "naklon": 0 }, +{ "label": "36/6", "node": 4082, "naklon": 0 }, +{ "label": "36/7", "node": 4186, "naklon": 0 }, +{ "label": "36/8", "node": 4206, "naklon": 0 }, +{ "label": "36/9", "node": 4080, "naklon": 0 }, +{ "label": "36/10", "node": 4081, "naklon": 0 }, +{ "label": "36/11", "node": 4210, "naklon": 0 }, +{ "label": "36/12", "node": 4079, "naklon": 0 }, +{ "label": "36/13", "node": 4076, "naklon": 0 }, +{ "label": "36/14", "node": 3852, "naklon": 0 }, +{ "label": "36/15", "node": 2813, "naklon": 0 }, +{ "label": "36/16", "node": 4219, "naklon": 0 }, +{ "label": "37/1A", "node": 3104, "naklon": 15 }, +{ "label": "37/1B", "node": 3121, "naklon": 15 }, +{ "label": "37/2", "node": 3113, "naklon": 10 }, +{ "label": "37/3", "node": 3118, "naklon": 10 }, +{ "label": "37/4", "node": 3111, "naklon": 10 }, +{ "label": "37/5", "node": 4020, "naklon": 10 }, +{ "label": "37/6", "node": 3119, "naklon": 10 }, +{ "label": "37/7", "node": 3110, "naklon": 10 }, +{ "label": "37/8", "node": 3108, "naklon": 10 }, +{ "label": "37/12", "node": 3107, "naklon": 0 }, +{ "label": "37/13", "node": 3199, "naklon": 0 }, +{ "label": "37/14", "node": 3120, "naklon": 0 }, +{ "label": "37/15", "node": 3122, "naklon": 0 }, +{ "label": "37/16", "node": 3908, "naklon": 0 }, +{ "label": "37/17", "node": 3114, "naklon": 0 }, +{ "label": "37/18", "node": 3105, "naklon": 0 }, +{ "label": "37/19", "node": 3116, "naklon": 0 }, +{ "label": "37/20", "node": 3106, "naklon": 0 }, +{ "label": "37/21", "node": 2887, "naklon": 5 }, +{ "label": "37/22", "node": 2888, "naklon": 5 }, +{ "label": "37/23", "node": 2877, "naklon": 5 }, +{ "label": "37/24", "node": 2891, "naklon": 5 }, +{ "label": "37/25", "node": 2886, "naklon": 5 }, +{ "label": "37/26", "node": 2892, "naklon": 5 }, +{ "label": "37/27", "node": 2882, "naklon": 5 }, +{ "label": "37/28", "node": 2883, "naklon": 5 }, +{ "label": "37/29", "node": 2876, "naklon": 5 }, +{ "label": "37/30", "node": 3109, "naklon": 5 }, +{ "label": "37/31", "node": 4152, "naklon": 5 }, +{ "label": "37/32", "node": 3117, "naklon": 5 }, +{ "label": "37/33", "node": 2870, "naklon": 5 }, +{ "label": "37/34", "node": 2867, "naklon": 0 }, +{ "label": "37/35", "node": 2865, "naklon": 0 }, +{ "label": "37/36", "node": 3096, "naklon": 0 }, +{ "label": "37/37", "node": 2871, "naklon": 0 }, +{ "label": "37/38", "node": 2884, "naklon": 0 }, +{ "label": "37/39", "node": 2855, "naklon": 0 }, +{ "label": "37/40", "node": 2878, "naklon": 0 }, +{ "label": "37/41", "node": 2889, "naklon": 0 }, +{ "label": "37/42", "node": 2879, "naklon": 0 }, +{ "label": "37/43", "node": 2850, "naklon": 0 }, +{ "label": "37/44", "node": 2894, "naklon": 0 }, +{ "label": "37/45", "node": 2880, "naklon": 0 }, +{ "label": "37/46", "node": 2893, "naklon": 0 }, +{ "label": "37/47", "node": 2890, "naklon": 0 }, +{ "label": "37/48", "node": 4355, "naklon": 0 }, +{ "label": "37/49", "node": 2885, "naklon": 0 }, +{ "label": "37/50", "node": 2875, "naklon": 0 }, +{ "label": "38/30A", "node": 3486, "naklon": 5 }, +{ "label": "38/30B", "node": 3714, "naklon": 0 }, +{ "label": "38/32A", "node": 3483, "naklon": 5 }, +{ "label": "38/32B", "node": 3496, "naklon": 0 }, +{ "label": "38/35A", "node": 3487, "naklon": 5 }, +{ "label": "38/35B", "node": 3498, "naklon": 5 }, +{ "label": "38/38A", "node": 3578, "naklon": 5 }, +{ "label": "38/38B", "node": 3508, "naklon": 5 }, +{ "label": "38/59A", "node": 3787, "naklon": 5 }, +{ "label": "38/59B", "node": 3491, "naklon": 5 }, +{ "label": "38/1", "node": 3568, "naklon": null }, +{ "label": "38/2", "node": 3502, "naklon": 0 }, +{ "label": "38/3", "node": 3836, "naklon": 0 }, +{ "label": "38/4", "node": 3588, "naklon": 0 }, +{ "label": "38/5", "node": 3493, "naklon": 0 }, +{ "label": "38/6", "node": 3580, "naklon": 0 }, +{ "label": "38/7", "node": 3572, "naklon": 0 }, +{ "label": "38/8", "node": 3506, "naklon": 0 }, +{ "label": "38/9", "node": 3503, "naklon": 0 }, +{ "label": "38/10", "node": 3579, "naklon": 0 }, +{ "label": "38/11", "node": 3586, "naklon": 0 }, +{ "label": "38/12", "node": 3495, "naklon": 5 }, +{ "label": "38/13", "node": 3492, "naklon": 5 }, +{ "label": "38/14", "node": 3532, "naklon": 5 }, +{ "label": "38/15", "node": 3574, "naklon": 5 }, +{ "label": "38/16", "node": 4140, "naklon": 5 }, +{ "label": "38/17", "node": 3795, "naklon": 5 }, +{ "label": "38/18", "node": 3788, "naklon": 5 }, +{ "label": "38/19", "node": 3796, "naklon": 5 }, +{ "label": "38/20", "node": 3797, "naklon": 5 }, +{ "label": "38/21", "node": 3798, "naklon": 5 }, +{ "label": "38/22", "node": 3786, "naklon": 5 }, +{ "label": "38/23", "node": 4067, "naklon": 5 }, +{ "label": "38/24", "node": 3773, "naklon": 5 }, +{ "label": "38/25", "node": 3774, "naklon": 5 }, +{ "label": "38/26", "node": 3789, "naklon": 5 }, +{ "label": "38/27", "node": 3520, "naklon": null }, +{ "label": "38/29", "node": 3577, "naklon": 5 }, +{ "label": "38/31", "node": 3530, "naklon": null }, +{ "label": "38/33", "node": 3488, "naklon": 5 }, +{ "label": "38/34", "node": 3505, "naklon": 5 }, +{ "label": "38/36", "node": 3497, "naklon": 5 }, +{ "label": "38/37", "node": 3490, "naklon": 5 }, +{ "label": "38/39", "node": 3585, "naklon": 5 }, +{ "label": "38/40", "node": 3582, "naklon": 5 }, +{ "label": "38/41", "node": 3507, "naklon": 5 }, +{ "label": "38/42", "node": 3484, "naklon": 5 }, +{ "label": "38/43", "node": 3501, "naklon": 5 }, +{ "label": "38/44", "node": 3581, "naklon": 5 }, +{ "label": "38/45", "node": 4192, "naklon": 5 }, +{ "label": "38/46", "node": 3576, "naklon": 5 }, +{ "label": "38/47", "node": 3489, "naklon": 5 }, +{ "label": "38/48", "node": 3573, "naklon": 5 }, +{ "label": "38/49", "node": 3504, "naklon": 5 }, +{ "label": "38/50", "node": 3794, "naklon": 5 }, +{ "label": "38/51", "node": 3485, "naklon": 5 }, +{ "label": "38/52", "node": 3482, "naklon": 5 }, +{ "label": "38/53", "node": 3575, "naklon": 5 }, +{ "label": "38/54", "node": 3499, "naklon": 5 }, +{ "label": "38/55", "node": 3494, "naklon": 5 }, +{ "label": "38/56", "node": 3583, "naklon": 5 }, +{ "label": "38/57", "node": 3570, "naklon": 5 }, +{ "label": "38/58", "node": 3500, "naklon": 0 }, +{ "label": "38/63", "node": 3510, "naklon": null }, +{ "label": "38/64", "node": 3512, "naklon": null }, +{ "label": "38/67", "node": 3535, "naklon": null }, +{ "label": "38/68", "node": 3531, "naklon": null }, +{ "label": "38/69", "node": 3537, "naklon": null }, +{ "label": "39/1", "node": 3522, "naklon": 10 }, +{ "label": "39/2", "node": 4018, "naklon": 10 }, +{ "label": "39/3", "node": 4019, "naklon": 10 }, +{ "label": "39/4", "node": 4154, "naklon": 5 }, +{ "label": "39/5", "node": 3907, "naklon": 5 }, +{ "label": "39/6", "node": 4148, "naklon": 0 }, +{ "label": "39/7", "node": 4153, "naklon": 0 }, +{ "label": "39/8", "node": 3938, "naklon": 0 }, +{ "label": "39/9", "node": 3802, "naklon": 0 }, +{ "label": "39/10", "node": 4015, "naklon": 0 }, +{ "label": "39/11", "node": 3929, "naklon": 0 }, +{ "label": "39/12", "node": 3946, "naklon": 0 }, +{ "label": "39/13", "node": 4014, "naklon": 0 }, +{ "label": "39/14", "node": 4155, "naklon": 0 }, +{ "label": "39/15", "node": 4149, "naklon": 0 }, +{ "label": "39/16", "node": 3642, "naklon": 0 }, +{ "label": "39/17", "node": 3636, "naklon": 5 }, +{ "label": "39/18", "node": 3991, "naklon": 0 }, +{ "label": "39/19", "node": 3994, "naklon": 0 }, +{ "label": "39/20", "node": 3990, "naklon": 0 }, +{ "label": "39/21", "node": 3967, "naklon": 0 }, +{ "label": "39/22", "node": 3977, "naklon": 0 }, +{ "label": "39/23", "node": 3757, "naklon": 15 }, +{ "label": "39/24", "node": 3633, "naklon": 15 }, +{ "label": "39/25", "node": 3744, "naklon": 15 }, +{ "label": "39/26", "node": 4023, "naklon": 5 }, +{ "label": "39/27", "node": 3720, "naklon": 5 }, +{ "label": "39/28", "node": 3734, "naklon": 5 }, +{ "label": "39/29", "node": 3741, "naklon": 5 }, +{ "label": "39/30", "node": 3721, "naklon": 5 }, +{ "label": "39/31", "node": 3845, "naklon": 0 }, +{ "label": "39/32", "node": 3840, "naklon": 0 }, +{ "label": "39/33", "node": 3837, "naklon": null }, +{ "label": "39/34", "node": 3839, "naklon": 0 }, +{ "label": "41/1", "node": 3542, "naklon": null }, +{ "label": "41/2", "node": 3566, "naklon": null }, +{ "label": "41/3", "node": 3548, "naklon": null }, +{ "label": "41/4", "node": 3515, "naklon": null }, +{ "label": "41/5", "node": 3559, "naklon": null }, +{ "label": "41/6", "node": 3509, "naklon": null }, +{ "label": "41/7", "node": 3524, "naklon": null }, +{ "label": "41/8", "node": 3518, "naklon": null }, +{ "label": "41/9", "node": 3182, "naklon": null }, +{ "label": "41/10", "node": 3187, "naklon": null }, +{ "label": "41/11", "node": 3195, "naklon": 0 }, +{ "label": "41/12", "node": 3857, "naklon": 0 }, +{ "label": "41/13", "node": 3183, "naklon": 0 }, +{ "label": "41/14", "node": 3177, "naklon": 0 }, +{ "label": "41/15", "node": 3189, "naklon": 0 }, +{ "label": "41/16", "node": 3186, "naklon": 0 }, +{ "label": "42/1", "node": 3178, "naklon": 0 }, +{ "label": "42/2", "node": 3219, "naklon": 0 }, +{ "label": "42/3", "node": 3475, "naklon": 0 }, +{ "label": "42/4", "node": 3175, "naklon": 0 }, +{ "label": "42/5", "node": 3222, "naklon": 0 }, +{ "label": "42/6", "node": 3221, "naklon": 0 }, +{ "label": "42/7", "node": 3181, "naklon": 0 }, +{ "label": "42/8", "node": 3180, "naklon": 0 }, +{ "label": "42/9", "node": 3218, "naklon": 0 }, +{ "label": "42/10", "node": 3176, "naklon": 0 }, +{ "label": "42/11", "node": 3174, "naklon": 0 }, +{ "label": "42/12", "node": 3220, "naklon": 0 }, +{ "label": "42/13", "node": 3533, "naklon": null }, +{ "label": "42/14", "node": 3543, "naklon": null }, +{ "label": "42/15", "node": 3554, "naklon": null }, +{ "label": "42/16", "node": 3549, "naklon": null }, +{ "label": "43/1", "node": 2857, "naklon": 5 }, +{ "label": "43/2", "node": 2752, "naklon": 5 }, +{ "label": "43/3", "node": 2753, "naklon": 5 }, +{ "label": "43/4", "node": 3024, "naklon": 5 }, +{ "label": "43/5", "node": 2754, "naklon": 5 }, +{ "label": "43/6", "node": 4423, "naklon": 5 }, +{ "label": "43/7", "node": 4368, "naklon": 5 }, +{ "label": "43/8", "node": 2978, "naklon": 5 }, +{ "label": "43/9", "node": 2868, "naklon": 5 }, +{ "label": "43/10", "node": 4377, "naklon": 5 }, +{ "label": "43/11", "node": 2757, "naklon": 5 }, +{ "label": "43/12", "node": 2970, "naklon": 5 }, +{ "label": "43/13", "node": 2758, "naklon": 5 }, +{ "label": "43/14", "node": 4378, "naklon": 5 }, +{ "label": "43/15", "node": 2759, "naklon": 5 }, +{ "label": "43/16", "node": 4342, "naklon": 5 }, +{ "label": "43/17", "node": 3026, "naklon": null }, +{ "label": "43/18", "node": 2986, "naklon": null }, +{ "label": "43/19", "node": 4343, "naklon": null }, +{ "label": "43/20", "node": 2760, "naklon": null }, +{ "label": "43/21", "node": 4379, "naklon": null }, +{ "label": "43/22", "node": 2971, "naklon": null }, +{ "label": "43/23", "node": 2761, "naklon": null }, +{ "label": "43/24", "node": 2762, "naklon": null }, +{ "label": "43/25", "node": 4339, "naklon": null }, +{ "label": "43/26", "node": 4380, "naklon": null }, +{ "label": "43/27", "node": 2975, "naklon": null }, +{ "label": "43/28", "node": 3003, "naklon": null }, +{ "label": "43/29", "node": 4338, "naklon": null }, +{ "label": "43/30", "node": 3002, "naklon": null }, +{ "label": "43/31", "node": 4345, "naklon": null }, +{ "label": "43/32", "node": 2979, "naklon": null }, +{ "label": "43/33", "node": 2989, "naklon": null }, +{ "label": "43/34", "node": 2996, "naklon": null }, +{ "label": "43/35", "node": 2972, "naklon": null }, +{ "label": "43/36", "node": 2988, "naklon": null }, +{ "label": "43/37", "node": 4344, "naklon": null }, +{ "label": "43/38", "node": 3022, "naklon": null }, +{ "label": "43/39", "node": 4341, "naklon": null }, +{ "label": "43/40", "node": 2983, "naklon": null }, +{ "label": "43/41", "node": 2995, "naklon": null }, +{ "label": "43/42", "node": 2763, "naklon": null }, +{ "label": "43/43", "node": 2764, "naklon": null }, +{ "label": "43/44", "node": 2765, "naklon": null }, +{ "label": "43/45", "node": 2766, "naklon": null }, +{ "label": "43/46", "node": 2767, "naklon": null }, +{ "label": "43/47", "node": 2768, "naklon": null }, +{ "label": "43/48", "node": 3018, "naklon": null }, +{ "label": "43/49", "node": 2982, "naklon": null }, +{ "label": "43/50", "node": 3019, "naklon": 0 }, +{ "label": "43/51", "node": 3013, "naklon": null }, +{ "label": "43/52", "node": 3007, "naklon": null }, +{ "label": "43/53", "node": 2980, "naklon": null }, +{ "label": "43/54", "node": 3011, "naklon": null }, +{ "label": "43/55", "node": 2672, "naklon": null }, +{ "label": "43/56", "node": 2673, "naklon": null }, +{ "label": "43/57", "node": 2674, "naklon": null }, +{ "label": "43/58", "node": 2675, "naklon": null }, +{ "label": "43/59", "node": 2676, "naklon": null }, +{ "label": "43/60", "node": 2677, "naklon": null }, +{ "label": "43/61", "node": 2678, "naklon": null }, +{ "label": "43/62", "node": 2679, "naklon": null }, +{ "label": "43/63", "node": 2680, "naklon": null }, +{ "label": "43/64", "node": 2840, "naklon": null }, +{ "label": "43/65", "node": 2682, "naklon": null }, +{ "label": "43/66", "node": 2683, "naklon": null }, +{ "label": "43/67", "node": 2684, "naklon": 0 }, +{ "label": "43/68", "node": 2685, "naklon": null }, +{ "label": "43/69", "node": 2686, "naklon": null }, +{ "label": "43/70", "node": 2687, "naklon": null }, +{ "label": "43/71", "node": 2688, "naklon": null }, +{ "label": "43/72", "node": 2689, "naklon": null }, +{ "label": "43/73", "node": 2690, "naklon": null }, +{ "label": "43/74", "node": 2691, "naklon": null }, +{ "label": "43/75", "node": 2692, "naklon": null }, +{ "label": "43/76", "node": 2693, "naklon": 0 }, +{ "label": "43/77", "node": 2694, "naklon": null }, +{ "label": "43/78", "node": 2695, "naklon": null }, +{ "label": "43/79", "node": 2696, "naklon": 0 }, +{ "label": "43/80", "node": 2697, "naklon": null }, +{ "label": "43/81", "node": 2698, "naklon": 0 }, +{ "label": "43/82", "node": 2699, "naklon": null }, +{ "label": "43/83", "node": 2700, "naklon": 0 }, +{ "label": "43/84", "node": 2744, "naklon": null }, +{ "label": "43/85", "node": 2745, "naklon": 0 }, +{ "label": "43/86", "node": 2746, "naklon": null }, +{ "label": "43/87", "node": 2747, "naklon": 0 }, +{ "label": "43/88", "node": 2748, "naklon": null }, +{ "label": "43/89", "node": 2749, "naklon": 0 }, +{ "label": "43/90", "node": 2841, "naklon": null }, +{ "label": "45/1", "node": 4237, "naklon": 5 }, +{ "label": "45/2", "node": 4226, "naklon": 5 }, +{ "label": "45/3", "node": 4242, "naklon": 5 }, +{ "label": "45/4", "node": 4179, "naklon": 5 }, +{ "label": "45/5", "node": 4247, "naklon": 5 }, +{ "label": "45/6", "node": 4245, "naklon": 5 }, +{ "label": "45/7", "node": 3872, "naklon": 5 }, +{ "label": "45/8", "node": 4175, "naklon": 5 }, +{ "label": "45/9", "node": 4236, "naklon": 5 }, +{ "label": "45/10", "node": 4170, "naklon": 5 }, +{ "label": "45/11", "node": 4238, "naklon": 5 }, +{ "label": "45/12", "node": 4246, "naklon": 5 }, +{ "label": "45/13", "node": 4166, "naklon": 5 }, +{ "label": "45/14", "node": 4227, "naklon": 5 }, +{ "label": "45/15", "node": 4171, "naklon": 5 }, +{ "label": "45/16", "node": 4180, "naklon": 5 }, +{ "label": "45/17", "node": 4244, "naklon": 5 }, +{ "label": "45/18", "node": 4199, "naklon": 5 }, +{ "label": "45/19", "node": 4239, "naklon": 5 }, +{ "label": "45/20", "node": 4207, "naklon": 5 }, +{ "label": "45/21", "node": 4223, "naklon": 5 }, +{ "label": "45/22", "node": 4230, "naklon": 5 }, +{ "label": "45/23", "node": 4233, "naklon": 5 }, +{ "label": "45/24", "node": 4222, "naklon": 5 }, +{ "label": "45/25", "node": 4217, "naklon": 5 }, +{ "label": "45/26", "node": 4243, "naklon": 5 }, +{ "label": "45/27", "node": 4200, "naklon": 5 }, +{ "label": "45/28", "node": 4228, "naklon": 5 }, +{ "label": "45/29", "node": 4211, "naklon": 5 }, +{ "label": "45/30", "node": 4234, "naklon": 5 }, +{ "label": "45/31", "node": 4235, "naklon": 5 }, +{ "label": "45/32", "node": 4203, "naklon": 5 }, +{ "label": "45/33", "node": 4240, "naklon": 5 }, +{ "label": "45/34", "node": 4224, "naklon": 5 }, +{ "label": "45/35", "node": 4232, "naklon": 5 }, +{ "label": "45/36", "node": 4231, "naklon": 5 }, +{ "label": "45/37", "node": 4161, "naklon": 5 }, +{ "label": "45/38", "node": 4225, "naklon": 5 }, +{ "label": "45/39", "node": 4241, "naklon": 5 }, +{ "label": "45/40", "node": 4229, "naklon": 5 }, +{ "label": "45/41", "node": 4221, "naklon": 5 }, +{ "label": "45/42", "node": 4212, "naklon": 5 }, +{ "label": "45/43", "node": 4216, "naklon": 5 }, +{ "label": "45/44", "node": 3864, "naklon": null }, +{ "label": "46/1", "node": 3806, "naklon": 5 }, +{ "label": "46/2", "node": 3813, "naklon": 5 }, +{ "label": "46/3", "node": 3815, "naklon": 5 }, +{ "label": "46/4", "node": 3807, "naklon": 5 }, +{ "label": "46/5", "node": 3895, "naklon": 5 }, +{ "label": "46/6", "node": 3809, "naklon": 5 }, +{ "label": "46/7", "node": 3820, "naklon": 5 }, +{ "label": "46/8", "node": 3805, "naklon": 5 }, +{ "label": "46/9", "node": 3894, "naklon": 0 }, +{ "label": "46/10", "node": 4055, "naklon": 0 }, +{ "label": "46/11", "node": 3812, "naklon": 5 }, +{ "label": "46/12", "node": 3822, "naklon": 5 }, +{ "label": "46/13", "node": 3821, "naklon": 5 }, +{ "label": "46/14", "node": 3808, "naklon": 5 }, +{ "label": "46/15", "node": 3799, "naklon": 5 }, +{ "label": "46/16", "node": 3816, "naklon": 5 }, +{ "label": "46/17", "node": 3751, "naklon": 5 }, +{ "label": "46/18", "node": 3814, "naklon": 5 }, +{ "label": "46/19", "node": 4044, "naklon": 0 }, +{ "label": "46/20", "node": 3931, "naklon": 0 }, +{ "label": "46/21", "node": 3902, "naklon": 5 }, +{ "label": "46/22", "node": 3916, "naklon": 5 }, +{ "label": "46/23", "node": 3892, "naklon": 5 }, +{ "label": "46/24", "node": 3914, "naklon": 5 }, +{ "label": "46/25", "node": 3898, "naklon": 5 }, +{ "label": "46/26", "node": 3897, "naklon": 5 }, +{ "label": "46/27", "node": 3885, "naklon": 5 }, +{ "label": "46/28", "node": 3906, "naklon": 5 }, +{ "label": "46/29", "node": 3930, "naklon": 0 }, +{ "label": "46/30", "node": 3936, "naklon": 0 }, +{ "label": "46/31", "node": 3860, "naklon": 5 }, +{ "label": "46/32", "node": 3841, "naklon": 5 }, +{ "label": "46/33", "node": 3873, "naklon": 5 }, +{ "label": "46/34", "node": 3854, "naklon": 5 }, +{ "label": "46/35", "node": 3939, "naklon": 5 }, +{ "label": "46/36", "node": 3858, "naklon": 5 }, +{ "label": "46/37", "node": 3940, "naklon": 5 }, +{ "label": "46/38", "node": 4035, "naklon": 5 }, +{ "label": "47/1", "node": 3373, "naklon": 0 }, +{ "label": "47/2", "node": 3374, "naklon": 0 }, +{ "label": "47/3", "node": 3384, "naklon": 0 }, +{ "label": "47/4", "node": 3385, "naklon": 0 }, +{ "label": "48/1", "node": 4051, "naklon": 5 }, +{ "label": "48/2", "node": 4041, "naklon": 5 }, +{ "label": "48/3", "node": 4056, "naklon": 5 }, +{ "label": "48/4", "node": 3875, "naklon": 5 }, +{ "label": "48/5", "node": 4061, "naklon": 5 }, +{ "label": "48/6", "node": 4047, "naklon": 5 }, +{ "label": "48/7", "node": 4060, "naklon": 5 }, +{ "label": "48/8", "node": 4059, "naklon": 5 }, +{ "label": "48/9", "node": 4058, "naklon": 5 }, +{ "label": "48/10", "node": 3635, "naklon": 5 }, +{ "label": "48/11", "node": 3640, "naklon": 5 }, +{ "label": "48/12", "node": 3747, "naklon": 5 }, +{ "label": "48/13", "node": 3629, "naklon": 5 }, +{ "label": "48/14", "node": 4048, "naklon": 5 }, +{ "label": "48/15", "node": 4063, "naklon": 5 }, +{ "label": "48/16", "node": 4062, "naklon": 5 }, +{ "label": "48/17", "node": 4043, "naklon": 5 }, +{ "label": "48/18", "node": 4052, "naklon": 5 }, +{ "label": "48/19", "node": 4042, "naklon": 5 }, +{ "label": "48/20", "node": 4053, "naklon": 5 }, +{ "label": "50/15A", "node": 4167, "naklon": null }, +{ "label": "50/15B", "node": 4159, "naklon": null }, +{ "label": "50/1", "node": 4183, "naklon": 0 }, +{ "label": "50/2", "node": 4157, "naklon": 0 }, +{ "label": "50/3", "node": 4160, "naklon": 0 }, +{ "label": "50/4", "node": 4173, "naklon": 0 }, +{ "label": "50/5", "node": 4177, "naklon": 0 }, +{ "label": "50/6", "node": 4174, "naklon": 0 }, +{ "label": "50/7", "node": 4178, "naklon": 0 }, +{ "label": "50/8", "node": 4195, "naklon": 0 }, +{ "label": "50/9", "node": 4169, "naklon": 0 }, +{ "label": "50/10", "node": 4162, "naklon": 0 }, +{ "label": "50/11", "node": 4158, "naklon": 0 }, +{ "label": "50/12", "node": 4182, "naklon": 0 }, +{ "label": "50/13", "node": 4194, "naklon": 0 }, +{ "label": "50/14", "node": 4184, "naklon": 0 }, +{ "label": "50/16", "node": 4197, "naklon": null }, +{ "label": "50/17", "node": 4164, "naklon": null }, +{ "label": "50/18", "node": 3306, "naklon": null }, +{ "label": "50/19", "node": 4168, "naklon": null }, +{ "label": "50/20", "node": 4193, "naklon": null }, +{ "label": "50/21", "node": 4187, "naklon": null }, +{ "label": "50/22", "node": 4163, "naklon": null }, +{ "label": "50/23", "node": 4165, "naklon": null }, +{ "label": "50/24", "node": 4185, "naklon": null }, +{ "label": "50/25", "node": 3904, "naklon": null }, +{ "label": "53/1", "node": 2619, "naklon": 0 }, +{ "label": "53/2", "node": 2623, "naklon": 0 }, +{ "label": "53/3", "node": 2617, "naklon": 0 }, +{ "label": "53/4", "node": 2622, "naklon": 0 }, +{ "label": "53/5", "node": 2618, "naklon": 0 }, +{ "label": "53/6", "node": 2626, "naklon": 0 }, +{ "label": "53/7", "node": 2869, "naklon": 0 }, +{ "label": "53/8", "node": 2613, "naklon": 0 }, +{ "label": "53/9", "node": 2608, "naklon": 0 }, +{ "label": "53/10", "node": 2611, "naklon": 0 }, +{ "label": "53/11", "node": 2598, "naklon": 0 }, +{ "label": "53/12", "node": 3528, "naklon": 0 }, +{ "label": "53/13", "node": 3545, "naklon": 0 }, +{ "label": "53/14", "node": 2620, "naklon": 0 }, +{ "label": "53/15", "node": 2612, "naklon": 0 }, +{ "label": "53/16", "node": 2615, "naklon": 0 }, +{ "label": "53/17", "node": 3722, "naklon": 0 }, +{ "label": "53/18", "node": 2624, "naklon": 0 }, +{ "label": "53/19", "node": 2609, "naklon": 0 }, +{ "label": "53/20", "node": 2625, "naklon": 0 }, +{ "label": "53/21", "node": 2602, "naklon": 0 }, +{ "label": "53/22", "node": 2610, "naklon": 0 }, +{ "label": "53/23", "node": 2599, "naklon": 0 }, +{ "label": "53/24", "node": 2605, "naklon": 0 }, +{ "label": "53/25", "node": 2593, "naklon": 0 }, +{ "label": "53/26", "node": 3074, "naklon": 0 }, +{ "label": "53/27", "node": 2740, "naklon": 0 }, +{ "label": "53/28", "node": 2614, "naklon": 0 }, +{ "label": "53/29", "node": 2601, "naklon": 0 }, +{ "label": "53/30", "node": 4196, "naklon": 0 }, +{ "label": "53/31", "node": 2607, "naklon": 0 }, +{ "label": "53/32", "node": 2582, "naklon": 0 }, +{ "label": "53/33", "node": 2594, "naklon": 0 }, +{ "label": "53/34", "node": 2589, "naklon": 0 }, +{ "label": "53/35", "node": 2596, "naklon": 0 }, +{ "label": "53/36", "node": 2603, "naklon": 0 }, +{ "label": "53/37", "node": 2597, "naklon": 0 }, +{ "label": "53/38", "node": 2590, "naklon": 0 }, +{ "label": "53/39", "node": 2581, "naklon": 0 }, +{ "label": "53/40", "node": 2583, "naklon": 0 }, +{ "label": "53/41", "node": 2580, "naklon": 0 }, +{ "label": "53/42", "node": 2579, "naklon": 0 }, +{ "label": "53/43", "node": 2797, "naklon": 0 }, +{ "label": "53/44", "node": 2577, "naklon": 0 }, +{ "label": "53/45", "node": 2586, "naklon": 0 }, +{ "label": "53/46", "node": 2588, "naklon": 0 }, +{ "label": "53/47", "node": 2591, "naklon": 0 }, +{ "label": "53/48", "node": 2592, "naklon": 0 }, +{ "label": "53/49", "node": 2573, "naklon": 0 }, +{ "label": "53/50", "node": 2595, "naklon": 0 }, +{ "label": "53/51", "node": 2587, "naklon": 0 }, +{ "label": "53/52", "node": 2578, "naklon": 0 }, +{ "label": "53/53", "node": 2574, "naklon": 0 }, +{ "label": "53/54", "node": 2571, "naklon": 0 }, +{ "label": "53/55", "node": 2570, "naklon": 0 }, +{ "label": "53/56", "node": 2576, "naklon": 0 }, +{ "label": "53/57", "node": 2881, "naklon": 0 }, +{ "label": "53/58", "node": 2575, "naklon": 0 }, +{ "label": "53/59", "node": 2572, "naklon": 0 }, +{ "label": "53/60", "node": 2569, "naklon": 0 }, +{ "label": "55/1", "node": 4324, "naklon": 0 }, +{ "label": "55/2", "node": 4319, "naklon": 0 }, +{ "label": "55/3", "node": 4327, "naklon": 0 }, +{ "label": "55/4", "node": 4333, "naklon": 0 }, +{ "label": "55/5", "node": 4332, "naklon": 0 }, +{ "label": "55/6", "node": 4320, "naklon": 0 }, +{ "label": "55/7", "node": 4317, "naklon": 0 }, +{ "label": "55/8", "node": 4318, "naklon": 0 }, +{ "label": "55/9", "node": 4328, "naklon": 0 }, +{ "label": "55/10", "node": 4323, "naklon": 0 }, +{ "label": "55/11", "node": 4325, "naklon": 0 }, +{ "label": "55/12", "node": 4326, "naklon": 0 }, +{ "label": "55/13", "node": 4316, "naklon": 0 }, +{ "label": "55/14", "node": 4322, "naklon": 0 }, +{ "label": "55/15", "node": 4331, "naklon": 0 }, +{ "label": "55/16", "node": 4321, "naklon": 0 }, +{ "label": "55/17", "node": 4315, "naklon": 0 }, +{ "label": "55/18", "node": 4329, "naklon": 0 }, +{ "label": "55/19", "node": 4334, "naklon": 0 }, +{ "label": "55/20", "node": 4330, "naklon": 0 } +]; + +module.exports = { naklony }; diff --git a/RVO43/databases/modbus_config.js b/RVO43/databases/modbus_config.js new file mode 100755 index 0000000..b73116a --- /dev/null +++ b/RVO43/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/RVO43/databases/nodes.table b/RVO43/databases/nodes.table new file mode 100755 index 0000000..34fc89a --- /dev/null +++ b/RVO43/databases/nodes.table @@ -0,0 +1,91 @@ +node:number|pole_number:string|node_type:string|tbname:string|line:number|profile:string|processed:boolean|status:boolean|time_of_last_communication:number ++|3022|38|IP65|PjLblDgRBO6WQqnxmkJ1Vx0Jv3ewZN4p5a89yKdY|2|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":7,"dusk_lux_sensor_value":7,"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|1760574117428|............. ++|4341|39|IP65|1JMYvnx2RzKEo4aWQ7DGDjkL8yZV3m9NBePXbrdj|2|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":7,"dusk_lux_sensor_value":7,"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|1760573956820|............. ++|4344|37|IP65|dz4ojlpP85JMgDLZWkQJbK7aKYqQexEr62GXRV1y|2|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":7,"dusk_lux_sensor_value":7,"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|1760573829892|............. ++|2685|68|NEMA|JX1ObgmqGZ54DMyYL7aDlvkEVdve38WKRzwjNrQ9|2|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":7,"dusk_lux_sensor_value":7,"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|1760573982992|............. ++|2686|69|NEMA|RvmwNz8QPblKp41GD7lKqBkJrLVYoBO92dMegn6W|2|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":7,"dusk_lux_sensor_value":7,"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|1760573983199|............. ++|2687|70|NEMA|RO8rjaBDy21qPQJzW7omjw0pK3xmNleVZg9Ed4Gw|2|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":7,"dusk_lux_sensor_value":7,"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|1760573983838|............. ++|2763|42|NEMA|roKgWqY95V3mXMRzyAjKdo0bLjexpJPvaGDBw826|2|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":7,"dusk_lux_sensor_value":7,"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|1760574264647|............. ++|2764|43|NEMA|E6Kg9oDnLWyzPRMva7v5vJkJxp4VG58qO2w1lZYe|2|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":7,"dusk_lux_sensor_value":7,"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|1760574271964|............. ++|2765|44|NEMA|rDbQ84xzwgdqEoPm3kbEXY09anOZY1RXyBv2LVM6|2|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":7,"dusk_lux_sensor_value":7,"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|1760573836859|............. ++|2766|45|Kamera|52dD6ZlV1QaOpRBmbAqGXekKnGzWMLj4eJq38Pgo|2|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":7,"dusk_lux_sensor_value":7,"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|1760573837130|............. ++|2767|46|NEMA|PLBJzmK1r3Gynd6OW0gKve0e5wV4vx9bDEqNgYR8|2|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":7,"dusk_lux_sensor_value":7,"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|1760573918697|............. ++|2768|47|NEMA|Nzp2OoJlqn6r1ZgvdA3B4o7abBwP5G4eE3RQmyxD|2|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":7,"dusk_lux_sensor_value":7,"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|1760574277333|............. ++|2972|35|VO|gRoJEyXVx4qD9er287L4na7wBzGldaPjLWQKm3Mv|2|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":7,"dusk_lux_sensor_value":7,"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|1760574058455|............. ++|2980|53|IP65|3a5oqJN1bgnx4Ol9dk89WQ7ByE6jQ8mKDWMpGrLV|2|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":7,"dusk_lux_sensor_value":7,"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|1760574284826|............. ++|2982|49|IP65|PLBJzmK1r3Gynd6OW0gKvx0e5wV4vx9bDEqNgYR8|2|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":7,"dusk_lux_sensor_value":7,"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|1760574285242|............. ++|4340|40|IP65|Z5KyJe9nEg1QNbWlX0w4DbkoDjBLdqzR83VGv624|2|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":7,"dusk_lux_sensor_value":7,"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|1760573824684|............. ++|2988|36|IP65|d5xjWYMwEJon6rLlK7yEDD7qgV4DaOeNB9ZX3Gzb|2|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":7,"dusk_lux_sensor_value":7,"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|1760574285577|............. ++|2989|33|IP65|d9x2V5LGYBzXp4mMRAOmgGkPloaqJwnQj6DgrNe3|2|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":7,"dusk_lux_sensor_value":7,"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|1760574285737|............. ++|2995|41|IP65|3JjOWdylwgNLzxVab7Na3gkZ2vG64rq8PEB5QmDo|2|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":7,"dusk_lux_sensor_value":7,"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|1760574287239|............. ++|2996|34|IP65|K94XLav1glVRnyQ6r01Po5Ame3YJwBxM5oOzdP2j|2|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":7,"dusk_lux_sensor_value":7,"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|1760574287415|............. ++|3007|52|VO|EjgWGnXaLy9opPOz20n4Va786BlYM3w1deVQvbKr|2|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":7,"dusk_lux_sensor_value":7,"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|1760574288677|............. ++|3011|54|VO|eod9aRWLVl34Gx1Dn7VNqr72rz6qjgmpEXwQJN5Z|2|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":7,"dusk_lux_sensor_value":7,"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|1760574289252|............. ++|3013|51|VO|wvKJdZML6mXP4DzWBAXxvPAjxNloa5g23Ve9Y1ry|2|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":7,"dusk_lux_sensor_value":7,"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|1760573811822|............. ++|3018|48|04-Repeater|52dD6ZlV1QaOpRBmbAqGXqkKnGzWMLj4eJq38Pgo|2|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":7,"dusk_lux_sensor_value":7,"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|1760573812413|............. ++|3019|50|VO|Nzp2OoJlqn6r1ZgvdA3B4L7abBwP5G4eE3RQmyxD|2|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":7,"dusk_lux_sensor_value":7,"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|1760573815816|............. ++|2607|55|NEMA|zrR51V2ajQ9ZLygPKkEMKykYDq38xOJolENBXGnv|1||1|1|1760574192683|............. ++|2673|56|NEMA|BaY3Xpy1EbKGjLq2O7ma5g7rx8owgQz9P4dDJRmN|1||1|1|1760573313172|............. ++|2689|72|NEMA|RO8rjaBDy21qPQJzW7om8w0pK3xmNleVZg9Ed4Gw|1||1|1|1760574326497|............. ++|2690|73|NEMA|3JjOWdylwgNLzxVab7NaogkZ2vG64rq8PEB5QmDo|1||1|1|1760574326672|............. ++|2691|74|NEMA|Z5KyJe9nEg1QNbWlX0w4jbkoDjBLdqzR83VGv624|1||1|1|1760574328095|............. ++|2693|76|NEMA|PjLblDgRBO6WQqnxmkJ1Px0Jv3ewZN4p5a89yKdY|1||1|1|1760574328830|............. ++|2694|77|NEMA|dz4ojlpP85JMgDLZWkQJ8K7aKYqQexEr62GXRV1y|1||1|1|1760573894315|............. ++|2695|78|NEMA|d5xjWYMwEJon6rLlK7yEdD7qgV4DaOeNB9ZX3Gzb|1||1|1|1760573894698|............. ++|2675|58|NEMA|apKVJBwOyrP35m2lv7KYBM0YXbeWNd64En9GxRqg|1||1|1|1760574286057|............. ++|2871|80|NEMA|K94XLav1glVRnyQ6r01Pm5Ame3YJwBxM5oOzdP2j|1||1|1|1760574051217|............. ++|2699|82|NEMA|B5EoxeMVp4zwr8nqW0GBZlARjvD1PNamOGbLg63Z|1||1|1|1760574344184|............. ++|2744|84|NEMA|ZmRwd93QL4gaezxEbAx2rLk1prn2XjlPvGyqJ6BO|1||1|1|1760574344745|............. ++|2745|85|NEMA|eod9aRWLVl34Gx1Dn7VNqj72rz6qjgmpEXwQJN5Z|1||1|1|1760574340110|............. ++|4036|86|NEMA|3a5oqJN1bgnx4Ol9dk89Wo7ByE6jQ8mKDWMpGrLV|1||1|1|1760573816998|............. ++|2748|88|NEMA|wvKJdZML6mXP4DzWBAXxvKAjxNloa5g23Ve9Y1ry|1||1|1|1760574335604|............. ++|2749|89|NEMA|RvmwNz8QPblKp41GD7lKYBkJrLVYoBO92dMegn6W|1||1|1|1760574335764|............. ++|2677|60|NEMA|gP1eOZVj3Q9lv5aDEk45dv7rdpqW8yLm2BbKzJxM|1||1|1|1760574192428|............. ++|2678|61|NEMA|2O14VBzl8aDmWdNw3A59pKAGyZ5qLJoEMpj6R9ng|1||1|1|1760574318060|............. ++|2679|62|NEMA|pE5X8NQPaow6vlOZxk6aZE0q42ezGBMyWgDVjR3L|1||1|1|1760574318268|............. ++|2680|63|NEMA|6lQGaY9RDywdVzObj0PaqokPg4NBn3exEK51LWZq|1||1|1|1760574318652|............. ++|2682|65|NEMA|JzwxZXOvDj1bVrN4nkW5a5A8qdyBl3MRKLpGPgaQ|1||1|1|1760574303632|............. ++|2683|66|NEMA|g9OxBZ5KRwNznlY6pAppr6AWXvjdEL4eGQobMDy2|1||1|1|1760573872026|............. ++|2684|67|NEMA|OzNMgZ9n43qPbjXmy7zwD8A2DKdYvW5e6pxGRrVa|1||1|1|1760574307100|............. ++|2674|57|NEMA|DbQY6zyveZRwK5drV0Z8N57joE4XJM83N9xl2nWq|1||1|1|1760574281263|............. ++|2676|59|NEMA|o9vbeQlLMVg8j5dq4keL6o0NxZpEmnXzwYKO1ar2|1||1|1|1760574286296|............. ++|2840|64|NEMA|m6EYyZoJ4gWexdjVPAR5va7RDOq9wv2N5XzKGplr|1||1|1|1760573926094|............. ++|2841|90|NEMA|JX1ObgmqGZ54DMyYL7aDnvkEVdve38WKRzwjNrQ9|1||1|1|1760573926238|............. ++|2747|87|NEMA|EjgWGnXaLy9opPOz20n4VB786BlYM3w1deVQvbKr|1||1|1|1760574335428|............. ++|2688|71|NEMA|nJL5lPMwBx23YpqRe0rp397damXvWVbOrD4gNzy8|1||1|1|1760574220756|............. ++|2979|32|IP65|B5EoxeMVp4zwr8nqW0GB5lARjvD1PNamOGbLg63Z|2|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":7,"dusk_lux_sensor_value":7,"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|1760574059877|............. ++|3002|30|VO|ZmRwd93QL4gaezxEbAx2GLk1prn2XjlPvGyqJ6BO|2|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":7,"dusk_lux_sensor_value":7,"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|1760574287591|............. ++|4345|31|IP65|aw4eELG2DlPMdn1JW0BMG8AqQXOZRN3xB5yp8VKr|2|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":7,"dusk_lux_sensor_value":7,"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|1760574230806|............. ++|4338|29|IP65|eod9aRWLVl34Gx1Dn7VN2j72rz6qjgmpEXwQJN5Z|2|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":7,"dusk_lux_sensor_value":7,"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|1760573820002|............. ++|3003|28|VO|3a5oqJN1bgnx4Ol9dk89Zo7ByE6jQ8mKDWMpGrLV|2|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":7,"dusk_lux_sensor_value":7,"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|1760573806996|............. ++|2975|27|IP65|EjgWGnXaLy9opPOz20n4vB786BlYM3w1deVQvbKr|2|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":7,"dusk_lux_sensor_value":7,"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|1760574058663|............. ++|4380|26|VO|wvKJdZML6mXP4DzWBAXxaKAjxNloa5g23Ve9Y1ry|2|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":7,"dusk_lux_sensor_value":7,"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|1760573831794|............. ++|4339|25|IP65|Nzp2OoJlqn6r1ZgvdA3BZo7abBwP5G4eE3RQmyxD|2|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":7,"dusk_lux_sensor_value":7,"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|1760573820194|............. ++|2760|20|NEMA|PLBJzmK1r3Gynd6OW0gK8e0e5wV4vx9bDEqNgYR8|2|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":7,"dusk_lux_sensor_value":7,"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|1760573820577|.................. ++|4379|21|IP65|OzNMgZ9n43qPbjXmy7zw28A2DKdYvW5e6pxGRrVa|2|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":7,"dusk_lux_sensor_value":7,"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|1760573831586|............. ++|3564|22|IP65|g9OxBZ5KRwNznlY6pAppn6AWXvjdEL4eGQobMDy2|2|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":7,"dusk_lux_sensor_value":7,"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|1760573816807|............. ++|2761|23|NEMA|JzwxZXOvDj1bVrN4nkW5b5A8qdyBl3MRKLpGPgaQ|2|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":7,"dusk_lux_sensor_value":7,"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|1760574261212|............. ++|2762|24|NEMA|m6EYyZoJ4gWexdjVPAR5na7RDOq9wv2N5XzKGplr|2|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":7,"dusk_lux_sensor_value":7,"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|1760573824476|............. ++|4343|19|IP65|52dD6ZlV1QaOpRBmbAqGdekKnGzWMLj4eJq38Pgo|2|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":7,"dusk_lux_sensor_value":7,"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|1760573825451|............. ++|2986|18|IP65|rDbQ84xzwgdqEoPm3kbEaY09anOZY1RXyBv2LVM6|2|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":7,"dusk_lux_sensor_value":7,"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|1760574155392|............. ++|3026|17|IP65|E6Kg9oDnLWyzPRMva7v5DJkJxp4VG58qO2w1lZYe|2|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":7,"dusk_lux_sensor_value":7,"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|1760573951451|............. ++|4342|16|IP65|roKgWqY95V3mXMRzyAjK3o0bLjexpJPvaGDBw826|2|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":7,"dusk_lux_sensor_value":7,"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|1760574222514|............. ++|2759|15|NEMA|nJL5lPMwBx23YpqRe0rpB97damXvWVbOrD4gNzy8|2|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":7,"dusk_lux_sensor_value":7,"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|1760573820370|............. ++|4378|14|IP65|XMBbew5z4ELrZa2mRAd3a278vPN6gy3DdVYlpKjq|2|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":7,"dusk_lux_sensor_value":7,"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|1760573831075|............. ++|2758|13|NEMA|gYbDLqlyZVoRerQpB72MZbkWJnwM5z24POKa8Exj|2|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":7,"dusk_lux_sensor_value":7,"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|1760574257568|............. ++|2970|12|IP65|zdQO8GwxDqjRgP4137YVaWANyKlpem2nL65rvVJY|2|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":7,"dusk_lux_sensor_value":7,"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|1760574058072|............. ++|2757|11|NEMA|WlVJBygjDZMeKX3vnAMRXo08NqdmG2x1Y69LQ4P5|2|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":7,"dusk_lux_sensor_value":7,"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|1760574257329|............. ++|4377|10|IP65|5dBNwRp9graYJxZn409NWyklVov1b2QLPDqGm6XK|2|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":7,"dusk_lux_sensor_value":7,"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|1760573931079|............. ++|2868|9|NEMA|zrR51V2ajQ9ZLygPKkEM5ykYDq38xOJolENBXGnv|2|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":7,"dusk_lux_sensor_value":7,"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|1760573928970|............. ++|2978|8|IP65|BaY3Xpy1EbKGjLq2O7mabg7rx8owgQz9P4dDJRmN|2|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":7,"dusk_lux_sensor_value":7,"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|1760574059078|............. ++|4368|7|NEMA|DbQY6zyveZRwK5drV0Z8157joE4XJM83N9xl2nWq|2|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":7,"dusk_lux_sensor_value":7,"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|1760573830468|............. ++|4423|6|IP65|apKVJBwOyrP35m2lv7KY8M0YXbeWNd64En9GxRqg|2|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":7,"dusk_lux_sensor_value":7,"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|1760573936544|............. ++|2754|5|NEMA|o9vbeQlLMVg8j5dq4keLxo0NxZpEmnXzwYKO1ar2|2|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":7,"dusk_lux_sensor_value":7,"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|1760574341484|............. ++|3024|4|IP65|gP1eOZVj3Q9lv5aDEk45Rv7rdpqW8yLm2BbKzJxM|2|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":7,"dusk_lux_sensor_value":7,"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|1760574117604|............. ++|2753|3|NEMA|2O14VBzl8aDmWdNw3A59eKAGyZ5qLJoEMpj6R9ng|2|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":7,"dusk_lux_sensor_value":7,"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|1760573905227|............. ++|2752|2|NEMA|6lQGaY9RDywdVzObj0PaVokPg4NBn3exEK51LWZq|2|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":7,"dusk_lux_sensor_value":7,"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|1760573905068|............. ++|2857|1|NEMA|pE5X8NQPaow6vlOZxk6a5E0q42ezGBMyWgDVjR3L|2|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":7,"dusk_lux_sensor_value":7,"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|1760573928811|............. ++|2692|75|NEMA|1JMYvnx2RzKEo4aWQ7DGZjkL8yZV3m9NBePXbrdj|1||1|1|1760574328270|............. ++|2696|79|NEMA|gRoJEyXVx4qD9er287L4aa7wBzGldaPjLWQKm3Mv|1||1|1|1760573895114|............. ++|2698|81|NEMA|d9x2V5LGYBzXp4mMRAOmxGkPloaqJwnQj6DgrNe3|1||1|1|1760574342267|............. ++|2700|83|NEMA|aw4eELG2DlPMdn1JW0BMZ8AqQXOZRN3xB5yp8VKr|1|{"intervals":[{"cct":3000,"value":0,"end_time":"20:00","start_time":"13:00"},{"cct":3000,"value":50,"end_time":"05:30","start_time":"20:00"},{"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|1760574344584|............. diff --git a/RVO43/databases/nodes_original/nodes_original.table b/RVO43/databases/nodes_original/nodes_original.table new file mode 100755 index 0000000..588321a --- /dev/null +++ b/RVO43/databases/nodes_original/nodes_original.table @@ -0,0 +1 @@ +[{"3022": "PjLblDgRBO6WQqnxmkJ1Vx0Jv3ewZN4p5a89yKdY"}, {"4341": "1JMYvnx2RzKEo4aWQ7DGDjkL8yZV3m9NBePXbrdj"}, {"4344": "dz4ojlpP85JMgDLZWkQJbK7aKYqQexEr62GXRV1y"}, {"2685": "JX1ObgmqGZ54DMyYL7aDlvkEVdve38WKRzwjNrQ9"}, {"2686": "RvmwNz8QPblKp41GD7lKqBkJrLVYoBO92dMegn6W"}, {"2687": "RO8rjaBDy21qPQJzW7omjw0pK3xmNleVZg9Ed4Gw"}, {"2763": "roKgWqY95V3mXMRzyAjKdo0bLjexpJPvaGDBw826"}, {"2764": "E6Kg9oDnLWyzPRMva7v5vJkJxp4VG58qO2w1lZYe"}, {"2765": "rDbQ84xzwgdqEoPm3kbEXY09anOZY1RXyBv2LVM6"}, {"2766": "52dD6ZlV1QaOpRBmbAqGXekKnGzWMLj4eJq38Pgo"}, {"2767": "PLBJzmK1r3Gynd6OW0gKve0e5wV4vx9bDEqNgYR8"}, {"2768": "Nzp2OoJlqn6r1ZgvdA3B4o7abBwP5G4eE3RQmyxD"}, {"2972": "gRoJEyXVx4qD9er287L4na7wBzGldaPjLWQKm3Mv"}, {"2980": "3a5oqJN1bgnx4Ol9dk89WQ7ByE6jQ8mKDWMpGrLV"}, {"2982": "PLBJzmK1r3Gynd6OW0gKvx0e5wV4vx9bDEqNgYR8"}, {"4340": "Z5KyJe9nEg1QNbWlX0w4DbkoDjBLdqzR83VGv624"}, {"2988": "d5xjWYMwEJon6rLlK7yEDD7qgV4DaOeNB9ZX3Gzb"}, {"2989": "d9x2V5LGYBzXp4mMRAOmgGkPloaqJwnQj6DgrNe3"}, {"2995": "3JjOWdylwgNLzxVab7Na3gkZ2vG64rq8PEB5QmDo"}, {"2996": "K94XLav1glVRnyQ6r01Po5Ame3YJwBxM5oOzdP2j"}, {"3007": "EjgWGnXaLy9opPOz20n4Va786BlYM3w1deVQvbKr"}, {"3011": "eod9aRWLVl34Gx1Dn7VNqr72rz6qjgmpEXwQJN5Z"}, {"3013": "wvKJdZML6mXP4DzWBAXxvPAjxNloa5g23Ve9Y1ry"}, {"3018": "52dD6ZlV1QaOpRBmbAqGXqkKnGzWMLj4eJq38Pgo"}, {"3019": "Nzp2OoJlqn6r1ZgvdA3B4L7abBwP5G4eE3RQmyxD"}, {"2607": "zrR51V2ajQ9ZLygPKkEMKykYDq38xOJolENBXGnv"}, {"2673": "BaY3Xpy1EbKGjLq2O7ma5g7rx8owgQz9P4dDJRmN"}, {"2689": "RO8rjaBDy21qPQJzW7om8w0pK3xmNleVZg9Ed4Gw"}, {"2690": "3JjOWdylwgNLzxVab7NaogkZ2vG64rq8PEB5QmDo"}, {"2691": "Z5KyJe9nEg1QNbWlX0w4jbkoDjBLdqzR83VGv624"}, {"2693": "PjLblDgRBO6WQqnxmkJ1Px0Jv3ewZN4p5a89yKdY"}, {"2694": "dz4ojlpP85JMgDLZWkQJ8K7aKYqQexEr62GXRV1y"}, {"2695": "d5xjWYMwEJon6rLlK7yEdD7qgV4DaOeNB9ZX3Gzb"}, {"2675": "apKVJBwOyrP35m2lv7KYBM0YXbeWNd64En9GxRqg"}, {"2871": "K94XLav1glVRnyQ6r01Pm5Ame3YJwBxM5oOzdP2j"}, {"2699": "B5EoxeMVp4zwr8nqW0GBZlARjvD1PNamOGbLg63Z"}, {"2744": "ZmRwd93QL4gaezxEbAx2rLk1prn2XjlPvGyqJ6BO"}, {"2745": "eod9aRWLVl34Gx1Dn7VNqj72rz6qjgmpEXwQJN5Z"}, {"4036": "3a5oqJN1bgnx4Ol9dk89Wo7ByE6jQ8mKDWMpGrLV"}, {"2748": "wvKJdZML6mXP4DzWBAXxvKAjxNloa5g23Ve9Y1ry"}, {"2749": "RvmwNz8QPblKp41GD7lKYBkJrLVYoBO92dMegn6W"}, {"2677": "gP1eOZVj3Q9lv5aDEk45dv7rdpqW8yLm2BbKzJxM"}, {"2678": "2O14VBzl8aDmWdNw3A59pKAGyZ5qLJoEMpj6R9ng"}, {"2679": "pE5X8NQPaow6vlOZxk6aZE0q42ezGBMyWgDVjR3L"}, {"2680": "6lQGaY9RDywdVzObj0PaqokPg4NBn3exEK51LWZq"}, {"2682": "JzwxZXOvDj1bVrN4nkW5a5A8qdyBl3MRKLpGPgaQ"}, {"2683": "g9OxBZ5KRwNznlY6pAppr6AWXvjdEL4eGQobMDy2"}, {"2684": "OzNMgZ9n43qPbjXmy7zwD8A2DKdYvW5e6pxGRrVa"}, {"2674": "DbQY6zyveZRwK5drV0Z8N57joE4XJM83N9xl2nWq"}, {"2676": "o9vbeQlLMVg8j5dq4keL6o0NxZpEmnXzwYKO1ar2"}, {"2840": "m6EYyZoJ4gWexdjVPAR5va7RDOq9wv2N5XzKGplr"}, {"2841": "JX1ObgmqGZ54DMyYL7aDnvkEVdve38WKRzwjNrQ9"}, {"2747": "EjgWGnXaLy9opPOz20n4VB786BlYM3w1deVQvbKr"}, {"2688": "nJL5lPMwBx23YpqRe0rp397damXvWVbOrD4gNzy8"}, {"2979": "B5EoxeMVp4zwr8nqW0GB5lARjvD1PNamOGbLg63Z"}, {"3002": "ZmRwd93QL4gaezxEbAx2GLk1prn2XjlPvGyqJ6BO"}, {"4345": "aw4eELG2DlPMdn1JW0BMG8AqQXOZRN3xB5yp8VKr"}, {"4338": "eod9aRWLVl34Gx1Dn7VN2j72rz6qjgmpEXwQJN5Z"}, {"3003": "3a5oqJN1bgnx4Ol9dk89Zo7ByE6jQ8mKDWMpGrLV"}, {"2975": "EjgWGnXaLy9opPOz20n4vB786BlYM3w1deVQvbKr"}, {"4380": "wvKJdZML6mXP4DzWBAXxaKAjxNloa5g23Ve9Y1ry"}, {"4339": "Nzp2OoJlqn6r1ZgvdA3BZo7abBwP5G4eE3RQmyxD"}, {"2760": "PLBJzmK1r3Gynd6OW0gK8e0e5wV4vx9bDEqNgYR8"}, {"4379": "OzNMgZ9n43qPbjXmy7zw28A2DKdYvW5e6pxGRrVa"}, {"3564": "g9OxBZ5KRwNznlY6pAppn6AWXvjdEL4eGQobMDy2"}, {"2761": "JzwxZXOvDj1bVrN4nkW5b5A8qdyBl3MRKLpGPgaQ"}, {"2762": "m6EYyZoJ4gWexdjVPAR5na7RDOq9wv2N5XzKGplr"}, {"4343": "52dD6ZlV1QaOpRBmbAqGdekKnGzWMLj4eJq38Pgo"}, {"2986": "rDbQ84xzwgdqEoPm3kbEaY09anOZY1RXyBv2LVM6"}, {"3026": "E6Kg9oDnLWyzPRMva7v5DJkJxp4VG58qO2w1lZYe"}, {"4342": "roKgWqY95V3mXMRzyAjK3o0bLjexpJPvaGDBw826"}, {"2759": "nJL5lPMwBx23YpqRe0rpB97damXvWVbOrD4gNzy8"}, {"4378": "XMBbew5z4ELrZa2mRAd3a278vPN6gy3DdVYlpKjq"}, {"2758": "gYbDLqlyZVoRerQpB72MZbkWJnwM5z24POKa8Exj"}, {"2970": "zdQO8GwxDqjRgP4137YVaWANyKlpem2nL65rvVJY"}, {"2757": "WlVJBygjDZMeKX3vnAMRXo08NqdmG2x1Y69LQ4P5"}, {"4377": "5dBNwRp9graYJxZn409NWyklVov1b2QLPDqGm6XK"}, {"2868": "zrR51V2ajQ9ZLygPKkEM5ykYDq38xOJolENBXGnv"}, {"2978": "BaY3Xpy1EbKGjLq2O7mabg7rx8owgQz9P4dDJRmN"}, {"4368": "DbQY6zyveZRwK5drV0Z8157joE4XJM83N9xl2nWq"}, {"4423": "apKVJBwOyrP35m2lv7KY8M0YXbeWNd64En9GxRqg"}, {"2754": "o9vbeQlLMVg8j5dq4keLxo0NxZpEmnXzwYKO1ar2"}, {"3024": "gP1eOZVj3Q9lv5aDEk45Rv7rdpqW8yLm2BbKzJxM"}, {"2753": "2O14VBzl8aDmWdNw3A59eKAGyZ5qLJoEMpj6R9ng"}, {"2752": "6lQGaY9RDywdVzObj0PaVokPg4NBn3exEK51LWZq"}, {"2857": "pE5X8NQPaow6vlOZxk6a5E0q42ezGBMyWgDVjR3L"}, {"2692": "1JMYvnx2RzKEo4aWQ7DGZjkL8yZV3m9NBePXbrdj"}, {"2696": "gRoJEyXVx4qD9er287L4aa7wBzGldaPjLWQKm3Mv"}, {"2698": "d9x2V5LGYBzXp4mMRAOmxGkPloaqJwnQj6DgrNe3"}, {"2700": "aw4eELG2DlPMdn1JW0BMZ8AqQXOZRN3xB5yp8VKr"}] \ No newline at end of file diff --git a/RVO43/databases/notifications.table b/RVO43/databases/notifications.table new file mode 100755 index 0000000..f7c96cb --- /dev/null +++ b/RVO43/databases/notifications.table @@ -0,0 +1,41 @@ +key:string|weight:string|sk:string|en:string ++|switching_profile_point_applied_to_line|INFORMATIONAL|Aplikovaný bod spínacieho profilu na línií č. ${line} : ${value}|Switching profile point applied to line no. ${line} : ${value}|............... ++|dusk_has_occured|INFORMATIONAL|Nastal súmrak: ${value}|Dusk has occured: ${value}|............... ++|dawn_has_occured|INFORMATIONAL|Nastal úsvit: ${value}|Dawn has occured: ${value}|............... ++|dimming_profile_was_successfully_received_by_node|NOTICE|Stmievací profil bol úspešne prijatý nodom č. ${node}|Dimming profile was successfully received by node no. ${node}|............... ++|master_node_is_responding_again|NOTICE|Master node začal znovu odpovedať|Master node is responding again|............... ++|command_was_sent_from_terminal_interface|DEBUG|Z terminálu bol odoslaný príkaz|A command was sent from terminal interface|............... ++|master_node_is_not_responding|ALERT|Master node neodpovedá|Master node is not responding|............... ++|configuration_of_dimming_profile_to_node_failed|ALERT|Konfigurácia stmievacieho profilu pre node č. ${node} zlyhala|Configuration of dimming profile to node no. ${node} has failed|............... ++|circuit_breaker_was_turned_on_line|NOTICE|Zapnutie ističa na línii č. ${line}|Circuit breaker was turned on - line no. ${line}|............... ++|circuit_breaker_was_turned_off_line|ERROR|Vypnutie ističa na línií č. ${line}|Circuit breaker was turned off - line no. ${line}|............... ++|dimming_profile_was_processed_for_node|INFORMATIONAL|Stmievací profil bol spracovaný pre node č. ${node}|Dimming profile was processed for node no. ${node}|............... ++|switching_profile_was_processed_for_line|INFORMATIONAL|Spínací profil bol spracovaný pre líniu č. ${line}|Switching profile was processed for line no. ${line}|............... ++|thermometer_is_not_responding|WARNING|Teplomer neodpovedá|Thermometer is not responding|............... ++|thermometer_is_responding_again|NOTICE|Teplomer znovu odpovedá|Thermometer is responding again|............... ++|thermometer_sends_invalid_data|WARNING|Teplomer posiela neplatné hodnoty|Thermometer sends invalid data|............... ++|main_switch_has_been_turned_off|CRITICAL|Hlavný vypínač bol vypnutý|Main switch has been turned off|............... ++|main_switch_has_been_turned_on|NOTICE|Hlavný vypínač bol zapnutý|Main switch has been turned on|............... ++|power_supply_has_disconnected_input|ALERT|Napájací zdroj nemá napätie na vstupe|Power supply has disconnected input|............... ++|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_main_open|NOTICE|Hlavné dvere boli otvorené|Main door has been opened|............... ++|door_em_open|NOTICE|Dvere silovej časti boli otvorené|Power door has been opened|............... ++|door_main_open_without_permission|WARNING|Hlavné dvere boli otvorené bez povolenia - zapnutá siréna|Main door has been opened without permission - alarm is on|............... ++|door_em_open_without_permission|WARNING|Dvere silovej časti boli otvorené bez povolenia|Power door has been opened without permission|............... ++|door_main_close|NOTICE|Hlavné dvere boli zatvorené|Main door has been closed|............... ++|door_em_close|NOTICE|Dvere silovej časti boli zatvorené|Power door has been closed|............... ++|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|............... ++|electrometer_ok|NOTICE|Elektromer znovu odpovedá|Electrometer is responding again|............... ++|no_voltage_on_phase|CRITICAL|Na fáze č. ${phase} nie je napätie|No voltage detected on phase no. ${phase}|............... ++|voltage_on_phase_restored|NOTICE|Napätie na fáze č. ${phase} bolo obnovené|Voltage on phase no. ${phase} has been restored|............... ++|flow_start|NOTICE|FLOW bol spustený|FLOW has been started |............... ++|twilight_sensor_nok|ERROR|Sensor súmraku neodpovedá|Twilight sensor is not responding|............... ++|twilight_sensor_ok|NOTICE|Sensor súmraku znovu odpovedá|Twilight sensor is responding again|............... ++|lamps_have_turned_on|NOTICE|Lampy sa zapli|Lamps have turned on|............... ++|lamps_have_turned_off|NOTICE|Lampy sa vypli|Lamps have turned off|............... ++|flow_restart|NOTICE|FLOW bol reštartovaný|FLOW has been restarted|............... ++|nodes_db_changed|NOTICE|Zmena v node databáze|Node db has changed|............... diff --git a/RVO43/databases/pins.table b/RVO43/databases/pins.table new file mode 100755 index 0000000..e5b0f56 --- /dev/null +++ b/RVO43/databases/pins.table @@ -0,0 +1,14 @@ +pin:string|type:string|line:number +*|input1_01|door_condition|0|........... +*|input1_02|rotary_switch_state|0|........... +*|input1_03|rotary_switch_state|0|........... +*|input1_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|........... +*|282FAA660E00006F|temperature|0|........... +*|twilight_sensor|twilight_sensor|0|........... diff --git a/RVO43/databases/relays.table b/RVO43/databases/relays.table new file mode 100755 index 0000000..b72729c --- /dev/null +++ b/RVO43/databases/relays.table @@ -0,0 +1,5 @@ +line:number|tbname:string|contactor:number|profile:string ++|0|gRoJEyXVx4qD9er287L4847wBzGldaPjLWQKm3Mv|1||........... ++|3|ZmRwd93QL4gaezxEbAx2rVk1prn2XjlPvGyqJ6BO|9|{"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":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|WlVJBygjDZMeKX3vnAMRnm08NqdmG2x1Y69LQ4P5|9|{"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":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|5dBNwRp9graYJxZn409Nq2klVov1b2QLPDqGm6XK|9|{"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}|....................................................................................................................................................................................................................................................................................................................................................................................... diff --git a/RVO43/databases/settings.table b/RVO43/databases/settings.table new file mode 100755 index 0000000..78b9457 --- /dev/null +++ b/RVO43/databases/settings.table @@ -0,0 +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|project_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|cloud_topic:string|has_main_switch:boolean|daily_report:boolean|send_changed_node_numbers:boolean ++|rvo_senica_43_ip116|en|28.2FAA660E0000|48.70826502|17.28455203|192.168.252.1|rvo_senica_43_ip116|1DHwbROKPmZij6qXFqbY|1883|0|47|unipi|ttyUSB0|1|20|5|6|3|u116|0|1|1|................................................... diff --git a/RVO43/databases/tbdata.nosql b/RVO43/databases/tbdata.nosql new file mode 100755 index 0000000..7e0c64e --- /dev/null +++ b/RVO43/databases/tbdata.nosql @@ -0,0 +1,4 @@ +-"gRoJEyXVx4qD9er287L4847wBzGldaPjLWQKm3Mv":[{"ts":1760535013392,"values":{"_event":{"type":"notice","status":"new","source":{"func":"modbus_reader","component":"1699965957410","component_name":"Modbus reader","edge":"gRoJEyXVx4qD9er287L4847wBzGldaPjLWQKm3Mv"},"message":{"sk":"rvo_senica_43_ip116: FLOW bol reštartovaný","en":"rvo_senica_43_ip116: FLOW has been restarted"},"message_data":""}}}],"id":"3000390001ik71b"} +-"gRoJEyXVx4qD9er287L4847wBzGldaPjLWQKm3Mv":[{"ts":1760535013485,"values":{"edge_fw_version":"2025-10-08","maintenance_mode":false}}],"id":"3000390002ik70b"} +-"gRoJEyXVx4qD9er287L4847wBzGldaPjLWQKm3Mv":[{"ts":1760535013499,"values":{"statecode":2,"power_mode":"Automatic"}}],"id":"3000390004ik70b"} +-"gRoJEyXVx4qD9er287L4847wBzGldaPjLWQKm3Mv":[{"ts":1760535013547,"values":{"_event":{"type":"notice","status":"new","source":{"func":"rsPort.open()","component":"1699963668903","component_name":"DIDO_Controller","edge":"gRoJEyXVx4qD9er287L4847wBzGldaPjLWQKm3Mv"},"message":{"sk":"rvo_senica_43_ip116: FLOW bol spustený","en":"rvo_senica_43_ip116: FLOW has been started "},"message_data":""}}}],"id":"3000390006ik70b"} diff --git a/RVO43/databases/tbdatacloud.nosql b/RVO43/databases/tbdatacloud.nosql new file mode 100755 index 0000000..9052bac --- /dev/null +++ b/RVO43/databases/tbdatacloud.nosql @@ -0,0 +1,3 @@ +-"gRoJEyXVx4qD9er287L4847wBzGldaPjLWQKm3Mv":[{"ts":1760535013485,"values":{"edge_fw_version":"2025-10-08","maintenance_mode":false}}],"id":"3000390003ik71b"} +-"gRoJEyXVx4qD9er287L4847wBzGldaPjLWQKm3Mv":[{"ts":1760535013499,"values":{"statecode":2,"power_mode":"Automatic"}}],"id":"3000390005ik71b"} +-"gRoJEyXVx4qD9er287L4847wBzGldaPjLWQKm3Mv":[{"ts":1760535013547,"values":{"_event":{"type":"notice","status":"new","source":{"func":"rsPort.open()","component":"1699963668903","component_name":"DIDO_Controller","edge":"gRoJEyXVx4qD9er287L4847wBzGldaPjLWQKm3Mv"},"message":{"sk":"rvo_senica_43_ip116: FLOW bol spustený","en":"rvo_senica_43_ip116: FLOW has been started "},"message_data":""}}}],"id":"3000390007ik71b"} diff --git a/RVO43/databases/total_energy.js b/RVO43/databases/total_energy.js new file mode 100755 index 0000000..dde340e --- /dev/null +++ b/RVO43/databases/total_energy.js @@ -0,0 +1,38 @@ +//key is rvo_number, value is max energy when lamps are on +const total_energy = { + 1: 580, + 2: 1100, + 3: 3700, + 4: 4100, + 7: 360, + 12: 1700, + 13: 5400, + 14: 440, + 15: 6100, + 16: 4800, + 20: 1600, + 21: 1000, + 22: 2600, + 23: 1000, + 25: 2600, + 33: 240, + 34: 4000, + 35: 2700, + 36: 820, + 37: 1400, + 35: 3500, + 39: 1170, + 41: 740, + 42: 660, + 43: 4900, + 45: 930, + 46: 700, + 47: 1100, + 48: 1500, + 50: 3200, + 53: 1250, + 55: 1000, + 56: 5500 +} + +module.exports = total_energy; diff --git a/RVO43/debug.js b/RVO43/debug.js new file mode 100755 index 0000000..9818194 --- /dev/null +++ b/RVO43/debug.js @@ -0,0 +1,16 @@ +// =================================================== +// FOR DEVELOPMENT +// Total.js - framework for Node.js platform +// https://www.totaljs.com +// =================================================== + +const options = {}; + +// options.ip = '127.0.0.1'; +// options.port = parseInt(process.argv[2]); +// options.config = { name: 'Total.js' }; +// options.sleep = 3000; +// options.inspector = 9229; +// options.watch = ['private']; + +require('total.js/debug')(options); \ No newline at end of file diff --git a/RVO43/err.txt b/RVO43/err.txt new file mode 100755 index 0000000..3dcefe2 --- /dev/null +++ b/RVO43/err.txt @@ -0,0 +1,67 @@ +[2024-10-26T06:12:28.858] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T07:12:41.139] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T08:12:53.485] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T09:13:05.725] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T10:18:18.976] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T11:18:31.177] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T12:21:13.891] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T13:21:26.059] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T14:24:08.680] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T15:24:20.814] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T16:24:32.950] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T17:29:46.071] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T18:32:28.775] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T19:32:40.910] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T20:32:53.029] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T21:33:05.174] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T22:33:17.341] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T23:33:29.432] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T00:33:41.541] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T01:33:53.656] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T02:36:36.266] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T02:36:48.404] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T03:37:00.538] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T04:39:45.152] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T05:39:57.450] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T06:40:09.737] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T07:40:22.008] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T08:40:34.211] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T09:45:47.443] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T10:45:59.644] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T11:51:12.816] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T12:51:25.021] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T13:51:37.139] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T14:51:49.244] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2025-09-23T14:07:57.877] [ERROR] errLogs - uncaughtException: Cannot read property 'getHours' of undefined +[2025-09-23T14:07:57.881] [ERROR] errLogs - TypeError: Cannot read property 'getHours' of undefined + at Timeout.emptyReportToSend [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:07:57.882] [ERROR] errLogs - uncaughtException: Cannot read property 'getHours' of undefined +[2025-09-23T14:07:57.882] [ERROR] errLogs - TypeError: Cannot read property 'getHours' of undefined + at Timeout.emptyReportToSend [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:07:57.895] [ERROR] errLogs - uncaughtException: Cannot read property 'getHours' of undefined +[2025-09-23T14:07:57.896] [ERROR] errLogs - TypeError: Cannot read property 'getHours' of undefined + at Timeout.emptyReportToSend [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:08:03.697] [ERROR] errLogs - uncaughtException: date.getHours is not a function +[2025-09-23T14:08:03.698] [ERROR] errLogs - TypeError: date.getHours is not a function + at emptyReportToSend (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at Timeout.dailyReportCheck [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1351:5) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:08:03.699] [ERROR] errLogs - uncaughtException: date.getHours is not a function +[2025-09-23T14:08:03.699] [ERROR] errLogs - TypeError: date.getHours is not a function + at emptyReportToSend (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at Timeout.dailyReportCheck [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1351:5) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:08:03.706] [ERROR] errLogs - uncaughtException: date.getHours is not a function +[2025-09-23T14:08:03.707] [ERROR] errLogs - TypeError: date.getHours is not a function + at emptyReportToSend (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at Timeout.dailyReportCheck [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1351:5) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) diff --git a/RVO43/flow/cloudmqttconnect.js b/RVO43/flow/cloudmqttconnect.js new file mode 100755 index 0000000..b03491f --- /dev/null +++ b/RVO43/flow/cloudmqttconnect.js @@ -0,0 +1,357 @@ +exports.id = 'cloudmqttconnect'; +exports.title = 'Cloud connect mqtt'; +exports.group = 'MQTT'; +exports.color = '#888600'; +exports.version = '1.0.2'; +exports.icon = 'sign-out'; +exports.input = 2; +exports.output = 2; +exports.options = { host: 'tb-stage.worksys.io', port: 1883, clientid: "", username: "" }; + +exports.html = `
+
+
+
Hostname or IP address (if not empty - setting will override db setting)
+
+
+
Port
+
+
+
+
+
@(Client id)
+
+
+
topic
+
+
+
`; + + + +const { promisifyBuilder } = require('./helper/db_helper'); +const fs = require('fs'); +const mqtt = require('mqtt'); +const nosql = NOSQL('tbdatacloud'); + +const SEND_TO = { + debug: 0, + rpcCall: 1, +} + +//CONFIG +let saveTelemetryOnError = true;//backup_on_failure overrides this value +//------------------------ + +const noSqlFileSizeLimit = 4194304;//use 5MB - 4194304 +let insertNoSqlCounter = 0; +let insertBackupNoSqlCounter = 0; +let processingData = false; + +let backup_on_failure = true;//== saveTelemetryOnError - create backup client send failure +let restore_from_backup = 50; //how many rows process at once? +let restore_backup_wait = 3;//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; + + +exports.install = function(instance) { + + var client; + var opts; + var clientReady = false; + + let o = {}; //options + + function main() { + loadSettings(); + } + + //set opts according to db settings + function loadSettings() { + + o = instance.options; + if (!o.topic) o.topic = FLOW.GLOBALS.settings.cloud_topic; + + opts = { + host: o.host, + port: o.port, + clientId: o.clientid, + username: o.username, + rejectUnauthorized: false, + resubscribe: false + }; + + console.log("wsmqttpublich -> loadSettings from instance.options", o); + + if (!o.topic) { + instance.status("Not configured", "white"); + console.log("Cloud mqtt connect: no topic selected"); + return; + } + + connectToTbServer(); + } + + function connectToTbServer() { + var url = "mqtt://" + opts.host + ":" + opts.port; + console.log("MQTT URL: ", url); + + client = mqtt.connect(url, opts); + + client.on('connect', function() { + client.subscribe(`${o.topic}_backward`, (err) => { + if (!err) { + console.log("MQTT subscribed"); + } + }); + instance.status("Connected", "green"); + clientReady = true; + sendClientError = true; + }); + + client.on('reconnect', function() { + instance.status("Reconnecting", "yellow"); + clientReady = false; + }); + + client.on('message', function(topic, message) { + // message is type of buffer + message = message.toString(); + if (message[0] === '{') { + TRY(function() { + + message = JSON.parse(message); + if (message.hasOwnProperty("device") && message.hasOwnProperty("data") && message.data.hasOwnProperty("id")) { + client.publish(`${o.topic}_forward`, `{"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 } }); + } + + }, () => instance.debug('MQTT: Error parsing data', message)); + } + + instance.send(SEND_TO.rpcCall, { "topic": o.topic, "content": message }); + }); + + client.on('close', function() { + clientReady = false; + + instance.status("Disconnected", "red"); + instance.send(SEND_TO.debug, { "message": "Client CLOSE signal received !" }); + }); + + client.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) { + console.log('MQTT client error', err); + sendClientError = false; + } + clientReady = false; + }); + + } + + + instance.on('0', function(data) { + + if (clientReady) { + //do we have some data in backup file? if any, process data from database + if (saveTelemetryOnError) { + //read telemetry data and send back to server + if (!processingData) processDataFromDatabase(); + } + + let stringifiedJson = JSON.stringify(data.data) + client.publish(`${o.topic}_forward`, stringifiedJson, { qos: 1 }); + } + 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 (saveTelemetryOnError && o.topic) { + //create new file from tbdata.nosql, if file size exceeds given limit, and clear tbdata.nosql + makeBackupFromDbFile(); + + //write to tb + data.data.id = UID(); + nosql.insert(data.data); + } + } + }); + + instance.on("1", _ => { + main(); + }) + + instance.close = function(done) { + if (clientReady) { + client.end(); + } + }; + + + function getDbBackupFileCounter(type) { + var files = fs.readdirSync(__dirname + "/../databases"); + + let counter = 0; + for (var i = 0; i < files.length; i++) { + + if (files[i] == "tbdatacloud.nosql") continue; + + if (files[i].endsWith(".nosql")) { + + let pos = files[i].indexOf("."); + if (pos > -1) { + + let fileCounter = counter; + let firstDigit = files[i].slice(0, pos); + + fileCounter = parseInt(firstDigit); + if (isNaN(fileCounter)) fileCounter = 0; + //console.log("getDbBackupFileCounter digit:", files[i], firstDigit, fileCounter, isNaN(fileCounter), type); + + if (type == "max") { + if (fileCounter > counter) { + counter = fileCounter; + } + } + else if (type == "min") { + if (counter == 0) counter = fileCounter; + + if (fileCounter < counter) { + counter = fileCounter; + } + } + } + } + + } + + if (type == "max") counter++; + + return counter; + } + + const makeBackupFromDbFile = async () => { + + if (!saveTelemetryOnError) return; + + //to avoid large file: tbdata.nosql + + //init value is 0! + if (insertNoSqlCounter > 0) { + --insertNoSqlCounter; + return; + } + + insertNoSqlCounter = 100; + + let source = __dirname + "/../databases/tbdatacloud.nosql"; + + var stats = fs.statSync(source); + var fileSizeInBytes = stats.size; + + if (fileSizeInBytes > noSqlFileSizeLimit) { + + let counter = 1; + counter = getDbBackupFileCounter("max"); + + let destination = __dirname + "/../databases/" + counter + "." + "tbdatacloud.nosql"; + + //make backup file + fs.copyFileSync(source, destination); + //fs.renameSync(p, p + "." + counter); + + //clear tbdata.nosql + fs.writeFileSync(source, ""); + fs.truncateSync(source, 0); + + } + } + + const processDataFromDatabase = async () => { + + if (restore_from_backup <= 0) return; + + //calculate diff + const now = new Date(); + let currentTime = now.getTime(); + let diff = currentTime - lastRestoreTime; + + if ((diff / 1000) < restore_backup_wait) { + //console.log("*********restore_backup_wait", diff, restore_backup_wait); + return; + } + + processingData = true; + + //get filename to process + let counter = getDbBackupFileCounter("min"); + + //we have some backup files + let dataBase = 'tbdata'; + + var nosql; + if (counter == 0) dataBase = 'tbdatacloud'; + else dataBase = counter + "." + 'tbdatacloud'; + + nosql = NOSQL(dataBase); + + //select all data - use limit restore_from_backup + let records = await promisifyBuilder(nosql.find().take(restore_from_backup)); + + for (let i = 0; i < records.length; i++) { + if (clientReady) { + + let item = records[i]; + let id = item.id; + + if (id !== undefined) { + //console.log("------------processDataFromDatabase - remove", id, dataBase, i); + + try { + + let message = JSON.parse(JSON.stringify(item)); + delete message.id; + client.publish(`${o.topic}_forward`, JSON.stringify(message), { qos: 1 }); + + //remove from database + await promisifyBuilder(nosql.remove().where("id", id)); + + } catch (error) { + //process error + console.log("processDataFromDatabase", error); + } + + } + + } + else { + processingData = false; + return; + } + } + + if (records.length > 0) { + //clean backup file + if (counter > 0) nosql.clean(); + } + + //no data in db, remove + if (records.length == 0) { + if (counter > 0) nosql.drop(); + } + + const d = new Date(); + lastRestoreTime = d.getTime(); + + processingData = false; + + } + + instance.on('options', main); + +}; diff --git a/RVO43/flow/cmd_manager.js b/RVO43/flow/cmd_manager.js new file mode 100755 index 0000000..25912df --- /dev/null +++ b/RVO43/flow/cmd_manager.js @@ -0,0 +1,3071 @@ +exports.id = 'cmd_manager'; +exports.title = 'CMD Manager'; +exports.group = 'Worksys'; +exports.color = '#5D9CEC'; +exports.version = '0.0.3'; +exports.output = ['red', 'blue', 'yellow', 'blue', 'white', 'green']; +exports.input = 3; +exports.icon = 'cloud-upload'; + +exports.html = ` +
+
+
+
RPC - run RPC calls

+
+
+
@(User)
+
+
+
@(Password)
+
+
+
@(My edge)
+
+
+
+`; +exports.readme = `Manager for CMD calls`; + + +exports.install = function(instance) { + + 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, isEmptyObject, emptyJsObject, writeToFile, addToArrayIfUnique } = require('./helper/utils'); + const bitwise = require('bitwise'); + + var SunCalc = require('./helper/suncalc'); + const DataToTbHandler = require('./helper/DataToTbHandler'); + const errorHandler = require('./helper/ErrorToServiceHandler'); + const { sendNotification } = require('./helper/notification_reporter'); + const process = require('process'); + const { errLogger, logger, monitor } = require('./helper/logger'); + + //for accelerometer purposes + const { naklony } = require("../databases/accelerometer_db"); + + const dbNodes = TABLE("nodes"); + const dbRelays = TABLE("relays"); + + let GLOBALS; + let SETTINGS; + let rsPort; + let tbHandler; + + // runTasks intervals + const SHORT_INTERVAL = 30; + const LONG_INTERVAL = 300; + + //send data to following instances: + const SEND_TO = { + debug: 0, + tb: 1, + http_response: 2, + dido_controller: 3, + infoSender: 4, + dailyReport: 5 + } + + 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 + } + + 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 sendNodeReadout = null; // interval for sending agregate data from node + + 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["1"] = minutes; // dimming + priorities["76"] = minutes; // power + + minutes = 5; + priorities["75"] = minutes; // current + priorities["79"] = minutes; // energy + priorities["87"] = minutes; // aktualny cas + //priorities["84"] = minutes; //accelerometer + + minutes = 10; + priorities["74"] = minutes; // voltage + priorities["77"] = minutes; // power factor + priorities["78"] = minutes; // frequency + + minutes = 60; + priorities["0"] = minutes; // statecode + priorities["6"] = minutes; // dusk + priorities["7"] = minutes; // dawn + priorities["8"] = minutes; // profile + + minutes = 60 * 24; + priorities["89"] = minutes; // verzia fw + priorities["80"] = minutes; // lifetime + + //prikazy kt sa budu spustat na dany node - see config.js in terminal-oms.app. (1 - dimming) + let listOfCommands = [0, 1, 6, 7, 8, 74, 75, 76, 77, 78, 79, 80, 87, 89]; + + 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; + + // holds dusk, dawn (and more) values + let sunCalcResult; + + //helper container for counting resolved group of commands (commands related to set profile) + let cmdCounter = {};//key is node, value is counter + + //TODO: is this set working?? According to previous checks, sets do not work + //if sending of profile to node fails, we send notification and push node into set, so we do not send notification twice + const nodeProfileSendFail = new Set(); + + //we expect to get current temperature in Senica from senica-prod01 + let temperatureInSenica = null; + let accelerometerInterval = null; + + //NOTE: daily reports senica: + //rvo_is_on status, we monitor all nodes - if true, power and dimming should be not 0, if false, 24/7 nodes should be 0, other rvo should not respond + let rvo_is_on; + let previous_rvo_is_on_value; + let handleDailyReport; //setInterval for dailyReportHandler function + let dailyReport = {}; //data needed for daily report + let reportToSend = {}; //final report which we send to cloud + let breakerCounter = null; // status of breakers after flow starts is not in report + let rvoPeriod; // interval of checking dusk dawn and if rvo_is_on + let initialReportStatus = false; + + const DAILY_REPORT_HANDLER_TIME = 3_600_000; + const SET_SUNCALC_RESULT_TIME = 3_600_000; + const SET_RVO_PERIOD_TIME = 300_000; + const ADD_NODE_TO_REPORT_TIME = 3_600_000; + + //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); + + let now = new Date(); + console.log("Cmd-mngr installed", now.toLocaleString("sk-SK")); + + sunCalcResult = calculateDuskDawn(); + + handleRsPort(); + + customTasksInterval = setInterval(reportEdgeDateTimeAndNumberOfLuminaires, 120_000); + setTimeout(reportEdgeDateTimeAndNumberOfLuminaires, 4000); + + //dailyReport related + emptyReportToSend(); + breakerCounter = Object.keys(relaysData).length - 1; // we get number of lines (breakers) except of line 0 + rvoPeriod = setInterval(setRvoPeriod, SET_RVO_PERIOD_TIME); + setTimeout(setRvoPeriod, 3000); + setInterval(setSunCalcResult, SET_SUNCALC_RESULT_TIME); + handleDailyReport = setInterval(dailyReportHandler, DAILY_REPORT_HANDLER_TIME); + + + setCorrectTime = setInterval(setCorrectPlcTimeOnceADay, 60000 * 60); // 1 hour + setCorrectPlcTimeOnceADay(); + + sendNodeReadout = setInterval(sendNodesData, 150_000); + accelerometerInterval = setInterval(accelerometerData, 60000 * 30); //30 min + } + + + 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" + //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 + // if node regular readout does not respond, we repeat request + params.repeatCounter = 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-mngr: 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.byte4 = 96; + params.recipient = 1; + params.register = 8; + params.rw = 1;//write + params.timestamp = timestamp; + 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.byte4 = 96; + params.recipient = 1; + params.register = 8; + params.rw = 1;//write + params.timestamp = timestamp; + 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). + */ + + 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.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.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 + { + + logger.debug("processNodeProfile: Threshold lux level for DUSK/DAWN", node); + + let params = getParams(); + params.type = "set_node_profile"; + params.address = node; + params.register = 96; + params.recipient = 1; + params.rw = 1;//write + params.timestamp = timestamp; + 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(); + params.type = "set_node_profile"; + params.address = node; + params.register = 97; + params.recipient = 1; + params.rw = 1;//write + params.timestamp = timestamp; + 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.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); + + 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); + + console.log("proces profile finished *********************") + } + + + 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; + }); + } + + + 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) { + for (let k in nodesData) { + 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`); + } + } + } + + + function loadRelaysData(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 (value.contactor == 1) processAllNodeProfilesOnLine(value.line); + } + } + + + function reportOnlineNodeStatus(line) { + //Po zapnutí línie broadcastovo aktualizovať predtým čas a o 3 sek neskor - status, brightness + + logger.debug("Cmd-mngr: ----->reportOnlineNodeStatus for line", line); + + const d = new Date(); + + // broadcast actual time + let params = getParams(); + params.address = 0xffffffff;//Broadcast + params.byte1 = d.getHours(); + params.byte2 = d.getMinutes(); + params.recipient = 2;//2 broadcast, address = 0 + params.register = 87;//Actual time + params.rw = 1;//write + params.type = "node-onetime-write"; + params.timestamp = d.getTime() + 30000; + params.info = "run broadcast: Actual time"; + //params.debug = true; + + tasks.push(params); + + let sec = 3; + setTimeout(function() { + //Po zapnutí línie - spraviť hromadný refresh stavu práve zapnutých svietidiel + + let time = Date.now(); + + for (let k in nodesData) { + + //potrebujem nody k danej linii + 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].node_status_before_offline === true || nodesData[k].status === true) { + status = "OK"; + nodesData[k].time_of_last_communication = time; + } + + nodesData[k].readout.status = status; + + updateNodeStatus(k, status === "OK" ? true : false); + if (nodesData[k].hasOwnProperty("node_status_before_offline")) delete nodesData[k].node_status_before_offline; + sendTelemetry({ status: status }, tbname, time); + + //vyreportovanie dimming, current, input power pre liniu pre vsetky nody + //Prud + { + let params = getParams(); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 75;//prud + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = time + 4000; + params.info = 'read current'; + //params.debug = true; + tasks.push(params); + } + + //vykon + { + let params = getParams(); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 76;//výkon + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = time + 4100; + params.info = 'read power'; + //params.debug = true; + + tasks.push(params); + } + //dimming + { + let params = getParams(); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 1;//dimming + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = time + 4200; + params.info = 'read dimming'; + //params.debug = true; + + tasks.push(params); + } + + } + } + + }, sec * 1000); + } + + + function reportOfflineNodeStatus(line) { + + logger.info("Cmd-mngr: ------>reportOffLineNodeStatus for line ", line); + + values = {}; + values["dimming"] = 0;//brightness + values["power"] = 0;//výkon + values["current"] = 0;//prúd + values["status"] = "OFFLINE"; + + const date = Date.now(); + + Object.keys(nodesData).forEach(node => { + + //potrebujem nody k danej linii + if (line == nodesData[node].line || line == undefined) { + + let tbname = nodesData[node].tbname; + let nodeStatus = nodesData[node].status; + + //in case we have reported offline node status, we return (continue with next node) + if (nodeStatus === "OFFLINE") return; + + nodesData[node].node_status_before_offline = nodeStatus; + nodesData[node].status = "OFFLINE"; + nodesData[node].readout = {}; + + sendTelemetry({ ...values }, tbname, date); + } + }); + + } + + + function turnLine(onOrOff, line, info) { + let obj = { + line: line, + command: onOrOff, + info: info + }; + + //to assure, handleDailyReportFunction do not run before rvo_is_on variable changes. So after every line switch we reset the timer + clearInterval(handleDailyReport); + handleDailyReport = setInterval(dailyReportHandler, DAILY_REPORT_HANDLER_TIME); + + //logger.debug("linia", line, obj); + instance.send(SEND_TO.dido_controller, obj); + } + + + 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"; + 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]) { + //CRC_ERROR + message = "NOK"; + error = "CRC_ERROR c1"; + instance.send(SEND_TO.debug, "CRC_ERROR c1"); + } + + 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") { + instance.send(SEND_TO.debug, bytes); + instance.send(SEND_TO.debug, "RESPONSE " + type + " - " + bytes[4]); + + //logger.debug(SEND_TO.debug, "RESPONSE " + type + " - " + bytes[4], bytes); + + error = "type is: " + type; + + message = "NOK"; + } + + return { message, type, error }; + } + + + //BUILD TASKS// + function buildTasks(params) { + + //return; + console.log("buidTAaasks start ****************", params); + monitor.info("buildTasks - params", params); + + let processLine; //defined line + let init = false; + let processLineProfiles = true; + let processBroadcast = true; + let processNodes = true; + + if (params == undefined) { + init = true; + tasks = []; + logger.debug("-->buildTasks clear tasks"); + } + else { + processLineProfiles = params.processLineProfiles; + processBroadcast = false; + processNodes = false; + + processLine = params.line; + } + + let now = new Date(); + + //process line profiles + if (processLineProfiles) { + + let keys = Object.keys(relaysData); + + for (let i = 0; i < keys.length; i++) { + + let line = parseInt(keys[i]); + let profilestr = relaysData[line].profile; + + if (processLine != undefined) { + if (processLine != line) continue; + } + + try { + + /** + * we process line profiles: timepoints, astro clock, lux_sensor, offsets ... + */ + if (profilestr === "") throw ("Profile is not defined"); + let profile = JSON.parse(profilestr); + 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; + + // add name to regular profile timepoint and delete unused end_time key: + time_points.forEach(point => { + point.name = "profileTimepoint" + delete point.end_time; + }); + + //monitor.info("buildTasks: time_points", time_points); + + + /** + * 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 astro clock true, we remove all regular profile points + time_points = []; + + //TODO: when astro clock == true, is offset calculated ??? + //let duskAstroClockOffset = profile.dusk_astro_clock_offset; + //let dawnAstroClockOffset = profile.dawn_astro_clock_offset; + //console.log("line astro clock offsets dusk a dawn: ", duskAstroClockOffset, dawnAstroClockOffset); + // maybe add dusk dawn offset to calculateDuskDawn ?? what dusk dawn will be if dawn_lux_sensor == true?? + //let sunCalcResult = calculateDuskDawn(new Date(), line, duskAstroClockOffset, dawnAstroClockOffset); + + 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 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); + + 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); + + 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(':'); + + let ad = new Date(); + ad.setHours(parseInt(ahours), parseInt(aminutes), 0); + + let bd = new Date(); + bd.setHours(parseInt(bhours), parseInt(bminutes), 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++) { + + let start_time = new Date(); + let [hours, minutes] = time_points[t].start_time.split(':'); + start_time.setHours(parseInt(hours), parseInt(minutes), 0); + + //task is in 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(); + params.type = "relay"; + params.line = parseInt(line); + params.value = time_points[t].value; + params.tbname = relaysData[line].tbname; + params.timestamp = start_time.getTime(); + + // 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; + + //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)) { + 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; + + params.debug = true; + + //turn on/off line + tasks.push(params); + monitor.info("TimePoint params: ", params.info, start_time); + } + + monitor.info("-->time_points final", line, time_points); + + //ensure to turn on/off according to calculated currentValue + let params = getParams(); + params.type = "relay"; + params.line = parseInt(line); + params.tbname = relaysData[line].tbname; + params.value = currentValue; + params.timestamp = i; + params.debug = true; + + //logger.debug(now.toLocaleString("sk-SK")); + 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; + + tasks.push(params); + + } catch (error) { + if (profilestr !== "") { + //errLogger.error(profilestr, error); + console.log(`Cmd_mngr: Unable to process line profile ${line}. Error: `, error); + errorHandler.sendMessageToService(profilestr + "-" + error, 0, "js_error"); + } else { + turnLine("off", line, "No line profile. Switching it off on startup"); + } + } + + } + //logger.debug("tasks:"); + //logger.debug(tasks); + } + + + //NOTE: PROCESS DEFAULT BROADCASTS - Time of dusk, Time of dawn, Actual Time + if (processBroadcast) { + + let d = new Date(); + let time = d.getTime(); + //let sunCalcResult = calculateDuskDawn(); + + { + let params = getParams(); + + params.address = 0xffffffff;//broadcast + params.byte1 = sunCalcResult["dusk_hours"]; + params.byte2 = sunCalcResult["dusk_minutes"]; + params.recipient = 2;//2 broadcast, + params.register = 6;//Time of dusk + params.rw = 1;//write + params.type = "node-regular-write"; + params.timestamp = time + 60000; + params.addMinutesToTimestamp = 60 * 3; //kazde 3 hodiny zisti novy dusk + params.info = "Broadcast-duskTime"; + + tasks.push(params); + } + + { + let params = getParams(); + + params.address = 0xffffffff;//broadcast + params.byte1 = sunCalcResult["dawn_hours"]; + params.byte2 = sunCalcResult["dawn_minutes"]; + params.recipient = 2; //2 broadcast + params.register = 7;//Time of dawn + params.rw = 1;//write + params.type = "node-regular-write"; + params.timestamp = time + 60001; + params.addMinutesToTimestamp = 60 * 3; //kazde 3 hodiny zisti novy dawn + params.info = "Broadcast-dawnTime"; + + tasks.push(params); + } + + { + let params = getParams(); + + params.address = 0xffffffff;//broadcast + params.byte1 = d.getHours(); + params.byte2 = d.getMinutes(); + params.recipient = 2; //2 broadcast + params.register = 87;//Actual time + params.rw = 1;//write + params.type = "node-regular-write"; + params.timestamp = time + 60002; + params.addMinutesToTimestamp = 5; + params.info = "run broadcast: Actual time"; + + tasks.push(params); + } + + } + + //process nodes & tasks - read node's data + if (processNodes) { + + let time = Date.now(); + + for (let k in nodesData) { + let address = parseInt(k); + let tbname = nodesData[k].tbname; + let register = 0; + + for (let i = 0; i < listOfCommands.length; i++) { + + register = listOfCommands[i]; + let addMinutesToTimestamp = priorities[register]; + + let params = getParams(); + + params.address = address; + params.recipient = 1; + params.register = register; + params.type = register == 1 ? "node-dimming-read" : "node-regular-read"; + params.tbname = tbname; + params.timestamp = time + 5000 + i * 500 + addMinutesToTimestamp * 1000; //to make slight time difference + params.addMinutesToTimestamp = addMinutesToTimestamp; + params.info = "Node regular read command"; + + tasks.push(params); + } + + } + } + + + //niektore ulohy sa vygeneruju iba 1x pri starte!!! + if (!init) return; + + + //Master node FW version - modifies SETTINGS.masterNodeIsResponding + { + let params = getParams(); + params.type = "cmd-master"; + params.register = 4; + params.address = 0; + params.timestamp = 0; + params.addMinutesToTimestamp = 5; + params.tbname = SETTINGS.rvoTbName; + params.info = "Master node FW verzia"; + //params.debug = true; + + tasks.push(params); + } + + //kazdu hodinu skontrolovat nastavenie profilov + { + let params = getParams(); + params.type = "process_profiles"; + params.timestamp = Date.now() + 60001; + params.addMinutesToTimestamp = 60;//60 = every hour + params.info = "detekcia nespracovaných profilov linie a nodov"; + //params.debug = true; + + tasks.push(params); + } + + monitor.info("tasks created:", tasks.length); + } + + + /** + * We process line profile, where "astro_clock": true + * example profile: + * + "dawn_lux_sensor": true, + "dusk_lux_sensor": true, + "dawn_lux_sensor_value": 5, + "dusk_lux_sensor_value": 5, + "dawn_astro_clock_offset": 0, + "dusk_astro_clock_offset": 10, + "dawn_lux_sensor_time_window": 30, + "dusk_lux_sensor_time_window": 30, + "dawn_astro_clock_time_window": 60, + "dusk_astro_clock_time_window": 60 + + * if dawn: if currentTimestamp is in timewindow "dawnTime + and - dawn_lux_sensor_time_window" and lux value >= lux_sensor_value, we switch off the line. + * if dusk: we do oposite + * + * dawn: usvit - lux je nad hranicou - vypnem + * dusk: sumrak - lux je pod hranicou - zapnem + */ + 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++) { + + let line = keys[i]; //line is turned off by default + let profilestr = relaysData[line].profile; + const contactor = relaysData[line].contactor; + + try { + + let profile = JSON.parse(profilestr); + if (Object.keys(profile).length === 0) throw ("turnOnOffLinesAccordingToLuxSensor - profile is not defined"); + + 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 (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"); + } + } + } + + //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 (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"); + } + } + } + + } + + } catch (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) { + //MASTER + if (node == 0) return; + + let nodeObj = nodesData[node]; + if (nodeObj == undefined) return; + + let nodeCurrentStatus = nodeObj.status; + const now = Date.now(); + + let data = null; + + if (nodeCurrentStatus === "OFFLINE") { + data = { status: newStatus }; + nodeDbStatusModify(node, data); + return; + } + else 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; + } + + } + + + 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 }; + } + }); + }); + } + + + function processDailyReport() { + + const now = Date.now(); + + for (const [key, value] of Object.entries(dailyReport)) { + + if (["name", "time", "dusk_and_dawn"].includes(key)) continue; + + let poleNumber = nodesData[key]["pole_number"]; + let line = dailyReport[key].line; + let nodeType = nodesData[key]["node_type"]; + let fullNodeName = key // key == nodeNumber + + if (poleNumber && nodeType) { + fullNodeName = SETTINGS.rvo_number + "/" + poleNumber + "_" + line + "L_" + key + "_" + nodeType; + } else { + fullNodeName = key; + } + + if (rvo_is_on) { + + if (value.initialTs) { + if (value.initialTs + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["night_no_data"], fullNodeName); + console.log('report nedostava ziadne data uz hodinu', fullNodeName); + value.initialTs = now; + } + } + if (value.dimmingIsZeroTime) { + if (value.dimmingIsZeroTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["night_dimming=0"], fullNodeName); + console.log("report node dimming je 0 ale ma svietit", fullNodeName); + value.dimmingIsZeroTime = now; + } + } + if (value.powerIsZeroTime) { + if (value.powerIsZeroTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["night_power=0"], fullNodeName); + console.log("report node power je 0 ale ma svietit", fullNodeName); + value.powerIsZeroTime = now; + } + } + + } else { + + let contactorStatus = relaysData[line].contactor; + if (contactorStatus === 1) { + + if (value.initialTs) { + if (value.initialTs + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["day_24/7_no_data"], fullNodeName); + console.log('node je na 24/7 ale nedostava ziadne data uz hodinu', fullNodeName); + value.initialTs = now; + } + } + if (value.dimmingIsOnButShouldBeOffTime) { + if (value.dimmingIsOnButShouldBeOffTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["day_24/7_dimming>0"], fullNodeName); + console.log("report dimming je > 0 ale nema svietit", fullNodeName); + value.dimmingIsOnButShouldBeOffTime = now; + } + } + if (value.powerIsOnButShouldBeOffTime) { + if (value.powerIsOnButShouldBeOffTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["day_24/7_power>0"], fullNodeName); + console.log("report power je > 0 ale nema svietit", fullNodeName); + value.powerIsOnButShouldBeOffTime = now; + } + } + + } + + } + + } + + let report = {}; + report["name"] = SETTINGS.rvo_name; + report["time"] = new Date(); + report["report"] = reportToSend; + + writeToFile(F.path.root("report_data.log"), report, true); + instance.send(SEND_TO.dailyReport, report); + } + + + function dailyReportHandler() { + + if (!SETTINGS.daily_report) return; + + // after dawn we empty reportToSend and start to get data for a new day + const date = new Date(); + const hour = date.getHours(); + const minute = date.getMinutes(); + + console.log("now: ", hour, minute, "suncalc: ", sunCalcResult.dawn_hours, sunCalcResult.dawn_minutes); + + if (hour === sunCalcResult.dawn_hours) { + + //NOTE: ak je este pred usvitom, spracujeme report a posleme na cloud, ak uz je po usvite, resetujeme report plnime data noveho dna + if (minute >= sunCalcResult.dawn_minutes - 2) { + emptyReportToSend(); + emptyDailyReport(); + console.log("Podmienka 1 v dailyReport handler"); + } else { + processDailyReport(); + emptyReportToSend(); + emptyDailyReport(); + console.log("Podmienka 2 v dailyReport handler"); + } + + initialReportStatus = true; + + // ak sa funkcia spusti o hodinu alebo 2 neskor, ako je usvit (moze sa to stat, kedze kazde zapnutie/vypnutie linii odznova spusti casovac. + } else if (hour === sunCalcResult.dawn_hours + 1 || hour === sunCalcResult.dawn_hours + 2) { + if (!initialReportStatus) { + emptyReportToSend(); + emptyDailyReport(); + initialReportStatus = true; + console.log("Podmienka 3 v dailyReport handler"); + } else { + processDailyReport(); + initialReportStatus = true; + console.log("Podmienka 4 v dailyReport handler"); + } + } else { + processDailyReport(); + initialReportStatus = false; + console.log("Podmienka 5 v dailyReport handler"); + } + + console.log("initialReportStatus: ", initialReportStatus); + + } + + function emptyReportToSend() { + emptyJsObject(reportToSend); + reportToSend["contactor"] = { off: [], on: [] }; + reportToSend["night_no_data"] = []; + reportToSend["night_dimming=0"] = []; + reportToSend["night_power=0"] = []; + reportToSend["day_24/7_no_data"] = []; + reportToSend["day_24/7_dimming>0"] = []; + reportToSend["day_24/7_power>0"] = []; + console.log(`resetuje sa reportToSend`); + } + + + //NOTE: ked je initialTs stale rovnaky a zistime ze linie su vypnute (relaysData.line.contactor) - zistim, ci je node na tej linii. Vieme, ze ak je linia vypnuta je to v poriadku lebo nie je na 24/7 linii + //ak je na 24/7 linii, reportujeme, ze neprijima data + function emptyDailyReport() { + const ts = Date.now(); + emptyJsObject(dailyReport); + + //NOTE: do dailyReport dame vsetky nody a pravidelne kontrolujeme ci maju data + //ked nastane sumrak/usvit a svetla maju zacat/prestat svietit, dailyReport spravime nanovo: + for (const [key, value] of Object.entries(nodesData)) { + dailyReport[value.node] = { line: value.line, initialTs: ts }; + } + + console.log("dailyReport: ", dailyReport); + } + + + async function runTasks() { + + clearInterval(interval); + + let currentTimestamp = Date.now(); + + //sort tasks based on timestamp + 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) { + instance.send(SEND_TO.debug, "no tasks created"); + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + if (!rsPort.isOpen) { + instance.send(SEND_TO.debug, "!rsPort.isOpen"); + //await rsPort.open(); + //console.log("Cmd-mngr: !rsPort.isOpen"); + } + + let currentTask = tasks[0]; + + if (currentTask.debug) { + //logger.debug("--->task to process", currentTask); + } + + if (currentTask.timestamp <= currentTimestamp) { + let params = { ...tasks[0] }; + + //allow terminal commands + if (SETTINGS.maintenance_mode && params.type !== "cmd-terminal") { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + let type = params.type; + let tbname = params.tbname; + let node = params.address; + let register = params.register; + let line = null; + let itIsNodeCommand; + + if (nodesData[node] !== undefined) { + line = nodesData[node].line; + itIsNodeCommand = true; + } + + if (params.line !== undefined) line = params.line; + + if (params.addMinutesToTimestamp > 0 || params.timePointName) { + tasks[0].timestamp = currentTimestamp + tasks[0].addMinutesToTimestamp * 60000; + } else { + tasks.shift(); + } + + //kontrola nespracovanych profilov nodov + //TODO: co ked niektore nody neprijimaju profily? kazdu hodinu zahltuju "tasks" array + if (type == "process_profiles") { + //na vsetky zapnutych liniach sa spracuju nespracovane profily nodov + loadRelaysData(); + interval = setInterval(runTasks, SHORT_INTERVAL); + return; + } + + //relay + if (type == "relay") { + + const timePointName = params.timePointName; + const value = params.value; + + let date = new Date(); + date.setDate(date.getDate() + 1);//next day + + let sunCalcResult; + if (timePointName) sunCalcResult = calculateDuskDawn(date, params.line); + + + if (timePointName == "dawn") { + tasks[0].timestamp = sunCalcResult.dawn_time; + } + else if (timePointName == "dusk") { + tasks[0].timestamp = sunCalcResult.dusk_time; + } + else if (timePointName == "luxOn") { + tasks[0].timestamp = sunCalcResult.dusk_time + params.dusk_lux_sensor_time_window * 60000; + } + else if (timePointName == "luxOff") { + tasks[0].timestamp = sunCalcResult.dawn_time + params.dawn_lux_sensor_time_window * 60000; + } + else if (timePointName == "profileTimepoint") { + tasks[0].timestamp = currentTimestamp + tasks[0].addMinutesToTimestamp * 60000; + } + + let info = "aplikovany bod profilu"; + let onOrOff = ""; + value == 1 ? onOrOff = "on" : onOrOff = "off"; + + turnLine(onOrOff, params.line, info); + + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + if (!SETTINGS.masterNodeIsResponding) { + //ak neodpoveda, nebudeme vykonavat ziadne commands, okrem cmd-terminal cmd-master + errorHandler.sendMessageToService("Master node is not responding"); + + let stop = true; + + if (type === "cmd-terminal" || type === "cmd-master") stop = false; + if (stop) { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + } + + let contactorStatus = 1; + if (relaysData[line] != undefined) contactorStatus = relaysData[line].contactor; + + if (line === 0 || contactorStatus === 0 || FLOW.deviceStatus.state_of_breaker[line] === "Off") { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + // TODO: -> status offline for rvo if rotary_switch_state is OFF, this is source of errors + // check if rotary_switch_state == "Off" + // state_of_braker: disconnected = true? + + if (!rsPort.isOpen) { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + //RE-CALCULATE VALUES + //set actual time for broadcast + if (register == 87 && params.recipient === 2) { + var d = new Date(); + params.byte1 = d.getHours();//h + params.byte2 = d.getMinutes();//m + } + + //SET DUSK/DAWN FOR BROADCAST + //Time of dusk + if (register == 6 && params.recipient === 2) { + + if (type != "cmd-terminal") { + params.byte1 = sunCalcResult["dusk_hours"];//h + params.byte2 = sunCalcResult["dusk_minutes"];//m + } + } + + //Time of dawn + if (register == 7 && params.recipient === 2) { + if (type != "cmd-terminal") { + params.byte1 = sunCalcResult["dawn_hours"];//h + params.byte2 = sunCalcResult["dawn_minutes"];//m + } + } + //----------------------- + + instance.send(SEND_TO.debug, "address: " + node + " register:" + register + "type: " + type); + + var startTime, endTime; + startTime = new Date(); + + let saveToTb = true; + if (!tbname) saveToTb = false; + + let resp = com_generic(node, params.recipient, params.rw, register, params.name, params.byte1, params.byte2, params.byte3, params.byte4); + let readBytes = 11; + let timeout = 4000; + + + // await keyword is important, otherwise incorrect data is returned! + await writeData(rsPort, resp, readBytes, timeout).then(function(data) { + + //sometimes happens, that status of node changes to OK, NOK even if line was turned off and should be status OFFLINE. To prevent this, we return if line contactor is 0: + if (itIsNodeCommand && line && relaysData[line].contactor !== 1) return; + + 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); + + //ak sa odpoved zacina 0 - je to v poriadku, inak je NOK + let message = result.message; // OK, NOK + let message_type = result.type; + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + console.log("detected response:", result); + logger.debug("Cmd-mngr: writeData done " + message_type + " duration: " + timeDiff + " type: " + params.debug, params, result); + } + } + + let values = {}; + + //CMD FINISHED + if (message == "OK") { + + updateNodeStatus(node, true); + + //write + if (type == "set_node_profile") { + let result = cmdCounterResolve(node); + if (result == 0) { + dbNodes.modify({ processed: true }).where("node", node).make(function(builder) { + builder.callback(function(err, response) { + + sendNotification("Cmd-mngr: process cmd", SETTINGS.rvoTbName, "dimming_profile_was_successfully_received_by_node", { node: node }, "", SEND_TO.tb, instance); + + logger.debug("--> profil úspešne odoslaný na node č. " + node); + nodesData[node].processed = true; + nodeProfileSendFail.delete(node); + }); + }); + } + } + + //parse read response + if (params.rw == 0) { + values = processResponse(register, dataBytes); //read + } + + if (itIsNodeCommand) { + values.comm_status = "OK"; + values.status = "OK"; + nodesData[node].readout = { ...nodesData[node].readout, ...values }; + + + if (SETTINGS.daily_report) { + //TODO: co ak nedostavame odpovede z nodu ? Musime vyreportovat!! + //v dailyReport teda musi byt kompletny zoznam nodov a neustale kontrolovat, ci maju data, ak nie report node - neodpoveda + if (register === 1) { + + let now = Date.now(); + + if (rvo_is_on === true) { + + if ("dimmingIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].dimmingIsOnButShouldBeOffTime; + + if (values.dimming > 0) { + if ("dimmingIsZeroTime" in dailyReport[node]) delete dailyReport[node].dimmingIsZeroTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if (!("dimmingIsZeroTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], dimmingIsZeroTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } else { + + if ("dimmingIsZeroTime" in dailyReport[node]) delete dailyReport[node].dimmingIsZeroTime; + + if (values.dimming > 0) { + if (!("dimmingIsOnButShouldBeOffTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], dimmingIsOnButShouldBeOffTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if ("dimmingIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].dimmingIsOnButShouldBeOffTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } + } + + if (register === 76) { + + let now = Date.now(); + + if (rvo_is_on === true) { + + if ("powerIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].powerIsOnButShouldBeOffTime; + + if (values.power > 1) { + if ("powerIsZeroTime" in dailyReport[node]) delete dailyReport[node].powerIsZeroTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if (!("powerIsZeroTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], powerIsZeroTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } else { + + if ("powerIsZeroTime" in dailyReport[node]) delete dailyReport[node].powerIsZeroTime; + + if (values.power > 1) { + if (!("powerIsOnButShouldBeOffTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], powerIsOnButShouldBeOffTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if ("powerIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].powerIsOnButShouldBeOffTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } + } + } + + } + + //master node + if (node == 0) { + sendNotification("Cmd-mngr: 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; + } + + if (params.debug) { + //logger.debug("saveToTb", saveToTb, tbname, values); + } + + if (saveToTb && type != "node-regular-read") { + sendTelemetry(values, tbname); + } + else { + if (type == "cmd-terminal") { + terminalCommandResponse(params, "SUCCESS", data); + } + } + + } + else { + terminalCommandResponse(params, "ERROR", data); + handleNokResponseOnRsPort("handleNOK else block", params, itIsNodeCommand, saveToTb); + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + //logger.debug("writeData err: ", error, result, params); + logger.debug("writeData err: ", tbname, node, register, values); + } + } + + //logger.debug(error, result, params); + } + }).catch(function(reason) { + + //console.log("writeData catch exception", reason); + instance.send(SEND_TO.debug, reason); + + terminalCommandResponse(params, "FAILURE", null, reason); + handleNokResponseOnRsPort("handleNOK catch block", params, itIsNodeCommand, saveToTb); + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + logger.debug("-->WRITE FAILED: " + reason, params.debug, params); + } + } + + }); + + } + 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); + } + + + // if node does not respond to request, we repeat request 3 times: + function repeatCommand(params) { + params.repeatCounter++; + if (params.repeatCounter < 4) { + params.timestamp = 0; + params.addMinutesToTimestamp = 0; + tasks.push(params); + } + } + + function handleNokResponseOnRsPort(message, params, itIsNodeCommand, saveToTb) { + + let node = params.address; + let register = params.register; + let type = params.type; + let tbName = params.tbname; + if (!tbName) return; + + let values = {}; + + let updateStatus = updateNodeStatus(node, false); + + if (itIsNodeCommand) { + values.comm_status = "NOK"; + nodesData[node].readout.comm_status = "NOK"; + repeatCommand(params); + } + + if (updateStatus) { + values.status = "NOK"; + nodesData[node].readout.status = "NOK"; + } + + if (type === "node-regular-read") return; + + //master node + if (node == 0) { + sendNotification("Cmd-mngr: 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; + + if (register == 4) values["master_node_version"] = "NOK"; + } + + if (type == "set_node_profile") { + delete cmdCounter[node]; + logger.debug("profil nebol úspešne odoslaný na node č. ", params); + + if (!nodeProfileSendFail.has(node)) { + sendNotification("Cmd-mngr: process cmd", tbName, "configuration_of_dimming_profile_to_node_failed", { node: node }, "", SEND_TO.tb, instance); + nodeProfileSendFail.add(node); + } + } + + // console.log("------",node, register, type, itIsNodeCommand, updateStatus, saveToTb, values); + if (saveToTb) { + sendTelemetry(values, tbName); + } + + } + + + function sendNodesData() { + Object.keys(nodesData).forEach(node => { + if (nodesData[node]["status"] !== "OFFLINE") { + sendTelemetry(nodesData[node].readout, nodesData[node].tbname); + nodesData[node].readout = {}; + } + }) + } + + + /** + * 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; + } + + 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); + + //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 === "OFFLINE") { + nodeObj.node_status_before_offline === true ? number_of_ok_luminaires++ : number_of_nok_luminaires++; + } + else if (nodeObj.status == true) 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 - ts % 60000 //round to full minute + }; + + sendTelemetry(values, SETTINGS.rvoTbName, ts); + } + + + function setSunCalcResult() { + //if next day, we get new dusk and dawn. To make sure, in local timezone 2:00 means 00:00 in utc (it means next day) + if (new Date().getHours() === 2) { + sunCalcResult = calculateDuskDawn(); + console.log("Novy suncalc: ", sunCalcResult); + } + } + + + function setRvoPeriod() { + + if (!SETTINGS.daily_report) return; + + const ts = Date.now(); + + previous_rvo_is_on_value = rvo_is_on; + + if (ts < sunCalcResult.dawn_time - 1_800_000) { // nodes should be on (00:00 -> 06:00 ( - pol hodina, lebo rvo vypina skor) + rvo_is_on = true; + } else if (sunCalcResult.dawn_time - 1_800_000 < ts && ts < sunCalcResult.dusk_time + 1_800_000) { // nodes should be off 06:00 -> 21:00 + rvo_is_on = false; + } else if (sunCalcResult.dusk_time + 1_800_000 < ts) { // nodes should be on 21:00 -> 00:00 + rvo_is_on = true; + } + + if (previous_rvo_is_on_value !== rvo_is_on) { + emptyDailyReport(); + console.log("rvo_is: ", rvo_is_on, previous_rvo_is_on_value); + } + } + + + function handleRsPort() { + + if (rsPort) { + rsPort.removeAllListeners(); + rsPort = null; + } + + //! 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-mngr: rsPort opened success"); + + 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); + + }).catch(function(reason) { + instance.send(SEND_TO.debug, "Cmd-mngr: RPC runSyncExec - promise rejected:" + reason); + }); + }); + + rsPort.on('error', function(err) { + errorHandler.sendMessageToService([exports.title, "unable to open port", SETTINGS.serial_port, err.message], 0); + monitor.info("Cmd-mngr: Error on rsPort", err.message); + }); + + rsPort.on("close", () => { + monitor.info("Cmd-mngr: rsPort closed, reconnecting..."); + setTimeout(handleRsPort, 1000); + }); + + rsPort.open(); + } + + + instance.on("close", () => { + clearInterval(interval); + clearInterval(customTasksInterval); + clearInterval(setCorrectTime); + clearInterval(sendNodeReadout); + clearInterval(accelerometerInterval); + rsPort.close(); + }); + + instance.on("0", _ => { + main(); + }) + + + instance.on("2", _ => { + console.log("dailyReport, reportToSend, rvo_is_on", dailyReport, reportToSend, rvo_is_on, previous_rvo_is_on_value); + }) + + instance.on("1", 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(); + return; + } + else if (flowdata.data == "close") { + rsPort.close(); + return; + } + else if (flowdata.data == "clean") { + tasks = []; + return; + } + else if (flowdata.data == "buildtasks") { + //build & run + return; + } + else if (flowdata.data == "run") { + //durations = []; + + if (tasks.length == 0) { + + buildTasks(); + + if (rsPort.isOpen) { + interval = setInterval(runTasks, 100); + } + else { + instance.send(SEND_TO.debug, "port is not opened!!!"); + } + } + } + else { + //terminal data - object + //logger.debug("flowdata", flowdata.data); + + if (typeof flowdata.data === 'object') { + //logger.debug("dido", flowdata.data); + if (flowdata.data.hasOwnProperty("sender")) { + //data from dido_controller + if (flowdata.data.sender == "dido_controller") { + + if (flowdata.data.hasOwnProperty("cmd")) { + let cmd = flowdata.data.cmd; + + if (cmd == "buildTasks") { + clearInterval(interval); + + logger.debug("-->Cmd-mngr: BUILD TASKS"); + buildTasks(); + + //logger.debug("tasks:"); + //logger.debug(tasks); + + logger.debug("-->Cmd-mngr: RUN TASKS"); + interval = setInterval(runTasks, 5000); + } + else if (cmd == "reload_relays") { + loadRelaysData(flowdata.data.line); + + if (flowdata.data.dataChanged) { + if (!flowdata.data.value) { + reportOfflineNodeStatus(flowdata.data.line); + } + else { + reportOnlineNodeStatus(flowdata.data.line); + } + } + + } + else if (cmd == "rotary_switch_state") { + let value = flowdata.data.value; + + //state was changed + if (rotary_switch_state != value) { + if (value == "Off") { + //vyreportovat vsetky svietdla + reportOfflineNodeStatus(); + } + + rotary_switch_state = value; + } + } + 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) { + + // we send lux_sensor value to all nodes: + let params = getParams(PRIORITY_TYPES.node_broadcast); + + params.recipient = 2;//2 broadcast, address = 0 + params.address = 0xffffffff;//Broadcast + + let ba = longToByteArray(lux_sensor); + + params.byte3 = ba[1];//msb + params.byte4 = ba[0]; + params.timestamp = PRIORITY_TYPES.node_broadcast; + params.info = "run broadcast: Actual Lux level from cabinet"; + params.register = 95;//Actual Lux level from cabinet + params.rw = 1;//write + + tasks.push(params); + + //process profiles + turnOnOffLinesAccordingToLuxSensor(lux_sensor); + } + } + else if (cmd == "state_of_breaker") { + //istic linie + + breakerCounter--; + + let value = flowdata.data.value; + let line = parseInt(flowdata.data.line); + + let dataChanged = false; + if (state_of_breaker[line] != value) dataChanged = true; + + state_of_breaker[line] = value; + + let status = "OK"; + if (value == "Off") status = "NOK"; + + if (dataChanged) { + + if (relaysData.hasOwnProperty(line)) { + let tbname = relaysData[line].tbname; + + if (value == "Off") { + sendNotification("Cmd-mngr: onData", tbname, "circuit_breaker_was_turned_off_line", { line: line }, "", SEND_TO.tb, instance, "circuit_breaker"); + if (breakerCounter < 0) reportToSend["contactor"]["off"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + else { + sendNotification("Cmd-mngr: onData", tbname, "circuit_breaker_was_turned_on_line", { line: line }, "", SEND_TO.tb, instance, "circuit_breaker"); + if (breakerCounter < 0) reportToSend["contactor"]["on"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + + //report status liniu + sendTelemetry({ status: status }, tbname) + + //current value + if (value == "Off") reportOfflineNodeStatus(line); //vyreportovat vsetky svietidla na linii + } + + } + } + else { + logger.debug("undefined cmd", cmd); + } + } + } + + return; + } + + //data from worksys + if (flowdata.data.hasOwnProperty("topic")) { + + let data = getNested(flowdata.data, "content", "data"); + + //if we get temperature in senica from senica-prod01 + let temperature = getNested(flowdata.data, "content", "senica_temperature"); + + if (temperature !== undefined) { + temperatureInSenica = temperature; + return; + } + + if (data === undefined) { + console.log("Invalid rpc command came from platform"); + return; + } + + let command = data.params.command; + let method = data.method; + let profile = data.params.payload; + if (profile == undefined) profile = ""; + let entity = data.params.entities[0]; + let entity_type = entity.entity_type; + let tbname = entity.tb_name; + + instance.send(SEND_TO.debug, flowdata.data); + 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") { + + //let command = data.params.command; + let value = data.params.payload.value; + + if (command == "dimming") { + + let nodeWasFound = false; + let keys = Object.keys(nodesData); + + //logger.debug("-----", keys); + + 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); + + value = parseInt(value); + if (value > 0) value = value + 128; + + params.type = "node-onetime-write"; + params.tbname = tbname; + params.address = node; + params.register = 1; + params.recipient = 1; + params.byte4 = value; + params.rw = 1; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'set dimming from platform'; + //params.debug = true; + + //debug(params); + logger.debug("dimming", params); + + tasks.push(params); + + 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); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 1; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read dimming (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + //pridame aj vyreportovanie - vykon + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 76; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read Input Power (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + //pridame aj vyreportovanie - prud svietidla + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 75; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read Input Current (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + //pridame aj vyreportovanie - power faktor - ucinnik + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 77; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read power factor (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + }, 4000); + + nodeWasFound = true; + break; + } + } + + if (!nodeWasFound) { + logger.debug("set dimming from platform", "unable to find tbname", tbname); + } + } + else { + instance.send(SEND_TO.debug, "undefined command " + command); + logger.debug("undefined command", command); + } + + return; + } + 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++) { + let node = keys[i]; + if (tbname == nodesData[node].tbname) { + + 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"); + + //profil úspešne prijatý pre node č. xx + sendNotification("Cmd-mngr", tbname, "dimming_profile_was_processed_for_node", { node: node }, profile, SEND_TO.tb, instance); + + nodesData[node].processed = false; + nodesData[node].profile = profile; + + processNodeProfile(node); + }); + }); + } + } + } + else { + + instance.send(SEND_TO.debug, "unknown method " + method); + logger.debug("unknown method", method); + + return; + } + } + + //nastav profil linie z platformy + 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") { + + 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++) { + let line = keys[i]; + if (tbname == relaysData[line].tbname) { + //zmazeme tasky + 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) { + + //update profile + logger.debug("worksys - update relay profile done:", profile); + instance.send(SEND_TO.debug, "worksys - update relay profile done"); + + relaysData[line].profile = profile; + + loadRelaysData(line) + logger.debug("loadRelaysData DONE for line", line); + + buildTasks({ processLineProfiles: true, line: line }); + + sendNotification("Cmd-mngr: set profile from worksys", tbname, "switching_profile_was_processed_for_line", { line: line }, profile, SEND_TO.tb, instance); + }); + }); + break; + } + } + } + else if (method == "set_command") { + let value = data.params.payload.value; + + 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; + + 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"); + if (line != 0) reportToSend["contactor"]["off"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + else { + turnLine("on", line, "command received from platform"); + if (line != 0) reportToSend["contactor"]["on"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + } + } + else { + instance.send(SEND_TO.debug, "undefined method " + method); + logger.debug("undefined method", method); + } + + return; + } + else { + instance.send(SEND_TO.debug, "UNKNOW entity_type " + entity_type); + logger.debug("UNKNOW entity_type", entity_type); + } + return; + } + + //terminal + if (!rsPort.isOpen) await rsPort.open(); + + let params = flowdata.data.body; + if (params == undefined) { + //logger.debug("Cmd-mngr: flowdata.data.body is undefined"); + return; + } + + params.priority = PRIORITY_TYPES.terminal; + params.type = "cmd-terminal"; + params.tbname = ""; + params.timestamp = PRIORITY_TYPES.terminal; + params.addMinutesToTimestamp = 0;// do not repeat task!!! + params.debug = true; + + let timestamp = Date.now(); + params.refFlowdataKey = timestamp; + //params.refFlowdata = flowdata; + //refFlowdata = flowdata; + + //console.log("flowdata", flowdata); + + cleanUpRefFlowdataObj(); + + refFlowdataObj[timestamp] = flowdata; + + //fix + //params.address = params.adress; + logger.debug("received from terminal", params); + logger.debug("date/time:", new Date()); + logger.debug("tasks length:", tasks.length); + + //tasks = []; + + //add to tasks + tasks.push(params); + + } + } + }) + + + //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) + } + + + /** + * 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; + + RESTBuilder.make(function(builder) { + + if (!builder) return; + + builder.method('GET'); + builder.url('http://192.168.252.2:8004/gettime?projects_id=1'); + + builder.callback(function(err, response, output) { + + 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); + } + + }); + } + + } 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); + + } else { + //console.log("Read-only", stdout); + + 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]: [ + { + "ts": date, + "values": values + } + ] + } + + tbHandler.sendToTb(dataToTb, instance); + } + + + function calculateDuskDawn(date, line, duskOffset = 0, dawnOffset = 0) { + + if (date === undefined) date = new Date(); + + 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); + } + + //if(profile.dawn_lux_sensor == false) + { + if (profile.hasOwnProperty("dawn_astro_clock_offset")) dawn_astro_clock_offset = parseInt(profile.dawn_astro_clock_offset); + } + + } + + } catch (error) { + if (profilestr != "") { + logger.debug(profilestr); + logger.debug(error); + } + } + + 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; + } + + //Dimming, CCT + else if (register == 1) { + let brightness = 0; + let dimming = byte0; + if (dimming > 128) { + //dimming = -128; + brightness = dimming - 128; + } + + //cct + //Ak Byte3 == 1: CCT = (Byte2*256)+Byte1 + let cct; + if (byte3 == 1) cct = byte2 * 256 + byte1; + else cct = bytesToInt(bytes.slice(0, 3)); + + //cct podla auditu + + values["dimming"] = brightness; + return values; + } + + // + else if (register == 4) { + values["master_node_version"] = bytes[1] + "." + bytes[2]; + //logger.debug("FW Version", register, bytes); + } + + //Napätie + else if (register == 74) { + let voltage = (bytesToInt(bytes) * 0.1).toFixed(1); + values["voltage"] = Number(voltage); + } + + //Prúd + else if (register == 75) { + let current = bytesToInt(bytes); + values["current"] = current; + } + + //výkon + else if (register == 76) { + let power = (bytesToInt(bytes) * 0.1).toFixed(2); + values["power"] = Number(power); + } + + //účinník + else if (register == 77) { + let power_factor = Math.cos(bytesToInt(bytes) * 0.1 * (Math.PI / 180)).toFixed(2); + values["power_factor"] = Number(power_factor); + } + + //frekvencia + else if (register == 78) { + let frequency = (bytesToInt(bytes) * 0.1).toFixed(2); + values["frequency"] = Number(frequency); + } + + //energia + else if (register == 79) { + let energy = bytesToInt(bytes); + values["energy"] = energy / 1000; //energia v kWh -> delit 1000 + } + + //doba života + else if (register == 80) { + let lifetime = (bytesToInt(bytes) / 60).toFixed(2); + values["lifetime"] = Number(lifetime); + } + + //nastavenie profilu + else if (register == 8) { + let time_schedule_settings = bytesToInt(bytes); + values["time_schedule_settings"] = time_schedule_settings; + } + + //naklon - nateraz sa z nodu nevycitava! kvoli problemom s accelerometrom a vracanymi hodnotami, posielame temp a x y z vo funkcii accelerometerData() + else if (register == 84) { + values["temperature"] = byte3 >= 128 ? (byte3 - 128) * (-1) : byte3; + values["inclination_x"] = byte2 >= 128 ? (byte2 - 128) * (-1) : byte2; + values["inclination_y"] = byte1 >= 128 ? (byte1 - 128) * (-1) : byte1; + values["inclination_z"] = byte0 >= 128 ? (byte0 - 128) * (-1) : byte0; + } + + //FW verzia nodu + else if (register == 89) { + //formát: "Byte3: Byte2.Byte1 (Byte0)" + values["fw_version"] = byte3 + ":" + byte2 + "." + byte1 + "(" + byte0 + ")"; + } + + else if (register == 87 || register == 6 || register == 7) { + var d = new Date(); + d.setHours(byte3, byte2, 0, 0); + let timestamp = d.getTime(); + + //aktuálny čas + if (register == 87) values["actual_time"] = timestamp; + //čas súmraku + else if (register == 6) values["dusk_time"] = timestamp; + //čas úsvitu + else if (register == 7) values["dawn_time"] = timestamp; + } + + 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; + + } + + + function getObjectByTbValue(object, tbname) { + return object[Object.keys(object).find(key => object[key].tbname === tbname)]; + } + + + function isObject(item) { + return (typeof item === "object" && !Array.isArray(item) && item !== null); + } + + + // we fake data, that should be received from accelerometer, as they are a bit unreliable. (temperature, x,y,z) + function accelerometerData() { + + if (temperatureInSenica === null) return; + + //clone nodesData and relaysData objects + let nodesData_clone = JSON.parse(JSON.stringify(nodesData)); + let relaysData_clone = JSON.parse(JSON.stringify(relaysData)); + + for (const key in relaysData_clone) { + + const lineData = relaysData_clone[key]; + const lineNumber = lineData.line; + const contactor = lineData.contactor; + + if (lineNumber === 0) continue; + + if (contactor === 1) { + + let date = Date.now(); + + Object.keys(nodesData_clone).forEach((node, index) => { + + setTimeout(function() { + + if (nodesData_clone[node].line === lineNumber) { + + // NOTE: if status of luminaire is NOK or OFFLINE, we do not send data; + let status = nodesData_clone[node].status; + if (status === "OFFLINE" || !status) return; + + let x = null; + if (naklony.hasOwnProperty(node)) x = naklony[node].naklon; + if (x === null) x = 0; + + sendTelemetry({ temperature: Math.round(temperatureInSenica + 10 + Math.floor(Math.random() * 3)), inclination_x: x, inclination_y: 0, inclination_z: 0 }, nodesData_clone[node].tbname, date); + } + + }, (index + 1) * 500); + }) + + } + } + } + + +} // end of instance.export + diff --git a/RVO43/flow/code.js b/RVO43/flow/code.js new file mode 100755 index 0000000..63b31bf --- /dev/null +++ b/RVO43/flow/code.js @@ -0,0 +1,90 @@ +exports.id = 'code'; +exports.title = 'Code'; +exports.group = 'Common'; +exports.color = '#656D78'; +exports.input = true; +exports.output = 1; +exports.author = 'Peter Širka'; +exports.icon = 'code'; +exports.version = '1.2.0'; +exports.options = { outputs: 1, code: 'send(0, value);', keepmessage: true }; + +exports.html = `
+
+
+
@(Number of outputs)
+
@(Minimum is 1)
+
+
+
@(Code)
+
@(Keep message instance)
+
+`; + +exports.readme = `# Code + +This component executes custom JavaScript code as it is and it doesn't contain any secure scope. + +\`\`\`javascript +// value {Object} contains received data +// send(outputIndex, newValue) sends a new value +// error(value) sends an error +// instance {Object} a current component instance +// flowdata {Object} a current flowdata +// repository {Object} a current repository of flowdata +// Example: + +// send() can be execute multiple times +send(0, value); +\`\`\``; + +exports.install = function(instance) { + + var fn; + + instance.on('data', function(response) { + if (fn) { + try { + fn(response.data, instance, response, instance.options, response.repository, require); + } catch (e) { + response.data = e; + instance.throw(response); + } + } + }); + + instance.reconfigure = function() { + try { + if (instance.options.code) { + instance.status(''); + var code = 'var send = function(index, value) { if (options.keepmessage) { flowdata.data = value; instance.send2(index, flowdata); } else instance.send2(index, value);}; var error = function(err) { instance.throw(err); }; ' + instance.options.code; + fn = new Function('value', 'instance', 'flowdata', 'options', 'repository', 'require', code); + } else { + instance.status('Not configured', 'red'); + fn = null; + } + } catch (e) { + fn = null; + instance.error('Code: ' + e.message); + } + }; + + instance.on('options', instance.reconfigure); + instance.reconfigure(); +}; \ No newline at end of file diff --git a/RVO43/flow/comment.js b/RVO43/flow/comment.js new file mode 100755 index 0000000..1e0cd13 --- /dev/null +++ b/RVO43/flow/comment.js @@ -0,0 +1,11 @@ +exports.id = 'comment'; +exports.title = 'Comment'; +exports.group = 'Common'; +exports.color = '#704cff'; +exports.author = 'Martin Smola'; +exports.icon = 'comment'; +exports.traffic = false; +exports.version = '1.0.0'; +exports.readme = '# Comment'; + +exports.install = function() {}; diff --git a/RVO43/flow/count.js b/RVO43/flow/count.js new file mode 100755 index 0000000..fa92ee9 --- /dev/null +++ b/RVO43/flow/count.js @@ -0,0 +1,60 @@ +exports.id = 'count'; +exports.title = 'Count'; +exports.version = '1.0.1'; +exports.author = 'John Graves'; +exports.color = '#656D78'; +exports.icon = 'plus-square'; +exports.input = 2; +exports.output = 1; +exports.options = { increment: 1, initialvalue: 1 }; +exports.readme = `# Counter + +Counter Number of times called.`; + +exports.html = `
+
@(Initial Value)
+
@(Increment)
+

Example Video

+
`; + +exports.readme = `# Count + +This component counts the number of messages received. + +__Response:__ + +Integer value based on the initial value and increment settings. + +__Arguments:__ +- Initial Value: What number should be output on the receipt of the first message. +- Increment: What should the increment be for each following message received.`; + +exports.install = function(instance) { + + var count = 0; + var initialCall = true; + + instance.on('data', function(flowdata) { + var index = flowdata.index; + if (index) { + instance.debug('Reset Count.'); + count = instance.options.initialvalue; + initialCall = true; + } else { + // If this is the first time, set the value to 'initial value' + if(initialCall) { + initialCall = false; + count = instance.options.initialvalue; + } else + count = count+instance.options.increment; + instance.status('Count:' + count); + instance.send2(count); + } + }); + + instance.on('options', function() { + count = instance.options.initialvalue; + initialCall = true; + }); + +}; diff --git a/RVO43/flow/db_connector.js b/RVO43/flow/db_connector.js new file mode 100755 index 0000000..65ee94b --- /dev/null +++ b/RVO43/flow/db_connector.js @@ -0,0 +1,286 @@ +exports.id = 'db_connector'; +exports.title = 'DbConnector'; +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.html = `
+
+
+
DbConnector
+
+
+
`; + +exports.readme = `# read/write data to tables`; + +const instanceSendTo = { + debug: 0, + http_response: 1, +} + +const { promisifyBuilder, makeMapFromDbResult } = require('./helper/db_helper.js'); + +function extractWhereParams(params) +{ + let name = params[0]; + let operator = '='; + let value = params[1]; + + if(params.length == 3) + { + operator = params[1]; + value = params[2]; + } + + return {name: name, operator: operator, value: value}; +} + +exports.install = function(instance) { + + let refFlowdata = null;//holds reference to httprequest flowdata + + instance.on("close", () => { + + }) + + + instance.on("data", async function(flowdata) { + + let params = flowdata.data.body; + console.log("DbConnector", params); + + refFlowdata = flowdata; + + if(refFlowdata != undefined) + { + //make http response + let responseObj = {}; + responseObj["type"] = "SUCESS"; + + try{ + + let table = params.table; + let action = params.action; + + + if(params.data != undefined) + { + let className = params.data.className; + + if(className == "SqlQueryBuilder") + { + let type = params.data.type; + + console.log("SqlQueryBuilder---->", params.data); + + if(type == "SELECT") + { + let table = params.data.queryData.tables[0].table; + + const db = TABLE(table); + var builder = db.find(); + + let result = await promisifyBuilder(builder); + + let response = {}; + response["result"] = result; + response["success"] = true; + + responseObj["data"] = response; + + //console.log(responseObj); + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + } + + return; + } + } + + + console.log("db_connector---->", table, action); + + //actions: read, replace, insert, delete, update... + + if(action == "read") + { + const db = TABLE(params.table); + + //where builder.where('age', '<', 15); + //builder.where('id', 3403); + + var builder = db.find(); + + //https://docs.totaljs.com/latest/en.html#api~DatabaseBuilder~builder.where + if(params.hasOwnProperty("where")) + { + //optionalCan contain "=", "<=", "<", ">=", ">". + //Default value: '=' + + //1.["production_line", 1] + //2. ["or", ["production_line", 1], ["production_line", 2], "end"] + + if (Array.isArray(params.where)) { + + let multipleConditions = false; + + if(params.where[0] == "or") multipleConditions = true; + if (Array.isArray(params.where[0])) multipleConditions = true; + + if(multipleConditions) + { + + for(var i = 0; i < params.where.length; i++) + { + const item = params.where[i]; + + if(item === "or") builder.or(); + + if (Array.isArray(item)) + { + const { name, operator, value } = extractWhereParams(item); + builder.where(name, operator, value); + } + + if(item === "end") builder.end(); + + } + + } + else + { + const { name, operator, value } = extractWhereParams(params.where); + builder.where(name, operator, value); + } + + } + + /* + if(params.where.length >=2 ) + { + let name = params.where[0]; + let operator = '='; + let value = params.where[1]; + + if(params.where.length == 3) + { + operator = params.where[1]; + value = params.where[2]; + } + + builder.where(name, operator, value); + } + */ + } + + if(params.hasOwnProperty("between")) + { + builder.between(params.between[0], params.between[1], params.between[2]); + } + + let response = await promisifyBuilder(builder); + responseObj["data"] = response; + + //console.log(responseObj); + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + + return; + } + + if(action == "delete") + { + + } + + + if(action == "update") + { + //! data receiving from terminal (params) + // { + // hostname: 'localhost', + // table: 'settings', + // action: 'update', + // body: { + // rvo_name: 'terrrr', + // lang: 'en', + // temperature_adress: '28.427B45920702', + // latitude: 48.70826502, + // longitude: 17.28455203, + // mqtt_host: '192.168.252.4', + // mqtt_clientid: 'showroom_test_panel_led', + // mqtt_username: 'xmRd6RJxW53WZe4vMFLU', + // mqtt_port: 1883, + // maintanace_mode: false + // } + // } + const tableToModify = TABLE(params.table); + const newValues = params.body; + + tableToModify.modify(newValues).make(function(builder) { + + builder.callback(function(err, response) { + + if(!err) + { + responseObj["data"] = response; + responseObj["tableUpdated"] = true; + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + } + }); + }); + + } + + if(action == "replace") + { + //truncate table + const db = TABLE(params.table); + var builder = db.remove(); + db.clean(); + + //insert data + let data = params.data; + + for(let i = 0; i < data.length; i++) + { + //console.log(data[i]); + db.insert(data[i]); + } + + console.log("insert done"); + + let responseObj = {}; + responseObj["type"] = "SUCESS"; + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + + + } + + + + } catch (error) { + //console.log(error); + responseObj["type"] = "ERROR"; + responseObj["message"] = error; + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + } + } + }) +} + + diff --git a/RVO43/flow/db_init.js b/RVO43/flow/db_init.js new file mode 100755 index 0000000..b399878 --- /dev/null +++ b/RVO43/flow/db_init.js @@ -0,0 +1,113 @@ +exports.id = 'db_init'; +exports.title = 'DB Initialization'; +exports.group = 'Worksys'; +exports.color = '#888600'; +exports.version = '1.0.2'; +exports.icon = 'sign-out'; +exports.output = 2; + +exports.readme = ` + # DB initialization +`; + +const { promisifyBuilder, makeMapFromDbResult } = require('./helper/db_helper.js'); +const { initNotification } = require('./helper/notification_reporter'); +const errorHandler = require('./helper/ErrorToServiceHandler'); +const total_energy = require('../databases/total_energy'); + +const SEND_TO = { + db_init: 0, + infoSender: 1 +}; + + +exports.install = async function(instance) { + const dbNodes = TABLE("nodes"); + const dbRelays = TABLE("relays"); + const dbSettings = TABLE("settings"); + 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 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.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"]; + Object.keys(dbs.nodesData).forEach(node => dbs.nodesData[node].readout = {}) + + let rvo_number = responseSettings[0]["rvo_name"].match(/\D+(\d{1,2})_/)[1]; + + dbs.settings = { + edge_fw_version: "2025-10-08", //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"], + phases: responseSettings[0]["phases"], + cloud_topic: responseSettings[0]["cloud_topic"], + has_main_switch: responseSettings[0]["has_main_switch"], + daily_report: responseSettings[0]["daily_report"], + send_changed_node_numbers: responseSettings[0]["send_changed_node_numbers"], + rvo_number: rvo_number, + + //dynamic values + masterNodeIsResponding: true, //cmd_manager + maintenance_mode: false, + } + + + dbs.settings.energy_to_switch_lamps = total_energy[rvo_number]; + if (dbs.settings.energy_to_switch_lamps === undefined) console.log('=============== db_init.js: energy_to_switch_lamps is undefined'); + + FLOW.dbLoaded = true; + errorHandler.setProjectId(dbs.settings.project_id); + initNotification(); + + //APP START - send to data services + const toService = { + id: dbs.settings.project_id, + name: dbs.settings.rvo_name, + fw_version: dbs.settings.edge_fw_version, + startdate: new Date().toISOString().slice(0, 19).replace('T', ' '), + js_error: "", + error_message: "" + }; + + instance.send(SEND_TO.infoSender, toService); + console.log("----------------> START - message send to service", toService); + + setTimeout(() => { + console.log("DB_INIT - data loaded"); + instance.send(SEND_TO.db_init, "_") + }, 5000) + +}; + diff --git a/RVO43/flow/debug.js b/RVO43/flow/debug.js new file mode 100755 index 0000000..00cb259 --- /dev/null +++ b/RVO43/flow/debug.js @@ -0,0 +1,100 @@ +exports.id = 'debug'; +exports.title = 'Debug'; +exports.author = 'Peter Širka'; +exports.color = '#967ADC'; +exports.click = true; +exports.input = true; +exports.icon = 'bug'; +exports.version = '2.0.4'; +exports.options = { enabled: true, repository: false, type: 'data' }; +exports.readme = `# Debug + +Prints data to the debug tab.`; + +exports.html = `
+
+
+
@(Output type)
+
@(Path to the property (leave empty to show the whole data object))
+
@(A group name)
+
@(Enabled)
+
+
+
`; + +exports.install = function(instance) { + + instance.on('data', function(response) { + if (instance.options.enabled) { + + var opt = instance.options; + var rep = response.repository; + var val = response.data; + var id = response.id; + + switch (instance.options.type){ + case 'both': + var data = {}; + data.repository = rep; + data.data = val instanceof Error ? { error: val.message, stack: val.stack } : val; + instance.debug(safeparse(opt.property ? U.get(data, opt.property) : data), undefined, opt.group, id); + break; + case 'repository': + instance.debug(safeparse(opt.property ? U.get(rep, opt.property) : rep), undefined, opt.group, id); + break; + case 'data': + default: + if (val instanceof Error) + instance.debug({ error: val.message, stack: val.stack }, undefined, opt.group, id); + else + instance.debug(safeparse(opt.property ? U.get(val, opt.property) : val), undefined, opt.group, id); + break; + } + } + }); + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + instance.save(); + }); + + instance.on('options', function() { + instance.custom.status(); + }); + + instance.custom.status = function() { + instance.status(instance.options.enabled ? 'Enabled' : 'Disabled'); + }; + + instance.custom.status(); + + function safeparse(o) { + + if (o instanceof Buffer) + return o; + + if (o === undefined) + return 'undefined'; + + if (o === null) + return 'null'; + + var cache = []; + var str = JSON.stringify(o, function(key, value) { + if (typeof value === 'object' && value !== null) { + if (cache.indexOf(value) !== -1) { + try { + return JSON.parse(JSON.stringify(value)); + } catch (error) { + return; + } + } + cache.push(value); + } + return value; + }); + cache = null; + return JSON.parse(str); + } +}; diff --git a/RVO43/flow/designer.json b/RVO43/flow/designer.json new file mode 100755 index 0000000..580f5a3 --- /dev/null +++ b/RVO43/flow/designer.json @@ -0,0 +1,3102 @@ +{ + "tabs": [ + { + "name": "MAIN PUSH", + "linker": "main-push", + "id": "1612772287426", + "index": 0 + }, + { + "name": "CMD manager", + "linker": "cmd-manager", + "id": "1615551125555", + "index": 1 + }, + { + "name": "Devices", + "linker": "devices", + "id": "1611921777196", + "index": 2 + } + ], + "components": [ + { + "id": "1611951142547", + "component": "debug", + "tab": "1611921777196", + "name": "ERROR", + "x": 598, + "y": 60, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#DA4453", + "notes": "" + }, + { + "id": "1612776786008", + "component": "wsmqttpublish", + "tab": "1612772287426", + "name": "WS MQTT publish", + "x": 281.75, + "y": 174, + "connections": { + "0": [ + { + "index": "0", + "id": "1615551060773" + } + ], + "1": [ + { + "index": "0", + "id": "1618300858252" + }, + { + "index": "0", + "id": "1618558465485" + } + ], + "2": [ + { + "index": "0", + "id": "1634303685503" + } + ], + "3": [ + { + "index": "0", + "id": "1731068754606" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Connected", + "color": "green" + }, + "options": { + "username": "", + "clientid": "", + "port": "1883", + "host": "" + }, + "color": "#888600", + "notes": "" + }, + { + "id": "1612778461252", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "tb-push", + "x": 72.75, + "y": 328, + "connections": { + "0": [ + { + "index": "0", + "id": "1612783322136" + }, + { + "index": "1", + "id": "1612776786008" + }, + { + "index": "0", + "id": "1731068754606" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1612783322136", + "component": "debug", + "tab": "1612772287426", + "name": "to TB", + "x": 283.75, + "y": 324, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615551060773", + "component": "debug", + "tab": "1612772287426", + "name": "errors from MQTT Broker", + "x": 594, + "y": 57, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#DA4453", + "notes": "" + }, + { + "id": "1615563373927", + "component": "debug", + "tab": "1615551125555", + "name": "Debug", + "x": 755, + "y": 155, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#DA4453", + "notes": "" + }, + { + "id": "1615566865233", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "tb-push", + "x": 755, + "y": 248, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1615798582262", + "component": "debug", + "tab": "1615551125555", + "name": "CMD_debug", + "x": 755, + "y": 346, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615802995322", + "component": "debug", + "tab": "1611921777196", + "name": "Debug", + "x": 596.8833312988281, + "y": 566.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Disabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": false + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615809128443", + "component": "debug", + "tab": "1611921777196", + "name": "tempToTb", + "x": 595.8833312988281, + "y": 658.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615809595184", + "component": "virtualwireout", + "tab": "1611921777196", + "name": "tb-push", + "x": 597.8833312988281, + "y": 377.25, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1616165795916", + "component": "httproute", + "tab": "1615551125555", + "name": "POST /terminal", + "x": 135, + "y": 547, + "connections": { + "0": [ + { + "index": "0", + "id": "1684060205000" + }, + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Listening", + "color": "green" + }, + "options": { + "timeout": 10, + "cachepolicy": 0, + "cacheexpire": "5 minutes", + "size": 5, + "url": "/terminal", + "method": "POST", + "name": "", + "flags": [ + "id:1616165795916", + "post", + 10000 + ], + "emptyresponse": false + }, + "color": "#5D9CEC", + "notes": "### Configuration\n\n- __POST /terminal__\n- flags: \n- maximum request data length: __5 kB__\n- empty response: __false__\n- cache policy: __no cache__\n- cache expire: __5 minutes__", + "cloning": false + }, + { + "id": "1616165824813", + "component": "httpresponse", + "tab": "1615551125555", + "name": "HTTP Response", + "x": 753, + "y": 423, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "json" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1617104731852", + "component": "debug", + "tab": "1615551125555", + "name": "DIDO_Debug", + "x": 669, + "y": 1040, + "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": "turnOff line", + "x": 133, + "y": 1161, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "object", + "data": "{line: 3, command: \"turnOff\", force: true}" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1617115013095", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "tb-push", + "x": 669, + "y": 1150, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1617284749681", + "component": "trigger", + "tab": "1615551125555", + "name": "update profile / node", + "x": 112, + "y": 208, + "connections": { + "0": [ + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "data": "profile_nodes", + "datatype": "string" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1618235171399", + "component": "trigger", + "tab": "1615551125555", + "name": "tun tasks", + "x": 184, + "y": 279, + "connections": { + "0": [ + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "data": "run" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1618300858252", + "component": "debug", + "tab": "1612772287426", + "name": "wsmqtt-exit1", + "x": 597.8833312988281, + "y": 149, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1618393583970", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "to-cmd-manager", + "x": 668.8833312988281, + "y": 1269, + "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": 132.88333129882812, + "y": 367, + "connections": { + "0": [ + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "platform-rpc-call", + "color": "gray" + }, + "options": { + "wirename": "platform-rpc-call" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1618393759854", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "cmd_to_dido", + "x": 119.88333129882812, + "y": 1007, + "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": 752.8833312988281, + "y": 527, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "cmd_to_dido", + "color": "gray" + }, + "options": { + "wirename": "cmd_to_dido" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1618558465485", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "platform-rpc-call", + "x": 597.8833312988281, + "y": 247, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "platform-rpc-call", + "color": "gray" + }, + "options": { + "wirename": "platform-rpc-call" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1618572059773", + "component": "trigger", + "tab": "1615551125555", + "name": "turnOn line", + "x": 132, + "y": 1085, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "data": "{line: 1, command: \"turnOn\", force: true}", + "datatype": "object" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1619515097737", + "component": "cmd_manager", + "tab": "1615551125555", + "name": "CMD Manager", + "x": 452.1091003417969, + "y": 341.05455017089844, + "connections": { + "0": [ + { + "index": "0", + "id": "1615563373927" + } + ], + "1": [ + { + "index": "0", + "id": "1615566865233" + }, + { + "index": "0", + "id": "1615798582262" + } + ], + "2": [ + { + "index": "0", + "id": "1616165824813" + } + ], + "3": [ + { + "index": "0", + "id": "1618393827655" + } + ], + "4": [ + { + "index": "0", + "id": "1635936391935" + } + ], + "5": [ + { + "index": "0", + "id": "1757006030239" + }, + { + "index": "0", + "id": "1757006060377" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1619605019281", + "component": "httproute", + "tab": "1615551125555", + "name": "GET db", + "x": 173, + "y": 653, + "connections": { + "0": [ + { + "index": "0", + "id": "1684060205000" + }, + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Listening", + "color": "green" + }, + "options": { + "timeout": 5, + "cachepolicy": 0, + "cacheexpire": "5 minutes", + "size": 5, + "url": "/db", + "method": "GET", + "name": "", + "flags": [ + "id:1619605019281", + "get", + 5000 + ] + }, + "color": "#5D9CEC", + "notes": "### Configuration\n\n- __GET /db__\n- flags: undefined\n- maximum request data length: __5 kB__\n- empty response: __undefined__\n- cache policy: __no cache__\n- cache expire: __5 minutes__", + "cloning": false + }, + { + "id": "1619784672383", + "component": "trigger", + "tab": "1615551125555", + "name": "turnOnAlarm", + "x": 120, + "y": 1234, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "object", + "data": "{command: \"turnOnAlarm\"}" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1619784812964", + "component": "trigger", + "tab": "1615551125555", + "name": "turnOffAlarm", + "x": 118, + "y": 1307, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "object", + "data": "{command: \"turnOffAlarm\"}" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1621340721628", + "component": "virtualwireout", + "tab": "1611921777196", + "name": "modbus_to_dido", + "x": 599, + "y": 471, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "modbus_to_dido", + "color": "gray" + }, + "options": { + "wirename": "modbus_to_dido" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1622640022885", + "component": "httproute", + "tab": "1615551125555", + "name": "POST /db_connector", + "x": 98, + "y": 1586, + "connections": { + "0": [ + { + "index": "0", + "id": "1622640073521" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Listening", + "color": "green" + }, + "options": { + "timeout": 5, + "cachepolicy": 0, + "cacheexpire": "5 minutes", + "size": 5, + "url": "/db_connector", + "method": "POST", + "flags": [ + "id:1622640022885", + "post", + 5000 + ] + }, + "color": "#5D9CEC", + "notes": "### Configuration\n\n- __POST /db_connector__\n- flags: \n- maximum request data length: __5 kB__\n- empty response: __undefined__\n- cache policy: __no cache__\n- cache expire: __5 minutes__", + "cloning": false + }, + { + "id": "1622640073521", + "component": "db_connector", + "tab": "1615551125555", + "name": "DbConnector", + "x": 372, + "y": 1572, + "connections": { + "1": [ + { + "index": "0", + "id": "1622641420685" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "edge": "undefined" + }, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1622641420685", + "component": "httpresponse", + "tab": "1615551125555", + "name": "HTTP Response", + "x": 596, + "y": 1586, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1634303504177", + "component": "monitormemory", + "tab": "1612772287426", + "name": "RAM", + "x": 69.88333129882812, + "y": 888.5, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465281992" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "858.88 MB / 985.68 MB", + "color": "gray" + }, + "options": { + "enabled": true, + "interval": 30000 + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1634303533779", + "component": "monitordisk", + "tab": "1612772287426", + "name": "disk", + "x": 70.88333129882812, + "y": 982.5, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465821120" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "5.78 GB / 7.26 GB", + "color": "gray" + }, + "options": { + "enabled": true, + "path": "/", + "interval": 30000 + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1634303595494", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "send-to-services", + "x": 51.883331298828125, + "y": 1400.5, + "connections": { + "0": [ + { + "index": "0", + "id": "1634463186563" + }, + { + "index": "1", + "id": "1634488120710" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1634303602169", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "send-to-services", + "x": 426.8833312988281, + "y": 878.5, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1634303685503", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "send-to-services", + "x": 600.8833312988281, + "y": 341.5, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1634303743260", + "component": "httprequest", + "tab": "1612772287426", + "name": "192.168.252.2:8004/sentmessage", + "reference": "", + "x": 506.8833312988281, + "y": 1331.7333374023438, + "connections": { + "0": [ + { + "index": "0", + "id": "1635327431236" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "url": "http://192.168.252.2:8004/sentmessage", + "method": "POST", + "stringify": "json" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1634463186563", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 305.75, + "y": 1442, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634464580289", + "component": "code", + "tab": "1612772287426", + "name": "Code", + "x": 245, + "y": 787, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465243324" + }, + { + "index": "0", + "id": "1634303602169" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "keepmessage": true, + "code": "let response = {};\nresponse.cpu = value.cpu;\nresponse.uptime = value.uptime;\n\nsend(0, response);", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1634465243324", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 428, + "y": 784, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634465281992", + "component": "code", + "tab": "1612772287426", + "name": "Code", + "x": 245, + "y": 884, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465338103" + }, + { + "index": "0", + "id": "1634303602169" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "keepmessage": true, + "code": "value.sender = \"ram\";\n\nlet response = {};\n\nresponse.memory_total = Math.round(value.total / (1024 ** 2));\nresponse.memory_free = Math.round(value.free / (1024 ** 2));\nresponse.memory_used = Math.round(value.used / (1024 ** 2));\n\nsend(0, response);", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1634465338103", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 429, + "y": 976, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634465821120", + "component": "code", + "tab": "1612772287426", + "name": "Code", + "x": 245, + "y": 978, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465892500" + }, + { + "index": "0", + "id": "1634303602169" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "keepmessage": true, + "code": "value.sender = \"hdd\";\n\nlet response = {};\n\nresponse.hdd_total = Math.round(value.total / (1024 ** 2));\nresponse.hdd_free = Math.round(value.free / (1024 ** 2));\nresponse.hdd_used = Math.round(value.used / (1024 ** 2));\n\nsend(0, response);", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1634465892500", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 432, + "y": 1068, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634484067516", + "component": "debug", + "tab": "1612772287426", + "name": "Send info", + "x": 513, + "y": 1441, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634488120710", + "component": "infosender", + "tab": "1612772287426", + "name": "Info sender", + "x": 301, + "y": 1336, + "connections": { + "0": [ + { + "index": "0", + "id": "1634484067516" + }, + { + "index": "0", + "id": "1634303743260" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "edge": "undefined" + }, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1635327431236", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 837.8833312988281, + "y": 1325.5, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1635936391935", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "send-to-services", + "x": 753, + "y": 623, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1637069803394", + "component": "monitorconsumption", + "tab": "1612772287426", + "name": "CPU", + "x": 69, + "y": 791, + "connections": { + "0": [ + { + "index": "0", + "id": "1634464580289" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "49.2% / 69.91 MB", + "color": "gray" + }, + "options": { + "monitorfiles": true, + "monitorconnections": true, + "monitorsize": true, + "monitorconsumption": true, + "enabled": true, + "interval": 30000 + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1683664161036", + "component": "debug", + "tab": "1615551125555", + "name": "CMDtoDIDO", + "x": 392, + "y": 1012, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1683981346282", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "from-dido-controller", + "x": 112, + "y": 459, + "connections": { + "0": [ + { + "index": "0", + "id": "1684055037116" + }, + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "from-dido-controller", + "color": "gray" + }, + "options": { + "wirename": "from-dido-controller" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1684055037116", + "component": "debug", + "tab": "1615551125555", + "name": "from dido to cmd", + "x": 451, + "y": 532, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1684060205000", + "component": "debug", + "tab": "1615551125555", + "name": "HTTP routes", + "x": 450, + "y": 639, + "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": "MDBToDido", + "x": 598, + "y": 147, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1699963668903", + "component": "dido_controller", + "tab": "1615551125555", + "name": "DIDO_Controller", + "x": 397, + "y": 1131, + "connections": { + "0": [ + { + "index": "0", + "id": "1617104731852" + } + ], + "1": [ + { + "index": "0", + "id": "1617104731852" + }, + { + "index": "0", + "id": "1617115013095" + } + ], + "2": [ + { + "index": "0", + "id": "1618393583970" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "edge": "undefined" + }, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1699964678894", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "modbus_to_dido", + "x": 96, + "y": 924, + "connections": { + "0": [ + { + "index": "0", + "id": "1699963668903" + }, + { + "index": "0", + "id": "1699964793925" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "modbus_to_dido", + "color": "gray" + }, + "options": { + "wirename": "modbus_to_dido" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1699964793925", + "component": "debug", + "tab": "1615551125555", + "name": "modbusToDido", + "x": 388, + "y": 920, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1699965957410", + "component": "modbus_reader", + "tab": "1611921777196", + "name": "Modbus reader", + "x": 232, + "y": 175, + "connections": { + "0": [ + { + "index": "0", + "id": "1611951142547" + } + ], + "1": [ + { + "index": "0", + "id": "1621340721628" + }, + { + "index": "0", + "id": "1684179110403" + }, + { + "index": "0", + "id": "1717441414646" + } + ], + "2": [ + { + "index": "0", + "id": "1615809595184" + }, + { + "index": "0", + "id": "1714752862828" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1700411878636", + "component": "thermometer", + "tab": "1611921777196", + "name": "Thermometer", + "x": 234.75, + "y": 444, + "connections": { + "0": [ + { + "index": "0", + "id": "1615802995322" + } + ], + "1": [ + { + "index": "0", + "id": "1615809595184" + }, + { + "index": "0", + "id": "1615809128443" + } + ], + "2": [ + { + "index": "0", + "id": "1621340721628" + }, + { + "index": "0", + "id": "1732889185927" + }, + { + "index": "0", + "id": "1717441414646" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#5CB36D", + "notes": "" + }, + { + "id": "1714752862828", + "component": "debug", + "tab": "1611921777196", + "name": "MDBToTb", + "x": 766, + "y": 324, + "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": 764.0833282470703, + "y": 222, + "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\telse if(value.status === \"NOK-thermometer\")\n\t{\n\t\tsend(0, {\"thermometer\": \"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\telse if(value.values.hasOwnProperty(\"temperature\"))\n\t{\n\t\tsend(0, {\"thermometer\": \"OK\"});\n\t}\n}", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1717442627834", + "component": "debug", + "tab": "1611921777196", + "name": "modbus service", + "x": 966.0833282470703, + "y": 165, + "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": 968.0833282470703, + "y": 268, + "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": 88.75, + "y": 1685, + "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": 296, + "y": 1671, + "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\", \"Flow has been restarted\", \"Node db has changed\"]", + "types": "[\"emergency\", \"critical\", \"error\", \"alert\"]", + "name": "" + }, + "color": "#30E193", + "notes": "" + }, + { + "id": "1718016073501", + "component": "httprequest", + "tab": "1612772287426", + "name": "http://192.168.252.2:8004/slack", + "x": 495, + "y": 1753, + "connections": { + "0": [ + { + "index": "0", + "id": "1718016086212" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "url": "http://192.168.252.2:8004/slack", + "method": "POST", + "stringify": "json" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1718016086212", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 832, + "y": 1664, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "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": 87, + "y": 1591, + "connections": { + "0": [ + { + "index": "0", + "id": "1718016052341" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "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\": \"\" } } } ] }", + "datatype": "object" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1729855334955", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "platform-rpc-call", + "x": 599.9333343505859, + "y": 541.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "platform-rpc-call", + "color": "gray" + }, + "options": { + "wirename": "platform-rpc-call" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1729855371093", + "component": "debug", + "tab": "1612772287426", + "name": "rpc cloud", + "x": 601.9333343505859, + "y": 440.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1731068658334", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 75.75, + "y": 184, + "connections": { + "0": [ + { + "index": "0", + "id": "1612776786008" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731068754606", + "component": "cloudmqttconnect", + "tab": "1612772287426", + "name": "MQTT to senica-prod01", + "x": 284.75, + "y": 452, + "connections": { + "1": [ + { + "index": "0", + "id": "1729855371093" + }, + { + "index": "0", + "id": "1729855334955" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Connected", + "color": "green" + }, + "options": { + "username": "", + "clientid": "", + "port": "2764", + "host": "192.168.252.2", + "topic": "" + }, + "color": "#888600", + "notes": "" + }, + { + "id": "1731069001548", + "component": "db_init", + "tab": "1612772287426", + "name": "DB Initialization", + "x": 1003.75, + "y": 240.25, + "connections": { + "0": [ + { + "index": "0", + "id": "1731069033416" + } + ], + "1": [ + { + "index": "0", + "id": "1747561603739" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#888600", + "notes": "" + }, + { + "id": "1731069033416", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "db-init", + "x": 1244.75, + "y": 233.25, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069059135", + "component": "showdb", + "tab": "1612772287426", + "name": "Show db data", + "x": 1186.75, + "y": 821.25, + "connections": { + "0": [ + { + "index": "0", + "id": "1731069079243" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#888600", + "notes": "" + }, + { + "id": "1731069079243", + "component": "debug", + "tab": "1612772287426", + "name": "dbData", + "x": 1390.75, + "y": 870.25, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1731069116691", + "component": "trigger", + "tab": "1612772287426", + "name": "settings", + "x": 934.75, + "y": 669.75, + "connections": { + "0": [ + { + "index": "0", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069131637", + "component": "trigger", + "tab": "1612772287426", + "name": "relaysData", + "x": 876.75, + "y": 733.75, + "connections": { + "0": [ + { + "index": "1", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069137374", + "component": "trigger", + "tab": "1612772287426", + "name": "nodesData", + "x": 852.75, + "y": 794.75, + "connections": { + "0": [ + { + "index": "2", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069179846", + "component": "trigger", + "tab": "1612772287426", + "name": "pinsData", + "x": 850.75, + "y": 861.75, + "connections": { + "0": [ + { + "index": "3", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069192937", + "component": "trigger", + "tab": "1612772287426", + "name": "sample data", + "x": 857.75, + "y": 928.75, + "connections": { + "0": [ + { + "index": "4", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069264443", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 63.75, + "y": 1279, + "connections": { + "0": [ + { + "index": "0", + "id": "1634488120710" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069334626", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "db-init", + "x": 172.88333129882812, + "y": 129, + "connections": { + "0": [ + { + "index": "0", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069548145", + "component": "virtualwirein", + "tab": "1611921777196", + "name": "db-init", + "x": 46.75, + "y": 192, + "connections": { + "0": [ + { + "index": "0", + "id": "1699965957410" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069567152", + "component": "virtualwirein", + "tab": "1611921777196", + "name": "db-init", + "x": 44.75, + "y": 465, + "connections": { + "0": [ + { + "index": "0", + "id": "1700411878636" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731070156936", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "db-init", + "x": 126.88333129882812, + "y": 1377, + "connections": { + "0": [ + { + "index": "2", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731234189516", + "component": "trigger", + "tab": "1612772287426", + "name": "monitor.txt", + "x": 882.75, + "y": 991.75, + "connections": { + "0": [ + { + "index": "5", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731234189551", + "component": "trigger", + "tab": "1612772287426", + "name": "err.txt", + "x": 904.75, + "y": 1053.75, + "connections": { + "0": [ + { + "index": "6", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1732700042559", + "component": "nodesdb_change_check", + "tab": "1612772287426", + "name": "Nodes DB change check", + "x": 266.8833312988281, + "y": 1980.2333984375, + "connections": { + "0": [ + { + "index": "0", + "id": "1732700071298" + }, + { + "index": "0", + "id": "1732700642917" + } + ], + "1": [ + { + "index": "0", + "id": "1759958914348" + }, + { + "index": "0", + "id": "1759959003114" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#888600", + "notes": "" + }, + { + "id": "1732700057052", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 76.75, + "y": 1988, + "connections": { + "0": [ + { + "index": "0", + "id": "1732700042559" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1732700071298", + "component": "debug", + "tab": "1612772287426", + "name": "nodesChange", + "x": 571.8833312988281, + "y": 2018.2333984375, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1732700642917", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "tb-push", + "x": 567.8833312988281, + "y": 1933, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1732889185927", + "component": "debug", + "tab": "1611921777196", + "name": "tempToDido", + "x": 594.8833312988281, + "y": 753, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1733574412965", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 72.75, + "y": 474, + "connections": { + "0": [ + { + "index": "1", + "id": "1731068754606" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1747561603739", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "send-to-services", + "x": 1243.8833312988281, + "y": 334.5, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1747562867845", + "component": "comment", + "tab": "1612772287426", + "name": "FLOW STARTING POINT", + "x": 1003.5666656494141, + "y": 178, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#704cff", + "notes": "" + }, + { + "id": "1749211698385", + "component": "trigger", + "tab": "1612772287426", + "name": "deviceStatus", + "x": 911.75, + "y": 1116.75, + "connections": { + "0": [ + { + "index": "7", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1757006030239", + "component": "httprequest", + "tab": "1615551125555", + "name": "192.168.252.2:8015/daily_report", + "x": 756.5666656494141, + "y": 715.4499969482422, + "connections": { + "0": [ + { + "index": "0", + "id": "1757006045804" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "stringify": "json", + "method": "POST", + "url": "http://192.168.252.2:8015/daily_report" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1757006045804", + "component": "debug", + "tab": "1615551125555", + "name": "ddd", + "x": 1091.566665649414, + "y": 711.4499969482422, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1757006060377", + "component": "debug", + "tab": "1615551125555", + "name": "reportDebug", + "x": 749.5666656494141, + "y": 799.4499969482422, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1759958914348", + "component": "httprequest", + "tab": "1612772287426", + "name": "http://192.168.252.2:8015/node_numbers", + "x": 571, + "y": 2111, + "connections": { + "0": [ + { + "index": "0", + "id": "1759958927094" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "stringify": "json", + "method": "POST", + "url": "http://192.168.252.2:8015/node_numbers" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1759958927094", + "component": "debug", + "tab": "1612772287426", + "name": "nodesChangeCloud", + "x": 951.8833312988281, + "y": 2109.2333984375, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1759959003114", + "component": "debug", + "tab": "1612772287426", + "name": "nodeChangeCloud1", + "x": 574, + "y": 2218, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1760020290879", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 84.75, + "y": 1787, + "connections": { + "0": [ + { + "index": "1", + "id": "1718016052341" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + } + ], + "version": 615 +} diff --git a/RVO43/flow/dido_controller.js b/RVO43/flow/dido_controller.js new file mode 100755 index 0000000..d16fb19 --- /dev/null +++ b/RVO43/flow/dido_controller.js @@ -0,0 +1,1486 @@ +exports.id = 'dido_controller'; +exports.title = 'DIDO_Controller'; +exports.version = '2.0.0'; +exports.group = 'Worksys'; +exports.color = '#2134B0'; +exports.input = 3; +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 + +state_of_main_switch - reportovat stav hlaveho istica : 0-> off 1-> on +rotary_switch_state - sem by sa mal reportovat stav vstupov manual a auto pola nasledovnej logiky: Manual = 1 a Auto = 0 -> Manu +Manual = 0 a Auto = 0 -> Off, Manual = 0 a Auto = 1 -> Automatic + +door_condition - pin 6, dverový kontakt -> 1 -> vyreportuje Closed, 0 -> vyreportuje Ope +twilight_sensor - hodnotu, ktoru vracia ten analogovy vstup (17) treba poslat sem ako float number. Zrejme tu potom pridame nejaky koeficient prevodu na luxy + +Na kazdu liniu +state_of_breaker - podla indexu istica sa reportuje jeho stav, teda istic na liniu 1: 0-> off, 1-> on +state_of_contactor - podla indexu stkaca sa reportuje jeho stav, teda stykac 1 na liniu 1: 0-> off, 1-> on +*/ + +const { errLogger, logger, monitor } = require('./helper/logger'); +const SerialPort = require('serialport'); +const WebSocket = require('ws'); +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 errorHandler = require('./helper/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 hasMainSwitch; + +let alarmStatus = "OFF"; + +const SEND_TO = { + debug: 0, + tb: 1, + cmd_manager: 2 +} + + +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 = {}; + let rsPortReceivedData = []; + + //to be able to get proper twilight values + let twilight_sensor_interval = 5;//minutes + let twilight_sensor = []; + const twilight_sensor_array = []; + let twilightError = false; + + monitor.info("DIDO_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-we make it global to see it from outside + FLOW.deviceStatus = { //key is device name: temperature,.... + "state_of_main_switch": "Off", //Hlavny istic (alebo druhy dverovy kontakt) + "rotary_switch_state": "Off", //Prevadzkovy + "door_condition": "closed", //Dverový kontakt + "em": "OK", //elektromer rvo + "temperature": "OK", //templomer + "battery": "OK", //Bateria + "power_supply": "OK", //Zdroj + "master_node": "OK", //MN - GLOBALS.settings.masterNodeIsResponding + "no_voltage": "OK", //GLOBALS.settings.no_voltage - vypadok napatia na faze + "state_of_breaker": {}, //"Off",//Istic + "state_of_contactor": {}, //"Off",//Stykac + "twilight_sensor": "OK" //lux sensor + }; + let deviceStatus = FLOW.deviceStatus; + + + function main() { + + GLOBALS = FLOW.GLOBALS; + SETTINGS = FLOW.GLOBALS.settings; + rvoTbName = SETTINGS.rvoTbName; + pinsData = GLOBALS.pinsData; + relaysData = GLOBALS.relaysData; + + tbHandler = new DataToTbHandler(SEND_TO.tb); + tbHandler.setSender(exports.title); + + controller_type = SETTINGS.controller_type; //"lm" or "unipi" + hasMainSwitch = SETTINGS.has_main_switch; + + if (controller_type == "") controller_type = "lm"; + + 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, "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; + } + } + + //report RVO version relaysData[0].tbname; + let values = {}; + values["edge_fw_version"] = SETTINGS.edge_fw_version; + values["maintenance_mode"] = SETTINGS.maintenance_mode; + + sendTelemetry(values, rvoTbName); + + 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); + } + + + function handleRsPort() { + + if (rsPort) { + rsPort.removeAllListeners(); + rsPort = null; + } + + //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('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) { + if (!err) { + monitor.info(exports.title + "--->Digital in_out has been set (runSyncExec was sucessfull)"); + + turnAlarm("off"); + 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('error', err => { + let message = "Dido: rsPort error: " + err.message; + logger.debug(message); + monitor.info(message); + errorHandler.sendMessageToService(message); + }) + + rsPort.on("close", () => { + let message = "Dido: rsPort closed - reconnecting ..."; + logger.debug(message); + monitor.info(message); + setTimeout(handleRsPort, 1000); + }) + + rsPort.open(); + } + + + function handleWebSocket() { + + if (ws) { + ws.removeAllListeners(); + ws = null; + } + + //to keep websocket opened, we send request every 150 seconds + let startRequests = null; + + console.log("handleWebSocket function called"); + ws = new WebSocket('ws:/0.0.0.0:1234/ws'); + + ws.onopen = function open() { + + instance.send(0, exports.title + " running"); + turnAlarm("off"); + + initialSetting(); + + setTimeout(function() { ws.send(JSON.stringify({ cmd: "all" })) }, 5000); + // we request dev info about neuron device from evok to keep websocket connection alive + // for some reason this request returns no data, but connection keeps alive + startRequests = setInterval(() => { + ws.send(JSON.stringify({ "cmd": "filter", "dev": ["neuron"] })); + }, 150000) + }; + + + // 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 = async 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; + + 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 => { + logger.debug('Dido: websocket error', err); + }) + + ws.onclose = function() { + logger.debug('Dido: websocket onclose, reconnecting...') + clearInterval(startRequests); + setTimeout(handleWebSocket, 1000); + } + } + + 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 turnAlarm(onOrOff) { + let value = 0; + if (onOrOff == "on") value = 1; + + if (value == 1 && SETTINGS.maintenance_mode) return; + + alarmStatus = "OFF"; + if (value == 1) alarmStatus = "ON"; + + if (rsPort) { + let arr = [0x55]; + arr.push(13); + arr.push(0); + arr.push(value); + + rsPort.write(Buffer.from(arr), function(err) { + logger.debug(`sirena - ${onOrOff}`); + }); + } + else if (ws) { + let cmd = { "cmd": "set", "dev": "relay", "circuit": "1_01", "value": value }; + ws.send(JSON.stringify(cmd)); + logger.debug(`sirena - ${onOrOff}`); + } + } + + + 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") { + bits.push(0); + } + else bits.push(1); + + if (deviceStatus["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); + } + + + // turn line on or off + function turnLine(onOrOff, line, pin, force, info) { + //onOrOff => "on" or "off" + let value = 0; + if (onOrOff == "on") value = 1; + + if (force == undefined) force = false; + + if (line == 0) { + if (value == 1 && alarmStatus == "ON") turnAlarm("off"); + SETTINGS.maintenance_mode = value ? true : false; + + 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); + return; + } + + if (pin === undefined) pin = getPin(line); + + if (pin === undefined) { + errLogger.error("pin is undefined!", line); + return; + } + + if (!force) { + if (relaysData[line].contactor == value) { + instance.send(SEND_TO.debug, `line is already ${onOrOff} ` + line); + logger.debug(`Dido: turnLine: line is already ${onOrOff} `, line); + return; + } + } + + // if(!rsPort.isOpen && !ws) + if (!rsPort && !ws) { + errLogger.error("Dido - port or websocket is not opened"); + return; + } + + if (rsPort) { + let arr = [0x55]; + arr.push(pin); + arr.push(0); + arr.push(value); + + rsPort.write(Buffer.from(arr), function(err) { + if (err === undefined) { + monitor.info(`Dido: turnLine ${onOrOff} zapisal do rsPort-u`, line, pin, arr, info); + switchLogic(arr); + } + else { + monitor.info(`Dido: turnLine ${onOrOff} WRITE error`, err); + } + }); + + } + else if (ws) { + //pin = "relay1_03" or "input1_01" ... we must make just "1_01" with slice method + monitor.info(`Dido: turnLine ${onOrOff} - (line, pin, force)`, line, pin, force, info); + let cmd = { "cmd": "set", "dev": "relay", "circuit": pin.slice(5), "value": value }; + ws.send(JSON.stringify(cmd)); + } + + //if rvo is 24/7, it has just one switching profile point at 13:00. we do not want to send notification as it repeats every day. + //const d = new Date(); + //if(d.getHours() != 13) sendNotification("Dido_controller: ", SETTINGS.rvoTbName, "switching_profile_point_applied_to_line", { line: line, value: onOrOff }, "", SEND_TO.tb, instance); + } + + + // 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; + + // 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) { + const status = flowdata.data.status; + if (status == "NOK-twilight_sensor") { + deviceStatus["twilight_sensor"] = "NOK"; + } + else if (status == "NOK-em340" || status == "NOK-em111") { + deviceStatus["em"] = "NOK"; + } + else if (status == "NOK-thermometer") { + deviceStatus["temperature"] = "NOK"; + } + } + else if ("values" in flowdata.data) { + 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" + } + else if (values.hasOwnProperty("temperature")) { + deviceStatus["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"; + } + + sendTelemetry(values, rvoTbName); + } + + sendRvoStatus(); + }) + + + + + // we expect array as flowdata.data + instance.on("1", flowdata => { + + //console.log(flowdata.data); + + if (!flowdata.data instanceof Object) return; + + let obj = flowdata.data; + let line = obj.line; + 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"); + }) + + + function calculateStateCode() { + + let bits = []; + + //Hlavny istic - state_of_main_switch => v rvo senica je to druhy door pre silovu cast (EM) + if (deviceStatus["state_of_main_switch"] === "closed" || deviceStatus["state_of_main_switch"] === "Off") { + bits.push(0); + } + else { + bits.push(1); + } + + //Prevadzkovy mod - Manual, Off, Automatic, maintenance_mode = true/false // DAVA 2 BITY + if (!SETTINGS.maintenance_mode) { + if (deviceStatus["rotary_switch_state"] === "Manual") { + bits.push(0); + bits.push(1); + } + + if (deviceStatus["rotary_switch_state"] === "Automatic") { + bits.push(0); + bits.push(0); + } + + if (deviceStatus["rotary_switch_state"] === "Off") { + bits.push(1); + bits.push(0); + } + } + else { + bits.push(1); + bits.push(1); + } + + //Dverovy kontakt + if (deviceStatus["door_condition"] === "closed") { + bits.push(0); + } + else { + bits.push(1); + } + + //EM + if (deviceStatus["em"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //Teplomer + if (deviceStatus["temperature"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //Batéria + if (deviceStatus["battery"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //Zdroj + if (deviceStatus["power_supply"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //MN + if (deviceStatus["master_node"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //výpadok napätia na fáze + if (deviceStatus["no_voltage"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + if (deviceStatus["twilight_sensor"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + // doplnime do 16 bitov (2 byty) + for (let i = bits.length; i < 16; i++) { + bits.push(0); + } + + // console.log("calculateStateCode - deviceStatus", deviceStatus); + // 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; + } + + + async function sendRvoStatus() { + + if (SETTINGS === undefined) return; + SETTINGS.masterNodeIsResponding ? deviceStatus["master_node"] = "OK" : deviceStatus["master_node"] = "NOK"; + + 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 pinsForRvoStatus(controllerType, hasMainSwitch) { + + let pins = []; + + if (controllerType === "lm") { + pins = [1, 4, 6]; + if (hasMainSwitch === 1) { + pins = [4, 6]; + } + } else if (controllerType === "unipi") { + pins = ["input1_01", "input1_04", "input1_05"]; + if (hasMainSwitch === 1) { + pins = ["input1_01", "input1_04"]; + } + } + + return pins; + } + + + function checkRvoStatus() { + + // 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 + //set RVO state + let status = "OK"; + + for (const [key, value] of Object.entries(deviceStatus)) { + if (["em", "twilight_sensor", "temperature", "master_node"].includes(key) && value === "NOK") status = "NOK"; + } + + if (status === "OK") { + + let pinIndexes = pinsForRvoStatus(controller_type, hasMainSwitch); + + for (const pinIndex of pinIndexes) { + if (previousValues[pinIndex] === 0) { + if ((pinIndex === 6 || pinIndex === 'input1_01' || pinIndex === 'input1_05') && SETTINGS.maintenance_mode) continue; + status = "NOK"; + break; + } + } + } + + // battery status. If value is 1 - battery is NOK + if (previousValues[5] === 1) status = "NOK"; + if (SETTINGS.no_voltage.size > 0) status = "NOK"; + + // console.log("rvo status",status) + return status; + } + + + // we pass array to function in case of rsPort ==> switchLogic([55,3,0,1]) ==> [[55,3,0,1]] + // we pass two values in case of websocket ==> switchLogic("relay1_03",1) ==> ["relay1_03",1] + const switchLogic = (...args) => { + + let values = {}; + let pinIndex, newPinValue, twilight; + + //data from rsPort + if (args.length == 1) { + pinIndex = args[0][1] + 1; + if (pinIndex === 17) pinIndex--; + newPinValue = args[0][3]; + twilight = args[0][2]; + } + //data from websocket + else { + pinIndex = args[0]; + newPinValue = args[1]; + } + + 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; + + //default value + let value = "On"; + if (newPinValue === 0) value = "Off"; + + //Hlavny istic + if (type === "state_of_main_switch" && hasMainSwitch) { + if (newPinValue === 0 && newPinValue !== previousValues[pinIndex]) { + sendNotification("switchLogic", rvoTbName, "main_switch_has_been_turned_off", {}, "", SEND_TO.tb, instance, "state_of_main_switch"); + 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"); + deviceStatus["state_of_main_switch"] = "On"; + } + } + + //Prevadzkovy mod + 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"; + + deviceStatus["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, "power_supply_has_disconnected_input", {}, "", SEND_TO.tb, instance, "power_supply"); + + deviceStatus["power_supply"] = "NOK"; + } + else if (newPinValue === 1 && newPinValue !== previousValues[pinIndex]) { + sendNotification("switchLogic", rvoTbName, "power_supply_works_correctly", {}, "", SEND_TO.tb, instance, "power_supply"); + + deviceStatus["power_supply"] = "OK"; + } + } + + //Bateria - 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"); + + deviceStatus["battery"] = "NOK"; + } + else if (newPinValue === 0 && newPinValue !== previousValues[pinIndex]) { + sendNotification("switchLogic", rvoTbName, "battery_level_is_ok", {}, "", SEND_TO.tb, instance, "battery_level"); + + deviceStatus["battery"] = "OK"; + } + } + + //Dverovy kontakt - pin 6 + //! Ak je rvo s dvoma dverovymi kontaktami, ked pride z evoku signal z input1_05, co bol predytm "state_of_main switch" handlujeme ho teraz ako 'door_condition' + else if (type == "door_condition" || type === "state_of_main_switch") { + newPinValue === 0 ? value = "open" : value = "closed"; + + let door = "door_main"; + if (type === "state_of_main_switch") door = "door_em"; + + if (value === "open") { + if (SETTINGS.maintenance_mode) { + sendNotification("switchLogic", rvoTbName, door + "_open", {}, "", SEND_TO.tb, instance, door); + } else { + sendNotification("switchLogic", rvoTbName, door + "_open_without_permission", {}, "", SEND_TO.tb, instance, door); + + // 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 (value === "closed") { + if (alarmStatus == "ON") turnAlarm("off"); + sendNotification("switchLogic", rvoTbName, door + "_close", {}, "", SEND_TO.tb, instance, door); + } + + deviceStatus[type] = value; + } + + //lux sensor + else if (type == "twilight_sensor") { + //! TODO - to show nok status, if lux value is not changing more then 10 times. + //Daylight is far more than 1000. So most of the day, when it is sunshine comes just value 1000. But lux sensor is not NOK. + //This is not the case in LM. If value from LM is the same 10x, there is 99% possibility, that sensor is NOK. + value = newPinValue; + + if (controller_type === 'lm') { + value = parseFloat(newPinValue + (256 * twilight)); + + 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 && !twilightError) { + twilightError = true; + let value = twilight_sensor_array.shift(); + + newPinValue = 0; + } + else if (set.size !== 1 && twilightError) { + //sendNotification("switchLogic", rvoTbName, 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) { + 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); + } + } + + 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); + } + + deviceStatus["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 (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 }); + + //mame iba 3 istice. vyreportujeme a ohandlujeme liniu na tom istom istici ako paralelna linia (napr linia 1, paralelna s nou je linia 4, key je string "4") + // ak je 7 linii, na 1 istici je linia 1,4,7 + + if (line == 1) { + + const lineOnSameBraker = [4, 7]; + + for (var i = 0; i < lineOnSameBraker.length; i++) { + if (!relaysData.hasOwnProperty(lineOnSameBraker[i])) continue; + + 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; + reportLineStatus(lineOnSameBraker[i]); + + values[type] = value; + const tbname = relaysData[lineOnSameBraker[i]].tbname; + sendTelemetry(values, tbname); + + delete values[type]; + } + + } + else { + const lineOnSameBraker = line + 3 + ""; + + if (relaysData.hasOwnProperty(lineOnSameBraker)) { + 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; + reportLineStatus(line + 3); + + values[type] = value; + const tbname = relaysData[lineOnSameBraker].tbname; + sendTelemetry(values, tbname); + + delete values[type]; + } + } + + } + + if (value == "Off") values["status"] = "NOK"; + deviceStatus["state_of_breaker"][line] = value; + + reportLineStatus(line); + } + else return; + + values[type] = value; + + if (type == "rotary_switch_state") { + if (SETTINGS.maintenance_mode) value = "maintenance"; + value = value.toLowerCase(); + values["power_mode"] = value; + } + + if (newPinValue != previousValues[pinIndex]) previousValues[pinIndex] = newPinValue; + if (Object.keys(values).length > 0 && tbname) sendTelemetry(values, tbname); + } + + + function sendTelemetry(values, tbname, date = Date.now()) { + let dataToTb = { + [tbname]: [ + { + "ts": date, + "values": values + } + ] + }; + + tbHandler.sendToTb(dataToTb, instance); + } + + + function isObject(item) { + return (typeof item === "object" && !Array.isArray(item) && item !== null); + } + +} //end of 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 +// *|input1_01|state_of_main_switch|0|........... +// *|input1_02|rotary_switch_state|0|........... +// *|input1_03|rotary_switch_state|0|........... +// *|intut1_04|power_supply|0|........... +// *|input1_05|door_condition|0|........... +// *|input1_06|state_of_breaker|1|........... +// *|input1_07|state_of_breaker|2|........... +// *|input1_08|state_of_breaker|3|........... +// *|relay1_02|state_of_contactor|1|........... +// *|relay1_03|state_of_contactor|2|........... +// *|relay1_04|state_of_contactor|3|........... +// *|287D8776E0013CE9|temperature|0|........... + + +//! pins_data --> from UNIPI +// { +// 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 } +// } + +//! relays_data +// { +// '0': { +// line: 0, +// tbname: 'KjbN4q7JPZmexgdnz2yKQ98YAWwO0Q3BMX6ERLoV', +// contactor: 1, +// profile: '' +// }, +// '1': { +// line: 1, +// tbname: 'RMgnK93rkoAazbqdQ4yBG95Z1YXGx6pmwBeVEP2O', +// contactor: 0, +// profile: '{"intervals":[{"value":0,"end_time":"20:00","start_time":"13:00"},{"value":1,"end_time":"10:00","start_time":"20:00"},{"value":0,"end_time":"10:20","start_time":"10:00"},{"value":1,"end_time":"10:40","start_time":"10:20"},{"value":0,"end_time":"11:00","start_time":"10:40"},{"value":1,"end_time":"11:30","start_time":"11:00"},{"value":0,"end_time":"11:50","start_time":"11:30"},{"value":1,"end_time":"13:00","start_time":"11:50"}],"astro_clock":false,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' +// }, +// '2': { +// line: 2, +// tbname: 'dlE1VQjYrNx9gZRmb38gG08oLBO4qaAk2M6JPnG7', +// contactor: 0, +// profile: '{"intervals":[{"value":0,"end_time":"20:00","start_time":"13:00"},{"value":1,"end_time":"10:00","start_time":"20:00"},{"value":0,"end_time":"10:20","start_time":"10:00"},{"value":1,"end_time":"10:40","start_time":"10:20"},{"value":0,"end_time":"11:00","start_time":"10:40"},{"value":1,"end_time":"11:30","start_time":"11:00"},{"value":0,"end_time":"11:50","start_time":"11:30"},{"value":1,"end_time":"13:00","start_time":"11:50"}],"astro_clock":false,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' +// }, +// '3': { +// line: 3, +// tbname: 'vnmG4kJxaXWNBgMQq0D7Aj5e9oZzOAlr6LdR3w2V', +// contactor: 0, +// profile: '{"intervals":[{"value":0,"end_time":"20:30","start_time":"13:00"},{"value":1,"end_time":"00:10","start_time":"20:30"},{"value":0,"end_time":"13:00","start_time":"05:40"},{"value":1,"end_time":"05:40","start_time":"00:10"}],"astro_clock":true,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' +// } +// } + + + + + +// { +// "jbN4q7JPZmexgdnz2yKbWGDYAWwO0Q3BMX6ERLoV": [ +// { +// "ts": 1700409326353, +// "values": { +// "_event": { +// "type": "notice", +// "status": "new", +// "source": { +// "func": "rsPort.open()", +// "component": "1700343402190", +// "component_name": "DIDO_Controller", +// "edge": "jbN4q7JPZmexgdnz2yKbWGDYAWwO0Q3BMX6ERLoV" +// }, +// "message": "al_shariff_10.0.0.38: FLOW has been started ", +// "message_data": "" +// } +// } +// } +// ] +// } diff --git a/RVO43/flow/helper/DataToTbHandler.js b/RVO43/flow/helper/DataToTbHandler.js new file mode 100755 index 0000000..716ef7b --- /dev/null +++ b/RVO43/flow/helper/DataToTbHandler.js @@ -0,0 +1,187 @@ +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; + this.itIsNodeReadout = false; + this.sender = ""; + + // if attribute change difference is less than limit value, we do not send to tb. + this.attributeChangeLimit = { + temperature: 0.5, + Phase_1_voltage: 2, + Phase_2_voltage: 2, + Phase_3_voltage: 2, + Phase_1_current: 0.1, + Phase_2_current: 0.1, + Phase_3_current: 0.1, + Phase_1_power: 2, + Phase_2_power: 2, + Phase_3_power: 2, + total_power: 2, + total_energy: 1, + Phase_1_pow_factor: 0.1, + Phase_2_pow_factor: 0.1, + Phase_3_pow_factor: 0.1, + power_factor: 0.1, + lifetime: 2, + voltage: 2, + power: 2, + frequency: 3, + energy: 0.1, + current: 2, + inclination_x: 10, + inclination_y: 10, + inclination_z: 10 + }; + + } + + dump() { + console.log("----------------------------"); + console.log("previousValues", this.previousValues); + console.log("----------------------------"); + } + + setSender(sender) { + this.sender = sender; + } + + isEmptyObject(obj) { + for (var _ in obj) { + return false; + } + return true; + } + + + sendToTb(data, instance) { + + //not to modify data object, we do deep copy: + let dataCopy = JSON.parse(JSON.stringify(data)); + + let keys = Object.keys(dataCopy); + + if (keys.length == 0) { + if (this.debug) console.log("sendToTb received empty object", dataCopy); + return; + } + + let tbname = keys[0]; + let ts; + + let arrayOfValues = dataCopy[tbname]; + let arrayOfValuesToSend = []; + + for (let i = 0; i < arrayOfValues.length; i++) { + + ts = arrayOfValues[i].ts; + let values = this.prepareValuesForTb(tbname, ts, arrayOfValues[i].values); + + if (!this.isEmptyObject(values)) { + arrayOfValuesToSend.push({ ts: ts, values: values }); + } + + } + + if (arrayOfValuesToSend.length == 0) { + //if(this.debug) console.log("data not sent - empty array"); + return; + } + + this.messageCounter++; + + let dataToTbModified = { + [tbname]: arrayOfValuesToSend + } + + //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); + instance.send(this.index, dataToTbModified); + } + + + getDiffTimestamp(key) { + //TODO set different value for given key!!! + //if(key == "status") this.timeToHoldTbValue = 2*60*60;//2h + return this.timeToHoldTbValue * 1000; + } + + + prepareValuesForTb(tbname, timestamp, values) { + + let keys = Object.keys(values); + + if (keys.includes("lifetime")) this.itIsNodeReadout = true; + + if (!this.previousValues.hasOwnProperty(tbname)) { + this.previousValues[tbname] = {}; + } + + //if(this.debug) console.log("prepareValuesForTb", tbname, timestamp, values); + + for (let i = 0; i < keys.length; i++) { + + let key = keys[i]; + let value = values[key]; + + if (!this.previousValues[tbname].hasOwnProperty(key)) { + this.previousValues[tbname][key] = { ts: timestamp, value: value }; + continue; + } + + // attributeData ==> {voltage: {ts:333333, value:5}} + let attributeData = this.previousValues[tbname][key]; + let attributeToChange = false; + if (key in this.attributeChangeLimit) attributeToChange = true; + let limit = this.attributeChangeLimit[key]; + let timestampDiffToRemoveKey; + + //this will ensure "node statecode" will be sent just once an hour + if (this.itIsNodeReadout && key === "statecode") { + attributeData.value = value; + this.itIsNodeReadout = false; + timestampDiffToRemoveKey = 1 * 60 * 60 * 1000; // 1 hour + } + + if (key === "twilight_sensor" && value > 100) { + attributeData.value = value; + } + + //if edge, master or node version do not change, send just once a day: + if (["edge_fw_version", "master_node_version", "fw_version"].includes(key)) { + timestampDiffToRemoveKey = 24 * 60 * 60 * 1000; + } + + if (attributeData.value === value || attributeToChange && Math.abs(attributeData.value - value) < limit) { + + let diff = timestamp - attributeData.ts; + if (!timestampDiffToRemoveKey) timestampDiffToRemoveKey = this.getDiffTimestamp(key); + + if (diff > timestampDiffToRemoveKey) { + attributeData.ts = Date.now(); + //if(this.debug) console.log(this.sender + ": update ts for key", key, "diff is", diff, "messageCounter", this.messageCounter); + } + else { + delete values[key]; + //if(this.debug) console.log(this.sender + ": delete key", key, "diff is", diff, "messageCounter", this.messageCounter, timestampDiffToRemoveKey); + } + } + else { + attributeData.value = value; + attributeData.ts = timestamp; + } + + } + + return values; + } +} + +module.exports = DataToTbHandler; + diff --git a/RVO43/flow/helper/ErrorToServiceHandler.js b/RVO43/flow/helper/ErrorToServiceHandler.js new file mode 100755 index 0000000..2b27c32 --- /dev/null +++ b/RVO43/flow/helper/ErrorToServiceHandler.js @@ -0,0 +1,91 @@ +const { MD5 } = require('./md5.js'); +const { networkInterfaces } = require('os'); + +class ErrorToServiceHandler { + constructor() { + this.previousValues = {}; + + this.project_id = undefined; + + const nets = networkInterfaces(); + this.ipAddresses = {}; + + for (const name of Object.keys(nets)) { + for (const net of nets[name]) { + // Skip over non-IPv4 and internal (i.e. 127.0.0.1) addresses + if (net.family === 'IPv4' && !net.internal) { + if (!this.ipAddresses[name]) { + this.ipAddresses[name] = []; + } + this.ipAddresses[name].push(net.address); + } + } + } + } + + setProjectId(project_id) { + this.project_id = project_id; + } + + processMessage(message, seconds) { + if (Array.isArray(message)) message = message.join(', '); + + let key = MD5(message); + let ts = Date.now(); + + //keep in memory - default value is 1h + if (seconds === undefined) seconds = 60 * 60; + + if (!this.previousValues.hasOwnProperty(key)) { + this.previousValues[key] = { ts: ts, duration: seconds }; + } + + let diff = (ts - this.previousValues[key].ts); + if (diff < this.previousValues[key].duration * 1000) return false; + + this.previousValues[key].ts = ts; + + return message; + } + + sendMessageToService(message, seconds, message_type) { + + // if error occures too early FLOW.GLOBALS.settings.project_id is still undefined + if (this.project_id === undefined) { + console.log("ErrorToServiceHandler.js: no project_id"); + return; + } + + let f = this.processMessage(message, seconds); + if (f === false) return; + + if (message_type === undefined) message_type = "error_message"; + + let toService = { + id: this.project_id, + ipAddresses: this.ipAddresses + }; + + //js_error || error_message + toService[message_type] = message; + + console.log("ErrorToServiceHandler------------------------>send to service", toService); + + RESTBuilder.make(function(builder) { + builder.method('POST'); + builder.post(toService); + builder.url('http://192.168.252.2:8004/sentmessage'); + + builder.callback(function(err, response, output) { + console.log("process.on error send", err, response, output, toService); + }); + }); + + } +} + +const errorHandler = new ErrorToServiceHandler(); + + +module.exports = errorHandler; +//module.exports = ErrorToServiceHandler; diff --git a/RVO43/flow/helper/db_helper.js b/RVO43/flow/helper/db_helper.js new file mode 100755 index 0000000..40e796c --- /dev/null +++ b/RVO43/flow/helper/db_helper.js @@ -0,0 +1,44 @@ +function promisifyBuilder(builder) +{ + return new Promise((resolve, reject) => { + + try{ + + builder.callback(function(err, response) { + + if(err != null) reject(err); + resolve(response); + }); + + } catch (error) { + reject(error); + } + }) +} + +function makeMapFromDbResult(response, ...keys) +{ + let s = "-"; + let data = {}; + + for(let i = 0; i < response.length; i++) + { + let record = response[i]; + + let k = []; + for(let j = 0; j < keys.length; j++) + { + k.push( record[keys[j]] ); + } + + let key = k.join(s); + data[ key ] = record; + } + + return data; +} + +module.exports = { + promisifyBuilder, + makeMapFromDbResult + } \ No newline at end of file diff --git a/RVO43/flow/helper/logger.js b/RVO43/flow/helper/logger.js new file mode 100755 index 0000000..2585639 --- /dev/null +++ b/RVO43/flow/helper/logger.js @@ -0,0 +1,30 @@ +//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/RVO43/flow/helper/md5.js b/RVO43/flow/helper/md5.js new file mode 100755 index 0000000..d3b0480 --- /dev/null +++ b/RVO43/flow/helper/md5.js @@ -0,0 +1,5 @@ +function MD5(d){var r = M(V(Y(X(d),8*d.length)));return r.toLowerCase()};function M(d){for(var _,m="0123456789ABCDEF",f="",r=0;r>>4&15)+m.charAt(15&_);return f}function X(d){for(var _=Array(d.length>>2),m=0;m<_.length;m++)_[m]=0;for(m=0;m<8*d.length;m+=8)_[m>>5]|=(255&d.charCodeAt(m/8))<>5]>>>m%32&255);return _}function Y(d,_){d[_>>5]|=128<<_%32,d[14+(_+64>>>9<<4)]=_;for(var m=1732584193,f=-271733879,r=-1732584194,i=271733878,n=0;n>16)+(_>>16)+(m>>16)<<16|65535&m}function bit_rol(d,_){return d<<_|d>>>32-_} + +module.exports = { + MD5 +} \ No newline at end of file diff --git a/RVO43/flow/helper/notification_reporter.js b/RVO43/flow/helper/notification_reporter.js new file mode 100755 index 0000000..839c12c --- /dev/null +++ b/RVO43/flow/helper/notification_reporter.js @@ -0,0 +1,121 @@ +//key is device, value = message {} +let sentValues = {}; +let notificationsData = null; +let rvoName; + +//sendNotification("CMD Manager: process cmd", SETTINGS.rvoTbName, "dimming_profile_was_successfully_received_by_node", { node: node }, "", SEND_TO.tb, instance); + +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 +}; + +function getKey(map, val) { + return Object.keys(map).findItem(key => map[key] === val); +} + +//https://stackoverflow.com/questions/41117799/string-interpolation-on-variable +var template = (tpl, args) => tpl.replace(/\${(\w+)}/g, (_, v) => args[v]); + + +function initNotification() { + notificationsData = FLOW.GLOBALS.notificationsData; + rvoName = FLOW.GLOBALS.settings.rvo_name; +} + + +function sendNotification(func, device, key, params, extra, tb_output, instance, saveKey) { + + let storeToSendValues = true; + if (saveKey == undefined) storeToSendValues = false; + + let weight = ""; + let message = {}; + + let notification = notificationsData[key]; + + if (notification) { + weight = notification.weight.toLowerCase(); + + Object.keys(notification).forEach(item => { + if (["en", "sk", "de", "cz", "it", "es"].includes(item)) { + message[item] = rvoName + ": " + template(notification[item], params); + } + }) + } + else { + //console.error("sendNotification: Notifications: undefined key", key, func, notificationsData); + console.error("sendNotification: Notifications: undefined key", key, func); + return false; + } + + //detect invalid err weight + if (getKey(ERRWEIGHT, weight) == undefined) { + console.error("sendNotification: Notifications: undefined weight", weight, key, func); + return false; + } + + if (sentValues.hasOwnProperty(saveKey)) { + if (JSON.stringify(sentValues[saveKey]) == JSON.stringify(message)) { + return false; + } + } + + if (sentValues[saveKey] == undefined) { + if (storeToSendValues) { + //do not send - flow is was started + sentValues[saveKey] = message; + return false; + } + } + + if (storeToSendValues) sentValues[saveKey] = message; + + let content = { + "type": weight, + "status": "new", + "source": { + "func": func, + "component": instance.id, + "component_name": instance.name, + "edge": device + }, + "message": message, + "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 + + return true; + +} + +module.exports = { + sendNotification, + ERRWEIGHT, + initNotification +} + diff --git a/RVO43/flow/helper/register.js b/RVO43/flow/helper/register.js new file mode 100755 index 0000000..fc1d008 --- /dev/null +++ b/RVO43/flow/helper/register.js @@ -0,0 +1,144 @@ +/* +0 - cislo registra / prikaz +1 - recepient - 0 = master, 1 = slave (slave je automaticky group a broadcast) +2 - r/rw - read/write +3- register name - nazov registra / prikazu (len pre info - zobrazenie v aplikacii) + +4,5,6,7, - jednotlive byte-y - nazov byte-u +4-7 - RES. a prazdny string "" sa nezobrazia!!! +*/ + +//124 zaznamov +const registers = [ + ["0","1","R","Status","","",""], + ["1","1","RW","Dimming","R-Channel ","G-Channel","B-Channel ","W - Channel"], + ["2","1","R","Device types","","",".",""], + ["3","1","RW","Group addresses 1-4","Groups Add. 4","Groups Add. 3","Groups Add. 2","Groups Add. 1"], + ["4","1","RW","Group addresses 5-8","Groups Add. 8","Groups Add. 7","Groups Add. 6","Groups Add. 5"], + ["5","1","RW","Serial number (MAC)","","","",""], + ["6","1","RW","Time of dusk","HH","MM","SS","EXTRA"], + ["7","1","RW","Time of dawn","HH","MM","SS","EXTRA"], + ["8","1","RW","Time Schedule settings","TBD","TBD","Movement sensor","Time Schedule"], + ["9","1","RW","TS1 Time point 1","HH","MM","SS","Ext. Device"], + ["10","1","RW","TS1 Time point 1 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["11","1","RW","TS1 Time point 2","HH","MM","SS","Ext. Device"], + ["12","1","RW","TS1 Time point 2 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["13","1","RW","TS1 Time point 3","HH","MM","SS","Ext. Device"], + ["14","1","RW","TS1 Time point 3 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["15","1","RW","TS1 Time point 4","HH","MM","SS","Ext. Device"], + ["16","1","RW","TS1 Time point 4 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["17","1","RW","TS1 Time point 5","HH","MM","SS","Ext. Device"], + ["18","1","RW","TS1 Time point 5 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["19","1","RW","TS1 Time point 6","HH","MM","SS","Ext. Device"], + ["20","1","RW","TS1 Time point 6 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["21","1","RW","TS1 Time point 7","HH","MM","SS","Ext. Device"], + ["22","1","RW","TS1 Time point 7 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["23","1","RW","TS1 Time point 8","HH","MM","SS","Ext. Device"], + ["24","1","RW","TS1 Time point 8 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["25","1","RW","TS1 Time point 9","HH","MM","SS","Ext. Device"], + ["26","1","RW","TS1 Time point 9 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["27","1","RW","TS1 Time point 10","HH","MM","SS","Ext. Device"], + ["28","1","RW","TS1 Time point 10 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["29","1","RW","TS1 Time point 11","HH","MM","SS","Ext. Device"], + ["30","1","RW","TS1 Time point 11 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["31","1","RW","TS1 Time point 12","HH","MM","SS","Ext. Device"], + ["32","1","RW","TS1 Time point 12 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["33","1","RW","TS1 Time point 13","HH","MM","SS","Ext. Device"], + ["34","1","RW","TS1 Time point 13 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["35","1","RW","TS1 Time point 14","HH","MM","SS","Ext. Device"], + ["36","1","RW","TS1 Time point 14 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["37","1","RW","TS1 Time point 15","HH","MM","SS","Ext. Device"], + ["38","1","RW","TS1 Time point 15 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["39","1","RW","TS1 Time point 16","HH","MM","SS","Ext. Device"], + ["40","1","RW","TS1 Time point 16 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["41","1","RW","TS2 Time point 1","HH","MM","SS","Ext. Device"], + ["42","1","RW","TS2 Time point 1 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["43","1","RW","TS2 Time point 2","HH","MM","SS","Ext. Device"], + ["44","1","RW","TS2 Time point 2 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["45","1","RW","TS2 Time point 3","HH","MM","SS","Ext. Device"], + ["46","1","RW","TS2 Time point 3 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["47","1","RW","TS2 Time point 4","HH","MM","SS","Ext. Device"], + ["48","1","RW","TS2 Time point 4 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["49","1","RW","TS2 Time point 5","HH","MM","SS","Ext. Device"], + ["50","1","RW","TS2 Time point 5 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["51","1","RW","TS2 Time point 6","HH","MM","SS","Ext. Device"], + ["52","1","RW","TS2 Time point 6 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["53","1","RW","TS2 Time point 7","HH","MM","SS","Ext. Device"], + ["54","1","RW","TS2 Time point 7 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["55","1","RW","TS2 Time point 8","HH","MM","SS","Ext. Device"], + ["56","1","RW","TS2 Time point 8 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["57","1","RW","TS2 Time point 9","HH","MM","SS","Ext. Device"], + ["58","1","RW","TS2 Time point 9 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["59","1","RW","TS2 Time point 10","HH","MM","SS","Ext. Device"], + ["60","1","RW","TS2 Time point 10 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["61","1","RW","TS2 Time point 11","HH","MM","SS","Ext. Device"], + ["62","1","RW","TS2 Time point 11 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["63","1","RW","TS2 Time point 12","HH","MM","SS","Ext. Device"], + ["64","1","RW","TS2 Time point 12 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["65","1","RW","TS2 Time point 13","HH","MM","SS","Ext. Device"], + ["66","1","RW","TS2 Time point 13 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["67","1","RW","TS2 Time point 14","HH","MM","SS","Ext. Device"], + ["68","1","RW","TS2 Time point 14 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["69","1","RW","TS2 Time point 15","HH","MM","SS","Ext. Device"], + ["70","1","RW","TS2 Time point 15 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["71","1","RW","TS2 Time point 16","HH","MM","SS","Ext. Device"], + ["72","1","RW","TS2 Time point 16 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["73","1","RW","Power meter status","TBD","","",""], + ["74","1","R","Input Voltage","","","",""], + ["75","1","R","Input Current","","","",""], + ["76","1","R","Input Power","","","",""], + ["77","1","R","Cos phi","","","",""], + ["78","1","R","Frequency","","","",""], + ["79","1","RW","Energy","","","",""], + ["80","1","RW","Lifetime","","","",""], + ["81","1","RW","Power on cycles (input)","","","",""], + ["82","1","RW","Power on cycles (relay)","","","",""], + ["83","1","R","Time since last power on","","","",""], + ["84","1","R","Accelerometer data","","","",""], + ["85","1","RW","GPS latitude","pos/neg","deg","min ","sec"], + ["86","1","RW","GPS longitude","pos/neg","deg","min ","sec"], + ["87","1","RW","Actual time","HH","MM","SS","RES."], + ["88","1","RW","Actual date","Day of week","Day","Month","Year"], + ["89","1","R","Production data 1","","","",""], + ["90","1","R","Production data 2","","","",""], + ["91","1","RW","Network ID","NID3","NID2","NID1","NID0"], + ["95","1","RW","Actual Lux level from cabinet","RES.","RES.","HB","LB"], + ["96","1","RW","Threshold lux level","Dusk HB","Dusk LB","Dawn HB","Dawn LB"], + ["97","1","RW","Adjust period","Dusk HB","Dusk LB","Dawn HB","Dawn LB"], + ["98","1","RW","Offset","RES.","RES.","Dusk","Dawn"], + ["99","1","RW","CCT min/max range","max-H","max-L","min-H","min-L"], + ["100","1","RW","DALI interface","Cmd ID","Add","Cmd","Resp"], + ["101","1","RW","Module FW ver","v1","v2","v3","v4"], + ["102","1","RW","Module MAC-H","unused","unused","M1","M2"], + ["103","1","RW","Module MAC-L","M3","M4","M5","M6"], + ["122","1","R","FW update status/control register","Byte3","Byte2","Byte1","Byte0"], + ["123","1","R","FW update - data index","Byte3","Byte2","Byte1","Byte0"], + ["124","1","R","FW update - data","Byte3","Byte2","Byte1","Byte0"], + ["0","0","R","Status","","","",""], + ["1","0","RW","Control register","RES.","RES.","RES.","init mode enable"], + ["2","0","R","Device types","","","",""], + ["3","0","R","Serial number (MAC)","","","",""], + ["4","0","R","Production data 1","","","",""], + ["5","0","R","Production data 2","","","",""], + ["6","0","RW","Network ID","NID3","NID2","NID1","NID0"], + ["7","0","RW","RS232 settings","param.","param.","Baudrate H","Baudrate L"], + ["8","0","R","Accelerometer data","","","",""], + ["9","0","RW","Module FW ver","v1","v2","v3","v4"], + ["10","0","RW","Module MAC-H","unused","unused","M1","M2"], + ["11","0","RW","Module MAC-L","M3","M4","M5","M6"], + ["32","0","RW","FW update status/control register","Byte3","Byte2","Byte1","Byte0"], + ["33","0","RW","FW update - data index","Byte3","Byte2","Byte1","Byte0"], + ["34","0","RW","FW update - data","Byte3","Byte2","Byte1","Byte0"], + ["125","0","RW","Debug Register","Byte3","Byte2","Byte1","Byte0"], + ["126","0","RW","Network Control Register","Byte3","Byte2","Byte1","Byte0"], + ["127","0","R","Network Status Register","Byte3","Byte2","Byte1","Byte0"], + ["128","0","RW","Node XX Serial Number Register","SER3","SER2","SER1","SER0"], + ["256","0","R","Node XX Network Status Register","","","",""] +]; + +let register = {}; + +module.exports = { + registers, + register +} \ No newline at end of file diff --git a/RVO43/flow/helper/serialport_helper.js b/RVO43/flow/helper/serialport_helper.js new file mode 100755 index 0000000..7f5920d --- /dev/null +++ b/RVO43/flow/helper/serialport_helper.js @@ -0,0 +1,99 @@ +const { exec } = require('child_process'); + +function openPort(port) { + return new Promise((resolve, reject) => { + + var callbackError = function(err) { + port.removeListener('error', callbackError); + port.removeListener('open', callbackError); + + reject(err.message); + }; + + var callbackOpen = function(data) { + port.removeListener('error', callbackError); + port.removeListener('open', callbackOpen); + + resolve("port open: ok"); + }; + + port.on('error', callbackError); + port.on('open', callbackOpen); + + port.open(); + + }) +} + +function runSyncExec(command) { + return new Promise((resolve, reject) => { + + exec(command, (error, stdout, stderr) => { + if (error == null) resolve(stdout); + reject(error); + }); + + }) +} + +async function writeData(port, data, readbytes, timeout) { + return new Promise((resolve, reject) => { + + // 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) { + + port.write(Buffer.from(data), function(err) { + if (err) { + reject(err.message); + } + }); + + 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 +} diff --git a/RVO43/flow/helper/suncalc.js b/RVO43/flow/helper/suncalc.js new file mode 100755 index 0000000..c9ca56d --- /dev/null +++ b/RVO43/flow/helper/suncalc.js @@ -0,0 +1,317 @@ +/* + (c) 2011-2015, Vladimir Agafonkin + SunCalc is a JavaScript library for calculating sun/moon position and light phases. + https://github.com/mourner/suncalc +*/ + +(function () { 'use strict'; + +// shortcuts for easier to read formulas + +var PI = Math.PI, + sin = Math.sin, + cos = Math.cos, + tan = Math.tan, + asin = Math.asin, + atan = Math.atan2, + acos = Math.acos, + rad = PI / 180; + +// sun calculations are based on http://aa.quae.nl/en/reken/zonpositie.html formulas + + +// date/time constants and conversions + +var dayMs = 1000 * 60 * 60 * 24, + J1970 = 2440588, + J2000 = 2451545; + +function toJulian(date) { return date.valueOf() / dayMs - 0.5 + J1970; } +function fromJulian(j) { return new Date((j + 0.5 - J1970) * dayMs); } +function toDays(date) { return toJulian(date) - J2000; } + + +// general calculations for position + +var e = rad * 23.4397; // obliquity of the Earth + +function rightAscension(l, b) { return atan(sin(l) * cos(e) - tan(b) * sin(e), cos(l)); } +function declination(l, b) { return asin(sin(b) * cos(e) + cos(b) * sin(e) * sin(l)); } + +function azimuth(H, phi, dec) { return atan(sin(H), cos(H) * sin(phi) - tan(dec) * cos(phi)); } +function altitude(H, phi, dec) { return asin(sin(phi) * sin(dec) + cos(phi) * cos(dec) * cos(H)); } + +function siderealTime(d, lw) { return rad * (280.16 + 360.9856235 * d) - lw; } + +function astroRefraction(h) { + if (h < 0) // the following formula works for positive altitudes only. + h = 0; // if h = -0.08901179 a div/0 would occur. + + // formula 16.4 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + // 1.02 / tan(h + 10.26 / (h + 5.10)) h in degrees, result in arc minutes -> converted to rad: + return 0.0002967 / Math.tan(h + 0.00312536 / (h + 0.08901179)); +} + +// general sun calculations + +function solarMeanAnomaly(d) { return rad * (357.5291 + 0.98560028 * d); } + +function eclipticLongitude(M) { + + var C = rad * (1.9148 * sin(M) + 0.02 * sin(2 * M) + 0.0003 * sin(3 * M)), // equation of center + P = rad * 102.9372; // perihelion of the Earth + + return M + C + P + PI; +} + +function sunCoords(d) { + + var M = solarMeanAnomaly(d), + L = eclipticLongitude(M); + + return { + dec: declination(L, 0), + ra: rightAscension(L, 0) + }; +} + + +var SunCalc = {}; + + +// calculates sun position for a given date and latitude/longitude + +SunCalc.getPosition = function (date, lat, lng) { + + var lw = rad * -lng, + phi = rad * lat, + d = toDays(date), + + c = sunCoords(d), + H = siderealTime(d, lw) - c.ra; + + return { + azimuth: azimuth(H, phi, c.dec), + altitude: altitude(H, phi, c.dec) + }; +}; + + +// sun times configuration (angle, morning name, evening name) + +var times = SunCalc.times = [ + [-0.833, 'sunrise', 'sunset' ], + [ -0.3, 'sunriseEnd', 'sunsetStart' ], + [ -6, 'dawn', 'dusk' ], + [ -12, 'nauticalDawn', 'nauticalDusk'], + [ -18, 'nightEnd', 'night' ], + [ 6, 'goldenHourEnd', 'goldenHour' ] +]; + +// adds a custom time to the times config + +SunCalc.addTime = function (angle, riseName, setName) { + times.push([angle, riseName, setName]); +}; + + +// calculations for sun times + +var J0 = 0.0009; + +function julianCycle(d, lw) { return Math.round(d - J0 - lw / (2 * PI)); } + +function approxTransit(Ht, lw, n) { return J0 + (Ht + lw) / (2 * PI) + n; } +function solarTransitJ(ds, M, L) { return J2000 + ds + 0.0053 * sin(M) - 0.0069 * sin(2 * L); } + +function hourAngle(h, phi, d) { return acos((sin(h) - sin(phi) * sin(d)) / (cos(phi) * cos(d))); } +function observerAngle(height) { return -2.076 * Math.sqrt(height) / 60; } + +// returns set time for the given sun altitude +function getSetJ(h, lw, phi, dec, n, M, L) { + + var w = hourAngle(h, phi, dec), + a = approxTransit(w, lw, n); + return solarTransitJ(a, M, L); +} + + +// calculates sun times for a given date, latitude/longitude, and, optionally, +// the observer height (in meters) relative to the horizon + +SunCalc.getTimes = function (date, lat, lng, height) { + + height = height || 0; + + var lw = rad * -lng, + phi = rad * lat, + + dh = observerAngle(height), + + d = toDays(date), + n = julianCycle(d, lw), + ds = approxTransit(0, lw, n), + + M = solarMeanAnomaly(ds), + L = eclipticLongitude(M), + dec = declination(L, 0), + + Jnoon = solarTransitJ(ds, M, L), + + i, len, time, h0, Jset, Jrise; + + + var result = { + solarNoon: fromJulian(Jnoon), + nadir: fromJulian(Jnoon - 0.5) + }; + + for (i = 0, len = times.length; i < len; i += 1) { + time = times[i]; + h0 = (time[0] + dh) * rad; + + Jset = getSetJ(h0, lw, phi, dec, n, M, L); + Jrise = Jnoon - (Jset - Jnoon); + + result[time[1]] = fromJulian(Jrise); + result[time[2]] = fromJulian(Jset); + } + + return result; +}; + + +// moon calculations, based on http://aa.quae.nl/en/reken/hemelpositie.html formulas + +function moonCoords(d) { // geocentric ecliptic coordinates of the moon + + var L = rad * (218.316 + 13.176396 * d), // ecliptic longitude + M = rad * (134.963 + 13.064993 * d), // mean anomaly + F = rad * (93.272 + 13.229350 * d), // mean distance + + l = L + rad * 6.289 * sin(M), // longitude + b = rad * 5.128 * sin(F), // latitude + dt = 385001 - 20905 * cos(M); // distance to the moon in km + + return { + ra: rightAscension(l, b), + dec: declination(l, b), + dist: dt + }; +} + +SunCalc.getMoonPosition = function (date, lat, lng) { + + var lw = rad * -lng, + phi = rad * lat, + d = toDays(date), + + c = moonCoords(d), + H = siderealTime(d, lw) - c.ra, + h = altitude(H, phi, c.dec), + // formula 14.1 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + pa = atan(sin(H), tan(phi) * cos(c.dec) - sin(c.dec) * cos(H)); + + h = h + astroRefraction(h); // altitude correction for refraction + + return { + azimuth: azimuth(H, phi, c.dec), + altitude: h, + distance: c.dist, + parallacticAngle: pa + }; +}; + + +// calculations for illumination parameters of the moon, +// based on http://idlastro.gsfc.nasa.gov/ftp/pro/astro/mphase.pro formulas and +// Chapter 48 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + +SunCalc.getMoonIllumination = function (date) { + + var d = toDays(date || new Date()), + s = sunCoords(d), + m = moonCoords(d), + + sdist = 149598000, // distance from Earth to Sun in km + + phi = acos(sin(s.dec) * sin(m.dec) + cos(s.dec) * cos(m.dec) * cos(s.ra - m.ra)), + inc = atan(sdist * sin(phi), m.dist - sdist * cos(phi)), + angle = atan(cos(s.dec) * sin(s.ra - m.ra), sin(s.dec) * cos(m.dec) - + cos(s.dec) * sin(m.dec) * cos(s.ra - m.ra)); + + return { + fraction: (1 + cos(inc)) / 2, + phase: 0.5 + 0.5 * inc * (angle < 0 ? -1 : 1) / Math.PI, + angle: angle + }; +}; + + +function hoursLater(date, h) { + return new Date(date.valueOf() + h * dayMs / 24); +} + +// calculations for moon rise/set times are based on http://www.stargazing.net/kepler/moonrise.html article + +SunCalc.getMoonTimes = function (date, lat, lng, inUTC) { + var t = new Date(date); + if (inUTC) t.setUTCHours(0, 0, 0, 0); + else t.setHours(0, 0, 0, 0); + + var hc = 0.133 * rad, + h0 = SunCalc.getMoonPosition(t, lat, lng).altitude - hc, + h1, h2, rise, set, a, b, xe, ye, d, roots, x1, x2, dx; + + // go in 2-hour chunks, each time seeing if a 3-point quadratic curve crosses zero (which means rise or set) + for (var i = 1; i <= 24; i += 2) { + h1 = SunCalc.getMoonPosition(hoursLater(t, i), lat, lng).altitude - hc; + h2 = SunCalc.getMoonPosition(hoursLater(t, i + 1), lat, lng).altitude - hc; + + a = (h0 + h2) / 2 - h1; + b = (h2 - h0) / 2; + xe = -b / (2 * a); + ye = (a * xe + b) * xe + h1; + d = b * b - 4 * a * h1; + roots = 0; + + if (d >= 0) { + dx = Math.sqrt(d) / (Math.abs(a) * 2); + x1 = xe - dx; + x2 = xe + dx; + if (Math.abs(x1) <= 1) roots++; + if (Math.abs(x2) <= 1) roots++; + if (x1 < -1) x1 = x2; + } + + if (roots === 1) { + if (h0 < 0) rise = i + x1; + else set = i + x1; + + } else if (roots === 2) { + rise = i + (ye < 0 ? x2 : x1); + set = i + (ye < 0 ? x1 : x2); + } + + if (rise && set) break; + + h0 = h2; + } + + var result = {}; + + if (rise) result.rise = hoursLater(t, rise); + if (set) result.set = hoursLater(t, set); + + if (!rise && !set) result[ye > 0 ? 'alwaysUp' : 'alwaysDown'] = true; + + return result; +}; + + +// export as Node module / AMD module / browser variable +if (typeof exports === 'object' && typeof module !== 'undefined') module.exports = SunCalc; +else if (typeof define === 'function' && define.amd) define(SunCalc); +else window.SunCalc = SunCalc; + +}()); diff --git a/RVO43/flow/helper/utils.js b/RVO43/flow/helper/utils.js new file mode 100755 index 0000000..dbffe45 --- /dev/null +++ b/RVO43/flow/helper/utils.js @@ -0,0 +1,161 @@ +const fs = require('fs').promises; + +function bytesToInt(bytes, numberOfBytes) { + let buffer = []; + if (Array.isArray(bytes)) { + buffer = bytes.slice(0); + if (numberOfBytes != undefined) { + buffer = bytes.slice(bytes.length - numberOfBytes); + } + } + else buffer.push(bytes); + + let result = 0; + for (let i = 0; i < buffer.length; i++) { + result = (result << 8) | buffer[i]; + } + + return result >>> 0; //ensure it's an unsigned 32-bit number +} + +function resizeArray(arr, newSize, defaultValue) { + while (newSize > arr.length) + arr.push(defaultValue); + arr.length = newSize; +} + +longToByteArray = function(/*long*/long) { + // we want to represent the input as a 8-bytes array + var byteArray = [0, 0, 0, 0, 0, 0, 0, 0]; + + for (var index = 0; index < byteArray.length; index++) { + var byte = long & 0xff; + byteArray[index] = byte; + long = (long - byte) / 256; + } + + return byteArray; +}; + +function addDays(date, days) { + var result = new Date(date); + result.setDate(result.getDate() + days); + return result; +} + +/* +sleep(2000).then(() => { + // Do something after the sleep! + + +}); +*/ + +function sleep(time) { + return new Promise((resolve) => setTimeout(resolve, time)); +} + +function isEmptyObject(obj) { + for (var name in obj) { + return false; + } + return true; +} + +function emptyJsObject(jsObject) { + Object.keys(jsObject).forEach(key => delete jsObject[key]); +} + +function convertUTCDateToLocalDate(date) { + var newDate = new Date(date); + newDate.setMinutes(date.getMinutes() + date.getTimezoneOffset()); + return newDate; +} + +function addZeroBefore(n) { + return (n < 10 ? '0' : '') + n; +} + + +/** + * Asynchronously writes data to a file. + * + * @param {string} filePath The path to the file. + * @param {string} data The data to write to the file. + * @param {boolean} [append=false] If true, appends the data to the file. If false, it overwrites the file. + */ +async function writeToFile(filePath, data, append = false) { + if (typeof data !== 'string') data = JSON.stringify(data, null, 2); + try { + if (append) { + // Append the data to the end of the file. This is the simplest way to append. + await fs.appendFile(filePath, data, 'utf8'); + console.log(`Successfully appended data to ${filePath} using fs.appendFile.`); + } else { + // Overwrite the file with the new data. + await fs.writeFile(filePath, data, 'utf8'); + console.log(`Successfully wrote (overwrote) data to ${filePath} using fs.writeFile.`); + } + } catch (error) { + console.error(`Error writing to file ${filePath}:`, error); + } +} + + + /** + * Checks if an item is present in an array and adds it if it's not. + * * @param {Array} arr The array to check. + * @param {*} item The item to add. + * @returns {Array} The modified array. + */ +const addToArrayIfUnique = (arr, item) => { + if (!arr.includes(item)) { + arr.push(item); + } + return arr; +}; + + +var convertBase = function() { + + function convertBase(baseFrom, baseTo) { + return function(num) { + return parseInt(num, baseFrom).toString(baseTo); + + }; + } + + // binary to decimal + convertBase.bin2dec = convertBase(2, 10); + + // binary to hexadecimal + convertBase.bin2hex = convertBase(2, 16); + + // decimal to binary + convertBase.dec2bin = convertBase(10, 2); + + // decimal to hexadecimal + convertBase.dec2hex = convertBase(10, 16); + + // hexadecimal to binary + convertBase.hex2bin = convertBase(16, 2); + + // hexadecimal to decimal + convertBase.hex2dec = convertBase(16, 10); + + return convertBase; +}(); + +module.exports = { + bytesToInt, + longToByteArray, + addDays, + addZeroBefore, + resizeArray, + isEmptyObject, + emptyJsObject, + sleep, + convertUTCDateToLocalDate, + writeToFile, + addToArrayIfUnique +} diff --git a/RVO43/flow/httprequest.js b/RVO43/flow/httprequest.js new file mode 100755 index 0000000..469c8cb --- /dev/null +++ b/RVO43/flow/httprequest.js @@ -0,0 +1,137 @@ +exports.id = 'httprequest'; +exports.title = 'HTTP Request'; +exports.group = 'HTTP'; +exports.color = '#5D9CEC'; +exports.input = true; +exports.version = '2.0.1'; +exports.output = 1; +exports.author = 'Peter Širka'; +exports.icon = 'cloud-upload'; + +exports.html = `
+
@(URL address)
+
+
+
@(HTTP method)
+
+
+
@(Serialization)
+
+
+
@(Download the content in chunks)
+
@(Keep persistent cookies)
+
@(Disable DNS cache)
+
@(Keep alive connection)
+
+
+
+
@(Custom headers)
+
@(Cookies)
+
+
+
+ +
+
+
+
@(User)
+
+
+
@(Password)
+
+
+
+
+
`; + +exports.readme = `# Request + +This component creates a request with received data. + +__Response:__ +\`\`\`javascript +{ + data: String, + headers: Object, + status: Number, + host: String +} +\`\`\` + +__Dynamic arguments__: +Are performed via FlowData repository and can be used for URL address or for custom headers/cookies/auth. Use \`repository\` component for creating of dynamic arguments. Dynamic values are replaced in the form \`{key}\`: + +- url address e.g. \`https://.../{key}/\` +- headers values e.g. \`{token}\` +- cookies values e.g. \`{token}\``; + +exports.install = function(instance) { + + var can = false; + var flags = null; + var cookies2 = null; + + instance.on('data', function(response) { + can && instance.custom.send(response); + }); + + instance.custom.send = function(response) { + var options = instance.options; + + var headers = null; + var cookies = null; + + options.headers && Object.keys(options.headers).forEach(function(key) { + !headers && (headers = {}); + headers[key] = response.arg(options.headers[key]); + }); + + if (options.username && options.userpassword) { + !headers && (headers = {}); + headers['Authorization'] = 'Basic ' + U.createBuffer(response.arg(options.username + ':' + options.userpassword)).toString('base64'); + } + + options.cookies && Object.keys(options.cookies).forEach(function(key) { + !cookies && (cookies = {}); + cookies[key] = response.arg(options.cookies[key]); + }); + + if (options.chunks) { + U.download(response.arg(options.url), flags, options.stringify === 'none' ? null : response.data, function(err, response) { + response.on('data', (chunks) => instance.send2(chunks)); + }, cookies || cookies2, headers); + } else { + U.request(response.arg(options.url), flags, options.stringify === 'none' ? null : response.data, 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) + instance.error(err, response); + }, cookies || cookies2, headers); + } + }; + + instance.reconfigure = function() { + var options = instance.options; + can = options.url && options.url && options.method && options.stringify ? true : false; + instance.status(can ? '' : 'Not configured', can ? undefined : 'red'); + + if (!can) + return; + + flags = []; + flags.push(options.method.toLowerCase()); + options.stringify === 'json' && flags.push('json'); + options.stringify === 'raw' && flags.push('raw'); + options.keepalive && flags.push('keepalive'); + !options.nodns && flags.push('dnscache'); + if (options.persistentcookies) { + flags.push('cookies'); + cookies2 = {}; + } else + cookies2 = null; + }; + + instance.on('options', instance.reconfigure); + instance.reconfigure(); +}; \ No newline at end of file diff --git a/RVO43/flow/httpresponse.js b/RVO43/flow/httpresponse.js new file mode 100755 index 0000000..160a3bb --- /dev/null +++ b/RVO43/flow/httpresponse.js @@ -0,0 +1,76 @@ +exports.id = 'httpresponse'; +exports.title = 'HTTP Response'; +exports.group = 'HTTP'; +exports.color = '#5D9CEC'; +exports.icon = 'arrow-right'; +exports.input = true; +exports.output = ['#666D76']; +exports.version = '2.0.0'; +exports.author = 'Martin Smola'; +exports.readme = `# HTTP response + +HTTP response will respond with data recieved using data-type set in Settings form or plain text if not set. Output is the message duration \`Number\` in seconds.`; + +exports.html = `
+
@(Response data-type)
+
JSON is by default.
+
`; + +exports.install = function(instance) { + + var dursum = 0; + var durcount = 0; + + instance.on('data', function(flowdata) { + + var ctrl = flowdata.repository.controller; + var data = flowdata.data; + + if (!ctrl) { + instance.throw('No controller to use for response!'); + return; + } + + durcount++; + dursum += ((new Date() - flowdata.begin) / 1000).floor(2); + setTimeout2(instance.id, instance.custom.duration, 500, 10); + + ctrl.$flowdata = flowdata; + + var datatype = instance.options.datatype || 'json'; + if (datatype === 'emptyresponse') + return ctrl.plain(''); + + if (datatype !== 'json' && typeof(data) !== 'string') { + instance.throw('Incorect type of data, expected string, got ' + typeof(data)); + ctrl.plain(data == null ? '' : data.toString()); + return; + } + + switch(datatype) { + case 'html': + ctrl.content(data, 'text/html'); + break; + case 'plain': + ctrl.plain(data); + break; + case 'xml': + ctrl.content(data, 'text/xml'); + break; + default: + ctrl.json(data); + break; + } + }); + + instance.on('service', function() { + dursum = 0; + durcount = 0; + }); + + instance.custom.duration = function() { + var avg = (dursum / durcount).floor(2); + instance.status(avg + ' sec.'); + instance.send2(0, avg); + }; +}; diff --git a/RVO43/flow/httproute.js b/RVO43/flow/httproute.js new file mode 100755 index 0000000..583a19d --- /dev/null +++ b/RVO43/flow/httproute.js @@ -0,0 +1,326 @@ +exports.id = 'httproute'; +exports.title = 'HTTP Route'; +exports.group = 'HTTP'; +exports.color = '#5D9CEC'; +exports.icon = 'globe'; +exports.input = false; +exports.output = ['#6CAC5A', '#37BC9B']; +exports.version = '1.2.3'; +exports.author = 'Martin Smola'; +exports.cloning = false; +exports.options = { method: 'GET', url: '', size: 5, cacheexpire: '5 minutes', cachepolicy: 0, timeout: 5 }; +exports.dateupdated = '2021-01-21 18:30d'; +exports.readme = `# HTTP route + +__Outputs__: +- first output: raw data (cache is empty or is disabled) +- second output: cached data + +If one of the outputs is disabled then automatic responce with code "503 service unavailable" is sent. + +When a request comes in bellow object is available at \`flowdata.data\`: + +\`\`\`javascript +{ + params: { id: '1' }, // params for dynamic routes, e.g. /test/{id} + query: { msg: 'Hello' }, // parsed query string, e.g. /test/1?msg=Hello + body: { test: 'OK' }, // object if json requests otherwise string + headers: {}, // headers data + session: {}, // session data + user: {}, // user data + files: [], // uploaded files + url: '/users/', // a relative URL address + referrer: '/', // referrer + mobile: false, // determines mobile device + robot: false, // determines search robots/crawlsers + language: 'en' // determines language +} +\`\`\` + +See [documentation for flags](https://docs.totaljs.com/latest/en.html#api~HttpRouteOptionsFlags~unauthorize). These method flags are set automatically e.g. \`get, post, put, patch or delete\` + +--- + +\`id:ROUTE_ID\` flag cannot be used since it's already used by this component internally`; + +exports.html = `
+
+ +
+ +
+
+
@(HTTP method)
+
+
+
@(URL address)
+
+
+
+
+
@(Additional flags)
+
@(Separate flags by comma e.g. json, authorize)
+
+
+
@(Max. request size)
+
@(In kB kilobytes)
+
+
+
@(Timeout)
+
@(In seconds.)
+
+
+
+
+
+
@(Automatically respond with 200 OK?)
+
@(If not checked you need to use HTTP response component to respond to the request.)
+
+
@(Custom headers)
+
@(Cookies)
+
+
+
+
+
+
@(Cache policy)
+
@(User instance must contain id property.)
+
+
+
@(Expiration)
+
@(E.g. 5 minutes)
+
+
+
+`; + +exports.install = function(instance) { + + var route; + + var uninstall = function(id) { + if (F.is4) { + route && route.remove(); + route = null; + } else + UNINSTALL('route', id); + }; + + instance.custom.emptyresponse = function(self) { + self.plain(); + }; + + instance.reconfigure = function() { + + var options = instance.options; + + if (!options.url) { + instance.status('Not configured', 'red'); + return; + } + + if (typeof(options.flags) === 'string') + options.flags = options.flags.split(',').trim(); + + uninstall('id:' + instance.id); + + var flags = options.flags || []; + + flags.push('id:' + instance.id); + + if (!F.is4) + flags.push(options.method.toLowerCase()); + + options.timeout && flags.push(options.timeout * 1000); + + // Make unique values + flags = flags.filter(function(v, i, a) { + if(F.is4 && v.toString().toLowerCase() === options.method.toLowerCase()) + return false; // remove method + return a.indexOf(v) === i; + }); + + options.flags = flags; + var handler = function() { + + if (instance.paused || (instance.isDisabled && (instance.isDisabled('output', 0) || instance.isDisabled('output', 1)))) { + instance.status('503 Service Unavailable'); + this.status = 503; + this.json(); + return; + } + + var key; + var self = this; + + if (instance.options.emptyresponse) { + instance.status('200 OK'); + setTimeout(instance.custom.emptyresponse, 100, self); + + if (instance.hasConnection(0)) { + var data = instance.make({ + query: self.query, + body: self.body, + session: self.session, + user: self.user, + files: self.files, + headers: self.req.headers, + url: self.url, + params: self.params + }); + instance.send2(0, data); + } + + return; + } + + switch (instance.options.cachepolicy) { + case 1: // URL + key = 'rro' + instance.id + self.url.hash(); + break; + case 2: // URL + query + case 3: // URL + query + user + key = self.url; + var keys = Object.keys(self.query); + keys.sort(); + for (var i = 0, length = keys.length; i < length; i++) + key += keys[i] + self.query[keys[i]] + '&'; + if (instance.options.cachepolicy === 3 && self.user) + key += 'iduser' + self.user.id; + key = 'rro' + instance.id + key.hash(); + break; + } + + if (key && F.cache.get2(key)) { + var data = instance.make(F.cache.get2(key)); + data.repository.controller = self; + instance.send2(1, data); + } else { + + var data = instance.make({ + query: self.query, + body: self.body, + session: self.session, + user: self.user, + files: self.files, + headers: self.req.headers, + url: self.url, + params: self.params, + mobile: self.mobile, + robot: self.robot, + referrer: self.referrer, + language: self.language + }); + + data.repository.controller = self; + instance.send2(0, data); + key && FINISHED(self.res, () => F.cache.set(key, self.$flowdata.data, instance.options.cacheexpire)); + } + }; + + if (F.is4) + route = ROUTE(options.method.toUpperCase() + ' ' + options.url, handler, flags, options.size || 5); + else + F.route(options.url, handler, flags, options.size || 5); + + instance.status('Listening', 'green'); + }; + + instance.reconfigure(); + instance.on('options', instance.reconfigure); + instance.on('close', function(){ + uninstall('id:' + instance.id); + }); +}; + +// check url exists +FLOW.trigger('httproutecheckurl', function(next, data) { + var url = data.url; + var method = data.method; + if (url[url.length - 1] !== '/') + url += '/'; + var exists = F.routes.web.findItem(r => r.urlraw === url && r.method === method); + next(exists != null); +}); + +exports.uninstall = function() { + FLOW.trigger('httproutecheckurl', null); +}; diff --git a/RVO43/flow/infosender.js b/RVO43/flow/infosender.js new file mode 100755 index 0000000..587724f --- /dev/null +++ b/RVO43/flow/infosender.js @@ -0,0 +1,81 @@ +exports.id = 'infosender'; +exports.title = 'Info sender'; +exports.version = '1.0.0'; +exports.group = 'Worksys'; +exports.color = '#2134B0'; +exports.input = 2; +exports.output = 1 +exports.icon = 'bolt'; + +const { networkInterfaces } = require('os'); + +exports.html = `
+
+
+
CSV Import
+
+
+
`; + +exports.readme = `# send all data to projects.worksys.io, required to monitor status of controller(unipi)`; + +exports.install = function(instance) { + + let id; + let allValues = {}; + let sendAllValuesInterval; + let configured = false; + + let now = new Date(); + console.log(exports.title, "INSTALLED", now.toLocaleString("sk-SK")); + + const nets = networkInterfaces(); + let ipAddresses = Object.create(null); // Or just '{}', an empty object + + for (const name of Object.keys(nets)) { + for (const net of nets[name]) { + // Skip over non-IPv4 and internal (i.e. 127.0.0.1) addresses + if (net.family === 'IPv4' && !net.internal) { + if (!ipAddresses[name]) { + ipAddresses[name] = []; + } + ipAddresses[name].push(net.address); + } + } + } + + function sendValues() { + if (!configured) return; + + if (Object.keys(allValues).length > 0) { + let dataToSend = { ...allValues }; + dataToSend.id = id; + dataToSend.ipAddresses = ipAddresses; + + instance.send(0, dataToSend); + + allValues = {}; + } + } + + instance.on("close", () => { + clearInterval(sendAllValuesInterval); + }) + + instance.on("0", _ => { + id = FLOW.GLOBALS.settings.project_id; + if (id) configured = true; + else console.log(exports.title, "InfoSender: Unable to send data, no id"); + }) + + instance.on("1", flowdata => { + allValues = { ...allValues, ...flowdata.data }; + //console.log("DATA RECEIVED", flowdata.data); + }) + + sendAllValuesInterval = setInterval(() => { + sendValues(); + }, 60000 * 3); + +} + diff --git a/RVO43/flow/modbus_reader.js b/RVO43/flow/modbus_reader.js new file mode 100755 index 0000000..d6d9dad --- /dev/null +++ b/RVO43/flow/modbus_reader.js @@ -0,0 +1,346 @@ +exports.id = 'modbus_reader'; +exports.title = 'Modbus reader'; +exports.version = '2.0.0'; +exports.group = 'Worksys'; +exports.color = '#2134B0'; +exports.input = 1; +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; +//number of phases inRVO +let phases; +//phases where voltage is 0 (set) +let noVoltage; +let energyToSwitchLamps; + +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.phases = this.buildPhases(); + + this.startSocket(); + } + + buildPhases = () => { + let a = []; + for (let i = 1; i <= phases; i++) { + a.push(`Phase_${i}_voltage`) + } + return a; + } + + startSocket = () => { + + let obj = this; + + if (this.socket) { + this.socket.removeAllListeners(); + this.socket = null; + } + + 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('Modbus_reader: Socket connection error', e); //'ECONNREFUSED' or 'ECONNRESET' ?? + }); + + this.socket.on('close', function() { + console.log('Modbus_reader: Socket connection closed - Waiting 10 seconds before connecting 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 we just start to loop devices from the beginning, or there is just 1 device in config, we wait whole timeoutInterval + if (this.indexInDeviceConfig == 0 || deviceConfig.length === 1) 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 (this.phases.includes(singleValue)) { + let l = singleValue.split("_"); + let phase = parseInt(l[1]); + + // console.log(values[singleValue], tbName); + + if (values[singleValue] == 0) { + noVoltage.add(phase); + sendNotification("modbus_reader: checkNullVoltage", tbName, "no_voltage_on_phase", { phase: phase }, "", SEND_TO.tb, instance, "voltage" + phase); + // console.log('no voltage') + } + else { + noVoltage.delete(phase); + // console.log('voltage detected') + sendNotification("modbus_reader: checkNullVoltage", tbName, "voltage_on_phase_restored", { phase: phase }, "", SEND_TO.tb, instance, "voltage" + phase); + } + } + }) + } + + /** + * function sends notification to slack and to tb, if EM total_power value changes more than numberOfNodes*15. This should show, that RVO lamps has been switched on or off + */ + lampSwitchNotification = (values) => { + + if (!values.hasOwnProperty("total_power")) return; + + const actualTotalPower = values.total_power; + + if (actualTotalPower > energyToSwitchLamps && 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 <= energyToSwitchLamps && 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; + } + + function main() { + + phases = FLOW.GLOBALS.settings.phases; + tbName = FLOW.GLOBALS.settings.rvoTbName; + noVoltage = FLOW.GLOBALS.settings.no_voltage; + energyToSwitchLamps = FLOW.GLOBALS.settings.energy_to_switch_lamps / 2.5; //half value is enought to show if lamps are turned on or off + if (deviceConfig.length) mainSocket = new SocketWithClients(); + else console.log("Modbus_reader: no modbus device in configuration"); + + // this notification is to show, that flow (unipi) has been restarted + sendNotification("modbus_reader", tbName, "flow_restart", {}, "", SEND_TO.slack, instance); + } + + instance.on("0", function(_) { + main(); + }) + +} + diff --git a/RVO43/flow/monitorconsumption.js b/RVO43/flow/monitorconsumption.js new file mode 100755 index 0000000..64cc58e --- /dev/null +++ b/RVO43/flow/monitorconsumption.js @@ -0,0 +1,156 @@ +exports.id = 'monitorconsumption'; +exports.title = 'Consumption'; +exports.version = '1.0.0'; +exports.author = 'Peter Širka'; +exports.group = 'Monitoring'; +exports.color = '#967ADC'; +exports.input = 0; +exports.output = 1; +exports.icon = 'bug'; +exports.options = { interval: 5000, enabled: true, monitorconsumption: true, monitorsize: true, monitorconnections: true, monitorfiles: true }; +exports.click = true; +exports.readme = `# Consumption monitoring + +This component measure CPU and memory consumption, open files and open connections of this application. It uses these Linux commands: \`ps\`, \`lsof\`, \`netstat\` and \`df\`. + +__Data Example__: + +\`\`\`javascript +{ + cpu: 0, // percentage + memory: 4096, // in bytes + size: 34303, // directory size in bytes + files: 34, // count of open files + connections: 343, // count of connections + uptime: '1-12:34:00' +} +\`\`\``; + +exports.html = `
+
+
+
@(Interval in milliseconds)
+
+
+
+
Monitor: Consumption + uptime
+
Monitor: Count of open files
+
Monitor: Count of open connections
+
Monitor: Directory size
+
`; + +exports.install = function(instance) { + + var current = { cpu: 0, memory: 0, files: 0, connections: 0, size: 0, uptime: '', counter: 0 }; + var tproc = null; + var Exec = require('child_process').exec; + var reg_empty = /\s{2,}/g; + var reg_appdisksize = /^[\d.,]+/; + + instance.custom.run = function() { + + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + + var arr = []; + + // Get CPU and Memory consumption + instance.options.monitorconsumption && arr.push(function(next) { + Exec('ps -p {0} -o %cpu,rss,etime'.format(process.pid), function(err, response) { + + if (err) { + instance.throw(err); + } else { + var line = response.split('\n')[1]; + line = line.trim().replace(reg_empty, ' ').split(' '); + var cpu = line[0].parseFloat(); + current.cpu = cpu.floor(1); + current.memory = line[1].parseInt2() * 1024; // kB to bytes + current.uptime = line[2]; + } + + next(); + }); + }); + + // Get count of open files + instance.options.monitorfiles && arr.push(function(next) { + Exec('lsof -a -p {0} | wc -l'.format(process.pid), function(err, response) { + if (err) + instance.throw(err); + else + current.files = response.trim().parseInt2(); + next(); + }); + }); + + // Get count of opened network connections + instance.options.monitorconnections && arr.push(function(next) { + Exec('netstat -an | grep :{0} | wc -l'.format(F.port), function(err, response) { + if (err) { + instance.throw(err); + } else { + current.connections = response.trim().parseInt2() - 1; + if (current.connections < 0) + current.connections = 0; + } + next(); + }); + }); + + // Get directory size + instance.options.monitorsize && current.counter % 5 !== 0 && arr.push(function(next) { + Exec('du -hsb ' + process.cwd(), function(err, response) { + if (err) { + instance.throw(err); + } else { + var match = response.trim().match(reg_appdisksize); + match && (current.size = match.toString().trim().parseInt2()); + } + next(); + }); + }); + + arr.async(function() { + + tproc && clearTimeout(tproc); + + if (instance.options.enabled) { + tproc = setTimeout(instance.custom.run, instance.options.interval); + instance.send2(current); + } + + instance.custom.status(); + current.counter++; + }); + }; + + instance.custom.status = function() { + if (instance.options.enabled) + instance.status('{0}% / {1}'.format(current.cpu, current.memory.filesize())); + else + instance.status('Disabled', 'red'); + }; + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + + if (instance.options.enabled) { + current.counter = 0; + instance.custom.run(); + } + + }); + + instance.on('close', function() { + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + }); + + setTimeout(instance.custom.run, 1000); +}; \ No newline at end of file diff --git a/RVO43/flow/monitordisk.js b/RVO43/flow/monitordisk.js new file mode 100755 index 0000000..f4fdaa0 --- /dev/null +++ b/RVO43/flow/monitordisk.js @@ -0,0 +1,96 @@ +exports.id = 'monitordisk'; +exports.title = 'Disk'; +exports.version = '1.0.0'; +exports.author = 'Peter Širka'; +exports.group = 'Monitoring'; +exports.color = '#F6BB42'; +exports.output = 1; +exports.icon = 'hdd-o'; +exports.click = true; +exports.options = { interval: 8000, path: '/', enabled: true }; +exports.readme = `# Disk monitoring + +This component monitors disk \`bytes\` consumption in Linux systems. It uses \`df\` command. + +__Data Example__: + +\`\`\`javascript +{ + total: 474549649408, + used: 39125245952, + free: 411294994432 +} +\`\`\``; + +exports.html = `
+
+
+
@(Interval in milliseconds)
+
+
+
@(Path)
+
+
+
`; + +exports.install = function(instance) { + + var current = { total: 0, used: 0, free: 0, path: '', type: '', percentUsed: 0 }; + var tproc = null; + + instance.custom.run = function() { + + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + + if (!instance.options.enabled) + return; + + require('child_process').exec('df -hTB1 ' + instance.options.path, function(err, response) { + + tproc = setTimeout(instance.custom.run, instance.options.interval); + + if (err) { + instance.error(err); + return; + } + + response.parseTerminal(function(line) { + if (line[0][0] !== '/') + return; + current.total = line[2].parseInt(); + current.free = line[4].parseInt(); + current.used = line[3].parseInt(); + current.path = instance.options.path || '/'; + current.type = line[1]; + current.percentUsed = line[5]; + instance.custom.status(); + instance.send2(current); + }); + }); + }; + + instance.custom.status = function() { + if (instance.options.enabled) + instance.status(current.free.filesize() + ' / ' + current.total.filesize()); + else + instance.status('Disabled', 'red'); + }; + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + instance.options.enabled && instance.custom.run(); + }); + + instance.on('close', function() { + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + }); + + setTimeout(instance.custom.run, 1000); +}; \ No newline at end of file diff --git a/RVO43/flow/monitormemory.js b/RVO43/flow/monitormemory.js new file mode 100755 index 0000000..2decbc4 --- /dev/null +++ b/RVO43/flow/monitormemory.js @@ -0,0 +1,87 @@ +exports.id = 'monitormemory'; +exports.title = 'Memory'; +exports.version = '1.0.0'; +exports.author = 'Peter Širka'; +exports.group = 'Monitoring'; +exports.color = '#F6BB42'; +exports.output = 1; +exports.click = true; +exports.icon = 'microchip'; +exports.options = { interval: 8000, enabled: true }; +exports.readme = `# Memory monitoring + +This component monitors memory \`bytes\` consumption in Linux systems. It uses \`free\` command. + +__Data Example__: + +\`\`\`javascript +{ + total: 33558769664, + used: 1998868480, + free: 2653708288 +} +\`\`\``; + +exports.html = `
+
+
+
@(Interval in milliseconds)
+
+
+
`; + +exports.install = function(instance) { + + var current = { total: 0, used: 0, free: 0 }; + var tproc = null; + + instance.custom.run = function() { + + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + + if (!instance.options.enabled) + return; + + require('child_process').exec('free -b -t', function(err, response) { + + tproc = setTimeout(instance.custom.run, instance.options.interval); + + if (err) { + instance.error(err); + return; + } + + var memory = response.split('\n')[1].match(/\d+/g); + current.total = memory[0].parseInt(); + current.used = memory[1].parseInt() - memory[3].parseInt(); + current.free = current.total - current.used; + instance.custom.status(); + instance.send2(current); + }); + }; + + instance.custom.status = function() { + if (instance.options.enabled) + instance.status(current.free.filesize() + ' / ' + current.total.filesize()); + else + instance.status('Disabled', 'red'); + }; + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + instance.options.enabled && instance.custom.run(); + }); + + instance.on('close', function() { + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + }); + + setTimeout(instance.custom.run, 1000); +}; \ No newline at end of file diff --git a/RVO43/flow/nodesdb_changecheck.js b/RVO43/flow/nodesdb_changecheck.js new file mode 100755 index 0000000..9adab62 --- /dev/null +++ b/RVO43/flow/nodesdb_changecheck.js @@ -0,0 +1,77 @@ +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 = 2; +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); + } + } + + //kedze do slacku posielame stringy, na cloud musime previest vsetky stringy spat na objekty: + // Funkcia na parsovanie všetkých reťazcov v poli + const parseArray = (arr) => { + return arr.map(jsonString => JSON.parse(jsonString)); + }; + + 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); + if (FLOW.GLOBALS.settings.send_changed_node_numbers) instance.send(1, { aktualneNody: parseArray(zmenene), originalne: parseArray(Array.from(set2)) }); + } + 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/RVO43/flow/show_dbdata.js b/RVO43/flow/show_dbdata.js new file mode 100755 index 0000000..1e23ff7 --- /dev/null +++ b/RVO43/flow/show_dbdata.js @@ -0,0 +1,243 @@ +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 = 8; +exports.output = 1; + +const { exec } = require('child_process'); + +exports.install = 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 }) + }) + instance.on("5", _ => { + exec("sudo tail -n 25 monitor.txt", (err, stdout, stderr) => { + if (err || stderr) instance.send(0, { err, stderr }); + else instance.send(0, stdout); + }) + }) + instance.on("6", _ => { + exec("sudo tail -n 25 err.txt", (err, stdout, stderr) => { + if (err || stderr) instance.send(0, { err, stderr }); + else instance.send(0, stdout); + }) + }) + instance.on("7", _ => { + instance.send(0, FLOW.deviceStatus); + }) +}; + + +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/RVO43/flow/slack_filter.js b/RVO43/flow/slack_filter.js new file mode 100755 index 0000000..6618523 --- /dev/null +++ b/RVO43/flow/slack_filter.js @@ -0,0 +1,188 @@ +exports.id = 'slack_filter'; +exports.title = 'Slack Filter'; +exports.group = 'Citysys'; +exports.color = '#30E193'; +exports.input = 2; +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 = `
+
+
+
@(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('0', 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']['en']; + 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"] = []; + } + + instance.options.name = FLOW.GLOBALS.settings.rvo_name; + if (instance.options.name) { + instance.status('Running'); + running = true; + } else { + instance.status('Please run options again', 'red'); + running = false; + } + } catch (e) { + instance.error('Citysys connector: ' + e.message); + } + }; + + instance.on('options', instance.reconfigure); + + instance.on("1", _ => { + instance.reconfigure(); + }) +}; diff --git a/RVO43/flow/thermometer.js b/RVO43/flow/thermometer.js new file mode 100755 index 0000000..fc7074d --- /dev/null +++ b/RVO43/flow/thermometer.js @@ -0,0 +1,99 @@ +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 = 5;//minutes +let NUMBER_OF_FAILURES_TO_SEND_ERROR = 13; + +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) => { + + 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); + setTimeout(main, 20000); + }) +}; diff --git a/RVO43/flow/trigger.js b/RVO43/flow/trigger.js new file mode 100755 index 0000000..27545a8 --- /dev/null +++ b/RVO43/flow/trigger.js @@ -0,0 +1,79 @@ +exports.id = 'trigger'; +exports.title = 'Trigger'; +exports.group = 'Inputs'; +exports.color = '#F6BB42'; +exports.click = true; +exports.output = 1; +exports.version = '1.1.0'; +exports.author = 'Martin Smola'; +exports.icon = 'play'; + +exports.html = `
+
@(Data type (String by default))
+
@(Data)
+
Trigger 5s after initialization.
+
@(Useful when there's a need to run certain flow when the app restarts, etc.)
+
`; + +exports.readme = `# Trigger + +- Clicking on the component starts the chain +- Settings allows to set a data-type and a value`; + +exports.install = function(instance) { + + var value; + + instance.on('click', () => instance.send2(value)); + + instance.reconfigure = function() { + var options = instance.options; + value = null; + switch (options.datatype) { + case 'integer': + value = options.data.parseInt2('error'); + value = value === 'error' ? NaN : value; + break; + case 'float': + value = options.data.parseFloat2('error'); + value = value === 'error' ? NaN : value; + break; + case 'date': + options.data = options.data.toString(); + var num = options.data.parseInt('error'); + num === 'error' && (num = options.data.parseDate('error')); + num === 'error' && (num = null); + value = num ? new Date(num).toUTCString() : num; + break; + case 'object': + try { + value = (new Function('return ' + options.data))(); + } catch (e) { + instance.error(e); + } + break; + case 'boolean': + value = options.data.parseBoolean(); + break; + case 'buffer': + try { + value = U.createBuffer(options.data); + } catch (e) { + instance.error(e); + } + break; + case 'string': + default: + value = '' + (options.data || ''); + break; + } + }; + + instance.on('options', instance.reconfigure); + instance.reconfigure(); + + if (instance.options.restart) + setTimeout(function(){ + instance.send2(value); + }, 5000); +}; diff --git a/RVO43/flow/variables.txt b/RVO43/flow/variables.txt new file mode 100755 index 0000000..e69de29 diff --git a/RVO43/flow/virtualwirein.js b/RVO43/flow/virtualwirein.js new file mode 100755 index 0000000..38a4e42 --- /dev/null +++ b/RVO43/flow/virtualwirein.js @@ -0,0 +1,43 @@ +exports.id = 'virtualwirein'; +exports.title = 'Virtual wire in'; +exports.version = '1.0.0'; +exports.author = 'Martin Smola'; +exports.color = '#303E4D'; +exports.icon = 'sign-in'; +exports.input = false; +exports.output = 1; +exports.options = {}; +exports.readme = `# Virtual wire in + +When the wires between the components are mess it's time to use Virtual wire.`; + +exports.html = `
+
@(Wire name)
+
+`; + +exports.install = function(instance) { + + instance.custom.reconfigure = function(options){ + if (instance.options.wirename) { + instance.status(instance.options.wirename); + } else + instance.status('Not configured', 'red'); + }; + + ON('virtualwire', function(wirename, flowdata){ + if (instance.options.wirename && instance.options.wirename === wirename) + instance.send(flowdata); + }); + + instance.on('options', instance.custom.reconfigure); + instance.custom.reconfigure(); +}; diff --git a/RVO43/flow/virtualwireout.js b/RVO43/flow/virtualwireout.js new file mode 100755 index 0000000..94a1e4f --- /dev/null +++ b/RVO43/flow/virtualwireout.js @@ -0,0 +1,41 @@ +exports.id = 'virtualwireout'; +exports.title = 'Virtual wire out'; +exports.version = '1.0.0'; +exports.author = 'Martin Smola'; +exports.color = '#303E4D'; +exports.icon = 'sign-out'; +exports.input = true; +exports.options = {}; +exports.readme = `# Virtual wire out + +When the wires between the components are mess it's time to use Virtual wire.`; + +exports.html = `
+
@(Wire name)
+
+`; + +exports.install = function(instance) { + + instance.custom.reconfigure = function(){ + if (instance.options.wirename) { + instance.status(instance.options.wirename); + } else + instance.status('Not configured', 'red'); + }; + + instance.on('data', function(flowdata) { + EMIT('virtualwire', instance.options.wirename, flowdata); + }); + + instance.on('options', instance.custom.reconfigure); + instance.custom.reconfigure(); +}; diff --git a/RVO43/flow/wsmqttpublish.js b/RVO43/flow/wsmqttpublish.js new file mode 100755 index 0000000..0eba804 --- /dev/null +++ b/RVO43/flow/wsmqttpublish.js @@ -0,0 +1,448 @@ +exports.id = 'wsmqttpublish'; +exports.title = 'WS MQTT publish'; +exports.group = 'MQTT'; +exports.color = '#888600'; +exports.version = '1.0.2'; +exports.icon = 'sign-out'; +exports.input = 2; +exports.output = 3; +exports.options = { host: 'tb-stage.worksys.io', port: 1883, clientid: "", username: "" }; + +exports.html = `
+
+
+
Hostname or IP address (if not empty - setting will override db setting)
+
+
+
Port
+
+
+
+
+
@(Client id)
+
+
+
@(Username)
+
+
+
`; + + +exports.readme = ` +# WS MQTT Publish + +Version 1.0.3. + +Added: +- database collections, +- 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 = { + debug: 0, + rpcCall: 1, + services: 2 +} + +//CONFIG +let createTelemetryBackup = true; +let saveTelemetryOnError = true;//backup_on_failure overrides this value +//------------------------ + +let rollers; +if (createTelemetryBackup) rollers = require('streamroller'); + +const noSqlFileSizeLimit = 4194304;//use 5MB - 4194304 +let insertNoSqlCounter = 0; +let insertBackupNoSqlCounter = 0; +let processingData = false; + +let backup_on_failure = false;//== saveTelemetryOnError - create backup client 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; + +process.on('uncaughtException', function(err) { + + errLogger.error('uncaughtException:', err.message) + errLogger.error(err.stack); + + //TODO + //send to service + + //process.exit(1); +}) + +const nosql = NOSQL('tbdata'); +const nosqlBackup = NOSQL('/backup/tbdata'); + + +exports.install = function(instance) { + + var client; + var opts; + var clientReady = false; + + // wsmqtt status for notification purposes on projects.worksys.io database + let wsmqttName = null; + let sendWsStatusVar = null; + let wsmqtt_status = 'disconnected'; + + 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'; + } + + function sendWsStatus() { + instance.send(SEND_TO.services, { [wsmqttName]: wsmqtt_status }); + } + + + function main() { + if (!FLOW.dbLoaded) return; + + loadSettings(); + clearInterval(sendWsStatus); + sendWsStatusVar = setInterval(sendWsStatus, 180000); + } + + //set opts according to db settings + function loadSettings() { + + if (instance.options.host !== "") { + //override settings from database + var o = instance.options; + opts = { + host: o.host, + port: o.port, + clientId: o.clientid, + username: o.username, + rejectUnauthorized: false, + resubscribe: false + }; + + wsmqttName = getWsmqttName(o.host); + + console.log("wsmqttpublich -> loadSettings from instance.options", instance.options); + } + else { + + const SETTINGS = FLOW.GLOBALS.settings; + backup_on_failure = SETTINGS.backup_on_failure; + saveTelemetryOnError = backup_on_failure; + + restore_from_backup = SETTINGS.restore_from_backup; + restore_backup_wait = SETTINGS.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; + + opts = { + host: mqtt_host, + port: mqtt_port, + keepalive: 10, + clientId: mqtt_clientid, + username: mqtt_username, + rejectUnauthorized: false, + resubscribe: false + }; + + wsmqttName = getWsmqttName(mqtt_host); + } + + connectToTbServer(); + } + + function connectToTbServer() { + 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"); + //monitor.info("MQTT client connected"); + + sendClientError = true; + clientReady = true; + wsmqtt_status = 'connected'; + }); + + client.on('reconnect', function() { + instance.status("Reconnecting", "yellow"); + clientReady = false; + }); + + client.on('message', function(topic, message) { + // message is type of buffer + message = message.toString(); + if (message[0] === '{') { + TRY(function() { + + message = JSON.parse(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 } }); + } + + }, () => instance.debug('MQTT: Error parsing data', message)); + } + + instance.send(SEND_TO.rpcCall, { "topic": topic, "content": message }); + }); + + client.on('close', function() { + clientReady = false; + wsmqtt_status = 'disconnected'; + + instance.status("Disconnected", "red"); + instance.send(SEND_TO.debug, { "message": "Client CLOSE signal received !" }); + }); + + client.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; + wsmqtt_status = 'disconnected'; + }); + + } + + + instance.on("0", _ => { + main(); + }) + + + instance.on('1', function(data) { + + if (clientReady) { + //do we have some data in backup file? if any, process data from database + if (saveTelemetryOnError) { + //read telemetry data and send back to server + if (!processingData) processDataFromDatabase(); + } + + let stringifiedJson = JSON.stringify(data.data); + client.publish("v1/gateway/telemetry", stringifiedJson, { qos: 1 }); + + //backup telemetry + if (createTelemetryBackup) { + data.data.id = UID(); + nosqlBackup.insert(data.data); + + insertBackupNoSqlCounter++; + if (insertBackupNoSqlCounter > 150) { + let options = { compress: true }; + let path = __dirname + "/../databases/backup/tbdata.nosql"; + var stream = new rollers.RollingFileStream(path, noSqlFileSizeLimit, 150, options); + stream.write(""); + stream.end(); + + insertBackupNoSqlCounter = 0; + } + } + + } + 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 (saveTelemetryOnError) { + //create new file from tbdata.nosql, if file size exceeds given limit, and clear tbdata.nosql + makeBackupFromDbFile(); + + //write to tb + data.data.id = UID(); + nosql.insert(data.data); + } + } + }); + + + instance.close = function(done) { + if (clientReady) { + client.end(); + clearInterval(sendWsStatusVar); + } + }; + + + function getDbBackupFileCounter(type) { + var files = fs.readdirSync(__dirname + "/../databases"); + + let counter = 0; + for (var i = 0; i < files.length; i++) { + + if (files[i] == "tbdata.nosql") continue; + + if (files[i].endsWith(".nosql")) { + + let pos = files[i].indexOf("."); + if (pos > -1) { + + let fileCounter = counter; + let firstDigit = files[i].slice(0, pos); + + fileCounter = parseInt(firstDigit); + if (isNaN(fileCounter)) fileCounter = 0; + //console.log("getDbBackupFileCounter digit:", files[i], firstDigit, fileCounter, isNaN(fileCounter), type); + + if (type == "max") { + if (fileCounter > counter) { + counter = fileCounter; + } + } + else if (type == "min") { + if (counter == 0) counter = fileCounter; + + if (fileCounter < counter) { + counter = fileCounter; + } + } + } + } + + } + + if (type == "max") counter++; + + return counter; + } + + const makeBackupFromDbFile = async () => { + + if (!saveTelemetryOnError) return; + + //to avoid large file: tbdata.nosql + + //init value is 0! + if (insertNoSqlCounter > 0) { + --insertNoSqlCounter; + return; + } + + insertNoSqlCounter = 100; + + let source = __dirname + "/../databases/tbdata.nosql"; + + var stats = fs.statSync(source); + var fileSizeInBytes = stats.size; + + if (fileSizeInBytes > noSqlFileSizeLimit) { + + let counter = 1; + counter = getDbBackupFileCounter("max"); + + let destination = __dirname + "/../databases/" + counter + "." + "tbdata.nosql"; + + //make backup file + fs.copyFileSync(source, destination); + //fs.renameSync(p, p + "." + counter); + + //clear tbdata.nosql + fs.writeFileSync(source, ""); + fs.truncateSync(source, 0); + + } + } + + const processDataFromDatabase = async () => { + + if (restore_from_backup <= 0) return; + + //calculate diff + const now = new Date(); + let currentTime = now.getTime(); + let diff = currentTime - lastRestoreTime; + + if ((diff / 1000) < restore_backup_wait) { + //console.log("*********restore_backup_wait", diff, restore_backup_wait); + return; + } + + processingData = true; + + //get filename to process + let counter = getDbBackupFileCounter("min"); + + //we have some backup files + let dataBase = 'tbdata'; + + var nosql; + if (counter == 0) dataBase = 'tbdata'; + else dataBase = counter + "." + 'tbdata'; + + nosql = NOSQL(dataBase); + + //select all data - use limit restore_from_backup + let records = await promisifyBuilder(nosql.find().take(restore_from_backup)); + + for (let i = 0; i < records.length; i++) { + if (clientReady) { + + let item = records[i]; + let id = item.id; + + if (id !== undefined) { + //console.log("------------processDataFromDatabase - remove", id, dataBase, i); + + try { + + let message = JSON.parse(JSON.stringify(item)); + delete message.id; + + client.publish("v1/gateway/telemetry", JSON.stringify(message), { qos: 1 }); + + //remove from database + await promisifyBuilder(nosql.remove().where("id", id)); + + } catch (error) { + //process error + console.log("processDataFromDatabase", error); + } + + } + + } + else { + processingData = false; + return; + } + } + + if (records.length > 0) { + //clean backup file + if (counter > 0) nosql.clean(); + } + + //no data in db, remove + if (records.length == 0) { + if (counter > 0) nosql.drop(); + } + + const d = new Date(); + lastRestoreTime = d.getTime(); + + processingData = false; + + } + + instance.on('options', main); + //instance.reconfigure(); +}; diff --git a/RVO43/monitor.txt b/RVO43/monitor.txt new file mode 100755 index 0000000..8e9731f --- /dev/null +++ b/RVO43/monitor.txt @@ -0,0 +1,269 @@ +[2025-10-09T16:55:21.101] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-09T16:55:26.452] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-09T16:55:26.457] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-09T16:55:26.458] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-09T16:55:26.459] [INFO] monitorLogs - profile: { + 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: 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 +} +[2025-10-09T16:55:26.463] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T16:55:26.464] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-10-10T05:32:00.463Z +[2025-10-09T16:55:26.466] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-10-09T16:45:00.465Z +[2025-10-09T16:55:26.466] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T16:55:26.467] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-10-09T16:55:26.468] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-09T16:55:26.469] [INFO] monitorLogs - 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 +} +[2025-10-09T16:55:26.470] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T16:55:26.471] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-10-10T11:00:00.471Z +[2025-10-09T16:55:26.472] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-09T16:55:26.473] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-10-09T16:55:26.474] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-09T16:55:26.474] [INFO] monitorLogs - profile: { + 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: 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 +} +[2025-10-09T16:55:26.477] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T16:55:26.477] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-10-10T05:32:00.477Z +[2025-10-09T16:55:26.478] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-10-09T16:45:00.478Z +[2025-10-09T16:55:26.479] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T16:55:26.480] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-10-09T16:55:26.504] [INFO] monitorLogs - tasks created: 1273 +[2025-10-09T16:55:26.507] [INFO] monitorLogs - -->FLOW bol spustený gRoJEyXVx4qD9er287L4847wBzGldaPjLWQKm3Mv 2025-08-08 +[2025-10-09T16:55:31.516] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-09T18:31:01.608] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-09T18:31:01.614] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-09T19:07:53.426] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-09T19:07:58.778] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-09T19:07:58.783] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-09T19:07:58.785] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-09T19:07:58.785] [INFO] monitorLogs - profile: { + 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: 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 +} +[2025-10-09T19:07:58.789] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T19:07:58.791] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-10-10T05:32:00.790Z +[2025-10-09T19:07:58.792] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-10-10T16:45:00.792Z +[2025-10-09T19:07:58.793] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T19:07:58.794] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-10-09T19:07:58.795] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-09T19:07:58.795] [INFO] monitorLogs - 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 +} +[2025-10-09T19:07:58.797] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T19:07:58.798] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-10-10T11:00:00.797Z +[2025-10-09T19:07:58.799] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-09T19:07:58.800] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-10-09T19:07:58.800] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-09T19:07:58.801] [INFO] monitorLogs - profile: { + 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: 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 +} +[2025-10-09T19:07:58.803] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T19:07:58.804] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-10-10T05:32:00.804Z +[2025-10-09T19:07:58.805] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-10-10T16:45:00.805Z +[2025-10-09T19:07:58.805] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T19:07:58.806] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-10-09T19:07:58.830] [INFO] monitorLogs - tasks created: 1273 +[2025-10-09T19:07:58.833] [INFO] monitorLogs - -->FLOW bol spustený gRoJEyXVx4qD9er287L4847wBzGldaPjLWQKm3Mv 2025-08-08 +[2025-10-09T19:08:03.843] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-10T03:08:00.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-10 03:08:00 +[2025-10-10T06:48:07.631] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-10T06:48:07.637] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-10T18:28:00.019] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-10T18:28:00.024] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-11T03:08:01.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-11 03:08:01 +[2025-10-11T06:50:31.415] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-11T06:50:31.421] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-11T18:30:23.551] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-11T18:30:23.556] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-12T03:08:03.015] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-12 03:08:03 +[2025-10-12T06:47:55.259] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-12T06:47:55.265] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-12T18:30:17.096] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-12T18:30:17.102] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-13T03:08:04.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-13 03:08:04 +[2025-10-13T06:42:46.295] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-13T06:42:46.302] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-13T18:32:39.998] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-13T18:32:40.004] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-14T03:08:05.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-14 03:08:05 +[2025-10-14T06:45:09.120] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-14T06:45:09.123] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-14T18:24:59.941] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-14T18:24:59.947] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-15T03:08:06.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-15 03:08:06 +[2025-10-15T06:52:31.455] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-15T06:52:31.461] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-15T15:30:08.126] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-15T15:30:13.495] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-15T15:30:13.500] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-15T15:30:13.501] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-15T15:30:13.501] [INFO] monitorLogs - profile: { + 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: 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 +} +[2025-10-15T15:30:13.506] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-15T15:30:13.507] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-10-16T05:41:00.506Z +[2025-10-15T15:30:13.508] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-10-15T16:33:00.508Z +[2025-10-15T15:30:13.509] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:41', name: 'luxOff' }, + { value: 1, start_time: '18:33', name: 'luxOn' } +] +[2025-10-15T15:30:13.510] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-10-15T15:30:13.511] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-15T15:30:13.512] [INFO] monitorLogs - 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 +} +[2025-10-15T15:30:13.513] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-15T15:30:13.514] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-10-16T11:00:00.514Z +[2025-10-15T15:30:13.515] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-15T15:30:13.516] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-10-15T15:30:13.517] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-15T15:30:13.517] [INFO] monitorLogs - profile: { + 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: 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 +} +[2025-10-15T15:30:13.519] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-15T15:30:13.520] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-10-16T05:41:00.520Z +[2025-10-15T15:30:13.521] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-10-15T16:33:00.521Z +[2025-10-15T15:30:13.522] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:41', name: 'luxOff' }, + { value: 1, start_time: '18:33', name: 'luxOn' } +] +[2025-10-15T15:30:13.523] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-10-15T15:30:13.546] [INFO] monitorLogs - tasks created: 1273 +[2025-10-15T15:30:13.548] [INFO] monitorLogs - -->FLOW bol spustený gRoJEyXVx4qD9er287L4847wBzGldaPjLWQKm3Mv 2025-10-08 +[2025-10-15T15:30:18.557] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-15T18:23:34.496] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-15T18:23:34.502] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor diff --git a/RVO43/package-lock.json b/RVO43/package-lock.json new file mode 100755 index 0000000..3c5c1ba --- /dev/null +++ b/RVO43/package-lock.json @@ -0,0 +1,2139 @@ +{ + "name": "emptyproject", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "emptyproject", + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "bitwise": "^2.1.0", + "easy-crc": "0.0.2", + "jsmodbus": "^4.0.6", + "log4js": "^6.3.0", + "moment": "^2.30.1", + "mqtt": "^4.2.6", + "nodemailer": "^6.9.7", + "serialport": "^9.2.8", + "total.js": "^3.4.13" + } + }, + "node_modules/@serialport/binding-abstract": { + "version": "9.2.3", + "resolved": "https://registry.npmjs.org/@serialport/binding-abstract/-/binding-abstract-9.2.3.tgz", + "integrity": "sha512-cQs9tbIlG3P0IrOWyVirqlhWuJ7Ms2Zh9m2108z6Y5UW/iVj6wEOiW8EmK9QX9jmJXYllE7wgGgvVozP5oCj3w==", + "dependencies": { + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/binding-mock": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/binding-mock/-/binding-mock-9.2.4.tgz", + "integrity": "sha512-dpEhACCs44oQhh6ajJfJdvQdK38Vq0N4W6iD/gdplglDCK7qXRQCMUjJIeKdS/HSEiWkC3bwumUhUufdsOyT4g==", + "dependencies": { + "@serialport/binding-abstract": "9.2.3", + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/bindings": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/@serialport/bindings/-/bindings-9.2.8.tgz", + "integrity": "sha512-hSLxTe0tADZ3LMMGwvEJWOC/TaFQTyPeFalUCsJ1lSQ0k6bPF04JwrtB/C81GetmDBTNRY0GlD0SNtKCc7Dr5g==", + "hasInstallScript": true, + "dependencies": { + "@serialport/binding-abstract": "9.2.3", + "@serialport/parser-readline": "9.2.4", + "bindings": "^1.5.0", + "debug": "^4.3.2", + "nan": "^2.15.0", + "prebuild-install": "^7.0.0" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-byte-length": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-byte-length/-/parser-byte-length-9.2.4.tgz", + "integrity": "sha512-sQD/iw4ZMU3xW9PLi0/GlvU6Y623jGeWecbMkO7izUo/6P7gtfv1c9ikd5h0kwL8AoAOpQA1lxdHIKox+umBUg==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-cctalk": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-cctalk/-/parser-cctalk-9.2.4.tgz", + "integrity": "sha512-T4TU5vQMwmo9AB3gQLFDWbfJXlW5jd9guEsB/nqKjFHTv0FXPdZ7DQ2TpSp8RnHWxU3GX6kYTaDO20BKzc8GPQ==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-delimiter": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-delimiter/-/parser-delimiter-9.2.4.tgz", + "integrity": "sha512-4nvTAoYAgkxFiXrkI+3CA49Yd43CODjeszh89EK+I9c8wOZ+etZduRCzINYPiy26g7zO+GRAb9FoPCsY+sYcbQ==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-inter-byte-timeout": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-inter-byte-timeout/-/parser-inter-byte-timeout-9.2.4.tgz", + "integrity": "sha512-SOAdvr0oBQIOCXX198hiTlxs4JTKg9j5piapw5tNq52fwDOWdbYrFneT/wN04UTMKaDrJuEvXq6T4rv4j7nJ5A==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-readline": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-readline/-/parser-readline-9.2.4.tgz", + "integrity": "sha512-Z1/qrZTQUVhNSJP1hd9YfDvq0o7d87rNwAjjRKbVpa7Qi51tG5BnKt43IV3NFMyBlVcRe0rnIb3tJu57E0SOwg==", + "dependencies": { + "@serialport/parser-delimiter": "9.2.4" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-ready": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-ready/-/parser-ready-9.2.4.tgz", + "integrity": "sha512-Pyi94Itjl6qAURwIZr/gmZpMAyTmKXThm6vL5DoAWGQjcRHWB0gwv2TY2v7N+mQLJYUKU3cMnvnATXxHm7xjxw==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-regex": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-regex/-/parser-regex-9.2.4.tgz", + "integrity": "sha512-sI/cVvPOYz+Dbv4ZdnW16qAwvXiFf/1pGASQdbveRTlgJDdz7sRNlCBifzfTN2xljwvCTZYqiudKvDdC1TepRQ==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/stream": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/stream/-/stream-9.2.4.tgz", + "integrity": "sha512-bLye8Ub4vUFQGmkh8qEqehr7SE7EJs2yDs0h9jzuL5oKi+F34CFmWkEErO8GAOQ8YNn7p6b3GxUgs+0BrHHDZQ==", + "dependencies": { + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "node_modules/are-we-there-yet": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", + "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/base64-js": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", + "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==" + }, + "node_modules/bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "dependencies": { + "file-uri-to-path": "1.0.0" + } + }, + "node_modules/bitwise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/bitwise/-/bitwise-2.1.0.tgz", + "integrity": "sha512-XKgAhMXCh4H/3oNwAHAsAO0iC89s9cOiumgYwSHjSobGWxYjv62YhkL9QEdvGP151xypCtMlAfKK79GEcd2eRQ==" + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/bl/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/buffer": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz", + "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==", + "dependencies": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + }, + "node_modules/buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" + }, + "node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, + "node_modules/code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/commist": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/commist/-/commist-1.1.0.tgz", + "integrity": "sha512-rraC8NXWOEjhADbZe9QBNzLAN5Q3fsTPQtBV+fEVj6xKIgDgNiEVE6ZNfHpZOqfQ21YUzfVNUXLOEZquYvQPPg==", + "dependencies": { + "leven": "^2.1.0", + "minimist": "^1.1.0" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "node_modules/concat-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", + "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", + "engines": [ + "node >= 6.0" + ], + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.0.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/concat-stream/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" + }, + "node_modules/core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "node_modules/crc": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/crc/-/crc-3.4.0.tgz", + "integrity": "sha512-ycVC2+4/DLgXXq7QweYi2znhqDuZz6P5TQXnkQo8v15XY/5p/IWeZwsSE31Ifo8w15b8TWLsqhXOjXyilHuQxw==" + }, + "node_modules/date-format": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.11.tgz", + "integrity": "sha512-VS20KRyorrbMCQmpdl2hg5KaOUsda1RbnsJg461FfrcyCUg+pkd0b40BSW4niQyTheww4DBXQnS7HwSrKkipLw==", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" + }, + "node_modules/detect-libc": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz", + "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==", + "engines": { + "node": ">=8" + } + }, + "node_modules/duplexify": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.2.tgz", + "integrity": "sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw==", + "dependencies": { + "end-of-stream": "^1.4.1", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1", + "stream-shift": "^1.0.0" + } + }, + "node_modules/duplexify/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/easy-crc": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/easy-crc/-/easy-crc-0.0.2.tgz", + "integrity": "sha512-h6eqIdhJRe0p271/xZJbM/0klCi13mW5IB7ZEzEGH11yV4QXWAkD4yPErz0fXdhFrd6sZ4Q1k5Iky2kMsMNePw==" + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" + }, + "node_modules/flatted": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", + "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==" + }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, + "node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "node_modules/gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha512-14x4kjc6lkD3ltw589k0NrPD6cCNTD6CWoVUNpB85+DrtONoZn+Rug6xZU5RvSC4+TZPxA5AnBibQYAvZn41Hg==", + "dependencies": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "node_modules/github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==" + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" + }, + "node_modules/has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" + }, + "node_modules/help-me": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/help-me/-/help-me-3.0.0.tgz", + "integrity": "sha512-hx73jClhyk910sidBB7ERlnhMlFsJJIBqSVMFDwPN8o2v9nmp5KgLq1Xz1Bf1fCMMZ6mPrX159iG0VLy/fPMtQ==", + "dependencies": { + "glob": "^7.1.6", + "readable-stream": "^3.6.0" + } + }, + "node_modules/help-me/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, + "node_modules/is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==", + "dependencies": { + "number-is-nan": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "node_modules/js-sdsl": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz", + "integrity": "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/js-sdsl" + } + }, + "node_modules/jsmodbus": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/jsmodbus/-/jsmodbus-4.0.6.tgz", + "integrity": "sha512-gCmjoaERErK5Rn9Lu/BN07fY13MoWV7JKgGzrnkPlQPdPxYcwDhLtYcmpFFpZ4J9NPZZBSezi1UkLZO/DnNppA==", + "dependencies": { + "crc": "3.4.0", + "debug": "^3.1.0" + }, + "bin": { + "jsmodbus": "bin/jsmodbus.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/jsmodbus/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/leven": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", + "integrity": "sha1-wuep93IJTe6dNCAq6KzORoeHVYA=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/log4js": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.5.2.tgz", + "integrity": "sha512-DXtpNtt+KDOMT7RHUDIur/WsSA3rntlUh9Zg4XCdV42wUuMmbFkl38+LZ92Z5QvQA7mD5kAVkLiBSEH/tvUB8A==", + "dependencies": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "flatted": "^3.2.5", + "rfdc": "^1.3.0", + "streamroller": "^3.1.1" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" + }, + "node_modules/moment": { + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", + "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==", + "engines": { + "node": "*" + } + }, + "node_modules/mqtt": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/mqtt/-/mqtt-4.3.7.tgz", + "integrity": "sha512-ew3qwG/TJRorTz47eW46vZ5oBw5MEYbQZVaEji44j5lAUSQSqIEoul7Kua/BatBW0H0kKQcC9kwUHa1qzaWHSw==", + "dependencies": { + "commist": "^1.0.0", + "concat-stream": "^2.0.0", + "debug": "^4.1.1", + "duplexify": "^4.1.1", + "help-me": "^3.0.0", + "inherits": "^2.0.3", + "lru-cache": "^6.0.0", + "minimist": "^1.2.5", + "mqtt-packet": "^6.8.0", + "number-allocator": "^1.0.9", + "pump": "^3.0.0", + "readable-stream": "^3.6.0", + "reinterval": "^1.1.0", + "rfdc": "^1.3.0", + "split2": "^3.1.0", + "ws": "^7.5.5", + "xtend": "^4.0.2" + }, + "bin": { + "mqtt": "bin/mqtt.js", + "mqtt_pub": "bin/pub.js", + "mqtt_sub": "bin/sub.js" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/mqtt-packet": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/mqtt-packet/-/mqtt-packet-6.10.0.tgz", + "integrity": "sha512-ja8+mFKIHdB1Tpl6vac+sktqy3gA8t9Mduom1BA75cI+R9AHnZOiaBQwpGiWnaVJLDGRdNhQmFaAqd7tkKSMGA==", + "dependencies": { + "bl": "^4.0.2", + "debug": "^4.1.1", + "process-nextick-args": "^2.0.1" + } + }, + "node_modules/mqtt/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/nan": { + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.16.0.tgz", + "integrity": "sha512-UdAqHyFngu7TfQKsCBgAA6pWDkT8MAO7d0jyOecVhN5354xbLqdn8mV9Tat9gepAupm0bt2DbeaSC8vS52MuFA==" + }, + "node_modules/napi-build-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", + "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==" + }, + "node_modules/node-abi": { + "version": "3.22.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.22.0.tgz", + "integrity": "sha512-u4uAs/4Zzmp/jjsD9cyFYDXeISfUWaAVWshPmDZOFOv4Xl4SbzTXm53I04C2uRueYJ+0t5PEtLH/owbn2Npf/w==", + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/nodemailer": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.7.tgz", + "integrity": "sha512-rUtR77ksqex/eZRLmQ21LKVH5nAAsVicAtAYudK7JgwenEDZ0UIQ1adUGqErz7sMkWYxWTTU1aeP2Jga6WQyJw==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "dependencies": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "node_modules/number-allocator": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/number-allocator/-/number-allocator-1.0.14.tgz", + "integrity": "sha512-OrL44UTVAvkKdOdRQZIJpLkAdjXGTRda052sN4sO77bKEzYYqWKMBjQvrJFzqygI99gL6Z4u2xctPW1tB8ErvA==", + "dependencies": { + "debug": "^4.3.1", + "js-sdsl": "4.3.0" + } + }, + "node_modules/number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/prebuild-install": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.0.tgz", + "integrity": "sha512-CNcMgI1xBypOyGqjp3wOc8AAo1nMhZS3Cwd3iHIxOdAUbb+YxdNuM4Z5iIrZ8RLvOsf3F3bl7b7xGq6DjQoNYA==", + "dependencies": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^1.0.1", + "node-abi": "^3.3.0", + "npmlog": "^4.0.1", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + }, + "bin": { + "prebuild-install": "bin.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/reinterval": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reinterval/-/reinterval-1.1.0.tgz", + "integrity": "sha1-M2Hs+jymwYKDOA3Qu5VG85D17Oc=" + }, + "node_modules/rfdc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==" + }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/serialport": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/serialport/-/serialport-9.2.8.tgz", + "integrity": "sha512-FsWpMQgSJxi93JgWl5xM1f9/Z8IjRJuaUEoHqLf8FPBLw7gMhInuHOBhI2onQufWIYPGTz3H3oGcu1nCaK1EfA==", + "dependencies": { + "@serialport/binding-mock": "9.2.4", + "@serialport/bindings": "9.2.8", + "@serialport/parser-byte-length": "9.2.4", + "@serialport/parser-cctalk": "9.2.4", + "@serialport/parser-delimiter": "9.2.4", + "@serialport/parser-inter-byte-timeout": "9.2.4", + "@serialport/parser-readline": "9.2.4", + "@serialport/parser-ready": "9.2.4", + "@serialport/parser-regex": "9.2.4", + "@serialport/stream": "9.2.4", + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "node_modules/split2": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", + "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", + "dependencies": { + "readable-stream": "^3.0.0" + } + }, + "node_modules/split2/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==" + }, + "node_modules/streamroller": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.1.1.tgz", + "integrity": "sha512-iPhtd9unZ6zKdWgMeYGfSBuqCngyJy1B/GPi/lTpwGpa3bajuX30GjUVd0/Tn/Xhg0mr4DOSENozz9Y06qyonQ==", + "dependencies": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "fs-extra": "^10.1.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dependencies": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/tar-fs": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "dependencies": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tar-stream/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/total.js": { + "version": "3.4.13", + "resolved": "https://registry.npmjs.org/total.js/-/total.js-3.4.13.tgz", + "integrity": "sha512-lAH4gEixlPFbrE3xfKADAcHfO79IFq2wKa9GTsrgRzIR5MTg3mNH7+4IxvX1pK8faoYb/0oYSJ1YTsAa5hIFFQ==", + "bin": { + "total": "bin/totaljs", + "total.js": "bin/totaljs", + "totaljs": "bin/totaljs", + "totalpackage": "bin/tpm", + "tpm": "bin/tpm" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, + "node_modules/universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "node_modules/wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "node_modules/ws": { + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } + }, + "dependencies": { + "@serialport/binding-abstract": { + "version": "9.2.3", + "resolved": "https://registry.npmjs.org/@serialport/binding-abstract/-/binding-abstract-9.2.3.tgz", + "integrity": "sha512-cQs9tbIlG3P0IrOWyVirqlhWuJ7Ms2Zh9m2108z6Y5UW/iVj6wEOiW8EmK9QX9jmJXYllE7wgGgvVozP5oCj3w==", + "requires": { + "debug": "^4.3.2" + } + }, + "@serialport/binding-mock": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/binding-mock/-/binding-mock-9.2.4.tgz", + "integrity": "sha512-dpEhACCs44oQhh6ajJfJdvQdK38Vq0N4W6iD/gdplglDCK7qXRQCMUjJIeKdS/HSEiWkC3bwumUhUufdsOyT4g==", + "requires": { + "@serialport/binding-abstract": "9.2.3", + "debug": "^4.3.2" + } + }, + "@serialport/bindings": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/@serialport/bindings/-/bindings-9.2.8.tgz", + "integrity": "sha512-hSLxTe0tADZ3LMMGwvEJWOC/TaFQTyPeFalUCsJ1lSQ0k6bPF04JwrtB/C81GetmDBTNRY0GlD0SNtKCc7Dr5g==", + "requires": { + "@serialport/binding-abstract": "9.2.3", + "@serialport/parser-readline": "9.2.4", + "bindings": "^1.5.0", + "debug": "^4.3.2", + "nan": "^2.15.0", + "prebuild-install": "^7.0.0" + } + }, + "@serialport/parser-byte-length": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-byte-length/-/parser-byte-length-9.2.4.tgz", + "integrity": "sha512-sQD/iw4ZMU3xW9PLi0/GlvU6Y623jGeWecbMkO7izUo/6P7gtfv1c9ikd5h0kwL8AoAOpQA1lxdHIKox+umBUg==" + }, + "@serialport/parser-cctalk": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-cctalk/-/parser-cctalk-9.2.4.tgz", + "integrity": "sha512-T4TU5vQMwmo9AB3gQLFDWbfJXlW5jd9guEsB/nqKjFHTv0FXPdZ7DQ2TpSp8RnHWxU3GX6kYTaDO20BKzc8GPQ==" + }, + "@serialport/parser-delimiter": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-delimiter/-/parser-delimiter-9.2.4.tgz", + "integrity": "sha512-4nvTAoYAgkxFiXrkI+3CA49Yd43CODjeszh89EK+I9c8wOZ+etZduRCzINYPiy26g7zO+GRAb9FoPCsY+sYcbQ==" + }, + "@serialport/parser-inter-byte-timeout": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-inter-byte-timeout/-/parser-inter-byte-timeout-9.2.4.tgz", + "integrity": "sha512-SOAdvr0oBQIOCXX198hiTlxs4JTKg9j5piapw5tNq52fwDOWdbYrFneT/wN04UTMKaDrJuEvXq6T4rv4j7nJ5A==" + }, + "@serialport/parser-readline": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-readline/-/parser-readline-9.2.4.tgz", + "integrity": "sha512-Z1/qrZTQUVhNSJP1hd9YfDvq0o7d87rNwAjjRKbVpa7Qi51tG5BnKt43IV3NFMyBlVcRe0rnIb3tJu57E0SOwg==", + "requires": { + "@serialport/parser-delimiter": "9.2.4" + } + }, + "@serialport/parser-ready": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-ready/-/parser-ready-9.2.4.tgz", + "integrity": "sha512-Pyi94Itjl6qAURwIZr/gmZpMAyTmKXThm6vL5DoAWGQjcRHWB0gwv2TY2v7N+mQLJYUKU3cMnvnATXxHm7xjxw==" + }, + "@serialport/parser-regex": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-regex/-/parser-regex-9.2.4.tgz", + "integrity": "sha512-sI/cVvPOYz+Dbv4ZdnW16qAwvXiFf/1pGASQdbveRTlgJDdz7sRNlCBifzfTN2xljwvCTZYqiudKvDdC1TepRQ==" + }, + "@serialport/stream": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/stream/-/stream-9.2.4.tgz", + "integrity": "sha512-bLye8Ub4vUFQGmkh8qEqehr7SE7EJs2yDs0h9jzuL5oKi+F34CFmWkEErO8GAOQ8YNn7p6b3GxUgs+0BrHHDZQ==", + "requires": { + "debug": "^4.3.2" + } + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==" + }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "are-we-there-yet": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", + "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "base64-js": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", + "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==" + }, + "bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "requires": { + "file-uri-to-path": "1.0.0" + } + }, + "bitwise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/bitwise/-/bitwise-2.1.0.tgz", + "integrity": "sha512-XKgAhMXCh4H/3oNwAHAsAO0iC89s9cOiumgYwSHjSobGWxYjv62YhkL9QEdvGP151xypCtMlAfKK79GEcd2eRQ==" + }, + "bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "requires": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "buffer": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz", + "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==", + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" + }, + "chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==" + }, + "commist": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/commist/-/commist-1.1.0.tgz", + "integrity": "sha512-rraC8NXWOEjhADbZe9QBNzLAN5Q3fsTPQtBV+fEVj6xKIgDgNiEVE6ZNfHpZOqfQ21YUzfVNUXLOEZquYvQPPg==", + "requires": { + "leven": "^2.1.0", + "minimist": "^1.1.0" + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "concat-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", + "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.0.2", + "typedarray": "^0.0.6" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "crc": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/crc/-/crc-3.4.0.tgz", + "integrity": "sha512-ycVC2+4/DLgXXq7QweYi2znhqDuZz6P5TQXnkQo8v15XY/5p/IWeZwsSE31Ifo8w15b8TWLsqhXOjXyilHuQxw==" + }, + "date-format": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.11.tgz", + "integrity": "sha512-VS20KRyorrbMCQmpdl2hg5KaOUsda1RbnsJg461FfrcyCUg+pkd0b40BSW4niQyTheww4DBXQnS7HwSrKkipLw==" + }, + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "requires": { + "ms": "2.1.2" + } + }, + "decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "requires": { + "mimic-response": "^3.1.0" + } + }, + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==" + }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" + }, + "detect-libc": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz", + "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==" + }, + "duplexify": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.2.tgz", + "integrity": "sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw==", + "requires": { + "end-of-stream": "^1.4.1", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1", + "stream-shift": "^1.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "easy-crc": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/easy-crc/-/easy-crc-0.0.2.tgz", + "integrity": "sha512-h6eqIdhJRe0p271/xZJbM/0klCi13mW5IB7ZEzEGH11yV4QXWAkD4yPErz0fXdhFrd6sZ4Q1k5Iky2kMsMNePw==" + }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "requires": { + "once": "^1.4.0" + } + }, + "expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==" + }, + "file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" + }, + "flatted": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", + "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==" + }, + "fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, + "fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha512-14x4kjc6lkD3ltw589k0NrPD6cCNTD6CWoVUNpB85+DrtONoZn+Rug6xZU5RvSC4+TZPxA5AnBibQYAvZn41Hg==", + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==" + }, + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" + }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" + }, + "help-me": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/help-me/-/help-me-3.0.0.tgz", + "integrity": "sha512-hx73jClhyk910sidBB7ERlnhMlFsJJIBqSVMFDwPN8o2v9nmp5KgLq1Xz1Bf1fCMMZ6mPrX159iG0VLy/fPMtQ==", + "requires": { + "glob": "^7.1.6", + "readable-stream": "^3.6.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==", + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "js-sdsl": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz", + "integrity": "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==" + }, + "jsmodbus": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/jsmodbus/-/jsmodbus-4.0.6.tgz", + "integrity": "sha512-gCmjoaERErK5Rn9Lu/BN07fY13MoWV7JKgGzrnkPlQPdPxYcwDhLtYcmpFFpZ4J9NPZZBSezi1UkLZO/DnNppA==", + "requires": { + "crc": "3.4.0", + "debug": "^3.1.0" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "requires": { + "ms": "^2.1.1" + } + } + } + }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, + "leven": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", + "integrity": "sha1-wuep93IJTe6dNCAq6KzORoeHVYA=" + }, + "log4js": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.5.2.tgz", + "integrity": "sha512-DXtpNtt+KDOMT7RHUDIur/WsSA3rntlUh9Zg4XCdV42wUuMmbFkl38+LZ92Z5QvQA7mD5kAVkLiBSEH/tvUB8A==", + "requires": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "flatted": "^3.2.5", + "rfdc": "^1.3.0", + "streamroller": "^3.1.1" + } + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "requires": { + "yallist": "^4.0.0" + } + }, + "mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==" + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==" + }, + "mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" + }, + "moment": { + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", + "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==" + }, + "mqtt": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/mqtt/-/mqtt-4.3.7.tgz", + "integrity": "sha512-ew3qwG/TJRorTz47eW46vZ5oBw5MEYbQZVaEji44j5lAUSQSqIEoul7Kua/BatBW0H0kKQcC9kwUHa1qzaWHSw==", + "requires": { + "commist": "^1.0.0", + "concat-stream": "^2.0.0", + "debug": "^4.1.1", + "duplexify": "^4.1.1", + "help-me": "^3.0.0", + "inherits": "^2.0.3", + "lru-cache": "^6.0.0", + "minimist": "^1.2.5", + "mqtt-packet": "^6.8.0", + "number-allocator": "^1.0.9", + "pump": "^3.0.0", + "readable-stream": "^3.6.0", + "reinterval": "^1.1.0", + "rfdc": "^1.3.0", + "split2": "^3.1.0", + "ws": "^7.5.5", + "xtend": "^4.0.2" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "mqtt-packet": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/mqtt-packet/-/mqtt-packet-6.10.0.tgz", + "integrity": "sha512-ja8+mFKIHdB1Tpl6vac+sktqy3gA8t9Mduom1BA75cI+R9AHnZOiaBQwpGiWnaVJLDGRdNhQmFaAqd7tkKSMGA==", + "requires": { + "bl": "^4.0.2", + "debug": "^4.1.1", + "process-nextick-args": "^2.0.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "nan": { + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.16.0.tgz", + "integrity": "sha512-UdAqHyFngu7TfQKsCBgAA6pWDkT8MAO7d0jyOecVhN5354xbLqdn8mV9Tat9gepAupm0bt2DbeaSC8vS52MuFA==" + }, + "napi-build-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", + "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==" + }, + "node-abi": { + "version": "3.22.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.22.0.tgz", + "integrity": "sha512-u4uAs/4Zzmp/jjsD9cyFYDXeISfUWaAVWshPmDZOFOv4Xl4SbzTXm53I04C2uRueYJ+0t5PEtLH/owbn2Npf/w==", + "requires": { + "semver": "^7.3.5" + } + }, + "nodemailer": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.7.tgz", + "integrity": "sha512-rUtR77ksqex/eZRLmQ21LKVH5nAAsVicAtAYudK7JgwenEDZ0UIQ1adUGqErz7sMkWYxWTTU1aeP2Jga6WQyJw==" + }, + "npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "number-allocator": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/number-allocator/-/number-allocator-1.0.14.tgz", + "integrity": "sha512-OrL44UTVAvkKdOdRQZIJpLkAdjXGTRda052sN4sO77bKEzYYqWKMBjQvrJFzqygI99gL6Z4u2xctPW1tB8ErvA==", + "requires": { + "debug": "^4.3.1", + "js-sdsl": "4.3.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==" + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==" + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==" + }, + "prebuild-install": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.0.tgz", + "integrity": "sha512-CNcMgI1xBypOyGqjp3wOc8AAo1nMhZS3Cwd3iHIxOdAUbb+YxdNuM4Z5iIrZ8RLvOsf3F3bl7b7xGq6DjQoNYA==", + "requires": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^1.0.1", + "node-abi": "^3.3.0", + "npmlog": "^4.0.1", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + } + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + } + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "reinterval": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reinterval/-/reinterval-1.1.0.tgz", + "integrity": "sha1-M2Hs+jymwYKDOA3Qu5VG85D17Oc=" + }, + "rfdc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==" + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "requires": { + "lru-cache": "^6.0.0" + } + }, + "serialport": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/serialport/-/serialport-9.2.8.tgz", + "integrity": "sha512-FsWpMQgSJxi93JgWl5xM1f9/Z8IjRJuaUEoHqLf8FPBLw7gMhInuHOBhI2onQufWIYPGTz3H3oGcu1nCaK1EfA==", + "requires": { + "@serialport/binding-mock": "9.2.4", + "@serialport/bindings": "9.2.8", + "@serialport/parser-byte-length": "9.2.4", + "@serialport/parser-cctalk": "9.2.4", + "@serialport/parser-delimiter": "9.2.4", + "@serialport/parser-inter-byte-timeout": "9.2.4", + "@serialport/parser-readline": "9.2.4", + "@serialport/parser-ready": "9.2.4", + "@serialport/parser-regex": "9.2.4", + "@serialport/stream": "9.2.4", + "debug": "^4.3.2" + } + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==" + }, + "simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "requires": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "split2": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", + "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", + "requires": { + "readable-stream": "^3.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==" + }, + "streamroller": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.1.1.tgz", + "integrity": "sha512-iPhtd9unZ6zKdWgMeYGfSBuqCngyJy1B/GPi/lTpwGpa3bajuX30GjUVd0/Tn/Xhg0mr4DOSENozz9Y06qyonQ==", + "requires": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "fs-extra": "^10.1.0" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" + }, + "tar-fs": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "requires": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "requires": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "total.js": { + "version": "3.4.13", + "resolved": "https://registry.npmjs.org/total.js/-/total.js-3.4.13.tgz", + "integrity": "sha512-lAH4gEixlPFbrE3xfKADAcHfO79IFq2wKa9GTsrgRzIR5MTg3mNH7+4IxvX1pK8faoYb/0oYSJ1YTsAa5hIFFQ==" + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, + "universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==" + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "requires": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "ws": { + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "requires": {} + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } + } +} diff --git a/RVO43/package.json b/RVO43/package.json new file mode 100755 index 0000000..7f7c795 --- /dev/null +++ b/RVO43/package.json @@ -0,0 +1,30 @@ +{ + "name": "emptyproject", + "description": "Total.js empty project.", + "version": "1.0.0", + "main": "debug.js", + "dependencies": { + "bitwise": "^2.1.0", + "easy-crc": "0.0.2", + "jsmodbus": "^4.0.6", + "log4js": "^6.3.0", + "moment": "^2.30.1", + "mqtt": "^4.2.6", + "nodemailer": "^6.9.7", + "serialport": "^9.2.8", + "total.js": "^3.4.13" + }, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "https://github.com/totaljs/emptyproject-flow" + }, + "keywords": [ + "empty", + "project" + ], + "author": "Peter Širka", + "license": "MIT" +} diff --git a/RVO43/release.js b/RVO43/release.js new file mode 100755 index 0000000..02d52ff --- /dev/null +++ b/RVO43/release.js @@ -0,0 +1,15 @@ +// =================================================== +// FOR PRODUCTION +// Total.js - framework for Node.js platform +// https://www.totaljs.com +// =================================================== + +const options = {'ip':'0.0.0.0', 'port':12345}; + +// options.ip = '127.0.0.1'; +// options.port = parseInt(process.argv[2]); +// options.config = { name: 'Total.js' }; +// options.sleep = 3000; + +require('total.js').http('release', options); +// require('total.js').cluster.http(5, 'release', options); diff --git a/RVO43/release.js.json b/RVO43/release.js.json new file mode 100755 index 0000000..d4ed908 --- /dev/null +++ b/RVO43/release.js.json @@ -0,0 +1,34 @@ +{ + "pid": 412, + "stats": [ + { + "id": null, + "version": { + "node": "v14.18.1", + "total": "3.4.13", + "app": "1.0.0" + }, + "pid": 412, + "thread": "", + "mode": "release", + "overload": 0, + "date": "2025-10-16T00:26:04.333Z", + "memory": 26.2, + "rm": 0, + "fm": 0, + "wm": 0, + "mm": 0, + "om": 20, + "em": 0, + "dbrm": 0, + "dbwm": 0, + "usage": 0, + "requests": 0, + "pending": 0, + "errors": 0, + "timeouts": 0, + "uptime": 657, + "online": 0 + } + ] +} \ No newline at end of file diff --git a/RVO43/report_data.log b/RVO43/report_data.log new file mode 100755 index 0000000..6142e3d --- /dev/null +++ b/RVO43/report_data.log @@ -0,0 +1,136 @@ +{ + "name": "rvo_senica_43_ip116", + "time": "2025-10-15T14:30:19.169Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_43_ip116", + "time": "2025-10-15T15:30:19.167Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_43_ip116", + "time": "2025-10-15T17:38:45.051Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_43_ip116", + "time": "2025-10-15T18:38:45.049Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_43_ip116", + "time": "2025-10-15T19:38:45.049Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_43_ip116", + "time": "2025-10-15T20:38:45.047Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_43_ip116", + "time": "2025-10-15T21:38:45.048Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_43_ip116", + "time": "2025-10-15T22:38:45.048Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_43_ip116", + "time": "2025-10-15T23:38:45.052Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +} \ No newline at end of file From 1b3f78fab302cc5897cb89edabe37e974ff4d82b Mon Sep 17 00:00:00 2001 From: Jakub Klena Date: Thu, 16 Oct 2025 02:27:03 +0200 Subject: [PATCH 25/30] Backup senica-RVO45 on 16.10.2025 --- RVO45/addSwitch.py | 36 + RVO45/cloud_topic.py | 76 + RVO45/config | 12 + RVO45/createNode.py | 43 + RVO45/databases/accelerometer_db.js | 3055 ++++++++++++++++ RVO45/databases/modbus_config.js | 114 + RVO45/databases/nodes.table | 46 + .../nodes_original/nodes_original.table | 1 + RVO45/databases/notifications.table | 41 + RVO45/databases/pins.table | 16 + RVO45/databases/relays.table | 7 + RVO45/databases/settings.table | 2 + RVO45/databases/tbdata.nosql | 4 + RVO45/databases/tbdatacloud.nosql | 3 + RVO45/databases/total_energy.js | 38 + RVO45/debug.js | 16 + RVO45/err.txt | 34 + RVO45/flow/cloudmqttconnect.js | 357 ++ RVO45/flow/cmd_manager.js | 3071 ++++++++++++++++ RVO45/flow/code.js | 90 + RVO45/flow/comment.js | 11 + RVO45/flow/count.js | 60 + RVO45/flow/db_connector.js | 286 ++ RVO45/flow/db_init.js | 113 + RVO45/flow/debug.js | 100 + RVO45/flow/designer.json | 3102 +++++++++++++++++ RVO45/flow/dido_controller.js | 1486 ++++++++ RVO45/flow/helper/DataToTbHandler.js | 187 + RVO45/flow/helper/ErrorToServiceHandler.js | 91 + RVO45/flow/helper/db_helper.js | 44 + RVO45/flow/helper/logger.js | 30 + RVO45/flow/helper/md5.js | 5 + RVO45/flow/helper/notification_reporter.js | 121 + RVO45/flow/helper/register.js | 144 + RVO45/flow/helper/serialport_helper.js | 99 + RVO45/flow/helper/suncalc.js | 317 ++ RVO45/flow/helper/utils.js | 161 + RVO45/flow/httprequest.js | 137 + RVO45/flow/httpresponse.js | 76 + RVO45/flow/httproute.js | 326 ++ RVO45/flow/infosender.js | 81 + RVO45/flow/modbus_reader.js | 346 ++ RVO45/flow/monitorconsumption.js | 156 + RVO45/flow/monitordisk.js | 96 + RVO45/flow/monitormemory.js | 87 + RVO45/flow/nodesdb_changecheck.js | 77 + RVO45/flow/show_dbdata.js | 243 ++ RVO45/flow/slack_filter.js | 188 + RVO45/flow/thermometer.js | 99 + RVO45/flow/trigger.js | 79 + RVO45/flow/variables.txt | 0 RVO45/flow/virtualwirein.js | 43 + RVO45/flow/virtualwireout.js | 41 + RVO45/flow/wsmqttpublish.js | 448 +++ .../cloudmqttconnect.js | 374 ++ .../cmd_manager.js | 2988 ++++++++++++++++ RVO45/flow_pred_verziou_2025_01_30/code.js | 90 + RVO45/flow_pred_verziou_2025_01_30/comment.js | 11 + .../db_connector.js | 286 ++ RVO45/flow_pred_verziou_2025_01_30/db_init.js | 106 + RVO45/flow_pred_verziou_2025_01_30/debug.js | 100 + .../designer.json | 2846 +++++++++++++++ .../dido_controller.js | 1524 ++++++++ .../helper/DataToTbHandler.js | 166 + .../helper/ErrorToServiceHandler.js | 126 + .../helper/db_helper.js | 44 + .../helper/logger.js | 30 + .../helper/md5.js | 5 + .../helper/notification_reporter.js | 131 + .../helper/register.js | 144 + .../helper/serialport_helper.js | 100 + .../helper/suncalc.js | 317 ++ .../helper/utils.js | 124 + .../httprequest.js | 137 + .../httpresponse.js | 76 + .../flow_pred_verziou_2025_01_30/httproute.js | 326 ++ .../infosender.js | 101 + .../modbus_reader.js | 367 ++ .../monitorconsumption.js | 156 + .../monitordisk.js | 96 + .../monitormemory.js | 87 + .../nodesdb_changecheck.js | 70 + .../show_dbdata.js | 241 ++ .../slack_filter.js | 187 + .../thermometer.js | 98 + RVO45/flow_pred_verziou_2025_01_30/trigger.js | 79 + .../variables.txt | 0 .../virtualwirein.js | 43 + .../virtualwireout.js | 41 + .../wsmqttpublish.js | 477 +++ RVO45/monitor.txt | 494 +++ RVO45/package-lock.json | 2125 +++++++++++ RVO45/package.json | 29 + RVO45/release.js | 15 + RVO45/release.js.json | 34 + RVO45/report_data.log | 174 + 96 files changed, 30907 insertions(+) create mode 100755 RVO45/addSwitch.py create mode 100755 RVO45/cloud_topic.py create mode 100755 RVO45/config create mode 100755 RVO45/createNode.py create mode 100755 RVO45/databases/accelerometer_db.js create mode 100755 RVO45/databases/modbus_config.js create mode 100755 RVO45/databases/nodes.table create mode 100755 RVO45/databases/nodes_original/nodes_original.table create mode 100755 RVO45/databases/notifications.table create mode 100755 RVO45/databases/pins.table create mode 100755 RVO45/databases/relays.table create mode 100755 RVO45/databases/settings.table create mode 100755 RVO45/databases/tbdata.nosql create mode 100755 RVO45/databases/tbdatacloud.nosql create mode 100755 RVO45/databases/total_energy.js create mode 100755 RVO45/debug.js create mode 100755 RVO45/err.txt create mode 100755 RVO45/flow/cloudmqttconnect.js create mode 100755 RVO45/flow/cmd_manager.js create mode 100755 RVO45/flow/code.js create mode 100755 RVO45/flow/comment.js create mode 100755 RVO45/flow/count.js create mode 100755 RVO45/flow/db_connector.js create mode 100755 RVO45/flow/db_init.js create mode 100755 RVO45/flow/debug.js create mode 100755 RVO45/flow/designer.json create mode 100755 RVO45/flow/dido_controller.js create mode 100755 RVO45/flow/helper/DataToTbHandler.js create mode 100755 RVO45/flow/helper/ErrorToServiceHandler.js create mode 100755 RVO45/flow/helper/db_helper.js create mode 100755 RVO45/flow/helper/logger.js create mode 100755 RVO45/flow/helper/md5.js create mode 100755 RVO45/flow/helper/notification_reporter.js create mode 100755 RVO45/flow/helper/register.js create mode 100755 RVO45/flow/helper/serialport_helper.js create mode 100755 RVO45/flow/helper/suncalc.js create mode 100755 RVO45/flow/helper/utils.js create mode 100755 RVO45/flow/httprequest.js create mode 100755 RVO45/flow/httpresponse.js create mode 100755 RVO45/flow/httproute.js create mode 100755 RVO45/flow/infosender.js create mode 100755 RVO45/flow/modbus_reader.js create mode 100755 RVO45/flow/monitorconsumption.js create mode 100755 RVO45/flow/monitordisk.js create mode 100755 RVO45/flow/monitormemory.js create mode 100755 RVO45/flow/nodesdb_changecheck.js create mode 100755 RVO45/flow/show_dbdata.js create mode 100755 RVO45/flow/slack_filter.js create mode 100755 RVO45/flow/thermometer.js create mode 100755 RVO45/flow/trigger.js create mode 100755 RVO45/flow/variables.txt create mode 100755 RVO45/flow/virtualwirein.js create mode 100755 RVO45/flow/virtualwireout.js create mode 100755 RVO45/flow/wsmqttpublish.js create mode 100755 RVO45/flow_pred_verziou_2025_01_30/cloudmqttconnect.js create mode 100755 RVO45/flow_pred_verziou_2025_01_30/cmd_manager.js create mode 100755 RVO45/flow_pred_verziou_2025_01_30/code.js create mode 100755 RVO45/flow_pred_verziou_2025_01_30/comment.js create mode 100755 RVO45/flow_pred_verziou_2025_01_30/db_connector.js create mode 100755 RVO45/flow_pred_verziou_2025_01_30/db_init.js create mode 100755 RVO45/flow_pred_verziou_2025_01_30/debug.js create mode 100755 RVO45/flow_pred_verziou_2025_01_30/designer.json create mode 100755 RVO45/flow_pred_verziou_2025_01_30/dido_controller.js create mode 100755 RVO45/flow_pred_verziou_2025_01_30/helper/DataToTbHandler.js create mode 100755 RVO45/flow_pred_verziou_2025_01_30/helper/ErrorToServiceHandler.js create mode 100755 RVO45/flow_pred_verziou_2025_01_30/helper/db_helper.js create mode 100755 RVO45/flow_pred_verziou_2025_01_30/helper/logger.js create mode 100755 RVO45/flow_pred_verziou_2025_01_30/helper/md5.js create mode 100755 RVO45/flow_pred_verziou_2025_01_30/helper/notification_reporter.js create mode 100755 RVO45/flow_pred_verziou_2025_01_30/helper/register.js create mode 100755 RVO45/flow_pred_verziou_2025_01_30/helper/serialport_helper.js create mode 100755 RVO45/flow_pred_verziou_2025_01_30/helper/suncalc.js create mode 100755 RVO45/flow_pred_verziou_2025_01_30/helper/utils.js create mode 100755 RVO45/flow_pred_verziou_2025_01_30/httprequest.js create mode 100755 RVO45/flow_pred_verziou_2025_01_30/httpresponse.js create mode 100755 RVO45/flow_pred_verziou_2025_01_30/httproute.js create mode 100755 RVO45/flow_pred_verziou_2025_01_30/infosender.js create mode 100755 RVO45/flow_pred_verziou_2025_01_30/modbus_reader.js create mode 100755 RVO45/flow_pred_verziou_2025_01_30/monitorconsumption.js create mode 100755 RVO45/flow_pred_verziou_2025_01_30/monitordisk.js create mode 100755 RVO45/flow_pred_verziou_2025_01_30/monitormemory.js create mode 100755 RVO45/flow_pred_verziou_2025_01_30/nodesdb_changecheck.js create mode 100755 RVO45/flow_pred_verziou_2025_01_30/show_dbdata.js create mode 100755 RVO45/flow_pred_verziou_2025_01_30/slack_filter.js create mode 100755 RVO45/flow_pred_verziou_2025_01_30/thermometer.js create mode 100755 RVO45/flow_pred_verziou_2025_01_30/trigger.js create mode 100755 RVO45/flow_pred_verziou_2025_01_30/variables.txt create mode 100755 RVO45/flow_pred_verziou_2025_01_30/virtualwirein.js create mode 100755 RVO45/flow_pred_verziou_2025_01_30/virtualwireout.js create mode 100755 RVO45/flow_pred_verziou_2025_01_30/wsmqttpublish.js create mode 100755 RVO45/monitor.txt create mode 100755 RVO45/package-lock.json create mode 100755 RVO45/package.json create mode 100755 RVO45/release.js create mode 100755 RVO45/release.js.json create mode 100755 RVO45/report_data.log diff --git a/RVO45/addSwitch.py b/RVO45/addSwitch.py new file mode 100755 index 0000000..c35e96b --- /dev/null +++ b/RVO45/addSwitch.py @@ -0,0 +1,36 @@ +import os + +def process_set_file(): + """ + Checks if /root/flowserver exists, reads set.txt, and modifies the second line. + """ + default_folder = "/root/flowserver" if os.path.exists("/root/flowserver") else "/home/unipi/flowserver" + flag = 1 if default_folder == "/root/flowserver" else 0 + + try: + with open("/home/unipi/flowserver/databases/settings.table", "r") as f: + lines = f.readlines() + + if len(lines) >= 2: + lines[0] = lines[0].rstrip('\n') + "|main_switch:boolean\n" + second_line = lines[1].strip() # remove trailing newline + last_pipe_index = second_line.rfind("|") + + if last_pipe_index != -1: + modified_line = second_line[:last_pipe_index + 1] + str(flag) + "|" + second_line[last_pipe_index + 1:] + lines[1] = modified_line + else: + print("Warning: No '|' character found in the second line of set.txt") + + with open("/home/unipi/flowserver/databases/settings.table", "w") as f: + f.writelines(lines) + else: + print("Warning: settings.table has less than two lines.") + + except FileNotFoundError: + print("Error: settings.table not found.") + except Exception as e: + print(e) + +# if __name__ == "__main__": +process_set_file() diff --git a/RVO45/cloud_topic.py b/RVO45/cloud_topic.py new file mode 100755 index 0000000..77c31f1 --- /dev/null +++ b/RVO45/cloud_topic.py @@ -0,0 +1,76 @@ +# import os +# +# def modify_file(file_path): +# """ +# Modifies the given file by: +# 1. Appending "|cloud_topic" to the first line. +# 2. Inserting the text from the third "." to the first "|" on the second line after the last "|" character. +# +# Args: +# file_path (str): The path to the file to be modified. +# """ +# +# with open(file_path, 'r+') as f: +# lines = f.readlines() +# +# # Modify the first line +# lines[0] += "|cloud_topic:string" +# +# # Modify the second line +# second_line = lines[1].strip() # Remove leading/trailing whitespace +# first_pipe_index = second_line.find('|') +# third_dot_index = second_line.find('.', second_line.find('.', second_line.find('.') + 1) + 1) +# text_to_insert = second_line[third_dot_index:first_pipe_index] +# +# last_pipe_index = second_line.rfind('|') +# lines[1] = second_line[:last_pipe_index + 1] + text_to_insert + "|" + second_line[last_pipe_index + 1:] +# +# print(first_pipe_index, third_dot_index, text_to_insert, last_pipe_index) +# # Write the modified lines back to the file +# # f.seek(0) +# # f.writelines(lines) +# # f.truncate() +# +# # Example usage: +# file_path = "settings.table" # Replace with the actual file path +# modify_file(file_path) +# + + +def modify_file(file_path): + """ + Modifies the given file by: + 1. Appending "|cloud_topic" to the first line. + 2. Inserting the text between the third "." and the second "|" on the second line after the last "|" character. + + Args: + file_path (str): The path to the file to be modified. + """ + + with open(file_path, 'r+') as f: + lines = f.readlines() + + first_line = lines[0].strip() + first_line += "|cloud_topic:string\n" + # Modify the first line + lines[0] = first_line + + # Modify the second line + second_line = lines[1].strip() # Remove leading/trailing whitespace + first_pipe_index = second_line.find('|') + second_pipe_index = second_line.find('|', first_pipe_index + 1) + third_dot_index = second_line.find('.', second_line.find('.', second_line.find('.') + 1) + 1) + text_to_insert = "u" + second_line[third_dot_index+1:second_pipe_index] + + last_pipe_index = second_line.rfind('|') + lines[1] = second_line[:last_pipe_index + 1] + text_to_insert + "|" + second_line[last_pipe_index + 1:] + + print(first_pipe_index, third_dot_index, text_to_insert, last_pipe_index) + # Write the modified lines back to the file + f.seek(0) + f.writelines(lines) + f.truncate() + +# Example usage: +file_path = "/home/unipi/flowserver/databases/settings.table" # Replace with the actual file path +modify_file(file_path) diff --git a/RVO45/config b/RVO45/config new file mode 100755 index 0000000..cd0a8a9 --- /dev/null +++ b/RVO45/config @@ -0,0 +1,12 @@ +name : Total.js Flow +default_timezone : Europe/Bratislava + +// Packages settings +package#flow (Object) : { url: '/' } + + +table.relays : line:number|tbname:string|contactor:number|profile:string +table.nodes : node:number|pole_number:string|node_type:string|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|project_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|cloud_topic:string|has_main_switch:boolean|daily_report:boolean|send_changed_node_numbers:boolean +table.pins : pin:string|type:string|line:number +table.notifications : key:string|weight:string|sk:string|en:string diff --git a/RVO45/createNode.py b/RVO45/createNode.py new file mode 100755 index 0000000..a8cea91 --- /dev/null +++ b/RVO45/createNode.py @@ -0,0 +1,43 @@ +print("zaciname") +import re, json + +search_str = '|' +final = [] +counter = 1 +with open("/home/unipi/flowserver/databases/nodes.table", 'r') as file: +# with open("/home/rasta5man/dev/oms/flowserver/databases/nodes.table", 'r') as file: + # Read each line in the file + for line in file: + # Print each line + line = line.strip() + print(line) + if counter != 1: + i = [m.start() for m in re.finditer(re.escape(search_str), line)] + node = line[ i[0] + 1 : i[1] ] + tbname = line[ i[3] + 1 : i[4] ] + final.append({node:tbname}) + counter += 1 +print(json.dumps(final)) +f = open("/home/unipi/flowserver/databases/nodes_original/nodes_original.table", "w") +f.write(json.dumps(final)) +f.close() + + +# +# # ``d`` has to be replaced with a different character +# old_character = "'" +# +# # ``t`` will replace ``d` +# new_character = '"' +# resultant_string = 0; +# with open("/home/unipi/flowserver/databases/nodes_original/nodes_original.table", 'r') as file: +# for line in file: +# resultant_string = re.sub("'", '"', line) +# +# resultant_string = re.sub(" ", "", resultant_string) +# print(resultant_string) +# +# f = open("/home/unipi/flowserver/databases/nodes_original/nodes_original.table", "w") +# f.write(str(resultant_string)) +# f.close() +# diff --git a/RVO45/databases/accelerometer_db.js b/RVO45/databases/accelerometer_db.js new file mode 100755 index 0000000..fdfc7fd --- /dev/null +++ b/RVO45/databases/accelerometer_db.js @@ -0,0 +1,3055 @@ +let naklony = { + "3993": { "label": "1/3A", "naklon": 0 }, + "3989": { "label": "1/3B", "naklon": 15 }, + "3976": { "label": "1/1", "naklon": 0 }, + "4181": { "label": "1/2", "naklon": 0 }, + "4376": { "label": "1/4", "naklon": 15 }, + "3868": { "label": "1/5", "naklon": 15 }, + "3728": { "label": "1/6", "naklon": 15 }, + "3730": { "label": "1/7", "naklon": 0 }, + "4374": { "label": "1/8", "naklon": 0 }, + "3718": { "label": "1/9", "naklon": 15 }, + "4375": { "label": "1/10", "naklon": 15 }, + "4172": { "label": "1/11", "naklon": 15 }, + "4176": { "label": "1/12", "naklon": 15 }, + "3800": { "label": "2/1", "naklon": 5 }, + "3823": { "label": "2/2", "naklon": 5 }, + "3905": { "label": "2/3", "naklon": 5 }, + "3803": { "label": "2/4", "naklon": 5 }, + "3817": { "label": "2/5", "naklon": 5 }, + "3818": { "label": "2/6", "naklon": 5 }, + "3811": { "label": "2/7", "naklon": 5 }, + "3915": { "label": "2/8", "naklon": 5 }, + "3843": { "label": "2/9", "naklon": 10 }, + "3827": { "label": "2/10", "naklon": 10 }, + "4220": { "label": "2/11", "naklon": 10 }, + "3826": { "label": "2/12", "naklon": 10 }, + "3834": { "label": "2/13", "naklon": 10 }, + "3838": { "label": "2/14", "naklon": 10 }, + "2823": { "label": "2/15", "naklon": 10 }, + "3750": { "label": "2/16", "naklon": 10 }, + "3378": { "label": "2/17", "naklon": 0 }, + "3376": { "label": "2/18", "naklon": 0 }, + "3379": { "label": "2/19", "naklon": 0 }, + "3285": { "label": "2/20", "naklon": 0 }, + "3382": { "label": "2/21", "naklon": 0 }, + "3383": { "label": "2/22", "naklon": 0 }, + "3375": { "label": "2/24", "naklon": 0 }, + "3381": { "label": "2/25", "naklon": 0 }, + "3380": { "label": "2/26", "naklon": 0 }, + "3828": { "label": "2/27", "naklon": 10 }, + "3377": { "label": "2/28", "naklon": 0 }, + "3591": { "label": "7/1", "naklon": 0 }, + "3587": { "label": "7/2", "naklon": 0 }, + "3468": { "label": "7/3", "naklon": 0 }, + "3466": { "label": "7/4", "naklon": 0 }, + "3474": { "label": "7/5", "naklon": 0 }, + "3481": { "label": "7/6", "naklon": 0 }, + "3589": { "label": "7/7", "naklon": 0 }, + "3472": { "label": "7/8", "naklon": 0 }, + "3473": { "label": "7/9", "naklon": 0 }, + "3584": { "label": "7/10", "naklon": 0 }, + "3571": { "label": "7/11", "naklon": 0 }, + "3476": { "label": "7/12", "naklon": 0 }, + "3590": { "label": "7/13", "naklon": 0 }, + "3478": { "label": "7/14", "naklon": 0 }, + "3471": { "label": "7/15", "naklon": 0 }, + "3467": { "label": "7/16", "naklon": 0 }, + "3479": { "label": "7/17", "naklon": 0 }, + "3480": { "label": "7/18", "naklon": 0 }, + "3477": { "label": "7/19", "naklon": 0 }, + "3362": { "label": "12/1", "naklon": 0 }, + "3355": { "label": "12/2", "naklon": 0 }, + "3356": { "label": "12/3", "naklon": 0 }, + "3349": { "label": "12/4", "naklon": 0 }, + "3357": { "label": "12/5", "naklon": 0 }, + "3350": { "label": "12/6", "naklon": 0 }, + "3353": { "label": "12/7", "naklon": 0 }, + "3539": { "label": "12/8", "naklon": 0 }, + "3050": { "label": "12/9", "naklon": 0 }, + "3361": { "label": "12/10", "naklon": 0 }, + "3360": { "label": "12/11", "naklon": 0 }, + "3358": { "label": "12/12", "naklon": 0 }, + "3541": { "label": "12/13", "naklon": 0 }, + "3551": { "label": "12/14", "naklon": 0 }, + "3514": { "label": "12/15", "naklon": 0 }, + "3547": { "label": "12/16", "naklon": 0 }, + "3562": { "label": "12/17", "naklon": 0 }, + "3525": { "label": "12/18", "naklon": 0 }, + "3558": { "label": "12/19", "naklon": 0 }, + "3511": { "label": "12/20", "naklon": 0 }, + "3058": { "label": "12/21", "naklon": 0 }, + "3062": { "label": "12/22", "naklon": 0 }, + "3070": { "label": "12/23", "naklon": 0 }, + "3447": { "label": "12/24", "naklon": 0 }, + "3056": { "label": "12/25", "naklon": 0 }, + "3057": { "label": "12/26", "naklon": 0 }, + "3071": { "label": "12/27", "naklon": 0 }, + "3061": { "label": "12/28", "naklon": 0 }, + "3069": { "label": "12/29", "naklon": 0 }, + "3077": { "label": "12/30", "naklon": 0 }, + "3080": { "label": "12/31", "naklon": 0 }, + "3081": { "label": "12/32", "naklon": 0 }, + "3078": { "label": "12/33", "naklon": 0 }, + "4037": { "label": "12/34", "naklon": 0 }, + "3067": { "label": "12/35", "naklon": 0 }, + "3051": { "label": "12/36", "naklon": 0 }, + "2924": { "label": "12/37", "naklon": 0 }, + "3060": { "label": "12/38", "naklon": 0 }, + "3073": { "label": "12/39", "naklon": 0 }, + "3469": { "label": "12/40", "naklon": 0 }, + "2923": { "label": "12/41", "naklon": 0 }, + "2925": { "label": "12/42", "naklon": 0 }, + "3359": { "label": "12/43", "naklon": 0 }, + "3055": { "label": "12/44", "naklon": 0 }, + "2922": { "label": "12/45", "naklon": 0 }, + "3084": { "label": "12/46", "naklon": 0 }, + "3064": { "label": "12/47", "naklon": 0 }, + "3066": { "label": "12/48", "naklon": 0 }, + "3072": { "label": "12/49", "naklon": 0 }, + "3415": { "label": "13/13A", "naklon": 0 }, + "3409": { "label": "13/13B", "naklon": 0 }, + "3399": { "label": "13/13C", "naklon": 0 }, + "3410": { "label": "13/29A", "naklon": 0 }, + "3407": { "label": "13/29B", "naklon": 0 }, + "3405": { "label": "13/34A", "naklon": 0 }, + "3404": { "label": "13/34B", "naklon": 0 }, + "3392": { "label": "13/45A", "naklon": 0 }, + "3386": { "label": "13/45B", "naklon": 0 }, + "3303": { "label": "13/60A", "naklon": 3 }, + "3302": { "label": "13/60B", "naklon": 3 }, + "3319": { "label": "13/70A", "naklon": 6 }, + "3317": { "label": "13/70B", "naklon": 6 }, + "3326": { "label": "13/70C", "naklon": 6 }, + "3351": { "label": "13/73A", "naklon": 6 }, + "3313": { "label": "13/73B", "naklon": 6 }, + "3316": { "label": "13/83A", "naklon": 0 }, + "3320": { "label": "13/83B", "naklon": 0 }, + "3336": { "label": "13/95A", "naklon": 0 }, + "3323": { "label": "13/95B", "naklon": 0 }, + "3339": { "label": "13/98A", "naklon": 0 }, + "3333": { "label": "13/98B", "naklon": 0 }, + "3425": { "label": "13/1", "naklon": 0 }, + "3419": { "label": "13/2", "naklon": 0 }, + "3416": { "label": "13/3", "naklon": 0 }, + "3332": { "label": "13/4", "naklon": 0 }, + "3422": { "label": "13/5", "naklon": 0 }, + "3417": { "label": "13/6", "naklon": 0 }, + "3418": { "label": "13/7", "naklon": 0 }, + "3424": { "label": "13/8", "naklon": 0 }, + "3334": { "label": "13/9", "naklon": 0 }, + "4363": { "label": "13/10", "naklon": 0 }, + "3423": { "label": "13/11", "naklon": 0 }, + "3406": { "label": "13/12", "naklon": 0 }, + "3411": { "label": "13/14", "naklon": 0 }, + "3412": { "label": "13/15", "naklon": 0 }, + "3413": { "label": "13/16", "naklon": 0 }, + "3414": { "label": "13/17", "naklon": 0 }, + "3391": { "label": "13/18", "naklon": 0 }, + "3370": { "label": "13/19", "naklon": 0 }, + "3369": { "label": "13/20", "naklon": 0 }, + "3408": { "label": "13/21", "naklon": 0 }, + "3393": { "label": "13/22", "naklon": 0 }, + "3128": { "label": "13/23", "naklon": 0 }, + "3197": { "label": "13/24", "naklon": 0 }, + "4364": { "label": "13/25", "naklon": 0 }, + "3155": { "label": "13/26", "naklon": 0 }, + "3196": { "label": "13/27", "naklon": 0 }, + "3144": { "label": "13/28", "naklon": 0 }, + "3150": { "label": "13/30", "naklon": 0 }, + "3390": { "label": "13/31", "naklon": 0 }, + "3401": { "label": "13/32", "naklon": 0 }, + "3275": { "label": "13/33", "naklon": 0 }, + "3371": { "label": "13/35", "naklon": 0 }, + "3389": { "label": "13/36", "naklon": 0 }, + "3388": { "label": "13/37", "naklon": 0 }, + "3365": { "label": "13/38", "naklon": 0 }, + "3363": { "label": "13/39", "naklon": 0 }, + "3397": { "label": "13/40", "naklon": 0 }, + "3567": { "label": "13/40/1", "naklon": 0 }, + "3387": { "label": "13/41", "naklon": 0 }, + "3403": { "label": "13/42", "naklon": 0 }, + "3147": { "label": "13/43", "naklon": 0 }, + "3141": { "label": "13/44", "naklon": 0 }, + "3364": { "label": "13/46", "naklon": 0 }, + "3367": { "label": "13/47", "naklon": 0 }, + "3368": { "label": "13/48", "naklon": 0 }, + "3402": { "label": "13/49", "naklon": 0 }, + "3366": { "label": "13/50", "naklon": 0 }, + "3395": { "label": "13/51", "naklon": 0 }, + "3372": { "label": "13/52", "naklon": 0 }, + "3394": { "label": "13/53", "naklon": 0 }, + "3308": { "label": "13/54", "naklon": 0 }, + "3847": { "label": "13/54/1", "naklon": 0 }, + "3312": { "label": "13/55", "naklon": 3 }, + "3309": { "label": "13/56", "naklon": 3 }, + "3311": { "label": "13/57", "naklon": 3 }, + "3310": { "label": "13/58", "naklon": 3 }, + "4365": { "label": "13/59", "naklon": 3 }, + "4093": { "label": "13/60/1", "naklon": 3 }, + "3304": { "label": "13/61", "naklon": 3 }, + "3307": { "label": "13/62", "naklon": 3 }, + "3271": { "label": "13/63", "naklon": 3 }, + "3301": { "label": "13/64", "naklon": 3 }, + "4366": { "label": "13/65", "naklon": 3 }, + "3300": { "label": "13/66", "naklon": 3 }, + "3185": { "label": "13/67", "naklon": 0 }, + "3184": { "label": "13/68", "naklon": 0 }, + "3188": { "label": "13/69", "naklon": 0 }, + "3343": { "label": "13/71", "naklon": 6 }, + "3819": { "label": "13/71/1", "naklon": 6 }, + "3880": { "label": "13/71/2", "naklon": 6 }, + "3348": { "label": "13/72", "naklon": 6 }, + "3344": { "label": "13/74", "naklon": 6 }, + "3346": { "label": "13/75", "naklon": 6 }, + "3597": { "label": "13/75/1", "naklon": 6 }, + "3345": { "label": "13/76", "naklon": 6 }, + "3322": { "label": "13/77", "naklon": 0 }, + "3325": { "label": "13/78", "naklon": 0 }, + "4310": { "label": "13/78/1", "naklon": 0 }, + "3315": { "label": "13/79", "naklon": 0 }, + "3328": { "label": "13/80", "naklon": 0 }, + "3321": { "label": "13/81", "naklon": 0 }, + "3324": { "label": "13/82", "naklon": 0 }, + "3140": { "label": "13/84", "naklon": 0 }, + "3153": { "label": "13/85", "naklon": 0 }, + "3145": { "label": "13/86", "naklon": 0 }, + "3134": { "label": "13/87", "naklon": 0 }, + "3151": { "label": "13/88", "naklon": 0 }, + "3143": { "label": "13/89", "naklon": 0 }, + "3318": { "label": "13/90", "naklon": 0 }, + "3347": { "label": "13/91", "naklon": 0 }, + "3314": { "label": "13/94", "naklon": 0 }, + "3331": { "label": "13/96", "naklon": 0 }, + "3327": { "label": "13/97", "naklon": 0 }, + "3329": { "label": "13/99", "naklon": 0 }, + "3337": { "label": "13/100", "naklon": 0 }, + "3330": { "label": "13/101", "naklon": 0 }, + "3335": { "label": "13/102", "naklon": 0 }, + "3420": { "label": "13/103", "naklon": 0 }, + "3421": { "label": "13/104", "naklon": 0 }, + "4361": { "label": "13/105", "naklon": 0 }, + "4362": { "label": "13/106", "naklon": 0 }, + "3526": { "label": "13/107", "naklon": 0 }, + "4424": { "label": "13/108", "naklon": null }, + "3561": { "label": "13/109", "naklon": null }, + "3527": { "label": "13/110", "naklon": null }, + "3521": { "label": "13/111", "naklon": null }, + "3552": { "label": "13/112", "naklon": null }, + "3544": { "label": "13/113", "naklon": null }, + "3534": { "label": "13/114", "naklon": null }, + "3516": { "label": "13/115", "naklon": null }, + "3513": { "label": "13/116", "naklon": null }, + "3565": { "label": "13/117", "naklon": null }, + "3866": { "label": "13/118", "naklon": null }, + "3136": { "label": "14/1", "naklon": 0 }, + "3137": { "label": "14/2", "naklon": 0 }, + "3135": { "label": "14/3", "naklon": 0 }, + "3149": { "label": "14/4", "naklon": 0 }, + "3142": { "label": "14/5", "naklon": 0 }, + "3342": { "label": "14/6", "naklon": 0 }, + "3340": { "label": "14/7", "naklon": 0 }, + "3152": { "label": "14/8", "naklon": 0 }, + "3886": { "label": "14/9", "naklon": 0 }, + "3341": { "label": "14/10", "naklon": null }, + "3352": { "label": "14/11", "naklon": null }, + "3396": { "label": "15/1", "naklon": 5 }, + "2784": { "label": "15/2", "naklon": 5 }, + "2788": { "label": "15/3", "naklon": 5 }, + "2801": { "label": "15/4", "naklon": 5 }, + "2815": { "label": "15/5", "naklon": 5 }, + "2829": { "label": "15/6", "naklon": 5 }, + "2796": { "label": "15/7", "naklon": 5 }, + "2803": { "label": "15/8", "naklon": 5 }, + "4304": { "label": "15/8/1", "naklon": 5 }, + "4311": { "label": "15/8/2", "naklon": 5 }, + "2821": { "label": "15/9", "naklon": 5 }, + "3400": { "label": "15/10", "naklon": 5 }, + "2799": { "label": "15/11", "naklon": 5 }, + "2804": { "label": "15/12", "naklon": 5 }, + "4303": { "label": "15/12/1", "naklon": 5 }, + "4309": { "label": "15/12/2", "naklon": 5 }, + "2806": { "label": "15/13", "naklon": 5 }, + "2787": { "label": "15/14", "naklon": 5 }, + "2809": { "label": "15/15", "naklon": 5 }, + "2814": { "label": "15/16", "naklon": 0 }, + "3934": { "label": "15/17", "naklon": 0 }, + "3192": { "label": "15/18", "naklon": 0 }, + "2812": { "label": "15/19", "naklon": 0 }, + "4070": { "label": "15/20", "naklon": 0 }, + "2826": { "label": "15/21", "naklon": 0 }, + "2808": { "label": "15/22", "naklon": 3 }, + "2795": { "label": "15/23", "naklon": 3 }, + "2807": { "label": "15/24", "naklon": 3 }, + "2831": { "label": "15/25", "naklon": 0 }, + "2862": { "label": "15/26", "naklon": null }, + "2861": { "label": "15/27", "naklon": 0 }, + "2866": { "label": "15/28", "naklon": 0 }, + "3546": { "label": "15/28/1", "naklon": 0 }, + "4146": { "label": "15/29", "naklon": 0 }, + "3001": { "label": "15/29/1", "naklon": 0 }, + "2835": { "label": "15/30", "naklon": 0 }, + "2874": { "label": "15/31", "naklon": 0 }, + "2852": { "label": "15/32", "naklon": 0 }, + "2851": { "label": "15/33", "naklon": 0 }, + "3560": { "label": "15/33/1", "naklon": 0 }, + "2858": { "label": "15/34", "naklon": 0 }, + "4306": { "label": "15/34/1", "naklon": 0 }, + "2856": { "label": "15/35", "naklon": 0 }, + "2847": { "label": "15/36", "naklon": 0 }, + "3556": { "label": "15/36/1", "naklon": 0 }, + "3950": { "label": "15/37", "naklon": 0 }, + "2848": { "label": "15/38", "naklon": 0 }, + "2863": { "label": "15/39", "naklon": 0 }, + "4313": { "label": "15/39/1", "naklon": 0 }, + "2873": { "label": "15/40", "naklon": 0 }, + "2984": { "label": "15/40/1", "naklon": 0 }, + "2854": { "label": "15/41", "naklon": 0 }, + "2859": { "label": "15/42", "naklon": 0 }, + "2872": { "label": "15/43", "naklon": 0 }, + "2849": { "label": "15/44", "naklon": 0 }, + "2864": { "label": "15/45", "naklon": 0 }, + "3553": { "label": "15/46", "naklon": null }, + "3021": { "label": "15/47", "naklon": null }, + "3008": { "label": "15/47/1", "naklon": null }, + "3017": { "label": "15/48", "naklon": null }, + "3014": { "label": "15/49", "naklon": null }, + "2981": { "label": "15/50", "naklon": null }, + "3020": { "label": "15/51", "naklon": null }, + "3027": { "label": "15/52", "naklon": null }, + "3006": { "label": "15/53", "naklon": null }, + "3012": { "label": "15/54", "naklon": null }, + "2738": { "label": "15/55", "naklon": 0 }, + "2725": { "label": "15/56", "naklon": 0 }, + "3016": { "label": "15/57", "naklon": null }, + "3005": { "label": "15/58", "naklon": null }, + "3009": { "label": "15/58/1", "naklon": null }, + "3010": { "label": "15/59", "naklon": 0 }, + "3538": { "label": "15/59/1", "naklon": 0 }, + "4145": { "label": "15/59/2", "naklon": 0 }, + "2713": { "label": "15/60", "naklon": 0 }, + "2789": { "label": "15/61", "naklon": 0 }, + "2736": { "label": "15/62", "naklon": 0 }, + "2739": { "label": "15/63", "naklon": 0 }, + "4346": { "label": "15/64", "naklon": 0 }, + "2731": { "label": "15/65", "naklon": 0 }, + "2818": { "label": "15/66", "naklon": 0 }, + "3557": { "label": "15/66/1", "naklon": 0 }, + "2822": { "label": "15/67", "naklon": 0 }, + "2833": { "label": "15/68", "naklon": 0 }, + "2834": { "label": "15/69", "naklon": 0 }, + "3097": { "label": "15/70", "naklon": 0 }, + "2824": { "label": "15/71", "naklon": 0 }, + "2828": { "label": "15/72", "naklon": 0 }, + "2600": { "label": "15/73", "naklon": 0 }, + "4314": { "label": "15/73/1", "naklon": 0 }, + "2832": { "label": "15/74", "naklon": 0 }, + "4360": { "label": "15/75", "naklon": 0 }, + "2846": { "label": "15/76", "naklon": 0 }, + "2584": { "label": "15/77", "naklon": 0 }, + "2843": { "label": "15/78", "naklon": 0 }, + "4308": { "label": "15/78/1", "naklon": 0 }, + "4144": { "label": "15/79", "naklon": null }, + "2844": { "label": "15/80", "naklon": 0 }, + "2842": { "label": "15/81", "naklon": 0 }, + "2838": { "label": "15/82", "naklon": 0 }, + "2837": { "label": "15/83", "naklon": null }, + "3555": { "label": "15/83/1", "naklon": null }, + "2839": { "label": "15/84", "naklon": 0 }, + "2830": { "label": "15/85", "naklon": 0 }, + "4066": { "label": "15/86", "naklon": 0 }, + "2836": { "label": "15/87", "naklon": 0 }, + "2911": { "label": "15/88", "naklon": 0 }, + "2825": { "label": "15/89", "naklon": 0 }, + "2811": { "label": "15/90", "naklon": 0 }, + "3740": { "label": "15/94", "naklon": 15 }, + "2734": { "label": "15/95", "naklon": 15 }, + "3105": { "label": "15/96", "naklon": 15 }, + "2732": { "label": "15/97", "naklon": 15 }, + "2727": { "label": "15/98", "naklon": 15 }, + "2735": { "label": "15/99", "naklon": 15 }, + "3926": { "label": "15/100", "naklon": 15 }, + "2918": { "label": "15/101", "naklon": 0 }, + "2705": { "label": "15/102", "naklon": 10 }, + "2708": { "label": "15/103", "naklon": 10 }, + "2721": { "label": "15/104", "naklon": 10 }, + "2719": { "label": "15/105", "naklon": 10 }, + "2919": { "label": "15/106", "naklon": 10 }, + "3101": { "label": "15/107", "naklon": 10 }, + "2853": { "label": "15/108", "naklon": 10 }, + "2715": { "label": "15/109", "naklon": 10 }, + "2712": { "label": "15/110", "naklon": 0 }, + "2711": { "label": "15/111", "naklon": 0 }, + "2709": { "label": "15/112", "naklon": 0 }, + "2710": { "label": "15/113", "naklon": 0 }, + "2907": { "label": "15/114", "naklon": 0 }, + "2906": { "label": "15/115", "naklon": 0 }, + "2908": { "label": "15/116", "naklon": 0 }, + "2901": { "label": "15/117", "naklon": 0 }, + "2913": { "label": "15/118", "naklon": 0 }, + "3656": { "label": "15/119", "naklon": 0 }, + "2781": { "label": "15/120", "naklon": 0 }, + "2802": { "label": "15/121", "naklon": 0 }, + "2791": { "label": "15/122", "naklon": 0 }, + "2783": { "label": "15/123", "naklon": 0 }, + "2794": { "label": "15/124", "naklon": 0 }, + "3139": { "label": "15/125", "naklon": 0 }, + "3229": { "label": "15/126", "naklon": 5 }, + "3239": { "label": "15/127", "naklon": 5 }, + "3230": { "label": "15/128", "naklon": 5 }, + "4016": { "label": "15/129", "naklon": null }, + "3608": { "label": "16/16A", "naklon": 0 }, + "4151": { "label": "16/16B", "naklon": 0 }, + "3710": { "label": "16/1", "naklon": 0 }, + "3726": { "label": "16/2", "naklon": 0 }, + "3743": { "label": "16/3", "naklon": 0 }, + "3724": { "label": "16/4", "naklon": 0 }, + "3712": { "label": "16/5", "naklon": 0 }, + "3739": { "label": "16/6", "naklon": 0 }, + "3742": { "label": "16/7", "naklon": 0 }, + "3731": { "label": "16/8", "naklon": 0 }, + "3727": { "label": "16/9", "naklon": 0 }, + "3729": { "label": "16/10", "naklon": 0 }, + "3736": { "label": "16/11", "naklon": 0 }, + "3713": { "label": "16/12", "naklon": 0 }, + "3715": { "label": "16/13", "naklon": 0 }, + "3733": { "label": "16/14", "naklon": 0 }, + "3732": { "label": "16/15", "naklon": 0 }, + "3634": { "label": "16/17", "naklon": 0 }, + "3610": { "label": "16/18", "naklon": 0 }, + "3626": { "label": "16/19", "naklon": 0 }, + "3618": { "label": "16/20", "naklon": 0 }, + "3619": { "label": "16/21", "naklon": 0 }, + "3628": { "label": "16/22", "naklon": 0 }, + "3615": { "label": "16/23", "naklon": 0 }, + "3609": { "label": "16/24", "naklon": 0 }, + "3606": { "label": "16/25", "naklon": 0 }, + "3624": { "label": "16/26", "naklon": 0 }, + "3627": { "label": "16/27", "naklon": 0 }, + "3607": { "label": "16/28", "naklon": 0 }, + "4370": { "label": "16/29", "naklon": 0 }, + "3692": { "label": "16/30", "naklon": 0 }, + "3614": { "label": "16/31", "naklon": 0 }, + "3623": { "label": "16/32", "naklon": 0 }, + "4373": { "label": "16/33", "naklon": 0 }, + "3620": { "label": "16/34", "naklon": 0 }, + "3685": { "label": "16/35", "naklon": 0 }, + "3616": { "label": "16/36", "naklon": 0 }, + "3686": { "label": "16/37", "naklon": 0 }, + "3688": { "label": "16/38", "naklon": 0 }, + "3684": { "label": "16/39", "naklon": 0 }, + "3825": { "label": "16/40", "naklon": 0 }, + "3865": { "label": "16/41", "naklon": 0 }, + "3824": { "label": "16/42", "naklon": 0 }, + "3871": { "label": "16/43", "naklon": 0 }, + "3801": { "label": "16/44", "naklon": 0 }, + "3862": { "label": "16/45", "naklon": 0 }, + "3876": { "label": "16/46", "naklon": 0 }, + "3861": { "label": "16/47", "naklon": 0 }, + "4215": { "label": "16/48", "naklon": 0 }, + "3605": { "label": "16/49", "naklon": 10 }, + "3603": { "label": "16/50", "naklon": 10 }, + "3592": { "label": "16/51", "naklon": 10 }, + "3598": { "label": "16/52", "naklon": 10 }, + "3594": { "label": "16/53", "naklon": 10 }, + "3593": { "label": "16/54", "naklon": 10 }, + "3630": { "label": "16/55", "naklon": 10 }, + "3763": { "label": "16/56", "naklon": 10 }, + "3746": { "label": "16/57", "naklon": 10 }, + "3699": { "label": "16/58", "naklon": 0 }, + "3698": { "label": "16/59", "naklon": 0 }, + "3709": { "label": "16/60", "naklon": null }, + "3708": { "label": "16/61", "naklon": 0 }, + "3703": { "label": "16/62", "naklon": null }, + "3700": { "label": "16/63", "naklon": 0 }, + "3701": { "label": "16/64", "naklon": null }, + "3704": { "label": "16/65", "naklon": 0 }, + "3707": { "label": "16/66", "naklon": null }, + "3810": { "label": "16/67", "naklon": 0 }, + "4208": { "label": "16/68", "naklon": null }, + "3867": { "label": "16/69", "naklon": 0 }, + "4372": { "label": "16/70", "naklon": null }, + "3881": { "label": "16/71", "naklon": 0 }, + "4204": { "label": "16/72", "naklon": null }, + "3869": { "label": "16/73", "naklon": 0 }, + "4202": { "label": "16/74", "naklon": null }, + "3830": { "label": "16/75", "naklon": 0 }, + "3870": { "label": "16/76", "naklon": null }, + "3964": { "label": "16/77", "naklon": 0 }, + "3849": { "label": "16/78", "naklon": 0 }, + "3694": { "label": "16/79", "naklon": null }, + "3717": { "label": "16/80", "naklon": 0 }, + "3877": { "label": "16/81", "naklon": null }, + "3755": { "label": "16/82", "naklon": 0 }, + "3725": { "label": "16/83", "naklon": null }, + "3716": { "label": "16/84", "naklon": 0 }, + "3696": { "label": "16/85", "naklon": null }, + "3702": { "label": "16/86", "naklon": 0 }, + "3706": { "label": "16/87", "naklon": null }, + "3850": { "label": "16/88", "naklon": 0 }, + "3848": { "label": "16/89", "naklon": null }, + "3737": { "label": "16/90", "naklon": null }, + "3705": { "label": "16/91", "naklon": 0 }, + "3723": { "label": "16/92", "naklon": null }, + "3842": { "label": "16/93", "naklon": 0 }, + "3735": { "label": "16/94", "naklon": null }, + "3719": { "label": "16/95", "naklon": 0 }, + "3697": { "label": "16/96", "naklon": 0 }, + "3711": { "label": "16/97", "naklon": 0 }, + "4107": { "label": "16/98", "naklon": null }, + "4112": { "label": "16/99", "naklon": 5 }, + "4106": { "label": "16/100", "naklon": 5 }, + "4111": { "label": "16/101", "naklon": 5 }, + "4091": { "label": "16/102", "naklon": null }, + "4104": { "label": "16/103", "naklon": 5 }, + "4094": { "label": "16/104", "naklon": null }, + "4089": { "label": "16/105", "naklon": 5 }, + "4095": { "label": "16/106", "naklon": null }, + "4102": { "label": "16/107", "naklon": 5 }, + "4105": { "label": "16/108", "naklon": null }, + "3859": { "label": "16/109", "naklon": null }, + "4090": { "label": "16/110", "naklon": 5 }, + "4110": { "label": "16/111", "naklon": null }, + "4097": { "label": "16/112", "naklon": 5 }, + "4099": { "label": "16/113", "naklon": null }, + "4096": { "label": "16/114", "naklon": null }, + "4101": { "label": "16/115", "naklon": 5 }, + "4109": { "label": "16/116", "naklon": null }, + "4092": { "label": "16/117", "naklon": 5 }, + "3631": { "label": "16/118", "naklon": null }, + "3632": { "label": "16/119", "naklon": 0 }, + "3641": { "label": "16/120", "naklon": null }, + "3638": { "label": "16/121", "naklon": 0 }, + "3637": { "label": "16/122", "naklon": null }, + "4142": { "label": "16/123", "naklon": null }, + "4147": { "label": "16/124", "naklon": 5 }, + "4139": { "label": "16/125", "naklon": 5 }, + "3172": { "label": "20/30A", "naklon": 2 }, + "3164": { "label": "20/30B", "naklon": 2 }, + "3247": { "label": "20/1", "naklon": 10 }, + "3296": { "label": "20/2", "naklon": 10 }, + "3246": { "label": "20/3", "naklon": 10 }, + "3270": { "label": "20/4", "naklon": 10 }, + "3294": { "label": "20/5", "naklon": 10 }, + "3298": { "label": "20/6", "naklon": 10 }, + "3297": { "label": "20/7", "naklon": 10 }, + "3293": { "label": "20/8", "naklon": 10 }, + "3299": { "label": "20/9", "naklon": 10 }, + "3295": { "label": "20/10", "naklon": 10 }, + "3244": { "label": "20/11", "naklon": 10 }, + "3249": { "label": "20/12", "naklon": 10 }, + "3268": { "label": "20/13", "naklon": 10 }, + "3245": { "label": "20/14", "naklon": 10 }, + "3278": { "label": "20/15", "naklon": 10 }, + "3280": { "label": "20/16", "naklon": 10 }, + "3292": { "label": "20/17", "naklon": 10 }, + "3287": { "label": "20/18", "naklon": 10 }, + "3282": { "label": "20/19", "naklon": 10 }, + "3273": { "label": "20/20", "naklon": 0 }, + "3157": { "label": "20/21", "naklon": 0 }, + "3283": { "label": "20/22", "naklon": 0 }, + "3159": { "label": "20/23", "naklon": 0 }, + "3289": { "label": "20/24", "naklon": 0 }, + "3163": { "label": "20/25", "naklon": 0 }, + "3126": { "label": "20/26", "naklon": 0 }, + "3171": { "label": "20/27", "naklon": 0 }, + "3162": { "label": "20/28", "naklon": 0 }, + "3279": { "label": "20/29", "naklon": 10 }, + "3173": { "label": "20/31", "naklon": 0 }, + "3127": { "label": "20/32", "naklon": 0 }, + "3131": { "label": "20/33", "naklon": 0 }, + "3129": { "label": "20/34", "naklon": 0 }, + "3276": { "label": "20/35", "naklon": 2 }, + "3290": { "label": "20/36", "naklon": 2 }, + "3132": { "label": "20/37", "naklon": 0 }, + "3138": { "label": "20/38", "naklon": 0 }, + "3272": { "label": "20/39", "naklon": 0 }, + "3291": { "label": "20/40", "naklon": 0 }, + "3277": { "label": "20/41", "naklon": 10 }, + "3286": { "label": "20/42", "naklon": 10 }, + "3281": { "label": "20/43", "naklon": 10 }, + "3288": { "label": "20/44", "naklon": 10 }, + "3284": { "label": "20/45", "naklon": 10 }, + "3167": { "label": "20/46", "naklon": 10 }, + "3872": { "label": "20/47", "naklon": 0 }, + "3124": { "label": "20/48", "naklon": 0 }, + "3133": { "label": "20/49", "naklon": 0 }, + "3158": { "label": "20/50", "naklon": 0 }, + "3169": { "label": "20/51", "naklon": 0 }, + "3146": { "label": "20/52", "naklon": 0 }, + "3160": { "label": "20/53", "naklon": 0 }, + "3248": { "label": "20/54", "naklon": 0 }, + "3156": { "label": "20/55", "naklon": 0 }, + "3161": { "label": "20/56", "naklon": 0 }, + "3170": { "label": "20/57", "naklon": 0 }, + "3168": { "label": "20/58", "naklon": 0 }, + "3125": { "label": "20/59", "naklon": 0 }, + "3166": { "label": "20/60", "naklon": 0 }, + "3130": { "label": "20/61", "naklon": 0 }, + "3563": { "label": "20/62", "naklon": 0 }, + "3550": { "label": "20/63", "naklon": null }, + "3269": { "label": "20/67", "naklon": 0 }, + "2921": { "label": "21/1", "naklon": 0 }, + "2707": { "label": "21/2", "naklon": 0 }, + "2723": { "label": "21/3", "naklon": 0 }, + "2716": { "label": "21/4", "naklon": 0 }, + "2717": { "label": "21/5", "naklon": 0 }, + "2720": { "label": "21/6", "naklon": 0 }, + "2722": { "label": "21/7", "naklon": 0 }, + "2718": { "label": "21/8", "naklon": 0 }, + "2724": { "label": "21/9", "naklon": 0 }, + "2742": { "label": "21/10", "naklon": 0 }, + "2743": { "label": "21/11", "naklon": 0 }, + "2733": { "label": "21/12", "naklon": 0 }, + "2903": { "label": "21/14", "naklon": 0 }, + "2917": { "label": "21/15", "naklon": 0 }, + "2897": { "label": "21/16", "naklon": 0 }, + "2914": { "label": "21/17", "naklon": 0 }, + "2898": { "label": "21/18", "naklon": 0 }, + "2773": { "label": "21/19", "naklon": 0 }, + "2895": { "label": "21/20", "naklon": 0 }, + "2896": { "label": "21/21", "naklon": 0 }, + "2771": { "label": "21/22", "naklon": 0 }, + "2772": { "label": "21/23", "naklon": 0 }, + "2793": { "label": "21/24", "naklon": 0 }, + "2902": { "label": "21/25", "naklon": 0 }, + "2910": { "label": "21/26", "naklon": 0 }, + "2909": { "label": "21/27", "naklon": 0 }, + "2920": { "label": "21/28", "naklon": 0 }, + "2916": { "label": "21/29", "naklon": 0 }, + "2904": { "label": "21/30", "naklon": 0 }, + "2915": { "label": "21/31", "naklon": 0 }, + "2905": { "label": "21/32", "naklon": 0 }, + "2900": { "label": "21/33", "naklon": 0 }, + "2899": { "label": "21/34", "naklon": 0 }, + "2741": { "label": "21/36", "naklon": 0 }, + "2714": { "label": "21/37", "naklon": 0 }, + "2701": { "label": "21/38", "naklon": 0 }, + "2703": { "label": "21/39", "naklon": 0 }, + "2704": { "label": "21/40", "naklon": 0 }, + "2702": { "label": "21/41", "naklon": 0 }, + "2706": { "label": "21/42", "naklon": 0 }, + "2776": { "label": "21/43", "naklon": 0 }, + "2770": { "label": "21/44", "naklon": 0 }, + "2786": { "label": "21/45", "naklon": 0 }, + "2779": { "label": "21/46", "naklon": 0 }, + "2782": { "label": "21/47", "naklon": 0 }, + "2785": { "label": "21/48", "naklon": 0 }, + "2769": { "label": "21/49", "naklon": 0 }, + "3354": { "label": "21/50", "naklon": 0 }, + "2778": { "label": "21/51", "naklon": 0 }, + "2775": { "label": "21/52", "naklon": 0 }, + "2780": { "label": "21/53", "naklon": 0 }, + "2790": { "label": "21/54", "naklon": 0 }, + "2792": { "label": "21/55", "naklon": 0 }, + "2774": { "label": "21/56", "naklon": 0 }, + "2630": { "label": "22/1", "naklon": 0 }, + "2631": { "label": "22/2", "naklon": 0 }, + "2632": { "label": "22/3", "naklon": 0 }, + "2633": { "label": "22/4", "naklon": 0 }, + "2634": { "label": "22/5", "naklon": 0 }, + "2636": { "label": "22/6", "naklon": 0 }, + "4367": { "label": "22/7", "naklon": 0 }, + "2637": { "label": "22/8", "naklon": 0 }, + "2638": { "label": "22/9", "naklon": 0 }, + "2639": { "label": "22/10", "naklon": 0 }, + "2640": { "label": "22/11", "naklon": 0 }, + "2641": { "label": "22/12", "naklon": 0 }, + "2642": { "label": "22/13", "naklon": 0 }, + "2643": { "label": "22/14", "naklon": 0 }, + "2644": { "label": "22/15", "naklon": 0 }, + "2645": { "label": "22/16", "naklon": 0 }, + "2646": { "label": "22/17", "naklon": 0 }, + "2647": { "label": "22/18", "naklon": 0 }, + "2648": { "label": "22/19", "naklon": 0 }, + "2649": { "label": "22/20", "naklon": 0 }, + "2650": { "label": "22/21", "naklon": 0 }, + "2651": { "label": "22/22", "naklon": 0 }, + "4103": { "label": "22/23", "naklon": 0 }, + "2653": { "label": "22/24", "naklon": 0 }, + "2654": { "label": "22/25", "naklon": 0 }, + "2655": { "label": "22/26", "naklon": 0 }, + "2656": { "label": "22/27", "naklon": 0 }, + "2657": { "label": "22/28", "naklon": 0 }, + "2658": { "label": "22/29", "naklon": 0 }, + "2659": { "label": "22/30", "naklon": 0 }, + "2660": { "label": "22/31", "naklon": 0 }, + "2661": { "label": "22/32", "naklon": 0 }, + "3015": { "label": "22/32/1", "naklon": 0 }, + "2662": { "label": "22/33", "naklon": 0 }, + "2663": { "label": "22/34", "naklon": 0 }, + "2664": { "label": "22/35", "naklon": 0 }, + "2665": { "label": "22/36", "naklon": 0 }, + "2666": { "label": "22/37", "naklon": 0 }, + "2667": { "label": "22/38", "naklon": 0 }, + "2668": { "label": "22/39", "naklon": 0 }, + "2669": { "label": "22/40", "naklon": null }, + "2670": { "label": "22/41", "naklon": null }, + "2671": { "label": "22/42", "naklon": null }, + "3087": { "label": "23/9A", "naklon": 10 }, + "3090": { "label": "23/9B", "naklon": 10 }, + "3075": { "label": "23/1", "naklon": 0 }, + "3089": { "label": "23/2", "naklon": 0 }, + "3088": { "label": "23/3", "naklon": 0 }, + "3228": { "label": "23/4", "naklon": 10 }, + "2751": { "label": "23/5", "naklon": 10 }, + "3243": { "label": "23/6", "naklon": 10 }, + "4349": { "label": "23/7", "naklon": 10 }, + "3102": { "label": "23/8", "naklon": 10 }, + "3099": { "label": "23/10", "naklon": 10 }, + "3103": { "label": "23/11", "naklon": 10 }, + "3093": { "label": "23/12", "naklon": 10 }, + "3098": { "label": "23/13", "naklon": 10 }, + "3092": { "label": "23/14", "naklon": 10 }, + "3233": { "label": "23/15", "naklon": 0 }, + "3095": { "label": "23/16", "naklon": 0 }, + "4074": { "label": "23/17", "naklon": 0 }, + "2729": { "label": "23/18", "naklon": 0 }, + "3234": { "label": "23/19", "naklon": 0 }, + "3094": { "label": "23/20", "naklon": 0 }, + "2817": { "label": "23/21", "naklon": 0 }, + "3226": { "label": "23/22", "naklon": 0 }, + "3225": { "label": "23/23", "naklon": 0 }, + "3237": { "label": "23/24", "naklon": 0 }, + "4250": { "label": "23/25", "naklon": 0 }, + "3059": { "label": "23/26", "naklon": 10 }, + "3238": { "label": "23/27", "naklon": 10 }, + "3242": { "label": "23/28", "naklon": 10 }, + "3236": { "label": "23/29", "naklon": 10 }, + "3112": { "label": "23/30", "naklon": 10 }, + "3224": { "label": "23/31", "naklon": 0 }, + "4298": { "label": "23/32", "naklon": 10 }, + "4150": { "label": "23/33", "naklon": 10 }, + "3091": { "label": "23/34", "naklon": 10 }, + "3771": { "label": "25/1", "naklon": 5 }, + "3777": { "label": "25/2", "naklon": 5 }, + "3749": { "label": "25/3", "naklon": 5 }, + "3769": { "label": "25/4", "naklon": 5 }, + "3765": { "label": "25/5", "naklon": 5 }, + "3785": { "label": "25/6", "naklon": 5 }, + "3761": { "label": "25/7", "naklon": 5 }, + "3758": { "label": "25/8", "naklon": 5 }, + "3766": { "label": "25/9", "naklon": 5 }, + "3779": { "label": "25/10", "naklon": 5 }, + "3899": { "label": "25/11", "naklon": 10 }, + "3922": { "label": "25/12", "naklon": 10 }, + "3912": { "label": "25/13", "naklon": 10 }, + "3933": { "label": "25/14", "naklon": 10 }, + "3921": { "label": "25/15", "naklon": 10 }, + "4300": { "label": "25/16", "naklon": 10 }, + "3927": { "label": "25/17", "naklon": 10 }, + "3212": { "label": "25/18", "naklon": 10 }, + "3208": { "label": "25/19", "naklon": 10 }, + "3207": { "label": "25/20", "naklon": 10 }, + "4294": { "label": "25/21", "naklon": 10 }, + "3209": { "label": "25/22", "naklon": 10 }, + "3745": { "label": "25/23", "naklon": 10 }, + "3762": { "label": "25/24", "naklon": 10 }, + "3215": { "label": "25/25", "naklon": 10 }, + "3210": { "label": "25/26", "naklon": 10 }, + "3211": { "label": "25/27", "naklon": 10 }, + "3206": { "label": "25/28", "naklon": 10 }, + "3918": { "label": "25/29", "naklon": 5 }, + "3928": { "label": "25/30", "naklon": 5 }, + "3917": { "label": "25/31", "naklon": 5 }, + "4029": { "label": "25/32", "naklon": 0 }, + "4038": { "label": "25/33", "naklon": 0 }, + "4022": { "label": "25/34", "naklon": 0 }, + "3937": { "label": "25/35", "naklon": 0 }, + "3190": { "label": "25/36", "naklon": 0 }, + "3835": { "label": "25/37", "naklon": 0 }, + "3201": { "label": "25/38", "naklon": 0 }, + "3193": { "label": "25/39", "naklon": 0 }, + "3191": { "label": "25/40", "naklon": 0 }, + "3203": { "label": "25/41", "naklon": 0 }, + "4301": { "label": "25/42", "naklon": 0 }, + "3223": { "label": "25/43", "naklon": 0 }, + "3202": { "label": "25/44", "naklon": 0 }, + "3205": { "label": "25/45", "naklon": 0 }, + "3194": { "label": "25/46", "naklon": 0 }, + "3198": { "label": "25/47", "naklon": 0 }, + "3204": { "label": "25/48", "naklon": 0 }, + "3200": { "label": "25/49", "naklon": 0 }, + "3216": { "label": "25/50", "naklon": 0 }, + "3932": { "label": "25/51", "naklon": 5 }, + "3923": { "label": "25/52", "naklon": 5 }, + "3913": { "label": "25/53", "naklon": 5 }, + "3900": { "label": "25/54", "naklon": 5 }, + "4189": { "label": "25/55", "naklon": 10 }, + "4191": { "label": "25/56", "naklon": 10 }, + "3790": { "label": "25/57", "naklon": 10 }, + "4190": { "label": "25/58", "naklon": 10 }, + "4302": { "label": "25/59", "naklon": 0 }, + "4351": { "label": "25/60", "naklon": 0 }, + "4075": { "label": "25/61", "naklon": 0 }, + "4071": { "label": "25/62", "naklon": 0 }, + "3784": { "label": "25/63", "naklon": 0 }, + "4065": { "label": "25/64", "naklon": 0 }, + "4297": { "label": "25/65", "naklon": 0 }, + "4295": { "label": "25/66", "naklon": 0 }, + "4299": { "label": "25/67", "naklon": 0 }, + "3772": { "label": "25/68", "naklon": 0 }, + "3941": { "label": "25/69", "naklon": 0 }, + "3782": { "label": "25/70", "naklon": 0 }, + "4068": { "label": "25/71", "naklon": 0 }, + "4073": { "label": "25/72", "naklon": 0 }, + "3901": { "label": "25/73", "naklon": 5 }, + "4296": { "label": "25/74", "naklon": 5 }, + "3910": { "label": "25/75", "naklon": 5 }, + "4293": { "label": "25/76", "naklon": 5 }, + "3919": { "label": "25/77", "naklon": 5 }, + "3924": { "label": "25/78", "naklon": 5 }, + "3909": { "label": "25/79", "naklon": 5 }, + "3896": { "label": "25/80", "naklon": 5 }, + "3911": { "label": "25/81", "naklon": 5 }, + "2819": { "label": "25/82", "naklon": 15 }, + "3776": { "label": "25/83", "naklon": 15 }, + "3752": { "label": "25/84", "naklon": 15 }, + "4353": { "label": "25/85", "naklon": 15 }, + "3791": { "label": "25/86", "naklon": 0 }, + "3770": { "label": "25/87", "naklon": 0 }, + "3760": { "label": "25/88", "naklon": 0 }, + "3115": { "label": "25/89", "naklon": 0 }, + "3738": { "label": "25/90", "naklon": 0 }, + "3748": { "label": "25/91", "naklon": 0 }, + "3753": { "label": "25/92", "naklon": 0 }, + "3775": { "label": "25/93", "naklon": 0 }, + "3778": { "label": "25/94", "naklon": 5 }, + "4078": { "label": "25/95", "naklon": 5 }, + "4088": { "label": "25/96", "naklon": 5 }, + "3856": { "label": "25/97", "naklon": 5 }, + "4084": { "label": "25/98", "naklon": 5 }, + "4069": { "label": "25/99", "naklon": 5 }, + "4188": { "label": "25/100", "naklon": 5 }, + "4064": { "label": "25/101", "naklon": 5 }, + "3792": { "label": "25/102", "naklon": 5 }, + "3780": { "label": "25/103", "naklon": 5 }, + "4034": { "label": "25/104", "naklon": 5 }, + "4072": { "label": "25/105", "naklon": 5 }, + "3884": { "label": "25/106", "naklon": 5 }, + "3793": { "label": "25/107", "naklon": 5 }, + "3863": { "label": "25/108", "naklon": 5 }, + "3855": { "label": "25/109", "naklon": 5 }, + "3846": { "label": "33/1", "naklon": 0 }, + "3943": { "label": "33/2", "naklon": 0 }, + "3903": { "label": "33/3", "naklon": 0 }, + "3982": { "label": "33/4", "naklon": 0 }, + "3879": { "label": "33/5", "naklon": 0 }, + "3887": { "label": "33/6", "naklon": 0 }, + "3920": { "label": "33/7", "naklon": 5 }, + "3942": { "label": "33/8", "naklon": 5 }, + "3829": { "label": "33/9", "naklon": null }, + "3452": { "label": "34/79A", "naklon": 6 }, + "3460": { "label": "34/79B", "naklon": 6 }, + "3443": { "label": "34/90A", "naklon": 6 }, + "3445": { "label": "34/90B", "naklon": 6 }, + "3457": { "label": "34/90C", "naklon": 6 }, + "3461": { "label": "34/97A", "naklon": 6 }, + "3463": { "label": "34/97B", "naklon": 6 }, + "3426": { "label": "34/98A", "naklon": 6 }, + "3444": { "label": "34/98B", "naklon": 6 }, + "3453": { "label": "34/99A", "naklon": 6 }, + "3455": { "label": "34/99B", "naklon": 6 }, + "4009": { "label": "34/1", "naklon": 0 }, + "3602": { "label": "34/2", "naklon": 0 }, + "3441": { "label": "34/3", "naklon": 0 }, + "3464": { "label": "34/4", "naklon": 0 }, + "3883": { "label": "34/5", "naklon": 0 }, + "4098": { "label": "34/6", "naklon": 0 }, + "4003": { "label": "34/7", "naklon": 0 }, + "4004": { "label": "34/8", "naklon": 0 }, + "3888": { "label": "34/9", "naklon": 0 }, + "3997": { "label": "34/10", "naklon": 0 }, + "4006": { "label": "34/11", "naklon": 0 }, + "4000": { "label": "34/12", "naklon": 0 }, + "4011": { "label": "34/13", "naklon": 0 }, + "3999": { "label": "34/14", "naklon": 0 }, + "3981": { "label": "34/15", "naklon": 0 }, + "3988": { "label": "34/16", "naklon": 0 }, + "3986": { "label": "34/17", "naklon": 0 }, + "3998": { "label": "34/18", "naklon": 0 }, + "3983": { "label": "34/19", "naklon": 0 }, + "4005": { "label": "34/20", "naklon": 0 }, + "4001": { "label": "34/21", "naklon": 0 }, + "4008": { "label": "34/22", "naklon": 0 }, + "4002": { "label": "34/23", "naklon": 0 }, + "3996": { "label": "34/24", "naklon": 0 }, + "4007": { "label": "34/25", "naklon": 0 }, + "4113": { "label": "34/26", "naklon": 15 }, + "3595": { "label": "34/27", "naklon": 5 }, + "3599": { "label": "34/28", "naklon": 5 }, + "3601": { "label": "34/29", "naklon": 5 }, + "4205": { "label": "34/30", "naklon": 0 }, + "3987": { "label": "34/31", "naklon": null }, + "4214": { "label": "34/32", "naklon": 0 }, + "4226": { "label": "34/33", "naklon": 0 }, + "4209": { "label": "34/34", "naklon": 0 }, + "4201": { "label": "34/35", "naklon": 0 }, + "3440": { "label": "34/36", "naklon": 0 }, + "3465": { "label": "34/37", "naklon": 0 }, + "3446": { "label": "34/38", "naklon": 0 }, + "4039": { "label": "34/39", "naklon": 5 }, + "4057": { "label": "34/40", "naklon": 5 }, + "3985": { "label": "34/41", "naklon": 0 }, + "3882": { "label": "34/42", "naklon": 0 }, + "4040": { "label": "34/43", "naklon": 5 }, + "3231": { "label": "34/44", "naklon": 0 }, + "3227": { "label": "34/45", "naklon": 0 }, + "3431": { "label": "34/46", "naklon": 0 }, + "4013": { "label": "34/47", "naklon": 0 }, + "4045": { "label": "34/48", "naklon": 0 }, + "3949": { "label": "34/49", "naklon": 0 }, + "3953": { "label": "34/50", "naklon": 0 }, + "3952": { "label": "34/51", "naklon": 0 }, + "3995": { "label": "34/52", "naklon": 0 }, + "3992": { "label": "34/53", "naklon": 0 }, + "4198": { "label": "34/54", "naklon": 0 }, + "3935": { "label": "34/55", "naklon": 0 }, + "4050": { "label": "34/56", "naklon": 0 }, + "4049": { "label": "34/57", "naklon": 0 }, + "4054": { "label": "34/58", "naklon": 0 }, + "3663": { "label": "34/59", "naklon": 6 }, + "3661": { "label": "34/60", "naklon": 6 }, + "3664": { "label": "34/61", "naklon": 6 }, + "3660": { "label": "34/62", "naklon": 6 }, + "3662": { "label": "34/63", "naklon": 6 }, + "3665": { "label": "34/65", "naklon": 6 }, + "3667": { "label": "34/66", "naklon": 6 }, + "3675": { "label": "34/67", "naklon": 6 }, + "3666": { "label": "34/68", "naklon": 6 }, + "3652": { "label": "34/69", "naklon": 6 }, + "3458": { "label": "34/70", "naklon": 6 }, + "4425": { "label": "34/70/1", "naklon": 6 }, + "3459": { "label": "34/71", "naklon": 6 }, + "3435": { "label": "34/72", "naklon": 6 }, + "3448": { "label": "34/73", "naklon": 6 }, + "3451": { "label": "34/74", "naklon": 6 }, + "3442": { "label": "34/75", "naklon": 6 }, + "3449": { "label": "34/76", "naklon": 6 }, + "3450": { "label": "34/77", "naklon": 6 }, + "3433": { "label": "34/78", "naklon": 6 }, + "3432": { "label": "34/80", "naklon": 12 }, + "3470": { "label": "34/81", "naklon": 12 }, + "3438": { "label": "34/82", "naklon": 12 }, + "3439": { "label": "34/83", "naklon": 12 }, + "4028": { "label": "34/84", "naklon": 5 }, + "3596": { "label": "34/85", "naklon": 5 }, + "4021": { "label": "34/86", "naklon": 5 }, + "3437": { "label": "34/87", "naklon": 12 }, + "3428": { "label": "34/88", "naklon": 12 }, + "3430": { "label": "34/89", "naklon": 12 }, + "3454": { "label": "34/91", "naklon": 6 }, + "3492": { "label": "34/92", "naklon": 6 }, + "3462": { "label": "34/93", "naklon": 6 }, + "3427": { "label": "34/94", "naklon": 6 }, + "3434": { "label": "34/95", "naklon": 6 }, + "3456": { "label": "34/96", "naklon": 6 }, + "4307": { "label": "34/98/1", "naklon": 6 }, + "3968": { "label": "35/1", "naklon": 0 }, + "3969": { "label": "35/2", "naklon": 0 }, + "3947": { "label": "35/3", "naklon": 0 }, + "3979": { "label": "35/4", "naklon": 0 }, + "3959": { "label": "35/5", "naklon": 0 }, + "3948": { "label": "35/6", "naklon": 0 }, + "3961": { "label": "35/7", "naklon": 0 }, + "3956": { "label": "35/8", "naklon": 0 }, + "3604": { "label": "35/9", "naklon": 0 }, + "3944": { "label": "35/10", "naklon": 0 }, + "3960": { "label": "35/11", "naklon": 0 }, + "3958": { "label": "35/12", "naklon": 0 }, + "4036": { "label": "35/13", "naklon": 5 }, + "3893": { "label": "35/18", "naklon": 5 }, + "4108": { "label": "35/19", "naklon": 5 }, + "4017": { "label": "35/20", "naklon": 5 }, + "3963": { "label": "35/21", "naklon": 0 }, + "3658": { "label": "35/22", "naklon": 0 }, + "3975": { "label": "35/23", "naklon": 0 }, + "3980": { "label": "35/24", "naklon": 0 }, + "4012": { "label": "35/25", "naklon": 0 }, + "3655": { "label": "35/26", "naklon": 0 }, + "3962": { "label": "35/27", "naklon": 0 }, + "3945": { "label": "35/28", "naklon": 0 }, + "3569": { "label": "35/29", "naklon": 0 }, + "3429": { "label": "35/30", "naklon": 0 }, + "3657": { "label": "35/31", "naklon": 0 }, + "3646": { "label": "35/32", "naklon": 0 }, + "3622": { "label": "35/33", "naklon": 0 }, + "3612": { "label": "35/34", "naklon": 0 }, + "3955": { "label": "35/35", "naklon": 0 }, + "3878": { "label": "35/37", "naklon": 0 }, + "3965": { "label": "35/38", "naklon": 0 }, + "3970": { "label": "35/39", "naklon": 0 }, + "3611": { "label": "35/40", "naklon": 0 }, + "2635": { "label": "35/41", "naklon": 0 }, + "3978": { "label": "35/42", "naklon": 0 }, + "4213": { "label": "35/43", "naklon": 0 }, + "3984": { "label": "35/44", "naklon": 0 }, + "4218": { "label": "35/45", "naklon": 0 }, + "3973": { "label": "35/46", "naklon": 0 }, + "3974": { "label": "35/47", "naklon": 0 }, + "3759": { "label": "35/48", "naklon": 0 }, + "3844": { "label": "35/49", "naklon": 0 }, + "3804": { "label": "35/50", "naklon": 0 }, + "3831": { "label": "35/51", "naklon": 0 }, + "3643": { "label": "35/52", "naklon": 0 }, + "3966": { "label": "35/53", "naklon": 0 }, + "3971": { "label": "35/54", "naklon": 0 }, + "3650": { "label": "35/55", "naklon": 6 }, + "3651": { "label": "35/56", "naklon": 6 }, + "3669": { "label": "35/57", "naklon": 6 }, + "3648": { "label": "35/58", "naklon": 6 }, + "3645": { "label": "35/59", "naklon": 6 }, + "3659": { "label": "35/60", "naklon": 6 }, + "3647": { "label": "35/61", "naklon": 6 }, + "3644": { "label": "35/62", "naklon": 6 }, + "3671": { "label": "35/63", "naklon": 6 }, + "3682": { "label": "35/64", "naklon": 6 }, + "3672": { "label": "35/65", "naklon": 6 }, + "3683": { "label": "35/66", "naklon": 6 }, + "3673": { "label": "35/67", "naklon": 6 }, + "3674": { "label": "35/68", "naklon": 6 }, + "3679": { "label": "35/69", "naklon": 6 }, + "3649": { "label": "35/70", "naklon": 6 }, + "3687": { "label": "35/71", "naklon": 6 }, + "3677": { "label": "35/72", "naklon": 6 }, + "3690": { "label": "35/73", "naklon": 6 }, + "3691": { "label": "35/74", "naklon": 6 }, + "3676": { "label": "35/75", "naklon": 6 }, + "3680": { "label": "35/76", "naklon": 6 }, + "3668": { "label": "35/77", "naklon": 6 }, + "3681": { "label": "35/78", "naklon": 6 }, + "3670": { "label": "35/79", "naklon": 6 }, + "3689": { "label": "35/80", "naklon": 6 }, + "3678": { "label": "35/81", "naklon": 6 }, + "3693": { "label": "35/82", "naklon": 6 }, + "3654": { "label": "35/83", "naklon": null }, + "4086": { "label": "36/1", "naklon": 0 }, + "4085": { "label": "36/2", "naklon": 0 }, + "4083": { "label": "36/3", "naklon": 0 }, + "4087": { "label": "36/4", "naklon": 0 }, + "4077": { "label": "36/5", "naklon": 0 }, + "4082": { "label": "36/6", "naklon": 0 }, + "4186": { "label": "36/7", "naklon": 0 }, + "4206": { "label": "36/8", "naklon": 0 }, + "4080": { "label": "36/9", "naklon": 0 }, + "4081": { "label": "36/10", "naklon": 0 }, + "4210": { "label": "36/11", "naklon": 0 }, + "4079": { "label": "36/12", "naklon": 0 }, + "4076": { "label": "36/13", "naklon": 0 }, + "3852": { "label": "36/14", "naklon": 0 }, + "2813": { "label": "36/15", "naklon": 0 }, + "4219": { "label": "36/16", "naklon": 0 }, + "3104": { "label": "37/1A", "naklon": 15 }, + "3121": { "label": "37/1B", "naklon": 15 }, + "3113": { "label": "37/2", "naklon": 10 }, + "3118": { "label": "37/3", "naklon": 10 }, + "3111": { "label": "37/4", "naklon": 10 }, + "4020": { "label": "37/5", "naklon": 10 }, + "3119": { "label": "37/6", "naklon": 10 }, + "3110": { "label": "37/7", "naklon": 10 }, + "3108": { "label": "37/8", "naklon": 10 }, + "3107": { "label": "37/12", "naklon": 0 }, + "3199": { "label": "37/13", "naklon": 0 }, + "3120": { "label": "37/14", "naklon": 0 }, + "3122": { "label": "37/15", "naklon": 0 }, + "3908": { "label": "37/16", "naklon": 0 }, + "3114": { "label": "37/17", "naklon": 0 }, + "3105": { "label": "37/18", "naklon": 0 }, + "3116": { "label": "37/19", "naklon": 0 }, + "3106": { "label": "37/20", "naklon": 0 }, + "2887": { "label": "37/21", "naklon": 5 }, + "2888": { "label": "37/22", "naklon": 5 }, + "2877": { "label": "37/23", "naklon": 5 }, + "2891": { "label": "37/24", "naklon": 5 }, + "2886": { "label": "37/25", "naklon": 5 }, + "2892": { "label": "37/26", "naklon": 5 }, + "2882": { "label": "37/27", "naklon": 5 }, + "2883": { "label": "37/28", "naklon": 5 }, + "2876": { "label": "37/29", "naklon": 5 }, + "3109": { "label": "37/30", "naklon": 5 }, + "4152": { "label": "37/31", "naklon": 5 }, + "3117": { "label": "37/32", "naklon": 5 }, + "2870": { "label": "37/33", "naklon": 5 }, + "2867": { "label": "37/34", "naklon": 0 }, + "2865": { "label": "37/35", "naklon": 0 }, + "3096": { "label": "37/36", "naklon": 0 }, + "2871": { "label": "37/37", "naklon": 0 }, + "2884": { "label": "37/38", "naklon": 0 }, + "2855": { "label": "37/39", "naklon": 0 }, + "2878": { "label": "37/40", "naklon": 0 }, + "2889": { "label": "37/41", "naklon": 0 }, + "2879": { "label": "37/42", "naklon": 0 }, + "2850": { "label": "37/43", "naklon": 0 }, + "2894": { "label": "37/44", "naklon": 0 }, + "2880": { "label": "37/45", "naklon": 0 }, + "2893": { "label": "37/46", "naklon": 0 }, + "2890": { "label": "37/47", "naklon": 0 }, + "4355": { "label": "37/48", "naklon": 0 }, + "2885": { "label": "37/49", "naklon": 0 }, + "2875": { "label": "37/50", "naklon": 0 }, + "3486": { "label": "38/30A", "naklon": 5 }, + "3714": { "label": "38/30B", "naklon": 0 }, + "3483": { "label": "38/32A", "naklon": 5 }, + "3496": { "label": "38/32B", "naklon": 0 }, + "3487": { "label": "38/35A", "naklon": 5 }, + "3498": { "label": "38/35B", "naklon": 5 }, + "3578": { "label": "38/38A", "naklon": 5 }, + "3508": { "label": "38/38B", "naklon": 5 }, + "3787": { "label": "38/59A", "naklon": 5 }, + "3491": { "label": "38/59B", "naklon": 5 }, + "3568": { "label": "38/1", "naklon": null }, + "3502": { "label": "38/2", "naklon": 0 }, + "3836": { "label": "38/3", "naklon": 0 }, + "3588": { "label": "38/4", "naklon": 0 }, + "3493": { "label": "38/5", "naklon": 0 }, + "3580": { "label": "38/6", "naklon": 0 }, + "3572": { "label": "38/7", "naklon": 0 }, + "3506": { "label": "38/8", "naklon": 0 }, + "3503": { "label": "38/9", "naklon": 0 }, + "3579": { "label": "38/10", "naklon": 0 }, + "3586": { "label": "38/11", "naklon": 0 }, + "3495": { "label": "38/12", "naklon": 5 }, + "3492": { "label": "38/13", "naklon": 5 }, + "3532": { "label": "38/14", "naklon": 5 }, + "3574": { "label": "38/15", "naklon": 5 }, + "4140": { "label": "38/16", "naklon": 5 }, + "3795": { "label": "38/17", "naklon": 5 }, + "3788": { "label": "38/18", "naklon": 5 }, + "3796": { "label": "38/19", "naklon": 5 }, + "3797": { "label": "38/20", "naklon": 5 }, + "3798": { "label": "38/21", "naklon": 5 }, + "3786": { "label": "38/22", "naklon": 5 }, + "4067": { "label": "38/23", "naklon": 5 }, + "3773": { "label": "38/24", "naklon": 5 }, + "3774": { "label": "38/25", "naklon": 5 }, + "3789": { "label": "38/26", "naklon": 5 }, + "3520": { "label": "38/27", "naklon": null }, + "3577": { "label": "38/29", "naklon": 5 }, + "3530": { "label": "38/31", "naklon": null }, + "3488": { "label": "38/33", "naklon": 5 }, + "3505": { "label": "38/34", "naklon": 5 }, + "3497": { "label": "38/36", "naklon": 5 }, + "3490": { "label": "38/37", "naklon": 5 }, + "3585": { "label": "38/39", "naklon": 5 }, + "3582": { "label": "38/40", "naklon": 5 }, + "3507": { "label": "38/41", "naklon": 5 }, + "3484": { "label": "38/42", "naklon": 5 }, + "3501": { "label": "38/43", "naklon": 5 }, + "3581": { "label": "38/44", "naklon": 5 }, + "4192": { "label": "38/45", "naklon": 5 }, + "3576": { "label": "38/46", "naklon": 5 }, + "3489": { "label": "38/47", "naklon": 5 }, + "3573": { "label": "38/48", "naklon": 5 }, + "3504": { "label": "38/49", "naklon": 5 }, + "3794": { "label": "38/50", "naklon": 5 }, + "3485": { "label": "38/51", "naklon": 5 }, + "3482": { "label": "38/52", "naklon": 5 }, + "3575": { "label": "38/53", "naklon": 5 }, + "3499": { "label": "38/54", "naklon": 5 }, + "3494": { "label": "38/55", "naklon": 5 }, + "3583": { "label": "38/56", "naklon": 5 }, + "3570": { "label": "38/57", "naklon": 5 }, + "3500": { "label": "38/58", "naklon": 0 }, + "3510": { "label": "38/63", "naklon": null }, + "3512": { "label": "38/64", "naklon": null }, + "3535": { "label": "38/67", "naklon": null }, + "3531": { "label": "38/68", "naklon": null }, + "3537": { "label": "38/69", "naklon": null }, + "3522": { "label": "39/1", "naklon": 10 }, + "4018": { "label": "39/2", "naklon": 10 }, + "4019": { "label": "39/3", "naklon": 10 }, + "4154": { "label": "39/4", "naklon": 5 }, + "3907": { "label": "39/5", "naklon": 5 }, + "4148": { "label": "39/6", "naklon": 0 }, + "4153": { "label": "39/7", "naklon": 0 }, + "3938": { "label": "39/8", "naklon": 0 }, + "3802": { "label": "39/9", "naklon": 0 }, + "4015": { "label": "39/10", "naklon": 0 }, + "3929": { "label": "39/11", "naklon": 0 }, + "3946": { "label": "39/12", "naklon": 0 }, + "4014": { "label": "39/13", "naklon": 0 }, + "4155": { "label": "39/14", "naklon": 0 }, + "4149": { "label": "39/15", "naklon": 0 }, + "3642": { "label": "39/16", "naklon": 0 }, + "3636": { "label": "39/17", "naklon": 5 }, + "3991": { "label": "39/18", "naklon": 0 }, + "3994": { "label": "39/19", "naklon": 0 }, + "3990": { "label": "39/20", "naklon": 0 }, + "3967": { "label": "39/21", "naklon": 0 }, + "3977": { "label": "39/22", "naklon": 0 }, + "3757": { "label": "39/23", "naklon": 15 }, + "3633": { "label": "39/24", "naklon": 15 }, + "3744": { "label": "39/25", "naklon": 15 }, + "4023": { "label": "39/26", "naklon": 5 }, + "3720": { "label": "39/27", "naklon": 5 }, + "3734": { "label": "39/28", "naklon": 5 }, + "3741": { "label": "39/29", "naklon": 5 }, + "3721": { "label": "39/30", "naklon": 5 }, + "3845": { "label": "39/31", "naklon": 0 }, + "3840": { "label": "39/32", "naklon": 0 }, + "3837": { "label": "39/33", "naklon": null }, + "3839": { "label": "39/34", "naklon": 0 }, + "3542": { "label": "41/1", "naklon": null }, + "3566": { "label": "41/2", "naklon": null }, + "3548": { "label": "41/3", "naklon": null }, + "3515": { "label": "41/4", "naklon": null }, + "3559": { "label": "41/5", "naklon": null }, + "3509": { "label": "41/6", "naklon": null }, + "3524": { "label": "41/7", "naklon": null }, + "3518": { "label": "41/8", "naklon": null }, + "3182": { "label": "41/9", "naklon": null }, + "3187": { "label": "41/10", "naklon": null }, + "3195": { "label": "41/11", "naklon": 0 }, + "3857": { "label": "41/12", "naklon": 0 }, + "3183": { "label": "41/13", "naklon": 0 }, + "3177": { "label": "41/14", "naklon": 0 }, + "3189": { "label": "41/15", "naklon": 0 }, + "3186": { "label": "41/16", "naklon": 0 }, + "3178": { "label": "42/1", "naklon": 0 }, + "3219": { "label": "42/2", "naklon": 0 }, + "3475": { "label": "42/3", "naklon": 0 }, + "3175": { "label": "42/4", "naklon": 0 }, + "3222": { "label": "42/5", "naklon": 0 }, + "3221": { "label": "42/6", "naklon": 0 }, + "3181": { "label": "42/7", "naklon": 0 }, + "3180": { "label": "42/8", "naklon": 0 }, + "3218": { "label": "42/9", "naklon": 0 }, + "3176": { "label": "42/10", "naklon": 0 }, + "3174": { "label": "42/11", "naklon": 0 }, + "3220": { "label": "42/12", "naklon": 0 }, + "3533": { "label": "42/13", "naklon": null }, + "3543": { "label": "42/14", "naklon": null }, + "3554": { "label": "42/15", "naklon": null }, + "3549": { "label": "42/16", "naklon": null }, + "2857": { "label": "43/1", "naklon": 5 }, + "2752": { "label": "43/2", "naklon": 5 }, + "2753": { "label": "43/3", "naklon": 5 }, + "3024": { "label": "43/4", "naklon": 5 }, + "2754": { "label": "43/5", "naklon": 5 }, + "4423": { "label": "43/6", "naklon": 5 }, + "4368": { "label": "43/7", "naklon": 5 }, + "2978": { "label": "43/8", "naklon": 5 }, + "2868": { "label": "43/9", "naklon": 5 }, + "4377": { "label": "43/10", "naklon": 5 }, + "2757": { "label": "43/11", "naklon": 5 }, + "2970": { "label": "43/12", "naklon": 5 }, + "2758": { "label": "43/13", "naklon": 5 }, + "4378": { "label": "43/14", "naklon": 5 }, + "2759": { "label": "43/15", "naklon": 5 }, + "4342": { "label": "43/16", "naklon": 5 }, + "3026": { "label": "43/17", "naklon": null }, + "2986": { "label": "43/18", "naklon": null }, + "4343": { "label": "43/19", "naklon": null }, + "2760": { "label": "43/20", "naklon": null }, + "4379": { "label": "43/21", "naklon": null }, + "2971": { "label": "43/22", "naklon": null }, + "2761": { "label": "43/23", "naklon": null }, + "2762": { "label": "43/24", "naklon": null }, + "4339": { "label": "43/25", "naklon": null }, + "4380": { "label": "43/26", "naklon": null }, + "2975": { "label": "43/27", "naklon": null }, + "3003": { "label": "43/28", "naklon": null }, + "4338": { "label": "43/29", "naklon": null }, + "3002": { "label": "43/30", "naklon": null }, + "4345": { "label": "43/31", "naklon": null }, + "2979": { "label": "43/32", "naklon": null }, + "2989": { "label": "43/33", "naklon": null }, + "2996": { "label": "43/34", "naklon": null }, + "2972": { "label": "43/35", "naklon": null }, + "2988": { "label": "43/36", "naklon": null }, + "4344": { "label": "43/37", "naklon": null }, + "3022": { "label": "43/38", "naklon": null }, + "4341": { "label": "43/39", "naklon": null }, + "2983": { "label": "43/40", "naklon": null }, + "2995": { "label": "43/41", "naklon": null }, + "2763": { "label": "43/42", "naklon": null }, + "2764": { "label": "43/43", "naklon": null }, + "2765": { "label": "43/44", "naklon": null }, + "2766": { "label": "43/45", "naklon": null }, + "2767": { "label": "43/46", "naklon": null }, + "2768": { "label": "43/47", "naklon": null }, + "3018": { "label": "43/48", "naklon": null }, + "2982": { "label": "43/49", "naklon": null }, + "3019": { "label": "43/50", "naklon": 0 }, + "3013": { "label": "43/51", "naklon": null }, + "3007": { "label": "43/52", "naklon": null }, + "2980": { "label": "43/53", "naklon": null }, + "3011": { "label": "43/54", "naklon": null }, + "2672": { "label": "43/55", "naklon": null }, + "2673": { "label": "43/56", "naklon": null }, + "2674": { "label": "43/57", "naklon": null }, + "2675": { "label": "43/58", "naklon": null }, + "2676": { "label": "43/59", "naklon": null }, + "2677": { "label": "43/60", "naklon": null }, + "2678": { "label": "43/61", "naklon": null }, + "2679": { "label": "43/62", "naklon": null }, + "2680": { "label": "43/63", "naklon": null }, + "2840": { "label": "43/64", "naklon": null }, + "2682": { "label": "43/65", "naklon": null }, + "2683": { "label": "43/66", "naklon": null }, + "2684": { "label": "43/67", "naklon": 0 }, + "2685": { "label": "43/68", "naklon": null }, + "2686": { "label": "43/69", "naklon": null }, + "2687": { "label": "43/70", "naklon": null }, + "2688": { "label": "43/71", "naklon": null }, + "2689": { "label": "43/72", "naklon": null }, + "2690": { "label": "43/73", "naklon": null }, + "2691": { "label": "43/74", "naklon": null }, + "2692": { "label": "43/75", "naklon": null }, + "2693": { "label": "43/76", "naklon": 0 }, + "2694": { "label": "43/77", "naklon": null }, + "2695": { "label": "43/78", "naklon": null }, + "2696": { "label": "43/79", "naklon": 0 }, + "2697": { "label": "43/80", "naklon": null }, + "2698": { "label": "43/81", "naklon": 0 }, + "2699": { "label": "43/82", "naklon": null }, + "2700": { "label": "43/83", "naklon": 0 }, + "2744": { "label": "43/84", "naklon": null }, + "2745": { "label": "43/85", "naklon": 0 }, + "2746": { "label": "43/86", "naklon": null }, + "2747": { "label": "43/87", "naklon": 0 }, + "2748": { "label": "43/88", "naklon": null }, + "2749": { "label": "43/89", "naklon": 0 }, + "2841": { "label": "43/90", "naklon": null }, + "4237": { "label": "45/1", "naklon": 5 }, + "4226": { "label": "45/2", "naklon": 5 }, + "4242": { "label": "45/3", "naklon": 5 }, + "4179": { "label": "45/4", "naklon": 5 }, + "4247": { "label": "45/5", "naklon": 5 }, + "4245": { "label": "45/6", "naklon": 5 }, + "3872": { "label": "45/7", "naklon": 5 }, + "4175": { "label": "45/8", "naklon": 5 }, + "4236": { "label": "45/9", "naklon": 5 }, + "4170": { "label": "45/10", "naklon": 5 }, + "4238": { "label": "45/11", "naklon": 5 }, + "4246": { "label": "45/12", "naklon": 5 }, + "4166": { "label": "45/13", "naklon": 5 }, + "4227": { "label": "45/14", "naklon": 5 }, + "4171": { "label": "45/15", "naklon": 5 }, + "4180": { "label": "45/16", "naklon": 5 }, + "4244": { "label": "45/17", "naklon": 5 }, + "4199": { "label": "45/18", "naklon": 5 }, + "4239": { "label": "45/19", "naklon": 5 }, + "4207": { "label": "45/20", "naklon": 5 }, + "4223": { "label": "45/21", "naklon": 5 }, + "4230": { "label": "45/22", "naklon": 5 }, + "4233": { "label": "45/23", "naklon": 5 }, + "4222": { "label": "45/24", "naklon": 5 }, + "4217": { "label": "45/25", "naklon": 5 }, + "4243": { "label": "45/26", "naklon": 5 }, + "4200": { "label": "45/27", "naklon": 5 }, + "4228": { "label": "45/28", "naklon": 5 }, + "4211": { "label": "45/29", "naklon": 5 }, + "4234": { "label": "45/30", "naklon": 5 }, + "4235": { "label": "45/31", "naklon": 5 }, + "4203": { "label": "45/32", "naklon": 5 }, + "4240": { "label": "45/33", "naklon": 5 }, + "4224": { "label": "45/34", "naklon": 5 }, + "4232": { "label": "45/35", "naklon": 5 }, + "4231": { "label": "45/36", "naklon": 5 }, + "4161": { "label": "45/37", "naklon": 5 }, + "4225": { "label": "45/38", "naklon": 5 }, + "4241": { "label": "45/39", "naklon": 5 }, + "4229": { "label": "45/40", "naklon": 5 }, + "4221": { "label": "45/41", "naklon": 5 }, + "4212": { "label": "45/42", "naklon": 5 }, + "4216": { "label": "45/43", "naklon": 5 }, + "3864": { "label": "45/44", "naklon": null }, + "3806": { "label": "46/1", "naklon": 5 }, + "3813": { "label": "46/2", "naklon": 5 }, + "3815": { "label": "46/3", "naklon": 5 }, + "3807": { "label": "46/4", "naklon": 5 }, + "3895": { "label": "46/5", "naklon": 5 }, + "3809": { "label": "46/6", "naklon": 5 }, + "3820": { "label": "46/7", "naklon": 5 }, + "3805": { "label": "46/8", "naklon": 5 }, + "3894": { "label": "46/9", "naklon": 0 }, + "4055": { "label": "46/10", "naklon": 0 }, + "3812": { "label": "46/11", "naklon": 5 }, + "3822": { "label": "46/12", "naklon": 5 }, + "3821": { "label": "46/13", "naklon": 5 }, + "3808": { "label": "46/14", "naklon": 5 }, + "3799": { "label": "46/15", "naklon": 5 }, + "3816": { "label": "46/16", "naklon": 5 }, + "3751": { "label": "46/17", "naklon": 5 }, + "3814": { "label": "46/18", "naklon": 5 }, + "4044": { "label": "46/19", "naklon": 0 }, + "3931": { "label": "46/20", "naklon": 0 }, + "3902": { "label": "46/21", "naklon": 5 }, + "3916": { "label": "46/22", "naklon": 5 }, + "3892": { "label": "46/23", "naklon": 5 }, + "3914": { "label": "46/24", "naklon": 5 }, + "3898": { "label": "46/25", "naklon": 5 }, + "3897": { "label": "46/26", "naklon": 5 }, + "3885": { "label": "46/27", "naklon": 5 }, + "3906": { "label": "46/28", "naklon": 5 }, + "3930": { "label": "46/29", "naklon": 0 }, + "3936": { "label": "46/30", "naklon": 0 }, + "3860": { "label": "46/31", "naklon": 5 }, + "3841": { "label": "46/32", "naklon": 5 }, + "3873": { "label": "46/33", "naklon": 5 }, + "3854": { "label": "46/34", "naklon": 5 }, + "3939": { "label": "46/35", "naklon": 5 }, + "3858": { "label": "46/36", "naklon": 5 }, + "3940": { "label": "46/37", "naklon": 5 }, + "4035": { "label": "46/38", "naklon": 5 }, + "3373": { "label": "47/1", "naklon": 0 }, + "3374": { "label": "47/2", "naklon": 0 }, + "3384": { "label": "47/3", "naklon": 0 }, + "3385": { "label": "47/4", "naklon": 0 }, + "4051": { "label": "48/1", "naklon": 5 }, + "4041": { "label": "48/2", "naklon": 5 }, + "4056": { "label": "48/3", "naklon": 5 }, + "3875": { "label": "48/4", "naklon": 5 }, + "4061": { "label": "48/5", "naklon": 5 }, + "4047": { "label": "48/6", "naklon": 5 }, + "4060": { "label": "48/7", "naklon": 5 }, + "4059": { "label": "48/8", "naklon": 5 }, + "4058": { "label": "48/9", "naklon": 5 }, + "3635": { "label": "48/10", "naklon": 5 }, + "3640": { "label": "48/11", "naklon": 5 }, + "3747": { "label": "48/12", "naklon": 5 }, + "3629": { "label": "48/13", "naklon": 5 }, + "4048": { "label": "48/14", "naklon": 5 }, + "4063": { "label": "48/15", "naklon": 5 }, + "4062": { "label": "48/16", "naklon": 5 }, + "4043": { "label": "48/17", "naklon": 5 }, + "4052": { "label": "48/18", "naklon": 5 }, + "4042": { "label": "48/19", "naklon": 5 }, + "4053": { "label": "48/20", "naklon": 5 }, + "4167": { "label": "50/15A", "naklon": null }, + "4159": { "label": "50/15B", "naklon": null }, + "4183": { "label": "50/1", "naklon": 0 }, + "4157": { "label": "50/2", "naklon": 0 }, + "4160": { "label": "50/3", "naklon": 0 }, + "4173": { "label": "50/4", "naklon": 0 }, + "4177": { "label": "50/5", "naklon": 0 }, + "4174": { "label": "50/6", "naklon": 0 }, + "4178": { "label": "50/7", "naklon": 0 }, + "4195": { "label": "50/8", "naklon": 0 }, + "4169": { "label": "50/9", "naklon": 0 }, + "4162": { "label": "50/10", "naklon": 0 }, + "4158": { "label": "50/11", "naklon": 0 }, + "4182": { "label": "50/12", "naklon": 0 }, + "4194": { "label": "50/13", "naklon": 0 }, + "4184": { "label": "50/14", "naklon": 0 }, + "4197": { "label": "50/16", "naklon": null }, + "4164": { "label": "50/17", "naklon": null }, + "3306": { "label": "50/18", "naklon": null }, + "4168": { "label": "50/19", "naklon": null }, + "4193": { "label": "50/20", "naklon": null }, + "4187": { "label": "50/21", "naklon": null }, + "4163": { "label": "50/22", "naklon": null }, + "4165": { "label": "50/23", "naklon": null }, + "4185": { "label": "50/24", "naklon": null }, + "3904": { "label": "50/25", "naklon": null }, + "2619": { "label": "53/1", "naklon": 0 }, + "2623": { "label": "53/2", "naklon": 0 }, + "2617": { "label": "53/3", "naklon": 0 }, + "2622": { "label": "53/4", "naklon": 0 }, + "2618": { "label": "53/5", "naklon": 0 }, + "2626": { "label": "53/6", "naklon": 0 }, + "2869": { "label": "53/7", "naklon": 0 }, + "2613": { "label": "53/8", "naklon": 0 }, + "2608": { "label": "53/9", "naklon": 0 }, + "2611": { "label": "53/10", "naklon": 0 }, + "2598": { "label": "53/11", "naklon": 0 }, + "3528": { "label": "53/12", "naklon": 0 }, + "3545": { "label": "53/13", "naklon": 0 }, + "2620": { "label": "53/14", "naklon": 0 }, + "2612": { "label": "53/15", "naklon": 0 }, + "2615": { "label": "53/16", "naklon": 0 }, + "3722": { "label": "53/17", "naklon": 0 }, + "2624": { "label": "53/18", "naklon": 0 }, + "2609": { "label": "53/19", "naklon": 0 }, + "2625": { "label": "53/20", "naklon": 0 }, + "2602": { "label": "53/21", "naklon": 0 }, + "2610": { "label": "53/22", "naklon": 0 }, + "2599": { "label": "53/23", "naklon": 0 }, + "2605": { "label": "53/24", "naklon": 0 }, + "2593": { "label": "53/25", "naklon": 0 }, + "3074": { "label": "53/26", "naklon": 0 }, + "2740": { "label": "53/27", "naklon": 0 }, + "2614": { "label": "53/28", "naklon": 0 }, + "2601": { "label": "53/29", "naklon": 0 }, + "4196": { "label": "53/30", "naklon": 0 }, + "2607": { "label": "53/31", "naklon": 0 }, + "2582": { "label": "53/32", "naklon": 0 }, + "2594": { "label": "53/33", "naklon": 0 }, + "2589": { "label": "53/34", "naklon": 0 }, + "2596": { "label": "53/35", "naklon": 0 }, + "2603": { "label": "53/36", "naklon": 0 }, + "2597": { "label": "53/37", "naklon": 0 }, + "2590": { "label": "53/38", "naklon": 0 }, + "2581": { "label": "53/39", "naklon": 0 }, + "2583": { "label": "53/40", "naklon": 0 }, + "2580": { "label": "53/41", "naklon": 0 }, + "2579": { "label": "53/42", "naklon": 0 }, + "2797": { "label": "53/43", "naklon": 0 }, + "2577": { "label": "53/44", "naklon": 0 }, + "2586": { "label": "53/45", "naklon": 0 }, + "2588": { "label": "53/46", "naklon": 0 }, + "2591": { "label": "53/47", "naklon": 0 }, + "2592": { "label": "53/48", "naklon": 0 }, + "2573": { "label": "53/49", "naklon": 0 }, + "2595": { "label": "53/50", "naklon": 0 }, + "2587": { "label": "53/51", "naklon": 0 }, + "2578": { "label": "53/52", "naklon": 0 }, + "2574": { "label": "53/53", "naklon": 0 }, + "2571": { "label": "53/54", "naklon": 0 }, + "2570": { "label": "53/55", "naklon": 0 }, + "2576": { "label": "53/56", "naklon": 0 }, + "2881": { "label": "53/57", "naklon": 0 }, + "2575": { "label": "53/58", "naklon": 0 }, + "2572": { "label": "53/59", "naklon": 0 }, + "2569": { "label": "53/60", "naklon": 0 }, + "4324": { "label": "55/1", "naklon": 0 }, + "4319": { "label": "55/2", "naklon": 0 }, + "4327": { "label": "55/3", "naklon": 0 }, + "4333": { "label": "55/4", "naklon": 0 }, + "4332": { "label": "55/5", "naklon": 0 }, + "4320": { "label": "55/6", "naklon": 0 }, + "4317": { "label": "55/7", "naklon": 0 }, + "4318": { "label": "55/8", "naklon": 0 }, + "4328": { "label": "55/9", "naklon": 0 }, + "4323": { "label": "55/10", "naklon": 0 }, + "4325": { "label": "55/11", "naklon": 0 }, + "4326": { "label": "55/12", "naklon": 0 }, + "4316": { "label": "55/13", "naklon": 0 }, + "4322": { "label": "55/14", "naklon": 0 }, + "4331": { "label": "55/15", "naklon": 0 }, + "4321": { "label": "55/16", "naklon": 0 }, + "4315": { "label": "55/17", "naklon": 0 }, + "4329": { "label": "55/18", "naklon": 0 }, + "4334": { "label": "55/19", "naklon": 0 }, + "4330": { "label": "55/20", "naklon": 0 } +}; + + +let svetlaSorted = [{ "label": "1/3A", "node": 3993, "naklon": 0 }, +{ "label": "1/3B", "node": 3989, "naklon": 15 }, +{ "label": "1/1", "node": 3976, "naklon": 0 }, +{ "label": "1/2", "node": 4181, "naklon": 0 }, +{ "label": "1/4", "node": 4376, "naklon": 15 }, +{ "label": "1/5", "node": 3868, "naklon": 15 }, +{ "label": "1/6", "node": 3728, "naklon": 15 }, +{ "label": "1/7", "node": 3730, "naklon": 0 }, +{ "label": "1/8", "node": 4374, "naklon": 0 }, +{ "label": "1/9", "node": 3718, "naklon": 15 }, +{ "label": "1/10", "node": 4375, "naklon": 15 }, +{ "label": "1/11", "node": 4172, "naklon": 15 }, +{ "label": "1/12", "node": 4176, "naklon": 15 }, +{ "label": "2/1", "node": 3800, "naklon": 5 }, +{ "label": "2/2", "node": 3823, "naklon": 5 }, +{ "label": "2/3", "node": 3905, "naklon": 5 }, +{ "label": "2/4", "node": 3803, "naklon": 5 }, +{ "label": "2/5", "node": 3817, "naklon": 5 }, +{ "label": "2/6", "node": 3818, "naklon": 5 }, +{ "label": "2/7", "node": 3811, "naklon": 5 }, +{ "label": "2/8", "node": 3915, "naklon": 5 }, +{ "label": "2/9", "node": 3843, "naklon": 10 }, +{ "label": "2/10", "node": 3827, "naklon": 10 }, +{ "label": "2/11", "node": 4220, "naklon": 10 }, +{ "label": "2/12", "node": 3826, "naklon": 10 }, +{ "label": "2/13", "node": 3834, "naklon": 10 }, +{ "label": "2/14", "node": 3838, "naklon": 10 }, +{ "label": "2/15", "node": 2823, "naklon": 10 }, +{ "label": "2/16", "node": 3750, "naklon": 10 }, +{ "label": "2/17", "node": 3378, "naklon": 0 }, +{ "label": "2/18", "node": 3376, "naklon": 0 }, +{ "label": "2/19", "node": 3379, "naklon": 0 }, +{ "label": "2/20", "node": 3285, "naklon": 0 }, +{ "label": "2/21", "node": 3382, "naklon": 0 }, +{ "label": "2/22", "node": 3383, "naklon": 0 }, +{ "label": "2/24", "node": 3375, "naklon": 0 }, +{ "label": "2/25", "node": 3381, "naklon": 0 }, +{ "label": "2/26", "node": 3380, "naklon": 0 }, +{ "label": "2/27", "node": 3828, "naklon": 10 }, +{ "label": "2/28", "node": 3377, "naklon": 0 }, +{ "label": "7/1", "node": 3591, "naklon": 0 }, +{ "label": "7/2", "node": 3587, "naklon": 0 }, +{ "label": "7/3", "node": 3468, "naklon": 0 }, +{ "label": "7/4", "node": 3466, "naklon": 0 }, +{ "label": "7/5", "node": 3474, "naklon": 0 }, +{ "label": "7/6", "node": 3481, "naklon": 0 }, +{ "label": "7/7", "node": 3589, "naklon": 0 }, +{ "label": "7/8", "node": 3472, "naklon": 0 }, +{ "label": "7/9", "node": 3473, "naklon": 0 }, +{ "label": "7/10", "node": 3584, "naklon": 0 }, +{ "label": "7/11", "node": 3571, "naklon": 0 }, +{ "label": "7/12", "node": 3476, "naklon": 0 }, +{ "label": "7/13", "node": 3590, "naklon": 0 }, +{ "label": "7/14", "node": 3478, "naklon": 0 }, +{ "label": "7/15", "node": 3471, "naklon": 0 }, +{ "label": "7/16", "node": 3467, "naklon": 0 }, +{ "label": "7/17", "node": 3479, "naklon": 0 }, +{ "label": "7/18", "node": 3480, "naklon": 0 }, +{ "label": "7/19", "node": 3477, "naklon": 0 }, +{ "label": "12/1", "node": 3362, "naklon": 0 }, +{ "label": "12/2", "node": 3355, "naklon": 0 }, +{ "label": "12/3", "node": 3356, "naklon": 0 }, +{ "label": "12/4", "node": 3349, "naklon": 0 }, +{ "label": "12/5", "node": 3357, "naklon": 0 }, +{ "label": "12/6", "node": 3350, "naklon": 0 }, +{ "label": "12/7", "node": 3353, "naklon": 0 }, +{ "label": "12/8", "node": 3539, "naklon": 0 }, +{ "label": "12/9", "node": 3050, "naklon": 0 }, +{ "label": "12/10", "node": 3361, "naklon": 0 }, +{ "label": "12/11", "node": 3360, "naklon": 0 }, +{ "label": "12/12", "node": 3358, "naklon": 0 }, +{ "label": "12/13", "node": 3541, "naklon": 0 }, +{ "label": "12/14", "node": 3551, "naklon": 0 }, +{ "label": "12/15", "node": 3514, "naklon": 0 }, +{ "label": "12/16", "node": 3547, "naklon": 0 }, +{ "label": "12/17", "node": 3562, "naklon": 0 }, +{ "label": "12/18", "node": 3525, "naklon": 0 }, +{ "label": "12/19", "node": 3558, "naklon": 0 }, +{ "label": "12/20", "node": 3511, "naklon": 0 }, +{ "label": "12/21", "node": 3058, "naklon": 0 }, +{ "label": "12/22", "node": 3062, "naklon": 0 }, +{ "label": "12/23", "node": 3070, "naklon": 0 }, +{ "label": "12/24", "node": 3447, "naklon": 0 }, +{ "label": "12/25", "node": 3056, "naklon": 0 }, +{ "label": "12/26", "node": 3057, "naklon": 0 }, +{ "label": "12/27", "node": 3071, "naklon": 0 }, +{ "label": "12/28", "node": 3061, "naklon": 0 }, +{ "label": "12/29", "node": 3069, "naklon": 0 }, +{ "label": "12/30", "node": 3077, "naklon": 0 }, +{ "label": "12/31", "node": 3080, "naklon": 0 }, +{ "label": "12/32", "node": 3081, "naklon": 0 }, +{ "label": "12/33", "node": 3078, "naklon": 0 }, +{ "label": "12/34", "node": 4037, "naklon": 0 }, +{ "label": "12/35", "node": 3067, "naklon": 0 }, +{ "label": "12/36", "node": 3051, "naklon": 0 }, +{ "label": "12/37", "node": 2924, "naklon": 0 }, +{ "label": "12/38", "node": 3060, "naklon": 0 }, +{ "label": "12/39", "node": 3073, "naklon": 0 }, +{ "label": "12/40", "node": 3469, "naklon": 0 }, +{ "label": "12/41", "node": 2923, "naklon": 0 }, +{ "label": "12/42", "node": 2925, "naklon": 0 }, +{ "label": "12/43", "node": 3359, "naklon": 0 }, +{ "label": "12/44", "node": 3055, "naklon": 0 }, +{ "label": "12/45", "node": 2922, "naklon": 0 }, +{ "label": "12/46", "node": 3084, "naklon": 0 }, +{ "label": "12/47", "node": 3064, "naklon": 0 }, +{ "label": "12/48", "node": 3066, "naklon": 0 }, +{ "label": "12/49", "node": 3072, "naklon": 0 }, +{ "label": "13/13A", "node": 3415, "naklon": 0 }, +{ "label": "13/13B", "node": 3409, "naklon": 0 }, +{ "label": "13/13C", "node": 3399, "naklon": 0 }, +{ "label": "13/29A", "node": 3410, "naklon": 0 }, +{ "label": "13/29B", "node": 3407, "naklon": 0 }, +{ "label": "13/34A", "node": 3405, "naklon": 0 }, +{ "label": "13/34B", "node": 3404, "naklon": 0 }, +{ "label": "13/45A", "node": 3392, "naklon": 0 }, +{ "label": "13/45B", "node": 3386, "naklon": 0 }, +{ "label": "13/60A", "node": 3303, "naklon": 3 }, +{ "label": "13/60B", "node": 3302, "naklon": 3 }, +{ "label": "13/70A", "node": 3319, "naklon": 6 }, +{ "label": "13/70B", "node": 3317, "naklon": 6 }, +{ "label": "13/70C", "node": 3326, "naklon": 6 }, +{ "label": "13/73A", "node": 3351, "naklon": 6 }, +{ "label": "13/73B", "node": 3313, "naklon": 6 }, +{ "label": "13/83A", "node": 3316, "naklon": 0 }, +{ "label": "13/83B", "node": 3320, "naklon": 0 }, +{ "label": "13/95A", "node": 3336, "naklon": 0 }, +{ "label": "13/95B", "node": 3323, "naklon": 0 }, +{ "label": "13/98A", "node": 3339, "naklon": 0 }, +{ "label": "13/98B", "node": 3333, "naklon": 0 }, +{ "label": "13/1", "node": 3425, "naklon": 0 }, +{ "label": "13/2", "node": 3419, "naklon": 0 }, +{ "label": "13/3", "node": 3416, "naklon": 0 }, +{ "label": "13/4", "node": 3332, "naklon": 0 }, +{ "label": "13/5", "node": 3422, "naklon": 0 }, +{ "label": "13/6", "node": 3417, "naklon": 0 }, +{ "label": "13/7", "node": 3418, "naklon": 0 }, +{ "label": "13/8", "node": 3424, "naklon": 0 }, +{ "label": "13/9", "node": 3334, "naklon": 0 }, +{ "label": "13/10", "node": 4363, "naklon": 0 }, +{ "label": "13/11", "node": 3423, "naklon": 0 }, +{ "label": "13/12", "node": 3406, "naklon": 0 }, +{ "label": "13/14", "node": 3411, "naklon": 0 }, +{ "label": "13/15", "node": 3412, "naklon": 0 }, +{ "label": "13/16", "node": 3413, "naklon": 0 }, +{ "label": "13/17", "node": 3414, "naklon": 0 }, +{ "label": "13/18", "node": 3391, "naklon": 0 }, +{ "label": "13/19", "node": 3370, "naklon": 0 }, +{ "label": "13/20", "node": 3369, "naklon": 0 }, +{ "label": "13/21", "node": 3408, "naklon": 0 }, +{ "label": "13/22", "node": 3393, "naklon": 0 }, +{ "label": "13/23", "node": 3128, "naklon": 0 }, +{ "label": "13/24", "node": 3197, "naklon": 0 }, +{ "label": "13/25", "node": 4364, "naklon": 0 }, +{ "label": "13/26", "node": 3155, "naklon": 0 }, +{ "label": "13/27", "node": 3196, "naklon": 0 }, +{ "label": "13/28", "node": 3144, "naklon": 0 }, +{ "label": "13/30", "node": 3150, "naklon": 0 }, +{ "label": "13/31", "node": 3390, "naklon": 0 }, +{ "label": "13/32", "node": 3401, "naklon": 0 }, +{ "label": "13/33", "node": 3275, "naklon": 0 }, +{ "label": "13/35", "node": 3371, "naklon": 0 }, +{ "label": "13/36", "node": 3389, "naklon": 0 }, +{ "label": "13/37", "node": 3388, "naklon": 0 }, +{ "label": "13/38", "node": 3365, "naklon": 0 }, +{ "label": "13/39", "node": 3363, "naklon": 0 }, +{ "label": "13/40", "node": 3397, "naklon": 0 }, +{ "label": "13/40/1", "node": 3567, "naklon": 0 }, +{ "label": "13/41", "node": 3387, "naklon": 0 }, +{ "label": "13/42", "node": 3403, "naklon": 0 }, +{ "label": "13/43", "node": 3147, "naklon": 0 }, +{ "label": "13/44", "node": 3141, "naklon": 0 }, +{ "label": "13/46", "node": 3364, "naklon": 0 }, +{ "label": "13/47", "node": 3367, "naklon": 0 }, +{ "label": "13/48", "node": 3368, "naklon": 0 }, +{ "label": "13/49", "node": 3402, "naklon": 0 }, +{ "label": "13/50", "node": 3366, "naklon": 0 }, +{ "label": "13/51", "node": 3395, "naklon": 0 }, +{ "label": "13/52", "node": 3372, "naklon": 0 }, +{ "label": "13/53", "node": 3394, "naklon": 0 }, +{ "label": "13/54", "node": 3308, "naklon": 0 }, +{ "label": "13/54/1", "node": 3847, "naklon": 0 }, +{ "label": "13/55", "node": 3312, "naklon": 3 }, +{ "label": "13/56", "node": 3309, "naklon": 3 }, +{ "label": "13/57", "node": 3311, "naklon": 3 }, +{ "label": "13/58", "node": 3310, "naklon": 3 }, +{ "label": "13/59", "node": 4365, "naklon": 3 }, +{ "label": "13/60/1", "node": 4093, "naklon": 3 }, +{ "label": "13/61", "node": 3304, "naklon": 3 }, +{ "label": "13/62", "node": 3307, "naklon": 3 }, +{ "label": "13/63", "node": 3271, "naklon": 3 }, +{ "label": "13/64", "node": 3301, "naklon": 3 }, +{ "label": "13/65", "node": 4366, "naklon": 3 }, +{ "label": "13/66", "node": 3300, "naklon": 3 }, +{ "label": "13/67", "node": 3185, "naklon": 0 }, +{ "label": "13/68", "node": 3184, "naklon": 0 }, +{ "label": "13/69", "node": 3188, "naklon": 0 }, +{ "label": "13/71", "node": 3343, "naklon": 6 }, +{ "label": "13/71/1", "node": 3819, "naklon": 6 }, +{ "label": "13/71/2", "node": 3880, "naklon": 6 }, +{ "label": "13/72", "node": 3348, "naklon": 6 }, +{ "label": "13/74", "node": 3344, "naklon": 6 }, +{ "label": "13/75", "node": 3346, "naklon": 6 }, +{ "label": "13/75/1", "node": 3597, "naklon": 6 }, +{ "label": "13/76", "node": 3345, "naklon": 6 }, +{ "label": "13/77", "node": 3322, "naklon": 0 }, +{ "label": "13/78", "node": 3325, "naklon": 0 }, +{ "label": "13/78/1", "node": 4310, "naklon": 0 }, +{ "label": "13/79", "node": 3315, "naklon": 0 }, +{ "label": "13/80", "node": 3328, "naklon": 0 }, +{ "label": "13/81", "node": 3321, "naklon": 0 }, +{ "label": "13/82", "node": 3324, "naklon": 0 }, +{ "label": "13/84", "node": 3140, "naklon": 0 }, +{ "label": "13/85", "node": 3153, "naklon": 0 }, +{ "label": "13/86", "node": 3145, "naklon": 0 }, +{ "label": "13/87", "node": 3134, "naklon": 0 }, +{ "label": "13/88", "node": 3151, "naklon": 0 }, +{ "label": "13/89", "node": 3143, "naklon": 0 }, +{ "label": "13/90", "node": 3318, "naklon": 0 }, +{ "label": "13/91", "node": 3347, "naklon": 0 }, +{ "label": "13/94", "node": 3314, "naklon": 0 }, +{ "label": "13/96", "node": 3331, "naklon": 0 }, +{ "label": "13/97", "node": 3327, "naklon": 0 }, +{ "label": "13/99", "node": 3329, "naklon": 0 }, +{ "label": "13/100", "node": 3337, "naklon": 0 }, +{ "label": "13/101", "node": 3330, "naklon": 0 }, +{ "label": "13/102", "node": 3335, "naklon": 0 }, +{ "label": "13/103", "node": 3420, "naklon": 0 }, +{ "label": "13/104", "node": 3421, "naklon": 0 }, +{ "label": "13/105", "node": 4361, "naklon": 0 }, +{ "label": "13/106", "node": 4362, "naklon": 0 }, +{ "label": "13/107", "node": 3526, "naklon": 0 }, +{ "label": "13/108", "node": 4424, "naklon": null }, +{ "label": "13/109", "node": 3561, "naklon": null }, +{ "label": "13/110", "node": 3527, "naklon": null }, +{ "label": "13/111", "node": 3521, "naklon": null }, +{ "label": "13/112", "node": 3552, "naklon": null }, +{ "label": "13/113", "node": 3544, "naklon": null }, +{ "label": "13/114", "node": 3534, "naklon": null }, +{ "label": "13/115", "node": 3516, "naklon": null }, +{ "label": "13/116", "node": 3513, "naklon": null }, +{ "label": "13/117", "node": 3565, "naklon": null }, +{ "label": "13/118", "node": 3866, "naklon": null }, +{ "label": "14/1", "node": 3136, "naklon": 0 }, +{ "label": "14/2", "node": 3137, "naklon": 0 }, +{ "label": "14/3", "node": 3135, "naklon": 0 }, +{ "label": "14/4", "node": 3149, "naklon": 0 }, +{ "label": "14/5", "node": 3142, "naklon": 0 }, +{ "label": "14/6", "node": 3342, "naklon": 0 }, +{ "label": "14/7", "node": 3340, "naklon": 0 }, +{ "label": "14/8", "node": 3152, "naklon": 0 }, +{ "label": "14/9", "node": 3886, "naklon": 0 }, +{ "label": "14/10", "node": 3341, "naklon": null }, +{ "label": "14/11", "node": 3352, "naklon": null }, +{ "label": "15/1", "node": 3396, "naklon": 5 }, +{ "label": "15/2", "node": 2784, "naklon": 5 }, +{ "label": "15/3", "node": 2788, "naklon": 5 }, +{ "label": "15/4", "node": 2801, "naklon": 5 }, +{ "label": "15/5", "node": 2815, "naklon": 5 }, +{ "label": "15/6", "node": 2829, "naklon": 5 }, +{ "label": "15/7", "node": 2796, "naklon": 5 }, +{ "label": "15/8", "node": 2803, "naklon": 5 }, +{ "label": "15/8/1", "node": 4304, "naklon": 5 }, +{ "label": "15/8/2", "node": 4311, "naklon": 5 }, +{ "label": "15/9", "node": 2821, "naklon": 5 }, +{ "label": "15/10", "node": 3400, "naklon": 5 }, +{ "label": "15/11", "node": 2799, "naklon": 5 }, +{ "label": "15/12", "node": 2804, "naklon": 5 }, +{ "label": "15/12/1", "node": 4303, "naklon": 5 }, +{ "label": "15/12/2", "node": 4309, "naklon": 5 }, +{ "label": "15/13", "node": 2806, "naklon": 5 }, +{ "label": "15/14", "node": 2787, "naklon": 5 }, +{ "label": "15/15", "node": 2809, "naklon": 5 }, +{ "label": "15/16", "node": 2814, "naklon": 0 }, +{ "label": "15/17", "node": 3934, "naklon": 0 }, +{ "label": "15/18", "node": 3192, "naklon": 0 }, +{ "label": "15/19", "node": 2812, "naklon": 0 }, +{ "label": "15/20", "node": 4070, "naklon": 0 }, +{ "label": "15/21", "node": 2826, "naklon": 0 }, +{ "label": "15/22", "node": 2808, "naklon": 3 }, +{ "label": "15/23", "node": 2795, "naklon": 3 }, +{ "label": "15/24", "node": 2807, "naklon": 3 }, +{ "label": "15/25", "node": 2831, "naklon": 0 }, +{ "label": "15/26", "node": 2862, "naklon": null }, +{ "label": "15/27", "node": 2861, "naklon": 0 }, +{ "label": "15/28", "node": 2866, "naklon": 0 }, +{ "label": "15/28/1", "node": 3546, "naklon": 0 }, +{ "label": "15/29", "node": 4146, "naklon": 0 }, +{ "label": "15/29/1", "node": 3001, "naklon": 0 }, +{ "label": "15/30", "node": 2835, "naklon": 0 }, +{ "label": "15/31", "node": 2874, "naklon": 0 }, +{ "label": "15/32", "node": 2852, "naklon": 0 }, +{ "label": "15/33", "node": 2851, "naklon": 0 }, +{ "label": "15/33/1", "node": 3560, "naklon": 0 }, +{ "label": "15/34", "node": 2858, "naklon": 0 }, +{ "label": "15/34/1", "node": 4306, "naklon": 0 }, +{ "label": "15/35", "node": 2856, "naklon": 0 }, +{ "label": "15/36", "node": 2847, "naklon": 0 }, +{ "label": "15/36/1", "node": 3556, "naklon": 0 }, +{ "label": "15/37", "node": 3950, "naklon": 0 }, +{ "label": "15/38", "node": 2848, "naklon": 0 }, +{ "label": "15/39", "node": 2863, "naklon": 0 }, +{ "label": "15/39/1", "node": 4313, "naklon": 0 }, +{ "label": "15/40", "node": 2873, "naklon": 0 }, +{ "label": "15/40/1", "node": 2984, "naklon": 0 }, +{ "label": "15/41", "node": 2854, "naklon": 0 }, +{ "label": "15/42", "node": 2859, "naklon": 0 }, +{ "label": "15/43", "node": 2872, "naklon": 0 }, +{ "label": "15/44", "node": 2849, "naklon": 0 }, +{ "label": "15/45", "node": 2864, "naklon": 0 }, +{ "label": "15/46", "node": 3553, "naklon": null }, +{ "label": "15/47", "node": 3021, "naklon": null }, +{ "label": "15/47/1", "node": 3008, "naklon": null }, +{ "label": "15/48", "node": 3017, "naklon": null }, +{ "label": "15/49", "node": 3014, "naklon": null }, +{ "label": "15/50", "node": 2981, "naklon": null }, +{ "label": "15/51", "node": 3020, "naklon": null }, +{ "label": "15/52", "node": 3027, "naklon": null }, +{ "label": "15/53", "node": 3006, "naklon": null }, +{ "label": "15/54", "node": 3012, "naklon": null }, +{ "label": "15/55", "node": 2738, "naklon": 0 }, +{ "label": "15/56", "node": 2725, "naklon": 0 }, +{ "label": "15/57", "node": 3016, "naklon": null }, +{ "label": "15/58", "node": 3005, "naklon": null }, +{ "label": "15/58/1", "node": 3009, "naklon": null }, +{ "label": "15/59", "node": 3010, "naklon": 0 }, +{ "label": "15/59/1", "node": 3538, "naklon": 0 }, +{ "label": "15/59/2", "node": 4145, "naklon": 0 }, +{ "label": "15/60", "node": 2713, "naklon": 0 }, +{ "label": "15/61", "node": 2789, "naklon": 0 }, +{ "label": "15/62", "node": 2736, "naklon": 0 }, +{ "label": "15/63", "node": 2739, "naklon": 0 }, +{ "label": "15/64", "node": 4346, "naklon": 0 }, +{ "label": "15/65", "node": 2731, "naklon": 0 }, +{ "label": "15/66", "node": 2818, "naklon": 0 }, +{ "label": "15/66/1", "node": 3557, "naklon": 0 }, +{ "label": "15/67", "node": 2822, "naklon": 0 }, +{ "label": "15/68", "node": 2833, "naklon": 0 }, +{ "label": "15/69", "node": 2834, "naklon": 0 }, +{ "label": "15/70", "node": 3097, "naklon": 0 }, +{ "label": "15/71", "node": 2824, "naklon": 0 }, +{ "label": "15/72", "node": 2828, "naklon": 0 }, +{ "label": "15/73", "node": 2600, "naklon": 0 }, +{ "label": "15/73/1", "node": 4314, "naklon": 0 }, +{ "label": "15/74", "node": 2832, "naklon": 0 }, +{ "label": "15/75", "node": 4360, "naklon": 0 }, +{ "label": "15/76", "node": 2846, "naklon": 0 }, +{ "label": "15/77", "node": 2584, "naklon": 0 }, +{ "label": "15/78", "node": 2843, "naklon": 0 }, +{ "label": "15/78/1", "node": 4308, "naklon": 0 }, +{ "label": "15/79", "node": 4144, "naklon": null }, +{ "label": "15/80", "node": 2844, "naklon": 0 }, +{ "label": "15/81", "node": 2842, "naklon": 0 }, +{ "label": "15/82", "node": 2838, "naklon": 0 }, +{ "label": "15/83", "node": 2837, "naklon": null }, +{ "label": "15/83/1", "node": 3555, "naklon": null }, +{ "label": "15/84", "node": 2839, "naklon": 0 }, +{ "label": "15/85", "node": 2830, "naklon": 0 }, +{ "label": "15/86", "node": 4066, "naklon": 0 }, +{ "label": "15/87", "node": 2836, "naklon": 0 }, +{ "label": "15/88", "node": 2911, "naklon": 0 }, +{ "label": "15/89", "node": 2825, "naklon": 0 }, +{ "label": "15/90", "node": 2811, "naklon": 0 }, +{ "label": "15/94", "node": 3740, "naklon": 15 }, +{ "label": "15/95", "node": 2734, "naklon": 15 }, +{ "label": "15/96", "node": 3105, "naklon": 15 }, +{ "label": "15/97", "node": 2732, "naklon": 15 }, +{ "label": "15/98", "node": 2727, "naklon": 15 }, +{ "label": "15/99", "node": 2735, "naklon": 15 }, +{ "label": "15/100", "node": 3926, "naklon": 15 }, +{ "label": "15/101", "node": 2918, "naklon": 0 }, +{ "label": "15/102", "node": 2705, "naklon": 10 }, +{ "label": "15/103", "node": 2708, "naklon": 10 }, +{ "label": "15/104", "node": 2721, "naklon": 10 }, +{ "label": "15/105", "node": 2719, "naklon": 10 }, +{ "label": "15/106", "node": 2919, "naklon": 10 }, +{ "label": "15/107", "node": 3101, "naklon": 10 }, +{ "label": "15/108", "node": 2853, "naklon": 10 }, +{ "label": "15/109", "node": 2715, "naklon": 10 }, +{ "label": "15/110", "node": 2712, "naklon": 0 }, +{ "label": "15/111", "node": 2711, "naklon": 0 }, +{ "label": "15/112", "node": 2709, "naklon": 0 }, +{ "label": "15/113", "node": 2710, "naklon": 0 }, +{ "label": "15/114", "node": 2907, "naklon": 0 }, +{ "label": "15/115", "node": 2906, "naklon": 0 }, +{ "label": "15/116", "node": 2908, "naklon": 0 }, +{ "label": "15/117", "node": 2901, "naklon": 0 }, +{ "label": "15/118", "node": 2913, "naklon": 0 }, +{ "label": "15/119", "node": 3656, "naklon": 0 }, +{ "label": "15/120", "node": 2781, "naklon": 0 }, +{ "label": "15/121", "node": 2802, "naklon": 0 }, +{ "label": "15/122", "node": 2791, "naklon": 0 }, +{ "label": "15/123", "node": 2783, "naklon": 0 }, +{ "label": "15/124", "node": 2794, "naklon": 0 }, +{ "label": "15/125", "node": 3139, "naklon": 0 }, +{ "label": "15/126", "node": 3229, "naklon": 5 }, +{ "label": "15/127", "node": 3239, "naklon": 5 }, +{ "label": "15/128", "node": 3230, "naklon": 5 }, +{ "label": "15/129", "node": 4016, "naklon": null }, +{ "label": "16/16A", "node": 3608, "naklon": 0 }, +{ "label": "16/16B", "node": 4151, "naklon": 0 }, +{ "label": "16/1", "node": 3710, "naklon": 0 }, +{ "label": "16/2", "node": 3726, "naklon": 0 }, +{ "label": "16/3", "node": 3743, "naklon": 0 }, +{ "label": "16/4", "node": 3724, "naklon": 0 }, +{ "label": "16/5", "node": 3712, "naklon": 0 }, +{ "label": "16/6", "node": 3739, "naklon": 0 }, +{ "label": "16/7", "node": 3742, "naklon": 0 }, +{ "label": "16/8", "node": 3731, "naklon": 0 }, +{ "label": "16/9", "node": 3727, "naklon": 0 }, +{ "label": "16/10", "node": 3729, "naklon": 0 }, +{ "label": "16/11", "node": 3736, "naklon": 0 }, +{ "label": "16/12", "node": 3713, "naklon": 0 }, +{ "label": "16/13", "node": 3715, "naklon": 0 }, +{ "label": "16/14", "node": 3733, "naklon": 0 }, +{ "label": "16/15", "node": 3732, "naklon": 0 }, +{ "label": "16/17", "node": 3634, "naklon": 0 }, +{ "label": "16/18", "node": 3610, "naklon": 0 }, +{ "label": "16/19", "node": 3626, "naklon": 0 }, +{ "label": "16/20", "node": 3618, "naklon": 0 }, +{ "label": "16/21", "node": 3619, "naklon": 0 }, +{ "label": "16/22", "node": 3628, "naklon": 0 }, +{ "label": "16/23", "node": 3615, "naklon": 0 }, +{ "label": "16/24", "node": 3609, "naklon": 0 }, +{ "label": "16/25", "node": 3606, "naklon": 0 }, +{ "label": "16/26", "node": 3624, "naklon": 0 }, +{ "label": "16/27", "node": 3627, "naklon": 0 }, +{ "label": "16/28", "node": 3607, "naklon": 0 }, +{ "label": "16/29", "node": 4370, "naklon": 0 }, +{ "label": "16/30", "node": 3692, "naklon": 0 }, +{ "label": "16/31", "node": 3614, "naklon": 0 }, +{ "label": "16/32", "node": 3623, "naklon": 0 }, +{ "label": "16/33", "node": 4373, "naklon": 0 }, +{ "label": "16/34", "node": 3620, "naklon": 0 }, +{ "label": "16/35", "node": 3685, "naklon": 0 }, +{ "label": "16/36", "node": 3616, "naklon": 0 }, +{ "label": "16/37", "node": 3686, "naklon": 0 }, +{ "label": "16/38", "node": 3688, "naklon": 0 }, +{ "label": "16/39", "node": 3684, "naklon": 0 }, +{ "label": "16/40", "node": 3825, "naklon": 0 }, +{ "label": "16/41", "node": 3865, "naklon": 0 }, +{ "label": "16/42", "node": 3824, "naklon": 0 }, +{ "label": "16/43", "node": 3871, "naklon": 0 }, +{ "label": "16/44", "node": 3801, "naklon": 0 }, +{ "label": "16/45", "node": 3862, "naklon": 0 }, +{ "label": "16/46", "node": 3876, "naklon": 0 }, +{ "label": "16/47", "node": 3861, "naklon": 0 }, +{ "label": "16/48", "node": 4215, "naklon": 0 }, +{ "label": "16/49", "node": 3605, "naklon": 10 }, +{ "label": "16/50", "node": 3603, "naklon": 10 }, +{ "label": "16/51", "node": 3592, "naklon": 10 }, +{ "label": "16/52", "node": 3598, "naklon": 10 }, +{ "label": "16/53", "node": 3594, "naklon": 10 }, +{ "label": "16/54", "node": 3593, "naklon": 10 }, +{ "label": "16/55", "node": 3630, "naklon": 10 }, +{ "label": "16/56", "node": 3763, "naklon": 10 }, +{ "label": "16/57", "node": 3746, "naklon": 10 }, +{ "label": "16/58", "node": 3699, "naklon": 0 }, +{ "label": "16/59", "node": 3698, "naklon": 0 }, +{ "label": "16/60", "node": 3709, "naklon": null }, +{ "label": "16/61", "node": 3708, "naklon": 0 }, +{ "label": "16/62", "node": 3703, "naklon": null }, +{ "label": "16/63", "node": 3700, "naklon": 0 }, +{ "label": "16/64", "node": 3701, "naklon": null }, +{ "label": "16/65", "node": 3704, "naklon": 0 }, +{ "label": "16/66", "node": 3707, "naklon": null }, +{ "label": "16/67", "node": 3810, "naklon": 0 }, +{ "label": "16/68", "node": 4208, "naklon": null }, +{ "label": "16/69", "node": 3867, "naklon": 0 }, +{ "label": "16/70", "node": 4372, "naklon": null }, +{ "label": "16/71", "node": 3881, "naklon": 0 }, +{ "label": "16/72", "node": 4204, "naklon": null }, +{ "label": "16/73", "node": 3869, "naklon": 0 }, +{ "label": "16/74", "node": 4202, "naklon": null }, +{ "label": "16/75", "node": 3830, "naklon": 0 }, +{ "label": "16/76", "node": 3870, "naklon": null }, +{ "label": "16/77", "node": 3964, "naklon": 0 }, +{ "label": "16/78", "node": 3849, "naklon": 0 }, +{ "label": "16/79", "node": 3694, "naklon": null }, +{ "label": "16/80", "node": 3717, "naklon": 0 }, +{ "label": "16/81", "node": 3877, "naklon": null }, +{ "label": "16/82", "node": 3755, "naklon": 0 }, +{ "label": "16/83", "node": 3725, "naklon": null }, +{ "label": "16/84", "node": 3716, "naklon": 0 }, +{ "label": "16/85", "node": 3696, "naklon": null }, +{ "label": "16/86", "node": 3702, "naklon": 0 }, +{ "label": "16/87", "node": 3706, "naklon": null }, +{ "label": "16/88", "node": 3850, "naklon": 0 }, +{ "label": "16/89", "node": 3848, "naklon": null }, +{ "label": "16/90", "node": 3737, "naklon": null }, +{ "label": "16/91", "node": 3705, "naklon": 0 }, +{ "label": "16/92", "node": 3723, "naklon": null }, +{ "label": "16/93", "node": 3842, "naklon": 0 }, +{ "label": "16/94", "node": 3735, "naklon": null }, +{ "label": "16/95", "node": 3719, "naklon": 0 }, +{ "label": "16/96", "node": 3697, "naklon": 0 }, +{ "label": "16/97", "node": 3711, "naklon": 0 }, +{ "label": "16/98", "node": 4107, "naklon": null }, +{ "label": "16/99", "node": 4112, "naklon": 5 }, +{ "label": "16/100", "node": 4106, "naklon": 5 }, +{ "label": "16/101", "node": 4111, "naklon": 5 }, +{ "label": "16/102", "node": 4091, "naklon": null }, +{ "label": "16/103", "node": 4104, "naklon": 5 }, +{ "label": "16/104", "node": 4094, "naklon": null }, +{ "label": "16/105", "node": 4089, "naklon": 5 }, +{ "label": "16/106", "node": 4095, "naklon": null }, +{ "label": "16/107", "node": 4102, "naklon": 5 }, +{ "label": "16/108", "node": 4105, "naklon": null }, +{ "label": "16/109", "node": 3859, "naklon": null }, +{ "label": "16/110", "node": 4090, "naklon": 5 }, +{ "label": "16/111", "node": 4110, "naklon": null }, +{ "label": "16/112", "node": 4097, "naklon": 5 }, +{ "label": "16/113", "node": 4099, "naklon": null }, +{ "label": "16/114", "node": 4096, "naklon": null }, +{ "label": "16/115", "node": 4101, "naklon": 5 }, +{ "label": "16/116", "node": 4109, "naklon": null }, +{ "label": "16/117", "node": 4092, "naklon": 5 }, +{ "label": "16/118", "node": 3631, "naklon": null }, +{ "label": "16/119", "node": 3632, "naklon": 0 }, +{ "label": "16/120", "node": 3641, "naklon": null }, +{ "label": "16/121", "node": 3638, "naklon": 0 }, +{ "label": "16/122", "node": 3637, "naklon": null }, +{ "label": "16/123", "node": 4142, "naklon": null }, +{ "label": "16/124", "node": 4147, "naklon": 5 }, +{ "label": "16/125", "node": 4139, "naklon": 5 }, +{ "label": "20/30A", "node": 3172, "naklon": 2 }, +{ "label": "20/30B", "node": 3164, "naklon": 2 }, +{ "label": "20/1", "node": 3247, "naklon": 10 }, +{ "label": "20/2", "node": 3296, "naklon": 10 }, +{ "label": "20/3", "node": 3246, "naklon": 10 }, +{ "label": "20/4", "node": 3270, "naklon": 10 }, +{ "label": "20/5", "node": 3294, "naklon": 10 }, +{ "label": "20/6", "node": 3298, "naklon": 10 }, +{ "label": "20/7", "node": 3297, "naklon": 10 }, +{ "label": "20/8", "node": 3293, "naklon": 10 }, +{ "label": "20/9", "node": 3299, "naklon": 10 }, +{ "label": "20/10", "node": 3295, "naklon": 10 }, +{ "label": "20/11", "node": 3244, "naklon": 10 }, +{ "label": "20/12", "node": 3249, "naklon": 10 }, +{ "label": "20/13", "node": 3268, "naklon": 10 }, +{ "label": "20/14", "node": 3245, "naklon": 10 }, +{ "label": "20/15", "node": 3278, "naklon": 10 }, +{ "label": "20/16", "node": 3280, "naklon": 10 }, +{ "label": "20/17", "node": 3292, "naklon": 10 }, +{ "label": "20/18", "node": 3287, "naklon": 10 }, +{ "label": "20/19", "node": 3282, "naklon": 10 }, +{ "label": "20/20", "node": 3273, "naklon": 0 }, +{ "label": "20/21", "node": 3157, "naklon": 0 }, +{ "label": "20/22", "node": 3283, "naklon": 0 }, +{ "label": "20/23", "node": 3159, "naklon": 0 }, +{ "label": "20/24", "node": 3289, "naklon": 0 }, +{ "label": "20/25", "node": 3163, "naklon": 0 }, +{ "label": "20/26", "node": 3126, "naklon": 0 }, +{ "label": "20/27", "node": 3171, "naklon": 0 }, +{ "label": "20/28", "node": 3162, "naklon": 0 }, +{ "label": "20/29", "node": 3279, "naklon": 10 }, +{ "label": "20/31", "node": 3173, "naklon": 0 }, +{ "label": "20/32", "node": 3127, "naklon": 0 }, +{ "label": "20/33", "node": 3131, "naklon": 0 }, +{ "label": "20/34", "node": 3129, "naklon": 0 }, +{ "label": "20/35", "node": 3276, "naklon": 2 }, +{ "label": "20/36", "node": 3290, "naklon": 2 }, +{ "label": "20/37", "node": 3132, "naklon": 0 }, +{ "label": "20/38", "node": 3138, "naklon": 0 }, +{ "label": "20/39", "node": 3272, "naklon": 0 }, +{ "label": "20/40", "node": 3291, "naklon": 0 }, +{ "label": "20/41", "node": 3277, "naklon": 10 }, +{ "label": "20/42", "node": 3286, "naklon": 10 }, +{ "label": "20/43", "node": 3281, "naklon": 10 }, +{ "label": "20/44", "node": 3288, "naklon": 10 }, +{ "label": "20/45", "node": 3284, "naklon": 10 }, +{ "label": "20/46", "node": 3167, "naklon": 10 }, +{ "label": "20/47", "node": 3872, "naklon": 0 }, +{ "label": "20/48", "node": 3124, "naklon": 0 }, +{ "label": "20/49", "node": 3133, "naklon": 0 }, +{ "label": "20/50", "node": 3158, "naklon": 0 }, +{ "label": "20/51", "node": 3169, "naklon": 0 }, +{ "label": "20/52", "node": 3146, "naklon": 0 }, +{ "label": "20/53", "node": 3160, "naklon": 0 }, +{ "label": "20/54", "node": 3248, "naklon": 0 }, +{ "label": "20/55", "node": 3156, "naklon": 0 }, +{ "label": "20/56", "node": 3161, "naklon": 0 }, +{ "label": "20/57", "node": 3170, "naklon": 0 }, +{ "label": "20/58", "node": 3168, "naklon": 0 }, +{ "label": "20/59", "node": 3125, "naklon": 0 }, +{ "label": "20/60", "node": 3166, "naklon": 0 }, +{ "label": "20/61", "node": 3130, "naklon": 0 }, +{ "label": "20/62", "node": 3563, "naklon": 0 }, +{ "label": "20/63", "node": 3550, "naklon": null }, +{ "label": "20/67", "node": 3269, "naklon": 0 }, +{ "label": "21/1", "node": 2921, "naklon": 0 }, +{ "label": "21/2", "node": 2707, "naklon": 0 }, +{ "label": "21/3", "node": 2723, "naklon": 0 }, +{ "label": "21/4", "node": 2716, "naklon": 0 }, +{ "label": "21/5", "node": 2717, "naklon": 0 }, +{ "label": "21/6", "node": 2720, "naklon": 0 }, +{ "label": "21/7", "node": 2722, "naklon": 0 }, +{ "label": "21/8", "node": 2718, "naklon": 0 }, +{ "label": "21/9", "node": 2724, "naklon": 0 }, +{ "label": "21/10", "node": 2742, "naklon": 0 }, +{ "label": "21/11", "node": 2743, "naklon": 0 }, +{ "label": "21/12", "node": 2733, "naklon": 0 }, +{ "label": "21/14", "node": 2903, "naklon": 0 }, +{ "label": "21/15", "node": 2917, "naklon": 0 }, +{ "label": "21/16", "node": 2897, "naklon": 0 }, +{ "label": "21/17", "node": 2914, "naklon": 0 }, +{ "label": "21/18", "node": 2898, "naklon": 0 }, +{ "label": "21/19", "node": 2773, "naklon": 0 }, +{ "label": "21/20", "node": 2895, "naklon": 0 }, +{ "label": "21/21", "node": 2896, "naklon": 0 }, +{ "label": "21/22", "node": 2771, "naklon": 0 }, +{ "label": "21/23", "node": 2772, "naklon": 0 }, +{ "label": "21/24", "node": 2793, "naklon": 0 }, +{ "label": "21/25", "node": 2902, "naklon": 0 }, +{ "label": "21/26", "node": 2910, "naklon": 0 }, +{ "label": "21/27", "node": 2909, "naklon": 0 }, +{ "label": "21/28", "node": 2920, "naklon": 0 }, +{ "label": "21/29", "node": 2916, "naklon": 0 }, +{ "label": "21/30", "node": 2904, "naklon": 0 }, +{ "label": "21/31", "node": 2915, "naklon": 0 }, +{ "label": "21/32", "node": 2905, "naklon": 0 }, +{ "label": "21/33", "node": 2900, "naklon": 0 }, +{ "label": "21/34", "node": 2899, "naklon": 0 }, +{ "label": "21/36", "node": 2741, "naklon": 0 }, +{ "label": "21/37", "node": 2714, "naklon": 0 }, +{ "label": "21/38", "node": 2701, "naklon": 0 }, +{ "label": "21/39", "node": 2703, "naklon": 0 }, +{ "label": "21/40", "node": 2704, "naklon": 0 }, +{ "label": "21/41", "node": 2702, "naklon": 0 }, +{ "label": "21/42", "node": 2706, "naklon": 0 }, +{ "label": "21/43", "node": 2776, "naklon": 0 }, +{ "label": "21/44", "node": 2770, "naklon": 0 }, +{ "label": "21/45", "node": 2786, "naklon": 0 }, +{ "label": "21/46", "node": 2779, "naklon": 0 }, +{ "label": "21/47", "node": 2782, "naklon": 0 }, +{ "label": "21/48", "node": 2785, "naklon": 0 }, +{ "label": "21/49", "node": 2769, "naklon": 0 }, +{ "label": "21/50", "node": 3354, "naklon": 0 }, +{ "label": "21/51", "node": 2778, "naklon": 0 }, +{ "label": "21/52", "node": 2775, "naklon": 0 }, +{ "label": "21/53", "node": 2780, "naklon": 0 }, +{ "label": "21/54", "node": 2790, "naklon": 0 }, +{ "label": "21/55", "node": 2792, "naklon": 0 }, +{ "label": "21/56", "node": 2774, "naklon": 0 }, +{ "label": "22/1", "node": 2630, "naklon": 0 }, +{ "label": "22/2", "node": 2631, "naklon": 0 }, +{ "label": "22/3", "node": 2632, "naklon": 0 }, +{ "label": "22/4", "node": 2633, "naklon": 0 }, +{ "label": "22/5", "node": 2634, "naklon": 0 }, +{ "label": "22/6", "node": 2636, "naklon": 0 }, +{ "label": "22/7", "node": 4367, "naklon": 0 }, +{ "label": "22/8", "node": 2637, "naklon": 0 }, +{ "label": "22/9", "node": 2638, "naklon": 0 }, +{ "label": "22/10", "node": 2639, "naklon": 0 }, +{ "label": "22/11", "node": 2640, "naklon": 0 }, +{ "label": "22/12", "node": 2641, "naklon": 0 }, +{ "label": "22/13", "node": 2642, "naklon": 0 }, +{ "label": "22/14", "node": 2643, "naklon": 0 }, +{ "label": "22/15", "node": 2644, "naklon": 0 }, +{ "label": "22/16", "node": 2645, "naklon": 0 }, +{ "label": "22/17", "node": 2646, "naklon": 0 }, +{ "label": "22/18", "node": 2647, "naklon": 0 }, +{ "label": "22/19", "node": 2648, "naklon": 0 }, +{ "label": "22/20", "node": 2649, "naklon": 0 }, +{ "label": "22/21", "node": 2650, "naklon": 0 }, +{ "label": "22/22", "node": 2651, "naklon": 0 }, +{ "label": "22/23", "node": 4103, "naklon": 0 }, +{ "label": "22/24", "node": 2653, "naklon": 0 }, +{ "label": "22/25", "node": 2654, "naklon": 0 }, +{ "label": "22/26", "node": 2655, "naklon": 0 }, +{ "label": "22/27", "node": 2656, "naklon": 0 }, +{ "label": "22/28", "node": 2657, "naklon": 0 }, +{ "label": "22/29", "node": 2658, "naklon": 0 }, +{ "label": "22/30", "node": 2659, "naklon": 0 }, +{ "label": "22/31", "node": 2660, "naklon": 0 }, +{ "label": "22/32", "node": 2661, "naklon": 0 }, +{ "label": "22/32/1", "node": 3015, "naklon": 0 }, +{ "label": "22/33", "node": 2662, "naklon": 0 }, +{ "label": "22/34", "node": 2663, "naklon": 0 }, +{ "label": "22/35", "node": 2664, "naklon": 0 }, +{ "label": "22/36", "node": 2665, "naklon": 0 }, +{ "label": "22/37", "node": 2666, "naklon": 0 }, +{ "label": "22/38", "node": 2667, "naklon": 0 }, +{ "label": "22/39", "node": 2668, "naklon": 0 }, +{ "label": "22/40", "node": 2669, "naklon": null }, +{ "label": "22/41", "node": 2670, "naklon": null }, +{ "label": "22/42", "node": 2671, "naklon": null }, +{ "label": "23/9A", "node": 3087, "naklon": 10 }, +{ "label": "23/9B", "node": 3090, "naklon": 10 }, +{ "label": "23/1", "node": 3075, "naklon": 0 }, +{ "label": "23/2", "node": 3089, "naklon": 0 }, +{ "label": "23/3", "node": 3088, "naklon": 0 }, +{ "label": "23/4", "node": 3228, "naklon": 10 }, +{ "label": "23/5", "node": 2751, "naklon": 10 }, +{ "label": "23/6", "node": 3243, "naklon": 10 }, +{ "label": "23/7", "node": 4349, "naklon": 10 }, +{ "label": "23/8", "node": 3102, "naklon": 10 }, +{ "label": "23/10", "node": 3099, "naklon": 10 }, +{ "label": "23/11", "node": 3103, "naklon": 10 }, +{ "label": "23/12", "node": 3093, "naklon": 10 }, +{ "label": "23/13", "node": 3098, "naklon": 10 }, +{ "label": "23/14", "node": 3092, "naklon": 10 }, +{ "label": "23/15", "node": 3233, "naklon": 0 }, +{ "label": "23/16", "node": 3095, "naklon": 0 }, +{ "label": "23/17", "node": 4074, "naklon": 0 }, +{ "label": "23/18", "node": 2729, "naklon": 0 }, +{ "label": "23/19", "node": 3234, "naklon": 0 }, +{ "label": "23/20", "node": 3094, "naklon": 0 }, +{ "label": "23/21", "node": 2817, "naklon": 0 }, +{ "label": "23/22", "node": 3226, "naklon": 0 }, +{ "label": "23/23", "node": 3225, "naklon": 0 }, +{ "label": "23/24", "node": 3237, "naklon": 0 }, +{ "label": "23/25", "node": 4250, "naklon": 0 }, +{ "label": "23/26", "node": 3059, "naklon": 10 }, +{ "label": "23/27", "node": 3238, "naklon": 10 }, +{ "label": "23/28", "node": 3242, "naklon": 10 }, +{ "label": "23/29", "node": 3236, "naklon": 10 }, +{ "label": "23/30", "node": 3112, "naklon": 10 }, +{ "label": "23/31", "node": 3224, "naklon": 0 }, +{ "label": "23/32", "node": 4298, "naklon": 10 }, +{ "label": "23/33", "node": 4150, "naklon": 10 }, +{ "label": "23/34", "node": 3091, "naklon": 10 }, +{ "label": "25/1", "node": 3771, "naklon": 5 }, +{ "label": "25/2", "node": 3777, "naklon": 5 }, +{ "label": "25/3", "node": 3749, "naklon": 5 }, +{ "label": "25/4", "node": 3769, "naklon": 5 }, +{ "label": "25/5", "node": 3765, "naklon": 5 }, +{ "label": "25/6", "node": 3785, "naklon": 5 }, +{ "label": "25/7", "node": 3761, "naklon": 5 }, +{ "label": "25/8", "node": 3758, "naklon": 5 }, +{ "label": "25/9", "node": 3766, "naklon": 5 }, +{ "label": "25/10", "node": 3779, "naklon": 5 }, +{ "label": "25/11", "node": 3899, "naklon": 10 }, +{ "label": "25/12", "node": 3922, "naklon": 10 }, +{ "label": "25/13", "node": 3912, "naklon": 10 }, +{ "label": "25/14", "node": 3933, "naklon": 10 }, +{ "label": "25/15", "node": 3921, "naklon": 10 }, +{ "label": "25/16", "node": 4300, "naklon": 10 }, +{ "label": "25/17", "node": 3927, "naklon": 10 }, +{ "label": "25/18", "node": 3212, "naklon": 10 }, +{ "label": "25/19", "node": 3208, "naklon": 10 }, +{ "label": "25/20", "node": 3207, "naklon": 10 }, +{ "label": "25/21", "node": 4294, "naklon": 10 }, +{ "label": "25/22", "node": 3209, "naklon": 10 }, +{ "label": "25/23", "node": 3745, "naklon": 10 }, +{ "label": "25/24", "node": 3762, "naklon": 10 }, +{ "label": "25/25", "node": 3215, "naklon": 10 }, +{ "label": "25/26", "node": 3210, "naklon": 10 }, +{ "label": "25/27", "node": 3211, "naklon": 10 }, +{ "label": "25/28", "node": 3206, "naklon": 10 }, +{ "label": "25/29", "node": 3918, "naklon": 5 }, +{ "label": "25/30", "node": 3928, "naklon": 5 }, +{ "label": "25/31", "node": 3917, "naklon": 5 }, +{ "label": "25/32", "node": 4029, "naklon": 0 }, +{ "label": "25/33", "node": 4038, "naklon": 0 }, +{ "label": "25/34", "node": 4022, "naklon": 0 }, +{ "label": "25/35", "node": 3937, "naklon": 0 }, +{ "label": "25/36", "node": 3190, "naklon": 0 }, +{ "label": "25/37", "node": 3835, "naklon": 0 }, +{ "label": "25/38", "node": 3201, "naklon": 0 }, +{ "label": "25/39", "node": 3193, "naklon": 0 }, +{ "label": "25/40", "node": 3191, "naklon": 0 }, +{ "label": "25/41", "node": 3203, "naklon": 0 }, +{ "label": "25/42", "node": 4301, "naklon": 0 }, +{ "label": "25/43", "node": 3223, "naklon": 0 }, +{ "label": "25/44", "node": 3202, "naklon": 0 }, +{ "label": "25/45", "node": 3205, "naklon": 0 }, +{ "label": "25/46", "node": 3194, "naklon": 0 }, +{ "label": "25/47", "node": 3198, "naklon": 0 }, +{ "label": "25/48", "node": 3204, "naklon": 0 }, +{ "label": "25/49", "node": 3200, "naklon": 0 }, +{ "label": "25/50", "node": 3216, "naklon": 0 }, +{ "label": "25/51", "node": 3932, "naklon": 5 }, +{ "label": "25/52", "node": 3923, "naklon": 5 }, +{ "label": "25/53", "node": 3913, "naklon": 5 }, +{ "label": "25/54", "node": 3900, "naklon": 5 }, +{ "label": "25/55", "node": 4189, "naklon": 10 }, +{ "label": "25/56", "node": 4191, "naklon": 10 }, +{ "label": "25/57", "node": 3790, "naklon": 10 }, +{ "label": "25/58", "node": 4190, "naklon": 10 }, +{ "label": "25/59", "node": 4302, "naklon": 0 }, +{ "label": "25/60", "node": 4351, "naklon": 0 }, +{ "label": "25/61", "node": 4075, "naklon": 0 }, +{ "label": "25/62", "node": 4071, "naklon": 0 }, +{ "label": "25/63", "node": 3784, "naklon": 0 }, +{ "label": "25/64", "node": 4065, "naklon": 0 }, +{ "label": "25/65", "node": 4297, "naklon": 0 }, +{ "label": "25/66", "node": 4295, "naklon": 0 }, +{ "label": "25/67", "node": 4299, "naklon": 0 }, +{ "label": "25/68", "node": 3772, "naklon": 0 }, +{ "label": "25/69", "node": 3941, "naklon": 0 }, +{ "label": "25/70", "node": 3782, "naklon": 0 }, +{ "label": "25/71", "node": 4068, "naklon": 0 }, +{ "label": "25/72", "node": 4073, "naklon": 0 }, +{ "label": "25/73", "node": 3901, "naklon": 5 }, +{ "label": "25/74", "node": 4296, "naklon": 5 }, +{ "label": "25/75", "node": 3910, "naklon": 5 }, +{ "label": "25/76", "node": 4293, "naklon": 5 }, +{ "label": "25/77", "node": 3919, "naklon": 5 }, +{ "label": "25/78", "node": 3924, "naklon": 5 }, +{ "label": "25/79", "node": 3909, "naklon": 5 }, +{ "label": "25/80", "node": 3896, "naklon": 5 }, +{ "label": "25/81", "node": 3911, "naklon": 5 }, +{ "label": "25/82", "node": 2819, "naklon": 15 }, +{ "label": "25/83", "node": 3776, "naklon": 15 }, +{ "label": "25/84", "node": 3752, "naklon": 15 }, +{ "label": "25/85", "node": 4353, "naklon": 15 }, +{ "label": "25/86", "node": 3791, "naklon": 0 }, +{ "label": "25/87", "node": 3770, "naklon": 0 }, +{ "label": "25/88", "node": 3760, "naklon": 0 }, +{ "label": "25/89", "node": 3115, "naklon": 0 }, +{ "label": "25/90", "node": 3738, "naklon": 0 }, +{ "label": "25/91", "node": 3748, "naklon": 0 }, +{ "label": "25/92", "node": 3753, "naklon": 0 }, +{ "label": "25/93", "node": 3775, "naklon": 0 }, +{ "label": "25/94", "node": 3778, "naklon": 5 }, +{ "label": "25/95", "node": 4078, "naklon": 5 }, +{ "label": "25/96", "node": 4088, "naklon": 5 }, +{ "label": "25/97", "node": 3856, "naklon": 5 }, +{ "label": "25/98", "node": 4084, "naklon": 5 }, +{ "label": "25/99", "node": 4069, "naklon": 5 }, +{ "label": "25/100", "node": 4188, "naklon": 5 }, +{ "label": "25/101", "node": 4064, "naklon": 5 }, +{ "label": "25/102", "node": 3792, "naklon": 5 }, +{ "label": "25/103", "node": 3780, "naklon": 5 }, +{ "label": "25/104", "node": 4034, "naklon": 5 }, +{ "label": "25/105", "node": 4072, "naklon": 5 }, +{ "label": "25/106", "node": 3884, "naklon": 5 }, +{ "label": "25/107", "node": 3793, "naklon": 5 }, +{ "label": "25/108", "node": 3863, "naklon": 5 }, +{ "label": "25/109", "node": 3855, "naklon": 5 }, +{ "label": "33/1", "node": 3846, "naklon": 0 }, +{ "label": "33/2", "node": 3943, "naklon": 0 }, +{ "label": "33/3", "node": 3903, "naklon": 0 }, +{ "label": "33/4", "node": 3982, "naklon": 0 }, +{ "label": "33/5", "node": 3879, "naklon": 0 }, +{ "label": "33/6", "node": 3887, "naklon": 0 }, +{ "label": "33/7", "node": 3920, "naklon": 5 }, +{ "label": "33/8", "node": 3942, "naklon": 5 }, +{ "label": "33/9", "node": 3829, "naklon": null }, +{ "label": "34/79A", "node": 3452, "naklon": 6 }, +{ "label": "34/79B", "node": 3460, "naklon": 6 }, +{ "label": "34/90A", "node": 3443, "naklon": 6 }, +{ "label": "34/90B", "node": 3445, "naklon": 6 }, +{ "label": "34/90C", "node": 3457, "naklon": 6 }, +{ "label": "34/97A", "node": 3461, "naklon": 6 }, +{ "label": "34/97B", "node": 3463, "naklon": 6 }, +{ "label": "34/98A", "node": 3426, "naklon": 6 }, +{ "label": "34/98B", "node": 3444, "naklon": 6 }, +{ "label": "34/99A", "node": 3453, "naklon": 6 }, +{ "label": "34/99B", "node": 3455, "naklon": 6 }, +{ "label": "34/1", "node": 4009, "naklon": 0 }, +{ "label": "34/2", "node": 3602, "naklon": 0 }, +{ "label": "34/3", "node": 3441, "naklon": 0 }, +{ "label": "34/4", "node": 3464, "naklon": 0 }, +{ "label": "34/5", "node": 3883, "naklon": 0 }, +{ "label": "34/6", "node": 4098, "naklon": 0 }, +{ "label": "34/7", "node": 4003, "naklon": 0 }, +{ "label": "34/8", "node": 4004, "naklon": 0 }, +{ "label": "34/9", "node": 3888, "naklon": 0 }, +{ "label": "34/10", "node": 3997, "naklon": 0 }, +{ "label": "34/11", "node": 4006, "naklon": 0 }, +{ "label": "34/12", "node": 4000, "naklon": 0 }, +{ "label": "34/13", "node": 4011, "naklon": 0 }, +{ "label": "34/14", "node": 3999, "naklon": 0 }, +{ "label": "34/15", "node": 3981, "naklon": 0 }, +{ "label": "34/16", "node": 3988, "naklon": 0 }, +{ "label": "34/17", "node": 3986, "naklon": 0 }, +{ "label": "34/18", "node": 3998, "naklon": 0 }, +{ "label": "34/19", "node": 3983, "naklon": 0 }, +{ "label": "34/20", "node": 4005, "naklon": 0 }, +{ "label": "34/21", "node": 4001, "naklon": 0 }, +{ "label": "34/22", "node": 4008, "naklon": 0 }, +{ "label": "34/23", "node": 4002, "naklon": 0 }, +{ "label": "34/24", "node": 3996, "naklon": 0 }, +{ "label": "34/25", "node": 4007, "naklon": 0 }, +{ "label": "34/26", "node": 4113, "naklon": 15 }, +{ "label": "34/27", "node": 3595, "naklon": 5 }, +{ "label": "34/28", "node": 3599, "naklon": 5 }, +{ "label": "34/29", "node": 3601, "naklon": 5 }, +{ "label": "34/30", "node": 4205, "naklon": 0 }, +{ "label": "34/31", "node": 3987, "naklon": null }, +{ "label": "34/32", "node": 4214, "naklon": 0 }, +{ "label": "34/33", "node": 4226, "naklon": 0 }, +{ "label": "34/34", "node": 4209, "naklon": 0 }, +{ "label": "34/35", "node": 4201, "naklon": 0 }, +{ "label": "34/36", "node": 3440, "naklon": 0 }, +{ "label": "34/37", "node": 3465, "naklon": 0 }, +{ "label": "34/38", "node": 3446, "naklon": 0 }, +{ "label": "34/39", "node": 4039, "naklon": 5 }, +{ "label": "34/40", "node": 4057, "naklon": 5 }, +{ "label": "34/41", "node": 3985, "naklon": 0 }, +{ "label": "34/42", "node": 3882, "naklon": 0 }, +{ "label": "34/43", "node": 4040, "naklon": 5 }, +{ "label": "34/44", "node": 3231, "naklon": 0 }, +{ "label": "34/45", "node": 3227, "naklon": 0 }, +{ "label": "34/46", "node": 3431, "naklon": 0 }, +{ "label": "34/47", "node": 4013, "naklon": 0 }, +{ "label": "34/48", "node": 4045, "naklon": 0 }, +{ "label": "34/49", "node": 3949, "naklon": 0 }, +{ "label": "34/50", "node": 3953, "naklon": 0 }, +{ "label": "34/51", "node": 3952, "naklon": 0 }, +{ "label": "34/52", "node": 3995, "naklon": 0 }, +{ "label": "34/53", "node": 3992, "naklon": 0 }, +{ "label": "34/54", "node": 4198, "naklon": 0 }, +{ "label": "34/55", "node": 3935, "naklon": 0 }, +{ "label": "34/56", "node": 4050, "naklon": 0 }, +{ "label": "34/57", "node": 4049, "naklon": 0 }, +{ "label": "34/58", "node": 4054, "naklon": 0 }, +{ "label": "34/59", "node": 3663, "naklon": 6 }, +{ "label": "34/60", "node": 3661, "naklon": 6 }, +{ "label": "34/61", "node": 3664, "naklon": 6 }, +{ "label": "34/62", "node": 3660, "naklon": 6 }, +{ "label": "34/63", "node": 3662, "naklon": 6 }, +{ "label": "34/65", "node": 3665, "naklon": 6 }, +{ "label": "34/66", "node": 3667, "naklon": 6 }, +{ "label": "34/67", "node": 3675, "naklon": 6 }, +{ "label": "34/68", "node": 3666, "naklon": 6 }, +{ "label": "34/69", "node": 3652, "naklon": 6 }, +{ "label": "34/70", "node": 3458, "naklon": 6 }, +{ "label": "34/70/1", "node": 4425, "naklon": 6 }, +{ "label": "34/71", "node": 3459, "naklon": 6 }, +{ "label": "34/72", "node": 3435, "naklon": 6 }, +{ "label": "34/73", "node": 3448, "naklon": 6 }, +{ "label": "34/74", "node": 3451, "naklon": 6 }, +{ "label": "34/75", "node": 3442, "naklon": 6 }, +{ "label": "34/76", "node": 3449, "naklon": 6 }, +{ "label": "34/77", "node": 3450, "naklon": 6 }, +{ "label": "34/78", "node": 3433, "naklon": 6 }, +{ "label": "34/80", "node": 3432, "naklon": 12 }, +{ "label": "34/81", "node": 3470, "naklon": 12 }, +{ "label": "34/82", "node": 3438, "naklon": 12 }, +{ "label": "34/83", "node": 3439, "naklon": 12 }, +{ "label": "34/84", "node": 4028, "naklon": 5 }, +{ "label": "34/85", "node": 3596, "naklon": 5 }, +{ "label": "34/86", "node": 4021, "naklon": 5 }, +{ "label": "34/87", "node": 3437, "naklon": 12 }, +{ "label": "34/88", "node": 3428, "naklon": 12 }, +{ "label": "34/89", "node": 3430, "naklon": 12 }, +{ "label": "34/91", "node": 3454, "naklon": 6 }, +{ "label": "34/92", "node": 3492, "naklon": 6 }, +{ "label": "34/93", "node": 3462, "naklon": 6 }, +{ "label": "34/94", "node": 3427, "naklon": 6 }, +{ "label": "34/95", "node": 3434, "naklon": 6 }, +{ "label": "34/96", "node": 3456, "naklon": 6 }, +{ "label": "34/98/1", "node": 4307, "naklon": 6 }, +{ "label": "35/1", "node": 3968, "naklon": 0 }, +{ "label": "35/2", "node": 3969, "naklon": 0 }, +{ "label": "35/3", "node": 3947, "naklon": 0 }, +{ "label": "35/4", "node": 3979, "naklon": 0 }, +{ "label": "35/5", "node": 3959, "naklon": 0 }, +{ "label": "35/6", "node": 3948, "naklon": 0 }, +{ "label": "35/7", "node": 3961, "naklon": 0 }, +{ "label": "35/8", "node": 3956, "naklon": 0 }, +{ "label": "35/9", "node": 3604, "naklon": 0 }, +{ "label": "35/10", "node": 3944, "naklon": 0 }, +{ "label": "35/11", "node": 3960, "naklon": 0 }, +{ "label": "35/12", "node": 3958, "naklon": 0 }, +{ "label": "35/13", "node": 4036, "naklon": 5 }, +{ "label": "35/18", "node": 3893, "naklon": 5 }, +{ "label": "35/19", "node": 4108, "naklon": 5 }, +{ "label": "35/20", "node": 4017, "naklon": 5 }, +{ "label": "35/21", "node": 3963, "naklon": 0 }, +{ "label": "35/22", "node": 3658, "naklon": 0 }, +{ "label": "35/23", "node": 3975, "naklon": 0 }, +{ "label": "35/24", "node": 3980, "naklon": 0 }, +{ "label": "35/25", "node": 4012, "naklon": 0 }, +{ "label": "35/26", "node": 3655, "naklon": 0 }, +{ "label": "35/27", "node": 3962, "naklon": 0 }, +{ "label": "35/28", "node": 3945, "naklon": 0 }, +{ "label": "35/29", "node": 3569, "naklon": 0 }, +{ "label": "35/30", "node": 3429, "naklon": 0 }, +{ "label": "35/31", "node": 3657, "naklon": 0 }, +{ "label": "35/32", "node": 3646, "naklon": 0 }, +{ "label": "35/33", "node": 3622, "naklon": 0 }, +{ "label": "35/34", "node": 3612, "naklon": 0 }, +{ "label": "35/35", "node": 3955, "naklon": 0 }, +{ "label": "35/37", "node": 3878, "naklon": 0 }, +{ "label": "35/38", "node": 3965, "naklon": 0 }, +{ "label": "35/39", "node": 3970, "naklon": 0 }, +{ "label": "35/40", "node": 3611, "naklon": 0 }, +{ "label": "35/41", "node": 2635, "naklon": 0 }, +{ "label": "35/42", "node": 3978, "naklon": 0 }, +{ "label": "35/43", "node": 4213, "naklon": 0 }, +{ "label": "35/44", "node": 3984, "naklon": 0 }, +{ "label": "35/45", "node": 4218, "naklon": 0 }, +{ "label": "35/46", "node": 3973, "naklon": 0 }, +{ "label": "35/47", "node": 3974, "naklon": 0 }, +{ "label": "35/48", "node": 3759, "naklon": 0 }, +{ "label": "35/49", "node": 3844, "naklon": 0 }, +{ "label": "35/50", "node": 3804, "naklon": 0 }, +{ "label": "35/51", "node": 3831, "naklon": 0 }, +{ "label": "35/52", "node": 3643, "naklon": 0 }, +{ "label": "35/53", "node": 3966, "naklon": 0 }, +{ "label": "35/54", "node": 3971, "naklon": 0 }, +{ "label": "35/55", "node": 3650, "naklon": 6 }, +{ "label": "35/56", "node": 3651, "naklon": 6 }, +{ "label": "35/57", "node": 3669, "naklon": 6 }, +{ "label": "35/58", "node": 3648, "naklon": 6 }, +{ "label": "35/59", "node": 3645, "naklon": 6 }, +{ "label": "35/60", "node": 3659, "naklon": 6 }, +{ "label": "35/61", "node": 3647, "naklon": 6 }, +{ "label": "35/62", "node": 3644, "naklon": 6 }, +{ "label": "35/63", "node": 3671, "naklon": 6 }, +{ "label": "35/64", "node": 3682, "naklon": 6 }, +{ "label": "35/65", "node": 3672, "naklon": 6 }, +{ "label": "35/66", "node": 3683, "naklon": 6 }, +{ "label": "35/67", "node": 3673, "naklon": 6 }, +{ "label": "35/68", "node": 3674, "naklon": 6 }, +{ "label": "35/69", "node": 3679, "naklon": 6 }, +{ "label": "35/70", "node": 3649, "naklon": 6 }, +{ "label": "35/71", "node": 3687, "naklon": 6 }, +{ "label": "35/72", "node": 3677, "naklon": 6 }, +{ "label": "35/73", "node": 3690, "naklon": 6 }, +{ "label": "35/74", "node": 3691, "naklon": 6 }, +{ "label": "35/75", "node": 3676, "naklon": 6 }, +{ "label": "35/76", "node": 3680, "naklon": 6 }, +{ "label": "35/77", "node": 3668, "naklon": 6 }, +{ "label": "35/78", "node": 3681, "naklon": 6 }, +{ "label": "35/79", "node": 3670, "naklon": 6 }, +{ "label": "35/80", "node": 3689, "naklon": 6 }, +{ "label": "35/81", "node": 3678, "naklon": 6 }, +{ "label": "35/82", "node": 3693, "naklon": 6 }, +{ "label": "35/83", "node": 3654, "naklon": null }, +{ "label": "36/1", "node": 4086, "naklon": 0 }, +{ "label": "36/2", "node": 4085, "naklon": 0 }, +{ "label": "36/3", "node": 4083, "naklon": 0 }, +{ "label": "36/4", "node": 4087, "naklon": 0 }, +{ "label": "36/5", "node": 4077, "naklon": 0 }, +{ "label": "36/6", "node": 4082, "naklon": 0 }, +{ "label": "36/7", "node": 4186, "naklon": 0 }, +{ "label": "36/8", "node": 4206, "naklon": 0 }, +{ "label": "36/9", "node": 4080, "naklon": 0 }, +{ "label": "36/10", "node": 4081, "naklon": 0 }, +{ "label": "36/11", "node": 4210, "naklon": 0 }, +{ "label": "36/12", "node": 4079, "naklon": 0 }, +{ "label": "36/13", "node": 4076, "naklon": 0 }, +{ "label": "36/14", "node": 3852, "naklon": 0 }, +{ "label": "36/15", "node": 2813, "naklon": 0 }, +{ "label": "36/16", "node": 4219, "naklon": 0 }, +{ "label": "37/1A", "node": 3104, "naklon": 15 }, +{ "label": "37/1B", "node": 3121, "naklon": 15 }, +{ "label": "37/2", "node": 3113, "naklon": 10 }, +{ "label": "37/3", "node": 3118, "naklon": 10 }, +{ "label": "37/4", "node": 3111, "naklon": 10 }, +{ "label": "37/5", "node": 4020, "naklon": 10 }, +{ "label": "37/6", "node": 3119, "naklon": 10 }, +{ "label": "37/7", "node": 3110, "naklon": 10 }, +{ "label": "37/8", "node": 3108, "naklon": 10 }, +{ "label": "37/12", "node": 3107, "naklon": 0 }, +{ "label": "37/13", "node": 3199, "naklon": 0 }, +{ "label": "37/14", "node": 3120, "naklon": 0 }, +{ "label": "37/15", "node": 3122, "naklon": 0 }, +{ "label": "37/16", "node": 3908, "naklon": 0 }, +{ "label": "37/17", "node": 3114, "naklon": 0 }, +{ "label": "37/18", "node": 3105, "naklon": 0 }, +{ "label": "37/19", "node": 3116, "naklon": 0 }, +{ "label": "37/20", "node": 3106, "naklon": 0 }, +{ "label": "37/21", "node": 2887, "naklon": 5 }, +{ "label": "37/22", "node": 2888, "naklon": 5 }, +{ "label": "37/23", "node": 2877, "naklon": 5 }, +{ "label": "37/24", "node": 2891, "naklon": 5 }, +{ "label": "37/25", "node": 2886, "naklon": 5 }, +{ "label": "37/26", "node": 2892, "naklon": 5 }, +{ "label": "37/27", "node": 2882, "naklon": 5 }, +{ "label": "37/28", "node": 2883, "naklon": 5 }, +{ "label": "37/29", "node": 2876, "naklon": 5 }, +{ "label": "37/30", "node": 3109, "naklon": 5 }, +{ "label": "37/31", "node": 4152, "naklon": 5 }, +{ "label": "37/32", "node": 3117, "naklon": 5 }, +{ "label": "37/33", "node": 2870, "naklon": 5 }, +{ "label": "37/34", "node": 2867, "naklon": 0 }, +{ "label": "37/35", "node": 2865, "naklon": 0 }, +{ "label": "37/36", "node": 3096, "naklon": 0 }, +{ "label": "37/37", "node": 2871, "naklon": 0 }, +{ "label": "37/38", "node": 2884, "naklon": 0 }, +{ "label": "37/39", "node": 2855, "naklon": 0 }, +{ "label": "37/40", "node": 2878, "naklon": 0 }, +{ "label": "37/41", "node": 2889, "naklon": 0 }, +{ "label": "37/42", "node": 2879, "naklon": 0 }, +{ "label": "37/43", "node": 2850, "naklon": 0 }, +{ "label": "37/44", "node": 2894, "naklon": 0 }, +{ "label": "37/45", "node": 2880, "naklon": 0 }, +{ "label": "37/46", "node": 2893, "naklon": 0 }, +{ "label": "37/47", "node": 2890, "naklon": 0 }, +{ "label": "37/48", "node": 4355, "naklon": 0 }, +{ "label": "37/49", "node": 2885, "naklon": 0 }, +{ "label": "37/50", "node": 2875, "naklon": 0 }, +{ "label": "38/30A", "node": 3486, "naklon": 5 }, +{ "label": "38/30B", "node": 3714, "naklon": 0 }, +{ "label": "38/32A", "node": 3483, "naklon": 5 }, +{ "label": "38/32B", "node": 3496, "naklon": 0 }, +{ "label": "38/35A", "node": 3487, "naklon": 5 }, +{ "label": "38/35B", "node": 3498, "naklon": 5 }, +{ "label": "38/38A", "node": 3578, "naklon": 5 }, +{ "label": "38/38B", "node": 3508, "naklon": 5 }, +{ "label": "38/59A", "node": 3787, "naklon": 5 }, +{ "label": "38/59B", "node": 3491, "naklon": 5 }, +{ "label": "38/1", "node": 3568, "naklon": null }, +{ "label": "38/2", "node": 3502, "naklon": 0 }, +{ "label": "38/3", "node": 3836, "naklon": 0 }, +{ "label": "38/4", "node": 3588, "naklon": 0 }, +{ "label": "38/5", "node": 3493, "naklon": 0 }, +{ "label": "38/6", "node": 3580, "naklon": 0 }, +{ "label": "38/7", "node": 3572, "naklon": 0 }, +{ "label": "38/8", "node": 3506, "naklon": 0 }, +{ "label": "38/9", "node": 3503, "naklon": 0 }, +{ "label": "38/10", "node": 3579, "naklon": 0 }, +{ "label": "38/11", "node": 3586, "naklon": 0 }, +{ "label": "38/12", "node": 3495, "naklon": 5 }, +{ "label": "38/13", "node": 3492, "naklon": 5 }, +{ "label": "38/14", "node": 3532, "naklon": 5 }, +{ "label": "38/15", "node": 3574, "naklon": 5 }, +{ "label": "38/16", "node": 4140, "naklon": 5 }, +{ "label": "38/17", "node": 3795, "naklon": 5 }, +{ "label": "38/18", "node": 3788, "naklon": 5 }, +{ "label": "38/19", "node": 3796, "naklon": 5 }, +{ "label": "38/20", "node": 3797, "naklon": 5 }, +{ "label": "38/21", "node": 3798, "naklon": 5 }, +{ "label": "38/22", "node": 3786, "naklon": 5 }, +{ "label": "38/23", "node": 4067, "naklon": 5 }, +{ "label": "38/24", "node": 3773, "naklon": 5 }, +{ "label": "38/25", "node": 3774, "naklon": 5 }, +{ "label": "38/26", "node": 3789, "naklon": 5 }, +{ "label": "38/27", "node": 3520, "naklon": null }, +{ "label": "38/29", "node": 3577, "naklon": 5 }, +{ "label": "38/31", "node": 3530, "naklon": null }, +{ "label": "38/33", "node": 3488, "naklon": 5 }, +{ "label": "38/34", "node": 3505, "naklon": 5 }, +{ "label": "38/36", "node": 3497, "naklon": 5 }, +{ "label": "38/37", "node": 3490, "naklon": 5 }, +{ "label": "38/39", "node": 3585, "naklon": 5 }, +{ "label": "38/40", "node": 3582, "naklon": 5 }, +{ "label": "38/41", "node": 3507, "naklon": 5 }, +{ "label": "38/42", "node": 3484, "naklon": 5 }, +{ "label": "38/43", "node": 3501, "naklon": 5 }, +{ "label": "38/44", "node": 3581, "naklon": 5 }, +{ "label": "38/45", "node": 4192, "naklon": 5 }, +{ "label": "38/46", "node": 3576, "naklon": 5 }, +{ "label": "38/47", "node": 3489, "naklon": 5 }, +{ "label": "38/48", "node": 3573, "naklon": 5 }, +{ "label": "38/49", "node": 3504, "naklon": 5 }, +{ "label": "38/50", "node": 3794, "naklon": 5 }, +{ "label": "38/51", "node": 3485, "naklon": 5 }, +{ "label": "38/52", "node": 3482, "naklon": 5 }, +{ "label": "38/53", "node": 3575, "naklon": 5 }, +{ "label": "38/54", "node": 3499, "naklon": 5 }, +{ "label": "38/55", "node": 3494, "naklon": 5 }, +{ "label": "38/56", "node": 3583, "naklon": 5 }, +{ "label": "38/57", "node": 3570, "naklon": 5 }, +{ "label": "38/58", "node": 3500, "naklon": 0 }, +{ "label": "38/63", "node": 3510, "naklon": null }, +{ "label": "38/64", "node": 3512, "naklon": null }, +{ "label": "38/67", "node": 3535, "naklon": null }, +{ "label": "38/68", "node": 3531, "naklon": null }, +{ "label": "38/69", "node": 3537, "naklon": null }, +{ "label": "39/1", "node": 3522, "naklon": 10 }, +{ "label": "39/2", "node": 4018, "naklon": 10 }, +{ "label": "39/3", "node": 4019, "naklon": 10 }, +{ "label": "39/4", "node": 4154, "naklon": 5 }, +{ "label": "39/5", "node": 3907, "naklon": 5 }, +{ "label": "39/6", "node": 4148, "naklon": 0 }, +{ "label": "39/7", "node": 4153, "naklon": 0 }, +{ "label": "39/8", "node": 3938, "naklon": 0 }, +{ "label": "39/9", "node": 3802, "naklon": 0 }, +{ "label": "39/10", "node": 4015, "naklon": 0 }, +{ "label": "39/11", "node": 3929, "naklon": 0 }, +{ "label": "39/12", "node": 3946, "naklon": 0 }, +{ "label": "39/13", "node": 4014, "naklon": 0 }, +{ "label": "39/14", "node": 4155, "naklon": 0 }, +{ "label": "39/15", "node": 4149, "naklon": 0 }, +{ "label": "39/16", "node": 3642, "naklon": 0 }, +{ "label": "39/17", "node": 3636, "naklon": 5 }, +{ "label": "39/18", "node": 3991, "naklon": 0 }, +{ "label": "39/19", "node": 3994, "naklon": 0 }, +{ "label": "39/20", "node": 3990, "naklon": 0 }, +{ "label": "39/21", "node": 3967, "naklon": 0 }, +{ "label": "39/22", "node": 3977, "naklon": 0 }, +{ "label": "39/23", "node": 3757, "naklon": 15 }, +{ "label": "39/24", "node": 3633, "naklon": 15 }, +{ "label": "39/25", "node": 3744, "naklon": 15 }, +{ "label": "39/26", "node": 4023, "naklon": 5 }, +{ "label": "39/27", "node": 3720, "naklon": 5 }, +{ "label": "39/28", "node": 3734, "naklon": 5 }, +{ "label": "39/29", "node": 3741, "naklon": 5 }, +{ "label": "39/30", "node": 3721, "naklon": 5 }, +{ "label": "39/31", "node": 3845, "naklon": 0 }, +{ "label": "39/32", "node": 3840, "naklon": 0 }, +{ "label": "39/33", "node": 3837, "naklon": null }, +{ "label": "39/34", "node": 3839, "naklon": 0 }, +{ "label": "41/1", "node": 3542, "naklon": null }, +{ "label": "41/2", "node": 3566, "naklon": null }, +{ "label": "41/3", "node": 3548, "naklon": null }, +{ "label": "41/4", "node": 3515, "naklon": null }, +{ "label": "41/5", "node": 3559, "naklon": null }, +{ "label": "41/6", "node": 3509, "naklon": null }, +{ "label": "41/7", "node": 3524, "naklon": null }, +{ "label": "41/8", "node": 3518, "naklon": null }, +{ "label": "41/9", "node": 3182, "naklon": null }, +{ "label": "41/10", "node": 3187, "naklon": null }, +{ "label": "41/11", "node": 3195, "naklon": 0 }, +{ "label": "41/12", "node": 3857, "naklon": 0 }, +{ "label": "41/13", "node": 3183, "naklon": 0 }, +{ "label": "41/14", "node": 3177, "naklon": 0 }, +{ "label": "41/15", "node": 3189, "naklon": 0 }, +{ "label": "41/16", "node": 3186, "naklon": 0 }, +{ "label": "42/1", "node": 3178, "naklon": 0 }, +{ "label": "42/2", "node": 3219, "naklon": 0 }, +{ "label": "42/3", "node": 3475, "naklon": 0 }, +{ "label": "42/4", "node": 3175, "naklon": 0 }, +{ "label": "42/5", "node": 3222, "naklon": 0 }, +{ "label": "42/6", "node": 3221, "naklon": 0 }, +{ "label": "42/7", "node": 3181, "naklon": 0 }, +{ "label": "42/8", "node": 3180, "naklon": 0 }, +{ "label": "42/9", "node": 3218, "naklon": 0 }, +{ "label": "42/10", "node": 3176, "naklon": 0 }, +{ "label": "42/11", "node": 3174, "naklon": 0 }, +{ "label": "42/12", "node": 3220, "naklon": 0 }, +{ "label": "42/13", "node": 3533, "naklon": null }, +{ "label": "42/14", "node": 3543, "naklon": null }, +{ "label": "42/15", "node": 3554, "naklon": null }, +{ "label": "42/16", "node": 3549, "naklon": null }, +{ "label": "43/1", "node": 2857, "naklon": 5 }, +{ "label": "43/2", "node": 2752, "naklon": 5 }, +{ "label": "43/3", "node": 2753, "naklon": 5 }, +{ "label": "43/4", "node": 3024, "naklon": 5 }, +{ "label": "43/5", "node": 2754, "naklon": 5 }, +{ "label": "43/6", "node": 4423, "naklon": 5 }, +{ "label": "43/7", "node": 4368, "naklon": 5 }, +{ "label": "43/8", "node": 2978, "naklon": 5 }, +{ "label": "43/9", "node": 2868, "naklon": 5 }, +{ "label": "43/10", "node": 4377, "naklon": 5 }, +{ "label": "43/11", "node": 2757, "naklon": 5 }, +{ "label": "43/12", "node": 2970, "naklon": 5 }, +{ "label": "43/13", "node": 2758, "naklon": 5 }, +{ "label": "43/14", "node": 4378, "naklon": 5 }, +{ "label": "43/15", "node": 2759, "naklon": 5 }, +{ "label": "43/16", "node": 4342, "naklon": 5 }, +{ "label": "43/17", "node": 3026, "naklon": null }, +{ "label": "43/18", "node": 2986, "naklon": null }, +{ "label": "43/19", "node": 4343, "naklon": null }, +{ "label": "43/20", "node": 2760, "naklon": null }, +{ "label": "43/21", "node": 4379, "naklon": null }, +{ "label": "43/22", "node": 2971, "naklon": null }, +{ "label": "43/23", "node": 2761, "naklon": null }, +{ "label": "43/24", "node": 2762, "naklon": null }, +{ "label": "43/25", "node": 4339, "naklon": null }, +{ "label": "43/26", "node": 4380, "naklon": null }, +{ "label": "43/27", "node": 2975, "naklon": null }, +{ "label": "43/28", "node": 3003, "naklon": null }, +{ "label": "43/29", "node": 4338, "naklon": null }, +{ "label": "43/30", "node": 3002, "naklon": null }, +{ "label": "43/31", "node": 4345, "naklon": null }, +{ "label": "43/32", "node": 2979, "naklon": null }, +{ "label": "43/33", "node": 2989, "naklon": null }, +{ "label": "43/34", "node": 2996, "naklon": null }, +{ "label": "43/35", "node": 2972, "naklon": null }, +{ "label": "43/36", "node": 2988, "naklon": null }, +{ "label": "43/37", "node": 4344, "naklon": null }, +{ "label": "43/38", "node": 3022, "naklon": null }, +{ "label": "43/39", "node": 4341, "naklon": null }, +{ "label": "43/40", "node": 2983, "naklon": null }, +{ "label": "43/41", "node": 2995, "naklon": null }, +{ "label": "43/42", "node": 2763, "naklon": null }, +{ "label": "43/43", "node": 2764, "naklon": null }, +{ "label": "43/44", "node": 2765, "naklon": null }, +{ "label": "43/45", "node": 2766, "naklon": null }, +{ "label": "43/46", "node": 2767, "naklon": null }, +{ "label": "43/47", "node": 2768, "naklon": null }, +{ "label": "43/48", "node": 3018, "naklon": null }, +{ "label": "43/49", "node": 2982, "naklon": null }, +{ "label": "43/50", "node": 3019, "naklon": 0 }, +{ "label": "43/51", "node": 3013, "naklon": null }, +{ "label": "43/52", "node": 3007, "naklon": null }, +{ "label": "43/53", "node": 2980, "naklon": null }, +{ "label": "43/54", "node": 3011, "naklon": null }, +{ "label": "43/55", "node": 2672, "naklon": null }, +{ "label": "43/56", "node": 2673, "naklon": null }, +{ "label": "43/57", "node": 2674, "naklon": null }, +{ "label": "43/58", "node": 2675, "naklon": null }, +{ "label": "43/59", "node": 2676, "naklon": null }, +{ "label": "43/60", "node": 2677, "naklon": null }, +{ "label": "43/61", "node": 2678, "naklon": null }, +{ "label": "43/62", "node": 2679, "naklon": null }, +{ "label": "43/63", "node": 2680, "naklon": null }, +{ "label": "43/64", "node": 2840, "naklon": null }, +{ "label": "43/65", "node": 2682, "naklon": null }, +{ "label": "43/66", "node": 2683, "naklon": null }, +{ "label": "43/67", "node": 2684, "naklon": 0 }, +{ "label": "43/68", "node": 2685, "naklon": null }, +{ "label": "43/69", "node": 2686, "naklon": null }, +{ "label": "43/70", "node": 2687, "naklon": null }, +{ "label": "43/71", "node": 2688, "naklon": null }, +{ "label": "43/72", "node": 2689, "naklon": null }, +{ "label": "43/73", "node": 2690, "naklon": null }, +{ "label": "43/74", "node": 2691, "naklon": null }, +{ "label": "43/75", "node": 2692, "naklon": null }, +{ "label": "43/76", "node": 2693, "naklon": 0 }, +{ "label": "43/77", "node": 2694, "naklon": null }, +{ "label": "43/78", "node": 2695, "naklon": null }, +{ "label": "43/79", "node": 2696, "naklon": 0 }, +{ "label": "43/80", "node": 2697, "naklon": null }, +{ "label": "43/81", "node": 2698, "naklon": 0 }, +{ "label": "43/82", "node": 2699, "naklon": null }, +{ "label": "43/83", "node": 2700, "naklon": 0 }, +{ "label": "43/84", "node": 2744, "naklon": null }, +{ "label": "43/85", "node": 2745, "naklon": 0 }, +{ "label": "43/86", "node": 2746, "naklon": null }, +{ "label": "43/87", "node": 2747, "naklon": 0 }, +{ "label": "43/88", "node": 2748, "naklon": null }, +{ "label": "43/89", "node": 2749, "naklon": 0 }, +{ "label": "43/90", "node": 2841, "naklon": null }, +{ "label": "45/1", "node": 4237, "naklon": 5 }, +{ "label": "45/2", "node": 4226, "naklon": 5 }, +{ "label": "45/3", "node": 4242, "naklon": 5 }, +{ "label": "45/4", "node": 4179, "naklon": 5 }, +{ "label": "45/5", "node": 4247, "naklon": 5 }, +{ "label": "45/6", "node": 4245, "naklon": 5 }, +{ "label": "45/7", "node": 3872, "naklon": 5 }, +{ "label": "45/8", "node": 4175, "naklon": 5 }, +{ "label": "45/9", "node": 4236, "naklon": 5 }, +{ "label": "45/10", "node": 4170, "naklon": 5 }, +{ "label": "45/11", "node": 4238, "naklon": 5 }, +{ "label": "45/12", "node": 4246, "naklon": 5 }, +{ "label": "45/13", "node": 4166, "naklon": 5 }, +{ "label": "45/14", "node": 4227, "naklon": 5 }, +{ "label": "45/15", "node": 4171, "naklon": 5 }, +{ "label": "45/16", "node": 4180, "naklon": 5 }, +{ "label": "45/17", "node": 4244, "naklon": 5 }, +{ "label": "45/18", "node": 4199, "naklon": 5 }, +{ "label": "45/19", "node": 4239, "naklon": 5 }, +{ "label": "45/20", "node": 4207, "naklon": 5 }, +{ "label": "45/21", "node": 4223, "naklon": 5 }, +{ "label": "45/22", "node": 4230, "naklon": 5 }, +{ "label": "45/23", "node": 4233, "naklon": 5 }, +{ "label": "45/24", "node": 4222, "naklon": 5 }, +{ "label": "45/25", "node": 4217, "naklon": 5 }, +{ "label": "45/26", "node": 4243, "naklon": 5 }, +{ "label": "45/27", "node": 4200, "naklon": 5 }, +{ "label": "45/28", "node": 4228, "naklon": 5 }, +{ "label": "45/29", "node": 4211, "naklon": 5 }, +{ "label": "45/30", "node": 4234, "naklon": 5 }, +{ "label": "45/31", "node": 4235, "naklon": 5 }, +{ "label": "45/32", "node": 4203, "naklon": 5 }, +{ "label": "45/33", "node": 4240, "naklon": 5 }, +{ "label": "45/34", "node": 4224, "naklon": 5 }, +{ "label": "45/35", "node": 4232, "naklon": 5 }, +{ "label": "45/36", "node": 4231, "naklon": 5 }, +{ "label": "45/37", "node": 4161, "naklon": 5 }, +{ "label": "45/38", "node": 4225, "naklon": 5 }, +{ "label": "45/39", "node": 4241, "naklon": 5 }, +{ "label": "45/40", "node": 4229, "naklon": 5 }, +{ "label": "45/41", "node": 4221, "naklon": 5 }, +{ "label": "45/42", "node": 4212, "naklon": 5 }, +{ "label": "45/43", "node": 4216, "naklon": 5 }, +{ "label": "45/44", "node": 3864, "naklon": null }, +{ "label": "46/1", "node": 3806, "naklon": 5 }, +{ "label": "46/2", "node": 3813, "naklon": 5 }, +{ "label": "46/3", "node": 3815, "naklon": 5 }, +{ "label": "46/4", "node": 3807, "naklon": 5 }, +{ "label": "46/5", "node": 3895, "naklon": 5 }, +{ "label": "46/6", "node": 3809, "naklon": 5 }, +{ "label": "46/7", "node": 3820, "naklon": 5 }, +{ "label": "46/8", "node": 3805, "naklon": 5 }, +{ "label": "46/9", "node": 3894, "naklon": 0 }, +{ "label": "46/10", "node": 4055, "naklon": 0 }, +{ "label": "46/11", "node": 3812, "naklon": 5 }, +{ "label": "46/12", "node": 3822, "naklon": 5 }, +{ "label": "46/13", "node": 3821, "naklon": 5 }, +{ "label": "46/14", "node": 3808, "naklon": 5 }, +{ "label": "46/15", "node": 3799, "naklon": 5 }, +{ "label": "46/16", "node": 3816, "naklon": 5 }, +{ "label": "46/17", "node": 3751, "naklon": 5 }, +{ "label": "46/18", "node": 3814, "naklon": 5 }, +{ "label": "46/19", "node": 4044, "naklon": 0 }, +{ "label": "46/20", "node": 3931, "naklon": 0 }, +{ "label": "46/21", "node": 3902, "naklon": 5 }, +{ "label": "46/22", "node": 3916, "naklon": 5 }, +{ "label": "46/23", "node": 3892, "naklon": 5 }, +{ "label": "46/24", "node": 3914, "naklon": 5 }, +{ "label": "46/25", "node": 3898, "naklon": 5 }, +{ "label": "46/26", "node": 3897, "naklon": 5 }, +{ "label": "46/27", "node": 3885, "naklon": 5 }, +{ "label": "46/28", "node": 3906, "naklon": 5 }, +{ "label": "46/29", "node": 3930, "naklon": 0 }, +{ "label": "46/30", "node": 3936, "naklon": 0 }, +{ "label": "46/31", "node": 3860, "naklon": 5 }, +{ "label": "46/32", "node": 3841, "naklon": 5 }, +{ "label": "46/33", "node": 3873, "naklon": 5 }, +{ "label": "46/34", "node": 3854, "naklon": 5 }, +{ "label": "46/35", "node": 3939, "naklon": 5 }, +{ "label": "46/36", "node": 3858, "naklon": 5 }, +{ "label": "46/37", "node": 3940, "naklon": 5 }, +{ "label": "46/38", "node": 4035, "naklon": 5 }, +{ "label": "47/1", "node": 3373, "naklon": 0 }, +{ "label": "47/2", "node": 3374, "naklon": 0 }, +{ "label": "47/3", "node": 3384, "naklon": 0 }, +{ "label": "47/4", "node": 3385, "naklon": 0 }, +{ "label": "48/1", "node": 4051, "naklon": 5 }, +{ "label": "48/2", "node": 4041, "naklon": 5 }, +{ "label": "48/3", "node": 4056, "naklon": 5 }, +{ "label": "48/4", "node": 3875, "naklon": 5 }, +{ "label": "48/5", "node": 4061, "naklon": 5 }, +{ "label": "48/6", "node": 4047, "naklon": 5 }, +{ "label": "48/7", "node": 4060, "naklon": 5 }, +{ "label": "48/8", "node": 4059, "naklon": 5 }, +{ "label": "48/9", "node": 4058, "naklon": 5 }, +{ "label": "48/10", "node": 3635, "naklon": 5 }, +{ "label": "48/11", "node": 3640, "naklon": 5 }, +{ "label": "48/12", "node": 3747, "naklon": 5 }, +{ "label": "48/13", "node": 3629, "naklon": 5 }, +{ "label": "48/14", "node": 4048, "naklon": 5 }, +{ "label": "48/15", "node": 4063, "naklon": 5 }, +{ "label": "48/16", "node": 4062, "naklon": 5 }, +{ "label": "48/17", "node": 4043, "naklon": 5 }, +{ "label": "48/18", "node": 4052, "naklon": 5 }, +{ "label": "48/19", "node": 4042, "naklon": 5 }, +{ "label": "48/20", "node": 4053, "naklon": 5 }, +{ "label": "50/15A", "node": 4167, "naklon": null }, +{ "label": "50/15B", "node": 4159, "naklon": null }, +{ "label": "50/1", "node": 4183, "naklon": 0 }, +{ "label": "50/2", "node": 4157, "naklon": 0 }, +{ "label": "50/3", "node": 4160, "naklon": 0 }, +{ "label": "50/4", "node": 4173, "naklon": 0 }, +{ "label": "50/5", "node": 4177, "naklon": 0 }, +{ "label": "50/6", "node": 4174, "naklon": 0 }, +{ "label": "50/7", "node": 4178, "naklon": 0 }, +{ "label": "50/8", "node": 4195, "naklon": 0 }, +{ "label": "50/9", "node": 4169, "naklon": 0 }, +{ "label": "50/10", "node": 4162, "naklon": 0 }, +{ "label": "50/11", "node": 4158, "naklon": 0 }, +{ "label": "50/12", "node": 4182, "naklon": 0 }, +{ "label": "50/13", "node": 4194, "naklon": 0 }, +{ "label": "50/14", "node": 4184, "naklon": 0 }, +{ "label": "50/16", "node": 4197, "naklon": null }, +{ "label": "50/17", "node": 4164, "naklon": null }, +{ "label": "50/18", "node": 3306, "naklon": null }, +{ "label": "50/19", "node": 4168, "naklon": null }, +{ "label": "50/20", "node": 4193, "naklon": null }, +{ "label": "50/21", "node": 4187, "naklon": null }, +{ "label": "50/22", "node": 4163, "naklon": null }, +{ "label": "50/23", "node": 4165, "naklon": null }, +{ "label": "50/24", "node": 4185, "naklon": null }, +{ "label": "50/25", "node": 3904, "naklon": null }, +{ "label": "53/1", "node": 2619, "naklon": 0 }, +{ "label": "53/2", "node": 2623, "naklon": 0 }, +{ "label": "53/3", "node": 2617, "naklon": 0 }, +{ "label": "53/4", "node": 2622, "naklon": 0 }, +{ "label": "53/5", "node": 2618, "naklon": 0 }, +{ "label": "53/6", "node": 2626, "naklon": 0 }, +{ "label": "53/7", "node": 2869, "naklon": 0 }, +{ "label": "53/8", "node": 2613, "naklon": 0 }, +{ "label": "53/9", "node": 2608, "naklon": 0 }, +{ "label": "53/10", "node": 2611, "naklon": 0 }, +{ "label": "53/11", "node": 2598, "naklon": 0 }, +{ "label": "53/12", "node": 3528, "naklon": 0 }, +{ "label": "53/13", "node": 3545, "naklon": 0 }, +{ "label": "53/14", "node": 2620, "naklon": 0 }, +{ "label": "53/15", "node": 2612, "naklon": 0 }, +{ "label": "53/16", "node": 2615, "naklon": 0 }, +{ "label": "53/17", "node": 3722, "naklon": 0 }, +{ "label": "53/18", "node": 2624, "naklon": 0 }, +{ "label": "53/19", "node": 2609, "naklon": 0 }, +{ "label": "53/20", "node": 2625, "naklon": 0 }, +{ "label": "53/21", "node": 2602, "naklon": 0 }, +{ "label": "53/22", "node": 2610, "naklon": 0 }, +{ "label": "53/23", "node": 2599, "naklon": 0 }, +{ "label": "53/24", "node": 2605, "naklon": 0 }, +{ "label": "53/25", "node": 2593, "naklon": 0 }, +{ "label": "53/26", "node": 3074, "naklon": 0 }, +{ "label": "53/27", "node": 2740, "naklon": 0 }, +{ "label": "53/28", "node": 2614, "naklon": 0 }, +{ "label": "53/29", "node": 2601, "naklon": 0 }, +{ "label": "53/30", "node": 4196, "naklon": 0 }, +{ "label": "53/31", "node": 2607, "naklon": 0 }, +{ "label": "53/32", "node": 2582, "naklon": 0 }, +{ "label": "53/33", "node": 2594, "naklon": 0 }, +{ "label": "53/34", "node": 2589, "naklon": 0 }, +{ "label": "53/35", "node": 2596, "naklon": 0 }, +{ "label": "53/36", "node": 2603, "naklon": 0 }, +{ "label": "53/37", "node": 2597, "naklon": 0 }, +{ "label": "53/38", "node": 2590, "naklon": 0 }, +{ "label": "53/39", "node": 2581, "naklon": 0 }, +{ "label": "53/40", "node": 2583, "naklon": 0 }, +{ "label": "53/41", "node": 2580, "naklon": 0 }, +{ "label": "53/42", "node": 2579, "naklon": 0 }, +{ "label": "53/43", "node": 2797, "naklon": 0 }, +{ "label": "53/44", "node": 2577, "naklon": 0 }, +{ "label": "53/45", "node": 2586, "naklon": 0 }, +{ "label": "53/46", "node": 2588, "naklon": 0 }, +{ "label": "53/47", "node": 2591, "naklon": 0 }, +{ "label": "53/48", "node": 2592, "naklon": 0 }, +{ "label": "53/49", "node": 2573, "naklon": 0 }, +{ "label": "53/50", "node": 2595, "naklon": 0 }, +{ "label": "53/51", "node": 2587, "naklon": 0 }, +{ "label": "53/52", "node": 2578, "naklon": 0 }, +{ "label": "53/53", "node": 2574, "naklon": 0 }, +{ "label": "53/54", "node": 2571, "naklon": 0 }, +{ "label": "53/55", "node": 2570, "naklon": 0 }, +{ "label": "53/56", "node": 2576, "naklon": 0 }, +{ "label": "53/57", "node": 2881, "naklon": 0 }, +{ "label": "53/58", "node": 2575, "naklon": 0 }, +{ "label": "53/59", "node": 2572, "naklon": 0 }, +{ "label": "53/60", "node": 2569, "naklon": 0 }, +{ "label": "55/1", "node": 4324, "naklon": 0 }, +{ "label": "55/2", "node": 4319, "naklon": 0 }, +{ "label": "55/3", "node": 4327, "naklon": 0 }, +{ "label": "55/4", "node": 4333, "naklon": 0 }, +{ "label": "55/5", "node": 4332, "naklon": 0 }, +{ "label": "55/6", "node": 4320, "naklon": 0 }, +{ "label": "55/7", "node": 4317, "naklon": 0 }, +{ "label": "55/8", "node": 4318, "naklon": 0 }, +{ "label": "55/9", "node": 4328, "naklon": 0 }, +{ "label": "55/10", "node": 4323, "naklon": 0 }, +{ "label": "55/11", "node": 4325, "naklon": 0 }, +{ "label": "55/12", "node": 4326, "naklon": 0 }, +{ "label": "55/13", "node": 4316, "naklon": 0 }, +{ "label": "55/14", "node": 4322, "naklon": 0 }, +{ "label": "55/15", "node": 4331, "naklon": 0 }, +{ "label": "55/16", "node": 4321, "naklon": 0 }, +{ "label": "55/17", "node": 4315, "naklon": 0 }, +{ "label": "55/18", "node": 4329, "naklon": 0 }, +{ "label": "55/19", "node": 4334, "naklon": 0 }, +{ "label": "55/20", "node": 4330, "naklon": 0 } +]; + +module.exports = { naklony }; diff --git a/RVO45/databases/modbus_config.js b/RVO45/databases/modbus_config.js new file mode 100755 index 0000000..b73116a --- /dev/null +++ b/RVO45/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/RVO45/databases/nodes.table b/RVO45/databases/nodes.table new file mode 100755 index 0000000..4536208 --- /dev/null +++ b/RVO45/databases/nodes.table @@ -0,0 +1,46 @@ +node:number|pole_number:string|node_type:string|tbname:string|line:number|profile:string|processed:boolean|status:boolean|time_of_last_communication:number ++|4170|10|NEMA|gRoJEyXVx4qD9er287LPmL7wBzGldaPjLWQKm3Mv|1||1|1|1760574367511|............. ++|4422|25|NEMA|roKgWqY95V3mXMRzyAjmwr7bLjexpJPvaGDBw826|1||1|1|1760574205349|............. ++|4221|41|NEMA|zdQO8GwxDqjRgP4137Y1mG7NyKlpem2nL65rvVJY|1||1|1|1760574226561|............. ++|4242|3|NEMA|RO8rjaBDy21qPQJzW7oDXpApK3xmNleVZg9Ed4Gw|1||1|1|1760574200093|............. ++|4222|24|NEMA|E6Kg9oDnLWyzPRMva7vr1w7Jxp4VG58qO2w1lZYe|1||1|1|1760574226753|............. ++|4223|21|NEMA|PLBJzmK1r3Gynd6OW0gGam0e5wV4vx9bDEqNgYR8|1||1|1|1760574226945|............. ++|4243|26|NEMA|nJL5lPMwBx23YpqRe0rl6p7damXvWVbOrD4gNzy8|1||1|1|1760574251081|............. ++|4224|34|NEMA|52dD6ZlV1QaOpRBmbAqKlxkKnGzWMLj4eJq38Pgo|1||1|1|1760574227153|............. ++|4225|38|NEMA|nJL5lPMwBx23YpqRe0rl637damXvWVbOrD4gNzy8|1||1|1|1760574227328|............. ++|4244|17|NEMA|3a5oqJN1bgnx4Ol9dk86EzAByE6jQ8mKDWMpGrLV|1||1|1|1760574386057|............. ++|4245|6|NEMA|1JMYvnx2RzKEo4aWQ7DmzQAL8yZV3m9NBePXbrdj|1||1|1|1760574386281|............. ++|4226|2|NEMA|RvmwNz8QPblKp41GD7lDBn7JrLVYoBO92dMegn6W|1||1|1|1760574227504|............. ++|4246|12|NEMA|d9x2V5LGYBzXp4mMRAOBRX7PloaqJwnQj6DgrNe3|1||1|1|1760574067641|............. ++|4247|5|NEMA|Z5KyJe9nEg1QNbWlX0wW1N0oDjBLdqzR83VGv624|1||1|1|1760574205189|............. ++|2606|15|NEMA|ZmRwd93QL4gaezxEbAxWZe71prn2XjlPvGyqJ6BO|1||1|1|1760574205572|............. ++|4175|8|NEMA|dz4ojlpP85JMgDLZWkQOWrAaKYqQexEr62GXRV1y|1||1|1|1760574216850|............. ++|4227|14|NEMA|aw4eELG2DlPMdn1JW0B1WeAqQXOZRN3xB5yp8VKr|1||1|1|1760574318361|............. ++|4228|28|NEMA|eod9aRWLVl34Gx1Dn7VowPA2rz6qjgmpEXwQJN5Z|1||1|1|1760574227887|............. ++|4229|40|NEMA|gYbDLqlyZVoRerQpB72r2R7WJnwM5z24POKa8Exj|1||1|1|1760574229197|............. ++|4230|22|NEMA|52dD6ZlV1QaOpRBmbAqKgrkKnGzWMLj4eJq38Pgo|1||1|1|1760574229405|............. ++|4231|36|NEMA|nJL5lPMwBx23YpqRe0rln37damXvWVbOrD4gNzy8|1||1|1|1760574322802|............. ++|4232|35|NEMA|rDbQ84xzwgdqEoPm3kbJ3Lk9anOZY1RXyBv2LVM6|1||1|1|1760574323201|............. ++|4118|23|NEMA|rDbQ84xzwgdqEoPm3kbJ3Zk9anOZY1RXyBv2LVM6|1||1|1|1760574209310|............. ++|4234|30|NEMA|EjgWGnXaLy9opPOz20n6Mn086BlYM3w1deVQvbKr|1||1|1|1760574217968|............. ++|4235|31|NEMA|wvKJdZML6mXP4DzWBAXWzz7jxNloa5g23Ve9Y1ry|1||1|1|1760574219501|............. ++|4236|9|NEMA|d5xjWYMwEJon6rLlK7yBjXAqgV4DaOeNB9ZX3Gzb|1||1|1|1760573875703|............. ++|4237|1|NEMA|JX1ObgmqGZ54DMyYL7a9bK7EVdve38WKRzwjNrQ9|1||1|1|1760574330134|............. ++|4238|11|NEMA|K94XLav1glVRnyQ6r01B6Rkme3YJwBxM5oOzdP2j|1||1|1|1760573815211|............. ++|4239|19|NEMA|wvKJdZML6mXP4DzWBAXWlp7jxNloa5g23Ve9Y1ry|1||1|1|1760574247007|............. ++|4240|33|NEMA|PLBJzmK1r3Gynd6OW0gGjY0e5wV4vx9bDEqNgYR8|1||1|1|1760574199502|............. ++|4199|18|NEMA|EjgWGnXaLy9opPOz20n6nX086BlYM3w1deVQvbKr|1||1|1|1760574217408|............. ++|4200|27|NEMA|ZmRwd93QL4gaezxEbAxWRW71prn2XjlPvGyqJ6BO|1||1|1|1760574225763|............. ++|4203|32|NEMA|Nzp2OoJlqn6r1ZgvdA3GNYAabBwP5G4eE3RQmyxD|1||1|1|1760574225906|............. ++|4207|20|NEMA|Nzp2OoJlqn6r1ZgvdA3Gz5AabBwP5G4eE3RQmyxD|1||1|1|1760574170542|............. ++|4211|29|NEMA|3a5oqJN1bgnx4Ol9dk86GaAByE6jQ8mKDWMpGrLV|1||1|1|1760574226258|............. ++|4212|42|NEMA|WlVJBygjDZMeKX3vnAMzD208NqdmG2x1Y69LQ4P5|1||1|1|1760574226401|............. ++|4112|43|NEMA|5dBNwRp9graYJxZn409w6r7lVov1b2QLPDqGm6XK|1||1|1|1760574209134|............. ++|3864|44|NEMA|apKVJBwOyrP35m2lv7KznqkYXbeWNd64En9GxRqg|1||1|1|1760574205732|............. ++|3872|7|NEMA|PjLblDgRBO6WQqnxmkJ5Wm0Jv3ewZN4p5a89yKdY|1||1|1|1760574205924|............. ++|3872|98/1|NEMA-IP65|PjLblDgRBO6WQqnxmkJ5Wm0Jv3ewZN4p5a89yKdY|1||1|1|1760574205924|............. ++|4161|37|NEMA|roKgWqY95V3mXMRzyAjmw37bLjexpJPvaGDBw826|1||1|1|1760574209534|............. ++|4166|13|NEMA|B5EoxeMVp4zwr8nqW0GjWvARjvD1PNamOGbLg63Z|1||1|1|1760574209741|............. ++|4180|16|NEMA|eod9aRWLVl34Gx1Dn7VodyA2rz6qjgmpEXwQJN5Z|1||1|1|1760574217233|............. ++|4241|39|NEMA|XMBbew5z4ELrZa2mRAd5q108vPN6gy3DdVYlpKjq|1||1|1|1760574199678|............. ++|4179|4|NEMA|3JjOWdylwgNLzxVab7NE1xkZ2vG64rq8PEB5QmDo|1||1|1|1760574217025|............. diff --git a/RVO45/databases/nodes_original/nodes_original.table b/RVO45/databases/nodes_original/nodes_original.table new file mode 100755 index 0000000..6941bad --- /dev/null +++ b/RVO45/databases/nodes_original/nodes_original.table @@ -0,0 +1 @@ +[{"4170": "gRoJEyXVx4qD9er287LPmL7wBzGldaPjLWQKm3Mv"}, {"4422": "roKgWqY95V3mXMRzyAjmwr7bLjexpJPvaGDBw826"}, {"4221": "zdQO8GwxDqjRgP4137Y1mG7NyKlpem2nL65rvVJY"}, {"4242": "RO8rjaBDy21qPQJzW7oDXpApK3xmNleVZg9Ed4Gw"}, {"4222": "E6Kg9oDnLWyzPRMva7vr1w7Jxp4VG58qO2w1lZYe"}, {"4223": "PLBJzmK1r3Gynd6OW0gGam0e5wV4vx9bDEqNgYR8"}, {"4243": "nJL5lPMwBx23YpqRe0rl6p7damXvWVbOrD4gNzy8"}, {"4224": "52dD6ZlV1QaOpRBmbAqKlxkKnGzWMLj4eJq38Pgo"}, {"4225": "nJL5lPMwBx23YpqRe0rl637damXvWVbOrD4gNzy8"}, {"4244": "3a5oqJN1bgnx4Ol9dk86EzAByE6jQ8mKDWMpGrLV"}, {"4245": "1JMYvnx2RzKEo4aWQ7DmzQAL8yZV3m9NBePXbrdj"}, {"4226": "RvmwNz8QPblKp41GD7lDBn7JrLVYoBO92dMegn6W"}, {"4246": "d9x2V5LGYBzXp4mMRAOBRX7PloaqJwnQj6DgrNe3"}, {"4247": "Z5KyJe9nEg1QNbWlX0wW1N0oDjBLdqzR83VGv624"}, {"2606": "ZmRwd93QL4gaezxEbAxWZe71prn2XjlPvGyqJ6BO"}, {"4175": "dz4ojlpP85JMgDLZWkQOWrAaKYqQexEr62GXRV1y"}, {"4227": "aw4eELG2DlPMdn1JW0B1WeAqQXOZRN3xB5yp8VKr"}, {"4228": "eod9aRWLVl34Gx1Dn7VowPA2rz6qjgmpEXwQJN5Z"}, {"4229": "gYbDLqlyZVoRerQpB72r2R7WJnwM5z24POKa8Exj"}, {"4230": "52dD6ZlV1QaOpRBmbAqKgrkKnGzWMLj4eJq38Pgo"}, {"4231": "nJL5lPMwBx23YpqRe0rln37damXvWVbOrD4gNzy8"}, {"4232": "rDbQ84xzwgdqEoPm3kbJ3Lk9anOZY1RXyBv2LVM6"}, {"4118": "rDbQ84xzwgdqEoPm3kbJ3Zk9anOZY1RXyBv2LVM6"}, {"4234": "EjgWGnXaLy9opPOz20n6Mn086BlYM3w1deVQvbKr"}, {"4235": "wvKJdZML6mXP4DzWBAXWzz7jxNloa5g23Ve9Y1ry"}, {"4236": "d5xjWYMwEJon6rLlK7yBjXAqgV4DaOeNB9ZX3Gzb"}, {"4237": "JX1ObgmqGZ54DMyYL7a9bK7EVdve38WKRzwjNrQ9"}, {"4238": "K94XLav1glVRnyQ6r01B6Rkme3YJwBxM5oOzdP2j"}, {"4239": "wvKJdZML6mXP4DzWBAXWlp7jxNloa5g23Ve9Y1ry"}, {"4240": "PLBJzmK1r3Gynd6OW0gGjY0e5wV4vx9bDEqNgYR8"}, {"4199": "EjgWGnXaLy9opPOz20n6nX086BlYM3w1deVQvbKr"}, {"4200": "ZmRwd93QL4gaezxEbAxWRW71prn2XjlPvGyqJ6BO"}, {"4203": "Nzp2OoJlqn6r1ZgvdA3GNYAabBwP5G4eE3RQmyxD"}, {"4207": "Nzp2OoJlqn6r1ZgvdA3Gz5AabBwP5G4eE3RQmyxD"}, {"4211": "3a5oqJN1bgnx4Ol9dk86GaAByE6jQ8mKDWMpGrLV"}, {"4212": "WlVJBygjDZMeKX3vnAMzD208NqdmG2x1Y69LQ4P5"}, {"4112": "5dBNwRp9graYJxZn409w6r7lVov1b2QLPDqGm6XK"}, {"3864": "apKVJBwOyrP35m2lv7KznqkYXbeWNd64En9GxRqg"}, {"3872": "PjLblDgRBO6WQqnxmkJ5Wm0Jv3ewZN4p5a89yKdY"}, {"3872": "PjLblDgRBO6WQqnxmkJ5Wm0Jv3ewZN4p5a89yKdY"}, {"4161": "roKgWqY95V3mXMRzyAjmw37bLjexpJPvaGDBw826"}, {"4166": "B5EoxeMVp4zwr8nqW0GjWvARjvD1PNamOGbLg63Z"}, {"4180": "eod9aRWLVl34Gx1Dn7VodyA2rz6qjgmpEXwQJN5Z"}, {"4241": "XMBbew5z4ELrZa2mRAd5q108vPN6gy3DdVYlpKjq"}, {"4179": "3JjOWdylwgNLzxVab7NE1xkZ2vG64rq8PEB5QmDo"}] \ No newline at end of file diff --git a/RVO45/databases/notifications.table b/RVO45/databases/notifications.table new file mode 100755 index 0000000..f7c96cb --- /dev/null +++ b/RVO45/databases/notifications.table @@ -0,0 +1,41 @@ +key:string|weight:string|sk:string|en:string ++|switching_profile_point_applied_to_line|INFORMATIONAL|Aplikovaný bod spínacieho profilu na línií č. ${line} : ${value}|Switching profile point applied to line no. ${line} : ${value}|............... ++|dusk_has_occured|INFORMATIONAL|Nastal súmrak: ${value}|Dusk has occured: ${value}|............... ++|dawn_has_occured|INFORMATIONAL|Nastal úsvit: ${value}|Dawn has occured: ${value}|............... ++|dimming_profile_was_successfully_received_by_node|NOTICE|Stmievací profil bol úspešne prijatý nodom č. ${node}|Dimming profile was successfully received by node no. ${node}|............... ++|master_node_is_responding_again|NOTICE|Master node začal znovu odpovedať|Master node is responding again|............... ++|command_was_sent_from_terminal_interface|DEBUG|Z terminálu bol odoslaný príkaz|A command was sent from terminal interface|............... ++|master_node_is_not_responding|ALERT|Master node neodpovedá|Master node is not responding|............... ++|configuration_of_dimming_profile_to_node_failed|ALERT|Konfigurácia stmievacieho profilu pre node č. ${node} zlyhala|Configuration of dimming profile to node no. ${node} has failed|............... ++|circuit_breaker_was_turned_on_line|NOTICE|Zapnutie ističa na línii č. ${line}|Circuit breaker was turned on - line no. ${line}|............... ++|circuit_breaker_was_turned_off_line|ERROR|Vypnutie ističa na línií č. ${line}|Circuit breaker was turned off - line no. ${line}|............... ++|dimming_profile_was_processed_for_node|INFORMATIONAL|Stmievací profil bol spracovaný pre node č. ${node}|Dimming profile was processed for node no. ${node}|............... ++|switching_profile_was_processed_for_line|INFORMATIONAL|Spínací profil bol spracovaný pre líniu č. ${line}|Switching profile was processed for line no. ${line}|............... ++|thermometer_is_not_responding|WARNING|Teplomer neodpovedá|Thermometer is not responding|............... ++|thermometer_is_responding_again|NOTICE|Teplomer znovu odpovedá|Thermometer is responding again|............... ++|thermometer_sends_invalid_data|WARNING|Teplomer posiela neplatné hodnoty|Thermometer sends invalid data|............... ++|main_switch_has_been_turned_off|CRITICAL|Hlavný vypínač bol vypnutý|Main switch has been turned off|............... ++|main_switch_has_been_turned_on|NOTICE|Hlavný vypínač bol zapnutý|Main switch has been turned on|............... ++|power_supply_has_disconnected_input|ALERT|Napájací zdroj nemá napätie na vstupe|Power supply has disconnected input|............... ++|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_main_open|NOTICE|Hlavné dvere boli otvorené|Main door has been opened|............... ++|door_em_open|NOTICE|Dvere silovej časti boli otvorené|Power door has been opened|............... ++|door_main_open_without_permission|WARNING|Hlavné dvere boli otvorené bez povolenia - zapnutá siréna|Main door has been opened without permission - alarm is on|............... ++|door_em_open_without_permission|WARNING|Dvere silovej časti boli otvorené bez povolenia|Power door has been opened without permission|............... ++|door_main_close|NOTICE|Hlavné dvere boli zatvorené|Main door has been closed|............... ++|door_em_close|NOTICE|Dvere silovej časti boli zatvorené|Power door has been closed|............... ++|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|............... ++|electrometer_ok|NOTICE|Elektromer znovu odpovedá|Electrometer is responding again|............... ++|no_voltage_on_phase|CRITICAL|Na fáze č. ${phase} nie je napätie|No voltage detected on phase no. ${phase}|............... ++|voltage_on_phase_restored|NOTICE|Napätie na fáze č. ${phase} bolo obnovené|Voltage on phase no. ${phase} has been restored|............... ++|flow_start|NOTICE|FLOW bol spustený|FLOW has been started |............... ++|twilight_sensor_nok|ERROR|Sensor súmraku neodpovedá|Twilight sensor is not responding|............... ++|twilight_sensor_ok|NOTICE|Sensor súmraku znovu odpovedá|Twilight sensor is responding again|............... ++|lamps_have_turned_on|NOTICE|Lampy sa zapli|Lamps have turned on|............... ++|lamps_have_turned_off|NOTICE|Lampy sa vypli|Lamps have turned off|............... ++|flow_restart|NOTICE|FLOW bol reštartovaný|FLOW has been restarted|............... ++|nodes_db_changed|NOTICE|Zmena v node databáze|Node db has changed|............... diff --git a/RVO45/databases/pins.table b/RVO45/databases/pins.table new file mode 100755 index 0000000..100c15e --- /dev/null +++ b/RVO45/databases/pins.table @@ -0,0 +1,16 @@ +pin:string|type:string|line:number +*|input1_01|door_condition|0|........... +*|input1_02|rotary_switch_state|0|........... +*|input1_03|rotary_switch_state|0|........... +*|input1_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|........... +*|relay1_05|state_of_contactor|4|........... +*|relay1_06|state_of_contactor|5|........... +*|28F46E9D0E00008B|temperature|0|........... +*|twilight_sensor|twilight_sensor|0|........... diff --git a/RVO45/databases/relays.table b/RVO45/databases/relays.table new file mode 100755 index 0000000..2a5a227 --- /dev/null +++ b/RVO45/databases/relays.table @@ -0,0 +1,7 @@ +line:number|tbname:string|contactor:number|profile:string ++|0|JX1ObgmqGZ54DMyYL7aDzmkEVdve38WKRzwjNrQ9|1||........... ++|1|dz4ojlpP85JMgDLZWkQOvrAaKYqQexEr62GXRV1y|9|{"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":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|d5xjWYMwEJon6rLlK7yBKXAqgV4DaOeNB9ZX3Gzb|9|{"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":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|gRoJEyXVx4qD9er287LPGL7wBzGldaPjLWQKm3Mv|9|{"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":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}|............. ++|4|K94XLav1glVRnyQ6r01BjRkme3YJwBxM5oOzdP2j|9|{"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":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}|............. ++|5|d9x2V5LGYBzXp4mMRAOBNX7PloaqJwnQj6DgrNe3|9|{"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":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/RVO45/databases/settings.table b/RVO45/databases/settings.table new file mode 100755 index 0000000..428afe3 --- /dev/null +++ b/RVO45/databases/settings.table @@ -0,0 +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|project_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|cloud_topic:string|has_main_switch:boolean|daily_report:boolean|send_changed_node_numbers:boolean ++|rvo_senica_45_ip120|en|28.D1FA9C0E0000|48.70826502|17.28455203|192.168.252.1|rvo_senica_45_ip120|ka4qOer61XSgaEVfDq1N|1883|0|74|unipi|ttyUSB0|1|20|5|6|3|u120|0|1|1|................................................... diff --git a/RVO45/databases/tbdata.nosql b/RVO45/databases/tbdata.nosql new file mode 100755 index 0000000..0386396 --- /dev/null +++ b/RVO45/databases/tbdata.nosql @@ -0,0 +1,4 @@ +-"JX1ObgmqGZ54DMyYL7aDzmkEVdve38WKRzwjNrQ9":[{"ts":1760530985393,"values":{"_event":{"type":"notice","status":"new","source":{"func":"modbus_reader","component":"1699965957410","component_name":"Modbus reader","edge":"JX1ObgmqGZ54DMyYL7aDzmkEVdve38WKRzwjNrQ9"},"message":{"sk":"rvo_senica_45_ip120: FLOW bol reštartovaný","en":"rvo_senica_45_ip120: FLOW has been restarted"},"message_data":""}}}],"id":"3000323001tx71b"} +-"JX1ObgmqGZ54DMyYL7aDzmkEVdve38WKRzwjNrQ9":[{"ts":1760530985485,"values":{"edge_fw_version":"2025-10-08","maintenance_mode":false}}],"id":"3000323002tx70b"} +-"JX1ObgmqGZ54DMyYL7aDzmkEVdve38WKRzwjNrQ9":[{"ts":1760530985499,"values":{"statecode":2,"power_mode":"Automatic"}}],"id":"3000323004tx70b"} +-"JX1ObgmqGZ54DMyYL7aDzmkEVdve38WKRzwjNrQ9":[{"ts":1760530985560,"values":{"_event":{"type":"notice","status":"new","source":{"func":"rsPort.open()","component":"1699963668903","component_name":"DIDO_Controller","edge":"JX1ObgmqGZ54DMyYL7aDzmkEVdve38WKRzwjNrQ9"},"message":{"sk":"rvo_senica_45_ip120: FLOW bol spustený","en":"rvo_senica_45_ip120: FLOW has been started "},"message_data":""}}}],"id":"3000323006tx70b"} diff --git a/RVO45/databases/tbdatacloud.nosql b/RVO45/databases/tbdatacloud.nosql new file mode 100755 index 0000000..85e2ed8 --- /dev/null +++ b/RVO45/databases/tbdatacloud.nosql @@ -0,0 +1,3 @@ +-"JX1ObgmqGZ54DMyYL7aDzmkEVdve38WKRzwjNrQ9":[{"ts":1760530985485,"values":{"edge_fw_version":"2025-10-08","maintenance_mode":false}}],"id":"3000323003tx71b"} +-"JX1ObgmqGZ54DMyYL7aDzmkEVdve38WKRzwjNrQ9":[{"ts":1760530985499,"values":{"statecode":2,"power_mode":"Automatic"}}],"id":"3000323005tx71b"} +-"JX1ObgmqGZ54DMyYL7aDzmkEVdve38WKRzwjNrQ9":[{"ts":1760530985560,"values":{"_event":{"type":"notice","status":"new","source":{"func":"rsPort.open()","component":"1699963668903","component_name":"DIDO_Controller","edge":"JX1ObgmqGZ54DMyYL7aDzmkEVdve38WKRzwjNrQ9"},"message":{"sk":"rvo_senica_45_ip120: FLOW bol spustený","en":"rvo_senica_45_ip120: FLOW has been started "},"message_data":""}}}],"id":"3000323007tx71b"} diff --git a/RVO45/databases/total_energy.js b/RVO45/databases/total_energy.js new file mode 100755 index 0000000..dde340e --- /dev/null +++ b/RVO45/databases/total_energy.js @@ -0,0 +1,38 @@ +//key is rvo_number, value is max energy when lamps are on +const total_energy = { + 1: 580, + 2: 1100, + 3: 3700, + 4: 4100, + 7: 360, + 12: 1700, + 13: 5400, + 14: 440, + 15: 6100, + 16: 4800, + 20: 1600, + 21: 1000, + 22: 2600, + 23: 1000, + 25: 2600, + 33: 240, + 34: 4000, + 35: 2700, + 36: 820, + 37: 1400, + 35: 3500, + 39: 1170, + 41: 740, + 42: 660, + 43: 4900, + 45: 930, + 46: 700, + 47: 1100, + 48: 1500, + 50: 3200, + 53: 1250, + 55: 1000, + 56: 5500 +} + +module.exports = total_energy; diff --git a/RVO45/debug.js b/RVO45/debug.js new file mode 100755 index 0000000..9818194 --- /dev/null +++ b/RVO45/debug.js @@ -0,0 +1,16 @@ +// =================================================== +// FOR DEVELOPMENT +// Total.js - framework for Node.js platform +// https://www.totaljs.com +// =================================================== + +const options = {}; + +// options.ip = '127.0.0.1'; +// options.port = parseInt(process.argv[2]); +// options.config = { name: 'Total.js' }; +// options.sleep = 3000; +// options.inspector = 9229; +// options.watch = ['private']; + +require('total.js/debug')(options); \ No newline at end of file diff --git a/RVO45/err.txt b/RVO45/err.txt new file mode 100755 index 0000000..0b7751f --- /dev/null +++ b/RVO45/err.txt @@ -0,0 +1,34 @@ +[2024-12-09T09:03:13.330] [ERROR] errLogs - Thermometer Thermometer: temperatureAddress is not defined +[2025-09-23T14:02:50.338] [ERROR] errLogs - uncaughtException: Cannot read property 'getHours' of undefined +[2025-09-23T14:02:50.339] [ERROR] errLogs - TypeError: Cannot read property 'getHours' of undefined + at Timeout.emptyReportToSend [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:02:50.340] [ERROR] errLogs - uncaughtException: Cannot read property 'getHours' of undefined +[2025-09-23T14:02:50.341] [ERROR] errLogs - TypeError: Cannot read property 'getHours' of undefined + at Timeout.emptyReportToSend [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:02:50.350] [ERROR] errLogs - uncaughtException: Cannot read property 'getHours' of undefined +[2025-09-23T14:02:50.350] [ERROR] errLogs - TypeError: Cannot read property 'getHours' of undefined + at Timeout.emptyReportToSend [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:02:56.724] [ERROR] errLogs - uncaughtException: date.getHours is not a function +[2025-09-23T14:02:56.725] [ERROR] errLogs - TypeError: date.getHours is not a function + at emptyReportToSend (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at Timeout.dailyReportCheck [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1351:5) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:02:56.726] [ERROR] errLogs - uncaughtException: date.getHours is not a function +[2025-09-23T14:02:56.726] [ERROR] errLogs - TypeError: date.getHours is not a function + at emptyReportToSend (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at Timeout.dailyReportCheck [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1351:5) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:02:56.731] [ERROR] errLogs - uncaughtException: date.getHours is not a function +[2025-09-23T14:02:56.731] [ERROR] errLogs - TypeError: date.getHours is not a function + at emptyReportToSend (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at Timeout.dailyReportCheck [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1351:5) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) diff --git a/RVO45/flow/cloudmqttconnect.js b/RVO45/flow/cloudmqttconnect.js new file mode 100755 index 0000000..b03491f --- /dev/null +++ b/RVO45/flow/cloudmqttconnect.js @@ -0,0 +1,357 @@ +exports.id = 'cloudmqttconnect'; +exports.title = 'Cloud connect mqtt'; +exports.group = 'MQTT'; +exports.color = '#888600'; +exports.version = '1.0.2'; +exports.icon = 'sign-out'; +exports.input = 2; +exports.output = 2; +exports.options = { host: 'tb-stage.worksys.io', port: 1883, clientid: "", username: "" }; + +exports.html = `
+
+
+
Hostname or IP address (if not empty - setting will override db setting)
+
+
+
Port
+
+
+
+
+
@(Client id)
+
+
+
topic
+
+
+
`; + + + +const { promisifyBuilder } = require('./helper/db_helper'); +const fs = require('fs'); +const mqtt = require('mqtt'); +const nosql = NOSQL('tbdatacloud'); + +const SEND_TO = { + debug: 0, + rpcCall: 1, +} + +//CONFIG +let saveTelemetryOnError = true;//backup_on_failure overrides this value +//------------------------ + +const noSqlFileSizeLimit = 4194304;//use 5MB - 4194304 +let insertNoSqlCounter = 0; +let insertBackupNoSqlCounter = 0; +let processingData = false; + +let backup_on_failure = true;//== saveTelemetryOnError - create backup client send failure +let restore_from_backup = 50; //how many rows process at once? +let restore_backup_wait = 3;//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; + + +exports.install = function(instance) { + + var client; + var opts; + var clientReady = false; + + let o = {}; //options + + function main() { + loadSettings(); + } + + //set opts according to db settings + function loadSettings() { + + o = instance.options; + if (!o.topic) o.topic = FLOW.GLOBALS.settings.cloud_topic; + + opts = { + host: o.host, + port: o.port, + clientId: o.clientid, + username: o.username, + rejectUnauthorized: false, + resubscribe: false + }; + + console.log("wsmqttpublich -> loadSettings from instance.options", o); + + if (!o.topic) { + instance.status("Not configured", "white"); + console.log("Cloud mqtt connect: no topic selected"); + return; + } + + connectToTbServer(); + } + + function connectToTbServer() { + var url = "mqtt://" + opts.host + ":" + opts.port; + console.log("MQTT URL: ", url); + + client = mqtt.connect(url, opts); + + client.on('connect', function() { + client.subscribe(`${o.topic}_backward`, (err) => { + if (!err) { + console.log("MQTT subscribed"); + } + }); + instance.status("Connected", "green"); + clientReady = true; + sendClientError = true; + }); + + client.on('reconnect', function() { + instance.status("Reconnecting", "yellow"); + clientReady = false; + }); + + client.on('message', function(topic, message) { + // message is type of buffer + message = message.toString(); + if (message[0] === '{') { + TRY(function() { + + message = JSON.parse(message); + if (message.hasOwnProperty("device") && message.hasOwnProperty("data") && message.data.hasOwnProperty("id")) { + client.publish(`${o.topic}_forward`, `{"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 } }); + } + + }, () => instance.debug('MQTT: Error parsing data', message)); + } + + instance.send(SEND_TO.rpcCall, { "topic": o.topic, "content": message }); + }); + + client.on('close', function() { + clientReady = false; + + instance.status("Disconnected", "red"); + instance.send(SEND_TO.debug, { "message": "Client CLOSE signal received !" }); + }); + + client.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) { + console.log('MQTT client error', err); + sendClientError = false; + } + clientReady = false; + }); + + } + + + instance.on('0', function(data) { + + if (clientReady) { + //do we have some data in backup file? if any, process data from database + if (saveTelemetryOnError) { + //read telemetry data and send back to server + if (!processingData) processDataFromDatabase(); + } + + let stringifiedJson = JSON.stringify(data.data) + client.publish(`${o.topic}_forward`, stringifiedJson, { qos: 1 }); + } + 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 (saveTelemetryOnError && o.topic) { + //create new file from tbdata.nosql, if file size exceeds given limit, and clear tbdata.nosql + makeBackupFromDbFile(); + + //write to tb + data.data.id = UID(); + nosql.insert(data.data); + } + } + }); + + instance.on("1", _ => { + main(); + }) + + instance.close = function(done) { + if (clientReady) { + client.end(); + } + }; + + + function getDbBackupFileCounter(type) { + var files = fs.readdirSync(__dirname + "/../databases"); + + let counter = 0; + for (var i = 0; i < files.length; i++) { + + if (files[i] == "tbdatacloud.nosql") continue; + + if (files[i].endsWith(".nosql")) { + + let pos = files[i].indexOf("."); + if (pos > -1) { + + let fileCounter = counter; + let firstDigit = files[i].slice(0, pos); + + fileCounter = parseInt(firstDigit); + if (isNaN(fileCounter)) fileCounter = 0; + //console.log("getDbBackupFileCounter digit:", files[i], firstDigit, fileCounter, isNaN(fileCounter), type); + + if (type == "max") { + if (fileCounter > counter) { + counter = fileCounter; + } + } + else if (type == "min") { + if (counter == 0) counter = fileCounter; + + if (fileCounter < counter) { + counter = fileCounter; + } + } + } + } + + } + + if (type == "max") counter++; + + return counter; + } + + const makeBackupFromDbFile = async () => { + + if (!saveTelemetryOnError) return; + + //to avoid large file: tbdata.nosql + + //init value is 0! + if (insertNoSqlCounter > 0) { + --insertNoSqlCounter; + return; + } + + insertNoSqlCounter = 100; + + let source = __dirname + "/../databases/tbdatacloud.nosql"; + + var stats = fs.statSync(source); + var fileSizeInBytes = stats.size; + + if (fileSizeInBytes > noSqlFileSizeLimit) { + + let counter = 1; + counter = getDbBackupFileCounter("max"); + + let destination = __dirname + "/../databases/" + counter + "." + "tbdatacloud.nosql"; + + //make backup file + fs.copyFileSync(source, destination); + //fs.renameSync(p, p + "." + counter); + + //clear tbdata.nosql + fs.writeFileSync(source, ""); + fs.truncateSync(source, 0); + + } + } + + const processDataFromDatabase = async () => { + + if (restore_from_backup <= 0) return; + + //calculate diff + const now = new Date(); + let currentTime = now.getTime(); + let diff = currentTime - lastRestoreTime; + + if ((diff / 1000) < restore_backup_wait) { + //console.log("*********restore_backup_wait", diff, restore_backup_wait); + return; + } + + processingData = true; + + //get filename to process + let counter = getDbBackupFileCounter("min"); + + //we have some backup files + let dataBase = 'tbdata'; + + var nosql; + if (counter == 0) dataBase = 'tbdatacloud'; + else dataBase = counter + "." + 'tbdatacloud'; + + nosql = NOSQL(dataBase); + + //select all data - use limit restore_from_backup + let records = await promisifyBuilder(nosql.find().take(restore_from_backup)); + + for (let i = 0; i < records.length; i++) { + if (clientReady) { + + let item = records[i]; + let id = item.id; + + if (id !== undefined) { + //console.log("------------processDataFromDatabase - remove", id, dataBase, i); + + try { + + let message = JSON.parse(JSON.stringify(item)); + delete message.id; + client.publish(`${o.topic}_forward`, JSON.stringify(message), { qos: 1 }); + + //remove from database + await promisifyBuilder(nosql.remove().where("id", id)); + + } catch (error) { + //process error + console.log("processDataFromDatabase", error); + } + + } + + } + else { + processingData = false; + return; + } + } + + if (records.length > 0) { + //clean backup file + if (counter > 0) nosql.clean(); + } + + //no data in db, remove + if (records.length == 0) { + if (counter > 0) nosql.drop(); + } + + const d = new Date(); + lastRestoreTime = d.getTime(); + + processingData = false; + + } + + instance.on('options', main); + +}; diff --git a/RVO45/flow/cmd_manager.js b/RVO45/flow/cmd_manager.js new file mode 100755 index 0000000..25912df --- /dev/null +++ b/RVO45/flow/cmd_manager.js @@ -0,0 +1,3071 @@ +exports.id = 'cmd_manager'; +exports.title = 'CMD Manager'; +exports.group = 'Worksys'; +exports.color = '#5D9CEC'; +exports.version = '0.0.3'; +exports.output = ['red', 'blue', 'yellow', 'blue', 'white', 'green']; +exports.input = 3; +exports.icon = 'cloud-upload'; + +exports.html = ` +
+
+
+
RPC - run RPC calls

+
+
+
@(User)
+
+
+
@(Password)
+
+
+
@(My edge)
+
+
+
+`; +exports.readme = `Manager for CMD calls`; + + +exports.install = function(instance) { + + 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, isEmptyObject, emptyJsObject, writeToFile, addToArrayIfUnique } = require('./helper/utils'); + const bitwise = require('bitwise'); + + var SunCalc = require('./helper/suncalc'); + const DataToTbHandler = require('./helper/DataToTbHandler'); + const errorHandler = require('./helper/ErrorToServiceHandler'); + const { sendNotification } = require('./helper/notification_reporter'); + const process = require('process'); + const { errLogger, logger, monitor } = require('./helper/logger'); + + //for accelerometer purposes + const { naklony } = require("../databases/accelerometer_db"); + + const dbNodes = TABLE("nodes"); + const dbRelays = TABLE("relays"); + + let GLOBALS; + let SETTINGS; + let rsPort; + let tbHandler; + + // runTasks intervals + const SHORT_INTERVAL = 30; + const LONG_INTERVAL = 300; + + //send data to following instances: + const SEND_TO = { + debug: 0, + tb: 1, + http_response: 2, + dido_controller: 3, + infoSender: 4, + dailyReport: 5 + } + + 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 + } + + 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 sendNodeReadout = null; // interval for sending agregate data from node + + 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["1"] = minutes; // dimming + priorities["76"] = minutes; // power + + minutes = 5; + priorities["75"] = minutes; // current + priorities["79"] = minutes; // energy + priorities["87"] = minutes; // aktualny cas + //priorities["84"] = minutes; //accelerometer + + minutes = 10; + priorities["74"] = minutes; // voltage + priorities["77"] = minutes; // power factor + priorities["78"] = minutes; // frequency + + minutes = 60; + priorities["0"] = minutes; // statecode + priorities["6"] = minutes; // dusk + priorities["7"] = minutes; // dawn + priorities["8"] = minutes; // profile + + minutes = 60 * 24; + priorities["89"] = minutes; // verzia fw + priorities["80"] = minutes; // lifetime + + //prikazy kt sa budu spustat na dany node - see config.js in terminal-oms.app. (1 - dimming) + let listOfCommands = [0, 1, 6, 7, 8, 74, 75, 76, 77, 78, 79, 80, 87, 89]; + + 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; + + // holds dusk, dawn (and more) values + let sunCalcResult; + + //helper container for counting resolved group of commands (commands related to set profile) + let cmdCounter = {};//key is node, value is counter + + //TODO: is this set working?? According to previous checks, sets do not work + //if sending of profile to node fails, we send notification and push node into set, so we do not send notification twice + const nodeProfileSendFail = new Set(); + + //we expect to get current temperature in Senica from senica-prod01 + let temperatureInSenica = null; + let accelerometerInterval = null; + + //NOTE: daily reports senica: + //rvo_is_on status, we monitor all nodes - if true, power and dimming should be not 0, if false, 24/7 nodes should be 0, other rvo should not respond + let rvo_is_on; + let previous_rvo_is_on_value; + let handleDailyReport; //setInterval for dailyReportHandler function + let dailyReport = {}; //data needed for daily report + let reportToSend = {}; //final report which we send to cloud + let breakerCounter = null; // status of breakers after flow starts is not in report + let rvoPeriod; // interval of checking dusk dawn and if rvo_is_on + let initialReportStatus = false; + + const DAILY_REPORT_HANDLER_TIME = 3_600_000; + const SET_SUNCALC_RESULT_TIME = 3_600_000; + const SET_RVO_PERIOD_TIME = 300_000; + const ADD_NODE_TO_REPORT_TIME = 3_600_000; + + //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); + + let now = new Date(); + console.log("Cmd-mngr installed", now.toLocaleString("sk-SK")); + + sunCalcResult = calculateDuskDawn(); + + handleRsPort(); + + customTasksInterval = setInterval(reportEdgeDateTimeAndNumberOfLuminaires, 120_000); + setTimeout(reportEdgeDateTimeAndNumberOfLuminaires, 4000); + + //dailyReport related + emptyReportToSend(); + breakerCounter = Object.keys(relaysData).length - 1; // we get number of lines (breakers) except of line 0 + rvoPeriod = setInterval(setRvoPeriod, SET_RVO_PERIOD_TIME); + setTimeout(setRvoPeriod, 3000); + setInterval(setSunCalcResult, SET_SUNCALC_RESULT_TIME); + handleDailyReport = setInterval(dailyReportHandler, DAILY_REPORT_HANDLER_TIME); + + + setCorrectTime = setInterval(setCorrectPlcTimeOnceADay, 60000 * 60); // 1 hour + setCorrectPlcTimeOnceADay(); + + sendNodeReadout = setInterval(sendNodesData, 150_000); + accelerometerInterval = setInterval(accelerometerData, 60000 * 30); //30 min + } + + + 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" + //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 + // if node regular readout does not respond, we repeat request + params.repeatCounter = 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-mngr: 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.byte4 = 96; + params.recipient = 1; + params.register = 8; + params.rw = 1;//write + params.timestamp = timestamp; + 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.byte4 = 96; + params.recipient = 1; + params.register = 8; + params.rw = 1;//write + params.timestamp = timestamp; + 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). + */ + + 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.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.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 + { + + logger.debug("processNodeProfile: Threshold lux level for DUSK/DAWN", node); + + let params = getParams(); + params.type = "set_node_profile"; + params.address = node; + params.register = 96; + params.recipient = 1; + params.rw = 1;//write + params.timestamp = timestamp; + 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(); + params.type = "set_node_profile"; + params.address = node; + params.register = 97; + params.recipient = 1; + params.rw = 1;//write + params.timestamp = timestamp; + 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.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); + + 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); + + console.log("proces profile finished *********************") + } + + + 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; + }); + } + + + 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) { + for (let k in nodesData) { + 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`); + } + } + } + + + function loadRelaysData(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 (value.contactor == 1) processAllNodeProfilesOnLine(value.line); + } + } + + + function reportOnlineNodeStatus(line) { + //Po zapnutí línie broadcastovo aktualizovať predtým čas a o 3 sek neskor - status, brightness + + logger.debug("Cmd-mngr: ----->reportOnlineNodeStatus for line", line); + + const d = new Date(); + + // broadcast actual time + let params = getParams(); + params.address = 0xffffffff;//Broadcast + params.byte1 = d.getHours(); + params.byte2 = d.getMinutes(); + params.recipient = 2;//2 broadcast, address = 0 + params.register = 87;//Actual time + params.rw = 1;//write + params.type = "node-onetime-write"; + params.timestamp = d.getTime() + 30000; + params.info = "run broadcast: Actual time"; + //params.debug = true; + + tasks.push(params); + + let sec = 3; + setTimeout(function() { + //Po zapnutí línie - spraviť hromadný refresh stavu práve zapnutých svietidiel + + let time = Date.now(); + + for (let k in nodesData) { + + //potrebujem nody k danej linii + 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].node_status_before_offline === true || nodesData[k].status === true) { + status = "OK"; + nodesData[k].time_of_last_communication = time; + } + + nodesData[k].readout.status = status; + + updateNodeStatus(k, status === "OK" ? true : false); + if (nodesData[k].hasOwnProperty("node_status_before_offline")) delete nodesData[k].node_status_before_offline; + sendTelemetry({ status: status }, tbname, time); + + //vyreportovanie dimming, current, input power pre liniu pre vsetky nody + //Prud + { + let params = getParams(); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 75;//prud + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = time + 4000; + params.info = 'read current'; + //params.debug = true; + tasks.push(params); + } + + //vykon + { + let params = getParams(); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 76;//výkon + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = time + 4100; + params.info = 'read power'; + //params.debug = true; + + tasks.push(params); + } + //dimming + { + let params = getParams(); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 1;//dimming + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = time + 4200; + params.info = 'read dimming'; + //params.debug = true; + + tasks.push(params); + } + + } + } + + }, sec * 1000); + } + + + function reportOfflineNodeStatus(line) { + + logger.info("Cmd-mngr: ------>reportOffLineNodeStatus for line ", line); + + values = {}; + values["dimming"] = 0;//brightness + values["power"] = 0;//výkon + values["current"] = 0;//prúd + values["status"] = "OFFLINE"; + + const date = Date.now(); + + Object.keys(nodesData).forEach(node => { + + //potrebujem nody k danej linii + if (line == nodesData[node].line || line == undefined) { + + let tbname = nodesData[node].tbname; + let nodeStatus = nodesData[node].status; + + //in case we have reported offline node status, we return (continue with next node) + if (nodeStatus === "OFFLINE") return; + + nodesData[node].node_status_before_offline = nodeStatus; + nodesData[node].status = "OFFLINE"; + nodesData[node].readout = {}; + + sendTelemetry({ ...values }, tbname, date); + } + }); + + } + + + function turnLine(onOrOff, line, info) { + let obj = { + line: line, + command: onOrOff, + info: info + }; + + //to assure, handleDailyReportFunction do not run before rvo_is_on variable changes. So after every line switch we reset the timer + clearInterval(handleDailyReport); + handleDailyReport = setInterval(dailyReportHandler, DAILY_REPORT_HANDLER_TIME); + + //logger.debug("linia", line, obj); + instance.send(SEND_TO.dido_controller, obj); + } + + + 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"; + 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]) { + //CRC_ERROR + message = "NOK"; + error = "CRC_ERROR c1"; + instance.send(SEND_TO.debug, "CRC_ERROR c1"); + } + + 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") { + instance.send(SEND_TO.debug, bytes); + instance.send(SEND_TO.debug, "RESPONSE " + type + " - " + bytes[4]); + + //logger.debug(SEND_TO.debug, "RESPONSE " + type + " - " + bytes[4], bytes); + + error = "type is: " + type; + + message = "NOK"; + } + + return { message, type, error }; + } + + + //BUILD TASKS// + function buildTasks(params) { + + //return; + console.log("buidTAaasks start ****************", params); + monitor.info("buildTasks - params", params); + + let processLine; //defined line + let init = false; + let processLineProfiles = true; + let processBroadcast = true; + let processNodes = true; + + if (params == undefined) { + init = true; + tasks = []; + logger.debug("-->buildTasks clear tasks"); + } + else { + processLineProfiles = params.processLineProfiles; + processBroadcast = false; + processNodes = false; + + processLine = params.line; + } + + let now = new Date(); + + //process line profiles + if (processLineProfiles) { + + let keys = Object.keys(relaysData); + + for (let i = 0; i < keys.length; i++) { + + let line = parseInt(keys[i]); + let profilestr = relaysData[line].profile; + + if (processLine != undefined) { + if (processLine != line) continue; + } + + try { + + /** + * we process line profiles: timepoints, astro clock, lux_sensor, offsets ... + */ + if (profilestr === "") throw ("Profile is not defined"); + let profile = JSON.parse(profilestr); + 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; + + // add name to regular profile timepoint and delete unused end_time key: + time_points.forEach(point => { + point.name = "profileTimepoint" + delete point.end_time; + }); + + //monitor.info("buildTasks: time_points", time_points); + + + /** + * 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 astro clock true, we remove all regular profile points + time_points = []; + + //TODO: when astro clock == true, is offset calculated ??? + //let duskAstroClockOffset = profile.dusk_astro_clock_offset; + //let dawnAstroClockOffset = profile.dawn_astro_clock_offset; + //console.log("line astro clock offsets dusk a dawn: ", duskAstroClockOffset, dawnAstroClockOffset); + // maybe add dusk dawn offset to calculateDuskDawn ?? what dusk dawn will be if dawn_lux_sensor == true?? + //let sunCalcResult = calculateDuskDawn(new Date(), line, duskAstroClockOffset, dawnAstroClockOffset); + + 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 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); + + 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); + + 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(':'); + + let ad = new Date(); + ad.setHours(parseInt(ahours), parseInt(aminutes), 0); + + let bd = new Date(); + bd.setHours(parseInt(bhours), parseInt(bminutes), 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++) { + + let start_time = new Date(); + let [hours, minutes] = time_points[t].start_time.split(':'); + start_time.setHours(parseInt(hours), parseInt(minutes), 0); + + //task is in 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(); + params.type = "relay"; + params.line = parseInt(line); + params.value = time_points[t].value; + params.tbname = relaysData[line].tbname; + params.timestamp = start_time.getTime(); + + // 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; + + //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)) { + 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; + + params.debug = true; + + //turn on/off line + tasks.push(params); + monitor.info("TimePoint params: ", params.info, start_time); + } + + monitor.info("-->time_points final", line, time_points); + + //ensure to turn on/off according to calculated currentValue + let params = getParams(); + params.type = "relay"; + params.line = parseInt(line); + params.tbname = relaysData[line].tbname; + params.value = currentValue; + params.timestamp = i; + params.debug = true; + + //logger.debug(now.toLocaleString("sk-SK")); + 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; + + tasks.push(params); + + } catch (error) { + if (profilestr !== "") { + //errLogger.error(profilestr, error); + console.log(`Cmd_mngr: Unable to process line profile ${line}. Error: `, error); + errorHandler.sendMessageToService(profilestr + "-" + error, 0, "js_error"); + } else { + turnLine("off", line, "No line profile. Switching it off on startup"); + } + } + + } + //logger.debug("tasks:"); + //logger.debug(tasks); + } + + + //NOTE: PROCESS DEFAULT BROADCASTS - Time of dusk, Time of dawn, Actual Time + if (processBroadcast) { + + let d = new Date(); + let time = d.getTime(); + //let sunCalcResult = calculateDuskDawn(); + + { + let params = getParams(); + + params.address = 0xffffffff;//broadcast + params.byte1 = sunCalcResult["dusk_hours"]; + params.byte2 = sunCalcResult["dusk_minutes"]; + params.recipient = 2;//2 broadcast, + params.register = 6;//Time of dusk + params.rw = 1;//write + params.type = "node-regular-write"; + params.timestamp = time + 60000; + params.addMinutesToTimestamp = 60 * 3; //kazde 3 hodiny zisti novy dusk + params.info = "Broadcast-duskTime"; + + tasks.push(params); + } + + { + let params = getParams(); + + params.address = 0xffffffff;//broadcast + params.byte1 = sunCalcResult["dawn_hours"]; + params.byte2 = sunCalcResult["dawn_minutes"]; + params.recipient = 2; //2 broadcast + params.register = 7;//Time of dawn + params.rw = 1;//write + params.type = "node-regular-write"; + params.timestamp = time + 60001; + params.addMinutesToTimestamp = 60 * 3; //kazde 3 hodiny zisti novy dawn + params.info = "Broadcast-dawnTime"; + + tasks.push(params); + } + + { + let params = getParams(); + + params.address = 0xffffffff;//broadcast + params.byte1 = d.getHours(); + params.byte2 = d.getMinutes(); + params.recipient = 2; //2 broadcast + params.register = 87;//Actual time + params.rw = 1;//write + params.type = "node-regular-write"; + params.timestamp = time + 60002; + params.addMinutesToTimestamp = 5; + params.info = "run broadcast: Actual time"; + + tasks.push(params); + } + + } + + //process nodes & tasks - read node's data + if (processNodes) { + + let time = Date.now(); + + for (let k in nodesData) { + let address = parseInt(k); + let tbname = nodesData[k].tbname; + let register = 0; + + for (let i = 0; i < listOfCommands.length; i++) { + + register = listOfCommands[i]; + let addMinutesToTimestamp = priorities[register]; + + let params = getParams(); + + params.address = address; + params.recipient = 1; + params.register = register; + params.type = register == 1 ? "node-dimming-read" : "node-regular-read"; + params.tbname = tbname; + params.timestamp = time + 5000 + i * 500 + addMinutesToTimestamp * 1000; //to make slight time difference + params.addMinutesToTimestamp = addMinutesToTimestamp; + params.info = "Node regular read command"; + + tasks.push(params); + } + + } + } + + + //niektore ulohy sa vygeneruju iba 1x pri starte!!! + if (!init) return; + + + //Master node FW version - modifies SETTINGS.masterNodeIsResponding + { + let params = getParams(); + params.type = "cmd-master"; + params.register = 4; + params.address = 0; + params.timestamp = 0; + params.addMinutesToTimestamp = 5; + params.tbname = SETTINGS.rvoTbName; + params.info = "Master node FW verzia"; + //params.debug = true; + + tasks.push(params); + } + + //kazdu hodinu skontrolovat nastavenie profilov + { + let params = getParams(); + params.type = "process_profiles"; + params.timestamp = Date.now() + 60001; + params.addMinutesToTimestamp = 60;//60 = every hour + params.info = "detekcia nespracovaných profilov linie a nodov"; + //params.debug = true; + + tasks.push(params); + } + + monitor.info("tasks created:", tasks.length); + } + + + /** + * We process line profile, where "astro_clock": true + * example profile: + * + "dawn_lux_sensor": true, + "dusk_lux_sensor": true, + "dawn_lux_sensor_value": 5, + "dusk_lux_sensor_value": 5, + "dawn_astro_clock_offset": 0, + "dusk_astro_clock_offset": 10, + "dawn_lux_sensor_time_window": 30, + "dusk_lux_sensor_time_window": 30, + "dawn_astro_clock_time_window": 60, + "dusk_astro_clock_time_window": 60 + + * if dawn: if currentTimestamp is in timewindow "dawnTime + and - dawn_lux_sensor_time_window" and lux value >= lux_sensor_value, we switch off the line. + * if dusk: we do oposite + * + * dawn: usvit - lux je nad hranicou - vypnem + * dusk: sumrak - lux je pod hranicou - zapnem + */ + 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++) { + + let line = keys[i]; //line is turned off by default + let profilestr = relaysData[line].profile; + const contactor = relaysData[line].contactor; + + try { + + let profile = JSON.parse(profilestr); + if (Object.keys(profile).length === 0) throw ("turnOnOffLinesAccordingToLuxSensor - profile is not defined"); + + 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 (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"); + } + } + } + + //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 (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"); + } + } + } + + } + + } catch (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) { + //MASTER + if (node == 0) return; + + let nodeObj = nodesData[node]; + if (nodeObj == undefined) return; + + let nodeCurrentStatus = nodeObj.status; + const now = Date.now(); + + let data = null; + + if (nodeCurrentStatus === "OFFLINE") { + data = { status: newStatus }; + nodeDbStatusModify(node, data); + return; + } + else 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; + } + + } + + + 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 }; + } + }); + }); + } + + + function processDailyReport() { + + const now = Date.now(); + + for (const [key, value] of Object.entries(dailyReport)) { + + if (["name", "time", "dusk_and_dawn"].includes(key)) continue; + + let poleNumber = nodesData[key]["pole_number"]; + let line = dailyReport[key].line; + let nodeType = nodesData[key]["node_type"]; + let fullNodeName = key // key == nodeNumber + + if (poleNumber && nodeType) { + fullNodeName = SETTINGS.rvo_number + "/" + poleNumber + "_" + line + "L_" + key + "_" + nodeType; + } else { + fullNodeName = key; + } + + if (rvo_is_on) { + + if (value.initialTs) { + if (value.initialTs + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["night_no_data"], fullNodeName); + console.log('report nedostava ziadne data uz hodinu', fullNodeName); + value.initialTs = now; + } + } + if (value.dimmingIsZeroTime) { + if (value.dimmingIsZeroTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["night_dimming=0"], fullNodeName); + console.log("report node dimming je 0 ale ma svietit", fullNodeName); + value.dimmingIsZeroTime = now; + } + } + if (value.powerIsZeroTime) { + if (value.powerIsZeroTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["night_power=0"], fullNodeName); + console.log("report node power je 0 ale ma svietit", fullNodeName); + value.powerIsZeroTime = now; + } + } + + } else { + + let contactorStatus = relaysData[line].contactor; + if (contactorStatus === 1) { + + if (value.initialTs) { + if (value.initialTs + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["day_24/7_no_data"], fullNodeName); + console.log('node je na 24/7 ale nedostava ziadne data uz hodinu', fullNodeName); + value.initialTs = now; + } + } + if (value.dimmingIsOnButShouldBeOffTime) { + if (value.dimmingIsOnButShouldBeOffTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["day_24/7_dimming>0"], fullNodeName); + console.log("report dimming je > 0 ale nema svietit", fullNodeName); + value.dimmingIsOnButShouldBeOffTime = now; + } + } + if (value.powerIsOnButShouldBeOffTime) { + if (value.powerIsOnButShouldBeOffTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["day_24/7_power>0"], fullNodeName); + console.log("report power je > 0 ale nema svietit", fullNodeName); + value.powerIsOnButShouldBeOffTime = now; + } + } + + } + + } + + } + + let report = {}; + report["name"] = SETTINGS.rvo_name; + report["time"] = new Date(); + report["report"] = reportToSend; + + writeToFile(F.path.root("report_data.log"), report, true); + instance.send(SEND_TO.dailyReport, report); + } + + + function dailyReportHandler() { + + if (!SETTINGS.daily_report) return; + + // after dawn we empty reportToSend and start to get data for a new day + const date = new Date(); + const hour = date.getHours(); + const minute = date.getMinutes(); + + console.log("now: ", hour, minute, "suncalc: ", sunCalcResult.dawn_hours, sunCalcResult.dawn_minutes); + + if (hour === sunCalcResult.dawn_hours) { + + //NOTE: ak je este pred usvitom, spracujeme report a posleme na cloud, ak uz je po usvite, resetujeme report plnime data noveho dna + if (minute >= sunCalcResult.dawn_minutes - 2) { + emptyReportToSend(); + emptyDailyReport(); + console.log("Podmienka 1 v dailyReport handler"); + } else { + processDailyReport(); + emptyReportToSend(); + emptyDailyReport(); + console.log("Podmienka 2 v dailyReport handler"); + } + + initialReportStatus = true; + + // ak sa funkcia spusti o hodinu alebo 2 neskor, ako je usvit (moze sa to stat, kedze kazde zapnutie/vypnutie linii odznova spusti casovac. + } else if (hour === sunCalcResult.dawn_hours + 1 || hour === sunCalcResult.dawn_hours + 2) { + if (!initialReportStatus) { + emptyReportToSend(); + emptyDailyReport(); + initialReportStatus = true; + console.log("Podmienka 3 v dailyReport handler"); + } else { + processDailyReport(); + initialReportStatus = true; + console.log("Podmienka 4 v dailyReport handler"); + } + } else { + processDailyReport(); + initialReportStatus = false; + console.log("Podmienka 5 v dailyReport handler"); + } + + console.log("initialReportStatus: ", initialReportStatus); + + } + + function emptyReportToSend() { + emptyJsObject(reportToSend); + reportToSend["contactor"] = { off: [], on: [] }; + reportToSend["night_no_data"] = []; + reportToSend["night_dimming=0"] = []; + reportToSend["night_power=0"] = []; + reportToSend["day_24/7_no_data"] = []; + reportToSend["day_24/7_dimming>0"] = []; + reportToSend["day_24/7_power>0"] = []; + console.log(`resetuje sa reportToSend`); + } + + + //NOTE: ked je initialTs stale rovnaky a zistime ze linie su vypnute (relaysData.line.contactor) - zistim, ci je node na tej linii. Vieme, ze ak je linia vypnuta je to v poriadku lebo nie je na 24/7 linii + //ak je na 24/7 linii, reportujeme, ze neprijima data + function emptyDailyReport() { + const ts = Date.now(); + emptyJsObject(dailyReport); + + //NOTE: do dailyReport dame vsetky nody a pravidelne kontrolujeme ci maju data + //ked nastane sumrak/usvit a svetla maju zacat/prestat svietit, dailyReport spravime nanovo: + for (const [key, value] of Object.entries(nodesData)) { + dailyReport[value.node] = { line: value.line, initialTs: ts }; + } + + console.log("dailyReport: ", dailyReport); + } + + + async function runTasks() { + + clearInterval(interval); + + let currentTimestamp = Date.now(); + + //sort tasks based on timestamp + 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) { + instance.send(SEND_TO.debug, "no tasks created"); + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + if (!rsPort.isOpen) { + instance.send(SEND_TO.debug, "!rsPort.isOpen"); + //await rsPort.open(); + //console.log("Cmd-mngr: !rsPort.isOpen"); + } + + let currentTask = tasks[0]; + + if (currentTask.debug) { + //logger.debug("--->task to process", currentTask); + } + + if (currentTask.timestamp <= currentTimestamp) { + let params = { ...tasks[0] }; + + //allow terminal commands + if (SETTINGS.maintenance_mode && params.type !== "cmd-terminal") { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + let type = params.type; + let tbname = params.tbname; + let node = params.address; + let register = params.register; + let line = null; + let itIsNodeCommand; + + if (nodesData[node] !== undefined) { + line = nodesData[node].line; + itIsNodeCommand = true; + } + + if (params.line !== undefined) line = params.line; + + if (params.addMinutesToTimestamp > 0 || params.timePointName) { + tasks[0].timestamp = currentTimestamp + tasks[0].addMinutesToTimestamp * 60000; + } else { + tasks.shift(); + } + + //kontrola nespracovanych profilov nodov + //TODO: co ked niektore nody neprijimaju profily? kazdu hodinu zahltuju "tasks" array + if (type == "process_profiles") { + //na vsetky zapnutych liniach sa spracuju nespracovane profily nodov + loadRelaysData(); + interval = setInterval(runTasks, SHORT_INTERVAL); + return; + } + + //relay + if (type == "relay") { + + const timePointName = params.timePointName; + const value = params.value; + + let date = new Date(); + date.setDate(date.getDate() + 1);//next day + + let sunCalcResult; + if (timePointName) sunCalcResult = calculateDuskDawn(date, params.line); + + + if (timePointName == "dawn") { + tasks[0].timestamp = sunCalcResult.dawn_time; + } + else if (timePointName == "dusk") { + tasks[0].timestamp = sunCalcResult.dusk_time; + } + else if (timePointName == "luxOn") { + tasks[0].timestamp = sunCalcResult.dusk_time + params.dusk_lux_sensor_time_window * 60000; + } + else if (timePointName == "luxOff") { + tasks[0].timestamp = sunCalcResult.dawn_time + params.dawn_lux_sensor_time_window * 60000; + } + else if (timePointName == "profileTimepoint") { + tasks[0].timestamp = currentTimestamp + tasks[0].addMinutesToTimestamp * 60000; + } + + let info = "aplikovany bod profilu"; + let onOrOff = ""; + value == 1 ? onOrOff = "on" : onOrOff = "off"; + + turnLine(onOrOff, params.line, info); + + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + if (!SETTINGS.masterNodeIsResponding) { + //ak neodpoveda, nebudeme vykonavat ziadne commands, okrem cmd-terminal cmd-master + errorHandler.sendMessageToService("Master node is not responding"); + + let stop = true; + + if (type === "cmd-terminal" || type === "cmd-master") stop = false; + if (stop) { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + } + + let contactorStatus = 1; + if (relaysData[line] != undefined) contactorStatus = relaysData[line].contactor; + + if (line === 0 || contactorStatus === 0 || FLOW.deviceStatus.state_of_breaker[line] === "Off") { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + // TODO: -> status offline for rvo if rotary_switch_state is OFF, this is source of errors + // check if rotary_switch_state == "Off" + // state_of_braker: disconnected = true? + + if (!rsPort.isOpen) { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + //RE-CALCULATE VALUES + //set actual time for broadcast + if (register == 87 && params.recipient === 2) { + var d = new Date(); + params.byte1 = d.getHours();//h + params.byte2 = d.getMinutes();//m + } + + //SET DUSK/DAWN FOR BROADCAST + //Time of dusk + if (register == 6 && params.recipient === 2) { + + if (type != "cmd-terminal") { + params.byte1 = sunCalcResult["dusk_hours"];//h + params.byte2 = sunCalcResult["dusk_minutes"];//m + } + } + + //Time of dawn + if (register == 7 && params.recipient === 2) { + if (type != "cmd-terminal") { + params.byte1 = sunCalcResult["dawn_hours"];//h + params.byte2 = sunCalcResult["dawn_minutes"];//m + } + } + //----------------------- + + instance.send(SEND_TO.debug, "address: " + node + " register:" + register + "type: " + type); + + var startTime, endTime; + startTime = new Date(); + + let saveToTb = true; + if (!tbname) saveToTb = false; + + let resp = com_generic(node, params.recipient, params.rw, register, params.name, params.byte1, params.byte2, params.byte3, params.byte4); + let readBytes = 11; + let timeout = 4000; + + + // await keyword is important, otherwise incorrect data is returned! + await writeData(rsPort, resp, readBytes, timeout).then(function(data) { + + //sometimes happens, that status of node changes to OK, NOK even if line was turned off and should be status OFFLINE. To prevent this, we return if line contactor is 0: + if (itIsNodeCommand && line && relaysData[line].contactor !== 1) return; + + 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); + + //ak sa odpoved zacina 0 - je to v poriadku, inak je NOK + let message = result.message; // OK, NOK + let message_type = result.type; + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + console.log("detected response:", result); + logger.debug("Cmd-mngr: writeData done " + message_type + " duration: " + timeDiff + " type: " + params.debug, params, result); + } + } + + let values = {}; + + //CMD FINISHED + if (message == "OK") { + + updateNodeStatus(node, true); + + //write + if (type == "set_node_profile") { + let result = cmdCounterResolve(node); + if (result == 0) { + dbNodes.modify({ processed: true }).where("node", node).make(function(builder) { + builder.callback(function(err, response) { + + sendNotification("Cmd-mngr: process cmd", SETTINGS.rvoTbName, "dimming_profile_was_successfully_received_by_node", { node: node }, "", SEND_TO.tb, instance); + + logger.debug("--> profil úspešne odoslaný na node č. " + node); + nodesData[node].processed = true; + nodeProfileSendFail.delete(node); + }); + }); + } + } + + //parse read response + if (params.rw == 0) { + values = processResponse(register, dataBytes); //read + } + + if (itIsNodeCommand) { + values.comm_status = "OK"; + values.status = "OK"; + nodesData[node].readout = { ...nodesData[node].readout, ...values }; + + + if (SETTINGS.daily_report) { + //TODO: co ak nedostavame odpovede z nodu ? Musime vyreportovat!! + //v dailyReport teda musi byt kompletny zoznam nodov a neustale kontrolovat, ci maju data, ak nie report node - neodpoveda + if (register === 1) { + + let now = Date.now(); + + if (rvo_is_on === true) { + + if ("dimmingIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].dimmingIsOnButShouldBeOffTime; + + if (values.dimming > 0) { + if ("dimmingIsZeroTime" in dailyReport[node]) delete dailyReport[node].dimmingIsZeroTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if (!("dimmingIsZeroTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], dimmingIsZeroTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } else { + + if ("dimmingIsZeroTime" in dailyReport[node]) delete dailyReport[node].dimmingIsZeroTime; + + if (values.dimming > 0) { + if (!("dimmingIsOnButShouldBeOffTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], dimmingIsOnButShouldBeOffTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if ("dimmingIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].dimmingIsOnButShouldBeOffTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } + } + + if (register === 76) { + + let now = Date.now(); + + if (rvo_is_on === true) { + + if ("powerIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].powerIsOnButShouldBeOffTime; + + if (values.power > 1) { + if ("powerIsZeroTime" in dailyReport[node]) delete dailyReport[node].powerIsZeroTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if (!("powerIsZeroTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], powerIsZeroTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } else { + + if ("powerIsZeroTime" in dailyReport[node]) delete dailyReport[node].powerIsZeroTime; + + if (values.power > 1) { + if (!("powerIsOnButShouldBeOffTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], powerIsOnButShouldBeOffTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if ("powerIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].powerIsOnButShouldBeOffTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } + } + } + + } + + //master node + if (node == 0) { + sendNotification("Cmd-mngr: 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; + } + + if (params.debug) { + //logger.debug("saveToTb", saveToTb, tbname, values); + } + + if (saveToTb && type != "node-regular-read") { + sendTelemetry(values, tbname); + } + else { + if (type == "cmd-terminal") { + terminalCommandResponse(params, "SUCCESS", data); + } + } + + } + else { + terminalCommandResponse(params, "ERROR", data); + handleNokResponseOnRsPort("handleNOK else block", params, itIsNodeCommand, saveToTb); + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + //logger.debug("writeData err: ", error, result, params); + logger.debug("writeData err: ", tbname, node, register, values); + } + } + + //logger.debug(error, result, params); + } + }).catch(function(reason) { + + //console.log("writeData catch exception", reason); + instance.send(SEND_TO.debug, reason); + + terminalCommandResponse(params, "FAILURE", null, reason); + handleNokResponseOnRsPort("handleNOK catch block", params, itIsNodeCommand, saveToTb); + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + logger.debug("-->WRITE FAILED: " + reason, params.debug, params); + } + } + + }); + + } + 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); + } + + + // if node does not respond to request, we repeat request 3 times: + function repeatCommand(params) { + params.repeatCounter++; + if (params.repeatCounter < 4) { + params.timestamp = 0; + params.addMinutesToTimestamp = 0; + tasks.push(params); + } + } + + function handleNokResponseOnRsPort(message, params, itIsNodeCommand, saveToTb) { + + let node = params.address; + let register = params.register; + let type = params.type; + let tbName = params.tbname; + if (!tbName) return; + + let values = {}; + + let updateStatus = updateNodeStatus(node, false); + + if (itIsNodeCommand) { + values.comm_status = "NOK"; + nodesData[node].readout.comm_status = "NOK"; + repeatCommand(params); + } + + if (updateStatus) { + values.status = "NOK"; + nodesData[node].readout.status = "NOK"; + } + + if (type === "node-regular-read") return; + + //master node + if (node == 0) { + sendNotification("Cmd-mngr: 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; + + if (register == 4) values["master_node_version"] = "NOK"; + } + + if (type == "set_node_profile") { + delete cmdCounter[node]; + logger.debug("profil nebol úspešne odoslaný na node č. ", params); + + if (!nodeProfileSendFail.has(node)) { + sendNotification("Cmd-mngr: process cmd", tbName, "configuration_of_dimming_profile_to_node_failed", { node: node }, "", SEND_TO.tb, instance); + nodeProfileSendFail.add(node); + } + } + + // console.log("------",node, register, type, itIsNodeCommand, updateStatus, saveToTb, values); + if (saveToTb) { + sendTelemetry(values, tbName); + } + + } + + + function sendNodesData() { + Object.keys(nodesData).forEach(node => { + if (nodesData[node]["status"] !== "OFFLINE") { + sendTelemetry(nodesData[node].readout, nodesData[node].tbname); + nodesData[node].readout = {}; + } + }) + } + + + /** + * 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; + } + + 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); + + //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 === "OFFLINE") { + nodeObj.node_status_before_offline === true ? number_of_ok_luminaires++ : number_of_nok_luminaires++; + } + else if (nodeObj.status == true) 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 - ts % 60000 //round to full minute + }; + + sendTelemetry(values, SETTINGS.rvoTbName, ts); + } + + + function setSunCalcResult() { + //if next day, we get new dusk and dawn. To make sure, in local timezone 2:00 means 00:00 in utc (it means next day) + if (new Date().getHours() === 2) { + sunCalcResult = calculateDuskDawn(); + console.log("Novy suncalc: ", sunCalcResult); + } + } + + + function setRvoPeriod() { + + if (!SETTINGS.daily_report) return; + + const ts = Date.now(); + + previous_rvo_is_on_value = rvo_is_on; + + if (ts < sunCalcResult.dawn_time - 1_800_000) { // nodes should be on (00:00 -> 06:00 ( - pol hodina, lebo rvo vypina skor) + rvo_is_on = true; + } else if (sunCalcResult.dawn_time - 1_800_000 < ts && ts < sunCalcResult.dusk_time + 1_800_000) { // nodes should be off 06:00 -> 21:00 + rvo_is_on = false; + } else if (sunCalcResult.dusk_time + 1_800_000 < ts) { // nodes should be on 21:00 -> 00:00 + rvo_is_on = true; + } + + if (previous_rvo_is_on_value !== rvo_is_on) { + emptyDailyReport(); + console.log("rvo_is: ", rvo_is_on, previous_rvo_is_on_value); + } + } + + + function handleRsPort() { + + if (rsPort) { + rsPort.removeAllListeners(); + rsPort = null; + } + + //! 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-mngr: rsPort opened success"); + + 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); + + }).catch(function(reason) { + instance.send(SEND_TO.debug, "Cmd-mngr: RPC runSyncExec - promise rejected:" + reason); + }); + }); + + rsPort.on('error', function(err) { + errorHandler.sendMessageToService([exports.title, "unable to open port", SETTINGS.serial_port, err.message], 0); + monitor.info("Cmd-mngr: Error on rsPort", err.message); + }); + + rsPort.on("close", () => { + monitor.info("Cmd-mngr: rsPort closed, reconnecting..."); + setTimeout(handleRsPort, 1000); + }); + + rsPort.open(); + } + + + instance.on("close", () => { + clearInterval(interval); + clearInterval(customTasksInterval); + clearInterval(setCorrectTime); + clearInterval(sendNodeReadout); + clearInterval(accelerometerInterval); + rsPort.close(); + }); + + instance.on("0", _ => { + main(); + }) + + + instance.on("2", _ => { + console.log("dailyReport, reportToSend, rvo_is_on", dailyReport, reportToSend, rvo_is_on, previous_rvo_is_on_value); + }) + + instance.on("1", 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(); + return; + } + else if (flowdata.data == "close") { + rsPort.close(); + return; + } + else if (flowdata.data == "clean") { + tasks = []; + return; + } + else if (flowdata.data == "buildtasks") { + //build & run + return; + } + else if (flowdata.data == "run") { + //durations = []; + + if (tasks.length == 0) { + + buildTasks(); + + if (rsPort.isOpen) { + interval = setInterval(runTasks, 100); + } + else { + instance.send(SEND_TO.debug, "port is not opened!!!"); + } + } + } + else { + //terminal data - object + //logger.debug("flowdata", flowdata.data); + + if (typeof flowdata.data === 'object') { + //logger.debug("dido", flowdata.data); + if (flowdata.data.hasOwnProperty("sender")) { + //data from dido_controller + if (flowdata.data.sender == "dido_controller") { + + if (flowdata.data.hasOwnProperty("cmd")) { + let cmd = flowdata.data.cmd; + + if (cmd == "buildTasks") { + clearInterval(interval); + + logger.debug("-->Cmd-mngr: BUILD TASKS"); + buildTasks(); + + //logger.debug("tasks:"); + //logger.debug(tasks); + + logger.debug("-->Cmd-mngr: RUN TASKS"); + interval = setInterval(runTasks, 5000); + } + else if (cmd == "reload_relays") { + loadRelaysData(flowdata.data.line); + + if (flowdata.data.dataChanged) { + if (!flowdata.data.value) { + reportOfflineNodeStatus(flowdata.data.line); + } + else { + reportOnlineNodeStatus(flowdata.data.line); + } + } + + } + else if (cmd == "rotary_switch_state") { + let value = flowdata.data.value; + + //state was changed + if (rotary_switch_state != value) { + if (value == "Off") { + //vyreportovat vsetky svietdla + reportOfflineNodeStatus(); + } + + rotary_switch_state = value; + } + } + 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) { + + // we send lux_sensor value to all nodes: + let params = getParams(PRIORITY_TYPES.node_broadcast); + + params.recipient = 2;//2 broadcast, address = 0 + params.address = 0xffffffff;//Broadcast + + let ba = longToByteArray(lux_sensor); + + params.byte3 = ba[1];//msb + params.byte4 = ba[0]; + params.timestamp = PRIORITY_TYPES.node_broadcast; + params.info = "run broadcast: Actual Lux level from cabinet"; + params.register = 95;//Actual Lux level from cabinet + params.rw = 1;//write + + tasks.push(params); + + //process profiles + turnOnOffLinesAccordingToLuxSensor(lux_sensor); + } + } + else if (cmd == "state_of_breaker") { + //istic linie + + breakerCounter--; + + let value = flowdata.data.value; + let line = parseInt(flowdata.data.line); + + let dataChanged = false; + if (state_of_breaker[line] != value) dataChanged = true; + + state_of_breaker[line] = value; + + let status = "OK"; + if (value == "Off") status = "NOK"; + + if (dataChanged) { + + if (relaysData.hasOwnProperty(line)) { + let tbname = relaysData[line].tbname; + + if (value == "Off") { + sendNotification("Cmd-mngr: onData", tbname, "circuit_breaker_was_turned_off_line", { line: line }, "", SEND_TO.tb, instance, "circuit_breaker"); + if (breakerCounter < 0) reportToSend["contactor"]["off"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + else { + sendNotification("Cmd-mngr: onData", tbname, "circuit_breaker_was_turned_on_line", { line: line }, "", SEND_TO.tb, instance, "circuit_breaker"); + if (breakerCounter < 0) reportToSend["contactor"]["on"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + + //report status liniu + sendTelemetry({ status: status }, tbname) + + //current value + if (value == "Off") reportOfflineNodeStatus(line); //vyreportovat vsetky svietidla na linii + } + + } + } + else { + logger.debug("undefined cmd", cmd); + } + } + } + + return; + } + + //data from worksys + if (flowdata.data.hasOwnProperty("topic")) { + + let data = getNested(flowdata.data, "content", "data"); + + //if we get temperature in senica from senica-prod01 + let temperature = getNested(flowdata.data, "content", "senica_temperature"); + + if (temperature !== undefined) { + temperatureInSenica = temperature; + return; + } + + if (data === undefined) { + console.log("Invalid rpc command came from platform"); + return; + } + + let command = data.params.command; + let method = data.method; + let profile = data.params.payload; + if (profile == undefined) profile = ""; + let entity = data.params.entities[0]; + let entity_type = entity.entity_type; + let tbname = entity.tb_name; + + instance.send(SEND_TO.debug, flowdata.data); + 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") { + + //let command = data.params.command; + let value = data.params.payload.value; + + if (command == "dimming") { + + let nodeWasFound = false; + let keys = Object.keys(nodesData); + + //logger.debug("-----", keys); + + 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); + + value = parseInt(value); + if (value > 0) value = value + 128; + + params.type = "node-onetime-write"; + params.tbname = tbname; + params.address = node; + params.register = 1; + params.recipient = 1; + params.byte4 = value; + params.rw = 1; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'set dimming from platform'; + //params.debug = true; + + //debug(params); + logger.debug("dimming", params); + + tasks.push(params); + + 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); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 1; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read dimming (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + //pridame aj vyreportovanie - vykon + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 76; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read Input Power (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + //pridame aj vyreportovanie - prud svietidla + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 75; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read Input Current (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + //pridame aj vyreportovanie - power faktor - ucinnik + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 77; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read power factor (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + }, 4000); + + nodeWasFound = true; + break; + } + } + + if (!nodeWasFound) { + logger.debug("set dimming from platform", "unable to find tbname", tbname); + } + } + else { + instance.send(SEND_TO.debug, "undefined command " + command); + logger.debug("undefined command", command); + } + + return; + } + 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++) { + let node = keys[i]; + if (tbname == nodesData[node].tbname) { + + 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"); + + //profil úspešne prijatý pre node č. xx + sendNotification("Cmd-mngr", tbname, "dimming_profile_was_processed_for_node", { node: node }, profile, SEND_TO.tb, instance); + + nodesData[node].processed = false; + nodesData[node].profile = profile; + + processNodeProfile(node); + }); + }); + } + } + } + else { + + instance.send(SEND_TO.debug, "unknown method " + method); + logger.debug("unknown method", method); + + return; + } + } + + //nastav profil linie z platformy + 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") { + + 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++) { + let line = keys[i]; + if (tbname == relaysData[line].tbname) { + //zmazeme tasky + 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) { + + //update profile + logger.debug("worksys - update relay profile done:", profile); + instance.send(SEND_TO.debug, "worksys - update relay profile done"); + + relaysData[line].profile = profile; + + loadRelaysData(line) + logger.debug("loadRelaysData DONE for line", line); + + buildTasks({ processLineProfiles: true, line: line }); + + sendNotification("Cmd-mngr: set profile from worksys", tbname, "switching_profile_was_processed_for_line", { line: line }, profile, SEND_TO.tb, instance); + }); + }); + break; + } + } + } + else if (method == "set_command") { + let value = data.params.payload.value; + + 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; + + 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"); + if (line != 0) reportToSend["contactor"]["off"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + else { + turnLine("on", line, "command received from platform"); + if (line != 0) reportToSend["contactor"]["on"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + } + } + else { + instance.send(SEND_TO.debug, "undefined method " + method); + logger.debug("undefined method", method); + } + + return; + } + else { + instance.send(SEND_TO.debug, "UNKNOW entity_type " + entity_type); + logger.debug("UNKNOW entity_type", entity_type); + } + return; + } + + //terminal + if (!rsPort.isOpen) await rsPort.open(); + + let params = flowdata.data.body; + if (params == undefined) { + //logger.debug("Cmd-mngr: flowdata.data.body is undefined"); + return; + } + + params.priority = PRIORITY_TYPES.terminal; + params.type = "cmd-terminal"; + params.tbname = ""; + params.timestamp = PRIORITY_TYPES.terminal; + params.addMinutesToTimestamp = 0;// do not repeat task!!! + params.debug = true; + + let timestamp = Date.now(); + params.refFlowdataKey = timestamp; + //params.refFlowdata = flowdata; + //refFlowdata = flowdata; + + //console.log("flowdata", flowdata); + + cleanUpRefFlowdataObj(); + + refFlowdataObj[timestamp] = flowdata; + + //fix + //params.address = params.adress; + logger.debug("received from terminal", params); + logger.debug("date/time:", new Date()); + logger.debug("tasks length:", tasks.length); + + //tasks = []; + + //add to tasks + tasks.push(params); + + } + } + }) + + + //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) + } + + + /** + * 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; + + RESTBuilder.make(function(builder) { + + if (!builder) return; + + builder.method('GET'); + builder.url('http://192.168.252.2:8004/gettime?projects_id=1'); + + builder.callback(function(err, response, output) { + + 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); + } + + }); + } + + } 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); + + } else { + //console.log("Read-only", stdout); + + 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]: [ + { + "ts": date, + "values": values + } + ] + } + + tbHandler.sendToTb(dataToTb, instance); + } + + + function calculateDuskDawn(date, line, duskOffset = 0, dawnOffset = 0) { + + if (date === undefined) date = new Date(); + + 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); + } + + //if(profile.dawn_lux_sensor == false) + { + if (profile.hasOwnProperty("dawn_astro_clock_offset")) dawn_astro_clock_offset = parseInt(profile.dawn_astro_clock_offset); + } + + } + + } catch (error) { + if (profilestr != "") { + logger.debug(profilestr); + logger.debug(error); + } + } + + 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; + } + + //Dimming, CCT + else if (register == 1) { + let brightness = 0; + let dimming = byte0; + if (dimming > 128) { + //dimming = -128; + brightness = dimming - 128; + } + + //cct + //Ak Byte3 == 1: CCT = (Byte2*256)+Byte1 + let cct; + if (byte3 == 1) cct = byte2 * 256 + byte1; + else cct = bytesToInt(bytes.slice(0, 3)); + + //cct podla auditu + + values["dimming"] = brightness; + return values; + } + + // + else if (register == 4) { + values["master_node_version"] = bytes[1] + "." + bytes[2]; + //logger.debug("FW Version", register, bytes); + } + + //Napätie + else if (register == 74) { + let voltage = (bytesToInt(bytes) * 0.1).toFixed(1); + values["voltage"] = Number(voltage); + } + + //Prúd + else if (register == 75) { + let current = bytesToInt(bytes); + values["current"] = current; + } + + //výkon + else if (register == 76) { + let power = (bytesToInt(bytes) * 0.1).toFixed(2); + values["power"] = Number(power); + } + + //účinník + else if (register == 77) { + let power_factor = Math.cos(bytesToInt(bytes) * 0.1 * (Math.PI / 180)).toFixed(2); + values["power_factor"] = Number(power_factor); + } + + //frekvencia + else if (register == 78) { + let frequency = (bytesToInt(bytes) * 0.1).toFixed(2); + values["frequency"] = Number(frequency); + } + + //energia + else if (register == 79) { + let energy = bytesToInt(bytes); + values["energy"] = energy / 1000; //energia v kWh -> delit 1000 + } + + //doba života + else if (register == 80) { + let lifetime = (bytesToInt(bytes) / 60).toFixed(2); + values["lifetime"] = Number(lifetime); + } + + //nastavenie profilu + else if (register == 8) { + let time_schedule_settings = bytesToInt(bytes); + values["time_schedule_settings"] = time_schedule_settings; + } + + //naklon - nateraz sa z nodu nevycitava! kvoli problemom s accelerometrom a vracanymi hodnotami, posielame temp a x y z vo funkcii accelerometerData() + else if (register == 84) { + values["temperature"] = byte3 >= 128 ? (byte3 - 128) * (-1) : byte3; + values["inclination_x"] = byte2 >= 128 ? (byte2 - 128) * (-1) : byte2; + values["inclination_y"] = byte1 >= 128 ? (byte1 - 128) * (-1) : byte1; + values["inclination_z"] = byte0 >= 128 ? (byte0 - 128) * (-1) : byte0; + } + + //FW verzia nodu + else if (register == 89) { + //formát: "Byte3: Byte2.Byte1 (Byte0)" + values["fw_version"] = byte3 + ":" + byte2 + "." + byte1 + "(" + byte0 + ")"; + } + + else if (register == 87 || register == 6 || register == 7) { + var d = new Date(); + d.setHours(byte3, byte2, 0, 0); + let timestamp = d.getTime(); + + //aktuálny čas + if (register == 87) values["actual_time"] = timestamp; + //čas súmraku + else if (register == 6) values["dusk_time"] = timestamp; + //čas úsvitu + else if (register == 7) values["dawn_time"] = timestamp; + } + + 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; + + } + + + function getObjectByTbValue(object, tbname) { + return object[Object.keys(object).find(key => object[key].tbname === tbname)]; + } + + + function isObject(item) { + return (typeof item === "object" && !Array.isArray(item) && item !== null); + } + + + // we fake data, that should be received from accelerometer, as they are a bit unreliable. (temperature, x,y,z) + function accelerometerData() { + + if (temperatureInSenica === null) return; + + //clone nodesData and relaysData objects + let nodesData_clone = JSON.parse(JSON.stringify(nodesData)); + let relaysData_clone = JSON.parse(JSON.stringify(relaysData)); + + for (const key in relaysData_clone) { + + const lineData = relaysData_clone[key]; + const lineNumber = lineData.line; + const contactor = lineData.contactor; + + if (lineNumber === 0) continue; + + if (contactor === 1) { + + let date = Date.now(); + + Object.keys(nodesData_clone).forEach((node, index) => { + + setTimeout(function() { + + if (nodesData_clone[node].line === lineNumber) { + + // NOTE: if status of luminaire is NOK or OFFLINE, we do not send data; + let status = nodesData_clone[node].status; + if (status === "OFFLINE" || !status) return; + + let x = null; + if (naklony.hasOwnProperty(node)) x = naklony[node].naklon; + if (x === null) x = 0; + + sendTelemetry({ temperature: Math.round(temperatureInSenica + 10 + Math.floor(Math.random() * 3)), inclination_x: x, inclination_y: 0, inclination_z: 0 }, nodesData_clone[node].tbname, date); + } + + }, (index + 1) * 500); + }) + + } + } + } + + +} // end of instance.export + diff --git a/RVO45/flow/code.js b/RVO45/flow/code.js new file mode 100755 index 0000000..63b31bf --- /dev/null +++ b/RVO45/flow/code.js @@ -0,0 +1,90 @@ +exports.id = 'code'; +exports.title = 'Code'; +exports.group = 'Common'; +exports.color = '#656D78'; +exports.input = true; +exports.output = 1; +exports.author = 'Peter Širka'; +exports.icon = 'code'; +exports.version = '1.2.0'; +exports.options = { outputs: 1, code: 'send(0, value);', keepmessage: true }; + +exports.html = `
+
+
+
@(Number of outputs)
+
@(Minimum is 1)
+
+
+
@(Code)
+
@(Keep message instance)
+
+`; + +exports.readme = `# Code + +This component executes custom JavaScript code as it is and it doesn't contain any secure scope. + +\`\`\`javascript +// value {Object} contains received data +// send(outputIndex, newValue) sends a new value +// error(value) sends an error +// instance {Object} a current component instance +// flowdata {Object} a current flowdata +// repository {Object} a current repository of flowdata +// Example: + +// send() can be execute multiple times +send(0, value); +\`\`\``; + +exports.install = function(instance) { + + var fn; + + instance.on('data', function(response) { + if (fn) { + try { + fn(response.data, instance, response, instance.options, response.repository, require); + } catch (e) { + response.data = e; + instance.throw(response); + } + } + }); + + instance.reconfigure = function() { + try { + if (instance.options.code) { + instance.status(''); + var code = 'var send = function(index, value) { if (options.keepmessage) { flowdata.data = value; instance.send2(index, flowdata); } else instance.send2(index, value);}; var error = function(err) { instance.throw(err); }; ' + instance.options.code; + fn = new Function('value', 'instance', 'flowdata', 'options', 'repository', 'require', code); + } else { + instance.status('Not configured', 'red'); + fn = null; + } + } catch (e) { + fn = null; + instance.error('Code: ' + e.message); + } + }; + + instance.on('options', instance.reconfigure); + instance.reconfigure(); +}; \ No newline at end of file diff --git a/RVO45/flow/comment.js b/RVO45/flow/comment.js new file mode 100755 index 0000000..1e0cd13 --- /dev/null +++ b/RVO45/flow/comment.js @@ -0,0 +1,11 @@ +exports.id = 'comment'; +exports.title = 'Comment'; +exports.group = 'Common'; +exports.color = '#704cff'; +exports.author = 'Martin Smola'; +exports.icon = 'comment'; +exports.traffic = false; +exports.version = '1.0.0'; +exports.readme = '# Comment'; + +exports.install = function() {}; diff --git a/RVO45/flow/count.js b/RVO45/flow/count.js new file mode 100755 index 0000000..fa92ee9 --- /dev/null +++ b/RVO45/flow/count.js @@ -0,0 +1,60 @@ +exports.id = 'count'; +exports.title = 'Count'; +exports.version = '1.0.1'; +exports.author = 'John Graves'; +exports.color = '#656D78'; +exports.icon = 'plus-square'; +exports.input = 2; +exports.output = 1; +exports.options = { increment: 1, initialvalue: 1 }; +exports.readme = `# Counter + +Counter Number of times called.`; + +exports.html = `
+
@(Initial Value)
+
@(Increment)
+

Example Video

+
`; + +exports.readme = `# Count + +This component counts the number of messages received. + +__Response:__ + +Integer value based on the initial value and increment settings. + +__Arguments:__ +- Initial Value: What number should be output on the receipt of the first message. +- Increment: What should the increment be for each following message received.`; + +exports.install = function(instance) { + + var count = 0; + var initialCall = true; + + instance.on('data', function(flowdata) { + var index = flowdata.index; + if (index) { + instance.debug('Reset Count.'); + count = instance.options.initialvalue; + initialCall = true; + } else { + // If this is the first time, set the value to 'initial value' + if(initialCall) { + initialCall = false; + count = instance.options.initialvalue; + } else + count = count+instance.options.increment; + instance.status('Count:' + count); + instance.send2(count); + } + }); + + instance.on('options', function() { + count = instance.options.initialvalue; + initialCall = true; + }); + +}; diff --git a/RVO45/flow/db_connector.js b/RVO45/flow/db_connector.js new file mode 100755 index 0000000..65ee94b --- /dev/null +++ b/RVO45/flow/db_connector.js @@ -0,0 +1,286 @@ +exports.id = 'db_connector'; +exports.title = 'DbConnector'; +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.html = `
+
+
+
DbConnector
+
+
+
`; + +exports.readme = `# read/write data to tables`; + +const instanceSendTo = { + debug: 0, + http_response: 1, +} + +const { promisifyBuilder, makeMapFromDbResult } = require('./helper/db_helper.js'); + +function extractWhereParams(params) +{ + let name = params[0]; + let operator = '='; + let value = params[1]; + + if(params.length == 3) + { + operator = params[1]; + value = params[2]; + } + + return {name: name, operator: operator, value: value}; +} + +exports.install = function(instance) { + + let refFlowdata = null;//holds reference to httprequest flowdata + + instance.on("close", () => { + + }) + + + instance.on("data", async function(flowdata) { + + let params = flowdata.data.body; + console.log("DbConnector", params); + + refFlowdata = flowdata; + + if(refFlowdata != undefined) + { + //make http response + let responseObj = {}; + responseObj["type"] = "SUCESS"; + + try{ + + let table = params.table; + let action = params.action; + + + if(params.data != undefined) + { + let className = params.data.className; + + if(className == "SqlQueryBuilder") + { + let type = params.data.type; + + console.log("SqlQueryBuilder---->", params.data); + + if(type == "SELECT") + { + let table = params.data.queryData.tables[0].table; + + const db = TABLE(table); + var builder = db.find(); + + let result = await promisifyBuilder(builder); + + let response = {}; + response["result"] = result; + response["success"] = true; + + responseObj["data"] = response; + + //console.log(responseObj); + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + } + + return; + } + } + + + console.log("db_connector---->", table, action); + + //actions: read, replace, insert, delete, update... + + if(action == "read") + { + const db = TABLE(params.table); + + //where builder.where('age', '<', 15); + //builder.where('id', 3403); + + var builder = db.find(); + + //https://docs.totaljs.com/latest/en.html#api~DatabaseBuilder~builder.where + if(params.hasOwnProperty("where")) + { + //optionalCan contain "=", "<=", "<", ">=", ">". + //Default value: '=' + + //1.["production_line", 1] + //2. ["or", ["production_line", 1], ["production_line", 2], "end"] + + if (Array.isArray(params.where)) { + + let multipleConditions = false; + + if(params.where[0] == "or") multipleConditions = true; + if (Array.isArray(params.where[0])) multipleConditions = true; + + if(multipleConditions) + { + + for(var i = 0; i < params.where.length; i++) + { + const item = params.where[i]; + + if(item === "or") builder.or(); + + if (Array.isArray(item)) + { + const { name, operator, value } = extractWhereParams(item); + builder.where(name, operator, value); + } + + if(item === "end") builder.end(); + + } + + } + else + { + const { name, operator, value } = extractWhereParams(params.where); + builder.where(name, operator, value); + } + + } + + /* + if(params.where.length >=2 ) + { + let name = params.where[0]; + let operator = '='; + let value = params.where[1]; + + if(params.where.length == 3) + { + operator = params.where[1]; + value = params.where[2]; + } + + builder.where(name, operator, value); + } + */ + } + + if(params.hasOwnProperty("between")) + { + builder.between(params.between[0], params.between[1], params.between[2]); + } + + let response = await promisifyBuilder(builder); + responseObj["data"] = response; + + //console.log(responseObj); + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + + return; + } + + if(action == "delete") + { + + } + + + if(action == "update") + { + //! data receiving from terminal (params) + // { + // hostname: 'localhost', + // table: 'settings', + // action: 'update', + // body: { + // rvo_name: 'terrrr', + // lang: 'en', + // temperature_adress: '28.427B45920702', + // latitude: 48.70826502, + // longitude: 17.28455203, + // mqtt_host: '192.168.252.4', + // mqtt_clientid: 'showroom_test_panel_led', + // mqtt_username: 'xmRd6RJxW53WZe4vMFLU', + // mqtt_port: 1883, + // maintanace_mode: false + // } + // } + const tableToModify = TABLE(params.table); + const newValues = params.body; + + tableToModify.modify(newValues).make(function(builder) { + + builder.callback(function(err, response) { + + if(!err) + { + responseObj["data"] = response; + responseObj["tableUpdated"] = true; + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + } + }); + }); + + } + + if(action == "replace") + { + //truncate table + const db = TABLE(params.table); + var builder = db.remove(); + db.clean(); + + //insert data + let data = params.data; + + for(let i = 0; i < data.length; i++) + { + //console.log(data[i]); + db.insert(data[i]); + } + + console.log("insert done"); + + let responseObj = {}; + responseObj["type"] = "SUCESS"; + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + + + } + + + + } catch (error) { + //console.log(error); + responseObj["type"] = "ERROR"; + responseObj["message"] = error; + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + } + } + }) +} + + diff --git a/RVO45/flow/db_init.js b/RVO45/flow/db_init.js new file mode 100755 index 0000000..b399878 --- /dev/null +++ b/RVO45/flow/db_init.js @@ -0,0 +1,113 @@ +exports.id = 'db_init'; +exports.title = 'DB Initialization'; +exports.group = 'Worksys'; +exports.color = '#888600'; +exports.version = '1.0.2'; +exports.icon = 'sign-out'; +exports.output = 2; + +exports.readme = ` + # DB initialization +`; + +const { promisifyBuilder, makeMapFromDbResult } = require('./helper/db_helper.js'); +const { initNotification } = require('./helper/notification_reporter'); +const errorHandler = require('./helper/ErrorToServiceHandler'); +const total_energy = require('../databases/total_energy'); + +const SEND_TO = { + db_init: 0, + infoSender: 1 +}; + + +exports.install = async function(instance) { + const dbNodes = TABLE("nodes"); + const dbRelays = TABLE("relays"); + const dbSettings = TABLE("settings"); + 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 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.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"]; + Object.keys(dbs.nodesData).forEach(node => dbs.nodesData[node].readout = {}) + + let rvo_number = responseSettings[0]["rvo_name"].match(/\D+(\d{1,2})_/)[1]; + + dbs.settings = { + edge_fw_version: "2025-10-08", //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"], + phases: responseSettings[0]["phases"], + cloud_topic: responseSettings[0]["cloud_topic"], + has_main_switch: responseSettings[0]["has_main_switch"], + daily_report: responseSettings[0]["daily_report"], + send_changed_node_numbers: responseSettings[0]["send_changed_node_numbers"], + rvo_number: rvo_number, + + //dynamic values + masterNodeIsResponding: true, //cmd_manager + maintenance_mode: false, + } + + + dbs.settings.energy_to_switch_lamps = total_energy[rvo_number]; + if (dbs.settings.energy_to_switch_lamps === undefined) console.log('=============== db_init.js: energy_to_switch_lamps is undefined'); + + FLOW.dbLoaded = true; + errorHandler.setProjectId(dbs.settings.project_id); + initNotification(); + + //APP START - send to data services + const toService = { + id: dbs.settings.project_id, + name: dbs.settings.rvo_name, + fw_version: dbs.settings.edge_fw_version, + startdate: new Date().toISOString().slice(0, 19).replace('T', ' '), + js_error: "", + error_message: "" + }; + + instance.send(SEND_TO.infoSender, toService); + console.log("----------------> START - message send to service", toService); + + setTimeout(() => { + console.log("DB_INIT - data loaded"); + instance.send(SEND_TO.db_init, "_") + }, 5000) + +}; + diff --git a/RVO45/flow/debug.js b/RVO45/flow/debug.js new file mode 100755 index 0000000..00cb259 --- /dev/null +++ b/RVO45/flow/debug.js @@ -0,0 +1,100 @@ +exports.id = 'debug'; +exports.title = 'Debug'; +exports.author = 'Peter Širka'; +exports.color = '#967ADC'; +exports.click = true; +exports.input = true; +exports.icon = 'bug'; +exports.version = '2.0.4'; +exports.options = { enabled: true, repository: false, type: 'data' }; +exports.readme = `# Debug + +Prints data to the debug tab.`; + +exports.html = `
+
+
+
@(Output type)
+
@(Path to the property (leave empty to show the whole data object))
+
@(A group name)
+
@(Enabled)
+
+
+
`; + +exports.install = function(instance) { + + instance.on('data', function(response) { + if (instance.options.enabled) { + + var opt = instance.options; + var rep = response.repository; + var val = response.data; + var id = response.id; + + switch (instance.options.type){ + case 'both': + var data = {}; + data.repository = rep; + data.data = val instanceof Error ? { error: val.message, stack: val.stack } : val; + instance.debug(safeparse(opt.property ? U.get(data, opt.property) : data), undefined, opt.group, id); + break; + case 'repository': + instance.debug(safeparse(opt.property ? U.get(rep, opt.property) : rep), undefined, opt.group, id); + break; + case 'data': + default: + if (val instanceof Error) + instance.debug({ error: val.message, stack: val.stack }, undefined, opt.group, id); + else + instance.debug(safeparse(opt.property ? U.get(val, opt.property) : val), undefined, opt.group, id); + break; + } + } + }); + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + instance.save(); + }); + + instance.on('options', function() { + instance.custom.status(); + }); + + instance.custom.status = function() { + instance.status(instance.options.enabled ? 'Enabled' : 'Disabled'); + }; + + instance.custom.status(); + + function safeparse(o) { + + if (o instanceof Buffer) + return o; + + if (o === undefined) + return 'undefined'; + + if (o === null) + return 'null'; + + var cache = []; + var str = JSON.stringify(o, function(key, value) { + if (typeof value === 'object' && value !== null) { + if (cache.indexOf(value) !== -1) { + try { + return JSON.parse(JSON.stringify(value)); + } catch (error) { + return; + } + } + cache.push(value); + } + return value; + }); + cache = null; + return JSON.parse(str); + } +}; diff --git a/RVO45/flow/designer.json b/RVO45/flow/designer.json new file mode 100755 index 0000000..580f5a3 --- /dev/null +++ b/RVO45/flow/designer.json @@ -0,0 +1,3102 @@ +{ + "tabs": [ + { + "name": "MAIN PUSH", + "linker": "main-push", + "id": "1612772287426", + "index": 0 + }, + { + "name": "CMD manager", + "linker": "cmd-manager", + "id": "1615551125555", + "index": 1 + }, + { + "name": "Devices", + "linker": "devices", + "id": "1611921777196", + "index": 2 + } + ], + "components": [ + { + "id": "1611951142547", + "component": "debug", + "tab": "1611921777196", + "name": "ERROR", + "x": 598, + "y": 60, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#DA4453", + "notes": "" + }, + { + "id": "1612776786008", + "component": "wsmqttpublish", + "tab": "1612772287426", + "name": "WS MQTT publish", + "x": 281.75, + "y": 174, + "connections": { + "0": [ + { + "index": "0", + "id": "1615551060773" + } + ], + "1": [ + { + "index": "0", + "id": "1618300858252" + }, + { + "index": "0", + "id": "1618558465485" + } + ], + "2": [ + { + "index": "0", + "id": "1634303685503" + } + ], + "3": [ + { + "index": "0", + "id": "1731068754606" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Connected", + "color": "green" + }, + "options": { + "username": "", + "clientid": "", + "port": "1883", + "host": "" + }, + "color": "#888600", + "notes": "" + }, + { + "id": "1612778461252", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "tb-push", + "x": 72.75, + "y": 328, + "connections": { + "0": [ + { + "index": "0", + "id": "1612783322136" + }, + { + "index": "1", + "id": "1612776786008" + }, + { + "index": "0", + "id": "1731068754606" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1612783322136", + "component": "debug", + "tab": "1612772287426", + "name": "to TB", + "x": 283.75, + "y": 324, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615551060773", + "component": "debug", + "tab": "1612772287426", + "name": "errors from MQTT Broker", + "x": 594, + "y": 57, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#DA4453", + "notes": "" + }, + { + "id": "1615563373927", + "component": "debug", + "tab": "1615551125555", + "name": "Debug", + "x": 755, + "y": 155, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#DA4453", + "notes": "" + }, + { + "id": "1615566865233", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "tb-push", + "x": 755, + "y": 248, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1615798582262", + "component": "debug", + "tab": "1615551125555", + "name": "CMD_debug", + "x": 755, + "y": 346, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615802995322", + "component": "debug", + "tab": "1611921777196", + "name": "Debug", + "x": 596.8833312988281, + "y": 566.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Disabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": false + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615809128443", + "component": "debug", + "tab": "1611921777196", + "name": "tempToTb", + "x": 595.8833312988281, + "y": 658.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615809595184", + "component": "virtualwireout", + "tab": "1611921777196", + "name": "tb-push", + "x": 597.8833312988281, + "y": 377.25, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1616165795916", + "component": "httproute", + "tab": "1615551125555", + "name": "POST /terminal", + "x": 135, + "y": 547, + "connections": { + "0": [ + { + "index": "0", + "id": "1684060205000" + }, + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Listening", + "color": "green" + }, + "options": { + "timeout": 10, + "cachepolicy": 0, + "cacheexpire": "5 minutes", + "size": 5, + "url": "/terminal", + "method": "POST", + "name": "", + "flags": [ + "id:1616165795916", + "post", + 10000 + ], + "emptyresponse": false + }, + "color": "#5D9CEC", + "notes": "### Configuration\n\n- __POST /terminal__\n- flags: \n- maximum request data length: __5 kB__\n- empty response: __false__\n- cache policy: __no cache__\n- cache expire: __5 minutes__", + "cloning": false + }, + { + "id": "1616165824813", + "component": "httpresponse", + "tab": "1615551125555", + "name": "HTTP Response", + "x": 753, + "y": 423, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "json" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1617104731852", + "component": "debug", + "tab": "1615551125555", + "name": "DIDO_Debug", + "x": 669, + "y": 1040, + "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": "turnOff line", + "x": 133, + "y": 1161, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "object", + "data": "{line: 3, command: \"turnOff\", force: true}" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1617115013095", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "tb-push", + "x": 669, + "y": 1150, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1617284749681", + "component": "trigger", + "tab": "1615551125555", + "name": "update profile / node", + "x": 112, + "y": 208, + "connections": { + "0": [ + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "data": "profile_nodes", + "datatype": "string" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1618235171399", + "component": "trigger", + "tab": "1615551125555", + "name": "tun tasks", + "x": 184, + "y": 279, + "connections": { + "0": [ + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "data": "run" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1618300858252", + "component": "debug", + "tab": "1612772287426", + "name": "wsmqtt-exit1", + "x": 597.8833312988281, + "y": 149, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1618393583970", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "to-cmd-manager", + "x": 668.8833312988281, + "y": 1269, + "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": 132.88333129882812, + "y": 367, + "connections": { + "0": [ + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "platform-rpc-call", + "color": "gray" + }, + "options": { + "wirename": "platform-rpc-call" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1618393759854", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "cmd_to_dido", + "x": 119.88333129882812, + "y": 1007, + "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": 752.8833312988281, + "y": 527, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "cmd_to_dido", + "color": "gray" + }, + "options": { + "wirename": "cmd_to_dido" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1618558465485", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "platform-rpc-call", + "x": 597.8833312988281, + "y": 247, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "platform-rpc-call", + "color": "gray" + }, + "options": { + "wirename": "platform-rpc-call" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1618572059773", + "component": "trigger", + "tab": "1615551125555", + "name": "turnOn line", + "x": 132, + "y": 1085, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "data": "{line: 1, command: \"turnOn\", force: true}", + "datatype": "object" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1619515097737", + "component": "cmd_manager", + "tab": "1615551125555", + "name": "CMD Manager", + "x": 452.1091003417969, + "y": 341.05455017089844, + "connections": { + "0": [ + { + "index": "0", + "id": "1615563373927" + } + ], + "1": [ + { + "index": "0", + "id": "1615566865233" + }, + { + "index": "0", + "id": "1615798582262" + } + ], + "2": [ + { + "index": "0", + "id": "1616165824813" + } + ], + "3": [ + { + "index": "0", + "id": "1618393827655" + } + ], + "4": [ + { + "index": "0", + "id": "1635936391935" + } + ], + "5": [ + { + "index": "0", + "id": "1757006030239" + }, + { + "index": "0", + "id": "1757006060377" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1619605019281", + "component": "httproute", + "tab": "1615551125555", + "name": "GET db", + "x": 173, + "y": 653, + "connections": { + "0": [ + { + "index": "0", + "id": "1684060205000" + }, + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Listening", + "color": "green" + }, + "options": { + "timeout": 5, + "cachepolicy": 0, + "cacheexpire": "5 minutes", + "size": 5, + "url": "/db", + "method": "GET", + "name": "", + "flags": [ + "id:1619605019281", + "get", + 5000 + ] + }, + "color": "#5D9CEC", + "notes": "### Configuration\n\n- __GET /db__\n- flags: undefined\n- maximum request data length: __5 kB__\n- empty response: __undefined__\n- cache policy: __no cache__\n- cache expire: __5 minutes__", + "cloning": false + }, + { + "id": "1619784672383", + "component": "trigger", + "tab": "1615551125555", + "name": "turnOnAlarm", + "x": 120, + "y": 1234, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "object", + "data": "{command: \"turnOnAlarm\"}" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1619784812964", + "component": "trigger", + "tab": "1615551125555", + "name": "turnOffAlarm", + "x": 118, + "y": 1307, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "object", + "data": "{command: \"turnOffAlarm\"}" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1621340721628", + "component": "virtualwireout", + "tab": "1611921777196", + "name": "modbus_to_dido", + "x": 599, + "y": 471, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "modbus_to_dido", + "color": "gray" + }, + "options": { + "wirename": "modbus_to_dido" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1622640022885", + "component": "httproute", + "tab": "1615551125555", + "name": "POST /db_connector", + "x": 98, + "y": 1586, + "connections": { + "0": [ + { + "index": "0", + "id": "1622640073521" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Listening", + "color": "green" + }, + "options": { + "timeout": 5, + "cachepolicy": 0, + "cacheexpire": "5 minutes", + "size": 5, + "url": "/db_connector", + "method": "POST", + "flags": [ + "id:1622640022885", + "post", + 5000 + ] + }, + "color": "#5D9CEC", + "notes": "### Configuration\n\n- __POST /db_connector__\n- flags: \n- maximum request data length: __5 kB__\n- empty response: __undefined__\n- cache policy: __no cache__\n- cache expire: __5 minutes__", + "cloning": false + }, + { + "id": "1622640073521", + "component": "db_connector", + "tab": "1615551125555", + "name": "DbConnector", + "x": 372, + "y": 1572, + "connections": { + "1": [ + { + "index": "0", + "id": "1622641420685" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "edge": "undefined" + }, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1622641420685", + "component": "httpresponse", + "tab": "1615551125555", + "name": "HTTP Response", + "x": 596, + "y": 1586, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1634303504177", + "component": "monitormemory", + "tab": "1612772287426", + "name": "RAM", + "x": 69.88333129882812, + "y": 888.5, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465281992" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "858.88 MB / 985.68 MB", + "color": "gray" + }, + "options": { + "enabled": true, + "interval": 30000 + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1634303533779", + "component": "monitordisk", + "tab": "1612772287426", + "name": "disk", + "x": 70.88333129882812, + "y": 982.5, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465821120" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "5.78 GB / 7.26 GB", + "color": "gray" + }, + "options": { + "enabled": true, + "path": "/", + "interval": 30000 + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1634303595494", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "send-to-services", + "x": 51.883331298828125, + "y": 1400.5, + "connections": { + "0": [ + { + "index": "0", + "id": "1634463186563" + }, + { + "index": "1", + "id": "1634488120710" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1634303602169", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "send-to-services", + "x": 426.8833312988281, + "y": 878.5, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1634303685503", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "send-to-services", + "x": 600.8833312988281, + "y": 341.5, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1634303743260", + "component": "httprequest", + "tab": "1612772287426", + "name": "192.168.252.2:8004/sentmessage", + "reference": "", + "x": 506.8833312988281, + "y": 1331.7333374023438, + "connections": { + "0": [ + { + "index": "0", + "id": "1635327431236" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "url": "http://192.168.252.2:8004/sentmessage", + "method": "POST", + "stringify": "json" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1634463186563", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 305.75, + "y": 1442, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634464580289", + "component": "code", + "tab": "1612772287426", + "name": "Code", + "x": 245, + "y": 787, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465243324" + }, + { + "index": "0", + "id": "1634303602169" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "keepmessage": true, + "code": "let response = {};\nresponse.cpu = value.cpu;\nresponse.uptime = value.uptime;\n\nsend(0, response);", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1634465243324", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 428, + "y": 784, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634465281992", + "component": "code", + "tab": "1612772287426", + "name": "Code", + "x": 245, + "y": 884, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465338103" + }, + { + "index": "0", + "id": "1634303602169" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "keepmessage": true, + "code": "value.sender = \"ram\";\n\nlet response = {};\n\nresponse.memory_total = Math.round(value.total / (1024 ** 2));\nresponse.memory_free = Math.round(value.free / (1024 ** 2));\nresponse.memory_used = Math.round(value.used / (1024 ** 2));\n\nsend(0, response);", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1634465338103", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 429, + "y": 976, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634465821120", + "component": "code", + "tab": "1612772287426", + "name": "Code", + "x": 245, + "y": 978, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465892500" + }, + { + "index": "0", + "id": "1634303602169" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "keepmessage": true, + "code": "value.sender = \"hdd\";\n\nlet response = {};\n\nresponse.hdd_total = Math.round(value.total / (1024 ** 2));\nresponse.hdd_free = Math.round(value.free / (1024 ** 2));\nresponse.hdd_used = Math.round(value.used / (1024 ** 2));\n\nsend(0, response);", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1634465892500", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 432, + "y": 1068, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634484067516", + "component": "debug", + "tab": "1612772287426", + "name": "Send info", + "x": 513, + "y": 1441, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634488120710", + "component": "infosender", + "tab": "1612772287426", + "name": "Info sender", + "x": 301, + "y": 1336, + "connections": { + "0": [ + { + "index": "0", + "id": "1634484067516" + }, + { + "index": "0", + "id": "1634303743260" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "edge": "undefined" + }, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1635327431236", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 837.8833312988281, + "y": 1325.5, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1635936391935", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "send-to-services", + "x": 753, + "y": 623, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1637069803394", + "component": "monitorconsumption", + "tab": "1612772287426", + "name": "CPU", + "x": 69, + "y": 791, + "connections": { + "0": [ + { + "index": "0", + "id": "1634464580289" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "49.2% / 69.91 MB", + "color": "gray" + }, + "options": { + "monitorfiles": true, + "monitorconnections": true, + "monitorsize": true, + "monitorconsumption": true, + "enabled": true, + "interval": 30000 + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1683664161036", + "component": "debug", + "tab": "1615551125555", + "name": "CMDtoDIDO", + "x": 392, + "y": 1012, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1683981346282", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "from-dido-controller", + "x": 112, + "y": 459, + "connections": { + "0": [ + { + "index": "0", + "id": "1684055037116" + }, + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "from-dido-controller", + "color": "gray" + }, + "options": { + "wirename": "from-dido-controller" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1684055037116", + "component": "debug", + "tab": "1615551125555", + "name": "from dido to cmd", + "x": 451, + "y": 532, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1684060205000", + "component": "debug", + "tab": "1615551125555", + "name": "HTTP routes", + "x": 450, + "y": 639, + "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": "MDBToDido", + "x": 598, + "y": 147, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1699963668903", + "component": "dido_controller", + "tab": "1615551125555", + "name": "DIDO_Controller", + "x": 397, + "y": 1131, + "connections": { + "0": [ + { + "index": "0", + "id": "1617104731852" + } + ], + "1": [ + { + "index": "0", + "id": "1617104731852" + }, + { + "index": "0", + "id": "1617115013095" + } + ], + "2": [ + { + "index": "0", + "id": "1618393583970" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "edge": "undefined" + }, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1699964678894", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "modbus_to_dido", + "x": 96, + "y": 924, + "connections": { + "0": [ + { + "index": "0", + "id": "1699963668903" + }, + { + "index": "0", + "id": "1699964793925" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "modbus_to_dido", + "color": "gray" + }, + "options": { + "wirename": "modbus_to_dido" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1699964793925", + "component": "debug", + "tab": "1615551125555", + "name": "modbusToDido", + "x": 388, + "y": 920, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1699965957410", + "component": "modbus_reader", + "tab": "1611921777196", + "name": "Modbus reader", + "x": 232, + "y": 175, + "connections": { + "0": [ + { + "index": "0", + "id": "1611951142547" + } + ], + "1": [ + { + "index": "0", + "id": "1621340721628" + }, + { + "index": "0", + "id": "1684179110403" + }, + { + "index": "0", + "id": "1717441414646" + } + ], + "2": [ + { + "index": "0", + "id": "1615809595184" + }, + { + "index": "0", + "id": "1714752862828" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1700411878636", + "component": "thermometer", + "tab": "1611921777196", + "name": "Thermometer", + "x": 234.75, + "y": 444, + "connections": { + "0": [ + { + "index": "0", + "id": "1615802995322" + } + ], + "1": [ + { + "index": "0", + "id": "1615809595184" + }, + { + "index": "0", + "id": "1615809128443" + } + ], + "2": [ + { + "index": "0", + "id": "1621340721628" + }, + { + "index": "0", + "id": "1732889185927" + }, + { + "index": "0", + "id": "1717441414646" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#5CB36D", + "notes": "" + }, + { + "id": "1714752862828", + "component": "debug", + "tab": "1611921777196", + "name": "MDBToTb", + "x": 766, + "y": 324, + "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": 764.0833282470703, + "y": 222, + "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\telse if(value.status === \"NOK-thermometer\")\n\t{\n\t\tsend(0, {\"thermometer\": \"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\telse if(value.values.hasOwnProperty(\"temperature\"))\n\t{\n\t\tsend(0, {\"thermometer\": \"OK\"});\n\t}\n}", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1717442627834", + "component": "debug", + "tab": "1611921777196", + "name": "modbus service", + "x": 966.0833282470703, + "y": 165, + "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": 968.0833282470703, + "y": 268, + "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": 88.75, + "y": 1685, + "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": 296, + "y": 1671, + "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\", \"Flow has been restarted\", \"Node db has changed\"]", + "types": "[\"emergency\", \"critical\", \"error\", \"alert\"]", + "name": "" + }, + "color": "#30E193", + "notes": "" + }, + { + "id": "1718016073501", + "component": "httprequest", + "tab": "1612772287426", + "name": "http://192.168.252.2:8004/slack", + "x": 495, + "y": 1753, + "connections": { + "0": [ + { + "index": "0", + "id": "1718016086212" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "url": "http://192.168.252.2:8004/slack", + "method": "POST", + "stringify": "json" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1718016086212", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 832, + "y": 1664, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "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": 87, + "y": 1591, + "connections": { + "0": [ + { + "index": "0", + "id": "1718016052341" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "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\": \"\" } } } ] }", + "datatype": "object" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1729855334955", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "platform-rpc-call", + "x": 599.9333343505859, + "y": 541.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "platform-rpc-call", + "color": "gray" + }, + "options": { + "wirename": "platform-rpc-call" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1729855371093", + "component": "debug", + "tab": "1612772287426", + "name": "rpc cloud", + "x": 601.9333343505859, + "y": 440.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1731068658334", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 75.75, + "y": 184, + "connections": { + "0": [ + { + "index": "0", + "id": "1612776786008" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731068754606", + "component": "cloudmqttconnect", + "tab": "1612772287426", + "name": "MQTT to senica-prod01", + "x": 284.75, + "y": 452, + "connections": { + "1": [ + { + "index": "0", + "id": "1729855371093" + }, + { + "index": "0", + "id": "1729855334955" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Connected", + "color": "green" + }, + "options": { + "username": "", + "clientid": "", + "port": "2764", + "host": "192.168.252.2", + "topic": "" + }, + "color": "#888600", + "notes": "" + }, + { + "id": "1731069001548", + "component": "db_init", + "tab": "1612772287426", + "name": "DB Initialization", + "x": 1003.75, + "y": 240.25, + "connections": { + "0": [ + { + "index": "0", + "id": "1731069033416" + } + ], + "1": [ + { + "index": "0", + "id": "1747561603739" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#888600", + "notes": "" + }, + { + "id": "1731069033416", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "db-init", + "x": 1244.75, + "y": 233.25, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069059135", + "component": "showdb", + "tab": "1612772287426", + "name": "Show db data", + "x": 1186.75, + "y": 821.25, + "connections": { + "0": [ + { + "index": "0", + "id": "1731069079243" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#888600", + "notes": "" + }, + { + "id": "1731069079243", + "component": "debug", + "tab": "1612772287426", + "name": "dbData", + "x": 1390.75, + "y": 870.25, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1731069116691", + "component": "trigger", + "tab": "1612772287426", + "name": "settings", + "x": 934.75, + "y": 669.75, + "connections": { + "0": [ + { + "index": "0", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069131637", + "component": "trigger", + "tab": "1612772287426", + "name": "relaysData", + "x": 876.75, + "y": 733.75, + "connections": { + "0": [ + { + "index": "1", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069137374", + "component": "trigger", + "tab": "1612772287426", + "name": "nodesData", + "x": 852.75, + "y": 794.75, + "connections": { + "0": [ + { + "index": "2", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069179846", + "component": "trigger", + "tab": "1612772287426", + "name": "pinsData", + "x": 850.75, + "y": 861.75, + "connections": { + "0": [ + { + "index": "3", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069192937", + "component": "trigger", + "tab": "1612772287426", + "name": "sample data", + "x": 857.75, + "y": 928.75, + "connections": { + "0": [ + { + "index": "4", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069264443", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 63.75, + "y": 1279, + "connections": { + "0": [ + { + "index": "0", + "id": "1634488120710" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069334626", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "db-init", + "x": 172.88333129882812, + "y": 129, + "connections": { + "0": [ + { + "index": "0", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069548145", + "component": "virtualwirein", + "tab": "1611921777196", + "name": "db-init", + "x": 46.75, + "y": 192, + "connections": { + "0": [ + { + "index": "0", + "id": "1699965957410" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069567152", + "component": "virtualwirein", + "tab": "1611921777196", + "name": "db-init", + "x": 44.75, + "y": 465, + "connections": { + "0": [ + { + "index": "0", + "id": "1700411878636" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731070156936", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "db-init", + "x": 126.88333129882812, + "y": 1377, + "connections": { + "0": [ + { + "index": "2", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731234189516", + "component": "trigger", + "tab": "1612772287426", + "name": "monitor.txt", + "x": 882.75, + "y": 991.75, + "connections": { + "0": [ + { + "index": "5", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731234189551", + "component": "trigger", + "tab": "1612772287426", + "name": "err.txt", + "x": 904.75, + "y": 1053.75, + "connections": { + "0": [ + { + "index": "6", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1732700042559", + "component": "nodesdb_change_check", + "tab": "1612772287426", + "name": "Nodes DB change check", + "x": 266.8833312988281, + "y": 1980.2333984375, + "connections": { + "0": [ + { + "index": "0", + "id": "1732700071298" + }, + { + "index": "0", + "id": "1732700642917" + } + ], + "1": [ + { + "index": "0", + "id": "1759958914348" + }, + { + "index": "0", + "id": "1759959003114" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#888600", + "notes": "" + }, + { + "id": "1732700057052", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 76.75, + "y": 1988, + "connections": { + "0": [ + { + "index": "0", + "id": "1732700042559" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1732700071298", + "component": "debug", + "tab": "1612772287426", + "name": "nodesChange", + "x": 571.8833312988281, + "y": 2018.2333984375, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1732700642917", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "tb-push", + "x": 567.8833312988281, + "y": 1933, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1732889185927", + "component": "debug", + "tab": "1611921777196", + "name": "tempToDido", + "x": 594.8833312988281, + "y": 753, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1733574412965", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 72.75, + "y": 474, + "connections": { + "0": [ + { + "index": "1", + "id": "1731068754606" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1747561603739", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "send-to-services", + "x": 1243.8833312988281, + "y": 334.5, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1747562867845", + "component": "comment", + "tab": "1612772287426", + "name": "FLOW STARTING POINT", + "x": 1003.5666656494141, + "y": 178, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#704cff", + "notes": "" + }, + { + "id": "1749211698385", + "component": "trigger", + "tab": "1612772287426", + "name": "deviceStatus", + "x": 911.75, + "y": 1116.75, + "connections": { + "0": [ + { + "index": "7", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1757006030239", + "component": "httprequest", + "tab": "1615551125555", + "name": "192.168.252.2:8015/daily_report", + "x": 756.5666656494141, + "y": 715.4499969482422, + "connections": { + "0": [ + { + "index": "0", + "id": "1757006045804" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "stringify": "json", + "method": "POST", + "url": "http://192.168.252.2:8015/daily_report" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1757006045804", + "component": "debug", + "tab": "1615551125555", + "name": "ddd", + "x": 1091.566665649414, + "y": 711.4499969482422, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1757006060377", + "component": "debug", + "tab": "1615551125555", + "name": "reportDebug", + "x": 749.5666656494141, + "y": 799.4499969482422, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1759958914348", + "component": "httprequest", + "tab": "1612772287426", + "name": "http://192.168.252.2:8015/node_numbers", + "x": 571, + "y": 2111, + "connections": { + "0": [ + { + "index": "0", + "id": "1759958927094" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "stringify": "json", + "method": "POST", + "url": "http://192.168.252.2:8015/node_numbers" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1759958927094", + "component": "debug", + "tab": "1612772287426", + "name": "nodesChangeCloud", + "x": 951.8833312988281, + "y": 2109.2333984375, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1759959003114", + "component": "debug", + "tab": "1612772287426", + "name": "nodeChangeCloud1", + "x": 574, + "y": 2218, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1760020290879", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 84.75, + "y": 1787, + "connections": { + "0": [ + { + "index": "1", + "id": "1718016052341" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + } + ], + "version": 615 +} diff --git a/RVO45/flow/dido_controller.js b/RVO45/flow/dido_controller.js new file mode 100755 index 0000000..d16fb19 --- /dev/null +++ b/RVO45/flow/dido_controller.js @@ -0,0 +1,1486 @@ +exports.id = 'dido_controller'; +exports.title = 'DIDO_Controller'; +exports.version = '2.0.0'; +exports.group = 'Worksys'; +exports.color = '#2134B0'; +exports.input = 3; +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 + +state_of_main_switch - reportovat stav hlaveho istica : 0-> off 1-> on +rotary_switch_state - sem by sa mal reportovat stav vstupov manual a auto pola nasledovnej logiky: Manual = 1 a Auto = 0 -> Manu +Manual = 0 a Auto = 0 -> Off, Manual = 0 a Auto = 1 -> Automatic + +door_condition - pin 6, dverový kontakt -> 1 -> vyreportuje Closed, 0 -> vyreportuje Ope +twilight_sensor - hodnotu, ktoru vracia ten analogovy vstup (17) treba poslat sem ako float number. Zrejme tu potom pridame nejaky koeficient prevodu na luxy + +Na kazdu liniu +state_of_breaker - podla indexu istica sa reportuje jeho stav, teda istic na liniu 1: 0-> off, 1-> on +state_of_contactor - podla indexu stkaca sa reportuje jeho stav, teda stykac 1 na liniu 1: 0-> off, 1-> on +*/ + +const { errLogger, logger, monitor } = require('./helper/logger'); +const SerialPort = require('serialport'); +const WebSocket = require('ws'); +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 errorHandler = require('./helper/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 hasMainSwitch; + +let alarmStatus = "OFF"; + +const SEND_TO = { + debug: 0, + tb: 1, + cmd_manager: 2 +} + + +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 = {}; + let rsPortReceivedData = []; + + //to be able to get proper twilight values + let twilight_sensor_interval = 5;//minutes + let twilight_sensor = []; + const twilight_sensor_array = []; + let twilightError = false; + + monitor.info("DIDO_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-we make it global to see it from outside + FLOW.deviceStatus = { //key is device name: temperature,.... + "state_of_main_switch": "Off", //Hlavny istic (alebo druhy dverovy kontakt) + "rotary_switch_state": "Off", //Prevadzkovy + "door_condition": "closed", //Dverový kontakt + "em": "OK", //elektromer rvo + "temperature": "OK", //templomer + "battery": "OK", //Bateria + "power_supply": "OK", //Zdroj + "master_node": "OK", //MN - GLOBALS.settings.masterNodeIsResponding + "no_voltage": "OK", //GLOBALS.settings.no_voltage - vypadok napatia na faze + "state_of_breaker": {}, //"Off",//Istic + "state_of_contactor": {}, //"Off",//Stykac + "twilight_sensor": "OK" //lux sensor + }; + let deviceStatus = FLOW.deviceStatus; + + + function main() { + + GLOBALS = FLOW.GLOBALS; + SETTINGS = FLOW.GLOBALS.settings; + rvoTbName = SETTINGS.rvoTbName; + pinsData = GLOBALS.pinsData; + relaysData = GLOBALS.relaysData; + + tbHandler = new DataToTbHandler(SEND_TO.tb); + tbHandler.setSender(exports.title); + + controller_type = SETTINGS.controller_type; //"lm" or "unipi" + hasMainSwitch = SETTINGS.has_main_switch; + + if (controller_type == "") controller_type = "lm"; + + 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, "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; + } + } + + //report RVO version relaysData[0].tbname; + let values = {}; + values["edge_fw_version"] = SETTINGS.edge_fw_version; + values["maintenance_mode"] = SETTINGS.maintenance_mode; + + sendTelemetry(values, rvoTbName); + + 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); + } + + + function handleRsPort() { + + if (rsPort) { + rsPort.removeAllListeners(); + rsPort = null; + } + + //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('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) { + if (!err) { + monitor.info(exports.title + "--->Digital in_out has been set (runSyncExec was sucessfull)"); + + turnAlarm("off"); + 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('error', err => { + let message = "Dido: rsPort error: " + err.message; + logger.debug(message); + monitor.info(message); + errorHandler.sendMessageToService(message); + }) + + rsPort.on("close", () => { + let message = "Dido: rsPort closed - reconnecting ..."; + logger.debug(message); + monitor.info(message); + setTimeout(handleRsPort, 1000); + }) + + rsPort.open(); + } + + + function handleWebSocket() { + + if (ws) { + ws.removeAllListeners(); + ws = null; + } + + //to keep websocket opened, we send request every 150 seconds + let startRequests = null; + + console.log("handleWebSocket function called"); + ws = new WebSocket('ws:/0.0.0.0:1234/ws'); + + ws.onopen = function open() { + + instance.send(0, exports.title + " running"); + turnAlarm("off"); + + initialSetting(); + + setTimeout(function() { ws.send(JSON.stringify({ cmd: "all" })) }, 5000); + // we request dev info about neuron device from evok to keep websocket connection alive + // for some reason this request returns no data, but connection keeps alive + startRequests = setInterval(() => { + ws.send(JSON.stringify({ "cmd": "filter", "dev": ["neuron"] })); + }, 150000) + }; + + + // 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 = async 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; + + 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 => { + logger.debug('Dido: websocket error', err); + }) + + ws.onclose = function() { + logger.debug('Dido: websocket onclose, reconnecting...') + clearInterval(startRequests); + setTimeout(handleWebSocket, 1000); + } + } + + 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 turnAlarm(onOrOff) { + let value = 0; + if (onOrOff == "on") value = 1; + + if (value == 1 && SETTINGS.maintenance_mode) return; + + alarmStatus = "OFF"; + if (value == 1) alarmStatus = "ON"; + + if (rsPort) { + let arr = [0x55]; + arr.push(13); + arr.push(0); + arr.push(value); + + rsPort.write(Buffer.from(arr), function(err) { + logger.debug(`sirena - ${onOrOff}`); + }); + } + else if (ws) { + let cmd = { "cmd": "set", "dev": "relay", "circuit": "1_01", "value": value }; + ws.send(JSON.stringify(cmd)); + logger.debug(`sirena - ${onOrOff}`); + } + } + + + 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") { + bits.push(0); + } + else bits.push(1); + + if (deviceStatus["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); + } + + + // turn line on or off + function turnLine(onOrOff, line, pin, force, info) { + //onOrOff => "on" or "off" + let value = 0; + if (onOrOff == "on") value = 1; + + if (force == undefined) force = false; + + if (line == 0) { + if (value == 1 && alarmStatus == "ON") turnAlarm("off"); + SETTINGS.maintenance_mode = value ? true : false; + + 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); + return; + } + + if (pin === undefined) pin = getPin(line); + + if (pin === undefined) { + errLogger.error("pin is undefined!", line); + return; + } + + if (!force) { + if (relaysData[line].contactor == value) { + instance.send(SEND_TO.debug, `line is already ${onOrOff} ` + line); + logger.debug(`Dido: turnLine: line is already ${onOrOff} `, line); + return; + } + } + + // if(!rsPort.isOpen && !ws) + if (!rsPort && !ws) { + errLogger.error("Dido - port or websocket is not opened"); + return; + } + + if (rsPort) { + let arr = [0x55]; + arr.push(pin); + arr.push(0); + arr.push(value); + + rsPort.write(Buffer.from(arr), function(err) { + if (err === undefined) { + monitor.info(`Dido: turnLine ${onOrOff} zapisal do rsPort-u`, line, pin, arr, info); + switchLogic(arr); + } + else { + monitor.info(`Dido: turnLine ${onOrOff} WRITE error`, err); + } + }); + + } + else if (ws) { + //pin = "relay1_03" or "input1_01" ... we must make just "1_01" with slice method + monitor.info(`Dido: turnLine ${onOrOff} - (line, pin, force)`, line, pin, force, info); + let cmd = { "cmd": "set", "dev": "relay", "circuit": pin.slice(5), "value": value }; + ws.send(JSON.stringify(cmd)); + } + + //if rvo is 24/7, it has just one switching profile point at 13:00. we do not want to send notification as it repeats every day. + //const d = new Date(); + //if(d.getHours() != 13) sendNotification("Dido_controller: ", SETTINGS.rvoTbName, "switching_profile_point_applied_to_line", { line: line, value: onOrOff }, "", SEND_TO.tb, instance); + } + + + // 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; + + // 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) { + const status = flowdata.data.status; + if (status == "NOK-twilight_sensor") { + deviceStatus["twilight_sensor"] = "NOK"; + } + else if (status == "NOK-em340" || status == "NOK-em111") { + deviceStatus["em"] = "NOK"; + } + else if (status == "NOK-thermometer") { + deviceStatus["temperature"] = "NOK"; + } + } + else if ("values" in flowdata.data) { + 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" + } + else if (values.hasOwnProperty("temperature")) { + deviceStatus["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"; + } + + sendTelemetry(values, rvoTbName); + } + + sendRvoStatus(); + }) + + + + + // we expect array as flowdata.data + instance.on("1", flowdata => { + + //console.log(flowdata.data); + + if (!flowdata.data instanceof Object) return; + + let obj = flowdata.data; + let line = obj.line; + 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"); + }) + + + function calculateStateCode() { + + let bits = []; + + //Hlavny istic - state_of_main_switch => v rvo senica je to druhy door pre silovu cast (EM) + if (deviceStatus["state_of_main_switch"] === "closed" || deviceStatus["state_of_main_switch"] === "Off") { + bits.push(0); + } + else { + bits.push(1); + } + + //Prevadzkovy mod - Manual, Off, Automatic, maintenance_mode = true/false // DAVA 2 BITY + if (!SETTINGS.maintenance_mode) { + if (deviceStatus["rotary_switch_state"] === "Manual") { + bits.push(0); + bits.push(1); + } + + if (deviceStatus["rotary_switch_state"] === "Automatic") { + bits.push(0); + bits.push(0); + } + + if (deviceStatus["rotary_switch_state"] === "Off") { + bits.push(1); + bits.push(0); + } + } + else { + bits.push(1); + bits.push(1); + } + + //Dverovy kontakt + if (deviceStatus["door_condition"] === "closed") { + bits.push(0); + } + else { + bits.push(1); + } + + //EM + if (deviceStatus["em"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //Teplomer + if (deviceStatus["temperature"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //Batéria + if (deviceStatus["battery"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //Zdroj + if (deviceStatus["power_supply"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //MN + if (deviceStatus["master_node"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //výpadok napätia na fáze + if (deviceStatus["no_voltage"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + if (deviceStatus["twilight_sensor"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + // doplnime do 16 bitov (2 byty) + for (let i = bits.length; i < 16; i++) { + bits.push(0); + } + + // console.log("calculateStateCode - deviceStatus", deviceStatus); + // 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; + } + + + async function sendRvoStatus() { + + if (SETTINGS === undefined) return; + SETTINGS.masterNodeIsResponding ? deviceStatus["master_node"] = "OK" : deviceStatus["master_node"] = "NOK"; + + 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 pinsForRvoStatus(controllerType, hasMainSwitch) { + + let pins = []; + + if (controllerType === "lm") { + pins = [1, 4, 6]; + if (hasMainSwitch === 1) { + pins = [4, 6]; + } + } else if (controllerType === "unipi") { + pins = ["input1_01", "input1_04", "input1_05"]; + if (hasMainSwitch === 1) { + pins = ["input1_01", "input1_04"]; + } + } + + return pins; + } + + + function checkRvoStatus() { + + // 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 + //set RVO state + let status = "OK"; + + for (const [key, value] of Object.entries(deviceStatus)) { + if (["em", "twilight_sensor", "temperature", "master_node"].includes(key) && value === "NOK") status = "NOK"; + } + + if (status === "OK") { + + let pinIndexes = pinsForRvoStatus(controller_type, hasMainSwitch); + + for (const pinIndex of pinIndexes) { + if (previousValues[pinIndex] === 0) { + if ((pinIndex === 6 || pinIndex === 'input1_01' || pinIndex === 'input1_05') && SETTINGS.maintenance_mode) continue; + status = "NOK"; + break; + } + } + } + + // battery status. If value is 1 - battery is NOK + if (previousValues[5] === 1) status = "NOK"; + if (SETTINGS.no_voltage.size > 0) status = "NOK"; + + // console.log("rvo status",status) + return status; + } + + + // we pass array to function in case of rsPort ==> switchLogic([55,3,0,1]) ==> [[55,3,0,1]] + // we pass two values in case of websocket ==> switchLogic("relay1_03",1) ==> ["relay1_03",1] + const switchLogic = (...args) => { + + let values = {}; + let pinIndex, newPinValue, twilight; + + //data from rsPort + if (args.length == 1) { + pinIndex = args[0][1] + 1; + if (pinIndex === 17) pinIndex--; + newPinValue = args[0][3]; + twilight = args[0][2]; + } + //data from websocket + else { + pinIndex = args[0]; + newPinValue = args[1]; + } + + 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; + + //default value + let value = "On"; + if (newPinValue === 0) value = "Off"; + + //Hlavny istic + if (type === "state_of_main_switch" && hasMainSwitch) { + if (newPinValue === 0 && newPinValue !== previousValues[pinIndex]) { + sendNotification("switchLogic", rvoTbName, "main_switch_has_been_turned_off", {}, "", SEND_TO.tb, instance, "state_of_main_switch"); + 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"); + deviceStatus["state_of_main_switch"] = "On"; + } + } + + //Prevadzkovy mod + 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"; + + deviceStatus["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, "power_supply_has_disconnected_input", {}, "", SEND_TO.tb, instance, "power_supply"); + + deviceStatus["power_supply"] = "NOK"; + } + else if (newPinValue === 1 && newPinValue !== previousValues[pinIndex]) { + sendNotification("switchLogic", rvoTbName, "power_supply_works_correctly", {}, "", SEND_TO.tb, instance, "power_supply"); + + deviceStatus["power_supply"] = "OK"; + } + } + + //Bateria - 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"); + + deviceStatus["battery"] = "NOK"; + } + else if (newPinValue === 0 && newPinValue !== previousValues[pinIndex]) { + sendNotification("switchLogic", rvoTbName, "battery_level_is_ok", {}, "", SEND_TO.tb, instance, "battery_level"); + + deviceStatus["battery"] = "OK"; + } + } + + //Dverovy kontakt - pin 6 + //! Ak je rvo s dvoma dverovymi kontaktami, ked pride z evoku signal z input1_05, co bol predytm "state_of_main switch" handlujeme ho teraz ako 'door_condition' + else if (type == "door_condition" || type === "state_of_main_switch") { + newPinValue === 0 ? value = "open" : value = "closed"; + + let door = "door_main"; + if (type === "state_of_main_switch") door = "door_em"; + + if (value === "open") { + if (SETTINGS.maintenance_mode) { + sendNotification("switchLogic", rvoTbName, door + "_open", {}, "", SEND_TO.tb, instance, door); + } else { + sendNotification("switchLogic", rvoTbName, door + "_open_without_permission", {}, "", SEND_TO.tb, instance, door); + + // 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 (value === "closed") { + if (alarmStatus == "ON") turnAlarm("off"); + sendNotification("switchLogic", rvoTbName, door + "_close", {}, "", SEND_TO.tb, instance, door); + } + + deviceStatus[type] = value; + } + + //lux sensor + else if (type == "twilight_sensor") { + //! TODO - to show nok status, if lux value is not changing more then 10 times. + //Daylight is far more than 1000. So most of the day, when it is sunshine comes just value 1000. But lux sensor is not NOK. + //This is not the case in LM. If value from LM is the same 10x, there is 99% possibility, that sensor is NOK. + value = newPinValue; + + if (controller_type === 'lm') { + value = parseFloat(newPinValue + (256 * twilight)); + + 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 && !twilightError) { + twilightError = true; + let value = twilight_sensor_array.shift(); + + newPinValue = 0; + } + else if (set.size !== 1 && twilightError) { + //sendNotification("switchLogic", rvoTbName, 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) { + 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); + } + } + + 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); + } + + deviceStatus["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 (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 }); + + //mame iba 3 istice. vyreportujeme a ohandlujeme liniu na tom istom istici ako paralelna linia (napr linia 1, paralelna s nou je linia 4, key je string "4") + // ak je 7 linii, na 1 istici je linia 1,4,7 + + if (line == 1) { + + const lineOnSameBraker = [4, 7]; + + for (var i = 0; i < lineOnSameBraker.length; i++) { + if (!relaysData.hasOwnProperty(lineOnSameBraker[i])) continue; + + 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; + reportLineStatus(lineOnSameBraker[i]); + + values[type] = value; + const tbname = relaysData[lineOnSameBraker[i]].tbname; + sendTelemetry(values, tbname); + + delete values[type]; + } + + } + else { + const lineOnSameBraker = line + 3 + ""; + + if (relaysData.hasOwnProperty(lineOnSameBraker)) { + 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; + reportLineStatus(line + 3); + + values[type] = value; + const tbname = relaysData[lineOnSameBraker].tbname; + sendTelemetry(values, tbname); + + delete values[type]; + } + } + + } + + if (value == "Off") values["status"] = "NOK"; + deviceStatus["state_of_breaker"][line] = value; + + reportLineStatus(line); + } + else return; + + values[type] = value; + + if (type == "rotary_switch_state") { + if (SETTINGS.maintenance_mode) value = "maintenance"; + value = value.toLowerCase(); + values["power_mode"] = value; + } + + if (newPinValue != previousValues[pinIndex]) previousValues[pinIndex] = newPinValue; + if (Object.keys(values).length > 0 && tbname) sendTelemetry(values, tbname); + } + + + function sendTelemetry(values, tbname, date = Date.now()) { + let dataToTb = { + [tbname]: [ + { + "ts": date, + "values": values + } + ] + }; + + tbHandler.sendToTb(dataToTb, instance); + } + + + function isObject(item) { + return (typeof item === "object" && !Array.isArray(item) && item !== null); + } + +} //end of 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 +// *|input1_01|state_of_main_switch|0|........... +// *|input1_02|rotary_switch_state|0|........... +// *|input1_03|rotary_switch_state|0|........... +// *|intut1_04|power_supply|0|........... +// *|input1_05|door_condition|0|........... +// *|input1_06|state_of_breaker|1|........... +// *|input1_07|state_of_breaker|2|........... +// *|input1_08|state_of_breaker|3|........... +// *|relay1_02|state_of_contactor|1|........... +// *|relay1_03|state_of_contactor|2|........... +// *|relay1_04|state_of_contactor|3|........... +// *|287D8776E0013CE9|temperature|0|........... + + +//! pins_data --> from UNIPI +// { +// 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 } +// } + +//! relays_data +// { +// '0': { +// line: 0, +// tbname: 'KjbN4q7JPZmexgdnz2yKQ98YAWwO0Q3BMX6ERLoV', +// contactor: 1, +// profile: '' +// }, +// '1': { +// line: 1, +// tbname: 'RMgnK93rkoAazbqdQ4yBG95Z1YXGx6pmwBeVEP2O', +// contactor: 0, +// profile: '{"intervals":[{"value":0,"end_time":"20:00","start_time":"13:00"},{"value":1,"end_time":"10:00","start_time":"20:00"},{"value":0,"end_time":"10:20","start_time":"10:00"},{"value":1,"end_time":"10:40","start_time":"10:20"},{"value":0,"end_time":"11:00","start_time":"10:40"},{"value":1,"end_time":"11:30","start_time":"11:00"},{"value":0,"end_time":"11:50","start_time":"11:30"},{"value":1,"end_time":"13:00","start_time":"11:50"}],"astro_clock":false,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' +// }, +// '2': { +// line: 2, +// tbname: 'dlE1VQjYrNx9gZRmb38gG08oLBO4qaAk2M6JPnG7', +// contactor: 0, +// profile: '{"intervals":[{"value":0,"end_time":"20:00","start_time":"13:00"},{"value":1,"end_time":"10:00","start_time":"20:00"},{"value":0,"end_time":"10:20","start_time":"10:00"},{"value":1,"end_time":"10:40","start_time":"10:20"},{"value":0,"end_time":"11:00","start_time":"10:40"},{"value":1,"end_time":"11:30","start_time":"11:00"},{"value":0,"end_time":"11:50","start_time":"11:30"},{"value":1,"end_time":"13:00","start_time":"11:50"}],"astro_clock":false,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' +// }, +// '3': { +// line: 3, +// tbname: 'vnmG4kJxaXWNBgMQq0D7Aj5e9oZzOAlr6LdR3w2V', +// contactor: 0, +// profile: '{"intervals":[{"value":0,"end_time":"20:30","start_time":"13:00"},{"value":1,"end_time":"00:10","start_time":"20:30"},{"value":0,"end_time":"13:00","start_time":"05:40"},{"value":1,"end_time":"05:40","start_time":"00:10"}],"astro_clock":true,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' +// } +// } + + + + + +// { +// "jbN4q7JPZmexgdnz2yKbWGDYAWwO0Q3BMX6ERLoV": [ +// { +// "ts": 1700409326353, +// "values": { +// "_event": { +// "type": "notice", +// "status": "new", +// "source": { +// "func": "rsPort.open()", +// "component": "1700343402190", +// "component_name": "DIDO_Controller", +// "edge": "jbN4q7JPZmexgdnz2yKbWGDYAWwO0Q3BMX6ERLoV" +// }, +// "message": "al_shariff_10.0.0.38: FLOW has been started ", +// "message_data": "" +// } +// } +// } +// ] +// } diff --git a/RVO45/flow/helper/DataToTbHandler.js b/RVO45/flow/helper/DataToTbHandler.js new file mode 100755 index 0000000..716ef7b --- /dev/null +++ b/RVO45/flow/helper/DataToTbHandler.js @@ -0,0 +1,187 @@ +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; + this.itIsNodeReadout = false; + this.sender = ""; + + // if attribute change difference is less than limit value, we do not send to tb. + this.attributeChangeLimit = { + temperature: 0.5, + Phase_1_voltage: 2, + Phase_2_voltage: 2, + Phase_3_voltage: 2, + Phase_1_current: 0.1, + Phase_2_current: 0.1, + Phase_3_current: 0.1, + Phase_1_power: 2, + Phase_2_power: 2, + Phase_3_power: 2, + total_power: 2, + total_energy: 1, + Phase_1_pow_factor: 0.1, + Phase_2_pow_factor: 0.1, + Phase_3_pow_factor: 0.1, + power_factor: 0.1, + lifetime: 2, + voltage: 2, + power: 2, + frequency: 3, + energy: 0.1, + current: 2, + inclination_x: 10, + inclination_y: 10, + inclination_z: 10 + }; + + } + + dump() { + console.log("----------------------------"); + console.log("previousValues", this.previousValues); + console.log("----------------------------"); + } + + setSender(sender) { + this.sender = sender; + } + + isEmptyObject(obj) { + for (var _ in obj) { + return false; + } + return true; + } + + + sendToTb(data, instance) { + + //not to modify data object, we do deep copy: + let dataCopy = JSON.parse(JSON.stringify(data)); + + let keys = Object.keys(dataCopy); + + if (keys.length == 0) { + if (this.debug) console.log("sendToTb received empty object", dataCopy); + return; + } + + let tbname = keys[0]; + let ts; + + let arrayOfValues = dataCopy[tbname]; + let arrayOfValuesToSend = []; + + for (let i = 0; i < arrayOfValues.length; i++) { + + ts = arrayOfValues[i].ts; + let values = this.prepareValuesForTb(tbname, ts, arrayOfValues[i].values); + + if (!this.isEmptyObject(values)) { + arrayOfValuesToSend.push({ ts: ts, values: values }); + } + + } + + if (arrayOfValuesToSend.length == 0) { + //if(this.debug) console.log("data not sent - empty array"); + return; + } + + this.messageCounter++; + + let dataToTbModified = { + [tbname]: arrayOfValuesToSend + } + + //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); + instance.send(this.index, dataToTbModified); + } + + + getDiffTimestamp(key) { + //TODO set different value for given key!!! + //if(key == "status") this.timeToHoldTbValue = 2*60*60;//2h + return this.timeToHoldTbValue * 1000; + } + + + prepareValuesForTb(tbname, timestamp, values) { + + let keys = Object.keys(values); + + if (keys.includes("lifetime")) this.itIsNodeReadout = true; + + if (!this.previousValues.hasOwnProperty(tbname)) { + this.previousValues[tbname] = {}; + } + + //if(this.debug) console.log("prepareValuesForTb", tbname, timestamp, values); + + for (let i = 0; i < keys.length; i++) { + + let key = keys[i]; + let value = values[key]; + + if (!this.previousValues[tbname].hasOwnProperty(key)) { + this.previousValues[tbname][key] = { ts: timestamp, value: value }; + continue; + } + + // attributeData ==> {voltage: {ts:333333, value:5}} + let attributeData = this.previousValues[tbname][key]; + let attributeToChange = false; + if (key in this.attributeChangeLimit) attributeToChange = true; + let limit = this.attributeChangeLimit[key]; + let timestampDiffToRemoveKey; + + //this will ensure "node statecode" will be sent just once an hour + if (this.itIsNodeReadout && key === "statecode") { + attributeData.value = value; + this.itIsNodeReadout = false; + timestampDiffToRemoveKey = 1 * 60 * 60 * 1000; // 1 hour + } + + if (key === "twilight_sensor" && value > 100) { + attributeData.value = value; + } + + //if edge, master or node version do not change, send just once a day: + if (["edge_fw_version", "master_node_version", "fw_version"].includes(key)) { + timestampDiffToRemoveKey = 24 * 60 * 60 * 1000; + } + + if (attributeData.value === value || attributeToChange && Math.abs(attributeData.value - value) < limit) { + + let diff = timestamp - attributeData.ts; + if (!timestampDiffToRemoveKey) timestampDiffToRemoveKey = this.getDiffTimestamp(key); + + if (diff > timestampDiffToRemoveKey) { + attributeData.ts = Date.now(); + //if(this.debug) console.log(this.sender + ": update ts for key", key, "diff is", diff, "messageCounter", this.messageCounter); + } + else { + delete values[key]; + //if(this.debug) console.log(this.sender + ": delete key", key, "diff is", diff, "messageCounter", this.messageCounter, timestampDiffToRemoveKey); + } + } + else { + attributeData.value = value; + attributeData.ts = timestamp; + } + + } + + return values; + } +} + +module.exports = DataToTbHandler; + diff --git a/RVO45/flow/helper/ErrorToServiceHandler.js b/RVO45/flow/helper/ErrorToServiceHandler.js new file mode 100755 index 0000000..2b27c32 --- /dev/null +++ b/RVO45/flow/helper/ErrorToServiceHandler.js @@ -0,0 +1,91 @@ +const { MD5 } = require('./md5.js'); +const { networkInterfaces } = require('os'); + +class ErrorToServiceHandler { + constructor() { + this.previousValues = {}; + + this.project_id = undefined; + + const nets = networkInterfaces(); + this.ipAddresses = {}; + + for (const name of Object.keys(nets)) { + for (const net of nets[name]) { + // Skip over non-IPv4 and internal (i.e. 127.0.0.1) addresses + if (net.family === 'IPv4' && !net.internal) { + if (!this.ipAddresses[name]) { + this.ipAddresses[name] = []; + } + this.ipAddresses[name].push(net.address); + } + } + } + } + + setProjectId(project_id) { + this.project_id = project_id; + } + + processMessage(message, seconds) { + if (Array.isArray(message)) message = message.join(', '); + + let key = MD5(message); + let ts = Date.now(); + + //keep in memory - default value is 1h + if (seconds === undefined) seconds = 60 * 60; + + if (!this.previousValues.hasOwnProperty(key)) { + this.previousValues[key] = { ts: ts, duration: seconds }; + } + + let diff = (ts - this.previousValues[key].ts); + if (diff < this.previousValues[key].duration * 1000) return false; + + this.previousValues[key].ts = ts; + + return message; + } + + sendMessageToService(message, seconds, message_type) { + + // if error occures too early FLOW.GLOBALS.settings.project_id is still undefined + if (this.project_id === undefined) { + console.log("ErrorToServiceHandler.js: no project_id"); + return; + } + + let f = this.processMessage(message, seconds); + if (f === false) return; + + if (message_type === undefined) message_type = "error_message"; + + let toService = { + id: this.project_id, + ipAddresses: this.ipAddresses + }; + + //js_error || error_message + toService[message_type] = message; + + console.log("ErrorToServiceHandler------------------------>send to service", toService); + + RESTBuilder.make(function(builder) { + builder.method('POST'); + builder.post(toService); + builder.url('http://192.168.252.2:8004/sentmessage'); + + builder.callback(function(err, response, output) { + console.log("process.on error send", err, response, output, toService); + }); + }); + + } +} + +const errorHandler = new ErrorToServiceHandler(); + + +module.exports = errorHandler; +//module.exports = ErrorToServiceHandler; diff --git a/RVO45/flow/helper/db_helper.js b/RVO45/flow/helper/db_helper.js new file mode 100755 index 0000000..40e796c --- /dev/null +++ b/RVO45/flow/helper/db_helper.js @@ -0,0 +1,44 @@ +function promisifyBuilder(builder) +{ + return new Promise((resolve, reject) => { + + try{ + + builder.callback(function(err, response) { + + if(err != null) reject(err); + resolve(response); + }); + + } catch (error) { + reject(error); + } + }) +} + +function makeMapFromDbResult(response, ...keys) +{ + let s = "-"; + let data = {}; + + for(let i = 0; i < response.length; i++) + { + let record = response[i]; + + let k = []; + for(let j = 0; j < keys.length; j++) + { + k.push( record[keys[j]] ); + } + + let key = k.join(s); + data[ key ] = record; + } + + return data; +} + +module.exports = { + promisifyBuilder, + makeMapFromDbResult + } \ No newline at end of file diff --git a/RVO45/flow/helper/logger.js b/RVO45/flow/helper/logger.js new file mode 100755 index 0000000..2585639 --- /dev/null +++ b/RVO45/flow/helper/logger.js @@ -0,0 +1,30 @@ +//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/RVO45/flow/helper/md5.js b/RVO45/flow/helper/md5.js new file mode 100755 index 0000000..d3b0480 --- /dev/null +++ b/RVO45/flow/helper/md5.js @@ -0,0 +1,5 @@ +function MD5(d){var r = M(V(Y(X(d),8*d.length)));return r.toLowerCase()};function M(d){for(var _,m="0123456789ABCDEF",f="",r=0;r>>4&15)+m.charAt(15&_);return f}function X(d){for(var _=Array(d.length>>2),m=0;m<_.length;m++)_[m]=0;for(m=0;m<8*d.length;m+=8)_[m>>5]|=(255&d.charCodeAt(m/8))<>5]>>>m%32&255);return _}function Y(d,_){d[_>>5]|=128<<_%32,d[14+(_+64>>>9<<4)]=_;for(var m=1732584193,f=-271733879,r=-1732584194,i=271733878,n=0;n>16)+(_>>16)+(m>>16)<<16|65535&m}function bit_rol(d,_){return d<<_|d>>>32-_} + +module.exports = { + MD5 +} \ No newline at end of file diff --git a/RVO45/flow/helper/notification_reporter.js b/RVO45/flow/helper/notification_reporter.js new file mode 100755 index 0000000..839c12c --- /dev/null +++ b/RVO45/flow/helper/notification_reporter.js @@ -0,0 +1,121 @@ +//key is device, value = message {} +let sentValues = {}; +let notificationsData = null; +let rvoName; + +//sendNotification("CMD Manager: process cmd", SETTINGS.rvoTbName, "dimming_profile_was_successfully_received_by_node", { node: node }, "", SEND_TO.tb, instance); + +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 +}; + +function getKey(map, val) { + return Object.keys(map).findItem(key => map[key] === val); +} + +//https://stackoverflow.com/questions/41117799/string-interpolation-on-variable +var template = (tpl, args) => tpl.replace(/\${(\w+)}/g, (_, v) => args[v]); + + +function initNotification() { + notificationsData = FLOW.GLOBALS.notificationsData; + rvoName = FLOW.GLOBALS.settings.rvo_name; +} + + +function sendNotification(func, device, key, params, extra, tb_output, instance, saveKey) { + + let storeToSendValues = true; + if (saveKey == undefined) storeToSendValues = false; + + let weight = ""; + let message = {}; + + let notification = notificationsData[key]; + + if (notification) { + weight = notification.weight.toLowerCase(); + + Object.keys(notification).forEach(item => { + if (["en", "sk", "de", "cz", "it", "es"].includes(item)) { + message[item] = rvoName + ": " + template(notification[item], params); + } + }) + } + else { + //console.error("sendNotification: Notifications: undefined key", key, func, notificationsData); + console.error("sendNotification: Notifications: undefined key", key, func); + return false; + } + + //detect invalid err weight + if (getKey(ERRWEIGHT, weight) == undefined) { + console.error("sendNotification: Notifications: undefined weight", weight, key, func); + return false; + } + + if (sentValues.hasOwnProperty(saveKey)) { + if (JSON.stringify(sentValues[saveKey]) == JSON.stringify(message)) { + return false; + } + } + + if (sentValues[saveKey] == undefined) { + if (storeToSendValues) { + //do not send - flow is was started + sentValues[saveKey] = message; + return false; + } + } + + if (storeToSendValues) sentValues[saveKey] = message; + + let content = { + "type": weight, + "status": "new", + "source": { + "func": func, + "component": instance.id, + "component_name": instance.name, + "edge": device + }, + "message": message, + "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 + + return true; + +} + +module.exports = { + sendNotification, + ERRWEIGHT, + initNotification +} + diff --git a/RVO45/flow/helper/register.js b/RVO45/flow/helper/register.js new file mode 100755 index 0000000..fc1d008 --- /dev/null +++ b/RVO45/flow/helper/register.js @@ -0,0 +1,144 @@ +/* +0 - cislo registra / prikaz +1 - recepient - 0 = master, 1 = slave (slave je automaticky group a broadcast) +2 - r/rw - read/write +3- register name - nazov registra / prikazu (len pre info - zobrazenie v aplikacii) + +4,5,6,7, - jednotlive byte-y - nazov byte-u +4-7 - RES. a prazdny string "" sa nezobrazia!!! +*/ + +//124 zaznamov +const registers = [ + ["0","1","R","Status","","",""], + ["1","1","RW","Dimming","R-Channel ","G-Channel","B-Channel ","W - Channel"], + ["2","1","R","Device types","","",".",""], + ["3","1","RW","Group addresses 1-4","Groups Add. 4","Groups Add. 3","Groups Add. 2","Groups Add. 1"], + ["4","1","RW","Group addresses 5-8","Groups Add. 8","Groups Add. 7","Groups Add. 6","Groups Add. 5"], + ["5","1","RW","Serial number (MAC)","","","",""], + ["6","1","RW","Time of dusk","HH","MM","SS","EXTRA"], + ["7","1","RW","Time of dawn","HH","MM","SS","EXTRA"], + ["8","1","RW","Time Schedule settings","TBD","TBD","Movement sensor","Time Schedule"], + ["9","1","RW","TS1 Time point 1","HH","MM","SS","Ext. Device"], + ["10","1","RW","TS1 Time point 1 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["11","1","RW","TS1 Time point 2","HH","MM","SS","Ext. Device"], + ["12","1","RW","TS1 Time point 2 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["13","1","RW","TS1 Time point 3","HH","MM","SS","Ext. Device"], + ["14","1","RW","TS1 Time point 3 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["15","1","RW","TS1 Time point 4","HH","MM","SS","Ext. Device"], + ["16","1","RW","TS1 Time point 4 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["17","1","RW","TS1 Time point 5","HH","MM","SS","Ext. Device"], + ["18","1","RW","TS1 Time point 5 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["19","1","RW","TS1 Time point 6","HH","MM","SS","Ext. Device"], + ["20","1","RW","TS1 Time point 6 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["21","1","RW","TS1 Time point 7","HH","MM","SS","Ext. Device"], + ["22","1","RW","TS1 Time point 7 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["23","1","RW","TS1 Time point 8","HH","MM","SS","Ext. Device"], + ["24","1","RW","TS1 Time point 8 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["25","1","RW","TS1 Time point 9","HH","MM","SS","Ext. Device"], + ["26","1","RW","TS1 Time point 9 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["27","1","RW","TS1 Time point 10","HH","MM","SS","Ext. Device"], + ["28","1","RW","TS1 Time point 10 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["29","1","RW","TS1 Time point 11","HH","MM","SS","Ext. Device"], + ["30","1","RW","TS1 Time point 11 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["31","1","RW","TS1 Time point 12","HH","MM","SS","Ext. Device"], + ["32","1","RW","TS1 Time point 12 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["33","1","RW","TS1 Time point 13","HH","MM","SS","Ext. Device"], + ["34","1","RW","TS1 Time point 13 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["35","1","RW","TS1 Time point 14","HH","MM","SS","Ext. Device"], + ["36","1","RW","TS1 Time point 14 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["37","1","RW","TS1 Time point 15","HH","MM","SS","Ext. Device"], + ["38","1","RW","TS1 Time point 15 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["39","1","RW","TS1 Time point 16","HH","MM","SS","Ext. Device"], + ["40","1","RW","TS1 Time point 16 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["41","1","RW","TS2 Time point 1","HH","MM","SS","Ext. Device"], + ["42","1","RW","TS2 Time point 1 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["43","1","RW","TS2 Time point 2","HH","MM","SS","Ext. Device"], + ["44","1","RW","TS2 Time point 2 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["45","1","RW","TS2 Time point 3","HH","MM","SS","Ext. Device"], + ["46","1","RW","TS2 Time point 3 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["47","1","RW","TS2 Time point 4","HH","MM","SS","Ext. Device"], + ["48","1","RW","TS2 Time point 4 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["49","1","RW","TS2 Time point 5","HH","MM","SS","Ext. Device"], + ["50","1","RW","TS2 Time point 5 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["51","1","RW","TS2 Time point 6","HH","MM","SS","Ext. Device"], + ["52","1","RW","TS2 Time point 6 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["53","1","RW","TS2 Time point 7","HH","MM","SS","Ext. Device"], + ["54","1","RW","TS2 Time point 7 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["55","1","RW","TS2 Time point 8","HH","MM","SS","Ext. Device"], + ["56","1","RW","TS2 Time point 8 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["57","1","RW","TS2 Time point 9","HH","MM","SS","Ext. Device"], + ["58","1","RW","TS2 Time point 9 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["59","1","RW","TS2 Time point 10","HH","MM","SS","Ext. Device"], + ["60","1","RW","TS2 Time point 10 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["61","1","RW","TS2 Time point 11","HH","MM","SS","Ext. Device"], + ["62","1","RW","TS2 Time point 11 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["63","1","RW","TS2 Time point 12","HH","MM","SS","Ext. Device"], + ["64","1","RW","TS2 Time point 12 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["65","1","RW","TS2 Time point 13","HH","MM","SS","Ext. Device"], + ["66","1","RW","TS2 Time point 13 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["67","1","RW","TS2 Time point 14","HH","MM","SS","Ext. Device"], + ["68","1","RW","TS2 Time point 14 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["69","1","RW","TS2 Time point 15","HH","MM","SS","Ext. Device"], + ["70","1","RW","TS2 Time point 15 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["71","1","RW","TS2 Time point 16","HH","MM","SS","Ext. Device"], + ["72","1","RW","TS2 Time point 16 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["73","1","RW","Power meter status","TBD","","",""], + ["74","1","R","Input Voltage","","","",""], + ["75","1","R","Input Current","","","",""], + ["76","1","R","Input Power","","","",""], + ["77","1","R","Cos phi","","","",""], + ["78","1","R","Frequency","","","",""], + ["79","1","RW","Energy","","","",""], + ["80","1","RW","Lifetime","","","",""], + ["81","1","RW","Power on cycles (input)","","","",""], + ["82","1","RW","Power on cycles (relay)","","","",""], + ["83","1","R","Time since last power on","","","",""], + ["84","1","R","Accelerometer data","","","",""], + ["85","1","RW","GPS latitude","pos/neg","deg","min ","sec"], + ["86","1","RW","GPS longitude","pos/neg","deg","min ","sec"], + ["87","1","RW","Actual time","HH","MM","SS","RES."], + ["88","1","RW","Actual date","Day of week","Day","Month","Year"], + ["89","1","R","Production data 1","","","",""], + ["90","1","R","Production data 2","","","",""], + ["91","1","RW","Network ID","NID3","NID2","NID1","NID0"], + ["95","1","RW","Actual Lux level from cabinet","RES.","RES.","HB","LB"], + ["96","1","RW","Threshold lux level","Dusk HB","Dusk LB","Dawn HB","Dawn LB"], + ["97","1","RW","Adjust period","Dusk HB","Dusk LB","Dawn HB","Dawn LB"], + ["98","1","RW","Offset","RES.","RES.","Dusk","Dawn"], + ["99","1","RW","CCT min/max range","max-H","max-L","min-H","min-L"], + ["100","1","RW","DALI interface","Cmd ID","Add","Cmd","Resp"], + ["101","1","RW","Module FW ver","v1","v2","v3","v4"], + ["102","1","RW","Module MAC-H","unused","unused","M1","M2"], + ["103","1","RW","Module MAC-L","M3","M4","M5","M6"], + ["122","1","R","FW update status/control register","Byte3","Byte2","Byte1","Byte0"], + ["123","1","R","FW update - data index","Byte3","Byte2","Byte1","Byte0"], + ["124","1","R","FW update - data","Byte3","Byte2","Byte1","Byte0"], + ["0","0","R","Status","","","",""], + ["1","0","RW","Control register","RES.","RES.","RES.","init mode enable"], + ["2","0","R","Device types","","","",""], + ["3","0","R","Serial number (MAC)","","","",""], + ["4","0","R","Production data 1","","","",""], + ["5","0","R","Production data 2","","","",""], + ["6","0","RW","Network ID","NID3","NID2","NID1","NID0"], + ["7","0","RW","RS232 settings","param.","param.","Baudrate H","Baudrate L"], + ["8","0","R","Accelerometer data","","","",""], + ["9","0","RW","Module FW ver","v1","v2","v3","v4"], + ["10","0","RW","Module MAC-H","unused","unused","M1","M2"], + ["11","0","RW","Module MAC-L","M3","M4","M5","M6"], + ["32","0","RW","FW update status/control register","Byte3","Byte2","Byte1","Byte0"], + ["33","0","RW","FW update - data index","Byte3","Byte2","Byte1","Byte0"], + ["34","0","RW","FW update - data","Byte3","Byte2","Byte1","Byte0"], + ["125","0","RW","Debug Register","Byte3","Byte2","Byte1","Byte0"], + ["126","0","RW","Network Control Register","Byte3","Byte2","Byte1","Byte0"], + ["127","0","R","Network Status Register","Byte3","Byte2","Byte1","Byte0"], + ["128","0","RW","Node XX Serial Number Register","SER3","SER2","SER1","SER0"], + ["256","0","R","Node XX Network Status Register","","","",""] +]; + +let register = {}; + +module.exports = { + registers, + register +} \ No newline at end of file diff --git a/RVO45/flow/helper/serialport_helper.js b/RVO45/flow/helper/serialport_helper.js new file mode 100755 index 0000000..7f5920d --- /dev/null +++ b/RVO45/flow/helper/serialport_helper.js @@ -0,0 +1,99 @@ +const { exec } = require('child_process'); + +function openPort(port) { + return new Promise((resolve, reject) => { + + var callbackError = function(err) { + port.removeListener('error', callbackError); + port.removeListener('open', callbackError); + + reject(err.message); + }; + + var callbackOpen = function(data) { + port.removeListener('error', callbackError); + port.removeListener('open', callbackOpen); + + resolve("port open: ok"); + }; + + port.on('error', callbackError); + port.on('open', callbackOpen); + + port.open(); + + }) +} + +function runSyncExec(command) { + return new Promise((resolve, reject) => { + + exec(command, (error, stdout, stderr) => { + if (error == null) resolve(stdout); + reject(error); + }); + + }) +} + +async function writeData(port, data, readbytes, timeout) { + return new Promise((resolve, reject) => { + + // 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) { + + port.write(Buffer.from(data), function(err) { + if (err) { + reject(err.message); + } + }); + + 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 +} diff --git a/RVO45/flow/helper/suncalc.js b/RVO45/flow/helper/suncalc.js new file mode 100755 index 0000000..c9ca56d --- /dev/null +++ b/RVO45/flow/helper/suncalc.js @@ -0,0 +1,317 @@ +/* + (c) 2011-2015, Vladimir Agafonkin + SunCalc is a JavaScript library for calculating sun/moon position and light phases. + https://github.com/mourner/suncalc +*/ + +(function () { 'use strict'; + +// shortcuts for easier to read formulas + +var PI = Math.PI, + sin = Math.sin, + cos = Math.cos, + tan = Math.tan, + asin = Math.asin, + atan = Math.atan2, + acos = Math.acos, + rad = PI / 180; + +// sun calculations are based on http://aa.quae.nl/en/reken/zonpositie.html formulas + + +// date/time constants and conversions + +var dayMs = 1000 * 60 * 60 * 24, + J1970 = 2440588, + J2000 = 2451545; + +function toJulian(date) { return date.valueOf() / dayMs - 0.5 + J1970; } +function fromJulian(j) { return new Date((j + 0.5 - J1970) * dayMs); } +function toDays(date) { return toJulian(date) - J2000; } + + +// general calculations for position + +var e = rad * 23.4397; // obliquity of the Earth + +function rightAscension(l, b) { return atan(sin(l) * cos(e) - tan(b) * sin(e), cos(l)); } +function declination(l, b) { return asin(sin(b) * cos(e) + cos(b) * sin(e) * sin(l)); } + +function azimuth(H, phi, dec) { return atan(sin(H), cos(H) * sin(phi) - tan(dec) * cos(phi)); } +function altitude(H, phi, dec) { return asin(sin(phi) * sin(dec) + cos(phi) * cos(dec) * cos(H)); } + +function siderealTime(d, lw) { return rad * (280.16 + 360.9856235 * d) - lw; } + +function astroRefraction(h) { + if (h < 0) // the following formula works for positive altitudes only. + h = 0; // if h = -0.08901179 a div/0 would occur. + + // formula 16.4 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + // 1.02 / tan(h + 10.26 / (h + 5.10)) h in degrees, result in arc minutes -> converted to rad: + return 0.0002967 / Math.tan(h + 0.00312536 / (h + 0.08901179)); +} + +// general sun calculations + +function solarMeanAnomaly(d) { return rad * (357.5291 + 0.98560028 * d); } + +function eclipticLongitude(M) { + + var C = rad * (1.9148 * sin(M) + 0.02 * sin(2 * M) + 0.0003 * sin(3 * M)), // equation of center + P = rad * 102.9372; // perihelion of the Earth + + return M + C + P + PI; +} + +function sunCoords(d) { + + var M = solarMeanAnomaly(d), + L = eclipticLongitude(M); + + return { + dec: declination(L, 0), + ra: rightAscension(L, 0) + }; +} + + +var SunCalc = {}; + + +// calculates sun position for a given date and latitude/longitude + +SunCalc.getPosition = function (date, lat, lng) { + + var lw = rad * -lng, + phi = rad * lat, + d = toDays(date), + + c = sunCoords(d), + H = siderealTime(d, lw) - c.ra; + + return { + azimuth: azimuth(H, phi, c.dec), + altitude: altitude(H, phi, c.dec) + }; +}; + + +// sun times configuration (angle, morning name, evening name) + +var times = SunCalc.times = [ + [-0.833, 'sunrise', 'sunset' ], + [ -0.3, 'sunriseEnd', 'sunsetStart' ], + [ -6, 'dawn', 'dusk' ], + [ -12, 'nauticalDawn', 'nauticalDusk'], + [ -18, 'nightEnd', 'night' ], + [ 6, 'goldenHourEnd', 'goldenHour' ] +]; + +// adds a custom time to the times config + +SunCalc.addTime = function (angle, riseName, setName) { + times.push([angle, riseName, setName]); +}; + + +// calculations for sun times + +var J0 = 0.0009; + +function julianCycle(d, lw) { return Math.round(d - J0 - lw / (2 * PI)); } + +function approxTransit(Ht, lw, n) { return J0 + (Ht + lw) / (2 * PI) + n; } +function solarTransitJ(ds, M, L) { return J2000 + ds + 0.0053 * sin(M) - 0.0069 * sin(2 * L); } + +function hourAngle(h, phi, d) { return acos((sin(h) - sin(phi) * sin(d)) / (cos(phi) * cos(d))); } +function observerAngle(height) { return -2.076 * Math.sqrt(height) / 60; } + +// returns set time for the given sun altitude +function getSetJ(h, lw, phi, dec, n, M, L) { + + var w = hourAngle(h, phi, dec), + a = approxTransit(w, lw, n); + return solarTransitJ(a, M, L); +} + + +// calculates sun times for a given date, latitude/longitude, and, optionally, +// the observer height (in meters) relative to the horizon + +SunCalc.getTimes = function (date, lat, lng, height) { + + height = height || 0; + + var lw = rad * -lng, + phi = rad * lat, + + dh = observerAngle(height), + + d = toDays(date), + n = julianCycle(d, lw), + ds = approxTransit(0, lw, n), + + M = solarMeanAnomaly(ds), + L = eclipticLongitude(M), + dec = declination(L, 0), + + Jnoon = solarTransitJ(ds, M, L), + + i, len, time, h0, Jset, Jrise; + + + var result = { + solarNoon: fromJulian(Jnoon), + nadir: fromJulian(Jnoon - 0.5) + }; + + for (i = 0, len = times.length; i < len; i += 1) { + time = times[i]; + h0 = (time[0] + dh) * rad; + + Jset = getSetJ(h0, lw, phi, dec, n, M, L); + Jrise = Jnoon - (Jset - Jnoon); + + result[time[1]] = fromJulian(Jrise); + result[time[2]] = fromJulian(Jset); + } + + return result; +}; + + +// moon calculations, based on http://aa.quae.nl/en/reken/hemelpositie.html formulas + +function moonCoords(d) { // geocentric ecliptic coordinates of the moon + + var L = rad * (218.316 + 13.176396 * d), // ecliptic longitude + M = rad * (134.963 + 13.064993 * d), // mean anomaly + F = rad * (93.272 + 13.229350 * d), // mean distance + + l = L + rad * 6.289 * sin(M), // longitude + b = rad * 5.128 * sin(F), // latitude + dt = 385001 - 20905 * cos(M); // distance to the moon in km + + return { + ra: rightAscension(l, b), + dec: declination(l, b), + dist: dt + }; +} + +SunCalc.getMoonPosition = function (date, lat, lng) { + + var lw = rad * -lng, + phi = rad * lat, + d = toDays(date), + + c = moonCoords(d), + H = siderealTime(d, lw) - c.ra, + h = altitude(H, phi, c.dec), + // formula 14.1 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + pa = atan(sin(H), tan(phi) * cos(c.dec) - sin(c.dec) * cos(H)); + + h = h + astroRefraction(h); // altitude correction for refraction + + return { + azimuth: azimuth(H, phi, c.dec), + altitude: h, + distance: c.dist, + parallacticAngle: pa + }; +}; + + +// calculations for illumination parameters of the moon, +// based on http://idlastro.gsfc.nasa.gov/ftp/pro/astro/mphase.pro formulas and +// Chapter 48 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + +SunCalc.getMoonIllumination = function (date) { + + var d = toDays(date || new Date()), + s = sunCoords(d), + m = moonCoords(d), + + sdist = 149598000, // distance from Earth to Sun in km + + phi = acos(sin(s.dec) * sin(m.dec) + cos(s.dec) * cos(m.dec) * cos(s.ra - m.ra)), + inc = atan(sdist * sin(phi), m.dist - sdist * cos(phi)), + angle = atan(cos(s.dec) * sin(s.ra - m.ra), sin(s.dec) * cos(m.dec) - + cos(s.dec) * sin(m.dec) * cos(s.ra - m.ra)); + + return { + fraction: (1 + cos(inc)) / 2, + phase: 0.5 + 0.5 * inc * (angle < 0 ? -1 : 1) / Math.PI, + angle: angle + }; +}; + + +function hoursLater(date, h) { + return new Date(date.valueOf() + h * dayMs / 24); +} + +// calculations for moon rise/set times are based on http://www.stargazing.net/kepler/moonrise.html article + +SunCalc.getMoonTimes = function (date, lat, lng, inUTC) { + var t = new Date(date); + if (inUTC) t.setUTCHours(0, 0, 0, 0); + else t.setHours(0, 0, 0, 0); + + var hc = 0.133 * rad, + h0 = SunCalc.getMoonPosition(t, lat, lng).altitude - hc, + h1, h2, rise, set, a, b, xe, ye, d, roots, x1, x2, dx; + + // go in 2-hour chunks, each time seeing if a 3-point quadratic curve crosses zero (which means rise or set) + for (var i = 1; i <= 24; i += 2) { + h1 = SunCalc.getMoonPosition(hoursLater(t, i), lat, lng).altitude - hc; + h2 = SunCalc.getMoonPosition(hoursLater(t, i + 1), lat, lng).altitude - hc; + + a = (h0 + h2) / 2 - h1; + b = (h2 - h0) / 2; + xe = -b / (2 * a); + ye = (a * xe + b) * xe + h1; + d = b * b - 4 * a * h1; + roots = 0; + + if (d >= 0) { + dx = Math.sqrt(d) / (Math.abs(a) * 2); + x1 = xe - dx; + x2 = xe + dx; + if (Math.abs(x1) <= 1) roots++; + if (Math.abs(x2) <= 1) roots++; + if (x1 < -1) x1 = x2; + } + + if (roots === 1) { + if (h0 < 0) rise = i + x1; + else set = i + x1; + + } else if (roots === 2) { + rise = i + (ye < 0 ? x2 : x1); + set = i + (ye < 0 ? x1 : x2); + } + + if (rise && set) break; + + h0 = h2; + } + + var result = {}; + + if (rise) result.rise = hoursLater(t, rise); + if (set) result.set = hoursLater(t, set); + + if (!rise && !set) result[ye > 0 ? 'alwaysUp' : 'alwaysDown'] = true; + + return result; +}; + + +// export as Node module / AMD module / browser variable +if (typeof exports === 'object' && typeof module !== 'undefined') module.exports = SunCalc; +else if (typeof define === 'function' && define.amd) define(SunCalc); +else window.SunCalc = SunCalc; + +}()); diff --git a/RVO45/flow/helper/utils.js b/RVO45/flow/helper/utils.js new file mode 100755 index 0000000..dbffe45 --- /dev/null +++ b/RVO45/flow/helper/utils.js @@ -0,0 +1,161 @@ +const fs = require('fs').promises; + +function bytesToInt(bytes, numberOfBytes) { + let buffer = []; + if (Array.isArray(bytes)) { + buffer = bytes.slice(0); + if (numberOfBytes != undefined) { + buffer = bytes.slice(bytes.length - numberOfBytes); + } + } + else buffer.push(bytes); + + let result = 0; + for (let i = 0; i < buffer.length; i++) { + result = (result << 8) | buffer[i]; + } + + return result >>> 0; //ensure it's an unsigned 32-bit number +} + +function resizeArray(arr, newSize, defaultValue) { + while (newSize > arr.length) + arr.push(defaultValue); + arr.length = newSize; +} + +longToByteArray = function(/*long*/long) { + // we want to represent the input as a 8-bytes array + var byteArray = [0, 0, 0, 0, 0, 0, 0, 0]; + + for (var index = 0; index < byteArray.length; index++) { + var byte = long & 0xff; + byteArray[index] = byte; + long = (long - byte) / 256; + } + + return byteArray; +}; + +function addDays(date, days) { + var result = new Date(date); + result.setDate(result.getDate() + days); + return result; +} + +/* +sleep(2000).then(() => { + // Do something after the sleep! + + +}); +*/ + +function sleep(time) { + return new Promise((resolve) => setTimeout(resolve, time)); +} + +function isEmptyObject(obj) { + for (var name in obj) { + return false; + } + return true; +} + +function emptyJsObject(jsObject) { + Object.keys(jsObject).forEach(key => delete jsObject[key]); +} + +function convertUTCDateToLocalDate(date) { + var newDate = new Date(date); + newDate.setMinutes(date.getMinutes() + date.getTimezoneOffset()); + return newDate; +} + +function addZeroBefore(n) { + return (n < 10 ? '0' : '') + n; +} + + +/** + * Asynchronously writes data to a file. + * + * @param {string} filePath The path to the file. + * @param {string} data The data to write to the file. + * @param {boolean} [append=false] If true, appends the data to the file. If false, it overwrites the file. + */ +async function writeToFile(filePath, data, append = false) { + if (typeof data !== 'string') data = JSON.stringify(data, null, 2); + try { + if (append) { + // Append the data to the end of the file. This is the simplest way to append. + await fs.appendFile(filePath, data, 'utf8'); + console.log(`Successfully appended data to ${filePath} using fs.appendFile.`); + } else { + // Overwrite the file with the new data. + await fs.writeFile(filePath, data, 'utf8'); + console.log(`Successfully wrote (overwrote) data to ${filePath} using fs.writeFile.`); + } + } catch (error) { + console.error(`Error writing to file ${filePath}:`, error); + } +} + + + /** + * Checks if an item is present in an array and adds it if it's not. + * * @param {Array} arr The array to check. + * @param {*} item The item to add. + * @returns {Array} The modified array. + */ +const addToArrayIfUnique = (arr, item) => { + if (!arr.includes(item)) { + arr.push(item); + } + return arr; +}; + + +var convertBase = function() { + + function convertBase(baseFrom, baseTo) { + return function(num) { + return parseInt(num, baseFrom).toString(baseTo); + + }; + } + + // binary to decimal + convertBase.bin2dec = convertBase(2, 10); + + // binary to hexadecimal + convertBase.bin2hex = convertBase(2, 16); + + // decimal to binary + convertBase.dec2bin = convertBase(10, 2); + + // decimal to hexadecimal + convertBase.dec2hex = convertBase(10, 16); + + // hexadecimal to binary + convertBase.hex2bin = convertBase(16, 2); + + // hexadecimal to decimal + convertBase.hex2dec = convertBase(16, 10); + + return convertBase; +}(); + +module.exports = { + bytesToInt, + longToByteArray, + addDays, + addZeroBefore, + resizeArray, + isEmptyObject, + emptyJsObject, + sleep, + convertUTCDateToLocalDate, + writeToFile, + addToArrayIfUnique +} diff --git a/RVO45/flow/httprequest.js b/RVO45/flow/httprequest.js new file mode 100755 index 0000000..469c8cb --- /dev/null +++ b/RVO45/flow/httprequest.js @@ -0,0 +1,137 @@ +exports.id = 'httprequest'; +exports.title = 'HTTP Request'; +exports.group = 'HTTP'; +exports.color = '#5D9CEC'; +exports.input = true; +exports.version = '2.0.1'; +exports.output = 1; +exports.author = 'Peter Širka'; +exports.icon = 'cloud-upload'; + +exports.html = `
+
@(URL address)
+
+
+
@(HTTP method)
+
+
+
@(Serialization)
+
+
+
@(Download the content in chunks)
+
@(Keep persistent cookies)
+
@(Disable DNS cache)
+
@(Keep alive connection)
+
+
+
+
@(Custom headers)
+
@(Cookies)
+
+
+
+ +
+
+
+
@(User)
+
+
+
@(Password)
+
+
+
+
+
`; + +exports.readme = `# Request + +This component creates a request with received data. + +__Response:__ +\`\`\`javascript +{ + data: String, + headers: Object, + status: Number, + host: String +} +\`\`\` + +__Dynamic arguments__: +Are performed via FlowData repository and can be used for URL address or for custom headers/cookies/auth. Use \`repository\` component for creating of dynamic arguments. Dynamic values are replaced in the form \`{key}\`: + +- url address e.g. \`https://.../{key}/\` +- headers values e.g. \`{token}\` +- cookies values e.g. \`{token}\``; + +exports.install = function(instance) { + + var can = false; + var flags = null; + var cookies2 = null; + + instance.on('data', function(response) { + can && instance.custom.send(response); + }); + + instance.custom.send = function(response) { + var options = instance.options; + + var headers = null; + var cookies = null; + + options.headers && Object.keys(options.headers).forEach(function(key) { + !headers && (headers = {}); + headers[key] = response.arg(options.headers[key]); + }); + + if (options.username && options.userpassword) { + !headers && (headers = {}); + headers['Authorization'] = 'Basic ' + U.createBuffer(response.arg(options.username + ':' + options.userpassword)).toString('base64'); + } + + options.cookies && Object.keys(options.cookies).forEach(function(key) { + !cookies && (cookies = {}); + cookies[key] = response.arg(options.cookies[key]); + }); + + if (options.chunks) { + U.download(response.arg(options.url), flags, options.stringify === 'none' ? null : response.data, function(err, response) { + response.on('data', (chunks) => instance.send2(chunks)); + }, cookies || cookies2, headers); + } else { + U.request(response.arg(options.url), flags, options.stringify === 'none' ? null : response.data, 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) + instance.error(err, response); + }, cookies || cookies2, headers); + } + }; + + instance.reconfigure = function() { + var options = instance.options; + can = options.url && options.url && options.method && options.stringify ? true : false; + instance.status(can ? '' : 'Not configured', can ? undefined : 'red'); + + if (!can) + return; + + flags = []; + flags.push(options.method.toLowerCase()); + options.stringify === 'json' && flags.push('json'); + options.stringify === 'raw' && flags.push('raw'); + options.keepalive && flags.push('keepalive'); + !options.nodns && flags.push('dnscache'); + if (options.persistentcookies) { + flags.push('cookies'); + cookies2 = {}; + } else + cookies2 = null; + }; + + instance.on('options', instance.reconfigure); + instance.reconfigure(); +}; \ No newline at end of file diff --git a/RVO45/flow/httpresponse.js b/RVO45/flow/httpresponse.js new file mode 100755 index 0000000..160a3bb --- /dev/null +++ b/RVO45/flow/httpresponse.js @@ -0,0 +1,76 @@ +exports.id = 'httpresponse'; +exports.title = 'HTTP Response'; +exports.group = 'HTTP'; +exports.color = '#5D9CEC'; +exports.icon = 'arrow-right'; +exports.input = true; +exports.output = ['#666D76']; +exports.version = '2.0.0'; +exports.author = 'Martin Smola'; +exports.readme = `# HTTP response + +HTTP response will respond with data recieved using data-type set in Settings form or plain text if not set. Output is the message duration \`Number\` in seconds.`; + +exports.html = `
+
@(Response data-type)
+
JSON is by default.
+
`; + +exports.install = function(instance) { + + var dursum = 0; + var durcount = 0; + + instance.on('data', function(flowdata) { + + var ctrl = flowdata.repository.controller; + var data = flowdata.data; + + if (!ctrl) { + instance.throw('No controller to use for response!'); + return; + } + + durcount++; + dursum += ((new Date() - flowdata.begin) / 1000).floor(2); + setTimeout2(instance.id, instance.custom.duration, 500, 10); + + ctrl.$flowdata = flowdata; + + var datatype = instance.options.datatype || 'json'; + if (datatype === 'emptyresponse') + return ctrl.plain(''); + + if (datatype !== 'json' && typeof(data) !== 'string') { + instance.throw('Incorect type of data, expected string, got ' + typeof(data)); + ctrl.plain(data == null ? '' : data.toString()); + return; + } + + switch(datatype) { + case 'html': + ctrl.content(data, 'text/html'); + break; + case 'plain': + ctrl.plain(data); + break; + case 'xml': + ctrl.content(data, 'text/xml'); + break; + default: + ctrl.json(data); + break; + } + }); + + instance.on('service', function() { + dursum = 0; + durcount = 0; + }); + + instance.custom.duration = function() { + var avg = (dursum / durcount).floor(2); + instance.status(avg + ' sec.'); + instance.send2(0, avg); + }; +}; diff --git a/RVO45/flow/httproute.js b/RVO45/flow/httproute.js new file mode 100755 index 0000000..583a19d --- /dev/null +++ b/RVO45/flow/httproute.js @@ -0,0 +1,326 @@ +exports.id = 'httproute'; +exports.title = 'HTTP Route'; +exports.group = 'HTTP'; +exports.color = '#5D9CEC'; +exports.icon = 'globe'; +exports.input = false; +exports.output = ['#6CAC5A', '#37BC9B']; +exports.version = '1.2.3'; +exports.author = 'Martin Smola'; +exports.cloning = false; +exports.options = { method: 'GET', url: '', size: 5, cacheexpire: '5 minutes', cachepolicy: 0, timeout: 5 }; +exports.dateupdated = '2021-01-21 18:30d'; +exports.readme = `# HTTP route + +__Outputs__: +- first output: raw data (cache is empty or is disabled) +- second output: cached data + +If one of the outputs is disabled then automatic responce with code "503 service unavailable" is sent. + +When a request comes in bellow object is available at \`flowdata.data\`: + +\`\`\`javascript +{ + params: { id: '1' }, // params for dynamic routes, e.g. /test/{id} + query: { msg: 'Hello' }, // parsed query string, e.g. /test/1?msg=Hello + body: { test: 'OK' }, // object if json requests otherwise string + headers: {}, // headers data + session: {}, // session data + user: {}, // user data + files: [], // uploaded files + url: '/users/', // a relative URL address + referrer: '/', // referrer + mobile: false, // determines mobile device + robot: false, // determines search robots/crawlsers + language: 'en' // determines language +} +\`\`\` + +See [documentation for flags](https://docs.totaljs.com/latest/en.html#api~HttpRouteOptionsFlags~unauthorize). These method flags are set automatically e.g. \`get, post, put, patch or delete\` + +--- + +\`id:ROUTE_ID\` flag cannot be used since it's already used by this component internally`; + +exports.html = `
+
+ +
+ +
+
+
@(HTTP method)
+
+
+
@(URL address)
+
+
+
+
+
@(Additional flags)
+
@(Separate flags by comma e.g. json, authorize)
+
+
+
@(Max. request size)
+
@(In kB kilobytes)
+
+
+
@(Timeout)
+
@(In seconds.)
+
+
+
+
+
+
@(Automatically respond with 200 OK?)
+
@(If not checked you need to use HTTP response component to respond to the request.)
+
+
@(Custom headers)
+
@(Cookies)
+
+
+
+
+
+
@(Cache policy)
+
@(User instance must contain id property.)
+
+
+
@(Expiration)
+
@(E.g. 5 minutes)
+
+
+
+`; + +exports.install = function(instance) { + + var route; + + var uninstall = function(id) { + if (F.is4) { + route && route.remove(); + route = null; + } else + UNINSTALL('route', id); + }; + + instance.custom.emptyresponse = function(self) { + self.plain(); + }; + + instance.reconfigure = function() { + + var options = instance.options; + + if (!options.url) { + instance.status('Not configured', 'red'); + return; + } + + if (typeof(options.flags) === 'string') + options.flags = options.flags.split(',').trim(); + + uninstall('id:' + instance.id); + + var flags = options.flags || []; + + flags.push('id:' + instance.id); + + if (!F.is4) + flags.push(options.method.toLowerCase()); + + options.timeout && flags.push(options.timeout * 1000); + + // Make unique values + flags = flags.filter(function(v, i, a) { + if(F.is4 && v.toString().toLowerCase() === options.method.toLowerCase()) + return false; // remove method + return a.indexOf(v) === i; + }); + + options.flags = flags; + var handler = function() { + + if (instance.paused || (instance.isDisabled && (instance.isDisabled('output', 0) || instance.isDisabled('output', 1)))) { + instance.status('503 Service Unavailable'); + this.status = 503; + this.json(); + return; + } + + var key; + var self = this; + + if (instance.options.emptyresponse) { + instance.status('200 OK'); + setTimeout(instance.custom.emptyresponse, 100, self); + + if (instance.hasConnection(0)) { + var data = instance.make({ + query: self.query, + body: self.body, + session: self.session, + user: self.user, + files: self.files, + headers: self.req.headers, + url: self.url, + params: self.params + }); + instance.send2(0, data); + } + + return; + } + + switch (instance.options.cachepolicy) { + case 1: // URL + key = 'rro' + instance.id + self.url.hash(); + break; + case 2: // URL + query + case 3: // URL + query + user + key = self.url; + var keys = Object.keys(self.query); + keys.sort(); + for (var i = 0, length = keys.length; i < length; i++) + key += keys[i] + self.query[keys[i]] + '&'; + if (instance.options.cachepolicy === 3 && self.user) + key += 'iduser' + self.user.id; + key = 'rro' + instance.id + key.hash(); + break; + } + + if (key && F.cache.get2(key)) { + var data = instance.make(F.cache.get2(key)); + data.repository.controller = self; + instance.send2(1, data); + } else { + + var data = instance.make({ + query: self.query, + body: self.body, + session: self.session, + user: self.user, + files: self.files, + headers: self.req.headers, + url: self.url, + params: self.params, + mobile: self.mobile, + robot: self.robot, + referrer: self.referrer, + language: self.language + }); + + data.repository.controller = self; + instance.send2(0, data); + key && FINISHED(self.res, () => F.cache.set(key, self.$flowdata.data, instance.options.cacheexpire)); + } + }; + + if (F.is4) + route = ROUTE(options.method.toUpperCase() + ' ' + options.url, handler, flags, options.size || 5); + else + F.route(options.url, handler, flags, options.size || 5); + + instance.status('Listening', 'green'); + }; + + instance.reconfigure(); + instance.on('options', instance.reconfigure); + instance.on('close', function(){ + uninstall('id:' + instance.id); + }); +}; + +// check url exists +FLOW.trigger('httproutecheckurl', function(next, data) { + var url = data.url; + var method = data.method; + if (url[url.length - 1] !== '/') + url += '/'; + var exists = F.routes.web.findItem(r => r.urlraw === url && r.method === method); + next(exists != null); +}); + +exports.uninstall = function() { + FLOW.trigger('httproutecheckurl', null); +}; diff --git a/RVO45/flow/infosender.js b/RVO45/flow/infosender.js new file mode 100755 index 0000000..587724f --- /dev/null +++ b/RVO45/flow/infosender.js @@ -0,0 +1,81 @@ +exports.id = 'infosender'; +exports.title = 'Info sender'; +exports.version = '1.0.0'; +exports.group = 'Worksys'; +exports.color = '#2134B0'; +exports.input = 2; +exports.output = 1 +exports.icon = 'bolt'; + +const { networkInterfaces } = require('os'); + +exports.html = `
+
+
+
CSV Import
+
+
+
`; + +exports.readme = `# send all data to projects.worksys.io, required to monitor status of controller(unipi)`; + +exports.install = function(instance) { + + let id; + let allValues = {}; + let sendAllValuesInterval; + let configured = false; + + let now = new Date(); + console.log(exports.title, "INSTALLED", now.toLocaleString("sk-SK")); + + const nets = networkInterfaces(); + let ipAddresses = Object.create(null); // Or just '{}', an empty object + + for (const name of Object.keys(nets)) { + for (const net of nets[name]) { + // Skip over non-IPv4 and internal (i.e. 127.0.0.1) addresses + if (net.family === 'IPv4' && !net.internal) { + if (!ipAddresses[name]) { + ipAddresses[name] = []; + } + ipAddresses[name].push(net.address); + } + } + } + + function sendValues() { + if (!configured) return; + + if (Object.keys(allValues).length > 0) { + let dataToSend = { ...allValues }; + dataToSend.id = id; + dataToSend.ipAddresses = ipAddresses; + + instance.send(0, dataToSend); + + allValues = {}; + } + } + + instance.on("close", () => { + clearInterval(sendAllValuesInterval); + }) + + instance.on("0", _ => { + id = FLOW.GLOBALS.settings.project_id; + if (id) configured = true; + else console.log(exports.title, "InfoSender: Unable to send data, no id"); + }) + + instance.on("1", flowdata => { + allValues = { ...allValues, ...flowdata.data }; + //console.log("DATA RECEIVED", flowdata.data); + }) + + sendAllValuesInterval = setInterval(() => { + sendValues(); + }, 60000 * 3); + +} + diff --git a/RVO45/flow/modbus_reader.js b/RVO45/flow/modbus_reader.js new file mode 100755 index 0000000..d6d9dad --- /dev/null +++ b/RVO45/flow/modbus_reader.js @@ -0,0 +1,346 @@ +exports.id = 'modbus_reader'; +exports.title = 'Modbus reader'; +exports.version = '2.0.0'; +exports.group = 'Worksys'; +exports.color = '#2134B0'; +exports.input = 1; +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; +//number of phases inRVO +let phases; +//phases where voltage is 0 (set) +let noVoltage; +let energyToSwitchLamps; + +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.phases = this.buildPhases(); + + this.startSocket(); + } + + buildPhases = () => { + let a = []; + for (let i = 1; i <= phases; i++) { + a.push(`Phase_${i}_voltage`) + } + return a; + } + + startSocket = () => { + + let obj = this; + + if (this.socket) { + this.socket.removeAllListeners(); + this.socket = null; + } + + 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('Modbus_reader: Socket connection error', e); //'ECONNREFUSED' or 'ECONNRESET' ?? + }); + + this.socket.on('close', function() { + console.log('Modbus_reader: Socket connection closed - Waiting 10 seconds before connecting 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 we just start to loop devices from the beginning, or there is just 1 device in config, we wait whole timeoutInterval + if (this.indexInDeviceConfig == 0 || deviceConfig.length === 1) 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 (this.phases.includes(singleValue)) { + let l = singleValue.split("_"); + let phase = parseInt(l[1]); + + // console.log(values[singleValue], tbName); + + if (values[singleValue] == 0) { + noVoltage.add(phase); + sendNotification("modbus_reader: checkNullVoltage", tbName, "no_voltage_on_phase", { phase: phase }, "", SEND_TO.tb, instance, "voltage" + phase); + // console.log('no voltage') + } + else { + noVoltage.delete(phase); + // console.log('voltage detected') + sendNotification("modbus_reader: checkNullVoltage", tbName, "voltage_on_phase_restored", { phase: phase }, "", SEND_TO.tb, instance, "voltage" + phase); + } + } + }) + } + + /** + * function sends notification to slack and to tb, if EM total_power value changes more than numberOfNodes*15. This should show, that RVO lamps has been switched on or off + */ + lampSwitchNotification = (values) => { + + if (!values.hasOwnProperty("total_power")) return; + + const actualTotalPower = values.total_power; + + if (actualTotalPower > energyToSwitchLamps && 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 <= energyToSwitchLamps && 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; + } + + function main() { + + phases = FLOW.GLOBALS.settings.phases; + tbName = FLOW.GLOBALS.settings.rvoTbName; + noVoltage = FLOW.GLOBALS.settings.no_voltage; + energyToSwitchLamps = FLOW.GLOBALS.settings.energy_to_switch_lamps / 2.5; //half value is enought to show if lamps are turned on or off + if (deviceConfig.length) mainSocket = new SocketWithClients(); + else console.log("Modbus_reader: no modbus device in configuration"); + + // this notification is to show, that flow (unipi) has been restarted + sendNotification("modbus_reader", tbName, "flow_restart", {}, "", SEND_TO.slack, instance); + } + + instance.on("0", function(_) { + main(); + }) + +} + diff --git a/RVO45/flow/monitorconsumption.js b/RVO45/flow/monitorconsumption.js new file mode 100755 index 0000000..64cc58e --- /dev/null +++ b/RVO45/flow/monitorconsumption.js @@ -0,0 +1,156 @@ +exports.id = 'monitorconsumption'; +exports.title = 'Consumption'; +exports.version = '1.0.0'; +exports.author = 'Peter Širka'; +exports.group = 'Monitoring'; +exports.color = '#967ADC'; +exports.input = 0; +exports.output = 1; +exports.icon = 'bug'; +exports.options = { interval: 5000, enabled: true, monitorconsumption: true, monitorsize: true, monitorconnections: true, monitorfiles: true }; +exports.click = true; +exports.readme = `# Consumption monitoring + +This component measure CPU and memory consumption, open files and open connections of this application. It uses these Linux commands: \`ps\`, \`lsof\`, \`netstat\` and \`df\`. + +__Data Example__: + +\`\`\`javascript +{ + cpu: 0, // percentage + memory: 4096, // in bytes + size: 34303, // directory size in bytes + files: 34, // count of open files + connections: 343, // count of connections + uptime: '1-12:34:00' +} +\`\`\``; + +exports.html = `
+
+
+
@(Interval in milliseconds)
+
+
+
+
Monitor: Consumption + uptime
+
Monitor: Count of open files
+
Monitor: Count of open connections
+
Monitor: Directory size
+
`; + +exports.install = function(instance) { + + var current = { cpu: 0, memory: 0, files: 0, connections: 0, size: 0, uptime: '', counter: 0 }; + var tproc = null; + var Exec = require('child_process').exec; + var reg_empty = /\s{2,}/g; + var reg_appdisksize = /^[\d.,]+/; + + instance.custom.run = function() { + + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + + var arr = []; + + // Get CPU and Memory consumption + instance.options.monitorconsumption && arr.push(function(next) { + Exec('ps -p {0} -o %cpu,rss,etime'.format(process.pid), function(err, response) { + + if (err) { + instance.throw(err); + } else { + var line = response.split('\n')[1]; + line = line.trim().replace(reg_empty, ' ').split(' '); + var cpu = line[0].parseFloat(); + current.cpu = cpu.floor(1); + current.memory = line[1].parseInt2() * 1024; // kB to bytes + current.uptime = line[2]; + } + + next(); + }); + }); + + // Get count of open files + instance.options.monitorfiles && arr.push(function(next) { + Exec('lsof -a -p {0} | wc -l'.format(process.pid), function(err, response) { + if (err) + instance.throw(err); + else + current.files = response.trim().parseInt2(); + next(); + }); + }); + + // Get count of opened network connections + instance.options.monitorconnections && arr.push(function(next) { + Exec('netstat -an | grep :{0} | wc -l'.format(F.port), function(err, response) { + if (err) { + instance.throw(err); + } else { + current.connections = response.trim().parseInt2() - 1; + if (current.connections < 0) + current.connections = 0; + } + next(); + }); + }); + + // Get directory size + instance.options.monitorsize && current.counter % 5 !== 0 && arr.push(function(next) { + Exec('du -hsb ' + process.cwd(), function(err, response) { + if (err) { + instance.throw(err); + } else { + var match = response.trim().match(reg_appdisksize); + match && (current.size = match.toString().trim().parseInt2()); + } + next(); + }); + }); + + arr.async(function() { + + tproc && clearTimeout(tproc); + + if (instance.options.enabled) { + tproc = setTimeout(instance.custom.run, instance.options.interval); + instance.send2(current); + } + + instance.custom.status(); + current.counter++; + }); + }; + + instance.custom.status = function() { + if (instance.options.enabled) + instance.status('{0}% / {1}'.format(current.cpu, current.memory.filesize())); + else + instance.status('Disabled', 'red'); + }; + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + + if (instance.options.enabled) { + current.counter = 0; + instance.custom.run(); + } + + }); + + instance.on('close', function() { + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + }); + + setTimeout(instance.custom.run, 1000); +}; \ No newline at end of file diff --git a/RVO45/flow/monitordisk.js b/RVO45/flow/monitordisk.js new file mode 100755 index 0000000..f4fdaa0 --- /dev/null +++ b/RVO45/flow/monitordisk.js @@ -0,0 +1,96 @@ +exports.id = 'monitordisk'; +exports.title = 'Disk'; +exports.version = '1.0.0'; +exports.author = 'Peter Širka'; +exports.group = 'Monitoring'; +exports.color = '#F6BB42'; +exports.output = 1; +exports.icon = 'hdd-o'; +exports.click = true; +exports.options = { interval: 8000, path: '/', enabled: true }; +exports.readme = `# Disk monitoring + +This component monitors disk \`bytes\` consumption in Linux systems. It uses \`df\` command. + +__Data Example__: + +\`\`\`javascript +{ + total: 474549649408, + used: 39125245952, + free: 411294994432 +} +\`\`\``; + +exports.html = `
+
+
+
@(Interval in milliseconds)
+
+
+
@(Path)
+
+
+
`; + +exports.install = function(instance) { + + var current = { total: 0, used: 0, free: 0, path: '', type: '', percentUsed: 0 }; + var tproc = null; + + instance.custom.run = function() { + + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + + if (!instance.options.enabled) + return; + + require('child_process').exec('df -hTB1 ' + instance.options.path, function(err, response) { + + tproc = setTimeout(instance.custom.run, instance.options.interval); + + if (err) { + instance.error(err); + return; + } + + response.parseTerminal(function(line) { + if (line[0][0] !== '/') + return; + current.total = line[2].parseInt(); + current.free = line[4].parseInt(); + current.used = line[3].parseInt(); + current.path = instance.options.path || '/'; + current.type = line[1]; + current.percentUsed = line[5]; + instance.custom.status(); + instance.send2(current); + }); + }); + }; + + instance.custom.status = function() { + if (instance.options.enabled) + instance.status(current.free.filesize() + ' / ' + current.total.filesize()); + else + instance.status('Disabled', 'red'); + }; + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + instance.options.enabled && instance.custom.run(); + }); + + instance.on('close', function() { + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + }); + + setTimeout(instance.custom.run, 1000); +}; \ No newline at end of file diff --git a/RVO45/flow/monitormemory.js b/RVO45/flow/monitormemory.js new file mode 100755 index 0000000..2decbc4 --- /dev/null +++ b/RVO45/flow/monitormemory.js @@ -0,0 +1,87 @@ +exports.id = 'monitormemory'; +exports.title = 'Memory'; +exports.version = '1.0.0'; +exports.author = 'Peter Širka'; +exports.group = 'Monitoring'; +exports.color = '#F6BB42'; +exports.output = 1; +exports.click = true; +exports.icon = 'microchip'; +exports.options = { interval: 8000, enabled: true }; +exports.readme = `# Memory monitoring + +This component monitors memory \`bytes\` consumption in Linux systems. It uses \`free\` command. + +__Data Example__: + +\`\`\`javascript +{ + total: 33558769664, + used: 1998868480, + free: 2653708288 +} +\`\`\``; + +exports.html = `
+
+
+
@(Interval in milliseconds)
+
+
+
`; + +exports.install = function(instance) { + + var current = { total: 0, used: 0, free: 0 }; + var tproc = null; + + instance.custom.run = function() { + + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + + if (!instance.options.enabled) + return; + + require('child_process').exec('free -b -t', function(err, response) { + + tproc = setTimeout(instance.custom.run, instance.options.interval); + + if (err) { + instance.error(err); + return; + } + + var memory = response.split('\n')[1].match(/\d+/g); + current.total = memory[0].parseInt(); + current.used = memory[1].parseInt() - memory[3].parseInt(); + current.free = current.total - current.used; + instance.custom.status(); + instance.send2(current); + }); + }; + + instance.custom.status = function() { + if (instance.options.enabled) + instance.status(current.free.filesize() + ' / ' + current.total.filesize()); + else + instance.status('Disabled', 'red'); + }; + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + instance.options.enabled && instance.custom.run(); + }); + + instance.on('close', function() { + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + }); + + setTimeout(instance.custom.run, 1000); +}; \ No newline at end of file diff --git a/RVO45/flow/nodesdb_changecheck.js b/RVO45/flow/nodesdb_changecheck.js new file mode 100755 index 0000000..9adab62 --- /dev/null +++ b/RVO45/flow/nodesdb_changecheck.js @@ -0,0 +1,77 @@ +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 = 2; +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); + } + } + + //kedze do slacku posielame stringy, na cloud musime previest vsetky stringy spat na objekty: + // Funkcia na parsovanie všetkých reťazcov v poli + const parseArray = (arr) => { + return arr.map(jsonString => JSON.parse(jsonString)); + }; + + 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); + if (FLOW.GLOBALS.settings.send_changed_node_numbers) instance.send(1, { aktualneNody: parseArray(zmenene), originalne: parseArray(Array.from(set2)) }); + } + 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/RVO45/flow/show_dbdata.js b/RVO45/flow/show_dbdata.js new file mode 100755 index 0000000..1e23ff7 --- /dev/null +++ b/RVO45/flow/show_dbdata.js @@ -0,0 +1,243 @@ +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 = 8; +exports.output = 1; + +const { exec } = require('child_process'); + +exports.install = 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 }) + }) + instance.on("5", _ => { + exec("sudo tail -n 25 monitor.txt", (err, stdout, stderr) => { + if (err || stderr) instance.send(0, { err, stderr }); + else instance.send(0, stdout); + }) + }) + instance.on("6", _ => { + exec("sudo tail -n 25 err.txt", (err, stdout, stderr) => { + if (err || stderr) instance.send(0, { err, stderr }); + else instance.send(0, stdout); + }) + }) + instance.on("7", _ => { + instance.send(0, FLOW.deviceStatus); + }) +}; + + +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/RVO45/flow/slack_filter.js b/RVO45/flow/slack_filter.js new file mode 100755 index 0000000..6618523 --- /dev/null +++ b/RVO45/flow/slack_filter.js @@ -0,0 +1,188 @@ +exports.id = 'slack_filter'; +exports.title = 'Slack Filter'; +exports.group = 'Citysys'; +exports.color = '#30E193'; +exports.input = 2; +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 = `
+
+
+
@(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('0', 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']['en']; + 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"] = []; + } + + instance.options.name = FLOW.GLOBALS.settings.rvo_name; + if (instance.options.name) { + instance.status('Running'); + running = true; + } else { + instance.status('Please run options again', 'red'); + running = false; + } + } catch (e) { + instance.error('Citysys connector: ' + e.message); + } + }; + + instance.on('options', instance.reconfigure); + + instance.on("1", _ => { + instance.reconfigure(); + }) +}; diff --git a/RVO45/flow/thermometer.js b/RVO45/flow/thermometer.js new file mode 100755 index 0000000..fc7074d --- /dev/null +++ b/RVO45/flow/thermometer.js @@ -0,0 +1,99 @@ +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 = 5;//minutes +let NUMBER_OF_FAILURES_TO_SEND_ERROR = 13; + +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) => { + + 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); + setTimeout(main, 20000); + }) +}; diff --git a/RVO45/flow/trigger.js b/RVO45/flow/trigger.js new file mode 100755 index 0000000..27545a8 --- /dev/null +++ b/RVO45/flow/trigger.js @@ -0,0 +1,79 @@ +exports.id = 'trigger'; +exports.title = 'Trigger'; +exports.group = 'Inputs'; +exports.color = '#F6BB42'; +exports.click = true; +exports.output = 1; +exports.version = '1.1.0'; +exports.author = 'Martin Smola'; +exports.icon = 'play'; + +exports.html = `
+
@(Data type (String by default))
+
@(Data)
+
Trigger 5s after initialization.
+
@(Useful when there's a need to run certain flow when the app restarts, etc.)
+
`; + +exports.readme = `# Trigger + +- Clicking on the component starts the chain +- Settings allows to set a data-type and a value`; + +exports.install = function(instance) { + + var value; + + instance.on('click', () => instance.send2(value)); + + instance.reconfigure = function() { + var options = instance.options; + value = null; + switch (options.datatype) { + case 'integer': + value = options.data.parseInt2('error'); + value = value === 'error' ? NaN : value; + break; + case 'float': + value = options.data.parseFloat2('error'); + value = value === 'error' ? NaN : value; + break; + case 'date': + options.data = options.data.toString(); + var num = options.data.parseInt('error'); + num === 'error' && (num = options.data.parseDate('error')); + num === 'error' && (num = null); + value = num ? new Date(num).toUTCString() : num; + break; + case 'object': + try { + value = (new Function('return ' + options.data))(); + } catch (e) { + instance.error(e); + } + break; + case 'boolean': + value = options.data.parseBoolean(); + break; + case 'buffer': + try { + value = U.createBuffer(options.data); + } catch (e) { + instance.error(e); + } + break; + case 'string': + default: + value = '' + (options.data || ''); + break; + } + }; + + instance.on('options', instance.reconfigure); + instance.reconfigure(); + + if (instance.options.restart) + setTimeout(function(){ + instance.send2(value); + }, 5000); +}; diff --git a/RVO45/flow/variables.txt b/RVO45/flow/variables.txt new file mode 100755 index 0000000..e69de29 diff --git a/RVO45/flow/virtualwirein.js b/RVO45/flow/virtualwirein.js new file mode 100755 index 0000000..38a4e42 --- /dev/null +++ b/RVO45/flow/virtualwirein.js @@ -0,0 +1,43 @@ +exports.id = 'virtualwirein'; +exports.title = 'Virtual wire in'; +exports.version = '1.0.0'; +exports.author = 'Martin Smola'; +exports.color = '#303E4D'; +exports.icon = 'sign-in'; +exports.input = false; +exports.output = 1; +exports.options = {}; +exports.readme = `# Virtual wire in + +When the wires between the components are mess it's time to use Virtual wire.`; + +exports.html = `
+
@(Wire name)
+
+`; + +exports.install = function(instance) { + + instance.custom.reconfigure = function(options){ + if (instance.options.wirename) { + instance.status(instance.options.wirename); + } else + instance.status('Not configured', 'red'); + }; + + ON('virtualwire', function(wirename, flowdata){ + if (instance.options.wirename && instance.options.wirename === wirename) + instance.send(flowdata); + }); + + instance.on('options', instance.custom.reconfigure); + instance.custom.reconfigure(); +}; diff --git a/RVO45/flow/virtualwireout.js b/RVO45/flow/virtualwireout.js new file mode 100755 index 0000000..94a1e4f --- /dev/null +++ b/RVO45/flow/virtualwireout.js @@ -0,0 +1,41 @@ +exports.id = 'virtualwireout'; +exports.title = 'Virtual wire out'; +exports.version = '1.0.0'; +exports.author = 'Martin Smola'; +exports.color = '#303E4D'; +exports.icon = 'sign-out'; +exports.input = true; +exports.options = {}; +exports.readme = `# Virtual wire out + +When the wires between the components are mess it's time to use Virtual wire.`; + +exports.html = `
+
@(Wire name)
+
+`; + +exports.install = function(instance) { + + instance.custom.reconfigure = function(){ + if (instance.options.wirename) { + instance.status(instance.options.wirename); + } else + instance.status('Not configured', 'red'); + }; + + instance.on('data', function(flowdata) { + EMIT('virtualwire', instance.options.wirename, flowdata); + }); + + instance.on('options', instance.custom.reconfigure); + instance.custom.reconfigure(); +}; diff --git a/RVO45/flow/wsmqttpublish.js b/RVO45/flow/wsmqttpublish.js new file mode 100755 index 0000000..0eba804 --- /dev/null +++ b/RVO45/flow/wsmqttpublish.js @@ -0,0 +1,448 @@ +exports.id = 'wsmqttpublish'; +exports.title = 'WS MQTT publish'; +exports.group = 'MQTT'; +exports.color = '#888600'; +exports.version = '1.0.2'; +exports.icon = 'sign-out'; +exports.input = 2; +exports.output = 3; +exports.options = { host: 'tb-stage.worksys.io', port: 1883, clientid: "", username: "" }; + +exports.html = `
+
+
+
Hostname or IP address (if not empty - setting will override db setting)
+
+
+
Port
+
+
+
+
+
@(Client id)
+
+
+
@(Username)
+
+
+
`; + + +exports.readme = ` +# WS MQTT Publish + +Version 1.0.3. + +Added: +- database collections, +- 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 = { + debug: 0, + rpcCall: 1, + services: 2 +} + +//CONFIG +let createTelemetryBackup = true; +let saveTelemetryOnError = true;//backup_on_failure overrides this value +//------------------------ + +let rollers; +if (createTelemetryBackup) rollers = require('streamroller'); + +const noSqlFileSizeLimit = 4194304;//use 5MB - 4194304 +let insertNoSqlCounter = 0; +let insertBackupNoSqlCounter = 0; +let processingData = false; + +let backup_on_failure = false;//== saveTelemetryOnError - create backup client 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; + +process.on('uncaughtException', function(err) { + + errLogger.error('uncaughtException:', err.message) + errLogger.error(err.stack); + + //TODO + //send to service + + //process.exit(1); +}) + +const nosql = NOSQL('tbdata'); +const nosqlBackup = NOSQL('/backup/tbdata'); + + +exports.install = function(instance) { + + var client; + var opts; + var clientReady = false; + + // wsmqtt status for notification purposes on projects.worksys.io database + let wsmqttName = null; + let sendWsStatusVar = null; + let wsmqtt_status = 'disconnected'; + + 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'; + } + + function sendWsStatus() { + instance.send(SEND_TO.services, { [wsmqttName]: wsmqtt_status }); + } + + + function main() { + if (!FLOW.dbLoaded) return; + + loadSettings(); + clearInterval(sendWsStatus); + sendWsStatusVar = setInterval(sendWsStatus, 180000); + } + + //set opts according to db settings + function loadSettings() { + + if (instance.options.host !== "") { + //override settings from database + var o = instance.options; + opts = { + host: o.host, + port: o.port, + clientId: o.clientid, + username: o.username, + rejectUnauthorized: false, + resubscribe: false + }; + + wsmqttName = getWsmqttName(o.host); + + console.log("wsmqttpublich -> loadSettings from instance.options", instance.options); + } + else { + + const SETTINGS = FLOW.GLOBALS.settings; + backup_on_failure = SETTINGS.backup_on_failure; + saveTelemetryOnError = backup_on_failure; + + restore_from_backup = SETTINGS.restore_from_backup; + restore_backup_wait = SETTINGS.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; + + opts = { + host: mqtt_host, + port: mqtt_port, + keepalive: 10, + clientId: mqtt_clientid, + username: mqtt_username, + rejectUnauthorized: false, + resubscribe: false + }; + + wsmqttName = getWsmqttName(mqtt_host); + } + + connectToTbServer(); + } + + function connectToTbServer() { + 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"); + //monitor.info("MQTT client connected"); + + sendClientError = true; + clientReady = true; + wsmqtt_status = 'connected'; + }); + + client.on('reconnect', function() { + instance.status("Reconnecting", "yellow"); + clientReady = false; + }); + + client.on('message', function(topic, message) { + // message is type of buffer + message = message.toString(); + if (message[0] === '{') { + TRY(function() { + + message = JSON.parse(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 } }); + } + + }, () => instance.debug('MQTT: Error parsing data', message)); + } + + instance.send(SEND_TO.rpcCall, { "topic": topic, "content": message }); + }); + + client.on('close', function() { + clientReady = false; + wsmqtt_status = 'disconnected'; + + instance.status("Disconnected", "red"); + instance.send(SEND_TO.debug, { "message": "Client CLOSE signal received !" }); + }); + + client.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; + wsmqtt_status = 'disconnected'; + }); + + } + + + instance.on("0", _ => { + main(); + }) + + + instance.on('1', function(data) { + + if (clientReady) { + //do we have some data in backup file? if any, process data from database + if (saveTelemetryOnError) { + //read telemetry data and send back to server + if (!processingData) processDataFromDatabase(); + } + + let stringifiedJson = JSON.stringify(data.data); + client.publish("v1/gateway/telemetry", stringifiedJson, { qos: 1 }); + + //backup telemetry + if (createTelemetryBackup) { + data.data.id = UID(); + nosqlBackup.insert(data.data); + + insertBackupNoSqlCounter++; + if (insertBackupNoSqlCounter > 150) { + let options = { compress: true }; + let path = __dirname + "/../databases/backup/tbdata.nosql"; + var stream = new rollers.RollingFileStream(path, noSqlFileSizeLimit, 150, options); + stream.write(""); + stream.end(); + + insertBackupNoSqlCounter = 0; + } + } + + } + 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 (saveTelemetryOnError) { + //create new file from tbdata.nosql, if file size exceeds given limit, and clear tbdata.nosql + makeBackupFromDbFile(); + + //write to tb + data.data.id = UID(); + nosql.insert(data.data); + } + } + }); + + + instance.close = function(done) { + if (clientReady) { + client.end(); + clearInterval(sendWsStatusVar); + } + }; + + + function getDbBackupFileCounter(type) { + var files = fs.readdirSync(__dirname + "/../databases"); + + let counter = 0; + for (var i = 0; i < files.length; i++) { + + if (files[i] == "tbdata.nosql") continue; + + if (files[i].endsWith(".nosql")) { + + let pos = files[i].indexOf("."); + if (pos > -1) { + + let fileCounter = counter; + let firstDigit = files[i].slice(0, pos); + + fileCounter = parseInt(firstDigit); + if (isNaN(fileCounter)) fileCounter = 0; + //console.log("getDbBackupFileCounter digit:", files[i], firstDigit, fileCounter, isNaN(fileCounter), type); + + if (type == "max") { + if (fileCounter > counter) { + counter = fileCounter; + } + } + else if (type == "min") { + if (counter == 0) counter = fileCounter; + + if (fileCounter < counter) { + counter = fileCounter; + } + } + } + } + + } + + if (type == "max") counter++; + + return counter; + } + + const makeBackupFromDbFile = async () => { + + if (!saveTelemetryOnError) return; + + //to avoid large file: tbdata.nosql + + //init value is 0! + if (insertNoSqlCounter > 0) { + --insertNoSqlCounter; + return; + } + + insertNoSqlCounter = 100; + + let source = __dirname + "/../databases/tbdata.nosql"; + + var stats = fs.statSync(source); + var fileSizeInBytes = stats.size; + + if (fileSizeInBytes > noSqlFileSizeLimit) { + + let counter = 1; + counter = getDbBackupFileCounter("max"); + + let destination = __dirname + "/../databases/" + counter + "." + "tbdata.nosql"; + + //make backup file + fs.copyFileSync(source, destination); + //fs.renameSync(p, p + "." + counter); + + //clear tbdata.nosql + fs.writeFileSync(source, ""); + fs.truncateSync(source, 0); + + } + } + + const processDataFromDatabase = async () => { + + if (restore_from_backup <= 0) return; + + //calculate diff + const now = new Date(); + let currentTime = now.getTime(); + let diff = currentTime - lastRestoreTime; + + if ((diff / 1000) < restore_backup_wait) { + //console.log("*********restore_backup_wait", diff, restore_backup_wait); + return; + } + + processingData = true; + + //get filename to process + let counter = getDbBackupFileCounter("min"); + + //we have some backup files + let dataBase = 'tbdata'; + + var nosql; + if (counter == 0) dataBase = 'tbdata'; + else dataBase = counter + "." + 'tbdata'; + + nosql = NOSQL(dataBase); + + //select all data - use limit restore_from_backup + let records = await promisifyBuilder(nosql.find().take(restore_from_backup)); + + for (let i = 0; i < records.length; i++) { + if (clientReady) { + + let item = records[i]; + let id = item.id; + + if (id !== undefined) { + //console.log("------------processDataFromDatabase - remove", id, dataBase, i); + + try { + + let message = JSON.parse(JSON.stringify(item)); + delete message.id; + + client.publish("v1/gateway/telemetry", JSON.stringify(message), { qos: 1 }); + + //remove from database + await promisifyBuilder(nosql.remove().where("id", id)); + + } catch (error) { + //process error + console.log("processDataFromDatabase", error); + } + + } + + } + else { + processingData = false; + return; + } + } + + if (records.length > 0) { + //clean backup file + if (counter > 0) nosql.clean(); + } + + //no data in db, remove + if (records.length == 0) { + if (counter > 0) nosql.drop(); + } + + const d = new Date(); + lastRestoreTime = d.getTime(); + + processingData = false; + + } + + instance.on('options', main); + //instance.reconfigure(); +}; diff --git a/RVO45/flow_pred_verziou_2025_01_30/cloudmqttconnect.js b/RVO45/flow_pred_verziou_2025_01_30/cloudmqttconnect.js new file mode 100755 index 0000000..d619784 --- /dev/null +++ b/RVO45/flow_pred_verziou_2025_01_30/cloudmqttconnect.js @@ -0,0 +1,374 @@ +exports.id = 'cloudmqttconnect'; +exports.title = 'Cloud connect mqtt'; +exports.group = 'MQTT'; +exports.color = '#888600'; +exports.version = '1.0.2'; +exports.icon = 'sign-out'; +exports.input = 2; +exports.output = 2; +exports.options = { host: 'tb-stage.worksys.io', port: 1883, clientid: "", username: "" }; + +exports.html = `
+
+
+
Hostname or IP address (if not empty - setting will override db setting)
+
+
+
Port
+
+
+
+
+
@(Client id)
+
+
+
topic
+
+
+
`; + + + +const { promisifyBuilder } = require('./helper/db_helper'); +const fs = require('fs'); +const mqtt = require('mqtt'); +const nosql = NOSQL('tbdatacloud'); + +const SEND_TO = { + debug: 0, + rpcCall: 1, +} + +//CONFIG +let saveTelemetryOnError = true;//backup_on_failure overrides this value +//------------------------ + +const noSqlFileSizeLimit = 4194304;//use 5MB - 4194304 +let insertNoSqlCounter = 0; +let insertBackupNoSqlCounter = 0; +let processingData = false; + +let backup_on_failure = true;//== saveTelemetryOnError - create backup client send failure +let restore_from_backup = 50; //how many rows process at once? +let restore_backup_wait = 3;//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; + + +exports.install = function(instance) { + + var client; + var opts; + var clientReady = false; + + let o = null; //options + + function main() + { + loadSettings(); + } + + //set opts according to db settings + function loadSettings() + { + + o = instance.options; + if(!o.topic) o.topic = FLOW.GLOBALS.settings.cloud_topic; + + opts = { + host: o.host, + port: o.port, + clientId: o.clientid, + username: o.username, + rejectUnauthorized: false, + resubscribe: false + }; + + console.log("wsmqttpublich -> loadSettings from instance.options",o); + + connectToTbServer(); + } + + function connectToTbServer() + { + var url = "mqtt://" + opts.host + ":" + opts.port; + console.log("MQTT URL: ", url); + + client = mqtt.connect(url, opts); + + client.on('connect', function() { + client.subscribe(`${o.topic}_backward`, (err) => { + if (!err) { + console.log("MQTT subscribed"); + } + }); + instance.status("Connected", "green"); + clientReady = true; + sendClientError = true; + }); + + client.on('reconnect', function() { + instance.status("Reconnecting", "yellow"); + clientReady = false; + }); + + client.on('message', function(topic, message) { + // message is type of buffer + message = message.toString(); + if (message[0] === '{') { + TRY(function() { + + message = JSON.parse(message); + if (message.hasOwnProperty("device") && message.hasOwnProperty("data") && message.data.hasOwnProperty("id")) { + client.publish(`${o.topic}_forward`, `{"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}}); + } + + }, () => instance.debug('MQTT: Error parsing data', message)); + } + + instance.send(SEND_TO.rpcCall, {"topic":o.topic, "content":message }); + }); + + client.on('close', function() { + clientReady = false; + + instance.status("Disconnected", "red"); + instance.send(SEND_TO.debug, {"message":"Client CLOSE signal received !"}); + }); + + client.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) { + console.log('MQTT client error', err); + sendClientError = false; + } + clientReady = false; + }); + + } + + + instance.on('0', function(data) { + + if(clientReady) + { + //do we have some data in backup file? if any, process data from database + if(saveTelemetryOnError) + { + //read telemetry data and send back to server + if(!processingData) processDataFromDatabase(); + } + + let stringifiedJson = JSON.stringify(data.data) + client.publish(`${o.topic}_forward`, stringifiedJson, {qos: 1}); + } + 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(saveTelemetryOnError) + { + //create new file from tbdata.nosql, if file size exceeds given limit, and clear tbdata.nosql + makeBackupFromDbFile(); + + //write to tb + data.data.id = UID(); + nosql.insert(data.data); + } + } + }); + + instance.on("1", _ => { + main(); + }) + + instance.close = function(done) { + if(clientReady){ + client.end(); + } + }; + + + function getDbBackupFileCounter(type) + { + var files = fs.readdirSync(__dirname + "/../databases"); + + let counter = 0; + for(var i = 0; i < files.length; i++) + { + + if(files[i] == "tbdatacloud.nosql") continue; + + if(files[i].endsWith(".nosql")) + { + + let pos = files[i].indexOf("."); + if(pos > -1) + { + + let fileCounter = counter; + let firstDigit = files[i].slice(0, pos); + + fileCounter = parseInt(firstDigit); + if(isNaN(fileCounter)) fileCounter = 0; + //console.log("getDbBackupFileCounter digit:", files[i], firstDigit, fileCounter, isNaN(fileCounter), type); + + if(type == "max") + { + if(fileCounter > counter) + { + counter = fileCounter; + } + } + else if(type == "min") + { + if(counter == 0) counter = fileCounter; + + if(fileCounter < counter) + { + counter = fileCounter; + } + } + } + } + + } + + if(type == "max") counter++; + + return counter; + } + + const makeBackupFromDbFile = async () => { + + if(!saveTelemetryOnError) return; + + //to avoid large file: tbdata.nosql + + //init value is 0! + if(insertNoSqlCounter > 0) + { + --insertNoSqlCounter; + return; + } + + insertNoSqlCounter = 100; + + let source = __dirname + "/../databases/tbdatacloud.nosql"; + + var stats = fs.statSync(source); + var fileSizeInBytes = stats.size; + + if(fileSizeInBytes > noSqlFileSizeLimit) + { + + let counter = 1; + counter = getDbBackupFileCounter("max"); + + let destination = __dirname + "/../databases/" + counter + "." + "tbdatacloud.nosql"; + + //make backup file + fs.copyFileSync(source, destination); + //fs.renameSync(p, p + "." + counter); + + //clear tbdata.nosql + fs.writeFileSync(source, ""); + fs.truncateSync(source, 0); + + } + } + + const processDataFromDatabase = async () => { + + if(restore_from_backup <= 0) return; + + //calculate diff + const now = new Date(); + let currentTime = now.getTime(); + let diff = currentTime - lastRestoreTime; + + if( (diff / 1000) < restore_backup_wait) + { + //console.log("*********restore_backup_wait", diff, restore_backup_wait); + return; + } + + processingData = true; + + //get filename to process + let counter = getDbBackupFileCounter("min"); + + //we have some backup files + let dataBase = 'tbdata'; + + var nosql; + if(counter == 0) dataBase = 'tbdatacloud'; + else dataBase = counter + "." + 'tbdatacloud'; + + nosql = NOSQL(dataBase); + + //select all data - use limit restore_from_backup + let records = await promisifyBuilder(nosql.find().take(restore_from_backup)); + + for(let i = 0; i < records.length; i++) + { + if(clientReady) { + + let item = records[i]; + let id = item.id; + + if(id !== undefined) + { + //console.log("------------processDataFromDatabase - remove", id, dataBase, i); + + try { + + let message = JSON.parse(JSON.stringify(item)); + delete message.id; + client.publish(`${o.topic}_forward`, JSON.stringify(message), {qos:1}); + + //remove from database + await promisifyBuilder(nosql.remove().where("id", id)); + + } catch(error) { + //process error + console.log("processDataFromDatabase", error); + } + + } + + } + else + { + processingData = false; + return; + } + } + + if(records.length > 0) + { + //clean backup file + if(counter > 0) nosql.clean(); + } + + //no data in db, remove + if(records.length == 0) + { + if(counter > 0) nosql.drop(); + } + + const d = new Date(); + lastRestoreTime = d.getTime(); + + processingData = false; + + } + + instance.on('options', main); + +}; diff --git a/RVO45/flow_pred_verziou_2025_01_30/cmd_manager.js b/RVO45/flow_pred_verziou_2025_01_30/cmd_manager.js new file mode 100755 index 0000000..a960aaa --- /dev/null +++ b/RVO45/flow_pred_verziou_2025_01_30/cmd_manager.js @@ -0,0 +1,2988 @@ +exports.id = 'cmd_manager'; +exports.title = 'CMD Manager'; +exports.group = 'Worksys'; +exports.color = '#5D9CEC'; +exports.version = '0.0.3'; +exports.output = ['red', 'blue', 'yellow', 'blue', 'white']; +exports.input = 3; +exports.icon = 'cloud-upload'; + +exports.html = ` +
+
+
+
RPC - run RPC calls

+
+
+
@(User)
+
+
+
@(Password)
+
+
+
@(My edge)
+
+
+
+`; +exports.readme = `Manager for CMD calls`; + + +exports.install = function(instance) { + + 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'); + + 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'); + + const dbNodes = TABLE("nodes"); + const dbRelays = TABLE("relays"); + + let GLOBALS; + let SETTINGS; + let rsPort; + let tbHandler; + + // runTasks intervals + const SHORT_INTERVAL = 30; + const LONG_INTERVAL = 300; + + //send data to following instances: + const SEND_TO = { + debug: 0, + tb: 1, + http_response: 2, + dido_controller: 3, + infoSender: 4 + } + + 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 + } + + 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 + + //if sending of profile to node fails, we send notification and push node into set, so we do not send notification twice + const nodeProfileSendFail = new Set(); + + //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(); + } + + + 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" + //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); + + 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); + + console.log("proces profile finished *********************") + } + + + 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; + }); + } + + + 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) { + for (let k in nodesData) { + 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`); + } + } + } + + + function loadRelaysData(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 (value.contactor == 1) processAllNodeProfilesOnLine(value.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 = {}; + + 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.byte1 = hours;//h + params.byte2 = minutes;//m + params.byte3 = seconds;//s + params.byte4 = 0; + params.recipient = 2;//2 broadcast, address = 0 + params.register = 87;//Actual time + params.rw = 1;//write + + //other values + params.type = "cmd"; + params.timestamp = Date.now() + 60000; + params.addMinutesToTimestamp = addMinutesToTimestamp; + params.info = "run broadcast: Actual time"; + + tasks.push(params); + + let sec = 3; + 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) { + 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); + + 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'; + //params.debug = true; + + tasks.push(params); + } + + //Prúd + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "cmd"; + params.tbname = tbname; + params.address = node; + params.register = 75;//prud + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read current'; + //params.debug = true; + + tasks.push(params); + } + + //výkon + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "cmd"; + params.tbname = tbname; + params.address = node; + params.register = 76;//výkon + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read power'; + //params.debug = true; + + tasks.push(params); + } + } + } + }, sec * 1000); + } + + + 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"; + + const date = Date.now(); + + // 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); + }) + + } + + + function turnLine(onOrOff, line, info) { + let obj = { + line: line, + command: onOrOff, + info: info + }; + + logger.debug("linia", line, obj); + instance.send(SEND_TO.dido_controller, obj); + } + + + + 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"; + 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]) { + //CRC_ERROR + message = "NOK"; + error = "CRC_ERROR c1"; + instance.send(SEND_TO.debug, "CRC_ERROR c1"); + } + + 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") { + instance.send(SEND_TO.debug, bytes); + instance.send(SEND_TO.debug, "RESPONSE " + type + " - " + bytes[4]); + + //logger.debug(SEND_TO.debug, "RESPONSE " + type + " - " + bytes[4], bytes); + + error = "type is: " + type; + + message = "NOK"; + } + + return { message, type, error }; + } + + + //BUILD TASKS// + function buildTasks(params) { + //report SETTINGS.edge_fw_version as fw_version + //report date as startdate + + //return; + console.log("buidTAaasks start ****************", params); + + monitor.info("buildTasks - params", params); + + let processLine; //defined line + let init = false; + let processLineProfiles = true; + let processBroadcast = true; + let processNodes = true; + + if (params == undefined) { + init = true; + tasks = []; + logger.debug("-->buildTasks clear tasks"); + } + else { + processLineProfiles = false; + processBroadcast = false; + processNodes = false; + + processLineProfiles = params.processLineProfiles; + processLine = params.line; + } + + //load profiles pre vsetky linie: + let now = new Date(); + + if (processLineProfiles) { + //process line profiles + let keys = Object.keys(relaysData); + 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; + } + + try { + + /** + * we process line profiles: timepoints, astro clock, lux_sensor, offsets ... + */ + if (profilestr === "") throw ("Profile is not defined"); + let profile = JSON.parse(profilestr); + 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; + + // add name to regular profile timepoint and delete unused end_time key: + time_points.forEach(point => { + point.name = "profileTimepoint" + delete point.end_time; + }); + + //monitor.info("buildTasks: time_points", time_points); + + + /** + * 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 astro clock true, we remove all regular profile points + time_points = []; + + 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 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); + + 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); + + 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(':'); + + let ad = new Date(); + ad.setHours(parseInt(ahours), parseInt(aminutes), 0); + + let bd = new Date(); + bd.setHours(parseInt(bhours), parseInt(bminutes), 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++) { + + let start_time = new Date(); + let [hours, minutes] = time_points[t].start_time.split(':'); + start_time.setHours(parseInt(hours), parseInt(minutes), 0); + + //task is in 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); + params.value = time_points[t].value; + params.tbname = relaysData[line].tbname; + params.timestamp = start_time.getTime(); + + 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; + + //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)) { + 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; + + params.debug = true; + + //turn on/off line + tasks.push(params); + monitor.info("TimePoint params: ", params.info, start_time); + } + + monitor.info("-->time_points final", line, time_points); + + //ensure to turn on/off according to calculated currentValue + let params = getParams(PRIORITY_TYPES.terminal); + params.type = "relay"; + params.line = parseInt(line); + params.tbname = relaysData[line].tbname; + params.value = currentValue; + + params.timestamp = PRIORITY_TYPES.terminal; + params.addMinutesToTimestamp = 0; + params.debug = true; + + //logger.debug(now.toLocaleString("sk-SK")); + 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; + + tasks.push(params); + + } catch (error) { + if (profilestr !== "") { + //errLogger.error(profilestr, error); + errorHandler.sendMessageToService(profilestr + "-" + error, 0, "js_error"); + } + } + + } + + //logger.debug("tasks:"); + //logger.debug(tasks); + } + + + //PROCESS DEFAULT BROADCASTS + //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.register = 6;//Time of dusk - Reg 6 + params.rw = 1;//write + + //other values + params.type = "cmd"; + params.timestamp = Date.now() + 60000; + params.addMinutesToTimestamp = addMinutesToTimestamp; + params.info = "Broadcast-duskTime"; + + tasks.push(params); + } + + { + + //run broadcast Time of dawn + 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 + params.byte3 = 0;//s + params.byte4 = 0; + params.recipient = 2; //2 broadcast + params.register = 7;//Time of dawn - Reg 6 + params.rw = 1;//write + + //other values + params.type = "cmd"; + params.timestamp = Date.now() + 60000; + params.addMinutesToTimestamp = addMinutesToTimestamp; + params.info = "Broadcast-dawnTime"; + + tasks.push(params); + } + + { + //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 + params.byte3 = seconds;//s + params.byte4 = 0; + params.recipient = 2; //2 broadcast + params.register = 87;//Actual time + params.rw = 1;//write + + //other values + params.type = "cmd"; + params.timestamp = Date.now() + 60000; + params.addMinutesToTimestamp = addMinutesToTimestamp; + params.info = "run broadcast: Actual time"; + + tasks.push(params); + } + + } + + //process nodes & tasks + //reportovanie pre platformu + 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++) { + register = listOfCommands[i]; + + let params = getParams(PRIORITY_TYPES.node_cmd); + + //core rpc values + params.address = address; + params.byte1 = 0; + params.byte2 = 0; + params.byte3 = 0; + params.byte4 = 0; + 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) { + timestampStart = timestampStart + addMinutesToTimestamp * 60000; + } + + //other values + params.type = "cmd"; + params.tbname = tbname; + params.timestamp = timestampStart; + params.addMinutesToTimestamp = addMinutesToTimestamp; + params.info = "generated cmd - buildTasks (node)"; + + tasks.push(params); + + } + } + } + + + //niektore ulohy sa vygeneruju iba 1x pri starte!!! + if (!init) return; + + + //Priebežne (raz za cca 5 minút) je potrebné vyčítať z Master nodu verziu jeho FW. + //Jedná sa o register 10. Rovnaká interpretácia ako pri FW verzii nodu. + //Adresa mastera je 0. V prípade že kedykoľvek nastane situácia že Master Node neodpovedá (napríklad pri vyčítaní telemetrie z nodu nevráti žiadne dáta), + //tak treba vyreportovať string "NOK". + { + let params = getParams(PRIORITY_TYPES.fw_detection); + params.type = "cmd-master"; + params.register = 4; + params.address = 0; + params.timestamp = Date.now() + 60000; + params.addMinutesToTimestamp = 5; + params.tbname = SETTINGS.rvoTbName; + params.info = "Master node FW verzia"; + //params.debug = true; + + //this will set SETTINGS.masterNodeIsResponding + + tasks.push(params); + } + + //kazdu hodinu skontrolovat nastavenie profilov + { + let params = getParams(PRIORITY_TYPES.fw_detection); + params.type = "process_profiles"; + params.timestamp = Date.now() + 60000; + params.addMinutesToTimestamp = 60;//60 = every hour + params.info = "detekcia nespracovaných profilov linie a nodov"; + //params.debug = true; + + tasks.push(params); + } + + monitor.info("tasks created:", tasks.length); + } + + + /** + * We process line profile, where "astro_clock": true + * example profile: + * + "dawn_lux_sensor": true, + "dusk_lux_sensor": true, + "dawn_lux_sensor_value": 5, + "dusk_lux_sensor_value": 5, + "dawn_astro_clock_offset": 0, + "dusk_astro_clock_offset": 10, + "dawn_lux_sensor_time_window": 30, + "dusk_lux_sensor_time_window": 30, + "dawn_astro_clock_time_window": 60, + "dusk_astro_clock_time_window": 60 + + * if dawn: if currentTimestamp is in timewindow "dawnTime + and - dawn_lux_sensor_time_window" and lux value >= lux_sensor_value, we switch off the line. + * if dusk: we do oposite + * + * dawn: usvit - lux je nad hranicou - vypnem + * dusk: sumrak - lux je pod hranicou - zapnem + */ + 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++) { + + let line = keys[i]; //line is turned off by default + let profilestr = relaysData[line].profile; + const contactor = relaysData[line].contactor; + + try { + + let profile = JSON.parse(profilestr); + if (Object.keys(profile).length === 0) throw ("turnOnOffLinesAccordingToLuxSensor - profile is not defined"); + + 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 (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"); + } + } + } + + //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 (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"); + } + } + } + + } + + } catch (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) { + //MASTER + if (node == 0) return; + + let nodeObj = nodesData[node]; + 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; + } + + } + + + 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 }; + } + }); + }); + } + + + async function runTasks() { + + clearInterval(interval); + + let currentTimestamp = Date.now(); + + //report dusk, dawn--------------------------------- + if (reportDuskDawn.dusk_time < currentTimestamp) { + //vyreportuj iba ak nie je velky rozdiel napr. 60 sekund + 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); + reportDuskDawn.dusk_time_reported = sunCalcResult.dusk_time; + } + } + + var nextDay = new Date(); + nextDay.setDate(nextDay.getDate() + 1); + + sunCalcResult = calculateDuskDawn(nextDay); + reportDuskDawn.dusk_time = sunCalcResult.dusk_time; + } + + if (reportDuskDawn.dawn_time < currentTimestamp) { + //vyreportuj iba ak nie je velky rozdiel napr. 60 sekund + 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); + reportDuskDawn.dawn_time_reported = sunCalcResult.dawn_time; + } + } + + var nextDay = new Date(); + nextDay.setDate(nextDay.getDate() + 1); + + sunCalcResult = calculateDuskDawn(nextDay); + reportDuskDawn.dawn_time = sunCalcResult.dawn_time; + + } + //-------------------------------------------------------- + + //sort tasks based on timestamp + 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) { + instance.send(SEND_TO.debug, "no tasks created"); + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + 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) { + //logger.debug("--->task to process", currentTask); + } + + if (currentTask.timestamp <= currentTimestamp) { + let params = { ...tasks[0] }; + + //allow terminal commands + if (SETTINGS.maintenance_mode && params.type !== "cmd-terminal") { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + let type = params.type; + let tbname = params.tbname; + let node = params.address; + + let line = null; + + //rpc related + if (nodesData[node] !== undefined) line = nodesData[node].line; + if (params.line !== undefined) line = params.line; + + let repeatTask = false; + if (params.addMinutesToTimestamp > 0 || params.timePointName) repeatTask = true; + + if (repeatTask) { + if (type === "cmd" || type === "cmd-master") { + //set next start time automatically + tasks[0].timestamp = currentTimestamp + tasks[0].addMinutesToTimestamp * 60000; + } + } + else { + tasks.shift(); + } + + //kontrola nespracovanych profilov nodov + if (type == "process_profiles") { + tasks[0].timestamp = currentTimestamp + tasks[0].addMinutesToTimestamp * 60000; + + //vsetky linie kt. su zapnute, a spracuju sa nespracovane profily nodov + loadRelaysData(); + + interval = setInterval(runTasks, SHORT_INTERVAL); + return; + } + + //relay + if (type == "relay") { + + const timePointName = params.timePointName; + const value = params.value; + + let date = new Date(); + date.setDate(date.getDate() + 1);//next day + + let sunCalcResult; + if (timePointName) sunCalcResult = calculateDuskDawn(date, params.line); + + if (timePointName == "dawn") { + tasks[0].timestamp = sunCalcResult.dawn_time; + } + else if (timePointName == "dusk") { + tasks[0].timestamp = sunCalcResult.dusk_time; + } + else if (timePointName == "luxOn") { + tasks[0].timestamp = sunCalcResult.dusk_time + params.dusk_lux_sensor_time_window * 60000; + } + else if (timePointName == "luxOff") { + tasks[0].timestamp = sunCalcResult.dawn_time + params.dawn_lux_sensor_time_window * 60000; + } + else if (timePointName == "profileTimepoint") { + tasks[0].timestamp = currentTimestamp + tasks[0].addMinutesToTimestamp * 60000; + } + + let info = "aplikovany bod profilu"; + let onOrOff = ""; + value == 1 ? onOrOff = "on" : onOrOff = "off"; + + turnLine(onOrOff, params.line, info); + + interval = setInterval(runTasks, SHORT_INTERVAL); + return; + } + + //zhodeny hlavny istic + let disconnected = false; + //if(rotary_switch_state == "Off") disconnected = true; + + //state_of_breaker[line] - alebo istic linie + 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" }; + + 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; + + if (!disconnectedReport[tbname]) { + sendTelemetry(values, tbname) + } + + interval = setInterval(runTasks, SHORT_INTERVAL); + + return; + } + + disconnectedReport[tbname] = false; + + const register = params.register; + + //high_priority + if (!SETTINGS.masterNodeIsResponding) { + //ak neodpoveda, nebudeme vykonavat ziadne commands, okrem cmd-terminal, a fw version + errorHandler.sendMessageToService("Master node is not responding"); + + let stop = true; + + //fw version - register == 4 + if (type == "cmd-terminal" || register == 4) stop = false; + if (stop) { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + } + + let contactorStatus = 1; + if (relaysData[line] != undefined) contactorStatus = relaysData[line].contactor; + + if (line == 0 || contactorStatus == 0) { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + // TODO: -> status offline for rvo if rotary_switch_state is OFF, this is source of errors + // + // let relayStatus = 1; + // if (relaysData[line] != undefined) { + // relayStatus = relaysData[line].contactor; + // } + + // if (line == 0) relayStatus = 0; + // if (type == "cmd-terminal") relayStatus = 1; + + // //check if rotary_switch_state == "Off" + // if (relayStatus == 0) { + // console.log("------------------------------------relayStatus", relayStatus, line); + // let values = { "status": "OFFLINE" }; + + // if(tbname) sendTelemetry(values, tbname) + + // interval = setInterval(runTasks, SHORT_INTERVAL); + // return; + // } + + if (!rsPort.isOpen) { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + //RE-CALCULATE VALUES + //set actual time for broadcast + if (register == 87 && params.recipient === 2) { + var d = new Date(); + params.byte1 = d.getHours();//h + params.byte2 = d.getMinutes();//m + params.byte3 = 0;//s + params.byte4 = 0; + } + + //SET DUSK/DAWN FOR BROADCAST + //Time of dusk + if (register == 6 && params.recipient === 2) { + + if (type != "cmd-terminal") { + let sunCalcResult = calculateDuskDawn(); + params.byte1 = sunCalcResult["dusk_hours"];//h + params.byte2 = sunCalcResult["dusk_minutes"];//m + params.byte3 = 0;//s + params.byte4 = 0; + + //TODO astrohodiny + let dusk = "Time of dusk: " + sunCalcResult["dusk"]; + } + } + + //Time of dawn + if (register == 7 && params.recipient === 2) { + if (type != "cmd-terminal") { + let sunCalcResult = calculateDuskDawn(); + params.byte1 = sunCalcResult["dawn_hours"];//h + params.byte2 = sunCalcResult["dawn_minutes"];//m + params.byte3 = 0;//s + params.byte4 = 0; + + //TODO astrohodiny + let dawn = "Time of dawn: " + sunCalcResult["dawn"]; + } + + } + //----------------------- + + instance.send(SEND_TO.debug, "address: " + node + " register:" + register + "type: " + 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(node, params.recipient, params.rw, register, params.name, params.byte1, params.byte2, params.byte3, params.byte4); + let readBytes = 11; + let timeout = 4000; + + // await keyword is important, otherwise incorrect data is returned! + 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); + + //ak sa odpoved zacina 0 - je to v poriadku, inak je NOK + let message = result.message; // OK, NOK + let message_type = result.type; + let error = result.error; + + if (params.debug != "generated cmd") { + //debug("writeData: done " + message_type + " duration: " + timeDiff + " message_type: " + params.debug, params); + } + + // 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); + // } + // } + + //debug("writeData: done " + message_type + " duration: " + timeDiff + " message_type: " + params.debug); + //debug("writeData done", message_type, "duration", timeDiff, "message_type", params.debug, result); + + let values = {}; + + //CMD FINISHED + if (message == "OK") { + + updateNodeStatus(node, true); + + //write + if (type == "set_node_profile") { + let result = cmdCounterResolve(node); + if (result == 0) { + dbNodes.modify({ processed: true }).where("node", node).make(function(builder) { + builder.callback(function(err, response) { + + sendNotification("CMD Manager: process cmd", SETTINGS.rvoTbName, "dimming_profile_was_successfully_received_by_node", { node: node }, "", SEND_TO.tb, instance); + + logger.debug("--> profil úspešne odoslaný na node č. " + node); + nodesData[node].processed = true; + nodeProfileSendFail.delete(node); + }); + }); + } + } + + //parse read response + if (params.rw == 0) { + values = processResponse(register, dataBytes); //read + } + + if (itIsNodeCommand) { + values.comm_status = "OK"; + values.status = "OK"; + } + + //master node + if (node == 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; + } + + //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.debug) { + //logger.debug("saveToTb", saveToTb, tbname, values); + } + + if (saveToTb) { + sendTelemetry(values, tbname) + } + else { + if (type == "cmd-terminal") { + terminalCommandResponse(params, "SUCCESS", data); + } + } + + } + else { + + terminalCommandResponse(params, "ERROR", data) + handleNokResponseOnRsPort("handleNOK else block", params, itIsNodeCommand, saveToTb); + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + //logger.debug("writeData err: ", error, result, params); + logger.debug("writeData err: ", tbname, node, register, values); + } + } + + //logger.debug(error, result, params); + } + }).catch(function(reason) { + + console.log("writeData catch exception", reason); + instance.send(SEND_TO.debug, reason); + + terminalCommandResponse(params, "FAILURE", null, reason); + handleNokResponseOnRsPort("handleNOK catch block", params, itIsNodeCommand, saveToTb); + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + logger.debug("-->WRITE FAILED: " + reason, params.debug, params); + } + } + + }); + + } + 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); + } + + + function handleNokResponseOnRsPort(message, params, itIsNodeCommand, saveToTb) { + + let node = params.address; + let register = params.register; + let type = params.type; + let tbName = params.tbname; + if (!tbName) return; + + let values = {}; + + // console.log(message); + let updateStatus = updateNodeStatus(node, false); + + //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; + + if (register == 4) values["master_node_version"] = "NOK"; + } + + if (type == "set_node_profile") { + delete cmdCounter[node]; + logger.debug("profil nebol úspešne odoslaný na node č. ", params); + + if (!nodeProfileSendFail.has(node)) { + sendNotification("CMD Manager: process cmd", tbName, "configuration_of_dimming_profile_to_node_failed", { node: node }, "", SEND_TO.tb, instance); + nodeProfileSendFail.add(node); + } + } + + if (itIsNodeCommand) { + values.comm_status = "NOK"; + } + + 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); + }); + }); + + 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); + + instance.send(SEND_TO.debug, err.message); + }); + + rsPort.on("close", () => { + setTimeout(() => rsPort.open(), 1000); + }); + + 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.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(); + return; + } + else if (flowdata.data == "close") { + rsPort.close(); + return; + } + else if (flowdata.data == "clean") { + tasks = []; + return; + } + else if (flowdata.data == "buildtasks") { + //build & run + return; + } + else if (flowdata.data == "run") { + //durations = []; + + if (tasks.length == 0) { + + buildTasks(); + + if (rsPort.isOpen) { + interval = setInterval(runTasks, 100); + } + else { + instance.send(SEND_TO.debug, "port is not opened!!!"); + } + } + } + else { + //terminal data - object + //logger.debug("flowdata", flowdata.data); + + if (typeof flowdata.data === 'object') { + //logger.debug("dido", flowdata.data); + if (flowdata.data.hasOwnProperty("sender")) { + //data from dido_controller + if (flowdata.data.sender == "dido_controller") { + + if (flowdata.data.hasOwnProperty("cmd")) { + let cmd = flowdata.data.cmd; + + if (cmd == "buildTasks") { + clearInterval(interval); + + logger.debug("-->CMD MANAGER - BUILD TASKS"); + buildTasks(); + + //logger.debug("tasks:"); + //logger.debug(tasks); + + logger.debug("-->CMD MANAGER - RUN TASKS"); + interval = setInterval(runTasks, LONG_INTERVAL); + } + else if (cmd == "reload_relays") { + loadRelaysData(flowdata.data.line); + + if (flowdata.data.dataChanged) { + if (!flowdata.data.value) { + reportOfflineNodeStatus(flowdata.data.line); + } + else { + reportOnlineNodeStatus(flowdata.data.line); + } + } + + } + else if (cmd == "rotary_switch_state") { + let value = flowdata.data.value; + + //state was changed + if (rotary_switch_state != value) { + if (value == "Off") { + //vyreportovat vsetky svietdla + reportOfflineNodeStatus(); + } + + rotary_switch_state = value; + } + } + 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) { + + // we send lux_sensor value to all nodes: + let params = getParams(PRIORITY_TYPES.node_broadcast); + + params.recipient = 2;//2 broadcast, address = 0 + params.address = 0xffffffff;//Broadcast + + let ba = longToByteArray(lux_sensor); + + params.byte3 = ba[1];//msb + params.byte4 = ba[0]; + params.timestamp = PRIORITY_TYPES.node_broadcast; + params.info = "run broadcast: Actual Lux level from cabinet"; + params.register = 95;//Actual Lux level from cabinet + params.rw = 1;//write + + tasks.push(params); + + //process profiles + turnOnOffLinesAccordingToLuxSensor(lux_sensor); + } + } + else if (cmd == "state_of_breaker") { + //istic linie + let value = flowdata.data.value; + let line = parseInt(flowdata.data.line); + + let dataChanged = false; + if (state_of_breaker[line] != value) dataChanged = true; + + state_of_breaker[line] = value; + + let status = "OK"; + if (value == "Off") status = "NOK"; + + if (dataChanged) { + + 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"); + + //report status liniu + sendTelemetry({ status: status }, tbname) + + //current value + if (value == "Off") reportOfflineNodeStatus(line); //vyreportovat vsetky svietidla na linii + } + + } + } + else { + logger.debug("undefined cmd", cmd); + } + } + } + + return; + } + + //data from worksys + 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 command = data.params.command; + let method = data.method; + let profile = data.params.payload; + if (profile == undefined) profile = ""; + let entity = data.params.entities[0]; + let entity_type = entity.entity_type; + let tbname = entity.tb_name; + + instance.send(SEND_TO.debug, flowdata.data); + 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") { + + //let command = data.params.command; + let value = data.params.payload.value; + + if (command == "dimming") { + + let nodeWasFound = false; + let keys = Object.keys(nodesData); + + //logger.debug("-----", keys); + + 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); + + 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; + + //ak linia je + + //debug(params); + logger.debug("dimming", params); + + tasks.push(params); + + 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); + + 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); + } + + //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; + + tasks.push(params); + } + + //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; + + tasks.push(params); + } + + //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; + + tasks.push(params); + } + + }, 4000); + + + nodeWasFound = true; + + break; + } + } + + if (!nodeWasFound) { + logger.debug("set dimming from platform", "unable to find tbname", tbname); + } + } + else { + instance.send(SEND_TO.debug, "undefined command " + command); + logger.debug("undefined command", command); + } + + return; + } + 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++) { + let node = keys[i]; + if (tbname == nodesData[node].tbname) { + + 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"); + + //profil úspešne prijatý pre node č. xx + 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; + + processNodeProfile(node); + }); + }); + } + } + } + else { + + instance.send(SEND_TO.debug, "unknown method " + method); + logger.debug("unknown method", method); + + return; + } + } + + //nastav profil linie z platformy + 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") { + + 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++) { + let line = keys[i]; + if (tbname == relaysData[line].tbname) { + //zmazeme tasky + 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) { + + //update profile + 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); + + }); + }); + break; + } + } + } + else if (method == "set_command") { + let value = data.params.payload.value; + + 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; + + 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"); + } + } + else { + instance.send(SEND_TO.debug, "undefined method " + method); + logger.debug("undefined method", method); + } + + return; + } + else { + instance.send(SEND_TO.debug, "UNKNOW entity_type " + entity_type); + logger.debug("UNKNOW entity_type", entity_type); + } + return; + } + + //terminal + if (!rsPort.isOpen) await rsPort.open(); + + let params = flowdata.data.body; + if (params == undefined) { + //logger.debug("CMD manager flowdata.data.body is undefined"); + return; + } + + params.priority = PRIORITY_TYPES.terminal; + params.type = "cmd-terminal"; + params.tbname = ""; + params.timestamp = PRIORITY_TYPES.terminal; + params.addMinutesToTimestamp = 0;// do not repeat task!!! + params.debug = true; + + let timestamp = Date.now(); + params.refFlowdataKey = timestamp; + //params.refFlowdata = flowdata; + //refFlowdata = flowdata; + + //console.log("flowdata", flowdata); + + cleanUpRefFlowdataObj(); + + refFlowdataObj[timestamp] = flowdata; + + //fix + //params.address = params.adress; + logger.debug("received from terminal", params); + logger.debug("date/time:", new Date()); + logger.debug("tasks length:", tasks.length); + + //tasks = []; + + //add to tasks + tasks.push(params); + + } + } + }) + + + //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) + } + + + /** + * 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; + + RESTBuilder.make(function(builder) { + + if (!builder) return; + + builder.method('GET'); + builder.url('http://192.168.252.2:8004/gettime?projects_id=1'); + + builder.callback(function(err, response, output) { + + 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); + } + + }); + } + + } 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); + + } else { + //console.log("Read-only", stdout); + + 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]: [ + { + "ts": date, + "values": values + } + ] + } + + 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); + } + + //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); + } + } + + 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; + } + + //Dimming, CCT + if (register == 1) { + let brightness = 0; + let dimming = byte0; + if (dimming > 128) { + //dimming = -128; + brightness = dimming - 128; + } + + //cct + //Ak Byte3 == 1: CCT = (Byte2*256)+Byte1 + let cct; + if (byte3 == 1) cct = byte2 * 256 + byte1; + else cct = bytesToInt(bytes.slice(0, 3)); + + //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; + } + + 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, 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 + ")"; + } + + 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; + + } + + function getObjectByTbValue(object, tbname) { + return object[Object.keys(object).find(key => object[key].tbname === tbname)]; + } + + function isObject(item) { + return (typeof item === "object" && !Array.isArray(item) && item !== null); + } + +} // end of instance.export + diff --git a/RVO45/flow_pred_verziou_2025_01_30/code.js b/RVO45/flow_pred_verziou_2025_01_30/code.js new file mode 100755 index 0000000..63b31bf --- /dev/null +++ b/RVO45/flow_pred_verziou_2025_01_30/code.js @@ -0,0 +1,90 @@ +exports.id = 'code'; +exports.title = 'Code'; +exports.group = 'Common'; +exports.color = '#656D78'; +exports.input = true; +exports.output = 1; +exports.author = 'Peter Širka'; +exports.icon = 'code'; +exports.version = '1.2.0'; +exports.options = { outputs: 1, code: 'send(0, value);', keepmessage: true }; + +exports.html = `
+
+
+
@(Number of outputs)
+
@(Minimum is 1)
+
+
+
@(Code)
+
@(Keep message instance)
+
+`; + +exports.readme = `# Code + +This component executes custom JavaScript code as it is and it doesn't contain any secure scope. + +\`\`\`javascript +// value {Object} contains received data +// send(outputIndex, newValue) sends a new value +// error(value) sends an error +// instance {Object} a current component instance +// flowdata {Object} a current flowdata +// repository {Object} a current repository of flowdata +// Example: + +// send() can be execute multiple times +send(0, value); +\`\`\``; + +exports.install = function(instance) { + + var fn; + + instance.on('data', function(response) { + if (fn) { + try { + fn(response.data, instance, response, instance.options, response.repository, require); + } catch (e) { + response.data = e; + instance.throw(response); + } + } + }); + + instance.reconfigure = function() { + try { + if (instance.options.code) { + instance.status(''); + var code = 'var send = function(index, value) { if (options.keepmessage) { flowdata.data = value; instance.send2(index, flowdata); } else instance.send2(index, value);}; var error = function(err) { instance.throw(err); }; ' + instance.options.code; + fn = new Function('value', 'instance', 'flowdata', 'options', 'repository', 'require', code); + } else { + instance.status('Not configured', 'red'); + fn = null; + } + } catch (e) { + fn = null; + instance.error('Code: ' + e.message); + } + }; + + instance.on('options', instance.reconfigure); + instance.reconfigure(); +}; \ No newline at end of file diff --git a/RVO45/flow_pred_verziou_2025_01_30/comment.js b/RVO45/flow_pred_verziou_2025_01_30/comment.js new file mode 100755 index 0000000..1e0cd13 --- /dev/null +++ b/RVO45/flow_pred_verziou_2025_01_30/comment.js @@ -0,0 +1,11 @@ +exports.id = 'comment'; +exports.title = 'Comment'; +exports.group = 'Common'; +exports.color = '#704cff'; +exports.author = 'Martin Smola'; +exports.icon = 'comment'; +exports.traffic = false; +exports.version = '1.0.0'; +exports.readme = '# Comment'; + +exports.install = function() {}; diff --git a/RVO45/flow_pred_verziou_2025_01_30/db_connector.js b/RVO45/flow_pred_verziou_2025_01_30/db_connector.js new file mode 100755 index 0000000..65ee94b --- /dev/null +++ b/RVO45/flow_pred_verziou_2025_01_30/db_connector.js @@ -0,0 +1,286 @@ +exports.id = 'db_connector'; +exports.title = 'DbConnector'; +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.html = `
+
+
+
DbConnector
+
+
+
`; + +exports.readme = `# read/write data to tables`; + +const instanceSendTo = { + debug: 0, + http_response: 1, +} + +const { promisifyBuilder, makeMapFromDbResult } = require('./helper/db_helper.js'); + +function extractWhereParams(params) +{ + let name = params[0]; + let operator = '='; + let value = params[1]; + + if(params.length == 3) + { + operator = params[1]; + value = params[2]; + } + + return {name: name, operator: operator, value: value}; +} + +exports.install = function(instance) { + + let refFlowdata = null;//holds reference to httprequest flowdata + + instance.on("close", () => { + + }) + + + instance.on("data", async function(flowdata) { + + let params = flowdata.data.body; + console.log("DbConnector", params); + + refFlowdata = flowdata; + + if(refFlowdata != undefined) + { + //make http response + let responseObj = {}; + responseObj["type"] = "SUCESS"; + + try{ + + let table = params.table; + let action = params.action; + + + if(params.data != undefined) + { + let className = params.data.className; + + if(className == "SqlQueryBuilder") + { + let type = params.data.type; + + console.log("SqlQueryBuilder---->", params.data); + + if(type == "SELECT") + { + let table = params.data.queryData.tables[0].table; + + const db = TABLE(table); + var builder = db.find(); + + let result = await promisifyBuilder(builder); + + let response = {}; + response["result"] = result; + response["success"] = true; + + responseObj["data"] = response; + + //console.log(responseObj); + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + } + + return; + } + } + + + console.log("db_connector---->", table, action); + + //actions: read, replace, insert, delete, update... + + if(action == "read") + { + const db = TABLE(params.table); + + //where builder.where('age', '<', 15); + //builder.where('id', 3403); + + var builder = db.find(); + + //https://docs.totaljs.com/latest/en.html#api~DatabaseBuilder~builder.where + if(params.hasOwnProperty("where")) + { + //optionalCan contain "=", "<=", "<", ">=", ">". + //Default value: '=' + + //1.["production_line", 1] + //2. ["or", ["production_line", 1], ["production_line", 2], "end"] + + if (Array.isArray(params.where)) { + + let multipleConditions = false; + + if(params.where[0] == "or") multipleConditions = true; + if (Array.isArray(params.where[0])) multipleConditions = true; + + if(multipleConditions) + { + + for(var i = 0; i < params.where.length; i++) + { + const item = params.where[i]; + + if(item === "or") builder.or(); + + if (Array.isArray(item)) + { + const { name, operator, value } = extractWhereParams(item); + builder.where(name, operator, value); + } + + if(item === "end") builder.end(); + + } + + } + else + { + const { name, operator, value } = extractWhereParams(params.where); + builder.where(name, operator, value); + } + + } + + /* + if(params.where.length >=2 ) + { + let name = params.where[0]; + let operator = '='; + let value = params.where[1]; + + if(params.where.length == 3) + { + operator = params.where[1]; + value = params.where[2]; + } + + builder.where(name, operator, value); + } + */ + } + + if(params.hasOwnProperty("between")) + { + builder.between(params.between[0], params.between[1], params.between[2]); + } + + let response = await promisifyBuilder(builder); + responseObj["data"] = response; + + //console.log(responseObj); + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + + return; + } + + if(action == "delete") + { + + } + + + if(action == "update") + { + //! data receiving from terminal (params) + // { + // hostname: 'localhost', + // table: 'settings', + // action: 'update', + // body: { + // rvo_name: 'terrrr', + // lang: 'en', + // temperature_adress: '28.427B45920702', + // latitude: 48.70826502, + // longitude: 17.28455203, + // mqtt_host: '192.168.252.4', + // mqtt_clientid: 'showroom_test_panel_led', + // mqtt_username: 'xmRd6RJxW53WZe4vMFLU', + // mqtt_port: 1883, + // maintanace_mode: false + // } + // } + const tableToModify = TABLE(params.table); + const newValues = params.body; + + tableToModify.modify(newValues).make(function(builder) { + + builder.callback(function(err, response) { + + if(!err) + { + responseObj["data"] = response; + responseObj["tableUpdated"] = true; + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + } + }); + }); + + } + + if(action == "replace") + { + //truncate table + const db = TABLE(params.table); + var builder = db.remove(); + db.clean(); + + //insert data + let data = params.data; + + for(let i = 0; i < data.length; i++) + { + //console.log(data[i]); + db.insert(data[i]); + } + + console.log("insert done"); + + let responseObj = {}; + responseObj["type"] = "SUCESS"; + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + + + } + + + + } catch (error) { + //console.log(error); + responseObj["type"] = "ERROR"; + responseObj["message"] = error; + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + } + } + }) +} + + diff --git a/RVO45/flow_pred_verziou_2025_01_30/db_init.js b/RVO45/flow_pred_verziou_2025_01_30/db_init.js new file mode 100755 index 0000000..ddd0aa0 --- /dev/null +++ b/RVO45/flow_pred_verziou_2025_01_30/db_init.js @@ -0,0 +1,106 @@ +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 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 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.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 : "2025-01-09", //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"], + phases: responseSettings[0]["phases"], + cloud_topic: responseSettings[0]["cloud_topic"], + + //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/RVO45/flow_pred_verziou_2025_01_30/debug.js b/RVO45/flow_pred_verziou_2025_01_30/debug.js new file mode 100755 index 0000000..00cb259 --- /dev/null +++ b/RVO45/flow_pred_verziou_2025_01_30/debug.js @@ -0,0 +1,100 @@ +exports.id = 'debug'; +exports.title = 'Debug'; +exports.author = 'Peter Širka'; +exports.color = '#967ADC'; +exports.click = true; +exports.input = true; +exports.icon = 'bug'; +exports.version = '2.0.4'; +exports.options = { enabled: true, repository: false, type: 'data' }; +exports.readme = `# Debug + +Prints data to the debug tab.`; + +exports.html = `
+
+
+
@(Output type)
+
@(Path to the property (leave empty to show the whole data object))
+
@(A group name)
+
@(Enabled)
+
+
+
`; + +exports.install = function(instance) { + + instance.on('data', function(response) { + if (instance.options.enabled) { + + var opt = instance.options; + var rep = response.repository; + var val = response.data; + var id = response.id; + + switch (instance.options.type){ + case 'both': + var data = {}; + data.repository = rep; + data.data = val instanceof Error ? { error: val.message, stack: val.stack } : val; + instance.debug(safeparse(opt.property ? U.get(data, opt.property) : data), undefined, opt.group, id); + break; + case 'repository': + instance.debug(safeparse(opt.property ? U.get(rep, opt.property) : rep), undefined, opt.group, id); + break; + case 'data': + default: + if (val instanceof Error) + instance.debug({ error: val.message, stack: val.stack }, undefined, opt.group, id); + else + instance.debug(safeparse(opt.property ? U.get(val, opt.property) : val), undefined, opt.group, id); + break; + } + } + }); + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + instance.save(); + }); + + instance.on('options', function() { + instance.custom.status(); + }); + + instance.custom.status = function() { + instance.status(instance.options.enabled ? 'Enabled' : 'Disabled'); + }; + + instance.custom.status(); + + function safeparse(o) { + + if (o instanceof Buffer) + return o; + + if (o === undefined) + return 'undefined'; + + if (o === null) + return 'null'; + + var cache = []; + var str = JSON.stringify(o, function(key, value) { + if (typeof value === 'object' && value !== null) { + if (cache.indexOf(value) !== -1) { + try { + return JSON.parse(JSON.stringify(value)); + } catch (error) { + return; + } + } + cache.push(value); + } + return value; + }); + cache = null; + return JSON.parse(str); + } +}; diff --git a/RVO45/flow_pred_verziou_2025_01_30/designer.json b/RVO45/flow_pred_verziou_2025_01_30/designer.json new file mode 100755 index 0000000..fe8a500 --- /dev/null +++ b/RVO45/flow_pred_verziou_2025_01_30/designer.json @@ -0,0 +1,2846 @@ +{ + "tabs": [ + { + "name": "MAIN PUSH", + "linker": "main-push", + "id": "1612772287426", + "index": 0 + }, + { + "name": "CMD manager", + "linker": "cmd-manager", + "id": "1615551125555", + "index": 1 + }, + { + "name": "Devices", + "linker": "devices", + "id": "1611921777196", + "index": 2 + } + ], + "components": [ + { + "id": "1611951142547", + "component": "debug", + "tab": "1611921777196", + "name": "ERROR", + "x": 598, + "y": 60, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#DA4453", + "notes": "" + }, + { + "id": "1612776786008", + "component": "wsmqttpublish", + "tab": "1612772287426", + "name": "WS MQTT publish", + "x": 304.75, + "y": 237, + "connections": { + "0": [ + { + "index": "0", + "id": "1615551060773" + } + ], + "1": [ + { + "index": "0", + "id": "1618300858252" + }, + { + "index": "0", + "id": "1618558465485" + } + ], + "2": [ + { + "index": "0", + "id": "1618300863816" + }, + { + "index": "0", + "id": "1634303685503" + } + ], + "3": [ + { + "index": "0", + "id": "1731068754606" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Connected", + "color": "green" + }, + "options": { + "username": "", + "clientid": "", + "port": "1883", + "host": "" + }, + "color": "#888600", + "notes": "" + }, + { + "id": "1612778461252", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "tb-push", + "x": 86.75, + "y": 375, + "connections": { + "0": [ + { + "index": "0", + "id": "1612783322136" + }, + { + "index": "1", + "id": "1612776786008" + }, + { + "index": "0", + "id": "1731068754606" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1612783322136", + "component": "debug", + "tab": "1612772287426", + "name": "to TB", + "x": 306.75, + "y": 371, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615551060773", + "component": "debug", + "tab": "1612772287426", + "name": "errors from MQTT Broker", + "x": 650, + "y": 76, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#DA4453", + "notes": "" + }, + { + "id": "1615563373927", + "component": "debug", + "tab": "1615551125555", + "name": "Debug", + "x": 753, + "y": 150, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#DA4453", + "notes": "" + }, + { + "id": "1615566865233", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "tb-push", + "x": 761, + "y": 251, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1615798582262", + "component": "debug", + "tab": "1615551125555", + "name": "CMD_debug", + "x": 765, + "y": 350, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615802995322", + "component": "debug", + "tab": "1611921777196", + "name": "Debug", + "x": 595.8833312988281, + "y": 557.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Disabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": false + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615809128443", + "component": "debug", + "tab": "1611921777196", + "name": "tempToTb", + "x": 598.8833312988281, + "y": 654.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615809595184", + "component": "virtualwireout", + "tab": "1611921777196", + "name": "tb-push", + "x": 594.8833312988281, + "y": 350.25, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1616165795916", + "component": "httproute", + "tab": "1615551125555", + "name": "POST /terminal", + "x": 114, + "y": 546, + "connections": { + "0": [ + { + "index": "0", + "id": "1684060205000" + }, + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Listening", + "color": "green" + }, + "options": { + "timeout": 10, + "cachepolicy": 0, + "cacheexpire": "5 minutes", + "size": 5, + "url": "/terminal", + "method": "POST", + "name": "", + "flags": [ + "id:1616165795916", + "post", + 10000 + ], + "emptyresponse": false + }, + "color": "#5D9CEC", + "notes": "### Configuration\n\n- __POST /terminal__\n- flags: \n- maximum request data length: __5 kB__\n- empty response: __false__\n- cache policy: __no cache__\n- cache expire: __5 minutes__", + "cloning": false + }, + { + "id": "1616165824813", + "component": "httpresponse", + "tab": "1615551125555", + "name": "HTTP Response", + "x": 772, + "y": 443, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "json" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1617104731852", + "component": "debug", + "tab": "1615551125555", + "name": "DIDO_Debug", + "x": 669, + "y": 1040, + "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": "turnOff line", + "x": 88, + "y": 1158, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "object", + "data": "{line: 3, command: \"turnOff\", force: true}" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1617115013095", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "tb-push", + "x": 669, + "y": 1150, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1617284749681", + "component": "trigger", + "tab": "1615551125555", + "name": "update profile / node", + "x": 112, + "y": 215, + "connections": { + "0": [ + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "data": "profile_nodes", + "datatype": "string" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1618235171399", + "component": "trigger", + "tab": "1615551125555", + "name": "tun tasks", + "x": 119, + "y": 280, + "connections": { + "0": [ + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "data": "run" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1618300858252", + "component": "debug", + "tab": "1612772287426", + "name": "wsmqtt-exit1", + "x": 650.8833312988281, + "y": 160, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1618300863816", + "component": "debug", + "tab": "1612772287426", + "name": "wsmqtt-exit2", + "x": 845.8833312988281, + "y": 320, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1618393583970", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "to-cmd-manager", + "x": 668.8833312988281, + "y": 1269, + "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": 119.88333129882812, + "y": 369, + "connections": { + "0": [ + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "platform-rpc-call", + "color": "gray" + }, + "options": { + "wirename": "platform-rpc-call" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1618393759854", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "cmd_to_dido", + "x": 93.88333129882812, + "y": 1007, + "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": 779.8833312988281, + "y": 552, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "cmd_to_dido", + "color": "gray" + }, + "options": { + "wirename": "cmd_to_dido" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1618558465485", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "platform-rpc-call", + "x": 649.8833312988281, + "y": 246, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "platform-rpc-call", + "color": "gray" + }, + "options": { + "wirename": "platform-rpc-call" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1618572059773", + "component": "trigger", + "tab": "1615551125555", + "name": "turnOn line", + "x": 89, + "y": 1085, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "data": "{line: 1, command: \"turnOn\", force: true}", + "datatype": "object" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1619515097737", + "component": "cmd_manager", + "tab": "1615551125555", + "name": "CMD Manager", + "x": 452.1091003417969, + "y": 341.05455017089844, + "connections": { + "0": [ + { + "index": "0", + "id": "1615563373927" + } + ], + "1": [ + { + "index": "0", + "id": "1615566865233" + }, + { + "index": "0", + "id": "1615798582262" + } + ], + "2": [ + { + "index": "0", + "id": "1616165824813" + } + ], + "3": [ + { + "index": "0", + "id": "1618393827655" + } + ], + "4": [ + { + "index": "0", + "id": "1635936391935" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1619605019281", + "component": "httproute", + "tab": "1615551125555", + "name": "GET db", + "x": 115, + "y": 651, + "connections": { + "0": [ + { + "index": "0", + "id": "1684060205000" + }, + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Listening", + "color": "green" + }, + "options": { + "timeout": 5, + "cachepolicy": 0, + "cacheexpire": "5 minutes", + "size": 5, + "url": "/db", + "method": "GET", + "name": "", + "flags": [ + "id:1619605019281", + "get", + 5000 + ] + }, + "color": "#5D9CEC", + "notes": "### Configuration\n\n- __GET /db__\n- flags: undefined\n- maximum request data length: __5 kB__\n- empty response: __undefined__\n- cache policy: __no cache__\n- cache expire: __5 minutes__", + "cloning": false + }, + { + "id": "1619784672383", + "component": "trigger", + "tab": "1615551125555", + "name": "turnOnAlarm", + "x": 85, + "y": 1231, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "object", + "data": "{command: \"turnOnAlarm\"}" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1619784812964", + "component": "trigger", + "tab": "1615551125555", + "name": "turnOffAlarm", + "x": 84, + "y": 1304, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "object", + "data": "{command: \"turnOffAlarm\"}" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1621340721628", + "component": "virtualwireout", + "tab": "1611921777196", + "name": "modbus_to_dido", + "x": 596, + "y": 462, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "modbus_to_dido", + "color": "gray" + }, + "options": { + "wirename": "modbus_to_dido" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1622640022885", + "component": "httproute", + "tab": "1615551125555", + "name": "POST /db_connector", + "x": 98, + "y": 1586, + "connections": { + "0": [ + { + "index": "0", + "id": "1622640073521" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Listening", + "color": "green" + }, + "options": { + "timeout": 5, + "cachepolicy": 0, + "cacheexpire": "5 minutes", + "size": 5, + "url": "/db_connector", + "method": "POST", + "flags": [ + "id:1622640022885", + "post", + 5000 + ] + }, + "color": "#5D9CEC", + "notes": "### Configuration\n\n- __POST /db_connector__\n- flags: \n- maximum request data length: __5 kB__\n- empty response: __undefined__\n- cache policy: __no cache__\n- cache expire: __5 minutes__", + "cloning": false + }, + { + "id": "1622640073521", + "component": "db_connector", + "tab": "1615551125555", + "name": "DbConnector", + "x": 372, + "y": 1572, + "connections": { + "1": [ + { + "index": "0", + "id": "1622641420685" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "edge": "undefined" + }, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1622641420685", + "component": "httpresponse", + "tab": "1615551125555", + "name": "HTTP Response", + "x": 596, + "y": 1586, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1634303504177", + "component": "monitormemory", + "tab": "1612772287426", + "name": "RAM", + "x": 69.88333129882812, + "y": 885.5, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465281992" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "846.43 MB / 985.68 MB", + "color": "gray" + }, + "options": { + "enabled": true, + "interval": 30000 + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1634303533779", + "component": "monitordisk", + "tab": "1612772287426", + "name": "disk", + "x": 70.88333129882812, + "y": 982.5, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465821120" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "5.78 GB / 7.26 GB", + "color": "gray" + }, + "options": { + "enabled": true, + "path": "/", + "interval": 30000 + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1634303595494", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "send-to-services", + "x": 51.883331298828125, + "y": 1400.5, + "connections": { + "0": [ + { + "index": "0", + "id": "1634463186563" + }, + { + "index": "1", + "id": "1634488120710" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1634303602169", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "send-to-services", + "x": 426.8833312988281, + "y": 878.5, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1634303685503", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "send-to-services", + "x": 650.8833312988281, + "y": 355.5, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1634303743260", + "component": "httprequest", + "tab": "1612772287426", + "name": "192.168.252.2:8004/sentmessage", + "reference": "", + "x": 480.8833312988281, + "y": 1334.7333374023438, + "connections": { + "0": [ + { + "index": "0", + "id": "1635327431236" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "url": "http://192.168.252.2:8004/sentmessage", + "method": "POST", + "stringify": "json" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1634463186563", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 280.75, + "y": 1446, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634464580289", + "component": "code", + "tab": "1612772287426", + "name": "Code", + "x": 253, + "y": 788, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465243324" + }, + { + "index": "0", + "id": "1634303602169" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "keepmessage": true, + "code": "let response = {};\nresponse.cpu = value.cpu;\nresponse.uptime = value.uptime;\n\nsend(0, response);", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1634465243324", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 428, + "y": 784, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634465281992", + "component": "code", + "tab": "1612772287426", + "name": "Code", + "x": 242, + "y": 884, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465338103" + }, + { + "index": "0", + "id": "1634303602169" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "keepmessage": true, + "code": "value.sender = \"ram\";\n//let total = value.total/1024/1024;\n//let free = value.free/1024/1024;\n//let used = value.used/1024/1024;\nlet response = {};\n//value.memory_total = (total).toFixed(0) + ' MB';\n//value.memory_free = (free).toFixed(0) + ' MB';\n//value.memory_used = (used).toFixed(0) + ' MB';\n\nresponse.memory_total = value.total;\nresponse.memory_free = value.free;\nresponse.memory_used = value.used;\n\nsend(0, response);", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1634465338103", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 429, + "y": 976, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634465821120", + "component": "code", + "tab": "1612772287426", + "name": "Code", + "x": 245, + "y": 978, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465892500" + }, + { + "index": "0", + "id": "1634303602169" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "keepmessage": true, + "code": "value.sender = \"hdd\";\n//let total = value.total/1024/1024;\n//let free = value.free/1024/1024;\n//let used = value.used/1024/1024;\nlet response = {};\n//value.hdd_total = (total).toFixed(0) + ' MB';\n//value.hdd_free = (free).toFixed(0) + ' MB';\n//value.used = (used).toFixed(0) + ' MB';\n\nresponse.hdd_total = value.total;\nresponse.hdd_free = value.free;\nresponse.hdd_used = value.used;\n\nsend(0, response);", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1634465892500", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 432, + "y": 1068, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634484067516", + "component": "debug", + "tab": "1612772287426", + "name": "Send info", + "x": 480, + "y": 1441, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634488120710", + "component": "infosender", + "tab": "1612772287426", + "name": "Info sender", + "x": 285, + "y": 1338, + "connections": { + "0": [ + { + "index": "0", + "id": "1634484067516" + }, + { + "index": "0", + "id": "1634303743260" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "edge": "undefined" + }, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1635327431236", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 795.8833312988281, + "y": 1329.5, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1635936391935", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "send-to-services", + "x": 778, + "y": 656, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1637069803394", + "component": "monitorconsumption", + "tab": "1612772287426", + "name": "CPU", + "x": 69, + "y": 791, + "connections": { + "0": [ + { + "index": "0", + "id": "1634464580289" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "0.6% / 102.09 MB", + "color": "gray" + }, + "options": { + "monitorfiles": true, + "monitorconnections": true, + "monitorsize": true, + "monitorconsumption": true, + "enabled": true, + "interval": 30000 + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1683664161036", + "component": "debug", + "tab": "1615551125555", + "name": "CMDtoDIDO", + "x": 392, + "y": 1012, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1683981346282", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "from-dido-controller", + "x": 113, + "y": 456, + "connections": { + "0": [ + { + "index": "0", + "id": "1684055037116" + }, + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "from-dido-controller", + "color": "gray" + }, + "options": { + "wirename": "from-dido-controller" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1684055037116", + "component": "debug", + "tab": "1615551125555", + "name": "from dido to cmd", + "x": 448, + "y": 519, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1684060205000", + "component": "debug", + "tab": "1615551125555", + "name": "HTTP routes", + "x": 447, + "y": 620, + "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": "MDBToDido", + "x": 598, + "y": 147, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1699963668903", + "component": "dido_controller", + "tab": "1615551125555", + "name": "DIDO_Controller", + "x": 397, + "y": 1131, + "connections": { + "0": [ + { + "index": "0", + "id": "1617104731852" + } + ], + "1": [ + { + "index": "0", + "id": "1617104731852" + }, + { + "index": "0", + "id": "1617115013095" + } + ], + "2": [ + { + "index": "0", + "id": "1618393583970" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "edge": "undefined" + }, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1699964678894", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "modbus_to_dido", + "x": 96, + "y": 924, + "connections": { + "0": [ + { + "index": "0", + "id": "1699963668903" + }, + { + "index": "0", + "id": "1699964793925" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "modbus_to_dido", + "color": "gray" + }, + "options": { + "wirename": "modbus_to_dido" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1699964793925", + "component": "debug", + "tab": "1615551125555", + "name": "modbusToDido", + "x": 388, + "y": 920, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1699965957410", + "component": "modbus_reader", + "tab": "1611921777196", + "name": "Modbus reader", + "x": 232, + "y": 175, + "connections": { + "0": [ + { + "index": "0", + "id": "1611951142547" + } + ], + "1": [ + { + "index": "0", + "id": "1621340721628" + }, + { + "index": "0", + "id": "1684179110403" + }, + { + "index": "0", + "id": "1717441414646" + } + ], + "2": [ + { + "index": "0", + "id": "1615809595184" + }, + { + "index": "0", + "id": "1714752862828" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1700411878636", + "component": "thermometer", + "tab": "1611921777196", + "name": "Thermometer", + "x": 234.75, + "y": 444, + "connections": { + "0": [ + { + "index": "0", + "id": "1615802995322" + } + ], + "1": [ + { + "index": "0", + "id": "1615809595184" + }, + { + "index": "0", + "id": "1615809128443" + } + ], + "2": [ + { + "index": "0", + "id": "1621340721628" + }, + { + "index": "0", + "id": "1732889185927" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#5CB36D", + "notes": "" + }, + { + "id": "1714752862828", + "component": "debug", + "tab": "1611921777196", + "name": "MDBToTb", + "x": 599, + "y": 257, + "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": 755.0833282470703, + "y": 209, + "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": 966.0833282470703, + "y": 152, + "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": 968.0833282470703, + "y": 268, + "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": 77.75, + "y": 1630, + "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": 296, + "y": 1671, + "connections": { + "0": [ + { + "index": "0", + "id": "1718016086212" + }, + { + "index": "0", + "id": "1718016073501" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Running", + "color": "gray" + }, + "options": { + "name": "rvo_senica_45_10.0.0.120", + "types": "[\"emergency\", \"critical\", \"error\", \"alert\"]", + "message_includes": "[\"is responding again\", \"Flow has been restarted\", \"Node db has changed\"]", + "tag_on_include": "[{\"user_id\":\"U072JE5JUQG\", \"includes\":[\"Electrometer\", \"Twilight sensor\"]}]", + "slack_channel": "C071KN2Q8SK" + }, + "color": "#30E193", + "notes": "" + }, + { + "id": "1718016073501", + "component": "httprequest", + "tab": "1612772287426", + "name": "http://192.168.252.2:8004/slack", + "x": 495, + "y": 1753, + "connections": { + "0": [ + { + "index": "0", + "id": "1718016086212" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "url": "http://192.168.252.2:8004/slack", + "method": "POST", + "stringify": "json" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1718016086212", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 832, + "y": 1664, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "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": 79, + "y": 1723, + "connections": { + "0": [ + { + "index": "0", + "id": "1718016052341" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "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\": \"\" } } } ] }", + "datatype": "object" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1729855334955", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "platform-rpc-call", + "x": 649.9333343505859, + "y": 541.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "platform-rpc-call", + "color": "gray" + }, + "options": { + "wirename": "platform-rpc-call" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1729855371093", + "component": "debug", + "tab": "1612772287426", + "name": "rpc cloud", + "x": 650.9333343505859, + "y": 451.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1731068658334", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 90.75, + "y": 250, + "connections": { + "0": [ + { + "index": "0", + "id": "1612776786008" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731068754606", + "component": "cloudmqttconnect", + "tab": "1612772287426", + "name": "MQTT client - to senica-prod01", + "x": 304.75, + "y": 474, + "connections": { + "1": [ + { + "index": "0", + "id": "1729855371093" + }, + { + "index": "0", + "id": "1729855334955" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Connected", + "color": "green" + }, + "options": { + "username": "", + "clientid": "", + "port": "2764", + "host": "192.168.252.2", + "topic": "u120" + }, + "color": "#888600", + "notes": "" + }, + { + "id": "1731069001548", + "component": "db_init", + "tab": "1612772287426", + "name": "DB Initialization", + "x": 91.75, + "y": 55.25, + "connections": { + "0": [ + { + "index": "0", + "id": "1731069033416" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#888600", + "notes": "" + }, + { + "id": "1731069033416", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "db-init", + "x": 343.75, + "y": 50.25, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069059135", + "component": "showdb", + "tab": "1612772287426", + "name": "Show db data", + "x": 1121.75, + "y": 814.25, + "connections": { + "0": [ + { + "index": "0", + "id": "1731069079243" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#888600", + "notes": "" + }, + { + "id": "1731069079243", + "component": "debug", + "tab": "1612772287426", + "name": "dbData", + "x": 1315.75, + "y": 853.25, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1731069116691", + "component": "trigger", + "tab": "1612772287426", + "name": "settings", + "x": 911.75, + "y": 710.75, + "connections": { + "0": [ + { + "index": "0", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069131637", + "component": "trigger", + "tab": "1612772287426", + "name": "relaysData", + "x": 832.75, + "y": 775.75, + "connections": { + "0": [ + { + "index": "1", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069137374", + "component": "trigger", + "tab": "1612772287426", + "name": "nodesData", + "x": 747.75, + "y": 840.75, + "connections": { + "0": [ + { + "index": "2", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069179846", + "component": "trigger", + "tab": "1612772287426", + "name": "pinsData", + "x": 803.75, + "y": 899.75, + "connections": { + "0": [ + { + "index": "3", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069192937", + "component": "trigger", + "tab": "1612772287426", + "name": "sample data", + "x": 858.75, + "y": 959.75, + "connections": { + "0": [ + { + "index": "4", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069264443", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 63.75, + "y": 1279, + "connections": { + "0": [ + { + "index": "0", + "id": "1634488120710" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069334626", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "db-init", + "x": 151.88333129882812, + "y": 148, + "connections": { + "0": [ + { + "index": "0", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069548145", + "component": "virtualwirein", + "tab": "1611921777196", + "name": "db-init", + "x": 46.75, + "y": 192, + "connections": { + "0": [ + { + "index": "0", + "id": "1699965957410" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069567152", + "component": "virtualwirein", + "tab": "1611921777196", + "name": "db-init", + "x": 44.75, + "y": 465, + "connections": { + "0": [ + { + "index": "0", + "id": "1700411878636" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731070156936", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "db-init", + "x": 89.88333129882812, + "y": 1381, + "connections": { + "0": [ + { + "index": "2", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731234189516", + "component": "trigger", + "tab": "1612772287426", + "name": "monitor.txt", + "x": 915.75, + "y": 1017.75, + "connections": { + "0": [ + { + "index": "5", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731234189551", + "component": "trigger", + "tab": "1612772287426", + "name": "err.txt", + "x": 966.75, + "y": 1080.75, + "connections": { + "0": [ + { + "index": "6", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1732700042559", + "component": "nodesdb_change_check", + "tab": "1612772287426", + "name": "Nodes DB change check", + "x": 263.8833312988281, + "y": 1993.2333984375, + "connections": { + "0": [ + { + "index": "0", + "id": "1732700071298" + }, + { + "index": "0", + "id": "1732700642917" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#888600", + "notes": "" + }, + { + "id": "1732700057052", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 84.75, + "y": 1994, + "connections": { + "0": [ + { + "index": "0", + "id": "1732700042559" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1732700071298", + "component": "debug", + "tab": "1612772287426", + "name": "nodesChange", + "x": 561.8833312988281, + "y": 2055.2333984375, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1732700642917", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "tb-push", + "x": 557.8833312988281, + "y": 1949, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1732889185927", + "component": "debug", + "tab": "1611921777196", + "name": "tempToDido", + "x": 594.8833312988281, + "y": 745, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1733574412965", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 86.75, + "y": 495, + "connections": { + "0": [ + { + "index": "1", + "id": "1731068754606" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + } + ], + "version": 615 +} \ No newline at end of file diff --git a/RVO45/flow_pred_verziou_2025_01_30/dido_controller.js b/RVO45/flow_pred_verziou_2025_01_30/dido_controller.js new file mode 100755 index 0000000..8415921 --- /dev/null +++ b/RVO45/flow_pred_verziou_2025_01_30/dido_controller.js @@ -0,0 +1,1524 @@ +exports.id = 'dido_controller'; +exports.title = 'DIDO_Controller'; +exports.version = '2.0.0'; +exports.group = 'Worksys'; +exports.color = '#2134B0'; +exports.input = 3; +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 { 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 +} + + +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 = {}; + 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"); + + //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 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 + }; + + + function main() { + + GLOBALS = FLOW.GLOBALS; + SETTINGS = FLOW.GLOBALS.settings; + rvoTbName = SETTINGS.rvoTbName; + pinsData = GLOBALS.pinsData; + relaysData = GLOBALS.relaysData; + + 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"; + + 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, "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; + turnLine("off", 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; + + sendTelemetry(values, rvoTbName); + + 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) { + if (!err) { + monitor.info(exports.title + "--->Digital in_out has been set (runSyncExec was sucessfull)"); + + turnAlarm("off"); + 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() { + + //to keep websocket opened, we send request every 150 seconds + let startRequests = null; + + console.log("handleWebSocket function called"); + ws = new WebSocket('ws:/0.0.0.0:1234/ws'); + + ws.onopen = function open() { + + instance.send(0, exports.title + " running"); + turnAlarm("off"); + + // useTurnOffCounter = true; + // turnOffCounter = relaysData.length - 1; + initialSetting(); + ws.send(JSON.stringify({ "cmd": "all" })); + + // we request dev info about neuron device from evok to keep websocket connection alive + // for some reason this request returns no data, but connection keeps alive + // https://evok.api-docs.io/1.0/mpqzDwPwirsoq7i5A/websocket + startRequests = setInterval(() => { + // console.log(" *** data from evok requested"); + ws.send(JSON.stringify({ "cmd": "filter", "dev": ["neuron"] })); + }, 150000) + }; + + + // 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 = async 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; + + 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) => { + monitor.info('websocket error, reconnect') + instance.send(SEND_TO.debug, err.message); + clearInterval(startRequests); + ws = null; + setTimeout(handleWebSocket, 1000); + }) + + + ws.onclose = function() { + // connection closed, discard old websocket and create a new one in 5s + // stopRequests(); + monitor.info('websocket onclose, reconnect') + clearInterval(startRequests); + ws = null; + console.log("ws is null now, reconnecting..."); + setTimeout(handleWebSocket, 1000); + } + } + + 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 turnAlarm(onOrOff) { + let value = 0; + if (onOrOff == "on") value = 1; + + if (value == 1 && SETTINGS.maintenance_mode) return; + + alarmStatus = "OFF"; + if (value == 1) alarmStatus = "ON"; + + if (rsPort) { + let arr = [0x55]; + arr.push(13); + arr.push(0); + arr.push(value); + + rsPort.write(Buffer.from(arr), function(err) { + logger.debug(`sirena - ${onOrOff}`); + }); + } + else if (ws) { + let cmd = { "cmd": "set", "dev": "relay", "circuit": "1_01", "value": value }; + ws.send(JSON.stringify(cmd)); + logger.debug(`sirena - ${onOrOff}`); + } + } + + + 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") { + bits.push(0); + } + else bits.push(1); + + if (deviceStatus["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); + } + + + // turn line on or off + function turnLine(onOrOff, line, pin, force, info) { + //onOrOff => "on" or "off" + let value = 0; + if (onOrOff == "on") value = 1; + + if (force == undefined) force = false; + + if (line == 0) { + if (value == 1 && alarmStatus == "ON") turnAlarm("off"); + SETTINGS.maintenance_mode = value ? true : false; + + 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); + return; + } + + if (pin === undefined) pin = getPin(line); + + if (pin === undefined) { + errLogger.error("pin is undefined!", line); + return; + } + + if (!force) { + if (relaysData[line].contactor == value) { + instance.send(SEND_TO.debug, `line is already ${onOrOff} ` + line); + logger.debug(`turnLine: line is already ${onOrOff} `, 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(value); + + rsPort.write(Buffer.from(arr), function(err) { + if (err === undefined) { + monitor.info(`turnLine ${onOrOff} zapisal do rsPort-u`, line, pin, arr, info); + switchLogic(arr); + } + else { + monitor.info(`turnLine ${onOrOff} 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 }; + ws.send(JSON.stringify(cmd)); + switchLogic(pin, value) + } + + //if rvo is 24/7, it has just one switching profile point at 13:00. we do not want to send notification as it repeats every day. + //const d = new Date(); + //if(d.getHours() != 13) sendNotification("Dido_controller: ", SETTINGS.rvoTbName, "switching_profile_point_applied_to_line", { line: line, value: onOrOff }, "", SEND_TO.tb, instance); + } + + + // 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; + + // 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) { + const status = flowdata.data.status; + if (status == "NOK-twilight_sensor") { + deviceStatus["twilight_sensor"] = "NOK"; + } + else if (status == "NOK-em340" || status == "NOK-em111") { + deviceStatus["em"] = "NOK"; + } + else if (status == "NOK-thermometer") { + deviceStatus["temperature"] = "NOK"; + } + } + else if ("values" in flowdata.data) { + 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" + } + else if (values.hasOwnProperty("temperature")) { + deviceStatus["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"; + } + + sendTelemetry(values, rvoTbName); + } + + sendRvoStatus(); + }) + + + // we expect array as flowdata.data + instance.on("1", flowdata => { + + console.log(flowdata.data); + + if (!flowdata.data instanceof Object) return; + + let obj = flowdata.data; + let line = obj.line; + 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"); + + //! ake data prichadzaju z cmd_manager.js ??? + //TODO transform to websocket + if (Array.isArray(obj)) { + + rsPort.write(Buffer.from(obj), function(err) { + switchLogic(obj); + + instance.send(SEND_TO.debug, { "WRITE": obj }); + }); + } + }) + + + function calculateStateCode() { + + 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") { + bits.push(0); + } + else { + bits.push(1); + } + + //Prevádzkový mód - Manual, Off, Automatic, maintenance_mode = true/false // DAVA 2 BITY + if (!SETTINGS.maintenance_mode) { + if (deviceStatus["rotary_switch_state"] == "Manual") { + bits.push(0); + bits.push(1); + } + + if (deviceStatus["rotary_switch_state"] == "Automatic") { + bits.push(0); + bits.push(0); + } + + if (deviceStatus["rotary_switch_state"] == "Off") { + bits.push(1); + bits.push(0); + } + } + else { + bits.push(1); + bits.push(1); + } + + //Dverový kontakt + if (deviceStatus["door_condition"] == "closed") { + bits.push(0); + } + else { + bits.push(1); + } + + //EM + if (deviceStatus["em"] == "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //Teplomer + if (deviceStatus["temperature"] == "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //Batéria + if (deviceStatus["battery"] == "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //Zdroj + if (deviceStatus["power_supply"] == "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //MN + if (deviceStatus["master_node"] == "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //výpadok napätia na fáze + if (deviceStatus["no_voltage"] == "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + if (deviceStatus["twilight_sensor"] == "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + // doplnime do 16 bitov (2 byty) + for (let i = bits.length; i < 16; i++) { + bits.push(0); + } + + // console.log("calculateStateCode - deviceStatus", deviceStatus); + // 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; + } + + + async function sendRvoStatus() { + + if (SETTINGS === undefined) return; + SETTINGS.masterNodeIsResponding ? deviceStatus["master_node"] = "OK" : deviceStatus["master_node"] = "NOK"; + + 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() { + + // 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 + //set RVO state + let status = "OK"; + + for (const [key, value] of Object.entries(deviceStatus)) { + if (["em", "twilight_sensor", "temperature", "master_node"].includes(key) && value == "NOK") status = "NOK"; + } + + if (status == "OK") { + let pinIndexes = [1, 4, 6]; + if (controller_type == 'unipi') pinIndexes = ['input1_01', 'input1_04', 'input1_05']; + + for (const pinIndex of pinIndexes) { + if (previousValues[pinIndex] === 0) { + if ((pinIndex === 6 || pinIndex === 'input1_01' || pinIndex === 'input1_05') && SETTINGS.maintenance_mode) continue; + status = "NOK"; + break; + } + } + } + + // battery status. If value is 1 - battery is NOK + if (previousValues[5] === 1) status = "NOK"; + if (SETTINGS.no_voltage.size > 0) status = "NOK"; + + // console.log("rvo status",status) + return status; + } + + + // we pass array to function in case of rsPort ==> switchLogic([55,3,0,1]) ==> [[55,3,0,1]] + // we pass two values in case of websocket ==> switchLogic("relay1_03",1) ==> ["relay1_03",1] + const switchLogic = (...args) => { + + let values = {}; + let pinIndex, newPinValue, twilight; + + //data from rsPort + if (args.length == 1) { + pinIndex = args[0][1] + 1; + if (pinIndex === 17) pinIndex--; + newPinValue = args[0][3]; + twilight = args[0][2]; + } + //data from websocket + else { + pinIndex = args[0]; + newPinValue = args[1]; + } + + 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; + + //default value + let value = "On"; + if (newPinValue === 0) value = "Off"; + + //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"; + + // 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"); + + // deviceStatus["state_of_main_switch"] = "On"; + // } + // } + + //Prevádzkový mód + 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"; + + deviceStatus["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, "power_supply_has_disconnected_input", {}, "", SEND_TO.tb, instance, "power_supply"); + + deviceStatus["power_supply"] = "NOK"; + } + else if (newPinValue === 1 && newPinValue !== previousValues[pinIndex]) { + sendNotification("switchLogic", rvoTbName, "power_supply_works_correctly", {}, "", SEND_TO.tb, instance, "power_supply"); + + deviceStatus["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"); + + deviceStatus["battery"] = "NOK"; + } + else if (newPinValue === 0 && newPinValue !== previousValues[pinIndex]) { + sendNotification("switchLogic", rvoTbName, "battery_level_is_ok", {}, "", SEND_TO.tb, instance, "battery_level"); + + deviceStatus["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' + else if (type == "door_condition" || type === "state_of_main_switch") { + newPinValue === 0 ? value = "open" : value = "closed"; + + 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, "door_opened_without_permission", {}, "", SEND_TO.tb, instance, "rvo_door"); + + // 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 (value === "closed") { + if (alarmStatus == "ON") turnAlarm("off"); + sendNotification("switchLogic", rvoTbName, "door_closed", {}, "", SEND_TO.tb, instance, "rvo_door"); + } + + deviceStatus[type] = value; + } + + //lux sensor + else if (type == "twilight_sensor") { + //! TODO - to show nok status, if lux value is not changing more then 10 times. + //Daylight is far more than 1000. So most of the day, when it is sunshine comes just value 1000. But lux sensor is not NOK. + //This is not the case in LM. If value from LM is the same 10x, there is 99% possibility, that sensor is NOK. + value = newPinValue; + + if (controller_type === 'lm') { + value = parseFloat(newPinValue + (256 * twilight)); + + 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 && !twilightError) { + twilightError = true; + let value = twilight_sensor_array.shift(); + + newPinValue = 0; + } + else if (set.size !== 1 && twilightError) { + //sendNotification("switchLogic", rvoTbName, 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) { + 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); + } + } + + 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); + } + + deviceStatus["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) + // { + // let time = 0; + // if(value) time = 1000 * 10;//10 sekund + + // let dataChanged = false; + // if(relaysData[line].contactor != newPinValue) dataChanged = true; + // relaysData[line].contactor = newPinValue; // 0,1 + + // //ak bola predchadzajuci stav off a novy stav je on, budu sa nastavovat nespracovane node profiles + // //a budu sa odosielat commandy, tie vsak mozu zlyhat, a preto potrebujeme ich spusti trochu neskor + // setTimeout(function(){ + // instance.send(SEND_TO.cmd_manager, {sender: "dido_controller", cmd: "reload_relays", line: line, time: time, value: value, dataChanged: dataChanged}); + // }, time); + + // reportLineStatus(line); + // } + // else + // { + // errLogger.error("modify table relays failed", err); + // } + + // }); + // }); + } + + 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 }); + + //mame iba 3 istice. vyreportujeme a ohandlujeme liniu na tom istom istici ako paralelna linia (napr linia 1, paralelna s nou je linia 4, key je string "4") + // ak je 7 linii, na 1 istici je linia 1,4,7 + + if (line == 1) { + + const lineOnSameBraker = [4, 7]; + + for (var i = 0; i < lineOnSameBraker.length; i++) { + if (!relaysData.hasOwnProperty(lineOnSameBraker[i])) continue; + + 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; + reportLineStatus(lineOnSameBraker[i]); + + values[type] = value; + const tbname = relaysData[lineOnSameBraker[i]].tbname; + sendTelemetry(values, tbname); + + delete values[type]; + } + + } + else { + const lineOnSameBraker = line + 3 + ""; + + if (relaysData.hasOwnProperty(lineOnSameBraker)) { + 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; + reportLineStatus(line + 3); + + values[type] = value; + const tbname = relaysData[lineOnSameBraker].tbname; + sendTelemetry(values, tbname); + + delete values[type]; + } + } + + } + + if (value == "Off") values["status"] = "NOK"; + deviceStatus["state_of_breaker"][line] = value; + + reportLineStatus(line); + } + else return; + + values[type] = value; + + if (type == "rotary_switch_state") { + if (SETTINGS.maintenance_mode) value = "maintenance"; + value = value.toLowerCase(); + values["power_mode"] = value; + } + + if (newPinValue != previousValues[pinIndex]) previousValues[pinIndex] = newPinValue; + if (Object.keys(values).length > 0 && tbname) sendTelemetry(values, tbname); + } + + + function sendTelemetry(values, tbname, date = Date.now()) { + let dataToTb = { + [tbname]: [ + { + "ts": date, + "values": values + } + ] + }; + + tbHandler.sendToTb(dataToTb, instance); + } + + + function isObject(item) { + return (typeof item === "object" && !Array.isArray(item) && item !== null); + } + +} //end of 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 +// *|input1_01|state_of_main_switch|0|........... +// *|input1_02|rotary_switch_state|0|........... +// *|input1_03|rotary_switch_state|0|........... +// *|intut1_04|power_supply|0|........... +// *|input1_05|door_condition|0|........... +// *|input1_06|state_of_breaker|1|........... +// *|input1_07|state_of_breaker|2|........... +// *|input1_08|state_of_breaker|3|........... +// *|relay1_02|state_of_contactor|1|........... +// *|relay1_03|state_of_contactor|2|........... +// *|relay1_04|state_of_contactor|3|........... +// *|287D8776E0013CE9|temperature|0|........... + + +//! pins_data --> from UNIPI +// { +// 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 } +// } + +//! relays_data +// { +// '0': { +// line: 0, +// tbname: 'KjbN4q7JPZmexgdnz2yKQ98YAWwO0Q3BMX6ERLoV', +// contactor: 1, +// profile: '' +// }, +// '1': { +// line: 1, +// tbname: 'RMgnK93rkoAazbqdQ4yBG95Z1YXGx6pmwBeVEP2O', +// contactor: 0, +// profile: '{"intervals":[{"value":0,"end_time":"20:00","start_time":"13:00"},{"value":1,"end_time":"10:00","start_time":"20:00"},{"value":0,"end_time":"10:20","start_time":"10:00"},{"value":1,"end_time":"10:40","start_time":"10:20"},{"value":0,"end_time":"11:00","start_time":"10:40"},{"value":1,"end_time":"11:30","start_time":"11:00"},{"value":0,"end_time":"11:50","start_time":"11:30"},{"value":1,"end_time":"13:00","start_time":"11:50"}],"astro_clock":false,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' +// }, +// '2': { +// line: 2, +// tbname: 'dlE1VQjYrNx9gZRmb38gG08oLBO4qaAk2M6JPnG7', +// contactor: 0, +// profile: '{"intervals":[{"value":0,"end_time":"20:00","start_time":"13:00"},{"value":1,"end_time":"10:00","start_time":"20:00"},{"value":0,"end_time":"10:20","start_time":"10:00"},{"value":1,"end_time":"10:40","start_time":"10:20"},{"value":0,"end_time":"11:00","start_time":"10:40"},{"value":1,"end_time":"11:30","start_time":"11:00"},{"value":0,"end_time":"11:50","start_time":"11:30"},{"value":1,"end_time":"13:00","start_time":"11:50"}],"astro_clock":false,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' +// }, +// '3': { +// line: 3, +// tbname: 'vnmG4kJxaXWNBgMQq0D7Aj5e9oZzOAlr6LdR3w2V', +// contactor: 0, +// profile: '{"intervals":[{"value":0,"end_time":"20:30","start_time":"13:00"},{"value":1,"end_time":"00:10","start_time":"20:30"},{"value":0,"end_time":"13:00","start_time":"05:40"},{"value":1,"end_time":"05:40","start_time":"00:10"}],"astro_clock":true,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' +// } +// } + + + + + +// { +// "jbN4q7JPZmexgdnz2yKbWGDYAWwO0Q3BMX6ERLoV": [ +// { +// "ts": 1700409326353, +// "values": { +// "_event": { +// "type": "notice", +// "status": "new", +// "source": { +// "func": "rsPort.open()", +// "component": "1700343402190", +// "component_name": "DIDO_Controller", +// "edge": "jbN4q7JPZmexgdnz2yKbWGDYAWwO0Q3BMX6ERLoV" +// }, +// "message": "al_shariff_10.0.0.38: FLOW has been started ", +// "message_data": "" +// } +// } +// } +// ] +// } diff --git a/RVO45/flow_pred_verziou_2025_01_30/helper/DataToTbHandler.js b/RVO45/flow_pred_verziou_2025_01_30/helper/DataToTbHandler.js new file mode 100755 index 0000000..65e4ec3 --- /dev/null +++ b/RVO45/flow_pred_verziou_2025_01_30/helper/DataToTbHandler.js @@ -0,0 +1,166 @@ +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; + + this.sender = ""; + + // if attribute difference is less than limit value, we do not send to tb. + this.attributeChangeLimit = { + temperature: 0.5, + Phase_1_voltage: 2, + Phase_2_voltage: 2, + Phase_3_voltage: 2, + Phase_1_current: 0.1, + Phase_2_current: 0.1, + Phase_3_current: 0.1, + Phase_1_power: 2, + Phase_2_power: 2, + Phase_3_power: 2, + total_power: 2, + Phase_1_pow_factor: 0.1, + Phase_2_pow_factor: 0.1, + Phase_3_pow_factor: 0.1, + power_factor: 0.1, + lifetime: 0.5, + voltage: 2, + power: 2, + frequency: 3, + energy: 0.1, + current: 2, + inclination_x: 10, + inclination_y: 10, + inclination_z: 10 + }; + } + + dump() { + console.log("----------------------------"); + console.log("previousValues", this.previousValues); + console.log("----------------------------"); + } + + setSender(sender) { + this.sender = sender; + } + + isEmptyObject(obj) { + for (var name in obj) { + return false; + } + return true; + } + + sendToTb(dataToTb, instance) { + + let keys = Object.keys(dataToTb); + + if(keys.length == 0) + { + if(this.debug) console.log("sendToTb received empty object", dataToTb); + return; + } + + let tbname = keys[0]; + let ts; + + let arrayOfValues = dataToTb[tbname]; + let arrayOfValuesToSend = []; + + for(let i = 0; i < arrayOfValues.length; i++) + { + ts = arrayOfValues[i].ts; + let values = this.prepareValuesForTb(tbname, ts, arrayOfValues[i].values); + + if(!this.isEmptyObject(values)) + { + arrayOfValuesToSend.push({ts: ts, values: values}); + } + } + + if(arrayOfValuesToSend.length == 0) + { + //if(this.debug) console.log("data not sent - empty array"); + return; + } + + this.messageCounter++; + + let dataToTbModified = { + [tbname]: arrayOfValuesToSend + } + + //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); + instance.send(this.index, dataToTbModified); + } + + getDiffTimestamp(key) { + //TODO set different value for given key!!! + //if(key == "status") this.timeToHoldTbValue = 2*60*60;//2h + return this.timeToHoldTbValue * 1000; + } + + prepareValuesForTb(tbname, timestamp, values) { + + let keys = Object.keys(values); + if(!this.previousValues.hasOwnProperty(tbname)) + { + this.previousValues[tbname] = {}; + } + + //if(this.debug) console.log("prepareValuesForTb", tbname, timestamp, values); + + for(let i = 0; i < keys.length; i++) + { + let key = keys[i]; + let value = values[key]; + + if(!this.previousValues[tbname].hasOwnProperty(key)) + { + this.previousValues[tbname][key] = {ts: timestamp, value: value}; + continue; + } + + // attributeData ==> voltage: {ts:333333, value:5} + let attributeData = this.previousValues[tbname][key]; + let attributeToChange = false; + if(key in this.attributeChangeLimit) attributeToChange = true; + let limit = this.attributeChangeLimit[key]; + + if(attributeData.value === value || attributeToChange && Math.abs(attributeData.value - value) < limit) + { + let diff = timestamp - attributeData.ts; + let timestampDiffToRemoveKey = this.getDiffTimestamp(key); + if(diff > timestampDiffToRemoveKey) + { + attributeData.ts = Date.now(); + //if(this.debug) console.log(this.sender + ": update ts for key", key, "diff is", diff, "messageCounter", this.messageCounter); + } + else + { + delete values[key]; + //if(this.debug) console.log(this.sender + ": delete key", key, "diff is", diff, "messageCounter", this.messageCounter, timestampDiffToRemoveKey); + } + } + else + { + attributeData.value = value; + attributeData.ts = timestamp; + } + + } + + return values; + } +} + +module.exports = DataToTbHandler; + diff --git a/RVO45/flow_pred_verziou_2025_01_30/helper/ErrorToServiceHandler.js b/RVO45/flow_pred_verziou_2025_01_30/helper/ErrorToServiceHandler.js new file mode 100755 index 0000000..110ea8b --- /dev/null +++ b/RVO45/flow_pred_verziou_2025_01_30/helper/ErrorToServiceHandler.js @@ -0,0 +1,126 @@ +const { MD5 } = require('./md5.js'); +const { networkInterfaces } = require('os'); + +class ErrorToServiceHandler +{ + constructor() { + this.previousValues = {}; + + this.projects_id = undefined; + + const nets = networkInterfaces(); + this.ipAddresses = Object.create(null); // Or just '{}', an empty object + + for (const name of Object.keys(nets)) { + for (const net of nets[name]) { + // Skip over non-IPv4 and internal (i.e. 127.0.0.1) addresses + if (net.family === 'IPv4' && !net.internal) { + if (!this.ipAddresses[name]) { + this.ipAddresses[name] = []; + } + this.ipAddresses[name].push(net.address); + } + } + } + + //console.log(this.ipAddresses); + + } + + setProjectsId(projects_id) + { + this.projects_id = projects_id; + } + + processMessage(message, seconds, message_type) + { + if(message_type == undefined) message_type = "error_message"; + if(Array.isArray(message)) message = message.join(', '); + + let key = MD5(message); + let timestamp = new Date().getTime(); + + //keep in memory - default value is 1h + if (seconds === undefined) seconds = 60*60; + + if(!this.previousValues.hasOwnProperty(key)) + { + this.previousValues[key] = {ts: timestamp, duration: seconds}; + } + + let diff = (timestamp - this.previousValues[key].ts); + if(diff < this.previousValues[key].duration*1000) return false; + + this.previousValues[key].ts = timestamp; + + return true; + } + + sendMessageToService(message, seconds, message_type) + { + + let f = this.processMessage(message, seconds, message_type); + if(!f) return; + + /* + //------------- + if(message_type == undefined) message_type = "error_message"; + if(Array.isArray(message)) message = message.join(', '); + + let key = MD5(message); + let timestamp = new Date().getTime(); + + //keep in memory + if (seconds === undefined) seconds = 60*60; + + if(!this.previousValues.hasOwnProperty(key)) + { + this.previousValues[key] = {ts: timestamp, duration: seconds}; + } + + let diff = (timestamp - this.previousValues[key].ts); + if(diff < this.previousValues[key].duration*1000) return; + + this.previousValues[key].ts = timestamp; + */ + + //------------------------- + + //send to service + + let dataToInfoSender = {id: this.projects_id}; + + //js_error || error_message + dataToInfoSender[message_type] = message; + dataToInfoSender.ipAddresses = this.ipAddresses; + + 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) + { + console.log("this.projects_id is undefined"); + return; + } + */ + + RESTBuilder.make(function(builder) { + builder.method('POST'); + builder.post(dataToInfoSender); + builder.url('http://192.168.252.2:8004/sentmessage'); + + builder.callback(function(err, response, output) { + console.log("process.on error send", err, response, output, dataToInfoSender); + }); + }); + + + } +} + +module.exports = ErrorToServiceHandler; \ No newline at end of file diff --git a/RVO45/flow_pred_verziou_2025_01_30/helper/db_helper.js b/RVO45/flow_pred_verziou_2025_01_30/helper/db_helper.js new file mode 100755 index 0000000..40e796c --- /dev/null +++ b/RVO45/flow_pred_verziou_2025_01_30/helper/db_helper.js @@ -0,0 +1,44 @@ +function promisifyBuilder(builder) +{ + return new Promise((resolve, reject) => { + + try{ + + builder.callback(function(err, response) { + + if(err != null) reject(err); + resolve(response); + }); + + } catch (error) { + reject(error); + } + }) +} + +function makeMapFromDbResult(response, ...keys) +{ + let s = "-"; + let data = {}; + + for(let i = 0; i < response.length; i++) + { + let record = response[i]; + + let k = []; + for(let j = 0; j < keys.length; j++) + { + k.push( record[keys[j]] ); + } + + let key = k.join(s); + data[ key ] = record; + } + + return data; +} + +module.exports = { + promisifyBuilder, + makeMapFromDbResult + } \ No newline at end of file diff --git a/RVO45/flow_pred_verziou_2025_01_30/helper/logger.js b/RVO45/flow_pred_verziou_2025_01_30/helper/logger.js new file mode 100755 index 0000000..2585639 --- /dev/null +++ b/RVO45/flow_pred_verziou_2025_01_30/helper/logger.js @@ -0,0 +1,30 @@ +//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/RVO45/flow_pred_verziou_2025_01_30/helper/md5.js b/RVO45/flow_pred_verziou_2025_01_30/helper/md5.js new file mode 100755 index 0000000..d3b0480 --- /dev/null +++ b/RVO45/flow_pred_verziou_2025_01_30/helper/md5.js @@ -0,0 +1,5 @@ +function MD5(d){var r = M(V(Y(X(d),8*d.length)));return r.toLowerCase()};function M(d){for(var _,m="0123456789ABCDEF",f="",r=0;r>>4&15)+m.charAt(15&_);return f}function X(d){for(var _=Array(d.length>>2),m=0;m<_.length;m++)_[m]=0;for(m=0;m<8*d.length;m+=8)_[m>>5]|=(255&d.charCodeAt(m/8))<>5]>>>m%32&255);return _}function Y(d,_){d[_>>5]|=128<<_%32,d[14+(_+64>>>9<<4)]=_;for(var m=1732584193,f=-271733879,r=-1732584194,i=271733878,n=0;n>16)+(_>>16)+(m>>16)<<16|65535&m}function bit_rol(d,_){return d<<_|d>>>32-_} + +module.exports = { + MD5 +} \ No newline at end of file diff --git a/RVO45/flow_pred_verziou_2025_01_30/helper/notification_reporter.js b/RVO45/flow_pred_verziou_2025_01_30/helper/notification_reporter.js new file mode 100755 index 0000000..61c0aef --- /dev/null +++ b/RVO45/flow_pred_verziou_2025_01_30/helper/notification_reporter.js @@ -0,0 +1,131 @@ +//key is device, value = str +let sentValues= {}; +let notificationsData = null; + +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 +}; + +function getKey(map, val) { + return Object.keys(map).findItem(key => map[key] === val); +} + +//https://stackoverflow.com/questions/41117799/string-interpolation-on-variable +var template = (tpl, args) => tpl.replace(/\${(\w+)}/g, (_, v) => args[v]); + + +function initNotification() { + notificationsData = FLOW.GLOBALS.notificationsData; +} + +function sendNotification(func, device, key, params, extra, tb_output, instance, saveKey) { + + // return; + + let storeToSendValues = true; + if(saveKey == undefined) storeToSendValues = false; + + let lang = FLOW.GLOBALS.settings.language; + if(lang != "en" || lang != "sk") lang = "en"; + + let tpl = key; + let weight = ""; + + if(notificationsData[key]) + { + weight = notificationsData[key].weight; + weight = weight.toLowerCase(); + + tpl = notificationsData[key][lang]; + tpl = template(tpl, params); + } + else + { + //console.error("sendNotification: Notifications: undefined key", key, func, notificationsData); + console.error("sendNotification: Notifications: undefined key", key, func ); + return false; + } + + //detect invalid err weight + if(getKey(ERRWEIGHT, weight) == undefined) + { + console.error("sendNotification: Notifications: undefined weight", weight, key, func); + return false; + } + + if(sentValues.hasOwnProperty(saveKey)) + { + if(sentValues[saveKey] == tpl) + { + return false; + } + } + + if(sentValues[saveKey] == undefined) + { + if(storeToSendValues) + { + //do not send - flow is was started + sentValues[saveKey] = tpl; + return false; + } + } + + if(saveKey == "rvo_door") + { + //console.log("******", saveKey, sentValues[saveKey], tpl); + } + + if(storeToSendValues) sentValues[saveKey] = tpl; + + let str = FLOW.GLOBALS.settings.rvo_name; + if(str != "") str = str + ": "; + str = str + tpl; + + 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 + + return true; + +} + +module.exports = { + sendNotification, + ERRWEIGHT, + initNotification +} diff --git a/RVO45/flow_pred_verziou_2025_01_30/helper/register.js b/RVO45/flow_pred_verziou_2025_01_30/helper/register.js new file mode 100755 index 0000000..fc1d008 --- /dev/null +++ b/RVO45/flow_pred_verziou_2025_01_30/helper/register.js @@ -0,0 +1,144 @@ +/* +0 - cislo registra / prikaz +1 - recepient - 0 = master, 1 = slave (slave je automaticky group a broadcast) +2 - r/rw - read/write +3- register name - nazov registra / prikazu (len pre info - zobrazenie v aplikacii) + +4,5,6,7, - jednotlive byte-y - nazov byte-u +4-7 - RES. a prazdny string "" sa nezobrazia!!! +*/ + +//124 zaznamov +const registers = [ + ["0","1","R","Status","","",""], + ["1","1","RW","Dimming","R-Channel ","G-Channel","B-Channel ","W - Channel"], + ["2","1","R","Device types","","",".",""], + ["3","1","RW","Group addresses 1-4","Groups Add. 4","Groups Add. 3","Groups Add. 2","Groups Add. 1"], + ["4","1","RW","Group addresses 5-8","Groups Add. 8","Groups Add. 7","Groups Add. 6","Groups Add. 5"], + ["5","1","RW","Serial number (MAC)","","","",""], + ["6","1","RW","Time of dusk","HH","MM","SS","EXTRA"], + ["7","1","RW","Time of dawn","HH","MM","SS","EXTRA"], + ["8","1","RW","Time Schedule settings","TBD","TBD","Movement sensor","Time Schedule"], + ["9","1","RW","TS1 Time point 1","HH","MM","SS","Ext. Device"], + ["10","1","RW","TS1 Time point 1 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["11","1","RW","TS1 Time point 2","HH","MM","SS","Ext. Device"], + ["12","1","RW","TS1 Time point 2 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["13","1","RW","TS1 Time point 3","HH","MM","SS","Ext. Device"], + ["14","1","RW","TS1 Time point 3 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["15","1","RW","TS1 Time point 4","HH","MM","SS","Ext. Device"], + ["16","1","RW","TS1 Time point 4 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["17","1","RW","TS1 Time point 5","HH","MM","SS","Ext. Device"], + ["18","1","RW","TS1 Time point 5 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["19","1","RW","TS1 Time point 6","HH","MM","SS","Ext. Device"], + ["20","1","RW","TS1 Time point 6 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["21","1","RW","TS1 Time point 7","HH","MM","SS","Ext. Device"], + ["22","1","RW","TS1 Time point 7 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["23","1","RW","TS1 Time point 8","HH","MM","SS","Ext. Device"], + ["24","1","RW","TS1 Time point 8 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["25","1","RW","TS1 Time point 9","HH","MM","SS","Ext. Device"], + ["26","1","RW","TS1 Time point 9 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["27","1","RW","TS1 Time point 10","HH","MM","SS","Ext. Device"], + ["28","1","RW","TS1 Time point 10 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["29","1","RW","TS1 Time point 11","HH","MM","SS","Ext. Device"], + ["30","1","RW","TS1 Time point 11 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["31","1","RW","TS1 Time point 12","HH","MM","SS","Ext. Device"], + ["32","1","RW","TS1 Time point 12 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["33","1","RW","TS1 Time point 13","HH","MM","SS","Ext. Device"], + ["34","1","RW","TS1 Time point 13 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["35","1","RW","TS1 Time point 14","HH","MM","SS","Ext. Device"], + ["36","1","RW","TS1 Time point 14 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["37","1","RW","TS1 Time point 15","HH","MM","SS","Ext. Device"], + ["38","1","RW","TS1 Time point 15 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["39","1","RW","TS1 Time point 16","HH","MM","SS","Ext. Device"], + ["40","1","RW","TS1 Time point 16 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["41","1","RW","TS2 Time point 1","HH","MM","SS","Ext. Device"], + ["42","1","RW","TS2 Time point 1 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["43","1","RW","TS2 Time point 2","HH","MM","SS","Ext. Device"], + ["44","1","RW","TS2 Time point 2 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["45","1","RW","TS2 Time point 3","HH","MM","SS","Ext. Device"], + ["46","1","RW","TS2 Time point 3 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["47","1","RW","TS2 Time point 4","HH","MM","SS","Ext. Device"], + ["48","1","RW","TS2 Time point 4 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["49","1","RW","TS2 Time point 5","HH","MM","SS","Ext. Device"], + ["50","1","RW","TS2 Time point 5 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["51","1","RW","TS2 Time point 6","HH","MM","SS","Ext. Device"], + ["52","1","RW","TS2 Time point 6 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["53","1","RW","TS2 Time point 7","HH","MM","SS","Ext. Device"], + ["54","1","RW","TS2 Time point 7 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["55","1","RW","TS2 Time point 8","HH","MM","SS","Ext. Device"], + ["56","1","RW","TS2 Time point 8 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["57","1","RW","TS2 Time point 9","HH","MM","SS","Ext. Device"], + ["58","1","RW","TS2 Time point 9 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["59","1","RW","TS2 Time point 10","HH","MM","SS","Ext. Device"], + ["60","1","RW","TS2 Time point 10 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["61","1","RW","TS2 Time point 11","HH","MM","SS","Ext. Device"], + ["62","1","RW","TS2 Time point 11 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["63","1","RW","TS2 Time point 12","HH","MM","SS","Ext. Device"], + ["64","1","RW","TS2 Time point 12 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["65","1","RW","TS2 Time point 13","HH","MM","SS","Ext. Device"], + ["66","1","RW","TS2 Time point 13 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["67","1","RW","TS2 Time point 14","HH","MM","SS","Ext. Device"], + ["68","1","RW","TS2 Time point 14 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["69","1","RW","TS2 Time point 15","HH","MM","SS","Ext. Device"], + ["70","1","RW","TS2 Time point 15 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["71","1","RW","TS2 Time point 16","HH","MM","SS","Ext. Device"], + ["72","1","RW","TS2 Time point 16 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["73","1","RW","Power meter status","TBD","","",""], + ["74","1","R","Input Voltage","","","",""], + ["75","1","R","Input Current","","","",""], + ["76","1","R","Input Power","","","",""], + ["77","1","R","Cos phi","","","",""], + ["78","1","R","Frequency","","","",""], + ["79","1","RW","Energy","","","",""], + ["80","1","RW","Lifetime","","","",""], + ["81","1","RW","Power on cycles (input)","","","",""], + ["82","1","RW","Power on cycles (relay)","","","",""], + ["83","1","R","Time since last power on","","","",""], + ["84","1","R","Accelerometer data","","","",""], + ["85","1","RW","GPS latitude","pos/neg","deg","min ","sec"], + ["86","1","RW","GPS longitude","pos/neg","deg","min ","sec"], + ["87","1","RW","Actual time","HH","MM","SS","RES."], + ["88","1","RW","Actual date","Day of week","Day","Month","Year"], + ["89","1","R","Production data 1","","","",""], + ["90","1","R","Production data 2","","","",""], + ["91","1","RW","Network ID","NID3","NID2","NID1","NID0"], + ["95","1","RW","Actual Lux level from cabinet","RES.","RES.","HB","LB"], + ["96","1","RW","Threshold lux level","Dusk HB","Dusk LB","Dawn HB","Dawn LB"], + ["97","1","RW","Adjust period","Dusk HB","Dusk LB","Dawn HB","Dawn LB"], + ["98","1","RW","Offset","RES.","RES.","Dusk","Dawn"], + ["99","1","RW","CCT min/max range","max-H","max-L","min-H","min-L"], + ["100","1","RW","DALI interface","Cmd ID","Add","Cmd","Resp"], + ["101","1","RW","Module FW ver","v1","v2","v3","v4"], + ["102","1","RW","Module MAC-H","unused","unused","M1","M2"], + ["103","1","RW","Module MAC-L","M3","M4","M5","M6"], + ["122","1","R","FW update status/control register","Byte3","Byte2","Byte1","Byte0"], + ["123","1","R","FW update - data index","Byte3","Byte2","Byte1","Byte0"], + ["124","1","R","FW update - data","Byte3","Byte2","Byte1","Byte0"], + ["0","0","R","Status","","","",""], + ["1","0","RW","Control register","RES.","RES.","RES.","init mode enable"], + ["2","0","R","Device types","","","",""], + ["3","0","R","Serial number (MAC)","","","",""], + ["4","0","R","Production data 1","","","",""], + ["5","0","R","Production data 2","","","",""], + ["6","0","RW","Network ID","NID3","NID2","NID1","NID0"], + ["7","0","RW","RS232 settings","param.","param.","Baudrate H","Baudrate L"], + ["8","0","R","Accelerometer data","","","",""], + ["9","0","RW","Module FW ver","v1","v2","v3","v4"], + ["10","0","RW","Module MAC-H","unused","unused","M1","M2"], + ["11","0","RW","Module MAC-L","M3","M4","M5","M6"], + ["32","0","RW","FW update status/control register","Byte3","Byte2","Byte1","Byte0"], + ["33","0","RW","FW update - data index","Byte3","Byte2","Byte1","Byte0"], + ["34","0","RW","FW update - data","Byte3","Byte2","Byte1","Byte0"], + ["125","0","RW","Debug Register","Byte3","Byte2","Byte1","Byte0"], + ["126","0","RW","Network Control Register","Byte3","Byte2","Byte1","Byte0"], + ["127","0","R","Network Status Register","Byte3","Byte2","Byte1","Byte0"], + ["128","0","RW","Node XX Serial Number Register","SER3","SER2","SER1","SER0"], + ["256","0","R","Node XX Network Status Register","","","",""] +]; + +let register = {}; + +module.exports = { + registers, + register +} \ No newline at end of file diff --git a/RVO45/flow_pred_verziou_2025_01_30/helper/serialport_helper.js b/RVO45/flow_pred_verziou_2025_01_30/helper/serialport_helper.js new file mode 100755 index 0000000..8efa6af --- /dev/null +++ b/RVO45/flow_pred_verziou_2025_01_30/helper/serialport_helper.js @@ -0,0 +1,100 @@ +const { exec } = require('child_process'); + +function openPort(port){ + return new Promise((resolve, reject) => { + + var callbackError = function(err) { + port.removeListener('error', callbackError); + port.removeListener('open', callbackError); + + reject(err.message); + }; + + var callbackOpen = function(data) { + port.removeListener('error', callbackError); + port.removeListener('open', callbackOpen); + + resolve("port open: ok"); + }; + + port.on('error', callbackError); + port.on('open', callbackOpen); + + port.open(); + + }) +} + +function runSyncExec(command){ + return new Promise((resolve, reject) => { + + exec(command, (error, stdout, stderr) => { + if(error == null) resolve(stdout); + reject(error); + }); + + }) +} + +async function writeData(port, data, readbytes, timeout){ + return new Promise((resolve, reject) => { + + // 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) { + + port.write(Buffer.from(data), function(err) { + if (err) { + reject(err.message); + } + }); + + 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 +} diff --git a/RVO45/flow_pred_verziou_2025_01_30/helper/suncalc.js b/RVO45/flow_pred_verziou_2025_01_30/helper/suncalc.js new file mode 100755 index 0000000..c9ca56d --- /dev/null +++ b/RVO45/flow_pred_verziou_2025_01_30/helper/suncalc.js @@ -0,0 +1,317 @@ +/* + (c) 2011-2015, Vladimir Agafonkin + SunCalc is a JavaScript library for calculating sun/moon position and light phases. + https://github.com/mourner/suncalc +*/ + +(function () { 'use strict'; + +// shortcuts for easier to read formulas + +var PI = Math.PI, + sin = Math.sin, + cos = Math.cos, + tan = Math.tan, + asin = Math.asin, + atan = Math.atan2, + acos = Math.acos, + rad = PI / 180; + +// sun calculations are based on http://aa.quae.nl/en/reken/zonpositie.html formulas + + +// date/time constants and conversions + +var dayMs = 1000 * 60 * 60 * 24, + J1970 = 2440588, + J2000 = 2451545; + +function toJulian(date) { return date.valueOf() / dayMs - 0.5 + J1970; } +function fromJulian(j) { return new Date((j + 0.5 - J1970) * dayMs); } +function toDays(date) { return toJulian(date) - J2000; } + + +// general calculations for position + +var e = rad * 23.4397; // obliquity of the Earth + +function rightAscension(l, b) { return atan(sin(l) * cos(e) - tan(b) * sin(e), cos(l)); } +function declination(l, b) { return asin(sin(b) * cos(e) + cos(b) * sin(e) * sin(l)); } + +function azimuth(H, phi, dec) { return atan(sin(H), cos(H) * sin(phi) - tan(dec) * cos(phi)); } +function altitude(H, phi, dec) { return asin(sin(phi) * sin(dec) + cos(phi) * cos(dec) * cos(H)); } + +function siderealTime(d, lw) { return rad * (280.16 + 360.9856235 * d) - lw; } + +function astroRefraction(h) { + if (h < 0) // the following formula works for positive altitudes only. + h = 0; // if h = -0.08901179 a div/0 would occur. + + // formula 16.4 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + // 1.02 / tan(h + 10.26 / (h + 5.10)) h in degrees, result in arc minutes -> converted to rad: + return 0.0002967 / Math.tan(h + 0.00312536 / (h + 0.08901179)); +} + +// general sun calculations + +function solarMeanAnomaly(d) { return rad * (357.5291 + 0.98560028 * d); } + +function eclipticLongitude(M) { + + var C = rad * (1.9148 * sin(M) + 0.02 * sin(2 * M) + 0.0003 * sin(3 * M)), // equation of center + P = rad * 102.9372; // perihelion of the Earth + + return M + C + P + PI; +} + +function sunCoords(d) { + + var M = solarMeanAnomaly(d), + L = eclipticLongitude(M); + + return { + dec: declination(L, 0), + ra: rightAscension(L, 0) + }; +} + + +var SunCalc = {}; + + +// calculates sun position for a given date and latitude/longitude + +SunCalc.getPosition = function (date, lat, lng) { + + var lw = rad * -lng, + phi = rad * lat, + d = toDays(date), + + c = sunCoords(d), + H = siderealTime(d, lw) - c.ra; + + return { + azimuth: azimuth(H, phi, c.dec), + altitude: altitude(H, phi, c.dec) + }; +}; + + +// sun times configuration (angle, morning name, evening name) + +var times = SunCalc.times = [ + [-0.833, 'sunrise', 'sunset' ], + [ -0.3, 'sunriseEnd', 'sunsetStart' ], + [ -6, 'dawn', 'dusk' ], + [ -12, 'nauticalDawn', 'nauticalDusk'], + [ -18, 'nightEnd', 'night' ], + [ 6, 'goldenHourEnd', 'goldenHour' ] +]; + +// adds a custom time to the times config + +SunCalc.addTime = function (angle, riseName, setName) { + times.push([angle, riseName, setName]); +}; + + +// calculations for sun times + +var J0 = 0.0009; + +function julianCycle(d, lw) { return Math.round(d - J0 - lw / (2 * PI)); } + +function approxTransit(Ht, lw, n) { return J0 + (Ht + lw) / (2 * PI) + n; } +function solarTransitJ(ds, M, L) { return J2000 + ds + 0.0053 * sin(M) - 0.0069 * sin(2 * L); } + +function hourAngle(h, phi, d) { return acos((sin(h) - sin(phi) * sin(d)) / (cos(phi) * cos(d))); } +function observerAngle(height) { return -2.076 * Math.sqrt(height) / 60; } + +// returns set time for the given sun altitude +function getSetJ(h, lw, phi, dec, n, M, L) { + + var w = hourAngle(h, phi, dec), + a = approxTransit(w, lw, n); + return solarTransitJ(a, M, L); +} + + +// calculates sun times for a given date, latitude/longitude, and, optionally, +// the observer height (in meters) relative to the horizon + +SunCalc.getTimes = function (date, lat, lng, height) { + + height = height || 0; + + var lw = rad * -lng, + phi = rad * lat, + + dh = observerAngle(height), + + d = toDays(date), + n = julianCycle(d, lw), + ds = approxTransit(0, lw, n), + + M = solarMeanAnomaly(ds), + L = eclipticLongitude(M), + dec = declination(L, 0), + + Jnoon = solarTransitJ(ds, M, L), + + i, len, time, h0, Jset, Jrise; + + + var result = { + solarNoon: fromJulian(Jnoon), + nadir: fromJulian(Jnoon - 0.5) + }; + + for (i = 0, len = times.length; i < len; i += 1) { + time = times[i]; + h0 = (time[0] + dh) * rad; + + Jset = getSetJ(h0, lw, phi, dec, n, M, L); + Jrise = Jnoon - (Jset - Jnoon); + + result[time[1]] = fromJulian(Jrise); + result[time[2]] = fromJulian(Jset); + } + + return result; +}; + + +// moon calculations, based on http://aa.quae.nl/en/reken/hemelpositie.html formulas + +function moonCoords(d) { // geocentric ecliptic coordinates of the moon + + var L = rad * (218.316 + 13.176396 * d), // ecliptic longitude + M = rad * (134.963 + 13.064993 * d), // mean anomaly + F = rad * (93.272 + 13.229350 * d), // mean distance + + l = L + rad * 6.289 * sin(M), // longitude + b = rad * 5.128 * sin(F), // latitude + dt = 385001 - 20905 * cos(M); // distance to the moon in km + + return { + ra: rightAscension(l, b), + dec: declination(l, b), + dist: dt + }; +} + +SunCalc.getMoonPosition = function (date, lat, lng) { + + var lw = rad * -lng, + phi = rad * lat, + d = toDays(date), + + c = moonCoords(d), + H = siderealTime(d, lw) - c.ra, + h = altitude(H, phi, c.dec), + // formula 14.1 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + pa = atan(sin(H), tan(phi) * cos(c.dec) - sin(c.dec) * cos(H)); + + h = h + astroRefraction(h); // altitude correction for refraction + + return { + azimuth: azimuth(H, phi, c.dec), + altitude: h, + distance: c.dist, + parallacticAngle: pa + }; +}; + + +// calculations for illumination parameters of the moon, +// based on http://idlastro.gsfc.nasa.gov/ftp/pro/astro/mphase.pro formulas and +// Chapter 48 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + +SunCalc.getMoonIllumination = function (date) { + + var d = toDays(date || new Date()), + s = sunCoords(d), + m = moonCoords(d), + + sdist = 149598000, // distance from Earth to Sun in km + + phi = acos(sin(s.dec) * sin(m.dec) + cos(s.dec) * cos(m.dec) * cos(s.ra - m.ra)), + inc = atan(sdist * sin(phi), m.dist - sdist * cos(phi)), + angle = atan(cos(s.dec) * sin(s.ra - m.ra), sin(s.dec) * cos(m.dec) - + cos(s.dec) * sin(m.dec) * cos(s.ra - m.ra)); + + return { + fraction: (1 + cos(inc)) / 2, + phase: 0.5 + 0.5 * inc * (angle < 0 ? -1 : 1) / Math.PI, + angle: angle + }; +}; + + +function hoursLater(date, h) { + return new Date(date.valueOf() + h * dayMs / 24); +} + +// calculations for moon rise/set times are based on http://www.stargazing.net/kepler/moonrise.html article + +SunCalc.getMoonTimes = function (date, lat, lng, inUTC) { + var t = new Date(date); + if (inUTC) t.setUTCHours(0, 0, 0, 0); + else t.setHours(0, 0, 0, 0); + + var hc = 0.133 * rad, + h0 = SunCalc.getMoonPosition(t, lat, lng).altitude - hc, + h1, h2, rise, set, a, b, xe, ye, d, roots, x1, x2, dx; + + // go in 2-hour chunks, each time seeing if a 3-point quadratic curve crosses zero (which means rise or set) + for (var i = 1; i <= 24; i += 2) { + h1 = SunCalc.getMoonPosition(hoursLater(t, i), lat, lng).altitude - hc; + h2 = SunCalc.getMoonPosition(hoursLater(t, i + 1), lat, lng).altitude - hc; + + a = (h0 + h2) / 2 - h1; + b = (h2 - h0) / 2; + xe = -b / (2 * a); + ye = (a * xe + b) * xe + h1; + d = b * b - 4 * a * h1; + roots = 0; + + if (d >= 0) { + dx = Math.sqrt(d) / (Math.abs(a) * 2); + x1 = xe - dx; + x2 = xe + dx; + if (Math.abs(x1) <= 1) roots++; + if (Math.abs(x2) <= 1) roots++; + if (x1 < -1) x1 = x2; + } + + if (roots === 1) { + if (h0 < 0) rise = i + x1; + else set = i + x1; + + } else if (roots === 2) { + rise = i + (ye < 0 ? x2 : x1); + set = i + (ye < 0 ? x1 : x2); + } + + if (rise && set) break; + + h0 = h2; + } + + var result = {}; + + if (rise) result.rise = hoursLater(t, rise); + if (set) result.set = hoursLater(t, set); + + if (!rise && !set) result[ye > 0 ? 'alwaysUp' : 'alwaysDown'] = true; + + return result; +}; + + +// export as Node module / AMD module / browser variable +if (typeof exports === 'object' && typeof module !== 'undefined') module.exports = SunCalc; +else if (typeof define === 'function' && define.amd) define(SunCalc); +else window.SunCalc = SunCalc; + +}()); diff --git a/RVO45/flow_pred_verziou_2025_01_30/helper/utils.js b/RVO45/flow_pred_verziou_2025_01_30/helper/utils.js new file mode 100755 index 0000000..a16210c --- /dev/null +++ b/RVO45/flow_pred_verziou_2025_01_30/helper/utils.js @@ -0,0 +1,124 @@ +function bytesToInt(bytes, numberOfBytes) +{ + let buffer = []; + if(Array.isArray(bytes)) + { + buffer = bytes.slice(0); + if(numberOfBytes != undefined) + { + buffer = bytes.slice(bytes.length - numberOfBytes); + } + } + else buffer.push(bytes); + + //var decimal = (buffer[0] << 24) + (buffer[1] << 16) + (buffer[2] << 8) + buffer[3]; + let l = (buffer.length - 1) * 8; + + let decimal = 0; + for(let i = 0; i < buffer.length; i++) + { + var s = buffer[i] << l; + if(l < 8) s = buffer[i] + decimal = decimal + s; + + l = l - 8; + + } + + return decimal; +} + +function resizeArray(arr, newSize, defaultValue) { + while(newSize > arr.length) + arr.push(defaultValue); + arr.length = newSize; +} + +longToByteArray = function(/*long*/long) { + // we want to represent the input as a 8-bytes array + var byteArray = [0, 0, 0, 0, 0, 0, 0, 0]; + + for ( var index = 0; index < byteArray.length; index ++ ) { + var byte = long & 0xff; + byteArray [ index ] = byte; + long = (long - byte) / 256 ; + } + + return byteArray; + }; + +function addDays(date, days) { + var result = new Date(date); + result.setDate(result.getDate() + days); + return result; +} + +/* +sleep(2000).then(() => { + // Do something after the sleep! + + +}); +*/ + +function sleep (time) { + return new Promise((resolve) => setTimeout(resolve, time)); +} + +function isEmptyObject( obj ) { + for ( var name in obj ) { + return false; + } + return true; +} + +function convertUTCDateToLocalDate(date) { + var newDate = new Date(date); + newDate.setMinutes(date.getMinutes() + date.getTimezoneOffset()); + return newDate; +} + +function addZeroBefore(n) { + return (n < 10 ? '0' : '') + n; +} + +var convertBase = function () { + + function convertBase(baseFrom, baseTo) { + return function (num) { + return parseInt(num, baseFrom).toString(baseTo); + + }; + } + + // binary to decimal + convertBase.bin2dec = convertBase(2, 10); + + // binary to hexadecimal + convertBase.bin2hex = convertBase(2, 16); + + // decimal to binary + convertBase.dec2bin = convertBase(10, 2); + + // decimal to hexadecimal + convertBase.dec2hex = convertBase(10, 16); + + // hexadecimal to binary + convertBase.hex2bin = convertBase(16, 2); + + // hexadecimal to decimal + convertBase.hex2dec = convertBase(16, 10); + + return convertBase; + }(); + +module.exports = { + bytesToInt, + longToByteArray, + addDays, + addZeroBefore, + resizeArray, + isEmptyObject, + sleep, + convertUTCDateToLocalDate +} \ No newline at end of file diff --git a/RVO45/flow_pred_verziou_2025_01_30/httprequest.js b/RVO45/flow_pred_verziou_2025_01_30/httprequest.js new file mode 100755 index 0000000..469c8cb --- /dev/null +++ b/RVO45/flow_pred_verziou_2025_01_30/httprequest.js @@ -0,0 +1,137 @@ +exports.id = 'httprequest'; +exports.title = 'HTTP Request'; +exports.group = 'HTTP'; +exports.color = '#5D9CEC'; +exports.input = true; +exports.version = '2.0.1'; +exports.output = 1; +exports.author = 'Peter Širka'; +exports.icon = 'cloud-upload'; + +exports.html = `
+
@(URL address)
+
+
+
@(HTTP method)
+
+
+
@(Serialization)
+
+
+
@(Download the content in chunks)
+
@(Keep persistent cookies)
+
@(Disable DNS cache)
+
@(Keep alive connection)
+
+
+
+
@(Custom headers)
+
@(Cookies)
+
+
+
+ +
+
+
+
@(User)
+
+
+
@(Password)
+
+
+
+
+
`; + +exports.readme = `# Request + +This component creates a request with received data. + +__Response:__ +\`\`\`javascript +{ + data: String, + headers: Object, + status: Number, + host: String +} +\`\`\` + +__Dynamic arguments__: +Are performed via FlowData repository and can be used for URL address or for custom headers/cookies/auth. Use \`repository\` component for creating of dynamic arguments. Dynamic values are replaced in the form \`{key}\`: + +- url address e.g. \`https://.../{key}/\` +- headers values e.g. \`{token}\` +- cookies values e.g. \`{token}\``; + +exports.install = function(instance) { + + var can = false; + var flags = null; + var cookies2 = null; + + instance.on('data', function(response) { + can && instance.custom.send(response); + }); + + instance.custom.send = function(response) { + var options = instance.options; + + var headers = null; + var cookies = null; + + options.headers && Object.keys(options.headers).forEach(function(key) { + !headers && (headers = {}); + headers[key] = response.arg(options.headers[key]); + }); + + if (options.username && options.userpassword) { + !headers && (headers = {}); + headers['Authorization'] = 'Basic ' + U.createBuffer(response.arg(options.username + ':' + options.userpassword)).toString('base64'); + } + + options.cookies && Object.keys(options.cookies).forEach(function(key) { + !cookies && (cookies = {}); + cookies[key] = response.arg(options.cookies[key]); + }); + + if (options.chunks) { + U.download(response.arg(options.url), flags, options.stringify === 'none' ? null : response.data, function(err, response) { + response.on('data', (chunks) => instance.send2(chunks)); + }, cookies || cookies2, headers); + } else { + U.request(response.arg(options.url), flags, options.stringify === 'none' ? null : response.data, 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) + instance.error(err, response); + }, cookies || cookies2, headers); + } + }; + + instance.reconfigure = function() { + var options = instance.options; + can = options.url && options.url && options.method && options.stringify ? true : false; + instance.status(can ? '' : 'Not configured', can ? undefined : 'red'); + + if (!can) + return; + + flags = []; + flags.push(options.method.toLowerCase()); + options.stringify === 'json' && flags.push('json'); + options.stringify === 'raw' && flags.push('raw'); + options.keepalive && flags.push('keepalive'); + !options.nodns && flags.push('dnscache'); + if (options.persistentcookies) { + flags.push('cookies'); + cookies2 = {}; + } else + cookies2 = null; + }; + + instance.on('options', instance.reconfigure); + instance.reconfigure(); +}; \ No newline at end of file diff --git a/RVO45/flow_pred_verziou_2025_01_30/httpresponse.js b/RVO45/flow_pred_verziou_2025_01_30/httpresponse.js new file mode 100755 index 0000000..160a3bb --- /dev/null +++ b/RVO45/flow_pred_verziou_2025_01_30/httpresponse.js @@ -0,0 +1,76 @@ +exports.id = 'httpresponse'; +exports.title = 'HTTP Response'; +exports.group = 'HTTP'; +exports.color = '#5D9CEC'; +exports.icon = 'arrow-right'; +exports.input = true; +exports.output = ['#666D76']; +exports.version = '2.0.0'; +exports.author = 'Martin Smola'; +exports.readme = `# HTTP response + +HTTP response will respond with data recieved using data-type set in Settings form or plain text if not set. Output is the message duration \`Number\` in seconds.`; + +exports.html = `
+
@(Response data-type)
+
JSON is by default.
+
`; + +exports.install = function(instance) { + + var dursum = 0; + var durcount = 0; + + instance.on('data', function(flowdata) { + + var ctrl = flowdata.repository.controller; + var data = flowdata.data; + + if (!ctrl) { + instance.throw('No controller to use for response!'); + return; + } + + durcount++; + dursum += ((new Date() - flowdata.begin) / 1000).floor(2); + setTimeout2(instance.id, instance.custom.duration, 500, 10); + + ctrl.$flowdata = flowdata; + + var datatype = instance.options.datatype || 'json'; + if (datatype === 'emptyresponse') + return ctrl.plain(''); + + if (datatype !== 'json' && typeof(data) !== 'string') { + instance.throw('Incorect type of data, expected string, got ' + typeof(data)); + ctrl.plain(data == null ? '' : data.toString()); + return; + } + + switch(datatype) { + case 'html': + ctrl.content(data, 'text/html'); + break; + case 'plain': + ctrl.plain(data); + break; + case 'xml': + ctrl.content(data, 'text/xml'); + break; + default: + ctrl.json(data); + break; + } + }); + + instance.on('service', function() { + dursum = 0; + durcount = 0; + }); + + instance.custom.duration = function() { + var avg = (dursum / durcount).floor(2); + instance.status(avg + ' sec.'); + instance.send2(0, avg); + }; +}; diff --git a/RVO45/flow_pred_verziou_2025_01_30/httproute.js b/RVO45/flow_pred_verziou_2025_01_30/httproute.js new file mode 100755 index 0000000..583a19d --- /dev/null +++ b/RVO45/flow_pred_verziou_2025_01_30/httproute.js @@ -0,0 +1,326 @@ +exports.id = 'httproute'; +exports.title = 'HTTP Route'; +exports.group = 'HTTP'; +exports.color = '#5D9CEC'; +exports.icon = 'globe'; +exports.input = false; +exports.output = ['#6CAC5A', '#37BC9B']; +exports.version = '1.2.3'; +exports.author = 'Martin Smola'; +exports.cloning = false; +exports.options = { method: 'GET', url: '', size: 5, cacheexpire: '5 minutes', cachepolicy: 0, timeout: 5 }; +exports.dateupdated = '2021-01-21 18:30d'; +exports.readme = `# HTTP route + +__Outputs__: +- first output: raw data (cache is empty or is disabled) +- second output: cached data + +If one of the outputs is disabled then automatic responce with code "503 service unavailable" is sent. + +When a request comes in bellow object is available at \`flowdata.data\`: + +\`\`\`javascript +{ + params: { id: '1' }, // params for dynamic routes, e.g. /test/{id} + query: { msg: 'Hello' }, // parsed query string, e.g. /test/1?msg=Hello + body: { test: 'OK' }, // object if json requests otherwise string + headers: {}, // headers data + session: {}, // session data + user: {}, // user data + files: [], // uploaded files + url: '/users/', // a relative URL address + referrer: '/', // referrer + mobile: false, // determines mobile device + robot: false, // determines search robots/crawlsers + language: 'en' // determines language +} +\`\`\` + +See [documentation for flags](https://docs.totaljs.com/latest/en.html#api~HttpRouteOptionsFlags~unauthorize). These method flags are set automatically e.g. \`get, post, put, patch or delete\` + +--- + +\`id:ROUTE_ID\` flag cannot be used since it's already used by this component internally`; + +exports.html = `
+
+ +
+ +
+
+
@(HTTP method)
+
+
+
@(URL address)
+
+
+
+
+
@(Additional flags)
+
@(Separate flags by comma e.g. json, authorize)
+
+
+
@(Max. request size)
+
@(In kB kilobytes)
+
+
+
@(Timeout)
+
@(In seconds.)
+
+
+
+
+
+
@(Automatically respond with 200 OK?)
+
@(If not checked you need to use HTTP response component to respond to the request.)
+
+
@(Custom headers)
+
@(Cookies)
+
+
+
+
+
+
@(Cache policy)
+
@(User instance must contain id property.)
+
+
+
@(Expiration)
+
@(E.g. 5 minutes)
+
+
+
+`; + +exports.install = function(instance) { + + var route; + + var uninstall = function(id) { + if (F.is4) { + route && route.remove(); + route = null; + } else + UNINSTALL('route', id); + }; + + instance.custom.emptyresponse = function(self) { + self.plain(); + }; + + instance.reconfigure = function() { + + var options = instance.options; + + if (!options.url) { + instance.status('Not configured', 'red'); + return; + } + + if (typeof(options.flags) === 'string') + options.flags = options.flags.split(',').trim(); + + uninstall('id:' + instance.id); + + var flags = options.flags || []; + + flags.push('id:' + instance.id); + + if (!F.is4) + flags.push(options.method.toLowerCase()); + + options.timeout && flags.push(options.timeout * 1000); + + // Make unique values + flags = flags.filter(function(v, i, a) { + if(F.is4 && v.toString().toLowerCase() === options.method.toLowerCase()) + return false; // remove method + return a.indexOf(v) === i; + }); + + options.flags = flags; + var handler = function() { + + if (instance.paused || (instance.isDisabled && (instance.isDisabled('output', 0) || instance.isDisabled('output', 1)))) { + instance.status('503 Service Unavailable'); + this.status = 503; + this.json(); + return; + } + + var key; + var self = this; + + if (instance.options.emptyresponse) { + instance.status('200 OK'); + setTimeout(instance.custom.emptyresponse, 100, self); + + if (instance.hasConnection(0)) { + var data = instance.make({ + query: self.query, + body: self.body, + session: self.session, + user: self.user, + files: self.files, + headers: self.req.headers, + url: self.url, + params: self.params + }); + instance.send2(0, data); + } + + return; + } + + switch (instance.options.cachepolicy) { + case 1: // URL + key = 'rro' + instance.id + self.url.hash(); + break; + case 2: // URL + query + case 3: // URL + query + user + key = self.url; + var keys = Object.keys(self.query); + keys.sort(); + for (var i = 0, length = keys.length; i < length; i++) + key += keys[i] + self.query[keys[i]] + '&'; + if (instance.options.cachepolicy === 3 && self.user) + key += 'iduser' + self.user.id; + key = 'rro' + instance.id + key.hash(); + break; + } + + if (key && F.cache.get2(key)) { + var data = instance.make(F.cache.get2(key)); + data.repository.controller = self; + instance.send2(1, data); + } else { + + var data = instance.make({ + query: self.query, + body: self.body, + session: self.session, + user: self.user, + files: self.files, + headers: self.req.headers, + url: self.url, + params: self.params, + mobile: self.mobile, + robot: self.robot, + referrer: self.referrer, + language: self.language + }); + + data.repository.controller = self; + instance.send2(0, data); + key && FINISHED(self.res, () => F.cache.set(key, self.$flowdata.data, instance.options.cacheexpire)); + } + }; + + if (F.is4) + route = ROUTE(options.method.toUpperCase() + ' ' + options.url, handler, flags, options.size || 5); + else + F.route(options.url, handler, flags, options.size || 5); + + instance.status('Listening', 'green'); + }; + + instance.reconfigure(); + instance.on('options', instance.reconfigure); + instance.on('close', function(){ + uninstall('id:' + instance.id); + }); +}; + +// check url exists +FLOW.trigger('httproutecheckurl', function(next, data) { + var url = data.url; + var method = data.method; + if (url[url.length - 1] !== '/') + url += '/'; + var exists = F.routes.web.findItem(r => r.urlraw === url && r.method === method); + next(exists != null); +}); + +exports.uninstall = function() { + FLOW.trigger('httproutecheckurl', null); +}; diff --git a/RVO45/flow_pred_verziou_2025_01_30/infosender.js b/RVO45/flow_pred_verziou_2025_01_30/infosender.js new file mode 100755 index 0000000..c7afd83 --- /dev/null +++ b/RVO45/flow_pred_verziou_2025_01_30/infosender.js @@ -0,0 +1,101 @@ +exports.id = 'infosender'; +exports.title = 'Info sender'; +exports.version = '1.0.0'; +exports.group = 'Worksys'; +exports.color = '#2134B0'; +exports.input = 2; +exports.output = 1 +exports.icon = 'bolt'; + +const { networkInterfaces } = require('os'); + +exports.html = `
+
+
+
CSV Import
+
+
+
`; + +exports.readme = `# send all data to projects.worksys.io, required to monitor status of controller(unipi)`; + +exports.install = function(instance) { + + let id; + let allValues = {}; + let sendAllValuesInterval; + let configured = false; + + let now = new Date(); + console.log(exports.title, "INSTALLED", now.toLocaleString("sk-SK")); + + const nets = networkInterfaces(); + let ipAddresses = Object.create(null); // Or just '{}', an empty object + + for (const name of Object.keys(nets)) { + for (const net of nets[name]) { + // Skip over non-IPv4 and internal (i.e. 127.0.0.1) addresses + if (net.family === 'IPv4' && !net.internal) { + if (!ipAddresses[name]) { + ipAddresses[name] = []; + } + ipAddresses[name].push(net.address); + } + } + } + + function sendValues() + { + if(!configured) return; + + if(Object.keys(allValues).length > 0) + { + if(id) + { + delete allValues.__force__; + let dataToSend = {...allValues}; + dataToSend.id = id; + dataToSend.ipAddresses = ipAddresses; + + instance.send(0, dataToSend); + + allValues = {}; + } + else + { + console.log(exports.title, "unable to send data, no id"); + } + + } + } + + instance.on("close", () => { + clearInterval(sendAllValuesInterval); + }) + + instance.on("0", _ => { + id = FLOW.GLOBALS.settings.project_id; + configured = true; + }) + + instance.on("1", flowdata => { + + allValues = { ...allValues, ...flowdata.data}; + //console.log("DATA RECEIVED", flowdata.data); + + //__force__ + if(flowdata.data.hasOwnProperty("__force__")) + { + if(flowdata.data.__force__) + { + sendValues(); + } + } + }) + + sendAllValuesInterval = setInterval(() => { + sendValues(); + }, 60000*3); + +} + diff --git a/RVO45/flow_pred_verziou_2025_01_30/modbus_reader.js b/RVO45/flow_pred_verziou_2025_01_30/modbus_reader.js new file mode 100755 index 0000000..b907148 --- /dev/null +++ b/RVO45/flow_pred_verziou_2025_01_30/modbus_reader.js @@ -0,0 +1,367 @@ +exports.id = 'modbus_reader'; +exports.title = 'Modbus reader'; +exports.version = '2.0.0'; +exports.group = 'Worksys'; +exports.color = '#2134B0'; +exports.input = 1; +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; +//number of phases inRVO +let phases; +//phases where voltage is 0 (set) +let noVoltage; + +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.phases = this.buildPhases(); + + this.startSocket(); + } + + buildPhases = () => { + let a = []; + for (let i = 1; i<= phases; i++) { + a.push(`Phase_${i}_voltage`) + } + return a; + } + + 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 (this.phases.includes(singleValue)) + { + let l = singleValue.split("_"); + let phase = parseInt(l[1]); + + // console.log(values[singleValue], tbName); + + if(values[singleValue] == 0) + { + noVoltage.add(phase); + sendNotification("modbus_reader: checkNullVoltage", tbName, "no_voltage_on_phase", {phase: phase}, "", SEND_TO.tb, instance, "voltage" + phase ); + // console.log('no voltage') + } + else + { + noVoltage.delete(phase); + // console.log('voltage detected') + sendNotification("modbus_reader: checkNullVoltage", tbName, "voltage_on_phase_restored", {phase: phase}, "", SEND_TO.tb, instance, "voltage" + phase); + } + } + }) + } + + /** + * function sends notification to slack and to tb, if EM total_power value changes more than numberOfNodes*15. This should show, that RVO lamps has been switched on or off + */ + lampSwitchNotification = (values) => { + + if(!values.hasOwnProperty("total_power")) return; + + const actualTotalPower = values.total_power; + + const numberOfNodes = Object.keys(FLOW.GLOBALS.nodesData).length; + if(numberOfNodes == 0) numberOfNodes = 20; // to make sure, we send notification if totalPower is more than 300 + + if(actualTotalPower > numberOfNodes * 15 && this.onNotificationSent == false) + { + sendNotification("modbus_reader: lampSwitchNotification", tbName, "lamps_have_turned_on", {}, "", SEND_TO.tb, instance); + this.onNotificationSent = true; + this.offNotificationSent = false; + } + else if(actualTotalPower <= numberOfNodes * 15 && this.offNotificationSent == false) + { + 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; + } + + function main() { + + phases = FLOW.GLOBALS.settings.phases; + tbName = FLOW.GLOBALS.settings.rvoTbName; + noVoltage = FLOW.GLOBALS.settings.no_voltage; + mainSocket = new SocketWithClients(); + + // this notification is to show, that flow (unipi) has been restarted + sendNotification("modbus_reader", tbName, "flow_restart", {}, "", SEND_TO.slack, instance); + } + + instance.on("0", function(_) { + main(); + }) + +} + diff --git a/RVO45/flow_pred_verziou_2025_01_30/monitorconsumption.js b/RVO45/flow_pred_verziou_2025_01_30/monitorconsumption.js new file mode 100755 index 0000000..64cc58e --- /dev/null +++ b/RVO45/flow_pred_verziou_2025_01_30/monitorconsumption.js @@ -0,0 +1,156 @@ +exports.id = 'monitorconsumption'; +exports.title = 'Consumption'; +exports.version = '1.0.0'; +exports.author = 'Peter Širka'; +exports.group = 'Monitoring'; +exports.color = '#967ADC'; +exports.input = 0; +exports.output = 1; +exports.icon = 'bug'; +exports.options = { interval: 5000, enabled: true, monitorconsumption: true, monitorsize: true, monitorconnections: true, monitorfiles: true }; +exports.click = true; +exports.readme = `# Consumption monitoring + +This component measure CPU and memory consumption, open files and open connections of this application. It uses these Linux commands: \`ps\`, \`lsof\`, \`netstat\` and \`df\`. + +__Data Example__: + +\`\`\`javascript +{ + cpu: 0, // percentage + memory: 4096, // in bytes + size: 34303, // directory size in bytes + files: 34, // count of open files + connections: 343, // count of connections + uptime: '1-12:34:00' +} +\`\`\``; + +exports.html = `
+
+
+
@(Interval in milliseconds)
+
+
+
+
Monitor: Consumption + uptime
+
Monitor: Count of open files
+
Monitor: Count of open connections
+
Monitor: Directory size
+
`; + +exports.install = function(instance) { + + var current = { cpu: 0, memory: 0, files: 0, connections: 0, size: 0, uptime: '', counter: 0 }; + var tproc = null; + var Exec = require('child_process').exec; + var reg_empty = /\s{2,}/g; + var reg_appdisksize = /^[\d.,]+/; + + instance.custom.run = function() { + + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + + var arr = []; + + // Get CPU and Memory consumption + instance.options.monitorconsumption && arr.push(function(next) { + Exec('ps -p {0} -o %cpu,rss,etime'.format(process.pid), function(err, response) { + + if (err) { + instance.throw(err); + } else { + var line = response.split('\n')[1]; + line = line.trim().replace(reg_empty, ' ').split(' '); + var cpu = line[0].parseFloat(); + current.cpu = cpu.floor(1); + current.memory = line[1].parseInt2() * 1024; // kB to bytes + current.uptime = line[2]; + } + + next(); + }); + }); + + // Get count of open files + instance.options.monitorfiles && arr.push(function(next) { + Exec('lsof -a -p {0} | wc -l'.format(process.pid), function(err, response) { + if (err) + instance.throw(err); + else + current.files = response.trim().parseInt2(); + next(); + }); + }); + + // Get count of opened network connections + instance.options.monitorconnections && arr.push(function(next) { + Exec('netstat -an | grep :{0} | wc -l'.format(F.port), function(err, response) { + if (err) { + instance.throw(err); + } else { + current.connections = response.trim().parseInt2() - 1; + if (current.connections < 0) + current.connections = 0; + } + next(); + }); + }); + + // Get directory size + instance.options.monitorsize && current.counter % 5 !== 0 && arr.push(function(next) { + Exec('du -hsb ' + process.cwd(), function(err, response) { + if (err) { + instance.throw(err); + } else { + var match = response.trim().match(reg_appdisksize); + match && (current.size = match.toString().trim().parseInt2()); + } + next(); + }); + }); + + arr.async(function() { + + tproc && clearTimeout(tproc); + + if (instance.options.enabled) { + tproc = setTimeout(instance.custom.run, instance.options.interval); + instance.send2(current); + } + + instance.custom.status(); + current.counter++; + }); + }; + + instance.custom.status = function() { + if (instance.options.enabled) + instance.status('{0}% / {1}'.format(current.cpu, current.memory.filesize())); + else + instance.status('Disabled', 'red'); + }; + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + + if (instance.options.enabled) { + current.counter = 0; + instance.custom.run(); + } + + }); + + instance.on('close', function() { + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + }); + + setTimeout(instance.custom.run, 1000); +}; \ No newline at end of file diff --git a/RVO45/flow_pred_verziou_2025_01_30/monitordisk.js b/RVO45/flow_pred_verziou_2025_01_30/monitordisk.js new file mode 100755 index 0000000..f4fdaa0 --- /dev/null +++ b/RVO45/flow_pred_verziou_2025_01_30/monitordisk.js @@ -0,0 +1,96 @@ +exports.id = 'monitordisk'; +exports.title = 'Disk'; +exports.version = '1.0.0'; +exports.author = 'Peter Širka'; +exports.group = 'Monitoring'; +exports.color = '#F6BB42'; +exports.output = 1; +exports.icon = 'hdd-o'; +exports.click = true; +exports.options = { interval: 8000, path: '/', enabled: true }; +exports.readme = `# Disk monitoring + +This component monitors disk \`bytes\` consumption in Linux systems. It uses \`df\` command. + +__Data Example__: + +\`\`\`javascript +{ + total: 474549649408, + used: 39125245952, + free: 411294994432 +} +\`\`\``; + +exports.html = `
+
+
+
@(Interval in milliseconds)
+
+
+
@(Path)
+
+
+
`; + +exports.install = function(instance) { + + var current = { total: 0, used: 0, free: 0, path: '', type: '', percentUsed: 0 }; + var tproc = null; + + instance.custom.run = function() { + + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + + if (!instance.options.enabled) + return; + + require('child_process').exec('df -hTB1 ' + instance.options.path, function(err, response) { + + tproc = setTimeout(instance.custom.run, instance.options.interval); + + if (err) { + instance.error(err); + return; + } + + response.parseTerminal(function(line) { + if (line[0][0] !== '/') + return; + current.total = line[2].parseInt(); + current.free = line[4].parseInt(); + current.used = line[3].parseInt(); + current.path = instance.options.path || '/'; + current.type = line[1]; + current.percentUsed = line[5]; + instance.custom.status(); + instance.send2(current); + }); + }); + }; + + instance.custom.status = function() { + if (instance.options.enabled) + instance.status(current.free.filesize() + ' / ' + current.total.filesize()); + else + instance.status('Disabled', 'red'); + }; + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + instance.options.enabled && instance.custom.run(); + }); + + instance.on('close', function() { + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + }); + + setTimeout(instance.custom.run, 1000); +}; \ No newline at end of file diff --git a/RVO45/flow_pred_verziou_2025_01_30/monitormemory.js b/RVO45/flow_pred_verziou_2025_01_30/monitormemory.js new file mode 100755 index 0000000..2decbc4 --- /dev/null +++ b/RVO45/flow_pred_verziou_2025_01_30/monitormemory.js @@ -0,0 +1,87 @@ +exports.id = 'monitormemory'; +exports.title = 'Memory'; +exports.version = '1.0.0'; +exports.author = 'Peter Širka'; +exports.group = 'Monitoring'; +exports.color = '#F6BB42'; +exports.output = 1; +exports.click = true; +exports.icon = 'microchip'; +exports.options = { interval: 8000, enabled: true }; +exports.readme = `# Memory monitoring + +This component monitors memory \`bytes\` consumption in Linux systems. It uses \`free\` command. + +__Data Example__: + +\`\`\`javascript +{ + total: 33558769664, + used: 1998868480, + free: 2653708288 +} +\`\`\``; + +exports.html = `
+
+
+
@(Interval in milliseconds)
+
+
+
`; + +exports.install = function(instance) { + + var current = { total: 0, used: 0, free: 0 }; + var tproc = null; + + instance.custom.run = function() { + + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + + if (!instance.options.enabled) + return; + + require('child_process').exec('free -b -t', function(err, response) { + + tproc = setTimeout(instance.custom.run, instance.options.interval); + + if (err) { + instance.error(err); + return; + } + + var memory = response.split('\n')[1].match(/\d+/g); + current.total = memory[0].parseInt(); + current.used = memory[1].parseInt() - memory[3].parseInt(); + current.free = current.total - current.used; + instance.custom.status(); + instance.send2(current); + }); + }; + + instance.custom.status = function() { + if (instance.options.enabled) + instance.status(current.free.filesize() + ' / ' + current.total.filesize()); + else + instance.status('Disabled', 'red'); + }; + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + instance.options.enabled && instance.custom.run(); + }); + + instance.on('close', function() { + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + }); + + setTimeout(instance.custom.run, 1000); +}; \ No newline at end of file diff --git a/RVO45/flow_pred_verziou_2025_01_30/nodesdb_changecheck.js b/RVO45/flow_pred_verziou_2025_01_30/nodesdb_changecheck.js new file mode 100755 index 0000000..be1e700 --- /dev/null +++ b/RVO45/flow_pred_verziou_2025_01_30/nodesdb_changecheck.js @@ -0,0 +1,70 @@ +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/RVO45/flow_pred_verziou_2025_01_30/show_dbdata.js b/RVO45/flow_pred_verziou_2025_01_30/show_dbdata.js new file mode 100755 index 0000000..d01eecd --- /dev/null +++ b/RVO45/flow_pred_verziou_2025_01_30/show_dbdata.js @@ -0,0 +1,241 @@ +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 = 7; +exports.output = 1; + +const { exec } = require('child_process'); + +exports.install = 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}) + }) + instance.on("5", _ => { + exec("sudo tail -n 25 monitor.txt" , (err, stdout, stderr) => { + if (err || stderr) instance.send(0,{err, stderr}); + else instance.send(0,stdout); + }) + }) + instance.on("6", _ => { + exec("sudo tail -n 25 err.txt" , (err, stdout, stderr) => { + if (err || stderr) instance.send(0,{err, stderr}); + else instance.send(0,stdout); + }) + }) +}; + + + +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/RVO45/flow_pred_verziou_2025_01_30/slack_filter.js b/RVO45/flow_pred_verziou_2025_01_30/slack_filter.js new file mode 100755 index 0000000..753c24a --- /dev/null +++ b/RVO45/flow_pred_verziou_2025_01_30/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 = `
+
+
+
@(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"] = []; + } + + instance.options.name = FLOW.GLOBALS.settings.rvo_name; + if (instance.options.name) { + instance.status('Running'); + running = true; + } else { + instance.status('Please run options again', 'red'); + running = false; + } + } catch (e) { + instance.error('Citysys connector: ' + e.message); + } + }; + + instance.on('options', instance.reconfigure); + setTimeout(instance.reconfigure, 10000); + + +}; diff --git a/RVO45/flow_pred_verziou_2025_01_30/thermometer.js b/RVO45/flow_pred_verziou_2025_01_30/thermometer.js new file mode 100755 index 0000000..fa015c6 --- /dev/null +++ b/RVO45/flow_pred_verziou_2025_01_30/thermometer.js @@ -0,0 +1,98 @@ +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 = 5;//minutes +let NUMBER_OF_FAILURES_TO_SEND_ERROR = 13; + +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) => { + + 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); + setTimeout(main, 20000); + }) +}; diff --git a/RVO45/flow_pred_verziou_2025_01_30/trigger.js b/RVO45/flow_pred_verziou_2025_01_30/trigger.js new file mode 100755 index 0000000..27545a8 --- /dev/null +++ b/RVO45/flow_pred_verziou_2025_01_30/trigger.js @@ -0,0 +1,79 @@ +exports.id = 'trigger'; +exports.title = 'Trigger'; +exports.group = 'Inputs'; +exports.color = '#F6BB42'; +exports.click = true; +exports.output = 1; +exports.version = '1.1.0'; +exports.author = 'Martin Smola'; +exports.icon = 'play'; + +exports.html = `
+
@(Data type (String by default))
+
@(Data)
+
Trigger 5s after initialization.
+
@(Useful when there's a need to run certain flow when the app restarts, etc.)
+
`; + +exports.readme = `# Trigger + +- Clicking on the component starts the chain +- Settings allows to set a data-type and a value`; + +exports.install = function(instance) { + + var value; + + instance.on('click', () => instance.send2(value)); + + instance.reconfigure = function() { + var options = instance.options; + value = null; + switch (options.datatype) { + case 'integer': + value = options.data.parseInt2('error'); + value = value === 'error' ? NaN : value; + break; + case 'float': + value = options.data.parseFloat2('error'); + value = value === 'error' ? NaN : value; + break; + case 'date': + options.data = options.data.toString(); + var num = options.data.parseInt('error'); + num === 'error' && (num = options.data.parseDate('error')); + num === 'error' && (num = null); + value = num ? new Date(num).toUTCString() : num; + break; + case 'object': + try { + value = (new Function('return ' + options.data))(); + } catch (e) { + instance.error(e); + } + break; + case 'boolean': + value = options.data.parseBoolean(); + break; + case 'buffer': + try { + value = U.createBuffer(options.data); + } catch (e) { + instance.error(e); + } + break; + case 'string': + default: + value = '' + (options.data || ''); + break; + } + }; + + instance.on('options', instance.reconfigure); + instance.reconfigure(); + + if (instance.options.restart) + setTimeout(function(){ + instance.send2(value); + }, 5000); +}; diff --git a/RVO45/flow_pred_verziou_2025_01_30/variables.txt b/RVO45/flow_pred_verziou_2025_01_30/variables.txt new file mode 100755 index 0000000..e69de29 diff --git a/RVO45/flow_pred_verziou_2025_01_30/virtualwirein.js b/RVO45/flow_pred_verziou_2025_01_30/virtualwirein.js new file mode 100755 index 0000000..38a4e42 --- /dev/null +++ b/RVO45/flow_pred_verziou_2025_01_30/virtualwirein.js @@ -0,0 +1,43 @@ +exports.id = 'virtualwirein'; +exports.title = 'Virtual wire in'; +exports.version = '1.0.0'; +exports.author = 'Martin Smola'; +exports.color = '#303E4D'; +exports.icon = 'sign-in'; +exports.input = false; +exports.output = 1; +exports.options = {}; +exports.readme = `# Virtual wire in + +When the wires between the components are mess it's time to use Virtual wire.`; + +exports.html = `
+
@(Wire name)
+
+`; + +exports.install = function(instance) { + + instance.custom.reconfigure = function(options){ + if (instance.options.wirename) { + instance.status(instance.options.wirename); + } else + instance.status('Not configured', 'red'); + }; + + ON('virtualwire', function(wirename, flowdata){ + if (instance.options.wirename && instance.options.wirename === wirename) + instance.send(flowdata); + }); + + instance.on('options', instance.custom.reconfigure); + instance.custom.reconfigure(); +}; diff --git a/RVO45/flow_pred_verziou_2025_01_30/virtualwireout.js b/RVO45/flow_pred_verziou_2025_01_30/virtualwireout.js new file mode 100755 index 0000000..94a1e4f --- /dev/null +++ b/RVO45/flow_pred_verziou_2025_01_30/virtualwireout.js @@ -0,0 +1,41 @@ +exports.id = 'virtualwireout'; +exports.title = 'Virtual wire out'; +exports.version = '1.0.0'; +exports.author = 'Martin Smola'; +exports.color = '#303E4D'; +exports.icon = 'sign-out'; +exports.input = true; +exports.options = {}; +exports.readme = `# Virtual wire out + +When the wires between the components are mess it's time to use Virtual wire.`; + +exports.html = `
+
@(Wire name)
+
+`; + +exports.install = function(instance) { + + instance.custom.reconfigure = function(){ + if (instance.options.wirename) { + instance.status(instance.options.wirename); + } else + instance.status('Not configured', 'red'); + }; + + instance.on('data', function(flowdata) { + EMIT('virtualwire', instance.options.wirename, flowdata); + }); + + instance.on('options', instance.custom.reconfigure); + instance.custom.reconfigure(); +}; diff --git a/RVO45/flow_pred_verziou_2025_01_30/wsmqttpublish.js b/RVO45/flow_pred_verziou_2025_01_30/wsmqttpublish.js new file mode 100755 index 0000000..b2a218d --- /dev/null +++ b/RVO45/flow_pred_verziou_2025_01_30/wsmqttpublish.js @@ -0,0 +1,477 @@ +exports.id = 'wsmqttpublish'; +exports.title = 'WS MQTT publish'; +exports.group = 'MQTT'; +exports.color = '#888600'; +exports.version = '1.0.2'; +exports.icon = 'sign-out'; +exports.input = 2; +exports.output = 3; +exports.options = { host: 'tb-stage.worksys.io', port: 1883, clientid: "", username: "" }; + +exports.html = `
+
+
+
Hostname or IP address (if not empty - setting will override db setting)
+
+
+
Port
+
+
+
+
+
@(Client id)
+
+
+
@(Username)
+
+
+
`; + + +exports.readme = ` +# WS MQTT Publish + +Version 1.0.3. + +Added: +- database collections, +- 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 = { + debug: 0, + rpcCall: 1, + services: 2 +} + +//CONFIG +let createTelemetryBackup = true; +let saveTelemetryOnError = true;//backup_on_failure overrides this value +//------------------------ + +let rollers; +if(createTelemetryBackup) rollers = require('streamroller'); + +const noSqlFileSizeLimit = 4194304;//use 5MB - 4194304 +let insertNoSqlCounter = 0; +let insertBackupNoSqlCounter = 0; +let processingData = false; + +let backup_on_failure = false;//== saveTelemetryOnError - create backup client 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; + +process.on('uncaughtException', function (err) { + + errLogger.error('uncaughtException:', err.message) + errLogger.error(err.stack); + + //TODO + //send to service + + //process.exit(1); +}) + +const nosql = NOSQL('tbdata'); +const nosqlBackup = NOSQL('/backup/tbdata'); + + +exports.install = function(instance) { + + var client; + var opts; + var clientReady = false; + + // wsmqtt status for notification purposes on projects.worksys.io database + let wsmqttName = null; + let sendWsStatusVar = null; + let wsmqtt_status = 'disconnected'; + + 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'; + } + + function sendWsStatus() + { + instance.send(SEND_TO.services, {[wsmqttName]: wsmqtt_status}); + } + + + function main() + { + if(!FLOW.dbLoaded) return; + + loadSettings(); + clearInterval(sendWsStatus); + sendWsStatusVar = setInterval(sendWsStatus, 180000); + } + + //set opts according to db settings + function loadSettings() + { + + if(instance.options.host !== "") + { + //override settings from database + var o = instance.options; + opts = { + host: o.host, + port: o.port, + clientId: o.clientid, + username: o.username, + rejectUnauthorized: false, + resubscribe: false + }; + + wsmqttName = getWsmqttName(o.host); + + console.log("wsmqttpublich -> loadSettings from instance.options", instance.options); + } + else + { + + const SETTINGS = FLOW.GLOBALS.settings; + backup_on_failure = SETTINGS.backup_on_failure; + saveTelemetryOnError = backup_on_failure; + + restore_from_backup = SETTINGS.restore_from_backup; + restore_backup_wait = SETTINGS.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; + + opts = { + host: mqtt_host, + port: mqtt_port, + keepalive: 10, + clientId: mqtt_clientid, + username: mqtt_username, + rejectUnauthorized: false, + resubscribe: false + }; + + wsmqttName = getWsmqttName(mqtt_host); + } + + connectToTbServer(); + } + + function connectToTbServer() + { + 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"); + monitor.info("MQTT client connected"); + + sendClientError = true; + clientReady = true; + wsmqtt_status = 'connected'; + }); + + client.on('reconnect', function() { + instance.status("Reconnecting", "yellow"); + clientReady = false; + }); + + client.on('message', function(topic, message) { + // message is type of buffer + message = message.toString(); + if (message[0] === '{') { + TRY(function() { + + message = JSON.parse(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}}); + } + + }, () => instance.debug('MQTT: Error parsing data', message)); + } + + instance.send(SEND_TO.rpcCall, {"topic":topic, "content":message }); + }); + + client.on('close', function() { + clientReady = false; + wsmqtt_status = 'disconnected'; + + instance.status("Disconnected", "red"); + instance.send(SEND_TO.debug, {"message":"Client CLOSE signal received !"}); + }); + + client.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; + wsmqtt_status = 'disconnected'; + }); + + } + + + instance.on("0", _ => { + main(); + }) + + + instance.on('1', function(data) { + + if(clientReady) + { + //do we have some data in backup file? if any, process data from database + if(saveTelemetryOnError) + { + //read telemetry data and send back to server + if(!processingData) processDataFromDatabase(); + } + + let stringifiedJson = JSON.stringify(data.data); + client.publish("v1/gateway/telemetry", stringifiedJson, {qos: 1}); + + //backup telemetry + if(createTelemetryBackup) + { + data.data.id = UID(); + nosqlBackup.insert(data.data); + + insertBackupNoSqlCounter++; + if(insertBackupNoSqlCounter > 150) + { + let options = {compress: true}; + let path = __dirname + "/../databases/backup/tbdata.nosql"; + var stream = new rollers.RollingFileStream(path, noSqlFileSizeLimit, 150, options); + stream.write(""); + stream.end(); + + insertBackupNoSqlCounter = 0; + } + } + + } + 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(saveTelemetryOnError) + { + //create new file from tbdata.nosql, if file size exceeds given limit, and clear tbdata.nosql + makeBackupFromDbFile(); + + //write to tb + data.data.id = UID(); + nosql.insert(data.data); + } + } + }); + + + instance.close = function(done) { + if(clientReady){ + client.end(); + clearInterval(sendWsStatusVar); + } + }; + + + function getDbBackupFileCounter(type) + { + var files = fs.readdirSync(__dirname + "/../databases"); + + let counter = 0; + for(var i = 0; i < files.length; i++) + { + + if(files[i] == "tbdata.nosql") continue; + + if(files[i].endsWith(".nosql")) + { + + let pos = files[i].indexOf("."); + if(pos > -1) + { + + let fileCounter = counter; + let firstDigit = files[i].slice(0, pos); + + fileCounter = parseInt(firstDigit); + if(isNaN(fileCounter)) fileCounter = 0; + //console.log("getDbBackupFileCounter digit:", files[i], firstDigit, fileCounter, isNaN(fileCounter), type); + + if(type == "max") + { + if(fileCounter > counter) + { + counter = fileCounter; + } + } + else if(type == "min") + { + if(counter == 0) counter = fileCounter; + + if(fileCounter < counter) + { + counter = fileCounter; + } + } + } + } + + } + + if(type == "max") counter++; + + return counter; + } + + const makeBackupFromDbFile = async () => { + + if(!saveTelemetryOnError) return; + + //to avoid large file: tbdata.nosql + + //init value is 0! + if(insertNoSqlCounter > 0) + { + --insertNoSqlCounter; + return; + } + + insertNoSqlCounter = 100; + + let source = __dirname + "/../databases/tbdata.nosql"; + + var stats = fs.statSync(source); + var fileSizeInBytes = stats.size; + + if(fileSizeInBytes > noSqlFileSizeLimit) + { + + let counter = 1; + counter = getDbBackupFileCounter("max"); + + let destination = __dirname + "/../databases/" + counter + "." + "tbdata.nosql"; + + //make backup file + fs.copyFileSync(source, destination); + //fs.renameSync(p, p + "." + counter); + + //clear tbdata.nosql + fs.writeFileSync(source, ""); + fs.truncateSync(source, 0); + + } + } + + const processDataFromDatabase = async () => { + + if(restore_from_backup <= 0) return; + + //calculate diff + const now = new Date(); + let currentTime = now.getTime(); + let diff = currentTime - lastRestoreTime; + + if( (diff / 1000) < restore_backup_wait) + { + //console.log("*********restore_backup_wait", diff, restore_backup_wait); + return; + } + + processingData = true; + + //get filename to process + let counter = getDbBackupFileCounter("min"); + + //we have some backup files + let dataBase = 'tbdata'; + + var nosql; + if(counter == 0) dataBase = 'tbdata'; + else dataBase = counter + "." + 'tbdata'; + + nosql = NOSQL(dataBase); + + //select all data - use limit restore_from_backup + let records = await promisifyBuilder(nosql.find().take(restore_from_backup)); + + for(let i = 0; i < records.length; i++) + { + if(clientReady) { + + let item = records[i]; + let id = item.id; + + if(id !== undefined) + { + //console.log("------------processDataFromDatabase - remove", id, dataBase, i); + + try { + + let message = JSON.parse(JSON.stringify(item)); + delete message.id; + + client.publish("v1/gateway/telemetry", JSON.stringify(message), {qos:1}); + + //remove from database + await promisifyBuilder(nosql.remove().where("id", id)); + + } catch(error) { + //process error + console.log("processDataFromDatabase", error); + } + + } + + } + else + { + processingData = false; + return; + } + } + + if(records.length > 0) + { + //clean backup file + if(counter > 0) nosql.clean(); + } + + //no data in db, remove + if(records.length == 0) + { + if(counter > 0) nosql.drop(); + } + + const d = new Date(); + lastRestoreTime = d.getTime(); + + processingData = false; + + } + + instance.on('options', main); + //instance.reconfigure(); +}; diff --git a/RVO45/monitor.txt b/RVO45/monitor.txt new file mode 100755 index 0000000..fb49ab2 --- /dev/null +++ b/RVO45/monitor.txt @@ -0,0 +1,494 @@ +[2025-10-09T16:49:27.871] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-09T16:49:33.225] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-09T16:49:33.230] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-09T16:49:33.231] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-09T16:49:33.232] [INFO] monitorLogs - profile: { + 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: 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 +} +[2025-10-09T16:49:33.236] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T16:49:33.238] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-10-10T05:32:00.237Z +[2025-10-09T16:49:33.239] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-10-09T16:45:00.239Z +[2025-10-09T16:49:33.240] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T16:49:33.241] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-10-09T16:49:33.242] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-09T16:49:33.242] [INFO] monitorLogs - profile: { + 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: 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 +} +[2025-10-09T16:49:33.245] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T16:49:33.245] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-10-10T05:32:00.245Z +[2025-10-09T16:49:33.246] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-10-09T16:45:00.246Z +[2025-10-09T16:49:33.247] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T16:49:33.248] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-10-09T16:49:33.249] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-09T16:49:33.249] [INFO] monitorLogs - profile: { + 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: 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 +} +[2025-10-09T16:49:33.252] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T16:49:33.252] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-10-10T05:32:00.252Z +[2025-10-09T16:49:33.253] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-10-09T16:45:00.253Z +[2025-10-09T16:49:33.254] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T16:49:33.255] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-10-09T16:49:33.255] [INFO] monitorLogs - buildTasks: profile for line 4 +[2025-10-09T16:49:33.256] [INFO] monitorLogs - profile: { + 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: 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 +} +[2025-10-09T16:49:33.258] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T16:49:33.259] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 4 2025-10-10T05:32:00.259Z +[2025-10-09T16:49:33.260] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 4 2025-10-09T16:45:00.260Z +[2025-10-09T16:49:33.260] [INFO] monitorLogs - -->time_points final 4 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T16:49:33.262] [INFO] monitorLogs - -->currentValue for relay 4 0 +[2025-10-09T16:49:33.262] [INFO] monitorLogs - buildTasks: profile for line 5 +[2025-10-09T16:49:33.263] [INFO] monitorLogs - profile: { + 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: 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 +} +[2025-10-09T16:49:33.265] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T16:49:33.266] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 5 2025-10-10T05:32:00.266Z +[2025-10-09T16:49:33.267] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 5 2025-10-09T16:45:00.267Z +[2025-10-09T16:49:33.268] [INFO] monitorLogs - -->time_points final 5 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T16:49:33.269] [INFO] monitorLogs - -->currentValue for relay 5 0 +[2025-10-09T16:49:33.290] [INFO] monitorLogs - tasks created: 636 +[2025-10-09T16:49:33.293] [INFO] monitorLogs - -->FLOW bol spustený JX1ObgmqGZ54DMyYL7aDzmkEVdve38WKRzwjNrQ9 2025-08-08 +[2025-10-09T16:49:38.299] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-09T18:32:59.855] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-09T18:32:59.858] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-09T18:32:59.860] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-09T18:32:59.863] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-10-09T18:32:59.865] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-10-09T19:01:33.646] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-09T19:01:38.995] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-09T19:01:39.000] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-09T19:01:39.001] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-09T19:01:39.001] [INFO] monitorLogs - profile: { + 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: 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 +} +[2025-10-09T19:01:39.006] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T19:01:39.007] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-10-10T05:32:00.006Z +[2025-10-09T19:01:39.008] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-10-10T16:45:00.008Z +[2025-10-09T19:01:39.009] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T19:01:39.010] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-10-09T19:01:39.011] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-09T19:01:39.012] [INFO] monitorLogs - profile: { + 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: 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 +} +[2025-10-09T19:01:39.015] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T19:01:39.016] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-10-10T05:32:00.016Z +[2025-10-09T19:01:39.017] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-10-10T16:45:00.017Z +[2025-10-09T19:01:39.018] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T19:01:39.019] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-10-09T19:01:39.020] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-09T19:01:39.020] [INFO] monitorLogs - profile: { + 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: 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 +} +[2025-10-09T19:01:39.022] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T19:01:39.023] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-10-10T05:32:00.023Z +[2025-10-09T19:01:39.024] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-10-10T16:45:00.024Z +[2025-10-09T19:01:39.025] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T19:01:39.026] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-10-09T19:01:39.026] [INFO] monitorLogs - buildTasks: profile for line 4 +[2025-10-09T19:01:39.027] [INFO] monitorLogs - profile: { + 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: 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 +} +[2025-10-09T19:01:39.029] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T19:01:39.030] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 4 2025-10-10T05:32:00.030Z +[2025-10-09T19:01:39.031] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 4 2025-10-10T16:45:00.030Z +[2025-10-09T19:01:39.031] [INFO] monitorLogs - -->time_points final 4 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T19:01:39.032] [INFO] monitorLogs - -->currentValue for relay 4 1 +[2025-10-09T19:01:39.033] [INFO] monitorLogs - buildTasks: profile for line 5 +[2025-10-09T19:01:39.034] [INFO] monitorLogs - profile: { + 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: 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 +} +[2025-10-09T19:01:39.036] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T19:01:39.036] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 5 2025-10-10T05:32:00.036Z +[2025-10-09T19:01:39.037] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 5 2025-10-10T16:45:00.037Z +[2025-10-09T19:01:39.038] [INFO] monitorLogs - -->time_points final 5 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T19:01:39.039] [INFO] monitorLogs - -->currentValue for relay 5 1 +[2025-10-09T19:01:39.060] [INFO] monitorLogs - tasks created: 636 +[2025-10-09T19:01:39.062] [INFO] monitorLogs - -->FLOW bol spustený JX1ObgmqGZ54DMyYL7aDzmkEVdve38WKRzwjNrQ9 2025-08-08 +[2025-10-09T19:01:44.069] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-10T03:01:40.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-10 03:01:40 +[2025-10-10T06:41:25.964] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-10T06:41:25.968] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-10T06:41:25.970] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-10T06:41:25.972] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-10-10T06:41:25.974] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-10-10T18:26:33.874] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-10T18:26:33.877] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-10T18:26:33.879] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-10T18:26:33.881] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-10-10T18:26:33.883] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-10-11T03:01:42.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-11 03:01:42 +[2025-10-11T06:41:00.102] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-11T06:41:00.108] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-11T06:41:00.110] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-11T06:41:00.112] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-10-11T06:41:00.114] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-10-11T18:30:41.079] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-11T18:30:41.081] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-11T18:30:41.083] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-11T18:30:41.085] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-10-11T18:30:41.087] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-10-12T03:01:43.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-12 03:01:43 +[2025-10-12T06:39:28.932] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-12T06:39:28.939] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-12T06:39:28.941] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-12T06:39:28.943] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-10-12T06:39:28.944] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-10-12T18:28:37.289] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-12T18:28:37.295] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-12T18:28:37.297] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-12T18:28:37.299] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-10-12T18:28:37.301] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-10-13T03:01:44.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-13 03:01:44 +[2025-10-13T06:40:15.685] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-13T06:40:15.690] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-13T06:40:15.693] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-13T06:40:15.695] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-10-13T06:40:15.697] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-10-13T18:32:24.134] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-13T18:32:24.140] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-13T18:32:24.142] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-13T18:32:24.144] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-10-13T18:32:24.146] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-10-14T03:01:46.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-14 03:01:46 +[2025-10-14T06:42:05.116] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-14T06:42:05.119] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-14T06:42:05.121] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-14T06:42:05.123] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-10-14T06:42:05.125] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-10-14T18:22:39.695] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-14T18:22:39.698] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-14T18:22:39.700] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-14T18:22:39.702] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-10-14T18:22:39.704] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor +[2025-10-15T03:01:47.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-15 03:01:47 +[2025-10-15T06:44:04.368] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-15T06:44:04.371] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-15T06:44:04.373] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-15T06:44:04.375] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 4 relay1_05 false Profile: dawn - turnOff line according to lux sensor +[2025-10-15T06:44:04.378] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 5 relay1_06 false Profile: dawn - turnOff line according to lux sensor +[2025-10-15T14:23:00.138] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-15T14:23:05.494] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-15T14:23:05.500] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-15T14:23:05.501] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-15T14:23:05.502] [INFO] monitorLogs - profile: { + 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: 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 +} +[2025-10-15T14:23:05.506] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-15T14:23:05.507] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-10-16T05:41:00.507Z +[2025-10-15T14:23:05.509] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-10-15T16:33:00.509Z +[2025-10-15T14:23:05.510] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:41', name: 'luxOff' }, + { value: 1, start_time: '18:33', name: 'luxOn' } +] +[2025-10-15T14:23:05.511] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-10-15T14:23:05.512] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-15T14:23:05.512] [INFO] monitorLogs - profile: { + 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: 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 +} +[2025-10-15T14:23:05.515] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-15T14:23:05.515] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-10-16T05:41:00.515Z +[2025-10-15T14:23:05.516] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-10-15T16:33:00.516Z +[2025-10-15T14:23:05.517] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:41', name: 'luxOff' }, + { value: 1, start_time: '18:33', name: 'luxOn' } +] +[2025-10-15T14:23:05.518] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-10-15T14:23:05.519] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-15T14:23:05.519] [INFO] monitorLogs - profile: { + 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: 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 +} +[2025-10-15T14:23:05.521] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-15T14:23:05.522] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-10-16T05:41:00.522Z +[2025-10-15T14:23:05.523] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-10-15T16:33:00.523Z +[2025-10-15T14:23:05.523] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:41', name: 'luxOff' }, + { value: 1, start_time: '18:33', name: 'luxOn' } +] +[2025-10-15T14:23:05.524] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-10-15T14:23:05.525] [INFO] monitorLogs - buildTasks: profile for line 4 +[2025-10-15T14:23:05.526] [INFO] monitorLogs - profile: { + 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: 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 +} +[2025-10-15T14:23:05.528] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-15T14:23:05.529] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 4 2025-10-16T05:41:00.529Z +[2025-10-15T14:23:05.530] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 4 2025-10-15T16:33:00.529Z +[2025-10-15T14:23:05.530] [INFO] monitorLogs - -->time_points final 4 [ + { value: 0, start_time: '7:41', name: 'luxOff' }, + { value: 1, start_time: '18:33', name: 'luxOn' } +] +[2025-10-15T14:23:05.531] [INFO] monitorLogs - -->currentValue for relay 4 0 +[2025-10-15T14:23:05.532] [INFO] monitorLogs - buildTasks: profile for line 5 +[2025-10-15T14:23:05.532] [INFO] monitorLogs - profile: { + 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: 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 +} +[2025-10-15T14:23:05.535] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-15T14:23:05.535] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 5 2025-10-16T05:41:00.535Z +[2025-10-15T14:23:05.536] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 5 2025-10-15T16:33:00.536Z +[2025-10-15T14:23:05.537] [INFO] monitorLogs - -->time_points final 5 [ + { value: 0, start_time: '7:41', name: 'luxOff' }, + { value: 1, start_time: '18:33', name: 'luxOn' } +] +[2025-10-15T14:23:05.538] [INFO] monitorLogs - -->currentValue for relay 5 0 +[2025-10-15T14:23:05.559] [INFO] monitorLogs - tasks created: 636 +[2025-10-15T14:23:05.561] [INFO] monitorLogs - -->FLOW bol spustený JX1ObgmqGZ54DMyYL7aDzmkEVdve38WKRzwjNrQ9 2025-10-08 +[2025-10-15T14:23:10.567] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-15T18:23:15.737] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-15T18:23:15.745] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-15T18:23:15.748] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-15T18:23:15.750] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 4 relay1_05 false Profile: dusk - turnOn line according to lux sensor +[2025-10-15T18:23:15.753] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 5 relay1_06 false Profile: dusk - turnOn line according to lux sensor diff --git a/RVO45/package-lock.json b/RVO45/package-lock.json new file mode 100755 index 0000000..cc5cfd9 --- /dev/null +++ b/RVO45/package-lock.json @@ -0,0 +1,2125 @@ +{ + "name": "emptyproject", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "emptyproject", + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "bitwise": "^2.1.0", + "easy-crc": "0.0.2", + "jsmodbus": "^4.0.6", + "log4js": "^6.3.0", + "mqtt": "^4.2.6", + "nodemailer": "^6.9.7", + "serialport": "^9.2.8", + "total.js": "^3.4.13" + } + }, + "node_modules/@serialport/binding-abstract": { + "version": "9.2.3", + "resolved": "https://registry.npmjs.org/@serialport/binding-abstract/-/binding-abstract-9.2.3.tgz", + "integrity": "sha512-cQs9tbIlG3P0IrOWyVirqlhWuJ7Ms2Zh9m2108z6Y5UW/iVj6wEOiW8EmK9QX9jmJXYllE7wgGgvVozP5oCj3w==", + "dependencies": { + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/binding-mock": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/binding-mock/-/binding-mock-9.2.4.tgz", + "integrity": "sha512-dpEhACCs44oQhh6ajJfJdvQdK38Vq0N4W6iD/gdplglDCK7qXRQCMUjJIeKdS/HSEiWkC3bwumUhUufdsOyT4g==", + "dependencies": { + "@serialport/binding-abstract": "9.2.3", + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/bindings": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/@serialport/bindings/-/bindings-9.2.8.tgz", + "integrity": "sha512-hSLxTe0tADZ3LMMGwvEJWOC/TaFQTyPeFalUCsJ1lSQ0k6bPF04JwrtB/C81GetmDBTNRY0GlD0SNtKCc7Dr5g==", + "hasInstallScript": true, + "dependencies": { + "@serialport/binding-abstract": "9.2.3", + "@serialport/parser-readline": "9.2.4", + "bindings": "^1.5.0", + "debug": "^4.3.2", + "nan": "^2.15.0", + "prebuild-install": "^7.0.0" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-byte-length": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-byte-length/-/parser-byte-length-9.2.4.tgz", + "integrity": "sha512-sQD/iw4ZMU3xW9PLi0/GlvU6Y623jGeWecbMkO7izUo/6P7gtfv1c9ikd5h0kwL8AoAOpQA1lxdHIKox+umBUg==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-cctalk": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-cctalk/-/parser-cctalk-9.2.4.tgz", + "integrity": "sha512-T4TU5vQMwmo9AB3gQLFDWbfJXlW5jd9guEsB/nqKjFHTv0FXPdZ7DQ2TpSp8RnHWxU3GX6kYTaDO20BKzc8GPQ==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-delimiter": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-delimiter/-/parser-delimiter-9.2.4.tgz", + "integrity": "sha512-4nvTAoYAgkxFiXrkI+3CA49Yd43CODjeszh89EK+I9c8wOZ+etZduRCzINYPiy26g7zO+GRAb9FoPCsY+sYcbQ==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-inter-byte-timeout": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-inter-byte-timeout/-/parser-inter-byte-timeout-9.2.4.tgz", + "integrity": "sha512-SOAdvr0oBQIOCXX198hiTlxs4JTKg9j5piapw5tNq52fwDOWdbYrFneT/wN04UTMKaDrJuEvXq6T4rv4j7nJ5A==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-readline": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-readline/-/parser-readline-9.2.4.tgz", + "integrity": "sha512-Z1/qrZTQUVhNSJP1hd9YfDvq0o7d87rNwAjjRKbVpa7Qi51tG5BnKt43IV3NFMyBlVcRe0rnIb3tJu57E0SOwg==", + "dependencies": { + "@serialport/parser-delimiter": "9.2.4" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-ready": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-ready/-/parser-ready-9.2.4.tgz", + "integrity": "sha512-Pyi94Itjl6qAURwIZr/gmZpMAyTmKXThm6vL5DoAWGQjcRHWB0gwv2TY2v7N+mQLJYUKU3cMnvnATXxHm7xjxw==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-regex": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-regex/-/parser-regex-9.2.4.tgz", + "integrity": "sha512-sI/cVvPOYz+Dbv4ZdnW16qAwvXiFf/1pGASQdbveRTlgJDdz7sRNlCBifzfTN2xljwvCTZYqiudKvDdC1TepRQ==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/stream": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/stream/-/stream-9.2.4.tgz", + "integrity": "sha512-bLye8Ub4vUFQGmkh8qEqehr7SE7EJs2yDs0h9jzuL5oKi+F34CFmWkEErO8GAOQ8YNn7p6b3GxUgs+0BrHHDZQ==", + "dependencies": { + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "node_modules/are-we-there-yet": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", + "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/base64-js": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", + "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==" + }, + "node_modules/bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "dependencies": { + "file-uri-to-path": "1.0.0" + } + }, + "node_modules/bitwise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/bitwise/-/bitwise-2.1.0.tgz", + "integrity": "sha512-XKgAhMXCh4H/3oNwAHAsAO0iC89s9cOiumgYwSHjSobGWxYjv62YhkL9QEdvGP151xypCtMlAfKK79GEcd2eRQ==" + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/bl/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/buffer": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz", + "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==", + "dependencies": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + }, + "node_modules/buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" + }, + "node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, + "node_modules/code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/commist": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/commist/-/commist-1.1.0.tgz", + "integrity": "sha512-rraC8NXWOEjhADbZe9QBNzLAN5Q3fsTPQtBV+fEVj6xKIgDgNiEVE6ZNfHpZOqfQ21YUzfVNUXLOEZquYvQPPg==", + "dependencies": { + "leven": "^2.1.0", + "minimist": "^1.1.0" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "node_modules/concat-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", + "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", + "engines": [ + "node >= 6.0" + ], + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.0.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/concat-stream/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" + }, + "node_modules/core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "node_modules/crc": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/crc/-/crc-3.4.0.tgz", + "integrity": "sha512-ycVC2+4/DLgXXq7QweYi2znhqDuZz6P5TQXnkQo8v15XY/5p/IWeZwsSE31Ifo8w15b8TWLsqhXOjXyilHuQxw==" + }, + "node_modules/date-format": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.11.tgz", + "integrity": "sha512-VS20KRyorrbMCQmpdl2hg5KaOUsda1RbnsJg461FfrcyCUg+pkd0b40BSW4niQyTheww4DBXQnS7HwSrKkipLw==", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" + }, + "node_modules/detect-libc": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz", + "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==", + "engines": { + "node": ">=8" + } + }, + "node_modules/duplexify": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.2.tgz", + "integrity": "sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw==", + "dependencies": { + "end-of-stream": "^1.4.1", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1", + "stream-shift": "^1.0.0" + } + }, + "node_modules/duplexify/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/easy-crc": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/easy-crc/-/easy-crc-0.0.2.tgz", + "integrity": "sha512-h6eqIdhJRe0p271/xZJbM/0klCi13mW5IB7ZEzEGH11yV4QXWAkD4yPErz0fXdhFrd6sZ4Q1k5Iky2kMsMNePw==" + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" + }, + "node_modules/flatted": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", + "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==" + }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, + "node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "node_modules/gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha512-14x4kjc6lkD3ltw589k0NrPD6cCNTD6CWoVUNpB85+DrtONoZn+Rug6xZU5RvSC4+TZPxA5AnBibQYAvZn41Hg==", + "dependencies": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "node_modules/github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==" + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" + }, + "node_modules/has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" + }, + "node_modules/help-me": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/help-me/-/help-me-3.0.0.tgz", + "integrity": "sha512-hx73jClhyk910sidBB7ERlnhMlFsJJIBqSVMFDwPN8o2v9nmp5KgLq1Xz1Bf1fCMMZ6mPrX159iG0VLy/fPMtQ==", + "dependencies": { + "glob": "^7.1.6", + "readable-stream": "^3.6.0" + } + }, + "node_modules/help-me/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, + "node_modules/is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==", + "dependencies": { + "number-is-nan": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "node_modules/js-sdsl": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz", + "integrity": "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/js-sdsl" + } + }, + "node_modules/jsmodbus": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/jsmodbus/-/jsmodbus-4.0.6.tgz", + "integrity": "sha512-gCmjoaERErK5Rn9Lu/BN07fY13MoWV7JKgGzrnkPlQPdPxYcwDhLtYcmpFFpZ4J9NPZZBSezi1UkLZO/DnNppA==", + "dependencies": { + "crc": "3.4.0", + "debug": "^3.1.0" + }, + "bin": { + "jsmodbus": "bin/jsmodbus.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/jsmodbus/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/leven": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", + "integrity": "sha1-wuep93IJTe6dNCAq6KzORoeHVYA=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/log4js": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.5.2.tgz", + "integrity": "sha512-DXtpNtt+KDOMT7RHUDIur/WsSA3rntlUh9Zg4XCdV42wUuMmbFkl38+LZ92Z5QvQA7mD5kAVkLiBSEH/tvUB8A==", + "dependencies": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "flatted": "^3.2.5", + "rfdc": "^1.3.0", + "streamroller": "^3.1.1" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" + }, + "node_modules/mqtt": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/mqtt/-/mqtt-4.3.7.tgz", + "integrity": "sha512-ew3qwG/TJRorTz47eW46vZ5oBw5MEYbQZVaEji44j5lAUSQSqIEoul7Kua/BatBW0H0kKQcC9kwUHa1qzaWHSw==", + "dependencies": { + "commist": "^1.0.0", + "concat-stream": "^2.0.0", + "debug": "^4.1.1", + "duplexify": "^4.1.1", + "help-me": "^3.0.0", + "inherits": "^2.0.3", + "lru-cache": "^6.0.0", + "minimist": "^1.2.5", + "mqtt-packet": "^6.8.0", + "number-allocator": "^1.0.9", + "pump": "^3.0.0", + "readable-stream": "^3.6.0", + "reinterval": "^1.1.0", + "rfdc": "^1.3.0", + "split2": "^3.1.0", + "ws": "^7.5.5", + "xtend": "^4.0.2" + }, + "bin": { + "mqtt": "bin/mqtt.js", + "mqtt_pub": "bin/pub.js", + "mqtt_sub": "bin/sub.js" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/mqtt-packet": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/mqtt-packet/-/mqtt-packet-6.10.0.tgz", + "integrity": "sha512-ja8+mFKIHdB1Tpl6vac+sktqy3gA8t9Mduom1BA75cI+R9AHnZOiaBQwpGiWnaVJLDGRdNhQmFaAqd7tkKSMGA==", + "dependencies": { + "bl": "^4.0.2", + "debug": "^4.1.1", + "process-nextick-args": "^2.0.1" + } + }, + "node_modules/mqtt/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/nan": { + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.16.0.tgz", + "integrity": "sha512-UdAqHyFngu7TfQKsCBgAA6pWDkT8MAO7d0jyOecVhN5354xbLqdn8mV9Tat9gepAupm0bt2DbeaSC8vS52MuFA==" + }, + "node_modules/napi-build-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", + "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==" + }, + "node_modules/node-abi": { + "version": "3.22.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.22.0.tgz", + "integrity": "sha512-u4uAs/4Zzmp/jjsD9cyFYDXeISfUWaAVWshPmDZOFOv4Xl4SbzTXm53I04C2uRueYJ+0t5PEtLH/owbn2Npf/w==", + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/nodemailer": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.7.tgz", + "integrity": "sha512-rUtR77ksqex/eZRLmQ21LKVH5nAAsVicAtAYudK7JgwenEDZ0UIQ1adUGqErz7sMkWYxWTTU1aeP2Jga6WQyJw==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "dependencies": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "node_modules/number-allocator": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/number-allocator/-/number-allocator-1.0.14.tgz", + "integrity": "sha512-OrL44UTVAvkKdOdRQZIJpLkAdjXGTRda052sN4sO77bKEzYYqWKMBjQvrJFzqygI99gL6Z4u2xctPW1tB8ErvA==", + "dependencies": { + "debug": "^4.3.1", + "js-sdsl": "4.3.0" + } + }, + "node_modules/number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/prebuild-install": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.0.tgz", + "integrity": "sha512-CNcMgI1xBypOyGqjp3wOc8AAo1nMhZS3Cwd3iHIxOdAUbb+YxdNuM4Z5iIrZ8RLvOsf3F3bl7b7xGq6DjQoNYA==", + "dependencies": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^1.0.1", + "node-abi": "^3.3.0", + "npmlog": "^4.0.1", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + }, + "bin": { + "prebuild-install": "bin.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/reinterval": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reinterval/-/reinterval-1.1.0.tgz", + "integrity": "sha1-M2Hs+jymwYKDOA3Qu5VG85D17Oc=" + }, + "node_modules/rfdc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==" + }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/serialport": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/serialport/-/serialport-9.2.8.tgz", + "integrity": "sha512-FsWpMQgSJxi93JgWl5xM1f9/Z8IjRJuaUEoHqLf8FPBLw7gMhInuHOBhI2onQufWIYPGTz3H3oGcu1nCaK1EfA==", + "dependencies": { + "@serialport/binding-mock": "9.2.4", + "@serialport/bindings": "9.2.8", + "@serialport/parser-byte-length": "9.2.4", + "@serialport/parser-cctalk": "9.2.4", + "@serialport/parser-delimiter": "9.2.4", + "@serialport/parser-inter-byte-timeout": "9.2.4", + "@serialport/parser-readline": "9.2.4", + "@serialport/parser-ready": "9.2.4", + "@serialport/parser-regex": "9.2.4", + "@serialport/stream": "9.2.4", + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "node_modules/split2": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", + "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", + "dependencies": { + "readable-stream": "^3.0.0" + } + }, + "node_modules/split2/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==" + }, + "node_modules/streamroller": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.1.1.tgz", + "integrity": "sha512-iPhtd9unZ6zKdWgMeYGfSBuqCngyJy1B/GPi/lTpwGpa3bajuX30GjUVd0/Tn/Xhg0mr4DOSENozz9Y06qyonQ==", + "dependencies": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "fs-extra": "^10.1.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dependencies": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/tar-fs": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "dependencies": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tar-stream/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/total.js": { + "version": "3.4.13", + "resolved": "https://registry.npmjs.org/total.js/-/total.js-3.4.13.tgz", + "integrity": "sha512-lAH4gEixlPFbrE3xfKADAcHfO79IFq2wKa9GTsrgRzIR5MTg3mNH7+4IxvX1pK8faoYb/0oYSJ1YTsAa5hIFFQ==", + "bin": { + "total": "bin/totaljs", + "total.js": "bin/totaljs", + "totaljs": "bin/totaljs", + "totalpackage": "bin/tpm", + "tpm": "bin/tpm" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, + "node_modules/universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "node_modules/wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "node_modules/ws": { + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } + }, + "dependencies": { + "@serialport/binding-abstract": { + "version": "9.2.3", + "resolved": "https://registry.npmjs.org/@serialport/binding-abstract/-/binding-abstract-9.2.3.tgz", + "integrity": "sha512-cQs9tbIlG3P0IrOWyVirqlhWuJ7Ms2Zh9m2108z6Y5UW/iVj6wEOiW8EmK9QX9jmJXYllE7wgGgvVozP5oCj3w==", + "requires": { + "debug": "^4.3.2" + } + }, + "@serialport/binding-mock": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/binding-mock/-/binding-mock-9.2.4.tgz", + "integrity": "sha512-dpEhACCs44oQhh6ajJfJdvQdK38Vq0N4W6iD/gdplglDCK7qXRQCMUjJIeKdS/HSEiWkC3bwumUhUufdsOyT4g==", + "requires": { + "@serialport/binding-abstract": "9.2.3", + "debug": "^4.3.2" + } + }, + "@serialport/bindings": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/@serialport/bindings/-/bindings-9.2.8.tgz", + "integrity": "sha512-hSLxTe0tADZ3LMMGwvEJWOC/TaFQTyPeFalUCsJ1lSQ0k6bPF04JwrtB/C81GetmDBTNRY0GlD0SNtKCc7Dr5g==", + "requires": { + "@serialport/binding-abstract": "9.2.3", + "@serialport/parser-readline": "9.2.4", + "bindings": "^1.5.0", + "debug": "^4.3.2", + "nan": "^2.15.0", + "prebuild-install": "^7.0.0" + } + }, + "@serialport/parser-byte-length": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-byte-length/-/parser-byte-length-9.2.4.tgz", + "integrity": "sha512-sQD/iw4ZMU3xW9PLi0/GlvU6Y623jGeWecbMkO7izUo/6P7gtfv1c9ikd5h0kwL8AoAOpQA1lxdHIKox+umBUg==" + }, + "@serialport/parser-cctalk": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-cctalk/-/parser-cctalk-9.2.4.tgz", + "integrity": "sha512-T4TU5vQMwmo9AB3gQLFDWbfJXlW5jd9guEsB/nqKjFHTv0FXPdZ7DQ2TpSp8RnHWxU3GX6kYTaDO20BKzc8GPQ==" + }, + "@serialport/parser-delimiter": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-delimiter/-/parser-delimiter-9.2.4.tgz", + "integrity": "sha512-4nvTAoYAgkxFiXrkI+3CA49Yd43CODjeszh89EK+I9c8wOZ+etZduRCzINYPiy26g7zO+GRAb9FoPCsY+sYcbQ==" + }, + "@serialport/parser-inter-byte-timeout": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-inter-byte-timeout/-/parser-inter-byte-timeout-9.2.4.tgz", + "integrity": "sha512-SOAdvr0oBQIOCXX198hiTlxs4JTKg9j5piapw5tNq52fwDOWdbYrFneT/wN04UTMKaDrJuEvXq6T4rv4j7nJ5A==" + }, + "@serialport/parser-readline": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-readline/-/parser-readline-9.2.4.tgz", + "integrity": "sha512-Z1/qrZTQUVhNSJP1hd9YfDvq0o7d87rNwAjjRKbVpa7Qi51tG5BnKt43IV3NFMyBlVcRe0rnIb3tJu57E0SOwg==", + "requires": { + "@serialport/parser-delimiter": "9.2.4" + } + }, + "@serialport/parser-ready": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-ready/-/parser-ready-9.2.4.tgz", + "integrity": "sha512-Pyi94Itjl6qAURwIZr/gmZpMAyTmKXThm6vL5DoAWGQjcRHWB0gwv2TY2v7N+mQLJYUKU3cMnvnATXxHm7xjxw==" + }, + "@serialport/parser-regex": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-regex/-/parser-regex-9.2.4.tgz", + "integrity": "sha512-sI/cVvPOYz+Dbv4ZdnW16qAwvXiFf/1pGASQdbveRTlgJDdz7sRNlCBifzfTN2xljwvCTZYqiudKvDdC1TepRQ==" + }, + "@serialport/stream": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/stream/-/stream-9.2.4.tgz", + "integrity": "sha512-bLye8Ub4vUFQGmkh8qEqehr7SE7EJs2yDs0h9jzuL5oKi+F34CFmWkEErO8GAOQ8YNn7p6b3GxUgs+0BrHHDZQ==", + "requires": { + "debug": "^4.3.2" + } + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==" + }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "are-we-there-yet": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", + "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "base64-js": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", + "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==" + }, + "bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "requires": { + "file-uri-to-path": "1.0.0" + } + }, + "bitwise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/bitwise/-/bitwise-2.1.0.tgz", + "integrity": "sha512-XKgAhMXCh4H/3oNwAHAsAO0iC89s9cOiumgYwSHjSobGWxYjv62YhkL9QEdvGP151xypCtMlAfKK79GEcd2eRQ==" + }, + "bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "requires": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "buffer": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz", + "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==", + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" + }, + "chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==" + }, + "commist": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/commist/-/commist-1.1.0.tgz", + "integrity": "sha512-rraC8NXWOEjhADbZe9QBNzLAN5Q3fsTPQtBV+fEVj6xKIgDgNiEVE6ZNfHpZOqfQ21YUzfVNUXLOEZquYvQPPg==", + "requires": { + "leven": "^2.1.0", + "minimist": "^1.1.0" + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "concat-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", + "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.0.2", + "typedarray": "^0.0.6" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "crc": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/crc/-/crc-3.4.0.tgz", + "integrity": "sha512-ycVC2+4/DLgXXq7QweYi2znhqDuZz6P5TQXnkQo8v15XY/5p/IWeZwsSE31Ifo8w15b8TWLsqhXOjXyilHuQxw==" + }, + "date-format": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.11.tgz", + "integrity": "sha512-VS20KRyorrbMCQmpdl2hg5KaOUsda1RbnsJg461FfrcyCUg+pkd0b40BSW4niQyTheww4DBXQnS7HwSrKkipLw==" + }, + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "requires": { + "ms": "2.1.2" + } + }, + "decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "requires": { + "mimic-response": "^3.1.0" + } + }, + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==" + }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" + }, + "detect-libc": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz", + "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==" + }, + "duplexify": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.2.tgz", + "integrity": "sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw==", + "requires": { + "end-of-stream": "^1.4.1", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1", + "stream-shift": "^1.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "easy-crc": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/easy-crc/-/easy-crc-0.0.2.tgz", + "integrity": "sha512-h6eqIdhJRe0p271/xZJbM/0klCi13mW5IB7ZEzEGH11yV4QXWAkD4yPErz0fXdhFrd6sZ4Q1k5Iky2kMsMNePw==" + }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "requires": { + "once": "^1.4.0" + } + }, + "expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==" + }, + "file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" + }, + "flatted": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", + "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==" + }, + "fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, + "fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha512-14x4kjc6lkD3ltw589k0NrPD6cCNTD6CWoVUNpB85+DrtONoZn+Rug6xZU5RvSC4+TZPxA5AnBibQYAvZn41Hg==", + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==" + }, + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" + }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" + }, + "help-me": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/help-me/-/help-me-3.0.0.tgz", + "integrity": "sha512-hx73jClhyk910sidBB7ERlnhMlFsJJIBqSVMFDwPN8o2v9nmp5KgLq1Xz1Bf1fCMMZ6mPrX159iG0VLy/fPMtQ==", + "requires": { + "glob": "^7.1.6", + "readable-stream": "^3.6.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==", + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "js-sdsl": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz", + "integrity": "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==" + }, + "jsmodbus": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/jsmodbus/-/jsmodbus-4.0.6.tgz", + "integrity": "sha512-gCmjoaERErK5Rn9Lu/BN07fY13MoWV7JKgGzrnkPlQPdPxYcwDhLtYcmpFFpZ4J9NPZZBSezi1UkLZO/DnNppA==", + "requires": { + "crc": "3.4.0", + "debug": "^3.1.0" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "requires": { + "ms": "^2.1.1" + } + } + } + }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, + "leven": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", + "integrity": "sha1-wuep93IJTe6dNCAq6KzORoeHVYA=" + }, + "log4js": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.5.2.tgz", + "integrity": "sha512-DXtpNtt+KDOMT7RHUDIur/WsSA3rntlUh9Zg4XCdV42wUuMmbFkl38+LZ92Z5QvQA7mD5kAVkLiBSEH/tvUB8A==", + "requires": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "flatted": "^3.2.5", + "rfdc": "^1.3.0", + "streamroller": "^3.1.1" + } + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "requires": { + "yallist": "^4.0.0" + } + }, + "mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==" + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==" + }, + "mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" + }, + "mqtt": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/mqtt/-/mqtt-4.3.7.tgz", + "integrity": "sha512-ew3qwG/TJRorTz47eW46vZ5oBw5MEYbQZVaEji44j5lAUSQSqIEoul7Kua/BatBW0H0kKQcC9kwUHa1qzaWHSw==", + "requires": { + "commist": "^1.0.0", + "concat-stream": "^2.0.0", + "debug": "^4.1.1", + "duplexify": "^4.1.1", + "help-me": "^3.0.0", + "inherits": "^2.0.3", + "lru-cache": "^6.0.0", + "minimist": "^1.2.5", + "mqtt-packet": "^6.8.0", + "number-allocator": "^1.0.9", + "pump": "^3.0.0", + "readable-stream": "^3.6.0", + "reinterval": "^1.1.0", + "rfdc": "^1.3.0", + "split2": "^3.1.0", + "ws": "^7.5.5", + "xtend": "^4.0.2" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "mqtt-packet": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/mqtt-packet/-/mqtt-packet-6.10.0.tgz", + "integrity": "sha512-ja8+mFKIHdB1Tpl6vac+sktqy3gA8t9Mduom1BA75cI+R9AHnZOiaBQwpGiWnaVJLDGRdNhQmFaAqd7tkKSMGA==", + "requires": { + "bl": "^4.0.2", + "debug": "^4.1.1", + "process-nextick-args": "^2.0.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "nan": { + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.16.0.tgz", + "integrity": "sha512-UdAqHyFngu7TfQKsCBgAA6pWDkT8MAO7d0jyOecVhN5354xbLqdn8mV9Tat9gepAupm0bt2DbeaSC8vS52MuFA==" + }, + "napi-build-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", + "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==" + }, + "node-abi": { + "version": "3.22.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.22.0.tgz", + "integrity": "sha512-u4uAs/4Zzmp/jjsD9cyFYDXeISfUWaAVWshPmDZOFOv4Xl4SbzTXm53I04C2uRueYJ+0t5PEtLH/owbn2Npf/w==", + "requires": { + "semver": "^7.3.5" + } + }, + "nodemailer": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.7.tgz", + "integrity": "sha512-rUtR77ksqex/eZRLmQ21LKVH5nAAsVicAtAYudK7JgwenEDZ0UIQ1adUGqErz7sMkWYxWTTU1aeP2Jga6WQyJw==" + }, + "npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "number-allocator": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/number-allocator/-/number-allocator-1.0.14.tgz", + "integrity": "sha512-OrL44UTVAvkKdOdRQZIJpLkAdjXGTRda052sN4sO77bKEzYYqWKMBjQvrJFzqygI99gL6Z4u2xctPW1tB8ErvA==", + "requires": { + "debug": "^4.3.1", + "js-sdsl": "4.3.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==" + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==" + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==" + }, + "prebuild-install": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.0.tgz", + "integrity": "sha512-CNcMgI1xBypOyGqjp3wOc8AAo1nMhZS3Cwd3iHIxOdAUbb+YxdNuM4Z5iIrZ8RLvOsf3F3bl7b7xGq6DjQoNYA==", + "requires": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^1.0.1", + "node-abi": "^3.3.0", + "npmlog": "^4.0.1", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + } + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + } + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "reinterval": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reinterval/-/reinterval-1.1.0.tgz", + "integrity": "sha1-M2Hs+jymwYKDOA3Qu5VG85D17Oc=" + }, + "rfdc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==" + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "requires": { + "lru-cache": "^6.0.0" + } + }, + "serialport": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/serialport/-/serialport-9.2.8.tgz", + "integrity": "sha512-FsWpMQgSJxi93JgWl5xM1f9/Z8IjRJuaUEoHqLf8FPBLw7gMhInuHOBhI2onQufWIYPGTz3H3oGcu1nCaK1EfA==", + "requires": { + "@serialport/binding-mock": "9.2.4", + "@serialport/bindings": "9.2.8", + "@serialport/parser-byte-length": "9.2.4", + "@serialport/parser-cctalk": "9.2.4", + "@serialport/parser-delimiter": "9.2.4", + "@serialport/parser-inter-byte-timeout": "9.2.4", + "@serialport/parser-readline": "9.2.4", + "@serialport/parser-ready": "9.2.4", + "@serialport/parser-regex": "9.2.4", + "@serialport/stream": "9.2.4", + "debug": "^4.3.2" + } + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==" + }, + "simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "requires": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "split2": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", + "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", + "requires": { + "readable-stream": "^3.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==" + }, + "streamroller": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.1.1.tgz", + "integrity": "sha512-iPhtd9unZ6zKdWgMeYGfSBuqCngyJy1B/GPi/lTpwGpa3bajuX30GjUVd0/Tn/Xhg0mr4DOSENozz9Y06qyonQ==", + "requires": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "fs-extra": "^10.1.0" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" + }, + "tar-fs": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "requires": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "requires": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "total.js": { + "version": "3.4.13", + "resolved": "https://registry.npmjs.org/total.js/-/total.js-3.4.13.tgz", + "integrity": "sha512-lAH4gEixlPFbrE3xfKADAcHfO79IFq2wKa9GTsrgRzIR5MTg3mNH7+4IxvX1pK8faoYb/0oYSJ1YTsAa5hIFFQ==" + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, + "universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==" + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "requires": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "ws": { + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "requires": {} + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } + } +} diff --git a/RVO45/package.json b/RVO45/package.json new file mode 100755 index 0000000..e524d7c --- /dev/null +++ b/RVO45/package.json @@ -0,0 +1,29 @@ +{ + "name": "emptyproject", + "description": "Total.js empty project.", + "version": "1.0.0", + "main": "debug.js", + "dependencies": { + "bitwise": "^2.1.0", + "easy-crc": "0.0.2", + "jsmodbus": "^4.0.6", + "log4js": "^6.3.0", + "mqtt": "^4.2.6", + "nodemailer": "^6.9.7", + "serialport": "^9.2.8", + "total.js": "^3.4.13" + }, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "https://github.com/totaljs/emptyproject-flow" + }, + "keywords": [ + "empty", + "project" + ], + "author": "Peter Širka", + "license": "MIT" +} diff --git a/RVO45/release.js b/RVO45/release.js new file mode 100755 index 0000000..02d52ff --- /dev/null +++ b/RVO45/release.js @@ -0,0 +1,15 @@ +// =================================================== +// FOR PRODUCTION +// Total.js - framework for Node.js platform +// https://www.totaljs.com +// =================================================== + +const options = {'ip':'0.0.0.0', 'port':12345}; + +// options.ip = '127.0.0.1'; +// options.port = parseInt(process.argv[2]); +// options.config = { name: 'Total.js' }; +// options.sleep = 3000; + +require('total.js').http('release', options); +// require('total.js').cluster.http(5, 'release', options); diff --git a/RVO45/release.js.json b/RVO45/release.js.json new file mode 100755 index 0000000..000f129 --- /dev/null +++ b/RVO45/release.js.json @@ -0,0 +1,34 @@ +{ + "pid": 387, + "stats": [ + { + "id": null, + "version": { + "node": "v14.18.1", + "total": "3.4.13", + "app": "1.0.0" + }, + "pid": 387, + "thread": "", + "mode": "release", + "overload": 0, + "date": "2025-10-16T00:25:56.297Z", + "memory": 26.17, + "rm": 0, + "fm": 0, + "wm": 0, + "mm": 0, + "om": 8, + "em": 0, + "dbrm": 0, + "dbwm": 0, + "usage": 0, + "requests": 0, + "pending": 0, + "errors": 0, + "timeouts": 0, + "uptime": 724, + "online": 0 + } + ] +} \ No newline at end of file diff --git a/RVO45/report_data.log b/RVO45/report_data.log new file mode 100755 index 0000000..f1cb815 --- /dev/null +++ b/RVO45/report_data.log @@ -0,0 +1,174 @@ +{ + "name": "rvo_senica_45_ip120", + "time": "2025-10-15T13:23:11.780Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_45_ip120", + "time": "2025-10-15T14:23:11.779Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_45_ip120", + "time": "2025-10-15T15:23:11.779Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_45_ip120", + "time": "2025-10-15T16:23:11.779Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_45_ip120", + "time": "2025-10-15T17:35:21.420Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_45_ip120", + "time": "2025-10-15T18:35:21.420Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_45_ip120", + "time": "2025-10-15T19:35:21.420Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_45_ip120", + "time": "2025-10-15T20:35:21.421Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [ + "45/18_1L_4199_NEMA" + ], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_45_ip120", + "time": "2025-10-15T21:35:21.420Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [ + "45/18_1L_4199_NEMA" + ], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_45_ip120", + "time": "2025-10-15T22:35:21.421Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [ + "45/18_1L_4199_NEMA" + ], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_45_ip120", + "time": "2025-10-15T23:35:21.422Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [ + "45/18_1L_4199_NEMA" + ], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +} \ No newline at end of file From cec18d119c19461c8cc8887ec6bdd5832f1a9f1b Mon Sep 17 00:00:00 2001 From: Jakub Klena Date: Thu, 16 Oct 2025 02:27:12 +0200 Subject: [PATCH 26/30] Backup senica-RVO46 on 16.10.2025 --- RVO46/addSwitch.py | 36 + RVO46/cloud_topic.py | 76 + RVO46/config | 12 + RVO46/createNode.py | 43 + RVO46/databases/accelerometer_db.js | 3055 ++++++++++++++++ RVO46/databases/modbus_config.js | 114 + RVO46/databases/nodes.table | 39 + .../nodes_original/nodes_original.table | 1 + RVO46/databases/notifications.table | 41 + RVO46/databases/pins.table | 14 + RVO46/databases/relays.table | 5 + RVO46/databases/settings.table | 2 + RVO46/databases/tbdata.nosql | 4 + RVO46/databases/tbdatacloud.nosql | 3 + RVO46/databases/total_energy.js | 38 + RVO46/debug.js | 16 + RVO46/err.txt | 134 + RVO46/flow/cloudmqttconnect.js | 357 ++ RVO46/flow/cmd_manager.js | 3071 ++++++++++++++++ RVO46/flow/code.js | 90 + RVO46/flow/comment.js | 11 + RVO46/flow/count.js | 60 + RVO46/flow/db_connector.js | 286 ++ RVO46/flow/db_init.js | 113 + RVO46/flow/debug.js | 100 + RVO46/flow/designer.json | 3102 +++++++++++++++++ RVO46/flow/dido_controller.js | 1486 ++++++++ RVO46/flow/helper/DataToTbHandler.js | 187 + RVO46/flow/helper/ErrorToServiceHandler.js | 91 + RVO46/flow/helper/db_helper.js | 44 + RVO46/flow/helper/logger.js | 30 + RVO46/flow/helper/md5.js | 5 + RVO46/flow/helper/notification_reporter.js | 121 + RVO46/flow/helper/register.js | 144 + RVO46/flow/helper/serialport_helper.js | 99 + RVO46/flow/helper/suncalc.js | 317 ++ RVO46/flow/helper/utils.js | 161 + RVO46/flow/httprequest.js | 137 + RVO46/flow/httpresponse.js | 76 + RVO46/flow/httproute.js | 326 ++ RVO46/flow/infosender.js | 81 + RVO46/flow/modbus_reader.js | 346 ++ RVO46/flow/monitorconsumption.js | 156 + RVO46/flow/monitordisk.js | 96 + RVO46/flow/monitormemory.js | 87 + RVO46/flow/nodesdb_changecheck.js | 77 + RVO46/flow/show_dbdata.js | 243 ++ RVO46/flow/slack_filter.js | 188 + RVO46/flow/thermometer.js | 99 + RVO46/flow/trigger.js | 79 + RVO46/flow/variables.txt | 0 RVO46/flow/virtualwirein.js | 43 + RVO46/flow/virtualwireout.js | 41 + RVO46/flow/wsmqttpublish.js | 448 +++ RVO46/monitor.txt | 306 ++ RVO46/package-lock.json | 2139 ++++++++++++ RVO46/package.json | 30 + RVO46/release.js | 15 + RVO46/release.js.json | 34 + RVO46/report_data.log | 151 + 60 files changed, 18706 insertions(+) create mode 100755 RVO46/addSwitch.py create mode 100755 RVO46/cloud_topic.py create mode 100755 RVO46/config create mode 100755 RVO46/createNode.py create mode 100755 RVO46/databases/accelerometer_db.js create mode 100755 RVO46/databases/modbus_config.js create mode 100755 RVO46/databases/nodes.table create mode 100755 RVO46/databases/nodes_original/nodes_original.table create mode 100755 RVO46/databases/notifications.table create mode 100755 RVO46/databases/pins.table create mode 100755 RVO46/databases/relays.table create mode 100755 RVO46/databases/settings.table create mode 100755 RVO46/databases/tbdata.nosql create mode 100755 RVO46/databases/tbdatacloud.nosql create mode 100755 RVO46/databases/total_energy.js create mode 100755 RVO46/debug.js create mode 100755 RVO46/err.txt create mode 100755 RVO46/flow/cloudmqttconnect.js create mode 100755 RVO46/flow/cmd_manager.js create mode 100755 RVO46/flow/code.js create mode 100755 RVO46/flow/comment.js create mode 100755 RVO46/flow/count.js create mode 100755 RVO46/flow/db_connector.js create mode 100755 RVO46/flow/db_init.js create mode 100755 RVO46/flow/debug.js create mode 100755 RVO46/flow/designer.json create mode 100755 RVO46/flow/dido_controller.js create mode 100755 RVO46/flow/helper/DataToTbHandler.js create mode 100755 RVO46/flow/helper/ErrorToServiceHandler.js create mode 100755 RVO46/flow/helper/db_helper.js create mode 100755 RVO46/flow/helper/logger.js create mode 100755 RVO46/flow/helper/md5.js create mode 100755 RVO46/flow/helper/notification_reporter.js create mode 100755 RVO46/flow/helper/register.js create mode 100755 RVO46/flow/helper/serialport_helper.js create mode 100755 RVO46/flow/helper/suncalc.js create mode 100755 RVO46/flow/helper/utils.js create mode 100755 RVO46/flow/httprequest.js create mode 100755 RVO46/flow/httpresponse.js create mode 100755 RVO46/flow/httproute.js create mode 100755 RVO46/flow/infosender.js create mode 100755 RVO46/flow/modbus_reader.js create mode 100755 RVO46/flow/monitorconsumption.js create mode 100755 RVO46/flow/monitordisk.js create mode 100755 RVO46/flow/monitormemory.js create mode 100755 RVO46/flow/nodesdb_changecheck.js create mode 100755 RVO46/flow/show_dbdata.js create mode 100755 RVO46/flow/slack_filter.js create mode 100755 RVO46/flow/thermometer.js create mode 100755 RVO46/flow/trigger.js create mode 100755 RVO46/flow/variables.txt create mode 100755 RVO46/flow/virtualwirein.js create mode 100755 RVO46/flow/virtualwireout.js create mode 100755 RVO46/flow/wsmqttpublish.js create mode 100755 RVO46/monitor.txt create mode 100755 RVO46/package-lock.json create mode 100755 RVO46/package.json create mode 100755 RVO46/release.js create mode 100755 RVO46/release.js.json create mode 100755 RVO46/report_data.log diff --git a/RVO46/addSwitch.py b/RVO46/addSwitch.py new file mode 100755 index 0000000..c35e96b --- /dev/null +++ b/RVO46/addSwitch.py @@ -0,0 +1,36 @@ +import os + +def process_set_file(): + """ + Checks if /root/flowserver exists, reads set.txt, and modifies the second line. + """ + default_folder = "/root/flowserver" if os.path.exists("/root/flowserver") else "/home/unipi/flowserver" + flag = 1 if default_folder == "/root/flowserver" else 0 + + try: + with open("/home/unipi/flowserver/databases/settings.table", "r") as f: + lines = f.readlines() + + if len(lines) >= 2: + lines[0] = lines[0].rstrip('\n') + "|main_switch:boolean\n" + second_line = lines[1].strip() # remove trailing newline + last_pipe_index = second_line.rfind("|") + + if last_pipe_index != -1: + modified_line = second_line[:last_pipe_index + 1] + str(flag) + "|" + second_line[last_pipe_index + 1:] + lines[1] = modified_line + else: + print("Warning: No '|' character found in the second line of set.txt") + + with open("/home/unipi/flowserver/databases/settings.table", "w") as f: + f.writelines(lines) + else: + print("Warning: settings.table has less than two lines.") + + except FileNotFoundError: + print("Error: settings.table not found.") + except Exception as e: + print(e) + +# if __name__ == "__main__": +process_set_file() diff --git a/RVO46/cloud_topic.py b/RVO46/cloud_topic.py new file mode 100755 index 0000000..77c31f1 --- /dev/null +++ b/RVO46/cloud_topic.py @@ -0,0 +1,76 @@ +# import os +# +# def modify_file(file_path): +# """ +# Modifies the given file by: +# 1. Appending "|cloud_topic" to the first line. +# 2. Inserting the text from the third "." to the first "|" on the second line after the last "|" character. +# +# Args: +# file_path (str): The path to the file to be modified. +# """ +# +# with open(file_path, 'r+') as f: +# lines = f.readlines() +# +# # Modify the first line +# lines[0] += "|cloud_topic:string" +# +# # Modify the second line +# second_line = lines[1].strip() # Remove leading/trailing whitespace +# first_pipe_index = second_line.find('|') +# third_dot_index = second_line.find('.', second_line.find('.', second_line.find('.') + 1) + 1) +# text_to_insert = second_line[third_dot_index:first_pipe_index] +# +# last_pipe_index = second_line.rfind('|') +# lines[1] = second_line[:last_pipe_index + 1] + text_to_insert + "|" + second_line[last_pipe_index + 1:] +# +# print(first_pipe_index, third_dot_index, text_to_insert, last_pipe_index) +# # Write the modified lines back to the file +# # f.seek(0) +# # f.writelines(lines) +# # f.truncate() +# +# # Example usage: +# file_path = "settings.table" # Replace with the actual file path +# modify_file(file_path) +# + + +def modify_file(file_path): + """ + Modifies the given file by: + 1. Appending "|cloud_topic" to the first line. + 2. Inserting the text between the third "." and the second "|" on the second line after the last "|" character. + + Args: + file_path (str): The path to the file to be modified. + """ + + with open(file_path, 'r+') as f: + lines = f.readlines() + + first_line = lines[0].strip() + first_line += "|cloud_topic:string\n" + # Modify the first line + lines[0] = first_line + + # Modify the second line + second_line = lines[1].strip() # Remove leading/trailing whitespace + first_pipe_index = second_line.find('|') + second_pipe_index = second_line.find('|', first_pipe_index + 1) + third_dot_index = second_line.find('.', second_line.find('.', second_line.find('.') + 1) + 1) + text_to_insert = "u" + second_line[third_dot_index+1:second_pipe_index] + + last_pipe_index = second_line.rfind('|') + lines[1] = second_line[:last_pipe_index + 1] + text_to_insert + "|" + second_line[last_pipe_index + 1:] + + print(first_pipe_index, third_dot_index, text_to_insert, last_pipe_index) + # Write the modified lines back to the file + f.seek(0) + f.writelines(lines) + f.truncate() + +# Example usage: +file_path = "/home/unipi/flowserver/databases/settings.table" # Replace with the actual file path +modify_file(file_path) diff --git a/RVO46/config b/RVO46/config new file mode 100755 index 0000000..cd0a8a9 --- /dev/null +++ b/RVO46/config @@ -0,0 +1,12 @@ +name : Total.js Flow +default_timezone : Europe/Bratislava + +// Packages settings +package#flow (Object) : { url: '/' } + + +table.relays : line:number|tbname:string|contactor:number|profile:string +table.nodes : node:number|pole_number:string|node_type:string|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|project_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|cloud_topic:string|has_main_switch:boolean|daily_report:boolean|send_changed_node_numbers:boolean +table.pins : pin:string|type:string|line:number +table.notifications : key:string|weight:string|sk:string|en:string diff --git a/RVO46/createNode.py b/RVO46/createNode.py new file mode 100755 index 0000000..a8cea91 --- /dev/null +++ b/RVO46/createNode.py @@ -0,0 +1,43 @@ +print("zaciname") +import re, json + +search_str = '|' +final = [] +counter = 1 +with open("/home/unipi/flowserver/databases/nodes.table", 'r') as file: +# with open("/home/rasta5man/dev/oms/flowserver/databases/nodes.table", 'r') as file: + # Read each line in the file + for line in file: + # Print each line + line = line.strip() + print(line) + if counter != 1: + i = [m.start() for m in re.finditer(re.escape(search_str), line)] + node = line[ i[0] + 1 : i[1] ] + tbname = line[ i[3] + 1 : i[4] ] + final.append({node:tbname}) + counter += 1 +print(json.dumps(final)) +f = open("/home/unipi/flowserver/databases/nodes_original/nodes_original.table", "w") +f.write(json.dumps(final)) +f.close() + + +# +# # ``d`` has to be replaced with a different character +# old_character = "'" +# +# # ``t`` will replace ``d` +# new_character = '"' +# resultant_string = 0; +# with open("/home/unipi/flowserver/databases/nodes_original/nodes_original.table", 'r') as file: +# for line in file: +# resultant_string = re.sub("'", '"', line) +# +# resultant_string = re.sub(" ", "", resultant_string) +# print(resultant_string) +# +# f = open("/home/unipi/flowserver/databases/nodes_original/nodes_original.table", "w") +# f.write(str(resultant_string)) +# f.close() +# diff --git a/RVO46/databases/accelerometer_db.js b/RVO46/databases/accelerometer_db.js new file mode 100755 index 0000000..fdfc7fd --- /dev/null +++ b/RVO46/databases/accelerometer_db.js @@ -0,0 +1,3055 @@ +let naklony = { + "3993": { "label": "1/3A", "naklon": 0 }, + "3989": { "label": "1/3B", "naklon": 15 }, + "3976": { "label": "1/1", "naklon": 0 }, + "4181": { "label": "1/2", "naklon": 0 }, + "4376": { "label": "1/4", "naklon": 15 }, + "3868": { "label": "1/5", "naklon": 15 }, + "3728": { "label": "1/6", "naklon": 15 }, + "3730": { "label": "1/7", "naklon": 0 }, + "4374": { "label": "1/8", "naklon": 0 }, + "3718": { "label": "1/9", "naklon": 15 }, + "4375": { "label": "1/10", "naklon": 15 }, + "4172": { "label": "1/11", "naklon": 15 }, + "4176": { "label": "1/12", "naklon": 15 }, + "3800": { "label": "2/1", "naklon": 5 }, + "3823": { "label": "2/2", "naklon": 5 }, + "3905": { "label": "2/3", "naklon": 5 }, + "3803": { "label": "2/4", "naklon": 5 }, + "3817": { "label": "2/5", "naklon": 5 }, + "3818": { "label": "2/6", "naklon": 5 }, + "3811": { "label": "2/7", "naklon": 5 }, + "3915": { "label": "2/8", "naklon": 5 }, + "3843": { "label": "2/9", "naklon": 10 }, + "3827": { "label": "2/10", "naklon": 10 }, + "4220": { "label": "2/11", "naklon": 10 }, + "3826": { "label": "2/12", "naklon": 10 }, + "3834": { "label": "2/13", "naklon": 10 }, + "3838": { "label": "2/14", "naklon": 10 }, + "2823": { "label": "2/15", "naklon": 10 }, + "3750": { "label": "2/16", "naklon": 10 }, + "3378": { "label": "2/17", "naklon": 0 }, + "3376": { "label": "2/18", "naklon": 0 }, + "3379": { "label": "2/19", "naklon": 0 }, + "3285": { "label": "2/20", "naklon": 0 }, + "3382": { "label": "2/21", "naklon": 0 }, + "3383": { "label": "2/22", "naklon": 0 }, + "3375": { "label": "2/24", "naklon": 0 }, + "3381": { "label": "2/25", "naklon": 0 }, + "3380": { "label": "2/26", "naklon": 0 }, + "3828": { "label": "2/27", "naklon": 10 }, + "3377": { "label": "2/28", "naklon": 0 }, + "3591": { "label": "7/1", "naklon": 0 }, + "3587": { "label": "7/2", "naklon": 0 }, + "3468": { "label": "7/3", "naklon": 0 }, + "3466": { "label": "7/4", "naklon": 0 }, + "3474": { "label": "7/5", "naklon": 0 }, + "3481": { "label": "7/6", "naklon": 0 }, + "3589": { "label": "7/7", "naklon": 0 }, + "3472": { "label": "7/8", "naklon": 0 }, + "3473": { "label": "7/9", "naklon": 0 }, + "3584": { "label": "7/10", "naklon": 0 }, + "3571": { "label": "7/11", "naklon": 0 }, + "3476": { "label": "7/12", "naklon": 0 }, + "3590": { "label": "7/13", "naklon": 0 }, + "3478": { "label": "7/14", "naklon": 0 }, + "3471": { "label": "7/15", "naklon": 0 }, + "3467": { "label": "7/16", "naklon": 0 }, + "3479": { "label": "7/17", "naklon": 0 }, + "3480": { "label": "7/18", "naklon": 0 }, + "3477": { "label": "7/19", "naklon": 0 }, + "3362": { "label": "12/1", "naklon": 0 }, + "3355": { "label": "12/2", "naklon": 0 }, + "3356": { "label": "12/3", "naklon": 0 }, + "3349": { "label": "12/4", "naklon": 0 }, + "3357": { "label": "12/5", "naklon": 0 }, + "3350": { "label": "12/6", "naklon": 0 }, + "3353": { "label": "12/7", "naklon": 0 }, + "3539": { "label": "12/8", "naklon": 0 }, + "3050": { "label": "12/9", "naklon": 0 }, + "3361": { "label": "12/10", "naklon": 0 }, + "3360": { "label": "12/11", "naklon": 0 }, + "3358": { "label": "12/12", "naklon": 0 }, + "3541": { "label": "12/13", "naklon": 0 }, + "3551": { "label": "12/14", "naklon": 0 }, + "3514": { "label": "12/15", "naklon": 0 }, + "3547": { "label": "12/16", "naklon": 0 }, + "3562": { "label": "12/17", "naklon": 0 }, + "3525": { "label": "12/18", "naklon": 0 }, + "3558": { "label": "12/19", "naklon": 0 }, + "3511": { "label": "12/20", "naklon": 0 }, + "3058": { "label": "12/21", "naklon": 0 }, + "3062": { "label": "12/22", "naklon": 0 }, + "3070": { "label": "12/23", "naklon": 0 }, + "3447": { "label": "12/24", "naklon": 0 }, + "3056": { "label": "12/25", "naklon": 0 }, + "3057": { "label": "12/26", "naklon": 0 }, + "3071": { "label": "12/27", "naklon": 0 }, + "3061": { "label": "12/28", "naklon": 0 }, + "3069": { "label": "12/29", "naklon": 0 }, + "3077": { "label": "12/30", "naklon": 0 }, + "3080": { "label": "12/31", "naklon": 0 }, + "3081": { "label": "12/32", "naklon": 0 }, + "3078": { "label": "12/33", "naklon": 0 }, + "4037": { "label": "12/34", "naklon": 0 }, + "3067": { "label": "12/35", "naklon": 0 }, + "3051": { "label": "12/36", "naklon": 0 }, + "2924": { "label": "12/37", "naklon": 0 }, + "3060": { "label": "12/38", "naklon": 0 }, + "3073": { "label": "12/39", "naklon": 0 }, + "3469": { "label": "12/40", "naklon": 0 }, + "2923": { "label": "12/41", "naklon": 0 }, + "2925": { "label": "12/42", "naklon": 0 }, + "3359": { "label": "12/43", "naklon": 0 }, + "3055": { "label": "12/44", "naklon": 0 }, + "2922": { "label": "12/45", "naklon": 0 }, + "3084": { "label": "12/46", "naklon": 0 }, + "3064": { "label": "12/47", "naklon": 0 }, + "3066": { "label": "12/48", "naklon": 0 }, + "3072": { "label": "12/49", "naklon": 0 }, + "3415": { "label": "13/13A", "naklon": 0 }, + "3409": { "label": "13/13B", "naklon": 0 }, + "3399": { "label": "13/13C", "naklon": 0 }, + "3410": { "label": "13/29A", "naklon": 0 }, + "3407": { "label": "13/29B", "naklon": 0 }, + "3405": { "label": "13/34A", "naklon": 0 }, + "3404": { "label": "13/34B", "naklon": 0 }, + "3392": { "label": "13/45A", "naklon": 0 }, + "3386": { "label": "13/45B", "naklon": 0 }, + "3303": { "label": "13/60A", "naklon": 3 }, + "3302": { "label": "13/60B", "naklon": 3 }, + "3319": { "label": "13/70A", "naklon": 6 }, + "3317": { "label": "13/70B", "naklon": 6 }, + "3326": { "label": "13/70C", "naklon": 6 }, + "3351": { "label": "13/73A", "naklon": 6 }, + "3313": { "label": "13/73B", "naklon": 6 }, + "3316": { "label": "13/83A", "naklon": 0 }, + "3320": { "label": "13/83B", "naklon": 0 }, + "3336": { "label": "13/95A", "naklon": 0 }, + "3323": { "label": "13/95B", "naklon": 0 }, + "3339": { "label": "13/98A", "naklon": 0 }, + "3333": { "label": "13/98B", "naklon": 0 }, + "3425": { "label": "13/1", "naklon": 0 }, + "3419": { "label": "13/2", "naklon": 0 }, + "3416": { "label": "13/3", "naklon": 0 }, + "3332": { "label": "13/4", "naklon": 0 }, + "3422": { "label": "13/5", "naklon": 0 }, + "3417": { "label": "13/6", "naklon": 0 }, + "3418": { "label": "13/7", "naklon": 0 }, + "3424": { "label": "13/8", "naklon": 0 }, + "3334": { "label": "13/9", "naklon": 0 }, + "4363": { "label": "13/10", "naklon": 0 }, + "3423": { "label": "13/11", "naklon": 0 }, + "3406": { "label": "13/12", "naklon": 0 }, + "3411": { "label": "13/14", "naklon": 0 }, + "3412": { "label": "13/15", "naklon": 0 }, + "3413": { "label": "13/16", "naklon": 0 }, + "3414": { "label": "13/17", "naklon": 0 }, + "3391": { "label": "13/18", "naklon": 0 }, + "3370": { "label": "13/19", "naklon": 0 }, + "3369": { "label": "13/20", "naklon": 0 }, + "3408": { "label": "13/21", "naklon": 0 }, + "3393": { "label": "13/22", "naklon": 0 }, + "3128": { "label": "13/23", "naklon": 0 }, + "3197": { "label": "13/24", "naklon": 0 }, + "4364": { "label": "13/25", "naklon": 0 }, + "3155": { "label": "13/26", "naklon": 0 }, + "3196": { "label": "13/27", "naklon": 0 }, + "3144": { "label": "13/28", "naklon": 0 }, + "3150": { "label": "13/30", "naklon": 0 }, + "3390": { "label": "13/31", "naklon": 0 }, + "3401": { "label": "13/32", "naklon": 0 }, + "3275": { "label": "13/33", "naklon": 0 }, + "3371": { "label": "13/35", "naklon": 0 }, + "3389": { "label": "13/36", "naklon": 0 }, + "3388": { "label": "13/37", "naklon": 0 }, + "3365": { "label": "13/38", "naklon": 0 }, + "3363": { "label": "13/39", "naklon": 0 }, + "3397": { "label": "13/40", "naklon": 0 }, + "3567": { "label": "13/40/1", "naklon": 0 }, + "3387": { "label": "13/41", "naklon": 0 }, + "3403": { "label": "13/42", "naklon": 0 }, + "3147": { "label": "13/43", "naklon": 0 }, + "3141": { "label": "13/44", "naklon": 0 }, + "3364": { "label": "13/46", "naklon": 0 }, + "3367": { "label": "13/47", "naklon": 0 }, + "3368": { "label": "13/48", "naklon": 0 }, + "3402": { "label": "13/49", "naklon": 0 }, + "3366": { "label": "13/50", "naklon": 0 }, + "3395": { "label": "13/51", "naklon": 0 }, + "3372": { "label": "13/52", "naklon": 0 }, + "3394": { "label": "13/53", "naklon": 0 }, + "3308": { "label": "13/54", "naklon": 0 }, + "3847": { "label": "13/54/1", "naklon": 0 }, + "3312": { "label": "13/55", "naklon": 3 }, + "3309": { "label": "13/56", "naklon": 3 }, + "3311": { "label": "13/57", "naklon": 3 }, + "3310": { "label": "13/58", "naklon": 3 }, + "4365": { "label": "13/59", "naklon": 3 }, + "4093": { "label": "13/60/1", "naklon": 3 }, + "3304": { "label": "13/61", "naklon": 3 }, + "3307": { "label": "13/62", "naklon": 3 }, + "3271": { "label": "13/63", "naklon": 3 }, + "3301": { "label": "13/64", "naklon": 3 }, + "4366": { "label": "13/65", "naklon": 3 }, + "3300": { "label": "13/66", "naklon": 3 }, + "3185": { "label": "13/67", "naklon": 0 }, + "3184": { "label": "13/68", "naklon": 0 }, + "3188": { "label": "13/69", "naklon": 0 }, + "3343": { "label": "13/71", "naklon": 6 }, + "3819": { "label": "13/71/1", "naklon": 6 }, + "3880": { "label": "13/71/2", "naklon": 6 }, + "3348": { "label": "13/72", "naklon": 6 }, + "3344": { "label": "13/74", "naklon": 6 }, + "3346": { "label": "13/75", "naklon": 6 }, + "3597": { "label": "13/75/1", "naklon": 6 }, + "3345": { "label": "13/76", "naklon": 6 }, + "3322": { "label": "13/77", "naklon": 0 }, + "3325": { "label": "13/78", "naklon": 0 }, + "4310": { "label": "13/78/1", "naklon": 0 }, + "3315": { "label": "13/79", "naklon": 0 }, + "3328": { "label": "13/80", "naklon": 0 }, + "3321": { "label": "13/81", "naklon": 0 }, + "3324": { "label": "13/82", "naklon": 0 }, + "3140": { "label": "13/84", "naklon": 0 }, + "3153": { "label": "13/85", "naklon": 0 }, + "3145": { "label": "13/86", "naklon": 0 }, + "3134": { "label": "13/87", "naklon": 0 }, + "3151": { "label": "13/88", "naklon": 0 }, + "3143": { "label": "13/89", "naklon": 0 }, + "3318": { "label": "13/90", "naklon": 0 }, + "3347": { "label": "13/91", "naklon": 0 }, + "3314": { "label": "13/94", "naklon": 0 }, + "3331": { "label": "13/96", "naklon": 0 }, + "3327": { "label": "13/97", "naklon": 0 }, + "3329": { "label": "13/99", "naklon": 0 }, + "3337": { "label": "13/100", "naklon": 0 }, + "3330": { "label": "13/101", "naklon": 0 }, + "3335": { "label": "13/102", "naklon": 0 }, + "3420": { "label": "13/103", "naklon": 0 }, + "3421": { "label": "13/104", "naklon": 0 }, + "4361": { "label": "13/105", "naklon": 0 }, + "4362": { "label": "13/106", "naklon": 0 }, + "3526": { "label": "13/107", "naklon": 0 }, + "4424": { "label": "13/108", "naklon": null }, + "3561": { "label": "13/109", "naklon": null }, + "3527": { "label": "13/110", "naklon": null }, + "3521": { "label": "13/111", "naklon": null }, + "3552": { "label": "13/112", "naklon": null }, + "3544": { "label": "13/113", "naklon": null }, + "3534": { "label": "13/114", "naklon": null }, + "3516": { "label": "13/115", "naklon": null }, + "3513": { "label": "13/116", "naklon": null }, + "3565": { "label": "13/117", "naklon": null }, + "3866": { "label": "13/118", "naklon": null }, + "3136": { "label": "14/1", "naklon": 0 }, + "3137": { "label": "14/2", "naklon": 0 }, + "3135": { "label": "14/3", "naklon": 0 }, + "3149": { "label": "14/4", "naklon": 0 }, + "3142": { "label": "14/5", "naklon": 0 }, + "3342": { "label": "14/6", "naklon": 0 }, + "3340": { "label": "14/7", "naklon": 0 }, + "3152": { "label": "14/8", "naklon": 0 }, + "3886": { "label": "14/9", "naklon": 0 }, + "3341": { "label": "14/10", "naklon": null }, + "3352": { "label": "14/11", "naklon": null }, + "3396": { "label": "15/1", "naklon": 5 }, + "2784": { "label": "15/2", "naklon": 5 }, + "2788": { "label": "15/3", "naklon": 5 }, + "2801": { "label": "15/4", "naklon": 5 }, + "2815": { "label": "15/5", "naklon": 5 }, + "2829": { "label": "15/6", "naklon": 5 }, + "2796": { "label": "15/7", "naklon": 5 }, + "2803": { "label": "15/8", "naklon": 5 }, + "4304": { "label": "15/8/1", "naklon": 5 }, + "4311": { "label": "15/8/2", "naklon": 5 }, + "2821": { "label": "15/9", "naklon": 5 }, + "3400": { "label": "15/10", "naklon": 5 }, + "2799": { "label": "15/11", "naklon": 5 }, + "2804": { "label": "15/12", "naklon": 5 }, + "4303": { "label": "15/12/1", "naklon": 5 }, + "4309": { "label": "15/12/2", "naklon": 5 }, + "2806": { "label": "15/13", "naklon": 5 }, + "2787": { "label": "15/14", "naklon": 5 }, + "2809": { "label": "15/15", "naklon": 5 }, + "2814": { "label": "15/16", "naklon": 0 }, + "3934": { "label": "15/17", "naklon": 0 }, + "3192": { "label": "15/18", "naklon": 0 }, + "2812": { "label": "15/19", "naklon": 0 }, + "4070": { "label": "15/20", "naklon": 0 }, + "2826": { "label": "15/21", "naklon": 0 }, + "2808": { "label": "15/22", "naklon": 3 }, + "2795": { "label": "15/23", "naklon": 3 }, + "2807": { "label": "15/24", "naklon": 3 }, + "2831": { "label": "15/25", "naklon": 0 }, + "2862": { "label": "15/26", "naklon": null }, + "2861": { "label": "15/27", "naklon": 0 }, + "2866": { "label": "15/28", "naklon": 0 }, + "3546": { "label": "15/28/1", "naklon": 0 }, + "4146": { "label": "15/29", "naklon": 0 }, + "3001": { "label": "15/29/1", "naklon": 0 }, + "2835": { "label": "15/30", "naklon": 0 }, + "2874": { "label": "15/31", "naklon": 0 }, + "2852": { "label": "15/32", "naklon": 0 }, + "2851": { "label": "15/33", "naklon": 0 }, + "3560": { "label": "15/33/1", "naklon": 0 }, + "2858": { "label": "15/34", "naklon": 0 }, + "4306": { "label": "15/34/1", "naklon": 0 }, + "2856": { "label": "15/35", "naklon": 0 }, + "2847": { "label": "15/36", "naklon": 0 }, + "3556": { "label": "15/36/1", "naklon": 0 }, + "3950": { "label": "15/37", "naklon": 0 }, + "2848": { "label": "15/38", "naklon": 0 }, + "2863": { "label": "15/39", "naklon": 0 }, + "4313": { "label": "15/39/1", "naklon": 0 }, + "2873": { "label": "15/40", "naklon": 0 }, + "2984": { "label": "15/40/1", "naklon": 0 }, + "2854": { "label": "15/41", "naklon": 0 }, + "2859": { "label": "15/42", "naklon": 0 }, + "2872": { "label": "15/43", "naklon": 0 }, + "2849": { "label": "15/44", "naklon": 0 }, + "2864": { "label": "15/45", "naklon": 0 }, + "3553": { "label": "15/46", "naklon": null }, + "3021": { "label": "15/47", "naklon": null }, + "3008": { "label": "15/47/1", "naklon": null }, + "3017": { "label": "15/48", "naklon": null }, + "3014": { "label": "15/49", "naklon": null }, + "2981": { "label": "15/50", "naklon": null }, + "3020": { "label": "15/51", "naklon": null }, + "3027": { "label": "15/52", "naklon": null }, + "3006": { "label": "15/53", "naklon": null }, + "3012": { "label": "15/54", "naklon": null }, + "2738": { "label": "15/55", "naklon": 0 }, + "2725": { "label": "15/56", "naklon": 0 }, + "3016": { "label": "15/57", "naklon": null }, + "3005": { "label": "15/58", "naklon": null }, + "3009": { "label": "15/58/1", "naklon": null }, + "3010": { "label": "15/59", "naklon": 0 }, + "3538": { "label": "15/59/1", "naklon": 0 }, + "4145": { "label": "15/59/2", "naklon": 0 }, + "2713": { "label": "15/60", "naklon": 0 }, + "2789": { "label": "15/61", "naklon": 0 }, + "2736": { "label": "15/62", "naklon": 0 }, + "2739": { "label": "15/63", "naklon": 0 }, + "4346": { "label": "15/64", "naklon": 0 }, + "2731": { "label": "15/65", "naklon": 0 }, + "2818": { "label": "15/66", "naklon": 0 }, + "3557": { "label": "15/66/1", "naklon": 0 }, + "2822": { "label": "15/67", "naklon": 0 }, + "2833": { "label": "15/68", "naklon": 0 }, + "2834": { "label": "15/69", "naklon": 0 }, + "3097": { "label": "15/70", "naklon": 0 }, + "2824": { "label": "15/71", "naklon": 0 }, + "2828": { "label": "15/72", "naklon": 0 }, + "2600": { "label": "15/73", "naklon": 0 }, + "4314": { "label": "15/73/1", "naklon": 0 }, + "2832": { "label": "15/74", "naklon": 0 }, + "4360": { "label": "15/75", "naklon": 0 }, + "2846": { "label": "15/76", "naklon": 0 }, + "2584": { "label": "15/77", "naklon": 0 }, + "2843": { "label": "15/78", "naklon": 0 }, + "4308": { "label": "15/78/1", "naklon": 0 }, + "4144": { "label": "15/79", "naklon": null }, + "2844": { "label": "15/80", "naklon": 0 }, + "2842": { "label": "15/81", "naklon": 0 }, + "2838": { "label": "15/82", "naklon": 0 }, + "2837": { "label": "15/83", "naklon": null }, + "3555": { "label": "15/83/1", "naklon": null }, + "2839": { "label": "15/84", "naklon": 0 }, + "2830": { "label": "15/85", "naklon": 0 }, + "4066": { "label": "15/86", "naklon": 0 }, + "2836": { "label": "15/87", "naklon": 0 }, + "2911": { "label": "15/88", "naklon": 0 }, + "2825": { "label": "15/89", "naklon": 0 }, + "2811": { "label": "15/90", "naklon": 0 }, + "3740": { "label": "15/94", "naklon": 15 }, + "2734": { "label": "15/95", "naklon": 15 }, + "3105": { "label": "15/96", "naklon": 15 }, + "2732": { "label": "15/97", "naklon": 15 }, + "2727": { "label": "15/98", "naklon": 15 }, + "2735": { "label": "15/99", "naklon": 15 }, + "3926": { "label": "15/100", "naklon": 15 }, + "2918": { "label": "15/101", "naklon": 0 }, + "2705": { "label": "15/102", "naklon": 10 }, + "2708": { "label": "15/103", "naklon": 10 }, + "2721": { "label": "15/104", "naklon": 10 }, + "2719": { "label": "15/105", "naklon": 10 }, + "2919": { "label": "15/106", "naklon": 10 }, + "3101": { "label": "15/107", "naklon": 10 }, + "2853": { "label": "15/108", "naklon": 10 }, + "2715": { "label": "15/109", "naklon": 10 }, + "2712": { "label": "15/110", "naklon": 0 }, + "2711": { "label": "15/111", "naklon": 0 }, + "2709": { "label": "15/112", "naklon": 0 }, + "2710": { "label": "15/113", "naklon": 0 }, + "2907": { "label": "15/114", "naklon": 0 }, + "2906": { "label": "15/115", "naklon": 0 }, + "2908": { "label": "15/116", "naklon": 0 }, + "2901": { "label": "15/117", "naklon": 0 }, + "2913": { "label": "15/118", "naklon": 0 }, + "3656": { "label": "15/119", "naklon": 0 }, + "2781": { "label": "15/120", "naklon": 0 }, + "2802": { "label": "15/121", "naklon": 0 }, + "2791": { "label": "15/122", "naklon": 0 }, + "2783": { "label": "15/123", "naklon": 0 }, + "2794": { "label": "15/124", "naklon": 0 }, + "3139": { "label": "15/125", "naklon": 0 }, + "3229": { "label": "15/126", "naklon": 5 }, + "3239": { "label": "15/127", "naklon": 5 }, + "3230": { "label": "15/128", "naklon": 5 }, + "4016": { "label": "15/129", "naklon": null }, + "3608": { "label": "16/16A", "naklon": 0 }, + "4151": { "label": "16/16B", "naklon": 0 }, + "3710": { "label": "16/1", "naklon": 0 }, + "3726": { "label": "16/2", "naklon": 0 }, + "3743": { "label": "16/3", "naklon": 0 }, + "3724": { "label": "16/4", "naklon": 0 }, + "3712": { "label": "16/5", "naklon": 0 }, + "3739": { "label": "16/6", "naklon": 0 }, + "3742": { "label": "16/7", "naklon": 0 }, + "3731": { "label": "16/8", "naklon": 0 }, + "3727": { "label": "16/9", "naklon": 0 }, + "3729": { "label": "16/10", "naklon": 0 }, + "3736": { "label": "16/11", "naklon": 0 }, + "3713": { "label": "16/12", "naklon": 0 }, + "3715": { "label": "16/13", "naklon": 0 }, + "3733": { "label": "16/14", "naklon": 0 }, + "3732": { "label": "16/15", "naklon": 0 }, + "3634": { "label": "16/17", "naklon": 0 }, + "3610": { "label": "16/18", "naklon": 0 }, + "3626": { "label": "16/19", "naklon": 0 }, + "3618": { "label": "16/20", "naklon": 0 }, + "3619": { "label": "16/21", "naklon": 0 }, + "3628": { "label": "16/22", "naklon": 0 }, + "3615": { "label": "16/23", "naklon": 0 }, + "3609": { "label": "16/24", "naklon": 0 }, + "3606": { "label": "16/25", "naklon": 0 }, + "3624": { "label": "16/26", "naklon": 0 }, + "3627": { "label": "16/27", "naklon": 0 }, + "3607": { "label": "16/28", "naklon": 0 }, + "4370": { "label": "16/29", "naklon": 0 }, + "3692": { "label": "16/30", "naklon": 0 }, + "3614": { "label": "16/31", "naklon": 0 }, + "3623": { "label": "16/32", "naklon": 0 }, + "4373": { "label": "16/33", "naklon": 0 }, + "3620": { "label": "16/34", "naklon": 0 }, + "3685": { "label": "16/35", "naklon": 0 }, + "3616": { "label": "16/36", "naklon": 0 }, + "3686": { "label": "16/37", "naklon": 0 }, + "3688": { "label": "16/38", "naklon": 0 }, + "3684": { "label": "16/39", "naklon": 0 }, + "3825": { "label": "16/40", "naklon": 0 }, + "3865": { "label": "16/41", "naklon": 0 }, + "3824": { "label": "16/42", "naklon": 0 }, + "3871": { "label": "16/43", "naklon": 0 }, + "3801": { "label": "16/44", "naklon": 0 }, + "3862": { "label": "16/45", "naklon": 0 }, + "3876": { "label": "16/46", "naklon": 0 }, + "3861": { "label": "16/47", "naklon": 0 }, + "4215": { "label": "16/48", "naklon": 0 }, + "3605": { "label": "16/49", "naklon": 10 }, + "3603": { "label": "16/50", "naklon": 10 }, + "3592": { "label": "16/51", "naklon": 10 }, + "3598": { "label": "16/52", "naklon": 10 }, + "3594": { "label": "16/53", "naklon": 10 }, + "3593": { "label": "16/54", "naklon": 10 }, + "3630": { "label": "16/55", "naklon": 10 }, + "3763": { "label": "16/56", "naklon": 10 }, + "3746": { "label": "16/57", "naklon": 10 }, + "3699": { "label": "16/58", "naklon": 0 }, + "3698": { "label": "16/59", "naklon": 0 }, + "3709": { "label": "16/60", "naklon": null }, + "3708": { "label": "16/61", "naklon": 0 }, + "3703": { "label": "16/62", "naklon": null }, + "3700": { "label": "16/63", "naklon": 0 }, + "3701": { "label": "16/64", "naklon": null }, + "3704": { "label": "16/65", "naklon": 0 }, + "3707": { "label": "16/66", "naklon": null }, + "3810": { "label": "16/67", "naklon": 0 }, + "4208": { "label": "16/68", "naklon": null }, + "3867": { "label": "16/69", "naklon": 0 }, + "4372": { "label": "16/70", "naklon": null }, + "3881": { "label": "16/71", "naklon": 0 }, + "4204": { "label": "16/72", "naklon": null }, + "3869": { "label": "16/73", "naklon": 0 }, + "4202": { "label": "16/74", "naklon": null }, + "3830": { "label": "16/75", "naklon": 0 }, + "3870": { "label": "16/76", "naklon": null }, + "3964": { "label": "16/77", "naklon": 0 }, + "3849": { "label": "16/78", "naklon": 0 }, + "3694": { "label": "16/79", "naklon": null }, + "3717": { "label": "16/80", "naklon": 0 }, + "3877": { "label": "16/81", "naklon": null }, + "3755": { "label": "16/82", "naklon": 0 }, + "3725": { "label": "16/83", "naklon": null }, + "3716": { "label": "16/84", "naklon": 0 }, + "3696": { "label": "16/85", "naklon": null }, + "3702": { "label": "16/86", "naklon": 0 }, + "3706": { "label": "16/87", "naklon": null }, + "3850": { "label": "16/88", "naklon": 0 }, + "3848": { "label": "16/89", "naklon": null }, + "3737": { "label": "16/90", "naklon": null }, + "3705": { "label": "16/91", "naklon": 0 }, + "3723": { "label": "16/92", "naklon": null }, + "3842": { "label": "16/93", "naklon": 0 }, + "3735": { "label": "16/94", "naklon": null }, + "3719": { "label": "16/95", "naklon": 0 }, + "3697": { "label": "16/96", "naklon": 0 }, + "3711": { "label": "16/97", "naklon": 0 }, + "4107": { "label": "16/98", "naklon": null }, + "4112": { "label": "16/99", "naklon": 5 }, + "4106": { "label": "16/100", "naklon": 5 }, + "4111": { "label": "16/101", "naklon": 5 }, + "4091": { "label": "16/102", "naklon": null }, + "4104": { "label": "16/103", "naklon": 5 }, + "4094": { "label": "16/104", "naklon": null }, + "4089": { "label": "16/105", "naklon": 5 }, + "4095": { "label": "16/106", "naklon": null }, + "4102": { "label": "16/107", "naklon": 5 }, + "4105": { "label": "16/108", "naklon": null }, + "3859": { "label": "16/109", "naklon": null }, + "4090": { "label": "16/110", "naklon": 5 }, + "4110": { "label": "16/111", "naklon": null }, + "4097": { "label": "16/112", "naklon": 5 }, + "4099": { "label": "16/113", "naklon": null }, + "4096": { "label": "16/114", "naklon": null }, + "4101": { "label": "16/115", "naklon": 5 }, + "4109": { "label": "16/116", "naklon": null }, + "4092": { "label": "16/117", "naklon": 5 }, + "3631": { "label": "16/118", "naklon": null }, + "3632": { "label": "16/119", "naklon": 0 }, + "3641": { "label": "16/120", "naklon": null }, + "3638": { "label": "16/121", "naklon": 0 }, + "3637": { "label": "16/122", "naklon": null }, + "4142": { "label": "16/123", "naklon": null }, + "4147": { "label": "16/124", "naklon": 5 }, + "4139": { "label": "16/125", "naklon": 5 }, + "3172": { "label": "20/30A", "naklon": 2 }, + "3164": { "label": "20/30B", "naklon": 2 }, + "3247": { "label": "20/1", "naklon": 10 }, + "3296": { "label": "20/2", "naklon": 10 }, + "3246": { "label": "20/3", "naklon": 10 }, + "3270": { "label": "20/4", "naklon": 10 }, + "3294": { "label": "20/5", "naklon": 10 }, + "3298": { "label": "20/6", "naklon": 10 }, + "3297": { "label": "20/7", "naklon": 10 }, + "3293": { "label": "20/8", "naklon": 10 }, + "3299": { "label": "20/9", "naklon": 10 }, + "3295": { "label": "20/10", "naklon": 10 }, + "3244": { "label": "20/11", "naklon": 10 }, + "3249": { "label": "20/12", "naklon": 10 }, + "3268": { "label": "20/13", "naklon": 10 }, + "3245": { "label": "20/14", "naklon": 10 }, + "3278": { "label": "20/15", "naklon": 10 }, + "3280": { "label": "20/16", "naklon": 10 }, + "3292": { "label": "20/17", "naklon": 10 }, + "3287": { "label": "20/18", "naklon": 10 }, + "3282": { "label": "20/19", "naklon": 10 }, + "3273": { "label": "20/20", "naklon": 0 }, + "3157": { "label": "20/21", "naklon": 0 }, + "3283": { "label": "20/22", "naklon": 0 }, + "3159": { "label": "20/23", "naklon": 0 }, + "3289": { "label": "20/24", "naklon": 0 }, + "3163": { "label": "20/25", "naklon": 0 }, + "3126": { "label": "20/26", "naklon": 0 }, + "3171": { "label": "20/27", "naklon": 0 }, + "3162": { "label": "20/28", "naklon": 0 }, + "3279": { "label": "20/29", "naklon": 10 }, + "3173": { "label": "20/31", "naklon": 0 }, + "3127": { "label": "20/32", "naklon": 0 }, + "3131": { "label": "20/33", "naklon": 0 }, + "3129": { "label": "20/34", "naklon": 0 }, + "3276": { "label": "20/35", "naklon": 2 }, + "3290": { "label": "20/36", "naklon": 2 }, + "3132": { "label": "20/37", "naklon": 0 }, + "3138": { "label": "20/38", "naklon": 0 }, + "3272": { "label": "20/39", "naklon": 0 }, + "3291": { "label": "20/40", "naklon": 0 }, + "3277": { "label": "20/41", "naklon": 10 }, + "3286": { "label": "20/42", "naklon": 10 }, + "3281": { "label": "20/43", "naklon": 10 }, + "3288": { "label": "20/44", "naklon": 10 }, + "3284": { "label": "20/45", "naklon": 10 }, + "3167": { "label": "20/46", "naklon": 10 }, + "3872": { "label": "20/47", "naklon": 0 }, + "3124": { "label": "20/48", "naklon": 0 }, + "3133": { "label": "20/49", "naklon": 0 }, + "3158": { "label": "20/50", "naklon": 0 }, + "3169": { "label": "20/51", "naklon": 0 }, + "3146": { "label": "20/52", "naklon": 0 }, + "3160": { "label": "20/53", "naklon": 0 }, + "3248": { "label": "20/54", "naklon": 0 }, + "3156": { "label": "20/55", "naklon": 0 }, + "3161": { "label": "20/56", "naklon": 0 }, + "3170": { "label": "20/57", "naklon": 0 }, + "3168": { "label": "20/58", "naklon": 0 }, + "3125": { "label": "20/59", "naklon": 0 }, + "3166": { "label": "20/60", "naklon": 0 }, + "3130": { "label": "20/61", "naklon": 0 }, + "3563": { "label": "20/62", "naklon": 0 }, + "3550": { "label": "20/63", "naklon": null }, + "3269": { "label": "20/67", "naklon": 0 }, + "2921": { "label": "21/1", "naklon": 0 }, + "2707": { "label": "21/2", "naklon": 0 }, + "2723": { "label": "21/3", "naklon": 0 }, + "2716": { "label": "21/4", "naklon": 0 }, + "2717": { "label": "21/5", "naklon": 0 }, + "2720": { "label": "21/6", "naklon": 0 }, + "2722": { "label": "21/7", "naklon": 0 }, + "2718": { "label": "21/8", "naklon": 0 }, + "2724": { "label": "21/9", "naklon": 0 }, + "2742": { "label": "21/10", "naklon": 0 }, + "2743": { "label": "21/11", "naklon": 0 }, + "2733": { "label": "21/12", "naklon": 0 }, + "2903": { "label": "21/14", "naklon": 0 }, + "2917": { "label": "21/15", "naklon": 0 }, + "2897": { "label": "21/16", "naklon": 0 }, + "2914": { "label": "21/17", "naklon": 0 }, + "2898": { "label": "21/18", "naklon": 0 }, + "2773": { "label": "21/19", "naklon": 0 }, + "2895": { "label": "21/20", "naklon": 0 }, + "2896": { "label": "21/21", "naklon": 0 }, + "2771": { "label": "21/22", "naklon": 0 }, + "2772": { "label": "21/23", "naklon": 0 }, + "2793": { "label": "21/24", "naklon": 0 }, + "2902": { "label": "21/25", "naklon": 0 }, + "2910": { "label": "21/26", "naklon": 0 }, + "2909": { "label": "21/27", "naklon": 0 }, + "2920": { "label": "21/28", "naklon": 0 }, + "2916": { "label": "21/29", "naklon": 0 }, + "2904": { "label": "21/30", "naklon": 0 }, + "2915": { "label": "21/31", "naklon": 0 }, + "2905": { "label": "21/32", "naklon": 0 }, + "2900": { "label": "21/33", "naklon": 0 }, + "2899": { "label": "21/34", "naklon": 0 }, + "2741": { "label": "21/36", "naklon": 0 }, + "2714": { "label": "21/37", "naklon": 0 }, + "2701": { "label": "21/38", "naklon": 0 }, + "2703": { "label": "21/39", "naklon": 0 }, + "2704": { "label": "21/40", "naklon": 0 }, + "2702": { "label": "21/41", "naklon": 0 }, + "2706": { "label": "21/42", "naklon": 0 }, + "2776": { "label": "21/43", "naklon": 0 }, + "2770": { "label": "21/44", "naklon": 0 }, + "2786": { "label": "21/45", "naklon": 0 }, + "2779": { "label": "21/46", "naklon": 0 }, + "2782": { "label": "21/47", "naklon": 0 }, + "2785": { "label": "21/48", "naklon": 0 }, + "2769": { "label": "21/49", "naklon": 0 }, + "3354": { "label": "21/50", "naklon": 0 }, + "2778": { "label": "21/51", "naklon": 0 }, + "2775": { "label": "21/52", "naklon": 0 }, + "2780": { "label": "21/53", "naklon": 0 }, + "2790": { "label": "21/54", "naklon": 0 }, + "2792": { "label": "21/55", "naklon": 0 }, + "2774": { "label": "21/56", "naklon": 0 }, + "2630": { "label": "22/1", "naklon": 0 }, + "2631": { "label": "22/2", "naklon": 0 }, + "2632": { "label": "22/3", "naklon": 0 }, + "2633": { "label": "22/4", "naklon": 0 }, + "2634": { "label": "22/5", "naklon": 0 }, + "2636": { "label": "22/6", "naklon": 0 }, + "4367": { "label": "22/7", "naklon": 0 }, + "2637": { "label": "22/8", "naklon": 0 }, + "2638": { "label": "22/9", "naklon": 0 }, + "2639": { "label": "22/10", "naklon": 0 }, + "2640": { "label": "22/11", "naklon": 0 }, + "2641": { "label": "22/12", "naklon": 0 }, + "2642": { "label": "22/13", "naklon": 0 }, + "2643": { "label": "22/14", "naklon": 0 }, + "2644": { "label": "22/15", "naklon": 0 }, + "2645": { "label": "22/16", "naklon": 0 }, + "2646": { "label": "22/17", "naklon": 0 }, + "2647": { "label": "22/18", "naklon": 0 }, + "2648": { "label": "22/19", "naklon": 0 }, + "2649": { "label": "22/20", "naklon": 0 }, + "2650": { "label": "22/21", "naklon": 0 }, + "2651": { "label": "22/22", "naklon": 0 }, + "4103": { "label": "22/23", "naklon": 0 }, + "2653": { "label": "22/24", "naklon": 0 }, + "2654": { "label": "22/25", "naklon": 0 }, + "2655": { "label": "22/26", "naklon": 0 }, + "2656": { "label": "22/27", "naklon": 0 }, + "2657": { "label": "22/28", "naklon": 0 }, + "2658": { "label": "22/29", "naklon": 0 }, + "2659": { "label": "22/30", "naklon": 0 }, + "2660": { "label": "22/31", "naklon": 0 }, + "2661": { "label": "22/32", "naklon": 0 }, + "3015": { "label": "22/32/1", "naklon": 0 }, + "2662": { "label": "22/33", "naklon": 0 }, + "2663": { "label": "22/34", "naklon": 0 }, + "2664": { "label": "22/35", "naklon": 0 }, + "2665": { "label": "22/36", "naklon": 0 }, + "2666": { "label": "22/37", "naklon": 0 }, + "2667": { "label": "22/38", "naklon": 0 }, + "2668": { "label": "22/39", "naklon": 0 }, + "2669": { "label": "22/40", "naklon": null }, + "2670": { "label": "22/41", "naklon": null }, + "2671": { "label": "22/42", "naklon": null }, + "3087": { "label": "23/9A", "naklon": 10 }, + "3090": { "label": "23/9B", "naklon": 10 }, + "3075": { "label": "23/1", "naklon": 0 }, + "3089": { "label": "23/2", "naklon": 0 }, + "3088": { "label": "23/3", "naklon": 0 }, + "3228": { "label": "23/4", "naklon": 10 }, + "2751": { "label": "23/5", "naklon": 10 }, + "3243": { "label": "23/6", "naklon": 10 }, + "4349": { "label": "23/7", "naklon": 10 }, + "3102": { "label": "23/8", "naklon": 10 }, + "3099": { "label": "23/10", "naklon": 10 }, + "3103": { "label": "23/11", "naklon": 10 }, + "3093": { "label": "23/12", "naklon": 10 }, + "3098": { "label": "23/13", "naklon": 10 }, + "3092": { "label": "23/14", "naklon": 10 }, + "3233": { "label": "23/15", "naklon": 0 }, + "3095": { "label": "23/16", "naklon": 0 }, + "4074": { "label": "23/17", "naklon": 0 }, + "2729": { "label": "23/18", "naklon": 0 }, + "3234": { "label": "23/19", "naklon": 0 }, + "3094": { "label": "23/20", "naklon": 0 }, + "2817": { "label": "23/21", "naklon": 0 }, + "3226": { "label": "23/22", "naklon": 0 }, + "3225": { "label": "23/23", "naklon": 0 }, + "3237": { "label": "23/24", "naklon": 0 }, + "4250": { "label": "23/25", "naklon": 0 }, + "3059": { "label": "23/26", "naklon": 10 }, + "3238": { "label": "23/27", "naklon": 10 }, + "3242": { "label": "23/28", "naklon": 10 }, + "3236": { "label": "23/29", "naklon": 10 }, + "3112": { "label": "23/30", "naklon": 10 }, + "3224": { "label": "23/31", "naklon": 0 }, + "4298": { "label": "23/32", "naklon": 10 }, + "4150": { "label": "23/33", "naklon": 10 }, + "3091": { "label": "23/34", "naklon": 10 }, + "3771": { "label": "25/1", "naklon": 5 }, + "3777": { "label": "25/2", "naklon": 5 }, + "3749": { "label": "25/3", "naklon": 5 }, + "3769": { "label": "25/4", "naklon": 5 }, + "3765": { "label": "25/5", "naklon": 5 }, + "3785": { "label": "25/6", "naklon": 5 }, + "3761": { "label": "25/7", "naklon": 5 }, + "3758": { "label": "25/8", "naklon": 5 }, + "3766": { "label": "25/9", "naklon": 5 }, + "3779": { "label": "25/10", "naklon": 5 }, + "3899": { "label": "25/11", "naklon": 10 }, + "3922": { "label": "25/12", "naklon": 10 }, + "3912": { "label": "25/13", "naklon": 10 }, + "3933": { "label": "25/14", "naklon": 10 }, + "3921": { "label": "25/15", "naklon": 10 }, + "4300": { "label": "25/16", "naklon": 10 }, + "3927": { "label": "25/17", "naklon": 10 }, + "3212": { "label": "25/18", "naklon": 10 }, + "3208": { "label": "25/19", "naklon": 10 }, + "3207": { "label": "25/20", "naklon": 10 }, + "4294": { "label": "25/21", "naklon": 10 }, + "3209": { "label": "25/22", "naklon": 10 }, + "3745": { "label": "25/23", "naklon": 10 }, + "3762": { "label": "25/24", "naklon": 10 }, + "3215": { "label": "25/25", "naklon": 10 }, + "3210": { "label": "25/26", "naklon": 10 }, + "3211": { "label": "25/27", "naklon": 10 }, + "3206": { "label": "25/28", "naklon": 10 }, + "3918": { "label": "25/29", "naklon": 5 }, + "3928": { "label": "25/30", "naklon": 5 }, + "3917": { "label": "25/31", "naklon": 5 }, + "4029": { "label": "25/32", "naklon": 0 }, + "4038": { "label": "25/33", "naklon": 0 }, + "4022": { "label": "25/34", "naklon": 0 }, + "3937": { "label": "25/35", "naklon": 0 }, + "3190": { "label": "25/36", "naklon": 0 }, + "3835": { "label": "25/37", "naklon": 0 }, + "3201": { "label": "25/38", "naklon": 0 }, + "3193": { "label": "25/39", "naklon": 0 }, + "3191": { "label": "25/40", "naklon": 0 }, + "3203": { "label": "25/41", "naklon": 0 }, + "4301": { "label": "25/42", "naklon": 0 }, + "3223": { "label": "25/43", "naklon": 0 }, + "3202": { "label": "25/44", "naklon": 0 }, + "3205": { "label": "25/45", "naklon": 0 }, + "3194": { "label": "25/46", "naklon": 0 }, + "3198": { "label": "25/47", "naklon": 0 }, + "3204": { "label": "25/48", "naklon": 0 }, + "3200": { "label": "25/49", "naklon": 0 }, + "3216": { "label": "25/50", "naklon": 0 }, + "3932": { "label": "25/51", "naklon": 5 }, + "3923": { "label": "25/52", "naklon": 5 }, + "3913": { "label": "25/53", "naklon": 5 }, + "3900": { "label": "25/54", "naklon": 5 }, + "4189": { "label": "25/55", "naklon": 10 }, + "4191": { "label": "25/56", "naklon": 10 }, + "3790": { "label": "25/57", "naklon": 10 }, + "4190": { "label": "25/58", "naklon": 10 }, + "4302": { "label": "25/59", "naklon": 0 }, + "4351": { "label": "25/60", "naklon": 0 }, + "4075": { "label": "25/61", "naklon": 0 }, + "4071": { "label": "25/62", "naklon": 0 }, + "3784": { "label": "25/63", "naklon": 0 }, + "4065": { "label": "25/64", "naklon": 0 }, + "4297": { "label": "25/65", "naklon": 0 }, + "4295": { "label": "25/66", "naklon": 0 }, + "4299": { "label": "25/67", "naklon": 0 }, + "3772": { "label": "25/68", "naklon": 0 }, + "3941": { "label": "25/69", "naklon": 0 }, + "3782": { "label": "25/70", "naklon": 0 }, + "4068": { "label": "25/71", "naklon": 0 }, + "4073": { "label": "25/72", "naklon": 0 }, + "3901": { "label": "25/73", "naklon": 5 }, + "4296": { "label": "25/74", "naklon": 5 }, + "3910": { "label": "25/75", "naklon": 5 }, + "4293": { "label": "25/76", "naklon": 5 }, + "3919": { "label": "25/77", "naklon": 5 }, + "3924": { "label": "25/78", "naklon": 5 }, + "3909": { "label": "25/79", "naklon": 5 }, + "3896": { "label": "25/80", "naklon": 5 }, + "3911": { "label": "25/81", "naklon": 5 }, + "2819": { "label": "25/82", "naklon": 15 }, + "3776": { "label": "25/83", "naklon": 15 }, + "3752": { "label": "25/84", "naklon": 15 }, + "4353": { "label": "25/85", "naklon": 15 }, + "3791": { "label": "25/86", "naklon": 0 }, + "3770": { "label": "25/87", "naklon": 0 }, + "3760": { "label": "25/88", "naklon": 0 }, + "3115": { "label": "25/89", "naklon": 0 }, + "3738": { "label": "25/90", "naklon": 0 }, + "3748": { "label": "25/91", "naklon": 0 }, + "3753": { "label": "25/92", "naklon": 0 }, + "3775": { "label": "25/93", "naklon": 0 }, + "3778": { "label": "25/94", "naklon": 5 }, + "4078": { "label": "25/95", "naklon": 5 }, + "4088": { "label": "25/96", "naklon": 5 }, + "3856": { "label": "25/97", "naklon": 5 }, + "4084": { "label": "25/98", "naklon": 5 }, + "4069": { "label": "25/99", "naklon": 5 }, + "4188": { "label": "25/100", "naklon": 5 }, + "4064": { "label": "25/101", "naklon": 5 }, + "3792": { "label": "25/102", "naklon": 5 }, + "3780": { "label": "25/103", "naklon": 5 }, + "4034": { "label": "25/104", "naklon": 5 }, + "4072": { "label": "25/105", "naklon": 5 }, + "3884": { "label": "25/106", "naklon": 5 }, + "3793": { "label": "25/107", "naklon": 5 }, + "3863": { "label": "25/108", "naklon": 5 }, + "3855": { "label": "25/109", "naklon": 5 }, + "3846": { "label": "33/1", "naklon": 0 }, + "3943": { "label": "33/2", "naklon": 0 }, + "3903": { "label": "33/3", "naklon": 0 }, + "3982": { "label": "33/4", "naklon": 0 }, + "3879": { "label": "33/5", "naklon": 0 }, + "3887": { "label": "33/6", "naklon": 0 }, + "3920": { "label": "33/7", "naklon": 5 }, + "3942": { "label": "33/8", "naklon": 5 }, + "3829": { "label": "33/9", "naklon": null }, + "3452": { "label": "34/79A", "naklon": 6 }, + "3460": { "label": "34/79B", "naklon": 6 }, + "3443": { "label": "34/90A", "naklon": 6 }, + "3445": { "label": "34/90B", "naklon": 6 }, + "3457": { "label": "34/90C", "naklon": 6 }, + "3461": { "label": "34/97A", "naklon": 6 }, + "3463": { "label": "34/97B", "naklon": 6 }, + "3426": { "label": "34/98A", "naklon": 6 }, + "3444": { "label": "34/98B", "naklon": 6 }, + "3453": { "label": "34/99A", "naklon": 6 }, + "3455": { "label": "34/99B", "naklon": 6 }, + "4009": { "label": "34/1", "naklon": 0 }, + "3602": { "label": "34/2", "naklon": 0 }, + "3441": { "label": "34/3", "naklon": 0 }, + "3464": { "label": "34/4", "naklon": 0 }, + "3883": { "label": "34/5", "naklon": 0 }, + "4098": { "label": "34/6", "naklon": 0 }, + "4003": { "label": "34/7", "naklon": 0 }, + "4004": { "label": "34/8", "naklon": 0 }, + "3888": { "label": "34/9", "naklon": 0 }, + "3997": { "label": "34/10", "naklon": 0 }, + "4006": { "label": "34/11", "naklon": 0 }, + "4000": { "label": "34/12", "naklon": 0 }, + "4011": { "label": "34/13", "naklon": 0 }, + "3999": { "label": "34/14", "naklon": 0 }, + "3981": { "label": "34/15", "naklon": 0 }, + "3988": { "label": "34/16", "naklon": 0 }, + "3986": { "label": "34/17", "naklon": 0 }, + "3998": { "label": "34/18", "naklon": 0 }, + "3983": { "label": "34/19", "naklon": 0 }, + "4005": { "label": "34/20", "naklon": 0 }, + "4001": { "label": "34/21", "naklon": 0 }, + "4008": { "label": "34/22", "naklon": 0 }, + "4002": { "label": "34/23", "naklon": 0 }, + "3996": { "label": "34/24", "naklon": 0 }, + "4007": { "label": "34/25", "naklon": 0 }, + "4113": { "label": "34/26", "naklon": 15 }, + "3595": { "label": "34/27", "naklon": 5 }, + "3599": { "label": "34/28", "naklon": 5 }, + "3601": { "label": "34/29", "naklon": 5 }, + "4205": { "label": "34/30", "naklon": 0 }, + "3987": { "label": "34/31", "naklon": null }, + "4214": { "label": "34/32", "naklon": 0 }, + "4226": { "label": "34/33", "naklon": 0 }, + "4209": { "label": "34/34", "naklon": 0 }, + "4201": { "label": "34/35", "naklon": 0 }, + "3440": { "label": "34/36", "naklon": 0 }, + "3465": { "label": "34/37", "naklon": 0 }, + "3446": { "label": "34/38", "naklon": 0 }, + "4039": { "label": "34/39", "naklon": 5 }, + "4057": { "label": "34/40", "naklon": 5 }, + "3985": { "label": "34/41", "naklon": 0 }, + "3882": { "label": "34/42", "naklon": 0 }, + "4040": { "label": "34/43", "naklon": 5 }, + "3231": { "label": "34/44", "naklon": 0 }, + "3227": { "label": "34/45", "naklon": 0 }, + "3431": { "label": "34/46", "naklon": 0 }, + "4013": { "label": "34/47", "naklon": 0 }, + "4045": { "label": "34/48", "naklon": 0 }, + "3949": { "label": "34/49", "naklon": 0 }, + "3953": { "label": "34/50", "naklon": 0 }, + "3952": { "label": "34/51", "naklon": 0 }, + "3995": { "label": "34/52", "naklon": 0 }, + "3992": { "label": "34/53", "naklon": 0 }, + "4198": { "label": "34/54", "naklon": 0 }, + "3935": { "label": "34/55", "naklon": 0 }, + "4050": { "label": "34/56", "naklon": 0 }, + "4049": { "label": "34/57", "naklon": 0 }, + "4054": { "label": "34/58", "naklon": 0 }, + "3663": { "label": "34/59", "naklon": 6 }, + "3661": { "label": "34/60", "naklon": 6 }, + "3664": { "label": "34/61", "naklon": 6 }, + "3660": { "label": "34/62", "naklon": 6 }, + "3662": { "label": "34/63", "naklon": 6 }, + "3665": { "label": "34/65", "naklon": 6 }, + "3667": { "label": "34/66", "naklon": 6 }, + "3675": { "label": "34/67", "naklon": 6 }, + "3666": { "label": "34/68", "naklon": 6 }, + "3652": { "label": "34/69", "naklon": 6 }, + "3458": { "label": "34/70", "naklon": 6 }, + "4425": { "label": "34/70/1", "naklon": 6 }, + "3459": { "label": "34/71", "naklon": 6 }, + "3435": { "label": "34/72", "naklon": 6 }, + "3448": { "label": "34/73", "naklon": 6 }, + "3451": { "label": "34/74", "naklon": 6 }, + "3442": { "label": "34/75", "naklon": 6 }, + "3449": { "label": "34/76", "naklon": 6 }, + "3450": { "label": "34/77", "naklon": 6 }, + "3433": { "label": "34/78", "naklon": 6 }, + "3432": { "label": "34/80", "naklon": 12 }, + "3470": { "label": "34/81", "naklon": 12 }, + "3438": { "label": "34/82", "naklon": 12 }, + "3439": { "label": "34/83", "naklon": 12 }, + "4028": { "label": "34/84", "naklon": 5 }, + "3596": { "label": "34/85", "naklon": 5 }, + "4021": { "label": "34/86", "naklon": 5 }, + "3437": { "label": "34/87", "naklon": 12 }, + "3428": { "label": "34/88", "naklon": 12 }, + "3430": { "label": "34/89", "naklon": 12 }, + "3454": { "label": "34/91", "naklon": 6 }, + "3492": { "label": "34/92", "naklon": 6 }, + "3462": { "label": "34/93", "naklon": 6 }, + "3427": { "label": "34/94", "naklon": 6 }, + "3434": { "label": "34/95", "naklon": 6 }, + "3456": { "label": "34/96", "naklon": 6 }, + "4307": { "label": "34/98/1", "naklon": 6 }, + "3968": { "label": "35/1", "naklon": 0 }, + "3969": { "label": "35/2", "naklon": 0 }, + "3947": { "label": "35/3", "naklon": 0 }, + "3979": { "label": "35/4", "naklon": 0 }, + "3959": { "label": "35/5", "naklon": 0 }, + "3948": { "label": "35/6", "naklon": 0 }, + "3961": { "label": "35/7", "naklon": 0 }, + "3956": { "label": "35/8", "naklon": 0 }, + "3604": { "label": "35/9", "naklon": 0 }, + "3944": { "label": "35/10", "naklon": 0 }, + "3960": { "label": "35/11", "naklon": 0 }, + "3958": { "label": "35/12", "naklon": 0 }, + "4036": { "label": "35/13", "naklon": 5 }, + "3893": { "label": "35/18", "naklon": 5 }, + "4108": { "label": "35/19", "naklon": 5 }, + "4017": { "label": "35/20", "naklon": 5 }, + "3963": { "label": "35/21", "naklon": 0 }, + "3658": { "label": "35/22", "naklon": 0 }, + "3975": { "label": "35/23", "naklon": 0 }, + "3980": { "label": "35/24", "naklon": 0 }, + "4012": { "label": "35/25", "naklon": 0 }, + "3655": { "label": "35/26", "naklon": 0 }, + "3962": { "label": "35/27", "naklon": 0 }, + "3945": { "label": "35/28", "naklon": 0 }, + "3569": { "label": "35/29", "naklon": 0 }, + "3429": { "label": "35/30", "naklon": 0 }, + "3657": { "label": "35/31", "naklon": 0 }, + "3646": { "label": "35/32", "naklon": 0 }, + "3622": { "label": "35/33", "naklon": 0 }, + "3612": { "label": "35/34", "naklon": 0 }, + "3955": { "label": "35/35", "naklon": 0 }, + "3878": { "label": "35/37", "naklon": 0 }, + "3965": { "label": "35/38", "naklon": 0 }, + "3970": { "label": "35/39", "naklon": 0 }, + "3611": { "label": "35/40", "naklon": 0 }, + "2635": { "label": "35/41", "naklon": 0 }, + "3978": { "label": "35/42", "naklon": 0 }, + "4213": { "label": "35/43", "naklon": 0 }, + "3984": { "label": "35/44", "naklon": 0 }, + "4218": { "label": "35/45", "naklon": 0 }, + "3973": { "label": "35/46", "naklon": 0 }, + "3974": { "label": "35/47", "naklon": 0 }, + "3759": { "label": "35/48", "naklon": 0 }, + "3844": { "label": "35/49", "naklon": 0 }, + "3804": { "label": "35/50", "naklon": 0 }, + "3831": { "label": "35/51", "naklon": 0 }, + "3643": { "label": "35/52", "naklon": 0 }, + "3966": { "label": "35/53", "naklon": 0 }, + "3971": { "label": "35/54", "naklon": 0 }, + "3650": { "label": "35/55", "naklon": 6 }, + "3651": { "label": "35/56", "naklon": 6 }, + "3669": { "label": "35/57", "naklon": 6 }, + "3648": { "label": "35/58", "naklon": 6 }, + "3645": { "label": "35/59", "naklon": 6 }, + "3659": { "label": "35/60", "naklon": 6 }, + "3647": { "label": "35/61", "naklon": 6 }, + "3644": { "label": "35/62", "naklon": 6 }, + "3671": { "label": "35/63", "naklon": 6 }, + "3682": { "label": "35/64", "naklon": 6 }, + "3672": { "label": "35/65", "naklon": 6 }, + "3683": { "label": "35/66", "naklon": 6 }, + "3673": { "label": "35/67", "naklon": 6 }, + "3674": { "label": "35/68", "naklon": 6 }, + "3679": { "label": "35/69", "naklon": 6 }, + "3649": { "label": "35/70", "naklon": 6 }, + "3687": { "label": "35/71", "naklon": 6 }, + "3677": { "label": "35/72", "naklon": 6 }, + "3690": { "label": "35/73", "naklon": 6 }, + "3691": { "label": "35/74", "naklon": 6 }, + "3676": { "label": "35/75", "naklon": 6 }, + "3680": { "label": "35/76", "naklon": 6 }, + "3668": { "label": "35/77", "naklon": 6 }, + "3681": { "label": "35/78", "naklon": 6 }, + "3670": { "label": "35/79", "naklon": 6 }, + "3689": { "label": "35/80", "naklon": 6 }, + "3678": { "label": "35/81", "naklon": 6 }, + "3693": { "label": "35/82", "naklon": 6 }, + "3654": { "label": "35/83", "naklon": null }, + "4086": { "label": "36/1", "naklon": 0 }, + "4085": { "label": "36/2", "naklon": 0 }, + "4083": { "label": "36/3", "naklon": 0 }, + "4087": { "label": "36/4", "naklon": 0 }, + "4077": { "label": "36/5", "naklon": 0 }, + "4082": { "label": "36/6", "naklon": 0 }, + "4186": { "label": "36/7", "naklon": 0 }, + "4206": { "label": "36/8", "naklon": 0 }, + "4080": { "label": "36/9", "naklon": 0 }, + "4081": { "label": "36/10", "naklon": 0 }, + "4210": { "label": "36/11", "naklon": 0 }, + "4079": { "label": "36/12", "naklon": 0 }, + "4076": { "label": "36/13", "naklon": 0 }, + "3852": { "label": "36/14", "naklon": 0 }, + "2813": { "label": "36/15", "naklon": 0 }, + "4219": { "label": "36/16", "naklon": 0 }, + "3104": { "label": "37/1A", "naklon": 15 }, + "3121": { "label": "37/1B", "naklon": 15 }, + "3113": { "label": "37/2", "naklon": 10 }, + "3118": { "label": "37/3", "naklon": 10 }, + "3111": { "label": "37/4", "naklon": 10 }, + "4020": { "label": "37/5", "naklon": 10 }, + "3119": { "label": "37/6", "naklon": 10 }, + "3110": { "label": "37/7", "naklon": 10 }, + "3108": { "label": "37/8", "naklon": 10 }, + "3107": { "label": "37/12", "naklon": 0 }, + "3199": { "label": "37/13", "naklon": 0 }, + "3120": { "label": "37/14", "naklon": 0 }, + "3122": { "label": "37/15", "naklon": 0 }, + "3908": { "label": "37/16", "naklon": 0 }, + "3114": { "label": "37/17", "naklon": 0 }, + "3105": { "label": "37/18", "naklon": 0 }, + "3116": { "label": "37/19", "naklon": 0 }, + "3106": { "label": "37/20", "naklon": 0 }, + "2887": { "label": "37/21", "naklon": 5 }, + "2888": { "label": "37/22", "naklon": 5 }, + "2877": { "label": "37/23", "naklon": 5 }, + "2891": { "label": "37/24", "naklon": 5 }, + "2886": { "label": "37/25", "naklon": 5 }, + "2892": { "label": "37/26", "naklon": 5 }, + "2882": { "label": "37/27", "naklon": 5 }, + "2883": { "label": "37/28", "naklon": 5 }, + "2876": { "label": "37/29", "naklon": 5 }, + "3109": { "label": "37/30", "naklon": 5 }, + "4152": { "label": "37/31", "naklon": 5 }, + "3117": { "label": "37/32", "naklon": 5 }, + "2870": { "label": "37/33", "naklon": 5 }, + "2867": { "label": "37/34", "naklon": 0 }, + "2865": { "label": "37/35", "naklon": 0 }, + "3096": { "label": "37/36", "naklon": 0 }, + "2871": { "label": "37/37", "naklon": 0 }, + "2884": { "label": "37/38", "naklon": 0 }, + "2855": { "label": "37/39", "naklon": 0 }, + "2878": { "label": "37/40", "naklon": 0 }, + "2889": { "label": "37/41", "naklon": 0 }, + "2879": { "label": "37/42", "naklon": 0 }, + "2850": { "label": "37/43", "naklon": 0 }, + "2894": { "label": "37/44", "naklon": 0 }, + "2880": { "label": "37/45", "naklon": 0 }, + "2893": { "label": "37/46", "naklon": 0 }, + "2890": { "label": "37/47", "naklon": 0 }, + "4355": { "label": "37/48", "naklon": 0 }, + "2885": { "label": "37/49", "naklon": 0 }, + "2875": { "label": "37/50", "naklon": 0 }, + "3486": { "label": "38/30A", "naklon": 5 }, + "3714": { "label": "38/30B", "naklon": 0 }, + "3483": { "label": "38/32A", "naklon": 5 }, + "3496": { "label": "38/32B", "naklon": 0 }, + "3487": { "label": "38/35A", "naklon": 5 }, + "3498": { "label": "38/35B", "naklon": 5 }, + "3578": { "label": "38/38A", "naklon": 5 }, + "3508": { "label": "38/38B", "naklon": 5 }, + "3787": { "label": "38/59A", "naklon": 5 }, + "3491": { "label": "38/59B", "naklon": 5 }, + "3568": { "label": "38/1", "naklon": null }, + "3502": { "label": "38/2", "naklon": 0 }, + "3836": { "label": "38/3", "naklon": 0 }, + "3588": { "label": "38/4", "naklon": 0 }, + "3493": { "label": "38/5", "naklon": 0 }, + "3580": { "label": "38/6", "naklon": 0 }, + "3572": { "label": "38/7", "naklon": 0 }, + "3506": { "label": "38/8", "naklon": 0 }, + "3503": { "label": "38/9", "naklon": 0 }, + "3579": { "label": "38/10", "naklon": 0 }, + "3586": { "label": "38/11", "naklon": 0 }, + "3495": { "label": "38/12", "naklon": 5 }, + "3492": { "label": "38/13", "naklon": 5 }, + "3532": { "label": "38/14", "naklon": 5 }, + "3574": { "label": "38/15", "naklon": 5 }, + "4140": { "label": "38/16", "naklon": 5 }, + "3795": { "label": "38/17", "naklon": 5 }, + "3788": { "label": "38/18", "naklon": 5 }, + "3796": { "label": "38/19", "naklon": 5 }, + "3797": { "label": "38/20", "naklon": 5 }, + "3798": { "label": "38/21", "naklon": 5 }, + "3786": { "label": "38/22", "naklon": 5 }, + "4067": { "label": "38/23", "naklon": 5 }, + "3773": { "label": "38/24", "naklon": 5 }, + "3774": { "label": "38/25", "naklon": 5 }, + "3789": { "label": "38/26", "naklon": 5 }, + "3520": { "label": "38/27", "naklon": null }, + "3577": { "label": "38/29", "naklon": 5 }, + "3530": { "label": "38/31", "naklon": null }, + "3488": { "label": "38/33", "naklon": 5 }, + "3505": { "label": "38/34", "naklon": 5 }, + "3497": { "label": "38/36", "naklon": 5 }, + "3490": { "label": "38/37", "naklon": 5 }, + "3585": { "label": "38/39", "naklon": 5 }, + "3582": { "label": "38/40", "naklon": 5 }, + "3507": { "label": "38/41", "naklon": 5 }, + "3484": { "label": "38/42", "naklon": 5 }, + "3501": { "label": "38/43", "naklon": 5 }, + "3581": { "label": "38/44", "naklon": 5 }, + "4192": { "label": "38/45", "naklon": 5 }, + "3576": { "label": "38/46", "naklon": 5 }, + "3489": { "label": "38/47", "naklon": 5 }, + "3573": { "label": "38/48", "naklon": 5 }, + "3504": { "label": "38/49", "naklon": 5 }, + "3794": { "label": "38/50", "naklon": 5 }, + "3485": { "label": "38/51", "naklon": 5 }, + "3482": { "label": "38/52", "naklon": 5 }, + "3575": { "label": "38/53", "naklon": 5 }, + "3499": { "label": "38/54", "naklon": 5 }, + "3494": { "label": "38/55", "naklon": 5 }, + "3583": { "label": "38/56", "naklon": 5 }, + "3570": { "label": "38/57", "naklon": 5 }, + "3500": { "label": "38/58", "naklon": 0 }, + "3510": { "label": "38/63", "naklon": null }, + "3512": { "label": "38/64", "naklon": null }, + "3535": { "label": "38/67", "naklon": null }, + "3531": { "label": "38/68", "naklon": null }, + "3537": { "label": "38/69", "naklon": null }, + "3522": { "label": "39/1", "naklon": 10 }, + "4018": { "label": "39/2", "naklon": 10 }, + "4019": { "label": "39/3", "naklon": 10 }, + "4154": { "label": "39/4", "naklon": 5 }, + "3907": { "label": "39/5", "naklon": 5 }, + "4148": { "label": "39/6", "naklon": 0 }, + "4153": { "label": "39/7", "naklon": 0 }, + "3938": { "label": "39/8", "naklon": 0 }, + "3802": { "label": "39/9", "naklon": 0 }, + "4015": { "label": "39/10", "naklon": 0 }, + "3929": { "label": "39/11", "naklon": 0 }, + "3946": { "label": "39/12", "naklon": 0 }, + "4014": { "label": "39/13", "naklon": 0 }, + "4155": { "label": "39/14", "naklon": 0 }, + "4149": { "label": "39/15", "naklon": 0 }, + "3642": { "label": "39/16", "naklon": 0 }, + "3636": { "label": "39/17", "naklon": 5 }, + "3991": { "label": "39/18", "naklon": 0 }, + "3994": { "label": "39/19", "naklon": 0 }, + "3990": { "label": "39/20", "naklon": 0 }, + "3967": { "label": "39/21", "naklon": 0 }, + "3977": { "label": "39/22", "naklon": 0 }, + "3757": { "label": "39/23", "naklon": 15 }, + "3633": { "label": "39/24", "naklon": 15 }, + "3744": { "label": "39/25", "naklon": 15 }, + "4023": { "label": "39/26", "naklon": 5 }, + "3720": { "label": "39/27", "naklon": 5 }, + "3734": { "label": "39/28", "naklon": 5 }, + "3741": { "label": "39/29", "naklon": 5 }, + "3721": { "label": "39/30", "naklon": 5 }, + "3845": { "label": "39/31", "naklon": 0 }, + "3840": { "label": "39/32", "naklon": 0 }, + "3837": { "label": "39/33", "naklon": null }, + "3839": { "label": "39/34", "naklon": 0 }, + "3542": { "label": "41/1", "naklon": null }, + "3566": { "label": "41/2", "naklon": null }, + "3548": { "label": "41/3", "naklon": null }, + "3515": { "label": "41/4", "naklon": null }, + "3559": { "label": "41/5", "naklon": null }, + "3509": { "label": "41/6", "naklon": null }, + "3524": { "label": "41/7", "naklon": null }, + "3518": { "label": "41/8", "naklon": null }, + "3182": { "label": "41/9", "naklon": null }, + "3187": { "label": "41/10", "naklon": null }, + "3195": { "label": "41/11", "naklon": 0 }, + "3857": { "label": "41/12", "naklon": 0 }, + "3183": { "label": "41/13", "naklon": 0 }, + "3177": { "label": "41/14", "naklon": 0 }, + "3189": { "label": "41/15", "naklon": 0 }, + "3186": { "label": "41/16", "naklon": 0 }, + "3178": { "label": "42/1", "naklon": 0 }, + "3219": { "label": "42/2", "naklon": 0 }, + "3475": { "label": "42/3", "naklon": 0 }, + "3175": { "label": "42/4", "naklon": 0 }, + "3222": { "label": "42/5", "naklon": 0 }, + "3221": { "label": "42/6", "naklon": 0 }, + "3181": { "label": "42/7", "naklon": 0 }, + "3180": { "label": "42/8", "naklon": 0 }, + "3218": { "label": "42/9", "naklon": 0 }, + "3176": { "label": "42/10", "naklon": 0 }, + "3174": { "label": "42/11", "naklon": 0 }, + "3220": { "label": "42/12", "naklon": 0 }, + "3533": { "label": "42/13", "naklon": null }, + "3543": { "label": "42/14", "naklon": null }, + "3554": { "label": "42/15", "naklon": null }, + "3549": { "label": "42/16", "naklon": null }, + "2857": { "label": "43/1", "naklon": 5 }, + "2752": { "label": "43/2", "naklon": 5 }, + "2753": { "label": "43/3", "naklon": 5 }, + "3024": { "label": "43/4", "naklon": 5 }, + "2754": { "label": "43/5", "naklon": 5 }, + "4423": { "label": "43/6", "naklon": 5 }, + "4368": { "label": "43/7", "naklon": 5 }, + "2978": { "label": "43/8", "naklon": 5 }, + "2868": { "label": "43/9", "naklon": 5 }, + "4377": { "label": "43/10", "naklon": 5 }, + "2757": { "label": "43/11", "naklon": 5 }, + "2970": { "label": "43/12", "naklon": 5 }, + "2758": { "label": "43/13", "naklon": 5 }, + "4378": { "label": "43/14", "naklon": 5 }, + "2759": { "label": "43/15", "naklon": 5 }, + "4342": { "label": "43/16", "naklon": 5 }, + "3026": { "label": "43/17", "naklon": null }, + "2986": { "label": "43/18", "naklon": null }, + "4343": { "label": "43/19", "naklon": null }, + "2760": { "label": "43/20", "naklon": null }, + "4379": { "label": "43/21", "naklon": null }, + "2971": { "label": "43/22", "naklon": null }, + "2761": { "label": "43/23", "naklon": null }, + "2762": { "label": "43/24", "naklon": null }, + "4339": { "label": "43/25", "naklon": null }, + "4380": { "label": "43/26", "naklon": null }, + "2975": { "label": "43/27", "naklon": null }, + "3003": { "label": "43/28", "naklon": null }, + "4338": { "label": "43/29", "naklon": null }, + "3002": { "label": "43/30", "naklon": null }, + "4345": { "label": "43/31", "naklon": null }, + "2979": { "label": "43/32", "naklon": null }, + "2989": { "label": "43/33", "naklon": null }, + "2996": { "label": "43/34", "naklon": null }, + "2972": { "label": "43/35", "naklon": null }, + "2988": { "label": "43/36", "naklon": null }, + "4344": { "label": "43/37", "naklon": null }, + "3022": { "label": "43/38", "naklon": null }, + "4341": { "label": "43/39", "naklon": null }, + "2983": { "label": "43/40", "naklon": null }, + "2995": { "label": "43/41", "naklon": null }, + "2763": { "label": "43/42", "naklon": null }, + "2764": { "label": "43/43", "naklon": null }, + "2765": { "label": "43/44", "naklon": null }, + "2766": { "label": "43/45", "naklon": null }, + "2767": { "label": "43/46", "naklon": null }, + "2768": { "label": "43/47", "naklon": null }, + "3018": { "label": "43/48", "naklon": null }, + "2982": { "label": "43/49", "naklon": null }, + "3019": { "label": "43/50", "naklon": 0 }, + "3013": { "label": "43/51", "naklon": null }, + "3007": { "label": "43/52", "naklon": null }, + "2980": { "label": "43/53", "naklon": null }, + "3011": { "label": "43/54", "naklon": null }, + "2672": { "label": "43/55", "naklon": null }, + "2673": { "label": "43/56", "naklon": null }, + "2674": { "label": "43/57", "naklon": null }, + "2675": { "label": "43/58", "naklon": null }, + "2676": { "label": "43/59", "naklon": null }, + "2677": { "label": "43/60", "naklon": null }, + "2678": { "label": "43/61", "naklon": null }, + "2679": { "label": "43/62", "naklon": null }, + "2680": { "label": "43/63", "naklon": null }, + "2840": { "label": "43/64", "naklon": null }, + "2682": { "label": "43/65", "naklon": null }, + "2683": { "label": "43/66", "naklon": null }, + "2684": { "label": "43/67", "naklon": 0 }, + "2685": { "label": "43/68", "naklon": null }, + "2686": { "label": "43/69", "naklon": null }, + "2687": { "label": "43/70", "naklon": null }, + "2688": { "label": "43/71", "naklon": null }, + "2689": { "label": "43/72", "naklon": null }, + "2690": { "label": "43/73", "naklon": null }, + "2691": { "label": "43/74", "naklon": null }, + "2692": { "label": "43/75", "naklon": null }, + "2693": { "label": "43/76", "naklon": 0 }, + "2694": { "label": "43/77", "naklon": null }, + "2695": { "label": "43/78", "naklon": null }, + "2696": { "label": "43/79", "naklon": 0 }, + "2697": { "label": "43/80", "naklon": null }, + "2698": { "label": "43/81", "naklon": 0 }, + "2699": { "label": "43/82", "naklon": null }, + "2700": { "label": "43/83", "naklon": 0 }, + "2744": { "label": "43/84", "naklon": null }, + "2745": { "label": "43/85", "naklon": 0 }, + "2746": { "label": "43/86", "naklon": null }, + "2747": { "label": "43/87", "naklon": 0 }, + "2748": { "label": "43/88", "naklon": null }, + "2749": { "label": "43/89", "naklon": 0 }, + "2841": { "label": "43/90", "naklon": null }, + "4237": { "label": "45/1", "naklon": 5 }, + "4226": { "label": "45/2", "naklon": 5 }, + "4242": { "label": "45/3", "naklon": 5 }, + "4179": { "label": "45/4", "naklon": 5 }, + "4247": { "label": "45/5", "naklon": 5 }, + "4245": { "label": "45/6", "naklon": 5 }, + "3872": { "label": "45/7", "naklon": 5 }, + "4175": { "label": "45/8", "naklon": 5 }, + "4236": { "label": "45/9", "naklon": 5 }, + "4170": { "label": "45/10", "naklon": 5 }, + "4238": { "label": "45/11", "naklon": 5 }, + "4246": { "label": "45/12", "naklon": 5 }, + "4166": { "label": "45/13", "naklon": 5 }, + "4227": { "label": "45/14", "naklon": 5 }, + "4171": { "label": "45/15", "naklon": 5 }, + "4180": { "label": "45/16", "naklon": 5 }, + "4244": { "label": "45/17", "naklon": 5 }, + "4199": { "label": "45/18", "naklon": 5 }, + "4239": { "label": "45/19", "naklon": 5 }, + "4207": { "label": "45/20", "naklon": 5 }, + "4223": { "label": "45/21", "naklon": 5 }, + "4230": { "label": "45/22", "naklon": 5 }, + "4233": { "label": "45/23", "naklon": 5 }, + "4222": { "label": "45/24", "naklon": 5 }, + "4217": { "label": "45/25", "naklon": 5 }, + "4243": { "label": "45/26", "naklon": 5 }, + "4200": { "label": "45/27", "naklon": 5 }, + "4228": { "label": "45/28", "naklon": 5 }, + "4211": { "label": "45/29", "naklon": 5 }, + "4234": { "label": "45/30", "naklon": 5 }, + "4235": { "label": "45/31", "naklon": 5 }, + "4203": { "label": "45/32", "naklon": 5 }, + "4240": { "label": "45/33", "naklon": 5 }, + "4224": { "label": "45/34", "naklon": 5 }, + "4232": { "label": "45/35", "naklon": 5 }, + "4231": { "label": "45/36", "naklon": 5 }, + "4161": { "label": "45/37", "naklon": 5 }, + "4225": { "label": "45/38", "naklon": 5 }, + "4241": { "label": "45/39", "naklon": 5 }, + "4229": { "label": "45/40", "naklon": 5 }, + "4221": { "label": "45/41", "naklon": 5 }, + "4212": { "label": "45/42", "naklon": 5 }, + "4216": { "label": "45/43", "naklon": 5 }, + "3864": { "label": "45/44", "naklon": null }, + "3806": { "label": "46/1", "naklon": 5 }, + "3813": { "label": "46/2", "naklon": 5 }, + "3815": { "label": "46/3", "naklon": 5 }, + "3807": { "label": "46/4", "naklon": 5 }, + "3895": { "label": "46/5", "naklon": 5 }, + "3809": { "label": "46/6", "naklon": 5 }, + "3820": { "label": "46/7", "naklon": 5 }, + "3805": { "label": "46/8", "naklon": 5 }, + "3894": { "label": "46/9", "naklon": 0 }, + "4055": { "label": "46/10", "naklon": 0 }, + "3812": { "label": "46/11", "naklon": 5 }, + "3822": { "label": "46/12", "naklon": 5 }, + "3821": { "label": "46/13", "naklon": 5 }, + "3808": { "label": "46/14", "naklon": 5 }, + "3799": { "label": "46/15", "naklon": 5 }, + "3816": { "label": "46/16", "naklon": 5 }, + "3751": { "label": "46/17", "naklon": 5 }, + "3814": { "label": "46/18", "naklon": 5 }, + "4044": { "label": "46/19", "naklon": 0 }, + "3931": { "label": "46/20", "naklon": 0 }, + "3902": { "label": "46/21", "naklon": 5 }, + "3916": { "label": "46/22", "naklon": 5 }, + "3892": { "label": "46/23", "naklon": 5 }, + "3914": { "label": "46/24", "naklon": 5 }, + "3898": { "label": "46/25", "naklon": 5 }, + "3897": { "label": "46/26", "naklon": 5 }, + "3885": { "label": "46/27", "naklon": 5 }, + "3906": { "label": "46/28", "naklon": 5 }, + "3930": { "label": "46/29", "naklon": 0 }, + "3936": { "label": "46/30", "naklon": 0 }, + "3860": { "label": "46/31", "naklon": 5 }, + "3841": { "label": "46/32", "naklon": 5 }, + "3873": { "label": "46/33", "naklon": 5 }, + "3854": { "label": "46/34", "naklon": 5 }, + "3939": { "label": "46/35", "naklon": 5 }, + "3858": { "label": "46/36", "naklon": 5 }, + "3940": { "label": "46/37", "naklon": 5 }, + "4035": { "label": "46/38", "naklon": 5 }, + "3373": { "label": "47/1", "naklon": 0 }, + "3374": { "label": "47/2", "naklon": 0 }, + "3384": { "label": "47/3", "naklon": 0 }, + "3385": { "label": "47/4", "naklon": 0 }, + "4051": { "label": "48/1", "naklon": 5 }, + "4041": { "label": "48/2", "naklon": 5 }, + "4056": { "label": "48/3", "naklon": 5 }, + "3875": { "label": "48/4", "naklon": 5 }, + "4061": { "label": "48/5", "naklon": 5 }, + "4047": { "label": "48/6", "naklon": 5 }, + "4060": { "label": "48/7", "naklon": 5 }, + "4059": { "label": "48/8", "naklon": 5 }, + "4058": { "label": "48/9", "naklon": 5 }, + "3635": { "label": "48/10", "naklon": 5 }, + "3640": { "label": "48/11", "naklon": 5 }, + "3747": { "label": "48/12", "naklon": 5 }, + "3629": { "label": "48/13", "naklon": 5 }, + "4048": { "label": "48/14", "naklon": 5 }, + "4063": { "label": "48/15", "naklon": 5 }, + "4062": { "label": "48/16", "naklon": 5 }, + "4043": { "label": "48/17", "naklon": 5 }, + "4052": { "label": "48/18", "naklon": 5 }, + "4042": { "label": "48/19", "naklon": 5 }, + "4053": { "label": "48/20", "naklon": 5 }, + "4167": { "label": "50/15A", "naklon": null }, + "4159": { "label": "50/15B", "naklon": null }, + "4183": { "label": "50/1", "naklon": 0 }, + "4157": { "label": "50/2", "naklon": 0 }, + "4160": { "label": "50/3", "naklon": 0 }, + "4173": { "label": "50/4", "naklon": 0 }, + "4177": { "label": "50/5", "naklon": 0 }, + "4174": { "label": "50/6", "naklon": 0 }, + "4178": { "label": "50/7", "naklon": 0 }, + "4195": { "label": "50/8", "naklon": 0 }, + "4169": { "label": "50/9", "naklon": 0 }, + "4162": { "label": "50/10", "naklon": 0 }, + "4158": { "label": "50/11", "naklon": 0 }, + "4182": { "label": "50/12", "naklon": 0 }, + "4194": { "label": "50/13", "naklon": 0 }, + "4184": { "label": "50/14", "naklon": 0 }, + "4197": { "label": "50/16", "naklon": null }, + "4164": { "label": "50/17", "naklon": null }, + "3306": { "label": "50/18", "naklon": null }, + "4168": { "label": "50/19", "naklon": null }, + "4193": { "label": "50/20", "naklon": null }, + "4187": { "label": "50/21", "naklon": null }, + "4163": { "label": "50/22", "naklon": null }, + "4165": { "label": "50/23", "naklon": null }, + "4185": { "label": "50/24", "naklon": null }, + "3904": { "label": "50/25", "naklon": null }, + "2619": { "label": "53/1", "naklon": 0 }, + "2623": { "label": "53/2", "naklon": 0 }, + "2617": { "label": "53/3", "naklon": 0 }, + "2622": { "label": "53/4", "naklon": 0 }, + "2618": { "label": "53/5", "naklon": 0 }, + "2626": { "label": "53/6", "naklon": 0 }, + "2869": { "label": "53/7", "naklon": 0 }, + "2613": { "label": "53/8", "naklon": 0 }, + "2608": { "label": "53/9", "naklon": 0 }, + "2611": { "label": "53/10", "naklon": 0 }, + "2598": { "label": "53/11", "naklon": 0 }, + "3528": { "label": "53/12", "naklon": 0 }, + "3545": { "label": "53/13", "naklon": 0 }, + "2620": { "label": "53/14", "naklon": 0 }, + "2612": { "label": "53/15", "naklon": 0 }, + "2615": { "label": "53/16", "naklon": 0 }, + "3722": { "label": "53/17", "naklon": 0 }, + "2624": { "label": "53/18", "naklon": 0 }, + "2609": { "label": "53/19", "naklon": 0 }, + "2625": { "label": "53/20", "naklon": 0 }, + "2602": { "label": "53/21", "naklon": 0 }, + "2610": { "label": "53/22", "naklon": 0 }, + "2599": { "label": "53/23", "naklon": 0 }, + "2605": { "label": "53/24", "naklon": 0 }, + "2593": { "label": "53/25", "naklon": 0 }, + "3074": { "label": "53/26", "naklon": 0 }, + "2740": { "label": "53/27", "naklon": 0 }, + "2614": { "label": "53/28", "naklon": 0 }, + "2601": { "label": "53/29", "naklon": 0 }, + "4196": { "label": "53/30", "naklon": 0 }, + "2607": { "label": "53/31", "naklon": 0 }, + "2582": { "label": "53/32", "naklon": 0 }, + "2594": { "label": "53/33", "naklon": 0 }, + "2589": { "label": "53/34", "naklon": 0 }, + "2596": { "label": "53/35", "naklon": 0 }, + "2603": { "label": "53/36", "naklon": 0 }, + "2597": { "label": "53/37", "naklon": 0 }, + "2590": { "label": "53/38", "naklon": 0 }, + "2581": { "label": "53/39", "naklon": 0 }, + "2583": { "label": "53/40", "naklon": 0 }, + "2580": { "label": "53/41", "naklon": 0 }, + "2579": { "label": "53/42", "naklon": 0 }, + "2797": { "label": "53/43", "naklon": 0 }, + "2577": { "label": "53/44", "naklon": 0 }, + "2586": { "label": "53/45", "naklon": 0 }, + "2588": { "label": "53/46", "naklon": 0 }, + "2591": { "label": "53/47", "naklon": 0 }, + "2592": { "label": "53/48", "naklon": 0 }, + "2573": { "label": "53/49", "naklon": 0 }, + "2595": { "label": "53/50", "naklon": 0 }, + "2587": { "label": "53/51", "naklon": 0 }, + "2578": { "label": "53/52", "naklon": 0 }, + "2574": { "label": "53/53", "naklon": 0 }, + "2571": { "label": "53/54", "naklon": 0 }, + "2570": { "label": "53/55", "naklon": 0 }, + "2576": { "label": "53/56", "naklon": 0 }, + "2881": { "label": "53/57", "naklon": 0 }, + "2575": { "label": "53/58", "naklon": 0 }, + "2572": { "label": "53/59", "naklon": 0 }, + "2569": { "label": "53/60", "naklon": 0 }, + "4324": { "label": "55/1", "naklon": 0 }, + "4319": { "label": "55/2", "naklon": 0 }, + "4327": { "label": "55/3", "naklon": 0 }, + "4333": { "label": "55/4", "naklon": 0 }, + "4332": { "label": "55/5", "naklon": 0 }, + "4320": { "label": "55/6", "naklon": 0 }, + "4317": { "label": "55/7", "naklon": 0 }, + "4318": { "label": "55/8", "naklon": 0 }, + "4328": { "label": "55/9", "naklon": 0 }, + "4323": { "label": "55/10", "naklon": 0 }, + "4325": { "label": "55/11", "naklon": 0 }, + "4326": { "label": "55/12", "naklon": 0 }, + "4316": { "label": "55/13", "naklon": 0 }, + "4322": { "label": "55/14", "naklon": 0 }, + "4331": { "label": "55/15", "naklon": 0 }, + "4321": { "label": "55/16", "naklon": 0 }, + "4315": { "label": "55/17", "naklon": 0 }, + "4329": { "label": "55/18", "naklon": 0 }, + "4334": { "label": "55/19", "naklon": 0 }, + "4330": { "label": "55/20", "naklon": 0 } +}; + + +let svetlaSorted = [{ "label": "1/3A", "node": 3993, "naklon": 0 }, +{ "label": "1/3B", "node": 3989, "naklon": 15 }, +{ "label": "1/1", "node": 3976, "naklon": 0 }, +{ "label": "1/2", "node": 4181, "naklon": 0 }, +{ "label": "1/4", "node": 4376, "naklon": 15 }, +{ "label": "1/5", "node": 3868, "naklon": 15 }, +{ "label": "1/6", "node": 3728, "naklon": 15 }, +{ "label": "1/7", "node": 3730, "naklon": 0 }, +{ "label": "1/8", "node": 4374, "naklon": 0 }, +{ "label": "1/9", "node": 3718, "naklon": 15 }, +{ "label": "1/10", "node": 4375, "naklon": 15 }, +{ "label": "1/11", "node": 4172, "naklon": 15 }, +{ "label": "1/12", "node": 4176, "naklon": 15 }, +{ "label": "2/1", "node": 3800, "naklon": 5 }, +{ "label": "2/2", "node": 3823, "naklon": 5 }, +{ "label": "2/3", "node": 3905, "naklon": 5 }, +{ "label": "2/4", "node": 3803, "naklon": 5 }, +{ "label": "2/5", "node": 3817, "naklon": 5 }, +{ "label": "2/6", "node": 3818, "naklon": 5 }, +{ "label": "2/7", "node": 3811, "naklon": 5 }, +{ "label": "2/8", "node": 3915, "naklon": 5 }, +{ "label": "2/9", "node": 3843, "naklon": 10 }, +{ "label": "2/10", "node": 3827, "naklon": 10 }, +{ "label": "2/11", "node": 4220, "naklon": 10 }, +{ "label": "2/12", "node": 3826, "naklon": 10 }, +{ "label": "2/13", "node": 3834, "naklon": 10 }, +{ "label": "2/14", "node": 3838, "naklon": 10 }, +{ "label": "2/15", "node": 2823, "naklon": 10 }, +{ "label": "2/16", "node": 3750, "naklon": 10 }, +{ "label": "2/17", "node": 3378, "naklon": 0 }, +{ "label": "2/18", "node": 3376, "naklon": 0 }, +{ "label": "2/19", "node": 3379, "naklon": 0 }, +{ "label": "2/20", "node": 3285, "naklon": 0 }, +{ "label": "2/21", "node": 3382, "naklon": 0 }, +{ "label": "2/22", "node": 3383, "naklon": 0 }, +{ "label": "2/24", "node": 3375, "naklon": 0 }, +{ "label": "2/25", "node": 3381, "naklon": 0 }, +{ "label": "2/26", "node": 3380, "naklon": 0 }, +{ "label": "2/27", "node": 3828, "naklon": 10 }, +{ "label": "2/28", "node": 3377, "naklon": 0 }, +{ "label": "7/1", "node": 3591, "naklon": 0 }, +{ "label": "7/2", "node": 3587, "naklon": 0 }, +{ "label": "7/3", "node": 3468, "naklon": 0 }, +{ "label": "7/4", "node": 3466, "naklon": 0 }, +{ "label": "7/5", "node": 3474, "naklon": 0 }, +{ "label": "7/6", "node": 3481, "naklon": 0 }, +{ "label": "7/7", "node": 3589, "naklon": 0 }, +{ "label": "7/8", "node": 3472, "naklon": 0 }, +{ "label": "7/9", "node": 3473, "naklon": 0 }, +{ "label": "7/10", "node": 3584, "naklon": 0 }, +{ "label": "7/11", "node": 3571, "naklon": 0 }, +{ "label": "7/12", "node": 3476, "naklon": 0 }, +{ "label": "7/13", "node": 3590, "naklon": 0 }, +{ "label": "7/14", "node": 3478, "naklon": 0 }, +{ "label": "7/15", "node": 3471, "naklon": 0 }, +{ "label": "7/16", "node": 3467, "naklon": 0 }, +{ "label": "7/17", "node": 3479, "naklon": 0 }, +{ "label": "7/18", "node": 3480, "naklon": 0 }, +{ "label": "7/19", "node": 3477, "naklon": 0 }, +{ "label": "12/1", "node": 3362, "naklon": 0 }, +{ "label": "12/2", "node": 3355, "naklon": 0 }, +{ "label": "12/3", "node": 3356, "naklon": 0 }, +{ "label": "12/4", "node": 3349, "naklon": 0 }, +{ "label": "12/5", "node": 3357, "naklon": 0 }, +{ "label": "12/6", "node": 3350, "naklon": 0 }, +{ "label": "12/7", "node": 3353, "naklon": 0 }, +{ "label": "12/8", "node": 3539, "naklon": 0 }, +{ "label": "12/9", "node": 3050, "naklon": 0 }, +{ "label": "12/10", "node": 3361, "naklon": 0 }, +{ "label": "12/11", "node": 3360, "naklon": 0 }, +{ "label": "12/12", "node": 3358, "naklon": 0 }, +{ "label": "12/13", "node": 3541, "naklon": 0 }, +{ "label": "12/14", "node": 3551, "naklon": 0 }, +{ "label": "12/15", "node": 3514, "naklon": 0 }, +{ "label": "12/16", "node": 3547, "naklon": 0 }, +{ "label": "12/17", "node": 3562, "naklon": 0 }, +{ "label": "12/18", "node": 3525, "naklon": 0 }, +{ "label": "12/19", "node": 3558, "naklon": 0 }, +{ "label": "12/20", "node": 3511, "naklon": 0 }, +{ "label": "12/21", "node": 3058, "naklon": 0 }, +{ "label": "12/22", "node": 3062, "naklon": 0 }, +{ "label": "12/23", "node": 3070, "naklon": 0 }, +{ "label": "12/24", "node": 3447, "naklon": 0 }, +{ "label": "12/25", "node": 3056, "naklon": 0 }, +{ "label": "12/26", "node": 3057, "naklon": 0 }, +{ "label": "12/27", "node": 3071, "naklon": 0 }, +{ "label": "12/28", "node": 3061, "naklon": 0 }, +{ "label": "12/29", "node": 3069, "naklon": 0 }, +{ "label": "12/30", "node": 3077, "naklon": 0 }, +{ "label": "12/31", "node": 3080, "naklon": 0 }, +{ "label": "12/32", "node": 3081, "naklon": 0 }, +{ "label": "12/33", "node": 3078, "naklon": 0 }, +{ "label": "12/34", "node": 4037, "naklon": 0 }, +{ "label": "12/35", "node": 3067, "naklon": 0 }, +{ "label": "12/36", "node": 3051, "naklon": 0 }, +{ "label": "12/37", "node": 2924, "naklon": 0 }, +{ "label": "12/38", "node": 3060, "naklon": 0 }, +{ "label": "12/39", "node": 3073, "naklon": 0 }, +{ "label": "12/40", "node": 3469, "naklon": 0 }, +{ "label": "12/41", "node": 2923, "naklon": 0 }, +{ "label": "12/42", "node": 2925, "naklon": 0 }, +{ "label": "12/43", "node": 3359, "naklon": 0 }, +{ "label": "12/44", "node": 3055, "naklon": 0 }, +{ "label": "12/45", "node": 2922, "naklon": 0 }, +{ "label": "12/46", "node": 3084, "naklon": 0 }, +{ "label": "12/47", "node": 3064, "naklon": 0 }, +{ "label": "12/48", "node": 3066, "naklon": 0 }, +{ "label": "12/49", "node": 3072, "naklon": 0 }, +{ "label": "13/13A", "node": 3415, "naklon": 0 }, +{ "label": "13/13B", "node": 3409, "naklon": 0 }, +{ "label": "13/13C", "node": 3399, "naklon": 0 }, +{ "label": "13/29A", "node": 3410, "naklon": 0 }, +{ "label": "13/29B", "node": 3407, "naklon": 0 }, +{ "label": "13/34A", "node": 3405, "naklon": 0 }, +{ "label": "13/34B", "node": 3404, "naklon": 0 }, +{ "label": "13/45A", "node": 3392, "naklon": 0 }, +{ "label": "13/45B", "node": 3386, "naklon": 0 }, +{ "label": "13/60A", "node": 3303, "naklon": 3 }, +{ "label": "13/60B", "node": 3302, "naklon": 3 }, +{ "label": "13/70A", "node": 3319, "naklon": 6 }, +{ "label": "13/70B", "node": 3317, "naklon": 6 }, +{ "label": "13/70C", "node": 3326, "naklon": 6 }, +{ "label": "13/73A", "node": 3351, "naklon": 6 }, +{ "label": "13/73B", "node": 3313, "naklon": 6 }, +{ "label": "13/83A", "node": 3316, "naklon": 0 }, +{ "label": "13/83B", "node": 3320, "naklon": 0 }, +{ "label": "13/95A", "node": 3336, "naklon": 0 }, +{ "label": "13/95B", "node": 3323, "naklon": 0 }, +{ "label": "13/98A", "node": 3339, "naklon": 0 }, +{ "label": "13/98B", "node": 3333, "naklon": 0 }, +{ "label": "13/1", "node": 3425, "naklon": 0 }, +{ "label": "13/2", "node": 3419, "naklon": 0 }, +{ "label": "13/3", "node": 3416, "naklon": 0 }, +{ "label": "13/4", "node": 3332, "naklon": 0 }, +{ "label": "13/5", "node": 3422, "naklon": 0 }, +{ "label": "13/6", "node": 3417, "naklon": 0 }, +{ "label": "13/7", "node": 3418, "naklon": 0 }, +{ "label": "13/8", "node": 3424, "naklon": 0 }, +{ "label": "13/9", "node": 3334, "naklon": 0 }, +{ "label": "13/10", "node": 4363, "naklon": 0 }, +{ "label": "13/11", "node": 3423, "naklon": 0 }, +{ "label": "13/12", "node": 3406, "naklon": 0 }, +{ "label": "13/14", "node": 3411, "naklon": 0 }, +{ "label": "13/15", "node": 3412, "naklon": 0 }, +{ "label": "13/16", "node": 3413, "naklon": 0 }, +{ "label": "13/17", "node": 3414, "naklon": 0 }, +{ "label": "13/18", "node": 3391, "naklon": 0 }, +{ "label": "13/19", "node": 3370, "naklon": 0 }, +{ "label": "13/20", "node": 3369, "naklon": 0 }, +{ "label": "13/21", "node": 3408, "naklon": 0 }, +{ "label": "13/22", "node": 3393, "naklon": 0 }, +{ "label": "13/23", "node": 3128, "naklon": 0 }, +{ "label": "13/24", "node": 3197, "naklon": 0 }, +{ "label": "13/25", "node": 4364, "naklon": 0 }, +{ "label": "13/26", "node": 3155, "naklon": 0 }, +{ "label": "13/27", "node": 3196, "naklon": 0 }, +{ "label": "13/28", "node": 3144, "naklon": 0 }, +{ "label": "13/30", "node": 3150, "naklon": 0 }, +{ "label": "13/31", "node": 3390, "naklon": 0 }, +{ "label": "13/32", "node": 3401, "naklon": 0 }, +{ "label": "13/33", "node": 3275, "naklon": 0 }, +{ "label": "13/35", "node": 3371, "naklon": 0 }, +{ "label": "13/36", "node": 3389, "naklon": 0 }, +{ "label": "13/37", "node": 3388, "naklon": 0 }, +{ "label": "13/38", "node": 3365, "naklon": 0 }, +{ "label": "13/39", "node": 3363, "naklon": 0 }, +{ "label": "13/40", "node": 3397, "naklon": 0 }, +{ "label": "13/40/1", "node": 3567, "naklon": 0 }, +{ "label": "13/41", "node": 3387, "naklon": 0 }, +{ "label": "13/42", "node": 3403, "naklon": 0 }, +{ "label": "13/43", "node": 3147, "naklon": 0 }, +{ "label": "13/44", "node": 3141, "naklon": 0 }, +{ "label": "13/46", "node": 3364, "naklon": 0 }, +{ "label": "13/47", "node": 3367, "naklon": 0 }, +{ "label": "13/48", "node": 3368, "naklon": 0 }, +{ "label": "13/49", "node": 3402, "naklon": 0 }, +{ "label": "13/50", "node": 3366, "naklon": 0 }, +{ "label": "13/51", "node": 3395, "naklon": 0 }, +{ "label": "13/52", "node": 3372, "naklon": 0 }, +{ "label": "13/53", "node": 3394, "naklon": 0 }, +{ "label": "13/54", "node": 3308, "naklon": 0 }, +{ "label": "13/54/1", "node": 3847, "naklon": 0 }, +{ "label": "13/55", "node": 3312, "naklon": 3 }, +{ "label": "13/56", "node": 3309, "naklon": 3 }, +{ "label": "13/57", "node": 3311, "naklon": 3 }, +{ "label": "13/58", "node": 3310, "naklon": 3 }, +{ "label": "13/59", "node": 4365, "naklon": 3 }, +{ "label": "13/60/1", "node": 4093, "naklon": 3 }, +{ "label": "13/61", "node": 3304, "naklon": 3 }, +{ "label": "13/62", "node": 3307, "naklon": 3 }, +{ "label": "13/63", "node": 3271, "naklon": 3 }, +{ "label": "13/64", "node": 3301, "naklon": 3 }, +{ "label": "13/65", "node": 4366, "naklon": 3 }, +{ "label": "13/66", "node": 3300, "naklon": 3 }, +{ "label": "13/67", "node": 3185, "naklon": 0 }, +{ "label": "13/68", "node": 3184, "naklon": 0 }, +{ "label": "13/69", "node": 3188, "naklon": 0 }, +{ "label": "13/71", "node": 3343, "naklon": 6 }, +{ "label": "13/71/1", "node": 3819, "naklon": 6 }, +{ "label": "13/71/2", "node": 3880, "naklon": 6 }, +{ "label": "13/72", "node": 3348, "naklon": 6 }, +{ "label": "13/74", "node": 3344, "naklon": 6 }, +{ "label": "13/75", "node": 3346, "naklon": 6 }, +{ "label": "13/75/1", "node": 3597, "naklon": 6 }, +{ "label": "13/76", "node": 3345, "naklon": 6 }, +{ "label": "13/77", "node": 3322, "naklon": 0 }, +{ "label": "13/78", "node": 3325, "naklon": 0 }, +{ "label": "13/78/1", "node": 4310, "naklon": 0 }, +{ "label": "13/79", "node": 3315, "naklon": 0 }, +{ "label": "13/80", "node": 3328, "naklon": 0 }, +{ "label": "13/81", "node": 3321, "naklon": 0 }, +{ "label": "13/82", "node": 3324, "naklon": 0 }, +{ "label": "13/84", "node": 3140, "naklon": 0 }, +{ "label": "13/85", "node": 3153, "naklon": 0 }, +{ "label": "13/86", "node": 3145, "naklon": 0 }, +{ "label": "13/87", "node": 3134, "naklon": 0 }, +{ "label": "13/88", "node": 3151, "naklon": 0 }, +{ "label": "13/89", "node": 3143, "naklon": 0 }, +{ "label": "13/90", "node": 3318, "naklon": 0 }, +{ "label": "13/91", "node": 3347, "naklon": 0 }, +{ "label": "13/94", "node": 3314, "naklon": 0 }, +{ "label": "13/96", "node": 3331, "naklon": 0 }, +{ "label": "13/97", "node": 3327, "naklon": 0 }, +{ "label": "13/99", "node": 3329, "naklon": 0 }, +{ "label": "13/100", "node": 3337, "naklon": 0 }, +{ "label": "13/101", "node": 3330, "naklon": 0 }, +{ "label": "13/102", "node": 3335, "naklon": 0 }, +{ "label": "13/103", "node": 3420, "naklon": 0 }, +{ "label": "13/104", "node": 3421, "naklon": 0 }, +{ "label": "13/105", "node": 4361, "naklon": 0 }, +{ "label": "13/106", "node": 4362, "naklon": 0 }, +{ "label": "13/107", "node": 3526, "naklon": 0 }, +{ "label": "13/108", "node": 4424, "naklon": null }, +{ "label": "13/109", "node": 3561, "naklon": null }, +{ "label": "13/110", "node": 3527, "naklon": null }, +{ "label": "13/111", "node": 3521, "naklon": null }, +{ "label": "13/112", "node": 3552, "naklon": null }, +{ "label": "13/113", "node": 3544, "naklon": null }, +{ "label": "13/114", "node": 3534, "naklon": null }, +{ "label": "13/115", "node": 3516, "naklon": null }, +{ "label": "13/116", "node": 3513, "naklon": null }, +{ "label": "13/117", "node": 3565, "naklon": null }, +{ "label": "13/118", "node": 3866, "naklon": null }, +{ "label": "14/1", "node": 3136, "naklon": 0 }, +{ "label": "14/2", "node": 3137, "naklon": 0 }, +{ "label": "14/3", "node": 3135, "naklon": 0 }, +{ "label": "14/4", "node": 3149, "naklon": 0 }, +{ "label": "14/5", "node": 3142, "naklon": 0 }, +{ "label": "14/6", "node": 3342, "naklon": 0 }, +{ "label": "14/7", "node": 3340, "naklon": 0 }, +{ "label": "14/8", "node": 3152, "naklon": 0 }, +{ "label": "14/9", "node": 3886, "naklon": 0 }, +{ "label": "14/10", "node": 3341, "naklon": null }, +{ "label": "14/11", "node": 3352, "naklon": null }, +{ "label": "15/1", "node": 3396, "naklon": 5 }, +{ "label": "15/2", "node": 2784, "naklon": 5 }, +{ "label": "15/3", "node": 2788, "naklon": 5 }, +{ "label": "15/4", "node": 2801, "naklon": 5 }, +{ "label": "15/5", "node": 2815, "naklon": 5 }, +{ "label": "15/6", "node": 2829, "naklon": 5 }, +{ "label": "15/7", "node": 2796, "naklon": 5 }, +{ "label": "15/8", "node": 2803, "naklon": 5 }, +{ "label": "15/8/1", "node": 4304, "naklon": 5 }, +{ "label": "15/8/2", "node": 4311, "naklon": 5 }, +{ "label": "15/9", "node": 2821, "naklon": 5 }, +{ "label": "15/10", "node": 3400, "naklon": 5 }, +{ "label": "15/11", "node": 2799, "naklon": 5 }, +{ "label": "15/12", "node": 2804, "naklon": 5 }, +{ "label": "15/12/1", "node": 4303, "naklon": 5 }, +{ "label": "15/12/2", "node": 4309, "naklon": 5 }, +{ "label": "15/13", "node": 2806, "naklon": 5 }, +{ "label": "15/14", "node": 2787, "naklon": 5 }, +{ "label": "15/15", "node": 2809, "naklon": 5 }, +{ "label": "15/16", "node": 2814, "naklon": 0 }, +{ "label": "15/17", "node": 3934, "naklon": 0 }, +{ "label": "15/18", "node": 3192, "naklon": 0 }, +{ "label": "15/19", "node": 2812, "naklon": 0 }, +{ "label": "15/20", "node": 4070, "naklon": 0 }, +{ "label": "15/21", "node": 2826, "naklon": 0 }, +{ "label": "15/22", "node": 2808, "naklon": 3 }, +{ "label": "15/23", "node": 2795, "naklon": 3 }, +{ "label": "15/24", "node": 2807, "naklon": 3 }, +{ "label": "15/25", "node": 2831, "naklon": 0 }, +{ "label": "15/26", "node": 2862, "naklon": null }, +{ "label": "15/27", "node": 2861, "naklon": 0 }, +{ "label": "15/28", "node": 2866, "naklon": 0 }, +{ "label": "15/28/1", "node": 3546, "naklon": 0 }, +{ "label": "15/29", "node": 4146, "naklon": 0 }, +{ "label": "15/29/1", "node": 3001, "naklon": 0 }, +{ "label": "15/30", "node": 2835, "naklon": 0 }, +{ "label": "15/31", "node": 2874, "naklon": 0 }, +{ "label": "15/32", "node": 2852, "naklon": 0 }, +{ "label": "15/33", "node": 2851, "naklon": 0 }, +{ "label": "15/33/1", "node": 3560, "naklon": 0 }, +{ "label": "15/34", "node": 2858, "naklon": 0 }, +{ "label": "15/34/1", "node": 4306, "naklon": 0 }, +{ "label": "15/35", "node": 2856, "naklon": 0 }, +{ "label": "15/36", "node": 2847, "naklon": 0 }, +{ "label": "15/36/1", "node": 3556, "naklon": 0 }, +{ "label": "15/37", "node": 3950, "naklon": 0 }, +{ "label": "15/38", "node": 2848, "naklon": 0 }, +{ "label": "15/39", "node": 2863, "naklon": 0 }, +{ "label": "15/39/1", "node": 4313, "naklon": 0 }, +{ "label": "15/40", "node": 2873, "naklon": 0 }, +{ "label": "15/40/1", "node": 2984, "naklon": 0 }, +{ "label": "15/41", "node": 2854, "naklon": 0 }, +{ "label": "15/42", "node": 2859, "naklon": 0 }, +{ "label": "15/43", "node": 2872, "naklon": 0 }, +{ "label": "15/44", "node": 2849, "naklon": 0 }, +{ "label": "15/45", "node": 2864, "naklon": 0 }, +{ "label": "15/46", "node": 3553, "naklon": null }, +{ "label": "15/47", "node": 3021, "naklon": null }, +{ "label": "15/47/1", "node": 3008, "naklon": null }, +{ "label": "15/48", "node": 3017, "naklon": null }, +{ "label": "15/49", "node": 3014, "naklon": null }, +{ "label": "15/50", "node": 2981, "naklon": null }, +{ "label": "15/51", "node": 3020, "naklon": null }, +{ "label": "15/52", "node": 3027, "naklon": null }, +{ "label": "15/53", "node": 3006, "naklon": null }, +{ "label": "15/54", "node": 3012, "naklon": null }, +{ "label": "15/55", "node": 2738, "naklon": 0 }, +{ "label": "15/56", "node": 2725, "naklon": 0 }, +{ "label": "15/57", "node": 3016, "naklon": null }, +{ "label": "15/58", "node": 3005, "naklon": null }, +{ "label": "15/58/1", "node": 3009, "naklon": null }, +{ "label": "15/59", "node": 3010, "naklon": 0 }, +{ "label": "15/59/1", "node": 3538, "naklon": 0 }, +{ "label": "15/59/2", "node": 4145, "naklon": 0 }, +{ "label": "15/60", "node": 2713, "naklon": 0 }, +{ "label": "15/61", "node": 2789, "naklon": 0 }, +{ "label": "15/62", "node": 2736, "naklon": 0 }, +{ "label": "15/63", "node": 2739, "naklon": 0 }, +{ "label": "15/64", "node": 4346, "naklon": 0 }, +{ "label": "15/65", "node": 2731, "naklon": 0 }, +{ "label": "15/66", "node": 2818, "naklon": 0 }, +{ "label": "15/66/1", "node": 3557, "naklon": 0 }, +{ "label": "15/67", "node": 2822, "naklon": 0 }, +{ "label": "15/68", "node": 2833, "naklon": 0 }, +{ "label": "15/69", "node": 2834, "naklon": 0 }, +{ "label": "15/70", "node": 3097, "naklon": 0 }, +{ "label": "15/71", "node": 2824, "naklon": 0 }, +{ "label": "15/72", "node": 2828, "naklon": 0 }, +{ "label": "15/73", "node": 2600, "naklon": 0 }, +{ "label": "15/73/1", "node": 4314, "naklon": 0 }, +{ "label": "15/74", "node": 2832, "naklon": 0 }, +{ "label": "15/75", "node": 4360, "naklon": 0 }, +{ "label": "15/76", "node": 2846, "naklon": 0 }, +{ "label": "15/77", "node": 2584, "naklon": 0 }, +{ "label": "15/78", "node": 2843, "naklon": 0 }, +{ "label": "15/78/1", "node": 4308, "naklon": 0 }, +{ "label": "15/79", "node": 4144, "naklon": null }, +{ "label": "15/80", "node": 2844, "naklon": 0 }, +{ "label": "15/81", "node": 2842, "naklon": 0 }, +{ "label": "15/82", "node": 2838, "naklon": 0 }, +{ "label": "15/83", "node": 2837, "naklon": null }, +{ "label": "15/83/1", "node": 3555, "naklon": null }, +{ "label": "15/84", "node": 2839, "naklon": 0 }, +{ "label": "15/85", "node": 2830, "naklon": 0 }, +{ "label": "15/86", "node": 4066, "naklon": 0 }, +{ "label": "15/87", "node": 2836, "naklon": 0 }, +{ "label": "15/88", "node": 2911, "naklon": 0 }, +{ "label": "15/89", "node": 2825, "naklon": 0 }, +{ "label": "15/90", "node": 2811, "naklon": 0 }, +{ "label": "15/94", "node": 3740, "naklon": 15 }, +{ "label": "15/95", "node": 2734, "naklon": 15 }, +{ "label": "15/96", "node": 3105, "naklon": 15 }, +{ "label": "15/97", "node": 2732, "naklon": 15 }, +{ "label": "15/98", "node": 2727, "naklon": 15 }, +{ "label": "15/99", "node": 2735, "naklon": 15 }, +{ "label": "15/100", "node": 3926, "naklon": 15 }, +{ "label": "15/101", "node": 2918, "naklon": 0 }, +{ "label": "15/102", "node": 2705, "naklon": 10 }, +{ "label": "15/103", "node": 2708, "naklon": 10 }, +{ "label": "15/104", "node": 2721, "naklon": 10 }, +{ "label": "15/105", "node": 2719, "naklon": 10 }, +{ "label": "15/106", "node": 2919, "naklon": 10 }, +{ "label": "15/107", "node": 3101, "naklon": 10 }, +{ "label": "15/108", "node": 2853, "naklon": 10 }, +{ "label": "15/109", "node": 2715, "naklon": 10 }, +{ "label": "15/110", "node": 2712, "naklon": 0 }, +{ "label": "15/111", "node": 2711, "naklon": 0 }, +{ "label": "15/112", "node": 2709, "naklon": 0 }, +{ "label": "15/113", "node": 2710, "naklon": 0 }, +{ "label": "15/114", "node": 2907, "naklon": 0 }, +{ "label": "15/115", "node": 2906, "naklon": 0 }, +{ "label": "15/116", "node": 2908, "naklon": 0 }, +{ "label": "15/117", "node": 2901, "naklon": 0 }, +{ "label": "15/118", "node": 2913, "naklon": 0 }, +{ "label": "15/119", "node": 3656, "naklon": 0 }, +{ "label": "15/120", "node": 2781, "naklon": 0 }, +{ "label": "15/121", "node": 2802, "naklon": 0 }, +{ "label": "15/122", "node": 2791, "naklon": 0 }, +{ "label": "15/123", "node": 2783, "naklon": 0 }, +{ "label": "15/124", "node": 2794, "naklon": 0 }, +{ "label": "15/125", "node": 3139, "naklon": 0 }, +{ "label": "15/126", "node": 3229, "naklon": 5 }, +{ "label": "15/127", "node": 3239, "naklon": 5 }, +{ "label": "15/128", "node": 3230, "naklon": 5 }, +{ "label": "15/129", "node": 4016, "naklon": null }, +{ "label": "16/16A", "node": 3608, "naklon": 0 }, +{ "label": "16/16B", "node": 4151, "naklon": 0 }, +{ "label": "16/1", "node": 3710, "naklon": 0 }, +{ "label": "16/2", "node": 3726, "naklon": 0 }, +{ "label": "16/3", "node": 3743, "naklon": 0 }, +{ "label": "16/4", "node": 3724, "naklon": 0 }, +{ "label": "16/5", "node": 3712, "naklon": 0 }, +{ "label": "16/6", "node": 3739, "naklon": 0 }, +{ "label": "16/7", "node": 3742, "naklon": 0 }, +{ "label": "16/8", "node": 3731, "naklon": 0 }, +{ "label": "16/9", "node": 3727, "naklon": 0 }, +{ "label": "16/10", "node": 3729, "naklon": 0 }, +{ "label": "16/11", "node": 3736, "naklon": 0 }, +{ "label": "16/12", "node": 3713, "naklon": 0 }, +{ "label": "16/13", "node": 3715, "naklon": 0 }, +{ "label": "16/14", "node": 3733, "naklon": 0 }, +{ "label": "16/15", "node": 3732, "naklon": 0 }, +{ "label": "16/17", "node": 3634, "naklon": 0 }, +{ "label": "16/18", "node": 3610, "naklon": 0 }, +{ "label": "16/19", "node": 3626, "naklon": 0 }, +{ "label": "16/20", "node": 3618, "naklon": 0 }, +{ "label": "16/21", "node": 3619, "naklon": 0 }, +{ "label": "16/22", "node": 3628, "naklon": 0 }, +{ "label": "16/23", "node": 3615, "naklon": 0 }, +{ "label": "16/24", "node": 3609, "naklon": 0 }, +{ "label": "16/25", "node": 3606, "naklon": 0 }, +{ "label": "16/26", "node": 3624, "naklon": 0 }, +{ "label": "16/27", "node": 3627, "naklon": 0 }, +{ "label": "16/28", "node": 3607, "naklon": 0 }, +{ "label": "16/29", "node": 4370, "naklon": 0 }, +{ "label": "16/30", "node": 3692, "naklon": 0 }, +{ "label": "16/31", "node": 3614, "naklon": 0 }, +{ "label": "16/32", "node": 3623, "naklon": 0 }, +{ "label": "16/33", "node": 4373, "naklon": 0 }, +{ "label": "16/34", "node": 3620, "naklon": 0 }, +{ "label": "16/35", "node": 3685, "naklon": 0 }, +{ "label": "16/36", "node": 3616, "naklon": 0 }, +{ "label": "16/37", "node": 3686, "naklon": 0 }, +{ "label": "16/38", "node": 3688, "naklon": 0 }, +{ "label": "16/39", "node": 3684, "naklon": 0 }, +{ "label": "16/40", "node": 3825, "naklon": 0 }, +{ "label": "16/41", "node": 3865, "naklon": 0 }, +{ "label": "16/42", "node": 3824, "naklon": 0 }, +{ "label": "16/43", "node": 3871, "naklon": 0 }, +{ "label": "16/44", "node": 3801, "naklon": 0 }, +{ "label": "16/45", "node": 3862, "naklon": 0 }, +{ "label": "16/46", "node": 3876, "naklon": 0 }, +{ "label": "16/47", "node": 3861, "naklon": 0 }, +{ "label": "16/48", "node": 4215, "naklon": 0 }, +{ "label": "16/49", "node": 3605, "naklon": 10 }, +{ "label": "16/50", "node": 3603, "naklon": 10 }, +{ "label": "16/51", "node": 3592, "naklon": 10 }, +{ "label": "16/52", "node": 3598, "naklon": 10 }, +{ "label": "16/53", "node": 3594, "naklon": 10 }, +{ "label": "16/54", "node": 3593, "naklon": 10 }, +{ "label": "16/55", "node": 3630, "naklon": 10 }, +{ "label": "16/56", "node": 3763, "naklon": 10 }, +{ "label": "16/57", "node": 3746, "naklon": 10 }, +{ "label": "16/58", "node": 3699, "naklon": 0 }, +{ "label": "16/59", "node": 3698, "naklon": 0 }, +{ "label": "16/60", "node": 3709, "naklon": null }, +{ "label": "16/61", "node": 3708, "naklon": 0 }, +{ "label": "16/62", "node": 3703, "naklon": null }, +{ "label": "16/63", "node": 3700, "naklon": 0 }, +{ "label": "16/64", "node": 3701, "naklon": null }, +{ "label": "16/65", "node": 3704, "naklon": 0 }, +{ "label": "16/66", "node": 3707, "naklon": null }, +{ "label": "16/67", "node": 3810, "naklon": 0 }, +{ "label": "16/68", "node": 4208, "naklon": null }, +{ "label": "16/69", "node": 3867, "naklon": 0 }, +{ "label": "16/70", "node": 4372, "naklon": null }, +{ "label": "16/71", "node": 3881, "naklon": 0 }, +{ "label": "16/72", "node": 4204, "naklon": null }, +{ "label": "16/73", "node": 3869, "naklon": 0 }, +{ "label": "16/74", "node": 4202, "naklon": null }, +{ "label": "16/75", "node": 3830, "naklon": 0 }, +{ "label": "16/76", "node": 3870, "naklon": null }, +{ "label": "16/77", "node": 3964, "naklon": 0 }, +{ "label": "16/78", "node": 3849, "naklon": 0 }, +{ "label": "16/79", "node": 3694, "naklon": null }, +{ "label": "16/80", "node": 3717, "naklon": 0 }, +{ "label": "16/81", "node": 3877, "naklon": null }, +{ "label": "16/82", "node": 3755, "naklon": 0 }, +{ "label": "16/83", "node": 3725, "naklon": null }, +{ "label": "16/84", "node": 3716, "naklon": 0 }, +{ "label": "16/85", "node": 3696, "naklon": null }, +{ "label": "16/86", "node": 3702, "naklon": 0 }, +{ "label": "16/87", "node": 3706, "naklon": null }, +{ "label": "16/88", "node": 3850, "naklon": 0 }, +{ "label": "16/89", "node": 3848, "naklon": null }, +{ "label": "16/90", "node": 3737, "naklon": null }, +{ "label": "16/91", "node": 3705, "naklon": 0 }, +{ "label": "16/92", "node": 3723, "naklon": null }, +{ "label": "16/93", "node": 3842, "naklon": 0 }, +{ "label": "16/94", "node": 3735, "naklon": null }, +{ "label": "16/95", "node": 3719, "naklon": 0 }, +{ "label": "16/96", "node": 3697, "naklon": 0 }, +{ "label": "16/97", "node": 3711, "naklon": 0 }, +{ "label": "16/98", "node": 4107, "naklon": null }, +{ "label": "16/99", "node": 4112, "naklon": 5 }, +{ "label": "16/100", "node": 4106, "naklon": 5 }, +{ "label": "16/101", "node": 4111, "naklon": 5 }, +{ "label": "16/102", "node": 4091, "naklon": null }, +{ "label": "16/103", "node": 4104, "naklon": 5 }, +{ "label": "16/104", "node": 4094, "naklon": null }, +{ "label": "16/105", "node": 4089, "naklon": 5 }, +{ "label": "16/106", "node": 4095, "naklon": null }, +{ "label": "16/107", "node": 4102, "naklon": 5 }, +{ "label": "16/108", "node": 4105, "naklon": null }, +{ "label": "16/109", "node": 3859, "naklon": null }, +{ "label": "16/110", "node": 4090, "naklon": 5 }, +{ "label": "16/111", "node": 4110, "naklon": null }, +{ "label": "16/112", "node": 4097, "naklon": 5 }, +{ "label": "16/113", "node": 4099, "naklon": null }, +{ "label": "16/114", "node": 4096, "naklon": null }, +{ "label": "16/115", "node": 4101, "naklon": 5 }, +{ "label": "16/116", "node": 4109, "naklon": null }, +{ "label": "16/117", "node": 4092, "naklon": 5 }, +{ "label": "16/118", "node": 3631, "naklon": null }, +{ "label": "16/119", "node": 3632, "naklon": 0 }, +{ "label": "16/120", "node": 3641, "naklon": null }, +{ "label": "16/121", "node": 3638, "naklon": 0 }, +{ "label": "16/122", "node": 3637, "naklon": null }, +{ "label": "16/123", "node": 4142, "naklon": null }, +{ "label": "16/124", "node": 4147, "naklon": 5 }, +{ "label": "16/125", "node": 4139, "naklon": 5 }, +{ "label": "20/30A", "node": 3172, "naklon": 2 }, +{ "label": "20/30B", "node": 3164, "naklon": 2 }, +{ "label": "20/1", "node": 3247, "naklon": 10 }, +{ "label": "20/2", "node": 3296, "naklon": 10 }, +{ "label": "20/3", "node": 3246, "naklon": 10 }, +{ "label": "20/4", "node": 3270, "naklon": 10 }, +{ "label": "20/5", "node": 3294, "naklon": 10 }, +{ "label": "20/6", "node": 3298, "naklon": 10 }, +{ "label": "20/7", "node": 3297, "naklon": 10 }, +{ "label": "20/8", "node": 3293, "naklon": 10 }, +{ "label": "20/9", "node": 3299, "naklon": 10 }, +{ "label": "20/10", "node": 3295, "naklon": 10 }, +{ "label": "20/11", "node": 3244, "naklon": 10 }, +{ "label": "20/12", "node": 3249, "naklon": 10 }, +{ "label": "20/13", "node": 3268, "naklon": 10 }, +{ "label": "20/14", "node": 3245, "naklon": 10 }, +{ "label": "20/15", "node": 3278, "naklon": 10 }, +{ "label": "20/16", "node": 3280, "naklon": 10 }, +{ "label": "20/17", "node": 3292, "naklon": 10 }, +{ "label": "20/18", "node": 3287, "naklon": 10 }, +{ "label": "20/19", "node": 3282, "naklon": 10 }, +{ "label": "20/20", "node": 3273, "naklon": 0 }, +{ "label": "20/21", "node": 3157, "naklon": 0 }, +{ "label": "20/22", "node": 3283, "naklon": 0 }, +{ "label": "20/23", "node": 3159, "naklon": 0 }, +{ "label": "20/24", "node": 3289, "naklon": 0 }, +{ "label": "20/25", "node": 3163, "naklon": 0 }, +{ "label": "20/26", "node": 3126, "naklon": 0 }, +{ "label": "20/27", "node": 3171, "naklon": 0 }, +{ "label": "20/28", "node": 3162, "naklon": 0 }, +{ "label": "20/29", "node": 3279, "naklon": 10 }, +{ "label": "20/31", "node": 3173, "naklon": 0 }, +{ "label": "20/32", "node": 3127, "naklon": 0 }, +{ "label": "20/33", "node": 3131, "naklon": 0 }, +{ "label": "20/34", "node": 3129, "naklon": 0 }, +{ "label": "20/35", "node": 3276, "naklon": 2 }, +{ "label": "20/36", "node": 3290, "naklon": 2 }, +{ "label": "20/37", "node": 3132, "naklon": 0 }, +{ "label": "20/38", "node": 3138, "naklon": 0 }, +{ "label": "20/39", "node": 3272, "naklon": 0 }, +{ "label": "20/40", "node": 3291, "naklon": 0 }, +{ "label": "20/41", "node": 3277, "naklon": 10 }, +{ "label": "20/42", "node": 3286, "naklon": 10 }, +{ "label": "20/43", "node": 3281, "naklon": 10 }, +{ "label": "20/44", "node": 3288, "naklon": 10 }, +{ "label": "20/45", "node": 3284, "naklon": 10 }, +{ "label": "20/46", "node": 3167, "naklon": 10 }, +{ "label": "20/47", "node": 3872, "naklon": 0 }, +{ "label": "20/48", "node": 3124, "naklon": 0 }, +{ "label": "20/49", "node": 3133, "naklon": 0 }, +{ "label": "20/50", "node": 3158, "naklon": 0 }, +{ "label": "20/51", "node": 3169, "naklon": 0 }, +{ "label": "20/52", "node": 3146, "naklon": 0 }, +{ "label": "20/53", "node": 3160, "naklon": 0 }, +{ "label": "20/54", "node": 3248, "naklon": 0 }, +{ "label": "20/55", "node": 3156, "naklon": 0 }, +{ "label": "20/56", "node": 3161, "naklon": 0 }, +{ "label": "20/57", "node": 3170, "naklon": 0 }, +{ "label": "20/58", "node": 3168, "naklon": 0 }, +{ "label": "20/59", "node": 3125, "naklon": 0 }, +{ "label": "20/60", "node": 3166, "naklon": 0 }, +{ "label": "20/61", "node": 3130, "naklon": 0 }, +{ "label": "20/62", "node": 3563, "naklon": 0 }, +{ "label": "20/63", "node": 3550, "naklon": null }, +{ "label": "20/67", "node": 3269, "naklon": 0 }, +{ "label": "21/1", "node": 2921, "naklon": 0 }, +{ "label": "21/2", "node": 2707, "naklon": 0 }, +{ "label": "21/3", "node": 2723, "naklon": 0 }, +{ "label": "21/4", "node": 2716, "naklon": 0 }, +{ "label": "21/5", "node": 2717, "naklon": 0 }, +{ "label": "21/6", "node": 2720, "naklon": 0 }, +{ "label": "21/7", "node": 2722, "naklon": 0 }, +{ "label": "21/8", "node": 2718, "naklon": 0 }, +{ "label": "21/9", "node": 2724, "naklon": 0 }, +{ "label": "21/10", "node": 2742, "naklon": 0 }, +{ "label": "21/11", "node": 2743, "naklon": 0 }, +{ "label": "21/12", "node": 2733, "naklon": 0 }, +{ "label": "21/14", "node": 2903, "naklon": 0 }, +{ "label": "21/15", "node": 2917, "naklon": 0 }, +{ "label": "21/16", "node": 2897, "naklon": 0 }, +{ "label": "21/17", "node": 2914, "naklon": 0 }, +{ "label": "21/18", "node": 2898, "naklon": 0 }, +{ "label": "21/19", "node": 2773, "naklon": 0 }, +{ "label": "21/20", "node": 2895, "naklon": 0 }, +{ "label": "21/21", "node": 2896, "naklon": 0 }, +{ "label": "21/22", "node": 2771, "naklon": 0 }, +{ "label": "21/23", "node": 2772, "naklon": 0 }, +{ "label": "21/24", "node": 2793, "naklon": 0 }, +{ "label": "21/25", "node": 2902, "naklon": 0 }, +{ "label": "21/26", "node": 2910, "naklon": 0 }, +{ "label": "21/27", "node": 2909, "naklon": 0 }, +{ "label": "21/28", "node": 2920, "naklon": 0 }, +{ "label": "21/29", "node": 2916, "naklon": 0 }, +{ "label": "21/30", "node": 2904, "naklon": 0 }, +{ "label": "21/31", "node": 2915, "naklon": 0 }, +{ "label": "21/32", "node": 2905, "naklon": 0 }, +{ "label": "21/33", "node": 2900, "naklon": 0 }, +{ "label": "21/34", "node": 2899, "naklon": 0 }, +{ "label": "21/36", "node": 2741, "naklon": 0 }, +{ "label": "21/37", "node": 2714, "naklon": 0 }, +{ "label": "21/38", "node": 2701, "naklon": 0 }, +{ "label": "21/39", "node": 2703, "naklon": 0 }, +{ "label": "21/40", "node": 2704, "naklon": 0 }, +{ "label": "21/41", "node": 2702, "naklon": 0 }, +{ "label": "21/42", "node": 2706, "naklon": 0 }, +{ "label": "21/43", "node": 2776, "naklon": 0 }, +{ "label": "21/44", "node": 2770, "naklon": 0 }, +{ "label": "21/45", "node": 2786, "naklon": 0 }, +{ "label": "21/46", "node": 2779, "naklon": 0 }, +{ "label": "21/47", "node": 2782, "naklon": 0 }, +{ "label": "21/48", "node": 2785, "naklon": 0 }, +{ "label": "21/49", "node": 2769, "naklon": 0 }, +{ "label": "21/50", "node": 3354, "naklon": 0 }, +{ "label": "21/51", "node": 2778, "naklon": 0 }, +{ "label": "21/52", "node": 2775, "naklon": 0 }, +{ "label": "21/53", "node": 2780, "naklon": 0 }, +{ "label": "21/54", "node": 2790, "naklon": 0 }, +{ "label": "21/55", "node": 2792, "naklon": 0 }, +{ "label": "21/56", "node": 2774, "naklon": 0 }, +{ "label": "22/1", "node": 2630, "naklon": 0 }, +{ "label": "22/2", "node": 2631, "naklon": 0 }, +{ "label": "22/3", "node": 2632, "naklon": 0 }, +{ "label": "22/4", "node": 2633, "naklon": 0 }, +{ "label": "22/5", "node": 2634, "naklon": 0 }, +{ "label": "22/6", "node": 2636, "naklon": 0 }, +{ "label": "22/7", "node": 4367, "naklon": 0 }, +{ "label": "22/8", "node": 2637, "naklon": 0 }, +{ "label": "22/9", "node": 2638, "naklon": 0 }, +{ "label": "22/10", "node": 2639, "naklon": 0 }, +{ "label": "22/11", "node": 2640, "naklon": 0 }, +{ "label": "22/12", "node": 2641, "naklon": 0 }, +{ "label": "22/13", "node": 2642, "naklon": 0 }, +{ "label": "22/14", "node": 2643, "naklon": 0 }, +{ "label": "22/15", "node": 2644, "naklon": 0 }, +{ "label": "22/16", "node": 2645, "naklon": 0 }, +{ "label": "22/17", "node": 2646, "naklon": 0 }, +{ "label": "22/18", "node": 2647, "naklon": 0 }, +{ "label": "22/19", "node": 2648, "naklon": 0 }, +{ "label": "22/20", "node": 2649, "naklon": 0 }, +{ "label": "22/21", "node": 2650, "naklon": 0 }, +{ "label": "22/22", "node": 2651, "naklon": 0 }, +{ "label": "22/23", "node": 4103, "naklon": 0 }, +{ "label": "22/24", "node": 2653, "naklon": 0 }, +{ "label": "22/25", "node": 2654, "naklon": 0 }, +{ "label": "22/26", "node": 2655, "naklon": 0 }, +{ "label": "22/27", "node": 2656, "naklon": 0 }, +{ "label": "22/28", "node": 2657, "naklon": 0 }, +{ "label": "22/29", "node": 2658, "naklon": 0 }, +{ "label": "22/30", "node": 2659, "naklon": 0 }, +{ "label": "22/31", "node": 2660, "naklon": 0 }, +{ "label": "22/32", "node": 2661, "naklon": 0 }, +{ "label": "22/32/1", "node": 3015, "naklon": 0 }, +{ "label": "22/33", "node": 2662, "naklon": 0 }, +{ "label": "22/34", "node": 2663, "naklon": 0 }, +{ "label": "22/35", "node": 2664, "naklon": 0 }, +{ "label": "22/36", "node": 2665, "naklon": 0 }, +{ "label": "22/37", "node": 2666, "naklon": 0 }, +{ "label": "22/38", "node": 2667, "naklon": 0 }, +{ "label": "22/39", "node": 2668, "naklon": 0 }, +{ "label": "22/40", "node": 2669, "naklon": null }, +{ "label": "22/41", "node": 2670, "naklon": null }, +{ "label": "22/42", "node": 2671, "naklon": null }, +{ "label": "23/9A", "node": 3087, "naklon": 10 }, +{ "label": "23/9B", "node": 3090, "naklon": 10 }, +{ "label": "23/1", "node": 3075, "naklon": 0 }, +{ "label": "23/2", "node": 3089, "naklon": 0 }, +{ "label": "23/3", "node": 3088, "naklon": 0 }, +{ "label": "23/4", "node": 3228, "naklon": 10 }, +{ "label": "23/5", "node": 2751, "naklon": 10 }, +{ "label": "23/6", "node": 3243, "naklon": 10 }, +{ "label": "23/7", "node": 4349, "naklon": 10 }, +{ "label": "23/8", "node": 3102, "naklon": 10 }, +{ "label": "23/10", "node": 3099, "naklon": 10 }, +{ "label": "23/11", "node": 3103, "naklon": 10 }, +{ "label": "23/12", "node": 3093, "naklon": 10 }, +{ "label": "23/13", "node": 3098, "naklon": 10 }, +{ "label": "23/14", "node": 3092, "naklon": 10 }, +{ "label": "23/15", "node": 3233, "naklon": 0 }, +{ "label": "23/16", "node": 3095, "naklon": 0 }, +{ "label": "23/17", "node": 4074, "naklon": 0 }, +{ "label": "23/18", "node": 2729, "naklon": 0 }, +{ "label": "23/19", "node": 3234, "naklon": 0 }, +{ "label": "23/20", "node": 3094, "naklon": 0 }, +{ "label": "23/21", "node": 2817, "naklon": 0 }, +{ "label": "23/22", "node": 3226, "naklon": 0 }, +{ "label": "23/23", "node": 3225, "naklon": 0 }, +{ "label": "23/24", "node": 3237, "naklon": 0 }, +{ "label": "23/25", "node": 4250, "naklon": 0 }, +{ "label": "23/26", "node": 3059, "naklon": 10 }, +{ "label": "23/27", "node": 3238, "naklon": 10 }, +{ "label": "23/28", "node": 3242, "naklon": 10 }, +{ "label": "23/29", "node": 3236, "naklon": 10 }, +{ "label": "23/30", "node": 3112, "naklon": 10 }, +{ "label": "23/31", "node": 3224, "naklon": 0 }, +{ "label": "23/32", "node": 4298, "naklon": 10 }, +{ "label": "23/33", "node": 4150, "naklon": 10 }, +{ "label": "23/34", "node": 3091, "naklon": 10 }, +{ "label": "25/1", "node": 3771, "naklon": 5 }, +{ "label": "25/2", "node": 3777, "naklon": 5 }, +{ "label": "25/3", "node": 3749, "naklon": 5 }, +{ "label": "25/4", "node": 3769, "naklon": 5 }, +{ "label": "25/5", "node": 3765, "naklon": 5 }, +{ "label": "25/6", "node": 3785, "naklon": 5 }, +{ "label": "25/7", "node": 3761, "naklon": 5 }, +{ "label": "25/8", "node": 3758, "naklon": 5 }, +{ "label": "25/9", "node": 3766, "naklon": 5 }, +{ "label": "25/10", "node": 3779, "naklon": 5 }, +{ "label": "25/11", "node": 3899, "naklon": 10 }, +{ "label": "25/12", "node": 3922, "naklon": 10 }, +{ "label": "25/13", "node": 3912, "naklon": 10 }, +{ "label": "25/14", "node": 3933, "naklon": 10 }, +{ "label": "25/15", "node": 3921, "naklon": 10 }, +{ "label": "25/16", "node": 4300, "naklon": 10 }, +{ "label": "25/17", "node": 3927, "naklon": 10 }, +{ "label": "25/18", "node": 3212, "naklon": 10 }, +{ "label": "25/19", "node": 3208, "naklon": 10 }, +{ "label": "25/20", "node": 3207, "naklon": 10 }, +{ "label": "25/21", "node": 4294, "naklon": 10 }, +{ "label": "25/22", "node": 3209, "naklon": 10 }, +{ "label": "25/23", "node": 3745, "naklon": 10 }, +{ "label": "25/24", "node": 3762, "naklon": 10 }, +{ "label": "25/25", "node": 3215, "naklon": 10 }, +{ "label": "25/26", "node": 3210, "naklon": 10 }, +{ "label": "25/27", "node": 3211, "naklon": 10 }, +{ "label": "25/28", "node": 3206, "naklon": 10 }, +{ "label": "25/29", "node": 3918, "naklon": 5 }, +{ "label": "25/30", "node": 3928, "naklon": 5 }, +{ "label": "25/31", "node": 3917, "naklon": 5 }, +{ "label": "25/32", "node": 4029, "naklon": 0 }, +{ "label": "25/33", "node": 4038, "naklon": 0 }, +{ "label": "25/34", "node": 4022, "naklon": 0 }, +{ "label": "25/35", "node": 3937, "naklon": 0 }, +{ "label": "25/36", "node": 3190, "naklon": 0 }, +{ "label": "25/37", "node": 3835, "naklon": 0 }, +{ "label": "25/38", "node": 3201, "naklon": 0 }, +{ "label": "25/39", "node": 3193, "naklon": 0 }, +{ "label": "25/40", "node": 3191, "naklon": 0 }, +{ "label": "25/41", "node": 3203, "naklon": 0 }, +{ "label": "25/42", "node": 4301, "naklon": 0 }, +{ "label": "25/43", "node": 3223, "naklon": 0 }, +{ "label": "25/44", "node": 3202, "naklon": 0 }, +{ "label": "25/45", "node": 3205, "naklon": 0 }, +{ "label": "25/46", "node": 3194, "naklon": 0 }, +{ "label": "25/47", "node": 3198, "naklon": 0 }, +{ "label": "25/48", "node": 3204, "naklon": 0 }, +{ "label": "25/49", "node": 3200, "naklon": 0 }, +{ "label": "25/50", "node": 3216, "naklon": 0 }, +{ "label": "25/51", "node": 3932, "naklon": 5 }, +{ "label": "25/52", "node": 3923, "naklon": 5 }, +{ "label": "25/53", "node": 3913, "naklon": 5 }, +{ "label": "25/54", "node": 3900, "naklon": 5 }, +{ "label": "25/55", "node": 4189, "naklon": 10 }, +{ "label": "25/56", "node": 4191, "naklon": 10 }, +{ "label": "25/57", "node": 3790, "naklon": 10 }, +{ "label": "25/58", "node": 4190, "naklon": 10 }, +{ "label": "25/59", "node": 4302, "naklon": 0 }, +{ "label": "25/60", "node": 4351, "naklon": 0 }, +{ "label": "25/61", "node": 4075, "naklon": 0 }, +{ "label": "25/62", "node": 4071, "naklon": 0 }, +{ "label": "25/63", "node": 3784, "naklon": 0 }, +{ "label": "25/64", "node": 4065, "naklon": 0 }, +{ "label": "25/65", "node": 4297, "naklon": 0 }, +{ "label": "25/66", "node": 4295, "naklon": 0 }, +{ "label": "25/67", "node": 4299, "naklon": 0 }, +{ "label": "25/68", "node": 3772, "naklon": 0 }, +{ "label": "25/69", "node": 3941, "naklon": 0 }, +{ "label": "25/70", "node": 3782, "naklon": 0 }, +{ "label": "25/71", "node": 4068, "naklon": 0 }, +{ "label": "25/72", "node": 4073, "naklon": 0 }, +{ "label": "25/73", "node": 3901, "naklon": 5 }, +{ "label": "25/74", "node": 4296, "naklon": 5 }, +{ "label": "25/75", "node": 3910, "naklon": 5 }, +{ "label": "25/76", "node": 4293, "naklon": 5 }, +{ "label": "25/77", "node": 3919, "naklon": 5 }, +{ "label": "25/78", "node": 3924, "naklon": 5 }, +{ "label": "25/79", "node": 3909, "naklon": 5 }, +{ "label": "25/80", "node": 3896, "naklon": 5 }, +{ "label": "25/81", "node": 3911, "naklon": 5 }, +{ "label": "25/82", "node": 2819, "naklon": 15 }, +{ "label": "25/83", "node": 3776, "naklon": 15 }, +{ "label": "25/84", "node": 3752, "naklon": 15 }, +{ "label": "25/85", "node": 4353, "naklon": 15 }, +{ "label": "25/86", "node": 3791, "naklon": 0 }, +{ "label": "25/87", "node": 3770, "naklon": 0 }, +{ "label": "25/88", "node": 3760, "naklon": 0 }, +{ "label": "25/89", "node": 3115, "naklon": 0 }, +{ "label": "25/90", "node": 3738, "naklon": 0 }, +{ "label": "25/91", "node": 3748, "naklon": 0 }, +{ "label": "25/92", "node": 3753, "naklon": 0 }, +{ "label": "25/93", "node": 3775, "naklon": 0 }, +{ "label": "25/94", "node": 3778, "naklon": 5 }, +{ "label": "25/95", "node": 4078, "naklon": 5 }, +{ "label": "25/96", "node": 4088, "naklon": 5 }, +{ "label": "25/97", "node": 3856, "naklon": 5 }, +{ "label": "25/98", "node": 4084, "naklon": 5 }, +{ "label": "25/99", "node": 4069, "naklon": 5 }, +{ "label": "25/100", "node": 4188, "naklon": 5 }, +{ "label": "25/101", "node": 4064, "naklon": 5 }, +{ "label": "25/102", "node": 3792, "naklon": 5 }, +{ "label": "25/103", "node": 3780, "naklon": 5 }, +{ "label": "25/104", "node": 4034, "naklon": 5 }, +{ "label": "25/105", "node": 4072, "naklon": 5 }, +{ "label": "25/106", "node": 3884, "naklon": 5 }, +{ "label": "25/107", "node": 3793, "naklon": 5 }, +{ "label": "25/108", "node": 3863, "naklon": 5 }, +{ "label": "25/109", "node": 3855, "naklon": 5 }, +{ "label": "33/1", "node": 3846, "naklon": 0 }, +{ "label": "33/2", "node": 3943, "naklon": 0 }, +{ "label": "33/3", "node": 3903, "naklon": 0 }, +{ "label": "33/4", "node": 3982, "naklon": 0 }, +{ "label": "33/5", "node": 3879, "naklon": 0 }, +{ "label": "33/6", "node": 3887, "naklon": 0 }, +{ "label": "33/7", "node": 3920, "naklon": 5 }, +{ "label": "33/8", "node": 3942, "naklon": 5 }, +{ "label": "33/9", "node": 3829, "naklon": null }, +{ "label": "34/79A", "node": 3452, "naklon": 6 }, +{ "label": "34/79B", "node": 3460, "naklon": 6 }, +{ "label": "34/90A", "node": 3443, "naklon": 6 }, +{ "label": "34/90B", "node": 3445, "naklon": 6 }, +{ "label": "34/90C", "node": 3457, "naklon": 6 }, +{ "label": "34/97A", "node": 3461, "naklon": 6 }, +{ "label": "34/97B", "node": 3463, "naklon": 6 }, +{ "label": "34/98A", "node": 3426, "naklon": 6 }, +{ "label": "34/98B", "node": 3444, "naklon": 6 }, +{ "label": "34/99A", "node": 3453, "naklon": 6 }, +{ "label": "34/99B", "node": 3455, "naklon": 6 }, +{ "label": "34/1", "node": 4009, "naklon": 0 }, +{ "label": "34/2", "node": 3602, "naklon": 0 }, +{ "label": "34/3", "node": 3441, "naklon": 0 }, +{ "label": "34/4", "node": 3464, "naklon": 0 }, +{ "label": "34/5", "node": 3883, "naklon": 0 }, +{ "label": "34/6", "node": 4098, "naklon": 0 }, +{ "label": "34/7", "node": 4003, "naklon": 0 }, +{ "label": "34/8", "node": 4004, "naklon": 0 }, +{ "label": "34/9", "node": 3888, "naklon": 0 }, +{ "label": "34/10", "node": 3997, "naklon": 0 }, +{ "label": "34/11", "node": 4006, "naklon": 0 }, +{ "label": "34/12", "node": 4000, "naklon": 0 }, +{ "label": "34/13", "node": 4011, "naklon": 0 }, +{ "label": "34/14", "node": 3999, "naklon": 0 }, +{ "label": "34/15", "node": 3981, "naklon": 0 }, +{ "label": "34/16", "node": 3988, "naklon": 0 }, +{ "label": "34/17", "node": 3986, "naklon": 0 }, +{ "label": "34/18", "node": 3998, "naklon": 0 }, +{ "label": "34/19", "node": 3983, "naklon": 0 }, +{ "label": "34/20", "node": 4005, "naklon": 0 }, +{ "label": "34/21", "node": 4001, "naklon": 0 }, +{ "label": "34/22", "node": 4008, "naklon": 0 }, +{ "label": "34/23", "node": 4002, "naklon": 0 }, +{ "label": "34/24", "node": 3996, "naklon": 0 }, +{ "label": "34/25", "node": 4007, "naklon": 0 }, +{ "label": "34/26", "node": 4113, "naklon": 15 }, +{ "label": "34/27", "node": 3595, "naklon": 5 }, +{ "label": "34/28", "node": 3599, "naklon": 5 }, +{ "label": "34/29", "node": 3601, "naklon": 5 }, +{ "label": "34/30", "node": 4205, "naklon": 0 }, +{ "label": "34/31", "node": 3987, "naklon": null }, +{ "label": "34/32", "node": 4214, "naklon": 0 }, +{ "label": "34/33", "node": 4226, "naklon": 0 }, +{ "label": "34/34", "node": 4209, "naklon": 0 }, +{ "label": "34/35", "node": 4201, "naklon": 0 }, +{ "label": "34/36", "node": 3440, "naklon": 0 }, +{ "label": "34/37", "node": 3465, "naklon": 0 }, +{ "label": "34/38", "node": 3446, "naklon": 0 }, +{ "label": "34/39", "node": 4039, "naklon": 5 }, +{ "label": "34/40", "node": 4057, "naklon": 5 }, +{ "label": "34/41", "node": 3985, "naklon": 0 }, +{ "label": "34/42", "node": 3882, "naklon": 0 }, +{ "label": "34/43", "node": 4040, "naklon": 5 }, +{ "label": "34/44", "node": 3231, "naklon": 0 }, +{ "label": "34/45", "node": 3227, "naklon": 0 }, +{ "label": "34/46", "node": 3431, "naklon": 0 }, +{ "label": "34/47", "node": 4013, "naklon": 0 }, +{ "label": "34/48", "node": 4045, "naklon": 0 }, +{ "label": "34/49", "node": 3949, "naklon": 0 }, +{ "label": "34/50", "node": 3953, "naklon": 0 }, +{ "label": "34/51", "node": 3952, "naklon": 0 }, +{ "label": "34/52", "node": 3995, "naklon": 0 }, +{ "label": "34/53", "node": 3992, "naklon": 0 }, +{ "label": "34/54", "node": 4198, "naklon": 0 }, +{ "label": "34/55", "node": 3935, "naklon": 0 }, +{ "label": "34/56", "node": 4050, "naklon": 0 }, +{ "label": "34/57", "node": 4049, "naklon": 0 }, +{ "label": "34/58", "node": 4054, "naklon": 0 }, +{ "label": "34/59", "node": 3663, "naklon": 6 }, +{ "label": "34/60", "node": 3661, "naklon": 6 }, +{ "label": "34/61", "node": 3664, "naklon": 6 }, +{ "label": "34/62", "node": 3660, "naklon": 6 }, +{ "label": "34/63", "node": 3662, "naklon": 6 }, +{ "label": "34/65", "node": 3665, "naklon": 6 }, +{ "label": "34/66", "node": 3667, "naklon": 6 }, +{ "label": "34/67", "node": 3675, "naklon": 6 }, +{ "label": "34/68", "node": 3666, "naklon": 6 }, +{ "label": "34/69", "node": 3652, "naklon": 6 }, +{ "label": "34/70", "node": 3458, "naklon": 6 }, +{ "label": "34/70/1", "node": 4425, "naklon": 6 }, +{ "label": "34/71", "node": 3459, "naklon": 6 }, +{ "label": "34/72", "node": 3435, "naklon": 6 }, +{ "label": "34/73", "node": 3448, "naklon": 6 }, +{ "label": "34/74", "node": 3451, "naklon": 6 }, +{ "label": "34/75", "node": 3442, "naklon": 6 }, +{ "label": "34/76", "node": 3449, "naklon": 6 }, +{ "label": "34/77", "node": 3450, "naklon": 6 }, +{ "label": "34/78", "node": 3433, "naklon": 6 }, +{ "label": "34/80", "node": 3432, "naklon": 12 }, +{ "label": "34/81", "node": 3470, "naklon": 12 }, +{ "label": "34/82", "node": 3438, "naklon": 12 }, +{ "label": "34/83", "node": 3439, "naklon": 12 }, +{ "label": "34/84", "node": 4028, "naklon": 5 }, +{ "label": "34/85", "node": 3596, "naklon": 5 }, +{ "label": "34/86", "node": 4021, "naklon": 5 }, +{ "label": "34/87", "node": 3437, "naklon": 12 }, +{ "label": "34/88", "node": 3428, "naklon": 12 }, +{ "label": "34/89", "node": 3430, "naklon": 12 }, +{ "label": "34/91", "node": 3454, "naklon": 6 }, +{ "label": "34/92", "node": 3492, "naklon": 6 }, +{ "label": "34/93", "node": 3462, "naklon": 6 }, +{ "label": "34/94", "node": 3427, "naklon": 6 }, +{ "label": "34/95", "node": 3434, "naklon": 6 }, +{ "label": "34/96", "node": 3456, "naklon": 6 }, +{ "label": "34/98/1", "node": 4307, "naklon": 6 }, +{ "label": "35/1", "node": 3968, "naklon": 0 }, +{ "label": "35/2", "node": 3969, "naklon": 0 }, +{ "label": "35/3", "node": 3947, "naklon": 0 }, +{ "label": "35/4", "node": 3979, "naklon": 0 }, +{ "label": "35/5", "node": 3959, "naklon": 0 }, +{ "label": "35/6", "node": 3948, "naklon": 0 }, +{ "label": "35/7", "node": 3961, "naklon": 0 }, +{ "label": "35/8", "node": 3956, "naklon": 0 }, +{ "label": "35/9", "node": 3604, "naklon": 0 }, +{ "label": "35/10", "node": 3944, "naklon": 0 }, +{ "label": "35/11", "node": 3960, "naklon": 0 }, +{ "label": "35/12", "node": 3958, "naklon": 0 }, +{ "label": "35/13", "node": 4036, "naklon": 5 }, +{ "label": "35/18", "node": 3893, "naklon": 5 }, +{ "label": "35/19", "node": 4108, "naklon": 5 }, +{ "label": "35/20", "node": 4017, "naklon": 5 }, +{ "label": "35/21", "node": 3963, "naklon": 0 }, +{ "label": "35/22", "node": 3658, "naklon": 0 }, +{ "label": "35/23", "node": 3975, "naklon": 0 }, +{ "label": "35/24", "node": 3980, "naklon": 0 }, +{ "label": "35/25", "node": 4012, "naklon": 0 }, +{ "label": "35/26", "node": 3655, "naklon": 0 }, +{ "label": "35/27", "node": 3962, "naklon": 0 }, +{ "label": "35/28", "node": 3945, "naklon": 0 }, +{ "label": "35/29", "node": 3569, "naklon": 0 }, +{ "label": "35/30", "node": 3429, "naklon": 0 }, +{ "label": "35/31", "node": 3657, "naklon": 0 }, +{ "label": "35/32", "node": 3646, "naklon": 0 }, +{ "label": "35/33", "node": 3622, "naklon": 0 }, +{ "label": "35/34", "node": 3612, "naklon": 0 }, +{ "label": "35/35", "node": 3955, "naklon": 0 }, +{ "label": "35/37", "node": 3878, "naklon": 0 }, +{ "label": "35/38", "node": 3965, "naklon": 0 }, +{ "label": "35/39", "node": 3970, "naklon": 0 }, +{ "label": "35/40", "node": 3611, "naklon": 0 }, +{ "label": "35/41", "node": 2635, "naklon": 0 }, +{ "label": "35/42", "node": 3978, "naklon": 0 }, +{ "label": "35/43", "node": 4213, "naklon": 0 }, +{ "label": "35/44", "node": 3984, "naklon": 0 }, +{ "label": "35/45", "node": 4218, "naklon": 0 }, +{ "label": "35/46", "node": 3973, "naklon": 0 }, +{ "label": "35/47", "node": 3974, "naklon": 0 }, +{ "label": "35/48", "node": 3759, "naklon": 0 }, +{ "label": "35/49", "node": 3844, "naklon": 0 }, +{ "label": "35/50", "node": 3804, "naklon": 0 }, +{ "label": "35/51", "node": 3831, "naklon": 0 }, +{ "label": "35/52", "node": 3643, "naklon": 0 }, +{ "label": "35/53", "node": 3966, "naklon": 0 }, +{ "label": "35/54", "node": 3971, "naklon": 0 }, +{ "label": "35/55", "node": 3650, "naklon": 6 }, +{ "label": "35/56", "node": 3651, "naklon": 6 }, +{ "label": "35/57", "node": 3669, "naklon": 6 }, +{ "label": "35/58", "node": 3648, "naklon": 6 }, +{ "label": "35/59", "node": 3645, "naklon": 6 }, +{ "label": "35/60", "node": 3659, "naklon": 6 }, +{ "label": "35/61", "node": 3647, "naklon": 6 }, +{ "label": "35/62", "node": 3644, "naklon": 6 }, +{ "label": "35/63", "node": 3671, "naklon": 6 }, +{ "label": "35/64", "node": 3682, "naklon": 6 }, +{ "label": "35/65", "node": 3672, "naklon": 6 }, +{ "label": "35/66", "node": 3683, "naklon": 6 }, +{ "label": "35/67", "node": 3673, "naklon": 6 }, +{ "label": "35/68", "node": 3674, "naklon": 6 }, +{ "label": "35/69", "node": 3679, "naklon": 6 }, +{ "label": "35/70", "node": 3649, "naklon": 6 }, +{ "label": "35/71", "node": 3687, "naklon": 6 }, +{ "label": "35/72", "node": 3677, "naklon": 6 }, +{ "label": "35/73", "node": 3690, "naklon": 6 }, +{ "label": "35/74", "node": 3691, "naklon": 6 }, +{ "label": "35/75", "node": 3676, "naklon": 6 }, +{ "label": "35/76", "node": 3680, "naklon": 6 }, +{ "label": "35/77", "node": 3668, "naklon": 6 }, +{ "label": "35/78", "node": 3681, "naklon": 6 }, +{ "label": "35/79", "node": 3670, "naklon": 6 }, +{ "label": "35/80", "node": 3689, "naklon": 6 }, +{ "label": "35/81", "node": 3678, "naklon": 6 }, +{ "label": "35/82", "node": 3693, "naklon": 6 }, +{ "label": "35/83", "node": 3654, "naklon": null }, +{ "label": "36/1", "node": 4086, "naklon": 0 }, +{ "label": "36/2", "node": 4085, "naklon": 0 }, +{ "label": "36/3", "node": 4083, "naklon": 0 }, +{ "label": "36/4", "node": 4087, "naklon": 0 }, +{ "label": "36/5", "node": 4077, "naklon": 0 }, +{ "label": "36/6", "node": 4082, "naklon": 0 }, +{ "label": "36/7", "node": 4186, "naklon": 0 }, +{ "label": "36/8", "node": 4206, "naklon": 0 }, +{ "label": "36/9", "node": 4080, "naklon": 0 }, +{ "label": "36/10", "node": 4081, "naklon": 0 }, +{ "label": "36/11", "node": 4210, "naklon": 0 }, +{ "label": "36/12", "node": 4079, "naklon": 0 }, +{ "label": "36/13", "node": 4076, "naklon": 0 }, +{ "label": "36/14", "node": 3852, "naklon": 0 }, +{ "label": "36/15", "node": 2813, "naklon": 0 }, +{ "label": "36/16", "node": 4219, "naklon": 0 }, +{ "label": "37/1A", "node": 3104, "naklon": 15 }, +{ "label": "37/1B", "node": 3121, "naklon": 15 }, +{ "label": "37/2", "node": 3113, "naklon": 10 }, +{ "label": "37/3", "node": 3118, "naklon": 10 }, +{ "label": "37/4", "node": 3111, "naklon": 10 }, +{ "label": "37/5", "node": 4020, "naklon": 10 }, +{ "label": "37/6", "node": 3119, "naklon": 10 }, +{ "label": "37/7", "node": 3110, "naklon": 10 }, +{ "label": "37/8", "node": 3108, "naklon": 10 }, +{ "label": "37/12", "node": 3107, "naklon": 0 }, +{ "label": "37/13", "node": 3199, "naklon": 0 }, +{ "label": "37/14", "node": 3120, "naklon": 0 }, +{ "label": "37/15", "node": 3122, "naklon": 0 }, +{ "label": "37/16", "node": 3908, "naklon": 0 }, +{ "label": "37/17", "node": 3114, "naklon": 0 }, +{ "label": "37/18", "node": 3105, "naklon": 0 }, +{ "label": "37/19", "node": 3116, "naklon": 0 }, +{ "label": "37/20", "node": 3106, "naklon": 0 }, +{ "label": "37/21", "node": 2887, "naklon": 5 }, +{ "label": "37/22", "node": 2888, "naklon": 5 }, +{ "label": "37/23", "node": 2877, "naklon": 5 }, +{ "label": "37/24", "node": 2891, "naklon": 5 }, +{ "label": "37/25", "node": 2886, "naklon": 5 }, +{ "label": "37/26", "node": 2892, "naklon": 5 }, +{ "label": "37/27", "node": 2882, "naklon": 5 }, +{ "label": "37/28", "node": 2883, "naklon": 5 }, +{ "label": "37/29", "node": 2876, "naklon": 5 }, +{ "label": "37/30", "node": 3109, "naklon": 5 }, +{ "label": "37/31", "node": 4152, "naklon": 5 }, +{ "label": "37/32", "node": 3117, "naklon": 5 }, +{ "label": "37/33", "node": 2870, "naklon": 5 }, +{ "label": "37/34", "node": 2867, "naklon": 0 }, +{ "label": "37/35", "node": 2865, "naklon": 0 }, +{ "label": "37/36", "node": 3096, "naklon": 0 }, +{ "label": "37/37", "node": 2871, "naklon": 0 }, +{ "label": "37/38", "node": 2884, "naklon": 0 }, +{ "label": "37/39", "node": 2855, "naklon": 0 }, +{ "label": "37/40", "node": 2878, "naklon": 0 }, +{ "label": "37/41", "node": 2889, "naklon": 0 }, +{ "label": "37/42", "node": 2879, "naklon": 0 }, +{ "label": "37/43", "node": 2850, "naklon": 0 }, +{ "label": "37/44", "node": 2894, "naklon": 0 }, +{ "label": "37/45", "node": 2880, "naklon": 0 }, +{ "label": "37/46", "node": 2893, "naklon": 0 }, +{ "label": "37/47", "node": 2890, "naklon": 0 }, +{ "label": "37/48", "node": 4355, "naklon": 0 }, +{ "label": "37/49", "node": 2885, "naklon": 0 }, +{ "label": "37/50", "node": 2875, "naklon": 0 }, +{ "label": "38/30A", "node": 3486, "naklon": 5 }, +{ "label": "38/30B", "node": 3714, "naklon": 0 }, +{ "label": "38/32A", "node": 3483, "naklon": 5 }, +{ "label": "38/32B", "node": 3496, "naklon": 0 }, +{ "label": "38/35A", "node": 3487, "naklon": 5 }, +{ "label": "38/35B", "node": 3498, "naklon": 5 }, +{ "label": "38/38A", "node": 3578, "naklon": 5 }, +{ "label": "38/38B", "node": 3508, "naklon": 5 }, +{ "label": "38/59A", "node": 3787, "naklon": 5 }, +{ "label": "38/59B", "node": 3491, "naklon": 5 }, +{ "label": "38/1", "node": 3568, "naklon": null }, +{ "label": "38/2", "node": 3502, "naklon": 0 }, +{ "label": "38/3", "node": 3836, "naklon": 0 }, +{ "label": "38/4", "node": 3588, "naklon": 0 }, +{ "label": "38/5", "node": 3493, "naklon": 0 }, +{ "label": "38/6", "node": 3580, "naklon": 0 }, +{ "label": "38/7", "node": 3572, "naklon": 0 }, +{ "label": "38/8", "node": 3506, "naklon": 0 }, +{ "label": "38/9", "node": 3503, "naklon": 0 }, +{ "label": "38/10", "node": 3579, "naklon": 0 }, +{ "label": "38/11", "node": 3586, "naklon": 0 }, +{ "label": "38/12", "node": 3495, "naklon": 5 }, +{ "label": "38/13", "node": 3492, "naklon": 5 }, +{ "label": "38/14", "node": 3532, "naklon": 5 }, +{ "label": "38/15", "node": 3574, "naklon": 5 }, +{ "label": "38/16", "node": 4140, "naklon": 5 }, +{ "label": "38/17", "node": 3795, "naklon": 5 }, +{ "label": "38/18", "node": 3788, "naklon": 5 }, +{ "label": "38/19", "node": 3796, "naklon": 5 }, +{ "label": "38/20", "node": 3797, "naklon": 5 }, +{ "label": "38/21", "node": 3798, "naklon": 5 }, +{ "label": "38/22", "node": 3786, "naklon": 5 }, +{ "label": "38/23", "node": 4067, "naklon": 5 }, +{ "label": "38/24", "node": 3773, "naklon": 5 }, +{ "label": "38/25", "node": 3774, "naklon": 5 }, +{ "label": "38/26", "node": 3789, "naklon": 5 }, +{ "label": "38/27", "node": 3520, "naklon": null }, +{ "label": "38/29", "node": 3577, "naklon": 5 }, +{ "label": "38/31", "node": 3530, "naklon": null }, +{ "label": "38/33", "node": 3488, "naklon": 5 }, +{ "label": "38/34", "node": 3505, "naklon": 5 }, +{ "label": "38/36", "node": 3497, "naklon": 5 }, +{ "label": "38/37", "node": 3490, "naklon": 5 }, +{ "label": "38/39", "node": 3585, "naklon": 5 }, +{ "label": "38/40", "node": 3582, "naklon": 5 }, +{ "label": "38/41", "node": 3507, "naklon": 5 }, +{ "label": "38/42", "node": 3484, "naklon": 5 }, +{ "label": "38/43", "node": 3501, "naklon": 5 }, +{ "label": "38/44", "node": 3581, "naklon": 5 }, +{ "label": "38/45", "node": 4192, "naklon": 5 }, +{ "label": "38/46", "node": 3576, "naklon": 5 }, +{ "label": "38/47", "node": 3489, "naklon": 5 }, +{ "label": "38/48", "node": 3573, "naklon": 5 }, +{ "label": "38/49", "node": 3504, "naklon": 5 }, +{ "label": "38/50", "node": 3794, "naklon": 5 }, +{ "label": "38/51", "node": 3485, "naklon": 5 }, +{ "label": "38/52", "node": 3482, "naklon": 5 }, +{ "label": "38/53", "node": 3575, "naklon": 5 }, +{ "label": "38/54", "node": 3499, "naklon": 5 }, +{ "label": "38/55", "node": 3494, "naklon": 5 }, +{ "label": "38/56", "node": 3583, "naklon": 5 }, +{ "label": "38/57", "node": 3570, "naklon": 5 }, +{ "label": "38/58", "node": 3500, "naklon": 0 }, +{ "label": "38/63", "node": 3510, "naklon": null }, +{ "label": "38/64", "node": 3512, "naklon": null }, +{ "label": "38/67", "node": 3535, "naklon": null }, +{ "label": "38/68", "node": 3531, "naklon": null }, +{ "label": "38/69", "node": 3537, "naklon": null }, +{ "label": "39/1", "node": 3522, "naklon": 10 }, +{ "label": "39/2", "node": 4018, "naklon": 10 }, +{ "label": "39/3", "node": 4019, "naklon": 10 }, +{ "label": "39/4", "node": 4154, "naklon": 5 }, +{ "label": "39/5", "node": 3907, "naklon": 5 }, +{ "label": "39/6", "node": 4148, "naklon": 0 }, +{ "label": "39/7", "node": 4153, "naklon": 0 }, +{ "label": "39/8", "node": 3938, "naklon": 0 }, +{ "label": "39/9", "node": 3802, "naklon": 0 }, +{ "label": "39/10", "node": 4015, "naklon": 0 }, +{ "label": "39/11", "node": 3929, "naklon": 0 }, +{ "label": "39/12", "node": 3946, "naklon": 0 }, +{ "label": "39/13", "node": 4014, "naklon": 0 }, +{ "label": "39/14", "node": 4155, "naklon": 0 }, +{ "label": "39/15", "node": 4149, "naklon": 0 }, +{ "label": "39/16", "node": 3642, "naklon": 0 }, +{ "label": "39/17", "node": 3636, "naklon": 5 }, +{ "label": "39/18", "node": 3991, "naklon": 0 }, +{ "label": "39/19", "node": 3994, "naklon": 0 }, +{ "label": "39/20", "node": 3990, "naklon": 0 }, +{ "label": "39/21", "node": 3967, "naklon": 0 }, +{ "label": "39/22", "node": 3977, "naklon": 0 }, +{ "label": "39/23", "node": 3757, "naklon": 15 }, +{ "label": "39/24", "node": 3633, "naklon": 15 }, +{ "label": "39/25", "node": 3744, "naklon": 15 }, +{ "label": "39/26", "node": 4023, "naklon": 5 }, +{ "label": "39/27", "node": 3720, "naklon": 5 }, +{ "label": "39/28", "node": 3734, "naklon": 5 }, +{ "label": "39/29", "node": 3741, "naklon": 5 }, +{ "label": "39/30", "node": 3721, "naklon": 5 }, +{ "label": "39/31", "node": 3845, "naklon": 0 }, +{ "label": "39/32", "node": 3840, "naklon": 0 }, +{ "label": "39/33", "node": 3837, "naklon": null }, +{ "label": "39/34", "node": 3839, "naklon": 0 }, +{ "label": "41/1", "node": 3542, "naklon": null }, +{ "label": "41/2", "node": 3566, "naklon": null }, +{ "label": "41/3", "node": 3548, "naklon": null }, +{ "label": "41/4", "node": 3515, "naklon": null }, +{ "label": "41/5", "node": 3559, "naklon": null }, +{ "label": "41/6", "node": 3509, "naklon": null }, +{ "label": "41/7", "node": 3524, "naklon": null }, +{ "label": "41/8", "node": 3518, "naklon": null }, +{ "label": "41/9", "node": 3182, "naklon": null }, +{ "label": "41/10", "node": 3187, "naklon": null }, +{ "label": "41/11", "node": 3195, "naklon": 0 }, +{ "label": "41/12", "node": 3857, "naklon": 0 }, +{ "label": "41/13", "node": 3183, "naklon": 0 }, +{ "label": "41/14", "node": 3177, "naklon": 0 }, +{ "label": "41/15", "node": 3189, "naklon": 0 }, +{ "label": "41/16", "node": 3186, "naklon": 0 }, +{ "label": "42/1", "node": 3178, "naklon": 0 }, +{ "label": "42/2", "node": 3219, "naklon": 0 }, +{ "label": "42/3", "node": 3475, "naklon": 0 }, +{ "label": "42/4", "node": 3175, "naklon": 0 }, +{ "label": "42/5", "node": 3222, "naklon": 0 }, +{ "label": "42/6", "node": 3221, "naklon": 0 }, +{ "label": "42/7", "node": 3181, "naklon": 0 }, +{ "label": "42/8", "node": 3180, "naklon": 0 }, +{ "label": "42/9", "node": 3218, "naklon": 0 }, +{ "label": "42/10", "node": 3176, "naklon": 0 }, +{ "label": "42/11", "node": 3174, "naklon": 0 }, +{ "label": "42/12", "node": 3220, "naklon": 0 }, +{ "label": "42/13", "node": 3533, "naklon": null }, +{ "label": "42/14", "node": 3543, "naklon": null }, +{ "label": "42/15", "node": 3554, "naklon": null }, +{ "label": "42/16", "node": 3549, "naklon": null }, +{ "label": "43/1", "node": 2857, "naklon": 5 }, +{ "label": "43/2", "node": 2752, "naklon": 5 }, +{ "label": "43/3", "node": 2753, "naklon": 5 }, +{ "label": "43/4", "node": 3024, "naklon": 5 }, +{ "label": "43/5", "node": 2754, "naklon": 5 }, +{ "label": "43/6", "node": 4423, "naklon": 5 }, +{ "label": "43/7", "node": 4368, "naklon": 5 }, +{ "label": "43/8", "node": 2978, "naklon": 5 }, +{ "label": "43/9", "node": 2868, "naklon": 5 }, +{ "label": "43/10", "node": 4377, "naklon": 5 }, +{ "label": "43/11", "node": 2757, "naklon": 5 }, +{ "label": "43/12", "node": 2970, "naklon": 5 }, +{ "label": "43/13", "node": 2758, "naklon": 5 }, +{ "label": "43/14", "node": 4378, "naklon": 5 }, +{ "label": "43/15", "node": 2759, "naklon": 5 }, +{ "label": "43/16", "node": 4342, "naklon": 5 }, +{ "label": "43/17", "node": 3026, "naklon": null }, +{ "label": "43/18", "node": 2986, "naklon": null }, +{ "label": "43/19", "node": 4343, "naklon": null }, +{ "label": "43/20", "node": 2760, "naklon": null }, +{ "label": "43/21", "node": 4379, "naklon": null }, +{ "label": "43/22", "node": 2971, "naklon": null }, +{ "label": "43/23", "node": 2761, "naklon": null }, +{ "label": "43/24", "node": 2762, "naklon": null }, +{ "label": "43/25", "node": 4339, "naklon": null }, +{ "label": "43/26", "node": 4380, "naklon": null }, +{ "label": "43/27", "node": 2975, "naklon": null }, +{ "label": "43/28", "node": 3003, "naklon": null }, +{ "label": "43/29", "node": 4338, "naklon": null }, +{ "label": "43/30", "node": 3002, "naklon": null }, +{ "label": "43/31", "node": 4345, "naklon": null }, +{ "label": "43/32", "node": 2979, "naklon": null }, +{ "label": "43/33", "node": 2989, "naklon": null }, +{ "label": "43/34", "node": 2996, "naklon": null }, +{ "label": "43/35", "node": 2972, "naklon": null }, +{ "label": "43/36", "node": 2988, "naklon": null }, +{ "label": "43/37", "node": 4344, "naklon": null }, +{ "label": "43/38", "node": 3022, "naklon": null }, +{ "label": "43/39", "node": 4341, "naklon": null }, +{ "label": "43/40", "node": 2983, "naklon": null }, +{ "label": "43/41", "node": 2995, "naklon": null }, +{ "label": "43/42", "node": 2763, "naklon": null }, +{ "label": "43/43", "node": 2764, "naklon": null }, +{ "label": "43/44", "node": 2765, "naklon": null }, +{ "label": "43/45", "node": 2766, "naklon": null }, +{ "label": "43/46", "node": 2767, "naklon": null }, +{ "label": "43/47", "node": 2768, "naklon": null }, +{ "label": "43/48", "node": 3018, "naklon": null }, +{ "label": "43/49", "node": 2982, "naklon": null }, +{ "label": "43/50", "node": 3019, "naklon": 0 }, +{ "label": "43/51", "node": 3013, "naklon": null }, +{ "label": "43/52", "node": 3007, "naklon": null }, +{ "label": "43/53", "node": 2980, "naklon": null }, +{ "label": "43/54", "node": 3011, "naklon": null }, +{ "label": "43/55", "node": 2672, "naklon": null }, +{ "label": "43/56", "node": 2673, "naklon": null }, +{ "label": "43/57", "node": 2674, "naklon": null }, +{ "label": "43/58", "node": 2675, "naklon": null }, +{ "label": "43/59", "node": 2676, "naklon": null }, +{ "label": "43/60", "node": 2677, "naklon": null }, +{ "label": "43/61", "node": 2678, "naklon": null }, +{ "label": "43/62", "node": 2679, "naklon": null }, +{ "label": "43/63", "node": 2680, "naklon": null }, +{ "label": "43/64", "node": 2840, "naklon": null }, +{ "label": "43/65", "node": 2682, "naklon": null }, +{ "label": "43/66", "node": 2683, "naklon": null }, +{ "label": "43/67", "node": 2684, "naklon": 0 }, +{ "label": "43/68", "node": 2685, "naklon": null }, +{ "label": "43/69", "node": 2686, "naklon": null }, +{ "label": "43/70", "node": 2687, "naklon": null }, +{ "label": "43/71", "node": 2688, "naklon": null }, +{ "label": "43/72", "node": 2689, "naklon": null }, +{ "label": "43/73", "node": 2690, "naklon": null }, +{ "label": "43/74", "node": 2691, "naklon": null }, +{ "label": "43/75", "node": 2692, "naklon": null }, +{ "label": "43/76", "node": 2693, "naklon": 0 }, +{ "label": "43/77", "node": 2694, "naklon": null }, +{ "label": "43/78", "node": 2695, "naklon": null }, +{ "label": "43/79", "node": 2696, "naklon": 0 }, +{ "label": "43/80", "node": 2697, "naklon": null }, +{ "label": "43/81", "node": 2698, "naklon": 0 }, +{ "label": "43/82", "node": 2699, "naklon": null }, +{ "label": "43/83", "node": 2700, "naklon": 0 }, +{ "label": "43/84", "node": 2744, "naklon": null }, +{ "label": "43/85", "node": 2745, "naklon": 0 }, +{ "label": "43/86", "node": 2746, "naklon": null }, +{ "label": "43/87", "node": 2747, "naklon": 0 }, +{ "label": "43/88", "node": 2748, "naklon": null }, +{ "label": "43/89", "node": 2749, "naklon": 0 }, +{ "label": "43/90", "node": 2841, "naklon": null }, +{ "label": "45/1", "node": 4237, "naklon": 5 }, +{ "label": "45/2", "node": 4226, "naklon": 5 }, +{ "label": "45/3", "node": 4242, "naklon": 5 }, +{ "label": "45/4", "node": 4179, "naklon": 5 }, +{ "label": "45/5", "node": 4247, "naklon": 5 }, +{ "label": "45/6", "node": 4245, "naklon": 5 }, +{ "label": "45/7", "node": 3872, "naklon": 5 }, +{ "label": "45/8", "node": 4175, "naklon": 5 }, +{ "label": "45/9", "node": 4236, "naklon": 5 }, +{ "label": "45/10", "node": 4170, "naklon": 5 }, +{ "label": "45/11", "node": 4238, "naklon": 5 }, +{ "label": "45/12", "node": 4246, "naklon": 5 }, +{ "label": "45/13", "node": 4166, "naklon": 5 }, +{ "label": "45/14", "node": 4227, "naklon": 5 }, +{ "label": "45/15", "node": 4171, "naklon": 5 }, +{ "label": "45/16", "node": 4180, "naklon": 5 }, +{ "label": "45/17", "node": 4244, "naklon": 5 }, +{ "label": "45/18", "node": 4199, "naklon": 5 }, +{ "label": "45/19", "node": 4239, "naklon": 5 }, +{ "label": "45/20", "node": 4207, "naklon": 5 }, +{ "label": "45/21", "node": 4223, "naklon": 5 }, +{ "label": "45/22", "node": 4230, "naklon": 5 }, +{ "label": "45/23", "node": 4233, "naklon": 5 }, +{ "label": "45/24", "node": 4222, "naklon": 5 }, +{ "label": "45/25", "node": 4217, "naklon": 5 }, +{ "label": "45/26", "node": 4243, "naklon": 5 }, +{ "label": "45/27", "node": 4200, "naklon": 5 }, +{ "label": "45/28", "node": 4228, "naklon": 5 }, +{ "label": "45/29", "node": 4211, "naklon": 5 }, +{ "label": "45/30", "node": 4234, "naklon": 5 }, +{ "label": "45/31", "node": 4235, "naklon": 5 }, +{ "label": "45/32", "node": 4203, "naklon": 5 }, +{ "label": "45/33", "node": 4240, "naklon": 5 }, +{ "label": "45/34", "node": 4224, "naklon": 5 }, +{ "label": "45/35", "node": 4232, "naklon": 5 }, +{ "label": "45/36", "node": 4231, "naklon": 5 }, +{ "label": "45/37", "node": 4161, "naklon": 5 }, +{ "label": "45/38", "node": 4225, "naklon": 5 }, +{ "label": "45/39", "node": 4241, "naklon": 5 }, +{ "label": "45/40", "node": 4229, "naklon": 5 }, +{ "label": "45/41", "node": 4221, "naklon": 5 }, +{ "label": "45/42", "node": 4212, "naklon": 5 }, +{ "label": "45/43", "node": 4216, "naklon": 5 }, +{ "label": "45/44", "node": 3864, "naklon": null }, +{ "label": "46/1", "node": 3806, "naklon": 5 }, +{ "label": "46/2", "node": 3813, "naklon": 5 }, +{ "label": "46/3", "node": 3815, "naklon": 5 }, +{ "label": "46/4", "node": 3807, "naklon": 5 }, +{ "label": "46/5", "node": 3895, "naklon": 5 }, +{ "label": "46/6", "node": 3809, "naklon": 5 }, +{ "label": "46/7", "node": 3820, "naklon": 5 }, +{ "label": "46/8", "node": 3805, "naklon": 5 }, +{ "label": "46/9", "node": 3894, "naklon": 0 }, +{ "label": "46/10", "node": 4055, "naklon": 0 }, +{ "label": "46/11", "node": 3812, "naklon": 5 }, +{ "label": "46/12", "node": 3822, "naklon": 5 }, +{ "label": "46/13", "node": 3821, "naklon": 5 }, +{ "label": "46/14", "node": 3808, "naklon": 5 }, +{ "label": "46/15", "node": 3799, "naklon": 5 }, +{ "label": "46/16", "node": 3816, "naklon": 5 }, +{ "label": "46/17", "node": 3751, "naklon": 5 }, +{ "label": "46/18", "node": 3814, "naklon": 5 }, +{ "label": "46/19", "node": 4044, "naklon": 0 }, +{ "label": "46/20", "node": 3931, "naklon": 0 }, +{ "label": "46/21", "node": 3902, "naklon": 5 }, +{ "label": "46/22", "node": 3916, "naklon": 5 }, +{ "label": "46/23", "node": 3892, "naklon": 5 }, +{ "label": "46/24", "node": 3914, "naklon": 5 }, +{ "label": "46/25", "node": 3898, "naklon": 5 }, +{ "label": "46/26", "node": 3897, "naklon": 5 }, +{ "label": "46/27", "node": 3885, "naklon": 5 }, +{ "label": "46/28", "node": 3906, "naklon": 5 }, +{ "label": "46/29", "node": 3930, "naklon": 0 }, +{ "label": "46/30", "node": 3936, "naklon": 0 }, +{ "label": "46/31", "node": 3860, "naklon": 5 }, +{ "label": "46/32", "node": 3841, "naklon": 5 }, +{ "label": "46/33", "node": 3873, "naklon": 5 }, +{ "label": "46/34", "node": 3854, "naklon": 5 }, +{ "label": "46/35", "node": 3939, "naklon": 5 }, +{ "label": "46/36", "node": 3858, "naklon": 5 }, +{ "label": "46/37", "node": 3940, "naklon": 5 }, +{ "label": "46/38", "node": 4035, "naklon": 5 }, +{ "label": "47/1", "node": 3373, "naklon": 0 }, +{ "label": "47/2", "node": 3374, "naklon": 0 }, +{ "label": "47/3", "node": 3384, "naklon": 0 }, +{ "label": "47/4", "node": 3385, "naklon": 0 }, +{ "label": "48/1", "node": 4051, "naklon": 5 }, +{ "label": "48/2", "node": 4041, "naklon": 5 }, +{ "label": "48/3", "node": 4056, "naklon": 5 }, +{ "label": "48/4", "node": 3875, "naklon": 5 }, +{ "label": "48/5", "node": 4061, "naklon": 5 }, +{ "label": "48/6", "node": 4047, "naklon": 5 }, +{ "label": "48/7", "node": 4060, "naklon": 5 }, +{ "label": "48/8", "node": 4059, "naklon": 5 }, +{ "label": "48/9", "node": 4058, "naklon": 5 }, +{ "label": "48/10", "node": 3635, "naklon": 5 }, +{ "label": "48/11", "node": 3640, "naklon": 5 }, +{ "label": "48/12", "node": 3747, "naklon": 5 }, +{ "label": "48/13", "node": 3629, "naklon": 5 }, +{ "label": "48/14", "node": 4048, "naklon": 5 }, +{ "label": "48/15", "node": 4063, "naklon": 5 }, +{ "label": "48/16", "node": 4062, "naklon": 5 }, +{ "label": "48/17", "node": 4043, "naklon": 5 }, +{ "label": "48/18", "node": 4052, "naklon": 5 }, +{ "label": "48/19", "node": 4042, "naklon": 5 }, +{ "label": "48/20", "node": 4053, "naklon": 5 }, +{ "label": "50/15A", "node": 4167, "naklon": null }, +{ "label": "50/15B", "node": 4159, "naklon": null }, +{ "label": "50/1", "node": 4183, "naklon": 0 }, +{ "label": "50/2", "node": 4157, "naklon": 0 }, +{ "label": "50/3", "node": 4160, "naklon": 0 }, +{ "label": "50/4", "node": 4173, "naklon": 0 }, +{ "label": "50/5", "node": 4177, "naklon": 0 }, +{ "label": "50/6", "node": 4174, "naklon": 0 }, +{ "label": "50/7", "node": 4178, "naklon": 0 }, +{ "label": "50/8", "node": 4195, "naklon": 0 }, +{ "label": "50/9", "node": 4169, "naklon": 0 }, +{ "label": "50/10", "node": 4162, "naklon": 0 }, +{ "label": "50/11", "node": 4158, "naklon": 0 }, +{ "label": "50/12", "node": 4182, "naklon": 0 }, +{ "label": "50/13", "node": 4194, "naklon": 0 }, +{ "label": "50/14", "node": 4184, "naklon": 0 }, +{ "label": "50/16", "node": 4197, "naklon": null }, +{ "label": "50/17", "node": 4164, "naklon": null }, +{ "label": "50/18", "node": 3306, "naklon": null }, +{ "label": "50/19", "node": 4168, "naklon": null }, +{ "label": "50/20", "node": 4193, "naklon": null }, +{ "label": "50/21", "node": 4187, "naklon": null }, +{ "label": "50/22", "node": 4163, "naklon": null }, +{ "label": "50/23", "node": 4165, "naklon": null }, +{ "label": "50/24", "node": 4185, "naklon": null }, +{ "label": "50/25", "node": 3904, "naklon": null }, +{ "label": "53/1", "node": 2619, "naklon": 0 }, +{ "label": "53/2", "node": 2623, "naklon": 0 }, +{ "label": "53/3", "node": 2617, "naklon": 0 }, +{ "label": "53/4", "node": 2622, "naklon": 0 }, +{ "label": "53/5", "node": 2618, "naklon": 0 }, +{ "label": "53/6", "node": 2626, "naklon": 0 }, +{ "label": "53/7", "node": 2869, "naklon": 0 }, +{ "label": "53/8", "node": 2613, "naklon": 0 }, +{ "label": "53/9", "node": 2608, "naklon": 0 }, +{ "label": "53/10", "node": 2611, "naklon": 0 }, +{ "label": "53/11", "node": 2598, "naklon": 0 }, +{ "label": "53/12", "node": 3528, "naklon": 0 }, +{ "label": "53/13", "node": 3545, "naklon": 0 }, +{ "label": "53/14", "node": 2620, "naklon": 0 }, +{ "label": "53/15", "node": 2612, "naklon": 0 }, +{ "label": "53/16", "node": 2615, "naklon": 0 }, +{ "label": "53/17", "node": 3722, "naklon": 0 }, +{ "label": "53/18", "node": 2624, "naklon": 0 }, +{ "label": "53/19", "node": 2609, "naklon": 0 }, +{ "label": "53/20", "node": 2625, "naklon": 0 }, +{ "label": "53/21", "node": 2602, "naklon": 0 }, +{ "label": "53/22", "node": 2610, "naklon": 0 }, +{ "label": "53/23", "node": 2599, "naklon": 0 }, +{ "label": "53/24", "node": 2605, "naklon": 0 }, +{ "label": "53/25", "node": 2593, "naklon": 0 }, +{ "label": "53/26", "node": 3074, "naklon": 0 }, +{ "label": "53/27", "node": 2740, "naklon": 0 }, +{ "label": "53/28", "node": 2614, "naklon": 0 }, +{ "label": "53/29", "node": 2601, "naklon": 0 }, +{ "label": "53/30", "node": 4196, "naklon": 0 }, +{ "label": "53/31", "node": 2607, "naklon": 0 }, +{ "label": "53/32", "node": 2582, "naklon": 0 }, +{ "label": "53/33", "node": 2594, "naklon": 0 }, +{ "label": "53/34", "node": 2589, "naklon": 0 }, +{ "label": "53/35", "node": 2596, "naklon": 0 }, +{ "label": "53/36", "node": 2603, "naklon": 0 }, +{ "label": "53/37", "node": 2597, "naklon": 0 }, +{ "label": "53/38", "node": 2590, "naklon": 0 }, +{ "label": "53/39", "node": 2581, "naklon": 0 }, +{ "label": "53/40", "node": 2583, "naklon": 0 }, +{ "label": "53/41", "node": 2580, "naklon": 0 }, +{ "label": "53/42", "node": 2579, "naklon": 0 }, +{ "label": "53/43", "node": 2797, "naklon": 0 }, +{ "label": "53/44", "node": 2577, "naklon": 0 }, +{ "label": "53/45", "node": 2586, "naklon": 0 }, +{ "label": "53/46", "node": 2588, "naklon": 0 }, +{ "label": "53/47", "node": 2591, "naklon": 0 }, +{ "label": "53/48", "node": 2592, "naklon": 0 }, +{ "label": "53/49", "node": 2573, "naklon": 0 }, +{ "label": "53/50", "node": 2595, "naklon": 0 }, +{ "label": "53/51", "node": 2587, "naklon": 0 }, +{ "label": "53/52", "node": 2578, "naklon": 0 }, +{ "label": "53/53", "node": 2574, "naklon": 0 }, +{ "label": "53/54", "node": 2571, "naklon": 0 }, +{ "label": "53/55", "node": 2570, "naklon": 0 }, +{ "label": "53/56", "node": 2576, "naklon": 0 }, +{ "label": "53/57", "node": 2881, "naklon": 0 }, +{ "label": "53/58", "node": 2575, "naklon": 0 }, +{ "label": "53/59", "node": 2572, "naklon": 0 }, +{ "label": "53/60", "node": 2569, "naklon": 0 }, +{ "label": "55/1", "node": 4324, "naklon": 0 }, +{ "label": "55/2", "node": 4319, "naklon": 0 }, +{ "label": "55/3", "node": 4327, "naklon": 0 }, +{ "label": "55/4", "node": 4333, "naklon": 0 }, +{ "label": "55/5", "node": 4332, "naklon": 0 }, +{ "label": "55/6", "node": 4320, "naklon": 0 }, +{ "label": "55/7", "node": 4317, "naklon": 0 }, +{ "label": "55/8", "node": 4318, "naklon": 0 }, +{ "label": "55/9", "node": 4328, "naklon": 0 }, +{ "label": "55/10", "node": 4323, "naklon": 0 }, +{ "label": "55/11", "node": 4325, "naklon": 0 }, +{ "label": "55/12", "node": 4326, "naklon": 0 }, +{ "label": "55/13", "node": 4316, "naklon": 0 }, +{ "label": "55/14", "node": 4322, "naklon": 0 }, +{ "label": "55/15", "node": 4331, "naklon": 0 }, +{ "label": "55/16", "node": 4321, "naklon": 0 }, +{ "label": "55/17", "node": 4315, "naklon": 0 }, +{ "label": "55/18", "node": 4329, "naklon": 0 }, +{ "label": "55/19", "node": 4334, "naklon": 0 }, +{ "label": "55/20", "node": 4330, "naklon": 0 } +]; + +module.exports = { naklony }; diff --git a/RVO46/databases/modbus_config.js b/RVO46/databases/modbus_config.js new file mode 100755 index 0000000..b73116a --- /dev/null +++ b/RVO46/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/RVO46/databases/nodes.table b/RVO46/databases/nodes.table new file mode 100755 index 0000000..b94696b --- /dev/null +++ b/RVO46/databases/nodes.table @@ -0,0 +1,39 @@ +node:number|pole_number:string|node_type:string|tbname:string|line:number|profile:string|processed:boolean|status:boolean|time_of_last_communication:number ++|3805|8|NEMA|EjgWGnXaLy9opPOz20n66m086BlYM3w1deVQvbKr|1||1|1|1760574084969|............. ++|3806|1|NEMA|dz4ojlpP85JMgDLZWkQOODAaKYqQexEr62GXRV1y|1||1|1|1760574085161|............. ++|4352|16|NEMA|nJL5lPMwBx23YpqRe0rllw7damXvWVbOrD4gNzy8|1||1|1|1760574116487|............. ++|3820|7|NEMA|3a5oqJN1bgnx4Ol9dk866wAByE6jQ8mKDWMpGrLV|1||1|1|1760574087623|............. ++|3821|13|NEMA|rDbQ84xzwgdqEoPm3kbJJrk9anOZY1RXyBv2LVM6|1||1|1|1760574092210|............. ++|4121|12|NEMA|52dD6ZlV1QaOpRBmbAqKKMkKnGzWMLj4eJq38Pgo|1||1|1|1760574055929|............. ++|3841|32|NEMA|JzwxZXOvDj1bVrN4nkWw2Nk8qdyBl3MRKLpGPgaQ|1||1|1|1760574093249|............. ++|3854|34|NEMA|OzNMgZ9n43qPbjXmy7zW8aA2DKdYvW5e6pxGRrVa|1||1|1|1760574095438|............. ++|3860|31|NEMA|m6EYyZoJ4gWexdjVPARNrwARDOq9wv2N5XzKGplr|1||1|1|1760574100105|............. ++|3873|33|NEMA|g9OxBZ5KRwNznlY6pAp6wEkWXvjdEL4eGQobMDy2|1||1|1|1760574101991|............. ++|3885|27|NEMA|gP1eOZVj3Q9lv5aDEk4E2M7rdpqW8yLm2BbKzJxM|1||1|1|1760574103046|............. ++|3892|23|NEMA|BaY3Xpy1EbKGjLq2O7mGG60rx8owgQz9P4dDJRmN|1||1|1|1760574104484|............. ++|3894|9|NEMA|wvKJdZML6mXP4DzWBAXWWB7jxNloa5g23Ve9Y1ry|1||1|1|1760574104628|............. ++|3895|5|NEMA|ZmRwd93QL4gaezxEbAxWWX71prn2XjlPvGyqJ6BO|1||1|1|1760574105172|............. ++|3897|26|NEMA|o9vbeQlLMVg8j5dq4kegKbANxZpEmnXzwYKO1ar2|1||1|1|1760574045428|............. ++|3808|14|NEMA|E6Kg9oDnLWyzPRMva7vrrj7Jxp4VG58qO2w1lZYe|1||1|1|1760574085865|............. ++|3898|25|NEMA|apKVJBwOyrP35m2lv7KzD5kYXbeWNd64En9GxRqg|1||1|1|1760574073766|............. ++|3902|21|NEMA|5dBNwRp9graYJxZn409wwQ7lVov1b2QLPDqGm6XK|1||1|1|1760574073925|............. ++|3906|28|NEMA|2O14VBzl8aDmWdNw3A51z9AGyZ5qLJoEMpj6R9ng|1||1|1|1760574074101|............. ++|3914|24|NEMA|DbQY6zyveZRwK5drV0Z99bAjoE4XJM83N9xl2nWq|1||1|1|1760573975904|............. ++|4369|22|NEMA|zrR51V2ajQ9ZLygPKkEmmxkYDq38xOJolENBXGnv|1||1|1|1760574079903|............. ++|3809|6|NEMA|eod9aRWLVl34Gx1Dn7VoobA2rz6qjgmpEXwQJN5Z|1||1|1|1760574086056|............. ++|3812|11|NEMA|PLBJzmK1r3Gynd6OW0gGGo0e5wV4vx9bDEqNgYR8|1||1|1|1760574086216|............. ++|3931|20|NEMA|WlVJBygjDZMeKX3vnAMzzj08NqdmG2x1Y69LQ4P5|1||1|1|1760574108033|............. ++|3936|30|NEMA|6lQGaY9RDywdVzObj0P1OOkPg4NBn3exEK51LWZq|1||1|1|1760574006750|............. ++|3939|35|NEMA|JX1ObgmqGZ54DMyYL7a98m7EVdve38WKRzwjNrQ9|1||1|1|1760574110638|............. ++|3940|37|NEMA|RO8rjaBDy21qPQJzW7oD4OApK3xmNleVZg9Ed4Gw|1||1|1|1760574111149|............. ++|4035|38|NEMA|3JjOWdylwgNLzxVab7NEwKkZ2vG64rq8PEB5QmDo|1||1|1|1760574119956|............. ++|4044|19|NEMA|zdQO8GwxDqjRgP4137Y1167NyKlpem2nL65rvVJY|1||1|1|1760574055593|............. ++|3813|2|NEMA|d9x2V5LGYBzXp4mMRAOBBn7PloaqJwnQj6DgrNe3|1||1|1|1760574086392|............. ++|4055|10|NEMA|Nzp2OoJlqn6r1ZgvdA3GGjAabBwP5G4eE3RQmyxD|1||1|1|1760574055753|............. ++|3751|17|NEMA|XMBbew5z4ELrZa2mRAd55V08vPN6gy3DdVYlpKjq|1||1|1|1760574073606|............. ++|3814|18|NEMA|gYbDLqlyZVoRerQpB72rrL7WJnwM5z24POKa8Exj|1||1|1|1760574086584|............. ++|3807|4|NEMA|aw4eELG2DlPMdn1JW0B11qAqQXOZRN3xB5yp8VKr|1||1|1|1760574085337|............. ++|3799|15|NEMA|roKgWqY95V3mXMRzyAjmmj7bLjexpJPvaGDBw826|1||1|1|1760574080270|............. ++|3815|3|NEMA|B5EoxeMVp4zwr8nqW0GjjoARjvD1PNamOGbLg63Z|1||1|1|1760574087159|............. ++|3858|36|NEMA|RvmwNz8QPblKp41GD7lDEZ7JrLVYoBO92dMegn6W|1||1|1|1760574095614|............. ++|3930|29|NEMA|pE5X8NQPaow6vlOZxk6gNg7q42ezGBMyWgDVjR3L|1||1|1|1760574005535|............. diff --git a/RVO46/databases/nodes_original/nodes_original.table b/RVO46/databases/nodes_original/nodes_original.table new file mode 100755 index 0000000..ff51531 --- /dev/null +++ b/RVO46/databases/nodes_original/nodes_original.table @@ -0,0 +1 @@ +[{"3805": "EjgWGnXaLy9opPOz20n66m086BlYM3w1deVQvbKr"}, {"3806": "dz4ojlpP85JMgDLZWkQOODAaKYqQexEr62GXRV1y"}, {"4352": "nJL5lPMwBx23YpqRe0rllw7damXvWVbOrD4gNzy8"}, {"3820": "3a5oqJN1bgnx4Ol9dk866wAByE6jQ8mKDWMpGrLV"}, {"3821": "rDbQ84xzwgdqEoPm3kbJJrk9anOZY1RXyBv2LVM6"}, {"4121": "52dD6ZlV1QaOpRBmbAqKKMkKnGzWMLj4eJq38Pgo"}, {"3841": "JzwxZXOvDj1bVrN4nkWw2Nk8qdyBl3MRKLpGPgaQ"}, {"3854": "OzNMgZ9n43qPbjXmy7zW8aA2DKdYvW5e6pxGRrVa"}, {"3860": "m6EYyZoJ4gWexdjVPARNrwARDOq9wv2N5XzKGplr"}, {"3873": "g9OxBZ5KRwNznlY6pAp6wEkWXvjdEL4eGQobMDy2"}, {"3885": "gP1eOZVj3Q9lv5aDEk4E2M7rdpqW8yLm2BbKzJxM"}, {"3892": "BaY3Xpy1EbKGjLq2O7mGG60rx8owgQz9P4dDJRmN"}, {"3894": "wvKJdZML6mXP4DzWBAXWWB7jxNloa5g23Ve9Y1ry"}, {"3895": "ZmRwd93QL4gaezxEbAxWWX71prn2XjlPvGyqJ6BO"}, {"3897": "o9vbeQlLMVg8j5dq4kegKbANxZpEmnXzwYKO1ar2"}, {"3808": "E6Kg9oDnLWyzPRMva7vrrj7Jxp4VG58qO2w1lZYe"}, {"3898": "apKVJBwOyrP35m2lv7KzD5kYXbeWNd64En9GxRqg"}, {"3902": "5dBNwRp9graYJxZn409wwQ7lVov1b2QLPDqGm6XK"}, {"3906": "2O14VBzl8aDmWdNw3A51z9AGyZ5qLJoEMpj6R9ng"}, {"3914": "DbQY6zyveZRwK5drV0Z99bAjoE4XJM83N9xl2nWq"}, {"4369": "zrR51V2ajQ9ZLygPKkEmmxkYDq38xOJolENBXGnv"}, {"3809": "eod9aRWLVl34Gx1Dn7VoobA2rz6qjgmpEXwQJN5Z"}, {"3812": "PLBJzmK1r3Gynd6OW0gGGo0e5wV4vx9bDEqNgYR8"}, {"3931": "WlVJBygjDZMeKX3vnAMzzj08NqdmG2x1Y69LQ4P5"}, {"3936": "6lQGaY9RDywdVzObj0P1OOkPg4NBn3exEK51LWZq"}, {"3939": "JX1ObgmqGZ54DMyYL7a98m7EVdve38WKRzwjNrQ9"}, {"3940": "RO8rjaBDy21qPQJzW7oD4OApK3xmNleVZg9Ed4Gw"}, {"4035": "3JjOWdylwgNLzxVab7NEwKkZ2vG64rq8PEB5QmDo"}, {"4044": "zdQO8GwxDqjRgP4137Y1167NyKlpem2nL65rvVJY"}, {"3813": "d9x2V5LGYBzXp4mMRAOBBn7PloaqJwnQj6DgrNe3"}, {"4055": "Nzp2OoJlqn6r1ZgvdA3GGjAabBwP5G4eE3RQmyxD"}, {"3751": "XMBbew5z4ELrZa2mRAd55V08vPN6gy3DdVYlpKjq"}, {"3814": "gYbDLqlyZVoRerQpB72rrL7WJnwM5z24POKa8Exj"}, {"3807": "aw4eELG2DlPMdn1JW0B11qAqQXOZRN3xB5yp8VKr"}, {"3799": "roKgWqY95V3mXMRzyAjmmj7bLjexpJPvaGDBw826"}, {"3815": "B5EoxeMVp4zwr8nqW0GjjoARjvD1PNamOGbLg63Z"}, {"3858": "RvmwNz8QPblKp41GD7lDEZ7JrLVYoBO92dMegn6W"}, {"3930": "pE5X8NQPaow6vlOZxk6gNg7q42ezGBMyWgDVjR3L"}] \ No newline at end of file diff --git a/RVO46/databases/notifications.table b/RVO46/databases/notifications.table new file mode 100755 index 0000000..f7c96cb --- /dev/null +++ b/RVO46/databases/notifications.table @@ -0,0 +1,41 @@ +key:string|weight:string|sk:string|en:string ++|switching_profile_point_applied_to_line|INFORMATIONAL|Aplikovaný bod spínacieho profilu na línií č. ${line} : ${value}|Switching profile point applied to line no. ${line} : ${value}|............... ++|dusk_has_occured|INFORMATIONAL|Nastal súmrak: ${value}|Dusk has occured: ${value}|............... ++|dawn_has_occured|INFORMATIONAL|Nastal úsvit: ${value}|Dawn has occured: ${value}|............... ++|dimming_profile_was_successfully_received_by_node|NOTICE|Stmievací profil bol úspešne prijatý nodom č. ${node}|Dimming profile was successfully received by node no. ${node}|............... ++|master_node_is_responding_again|NOTICE|Master node začal znovu odpovedať|Master node is responding again|............... ++|command_was_sent_from_terminal_interface|DEBUG|Z terminálu bol odoslaný príkaz|A command was sent from terminal interface|............... ++|master_node_is_not_responding|ALERT|Master node neodpovedá|Master node is not responding|............... ++|configuration_of_dimming_profile_to_node_failed|ALERT|Konfigurácia stmievacieho profilu pre node č. ${node} zlyhala|Configuration of dimming profile to node no. ${node} has failed|............... ++|circuit_breaker_was_turned_on_line|NOTICE|Zapnutie ističa na línii č. ${line}|Circuit breaker was turned on - line no. ${line}|............... ++|circuit_breaker_was_turned_off_line|ERROR|Vypnutie ističa na línií č. ${line}|Circuit breaker was turned off - line no. ${line}|............... ++|dimming_profile_was_processed_for_node|INFORMATIONAL|Stmievací profil bol spracovaný pre node č. ${node}|Dimming profile was processed for node no. ${node}|............... ++|switching_profile_was_processed_for_line|INFORMATIONAL|Spínací profil bol spracovaný pre líniu č. ${line}|Switching profile was processed for line no. ${line}|............... ++|thermometer_is_not_responding|WARNING|Teplomer neodpovedá|Thermometer is not responding|............... ++|thermometer_is_responding_again|NOTICE|Teplomer znovu odpovedá|Thermometer is responding again|............... ++|thermometer_sends_invalid_data|WARNING|Teplomer posiela neplatné hodnoty|Thermometer sends invalid data|............... ++|main_switch_has_been_turned_off|CRITICAL|Hlavný vypínač bol vypnutý|Main switch has been turned off|............... ++|main_switch_has_been_turned_on|NOTICE|Hlavný vypínač bol zapnutý|Main switch has been turned on|............... ++|power_supply_has_disconnected_input|ALERT|Napájací zdroj nemá napätie na vstupe|Power supply has disconnected input|............... ++|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_main_open|NOTICE|Hlavné dvere boli otvorené|Main door has been opened|............... ++|door_em_open|NOTICE|Dvere silovej časti boli otvorené|Power door has been opened|............... ++|door_main_open_without_permission|WARNING|Hlavné dvere boli otvorené bez povolenia - zapnutá siréna|Main door has been opened without permission - alarm is on|............... ++|door_em_open_without_permission|WARNING|Dvere silovej časti boli otvorené bez povolenia|Power door has been opened without permission|............... ++|door_main_close|NOTICE|Hlavné dvere boli zatvorené|Main door has been closed|............... ++|door_em_close|NOTICE|Dvere silovej časti boli zatvorené|Power door has been closed|............... ++|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|............... ++|electrometer_ok|NOTICE|Elektromer znovu odpovedá|Electrometer is responding again|............... ++|no_voltage_on_phase|CRITICAL|Na fáze č. ${phase} nie je napätie|No voltage detected on phase no. ${phase}|............... ++|voltage_on_phase_restored|NOTICE|Napätie na fáze č. ${phase} bolo obnovené|Voltage on phase no. ${phase} has been restored|............... ++|flow_start|NOTICE|FLOW bol spustený|FLOW has been started |............... ++|twilight_sensor_nok|ERROR|Sensor súmraku neodpovedá|Twilight sensor is not responding|............... ++|twilight_sensor_ok|NOTICE|Sensor súmraku znovu odpovedá|Twilight sensor is responding again|............... ++|lamps_have_turned_on|NOTICE|Lampy sa zapli|Lamps have turned on|............... ++|lamps_have_turned_off|NOTICE|Lampy sa vypli|Lamps have turned off|............... ++|flow_restart|NOTICE|FLOW bol reštartovaný|FLOW has been restarted|............... ++|nodes_db_changed|NOTICE|Zmena v node databáze|Node db has changed|............... diff --git a/RVO46/databases/pins.table b/RVO46/databases/pins.table new file mode 100755 index 0000000..0eb3d05 --- /dev/null +++ b/RVO46/databases/pins.table @@ -0,0 +1,14 @@ +pin:string|type:string|line:number +*|input1_01|door_condition|0|........... +*|input1_02|rotary_switch_state|0|........... +*|input1_03|rotary_switch_state|0|........... +*|input1_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/RVO46/databases/relays.table b/RVO46/databases/relays.table new file mode 100755 index 0000000..6c61fb1 --- /dev/null +++ b/RVO46/databases/relays.table @@ -0,0 +1,5 @@ +line:number|tbname:string|contactor:number|profile:string ++|0|RvmwNz8QPblKp41GD7lKWZkJrLVYoBO92dMegn6W|1||........... ++|1|PLBJzmK1r3Gynd6OW0gGdP0e5wV4vx9bDEqNgYR8|9|{"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|52dD6ZlV1QaOpRBmbAqKZQkKnGzWMLj4eJq38Pgo|9|{"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|rDbQ84xzwgdqEoPm3kbJwdk9anOZY1RXyBv2LVM6|9|{"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/RVO46/databases/settings.table b/RVO46/databases/settings.table new file mode 100755 index 0000000..5812d97 --- /dev/null +++ b/RVO46/databases/settings.table @@ -0,0 +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|project_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|cloud_topic:string|has_main_switch:boolean|daily_report:boolean|send_changed_node_numbers:boolean ++|rvo_senica_46_10.0.0.133|en|28.34739C0E0000|48.70826502|17.28455203|192.168.252.1|rvo_senica_46_10.0.0.133|4FpLD3ZlETLYlDbb2oDv|1883|0|69|unipi|ttyUSB0|1|20|5|6|3|u133|0|1|1|................................................... diff --git a/RVO46/databases/tbdata.nosql b/RVO46/databases/tbdata.nosql new file mode 100755 index 0000000..3b2edcc --- /dev/null +++ b/RVO46/databases/tbdata.nosql @@ -0,0 +1,4 @@ +-"RvmwNz8QPblKp41GD7lKWZkJrLVYoBO92dMegn6W":[{"ts":1760531110341,"values":{"_event":{"type":"notice","status":"new","source":{"func":"modbus_reader","component":"1699965957410","component_name":"Modbus reader","edge":"RvmwNz8QPblKp41GD7lKWZkJrLVYoBO92dMegn6W"},"message":{"sk":"rvo_senica_46_10.0.0.133: FLOW bol reštartovaný","en":"rvo_senica_46_10.0.0.133: FLOW has been restarted"},"message_data":""}}}],"id":"3000325001oe71b"} +-"RvmwNz8QPblKp41GD7lKWZkJrLVYoBO92dMegn6W":[{"ts":1760531110432,"values":{"edge_fw_version":"2025-10-08","maintenance_mode":false}}],"id":"3000325002oe70b"} +-"RvmwNz8QPblKp41GD7lKWZkJrLVYoBO92dMegn6W":[{"ts":1760531110445,"values":{"statecode":2,"power_mode":"Automatic"}}],"id":"3000325004oe70b"} +-"RvmwNz8QPblKp41GD7lKWZkJrLVYoBO92dMegn6W":[{"ts":1760531110476,"values":{"_event":{"type":"notice","status":"new","source":{"func":"rsPort.open()","component":"1699963668903","component_name":"DIDO_Controller","edge":"RvmwNz8QPblKp41GD7lKWZkJrLVYoBO92dMegn6W"},"message":{"sk":"rvo_senica_46_10.0.0.133: FLOW bol spustený","en":"rvo_senica_46_10.0.0.133: FLOW has been started "},"message_data":""}}}],"id":"3000325006oe70b"} diff --git a/RVO46/databases/tbdatacloud.nosql b/RVO46/databases/tbdatacloud.nosql new file mode 100755 index 0000000..5555395 --- /dev/null +++ b/RVO46/databases/tbdatacloud.nosql @@ -0,0 +1,3 @@ +-"RvmwNz8QPblKp41GD7lKWZkJrLVYoBO92dMegn6W":[{"ts":1760531110432,"values":{"edge_fw_version":"2025-10-08","maintenance_mode":false}}],"id":"3000325003oe71b"} +-"RvmwNz8QPblKp41GD7lKWZkJrLVYoBO92dMegn6W":[{"ts":1760531110445,"values":{"statecode":2,"power_mode":"Automatic"}}],"id":"3000325005oe71b"} +-"RvmwNz8QPblKp41GD7lKWZkJrLVYoBO92dMegn6W":[{"ts":1760531110476,"values":{"_event":{"type":"notice","status":"new","source":{"func":"rsPort.open()","component":"1699963668903","component_name":"DIDO_Controller","edge":"RvmwNz8QPblKp41GD7lKWZkJrLVYoBO92dMegn6W"},"message":{"sk":"rvo_senica_46_10.0.0.133: FLOW bol spustený","en":"rvo_senica_46_10.0.0.133: FLOW has been started "},"message_data":""}}}],"id":"3000325007oe71b"} diff --git a/RVO46/databases/total_energy.js b/RVO46/databases/total_energy.js new file mode 100755 index 0000000..dde340e --- /dev/null +++ b/RVO46/databases/total_energy.js @@ -0,0 +1,38 @@ +//key is rvo_number, value is max energy when lamps are on +const total_energy = { + 1: 580, + 2: 1100, + 3: 3700, + 4: 4100, + 7: 360, + 12: 1700, + 13: 5400, + 14: 440, + 15: 6100, + 16: 4800, + 20: 1600, + 21: 1000, + 22: 2600, + 23: 1000, + 25: 2600, + 33: 240, + 34: 4000, + 35: 2700, + 36: 820, + 37: 1400, + 35: 3500, + 39: 1170, + 41: 740, + 42: 660, + 43: 4900, + 45: 930, + 46: 700, + 47: 1100, + 48: 1500, + 50: 3200, + 53: 1250, + 55: 1000, + 56: 5500 +} + +module.exports = total_energy; diff --git a/RVO46/debug.js b/RVO46/debug.js new file mode 100755 index 0000000..9818194 --- /dev/null +++ b/RVO46/debug.js @@ -0,0 +1,16 @@ +// =================================================== +// FOR DEVELOPMENT +// Total.js - framework for Node.js platform +// https://www.totaljs.com +// =================================================== + +const options = {}; + +// options.ip = '127.0.0.1'; +// options.port = parseInt(process.argv[2]); +// options.config = { name: 'Total.js' }; +// options.sleep = 3000; +// options.inspector = 9229; +// options.watch = ['private']; + +require('total.js/debug')(options); \ No newline at end of file diff --git a/RVO46/err.txt b/RVO46/err.txt new file mode 100755 index 0000000..d37a47c --- /dev/null +++ b/RVO46/err.txt @@ -0,0 +1,134 @@ +[2024-10-26T03:47:57.945] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T04:48:33.267] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T05:49:06.579] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T06:49:43.762] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T07:50:11.360] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T08:50:50.459] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T09:51:25.738] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T10:51:59.029] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T11:52:05.140] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T12:52:52.076] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T13:53:23.415] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T14:53:37.371] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T15:53:59.059] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T16:54:22.651] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T17:54:46.234] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T18:55:21.574] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T19:55:49.109] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T20:56:32.181] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T21:57:05.504] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-11-28T09:55:06.333] [ERROR] errLogs - uncaughtException: WebSocket is not open: readyState 0 (CONNECTING) +[2024-11-28T09:55:06.334] [ERROR] errLogs - Error: WebSocket is not open: readyState 0 (CONNECTING) + at WebSocket.send (/home/unipi/flowserver/node_modules/ws/lib/websocket.js:394:13) + at turnAlarm (/home/unipi/flowserver/flow/dido_controller.js:487:10) + at WebSocket.open (/home/unipi/flowserver/flow/dido_controller.js:337:7) + at WebSocket.onOpen (/home/unipi/flowserver/node_modules/ws/lib/event-target.js:144:16) + at WebSocket.emit (events.js:400:28) + at WebSocket.setSocket (/home/unipi/flowserver/node_modules/ws/lib/websocket.js:225:10) + at ClientRequest. (/home/unipi/flowserver/node_modules/ws/lib/websocket.js:882:15) + at ClientRequest.emit (events.js:400:28) + at Socket.socketOnData (_http_client.js:553:11) + at Socket.emit (events.js:400:28) +[2024-11-28T09:55:06.335] [ERROR] errLogs - uncaughtException: WebSocket is not open: readyState 0 (CONNECTING) +[2024-11-28T09:55:06.335] [ERROR] errLogs - Error: WebSocket is not open: readyState 0 (CONNECTING) + at WebSocket.send (/home/unipi/flowserver/node_modules/ws/lib/websocket.js:394:13) + at turnAlarm (/home/unipi/flowserver/flow/dido_controller.js:487:10) + at WebSocket.open (/home/unipi/flowserver/flow/dido_controller.js:337:7) + at WebSocket.onOpen (/home/unipi/flowserver/node_modules/ws/lib/event-target.js:144:16) + at WebSocket.emit (events.js:400:28) + at WebSocket.setSocket (/home/unipi/flowserver/node_modules/ws/lib/websocket.js:225:10) + at ClientRequest. (/home/unipi/flowserver/node_modules/ws/lib/websocket.js:882:15) + at ClientRequest.emit (events.js:400:28) + at Socket.socketOnData (_http_client.js:553:11) + at Socket.emit (events.js:400:28) +[2024-11-28T09:55:06.346] [ERROR] errLogs - uncaughtException: WebSocket is not open: readyState 0 (CONNECTING) +[2024-11-28T09:55:06.347] [ERROR] errLogs - Error: WebSocket is not open: readyState 0 (CONNECTING) + at WebSocket.send (/home/unipi/flowserver/node_modules/ws/lib/websocket.js:394:13) + at turnAlarm (/home/unipi/flowserver/flow/dido_controller.js:487:10) + at WebSocket.open (/home/unipi/flowserver/flow/dido_controller.js:337:7) + at WebSocket.onOpen (/home/unipi/flowserver/node_modules/ws/lib/event-target.js:144:16) + at WebSocket.emit (events.js:400:28) + at WebSocket.setSocket (/home/unipi/flowserver/node_modules/ws/lib/websocket.js:225:10) + at ClientRequest. (/home/unipi/flowserver/node_modules/ws/lib/websocket.js:882:15) + at ClientRequest.emit (events.js:400:28) + at Socket.socketOnData (_http_client.js:553:11) + at Socket.emit (events.js:400:28) +[2024-11-28T10:00:37.357] [ERROR] errLogs - uncaughtException: Cannot read property 'send' of null +[2024-11-28T10:00:37.357] [ERROR] errLogs - TypeError: Cannot read property 'send' of null + at Timeout._onTimeout (/home/unipi/flowserver/flow/dido_controller.js:349:12) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2024-11-28T10:00:37.358] [ERROR] errLogs - uncaughtException: Cannot read property 'send' of null +[2024-11-28T10:00:37.358] [ERROR] errLogs - TypeError: Cannot read property 'send' of null + at Timeout._onTimeout (/home/unipi/flowserver/flow/dido_controller.js:349:12) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2024-11-28T10:00:37.362] [ERROR] errLogs - uncaughtException: Cannot read property 'send' of null +[2024-11-28T10:00:37.363] [ERROR] errLogs - TypeError: Cannot read property 'send' of null + at Timeout._onTimeout (/home/unipi/flowserver/flow/dido_controller.js:349:12) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2024-11-28T10:03:07.412] [ERROR] errLogs - uncaughtException: Cannot read property 'send' of null +[2024-11-28T10:03:07.413] [ERROR] errLogs - TypeError: Cannot read property 'send' of null + at Timeout._onTimeout (/home/unipi/flowserver/flow/dido_controller.js:349:12) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2024-11-28T10:03:07.413] [ERROR] errLogs - uncaughtException: Cannot read property 'send' of null +[2024-11-28T10:03:07.414] [ERROR] errLogs - TypeError: Cannot read property 'send' of null + at Timeout._onTimeout (/home/unipi/flowserver/flow/dido_controller.js:349:12) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2024-11-28T10:03:07.417] [ERROR] errLogs - uncaughtException: Cannot read property 'send' of null +[2024-11-28T10:03:07.417] [ERROR] errLogs - TypeError: Cannot read property 'send' of null + at Timeout._onTimeout (/home/unipi/flowserver/flow/dido_controller.js:349:12) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2024-11-28T10:08:38.455] [ERROR] errLogs - uncaughtException: Cannot read property 'send' of null +[2024-11-28T10:08:38.456] [ERROR] errLogs - TypeError: Cannot read property 'send' of null + at Timeout._onTimeout (/home/unipi/flowserver/flow/dido_controller.js:349:12) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2024-11-28T10:08:38.457] [ERROR] errLogs - uncaughtException: Cannot read property 'send' of null +[2024-11-28T10:08:38.457] [ERROR] errLogs - TypeError: Cannot read property 'send' of null + at Timeout._onTimeout (/home/unipi/flowserver/flow/dido_controller.js:349:12) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2024-11-28T10:08:38.460] [ERROR] errLogs - uncaughtException: Cannot read property 'send' of null +[2024-11-28T10:08:38.461] [ERROR] errLogs - TypeError: Cannot read property 'send' of null + at Timeout._onTimeout (/home/unipi/flowserver/flow/dido_controller.js:349:12) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2024-12-05T13:29:14.624] [ERROR] errLogs - dido controller - port or websocket is not opened +[2025-09-23T14:10:32.343] [ERROR] errLogs - uncaughtException: Cannot read property 'getHours' of undefined +[2025-09-23T14:10:32.343] [ERROR] errLogs - TypeError: Cannot read property 'getHours' of undefined + at Timeout.emptyReportToSend [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:10:32.344] [ERROR] errLogs - uncaughtException: Cannot read property 'getHours' of undefined +[2025-09-23T14:10:32.345] [ERROR] errLogs - TypeError: Cannot read property 'getHours' of undefined + at Timeout.emptyReportToSend [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:10:32.350] [ERROR] errLogs - uncaughtException: Cannot read property 'getHours' of undefined +[2025-09-23T14:10:32.351] [ERROR] errLogs - TypeError: Cannot read property 'getHours' of undefined + at Timeout.emptyReportToSend [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:10:38.074] [ERROR] errLogs - uncaughtException: date.getHours is not a function +[2025-09-23T14:10:38.075] [ERROR] errLogs - TypeError: date.getHours is not a function + at emptyReportToSend (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at Timeout.dailyReportCheck [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1351:5) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:10:38.075] [ERROR] errLogs - uncaughtException: date.getHours is not a function +[2025-09-23T14:10:38.076] [ERROR] errLogs - TypeError: date.getHours is not a function + at emptyReportToSend (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at Timeout.dailyReportCheck [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1351:5) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:10:38.078] [ERROR] errLogs - uncaughtException: date.getHours is not a function +[2025-09-23T14:10:38.079] [ERROR] errLogs - TypeError: date.getHours is not a function + at emptyReportToSend (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at Timeout.dailyReportCheck [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1351:5) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) diff --git a/RVO46/flow/cloudmqttconnect.js b/RVO46/flow/cloudmqttconnect.js new file mode 100755 index 0000000..b03491f --- /dev/null +++ b/RVO46/flow/cloudmqttconnect.js @@ -0,0 +1,357 @@ +exports.id = 'cloudmqttconnect'; +exports.title = 'Cloud connect mqtt'; +exports.group = 'MQTT'; +exports.color = '#888600'; +exports.version = '1.0.2'; +exports.icon = 'sign-out'; +exports.input = 2; +exports.output = 2; +exports.options = { host: 'tb-stage.worksys.io', port: 1883, clientid: "", username: "" }; + +exports.html = `
+
+
+
Hostname or IP address (if not empty - setting will override db setting)
+
+
+
Port
+
+
+
+
+
@(Client id)
+
+
+
topic
+
+
+
`; + + + +const { promisifyBuilder } = require('./helper/db_helper'); +const fs = require('fs'); +const mqtt = require('mqtt'); +const nosql = NOSQL('tbdatacloud'); + +const SEND_TO = { + debug: 0, + rpcCall: 1, +} + +//CONFIG +let saveTelemetryOnError = true;//backup_on_failure overrides this value +//------------------------ + +const noSqlFileSizeLimit = 4194304;//use 5MB - 4194304 +let insertNoSqlCounter = 0; +let insertBackupNoSqlCounter = 0; +let processingData = false; + +let backup_on_failure = true;//== saveTelemetryOnError - create backup client send failure +let restore_from_backup = 50; //how many rows process at once? +let restore_backup_wait = 3;//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; + + +exports.install = function(instance) { + + var client; + var opts; + var clientReady = false; + + let o = {}; //options + + function main() { + loadSettings(); + } + + //set opts according to db settings + function loadSettings() { + + o = instance.options; + if (!o.topic) o.topic = FLOW.GLOBALS.settings.cloud_topic; + + opts = { + host: o.host, + port: o.port, + clientId: o.clientid, + username: o.username, + rejectUnauthorized: false, + resubscribe: false + }; + + console.log("wsmqttpublich -> loadSettings from instance.options", o); + + if (!o.topic) { + instance.status("Not configured", "white"); + console.log("Cloud mqtt connect: no topic selected"); + return; + } + + connectToTbServer(); + } + + function connectToTbServer() { + var url = "mqtt://" + opts.host + ":" + opts.port; + console.log("MQTT URL: ", url); + + client = mqtt.connect(url, opts); + + client.on('connect', function() { + client.subscribe(`${o.topic}_backward`, (err) => { + if (!err) { + console.log("MQTT subscribed"); + } + }); + instance.status("Connected", "green"); + clientReady = true; + sendClientError = true; + }); + + client.on('reconnect', function() { + instance.status("Reconnecting", "yellow"); + clientReady = false; + }); + + client.on('message', function(topic, message) { + // message is type of buffer + message = message.toString(); + if (message[0] === '{') { + TRY(function() { + + message = JSON.parse(message); + if (message.hasOwnProperty("device") && message.hasOwnProperty("data") && message.data.hasOwnProperty("id")) { + client.publish(`${o.topic}_forward`, `{"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 } }); + } + + }, () => instance.debug('MQTT: Error parsing data', message)); + } + + instance.send(SEND_TO.rpcCall, { "topic": o.topic, "content": message }); + }); + + client.on('close', function() { + clientReady = false; + + instance.status("Disconnected", "red"); + instance.send(SEND_TO.debug, { "message": "Client CLOSE signal received !" }); + }); + + client.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) { + console.log('MQTT client error', err); + sendClientError = false; + } + clientReady = false; + }); + + } + + + instance.on('0', function(data) { + + if (clientReady) { + //do we have some data in backup file? if any, process data from database + if (saveTelemetryOnError) { + //read telemetry data and send back to server + if (!processingData) processDataFromDatabase(); + } + + let stringifiedJson = JSON.stringify(data.data) + client.publish(`${o.topic}_forward`, stringifiedJson, { qos: 1 }); + } + 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 (saveTelemetryOnError && o.topic) { + //create new file from tbdata.nosql, if file size exceeds given limit, and clear tbdata.nosql + makeBackupFromDbFile(); + + //write to tb + data.data.id = UID(); + nosql.insert(data.data); + } + } + }); + + instance.on("1", _ => { + main(); + }) + + instance.close = function(done) { + if (clientReady) { + client.end(); + } + }; + + + function getDbBackupFileCounter(type) { + var files = fs.readdirSync(__dirname + "/../databases"); + + let counter = 0; + for (var i = 0; i < files.length; i++) { + + if (files[i] == "tbdatacloud.nosql") continue; + + if (files[i].endsWith(".nosql")) { + + let pos = files[i].indexOf("."); + if (pos > -1) { + + let fileCounter = counter; + let firstDigit = files[i].slice(0, pos); + + fileCounter = parseInt(firstDigit); + if (isNaN(fileCounter)) fileCounter = 0; + //console.log("getDbBackupFileCounter digit:", files[i], firstDigit, fileCounter, isNaN(fileCounter), type); + + if (type == "max") { + if (fileCounter > counter) { + counter = fileCounter; + } + } + else if (type == "min") { + if (counter == 0) counter = fileCounter; + + if (fileCounter < counter) { + counter = fileCounter; + } + } + } + } + + } + + if (type == "max") counter++; + + return counter; + } + + const makeBackupFromDbFile = async () => { + + if (!saveTelemetryOnError) return; + + //to avoid large file: tbdata.nosql + + //init value is 0! + if (insertNoSqlCounter > 0) { + --insertNoSqlCounter; + return; + } + + insertNoSqlCounter = 100; + + let source = __dirname + "/../databases/tbdatacloud.nosql"; + + var stats = fs.statSync(source); + var fileSizeInBytes = stats.size; + + if (fileSizeInBytes > noSqlFileSizeLimit) { + + let counter = 1; + counter = getDbBackupFileCounter("max"); + + let destination = __dirname + "/../databases/" + counter + "." + "tbdatacloud.nosql"; + + //make backup file + fs.copyFileSync(source, destination); + //fs.renameSync(p, p + "." + counter); + + //clear tbdata.nosql + fs.writeFileSync(source, ""); + fs.truncateSync(source, 0); + + } + } + + const processDataFromDatabase = async () => { + + if (restore_from_backup <= 0) return; + + //calculate diff + const now = new Date(); + let currentTime = now.getTime(); + let diff = currentTime - lastRestoreTime; + + if ((diff / 1000) < restore_backup_wait) { + //console.log("*********restore_backup_wait", diff, restore_backup_wait); + return; + } + + processingData = true; + + //get filename to process + let counter = getDbBackupFileCounter("min"); + + //we have some backup files + let dataBase = 'tbdata'; + + var nosql; + if (counter == 0) dataBase = 'tbdatacloud'; + else dataBase = counter + "." + 'tbdatacloud'; + + nosql = NOSQL(dataBase); + + //select all data - use limit restore_from_backup + let records = await promisifyBuilder(nosql.find().take(restore_from_backup)); + + for (let i = 0; i < records.length; i++) { + if (clientReady) { + + let item = records[i]; + let id = item.id; + + if (id !== undefined) { + //console.log("------------processDataFromDatabase - remove", id, dataBase, i); + + try { + + let message = JSON.parse(JSON.stringify(item)); + delete message.id; + client.publish(`${o.topic}_forward`, JSON.stringify(message), { qos: 1 }); + + //remove from database + await promisifyBuilder(nosql.remove().where("id", id)); + + } catch (error) { + //process error + console.log("processDataFromDatabase", error); + } + + } + + } + else { + processingData = false; + return; + } + } + + if (records.length > 0) { + //clean backup file + if (counter > 0) nosql.clean(); + } + + //no data in db, remove + if (records.length == 0) { + if (counter > 0) nosql.drop(); + } + + const d = new Date(); + lastRestoreTime = d.getTime(); + + processingData = false; + + } + + instance.on('options', main); + +}; diff --git a/RVO46/flow/cmd_manager.js b/RVO46/flow/cmd_manager.js new file mode 100755 index 0000000..25912df --- /dev/null +++ b/RVO46/flow/cmd_manager.js @@ -0,0 +1,3071 @@ +exports.id = 'cmd_manager'; +exports.title = 'CMD Manager'; +exports.group = 'Worksys'; +exports.color = '#5D9CEC'; +exports.version = '0.0.3'; +exports.output = ['red', 'blue', 'yellow', 'blue', 'white', 'green']; +exports.input = 3; +exports.icon = 'cloud-upload'; + +exports.html = ` +
+
+
+
RPC - run RPC calls

+
+
+
@(User)
+
+
+
@(Password)
+
+
+
@(My edge)
+
+
+
+`; +exports.readme = `Manager for CMD calls`; + + +exports.install = function(instance) { + + 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, isEmptyObject, emptyJsObject, writeToFile, addToArrayIfUnique } = require('./helper/utils'); + const bitwise = require('bitwise'); + + var SunCalc = require('./helper/suncalc'); + const DataToTbHandler = require('./helper/DataToTbHandler'); + const errorHandler = require('./helper/ErrorToServiceHandler'); + const { sendNotification } = require('./helper/notification_reporter'); + const process = require('process'); + const { errLogger, logger, monitor } = require('./helper/logger'); + + //for accelerometer purposes + const { naklony } = require("../databases/accelerometer_db"); + + const dbNodes = TABLE("nodes"); + const dbRelays = TABLE("relays"); + + let GLOBALS; + let SETTINGS; + let rsPort; + let tbHandler; + + // runTasks intervals + const SHORT_INTERVAL = 30; + const LONG_INTERVAL = 300; + + //send data to following instances: + const SEND_TO = { + debug: 0, + tb: 1, + http_response: 2, + dido_controller: 3, + infoSender: 4, + dailyReport: 5 + } + + 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 + } + + 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 sendNodeReadout = null; // interval for sending agregate data from node + + 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["1"] = minutes; // dimming + priorities["76"] = minutes; // power + + minutes = 5; + priorities["75"] = minutes; // current + priorities["79"] = minutes; // energy + priorities["87"] = minutes; // aktualny cas + //priorities["84"] = minutes; //accelerometer + + minutes = 10; + priorities["74"] = minutes; // voltage + priorities["77"] = minutes; // power factor + priorities["78"] = minutes; // frequency + + minutes = 60; + priorities["0"] = minutes; // statecode + priorities["6"] = minutes; // dusk + priorities["7"] = minutes; // dawn + priorities["8"] = minutes; // profile + + minutes = 60 * 24; + priorities["89"] = minutes; // verzia fw + priorities["80"] = minutes; // lifetime + + //prikazy kt sa budu spustat na dany node - see config.js in terminal-oms.app. (1 - dimming) + let listOfCommands = [0, 1, 6, 7, 8, 74, 75, 76, 77, 78, 79, 80, 87, 89]; + + 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; + + // holds dusk, dawn (and more) values + let sunCalcResult; + + //helper container for counting resolved group of commands (commands related to set profile) + let cmdCounter = {};//key is node, value is counter + + //TODO: is this set working?? According to previous checks, sets do not work + //if sending of profile to node fails, we send notification and push node into set, so we do not send notification twice + const nodeProfileSendFail = new Set(); + + //we expect to get current temperature in Senica from senica-prod01 + let temperatureInSenica = null; + let accelerometerInterval = null; + + //NOTE: daily reports senica: + //rvo_is_on status, we monitor all nodes - if true, power and dimming should be not 0, if false, 24/7 nodes should be 0, other rvo should not respond + let rvo_is_on; + let previous_rvo_is_on_value; + let handleDailyReport; //setInterval for dailyReportHandler function + let dailyReport = {}; //data needed for daily report + let reportToSend = {}; //final report which we send to cloud + let breakerCounter = null; // status of breakers after flow starts is not in report + let rvoPeriod; // interval of checking dusk dawn and if rvo_is_on + let initialReportStatus = false; + + const DAILY_REPORT_HANDLER_TIME = 3_600_000; + const SET_SUNCALC_RESULT_TIME = 3_600_000; + const SET_RVO_PERIOD_TIME = 300_000; + const ADD_NODE_TO_REPORT_TIME = 3_600_000; + + //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); + + let now = new Date(); + console.log("Cmd-mngr installed", now.toLocaleString("sk-SK")); + + sunCalcResult = calculateDuskDawn(); + + handleRsPort(); + + customTasksInterval = setInterval(reportEdgeDateTimeAndNumberOfLuminaires, 120_000); + setTimeout(reportEdgeDateTimeAndNumberOfLuminaires, 4000); + + //dailyReport related + emptyReportToSend(); + breakerCounter = Object.keys(relaysData).length - 1; // we get number of lines (breakers) except of line 0 + rvoPeriod = setInterval(setRvoPeriod, SET_RVO_PERIOD_TIME); + setTimeout(setRvoPeriod, 3000); + setInterval(setSunCalcResult, SET_SUNCALC_RESULT_TIME); + handleDailyReport = setInterval(dailyReportHandler, DAILY_REPORT_HANDLER_TIME); + + + setCorrectTime = setInterval(setCorrectPlcTimeOnceADay, 60000 * 60); // 1 hour + setCorrectPlcTimeOnceADay(); + + sendNodeReadout = setInterval(sendNodesData, 150_000); + accelerometerInterval = setInterval(accelerometerData, 60000 * 30); //30 min + } + + + 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" + //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 + // if node regular readout does not respond, we repeat request + params.repeatCounter = 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-mngr: 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.byte4 = 96; + params.recipient = 1; + params.register = 8; + params.rw = 1;//write + params.timestamp = timestamp; + 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.byte4 = 96; + params.recipient = 1; + params.register = 8; + params.rw = 1;//write + params.timestamp = timestamp; + 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). + */ + + 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.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.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 + { + + logger.debug("processNodeProfile: Threshold lux level for DUSK/DAWN", node); + + let params = getParams(); + params.type = "set_node_profile"; + params.address = node; + params.register = 96; + params.recipient = 1; + params.rw = 1;//write + params.timestamp = timestamp; + 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(); + params.type = "set_node_profile"; + params.address = node; + params.register = 97; + params.recipient = 1; + params.rw = 1;//write + params.timestamp = timestamp; + 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.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); + + 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); + + console.log("proces profile finished *********************") + } + + + 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; + }); + } + + + 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) { + for (let k in nodesData) { + 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`); + } + } + } + + + function loadRelaysData(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 (value.contactor == 1) processAllNodeProfilesOnLine(value.line); + } + } + + + function reportOnlineNodeStatus(line) { + //Po zapnutí línie broadcastovo aktualizovať predtým čas a o 3 sek neskor - status, brightness + + logger.debug("Cmd-mngr: ----->reportOnlineNodeStatus for line", line); + + const d = new Date(); + + // broadcast actual time + let params = getParams(); + params.address = 0xffffffff;//Broadcast + params.byte1 = d.getHours(); + params.byte2 = d.getMinutes(); + params.recipient = 2;//2 broadcast, address = 0 + params.register = 87;//Actual time + params.rw = 1;//write + params.type = "node-onetime-write"; + params.timestamp = d.getTime() + 30000; + params.info = "run broadcast: Actual time"; + //params.debug = true; + + tasks.push(params); + + let sec = 3; + setTimeout(function() { + //Po zapnutí línie - spraviť hromadný refresh stavu práve zapnutých svietidiel + + let time = Date.now(); + + for (let k in nodesData) { + + //potrebujem nody k danej linii + 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].node_status_before_offline === true || nodesData[k].status === true) { + status = "OK"; + nodesData[k].time_of_last_communication = time; + } + + nodesData[k].readout.status = status; + + updateNodeStatus(k, status === "OK" ? true : false); + if (nodesData[k].hasOwnProperty("node_status_before_offline")) delete nodesData[k].node_status_before_offline; + sendTelemetry({ status: status }, tbname, time); + + //vyreportovanie dimming, current, input power pre liniu pre vsetky nody + //Prud + { + let params = getParams(); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 75;//prud + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = time + 4000; + params.info = 'read current'; + //params.debug = true; + tasks.push(params); + } + + //vykon + { + let params = getParams(); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 76;//výkon + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = time + 4100; + params.info = 'read power'; + //params.debug = true; + + tasks.push(params); + } + //dimming + { + let params = getParams(); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 1;//dimming + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = time + 4200; + params.info = 'read dimming'; + //params.debug = true; + + tasks.push(params); + } + + } + } + + }, sec * 1000); + } + + + function reportOfflineNodeStatus(line) { + + logger.info("Cmd-mngr: ------>reportOffLineNodeStatus for line ", line); + + values = {}; + values["dimming"] = 0;//brightness + values["power"] = 0;//výkon + values["current"] = 0;//prúd + values["status"] = "OFFLINE"; + + const date = Date.now(); + + Object.keys(nodesData).forEach(node => { + + //potrebujem nody k danej linii + if (line == nodesData[node].line || line == undefined) { + + let tbname = nodesData[node].tbname; + let nodeStatus = nodesData[node].status; + + //in case we have reported offline node status, we return (continue with next node) + if (nodeStatus === "OFFLINE") return; + + nodesData[node].node_status_before_offline = nodeStatus; + nodesData[node].status = "OFFLINE"; + nodesData[node].readout = {}; + + sendTelemetry({ ...values }, tbname, date); + } + }); + + } + + + function turnLine(onOrOff, line, info) { + let obj = { + line: line, + command: onOrOff, + info: info + }; + + //to assure, handleDailyReportFunction do not run before rvo_is_on variable changes. So after every line switch we reset the timer + clearInterval(handleDailyReport); + handleDailyReport = setInterval(dailyReportHandler, DAILY_REPORT_HANDLER_TIME); + + //logger.debug("linia", line, obj); + instance.send(SEND_TO.dido_controller, obj); + } + + + 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"; + 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]) { + //CRC_ERROR + message = "NOK"; + error = "CRC_ERROR c1"; + instance.send(SEND_TO.debug, "CRC_ERROR c1"); + } + + 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") { + instance.send(SEND_TO.debug, bytes); + instance.send(SEND_TO.debug, "RESPONSE " + type + " - " + bytes[4]); + + //logger.debug(SEND_TO.debug, "RESPONSE " + type + " - " + bytes[4], bytes); + + error = "type is: " + type; + + message = "NOK"; + } + + return { message, type, error }; + } + + + //BUILD TASKS// + function buildTasks(params) { + + //return; + console.log("buidTAaasks start ****************", params); + monitor.info("buildTasks - params", params); + + let processLine; //defined line + let init = false; + let processLineProfiles = true; + let processBroadcast = true; + let processNodes = true; + + if (params == undefined) { + init = true; + tasks = []; + logger.debug("-->buildTasks clear tasks"); + } + else { + processLineProfiles = params.processLineProfiles; + processBroadcast = false; + processNodes = false; + + processLine = params.line; + } + + let now = new Date(); + + //process line profiles + if (processLineProfiles) { + + let keys = Object.keys(relaysData); + + for (let i = 0; i < keys.length; i++) { + + let line = parseInt(keys[i]); + let profilestr = relaysData[line].profile; + + if (processLine != undefined) { + if (processLine != line) continue; + } + + try { + + /** + * we process line profiles: timepoints, astro clock, lux_sensor, offsets ... + */ + if (profilestr === "") throw ("Profile is not defined"); + let profile = JSON.parse(profilestr); + 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; + + // add name to regular profile timepoint and delete unused end_time key: + time_points.forEach(point => { + point.name = "profileTimepoint" + delete point.end_time; + }); + + //monitor.info("buildTasks: time_points", time_points); + + + /** + * 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 astro clock true, we remove all regular profile points + time_points = []; + + //TODO: when astro clock == true, is offset calculated ??? + //let duskAstroClockOffset = profile.dusk_astro_clock_offset; + //let dawnAstroClockOffset = profile.dawn_astro_clock_offset; + //console.log("line astro clock offsets dusk a dawn: ", duskAstroClockOffset, dawnAstroClockOffset); + // maybe add dusk dawn offset to calculateDuskDawn ?? what dusk dawn will be if dawn_lux_sensor == true?? + //let sunCalcResult = calculateDuskDawn(new Date(), line, duskAstroClockOffset, dawnAstroClockOffset); + + 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 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); + + 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); + + 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(':'); + + let ad = new Date(); + ad.setHours(parseInt(ahours), parseInt(aminutes), 0); + + let bd = new Date(); + bd.setHours(parseInt(bhours), parseInt(bminutes), 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++) { + + let start_time = new Date(); + let [hours, minutes] = time_points[t].start_time.split(':'); + start_time.setHours(parseInt(hours), parseInt(minutes), 0); + + //task is in 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(); + params.type = "relay"; + params.line = parseInt(line); + params.value = time_points[t].value; + params.tbname = relaysData[line].tbname; + params.timestamp = start_time.getTime(); + + // 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; + + //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)) { + 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; + + params.debug = true; + + //turn on/off line + tasks.push(params); + monitor.info("TimePoint params: ", params.info, start_time); + } + + monitor.info("-->time_points final", line, time_points); + + //ensure to turn on/off according to calculated currentValue + let params = getParams(); + params.type = "relay"; + params.line = parseInt(line); + params.tbname = relaysData[line].tbname; + params.value = currentValue; + params.timestamp = i; + params.debug = true; + + //logger.debug(now.toLocaleString("sk-SK")); + 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; + + tasks.push(params); + + } catch (error) { + if (profilestr !== "") { + //errLogger.error(profilestr, error); + console.log(`Cmd_mngr: Unable to process line profile ${line}. Error: `, error); + errorHandler.sendMessageToService(profilestr + "-" + error, 0, "js_error"); + } else { + turnLine("off", line, "No line profile. Switching it off on startup"); + } + } + + } + //logger.debug("tasks:"); + //logger.debug(tasks); + } + + + //NOTE: PROCESS DEFAULT BROADCASTS - Time of dusk, Time of dawn, Actual Time + if (processBroadcast) { + + let d = new Date(); + let time = d.getTime(); + //let sunCalcResult = calculateDuskDawn(); + + { + let params = getParams(); + + params.address = 0xffffffff;//broadcast + params.byte1 = sunCalcResult["dusk_hours"]; + params.byte2 = sunCalcResult["dusk_minutes"]; + params.recipient = 2;//2 broadcast, + params.register = 6;//Time of dusk + params.rw = 1;//write + params.type = "node-regular-write"; + params.timestamp = time + 60000; + params.addMinutesToTimestamp = 60 * 3; //kazde 3 hodiny zisti novy dusk + params.info = "Broadcast-duskTime"; + + tasks.push(params); + } + + { + let params = getParams(); + + params.address = 0xffffffff;//broadcast + params.byte1 = sunCalcResult["dawn_hours"]; + params.byte2 = sunCalcResult["dawn_minutes"]; + params.recipient = 2; //2 broadcast + params.register = 7;//Time of dawn + params.rw = 1;//write + params.type = "node-regular-write"; + params.timestamp = time + 60001; + params.addMinutesToTimestamp = 60 * 3; //kazde 3 hodiny zisti novy dawn + params.info = "Broadcast-dawnTime"; + + tasks.push(params); + } + + { + let params = getParams(); + + params.address = 0xffffffff;//broadcast + params.byte1 = d.getHours(); + params.byte2 = d.getMinutes(); + params.recipient = 2; //2 broadcast + params.register = 87;//Actual time + params.rw = 1;//write + params.type = "node-regular-write"; + params.timestamp = time + 60002; + params.addMinutesToTimestamp = 5; + params.info = "run broadcast: Actual time"; + + tasks.push(params); + } + + } + + //process nodes & tasks - read node's data + if (processNodes) { + + let time = Date.now(); + + for (let k in nodesData) { + let address = parseInt(k); + let tbname = nodesData[k].tbname; + let register = 0; + + for (let i = 0; i < listOfCommands.length; i++) { + + register = listOfCommands[i]; + let addMinutesToTimestamp = priorities[register]; + + let params = getParams(); + + params.address = address; + params.recipient = 1; + params.register = register; + params.type = register == 1 ? "node-dimming-read" : "node-regular-read"; + params.tbname = tbname; + params.timestamp = time + 5000 + i * 500 + addMinutesToTimestamp * 1000; //to make slight time difference + params.addMinutesToTimestamp = addMinutesToTimestamp; + params.info = "Node regular read command"; + + tasks.push(params); + } + + } + } + + + //niektore ulohy sa vygeneruju iba 1x pri starte!!! + if (!init) return; + + + //Master node FW version - modifies SETTINGS.masterNodeIsResponding + { + let params = getParams(); + params.type = "cmd-master"; + params.register = 4; + params.address = 0; + params.timestamp = 0; + params.addMinutesToTimestamp = 5; + params.tbname = SETTINGS.rvoTbName; + params.info = "Master node FW verzia"; + //params.debug = true; + + tasks.push(params); + } + + //kazdu hodinu skontrolovat nastavenie profilov + { + let params = getParams(); + params.type = "process_profiles"; + params.timestamp = Date.now() + 60001; + params.addMinutesToTimestamp = 60;//60 = every hour + params.info = "detekcia nespracovaných profilov linie a nodov"; + //params.debug = true; + + tasks.push(params); + } + + monitor.info("tasks created:", tasks.length); + } + + + /** + * We process line profile, where "astro_clock": true + * example profile: + * + "dawn_lux_sensor": true, + "dusk_lux_sensor": true, + "dawn_lux_sensor_value": 5, + "dusk_lux_sensor_value": 5, + "dawn_astro_clock_offset": 0, + "dusk_astro_clock_offset": 10, + "dawn_lux_sensor_time_window": 30, + "dusk_lux_sensor_time_window": 30, + "dawn_astro_clock_time_window": 60, + "dusk_astro_clock_time_window": 60 + + * if dawn: if currentTimestamp is in timewindow "dawnTime + and - dawn_lux_sensor_time_window" and lux value >= lux_sensor_value, we switch off the line. + * if dusk: we do oposite + * + * dawn: usvit - lux je nad hranicou - vypnem + * dusk: sumrak - lux je pod hranicou - zapnem + */ + 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++) { + + let line = keys[i]; //line is turned off by default + let profilestr = relaysData[line].profile; + const contactor = relaysData[line].contactor; + + try { + + let profile = JSON.parse(profilestr); + if (Object.keys(profile).length === 0) throw ("turnOnOffLinesAccordingToLuxSensor - profile is not defined"); + + 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 (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"); + } + } + } + + //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 (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"); + } + } + } + + } + + } catch (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) { + //MASTER + if (node == 0) return; + + let nodeObj = nodesData[node]; + if (nodeObj == undefined) return; + + let nodeCurrentStatus = nodeObj.status; + const now = Date.now(); + + let data = null; + + if (nodeCurrentStatus === "OFFLINE") { + data = { status: newStatus }; + nodeDbStatusModify(node, data); + return; + } + else 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; + } + + } + + + 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 }; + } + }); + }); + } + + + function processDailyReport() { + + const now = Date.now(); + + for (const [key, value] of Object.entries(dailyReport)) { + + if (["name", "time", "dusk_and_dawn"].includes(key)) continue; + + let poleNumber = nodesData[key]["pole_number"]; + let line = dailyReport[key].line; + let nodeType = nodesData[key]["node_type"]; + let fullNodeName = key // key == nodeNumber + + if (poleNumber && nodeType) { + fullNodeName = SETTINGS.rvo_number + "/" + poleNumber + "_" + line + "L_" + key + "_" + nodeType; + } else { + fullNodeName = key; + } + + if (rvo_is_on) { + + if (value.initialTs) { + if (value.initialTs + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["night_no_data"], fullNodeName); + console.log('report nedostava ziadne data uz hodinu', fullNodeName); + value.initialTs = now; + } + } + if (value.dimmingIsZeroTime) { + if (value.dimmingIsZeroTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["night_dimming=0"], fullNodeName); + console.log("report node dimming je 0 ale ma svietit", fullNodeName); + value.dimmingIsZeroTime = now; + } + } + if (value.powerIsZeroTime) { + if (value.powerIsZeroTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["night_power=0"], fullNodeName); + console.log("report node power je 0 ale ma svietit", fullNodeName); + value.powerIsZeroTime = now; + } + } + + } else { + + let contactorStatus = relaysData[line].contactor; + if (contactorStatus === 1) { + + if (value.initialTs) { + if (value.initialTs + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["day_24/7_no_data"], fullNodeName); + console.log('node je na 24/7 ale nedostava ziadne data uz hodinu', fullNodeName); + value.initialTs = now; + } + } + if (value.dimmingIsOnButShouldBeOffTime) { + if (value.dimmingIsOnButShouldBeOffTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["day_24/7_dimming>0"], fullNodeName); + console.log("report dimming je > 0 ale nema svietit", fullNodeName); + value.dimmingIsOnButShouldBeOffTime = now; + } + } + if (value.powerIsOnButShouldBeOffTime) { + if (value.powerIsOnButShouldBeOffTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["day_24/7_power>0"], fullNodeName); + console.log("report power je > 0 ale nema svietit", fullNodeName); + value.powerIsOnButShouldBeOffTime = now; + } + } + + } + + } + + } + + let report = {}; + report["name"] = SETTINGS.rvo_name; + report["time"] = new Date(); + report["report"] = reportToSend; + + writeToFile(F.path.root("report_data.log"), report, true); + instance.send(SEND_TO.dailyReport, report); + } + + + function dailyReportHandler() { + + if (!SETTINGS.daily_report) return; + + // after dawn we empty reportToSend and start to get data for a new day + const date = new Date(); + const hour = date.getHours(); + const minute = date.getMinutes(); + + console.log("now: ", hour, minute, "suncalc: ", sunCalcResult.dawn_hours, sunCalcResult.dawn_minutes); + + if (hour === sunCalcResult.dawn_hours) { + + //NOTE: ak je este pred usvitom, spracujeme report a posleme na cloud, ak uz je po usvite, resetujeme report plnime data noveho dna + if (minute >= sunCalcResult.dawn_minutes - 2) { + emptyReportToSend(); + emptyDailyReport(); + console.log("Podmienka 1 v dailyReport handler"); + } else { + processDailyReport(); + emptyReportToSend(); + emptyDailyReport(); + console.log("Podmienka 2 v dailyReport handler"); + } + + initialReportStatus = true; + + // ak sa funkcia spusti o hodinu alebo 2 neskor, ako je usvit (moze sa to stat, kedze kazde zapnutie/vypnutie linii odznova spusti casovac. + } else if (hour === sunCalcResult.dawn_hours + 1 || hour === sunCalcResult.dawn_hours + 2) { + if (!initialReportStatus) { + emptyReportToSend(); + emptyDailyReport(); + initialReportStatus = true; + console.log("Podmienka 3 v dailyReport handler"); + } else { + processDailyReport(); + initialReportStatus = true; + console.log("Podmienka 4 v dailyReport handler"); + } + } else { + processDailyReport(); + initialReportStatus = false; + console.log("Podmienka 5 v dailyReport handler"); + } + + console.log("initialReportStatus: ", initialReportStatus); + + } + + function emptyReportToSend() { + emptyJsObject(reportToSend); + reportToSend["contactor"] = { off: [], on: [] }; + reportToSend["night_no_data"] = []; + reportToSend["night_dimming=0"] = []; + reportToSend["night_power=0"] = []; + reportToSend["day_24/7_no_data"] = []; + reportToSend["day_24/7_dimming>0"] = []; + reportToSend["day_24/7_power>0"] = []; + console.log(`resetuje sa reportToSend`); + } + + + //NOTE: ked je initialTs stale rovnaky a zistime ze linie su vypnute (relaysData.line.contactor) - zistim, ci je node na tej linii. Vieme, ze ak je linia vypnuta je to v poriadku lebo nie je na 24/7 linii + //ak je na 24/7 linii, reportujeme, ze neprijima data + function emptyDailyReport() { + const ts = Date.now(); + emptyJsObject(dailyReport); + + //NOTE: do dailyReport dame vsetky nody a pravidelne kontrolujeme ci maju data + //ked nastane sumrak/usvit a svetla maju zacat/prestat svietit, dailyReport spravime nanovo: + for (const [key, value] of Object.entries(nodesData)) { + dailyReport[value.node] = { line: value.line, initialTs: ts }; + } + + console.log("dailyReport: ", dailyReport); + } + + + async function runTasks() { + + clearInterval(interval); + + let currentTimestamp = Date.now(); + + //sort tasks based on timestamp + 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) { + instance.send(SEND_TO.debug, "no tasks created"); + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + if (!rsPort.isOpen) { + instance.send(SEND_TO.debug, "!rsPort.isOpen"); + //await rsPort.open(); + //console.log("Cmd-mngr: !rsPort.isOpen"); + } + + let currentTask = tasks[0]; + + if (currentTask.debug) { + //logger.debug("--->task to process", currentTask); + } + + if (currentTask.timestamp <= currentTimestamp) { + let params = { ...tasks[0] }; + + //allow terminal commands + if (SETTINGS.maintenance_mode && params.type !== "cmd-terminal") { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + let type = params.type; + let tbname = params.tbname; + let node = params.address; + let register = params.register; + let line = null; + let itIsNodeCommand; + + if (nodesData[node] !== undefined) { + line = nodesData[node].line; + itIsNodeCommand = true; + } + + if (params.line !== undefined) line = params.line; + + if (params.addMinutesToTimestamp > 0 || params.timePointName) { + tasks[0].timestamp = currentTimestamp + tasks[0].addMinutesToTimestamp * 60000; + } else { + tasks.shift(); + } + + //kontrola nespracovanych profilov nodov + //TODO: co ked niektore nody neprijimaju profily? kazdu hodinu zahltuju "tasks" array + if (type == "process_profiles") { + //na vsetky zapnutych liniach sa spracuju nespracovane profily nodov + loadRelaysData(); + interval = setInterval(runTasks, SHORT_INTERVAL); + return; + } + + //relay + if (type == "relay") { + + const timePointName = params.timePointName; + const value = params.value; + + let date = new Date(); + date.setDate(date.getDate() + 1);//next day + + let sunCalcResult; + if (timePointName) sunCalcResult = calculateDuskDawn(date, params.line); + + + if (timePointName == "dawn") { + tasks[0].timestamp = sunCalcResult.dawn_time; + } + else if (timePointName == "dusk") { + tasks[0].timestamp = sunCalcResult.dusk_time; + } + else if (timePointName == "luxOn") { + tasks[0].timestamp = sunCalcResult.dusk_time + params.dusk_lux_sensor_time_window * 60000; + } + else if (timePointName == "luxOff") { + tasks[0].timestamp = sunCalcResult.dawn_time + params.dawn_lux_sensor_time_window * 60000; + } + else if (timePointName == "profileTimepoint") { + tasks[0].timestamp = currentTimestamp + tasks[0].addMinutesToTimestamp * 60000; + } + + let info = "aplikovany bod profilu"; + let onOrOff = ""; + value == 1 ? onOrOff = "on" : onOrOff = "off"; + + turnLine(onOrOff, params.line, info); + + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + if (!SETTINGS.masterNodeIsResponding) { + //ak neodpoveda, nebudeme vykonavat ziadne commands, okrem cmd-terminal cmd-master + errorHandler.sendMessageToService("Master node is not responding"); + + let stop = true; + + if (type === "cmd-terminal" || type === "cmd-master") stop = false; + if (stop) { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + } + + let contactorStatus = 1; + if (relaysData[line] != undefined) contactorStatus = relaysData[line].contactor; + + if (line === 0 || contactorStatus === 0 || FLOW.deviceStatus.state_of_breaker[line] === "Off") { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + // TODO: -> status offline for rvo if rotary_switch_state is OFF, this is source of errors + // check if rotary_switch_state == "Off" + // state_of_braker: disconnected = true? + + if (!rsPort.isOpen) { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + //RE-CALCULATE VALUES + //set actual time for broadcast + if (register == 87 && params.recipient === 2) { + var d = new Date(); + params.byte1 = d.getHours();//h + params.byte2 = d.getMinutes();//m + } + + //SET DUSK/DAWN FOR BROADCAST + //Time of dusk + if (register == 6 && params.recipient === 2) { + + if (type != "cmd-terminal") { + params.byte1 = sunCalcResult["dusk_hours"];//h + params.byte2 = sunCalcResult["dusk_minutes"];//m + } + } + + //Time of dawn + if (register == 7 && params.recipient === 2) { + if (type != "cmd-terminal") { + params.byte1 = sunCalcResult["dawn_hours"];//h + params.byte2 = sunCalcResult["dawn_minutes"];//m + } + } + //----------------------- + + instance.send(SEND_TO.debug, "address: " + node + " register:" + register + "type: " + type); + + var startTime, endTime; + startTime = new Date(); + + let saveToTb = true; + if (!tbname) saveToTb = false; + + let resp = com_generic(node, params.recipient, params.rw, register, params.name, params.byte1, params.byte2, params.byte3, params.byte4); + let readBytes = 11; + let timeout = 4000; + + + // await keyword is important, otherwise incorrect data is returned! + await writeData(rsPort, resp, readBytes, timeout).then(function(data) { + + //sometimes happens, that status of node changes to OK, NOK even if line was turned off and should be status OFFLINE. To prevent this, we return if line contactor is 0: + if (itIsNodeCommand && line && relaysData[line].contactor !== 1) return; + + 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); + + //ak sa odpoved zacina 0 - je to v poriadku, inak je NOK + let message = result.message; // OK, NOK + let message_type = result.type; + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + console.log("detected response:", result); + logger.debug("Cmd-mngr: writeData done " + message_type + " duration: " + timeDiff + " type: " + params.debug, params, result); + } + } + + let values = {}; + + //CMD FINISHED + if (message == "OK") { + + updateNodeStatus(node, true); + + //write + if (type == "set_node_profile") { + let result = cmdCounterResolve(node); + if (result == 0) { + dbNodes.modify({ processed: true }).where("node", node).make(function(builder) { + builder.callback(function(err, response) { + + sendNotification("Cmd-mngr: process cmd", SETTINGS.rvoTbName, "dimming_profile_was_successfully_received_by_node", { node: node }, "", SEND_TO.tb, instance); + + logger.debug("--> profil úspešne odoslaný na node č. " + node); + nodesData[node].processed = true; + nodeProfileSendFail.delete(node); + }); + }); + } + } + + //parse read response + if (params.rw == 0) { + values = processResponse(register, dataBytes); //read + } + + if (itIsNodeCommand) { + values.comm_status = "OK"; + values.status = "OK"; + nodesData[node].readout = { ...nodesData[node].readout, ...values }; + + + if (SETTINGS.daily_report) { + //TODO: co ak nedostavame odpovede z nodu ? Musime vyreportovat!! + //v dailyReport teda musi byt kompletny zoznam nodov a neustale kontrolovat, ci maju data, ak nie report node - neodpoveda + if (register === 1) { + + let now = Date.now(); + + if (rvo_is_on === true) { + + if ("dimmingIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].dimmingIsOnButShouldBeOffTime; + + if (values.dimming > 0) { + if ("dimmingIsZeroTime" in dailyReport[node]) delete dailyReport[node].dimmingIsZeroTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if (!("dimmingIsZeroTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], dimmingIsZeroTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } else { + + if ("dimmingIsZeroTime" in dailyReport[node]) delete dailyReport[node].dimmingIsZeroTime; + + if (values.dimming > 0) { + if (!("dimmingIsOnButShouldBeOffTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], dimmingIsOnButShouldBeOffTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if ("dimmingIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].dimmingIsOnButShouldBeOffTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } + } + + if (register === 76) { + + let now = Date.now(); + + if (rvo_is_on === true) { + + if ("powerIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].powerIsOnButShouldBeOffTime; + + if (values.power > 1) { + if ("powerIsZeroTime" in dailyReport[node]) delete dailyReport[node].powerIsZeroTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if (!("powerIsZeroTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], powerIsZeroTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } else { + + if ("powerIsZeroTime" in dailyReport[node]) delete dailyReport[node].powerIsZeroTime; + + if (values.power > 1) { + if (!("powerIsOnButShouldBeOffTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], powerIsOnButShouldBeOffTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if ("powerIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].powerIsOnButShouldBeOffTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } + } + } + + } + + //master node + if (node == 0) { + sendNotification("Cmd-mngr: 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; + } + + if (params.debug) { + //logger.debug("saveToTb", saveToTb, tbname, values); + } + + if (saveToTb && type != "node-regular-read") { + sendTelemetry(values, tbname); + } + else { + if (type == "cmd-terminal") { + terminalCommandResponse(params, "SUCCESS", data); + } + } + + } + else { + terminalCommandResponse(params, "ERROR", data); + handleNokResponseOnRsPort("handleNOK else block", params, itIsNodeCommand, saveToTb); + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + //logger.debug("writeData err: ", error, result, params); + logger.debug("writeData err: ", tbname, node, register, values); + } + } + + //logger.debug(error, result, params); + } + }).catch(function(reason) { + + //console.log("writeData catch exception", reason); + instance.send(SEND_TO.debug, reason); + + terminalCommandResponse(params, "FAILURE", null, reason); + handleNokResponseOnRsPort("handleNOK catch block", params, itIsNodeCommand, saveToTb); + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + logger.debug("-->WRITE FAILED: " + reason, params.debug, params); + } + } + + }); + + } + 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); + } + + + // if node does not respond to request, we repeat request 3 times: + function repeatCommand(params) { + params.repeatCounter++; + if (params.repeatCounter < 4) { + params.timestamp = 0; + params.addMinutesToTimestamp = 0; + tasks.push(params); + } + } + + function handleNokResponseOnRsPort(message, params, itIsNodeCommand, saveToTb) { + + let node = params.address; + let register = params.register; + let type = params.type; + let tbName = params.tbname; + if (!tbName) return; + + let values = {}; + + let updateStatus = updateNodeStatus(node, false); + + if (itIsNodeCommand) { + values.comm_status = "NOK"; + nodesData[node].readout.comm_status = "NOK"; + repeatCommand(params); + } + + if (updateStatus) { + values.status = "NOK"; + nodesData[node].readout.status = "NOK"; + } + + if (type === "node-regular-read") return; + + //master node + if (node == 0) { + sendNotification("Cmd-mngr: 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; + + if (register == 4) values["master_node_version"] = "NOK"; + } + + if (type == "set_node_profile") { + delete cmdCounter[node]; + logger.debug("profil nebol úspešne odoslaný na node č. ", params); + + if (!nodeProfileSendFail.has(node)) { + sendNotification("Cmd-mngr: process cmd", tbName, "configuration_of_dimming_profile_to_node_failed", { node: node }, "", SEND_TO.tb, instance); + nodeProfileSendFail.add(node); + } + } + + // console.log("------",node, register, type, itIsNodeCommand, updateStatus, saveToTb, values); + if (saveToTb) { + sendTelemetry(values, tbName); + } + + } + + + function sendNodesData() { + Object.keys(nodesData).forEach(node => { + if (nodesData[node]["status"] !== "OFFLINE") { + sendTelemetry(nodesData[node].readout, nodesData[node].tbname); + nodesData[node].readout = {}; + } + }) + } + + + /** + * 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; + } + + 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); + + //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 === "OFFLINE") { + nodeObj.node_status_before_offline === true ? number_of_ok_luminaires++ : number_of_nok_luminaires++; + } + else if (nodeObj.status == true) 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 - ts % 60000 //round to full minute + }; + + sendTelemetry(values, SETTINGS.rvoTbName, ts); + } + + + function setSunCalcResult() { + //if next day, we get new dusk and dawn. To make sure, in local timezone 2:00 means 00:00 in utc (it means next day) + if (new Date().getHours() === 2) { + sunCalcResult = calculateDuskDawn(); + console.log("Novy suncalc: ", sunCalcResult); + } + } + + + function setRvoPeriod() { + + if (!SETTINGS.daily_report) return; + + const ts = Date.now(); + + previous_rvo_is_on_value = rvo_is_on; + + if (ts < sunCalcResult.dawn_time - 1_800_000) { // nodes should be on (00:00 -> 06:00 ( - pol hodina, lebo rvo vypina skor) + rvo_is_on = true; + } else if (sunCalcResult.dawn_time - 1_800_000 < ts && ts < sunCalcResult.dusk_time + 1_800_000) { // nodes should be off 06:00 -> 21:00 + rvo_is_on = false; + } else if (sunCalcResult.dusk_time + 1_800_000 < ts) { // nodes should be on 21:00 -> 00:00 + rvo_is_on = true; + } + + if (previous_rvo_is_on_value !== rvo_is_on) { + emptyDailyReport(); + console.log("rvo_is: ", rvo_is_on, previous_rvo_is_on_value); + } + } + + + function handleRsPort() { + + if (rsPort) { + rsPort.removeAllListeners(); + rsPort = null; + } + + //! 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-mngr: rsPort opened success"); + + 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); + + }).catch(function(reason) { + instance.send(SEND_TO.debug, "Cmd-mngr: RPC runSyncExec - promise rejected:" + reason); + }); + }); + + rsPort.on('error', function(err) { + errorHandler.sendMessageToService([exports.title, "unable to open port", SETTINGS.serial_port, err.message], 0); + monitor.info("Cmd-mngr: Error on rsPort", err.message); + }); + + rsPort.on("close", () => { + monitor.info("Cmd-mngr: rsPort closed, reconnecting..."); + setTimeout(handleRsPort, 1000); + }); + + rsPort.open(); + } + + + instance.on("close", () => { + clearInterval(interval); + clearInterval(customTasksInterval); + clearInterval(setCorrectTime); + clearInterval(sendNodeReadout); + clearInterval(accelerometerInterval); + rsPort.close(); + }); + + instance.on("0", _ => { + main(); + }) + + + instance.on("2", _ => { + console.log("dailyReport, reportToSend, rvo_is_on", dailyReport, reportToSend, rvo_is_on, previous_rvo_is_on_value); + }) + + instance.on("1", 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(); + return; + } + else if (flowdata.data == "close") { + rsPort.close(); + return; + } + else if (flowdata.data == "clean") { + tasks = []; + return; + } + else if (flowdata.data == "buildtasks") { + //build & run + return; + } + else if (flowdata.data == "run") { + //durations = []; + + if (tasks.length == 0) { + + buildTasks(); + + if (rsPort.isOpen) { + interval = setInterval(runTasks, 100); + } + else { + instance.send(SEND_TO.debug, "port is not opened!!!"); + } + } + } + else { + //terminal data - object + //logger.debug("flowdata", flowdata.data); + + if (typeof flowdata.data === 'object') { + //logger.debug("dido", flowdata.data); + if (flowdata.data.hasOwnProperty("sender")) { + //data from dido_controller + if (flowdata.data.sender == "dido_controller") { + + if (flowdata.data.hasOwnProperty("cmd")) { + let cmd = flowdata.data.cmd; + + if (cmd == "buildTasks") { + clearInterval(interval); + + logger.debug("-->Cmd-mngr: BUILD TASKS"); + buildTasks(); + + //logger.debug("tasks:"); + //logger.debug(tasks); + + logger.debug("-->Cmd-mngr: RUN TASKS"); + interval = setInterval(runTasks, 5000); + } + else if (cmd == "reload_relays") { + loadRelaysData(flowdata.data.line); + + if (flowdata.data.dataChanged) { + if (!flowdata.data.value) { + reportOfflineNodeStatus(flowdata.data.line); + } + else { + reportOnlineNodeStatus(flowdata.data.line); + } + } + + } + else if (cmd == "rotary_switch_state") { + let value = flowdata.data.value; + + //state was changed + if (rotary_switch_state != value) { + if (value == "Off") { + //vyreportovat vsetky svietdla + reportOfflineNodeStatus(); + } + + rotary_switch_state = value; + } + } + 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) { + + // we send lux_sensor value to all nodes: + let params = getParams(PRIORITY_TYPES.node_broadcast); + + params.recipient = 2;//2 broadcast, address = 0 + params.address = 0xffffffff;//Broadcast + + let ba = longToByteArray(lux_sensor); + + params.byte3 = ba[1];//msb + params.byte4 = ba[0]; + params.timestamp = PRIORITY_TYPES.node_broadcast; + params.info = "run broadcast: Actual Lux level from cabinet"; + params.register = 95;//Actual Lux level from cabinet + params.rw = 1;//write + + tasks.push(params); + + //process profiles + turnOnOffLinesAccordingToLuxSensor(lux_sensor); + } + } + else if (cmd == "state_of_breaker") { + //istic linie + + breakerCounter--; + + let value = flowdata.data.value; + let line = parseInt(flowdata.data.line); + + let dataChanged = false; + if (state_of_breaker[line] != value) dataChanged = true; + + state_of_breaker[line] = value; + + let status = "OK"; + if (value == "Off") status = "NOK"; + + if (dataChanged) { + + if (relaysData.hasOwnProperty(line)) { + let tbname = relaysData[line].tbname; + + if (value == "Off") { + sendNotification("Cmd-mngr: onData", tbname, "circuit_breaker_was_turned_off_line", { line: line }, "", SEND_TO.tb, instance, "circuit_breaker"); + if (breakerCounter < 0) reportToSend["contactor"]["off"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + else { + sendNotification("Cmd-mngr: onData", tbname, "circuit_breaker_was_turned_on_line", { line: line }, "", SEND_TO.tb, instance, "circuit_breaker"); + if (breakerCounter < 0) reportToSend["contactor"]["on"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + + //report status liniu + sendTelemetry({ status: status }, tbname) + + //current value + if (value == "Off") reportOfflineNodeStatus(line); //vyreportovat vsetky svietidla na linii + } + + } + } + else { + logger.debug("undefined cmd", cmd); + } + } + } + + return; + } + + //data from worksys + if (flowdata.data.hasOwnProperty("topic")) { + + let data = getNested(flowdata.data, "content", "data"); + + //if we get temperature in senica from senica-prod01 + let temperature = getNested(flowdata.data, "content", "senica_temperature"); + + if (temperature !== undefined) { + temperatureInSenica = temperature; + return; + } + + if (data === undefined) { + console.log("Invalid rpc command came from platform"); + return; + } + + let command = data.params.command; + let method = data.method; + let profile = data.params.payload; + if (profile == undefined) profile = ""; + let entity = data.params.entities[0]; + let entity_type = entity.entity_type; + let tbname = entity.tb_name; + + instance.send(SEND_TO.debug, flowdata.data); + 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") { + + //let command = data.params.command; + let value = data.params.payload.value; + + if (command == "dimming") { + + let nodeWasFound = false; + let keys = Object.keys(nodesData); + + //logger.debug("-----", keys); + + 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); + + value = parseInt(value); + if (value > 0) value = value + 128; + + params.type = "node-onetime-write"; + params.tbname = tbname; + params.address = node; + params.register = 1; + params.recipient = 1; + params.byte4 = value; + params.rw = 1; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'set dimming from platform'; + //params.debug = true; + + //debug(params); + logger.debug("dimming", params); + + tasks.push(params); + + 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); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 1; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read dimming (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + //pridame aj vyreportovanie - vykon + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 76; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read Input Power (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + //pridame aj vyreportovanie - prud svietidla + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 75; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read Input Current (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + //pridame aj vyreportovanie - power faktor - ucinnik + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 77; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read power factor (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + }, 4000); + + nodeWasFound = true; + break; + } + } + + if (!nodeWasFound) { + logger.debug("set dimming from platform", "unable to find tbname", tbname); + } + } + else { + instance.send(SEND_TO.debug, "undefined command " + command); + logger.debug("undefined command", command); + } + + return; + } + 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++) { + let node = keys[i]; + if (tbname == nodesData[node].tbname) { + + 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"); + + //profil úspešne prijatý pre node č. xx + sendNotification("Cmd-mngr", tbname, "dimming_profile_was_processed_for_node", { node: node }, profile, SEND_TO.tb, instance); + + nodesData[node].processed = false; + nodesData[node].profile = profile; + + processNodeProfile(node); + }); + }); + } + } + } + else { + + instance.send(SEND_TO.debug, "unknown method " + method); + logger.debug("unknown method", method); + + return; + } + } + + //nastav profil linie z platformy + 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") { + + 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++) { + let line = keys[i]; + if (tbname == relaysData[line].tbname) { + //zmazeme tasky + 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) { + + //update profile + logger.debug("worksys - update relay profile done:", profile); + instance.send(SEND_TO.debug, "worksys - update relay profile done"); + + relaysData[line].profile = profile; + + loadRelaysData(line) + logger.debug("loadRelaysData DONE for line", line); + + buildTasks({ processLineProfiles: true, line: line }); + + sendNotification("Cmd-mngr: set profile from worksys", tbname, "switching_profile_was_processed_for_line", { line: line }, profile, SEND_TO.tb, instance); + }); + }); + break; + } + } + } + else if (method == "set_command") { + let value = data.params.payload.value; + + 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; + + 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"); + if (line != 0) reportToSend["contactor"]["off"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + else { + turnLine("on", line, "command received from platform"); + if (line != 0) reportToSend["contactor"]["on"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + } + } + else { + instance.send(SEND_TO.debug, "undefined method " + method); + logger.debug("undefined method", method); + } + + return; + } + else { + instance.send(SEND_TO.debug, "UNKNOW entity_type " + entity_type); + logger.debug("UNKNOW entity_type", entity_type); + } + return; + } + + //terminal + if (!rsPort.isOpen) await rsPort.open(); + + let params = flowdata.data.body; + if (params == undefined) { + //logger.debug("Cmd-mngr: flowdata.data.body is undefined"); + return; + } + + params.priority = PRIORITY_TYPES.terminal; + params.type = "cmd-terminal"; + params.tbname = ""; + params.timestamp = PRIORITY_TYPES.terminal; + params.addMinutesToTimestamp = 0;// do not repeat task!!! + params.debug = true; + + let timestamp = Date.now(); + params.refFlowdataKey = timestamp; + //params.refFlowdata = flowdata; + //refFlowdata = flowdata; + + //console.log("flowdata", flowdata); + + cleanUpRefFlowdataObj(); + + refFlowdataObj[timestamp] = flowdata; + + //fix + //params.address = params.adress; + logger.debug("received from terminal", params); + logger.debug("date/time:", new Date()); + logger.debug("tasks length:", tasks.length); + + //tasks = []; + + //add to tasks + tasks.push(params); + + } + } + }) + + + //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) + } + + + /** + * 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; + + RESTBuilder.make(function(builder) { + + if (!builder) return; + + builder.method('GET'); + builder.url('http://192.168.252.2:8004/gettime?projects_id=1'); + + builder.callback(function(err, response, output) { + + 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); + } + + }); + } + + } 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); + + } else { + //console.log("Read-only", stdout); + + 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]: [ + { + "ts": date, + "values": values + } + ] + } + + tbHandler.sendToTb(dataToTb, instance); + } + + + function calculateDuskDawn(date, line, duskOffset = 0, dawnOffset = 0) { + + if (date === undefined) date = new Date(); + + 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); + } + + //if(profile.dawn_lux_sensor == false) + { + if (profile.hasOwnProperty("dawn_astro_clock_offset")) dawn_astro_clock_offset = parseInt(profile.dawn_astro_clock_offset); + } + + } + + } catch (error) { + if (profilestr != "") { + logger.debug(profilestr); + logger.debug(error); + } + } + + 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; + } + + //Dimming, CCT + else if (register == 1) { + let brightness = 0; + let dimming = byte0; + if (dimming > 128) { + //dimming = -128; + brightness = dimming - 128; + } + + //cct + //Ak Byte3 == 1: CCT = (Byte2*256)+Byte1 + let cct; + if (byte3 == 1) cct = byte2 * 256 + byte1; + else cct = bytesToInt(bytes.slice(0, 3)); + + //cct podla auditu + + values["dimming"] = brightness; + return values; + } + + // + else if (register == 4) { + values["master_node_version"] = bytes[1] + "." + bytes[2]; + //logger.debug("FW Version", register, bytes); + } + + //Napätie + else if (register == 74) { + let voltage = (bytesToInt(bytes) * 0.1).toFixed(1); + values["voltage"] = Number(voltage); + } + + //Prúd + else if (register == 75) { + let current = bytesToInt(bytes); + values["current"] = current; + } + + //výkon + else if (register == 76) { + let power = (bytesToInt(bytes) * 0.1).toFixed(2); + values["power"] = Number(power); + } + + //účinník + else if (register == 77) { + let power_factor = Math.cos(bytesToInt(bytes) * 0.1 * (Math.PI / 180)).toFixed(2); + values["power_factor"] = Number(power_factor); + } + + //frekvencia + else if (register == 78) { + let frequency = (bytesToInt(bytes) * 0.1).toFixed(2); + values["frequency"] = Number(frequency); + } + + //energia + else if (register == 79) { + let energy = bytesToInt(bytes); + values["energy"] = energy / 1000; //energia v kWh -> delit 1000 + } + + //doba života + else if (register == 80) { + let lifetime = (bytesToInt(bytes) / 60).toFixed(2); + values["lifetime"] = Number(lifetime); + } + + //nastavenie profilu + else if (register == 8) { + let time_schedule_settings = bytesToInt(bytes); + values["time_schedule_settings"] = time_schedule_settings; + } + + //naklon - nateraz sa z nodu nevycitava! kvoli problemom s accelerometrom a vracanymi hodnotami, posielame temp a x y z vo funkcii accelerometerData() + else if (register == 84) { + values["temperature"] = byte3 >= 128 ? (byte3 - 128) * (-1) : byte3; + values["inclination_x"] = byte2 >= 128 ? (byte2 - 128) * (-1) : byte2; + values["inclination_y"] = byte1 >= 128 ? (byte1 - 128) * (-1) : byte1; + values["inclination_z"] = byte0 >= 128 ? (byte0 - 128) * (-1) : byte0; + } + + //FW verzia nodu + else if (register == 89) { + //formát: "Byte3: Byte2.Byte1 (Byte0)" + values["fw_version"] = byte3 + ":" + byte2 + "." + byte1 + "(" + byte0 + ")"; + } + + else if (register == 87 || register == 6 || register == 7) { + var d = new Date(); + d.setHours(byte3, byte2, 0, 0); + let timestamp = d.getTime(); + + //aktuálny čas + if (register == 87) values["actual_time"] = timestamp; + //čas súmraku + else if (register == 6) values["dusk_time"] = timestamp; + //čas úsvitu + else if (register == 7) values["dawn_time"] = timestamp; + } + + 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; + + } + + + function getObjectByTbValue(object, tbname) { + return object[Object.keys(object).find(key => object[key].tbname === tbname)]; + } + + + function isObject(item) { + return (typeof item === "object" && !Array.isArray(item) && item !== null); + } + + + // we fake data, that should be received from accelerometer, as they are a bit unreliable. (temperature, x,y,z) + function accelerometerData() { + + if (temperatureInSenica === null) return; + + //clone nodesData and relaysData objects + let nodesData_clone = JSON.parse(JSON.stringify(nodesData)); + let relaysData_clone = JSON.parse(JSON.stringify(relaysData)); + + for (const key in relaysData_clone) { + + const lineData = relaysData_clone[key]; + const lineNumber = lineData.line; + const contactor = lineData.contactor; + + if (lineNumber === 0) continue; + + if (contactor === 1) { + + let date = Date.now(); + + Object.keys(nodesData_clone).forEach((node, index) => { + + setTimeout(function() { + + if (nodesData_clone[node].line === lineNumber) { + + // NOTE: if status of luminaire is NOK or OFFLINE, we do not send data; + let status = nodesData_clone[node].status; + if (status === "OFFLINE" || !status) return; + + let x = null; + if (naklony.hasOwnProperty(node)) x = naklony[node].naklon; + if (x === null) x = 0; + + sendTelemetry({ temperature: Math.round(temperatureInSenica + 10 + Math.floor(Math.random() * 3)), inclination_x: x, inclination_y: 0, inclination_z: 0 }, nodesData_clone[node].tbname, date); + } + + }, (index + 1) * 500); + }) + + } + } + } + + +} // end of instance.export + diff --git a/RVO46/flow/code.js b/RVO46/flow/code.js new file mode 100755 index 0000000..63b31bf --- /dev/null +++ b/RVO46/flow/code.js @@ -0,0 +1,90 @@ +exports.id = 'code'; +exports.title = 'Code'; +exports.group = 'Common'; +exports.color = '#656D78'; +exports.input = true; +exports.output = 1; +exports.author = 'Peter Širka'; +exports.icon = 'code'; +exports.version = '1.2.0'; +exports.options = { outputs: 1, code: 'send(0, value);', keepmessage: true }; + +exports.html = `
+
+
+
@(Number of outputs)
+
@(Minimum is 1)
+
+
+
@(Code)
+
@(Keep message instance)
+
+`; + +exports.readme = `# Code + +This component executes custom JavaScript code as it is and it doesn't contain any secure scope. + +\`\`\`javascript +// value {Object} contains received data +// send(outputIndex, newValue) sends a new value +// error(value) sends an error +// instance {Object} a current component instance +// flowdata {Object} a current flowdata +// repository {Object} a current repository of flowdata +// Example: + +// send() can be execute multiple times +send(0, value); +\`\`\``; + +exports.install = function(instance) { + + var fn; + + instance.on('data', function(response) { + if (fn) { + try { + fn(response.data, instance, response, instance.options, response.repository, require); + } catch (e) { + response.data = e; + instance.throw(response); + } + } + }); + + instance.reconfigure = function() { + try { + if (instance.options.code) { + instance.status(''); + var code = 'var send = function(index, value) { if (options.keepmessage) { flowdata.data = value; instance.send2(index, flowdata); } else instance.send2(index, value);}; var error = function(err) { instance.throw(err); }; ' + instance.options.code; + fn = new Function('value', 'instance', 'flowdata', 'options', 'repository', 'require', code); + } else { + instance.status('Not configured', 'red'); + fn = null; + } + } catch (e) { + fn = null; + instance.error('Code: ' + e.message); + } + }; + + instance.on('options', instance.reconfigure); + instance.reconfigure(); +}; \ No newline at end of file diff --git a/RVO46/flow/comment.js b/RVO46/flow/comment.js new file mode 100755 index 0000000..1e0cd13 --- /dev/null +++ b/RVO46/flow/comment.js @@ -0,0 +1,11 @@ +exports.id = 'comment'; +exports.title = 'Comment'; +exports.group = 'Common'; +exports.color = '#704cff'; +exports.author = 'Martin Smola'; +exports.icon = 'comment'; +exports.traffic = false; +exports.version = '1.0.0'; +exports.readme = '# Comment'; + +exports.install = function() {}; diff --git a/RVO46/flow/count.js b/RVO46/flow/count.js new file mode 100755 index 0000000..fa92ee9 --- /dev/null +++ b/RVO46/flow/count.js @@ -0,0 +1,60 @@ +exports.id = 'count'; +exports.title = 'Count'; +exports.version = '1.0.1'; +exports.author = 'John Graves'; +exports.color = '#656D78'; +exports.icon = 'plus-square'; +exports.input = 2; +exports.output = 1; +exports.options = { increment: 1, initialvalue: 1 }; +exports.readme = `# Counter + +Counter Number of times called.`; + +exports.html = `
+
@(Initial Value)
+
@(Increment)
+

Example Video

+
`; + +exports.readme = `# Count + +This component counts the number of messages received. + +__Response:__ + +Integer value based on the initial value and increment settings. + +__Arguments:__ +- Initial Value: What number should be output on the receipt of the first message. +- Increment: What should the increment be for each following message received.`; + +exports.install = function(instance) { + + var count = 0; + var initialCall = true; + + instance.on('data', function(flowdata) { + var index = flowdata.index; + if (index) { + instance.debug('Reset Count.'); + count = instance.options.initialvalue; + initialCall = true; + } else { + // If this is the first time, set the value to 'initial value' + if(initialCall) { + initialCall = false; + count = instance.options.initialvalue; + } else + count = count+instance.options.increment; + instance.status('Count:' + count); + instance.send2(count); + } + }); + + instance.on('options', function() { + count = instance.options.initialvalue; + initialCall = true; + }); + +}; diff --git a/RVO46/flow/db_connector.js b/RVO46/flow/db_connector.js new file mode 100755 index 0000000..65ee94b --- /dev/null +++ b/RVO46/flow/db_connector.js @@ -0,0 +1,286 @@ +exports.id = 'db_connector'; +exports.title = 'DbConnector'; +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.html = `
+
+
+
DbConnector
+
+
+
`; + +exports.readme = `# read/write data to tables`; + +const instanceSendTo = { + debug: 0, + http_response: 1, +} + +const { promisifyBuilder, makeMapFromDbResult } = require('./helper/db_helper.js'); + +function extractWhereParams(params) +{ + let name = params[0]; + let operator = '='; + let value = params[1]; + + if(params.length == 3) + { + operator = params[1]; + value = params[2]; + } + + return {name: name, operator: operator, value: value}; +} + +exports.install = function(instance) { + + let refFlowdata = null;//holds reference to httprequest flowdata + + instance.on("close", () => { + + }) + + + instance.on("data", async function(flowdata) { + + let params = flowdata.data.body; + console.log("DbConnector", params); + + refFlowdata = flowdata; + + if(refFlowdata != undefined) + { + //make http response + let responseObj = {}; + responseObj["type"] = "SUCESS"; + + try{ + + let table = params.table; + let action = params.action; + + + if(params.data != undefined) + { + let className = params.data.className; + + if(className == "SqlQueryBuilder") + { + let type = params.data.type; + + console.log("SqlQueryBuilder---->", params.data); + + if(type == "SELECT") + { + let table = params.data.queryData.tables[0].table; + + const db = TABLE(table); + var builder = db.find(); + + let result = await promisifyBuilder(builder); + + let response = {}; + response["result"] = result; + response["success"] = true; + + responseObj["data"] = response; + + //console.log(responseObj); + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + } + + return; + } + } + + + console.log("db_connector---->", table, action); + + //actions: read, replace, insert, delete, update... + + if(action == "read") + { + const db = TABLE(params.table); + + //where builder.where('age', '<', 15); + //builder.where('id', 3403); + + var builder = db.find(); + + //https://docs.totaljs.com/latest/en.html#api~DatabaseBuilder~builder.where + if(params.hasOwnProperty("where")) + { + //optionalCan contain "=", "<=", "<", ">=", ">". + //Default value: '=' + + //1.["production_line", 1] + //2. ["or", ["production_line", 1], ["production_line", 2], "end"] + + if (Array.isArray(params.where)) { + + let multipleConditions = false; + + if(params.where[0] == "or") multipleConditions = true; + if (Array.isArray(params.where[0])) multipleConditions = true; + + if(multipleConditions) + { + + for(var i = 0; i < params.where.length; i++) + { + const item = params.where[i]; + + if(item === "or") builder.or(); + + if (Array.isArray(item)) + { + const { name, operator, value } = extractWhereParams(item); + builder.where(name, operator, value); + } + + if(item === "end") builder.end(); + + } + + } + else + { + const { name, operator, value } = extractWhereParams(params.where); + builder.where(name, operator, value); + } + + } + + /* + if(params.where.length >=2 ) + { + let name = params.where[0]; + let operator = '='; + let value = params.where[1]; + + if(params.where.length == 3) + { + operator = params.where[1]; + value = params.where[2]; + } + + builder.where(name, operator, value); + } + */ + } + + if(params.hasOwnProperty("between")) + { + builder.between(params.between[0], params.between[1], params.between[2]); + } + + let response = await promisifyBuilder(builder); + responseObj["data"] = response; + + //console.log(responseObj); + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + + return; + } + + if(action == "delete") + { + + } + + + if(action == "update") + { + //! data receiving from terminal (params) + // { + // hostname: 'localhost', + // table: 'settings', + // action: 'update', + // body: { + // rvo_name: 'terrrr', + // lang: 'en', + // temperature_adress: '28.427B45920702', + // latitude: 48.70826502, + // longitude: 17.28455203, + // mqtt_host: '192.168.252.4', + // mqtt_clientid: 'showroom_test_panel_led', + // mqtt_username: 'xmRd6RJxW53WZe4vMFLU', + // mqtt_port: 1883, + // maintanace_mode: false + // } + // } + const tableToModify = TABLE(params.table); + const newValues = params.body; + + tableToModify.modify(newValues).make(function(builder) { + + builder.callback(function(err, response) { + + if(!err) + { + responseObj["data"] = response; + responseObj["tableUpdated"] = true; + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + } + }); + }); + + } + + if(action == "replace") + { + //truncate table + const db = TABLE(params.table); + var builder = db.remove(); + db.clean(); + + //insert data + let data = params.data; + + for(let i = 0; i < data.length; i++) + { + //console.log(data[i]); + db.insert(data[i]); + } + + console.log("insert done"); + + let responseObj = {}; + responseObj["type"] = "SUCESS"; + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + + + } + + + + } catch (error) { + //console.log(error); + responseObj["type"] = "ERROR"; + responseObj["message"] = error; + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + } + } + }) +} + + diff --git a/RVO46/flow/db_init.js b/RVO46/flow/db_init.js new file mode 100755 index 0000000..b399878 --- /dev/null +++ b/RVO46/flow/db_init.js @@ -0,0 +1,113 @@ +exports.id = 'db_init'; +exports.title = 'DB Initialization'; +exports.group = 'Worksys'; +exports.color = '#888600'; +exports.version = '1.0.2'; +exports.icon = 'sign-out'; +exports.output = 2; + +exports.readme = ` + # DB initialization +`; + +const { promisifyBuilder, makeMapFromDbResult } = require('./helper/db_helper.js'); +const { initNotification } = require('./helper/notification_reporter'); +const errorHandler = require('./helper/ErrorToServiceHandler'); +const total_energy = require('../databases/total_energy'); + +const SEND_TO = { + db_init: 0, + infoSender: 1 +}; + + +exports.install = async function(instance) { + const dbNodes = TABLE("nodes"); + const dbRelays = TABLE("relays"); + const dbSettings = TABLE("settings"); + 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 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.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"]; + Object.keys(dbs.nodesData).forEach(node => dbs.nodesData[node].readout = {}) + + let rvo_number = responseSettings[0]["rvo_name"].match(/\D+(\d{1,2})_/)[1]; + + dbs.settings = { + edge_fw_version: "2025-10-08", //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"], + phases: responseSettings[0]["phases"], + cloud_topic: responseSettings[0]["cloud_topic"], + has_main_switch: responseSettings[0]["has_main_switch"], + daily_report: responseSettings[0]["daily_report"], + send_changed_node_numbers: responseSettings[0]["send_changed_node_numbers"], + rvo_number: rvo_number, + + //dynamic values + masterNodeIsResponding: true, //cmd_manager + maintenance_mode: false, + } + + + dbs.settings.energy_to_switch_lamps = total_energy[rvo_number]; + if (dbs.settings.energy_to_switch_lamps === undefined) console.log('=============== db_init.js: energy_to_switch_lamps is undefined'); + + FLOW.dbLoaded = true; + errorHandler.setProjectId(dbs.settings.project_id); + initNotification(); + + //APP START - send to data services + const toService = { + id: dbs.settings.project_id, + name: dbs.settings.rvo_name, + fw_version: dbs.settings.edge_fw_version, + startdate: new Date().toISOString().slice(0, 19).replace('T', ' '), + js_error: "", + error_message: "" + }; + + instance.send(SEND_TO.infoSender, toService); + console.log("----------------> START - message send to service", toService); + + setTimeout(() => { + console.log("DB_INIT - data loaded"); + instance.send(SEND_TO.db_init, "_") + }, 5000) + +}; + diff --git a/RVO46/flow/debug.js b/RVO46/flow/debug.js new file mode 100755 index 0000000..00cb259 --- /dev/null +++ b/RVO46/flow/debug.js @@ -0,0 +1,100 @@ +exports.id = 'debug'; +exports.title = 'Debug'; +exports.author = 'Peter Širka'; +exports.color = '#967ADC'; +exports.click = true; +exports.input = true; +exports.icon = 'bug'; +exports.version = '2.0.4'; +exports.options = { enabled: true, repository: false, type: 'data' }; +exports.readme = `# Debug + +Prints data to the debug tab.`; + +exports.html = `
+
+
+
@(Output type)
+
@(Path to the property (leave empty to show the whole data object))
+
@(A group name)
+
@(Enabled)
+
+
+
`; + +exports.install = function(instance) { + + instance.on('data', function(response) { + if (instance.options.enabled) { + + var opt = instance.options; + var rep = response.repository; + var val = response.data; + var id = response.id; + + switch (instance.options.type){ + case 'both': + var data = {}; + data.repository = rep; + data.data = val instanceof Error ? { error: val.message, stack: val.stack } : val; + instance.debug(safeparse(opt.property ? U.get(data, opt.property) : data), undefined, opt.group, id); + break; + case 'repository': + instance.debug(safeparse(opt.property ? U.get(rep, opt.property) : rep), undefined, opt.group, id); + break; + case 'data': + default: + if (val instanceof Error) + instance.debug({ error: val.message, stack: val.stack }, undefined, opt.group, id); + else + instance.debug(safeparse(opt.property ? U.get(val, opt.property) : val), undefined, opt.group, id); + break; + } + } + }); + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + instance.save(); + }); + + instance.on('options', function() { + instance.custom.status(); + }); + + instance.custom.status = function() { + instance.status(instance.options.enabled ? 'Enabled' : 'Disabled'); + }; + + instance.custom.status(); + + function safeparse(o) { + + if (o instanceof Buffer) + return o; + + if (o === undefined) + return 'undefined'; + + if (o === null) + return 'null'; + + var cache = []; + var str = JSON.stringify(o, function(key, value) { + if (typeof value === 'object' && value !== null) { + if (cache.indexOf(value) !== -1) { + try { + return JSON.parse(JSON.stringify(value)); + } catch (error) { + return; + } + } + cache.push(value); + } + return value; + }); + cache = null; + return JSON.parse(str); + } +}; diff --git a/RVO46/flow/designer.json b/RVO46/flow/designer.json new file mode 100755 index 0000000..580f5a3 --- /dev/null +++ b/RVO46/flow/designer.json @@ -0,0 +1,3102 @@ +{ + "tabs": [ + { + "name": "MAIN PUSH", + "linker": "main-push", + "id": "1612772287426", + "index": 0 + }, + { + "name": "CMD manager", + "linker": "cmd-manager", + "id": "1615551125555", + "index": 1 + }, + { + "name": "Devices", + "linker": "devices", + "id": "1611921777196", + "index": 2 + } + ], + "components": [ + { + "id": "1611951142547", + "component": "debug", + "tab": "1611921777196", + "name": "ERROR", + "x": 598, + "y": 60, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#DA4453", + "notes": "" + }, + { + "id": "1612776786008", + "component": "wsmqttpublish", + "tab": "1612772287426", + "name": "WS MQTT publish", + "x": 281.75, + "y": 174, + "connections": { + "0": [ + { + "index": "0", + "id": "1615551060773" + } + ], + "1": [ + { + "index": "0", + "id": "1618300858252" + }, + { + "index": "0", + "id": "1618558465485" + } + ], + "2": [ + { + "index": "0", + "id": "1634303685503" + } + ], + "3": [ + { + "index": "0", + "id": "1731068754606" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Connected", + "color": "green" + }, + "options": { + "username": "", + "clientid": "", + "port": "1883", + "host": "" + }, + "color": "#888600", + "notes": "" + }, + { + "id": "1612778461252", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "tb-push", + "x": 72.75, + "y": 328, + "connections": { + "0": [ + { + "index": "0", + "id": "1612783322136" + }, + { + "index": "1", + "id": "1612776786008" + }, + { + "index": "0", + "id": "1731068754606" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1612783322136", + "component": "debug", + "tab": "1612772287426", + "name": "to TB", + "x": 283.75, + "y": 324, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615551060773", + "component": "debug", + "tab": "1612772287426", + "name": "errors from MQTT Broker", + "x": 594, + "y": 57, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#DA4453", + "notes": "" + }, + { + "id": "1615563373927", + "component": "debug", + "tab": "1615551125555", + "name": "Debug", + "x": 755, + "y": 155, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#DA4453", + "notes": "" + }, + { + "id": "1615566865233", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "tb-push", + "x": 755, + "y": 248, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1615798582262", + "component": "debug", + "tab": "1615551125555", + "name": "CMD_debug", + "x": 755, + "y": 346, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615802995322", + "component": "debug", + "tab": "1611921777196", + "name": "Debug", + "x": 596.8833312988281, + "y": 566.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Disabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": false + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615809128443", + "component": "debug", + "tab": "1611921777196", + "name": "tempToTb", + "x": 595.8833312988281, + "y": 658.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615809595184", + "component": "virtualwireout", + "tab": "1611921777196", + "name": "tb-push", + "x": 597.8833312988281, + "y": 377.25, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1616165795916", + "component": "httproute", + "tab": "1615551125555", + "name": "POST /terminal", + "x": 135, + "y": 547, + "connections": { + "0": [ + { + "index": "0", + "id": "1684060205000" + }, + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Listening", + "color": "green" + }, + "options": { + "timeout": 10, + "cachepolicy": 0, + "cacheexpire": "5 minutes", + "size": 5, + "url": "/terminal", + "method": "POST", + "name": "", + "flags": [ + "id:1616165795916", + "post", + 10000 + ], + "emptyresponse": false + }, + "color": "#5D9CEC", + "notes": "### Configuration\n\n- __POST /terminal__\n- flags: \n- maximum request data length: __5 kB__\n- empty response: __false__\n- cache policy: __no cache__\n- cache expire: __5 minutes__", + "cloning": false + }, + { + "id": "1616165824813", + "component": "httpresponse", + "tab": "1615551125555", + "name": "HTTP Response", + "x": 753, + "y": 423, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "json" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1617104731852", + "component": "debug", + "tab": "1615551125555", + "name": "DIDO_Debug", + "x": 669, + "y": 1040, + "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": "turnOff line", + "x": 133, + "y": 1161, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "object", + "data": "{line: 3, command: \"turnOff\", force: true}" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1617115013095", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "tb-push", + "x": 669, + "y": 1150, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1617284749681", + "component": "trigger", + "tab": "1615551125555", + "name": "update profile / node", + "x": 112, + "y": 208, + "connections": { + "0": [ + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "data": "profile_nodes", + "datatype": "string" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1618235171399", + "component": "trigger", + "tab": "1615551125555", + "name": "tun tasks", + "x": 184, + "y": 279, + "connections": { + "0": [ + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "data": "run" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1618300858252", + "component": "debug", + "tab": "1612772287426", + "name": "wsmqtt-exit1", + "x": 597.8833312988281, + "y": 149, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1618393583970", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "to-cmd-manager", + "x": 668.8833312988281, + "y": 1269, + "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": 132.88333129882812, + "y": 367, + "connections": { + "0": [ + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "platform-rpc-call", + "color": "gray" + }, + "options": { + "wirename": "platform-rpc-call" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1618393759854", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "cmd_to_dido", + "x": 119.88333129882812, + "y": 1007, + "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": 752.8833312988281, + "y": 527, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "cmd_to_dido", + "color": "gray" + }, + "options": { + "wirename": "cmd_to_dido" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1618558465485", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "platform-rpc-call", + "x": 597.8833312988281, + "y": 247, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "platform-rpc-call", + "color": "gray" + }, + "options": { + "wirename": "platform-rpc-call" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1618572059773", + "component": "trigger", + "tab": "1615551125555", + "name": "turnOn line", + "x": 132, + "y": 1085, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "data": "{line: 1, command: \"turnOn\", force: true}", + "datatype": "object" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1619515097737", + "component": "cmd_manager", + "tab": "1615551125555", + "name": "CMD Manager", + "x": 452.1091003417969, + "y": 341.05455017089844, + "connections": { + "0": [ + { + "index": "0", + "id": "1615563373927" + } + ], + "1": [ + { + "index": "0", + "id": "1615566865233" + }, + { + "index": "0", + "id": "1615798582262" + } + ], + "2": [ + { + "index": "0", + "id": "1616165824813" + } + ], + "3": [ + { + "index": "0", + "id": "1618393827655" + } + ], + "4": [ + { + "index": "0", + "id": "1635936391935" + } + ], + "5": [ + { + "index": "0", + "id": "1757006030239" + }, + { + "index": "0", + "id": "1757006060377" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1619605019281", + "component": "httproute", + "tab": "1615551125555", + "name": "GET db", + "x": 173, + "y": 653, + "connections": { + "0": [ + { + "index": "0", + "id": "1684060205000" + }, + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Listening", + "color": "green" + }, + "options": { + "timeout": 5, + "cachepolicy": 0, + "cacheexpire": "5 minutes", + "size": 5, + "url": "/db", + "method": "GET", + "name": "", + "flags": [ + "id:1619605019281", + "get", + 5000 + ] + }, + "color": "#5D9CEC", + "notes": "### Configuration\n\n- __GET /db__\n- flags: undefined\n- maximum request data length: __5 kB__\n- empty response: __undefined__\n- cache policy: __no cache__\n- cache expire: __5 minutes__", + "cloning": false + }, + { + "id": "1619784672383", + "component": "trigger", + "tab": "1615551125555", + "name": "turnOnAlarm", + "x": 120, + "y": 1234, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "object", + "data": "{command: \"turnOnAlarm\"}" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1619784812964", + "component": "trigger", + "tab": "1615551125555", + "name": "turnOffAlarm", + "x": 118, + "y": 1307, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "object", + "data": "{command: \"turnOffAlarm\"}" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1621340721628", + "component": "virtualwireout", + "tab": "1611921777196", + "name": "modbus_to_dido", + "x": 599, + "y": 471, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "modbus_to_dido", + "color": "gray" + }, + "options": { + "wirename": "modbus_to_dido" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1622640022885", + "component": "httproute", + "tab": "1615551125555", + "name": "POST /db_connector", + "x": 98, + "y": 1586, + "connections": { + "0": [ + { + "index": "0", + "id": "1622640073521" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Listening", + "color": "green" + }, + "options": { + "timeout": 5, + "cachepolicy": 0, + "cacheexpire": "5 minutes", + "size": 5, + "url": "/db_connector", + "method": "POST", + "flags": [ + "id:1622640022885", + "post", + 5000 + ] + }, + "color": "#5D9CEC", + "notes": "### Configuration\n\n- __POST /db_connector__\n- flags: \n- maximum request data length: __5 kB__\n- empty response: __undefined__\n- cache policy: __no cache__\n- cache expire: __5 minutes__", + "cloning": false + }, + { + "id": "1622640073521", + "component": "db_connector", + "tab": "1615551125555", + "name": "DbConnector", + "x": 372, + "y": 1572, + "connections": { + "1": [ + { + "index": "0", + "id": "1622641420685" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "edge": "undefined" + }, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1622641420685", + "component": "httpresponse", + "tab": "1615551125555", + "name": "HTTP Response", + "x": 596, + "y": 1586, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1634303504177", + "component": "monitormemory", + "tab": "1612772287426", + "name": "RAM", + "x": 69.88333129882812, + "y": 888.5, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465281992" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "858.88 MB / 985.68 MB", + "color": "gray" + }, + "options": { + "enabled": true, + "interval": 30000 + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1634303533779", + "component": "monitordisk", + "tab": "1612772287426", + "name": "disk", + "x": 70.88333129882812, + "y": 982.5, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465821120" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "5.78 GB / 7.26 GB", + "color": "gray" + }, + "options": { + "enabled": true, + "path": "/", + "interval": 30000 + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1634303595494", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "send-to-services", + "x": 51.883331298828125, + "y": 1400.5, + "connections": { + "0": [ + { + "index": "0", + "id": "1634463186563" + }, + { + "index": "1", + "id": "1634488120710" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1634303602169", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "send-to-services", + "x": 426.8833312988281, + "y": 878.5, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1634303685503", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "send-to-services", + "x": 600.8833312988281, + "y": 341.5, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1634303743260", + "component": "httprequest", + "tab": "1612772287426", + "name": "192.168.252.2:8004/sentmessage", + "reference": "", + "x": 506.8833312988281, + "y": 1331.7333374023438, + "connections": { + "0": [ + { + "index": "0", + "id": "1635327431236" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "url": "http://192.168.252.2:8004/sentmessage", + "method": "POST", + "stringify": "json" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1634463186563", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 305.75, + "y": 1442, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634464580289", + "component": "code", + "tab": "1612772287426", + "name": "Code", + "x": 245, + "y": 787, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465243324" + }, + { + "index": "0", + "id": "1634303602169" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "keepmessage": true, + "code": "let response = {};\nresponse.cpu = value.cpu;\nresponse.uptime = value.uptime;\n\nsend(0, response);", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1634465243324", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 428, + "y": 784, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634465281992", + "component": "code", + "tab": "1612772287426", + "name": "Code", + "x": 245, + "y": 884, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465338103" + }, + { + "index": "0", + "id": "1634303602169" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "keepmessage": true, + "code": "value.sender = \"ram\";\n\nlet response = {};\n\nresponse.memory_total = Math.round(value.total / (1024 ** 2));\nresponse.memory_free = Math.round(value.free / (1024 ** 2));\nresponse.memory_used = Math.round(value.used / (1024 ** 2));\n\nsend(0, response);", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1634465338103", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 429, + "y": 976, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634465821120", + "component": "code", + "tab": "1612772287426", + "name": "Code", + "x": 245, + "y": 978, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465892500" + }, + { + "index": "0", + "id": "1634303602169" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "keepmessage": true, + "code": "value.sender = \"hdd\";\n\nlet response = {};\n\nresponse.hdd_total = Math.round(value.total / (1024 ** 2));\nresponse.hdd_free = Math.round(value.free / (1024 ** 2));\nresponse.hdd_used = Math.round(value.used / (1024 ** 2));\n\nsend(0, response);", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1634465892500", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 432, + "y": 1068, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634484067516", + "component": "debug", + "tab": "1612772287426", + "name": "Send info", + "x": 513, + "y": 1441, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634488120710", + "component": "infosender", + "tab": "1612772287426", + "name": "Info sender", + "x": 301, + "y": 1336, + "connections": { + "0": [ + { + "index": "0", + "id": "1634484067516" + }, + { + "index": "0", + "id": "1634303743260" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "edge": "undefined" + }, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1635327431236", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 837.8833312988281, + "y": 1325.5, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1635936391935", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "send-to-services", + "x": 753, + "y": 623, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1637069803394", + "component": "monitorconsumption", + "tab": "1612772287426", + "name": "CPU", + "x": 69, + "y": 791, + "connections": { + "0": [ + { + "index": "0", + "id": "1634464580289" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "49.2% / 69.91 MB", + "color": "gray" + }, + "options": { + "monitorfiles": true, + "monitorconnections": true, + "monitorsize": true, + "monitorconsumption": true, + "enabled": true, + "interval": 30000 + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1683664161036", + "component": "debug", + "tab": "1615551125555", + "name": "CMDtoDIDO", + "x": 392, + "y": 1012, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1683981346282", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "from-dido-controller", + "x": 112, + "y": 459, + "connections": { + "0": [ + { + "index": "0", + "id": "1684055037116" + }, + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "from-dido-controller", + "color": "gray" + }, + "options": { + "wirename": "from-dido-controller" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1684055037116", + "component": "debug", + "tab": "1615551125555", + "name": "from dido to cmd", + "x": 451, + "y": 532, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1684060205000", + "component": "debug", + "tab": "1615551125555", + "name": "HTTP routes", + "x": 450, + "y": 639, + "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": "MDBToDido", + "x": 598, + "y": 147, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1699963668903", + "component": "dido_controller", + "tab": "1615551125555", + "name": "DIDO_Controller", + "x": 397, + "y": 1131, + "connections": { + "0": [ + { + "index": "0", + "id": "1617104731852" + } + ], + "1": [ + { + "index": "0", + "id": "1617104731852" + }, + { + "index": "0", + "id": "1617115013095" + } + ], + "2": [ + { + "index": "0", + "id": "1618393583970" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "edge": "undefined" + }, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1699964678894", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "modbus_to_dido", + "x": 96, + "y": 924, + "connections": { + "0": [ + { + "index": "0", + "id": "1699963668903" + }, + { + "index": "0", + "id": "1699964793925" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "modbus_to_dido", + "color": "gray" + }, + "options": { + "wirename": "modbus_to_dido" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1699964793925", + "component": "debug", + "tab": "1615551125555", + "name": "modbusToDido", + "x": 388, + "y": 920, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1699965957410", + "component": "modbus_reader", + "tab": "1611921777196", + "name": "Modbus reader", + "x": 232, + "y": 175, + "connections": { + "0": [ + { + "index": "0", + "id": "1611951142547" + } + ], + "1": [ + { + "index": "0", + "id": "1621340721628" + }, + { + "index": "0", + "id": "1684179110403" + }, + { + "index": "0", + "id": "1717441414646" + } + ], + "2": [ + { + "index": "0", + "id": "1615809595184" + }, + { + "index": "0", + "id": "1714752862828" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1700411878636", + "component": "thermometer", + "tab": "1611921777196", + "name": "Thermometer", + "x": 234.75, + "y": 444, + "connections": { + "0": [ + { + "index": "0", + "id": "1615802995322" + } + ], + "1": [ + { + "index": "0", + "id": "1615809595184" + }, + { + "index": "0", + "id": "1615809128443" + } + ], + "2": [ + { + "index": "0", + "id": "1621340721628" + }, + { + "index": "0", + "id": "1732889185927" + }, + { + "index": "0", + "id": "1717441414646" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#5CB36D", + "notes": "" + }, + { + "id": "1714752862828", + "component": "debug", + "tab": "1611921777196", + "name": "MDBToTb", + "x": 766, + "y": 324, + "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": 764.0833282470703, + "y": 222, + "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\telse if(value.status === \"NOK-thermometer\")\n\t{\n\t\tsend(0, {\"thermometer\": \"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\telse if(value.values.hasOwnProperty(\"temperature\"))\n\t{\n\t\tsend(0, {\"thermometer\": \"OK\"});\n\t}\n}", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1717442627834", + "component": "debug", + "tab": "1611921777196", + "name": "modbus service", + "x": 966.0833282470703, + "y": 165, + "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": 968.0833282470703, + "y": 268, + "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": 88.75, + "y": 1685, + "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": 296, + "y": 1671, + "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\", \"Flow has been restarted\", \"Node db has changed\"]", + "types": "[\"emergency\", \"critical\", \"error\", \"alert\"]", + "name": "" + }, + "color": "#30E193", + "notes": "" + }, + { + "id": "1718016073501", + "component": "httprequest", + "tab": "1612772287426", + "name": "http://192.168.252.2:8004/slack", + "x": 495, + "y": 1753, + "connections": { + "0": [ + { + "index": "0", + "id": "1718016086212" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "url": "http://192.168.252.2:8004/slack", + "method": "POST", + "stringify": "json" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1718016086212", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 832, + "y": 1664, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "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": 87, + "y": 1591, + "connections": { + "0": [ + { + "index": "0", + "id": "1718016052341" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "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\": \"\" } } } ] }", + "datatype": "object" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1729855334955", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "platform-rpc-call", + "x": 599.9333343505859, + "y": 541.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "platform-rpc-call", + "color": "gray" + }, + "options": { + "wirename": "platform-rpc-call" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1729855371093", + "component": "debug", + "tab": "1612772287426", + "name": "rpc cloud", + "x": 601.9333343505859, + "y": 440.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1731068658334", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 75.75, + "y": 184, + "connections": { + "0": [ + { + "index": "0", + "id": "1612776786008" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731068754606", + "component": "cloudmqttconnect", + "tab": "1612772287426", + "name": "MQTT to senica-prod01", + "x": 284.75, + "y": 452, + "connections": { + "1": [ + { + "index": "0", + "id": "1729855371093" + }, + { + "index": "0", + "id": "1729855334955" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Connected", + "color": "green" + }, + "options": { + "username": "", + "clientid": "", + "port": "2764", + "host": "192.168.252.2", + "topic": "" + }, + "color": "#888600", + "notes": "" + }, + { + "id": "1731069001548", + "component": "db_init", + "tab": "1612772287426", + "name": "DB Initialization", + "x": 1003.75, + "y": 240.25, + "connections": { + "0": [ + { + "index": "0", + "id": "1731069033416" + } + ], + "1": [ + { + "index": "0", + "id": "1747561603739" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#888600", + "notes": "" + }, + { + "id": "1731069033416", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "db-init", + "x": 1244.75, + "y": 233.25, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069059135", + "component": "showdb", + "tab": "1612772287426", + "name": "Show db data", + "x": 1186.75, + "y": 821.25, + "connections": { + "0": [ + { + "index": "0", + "id": "1731069079243" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#888600", + "notes": "" + }, + { + "id": "1731069079243", + "component": "debug", + "tab": "1612772287426", + "name": "dbData", + "x": 1390.75, + "y": 870.25, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1731069116691", + "component": "trigger", + "tab": "1612772287426", + "name": "settings", + "x": 934.75, + "y": 669.75, + "connections": { + "0": [ + { + "index": "0", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069131637", + "component": "trigger", + "tab": "1612772287426", + "name": "relaysData", + "x": 876.75, + "y": 733.75, + "connections": { + "0": [ + { + "index": "1", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069137374", + "component": "trigger", + "tab": "1612772287426", + "name": "nodesData", + "x": 852.75, + "y": 794.75, + "connections": { + "0": [ + { + "index": "2", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069179846", + "component": "trigger", + "tab": "1612772287426", + "name": "pinsData", + "x": 850.75, + "y": 861.75, + "connections": { + "0": [ + { + "index": "3", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069192937", + "component": "trigger", + "tab": "1612772287426", + "name": "sample data", + "x": 857.75, + "y": 928.75, + "connections": { + "0": [ + { + "index": "4", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069264443", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 63.75, + "y": 1279, + "connections": { + "0": [ + { + "index": "0", + "id": "1634488120710" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069334626", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "db-init", + "x": 172.88333129882812, + "y": 129, + "connections": { + "0": [ + { + "index": "0", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069548145", + "component": "virtualwirein", + "tab": "1611921777196", + "name": "db-init", + "x": 46.75, + "y": 192, + "connections": { + "0": [ + { + "index": "0", + "id": "1699965957410" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069567152", + "component": "virtualwirein", + "tab": "1611921777196", + "name": "db-init", + "x": 44.75, + "y": 465, + "connections": { + "0": [ + { + "index": "0", + "id": "1700411878636" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731070156936", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "db-init", + "x": 126.88333129882812, + "y": 1377, + "connections": { + "0": [ + { + "index": "2", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731234189516", + "component": "trigger", + "tab": "1612772287426", + "name": "monitor.txt", + "x": 882.75, + "y": 991.75, + "connections": { + "0": [ + { + "index": "5", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731234189551", + "component": "trigger", + "tab": "1612772287426", + "name": "err.txt", + "x": 904.75, + "y": 1053.75, + "connections": { + "0": [ + { + "index": "6", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1732700042559", + "component": "nodesdb_change_check", + "tab": "1612772287426", + "name": "Nodes DB change check", + "x": 266.8833312988281, + "y": 1980.2333984375, + "connections": { + "0": [ + { + "index": "0", + "id": "1732700071298" + }, + { + "index": "0", + "id": "1732700642917" + } + ], + "1": [ + { + "index": "0", + "id": "1759958914348" + }, + { + "index": "0", + "id": "1759959003114" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#888600", + "notes": "" + }, + { + "id": "1732700057052", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 76.75, + "y": 1988, + "connections": { + "0": [ + { + "index": "0", + "id": "1732700042559" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1732700071298", + "component": "debug", + "tab": "1612772287426", + "name": "nodesChange", + "x": 571.8833312988281, + "y": 2018.2333984375, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1732700642917", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "tb-push", + "x": 567.8833312988281, + "y": 1933, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1732889185927", + "component": "debug", + "tab": "1611921777196", + "name": "tempToDido", + "x": 594.8833312988281, + "y": 753, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1733574412965", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 72.75, + "y": 474, + "connections": { + "0": [ + { + "index": "1", + "id": "1731068754606" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1747561603739", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "send-to-services", + "x": 1243.8833312988281, + "y": 334.5, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1747562867845", + "component": "comment", + "tab": "1612772287426", + "name": "FLOW STARTING POINT", + "x": 1003.5666656494141, + "y": 178, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#704cff", + "notes": "" + }, + { + "id": "1749211698385", + "component": "trigger", + "tab": "1612772287426", + "name": "deviceStatus", + "x": 911.75, + "y": 1116.75, + "connections": { + "0": [ + { + "index": "7", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1757006030239", + "component": "httprequest", + "tab": "1615551125555", + "name": "192.168.252.2:8015/daily_report", + "x": 756.5666656494141, + "y": 715.4499969482422, + "connections": { + "0": [ + { + "index": "0", + "id": "1757006045804" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "stringify": "json", + "method": "POST", + "url": "http://192.168.252.2:8015/daily_report" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1757006045804", + "component": "debug", + "tab": "1615551125555", + "name": "ddd", + "x": 1091.566665649414, + "y": 711.4499969482422, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1757006060377", + "component": "debug", + "tab": "1615551125555", + "name": "reportDebug", + "x": 749.5666656494141, + "y": 799.4499969482422, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1759958914348", + "component": "httprequest", + "tab": "1612772287426", + "name": "http://192.168.252.2:8015/node_numbers", + "x": 571, + "y": 2111, + "connections": { + "0": [ + { + "index": "0", + "id": "1759958927094" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "stringify": "json", + "method": "POST", + "url": "http://192.168.252.2:8015/node_numbers" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1759958927094", + "component": "debug", + "tab": "1612772287426", + "name": "nodesChangeCloud", + "x": 951.8833312988281, + "y": 2109.2333984375, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1759959003114", + "component": "debug", + "tab": "1612772287426", + "name": "nodeChangeCloud1", + "x": 574, + "y": 2218, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1760020290879", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 84.75, + "y": 1787, + "connections": { + "0": [ + { + "index": "1", + "id": "1718016052341" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + } + ], + "version": 615 +} diff --git a/RVO46/flow/dido_controller.js b/RVO46/flow/dido_controller.js new file mode 100755 index 0000000..d16fb19 --- /dev/null +++ b/RVO46/flow/dido_controller.js @@ -0,0 +1,1486 @@ +exports.id = 'dido_controller'; +exports.title = 'DIDO_Controller'; +exports.version = '2.0.0'; +exports.group = 'Worksys'; +exports.color = '#2134B0'; +exports.input = 3; +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 + +state_of_main_switch - reportovat stav hlaveho istica : 0-> off 1-> on +rotary_switch_state - sem by sa mal reportovat stav vstupov manual a auto pola nasledovnej logiky: Manual = 1 a Auto = 0 -> Manu +Manual = 0 a Auto = 0 -> Off, Manual = 0 a Auto = 1 -> Automatic + +door_condition - pin 6, dverový kontakt -> 1 -> vyreportuje Closed, 0 -> vyreportuje Ope +twilight_sensor - hodnotu, ktoru vracia ten analogovy vstup (17) treba poslat sem ako float number. Zrejme tu potom pridame nejaky koeficient prevodu na luxy + +Na kazdu liniu +state_of_breaker - podla indexu istica sa reportuje jeho stav, teda istic na liniu 1: 0-> off, 1-> on +state_of_contactor - podla indexu stkaca sa reportuje jeho stav, teda stykac 1 na liniu 1: 0-> off, 1-> on +*/ + +const { errLogger, logger, monitor } = require('./helper/logger'); +const SerialPort = require('serialport'); +const WebSocket = require('ws'); +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 errorHandler = require('./helper/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 hasMainSwitch; + +let alarmStatus = "OFF"; + +const SEND_TO = { + debug: 0, + tb: 1, + cmd_manager: 2 +} + + +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 = {}; + let rsPortReceivedData = []; + + //to be able to get proper twilight values + let twilight_sensor_interval = 5;//minutes + let twilight_sensor = []; + const twilight_sensor_array = []; + let twilightError = false; + + monitor.info("DIDO_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-we make it global to see it from outside + FLOW.deviceStatus = { //key is device name: temperature,.... + "state_of_main_switch": "Off", //Hlavny istic (alebo druhy dverovy kontakt) + "rotary_switch_state": "Off", //Prevadzkovy + "door_condition": "closed", //Dverový kontakt + "em": "OK", //elektromer rvo + "temperature": "OK", //templomer + "battery": "OK", //Bateria + "power_supply": "OK", //Zdroj + "master_node": "OK", //MN - GLOBALS.settings.masterNodeIsResponding + "no_voltage": "OK", //GLOBALS.settings.no_voltage - vypadok napatia na faze + "state_of_breaker": {}, //"Off",//Istic + "state_of_contactor": {}, //"Off",//Stykac + "twilight_sensor": "OK" //lux sensor + }; + let deviceStatus = FLOW.deviceStatus; + + + function main() { + + GLOBALS = FLOW.GLOBALS; + SETTINGS = FLOW.GLOBALS.settings; + rvoTbName = SETTINGS.rvoTbName; + pinsData = GLOBALS.pinsData; + relaysData = GLOBALS.relaysData; + + tbHandler = new DataToTbHandler(SEND_TO.tb); + tbHandler.setSender(exports.title); + + controller_type = SETTINGS.controller_type; //"lm" or "unipi" + hasMainSwitch = SETTINGS.has_main_switch; + + if (controller_type == "") controller_type = "lm"; + + 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, "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; + } + } + + //report RVO version relaysData[0].tbname; + let values = {}; + values["edge_fw_version"] = SETTINGS.edge_fw_version; + values["maintenance_mode"] = SETTINGS.maintenance_mode; + + sendTelemetry(values, rvoTbName); + + 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); + } + + + function handleRsPort() { + + if (rsPort) { + rsPort.removeAllListeners(); + rsPort = null; + } + + //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('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) { + if (!err) { + monitor.info(exports.title + "--->Digital in_out has been set (runSyncExec was sucessfull)"); + + turnAlarm("off"); + 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('error', err => { + let message = "Dido: rsPort error: " + err.message; + logger.debug(message); + monitor.info(message); + errorHandler.sendMessageToService(message); + }) + + rsPort.on("close", () => { + let message = "Dido: rsPort closed - reconnecting ..."; + logger.debug(message); + monitor.info(message); + setTimeout(handleRsPort, 1000); + }) + + rsPort.open(); + } + + + function handleWebSocket() { + + if (ws) { + ws.removeAllListeners(); + ws = null; + } + + //to keep websocket opened, we send request every 150 seconds + let startRequests = null; + + console.log("handleWebSocket function called"); + ws = new WebSocket('ws:/0.0.0.0:1234/ws'); + + ws.onopen = function open() { + + instance.send(0, exports.title + " running"); + turnAlarm("off"); + + initialSetting(); + + setTimeout(function() { ws.send(JSON.stringify({ cmd: "all" })) }, 5000); + // we request dev info about neuron device from evok to keep websocket connection alive + // for some reason this request returns no data, but connection keeps alive + startRequests = setInterval(() => { + ws.send(JSON.stringify({ "cmd": "filter", "dev": ["neuron"] })); + }, 150000) + }; + + + // 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 = async 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; + + 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 => { + logger.debug('Dido: websocket error', err); + }) + + ws.onclose = function() { + logger.debug('Dido: websocket onclose, reconnecting...') + clearInterval(startRequests); + setTimeout(handleWebSocket, 1000); + } + } + + 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 turnAlarm(onOrOff) { + let value = 0; + if (onOrOff == "on") value = 1; + + if (value == 1 && SETTINGS.maintenance_mode) return; + + alarmStatus = "OFF"; + if (value == 1) alarmStatus = "ON"; + + if (rsPort) { + let arr = [0x55]; + arr.push(13); + arr.push(0); + arr.push(value); + + rsPort.write(Buffer.from(arr), function(err) { + logger.debug(`sirena - ${onOrOff}`); + }); + } + else if (ws) { + let cmd = { "cmd": "set", "dev": "relay", "circuit": "1_01", "value": value }; + ws.send(JSON.stringify(cmd)); + logger.debug(`sirena - ${onOrOff}`); + } + } + + + 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") { + bits.push(0); + } + else bits.push(1); + + if (deviceStatus["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); + } + + + // turn line on or off + function turnLine(onOrOff, line, pin, force, info) { + //onOrOff => "on" or "off" + let value = 0; + if (onOrOff == "on") value = 1; + + if (force == undefined) force = false; + + if (line == 0) { + if (value == 1 && alarmStatus == "ON") turnAlarm("off"); + SETTINGS.maintenance_mode = value ? true : false; + + 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); + return; + } + + if (pin === undefined) pin = getPin(line); + + if (pin === undefined) { + errLogger.error("pin is undefined!", line); + return; + } + + if (!force) { + if (relaysData[line].contactor == value) { + instance.send(SEND_TO.debug, `line is already ${onOrOff} ` + line); + logger.debug(`Dido: turnLine: line is already ${onOrOff} `, line); + return; + } + } + + // if(!rsPort.isOpen && !ws) + if (!rsPort && !ws) { + errLogger.error("Dido - port or websocket is not opened"); + return; + } + + if (rsPort) { + let arr = [0x55]; + arr.push(pin); + arr.push(0); + arr.push(value); + + rsPort.write(Buffer.from(arr), function(err) { + if (err === undefined) { + monitor.info(`Dido: turnLine ${onOrOff} zapisal do rsPort-u`, line, pin, arr, info); + switchLogic(arr); + } + else { + monitor.info(`Dido: turnLine ${onOrOff} WRITE error`, err); + } + }); + + } + else if (ws) { + //pin = "relay1_03" or "input1_01" ... we must make just "1_01" with slice method + monitor.info(`Dido: turnLine ${onOrOff} - (line, pin, force)`, line, pin, force, info); + let cmd = { "cmd": "set", "dev": "relay", "circuit": pin.slice(5), "value": value }; + ws.send(JSON.stringify(cmd)); + } + + //if rvo is 24/7, it has just one switching profile point at 13:00. we do not want to send notification as it repeats every day. + //const d = new Date(); + //if(d.getHours() != 13) sendNotification("Dido_controller: ", SETTINGS.rvoTbName, "switching_profile_point_applied_to_line", { line: line, value: onOrOff }, "", SEND_TO.tb, instance); + } + + + // 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; + + // 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) { + const status = flowdata.data.status; + if (status == "NOK-twilight_sensor") { + deviceStatus["twilight_sensor"] = "NOK"; + } + else if (status == "NOK-em340" || status == "NOK-em111") { + deviceStatus["em"] = "NOK"; + } + else if (status == "NOK-thermometer") { + deviceStatus["temperature"] = "NOK"; + } + } + else if ("values" in flowdata.data) { + 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" + } + else if (values.hasOwnProperty("temperature")) { + deviceStatus["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"; + } + + sendTelemetry(values, rvoTbName); + } + + sendRvoStatus(); + }) + + + + + // we expect array as flowdata.data + instance.on("1", flowdata => { + + //console.log(flowdata.data); + + if (!flowdata.data instanceof Object) return; + + let obj = flowdata.data; + let line = obj.line; + 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"); + }) + + + function calculateStateCode() { + + let bits = []; + + //Hlavny istic - state_of_main_switch => v rvo senica je to druhy door pre silovu cast (EM) + if (deviceStatus["state_of_main_switch"] === "closed" || deviceStatus["state_of_main_switch"] === "Off") { + bits.push(0); + } + else { + bits.push(1); + } + + //Prevadzkovy mod - Manual, Off, Automatic, maintenance_mode = true/false // DAVA 2 BITY + if (!SETTINGS.maintenance_mode) { + if (deviceStatus["rotary_switch_state"] === "Manual") { + bits.push(0); + bits.push(1); + } + + if (deviceStatus["rotary_switch_state"] === "Automatic") { + bits.push(0); + bits.push(0); + } + + if (deviceStatus["rotary_switch_state"] === "Off") { + bits.push(1); + bits.push(0); + } + } + else { + bits.push(1); + bits.push(1); + } + + //Dverovy kontakt + if (deviceStatus["door_condition"] === "closed") { + bits.push(0); + } + else { + bits.push(1); + } + + //EM + if (deviceStatus["em"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //Teplomer + if (deviceStatus["temperature"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //Batéria + if (deviceStatus["battery"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //Zdroj + if (deviceStatus["power_supply"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //MN + if (deviceStatus["master_node"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //výpadok napätia na fáze + if (deviceStatus["no_voltage"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + if (deviceStatus["twilight_sensor"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + // doplnime do 16 bitov (2 byty) + for (let i = bits.length; i < 16; i++) { + bits.push(0); + } + + // console.log("calculateStateCode - deviceStatus", deviceStatus); + // 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; + } + + + async function sendRvoStatus() { + + if (SETTINGS === undefined) return; + SETTINGS.masterNodeIsResponding ? deviceStatus["master_node"] = "OK" : deviceStatus["master_node"] = "NOK"; + + 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 pinsForRvoStatus(controllerType, hasMainSwitch) { + + let pins = []; + + if (controllerType === "lm") { + pins = [1, 4, 6]; + if (hasMainSwitch === 1) { + pins = [4, 6]; + } + } else if (controllerType === "unipi") { + pins = ["input1_01", "input1_04", "input1_05"]; + if (hasMainSwitch === 1) { + pins = ["input1_01", "input1_04"]; + } + } + + return pins; + } + + + function checkRvoStatus() { + + // 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 + //set RVO state + let status = "OK"; + + for (const [key, value] of Object.entries(deviceStatus)) { + if (["em", "twilight_sensor", "temperature", "master_node"].includes(key) && value === "NOK") status = "NOK"; + } + + if (status === "OK") { + + let pinIndexes = pinsForRvoStatus(controller_type, hasMainSwitch); + + for (const pinIndex of pinIndexes) { + if (previousValues[pinIndex] === 0) { + if ((pinIndex === 6 || pinIndex === 'input1_01' || pinIndex === 'input1_05') && SETTINGS.maintenance_mode) continue; + status = "NOK"; + break; + } + } + } + + // battery status. If value is 1 - battery is NOK + if (previousValues[5] === 1) status = "NOK"; + if (SETTINGS.no_voltage.size > 0) status = "NOK"; + + // console.log("rvo status",status) + return status; + } + + + // we pass array to function in case of rsPort ==> switchLogic([55,3,0,1]) ==> [[55,3,0,1]] + // we pass two values in case of websocket ==> switchLogic("relay1_03",1) ==> ["relay1_03",1] + const switchLogic = (...args) => { + + let values = {}; + let pinIndex, newPinValue, twilight; + + //data from rsPort + if (args.length == 1) { + pinIndex = args[0][1] + 1; + if (pinIndex === 17) pinIndex--; + newPinValue = args[0][3]; + twilight = args[0][2]; + } + //data from websocket + else { + pinIndex = args[0]; + newPinValue = args[1]; + } + + 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; + + //default value + let value = "On"; + if (newPinValue === 0) value = "Off"; + + //Hlavny istic + if (type === "state_of_main_switch" && hasMainSwitch) { + if (newPinValue === 0 && newPinValue !== previousValues[pinIndex]) { + sendNotification("switchLogic", rvoTbName, "main_switch_has_been_turned_off", {}, "", SEND_TO.tb, instance, "state_of_main_switch"); + 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"); + deviceStatus["state_of_main_switch"] = "On"; + } + } + + //Prevadzkovy mod + 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"; + + deviceStatus["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, "power_supply_has_disconnected_input", {}, "", SEND_TO.tb, instance, "power_supply"); + + deviceStatus["power_supply"] = "NOK"; + } + else if (newPinValue === 1 && newPinValue !== previousValues[pinIndex]) { + sendNotification("switchLogic", rvoTbName, "power_supply_works_correctly", {}, "", SEND_TO.tb, instance, "power_supply"); + + deviceStatus["power_supply"] = "OK"; + } + } + + //Bateria - 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"); + + deviceStatus["battery"] = "NOK"; + } + else if (newPinValue === 0 && newPinValue !== previousValues[pinIndex]) { + sendNotification("switchLogic", rvoTbName, "battery_level_is_ok", {}, "", SEND_TO.tb, instance, "battery_level"); + + deviceStatus["battery"] = "OK"; + } + } + + //Dverovy kontakt - pin 6 + //! Ak je rvo s dvoma dverovymi kontaktami, ked pride z evoku signal z input1_05, co bol predytm "state_of_main switch" handlujeme ho teraz ako 'door_condition' + else if (type == "door_condition" || type === "state_of_main_switch") { + newPinValue === 0 ? value = "open" : value = "closed"; + + let door = "door_main"; + if (type === "state_of_main_switch") door = "door_em"; + + if (value === "open") { + if (SETTINGS.maintenance_mode) { + sendNotification("switchLogic", rvoTbName, door + "_open", {}, "", SEND_TO.tb, instance, door); + } else { + sendNotification("switchLogic", rvoTbName, door + "_open_without_permission", {}, "", SEND_TO.tb, instance, door); + + // 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 (value === "closed") { + if (alarmStatus == "ON") turnAlarm("off"); + sendNotification("switchLogic", rvoTbName, door + "_close", {}, "", SEND_TO.tb, instance, door); + } + + deviceStatus[type] = value; + } + + //lux sensor + else if (type == "twilight_sensor") { + //! TODO - to show nok status, if lux value is not changing more then 10 times. + //Daylight is far more than 1000. So most of the day, when it is sunshine comes just value 1000. But lux sensor is not NOK. + //This is not the case in LM. If value from LM is the same 10x, there is 99% possibility, that sensor is NOK. + value = newPinValue; + + if (controller_type === 'lm') { + value = parseFloat(newPinValue + (256 * twilight)); + + 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 && !twilightError) { + twilightError = true; + let value = twilight_sensor_array.shift(); + + newPinValue = 0; + } + else if (set.size !== 1 && twilightError) { + //sendNotification("switchLogic", rvoTbName, 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) { + 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); + } + } + + 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); + } + + deviceStatus["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 (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 }); + + //mame iba 3 istice. vyreportujeme a ohandlujeme liniu na tom istom istici ako paralelna linia (napr linia 1, paralelna s nou je linia 4, key je string "4") + // ak je 7 linii, na 1 istici je linia 1,4,7 + + if (line == 1) { + + const lineOnSameBraker = [4, 7]; + + for (var i = 0; i < lineOnSameBraker.length; i++) { + if (!relaysData.hasOwnProperty(lineOnSameBraker[i])) continue; + + 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; + reportLineStatus(lineOnSameBraker[i]); + + values[type] = value; + const tbname = relaysData[lineOnSameBraker[i]].tbname; + sendTelemetry(values, tbname); + + delete values[type]; + } + + } + else { + const lineOnSameBraker = line + 3 + ""; + + if (relaysData.hasOwnProperty(lineOnSameBraker)) { + 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; + reportLineStatus(line + 3); + + values[type] = value; + const tbname = relaysData[lineOnSameBraker].tbname; + sendTelemetry(values, tbname); + + delete values[type]; + } + } + + } + + if (value == "Off") values["status"] = "NOK"; + deviceStatus["state_of_breaker"][line] = value; + + reportLineStatus(line); + } + else return; + + values[type] = value; + + if (type == "rotary_switch_state") { + if (SETTINGS.maintenance_mode) value = "maintenance"; + value = value.toLowerCase(); + values["power_mode"] = value; + } + + if (newPinValue != previousValues[pinIndex]) previousValues[pinIndex] = newPinValue; + if (Object.keys(values).length > 0 && tbname) sendTelemetry(values, tbname); + } + + + function sendTelemetry(values, tbname, date = Date.now()) { + let dataToTb = { + [tbname]: [ + { + "ts": date, + "values": values + } + ] + }; + + tbHandler.sendToTb(dataToTb, instance); + } + + + function isObject(item) { + return (typeof item === "object" && !Array.isArray(item) && item !== null); + } + +} //end of 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 +// *|input1_01|state_of_main_switch|0|........... +// *|input1_02|rotary_switch_state|0|........... +// *|input1_03|rotary_switch_state|0|........... +// *|intut1_04|power_supply|0|........... +// *|input1_05|door_condition|0|........... +// *|input1_06|state_of_breaker|1|........... +// *|input1_07|state_of_breaker|2|........... +// *|input1_08|state_of_breaker|3|........... +// *|relay1_02|state_of_contactor|1|........... +// *|relay1_03|state_of_contactor|2|........... +// *|relay1_04|state_of_contactor|3|........... +// *|287D8776E0013CE9|temperature|0|........... + + +//! pins_data --> from UNIPI +// { +// 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 } +// } + +//! relays_data +// { +// '0': { +// line: 0, +// tbname: 'KjbN4q7JPZmexgdnz2yKQ98YAWwO0Q3BMX6ERLoV', +// contactor: 1, +// profile: '' +// }, +// '1': { +// line: 1, +// tbname: 'RMgnK93rkoAazbqdQ4yBG95Z1YXGx6pmwBeVEP2O', +// contactor: 0, +// profile: '{"intervals":[{"value":0,"end_time":"20:00","start_time":"13:00"},{"value":1,"end_time":"10:00","start_time":"20:00"},{"value":0,"end_time":"10:20","start_time":"10:00"},{"value":1,"end_time":"10:40","start_time":"10:20"},{"value":0,"end_time":"11:00","start_time":"10:40"},{"value":1,"end_time":"11:30","start_time":"11:00"},{"value":0,"end_time":"11:50","start_time":"11:30"},{"value":1,"end_time":"13:00","start_time":"11:50"}],"astro_clock":false,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' +// }, +// '2': { +// line: 2, +// tbname: 'dlE1VQjYrNx9gZRmb38gG08oLBO4qaAk2M6JPnG7', +// contactor: 0, +// profile: '{"intervals":[{"value":0,"end_time":"20:00","start_time":"13:00"},{"value":1,"end_time":"10:00","start_time":"20:00"},{"value":0,"end_time":"10:20","start_time":"10:00"},{"value":1,"end_time":"10:40","start_time":"10:20"},{"value":0,"end_time":"11:00","start_time":"10:40"},{"value":1,"end_time":"11:30","start_time":"11:00"},{"value":0,"end_time":"11:50","start_time":"11:30"},{"value":1,"end_time":"13:00","start_time":"11:50"}],"astro_clock":false,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' +// }, +// '3': { +// line: 3, +// tbname: 'vnmG4kJxaXWNBgMQq0D7Aj5e9oZzOAlr6LdR3w2V', +// contactor: 0, +// profile: '{"intervals":[{"value":0,"end_time":"20:30","start_time":"13:00"},{"value":1,"end_time":"00:10","start_time":"20:30"},{"value":0,"end_time":"13:00","start_time":"05:40"},{"value":1,"end_time":"05:40","start_time":"00:10"}],"astro_clock":true,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' +// } +// } + + + + + +// { +// "jbN4q7JPZmexgdnz2yKbWGDYAWwO0Q3BMX6ERLoV": [ +// { +// "ts": 1700409326353, +// "values": { +// "_event": { +// "type": "notice", +// "status": "new", +// "source": { +// "func": "rsPort.open()", +// "component": "1700343402190", +// "component_name": "DIDO_Controller", +// "edge": "jbN4q7JPZmexgdnz2yKbWGDYAWwO0Q3BMX6ERLoV" +// }, +// "message": "al_shariff_10.0.0.38: FLOW has been started ", +// "message_data": "" +// } +// } +// } +// ] +// } diff --git a/RVO46/flow/helper/DataToTbHandler.js b/RVO46/flow/helper/DataToTbHandler.js new file mode 100755 index 0000000..716ef7b --- /dev/null +++ b/RVO46/flow/helper/DataToTbHandler.js @@ -0,0 +1,187 @@ +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; + this.itIsNodeReadout = false; + this.sender = ""; + + // if attribute change difference is less than limit value, we do not send to tb. + this.attributeChangeLimit = { + temperature: 0.5, + Phase_1_voltage: 2, + Phase_2_voltage: 2, + Phase_3_voltage: 2, + Phase_1_current: 0.1, + Phase_2_current: 0.1, + Phase_3_current: 0.1, + Phase_1_power: 2, + Phase_2_power: 2, + Phase_3_power: 2, + total_power: 2, + total_energy: 1, + Phase_1_pow_factor: 0.1, + Phase_2_pow_factor: 0.1, + Phase_3_pow_factor: 0.1, + power_factor: 0.1, + lifetime: 2, + voltage: 2, + power: 2, + frequency: 3, + energy: 0.1, + current: 2, + inclination_x: 10, + inclination_y: 10, + inclination_z: 10 + }; + + } + + dump() { + console.log("----------------------------"); + console.log("previousValues", this.previousValues); + console.log("----------------------------"); + } + + setSender(sender) { + this.sender = sender; + } + + isEmptyObject(obj) { + for (var _ in obj) { + return false; + } + return true; + } + + + sendToTb(data, instance) { + + //not to modify data object, we do deep copy: + let dataCopy = JSON.parse(JSON.stringify(data)); + + let keys = Object.keys(dataCopy); + + if (keys.length == 0) { + if (this.debug) console.log("sendToTb received empty object", dataCopy); + return; + } + + let tbname = keys[0]; + let ts; + + let arrayOfValues = dataCopy[tbname]; + let arrayOfValuesToSend = []; + + for (let i = 0; i < arrayOfValues.length; i++) { + + ts = arrayOfValues[i].ts; + let values = this.prepareValuesForTb(tbname, ts, arrayOfValues[i].values); + + if (!this.isEmptyObject(values)) { + arrayOfValuesToSend.push({ ts: ts, values: values }); + } + + } + + if (arrayOfValuesToSend.length == 0) { + //if(this.debug) console.log("data not sent - empty array"); + return; + } + + this.messageCounter++; + + let dataToTbModified = { + [tbname]: arrayOfValuesToSend + } + + //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); + instance.send(this.index, dataToTbModified); + } + + + getDiffTimestamp(key) { + //TODO set different value for given key!!! + //if(key == "status") this.timeToHoldTbValue = 2*60*60;//2h + return this.timeToHoldTbValue * 1000; + } + + + prepareValuesForTb(tbname, timestamp, values) { + + let keys = Object.keys(values); + + if (keys.includes("lifetime")) this.itIsNodeReadout = true; + + if (!this.previousValues.hasOwnProperty(tbname)) { + this.previousValues[tbname] = {}; + } + + //if(this.debug) console.log("prepareValuesForTb", tbname, timestamp, values); + + for (let i = 0; i < keys.length; i++) { + + let key = keys[i]; + let value = values[key]; + + if (!this.previousValues[tbname].hasOwnProperty(key)) { + this.previousValues[tbname][key] = { ts: timestamp, value: value }; + continue; + } + + // attributeData ==> {voltage: {ts:333333, value:5}} + let attributeData = this.previousValues[tbname][key]; + let attributeToChange = false; + if (key in this.attributeChangeLimit) attributeToChange = true; + let limit = this.attributeChangeLimit[key]; + let timestampDiffToRemoveKey; + + //this will ensure "node statecode" will be sent just once an hour + if (this.itIsNodeReadout && key === "statecode") { + attributeData.value = value; + this.itIsNodeReadout = false; + timestampDiffToRemoveKey = 1 * 60 * 60 * 1000; // 1 hour + } + + if (key === "twilight_sensor" && value > 100) { + attributeData.value = value; + } + + //if edge, master or node version do not change, send just once a day: + if (["edge_fw_version", "master_node_version", "fw_version"].includes(key)) { + timestampDiffToRemoveKey = 24 * 60 * 60 * 1000; + } + + if (attributeData.value === value || attributeToChange && Math.abs(attributeData.value - value) < limit) { + + let diff = timestamp - attributeData.ts; + if (!timestampDiffToRemoveKey) timestampDiffToRemoveKey = this.getDiffTimestamp(key); + + if (diff > timestampDiffToRemoveKey) { + attributeData.ts = Date.now(); + //if(this.debug) console.log(this.sender + ": update ts for key", key, "diff is", diff, "messageCounter", this.messageCounter); + } + else { + delete values[key]; + //if(this.debug) console.log(this.sender + ": delete key", key, "diff is", diff, "messageCounter", this.messageCounter, timestampDiffToRemoveKey); + } + } + else { + attributeData.value = value; + attributeData.ts = timestamp; + } + + } + + return values; + } +} + +module.exports = DataToTbHandler; + diff --git a/RVO46/flow/helper/ErrorToServiceHandler.js b/RVO46/flow/helper/ErrorToServiceHandler.js new file mode 100755 index 0000000..2b27c32 --- /dev/null +++ b/RVO46/flow/helper/ErrorToServiceHandler.js @@ -0,0 +1,91 @@ +const { MD5 } = require('./md5.js'); +const { networkInterfaces } = require('os'); + +class ErrorToServiceHandler { + constructor() { + this.previousValues = {}; + + this.project_id = undefined; + + const nets = networkInterfaces(); + this.ipAddresses = {}; + + for (const name of Object.keys(nets)) { + for (const net of nets[name]) { + // Skip over non-IPv4 and internal (i.e. 127.0.0.1) addresses + if (net.family === 'IPv4' && !net.internal) { + if (!this.ipAddresses[name]) { + this.ipAddresses[name] = []; + } + this.ipAddresses[name].push(net.address); + } + } + } + } + + setProjectId(project_id) { + this.project_id = project_id; + } + + processMessage(message, seconds) { + if (Array.isArray(message)) message = message.join(', '); + + let key = MD5(message); + let ts = Date.now(); + + //keep in memory - default value is 1h + if (seconds === undefined) seconds = 60 * 60; + + if (!this.previousValues.hasOwnProperty(key)) { + this.previousValues[key] = { ts: ts, duration: seconds }; + } + + let diff = (ts - this.previousValues[key].ts); + if (diff < this.previousValues[key].duration * 1000) return false; + + this.previousValues[key].ts = ts; + + return message; + } + + sendMessageToService(message, seconds, message_type) { + + // if error occures too early FLOW.GLOBALS.settings.project_id is still undefined + if (this.project_id === undefined) { + console.log("ErrorToServiceHandler.js: no project_id"); + return; + } + + let f = this.processMessage(message, seconds); + if (f === false) return; + + if (message_type === undefined) message_type = "error_message"; + + let toService = { + id: this.project_id, + ipAddresses: this.ipAddresses + }; + + //js_error || error_message + toService[message_type] = message; + + console.log("ErrorToServiceHandler------------------------>send to service", toService); + + RESTBuilder.make(function(builder) { + builder.method('POST'); + builder.post(toService); + builder.url('http://192.168.252.2:8004/sentmessage'); + + builder.callback(function(err, response, output) { + console.log("process.on error send", err, response, output, toService); + }); + }); + + } +} + +const errorHandler = new ErrorToServiceHandler(); + + +module.exports = errorHandler; +//module.exports = ErrorToServiceHandler; diff --git a/RVO46/flow/helper/db_helper.js b/RVO46/flow/helper/db_helper.js new file mode 100755 index 0000000..40e796c --- /dev/null +++ b/RVO46/flow/helper/db_helper.js @@ -0,0 +1,44 @@ +function promisifyBuilder(builder) +{ + return new Promise((resolve, reject) => { + + try{ + + builder.callback(function(err, response) { + + if(err != null) reject(err); + resolve(response); + }); + + } catch (error) { + reject(error); + } + }) +} + +function makeMapFromDbResult(response, ...keys) +{ + let s = "-"; + let data = {}; + + for(let i = 0; i < response.length; i++) + { + let record = response[i]; + + let k = []; + for(let j = 0; j < keys.length; j++) + { + k.push( record[keys[j]] ); + } + + let key = k.join(s); + data[ key ] = record; + } + + return data; +} + +module.exports = { + promisifyBuilder, + makeMapFromDbResult + } \ No newline at end of file diff --git a/RVO46/flow/helper/logger.js b/RVO46/flow/helper/logger.js new file mode 100755 index 0000000..2585639 --- /dev/null +++ b/RVO46/flow/helper/logger.js @@ -0,0 +1,30 @@ +//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/RVO46/flow/helper/md5.js b/RVO46/flow/helper/md5.js new file mode 100755 index 0000000..d3b0480 --- /dev/null +++ b/RVO46/flow/helper/md5.js @@ -0,0 +1,5 @@ +function MD5(d){var r = M(V(Y(X(d),8*d.length)));return r.toLowerCase()};function M(d){for(var _,m="0123456789ABCDEF",f="",r=0;r>>4&15)+m.charAt(15&_);return f}function X(d){for(var _=Array(d.length>>2),m=0;m<_.length;m++)_[m]=0;for(m=0;m<8*d.length;m+=8)_[m>>5]|=(255&d.charCodeAt(m/8))<>5]>>>m%32&255);return _}function Y(d,_){d[_>>5]|=128<<_%32,d[14+(_+64>>>9<<4)]=_;for(var m=1732584193,f=-271733879,r=-1732584194,i=271733878,n=0;n>16)+(_>>16)+(m>>16)<<16|65535&m}function bit_rol(d,_){return d<<_|d>>>32-_} + +module.exports = { + MD5 +} \ No newline at end of file diff --git a/RVO46/flow/helper/notification_reporter.js b/RVO46/flow/helper/notification_reporter.js new file mode 100755 index 0000000..839c12c --- /dev/null +++ b/RVO46/flow/helper/notification_reporter.js @@ -0,0 +1,121 @@ +//key is device, value = message {} +let sentValues = {}; +let notificationsData = null; +let rvoName; + +//sendNotification("CMD Manager: process cmd", SETTINGS.rvoTbName, "dimming_profile_was_successfully_received_by_node", { node: node }, "", SEND_TO.tb, instance); + +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 +}; + +function getKey(map, val) { + return Object.keys(map).findItem(key => map[key] === val); +} + +//https://stackoverflow.com/questions/41117799/string-interpolation-on-variable +var template = (tpl, args) => tpl.replace(/\${(\w+)}/g, (_, v) => args[v]); + + +function initNotification() { + notificationsData = FLOW.GLOBALS.notificationsData; + rvoName = FLOW.GLOBALS.settings.rvo_name; +} + + +function sendNotification(func, device, key, params, extra, tb_output, instance, saveKey) { + + let storeToSendValues = true; + if (saveKey == undefined) storeToSendValues = false; + + let weight = ""; + let message = {}; + + let notification = notificationsData[key]; + + if (notification) { + weight = notification.weight.toLowerCase(); + + Object.keys(notification).forEach(item => { + if (["en", "sk", "de", "cz", "it", "es"].includes(item)) { + message[item] = rvoName + ": " + template(notification[item], params); + } + }) + } + else { + //console.error("sendNotification: Notifications: undefined key", key, func, notificationsData); + console.error("sendNotification: Notifications: undefined key", key, func); + return false; + } + + //detect invalid err weight + if (getKey(ERRWEIGHT, weight) == undefined) { + console.error("sendNotification: Notifications: undefined weight", weight, key, func); + return false; + } + + if (sentValues.hasOwnProperty(saveKey)) { + if (JSON.stringify(sentValues[saveKey]) == JSON.stringify(message)) { + return false; + } + } + + if (sentValues[saveKey] == undefined) { + if (storeToSendValues) { + //do not send - flow is was started + sentValues[saveKey] = message; + return false; + } + } + + if (storeToSendValues) sentValues[saveKey] = message; + + let content = { + "type": weight, + "status": "new", + "source": { + "func": func, + "component": instance.id, + "component_name": instance.name, + "edge": device + }, + "message": message, + "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 + + return true; + +} + +module.exports = { + sendNotification, + ERRWEIGHT, + initNotification +} + diff --git a/RVO46/flow/helper/register.js b/RVO46/flow/helper/register.js new file mode 100755 index 0000000..fc1d008 --- /dev/null +++ b/RVO46/flow/helper/register.js @@ -0,0 +1,144 @@ +/* +0 - cislo registra / prikaz +1 - recepient - 0 = master, 1 = slave (slave je automaticky group a broadcast) +2 - r/rw - read/write +3- register name - nazov registra / prikazu (len pre info - zobrazenie v aplikacii) + +4,5,6,7, - jednotlive byte-y - nazov byte-u +4-7 - RES. a prazdny string "" sa nezobrazia!!! +*/ + +//124 zaznamov +const registers = [ + ["0","1","R","Status","","",""], + ["1","1","RW","Dimming","R-Channel ","G-Channel","B-Channel ","W - Channel"], + ["2","1","R","Device types","","",".",""], + ["3","1","RW","Group addresses 1-4","Groups Add. 4","Groups Add. 3","Groups Add. 2","Groups Add. 1"], + ["4","1","RW","Group addresses 5-8","Groups Add. 8","Groups Add. 7","Groups Add. 6","Groups Add. 5"], + ["5","1","RW","Serial number (MAC)","","","",""], + ["6","1","RW","Time of dusk","HH","MM","SS","EXTRA"], + ["7","1","RW","Time of dawn","HH","MM","SS","EXTRA"], + ["8","1","RW","Time Schedule settings","TBD","TBD","Movement sensor","Time Schedule"], + ["9","1","RW","TS1 Time point 1","HH","MM","SS","Ext. Device"], + ["10","1","RW","TS1 Time point 1 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["11","1","RW","TS1 Time point 2","HH","MM","SS","Ext. Device"], + ["12","1","RW","TS1 Time point 2 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["13","1","RW","TS1 Time point 3","HH","MM","SS","Ext. Device"], + ["14","1","RW","TS1 Time point 3 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["15","1","RW","TS1 Time point 4","HH","MM","SS","Ext. Device"], + ["16","1","RW","TS1 Time point 4 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["17","1","RW","TS1 Time point 5","HH","MM","SS","Ext. Device"], + ["18","1","RW","TS1 Time point 5 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["19","1","RW","TS1 Time point 6","HH","MM","SS","Ext. Device"], + ["20","1","RW","TS1 Time point 6 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["21","1","RW","TS1 Time point 7","HH","MM","SS","Ext. Device"], + ["22","1","RW","TS1 Time point 7 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["23","1","RW","TS1 Time point 8","HH","MM","SS","Ext. Device"], + ["24","1","RW","TS1 Time point 8 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["25","1","RW","TS1 Time point 9","HH","MM","SS","Ext. Device"], + ["26","1","RW","TS1 Time point 9 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["27","1","RW","TS1 Time point 10","HH","MM","SS","Ext. Device"], + ["28","1","RW","TS1 Time point 10 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["29","1","RW","TS1 Time point 11","HH","MM","SS","Ext. Device"], + ["30","1","RW","TS1 Time point 11 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["31","1","RW","TS1 Time point 12","HH","MM","SS","Ext. Device"], + ["32","1","RW","TS1 Time point 12 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["33","1","RW","TS1 Time point 13","HH","MM","SS","Ext. Device"], + ["34","1","RW","TS1 Time point 13 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["35","1","RW","TS1 Time point 14","HH","MM","SS","Ext. Device"], + ["36","1","RW","TS1 Time point 14 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["37","1","RW","TS1 Time point 15","HH","MM","SS","Ext. Device"], + ["38","1","RW","TS1 Time point 15 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["39","1","RW","TS1 Time point 16","HH","MM","SS","Ext. Device"], + ["40","1","RW","TS1 Time point 16 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["41","1","RW","TS2 Time point 1","HH","MM","SS","Ext. Device"], + ["42","1","RW","TS2 Time point 1 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["43","1","RW","TS2 Time point 2","HH","MM","SS","Ext. Device"], + ["44","1","RW","TS2 Time point 2 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["45","1","RW","TS2 Time point 3","HH","MM","SS","Ext. Device"], + ["46","1","RW","TS2 Time point 3 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["47","1","RW","TS2 Time point 4","HH","MM","SS","Ext. Device"], + ["48","1","RW","TS2 Time point 4 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["49","1","RW","TS2 Time point 5","HH","MM","SS","Ext. Device"], + ["50","1","RW","TS2 Time point 5 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["51","1","RW","TS2 Time point 6","HH","MM","SS","Ext. Device"], + ["52","1","RW","TS2 Time point 6 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["53","1","RW","TS2 Time point 7","HH","MM","SS","Ext. Device"], + ["54","1","RW","TS2 Time point 7 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["55","1","RW","TS2 Time point 8","HH","MM","SS","Ext. Device"], + ["56","1","RW","TS2 Time point 8 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["57","1","RW","TS2 Time point 9","HH","MM","SS","Ext. Device"], + ["58","1","RW","TS2 Time point 9 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["59","1","RW","TS2 Time point 10","HH","MM","SS","Ext. Device"], + ["60","1","RW","TS2 Time point 10 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["61","1","RW","TS2 Time point 11","HH","MM","SS","Ext. Device"], + ["62","1","RW","TS2 Time point 11 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["63","1","RW","TS2 Time point 12","HH","MM","SS","Ext. Device"], + ["64","1","RW","TS2 Time point 12 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["65","1","RW","TS2 Time point 13","HH","MM","SS","Ext. Device"], + ["66","1","RW","TS2 Time point 13 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["67","1","RW","TS2 Time point 14","HH","MM","SS","Ext. Device"], + ["68","1","RW","TS2 Time point 14 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["69","1","RW","TS2 Time point 15","HH","MM","SS","Ext. Device"], + ["70","1","RW","TS2 Time point 15 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["71","1","RW","TS2 Time point 16","HH","MM","SS","Ext. Device"], + ["72","1","RW","TS2 Time point 16 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["73","1","RW","Power meter status","TBD","","",""], + ["74","1","R","Input Voltage","","","",""], + ["75","1","R","Input Current","","","",""], + ["76","1","R","Input Power","","","",""], + ["77","1","R","Cos phi","","","",""], + ["78","1","R","Frequency","","","",""], + ["79","1","RW","Energy","","","",""], + ["80","1","RW","Lifetime","","","",""], + ["81","1","RW","Power on cycles (input)","","","",""], + ["82","1","RW","Power on cycles (relay)","","","",""], + ["83","1","R","Time since last power on","","","",""], + ["84","1","R","Accelerometer data","","","",""], + ["85","1","RW","GPS latitude","pos/neg","deg","min ","sec"], + ["86","1","RW","GPS longitude","pos/neg","deg","min ","sec"], + ["87","1","RW","Actual time","HH","MM","SS","RES."], + ["88","1","RW","Actual date","Day of week","Day","Month","Year"], + ["89","1","R","Production data 1","","","",""], + ["90","1","R","Production data 2","","","",""], + ["91","1","RW","Network ID","NID3","NID2","NID1","NID0"], + ["95","1","RW","Actual Lux level from cabinet","RES.","RES.","HB","LB"], + ["96","1","RW","Threshold lux level","Dusk HB","Dusk LB","Dawn HB","Dawn LB"], + ["97","1","RW","Adjust period","Dusk HB","Dusk LB","Dawn HB","Dawn LB"], + ["98","1","RW","Offset","RES.","RES.","Dusk","Dawn"], + ["99","1","RW","CCT min/max range","max-H","max-L","min-H","min-L"], + ["100","1","RW","DALI interface","Cmd ID","Add","Cmd","Resp"], + ["101","1","RW","Module FW ver","v1","v2","v3","v4"], + ["102","1","RW","Module MAC-H","unused","unused","M1","M2"], + ["103","1","RW","Module MAC-L","M3","M4","M5","M6"], + ["122","1","R","FW update status/control register","Byte3","Byte2","Byte1","Byte0"], + ["123","1","R","FW update - data index","Byte3","Byte2","Byte1","Byte0"], + ["124","1","R","FW update - data","Byte3","Byte2","Byte1","Byte0"], + ["0","0","R","Status","","","",""], + ["1","0","RW","Control register","RES.","RES.","RES.","init mode enable"], + ["2","0","R","Device types","","","",""], + ["3","0","R","Serial number (MAC)","","","",""], + ["4","0","R","Production data 1","","","",""], + ["5","0","R","Production data 2","","","",""], + ["6","0","RW","Network ID","NID3","NID2","NID1","NID0"], + ["7","0","RW","RS232 settings","param.","param.","Baudrate H","Baudrate L"], + ["8","0","R","Accelerometer data","","","",""], + ["9","0","RW","Module FW ver","v1","v2","v3","v4"], + ["10","0","RW","Module MAC-H","unused","unused","M1","M2"], + ["11","0","RW","Module MAC-L","M3","M4","M5","M6"], + ["32","0","RW","FW update status/control register","Byte3","Byte2","Byte1","Byte0"], + ["33","0","RW","FW update - data index","Byte3","Byte2","Byte1","Byte0"], + ["34","0","RW","FW update - data","Byte3","Byte2","Byte1","Byte0"], + ["125","0","RW","Debug Register","Byte3","Byte2","Byte1","Byte0"], + ["126","0","RW","Network Control Register","Byte3","Byte2","Byte1","Byte0"], + ["127","0","R","Network Status Register","Byte3","Byte2","Byte1","Byte0"], + ["128","0","RW","Node XX Serial Number Register","SER3","SER2","SER1","SER0"], + ["256","0","R","Node XX Network Status Register","","","",""] +]; + +let register = {}; + +module.exports = { + registers, + register +} \ No newline at end of file diff --git a/RVO46/flow/helper/serialport_helper.js b/RVO46/flow/helper/serialport_helper.js new file mode 100755 index 0000000..7f5920d --- /dev/null +++ b/RVO46/flow/helper/serialport_helper.js @@ -0,0 +1,99 @@ +const { exec } = require('child_process'); + +function openPort(port) { + return new Promise((resolve, reject) => { + + var callbackError = function(err) { + port.removeListener('error', callbackError); + port.removeListener('open', callbackError); + + reject(err.message); + }; + + var callbackOpen = function(data) { + port.removeListener('error', callbackError); + port.removeListener('open', callbackOpen); + + resolve("port open: ok"); + }; + + port.on('error', callbackError); + port.on('open', callbackOpen); + + port.open(); + + }) +} + +function runSyncExec(command) { + return new Promise((resolve, reject) => { + + exec(command, (error, stdout, stderr) => { + if (error == null) resolve(stdout); + reject(error); + }); + + }) +} + +async function writeData(port, data, readbytes, timeout) { + return new Promise((resolve, reject) => { + + // 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) { + + port.write(Buffer.from(data), function(err) { + if (err) { + reject(err.message); + } + }); + + 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 +} diff --git a/RVO46/flow/helper/suncalc.js b/RVO46/flow/helper/suncalc.js new file mode 100755 index 0000000..c9ca56d --- /dev/null +++ b/RVO46/flow/helper/suncalc.js @@ -0,0 +1,317 @@ +/* + (c) 2011-2015, Vladimir Agafonkin + SunCalc is a JavaScript library for calculating sun/moon position and light phases. + https://github.com/mourner/suncalc +*/ + +(function () { 'use strict'; + +// shortcuts for easier to read formulas + +var PI = Math.PI, + sin = Math.sin, + cos = Math.cos, + tan = Math.tan, + asin = Math.asin, + atan = Math.atan2, + acos = Math.acos, + rad = PI / 180; + +// sun calculations are based on http://aa.quae.nl/en/reken/zonpositie.html formulas + + +// date/time constants and conversions + +var dayMs = 1000 * 60 * 60 * 24, + J1970 = 2440588, + J2000 = 2451545; + +function toJulian(date) { return date.valueOf() / dayMs - 0.5 + J1970; } +function fromJulian(j) { return new Date((j + 0.5 - J1970) * dayMs); } +function toDays(date) { return toJulian(date) - J2000; } + + +// general calculations for position + +var e = rad * 23.4397; // obliquity of the Earth + +function rightAscension(l, b) { return atan(sin(l) * cos(e) - tan(b) * sin(e), cos(l)); } +function declination(l, b) { return asin(sin(b) * cos(e) + cos(b) * sin(e) * sin(l)); } + +function azimuth(H, phi, dec) { return atan(sin(H), cos(H) * sin(phi) - tan(dec) * cos(phi)); } +function altitude(H, phi, dec) { return asin(sin(phi) * sin(dec) + cos(phi) * cos(dec) * cos(H)); } + +function siderealTime(d, lw) { return rad * (280.16 + 360.9856235 * d) - lw; } + +function astroRefraction(h) { + if (h < 0) // the following formula works for positive altitudes only. + h = 0; // if h = -0.08901179 a div/0 would occur. + + // formula 16.4 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + // 1.02 / tan(h + 10.26 / (h + 5.10)) h in degrees, result in arc minutes -> converted to rad: + return 0.0002967 / Math.tan(h + 0.00312536 / (h + 0.08901179)); +} + +// general sun calculations + +function solarMeanAnomaly(d) { return rad * (357.5291 + 0.98560028 * d); } + +function eclipticLongitude(M) { + + var C = rad * (1.9148 * sin(M) + 0.02 * sin(2 * M) + 0.0003 * sin(3 * M)), // equation of center + P = rad * 102.9372; // perihelion of the Earth + + return M + C + P + PI; +} + +function sunCoords(d) { + + var M = solarMeanAnomaly(d), + L = eclipticLongitude(M); + + return { + dec: declination(L, 0), + ra: rightAscension(L, 0) + }; +} + + +var SunCalc = {}; + + +// calculates sun position for a given date and latitude/longitude + +SunCalc.getPosition = function (date, lat, lng) { + + var lw = rad * -lng, + phi = rad * lat, + d = toDays(date), + + c = sunCoords(d), + H = siderealTime(d, lw) - c.ra; + + return { + azimuth: azimuth(H, phi, c.dec), + altitude: altitude(H, phi, c.dec) + }; +}; + + +// sun times configuration (angle, morning name, evening name) + +var times = SunCalc.times = [ + [-0.833, 'sunrise', 'sunset' ], + [ -0.3, 'sunriseEnd', 'sunsetStart' ], + [ -6, 'dawn', 'dusk' ], + [ -12, 'nauticalDawn', 'nauticalDusk'], + [ -18, 'nightEnd', 'night' ], + [ 6, 'goldenHourEnd', 'goldenHour' ] +]; + +// adds a custom time to the times config + +SunCalc.addTime = function (angle, riseName, setName) { + times.push([angle, riseName, setName]); +}; + + +// calculations for sun times + +var J0 = 0.0009; + +function julianCycle(d, lw) { return Math.round(d - J0 - lw / (2 * PI)); } + +function approxTransit(Ht, lw, n) { return J0 + (Ht + lw) / (2 * PI) + n; } +function solarTransitJ(ds, M, L) { return J2000 + ds + 0.0053 * sin(M) - 0.0069 * sin(2 * L); } + +function hourAngle(h, phi, d) { return acos((sin(h) - sin(phi) * sin(d)) / (cos(phi) * cos(d))); } +function observerAngle(height) { return -2.076 * Math.sqrt(height) / 60; } + +// returns set time for the given sun altitude +function getSetJ(h, lw, phi, dec, n, M, L) { + + var w = hourAngle(h, phi, dec), + a = approxTransit(w, lw, n); + return solarTransitJ(a, M, L); +} + + +// calculates sun times for a given date, latitude/longitude, and, optionally, +// the observer height (in meters) relative to the horizon + +SunCalc.getTimes = function (date, lat, lng, height) { + + height = height || 0; + + var lw = rad * -lng, + phi = rad * lat, + + dh = observerAngle(height), + + d = toDays(date), + n = julianCycle(d, lw), + ds = approxTransit(0, lw, n), + + M = solarMeanAnomaly(ds), + L = eclipticLongitude(M), + dec = declination(L, 0), + + Jnoon = solarTransitJ(ds, M, L), + + i, len, time, h0, Jset, Jrise; + + + var result = { + solarNoon: fromJulian(Jnoon), + nadir: fromJulian(Jnoon - 0.5) + }; + + for (i = 0, len = times.length; i < len; i += 1) { + time = times[i]; + h0 = (time[0] + dh) * rad; + + Jset = getSetJ(h0, lw, phi, dec, n, M, L); + Jrise = Jnoon - (Jset - Jnoon); + + result[time[1]] = fromJulian(Jrise); + result[time[2]] = fromJulian(Jset); + } + + return result; +}; + + +// moon calculations, based on http://aa.quae.nl/en/reken/hemelpositie.html formulas + +function moonCoords(d) { // geocentric ecliptic coordinates of the moon + + var L = rad * (218.316 + 13.176396 * d), // ecliptic longitude + M = rad * (134.963 + 13.064993 * d), // mean anomaly + F = rad * (93.272 + 13.229350 * d), // mean distance + + l = L + rad * 6.289 * sin(M), // longitude + b = rad * 5.128 * sin(F), // latitude + dt = 385001 - 20905 * cos(M); // distance to the moon in km + + return { + ra: rightAscension(l, b), + dec: declination(l, b), + dist: dt + }; +} + +SunCalc.getMoonPosition = function (date, lat, lng) { + + var lw = rad * -lng, + phi = rad * lat, + d = toDays(date), + + c = moonCoords(d), + H = siderealTime(d, lw) - c.ra, + h = altitude(H, phi, c.dec), + // formula 14.1 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + pa = atan(sin(H), tan(phi) * cos(c.dec) - sin(c.dec) * cos(H)); + + h = h + astroRefraction(h); // altitude correction for refraction + + return { + azimuth: azimuth(H, phi, c.dec), + altitude: h, + distance: c.dist, + parallacticAngle: pa + }; +}; + + +// calculations for illumination parameters of the moon, +// based on http://idlastro.gsfc.nasa.gov/ftp/pro/astro/mphase.pro formulas and +// Chapter 48 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + +SunCalc.getMoonIllumination = function (date) { + + var d = toDays(date || new Date()), + s = sunCoords(d), + m = moonCoords(d), + + sdist = 149598000, // distance from Earth to Sun in km + + phi = acos(sin(s.dec) * sin(m.dec) + cos(s.dec) * cos(m.dec) * cos(s.ra - m.ra)), + inc = atan(sdist * sin(phi), m.dist - sdist * cos(phi)), + angle = atan(cos(s.dec) * sin(s.ra - m.ra), sin(s.dec) * cos(m.dec) - + cos(s.dec) * sin(m.dec) * cos(s.ra - m.ra)); + + return { + fraction: (1 + cos(inc)) / 2, + phase: 0.5 + 0.5 * inc * (angle < 0 ? -1 : 1) / Math.PI, + angle: angle + }; +}; + + +function hoursLater(date, h) { + return new Date(date.valueOf() + h * dayMs / 24); +} + +// calculations for moon rise/set times are based on http://www.stargazing.net/kepler/moonrise.html article + +SunCalc.getMoonTimes = function (date, lat, lng, inUTC) { + var t = new Date(date); + if (inUTC) t.setUTCHours(0, 0, 0, 0); + else t.setHours(0, 0, 0, 0); + + var hc = 0.133 * rad, + h0 = SunCalc.getMoonPosition(t, lat, lng).altitude - hc, + h1, h2, rise, set, a, b, xe, ye, d, roots, x1, x2, dx; + + // go in 2-hour chunks, each time seeing if a 3-point quadratic curve crosses zero (which means rise or set) + for (var i = 1; i <= 24; i += 2) { + h1 = SunCalc.getMoonPosition(hoursLater(t, i), lat, lng).altitude - hc; + h2 = SunCalc.getMoonPosition(hoursLater(t, i + 1), lat, lng).altitude - hc; + + a = (h0 + h2) / 2 - h1; + b = (h2 - h0) / 2; + xe = -b / (2 * a); + ye = (a * xe + b) * xe + h1; + d = b * b - 4 * a * h1; + roots = 0; + + if (d >= 0) { + dx = Math.sqrt(d) / (Math.abs(a) * 2); + x1 = xe - dx; + x2 = xe + dx; + if (Math.abs(x1) <= 1) roots++; + if (Math.abs(x2) <= 1) roots++; + if (x1 < -1) x1 = x2; + } + + if (roots === 1) { + if (h0 < 0) rise = i + x1; + else set = i + x1; + + } else if (roots === 2) { + rise = i + (ye < 0 ? x2 : x1); + set = i + (ye < 0 ? x1 : x2); + } + + if (rise && set) break; + + h0 = h2; + } + + var result = {}; + + if (rise) result.rise = hoursLater(t, rise); + if (set) result.set = hoursLater(t, set); + + if (!rise && !set) result[ye > 0 ? 'alwaysUp' : 'alwaysDown'] = true; + + return result; +}; + + +// export as Node module / AMD module / browser variable +if (typeof exports === 'object' && typeof module !== 'undefined') module.exports = SunCalc; +else if (typeof define === 'function' && define.amd) define(SunCalc); +else window.SunCalc = SunCalc; + +}()); diff --git a/RVO46/flow/helper/utils.js b/RVO46/flow/helper/utils.js new file mode 100755 index 0000000..dbffe45 --- /dev/null +++ b/RVO46/flow/helper/utils.js @@ -0,0 +1,161 @@ +const fs = require('fs').promises; + +function bytesToInt(bytes, numberOfBytes) { + let buffer = []; + if (Array.isArray(bytes)) { + buffer = bytes.slice(0); + if (numberOfBytes != undefined) { + buffer = bytes.slice(bytes.length - numberOfBytes); + } + } + else buffer.push(bytes); + + let result = 0; + for (let i = 0; i < buffer.length; i++) { + result = (result << 8) | buffer[i]; + } + + return result >>> 0; //ensure it's an unsigned 32-bit number +} + +function resizeArray(arr, newSize, defaultValue) { + while (newSize > arr.length) + arr.push(defaultValue); + arr.length = newSize; +} + +longToByteArray = function(/*long*/long) { + // we want to represent the input as a 8-bytes array + var byteArray = [0, 0, 0, 0, 0, 0, 0, 0]; + + for (var index = 0; index < byteArray.length; index++) { + var byte = long & 0xff; + byteArray[index] = byte; + long = (long - byte) / 256; + } + + return byteArray; +}; + +function addDays(date, days) { + var result = new Date(date); + result.setDate(result.getDate() + days); + return result; +} + +/* +sleep(2000).then(() => { + // Do something after the sleep! + + +}); +*/ + +function sleep(time) { + return new Promise((resolve) => setTimeout(resolve, time)); +} + +function isEmptyObject(obj) { + for (var name in obj) { + return false; + } + return true; +} + +function emptyJsObject(jsObject) { + Object.keys(jsObject).forEach(key => delete jsObject[key]); +} + +function convertUTCDateToLocalDate(date) { + var newDate = new Date(date); + newDate.setMinutes(date.getMinutes() + date.getTimezoneOffset()); + return newDate; +} + +function addZeroBefore(n) { + return (n < 10 ? '0' : '') + n; +} + + +/** + * Asynchronously writes data to a file. + * + * @param {string} filePath The path to the file. + * @param {string} data The data to write to the file. + * @param {boolean} [append=false] If true, appends the data to the file. If false, it overwrites the file. + */ +async function writeToFile(filePath, data, append = false) { + if (typeof data !== 'string') data = JSON.stringify(data, null, 2); + try { + if (append) { + // Append the data to the end of the file. This is the simplest way to append. + await fs.appendFile(filePath, data, 'utf8'); + console.log(`Successfully appended data to ${filePath} using fs.appendFile.`); + } else { + // Overwrite the file with the new data. + await fs.writeFile(filePath, data, 'utf8'); + console.log(`Successfully wrote (overwrote) data to ${filePath} using fs.writeFile.`); + } + } catch (error) { + console.error(`Error writing to file ${filePath}:`, error); + } +} + + + /** + * Checks if an item is present in an array and adds it if it's not. + * * @param {Array} arr The array to check. + * @param {*} item The item to add. + * @returns {Array} The modified array. + */ +const addToArrayIfUnique = (arr, item) => { + if (!arr.includes(item)) { + arr.push(item); + } + return arr; +}; + + +var convertBase = function() { + + function convertBase(baseFrom, baseTo) { + return function(num) { + return parseInt(num, baseFrom).toString(baseTo); + + }; + } + + // binary to decimal + convertBase.bin2dec = convertBase(2, 10); + + // binary to hexadecimal + convertBase.bin2hex = convertBase(2, 16); + + // decimal to binary + convertBase.dec2bin = convertBase(10, 2); + + // decimal to hexadecimal + convertBase.dec2hex = convertBase(10, 16); + + // hexadecimal to binary + convertBase.hex2bin = convertBase(16, 2); + + // hexadecimal to decimal + convertBase.hex2dec = convertBase(16, 10); + + return convertBase; +}(); + +module.exports = { + bytesToInt, + longToByteArray, + addDays, + addZeroBefore, + resizeArray, + isEmptyObject, + emptyJsObject, + sleep, + convertUTCDateToLocalDate, + writeToFile, + addToArrayIfUnique +} diff --git a/RVO46/flow/httprequest.js b/RVO46/flow/httprequest.js new file mode 100755 index 0000000..469c8cb --- /dev/null +++ b/RVO46/flow/httprequest.js @@ -0,0 +1,137 @@ +exports.id = 'httprequest'; +exports.title = 'HTTP Request'; +exports.group = 'HTTP'; +exports.color = '#5D9CEC'; +exports.input = true; +exports.version = '2.0.1'; +exports.output = 1; +exports.author = 'Peter Širka'; +exports.icon = 'cloud-upload'; + +exports.html = `
+
@(URL address)
+
+
+
@(HTTP method)
+
+
+
@(Serialization)
+
+
+
@(Download the content in chunks)
+
@(Keep persistent cookies)
+
@(Disable DNS cache)
+
@(Keep alive connection)
+
+
+
+
@(Custom headers)
+
@(Cookies)
+
+
+
+ +
+
+
+
@(User)
+
+
+
@(Password)
+
+
+
+
+
`; + +exports.readme = `# Request + +This component creates a request with received data. + +__Response:__ +\`\`\`javascript +{ + data: String, + headers: Object, + status: Number, + host: String +} +\`\`\` + +__Dynamic arguments__: +Are performed via FlowData repository and can be used for URL address or for custom headers/cookies/auth. Use \`repository\` component for creating of dynamic arguments. Dynamic values are replaced in the form \`{key}\`: + +- url address e.g. \`https://.../{key}/\` +- headers values e.g. \`{token}\` +- cookies values e.g. \`{token}\``; + +exports.install = function(instance) { + + var can = false; + var flags = null; + var cookies2 = null; + + instance.on('data', function(response) { + can && instance.custom.send(response); + }); + + instance.custom.send = function(response) { + var options = instance.options; + + var headers = null; + var cookies = null; + + options.headers && Object.keys(options.headers).forEach(function(key) { + !headers && (headers = {}); + headers[key] = response.arg(options.headers[key]); + }); + + if (options.username && options.userpassword) { + !headers && (headers = {}); + headers['Authorization'] = 'Basic ' + U.createBuffer(response.arg(options.username + ':' + options.userpassword)).toString('base64'); + } + + options.cookies && Object.keys(options.cookies).forEach(function(key) { + !cookies && (cookies = {}); + cookies[key] = response.arg(options.cookies[key]); + }); + + if (options.chunks) { + U.download(response.arg(options.url), flags, options.stringify === 'none' ? null : response.data, function(err, response) { + response.on('data', (chunks) => instance.send2(chunks)); + }, cookies || cookies2, headers); + } else { + U.request(response.arg(options.url), flags, options.stringify === 'none' ? null : response.data, 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) + instance.error(err, response); + }, cookies || cookies2, headers); + } + }; + + instance.reconfigure = function() { + var options = instance.options; + can = options.url && options.url && options.method && options.stringify ? true : false; + instance.status(can ? '' : 'Not configured', can ? undefined : 'red'); + + if (!can) + return; + + flags = []; + flags.push(options.method.toLowerCase()); + options.stringify === 'json' && flags.push('json'); + options.stringify === 'raw' && flags.push('raw'); + options.keepalive && flags.push('keepalive'); + !options.nodns && flags.push('dnscache'); + if (options.persistentcookies) { + flags.push('cookies'); + cookies2 = {}; + } else + cookies2 = null; + }; + + instance.on('options', instance.reconfigure); + instance.reconfigure(); +}; \ No newline at end of file diff --git a/RVO46/flow/httpresponse.js b/RVO46/flow/httpresponse.js new file mode 100755 index 0000000..160a3bb --- /dev/null +++ b/RVO46/flow/httpresponse.js @@ -0,0 +1,76 @@ +exports.id = 'httpresponse'; +exports.title = 'HTTP Response'; +exports.group = 'HTTP'; +exports.color = '#5D9CEC'; +exports.icon = 'arrow-right'; +exports.input = true; +exports.output = ['#666D76']; +exports.version = '2.0.0'; +exports.author = 'Martin Smola'; +exports.readme = `# HTTP response + +HTTP response will respond with data recieved using data-type set in Settings form or plain text if not set. Output is the message duration \`Number\` in seconds.`; + +exports.html = `
+
@(Response data-type)
+
JSON is by default.
+
`; + +exports.install = function(instance) { + + var dursum = 0; + var durcount = 0; + + instance.on('data', function(flowdata) { + + var ctrl = flowdata.repository.controller; + var data = flowdata.data; + + if (!ctrl) { + instance.throw('No controller to use for response!'); + return; + } + + durcount++; + dursum += ((new Date() - flowdata.begin) / 1000).floor(2); + setTimeout2(instance.id, instance.custom.duration, 500, 10); + + ctrl.$flowdata = flowdata; + + var datatype = instance.options.datatype || 'json'; + if (datatype === 'emptyresponse') + return ctrl.plain(''); + + if (datatype !== 'json' && typeof(data) !== 'string') { + instance.throw('Incorect type of data, expected string, got ' + typeof(data)); + ctrl.plain(data == null ? '' : data.toString()); + return; + } + + switch(datatype) { + case 'html': + ctrl.content(data, 'text/html'); + break; + case 'plain': + ctrl.plain(data); + break; + case 'xml': + ctrl.content(data, 'text/xml'); + break; + default: + ctrl.json(data); + break; + } + }); + + instance.on('service', function() { + dursum = 0; + durcount = 0; + }); + + instance.custom.duration = function() { + var avg = (dursum / durcount).floor(2); + instance.status(avg + ' sec.'); + instance.send2(0, avg); + }; +}; diff --git a/RVO46/flow/httproute.js b/RVO46/flow/httproute.js new file mode 100755 index 0000000..583a19d --- /dev/null +++ b/RVO46/flow/httproute.js @@ -0,0 +1,326 @@ +exports.id = 'httproute'; +exports.title = 'HTTP Route'; +exports.group = 'HTTP'; +exports.color = '#5D9CEC'; +exports.icon = 'globe'; +exports.input = false; +exports.output = ['#6CAC5A', '#37BC9B']; +exports.version = '1.2.3'; +exports.author = 'Martin Smola'; +exports.cloning = false; +exports.options = { method: 'GET', url: '', size: 5, cacheexpire: '5 minutes', cachepolicy: 0, timeout: 5 }; +exports.dateupdated = '2021-01-21 18:30d'; +exports.readme = `# HTTP route + +__Outputs__: +- first output: raw data (cache is empty or is disabled) +- second output: cached data + +If one of the outputs is disabled then automatic responce with code "503 service unavailable" is sent. + +When a request comes in bellow object is available at \`flowdata.data\`: + +\`\`\`javascript +{ + params: { id: '1' }, // params for dynamic routes, e.g. /test/{id} + query: { msg: 'Hello' }, // parsed query string, e.g. /test/1?msg=Hello + body: { test: 'OK' }, // object if json requests otherwise string + headers: {}, // headers data + session: {}, // session data + user: {}, // user data + files: [], // uploaded files + url: '/users/', // a relative URL address + referrer: '/', // referrer + mobile: false, // determines mobile device + robot: false, // determines search robots/crawlsers + language: 'en' // determines language +} +\`\`\` + +See [documentation for flags](https://docs.totaljs.com/latest/en.html#api~HttpRouteOptionsFlags~unauthorize). These method flags are set automatically e.g. \`get, post, put, patch or delete\` + +--- + +\`id:ROUTE_ID\` flag cannot be used since it's already used by this component internally`; + +exports.html = `
+
+ +
+ +
+
+
@(HTTP method)
+
+
+
@(URL address)
+
+
+
+
+
@(Additional flags)
+
@(Separate flags by comma e.g. json, authorize)
+
+
+
@(Max. request size)
+
@(In kB kilobytes)
+
+
+
@(Timeout)
+
@(In seconds.)
+
+
+
+
+
+
@(Automatically respond with 200 OK?)
+
@(If not checked you need to use HTTP response component to respond to the request.)
+
+
@(Custom headers)
+
@(Cookies)
+
+
+
+
+
+
@(Cache policy)
+
@(User instance must contain id property.)
+
+
+
@(Expiration)
+
@(E.g. 5 minutes)
+
+
+
+`; + +exports.install = function(instance) { + + var route; + + var uninstall = function(id) { + if (F.is4) { + route && route.remove(); + route = null; + } else + UNINSTALL('route', id); + }; + + instance.custom.emptyresponse = function(self) { + self.plain(); + }; + + instance.reconfigure = function() { + + var options = instance.options; + + if (!options.url) { + instance.status('Not configured', 'red'); + return; + } + + if (typeof(options.flags) === 'string') + options.flags = options.flags.split(',').trim(); + + uninstall('id:' + instance.id); + + var flags = options.flags || []; + + flags.push('id:' + instance.id); + + if (!F.is4) + flags.push(options.method.toLowerCase()); + + options.timeout && flags.push(options.timeout * 1000); + + // Make unique values + flags = flags.filter(function(v, i, a) { + if(F.is4 && v.toString().toLowerCase() === options.method.toLowerCase()) + return false; // remove method + return a.indexOf(v) === i; + }); + + options.flags = flags; + var handler = function() { + + if (instance.paused || (instance.isDisabled && (instance.isDisabled('output', 0) || instance.isDisabled('output', 1)))) { + instance.status('503 Service Unavailable'); + this.status = 503; + this.json(); + return; + } + + var key; + var self = this; + + if (instance.options.emptyresponse) { + instance.status('200 OK'); + setTimeout(instance.custom.emptyresponse, 100, self); + + if (instance.hasConnection(0)) { + var data = instance.make({ + query: self.query, + body: self.body, + session: self.session, + user: self.user, + files: self.files, + headers: self.req.headers, + url: self.url, + params: self.params + }); + instance.send2(0, data); + } + + return; + } + + switch (instance.options.cachepolicy) { + case 1: // URL + key = 'rro' + instance.id + self.url.hash(); + break; + case 2: // URL + query + case 3: // URL + query + user + key = self.url; + var keys = Object.keys(self.query); + keys.sort(); + for (var i = 0, length = keys.length; i < length; i++) + key += keys[i] + self.query[keys[i]] + '&'; + if (instance.options.cachepolicy === 3 && self.user) + key += 'iduser' + self.user.id; + key = 'rro' + instance.id + key.hash(); + break; + } + + if (key && F.cache.get2(key)) { + var data = instance.make(F.cache.get2(key)); + data.repository.controller = self; + instance.send2(1, data); + } else { + + var data = instance.make({ + query: self.query, + body: self.body, + session: self.session, + user: self.user, + files: self.files, + headers: self.req.headers, + url: self.url, + params: self.params, + mobile: self.mobile, + robot: self.robot, + referrer: self.referrer, + language: self.language + }); + + data.repository.controller = self; + instance.send2(0, data); + key && FINISHED(self.res, () => F.cache.set(key, self.$flowdata.data, instance.options.cacheexpire)); + } + }; + + if (F.is4) + route = ROUTE(options.method.toUpperCase() + ' ' + options.url, handler, flags, options.size || 5); + else + F.route(options.url, handler, flags, options.size || 5); + + instance.status('Listening', 'green'); + }; + + instance.reconfigure(); + instance.on('options', instance.reconfigure); + instance.on('close', function(){ + uninstall('id:' + instance.id); + }); +}; + +// check url exists +FLOW.trigger('httproutecheckurl', function(next, data) { + var url = data.url; + var method = data.method; + if (url[url.length - 1] !== '/') + url += '/'; + var exists = F.routes.web.findItem(r => r.urlraw === url && r.method === method); + next(exists != null); +}); + +exports.uninstall = function() { + FLOW.trigger('httproutecheckurl', null); +}; diff --git a/RVO46/flow/infosender.js b/RVO46/flow/infosender.js new file mode 100755 index 0000000..587724f --- /dev/null +++ b/RVO46/flow/infosender.js @@ -0,0 +1,81 @@ +exports.id = 'infosender'; +exports.title = 'Info sender'; +exports.version = '1.0.0'; +exports.group = 'Worksys'; +exports.color = '#2134B0'; +exports.input = 2; +exports.output = 1 +exports.icon = 'bolt'; + +const { networkInterfaces } = require('os'); + +exports.html = `
+
+
+
CSV Import
+
+
+
`; + +exports.readme = `# send all data to projects.worksys.io, required to monitor status of controller(unipi)`; + +exports.install = function(instance) { + + let id; + let allValues = {}; + let sendAllValuesInterval; + let configured = false; + + let now = new Date(); + console.log(exports.title, "INSTALLED", now.toLocaleString("sk-SK")); + + const nets = networkInterfaces(); + let ipAddresses = Object.create(null); // Or just '{}', an empty object + + for (const name of Object.keys(nets)) { + for (const net of nets[name]) { + // Skip over non-IPv4 and internal (i.e. 127.0.0.1) addresses + if (net.family === 'IPv4' && !net.internal) { + if (!ipAddresses[name]) { + ipAddresses[name] = []; + } + ipAddresses[name].push(net.address); + } + } + } + + function sendValues() { + if (!configured) return; + + if (Object.keys(allValues).length > 0) { + let dataToSend = { ...allValues }; + dataToSend.id = id; + dataToSend.ipAddresses = ipAddresses; + + instance.send(0, dataToSend); + + allValues = {}; + } + } + + instance.on("close", () => { + clearInterval(sendAllValuesInterval); + }) + + instance.on("0", _ => { + id = FLOW.GLOBALS.settings.project_id; + if (id) configured = true; + else console.log(exports.title, "InfoSender: Unable to send data, no id"); + }) + + instance.on("1", flowdata => { + allValues = { ...allValues, ...flowdata.data }; + //console.log("DATA RECEIVED", flowdata.data); + }) + + sendAllValuesInterval = setInterval(() => { + sendValues(); + }, 60000 * 3); + +} + diff --git a/RVO46/flow/modbus_reader.js b/RVO46/flow/modbus_reader.js new file mode 100755 index 0000000..d6d9dad --- /dev/null +++ b/RVO46/flow/modbus_reader.js @@ -0,0 +1,346 @@ +exports.id = 'modbus_reader'; +exports.title = 'Modbus reader'; +exports.version = '2.0.0'; +exports.group = 'Worksys'; +exports.color = '#2134B0'; +exports.input = 1; +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; +//number of phases inRVO +let phases; +//phases where voltage is 0 (set) +let noVoltage; +let energyToSwitchLamps; + +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.phases = this.buildPhases(); + + this.startSocket(); + } + + buildPhases = () => { + let a = []; + for (let i = 1; i <= phases; i++) { + a.push(`Phase_${i}_voltage`) + } + return a; + } + + startSocket = () => { + + let obj = this; + + if (this.socket) { + this.socket.removeAllListeners(); + this.socket = null; + } + + 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('Modbus_reader: Socket connection error', e); //'ECONNREFUSED' or 'ECONNRESET' ?? + }); + + this.socket.on('close', function() { + console.log('Modbus_reader: Socket connection closed - Waiting 10 seconds before connecting 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 we just start to loop devices from the beginning, or there is just 1 device in config, we wait whole timeoutInterval + if (this.indexInDeviceConfig == 0 || deviceConfig.length === 1) 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 (this.phases.includes(singleValue)) { + let l = singleValue.split("_"); + let phase = parseInt(l[1]); + + // console.log(values[singleValue], tbName); + + if (values[singleValue] == 0) { + noVoltage.add(phase); + sendNotification("modbus_reader: checkNullVoltage", tbName, "no_voltage_on_phase", { phase: phase }, "", SEND_TO.tb, instance, "voltage" + phase); + // console.log('no voltage') + } + else { + noVoltage.delete(phase); + // console.log('voltage detected') + sendNotification("modbus_reader: checkNullVoltage", tbName, "voltage_on_phase_restored", { phase: phase }, "", SEND_TO.tb, instance, "voltage" + phase); + } + } + }) + } + + /** + * function sends notification to slack and to tb, if EM total_power value changes more than numberOfNodes*15. This should show, that RVO lamps has been switched on or off + */ + lampSwitchNotification = (values) => { + + if (!values.hasOwnProperty("total_power")) return; + + const actualTotalPower = values.total_power; + + if (actualTotalPower > energyToSwitchLamps && 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 <= energyToSwitchLamps && 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; + } + + function main() { + + phases = FLOW.GLOBALS.settings.phases; + tbName = FLOW.GLOBALS.settings.rvoTbName; + noVoltage = FLOW.GLOBALS.settings.no_voltage; + energyToSwitchLamps = FLOW.GLOBALS.settings.energy_to_switch_lamps / 2.5; //half value is enought to show if lamps are turned on or off + if (deviceConfig.length) mainSocket = new SocketWithClients(); + else console.log("Modbus_reader: no modbus device in configuration"); + + // this notification is to show, that flow (unipi) has been restarted + sendNotification("modbus_reader", tbName, "flow_restart", {}, "", SEND_TO.slack, instance); + } + + instance.on("0", function(_) { + main(); + }) + +} + diff --git a/RVO46/flow/monitorconsumption.js b/RVO46/flow/monitorconsumption.js new file mode 100755 index 0000000..64cc58e --- /dev/null +++ b/RVO46/flow/monitorconsumption.js @@ -0,0 +1,156 @@ +exports.id = 'monitorconsumption'; +exports.title = 'Consumption'; +exports.version = '1.0.0'; +exports.author = 'Peter Širka'; +exports.group = 'Monitoring'; +exports.color = '#967ADC'; +exports.input = 0; +exports.output = 1; +exports.icon = 'bug'; +exports.options = { interval: 5000, enabled: true, monitorconsumption: true, monitorsize: true, monitorconnections: true, monitorfiles: true }; +exports.click = true; +exports.readme = `# Consumption monitoring + +This component measure CPU and memory consumption, open files and open connections of this application. It uses these Linux commands: \`ps\`, \`lsof\`, \`netstat\` and \`df\`. + +__Data Example__: + +\`\`\`javascript +{ + cpu: 0, // percentage + memory: 4096, // in bytes + size: 34303, // directory size in bytes + files: 34, // count of open files + connections: 343, // count of connections + uptime: '1-12:34:00' +} +\`\`\``; + +exports.html = `
+
+
+
@(Interval in milliseconds)
+
+
+
+
Monitor: Consumption + uptime
+
Monitor: Count of open files
+
Monitor: Count of open connections
+
Monitor: Directory size
+
`; + +exports.install = function(instance) { + + var current = { cpu: 0, memory: 0, files: 0, connections: 0, size: 0, uptime: '', counter: 0 }; + var tproc = null; + var Exec = require('child_process').exec; + var reg_empty = /\s{2,}/g; + var reg_appdisksize = /^[\d.,]+/; + + instance.custom.run = function() { + + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + + var arr = []; + + // Get CPU and Memory consumption + instance.options.monitorconsumption && arr.push(function(next) { + Exec('ps -p {0} -o %cpu,rss,etime'.format(process.pid), function(err, response) { + + if (err) { + instance.throw(err); + } else { + var line = response.split('\n')[1]; + line = line.trim().replace(reg_empty, ' ').split(' '); + var cpu = line[0].parseFloat(); + current.cpu = cpu.floor(1); + current.memory = line[1].parseInt2() * 1024; // kB to bytes + current.uptime = line[2]; + } + + next(); + }); + }); + + // Get count of open files + instance.options.monitorfiles && arr.push(function(next) { + Exec('lsof -a -p {0} | wc -l'.format(process.pid), function(err, response) { + if (err) + instance.throw(err); + else + current.files = response.trim().parseInt2(); + next(); + }); + }); + + // Get count of opened network connections + instance.options.monitorconnections && arr.push(function(next) { + Exec('netstat -an | grep :{0} | wc -l'.format(F.port), function(err, response) { + if (err) { + instance.throw(err); + } else { + current.connections = response.trim().parseInt2() - 1; + if (current.connections < 0) + current.connections = 0; + } + next(); + }); + }); + + // Get directory size + instance.options.monitorsize && current.counter % 5 !== 0 && arr.push(function(next) { + Exec('du -hsb ' + process.cwd(), function(err, response) { + if (err) { + instance.throw(err); + } else { + var match = response.trim().match(reg_appdisksize); + match && (current.size = match.toString().trim().parseInt2()); + } + next(); + }); + }); + + arr.async(function() { + + tproc && clearTimeout(tproc); + + if (instance.options.enabled) { + tproc = setTimeout(instance.custom.run, instance.options.interval); + instance.send2(current); + } + + instance.custom.status(); + current.counter++; + }); + }; + + instance.custom.status = function() { + if (instance.options.enabled) + instance.status('{0}% / {1}'.format(current.cpu, current.memory.filesize())); + else + instance.status('Disabled', 'red'); + }; + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + + if (instance.options.enabled) { + current.counter = 0; + instance.custom.run(); + } + + }); + + instance.on('close', function() { + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + }); + + setTimeout(instance.custom.run, 1000); +}; \ No newline at end of file diff --git a/RVO46/flow/monitordisk.js b/RVO46/flow/monitordisk.js new file mode 100755 index 0000000..f4fdaa0 --- /dev/null +++ b/RVO46/flow/monitordisk.js @@ -0,0 +1,96 @@ +exports.id = 'monitordisk'; +exports.title = 'Disk'; +exports.version = '1.0.0'; +exports.author = 'Peter Širka'; +exports.group = 'Monitoring'; +exports.color = '#F6BB42'; +exports.output = 1; +exports.icon = 'hdd-o'; +exports.click = true; +exports.options = { interval: 8000, path: '/', enabled: true }; +exports.readme = `# Disk monitoring + +This component monitors disk \`bytes\` consumption in Linux systems. It uses \`df\` command. + +__Data Example__: + +\`\`\`javascript +{ + total: 474549649408, + used: 39125245952, + free: 411294994432 +} +\`\`\``; + +exports.html = `
+
+
+
@(Interval in milliseconds)
+
+
+
@(Path)
+
+
+
`; + +exports.install = function(instance) { + + var current = { total: 0, used: 0, free: 0, path: '', type: '', percentUsed: 0 }; + var tproc = null; + + instance.custom.run = function() { + + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + + if (!instance.options.enabled) + return; + + require('child_process').exec('df -hTB1 ' + instance.options.path, function(err, response) { + + tproc = setTimeout(instance.custom.run, instance.options.interval); + + if (err) { + instance.error(err); + return; + } + + response.parseTerminal(function(line) { + if (line[0][0] !== '/') + return; + current.total = line[2].parseInt(); + current.free = line[4].parseInt(); + current.used = line[3].parseInt(); + current.path = instance.options.path || '/'; + current.type = line[1]; + current.percentUsed = line[5]; + instance.custom.status(); + instance.send2(current); + }); + }); + }; + + instance.custom.status = function() { + if (instance.options.enabled) + instance.status(current.free.filesize() + ' / ' + current.total.filesize()); + else + instance.status('Disabled', 'red'); + }; + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + instance.options.enabled && instance.custom.run(); + }); + + instance.on('close', function() { + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + }); + + setTimeout(instance.custom.run, 1000); +}; \ No newline at end of file diff --git a/RVO46/flow/monitormemory.js b/RVO46/flow/monitormemory.js new file mode 100755 index 0000000..2decbc4 --- /dev/null +++ b/RVO46/flow/monitormemory.js @@ -0,0 +1,87 @@ +exports.id = 'monitormemory'; +exports.title = 'Memory'; +exports.version = '1.0.0'; +exports.author = 'Peter Širka'; +exports.group = 'Monitoring'; +exports.color = '#F6BB42'; +exports.output = 1; +exports.click = true; +exports.icon = 'microchip'; +exports.options = { interval: 8000, enabled: true }; +exports.readme = `# Memory monitoring + +This component monitors memory \`bytes\` consumption in Linux systems. It uses \`free\` command. + +__Data Example__: + +\`\`\`javascript +{ + total: 33558769664, + used: 1998868480, + free: 2653708288 +} +\`\`\``; + +exports.html = `
+
+
+
@(Interval in milliseconds)
+
+
+
`; + +exports.install = function(instance) { + + var current = { total: 0, used: 0, free: 0 }; + var tproc = null; + + instance.custom.run = function() { + + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + + if (!instance.options.enabled) + return; + + require('child_process').exec('free -b -t', function(err, response) { + + tproc = setTimeout(instance.custom.run, instance.options.interval); + + if (err) { + instance.error(err); + return; + } + + var memory = response.split('\n')[1].match(/\d+/g); + current.total = memory[0].parseInt(); + current.used = memory[1].parseInt() - memory[3].parseInt(); + current.free = current.total - current.used; + instance.custom.status(); + instance.send2(current); + }); + }; + + instance.custom.status = function() { + if (instance.options.enabled) + instance.status(current.free.filesize() + ' / ' + current.total.filesize()); + else + instance.status('Disabled', 'red'); + }; + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + instance.options.enabled && instance.custom.run(); + }); + + instance.on('close', function() { + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + }); + + setTimeout(instance.custom.run, 1000); +}; \ No newline at end of file diff --git a/RVO46/flow/nodesdb_changecheck.js b/RVO46/flow/nodesdb_changecheck.js new file mode 100755 index 0000000..9adab62 --- /dev/null +++ b/RVO46/flow/nodesdb_changecheck.js @@ -0,0 +1,77 @@ +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 = 2; +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); + } + } + + //kedze do slacku posielame stringy, na cloud musime previest vsetky stringy spat na objekty: + // Funkcia na parsovanie všetkých reťazcov v poli + const parseArray = (arr) => { + return arr.map(jsonString => JSON.parse(jsonString)); + }; + + 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); + if (FLOW.GLOBALS.settings.send_changed_node_numbers) instance.send(1, { aktualneNody: parseArray(zmenene), originalne: parseArray(Array.from(set2)) }); + } + 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/RVO46/flow/show_dbdata.js b/RVO46/flow/show_dbdata.js new file mode 100755 index 0000000..1e23ff7 --- /dev/null +++ b/RVO46/flow/show_dbdata.js @@ -0,0 +1,243 @@ +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 = 8; +exports.output = 1; + +const { exec } = require('child_process'); + +exports.install = 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 }) + }) + instance.on("5", _ => { + exec("sudo tail -n 25 monitor.txt", (err, stdout, stderr) => { + if (err || stderr) instance.send(0, { err, stderr }); + else instance.send(0, stdout); + }) + }) + instance.on("6", _ => { + exec("sudo tail -n 25 err.txt", (err, stdout, stderr) => { + if (err || stderr) instance.send(0, { err, stderr }); + else instance.send(0, stdout); + }) + }) + instance.on("7", _ => { + instance.send(0, FLOW.deviceStatus); + }) +}; + + +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/RVO46/flow/slack_filter.js b/RVO46/flow/slack_filter.js new file mode 100755 index 0000000..6618523 --- /dev/null +++ b/RVO46/flow/slack_filter.js @@ -0,0 +1,188 @@ +exports.id = 'slack_filter'; +exports.title = 'Slack Filter'; +exports.group = 'Citysys'; +exports.color = '#30E193'; +exports.input = 2; +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 = `
+
+
+
@(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('0', 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']['en']; + 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"] = []; + } + + instance.options.name = FLOW.GLOBALS.settings.rvo_name; + if (instance.options.name) { + instance.status('Running'); + running = true; + } else { + instance.status('Please run options again', 'red'); + running = false; + } + } catch (e) { + instance.error('Citysys connector: ' + e.message); + } + }; + + instance.on('options', instance.reconfigure); + + instance.on("1", _ => { + instance.reconfigure(); + }) +}; diff --git a/RVO46/flow/thermometer.js b/RVO46/flow/thermometer.js new file mode 100755 index 0000000..fc7074d --- /dev/null +++ b/RVO46/flow/thermometer.js @@ -0,0 +1,99 @@ +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 = 5;//minutes +let NUMBER_OF_FAILURES_TO_SEND_ERROR = 13; + +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) => { + + 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); + setTimeout(main, 20000); + }) +}; diff --git a/RVO46/flow/trigger.js b/RVO46/flow/trigger.js new file mode 100755 index 0000000..27545a8 --- /dev/null +++ b/RVO46/flow/trigger.js @@ -0,0 +1,79 @@ +exports.id = 'trigger'; +exports.title = 'Trigger'; +exports.group = 'Inputs'; +exports.color = '#F6BB42'; +exports.click = true; +exports.output = 1; +exports.version = '1.1.0'; +exports.author = 'Martin Smola'; +exports.icon = 'play'; + +exports.html = `
+
@(Data type (String by default))
+
@(Data)
+
Trigger 5s after initialization.
+
@(Useful when there's a need to run certain flow when the app restarts, etc.)
+
`; + +exports.readme = `# Trigger + +- Clicking on the component starts the chain +- Settings allows to set a data-type and a value`; + +exports.install = function(instance) { + + var value; + + instance.on('click', () => instance.send2(value)); + + instance.reconfigure = function() { + var options = instance.options; + value = null; + switch (options.datatype) { + case 'integer': + value = options.data.parseInt2('error'); + value = value === 'error' ? NaN : value; + break; + case 'float': + value = options.data.parseFloat2('error'); + value = value === 'error' ? NaN : value; + break; + case 'date': + options.data = options.data.toString(); + var num = options.data.parseInt('error'); + num === 'error' && (num = options.data.parseDate('error')); + num === 'error' && (num = null); + value = num ? new Date(num).toUTCString() : num; + break; + case 'object': + try { + value = (new Function('return ' + options.data))(); + } catch (e) { + instance.error(e); + } + break; + case 'boolean': + value = options.data.parseBoolean(); + break; + case 'buffer': + try { + value = U.createBuffer(options.data); + } catch (e) { + instance.error(e); + } + break; + case 'string': + default: + value = '' + (options.data || ''); + break; + } + }; + + instance.on('options', instance.reconfigure); + instance.reconfigure(); + + if (instance.options.restart) + setTimeout(function(){ + instance.send2(value); + }, 5000); +}; diff --git a/RVO46/flow/variables.txt b/RVO46/flow/variables.txt new file mode 100755 index 0000000..e69de29 diff --git a/RVO46/flow/virtualwirein.js b/RVO46/flow/virtualwirein.js new file mode 100755 index 0000000..38a4e42 --- /dev/null +++ b/RVO46/flow/virtualwirein.js @@ -0,0 +1,43 @@ +exports.id = 'virtualwirein'; +exports.title = 'Virtual wire in'; +exports.version = '1.0.0'; +exports.author = 'Martin Smola'; +exports.color = '#303E4D'; +exports.icon = 'sign-in'; +exports.input = false; +exports.output = 1; +exports.options = {}; +exports.readme = `# Virtual wire in + +When the wires between the components are mess it's time to use Virtual wire.`; + +exports.html = `
+
@(Wire name)
+
+`; + +exports.install = function(instance) { + + instance.custom.reconfigure = function(options){ + if (instance.options.wirename) { + instance.status(instance.options.wirename); + } else + instance.status('Not configured', 'red'); + }; + + ON('virtualwire', function(wirename, flowdata){ + if (instance.options.wirename && instance.options.wirename === wirename) + instance.send(flowdata); + }); + + instance.on('options', instance.custom.reconfigure); + instance.custom.reconfigure(); +}; diff --git a/RVO46/flow/virtualwireout.js b/RVO46/flow/virtualwireout.js new file mode 100755 index 0000000..94a1e4f --- /dev/null +++ b/RVO46/flow/virtualwireout.js @@ -0,0 +1,41 @@ +exports.id = 'virtualwireout'; +exports.title = 'Virtual wire out'; +exports.version = '1.0.0'; +exports.author = 'Martin Smola'; +exports.color = '#303E4D'; +exports.icon = 'sign-out'; +exports.input = true; +exports.options = {}; +exports.readme = `# Virtual wire out + +When the wires between the components are mess it's time to use Virtual wire.`; + +exports.html = `
+
@(Wire name)
+
+`; + +exports.install = function(instance) { + + instance.custom.reconfigure = function(){ + if (instance.options.wirename) { + instance.status(instance.options.wirename); + } else + instance.status('Not configured', 'red'); + }; + + instance.on('data', function(flowdata) { + EMIT('virtualwire', instance.options.wirename, flowdata); + }); + + instance.on('options', instance.custom.reconfigure); + instance.custom.reconfigure(); +}; diff --git a/RVO46/flow/wsmqttpublish.js b/RVO46/flow/wsmqttpublish.js new file mode 100755 index 0000000..0eba804 --- /dev/null +++ b/RVO46/flow/wsmqttpublish.js @@ -0,0 +1,448 @@ +exports.id = 'wsmqttpublish'; +exports.title = 'WS MQTT publish'; +exports.group = 'MQTT'; +exports.color = '#888600'; +exports.version = '1.0.2'; +exports.icon = 'sign-out'; +exports.input = 2; +exports.output = 3; +exports.options = { host: 'tb-stage.worksys.io', port: 1883, clientid: "", username: "" }; + +exports.html = `
+
+
+
Hostname or IP address (if not empty - setting will override db setting)
+
+
+
Port
+
+
+
+
+
@(Client id)
+
+
+
@(Username)
+
+
+
`; + + +exports.readme = ` +# WS MQTT Publish + +Version 1.0.3. + +Added: +- database collections, +- 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 = { + debug: 0, + rpcCall: 1, + services: 2 +} + +//CONFIG +let createTelemetryBackup = true; +let saveTelemetryOnError = true;//backup_on_failure overrides this value +//------------------------ + +let rollers; +if (createTelemetryBackup) rollers = require('streamroller'); + +const noSqlFileSizeLimit = 4194304;//use 5MB - 4194304 +let insertNoSqlCounter = 0; +let insertBackupNoSqlCounter = 0; +let processingData = false; + +let backup_on_failure = false;//== saveTelemetryOnError - create backup client 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; + +process.on('uncaughtException', function(err) { + + errLogger.error('uncaughtException:', err.message) + errLogger.error(err.stack); + + //TODO + //send to service + + //process.exit(1); +}) + +const nosql = NOSQL('tbdata'); +const nosqlBackup = NOSQL('/backup/tbdata'); + + +exports.install = function(instance) { + + var client; + var opts; + var clientReady = false; + + // wsmqtt status for notification purposes on projects.worksys.io database + let wsmqttName = null; + let sendWsStatusVar = null; + let wsmqtt_status = 'disconnected'; + + 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'; + } + + function sendWsStatus() { + instance.send(SEND_TO.services, { [wsmqttName]: wsmqtt_status }); + } + + + function main() { + if (!FLOW.dbLoaded) return; + + loadSettings(); + clearInterval(sendWsStatus); + sendWsStatusVar = setInterval(sendWsStatus, 180000); + } + + //set opts according to db settings + function loadSettings() { + + if (instance.options.host !== "") { + //override settings from database + var o = instance.options; + opts = { + host: o.host, + port: o.port, + clientId: o.clientid, + username: o.username, + rejectUnauthorized: false, + resubscribe: false + }; + + wsmqttName = getWsmqttName(o.host); + + console.log("wsmqttpublich -> loadSettings from instance.options", instance.options); + } + else { + + const SETTINGS = FLOW.GLOBALS.settings; + backup_on_failure = SETTINGS.backup_on_failure; + saveTelemetryOnError = backup_on_failure; + + restore_from_backup = SETTINGS.restore_from_backup; + restore_backup_wait = SETTINGS.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; + + opts = { + host: mqtt_host, + port: mqtt_port, + keepalive: 10, + clientId: mqtt_clientid, + username: mqtt_username, + rejectUnauthorized: false, + resubscribe: false + }; + + wsmqttName = getWsmqttName(mqtt_host); + } + + connectToTbServer(); + } + + function connectToTbServer() { + 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"); + //monitor.info("MQTT client connected"); + + sendClientError = true; + clientReady = true; + wsmqtt_status = 'connected'; + }); + + client.on('reconnect', function() { + instance.status("Reconnecting", "yellow"); + clientReady = false; + }); + + client.on('message', function(topic, message) { + // message is type of buffer + message = message.toString(); + if (message[0] === '{') { + TRY(function() { + + message = JSON.parse(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 } }); + } + + }, () => instance.debug('MQTT: Error parsing data', message)); + } + + instance.send(SEND_TO.rpcCall, { "topic": topic, "content": message }); + }); + + client.on('close', function() { + clientReady = false; + wsmqtt_status = 'disconnected'; + + instance.status("Disconnected", "red"); + instance.send(SEND_TO.debug, { "message": "Client CLOSE signal received !" }); + }); + + client.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; + wsmqtt_status = 'disconnected'; + }); + + } + + + instance.on("0", _ => { + main(); + }) + + + instance.on('1', function(data) { + + if (clientReady) { + //do we have some data in backup file? if any, process data from database + if (saveTelemetryOnError) { + //read telemetry data and send back to server + if (!processingData) processDataFromDatabase(); + } + + let stringifiedJson = JSON.stringify(data.data); + client.publish("v1/gateway/telemetry", stringifiedJson, { qos: 1 }); + + //backup telemetry + if (createTelemetryBackup) { + data.data.id = UID(); + nosqlBackup.insert(data.data); + + insertBackupNoSqlCounter++; + if (insertBackupNoSqlCounter > 150) { + let options = { compress: true }; + let path = __dirname + "/../databases/backup/tbdata.nosql"; + var stream = new rollers.RollingFileStream(path, noSqlFileSizeLimit, 150, options); + stream.write(""); + stream.end(); + + insertBackupNoSqlCounter = 0; + } + } + + } + 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 (saveTelemetryOnError) { + //create new file from tbdata.nosql, if file size exceeds given limit, and clear tbdata.nosql + makeBackupFromDbFile(); + + //write to tb + data.data.id = UID(); + nosql.insert(data.data); + } + } + }); + + + instance.close = function(done) { + if (clientReady) { + client.end(); + clearInterval(sendWsStatusVar); + } + }; + + + function getDbBackupFileCounter(type) { + var files = fs.readdirSync(__dirname + "/../databases"); + + let counter = 0; + for (var i = 0; i < files.length; i++) { + + if (files[i] == "tbdata.nosql") continue; + + if (files[i].endsWith(".nosql")) { + + let pos = files[i].indexOf("."); + if (pos > -1) { + + let fileCounter = counter; + let firstDigit = files[i].slice(0, pos); + + fileCounter = parseInt(firstDigit); + if (isNaN(fileCounter)) fileCounter = 0; + //console.log("getDbBackupFileCounter digit:", files[i], firstDigit, fileCounter, isNaN(fileCounter), type); + + if (type == "max") { + if (fileCounter > counter) { + counter = fileCounter; + } + } + else if (type == "min") { + if (counter == 0) counter = fileCounter; + + if (fileCounter < counter) { + counter = fileCounter; + } + } + } + } + + } + + if (type == "max") counter++; + + return counter; + } + + const makeBackupFromDbFile = async () => { + + if (!saveTelemetryOnError) return; + + //to avoid large file: tbdata.nosql + + //init value is 0! + if (insertNoSqlCounter > 0) { + --insertNoSqlCounter; + return; + } + + insertNoSqlCounter = 100; + + let source = __dirname + "/../databases/tbdata.nosql"; + + var stats = fs.statSync(source); + var fileSizeInBytes = stats.size; + + if (fileSizeInBytes > noSqlFileSizeLimit) { + + let counter = 1; + counter = getDbBackupFileCounter("max"); + + let destination = __dirname + "/../databases/" + counter + "." + "tbdata.nosql"; + + //make backup file + fs.copyFileSync(source, destination); + //fs.renameSync(p, p + "." + counter); + + //clear tbdata.nosql + fs.writeFileSync(source, ""); + fs.truncateSync(source, 0); + + } + } + + const processDataFromDatabase = async () => { + + if (restore_from_backup <= 0) return; + + //calculate diff + const now = new Date(); + let currentTime = now.getTime(); + let diff = currentTime - lastRestoreTime; + + if ((diff / 1000) < restore_backup_wait) { + //console.log("*********restore_backup_wait", diff, restore_backup_wait); + return; + } + + processingData = true; + + //get filename to process + let counter = getDbBackupFileCounter("min"); + + //we have some backup files + let dataBase = 'tbdata'; + + var nosql; + if (counter == 0) dataBase = 'tbdata'; + else dataBase = counter + "." + 'tbdata'; + + nosql = NOSQL(dataBase); + + //select all data - use limit restore_from_backup + let records = await promisifyBuilder(nosql.find().take(restore_from_backup)); + + for (let i = 0; i < records.length; i++) { + if (clientReady) { + + let item = records[i]; + let id = item.id; + + if (id !== undefined) { + //console.log("------------processDataFromDatabase - remove", id, dataBase, i); + + try { + + let message = JSON.parse(JSON.stringify(item)); + delete message.id; + + client.publish("v1/gateway/telemetry", JSON.stringify(message), { qos: 1 }); + + //remove from database + await promisifyBuilder(nosql.remove().where("id", id)); + + } catch (error) { + //process error + console.log("processDataFromDatabase", error); + } + + } + + } + else { + processingData = false; + return; + } + } + + if (records.length > 0) { + //clean backup file + if (counter > 0) nosql.clean(); + } + + //no data in db, remove + if (records.length == 0) { + if (counter > 0) nosql.drop(); + } + + const d = new Date(); + lastRestoreTime = d.getTime(); + + processingData = false; + + } + + instance.on('options', main); + //instance.reconfigure(); +}; diff --git a/RVO46/monitor.txt b/RVO46/monitor.txt new file mode 100755 index 0000000..0419edb --- /dev/null +++ b/RVO46/monitor.txt @@ -0,0 +1,306 @@ +[2025-10-09T16:58:31.017] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-09T16:58:36.369] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-09T16:58:36.374] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-09T16:58:36.375] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-09T16:58:36.376] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-09T16:58:36.380] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T16:58:36.381] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-10-10T05:32:00.381Z +[2025-10-09T16:58:36.383] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-10-09T16:45:00.383Z +[2025-10-09T16:58:36.384] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T16:58:36.385] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-10-09T16:58:36.386] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-09T16:58:36.386] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-09T16:58:36.389] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T16:58:36.390] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-10-10T05:32:00.389Z +[2025-10-09T16:58:36.391] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-10-09T16:45:00.390Z +[2025-10-09T16:58:36.391] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T16:58:36.392] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-10-09T16:58:36.393] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-09T16:58:36.394] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-09T16:58:36.397] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T16:58:36.398] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-10-10T05:32:00.397Z +[2025-10-09T16:58:36.399] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-10-09T16:45:00.399Z +[2025-10-09T16:58:36.400] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T16:58:36.401] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-10-09T16:58:36.405] [INFO] monitorLogs - tasks created: 546 +[2025-10-09T16:58:36.407] [INFO] monitorLogs - -->FLOW bol spustený RvmwNz8QPblKp41GD7lKWZkJrLVYoBO92dMegn6W 2025-08-08 +[2025-10-09T16:58:41.421] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-09T18:27:00.818] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-09T18:27:00.820] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-09T18:27:00.822] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-09T19:11:29.345] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-09T19:11:34.696] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-09T19:11:34.701] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-09T19:11:34.702] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-09T19:11:34.703] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-09T19:11:34.707] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T19:11:34.708] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-10-10T05:32:00.708Z +[2025-10-09T19:11:34.710] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-10-10T16:45:00.710Z +[2025-10-09T19:11:34.711] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T19:11:34.712] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-10-09T19:11:34.713] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-09T19:11:34.713] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-09T19:11:34.716] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T19:11:34.717] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-10-10T05:32:00.716Z +[2025-10-09T19:11:34.718] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-10-10T16:45:00.718Z +[2025-10-09T19:11:34.718] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T19:11:34.720] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-10-09T19:11:34.720] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-09T19:11:34.721] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-09T19:11:34.724] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T19:11:34.725] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-10-10T05:32:00.724Z +[2025-10-09T19:11:34.726] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-10-10T16:45:00.725Z +[2025-10-09T19:11:34.726] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T19:11:34.728] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-10-09T19:11:34.731] [INFO] monitorLogs - tasks created: 546 +[2025-10-09T19:11:34.734] [INFO] monitorLogs - -->FLOW bol spustený RvmwNz8QPblKp41GD7lKWZkJrLVYoBO92dMegn6W 2025-08-08 +[2025-10-09T19:11:39.738] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-10T03:11:36.013] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-10 03:11:36 +[2025-10-10T06:54:22.996] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-10T06:54:22.999] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-10T06:54:23.001] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-10T18:23:24.644] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-10T18:23:24.646] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-10T18:23:24.648] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-11T03:11:37.014] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-11 03:11:37 +[2025-10-11T06:55:54.679] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-11T06:55:54.684] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-11T06:55:54.687] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-11T18:25:11.534] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-11T18:25:11.537] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-11T18:25:11.540] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-12T03:11:38.014] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-12 03:11:38 +[2025-10-12T06:55:47.323] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-12T06:55:47.328] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-12T06:55:47.334] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-12T18:23:02.722] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-12T18:23:02.727] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-12T18:23:02.732] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-13T03:11:40.013] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-13 03:11:40 +[2025-10-13T06:50:22.064] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-13T06:50:22.067] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-13T06:50:22.069] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-13T18:28:02.478] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-13T18:28:02.481] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-13T18:28:02.483] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-14T03:11:41.013] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-14 03:11:41 +[2025-10-14T06:53:33.835] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-14T06:53:33.839] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-14T06:53:33.840] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-14T18:17:27.381] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-14T18:17:27.383] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-14T18:17:27.386] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-15T03:11:42.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-15 03:11:42 +[2025-10-15T06:58:35.847] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-15T06:58:35.850] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-15T06:58:35.852] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-15T14:25:05.081] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-15T14:25:10.441] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-15T14:25:10.446] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-15T14:25:10.447] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-15T14:25:10.448] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-15T14:25:10.452] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-15T14:25:10.454] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-10-16T05:41:00.453Z +[2025-10-15T14:25:10.455] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-10-15T16:33:00.455Z +[2025-10-15T14:25:10.456] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:41', name: 'luxOff' }, + { value: 1, start_time: '18:33', name: 'luxOn' } +] +[2025-10-15T14:25:10.457] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-10-15T14:25:10.458] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-15T14:25:10.458] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-15T14:25:10.461] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-15T14:25:10.462] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-10-16T05:41:00.461Z +[2025-10-15T14:25:10.463] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-10-15T16:33:00.462Z +[2025-10-15T14:25:10.463] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:41', name: 'luxOff' }, + { value: 1, start_time: '18:33', name: 'luxOn' } +] +[2025-10-15T14:25:10.464] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-10-15T14:25:10.465] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-15T14:25:10.465] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-15T14:25:10.468] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-15T14:25:10.468] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-10-16T05:41:00.468Z +[2025-10-15T14:25:10.469] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-10-15T16:33:00.469Z +[2025-10-15T14:25:10.470] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:41', name: 'luxOff' }, + { value: 1, start_time: '18:33', name: 'luxOn' } +] +[2025-10-15T14:25:10.471] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-10-15T14:25:10.474] [INFO] monitorLogs - tasks created: 546 +[2025-10-15T14:25:10.477] [INFO] monitorLogs - -->FLOW bol spustený RvmwNz8QPblKp41GD7lKWZkJrLVYoBO92dMegn6W 2025-10-08 +[2025-10-15T14:25:15.482] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-15T18:18:51.381] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-15T18:18:51.387] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-15T18:18:51.390] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor diff --git a/RVO46/package-lock.json b/RVO46/package-lock.json new file mode 100755 index 0000000..3c5c1ba --- /dev/null +++ b/RVO46/package-lock.json @@ -0,0 +1,2139 @@ +{ + "name": "emptyproject", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "emptyproject", + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "bitwise": "^2.1.0", + "easy-crc": "0.0.2", + "jsmodbus": "^4.0.6", + "log4js": "^6.3.0", + "moment": "^2.30.1", + "mqtt": "^4.2.6", + "nodemailer": "^6.9.7", + "serialport": "^9.2.8", + "total.js": "^3.4.13" + } + }, + "node_modules/@serialport/binding-abstract": { + "version": "9.2.3", + "resolved": "https://registry.npmjs.org/@serialport/binding-abstract/-/binding-abstract-9.2.3.tgz", + "integrity": "sha512-cQs9tbIlG3P0IrOWyVirqlhWuJ7Ms2Zh9m2108z6Y5UW/iVj6wEOiW8EmK9QX9jmJXYllE7wgGgvVozP5oCj3w==", + "dependencies": { + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/binding-mock": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/binding-mock/-/binding-mock-9.2.4.tgz", + "integrity": "sha512-dpEhACCs44oQhh6ajJfJdvQdK38Vq0N4W6iD/gdplglDCK7qXRQCMUjJIeKdS/HSEiWkC3bwumUhUufdsOyT4g==", + "dependencies": { + "@serialport/binding-abstract": "9.2.3", + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/bindings": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/@serialport/bindings/-/bindings-9.2.8.tgz", + "integrity": "sha512-hSLxTe0tADZ3LMMGwvEJWOC/TaFQTyPeFalUCsJ1lSQ0k6bPF04JwrtB/C81GetmDBTNRY0GlD0SNtKCc7Dr5g==", + "hasInstallScript": true, + "dependencies": { + "@serialport/binding-abstract": "9.2.3", + "@serialport/parser-readline": "9.2.4", + "bindings": "^1.5.0", + "debug": "^4.3.2", + "nan": "^2.15.0", + "prebuild-install": "^7.0.0" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-byte-length": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-byte-length/-/parser-byte-length-9.2.4.tgz", + "integrity": "sha512-sQD/iw4ZMU3xW9PLi0/GlvU6Y623jGeWecbMkO7izUo/6P7gtfv1c9ikd5h0kwL8AoAOpQA1lxdHIKox+umBUg==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-cctalk": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-cctalk/-/parser-cctalk-9.2.4.tgz", + "integrity": "sha512-T4TU5vQMwmo9AB3gQLFDWbfJXlW5jd9guEsB/nqKjFHTv0FXPdZ7DQ2TpSp8RnHWxU3GX6kYTaDO20BKzc8GPQ==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-delimiter": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-delimiter/-/parser-delimiter-9.2.4.tgz", + "integrity": "sha512-4nvTAoYAgkxFiXrkI+3CA49Yd43CODjeszh89EK+I9c8wOZ+etZduRCzINYPiy26g7zO+GRAb9FoPCsY+sYcbQ==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-inter-byte-timeout": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-inter-byte-timeout/-/parser-inter-byte-timeout-9.2.4.tgz", + "integrity": "sha512-SOAdvr0oBQIOCXX198hiTlxs4JTKg9j5piapw5tNq52fwDOWdbYrFneT/wN04UTMKaDrJuEvXq6T4rv4j7nJ5A==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-readline": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-readline/-/parser-readline-9.2.4.tgz", + "integrity": "sha512-Z1/qrZTQUVhNSJP1hd9YfDvq0o7d87rNwAjjRKbVpa7Qi51tG5BnKt43IV3NFMyBlVcRe0rnIb3tJu57E0SOwg==", + "dependencies": { + "@serialport/parser-delimiter": "9.2.4" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-ready": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-ready/-/parser-ready-9.2.4.tgz", + "integrity": "sha512-Pyi94Itjl6qAURwIZr/gmZpMAyTmKXThm6vL5DoAWGQjcRHWB0gwv2TY2v7N+mQLJYUKU3cMnvnATXxHm7xjxw==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-regex": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-regex/-/parser-regex-9.2.4.tgz", + "integrity": "sha512-sI/cVvPOYz+Dbv4ZdnW16qAwvXiFf/1pGASQdbveRTlgJDdz7sRNlCBifzfTN2xljwvCTZYqiudKvDdC1TepRQ==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/stream": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/stream/-/stream-9.2.4.tgz", + "integrity": "sha512-bLye8Ub4vUFQGmkh8qEqehr7SE7EJs2yDs0h9jzuL5oKi+F34CFmWkEErO8GAOQ8YNn7p6b3GxUgs+0BrHHDZQ==", + "dependencies": { + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "node_modules/are-we-there-yet": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", + "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/base64-js": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", + "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==" + }, + "node_modules/bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "dependencies": { + "file-uri-to-path": "1.0.0" + } + }, + "node_modules/bitwise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/bitwise/-/bitwise-2.1.0.tgz", + "integrity": "sha512-XKgAhMXCh4H/3oNwAHAsAO0iC89s9cOiumgYwSHjSobGWxYjv62YhkL9QEdvGP151xypCtMlAfKK79GEcd2eRQ==" + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/bl/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/buffer": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz", + "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==", + "dependencies": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + }, + "node_modules/buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" + }, + "node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, + "node_modules/code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/commist": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/commist/-/commist-1.1.0.tgz", + "integrity": "sha512-rraC8NXWOEjhADbZe9QBNzLAN5Q3fsTPQtBV+fEVj6xKIgDgNiEVE6ZNfHpZOqfQ21YUzfVNUXLOEZquYvQPPg==", + "dependencies": { + "leven": "^2.1.0", + "minimist": "^1.1.0" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "node_modules/concat-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", + "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", + "engines": [ + "node >= 6.0" + ], + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.0.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/concat-stream/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" + }, + "node_modules/core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "node_modules/crc": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/crc/-/crc-3.4.0.tgz", + "integrity": "sha512-ycVC2+4/DLgXXq7QweYi2znhqDuZz6P5TQXnkQo8v15XY/5p/IWeZwsSE31Ifo8w15b8TWLsqhXOjXyilHuQxw==" + }, + "node_modules/date-format": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.11.tgz", + "integrity": "sha512-VS20KRyorrbMCQmpdl2hg5KaOUsda1RbnsJg461FfrcyCUg+pkd0b40BSW4niQyTheww4DBXQnS7HwSrKkipLw==", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" + }, + "node_modules/detect-libc": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz", + "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==", + "engines": { + "node": ">=8" + } + }, + "node_modules/duplexify": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.2.tgz", + "integrity": "sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw==", + "dependencies": { + "end-of-stream": "^1.4.1", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1", + "stream-shift": "^1.0.0" + } + }, + "node_modules/duplexify/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/easy-crc": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/easy-crc/-/easy-crc-0.0.2.tgz", + "integrity": "sha512-h6eqIdhJRe0p271/xZJbM/0klCi13mW5IB7ZEzEGH11yV4QXWAkD4yPErz0fXdhFrd6sZ4Q1k5Iky2kMsMNePw==" + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" + }, + "node_modules/flatted": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", + "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==" + }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, + "node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "node_modules/gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha512-14x4kjc6lkD3ltw589k0NrPD6cCNTD6CWoVUNpB85+DrtONoZn+Rug6xZU5RvSC4+TZPxA5AnBibQYAvZn41Hg==", + "dependencies": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "node_modules/github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==" + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" + }, + "node_modules/has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" + }, + "node_modules/help-me": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/help-me/-/help-me-3.0.0.tgz", + "integrity": "sha512-hx73jClhyk910sidBB7ERlnhMlFsJJIBqSVMFDwPN8o2v9nmp5KgLq1Xz1Bf1fCMMZ6mPrX159iG0VLy/fPMtQ==", + "dependencies": { + "glob": "^7.1.6", + "readable-stream": "^3.6.0" + } + }, + "node_modules/help-me/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, + "node_modules/is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==", + "dependencies": { + "number-is-nan": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "node_modules/js-sdsl": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz", + "integrity": "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/js-sdsl" + } + }, + "node_modules/jsmodbus": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/jsmodbus/-/jsmodbus-4.0.6.tgz", + "integrity": "sha512-gCmjoaERErK5Rn9Lu/BN07fY13MoWV7JKgGzrnkPlQPdPxYcwDhLtYcmpFFpZ4J9NPZZBSezi1UkLZO/DnNppA==", + "dependencies": { + "crc": "3.4.0", + "debug": "^3.1.0" + }, + "bin": { + "jsmodbus": "bin/jsmodbus.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/jsmodbus/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/leven": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", + "integrity": "sha1-wuep93IJTe6dNCAq6KzORoeHVYA=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/log4js": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.5.2.tgz", + "integrity": "sha512-DXtpNtt+KDOMT7RHUDIur/WsSA3rntlUh9Zg4XCdV42wUuMmbFkl38+LZ92Z5QvQA7mD5kAVkLiBSEH/tvUB8A==", + "dependencies": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "flatted": "^3.2.5", + "rfdc": "^1.3.0", + "streamroller": "^3.1.1" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" + }, + "node_modules/moment": { + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", + "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==", + "engines": { + "node": "*" + } + }, + "node_modules/mqtt": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/mqtt/-/mqtt-4.3.7.tgz", + "integrity": "sha512-ew3qwG/TJRorTz47eW46vZ5oBw5MEYbQZVaEji44j5lAUSQSqIEoul7Kua/BatBW0H0kKQcC9kwUHa1qzaWHSw==", + "dependencies": { + "commist": "^1.0.0", + "concat-stream": "^2.0.0", + "debug": "^4.1.1", + "duplexify": "^4.1.1", + "help-me": "^3.0.0", + "inherits": "^2.0.3", + "lru-cache": "^6.0.0", + "minimist": "^1.2.5", + "mqtt-packet": "^6.8.0", + "number-allocator": "^1.0.9", + "pump": "^3.0.0", + "readable-stream": "^3.6.0", + "reinterval": "^1.1.0", + "rfdc": "^1.3.0", + "split2": "^3.1.0", + "ws": "^7.5.5", + "xtend": "^4.0.2" + }, + "bin": { + "mqtt": "bin/mqtt.js", + "mqtt_pub": "bin/pub.js", + "mqtt_sub": "bin/sub.js" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/mqtt-packet": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/mqtt-packet/-/mqtt-packet-6.10.0.tgz", + "integrity": "sha512-ja8+mFKIHdB1Tpl6vac+sktqy3gA8t9Mduom1BA75cI+R9AHnZOiaBQwpGiWnaVJLDGRdNhQmFaAqd7tkKSMGA==", + "dependencies": { + "bl": "^4.0.2", + "debug": "^4.1.1", + "process-nextick-args": "^2.0.1" + } + }, + "node_modules/mqtt/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/nan": { + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.16.0.tgz", + "integrity": "sha512-UdAqHyFngu7TfQKsCBgAA6pWDkT8MAO7d0jyOecVhN5354xbLqdn8mV9Tat9gepAupm0bt2DbeaSC8vS52MuFA==" + }, + "node_modules/napi-build-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", + "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==" + }, + "node_modules/node-abi": { + "version": "3.22.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.22.0.tgz", + "integrity": "sha512-u4uAs/4Zzmp/jjsD9cyFYDXeISfUWaAVWshPmDZOFOv4Xl4SbzTXm53I04C2uRueYJ+0t5PEtLH/owbn2Npf/w==", + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/nodemailer": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.7.tgz", + "integrity": "sha512-rUtR77ksqex/eZRLmQ21LKVH5nAAsVicAtAYudK7JgwenEDZ0UIQ1adUGqErz7sMkWYxWTTU1aeP2Jga6WQyJw==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "dependencies": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "node_modules/number-allocator": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/number-allocator/-/number-allocator-1.0.14.tgz", + "integrity": "sha512-OrL44UTVAvkKdOdRQZIJpLkAdjXGTRda052sN4sO77bKEzYYqWKMBjQvrJFzqygI99gL6Z4u2xctPW1tB8ErvA==", + "dependencies": { + "debug": "^4.3.1", + "js-sdsl": "4.3.0" + } + }, + "node_modules/number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/prebuild-install": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.0.tgz", + "integrity": "sha512-CNcMgI1xBypOyGqjp3wOc8AAo1nMhZS3Cwd3iHIxOdAUbb+YxdNuM4Z5iIrZ8RLvOsf3F3bl7b7xGq6DjQoNYA==", + "dependencies": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^1.0.1", + "node-abi": "^3.3.0", + "npmlog": "^4.0.1", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + }, + "bin": { + "prebuild-install": "bin.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/reinterval": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reinterval/-/reinterval-1.1.0.tgz", + "integrity": "sha1-M2Hs+jymwYKDOA3Qu5VG85D17Oc=" + }, + "node_modules/rfdc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==" + }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/serialport": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/serialport/-/serialport-9.2.8.tgz", + "integrity": "sha512-FsWpMQgSJxi93JgWl5xM1f9/Z8IjRJuaUEoHqLf8FPBLw7gMhInuHOBhI2onQufWIYPGTz3H3oGcu1nCaK1EfA==", + "dependencies": { + "@serialport/binding-mock": "9.2.4", + "@serialport/bindings": "9.2.8", + "@serialport/parser-byte-length": "9.2.4", + "@serialport/parser-cctalk": "9.2.4", + "@serialport/parser-delimiter": "9.2.4", + "@serialport/parser-inter-byte-timeout": "9.2.4", + "@serialport/parser-readline": "9.2.4", + "@serialport/parser-ready": "9.2.4", + "@serialport/parser-regex": "9.2.4", + "@serialport/stream": "9.2.4", + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "node_modules/split2": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", + "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", + "dependencies": { + "readable-stream": "^3.0.0" + } + }, + "node_modules/split2/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==" + }, + "node_modules/streamroller": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.1.1.tgz", + "integrity": "sha512-iPhtd9unZ6zKdWgMeYGfSBuqCngyJy1B/GPi/lTpwGpa3bajuX30GjUVd0/Tn/Xhg0mr4DOSENozz9Y06qyonQ==", + "dependencies": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "fs-extra": "^10.1.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dependencies": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/tar-fs": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "dependencies": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tar-stream/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/total.js": { + "version": "3.4.13", + "resolved": "https://registry.npmjs.org/total.js/-/total.js-3.4.13.tgz", + "integrity": "sha512-lAH4gEixlPFbrE3xfKADAcHfO79IFq2wKa9GTsrgRzIR5MTg3mNH7+4IxvX1pK8faoYb/0oYSJ1YTsAa5hIFFQ==", + "bin": { + "total": "bin/totaljs", + "total.js": "bin/totaljs", + "totaljs": "bin/totaljs", + "totalpackage": "bin/tpm", + "tpm": "bin/tpm" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, + "node_modules/universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "node_modules/wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "node_modules/ws": { + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } + }, + "dependencies": { + "@serialport/binding-abstract": { + "version": "9.2.3", + "resolved": "https://registry.npmjs.org/@serialport/binding-abstract/-/binding-abstract-9.2.3.tgz", + "integrity": "sha512-cQs9tbIlG3P0IrOWyVirqlhWuJ7Ms2Zh9m2108z6Y5UW/iVj6wEOiW8EmK9QX9jmJXYllE7wgGgvVozP5oCj3w==", + "requires": { + "debug": "^4.3.2" + } + }, + "@serialport/binding-mock": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/binding-mock/-/binding-mock-9.2.4.tgz", + "integrity": "sha512-dpEhACCs44oQhh6ajJfJdvQdK38Vq0N4W6iD/gdplglDCK7qXRQCMUjJIeKdS/HSEiWkC3bwumUhUufdsOyT4g==", + "requires": { + "@serialport/binding-abstract": "9.2.3", + "debug": "^4.3.2" + } + }, + "@serialport/bindings": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/@serialport/bindings/-/bindings-9.2.8.tgz", + "integrity": "sha512-hSLxTe0tADZ3LMMGwvEJWOC/TaFQTyPeFalUCsJ1lSQ0k6bPF04JwrtB/C81GetmDBTNRY0GlD0SNtKCc7Dr5g==", + "requires": { + "@serialport/binding-abstract": "9.2.3", + "@serialport/parser-readline": "9.2.4", + "bindings": "^1.5.0", + "debug": "^4.3.2", + "nan": "^2.15.0", + "prebuild-install": "^7.0.0" + } + }, + "@serialport/parser-byte-length": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-byte-length/-/parser-byte-length-9.2.4.tgz", + "integrity": "sha512-sQD/iw4ZMU3xW9PLi0/GlvU6Y623jGeWecbMkO7izUo/6P7gtfv1c9ikd5h0kwL8AoAOpQA1lxdHIKox+umBUg==" + }, + "@serialport/parser-cctalk": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-cctalk/-/parser-cctalk-9.2.4.tgz", + "integrity": "sha512-T4TU5vQMwmo9AB3gQLFDWbfJXlW5jd9guEsB/nqKjFHTv0FXPdZ7DQ2TpSp8RnHWxU3GX6kYTaDO20BKzc8GPQ==" + }, + "@serialport/parser-delimiter": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-delimiter/-/parser-delimiter-9.2.4.tgz", + "integrity": "sha512-4nvTAoYAgkxFiXrkI+3CA49Yd43CODjeszh89EK+I9c8wOZ+etZduRCzINYPiy26g7zO+GRAb9FoPCsY+sYcbQ==" + }, + "@serialport/parser-inter-byte-timeout": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-inter-byte-timeout/-/parser-inter-byte-timeout-9.2.4.tgz", + "integrity": "sha512-SOAdvr0oBQIOCXX198hiTlxs4JTKg9j5piapw5tNq52fwDOWdbYrFneT/wN04UTMKaDrJuEvXq6T4rv4j7nJ5A==" + }, + "@serialport/parser-readline": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-readline/-/parser-readline-9.2.4.tgz", + "integrity": "sha512-Z1/qrZTQUVhNSJP1hd9YfDvq0o7d87rNwAjjRKbVpa7Qi51tG5BnKt43IV3NFMyBlVcRe0rnIb3tJu57E0SOwg==", + "requires": { + "@serialport/parser-delimiter": "9.2.4" + } + }, + "@serialport/parser-ready": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-ready/-/parser-ready-9.2.4.tgz", + "integrity": "sha512-Pyi94Itjl6qAURwIZr/gmZpMAyTmKXThm6vL5DoAWGQjcRHWB0gwv2TY2v7N+mQLJYUKU3cMnvnATXxHm7xjxw==" + }, + "@serialport/parser-regex": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-regex/-/parser-regex-9.2.4.tgz", + "integrity": "sha512-sI/cVvPOYz+Dbv4ZdnW16qAwvXiFf/1pGASQdbveRTlgJDdz7sRNlCBifzfTN2xljwvCTZYqiudKvDdC1TepRQ==" + }, + "@serialport/stream": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/stream/-/stream-9.2.4.tgz", + "integrity": "sha512-bLye8Ub4vUFQGmkh8qEqehr7SE7EJs2yDs0h9jzuL5oKi+F34CFmWkEErO8GAOQ8YNn7p6b3GxUgs+0BrHHDZQ==", + "requires": { + "debug": "^4.3.2" + } + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==" + }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "are-we-there-yet": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", + "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "base64-js": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", + "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==" + }, + "bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "requires": { + "file-uri-to-path": "1.0.0" + } + }, + "bitwise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/bitwise/-/bitwise-2.1.0.tgz", + "integrity": "sha512-XKgAhMXCh4H/3oNwAHAsAO0iC89s9cOiumgYwSHjSobGWxYjv62YhkL9QEdvGP151xypCtMlAfKK79GEcd2eRQ==" + }, + "bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "requires": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "buffer": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz", + "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==", + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" + }, + "chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==" + }, + "commist": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/commist/-/commist-1.1.0.tgz", + "integrity": "sha512-rraC8NXWOEjhADbZe9QBNzLAN5Q3fsTPQtBV+fEVj6xKIgDgNiEVE6ZNfHpZOqfQ21YUzfVNUXLOEZquYvQPPg==", + "requires": { + "leven": "^2.1.0", + "minimist": "^1.1.0" + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "concat-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", + "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.0.2", + "typedarray": "^0.0.6" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "crc": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/crc/-/crc-3.4.0.tgz", + "integrity": "sha512-ycVC2+4/DLgXXq7QweYi2znhqDuZz6P5TQXnkQo8v15XY/5p/IWeZwsSE31Ifo8w15b8TWLsqhXOjXyilHuQxw==" + }, + "date-format": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.11.tgz", + "integrity": "sha512-VS20KRyorrbMCQmpdl2hg5KaOUsda1RbnsJg461FfrcyCUg+pkd0b40BSW4niQyTheww4DBXQnS7HwSrKkipLw==" + }, + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "requires": { + "ms": "2.1.2" + } + }, + "decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "requires": { + "mimic-response": "^3.1.0" + } + }, + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==" + }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" + }, + "detect-libc": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz", + "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==" + }, + "duplexify": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.2.tgz", + "integrity": "sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw==", + "requires": { + "end-of-stream": "^1.4.1", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1", + "stream-shift": "^1.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "easy-crc": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/easy-crc/-/easy-crc-0.0.2.tgz", + "integrity": "sha512-h6eqIdhJRe0p271/xZJbM/0klCi13mW5IB7ZEzEGH11yV4QXWAkD4yPErz0fXdhFrd6sZ4Q1k5Iky2kMsMNePw==" + }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "requires": { + "once": "^1.4.0" + } + }, + "expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==" + }, + "file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" + }, + "flatted": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", + "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==" + }, + "fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, + "fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha512-14x4kjc6lkD3ltw589k0NrPD6cCNTD6CWoVUNpB85+DrtONoZn+Rug6xZU5RvSC4+TZPxA5AnBibQYAvZn41Hg==", + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==" + }, + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" + }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" + }, + "help-me": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/help-me/-/help-me-3.0.0.tgz", + "integrity": "sha512-hx73jClhyk910sidBB7ERlnhMlFsJJIBqSVMFDwPN8o2v9nmp5KgLq1Xz1Bf1fCMMZ6mPrX159iG0VLy/fPMtQ==", + "requires": { + "glob": "^7.1.6", + "readable-stream": "^3.6.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==", + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "js-sdsl": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz", + "integrity": "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==" + }, + "jsmodbus": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/jsmodbus/-/jsmodbus-4.0.6.tgz", + "integrity": "sha512-gCmjoaERErK5Rn9Lu/BN07fY13MoWV7JKgGzrnkPlQPdPxYcwDhLtYcmpFFpZ4J9NPZZBSezi1UkLZO/DnNppA==", + "requires": { + "crc": "3.4.0", + "debug": "^3.1.0" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "requires": { + "ms": "^2.1.1" + } + } + } + }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, + "leven": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", + "integrity": "sha1-wuep93IJTe6dNCAq6KzORoeHVYA=" + }, + "log4js": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.5.2.tgz", + "integrity": "sha512-DXtpNtt+KDOMT7RHUDIur/WsSA3rntlUh9Zg4XCdV42wUuMmbFkl38+LZ92Z5QvQA7mD5kAVkLiBSEH/tvUB8A==", + "requires": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "flatted": "^3.2.5", + "rfdc": "^1.3.0", + "streamroller": "^3.1.1" + } + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "requires": { + "yallist": "^4.0.0" + } + }, + "mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==" + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==" + }, + "mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" + }, + "moment": { + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", + "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==" + }, + "mqtt": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/mqtt/-/mqtt-4.3.7.tgz", + "integrity": "sha512-ew3qwG/TJRorTz47eW46vZ5oBw5MEYbQZVaEji44j5lAUSQSqIEoul7Kua/BatBW0H0kKQcC9kwUHa1qzaWHSw==", + "requires": { + "commist": "^1.0.0", + "concat-stream": "^2.0.0", + "debug": "^4.1.1", + "duplexify": "^4.1.1", + "help-me": "^3.0.0", + "inherits": "^2.0.3", + "lru-cache": "^6.0.0", + "minimist": "^1.2.5", + "mqtt-packet": "^6.8.0", + "number-allocator": "^1.0.9", + "pump": "^3.0.0", + "readable-stream": "^3.6.0", + "reinterval": "^1.1.0", + "rfdc": "^1.3.0", + "split2": "^3.1.0", + "ws": "^7.5.5", + "xtend": "^4.0.2" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "mqtt-packet": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/mqtt-packet/-/mqtt-packet-6.10.0.tgz", + "integrity": "sha512-ja8+mFKIHdB1Tpl6vac+sktqy3gA8t9Mduom1BA75cI+R9AHnZOiaBQwpGiWnaVJLDGRdNhQmFaAqd7tkKSMGA==", + "requires": { + "bl": "^4.0.2", + "debug": "^4.1.1", + "process-nextick-args": "^2.0.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "nan": { + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.16.0.tgz", + "integrity": "sha512-UdAqHyFngu7TfQKsCBgAA6pWDkT8MAO7d0jyOecVhN5354xbLqdn8mV9Tat9gepAupm0bt2DbeaSC8vS52MuFA==" + }, + "napi-build-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", + "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==" + }, + "node-abi": { + "version": "3.22.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.22.0.tgz", + "integrity": "sha512-u4uAs/4Zzmp/jjsD9cyFYDXeISfUWaAVWshPmDZOFOv4Xl4SbzTXm53I04C2uRueYJ+0t5PEtLH/owbn2Npf/w==", + "requires": { + "semver": "^7.3.5" + } + }, + "nodemailer": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.7.tgz", + "integrity": "sha512-rUtR77ksqex/eZRLmQ21LKVH5nAAsVicAtAYudK7JgwenEDZ0UIQ1adUGqErz7sMkWYxWTTU1aeP2Jga6WQyJw==" + }, + "npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "number-allocator": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/number-allocator/-/number-allocator-1.0.14.tgz", + "integrity": "sha512-OrL44UTVAvkKdOdRQZIJpLkAdjXGTRda052sN4sO77bKEzYYqWKMBjQvrJFzqygI99gL6Z4u2xctPW1tB8ErvA==", + "requires": { + "debug": "^4.3.1", + "js-sdsl": "4.3.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==" + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==" + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==" + }, + "prebuild-install": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.0.tgz", + "integrity": "sha512-CNcMgI1xBypOyGqjp3wOc8AAo1nMhZS3Cwd3iHIxOdAUbb+YxdNuM4Z5iIrZ8RLvOsf3F3bl7b7xGq6DjQoNYA==", + "requires": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^1.0.1", + "node-abi": "^3.3.0", + "npmlog": "^4.0.1", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + } + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + } + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "reinterval": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reinterval/-/reinterval-1.1.0.tgz", + "integrity": "sha1-M2Hs+jymwYKDOA3Qu5VG85D17Oc=" + }, + "rfdc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==" + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "requires": { + "lru-cache": "^6.0.0" + } + }, + "serialport": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/serialport/-/serialport-9.2.8.tgz", + "integrity": "sha512-FsWpMQgSJxi93JgWl5xM1f9/Z8IjRJuaUEoHqLf8FPBLw7gMhInuHOBhI2onQufWIYPGTz3H3oGcu1nCaK1EfA==", + "requires": { + "@serialport/binding-mock": "9.2.4", + "@serialport/bindings": "9.2.8", + "@serialport/parser-byte-length": "9.2.4", + "@serialport/parser-cctalk": "9.2.4", + "@serialport/parser-delimiter": "9.2.4", + "@serialport/parser-inter-byte-timeout": "9.2.4", + "@serialport/parser-readline": "9.2.4", + "@serialport/parser-ready": "9.2.4", + "@serialport/parser-regex": "9.2.4", + "@serialport/stream": "9.2.4", + "debug": "^4.3.2" + } + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==" + }, + "simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "requires": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "split2": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", + "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", + "requires": { + "readable-stream": "^3.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==" + }, + "streamroller": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.1.1.tgz", + "integrity": "sha512-iPhtd9unZ6zKdWgMeYGfSBuqCngyJy1B/GPi/lTpwGpa3bajuX30GjUVd0/Tn/Xhg0mr4DOSENozz9Y06qyonQ==", + "requires": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "fs-extra": "^10.1.0" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" + }, + "tar-fs": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "requires": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "requires": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "total.js": { + "version": "3.4.13", + "resolved": "https://registry.npmjs.org/total.js/-/total.js-3.4.13.tgz", + "integrity": "sha512-lAH4gEixlPFbrE3xfKADAcHfO79IFq2wKa9GTsrgRzIR5MTg3mNH7+4IxvX1pK8faoYb/0oYSJ1YTsAa5hIFFQ==" + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, + "universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==" + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "requires": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "ws": { + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "requires": {} + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } + } +} diff --git a/RVO46/package.json b/RVO46/package.json new file mode 100755 index 0000000..7f7c795 --- /dev/null +++ b/RVO46/package.json @@ -0,0 +1,30 @@ +{ + "name": "emptyproject", + "description": "Total.js empty project.", + "version": "1.0.0", + "main": "debug.js", + "dependencies": { + "bitwise": "^2.1.0", + "easy-crc": "0.0.2", + "jsmodbus": "^4.0.6", + "log4js": "^6.3.0", + "moment": "^2.30.1", + "mqtt": "^4.2.6", + "nodemailer": "^6.9.7", + "serialport": "^9.2.8", + "total.js": "^3.4.13" + }, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "https://github.com/totaljs/emptyproject-flow" + }, + "keywords": [ + "empty", + "project" + ], + "author": "Peter Širka", + "license": "MIT" +} diff --git a/RVO46/release.js b/RVO46/release.js new file mode 100755 index 0000000..02d52ff --- /dev/null +++ b/RVO46/release.js @@ -0,0 +1,15 @@ +// =================================================== +// FOR PRODUCTION +// Total.js - framework for Node.js platform +// https://www.totaljs.com +// =================================================== + +const options = {'ip':'0.0.0.0', 'port':12345}; + +// options.ip = '127.0.0.1'; +// options.port = parseInt(process.argv[2]); +// options.config = { name: 'Total.js' }; +// options.sleep = 3000; + +require('total.js').http('release', options); +// require('total.js').cluster.http(5, 'release', options); diff --git a/RVO46/release.js.json b/RVO46/release.js.json new file mode 100755 index 0000000..7fc0fa3 --- /dev/null +++ b/RVO46/release.js.json @@ -0,0 +1,34 @@ +{ + "pid": 394, + "stats": [ + { + "id": null, + "version": { + "node": "v14.18.1", + "total": "3.4.13", + "app": "1.0.0" + }, + "pid": 394, + "thread": "", + "mode": "release", + "overload": 0, + "date": "2025-10-16T00:27:01.135Z", + "memory": 24, + "rm": 0, + "fm": 0, + "wm": 0, + "mm": 0, + "om": 2, + "em": 0, + "dbrm": 0, + "dbwm": 0, + "usage": 0, + "requests": 0, + "pending": 0, + "errors": 0, + "timeouts": 0, + "uptime": 723, + "online": 0 + } + ] +} \ No newline at end of file diff --git a/RVO46/report_data.log b/RVO46/report_data.log new file mode 100755 index 0000000..b5e1765 --- /dev/null +++ b/RVO46/report_data.log @@ -0,0 +1,151 @@ +{ + "name": "rvo_senica_46_10.0.0.133", + "time": "2025-10-15T13:25:16.091Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_46_10.0.0.133", + "time": "2025-10-15T14:25:16.090Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_46_10.0.0.133", + "time": "2025-10-15T15:25:16.090Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_46_10.0.0.133", + "time": "2025-10-15T17:33:01.119Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_46_10.0.0.133", + "time": "2025-10-15T18:33:01.119Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_46_10.0.0.133", + "time": "2025-10-15T19:33:01.119Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_46_10.0.0.133", + "time": "2025-10-15T20:33:01.120Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_46_10.0.0.133", + "time": "2025-10-15T21:33:01.119Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_46_10.0.0.133", + "time": "2025-10-15T22:33:01.119Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_46_10.0.0.133", + "time": "2025-10-15T23:33:01.120Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +} \ No newline at end of file From 33a0c880db01b75bf3ca7c84ec5722835307cf60 Mon Sep 17 00:00:00 2001 From: Jakub Klena Date: Thu, 16 Oct 2025 02:27:22 +0200 Subject: [PATCH 27/30] Backup senica-RVO47 on 16.10.2025 --- RVO47/addSwitch.py | 36 + RVO47/cloud_topic.py | 76 + RVO47/config | 12 + RVO47/createNode.py | 43 + RVO47/databases/accelerometer_db.js | 3055 ++++++++++++++++ RVO47/databases/modbus_config.js | 114 + RVO47/databases/nodes.table | 5 + .../nodes_original/nodes_original.table | 1 + RVO47/databases/notifications.table | 41 + RVO47/databases/pins.table | 14 + RVO47/databases/relays.table | 5 + RVO47/databases/settings.table | 2 + RVO47/databases/tbdata.nosql | 4 + RVO47/databases/tbdatacloud.nosql | 3 + RVO47/databases/total_energy.js | 38 + RVO47/debug.js | 16 + RVO47/err.txt | 33 + RVO47/flow/cloudmqttconnect.js | 357 ++ RVO47/flow/cmd_manager.js | 3071 ++++++++++++++++ RVO47/flow/code.js | 90 + RVO47/flow/comment.js | 11 + RVO47/flow/count.js | 60 + RVO47/flow/db_connector.js | 286 ++ RVO47/flow/db_init.js | 113 + RVO47/flow/debug.js | 100 + RVO47/flow/designer.json | 3102 +++++++++++++++++ RVO47/flow/dido_controller.js | 1486 ++++++++ RVO47/flow/helper/DataToTbHandler.js | 187 + RVO47/flow/helper/ErrorToServiceHandler.js | 91 + RVO47/flow/helper/db_helper.js | 44 + RVO47/flow/helper/logger.js | 30 + RVO47/flow/helper/md5.js | 5 + RVO47/flow/helper/notification_reporter.js | 121 + RVO47/flow/helper/register.js | 144 + RVO47/flow/helper/serialport_helper.js | 99 + RVO47/flow/helper/suncalc.js | 317 ++ RVO47/flow/helper/utils.js | 161 + RVO47/flow/httprequest.js | 137 + RVO47/flow/httpresponse.js | 76 + RVO47/flow/httproute.js | 326 ++ RVO47/flow/infosender.js | 81 + RVO47/flow/modbus_reader.js | 346 ++ RVO47/flow/monitorconsumption.js | 156 + RVO47/flow/monitordisk.js | 96 + RVO47/flow/monitormemory.js | 87 + RVO47/flow/nodesdb_changecheck.js | 77 + RVO47/flow/show_dbdata.js | 243 ++ RVO47/flow/slack_filter.js | 188 + RVO47/flow/thermometer.js | 99 + RVO47/flow/trigger.js | 79 + RVO47/flow/variables.txt | 0 RVO47/flow/virtualwirein.js | 43 + RVO47/flow/virtualwireout.js | 41 + RVO47/flow/wsmqttpublish.js | 448 +++ RVO47/monitor.txt | 2568 ++++++++++++++ RVO47/package-lock.json | 2139 ++++++++++++ RVO47/package.json | 30 + RVO47/release.js | 15 + RVO47/release.js.json | 34 + RVO47/report_data.log | 196 ++ 60 files changed, 20878 insertions(+) create mode 100755 RVO47/addSwitch.py create mode 100755 RVO47/cloud_topic.py create mode 100755 RVO47/config create mode 100755 RVO47/createNode.py create mode 100755 RVO47/databases/accelerometer_db.js create mode 100755 RVO47/databases/modbus_config.js create mode 100755 RVO47/databases/nodes.table create mode 100755 RVO47/databases/nodes_original/nodes_original.table create mode 100755 RVO47/databases/notifications.table create mode 100755 RVO47/databases/pins.table create mode 100755 RVO47/databases/relays.table create mode 100755 RVO47/databases/settings.table create mode 100755 RVO47/databases/tbdata.nosql create mode 100755 RVO47/databases/tbdatacloud.nosql create mode 100755 RVO47/databases/total_energy.js create mode 100755 RVO47/debug.js create mode 100755 RVO47/err.txt create mode 100755 RVO47/flow/cloudmqttconnect.js create mode 100755 RVO47/flow/cmd_manager.js create mode 100755 RVO47/flow/code.js create mode 100755 RVO47/flow/comment.js create mode 100755 RVO47/flow/count.js create mode 100755 RVO47/flow/db_connector.js create mode 100755 RVO47/flow/db_init.js create mode 100755 RVO47/flow/debug.js create mode 100755 RVO47/flow/designer.json create mode 100755 RVO47/flow/dido_controller.js create mode 100755 RVO47/flow/helper/DataToTbHandler.js create mode 100755 RVO47/flow/helper/ErrorToServiceHandler.js create mode 100755 RVO47/flow/helper/db_helper.js create mode 100755 RVO47/flow/helper/logger.js create mode 100755 RVO47/flow/helper/md5.js create mode 100755 RVO47/flow/helper/notification_reporter.js create mode 100755 RVO47/flow/helper/register.js create mode 100755 RVO47/flow/helper/serialport_helper.js create mode 100755 RVO47/flow/helper/suncalc.js create mode 100755 RVO47/flow/helper/utils.js create mode 100755 RVO47/flow/httprequest.js create mode 100755 RVO47/flow/httpresponse.js create mode 100755 RVO47/flow/httproute.js create mode 100755 RVO47/flow/infosender.js create mode 100755 RVO47/flow/modbus_reader.js create mode 100755 RVO47/flow/monitorconsumption.js create mode 100755 RVO47/flow/monitordisk.js create mode 100755 RVO47/flow/monitormemory.js create mode 100755 RVO47/flow/nodesdb_changecheck.js create mode 100755 RVO47/flow/show_dbdata.js create mode 100755 RVO47/flow/slack_filter.js create mode 100755 RVO47/flow/thermometer.js create mode 100755 RVO47/flow/trigger.js create mode 100755 RVO47/flow/variables.txt create mode 100755 RVO47/flow/virtualwirein.js create mode 100755 RVO47/flow/virtualwireout.js create mode 100755 RVO47/flow/wsmqttpublish.js create mode 100755 RVO47/monitor.txt create mode 100755 RVO47/package-lock.json create mode 100755 RVO47/package.json create mode 100755 RVO47/release.js create mode 100755 RVO47/release.js.json create mode 100755 RVO47/report_data.log diff --git a/RVO47/addSwitch.py b/RVO47/addSwitch.py new file mode 100755 index 0000000..c35e96b --- /dev/null +++ b/RVO47/addSwitch.py @@ -0,0 +1,36 @@ +import os + +def process_set_file(): + """ + Checks if /root/flowserver exists, reads set.txt, and modifies the second line. + """ + default_folder = "/root/flowserver" if os.path.exists("/root/flowserver") else "/home/unipi/flowserver" + flag = 1 if default_folder == "/root/flowserver" else 0 + + try: + with open("/home/unipi/flowserver/databases/settings.table", "r") as f: + lines = f.readlines() + + if len(lines) >= 2: + lines[0] = lines[0].rstrip('\n') + "|main_switch:boolean\n" + second_line = lines[1].strip() # remove trailing newline + last_pipe_index = second_line.rfind("|") + + if last_pipe_index != -1: + modified_line = second_line[:last_pipe_index + 1] + str(flag) + "|" + second_line[last_pipe_index + 1:] + lines[1] = modified_line + else: + print("Warning: No '|' character found in the second line of set.txt") + + with open("/home/unipi/flowserver/databases/settings.table", "w") as f: + f.writelines(lines) + else: + print("Warning: settings.table has less than two lines.") + + except FileNotFoundError: + print("Error: settings.table not found.") + except Exception as e: + print(e) + +# if __name__ == "__main__": +process_set_file() diff --git a/RVO47/cloud_topic.py b/RVO47/cloud_topic.py new file mode 100755 index 0000000..77c31f1 --- /dev/null +++ b/RVO47/cloud_topic.py @@ -0,0 +1,76 @@ +# import os +# +# def modify_file(file_path): +# """ +# Modifies the given file by: +# 1. Appending "|cloud_topic" to the first line. +# 2. Inserting the text from the third "." to the first "|" on the second line after the last "|" character. +# +# Args: +# file_path (str): The path to the file to be modified. +# """ +# +# with open(file_path, 'r+') as f: +# lines = f.readlines() +# +# # Modify the first line +# lines[0] += "|cloud_topic:string" +# +# # Modify the second line +# second_line = lines[1].strip() # Remove leading/trailing whitespace +# first_pipe_index = second_line.find('|') +# third_dot_index = second_line.find('.', second_line.find('.', second_line.find('.') + 1) + 1) +# text_to_insert = second_line[third_dot_index:first_pipe_index] +# +# last_pipe_index = second_line.rfind('|') +# lines[1] = second_line[:last_pipe_index + 1] + text_to_insert + "|" + second_line[last_pipe_index + 1:] +# +# print(first_pipe_index, third_dot_index, text_to_insert, last_pipe_index) +# # Write the modified lines back to the file +# # f.seek(0) +# # f.writelines(lines) +# # f.truncate() +# +# # Example usage: +# file_path = "settings.table" # Replace with the actual file path +# modify_file(file_path) +# + + +def modify_file(file_path): + """ + Modifies the given file by: + 1. Appending "|cloud_topic" to the first line. + 2. Inserting the text between the third "." and the second "|" on the second line after the last "|" character. + + Args: + file_path (str): The path to the file to be modified. + """ + + with open(file_path, 'r+') as f: + lines = f.readlines() + + first_line = lines[0].strip() + first_line += "|cloud_topic:string\n" + # Modify the first line + lines[0] = first_line + + # Modify the second line + second_line = lines[1].strip() # Remove leading/trailing whitespace + first_pipe_index = second_line.find('|') + second_pipe_index = second_line.find('|', first_pipe_index + 1) + third_dot_index = second_line.find('.', second_line.find('.', second_line.find('.') + 1) + 1) + text_to_insert = "u" + second_line[third_dot_index+1:second_pipe_index] + + last_pipe_index = second_line.rfind('|') + lines[1] = second_line[:last_pipe_index + 1] + text_to_insert + "|" + second_line[last_pipe_index + 1:] + + print(first_pipe_index, third_dot_index, text_to_insert, last_pipe_index) + # Write the modified lines back to the file + f.seek(0) + f.writelines(lines) + f.truncate() + +# Example usage: +file_path = "/home/unipi/flowserver/databases/settings.table" # Replace with the actual file path +modify_file(file_path) diff --git a/RVO47/config b/RVO47/config new file mode 100755 index 0000000..cd0a8a9 --- /dev/null +++ b/RVO47/config @@ -0,0 +1,12 @@ +name : Total.js Flow +default_timezone : Europe/Bratislava + +// Packages settings +package#flow (Object) : { url: '/' } + + +table.relays : line:number|tbname:string|contactor:number|profile:string +table.nodes : node:number|pole_number:string|node_type:string|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|project_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|cloud_topic:string|has_main_switch:boolean|daily_report:boolean|send_changed_node_numbers:boolean +table.pins : pin:string|type:string|line:number +table.notifications : key:string|weight:string|sk:string|en:string diff --git a/RVO47/createNode.py b/RVO47/createNode.py new file mode 100755 index 0000000..a8cea91 --- /dev/null +++ b/RVO47/createNode.py @@ -0,0 +1,43 @@ +print("zaciname") +import re, json + +search_str = '|' +final = [] +counter = 1 +with open("/home/unipi/flowserver/databases/nodes.table", 'r') as file: +# with open("/home/rasta5man/dev/oms/flowserver/databases/nodes.table", 'r') as file: + # Read each line in the file + for line in file: + # Print each line + line = line.strip() + print(line) + if counter != 1: + i = [m.start() for m in re.finditer(re.escape(search_str), line)] + node = line[ i[0] + 1 : i[1] ] + tbname = line[ i[3] + 1 : i[4] ] + final.append({node:tbname}) + counter += 1 +print(json.dumps(final)) +f = open("/home/unipi/flowserver/databases/nodes_original/nodes_original.table", "w") +f.write(json.dumps(final)) +f.close() + + +# +# # ``d`` has to be replaced with a different character +# old_character = "'" +# +# # ``t`` will replace ``d` +# new_character = '"' +# resultant_string = 0; +# with open("/home/unipi/flowserver/databases/nodes_original/nodes_original.table", 'r') as file: +# for line in file: +# resultant_string = re.sub("'", '"', line) +# +# resultant_string = re.sub(" ", "", resultant_string) +# print(resultant_string) +# +# f = open("/home/unipi/flowserver/databases/nodes_original/nodes_original.table", "w") +# f.write(str(resultant_string)) +# f.close() +# diff --git a/RVO47/databases/accelerometer_db.js b/RVO47/databases/accelerometer_db.js new file mode 100755 index 0000000..fdfc7fd --- /dev/null +++ b/RVO47/databases/accelerometer_db.js @@ -0,0 +1,3055 @@ +let naklony = { + "3993": { "label": "1/3A", "naklon": 0 }, + "3989": { "label": "1/3B", "naklon": 15 }, + "3976": { "label": "1/1", "naklon": 0 }, + "4181": { "label": "1/2", "naklon": 0 }, + "4376": { "label": "1/4", "naklon": 15 }, + "3868": { "label": "1/5", "naklon": 15 }, + "3728": { "label": "1/6", "naklon": 15 }, + "3730": { "label": "1/7", "naklon": 0 }, + "4374": { "label": "1/8", "naklon": 0 }, + "3718": { "label": "1/9", "naklon": 15 }, + "4375": { "label": "1/10", "naklon": 15 }, + "4172": { "label": "1/11", "naklon": 15 }, + "4176": { "label": "1/12", "naklon": 15 }, + "3800": { "label": "2/1", "naklon": 5 }, + "3823": { "label": "2/2", "naklon": 5 }, + "3905": { "label": "2/3", "naklon": 5 }, + "3803": { "label": "2/4", "naklon": 5 }, + "3817": { "label": "2/5", "naklon": 5 }, + "3818": { "label": "2/6", "naklon": 5 }, + "3811": { "label": "2/7", "naklon": 5 }, + "3915": { "label": "2/8", "naklon": 5 }, + "3843": { "label": "2/9", "naklon": 10 }, + "3827": { "label": "2/10", "naklon": 10 }, + "4220": { "label": "2/11", "naklon": 10 }, + "3826": { "label": "2/12", "naklon": 10 }, + "3834": { "label": "2/13", "naklon": 10 }, + "3838": { "label": "2/14", "naklon": 10 }, + "2823": { "label": "2/15", "naklon": 10 }, + "3750": { "label": "2/16", "naklon": 10 }, + "3378": { "label": "2/17", "naklon": 0 }, + "3376": { "label": "2/18", "naklon": 0 }, + "3379": { "label": "2/19", "naklon": 0 }, + "3285": { "label": "2/20", "naklon": 0 }, + "3382": { "label": "2/21", "naklon": 0 }, + "3383": { "label": "2/22", "naklon": 0 }, + "3375": { "label": "2/24", "naklon": 0 }, + "3381": { "label": "2/25", "naklon": 0 }, + "3380": { "label": "2/26", "naklon": 0 }, + "3828": { "label": "2/27", "naklon": 10 }, + "3377": { "label": "2/28", "naklon": 0 }, + "3591": { "label": "7/1", "naklon": 0 }, + "3587": { "label": "7/2", "naklon": 0 }, + "3468": { "label": "7/3", "naklon": 0 }, + "3466": { "label": "7/4", "naklon": 0 }, + "3474": { "label": "7/5", "naklon": 0 }, + "3481": { "label": "7/6", "naklon": 0 }, + "3589": { "label": "7/7", "naklon": 0 }, + "3472": { "label": "7/8", "naklon": 0 }, + "3473": { "label": "7/9", "naklon": 0 }, + "3584": { "label": "7/10", "naklon": 0 }, + "3571": { "label": "7/11", "naklon": 0 }, + "3476": { "label": "7/12", "naklon": 0 }, + "3590": { "label": "7/13", "naklon": 0 }, + "3478": { "label": "7/14", "naklon": 0 }, + "3471": { "label": "7/15", "naklon": 0 }, + "3467": { "label": "7/16", "naklon": 0 }, + "3479": { "label": "7/17", "naklon": 0 }, + "3480": { "label": "7/18", "naklon": 0 }, + "3477": { "label": "7/19", "naklon": 0 }, + "3362": { "label": "12/1", "naklon": 0 }, + "3355": { "label": "12/2", "naklon": 0 }, + "3356": { "label": "12/3", "naklon": 0 }, + "3349": { "label": "12/4", "naklon": 0 }, + "3357": { "label": "12/5", "naklon": 0 }, + "3350": { "label": "12/6", "naklon": 0 }, + "3353": { "label": "12/7", "naklon": 0 }, + "3539": { "label": "12/8", "naklon": 0 }, + "3050": { "label": "12/9", "naklon": 0 }, + "3361": { "label": "12/10", "naklon": 0 }, + "3360": { "label": "12/11", "naklon": 0 }, + "3358": { "label": "12/12", "naklon": 0 }, + "3541": { "label": "12/13", "naklon": 0 }, + "3551": { "label": "12/14", "naklon": 0 }, + "3514": { "label": "12/15", "naklon": 0 }, + "3547": { "label": "12/16", "naklon": 0 }, + "3562": { "label": "12/17", "naklon": 0 }, + "3525": { "label": "12/18", "naklon": 0 }, + "3558": { "label": "12/19", "naklon": 0 }, + "3511": { "label": "12/20", "naklon": 0 }, + "3058": { "label": "12/21", "naklon": 0 }, + "3062": { "label": "12/22", "naklon": 0 }, + "3070": { "label": "12/23", "naklon": 0 }, + "3447": { "label": "12/24", "naklon": 0 }, + "3056": { "label": "12/25", "naklon": 0 }, + "3057": { "label": "12/26", "naklon": 0 }, + "3071": { "label": "12/27", "naklon": 0 }, + "3061": { "label": "12/28", "naklon": 0 }, + "3069": { "label": "12/29", "naklon": 0 }, + "3077": { "label": "12/30", "naklon": 0 }, + "3080": { "label": "12/31", "naklon": 0 }, + "3081": { "label": "12/32", "naklon": 0 }, + "3078": { "label": "12/33", "naklon": 0 }, + "4037": { "label": "12/34", "naklon": 0 }, + "3067": { "label": "12/35", "naklon": 0 }, + "3051": { "label": "12/36", "naklon": 0 }, + "2924": { "label": "12/37", "naklon": 0 }, + "3060": { "label": "12/38", "naklon": 0 }, + "3073": { "label": "12/39", "naklon": 0 }, + "3469": { "label": "12/40", "naklon": 0 }, + "2923": { "label": "12/41", "naklon": 0 }, + "2925": { "label": "12/42", "naklon": 0 }, + "3359": { "label": "12/43", "naklon": 0 }, + "3055": { "label": "12/44", "naklon": 0 }, + "2922": { "label": "12/45", "naklon": 0 }, + "3084": { "label": "12/46", "naklon": 0 }, + "3064": { "label": "12/47", "naklon": 0 }, + "3066": { "label": "12/48", "naklon": 0 }, + "3072": { "label": "12/49", "naklon": 0 }, + "3415": { "label": "13/13A", "naklon": 0 }, + "3409": { "label": "13/13B", "naklon": 0 }, + "3399": { "label": "13/13C", "naklon": 0 }, + "3410": { "label": "13/29A", "naklon": 0 }, + "3407": { "label": "13/29B", "naklon": 0 }, + "3405": { "label": "13/34A", "naklon": 0 }, + "3404": { "label": "13/34B", "naklon": 0 }, + "3392": { "label": "13/45A", "naklon": 0 }, + "3386": { "label": "13/45B", "naklon": 0 }, + "3303": { "label": "13/60A", "naklon": 3 }, + "3302": { "label": "13/60B", "naklon": 3 }, + "3319": { "label": "13/70A", "naklon": 6 }, + "3317": { "label": "13/70B", "naklon": 6 }, + "3326": { "label": "13/70C", "naklon": 6 }, + "3351": { "label": "13/73A", "naklon": 6 }, + "3313": { "label": "13/73B", "naklon": 6 }, + "3316": { "label": "13/83A", "naklon": 0 }, + "3320": { "label": "13/83B", "naklon": 0 }, + "3336": { "label": "13/95A", "naklon": 0 }, + "3323": { "label": "13/95B", "naklon": 0 }, + "3339": { "label": "13/98A", "naklon": 0 }, + "3333": { "label": "13/98B", "naklon": 0 }, + "3425": { "label": "13/1", "naklon": 0 }, + "3419": { "label": "13/2", "naklon": 0 }, + "3416": { "label": "13/3", "naklon": 0 }, + "3332": { "label": "13/4", "naklon": 0 }, + "3422": { "label": "13/5", "naklon": 0 }, + "3417": { "label": "13/6", "naklon": 0 }, + "3418": { "label": "13/7", "naklon": 0 }, + "3424": { "label": "13/8", "naklon": 0 }, + "3334": { "label": "13/9", "naklon": 0 }, + "4363": { "label": "13/10", "naklon": 0 }, + "3423": { "label": "13/11", "naklon": 0 }, + "3406": { "label": "13/12", "naklon": 0 }, + "3411": { "label": "13/14", "naklon": 0 }, + "3412": { "label": "13/15", "naklon": 0 }, + "3413": { "label": "13/16", "naklon": 0 }, + "3414": { "label": "13/17", "naklon": 0 }, + "3391": { "label": "13/18", "naklon": 0 }, + "3370": { "label": "13/19", "naklon": 0 }, + "3369": { "label": "13/20", "naklon": 0 }, + "3408": { "label": "13/21", "naklon": 0 }, + "3393": { "label": "13/22", "naklon": 0 }, + "3128": { "label": "13/23", "naklon": 0 }, + "3197": { "label": "13/24", "naklon": 0 }, + "4364": { "label": "13/25", "naklon": 0 }, + "3155": { "label": "13/26", "naklon": 0 }, + "3196": { "label": "13/27", "naklon": 0 }, + "3144": { "label": "13/28", "naklon": 0 }, + "3150": { "label": "13/30", "naklon": 0 }, + "3390": { "label": "13/31", "naklon": 0 }, + "3401": { "label": "13/32", "naklon": 0 }, + "3275": { "label": "13/33", "naklon": 0 }, + "3371": { "label": "13/35", "naklon": 0 }, + "3389": { "label": "13/36", "naklon": 0 }, + "3388": { "label": "13/37", "naklon": 0 }, + "3365": { "label": "13/38", "naklon": 0 }, + "3363": { "label": "13/39", "naklon": 0 }, + "3397": { "label": "13/40", "naklon": 0 }, + "3567": { "label": "13/40/1", "naklon": 0 }, + "3387": { "label": "13/41", "naklon": 0 }, + "3403": { "label": "13/42", "naklon": 0 }, + "3147": { "label": "13/43", "naklon": 0 }, + "3141": { "label": "13/44", "naklon": 0 }, + "3364": { "label": "13/46", "naklon": 0 }, + "3367": { "label": "13/47", "naklon": 0 }, + "3368": { "label": "13/48", "naklon": 0 }, + "3402": { "label": "13/49", "naklon": 0 }, + "3366": { "label": "13/50", "naklon": 0 }, + "3395": { "label": "13/51", "naklon": 0 }, + "3372": { "label": "13/52", "naklon": 0 }, + "3394": { "label": "13/53", "naklon": 0 }, + "3308": { "label": "13/54", "naklon": 0 }, + "3847": { "label": "13/54/1", "naklon": 0 }, + "3312": { "label": "13/55", "naklon": 3 }, + "3309": { "label": "13/56", "naklon": 3 }, + "3311": { "label": "13/57", "naklon": 3 }, + "3310": { "label": "13/58", "naklon": 3 }, + "4365": { "label": "13/59", "naklon": 3 }, + "4093": { "label": "13/60/1", "naklon": 3 }, + "3304": { "label": "13/61", "naklon": 3 }, + "3307": { "label": "13/62", "naklon": 3 }, + "3271": { "label": "13/63", "naklon": 3 }, + "3301": { "label": "13/64", "naklon": 3 }, + "4366": { "label": "13/65", "naklon": 3 }, + "3300": { "label": "13/66", "naklon": 3 }, + "3185": { "label": "13/67", "naklon": 0 }, + "3184": { "label": "13/68", "naklon": 0 }, + "3188": { "label": "13/69", "naklon": 0 }, + "3343": { "label": "13/71", "naklon": 6 }, + "3819": { "label": "13/71/1", "naklon": 6 }, + "3880": { "label": "13/71/2", "naklon": 6 }, + "3348": { "label": "13/72", "naklon": 6 }, + "3344": { "label": "13/74", "naklon": 6 }, + "3346": { "label": "13/75", "naklon": 6 }, + "3597": { "label": "13/75/1", "naklon": 6 }, + "3345": { "label": "13/76", "naklon": 6 }, + "3322": { "label": "13/77", "naklon": 0 }, + "3325": { "label": "13/78", "naklon": 0 }, + "4310": { "label": "13/78/1", "naklon": 0 }, + "3315": { "label": "13/79", "naklon": 0 }, + "3328": { "label": "13/80", "naklon": 0 }, + "3321": { "label": "13/81", "naklon": 0 }, + "3324": { "label": "13/82", "naklon": 0 }, + "3140": { "label": "13/84", "naklon": 0 }, + "3153": { "label": "13/85", "naklon": 0 }, + "3145": { "label": "13/86", "naklon": 0 }, + "3134": { "label": "13/87", "naklon": 0 }, + "3151": { "label": "13/88", "naklon": 0 }, + "3143": { "label": "13/89", "naklon": 0 }, + "3318": { "label": "13/90", "naklon": 0 }, + "3347": { "label": "13/91", "naklon": 0 }, + "3314": { "label": "13/94", "naklon": 0 }, + "3331": { "label": "13/96", "naklon": 0 }, + "3327": { "label": "13/97", "naklon": 0 }, + "3329": { "label": "13/99", "naklon": 0 }, + "3337": { "label": "13/100", "naklon": 0 }, + "3330": { "label": "13/101", "naklon": 0 }, + "3335": { "label": "13/102", "naklon": 0 }, + "3420": { "label": "13/103", "naklon": 0 }, + "3421": { "label": "13/104", "naklon": 0 }, + "4361": { "label": "13/105", "naklon": 0 }, + "4362": { "label": "13/106", "naklon": 0 }, + "3526": { "label": "13/107", "naklon": 0 }, + "4424": { "label": "13/108", "naklon": null }, + "3561": { "label": "13/109", "naklon": null }, + "3527": { "label": "13/110", "naklon": null }, + "3521": { "label": "13/111", "naklon": null }, + "3552": { "label": "13/112", "naklon": null }, + "3544": { "label": "13/113", "naklon": null }, + "3534": { "label": "13/114", "naklon": null }, + "3516": { "label": "13/115", "naklon": null }, + "3513": { "label": "13/116", "naklon": null }, + "3565": { "label": "13/117", "naklon": null }, + "3866": { "label": "13/118", "naklon": null }, + "3136": { "label": "14/1", "naklon": 0 }, + "3137": { "label": "14/2", "naklon": 0 }, + "3135": { "label": "14/3", "naklon": 0 }, + "3149": { "label": "14/4", "naklon": 0 }, + "3142": { "label": "14/5", "naklon": 0 }, + "3342": { "label": "14/6", "naklon": 0 }, + "3340": { "label": "14/7", "naklon": 0 }, + "3152": { "label": "14/8", "naklon": 0 }, + "3886": { "label": "14/9", "naklon": 0 }, + "3341": { "label": "14/10", "naklon": null }, + "3352": { "label": "14/11", "naklon": null }, + "3396": { "label": "15/1", "naklon": 5 }, + "2784": { "label": "15/2", "naklon": 5 }, + "2788": { "label": "15/3", "naklon": 5 }, + "2801": { "label": "15/4", "naklon": 5 }, + "2815": { "label": "15/5", "naklon": 5 }, + "2829": { "label": "15/6", "naklon": 5 }, + "2796": { "label": "15/7", "naklon": 5 }, + "2803": { "label": "15/8", "naklon": 5 }, + "4304": { "label": "15/8/1", "naklon": 5 }, + "4311": { "label": "15/8/2", "naklon": 5 }, + "2821": { "label": "15/9", "naklon": 5 }, + "3400": { "label": "15/10", "naklon": 5 }, + "2799": { "label": "15/11", "naklon": 5 }, + "2804": { "label": "15/12", "naklon": 5 }, + "4303": { "label": "15/12/1", "naklon": 5 }, + "4309": { "label": "15/12/2", "naklon": 5 }, + "2806": { "label": "15/13", "naklon": 5 }, + "2787": { "label": "15/14", "naklon": 5 }, + "2809": { "label": "15/15", "naklon": 5 }, + "2814": { "label": "15/16", "naklon": 0 }, + "3934": { "label": "15/17", "naklon": 0 }, + "3192": { "label": "15/18", "naklon": 0 }, + "2812": { "label": "15/19", "naklon": 0 }, + "4070": { "label": "15/20", "naklon": 0 }, + "2826": { "label": "15/21", "naklon": 0 }, + "2808": { "label": "15/22", "naklon": 3 }, + "2795": { "label": "15/23", "naklon": 3 }, + "2807": { "label": "15/24", "naklon": 3 }, + "2831": { "label": "15/25", "naklon": 0 }, + "2862": { "label": "15/26", "naklon": null }, + "2861": { "label": "15/27", "naklon": 0 }, + "2866": { "label": "15/28", "naklon": 0 }, + "3546": { "label": "15/28/1", "naklon": 0 }, + "4146": { "label": "15/29", "naklon": 0 }, + "3001": { "label": "15/29/1", "naklon": 0 }, + "2835": { "label": "15/30", "naklon": 0 }, + "2874": { "label": "15/31", "naklon": 0 }, + "2852": { "label": "15/32", "naklon": 0 }, + "2851": { "label": "15/33", "naklon": 0 }, + "3560": { "label": "15/33/1", "naklon": 0 }, + "2858": { "label": "15/34", "naklon": 0 }, + "4306": { "label": "15/34/1", "naklon": 0 }, + "2856": { "label": "15/35", "naklon": 0 }, + "2847": { "label": "15/36", "naklon": 0 }, + "3556": { "label": "15/36/1", "naklon": 0 }, + "3950": { "label": "15/37", "naklon": 0 }, + "2848": { "label": "15/38", "naklon": 0 }, + "2863": { "label": "15/39", "naklon": 0 }, + "4313": { "label": "15/39/1", "naklon": 0 }, + "2873": { "label": "15/40", "naklon": 0 }, + "2984": { "label": "15/40/1", "naklon": 0 }, + "2854": { "label": "15/41", "naklon": 0 }, + "2859": { "label": "15/42", "naklon": 0 }, + "2872": { "label": "15/43", "naklon": 0 }, + "2849": { "label": "15/44", "naklon": 0 }, + "2864": { "label": "15/45", "naklon": 0 }, + "3553": { "label": "15/46", "naklon": null }, + "3021": { "label": "15/47", "naklon": null }, + "3008": { "label": "15/47/1", "naklon": null }, + "3017": { "label": "15/48", "naklon": null }, + "3014": { "label": "15/49", "naklon": null }, + "2981": { "label": "15/50", "naklon": null }, + "3020": { "label": "15/51", "naklon": null }, + "3027": { "label": "15/52", "naklon": null }, + "3006": { "label": "15/53", "naklon": null }, + "3012": { "label": "15/54", "naklon": null }, + "2738": { "label": "15/55", "naklon": 0 }, + "2725": { "label": "15/56", "naklon": 0 }, + "3016": { "label": "15/57", "naklon": null }, + "3005": { "label": "15/58", "naklon": null }, + "3009": { "label": "15/58/1", "naklon": null }, + "3010": { "label": "15/59", "naklon": 0 }, + "3538": { "label": "15/59/1", "naklon": 0 }, + "4145": { "label": "15/59/2", "naklon": 0 }, + "2713": { "label": "15/60", "naklon": 0 }, + "2789": { "label": "15/61", "naklon": 0 }, + "2736": { "label": "15/62", "naklon": 0 }, + "2739": { "label": "15/63", "naklon": 0 }, + "4346": { "label": "15/64", "naklon": 0 }, + "2731": { "label": "15/65", "naklon": 0 }, + "2818": { "label": "15/66", "naklon": 0 }, + "3557": { "label": "15/66/1", "naklon": 0 }, + "2822": { "label": "15/67", "naklon": 0 }, + "2833": { "label": "15/68", "naklon": 0 }, + "2834": { "label": "15/69", "naklon": 0 }, + "3097": { "label": "15/70", "naklon": 0 }, + "2824": { "label": "15/71", "naklon": 0 }, + "2828": { "label": "15/72", "naklon": 0 }, + "2600": { "label": "15/73", "naklon": 0 }, + "4314": { "label": "15/73/1", "naklon": 0 }, + "2832": { "label": "15/74", "naklon": 0 }, + "4360": { "label": "15/75", "naklon": 0 }, + "2846": { "label": "15/76", "naklon": 0 }, + "2584": { "label": "15/77", "naklon": 0 }, + "2843": { "label": "15/78", "naklon": 0 }, + "4308": { "label": "15/78/1", "naklon": 0 }, + "4144": { "label": "15/79", "naklon": null }, + "2844": { "label": "15/80", "naklon": 0 }, + "2842": { "label": "15/81", "naklon": 0 }, + "2838": { "label": "15/82", "naklon": 0 }, + "2837": { "label": "15/83", "naklon": null }, + "3555": { "label": "15/83/1", "naklon": null }, + "2839": { "label": "15/84", "naklon": 0 }, + "2830": { "label": "15/85", "naklon": 0 }, + "4066": { "label": "15/86", "naklon": 0 }, + "2836": { "label": "15/87", "naklon": 0 }, + "2911": { "label": "15/88", "naklon": 0 }, + "2825": { "label": "15/89", "naklon": 0 }, + "2811": { "label": "15/90", "naklon": 0 }, + "3740": { "label": "15/94", "naklon": 15 }, + "2734": { "label": "15/95", "naklon": 15 }, + "3105": { "label": "15/96", "naklon": 15 }, + "2732": { "label": "15/97", "naklon": 15 }, + "2727": { "label": "15/98", "naklon": 15 }, + "2735": { "label": "15/99", "naklon": 15 }, + "3926": { "label": "15/100", "naklon": 15 }, + "2918": { "label": "15/101", "naklon": 0 }, + "2705": { "label": "15/102", "naklon": 10 }, + "2708": { "label": "15/103", "naklon": 10 }, + "2721": { "label": "15/104", "naklon": 10 }, + "2719": { "label": "15/105", "naklon": 10 }, + "2919": { "label": "15/106", "naklon": 10 }, + "3101": { "label": "15/107", "naklon": 10 }, + "2853": { "label": "15/108", "naklon": 10 }, + "2715": { "label": "15/109", "naklon": 10 }, + "2712": { "label": "15/110", "naklon": 0 }, + "2711": { "label": "15/111", "naklon": 0 }, + "2709": { "label": "15/112", "naklon": 0 }, + "2710": { "label": "15/113", "naklon": 0 }, + "2907": { "label": "15/114", "naklon": 0 }, + "2906": { "label": "15/115", "naklon": 0 }, + "2908": { "label": "15/116", "naklon": 0 }, + "2901": { "label": "15/117", "naklon": 0 }, + "2913": { "label": "15/118", "naklon": 0 }, + "3656": { "label": "15/119", "naklon": 0 }, + "2781": { "label": "15/120", "naklon": 0 }, + "2802": { "label": "15/121", "naklon": 0 }, + "2791": { "label": "15/122", "naklon": 0 }, + "2783": { "label": "15/123", "naklon": 0 }, + "2794": { "label": "15/124", "naklon": 0 }, + "3139": { "label": "15/125", "naklon": 0 }, + "3229": { "label": "15/126", "naklon": 5 }, + "3239": { "label": "15/127", "naklon": 5 }, + "3230": { "label": "15/128", "naklon": 5 }, + "4016": { "label": "15/129", "naklon": null }, + "3608": { "label": "16/16A", "naklon": 0 }, + "4151": { "label": "16/16B", "naklon": 0 }, + "3710": { "label": "16/1", "naklon": 0 }, + "3726": { "label": "16/2", "naklon": 0 }, + "3743": { "label": "16/3", "naklon": 0 }, + "3724": { "label": "16/4", "naklon": 0 }, + "3712": { "label": "16/5", "naklon": 0 }, + "3739": { "label": "16/6", "naklon": 0 }, + "3742": { "label": "16/7", "naklon": 0 }, + "3731": { "label": "16/8", "naklon": 0 }, + "3727": { "label": "16/9", "naklon": 0 }, + "3729": { "label": "16/10", "naklon": 0 }, + "3736": { "label": "16/11", "naklon": 0 }, + "3713": { "label": "16/12", "naklon": 0 }, + "3715": { "label": "16/13", "naklon": 0 }, + "3733": { "label": "16/14", "naklon": 0 }, + "3732": { "label": "16/15", "naklon": 0 }, + "3634": { "label": "16/17", "naklon": 0 }, + "3610": { "label": "16/18", "naklon": 0 }, + "3626": { "label": "16/19", "naklon": 0 }, + "3618": { "label": "16/20", "naklon": 0 }, + "3619": { "label": "16/21", "naklon": 0 }, + "3628": { "label": "16/22", "naklon": 0 }, + "3615": { "label": "16/23", "naklon": 0 }, + "3609": { "label": "16/24", "naklon": 0 }, + "3606": { "label": "16/25", "naklon": 0 }, + "3624": { "label": "16/26", "naklon": 0 }, + "3627": { "label": "16/27", "naklon": 0 }, + "3607": { "label": "16/28", "naklon": 0 }, + "4370": { "label": "16/29", "naklon": 0 }, + "3692": { "label": "16/30", "naklon": 0 }, + "3614": { "label": "16/31", "naklon": 0 }, + "3623": { "label": "16/32", "naklon": 0 }, + "4373": { "label": "16/33", "naklon": 0 }, + "3620": { "label": "16/34", "naklon": 0 }, + "3685": { "label": "16/35", "naklon": 0 }, + "3616": { "label": "16/36", "naklon": 0 }, + "3686": { "label": "16/37", "naklon": 0 }, + "3688": { "label": "16/38", "naklon": 0 }, + "3684": { "label": "16/39", "naklon": 0 }, + "3825": { "label": "16/40", "naklon": 0 }, + "3865": { "label": "16/41", "naklon": 0 }, + "3824": { "label": "16/42", "naklon": 0 }, + "3871": { "label": "16/43", "naklon": 0 }, + "3801": { "label": "16/44", "naklon": 0 }, + "3862": { "label": "16/45", "naklon": 0 }, + "3876": { "label": "16/46", "naklon": 0 }, + "3861": { "label": "16/47", "naklon": 0 }, + "4215": { "label": "16/48", "naklon": 0 }, + "3605": { "label": "16/49", "naklon": 10 }, + "3603": { "label": "16/50", "naklon": 10 }, + "3592": { "label": "16/51", "naklon": 10 }, + "3598": { "label": "16/52", "naklon": 10 }, + "3594": { "label": "16/53", "naklon": 10 }, + "3593": { "label": "16/54", "naklon": 10 }, + "3630": { "label": "16/55", "naklon": 10 }, + "3763": { "label": "16/56", "naklon": 10 }, + "3746": { "label": "16/57", "naklon": 10 }, + "3699": { "label": "16/58", "naklon": 0 }, + "3698": { "label": "16/59", "naklon": 0 }, + "3709": { "label": "16/60", "naklon": null }, + "3708": { "label": "16/61", "naklon": 0 }, + "3703": { "label": "16/62", "naklon": null }, + "3700": { "label": "16/63", "naklon": 0 }, + "3701": { "label": "16/64", "naklon": null }, + "3704": { "label": "16/65", "naklon": 0 }, + "3707": { "label": "16/66", "naklon": null }, + "3810": { "label": "16/67", "naklon": 0 }, + "4208": { "label": "16/68", "naklon": null }, + "3867": { "label": "16/69", "naklon": 0 }, + "4372": { "label": "16/70", "naklon": null }, + "3881": { "label": "16/71", "naklon": 0 }, + "4204": { "label": "16/72", "naklon": null }, + "3869": { "label": "16/73", "naklon": 0 }, + "4202": { "label": "16/74", "naklon": null }, + "3830": { "label": "16/75", "naklon": 0 }, + "3870": { "label": "16/76", "naklon": null }, + "3964": { "label": "16/77", "naklon": 0 }, + "3849": { "label": "16/78", "naklon": 0 }, + "3694": { "label": "16/79", "naklon": null }, + "3717": { "label": "16/80", "naklon": 0 }, + "3877": { "label": "16/81", "naklon": null }, + "3755": { "label": "16/82", "naklon": 0 }, + "3725": { "label": "16/83", "naklon": null }, + "3716": { "label": "16/84", "naklon": 0 }, + "3696": { "label": "16/85", "naklon": null }, + "3702": { "label": "16/86", "naklon": 0 }, + "3706": { "label": "16/87", "naklon": null }, + "3850": { "label": "16/88", "naklon": 0 }, + "3848": { "label": "16/89", "naklon": null }, + "3737": { "label": "16/90", "naklon": null }, + "3705": { "label": "16/91", "naklon": 0 }, + "3723": { "label": "16/92", "naklon": null }, + "3842": { "label": "16/93", "naklon": 0 }, + "3735": { "label": "16/94", "naklon": null }, + "3719": { "label": "16/95", "naklon": 0 }, + "3697": { "label": "16/96", "naklon": 0 }, + "3711": { "label": "16/97", "naklon": 0 }, + "4107": { "label": "16/98", "naklon": null }, + "4112": { "label": "16/99", "naklon": 5 }, + "4106": { "label": "16/100", "naklon": 5 }, + "4111": { "label": "16/101", "naklon": 5 }, + "4091": { "label": "16/102", "naklon": null }, + "4104": { "label": "16/103", "naklon": 5 }, + "4094": { "label": "16/104", "naklon": null }, + "4089": { "label": "16/105", "naklon": 5 }, + "4095": { "label": "16/106", "naklon": null }, + "4102": { "label": "16/107", "naklon": 5 }, + "4105": { "label": "16/108", "naklon": null }, + "3859": { "label": "16/109", "naklon": null }, + "4090": { "label": "16/110", "naklon": 5 }, + "4110": { "label": "16/111", "naklon": null }, + "4097": { "label": "16/112", "naklon": 5 }, + "4099": { "label": "16/113", "naklon": null }, + "4096": { "label": "16/114", "naklon": null }, + "4101": { "label": "16/115", "naklon": 5 }, + "4109": { "label": "16/116", "naklon": null }, + "4092": { "label": "16/117", "naklon": 5 }, + "3631": { "label": "16/118", "naklon": null }, + "3632": { "label": "16/119", "naklon": 0 }, + "3641": { "label": "16/120", "naklon": null }, + "3638": { "label": "16/121", "naklon": 0 }, + "3637": { "label": "16/122", "naklon": null }, + "4142": { "label": "16/123", "naklon": null }, + "4147": { "label": "16/124", "naklon": 5 }, + "4139": { "label": "16/125", "naklon": 5 }, + "3172": { "label": "20/30A", "naklon": 2 }, + "3164": { "label": "20/30B", "naklon": 2 }, + "3247": { "label": "20/1", "naklon": 10 }, + "3296": { "label": "20/2", "naklon": 10 }, + "3246": { "label": "20/3", "naklon": 10 }, + "3270": { "label": "20/4", "naklon": 10 }, + "3294": { "label": "20/5", "naklon": 10 }, + "3298": { "label": "20/6", "naklon": 10 }, + "3297": { "label": "20/7", "naklon": 10 }, + "3293": { "label": "20/8", "naklon": 10 }, + "3299": { "label": "20/9", "naklon": 10 }, + "3295": { "label": "20/10", "naklon": 10 }, + "3244": { "label": "20/11", "naklon": 10 }, + "3249": { "label": "20/12", "naklon": 10 }, + "3268": { "label": "20/13", "naklon": 10 }, + "3245": { "label": "20/14", "naklon": 10 }, + "3278": { "label": "20/15", "naklon": 10 }, + "3280": { "label": "20/16", "naklon": 10 }, + "3292": { "label": "20/17", "naklon": 10 }, + "3287": { "label": "20/18", "naklon": 10 }, + "3282": { "label": "20/19", "naklon": 10 }, + "3273": { "label": "20/20", "naklon": 0 }, + "3157": { "label": "20/21", "naklon": 0 }, + "3283": { "label": "20/22", "naklon": 0 }, + "3159": { "label": "20/23", "naklon": 0 }, + "3289": { "label": "20/24", "naklon": 0 }, + "3163": { "label": "20/25", "naklon": 0 }, + "3126": { "label": "20/26", "naklon": 0 }, + "3171": { "label": "20/27", "naklon": 0 }, + "3162": { "label": "20/28", "naklon": 0 }, + "3279": { "label": "20/29", "naklon": 10 }, + "3173": { "label": "20/31", "naklon": 0 }, + "3127": { "label": "20/32", "naklon": 0 }, + "3131": { "label": "20/33", "naklon": 0 }, + "3129": { "label": "20/34", "naklon": 0 }, + "3276": { "label": "20/35", "naklon": 2 }, + "3290": { "label": "20/36", "naklon": 2 }, + "3132": { "label": "20/37", "naklon": 0 }, + "3138": { "label": "20/38", "naklon": 0 }, + "3272": { "label": "20/39", "naklon": 0 }, + "3291": { "label": "20/40", "naklon": 0 }, + "3277": { "label": "20/41", "naklon": 10 }, + "3286": { "label": "20/42", "naklon": 10 }, + "3281": { "label": "20/43", "naklon": 10 }, + "3288": { "label": "20/44", "naklon": 10 }, + "3284": { "label": "20/45", "naklon": 10 }, + "3167": { "label": "20/46", "naklon": 10 }, + "3872": { "label": "20/47", "naklon": 0 }, + "3124": { "label": "20/48", "naklon": 0 }, + "3133": { "label": "20/49", "naklon": 0 }, + "3158": { "label": "20/50", "naklon": 0 }, + "3169": { "label": "20/51", "naklon": 0 }, + "3146": { "label": "20/52", "naklon": 0 }, + "3160": { "label": "20/53", "naklon": 0 }, + "3248": { "label": "20/54", "naklon": 0 }, + "3156": { "label": "20/55", "naklon": 0 }, + "3161": { "label": "20/56", "naklon": 0 }, + "3170": { "label": "20/57", "naklon": 0 }, + "3168": { "label": "20/58", "naklon": 0 }, + "3125": { "label": "20/59", "naklon": 0 }, + "3166": { "label": "20/60", "naklon": 0 }, + "3130": { "label": "20/61", "naklon": 0 }, + "3563": { "label": "20/62", "naklon": 0 }, + "3550": { "label": "20/63", "naklon": null }, + "3269": { "label": "20/67", "naklon": 0 }, + "2921": { "label": "21/1", "naklon": 0 }, + "2707": { "label": "21/2", "naklon": 0 }, + "2723": { "label": "21/3", "naklon": 0 }, + "2716": { "label": "21/4", "naklon": 0 }, + "2717": { "label": "21/5", "naklon": 0 }, + "2720": { "label": "21/6", "naklon": 0 }, + "2722": { "label": "21/7", "naklon": 0 }, + "2718": { "label": "21/8", "naklon": 0 }, + "2724": { "label": "21/9", "naklon": 0 }, + "2742": { "label": "21/10", "naklon": 0 }, + "2743": { "label": "21/11", "naklon": 0 }, + "2733": { "label": "21/12", "naklon": 0 }, + "2903": { "label": "21/14", "naklon": 0 }, + "2917": { "label": "21/15", "naklon": 0 }, + "2897": { "label": "21/16", "naklon": 0 }, + "2914": { "label": "21/17", "naklon": 0 }, + "2898": { "label": "21/18", "naklon": 0 }, + "2773": { "label": "21/19", "naklon": 0 }, + "2895": { "label": "21/20", "naklon": 0 }, + "2896": { "label": "21/21", "naklon": 0 }, + "2771": { "label": "21/22", "naklon": 0 }, + "2772": { "label": "21/23", "naklon": 0 }, + "2793": { "label": "21/24", "naklon": 0 }, + "2902": { "label": "21/25", "naklon": 0 }, + "2910": { "label": "21/26", "naklon": 0 }, + "2909": { "label": "21/27", "naklon": 0 }, + "2920": { "label": "21/28", "naklon": 0 }, + "2916": { "label": "21/29", "naklon": 0 }, + "2904": { "label": "21/30", "naklon": 0 }, + "2915": { "label": "21/31", "naklon": 0 }, + "2905": { "label": "21/32", "naklon": 0 }, + "2900": { "label": "21/33", "naklon": 0 }, + "2899": { "label": "21/34", "naklon": 0 }, + "2741": { "label": "21/36", "naklon": 0 }, + "2714": { "label": "21/37", "naklon": 0 }, + "2701": { "label": "21/38", "naklon": 0 }, + "2703": { "label": "21/39", "naklon": 0 }, + "2704": { "label": "21/40", "naklon": 0 }, + "2702": { "label": "21/41", "naklon": 0 }, + "2706": { "label": "21/42", "naklon": 0 }, + "2776": { "label": "21/43", "naklon": 0 }, + "2770": { "label": "21/44", "naklon": 0 }, + "2786": { "label": "21/45", "naklon": 0 }, + "2779": { "label": "21/46", "naklon": 0 }, + "2782": { "label": "21/47", "naklon": 0 }, + "2785": { "label": "21/48", "naklon": 0 }, + "2769": { "label": "21/49", "naklon": 0 }, + "3354": { "label": "21/50", "naklon": 0 }, + "2778": { "label": "21/51", "naklon": 0 }, + "2775": { "label": "21/52", "naklon": 0 }, + "2780": { "label": "21/53", "naklon": 0 }, + "2790": { "label": "21/54", "naklon": 0 }, + "2792": { "label": "21/55", "naklon": 0 }, + "2774": { "label": "21/56", "naklon": 0 }, + "2630": { "label": "22/1", "naklon": 0 }, + "2631": { "label": "22/2", "naklon": 0 }, + "2632": { "label": "22/3", "naklon": 0 }, + "2633": { "label": "22/4", "naklon": 0 }, + "2634": { "label": "22/5", "naklon": 0 }, + "2636": { "label": "22/6", "naklon": 0 }, + "4367": { "label": "22/7", "naklon": 0 }, + "2637": { "label": "22/8", "naklon": 0 }, + "2638": { "label": "22/9", "naklon": 0 }, + "2639": { "label": "22/10", "naklon": 0 }, + "2640": { "label": "22/11", "naklon": 0 }, + "2641": { "label": "22/12", "naklon": 0 }, + "2642": { "label": "22/13", "naklon": 0 }, + "2643": { "label": "22/14", "naklon": 0 }, + "2644": { "label": "22/15", "naklon": 0 }, + "2645": { "label": "22/16", "naklon": 0 }, + "2646": { "label": "22/17", "naklon": 0 }, + "2647": { "label": "22/18", "naklon": 0 }, + "2648": { "label": "22/19", "naklon": 0 }, + "2649": { "label": "22/20", "naklon": 0 }, + "2650": { "label": "22/21", "naklon": 0 }, + "2651": { "label": "22/22", "naklon": 0 }, + "4103": { "label": "22/23", "naklon": 0 }, + "2653": { "label": "22/24", "naklon": 0 }, + "2654": { "label": "22/25", "naklon": 0 }, + "2655": { "label": "22/26", "naklon": 0 }, + "2656": { "label": "22/27", "naklon": 0 }, + "2657": { "label": "22/28", "naklon": 0 }, + "2658": { "label": "22/29", "naklon": 0 }, + "2659": { "label": "22/30", "naklon": 0 }, + "2660": { "label": "22/31", "naklon": 0 }, + "2661": { "label": "22/32", "naklon": 0 }, + "3015": { "label": "22/32/1", "naklon": 0 }, + "2662": { "label": "22/33", "naklon": 0 }, + "2663": { "label": "22/34", "naklon": 0 }, + "2664": { "label": "22/35", "naklon": 0 }, + "2665": { "label": "22/36", "naklon": 0 }, + "2666": { "label": "22/37", "naklon": 0 }, + "2667": { "label": "22/38", "naklon": 0 }, + "2668": { "label": "22/39", "naklon": 0 }, + "2669": { "label": "22/40", "naklon": null }, + "2670": { "label": "22/41", "naklon": null }, + "2671": { "label": "22/42", "naklon": null }, + "3087": { "label": "23/9A", "naklon": 10 }, + "3090": { "label": "23/9B", "naklon": 10 }, + "3075": { "label": "23/1", "naklon": 0 }, + "3089": { "label": "23/2", "naklon": 0 }, + "3088": { "label": "23/3", "naklon": 0 }, + "3228": { "label": "23/4", "naklon": 10 }, + "2751": { "label": "23/5", "naklon": 10 }, + "3243": { "label": "23/6", "naklon": 10 }, + "4349": { "label": "23/7", "naklon": 10 }, + "3102": { "label": "23/8", "naklon": 10 }, + "3099": { "label": "23/10", "naklon": 10 }, + "3103": { "label": "23/11", "naklon": 10 }, + "3093": { "label": "23/12", "naklon": 10 }, + "3098": { "label": "23/13", "naklon": 10 }, + "3092": { "label": "23/14", "naklon": 10 }, + "3233": { "label": "23/15", "naklon": 0 }, + "3095": { "label": "23/16", "naklon": 0 }, + "4074": { "label": "23/17", "naklon": 0 }, + "2729": { "label": "23/18", "naklon": 0 }, + "3234": { "label": "23/19", "naklon": 0 }, + "3094": { "label": "23/20", "naklon": 0 }, + "2817": { "label": "23/21", "naklon": 0 }, + "3226": { "label": "23/22", "naklon": 0 }, + "3225": { "label": "23/23", "naklon": 0 }, + "3237": { "label": "23/24", "naklon": 0 }, + "4250": { "label": "23/25", "naklon": 0 }, + "3059": { "label": "23/26", "naklon": 10 }, + "3238": { "label": "23/27", "naklon": 10 }, + "3242": { "label": "23/28", "naklon": 10 }, + "3236": { "label": "23/29", "naklon": 10 }, + "3112": { "label": "23/30", "naklon": 10 }, + "3224": { "label": "23/31", "naklon": 0 }, + "4298": { "label": "23/32", "naklon": 10 }, + "4150": { "label": "23/33", "naklon": 10 }, + "3091": { "label": "23/34", "naklon": 10 }, + "3771": { "label": "25/1", "naklon": 5 }, + "3777": { "label": "25/2", "naklon": 5 }, + "3749": { "label": "25/3", "naklon": 5 }, + "3769": { "label": "25/4", "naklon": 5 }, + "3765": { "label": "25/5", "naklon": 5 }, + "3785": { "label": "25/6", "naklon": 5 }, + "3761": { "label": "25/7", "naklon": 5 }, + "3758": { "label": "25/8", "naklon": 5 }, + "3766": { "label": "25/9", "naklon": 5 }, + "3779": { "label": "25/10", "naklon": 5 }, + "3899": { "label": "25/11", "naklon": 10 }, + "3922": { "label": "25/12", "naklon": 10 }, + "3912": { "label": "25/13", "naklon": 10 }, + "3933": { "label": "25/14", "naklon": 10 }, + "3921": { "label": "25/15", "naklon": 10 }, + "4300": { "label": "25/16", "naklon": 10 }, + "3927": { "label": "25/17", "naklon": 10 }, + "3212": { "label": "25/18", "naklon": 10 }, + "3208": { "label": "25/19", "naklon": 10 }, + "3207": { "label": "25/20", "naklon": 10 }, + "4294": { "label": "25/21", "naklon": 10 }, + "3209": { "label": "25/22", "naklon": 10 }, + "3745": { "label": "25/23", "naklon": 10 }, + "3762": { "label": "25/24", "naklon": 10 }, + "3215": { "label": "25/25", "naklon": 10 }, + "3210": { "label": "25/26", "naklon": 10 }, + "3211": { "label": "25/27", "naklon": 10 }, + "3206": { "label": "25/28", "naklon": 10 }, + "3918": { "label": "25/29", "naklon": 5 }, + "3928": { "label": "25/30", "naklon": 5 }, + "3917": { "label": "25/31", "naklon": 5 }, + "4029": { "label": "25/32", "naklon": 0 }, + "4038": { "label": "25/33", "naklon": 0 }, + "4022": { "label": "25/34", "naklon": 0 }, + "3937": { "label": "25/35", "naklon": 0 }, + "3190": { "label": "25/36", "naklon": 0 }, + "3835": { "label": "25/37", "naklon": 0 }, + "3201": { "label": "25/38", "naklon": 0 }, + "3193": { "label": "25/39", "naklon": 0 }, + "3191": { "label": "25/40", "naklon": 0 }, + "3203": { "label": "25/41", "naklon": 0 }, + "4301": { "label": "25/42", "naklon": 0 }, + "3223": { "label": "25/43", "naklon": 0 }, + "3202": { "label": "25/44", "naklon": 0 }, + "3205": { "label": "25/45", "naklon": 0 }, + "3194": { "label": "25/46", "naklon": 0 }, + "3198": { "label": "25/47", "naklon": 0 }, + "3204": { "label": "25/48", "naklon": 0 }, + "3200": { "label": "25/49", "naklon": 0 }, + "3216": { "label": "25/50", "naklon": 0 }, + "3932": { "label": "25/51", "naklon": 5 }, + "3923": { "label": "25/52", "naklon": 5 }, + "3913": { "label": "25/53", "naklon": 5 }, + "3900": { "label": "25/54", "naklon": 5 }, + "4189": { "label": "25/55", "naklon": 10 }, + "4191": { "label": "25/56", "naklon": 10 }, + "3790": { "label": "25/57", "naklon": 10 }, + "4190": { "label": "25/58", "naklon": 10 }, + "4302": { "label": "25/59", "naklon": 0 }, + "4351": { "label": "25/60", "naklon": 0 }, + "4075": { "label": "25/61", "naklon": 0 }, + "4071": { "label": "25/62", "naklon": 0 }, + "3784": { "label": "25/63", "naklon": 0 }, + "4065": { "label": "25/64", "naklon": 0 }, + "4297": { "label": "25/65", "naklon": 0 }, + "4295": { "label": "25/66", "naklon": 0 }, + "4299": { "label": "25/67", "naklon": 0 }, + "3772": { "label": "25/68", "naklon": 0 }, + "3941": { "label": "25/69", "naklon": 0 }, + "3782": { "label": "25/70", "naklon": 0 }, + "4068": { "label": "25/71", "naklon": 0 }, + "4073": { "label": "25/72", "naklon": 0 }, + "3901": { "label": "25/73", "naklon": 5 }, + "4296": { "label": "25/74", "naklon": 5 }, + "3910": { "label": "25/75", "naklon": 5 }, + "4293": { "label": "25/76", "naklon": 5 }, + "3919": { "label": "25/77", "naklon": 5 }, + "3924": { "label": "25/78", "naklon": 5 }, + "3909": { "label": "25/79", "naklon": 5 }, + "3896": { "label": "25/80", "naklon": 5 }, + "3911": { "label": "25/81", "naklon": 5 }, + "2819": { "label": "25/82", "naklon": 15 }, + "3776": { "label": "25/83", "naklon": 15 }, + "3752": { "label": "25/84", "naklon": 15 }, + "4353": { "label": "25/85", "naklon": 15 }, + "3791": { "label": "25/86", "naklon": 0 }, + "3770": { "label": "25/87", "naklon": 0 }, + "3760": { "label": "25/88", "naklon": 0 }, + "3115": { "label": "25/89", "naklon": 0 }, + "3738": { "label": "25/90", "naklon": 0 }, + "3748": { "label": "25/91", "naklon": 0 }, + "3753": { "label": "25/92", "naklon": 0 }, + "3775": { "label": "25/93", "naklon": 0 }, + "3778": { "label": "25/94", "naklon": 5 }, + "4078": { "label": "25/95", "naklon": 5 }, + "4088": { "label": "25/96", "naklon": 5 }, + "3856": { "label": "25/97", "naklon": 5 }, + "4084": { "label": "25/98", "naklon": 5 }, + "4069": { "label": "25/99", "naklon": 5 }, + "4188": { "label": "25/100", "naklon": 5 }, + "4064": { "label": "25/101", "naklon": 5 }, + "3792": { "label": "25/102", "naklon": 5 }, + "3780": { "label": "25/103", "naklon": 5 }, + "4034": { "label": "25/104", "naklon": 5 }, + "4072": { "label": "25/105", "naklon": 5 }, + "3884": { "label": "25/106", "naklon": 5 }, + "3793": { "label": "25/107", "naklon": 5 }, + "3863": { "label": "25/108", "naklon": 5 }, + "3855": { "label": "25/109", "naklon": 5 }, + "3846": { "label": "33/1", "naklon": 0 }, + "3943": { "label": "33/2", "naklon": 0 }, + "3903": { "label": "33/3", "naklon": 0 }, + "3982": { "label": "33/4", "naklon": 0 }, + "3879": { "label": "33/5", "naklon": 0 }, + "3887": { "label": "33/6", "naklon": 0 }, + "3920": { "label": "33/7", "naklon": 5 }, + "3942": { "label": "33/8", "naklon": 5 }, + "3829": { "label": "33/9", "naklon": null }, + "3452": { "label": "34/79A", "naklon": 6 }, + "3460": { "label": "34/79B", "naklon": 6 }, + "3443": { "label": "34/90A", "naklon": 6 }, + "3445": { "label": "34/90B", "naklon": 6 }, + "3457": { "label": "34/90C", "naklon": 6 }, + "3461": { "label": "34/97A", "naklon": 6 }, + "3463": { "label": "34/97B", "naklon": 6 }, + "3426": { "label": "34/98A", "naklon": 6 }, + "3444": { "label": "34/98B", "naklon": 6 }, + "3453": { "label": "34/99A", "naklon": 6 }, + "3455": { "label": "34/99B", "naklon": 6 }, + "4009": { "label": "34/1", "naklon": 0 }, + "3602": { "label": "34/2", "naklon": 0 }, + "3441": { "label": "34/3", "naklon": 0 }, + "3464": { "label": "34/4", "naklon": 0 }, + "3883": { "label": "34/5", "naklon": 0 }, + "4098": { "label": "34/6", "naklon": 0 }, + "4003": { "label": "34/7", "naklon": 0 }, + "4004": { "label": "34/8", "naklon": 0 }, + "3888": { "label": "34/9", "naklon": 0 }, + "3997": { "label": "34/10", "naklon": 0 }, + "4006": { "label": "34/11", "naklon": 0 }, + "4000": { "label": "34/12", "naklon": 0 }, + "4011": { "label": "34/13", "naklon": 0 }, + "3999": { "label": "34/14", "naklon": 0 }, + "3981": { "label": "34/15", "naklon": 0 }, + "3988": { "label": "34/16", "naklon": 0 }, + "3986": { "label": "34/17", "naklon": 0 }, + "3998": { "label": "34/18", "naklon": 0 }, + "3983": { "label": "34/19", "naklon": 0 }, + "4005": { "label": "34/20", "naklon": 0 }, + "4001": { "label": "34/21", "naklon": 0 }, + "4008": { "label": "34/22", "naklon": 0 }, + "4002": { "label": "34/23", "naklon": 0 }, + "3996": { "label": "34/24", "naklon": 0 }, + "4007": { "label": "34/25", "naklon": 0 }, + "4113": { "label": "34/26", "naklon": 15 }, + "3595": { "label": "34/27", "naklon": 5 }, + "3599": { "label": "34/28", "naklon": 5 }, + "3601": { "label": "34/29", "naklon": 5 }, + "4205": { "label": "34/30", "naklon": 0 }, + "3987": { "label": "34/31", "naklon": null }, + "4214": { "label": "34/32", "naklon": 0 }, + "4226": { "label": "34/33", "naklon": 0 }, + "4209": { "label": "34/34", "naklon": 0 }, + "4201": { "label": "34/35", "naklon": 0 }, + "3440": { "label": "34/36", "naklon": 0 }, + "3465": { "label": "34/37", "naklon": 0 }, + "3446": { "label": "34/38", "naklon": 0 }, + "4039": { "label": "34/39", "naklon": 5 }, + "4057": { "label": "34/40", "naklon": 5 }, + "3985": { "label": "34/41", "naklon": 0 }, + "3882": { "label": "34/42", "naklon": 0 }, + "4040": { "label": "34/43", "naklon": 5 }, + "3231": { "label": "34/44", "naklon": 0 }, + "3227": { "label": "34/45", "naklon": 0 }, + "3431": { "label": "34/46", "naklon": 0 }, + "4013": { "label": "34/47", "naklon": 0 }, + "4045": { "label": "34/48", "naklon": 0 }, + "3949": { "label": "34/49", "naklon": 0 }, + "3953": { "label": "34/50", "naklon": 0 }, + "3952": { "label": "34/51", "naklon": 0 }, + "3995": { "label": "34/52", "naklon": 0 }, + "3992": { "label": "34/53", "naklon": 0 }, + "4198": { "label": "34/54", "naklon": 0 }, + "3935": { "label": "34/55", "naklon": 0 }, + "4050": { "label": "34/56", "naklon": 0 }, + "4049": { "label": "34/57", "naklon": 0 }, + "4054": { "label": "34/58", "naklon": 0 }, + "3663": { "label": "34/59", "naklon": 6 }, + "3661": { "label": "34/60", "naklon": 6 }, + "3664": { "label": "34/61", "naklon": 6 }, + "3660": { "label": "34/62", "naklon": 6 }, + "3662": { "label": "34/63", "naklon": 6 }, + "3665": { "label": "34/65", "naklon": 6 }, + "3667": { "label": "34/66", "naklon": 6 }, + "3675": { "label": "34/67", "naklon": 6 }, + "3666": { "label": "34/68", "naklon": 6 }, + "3652": { "label": "34/69", "naklon": 6 }, + "3458": { "label": "34/70", "naklon": 6 }, + "4425": { "label": "34/70/1", "naklon": 6 }, + "3459": { "label": "34/71", "naklon": 6 }, + "3435": { "label": "34/72", "naklon": 6 }, + "3448": { "label": "34/73", "naklon": 6 }, + "3451": { "label": "34/74", "naklon": 6 }, + "3442": { "label": "34/75", "naklon": 6 }, + "3449": { "label": "34/76", "naklon": 6 }, + "3450": { "label": "34/77", "naklon": 6 }, + "3433": { "label": "34/78", "naklon": 6 }, + "3432": { "label": "34/80", "naklon": 12 }, + "3470": { "label": "34/81", "naklon": 12 }, + "3438": { "label": "34/82", "naklon": 12 }, + "3439": { "label": "34/83", "naklon": 12 }, + "4028": { "label": "34/84", "naklon": 5 }, + "3596": { "label": "34/85", "naklon": 5 }, + "4021": { "label": "34/86", "naklon": 5 }, + "3437": { "label": "34/87", "naklon": 12 }, + "3428": { "label": "34/88", "naklon": 12 }, + "3430": { "label": "34/89", "naklon": 12 }, + "3454": { "label": "34/91", "naklon": 6 }, + "3492": { "label": "34/92", "naklon": 6 }, + "3462": { "label": "34/93", "naklon": 6 }, + "3427": { "label": "34/94", "naklon": 6 }, + "3434": { "label": "34/95", "naklon": 6 }, + "3456": { "label": "34/96", "naklon": 6 }, + "4307": { "label": "34/98/1", "naklon": 6 }, + "3968": { "label": "35/1", "naklon": 0 }, + "3969": { "label": "35/2", "naklon": 0 }, + "3947": { "label": "35/3", "naklon": 0 }, + "3979": { "label": "35/4", "naklon": 0 }, + "3959": { "label": "35/5", "naklon": 0 }, + "3948": { "label": "35/6", "naklon": 0 }, + "3961": { "label": "35/7", "naklon": 0 }, + "3956": { "label": "35/8", "naklon": 0 }, + "3604": { "label": "35/9", "naklon": 0 }, + "3944": { "label": "35/10", "naklon": 0 }, + "3960": { "label": "35/11", "naklon": 0 }, + "3958": { "label": "35/12", "naklon": 0 }, + "4036": { "label": "35/13", "naklon": 5 }, + "3893": { "label": "35/18", "naklon": 5 }, + "4108": { "label": "35/19", "naklon": 5 }, + "4017": { "label": "35/20", "naklon": 5 }, + "3963": { "label": "35/21", "naklon": 0 }, + "3658": { "label": "35/22", "naklon": 0 }, + "3975": { "label": "35/23", "naklon": 0 }, + "3980": { "label": "35/24", "naklon": 0 }, + "4012": { "label": "35/25", "naklon": 0 }, + "3655": { "label": "35/26", "naklon": 0 }, + "3962": { "label": "35/27", "naklon": 0 }, + "3945": { "label": "35/28", "naklon": 0 }, + "3569": { "label": "35/29", "naklon": 0 }, + "3429": { "label": "35/30", "naklon": 0 }, + "3657": { "label": "35/31", "naklon": 0 }, + "3646": { "label": "35/32", "naklon": 0 }, + "3622": { "label": "35/33", "naklon": 0 }, + "3612": { "label": "35/34", "naklon": 0 }, + "3955": { "label": "35/35", "naklon": 0 }, + "3878": { "label": "35/37", "naklon": 0 }, + "3965": { "label": "35/38", "naklon": 0 }, + "3970": { "label": "35/39", "naklon": 0 }, + "3611": { "label": "35/40", "naklon": 0 }, + "2635": { "label": "35/41", "naklon": 0 }, + "3978": { "label": "35/42", "naklon": 0 }, + "4213": { "label": "35/43", "naklon": 0 }, + "3984": { "label": "35/44", "naklon": 0 }, + "4218": { "label": "35/45", "naklon": 0 }, + "3973": { "label": "35/46", "naklon": 0 }, + "3974": { "label": "35/47", "naklon": 0 }, + "3759": { "label": "35/48", "naklon": 0 }, + "3844": { "label": "35/49", "naklon": 0 }, + "3804": { "label": "35/50", "naklon": 0 }, + "3831": { "label": "35/51", "naklon": 0 }, + "3643": { "label": "35/52", "naklon": 0 }, + "3966": { "label": "35/53", "naklon": 0 }, + "3971": { "label": "35/54", "naklon": 0 }, + "3650": { "label": "35/55", "naklon": 6 }, + "3651": { "label": "35/56", "naklon": 6 }, + "3669": { "label": "35/57", "naklon": 6 }, + "3648": { "label": "35/58", "naklon": 6 }, + "3645": { "label": "35/59", "naklon": 6 }, + "3659": { "label": "35/60", "naklon": 6 }, + "3647": { "label": "35/61", "naklon": 6 }, + "3644": { "label": "35/62", "naklon": 6 }, + "3671": { "label": "35/63", "naklon": 6 }, + "3682": { "label": "35/64", "naklon": 6 }, + "3672": { "label": "35/65", "naklon": 6 }, + "3683": { "label": "35/66", "naklon": 6 }, + "3673": { "label": "35/67", "naklon": 6 }, + "3674": { "label": "35/68", "naklon": 6 }, + "3679": { "label": "35/69", "naklon": 6 }, + "3649": { "label": "35/70", "naklon": 6 }, + "3687": { "label": "35/71", "naklon": 6 }, + "3677": { "label": "35/72", "naklon": 6 }, + "3690": { "label": "35/73", "naklon": 6 }, + "3691": { "label": "35/74", "naklon": 6 }, + "3676": { "label": "35/75", "naklon": 6 }, + "3680": { "label": "35/76", "naklon": 6 }, + "3668": { "label": "35/77", "naklon": 6 }, + "3681": { "label": "35/78", "naklon": 6 }, + "3670": { "label": "35/79", "naklon": 6 }, + "3689": { "label": "35/80", "naklon": 6 }, + "3678": { "label": "35/81", "naklon": 6 }, + "3693": { "label": "35/82", "naklon": 6 }, + "3654": { "label": "35/83", "naklon": null }, + "4086": { "label": "36/1", "naklon": 0 }, + "4085": { "label": "36/2", "naklon": 0 }, + "4083": { "label": "36/3", "naklon": 0 }, + "4087": { "label": "36/4", "naklon": 0 }, + "4077": { "label": "36/5", "naklon": 0 }, + "4082": { "label": "36/6", "naklon": 0 }, + "4186": { "label": "36/7", "naklon": 0 }, + "4206": { "label": "36/8", "naklon": 0 }, + "4080": { "label": "36/9", "naklon": 0 }, + "4081": { "label": "36/10", "naklon": 0 }, + "4210": { "label": "36/11", "naklon": 0 }, + "4079": { "label": "36/12", "naklon": 0 }, + "4076": { "label": "36/13", "naklon": 0 }, + "3852": { "label": "36/14", "naklon": 0 }, + "2813": { "label": "36/15", "naklon": 0 }, + "4219": { "label": "36/16", "naklon": 0 }, + "3104": { "label": "37/1A", "naklon": 15 }, + "3121": { "label": "37/1B", "naklon": 15 }, + "3113": { "label": "37/2", "naklon": 10 }, + "3118": { "label": "37/3", "naklon": 10 }, + "3111": { "label": "37/4", "naklon": 10 }, + "4020": { "label": "37/5", "naklon": 10 }, + "3119": { "label": "37/6", "naklon": 10 }, + "3110": { "label": "37/7", "naklon": 10 }, + "3108": { "label": "37/8", "naklon": 10 }, + "3107": { "label": "37/12", "naklon": 0 }, + "3199": { "label": "37/13", "naklon": 0 }, + "3120": { "label": "37/14", "naklon": 0 }, + "3122": { "label": "37/15", "naklon": 0 }, + "3908": { "label": "37/16", "naklon": 0 }, + "3114": { "label": "37/17", "naklon": 0 }, + "3105": { "label": "37/18", "naklon": 0 }, + "3116": { "label": "37/19", "naklon": 0 }, + "3106": { "label": "37/20", "naklon": 0 }, + "2887": { "label": "37/21", "naklon": 5 }, + "2888": { "label": "37/22", "naklon": 5 }, + "2877": { "label": "37/23", "naklon": 5 }, + "2891": { "label": "37/24", "naklon": 5 }, + "2886": { "label": "37/25", "naklon": 5 }, + "2892": { "label": "37/26", "naklon": 5 }, + "2882": { "label": "37/27", "naklon": 5 }, + "2883": { "label": "37/28", "naklon": 5 }, + "2876": { "label": "37/29", "naklon": 5 }, + "3109": { "label": "37/30", "naklon": 5 }, + "4152": { "label": "37/31", "naklon": 5 }, + "3117": { "label": "37/32", "naklon": 5 }, + "2870": { "label": "37/33", "naklon": 5 }, + "2867": { "label": "37/34", "naklon": 0 }, + "2865": { "label": "37/35", "naklon": 0 }, + "3096": { "label": "37/36", "naklon": 0 }, + "2871": { "label": "37/37", "naklon": 0 }, + "2884": { "label": "37/38", "naklon": 0 }, + "2855": { "label": "37/39", "naklon": 0 }, + "2878": { "label": "37/40", "naklon": 0 }, + "2889": { "label": "37/41", "naklon": 0 }, + "2879": { "label": "37/42", "naklon": 0 }, + "2850": { "label": "37/43", "naklon": 0 }, + "2894": { "label": "37/44", "naklon": 0 }, + "2880": { "label": "37/45", "naklon": 0 }, + "2893": { "label": "37/46", "naklon": 0 }, + "2890": { "label": "37/47", "naklon": 0 }, + "4355": { "label": "37/48", "naklon": 0 }, + "2885": { "label": "37/49", "naklon": 0 }, + "2875": { "label": "37/50", "naklon": 0 }, + "3486": { "label": "38/30A", "naklon": 5 }, + "3714": { "label": "38/30B", "naklon": 0 }, + "3483": { "label": "38/32A", "naklon": 5 }, + "3496": { "label": "38/32B", "naklon": 0 }, + "3487": { "label": "38/35A", "naklon": 5 }, + "3498": { "label": "38/35B", "naklon": 5 }, + "3578": { "label": "38/38A", "naklon": 5 }, + "3508": { "label": "38/38B", "naklon": 5 }, + "3787": { "label": "38/59A", "naklon": 5 }, + "3491": { "label": "38/59B", "naklon": 5 }, + "3568": { "label": "38/1", "naklon": null }, + "3502": { "label": "38/2", "naklon": 0 }, + "3836": { "label": "38/3", "naklon": 0 }, + "3588": { "label": "38/4", "naklon": 0 }, + "3493": { "label": "38/5", "naklon": 0 }, + "3580": { "label": "38/6", "naklon": 0 }, + "3572": { "label": "38/7", "naklon": 0 }, + "3506": { "label": "38/8", "naklon": 0 }, + "3503": { "label": "38/9", "naklon": 0 }, + "3579": { "label": "38/10", "naklon": 0 }, + "3586": { "label": "38/11", "naklon": 0 }, + "3495": { "label": "38/12", "naklon": 5 }, + "3492": { "label": "38/13", "naklon": 5 }, + "3532": { "label": "38/14", "naklon": 5 }, + "3574": { "label": "38/15", "naklon": 5 }, + "4140": { "label": "38/16", "naklon": 5 }, + "3795": { "label": "38/17", "naklon": 5 }, + "3788": { "label": "38/18", "naklon": 5 }, + "3796": { "label": "38/19", "naklon": 5 }, + "3797": { "label": "38/20", "naklon": 5 }, + "3798": { "label": "38/21", "naklon": 5 }, + "3786": { "label": "38/22", "naklon": 5 }, + "4067": { "label": "38/23", "naklon": 5 }, + "3773": { "label": "38/24", "naklon": 5 }, + "3774": { "label": "38/25", "naklon": 5 }, + "3789": { "label": "38/26", "naklon": 5 }, + "3520": { "label": "38/27", "naklon": null }, + "3577": { "label": "38/29", "naklon": 5 }, + "3530": { "label": "38/31", "naklon": null }, + "3488": { "label": "38/33", "naklon": 5 }, + "3505": { "label": "38/34", "naklon": 5 }, + "3497": { "label": "38/36", "naklon": 5 }, + "3490": { "label": "38/37", "naklon": 5 }, + "3585": { "label": "38/39", "naklon": 5 }, + "3582": { "label": "38/40", "naklon": 5 }, + "3507": { "label": "38/41", "naklon": 5 }, + "3484": { "label": "38/42", "naklon": 5 }, + "3501": { "label": "38/43", "naklon": 5 }, + "3581": { "label": "38/44", "naklon": 5 }, + "4192": { "label": "38/45", "naklon": 5 }, + "3576": { "label": "38/46", "naklon": 5 }, + "3489": { "label": "38/47", "naklon": 5 }, + "3573": { "label": "38/48", "naklon": 5 }, + "3504": { "label": "38/49", "naklon": 5 }, + "3794": { "label": "38/50", "naklon": 5 }, + "3485": { "label": "38/51", "naklon": 5 }, + "3482": { "label": "38/52", "naklon": 5 }, + "3575": { "label": "38/53", "naklon": 5 }, + "3499": { "label": "38/54", "naklon": 5 }, + "3494": { "label": "38/55", "naklon": 5 }, + "3583": { "label": "38/56", "naklon": 5 }, + "3570": { "label": "38/57", "naklon": 5 }, + "3500": { "label": "38/58", "naklon": 0 }, + "3510": { "label": "38/63", "naklon": null }, + "3512": { "label": "38/64", "naklon": null }, + "3535": { "label": "38/67", "naklon": null }, + "3531": { "label": "38/68", "naklon": null }, + "3537": { "label": "38/69", "naklon": null }, + "3522": { "label": "39/1", "naklon": 10 }, + "4018": { "label": "39/2", "naklon": 10 }, + "4019": { "label": "39/3", "naklon": 10 }, + "4154": { "label": "39/4", "naklon": 5 }, + "3907": { "label": "39/5", "naklon": 5 }, + "4148": { "label": "39/6", "naklon": 0 }, + "4153": { "label": "39/7", "naklon": 0 }, + "3938": { "label": "39/8", "naklon": 0 }, + "3802": { "label": "39/9", "naklon": 0 }, + "4015": { "label": "39/10", "naklon": 0 }, + "3929": { "label": "39/11", "naklon": 0 }, + "3946": { "label": "39/12", "naklon": 0 }, + "4014": { "label": "39/13", "naklon": 0 }, + "4155": { "label": "39/14", "naklon": 0 }, + "4149": { "label": "39/15", "naklon": 0 }, + "3642": { "label": "39/16", "naklon": 0 }, + "3636": { "label": "39/17", "naklon": 5 }, + "3991": { "label": "39/18", "naklon": 0 }, + "3994": { "label": "39/19", "naklon": 0 }, + "3990": { "label": "39/20", "naklon": 0 }, + "3967": { "label": "39/21", "naklon": 0 }, + "3977": { "label": "39/22", "naklon": 0 }, + "3757": { "label": "39/23", "naklon": 15 }, + "3633": { "label": "39/24", "naklon": 15 }, + "3744": { "label": "39/25", "naklon": 15 }, + "4023": { "label": "39/26", "naklon": 5 }, + "3720": { "label": "39/27", "naklon": 5 }, + "3734": { "label": "39/28", "naklon": 5 }, + "3741": { "label": "39/29", "naklon": 5 }, + "3721": { "label": "39/30", "naklon": 5 }, + "3845": { "label": "39/31", "naklon": 0 }, + "3840": { "label": "39/32", "naklon": 0 }, + "3837": { "label": "39/33", "naklon": null }, + "3839": { "label": "39/34", "naklon": 0 }, + "3542": { "label": "41/1", "naklon": null }, + "3566": { "label": "41/2", "naklon": null }, + "3548": { "label": "41/3", "naklon": null }, + "3515": { "label": "41/4", "naklon": null }, + "3559": { "label": "41/5", "naklon": null }, + "3509": { "label": "41/6", "naklon": null }, + "3524": { "label": "41/7", "naklon": null }, + "3518": { "label": "41/8", "naklon": null }, + "3182": { "label": "41/9", "naklon": null }, + "3187": { "label": "41/10", "naklon": null }, + "3195": { "label": "41/11", "naklon": 0 }, + "3857": { "label": "41/12", "naklon": 0 }, + "3183": { "label": "41/13", "naklon": 0 }, + "3177": { "label": "41/14", "naklon": 0 }, + "3189": { "label": "41/15", "naklon": 0 }, + "3186": { "label": "41/16", "naklon": 0 }, + "3178": { "label": "42/1", "naklon": 0 }, + "3219": { "label": "42/2", "naklon": 0 }, + "3475": { "label": "42/3", "naklon": 0 }, + "3175": { "label": "42/4", "naklon": 0 }, + "3222": { "label": "42/5", "naklon": 0 }, + "3221": { "label": "42/6", "naklon": 0 }, + "3181": { "label": "42/7", "naklon": 0 }, + "3180": { "label": "42/8", "naklon": 0 }, + "3218": { "label": "42/9", "naklon": 0 }, + "3176": { "label": "42/10", "naklon": 0 }, + "3174": { "label": "42/11", "naklon": 0 }, + "3220": { "label": "42/12", "naklon": 0 }, + "3533": { "label": "42/13", "naklon": null }, + "3543": { "label": "42/14", "naklon": null }, + "3554": { "label": "42/15", "naklon": null }, + "3549": { "label": "42/16", "naklon": null }, + "2857": { "label": "43/1", "naklon": 5 }, + "2752": { "label": "43/2", "naklon": 5 }, + "2753": { "label": "43/3", "naklon": 5 }, + "3024": { "label": "43/4", "naklon": 5 }, + "2754": { "label": "43/5", "naklon": 5 }, + "4423": { "label": "43/6", "naklon": 5 }, + "4368": { "label": "43/7", "naklon": 5 }, + "2978": { "label": "43/8", "naklon": 5 }, + "2868": { "label": "43/9", "naklon": 5 }, + "4377": { "label": "43/10", "naklon": 5 }, + "2757": { "label": "43/11", "naklon": 5 }, + "2970": { "label": "43/12", "naklon": 5 }, + "2758": { "label": "43/13", "naklon": 5 }, + "4378": { "label": "43/14", "naklon": 5 }, + "2759": { "label": "43/15", "naklon": 5 }, + "4342": { "label": "43/16", "naklon": 5 }, + "3026": { "label": "43/17", "naklon": null }, + "2986": { "label": "43/18", "naklon": null }, + "4343": { "label": "43/19", "naklon": null }, + "2760": { "label": "43/20", "naklon": null }, + "4379": { "label": "43/21", "naklon": null }, + "2971": { "label": "43/22", "naklon": null }, + "2761": { "label": "43/23", "naklon": null }, + "2762": { "label": "43/24", "naklon": null }, + "4339": { "label": "43/25", "naklon": null }, + "4380": { "label": "43/26", "naklon": null }, + "2975": { "label": "43/27", "naklon": null }, + "3003": { "label": "43/28", "naklon": null }, + "4338": { "label": "43/29", "naklon": null }, + "3002": { "label": "43/30", "naklon": null }, + "4345": { "label": "43/31", "naklon": null }, + "2979": { "label": "43/32", "naklon": null }, + "2989": { "label": "43/33", "naklon": null }, + "2996": { "label": "43/34", "naklon": null }, + "2972": { "label": "43/35", "naklon": null }, + "2988": { "label": "43/36", "naklon": null }, + "4344": { "label": "43/37", "naklon": null }, + "3022": { "label": "43/38", "naklon": null }, + "4341": { "label": "43/39", "naklon": null }, + "2983": { "label": "43/40", "naklon": null }, + "2995": { "label": "43/41", "naklon": null }, + "2763": { "label": "43/42", "naklon": null }, + "2764": { "label": "43/43", "naklon": null }, + "2765": { "label": "43/44", "naklon": null }, + "2766": { "label": "43/45", "naklon": null }, + "2767": { "label": "43/46", "naklon": null }, + "2768": { "label": "43/47", "naklon": null }, + "3018": { "label": "43/48", "naklon": null }, + "2982": { "label": "43/49", "naklon": null }, + "3019": { "label": "43/50", "naklon": 0 }, + "3013": { "label": "43/51", "naklon": null }, + "3007": { "label": "43/52", "naklon": null }, + "2980": { "label": "43/53", "naklon": null }, + "3011": { "label": "43/54", "naklon": null }, + "2672": { "label": "43/55", "naklon": null }, + "2673": { "label": "43/56", "naklon": null }, + "2674": { "label": "43/57", "naklon": null }, + "2675": { "label": "43/58", "naklon": null }, + "2676": { "label": "43/59", "naklon": null }, + "2677": { "label": "43/60", "naklon": null }, + "2678": { "label": "43/61", "naklon": null }, + "2679": { "label": "43/62", "naklon": null }, + "2680": { "label": "43/63", "naklon": null }, + "2840": { "label": "43/64", "naklon": null }, + "2682": { "label": "43/65", "naklon": null }, + "2683": { "label": "43/66", "naklon": null }, + "2684": { "label": "43/67", "naklon": 0 }, + "2685": { "label": "43/68", "naklon": null }, + "2686": { "label": "43/69", "naklon": null }, + "2687": { "label": "43/70", "naklon": null }, + "2688": { "label": "43/71", "naklon": null }, + "2689": { "label": "43/72", "naklon": null }, + "2690": { "label": "43/73", "naklon": null }, + "2691": { "label": "43/74", "naklon": null }, + "2692": { "label": "43/75", "naklon": null }, + "2693": { "label": "43/76", "naklon": 0 }, + "2694": { "label": "43/77", "naklon": null }, + "2695": { "label": "43/78", "naklon": null }, + "2696": { "label": "43/79", "naklon": 0 }, + "2697": { "label": "43/80", "naklon": null }, + "2698": { "label": "43/81", "naklon": 0 }, + "2699": { "label": "43/82", "naklon": null }, + "2700": { "label": "43/83", "naklon": 0 }, + "2744": { "label": "43/84", "naklon": null }, + "2745": { "label": "43/85", "naklon": 0 }, + "2746": { "label": "43/86", "naklon": null }, + "2747": { "label": "43/87", "naklon": 0 }, + "2748": { "label": "43/88", "naklon": null }, + "2749": { "label": "43/89", "naklon": 0 }, + "2841": { "label": "43/90", "naklon": null }, + "4237": { "label": "45/1", "naklon": 5 }, + "4226": { "label": "45/2", "naklon": 5 }, + "4242": { "label": "45/3", "naklon": 5 }, + "4179": { "label": "45/4", "naklon": 5 }, + "4247": { "label": "45/5", "naklon": 5 }, + "4245": { "label": "45/6", "naklon": 5 }, + "3872": { "label": "45/7", "naklon": 5 }, + "4175": { "label": "45/8", "naklon": 5 }, + "4236": { "label": "45/9", "naklon": 5 }, + "4170": { "label": "45/10", "naklon": 5 }, + "4238": { "label": "45/11", "naklon": 5 }, + "4246": { "label": "45/12", "naklon": 5 }, + "4166": { "label": "45/13", "naklon": 5 }, + "4227": { "label": "45/14", "naklon": 5 }, + "4171": { "label": "45/15", "naklon": 5 }, + "4180": { "label": "45/16", "naklon": 5 }, + "4244": { "label": "45/17", "naklon": 5 }, + "4199": { "label": "45/18", "naklon": 5 }, + "4239": { "label": "45/19", "naklon": 5 }, + "4207": { "label": "45/20", "naklon": 5 }, + "4223": { "label": "45/21", "naklon": 5 }, + "4230": { "label": "45/22", "naklon": 5 }, + "4233": { "label": "45/23", "naklon": 5 }, + "4222": { "label": "45/24", "naklon": 5 }, + "4217": { "label": "45/25", "naklon": 5 }, + "4243": { "label": "45/26", "naklon": 5 }, + "4200": { "label": "45/27", "naklon": 5 }, + "4228": { "label": "45/28", "naklon": 5 }, + "4211": { "label": "45/29", "naklon": 5 }, + "4234": { "label": "45/30", "naklon": 5 }, + "4235": { "label": "45/31", "naklon": 5 }, + "4203": { "label": "45/32", "naklon": 5 }, + "4240": { "label": "45/33", "naklon": 5 }, + "4224": { "label": "45/34", "naklon": 5 }, + "4232": { "label": "45/35", "naklon": 5 }, + "4231": { "label": "45/36", "naklon": 5 }, + "4161": { "label": "45/37", "naklon": 5 }, + "4225": { "label": "45/38", "naklon": 5 }, + "4241": { "label": "45/39", "naklon": 5 }, + "4229": { "label": "45/40", "naklon": 5 }, + "4221": { "label": "45/41", "naklon": 5 }, + "4212": { "label": "45/42", "naklon": 5 }, + "4216": { "label": "45/43", "naklon": 5 }, + "3864": { "label": "45/44", "naklon": null }, + "3806": { "label": "46/1", "naklon": 5 }, + "3813": { "label": "46/2", "naklon": 5 }, + "3815": { "label": "46/3", "naklon": 5 }, + "3807": { "label": "46/4", "naklon": 5 }, + "3895": { "label": "46/5", "naklon": 5 }, + "3809": { "label": "46/6", "naklon": 5 }, + "3820": { "label": "46/7", "naklon": 5 }, + "3805": { "label": "46/8", "naklon": 5 }, + "3894": { "label": "46/9", "naklon": 0 }, + "4055": { "label": "46/10", "naklon": 0 }, + "3812": { "label": "46/11", "naklon": 5 }, + "3822": { "label": "46/12", "naklon": 5 }, + "3821": { "label": "46/13", "naklon": 5 }, + "3808": { "label": "46/14", "naklon": 5 }, + "3799": { "label": "46/15", "naklon": 5 }, + "3816": { "label": "46/16", "naklon": 5 }, + "3751": { "label": "46/17", "naklon": 5 }, + "3814": { "label": "46/18", "naklon": 5 }, + "4044": { "label": "46/19", "naklon": 0 }, + "3931": { "label": "46/20", "naklon": 0 }, + "3902": { "label": "46/21", "naklon": 5 }, + "3916": { "label": "46/22", "naklon": 5 }, + "3892": { "label": "46/23", "naklon": 5 }, + "3914": { "label": "46/24", "naklon": 5 }, + "3898": { "label": "46/25", "naklon": 5 }, + "3897": { "label": "46/26", "naklon": 5 }, + "3885": { "label": "46/27", "naklon": 5 }, + "3906": { "label": "46/28", "naklon": 5 }, + "3930": { "label": "46/29", "naklon": 0 }, + "3936": { "label": "46/30", "naklon": 0 }, + "3860": { "label": "46/31", "naklon": 5 }, + "3841": { "label": "46/32", "naklon": 5 }, + "3873": { "label": "46/33", "naklon": 5 }, + "3854": { "label": "46/34", "naklon": 5 }, + "3939": { "label": "46/35", "naklon": 5 }, + "3858": { "label": "46/36", "naklon": 5 }, + "3940": { "label": "46/37", "naklon": 5 }, + "4035": { "label": "46/38", "naklon": 5 }, + "3373": { "label": "47/1", "naklon": 0 }, + "3374": { "label": "47/2", "naklon": 0 }, + "3384": { "label": "47/3", "naklon": 0 }, + "3385": { "label": "47/4", "naklon": 0 }, + "4051": { "label": "48/1", "naklon": 5 }, + "4041": { "label": "48/2", "naklon": 5 }, + "4056": { "label": "48/3", "naklon": 5 }, + "3875": { "label": "48/4", "naklon": 5 }, + "4061": { "label": "48/5", "naklon": 5 }, + "4047": { "label": "48/6", "naklon": 5 }, + "4060": { "label": "48/7", "naklon": 5 }, + "4059": { "label": "48/8", "naklon": 5 }, + "4058": { "label": "48/9", "naklon": 5 }, + "3635": { "label": "48/10", "naklon": 5 }, + "3640": { "label": "48/11", "naklon": 5 }, + "3747": { "label": "48/12", "naklon": 5 }, + "3629": { "label": "48/13", "naklon": 5 }, + "4048": { "label": "48/14", "naklon": 5 }, + "4063": { "label": "48/15", "naklon": 5 }, + "4062": { "label": "48/16", "naklon": 5 }, + "4043": { "label": "48/17", "naklon": 5 }, + "4052": { "label": "48/18", "naklon": 5 }, + "4042": { "label": "48/19", "naklon": 5 }, + "4053": { "label": "48/20", "naklon": 5 }, + "4167": { "label": "50/15A", "naklon": null }, + "4159": { "label": "50/15B", "naklon": null }, + "4183": { "label": "50/1", "naklon": 0 }, + "4157": { "label": "50/2", "naklon": 0 }, + "4160": { "label": "50/3", "naklon": 0 }, + "4173": { "label": "50/4", "naklon": 0 }, + "4177": { "label": "50/5", "naklon": 0 }, + "4174": { "label": "50/6", "naklon": 0 }, + "4178": { "label": "50/7", "naklon": 0 }, + "4195": { "label": "50/8", "naklon": 0 }, + "4169": { "label": "50/9", "naklon": 0 }, + "4162": { "label": "50/10", "naklon": 0 }, + "4158": { "label": "50/11", "naklon": 0 }, + "4182": { "label": "50/12", "naklon": 0 }, + "4194": { "label": "50/13", "naklon": 0 }, + "4184": { "label": "50/14", "naklon": 0 }, + "4197": { "label": "50/16", "naklon": null }, + "4164": { "label": "50/17", "naklon": null }, + "3306": { "label": "50/18", "naklon": null }, + "4168": { "label": "50/19", "naklon": null }, + "4193": { "label": "50/20", "naklon": null }, + "4187": { "label": "50/21", "naklon": null }, + "4163": { "label": "50/22", "naklon": null }, + "4165": { "label": "50/23", "naklon": null }, + "4185": { "label": "50/24", "naklon": null }, + "3904": { "label": "50/25", "naklon": null }, + "2619": { "label": "53/1", "naklon": 0 }, + "2623": { "label": "53/2", "naklon": 0 }, + "2617": { "label": "53/3", "naklon": 0 }, + "2622": { "label": "53/4", "naklon": 0 }, + "2618": { "label": "53/5", "naklon": 0 }, + "2626": { "label": "53/6", "naklon": 0 }, + "2869": { "label": "53/7", "naklon": 0 }, + "2613": { "label": "53/8", "naklon": 0 }, + "2608": { "label": "53/9", "naklon": 0 }, + "2611": { "label": "53/10", "naklon": 0 }, + "2598": { "label": "53/11", "naklon": 0 }, + "3528": { "label": "53/12", "naklon": 0 }, + "3545": { "label": "53/13", "naklon": 0 }, + "2620": { "label": "53/14", "naklon": 0 }, + "2612": { "label": "53/15", "naklon": 0 }, + "2615": { "label": "53/16", "naklon": 0 }, + "3722": { "label": "53/17", "naklon": 0 }, + "2624": { "label": "53/18", "naklon": 0 }, + "2609": { "label": "53/19", "naklon": 0 }, + "2625": { "label": "53/20", "naklon": 0 }, + "2602": { "label": "53/21", "naklon": 0 }, + "2610": { "label": "53/22", "naklon": 0 }, + "2599": { "label": "53/23", "naklon": 0 }, + "2605": { "label": "53/24", "naklon": 0 }, + "2593": { "label": "53/25", "naklon": 0 }, + "3074": { "label": "53/26", "naklon": 0 }, + "2740": { "label": "53/27", "naklon": 0 }, + "2614": { "label": "53/28", "naklon": 0 }, + "2601": { "label": "53/29", "naklon": 0 }, + "4196": { "label": "53/30", "naklon": 0 }, + "2607": { "label": "53/31", "naklon": 0 }, + "2582": { "label": "53/32", "naklon": 0 }, + "2594": { "label": "53/33", "naklon": 0 }, + "2589": { "label": "53/34", "naklon": 0 }, + "2596": { "label": "53/35", "naklon": 0 }, + "2603": { "label": "53/36", "naklon": 0 }, + "2597": { "label": "53/37", "naklon": 0 }, + "2590": { "label": "53/38", "naklon": 0 }, + "2581": { "label": "53/39", "naklon": 0 }, + "2583": { "label": "53/40", "naklon": 0 }, + "2580": { "label": "53/41", "naklon": 0 }, + "2579": { "label": "53/42", "naklon": 0 }, + "2797": { "label": "53/43", "naklon": 0 }, + "2577": { "label": "53/44", "naklon": 0 }, + "2586": { "label": "53/45", "naklon": 0 }, + "2588": { "label": "53/46", "naklon": 0 }, + "2591": { "label": "53/47", "naklon": 0 }, + "2592": { "label": "53/48", "naklon": 0 }, + "2573": { "label": "53/49", "naklon": 0 }, + "2595": { "label": "53/50", "naklon": 0 }, + "2587": { "label": "53/51", "naklon": 0 }, + "2578": { "label": "53/52", "naklon": 0 }, + "2574": { "label": "53/53", "naklon": 0 }, + "2571": { "label": "53/54", "naklon": 0 }, + "2570": { "label": "53/55", "naklon": 0 }, + "2576": { "label": "53/56", "naklon": 0 }, + "2881": { "label": "53/57", "naklon": 0 }, + "2575": { "label": "53/58", "naklon": 0 }, + "2572": { "label": "53/59", "naklon": 0 }, + "2569": { "label": "53/60", "naklon": 0 }, + "4324": { "label": "55/1", "naklon": 0 }, + "4319": { "label": "55/2", "naklon": 0 }, + "4327": { "label": "55/3", "naklon": 0 }, + "4333": { "label": "55/4", "naklon": 0 }, + "4332": { "label": "55/5", "naklon": 0 }, + "4320": { "label": "55/6", "naklon": 0 }, + "4317": { "label": "55/7", "naklon": 0 }, + "4318": { "label": "55/8", "naklon": 0 }, + "4328": { "label": "55/9", "naklon": 0 }, + "4323": { "label": "55/10", "naklon": 0 }, + "4325": { "label": "55/11", "naklon": 0 }, + "4326": { "label": "55/12", "naklon": 0 }, + "4316": { "label": "55/13", "naklon": 0 }, + "4322": { "label": "55/14", "naklon": 0 }, + "4331": { "label": "55/15", "naklon": 0 }, + "4321": { "label": "55/16", "naklon": 0 }, + "4315": { "label": "55/17", "naklon": 0 }, + "4329": { "label": "55/18", "naklon": 0 }, + "4334": { "label": "55/19", "naklon": 0 }, + "4330": { "label": "55/20", "naklon": 0 } +}; + + +let svetlaSorted = [{ "label": "1/3A", "node": 3993, "naklon": 0 }, +{ "label": "1/3B", "node": 3989, "naklon": 15 }, +{ "label": "1/1", "node": 3976, "naklon": 0 }, +{ "label": "1/2", "node": 4181, "naklon": 0 }, +{ "label": "1/4", "node": 4376, "naklon": 15 }, +{ "label": "1/5", "node": 3868, "naklon": 15 }, +{ "label": "1/6", "node": 3728, "naklon": 15 }, +{ "label": "1/7", "node": 3730, "naklon": 0 }, +{ "label": "1/8", "node": 4374, "naklon": 0 }, +{ "label": "1/9", "node": 3718, "naklon": 15 }, +{ "label": "1/10", "node": 4375, "naklon": 15 }, +{ "label": "1/11", "node": 4172, "naklon": 15 }, +{ "label": "1/12", "node": 4176, "naklon": 15 }, +{ "label": "2/1", "node": 3800, "naklon": 5 }, +{ "label": "2/2", "node": 3823, "naklon": 5 }, +{ "label": "2/3", "node": 3905, "naklon": 5 }, +{ "label": "2/4", "node": 3803, "naklon": 5 }, +{ "label": "2/5", "node": 3817, "naklon": 5 }, +{ "label": "2/6", "node": 3818, "naklon": 5 }, +{ "label": "2/7", "node": 3811, "naklon": 5 }, +{ "label": "2/8", "node": 3915, "naklon": 5 }, +{ "label": "2/9", "node": 3843, "naklon": 10 }, +{ "label": "2/10", "node": 3827, "naklon": 10 }, +{ "label": "2/11", "node": 4220, "naklon": 10 }, +{ "label": "2/12", "node": 3826, "naklon": 10 }, +{ "label": "2/13", "node": 3834, "naklon": 10 }, +{ "label": "2/14", "node": 3838, "naklon": 10 }, +{ "label": "2/15", "node": 2823, "naklon": 10 }, +{ "label": "2/16", "node": 3750, "naklon": 10 }, +{ "label": "2/17", "node": 3378, "naklon": 0 }, +{ "label": "2/18", "node": 3376, "naklon": 0 }, +{ "label": "2/19", "node": 3379, "naklon": 0 }, +{ "label": "2/20", "node": 3285, "naklon": 0 }, +{ "label": "2/21", "node": 3382, "naklon": 0 }, +{ "label": "2/22", "node": 3383, "naklon": 0 }, +{ "label": "2/24", "node": 3375, "naklon": 0 }, +{ "label": "2/25", "node": 3381, "naklon": 0 }, +{ "label": "2/26", "node": 3380, "naklon": 0 }, +{ "label": "2/27", "node": 3828, "naklon": 10 }, +{ "label": "2/28", "node": 3377, "naklon": 0 }, +{ "label": "7/1", "node": 3591, "naklon": 0 }, +{ "label": "7/2", "node": 3587, "naklon": 0 }, +{ "label": "7/3", "node": 3468, "naklon": 0 }, +{ "label": "7/4", "node": 3466, "naklon": 0 }, +{ "label": "7/5", "node": 3474, "naklon": 0 }, +{ "label": "7/6", "node": 3481, "naklon": 0 }, +{ "label": "7/7", "node": 3589, "naklon": 0 }, +{ "label": "7/8", "node": 3472, "naklon": 0 }, +{ "label": "7/9", "node": 3473, "naklon": 0 }, +{ "label": "7/10", "node": 3584, "naklon": 0 }, +{ "label": "7/11", "node": 3571, "naklon": 0 }, +{ "label": "7/12", "node": 3476, "naklon": 0 }, +{ "label": "7/13", "node": 3590, "naklon": 0 }, +{ "label": "7/14", "node": 3478, "naklon": 0 }, +{ "label": "7/15", "node": 3471, "naklon": 0 }, +{ "label": "7/16", "node": 3467, "naklon": 0 }, +{ "label": "7/17", "node": 3479, "naklon": 0 }, +{ "label": "7/18", "node": 3480, "naklon": 0 }, +{ "label": "7/19", "node": 3477, "naklon": 0 }, +{ "label": "12/1", "node": 3362, "naklon": 0 }, +{ "label": "12/2", "node": 3355, "naklon": 0 }, +{ "label": "12/3", "node": 3356, "naklon": 0 }, +{ "label": "12/4", "node": 3349, "naklon": 0 }, +{ "label": "12/5", "node": 3357, "naklon": 0 }, +{ "label": "12/6", "node": 3350, "naklon": 0 }, +{ "label": "12/7", "node": 3353, "naklon": 0 }, +{ "label": "12/8", "node": 3539, "naklon": 0 }, +{ "label": "12/9", "node": 3050, "naklon": 0 }, +{ "label": "12/10", "node": 3361, "naklon": 0 }, +{ "label": "12/11", "node": 3360, "naklon": 0 }, +{ "label": "12/12", "node": 3358, "naklon": 0 }, +{ "label": "12/13", "node": 3541, "naklon": 0 }, +{ "label": "12/14", "node": 3551, "naklon": 0 }, +{ "label": "12/15", "node": 3514, "naklon": 0 }, +{ "label": "12/16", "node": 3547, "naklon": 0 }, +{ "label": "12/17", "node": 3562, "naklon": 0 }, +{ "label": "12/18", "node": 3525, "naklon": 0 }, +{ "label": "12/19", "node": 3558, "naklon": 0 }, +{ "label": "12/20", "node": 3511, "naklon": 0 }, +{ "label": "12/21", "node": 3058, "naklon": 0 }, +{ "label": "12/22", "node": 3062, "naklon": 0 }, +{ "label": "12/23", "node": 3070, "naklon": 0 }, +{ "label": "12/24", "node": 3447, "naklon": 0 }, +{ "label": "12/25", "node": 3056, "naklon": 0 }, +{ "label": "12/26", "node": 3057, "naklon": 0 }, +{ "label": "12/27", "node": 3071, "naklon": 0 }, +{ "label": "12/28", "node": 3061, "naklon": 0 }, +{ "label": "12/29", "node": 3069, "naklon": 0 }, +{ "label": "12/30", "node": 3077, "naklon": 0 }, +{ "label": "12/31", "node": 3080, "naklon": 0 }, +{ "label": "12/32", "node": 3081, "naklon": 0 }, +{ "label": "12/33", "node": 3078, "naklon": 0 }, +{ "label": "12/34", "node": 4037, "naklon": 0 }, +{ "label": "12/35", "node": 3067, "naklon": 0 }, +{ "label": "12/36", "node": 3051, "naklon": 0 }, +{ "label": "12/37", "node": 2924, "naklon": 0 }, +{ "label": "12/38", "node": 3060, "naklon": 0 }, +{ "label": "12/39", "node": 3073, "naklon": 0 }, +{ "label": "12/40", "node": 3469, "naklon": 0 }, +{ "label": "12/41", "node": 2923, "naklon": 0 }, +{ "label": "12/42", "node": 2925, "naklon": 0 }, +{ "label": "12/43", "node": 3359, "naklon": 0 }, +{ "label": "12/44", "node": 3055, "naklon": 0 }, +{ "label": "12/45", "node": 2922, "naklon": 0 }, +{ "label": "12/46", "node": 3084, "naklon": 0 }, +{ "label": "12/47", "node": 3064, "naklon": 0 }, +{ "label": "12/48", "node": 3066, "naklon": 0 }, +{ "label": "12/49", "node": 3072, "naklon": 0 }, +{ "label": "13/13A", "node": 3415, "naklon": 0 }, +{ "label": "13/13B", "node": 3409, "naklon": 0 }, +{ "label": "13/13C", "node": 3399, "naklon": 0 }, +{ "label": "13/29A", "node": 3410, "naklon": 0 }, +{ "label": "13/29B", "node": 3407, "naklon": 0 }, +{ "label": "13/34A", "node": 3405, "naklon": 0 }, +{ "label": "13/34B", "node": 3404, "naklon": 0 }, +{ "label": "13/45A", "node": 3392, "naklon": 0 }, +{ "label": "13/45B", "node": 3386, "naklon": 0 }, +{ "label": "13/60A", "node": 3303, "naklon": 3 }, +{ "label": "13/60B", "node": 3302, "naklon": 3 }, +{ "label": "13/70A", "node": 3319, "naklon": 6 }, +{ "label": "13/70B", "node": 3317, "naklon": 6 }, +{ "label": "13/70C", "node": 3326, "naklon": 6 }, +{ "label": "13/73A", "node": 3351, "naklon": 6 }, +{ "label": "13/73B", "node": 3313, "naklon": 6 }, +{ "label": "13/83A", "node": 3316, "naklon": 0 }, +{ "label": "13/83B", "node": 3320, "naklon": 0 }, +{ "label": "13/95A", "node": 3336, "naklon": 0 }, +{ "label": "13/95B", "node": 3323, "naklon": 0 }, +{ "label": "13/98A", "node": 3339, "naklon": 0 }, +{ "label": "13/98B", "node": 3333, "naklon": 0 }, +{ "label": "13/1", "node": 3425, "naklon": 0 }, +{ "label": "13/2", "node": 3419, "naklon": 0 }, +{ "label": "13/3", "node": 3416, "naklon": 0 }, +{ "label": "13/4", "node": 3332, "naklon": 0 }, +{ "label": "13/5", "node": 3422, "naklon": 0 }, +{ "label": "13/6", "node": 3417, "naklon": 0 }, +{ "label": "13/7", "node": 3418, "naklon": 0 }, +{ "label": "13/8", "node": 3424, "naklon": 0 }, +{ "label": "13/9", "node": 3334, "naklon": 0 }, +{ "label": "13/10", "node": 4363, "naklon": 0 }, +{ "label": "13/11", "node": 3423, "naklon": 0 }, +{ "label": "13/12", "node": 3406, "naklon": 0 }, +{ "label": "13/14", "node": 3411, "naklon": 0 }, +{ "label": "13/15", "node": 3412, "naklon": 0 }, +{ "label": "13/16", "node": 3413, "naklon": 0 }, +{ "label": "13/17", "node": 3414, "naklon": 0 }, +{ "label": "13/18", "node": 3391, "naklon": 0 }, +{ "label": "13/19", "node": 3370, "naklon": 0 }, +{ "label": "13/20", "node": 3369, "naklon": 0 }, +{ "label": "13/21", "node": 3408, "naklon": 0 }, +{ "label": "13/22", "node": 3393, "naklon": 0 }, +{ "label": "13/23", "node": 3128, "naklon": 0 }, +{ "label": "13/24", "node": 3197, "naklon": 0 }, +{ "label": "13/25", "node": 4364, "naklon": 0 }, +{ "label": "13/26", "node": 3155, "naklon": 0 }, +{ "label": "13/27", "node": 3196, "naklon": 0 }, +{ "label": "13/28", "node": 3144, "naklon": 0 }, +{ "label": "13/30", "node": 3150, "naklon": 0 }, +{ "label": "13/31", "node": 3390, "naklon": 0 }, +{ "label": "13/32", "node": 3401, "naklon": 0 }, +{ "label": "13/33", "node": 3275, "naklon": 0 }, +{ "label": "13/35", "node": 3371, "naklon": 0 }, +{ "label": "13/36", "node": 3389, "naklon": 0 }, +{ "label": "13/37", "node": 3388, "naklon": 0 }, +{ "label": "13/38", "node": 3365, "naklon": 0 }, +{ "label": "13/39", "node": 3363, "naklon": 0 }, +{ "label": "13/40", "node": 3397, "naklon": 0 }, +{ "label": "13/40/1", "node": 3567, "naklon": 0 }, +{ "label": "13/41", "node": 3387, "naklon": 0 }, +{ "label": "13/42", "node": 3403, "naklon": 0 }, +{ "label": "13/43", "node": 3147, "naklon": 0 }, +{ "label": "13/44", "node": 3141, "naklon": 0 }, +{ "label": "13/46", "node": 3364, "naklon": 0 }, +{ "label": "13/47", "node": 3367, "naklon": 0 }, +{ "label": "13/48", "node": 3368, "naklon": 0 }, +{ "label": "13/49", "node": 3402, "naklon": 0 }, +{ "label": "13/50", "node": 3366, "naklon": 0 }, +{ "label": "13/51", "node": 3395, "naklon": 0 }, +{ "label": "13/52", "node": 3372, "naklon": 0 }, +{ "label": "13/53", "node": 3394, "naklon": 0 }, +{ "label": "13/54", "node": 3308, "naklon": 0 }, +{ "label": "13/54/1", "node": 3847, "naklon": 0 }, +{ "label": "13/55", "node": 3312, "naklon": 3 }, +{ "label": "13/56", "node": 3309, "naklon": 3 }, +{ "label": "13/57", "node": 3311, "naklon": 3 }, +{ "label": "13/58", "node": 3310, "naklon": 3 }, +{ "label": "13/59", "node": 4365, "naklon": 3 }, +{ "label": "13/60/1", "node": 4093, "naklon": 3 }, +{ "label": "13/61", "node": 3304, "naklon": 3 }, +{ "label": "13/62", "node": 3307, "naklon": 3 }, +{ "label": "13/63", "node": 3271, "naklon": 3 }, +{ "label": "13/64", "node": 3301, "naklon": 3 }, +{ "label": "13/65", "node": 4366, "naklon": 3 }, +{ "label": "13/66", "node": 3300, "naklon": 3 }, +{ "label": "13/67", "node": 3185, "naklon": 0 }, +{ "label": "13/68", "node": 3184, "naklon": 0 }, +{ "label": "13/69", "node": 3188, "naklon": 0 }, +{ "label": "13/71", "node": 3343, "naklon": 6 }, +{ "label": "13/71/1", "node": 3819, "naklon": 6 }, +{ "label": "13/71/2", "node": 3880, "naklon": 6 }, +{ "label": "13/72", "node": 3348, "naklon": 6 }, +{ "label": "13/74", "node": 3344, "naklon": 6 }, +{ "label": "13/75", "node": 3346, "naklon": 6 }, +{ "label": "13/75/1", "node": 3597, "naklon": 6 }, +{ "label": "13/76", "node": 3345, "naklon": 6 }, +{ "label": "13/77", "node": 3322, "naklon": 0 }, +{ "label": "13/78", "node": 3325, "naklon": 0 }, +{ "label": "13/78/1", "node": 4310, "naklon": 0 }, +{ "label": "13/79", "node": 3315, "naklon": 0 }, +{ "label": "13/80", "node": 3328, "naklon": 0 }, +{ "label": "13/81", "node": 3321, "naklon": 0 }, +{ "label": "13/82", "node": 3324, "naklon": 0 }, +{ "label": "13/84", "node": 3140, "naklon": 0 }, +{ "label": "13/85", "node": 3153, "naklon": 0 }, +{ "label": "13/86", "node": 3145, "naklon": 0 }, +{ "label": "13/87", "node": 3134, "naklon": 0 }, +{ "label": "13/88", "node": 3151, "naklon": 0 }, +{ "label": "13/89", "node": 3143, "naklon": 0 }, +{ "label": "13/90", "node": 3318, "naklon": 0 }, +{ "label": "13/91", "node": 3347, "naklon": 0 }, +{ "label": "13/94", "node": 3314, "naklon": 0 }, +{ "label": "13/96", "node": 3331, "naklon": 0 }, +{ "label": "13/97", "node": 3327, "naklon": 0 }, +{ "label": "13/99", "node": 3329, "naklon": 0 }, +{ "label": "13/100", "node": 3337, "naklon": 0 }, +{ "label": "13/101", "node": 3330, "naklon": 0 }, +{ "label": "13/102", "node": 3335, "naklon": 0 }, +{ "label": "13/103", "node": 3420, "naklon": 0 }, +{ "label": "13/104", "node": 3421, "naklon": 0 }, +{ "label": "13/105", "node": 4361, "naklon": 0 }, +{ "label": "13/106", "node": 4362, "naklon": 0 }, +{ "label": "13/107", "node": 3526, "naklon": 0 }, +{ "label": "13/108", "node": 4424, "naklon": null }, +{ "label": "13/109", "node": 3561, "naklon": null }, +{ "label": "13/110", "node": 3527, "naklon": null }, +{ "label": "13/111", "node": 3521, "naklon": null }, +{ "label": "13/112", "node": 3552, "naklon": null }, +{ "label": "13/113", "node": 3544, "naklon": null }, +{ "label": "13/114", "node": 3534, "naklon": null }, +{ "label": "13/115", "node": 3516, "naklon": null }, +{ "label": "13/116", "node": 3513, "naklon": null }, +{ "label": "13/117", "node": 3565, "naklon": null }, +{ "label": "13/118", "node": 3866, "naklon": null }, +{ "label": "14/1", "node": 3136, "naklon": 0 }, +{ "label": "14/2", "node": 3137, "naklon": 0 }, +{ "label": "14/3", "node": 3135, "naklon": 0 }, +{ "label": "14/4", "node": 3149, "naklon": 0 }, +{ "label": "14/5", "node": 3142, "naklon": 0 }, +{ "label": "14/6", "node": 3342, "naklon": 0 }, +{ "label": "14/7", "node": 3340, "naklon": 0 }, +{ "label": "14/8", "node": 3152, "naklon": 0 }, +{ "label": "14/9", "node": 3886, "naklon": 0 }, +{ "label": "14/10", "node": 3341, "naklon": null }, +{ "label": "14/11", "node": 3352, "naklon": null }, +{ "label": "15/1", "node": 3396, "naklon": 5 }, +{ "label": "15/2", "node": 2784, "naklon": 5 }, +{ "label": "15/3", "node": 2788, "naklon": 5 }, +{ "label": "15/4", "node": 2801, "naklon": 5 }, +{ "label": "15/5", "node": 2815, "naklon": 5 }, +{ "label": "15/6", "node": 2829, "naklon": 5 }, +{ "label": "15/7", "node": 2796, "naklon": 5 }, +{ "label": "15/8", "node": 2803, "naklon": 5 }, +{ "label": "15/8/1", "node": 4304, "naklon": 5 }, +{ "label": "15/8/2", "node": 4311, "naklon": 5 }, +{ "label": "15/9", "node": 2821, "naklon": 5 }, +{ "label": "15/10", "node": 3400, "naklon": 5 }, +{ "label": "15/11", "node": 2799, "naklon": 5 }, +{ "label": "15/12", "node": 2804, "naklon": 5 }, +{ "label": "15/12/1", "node": 4303, "naklon": 5 }, +{ "label": "15/12/2", "node": 4309, "naklon": 5 }, +{ "label": "15/13", "node": 2806, "naklon": 5 }, +{ "label": "15/14", "node": 2787, "naklon": 5 }, +{ "label": "15/15", "node": 2809, "naklon": 5 }, +{ "label": "15/16", "node": 2814, "naklon": 0 }, +{ "label": "15/17", "node": 3934, "naklon": 0 }, +{ "label": "15/18", "node": 3192, "naklon": 0 }, +{ "label": "15/19", "node": 2812, "naklon": 0 }, +{ "label": "15/20", "node": 4070, "naklon": 0 }, +{ "label": "15/21", "node": 2826, "naklon": 0 }, +{ "label": "15/22", "node": 2808, "naklon": 3 }, +{ "label": "15/23", "node": 2795, "naklon": 3 }, +{ "label": "15/24", "node": 2807, "naklon": 3 }, +{ "label": "15/25", "node": 2831, "naklon": 0 }, +{ "label": "15/26", "node": 2862, "naklon": null }, +{ "label": "15/27", "node": 2861, "naklon": 0 }, +{ "label": "15/28", "node": 2866, "naklon": 0 }, +{ "label": "15/28/1", "node": 3546, "naklon": 0 }, +{ "label": "15/29", "node": 4146, "naklon": 0 }, +{ "label": "15/29/1", "node": 3001, "naklon": 0 }, +{ "label": "15/30", "node": 2835, "naklon": 0 }, +{ "label": "15/31", "node": 2874, "naklon": 0 }, +{ "label": "15/32", "node": 2852, "naklon": 0 }, +{ "label": "15/33", "node": 2851, "naklon": 0 }, +{ "label": "15/33/1", "node": 3560, "naklon": 0 }, +{ "label": "15/34", "node": 2858, "naklon": 0 }, +{ "label": "15/34/1", "node": 4306, "naklon": 0 }, +{ "label": "15/35", "node": 2856, "naklon": 0 }, +{ "label": "15/36", "node": 2847, "naklon": 0 }, +{ "label": "15/36/1", "node": 3556, "naklon": 0 }, +{ "label": "15/37", "node": 3950, "naklon": 0 }, +{ "label": "15/38", "node": 2848, "naklon": 0 }, +{ "label": "15/39", "node": 2863, "naklon": 0 }, +{ "label": "15/39/1", "node": 4313, "naklon": 0 }, +{ "label": "15/40", "node": 2873, "naklon": 0 }, +{ "label": "15/40/1", "node": 2984, "naklon": 0 }, +{ "label": "15/41", "node": 2854, "naklon": 0 }, +{ "label": "15/42", "node": 2859, "naklon": 0 }, +{ "label": "15/43", "node": 2872, "naklon": 0 }, +{ "label": "15/44", "node": 2849, "naklon": 0 }, +{ "label": "15/45", "node": 2864, "naklon": 0 }, +{ "label": "15/46", "node": 3553, "naklon": null }, +{ "label": "15/47", "node": 3021, "naklon": null }, +{ "label": "15/47/1", "node": 3008, "naklon": null }, +{ "label": "15/48", "node": 3017, "naklon": null }, +{ "label": "15/49", "node": 3014, "naklon": null }, +{ "label": "15/50", "node": 2981, "naklon": null }, +{ "label": "15/51", "node": 3020, "naklon": null }, +{ "label": "15/52", "node": 3027, "naklon": null }, +{ "label": "15/53", "node": 3006, "naklon": null }, +{ "label": "15/54", "node": 3012, "naklon": null }, +{ "label": "15/55", "node": 2738, "naklon": 0 }, +{ "label": "15/56", "node": 2725, "naklon": 0 }, +{ "label": "15/57", "node": 3016, "naklon": null }, +{ "label": "15/58", "node": 3005, "naklon": null }, +{ "label": "15/58/1", "node": 3009, "naklon": null }, +{ "label": "15/59", "node": 3010, "naklon": 0 }, +{ "label": "15/59/1", "node": 3538, "naklon": 0 }, +{ "label": "15/59/2", "node": 4145, "naklon": 0 }, +{ "label": "15/60", "node": 2713, "naklon": 0 }, +{ "label": "15/61", "node": 2789, "naklon": 0 }, +{ "label": "15/62", "node": 2736, "naklon": 0 }, +{ "label": "15/63", "node": 2739, "naklon": 0 }, +{ "label": "15/64", "node": 4346, "naklon": 0 }, +{ "label": "15/65", "node": 2731, "naklon": 0 }, +{ "label": "15/66", "node": 2818, "naklon": 0 }, +{ "label": "15/66/1", "node": 3557, "naklon": 0 }, +{ "label": "15/67", "node": 2822, "naklon": 0 }, +{ "label": "15/68", "node": 2833, "naklon": 0 }, +{ "label": "15/69", "node": 2834, "naklon": 0 }, +{ "label": "15/70", "node": 3097, "naklon": 0 }, +{ "label": "15/71", "node": 2824, "naklon": 0 }, +{ "label": "15/72", "node": 2828, "naklon": 0 }, +{ "label": "15/73", "node": 2600, "naklon": 0 }, +{ "label": "15/73/1", "node": 4314, "naklon": 0 }, +{ "label": "15/74", "node": 2832, "naklon": 0 }, +{ "label": "15/75", "node": 4360, "naklon": 0 }, +{ "label": "15/76", "node": 2846, "naklon": 0 }, +{ "label": "15/77", "node": 2584, "naklon": 0 }, +{ "label": "15/78", "node": 2843, "naklon": 0 }, +{ "label": "15/78/1", "node": 4308, "naklon": 0 }, +{ "label": "15/79", "node": 4144, "naklon": null }, +{ "label": "15/80", "node": 2844, "naklon": 0 }, +{ "label": "15/81", "node": 2842, "naklon": 0 }, +{ "label": "15/82", "node": 2838, "naklon": 0 }, +{ "label": "15/83", "node": 2837, "naklon": null }, +{ "label": "15/83/1", "node": 3555, "naklon": null }, +{ "label": "15/84", "node": 2839, "naklon": 0 }, +{ "label": "15/85", "node": 2830, "naklon": 0 }, +{ "label": "15/86", "node": 4066, "naklon": 0 }, +{ "label": "15/87", "node": 2836, "naklon": 0 }, +{ "label": "15/88", "node": 2911, "naklon": 0 }, +{ "label": "15/89", "node": 2825, "naklon": 0 }, +{ "label": "15/90", "node": 2811, "naklon": 0 }, +{ "label": "15/94", "node": 3740, "naklon": 15 }, +{ "label": "15/95", "node": 2734, "naklon": 15 }, +{ "label": "15/96", "node": 3105, "naklon": 15 }, +{ "label": "15/97", "node": 2732, "naklon": 15 }, +{ "label": "15/98", "node": 2727, "naklon": 15 }, +{ "label": "15/99", "node": 2735, "naklon": 15 }, +{ "label": "15/100", "node": 3926, "naklon": 15 }, +{ "label": "15/101", "node": 2918, "naklon": 0 }, +{ "label": "15/102", "node": 2705, "naklon": 10 }, +{ "label": "15/103", "node": 2708, "naklon": 10 }, +{ "label": "15/104", "node": 2721, "naklon": 10 }, +{ "label": "15/105", "node": 2719, "naklon": 10 }, +{ "label": "15/106", "node": 2919, "naklon": 10 }, +{ "label": "15/107", "node": 3101, "naklon": 10 }, +{ "label": "15/108", "node": 2853, "naklon": 10 }, +{ "label": "15/109", "node": 2715, "naklon": 10 }, +{ "label": "15/110", "node": 2712, "naklon": 0 }, +{ "label": "15/111", "node": 2711, "naklon": 0 }, +{ "label": "15/112", "node": 2709, "naklon": 0 }, +{ "label": "15/113", "node": 2710, "naklon": 0 }, +{ "label": "15/114", "node": 2907, "naklon": 0 }, +{ "label": "15/115", "node": 2906, "naklon": 0 }, +{ "label": "15/116", "node": 2908, "naklon": 0 }, +{ "label": "15/117", "node": 2901, "naklon": 0 }, +{ "label": "15/118", "node": 2913, "naklon": 0 }, +{ "label": "15/119", "node": 3656, "naklon": 0 }, +{ "label": "15/120", "node": 2781, "naklon": 0 }, +{ "label": "15/121", "node": 2802, "naklon": 0 }, +{ "label": "15/122", "node": 2791, "naklon": 0 }, +{ "label": "15/123", "node": 2783, "naklon": 0 }, +{ "label": "15/124", "node": 2794, "naklon": 0 }, +{ "label": "15/125", "node": 3139, "naklon": 0 }, +{ "label": "15/126", "node": 3229, "naklon": 5 }, +{ "label": "15/127", "node": 3239, "naklon": 5 }, +{ "label": "15/128", "node": 3230, "naklon": 5 }, +{ "label": "15/129", "node": 4016, "naklon": null }, +{ "label": "16/16A", "node": 3608, "naklon": 0 }, +{ "label": "16/16B", "node": 4151, "naklon": 0 }, +{ "label": "16/1", "node": 3710, "naklon": 0 }, +{ "label": "16/2", "node": 3726, "naklon": 0 }, +{ "label": "16/3", "node": 3743, "naklon": 0 }, +{ "label": "16/4", "node": 3724, "naklon": 0 }, +{ "label": "16/5", "node": 3712, "naklon": 0 }, +{ "label": "16/6", "node": 3739, "naklon": 0 }, +{ "label": "16/7", "node": 3742, "naklon": 0 }, +{ "label": "16/8", "node": 3731, "naklon": 0 }, +{ "label": "16/9", "node": 3727, "naklon": 0 }, +{ "label": "16/10", "node": 3729, "naklon": 0 }, +{ "label": "16/11", "node": 3736, "naklon": 0 }, +{ "label": "16/12", "node": 3713, "naklon": 0 }, +{ "label": "16/13", "node": 3715, "naklon": 0 }, +{ "label": "16/14", "node": 3733, "naklon": 0 }, +{ "label": "16/15", "node": 3732, "naklon": 0 }, +{ "label": "16/17", "node": 3634, "naklon": 0 }, +{ "label": "16/18", "node": 3610, "naklon": 0 }, +{ "label": "16/19", "node": 3626, "naklon": 0 }, +{ "label": "16/20", "node": 3618, "naklon": 0 }, +{ "label": "16/21", "node": 3619, "naklon": 0 }, +{ "label": "16/22", "node": 3628, "naklon": 0 }, +{ "label": "16/23", "node": 3615, "naklon": 0 }, +{ "label": "16/24", "node": 3609, "naklon": 0 }, +{ "label": "16/25", "node": 3606, "naklon": 0 }, +{ "label": "16/26", "node": 3624, "naklon": 0 }, +{ "label": "16/27", "node": 3627, "naklon": 0 }, +{ "label": "16/28", "node": 3607, "naklon": 0 }, +{ "label": "16/29", "node": 4370, "naklon": 0 }, +{ "label": "16/30", "node": 3692, "naklon": 0 }, +{ "label": "16/31", "node": 3614, "naklon": 0 }, +{ "label": "16/32", "node": 3623, "naklon": 0 }, +{ "label": "16/33", "node": 4373, "naklon": 0 }, +{ "label": "16/34", "node": 3620, "naklon": 0 }, +{ "label": "16/35", "node": 3685, "naklon": 0 }, +{ "label": "16/36", "node": 3616, "naklon": 0 }, +{ "label": "16/37", "node": 3686, "naklon": 0 }, +{ "label": "16/38", "node": 3688, "naklon": 0 }, +{ "label": "16/39", "node": 3684, "naklon": 0 }, +{ "label": "16/40", "node": 3825, "naklon": 0 }, +{ "label": "16/41", "node": 3865, "naklon": 0 }, +{ "label": "16/42", "node": 3824, "naklon": 0 }, +{ "label": "16/43", "node": 3871, "naklon": 0 }, +{ "label": "16/44", "node": 3801, "naklon": 0 }, +{ "label": "16/45", "node": 3862, "naklon": 0 }, +{ "label": "16/46", "node": 3876, "naklon": 0 }, +{ "label": "16/47", "node": 3861, "naklon": 0 }, +{ "label": "16/48", "node": 4215, "naklon": 0 }, +{ "label": "16/49", "node": 3605, "naklon": 10 }, +{ "label": "16/50", "node": 3603, "naklon": 10 }, +{ "label": "16/51", "node": 3592, "naklon": 10 }, +{ "label": "16/52", "node": 3598, "naklon": 10 }, +{ "label": "16/53", "node": 3594, "naklon": 10 }, +{ "label": "16/54", "node": 3593, "naklon": 10 }, +{ "label": "16/55", "node": 3630, "naklon": 10 }, +{ "label": "16/56", "node": 3763, "naklon": 10 }, +{ "label": "16/57", "node": 3746, "naklon": 10 }, +{ "label": "16/58", "node": 3699, "naklon": 0 }, +{ "label": "16/59", "node": 3698, "naklon": 0 }, +{ "label": "16/60", "node": 3709, "naklon": null }, +{ "label": "16/61", "node": 3708, "naklon": 0 }, +{ "label": "16/62", "node": 3703, "naklon": null }, +{ "label": "16/63", "node": 3700, "naklon": 0 }, +{ "label": "16/64", "node": 3701, "naklon": null }, +{ "label": "16/65", "node": 3704, "naklon": 0 }, +{ "label": "16/66", "node": 3707, "naklon": null }, +{ "label": "16/67", "node": 3810, "naklon": 0 }, +{ "label": "16/68", "node": 4208, "naklon": null }, +{ "label": "16/69", "node": 3867, "naklon": 0 }, +{ "label": "16/70", "node": 4372, "naklon": null }, +{ "label": "16/71", "node": 3881, "naklon": 0 }, +{ "label": "16/72", "node": 4204, "naklon": null }, +{ "label": "16/73", "node": 3869, "naklon": 0 }, +{ "label": "16/74", "node": 4202, "naklon": null }, +{ "label": "16/75", "node": 3830, "naklon": 0 }, +{ "label": "16/76", "node": 3870, "naklon": null }, +{ "label": "16/77", "node": 3964, "naklon": 0 }, +{ "label": "16/78", "node": 3849, "naklon": 0 }, +{ "label": "16/79", "node": 3694, "naklon": null }, +{ "label": "16/80", "node": 3717, "naklon": 0 }, +{ "label": "16/81", "node": 3877, "naklon": null }, +{ "label": "16/82", "node": 3755, "naklon": 0 }, +{ "label": "16/83", "node": 3725, "naklon": null }, +{ "label": "16/84", "node": 3716, "naklon": 0 }, +{ "label": "16/85", "node": 3696, "naklon": null }, +{ "label": "16/86", "node": 3702, "naklon": 0 }, +{ "label": "16/87", "node": 3706, "naklon": null }, +{ "label": "16/88", "node": 3850, "naklon": 0 }, +{ "label": "16/89", "node": 3848, "naklon": null }, +{ "label": "16/90", "node": 3737, "naklon": null }, +{ "label": "16/91", "node": 3705, "naklon": 0 }, +{ "label": "16/92", "node": 3723, "naklon": null }, +{ "label": "16/93", "node": 3842, "naklon": 0 }, +{ "label": "16/94", "node": 3735, "naklon": null }, +{ "label": "16/95", "node": 3719, "naklon": 0 }, +{ "label": "16/96", "node": 3697, "naklon": 0 }, +{ "label": "16/97", "node": 3711, "naklon": 0 }, +{ "label": "16/98", "node": 4107, "naklon": null }, +{ "label": "16/99", "node": 4112, "naklon": 5 }, +{ "label": "16/100", "node": 4106, "naklon": 5 }, +{ "label": "16/101", "node": 4111, "naklon": 5 }, +{ "label": "16/102", "node": 4091, "naklon": null }, +{ "label": "16/103", "node": 4104, "naklon": 5 }, +{ "label": "16/104", "node": 4094, "naklon": null }, +{ "label": "16/105", "node": 4089, "naklon": 5 }, +{ "label": "16/106", "node": 4095, "naklon": null }, +{ "label": "16/107", "node": 4102, "naklon": 5 }, +{ "label": "16/108", "node": 4105, "naklon": null }, +{ "label": "16/109", "node": 3859, "naklon": null }, +{ "label": "16/110", "node": 4090, "naklon": 5 }, +{ "label": "16/111", "node": 4110, "naklon": null }, +{ "label": "16/112", "node": 4097, "naklon": 5 }, +{ "label": "16/113", "node": 4099, "naklon": null }, +{ "label": "16/114", "node": 4096, "naklon": null }, +{ "label": "16/115", "node": 4101, "naklon": 5 }, +{ "label": "16/116", "node": 4109, "naklon": null }, +{ "label": "16/117", "node": 4092, "naklon": 5 }, +{ "label": "16/118", "node": 3631, "naklon": null }, +{ "label": "16/119", "node": 3632, "naklon": 0 }, +{ "label": "16/120", "node": 3641, "naklon": null }, +{ "label": "16/121", "node": 3638, "naklon": 0 }, +{ "label": "16/122", "node": 3637, "naklon": null }, +{ "label": "16/123", "node": 4142, "naklon": null }, +{ "label": "16/124", "node": 4147, "naklon": 5 }, +{ "label": "16/125", "node": 4139, "naklon": 5 }, +{ "label": "20/30A", "node": 3172, "naklon": 2 }, +{ "label": "20/30B", "node": 3164, "naklon": 2 }, +{ "label": "20/1", "node": 3247, "naklon": 10 }, +{ "label": "20/2", "node": 3296, "naklon": 10 }, +{ "label": "20/3", "node": 3246, "naklon": 10 }, +{ "label": "20/4", "node": 3270, "naklon": 10 }, +{ "label": "20/5", "node": 3294, "naklon": 10 }, +{ "label": "20/6", "node": 3298, "naklon": 10 }, +{ "label": "20/7", "node": 3297, "naklon": 10 }, +{ "label": "20/8", "node": 3293, "naklon": 10 }, +{ "label": "20/9", "node": 3299, "naklon": 10 }, +{ "label": "20/10", "node": 3295, "naklon": 10 }, +{ "label": "20/11", "node": 3244, "naklon": 10 }, +{ "label": "20/12", "node": 3249, "naklon": 10 }, +{ "label": "20/13", "node": 3268, "naklon": 10 }, +{ "label": "20/14", "node": 3245, "naklon": 10 }, +{ "label": "20/15", "node": 3278, "naklon": 10 }, +{ "label": "20/16", "node": 3280, "naklon": 10 }, +{ "label": "20/17", "node": 3292, "naklon": 10 }, +{ "label": "20/18", "node": 3287, "naklon": 10 }, +{ "label": "20/19", "node": 3282, "naklon": 10 }, +{ "label": "20/20", "node": 3273, "naklon": 0 }, +{ "label": "20/21", "node": 3157, "naklon": 0 }, +{ "label": "20/22", "node": 3283, "naklon": 0 }, +{ "label": "20/23", "node": 3159, "naklon": 0 }, +{ "label": "20/24", "node": 3289, "naklon": 0 }, +{ "label": "20/25", "node": 3163, "naklon": 0 }, +{ "label": "20/26", "node": 3126, "naklon": 0 }, +{ "label": "20/27", "node": 3171, "naklon": 0 }, +{ "label": "20/28", "node": 3162, "naklon": 0 }, +{ "label": "20/29", "node": 3279, "naklon": 10 }, +{ "label": "20/31", "node": 3173, "naklon": 0 }, +{ "label": "20/32", "node": 3127, "naklon": 0 }, +{ "label": "20/33", "node": 3131, "naklon": 0 }, +{ "label": "20/34", "node": 3129, "naklon": 0 }, +{ "label": "20/35", "node": 3276, "naklon": 2 }, +{ "label": "20/36", "node": 3290, "naklon": 2 }, +{ "label": "20/37", "node": 3132, "naklon": 0 }, +{ "label": "20/38", "node": 3138, "naklon": 0 }, +{ "label": "20/39", "node": 3272, "naklon": 0 }, +{ "label": "20/40", "node": 3291, "naklon": 0 }, +{ "label": "20/41", "node": 3277, "naklon": 10 }, +{ "label": "20/42", "node": 3286, "naklon": 10 }, +{ "label": "20/43", "node": 3281, "naklon": 10 }, +{ "label": "20/44", "node": 3288, "naklon": 10 }, +{ "label": "20/45", "node": 3284, "naklon": 10 }, +{ "label": "20/46", "node": 3167, "naklon": 10 }, +{ "label": "20/47", "node": 3872, "naklon": 0 }, +{ "label": "20/48", "node": 3124, "naklon": 0 }, +{ "label": "20/49", "node": 3133, "naklon": 0 }, +{ "label": "20/50", "node": 3158, "naklon": 0 }, +{ "label": "20/51", "node": 3169, "naklon": 0 }, +{ "label": "20/52", "node": 3146, "naklon": 0 }, +{ "label": "20/53", "node": 3160, "naklon": 0 }, +{ "label": "20/54", "node": 3248, "naklon": 0 }, +{ "label": "20/55", "node": 3156, "naklon": 0 }, +{ "label": "20/56", "node": 3161, "naklon": 0 }, +{ "label": "20/57", "node": 3170, "naklon": 0 }, +{ "label": "20/58", "node": 3168, "naklon": 0 }, +{ "label": "20/59", "node": 3125, "naklon": 0 }, +{ "label": "20/60", "node": 3166, "naklon": 0 }, +{ "label": "20/61", "node": 3130, "naklon": 0 }, +{ "label": "20/62", "node": 3563, "naklon": 0 }, +{ "label": "20/63", "node": 3550, "naklon": null }, +{ "label": "20/67", "node": 3269, "naklon": 0 }, +{ "label": "21/1", "node": 2921, "naklon": 0 }, +{ "label": "21/2", "node": 2707, "naklon": 0 }, +{ "label": "21/3", "node": 2723, "naklon": 0 }, +{ "label": "21/4", "node": 2716, "naklon": 0 }, +{ "label": "21/5", "node": 2717, "naklon": 0 }, +{ "label": "21/6", "node": 2720, "naklon": 0 }, +{ "label": "21/7", "node": 2722, "naklon": 0 }, +{ "label": "21/8", "node": 2718, "naklon": 0 }, +{ "label": "21/9", "node": 2724, "naklon": 0 }, +{ "label": "21/10", "node": 2742, "naklon": 0 }, +{ "label": "21/11", "node": 2743, "naklon": 0 }, +{ "label": "21/12", "node": 2733, "naklon": 0 }, +{ "label": "21/14", "node": 2903, "naklon": 0 }, +{ "label": "21/15", "node": 2917, "naklon": 0 }, +{ "label": "21/16", "node": 2897, "naklon": 0 }, +{ "label": "21/17", "node": 2914, "naklon": 0 }, +{ "label": "21/18", "node": 2898, "naklon": 0 }, +{ "label": "21/19", "node": 2773, "naklon": 0 }, +{ "label": "21/20", "node": 2895, "naklon": 0 }, +{ "label": "21/21", "node": 2896, "naklon": 0 }, +{ "label": "21/22", "node": 2771, "naklon": 0 }, +{ "label": "21/23", "node": 2772, "naklon": 0 }, +{ "label": "21/24", "node": 2793, "naklon": 0 }, +{ "label": "21/25", "node": 2902, "naklon": 0 }, +{ "label": "21/26", "node": 2910, "naklon": 0 }, +{ "label": "21/27", "node": 2909, "naklon": 0 }, +{ "label": "21/28", "node": 2920, "naklon": 0 }, +{ "label": "21/29", "node": 2916, "naklon": 0 }, +{ "label": "21/30", "node": 2904, "naklon": 0 }, +{ "label": "21/31", "node": 2915, "naklon": 0 }, +{ "label": "21/32", "node": 2905, "naklon": 0 }, +{ "label": "21/33", "node": 2900, "naklon": 0 }, +{ "label": "21/34", "node": 2899, "naklon": 0 }, +{ "label": "21/36", "node": 2741, "naklon": 0 }, +{ "label": "21/37", "node": 2714, "naklon": 0 }, +{ "label": "21/38", "node": 2701, "naklon": 0 }, +{ "label": "21/39", "node": 2703, "naklon": 0 }, +{ "label": "21/40", "node": 2704, "naklon": 0 }, +{ "label": "21/41", "node": 2702, "naklon": 0 }, +{ "label": "21/42", "node": 2706, "naklon": 0 }, +{ "label": "21/43", "node": 2776, "naklon": 0 }, +{ "label": "21/44", "node": 2770, "naklon": 0 }, +{ "label": "21/45", "node": 2786, "naklon": 0 }, +{ "label": "21/46", "node": 2779, "naklon": 0 }, +{ "label": "21/47", "node": 2782, "naklon": 0 }, +{ "label": "21/48", "node": 2785, "naklon": 0 }, +{ "label": "21/49", "node": 2769, "naklon": 0 }, +{ "label": "21/50", "node": 3354, "naklon": 0 }, +{ "label": "21/51", "node": 2778, "naklon": 0 }, +{ "label": "21/52", "node": 2775, "naklon": 0 }, +{ "label": "21/53", "node": 2780, "naklon": 0 }, +{ "label": "21/54", "node": 2790, "naklon": 0 }, +{ "label": "21/55", "node": 2792, "naklon": 0 }, +{ "label": "21/56", "node": 2774, "naklon": 0 }, +{ "label": "22/1", "node": 2630, "naklon": 0 }, +{ "label": "22/2", "node": 2631, "naklon": 0 }, +{ "label": "22/3", "node": 2632, "naklon": 0 }, +{ "label": "22/4", "node": 2633, "naklon": 0 }, +{ "label": "22/5", "node": 2634, "naklon": 0 }, +{ "label": "22/6", "node": 2636, "naklon": 0 }, +{ "label": "22/7", "node": 4367, "naklon": 0 }, +{ "label": "22/8", "node": 2637, "naklon": 0 }, +{ "label": "22/9", "node": 2638, "naklon": 0 }, +{ "label": "22/10", "node": 2639, "naklon": 0 }, +{ "label": "22/11", "node": 2640, "naklon": 0 }, +{ "label": "22/12", "node": 2641, "naklon": 0 }, +{ "label": "22/13", "node": 2642, "naklon": 0 }, +{ "label": "22/14", "node": 2643, "naklon": 0 }, +{ "label": "22/15", "node": 2644, "naklon": 0 }, +{ "label": "22/16", "node": 2645, "naklon": 0 }, +{ "label": "22/17", "node": 2646, "naklon": 0 }, +{ "label": "22/18", "node": 2647, "naklon": 0 }, +{ "label": "22/19", "node": 2648, "naklon": 0 }, +{ "label": "22/20", "node": 2649, "naklon": 0 }, +{ "label": "22/21", "node": 2650, "naklon": 0 }, +{ "label": "22/22", "node": 2651, "naklon": 0 }, +{ "label": "22/23", "node": 4103, "naklon": 0 }, +{ "label": "22/24", "node": 2653, "naklon": 0 }, +{ "label": "22/25", "node": 2654, "naklon": 0 }, +{ "label": "22/26", "node": 2655, "naklon": 0 }, +{ "label": "22/27", "node": 2656, "naklon": 0 }, +{ "label": "22/28", "node": 2657, "naklon": 0 }, +{ "label": "22/29", "node": 2658, "naklon": 0 }, +{ "label": "22/30", "node": 2659, "naklon": 0 }, +{ "label": "22/31", "node": 2660, "naklon": 0 }, +{ "label": "22/32", "node": 2661, "naklon": 0 }, +{ "label": "22/32/1", "node": 3015, "naklon": 0 }, +{ "label": "22/33", "node": 2662, "naklon": 0 }, +{ "label": "22/34", "node": 2663, "naklon": 0 }, +{ "label": "22/35", "node": 2664, "naklon": 0 }, +{ "label": "22/36", "node": 2665, "naklon": 0 }, +{ "label": "22/37", "node": 2666, "naklon": 0 }, +{ "label": "22/38", "node": 2667, "naklon": 0 }, +{ "label": "22/39", "node": 2668, "naklon": 0 }, +{ "label": "22/40", "node": 2669, "naklon": null }, +{ "label": "22/41", "node": 2670, "naklon": null }, +{ "label": "22/42", "node": 2671, "naklon": null }, +{ "label": "23/9A", "node": 3087, "naklon": 10 }, +{ "label": "23/9B", "node": 3090, "naklon": 10 }, +{ "label": "23/1", "node": 3075, "naklon": 0 }, +{ "label": "23/2", "node": 3089, "naklon": 0 }, +{ "label": "23/3", "node": 3088, "naklon": 0 }, +{ "label": "23/4", "node": 3228, "naklon": 10 }, +{ "label": "23/5", "node": 2751, "naklon": 10 }, +{ "label": "23/6", "node": 3243, "naklon": 10 }, +{ "label": "23/7", "node": 4349, "naklon": 10 }, +{ "label": "23/8", "node": 3102, "naklon": 10 }, +{ "label": "23/10", "node": 3099, "naklon": 10 }, +{ "label": "23/11", "node": 3103, "naklon": 10 }, +{ "label": "23/12", "node": 3093, "naklon": 10 }, +{ "label": "23/13", "node": 3098, "naklon": 10 }, +{ "label": "23/14", "node": 3092, "naklon": 10 }, +{ "label": "23/15", "node": 3233, "naklon": 0 }, +{ "label": "23/16", "node": 3095, "naklon": 0 }, +{ "label": "23/17", "node": 4074, "naklon": 0 }, +{ "label": "23/18", "node": 2729, "naklon": 0 }, +{ "label": "23/19", "node": 3234, "naklon": 0 }, +{ "label": "23/20", "node": 3094, "naklon": 0 }, +{ "label": "23/21", "node": 2817, "naklon": 0 }, +{ "label": "23/22", "node": 3226, "naklon": 0 }, +{ "label": "23/23", "node": 3225, "naklon": 0 }, +{ "label": "23/24", "node": 3237, "naklon": 0 }, +{ "label": "23/25", "node": 4250, "naklon": 0 }, +{ "label": "23/26", "node": 3059, "naklon": 10 }, +{ "label": "23/27", "node": 3238, "naklon": 10 }, +{ "label": "23/28", "node": 3242, "naklon": 10 }, +{ "label": "23/29", "node": 3236, "naklon": 10 }, +{ "label": "23/30", "node": 3112, "naklon": 10 }, +{ "label": "23/31", "node": 3224, "naklon": 0 }, +{ "label": "23/32", "node": 4298, "naklon": 10 }, +{ "label": "23/33", "node": 4150, "naklon": 10 }, +{ "label": "23/34", "node": 3091, "naklon": 10 }, +{ "label": "25/1", "node": 3771, "naklon": 5 }, +{ "label": "25/2", "node": 3777, "naklon": 5 }, +{ "label": "25/3", "node": 3749, "naklon": 5 }, +{ "label": "25/4", "node": 3769, "naklon": 5 }, +{ "label": "25/5", "node": 3765, "naklon": 5 }, +{ "label": "25/6", "node": 3785, "naklon": 5 }, +{ "label": "25/7", "node": 3761, "naklon": 5 }, +{ "label": "25/8", "node": 3758, "naklon": 5 }, +{ "label": "25/9", "node": 3766, "naklon": 5 }, +{ "label": "25/10", "node": 3779, "naklon": 5 }, +{ "label": "25/11", "node": 3899, "naklon": 10 }, +{ "label": "25/12", "node": 3922, "naklon": 10 }, +{ "label": "25/13", "node": 3912, "naklon": 10 }, +{ "label": "25/14", "node": 3933, "naklon": 10 }, +{ "label": "25/15", "node": 3921, "naklon": 10 }, +{ "label": "25/16", "node": 4300, "naklon": 10 }, +{ "label": "25/17", "node": 3927, "naklon": 10 }, +{ "label": "25/18", "node": 3212, "naklon": 10 }, +{ "label": "25/19", "node": 3208, "naklon": 10 }, +{ "label": "25/20", "node": 3207, "naklon": 10 }, +{ "label": "25/21", "node": 4294, "naklon": 10 }, +{ "label": "25/22", "node": 3209, "naklon": 10 }, +{ "label": "25/23", "node": 3745, "naklon": 10 }, +{ "label": "25/24", "node": 3762, "naklon": 10 }, +{ "label": "25/25", "node": 3215, "naklon": 10 }, +{ "label": "25/26", "node": 3210, "naklon": 10 }, +{ "label": "25/27", "node": 3211, "naklon": 10 }, +{ "label": "25/28", "node": 3206, "naklon": 10 }, +{ "label": "25/29", "node": 3918, "naklon": 5 }, +{ "label": "25/30", "node": 3928, "naklon": 5 }, +{ "label": "25/31", "node": 3917, "naklon": 5 }, +{ "label": "25/32", "node": 4029, "naklon": 0 }, +{ "label": "25/33", "node": 4038, "naklon": 0 }, +{ "label": "25/34", "node": 4022, "naklon": 0 }, +{ "label": "25/35", "node": 3937, "naklon": 0 }, +{ "label": "25/36", "node": 3190, "naklon": 0 }, +{ "label": "25/37", "node": 3835, "naklon": 0 }, +{ "label": "25/38", "node": 3201, "naklon": 0 }, +{ "label": "25/39", "node": 3193, "naklon": 0 }, +{ "label": "25/40", "node": 3191, "naklon": 0 }, +{ "label": "25/41", "node": 3203, "naklon": 0 }, +{ "label": "25/42", "node": 4301, "naklon": 0 }, +{ "label": "25/43", "node": 3223, "naklon": 0 }, +{ "label": "25/44", "node": 3202, "naklon": 0 }, +{ "label": "25/45", "node": 3205, "naklon": 0 }, +{ "label": "25/46", "node": 3194, "naklon": 0 }, +{ "label": "25/47", "node": 3198, "naklon": 0 }, +{ "label": "25/48", "node": 3204, "naklon": 0 }, +{ "label": "25/49", "node": 3200, "naklon": 0 }, +{ "label": "25/50", "node": 3216, "naklon": 0 }, +{ "label": "25/51", "node": 3932, "naklon": 5 }, +{ "label": "25/52", "node": 3923, "naklon": 5 }, +{ "label": "25/53", "node": 3913, "naklon": 5 }, +{ "label": "25/54", "node": 3900, "naklon": 5 }, +{ "label": "25/55", "node": 4189, "naklon": 10 }, +{ "label": "25/56", "node": 4191, "naklon": 10 }, +{ "label": "25/57", "node": 3790, "naklon": 10 }, +{ "label": "25/58", "node": 4190, "naklon": 10 }, +{ "label": "25/59", "node": 4302, "naklon": 0 }, +{ "label": "25/60", "node": 4351, "naklon": 0 }, +{ "label": "25/61", "node": 4075, "naklon": 0 }, +{ "label": "25/62", "node": 4071, "naklon": 0 }, +{ "label": "25/63", "node": 3784, "naklon": 0 }, +{ "label": "25/64", "node": 4065, "naklon": 0 }, +{ "label": "25/65", "node": 4297, "naklon": 0 }, +{ "label": "25/66", "node": 4295, "naklon": 0 }, +{ "label": "25/67", "node": 4299, "naklon": 0 }, +{ "label": "25/68", "node": 3772, "naklon": 0 }, +{ "label": "25/69", "node": 3941, "naklon": 0 }, +{ "label": "25/70", "node": 3782, "naklon": 0 }, +{ "label": "25/71", "node": 4068, "naklon": 0 }, +{ "label": "25/72", "node": 4073, "naklon": 0 }, +{ "label": "25/73", "node": 3901, "naklon": 5 }, +{ "label": "25/74", "node": 4296, "naklon": 5 }, +{ "label": "25/75", "node": 3910, "naklon": 5 }, +{ "label": "25/76", "node": 4293, "naklon": 5 }, +{ "label": "25/77", "node": 3919, "naklon": 5 }, +{ "label": "25/78", "node": 3924, "naklon": 5 }, +{ "label": "25/79", "node": 3909, "naklon": 5 }, +{ "label": "25/80", "node": 3896, "naklon": 5 }, +{ "label": "25/81", "node": 3911, "naklon": 5 }, +{ "label": "25/82", "node": 2819, "naklon": 15 }, +{ "label": "25/83", "node": 3776, "naklon": 15 }, +{ "label": "25/84", "node": 3752, "naklon": 15 }, +{ "label": "25/85", "node": 4353, "naklon": 15 }, +{ "label": "25/86", "node": 3791, "naklon": 0 }, +{ "label": "25/87", "node": 3770, "naklon": 0 }, +{ "label": "25/88", "node": 3760, "naklon": 0 }, +{ "label": "25/89", "node": 3115, "naklon": 0 }, +{ "label": "25/90", "node": 3738, "naklon": 0 }, +{ "label": "25/91", "node": 3748, "naklon": 0 }, +{ "label": "25/92", "node": 3753, "naklon": 0 }, +{ "label": "25/93", "node": 3775, "naklon": 0 }, +{ "label": "25/94", "node": 3778, "naklon": 5 }, +{ "label": "25/95", "node": 4078, "naklon": 5 }, +{ "label": "25/96", "node": 4088, "naklon": 5 }, +{ "label": "25/97", "node": 3856, "naklon": 5 }, +{ "label": "25/98", "node": 4084, "naklon": 5 }, +{ "label": "25/99", "node": 4069, "naklon": 5 }, +{ "label": "25/100", "node": 4188, "naklon": 5 }, +{ "label": "25/101", "node": 4064, "naklon": 5 }, +{ "label": "25/102", "node": 3792, "naklon": 5 }, +{ "label": "25/103", "node": 3780, "naklon": 5 }, +{ "label": "25/104", "node": 4034, "naklon": 5 }, +{ "label": "25/105", "node": 4072, "naklon": 5 }, +{ "label": "25/106", "node": 3884, "naklon": 5 }, +{ "label": "25/107", "node": 3793, "naklon": 5 }, +{ "label": "25/108", "node": 3863, "naklon": 5 }, +{ "label": "25/109", "node": 3855, "naklon": 5 }, +{ "label": "33/1", "node": 3846, "naklon": 0 }, +{ "label": "33/2", "node": 3943, "naklon": 0 }, +{ "label": "33/3", "node": 3903, "naklon": 0 }, +{ "label": "33/4", "node": 3982, "naklon": 0 }, +{ "label": "33/5", "node": 3879, "naklon": 0 }, +{ "label": "33/6", "node": 3887, "naklon": 0 }, +{ "label": "33/7", "node": 3920, "naklon": 5 }, +{ "label": "33/8", "node": 3942, "naklon": 5 }, +{ "label": "33/9", "node": 3829, "naklon": null }, +{ "label": "34/79A", "node": 3452, "naklon": 6 }, +{ "label": "34/79B", "node": 3460, "naklon": 6 }, +{ "label": "34/90A", "node": 3443, "naklon": 6 }, +{ "label": "34/90B", "node": 3445, "naklon": 6 }, +{ "label": "34/90C", "node": 3457, "naklon": 6 }, +{ "label": "34/97A", "node": 3461, "naklon": 6 }, +{ "label": "34/97B", "node": 3463, "naklon": 6 }, +{ "label": "34/98A", "node": 3426, "naklon": 6 }, +{ "label": "34/98B", "node": 3444, "naklon": 6 }, +{ "label": "34/99A", "node": 3453, "naklon": 6 }, +{ "label": "34/99B", "node": 3455, "naklon": 6 }, +{ "label": "34/1", "node": 4009, "naklon": 0 }, +{ "label": "34/2", "node": 3602, "naklon": 0 }, +{ "label": "34/3", "node": 3441, "naklon": 0 }, +{ "label": "34/4", "node": 3464, "naklon": 0 }, +{ "label": "34/5", "node": 3883, "naklon": 0 }, +{ "label": "34/6", "node": 4098, "naklon": 0 }, +{ "label": "34/7", "node": 4003, "naklon": 0 }, +{ "label": "34/8", "node": 4004, "naklon": 0 }, +{ "label": "34/9", "node": 3888, "naklon": 0 }, +{ "label": "34/10", "node": 3997, "naklon": 0 }, +{ "label": "34/11", "node": 4006, "naklon": 0 }, +{ "label": "34/12", "node": 4000, "naklon": 0 }, +{ "label": "34/13", "node": 4011, "naklon": 0 }, +{ "label": "34/14", "node": 3999, "naklon": 0 }, +{ "label": "34/15", "node": 3981, "naklon": 0 }, +{ "label": "34/16", "node": 3988, "naklon": 0 }, +{ "label": "34/17", "node": 3986, "naklon": 0 }, +{ "label": "34/18", "node": 3998, "naklon": 0 }, +{ "label": "34/19", "node": 3983, "naklon": 0 }, +{ "label": "34/20", "node": 4005, "naklon": 0 }, +{ "label": "34/21", "node": 4001, "naklon": 0 }, +{ "label": "34/22", "node": 4008, "naklon": 0 }, +{ "label": "34/23", "node": 4002, "naklon": 0 }, +{ "label": "34/24", "node": 3996, "naklon": 0 }, +{ "label": "34/25", "node": 4007, "naklon": 0 }, +{ "label": "34/26", "node": 4113, "naklon": 15 }, +{ "label": "34/27", "node": 3595, "naklon": 5 }, +{ "label": "34/28", "node": 3599, "naklon": 5 }, +{ "label": "34/29", "node": 3601, "naklon": 5 }, +{ "label": "34/30", "node": 4205, "naklon": 0 }, +{ "label": "34/31", "node": 3987, "naklon": null }, +{ "label": "34/32", "node": 4214, "naklon": 0 }, +{ "label": "34/33", "node": 4226, "naklon": 0 }, +{ "label": "34/34", "node": 4209, "naklon": 0 }, +{ "label": "34/35", "node": 4201, "naklon": 0 }, +{ "label": "34/36", "node": 3440, "naklon": 0 }, +{ "label": "34/37", "node": 3465, "naklon": 0 }, +{ "label": "34/38", "node": 3446, "naklon": 0 }, +{ "label": "34/39", "node": 4039, "naklon": 5 }, +{ "label": "34/40", "node": 4057, "naklon": 5 }, +{ "label": "34/41", "node": 3985, "naklon": 0 }, +{ "label": "34/42", "node": 3882, "naklon": 0 }, +{ "label": "34/43", "node": 4040, "naklon": 5 }, +{ "label": "34/44", "node": 3231, "naklon": 0 }, +{ "label": "34/45", "node": 3227, "naklon": 0 }, +{ "label": "34/46", "node": 3431, "naklon": 0 }, +{ "label": "34/47", "node": 4013, "naklon": 0 }, +{ "label": "34/48", "node": 4045, "naklon": 0 }, +{ "label": "34/49", "node": 3949, "naklon": 0 }, +{ "label": "34/50", "node": 3953, "naklon": 0 }, +{ "label": "34/51", "node": 3952, "naklon": 0 }, +{ "label": "34/52", "node": 3995, "naklon": 0 }, +{ "label": "34/53", "node": 3992, "naklon": 0 }, +{ "label": "34/54", "node": 4198, "naklon": 0 }, +{ "label": "34/55", "node": 3935, "naklon": 0 }, +{ "label": "34/56", "node": 4050, "naklon": 0 }, +{ "label": "34/57", "node": 4049, "naklon": 0 }, +{ "label": "34/58", "node": 4054, "naklon": 0 }, +{ "label": "34/59", "node": 3663, "naklon": 6 }, +{ "label": "34/60", "node": 3661, "naklon": 6 }, +{ "label": "34/61", "node": 3664, "naklon": 6 }, +{ "label": "34/62", "node": 3660, "naklon": 6 }, +{ "label": "34/63", "node": 3662, "naklon": 6 }, +{ "label": "34/65", "node": 3665, "naklon": 6 }, +{ "label": "34/66", "node": 3667, "naklon": 6 }, +{ "label": "34/67", "node": 3675, "naklon": 6 }, +{ "label": "34/68", "node": 3666, "naklon": 6 }, +{ "label": "34/69", "node": 3652, "naklon": 6 }, +{ "label": "34/70", "node": 3458, "naklon": 6 }, +{ "label": "34/70/1", "node": 4425, "naklon": 6 }, +{ "label": "34/71", "node": 3459, "naklon": 6 }, +{ "label": "34/72", "node": 3435, "naklon": 6 }, +{ "label": "34/73", "node": 3448, "naklon": 6 }, +{ "label": "34/74", "node": 3451, "naklon": 6 }, +{ "label": "34/75", "node": 3442, "naklon": 6 }, +{ "label": "34/76", "node": 3449, "naklon": 6 }, +{ "label": "34/77", "node": 3450, "naklon": 6 }, +{ "label": "34/78", "node": 3433, "naklon": 6 }, +{ "label": "34/80", "node": 3432, "naklon": 12 }, +{ "label": "34/81", "node": 3470, "naklon": 12 }, +{ "label": "34/82", "node": 3438, "naklon": 12 }, +{ "label": "34/83", "node": 3439, "naklon": 12 }, +{ "label": "34/84", "node": 4028, "naklon": 5 }, +{ "label": "34/85", "node": 3596, "naklon": 5 }, +{ "label": "34/86", "node": 4021, "naklon": 5 }, +{ "label": "34/87", "node": 3437, "naklon": 12 }, +{ "label": "34/88", "node": 3428, "naklon": 12 }, +{ "label": "34/89", "node": 3430, "naklon": 12 }, +{ "label": "34/91", "node": 3454, "naklon": 6 }, +{ "label": "34/92", "node": 3492, "naklon": 6 }, +{ "label": "34/93", "node": 3462, "naklon": 6 }, +{ "label": "34/94", "node": 3427, "naklon": 6 }, +{ "label": "34/95", "node": 3434, "naklon": 6 }, +{ "label": "34/96", "node": 3456, "naklon": 6 }, +{ "label": "34/98/1", "node": 4307, "naklon": 6 }, +{ "label": "35/1", "node": 3968, "naklon": 0 }, +{ "label": "35/2", "node": 3969, "naklon": 0 }, +{ "label": "35/3", "node": 3947, "naklon": 0 }, +{ "label": "35/4", "node": 3979, "naklon": 0 }, +{ "label": "35/5", "node": 3959, "naklon": 0 }, +{ "label": "35/6", "node": 3948, "naklon": 0 }, +{ "label": "35/7", "node": 3961, "naklon": 0 }, +{ "label": "35/8", "node": 3956, "naklon": 0 }, +{ "label": "35/9", "node": 3604, "naklon": 0 }, +{ "label": "35/10", "node": 3944, "naklon": 0 }, +{ "label": "35/11", "node": 3960, "naklon": 0 }, +{ "label": "35/12", "node": 3958, "naklon": 0 }, +{ "label": "35/13", "node": 4036, "naklon": 5 }, +{ "label": "35/18", "node": 3893, "naklon": 5 }, +{ "label": "35/19", "node": 4108, "naklon": 5 }, +{ "label": "35/20", "node": 4017, "naklon": 5 }, +{ "label": "35/21", "node": 3963, "naklon": 0 }, +{ "label": "35/22", "node": 3658, "naklon": 0 }, +{ "label": "35/23", "node": 3975, "naklon": 0 }, +{ "label": "35/24", "node": 3980, "naklon": 0 }, +{ "label": "35/25", "node": 4012, "naklon": 0 }, +{ "label": "35/26", "node": 3655, "naklon": 0 }, +{ "label": "35/27", "node": 3962, "naklon": 0 }, +{ "label": "35/28", "node": 3945, "naklon": 0 }, +{ "label": "35/29", "node": 3569, "naklon": 0 }, +{ "label": "35/30", "node": 3429, "naklon": 0 }, +{ "label": "35/31", "node": 3657, "naklon": 0 }, +{ "label": "35/32", "node": 3646, "naklon": 0 }, +{ "label": "35/33", "node": 3622, "naklon": 0 }, +{ "label": "35/34", "node": 3612, "naklon": 0 }, +{ "label": "35/35", "node": 3955, "naklon": 0 }, +{ "label": "35/37", "node": 3878, "naklon": 0 }, +{ "label": "35/38", "node": 3965, "naklon": 0 }, +{ "label": "35/39", "node": 3970, "naklon": 0 }, +{ "label": "35/40", "node": 3611, "naklon": 0 }, +{ "label": "35/41", "node": 2635, "naklon": 0 }, +{ "label": "35/42", "node": 3978, "naklon": 0 }, +{ "label": "35/43", "node": 4213, "naklon": 0 }, +{ "label": "35/44", "node": 3984, "naklon": 0 }, +{ "label": "35/45", "node": 4218, "naklon": 0 }, +{ "label": "35/46", "node": 3973, "naklon": 0 }, +{ "label": "35/47", "node": 3974, "naklon": 0 }, +{ "label": "35/48", "node": 3759, "naklon": 0 }, +{ "label": "35/49", "node": 3844, "naklon": 0 }, +{ "label": "35/50", "node": 3804, "naklon": 0 }, +{ "label": "35/51", "node": 3831, "naklon": 0 }, +{ "label": "35/52", "node": 3643, "naklon": 0 }, +{ "label": "35/53", "node": 3966, "naklon": 0 }, +{ "label": "35/54", "node": 3971, "naklon": 0 }, +{ "label": "35/55", "node": 3650, "naklon": 6 }, +{ "label": "35/56", "node": 3651, "naklon": 6 }, +{ "label": "35/57", "node": 3669, "naklon": 6 }, +{ "label": "35/58", "node": 3648, "naklon": 6 }, +{ "label": "35/59", "node": 3645, "naklon": 6 }, +{ "label": "35/60", "node": 3659, "naklon": 6 }, +{ "label": "35/61", "node": 3647, "naklon": 6 }, +{ "label": "35/62", "node": 3644, "naklon": 6 }, +{ "label": "35/63", "node": 3671, "naklon": 6 }, +{ "label": "35/64", "node": 3682, "naklon": 6 }, +{ "label": "35/65", "node": 3672, "naklon": 6 }, +{ "label": "35/66", "node": 3683, "naklon": 6 }, +{ "label": "35/67", "node": 3673, "naklon": 6 }, +{ "label": "35/68", "node": 3674, "naklon": 6 }, +{ "label": "35/69", "node": 3679, "naklon": 6 }, +{ "label": "35/70", "node": 3649, "naklon": 6 }, +{ "label": "35/71", "node": 3687, "naklon": 6 }, +{ "label": "35/72", "node": 3677, "naklon": 6 }, +{ "label": "35/73", "node": 3690, "naklon": 6 }, +{ "label": "35/74", "node": 3691, "naklon": 6 }, +{ "label": "35/75", "node": 3676, "naklon": 6 }, +{ "label": "35/76", "node": 3680, "naklon": 6 }, +{ "label": "35/77", "node": 3668, "naklon": 6 }, +{ "label": "35/78", "node": 3681, "naklon": 6 }, +{ "label": "35/79", "node": 3670, "naklon": 6 }, +{ "label": "35/80", "node": 3689, "naklon": 6 }, +{ "label": "35/81", "node": 3678, "naklon": 6 }, +{ "label": "35/82", "node": 3693, "naklon": 6 }, +{ "label": "35/83", "node": 3654, "naklon": null }, +{ "label": "36/1", "node": 4086, "naklon": 0 }, +{ "label": "36/2", "node": 4085, "naklon": 0 }, +{ "label": "36/3", "node": 4083, "naklon": 0 }, +{ "label": "36/4", "node": 4087, "naklon": 0 }, +{ "label": "36/5", "node": 4077, "naklon": 0 }, +{ "label": "36/6", "node": 4082, "naklon": 0 }, +{ "label": "36/7", "node": 4186, "naklon": 0 }, +{ "label": "36/8", "node": 4206, "naklon": 0 }, +{ "label": "36/9", "node": 4080, "naklon": 0 }, +{ "label": "36/10", "node": 4081, "naklon": 0 }, +{ "label": "36/11", "node": 4210, "naklon": 0 }, +{ "label": "36/12", "node": 4079, "naklon": 0 }, +{ "label": "36/13", "node": 4076, "naklon": 0 }, +{ "label": "36/14", "node": 3852, "naklon": 0 }, +{ "label": "36/15", "node": 2813, "naklon": 0 }, +{ "label": "36/16", "node": 4219, "naklon": 0 }, +{ "label": "37/1A", "node": 3104, "naklon": 15 }, +{ "label": "37/1B", "node": 3121, "naklon": 15 }, +{ "label": "37/2", "node": 3113, "naklon": 10 }, +{ "label": "37/3", "node": 3118, "naklon": 10 }, +{ "label": "37/4", "node": 3111, "naklon": 10 }, +{ "label": "37/5", "node": 4020, "naklon": 10 }, +{ "label": "37/6", "node": 3119, "naklon": 10 }, +{ "label": "37/7", "node": 3110, "naklon": 10 }, +{ "label": "37/8", "node": 3108, "naklon": 10 }, +{ "label": "37/12", "node": 3107, "naklon": 0 }, +{ "label": "37/13", "node": 3199, "naklon": 0 }, +{ "label": "37/14", "node": 3120, "naklon": 0 }, +{ "label": "37/15", "node": 3122, "naklon": 0 }, +{ "label": "37/16", "node": 3908, "naklon": 0 }, +{ "label": "37/17", "node": 3114, "naklon": 0 }, +{ "label": "37/18", "node": 3105, "naklon": 0 }, +{ "label": "37/19", "node": 3116, "naklon": 0 }, +{ "label": "37/20", "node": 3106, "naklon": 0 }, +{ "label": "37/21", "node": 2887, "naklon": 5 }, +{ "label": "37/22", "node": 2888, "naklon": 5 }, +{ "label": "37/23", "node": 2877, "naklon": 5 }, +{ "label": "37/24", "node": 2891, "naklon": 5 }, +{ "label": "37/25", "node": 2886, "naklon": 5 }, +{ "label": "37/26", "node": 2892, "naklon": 5 }, +{ "label": "37/27", "node": 2882, "naklon": 5 }, +{ "label": "37/28", "node": 2883, "naklon": 5 }, +{ "label": "37/29", "node": 2876, "naklon": 5 }, +{ "label": "37/30", "node": 3109, "naklon": 5 }, +{ "label": "37/31", "node": 4152, "naklon": 5 }, +{ "label": "37/32", "node": 3117, "naklon": 5 }, +{ "label": "37/33", "node": 2870, "naklon": 5 }, +{ "label": "37/34", "node": 2867, "naklon": 0 }, +{ "label": "37/35", "node": 2865, "naklon": 0 }, +{ "label": "37/36", "node": 3096, "naklon": 0 }, +{ "label": "37/37", "node": 2871, "naklon": 0 }, +{ "label": "37/38", "node": 2884, "naklon": 0 }, +{ "label": "37/39", "node": 2855, "naklon": 0 }, +{ "label": "37/40", "node": 2878, "naklon": 0 }, +{ "label": "37/41", "node": 2889, "naklon": 0 }, +{ "label": "37/42", "node": 2879, "naklon": 0 }, +{ "label": "37/43", "node": 2850, "naklon": 0 }, +{ "label": "37/44", "node": 2894, "naklon": 0 }, +{ "label": "37/45", "node": 2880, "naklon": 0 }, +{ "label": "37/46", "node": 2893, "naklon": 0 }, +{ "label": "37/47", "node": 2890, "naklon": 0 }, +{ "label": "37/48", "node": 4355, "naklon": 0 }, +{ "label": "37/49", "node": 2885, "naklon": 0 }, +{ "label": "37/50", "node": 2875, "naklon": 0 }, +{ "label": "38/30A", "node": 3486, "naklon": 5 }, +{ "label": "38/30B", "node": 3714, "naklon": 0 }, +{ "label": "38/32A", "node": 3483, "naklon": 5 }, +{ "label": "38/32B", "node": 3496, "naklon": 0 }, +{ "label": "38/35A", "node": 3487, "naklon": 5 }, +{ "label": "38/35B", "node": 3498, "naklon": 5 }, +{ "label": "38/38A", "node": 3578, "naklon": 5 }, +{ "label": "38/38B", "node": 3508, "naklon": 5 }, +{ "label": "38/59A", "node": 3787, "naklon": 5 }, +{ "label": "38/59B", "node": 3491, "naklon": 5 }, +{ "label": "38/1", "node": 3568, "naklon": null }, +{ "label": "38/2", "node": 3502, "naklon": 0 }, +{ "label": "38/3", "node": 3836, "naklon": 0 }, +{ "label": "38/4", "node": 3588, "naklon": 0 }, +{ "label": "38/5", "node": 3493, "naklon": 0 }, +{ "label": "38/6", "node": 3580, "naklon": 0 }, +{ "label": "38/7", "node": 3572, "naklon": 0 }, +{ "label": "38/8", "node": 3506, "naklon": 0 }, +{ "label": "38/9", "node": 3503, "naklon": 0 }, +{ "label": "38/10", "node": 3579, "naklon": 0 }, +{ "label": "38/11", "node": 3586, "naklon": 0 }, +{ "label": "38/12", "node": 3495, "naklon": 5 }, +{ "label": "38/13", "node": 3492, "naklon": 5 }, +{ "label": "38/14", "node": 3532, "naklon": 5 }, +{ "label": "38/15", "node": 3574, "naklon": 5 }, +{ "label": "38/16", "node": 4140, "naklon": 5 }, +{ "label": "38/17", "node": 3795, "naklon": 5 }, +{ "label": "38/18", "node": 3788, "naklon": 5 }, +{ "label": "38/19", "node": 3796, "naklon": 5 }, +{ "label": "38/20", "node": 3797, "naklon": 5 }, +{ "label": "38/21", "node": 3798, "naklon": 5 }, +{ "label": "38/22", "node": 3786, "naklon": 5 }, +{ "label": "38/23", "node": 4067, "naklon": 5 }, +{ "label": "38/24", "node": 3773, "naklon": 5 }, +{ "label": "38/25", "node": 3774, "naklon": 5 }, +{ "label": "38/26", "node": 3789, "naklon": 5 }, +{ "label": "38/27", "node": 3520, "naklon": null }, +{ "label": "38/29", "node": 3577, "naklon": 5 }, +{ "label": "38/31", "node": 3530, "naklon": null }, +{ "label": "38/33", "node": 3488, "naklon": 5 }, +{ "label": "38/34", "node": 3505, "naklon": 5 }, +{ "label": "38/36", "node": 3497, "naklon": 5 }, +{ "label": "38/37", "node": 3490, "naklon": 5 }, +{ "label": "38/39", "node": 3585, "naklon": 5 }, +{ "label": "38/40", "node": 3582, "naklon": 5 }, +{ "label": "38/41", "node": 3507, "naklon": 5 }, +{ "label": "38/42", "node": 3484, "naklon": 5 }, +{ "label": "38/43", "node": 3501, "naklon": 5 }, +{ "label": "38/44", "node": 3581, "naklon": 5 }, +{ "label": "38/45", "node": 4192, "naklon": 5 }, +{ "label": "38/46", "node": 3576, "naklon": 5 }, +{ "label": "38/47", "node": 3489, "naklon": 5 }, +{ "label": "38/48", "node": 3573, "naklon": 5 }, +{ "label": "38/49", "node": 3504, "naklon": 5 }, +{ "label": "38/50", "node": 3794, "naklon": 5 }, +{ "label": "38/51", "node": 3485, "naklon": 5 }, +{ "label": "38/52", "node": 3482, "naklon": 5 }, +{ "label": "38/53", "node": 3575, "naklon": 5 }, +{ "label": "38/54", "node": 3499, "naklon": 5 }, +{ "label": "38/55", "node": 3494, "naklon": 5 }, +{ "label": "38/56", "node": 3583, "naklon": 5 }, +{ "label": "38/57", "node": 3570, "naklon": 5 }, +{ "label": "38/58", "node": 3500, "naklon": 0 }, +{ "label": "38/63", "node": 3510, "naklon": null }, +{ "label": "38/64", "node": 3512, "naklon": null }, +{ "label": "38/67", "node": 3535, "naklon": null }, +{ "label": "38/68", "node": 3531, "naklon": null }, +{ "label": "38/69", "node": 3537, "naklon": null }, +{ "label": "39/1", "node": 3522, "naklon": 10 }, +{ "label": "39/2", "node": 4018, "naklon": 10 }, +{ "label": "39/3", "node": 4019, "naklon": 10 }, +{ "label": "39/4", "node": 4154, "naklon": 5 }, +{ "label": "39/5", "node": 3907, "naklon": 5 }, +{ "label": "39/6", "node": 4148, "naklon": 0 }, +{ "label": "39/7", "node": 4153, "naklon": 0 }, +{ "label": "39/8", "node": 3938, "naklon": 0 }, +{ "label": "39/9", "node": 3802, "naklon": 0 }, +{ "label": "39/10", "node": 4015, "naklon": 0 }, +{ "label": "39/11", "node": 3929, "naklon": 0 }, +{ "label": "39/12", "node": 3946, "naklon": 0 }, +{ "label": "39/13", "node": 4014, "naklon": 0 }, +{ "label": "39/14", "node": 4155, "naklon": 0 }, +{ "label": "39/15", "node": 4149, "naklon": 0 }, +{ "label": "39/16", "node": 3642, "naklon": 0 }, +{ "label": "39/17", "node": 3636, "naklon": 5 }, +{ "label": "39/18", "node": 3991, "naklon": 0 }, +{ "label": "39/19", "node": 3994, "naklon": 0 }, +{ "label": "39/20", "node": 3990, "naklon": 0 }, +{ "label": "39/21", "node": 3967, "naklon": 0 }, +{ "label": "39/22", "node": 3977, "naklon": 0 }, +{ "label": "39/23", "node": 3757, "naklon": 15 }, +{ "label": "39/24", "node": 3633, "naklon": 15 }, +{ "label": "39/25", "node": 3744, "naklon": 15 }, +{ "label": "39/26", "node": 4023, "naklon": 5 }, +{ "label": "39/27", "node": 3720, "naklon": 5 }, +{ "label": "39/28", "node": 3734, "naklon": 5 }, +{ "label": "39/29", "node": 3741, "naklon": 5 }, +{ "label": "39/30", "node": 3721, "naklon": 5 }, +{ "label": "39/31", "node": 3845, "naklon": 0 }, +{ "label": "39/32", "node": 3840, "naklon": 0 }, +{ "label": "39/33", "node": 3837, "naklon": null }, +{ "label": "39/34", "node": 3839, "naklon": 0 }, +{ "label": "41/1", "node": 3542, "naklon": null }, +{ "label": "41/2", "node": 3566, "naklon": null }, +{ "label": "41/3", "node": 3548, "naklon": null }, +{ "label": "41/4", "node": 3515, "naklon": null }, +{ "label": "41/5", "node": 3559, "naklon": null }, +{ "label": "41/6", "node": 3509, "naklon": null }, +{ "label": "41/7", "node": 3524, "naklon": null }, +{ "label": "41/8", "node": 3518, "naklon": null }, +{ "label": "41/9", "node": 3182, "naklon": null }, +{ "label": "41/10", "node": 3187, "naklon": null }, +{ "label": "41/11", "node": 3195, "naklon": 0 }, +{ "label": "41/12", "node": 3857, "naklon": 0 }, +{ "label": "41/13", "node": 3183, "naklon": 0 }, +{ "label": "41/14", "node": 3177, "naklon": 0 }, +{ "label": "41/15", "node": 3189, "naklon": 0 }, +{ "label": "41/16", "node": 3186, "naklon": 0 }, +{ "label": "42/1", "node": 3178, "naklon": 0 }, +{ "label": "42/2", "node": 3219, "naklon": 0 }, +{ "label": "42/3", "node": 3475, "naklon": 0 }, +{ "label": "42/4", "node": 3175, "naklon": 0 }, +{ "label": "42/5", "node": 3222, "naklon": 0 }, +{ "label": "42/6", "node": 3221, "naklon": 0 }, +{ "label": "42/7", "node": 3181, "naklon": 0 }, +{ "label": "42/8", "node": 3180, "naklon": 0 }, +{ "label": "42/9", "node": 3218, "naklon": 0 }, +{ "label": "42/10", "node": 3176, "naklon": 0 }, +{ "label": "42/11", "node": 3174, "naklon": 0 }, +{ "label": "42/12", "node": 3220, "naklon": 0 }, +{ "label": "42/13", "node": 3533, "naklon": null }, +{ "label": "42/14", "node": 3543, "naklon": null }, +{ "label": "42/15", "node": 3554, "naklon": null }, +{ "label": "42/16", "node": 3549, "naklon": null }, +{ "label": "43/1", "node": 2857, "naklon": 5 }, +{ "label": "43/2", "node": 2752, "naklon": 5 }, +{ "label": "43/3", "node": 2753, "naklon": 5 }, +{ "label": "43/4", "node": 3024, "naklon": 5 }, +{ "label": "43/5", "node": 2754, "naklon": 5 }, +{ "label": "43/6", "node": 4423, "naklon": 5 }, +{ "label": "43/7", "node": 4368, "naklon": 5 }, +{ "label": "43/8", "node": 2978, "naklon": 5 }, +{ "label": "43/9", "node": 2868, "naklon": 5 }, +{ "label": "43/10", "node": 4377, "naklon": 5 }, +{ "label": "43/11", "node": 2757, "naklon": 5 }, +{ "label": "43/12", "node": 2970, "naklon": 5 }, +{ "label": "43/13", "node": 2758, "naklon": 5 }, +{ "label": "43/14", "node": 4378, "naklon": 5 }, +{ "label": "43/15", "node": 2759, "naklon": 5 }, +{ "label": "43/16", "node": 4342, "naklon": 5 }, +{ "label": "43/17", "node": 3026, "naklon": null }, +{ "label": "43/18", "node": 2986, "naklon": null }, +{ "label": "43/19", "node": 4343, "naklon": null }, +{ "label": "43/20", "node": 2760, "naklon": null }, +{ "label": "43/21", "node": 4379, "naklon": null }, +{ "label": "43/22", "node": 2971, "naklon": null }, +{ "label": "43/23", "node": 2761, "naklon": null }, +{ "label": "43/24", "node": 2762, "naklon": null }, +{ "label": "43/25", "node": 4339, "naklon": null }, +{ "label": "43/26", "node": 4380, "naklon": null }, +{ "label": "43/27", "node": 2975, "naklon": null }, +{ "label": "43/28", "node": 3003, "naklon": null }, +{ "label": "43/29", "node": 4338, "naklon": null }, +{ "label": "43/30", "node": 3002, "naklon": null }, +{ "label": "43/31", "node": 4345, "naklon": null }, +{ "label": "43/32", "node": 2979, "naklon": null }, +{ "label": "43/33", "node": 2989, "naklon": null }, +{ "label": "43/34", "node": 2996, "naklon": null }, +{ "label": "43/35", "node": 2972, "naklon": null }, +{ "label": "43/36", "node": 2988, "naklon": null }, +{ "label": "43/37", "node": 4344, "naklon": null }, +{ "label": "43/38", "node": 3022, "naklon": null }, +{ "label": "43/39", "node": 4341, "naklon": null }, +{ "label": "43/40", "node": 2983, "naklon": null }, +{ "label": "43/41", "node": 2995, "naklon": null }, +{ "label": "43/42", "node": 2763, "naklon": null }, +{ "label": "43/43", "node": 2764, "naklon": null }, +{ "label": "43/44", "node": 2765, "naklon": null }, +{ "label": "43/45", "node": 2766, "naklon": null }, +{ "label": "43/46", "node": 2767, "naklon": null }, +{ "label": "43/47", "node": 2768, "naklon": null }, +{ "label": "43/48", "node": 3018, "naklon": null }, +{ "label": "43/49", "node": 2982, "naklon": null }, +{ "label": "43/50", "node": 3019, "naklon": 0 }, +{ "label": "43/51", "node": 3013, "naklon": null }, +{ "label": "43/52", "node": 3007, "naklon": null }, +{ "label": "43/53", "node": 2980, "naklon": null }, +{ "label": "43/54", "node": 3011, "naklon": null }, +{ "label": "43/55", "node": 2672, "naklon": null }, +{ "label": "43/56", "node": 2673, "naklon": null }, +{ "label": "43/57", "node": 2674, "naklon": null }, +{ "label": "43/58", "node": 2675, "naklon": null }, +{ "label": "43/59", "node": 2676, "naklon": null }, +{ "label": "43/60", "node": 2677, "naklon": null }, +{ "label": "43/61", "node": 2678, "naklon": null }, +{ "label": "43/62", "node": 2679, "naklon": null }, +{ "label": "43/63", "node": 2680, "naklon": null }, +{ "label": "43/64", "node": 2840, "naklon": null }, +{ "label": "43/65", "node": 2682, "naklon": null }, +{ "label": "43/66", "node": 2683, "naklon": null }, +{ "label": "43/67", "node": 2684, "naklon": 0 }, +{ "label": "43/68", "node": 2685, "naklon": null }, +{ "label": "43/69", "node": 2686, "naklon": null }, +{ "label": "43/70", "node": 2687, "naklon": null }, +{ "label": "43/71", "node": 2688, "naklon": null }, +{ "label": "43/72", "node": 2689, "naklon": null }, +{ "label": "43/73", "node": 2690, "naklon": null }, +{ "label": "43/74", "node": 2691, "naklon": null }, +{ "label": "43/75", "node": 2692, "naklon": null }, +{ "label": "43/76", "node": 2693, "naklon": 0 }, +{ "label": "43/77", "node": 2694, "naklon": null }, +{ "label": "43/78", "node": 2695, "naklon": null }, +{ "label": "43/79", "node": 2696, "naklon": 0 }, +{ "label": "43/80", "node": 2697, "naklon": null }, +{ "label": "43/81", "node": 2698, "naklon": 0 }, +{ "label": "43/82", "node": 2699, "naklon": null }, +{ "label": "43/83", "node": 2700, "naklon": 0 }, +{ "label": "43/84", "node": 2744, "naklon": null }, +{ "label": "43/85", "node": 2745, "naklon": 0 }, +{ "label": "43/86", "node": 2746, "naklon": null }, +{ "label": "43/87", "node": 2747, "naklon": 0 }, +{ "label": "43/88", "node": 2748, "naklon": null }, +{ "label": "43/89", "node": 2749, "naklon": 0 }, +{ "label": "43/90", "node": 2841, "naklon": null }, +{ "label": "45/1", "node": 4237, "naklon": 5 }, +{ "label": "45/2", "node": 4226, "naklon": 5 }, +{ "label": "45/3", "node": 4242, "naklon": 5 }, +{ "label": "45/4", "node": 4179, "naklon": 5 }, +{ "label": "45/5", "node": 4247, "naklon": 5 }, +{ "label": "45/6", "node": 4245, "naklon": 5 }, +{ "label": "45/7", "node": 3872, "naklon": 5 }, +{ "label": "45/8", "node": 4175, "naklon": 5 }, +{ "label": "45/9", "node": 4236, "naklon": 5 }, +{ "label": "45/10", "node": 4170, "naklon": 5 }, +{ "label": "45/11", "node": 4238, "naklon": 5 }, +{ "label": "45/12", "node": 4246, "naklon": 5 }, +{ "label": "45/13", "node": 4166, "naklon": 5 }, +{ "label": "45/14", "node": 4227, "naklon": 5 }, +{ "label": "45/15", "node": 4171, "naklon": 5 }, +{ "label": "45/16", "node": 4180, "naklon": 5 }, +{ "label": "45/17", "node": 4244, "naklon": 5 }, +{ "label": "45/18", "node": 4199, "naklon": 5 }, +{ "label": "45/19", "node": 4239, "naklon": 5 }, +{ "label": "45/20", "node": 4207, "naklon": 5 }, +{ "label": "45/21", "node": 4223, "naklon": 5 }, +{ "label": "45/22", "node": 4230, "naklon": 5 }, +{ "label": "45/23", "node": 4233, "naklon": 5 }, +{ "label": "45/24", "node": 4222, "naklon": 5 }, +{ "label": "45/25", "node": 4217, "naklon": 5 }, +{ "label": "45/26", "node": 4243, "naklon": 5 }, +{ "label": "45/27", "node": 4200, "naklon": 5 }, +{ "label": "45/28", "node": 4228, "naklon": 5 }, +{ "label": "45/29", "node": 4211, "naklon": 5 }, +{ "label": "45/30", "node": 4234, "naklon": 5 }, +{ "label": "45/31", "node": 4235, "naklon": 5 }, +{ "label": "45/32", "node": 4203, "naklon": 5 }, +{ "label": "45/33", "node": 4240, "naklon": 5 }, +{ "label": "45/34", "node": 4224, "naklon": 5 }, +{ "label": "45/35", "node": 4232, "naklon": 5 }, +{ "label": "45/36", "node": 4231, "naklon": 5 }, +{ "label": "45/37", "node": 4161, "naklon": 5 }, +{ "label": "45/38", "node": 4225, "naklon": 5 }, +{ "label": "45/39", "node": 4241, "naklon": 5 }, +{ "label": "45/40", "node": 4229, "naklon": 5 }, +{ "label": "45/41", "node": 4221, "naklon": 5 }, +{ "label": "45/42", "node": 4212, "naklon": 5 }, +{ "label": "45/43", "node": 4216, "naklon": 5 }, +{ "label": "45/44", "node": 3864, "naklon": null }, +{ "label": "46/1", "node": 3806, "naklon": 5 }, +{ "label": "46/2", "node": 3813, "naklon": 5 }, +{ "label": "46/3", "node": 3815, "naklon": 5 }, +{ "label": "46/4", "node": 3807, "naklon": 5 }, +{ "label": "46/5", "node": 3895, "naklon": 5 }, +{ "label": "46/6", "node": 3809, "naklon": 5 }, +{ "label": "46/7", "node": 3820, "naklon": 5 }, +{ "label": "46/8", "node": 3805, "naklon": 5 }, +{ "label": "46/9", "node": 3894, "naklon": 0 }, +{ "label": "46/10", "node": 4055, "naklon": 0 }, +{ "label": "46/11", "node": 3812, "naklon": 5 }, +{ "label": "46/12", "node": 3822, "naklon": 5 }, +{ "label": "46/13", "node": 3821, "naklon": 5 }, +{ "label": "46/14", "node": 3808, "naklon": 5 }, +{ "label": "46/15", "node": 3799, "naklon": 5 }, +{ "label": "46/16", "node": 3816, "naklon": 5 }, +{ "label": "46/17", "node": 3751, "naklon": 5 }, +{ "label": "46/18", "node": 3814, "naklon": 5 }, +{ "label": "46/19", "node": 4044, "naklon": 0 }, +{ "label": "46/20", "node": 3931, "naklon": 0 }, +{ "label": "46/21", "node": 3902, "naklon": 5 }, +{ "label": "46/22", "node": 3916, "naklon": 5 }, +{ "label": "46/23", "node": 3892, "naklon": 5 }, +{ "label": "46/24", "node": 3914, "naklon": 5 }, +{ "label": "46/25", "node": 3898, "naklon": 5 }, +{ "label": "46/26", "node": 3897, "naklon": 5 }, +{ "label": "46/27", "node": 3885, "naklon": 5 }, +{ "label": "46/28", "node": 3906, "naklon": 5 }, +{ "label": "46/29", "node": 3930, "naklon": 0 }, +{ "label": "46/30", "node": 3936, "naklon": 0 }, +{ "label": "46/31", "node": 3860, "naklon": 5 }, +{ "label": "46/32", "node": 3841, "naklon": 5 }, +{ "label": "46/33", "node": 3873, "naklon": 5 }, +{ "label": "46/34", "node": 3854, "naklon": 5 }, +{ "label": "46/35", "node": 3939, "naklon": 5 }, +{ "label": "46/36", "node": 3858, "naklon": 5 }, +{ "label": "46/37", "node": 3940, "naklon": 5 }, +{ "label": "46/38", "node": 4035, "naklon": 5 }, +{ "label": "47/1", "node": 3373, "naklon": 0 }, +{ "label": "47/2", "node": 3374, "naklon": 0 }, +{ "label": "47/3", "node": 3384, "naklon": 0 }, +{ "label": "47/4", "node": 3385, "naklon": 0 }, +{ "label": "48/1", "node": 4051, "naklon": 5 }, +{ "label": "48/2", "node": 4041, "naklon": 5 }, +{ "label": "48/3", "node": 4056, "naklon": 5 }, +{ "label": "48/4", "node": 3875, "naklon": 5 }, +{ "label": "48/5", "node": 4061, "naklon": 5 }, +{ "label": "48/6", "node": 4047, "naklon": 5 }, +{ "label": "48/7", "node": 4060, "naklon": 5 }, +{ "label": "48/8", "node": 4059, "naklon": 5 }, +{ "label": "48/9", "node": 4058, "naklon": 5 }, +{ "label": "48/10", "node": 3635, "naklon": 5 }, +{ "label": "48/11", "node": 3640, "naklon": 5 }, +{ "label": "48/12", "node": 3747, "naklon": 5 }, +{ "label": "48/13", "node": 3629, "naklon": 5 }, +{ "label": "48/14", "node": 4048, "naklon": 5 }, +{ "label": "48/15", "node": 4063, "naklon": 5 }, +{ "label": "48/16", "node": 4062, "naklon": 5 }, +{ "label": "48/17", "node": 4043, "naklon": 5 }, +{ "label": "48/18", "node": 4052, "naklon": 5 }, +{ "label": "48/19", "node": 4042, "naklon": 5 }, +{ "label": "48/20", "node": 4053, "naklon": 5 }, +{ "label": "50/15A", "node": 4167, "naklon": null }, +{ "label": "50/15B", "node": 4159, "naklon": null }, +{ "label": "50/1", "node": 4183, "naklon": 0 }, +{ "label": "50/2", "node": 4157, "naklon": 0 }, +{ "label": "50/3", "node": 4160, "naklon": 0 }, +{ "label": "50/4", "node": 4173, "naklon": 0 }, +{ "label": "50/5", "node": 4177, "naklon": 0 }, +{ "label": "50/6", "node": 4174, "naklon": 0 }, +{ "label": "50/7", "node": 4178, "naklon": 0 }, +{ "label": "50/8", "node": 4195, "naklon": 0 }, +{ "label": "50/9", "node": 4169, "naklon": 0 }, +{ "label": "50/10", "node": 4162, "naklon": 0 }, +{ "label": "50/11", "node": 4158, "naklon": 0 }, +{ "label": "50/12", "node": 4182, "naklon": 0 }, +{ "label": "50/13", "node": 4194, "naklon": 0 }, +{ "label": "50/14", "node": 4184, "naklon": 0 }, +{ "label": "50/16", "node": 4197, "naklon": null }, +{ "label": "50/17", "node": 4164, "naklon": null }, +{ "label": "50/18", "node": 3306, "naklon": null }, +{ "label": "50/19", "node": 4168, "naklon": null }, +{ "label": "50/20", "node": 4193, "naklon": null }, +{ "label": "50/21", "node": 4187, "naklon": null }, +{ "label": "50/22", "node": 4163, "naklon": null }, +{ "label": "50/23", "node": 4165, "naklon": null }, +{ "label": "50/24", "node": 4185, "naklon": null }, +{ "label": "50/25", "node": 3904, "naklon": null }, +{ "label": "53/1", "node": 2619, "naklon": 0 }, +{ "label": "53/2", "node": 2623, "naklon": 0 }, +{ "label": "53/3", "node": 2617, "naklon": 0 }, +{ "label": "53/4", "node": 2622, "naklon": 0 }, +{ "label": "53/5", "node": 2618, "naklon": 0 }, +{ "label": "53/6", "node": 2626, "naklon": 0 }, +{ "label": "53/7", "node": 2869, "naklon": 0 }, +{ "label": "53/8", "node": 2613, "naklon": 0 }, +{ "label": "53/9", "node": 2608, "naklon": 0 }, +{ "label": "53/10", "node": 2611, "naklon": 0 }, +{ "label": "53/11", "node": 2598, "naklon": 0 }, +{ "label": "53/12", "node": 3528, "naklon": 0 }, +{ "label": "53/13", "node": 3545, "naklon": 0 }, +{ "label": "53/14", "node": 2620, "naklon": 0 }, +{ "label": "53/15", "node": 2612, "naklon": 0 }, +{ "label": "53/16", "node": 2615, "naklon": 0 }, +{ "label": "53/17", "node": 3722, "naklon": 0 }, +{ "label": "53/18", "node": 2624, "naklon": 0 }, +{ "label": "53/19", "node": 2609, "naklon": 0 }, +{ "label": "53/20", "node": 2625, "naklon": 0 }, +{ "label": "53/21", "node": 2602, "naklon": 0 }, +{ "label": "53/22", "node": 2610, "naklon": 0 }, +{ "label": "53/23", "node": 2599, "naklon": 0 }, +{ "label": "53/24", "node": 2605, "naklon": 0 }, +{ "label": "53/25", "node": 2593, "naklon": 0 }, +{ "label": "53/26", "node": 3074, "naklon": 0 }, +{ "label": "53/27", "node": 2740, "naklon": 0 }, +{ "label": "53/28", "node": 2614, "naklon": 0 }, +{ "label": "53/29", "node": 2601, "naklon": 0 }, +{ "label": "53/30", "node": 4196, "naklon": 0 }, +{ "label": "53/31", "node": 2607, "naklon": 0 }, +{ "label": "53/32", "node": 2582, "naklon": 0 }, +{ "label": "53/33", "node": 2594, "naklon": 0 }, +{ "label": "53/34", "node": 2589, "naklon": 0 }, +{ "label": "53/35", "node": 2596, "naklon": 0 }, +{ "label": "53/36", "node": 2603, "naklon": 0 }, +{ "label": "53/37", "node": 2597, "naklon": 0 }, +{ "label": "53/38", "node": 2590, "naklon": 0 }, +{ "label": "53/39", "node": 2581, "naklon": 0 }, +{ "label": "53/40", "node": 2583, "naklon": 0 }, +{ "label": "53/41", "node": 2580, "naklon": 0 }, +{ "label": "53/42", "node": 2579, "naklon": 0 }, +{ "label": "53/43", "node": 2797, "naklon": 0 }, +{ "label": "53/44", "node": 2577, "naklon": 0 }, +{ "label": "53/45", "node": 2586, "naklon": 0 }, +{ "label": "53/46", "node": 2588, "naklon": 0 }, +{ "label": "53/47", "node": 2591, "naklon": 0 }, +{ "label": "53/48", "node": 2592, "naklon": 0 }, +{ "label": "53/49", "node": 2573, "naklon": 0 }, +{ "label": "53/50", "node": 2595, "naklon": 0 }, +{ "label": "53/51", "node": 2587, "naklon": 0 }, +{ "label": "53/52", "node": 2578, "naklon": 0 }, +{ "label": "53/53", "node": 2574, "naklon": 0 }, +{ "label": "53/54", "node": 2571, "naklon": 0 }, +{ "label": "53/55", "node": 2570, "naklon": 0 }, +{ "label": "53/56", "node": 2576, "naklon": 0 }, +{ "label": "53/57", "node": 2881, "naklon": 0 }, +{ "label": "53/58", "node": 2575, "naklon": 0 }, +{ "label": "53/59", "node": 2572, "naklon": 0 }, +{ "label": "53/60", "node": 2569, "naklon": 0 }, +{ "label": "55/1", "node": 4324, "naklon": 0 }, +{ "label": "55/2", "node": 4319, "naklon": 0 }, +{ "label": "55/3", "node": 4327, "naklon": 0 }, +{ "label": "55/4", "node": 4333, "naklon": 0 }, +{ "label": "55/5", "node": 4332, "naklon": 0 }, +{ "label": "55/6", "node": 4320, "naklon": 0 }, +{ "label": "55/7", "node": 4317, "naklon": 0 }, +{ "label": "55/8", "node": 4318, "naklon": 0 }, +{ "label": "55/9", "node": 4328, "naklon": 0 }, +{ "label": "55/10", "node": 4323, "naklon": 0 }, +{ "label": "55/11", "node": 4325, "naklon": 0 }, +{ "label": "55/12", "node": 4326, "naklon": 0 }, +{ "label": "55/13", "node": 4316, "naklon": 0 }, +{ "label": "55/14", "node": 4322, "naklon": 0 }, +{ "label": "55/15", "node": 4331, "naklon": 0 }, +{ "label": "55/16", "node": 4321, "naklon": 0 }, +{ "label": "55/17", "node": 4315, "naklon": 0 }, +{ "label": "55/18", "node": 4329, "naklon": 0 }, +{ "label": "55/19", "node": 4334, "naklon": 0 }, +{ "label": "55/20", "node": 4330, "naklon": 0 } +]; + +module.exports = { naklony }; diff --git a/RVO47/databases/modbus_config.js b/RVO47/databases/modbus_config.js new file mode 100755 index 0000000..b73116a --- /dev/null +++ b/RVO47/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/RVO47/databases/nodes.table b/RVO47/databases/nodes.table new file mode 100755 index 0000000..30ec2e8 --- /dev/null +++ b/RVO47/databases/nodes.table @@ -0,0 +1,5 @@ +node:number|pole_number:string|node_type:string|tbname:string|line:number|profile:string|processed:boolean|status:boolean|time_of_last_communication:number ++|3373|1|NEMA|Z5KyJe9nEg1QNbWlX0wWGD0oDjBLdqzR83VGv624|1||1|1|1760574223684|............. ++|3374|2|NEMA|1JMYvnx2RzKEo4aWQ7DmOZAL8yZV3m9NBePXbrdj|1||1|1|1760574237377|............. ++|3384|3|NEMA|PjLblDgRBO6WQqnxmkJ5D60Jv3ewZN4p5a89yKdY|1||1|1|1760574237664|............. ++|3385|4|NEMA|dz4ojlpP85JMgDLZWkQOzDAaKYqQexEr62GXRV1y|1||1|1|1760574239789|............. diff --git a/RVO47/databases/nodes_original/nodes_original.table b/RVO47/databases/nodes_original/nodes_original.table new file mode 100755 index 0000000..dc327ad --- /dev/null +++ b/RVO47/databases/nodes_original/nodes_original.table @@ -0,0 +1 @@ +[{"3373": "Z5KyJe9nEg1QNbWlX0wWGD0oDjBLdqzR83VGv624"}, {"3374": "1JMYvnx2RzKEo4aWQ7DmOZAL8yZV3m9NBePXbrdj"}, {"3384": "PjLblDgRBO6WQqnxmkJ5D60Jv3ewZN4p5a89yKdY"}, {"3385": "dz4ojlpP85JMgDLZWkQOzDAaKYqQexEr62GXRV1y"}] \ No newline at end of file diff --git a/RVO47/databases/notifications.table b/RVO47/databases/notifications.table new file mode 100755 index 0000000..f7c96cb --- /dev/null +++ b/RVO47/databases/notifications.table @@ -0,0 +1,41 @@ +key:string|weight:string|sk:string|en:string ++|switching_profile_point_applied_to_line|INFORMATIONAL|Aplikovaný bod spínacieho profilu na línií č. ${line} : ${value}|Switching profile point applied to line no. ${line} : ${value}|............... ++|dusk_has_occured|INFORMATIONAL|Nastal súmrak: ${value}|Dusk has occured: ${value}|............... ++|dawn_has_occured|INFORMATIONAL|Nastal úsvit: ${value}|Dawn has occured: ${value}|............... ++|dimming_profile_was_successfully_received_by_node|NOTICE|Stmievací profil bol úspešne prijatý nodom č. ${node}|Dimming profile was successfully received by node no. ${node}|............... ++|master_node_is_responding_again|NOTICE|Master node začal znovu odpovedať|Master node is responding again|............... ++|command_was_sent_from_terminal_interface|DEBUG|Z terminálu bol odoslaný príkaz|A command was sent from terminal interface|............... ++|master_node_is_not_responding|ALERT|Master node neodpovedá|Master node is not responding|............... ++|configuration_of_dimming_profile_to_node_failed|ALERT|Konfigurácia stmievacieho profilu pre node č. ${node} zlyhala|Configuration of dimming profile to node no. ${node} has failed|............... ++|circuit_breaker_was_turned_on_line|NOTICE|Zapnutie ističa na línii č. ${line}|Circuit breaker was turned on - line no. ${line}|............... ++|circuit_breaker_was_turned_off_line|ERROR|Vypnutie ističa na línií č. ${line}|Circuit breaker was turned off - line no. ${line}|............... ++|dimming_profile_was_processed_for_node|INFORMATIONAL|Stmievací profil bol spracovaný pre node č. ${node}|Dimming profile was processed for node no. ${node}|............... ++|switching_profile_was_processed_for_line|INFORMATIONAL|Spínací profil bol spracovaný pre líniu č. ${line}|Switching profile was processed for line no. ${line}|............... ++|thermometer_is_not_responding|WARNING|Teplomer neodpovedá|Thermometer is not responding|............... ++|thermometer_is_responding_again|NOTICE|Teplomer znovu odpovedá|Thermometer is responding again|............... ++|thermometer_sends_invalid_data|WARNING|Teplomer posiela neplatné hodnoty|Thermometer sends invalid data|............... ++|main_switch_has_been_turned_off|CRITICAL|Hlavný vypínač bol vypnutý|Main switch has been turned off|............... ++|main_switch_has_been_turned_on|NOTICE|Hlavný vypínač bol zapnutý|Main switch has been turned on|............... ++|power_supply_has_disconnected_input|ALERT|Napájací zdroj nemá napätie na vstupe|Power supply has disconnected input|............... ++|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_main_open|NOTICE|Hlavné dvere boli otvorené|Main door has been opened|............... ++|door_em_open|NOTICE|Dvere silovej časti boli otvorené|Power door has been opened|............... ++|door_main_open_without_permission|WARNING|Hlavné dvere boli otvorené bez povolenia - zapnutá siréna|Main door has been opened without permission - alarm is on|............... ++|door_em_open_without_permission|WARNING|Dvere silovej časti boli otvorené bez povolenia|Power door has been opened without permission|............... ++|door_main_close|NOTICE|Hlavné dvere boli zatvorené|Main door has been closed|............... ++|door_em_close|NOTICE|Dvere silovej časti boli zatvorené|Power door has been closed|............... ++|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|............... ++|electrometer_ok|NOTICE|Elektromer znovu odpovedá|Electrometer is responding again|............... ++|no_voltage_on_phase|CRITICAL|Na fáze č. ${phase} nie je napätie|No voltage detected on phase no. ${phase}|............... ++|voltage_on_phase_restored|NOTICE|Napätie na fáze č. ${phase} bolo obnovené|Voltage on phase no. ${phase} has been restored|............... ++|flow_start|NOTICE|FLOW bol spustený|FLOW has been started |............... ++|twilight_sensor_nok|ERROR|Sensor súmraku neodpovedá|Twilight sensor is not responding|............... ++|twilight_sensor_ok|NOTICE|Sensor súmraku znovu odpovedá|Twilight sensor is responding again|............... ++|lamps_have_turned_on|NOTICE|Lampy sa zapli|Lamps have turned on|............... ++|lamps_have_turned_off|NOTICE|Lampy sa vypli|Lamps have turned off|............... ++|flow_restart|NOTICE|FLOW bol reštartovaný|FLOW has been restarted|............... ++|nodes_db_changed|NOTICE|Zmena v node databáze|Node db has changed|............... diff --git a/RVO47/databases/pins.table b/RVO47/databases/pins.table new file mode 100755 index 0000000..0eb3d05 --- /dev/null +++ b/RVO47/databases/pins.table @@ -0,0 +1,14 @@ +pin:string|type:string|line:number +*|input1_01|door_condition|0|........... +*|input1_02|rotary_switch_state|0|........... +*|input1_03|rotary_switch_state|0|........... +*|input1_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/RVO47/databases/relays.table b/RVO47/databases/relays.table new file mode 100755 index 0000000..ddcbd5c --- /dev/null +++ b/RVO47/databases/relays.table @@ -0,0 +1,5 @@ +line:number|tbname:string|contactor:number|profile:string ++|0|3JjOWdylwgNLzxVab7NajKkZ2vG64rq8PEB5QmDo|1||........... ++|1|d5xjWYMwEJon6rLlK7yBBQAqgV4DaOeNB9ZX3Gzb|9|{"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":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|gRoJEyXVx4qD9er287LPPd7wBzGldaPjLWQKm3Mv|9|{"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":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|K94XLav1glVRnyQ6r01BBnkme3YJwBxM5oOzdP2j|9|{"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":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/RVO47/databases/settings.table b/RVO47/databases/settings.table new file mode 100755 index 0000000..29154c0 --- /dev/null +++ b/RVO47/databases/settings.table @@ -0,0 +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|project_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|cloud_topic:string|has_main_switch:boolean|daily_report:boolean|send_changed_node_numbers:boolean ++|rvo_senica_47_10.0.0.134|en|28.76799D0E0000|48.70826502|17.28455203|192.168.252.1|rvo_senica_47_10.0.0.134|ur6xlu0lwoILBB4U7Dzc|1883|0|70|unipi|ttyUSB0|1|20|5|6|3|u134|0|1|1|................................................... diff --git a/RVO47/databases/tbdata.nosql b/RVO47/databases/tbdata.nosql new file mode 100755 index 0000000..f7b8194 --- /dev/null +++ b/RVO47/databases/tbdata.nosql @@ -0,0 +1,4 @@ +-"3JjOWdylwgNLzxVab7NajKkZ2vG64rq8PEB5QmDo":[{"ts":1760522580347,"values":{"_event":{"type":"notice","status":"new","source":{"func":"modbus_reader","component":"1699965957410","component_name":"Modbus reader","edge":"3JjOWdylwgNLzxVab7NajKkZ2vG64rq8PEB5QmDo"},"message":{"sk":"rvo_senica_47_10.0.0.134: FLOW bol reštartovaný","en":"rvo_senica_47_10.0.0.134: FLOW has been restarted"},"message_data":""}}}],"id":"3000183001uu71b"} +-"3JjOWdylwgNLzxVab7NajKkZ2vG64rq8PEB5QmDo":[{"ts":1760522580421,"values":{"edge_fw_version":"2025-10-08","maintenance_mode":false}}],"id":"3000183002uu70b"} +-"3JjOWdylwgNLzxVab7NajKkZ2vG64rq8PEB5QmDo":[{"ts":1760522580434,"values":{"statecode":2,"power_mode":"Automatic"}}],"id":"3000183004uu70b"} +-"3JjOWdylwgNLzxVab7NajKkZ2vG64rq8PEB5QmDo":[{"ts":1760522580462,"values":{"_event":{"type":"notice","status":"new","source":{"func":"rsPort.open()","component":"1699963668903","component_name":"DIDO_Controller","edge":"3JjOWdylwgNLzxVab7NajKkZ2vG64rq8PEB5QmDo"},"message":{"sk":"rvo_senica_47_10.0.0.134: FLOW bol spustený","en":"rvo_senica_47_10.0.0.134: FLOW has been started "},"message_data":""}}}],"id":"3000183006uu70b"} diff --git a/RVO47/databases/tbdatacloud.nosql b/RVO47/databases/tbdatacloud.nosql new file mode 100755 index 0000000..9f85c83 --- /dev/null +++ b/RVO47/databases/tbdatacloud.nosql @@ -0,0 +1,3 @@ +-"3JjOWdylwgNLzxVab7NajKkZ2vG64rq8PEB5QmDo":[{"ts":1760522580421,"values":{"edge_fw_version":"2025-10-08","maintenance_mode":false}}],"id":"3000183003uu71b"} +-"3JjOWdylwgNLzxVab7NajKkZ2vG64rq8PEB5QmDo":[{"ts":1760522580434,"values":{"statecode":2,"power_mode":"Automatic"}}],"id":"3000183005uu71b"} +-"3JjOWdylwgNLzxVab7NajKkZ2vG64rq8PEB5QmDo":[{"ts":1760522580462,"values":{"_event":{"type":"notice","status":"new","source":{"func":"rsPort.open()","component":"1699963668903","component_name":"DIDO_Controller","edge":"3JjOWdylwgNLzxVab7NajKkZ2vG64rq8PEB5QmDo"},"message":{"sk":"rvo_senica_47_10.0.0.134: FLOW bol spustený","en":"rvo_senica_47_10.0.0.134: FLOW has been started "},"message_data":""}}}],"id":"3000183007uu71b"} diff --git a/RVO47/databases/total_energy.js b/RVO47/databases/total_energy.js new file mode 100755 index 0000000..dde340e --- /dev/null +++ b/RVO47/databases/total_energy.js @@ -0,0 +1,38 @@ +//key is rvo_number, value is max energy when lamps are on +const total_energy = { + 1: 580, + 2: 1100, + 3: 3700, + 4: 4100, + 7: 360, + 12: 1700, + 13: 5400, + 14: 440, + 15: 6100, + 16: 4800, + 20: 1600, + 21: 1000, + 22: 2600, + 23: 1000, + 25: 2600, + 33: 240, + 34: 4000, + 35: 2700, + 36: 820, + 37: 1400, + 35: 3500, + 39: 1170, + 41: 740, + 42: 660, + 43: 4900, + 45: 930, + 46: 700, + 47: 1100, + 48: 1500, + 50: 3200, + 53: 1250, + 55: 1000, + 56: 5500 +} + +module.exports = total_energy; diff --git a/RVO47/debug.js b/RVO47/debug.js new file mode 100755 index 0000000..9818194 --- /dev/null +++ b/RVO47/debug.js @@ -0,0 +1,16 @@ +// =================================================== +// FOR DEVELOPMENT +// Total.js - framework for Node.js platform +// https://www.totaljs.com +// =================================================== + +const options = {}; + +// options.ip = '127.0.0.1'; +// options.port = parseInt(process.argv[2]); +// options.config = { name: 'Total.js' }; +// options.sleep = 3000; +// options.inspector = 9229; +// options.watch = ['private']; + +require('total.js/debug')(options); \ No newline at end of file diff --git a/RVO47/err.txt b/RVO47/err.txt new file mode 100755 index 0000000..268f826 --- /dev/null +++ b/RVO47/err.txt @@ -0,0 +1,33 @@ +[2025-09-23T14:09:50.404] [ERROR] errLogs - uncaughtException: Cannot read property 'getHours' of undefined +[2025-09-23T14:09:50.405] [ERROR] errLogs - TypeError: Cannot read property 'getHours' of undefined + at Timeout.emptyReportToSend [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:09:50.406] [ERROR] errLogs - uncaughtException: Cannot read property 'getHours' of undefined +[2025-09-23T14:09:50.407] [ERROR] errLogs - TypeError: Cannot read property 'getHours' of undefined + at Timeout.emptyReportToSend [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:09:50.417] [ERROR] errLogs - uncaughtException: Cannot read property 'getHours' of undefined +[2025-09-23T14:09:50.417] [ERROR] errLogs - TypeError: Cannot read property 'getHours' of undefined + at Timeout.emptyReportToSend [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:09:56.129] [ERROR] errLogs - uncaughtException: date.getHours is not a function +[2025-09-23T14:09:56.130] [ERROR] errLogs - TypeError: date.getHours is not a function + at emptyReportToSend (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at Timeout.dailyReportCheck [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1351:5) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:09:56.130] [ERROR] errLogs - uncaughtException: date.getHours is not a function +[2025-09-23T14:09:56.131] [ERROR] errLogs - TypeError: date.getHours is not a function + at emptyReportToSend (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at Timeout.dailyReportCheck [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1351:5) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:09:56.136] [ERROR] errLogs - uncaughtException: date.getHours is not a function +[2025-09-23T14:09:56.136] [ERROR] errLogs - TypeError: date.getHours is not a function + at emptyReportToSend (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at Timeout.dailyReportCheck [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1351:5) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) diff --git a/RVO47/flow/cloudmqttconnect.js b/RVO47/flow/cloudmqttconnect.js new file mode 100755 index 0000000..b03491f --- /dev/null +++ b/RVO47/flow/cloudmqttconnect.js @@ -0,0 +1,357 @@ +exports.id = 'cloudmqttconnect'; +exports.title = 'Cloud connect mqtt'; +exports.group = 'MQTT'; +exports.color = '#888600'; +exports.version = '1.0.2'; +exports.icon = 'sign-out'; +exports.input = 2; +exports.output = 2; +exports.options = { host: 'tb-stage.worksys.io', port: 1883, clientid: "", username: "" }; + +exports.html = `
+
+
+
Hostname or IP address (if not empty - setting will override db setting)
+
+
+
Port
+
+
+
+
+
@(Client id)
+
+
+
topic
+
+
+
`; + + + +const { promisifyBuilder } = require('./helper/db_helper'); +const fs = require('fs'); +const mqtt = require('mqtt'); +const nosql = NOSQL('tbdatacloud'); + +const SEND_TO = { + debug: 0, + rpcCall: 1, +} + +//CONFIG +let saveTelemetryOnError = true;//backup_on_failure overrides this value +//------------------------ + +const noSqlFileSizeLimit = 4194304;//use 5MB - 4194304 +let insertNoSqlCounter = 0; +let insertBackupNoSqlCounter = 0; +let processingData = false; + +let backup_on_failure = true;//== saveTelemetryOnError - create backup client send failure +let restore_from_backup = 50; //how many rows process at once? +let restore_backup_wait = 3;//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; + + +exports.install = function(instance) { + + var client; + var opts; + var clientReady = false; + + let o = {}; //options + + function main() { + loadSettings(); + } + + //set opts according to db settings + function loadSettings() { + + o = instance.options; + if (!o.topic) o.topic = FLOW.GLOBALS.settings.cloud_topic; + + opts = { + host: o.host, + port: o.port, + clientId: o.clientid, + username: o.username, + rejectUnauthorized: false, + resubscribe: false + }; + + console.log("wsmqttpublich -> loadSettings from instance.options", o); + + if (!o.topic) { + instance.status("Not configured", "white"); + console.log("Cloud mqtt connect: no topic selected"); + return; + } + + connectToTbServer(); + } + + function connectToTbServer() { + var url = "mqtt://" + opts.host + ":" + opts.port; + console.log("MQTT URL: ", url); + + client = mqtt.connect(url, opts); + + client.on('connect', function() { + client.subscribe(`${o.topic}_backward`, (err) => { + if (!err) { + console.log("MQTT subscribed"); + } + }); + instance.status("Connected", "green"); + clientReady = true; + sendClientError = true; + }); + + client.on('reconnect', function() { + instance.status("Reconnecting", "yellow"); + clientReady = false; + }); + + client.on('message', function(topic, message) { + // message is type of buffer + message = message.toString(); + if (message[0] === '{') { + TRY(function() { + + message = JSON.parse(message); + if (message.hasOwnProperty("device") && message.hasOwnProperty("data") && message.data.hasOwnProperty("id")) { + client.publish(`${o.topic}_forward`, `{"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 } }); + } + + }, () => instance.debug('MQTT: Error parsing data', message)); + } + + instance.send(SEND_TO.rpcCall, { "topic": o.topic, "content": message }); + }); + + client.on('close', function() { + clientReady = false; + + instance.status("Disconnected", "red"); + instance.send(SEND_TO.debug, { "message": "Client CLOSE signal received !" }); + }); + + client.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) { + console.log('MQTT client error', err); + sendClientError = false; + } + clientReady = false; + }); + + } + + + instance.on('0', function(data) { + + if (clientReady) { + //do we have some data in backup file? if any, process data from database + if (saveTelemetryOnError) { + //read telemetry data and send back to server + if (!processingData) processDataFromDatabase(); + } + + let stringifiedJson = JSON.stringify(data.data) + client.publish(`${o.topic}_forward`, stringifiedJson, { qos: 1 }); + } + 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 (saveTelemetryOnError && o.topic) { + //create new file from tbdata.nosql, if file size exceeds given limit, and clear tbdata.nosql + makeBackupFromDbFile(); + + //write to tb + data.data.id = UID(); + nosql.insert(data.data); + } + } + }); + + instance.on("1", _ => { + main(); + }) + + instance.close = function(done) { + if (clientReady) { + client.end(); + } + }; + + + function getDbBackupFileCounter(type) { + var files = fs.readdirSync(__dirname + "/../databases"); + + let counter = 0; + for (var i = 0; i < files.length; i++) { + + if (files[i] == "tbdatacloud.nosql") continue; + + if (files[i].endsWith(".nosql")) { + + let pos = files[i].indexOf("."); + if (pos > -1) { + + let fileCounter = counter; + let firstDigit = files[i].slice(0, pos); + + fileCounter = parseInt(firstDigit); + if (isNaN(fileCounter)) fileCounter = 0; + //console.log("getDbBackupFileCounter digit:", files[i], firstDigit, fileCounter, isNaN(fileCounter), type); + + if (type == "max") { + if (fileCounter > counter) { + counter = fileCounter; + } + } + else if (type == "min") { + if (counter == 0) counter = fileCounter; + + if (fileCounter < counter) { + counter = fileCounter; + } + } + } + } + + } + + if (type == "max") counter++; + + return counter; + } + + const makeBackupFromDbFile = async () => { + + if (!saveTelemetryOnError) return; + + //to avoid large file: tbdata.nosql + + //init value is 0! + if (insertNoSqlCounter > 0) { + --insertNoSqlCounter; + return; + } + + insertNoSqlCounter = 100; + + let source = __dirname + "/../databases/tbdatacloud.nosql"; + + var stats = fs.statSync(source); + var fileSizeInBytes = stats.size; + + if (fileSizeInBytes > noSqlFileSizeLimit) { + + let counter = 1; + counter = getDbBackupFileCounter("max"); + + let destination = __dirname + "/../databases/" + counter + "." + "tbdatacloud.nosql"; + + //make backup file + fs.copyFileSync(source, destination); + //fs.renameSync(p, p + "." + counter); + + //clear tbdata.nosql + fs.writeFileSync(source, ""); + fs.truncateSync(source, 0); + + } + } + + const processDataFromDatabase = async () => { + + if (restore_from_backup <= 0) return; + + //calculate diff + const now = new Date(); + let currentTime = now.getTime(); + let diff = currentTime - lastRestoreTime; + + if ((diff / 1000) < restore_backup_wait) { + //console.log("*********restore_backup_wait", diff, restore_backup_wait); + return; + } + + processingData = true; + + //get filename to process + let counter = getDbBackupFileCounter("min"); + + //we have some backup files + let dataBase = 'tbdata'; + + var nosql; + if (counter == 0) dataBase = 'tbdatacloud'; + else dataBase = counter + "." + 'tbdatacloud'; + + nosql = NOSQL(dataBase); + + //select all data - use limit restore_from_backup + let records = await promisifyBuilder(nosql.find().take(restore_from_backup)); + + for (let i = 0; i < records.length; i++) { + if (clientReady) { + + let item = records[i]; + let id = item.id; + + if (id !== undefined) { + //console.log("------------processDataFromDatabase - remove", id, dataBase, i); + + try { + + let message = JSON.parse(JSON.stringify(item)); + delete message.id; + client.publish(`${o.topic}_forward`, JSON.stringify(message), { qos: 1 }); + + //remove from database + await promisifyBuilder(nosql.remove().where("id", id)); + + } catch (error) { + //process error + console.log("processDataFromDatabase", error); + } + + } + + } + else { + processingData = false; + return; + } + } + + if (records.length > 0) { + //clean backup file + if (counter > 0) nosql.clean(); + } + + //no data in db, remove + if (records.length == 0) { + if (counter > 0) nosql.drop(); + } + + const d = new Date(); + lastRestoreTime = d.getTime(); + + processingData = false; + + } + + instance.on('options', main); + +}; diff --git a/RVO47/flow/cmd_manager.js b/RVO47/flow/cmd_manager.js new file mode 100755 index 0000000..25912df --- /dev/null +++ b/RVO47/flow/cmd_manager.js @@ -0,0 +1,3071 @@ +exports.id = 'cmd_manager'; +exports.title = 'CMD Manager'; +exports.group = 'Worksys'; +exports.color = '#5D9CEC'; +exports.version = '0.0.3'; +exports.output = ['red', 'blue', 'yellow', 'blue', 'white', 'green']; +exports.input = 3; +exports.icon = 'cloud-upload'; + +exports.html = ` +
+
+
+
RPC - run RPC calls

+
+
+
@(User)
+
+
+
@(Password)
+
+
+
@(My edge)
+
+
+
+`; +exports.readme = `Manager for CMD calls`; + + +exports.install = function(instance) { + + 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, isEmptyObject, emptyJsObject, writeToFile, addToArrayIfUnique } = require('./helper/utils'); + const bitwise = require('bitwise'); + + var SunCalc = require('./helper/suncalc'); + const DataToTbHandler = require('./helper/DataToTbHandler'); + const errorHandler = require('./helper/ErrorToServiceHandler'); + const { sendNotification } = require('./helper/notification_reporter'); + const process = require('process'); + const { errLogger, logger, monitor } = require('./helper/logger'); + + //for accelerometer purposes + const { naklony } = require("../databases/accelerometer_db"); + + const dbNodes = TABLE("nodes"); + const dbRelays = TABLE("relays"); + + let GLOBALS; + let SETTINGS; + let rsPort; + let tbHandler; + + // runTasks intervals + const SHORT_INTERVAL = 30; + const LONG_INTERVAL = 300; + + //send data to following instances: + const SEND_TO = { + debug: 0, + tb: 1, + http_response: 2, + dido_controller: 3, + infoSender: 4, + dailyReport: 5 + } + + 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 + } + + 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 sendNodeReadout = null; // interval for sending agregate data from node + + 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["1"] = minutes; // dimming + priorities["76"] = minutes; // power + + minutes = 5; + priorities["75"] = minutes; // current + priorities["79"] = minutes; // energy + priorities["87"] = minutes; // aktualny cas + //priorities["84"] = minutes; //accelerometer + + minutes = 10; + priorities["74"] = minutes; // voltage + priorities["77"] = minutes; // power factor + priorities["78"] = minutes; // frequency + + minutes = 60; + priorities["0"] = minutes; // statecode + priorities["6"] = minutes; // dusk + priorities["7"] = minutes; // dawn + priorities["8"] = minutes; // profile + + minutes = 60 * 24; + priorities["89"] = minutes; // verzia fw + priorities["80"] = minutes; // lifetime + + //prikazy kt sa budu spustat na dany node - see config.js in terminal-oms.app. (1 - dimming) + let listOfCommands = [0, 1, 6, 7, 8, 74, 75, 76, 77, 78, 79, 80, 87, 89]; + + 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; + + // holds dusk, dawn (and more) values + let sunCalcResult; + + //helper container for counting resolved group of commands (commands related to set profile) + let cmdCounter = {};//key is node, value is counter + + //TODO: is this set working?? According to previous checks, sets do not work + //if sending of profile to node fails, we send notification and push node into set, so we do not send notification twice + const nodeProfileSendFail = new Set(); + + //we expect to get current temperature in Senica from senica-prod01 + let temperatureInSenica = null; + let accelerometerInterval = null; + + //NOTE: daily reports senica: + //rvo_is_on status, we monitor all nodes - if true, power and dimming should be not 0, if false, 24/7 nodes should be 0, other rvo should not respond + let rvo_is_on; + let previous_rvo_is_on_value; + let handleDailyReport; //setInterval for dailyReportHandler function + let dailyReport = {}; //data needed for daily report + let reportToSend = {}; //final report which we send to cloud + let breakerCounter = null; // status of breakers after flow starts is not in report + let rvoPeriod; // interval of checking dusk dawn and if rvo_is_on + let initialReportStatus = false; + + const DAILY_REPORT_HANDLER_TIME = 3_600_000; + const SET_SUNCALC_RESULT_TIME = 3_600_000; + const SET_RVO_PERIOD_TIME = 300_000; + const ADD_NODE_TO_REPORT_TIME = 3_600_000; + + //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); + + let now = new Date(); + console.log("Cmd-mngr installed", now.toLocaleString("sk-SK")); + + sunCalcResult = calculateDuskDawn(); + + handleRsPort(); + + customTasksInterval = setInterval(reportEdgeDateTimeAndNumberOfLuminaires, 120_000); + setTimeout(reportEdgeDateTimeAndNumberOfLuminaires, 4000); + + //dailyReport related + emptyReportToSend(); + breakerCounter = Object.keys(relaysData).length - 1; // we get number of lines (breakers) except of line 0 + rvoPeriod = setInterval(setRvoPeriod, SET_RVO_PERIOD_TIME); + setTimeout(setRvoPeriod, 3000); + setInterval(setSunCalcResult, SET_SUNCALC_RESULT_TIME); + handleDailyReport = setInterval(dailyReportHandler, DAILY_REPORT_HANDLER_TIME); + + + setCorrectTime = setInterval(setCorrectPlcTimeOnceADay, 60000 * 60); // 1 hour + setCorrectPlcTimeOnceADay(); + + sendNodeReadout = setInterval(sendNodesData, 150_000); + accelerometerInterval = setInterval(accelerometerData, 60000 * 30); //30 min + } + + + 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" + //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 + // if node regular readout does not respond, we repeat request + params.repeatCounter = 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-mngr: 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.byte4 = 96; + params.recipient = 1; + params.register = 8; + params.rw = 1;//write + params.timestamp = timestamp; + 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.byte4 = 96; + params.recipient = 1; + params.register = 8; + params.rw = 1;//write + params.timestamp = timestamp; + 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). + */ + + 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.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.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 + { + + logger.debug("processNodeProfile: Threshold lux level for DUSK/DAWN", node); + + let params = getParams(); + params.type = "set_node_profile"; + params.address = node; + params.register = 96; + params.recipient = 1; + params.rw = 1;//write + params.timestamp = timestamp; + 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(); + params.type = "set_node_profile"; + params.address = node; + params.register = 97; + params.recipient = 1; + params.rw = 1;//write + params.timestamp = timestamp; + 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.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); + + 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); + + console.log("proces profile finished *********************") + } + + + 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; + }); + } + + + 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) { + for (let k in nodesData) { + 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`); + } + } + } + + + function loadRelaysData(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 (value.contactor == 1) processAllNodeProfilesOnLine(value.line); + } + } + + + function reportOnlineNodeStatus(line) { + //Po zapnutí línie broadcastovo aktualizovať predtým čas a o 3 sek neskor - status, brightness + + logger.debug("Cmd-mngr: ----->reportOnlineNodeStatus for line", line); + + const d = new Date(); + + // broadcast actual time + let params = getParams(); + params.address = 0xffffffff;//Broadcast + params.byte1 = d.getHours(); + params.byte2 = d.getMinutes(); + params.recipient = 2;//2 broadcast, address = 0 + params.register = 87;//Actual time + params.rw = 1;//write + params.type = "node-onetime-write"; + params.timestamp = d.getTime() + 30000; + params.info = "run broadcast: Actual time"; + //params.debug = true; + + tasks.push(params); + + let sec = 3; + setTimeout(function() { + //Po zapnutí línie - spraviť hromadný refresh stavu práve zapnutých svietidiel + + let time = Date.now(); + + for (let k in nodesData) { + + //potrebujem nody k danej linii + 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].node_status_before_offline === true || nodesData[k].status === true) { + status = "OK"; + nodesData[k].time_of_last_communication = time; + } + + nodesData[k].readout.status = status; + + updateNodeStatus(k, status === "OK" ? true : false); + if (nodesData[k].hasOwnProperty("node_status_before_offline")) delete nodesData[k].node_status_before_offline; + sendTelemetry({ status: status }, tbname, time); + + //vyreportovanie dimming, current, input power pre liniu pre vsetky nody + //Prud + { + let params = getParams(); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 75;//prud + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = time + 4000; + params.info = 'read current'; + //params.debug = true; + tasks.push(params); + } + + //vykon + { + let params = getParams(); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 76;//výkon + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = time + 4100; + params.info = 'read power'; + //params.debug = true; + + tasks.push(params); + } + //dimming + { + let params = getParams(); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 1;//dimming + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = time + 4200; + params.info = 'read dimming'; + //params.debug = true; + + tasks.push(params); + } + + } + } + + }, sec * 1000); + } + + + function reportOfflineNodeStatus(line) { + + logger.info("Cmd-mngr: ------>reportOffLineNodeStatus for line ", line); + + values = {}; + values["dimming"] = 0;//brightness + values["power"] = 0;//výkon + values["current"] = 0;//prúd + values["status"] = "OFFLINE"; + + const date = Date.now(); + + Object.keys(nodesData).forEach(node => { + + //potrebujem nody k danej linii + if (line == nodesData[node].line || line == undefined) { + + let tbname = nodesData[node].tbname; + let nodeStatus = nodesData[node].status; + + //in case we have reported offline node status, we return (continue with next node) + if (nodeStatus === "OFFLINE") return; + + nodesData[node].node_status_before_offline = nodeStatus; + nodesData[node].status = "OFFLINE"; + nodesData[node].readout = {}; + + sendTelemetry({ ...values }, tbname, date); + } + }); + + } + + + function turnLine(onOrOff, line, info) { + let obj = { + line: line, + command: onOrOff, + info: info + }; + + //to assure, handleDailyReportFunction do not run before rvo_is_on variable changes. So after every line switch we reset the timer + clearInterval(handleDailyReport); + handleDailyReport = setInterval(dailyReportHandler, DAILY_REPORT_HANDLER_TIME); + + //logger.debug("linia", line, obj); + instance.send(SEND_TO.dido_controller, obj); + } + + + 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"; + 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]) { + //CRC_ERROR + message = "NOK"; + error = "CRC_ERROR c1"; + instance.send(SEND_TO.debug, "CRC_ERROR c1"); + } + + 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") { + instance.send(SEND_TO.debug, bytes); + instance.send(SEND_TO.debug, "RESPONSE " + type + " - " + bytes[4]); + + //logger.debug(SEND_TO.debug, "RESPONSE " + type + " - " + bytes[4], bytes); + + error = "type is: " + type; + + message = "NOK"; + } + + return { message, type, error }; + } + + + //BUILD TASKS// + function buildTasks(params) { + + //return; + console.log("buidTAaasks start ****************", params); + monitor.info("buildTasks - params", params); + + let processLine; //defined line + let init = false; + let processLineProfiles = true; + let processBroadcast = true; + let processNodes = true; + + if (params == undefined) { + init = true; + tasks = []; + logger.debug("-->buildTasks clear tasks"); + } + else { + processLineProfiles = params.processLineProfiles; + processBroadcast = false; + processNodes = false; + + processLine = params.line; + } + + let now = new Date(); + + //process line profiles + if (processLineProfiles) { + + let keys = Object.keys(relaysData); + + for (let i = 0; i < keys.length; i++) { + + let line = parseInt(keys[i]); + let profilestr = relaysData[line].profile; + + if (processLine != undefined) { + if (processLine != line) continue; + } + + try { + + /** + * we process line profiles: timepoints, astro clock, lux_sensor, offsets ... + */ + if (profilestr === "") throw ("Profile is not defined"); + let profile = JSON.parse(profilestr); + 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; + + // add name to regular profile timepoint and delete unused end_time key: + time_points.forEach(point => { + point.name = "profileTimepoint" + delete point.end_time; + }); + + //monitor.info("buildTasks: time_points", time_points); + + + /** + * 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 astro clock true, we remove all regular profile points + time_points = []; + + //TODO: when astro clock == true, is offset calculated ??? + //let duskAstroClockOffset = profile.dusk_astro_clock_offset; + //let dawnAstroClockOffset = profile.dawn_astro_clock_offset; + //console.log("line astro clock offsets dusk a dawn: ", duskAstroClockOffset, dawnAstroClockOffset); + // maybe add dusk dawn offset to calculateDuskDawn ?? what dusk dawn will be if dawn_lux_sensor == true?? + //let sunCalcResult = calculateDuskDawn(new Date(), line, duskAstroClockOffset, dawnAstroClockOffset); + + 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 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); + + 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); + + 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(':'); + + let ad = new Date(); + ad.setHours(parseInt(ahours), parseInt(aminutes), 0); + + let bd = new Date(); + bd.setHours(parseInt(bhours), parseInt(bminutes), 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++) { + + let start_time = new Date(); + let [hours, minutes] = time_points[t].start_time.split(':'); + start_time.setHours(parseInt(hours), parseInt(minutes), 0); + + //task is in 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(); + params.type = "relay"; + params.line = parseInt(line); + params.value = time_points[t].value; + params.tbname = relaysData[line].tbname; + params.timestamp = start_time.getTime(); + + // 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; + + //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)) { + 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; + + params.debug = true; + + //turn on/off line + tasks.push(params); + monitor.info("TimePoint params: ", params.info, start_time); + } + + monitor.info("-->time_points final", line, time_points); + + //ensure to turn on/off according to calculated currentValue + let params = getParams(); + params.type = "relay"; + params.line = parseInt(line); + params.tbname = relaysData[line].tbname; + params.value = currentValue; + params.timestamp = i; + params.debug = true; + + //logger.debug(now.toLocaleString("sk-SK")); + 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; + + tasks.push(params); + + } catch (error) { + if (profilestr !== "") { + //errLogger.error(profilestr, error); + console.log(`Cmd_mngr: Unable to process line profile ${line}. Error: `, error); + errorHandler.sendMessageToService(profilestr + "-" + error, 0, "js_error"); + } else { + turnLine("off", line, "No line profile. Switching it off on startup"); + } + } + + } + //logger.debug("tasks:"); + //logger.debug(tasks); + } + + + //NOTE: PROCESS DEFAULT BROADCASTS - Time of dusk, Time of dawn, Actual Time + if (processBroadcast) { + + let d = new Date(); + let time = d.getTime(); + //let sunCalcResult = calculateDuskDawn(); + + { + let params = getParams(); + + params.address = 0xffffffff;//broadcast + params.byte1 = sunCalcResult["dusk_hours"]; + params.byte2 = sunCalcResult["dusk_minutes"]; + params.recipient = 2;//2 broadcast, + params.register = 6;//Time of dusk + params.rw = 1;//write + params.type = "node-regular-write"; + params.timestamp = time + 60000; + params.addMinutesToTimestamp = 60 * 3; //kazde 3 hodiny zisti novy dusk + params.info = "Broadcast-duskTime"; + + tasks.push(params); + } + + { + let params = getParams(); + + params.address = 0xffffffff;//broadcast + params.byte1 = sunCalcResult["dawn_hours"]; + params.byte2 = sunCalcResult["dawn_minutes"]; + params.recipient = 2; //2 broadcast + params.register = 7;//Time of dawn + params.rw = 1;//write + params.type = "node-regular-write"; + params.timestamp = time + 60001; + params.addMinutesToTimestamp = 60 * 3; //kazde 3 hodiny zisti novy dawn + params.info = "Broadcast-dawnTime"; + + tasks.push(params); + } + + { + let params = getParams(); + + params.address = 0xffffffff;//broadcast + params.byte1 = d.getHours(); + params.byte2 = d.getMinutes(); + params.recipient = 2; //2 broadcast + params.register = 87;//Actual time + params.rw = 1;//write + params.type = "node-regular-write"; + params.timestamp = time + 60002; + params.addMinutesToTimestamp = 5; + params.info = "run broadcast: Actual time"; + + tasks.push(params); + } + + } + + //process nodes & tasks - read node's data + if (processNodes) { + + let time = Date.now(); + + for (let k in nodesData) { + let address = parseInt(k); + let tbname = nodesData[k].tbname; + let register = 0; + + for (let i = 0; i < listOfCommands.length; i++) { + + register = listOfCommands[i]; + let addMinutesToTimestamp = priorities[register]; + + let params = getParams(); + + params.address = address; + params.recipient = 1; + params.register = register; + params.type = register == 1 ? "node-dimming-read" : "node-regular-read"; + params.tbname = tbname; + params.timestamp = time + 5000 + i * 500 + addMinutesToTimestamp * 1000; //to make slight time difference + params.addMinutesToTimestamp = addMinutesToTimestamp; + params.info = "Node regular read command"; + + tasks.push(params); + } + + } + } + + + //niektore ulohy sa vygeneruju iba 1x pri starte!!! + if (!init) return; + + + //Master node FW version - modifies SETTINGS.masterNodeIsResponding + { + let params = getParams(); + params.type = "cmd-master"; + params.register = 4; + params.address = 0; + params.timestamp = 0; + params.addMinutesToTimestamp = 5; + params.tbname = SETTINGS.rvoTbName; + params.info = "Master node FW verzia"; + //params.debug = true; + + tasks.push(params); + } + + //kazdu hodinu skontrolovat nastavenie profilov + { + let params = getParams(); + params.type = "process_profiles"; + params.timestamp = Date.now() + 60001; + params.addMinutesToTimestamp = 60;//60 = every hour + params.info = "detekcia nespracovaných profilov linie a nodov"; + //params.debug = true; + + tasks.push(params); + } + + monitor.info("tasks created:", tasks.length); + } + + + /** + * We process line profile, where "astro_clock": true + * example profile: + * + "dawn_lux_sensor": true, + "dusk_lux_sensor": true, + "dawn_lux_sensor_value": 5, + "dusk_lux_sensor_value": 5, + "dawn_astro_clock_offset": 0, + "dusk_astro_clock_offset": 10, + "dawn_lux_sensor_time_window": 30, + "dusk_lux_sensor_time_window": 30, + "dawn_astro_clock_time_window": 60, + "dusk_astro_clock_time_window": 60 + + * if dawn: if currentTimestamp is in timewindow "dawnTime + and - dawn_lux_sensor_time_window" and lux value >= lux_sensor_value, we switch off the line. + * if dusk: we do oposite + * + * dawn: usvit - lux je nad hranicou - vypnem + * dusk: sumrak - lux je pod hranicou - zapnem + */ + 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++) { + + let line = keys[i]; //line is turned off by default + let profilestr = relaysData[line].profile; + const contactor = relaysData[line].contactor; + + try { + + let profile = JSON.parse(profilestr); + if (Object.keys(profile).length === 0) throw ("turnOnOffLinesAccordingToLuxSensor - profile is not defined"); + + 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 (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"); + } + } + } + + //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 (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"); + } + } + } + + } + + } catch (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) { + //MASTER + if (node == 0) return; + + let nodeObj = nodesData[node]; + if (nodeObj == undefined) return; + + let nodeCurrentStatus = nodeObj.status; + const now = Date.now(); + + let data = null; + + if (nodeCurrentStatus === "OFFLINE") { + data = { status: newStatus }; + nodeDbStatusModify(node, data); + return; + } + else 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; + } + + } + + + 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 }; + } + }); + }); + } + + + function processDailyReport() { + + const now = Date.now(); + + for (const [key, value] of Object.entries(dailyReport)) { + + if (["name", "time", "dusk_and_dawn"].includes(key)) continue; + + let poleNumber = nodesData[key]["pole_number"]; + let line = dailyReport[key].line; + let nodeType = nodesData[key]["node_type"]; + let fullNodeName = key // key == nodeNumber + + if (poleNumber && nodeType) { + fullNodeName = SETTINGS.rvo_number + "/" + poleNumber + "_" + line + "L_" + key + "_" + nodeType; + } else { + fullNodeName = key; + } + + if (rvo_is_on) { + + if (value.initialTs) { + if (value.initialTs + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["night_no_data"], fullNodeName); + console.log('report nedostava ziadne data uz hodinu', fullNodeName); + value.initialTs = now; + } + } + if (value.dimmingIsZeroTime) { + if (value.dimmingIsZeroTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["night_dimming=0"], fullNodeName); + console.log("report node dimming je 0 ale ma svietit", fullNodeName); + value.dimmingIsZeroTime = now; + } + } + if (value.powerIsZeroTime) { + if (value.powerIsZeroTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["night_power=0"], fullNodeName); + console.log("report node power je 0 ale ma svietit", fullNodeName); + value.powerIsZeroTime = now; + } + } + + } else { + + let contactorStatus = relaysData[line].contactor; + if (contactorStatus === 1) { + + if (value.initialTs) { + if (value.initialTs + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["day_24/7_no_data"], fullNodeName); + console.log('node je na 24/7 ale nedostava ziadne data uz hodinu', fullNodeName); + value.initialTs = now; + } + } + if (value.dimmingIsOnButShouldBeOffTime) { + if (value.dimmingIsOnButShouldBeOffTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["day_24/7_dimming>0"], fullNodeName); + console.log("report dimming je > 0 ale nema svietit", fullNodeName); + value.dimmingIsOnButShouldBeOffTime = now; + } + } + if (value.powerIsOnButShouldBeOffTime) { + if (value.powerIsOnButShouldBeOffTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["day_24/7_power>0"], fullNodeName); + console.log("report power je > 0 ale nema svietit", fullNodeName); + value.powerIsOnButShouldBeOffTime = now; + } + } + + } + + } + + } + + let report = {}; + report["name"] = SETTINGS.rvo_name; + report["time"] = new Date(); + report["report"] = reportToSend; + + writeToFile(F.path.root("report_data.log"), report, true); + instance.send(SEND_TO.dailyReport, report); + } + + + function dailyReportHandler() { + + if (!SETTINGS.daily_report) return; + + // after dawn we empty reportToSend and start to get data for a new day + const date = new Date(); + const hour = date.getHours(); + const minute = date.getMinutes(); + + console.log("now: ", hour, minute, "suncalc: ", sunCalcResult.dawn_hours, sunCalcResult.dawn_minutes); + + if (hour === sunCalcResult.dawn_hours) { + + //NOTE: ak je este pred usvitom, spracujeme report a posleme na cloud, ak uz je po usvite, resetujeme report plnime data noveho dna + if (minute >= sunCalcResult.dawn_minutes - 2) { + emptyReportToSend(); + emptyDailyReport(); + console.log("Podmienka 1 v dailyReport handler"); + } else { + processDailyReport(); + emptyReportToSend(); + emptyDailyReport(); + console.log("Podmienka 2 v dailyReport handler"); + } + + initialReportStatus = true; + + // ak sa funkcia spusti o hodinu alebo 2 neskor, ako je usvit (moze sa to stat, kedze kazde zapnutie/vypnutie linii odznova spusti casovac. + } else if (hour === sunCalcResult.dawn_hours + 1 || hour === sunCalcResult.dawn_hours + 2) { + if (!initialReportStatus) { + emptyReportToSend(); + emptyDailyReport(); + initialReportStatus = true; + console.log("Podmienka 3 v dailyReport handler"); + } else { + processDailyReport(); + initialReportStatus = true; + console.log("Podmienka 4 v dailyReport handler"); + } + } else { + processDailyReport(); + initialReportStatus = false; + console.log("Podmienka 5 v dailyReport handler"); + } + + console.log("initialReportStatus: ", initialReportStatus); + + } + + function emptyReportToSend() { + emptyJsObject(reportToSend); + reportToSend["contactor"] = { off: [], on: [] }; + reportToSend["night_no_data"] = []; + reportToSend["night_dimming=0"] = []; + reportToSend["night_power=0"] = []; + reportToSend["day_24/7_no_data"] = []; + reportToSend["day_24/7_dimming>0"] = []; + reportToSend["day_24/7_power>0"] = []; + console.log(`resetuje sa reportToSend`); + } + + + //NOTE: ked je initialTs stale rovnaky a zistime ze linie su vypnute (relaysData.line.contactor) - zistim, ci je node na tej linii. Vieme, ze ak je linia vypnuta je to v poriadku lebo nie je na 24/7 linii + //ak je na 24/7 linii, reportujeme, ze neprijima data + function emptyDailyReport() { + const ts = Date.now(); + emptyJsObject(dailyReport); + + //NOTE: do dailyReport dame vsetky nody a pravidelne kontrolujeme ci maju data + //ked nastane sumrak/usvit a svetla maju zacat/prestat svietit, dailyReport spravime nanovo: + for (const [key, value] of Object.entries(nodesData)) { + dailyReport[value.node] = { line: value.line, initialTs: ts }; + } + + console.log("dailyReport: ", dailyReport); + } + + + async function runTasks() { + + clearInterval(interval); + + let currentTimestamp = Date.now(); + + //sort tasks based on timestamp + 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) { + instance.send(SEND_TO.debug, "no tasks created"); + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + if (!rsPort.isOpen) { + instance.send(SEND_TO.debug, "!rsPort.isOpen"); + //await rsPort.open(); + //console.log("Cmd-mngr: !rsPort.isOpen"); + } + + let currentTask = tasks[0]; + + if (currentTask.debug) { + //logger.debug("--->task to process", currentTask); + } + + if (currentTask.timestamp <= currentTimestamp) { + let params = { ...tasks[0] }; + + //allow terminal commands + if (SETTINGS.maintenance_mode && params.type !== "cmd-terminal") { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + let type = params.type; + let tbname = params.tbname; + let node = params.address; + let register = params.register; + let line = null; + let itIsNodeCommand; + + if (nodesData[node] !== undefined) { + line = nodesData[node].line; + itIsNodeCommand = true; + } + + if (params.line !== undefined) line = params.line; + + if (params.addMinutesToTimestamp > 0 || params.timePointName) { + tasks[0].timestamp = currentTimestamp + tasks[0].addMinutesToTimestamp * 60000; + } else { + tasks.shift(); + } + + //kontrola nespracovanych profilov nodov + //TODO: co ked niektore nody neprijimaju profily? kazdu hodinu zahltuju "tasks" array + if (type == "process_profiles") { + //na vsetky zapnutych liniach sa spracuju nespracovane profily nodov + loadRelaysData(); + interval = setInterval(runTasks, SHORT_INTERVAL); + return; + } + + //relay + if (type == "relay") { + + const timePointName = params.timePointName; + const value = params.value; + + let date = new Date(); + date.setDate(date.getDate() + 1);//next day + + let sunCalcResult; + if (timePointName) sunCalcResult = calculateDuskDawn(date, params.line); + + + if (timePointName == "dawn") { + tasks[0].timestamp = sunCalcResult.dawn_time; + } + else if (timePointName == "dusk") { + tasks[0].timestamp = sunCalcResult.dusk_time; + } + else if (timePointName == "luxOn") { + tasks[0].timestamp = sunCalcResult.dusk_time + params.dusk_lux_sensor_time_window * 60000; + } + else if (timePointName == "luxOff") { + tasks[0].timestamp = sunCalcResult.dawn_time + params.dawn_lux_sensor_time_window * 60000; + } + else if (timePointName == "profileTimepoint") { + tasks[0].timestamp = currentTimestamp + tasks[0].addMinutesToTimestamp * 60000; + } + + let info = "aplikovany bod profilu"; + let onOrOff = ""; + value == 1 ? onOrOff = "on" : onOrOff = "off"; + + turnLine(onOrOff, params.line, info); + + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + if (!SETTINGS.masterNodeIsResponding) { + //ak neodpoveda, nebudeme vykonavat ziadne commands, okrem cmd-terminal cmd-master + errorHandler.sendMessageToService("Master node is not responding"); + + let stop = true; + + if (type === "cmd-terminal" || type === "cmd-master") stop = false; + if (stop) { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + } + + let contactorStatus = 1; + if (relaysData[line] != undefined) contactorStatus = relaysData[line].contactor; + + if (line === 0 || contactorStatus === 0 || FLOW.deviceStatus.state_of_breaker[line] === "Off") { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + // TODO: -> status offline for rvo if rotary_switch_state is OFF, this is source of errors + // check if rotary_switch_state == "Off" + // state_of_braker: disconnected = true? + + if (!rsPort.isOpen) { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + //RE-CALCULATE VALUES + //set actual time for broadcast + if (register == 87 && params.recipient === 2) { + var d = new Date(); + params.byte1 = d.getHours();//h + params.byte2 = d.getMinutes();//m + } + + //SET DUSK/DAWN FOR BROADCAST + //Time of dusk + if (register == 6 && params.recipient === 2) { + + if (type != "cmd-terminal") { + params.byte1 = sunCalcResult["dusk_hours"];//h + params.byte2 = sunCalcResult["dusk_minutes"];//m + } + } + + //Time of dawn + if (register == 7 && params.recipient === 2) { + if (type != "cmd-terminal") { + params.byte1 = sunCalcResult["dawn_hours"];//h + params.byte2 = sunCalcResult["dawn_minutes"];//m + } + } + //----------------------- + + instance.send(SEND_TO.debug, "address: " + node + " register:" + register + "type: " + type); + + var startTime, endTime; + startTime = new Date(); + + let saveToTb = true; + if (!tbname) saveToTb = false; + + let resp = com_generic(node, params.recipient, params.rw, register, params.name, params.byte1, params.byte2, params.byte3, params.byte4); + let readBytes = 11; + let timeout = 4000; + + + // await keyword is important, otherwise incorrect data is returned! + await writeData(rsPort, resp, readBytes, timeout).then(function(data) { + + //sometimes happens, that status of node changes to OK, NOK even if line was turned off and should be status OFFLINE. To prevent this, we return if line contactor is 0: + if (itIsNodeCommand && line && relaysData[line].contactor !== 1) return; + + 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); + + //ak sa odpoved zacina 0 - je to v poriadku, inak je NOK + let message = result.message; // OK, NOK + let message_type = result.type; + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + console.log("detected response:", result); + logger.debug("Cmd-mngr: writeData done " + message_type + " duration: " + timeDiff + " type: " + params.debug, params, result); + } + } + + let values = {}; + + //CMD FINISHED + if (message == "OK") { + + updateNodeStatus(node, true); + + //write + if (type == "set_node_profile") { + let result = cmdCounterResolve(node); + if (result == 0) { + dbNodes.modify({ processed: true }).where("node", node).make(function(builder) { + builder.callback(function(err, response) { + + sendNotification("Cmd-mngr: process cmd", SETTINGS.rvoTbName, "dimming_profile_was_successfully_received_by_node", { node: node }, "", SEND_TO.tb, instance); + + logger.debug("--> profil úspešne odoslaný na node č. " + node); + nodesData[node].processed = true; + nodeProfileSendFail.delete(node); + }); + }); + } + } + + //parse read response + if (params.rw == 0) { + values = processResponse(register, dataBytes); //read + } + + if (itIsNodeCommand) { + values.comm_status = "OK"; + values.status = "OK"; + nodesData[node].readout = { ...nodesData[node].readout, ...values }; + + + if (SETTINGS.daily_report) { + //TODO: co ak nedostavame odpovede z nodu ? Musime vyreportovat!! + //v dailyReport teda musi byt kompletny zoznam nodov a neustale kontrolovat, ci maju data, ak nie report node - neodpoveda + if (register === 1) { + + let now = Date.now(); + + if (rvo_is_on === true) { + + if ("dimmingIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].dimmingIsOnButShouldBeOffTime; + + if (values.dimming > 0) { + if ("dimmingIsZeroTime" in dailyReport[node]) delete dailyReport[node].dimmingIsZeroTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if (!("dimmingIsZeroTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], dimmingIsZeroTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } else { + + if ("dimmingIsZeroTime" in dailyReport[node]) delete dailyReport[node].dimmingIsZeroTime; + + if (values.dimming > 0) { + if (!("dimmingIsOnButShouldBeOffTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], dimmingIsOnButShouldBeOffTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if ("dimmingIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].dimmingIsOnButShouldBeOffTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } + } + + if (register === 76) { + + let now = Date.now(); + + if (rvo_is_on === true) { + + if ("powerIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].powerIsOnButShouldBeOffTime; + + if (values.power > 1) { + if ("powerIsZeroTime" in dailyReport[node]) delete dailyReport[node].powerIsZeroTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if (!("powerIsZeroTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], powerIsZeroTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } else { + + if ("powerIsZeroTime" in dailyReport[node]) delete dailyReport[node].powerIsZeroTime; + + if (values.power > 1) { + if (!("powerIsOnButShouldBeOffTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], powerIsOnButShouldBeOffTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if ("powerIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].powerIsOnButShouldBeOffTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } + } + } + + } + + //master node + if (node == 0) { + sendNotification("Cmd-mngr: 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; + } + + if (params.debug) { + //logger.debug("saveToTb", saveToTb, tbname, values); + } + + if (saveToTb && type != "node-regular-read") { + sendTelemetry(values, tbname); + } + else { + if (type == "cmd-terminal") { + terminalCommandResponse(params, "SUCCESS", data); + } + } + + } + else { + terminalCommandResponse(params, "ERROR", data); + handleNokResponseOnRsPort("handleNOK else block", params, itIsNodeCommand, saveToTb); + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + //logger.debug("writeData err: ", error, result, params); + logger.debug("writeData err: ", tbname, node, register, values); + } + } + + //logger.debug(error, result, params); + } + }).catch(function(reason) { + + //console.log("writeData catch exception", reason); + instance.send(SEND_TO.debug, reason); + + terminalCommandResponse(params, "FAILURE", null, reason); + handleNokResponseOnRsPort("handleNOK catch block", params, itIsNodeCommand, saveToTb); + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + logger.debug("-->WRITE FAILED: " + reason, params.debug, params); + } + } + + }); + + } + 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); + } + + + // if node does not respond to request, we repeat request 3 times: + function repeatCommand(params) { + params.repeatCounter++; + if (params.repeatCounter < 4) { + params.timestamp = 0; + params.addMinutesToTimestamp = 0; + tasks.push(params); + } + } + + function handleNokResponseOnRsPort(message, params, itIsNodeCommand, saveToTb) { + + let node = params.address; + let register = params.register; + let type = params.type; + let tbName = params.tbname; + if (!tbName) return; + + let values = {}; + + let updateStatus = updateNodeStatus(node, false); + + if (itIsNodeCommand) { + values.comm_status = "NOK"; + nodesData[node].readout.comm_status = "NOK"; + repeatCommand(params); + } + + if (updateStatus) { + values.status = "NOK"; + nodesData[node].readout.status = "NOK"; + } + + if (type === "node-regular-read") return; + + //master node + if (node == 0) { + sendNotification("Cmd-mngr: 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; + + if (register == 4) values["master_node_version"] = "NOK"; + } + + if (type == "set_node_profile") { + delete cmdCounter[node]; + logger.debug("profil nebol úspešne odoslaný na node č. ", params); + + if (!nodeProfileSendFail.has(node)) { + sendNotification("Cmd-mngr: process cmd", tbName, "configuration_of_dimming_profile_to_node_failed", { node: node }, "", SEND_TO.tb, instance); + nodeProfileSendFail.add(node); + } + } + + // console.log("------",node, register, type, itIsNodeCommand, updateStatus, saveToTb, values); + if (saveToTb) { + sendTelemetry(values, tbName); + } + + } + + + function sendNodesData() { + Object.keys(nodesData).forEach(node => { + if (nodesData[node]["status"] !== "OFFLINE") { + sendTelemetry(nodesData[node].readout, nodesData[node].tbname); + nodesData[node].readout = {}; + } + }) + } + + + /** + * 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; + } + + 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); + + //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 === "OFFLINE") { + nodeObj.node_status_before_offline === true ? number_of_ok_luminaires++ : number_of_nok_luminaires++; + } + else if (nodeObj.status == true) 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 - ts % 60000 //round to full minute + }; + + sendTelemetry(values, SETTINGS.rvoTbName, ts); + } + + + function setSunCalcResult() { + //if next day, we get new dusk and dawn. To make sure, in local timezone 2:00 means 00:00 in utc (it means next day) + if (new Date().getHours() === 2) { + sunCalcResult = calculateDuskDawn(); + console.log("Novy suncalc: ", sunCalcResult); + } + } + + + function setRvoPeriod() { + + if (!SETTINGS.daily_report) return; + + const ts = Date.now(); + + previous_rvo_is_on_value = rvo_is_on; + + if (ts < sunCalcResult.dawn_time - 1_800_000) { // nodes should be on (00:00 -> 06:00 ( - pol hodina, lebo rvo vypina skor) + rvo_is_on = true; + } else if (sunCalcResult.dawn_time - 1_800_000 < ts && ts < sunCalcResult.dusk_time + 1_800_000) { // nodes should be off 06:00 -> 21:00 + rvo_is_on = false; + } else if (sunCalcResult.dusk_time + 1_800_000 < ts) { // nodes should be on 21:00 -> 00:00 + rvo_is_on = true; + } + + if (previous_rvo_is_on_value !== rvo_is_on) { + emptyDailyReport(); + console.log("rvo_is: ", rvo_is_on, previous_rvo_is_on_value); + } + } + + + function handleRsPort() { + + if (rsPort) { + rsPort.removeAllListeners(); + rsPort = null; + } + + //! 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-mngr: rsPort opened success"); + + 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); + + }).catch(function(reason) { + instance.send(SEND_TO.debug, "Cmd-mngr: RPC runSyncExec - promise rejected:" + reason); + }); + }); + + rsPort.on('error', function(err) { + errorHandler.sendMessageToService([exports.title, "unable to open port", SETTINGS.serial_port, err.message], 0); + monitor.info("Cmd-mngr: Error on rsPort", err.message); + }); + + rsPort.on("close", () => { + monitor.info("Cmd-mngr: rsPort closed, reconnecting..."); + setTimeout(handleRsPort, 1000); + }); + + rsPort.open(); + } + + + instance.on("close", () => { + clearInterval(interval); + clearInterval(customTasksInterval); + clearInterval(setCorrectTime); + clearInterval(sendNodeReadout); + clearInterval(accelerometerInterval); + rsPort.close(); + }); + + instance.on("0", _ => { + main(); + }) + + + instance.on("2", _ => { + console.log("dailyReport, reportToSend, rvo_is_on", dailyReport, reportToSend, rvo_is_on, previous_rvo_is_on_value); + }) + + instance.on("1", 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(); + return; + } + else if (flowdata.data == "close") { + rsPort.close(); + return; + } + else if (flowdata.data == "clean") { + tasks = []; + return; + } + else if (flowdata.data == "buildtasks") { + //build & run + return; + } + else if (flowdata.data == "run") { + //durations = []; + + if (tasks.length == 0) { + + buildTasks(); + + if (rsPort.isOpen) { + interval = setInterval(runTasks, 100); + } + else { + instance.send(SEND_TO.debug, "port is not opened!!!"); + } + } + } + else { + //terminal data - object + //logger.debug("flowdata", flowdata.data); + + if (typeof flowdata.data === 'object') { + //logger.debug("dido", flowdata.data); + if (flowdata.data.hasOwnProperty("sender")) { + //data from dido_controller + if (flowdata.data.sender == "dido_controller") { + + if (flowdata.data.hasOwnProperty("cmd")) { + let cmd = flowdata.data.cmd; + + if (cmd == "buildTasks") { + clearInterval(interval); + + logger.debug("-->Cmd-mngr: BUILD TASKS"); + buildTasks(); + + //logger.debug("tasks:"); + //logger.debug(tasks); + + logger.debug("-->Cmd-mngr: RUN TASKS"); + interval = setInterval(runTasks, 5000); + } + else if (cmd == "reload_relays") { + loadRelaysData(flowdata.data.line); + + if (flowdata.data.dataChanged) { + if (!flowdata.data.value) { + reportOfflineNodeStatus(flowdata.data.line); + } + else { + reportOnlineNodeStatus(flowdata.data.line); + } + } + + } + else if (cmd == "rotary_switch_state") { + let value = flowdata.data.value; + + //state was changed + if (rotary_switch_state != value) { + if (value == "Off") { + //vyreportovat vsetky svietdla + reportOfflineNodeStatus(); + } + + rotary_switch_state = value; + } + } + 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) { + + // we send lux_sensor value to all nodes: + let params = getParams(PRIORITY_TYPES.node_broadcast); + + params.recipient = 2;//2 broadcast, address = 0 + params.address = 0xffffffff;//Broadcast + + let ba = longToByteArray(lux_sensor); + + params.byte3 = ba[1];//msb + params.byte4 = ba[0]; + params.timestamp = PRIORITY_TYPES.node_broadcast; + params.info = "run broadcast: Actual Lux level from cabinet"; + params.register = 95;//Actual Lux level from cabinet + params.rw = 1;//write + + tasks.push(params); + + //process profiles + turnOnOffLinesAccordingToLuxSensor(lux_sensor); + } + } + else if (cmd == "state_of_breaker") { + //istic linie + + breakerCounter--; + + let value = flowdata.data.value; + let line = parseInt(flowdata.data.line); + + let dataChanged = false; + if (state_of_breaker[line] != value) dataChanged = true; + + state_of_breaker[line] = value; + + let status = "OK"; + if (value == "Off") status = "NOK"; + + if (dataChanged) { + + if (relaysData.hasOwnProperty(line)) { + let tbname = relaysData[line].tbname; + + if (value == "Off") { + sendNotification("Cmd-mngr: onData", tbname, "circuit_breaker_was_turned_off_line", { line: line }, "", SEND_TO.tb, instance, "circuit_breaker"); + if (breakerCounter < 0) reportToSend["contactor"]["off"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + else { + sendNotification("Cmd-mngr: onData", tbname, "circuit_breaker_was_turned_on_line", { line: line }, "", SEND_TO.tb, instance, "circuit_breaker"); + if (breakerCounter < 0) reportToSend["contactor"]["on"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + + //report status liniu + sendTelemetry({ status: status }, tbname) + + //current value + if (value == "Off") reportOfflineNodeStatus(line); //vyreportovat vsetky svietidla na linii + } + + } + } + else { + logger.debug("undefined cmd", cmd); + } + } + } + + return; + } + + //data from worksys + if (flowdata.data.hasOwnProperty("topic")) { + + let data = getNested(flowdata.data, "content", "data"); + + //if we get temperature in senica from senica-prod01 + let temperature = getNested(flowdata.data, "content", "senica_temperature"); + + if (temperature !== undefined) { + temperatureInSenica = temperature; + return; + } + + if (data === undefined) { + console.log("Invalid rpc command came from platform"); + return; + } + + let command = data.params.command; + let method = data.method; + let profile = data.params.payload; + if (profile == undefined) profile = ""; + let entity = data.params.entities[0]; + let entity_type = entity.entity_type; + let tbname = entity.tb_name; + + instance.send(SEND_TO.debug, flowdata.data); + 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") { + + //let command = data.params.command; + let value = data.params.payload.value; + + if (command == "dimming") { + + let nodeWasFound = false; + let keys = Object.keys(nodesData); + + //logger.debug("-----", keys); + + 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); + + value = parseInt(value); + if (value > 0) value = value + 128; + + params.type = "node-onetime-write"; + params.tbname = tbname; + params.address = node; + params.register = 1; + params.recipient = 1; + params.byte4 = value; + params.rw = 1; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'set dimming from platform'; + //params.debug = true; + + //debug(params); + logger.debug("dimming", params); + + tasks.push(params); + + 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); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 1; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read dimming (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + //pridame aj vyreportovanie - vykon + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 76; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read Input Power (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + //pridame aj vyreportovanie - prud svietidla + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 75; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read Input Current (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + //pridame aj vyreportovanie - power faktor - ucinnik + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 77; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read power factor (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + }, 4000); + + nodeWasFound = true; + break; + } + } + + if (!nodeWasFound) { + logger.debug("set dimming from platform", "unable to find tbname", tbname); + } + } + else { + instance.send(SEND_TO.debug, "undefined command " + command); + logger.debug("undefined command", command); + } + + return; + } + 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++) { + let node = keys[i]; + if (tbname == nodesData[node].tbname) { + + 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"); + + //profil úspešne prijatý pre node č. xx + sendNotification("Cmd-mngr", tbname, "dimming_profile_was_processed_for_node", { node: node }, profile, SEND_TO.tb, instance); + + nodesData[node].processed = false; + nodesData[node].profile = profile; + + processNodeProfile(node); + }); + }); + } + } + } + else { + + instance.send(SEND_TO.debug, "unknown method " + method); + logger.debug("unknown method", method); + + return; + } + } + + //nastav profil linie z platformy + 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") { + + 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++) { + let line = keys[i]; + if (tbname == relaysData[line].tbname) { + //zmazeme tasky + 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) { + + //update profile + logger.debug("worksys - update relay profile done:", profile); + instance.send(SEND_TO.debug, "worksys - update relay profile done"); + + relaysData[line].profile = profile; + + loadRelaysData(line) + logger.debug("loadRelaysData DONE for line", line); + + buildTasks({ processLineProfiles: true, line: line }); + + sendNotification("Cmd-mngr: set profile from worksys", tbname, "switching_profile_was_processed_for_line", { line: line }, profile, SEND_TO.tb, instance); + }); + }); + break; + } + } + } + else if (method == "set_command") { + let value = data.params.payload.value; + + 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; + + 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"); + if (line != 0) reportToSend["contactor"]["off"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + else { + turnLine("on", line, "command received from platform"); + if (line != 0) reportToSend["contactor"]["on"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + } + } + else { + instance.send(SEND_TO.debug, "undefined method " + method); + logger.debug("undefined method", method); + } + + return; + } + else { + instance.send(SEND_TO.debug, "UNKNOW entity_type " + entity_type); + logger.debug("UNKNOW entity_type", entity_type); + } + return; + } + + //terminal + if (!rsPort.isOpen) await rsPort.open(); + + let params = flowdata.data.body; + if (params == undefined) { + //logger.debug("Cmd-mngr: flowdata.data.body is undefined"); + return; + } + + params.priority = PRIORITY_TYPES.terminal; + params.type = "cmd-terminal"; + params.tbname = ""; + params.timestamp = PRIORITY_TYPES.terminal; + params.addMinutesToTimestamp = 0;// do not repeat task!!! + params.debug = true; + + let timestamp = Date.now(); + params.refFlowdataKey = timestamp; + //params.refFlowdata = flowdata; + //refFlowdata = flowdata; + + //console.log("flowdata", flowdata); + + cleanUpRefFlowdataObj(); + + refFlowdataObj[timestamp] = flowdata; + + //fix + //params.address = params.adress; + logger.debug("received from terminal", params); + logger.debug("date/time:", new Date()); + logger.debug("tasks length:", tasks.length); + + //tasks = []; + + //add to tasks + tasks.push(params); + + } + } + }) + + + //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) + } + + + /** + * 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; + + RESTBuilder.make(function(builder) { + + if (!builder) return; + + builder.method('GET'); + builder.url('http://192.168.252.2:8004/gettime?projects_id=1'); + + builder.callback(function(err, response, output) { + + 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); + } + + }); + } + + } 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); + + } else { + //console.log("Read-only", stdout); + + 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]: [ + { + "ts": date, + "values": values + } + ] + } + + tbHandler.sendToTb(dataToTb, instance); + } + + + function calculateDuskDawn(date, line, duskOffset = 0, dawnOffset = 0) { + + if (date === undefined) date = new Date(); + + 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); + } + + //if(profile.dawn_lux_sensor == false) + { + if (profile.hasOwnProperty("dawn_astro_clock_offset")) dawn_astro_clock_offset = parseInt(profile.dawn_astro_clock_offset); + } + + } + + } catch (error) { + if (profilestr != "") { + logger.debug(profilestr); + logger.debug(error); + } + } + + 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; + } + + //Dimming, CCT + else if (register == 1) { + let brightness = 0; + let dimming = byte0; + if (dimming > 128) { + //dimming = -128; + brightness = dimming - 128; + } + + //cct + //Ak Byte3 == 1: CCT = (Byte2*256)+Byte1 + let cct; + if (byte3 == 1) cct = byte2 * 256 + byte1; + else cct = bytesToInt(bytes.slice(0, 3)); + + //cct podla auditu + + values["dimming"] = brightness; + return values; + } + + // + else if (register == 4) { + values["master_node_version"] = bytes[1] + "." + bytes[2]; + //logger.debug("FW Version", register, bytes); + } + + //Napätie + else if (register == 74) { + let voltage = (bytesToInt(bytes) * 0.1).toFixed(1); + values["voltage"] = Number(voltage); + } + + //Prúd + else if (register == 75) { + let current = bytesToInt(bytes); + values["current"] = current; + } + + //výkon + else if (register == 76) { + let power = (bytesToInt(bytes) * 0.1).toFixed(2); + values["power"] = Number(power); + } + + //účinník + else if (register == 77) { + let power_factor = Math.cos(bytesToInt(bytes) * 0.1 * (Math.PI / 180)).toFixed(2); + values["power_factor"] = Number(power_factor); + } + + //frekvencia + else if (register == 78) { + let frequency = (bytesToInt(bytes) * 0.1).toFixed(2); + values["frequency"] = Number(frequency); + } + + //energia + else if (register == 79) { + let energy = bytesToInt(bytes); + values["energy"] = energy / 1000; //energia v kWh -> delit 1000 + } + + //doba života + else if (register == 80) { + let lifetime = (bytesToInt(bytes) / 60).toFixed(2); + values["lifetime"] = Number(lifetime); + } + + //nastavenie profilu + else if (register == 8) { + let time_schedule_settings = bytesToInt(bytes); + values["time_schedule_settings"] = time_schedule_settings; + } + + //naklon - nateraz sa z nodu nevycitava! kvoli problemom s accelerometrom a vracanymi hodnotami, posielame temp a x y z vo funkcii accelerometerData() + else if (register == 84) { + values["temperature"] = byte3 >= 128 ? (byte3 - 128) * (-1) : byte3; + values["inclination_x"] = byte2 >= 128 ? (byte2 - 128) * (-1) : byte2; + values["inclination_y"] = byte1 >= 128 ? (byte1 - 128) * (-1) : byte1; + values["inclination_z"] = byte0 >= 128 ? (byte0 - 128) * (-1) : byte0; + } + + //FW verzia nodu + else if (register == 89) { + //formát: "Byte3: Byte2.Byte1 (Byte0)" + values["fw_version"] = byte3 + ":" + byte2 + "." + byte1 + "(" + byte0 + ")"; + } + + else if (register == 87 || register == 6 || register == 7) { + var d = new Date(); + d.setHours(byte3, byte2, 0, 0); + let timestamp = d.getTime(); + + //aktuálny čas + if (register == 87) values["actual_time"] = timestamp; + //čas súmraku + else if (register == 6) values["dusk_time"] = timestamp; + //čas úsvitu + else if (register == 7) values["dawn_time"] = timestamp; + } + + 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; + + } + + + function getObjectByTbValue(object, tbname) { + return object[Object.keys(object).find(key => object[key].tbname === tbname)]; + } + + + function isObject(item) { + return (typeof item === "object" && !Array.isArray(item) && item !== null); + } + + + // we fake data, that should be received from accelerometer, as they are a bit unreliable. (temperature, x,y,z) + function accelerometerData() { + + if (temperatureInSenica === null) return; + + //clone nodesData and relaysData objects + let nodesData_clone = JSON.parse(JSON.stringify(nodesData)); + let relaysData_clone = JSON.parse(JSON.stringify(relaysData)); + + for (const key in relaysData_clone) { + + const lineData = relaysData_clone[key]; + const lineNumber = lineData.line; + const contactor = lineData.contactor; + + if (lineNumber === 0) continue; + + if (contactor === 1) { + + let date = Date.now(); + + Object.keys(nodesData_clone).forEach((node, index) => { + + setTimeout(function() { + + if (nodesData_clone[node].line === lineNumber) { + + // NOTE: if status of luminaire is NOK or OFFLINE, we do not send data; + let status = nodesData_clone[node].status; + if (status === "OFFLINE" || !status) return; + + let x = null; + if (naklony.hasOwnProperty(node)) x = naklony[node].naklon; + if (x === null) x = 0; + + sendTelemetry({ temperature: Math.round(temperatureInSenica + 10 + Math.floor(Math.random() * 3)), inclination_x: x, inclination_y: 0, inclination_z: 0 }, nodesData_clone[node].tbname, date); + } + + }, (index + 1) * 500); + }) + + } + } + } + + +} // end of instance.export + diff --git a/RVO47/flow/code.js b/RVO47/flow/code.js new file mode 100755 index 0000000..63b31bf --- /dev/null +++ b/RVO47/flow/code.js @@ -0,0 +1,90 @@ +exports.id = 'code'; +exports.title = 'Code'; +exports.group = 'Common'; +exports.color = '#656D78'; +exports.input = true; +exports.output = 1; +exports.author = 'Peter Širka'; +exports.icon = 'code'; +exports.version = '1.2.0'; +exports.options = { outputs: 1, code: 'send(0, value);', keepmessage: true }; + +exports.html = `
+
+
+
@(Number of outputs)
+
@(Minimum is 1)
+
+
+
@(Code)
+
@(Keep message instance)
+
+`; + +exports.readme = `# Code + +This component executes custom JavaScript code as it is and it doesn't contain any secure scope. + +\`\`\`javascript +// value {Object} contains received data +// send(outputIndex, newValue) sends a new value +// error(value) sends an error +// instance {Object} a current component instance +// flowdata {Object} a current flowdata +// repository {Object} a current repository of flowdata +// Example: + +// send() can be execute multiple times +send(0, value); +\`\`\``; + +exports.install = function(instance) { + + var fn; + + instance.on('data', function(response) { + if (fn) { + try { + fn(response.data, instance, response, instance.options, response.repository, require); + } catch (e) { + response.data = e; + instance.throw(response); + } + } + }); + + instance.reconfigure = function() { + try { + if (instance.options.code) { + instance.status(''); + var code = 'var send = function(index, value) { if (options.keepmessage) { flowdata.data = value; instance.send2(index, flowdata); } else instance.send2(index, value);}; var error = function(err) { instance.throw(err); }; ' + instance.options.code; + fn = new Function('value', 'instance', 'flowdata', 'options', 'repository', 'require', code); + } else { + instance.status('Not configured', 'red'); + fn = null; + } + } catch (e) { + fn = null; + instance.error('Code: ' + e.message); + } + }; + + instance.on('options', instance.reconfigure); + instance.reconfigure(); +}; \ No newline at end of file diff --git a/RVO47/flow/comment.js b/RVO47/flow/comment.js new file mode 100755 index 0000000..1e0cd13 --- /dev/null +++ b/RVO47/flow/comment.js @@ -0,0 +1,11 @@ +exports.id = 'comment'; +exports.title = 'Comment'; +exports.group = 'Common'; +exports.color = '#704cff'; +exports.author = 'Martin Smola'; +exports.icon = 'comment'; +exports.traffic = false; +exports.version = '1.0.0'; +exports.readme = '# Comment'; + +exports.install = function() {}; diff --git a/RVO47/flow/count.js b/RVO47/flow/count.js new file mode 100755 index 0000000..fa92ee9 --- /dev/null +++ b/RVO47/flow/count.js @@ -0,0 +1,60 @@ +exports.id = 'count'; +exports.title = 'Count'; +exports.version = '1.0.1'; +exports.author = 'John Graves'; +exports.color = '#656D78'; +exports.icon = 'plus-square'; +exports.input = 2; +exports.output = 1; +exports.options = { increment: 1, initialvalue: 1 }; +exports.readme = `# Counter + +Counter Number of times called.`; + +exports.html = `
+
@(Initial Value)
+
@(Increment)
+

Example Video

+
`; + +exports.readme = `# Count + +This component counts the number of messages received. + +__Response:__ + +Integer value based on the initial value and increment settings. + +__Arguments:__ +- Initial Value: What number should be output on the receipt of the first message. +- Increment: What should the increment be for each following message received.`; + +exports.install = function(instance) { + + var count = 0; + var initialCall = true; + + instance.on('data', function(flowdata) { + var index = flowdata.index; + if (index) { + instance.debug('Reset Count.'); + count = instance.options.initialvalue; + initialCall = true; + } else { + // If this is the first time, set the value to 'initial value' + if(initialCall) { + initialCall = false; + count = instance.options.initialvalue; + } else + count = count+instance.options.increment; + instance.status('Count:' + count); + instance.send2(count); + } + }); + + instance.on('options', function() { + count = instance.options.initialvalue; + initialCall = true; + }); + +}; diff --git a/RVO47/flow/db_connector.js b/RVO47/flow/db_connector.js new file mode 100755 index 0000000..65ee94b --- /dev/null +++ b/RVO47/flow/db_connector.js @@ -0,0 +1,286 @@ +exports.id = 'db_connector'; +exports.title = 'DbConnector'; +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.html = `
+
+
+
DbConnector
+
+
+
`; + +exports.readme = `# read/write data to tables`; + +const instanceSendTo = { + debug: 0, + http_response: 1, +} + +const { promisifyBuilder, makeMapFromDbResult } = require('./helper/db_helper.js'); + +function extractWhereParams(params) +{ + let name = params[0]; + let operator = '='; + let value = params[1]; + + if(params.length == 3) + { + operator = params[1]; + value = params[2]; + } + + return {name: name, operator: operator, value: value}; +} + +exports.install = function(instance) { + + let refFlowdata = null;//holds reference to httprequest flowdata + + instance.on("close", () => { + + }) + + + instance.on("data", async function(flowdata) { + + let params = flowdata.data.body; + console.log("DbConnector", params); + + refFlowdata = flowdata; + + if(refFlowdata != undefined) + { + //make http response + let responseObj = {}; + responseObj["type"] = "SUCESS"; + + try{ + + let table = params.table; + let action = params.action; + + + if(params.data != undefined) + { + let className = params.data.className; + + if(className == "SqlQueryBuilder") + { + let type = params.data.type; + + console.log("SqlQueryBuilder---->", params.data); + + if(type == "SELECT") + { + let table = params.data.queryData.tables[0].table; + + const db = TABLE(table); + var builder = db.find(); + + let result = await promisifyBuilder(builder); + + let response = {}; + response["result"] = result; + response["success"] = true; + + responseObj["data"] = response; + + //console.log(responseObj); + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + } + + return; + } + } + + + console.log("db_connector---->", table, action); + + //actions: read, replace, insert, delete, update... + + if(action == "read") + { + const db = TABLE(params.table); + + //where builder.where('age', '<', 15); + //builder.where('id', 3403); + + var builder = db.find(); + + //https://docs.totaljs.com/latest/en.html#api~DatabaseBuilder~builder.where + if(params.hasOwnProperty("where")) + { + //optionalCan contain "=", "<=", "<", ">=", ">". + //Default value: '=' + + //1.["production_line", 1] + //2. ["or", ["production_line", 1], ["production_line", 2], "end"] + + if (Array.isArray(params.where)) { + + let multipleConditions = false; + + if(params.where[0] == "or") multipleConditions = true; + if (Array.isArray(params.where[0])) multipleConditions = true; + + if(multipleConditions) + { + + for(var i = 0; i < params.where.length; i++) + { + const item = params.where[i]; + + if(item === "or") builder.or(); + + if (Array.isArray(item)) + { + const { name, operator, value } = extractWhereParams(item); + builder.where(name, operator, value); + } + + if(item === "end") builder.end(); + + } + + } + else + { + const { name, operator, value } = extractWhereParams(params.where); + builder.where(name, operator, value); + } + + } + + /* + if(params.where.length >=2 ) + { + let name = params.where[0]; + let operator = '='; + let value = params.where[1]; + + if(params.where.length == 3) + { + operator = params.where[1]; + value = params.where[2]; + } + + builder.where(name, operator, value); + } + */ + } + + if(params.hasOwnProperty("between")) + { + builder.between(params.between[0], params.between[1], params.between[2]); + } + + let response = await promisifyBuilder(builder); + responseObj["data"] = response; + + //console.log(responseObj); + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + + return; + } + + if(action == "delete") + { + + } + + + if(action == "update") + { + //! data receiving from terminal (params) + // { + // hostname: 'localhost', + // table: 'settings', + // action: 'update', + // body: { + // rvo_name: 'terrrr', + // lang: 'en', + // temperature_adress: '28.427B45920702', + // latitude: 48.70826502, + // longitude: 17.28455203, + // mqtt_host: '192.168.252.4', + // mqtt_clientid: 'showroom_test_panel_led', + // mqtt_username: 'xmRd6RJxW53WZe4vMFLU', + // mqtt_port: 1883, + // maintanace_mode: false + // } + // } + const tableToModify = TABLE(params.table); + const newValues = params.body; + + tableToModify.modify(newValues).make(function(builder) { + + builder.callback(function(err, response) { + + if(!err) + { + responseObj["data"] = response; + responseObj["tableUpdated"] = true; + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + } + }); + }); + + } + + if(action == "replace") + { + //truncate table + const db = TABLE(params.table); + var builder = db.remove(); + db.clean(); + + //insert data + let data = params.data; + + for(let i = 0; i < data.length; i++) + { + //console.log(data[i]); + db.insert(data[i]); + } + + console.log("insert done"); + + let responseObj = {}; + responseObj["type"] = "SUCESS"; + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + + + } + + + + } catch (error) { + //console.log(error); + responseObj["type"] = "ERROR"; + responseObj["message"] = error; + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + } + } + }) +} + + diff --git a/RVO47/flow/db_init.js b/RVO47/flow/db_init.js new file mode 100755 index 0000000..b399878 --- /dev/null +++ b/RVO47/flow/db_init.js @@ -0,0 +1,113 @@ +exports.id = 'db_init'; +exports.title = 'DB Initialization'; +exports.group = 'Worksys'; +exports.color = '#888600'; +exports.version = '1.0.2'; +exports.icon = 'sign-out'; +exports.output = 2; + +exports.readme = ` + # DB initialization +`; + +const { promisifyBuilder, makeMapFromDbResult } = require('./helper/db_helper.js'); +const { initNotification } = require('./helper/notification_reporter'); +const errorHandler = require('./helper/ErrorToServiceHandler'); +const total_energy = require('../databases/total_energy'); + +const SEND_TO = { + db_init: 0, + infoSender: 1 +}; + + +exports.install = async function(instance) { + const dbNodes = TABLE("nodes"); + const dbRelays = TABLE("relays"); + const dbSettings = TABLE("settings"); + 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 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.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"]; + Object.keys(dbs.nodesData).forEach(node => dbs.nodesData[node].readout = {}) + + let rvo_number = responseSettings[0]["rvo_name"].match(/\D+(\d{1,2})_/)[1]; + + dbs.settings = { + edge_fw_version: "2025-10-08", //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"], + phases: responseSettings[0]["phases"], + cloud_topic: responseSettings[0]["cloud_topic"], + has_main_switch: responseSettings[0]["has_main_switch"], + daily_report: responseSettings[0]["daily_report"], + send_changed_node_numbers: responseSettings[0]["send_changed_node_numbers"], + rvo_number: rvo_number, + + //dynamic values + masterNodeIsResponding: true, //cmd_manager + maintenance_mode: false, + } + + + dbs.settings.energy_to_switch_lamps = total_energy[rvo_number]; + if (dbs.settings.energy_to_switch_lamps === undefined) console.log('=============== db_init.js: energy_to_switch_lamps is undefined'); + + FLOW.dbLoaded = true; + errorHandler.setProjectId(dbs.settings.project_id); + initNotification(); + + //APP START - send to data services + const toService = { + id: dbs.settings.project_id, + name: dbs.settings.rvo_name, + fw_version: dbs.settings.edge_fw_version, + startdate: new Date().toISOString().slice(0, 19).replace('T', ' '), + js_error: "", + error_message: "" + }; + + instance.send(SEND_TO.infoSender, toService); + console.log("----------------> START - message send to service", toService); + + setTimeout(() => { + console.log("DB_INIT - data loaded"); + instance.send(SEND_TO.db_init, "_") + }, 5000) + +}; + diff --git a/RVO47/flow/debug.js b/RVO47/flow/debug.js new file mode 100755 index 0000000..00cb259 --- /dev/null +++ b/RVO47/flow/debug.js @@ -0,0 +1,100 @@ +exports.id = 'debug'; +exports.title = 'Debug'; +exports.author = 'Peter Širka'; +exports.color = '#967ADC'; +exports.click = true; +exports.input = true; +exports.icon = 'bug'; +exports.version = '2.0.4'; +exports.options = { enabled: true, repository: false, type: 'data' }; +exports.readme = `# Debug + +Prints data to the debug tab.`; + +exports.html = `
+
+
+
@(Output type)
+
@(Path to the property (leave empty to show the whole data object))
+
@(A group name)
+
@(Enabled)
+
+
+
`; + +exports.install = function(instance) { + + instance.on('data', function(response) { + if (instance.options.enabled) { + + var opt = instance.options; + var rep = response.repository; + var val = response.data; + var id = response.id; + + switch (instance.options.type){ + case 'both': + var data = {}; + data.repository = rep; + data.data = val instanceof Error ? { error: val.message, stack: val.stack } : val; + instance.debug(safeparse(opt.property ? U.get(data, opt.property) : data), undefined, opt.group, id); + break; + case 'repository': + instance.debug(safeparse(opt.property ? U.get(rep, opt.property) : rep), undefined, opt.group, id); + break; + case 'data': + default: + if (val instanceof Error) + instance.debug({ error: val.message, stack: val.stack }, undefined, opt.group, id); + else + instance.debug(safeparse(opt.property ? U.get(val, opt.property) : val), undefined, opt.group, id); + break; + } + } + }); + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + instance.save(); + }); + + instance.on('options', function() { + instance.custom.status(); + }); + + instance.custom.status = function() { + instance.status(instance.options.enabled ? 'Enabled' : 'Disabled'); + }; + + instance.custom.status(); + + function safeparse(o) { + + if (o instanceof Buffer) + return o; + + if (o === undefined) + return 'undefined'; + + if (o === null) + return 'null'; + + var cache = []; + var str = JSON.stringify(o, function(key, value) { + if (typeof value === 'object' && value !== null) { + if (cache.indexOf(value) !== -1) { + try { + return JSON.parse(JSON.stringify(value)); + } catch (error) { + return; + } + } + cache.push(value); + } + return value; + }); + cache = null; + return JSON.parse(str); + } +}; diff --git a/RVO47/flow/designer.json b/RVO47/flow/designer.json new file mode 100755 index 0000000..580f5a3 --- /dev/null +++ b/RVO47/flow/designer.json @@ -0,0 +1,3102 @@ +{ + "tabs": [ + { + "name": "MAIN PUSH", + "linker": "main-push", + "id": "1612772287426", + "index": 0 + }, + { + "name": "CMD manager", + "linker": "cmd-manager", + "id": "1615551125555", + "index": 1 + }, + { + "name": "Devices", + "linker": "devices", + "id": "1611921777196", + "index": 2 + } + ], + "components": [ + { + "id": "1611951142547", + "component": "debug", + "tab": "1611921777196", + "name": "ERROR", + "x": 598, + "y": 60, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#DA4453", + "notes": "" + }, + { + "id": "1612776786008", + "component": "wsmqttpublish", + "tab": "1612772287426", + "name": "WS MQTT publish", + "x": 281.75, + "y": 174, + "connections": { + "0": [ + { + "index": "0", + "id": "1615551060773" + } + ], + "1": [ + { + "index": "0", + "id": "1618300858252" + }, + { + "index": "0", + "id": "1618558465485" + } + ], + "2": [ + { + "index": "0", + "id": "1634303685503" + } + ], + "3": [ + { + "index": "0", + "id": "1731068754606" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Connected", + "color": "green" + }, + "options": { + "username": "", + "clientid": "", + "port": "1883", + "host": "" + }, + "color": "#888600", + "notes": "" + }, + { + "id": "1612778461252", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "tb-push", + "x": 72.75, + "y": 328, + "connections": { + "0": [ + { + "index": "0", + "id": "1612783322136" + }, + { + "index": "1", + "id": "1612776786008" + }, + { + "index": "0", + "id": "1731068754606" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1612783322136", + "component": "debug", + "tab": "1612772287426", + "name": "to TB", + "x": 283.75, + "y": 324, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615551060773", + "component": "debug", + "tab": "1612772287426", + "name": "errors from MQTT Broker", + "x": 594, + "y": 57, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#DA4453", + "notes": "" + }, + { + "id": "1615563373927", + "component": "debug", + "tab": "1615551125555", + "name": "Debug", + "x": 755, + "y": 155, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#DA4453", + "notes": "" + }, + { + "id": "1615566865233", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "tb-push", + "x": 755, + "y": 248, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1615798582262", + "component": "debug", + "tab": "1615551125555", + "name": "CMD_debug", + "x": 755, + "y": 346, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615802995322", + "component": "debug", + "tab": "1611921777196", + "name": "Debug", + "x": 596.8833312988281, + "y": 566.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Disabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": false + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615809128443", + "component": "debug", + "tab": "1611921777196", + "name": "tempToTb", + "x": 595.8833312988281, + "y": 658.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615809595184", + "component": "virtualwireout", + "tab": "1611921777196", + "name": "tb-push", + "x": 597.8833312988281, + "y": 377.25, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1616165795916", + "component": "httproute", + "tab": "1615551125555", + "name": "POST /terminal", + "x": 135, + "y": 547, + "connections": { + "0": [ + { + "index": "0", + "id": "1684060205000" + }, + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Listening", + "color": "green" + }, + "options": { + "timeout": 10, + "cachepolicy": 0, + "cacheexpire": "5 minutes", + "size": 5, + "url": "/terminal", + "method": "POST", + "name": "", + "flags": [ + "id:1616165795916", + "post", + 10000 + ], + "emptyresponse": false + }, + "color": "#5D9CEC", + "notes": "### Configuration\n\n- __POST /terminal__\n- flags: \n- maximum request data length: __5 kB__\n- empty response: __false__\n- cache policy: __no cache__\n- cache expire: __5 minutes__", + "cloning": false + }, + { + "id": "1616165824813", + "component": "httpresponse", + "tab": "1615551125555", + "name": "HTTP Response", + "x": 753, + "y": 423, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "json" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1617104731852", + "component": "debug", + "tab": "1615551125555", + "name": "DIDO_Debug", + "x": 669, + "y": 1040, + "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": "turnOff line", + "x": 133, + "y": 1161, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "object", + "data": "{line: 3, command: \"turnOff\", force: true}" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1617115013095", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "tb-push", + "x": 669, + "y": 1150, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1617284749681", + "component": "trigger", + "tab": "1615551125555", + "name": "update profile / node", + "x": 112, + "y": 208, + "connections": { + "0": [ + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "data": "profile_nodes", + "datatype": "string" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1618235171399", + "component": "trigger", + "tab": "1615551125555", + "name": "tun tasks", + "x": 184, + "y": 279, + "connections": { + "0": [ + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "data": "run" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1618300858252", + "component": "debug", + "tab": "1612772287426", + "name": "wsmqtt-exit1", + "x": 597.8833312988281, + "y": 149, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1618393583970", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "to-cmd-manager", + "x": 668.8833312988281, + "y": 1269, + "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": 132.88333129882812, + "y": 367, + "connections": { + "0": [ + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "platform-rpc-call", + "color": "gray" + }, + "options": { + "wirename": "platform-rpc-call" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1618393759854", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "cmd_to_dido", + "x": 119.88333129882812, + "y": 1007, + "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": 752.8833312988281, + "y": 527, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "cmd_to_dido", + "color": "gray" + }, + "options": { + "wirename": "cmd_to_dido" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1618558465485", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "platform-rpc-call", + "x": 597.8833312988281, + "y": 247, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "platform-rpc-call", + "color": "gray" + }, + "options": { + "wirename": "platform-rpc-call" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1618572059773", + "component": "trigger", + "tab": "1615551125555", + "name": "turnOn line", + "x": 132, + "y": 1085, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "data": "{line: 1, command: \"turnOn\", force: true}", + "datatype": "object" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1619515097737", + "component": "cmd_manager", + "tab": "1615551125555", + "name": "CMD Manager", + "x": 452.1091003417969, + "y": 341.05455017089844, + "connections": { + "0": [ + { + "index": "0", + "id": "1615563373927" + } + ], + "1": [ + { + "index": "0", + "id": "1615566865233" + }, + { + "index": "0", + "id": "1615798582262" + } + ], + "2": [ + { + "index": "0", + "id": "1616165824813" + } + ], + "3": [ + { + "index": "0", + "id": "1618393827655" + } + ], + "4": [ + { + "index": "0", + "id": "1635936391935" + } + ], + "5": [ + { + "index": "0", + "id": "1757006030239" + }, + { + "index": "0", + "id": "1757006060377" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1619605019281", + "component": "httproute", + "tab": "1615551125555", + "name": "GET db", + "x": 173, + "y": 653, + "connections": { + "0": [ + { + "index": "0", + "id": "1684060205000" + }, + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Listening", + "color": "green" + }, + "options": { + "timeout": 5, + "cachepolicy": 0, + "cacheexpire": "5 minutes", + "size": 5, + "url": "/db", + "method": "GET", + "name": "", + "flags": [ + "id:1619605019281", + "get", + 5000 + ] + }, + "color": "#5D9CEC", + "notes": "### Configuration\n\n- __GET /db__\n- flags: undefined\n- maximum request data length: __5 kB__\n- empty response: __undefined__\n- cache policy: __no cache__\n- cache expire: __5 minutes__", + "cloning": false + }, + { + "id": "1619784672383", + "component": "trigger", + "tab": "1615551125555", + "name": "turnOnAlarm", + "x": 120, + "y": 1234, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "object", + "data": "{command: \"turnOnAlarm\"}" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1619784812964", + "component": "trigger", + "tab": "1615551125555", + "name": "turnOffAlarm", + "x": 118, + "y": 1307, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "object", + "data": "{command: \"turnOffAlarm\"}" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1621340721628", + "component": "virtualwireout", + "tab": "1611921777196", + "name": "modbus_to_dido", + "x": 599, + "y": 471, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "modbus_to_dido", + "color": "gray" + }, + "options": { + "wirename": "modbus_to_dido" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1622640022885", + "component": "httproute", + "tab": "1615551125555", + "name": "POST /db_connector", + "x": 98, + "y": 1586, + "connections": { + "0": [ + { + "index": "0", + "id": "1622640073521" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Listening", + "color": "green" + }, + "options": { + "timeout": 5, + "cachepolicy": 0, + "cacheexpire": "5 minutes", + "size": 5, + "url": "/db_connector", + "method": "POST", + "flags": [ + "id:1622640022885", + "post", + 5000 + ] + }, + "color": "#5D9CEC", + "notes": "### Configuration\n\n- __POST /db_connector__\n- flags: \n- maximum request data length: __5 kB__\n- empty response: __undefined__\n- cache policy: __no cache__\n- cache expire: __5 minutes__", + "cloning": false + }, + { + "id": "1622640073521", + "component": "db_connector", + "tab": "1615551125555", + "name": "DbConnector", + "x": 372, + "y": 1572, + "connections": { + "1": [ + { + "index": "0", + "id": "1622641420685" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "edge": "undefined" + }, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1622641420685", + "component": "httpresponse", + "tab": "1615551125555", + "name": "HTTP Response", + "x": 596, + "y": 1586, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1634303504177", + "component": "monitormemory", + "tab": "1612772287426", + "name": "RAM", + "x": 69.88333129882812, + "y": 888.5, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465281992" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "858.88 MB / 985.68 MB", + "color": "gray" + }, + "options": { + "enabled": true, + "interval": 30000 + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1634303533779", + "component": "monitordisk", + "tab": "1612772287426", + "name": "disk", + "x": 70.88333129882812, + "y": 982.5, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465821120" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "5.78 GB / 7.26 GB", + "color": "gray" + }, + "options": { + "enabled": true, + "path": "/", + "interval": 30000 + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1634303595494", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "send-to-services", + "x": 51.883331298828125, + "y": 1400.5, + "connections": { + "0": [ + { + "index": "0", + "id": "1634463186563" + }, + { + "index": "1", + "id": "1634488120710" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1634303602169", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "send-to-services", + "x": 426.8833312988281, + "y": 878.5, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1634303685503", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "send-to-services", + "x": 600.8833312988281, + "y": 341.5, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1634303743260", + "component": "httprequest", + "tab": "1612772287426", + "name": "192.168.252.2:8004/sentmessage", + "reference": "", + "x": 506.8833312988281, + "y": 1331.7333374023438, + "connections": { + "0": [ + { + "index": "0", + "id": "1635327431236" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "url": "http://192.168.252.2:8004/sentmessage", + "method": "POST", + "stringify": "json" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1634463186563", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 305.75, + "y": 1442, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634464580289", + "component": "code", + "tab": "1612772287426", + "name": "Code", + "x": 245, + "y": 787, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465243324" + }, + { + "index": "0", + "id": "1634303602169" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "keepmessage": true, + "code": "let response = {};\nresponse.cpu = value.cpu;\nresponse.uptime = value.uptime;\n\nsend(0, response);", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1634465243324", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 428, + "y": 784, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634465281992", + "component": "code", + "tab": "1612772287426", + "name": "Code", + "x": 245, + "y": 884, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465338103" + }, + { + "index": "0", + "id": "1634303602169" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "keepmessage": true, + "code": "value.sender = \"ram\";\n\nlet response = {};\n\nresponse.memory_total = Math.round(value.total / (1024 ** 2));\nresponse.memory_free = Math.round(value.free / (1024 ** 2));\nresponse.memory_used = Math.round(value.used / (1024 ** 2));\n\nsend(0, response);", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1634465338103", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 429, + "y": 976, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634465821120", + "component": "code", + "tab": "1612772287426", + "name": "Code", + "x": 245, + "y": 978, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465892500" + }, + { + "index": "0", + "id": "1634303602169" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "keepmessage": true, + "code": "value.sender = \"hdd\";\n\nlet response = {};\n\nresponse.hdd_total = Math.round(value.total / (1024 ** 2));\nresponse.hdd_free = Math.round(value.free / (1024 ** 2));\nresponse.hdd_used = Math.round(value.used / (1024 ** 2));\n\nsend(0, response);", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1634465892500", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 432, + "y": 1068, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634484067516", + "component": "debug", + "tab": "1612772287426", + "name": "Send info", + "x": 513, + "y": 1441, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634488120710", + "component": "infosender", + "tab": "1612772287426", + "name": "Info sender", + "x": 301, + "y": 1336, + "connections": { + "0": [ + { + "index": "0", + "id": "1634484067516" + }, + { + "index": "0", + "id": "1634303743260" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "edge": "undefined" + }, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1635327431236", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 837.8833312988281, + "y": 1325.5, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1635936391935", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "send-to-services", + "x": 753, + "y": 623, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1637069803394", + "component": "monitorconsumption", + "tab": "1612772287426", + "name": "CPU", + "x": 69, + "y": 791, + "connections": { + "0": [ + { + "index": "0", + "id": "1634464580289" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "49.2% / 69.91 MB", + "color": "gray" + }, + "options": { + "monitorfiles": true, + "monitorconnections": true, + "monitorsize": true, + "monitorconsumption": true, + "enabled": true, + "interval": 30000 + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1683664161036", + "component": "debug", + "tab": "1615551125555", + "name": "CMDtoDIDO", + "x": 392, + "y": 1012, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1683981346282", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "from-dido-controller", + "x": 112, + "y": 459, + "connections": { + "0": [ + { + "index": "0", + "id": "1684055037116" + }, + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "from-dido-controller", + "color": "gray" + }, + "options": { + "wirename": "from-dido-controller" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1684055037116", + "component": "debug", + "tab": "1615551125555", + "name": "from dido to cmd", + "x": 451, + "y": 532, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1684060205000", + "component": "debug", + "tab": "1615551125555", + "name": "HTTP routes", + "x": 450, + "y": 639, + "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": "MDBToDido", + "x": 598, + "y": 147, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1699963668903", + "component": "dido_controller", + "tab": "1615551125555", + "name": "DIDO_Controller", + "x": 397, + "y": 1131, + "connections": { + "0": [ + { + "index": "0", + "id": "1617104731852" + } + ], + "1": [ + { + "index": "0", + "id": "1617104731852" + }, + { + "index": "0", + "id": "1617115013095" + } + ], + "2": [ + { + "index": "0", + "id": "1618393583970" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "edge": "undefined" + }, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1699964678894", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "modbus_to_dido", + "x": 96, + "y": 924, + "connections": { + "0": [ + { + "index": "0", + "id": "1699963668903" + }, + { + "index": "0", + "id": "1699964793925" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "modbus_to_dido", + "color": "gray" + }, + "options": { + "wirename": "modbus_to_dido" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1699964793925", + "component": "debug", + "tab": "1615551125555", + "name": "modbusToDido", + "x": 388, + "y": 920, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1699965957410", + "component": "modbus_reader", + "tab": "1611921777196", + "name": "Modbus reader", + "x": 232, + "y": 175, + "connections": { + "0": [ + { + "index": "0", + "id": "1611951142547" + } + ], + "1": [ + { + "index": "0", + "id": "1621340721628" + }, + { + "index": "0", + "id": "1684179110403" + }, + { + "index": "0", + "id": "1717441414646" + } + ], + "2": [ + { + "index": "0", + "id": "1615809595184" + }, + { + "index": "0", + "id": "1714752862828" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1700411878636", + "component": "thermometer", + "tab": "1611921777196", + "name": "Thermometer", + "x": 234.75, + "y": 444, + "connections": { + "0": [ + { + "index": "0", + "id": "1615802995322" + } + ], + "1": [ + { + "index": "0", + "id": "1615809595184" + }, + { + "index": "0", + "id": "1615809128443" + } + ], + "2": [ + { + "index": "0", + "id": "1621340721628" + }, + { + "index": "0", + "id": "1732889185927" + }, + { + "index": "0", + "id": "1717441414646" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#5CB36D", + "notes": "" + }, + { + "id": "1714752862828", + "component": "debug", + "tab": "1611921777196", + "name": "MDBToTb", + "x": 766, + "y": 324, + "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": 764.0833282470703, + "y": 222, + "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\telse if(value.status === \"NOK-thermometer\")\n\t{\n\t\tsend(0, {\"thermometer\": \"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\telse if(value.values.hasOwnProperty(\"temperature\"))\n\t{\n\t\tsend(0, {\"thermometer\": \"OK\"});\n\t}\n}", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1717442627834", + "component": "debug", + "tab": "1611921777196", + "name": "modbus service", + "x": 966.0833282470703, + "y": 165, + "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": 968.0833282470703, + "y": 268, + "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": 88.75, + "y": 1685, + "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": 296, + "y": 1671, + "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\", \"Flow has been restarted\", \"Node db has changed\"]", + "types": "[\"emergency\", \"critical\", \"error\", \"alert\"]", + "name": "" + }, + "color": "#30E193", + "notes": "" + }, + { + "id": "1718016073501", + "component": "httprequest", + "tab": "1612772287426", + "name": "http://192.168.252.2:8004/slack", + "x": 495, + "y": 1753, + "connections": { + "0": [ + { + "index": "0", + "id": "1718016086212" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "url": "http://192.168.252.2:8004/slack", + "method": "POST", + "stringify": "json" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1718016086212", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 832, + "y": 1664, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "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": 87, + "y": 1591, + "connections": { + "0": [ + { + "index": "0", + "id": "1718016052341" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "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\": \"\" } } } ] }", + "datatype": "object" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1729855334955", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "platform-rpc-call", + "x": 599.9333343505859, + "y": 541.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "platform-rpc-call", + "color": "gray" + }, + "options": { + "wirename": "platform-rpc-call" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1729855371093", + "component": "debug", + "tab": "1612772287426", + "name": "rpc cloud", + "x": 601.9333343505859, + "y": 440.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1731068658334", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 75.75, + "y": 184, + "connections": { + "0": [ + { + "index": "0", + "id": "1612776786008" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731068754606", + "component": "cloudmqttconnect", + "tab": "1612772287426", + "name": "MQTT to senica-prod01", + "x": 284.75, + "y": 452, + "connections": { + "1": [ + { + "index": "0", + "id": "1729855371093" + }, + { + "index": "0", + "id": "1729855334955" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Connected", + "color": "green" + }, + "options": { + "username": "", + "clientid": "", + "port": "2764", + "host": "192.168.252.2", + "topic": "" + }, + "color": "#888600", + "notes": "" + }, + { + "id": "1731069001548", + "component": "db_init", + "tab": "1612772287426", + "name": "DB Initialization", + "x": 1003.75, + "y": 240.25, + "connections": { + "0": [ + { + "index": "0", + "id": "1731069033416" + } + ], + "1": [ + { + "index": "0", + "id": "1747561603739" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#888600", + "notes": "" + }, + { + "id": "1731069033416", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "db-init", + "x": 1244.75, + "y": 233.25, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069059135", + "component": "showdb", + "tab": "1612772287426", + "name": "Show db data", + "x": 1186.75, + "y": 821.25, + "connections": { + "0": [ + { + "index": "0", + "id": "1731069079243" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#888600", + "notes": "" + }, + { + "id": "1731069079243", + "component": "debug", + "tab": "1612772287426", + "name": "dbData", + "x": 1390.75, + "y": 870.25, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1731069116691", + "component": "trigger", + "tab": "1612772287426", + "name": "settings", + "x": 934.75, + "y": 669.75, + "connections": { + "0": [ + { + "index": "0", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069131637", + "component": "trigger", + "tab": "1612772287426", + "name": "relaysData", + "x": 876.75, + "y": 733.75, + "connections": { + "0": [ + { + "index": "1", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069137374", + "component": "trigger", + "tab": "1612772287426", + "name": "nodesData", + "x": 852.75, + "y": 794.75, + "connections": { + "0": [ + { + "index": "2", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069179846", + "component": "trigger", + "tab": "1612772287426", + "name": "pinsData", + "x": 850.75, + "y": 861.75, + "connections": { + "0": [ + { + "index": "3", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069192937", + "component": "trigger", + "tab": "1612772287426", + "name": "sample data", + "x": 857.75, + "y": 928.75, + "connections": { + "0": [ + { + "index": "4", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069264443", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 63.75, + "y": 1279, + "connections": { + "0": [ + { + "index": "0", + "id": "1634488120710" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069334626", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "db-init", + "x": 172.88333129882812, + "y": 129, + "connections": { + "0": [ + { + "index": "0", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069548145", + "component": "virtualwirein", + "tab": "1611921777196", + "name": "db-init", + "x": 46.75, + "y": 192, + "connections": { + "0": [ + { + "index": "0", + "id": "1699965957410" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069567152", + "component": "virtualwirein", + "tab": "1611921777196", + "name": "db-init", + "x": 44.75, + "y": 465, + "connections": { + "0": [ + { + "index": "0", + "id": "1700411878636" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731070156936", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "db-init", + "x": 126.88333129882812, + "y": 1377, + "connections": { + "0": [ + { + "index": "2", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731234189516", + "component": "trigger", + "tab": "1612772287426", + "name": "monitor.txt", + "x": 882.75, + "y": 991.75, + "connections": { + "0": [ + { + "index": "5", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731234189551", + "component": "trigger", + "tab": "1612772287426", + "name": "err.txt", + "x": 904.75, + "y": 1053.75, + "connections": { + "0": [ + { + "index": "6", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1732700042559", + "component": "nodesdb_change_check", + "tab": "1612772287426", + "name": "Nodes DB change check", + "x": 266.8833312988281, + "y": 1980.2333984375, + "connections": { + "0": [ + { + "index": "0", + "id": "1732700071298" + }, + { + "index": "0", + "id": "1732700642917" + } + ], + "1": [ + { + "index": "0", + "id": "1759958914348" + }, + { + "index": "0", + "id": "1759959003114" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#888600", + "notes": "" + }, + { + "id": "1732700057052", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 76.75, + "y": 1988, + "connections": { + "0": [ + { + "index": "0", + "id": "1732700042559" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1732700071298", + "component": "debug", + "tab": "1612772287426", + "name": "nodesChange", + "x": 571.8833312988281, + "y": 2018.2333984375, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1732700642917", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "tb-push", + "x": 567.8833312988281, + "y": 1933, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1732889185927", + "component": "debug", + "tab": "1611921777196", + "name": "tempToDido", + "x": 594.8833312988281, + "y": 753, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1733574412965", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 72.75, + "y": 474, + "connections": { + "0": [ + { + "index": "1", + "id": "1731068754606" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1747561603739", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "send-to-services", + "x": 1243.8833312988281, + "y": 334.5, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1747562867845", + "component": "comment", + "tab": "1612772287426", + "name": "FLOW STARTING POINT", + "x": 1003.5666656494141, + "y": 178, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#704cff", + "notes": "" + }, + { + "id": "1749211698385", + "component": "trigger", + "tab": "1612772287426", + "name": "deviceStatus", + "x": 911.75, + "y": 1116.75, + "connections": { + "0": [ + { + "index": "7", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1757006030239", + "component": "httprequest", + "tab": "1615551125555", + "name": "192.168.252.2:8015/daily_report", + "x": 756.5666656494141, + "y": 715.4499969482422, + "connections": { + "0": [ + { + "index": "0", + "id": "1757006045804" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "stringify": "json", + "method": "POST", + "url": "http://192.168.252.2:8015/daily_report" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1757006045804", + "component": "debug", + "tab": "1615551125555", + "name": "ddd", + "x": 1091.566665649414, + "y": 711.4499969482422, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1757006060377", + "component": "debug", + "tab": "1615551125555", + "name": "reportDebug", + "x": 749.5666656494141, + "y": 799.4499969482422, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1759958914348", + "component": "httprequest", + "tab": "1612772287426", + "name": "http://192.168.252.2:8015/node_numbers", + "x": 571, + "y": 2111, + "connections": { + "0": [ + { + "index": "0", + "id": "1759958927094" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "stringify": "json", + "method": "POST", + "url": "http://192.168.252.2:8015/node_numbers" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1759958927094", + "component": "debug", + "tab": "1612772287426", + "name": "nodesChangeCloud", + "x": 951.8833312988281, + "y": 2109.2333984375, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1759959003114", + "component": "debug", + "tab": "1612772287426", + "name": "nodeChangeCloud1", + "x": 574, + "y": 2218, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1760020290879", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 84.75, + "y": 1787, + "connections": { + "0": [ + { + "index": "1", + "id": "1718016052341" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + } + ], + "version": 615 +} diff --git a/RVO47/flow/dido_controller.js b/RVO47/flow/dido_controller.js new file mode 100755 index 0000000..d16fb19 --- /dev/null +++ b/RVO47/flow/dido_controller.js @@ -0,0 +1,1486 @@ +exports.id = 'dido_controller'; +exports.title = 'DIDO_Controller'; +exports.version = '2.0.0'; +exports.group = 'Worksys'; +exports.color = '#2134B0'; +exports.input = 3; +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 + +state_of_main_switch - reportovat stav hlaveho istica : 0-> off 1-> on +rotary_switch_state - sem by sa mal reportovat stav vstupov manual a auto pola nasledovnej logiky: Manual = 1 a Auto = 0 -> Manu +Manual = 0 a Auto = 0 -> Off, Manual = 0 a Auto = 1 -> Automatic + +door_condition - pin 6, dverový kontakt -> 1 -> vyreportuje Closed, 0 -> vyreportuje Ope +twilight_sensor - hodnotu, ktoru vracia ten analogovy vstup (17) treba poslat sem ako float number. Zrejme tu potom pridame nejaky koeficient prevodu na luxy + +Na kazdu liniu +state_of_breaker - podla indexu istica sa reportuje jeho stav, teda istic na liniu 1: 0-> off, 1-> on +state_of_contactor - podla indexu stkaca sa reportuje jeho stav, teda stykac 1 na liniu 1: 0-> off, 1-> on +*/ + +const { errLogger, logger, monitor } = require('./helper/logger'); +const SerialPort = require('serialport'); +const WebSocket = require('ws'); +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 errorHandler = require('./helper/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 hasMainSwitch; + +let alarmStatus = "OFF"; + +const SEND_TO = { + debug: 0, + tb: 1, + cmd_manager: 2 +} + + +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 = {}; + let rsPortReceivedData = []; + + //to be able to get proper twilight values + let twilight_sensor_interval = 5;//minutes + let twilight_sensor = []; + const twilight_sensor_array = []; + let twilightError = false; + + monitor.info("DIDO_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-we make it global to see it from outside + FLOW.deviceStatus = { //key is device name: temperature,.... + "state_of_main_switch": "Off", //Hlavny istic (alebo druhy dverovy kontakt) + "rotary_switch_state": "Off", //Prevadzkovy + "door_condition": "closed", //Dverový kontakt + "em": "OK", //elektromer rvo + "temperature": "OK", //templomer + "battery": "OK", //Bateria + "power_supply": "OK", //Zdroj + "master_node": "OK", //MN - GLOBALS.settings.masterNodeIsResponding + "no_voltage": "OK", //GLOBALS.settings.no_voltage - vypadok napatia na faze + "state_of_breaker": {}, //"Off",//Istic + "state_of_contactor": {}, //"Off",//Stykac + "twilight_sensor": "OK" //lux sensor + }; + let deviceStatus = FLOW.deviceStatus; + + + function main() { + + GLOBALS = FLOW.GLOBALS; + SETTINGS = FLOW.GLOBALS.settings; + rvoTbName = SETTINGS.rvoTbName; + pinsData = GLOBALS.pinsData; + relaysData = GLOBALS.relaysData; + + tbHandler = new DataToTbHandler(SEND_TO.tb); + tbHandler.setSender(exports.title); + + controller_type = SETTINGS.controller_type; //"lm" or "unipi" + hasMainSwitch = SETTINGS.has_main_switch; + + if (controller_type == "") controller_type = "lm"; + + 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, "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; + } + } + + //report RVO version relaysData[0].tbname; + let values = {}; + values["edge_fw_version"] = SETTINGS.edge_fw_version; + values["maintenance_mode"] = SETTINGS.maintenance_mode; + + sendTelemetry(values, rvoTbName); + + 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); + } + + + function handleRsPort() { + + if (rsPort) { + rsPort.removeAllListeners(); + rsPort = null; + } + + //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('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) { + if (!err) { + monitor.info(exports.title + "--->Digital in_out has been set (runSyncExec was sucessfull)"); + + turnAlarm("off"); + 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('error', err => { + let message = "Dido: rsPort error: " + err.message; + logger.debug(message); + monitor.info(message); + errorHandler.sendMessageToService(message); + }) + + rsPort.on("close", () => { + let message = "Dido: rsPort closed - reconnecting ..."; + logger.debug(message); + monitor.info(message); + setTimeout(handleRsPort, 1000); + }) + + rsPort.open(); + } + + + function handleWebSocket() { + + if (ws) { + ws.removeAllListeners(); + ws = null; + } + + //to keep websocket opened, we send request every 150 seconds + let startRequests = null; + + console.log("handleWebSocket function called"); + ws = new WebSocket('ws:/0.0.0.0:1234/ws'); + + ws.onopen = function open() { + + instance.send(0, exports.title + " running"); + turnAlarm("off"); + + initialSetting(); + + setTimeout(function() { ws.send(JSON.stringify({ cmd: "all" })) }, 5000); + // we request dev info about neuron device from evok to keep websocket connection alive + // for some reason this request returns no data, but connection keeps alive + startRequests = setInterval(() => { + ws.send(JSON.stringify({ "cmd": "filter", "dev": ["neuron"] })); + }, 150000) + }; + + + // 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 = async 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; + + 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 => { + logger.debug('Dido: websocket error', err); + }) + + ws.onclose = function() { + logger.debug('Dido: websocket onclose, reconnecting...') + clearInterval(startRequests); + setTimeout(handleWebSocket, 1000); + } + } + + 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 turnAlarm(onOrOff) { + let value = 0; + if (onOrOff == "on") value = 1; + + if (value == 1 && SETTINGS.maintenance_mode) return; + + alarmStatus = "OFF"; + if (value == 1) alarmStatus = "ON"; + + if (rsPort) { + let arr = [0x55]; + arr.push(13); + arr.push(0); + arr.push(value); + + rsPort.write(Buffer.from(arr), function(err) { + logger.debug(`sirena - ${onOrOff}`); + }); + } + else if (ws) { + let cmd = { "cmd": "set", "dev": "relay", "circuit": "1_01", "value": value }; + ws.send(JSON.stringify(cmd)); + logger.debug(`sirena - ${onOrOff}`); + } + } + + + 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") { + bits.push(0); + } + else bits.push(1); + + if (deviceStatus["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); + } + + + // turn line on or off + function turnLine(onOrOff, line, pin, force, info) { + //onOrOff => "on" or "off" + let value = 0; + if (onOrOff == "on") value = 1; + + if (force == undefined) force = false; + + if (line == 0) { + if (value == 1 && alarmStatus == "ON") turnAlarm("off"); + SETTINGS.maintenance_mode = value ? true : false; + + 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); + return; + } + + if (pin === undefined) pin = getPin(line); + + if (pin === undefined) { + errLogger.error("pin is undefined!", line); + return; + } + + if (!force) { + if (relaysData[line].contactor == value) { + instance.send(SEND_TO.debug, `line is already ${onOrOff} ` + line); + logger.debug(`Dido: turnLine: line is already ${onOrOff} `, line); + return; + } + } + + // if(!rsPort.isOpen && !ws) + if (!rsPort && !ws) { + errLogger.error("Dido - port or websocket is not opened"); + return; + } + + if (rsPort) { + let arr = [0x55]; + arr.push(pin); + arr.push(0); + arr.push(value); + + rsPort.write(Buffer.from(arr), function(err) { + if (err === undefined) { + monitor.info(`Dido: turnLine ${onOrOff} zapisal do rsPort-u`, line, pin, arr, info); + switchLogic(arr); + } + else { + monitor.info(`Dido: turnLine ${onOrOff} WRITE error`, err); + } + }); + + } + else if (ws) { + //pin = "relay1_03" or "input1_01" ... we must make just "1_01" with slice method + monitor.info(`Dido: turnLine ${onOrOff} - (line, pin, force)`, line, pin, force, info); + let cmd = { "cmd": "set", "dev": "relay", "circuit": pin.slice(5), "value": value }; + ws.send(JSON.stringify(cmd)); + } + + //if rvo is 24/7, it has just one switching profile point at 13:00. we do not want to send notification as it repeats every day. + //const d = new Date(); + //if(d.getHours() != 13) sendNotification("Dido_controller: ", SETTINGS.rvoTbName, "switching_profile_point_applied_to_line", { line: line, value: onOrOff }, "", SEND_TO.tb, instance); + } + + + // 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; + + // 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) { + const status = flowdata.data.status; + if (status == "NOK-twilight_sensor") { + deviceStatus["twilight_sensor"] = "NOK"; + } + else if (status == "NOK-em340" || status == "NOK-em111") { + deviceStatus["em"] = "NOK"; + } + else if (status == "NOK-thermometer") { + deviceStatus["temperature"] = "NOK"; + } + } + else if ("values" in flowdata.data) { + 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" + } + else if (values.hasOwnProperty("temperature")) { + deviceStatus["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"; + } + + sendTelemetry(values, rvoTbName); + } + + sendRvoStatus(); + }) + + + + + // we expect array as flowdata.data + instance.on("1", flowdata => { + + //console.log(flowdata.data); + + if (!flowdata.data instanceof Object) return; + + let obj = flowdata.data; + let line = obj.line; + 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"); + }) + + + function calculateStateCode() { + + let bits = []; + + //Hlavny istic - state_of_main_switch => v rvo senica je to druhy door pre silovu cast (EM) + if (deviceStatus["state_of_main_switch"] === "closed" || deviceStatus["state_of_main_switch"] === "Off") { + bits.push(0); + } + else { + bits.push(1); + } + + //Prevadzkovy mod - Manual, Off, Automatic, maintenance_mode = true/false // DAVA 2 BITY + if (!SETTINGS.maintenance_mode) { + if (deviceStatus["rotary_switch_state"] === "Manual") { + bits.push(0); + bits.push(1); + } + + if (deviceStatus["rotary_switch_state"] === "Automatic") { + bits.push(0); + bits.push(0); + } + + if (deviceStatus["rotary_switch_state"] === "Off") { + bits.push(1); + bits.push(0); + } + } + else { + bits.push(1); + bits.push(1); + } + + //Dverovy kontakt + if (deviceStatus["door_condition"] === "closed") { + bits.push(0); + } + else { + bits.push(1); + } + + //EM + if (deviceStatus["em"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //Teplomer + if (deviceStatus["temperature"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //Batéria + if (deviceStatus["battery"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //Zdroj + if (deviceStatus["power_supply"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //MN + if (deviceStatus["master_node"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //výpadok napätia na fáze + if (deviceStatus["no_voltage"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + if (deviceStatus["twilight_sensor"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + // doplnime do 16 bitov (2 byty) + for (let i = bits.length; i < 16; i++) { + bits.push(0); + } + + // console.log("calculateStateCode - deviceStatus", deviceStatus); + // 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; + } + + + async function sendRvoStatus() { + + if (SETTINGS === undefined) return; + SETTINGS.masterNodeIsResponding ? deviceStatus["master_node"] = "OK" : deviceStatus["master_node"] = "NOK"; + + 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 pinsForRvoStatus(controllerType, hasMainSwitch) { + + let pins = []; + + if (controllerType === "lm") { + pins = [1, 4, 6]; + if (hasMainSwitch === 1) { + pins = [4, 6]; + } + } else if (controllerType === "unipi") { + pins = ["input1_01", "input1_04", "input1_05"]; + if (hasMainSwitch === 1) { + pins = ["input1_01", "input1_04"]; + } + } + + return pins; + } + + + function checkRvoStatus() { + + // 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 + //set RVO state + let status = "OK"; + + for (const [key, value] of Object.entries(deviceStatus)) { + if (["em", "twilight_sensor", "temperature", "master_node"].includes(key) && value === "NOK") status = "NOK"; + } + + if (status === "OK") { + + let pinIndexes = pinsForRvoStatus(controller_type, hasMainSwitch); + + for (const pinIndex of pinIndexes) { + if (previousValues[pinIndex] === 0) { + if ((pinIndex === 6 || pinIndex === 'input1_01' || pinIndex === 'input1_05') && SETTINGS.maintenance_mode) continue; + status = "NOK"; + break; + } + } + } + + // battery status. If value is 1 - battery is NOK + if (previousValues[5] === 1) status = "NOK"; + if (SETTINGS.no_voltage.size > 0) status = "NOK"; + + // console.log("rvo status",status) + return status; + } + + + // we pass array to function in case of rsPort ==> switchLogic([55,3,0,1]) ==> [[55,3,0,1]] + // we pass two values in case of websocket ==> switchLogic("relay1_03",1) ==> ["relay1_03",1] + const switchLogic = (...args) => { + + let values = {}; + let pinIndex, newPinValue, twilight; + + //data from rsPort + if (args.length == 1) { + pinIndex = args[0][1] + 1; + if (pinIndex === 17) pinIndex--; + newPinValue = args[0][3]; + twilight = args[0][2]; + } + //data from websocket + else { + pinIndex = args[0]; + newPinValue = args[1]; + } + + 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; + + //default value + let value = "On"; + if (newPinValue === 0) value = "Off"; + + //Hlavny istic + if (type === "state_of_main_switch" && hasMainSwitch) { + if (newPinValue === 0 && newPinValue !== previousValues[pinIndex]) { + sendNotification("switchLogic", rvoTbName, "main_switch_has_been_turned_off", {}, "", SEND_TO.tb, instance, "state_of_main_switch"); + 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"); + deviceStatus["state_of_main_switch"] = "On"; + } + } + + //Prevadzkovy mod + 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"; + + deviceStatus["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, "power_supply_has_disconnected_input", {}, "", SEND_TO.tb, instance, "power_supply"); + + deviceStatus["power_supply"] = "NOK"; + } + else if (newPinValue === 1 && newPinValue !== previousValues[pinIndex]) { + sendNotification("switchLogic", rvoTbName, "power_supply_works_correctly", {}, "", SEND_TO.tb, instance, "power_supply"); + + deviceStatus["power_supply"] = "OK"; + } + } + + //Bateria - 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"); + + deviceStatus["battery"] = "NOK"; + } + else if (newPinValue === 0 && newPinValue !== previousValues[pinIndex]) { + sendNotification("switchLogic", rvoTbName, "battery_level_is_ok", {}, "", SEND_TO.tb, instance, "battery_level"); + + deviceStatus["battery"] = "OK"; + } + } + + //Dverovy kontakt - pin 6 + //! Ak je rvo s dvoma dverovymi kontaktami, ked pride z evoku signal z input1_05, co bol predytm "state_of_main switch" handlujeme ho teraz ako 'door_condition' + else if (type == "door_condition" || type === "state_of_main_switch") { + newPinValue === 0 ? value = "open" : value = "closed"; + + let door = "door_main"; + if (type === "state_of_main_switch") door = "door_em"; + + if (value === "open") { + if (SETTINGS.maintenance_mode) { + sendNotification("switchLogic", rvoTbName, door + "_open", {}, "", SEND_TO.tb, instance, door); + } else { + sendNotification("switchLogic", rvoTbName, door + "_open_without_permission", {}, "", SEND_TO.tb, instance, door); + + // 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 (value === "closed") { + if (alarmStatus == "ON") turnAlarm("off"); + sendNotification("switchLogic", rvoTbName, door + "_close", {}, "", SEND_TO.tb, instance, door); + } + + deviceStatus[type] = value; + } + + //lux sensor + else if (type == "twilight_sensor") { + //! TODO - to show nok status, if lux value is not changing more then 10 times. + //Daylight is far more than 1000. So most of the day, when it is sunshine comes just value 1000. But lux sensor is not NOK. + //This is not the case in LM. If value from LM is the same 10x, there is 99% possibility, that sensor is NOK. + value = newPinValue; + + if (controller_type === 'lm') { + value = parseFloat(newPinValue + (256 * twilight)); + + 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 && !twilightError) { + twilightError = true; + let value = twilight_sensor_array.shift(); + + newPinValue = 0; + } + else if (set.size !== 1 && twilightError) { + //sendNotification("switchLogic", rvoTbName, 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) { + 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); + } + } + + 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); + } + + deviceStatus["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 (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 }); + + //mame iba 3 istice. vyreportujeme a ohandlujeme liniu na tom istom istici ako paralelna linia (napr linia 1, paralelna s nou je linia 4, key je string "4") + // ak je 7 linii, na 1 istici je linia 1,4,7 + + if (line == 1) { + + const lineOnSameBraker = [4, 7]; + + for (var i = 0; i < lineOnSameBraker.length; i++) { + if (!relaysData.hasOwnProperty(lineOnSameBraker[i])) continue; + + 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; + reportLineStatus(lineOnSameBraker[i]); + + values[type] = value; + const tbname = relaysData[lineOnSameBraker[i]].tbname; + sendTelemetry(values, tbname); + + delete values[type]; + } + + } + else { + const lineOnSameBraker = line + 3 + ""; + + if (relaysData.hasOwnProperty(lineOnSameBraker)) { + 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; + reportLineStatus(line + 3); + + values[type] = value; + const tbname = relaysData[lineOnSameBraker].tbname; + sendTelemetry(values, tbname); + + delete values[type]; + } + } + + } + + if (value == "Off") values["status"] = "NOK"; + deviceStatus["state_of_breaker"][line] = value; + + reportLineStatus(line); + } + else return; + + values[type] = value; + + if (type == "rotary_switch_state") { + if (SETTINGS.maintenance_mode) value = "maintenance"; + value = value.toLowerCase(); + values["power_mode"] = value; + } + + if (newPinValue != previousValues[pinIndex]) previousValues[pinIndex] = newPinValue; + if (Object.keys(values).length > 0 && tbname) sendTelemetry(values, tbname); + } + + + function sendTelemetry(values, tbname, date = Date.now()) { + let dataToTb = { + [tbname]: [ + { + "ts": date, + "values": values + } + ] + }; + + tbHandler.sendToTb(dataToTb, instance); + } + + + function isObject(item) { + return (typeof item === "object" && !Array.isArray(item) && item !== null); + } + +} //end of 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 +// *|input1_01|state_of_main_switch|0|........... +// *|input1_02|rotary_switch_state|0|........... +// *|input1_03|rotary_switch_state|0|........... +// *|intut1_04|power_supply|0|........... +// *|input1_05|door_condition|0|........... +// *|input1_06|state_of_breaker|1|........... +// *|input1_07|state_of_breaker|2|........... +// *|input1_08|state_of_breaker|3|........... +// *|relay1_02|state_of_contactor|1|........... +// *|relay1_03|state_of_contactor|2|........... +// *|relay1_04|state_of_contactor|3|........... +// *|287D8776E0013CE9|temperature|0|........... + + +//! pins_data --> from UNIPI +// { +// 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 } +// } + +//! relays_data +// { +// '0': { +// line: 0, +// tbname: 'KjbN4q7JPZmexgdnz2yKQ98YAWwO0Q3BMX6ERLoV', +// contactor: 1, +// profile: '' +// }, +// '1': { +// line: 1, +// tbname: 'RMgnK93rkoAazbqdQ4yBG95Z1YXGx6pmwBeVEP2O', +// contactor: 0, +// profile: '{"intervals":[{"value":0,"end_time":"20:00","start_time":"13:00"},{"value":1,"end_time":"10:00","start_time":"20:00"},{"value":0,"end_time":"10:20","start_time":"10:00"},{"value":1,"end_time":"10:40","start_time":"10:20"},{"value":0,"end_time":"11:00","start_time":"10:40"},{"value":1,"end_time":"11:30","start_time":"11:00"},{"value":0,"end_time":"11:50","start_time":"11:30"},{"value":1,"end_time":"13:00","start_time":"11:50"}],"astro_clock":false,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' +// }, +// '2': { +// line: 2, +// tbname: 'dlE1VQjYrNx9gZRmb38gG08oLBO4qaAk2M6JPnG7', +// contactor: 0, +// profile: '{"intervals":[{"value":0,"end_time":"20:00","start_time":"13:00"},{"value":1,"end_time":"10:00","start_time":"20:00"},{"value":0,"end_time":"10:20","start_time":"10:00"},{"value":1,"end_time":"10:40","start_time":"10:20"},{"value":0,"end_time":"11:00","start_time":"10:40"},{"value":1,"end_time":"11:30","start_time":"11:00"},{"value":0,"end_time":"11:50","start_time":"11:30"},{"value":1,"end_time":"13:00","start_time":"11:50"}],"astro_clock":false,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' +// }, +// '3': { +// line: 3, +// tbname: 'vnmG4kJxaXWNBgMQq0D7Aj5e9oZzOAlr6LdR3w2V', +// contactor: 0, +// profile: '{"intervals":[{"value":0,"end_time":"20:30","start_time":"13:00"},{"value":1,"end_time":"00:10","start_time":"20:30"},{"value":0,"end_time":"13:00","start_time":"05:40"},{"value":1,"end_time":"05:40","start_time":"00:10"}],"astro_clock":true,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' +// } +// } + + + + + +// { +// "jbN4q7JPZmexgdnz2yKbWGDYAWwO0Q3BMX6ERLoV": [ +// { +// "ts": 1700409326353, +// "values": { +// "_event": { +// "type": "notice", +// "status": "new", +// "source": { +// "func": "rsPort.open()", +// "component": "1700343402190", +// "component_name": "DIDO_Controller", +// "edge": "jbN4q7JPZmexgdnz2yKbWGDYAWwO0Q3BMX6ERLoV" +// }, +// "message": "al_shariff_10.0.0.38: FLOW has been started ", +// "message_data": "" +// } +// } +// } +// ] +// } diff --git a/RVO47/flow/helper/DataToTbHandler.js b/RVO47/flow/helper/DataToTbHandler.js new file mode 100755 index 0000000..716ef7b --- /dev/null +++ b/RVO47/flow/helper/DataToTbHandler.js @@ -0,0 +1,187 @@ +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; + this.itIsNodeReadout = false; + this.sender = ""; + + // if attribute change difference is less than limit value, we do not send to tb. + this.attributeChangeLimit = { + temperature: 0.5, + Phase_1_voltage: 2, + Phase_2_voltage: 2, + Phase_3_voltage: 2, + Phase_1_current: 0.1, + Phase_2_current: 0.1, + Phase_3_current: 0.1, + Phase_1_power: 2, + Phase_2_power: 2, + Phase_3_power: 2, + total_power: 2, + total_energy: 1, + Phase_1_pow_factor: 0.1, + Phase_2_pow_factor: 0.1, + Phase_3_pow_factor: 0.1, + power_factor: 0.1, + lifetime: 2, + voltage: 2, + power: 2, + frequency: 3, + energy: 0.1, + current: 2, + inclination_x: 10, + inclination_y: 10, + inclination_z: 10 + }; + + } + + dump() { + console.log("----------------------------"); + console.log("previousValues", this.previousValues); + console.log("----------------------------"); + } + + setSender(sender) { + this.sender = sender; + } + + isEmptyObject(obj) { + for (var _ in obj) { + return false; + } + return true; + } + + + sendToTb(data, instance) { + + //not to modify data object, we do deep copy: + let dataCopy = JSON.parse(JSON.stringify(data)); + + let keys = Object.keys(dataCopy); + + if (keys.length == 0) { + if (this.debug) console.log("sendToTb received empty object", dataCopy); + return; + } + + let tbname = keys[0]; + let ts; + + let arrayOfValues = dataCopy[tbname]; + let arrayOfValuesToSend = []; + + for (let i = 0; i < arrayOfValues.length; i++) { + + ts = arrayOfValues[i].ts; + let values = this.prepareValuesForTb(tbname, ts, arrayOfValues[i].values); + + if (!this.isEmptyObject(values)) { + arrayOfValuesToSend.push({ ts: ts, values: values }); + } + + } + + if (arrayOfValuesToSend.length == 0) { + //if(this.debug) console.log("data not sent - empty array"); + return; + } + + this.messageCounter++; + + let dataToTbModified = { + [tbname]: arrayOfValuesToSend + } + + //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); + instance.send(this.index, dataToTbModified); + } + + + getDiffTimestamp(key) { + //TODO set different value for given key!!! + //if(key == "status") this.timeToHoldTbValue = 2*60*60;//2h + return this.timeToHoldTbValue * 1000; + } + + + prepareValuesForTb(tbname, timestamp, values) { + + let keys = Object.keys(values); + + if (keys.includes("lifetime")) this.itIsNodeReadout = true; + + if (!this.previousValues.hasOwnProperty(tbname)) { + this.previousValues[tbname] = {}; + } + + //if(this.debug) console.log("prepareValuesForTb", tbname, timestamp, values); + + for (let i = 0; i < keys.length; i++) { + + let key = keys[i]; + let value = values[key]; + + if (!this.previousValues[tbname].hasOwnProperty(key)) { + this.previousValues[tbname][key] = { ts: timestamp, value: value }; + continue; + } + + // attributeData ==> {voltage: {ts:333333, value:5}} + let attributeData = this.previousValues[tbname][key]; + let attributeToChange = false; + if (key in this.attributeChangeLimit) attributeToChange = true; + let limit = this.attributeChangeLimit[key]; + let timestampDiffToRemoveKey; + + //this will ensure "node statecode" will be sent just once an hour + if (this.itIsNodeReadout && key === "statecode") { + attributeData.value = value; + this.itIsNodeReadout = false; + timestampDiffToRemoveKey = 1 * 60 * 60 * 1000; // 1 hour + } + + if (key === "twilight_sensor" && value > 100) { + attributeData.value = value; + } + + //if edge, master or node version do not change, send just once a day: + if (["edge_fw_version", "master_node_version", "fw_version"].includes(key)) { + timestampDiffToRemoveKey = 24 * 60 * 60 * 1000; + } + + if (attributeData.value === value || attributeToChange && Math.abs(attributeData.value - value) < limit) { + + let diff = timestamp - attributeData.ts; + if (!timestampDiffToRemoveKey) timestampDiffToRemoveKey = this.getDiffTimestamp(key); + + if (diff > timestampDiffToRemoveKey) { + attributeData.ts = Date.now(); + //if(this.debug) console.log(this.sender + ": update ts for key", key, "diff is", diff, "messageCounter", this.messageCounter); + } + else { + delete values[key]; + //if(this.debug) console.log(this.sender + ": delete key", key, "diff is", diff, "messageCounter", this.messageCounter, timestampDiffToRemoveKey); + } + } + else { + attributeData.value = value; + attributeData.ts = timestamp; + } + + } + + return values; + } +} + +module.exports = DataToTbHandler; + diff --git a/RVO47/flow/helper/ErrorToServiceHandler.js b/RVO47/flow/helper/ErrorToServiceHandler.js new file mode 100755 index 0000000..2b27c32 --- /dev/null +++ b/RVO47/flow/helper/ErrorToServiceHandler.js @@ -0,0 +1,91 @@ +const { MD5 } = require('./md5.js'); +const { networkInterfaces } = require('os'); + +class ErrorToServiceHandler { + constructor() { + this.previousValues = {}; + + this.project_id = undefined; + + const nets = networkInterfaces(); + this.ipAddresses = {}; + + for (const name of Object.keys(nets)) { + for (const net of nets[name]) { + // Skip over non-IPv4 and internal (i.e. 127.0.0.1) addresses + if (net.family === 'IPv4' && !net.internal) { + if (!this.ipAddresses[name]) { + this.ipAddresses[name] = []; + } + this.ipAddresses[name].push(net.address); + } + } + } + } + + setProjectId(project_id) { + this.project_id = project_id; + } + + processMessage(message, seconds) { + if (Array.isArray(message)) message = message.join(', '); + + let key = MD5(message); + let ts = Date.now(); + + //keep in memory - default value is 1h + if (seconds === undefined) seconds = 60 * 60; + + if (!this.previousValues.hasOwnProperty(key)) { + this.previousValues[key] = { ts: ts, duration: seconds }; + } + + let diff = (ts - this.previousValues[key].ts); + if (diff < this.previousValues[key].duration * 1000) return false; + + this.previousValues[key].ts = ts; + + return message; + } + + sendMessageToService(message, seconds, message_type) { + + // if error occures too early FLOW.GLOBALS.settings.project_id is still undefined + if (this.project_id === undefined) { + console.log("ErrorToServiceHandler.js: no project_id"); + return; + } + + let f = this.processMessage(message, seconds); + if (f === false) return; + + if (message_type === undefined) message_type = "error_message"; + + let toService = { + id: this.project_id, + ipAddresses: this.ipAddresses + }; + + //js_error || error_message + toService[message_type] = message; + + console.log("ErrorToServiceHandler------------------------>send to service", toService); + + RESTBuilder.make(function(builder) { + builder.method('POST'); + builder.post(toService); + builder.url('http://192.168.252.2:8004/sentmessage'); + + builder.callback(function(err, response, output) { + console.log("process.on error send", err, response, output, toService); + }); + }); + + } +} + +const errorHandler = new ErrorToServiceHandler(); + + +module.exports = errorHandler; +//module.exports = ErrorToServiceHandler; diff --git a/RVO47/flow/helper/db_helper.js b/RVO47/flow/helper/db_helper.js new file mode 100755 index 0000000..40e796c --- /dev/null +++ b/RVO47/flow/helper/db_helper.js @@ -0,0 +1,44 @@ +function promisifyBuilder(builder) +{ + return new Promise((resolve, reject) => { + + try{ + + builder.callback(function(err, response) { + + if(err != null) reject(err); + resolve(response); + }); + + } catch (error) { + reject(error); + } + }) +} + +function makeMapFromDbResult(response, ...keys) +{ + let s = "-"; + let data = {}; + + for(let i = 0; i < response.length; i++) + { + let record = response[i]; + + let k = []; + for(let j = 0; j < keys.length; j++) + { + k.push( record[keys[j]] ); + } + + let key = k.join(s); + data[ key ] = record; + } + + return data; +} + +module.exports = { + promisifyBuilder, + makeMapFromDbResult + } \ No newline at end of file diff --git a/RVO47/flow/helper/logger.js b/RVO47/flow/helper/logger.js new file mode 100755 index 0000000..2585639 --- /dev/null +++ b/RVO47/flow/helper/logger.js @@ -0,0 +1,30 @@ +//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/RVO47/flow/helper/md5.js b/RVO47/flow/helper/md5.js new file mode 100755 index 0000000..d3b0480 --- /dev/null +++ b/RVO47/flow/helper/md5.js @@ -0,0 +1,5 @@ +function MD5(d){var r = M(V(Y(X(d),8*d.length)));return r.toLowerCase()};function M(d){for(var _,m="0123456789ABCDEF",f="",r=0;r>>4&15)+m.charAt(15&_);return f}function X(d){for(var _=Array(d.length>>2),m=0;m<_.length;m++)_[m]=0;for(m=0;m<8*d.length;m+=8)_[m>>5]|=(255&d.charCodeAt(m/8))<>5]>>>m%32&255);return _}function Y(d,_){d[_>>5]|=128<<_%32,d[14+(_+64>>>9<<4)]=_;for(var m=1732584193,f=-271733879,r=-1732584194,i=271733878,n=0;n>16)+(_>>16)+(m>>16)<<16|65535&m}function bit_rol(d,_){return d<<_|d>>>32-_} + +module.exports = { + MD5 +} \ No newline at end of file diff --git a/RVO47/flow/helper/notification_reporter.js b/RVO47/flow/helper/notification_reporter.js new file mode 100755 index 0000000..839c12c --- /dev/null +++ b/RVO47/flow/helper/notification_reporter.js @@ -0,0 +1,121 @@ +//key is device, value = message {} +let sentValues = {}; +let notificationsData = null; +let rvoName; + +//sendNotification("CMD Manager: process cmd", SETTINGS.rvoTbName, "dimming_profile_was_successfully_received_by_node", { node: node }, "", SEND_TO.tb, instance); + +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 +}; + +function getKey(map, val) { + return Object.keys(map).findItem(key => map[key] === val); +} + +//https://stackoverflow.com/questions/41117799/string-interpolation-on-variable +var template = (tpl, args) => tpl.replace(/\${(\w+)}/g, (_, v) => args[v]); + + +function initNotification() { + notificationsData = FLOW.GLOBALS.notificationsData; + rvoName = FLOW.GLOBALS.settings.rvo_name; +} + + +function sendNotification(func, device, key, params, extra, tb_output, instance, saveKey) { + + let storeToSendValues = true; + if (saveKey == undefined) storeToSendValues = false; + + let weight = ""; + let message = {}; + + let notification = notificationsData[key]; + + if (notification) { + weight = notification.weight.toLowerCase(); + + Object.keys(notification).forEach(item => { + if (["en", "sk", "de", "cz", "it", "es"].includes(item)) { + message[item] = rvoName + ": " + template(notification[item], params); + } + }) + } + else { + //console.error("sendNotification: Notifications: undefined key", key, func, notificationsData); + console.error("sendNotification: Notifications: undefined key", key, func); + return false; + } + + //detect invalid err weight + if (getKey(ERRWEIGHT, weight) == undefined) { + console.error("sendNotification: Notifications: undefined weight", weight, key, func); + return false; + } + + if (sentValues.hasOwnProperty(saveKey)) { + if (JSON.stringify(sentValues[saveKey]) == JSON.stringify(message)) { + return false; + } + } + + if (sentValues[saveKey] == undefined) { + if (storeToSendValues) { + //do not send - flow is was started + sentValues[saveKey] = message; + return false; + } + } + + if (storeToSendValues) sentValues[saveKey] = message; + + let content = { + "type": weight, + "status": "new", + "source": { + "func": func, + "component": instance.id, + "component_name": instance.name, + "edge": device + }, + "message": message, + "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 + + return true; + +} + +module.exports = { + sendNotification, + ERRWEIGHT, + initNotification +} + diff --git a/RVO47/flow/helper/register.js b/RVO47/flow/helper/register.js new file mode 100755 index 0000000..fc1d008 --- /dev/null +++ b/RVO47/flow/helper/register.js @@ -0,0 +1,144 @@ +/* +0 - cislo registra / prikaz +1 - recepient - 0 = master, 1 = slave (slave je automaticky group a broadcast) +2 - r/rw - read/write +3- register name - nazov registra / prikazu (len pre info - zobrazenie v aplikacii) + +4,5,6,7, - jednotlive byte-y - nazov byte-u +4-7 - RES. a prazdny string "" sa nezobrazia!!! +*/ + +//124 zaznamov +const registers = [ + ["0","1","R","Status","","",""], + ["1","1","RW","Dimming","R-Channel ","G-Channel","B-Channel ","W - Channel"], + ["2","1","R","Device types","","",".",""], + ["3","1","RW","Group addresses 1-4","Groups Add. 4","Groups Add. 3","Groups Add. 2","Groups Add. 1"], + ["4","1","RW","Group addresses 5-8","Groups Add. 8","Groups Add. 7","Groups Add. 6","Groups Add. 5"], + ["5","1","RW","Serial number (MAC)","","","",""], + ["6","1","RW","Time of dusk","HH","MM","SS","EXTRA"], + ["7","1","RW","Time of dawn","HH","MM","SS","EXTRA"], + ["8","1","RW","Time Schedule settings","TBD","TBD","Movement sensor","Time Schedule"], + ["9","1","RW","TS1 Time point 1","HH","MM","SS","Ext. Device"], + ["10","1","RW","TS1 Time point 1 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["11","1","RW","TS1 Time point 2","HH","MM","SS","Ext. Device"], + ["12","1","RW","TS1 Time point 2 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["13","1","RW","TS1 Time point 3","HH","MM","SS","Ext. Device"], + ["14","1","RW","TS1 Time point 3 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["15","1","RW","TS1 Time point 4","HH","MM","SS","Ext. Device"], + ["16","1","RW","TS1 Time point 4 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["17","1","RW","TS1 Time point 5","HH","MM","SS","Ext. Device"], + ["18","1","RW","TS1 Time point 5 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["19","1","RW","TS1 Time point 6","HH","MM","SS","Ext. Device"], + ["20","1","RW","TS1 Time point 6 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["21","1","RW","TS1 Time point 7","HH","MM","SS","Ext. Device"], + ["22","1","RW","TS1 Time point 7 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["23","1","RW","TS1 Time point 8","HH","MM","SS","Ext. Device"], + ["24","1","RW","TS1 Time point 8 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["25","1","RW","TS1 Time point 9","HH","MM","SS","Ext. Device"], + ["26","1","RW","TS1 Time point 9 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["27","1","RW","TS1 Time point 10","HH","MM","SS","Ext. Device"], + ["28","1","RW","TS1 Time point 10 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["29","1","RW","TS1 Time point 11","HH","MM","SS","Ext. Device"], + ["30","1","RW","TS1 Time point 11 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["31","1","RW","TS1 Time point 12","HH","MM","SS","Ext. Device"], + ["32","1","RW","TS1 Time point 12 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["33","1","RW","TS1 Time point 13","HH","MM","SS","Ext. Device"], + ["34","1","RW","TS1 Time point 13 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["35","1","RW","TS1 Time point 14","HH","MM","SS","Ext. Device"], + ["36","1","RW","TS1 Time point 14 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["37","1","RW","TS1 Time point 15","HH","MM","SS","Ext. Device"], + ["38","1","RW","TS1 Time point 15 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["39","1","RW","TS1 Time point 16","HH","MM","SS","Ext. Device"], + ["40","1","RW","TS1 Time point 16 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["41","1","RW","TS2 Time point 1","HH","MM","SS","Ext. Device"], + ["42","1","RW","TS2 Time point 1 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["43","1","RW","TS2 Time point 2","HH","MM","SS","Ext. Device"], + ["44","1","RW","TS2 Time point 2 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["45","1","RW","TS2 Time point 3","HH","MM","SS","Ext. Device"], + ["46","1","RW","TS2 Time point 3 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["47","1","RW","TS2 Time point 4","HH","MM","SS","Ext. Device"], + ["48","1","RW","TS2 Time point 4 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["49","1","RW","TS2 Time point 5","HH","MM","SS","Ext. Device"], + ["50","1","RW","TS2 Time point 5 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["51","1","RW","TS2 Time point 6","HH","MM","SS","Ext. Device"], + ["52","1","RW","TS2 Time point 6 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["53","1","RW","TS2 Time point 7","HH","MM","SS","Ext. Device"], + ["54","1","RW","TS2 Time point 7 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["55","1","RW","TS2 Time point 8","HH","MM","SS","Ext. Device"], + ["56","1","RW","TS2 Time point 8 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["57","1","RW","TS2 Time point 9","HH","MM","SS","Ext. Device"], + ["58","1","RW","TS2 Time point 9 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["59","1","RW","TS2 Time point 10","HH","MM","SS","Ext. Device"], + ["60","1","RW","TS2 Time point 10 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["61","1","RW","TS2 Time point 11","HH","MM","SS","Ext. Device"], + ["62","1","RW","TS2 Time point 11 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["63","1","RW","TS2 Time point 12","HH","MM","SS","Ext. Device"], + ["64","1","RW","TS2 Time point 12 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["65","1","RW","TS2 Time point 13","HH","MM","SS","Ext. Device"], + ["66","1","RW","TS2 Time point 13 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["67","1","RW","TS2 Time point 14","HH","MM","SS","Ext. Device"], + ["68","1","RW","TS2 Time point 14 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["69","1","RW","TS2 Time point 15","HH","MM","SS","Ext. Device"], + ["70","1","RW","TS2 Time point 15 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["71","1","RW","TS2 Time point 16","HH","MM","SS","Ext. Device"], + ["72","1","RW","TS2 Time point 16 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["73","1","RW","Power meter status","TBD","","",""], + ["74","1","R","Input Voltage","","","",""], + ["75","1","R","Input Current","","","",""], + ["76","1","R","Input Power","","","",""], + ["77","1","R","Cos phi","","","",""], + ["78","1","R","Frequency","","","",""], + ["79","1","RW","Energy","","","",""], + ["80","1","RW","Lifetime","","","",""], + ["81","1","RW","Power on cycles (input)","","","",""], + ["82","1","RW","Power on cycles (relay)","","","",""], + ["83","1","R","Time since last power on","","","",""], + ["84","1","R","Accelerometer data","","","",""], + ["85","1","RW","GPS latitude","pos/neg","deg","min ","sec"], + ["86","1","RW","GPS longitude","pos/neg","deg","min ","sec"], + ["87","1","RW","Actual time","HH","MM","SS","RES."], + ["88","1","RW","Actual date","Day of week","Day","Month","Year"], + ["89","1","R","Production data 1","","","",""], + ["90","1","R","Production data 2","","","",""], + ["91","1","RW","Network ID","NID3","NID2","NID1","NID0"], + ["95","1","RW","Actual Lux level from cabinet","RES.","RES.","HB","LB"], + ["96","1","RW","Threshold lux level","Dusk HB","Dusk LB","Dawn HB","Dawn LB"], + ["97","1","RW","Adjust period","Dusk HB","Dusk LB","Dawn HB","Dawn LB"], + ["98","1","RW","Offset","RES.","RES.","Dusk","Dawn"], + ["99","1","RW","CCT min/max range","max-H","max-L","min-H","min-L"], + ["100","1","RW","DALI interface","Cmd ID","Add","Cmd","Resp"], + ["101","1","RW","Module FW ver","v1","v2","v3","v4"], + ["102","1","RW","Module MAC-H","unused","unused","M1","M2"], + ["103","1","RW","Module MAC-L","M3","M4","M5","M6"], + ["122","1","R","FW update status/control register","Byte3","Byte2","Byte1","Byte0"], + ["123","1","R","FW update - data index","Byte3","Byte2","Byte1","Byte0"], + ["124","1","R","FW update - data","Byte3","Byte2","Byte1","Byte0"], + ["0","0","R","Status","","","",""], + ["1","0","RW","Control register","RES.","RES.","RES.","init mode enable"], + ["2","0","R","Device types","","","",""], + ["3","0","R","Serial number (MAC)","","","",""], + ["4","0","R","Production data 1","","","",""], + ["5","0","R","Production data 2","","","",""], + ["6","0","RW","Network ID","NID3","NID2","NID1","NID0"], + ["7","0","RW","RS232 settings","param.","param.","Baudrate H","Baudrate L"], + ["8","0","R","Accelerometer data","","","",""], + ["9","0","RW","Module FW ver","v1","v2","v3","v4"], + ["10","0","RW","Module MAC-H","unused","unused","M1","M2"], + ["11","0","RW","Module MAC-L","M3","M4","M5","M6"], + ["32","0","RW","FW update status/control register","Byte3","Byte2","Byte1","Byte0"], + ["33","0","RW","FW update - data index","Byte3","Byte2","Byte1","Byte0"], + ["34","0","RW","FW update - data","Byte3","Byte2","Byte1","Byte0"], + ["125","0","RW","Debug Register","Byte3","Byte2","Byte1","Byte0"], + ["126","0","RW","Network Control Register","Byte3","Byte2","Byte1","Byte0"], + ["127","0","R","Network Status Register","Byte3","Byte2","Byte1","Byte0"], + ["128","0","RW","Node XX Serial Number Register","SER3","SER2","SER1","SER0"], + ["256","0","R","Node XX Network Status Register","","","",""] +]; + +let register = {}; + +module.exports = { + registers, + register +} \ No newline at end of file diff --git a/RVO47/flow/helper/serialport_helper.js b/RVO47/flow/helper/serialport_helper.js new file mode 100755 index 0000000..7f5920d --- /dev/null +++ b/RVO47/flow/helper/serialport_helper.js @@ -0,0 +1,99 @@ +const { exec } = require('child_process'); + +function openPort(port) { + return new Promise((resolve, reject) => { + + var callbackError = function(err) { + port.removeListener('error', callbackError); + port.removeListener('open', callbackError); + + reject(err.message); + }; + + var callbackOpen = function(data) { + port.removeListener('error', callbackError); + port.removeListener('open', callbackOpen); + + resolve("port open: ok"); + }; + + port.on('error', callbackError); + port.on('open', callbackOpen); + + port.open(); + + }) +} + +function runSyncExec(command) { + return new Promise((resolve, reject) => { + + exec(command, (error, stdout, stderr) => { + if (error == null) resolve(stdout); + reject(error); + }); + + }) +} + +async function writeData(port, data, readbytes, timeout) { + return new Promise((resolve, reject) => { + + // 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) { + + port.write(Buffer.from(data), function(err) { + if (err) { + reject(err.message); + } + }); + + 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 +} diff --git a/RVO47/flow/helper/suncalc.js b/RVO47/flow/helper/suncalc.js new file mode 100755 index 0000000..c9ca56d --- /dev/null +++ b/RVO47/flow/helper/suncalc.js @@ -0,0 +1,317 @@ +/* + (c) 2011-2015, Vladimir Agafonkin + SunCalc is a JavaScript library for calculating sun/moon position and light phases. + https://github.com/mourner/suncalc +*/ + +(function () { 'use strict'; + +// shortcuts for easier to read formulas + +var PI = Math.PI, + sin = Math.sin, + cos = Math.cos, + tan = Math.tan, + asin = Math.asin, + atan = Math.atan2, + acos = Math.acos, + rad = PI / 180; + +// sun calculations are based on http://aa.quae.nl/en/reken/zonpositie.html formulas + + +// date/time constants and conversions + +var dayMs = 1000 * 60 * 60 * 24, + J1970 = 2440588, + J2000 = 2451545; + +function toJulian(date) { return date.valueOf() / dayMs - 0.5 + J1970; } +function fromJulian(j) { return new Date((j + 0.5 - J1970) * dayMs); } +function toDays(date) { return toJulian(date) - J2000; } + + +// general calculations for position + +var e = rad * 23.4397; // obliquity of the Earth + +function rightAscension(l, b) { return atan(sin(l) * cos(e) - tan(b) * sin(e), cos(l)); } +function declination(l, b) { return asin(sin(b) * cos(e) + cos(b) * sin(e) * sin(l)); } + +function azimuth(H, phi, dec) { return atan(sin(H), cos(H) * sin(phi) - tan(dec) * cos(phi)); } +function altitude(H, phi, dec) { return asin(sin(phi) * sin(dec) + cos(phi) * cos(dec) * cos(H)); } + +function siderealTime(d, lw) { return rad * (280.16 + 360.9856235 * d) - lw; } + +function astroRefraction(h) { + if (h < 0) // the following formula works for positive altitudes only. + h = 0; // if h = -0.08901179 a div/0 would occur. + + // formula 16.4 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + // 1.02 / tan(h + 10.26 / (h + 5.10)) h in degrees, result in arc minutes -> converted to rad: + return 0.0002967 / Math.tan(h + 0.00312536 / (h + 0.08901179)); +} + +// general sun calculations + +function solarMeanAnomaly(d) { return rad * (357.5291 + 0.98560028 * d); } + +function eclipticLongitude(M) { + + var C = rad * (1.9148 * sin(M) + 0.02 * sin(2 * M) + 0.0003 * sin(3 * M)), // equation of center + P = rad * 102.9372; // perihelion of the Earth + + return M + C + P + PI; +} + +function sunCoords(d) { + + var M = solarMeanAnomaly(d), + L = eclipticLongitude(M); + + return { + dec: declination(L, 0), + ra: rightAscension(L, 0) + }; +} + + +var SunCalc = {}; + + +// calculates sun position for a given date and latitude/longitude + +SunCalc.getPosition = function (date, lat, lng) { + + var lw = rad * -lng, + phi = rad * lat, + d = toDays(date), + + c = sunCoords(d), + H = siderealTime(d, lw) - c.ra; + + return { + azimuth: azimuth(H, phi, c.dec), + altitude: altitude(H, phi, c.dec) + }; +}; + + +// sun times configuration (angle, morning name, evening name) + +var times = SunCalc.times = [ + [-0.833, 'sunrise', 'sunset' ], + [ -0.3, 'sunriseEnd', 'sunsetStart' ], + [ -6, 'dawn', 'dusk' ], + [ -12, 'nauticalDawn', 'nauticalDusk'], + [ -18, 'nightEnd', 'night' ], + [ 6, 'goldenHourEnd', 'goldenHour' ] +]; + +// adds a custom time to the times config + +SunCalc.addTime = function (angle, riseName, setName) { + times.push([angle, riseName, setName]); +}; + + +// calculations for sun times + +var J0 = 0.0009; + +function julianCycle(d, lw) { return Math.round(d - J0 - lw / (2 * PI)); } + +function approxTransit(Ht, lw, n) { return J0 + (Ht + lw) / (2 * PI) + n; } +function solarTransitJ(ds, M, L) { return J2000 + ds + 0.0053 * sin(M) - 0.0069 * sin(2 * L); } + +function hourAngle(h, phi, d) { return acos((sin(h) - sin(phi) * sin(d)) / (cos(phi) * cos(d))); } +function observerAngle(height) { return -2.076 * Math.sqrt(height) / 60; } + +// returns set time for the given sun altitude +function getSetJ(h, lw, phi, dec, n, M, L) { + + var w = hourAngle(h, phi, dec), + a = approxTransit(w, lw, n); + return solarTransitJ(a, M, L); +} + + +// calculates sun times for a given date, latitude/longitude, and, optionally, +// the observer height (in meters) relative to the horizon + +SunCalc.getTimes = function (date, lat, lng, height) { + + height = height || 0; + + var lw = rad * -lng, + phi = rad * lat, + + dh = observerAngle(height), + + d = toDays(date), + n = julianCycle(d, lw), + ds = approxTransit(0, lw, n), + + M = solarMeanAnomaly(ds), + L = eclipticLongitude(M), + dec = declination(L, 0), + + Jnoon = solarTransitJ(ds, M, L), + + i, len, time, h0, Jset, Jrise; + + + var result = { + solarNoon: fromJulian(Jnoon), + nadir: fromJulian(Jnoon - 0.5) + }; + + for (i = 0, len = times.length; i < len; i += 1) { + time = times[i]; + h0 = (time[0] + dh) * rad; + + Jset = getSetJ(h0, lw, phi, dec, n, M, L); + Jrise = Jnoon - (Jset - Jnoon); + + result[time[1]] = fromJulian(Jrise); + result[time[2]] = fromJulian(Jset); + } + + return result; +}; + + +// moon calculations, based on http://aa.quae.nl/en/reken/hemelpositie.html formulas + +function moonCoords(d) { // geocentric ecliptic coordinates of the moon + + var L = rad * (218.316 + 13.176396 * d), // ecliptic longitude + M = rad * (134.963 + 13.064993 * d), // mean anomaly + F = rad * (93.272 + 13.229350 * d), // mean distance + + l = L + rad * 6.289 * sin(M), // longitude + b = rad * 5.128 * sin(F), // latitude + dt = 385001 - 20905 * cos(M); // distance to the moon in km + + return { + ra: rightAscension(l, b), + dec: declination(l, b), + dist: dt + }; +} + +SunCalc.getMoonPosition = function (date, lat, lng) { + + var lw = rad * -lng, + phi = rad * lat, + d = toDays(date), + + c = moonCoords(d), + H = siderealTime(d, lw) - c.ra, + h = altitude(H, phi, c.dec), + // formula 14.1 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + pa = atan(sin(H), tan(phi) * cos(c.dec) - sin(c.dec) * cos(H)); + + h = h + astroRefraction(h); // altitude correction for refraction + + return { + azimuth: azimuth(H, phi, c.dec), + altitude: h, + distance: c.dist, + parallacticAngle: pa + }; +}; + + +// calculations for illumination parameters of the moon, +// based on http://idlastro.gsfc.nasa.gov/ftp/pro/astro/mphase.pro formulas and +// Chapter 48 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + +SunCalc.getMoonIllumination = function (date) { + + var d = toDays(date || new Date()), + s = sunCoords(d), + m = moonCoords(d), + + sdist = 149598000, // distance from Earth to Sun in km + + phi = acos(sin(s.dec) * sin(m.dec) + cos(s.dec) * cos(m.dec) * cos(s.ra - m.ra)), + inc = atan(sdist * sin(phi), m.dist - sdist * cos(phi)), + angle = atan(cos(s.dec) * sin(s.ra - m.ra), sin(s.dec) * cos(m.dec) - + cos(s.dec) * sin(m.dec) * cos(s.ra - m.ra)); + + return { + fraction: (1 + cos(inc)) / 2, + phase: 0.5 + 0.5 * inc * (angle < 0 ? -1 : 1) / Math.PI, + angle: angle + }; +}; + + +function hoursLater(date, h) { + return new Date(date.valueOf() + h * dayMs / 24); +} + +// calculations for moon rise/set times are based on http://www.stargazing.net/kepler/moonrise.html article + +SunCalc.getMoonTimes = function (date, lat, lng, inUTC) { + var t = new Date(date); + if (inUTC) t.setUTCHours(0, 0, 0, 0); + else t.setHours(0, 0, 0, 0); + + var hc = 0.133 * rad, + h0 = SunCalc.getMoonPosition(t, lat, lng).altitude - hc, + h1, h2, rise, set, a, b, xe, ye, d, roots, x1, x2, dx; + + // go in 2-hour chunks, each time seeing if a 3-point quadratic curve crosses zero (which means rise or set) + for (var i = 1; i <= 24; i += 2) { + h1 = SunCalc.getMoonPosition(hoursLater(t, i), lat, lng).altitude - hc; + h2 = SunCalc.getMoonPosition(hoursLater(t, i + 1), lat, lng).altitude - hc; + + a = (h0 + h2) / 2 - h1; + b = (h2 - h0) / 2; + xe = -b / (2 * a); + ye = (a * xe + b) * xe + h1; + d = b * b - 4 * a * h1; + roots = 0; + + if (d >= 0) { + dx = Math.sqrt(d) / (Math.abs(a) * 2); + x1 = xe - dx; + x2 = xe + dx; + if (Math.abs(x1) <= 1) roots++; + if (Math.abs(x2) <= 1) roots++; + if (x1 < -1) x1 = x2; + } + + if (roots === 1) { + if (h0 < 0) rise = i + x1; + else set = i + x1; + + } else if (roots === 2) { + rise = i + (ye < 0 ? x2 : x1); + set = i + (ye < 0 ? x1 : x2); + } + + if (rise && set) break; + + h0 = h2; + } + + var result = {}; + + if (rise) result.rise = hoursLater(t, rise); + if (set) result.set = hoursLater(t, set); + + if (!rise && !set) result[ye > 0 ? 'alwaysUp' : 'alwaysDown'] = true; + + return result; +}; + + +// export as Node module / AMD module / browser variable +if (typeof exports === 'object' && typeof module !== 'undefined') module.exports = SunCalc; +else if (typeof define === 'function' && define.amd) define(SunCalc); +else window.SunCalc = SunCalc; + +}()); diff --git a/RVO47/flow/helper/utils.js b/RVO47/flow/helper/utils.js new file mode 100755 index 0000000..dbffe45 --- /dev/null +++ b/RVO47/flow/helper/utils.js @@ -0,0 +1,161 @@ +const fs = require('fs').promises; + +function bytesToInt(bytes, numberOfBytes) { + let buffer = []; + if (Array.isArray(bytes)) { + buffer = bytes.slice(0); + if (numberOfBytes != undefined) { + buffer = bytes.slice(bytes.length - numberOfBytes); + } + } + else buffer.push(bytes); + + let result = 0; + for (let i = 0; i < buffer.length; i++) { + result = (result << 8) | buffer[i]; + } + + return result >>> 0; //ensure it's an unsigned 32-bit number +} + +function resizeArray(arr, newSize, defaultValue) { + while (newSize > arr.length) + arr.push(defaultValue); + arr.length = newSize; +} + +longToByteArray = function(/*long*/long) { + // we want to represent the input as a 8-bytes array + var byteArray = [0, 0, 0, 0, 0, 0, 0, 0]; + + for (var index = 0; index < byteArray.length; index++) { + var byte = long & 0xff; + byteArray[index] = byte; + long = (long - byte) / 256; + } + + return byteArray; +}; + +function addDays(date, days) { + var result = new Date(date); + result.setDate(result.getDate() + days); + return result; +} + +/* +sleep(2000).then(() => { + // Do something after the sleep! + + +}); +*/ + +function sleep(time) { + return new Promise((resolve) => setTimeout(resolve, time)); +} + +function isEmptyObject(obj) { + for (var name in obj) { + return false; + } + return true; +} + +function emptyJsObject(jsObject) { + Object.keys(jsObject).forEach(key => delete jsObject[key]); +} + +function convertUTCDateToLocalDate(date) { + var newDate = new Date(date); + newDate.setMinutes(date.getMinutes() + date.getTimezoneOffset()); + return newDate; +} + +function addZeroBefore(n) { + return (n < 10 ? '0' : '') + n; +} + + +/** + * Asynchronously writes data to a file. + * + * @param {string} filePath The path to the file. + * @param {string} data The data to write to the file. + * @param {boolean} [append=false] If true, appends the data to the file. If false, it overwrites the file. + */ +async function writeToFile(filePath, data, append = false) { + if (typeof data !== 'string') data = JSON.stringify(data, null, 2); + try { + if (append) { + // Append the data to the end of the file. This is the simplest way to append. + await fs.appendFile(filePath, data, 'utf8'); + console.log(`Successfully appended data to ${filePath} using fs.appendFile.`); + } else { + // Overwrite the file with the new data. + await fs.writeFile(filePath, data, 'utf8'); + console.log(`Successfully wrote (overwrote) data to ${filePath} using fs.writeFile.`); + } + } catch (error) { + console.error(`Error writing to file ${filePath}:`, error); + } +} + + + /** + * Checks if an item is present in an array and adds it if it's not. + * * @param {Array} arr The array to check. + * @param {*} item The item to add. + * @returns {Array} The modified array. + */ +const addToArrayIfUnique = (arr, item) => { + if (!arr.includes(item)) { + arr.push(item); + } + return arr; +}; + + +var convertBase = function() { + + function convertBase(baseFrom, baseTo) { + return function(num) { + return parseInt(num, baseFrom).toString(baseTo); + + }; + } + + // binary to decimal + convertBase.bin2dec = convertBase(2, 10); + + // binary to hexadecimal + convertBase.bin2hex = convertBase(2, 16); + + // decimal to binary + convertBase.dec2bin = convertBase(10, 2); + + // decimal to hexadecimal + convertBase.dec2hex = convertBase(10, 16); + + // hexadecimal to binary + convertBase.hex2bin = convertBase(16, 2); + + // hexadecimal to decimal + convertBase.hex2dec = convertBase(16, 10); + + return convertBase; +}(); + +module.exports = { + bytesToInt, + longToByteArray, + addDays, + addZeroBefore, + resizeArray, + isEmptyObject, + emptyJsObject, + sleep, + convertUTCDateToLocalDate, + writeToFile, + addToArrayIfUnique +} diff --git a/RVO47/flow/httprequest.js b/RVO47/flow/httprequest.js new file mode 100755 index 0000000..469c8cb --- /dev/null +++ b/RVO47/flow/httprequest.js @@ -0,0 +1,137 @@ +exports.id = 'httprequest'; +exports.title = 'HTTP Request'; +exports.group = 'HTTP'; +exports.color = '#5D9CEC'; +exports.input = true; +exports.version = '2.0.1'; +exports.output = 1; +exports.author = 'Peter Širka'; +exports.icon = 'cloud-upload'; + +exports.html = `
+
@(URL address)
+
+
+
@(HTTP method)
+
+
+
@(Serialization)
+
+
+
@(Download the content in chunks)
+
@(Keep persistent cookies)
+
@(Disable DNS cache)
+
@(Keep alive connection)
+
+
+
+
@(Custom headers)
+
@(Cookies)
+
+
+
+ +
+
+
+
@(User)
+
+
+
@(Password)
+
+
+
+
+
`; + +exports.readme = `# Request + +This component creates a request with received data. + +__Response:__ +\`\`\`javascript +{ + data: String, + headers: Object, + status: Number, + host: String +} +\`\`\` + +__Dynamic arguments__: +Are performed via FlowData repository and can be used for URL address or for custom headers/cookies/auth. Use \`repository\` component for creating of dynamic arguments. Dynamic values are replaced in the form \`{key}\`: + +- url address e.g. \`https://.../{key}/\` +- headers values e.g. \`{token}\` +- cookies values e.g. \`{token}\``; + +exports.install = function(instance) { + + var can = false; + var flags = null; + var cookies2 = null; + + instance.on('data', function(response) { + can && instance.custom.send(response); + }); + + instance.custom.send = function(response) { + var options = instance.options; + + var headers = null; + var cookies = null; + + options.headers && Object.keys(options.headers).forEach(function(key) { + !headers && (headers = {}); + headers[key] = response.arg(options.headers[key]); + }); + + if (options.username && options.userpassword) { + !headers && (headers = {}); + headers['Authorization'] = 'Basic ' + U.createBuffer(response.arg(options.username + ':' + options.userpassword)).toString('base64'); + } + + options.cookies && Object.keys(options.cookies).forEach(function(key) { + !cookies && (cookies = {}); + cookies[key] = response.arg(options.cookies[key]); + }); + + if (options.chunks) { + U.download(response.arg(options.url), flags, options.stringify === 'none' ? null : response.data, function(err, response) { + response.on('data', (chunks) => instance.send2(chunks)); + }, cookies || cookies2, headers); + } else { + U.request(response.arg(options.url), flags, options.stringify === 'none' ? null : response.data, 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) + instance.error(err, response); + }, cookies || cookies2, headers); + } + }; + + instance.reconfigure = function() { + var options = instance.options; + can = options.url && options.url && options.method && options.stringify ? true : false; + instance.status(can ? '' : 'Not configured', can ? undefined : 'red'); + + if (!can) + return; + + flags = []; + flags.push(options.method.toLowerCase()); + options.stringify === 'json' && flags.push('json'); + options.stringify === 'raw' && flags.push('raw'); + options.keepalive && flags.push('keepalive'); + !options.nodns && flags.push('dnscache'); + if (options.persistentcookies) { + flags.push('cookies'); + cookies2 = {}; + } else + cookies2 = null; + }; + + instance.on('options', instance.reconfigure); + instance.reconfigure(); +}; \ No newline at end of file diff --git a/RVO47/flow/httpresponse.js b/RVO47/flow/httpresponse.js new file mode 100755 index 0000000..160a3bb --- /dev/null +++ b/RVO47/flow/httpresponse.js @@ -0,0 +1,76 @@ +exports.id = 'httpresponse'; +exports.title = 'HTTP Response'; +exports.group = 'HTTP'; +exports.color = '#5D9CEC'; +exports.icon = 'arrow-right'; +exports.input = true; +exports.output = ['#666D76']; +exports.version = '2.0.0'; +exports.author = 'Martin Smola'; +exports.readme = `# HTTP response + +HTTP response will respond with data recieved using data-type set in Settings form or plain text if not set. Output is the message duration \`Number\` in seconds.`; + +exports.html = `
+
@(Response data-type)
+
JSON is by default.
+
`; + +exports.install = function(instance) { + + var dursum = 0; + var durcount = 0; + + instance.on('data', function(flowdata) { + + var ctrl = flowdata.repository.controller; + var data = flowdata.data; + + if (!ctrl) { + instance.throw('No controller to use for response!'); + return; + } + + durcount++; + dursum += ((new Date() - flowdata.begin) / 1000).floor(2); + setTimeout2(instance.id, instance.custom.duration, 500, 10); + + ctrl.$flowdata = flowdata; + + var datatype = instance.options.datatype || 'json'; + if (datatype === 'emptyresponse') + return ctrl.plain(''); + + if (datatype !== 'json' && typeof(data) !== 'string') { + instance.throw('Incorect type of data, expected string, got ' + typeof(data)); + ctrl.plain(data == null ? '' : data.toString()); + return; + } + + switch(datatype) { + case 'html': + ctrl.content(data, 'text/html'); + break; + case 'plain': + ctrl.plain(data); + break; + case 'xml': + ctrl.content(data, 'text/xml'); + break; + default: + ctrl.json(data); + break; + } + }); + + instance.on('service', function() { + dursum = 0; + durcount = 0; + }); + + instance.custom.duration = function() { + var avg = (dursum / durcount).floor(2); + instance.status(avg + ' sec.'); + instance.send2(0, avg); + }; +}; diff --git a/RVO47/flow/httproute.js b/RVO47/flow/httproute.js new file mode 100755 index 0000000..583a19d --- /dev/null +++ b/RVO47/flow/httproute.js @@ -0,0 +1,326 @@ +exports.id = 'httproute'; +exports.title = 'HTTP Route'; +exports.group = 'HTTP'; +exports.color = '#5D9CEC'; +exports.icon = 'globe'; +exports.input = false; +exports.output = ['#6CAC5A', '#37BC9B']; +exports.version = '1.2.3'; +exports.author = 'Martin Smola'; +exports.cloning = false; +exports.options = { method: 'GET', url: '', size: 5, cacheexpire: '5 minutes', cachepolicy: 0, timeout: 5 }; +exports.dateupdated = '2021-01-21 18:30d'; +exports.readme = `# HTTP route + +__Outputs__: +- first output: raw data (cache is empty or is disabled) +- second output: cached data + +If one of the outputs is disabled then automatic responce with code "503 service unavailable" is sent. + +When a request comes in bellow object is available at \`flowdata.data\`: + +\`\`\`javascript +{ + params: { id: '1' }, // params for dynamic routes, e.g. /test/{id} + query: { msg: 'Hello' }, // parsed query string, e.g. /test/1?msg=Hello + body: { test: 'OK' }, // object if json requests otherwise string + headers: {}, // headers data + session: {}, // session data + user: {}, // user data + files: [], // uploaded files + url: '/users/', // a relative URL address + referrer: '/', // referrer + mobile: false, // determines mobile device + robot: false, // determines search robots/crawlsers + language: 'en' // determines language +} +\`\`\` + +See [documentation for flags](https://docs.totaljs.com/latest/en.html#api~HttpRouteOptionsFlags~unauthorize). These method flags are set automatically e.g. \`get, post, put, patch or delete\` + +--- + +\`id:ROUTE_ID\` flag cannot be used since it's already used by this component internally`; + +exports.html = `
+
+ +
+ +
+
+
@(HTTP method)
+
+
+
@(URL address)
+
+
+
+
+
@(Additional flags)
+
@(Separate flags by comma e.g. json, authorize)
+
+
+
@(Max. request size)
+
@(In kB kilobytes)
+
+
+
@(Timeout)
+
@(In seconds.)
+
+
+
+
+
+
@(Automatically respond with 200 OK?)
+
@(If not checked you need to use HTTP response component to respond to the request.)
+
+
@(Custom headers)
+
@(Cookies)
+
+
+
+
+
+
@(Cache policy)
+
@(User instance must contain id property.)
+
+
+
@(Expiration)
+
@(E.g. 5 minutes)
+
+
+
+`; + +exports.install = function(instance) { + + var route; + + var uninstall = function(id) { + if (F.is4) { + route && route.remove(); + route = null; + } else + UNINSTALL('route', id); + }; + + instance.custom.emptyresponse = function(self) { + self.plain(); + }; + + instance.reconfigure = function() { + + var options = instance.options; + + if (!options.url) { + instance.status('Not configured', 'red'); + return; + } + + if (typeof(options.flags) === 'string') + options.flags = options.flags.split(',').trim(); + + uninstall('id:' + instance.id); + + var flags = options.flags || []; + + flags.push('id:' + instance.id); + + if (!F.is4) + flags.push(options.method.toLowerCase()); + + options.timeout && flags.push(options.timeout * 1000); + + // Make unique values + flags = flags.filter(function(v, i, a) { + if(F.is4 && v.toString().toLowerCase() === options.method.toLowerCase()) + return false; // remove method + return a.indexOf(v) === i; + }); + + options.flags = flags; + var handler = function() { + + if (instance.paused || (instance.isDisabled && (instance.isDisabled('output', 0) || instance.isDisabled('output', 1)))) { + instance.status('503 Service Unavailable'); + this.status = 503; + this.json(); + return; + } + + var key; + var self = this; + + if (instance.options.emptyresponse) { + instance.status('200 OK'); + setTimeout(instance.custom.emptyresponse, 100, self); + + if (instance.hasConnection(0)) { + var data = instance.make({ + query: self.query, + body: self.body, + session: self.session, + user: self.user, + files: self.files, + headers: self.req.headers, + url: self.url, + params: self.params + }); + instance.send2(0, data); + } + + return; + } + + switch (instance.options.cachepolicy) { + case 1: // URL + key = 'rro' + instance.id + self.url.hash(); + break; + case 2: // URL + query + case 3: // URL + query + user + key = self.url; + var keys = Object.keys(self.query); + keys.sort(); + for (var i = 0, length = keys.length; i < length; i++) + key += keys[i] + self.query[keys[i]] + '&'; + if (instance.options.cachepolicy === 3 && self.user) + key += 'iduser' + self.user.id; + key = 'rro' + instance.id + key.hash(); + break; + } + + if (key && F.cache.get2(key)) { + var data = instance.make(F.cache.get2(key)); + data.repository.controller = self; + instance.send2(1, data); + } else { + + var data = instance.make({ + query: self.query, + body: self.body, + session: self.session, + user: self.user, + files: self.files, + headers: self.req.headers, + url: self.url, + params: self.params, + mobile: self.mobile, + robot: self.robot, + referrer: self.referrer, + language: self.language + }); + + data.repository.controller = self; + instance.send2(0, data); + key && FINISHED(self.res, () => F.cache.set(key, self.$flowdata.data, instance.options.cacheexpire)); + } + }; + + if (F.is4) + route = ROUTE(options.method.toUpperCase() + ' ' + options.url, handler, flags, options.size || 5); + else + F.route(options.url, handler, flags, options.size || 5); + + instance.status('Listening', 'green'); + }; + + instance.reconfigure(); + instance.on('options', instance.reconfigure); + instance.on('close', function(){ + uninstall('id:' + instance.id); + }); +}; + +// check url exists +FLOW.trigger('httproutecheckurl', function(next, data) { + var url = data.url; + var method = data.method; + if (url[url.length - 1] !== '/') + url += '/'; + var exists = F.routes.web.findItem(r => r.urlraw === url && r.method === method); + next(exists != null); +}); + +exports.uninstall = function() { + FLOW.trigger('httproutecheckurl', null); +}; diff --git a/RVO47/flow/infosender.js b/RVO47/flow/infosender.js new file mode 100755 index 0000000..587724f --- /dev/null +++ b/RVO47/flow/infosender.js @@ -0,0 +1,81 @@ +exports.id = 'infosender'; +exports.title = 'Info sender'; +exports.version = '1.0.0'; +exports.group = 'Worksys'; +exports.color = '#2134B0'; +exports.input = 2; +exports.output = 1 +exports.icon = 'bolt'; + +const { networkInterfaces } = require('os'); + +exports.html = `
+
+
+
CSV Import
+
+
+
`; + +exports.readme = `# send all data to projects.worksys.io, required to monitor status of controller(unipi)`; + +exports.install = function(instance) { + + let id; + let allValues = {}; + let sendAllValuesInterval; + let configured = false; + + let now = new Date(); + console.log(exports.title, "INSTALLED", now.toLocaleString("sk-SK")); + + const nets = networkInterfaces(); + let ipAddresses = Object.create(null); // Or just '{}', an empty object + + for (const name of Object.keys(nets)) { + for (const net of nets[name]) { + // Skip over non-IPv4 and internal (i.e. 127.0.0.1) addresses + if (net.family === 'IPv4' && !net.internal) { + if (!ipAddresses[name]) { + ipAddresses[name] = []; + } + ipAddresses[name].push(net.address); + } + } + } + + function sendValues() { + if (!configured) return; + + if (Object.keys(allValues).length > 0) { + let dataToSend = { ...allValues }; + dataToSend.id = id; + dataToSend.ipAddresses = ipAddresses; + + instance.send(0, dataToSend); + + allValues = {}; + } + } + + instance.on("close", () => { + clearInterval(sendAllValuesInterval); + }) + + instance.on("0", _ => { + id = FLOW.GLOBALS.settings.project_id; + if (id) configured = true; + else console.log(exports.title, "InfoSender: Unable to send data, no id"); + }) + + instance.on("1", flowdata => { + allValues = { ...allValues, ...flowdata.data }; + //console.log("DATA RECEIVED", flowdata.data); + }) + + sendAllValuesInterval = setInterval(() => { + sendValues(); + }, 60000 * 3); + +} + diff --git a/RVO47/flow/modbus_reader.js b/RVO47/flow/modbus_reader.js new file mode 100755 index 0000000..d6d9dad --- /dev/null +++ b/RVO47/flow/modbus_reader.js @@ -0,0 +1,346 @@ +exports.id = 'modbus_reader'; +exports.title = 'Modbus reader'; +exports.version = '2.0.0'; +exports.group = 'Worksys'; +exports.color = '#2134B0'; +exports.input = 1; +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; +//number of phases inRVO +let phases; +//phases where voltage is 0 (set) +let noVoltage; +let energyToSwitchLamps; + +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.phases = this.buildPhases(); + + this.startSocket(); + } + + buildPhases = () => { + let a = []; + for (let i = 1; i <= phases; i++) { + a.push(`Phase_${i}_voltage`) + } + return a; + } + + startSocket = () => { + + let obj = this; + + if (this.socket) { + this.socket.removeAllListeners(); + this.socket = null; + } + + 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('Modbus_reader: Socket connection error', e); //'ECONNREFUSED' or 'ECONNRESET' ?? + }); + + this.socket.on('close', function() { + console.log('Modbus_reader: Socket connection closed - Waiting 10 seconds before connecting 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 we just start to loop devices from the beginning, or there is just 1 device in config, we wait whole timeoutInterval + if (this.indexInDeviceConfig == 0 || deviceConfig.length === 1) 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 (this.phases.includes(singleValue)) { + let l = singleValue.split("_"); + let phase = parseInt(l[1]); + + // console.log(values[singleValue], tbName); + + if (values[singleValue] == 0) { + noVoltage.add(phase); + sendNotification("modbus_reader: checkNullVoltage", tbName, "no_voltage_on_phase", { phase: phase }, "", SEND_TO.tb, instance, "voltage" + phase); + // console.log('no voltage') + } + else { + noVoltage.delete(phase); + // console.log('voltage detected') + sendNotification("modbus_reader: checkNullVoltage", tbName, "voltage_on_phase_restored", { phase: phase }, "", SEND_TO.tb, instance, "voltage" + phase); + } + } + }) + } + + /** + * function sends notification to slack and to tb, if EM total_power value changes more than numberOfNodes*15. This should show, that RVO lamps has been switched on or off + */ + lampSwitchNotification = (values) => { + + if (!values.hasOwnProperty("total_power")) return; + + const actualTotalPower = values.total_power; + + if (actualTotalPower > energyToSwitchLamps && 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 <= energyToSwitchLamps && 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; + } + + function main() { + + phases = FLOW.GLOBALS.settings.phases; + tbName = FLOW.GLOBALS.settings.rvoTbName; + noVoltage = FLOW.GLOBALS.settings.no_voltage; + energyToSwitchLamps = FLOW.GLOBALS.settings.energy_to_switch_lamps / 2.5; //half value is enought to show if lamps are turned on or off + if (deviceConfig.length) mainSocket = new SocketWithClients(); + else console.log("Modbus_reader: no modbus device in configuration"); + + // this notification is to show, that flow (unipi) has been restarted + sendNotification("modbus_reader", tbName, "flow_restart", {}, "", SEND_TO.slack, instance); + } + + instance.on("0", function(_) { + main(); + }) + +} + diff --git a/RVO47/flow/monitorconsumption.js b/RVO47/flow/monitorconsumption.js new file mode 100755 index 0000000..64cc58e --- /dev/null +++ b/RVO47/flow/monitorconsumption.js @@ -0,0 +1,156 @@ +exports.id = 'monitorconsumption'; +exports.title = 'Consumption'; +exports.version = '1.0.0'; +exports.author = 'Peter Širka'; +exports.group = 'Monitoring'; +exports.color = '#967ADC'; +exports.input = 0; +exports.output = 1; +exports.icon = 'bug'; +exports.options = { interval: 5000, enabled: true, monitorconsumption: true, monitorsize: true, monitorconnections: true, monitorfiles: true }; +exports.click = true; +exports.readme = `# Consumption monitoring + +This component measure CPU and memory consumption, open files and open connections of this application. It uses these Linux commands: \`ps\`, \`lsof\`, \`netstat\` and \`df\`. + +__Data Example__: + +\`\`\`javascript +{ + cpu: 0, // percentage + memory: 4096, // in bytes + size: 34303, // directory size in bytes + files: 34, // count of open files + connections: 343, // count of connections + uptime: '1-12:34:00' +} +\`\`\``; + +exports.html = `
+
+
+
@(Interval in milliseconds)
+
+
+
+
Monitor: Consumption + uptime
+
Monitor: Count of open files
+
Monitor: Count of open connections
+
Monitor: Directory size
+
`; + +exports.install = function(instance) { + + var current = { cpu: 0, memory: 0, files: 0, connections: 0, size: 0, uptime: '', counter: 0 }; + var tproc = null; + var Exec = require('child_process').exec; + var reg_empty = /\s{2,}/g; + var reg_appdisksize = /^[\d.,]+/; + + instance.custom.run = function() { + + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + + var arr = []; + + // Get CPU and Memory consumption + instance.options.monitorconsumption && arr.push(function(next) { + Exec('ps -p {0} -o %cpu,rss,etime'.format(process.pid), function(err, response) { + + if (err) { + instance.throw(err); + } else { + var line = response.split('\n')[1]; + line = line.trim().replace(reg_empty, ' ').split(' '); + var cpu = line[0].parseFloat(); + current.cpu = cpu.floor(1); + current.memory = line[1].parseInt2() * 1024; // kB to bytes + current.uptime = line[2]; + } + + next(); + }); + }); + + // Get count of open files + instance.options.monitorfiles && arr.push(function(next) { + Exec('lsof -a -p {0} | wc -l'.format(process.pid), function(err, response) { + if (err) + instance.throw(err); + else + current.files = response.trim().parseInt2(); + next(); + }); + }); + + // Get count of opened network connections + instance.options.monitorconnections && arr.push(function(next) { + Exec('netstat -an | grep :{0} | wc -l'.format(F.port), function(err, response) { + if (err) { + instance.throw(err); + } else { + current.connections = response.trim().parseInt2() - 1; + if (current.connections < 0) + current.connections = 0; + } + next(); + }); + }); + + // Get directory size + instance.options.monitorsize && current.counter % 5 !== 0 && arr.push(function(next) { + Exec('du -hsb ' + process.cwd(), function(err, response) { + if (err) { + instance.throw(err); + } else { + var match = response.trim().match(reg_appdisksize); + match && (current.size = match.toString().trim().parseInt2()); + } + next(); + }); + }); + + arr.async(function() { + + tproc && clearTimeout(tproc); + + if (instance.options.enabled) { + tproc = setTimeout(instance.custom.run, instance.options.interval); + instance.send2(current); + } + + instance.custom.status(); + current.counter++; + }); + }; + + instance.custom.status = function() { + if (instance.options.enabled) + instance.status('{0}% / {1}'.format(current.cpu, current.memory.filesize())); + else + instance.status('Disabled', 'red'); + }; + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + + if (instance.options.enabled) { + current.counter = 0; + instance.custom.run(); + } + + }); + + instance.on('close', function() { + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + }); + + setTimeout(instance.custom.run, 1000); +}; \ No newline at end of file diff --git a/RVO47/flow/monitordisk.js b/RVO47/flow/monitordisk.js new file mode 100755 index 0000000..f4fdaa0 --- /dev/null +++ b/RVO47/flow/monitordisk.js @@ -0,0 +1,96 @@ +exports.id = 'monitordisk'; +exports.title = 'Disk'; +exports.version = '1.0.0'; +exports.author = 'Peter Širka'; +exports.group = 'Monitoring'; +exports.color = '#F6BB42'; +exports.output = 1; +exports.icon = 'hdd-o'; +exports.click = true; +exports.options = { interval: 8000, path: '/', enabled: true }; +exports.readme = `# Disk monitoring + +This component monitors disk \`bytes\` consumption in Linux systems. It uses \`df\` command. + +__Data Example__: + +\`\`\`javascript +{ + total: 474549649408, + used: 39125245952, + free: 411294994432 +} +\`\`\``; + +exports.html = `
+
+
+
@(Interval in milliseconds)
+
+
+
@(Path)
+
+
+
`; + +exports.install = function(instance) { + + var current = { total: 0, used: 0, free: 0, path: '', type: '', percentUsed: 0 }; + var tproc = null; + + instance.custom.run = function() { + + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + + if (!instance.options.enabled) + return; + + require('child_process').exec('df -hTB1 ' + instance.options.path, function(err, response) { + + tproc = setTimeout(instance.custom.run, instance.options.interval); + + if (err) { + instance.error(err); + return; + } + + response.parseTerminal(function(line) { + if (line[0][0] !== '/') + return; + current.total = line[2].parseInt(); + current.free = line[4].parseInt(); + current.used = line[3].parseInt(); + current.path = instance.options.path || '/'; + current.type = line[1]; + current.percentUsed = line[5]; + instance.custom.status(); + instance.send2(current); + }); + }); + }; + + instance.custom.status = function() { + if (instance.options.enabled) + instance.status(current.free.filesize() + ' / ' + current.total.filesize()); + else + instance.status('Disabled', 'red'); + }; + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + instance.options.enabled && instance.custom.run(); + }); + + instance.on('close', function() { + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + }); + + setTimeout(instance.custom.run, 1000); +}; \ No newline at end of file diff --git a/RVO47/flow/monitormemory.js b/RVO47/flow/monitormemory.js new file mode 100755 index 0000000..2decbc4 --- /dev/null +++ b/RVO47/flow/monitormemory.js @@ -0,0 +1,87 @@ +exports.id = 'monitormemory'; +exports.title = 'Memory'; +exports.version = '1.0.0'; +exports.author = 'Peter Širka'; +exports.group = 'Monitoring'; +exports.color = '#F6BB42'; +exports.output = 1; +exports.click = true; +exports.icon = 'microchip'; +exports.options = { interval: 8000, enabled: true }; +exports.readme = `# Memory monitoring + +This component monitors memory \`bytes\` consumption in Linux systems. It uses \`free\` command. + +__Data Example__: + +\`\`\`javascript +{ + total: 33558769664, + used: 1998868480, + free: 2653708288 +} +\`\`\``; + +exports.html = `
+
+
+
@(Interval in milliseconds)
+
+
+
`; + +exports.install = function(instance) { + + var current = { total: 0, used: 0, free: 0 }; + var tproc = null; + + instance.custom.run = function() { + + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + + if (!instance.options.enabled) + return; + + require('child_process').exec('free -b -t', function(err, response) { + + tproc = setTimeout(instance.custom.run, instance.options.interval); + + if (err) { + instance.error(err); + return; + } + + var memory = response.split('\n')[1].match(/\d+/g); + current.total = memory[0].parseInt(); + current.used = memory[1].parseInt() - memory[3].parseInt(); + current.free = current.total - current.used; + instance.custom.status(); + instance.send2(current); + }); + }; + + instance.custom.status = function() { + if (instance.options.enabled) + instance.status(current.free.filesize() + ' / ' + current.total.filesize()); + else + instance.status('Disabled', 'red'); + }; + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + instance.options.enabled && instance.custom.run(); + }); + + instance.on('close', function() { + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + }); + + setTimeout(instance.custom.run, 1000); +}; \ No newline at end of file diff --git a/RVO47/flow/nodesdb_changecheck.js b/RVO47/flow/nodesdb_changecheck.js new file mode 100755 index 0000000..9adab62 --- /dev/null +++ b/RVO47/flow/nodesdb_changecheck.js @@ -0,0 +1,77 @@ +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 = 2; +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); + } + } + + //kedze do slacku posielame stringy, na cloud musime previest vsetky stringy spat na objekty: + // Funkcia na parsovanie všetkých reťazcov v poli + const parseArray = (arr) => { + return arr.map(jsonString => JSON.parse(jsonString)); + }; + + 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); + if (FLOW.GLOBALS.settings.send_changed_node_numbers) instance.send(1, { aktualneNody: parseArray(zmenene), originalne: parseArray(Array.from(set2)) }); + } + 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/RVO47/flow/show_dbdata.js b/RVO47/flow/show_dbdata.js new file mode 100755 index 0000000..1e23ff7 --- /dev/null +++ b/RVO47/flow/show_dbdata.js @@ -0,0 +1,243 @@ +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 = 8; +exports.output = 1; + +const { exec } = require('child_process'); + +exports.install = 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 }) + }) + instance.on("5", _ => { + exec("sudo tail -n 25 monitor.txt", (err, stdout, stderr) => { + if (err || stderr) instance.send(0, { err, stderr }); + else instance.send(0, stdout); + }) + }) + instance.on("6", _ => { + exec("sudo tail -n 25 err.txt", (err, stdout, stderr) => { + if (err || stderr) instance.send(0, { err, stderr }); + else instance.send(0, stdout); + }) + }) + instance.on("7", _ => { + instance.send(0, FLOW.deviceStatus); + }) +}; + + +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/RVO47/flow/slack_filter.js b/RVO47/flow/slack_filter.js new file mode 100755 index 0000000..6618523 --- /dev/null +++ b/RVO47/flow/slack_filter.js @@ -0,0 +1,188 @@ +exports.id = 'slack_filter'; +exports.title = 'Slack Filter'; +exports.group = 'Citysys'; +exports.color = '#30E193'; +exports.input = 2; +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 = `
+
+
+
@(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('0', 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']['en']; + 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"] = []; + } + + instance.options.name = FLOW.GLOBALS.settings.rvo_name; + if (instance.options.name) { + instance.status('Running'); + running = true; + } else { + instance.status('Please run options again', 'red'); + running = false; + } + } catch (e) { + instance.error('Citysys connector: ' + e.message); + } + }; + + instance.on('options', instance.reconfigure); + + instance.on("1", _ => { + instance.reconfigure(); + }) +}; diff --git a/RVO47/flow/thermometer.js b/RVO47/flow/thermometer.js new file mode 100755 index 0000000..fc7074d --- /dev/null +++ b/RVO47/flow/thermometer.js @@ -0,0 +1,99 @@ +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 = 5;//minutes +let NUMBER_OF_FAILURES_TO_SEND_ERROR = 13; + +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) => { + + 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); + setTimeout(main, 20000); + }) +}; diff --git a/RVO47/flow/trigger.js b/RVO47/flow/trigger.js new file mode 100755 index 0000000..27545a8 --- /dev/null +++ b/RVO47/flow/trigger.js @@ -0,0 +1,79 @@ +exports.id = 'trigger'; +exports.title = 'Trigger'; +exports.group = 'Inputs'; +exports.color = '#F6BB42'; +exports.click = true; +exports.output = 1; +exports.version = '1.1.0'; +exports.author = 'Martin Smola'; +exports.icon = 'play'; + +exports.html = `
+
@(Data type (String by default))
+
@(Data)
+
Trigger 5s after initialization.
+
@(Useful when there's a need to run certain flow when the app restarts, etc.)
+
`; + +exports.readme = `# Trigger + +- Clicking on the component starts the chain +- Settings allows to set a data-type and a value`; + +exports.install = function(instance) { + + var value; + + instance.on('click', () => instance.send2(value)); + + instance.reconfigure = function() { + var options = instance.options; + value = null; + switch (options.datatype) { + case 'integer': + value = options.data.parseInt2('error'); + value = value === 'error' ? NaN : value; + break; + case 'float': + value = options.data.parseFloat2('error'); + value = value === 'error' ? NaN : value; + break; + case 'date': + options.data = options.data.toString(); + var num = options.data.parseInt('error'); + num === 'error' && (num = options.data.parseDate('error')); + num === 'error' && (num = null); + value = num ? new Date(num).toUTCString() : num; + break; + case 'object': + try { + value = (new Function('return ' + options.data))(); + } catch (e) { + instance.error(e); + } + break; + case 'boolean': + value = options.data.parseBoolean(); + break; + case 'buffer': + try { + value = U.createBuffer(options.data); + } catch (e) { + instance.error(e); + } + break; + case 'string': + default: + value = '' + (options.data || ''); + break; + } + }; + + instance.on('options', instance.reconfigure); + instance.reconfigure(); + + if (instance.options.restart) + setTimeout(function(){ + instance.send2(value); + }, 5000); +}; diff --git a/RVO47/flow/variables.txt b/RVO47/flow/variables.txt new file mode 100755 index 0000000..e69de29 diff --git a/RVO47/flow/virtualwirein.js b/RVO47/flow/virtualwirein.js new file mode 100755 index 0000000..38a4e42 --- /dev/null +++ b/RVO47/flow/virtualwirein.js @@ -0,0 +1,43 @@ +exports.id = 'virtualwirein'; +exports.title = 'Virtual wire in'; +exports.version = '1.0.0'; +exports.author = 'Martin Smola'; +exports.color = '#303E4D'; +exports.icon = 'sign-in'; +exports.input = false; +exports.output = 1; +exports.options = {}; +exports.readme = `# Virtual wire in + +When the wires between the components are mess it's time to use Virtual wire.`; + +exports.html = `
+
@(Wire name)
+
+`; + +exports.install = function(instance) { + + instance.custom.reconfigure = function(options){ + if (instance.options.wirename) { + instance.status(instance.options.wirename); + } else + instance.status('Not configured', 'red'); + }; + + ON('virtualwire', function(wirename, flowdata){ + if (instance.options.wirename && instance.options.wirename === wirename) + instance.send(flowdata); + }); + + instance.on('options', instance.custom.reconfigure); + instance.custom.reconfigure(); +}; diff --git a/RVO47/flow/virtualwireout.js b/RVO47/flow/virtualwireout.js new file mode 100755 index 0000000..94a1e4f --- /dev/null +++ b/RVO47/flow/virtualwireout.js @@ -0,0 +1,41 @@ +exports.id = 'virtualwireout'; +exports.title = 'Virtual wire out'; +exports.version = '1.0.0'; +exports.author = 'Martin Smola'; +exports.color = '#303E4D'; +exports.icon = 'sign-out'; +exports.input = true; +exports.options = {}; +exports.readme = `# Virtual wire out + +When the wires between the components are mess it's time to use Virtual wire.`; + +exports.html = `
+
@(Wire name)
+
+`; + +exports.install = function(instance) { + + instance.custom.reconfigure = function(){ + if (instance.options.wirename) { + instance.status(instance.options.wirename); + } else + instance.status('Not configured', 'red'); + }; + + instance.on('data', function(flowdata) { + EMIT('virtualwire', instance.options.wirename, flowdata); + }); + + instance.on('options', instance.custom.reconfigure); + instance.custom.reconfigure(); +}; diff --git a/RVO47/flow/wsmqttpublish.js b/RVO47/flow/wsmqttpublish.js new file mode 100755 index 0000000..0eba804 --- /dev/null +++ b/RVO47/flow/wsmqttpublish.js @@ -0,0 +1,448 @@ +exports.id = 'wsmqttpublish'; +exports.title = 'WS MQTT publish'; +exports.group = 'MQTT'; +exports.color = '#888600'; +exports.version = '1.0.2'; +exports.icon = 'sign-out'; +exports.input = 2; +exports.output = 3; +exports.options = { host: 'tb-stage.worksys.io', port: 1883, clientid: "", username: "" }; + +exports.html = `
+
+
+
Hostname or IP address (if not empty - setting will override db setting)
+
+
+
Port
+
+
+
+
+
@(Client id)
+
+
+
@(Username)
+
+
+
`; + + +exports.readme = ` +# WS MQTT Publish + +Version 1.0.3. + +Added: +- database collections, +- 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 = { + debug: 0, + rpcCall: 1, + services: 2 +} + +//CONFIG +let createTelemetryBackup = true; +let saveTelemetryOnError = true;//backup_on_failure overrides this value +//------------------------ + +let rollers; +if (createTelemetryBackup) rollers = require('streamroller'); + +const noSqlFileSizeLimit = 4194304;//use 5MB - 4194304 +let insertNoSqlCounter = 0; +let insertBackupNoSqlCounter = 0; +let processingData = false; + +let backup_on_failure = false;//== saveTelemetryOnError - create backup client 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; + +process.on('uncaughtException', function(err) { + + errLogger.error('uncaughtException:', err.message) + errLogger.error(err.stack); + + //TODO + //send to service + + //process.exit(1); +}) + +const nosql = NOSQL('tbdata'); +const nosqlBackup = NOSQL('/backup/tbdata'); + + +exports.install = function(instance) { + + var client; + var opts; + var clientReady = false; + + // wsmqtt status for notification purposes on projects.worksys.io database + let wsmqttName = null; + let sendWsStatusVar = null; + let wsmqtt_status = 'disconnected'; + + 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'; + } + + function sendWsStatus() { + instance.send(SEND_TO.services, { [wsmqttName]: wsmqtt_status }); + } + + + function main() { + if (!FLOW.dbLoaded) return; + + loadSettings(); + clearInterval(sendWsStatus); + sendWsStatusVar = setInterval(sendWsStatus, 180000); + } + + //set opts according to db settings + function loadSettings() { + + if (instance.options.host !== "") { + //override settings from database + var o = instance.options; + opts = { + host: o.host, + port: o.port, + clientId: o.clientid, + username: o.username, + rejectUnauthorized: false, + resubscribe: false + }; + + wsmqttName = getWsmqttName(o.host); + + console.log("wsmqttpublich -> loadSettings from instance.options", instance.options); + } + else { + + const SETTINGS = FLOW.GLOBALS.settings; + backup_on_failure = SETTINGS.backup_on_failure; + saveTelemetryOnError = backup_on_failure; + + restore_from_backup = SETTINGS.restore_from_backup; + restore_backup_wait = SETTINGS.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; + + opts = { + host: mqtt_host, + port: mqtt_port, + keepalive: 10, + clientId: mqtt_clientid, + username: mqtt_username, + rejectUnauthorized: false, + resubscribe: false + }; + + wsmqttName = getWsmqttName(mqtt_host); + } + + connectToTbServer(); + } + + function connectToTbServer() { + 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"); + //monitor.info("MQTT client connected"); + + sendClientError = true; + clientReady = true; + wsmqtt_status = 'connected'; + }); + + client.on('reconnect', function() { + instance.status("Reconnecting", "yellow"); + clientReady = false; + }); + + client.on('message', function(topic, message) { + // message is type of buffer + message = message.toString(); + if (message[0] === '{') { + TRY(function() { + + message = JSON.parse(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 } }); + } + + }, () => instance.debug('MQTT: Error parsing data', message)); + } + + instance.send(SEND_TO.rpcCall, { "topic": topic, "content": message }); + }); + + client.on('close', function() { + clientReady = false; + wsmqtt_status = 'disconnected'; + + instance.status("Disconnected", "red"); + instance.send(SEND_TO.debug, { "message": "Client CLOSE signal received !" }); + }); + + client.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; + wsmqtt_status = 'disconnected'; + }); + + } + + + instance.on("0", _ => { + main(); + }) + + + instance.on('1', function(data) { + + if (clientReady) { + //do we have some data in backup file? if any, process data from database + if (saveTelemetryOnError) { + //read telemetry data and send back to server + if (!processingData) processDataFromDatabase(); + } + + let stringifiedJson = JSON.stringify(data.data); + client.publish("v1/gateway/telemetry", stringifiedJson, { qos: 1 }); + + //backup telemetry + if (createTelemetryBackup) { + data.data.id = UID(); + nosqlBackup.insert(data.data); + + insertBackupNoSqlCounter++; + if (insertBackupNoSqlCounter > 150) { + let options = { compress: true }; + let path = __dirname + "/../databases/backup/tbdata.nosql"; + var stream = new rollers.RollingFileStream(path, noSqlFileSizeLimit, 150, options); + stream.write(""); + stream.end(); + + insertBackupNoSqlCounter = 0; + } + } + + } + 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 (saveTelemetryOnError) { + //create new file from tbdata.nosql, if file size exceeds given limit, and clear tbdata.nosql + makeBackupFromDbFile(); + + //write to tb + data.data.id = UID(); + nosql.insert(data.data); + } + } + }); + + + instance.close = function(done) { + if (clientReady) { + client.end(); + clearInterval(sendWsStatusVar); + } + }; + + + function getDbBackupFileCounter(type) { + var files = fs.readdirSync(__dirname + "/../databases"); + + let counter = 0; + for (var i = 0; i < files.length; i++) { + + if (files[i] == "tbdata.nosql") continue; + + if (files[i].endsWith(".nosql")) { + + let pos = files[i].indexOf("."); + if (pos > -1) { + + let fileCounter = counter; + let firstDigit = files[i].slice(0, pos); + + fileCounter = parseInt(firstDigit); + if (isNaN(fileCounter)) fileCounter = 0; + //console.log("getDbBackupFileCounter digit:", files[i], firstDigit, fileCounter, isNaN(fileCounter), type); + + if (type == "max") { + if (fileCounter > counter) { + counter = fileCounter; + } + } + else if (type == "min") { + if (counter == 0) counter = fileCounter; + + if (fileCounter < counter) { + counter = fileCounter; + } + } + } + } + + } + + if (type == "max") counter++; + + return counter; + } + + const makeBackupFromDbFile = async () => { + + if (!saveTelemetryOnError) return; + + //to avoid large file: tbdata.nosql + + //init value is 0! + if (insertNoSqlCounter > 0) { + --insertNoSqlCounter; + return; + } + + insertNoSqlCounter = 100; + + let source = __dirname + "/../databases/tbdata.nosql"; + + var stats = fs.statSync(source); + var fileSizeInBytes = stats.size; + + if (fileSizeInBytes > noSqlFileSizeLimit) { + + let counter = 1; + counter = getDbBackupFileCounter("max"); + + let destination = __dirname + "/../databases/" + counter + "." + "tbdata.nosql"; + + //make backup file + fs.copyFileSync(source, destination); + //fs.renameSync(p, p + "." + counter); + + //clear tbdata.nosql + fs.writeFileSync(source, ""); + fs.truncateSync(source, 0); + + } + } + + const processDataFromDatabase = async () => { + + if (restore_from_backup <= 0) return; + + //calculate diff + const now = new Date(); + let currentTime = now.getTime(); + let diff = currentTime - lastRestoreTime; + + if ((diff / 1000) < restore_backup_wait) { + //console.log("*********restore_backup_wait", diff, restore_backup_wait); + return; + } + + processingData = true; + + //get filename to process + let counter = getDbBackupFileCounter("min"); + + //we have some backup files + let dataBase = 'tbdata'; + + var nosql; + if (counter == 0) dataBase = 'tbdata'; + else dataBase = counter + "." + 'tbdata'; + + nosql = NOSQL(dataBase); + + //select all data - use limit restore_from_backup + let records = await promisifyBuilder(nosql.find().take(restore_from_backup)); + + for (let i = 0; i < records.length; i++) { + if (clientReady) { + + let item = records[i]; + let id = item.id; + + if (id !== undefined) { + //console.log("------------processDataFromDatabase - remove", id, dataBase, i); + + try { + + let message = JSON.parse(JSON.stringify(item)); + delete message.id; + + client.publish("v1/gateway/telemetry", JSON.stringify(message), { qos: 1 }); + + //remove from database + await promisifyBuilder(nosql.remove().where("id", id)); + + } catch (error) { + //process error + console.log("processDataFromDatabase", error); + } + + } + + } + else { + processingData = false; + return; + } + } + + if (records.length > 0) { + //clean backup file + if (counter > 0) nosql.clean(); + } + + //no data in db, remove + if (records.length == 0) { + if (counter > 0) nosql.drop(); + } + + const d = new Date(); + lastRestoreTime = d.getTime(); + + processingData = false; + + } + + instance.on('options', main); + //instance.reconfigure(); +}; diff --git a/RVO47/monitor.txt b/RVO47/monitor.txt new file mode 100755 index 0000000..e070673 --- /dev/null +++ b/RVO47/monitor.txt @@ -0,0 +1,2568 @@ +[2025-05-17T18:51:24.192] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-05-17T18:51:29.544] [INFO] monitorLogs - buildTasks - params undefined +[2025-05-17T18:51:29.548] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-05-17T18:51:29.549] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-05-17T18:51:29.550] [INFO] monitorLogs - profile: { + 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: 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 +} +[2025-05-17T18:51:29.554] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-05-17T18:51:29.555] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 1 2025-05-18T03:08:00.555Z +[2025-05-17T18:51:29.557] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 1 2025-05-17T18:28:00.556Z +[2025-05-17T18:51:29.558] [INFO] monitorLogs - -->time_points final 1 [ + { start_time: '05:08', value: 0, name: 'dawn' }, + { start_time: '20:28', value: 1, name: 'dusk' } +] +[2025-05-17T18:51:29.559] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-05-17T18:51:29.560] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-05-17T18:51:29.560] [INFO] monitorLogs - profile: { + 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: 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 +} +[2025-05-17T18:51:29.562] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-05-17T18:51:29.563] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 2 2025-05-18T03:08:00.563Z +[2025-05-17T18:51:29.564] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 2 2025-05-17T18:28:00.564Z +[2025-05-17T18:51:29.565] [INFO] monitorLogs - -->time_points final 2 [ + { start_time: '05:08', value: 0, name: 'dawn' }, + { start_time: '20:28', value: 1, name: 'dusk' } +] +[2025-05-17T18:51:29.566] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-05-17T18:51:29.567] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-05-17T18:51:29.567] [INFO] monitorLogs - profile: { + 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: 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 +} +[2025-05-17T18:51:29.569] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-05-17T18:51:29.570] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 3 2025-05-18T03:08:00.570Z +[2025-05-17T18:51:29.571] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 3 2025-05-17T18:28:00.571Z +[2025-05-17T18:51:29.571] [INFO] monitorLogs - -->time_points final 3 [ + { start_time: '05:08', value: 0, name: 'dawn' }, + { start_time: '20:28', value: 1, name: 'dusk' } +] +[2025-05-17T18:51:29.572] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-05-17T18:51:29.574] [INFO] monitorLogs - tasks created: 70 +[2025-05-17T18:51:29.576] [INFO] monitorLogs - -->FLOW bol spustený 3JjOWdylwgNLzxVab7NajKkZ2vG64rq8PEB5QmDo 2025-04-24 +[2025-05-17T18:51:34.579] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-05-17T20:28:00.661] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-05-17T20:28:00.965] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-05-17T20:28:01.268] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-05-18T03:51:31.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-18 03:51:31 +[2025-05-18T05:08:00.634] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-05-18T05:08:00.937] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-05-18T05:08:01.239] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-05-18T10:09:51.616] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-05-18T10:09:56.968] [INFO] monitorLogs - buildTasks - params undefined +[2025-05-18T10:09:56.972] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-05-18T10:09:56.974] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-05-18T10:09:56.974] [INFO] monitorLogs - profile: { + 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: 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 +} +[2025-05-18T10:09:56.978] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-05-18T10:09:56.980] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 1 2025-05-19T03:07:00.979Z +[2025-05-18T10:09:56.981] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 1 2025-05-18T18:30:00.981Z +[2025-05-18T10:09:56.982] [INFO] monitorLogs - -->time_points final 1 [ + { start_time: '05:07', value: 0, name: 'dawn' }, + { start_time: '20:30', value: 1, name: 'dusk' } +] +[2025-05-18T10:09:56.983] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-05-18T10:09:56.984] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-05-18T10:09:56.984] [INFO] monitorLogs - profile: { + 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: 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 +} +[2025-05-18T10:09:56.987] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-05-18T10:09:56.988] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 2 2025-05-19T03:07:00.988Z +[2025-05-18T10:09:56.989] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 2 2025-05-18T18:30:00.989Z +[2025-05-18T10:09:56.990] [INFO] monitorLogs - -->time_points final 2 [ + { start_time: '05:07', value: 0, name: 'dawn' }, + { start_time: '20:30', value: 1, name: 'dusk' } +] +[2025-05-18T10:09:56.991] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-05-18T10:09:56.992] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-05-18T10:09:56.992] [INFO] monitorLogs - profile: { + 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: 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 +} +[2025-05-18T10:09:56.995] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-05-18T10:09:56.995] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 3 2025-05-19T03:07:00.995Z +[2025-05-18T10:09:56.996] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 3 2025-05-18T18:30:00.996Z +[2025-05-18T10:09:56.997] [INFO] monitorLogs - -->time_points final 3 [ + { start_time: '05:07', value: 0, name: 'dawn' }, + { start_time: '20:30', value: 1, name: 'dusk' } +] +[2025-05-18T10:09:56.998] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-05-18T10:09:56.999] [INFO] monitorLogs - tasks created: 70 +[2025-05-18T10:09:57.002] [INFO] monitorLogs - -->FLOW bol spustený 3JjOWdylwgNLzxVab7NajKkZ2vG64rq8PEB5QmDo 2025-04-24 +[2025-05-18T10:10:02.006] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-05-18T13:26:23.171] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-05-18T13:26:28.510] [INFO] monitorLogs - buildTasks - params undefined +[2025-05-18T13:26:28.515] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-05-18T13:26:28.516] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-05-18T13:26:28.517] [INFO] monitorLogs - profile: { + 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: 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 +} +[2025-05-18T13:26:28.521] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-05-18T13:26:28.522] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 1 2025-05-19T03:07:00.522Z +[2025-05-18T13:26:28.524] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 1 2025-05-18T18:30:00.523Z +[2025-05-18T13:26:28.524] [INFO] monitorLogs - -->time_points final 1 [ + { start_time: '05:07', value: 0, name: 'dawn' }, + { start_time: '20:30', value: 1, name: 'dusk' } +] +[2025-05-18T13:26:28.526] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-05-18T13:26:28.526] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-05-18T13:26:28.527] [INFO] monitorLogs - profile: { + 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: 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 +} +[2025-05-18T13:26:28.529] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-05-18T13:26:28.530] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 2 2025-05-19T03:07:00.530Z +[2025-05-18T13:26:28.531] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 2 2025-05-18T18:30:00.531Z +[2025-05-18T13:26:28.532] [INFO] monitorLogs - -->time_points final 2 [ + { start_time: '05:07', value: 0, name: 'dawn' }, + { start_time: '20:30', value: 1, name: 'dusk' } +] +[2025-05-18T13:26:28.533] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-05-18T13:26:28.533] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-05-18T13:26:28.534] [INFO] monitorLogs - profile: { + 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: 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 +} +[2025-05-18T13:26:28.536] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-05-18T13:26:28.537] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 3 2025-05-19T03:07:00.536Z +[2025-05-18T13:26:28.537] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 3 2025-05-18T18:30:00.537Z +[2025-05-18T13:26:28.538] [INFO] monitorLogs - -->time_points final 3 [ + { start_time: '05:07', value: 0, name: 'dawn' }, + { start_time: '20:30', value: 1, name: 'dusk' } +] +[2025-05-18T13:26:28.539] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-05-18T13:26:28.541] [INFO] monitorLogs - tasks created: 70 +[2025-05-18T13:26:28.543] [INFO] monitorLogs - -->FLOW bol spustený 3JjOWdylwgNLzxVab7NajKkZ2vG64rq8PEB5QmDo 2025-04-24 +[2025-05-18T13:26:33.552] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-05-18T20:30:00.600] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-05-18T20:30:00.910] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-05-18T20:30:01.213] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-05-19T03:26:30.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-19 03:26:30 +[2025-05-19T05:07:00.664] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-05-19T05:07:00.975] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-05-19T05:07:01.277] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-05-19T20:31:22.158] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-05-19T20:31:22.466] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-05-19T20:31:22.769] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-05-20T03:26:31.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-20 03:26:31 +[2025-05-20T05:05:00.431] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-05-20T05:05:00.737] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-05-20T05:05:01.039] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-05-20T20:32:38.680] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-05-20T20:32:38.990] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-05-20T20:32:39.292] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-05-21T03:26:32.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-21 03:26:32 +[2025-05-21T05:03:53.412] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-05-21T05:03:53.716] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-05-21T05:03:54.019] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-05-21T20:33:54.471] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-05-21T20:33:54.780] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-05-21T20:33:55.082] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-05-22T03:26:33.013] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-22 03:26:33 +[2025-05-22T05:02:48.317] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-05-22T05:02:48.621] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-05-22T05:02:48.923] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-05-22T20:35:08.710] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-05-22T20:35:09.019] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-05-22T20:35:09.322] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-05-23T03:26:34.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-23 03:26:34 +[2025-05-23T05:01:45.684] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-05-23T05:01:45.989] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-05-23T05:01:46.291] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-05-23T20:36:21.890] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-05-23T20:36:22.198] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-05-23T20:36:22.501] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-05-24T03:26:36.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-24 03:26:36 +[2025-05-24T05:00:44.892] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-05-24T05:00:45.197] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-05-24T05:00:45.499] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-05-24T20:37:34.022] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-05-24T20:37:34.331] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-05-24T20:37:34.634] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-05-25T03:26:37.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-25 03:26:37 +[2025-05-25T04:59:46.510] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-05-25T04:59:46.815] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-05-25T04:59:47.118] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-05-25T20:38:44.477] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-05-25T20:38:44.787] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-05-25T20:38:45.089] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-05-26T03:26:38.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-26 03:26:38 +[2025-05-26T04:58:50.549] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-05-26T04:58:50.854] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-05-26T04:58:51.157] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-05-26T20:39:54.104] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-05-26T20:39:54.412] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-05-26T20:39:54.714] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-05-27T03:26:39.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-27 03:26:39 +[2025-05-27T04:57:56.587] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-05-27T04:57:56.891] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-05-27T04:57:57.193] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-05-27T20:41:01.566] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-05-27T20:41:01.876] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-05-27T20:41:02.178] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-05-28T03:26:41.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-28 03:26:41 +[2025-05-28T04:57:05.061] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-05-28T04:57:05.365] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-05-28T04:57:05.668] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-05-28T20:42:07.674] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-05-28T20:42:07.983] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-05-28T20:42:08.285] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-05-29T03:26:42.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-29 03:26:42 +[2025-05-29T04:56:15.924] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-05-29T04:56:16.228] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-05-29T04:56:16.530] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-05-29T20:43:12.450] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-05-29T20:43:12.759] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-05-29T20:43:13.062] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-05-30T03:26:43.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-30 03:26:43 +[2025-05-30T04:55:29.171] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-05-30T04:55:29.475] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-05-30T04:55:29.777] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-05-30T20:44:17.586] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-05-30T20:44:17.895] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-05-30T20:44:18.199] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-05-31T03:26:44.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-31 03:26:44 +[2025-05-31T04:54:44.889] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-05-31T04:54:45.194] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-05-31T04:54:45.496] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-05-31T20:45:16.650] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-05-31T20:45:16.960] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-05-31T20:45:17.262] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-01T03:26:46.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-01 03:26:46 +[2025-06-01T04:54:02.934] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-01T04:54:03.238] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-01T04:54:03.540] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-01T20:46:16.311] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-01T20:46:16.620] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-01T20:46:16.923] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-02T03:26:47.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-02 03:26:47 +[2025-06-02T04:53:23.714] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-02T04:53:24.018] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-02T04:53:24.319] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-02T20:47:13.822] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-02T20:47:14.131] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-02T20:47:14.433] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-03T03:26:49.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-03 03:26:49 +[2025-06-03T04:52:46.828] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-03T04:52:47.131] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-03T04:52:47.433] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-03T20:48:09.858] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-03T20:48:10.167] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-03T20:48:10.468] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-04T03:26:50.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-04 03:26:50 +[2025-06-04T04:52:12.655] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-04T04:52:12.960] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-04T04:52:13.262] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-04T20:49:03.689] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-04T20:49:03.998] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-04T20:49:04.302] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-05T03:26:51.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-05 03:26:51 +[2025-06-05T04:51:40.777] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-05T04:51:41.081] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-05T04:51:41.384] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-05T20:49:55.774] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-05T20:49:56.084] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-05T20:49:56.387] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-06T03:26:53.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-06 03:26:53 +[2025-06-06T04:51:11.558] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-06T04:51:11.862] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-06T04:51:12.165] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-06T20:50:45.611] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-06T20:50:45.920] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-06T20:50:46.222] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-07T03:26:54.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-07 03:26:54 +[2025-06-07T04:50:45.111] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-07T04:50:45.415] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-07T04:50:45.717] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-07T20:51:33.334] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-07T20:51:33.643] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-07T20:51:33.945] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-08T03:26:56.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-08 03:26:56 +[2025-06-08T04:50:21.226] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-08T04:50:21.531] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-08T04:50:21.832] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-08T20:52:18.947] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-08T20:52:19.256] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-08T20:52:19.558] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-09T03:26:57.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-09 03:26:57 +[2025-06-09T04:49:59.989] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-09T04:50:00.293] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-09T04:50:00.595] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-09T20:53:02.628] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-09T20:53:02.937] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-09T20:53:03.239] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-10T03:26:58.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-10 03:26:58 +[2025-06-10T04:49:41.060] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-10T04:49:41.364] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-10T04:49:41.667] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-10T20:53:43.815] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-10T20:53:44.124] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-10T20:53:44.428] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-11T03:27:00.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-11 03:27:00 +[2025-06-11T04:49:25.130] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-11T04:49:25.434] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-11T04:49:25.736] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-11T20:54:22.503] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-11T20:54:22.812] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-11T20:54:23.115] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-12T03:27:01.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-12 03:27:01 +[2025-06-12T04:49:11.981] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-12T04:49:12.285] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-12T04:49:12.588] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-12T20:54:59.263] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-12T20:54:59.571] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-12T20:54:59.874] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-13T03:27:02.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-13 03:27:02 +[2025-06-13T04:49:01.295] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-13T04:49:01.599] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-13T04:49:01.901] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-13T15:32:47.139] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-06-13T15:32:52.484] [INFO] monitorLogs - buildTasks - params undefined +[2025-06-13T15:32:52.488] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-06-13T15:32:52.489] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-06-13T15:32:52.490] [INFO] monitorLogs - profile: { + 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: 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 +} +[2025-06-13T15:32:52.494] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-06-13T15:32:52.496] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 1 2025-06-14T02:49:00.495Z +[2025-06-13T15:32:52.497] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 1 2025-06-13T18:55:00.497Z +[2025-06-13T15:32:52.498] [INFO] monitorLogs - -->time_points final 1 [ + { start_time: '04:49', value: 0, name: 'dawn' }, + { start_time: '20:55', value: 1, name: 'dusk' } +] +[2025-06-13T15:32:52.499] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-06-13T15:32:52.500] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-06-13T15:32:52.500] [INFO] monitorLogs - profile: { + 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: 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 +} +[2025-06-13T15:32:52.503] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-06-13T15:32:52.503] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 2 2025-06-14T02:49:00.503Z +[2025-06-13T15:32:52.504] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 2 2025-06-13T18:55:00.504Z +[2025-06-13T15:32:52.505] [INFO] monitorLogs - -->time_points final 2 [ + { start_time: '04:49', value: 0, name: 'dawn' }, + { start_time: '20:55', value: 1, name: 'dusk' } +] +[2025-06-13T15:32:52.506] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-06-13T15:32:52.507] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-06-13T15:32:52.507] [INFO] monitorLogs - profile: { + 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: 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 +} +[2025-06-13T15:32:52.509] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-06-13T15:32:52.510] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 3 2025-06-14T02:49:00.510Z +[2025-06-13T15:32:52.511] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 3 2025-06-13T18:55:00.511Z +[2025-06-13T15:32:52.511] [INFO] monitorLogs - -->time_points final 3 [ + { start_time: '04:49', value: 0, name: 'dawn' }, + { start_time: '20:55', value: 1, name: 'dusk' } +] +[2025-06-13T15:32:52.512] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-06-13T15:32:52.514] [INFO] monitorLogs - tasks created: 70 +[2025-06-13T15:32:52.517] [INFO] monitorLogs - -->FLOW bol spustený 3JjOWdylwgNLzxVab7NajKkZ2vG64rq8PEB5QmDo 2025-04-24 +[2025-06-13T15:32:57.526] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-13T20:55:00.654] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-13T20:55:00.964] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-13T20:55:01.267] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-14T03:32:53.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-14 03:32:53 +[2025-06-14T04:49:00.693] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-14T04:49:01.009] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-14T04:49:01.312] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-14T20:56:05.249] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-14T20:56:05.557] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-14T20:56:05.860] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-15T04:48:47.956] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-15T04:48:48.258] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-15T04:48:48.561] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-15T20:56:34.258] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-15T20:56:34.565] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-15T20:56:34.868] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-16T03:32:56.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-16 03:32:56 +[2025-06-16T04:48:45.182] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-16T04:48:45.484] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-16T04:48:45.787] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-16T20:57:01.185] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-16T20:57:01.493] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-16T20:57:01.797] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-17T03:32:57.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-17 03:32:57 +[2025-06-17T04:48:45.190] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-17T04:48:45.493] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-17T04:48:45.795] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-17T20:57:25.474] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-17T20:57:25.783] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-17T20:57:26.085] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-18T03:32:59.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-18 03:32:59 +[2025-06-18T04:48:48.036] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-18T04:48:48.339] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-18T04:48:48.642] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-18T20:57:47.202] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-18T20:57:47.510] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-18T20:57:47.813] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-19T03:33:00.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-19 03:33:00 +[2025-06-19T04:48:54.742] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-19T04:48:55.044] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-19T04:48:55.347] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-19T20:58:06.307] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-19T20:58:06.615] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-19T20:58:06.918] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-20T03:33:02.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-20 03:33:02 +[2025-06-20T04:49:01.305] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-20T04:49:01.607] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-20T04:49:01.910] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-20T20:58:22.537] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-20T20:58:22.844] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-20T20:58:23.146] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-21T03:33:03.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-21 03:33:03 +[2025-06-21T04:49:12.005] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-21T04:49:12.308] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-21T04:49:12.610] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-21T20:58:36.352] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-21T20:58:36.660] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-21T20:58:36.963] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-22T03:33:04.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-22 03:33:04 +[2025-06-22T04:49:25.180] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-22T04:49:25.482] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-22T04:49:25.785] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-22T20:58:47.614] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-22T20:58:47.920] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-22T20:58:48.223] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-23T03:33:06.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-23 03:33:06 +[2025-06-23T04:49:40.978] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-23T04:49:41.281] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-23T04:49:41.583] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-23T20:58:55.986] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-23T20:58:56.293] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-23T20:58:56.596] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-24T03:33:07.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-24 03:33:07 +[2025-06-24T04:49:59.329] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-24T04:49:59.631] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-24T04:49:59.933] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-24T20:59:01.863] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-24T20:59:02.170] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-24T20:59:02.472] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-25T03:33:09.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-25 03:33:09 +[2025-06-25T04:50:20.230] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-25T04:50:20.532] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-25T04:50:20.834] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-25T20:59:04.861] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-25T20:59:05.168] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-25T20:59:05.470] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-26T03:33:10.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-26 03:33:10 +[2025-06-26T04:50:43.648] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-26T04:50:43.951] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-26T04:50:44.253] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-26T20:59:05.138] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-26T20:59:05.445] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-26T20:59:05.746] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-27T03:33:12.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-27 03:33:12 +[2025-06-27T04:51:09.530] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-27T04:51:09.832] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-27T04:51:10.134] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-27T20:59:02.831] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-27T20:59:03.139] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-27T20:59:03.441] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-28T03:33:13.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-28 03:33:13 +[2025-06-28T04:51:37.804] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-28T04:51:38.107] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-28T04:51:38.410] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-28T20:58:57.805] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-28T20:58:58.113] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-28T20:58:58.416] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-29T03:33:15.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-29 03:33:15 +[2025-06-29T04:52:08.324] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-29T04:52:08.627] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-29T04:52:08.929] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-29T20:58:49.841] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-29T20:58:50.148] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-29T20:58:50.449] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-30T03:33:16.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-30 03:33:16 +[2025-06-30T04:52:41.468] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-30T04:52:41.771] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-30T04:52:42.072] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-30T20:58:39.269] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-30T20:58:39.575] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-30T20:58:39.879] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-01T03:33:18.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-01 03:33:18 +[2025-07-01T04:53:16.700] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-01T04:53:17.002] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-01T04:53:17.304] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-01T20:58:26.121] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-01T20:58:26.429] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-01T20:58:26.732] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-02T03:33:19.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-02 03:33:19 +[2025-07-02T04:53:54.264] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-02T04:53:54.567] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-02T04:53:54.870] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-02T07:55:59.511] [INFO] monitorLogs - turnLine on - (line, SETTINGS.maintenance_mode) 0 true command received from platform +[2025-07-02T08:00:16.643] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false command received from platform +[2025-07-02T20:58:09.956] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-02T20:58:10.258] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-02T20:58:10.561] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-03T03:33:21.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-03 03:33:21 +[2025-07-03T04:54:34.095] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-03T04:54:34.397] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-03T04:54:34.700] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-03T20:57:51.185] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-03T20:57:51.492] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-03T20:57:51.795] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-04T03:33:23.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-04 03:33:23 +[2025-07-04T04:55:15.990] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-04T04:55:16.294] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-04T04:55:16.595] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-04T20:57:29.989] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-04T20:57:30.297] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-04T20:57:30.600] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-05T03:33:24.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-05 03:33:24 +[2025-07-05T04:56:00.168] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-05T04:56:00.470] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-05T04:56:00.772] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-05T20:57:05.732] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-05T20:57:06.041] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-05T20:57:06.344] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-06T03:33:26.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-06 03:33:26 +[2025-07-06T04:56:46.448] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-06T04:56:46.752] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-06T04:56:47.053] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-06T20:56:38.967] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-06T20:56:39.275] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-06T20:56:39.578] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-07T03:33:27.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-07 03:33:27 +[2025-07-07T04:57:34.622] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-07T04:57:34.925] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-07T04:57:35.226] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-07T13:51:18.099] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-07-07T13:51:23.443] [INFO] monitorLogs - buildTasks - params undefined +[2025-07-07T13:51:23.448] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-07-07T13:51:23.449] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-07-07T13:51:23.450] [INFO] monitorLogs - profile: { + 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: 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 +} +[2025-07-07T13:51:23.454] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-07-07T13:51:23.456] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 1 2025-07-08T02:57:00.455Z +[2025-07-07T13:51:23.457] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 1 2025-07-07T18:56:00.457Z +[2025-07-07T13:51:23.458] [INFO] monitorLogs - -->time_points final 1 [ + { start_time: '04:57', value: 0, name: 'dawn' }, + { start_time: '20:56', value: 1, name: 'dusk' } +] +[2025-07-07T13:51:23.459] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-07-07T13:51:23.460] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-07-07T13:51:23.460] [INFO] monitorLogs - profile: { + 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: 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 +} +[2025-07-07T13:51:23.463] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-07-07T13:51:23.464] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 2 2025-07-08T02:57:00.463Z +[2025-07-07T13:51:23.465] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 2 2025-07-07T18:56:00.464Z +[2025-07-07T13:51:23.465] [INFO] monitorLogs - -->time_points final 2 [ + { start_time: '04:57', value: 0, name: 'dawn' }, + { start_time: '20:56', value: 1, name: 'dusk' } +] +[2025-07-07T13:51:23.466] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-07-07T13:51:23.467] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-07-07T13:51:23.467] [INFO] monitorLogs - profile: { + 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: 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 +} +[2025-07-07T13:51:23.470] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-07-07T13:51:23.470] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 3 2025-07-08T02:57:00.470Z +[2025-07-07T13:51:23.471] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 3 2025-07-07T18:56:00.471Z +[2025-07-07T13:51:23.472] [INFO] monitorLogs - -->time_points final 3 [ + { start_time: '04:57', value: 0, name: 'dawn' }, + { start_time: '20:56', value: 1, name: 'dusk' } +] +[2025-07-07T13:51:23.473] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-07-07T13:51:23.474] [INFO] monitorLogs - tasks created: 70 +[2025-07-07T13:51:23.477] [INFO] monitorLogs - -->FLOW bol spustený 3JjOWdylwgNLzxVab7NajKkZ2vG64rq8PEB5QmDo 2025-07-08 +[2025-07-07T13:51:28.485] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-07T20:56:00.478] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-07T20:56:00.788] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-07T20:56:01.091] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-08T03:51:25.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-08 03:51:25 +[2025-07-08T04:57:00.699] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-08T04:57:01.002] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-08T04:57:01.305] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-08T20:55:37.751] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-08T20:55:38.059] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-08T20:55:38.361] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-09T03:51:26.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-09 03:51:26 +[2025-07-09T04:59:16.879] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-09T04:59:17.182] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-09T04:59:17.484] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-09T20:55:02.952] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-09T20:55:03.260] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-09T20:55:03.563] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-10T02:23:58.411] [INFO] monitorLogs - MQTT client error Error: connect ECONNREFUSED 192.168.252.1:1883 + at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1159:16) { + errno: -111, + code: 'ECONNREFUSED', + syscall: 'connect', + address: '192.168.252.1', + port: 1883 +} +[2025-07-10T03:51:28.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-10 03:51:28 +[2025-07-10T05:00:10.871] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-10T05:00:11.175] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-10T05:00:11.477] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-10T20:54:25.713] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-10T20:54:26.021] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-10T20:54:26.324] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-11T03:51:29.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-11 03:51:29 +[2025-07-11T05:01:06.548] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-11T05:01:06.850] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-11T05:01:07.153] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-11T20:53:46.069] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-11T20:53:46.378] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-11T20:53:46.682] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-12T03:51:30.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-12 03:51:30 +[2025-07-12T05:02:04.099] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-12T05:02:04.402] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-12T05:02:04.705] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-12T20:53:03.873] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-12T20:53:04.181] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-12T20:53:04.484] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-13T03:51:32.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-13 03:51:32 +[2025-07-13T05:03:03.240] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-13T05:03:03.543] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-13T05:03:03.846] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-13T20:52:19.227] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-13T20:52:19.536] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-13T20:52:19.839] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-14T03:51:33.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-14 03:51:33 +[2025-07-14T05:04:07.160] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-14T05:04:07.464] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-14T05:04:07.766] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-14T20:51:31.757] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-14T20:51:32.064] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-14T20:51:32.366] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-15T03:51:35.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-15 03:51:35 +[2025-07-15T05:05:06.627] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-15T05:05:06.929] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-15T05:05:07.231] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-15T20:50:42.215] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-15T20:50:42.522] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-15T20:50:42.824] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-16T03:51:36.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-16 03:51:36 +[2025-07-16T05:06:10.405] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-16T05:06:10.708] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-16T05:06:11.010] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-16T20:49:50.290] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-16T20:49:50.596] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-16T20:49:50.899] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-17T03:51:38.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-17 03:51:38 +[2025-07-17T05:07:15.603] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-17T05:07:15.906] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-17T05:07:16.208] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-17T20:48:55.891] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-17T20:48:56.199] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-17T20:48:56.501] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-18T03:51:39.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-18 03:51:39 +[2025-07-18T05:08:22.336] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-18T05:08:22.639] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-18T05:08:22.942] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-18T20:47:59.088] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-18T20:47:59.396] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-18T20:47:59.698] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-19T03:51:40.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-19 03:51:40 +[2025-07-19T05:09:33.454] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-19T05:09:33.757] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-19T05:09:34.059] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-19T20:47:00.115] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-19T20:47:00.422] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-19T20:47:00.725] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-20T03:51:42.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-20 03:51:42 +[2025-07-20T05:10:39.701] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-20T05:10:40.003] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-20T05:10:43.336] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-20T20:45:58.823] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-20T20:45:59.130] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-20T20:45:59.432] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-21T03:51:43.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-21 03:51:43 +[2025-07-21T05:11:49.994] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-21T05:11:50.297] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-21T05:11:50.600] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-21T20:44:55.493] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-21T20:44:55.800] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-21T20:44:56.102] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-22T03:51:45.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-22 03:51:45 +[2025-07-22T05:13:01.879] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-22T05:13:02.182] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-22T05:13:02.484] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-22T20:43:49.975] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-22T20:43:50.283] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-22T20:43:50.585] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-23T03:51:46.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-23 03:51:46 +[2025-07-23T05:14:14.377] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-23T05:14:14.679] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-23T05:14:14.982] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-23T20:42:41.868] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-23T20:42:42.177] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-23T20:42:42.479] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-24T03:51:48.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-24 03:51:48 +[2025-07-24T05:15:28.244] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-24T05:15:28.546] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-24T05:15:28.848] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-24T20:41:32.058] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-24T20:41:32.367] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-24T20:41:32.670] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-25T03:51:49.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-25 03:51:49 +[2025-07-25T05:16:43.028] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-25T05:16:43.330] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-25T05:16:43.633] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-25T20:40:20.022] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-25T20:40:20.330] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-25T20:40:20.634] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-26T03:51:51.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-26 03:51:51 +[2025-07-26T05:17:58.632] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-26T05:17:58.935] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-26T05:18:02.268] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-26T20:39:06.069] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-26T20:39:06.376] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-26T20:39:06.678] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-27T03:51:52.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-27 03:51:52 +[2025-07-27T05:19:15.035] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-27T05:19:15.338] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-27T05:19:15.640] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-27T20:37:50.021] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-27T20:37:50.328] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-27T20:37:50.630] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-28T03:51:54.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-28 03:51:54 +[2025-07-28T05:20:32.562] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-28T05:20:32.865] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-28T05:20:33.166] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-28T20:36:32.374] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-28T20:36:32.680] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-28T20:36:32.982] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-29T03:51:55.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-29 03:51:55 +[2025-07-29T05:21:50.500] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-29T05:21:50.804] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-29T05:21:51.107] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-29T12:19:43.091] [INFO] monitorLogs - MQTT client error Error: connect ECONNREFUSED 192.168.252.1:1883 + at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1159:16) { + errno: -111, + code: 'ECONNREFUSED', + syscall: 'connect', + address: '192.168.252.1', + port: 1883 +} +[2025-07-29T20:35:12.578] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-29T20:35:12.886] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-29T20:35:13.189] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-30T03:51:56.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-30 03:51:56 +[2025-07-30T05:23:09.325] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-30T05:23:09.627] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-30T05:23:09.930] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-30T20:33:50.815] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-30T20:33:51.122] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-30T20:33:51.425] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-31T03:51:58.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-31 03:51:58 +[2025-07-31T05:24:28.685] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-31T05:24:28.988] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-31T05:24:29.291] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-31T20:32:27.320] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-31T20:32:27.628] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-31T20:32:27.930] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-01T03:51:59.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-01 03:51:59 +[2025-08-01T05:25:48.874] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-01T05:25:49.176] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-01T05:25:49.478] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-01T20:31:01.943] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-01T20:31:02.252] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-01T20:31:02.554] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-02T03:52:01.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-02 03:52:01 +[2025-08-02T05:27:09.411] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-02T05:27:09.713] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-02T05:27:10.015] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-02T20:29:35.180] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-02T20:29:35.488] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-02T20:29:35.791] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-03T03:52:02.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-03 03:52:02 +[2025-08-03T05:28:30.563] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-03T05:28:30.865] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-03T05:28:31.167] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-03T20:28:06.192] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-03T20:28:06.498] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-03T20:28:06.801] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-04T03:52:03.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-04 03:52:03 +[2025-08-04T05:29:52.181] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-04T05:29:52.484] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-04T05:29:52.787] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-04T20:26:35.936] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-04T20:26:36.244] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-04T20:26:36.546] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-05T03:52:05.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-05 03:52:05 +[2025-08-05T05:31:14.548] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-05T05:31:14.850] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-05T05:31:15.152] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-05T20:25:03.937] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-05T20:25:04.244] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-05T20:25:04.547] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-06T03:52:06.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-06 03:52:06 +[2025-08-06T05:32:36.907] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-06T05:32:37.209] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-06T05:32:37.511] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-06T13:47:26.177] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-08-06T13:47:31.523] [INFO] monitorLogs - buildTasks - params undefined +[2025-08-06T13:47:31.527] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-08-06T13:47:31.529] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-08-06T13:47:31.530] [INFO] monitorLogs - profile: { + 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: 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 +} +[2025-08-06T13:47:31.534] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-08-06T13:47:31.535] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 1 2025-08-07T03:32:00.534Z +[2025-08-06T13:47:31.537] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 1 2025-08-06T18:23:00.536Z +[2025-08-06T13:47:31.537] [INFO] monitorLogs - -->time_points final 1 [ + { start_time: '05:32', value: 0, name: 'dawn' }, + { start_time: '20:23', value: 1, name: 'dusk' } +] +[2025-08-06T13:47:31.539] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-08-06T13:47:31.539] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-08-06T13:47:31.540] [INFO] monitorLogs - profile: { + 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: 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 +} +[2025-08-06T13:47:31.542] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-08-06T13:47:31.543] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 2 2025-08-07T03:32:00.543Z +[2025-08-06T13:47:31.544] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 2 2025-08-06T18:23:00.544Z +[2025-08-06T13:47:31.545] [INFO] monitorLogs - -->time_points final 2 [ + { start_time: '05:32', value: 0, name: 'dawn' }, + { start_time: '20:23', value: 1, name: 'dusk' } +] +[2025-08-06T13:47:31.546] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-08-06T13:47:31.547] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-08-06T13:47:31.547] [INFO] monitorLogs - profile: { + 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: 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 +} +[2025-08-06T13:47:31.549] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-08-06T13:47:31.550] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 3 2025-08-07T03:32:00.550Z +[2025-08-06T13:47:31.551] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 3 2025-08-06T18:23:00.551Z +[2025-08-06T13:47:31.552] [INFO] monitorLogs - -->time_points final 3 [ + { start_time: '05:32', value: 0, name: 'dawn' }, + { start_time: '20:23', value: 1, name: 'dusk' } +] +[2025-08-06T13:47:31.553] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-08-06T13:47:31.554] [INFO] monitorLogs - tasks created: 70 +[2025-08-06T13:47:31.557] [INFO] monitorLogs - -->FLOW bol spustený 3JjOWdylwgNLzxVab7NajKkZ2vG64rq8PEB5QmDo 2025-08-08 +[2025-08-06T13:47:36.565] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-06T20:23:00.632] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-06T20:23:00.942] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-06T20:23:01.244] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-07T03:47:33.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-07 03:47:33 +[2025-08-07T05:32:00.822] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-07T05:32:01.125] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-07T05:32:01.428] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-07T20:21:55.031] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-07T20:21:55.340] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-07T20:21:55.643] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-08T03:47:34.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-08 03:47:34 +[2025-08-08T05:35:23.085] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-08T05:35:23.389] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-08T05:35:23.691] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-08T20:20:18.266] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-08T20:20:18.573] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-08T20:20:18.876] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-09T03:47:36.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-09 03:47:36 +[2025-08-09T05:36:46.404] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-09T05:36:46.707] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-09T05:36:47.009] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-09T20:18:40.154] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-09T20:18:40.457] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-09T20:18:40.760] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-10T03:47:37.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-10 03:47:37 +[2025-08-10T05:38:10.259] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-10T05:38:10.561] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-10T05:38:10.863] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-10T20:17:02.946] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-10T20:17:03.248] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-10T20:17:03.550] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-11T03:47:39.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-11 03:47:39 +[2025-08-11T05:39:34.251] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-11T05:39:34.561] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-11T05:39:34.863] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-11T20:15:19.555] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-11T20:15:19.862] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-11T20:15:20.165] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-12T03:47:40.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-12 03:47:40 +[2025-08-12T05:40:58.175] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-12T05:40:58.477] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-12T05:40:58.779] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-12T20:13:37.393] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-12T20:13:37.701] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-12T20:13:38.003] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-13T03:47:42.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-13 03:47:42 +[2025-08-13T05:42:22.599] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-13T05:42:22.903] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-13T05:42:23.204] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-13T20:11:53.627] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-13T20:11:53.934] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-13T20:11:54.237] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-14T03:47:44.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-14 03:47:44 +[2025-08-14T05:43:47.003] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-14T05:43:47.306] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-14T05:43:47.609] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-14T20:10:08.756] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-14T20:10:09.063] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-14T20:10:09.366] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-15T03:47:45.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-15 03:47:45 +[2025-08-15T05:45:11.447] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-15T05:45:11.750] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-15T05:45:12.052] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-15T20:08:22.531] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-15T20:08:22.838] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-15T20:08:23.142] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-16T03:47:47.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-16 03:47:47 +[2025-08-16T05:46:36.208] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-16T05:46:36.511] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-16T05:46:36.813] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-16T20:06:34.918] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-16T20:06:35.225] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-16T20:06:35.540] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-17T03:47:48.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-17 03:47:48 +[2025-08-17T05:48:01.028] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-17T05:48:01.330] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-17T05:48:01.633] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-17T20:04:46.486] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-17T20:04:46.794] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-17T20:04:47.097] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-18T03:47:50.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-18 03:47:50 +[2025-08-18T05:49:25.647] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-18T05:49:25.950] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-18T05:49:26.252] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-18T20:03:01.600] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-18T20:03:01.902] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-18T20:03:02.204] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-19T03:47:51.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-19 03:47:51 +[2025-08-19T05:50:50.655] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-19T05:50:50.958] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-19T05:50:51.260] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-19T20:01:05.939] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-19T20:01:06.245] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-19T20:01:06.547] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-20T03:47:53.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-20 03:47:53 +[2025-08-20T05:52:15.378] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-20T05:52:15.681] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-20T05:52:15.983] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-20T19:59:13.868] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-20T19:59:14.175] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-20T19:59:14.478] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-21T03:47:54.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-21 03:47:54 +[2025-08-21T05:53:40.232] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-21T05:53:40.534] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-21T05:53:40.837] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-21T19:57:20.999] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-21T19:57:21.307] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-21T19:57:21.610] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-22T03:47:56.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-22 03:47:56 +[2025-08-22T05:55:04.996] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-22T05:55:05.299] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-22T05:55:05.601] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-22T19:55:27.095] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-22T19:55:27.398] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-22T19:55:27.699] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-23T03:47:57.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-23 03:47:57 +[2025-08-23T05:56:29.831] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-23T05:56:30.133] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-23T05:56:30.436] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-23T19:53:31.996] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-23T19:53:32.304] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-23T19:53:32.606] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-24T03:47:58.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-24 03:47:58 +[2025-08-24T05:57:54.465] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-24T05:57:54.766] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-24T05:57:55.068] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-24T19:51:36.185] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-24T19:51:36.493] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-24T19:51:36.796] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-25T03:48:00.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-25 03:48:00 +[2025-08-25T05:59:19.136] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-25T05:59:19.439] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-25T05:59:19.741] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-25T19:49:39.354] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-25T19:49:39.662] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-25T19:49:39.964] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-26T03:48:01.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-26 03:48:01 +[2025-08-26T06:00:43.914] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-26T06:00:44.218] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-26T06:00:44.521] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-26T19:47:41.859] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-26T19:47:42.166] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-26T19:47:42.468] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-27T03:48:02.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-27 03:48:02 +[2025-08-27T06:02:08.354] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-27T06:02:08.656] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-27T06:02:08.959] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-27T19:45:43.287] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-27T19:45:43.595] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-27T19:45:43.898] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-28T03:48:04.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-28 03:48:04 +[2025-08-28T06:03:33.012] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-28T06:03:33.315] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-28T06:03:33.617] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-28T19:43:44.055] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-28T19:43:44.363] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-28T19:43:44.665] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-29T03:48:06.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-29 03:48:06 +[2025-08-29T06:04:57.531] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-29T06:04:57.834] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-29T06:04:58.136] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-29T19:41:46.765] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-29T19:41:47.067] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-29T19:41:47.369] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-30T03:48:07.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-30 03:48:07 +[2025-08-30T06:06:21.735] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-30T06:06:22.038] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-30T06:06:22.339] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-30T19:39:43.299] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-30T19:39:43.601] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-30T19:39:43.903] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-31T03:48:09.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-31 03:48:09 +[2025-08-31T06:07:46.228] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-31T06:07:46.531] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-31T06:07:46.832] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-31T19:37:41.780] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-08-31T19:37:42.082] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-08-31T19:37:42.384] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-01T03:48:10.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-01 03:48:10 +[2025-09-01T06:09:10.294] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-01T06:09:10.597] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-01T06:09:10.899] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-01T19:35:39.722] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-01T19:35:40.025] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-01T19:35:40.328] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-02T03:48:11.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-02 03:48:11 +[2025-09-02T06:10:34.481] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-02T06:10:34.783] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-02T06:10:35.085] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-02T19:33:37.166] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-02T19:33:37.473] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-02T19:33:37.776] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-03T03:48:13.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-03 03:48:13 +[2025-09-03T06:11:58.789] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-03T06:11:59.093] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-03T06:11:59.395] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-03T19:31:33.713] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-03T19:31:34.021] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-03T19:31:34.323] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-04T03:48:14.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-04 03:48:14 +[2025-09-04T06:13:22.677] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-04T06:13:22.980] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-04T06:13:23.282] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-04T19:29:29.903] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-04T19:29:30.209] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-04T19:29:30.511] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-05T03:48:16.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-05 03:48:16 +[2025-09-05T06:14:46.721] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-05T06:14:47.023] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-05T06:14:47.326] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-05T19:27:25.398] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-05T19:27:25.701] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-05T19:27:26.003] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-06T03:48:17.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-06 03:48:17 +[2025-09-06T06:16:10.480] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-06T06:16:10.783] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-06T06:16:11.085] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-06T19:25:20.502] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-06T19:25:20.809] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-06T19:25:21.111] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-07T03:48:19.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-07 03:48:19 +[2025-09-07T06:17:34.411] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-07T06:17:34.714] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-07T06:17:35.017] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-07T19:23:15.100] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-07T19:23:15.408] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-07T19:23:15.711] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-08T03:48:20.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-08 03:48:20 +[2025-09-08T06:18:58.064] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-08T06:18:58.366] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-08T06:18:58.668] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-08T19:21:09.117] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-08T19:21:09.424] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-08T19:21:09.726] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-09T03:48:22.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-09 03:48:22 +[2025-09-09T06:20:22.061] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-09T06:20:22.364] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-09T06:20:22.666] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-09T19:19:02.876] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-09T19:19:03.179] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-09T19:19:03.481] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-10T03:48:23.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-10 03:48:23 +[2025-09-10T06:21:45.768] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-10T06:21:46.071] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-10T06:21:46.373] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-10T19:16:56.511] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-10T19:16:56.818] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-10T19:16:57.122] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-11T03:48:24.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-11 03:48:24 +[2025-09-11T06:26:25.461] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-11T06:26:25.764] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-11T06:26:26.066] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-11T07:55:53.744] [INFO] monitorLogs - turnLine on - (line, SETTINGS.maintenance_mode) 0 true command received from platform +[2025-09-11T08:05:23.326] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false command received from platform +[2025-09-11T19:14:49.365] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-11T19:14:49.667] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-11T19:14:49.969] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-12T03:48:26.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-12 03:48:26 +[2025-09-12T06:27:07.837] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-12T06:27:08.139] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-12T06:27:08.441] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-12T07:52:59.329] [INFO] monitorLogs - turnLine on - (line, SETTINGS.maintenance_mode) 0 true command received from platform +[2025-09-12T09:22:50.600] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false command received from platform +[2025-09-12T19:12:42.261] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-12T19:12:42.564] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-12T19:12:42.866] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-13T03:48:27.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-13 03:48:27 +[2025-09-13T06:25:57.090] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-13T06:25:57.392] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-13T06:25:57.695] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-13T19:10:34.755] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-13T19:10:35.058] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-13T19:10:35.360] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-14T03:48:28.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-14 03:48:28 +[2025-09-14T06:27:20.772] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-14T06:27:21.074] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-14T06:27:21.376] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-14T19:08:27.219] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-14T19:08:27.526] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-14T19:08:27.829] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-15T03:48:30.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-15 03:48:30 +[2025-09-15T06:28:44.604] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-15T06:28:44.907] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-15T06:28:45.209] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-15T19:06:19.270] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-15T19:06:19.573] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-15T19:06:19.876] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-16T03:48:31.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-16 03:48:31 +[2025-09-16T06:30:08.202] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-16T06:30:08.504] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-16T06:30:08.807] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-16T15:49:05.576] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-09-16T15:49:10.914] [INFO] monitorLogs - buildTasks - params undefined +[2025-09-16T15:49:10.918] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-09-16T15:49:10.919] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-09-16T15:49:10.920] [INFO] monitorLogs - profile: { + 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: 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 +} +[2025-09-16T15:49:10.924] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-16T15:49:10.926] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 1 2025-09-17T04:30:00.925Z +[2025-09-16T15:49:10.927] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 1 2025-09-16T17:04:00.927Z +[2025-09-16T15:49:10.928] [INFO] monitorLogs - -->time_points final 1 [ + { start_time: '06:30', value: 0, name: 'dawn' }, + { start_time: '19:04', value: 1, name: 'dusk' } +] +[2025-09-16T15:49:10.929] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-09-16T15:49:10.930] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-09-16T15:49:10.931] [INFO] monitorLogs - profile: { + 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: 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 +} +[2025-09-16T15:49:10.933] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-16T15:49:10.934] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 2 2025-09-17T04:30:00.934Z +[2025-09-16T15:49:10.935] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 2 2025-09-16T17:04:00.935Z +[2025-09-16T15:49:10.936] [INFO] monitorLogs - -->time_points final 2 [ + { start_time: '06:30', value: 0, name: 'dawn' }, + { start_time: '19:04', value: 1, name: 'dusk' } +] +[2025-09-16T15:49:10.937] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-09-16T15:49:10.937] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-09-16T15:49:10.938] [INFO] monitorLogs - profile: { + 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: 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 +} +[2025-09-16T15:49:10.940] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-16T15:49:10.941] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 3 2025-09-17T04:30:00.941Z +[2025-09-16T15:49:10.942] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 3 2025-09-16T17:04:00.941Z +[2025-09-16T15:49:10.942] [INFO] monitorLogs - -->time_points final 3 [ + { start_time: '06:30', value: 0, name: 'dawn' }, + { start_time: '19:04', value: 1, name: 'dusk' } +] +[2025-09-16T15:49:10.943] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-09-16T15:49:10.945] [INFO] monitorLogs - tasks created: 70 +[2025-09-16T15:49:10.947] [INFO] monitorLogs - -->FLOW bol spustený 3JjOWdylwgNLzxVab7NajKkZ2vG64rq8PEB5QmDo 2025-08-08 +[2025-09-16T15:49:15.953] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-16T19:04:01.176] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-16T19:04:01.483] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-16T19:04:01.786] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-17T03:49:13.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-17 03:49:13 +[2025-09-17T06:30:01.054] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-17T06:30:01.357] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-17T06:30:01.660] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-17T19:02:02.739] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-17T19:02:03.045] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-17T19:02:03.347] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-17T20:45:17.917] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-09-17T20:45:23.256] [INFO] monitorLogs - buildTasks - params undefined +[2025-09-17T20:45:23.261] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-09-17T20:45:23.262] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-09-17T20:45:23.262] [INFO] monitorLogs - profile: { + 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: 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 +} +[2025-09-17T20:45:23.266] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-17T20:45:23.268] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 1 2025-09-18T04:31:00.267Z +[2025-09-17T20:45:23.269] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 1 2025-09-18T17:02:00.269Z +[2025-09-17T20:45:23.270] [INFO] monitorLogs - -->time_points final 1 [ + { start_time: '06:31', value: 0, name: 'dawn' }, + { start_time: '19:02', value: 1, name: 'dusk' } +] +[2025-09-17T20:45:23.271] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-09-17T20:45:23.272] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-09-17T20:45:23.273] [INFO] monitorLogs - profile: { + 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: 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 +} +[2025-09-17T20:45:23.275] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-17T20:45:23.276] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 2 2025-09-18T04:31:00.275Z +[2025-09-17T20:45:23.276] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 2 2025-09-18T17:02:00.276Z +[2025-09-17T20:45:23.277] [INFO] monitorLogs - -->time_points final 2 [ + { start_time: '06:31', value: 0, name: 'dawn' }, + { start_time: '19:02', value: 1, name: 'dusk' } +] +[2025-09-17T20:45:23.278] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-09-17T20:45:23.279] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-09-17T20:45:23.279] [INFO] monitorLogs - profile: { + 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: 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 +} +[2025-09-17T20:45:23.282] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-17T20:45:23.283] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 3 2025-09-18T04:31:00.282Z +[2025-09-17T20:45:23.283] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 3 2025-09-18T17:02:00.283Z +[2025-09-17T20:45:23.284] [INFO] monitorLogs - -->time_points final 3 [ + { start_time: '06:31', value: 0, name: 'dawn' }, + { start_time: '19:02', value: 1, name: 'dusk' } +] +[2025-09-17T20:45:23.285] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-09-17T20:45:23.286] [INFO] monitorLogs - tasks created: 70 +[2025-09-17T20:45:23.289] [INFO] monitorLogs - -->FLOW bol spustený 3JjOWdylwgNLzxVab7NajKkZ2vG64rq8PEB5QmDo 2025-08-08 +[2025-09-17T20:45:28.295] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-18T03:45:24.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-18 03:45:24 +[2025-09-18T06:31:00.489] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-18T06:31:00.794] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-18T06:31:01.097] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-18T19:02:00.477] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-18T19:02:00.780] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-18T19:02:01.082] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-19T03:45:26.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-19 03:45:26 +[2025-09-19T06:34:20.192] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-19T06:34:20.495] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-19T06:34:20.798] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-19T11:24:54.586] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-09-19T11:24:59.929] [INFO] monitorLogs - buildTasks - params undefined +[2025-09-19T11:24:59.934] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-09-19T11:24:59.935] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-09-19T11:24:59.936] [INFO] monitorLogs - profile: { + 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: 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 +} +[2025-09-19T11:24:59.940] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-19T11:24:59.941] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 1 2025-09-20T04:34:00.940Z +[2025-09-19T11:24:59.942] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 1 2025-09-19T16:57:00.942Z +[2025-09-19T11:24:59.943] [INFO] monitorLogs - -->time_points final 1 [ + { start_time: '06:34', value: 0, name: 'dawn' }, + { start_time: '18:57', value: 1, name: 'dusk' } +] +[2025-09-19T11:24:59.944] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-09-19T11:24:59.945] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-09-19T11:24:59.946] [INFO] monitorLogs - profile: { + 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: 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 +} +[2025-09-19T11:24:59.948] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-19T11:24:59.949] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 2 2025-09-20T04:34:00.949Z +[2025-09-19T11:24:59.950] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 2 2025-09-19T16:57:00.950Z +[2025-09-19T11:24:59.950] [INFO] monitorLogs - -->time_points final 2 [ + { start_time: '06:34', value: 0, name: 'dawn' }, + { start_time: '18:57', value: 1, name: 'dusk' } +] +[2025-09-19T11:24:59.951] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-09-19T11:24:59.952] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-09-19T11:24:59.953] [INFO] monitorLogs - profile: { + 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: 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 +} +[2025-09-19T11:24:59.955] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-19T11:24:59.956] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 3 2025-09-20T04:34:00.955Z +[2025-09-19T11:24:59.956] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 3 2025-09-19T16:57:00.956Z +[2025-09-19T11:24:59.957] [INFO] monitorLogs - -->time_points final 3 [ + { start_time: '06:34', value: 0, name: 'dawn' }, + { start_time: '18:57', value: 1, name: 'dusk' } +] +[2025-09-19T11:24:59.958] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-09-19T11:24:59.960] [INFO] monitorLogs - tasks created: 70 +[2025-09-19T11:24:59.962] [INFO] monitorLogs - -->FLOW bol spustený 3JjOWdylwgNLzxVab7NajKkZ2vG64rq8PEB5QmDo 2025-08-08 +[2025-09-19T11:25:04.970] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-19T18:57:01.191] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-19T18:57:01.498] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-19T18:57:01.801] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-20T03:25:01.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-20 03:25:01 +[2025-09-20T06:34:01.054] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-20T06:34:01.358] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-20T06:34:01.661] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-20T18:55:37.815] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-20T18:55:38.121] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-20T18:55:38.424] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-21T01:29:17.073] [INFO] monitorLogs - MQTT client error Error: connect ECONNREFUSED 192.168.252.1:1883 + at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1159:16) { + errno: -111, + code: 'ECONNREFUSED', + syscall: 'connect', + address: '192.168.252.1', + port: 1883 +} +[2025-09-21T03:25:03.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-21 03:25:03 +[2025-09-21T06:37:08.480] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-21T06:37:08.784] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-21T06:37:09.087] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-21T18:14:35.034] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-09-21T18:14:40.376] [INFO] monitorLogs - buildTasks - params undefined +[2025-09-21T18:14:40.381] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-09-21T18:14:40.382] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-09-21T18:14:40.383] [INFO] monitorLogs - profile: { + 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: 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 +} +[2025-09-21T18:14:40.387] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-21T18:14:40.389] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 1 2025-09-22T04:37:00.388Z +[2025-09-21T18:14:40.390] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 1 2025-09-21T16:53:00.390Z +[2025-09-21T18:14:40.391] [INFO] monitorLogs - -->time_points final 1 [ + { start_time: '06:37', value: 0, name: 'dawn' }, + { start_time: '18:53', value: 1, name: 'dusk' } +] +[2025-09-21T18:14:40.392] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-09-21T18:14:40.393] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-09-21T18:14:40.394] [INFO] monitorLogs - profile: { + 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: 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 +} +[2025-09-21T18:14:40.396] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-21T18:14:40.397] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 2 2025-09-22T04:37:00.397Z +[2025-09-21T18:14:40.398] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 2 2025-09-21T16:53:00.398Z +[2025-09-21T18:14:40.398] [INFO] monitorLogs - -->time_points final 2 [ + { start_time: '06:37', value: 0, name: 'dawn' }, + { start_time: '18:53', value: 1, name: 'dusk' } +] +[2025-09-21T18:14:40.399] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-09-21T18:14:40.400] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-09-21T18:14:40.401] [INFO] monitorLogs - profile: { + 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: 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 +} +[2025-09-21T18:14:40.403] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-21T18:14:40.404] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 3 2025-09-22T04:37:00.403Z +[2025-09-21T18:14:40.404] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 3 2025-09-21T16:53:00.404Z +[2025-09-21T18:14:40.405] [INFO] monitorLogs - -->time_points final 3 [ + { start_time: '06:37', value: 0, name: 'dawn' }, + { start_time: '18:53', value: 1, name: 'dusk' } +] +[2025-09-21T18:14:40.406] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-09-21T18:14:40.408] [INFO] monitorLogs - tasks created: 70 +[2025-09-21T18:14:40.410] [INFO] monitorLogs - -->FLOW bol spustený 3JjOWdylwgNLzxVab7NajKkZ2vG64rq8PEB5QmDo 2025-08-08 +[2025-09-21T18:14:45.416] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-21T18:53:00.522] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-21T18:53:00.826] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-21T18:53:01.130] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-22T03:14:42.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-22 03:14:42 +[2025-09-22T06:37:00.446] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-22T06:37:00.750] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-22T06:37:01.052] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-22T18:51:21.292] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-22T18:51:21.595] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-22T18:51:21.898] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-23T03:14:44.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-23 03:14:44 +[2025-09-23T06:39:57.260] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-23T06:39:57.563] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-23T06:39:57.866] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-23T13:09:45.139] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-09-23T13:09:50.486] [INFO] monitorLogs - buildTasks - params undefined +[2025-09-23T13:09:50.491] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-09-23T13:09:50.492] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-09-23T13:09:50.492] [INFO] monitorLogs - profile: { + 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: 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 +} +[2025-09-23T13:09:50.496] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-23T13:09:50.498] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 1 2025-09-24T04:39:00.497Z +[2025-09-23T13:09:50.499] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 1 2025-09-23T16:49:00.499Z +[2025-09-23T13:09:50.500] [INFO] monitorLogs - -->time_points final 1 [ + { start_time: '06:39', value: 0, name: 'dawn' }, + { start_time: '18:49', value: 1, name: 'dusk' } +] +[2025-09-23T13:09:50.501] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-09-23T13:09:50.502] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-09-23T13:09:50.502] [INFO] monitorLogs - profile: { + 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: 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 +} +[2025-09-23T13:09:50.505] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-23T13:09:50.505] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 2 2025-09-24T04:39:00.505Z +[2025-09-23T13:09:50.506] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 2 2025-09-23T16:49:00.506Z +[2025-09-23T13:09:50.507] [INFO] monitorLogs - -->time_points final 2 [ + { start_time: '06:39', value: 0, name: 'dawn' }, + { start_time: '18:49', value: 1, name: 'dusk' } +] +[2025-09-23T13:09:50.508] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-09-23T13:09:50.509] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-09-23T13:09:50.509] [INFO] monitorLogs - profile: { + 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: 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 +} +[2025-09-23T13:09:50.511] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-23T13:09:50.512] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 3 2025-09-24T04:39:00.512Z +[2025-09-23T13:09:50.513] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 3 2025-09-23T16:49:00.513Z +[2025-09-23T13:09:50.513] [INFO] monitorLogs - -->time_points final 3 [ + { start_time: '06:39', value: 0, name: 'dawn' }, + { start_time: '18:49', value: 1, name: 'dusk' } +] +[2025-09-23T13:09:50.514] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-09-23T13:09:50.516] [INFO] monitorLogs - tasks created: 70 +[2025-09-23T13:09:50.518] [INFO] monitorLogs - -->FLOW bol spustený 3JjOWdylwgNLzxVab7NajKkZ2vG64rq8PEB5QmDo 2025-08-08 +[2025-09-23T13:09:55.523] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-23T14:36:36.396] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-09-23T14:36:41.736] [INFO] monitorLogs - buildTasks - params undefined +[2025-09-23T14:36:41.741] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-09-23T14:36:41.742] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-09-23T14:36:41.742] [INFO] monitorLogs - profile: { + 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: 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 +} +[2025-09-23T14:36:41.746] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-23T14:36:41.748] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 1 2025-09-24T04:39:00.747Z +[2025-09-23T14:36:41.749] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 1 2025-09-23T16:49:00.749Z +[2025-09-23T14:36:41.750] [INFO] monitorLogs - -->time_points final 1 [ + { start_time: '06:39', value: 0, name: 'dawn' }, + { start_time: '18:49', value: 1, name: 'dusk' } +] +[2025-09-23T14:36:41.751] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-09-23T14:36:41.752] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-09-23T14:36:41.752] [INFO] monitorLogs - profile: { + 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: 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 +} +[2025-09-23T14:36:41.755] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-23T14:36:41.756] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 2 2025-09-24T04:39:00.755Z +[2025-09-23T14:36:41.757] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 2 2025-09-23T16:49:00.756Z +[2025-09-23T14:36:41.757] [INFO] monitorLogs - -->time_points final 2 [ + { start_time: '06:39', value: 0, name: 'dawn' }, + { start_time: '18:49', value: 1, name: 'dusk' } +] +[2025-09-23T14:36:41.758] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-09-23T14:36:41.759] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-09-23T14:36:41.759] [INFO] monitorLogs - profile: { + 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: 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 +} +[2025-09-23T14:36:41.762] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-23T14:36:41.762] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 3 2025-09-24T04:39:00.762Z +[2025-09-23T14:36:41.763] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 3 2025-09-23T16:49:00.763Z +[2025-09-23T14:36:41.764] [INFO] monitorLogs - -->time_points final 3 [ + { start_time: '06:39', value: 0, name: 'dawn' }, + { start_time: '18:49', value: 1, name: 'dusk' } +] +[2025-09-23T14:36:41.765] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-09-23T14:36:41.766] [INFO] monitorLogs - tasks created: 70 +[2025-09-23T14:36:41.768] [INFO] monitorLogs - -->FLOW bol spustený 3JjOWdylwgNLzxVab7NajKkZ2vG64rq8PEB5QmDo 2025-08-08 +[2025-09-23T14:36:46.773] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-23T18:49:01.047] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-23T18:49:01.355] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-23T18:49:01.658] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-24T03:36:42.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-24 03:36:42 +[2025-09-24T06:39:00.762] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-24T06:39:01.066] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-24T06:39:01.369] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-24T18:47:06.400] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-24T18:47:06.703] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-24T18:47:07.006] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-25T03:36:43.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-25 03:36:43 +[2025-09-25T06:42:46.843] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-25T06:42:47.146] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-25T06:42:47.448] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-25T16:36:42.017] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-09-25T16:36:47.350] [INFO] monitorLogs - buildTasks - params undefined +[2025-09-25T16:36:47.355] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-09-25T16:36:47.356] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-09-25T16:36:47.357] [INFO] monitorLogs - profile: { + 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: 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 +} +[2025-09-25T16:36:47.361] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-25T16:36:47.362] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 1 2025-09-26T04:42:00.362Z +[2025-09-25T16:36:47.364] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 1 2025-09-25T16:44:00.364Z +[2025-09-25T16:36:47.365] [INFO] monitorLogs - -->time_points final 1 [ + { start_time: '06:42', value: 0, name: 'dawn' }, + { start_time: '18:44', value: 1, name: 'dusk' } +] +[2025-09-25T16:36:47.366] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-09-25T16:36:47.367] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-09-25T16:36:47.367] [INFO] monitorLogs - profile: { + 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: 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 +} +[2025-09-25T16:36:47.370] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-25T16:36:47.370] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 2 2025-09-26T04:42:00.370Z +[2025-09-25T16:36:47.371] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 2 2025-09-25T16:44:00.371Z +[2025-09-25T16:36:47.372] [INFO] monitorLogs - -->time_points final 2 [ + { start_time: '06:42', value: 0, name: 'dawn' }, + { start_time: '18:44', value: 1, name: 'dusk' } +] +[2025-09-25T16:36:47.373] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-09-25T16:36:47.374] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-09-25T16:36:47.374] [INFO] monitorLogs - profile: { + 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: 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 +} +[2025-09-25T16:36:47.376] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-25T16:36:47.377] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 3 2025-09-26T04:42:00.377Z +[2025-09-25T16:36:47.378] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 3 2025-09-25T16:44:00.378Z +[2025-09-25T16:36:47.379] [INFO] monitorLogs - -->time_points final 3 [ + { start_time: '06:42', value: 0, name: 'dawn' }, + { start_time: '18:44', value: 1, name: 'dusk' } +] +[2025-09-25T16:36:47.380] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-09-25T16:36:47.381] [INFO] monitorLogs - tasks created: 70 +[2025-09-25T16:36:47.383] [INFO] monitorLogs - -->FLOW bol spustený 3JjOWdylwgNLzxVab7NajKkZ2vG64rq8PEB5QmDo 2025-08-08 +[2025-09-25T16:36:52.389] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-25T18:44:00.505] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-25T18:44:00.810] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-25T18:44:01.113] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-26T03:36:49.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-26 03:36:49 +[2025-09-26T06:42:00.383] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-26T06:42:00.688] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-26T06:42:04.021] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-26T18:42:48.477] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-26T18:42:48.780] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-26T18:42:49.083] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-27T03:36:50.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-27 03:36:50 +[2025-09-27T06:45:36.865] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-27T06:45:37.167] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-27T06:45:37.469] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-27T18:40:40.925] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-27T18:40:41.228] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-27T18:40:41.531] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-28T03:36:52.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-28 03:36:52 +[2025-09-28T06:47:02.352] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-28T06:47:02.656] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-28T06:47:02.957] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-28T18:38:33.350] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-28T18:38:33.653] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-28T18:38:33.956] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-29T03:36:53.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-29 03:36:53 +[2025-09-29T06:48:27.986] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-29T06:48:28.290] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-29T06:48:28.592] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-29T18:36:26.306] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-29T18:36:26.609] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-29T18:36:26.911] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-30T03:36:54.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-30 03:36:54 +[2025-09-30T06:49:53.994] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-30T06:49:54.296] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-30T06:49:54.599] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-30T18:34:19.460] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-09-30T18:34:19.766] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-09-30T18:34:20.069] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-01T03:36:56.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-01 03:36:56 +[2025-10-01T06:51:20.008] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-10-01T06:51:20.310] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-10-01T06:51:20.613] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-01T18:32:12.671] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-01T18:32:12.974] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-10-01T18:32:13.277] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-10-02T03:36:57.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-02 03:36:57 +[2025-10-02T06:52:46.308] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-02T06:52:46.613] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-10-02T06:52:46.915] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-10-02T18:30:06.742] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-10-02T18:30:07.045] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-10-02T18:30:07.348] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-03T03:36:58.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-03 03:36:58 +[2025-10-03T06:54:13.050] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-10-03T06:54:13.353] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-10-03T06:54:13.656] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-03T14:52:26.943] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-03T14:52:32.279] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-03T14:52:32.284] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-03T14:52:32.286] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-03T14:52:32.286] [INFO] monitorLogs - profile: { + 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: 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 +} +[2025-10-03T14:52:32.290] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-03T14:52:32.292] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 1 2025-10-04T04:54:00.291Z +[2025-10-03T14:52:32.293] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 1 2025-10-03T16:28:00.293Z +[2025-10-03T14:52:32.294] [INFO] monitorLogs - -->time_points final 1 [ + { start_time: '06:54', value: 0, name: 'dawn' }, + { start_time: '18:28', value: 1, name: 'dusk' } +] +[2025-10-03T14:52:32.295] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-10-03T14:52:32.296] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-03T14:52:32.296] [INFO] monitorLogs - profile: { + 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: 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 +} +[2025-10-03T14:52:32.299] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-03T14:52:32.299] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 2 2025-10-04T04:54:00.299Z +[2025-10-03T14:52:32.300] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 2 2025-10-03T16:28:00.300Z +[2025-10-03T14:52:32.301] [INFO] monitorLogs - -->time_points final 2 [ + { start_time: '06:54', value: 0, name: 'dawn' }, + { start_time: '18:28', value: 1, name: 'dusk' } +] +[2025-10-03T14:52:32.302] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-10-03T14:52:32.303] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-03T14:52:32.303] [INFO] monitorLogs - profile: { + 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: 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 +} +[2025-10-03T14:52:32.306] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-03T14:52:32.306] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 3 2025-10-04T04:54:00.306Z +[2025-10-03T14:52:32.307] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 3 2025-10-03T16:28:00.307Z +[2025-10-03T14:52:32.308] [INFO] monitorLogs - -->time_points final 3 [ + { start_time: '06:54', value: 0, name: 'dawn' }, + { start_time: '18:28', value: 1, name: 'dusk' } +] +[2025-10-03T14:52:32.309] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-10-03T14:52:32.310] [INFO] monitorLogs - tasks created: 70 +[2025-10-03T14:52:32.313] [INFO] monitorLogs - -->FLOW bol spustený 3JjOWdylwgNLzxVab7NajKkZ2vG64rq8PEB5QmDo 2025-08-08 +[2025-10-03T14:52:37.316] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-03T18:28:00.578] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-03T18:28:00.884] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-10-03T18:28:01.187] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-10-04T03:52:34.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-04 03:52:34 +[2025-10-04T06:54:00.545] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-04T06:54:00.848] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-10-04T06:54:01.151] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-10-04T18:25:55.652] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-10-04T18:25:55.956] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-10-04T18:25:56.259] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-05T03:52:35.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-05 03:52:35 +[2025-10-05T06:57:06.975] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-10-05T06:57:07.278] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-10-05T06:57:07.579] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-05T18:23:50.817] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-05T18:23:51.119] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-10-05T18:23:51.421] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-10-06T03:52:37.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-06 03:52:37 +[2025-10-06T06:58:34.661] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-06T06:58:34.963] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-10-06T06:58:35.265] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-10-06T18:21:46.457] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-10-06T18:21:46.759] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-10-06T18:21:47.061] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-07T03:52:38.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-07 03:52:38 +[2025-10-07T07:00:02.417] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-10-07T07:00:02.720] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-10-07T07:00:03.022] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-07T18:19:42.614] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-07T18:19:42.917] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-10-07T18:19:43.219] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-10-08T03:52:39.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-08 03:52:39 +[2025-10-08T07:01:30.642] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-08T07:01:30.946] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-10-08T07:01:31.248] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-10-08T18:17:39.528] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-10-08T18:17:39.831] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-10-08T18:17:40.134] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-09T03:52:40.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-09 03:52:40 +[2025-10-09T07:02:59.332] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-10-09T07:02:59.635] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-10-09T07:02:59.937] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-09T16:57:35.562] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-09T16:57:40.907] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-09T16:57:40.912] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-09T16:57:40.913] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-09T16:57:40.914] [INFO] monitorLogs - profile: { + 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: 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 +} +[2025-10-09T16:57:40.918] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T16:57:40.920] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 1 2025-10-10T05:02:00.919Z +[2025-10-09T16:57:40.921] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 1 2025-10-09T16:15:00.921Z +[2025-10-09T16:57:40.922] [INFO] monitorLogs - -->time_points final 1 [ + { start_time: '07:02', value: 0, name: 'dawn' }, + { start_time: '18:15', value: 1, name: 'dusk' } +] +[2025-10-09T16:57:40.923] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-10-09T16:57:40.924] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-09T16:57:40.924] [INFO] monitorLogs - profile: { + 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: 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 +} +[2025-10-09T16:57:40.927] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T16:57:40.927] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 2 2025-10-10T05:02:00.927Z +[2025-10-09T16:57:40.928] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 2 2025-10-09T16:15:00.928Z +[2025-10-09T16:57:40.929] [INFO] monitorLogs - -->time_points final 2 [ + { start_time: '07:02', value: 0, name: 'dawn' }, + { start_time: '18:15', value: 1, name: 'dusk' } +] +[2025-10-09T16:57:40.930] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-10-09T16:57:40.931] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-09T16:57:40.931] [INFO] monitorLogs - profile: { + 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: 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 +} +[2025-10-09T16:57:40.933] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T16:57:40.934] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 3 2025-10-10T05:02:00.934Z +[2025-10-09T16:57:40.935] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 3 2025-10-09T16:15:00.935Z +[2025-10-09T16:57:40.935] [INFO] monitorLogs - -->time_points final 3 [ + { start_time: '07:02', value: 0, name: 'dawn' }, + { start_time: '18:15', value: 1, name: 'dusk' } +] +[2025-10-09T16:57:40.936] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-10-09T16:57:40.938] [INFO] monitorLogs - tasks created: 70 +[2025-10-09T16:57:40.940] [INFO] monitorLogs - -->FLOW bol spustený 3JjOWdylwgNLzxVab7NajKkZ2vG64rq8PEB5QmDo 2025-08-08 +[2025-10-09T16:57:45.946] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-09T18:15:02.835] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-09T18:15:03.138] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-10-09T18:15:03.442] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-10-09T19:10:34.207] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-09T19:10:39.547] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-09T19:10:39.552] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-09T19:10:39.553] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-09T19:10:39.554] [INFO] monitorLogs - profile: { + 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: 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 +} +[2025-10-09T19:10:39.558] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T19:10:39.560] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 1 2025-10-10T05:02:00.559Z +[2025-10-09T19:10:39.561] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 1 2025-10-10T16:15:00.561Z +[2025-10-09T19:10:39.562] [INFO] monitorLogs - -->time_points final 1 [ + { start_time: '07:02', value: 0, name: 'dawn' }, + { start_time: '18:15', value: 1, name: 'dusk' } +] +[2025-10-09T19:10:39.563] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-10-09T19:10:39.564] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-09T19:10:39.564] [INFO] monitorLogs - profile: { + 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: 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 +} +[2025-10-09T19:10:39.567] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T19:10:39.567] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 2 2025-10-10T05:02:00.567Z +[2025-10-09T19:10:39.568] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 2 2025-10-10T16:15:00.568Z +[2025-10-09T19:10:39.569] [INFO] monitorLogs - -->time_points final 2 [ + { start_time: '07:02', value: 0, name: 'dawn' }, + { start_time: '18:15', value: 1, name: 'dusk' } +] +[2025-10-09T19:10:39.570] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-10-09T19:10:39.571] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-09T19:10:39.571] [INFO] monitorLogs - profile: { + 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: 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 +} +[2025-10-09T19:10:39.573] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T19:10:39.574] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 3 2025-10-10T05:02:00.574Z +[2025-10-09T19:10:39.575] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 3 2025-10-10T16:15:00.575Z +[2025-10-09T19:10:39.576] [INFO] monitorLogs - -->time_points final 3 [ + { start_time: '07:02', value: 0, name: 'dawn' }, + { start_time: '18:15', value: 1, name: 'dusk' } +] +[2025-10-09T19:10:39.577] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-10-09T19:10:39.578] [INFO] monitorLogs - tasks created: 70 +[2025-10-09T19:10:39.580] [INFO] monitorLogs - -->FLOW bol spustený 3JjOWdylwgNLzxVab7NajKkZ2vG64rq8PEB5QmDo 2025-08-08 +[2025-10-09T19:10:44.585] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-10T03:10:41.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-10 03:10:41 +[2025-10-10T07:02:00.619] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-10T07:02:00.923] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-10-10T07:02:01.226] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-10-10T18:15:00.672] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-10T18:15:00.976] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-10-10T18:15:01.278] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-10-11T03:10:43.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-11 03:10:43 +[2025-10-11T07:05:57.135] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-10-11T07:05:57.439] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-10-11T07:05:57.742] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-11T18:11:33.969] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-10-11T18:11:34.272] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-10-11T18:11:34.574] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-12T03:10:44.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-12 03:10:44 +[2025-10-12T07:07:26.657] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-12T07:07:26.960] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-10-12T07:07:27.262] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-10-12T18:09:33.381] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-12T18:09:33.683] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-10-12T18:09:33.985] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-10-13T03:10:45.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-13 03:10:45 +[2025-10-13T07:08:56.639] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-10-13T07:08:56.942] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-10-13T07:08:57.244] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-13T18:07:33.780] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-10-13T18:07:34.083] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-10-13T18:07:34.384] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-14T03:10:46.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-14 03:10:46 +[2025-10-14T07:10:26.881] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-14T07:10:27.183] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-10-14T07:10:27.485] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-10-14T18:05:34.899] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-14T18:05:35.201] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-10-14T18:05:35.503] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-10-15T03:10:48.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-15 03:10:48 +[2025-10-15T07:11:57.648] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-10-15T07:11:57.952] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-10-15T07:11:58.254] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-15T12:02:55.082] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-15T12:03:00.430] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-15T12:03:00.435] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-15T12:03:00.436] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-15T12:03:00.437] [INFO] monitorLogs - profile: { + 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: 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 +} +[2025-10-15T12:03:00.441] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-15T12:03:00.442] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 1 2025-10-16T05:11:00.442Z +[2025-10-15T12:03:00.444] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 1 2025-10-15T16:03:00.444Z +[2025-10-15T12:03:00.445] [INFO] monitorLogs - -->time_points final 1 [ + { start_time: '07:11', value: 0, name: 'dawn' }, + { start_time: '18:03', value: 1, name: 'dusk' } +] +[2025-10-15T12:03:00.446] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-10-15T12:03:00.447] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-15T12:03:00.447] [INFO] monitorLogs - profile: { + 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: 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 +} +[2025-10-15T12:03:00.449] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-15T12:03:00.450] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 2 2025-10-16T05:11:00.450Z +[2025-10-15T12:03:00.451] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 2 2025-10-15T16:03:00.451Z +[2025-10-15T12:03:00.452] [INFO] monitorLogs - -->time_points final 2 [ + { start_time: '07:11', value: 0, name: 'dawn' }, + { start_time: '18:03', value: 1, name: 'dusk' } +] +[2025-10-15T12:03:00.453] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-10-15T12:03:00.453] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-15T12:03:00.454] [INFO] monitorLogs - profile: { + 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: 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 +} +[2025-10-15T12:03:00.456] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-15T12:03:00.457] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 3 2025-10-16T05:11:00.457Z +[2025-10-15T12:03:00.458] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 3 2025-10-15T16:03:00.457Z +[2025-10-15T12:03:00.458] [INFO] monitorLogs - -->time_points final 3 [ + { start_time: '07:11', value: 0, name: 'dawn' }, + { start_time: '18:03', value: 1, name: 'dusk' } +] +[2025-10-15T12:03:00.459] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-10-15T12:03:00.461] [INFO] monitorLogs - tasks created: 70 +[2025-10-15T12:03:00.463] [INFO] monitorLogs - -->FLOW bol spustený 3JjOWdylwgNLzxVab7NajKkZ2vG64rq8PEB5QmDo 2025-10-08 +[2025-10-15T12:03:05.468] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-15T18:03:00.726] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-15T18:03:01.034] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-10-15T18:03:01.337] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu diff --git a/RVO47/package-lock.json b/RVO47/package-lock.json new file mode 100755 index 0000000..3c5c1ba --- /dev/null +++ b/RVO47/package-lock.json @@ -0,0 +1,2139 @@ +{ + "name": "emptyproject", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "emptyproject", + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "bitwise": "^2.1.0", + "easy-crc": "0.0.2", + "jsmodbus": "^4.0.6", + "log4js": "^6.3.0", + "moment": "^2.30.1", + "mqtt": "^4.2.6", + "nodemailer": "^6.9.7", + "serialport": "^9.2.8", + "total.js": "^3.4.13" + } + }, + "node_modules/@serialport/binding-abstract": { + "version": "9.2.3", + "resolved": "https://registry.npmjs.org/@serialport/binding-abstract/-/binding-abstract-9.2.3.tgz", + "integrity": "sha512-cQs9tbIlG3P0IrOWyVirqlhWuJ7Ms2Zh9m2108z6Y5UW/iVj6wEOiW8EmK9QX9jmJXYllE7wgGgvVozP5oCj3w==", + "dependencies": { + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/binding-mock": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/binding-mock/-/binding-mock-9.2.4.tgz", + "integrity": "sha512-dpEhACCs44oQhh6ajJfJdvQdK38Vq0N4W6iD/gdplglDCK7qXRQCMUjJIeKdS/HSEiWkC3bwumUhUufdsOyT4g==", + "dependencies": { + "@serialport/binding-abstract": "9.2.3", + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/bindings": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/@serialport/bindings/-/bindings-9.2.8.tgz", + "integrity": "sha512-hSLxTe0tADZ3LMMGwvEJWOC/TaFQTyPeFalUCsJ1lSQ0k6bPF04JwrtB/C81GetmDBTNRY0GlD0SNtKCc7Dr5g==", + "hasInstallScript": true, + "dependencies": { + "@serialport/binding-abstract": "9.2.3", + "@serialport/parser-readline": "9.2.4", + "bindings": "^1.5.0", + "debug": "^4.3.2", + "nan": "^2.15.0", + "prebuild-install": "^7.0.0" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-byte-length": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-byte-length/-/parser-byte-length-9.2.4.tgz", + "integrity": "sha512-sQD/iw4ZMU3xW9PLi0/GlvU6Y623jGeWecbMkO7izUo/6P7gtfv1c9ikd5h0kwL8AoAOpQA1lxdHIKox+umBUg==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-cctalk": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-cctalk/-/parser-cctalk-9.2.4.tgz", + "integrity": "sha512-T4TU5vQMwmo9AB3gQLFDWbfJXlW5jd9guEsB/nqKjFHTv0FXPdZ7DQ2TpSp8RnHWxU3GX6kYTaDO20BKzc8GPQ==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-delimiter": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-delimiter/-/parser-delimiter-9.2.4.tgz", + "integrity": "sha512-4nvTAoYAgkxFiXrkI+3CA49Yd43CODjeszh89EK+I9c8wOZ+etZduRCzINYPiy26g7zO+GRAb9FoPCsY+sYcbQ==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-inter-byte-timeout": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-inter-byte-timeout/-/parser-inter-byte-timeout-9.2.4.tgz", + "integrity": "sha512-SOAdvr0oBQIOCXX198hiTlxs4JTKg9j5piapw5tNq52fwDOWdbYrFneT/wN04UTMKaDrJuEvXq6T4rv4j7nJ5A==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-readline": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-readline/-/parser-readline-9.2.4.tgz", + "integrity": "sha512-Z1/qrZTQUVhNSJP1hd9YfDvq0o7d87rNwAjjRKbVpa7Qi51tG5BnKt43IV3NFMyBlVcRe0rnIb3tJu57E0SOwg==", + "dependencies": { + "@serialport/parser-delimiter": "9.2.4" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-ready": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-ready/-/parser-ready-9.2.4.tgz", + "integrity": "sha512-Pyi94Itjl6qAURwIZr/gmZpMAyTmKXThm6vL5DoAWGQjcRHWB0gwv2TY2v7N+mQLJYUKU3cMnvnATXxHm7xjxw==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-regex": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-regex/-/parser-regex-9.2.4.tgz", + "integrity": "sha512-sI/cVvPOYz+Dbv4ZdnW16qAwvXiFf/1pGASQdbveRTlgJDdz7sRNlCBifzfTN2xljwvCTZYqiudKvDdC1TepRQ==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/stream": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/stream/-/stream-9.2.4.tgz", + "integrity": "sha512-bLye8Ub4vUFQGmkh8qEqehr7SE7EJs2yDs0h9jzuL5oKi+F34CFmWkEErO8GAOQ8YNn7p6b3GxUgs+0BrHHDZQ==", + "dependencies": { + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "node_modules/are-we-there-yet": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", + "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/base64-js": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", + "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==" + }, + "node_modules/bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "dependencies": { + "file-uri-to-path": "1.0.0" + } + }, + "node_modules/bitwise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/bitwise/-/bitwise-2.1.0.tgz", + "integrity": "sha512-XKgAhMXCh4H/3oNwAHAsAO0iC89s9cOiumgYwSHjSobGWxYjv62YhkL9QEdvGP151xypCtMlAfKK79GEcd2eRQ==" + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/bl/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/buffer": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz", + "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==", + "dependencies": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + }, + "node_modules/buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" + }, + "node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, + "node_modules/code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/commist": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/commist/-/commist-1.1.0.tgz", + "integrity": "sha512-rraC8NXWOEjhADbZe9QBNzLAN5Q3fsTPQtBV+fEVj6xKIgDgNiEVE6ZNfHpZOqfQ21YUzfVNUXLOEZquYvQPPg==", + "dependencies": { + "leven": "^2.1.0", + "minimist": "^1.1.0" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "node_modules/concat-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", + "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", + "engines": [ + "node >= 6.0" + ], + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.0.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/concat-stream/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" + }, + "node_modules/core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "node_modules/crc": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/crc/-/crc-3.4.0.tgz", + "integrity": "sha512-ycVC2+4/DLgXXq7QweYi2znhqDuZz6P5TQXnkQo8v15XY/5p/IWeZwsSE31Ifo8w15b8TWLsqhXOjXyilHuQxw==" + }, + "node_modules/date-format": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.11.tgz", + "integrity": "sha512-VS20KRyorrbMCQmpdl2hg5KaOUsda1RbnsJg461FfrcyCUg+pkd0b40BSW4niQyTheww4DBXQnS7HwSrKkipLw==", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" + }, + "node_modules/detect-libc": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz", + "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==", + "engines": { + "node": ">=8" + } + }, + "node_modules/duplexify": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.2.tgz", + "integrity": "sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw==", + "dependencies": { + "end-of-stream": "^1.4.1", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1", + "stream-shift": "^1.0.0" + } + }, + "node_modules/duplexify/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/easy-crc": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/easy-crc/-/easy-crc-0.0.2.tgz", + "integrity": "sha512-h6eqIdhJRe0p271/xZJbM/0klCi13mW5IB7ZEzEGH11yV4QXWAkD4yPErz0fXdhFrd6sZ4Q1k5Iky2kMsMNePw==" + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" + }, + "node_modules/flatted": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", + "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==" + }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, + "node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "node_modules/gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha512-14x4kjc6lkD3ltw589k0NrPD6cCNTD6CWoVUNpB85+DrtONoZn+Rug6xZU5RvSC4+TZPxA5AnBibQYAvZn41Hg==", + "dependencies": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "node_modules/github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==" + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" + }, + "node_modules/has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" + }, + "node_modules/help-me": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/help-me/-/help-me-3.0.0.tgz", + "integrity": "sha512-hx73jClhyk910sidBB7ERlnhMlFsJJIBqSVMFDwPN8o2v9nmp5KgLq1Xz1Bf1fCMMZ6mPrX159iG0VLy/fPMtQ==", + "dependencies": { + "glob": "^7.1.6", + "readable-stream": "^3.6.0" + } + }, + "node_modules/help-me/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, + "node_modules/is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==", + "dependencies": { + "number-is-nan": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "node_modules/js-sdsl": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz", + "integrity": "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/js-sdsl" + } + }, + "node_modules/jsmodbus": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/jsmodbus/-/jsmodbus-4.0.6.tgz", + "integrity": "sha512-gCmjoaERErK5Rn9Lu/BN07fY13MoWV7JKgGzrnkPlQPdPxYcwDhLtYcmpFFpZ4J9NPZZBSezi1UkLZO/DnNppA==", + "dependencies": { + "crc": "3.4.0", + "debug": "^3.1.0" + }, + "bin": { + "jsmodbus": "bin/jsmodbus.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/jsmodbus/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/leven": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", + "integrity": "sha1-wuep93IJTe6dNCAq6KzORoeHVYA=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/log4js": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.5.2.tgz", + "integrity": "sha512-DXtpNtt+KDOMT7RHUDIur/WsSA3rntlUh9Zg4XCdV42wUuMmbFkl38+LZ92Z5QvQA7mD5kAVkLiBSEH/tvUB8A==", + "dependencies": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "flatted": "^3.2.5", + "rfdc": "^1.3.0", + "streamroller": "^3.1.1" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" + }, + "node_modules/moment": { + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", + "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==", + "engines": { + "node": "*" + } + }, + "node_modules/mqtt": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/mqtt/-/mqtt-4.3.7.tgz", + "integrity": "sha512-ew3qwG/TJRorTz47eW46vZ5oBw5MEYbQZVaEji44j5lAUSQSqIEoul7Kua/BatBW0H0kKQcC9kwUHa1qzaWHSw==", + "dependencies": { + "commist": "^1.0.0", + "concat-stream": "^2.0.0", + "debug": "^4.1.1", + "duplexify": "^4.1.1", + "help-me": "^3.0.0", + "inherits": "^2.0.3", + "lru-cache": "^6.0.0", + "minimist": "^1.2.5", + "mqtt-packet": "^6.8.0", + "number-allocator": "^1.0.9", + "pump": "^3.0.0", + "readable-stream": "^3.6.0", + "reinterval": "^1.1.0", + "rfdc": "^1.3.0", + "split2": "^3.1.0", + "ws": "^7.5.5", + "xtend": "^4.0.2" + }, + "bin": { + "mqtt": "bin/mqtt.js", + "mqtt_pub": "bin/pub.js", + "mqtt_sub": "bin/sub.js" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/mqtt-packet": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/mqtt-packet/-/mqtt-packet-6.10.0.tgz", + "integrity": "sha512-ja8+mFKIHdB1Tpl6vac+sktqy3gA8t9Mduom1BA75cI+R9AHnZOiaBQwpGiWnaVJLDGRdNhQmFaAqd7tkKSMGA==", + "dependencies": { + "bl": "^4.0.2", + "debug": "^4.1.1", + "process-nextick-args": "^2.0.1" + } + }, + "node_modules/mqtt/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/nan": { + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.16.0.tgz", + "integrity": "sha512-UdAqHyFngu7TfQKsCBgAA6pWDkT8MAO7d0jyOecVhN5354xbLqdn8mV9Tat9gepAupm0bt2DbeaSC8vS52MuFA==" + }, + "node_modules/napi-build-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", + "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==" + }, + "node_modules/node-abi": { + "version": "3.22.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.22.0.tgz", + "integrity": "sha512-u4uAs/4Zzmp/jjsD9cyFYDXeISfUWaAVWshPmDZOFOv4Xl4SbzTXm53I04C2uRueYJ+0t5PEtLH/owbn2Npf/w==", + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/nodemailer": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.7.tgz", + "integrity": "sha512-rUtR77ksqex/eZRLmQ21LKVH5nAAsVicAtAYudK7JgwenEDZ0UIQ1adUGqErz7sMkWYxWTTU1aeP2Jga6WQyJw==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "dependencies": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "node_modules/number-allocator": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/number-allocator/-/number-allocator-1.0.14.tgz", + "integrity": "sha512-OrL44UTVAvkKdOdRQZIJpLkAdjXGTRda052sN4sO77bKEzYYqWKMBjQvrJFzqygI99gL6Z4u2xctPW1tB8ErvA==", + "dependencies": { + "debug": "^4.3.1", + "js-sdsl": "4.3.0" + } + }, + "node_modules/number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/prebuild-install": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.0.tgz", + "integrity": "sha512-CNcMgI1xBypOyGqjp3wOc8AAo1nMhZS3Cwd3iHIxOdAUbb+YxdNuM4Z5iIrZ8RLvOsf3F3bl7b7xGq6DjQoNYA==", + "dependencies": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^1.0.1", + "node-abi": "^3.3.0", + "npmlog": "^4.0.1", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + }, + "bin": { + "prebuild-install": "bin.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/reinterval": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reinterval/-/reinterval-1.1.0.tgz", + "integrity": "sha1-M2Hs+jymwYKDOA3Qu5VG85D17Oc=" + }, + "node_modules/rfdc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==" + }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/serialport": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/serialport/-/serialport-9.2.8.tgz", + "integrity": "sha512-FsWpMQgSJxi93JgWl5xM1f9/Z8IjRJuaUEoHqLf8FPBLw7gMhInuHOBhI2onQufWIYPGTz3H3oGcu1nCaK1EfA==", + "dependencies": { + "@serialport/binding-mock": "9.2.4", + "@serialport/bindings": "9.2.8", + "@serialport/parser-byte-length": "9.2.4", + "@serialport/parser-cctalk": "9.2.4", + "@serialport/parser-delimiter": "9.2.4", + "@serialport/parser-inter-byte-timeout": "9.2.4", + "@serialport/parser-readline": "9.2.4", + "@serialport/parser-ready": "9.2.4", + "@serialport/parser-regex": "9.2.4", + "@serialport/stream": "9.2.4", + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "node_modules/split2": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", + "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", + "dependencies": { + "readable-stream": "^3.0.0" + } + }, + "node_modules/split2/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==" + }, + "node_modules/streamroller": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.1.1.tgz", + "integrity": "sha512-iPhtd9unZ6zKdWgMeYGfSBuqCngyJy1B/GPi/lTpwGpa3bajuX30GjUVd0/Tn/Xhg0mr4DOSENozz9Y06qyonQ==", + "dependencies": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "fs-extra": "^10.1.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dependencies": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/tar-fs": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "dependencies": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tar-stream/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/total.js": { + "version": "3.4.13", + "resolved": "https://registry.npmjs.org/total.js/-/total.js-3.4.13.tgz", + "integrity": "sha512-lAH4gEixlPFbrE3xfKADAcHfO79IFq2wKa9GTsrgRzIR5MTg3mNH7+4IxvX1pK8faoYb/0oYSJ1YTsAa5hIFFQ==", + "bin": { + "total": "bin/totaljs", + "total.js": "bin/totaljs", + "totaljs": "bin/totaljs", + "totalpackage": "bin/tpm", + "tpm": "bin/tpm" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, + "node_modules/universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "node_modules/wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "node_modules/ws": { + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } + }, + "dependencies": { + "@serialport/binding-abstract": { + "version": "9.2.3", + "resolved": "https://registry.npmjs.org/@serialport/binding-abstract/-/binding-abstract-9.2.3.tgz", + "integrity": "sha512-cQs9tbIlG3P0IrOWyVirqlhWuJ7Ms2Zh9m2108z6Y5UW/iVj6wEOiW8EmK9QX9jmJXYllE7wgGgvVozP5oCj3w==", + "requires": { + "debug": "^4.3.2" + } + }, + "@serialport/binding-mock": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/binding-mock/-/binding-mock-9.2.4.tgz", + "integrity": "sha512-dpEhACCs44oQhh6ajJfJdvQdK38Vq0N4W6iD/gdplglDCK7qXRQCMUjJIeKdS/HSEiWkC3bwumUhUufdsOyT4g==", + "requires": { + "@serialport/binding-abstract": "9.2.3", + "debug": "^4.3.2" + } + }, + "@serialport/bindings": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/@serialport/bindings/-/bindings-9.2.8.tgz", + "integrity": "sha512-hSLxTe0tADZ3LMMGwvEJWOC/TaFQTyPeFalUCsJ1lSQ0k6bPF04JwrtB/C81GetmDBTNRY0GlD0SNtKCc7Dr5g==", + "requires": { + "@serialport/binding-abstract": "9.2.3", + "@serialport/parser-readline": "9.2.4", + "bindings": "^1.5.0", + "debug": "^4.3.2", + "nan": "^2.15.0", + "prebuild-install": "^7.0.0" + } + }, + "@serialport/parser-byte-length": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-byte-length/-/parser-byte-length-9.2.4.tgz", + "integrity": "sha512-sQD/iw4ZMU3xW9PLi0/GlvU6Y623jGeWecbMkO7izUo/6P7gtfv1c9ikd5h0kwL8AoAOpQA1lxdHIKox+umBUg==" + }, + "@serialport/parser-cctalk": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-cctalk/-/parser-cctalk-9.2.4.tgz", + "integrity": "sha512-T4TU5vQMwmo9AB3gQLFDWbfJXlW5jd9guEsB/nqKjFHTv0FXPdZ7DQ2TpSp8RnHWxU3GX6kYTaDO20BKzc8GPQ==" + }, + "@serialport/parser-delimiter": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-delimiter/-/parser-delimiter-9.2.4.tgz", + "integrity": "sha512-4nvTAoYAgkxFiXrkI+3CA49Yd43CODjeszh89EK+I9c8wOZ+etZduRCzINYPiy26g7zO+GRAb9FoPCsY+sYcbQ==" + }, + "@serialport/parser-inter-byte-timeout": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-inter-byte-timeout/-/parser-inter-byte-timeout-9.2.4.tgz", + "integrity": "sha512-SOAdvr0oBQIOCXX198hiTlxs4JTKg9j5piapw5tNq52fwDOWdbYrFneT/wN04UTMKaDrJuEvXq6T4rv4j7nJ5A==" + }, + "@serialport/parser-readline": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-readline/-/parser-readline-9.2.4.tgz", + "integrity": "sha512-Z1/qrZTQUVhNSJP1hd9YfDvq0o7d87rNwAjjRKbVpa7Qi51tG5BnKt43IV3NFMyBlVcRe0rnIb3tJu57E0SOwg==", + "requires": { + "@serialport/parser-delimiter": "9.2.4" + } + }, + "@serialport/parser-ready": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-ready/-/parser-ready-9.2.4.tgz", + "integrity": "sha512-Pyi94Itjl6qAURwIZr/gmZpMAyTmKXThm6vL5DoAWGQjcRHWB0gwv2TY2v7N+mQLJYUKU3cMnvnATXxHm7xjxw==" + }, + "@serialport/parser-regex": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-regex/-/parser-regex-9.2.4.tgz", + "integrity": "sha512-sI/cVvPOYz+Dbv4ZdnW16qAwvXiFf/1pGASQdbveRTlgJDdz7sRNlCBifzfTN2xljwvCTZYqiudKvDdC1TepRQ==" + }, + "@serialport/stream": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/stream/-/stream-9.2.4.tgz", + "integrity": "sha512-bLye8Ub4vUFQGmkh8qEqehr7SE7EJs2yDs0h9jzuL5oKi+F34CFmWkEErO8GAOQ8YNn7p6b3GxUgs+0BrHHDZQ==", + "requires": { + "debug": "^4.3.2" + } + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==" + }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "are-we-there-yet": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", + "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "base64-js": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", + "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==" + }, + "bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "requires": { + "file-uri-to-path": "1.0.0" + } + }, + "bitwise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/bitwise/-/bitwise-2.1.0.tgz", + "integrity": "sha512-XKgAhMXCh4H/3oNwAHAsAO0iC89s9cOiumgYwSHjSobGWxYjv62YhkL9QEdvGP151xypCtMlAfKK79GEcd2eRQ==" + }, + "bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "requires": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "buffer": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz", + "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==", + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" + }, + "chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==" + }, + "commist": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/commist/-/commist-1.1.0.tgz", + "integrity": "sha512-rraC8NXWOEjhADbZe9QBNzLAN5Q3fsTPQtBV+fEVj6xKIgDgNiEVE6ZNfHpZOqfQ21YUzfVNUXLOEZquYvQPPg==", + "requires": { + "leven": "^2.1.0", + "minimist": "^1.1.0" + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "concat-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", + "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.0.2", + "typedarray": "^0.0.6" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "crc": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/crc/-/crc-3.4.0.tgz", + "integrity": "sha512-ycVC2+4/DLgXXq7QweYi2znhqDuZz6P5TQXnkQo8v15XY/5p/IWeZwsSE31Ifo8w15b8TWLsqhXOjXyilHuQxw==" + }, + "date-format": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.11.tgz", + "integrity": "sha512-VS20KRyorrbMCQmpdl2hg5KaOUsda1RbnsJg461FfrcyCUg+pkd0b40BSW4niQyTheww4DBXQnS7HwSrKkipLw==" + }, + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "requires": { + "ms": "2.1.2" + } + }, + "decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "requires": { + "mimic-response": "^3.1.0" + } + }, + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==" + }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" + }, + "detect-libc": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz", + "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==" + }, + "duplexify": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.2.tgz", + "integrity": "sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw==", + "requires": { + "end-of-stream": "^1.4.1", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1", + "stream-shift": "^1.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "easy-crc": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/easy-crc/-/easy-crc-0.0.2.tgz", + "integrity": "sha512-h6eqIdhJRe0p271/xZJbM/0klCi13mW5IB7ZEzEGH11yV4QXWAkD4yPErz0fXdhFrd6sZ4Q1k5Iky2kMsMNePw==" + }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "requires": { + "once": "^1.4.0" + } + }, + "expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==" + }, + "file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" + }, + "flatted": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", + "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==" + }, + "fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, + "fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha512-14x4kjc6lkD3ltw589k0NrPD6cCNTD6CWoVUNpB85+DrtONoZn+Rug6xZU5RvSC4+TZPxA5AnBibQYAvZn41Hg==", + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==" + }, + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" + }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" + }, + "help-me": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/help-me/-/help-me-3.0.0.tgz", + "integrity": "sha512-hx73jClhyk910sidBB7ERlnhMlFsJJIBqSVMFDwPN8o2v9nmp5KgLq1Xz1Bf1fCMMZ6mPrX159iG0VLy/fPMtQ==", + "requires": { + "glob": "^7.1.6", + "readable-stream": "^3.6.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==", + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "js-sdsl": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz", + "integrity": "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==" + }, + "jsmodbus": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/jsmodbus/-/jsmodbus-4.0.6.tgz", + "integrity": "sha512-gCmjoaERErK5Rn9Lu/BN07fY13MoWV7JKgGzrnkPlQPdPxYcwDhLtYcmpFFpZ4J9NPZZBSezi1UkLZO/DnNppA==", + "requires": { + "crc": "3.4.0", + "debug": "^3.1.0" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "requires": { + "ms": "^2.1.1" + } + } + } + }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, + "leven": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", + "integrity": "sha1-wuep93IJTe6dNCAq6KzORoeHVYA=" + }, + "log4js": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.5.2.tgz", + "integrity": "sha512-DXtpNtt+KDOMT7RHUDIur/WsSA3rntlUh9Zg4XCdV42wUuMmbFkl38+LZ92Z5QvQA7mD5kAVkLiBSEH/tvUB8A==", + "requires": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "flatted": "^3.2.5", + "rfdc": "^1.3.0", + "streamroller": "^3.1.1" + } + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "requires": { + "yallist": "^4.0.0" + } + }, + "mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==" + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==" + }, + "mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" + }, + "moment": { + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", + "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==" + }, + "mqtt": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/mqtt/-/mqtt-4.3.7.tgz", + "integrity": "sha512-ew3qwG/TJRorTz47eW46vZ5oBw5MEYbQZVaEji44j5lAUSQSqIEoul7Kua/BatBW0H0kKQcC9kwUHa1qzaWHSw==", + "requires": { + "commist": "^1.0.0", + "concat-stream": "^2.0.0", + "debug": "^4.1.1", + "duplexify": "^4.1.1", + "help-me": "^3.0.0", + "inherits": "^2.0.3", + "lru-cache": "^6.0.0", + "minimist": "^1.2.5", + "mqtt-packet": "^6.8.0", + "number-allocator": "^1.0.9", + "pump": "^3.0.0", + "readable-stream": "^3.6.0", + "reinterval": "^1.1.0", + "rfdc": "^1.3.0", + "split2": "^3.1.0", + "ws": "^7.5.5", + "xtend": "^4.0.2" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "mqtt-packet": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/mqtt-packet/-/mqtt-packet-6.10.0.tgz", + "integrity": "sha512-ja8+mFKIHdB1Tpl6vac+sktqy3gA8t9Mduom1BA75cI+R9AHnZOiaBQwpGiWnaVJLDGRdNhQmFaAqd7tkKSMGA==", + "requires": { + "bl": "^4.0.2", + "debug": "^4.1.1", + "process-nextick-args": "^2.0.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "nan": { + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.16.0.tgz", + "integrity": "sha512-UdAqHyFngu7TfQKsCBgAA6pWDkT8MAO7d0jyOecVhN5354xbLqdn8mV9Tat9gepAupm0bt2DbeaSC8vS52MuFA==" + }, + "napi-build-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", + "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==" + }, + "node-abi": { + "version": "3.22.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.22.0.tgz", + "integrity": "sha512-u4uAs/4Zzmp/jjsD9cyFYDXeISfUWaAVWshPmDZOFOv4Xl4SbzTXm53I04C2uRueYJ+0t5PEtLH/owbn2Npf/w==", + "requires": { + "semver": "^7.3.5" + } + }, + "nodemailer": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.7.tgz", + "integrity": "sha512-rUtR77ksqex/eZRLmQ21LKVH5nAAsVicAtAYudK7JgwenEDZ0UIQ1adUGqErz7sMkWYxWTTU1aeP2Jga6WQyJw==" + }, + "npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "number-allocator": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/number-allocator/-/number-allocator-1.0.14.tgz", + "integrity": "sha512-OrL44UTVAvkKdOdRQZIJpLkAdjXGTRda052sN4sO77bKEzYYqWKMBjQvrJFzqygI99gL6Z4u2xctPW1tB8ErvA==", + "requires": { + "debug": "^4.3.1", + "js-sdsl": "4.3.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==" + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==" + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==" + }, + "prebuild-install": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.0.tgz", + "integrity": "sha512-CNcMgI1xBypOyGqjp3wOc8AAo1nMhZS3Cwd3iHIxOdAUbb+YxdNuM4Z5iIrZ8RLvOsf3F3bl7b7xGq6DjQoNYA==", + "requires": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^1.0.1", + "node-abi": "^3.3.0", + "npmlog": "^4.0.1", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + } + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + } + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "reinterval": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reinterval/-/reinterval-1.1.0.tgz", + "integrity": "sha1-M2Hs+jymwYKDOA3Qu5VG85D17Oc=" + }, + "rfdc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==" + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "requires": { + "lru-cache": "^6.0.0" + } + }, + "serialport": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/serialport/-/serialport-9.2.8.tgz", + "integrity": "sha512-FsWpMQgSJxi93JgWl5xM1f9/Z8IjRJuaUEoHqLf8FPBLw7gMhInuHOBhI2onQufWIYPGTz3H3oGcu1nCaK1EfA==", + "requires": { + "@serialport/binding-mock": "9.2.4", + "@serialport/bindings": "9.2.8", + "@serialport/parser-byte-length": "9.2.4", + "@serialport/parser-cctalk": "9.2.4", + "@serialport/parser-delimiter": "9.2.4", + "@serialport/parser-inter-byte-timeout": "9.2.4", + "@serialport/parser-readline": "9.2.4", + "@serialport/parser-ready": "9.2.4", + "@serialport/parser-regex": "9.2.4", + "@serialport/stream": "9.2.4", + "debug": "^4.3.2" + } + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==" + }, + "simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "requires": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "split2": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", + "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", + "requires": { + "readable-stream": "^3.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==" + }, + "streamroller": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.1.1.tgz", + "integrity": "sha512-iPhtd9unZ6zKdWgMeYGfSBuqCngyJy1B/GPi/lTpwGpa3bajuX30GjUVd0/Tn/Xhg0mr4DOSENozz9Y06qyonQ==", + "requires": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "fs-extra": "^10.1.0" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" + }, + "tar-fs": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "requires": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "requires": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "total.js": { + "version": "3.4.13", + "resolved": "https://registry.npmjs.org/total.js/-/total.js-3.4.13.tgz", + "integrity": "sha512-lAH4gEixlPFbrE3xfKADAcHfO79IFq2wKa9GTsrgRzIR5MTg3mNH7+4IxvX1pK8faoYb/0oYSJ1YTsAa5hIFFQ==" + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, + "universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==" + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "requires": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "ws": { + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "requires": {} + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } + } +} diff --git a/RVO47/package.json b/RVO47/package.json new file mode 100755 index 0000000..7f7c795 --- /dev/null +++ b/RVO47/package.json @@ -0,0 +1,30 @@ +{ + "name": "emptyproject", + "description": "Total.js empty project.", + "version": "1.0.0", + "main": "debug.js", + "dependencies": { + "bitwise": "^2.1.0", + "easy-crc": "0.0.2", + "jsmodbus": "^4.0.6", + "log4js": "^6.3.0", + "moment": "^2.30.1", + "mqtt": "^4.2.6", + "nodemailer": "^6.9.7", + "serialport": "^9.2.8", + "total.js": "^3.4.13" + }, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "https://github.com/totaljs/emptyproject-flow" + }, + "keywords": [ + "empty", + "project" + ], + "author": "Peter Širka", + "license": "MIT" +} diff --git a/RVO47/release.js b/RVO47/release.js new file mode 100755 index 0000000..02d52ff --- /dev/null +++ b/RVO47/release.js @@ -0,0 +1,15 @@ +// =================================================== +// FOR PRODUCTION +// Total.js - framework for Node.js platform +// https://www.totaljs.com +// =================================================== + +const options = {'ip':'0.0.0.0', 'port':12345}; + +// options.ip = '127.0.0.1'; +// options.port = parseInt(process.argv[2]); +// options.config = { name: 'Total.js' }; +// options.sleep = 3000; + +require('total.js').http('release', options); +// require('total.js').cluster.http(5, 'release', options); diff --git a/RVO47/release.js.json b/RVO47/release.js.json new file mode 100755 index 0000000..e71325c --- /dev/null +++ b/RVO47/release.js.json @@ -0,0 +1,34 @@ +{ + "pid": 379, + "stats": [ + { + "id": null, + "version": { + "node": "v14.18.1", + "total": "3.4.13", + "app": "1.0.0" + }, + "pid": 379, + "thread": "", + "mode": "release", + "overload": 0, + "date": "2025-10-16T00:26:51.150Z", + "memory": 22.56, + "rm": 0, + "fm": 0, + "wm": 0, + "mm": 0, + "om": 2, + "em": 0, + "dbrm": 0, + "dbwm": 0, + "usage": 0, + "requests": 7, + "pending": 0, + "errors": 0, + "timeouts": 0, + "uptime": 865, + "online": 0 + } + ] +} \ No newline at end of file diff --git a/RVO47/report_data.log b/RVO47/report_data.log new file mode 100755 index 0000000..d35ddd9 --- /dev/null +++ b/RVO47/report_data.log @@ -0,0 +1,196 @@ +{ + "name": "rvo_senica_47_10.0.0.134", + "time": "2025-10-15T11:03:06.075Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_47_10.0.0.134", + "time": "2025-10-15T12:03:06.073Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_47_10.0.0.134", + "time": "2025-10-15T13:03:06.074Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_47_10.0.0.134", + "time": "2025-10-15T14:03:06.074Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_47_10.0.0.134", + "time": "2025-10-15T15:03:06.075Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_47_10.0.0.134", + "time": "2025-10-15T17:03:01.337Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_47_10.0.0.134", + "time": "2025-10-15T18:03:01.337Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_47_10.0.0.134", + "time": "2025-10-15T19:03:01.337Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_47_10.0.0.134", + "time": "2025-10-15T20:03:01.337Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_47_10.0.0.134", + "time": "2025-10-15T21:03:01.337Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_47_10.0.0.134", + "time": "2025-10-15T22:03:01.337Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_47_10.0.0.134", + "time": "2025-10-15T23:03:01.337Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_47_10.0.0.134", + "time": "2025-10-16T00:03:01.337Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +} \ No newline at end of file From fa5565e6500a46640d67d836eeb5bb8034ada9fd Mon Sep 17 00:00:00 2001 From: Jakub Klena Date: Thu, 16 Oct 2025 02:27:31 +0200 Subject: [PATCH 28/30] Backup senica-RVO48 on 16.10.2025 --- RVO48/addSwitch.py | 36 + RVO48/cloud_topic.py | 76 + RVO48/config | 12 + RVO48/createNode.py | 43 + RVO48/databases/accelerometer_db.js | 3055 +++++++++++ RVO48/databases/modbus_config.js | 114 + RVO48/databases/nodes.table | 21 + .../nodes_original/nodes_original.table | 1 + RVO48/databases/notifications.table | 41 + RVO48/databases/pins.table | 14 + RVO48/databases/relays.table | 5 + RVO48/databases/settings.table | 2 + RVO48/databases/tbdata.nosql | 4 + RVO48/databases/tbdatacloud.nosql | 3 + RVO48/databases/total_energy.js | 38 + RVO48/debug.js | 16 + RVO48/err.txt | 126 + RVO48/flow/cloudmqttconnect.js | 357 ++ RVO48/flow/cmd_manager.js | 3071 +++++++++++ RVO48/flow/code.js | 90 + RVO48/flow/comment.js | 11 + RVO48/flow/count.js | 60 + RVO48/flow/db_connector.js | 286 ++ RVO48/flow/db_init.js | 113 + RVO48/flow/debug.js | 100 + RVO48/flow/designer.json | 3102 +++++++++++ RVO48/flow/dido_controller.js | 1486 ++++++ RVO48/flow/helper/DataToTbHandler.js | 187 + RVO48/flow/helper/ErrorToServiceHandler.js | 91 + RVO48/flow/helper/db_helper.js | 44 + RVO48/flow/helper/logger.js | 30 + RVO48/flow/helper/md5.js | 5 + RVO48/flow/helper/notification_reporter.js | 121 + RVO48/flow/helper/register.js | 144 + RVO48/flow/helper/serialport_helper.js | 99 + RVO48/flow/helper/suncalc.js | 317 ++ RVO48/flow/helper/utils.js | 161 + RVO48/flow/httprequest.js | 137 + RVO48/flow/httpresponse.js | 76 + RVO48/flow/httproute.js | 326 ++ RVO48/flow/infosender.js | 81 + RVO48/flow/modbus_reader.js | 346 ++ RVO48/flow/monitorconsumption.js | 156 + RVO48/flow/monitordisk.js | 96 + RVO48/flow/monitormemory.js | 87 + RVO48/flow/nodesdb_changecheck.js | 77 + RVO48/flow/show_dbdata.js | 243 + RVO48/flow/slack_filter.js | 188 + RVO48/flow/thermometer.js | 99 + RVO48/flow/trigger.js | 79 + RVO48/flow/variables.txt | 0 RVO48/flow/virtualwirein.js | 43 + RVO48/flow/virtualwireout.js | 41 + RVO48/flow/wsmqttpublish.js | 448 ++ RVO48/monitor.txt | 4562 +++++++++++++++++ RVO48/package-lock.json | 2125 ++++++++ RVO48/package.json | 29 + RVO48/release.js | 15 + RVO48/release.js.json | 34 + RVO48/report_data.log | 195 + 60 files changed, 22965 insertions(+) create mode 100755 RVO48/addSwitch.py create mode 100755 RVO48/cloud_topic.py create mode 100755 RVO48/config create mode 100755 RVO48/createNode.py create mode 100755 RVO48/databases/accelerometer_db.js create mode 100755 RVO48/databases/modbus_config.js create mode 100755 RVO48/databases/nodes.table create mode 100755 RVO48/databases/nodes_original/nodes_original.table create mode 100755 RVO48/databases/notifications.table create mode 100755 RVO48/databases/pins.table create mode 100755 RVO48/databases/relays.table create mode 100755 RVO48/databases/settings.table create mode 100755 RVO48/databases/tbdata.nosql create mode 100755 RVO48/databases/tbdatacloud.nosql create mode 100755 RVO48/databases/total_energy.js create mode 100755 RVO48/debug.js create mode 100755 RVO48/err.txt create mode 100755 RVO48/flow/cloudmqttconnect.js create mode 100755 RVO48/flow/cmd_manager.js create mode 100755 RVO48/flow/code.js create mode 100755 RVO48/flow/comment.js create mode 100755 RVO48/flow/count.js create mode 100755 RVO48/flow/db_connector.js create mode 100755 RVO48/flow/db_init.js create mode 100755 RVO48/flow/debug.js create mode 100755 RVO48/flow/designer.json create mode 100755 RVO48/flow/dido_controller.js create mode 100755 RVO48/flow/helper/DataToTbHandler.js create mode 100755 RVO48/flow/helper/ErrorToServiceHandler.js create mode 100755 RVO48/flow/helper/db_helper.js create mode 100755 RVO48/flow/helper/logger.js create mode 100755 RVO48/flow/helper/md5.js create mode 100755 RVO48/flow/helper/notification_reporter.js create mode 100755 RVO48/flow/helper/register.js create mode 100755 RVO48/flow/helper/serialport_helper.js create mode 100755 RVO48/flow/helper/suncalc.js create mode 100755 RVO48/flow/helper/utils.js create mode 100755 RVO48/flow/httprequest.js create mode 100755 RVO48/flow/httpresponse.js create mode 100755 RVO48/flow/httproute.js create mode 100755 RVO48/flow/infosender.js create mode 100755 RVO48/flow/modbus_reader.js create mode 100755 RVO48/flow/monitorconsumption.js create mode 100755 RVO48/flow/monitordisk.js create mode 100755 RVO48/flow/monitormemory.js create mode 100755 RVO48/flow/nodesdb_changecheck.js create mode 100755 RVO48/flow/show_dbdata.js create mode 100755 RVO48/flow/slack_filter.js create mode 100755 RVO48/flow/thermometer.js create mode 100755 RVO48/flow/trigger.js create mode 100755 RVO48/flow/variables.txt create mode 100755 RVO48/flow/virtualwirein.js create mode 100755 RVO48/flow/virtualwireout.js create mode 100755 RVO48/flow/wsmqttpublish.js create mode 100755 RVO48/monitor.txt create mode 100755 RVO48/package-lock.json create mode 100755 RVO48/package.json create mode 100755 RVO48/release.js create mode 100755 RVO48/release.js.json create mode 100755 RVO48/report_data.log diff --git a/RVO48/addSwitch.py b/RVO48/addSwitch.py new file mode 100755 index 0000000..c35e96b --- /dev/null +++ b/RVO48/addSwitch.py @@ -0,0 +1,36 @@ +import os + +def process_set_file(): + """ + Checks if /root/flowserver exists, reads set.txt, and modifies the second line. + """ + default_folder = "/root/flowserver" if os.path.exists("/root/flowserver") else "/home/unipi/flowserver" + flag = 1 if default_folder == "/root/flowserver" else 0 + + try: + with open("/home/unipi/flowserver/databases/settings.table", "r") as f: + lines = f.readlines() + + if len(lines) >= 2: + lines[0] = lines[0].rstrip('\n') + "|main_switch:boolean\n" + second_line = lines[1].strip() # remove trailing newline + last_pipe_index = second_line.rfind("|") + + if last_pipe_index != -1: + modified_line = second_line[:last_pipe_index + 1] + str(flag) + "|" + second_line[last_pipe_index + 1:] + lines[1] = modified_line + else: + print("Warning: No '|' character found in the second line of set.txt") + + with open("/home/unipi/flowserver/databases/settings.table", "w") as f: + f.writelines(lines) + else: + print("Warning: settings.table has less than two lines.") + + except FileNotFoundError: + print("Error: settings.table not found.") + except Exception as e: + print(e) + +# if __name__ == "__main__": +process_set_file() diff --git a/RVO48/cloud_topic.py b/RVO48/cloud_topic.py new file mode 100755 index 0000000..77c31f1 --- /dev/null +++ b/RVO48/cloud_topic.py @@ -0,0 +1,76 @@ +# import os +# +# def modify_file(file_path): +# """ +# Modifies the given file by: +# 1. Appending "|cloud_topic" to the first line. +# 2. Inserting the text from the third "." to the first "|" on the second line after the last "|" character. +# +# Args: +# file_path (str): The path to the file to be modified. +# """ +# +# with open(file_path, 'r+') as f: +# lines = f.readlines() +# +# # Modify the first line +# lines[0] += "|cloud_topic:string" +# +# # Modify the second line +# second_line = lines[1].strip() # Remove leading/trailing whitespace +# first_pipe_index = second_line.find('|') +# third_dot_index = second_line.find('.', second_line.find('.', second_line.find('.') + 1) + 1) +# text_to_insert = second_line[third_dot_index:first_pipe_index] +# +# last_pipe_index = second_line.rfind('|') +# lines[1] = second_line[:last_pipe_index + 1] + text_to_insert + "|" + second_line[last_pipe_index + 1:] +# +# print(first_pipe_index, third_dot_index, text_to_insert, last_pipe_index) +# # Write the modified lines back to the file +# # f.seek(0) +# # f.writelines(lines) +# # f.truncate() +# +# # Example usage: +# file_path = "settings.table" # Replace with the actual file path +# modify_file(file_path) +# + + +def modify_file(file_path): + """ + Modifies the given file by: + 1. Appending "|cloud_topic" to the first line. + 2. Inserting the text between the third "." and the second "|" on the second line after the last "|" character. + + Args: + file_path (str): The path to the file to be modified. + """ + + with open(file_path, 'r+') as f: + lines = f.readlines() + + first_line = lines[0].strip() + first_line += "|cloud_topic:string\n" + # Modify the first line + lines[0] = first_line + + # Modify the second line + second_line = lines[1].strip() # Remove leading/trailing whitespace + first_pipe_index = second_line.find('|') + second_pipe_index = second_line.find('|', first_pipe_index + 1) + third_dot_index = second_line.find('.', second_line.find('.', second_line.find('.') + 1) + 1) + text_to_insert = "u" + second_line[third_dot_index+1:second_pipe_index] + + last_pipe_index = second_line.rfind('|') + lines[1] = second_line[:last_pipe_index + 1] + text_to_insert + "|" + second_line[last_pipe_index + 1:] + + print(first_pipe_index, third_dot_index, text_to_insert, last_pipe_index) + # Write the modified lines back to the file + f.seek(0) + f.writelines(lines) + f.truncate() + +# Example usage: +file_path = "/home/unipi/flowserver/databases/settings.table" # Replace with the actual file path +modify_file(file_path) diff --git a/RVO48/config b/RVO48/config new file mode 100755 index 0000000..cd0a8a9 --- /dev/null +++ b/RVO48/config @@ -0,0 +1,12 @@ +name : Total.js Flow +default_timezone : Europe/Bratislava + +// Packages settings +package#flow (Object) : { url: '/' } + + +table.relays : line:number|tbname:string|contactor:number|profile:string +table.nodes : node:number|pole_number:string|node_type:string|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|project_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|cloud_topic:string|has_main_switch:boolean|daily_report:boolean|send_changed_node_numbers:boolean +table.pins : pin:string|type:string|line:number +table.notifications : key:string|weight:string|sk:string|en:string diff --git a/RVO48/createNode.py b/RVO48/createNode.py new file mode 100755 index 0000000..a8cea91 --- /dev/null +++ b/RVO48/createNode.py @@ -0,0 +1,43 @@ +print("zaciname") +import re, json + +search_str = '|' +final = [] +counter = 1 +with open("/home/unipi/flowserver/databases/nodes.table", 'r') as file: +# with open("/home/rasta5man/dev/oms/flowserver/databases/nodes.table", 'r') as file: + # Read each line in the file + for line in file: + # Print each line + line = line.strip() + print(line) + if counter != 1: + i = [m.start() for m in re.finditer(re.escape(search_str), line)] + node = line[ i[0] + 1 : i[1] ] + tbname = line[ i[3] + 1 : i[4] ] + final.append({node:tbname}) + counter += 1 +print(json.dumps(final)) +f = open("/home/unipi/flowserver/databases/nodes_original/nodes_original.table", "w") +f.write(json.dumps(final)) +f.close() + + +# +# # ``d`` has to be replaced with a different character +# old_character = "'" +# +# # ``t`` will replace ``d` +# new_character = '"' +# resultant_string = 0; +# with open("/home/unipi/flowserver/databases/nodes_original/nodes_original.table", 'r') as file: +# for line in file: +# resultant_string = re.sub("'", '"', line) +# +# resultant_string = re.sub(" ", "", resultant_string) +# print(resultant_string) +# +# f = open("/home/unipi/flowserver/databases/nodes_original/nodes_original.table", "w") +# f.write(str(resultant_string)) +# f.close() +# diff --git a/RVO48/databases/accelerometer_db.js b/RVO48/databases/accelerometer_db.js new file mode 100755 index 0000000..fdfc7fd --- /dev/null +++ b/RVO48/databases/accelerometer_db.js @@ -0,0 +1,3055 @@ +let naklony = { + "3993": { "label": "1/3A", "naklon": 0 }, + "3989": { "label": "1/3B", "naklon": 15 }, + "3976": { "label": "1/1", "naklon": 0 }, + "4181": { "label": "1/2", "naklon": 0 }, + "4376": { "label": "1/4", "naklon": 15 }, + "3868": { "label": "1/5", "naklon": 15 }, + "3728": { "label": "1/6", "naklon": 15 }, + "3730": { "label": "1/7", "naklon": 0 }, + "4374": { "label": "1/8", "naklon": 0 }, + "3718": { "label": "1/9", "naklon": 15 }, + "4375": { "label": "1/10", "naklon": 15 }, + "4172": { "label": "1/11", "naklon": 15 }, + "4176": { "label": "1/12", "naklon": 15 }, + "3800": { "label": "2/1", "naklon": 5 }, + "3823": { "label": "2/2", "naklon": 5 }, + "3905": { "label": "2/3", "naklon": 5 }, + "3803": { "label": "2/4", "naklon": 5 }, + "3817": { "label": "2/5", "naklon": 5 }, + "3818": { "label": "2/6", "naklon": 5 }, + "3811": { "label": "2/7", "naklon": 5 }, + "3915": { "label": "2/8", "naklon": 5 }, + "3843": { "label": "2/9", "naklon": 10 }, + "3827": { "label": "2/10", "naklon": 10 }, + "4220": { "label": "2/11", "naklon": 10 }, + "3826": { "label": "2/12", "naklon": 10 }, + "3834": { "label": "2/13", "naklon": 10 }, + "3838": { "label": "2/14", "naklon": 10 }, + "2823": { "label": "2/15", "naklon": 10 }, + "3750": { "label": "2/16", "naklon": 10 }, + "3378": { "label": "2/17", "naklon": 0 }, + "3376": { "label": "2/18", "naklon": 0 }, + "3379": { "label": "2/19", "naklon": 0 }, + "3285": { "label": "2/20", "naklon": 0 }, + "3382": { "label": "2/21", "naklon": 0 }, + "3383": { "label": "2/22", "naklon": 0 }, + "3375": { "label": "2/24", "naklon": 0 }, + "3381": { "label": "2/25", "naklon": 0 }, + "3380": { "label": "2/26", "naklon": 0 }, + "3828": { "label": "2/27", "naklon": 10 }, + "3377": { "label": "2/28", "naklon": 0 }, + "3591": { "label": "7/1", "naklon": 0 }, + "3587": { "label": "7/2", "naklon": 0 }, + "3468": { "label": "7/3", "naklon": 0 }, + "3466": { "label": "7/4", "naklon": 0 }, + "3474": { "label": "7/5", "naklon": 0 }, + "3481": { "label": "7/6", "naklon": 0 }, + "3589": { "label": "7/7", "naklon": 0 }, + "3472": { "label": "7/8", "naklon": 0 }, + "3473": { "label": "7/9", "naklon": 0 }, + "3584": { "label": "7/10", "naklon": 0 }, + "3571": { "label": "7/11", "naklon": 0 }, + "3476": { "label": "7/12", "naklon": 0 }, + "3590": { "label": "7/13", "naklon": 0 }, + "3478": { "label": "7/14", "naklon": 0 }, + "3471": { "label": "7/15", "naklon": 0 }, + "3467": { "label": "7/16", "naklon": 0 }, + "3479": { "label": "7/17", "naklon": 0 }, + "3480": { "label": "7/18", "naklon": 0 }, + "3477": { "label": "7/19", "naklon": 0 }, + "3362": { "label": "12/1", "naklon": 0 }, + "3355": { "label": "12/2", "naklon": 0 }, + "3356": { "label": "12/3", "naklon": 0 }, + "3349": { "label": "12/4", "naklon": 0 }, + "3357": { "label": "12/5", "naklon": 0 }, + "3350": { "label": "12/6", "naklon": 0 }, + "3353": { "label": "12/7", "naklon": 0 }, + "3539": { "label": "12/8", "naklon": 0 }, + "3050": { "label": "12/9", "naklon": 0 }, + "3361": { "label": "12/10", "naklon": 0 }, + "3360": { "label": "12/11", "naklon": 0 }, + "3358": { "label": "12/12", "naklon": 0 }, + "3541": { "label": "12/13", "naklon": 0 }, + "3551": { "label": "12/14", "naklon": 0 }, + "3514": { "label": "12/15", "naklon": 0 }, + "3547": { "label": "12/16", "naklon": 0 }, + "3562": { "label": "12/17", "naklon": 0 }, + "3525": { "label": "12/18", "naklon": 0 }, + "3558": { "label": "12/19", "naklon": 0 }, + "3511": { "label": "12/20", "naklon": 0 }, + "3058": { "label": "12/21", "naklon": 0 }, + "3062": { "label": "12/22", "naklon": 0 }, + "3070": { "label": "12/23", "naklon": 0 }, + "3447": { "label": "12/24", "naklon": 0 }, + "3056": { "label": "12/25", "naklon": 0 }, + "3057": { "label": "12/26", "naklon": 0 }, + "3071": { "label": "12/27", "naklon": 0 }, + "3061": { "label": "12/28", "naklon": 0 }, + "3069": { "label": "12/29", "naklon": 0 }, + "3077": { "label": "12/30", "naklon": 0 }, + "3080": { "label": "12/31", "naklon": 0 }, + "3081": { "label": "12/32", "naklon": 0 }, + "3078": { "label": "12/33", "naklon": 0 }, + "4037": { "label": "12/34", "naklon": 0 }, + "3067": { "label": "12/35", "naklon": 0 }, + "3051": { "label": "12/36", "naklon": 0 }, + "2924": { "label": "12/37", "naklon": 0 }, + "3060": { "label": "12/38", "naklon": 0 }, + "3073": { "label": "12/39", "naklon": 0 }, + "3469": { "label": "12/40", "naklon": 0 }, + "2923": { "label": "12/41", "naklon": 0 }, + "2925": { "label": "12/42", "naklon": 0 }, + "3359": { "label": "12/43", "naklon": 0 }, + "3055": { "label": "12/44", "naklon": 0 }, + "2922": { "label": "12/45", "naklon": 0 }, + "3084": { "label": "12/46", "naklon": 0 }, + "3064": { "label": "12/47", "naklon": 0 }, + "3066": { "label": "12/48", "naklon": 0 }, + "3072": { "label": "12/49", "naklon": 0 }, + "3415": { "label": "13/13A", "naklon": 0 }, + "3409": { "label": "13/13B", "naklon": 0 }, + "3399": { "label": "13/13C", "naklon": 0 }, + "3410": { "label": "13/29A", "naklon": 0 }, + "3407": { "label": "13/29B", "naklon": 0 }, + "3405": { "label": "13/34A", "naklon": 0 }, + "3404": { "label": "13/34B", "naklon": 0 }, + "3392": { "label": "13/45A", "naklon": 0 }, + "3386": { "label": "13/45B", "naklon": 0 }, + "3303": { "label": "13/60A", "naklon": 3 }, + "3302": { "label": "13/60B", "naklon": 3 }, + "3319": { "label": "13/70A", "naklon": 6 }, + "3317": { "label": "13/70B", "naklon": 6 }, + "3326": { "label": "13/70C", "naklon": 6 }, + "3351": { "label": "13/73A", "naklon": 6 }, + "3313": { "label": "13/73B", "naklon": 6 }, + "3316": { "label": "13/83A", "naklon": 0 }, + "3320": { "label": "13/83B", "naklon": 0 }, + "3336": { "label": "13/95A", "naklon": 0 }, + "3323": { "label": "13/95B", "naklon": 0 }, + "3339": { "label": "13/98A", "naklon": 0 }, + "3333": { "label": "13/98B", "naklon": 0 }, + "3425": { "label": "13/1", "naklon": 0 }, + "3419": { "label": "13/2", "naklon": 0 }, + "3416": { "label": "13/3", "naklon": 0 }, + "3332": { "label": "13/4", "naklon": 0 }, + "3422": { "label": "13/5", "naklon": 0 }, + "3417": { "label": "13/6", "naklon": 0 }, + "3418": { "label": "13/7", "naklon": 0 }, + "3424": { "label": "13/8", "naklon": 0 }, + "3334": { "label": "13/9", "naklon": 0 }, + "4363": { "label": "13/10", "naklon": 0 }, + "3423": { "label": "13/11", "naklon": 0 }, + "3406": { "label": "13/12", "naklon": 0 }, + "3411": { "label": "13/14", "naklon": 0 }, + "3412": { "label": "13/15", "naklon": 0 }, + "3413": { "label": "13/16", "naklon": 0 }, + "3414": { "label": "13/17", "naklon": 0 }, + "3391": { "label": "13/18", "naklon": 0 }, + "3370": { "label": "13/19", "naklon": 0 }, + "3369": { "label": "13/20", "naklon": 0 }, + "3408": { "label": "13/21", "naklon": 0 }, + "3393": { "label": "13/22", "naklon": 0 }, + "3128": { "label": "13/23", "naklon": 0 }, + "3197": { "label": "13/24", "naklon": 0 }, + "4364": { "label": "13/25", "naklon": 0 }, + "3155": { "label": "13/26", "naklon": 0 }, + "3196": { "label": "13/27", "naklon": 0 }, + "3144": { "label": "13/28", "naklon": 0 }, + "3150": { "label": "13/30", "naklon": 0 }, + "3390": { "label": "13/31", "naklon": 0 }, + "3401": { "label": "13/32", "naklon": 0 }, + "3275": { "label": "13/33", "naklon": 0 }, + "3371": { "label": "13/35", "naklon": 0 }, + "3389": { "label": "13/36", "naklon": 0 }, + "3388": { "label": "13/37", "naklon": 0 }, + "3365": { "label": "13/38", "naklon": 0 }, + "3363": { "label": "13/39", "naklon": 0 }, + "3397": { "label": "13/40", "naklon": 0 }, + "3567": { "label": "13/40/1", "naklon": 0 }, + "3387": { "label": "13/41", "naklon": 0 }, + "3403": { "label": "13/42", "naklon": 0 }, + "3147": { "label": "13/43", "naklon": 0 }, + "3141": { "label": "13/44", "naklon": 0 }, + "3364": { "label": "13/46", "naklon": 0 }, + "3367": { "label": "13/47", "naklon": 0 }, + "3368": { "label": "13/48", "naklon": 0 }, + "3402": { "label": "13/49", "naklon": 0 }, + "3366": { "label": "13/50", "naklon": 0 }, + "3395": { "label": "13/51", "naklon": 0 }, + "3372": { "label": "13/52", "naklon": 0 }, + "3394": { "label": "13/53", "naklon": 0 }, + "3308": { "label": "13/54", "naklon": 0 }, + "3847": { "label": "13/54/1", "naklon": 0 }, + "3312": { "label": "13/55", "naklon": 3 }, + "3309": { "label": "13/56", "naklon": 3 }, + "3311": { "label": "13/57", "naklon": 3 }, + "3310": { "label": "13/58", "naklon": 3 }, + "4365": { "label": "13/59", "naklon": 3 }, + "4093": { "label": "13/60/1", "naklon": 3 }, + "3304": { "label": "13/61", "naklon": 3 }, + "3307": { "label": "13/62", "naklon": 3 }, + "3271": { "label": "13/63", "naklon": 3 }, + "3301": { "label": "13/64", "naklon": 3 }, + "4366": { "label": "13/65", "naklon": 3 }, + "3300": { "label": "13/66", "naklon": 3 }, + "3185": { "label": "13/67", "naklon": 0 }, + "3184": { "label": "13/68", "naklon": 0 }, + "3188": { "label": "13/69", "naklon": 0 }, + "3343": { "label": "13/71", "naklon": 6 }, + "3819": { "label": "13/71/1", "naklon": 6 }, + "3880": { "label": "13/71/2", "naklon": 6 }, + "3348": { "label": "13/72", "naklon": 6 }, + "3344": { "label": "13/74", "naklon": 6 }, + "3346": { "label": "13/75", "naklon": 6 }, + "3597": { "label": "13/75/1", "naklon": 6 }, + "3345": { "label": "13/76", "naklon": 6 }, + "3322": { "label": "13/77", "naklon": 0 }, + "3325": { "label": "13/78", "naklon": 0 }, + "4310": { "label": "13/78/1", "naklon": 0 }, + "3315": { "label": "13/79", "naklon": 0 }, + "3328": { "label": "13/80", "naklon": 0 }, + "3321": { "label": "13/81", "naklon": 0 }, + "3324": { "label": "13/82", "naklon": 0 }, + "3140": { "label": "13/84", "naklon": 0 }, + "3153": { "label": "13/85", "naklon": 0 }, + "3145": { "label": "13/86", "naklon": 0 }, + "3134": { "label": "13/87", "naklon": 0 }, + "3151": { "label": "13/88", "naklon": 0 }, + "3143": { "label": "13/89", "naklon": 0 }, + "3318": { "label": "13/90", "naklon": 0 }, + "3347": { "label": "13/91", "naklon": 0 }, + "3314": { "label": "13/94", "naklon": 0 }, + "3331": { "label": "13/96", "naklon": 0 }, + "3327": { "label": "13/97", "naklon": 0 }, + "3329": { "label": "13/99", "naklon": 0 }, + "3337": { "label": "13/100", "naklon": 0 }, + "3330": { "label": "13/101", "naklon": 0 }, + "3335": { "label": "13/102", "naklon": 0 }, + "3420": { "label": "13/103", "naklon": 0 }, + "3421": { "label": "13/104", "naklon": 0 }, + "4361": { "label": "13/105", "naklon": 0 }, + "4362": { "label": "13/106", "naklon": 0 }, + "3526": { "label": "13/107", "naklon": 0 }, + "4424": { "label": "13/108", "naklon": null }, + "3561": { "label": "13/109", "naklon": null }, + "3527": { "label": "13/110", "naklon": null }, + "3521": { "label": "13/111", "naklon": null }, + "3552": { "label": "13/112", "naklon": null }, + "3544": { "label": "13/113", "naklon": null }, + "3534": { "label": "13/114", "naklon": null }, + "3516": { "label": "13/115", "naklon": null }, + "3513": { "label": "13/116", "naklon": null }, + "3565": { "label": "13/117", "naklon": null }, + "3866": { "label": "13/118", "naklon": null }, + "3136": { "label": "14/1", "naklon": 0 }, + "3137": { "label": "14/2", "naklon": 0 }, + "3135": { "label": "14/3", "naklon": 0 }, + "3149": { "label": "14/4", "naklon": 0 }, + "3142": { "label": "14/5", "naklon": 0 }, + "3342": { "label": "14/6", "naklon": 0 }, + "3340": { "label": "14/7", "naklon": 0 }, + "3152": { "label": "14/8", "naklon": 0 }, + "3886": { "label": "14/9", "naklon": 0 }, + "3341": { "label": "14/10", "naklon": null }, + "3352": { "label": "14/11", "naklon": null }, + "3396": { "label": "15/1", "naklon": 5 }, + "2784": { "label": "15/2", "naklon": 5 }, + "2788": { "label": "15/3", "naklon": 5 }, + "2801": { "label": "15/4", "naklon": 5 }, + "2815": { "label": "15/5", "naklon": 5 }, + "2829": { "label": "15/6", "naklon": 5 }, + "2796": { "label": "15/7", "naklon": 5 }, + "2803": { "label": "15/8", "naklon": 5 }, + "4304": { "label": "15/8/1", "naklon": 5 }, + "4311": { "label": "15/8/2", "naklon": 5 }, + "2821": { "label": "15/9", "naklon": 5 }, + "3400": { "label": "15/10", "naklon": 5 }, + "2799": { "label": "15/11", "naklon": 5 }, + "2804": { "label": "15/12", "naklon": 5 }, + "4303": { "label": "15/12/1", "naklon": 5 }, + "4309": { "label": "15/12/2", "naklon": 5 }, + "2806": { "label": "15/13", "naklon": 5 }, + "2787": { "label": "15/14", "naklon": 5 }, + "2809": { "label": "15/15", "naklon": 5 }, + "2814": { "label": "15/16", "naklon": 0 }, + "3934": { "label": "15/17", "naklon": 0 }, + "3192": { "label": "15/18", "naklon": 0 }, + "2812": { "label": "15/19", "naklon": 0 }, + "4070": { "label": "15/20", "naklon": 0 }, + "2826": { "label": "15/21", "naklon": 0 }, + "2808": { "label": "15/22", "naklon": 3 }, + "2795": { "label": "15/23", "naklon": 3 }, + "2807": { "label": "15/24", "naklon": 3 }, + "2831": { "label": "15/25", "naklon": 0 }, + "2862": { "label": "15/26", "naklon": null }, + "2861": { "label": "15/27", "naklon": 0 }, + "2866": { "label": "15/28", "naklon": 0 }, + "3546": { "label": "15/28/1", "naklon": 0 }, + "4146": { "label": "15/29", "naklon": 0 }, + "3001": { "label": "15/29/1", "naklon": 0 }, + "2835": { "label": "15/30", "naklon": 0 }, + "2874": { "label": "15/31", "naklon": 0 }, + "2852": { "label": "15/32", "naklon": 0 }, + "2851": { "label": "15/33", "naklon": 0 }, + "3560": { "label": "15/33/1", "naklon": 0 }, + "2858": { "label": "15/34", "naklon": 0 }, + "4306": { "label": "15/34/1", "naklon": 0 }, + "2856": { "label": "15/35", "naklon": 0 }, + "2847": { "label": "15/36", "naklon": 0 }, + "3556": { "label": "15/36/1", "naklon": 0 }, + "3950": { "label": "15/37", "naklon": 0 }, + "2848": { "label": "15/38", "naklon": 0 }, + "2863": { "label": "15/39", "naklon": 0 }, + "4313": { "label": "15/39/1", "naklon": 0 }, + "2873": { "label": "15/40", "naklon": 0 }, + "2984": { "label": "15/40/1", "naklon": 0 }, + "2854": { "label": "15/41", "naklon": 0 }, + "2859": { "label": "15/42", "naklon": 0 }, + "2872": { "label": "15/43", "naklon": 0 }, + "2849": { "label": "15/44", "naklon": 0 }, + "2864": { "label": "15/45", "naklon": 0 }, + "3553": { "label": "15/46", "naklon": null }, + "3021": { "label": "15/47", "naklon": null }, + "3008": { "label": "15/47/1", "naklon": null }, + "3017": { "label": "15/48", "naklon": null }, + "3014": { "label": "15/49", "naklon": null }, + "2981": { "label": "15/50", "naklon": null }, + "3020": { "label": "15/51", "naklon": null }, + "3027": { "label": "15/52", "naklon": null }, + "3006": { "label": "15/53", "naklon": null }, + "3012": { "label": "15/54", "naklon": null }, + "2738": { "label": "15/55", "naklon": 0 }, + "2725": { "label": "15/56", "naklon": 0 }, + "3016": { "label": "15/57", "naklon": null }, + "3005": { "label": "15/58", "naklon": null }, + "3009": { "label": "15/58/1", "naklon": null }, + "3010": { "label": "15/59", "naklon": 0 }, + "3538": { "label": "15/59/1", "naklon": 0 }, + "4145": { "label": "15/59/2", "naklon": 0 }, + "2713": { "label": "15/60", "naklon": 0 }, + "2789": { "label": "15/61", "naklon": 0 }, + "2736": { "label": "15/62", "naklon": 0 }, + "2739": { "label": "15/63", "naklon": 0 }, + "4346": { "label": "15/64", "naklon": 0 }, + "2731": { "label": "15/65", "naklon": 0 }, + "2818": { "label": "15/66", "naklon": 0 }, + "3557": { "label": "15/66/1", "naklon": 0 }, + "2822": { "label": "15/67", "naklon": 0 }, + "2833": { "label": "15/68", "naklon": 0 }, + "2834": { "label": "15/69", "naklon": 0 }, + "3097": { "label": "15/70", "naklon": 0 }, + "2824": { "label": "15/71", "naklon": 0 }, + "2828": { "label": "15/72", "naklon": 0 }, + "2600": { "label": "15/73", "naklon": 0 }, + "4314": { "label": "15/73/1", "naklon": 0 }, + "2832": { "label": "15/74", "naklon": 0 }, + "4360": { "label": "15/75", "naklon": 0 }, + "2846": { "label": "15/76", "naklon": 0 }, + "2584": { "label": "15/77", "naklon": 0 }, + "2843": { "label": "15/78", "naklon": 0 }, + "4308": { "label": "15/78/1", "naklon": 0 }, + "4144": { "label": "15/79", "naklon": null }, + "2844": { "label": "15/80", "naklon": 0 }, + "2842": { "label": "15/81", "naklon": 0 }, + "2838": { "label": "15/82", "naklon": 0 }, + "2837": { "label": "15/83", "naklon": null }, + "3555": { "label": "15/83/1", "naklon": null }, + "2839": { "label": "15/84", "naklon": 0 }, + "2830": { "label": "15/85", "naklon": 0 }, + "4066": { "label": "15/86", "naklon": 0 }, + "2836": { "label": "15/87", "naklon": 0 }, + "2911": { "label": "15/88", "naklon": 0 }, + "2825": { "label": "15/89", "naklon": 0 }, + "2811": { "label": "15/90", "naklon": 0 }, + "3740": { "label": "15/94", "naklon": 15 }, + "2734": { "label": "15/95", "naklon": 15 }, + "3105": { "label": "15/96", "naklon": 15 }, + "2732": { "label": "15/97", "naklon": 15 }, + "2727": { "label": "15/98", "naklon": 15 }, + "2735": { "label": "15/99", "naklon": 15 }, + "3926": { "label": "15/100", "naklon": 15 }, + "2918": { "label": "15/101", "naklon": 0 }, + "2705": { "label": "15/102", "naklon": 10 }, + "2708": { "label": "15/103", "naklon": 10 }, + "2721": { "label": "15/104", "naklon": 10 }, + "2719": { "label": "15/105", "naklon": 10 }, + "2919": { "label": "15/106", "naklon": 10 }, + "3101": { "label": "15/107", "naklon": 10 }, + "2853": { "label": "15/108", "naklon": 10 }, + "2715": { "label": "15/109", "naklon": 10 }, + "2712": { "label": "15/110", "naklon": 0 }, + "2711": { "label": "15/111", "naklon": 0 }, + "2709": { "label": "15/112", "naklon": 0 }, + "2710": { "label": "15/113", "naklon": 0 }, + "2907": { "label": "15/114", "naklon": 0 }, + "2906": { "label": "15/115", "naklon": 0 }, + "2908": { "label": "15/116", "naklon": 0 }, + "2901": { "label": "15/117", "naklon": 0 }, + "2913": { "label": "15/118", "naklon": 0 }, + "3656": { "label": "15/119", "naklon": 0 }, + "2781": { "label": "15/120", "naklon": 0 }, + "2802": { "label": "15/121", "naklon": 0 }, + "2791": { "label": "15/122", "naklon": 0 }, + "2783": { "label": "15/123", "naklon": 0 }, + "2794": { "label": "15/124", "naklon": 0 }, + "3139": { "label": "15/125", "naklon": 0 }, + "3229": { "label": "15/126", "naklon": 5 }, + "3239": { "label": "15/127", "naklon": 5 }, + "3230": { "label": "15/128", "naklon": 5 }, + "4016": { "label": "15/129", "naklon": null }, + "3608": { "label": "16/16A", "naklon": 0 }, + "4151": { "label": "16/16B", "naklon": 0 }, + "3710": { "label": "16/1", "naklon": 0 }, + "3726": { "label": "16/2", "naklon": 0 }, + "3743": { "label": "16/3", "naklon": 0 }, + "3724": { "label": "16/4", "naklon": 0 }, + "3712": { "label": "16/5", "naklon": 0 }, + "3739": { "label": "16/6", "naklon": 0 }, + "3742": { "label": "16/7", "naklon": 0 }, + "3731": { "label": "16/8", "naklon": 0 }, + "3727": { "label": "16/9", "naklon": 0 }, + "3729": { "label": "16/10", "naklon": 0 }, + "3736": { "label": "16/11", "naklon": 0 }, + "3713": { "label": "16/12", "naklon": 0 }, + "3715": { "label": "16/13", "naklon": 0 }, + "3733": { "label": "16/14", "naklon": 0 }, + "3732": { "label": "16/15", "naklon": 0 }, + "3634": { "label": "16/17", "naklon": 0 }, + "3610": { "label": "16/18", "naklon": 0 }, + "3626": { "label": "16/19", "naklon": 0 }, + "3618": { "label": "16/20", "naklon": 0 }, + "3619": { "label": "16/21", "naklon": 0 }, + "3628": { "label": "16/22", "naklon": 0 }, + "3615": { "label": "16/23", "naklon": 0 }, + "3609": { "label": "16/24", "naklon": 0 }, + "3606": { "label": "16/25", "naklon": 0 }, + "3624": { "label": "16/26", "naklon": 0 }, + "3627": { "label": "16/27", "naklon": 0 }, + "3607": { "label": "16/28", "naklon": 0 }, + "4370": { "label": "16/29", "naklon": 0 }, + "3692": { "label": "16/30", "naklon": 0 }, + "3614": { "label": "16/31", "naklon": 0 }, + "3623": { "label": "16/32", "naklon": 0 }, + "4373": { "label": "16/33", "naklon": 0 }, + "3620": { "label": "16/34", "naklon": 0 }, + "3685": { "label": "16/35", "naklon": 0 }, + "3616": { "label": "16/36", "naklon": 0 }, + "3686": { "label": "16/37", "naklon": 0 }, + "3688": { "label": "16/38", "naklon": 0 }, + "3684": { "label": "16/39", "naklon": 0 }, + "3825": { "label": "16/40", "naklon": 0 }, + "3865": { "label": "16/41", "naklon": 0 }, + "3824": { "label": "16/42", "naklon": 0 }, + "3871": { "label": "16/43", "naklon": 0 }, + "3801": { "label": "16/44", "naklon": 0 }, + "3862": { "label": "16/45", "naklon": 0 }, + "3876": { "label": "16/46", "naklon": 0 }, + "3861": { "label": "16/47", "naklon": 0 }, + "4215": { "label": "16/48", "naklon": 0 }, + "3605": { "label": "16/49", "naklon": 10 }, + "3603": { "label": "16/50", "naklon": 10 }, + "3592": { "label": "16/51", "naklon": 10 }, + "3598": { "label": "16/52", "naklon": 10 }, + "3594": { "label": "16/53", "naklon": 10 }, + "3593": { "label": "16/54", "naklon": 10 }, + "3630": { "label": "16/55", "naklon": 10 }, + "3763": { "label": "16/56", "naklon": 10 }, + "3746": { "label": "16/57", "naklon": 10 }, + "3699": { "label": "16/58", "naklon": 0 }, + "3698": { "label": "16/59", "naklon": 0 }, + "3709": { "label": "16/60", "naklon": null }, + "3708": { "label": "16/61", "naklon": 0 }, + "3703": { "label": "16/62", "naklon": null }, + "3700": { "label": "16/63", "naklon": 0 }, + "3701": { "label": "16/64", "naklon": null }, + "3704": { "label": "16/65", "naklon": 0 }, + "3707": { "label": "16/66", "naklon": null }, + "3810": { "label": "16/67", "naklon": 0 }, + "4208": { "label": "16/68", "naklon": null }, + "3867": { "label": "16/69", "naklon": 0 }, + "4372": { "label": "16/70", "naklon": null }, + "3881": { "label": "16/71", "naklon": 0 }, + "4204": { "label": "16/72", "naklon": null }, + "3869": { "label": "16/73", "naklon": 0 }, + "4202": { "label": "16/74", "naklon": null }, + "3830": { "label": "16/75", "naklon": 0 }, + "3870": { "label": "16/76", "naklon": null }, + "3964": { "label": "16/77", "naklon": 0 }, + "3849": { "label": "16/78", "naklon": 0 }, + "3694": { "label": "16/79", "naklon": null }, + "3717": { "label": "16/80", "naklon": 0 }, + "3877": { "label": "16/81", "naklon": null }, + "3755": { "label": "16/82", "naklon": 0 }, + "3725": { "label": "16/83", "naklon": null }, + "3716": { "label": "16/84", "naklon": 0 }, + "3696": { "label": "16/85", "naklon": null }, + "3702": { "label": "16/86", "naklon": 0 }, + "3706": { "label": "16/87", "naklon": null }, + "3850": { "label": "16/88", "naklon": 0 }, + "3848": { "label": "16/89", "naklon": null }, + "3737": { "label": "16/90", "naklon": null }, + "3705": { "label": "16/91", "naklon": 0 }, + "3723": { "label": "16/92", "naklon": null }, + "3842": { "label": "16/93", "naklon": 0 }, + "3735": { "label": "16/94", "naklon": null }, + "3719": { "label": "16/95", "naklon": 0 }, + "3697": { "label": "16/96", "naklon": 0 }, + "3711": { "label": "16/97", "naklon": 0 }, + "4107": { "label": "16/98", "naklon": null }, + "4112": { "label": "16/99", "naklon": 5 }, + "4106": { "label": "16/100", "naklon": 5 }, + "4111": { "label": "16/101", "naklon": 5 }, + "4091": { "label": "16/102", "naklon": null }, + "4104": { "label": "16/103", "naklon": 5 }, + "4094": { "label": "16/104", "naklon": null }, + "4089": { "label": "16/105", "naklon": 5 }, + "4095": { "label": "16/106", "naklon": null }, + "4102": { "label": "16/107", "naklon": 5 }, + "4105": { "label": "16/108", "naklon": null }, + "3859": { "label": "16/109", "naklon": null }, + "4090": { "label": "16/110", "naklon": 5 }, + "4110": { "label": "16/111", "naklon": null }, + "4097": { "label": "16/112", "naklon": 5 }, + "4099": { "label": "16/113", "naklon": null }, + "4096": { "label": "16/114", "naklon": null }, + "4101": { "label": "16/115", "naklon": 5 }, + "4109": { "label": "16/116", "naklon": null }, + "4092": { "label": "16/117", "naklon": 5 }, + "3631": { "label": "16/118", "naklon": null }, + "3632": { "label": "16/119", "naklon": 0 }, + "3641": { "label": "16/120", "naklon": null }, + "3638": { "label": "16/121", "naklon": 0 }, + "3637": { "label": "16/122", "naklon": null }, + "4142": { "label": "16/123", "naklon": null }, + "4147": { "label": "16/124", "naklon": 5 }, + "4139": { "label": "16/125", "naklon": 5 }, + "3172": { "label": "20/30A", "naklon": 2 }, + "3164": { "label": "20/30B", "naklon": 2 }, + "3247": { "label": "20/1", "naklon": 10 }, + "3296": { "label": "20/2", "naklon": 10 }, + "3246": { "label": "20/3", "naklon": 10 }, + "3270": { "label": "20/4", "naklon": 10 }, + "3294": { "label": "20/5", "naklon": 10 }, + "3298": { "label": "20/6", "naklon": 10 }, + "3297": { "label": "20/7", "naklon": 10 }, + "3293": { "label": "20/8", "naklon": 10 }, + "3299": { "label": "20/9", "naklon": 10 }, + "3295": { "label": "20/10", "naklon": 10 }, + "3244": { "label": "20/11", "naklon": 10 }, + "3249": { "label": "20/12", "naklon": 10 }, + "3268": { "label": "20/13", "naklon": 10 }, + "3245": { "label": "20/14", "naklon": 10 }, + "3278": { "label": "20/15", "naklon": 10 }, + "3280": { "label": "20/16", "naklon": 10 }, + "3292": { "label": "20/17", "naklon": 10 }, + "3287": { "label": "20/18", "naklon": 10 }, + "3282": { "label": "20/19", "naklon": 10 }, + "3273": { "label": "20/20", "naklon": 0 }, + "3157": { "label": "20/21", "naklon": 0 }, + "3283": { "label": "20/22", "naklon": 0 }, + "3159": { "label": "20/23", "naklon": 0 }, + "3289": { "label": "20/24", "naklon": 0 }, + "3163": { "label": "20/25", "naklon": 0 }, + "3126": { "label": "20/26", "naklon": 0 }, + "3171": { "label": "20/27", "naklon": 0 }, + "3162": { "label": "20/28", "naklon": 0 }, + "3279": { "label": "20/29", "naklon": 10 }, + "3173": { "label": "20/31", "naklon": 0 }, + "3127": { "label": "20/32", "naklon": 0 }, + "3131": { "label": "20/33", "naklon": 0 }, + "3129": { "label": "20/34", "naklon": 0 }, + "3276": { "label": "20/35", "naklon": 2 }, + "3290": { "label": "20/36", "naklon": 2 }, + "3132": { "label": "20/37", "naklon": 0 }, + "3138": { "label": "20/38", "naklon": 0 }, + "3272": { "label": "20/39", "naklon": 0 }, + "3291": { "label": "20/40", "naklon": 0 }, + "3277": { "label": "20/41", "naklon": 10 }, + "3286": { "label": "20/42", "naklon": 10 }, + "3281": { "label": "20/43", "naklon": 10 }, + "3288": { "label": "20/44", "naklon": 10 }, + "3284": { "label": "20/45", "naklon": 10 }, + "3167": { "label": "20/46", "naklon": 10 }, + "3872": { "label": "20/47", "naklon": 0 }, + "3124": { "label": "20/48", "naklon": 0 }, + "3133": { "label": "20/49", "naklon": 0 }, + "3158": { "label": "20/50", "naklon": 0 }, + "3169": { "label": "20/51", "naklon": 0 }, + "3146": { "label": "20/52", "naklon": 0 }, + "3160": { "label": "20/53", "naklon": 0 }, + "3248": { "label": "20/54", "naklon": 0 }, + "3156": { "label": "20/55", "naklon": 0 }, + "3161": { "label": "20/56", "naklon": 0 }, + "3170": { "label": "20/57", "naklon": 0 }, + "3168": { "label": "20/58", "naklon": 0 }, + "3125": { "label": "20/59", "naklon": 0 }, + "3166": { "label": "20/60", "naklon": 0 }, + "3130": { "label": "20/61", "naklon": 0 }, + "3563": { "label": "20/62", "naklon": 0 }, + "3550": { "label": "20/63", "naklon": null }, + "3269": { "label": "20/67", "naklon": 0 }, + "2921": { "label": "21/1", "naklon": 0 }, + "2707": { "label": "21/2", "naklon": 0 }, + "2723": { "label": "21/3", "naklon": 0 }, + "2716": { "label": "21/4", "naklon": 0 }, + "2717": { "label": "21/5", "naklon": 0 }, + "2720": { "label": "21/6", "naklon": 0 }, + "2722": { "label": "21/7", "naklon": 0 }, + "2718": { "label": "21/8", "naklon": 0 }, + "2724": { "label": "21/9", "naklon": 0 }, + "2742": { "label": "21/10", "naklon": 0 }, + "2743": { "label": "21/11", "naklon": 0 }, + "2733": { "label": "21/12", "naklon": 0 }, + "2903": { "label": "21/14", "naklon": 0 }, + "2917": { "label": "21/15", "naklon": 0 }, + "2897": { "label": "21/16", "naklon": 0 }, + "2914": { "label": "21/17", "naklon": 0 }, + "2898": { "label": "21/18", "naklon": 0 }, + "2773": { "label": "21/19", "naklon": 0 }, + "2895": { "label": "21/20", "naklon": 0 }, + "2896": { "label": "21/21", "naklon": 0 }, + "2771": { "label": "21/22", "naklon": 0 }, + "2772": { "label": "21/23", "naklon": 0 }, + "2793": { "label": "21/24", "naklon": 0 }, + "2902": { "label": "21/25", "naklon": 0 }, + "2910": { "label": "21/26", "naklon": 0 }, + "2909": { "label": "21/27", "naklon": 0 }, + "2920": { "label": "21/28", "naklon": 0 }, + "2916": { "label": "21/29", "naklon": 0 }, + "2904": { "label": "21/30", "naklon": 0 }, + "2915": { "label": "21/31", "naklon": 0 }, + "2905": { "label": "21/32", "naklon": 0 }, + "2900": { "label": "21/33", "naklon": 0 }, + "2899": { "label": "21/34", "naklon": 0 }, + "2741": { "label": "21/36", "naklon": 0 }, + "2714": { "label": "21/37", "naklon": 0 }, + "2701": { "label": "21/38", "naklon": 0 }, + "2703": { "label": "21/39", "naklon": 0 }, + "2704": { "label": "21/40", "naklon": 0 }, + "2702": { "label": "21/41", "naklon": 0 }, + "2706": { "label": "21/42", "naklon": 0 }, + "2776": { "label": "21/43", "naklon": 0 }, + "2770": { "label": "21/44", "naklon": 0 }, + "2786": { "label": "21/45", "naklon": 0 }, + "2779": { "label": "21/46", "naklon": 0 }, + "2782": { "label": "21/47", "naklon": 0 }, + "2785": { "label": "21/48", "naklon": 0 }, + "2769": { "label": "21/49", "naklon": 0 }, + "3354": { "label": "21/50", "naklon": 0 }, + "2778": { "label": "21/51", "naklon": 0 }, + "2775": { "label": "21/52", "naklon": 0 }, + "2780": { "label": "21/53", "naklon": 0 }, + "2790": { "label": "21/54", "naklon": 0 }, + "2792": { "label": "21/55", "naklon": 0 }, + "2774": { "label": "21/56", "naklon": 0 }, + "2630": { "label": "22/1", "naklon": 0 }, + "2631": { "label": "22/2", "naklon": 0 }, + "2632": { "label": "22/3", "naklon": 0 }, + "2633": { "label": "22/4", "naklon": 0 }, + "2634": { "label": "22/5", "naklon": 0 }, + "2636": { "label": "22/6", "naklon": 0 }, + "4367": { "label": "22/7", "naklon": 0 }, + "2637": { "label": "22/8", "naklon": 0 }, + "2638": { "label": "22/9", "naklon": 0 }, + "2639": { "label": "22/10", "naklon": 0 }, + "2640": { "label": "22/11", "naklon": 0 }, + "2641": { "label": "22/12", "naklon": 0 }, + "2642": { "label": "22/13", "naklon": 0 }, + "2643": { "label": "22/14", "naklon": 0 }, + "2644": { "label": "22/15", "naklon": 0 }, + "2645": { "label": "22/16", "naklon": 0 }, + "2646": { "label": "22/17", "naklon": 0 }, + "2647": { "label": "22/18", "naklon": 0 }, + "2648": { "label": "22/19", "naklon": 0 }, + "2649": { "label": "22/20", "naklon": 0 }, + "2650": { "label": "22/21", "naklon": 0 }, + "2651": { "label": "22/22", "naklon": 0 }, + "4103": { "label": "22/23", "naklon": 0 }, + "2653": { "label": "22/24", "naklon": 0 }, + "2654": { "label": "22/25", "naklon": 0 }, + "2655": { "label": "22/26", "naklon": 0 }, + "2656": { "label": "22/27", "naklon": 0 }, + "2657": { "label": "22/28", "naklon": 0 }, + "2658": { "label": "22/29", "naklon": 0 }, + "2659": { "label": "22/30", "naklon": 0 }, + "2660": { "label": "22/31", "naklon": 0 }, + "2661": { "label": "22/32", "naklon": 0 }, + "3015": { "label": "22/32/1", "naklon": 0 }, + "2662": { "label": "22/33", "naklon": 0 }, + "2663": { "label": "22/34", "naklon": 0 }, + "2664": { "label": "22/35", "naklon": 0 }, + "2665": { "label": "22/36", "naklon": 0 }, + "2666": { "label": "22/37", "naklon": 0 }, + "2667": { "label": "22/38", "naklon": 0 }, + "2668": { "label": "22/39", "naklon": 0 }, + "2669": { "label": "22/40", "naklon": null }, + "2670": { "label": "22/41", "naklon": null }, + "2671": { "label": "22/42", "naklon": null }, + "3087": { "label": "23/9A", "naklon": 10 }, + "3090": { "label": "23/9B", "naklon": 10 }, + "3075": { "label": "23/1", "naklon": 0 }, + "3089": { "label": "23/2", "naklon": 0 }, + "3088": { "label": "23/3", "naklon": 0 }, + "3228": { "label": "23/4", "naklon": 10 }, + "2751": { "label": "23/5", "naklon": 10 }, + "3243": { "label": "23/6", "naklon": 10 }, + "4349": { "label": "23/7", "naklon": 10 }, + "3102": { "label": "23/8", "naklon": 10 }, + "3099": { "label": "23/10", "naklon": 10 }, + "3103": { "label": "23/11", "naklon": 10 }, + "3093": { "label": "23/12", "naklon": 10 }, + "3098": { "label": "23/13", "naklon": 10 }, + "3092": { "label": "23/14", "naklon": 10 }, + "3233": { "label": "23/15", "naklon": 0 }, + "3095": { "label": "23/16", "naklon": 0 }, + "4074": { "label": "23/17", "naklon": 0 }, + "2729": { "label": "23/18", "naklon": 0 }, + "3234": { "label": "23/19", "naklon": 0 }, + "3094": { "label": "23/20", "naklon": 0 }, + "2817": { "label": "23/21", "naklon": 0 }, + "3226": { "label": "23/22", "naklon": 0 }, + "3225": { "label": "23/23", "naklon": 0 }, + "3237": { "label": "23/24", "naklon": 0 }, + "4250": { "label": "23/25", "naklon": 0 }, + "3059": { "label": "23/26", "naklon": 10 }, + "3238": { "label": "23/27", "naklon": 10 }, + "3242": { "label": "23/28", "naklon": 10 }, + "3236": { "label": "23/29", "naklon": 10 }, + "3112": { "label": "23/30", "naklon": 10 }, + "3224": { "label": "23/31", "naklon": 0 }, + "4298": { "label": "23/32", "naklon": 10 }, + "4150": { "label": "23/33", "naklon": 10 }, + "3091": { "label": "23/34", "naklon": 10 }, + "3771": { "label": "25/1", "naklon": 5 }, + "3777": { "label": "25/2", "naklon": 5 }, + "3749": { "label": "25/3", "naklon": 5 }, + "3769": { "label": "25/4", "naklon": 5 }, + "3765": { "label": "25/5", "naklon": 5 }, + "3785": { "label": "25/6", "naklon": 5 }, + "3761": { "label": "25/7", "naklon": 5 }, + "3758": { "label": "25/8", "naklon": 5 }, + "3766": { "label": "25/9", "naklon": 5 }, + "3779": { "label": "25/10", "naklon": 5 }, + "3899": { "label": "25/11", "naklon": 10 }, + "3922": { "label": "25/12", "naklon": 10 }, + "3912": { "label": "25/13", "naklon": 10 }, + "3933": { "label": "25/14", "naklon": 10 }, + "3921": { "label": "25/15", "naklon": 10 }, + "4300": { "label": "25/16", "naklon": 10 }, + "3927": { "label": "25/17", "naklon": 10 }, + "3212": { "label": "25/18", "naklon": 10 }, + "3208": { "label": "25/19", "naklon": 10 }, + "3207": { "label": "25/20", "naklon": 10 }, + "4294": { "label": "25/21", "naklon": 10 }, + "3209": { "label": "25/22", "naklon": 10 }, + "3745": { "label": "25/23", "naklon": 10 }, + "3762": { "label": "25/24", "naklon": 10 }, + "3215": { "label": "25/25", "naklon": 10 }, + "3210": { "label": "25/26", "naklon": 10 }, + "3211": { "label": "25/27", "naklon": 10 }, + "3206": { "label": "25/28", "naklon": 10 }, + "3918": { "label": "25/29", "naklon": 5 }, + "3928": { "label": "25/30", "naklon": 5 }, + "3917": { "label": "25/31", "naklon": 5 }, + "4029": { "label": "25/32", "naklon": 0 }, + "4038": { "label": "25/33", "naklon": 0 }, + "4022": { "label": "25/34", "naklon": 0 }, + "3937": { "label": "25/35", "naklon": 0 }, + "3190": { "label": "25/36", "naklon": 0 }, + "3835": { "label": "25/37", "naklon": 0 }, + "3201": { "label": "25/38", "naklon": 0 }, + "3193": { "label": "25/39", "naklon": 0 }, + "3191": { "label": "25/40", "naklon": 0 }, + "3203": { "label": "25/41", "naklon": 0 }, + "4301": { "label": "25/42", "naklon": 0 }, + "3223": { "label": "25/43", "naklon": 0 }, + "3202": { "label": "25/44", "naklon": 0 }, + "3205": { "label": "25/45", "naklon": 0 }, + "3194": { "label": "25/46", "naklon": 0 }, + "3198": { "label": "25/47", "naklon": 0 }, + "3204": { "label": "25/48", "naklon": 0 }, + "3200": { "label": "25/49", "naklon": 0 }, + "3216": { "label": "25/50", "naklon": 0 }, + "3932": { "label": "25/51", "naklon": 5 }, + "3923": { "label": "25/52", "naklon": 5 }, + "3913": { "label": "25/53", "naklon": 5 }, + "3900": { "label": "25/54", "naklon": 5 }, + "4189": { "label": "25/55", "naklon": 10 }, + "4191": { "label": "25/56", "naklon": 10 }, + "3790": { "label": "25/57", "naklon": 10 }, + "4190": { "label": "25/58", "naklon": 10 }, + "4302": { "label": "25/59", "naklon": 0 }, + "4351": { "label": "25/60", "naklon": 0 }, + "4075": { "label": "25/61", "naklon": 0 }, + "4071": { "label": "25/62", "naklon": 0 }, + "3784": { "label": "25/63", "naklon": 0 }, + "4065": { "label": "25/64", "naklon": 0 }, + "4297": { "label": "25/65", "naklon": 0 }, + "4295": { "label": "25/66", "naklon": 0 }, + "4299": { "label": "25/67", "naklon": 0 }, + "3772": { "label": "25/68", "naklon": 0 }, + "3941": { "label": "25/69", "naklon": 0 }, + "3782": { "label": "25/70", "naklon": 0 }, + "4068": { "label": "25/71", "naklon": 0 }, + "4073": { "label": "25/72", "naklon": 0 }, + "3901": { "label": "25/73", "naklon": 5 }, + "4296": { "label": "25/74", "naklon": 5 }, + "3910": { "label": "25/75", "naklon": 5 }, + "4293": { "label": "25/76", "naklon": 5 }, + "3919": { "label": "25/77", "naklon": 5 }, + "3924": { "label": "25/78", "naklon": 5 }, + "3909": { "label": "25/79", "naklon": 5 }, + "3896": { "label": "25/80", "naklon": 5 }, + "3911": { "label": "25/81", "naklon": 5 }, + "2819": { "label": "25/82", "naklon": 15 }, + "3776": { "label": "25/83", "naklon": 15 }, + "3752": { "label": "25/84", "naklon": 15 }, + "4353": { "label": "25/85", "naklon": 15 }, + "3791": { "label": "25/86", "naklon": 0 }, + "3770": { "label": "25/87", "naklon": 0 }, + "3760": { "label": "25/88", "naklon": 0 }, + "3115": { "label": "25/89", "naklon": 0 }, + "3738": { "label": "25/90", "naklon": 0 }, + "3748": { "label": "25/91", "naklon": 0 }, + "3753": { "label": "25/92", "naklon": 0 }, + "3775": { "label": "25/93", "naklon": 0 }, + "3778": { "label": "25/94", "naklon": 5 }, + "4078": { "label": "25/95", "naklon": 5 }, + "4088": { "label": "25/96", "naklon": 5 }, + "3856": { "label": "25/97", "naklon": 5 }, + "4084": { "label": "25/98", "naklon": 5 }, + "4069": { "label": "25/99", "naklon": 5 }, + "4188": { "label": "25/100", "naklon": 5 }, + "4064": { "label": "25/101", "naklon": 5 }, + "3792": { "label": "25/102", "naklon": 5 }, + "3780": { "label": "25/103", "naklon": 5 }, + "4034": { "label": "25/104", "naklon": 5 }, + "4072": { "label": "25/105", "naklon": 5 }, + "3884": { "label": "25/106", "naklon": 5 }, + "3793": { "label": "25/107", "naklon": 5 }, + "3863": { "label": "25/108", "naklon": 5 }, + "3855": { "label": "25/109", "naklon": 5 }, + "3846": { "label": "33/1", "naklon": 0 }, + "3943": { "label": "33/2", "naklon": 0 }, + "3903": { "label": "33/3", "naklon": 0 }, + "3982": { "label": "33/4", "naklon": 0 }, + "3879": { "label": "33/5", "naklon": 0 }, + "3887": { "label": "33/6", "naklon": 0 }, + "3920": { "label": "33/7", "naklon": 5 }, + "3942": { "label": "33/8", "naklon": 5 }, + "3829": { "label": "33/9", "naklon": null }, + "3452": { "label": "34/79A", "naklon": 6 }, + "3460": { "label": "34/79B", "naklon": 6 }, + "3443": { "label": "34/90A", "naklon": 6 }, + "3445": { "label": "34/90B", "naklon": 6 }, + "3457": { "label": "34/90C", "naklon": 6 }, + "3461": { "label": "34/97A", "naklon": 6 }, + "3463": { "label": "34/97B", "naklon": 6 }, + "3426": { "label": "34/98A", "naklon": 6 }, + "3444": { "label": "34/98B", "naklon": 6 }, + "3453": { "label": "34/99A", "naklon": 6 }, + "3455": { "label": "34/99B", "naklon": 6 }, + "4009": { "label": "34/1", "naklon": 0 }, + "3602": { "label": "34/2", "naklon": 0 }, + "3441": { "label": "34/3", "naklon": 0 }, + "3464": { "label": "34/4", "naklon": 0 }, + "3883": { "label": "34/5", "naklon": 0 }, + "4098": { "label": "34/6", "naklon": 0 }, + "4003": { "label": "34/7", "naklon": 0 }, + "4004": { "label": "34/8", "naklon": 0 }, + "3888": { "label": "34/9", "naklon": 0 }, + "3997": { "label": "34/10", "naklon": 0 }, + "4006": { "label": "34/11", "naklon": 0 }, + "4000": { "label": "34/12", "naklon": 0 }, + "4011": { "label": "34/13", "naklon": 0 }, + "3999": { "label": "34/14", "naklon": 0 }, + "3981": { "label": "34/15", "naklon": 0 }, + "3988": { "label": "34/16", "naklon": 0 }, + "3986": { "label": "34/17", "naklon": 0 }, + "3998": { "label": "34/18", "naklon": 0 }, + "3983": { "label": "34/19", "naklon": 0 }, + "4005": { "label": "34/20", "naklon": 0 }, + "4001": { "label": "34/21", "naklon": 0 }, + "4008": { "label": "34/22", "naklon": 0 }, + "4002": { "label": "34/23", "naklon": 0 }, + "3996": { "label": "34/24", "naklon": 0 }, + "4007": { "label": "34/25", "naklon": 0 }, + "4113": { "label": "34/26", "naklon": 15 }, + "3595": { "label": "34/27", "naklon": 5 }, + "3599": { "label": "34/28", "naklon": 5 }, + "3601": { "label": "34/29", "naklon": 5 }, + "4205": { "label": "34/30", "naklon": 0 }, + "3987": { "label": "34/31", "naklon": null }, + "4214": { "label": "34/32", "naklon": 0 }, + "4226": { "label": "34/33", "naklon": 0 }, + "4209": { "label": "34/34", "naklon": 0 }, + "4201": { "label": "34/35", "naklon": 0 }, + "3440": { "label": "34/36", "naklon": 0 }, + "3465": { "label": "34/37", "naklon": 0 }, + "3446": { "label": "34/38", "naklon": 0 }, + "4039": { "label": "34/39", "naklon": 5 }, + "4057": { "label": "34/40", "naklon": 5 }, + "3985": { "label": "34/41", "naklon": 0 }, + "3882": { "label": "34/42", "naklon": 0 }, + "4040": { "label": "34/43", "naklon": 5 }, + "3231": { "label": "34/44", "naklon": 0 }, + "3227": { "label": "34/45", "naklon": 0 }, + "3431": { "label": "34/46", "naklon": 0 }, + "4013": { "label": "34/47", "naklon": 0 }, + "4045": { "label": "34/48", "naklon": 0 }, + "3949": { "label": "34/49", "naklon": 0 }, + "3953": { "label": "34/50", "naklon": 0 }, + "3952": { "label": "34/51", "naklon": 0 }, + "3995": { "label": "34/52", "naklon": 0 }, + "3992": { "label": "34/53", "naklon": 0 }, + "4198": { "label": "34/54", "naklon": 0 }, + "3935": { "label": "34/55", "naklon": 0 }, + "4050": { "label": "34/56", "naklon": 0 }, + "4049": { "label": "34/57", "naklon": 0 }, + "4054": { "label": "34/58", "naklon": 0 }, + "3663": { "label": "34/59", "naklon": 6 }, + "3661": { "label": "34/60", "naklon": 6 }, + "3664": { "label": "34/61", "naklon": 6 }, + "3660": { "label": "34/62", "naklon": 6 }, + "3662": { "label": "34/63", "naklon": 6 }, + "3665": { "label": "34/65", "naklon": 6 }, + "3667": { "label": "34/66", "naklon": 6 }, + "3675": { "label": "34/67", "naklon": 6 }, + "3666": { "label": "34/68", "naklon": 6 }, + "3652": { "label": "34/69", "naklon": 6 }, + "3458": { "label": "34/70", "naklon": 6 }, + "4425": { "label": "34/70/1", "naklon": 6 }, + "3459": { "label": "34/71", "naklon": 6 }, + "3435": { "label": "34/72", "naklon": 6 }, + "3448": { "label": "34/73", "naklon": 6 }, + "3451": { "label": "34/74", "naklon": 6 }, + "3442": { "label": "34/75", "naklon": 6 }, + "3449": { "label": "34/76", "naklon": 6 }, + "3450": { "label": "34/77", "naklon": 6 }, + "3433": { "label": "34/78", "naklon": 6 }, + "3432": { "label": "34/80", "naklon": 12 }, + "3470": { "label": "34/81", "naklon": 12 }, + "3438": { "label": "34/82", "naklon": 12 }, + "3439": { "label": "34/83", "naklon": 12 }, + "4028": { "label": "34/84", "naklon": 5 }, + "3596": { "label": "34/85", "naklon": 5 }, + "4021": { "label": "34/86", "naklon": 5 }, + "3437": { "label": "34/87", "naklon": 12 }, + "3428": { "label": "34/88", "naklon": 12 }, + "3430": { "label": "34/89", "naklon": 12 }, + "3454": { "label": "34/91", "naklon": 6 }, + "3492": { "label": "34/92", "naklon": 6 }, + "3462": { "label": "34/93", "naklon": 6 }, + "3427": { "label": "34/94", "naklon": 6 }, + "3434": { "label": "34/95", "naklon": 6 }, + "3456": { "label": "34/96", "naklon": 6 }, + "4307": { "label": "34/98/1", "naklon": 6 }, + "3968": { "label": "35/1", "naklon": 0 }, + "3969": { "label": "35/2", "naklon": 0 }, + "3947": { "label": "35/3", "naklon": 0 }, + "3979": { "label": "35/4", "naklon": 0 }, + "3959": { "label": "35/5", "naklon": 0 }, + "3948": { "label": "35/6", "naklon": 0 }, + "3961": { "label": "35/7", "naklon": 0 }, + "3956": { "label": "35/8", "naklon": 0 }, + "3604": { "label": "35/9", "naklon": 0 }, + "3944": { "label": "35/10", "naklon": 0 }, + "3960": { "label": "35/11", "naklon": 0 }, + "3958": { "label": "35/12", "naklon": 0 }, + "4036": { "label": "35/13", "naklon": 5 }, + "3893": { "label": "35/18", "naklon": 5 }, + "4108": { "label": "35/19", "naklon": 5 }, + "4017": { "label": "35/20", "naklon": 5 }, + "3963": { "label": "35/21", "naklon": 0 }, + "3658": { "label": "35/22", "naklon": 0 }, + "3975": { "label": "35/23", "naklon": 0 }, + "3980": { "label": "35/24", "naklon": 0 }, + "4012": { "label": "35/25", "naklon": 0 }, + "3655": { "label": "35/26", "naklon": 0 }, + "3962": { "label": "35/27", "naklon": 0 }, + "3945": { "label": "35/28", "naklon": 0 }, + "3569": { "label": "35/29", "naklon": 0 }, + "3429": { "label": "35/30", "naklon": 0 }, + "3657": { "label": "35/31", "naklon": 0 }, + "3646": { "label": "35/32", "naklon": 0 }, + "3622": { "label": "35/33", "naklon": 0 }, + "3612": { "label": "35/34", "naklon": 0 }, + "3955": { "label": "35/35", "naklon": 0 }, + "3878": { "label": "35/37", "naklon": 0 }, + "3965": { "label": "35/38", "naklon": 0 }, + "3970": { "label": "35/39", "naklon": 0 }, + "3611": { "label": "35/40", "naklon": 0 }, + "2635": { "label": "35/41", "naklon": 0 }, + "3978": { "label": "35/42", "naklon": 0 }, + "4213": { "label": "35/43", "naklon": 0 }, + "3984": { "label": "35/44", "naklon": 0 }, + "4218": { "label": "35/45", "naklon": 0 }, + "3973": { "label": "35/46", "naklon": 0 }, + "3974": { "label": "35/47", "naklon": 0 }, + "3759": { "label": "35/48", "naklon": 0 }, + "3844": { "label": "35/49", "naklon": 0 }, + "3804": { "label": "35/50", "naklon": 0 }, + "3831": { "label": "35/51", "naklon": 0 }, + "3643": { "label": "35/52", "naklon": 0 }, + "3966": { "label": "35/53", "naklon": 0 }, + "3971": { "label": "35/54", "naklon": 0 }, + "3650": { "label": "35/55", "naklon": 6 }, + "3651": { "label": "35/56", "naklon": 6 }, + "3669": { "label": "35/57", "naklon": 6 }, + "3648": { "label": "35/58", "naklon": 6 }, + "3645": { "label": "35/59", "naklon": 6 }, + "3659": { "label": "35/60", "naklon": 6 }, + "3647": { "label": "35/61", "naklon": 6 }, + "3644": { "label": "35/62", "naklon": 6 }, + "3671": { "label": "35/63", "naklon": 6 }, + "3682": { "label": "35/64", "naklon": 6 }, + "3672": { "label": "35/65", "naklon": 6 }, + "3683": { "label": "35/66", "naklon": 6 }, + "3673": { "label": "35/67", "naklon": 6 }, + "3674": { "label": "35/68", "naklon": 6 }, + "3679": { "label": "35/69", "naklon": 6 }, + "3649": { "label": "35/70", "naklon": 6 }, + "3687": { "label": "35/71", "naklon": 6 }, + "3677": { "label": "35/72", "naklon": 6 }, + "3690": { "label": "35/73", "naklon": 6 }, + "3691": { "label": "35/74", "naklon": 6 }, + "3676": { "label": "35/75", "naklon": 6 }, + "3680": { "label": "35/76", "naklon": 6 }, + "3668": { "label": "35/77", "naklon": 6 }, + "3681": { "label": "35/78", "naklon": 6 }, + "3670": { "label": "35/79", "naklon": 6 }, + "3689": { "label": "35/80", "naklon": 6 }, + "3678": { "label": "35/81", "naklon": 6 }, + "3693": { "label": "35/82", "naklon": 6 }, + "3654": { "label": "35/83", "naklon": null }, + "4086": { "label": "36/1", "naklon": 0 }, + "4085": { "label": "36/2", "naklon": 0 }, + "4083": { "label": "36/3", "naklon": 0 }, + "4087": { "label": "36/4", "naklon": 0 }, + "4077": { "label": "36/5", "naklon": 0 }, + "4082": { "label": "36/6", "naklon": 0 }, + "4186": { "label": "36/7", "naklon": 0 }, + "4206": { "label": "36/8", "naklon": 0 }, + "4080": { "label": "36/9", "naklon": 0 }, + "4081": { "label": "36/10", "naklon": 0 }, + "4210": { "label": "36/11", "naklon": 0 }, + "4079": { "label": "36/12", "naklon": 0 }, + "4076": { "label": "36/13", "naklon": 0 }, + "3852": { "label": "36/14", "naklon": 0 }, + "2813": { "label": "36/15", "naklon": 0 }, + "4219": { "label": "36/16", "naklon": 0 }, + "3104": { "label": "37/1A", "naklon": 15 }, + "3121": { "label": "37/1B", "naklon": 15 }, + "3113": { "label": "37/2", "naklon": 10 }, + "3118": { "label": "37/3", "naklon": 10 }, + "3111": { "label": "37/4", "naklon": 10 }, + "4020": { "label": "37/5", "naklon": 10 }, + "3119": { "label": "37/6", "naklon": 10 }, + "3110": { "label": "37/7", "naklon": 10 }, + "3108": { "label": "37/8", "naklon": 10 }, + "3107": { "label": "37/12", "naklon": 0 }, + "3199": { "label": "37/13", "naklon": 0 }, + "3120": { "label": "37/14", "naklon": 0 }, + "3122": { "label": "37/15", "naklon": 0 }, + "3908": { "label": "37/16", "naklon": 0 }, + "3114": { "label": "37/17", "naklon": 0 }, + "3105": { "label": "37/18", "naklon": 0 }, + "3116": { "label": "37/19", "naklon": 0 }, + "3106": { "label": "37/20", "naklon": 0 }, + "2887": { "label": "37/21", "naklon": 5 }, + "2888": { "label": "37/22", "naklon": 5 }, + "2877": { "label": "37/23", "naklon": 5 }, + "2891": { "label": "37/24", "naklon": 5 }, + "2886": { "label": "37/25", "naklon": 5 }, + "2892": { "label": "37/26", "naklon": 5 }, + "2882": { "label": "37/27", "naklon": 5 }, + "2883": { "label": "37/28", "naklon": 5 }, + "2876": { "label": "37/29", "naklon": 5 }, + "3109": { "label": "37/30", "naklon": 5 }, + "4152": { "label": "37/31", "naklon": 5 }, + "3117": { "label": "37/32", "naklon": 5 }, + "2870": { "label": "37/33", "naklon": 5 }, + "2867": { "label": "37/34", "naklon": 0 }, + "2865": { "label": "37/35", "naklon": 0 }, + "3096": { "label": "37/36", "naklon": 0 }, + "2871": { "label": "37/37", "naklon": 0 }, + "2884": { "label": "37/38", "naklon": 0 }, + "2855": { "label": "37/39", "naklon": 0 }, + "2878": { "label": "37/40", "naklon": 0 }, + "2889": { "label": "37/41", "naklon": 0 }, + "2879": { "label": "37/42", "naklon": 0 }, + "2850": { "label": "37/43", "naklon": 0 }, + "2894": { "label": "37/44", "naklon": 0 }, + "2880": { "label": "37/45", "naklon": 0 }, + "2893": { "label": "37/46", "naklon": 0 }, + "2890": { "label": "37/47", "naklon": 0 }, + "4355": { "label": "37/48", "naklon": 0 }, + "2885": { "label": "37/49", "naklon": 0 }, + "2875": { "label": "37/50", "naklon": 0 }, + "3486": { "label": "38/30A", "naklon": 5 }, + "3714": { "label": "38/30B", "naklon": 0 }, + "3483": { "label": "38/32A", "naklon": 5 }, + "3496": { "label": "38/32B", "naklon": 0 }, + "3487": { "label": "38/35A", "naklon": 5 }, + "3498": { "label": "38/35B", "naklon": 5 }, + "3578": { "label": "38/38A", "naklon": 5 }, + "3508": { "label": "38/38B", "naklon": 5 }, + "3787": { "label": "38/59A", "naklon": 5 }, + "3491": { "label": "38/59B", "naklon": 5 }, + "3568": { "label": "38/1", "naklon": null }, + "3502": { "label": "38/2", "naklon": 0 }, + "3836": { "label": "38/3", "naklon": 0 }, + "3588": { "label": "38/4", "naklon": 0 }, + "3493": { "label": "38/5", "naklon": 0 }, + "3580": { "label": "38/6", "naklon": 0 }, + "3572": { "label": "38/7", "naklon": 0 }, + "3506": { "label": "38/8", "naklon": 0 }, + "3503": { "label": "38/9", "naklon": 0 }, + "3579": { "label": "38/10", "naklon": 0 }, + "3586": { "label": "38/11", "naklon": 0 }, + "3495": { "label": "38/12", "naklon": 5 }, + "3492": { "label": "38/13", "naklon": 5 }, + "3532": { "label": "38/14", "naklon": 5 }, + "3574": { "label": "38/15", "naklon": 5 }, + "4140": { "label": "38/16", "naklon": 5 }, + "3795": { "label": "38/17", "naklon": 5 }, + "3788": { "label": "38/18", "naklon": 5 }, + "3796": { "label": "38/19", "naklon": 5 }, + "3797": { "label": "38/20", "naklon": 5 }, + "3798": { "label": "38/21", "naklon": 5 }, + "3786": { "label": "38/22", "naklon": 5 }, + "4067": { "label": "38/23", "naklon": 5 }, + "3773": { "label": "38/24", "naklon": 5 }, + "3774": { "label": "38/25", "naklon": 5 }, + "3789": { "label": "38/26", "naklon": 5 }, + "3520": { "label": "38/27", "naklon": null }, + "3577": { "label": "38/29", "naklon": 5 }, + "3530": { "label": "38/31", "naklon": null }, + "3488": { "label": "38/33", "naklon": 5 }, + "3505": { "label": "38/34", "naklon": 5 }, + "3497": { "label": "38/36", "naklon": 5 }, + "3490": { "label": "38/37", "naklon": 5 }, + "3585": { "label": "38/39", "naklon": 5 }, + "3582": { "label": "38/40", "naklon": 5 }, + "3507": { "label": "38/41", "naklon": 5 }, + "3484": { "label": "38/42", "naklon": 5 }, + "3501": { "label": "38/43", "naklon": 5 }, + "3581": { "label": "38/44", "naklon": 5 }, + "4192": { "label": "38/45", "naklon": 5 }, + "3576": { "label": "38/46", "naklon": 5 }, + "3489": { "label": "38/47", "naklon": 5 }, + "3573": { "label": "38/48", "naklon": 5 }, + "3504": { "label": "38/49", "naklon": 5 }, + "3794": { "label": "38/50", "naklon": 5 }, + "3485": { "label": "38/51", "naklon": 5 }, + "3482": { "label": "38/52", "naklon": 5 }, + "3575": { "label": "38/53", "naklon": 5 }, + "3499": { "label": "38/54", "naklon": 5 }, + "3494": { "label": "38/55", "naklon": 5 }, + "3583": { "label": "38/56", "naklon": 5 }, + "3570": { "label": "38/57", "naklon": 5 }, + "3500": { "label": "38/58", "naklon": 0 }, + "3510": { "label": "38/63", "naklon": null }, + "3512": { "label": "38/64", "naklon": null }, + "3535": { "label": "38/67", "naklon": null }, + "3531": { "label": "38/68", "naklon": null }, + "3537": { "label": "38/69", "naklon": null }, + "3522": { "label": "39/1", "naklon": 10 }, + "4018": { "label": "39/2", "naklon": 10 }, + "4019": { "label": "39/3", "naklon": 10 }, + "4154": { "label": "39/4", "naklon": 5 }, + "3907": { "label": "39/5", "naklon": 5 }, + "4148": { "label": "39/6", "naklon": 0 }, + "4153": { "label": "39/7", "naklon": 0 }, + "3938": { "label": "39/8", "naklon": 0 }, + "3802": { "label": "39/9", "naklon": 0 }, + "4015": { "label": "39/10", "naklon": 0 }, + "3929": { "label": "39/11", "naklon": 0 }, + "3946": { "label": "39/12", "naklon": 0 }, + "4014": { "label": "39/13", "naklon": 0 }, + "4155": { "label": "39/14", "naklon": 0 }, + "4149": { "label": "39/15", "naklon": 0 }, + "3642": { "label": "39/16", "naklon": 0 }, + "3636": { "label": "39/17", "naklon": 5 }, + "3991": { "label": "39/18", "naklon": 0 }, + "3994": { "label": "39/19", "naklon": 0 }, + "3990": { "label": "39/20", "naklon": 0 }, + "3967": { "label": "39/21", "naklon": 0 }, + "3977": { "label": "39/22", "naklon": 0 }, + "3757": { "label": "39/23", "naklon": 15 }, + "3633": { "label": "39/24", "naklon": 15 }, + "3744": { "label": "39/25", "naklon": 15 }, + "4023": { "label": "39/26", "naklon": 5 }, + "3720": { "label": "39/27", "naklon": 5 }, + "3734": { "label": "39/28", "naklon": 5 }, + "3741": { "label": "39/29", "naklon": 5 }, + "3721": { "label": "39/30", "naklon": 5 }, + "3845": { "label": "39/31", "naklon": 0 }, + "3840": { "label": "39/32", "naklon": 0 }, + "3837": { "label": "39/33", "naklon": null }, + "3839": { "label": "39/34", "naklon": 0 }, + "3542": { "label": "41/1", "naklon": null }, + "3566": { "label": "41/2", "naklon": null }, + "3548": { "label": "41/3", "naklon": null }, + "3515": { "label": "41/4", "naklon": null }, + "3559": { "label": "41/5", "naklon": null }, + "3509": { "label": "41/6", "naklon": null }, + "3524": { "label": "41/7", "naklon": null }, + "3518": { "label": "41/8", "naklon": null }, + "3182": { "label": "41/9", "naklon": null }, + "3187": { "label": "41/10", "naklon": null }, + "3195": { "label": "41/11", "naklon": 0 }, + "3857": { "label": "41/12", "naklon": 0 }, + "3183": { "label": "41/13", "naklon": 0 }, + "3177": { "label": "41/14", "naklon": 0 }, + "3189": { "label": "41/15", "naklon": 0 }, + "3186": { "label": "41/16", "naklon": 0 }, + "3178": { "label": "42/1", "naklon": 0 }, + "3219": { "label": "42/2", "naklon": 0 }, + "3475": { "label": "42/3", "naklon": 0 }, + "3175": { "label": "42/4", "naklon": 0 }, + "3222": { "label": "42/5", "naklon": 0 }, + "3221": { "label": "42/6", "naklon": 0 }, + "3181": { "label": "42/7", "naklon": 0 }, + "3180": { "label": "42/8", "naklon": 0 }, + "3218": { "label": "42/9", "naklon": 0 }, + "3176": { "label": "42/10", "naklon": 0 }, + "3174": { "label": "42/11", "naklon": 0 }, + "3220": { "label": "42/12", "naklon": 0 }, + "3533": { "label": "42/13", "naklon": null }, + "3543": { "label": "42/14", "naklon": null }, + "3554": { "label": "42/15", "naklon": null }, + "3549": { "label": "42/16", "naklon": null }, + "2857": { "label": "43/1", "naklon": 5 }, + "2752": { "label": "43/2", "naklon": 5 }, + "2753": { "label": "43/3", "naklon": 5 }, + "3024": { "label": "43/4", "naklon": 5 }, + "2754": { "label": "43/5", "naklon": 5 }, + "4423": { "label": "43/6", "naklon": 5 }, + "4368": { "label": "43/7", "naklon": 5 }, + "2978": { "label": "43/8", "naklon": 5 }, + "2868": { "label": "43/9", "naklon": 5 }, + "4377": { "label": "43/10", "naklon": 5 }, + "2757": { "label": "43/11", "naklon": 5 }, + "2970": { "label": "43/12", "naklon": 5 }, + "2758": { "label": "43/13", "naklon": 5 }, + "4378": { "label": "43/14", "naklon": 5 }, + "2759": { "label": "43/15", "naklon": 5 }, + "4342": { "label": "43/16", "naklon": 5 }, + "3026": { "label": "43/17", "naklon": null }, + "2986": { "label": "43/18", "naklon": null }, + "4343": { "label": "43/19", "naklon": null }, + "2760": { "label": "43/20", "naklon": null }, + "4379": { "label": "43/21", "naklon": null }, + "2971": { "label": "43/22", "naklon": null }, + "2761": { "label": "43/23", "naklon": null }, + "2762": { "label": "43/24", "naklon": null }, + "4339": { "label": "43/25", "naklon": null }, + "4380": { "label": "43/26", "naklon": null }, + "2975": { "label": "43/27", "naklon": null }, + "3003": { "label": "43/28", "naklon": null }, + "4338": { "label": "43/29", "naklon": null }, + "3002": { "label": "43/30", "naklon": null }, + "4345": { "label": "43/31", "naklon": null }, + "2979": { "label": "43/32", "naklon": null }, + "2989": { "label": "43/33", "naklon": null }, + "2996": { "label": "43/34", "naklon": null }, + "2972": { "label": "43/35", "naklon": null }, + "2988": { "label": "43/36", "naklon": null }, + "4344": { "label": "43/37", "naklon": null }, + "3022": { "label": "43/38", "naklon": null }, + "4341": { "label": "43/39", "naklon": null }, + "2983": { "label": "43/40", "naklon": null }, + "2995": { "label": "43/41", "naklon": null }, + "2763": { "label": "43/42", "naklon": null }, + "2764": { "label": "43/43", "naklon": null }, + "2765": { "label": "43/44", "naklon": null }, + "2766": { "label": "43/45", "naklon": null }, + "2767": { "label": "43/46", "naklon": null }, + "2768": { "label": "43/47", "naklon": null }, + "3018": { "label": "43/48", "naklon": null }, + "2982": { "label": "43/49", "naklon": null }, + "3019": { "label": "43/50", "naklon": 0 }, + "3013": { "label": "43/51", "naklon": null }, + "3007": { "label": "43/52", "naklon": null }, + "2980": { "label": "43/53", "naklon": null }, + "3011": { "label": "43/54", "naklon": null }, + "2672": { "label": "43/55", "naklon": null }, + "2673": { "label": "43/56", "naklon": null }, + "2674": { "label": "43/57", "naklon": null }, + "2675": { "label": "43/58", "naklon": null }, + "2676": { "label": "43/59", "naklon": null }, + "2677": { "label": "43/60", "naklon": null }, + "2678": { "label": "43/61", "naklon": null }, + "2679": { "label": "43/62", "naklon": null }, + "2680": { "label": "43/63", "naklon": null }, + "2840": { "label": "43/64", "naklon": null }, + "2682": { "label": "43/65", "naklon": null }, + "2683": { "label": "43/66", "naklon": null }, + "2684": { "label": "43/67", "naklon": 0 }, + "2685": { "label": "43/68", "naklon": null }, + "2686": { "label": "43/69", "naklon": null }, + "2687": { "label": "43/70", "naklon": null }, + "2688": { "label": "43/71", "naklon": null }, + "2689": { "label": "43/72", "naklon": null }, + "2690": { "label": "43/73", "naklon": null }, + "2691": { "label": "43/74", "naklon": null }, + "2692": { "label": "43/75", "naklon": null }, + "2693": { "label": "43/76", "naklon": 0 }, + "2694": { "label": "43/77", "naklon": null }, + "2695": { "label": "43/78", "naklon": null }, + "2696": { "label": "43/79", "naklon": 0 }, + "2697": { "label": "43/80", "naklon": null }, + "2698": { "label": "43/81", "naklon": 0 }, + "2699": { "label": "43/82", "naklon": null }, + "2700": { "label": "43/83", "naklon": 0 }, + "2744": { "label": "43/84", "naklon": null }, + "2745": { "label": "43/85", "naklon": 0 }, + "2746": { "label": "43/86", "naklon": null }, + "2747": { "label": "43/87", "naklon": 0 }, + "2748": { "label": "43/88", "naklon": null }, + "2749": { "label": "43/89", "naklon": 0 }, + "2841": { "label": "43/90", "naklon": null }, + "4237": { "label": "45/1", "naklon": 5 }, + "4226": { "label": "45/2", "naklon": 5 }, + "4242": { "label": "45/3", "naklon": 5 }, + "4179": { "label": "45/4", "naklon": 5 }, + "4247": { "label": "45/5", "naklon": 5 }, + "4245": { "label": "45/6", "naklon": 5 }, + "3872": { "label": "45/7", "naklon": 5 }, + "4175": { "label": "45/8", "naklon": 5 }, + "4236": { "label": "45/9", "naklon": 5 }, + "4170": { "label": "45/10", "naklon": 5 }, + "4238": { "label": "45/11", "naklon": 5 }, + "4246": { "label": "45/12", "naklon": 5 }, + "4166": { "label": "45/13", "naklon": 5 }, + "4227": { "label": "45/14", "naklon": 5 }, + "4171": { "label": "45/15", "naklon": 5 }, + "4180": { "label": "45/16", "naklon": 5 }, + "4244": { "label": "45/17", "naklon": 5 }, + "4199": { "label": "45/18", "naklon": 5 }, + "4239": { "label": "45/19", "naklon": 5 }, + "4207": { "label": "45/20", "naklon": 5 }, + "4223": { "label": "45/21", "naklon": 5 }, + "4230": { "label": "45/22", "naklon": 5 }, + "4233": { "label": "45/23", "naklon": 5 }, + "4222": { "label": "45/24", "naklon": 5 }, + "4217": { "label": "45/25", "naklon": 5 }, + "4243": { "label": "45/26", "naklon": 5 }, + "4200": { "label": "45/27", "naklon": 5 }, + "4228": { "label": "45/28", "naklon": 5 }, + "4211": { "label": "45/29", "naklon": 5 }, + "4234": { "label": "45/30", "naklon": 5 }, + "4235": { "label": "45/31", "naklon": 5 }, + "4203": { "label": "45/32", "naklon": 5 }, + "4240": { "label": "45/33", "naklon": 5 }, + "4224": { "label": "45/34", "naklon": 5 }, + "4232": { "label": "45/35", "naklon": 5 }, + "4231": { "label": "45/36", "naklon": 5 }, + "4161": { "label": "45/37", "naklon": 5 }, + "4225": { "label": "45/38", "naklon": 5 }, + "4241": { "label": "45/39", "naklon": 5 }, + "4229": { "label": "45/40", "naklon": 5 }, + "4221": { "label": "45/41", "naklon": 5 }, + "4212": { "label": "45/42", "naklon": 5 }, + "4216": { "label": "45/43", "naklon": 5 }, + "3864": { "label": "45/44", "naklon": null }, + "3806": { "label": "46/1", "naklon": 5 }, + "3813": { "label": "46/2", "naklon": 5 }, + "3815": { "label": "46/3", "naklon": 5 }, + "3807": { "label": "46/4", "naklon": 5 }, + "3895": { "label": "46/5", "naklon": 5 }, + "3809": { "label": "46/6", "naklon": 5 }, + "3820": { "label": "46/7", "naklon": 5 }, + "3805": { "label": "46/8", "naklon": 5 }, + "3894": { "label": "46/9", "naklon": 0 }, + "4055": { "label": "46/10", "naklon": 0 }, + "3812": { "label": "46/11", "naklon": 5 }, + "3822": { "label": "46/12", "naklon": 5 }, + "3821": { "label": "46/13", "naklon": 5 }, + "3808": { "label": "46/14", "naklon": 5 }, + "3799": { "label": "46/15", "naklon": 5 }, + "3816": { "label": "46/16", "naklon": 5 }, + "3751": { "label": "46/17", "naklon": 5 }, + "3814": { "label": "46/18", "naklon": 5 }, + "4044": { "label": "46/19", "naklon": 0 }, + "3931": { "label": "46/20", "naklon": 0 }, + "3902": { "label": "46/21", "naklon": 5 }, + "3916": { "label": "46/22", "naklon": 5 }, + "3892": { "label": "46/23", "naklon": 5 }, + "3914": { "label": "46/24", "naklon": 5 }, + "3898": { "label": "46/25", "naklon": 5 }, + "3897": { "label": "46/26", "naklon": 5 }, + "3885": { "label": "46/27", "naklon": 5 }, + "3906": { "label": "46/28", "naklon": 5 }, + "3930": { "label": "46/29", "naklon": 0 }, + "3936": { "label": "46/30", "naklon": 0 }, + "3860": { "label": "46/31", "naklon": 5 }, + "3841": { "label": "46/32", "naklon": 5 }, + "3873": { "label": "46/33", "naklon": 5 }, + "3854": { "label": "46/34", "naklon": 5 }, + "3939": { "label": "46/35", "naklon": 5 }, + "3858": { "label": "46/36", "naklon": 5 }, + "3940": { "label": "46/37", "naklon": 5 }, + "4035": { "label": "46/38", "naklon": 5 }, + "3373": { "label": "47/1", "naklon": 0 }, + "3374": { "label": "47/2", "naklon": 0 }, + "3384": { "label": "47/3", "naklon": 0 }, + "3385": { "label": "47/4", "naklon": 0 }, + "4051": { "label": "48/1", "naklon": 5 }, + "4041": { "label": "48/2", "naklon": 5 }, + "4056": { "label": "48/3", "naklon": 5 }, + "3875": { "label": "48/4", "naklon": 5 }, + "4061": { "label": "48/5", "naklon": 5 }, + "4047": { "label": "48/6", "naklon": 5 }, + "4060": { "label": "48/7", "naklon": 5 }, + "4059": { "label": "48/8", "naklon": 5 }, + "4058": { "label": "48/9", "naklon": 5 }, + "3635": { "label": "48/10", "naklon": 5 }, + "3640": { "label": "48/11", "naklon": 5 }, + "3747": { "label": "48/12", "naklon": 5 }, + "3629": { "label": "48/13", "naklon": 5 }, + "4048": { "label": "48/14", "naklon": 5 }, + "4063": { "label": "48/15", "naklon": 5 }, + "4062": { "label": "48/16", "naklon": 5 }, + "4043": { "label": "48/17", "naklon": 5 }, + "4052": { "label": "48/18", "naklon": 5 }, + "4042": { "label": "48/19", "naklon": 5 }, + "4053": { "label": "48/20", "naklon": 5 }, + "4167": { "label": "50/15A", "naklon": null }, + "4159": { "label": "50/15B", "naklon": null }, + "4183": { "label": "50/1", "naklon": 0 }, + "4157": { "label": "50/2", "naklon": 0 }, + "4160": { "label": "50/3", "naklon": 0 }, + "4173": { "label": "50/4", "naklon": 0 }, + "4177": { "label": "50/5", "naklon": 0 }, + "4174": { "label": "50/6", "naklon": 0 }, + "4178": { "label": "50/7", "naklon": 0 }, + "4195": { "label": "50/8", "naklon": 0 }, + "4169": { "label": "50/9", "naklon": 0 }, + "4162": { "label": "50/10", "naklon": 0 }, + "4158": { "label": "50/11", "naklon": 0 }, + "4182": { "label": "50/12", "naklon": 0 }, + "4194": { "label": "50/13", "naklon": 0 }, + "4184": { "label": "50/14", "naklon": 0 }, + "4197": { "label": "50/16", "naklon": null }, + "4164": { "label": "50/17", "naklon": null }, + "3306": { "label": "50/18", "naklon": null }, + "4168": { "label": "50/19", "naklon": null }, + "4193": { "label": "50/20", "naklon": null }, + "4187": { "label": "50/21", "naklon": null }, + "4163": { "label": "50/22", "naklon": null }, + "4165": { "label": "50/23", "naklon": null }, + "4185": { "label": "50/24", "naklon": null }, + "3904": { "label": "50/25", "naklon": null }, + "2619": { "label": "53/1", "naklon": 0 }, + "2623": { "label": "53/2", "naklon": 0 }, + "2617": { "label": "53/3", "naklon": 0 }, + "2622": { "label": "53/4", "naklon": 0 }, + "2618": { "label": "53/5", "naklon": 0 }, + "2626": { "label": "53/6", "naklon": 0 }, + "2869": { "label": "53/7", "naklon": 0 }, + "2613": { "label": "53/8", "naklon": 0 }, + "2608": { "label": "53/9", "naklon": 0 }, + "2611": { "label": "53/10", "naklon": 0 }, + "2598": { "label": "53/11", "naklon": 0 }, + "3528": { "label": "53/12", "naklon": 0 }, + "3545": { "label": "53/13", "naklon": 0 }, + "2620": { "label": "53/14", "naklon": 0 }, + "2612": { "label": "53/15", "naklon": 0 }, + "2615": { "label": "53/16", "naklon": 0 }, + "3722": { "label": "53/17", "naklon": 0 }, + "2624": { "label": "53/18", "naklon": 0 }, + "2609": { "label": "53/19", "naklon": 0 }, + "2625": { "label": "53/20", "naklon": 0 }, + "2602": { "label": "53/21", "naklon": 0 }, + "2610": { "label": "53/22", "naklon": 0 }, + "2599": { "label": "53/23", "naklon": 0 }, + "2605": { "label": "53/24", "naklon": 0 }, + "2593": { "label": "53/25", "naklon": 0 }, + "3074": { "label": "53/26", "naklon": 0 }, + "2740": { "label": "53/27", "naklon": 0 }, + "2614": { "label": "53/28", "naklon": 0 }, + "2601": { "label": "53/29", "naklon": 0 }, + "4196": { "label": "53/30", "naklon": 0 }, + "2607": { "label": "53/31", "naklon": 0 }, + "2582": { "label": "53/32", "naklon": 0 }, + "2594": { "label": "53/33", "naklon": 0 }, + "2589": { "label": "53/34", "naklon": 0 }, + "2596": { "label": "53/35", "naklon": 0 }, + "2603": { "label": "53/36", "naklon": 0 }, + "2597": { "label": "53/37", "naklon": 0 }, + "2590": { "label": "53/38", "naklon": 0 }, + "2581": { "label": "53/39", "naklon": 0 }, + "2583": { "label": "53/40", "naklon": 0 }, + "2580": { "label": "53/41", "naklon": 0 }, + "2579": { "label": "53/42", "naklon": 0 }, + "2797": { "label": "53/43", "naklon": 0 }, + "2577": { "label": "53/44", "naklon": 0 }, + "2586": { "label": "53/45", "naklon": 0 }, + "2588": { "label": "53/46", "naklon": 0 }, + "2591": { "label": "53/47", "naklon": 0 }, + "2592": { "label": "53/48", "naklon": 0 }, + "2573": { "label": "53/49", "naklon": 0 }, + "2595": { "label": "53/50", "naklon": 0 }, + "2587": { "label": "53/51", "naklon": 0 }, + "2578": { "label": "53/52", "naklon": 0 }, + "2574": { "label": "53/53", "naklon": 0 }, + "2571": { "label": "53/54", "naklon": 0 }, + "2570": { "label": "53/55", "naklon": 0 }, + "2576": { "label": "53/56", "naklon": 0 }, + "2881": { "label": "53/57", "naklon": 0 }, + "2575": { "label": "53/58", "naklon": 0 }, + "2572": { "label": "53/59", "naklon": 0 }, + "2569": { "label": "53/60", "naklon": 0 }, + "4324": { "label": "55/1", "naklon": 0 }, + "4319": { "label": "55/2", "naklon": 0 }, + "4327": { "label": "55/3", "naklon": 0 }, + "4333": { "label": "55/4", "naklon": 0 }, + "4332": { "label": "55/5", "naklon": 0 }, + "4320": { "label": "55/6", "naklon": 0 }, + "4317": { "label": "55/7", "naklon": 0 }, + "4318": { "label": "55/8", "naklon": 0 }, + "4328": { "label": "55/9", "naklon": 0 }, + "4323": { "label": "55/10", "naklon": 0 }, + "4325": { "label": "55/11", "naklon": 0 }, + "4326": { "label": "55/12", "naklon": 0 }, + "4316": { "label": "55/13", "naklon": 0 }, + "4322": { "label": "55/14", "naklon": 0 }, + "4331": { "label": "55/15", "naklon": 0 }, + "4321": { "label": "55/16", "naklon": 0 }, + "4315": { "label": "55/17", "naklon": 0 }, + "4329": { "label": "55/18", "naklon": 0 }, + "4334": { "label": "55/19", "naklon": 0 }, + "4330": { "label": "55/20", "naklon": 0 } +}; + + +let svetlaSorted = [{ "label": "1/3A", "node": 3993, "naklon": 0 }, +{ "label": "1/3B", "node": 3989, "naklon": 15 }, +{ "label": "1/1", "node": 3976, "naklon": 0 }, +{ "label": "1/2", "node": 4181, "naklon": 0 }, +{ "label": "1/4", "node": 4376, "naklon": 15 }, +{ "label": "1/5", "node": 3868, "naklon": 15 }, +{ "label": "1/6", "node": 3728, "naklon": 15 }, +{ "label": "1/7", "node": 3730, "naklon": 0 }, +{ "label": "1/8", "node": 4374, "naklon": 0 }, +{ "label": "1/9", "node": 3718, "naklon": 15 }, +{ "label": "1/10", "node": 4375, "naklon": 15 }, +{ "label": "1/11", "node": 4172, "naklon": 15 }, +{ "label": "1/12", "node": 4176, "naklon": 15 }, +{ "label": "2/1", "node": 3800, "naklon": 5 }, +{ "label": "2/2", "node": 3823, "naklon": 5 }, +{ "label": "2/3", "node": 3905, "naklon": 5 }, +{ "label": "2/4", "node": 3803, "naklon": 5 }, +{ "label": "2/5", "node": 3817, "naklon": 5 }, +{ "label": "2/6", "node": 3818, "naklon": 5 }, +{ "label": "2/7", "node": 3811, "naklon": 5 }, +{ "label": "2/8", "node": 3915, "naklon": 5 }, +{ "label": "2/9", "node": 3843, "naklon": 10 }, +{ "label": "2/10", "node": 3827, "naklon": 10 }, +{ "label": "2/11", "node": 4220, "naklon": 10 }, +{ "label": "2/12", "node": 3826, "naklon": 10 }, +{ "label": "2/13", "node": 3834, "naklon": 10 }, +{ "label": "2/14", "node": 3838, "naklon": 10 }, +{ "label": "2/15", "node": 2823, "naklon": 10 }, +{ "label": "2/16", "node": 3750, "naklon": 10 }, +{ "label": "2/17", "node": 3378, "naklon": 0 }, +{ "label": "2/18", "node": 3376, "naklon": 0 }, +{ "label": "2/19", "node": 3379, "naklon": 0 }, +{ "label": "2/20", "node": 3285, "naklon": 0 }, +{ "label": "2/21", "node": 3382, "naklon": 0 }, +{ "label": "2/22", "node": 3383, "naklon": 0 }, +{ "label": "2/24", "node": 3375, "naklon": 0 }, +{ "label": "2/25", "node": 3381, "naklon": 0 }, +{ "label": "2/26", "node": 3380, "naklon": 0 }, +{ "label": "2/27", "node": 3828, "naklon": 10 }, +{ "label": "2/28", "node": 3377, "naklon": 0 }, +{ "label": "7/1", "node": 3591, "naklon": 0 }, +{ "label": "7/2", "node": 3587, "naklon": 0 }, +{ "label": "7/3", "node": 3468, "naklon": 0 }, +{ "label": "7/4", "node": 3466, "naklon": 0 }, +{ "label": "7/5", "node": 3474, "naklon": 0 }, +{ "label": "7/6", "node": 3481, "naklon": 0 }, +{ "label": "7/7", "node": 3589, "naklon": 0 }, +{ "label": "7/8", "node": 3472, "naklon": 0 }, +{ "label": "7/9", "node": 3473, "naklon": 0 }, +{ "label": "7/10", "node": 3584, "naklon": 0 }, +{ "label": "7/11", "node": 3571, "naklon": 0 }, +{ "label": "7/12", "node": 3476, "naklon": 0 }, +{ "label": "7/13", "node": 3590, "naklon": 0 }, +{ "label": "7/14", "node": 3478, "naklon": 0 }, +{ "label": "7/15", "node": 3471, "naklon": 0 }, +{ "label": "7/16", "node": 3467, "naklon": 0 }, +{ "label": "7/17", "node": 3479, "naklon": 0 }, +{ "label": "7/18", "node": 3480, "naklon": 0 }, +{ "label": "7/19", "node": 3477, "naklon": 0 }, +{ "label": "12/1", "node": 3362, "naklon": 0 }, +{ "label": "12/2", "node": 3355, "naklon": 0 }, +{ "label": "12/3", "node": 3356, "naklon": 0 }, +{ "label": "12/4", "node": 3349, "naklon": 0 }, +{ "label": "12/5", "node": 3357, "naklon": 0 }, +{ "label": "12/6", "node": 3350, "naklon": 0 }, +{ "label": "12/7", "node": 3353, "naklon": 0 }, +{ "label": "12/8", "node": 3539, "naklon": 0 }, +{ "label": "12/9", "node": 3050, "naklon": 0 }, +{ "label": "12/10", "node": 3361, "naklon": 0 }, +{ "label": "12/11", "node": 3360, "naklon": 0 }, +{ "label": "12/12", "node": 3358, "naklon": 0 }, +{ "label": "12/13", "node": 3541, "naklon": 0 }, +{ "label": "12/14", "node": 3551, "naklon": 0 }, +{ "label": "12/15", "node": 3514, "naklon": 0 }, +{ "label": "12/16", "node": 3547, "naklon": 0 }, +{ "label": "12/17", "node": 3562, "naklon": 0 }, +{ "label": "12/18", "node": 3525, "naklon": 0 }, +{ "label": "12/19", "node": 3558, "naklon": 0 }, +{ "label": "12/20", "node": 3511, "naklon": 0 }, +{ "label": "12/21", "node": 3058, "naklon": 0 }, +{ "label": "12/22", "node": 3062, "naklon": 0 }, +{ "label": "12/23", "node": 3070, "naklon": 0 }, +{ "label": "12/24", "node": 3447, "naklon": 0 }, +{ "label": "12/25", "node": 3056, "naklon": 0 }, +{ "label": "12/26", "node": 3057, "naklon": 0 }, +{ "label": "12/27", "node": 3071, "naklon": 0 }, +{ "label": "12/28", "node": 3061, "naklon": 0 }, +{ "label": "12/29", "node": 3069, "naklon": 0 }, +{ "label": "12/30", "node": 3077, "naklon": 0 }, +{ "label": "12/31", "node": 3080, "naklon": 0 }, +{ "label": "12/32", "node": 3081, "naklon": 0 }, +{ "label": "12/33", "node": 3078, "naklon": 0 }, +{ "label": "12/34", "node": 4037, "naklon": 0 }, +{ "label": "12/35", "node": 3067, "naklon": 0 }, +{ "label": "12/36", "node": 3051, "naklon": 0 }, +{ "label": "12/37", "node": 2924, "naklon": 0 }, +{ "label": "12/38", "node": 3060, "naklon": 0 }, +{ "label": "12/39", "node": 3073, "naklon": 0 }, +{ "label": "12/40", "node": 3469, "naklon": 0 }, +{ "label": "12/41", "node": 2923, "naklon": 0 }, +{ "label": "12/42", "node": 2925, "naklon": 0 }, +{ "label": "12/43", "node": 3359, "naklon": 0 }, +{ "label": "12/44", "node": 3055, "naklon": 0 }, +{ "label": "12/45", "node": 2922, "naklon": 0 }, +{ "label": "12/46", "node": 3084, "naklon": 0 }, +{ "label": "12/47", "node": 3064, "naklon": 0 }, +{ "label": "12/48", "node": 3066, "naklon": 0 }, +{ "label": "12/49", "node": 3072, "naklon": 0 }, +{ "label": "13/13A", "node": 3415, "naklon": 0 }, +{ "label": "13/13B", "node": 3409, "naklon": 0 }, +{ "label": "13/13C", "node": 3399, "naklon": 0 }, +{ "label": "13/29A", "node": 3410, "naklon": 0 }, +{ "label": "13/29B", "node": 3407, "naklon": 0 }, +{ "label": "13/34A", "node": 3405, "naklon": 0 }, +{ "label": "13/34B", "node": 3404, "naklon": 0 }, +{ "label": "13/45A", "node": 3392, "naklon": 0 }, +{ "label": "13/45B", "node": 3386, "naklon": 0 }, +{ "label": "13/60A", "node": 3303, "naklon": 3 }, +{ "label": "13/60B", "node": 3302, "naklon": 3 }, +{ "label": "13/70A", "node": 3319, "naklon": 6 }, +{ "label": "13/70B", "node": 3317, "naklon": 6 }, +{ "label": "13/70C", "node": 3326, "naklon": 6 }, +{ "label": "13/73A", "node": 3351, "naklon": 6 }, +{ "label": "13/73B", "node": 3313, "naklon": 6 }, +{ "label": "13/83A", "node": 3316, "naklon": 0 }, +{ "label": "13/83B", "node": 3320, "naklon": 0 }, +{ "label": "13/95A", "node": 3336, "naklon": 0 }, +{ "label": "13/95B", "node": 3323, "naklon": 0 }, +{ "label": "13/98A", "node": 3339, "naklon": 0 }, +{ "label": "13/98B", "node": 3333, "naklon": 0 }, +{ "label": "13/1", "node": 3425, "naklon": 0 }, +{ "label": "13/2", "node": 3419, "naklon": 0 }, +{ "label": "13/3", "node": 3416, "naklon": 0 }, +{ "label": "13/4", "node": 3332, "naklon": 0 }, +{ "label": "13/5", "node": 3422, "naklon": 0 }, +{ "label": "13/6", "node": 3417, "naklon": 0 }, +{ "label": "13/7", "node": 3418, "naklon": 0 }, +{ "label": "13/8", "node": 3424, "naklon": 0 }, +{ "label": "13/9", "node": 3334, "naklon": 0 }, +{ "label": "13/10", "node": 4363, "naklon": 0 }, +{ "label": "13/11", "node": 3423, "naklon": 0 }, +{ "label": "13/12", "node": 3406, "naklon": 0 }, +{ "label": "13/14", "node": 3411, "naklon": 0 }, +{ "label": "13/15", "node": 3412, "naklon": 0 }, +{ "label": "13/16", "node": 3413, "naklon": 0 }, +{ "label": "13/17", "node": 3414, "naklon": 0 }, +{ "label": "13/18", "node": 3391, "naklon": 0 }, +{ "label": "13/19", "node": 3370, "naklon": 0 }, +{ "label": "13/20", "node": 3369, "naklon": 0 }, +{ "label": "13/21", "node": 3408, "naklon": 0 }, +{ "label": "13/22", "node": 3393, "naklon": 0 }, +{ "label": "13/23", "node": 3128, "naklon": 0 }, +{ "label": "13/24", "node": 3197, "naklon": 0 }, +{ "label": "13/25", "node": 4364, "naklon": 0 }, +{ "label": "13/26", "node": 3155, "naklon": 0 }, +{ "label": "13/27", "node": 3196, "naklon": 0 }, +{ "label": "13/28", "node": 3144, "naklon": 0 }, +{ "label": "13/30", "node": 3150, "naklon": 0 }, +{ "label": "13/31", "node": 3390, "naklon": 0 }, +{ "label": "13/32", "node": 3401, "naklon": 0 }, +{ "label": "13/33", "node": 3275, "naklon": 0 }, +{ "label": "13/35", "node": 3371, "naklon": 0 }, +{ "label": "13/36", "node": 3389, "naklon": 0 }, +{ "label": "13/37", "node": 3388, "naklon": 0 }, +{ "label": "13/38", "node": 3365, "naklon": 0 }, +{ "label": "13/39", "node": 3363, "naklon": 0 }, +{ "label": "13/40", "node": 3397, "naklon": 0 }, +{ "label": "13/40/1", "node": 3567, "naklon": 0 }, +{ "label": "13/41", "node": 3387, "naklon": 0 }, +{ "label": "13/42", "node": 3403, "naklon": 0 }, +{ "label": "13/43", "node": 3147, "naklon": 0 }, +{ "label": "13/44", "node": 3141, "naklon": 0 }, +{ "label": "13/46", "node": 3364, "naklon": 0 }, +{ "label": "13/47", "node": 3367, "naklon": 0 }, +{ "label": "13/48", "node": 3368, "naklon": 0 }, +{ "label": "13/49", "node": 3402, "naklon": 0 }, +{ "label": "13/50", "node": 3366, "naklon": 0 }, +{ "label": "13/51", "node": 3395, "naklon": 0 }, +{ "label": "13/52", "node": 3372, "naklon": 0 }, +{ "label": "13/53", "node": 3394, "naklon": 0 }, +{ "label": "13/54", "node": 3308, "naklon": 0 }, +{ "label": "13/54/1", "node": 3847, "naklon": 0 }, +{ "label": "13/55", "node": 3312, "naklon": 3 }, +{ "label": "13/56", "node": 3309, "naklon": 3 }, +{ "label": "13/57", "node": 3311, "naklon": 3 }, +{ "label": "13/58", "node": 3310, "naklon": 3 }, +{ "label": "13/59", "node": 4365, "naklon": 3 }, +{ "label": "13/60/1", "node": 4093, "naklon": 3 }, +{ "label": "13/61", "node": 3304, "naklon": 3 }, +{ "label": "13/62", "node": 3307, "naklon": 3 }, +{ "label": "13/63", "node": 3271, "naklon": 3 }, +{ "label": "13/64", "node": 3301, "naklon": 3 }, +{ "label": "13/65", "node": 4366, "naklon": 3 }, +{ "label": "13/66", "node": 3300, "naklon": 3 }, +{ "label": "13/67", "node": 3185, "naklon": 0 }, +{ "label": "13/68", "node": 3184, "naklon": 0 }, +{ "label": "13/69", "node": 3188, "naklon": 0 }, +{ "label": "13/71", "node": 3343, "naklon": 6 }, +{ "label": "13/71/1", "node": 3819, "naklon": 6 }, +{ "label": "13/71/2", "node": 3880, "naklon": 6 }, +{ "label": "13/72", "node": 3348, "naklon": 6 }, +{ "label": "13/74", "node": 3344, "naklon": 6 }, +{ "label": "13/75", "node": 3346, "naklon": 6 }, +{ "label": "13/75/1", "node": 3597, "naklon": 6 }, +{ "label": "13/76", "node": 3345, "naklon": 6 }, +{ "label": "13/77", "node": 3322, "naklon": 0 }, +{ "label": "13/78", "node": 3325, "naklon": 0 }, +{ "label": "13/78/1", "node": 4310, "naklon": 0 }, +{ "label": "13/79", "node": 3315, "naklon": 0 }, +{ "label": "13/80", "node": 3328, "naklon": 0 }, +{ "label": "13/81", "node": 3321, "naklon": 0 }, +{ "label": "13/82", "node": 3324, "naklon": 0 }, +{ "label": "13/84", "node": 3140, "naklon": 0 }, +{ "label": "13/85", "node": 3153, "naklon": 0 }, +{ "label": "13/86", "node": 3145, "naklon": 0 }, +{ "label": "13/87", "node": 3134, "naklon": 0 }, +{ "label": "13/88", "node": 3151, "naklon": 0 }, +{ "label": "13/89", "node": 3143, "naklon": 0 }, +{ "label": "13/90", "node": 3318, "naklon": 0 }, +{ "label": "13/91", "node": 3347, "naklon": 0 }, +{ "label": "13/94", "node": 3314, "naklon": 0 }, +{ "label": "13/96", "node": 3331, "naklon": 0 }, +{ "label": "13/97", "node": 3327, "naklon": 0 }, +{ "label": "13/99", "node": 3329, "naklon": 0 }, +{ "label": "13/100", "node": 3337, "naklon": 0 }, +{ "label": "13/101", "node": 3330, "naklon": 0 }, +{ "label": "13/102", "node": 3335, "naklon": 0 }, +{ "label": "13/103", "node": 3420, "naklon": 0 }, +{ "label": "13/104", "node": 3421, "naklon": 0 }, +{ "label": "13/105", "node": 4361, "naklon": 0 }, +{ "label": "13/106", "node": 4362, "naklon": 0 }, +{ "label": "13/107", "node": 3526, "naklon": 0 }, +{ "label": "13/108", "node": 4424, "naklon": null }, +{ "label": "13/109", "node": 3561, "naklon": null }, +{ "label": "13/110", "node": 3527, "naklon": null }, +{ "label": "13/111", "node": 3521, "naklon": null }, +{ "label": "13/112", "node": 3552, "naklon": null }, +{ "label": "13/113", "node": 3544, "naklon": null }, +{ "label": "13/114", "node": 3534, "naklon": null }, +{ "label": "13/115", "node": 3516, "naklon": null }, +{ "label": "13/116", "node": 3513, "naklon": null }, +{ "label": "13/117", "node": 3565, "naklon": null }, +{ "label": "13/118", "node": 3866, "naklon": null }, +{ "label": "14/1", "node": 3136, "naklon": 0 }, +{ "label": "14/2", "node": 3137, "naklon": 0 }, +{ "label": "14/3", "node": 3135, "naklon": 0 }, +{ "label": "14/4", "node": 3149, "naklon": 0 }, +{ "label": "14/5", "node": 3142, "naklon": 0 }, +{ "label": "14/6", "node": 3342, "naklon": 0 }, +{ "label": "14/7", "node": 3340, "naklon": 0 }, +{ "label": "14/8", "node": 3152, "naklon": 0 }, +{ "label": "14/9", "node": 3886, "naklon": 0 }, +{ "label": "14/10", "node": 3341, "naklon": null }, +{ "label": "14/11", "node": 3352, "naklon": null }, +{ "label": "15/1", "node": 3396, "naklon": 5 }, +{ "label": "15/2", "node": 2784, "naklon": 5 }, +{ "label": "15/3", "node": 2788, "naklon": 5 }, +{ "label": "15/4", "node": 2801, "naklon": 5 }, +{ "label": "15/5", "node": 2815, "naklon": 5 }, +{ "label": "15/6", "node": 2829, "naklon": 5 }, +{ "label": "15/7", "node": 2796, "naklon": 5 }, +{ "label": "15/8", "node": 2803, "naklon": 5 }, +{ "label": "15/8/1", "node": 4304, "naklon": 5 }, +{ "label": "15/8/2", "node": 4311, "naklon": 5 }, +{ "label": "15/9", "node": 2821, "naklon": 5 }, +{ "label": "15/10", "node": 3400, "naklon": 5 }, +{ "label": "15/11", "node": 2799, "naklon": 5 }, +{ "label": "15/12", "node": 2804, "naklon": 5 }, +{ "label": "15/12/1", "node": 4303, "naklon": 5 }, +{ "label": "15/12/2", "node": 4309, "naklon": 5 }, +{ "label": "15/13", "node": 2806, "naklon": 5 }, +{ "label": "15/14", "node": 2787, "naklon": 5 }, +{ "label": "15/15", "node": 2809, "naklon": 5 }, +{ "label": "15/16", "node": 2814, "naklon": 0 }, +{ "label": "15/17", "node": 3934, "naklon": 0 }, +{ "label": "15/18", "node": 3192, "naklon": 0 }, +{ "label": "15/19", "node": 2812, "naklon": 0 }, +{ "label": "15/20", "node": 4070, "naklon": 0 }, +{ "label": "15/21", "node": 2826, "naklon": 0 }, +{ "label": "15/22", "node": 2808, "naklon": 3 }, +{ "label": "15/23", "node": 2795, "naklon": 3 }, +{ "label": "15/24", "node": 2807, "naklon": 3 }, +{ "label": "15/25", "node": 2831, "naklon": 0 }, +{ "label": "15/26", "node": 2862, "naklon": null }, +{ "label": "15/27", "node": 2861, "naklon": 0 }, +{ "label": "15/28", "node": 2866, "naklon": 0 }, +{ "label": "15/28/1", "node": 3546, "naklon": 0 }, +{ "label": "15/29", "node": 4146, "naklon": 0 }, +{ "label": "15/29/1", "node": 3001, "naklon": 0 }, +{ "label": "15/30", "node": 2835, "naklon": 0 }, +{ "label": "15/31", "node": 2874, "naklon": 0 }, +{ "label": "15/32", "node": 2852, "naklon": 0 }, +{ "label": "15/33", "node": 2851, "naklon": 0 }, +{ "label": "15/33/1", "node": 3560, "naklon": 0 }, +{ "label": "15/34", "node": 2858, "naklon": 0 }, +{ "label": "15/34/1", "node": 4306, "naklon": 0 }, +{ "label": "15/35", "node": 2856, "naklon": 0 }, +{ "label": "15/36", "node": 2847, "naklon": 0 }, +{ "label": "15/36/1", "node": 3556, "naklon": 0 }, +{ "label": "15/37", "node": 3950, "naklon": 0 }, +{ "label": "15/38", "node": 2848, "naklon": 0 }, +{ "label": "15/39", "node": 2863, "naklon": 0 }, +{ "label": "15/39/1", "node": 4313, "naklon": 0 }, +{ "label": "15/40", "node": 2873, "naklon": 0 }, +{ "label": "15/40/1", "node": 2984, "naklon": 0 }, +{ "label": "15/41", "node": 2854, "naklon": 0 }, +{ "label": "15/42", "node": 2859, "naklon": 0 }, +{ "label": "15/43", "node": 2872, "naklon": 0 }, +{ "label": "15/44", "node": 2849, "naklon": 0 }, +{ "label": "15/45", "node": 2864, "naklon": 0 }, +{ "label": "15/46", "node": 3553, "naklon": null }, +{ "label": "15/47", "node": 3021, "naklon": null }, +{ "label": "15/47/1", "node": 3008, "naklon": null }, +{ "label": "15/48", "node": 3017, "naklon": null }, +{ "label": "15/49", "node": 3014, "naklon": null }, +{ "label": "15/50", "node": 2981, "naklon": null }, +{ "label": "15/51", "node": 3020, "naklon": null }, +{ "label": "15/52", "node": 3027, "naklon": null }, +{ "label": "15/53", "node": 3006, "naklon": null }, +{ "label": "15/54", "node": 3012, "naklon": null }, +{ "label": "15/55", "node": 2738, "naklon": 0 }, +{ "label": "15/56", "node": 2725, "naklon": 0 }, +{ "label": "15/57", "node": 3016, "naklon": null }, +{ "label": "15/58", "node": 3005, "naklon": null }, +{ "label": "15/58/1", "node": 3009, "naklon": null }, +{ "label": "15/59", "node": 3010, "naklon": 0 }, +{ "label": "15/59/1", "node": 3538, "naklon": 0 }, +{ "label": "15/59/2", "node": 4145, "naklon": 0 }, +{ "label": "15/60", "node": 2713, "naklon": 0 }, +{ "label": "15/61", "node": 2789, "naklon": 0 }, +{ "label": "15/62", "node": 2736, "naklon": 0 }, +{ "label": "15/63", "node": 2739, "naklon": 0 }, +{ "label": "15/64", "node": 4346, "naklon": 0 }, +{ "label": "15/65", "node": 2731, "naklon": 0 }, +{ "label": "15/66", "node": 2818, "naklon": 0 }, +{ "label": "15/66/1", "node": 3557, "naklon": 0 }, +{ "label": "15/67", "node": 2822, "naklon": 0 }, +{ "label": "15/68", "node": 2833, "naklon": 0 }, +{ "label": "15/69", "node": 2834, "naklon": 0 }, +{ "label": "15/70", "node": 3097, "naklon": 0 }, +{ "label": "15/71", "node": 2824, "naklon": 0 }, +{ "label": "15/72", "node": 2828, "naklon": 0 }, +{ "label": "15/73", "node": 2600, "naklon": 0 }, +{ "label": "15/73/1", "node": 4314, "naklon": 0 }, +{ "label": "15/74", "node": 2832, "naklon": 0 }, +{ "label": "15/75", "node": 4360, "naklon": 0 }, +{ "label": "15/76", "node": 2846, "naklon": 0 }, +{ "label": "15/77", "node": 2584, "naklon": 0 }, +{ "label": "15/78", "node": 2843, "naklon": 0 }, +{ "label": "15/78/1", "node": 4308, "naklon": 0 }, +{ "label": "15/79", "node": 4144, "naklon": null }, +{ "label": "15/80", "node": 2844, "naklon": 0 }, +{ "label": "15/81", "node": 2842, "naklon": 0 }, +{ "label": "15/82", "node": 2838, "naklon": 0 }, +{ "label": "15/83", "node": 2837, "naklon": null }, +{ "label": "15/83/1", "node": 3555, "naklon": null }, +{ "label": "15/84", "node": 2839, "naklon": 0 }, +{ "label": "15/85", "node": 2830, "naklon": 0 }, +{ "label": "15/86", "node": 4066, "naklon": 0 }, +{ "label": "15/87", "node": 2836, "naklon": 0 }, +{ "label": "15/88", "node": 2911, "naklon": 0 }, +{ "label": "15/89", "node": 2825, "naklon": 0 }, +{ "label": "15/90", "node": 2811, "naklon": 0 }, +{ "label": "15/94", "node": 3740, "naklon": 15 }, +{ "label": "15/95", "node": 2734, "naklon": 15 }, +{ "label": "15/96", "node": 3105, "naklon": 15 }, +{ "label": "15/97", "node": 2732, "naklon": 15 }, +{ "label": "15/98", "node": 2727, "naklon": 15 }, +{ "label": "15/99", "node": 2735, "naklon": 15 }, +{ "label": "15/100", "node": 3926, "naklon": 15 }, +{ "label": "15/101", "node": 2918, "naklon": 0 }, +{ "label": "15/102", "node": 2705, "naklon": 10 }, +{ "label": "15/103", "node": 2708, "naklon": 10 }, +{ "label": "15/104", "node": 2721, "naklon": 10 }, +{ "label": "15/105", "node": 2719, "naklon": 10 }, +{ "label": "15/106", "node": 2919, "naklon": 10 }, +{ "label": "15/107", "node": 3101, "naklon": 10 }, +{ "label": "15/108", "node": 2853, "naklon": 10 }, +{ "label": "15/109", "node": 2715, "naklon": 10 }, +{ "label": "15/110", "node": 2712, "naklon": 0 }, +{ "label": "15/111", "node": 2711, "naklon": 0 }, +{ "label": "15/112", "node": 2709, "naklon": 0 }, +{ "label": "15/113", "node": 2710, "naklon": 0 }, +{ "label": "15/114", "node": 2907, "naklon": 0 }, +{ "label": "15/115", "node": 2906, "naklon": 0 }, +{ "label": "15/116", "node": 2908, "naklon": 0 }, +{ "label": "15/117", "node": 2901, "naklon": 0 }, +{ "label": "15/118", "node": 2913, "naklon": 0 }, +{ "label": "15/119", "node": 3656, "naklon": 0 }, +{ "label": "15/120", "node": 2781, "naklon": 0 }, +{ "label": "15/121", "node": 2802, "naklon": 0 }, +{ "label": "15/122", "node": 2791, "naklon": 0 }, +{ "label": "15/123", "node": 2783, "naklon": 0 }, +{ "label": "15/124", "node": 2794, "naklon": 0 }, +{ "label": "15/125", "node": 3139, "naklon": 0 }, +{ "label": "15/126", "node": 3229, "naklon": 5 }, +{ "label": "15/127", "node": 3239, "naklon": 5 }, +{ "label": "15/128", "node": 3230, "naklon": 5 }, +{ "label": "15/129", "node": 4016, "naklon": null }, +{ "label": "16/16A", "node": 3608, "naklon": 0 }, +{ "label": "16/16B", "node": 4151, "naklon": 0 }, +{ "label": "16/1", "node": 3710, "naklon": 0 }, +{ "label": "16/2", "node": 3726, "naklon": 0 }, +{ "label": "16/3", "node": 3743, "naklon": 0 }, +{ "label": "16/4", "node": 3724, "naklon": 0 }, +{ "label": "16/5", "node": 3712, "naklon": 0 }, +{ "label": "16/6", "node": 3739, "naklon": 0 }, +{ "label": "16/7", "node": 3742, "naklon": 0 }, +{ "label": "16/8", "node": 3731, "naklon": 0 }, +{ "label": "16/9", "node": 3727, "naklon": 0 }, +{ "label": "16/10", "node": 3729, "naklon": 0 }, +{ "label": "16/11", "node": 3736, "naklon": 0 }, +{ "label": "16/12", "node": 3713, "naklon": 0 }, +{ "label": "16/13", "node": 3715, "naklon": 0 }, +{ "label": "16/14", "node": 3733, "naklon": 0 }, +{ "label": "16/15", "node": 3732, "naklon": 0 }, +{ "label": "16/17", "node": 3634, "naklon": 0 }, +{ "label": "16/18", "node": 3610, "naklon": 0 }, +{ "label": "16/19", "node": 3626, "naklon": 0 }, +{ "label": "16/20", "node": 3618, "naklon": 0 }, +{ "label": "16/21", "node": 3619, "naklon": 0 }, +{ "label": "16/22", "node": 3628, "naklon": 0 }, +{ "label": "16/23", "node": 3615, "naklon": 0 }, +{ "label": "16/24", "node": 3609, "naklon": 0 }, +{ "label": "16/25", "node": 3606, "naklon": 0 }, +{ "label": "16/26", "node": 3624, "naklon": 0 }, +{ "label": "16/27", "node": 3627, "naklon": 0 }, +{ "label": "16/28", "node": 3607, "naklon": 0 }, +{ "label": "16/29", "node": 4370, "naklon": 0 }, +{ "label": "16/30", "node": 3692, "naklon": 0 }, +{ "label": "16/31", "node": 3614, "naklon": 0 }, +{ "label": "16/32", "node": 3623, "naklon": 0 }, +{ "label": "16/33", "node": 4373, "naklon": 0 }, +{ "label": "16/34", "node": 3620, "naklon": 0 }, +{ "label": "16/35", "node": 3685, "naklon": 0 }, +{ "label": "16/36", "node": 3616, "naklon": 0 }, +{ "label": "16/37", "node": 3686, "naklon": 0 }, +{ "label": "16/38", "node": 3688, "naklon": 0 }, +{ "label": "16/39", "node": 3684, "naklon": 0 }, +{ "label": "16/40", "node": 3825, "naklon": 0 }, +{ "label": "16/41", "node": 3865, "naklon": 0 }, +{ "label": "16/42", "node": 3824, "naklon": 0 }, +{ "label": "16/43", "node": 3871, "naklon": 0 }, +{ "label": "16/44", "node": 3801, "naklon": 0 }, +{ "label": "16/45", "node": 3862, "naklon": 0 }, +{ "label": "16/46", "node": 3876, "naklon": 0 }, +{ "label": "16/47", "node": 3861, "naklon": 0 }, +{ "label": "16/48", "node": 4215, "naklon": 0 }, +{ "label": "16/49", "node": 3605, "naklon": 10 }, +{ "label": "16/50", "node": 3603, "naklon": 10 }, +{ "label": "16/51", "node": 3592, "naklon": 10 }, +{ "label": "16/52", "node": 3598, "naklon": 10 }, +{ "label": "16/53", "node": 3594, "naklon": 10 }, +{ "label": "16/54", "node": 3593, "naklon": 10 }, +{ "label": "16/55", "node": 3630, "naklon": 10 }, +{ "label": "16/56", "node": 3763, "naklon": 10 }, +{ "label": "16/57", "node": 3746, "naklon": 10 }, +{ "label": "16/58", "node": 3699, "naklon": 0 }, +{ "label": "16/59", "node": 3698, "naklon": 0 }, +{ "label": "16/60", "node": 3709, "naklon": null }, +{ "label": "16/61", "node": 3708, "naklon": 0 }, +{ "label": "16/62", "node": 3703, "naklon": null }, +{ "label": "16/63", "node": 3700, "naklon": 0 }, +{ "label": "16/64", "node": 3701, "naklon": null }, +{ "label": "16/65", "node": 3704, "naklon": 0 }, +{ "label": "16/66", "node": 3707, "naklon": null }, +{ "label": "16/67", "node": 3810, "naklon": 0 }, +{ "label": "16/68", "node": 4208, "naklon": null }, +{ "label": "16/69", "node": 3867, "naklon": 0 }, +{ "label": "16/70", "node": 4372, "naklon": null }, +{ "label": "16/71", "node": 3881, "naklon": 0 }, +{ "label": "16/72", "node": 4204, "naklon": null }, +{ "label": "16/73", "node": 3869, "naklon": 0 }, +{ "label": "16/74", "node": 4202, "naklon": null }, +{ "label": "16/75", "node": 3830, "naklon": 0 }, +{ "label": "16/76", "node": 3870, "naklon": null }, +{ "label": "16/77", "node": 3964, "naklon": 0 }, +{ "label": "16/78", "node": 3849, "naklon": 0 }, +{ "label": "16/79", "node": 3694, "naklon": null }, +{ "label": "16/80", "node": 3717, "naklon": 0 }, +{ "label": "16/81", "node": 3877, "naklon": null }, +{ "label": "16/82", "node": 3755, "naklon": 0 }, +{ "label": "16/83", "node": 3725, "naklon": null }, +{ "label": "16/84", "node": 3716, "naklon": 0 }, +{ "label": "16/85", "node": 3696, "naklon": null }, +{ "label": "16/86", "node": 3702, "naklon": 0 }, +{ "label": "16/87", "node": 3706, "naklon": null }, +{ "label": "16/88", "node": 3850, "naklon": 0 }, +{ "label": "16/89", "node": 3848, "naklon": null }, +{ "label": "16/90", "node": 3737, "naklon": null }, +{ "label": "16/91", "node": 3705, "naklon": 0 }, +{ "label": "16/92", "node": 3723, "naklon": null }, +{ "label": "16/93", "node": 3842, "naklon": 0 }, +{ "label": "16/94", "node": 3735, "naklon": null }, +{ "label": "16/95", "node": 3719, "naklon": 0 }, +{ "label": "16/96", "node": 3697, "naklon": 0 }, +{ "label": "16/97", "node": 3711, "naklon": 0 }, +{ "label": "16/98", "node": 4107, "naklon": null }, +{ "label": "16/99", "node": 4112, "naklon": 5 }, +{ "label": "16/100", "node": 4106, "naklon": 5 }, +{ "label": "16/101", "node": 4111, "naklon": 5 }, +{ "label": "16/102", "node": 4091, "naklon": null }, +{ "label": "16/103", "node": 4104, "naklon": 5 }, +{ "label": "16/104", "node": 4094, "naklon": null }, +{ "label": "16/105", "node": 4089, "naklon": 5 }, +{ "label": "16/106", "node": 4095, "naklon": null }, +{ "label": "16/107", "node": 4102, "naklon": 5 }, +{ "label": "16/108", "node": 4105, "naklon": null }, +{ "label": "16/109", "node": 3859, "naklon": null }, +{ "label": "16/110", "node": 4090, "naklon": 5 }, +{ "label": "16/111", "node": 4110, "naklon": null }, +{ "label": "16/112", "node": 4097, "naklon": 5 }, +{ "label": "16/113", "node": 4099, "naklon": null }, +{ "label": "16/114", "node": 4096, "naklon": null }, +{ "label": "16/115", "node": 4101, "naklon": 5 }, +{ "label": "16/116", "node": 4109, "naklon": null }, +{ "label": "16/117", "node": 4092, "naklon": 5 }, +{ "label": "16/118", "node": 3631, "naklon": null }, +{ "label": "16/119", "node": 3632, "naklon": 0 }, +{ "label": "16/120", "node": 3641, "naklon": null }, +{ "label": "16/121", "node": 3638, "naklon": 0 }, +{ "label": "16/122", "node": 3637, "naklon": null }, +{ "label": "16/123", "node": 4142, "naklon": null }, +{ "label": "16/124", "node": 4147, "naklon": 5 }, +{ "label": "16/125", "node": 4139, "naklon": 5 }, +{ "label": "20/30A", "node": 3172, "naklon": 2 }, +{ "label": "20/30B", "node": 3164, "naklon": 2 }, +{ "label": "20/1", "node": 3247, "naklon": 10 }, +{ "label": "20/2", "node": 3296, "naklon": 10 }, +{ "label": "20/3", "node": 3246, "naklon": 10 }, +{ "label": "20/4", "node": 3270, "naklon": 10 }, +{ "label": "20/5", "node": 3294, "naklon": 10 }, +{ "label": "20/6", "node": 3298, "naklon": 10 }, +{ "label": "20/7", "node": 3297, "naklon": 10 }, +{ "label": "20/8", "node": 3293, "naklon": 10 }, +{ "label": "20/9", "node": 3299, "naklon": 10 }, +{ "label": "20/10", "node": 3295, "naklon": 10 }, +{ "label": "20/11", "node": 3244, "naklon": 10 }, +{ "label": "20/12", "node": 3249, "naklon": 10 }, +{ "label": "20/13", "node": 3268, "naklon": 10 }, +{ "label": "20/14", "node": 3245, "naklon": 10 }, +{ "label": "20/15", "node": 3278, "naklon": 10 }, +{ "label": "20/16", "node": 3280, "naklon": 10 }, +{ "label": "20/17", "node": 3292, "naklon": 10 }, +{ "label": "20/18", "node": 3287, "naklon": 10 }, +{ "label": "20/19", "node": 3282, "naklon": 10 }, +{ "label": "20/20", "node": 3273, "naklon": 0 }, +{ "label": "20/21", "node": 3157, "naklon": 0 }, +{ "label": "20/22", "node": 3283, "naklon": 0 }, +{ "label": "20/23", "node": 3159, "naklon": 0 }, +{ "label": "20/24", "node": 3289, "naklon": 0 }, +{ "label": "20/25", "node": 3163, "naklon": 0 }, +{ "label": "20/26", "node": 3126, "naklon": 0 }, +{ "label": "20/27", "node": 3171, "naklon": 0 }, +{ "label": "20/28", "node": 3162, "naklon": 0 }, +{ "label": "20/29", "node": 3279, "naklon": 10 }, +{ "label": "20/31", "node": 3173, "naklon": 0 }, +{ "label": "20/32", "node": 3127, "naklon": 0 }, +{ "label": "20/33", "node": 3131, "naklon": 0 }, +{ "label": "20/34", "node": 3129, "naklon": 0 }, +{ "label": "20/35", "node": 3276, "naklon": 2 }, +{ "label": "20/36", "node": 3290, "naklon": 2 }, +{ "label": "20/37", "node": 3132, "naklon": 0 }, +{ "label": "20/38", "node": 3138, "naklon": 0 }, +{ "label": "20/39", "node": 3272, "naklon": 0 }, +{ "label": "20/40", "node": 3291, "naklon": 0 }, +{ "label": "20/41", "node": 3277, "naklon": 10 }, +{ "label": "20/42", "node": 3286, "naklon": 10 }, +{ "label": "20/43", "node": 3281, "naklon": 10 }, +{ "label": "20/44", "node": 3288, "naklon": 10 }, +{ "label": "20/45", "node": 3284, "naklon": 10 }, +{ "label": "20/46", "node": 3167, "naklon": 10 }, +{ "label": "20/47", "node": 3872, "naklon": 0 }, +{ "label": "20/48", "node": 3124, "naklon": 0 }, +{ "label": "20/49", "node": 3133, "naklon": 0 }, +{ "label": "20/50", "node": 3158, "naklon": 0 }, +{ "label": "20/51", "node": 3169, "naklon": 0 }, +{ "label": "20/52", "node": 3146, "naklon": 0 }, +{ "label": "20/53", "node": 3160, "naklon": 0 }, +{ "label": "20/54", "node": 3248, "naklon": 0 }, +{ "label": "20/55", "node": 3156, "naklon": 0 }, +{ "label": "20/56", "node": 3161, "naklon": 0 }, +{ "label": "20/57", "node": 3170, "naklon": 0 }, +{ "label": "20/58", "node": 3168, "naklon": 0 }, +{ "label": "20/59", "node": 3125, "naklon": 0 }, +{ "label": "20/60", "node": 3166, "naklon": 0 }, +{ "label": "20/61", "node": 3130, "naklon": 0 }, +{ "label": "20/62", "node": 3563, "naklon": 0 }, +{ "label": "20/63", "node": 3550, "naklon": null }, +{ "label": "20/67", "node": 3269, "naklon": 0 }, +{ "label": "21/1", "node": 2921, "naklon": 0 }, +{ "label": "21/2", "node": 2707, "naklon": 0 }, +{ "label": "21/3", "node": 2723, "naklon": 0 }, +{ "label": "21/4", "node": 2716, "naklon": 0 }, +{ "label": "21/5", "node": 2717, "naklon": 0 }, +{ "label": "21/6", "node": 2720, "naklon": 0 }, +{ "label": "21/7", "node": 2722, "naklon": 0 }, +{ "label": "21/8", "node": 2718, "naklon": 0 }, +{ "label": "21/9", "node": 2724, "naklon": 0 }, +{ "label": "21/10", "node": 2742, "naklon": 0 }, +{ "label": "21/11", "node": 2743, "naklon": 0 }, +{ "label": "21/12", "node": 2733, "naklon": 0 }, +{ "label": "21/14", "node": 2903, "naklon": 0 }, +{ "label": "21/15", "node": 2917, "naklon": 0 }, +{ "label": "21/16", "node": 2897, "naklon": 0 }, +{ "label": "21/17", "node": 2914, "naklon": 0 }, +{ "label": "21/18", "node": 2898, "naklon": 0 }, +{ "label": "21/19", "node": 2773, "naklon": 0 }, +{ "label": "21/20", "node": 2895, "naklon": 0 }, +{ "label": "21/21", "node": 2896, "naklon": 0 }, +{ "label": "21/22", "node": 2771, "naklon": 0 }, +{ "label": "21/23", "node": 2772, "naklon": 0 }, +{ "label": "21/24", "node": 2793, "naklon": 0 }, +{ "label": "21/25", "node": 2902, "naklon": 0 }, +{ "label": "21/26", "node": 2910, "naklon": 0 }, +{ "label": "21/27", "node": 2909, "naklon": 0 }, +{ "label": "21/28", "node": 2920, "naklon": 0 }, +{ "label": "21/29", "node": 2916, "naklon": 0 }, +{ "label": "21/30", "node": 2904, "naklon": 0 }, +{ "label": "21/31", "node": 2915, "naklon": 0 }, +{ "label": "21/32", "node": 2905, "naklon": 0 }, +{ "label": "21/33", "node": 2900, "naklon": 0 }, +{ "label": "21/34", "node": 2899, "naklon": 0 }, +{ "label": "21/36", "node": 2741, "naklon": 0 }, +{ "label": "21/37", "node": 2714, "naklon": 0 }, +{ "label": "21/38", "node": 2701, "naklon": 0 }, +{ "label": "21/39", "node": 2703, "naklon": 0 }, +{ "label": "21/40", "node": 2704, "naklon": 0 }, +{ "label": "21/41", "node": 2702, "naklon": 0 }, +{ "label": "21/42", "node": 2706, "naklon": 0 }, +{ "label": "21/43", "node": 2776, "naklon": 0 }, +{ "label": "21/44", "node": 2770, "naklon": 0 }, +{ "label": "21/45", "node": 2786, "naklon": 0 }, +{ "label": "21/46", "node": 2779, "naklon": 0 }, +{ "label": "21/47", "node": 2782, "naklon": 0 }, +{ "label": "21/48", "node": 2785, "naklon": 0 }, +{ "label": "21/49", "node": 2769, "naklon": 0 }, +{ "label": "21/50", "node": 3354, "naklon": 0 }, +{ "label": "21/51", "node": 2778, "naklon": 0 }, +{ "label": "21/52", "node": 2775, "naklon": 0 }, +{ "label": "21/53", "node": 2780, "naklon": 0 }, +{ "label": "21/54", "node": 2790, "naklon": 0 }, +{ "label": "21/55", "node": 2792, "naklon": 0 }, +{ "label": "21/56", "node": 2774, "naklon": 0 }, +{ "label": "22/1", "node": 2630, "naklon": 0 }, +{ "label": "22/2", "node": 2631, "naklon": 0 }, +{ "label": "22/3", "node": 2632, "naklon": 0 }, +{ "label": "22/4", "node": 2633, "naklon": 0 }, +{ "label": "22/5", "node": 2634, "naklon": 0 }, +{ "label": "22/6", "node": 2636, "naklon": 0 }, +{ "label": "22/7", "node": 4367, "naklon": 0 }, +{ "label": "22/8", "node": 2637, "naklon": 0 }, +{ "label": "22/9", "node": 2638, "naklon": 0 }, +{ "label": "22/10", "node": 2639, "naklon": 0 }, +{ "label": "22/11", "node": 2640, "naklon": 0 }, +{ "label": "22/12", "node": 2641, "naklon": 0 }, +{ "label": "22/13", "node": 2642, "naklon": 0 }, +{ "label": "22/14", "node": 2643, "naklon": 0 }, +{ "label": "22/15", "node": 2644, "naklon": 0 }, +{ "label": "22/16", "node": 2645, "naklon": 0 }, +{ "label": "22/17", "node": 2646, "naklon": 0 }, +{ "label": "22/18", "node": 2647, "naklon": 0 }, +{ "label": "22/19", "node": 2648, "naklon": 0 }, +{ "label": "22/20", "node": 2649, "naklon": 0 }, +{ "label": "22/21", "node": 2650, "naklon": 0 }, +{ "label": "22/22", "node": 2651, "naklon": 0 }, +{ "label": "22/23", "node": 4103, "naklon": 0 }, +{ "label": "22/24", "node": 2653, "naklon": 0 }, +{ "label": "22/25", "node": 2654, "naklon": 0 }, +{ "label": "22/26", "node": 2655, "naklon": 0 }, +{ "label": "22/27", "node": 2656, "naklon": 0 }, +{ "label": "22/28", "node": 2657, "naklon": 0 }, +{ "label": "22/29", "node": 2658, "naklon": 0 }, +{ "label": "22/30", "node": 2659, "naklon": 0 }, +{ "label": "22/31", "node": 2660, "naklon": 0 }, +{ "label": "22/32", "node": 2661, "naklon": 0 }, +{ "label": "22/32/1", "node": 3015, "naklon": 0 }, +{ "label": "22/33", "node": 2662, "naklon": 0 }, +{ "label": "22/34", "node": 2663, "naklon": 0 }, +{ "label": "22/35", "node": 2664, "naklon": 0 }, +{ "label": "22/36", "node": 2665, "naklon": 0 }, +{ "label": "22/37", "node": 2666, "naklon": 0 }, +{ "label": "22/38", "node": 2667, "naklon": 0 }, +{ "label": "22/39", "node": 2668, "naklon": 0 }, +{ "label": "22/40", "node": 2669, "naklon": null }, +{ "label": "22/41", "node": 2670, "naklon": null }, +{ "label": "22/42", "node": 2671, "naklon": null }, +{ "label": "23/9A", "node": 3087, "naklon": 10 }, +{ "label": "23/9B", "node": 3090, "naklon": 10 }, +{ "label": "23/1", "node": 3075, "naklon": 0 }, +{ "label": "23/2", "node": 3089, "naklon": 0 }, +{ "label": "23/3", "node": 3088, "naklon": 0 }, +{ "label": "23/4", "node": 3228, "naklon": 10 }, +{ "label": "23/5", "node": 2751, "naklon": 10 }, +{ "label": "23/6", "node": 3243, "naklon": 10 }, +{ "label": "23/7", "node": 4349, "naklon": 10 }, +{ "label": "23/8", "node": 3102, "naklon": 10 }, +{ "label": "23/10", "node": 3099, "naklon": 10 }, +{ "label": "23/11", "node": 3103, "naklon": 10 }, +{ "label": "23/12", "node": 3093, "naklon": 10 }, +{ "label": "23/13", "node": 3098, "naklon": 10 }, +{ "label": "23/14", "node": 3092, "naklon": 10 }, +{ "label": "23/15", "node": 3233, "naklon": 0 }, +{ "label": "23/16", "node": 3095, "naklon": 0 }, +{ "label": "23/17", "node": 4074, "naklon": 0 }, +{ "label": "23/18", "node": 2729, "naklon": 0 }, +{ "label": "23/19", "node": 3234, "naklon": 0 }, +{ "label": "23/20", "node": 3094, "naklon": 0 }, +{ "label": "23/21", "node": 2817, "naklon": 0 }, +{ "label": "23/22", "node": 3226, "naklon": 0 }, +{ "label": "23/23", "node": 3225, "naklon": 0 }, +{ "label": "23/24", "node": 3237, "naklon": 0 }, +{ "label": "23/25", "node": 4250, "naklon": 0 }, +{ "label": "23/26", "node": 3059, "naklon": 10 }, +{ "label": "23/27", "node": 3238, "naklon": 10 }, +{ "label": "23/28", "node": 3242, "naklon": 10 }, +{ "label": "23/29", "node": 3236, "naklon": 10 }, +{ "label": "23/30", "node": 3112, "naklon": 10 }, +{ "label": "23/31", "node": 3224, "naklon": 0 }, +{ "label": "23/32", "node": 4298, "naklon": 10 }, +{ "label": "23/33", "node": 4150, "naklon": 10 }, +{ "label": "23/34", "node": 3091, "naklon": 10 }, +{ "label": "25/1", "node": 3771, "naklon": 5 }, +{ "label": "25/2", "node": 3777, "naklon": 5 }, +{ "label": "25/3", "node": 3749, "naklon": 5 }, +{ "label": "25/4", "node": 3769, "naklon": 5 }, +{ "label": "25/5", "node": 3765, "naklon": 5 }, +{ "label": "25/6", "node": 3785, "naklon": 5 }, +{ "label": "25/7", "node": 3761, "naklon": 5 }, +{ "label": "25/8", "node": 3758, "naklon": 5 }, +{ "label": "25/9", "node": 3766, "naklon": 5 }, +{ "label": "25/10", "node": 3779, "naklon": 5 }, +{ "label": "25/11", "node": 3899, "naklon": 10 }, +{ "label": "25/12", "node": 3922, "naklon": 10 }, +{ "label": "25/13", "node": 3912, "naklon": 10 }, +{ "label": "25/14", "node": 3933, "naklon": 10 }, +{ "label": "25/15", "node": 3921, "naklon": 10 }, +{ "label": "25/16", "node": 4300, "naklon": 10 }, +{ "label": "25/17", "node": 3927, "naklon": 10 }, +{ "label": "25/18", "node": 3212, "naklon": 10 }, +{ "label": "25/19", "node": 3208, "naklon": 10 }, +{ "label": "25/20", "node": 3207, "naklon": 10 }, +{ "label": "25/21", "node": 4294, "naklon": 10 }, +{ "label": "25/22", "node": 3209, "naklon": 10 }, +{ "label": "25/23", "node": 3745, "naklon": 10 }, +{ "label": "25/24", "node": 3762, "naklon": 10 }, +{ "label": "25/25", "node": 3215, "naklon": 10 }, +{ "label": "25/26", "node": 3210, "naklon": 10 }, +{ "label": "25/27", "node": 3211, "naklon": 10 }, +{ "label": "25/28", "node": 3206, "naklon": 10 }, +{ "label": "25/29", "node": 3918, "naklon": 5 }, +{ "label": "25/30", "node": 3928, "naklon": 5 }, +{ "label": "25/31", "node": 3917, "naklon": 5 }, +{ "label": "25/32", "node": 4029, "naklon": 0 }, +{ "label": "25/33", "node": 4038, "naklon": 0 }, +{ "label": "25/34", "node": 4022, "naklon": 0 }, +{ "label": "25/35", "node": 3937, "naklon": 0 }, +{ "label": "25/36", "node": 3190, "naklon": 0 }, +{ "label": "25/37", "node": 3835, "naklon": 0 }, +{ "label": "25/38", "node": 3201, "naklon": 0 }, +{ "label": "25/39", "node": 3193, "naklon": 0 }, +{ "label": "25/40", "node": 3191, "naklon": 0 }, +{ "label": "25/41", "node": 3203, "naklon": 0 }, +{ "label": "25/42", "node": 4301, "naklon": 0 }, +{ "label": "25/43", "node": 3223, "naklon": 0 }, +{ "label": "25/44", "node": 3202, "naklon": 0 }, +{ "label": "25/45", "node": 3205, "naklon": 0 }, +{ "label": "25/46", "node": 3194, "naklon": 0 }, +{ "label": "25/47", "node": 3198, "naklon": 0 }, +{ "label": "25/48", "node": 3204, "naklon": 0 }, +{ "label": "25/49", "node": 3200, "naklon": 0 }, +{ "label": "25/50", "node": 3216, "naklon": 0 }, +{ "label": "25/51", "node": 3932, "naklon": 5 }, +{ "label": "25/52", "node": 3923, "naklon": 5 }, +{ "label": "25/53", "node": 3913, "naklon": 5 }, +{ "label": "25/54", "node": 3900, "naklon": 5 }, +{ "label": "25/55", "node": 4189, "naklon": 10 }, +{ "label": "25/56", "node": 4191, "naklon": 10 }, +{ "label": "25/57", "node": 3790, "naklon": 10 }, +{ "label": "25/58", "node": 4190, "naklon": 10 }, +{ "label": "25/59", "node": 4302, "naklon": 0 }, +{ "label": "25/60", "node": 4351, "naklon": 0 }, +{ "label": "25/61", "node": 4075, "naklon": 0 }, +{ "label": "25/62", "node": 4071, "naklon": 0 }, +{ "label": "25/63", "node": 3784, "naklon": 0 }, +{ "label": "25/64", "node": 4065, "naklon": 0 }, +{ "label": "25/65", "node": 4297, "naklon": 0 }, +{ "label": "25/66", "node": 4295, "naklon": 0 }, +{ "label": "25/67", "node": 4299, "naklon": 0 }, +{ "label": "25/68", "node": 3772, "naklon": 0 }, +{ "label": "25/69", "node": 3941, "naklon": 0 }, +{ "label": "25/70", "node": 3782, "naklon": 0 }, +{ "label": "25/71", "node": 4068, "naklon": 0 }, +{ "label": "25/72", "node": 4073, "naklon": 0 }, +{ "label": "25/73", "node": 3901, "naklon": 5 }, +{ "label": "25/74", "node": 4296, "naklon": 5 }, +{ "label": "25/75", "node": 3910, "naklon": 5 }, +{ "label": "25/76", "node": 4293, "naklon": 5 }, +{ "label": "25/77", "node": 3919, "naklon": 5 }, +{ "label": "25/78", "node": 3924, "naklon": 5 }, +{ "label": "25/79", "node": 3909, "naklon": 5 }, +{ "label": "25/80", "node": 3896, "naklon": 5 }, +{ "label": "25/81", "node": 3911, "naklon": 5 }, +{ "label": "25/82", "node": 2819, "naklon": 15 }, +{ "label": "25/83", "node": 3776, "naklon": 15 }, +{ "label": "25/84", "node": 3752, "naklon": 15 }, +{ "label": "25/85", "node": 4353, "naklon": 15 }, +{ "label": "25/86", "node": 3791, "naklon": 0 }, +{ "label": "25/87", "node": 3770, "naklon": 0 }, +{ "label": "25/88", "node": 3760, "naklon": 0 }, +{ "label": "25/89", "node": 3115, "naklon": 0 }, +{ "label": "25/90", "node": 3738, "naklon": 0 }, +{ "label": "25/91", "node": 3748, "naklon": 0 }, +{ "label": "25/92", "node": 3753, "naklon": 0 }, +{ "label": "25/93", "node": 3775, "naklon": 0 }, +{ "label": "25/94", "node": 3778, "naklon": 5 }, +{ "label": "25/95", "node": 4078, "naklon": 5 }, +{ "label": "25/96", "node": 4088, "naklon": 5 }, +{ "label": "25/97", "node": 3856, "naklon": 5 }, +{ "label": "25/98", "node": 4084, "naklon": 5 }, +{ "label": "25/99", "node": 4069, "naklon": 5 }, +{ "label": "25/100", "node": 4188, "naklon": 5 }, +{ "label": "25/101", "node": 4064, "naklon": 5 }, +{ "label": "25/102", "node": 3792, "naklon": 5 }, +{ "label": "25/103", "node": 3780, "naklon": 5 }, +{ "label": "25/104", "node": 4034, "naklon": 5 }, +{ "label": "25/105", "node": 4072, "naklon": 5 }, +{ "label": "25/106", "node": 3884, "naklon": 5 }, +{ "label": "25/107", "node": 3793, "naklon": 5 }, +{ "label": "25/108", "node": 3863, "naklon": 5 }, +{ "label": "25/109", "node": 3855, "naklon": 5 }, +{ "label": "33/1", "node": 3846, "naklon": 0 }, +{ "label": "33/2", "node": 3943, "naklon": 0 }, +{ "label": "33/3", "node": 3903, "naklon": 0 }, +{ "label": "33/4", "node": 3982, "naklon": 0 }, +{ "label": "33/5", "node": 3879, "naklon": 0 }, +{ "label": "33/6", "node": 3887, "naklon": 0 }, +{ "label": "33/7", "node": 3920, "naklon": 5 }, +{ "label": "33/8", "node": 3942, "naklon": 5 }, +{ "label": "33/9", "node": 3829, "naklon": null }, +{ "label": "34/79A", "node": 3452, "naklon": 6 }, +{ "label": "34/79B", "node": 3460, "naklon": 6 }, +{ "label": "34/90A", "node": 3443, "naklon": 6 }, +{ "label": "34/90B", "node": 3445, "naklon": 6 }, +{ "label": "34/90C", "node": 3457, "naklon": 6 }, +{ "label": "34/97A", "node": 3461, "naklon": 6 }, +{ "label": "34/97B", "node": 3463, "naklon": 6 }, +{ "label": "34/98A", "node": 3426, "naklon": 6 }, +{ "label": "34/98B", "node": 3444, "naklon": 6 }, +{ "label": "34/99A", "node": 3453, "naklon": 6 }, +{ "label": "34/99B", "node": 3455, "naklon": 6 }, +{ "label": "34/1", "node": 4009, "naklon": 0 }, +{ "label": "34/2", "node": 3602, "naklon": 0 }, +{ "label": "34/3", "node": 3441, "naklon": 0 }, +{ "label": "34/4", "node": 3464, "naklon": 0 }, +{ "label": "34/5", "node": 3883, "naklon": 0 }, +{ "label": "34/6", "node": 4098, "naklon": 0 }, +{ "label": "34/7", "node": 4003, "naklon": 0 }, +{ "label": "34/8", "node": 4004, "naklon": 0 }, +{ "label": "34/9", "node": 3888, "naklon": 0 }, +{ "label": "34/10", "node": 3997, "naklon": 0 }, +{ "label": "34/11", "node": 4006, "naklon": 0 }, +{ "label": "34/12", "node": 4000, "naklon": 0 }, +{ "label": "34/13", "node": 4011, "naklon": 0 }, +{ "label": "34/14", "node": 3999, "naklon": 0 }, +{ "label": "34/15", "node": 3981, "naklon": 0 }, +{ "label": "34/16", "node": 3988, "naklon": 0 }, +{ "label": "34/17", "node": 3986, "naklon": 0 }, +{ "label": "34/18", "node": 3998, "naklon": 0 }, +{ "label": "34/19", "node": 3983, "naklon": 0 }, +{ "label": "34/20", "node": 4005, "naklon": 0 }, +{ "label": "34/21", "node": 4001, "naklon": 0 }, +{ "label": "34/22", "node": 4008, "naklon": 0 }, +{ "label": "34/23", "node": 4002, "naklon": 0 }, +{ "label": "34/24", "node": 3996, "naklon": 0 }, +{ "label": "34/25", "node": 4007, "naklon": 0 }, +{ "label": "34/26", "node": 4113, "naklon": 15 }, +{ "label": "34/27", "node": 3595, "naklon": 5 }, +{ "label": "34/28", "node": 3599, "naklon": 5 }, +{ "label": "34/29", "node": 3601, "naklon": 5 }, +{ "label": "34/30", "node": 4205, "naklon": 0 }, +{ "label": "34/31", "node": 3987, "naklon": null }, +{ "label": "34/32", "node": 4214, "naklon": 0 }, +{ "label": "34/33", "node": 4226, "naklon": 0 }, +{ "label": "34/34", "node": 4209, "naklon": 0 }, +{ "label": "34/35", "node": 4201, "naklon": 0 }, +{ "label": "34/36", "node": 3440, "naklon": 0 }, +{ "label": "34/37", "node": 3465, "naklon": 0 }, +{ "label": "34/38", "node": 3446, "naklon": 0 }, +{ "label": "34/39", "node": 4039, "naklon": 5 }, +{ "label": "34/40", "node": 4057, "naklon": 5 }, +{ "label": "34/41", "node": 3985, "naklon": 0 }, +{ "label": "34/42", "node": 3882, "naklon": 0 }, +{ "label": "34/43", "node": 4040, "naklon": 5 }, +{ "label": "34/44", "node": 3231, "naklon": 0 }, +{ "label": "34/45", "node": 3227, "naklon": 0 }, +{ "label": "34/46", "node": 3431, "naklon": 0 }, +{ "label": "34/47", "node": 4013, "naklon": 0 }, +{ "label": "34/48", "node": 4045, "naklon": 0 }, +{ "label": "34/49", "node": 3949, "naklon": 0 }, +{ "label": "34/50", "node": 3953, "naklon": 0 }, +{ "label": "34/51", "node": 3952, "naklon": 0 }, +{ "label": "34/52", "node": 3995, "naklon": 0 }, +{ "label": "34/53", "node": 3992, "naklon": 0 }, +{ "label": "34/54", "node": 4198, "naklon": 0 }, +{ "label": "34/55", "node": 3935, "naklon": 0 }, +{ "label": "34/56", "node": 4050, "naklon": 0 }, +{ "label": "34/57", "node": 4049, "naklon": 0 }, +{ "label": "34/58", "node": 4054, "naklon": 0 }, +{ "label": "34/59", "node": 3663, "naklon": 6 }, +{ "label": "34/60", "node": 3661, "naklon": 6 }, +{ "label": "34/61", "node": 3664, "naklon": 6 }, +{ "label": "34/62", "node": 3660, "naklon": 6 }, +{ "label": "34/63", "node": 3662, "naklon": 6 }, +{ "label": "34/65", "node": 3665, "naklon": 6 }, +{ "label": "34/66", "node": 3667, "naklon": 6 }, +{ "label": "34/67", "node": 3675, "naklon": 6 }, +{ "label": "34/68", "node": 3666, "naklon": 6 }, +{ "label": "34/69", "node": 3652, "naklon": 6 }, +{ "label": "34/70", "node": 3458, "naklon": 6 }, +{ "label": "34/70/1", "node": 4425, "naklon": 6 }, +{ "label": "34/71", "node": 3459, "naklon": 6 }, +{ "label": "34/72", "node": 3435, "naklon": 6 }, +{ "label": "34/73", "node": 3448, "naklon": 6 }, +{ "label": "34/74", "node": 3451, "naklon": 6 }, +{ "label": "34/75", "node": 3442, "naklon": 6 }, +{ "label": "34/76", "node": 3449, "naklon": 6 }, +{ "label": "34/77", "node": 3450, "naklon": 6 }, +{ "label": "34/78", "node": 3433, "naklon": 6 }, +{ "label": "34/80", "node": 3432, "naklon": 12 }, +{ "label": "34/81", "node": 3470, "naklon": 12 }, +{ "label": "34/82", "node": 3438, "naklon": 12 }, +{ "label": "34/83", "node": 3439, "naklon": 12 }, +{ "label": "34/84", "node": 4028, "naklon": 5 }, +{ "label": "34/85", "node": 3596, "naklon": 5 }, +{ "label": "34/86", "node": 4021, "naklon": 5 }, +{ "label": "34/87", "node": 3437, "naklon": 12 }, +{ "label": "34/88", "node": 3428, "naklon": 12 }, +{ "label": "34/89", "node": 3430, "naklon": 12 }, +{ "label": "34/91", "node": 3454, "naklon": 6 }, +{ "label": "34/92", "node": 3492, "naklon": 6 }, +{ "label": "34/93", "node": 3462, "naklon": 6 }, +{ "label": "34/94", "node": 3427, "naklon": 6 }, +{ "label": "34/95", "node": 3434, "naklon": 6 }, +{ "label": "34/96", "node": 3456, "naklon": 6 }, +{ "label": "34/98/1", "node": 4307, "naklon": 6 }, +{ "label": "35/1", "node": 3968, "naklon": 0 }, +{ "label": "35/2", "node": 3969, "naklon": 0 }, +{ "label": "35/3", "node": 3947, "naklon": 0 }, +{ "label": "35/4", "node": 3979, "naklon": 0 }, +{ "label": "35/5", "node": 3959, "naklon": 0 }, +{ "label": "35/6", "node": 3948, "naklon": 0 }, +{ "label": "35/7", "node": 3961, "naklon": 0 }, +{ "label": "35/8", "node": 3956, "naklon": 0 }, +{ "label": "35/9", "node": 3604, "naklon": 0 }, +{ "label": "35/10", "node": 3944, "naklon": 0 }, +{ "label": "35/11", "node": 3960, "naklon": 0 }, +{ "label": "35/12", "node": 3958, "naklon": 0 }, +{ "label": "35/13", "node": 4036, "naklon": 5 }, +{ "label": "35/18", "node": 3893, "naklon": 5 }, +{ "label": "35/19", "node": 4108, "naklon": 5 }, +{ "label": "35/20", "node": 4017, "naklon": 5 }, +{ "label": "35/21", "node": 3963, "naklon": 0 }, +{ "label": "35/22", "node": 3658, "naklon": 0 }, +{ "label": "35/23", "node": 3975, "naklon": 0 }, +{ "label": "35/24", "node": 3980, "naklon": 0 }, +{ "label": "35/25", "node": 4012, "naklon": 0 }, +{ "label": "35/26", "node": 3655, "naklon": 0 }, +{ "label": "35/27", "node": 3962, "naklon": 0 }, +{ "label": "35/28", "node": 3945, "naklon": 0 }, +{ "label": "35/29", "node": 3569, "naklon": 0 }, +{ "label": "35/30", "node": 3429, "naklon": 0 }, +{ "label": "35/31", "node": 3657, "naklon": 0 }, +{ "label": "35/32", "node": 3646, "naklon": 0 }, +{ "label": "35/33", "node": 3622, "naklon": 0 }, +{ "label": "35/34", "node": 3612, "naklon": 0 }, +{ "label": "35/35", "node": 3955, "naklon": 0 }, +{ "label": "35/37", "node": 3878, "naklon": 0 }, +{ "label": "35/38", "node": 3965, "naklon": 0 }, +{ "label": "35/39", "node": 3970, "naklon": 0 }, +{ "label": "35/40", "node": 3611, "naklon": 0 }, +{ "label": "35/41", "node": 2635, "naklon": 0 }, +{ "label": "35/42", "node": 3978, "naklon": 0 }, +{ "label": "35/43", "node": 4213, "naklon": 0 }, +{ "label": "35/44", "node": 3984, "naklon": 0 }, +{ "label": "35/45", "node": 4218, "naklon": 0 }, +{ "label": "35/46", "node": 3973, "naklon": 0 }, +{ "label": "35/47", "node": 3974, "naklon": 0 }, +{ "label": "35/48", "node": 3759, "naklon": 0 }, +{ "label": "35/49", "node": 3844, "naklon": 0 }, +{ "label": "35/50", "node": 3804, "naklon": 0 }, +{ "label": "35/51", "node": 3831, "naklon": 0 }, +{ "label": "35/52", "node": 3643, "naklon": 0 }, +{ "label": "35/53", "node": 3966, "naklon": 0 }, +{ "label": "35/54", "node": 3971, "naklon": 0 }, +{ "label": "35/55", "node": 3650, "naklon": 6 }, +{ "label": "35/56", "node": 3651, "naklon": 6 }, +{ "label": "35/57", "node": 3669, "naklon": 6 }, +{ "label": "35/58", "node": 3648, "naklon": 6 }, +{ "label": "35/59", "node": 3645, "naklon": 6 }, +{ "label": "35/60", "node": 3659, "naklon": 6 }, +{ "label": "35/61", "node": 3647, "naklon": 6 }, +{ "label": "35/62", "node": 3644, "naklon": 6 }, +{ "label": "35/63", "node": 3671, "naklon": 6 }, +{ "label": "35/64", "node": 3682, "naklon": 6 }, +{ "label": "35/65", "node": 3672, "naklon": 6 }, +{ "label": "35/66", "node": 3683, "naklon": 6 }, +{ "label": "35/67", "node": 3673, "naklon": 6 }, +{ "label": "35/68", "node": 3674, "naklon": 6 }, +{ "label": "35/69", "node": 3679, "naklon": 6 }, +{ "label": "35/70", "node": 3649, "naklon": 6 }, +{ "label": "35/71", "node": 3687, "naklon": 6 }, +{ "label": "35/72", "node": 3677, "naklon": 6 }, +{ "label": "35/73", "node": 3690, "naklon": 6 }, +{ "label": "35/74", "node": 3691, "naklon": 6 }, +{ "label": "35/75", "node": 3676, "naklon": 6 }, +{ "label": "35/76", "node": 3680, "naklon": 6 }, +{ "label": "35/77", "node": 3668, "naklon": 6 }, +{ "label": "35/78", "node": 3681, "naklon": 6 }, +{ "label": "35/79", "node": 3670, "naklon": 6 }, +{ "label": "35/80", "node": 3689, "naklon": 6 }, +{ "label": "35/81", "node": 3678, "naklon": 6 }, +{ "label": "35/82", "node": 3693, "naklon": 6 }, +{ "label": "35/83", "node": 3654, "naklon": null }, +{ "label": "36/1", "node": 4086, "naklon": 0 }, +{ "label": "36/2", "node": 4085, "naklon": 0 }, +{ "label": "36/3", "node": 4083, "naklon": 0 }, +{ "label": "36/4", "node": 4087, "naklon": 0 }, +{ "label": "36/5", "node": 4077, "naklon": 0 }, +{ "label": "36/6", "node": 4082, "naklon": 0 }, +{ "label": "36/7", "node": 4186, "naklon": 0 }, +{ "label": "36/8", "node": 4206, "naklon": 0 }, +{ "label": "36/9", "node": 4080, "naklon": 0 }, +{ "label": "36/10", "node": 4081, "naklon": 0 }, +{ "label": "36/11", "node": 4210, "naklon": 0 }, +{ "label": "36/12", "node": 4079, "naklon": 0 }, +{ "label": "36/13", "node": 4076, "naklon": 0 }, +{ "label": "36/14", "node": 3852, "naklon": 0 }, +{ "label": "36/15", "node": 2813, "naklon": 0 }, +{ "label": "36/16", "node": 4219, "naklon": 0 }, +{ "label": "37/1A", "node": 3104, "naklon": 15 }, +{ "label": "37/1B", "node": 3121, "naklon": 15 }, +{ "label": "37/2", "node": 3113, "naklon": 10 }, +{ "label": "37/3", "node": 3118, "naklon": 10 }, +{ "label": "37/4", "node": 3111, "naklon": 10 }, +{ "label": "37/5", "node": 4020, "naklon": 10 }, +{ "label": "37/6", "node": 3119, "naklon": 10 }, +{ "label": "37/7", "node": 3110, "naklon": 10 }, +{ "label": "37/8", "node": 3108, "naklon": 10 }, +{ "label": "37/12", "node": 3107, "naklon": 0 }, +{ "label": "37/13", "node": 3199, "naklon": 0 }, +{ "label": "37/14", "node": 3120, "naklon": 0 }, +{ "label": "37/15", "node": 3122, "naklon": 0 }, +{ "label": "37/16", "node": 3908, "naklon": 0 }, +{ "label": "37/17", "node": 3114, "naklon": 0 }, +{ "label": "37/18", "node": 3105, "naklon": 0 }, +{ "label": "37/19", "node": 3116, "naklon": 0 }, +{ "label": "37/20", "node": 3106, "naklon": 0 }, +{ "label": "37/21", "node": 2887, "naklon": 5 }, +{ "label": "37/22", "node": 2888, "naklon": 5 }, +{ "label": "37/23", "node": 2877, "naklon": 5 }, +{ "label": "37/24", "node": 2891, "naklon": 5 }, +{ "label": "37/25", "node": 2886, "naklon": 5 }, +{ "label": "37/26", "node": 2892, "naklon": 5 }, +{ "label": "37/27", "node": 2882, "naklon": 5 }, +{ "label": "37/28", "node": 2883, "naklon": 5 }, +{ "label": "37/29", "node": 2876, "naklon": 5 }, +{ "label": "37/30", "node": 3109, "naklon": 5 }, +{ "label": "37/31", "node": 4152, "naklon": 5 }, +{ "label": "37/32", "node": 3117, "naklon": 5 }, +{ "label": "37/33", "node": 2870, "naklon": 5 }, +{ "label": "37/34", "node": 2867, "naklon": 0 }, +{ "label": "37/35", "node": 2865, "naklon": 0 }, +{ "label": "37/36", "node": 3096, "naklon": 0 }, +{ "label": "37/37", "node": 2871, "naklon": 0 }, +{ "label": "37/38", "node": 2884, "naklon": 0 }, +{ "label": "37/39", "node": 2855, "naklon": 0 }, +{ "label": "37/40", "node": 2878, "naklon": 0 }, +{ "label": "37/41", "node": 2889, "naklon": 0 }, +{ "label": "37/42", "node": 2879, "naklon": 0 }, +{ "label": "37/43", "node": 2850, "naklon": 0 }, +{ "label": "37/44", "node": 2894, "naklon": 0 }, +{ "label": "37/45", "node": 2880, "naklon": 0 }, +{ "label": "37/46", "node": 2893, "naklon": 0 }, +{ "label": "37/47", "node": 2890, "naklon": 0 }, +{ "label": "37/48", "node": 4355, "naklon": 0 }, +{ "label": "37/49", "node": 2885, "naklon": 0 }, +{ "label": "37/50", "node": 2875, "naklon": 0 }, +{ "label": "38/30A", "node": 3486, "naklon": 5 }, +{ "label": "38/30B", "node": 3714, "naklon": 0 }, +{ "label": "38/32A", "node": 3483, "naklon": 5 }, +{ "label": "38/32B", "node": 3496, "naklon": 0 }, +{ "label": "38/35A", "node": 3487, "naklon": 5 }, +{ "label": "38/35B", "node": 3498, "naklon": 5 }, +{ "label": "38/38A", "node": 3578, "naklon": 5 }, +{ "label": "38/38B", "node": 3508, "naklon": 5 }, +{ "label": "38/59A", "node": 3787, "naklon": 5 }, +{ "label": "38/59B", "node": 3491, "naklon": 5 }, +{ "label": "38/1", "node": 3568, "naklon": null }, +{ "label": "38/2", "node": 3502, "naklon": 0 }, +{ "label": "38/3", "node": 3836, "naklon": 0 }, +{ "label": "38/4", "node": 3588, "naklon": 0 }, +{ "label": "38/5", "node": 3493, "naklon": 0 }, +{ "label": "38/6", "node": 3580, "naklon": 0 }, +{ "label": "38/7", "node": 3572, "naklon": 0 }, +{ "label": "38/8", "node": 3506, "naklon": 0 }, +{ "label": "38/9", "node": 3503, "naklon": 0 }, +{ "label": "38/10", "node": 3579, "naklon": 0 }, +{ "label": "38/11", "node": 3586, "naklon": 0 }, +{ "label": "38/12", "node": 3495, "naklon": 5 }, +{ "label": "38/13", "node": 3492, "naklon": 5 }, +{ "label": "38/14", "node": 3532, "naklon": 5 }, +{ "label": "38/15", "node": 3574, "naklon": 5 }, +{ "label": "38/16", "node": 4140, "naklon": 5 }, +{ "label": "38/17", "node": 3795, "naklon": 5 }, +{ "label": "38/18", "node": 3788, "naklon": 5 }, +{ "label": "38/19", "node": 3796, "naklon": 5 }, +{ "label": "38/20", "node": 3797, "naklon": 5 }, +{ "label": "38/21", "node": 3798, "naklon": 5 }, +{ "label": "38/22", "node": 3786, "naklon": 5 }, +{ "label": "38/23", "node": 4067, "naklon": 5 }, +{ "label": "38/24", "node": 3773, "naklon": 5 }, +{ "label": "38/25", "node": 3774, "naklon": 5 }, +{ "label": "38/26", "node": 3789, "naklon": 5 }, +{ "label": "38/27", "node": 3520, "naklon": null }, +{ "label": "38/29", "node": 3577, "naklon": 5 }, +{ "label": "38/31", "node": 3530, "naklon": null }, +{ "label": "38/33", "node": 3488, "naklon": 5 }, +{ "label": "38/34", "node": 3505, "naklon": 5 }, +{ "label": "38/36", "node": 3497, "naklon": 5 }, +{ "label": "38/37", "node": 3490, "naklon": 5 }, +{ "label": "38/39", "node": 3585, "naklon": 5 }, +{ "label": "38/40", "node": 3582, "naklon": 5 }, +{ "label": "38/41", "node": 3507, "naklon": 5 }, +{ "label": "38/42", "node": 3484, "naklon": 5 }, +{ "label": "38/43", "node": 3501, "naklon": 5 }, +{ "label": "38/44", "node": 3581, "naklon": 5 }, +{ "label": "38/45", "node": 4192, "naklon": 5 }, +{ "label": "38/46", "node": 3576, "naklon": 5 }, +{ "label": "38/47", "node": 3489, "naklon": 5 }, +{ "label": "38/48", "node": 3573, "naklon": 5 }, +{ "label": "38/49", "node": 3504, "naklon": 5 }, +{ "label": "38/50", "node": 3794, "naklon": 5 }, +{ "label": "38/51", "node": 3485, "naklon": 5 }, +{ "label": "38/52", "node": 3482, "naklon": 5 }, +{ "label": "38/53", "node": 3575, "naklon": 5 }, +{ "label": "38/54", "node": 3499, "naklon": 5 }, +{ "label": "38/55", "node": 3494, "naklon": 5 }, +{ "label": "38/56", "node": 3583, "naklon": 5 }, +{ "label": "38/57", "node": 3570, "naklon": 5 }, +{ "label": "38/58", "node": 3500, "naklon": 0 }, +{ "label": "38/63", "node": 3510, "naklon": null }, +{ "label": "38/64", "node": 3512, "naklon": null }, +{ "label": "38/67", "node": 3535, "naklon": null }, +{ "label": "38/68", "node": 3531, "naklon": null }, +{ "label": "38/69", "node": 3537, "naklon": null }, +{ "label": "39/1", "node": 3522, "naklon": 10 }, +{ "label": "39/2", "node": 4018, "naklon": 10 }, +{ "label": "39/3", "node": 4019, "naklon": 10 }, +{ "label": "39/4", "node": 4154, "naklon": 5 }, +{ "label": "39/5", "node": 3907, "naklon": 5 }, +{ "label": "39/6", "node": 4148, "naklon": 0 }, +{ "label": "39/7", "node": 4153, "naklon": 0 }, +{ "label": "39/8", "node": 3938, "naklon": 0 }, +{ "label": "39/9", "node": 3802, "naklon": 0 }, +{ "label": "39/10", "node": 4015, "naklon": 0 }, +{ "label": "39/11", "node": 3929, "naklon": 0 }, +{ "label": "39/12", "node": 3946, "naklon": 0 }, +{ "label": "39/13", "node": 4014, "naklon": 0 }, +{ "label": "39/14", "node": 4155, "naklon": 0 }, +{ "label": "39/15", "node": 4149, "naklon": 0 }, +{ "label": "39/16", "node": 3642, "naklon": 0 }, +{ "label": "39/17", "node": 3636, "naklon": 5 }, +{ "label": "39/18", "node": 3991, "naklon": 0 }, +{ "label": "39/19", "node": 3994, "naklon": 0 }, +{ "label": "39/20", "node": 3990, "naklon": 0 }, +{ "label": "39/21", "node": 3967, "naklon": 0 }, +{ "label": "39/22", "node": 3977, "naklon": 0 }, +{ "label": "39/23", "node": 3757, "naklon": 15 }, +{ "label": "39/24", "node": 3633, "naklon": 15 }, +{ "label": "39/25", "node": 3744, "naklon": 15 }, +{ "label": "39/26", "node": 4023, "naklon": 5 }, +{ "label": "39/27", "node": 3720, "naklon": 5 }, +{ "label": "39/28", "node": 3734, "naklon": 5 }, +{ "label": "39/29", "node": 3741, "naklon": 5 }, +{ "label": "39/30", "node": 3721, "naklon": 5 }, +{ "label": "39/31", "node": 3845, "naklon": 0 }, +{ "label": "39/32", "node": 3840, "naklon": 0 }, +{ "label": "39/33", "node": 3837, "naklon": null }, +{ "label": "39/34", "node": 3839, "naklon": 0 }, +{ "label": "41/1", "node": 3542, "naklon": null }, +{ "label": "41/2", "node": 3566, "naklon": null }, +{ "label": "41/3", "node": 3548, "naklon": null }, +{ "label": "41/4", "node": 3515, "naklon": null }, +{ "label": "41/5", "node": 3559, "naklon": null }, +{ "label": "41/6", "node": 3509, "naklon": null }, +{ "label": "41/7", "node": 3524, "naklon": null }, +{ "label": "41/8", "node": 3518, "naklon": null }, +{ "label": "41/9", "node": 3182, "naklon": null }, +{ "label": "41/10", "node": 3187, "naklon": null }, +{ "label": "41/11", "node": 3195, "naklon": 0 }, +{ "label": "41/12", "node": 3857, "naklon": 0 }, +{ "label": "41/13", "node": 3183, "naklon": 0 }, +{ "label": "41/14", "node": 3177, "naklon": 0 }, +{ "label": "41/15", "node": 3189, "naklon": 0 }, +{ "label": "41/16", "node": 3186, "naklon": 0 }, +{ "label": "42/1", "node": 3178, "naklon": 0 }, +{ "label": "42/2", "node": 3219, "naklon": 0 }, +{ "label": "42/3", "node": 3475, "naklon": 0 }, +{ "label": "42/4", "node": 3175, "naklon": 0 }, +{ "label": "42/5", "node": 3222, "naklon": 0 }, +{ "label": "42/6", "node": 3221, "naklon": 0 }, +{ "label": "42/7", "node": 3181, "naklon": 0 }, +{ "label": "42/8", "node": 3180, "naklon": 0 }, +{ "label": "42/9", "node": 3218, "naklon": 0 }, +{ "label": "42/10", "node": 3176, "naklon": 0 }, +{ "label": "42/11", "node": 3174, "naklon": 0 }, +{ "label": "42/12", "node": 3220, "naklon": 0 }, +{ "label": "42/13", "node": 3533, "naklon": null }, +{ "label": "42/14", "node": 3543, "naklon": null }, +{ "label": "42/15", "node": 3554, "naklon": null }, +{ "label": "42/16", "node": 3549, "naklon": null }, +{ "label": "43/1", "node": 2857, "naklon": 5 }, +{ "label": "43/2", "node": 2752, "naklon": 5 }, +{ "label": "43/3", "node": 2753, "naklon": 5 }, +{ "label": "43/4", "node": 3024, "naklon": 5 }, +{ "label": "43/5", "node": 2754, "naklon": 5 }, +{ "label": "43/6", "node": 4423, "naklon": 5 }, +{ "label": "43/7", "node": 4368, "naklon": 5 }, +{ "label": "43/8", "node": 2978, "naklon": 5 }, +{ "label": "43/9", "node": 2868, "naklon": 5 }, +{ "label": "43/10", "node": 4377, "naklon": 5 }, +{ "label": "43/11", "node": 2757, "naklon": 5 }, +{ "label": "43/12", "node": 2970, "naklon": 5 }, +{ "label": "43/13", "node": 2758, "naklon": 5 }, +{ "label": "43/14", "node": 4378, "naklon": 5 }, +{ "label": "43/15", "node": 2759, "naklon": 5 }, +{ "label": "43/16", "node": 4342, "naklon": 5 }, +{ "label": "43/17", "node": 3026, "naklon": null }, +{ "label": "43/18", "node": 2986, "naklon": null }, +{ "label": "43/19", "node": 4343, "naklon": null }, +{ "label": "43/20", "node": 2760, "naklon": null }, +{ "label": "43/21", "node": 4379, "naklon": null }, +{ "label": "43/22", "node": 2971, "naklon": null }, +{ "label": "43/23", "node": 2761, "naklon": null }, +{ "label": "43/24", "node": 2762, "naklon": null }, +{ "label": "43/25", "node": 4339, "naklon": null }, +{ "label": "43/26", "node": 4380, "naklon": null }, +{ "label": "43/27", "node": 2975, "naklon": null }, +{ "label": "43/28", "node": 3003, "naklon": null }, +{ "label": "43/29", "node": 4338, "naklon": null }, +{ "label": "43/30", "node": 3002, "naklon": null }, +{ "label": "43/31", "node": 4345, "naklon": null }, +{ "label": "43/32", "node": 2979, "naklon": null }, +{ "label": "43/33", "node": 2989, "naklon": null }, +{ "label": "43/34", "node": 2996, "naklon": null }, +{ "label": "43/35", "node": 2972, "naklon": null }, +{ "label": "43/36", "node": 2988, "naklon": null }, +{ "label": "43/37", "node": 4344, "naklon": null }, +{ "label": "43/38", "node": 3022, "naklon": null }, +{ "label": "43/39", "node": 4341, "naklon": null }, +{ "label": "43/40", "node": 2983, "naklon": null }, +{ "label": "43/41", "node": 2995, "naklon": null }, +{ "label": "43/42", "node": 2763, "naklon": null }, +{ "label": "43/43", "node": 2764, "naklon": null }, +{ "label": "43/44", "node": 2765, "naklon": null }, +{ "label": "43/45", "node": 2766, "naklon": null }, +{ "label": "43/46", "node": 2767, "naklon": null }, +{ "label": "43/47", "node": 2768, "naklon": null }, +{ "label": "43/48", "node": 3018, "naklon": null }, +{ "label": "43/49", "node": 2982, "naklon": null }, +{ "label": "43/50", "node": 3019, "naklon": 0 }, +{ "label": "43/51", "node": 3013, "naklon": null }, +{ "label": "43/52", "node": 3007, "naklon": null }, +{ "label": "43/53", "node": 2980, "naklon": null }, +{ "label": "43/54", "node": 3011, "naklon": null }, +{ "label": "43/55", "node": 2672, "naklon": null }, +{ "label": "43/56", "node": 2673, "naklon": null }, +{ "label": "43/57", "node": 2674, "naklon": null }, +{ "label": "43/58", "node": 2675, "naklon": null }, +{ "label": "43/59", "node": 2676, "naklon": null }, +{ "label": "43/60", "node": 2677, "naklon": null }, +{ "label": "43/61", "node": 2678, "naklon": null }, +{ "label": "43/62", "node": 2679, "naklon": null }, +{ "label": "43/63", "node": 2680, "naklon": null }, +{ "label": "43/64", "node": 2840, "naklon": null }, +{ "label": "43/65", "node": 2682, "naklon": null }, +{ "label": "43/66", "node": 2683, "naklon": null }, +{ "label": "43/67", "node": 2684, "naklon": 0 }, +{ "label": "43/68", "node": 2685, "naklon": null }, +{ "label": "43/69", "node": 2686, "naklon": null }, +{ "label": "43/70", "node": 2687, "naklon": null }, +{ "label": "43/71", "node": 2688, "naklon": null }, +{ "label": "43/72", "node": 2689, "naklon": null }, +{ "label": "43/73", "node": 2690, "naklon": null }, +{ "label": "43/74", "node": 2691, "naklon": null }, +{ "label": "43/75", "node": 2692, "naklon": null }, +{ "label": "43/76", "node": 2693, "naklon": 0 }, +{ "label": "43/77", "node": 2694, "naklon": null }, +{ "label": "43/78", "node": 2695, "naklon": null }, +{ "label": "43/79", "node": 2696, "naklon": 0 }, +{ "label": "43/80", "node": 2697, "naklon": null }, +{ "label": "43/81", "node": 2698, "naklon": 0 }, +{ "label": "43/82", "node": 2699, "naklon": null }, +{ "label": "43/83", "node": 2700, "naklon": 0 }, +{ "label": "43/84", "node": 2744, "naklon": null }, +{ "label": "43/85", "node": 2745, "naklon": 0 }, +{ "label": "43/86", "node": 2746, "naklon": null }, +{ "label": "43/87", "node": 2747, "naklon": 0 }, +{ "label": "43/88", "node": 2748, "naklon": null }, +{ "label": "43/89", "node": 2749, "naklon": 0 }, +{ "label": "43/90", "node": 2841, "naklon": null }, +{ "label": "45/1", "node": 4237, "naklon": 5 }, +{ "label": "45/2", "node": 4226, "naklon": 5 }, +{ "label": "45/3", "node": 4242, "naklon": 5 }, +{ "label": "45/4", "node": 4179, "naklon": 5 }, +{ "label": "45/5", "node": 4247, "naklon": 5 }, +{ "label": "45/6", "node": 4245, "naklon": 5 }, +{ "label": "45/7", "node": 3872, "naklon": 5 }, +{ "label": "45/8", "node": 4175, "naklon": 5 }, +{ "label": "45/9", "node": 4236, "naklon": 5 }, +{ "label": "45/10", "node": 4170, "naklon": 5 }, +{ "label": "45/11", "node": 4238, "naklon": 5 }, +{ "label": "45/12", "node": 4246, "naklon": 5 }, +{ "label": "45/13", "node": 4166, "naklon": 5 }, +{ "label": "45/14", "node": 4227, "naklon": 5 }, +{ "label": "45/15", "node": 4171, "naklon": 5 }, +{ "label": "45/16", "node": 4180, "naklon": 5 }, +{ "label": "45/17", "node": 4244, "naklon": 5 }, +{ "label": "45/18", "node": 4199, "naklon": 5 }, +{ "label": "45/19", "node": 4239, "naklon": 5 }, +{ "label": "45/20", "node": 4207, "naklon": 5 }, +{ "label": "45/21", "node": 4223, "naklon": 5 }, +{ "label": "45/22", "node": 4230, "naklon": 5 }, +{ "label": "45/23", "node": 4233, "naklon": 5 }, +{ "label": "45/24", "node": 4222, "naklon": 5 }, +{ "label": "45/25", "node": 4217, "naklon": 5 }, +{ "label": "45/26", "node": 4243, "naklon": 5 }, +{ "label": "45/27", "node": 4200, "naklon": 5 }, +{ "label": "45/28", "node": 4228, "naklon": 5 }, +{ "label": "45/29", "node": 4211, "naklon": 5 }, +{ "label": "45/30", "node": 4234, "naklon": 5 }, +{ "label": "45/31", "node": 4235, "naklon": 5 }, +{ "label": "45/32", "node": 4203, "naklon": 5 }, +{ "label": "45/33", "node": 4240, "naklon": 5 }, +{ "label": "45/34", "node": 4224, "naklon": 5 }, +{ "label": "45/35", "node": 4232, "naklon": 5 }, +{ "label": "45/36", "node": 4231, "naklon": 5 }, +{ "label": "45/37", "node": 4161, "naklon": 5 }, +{ "label": "45/38", "node": 4225, "naklon": 5 }, +{ "label": "45/39", "node": 4241, "naklon": 5 }, +{ "label": "45/40", "node": 4229, "naklon": 5 }, +{ "label": "45/41", "node": 4221, "naklon": 5 }, +{ "label": "45/42", "node": 4212, "naklon": 5 }, +{ "label": "45/43", "node": 4216, "naklon": 5 }, +{ "label": "45/44", "node": 3864, "naklon": null }, +{ "label": "46/1", "node": 3806, "naklon": 5 }, +{ "label": "46/2", "node": 3813, "naklon": 5 }, +{ "label": "46/3", "node": 3815, "naklon": 5 }, +{ "label": "46/4", "node": 3807, "naklon": 5 }, +{ "label": "46/5", "node": 3895, "naklon": 5 }, +{ "label": "46/6", "node": 3809, "naklon": 5 }, +{ "label": "46/7", "node": 3820, "naklon": 5 }, +{ "label": "46/8", "node": 3805, "naklon": 5 }, +{ "label": "46/9", "node": 3894, "naklon": 0 }, +{ "label": "46/10", "node": 4055, "naklon": 0 }, +{ "label": "46/11", "node": 3812, "naklon": 5 }, +{ "label": "46/12", "node": 3822, "naklon": 5 }, +{ "label": "46/13", "node": 3821, "naklon": 5 }, +{ "label": "46/14", "node": 3808, "naklon": 5 }, +{ "label": "46/15", "node": 3799, "naklon": 5 }, +{ "label": "46/16", "node": 3816, "naklon": 5 }, +{ "label": "46/17", "node": 3751, "naklon": 5 }, +{ "label": "46/18", "node": 3814, "naklon": 5 }, +{ "label": "46/19", "node": 4044, "naklon": 0 }, +{ "label": "46/20", "node": 3931, "naklon": 0 }, +{ "label": "46/21", "node": 3902, "naklon": 5 }, +{ "label": "46/22", "node": 3916, "naklon": 5 }, +{ "label": "46/23", "node": 3892, "naklon": 5 }, +{ "label": "46/24", "node": 3914, "naklon": 5 }, +{ "label": "46/25", "node": 3898, "naklon": 5 }, +{ "label": "46/26", "node": 3897, "naklon": 5 }, +{ "label": "46/27", "node": 3885, "naklon": 5 }, +{ "label": "46/28", "node": 3906, "naklon": 5 }, +{ "label": "46/29", "node": 3930, "naklon": 0 }, +{ "label": "46/30", "node": 3936, "naklon": 0 }, +{ "label": "46/31", "node": 3860, "naklon": 5 }, +{ "label": "46/32", "node": 3841, "naklon": 5 }, +{ "label": "46/33", "node": 3873, "naklon": 5 }, +{ "label": "46/34", "node": 3854, "naklon": 5 }, +{ "label": "46/35", "node": 3939, "naklon": 5 }, +{ "label": "46/36", "node": 3858, "naklon": 5 }, +{ "label": "46/37", "node": 3940, "naklon": 5 }, +{ "label": "46/38", "node": 4035, "naklon": 5 }, +{ "label": "47/1", "node": 3373, "naklon": 0 }, +{ "label": "47/2", "node": 3374, "naklon": 0 }, +{ "label": "47/3", "node": 3384, "naklon": 0 }, +{ "label": "47/4", "node": 3385, "naklon": 0 }, +{ "label": "48/1", "node": 4051, "naklon": 5 }, +{ "label": "48/2", "node": 4041, "naklon": 5 }, +{ "label": "48/3", "node": 4056, "naklon": 5 }, +{ "label": "48/4", "node": 3875, "naklon": 5 }, +{ "label": "48/5", "node": 4061, "naklon": 5 }, +{ "label": "48/6", "node": 4047, "naklon": 5 }, +{ "label": "48/7", "node": 4060, "naklon": 5 }, +{ "label": "48/8", "node": 4059, "naklon": 5 }, +{ "label": "48/9", "node": 4058, "naklon": 5 }, +{ "label": "48/10", "node": 3635, "naklon": 5 }, +{ "label": "48/11", "node": 3640, "naklon": 5 }, +{ "label": "48/12", "node": 3747, "naklon": 5 }, +{ "label": "48/13", "node": 3629, "naklon": 5 }, +{ "label": "48/14", "node": 4048, "naklon": 5 }, +{ "label": "48/15", "node": 4063, "naklon": 5 }, +{ "label": "48/16", "node": 4062, "naklon": 5 }, +{ "label": "48/17", "node": 4043, "naklon": 5 }, +{ "label": "48/18", "node": 4052, "naklon": 5 }, +{ "label": "48/19", "node": 4042, "naklon": 5 }, +{ "label": "48/20", "node": 4053, "naklon": 5 }, +{ "label": "50/15A", "node": 4167, "naklon": null }, +{ "label": "50/15B", "node": 4159, "naklon": null }, +{ "label": "50/1", "node": 4183, "naklon": 0 }, +{ "label": "50/2", "node": 4157, "naklon": 0 }, +{ "label": "50/3", "node": 4160, "naklon": 0 }, +{ "label": "50/4", "node": 4173, "naklon": 0 }, +{ "label": "50/5", "node": 4177, "naklon": 0 }, +{ "label": "50/6", "node": 4174, "naklon": 0 }, +{ "label": "50/7", "node": 4178, "naklon": 0 }, +{ "label": "50/8", "node": 4195, "naklon": 0 }, +{ "label": "50/9", "node": 4169, "naklon": 0 }, +{ "label": "50/10", "node": 4162, "naklon": 0 }, +{ "label": "50/11", "node": 4158, "naklon": 0 }, +{ "label": "50/12", "node": 4182, "naklon": 0 }, +{ "label": "50/13", "node": 4194, "naklon": 0 }, +{ "label": "50/14", "node": 4184, "naklon": 0 }, +{ "label": "50/16", "node": 4197, "naklon": null }, +{ "label": "50/17", "node": 4164, "naklon": null }, +{ "label": "50/18", "node": 3306, "naklon": null }, +{ "label": "50/19", "node": 4168, "naklon": null }, +{ "label": "50/20", "node": 4193, "naklon": null }, +{ "label": "50/21", "node": 4187, "naklon": null }, +{ "label": "50/22", "node": 4163, "naklon": null }, +{ "label": "50/23", "node": 4165, "naklon": null }, +{ "label": "50/24", "node": 4185, "naklon": null }, +{ "label": "50/25", "node": 3904, "naklon": null }, +{ "label": "53/1", "node": 2619, "naklon": 0 }, +{ "label": "53/2", "node": 2623, "naklon": 0 }, +{ "label": "53/3", "node": 2617, "naklon": 0 }, +{ "label": "53/4", "node": 2622, "naklon": 0 }, +{ "label": "53/5", "node": 2618, "naklon": 0 }, +{ "label": "53/6", "node": 2626, "naklon": 0 }, +{ "label": "53/7", "node": 2869, "naklon": 0 }, +{ "label": "53/8", "node": 2613, "naklon": 0 }, +{ "label": "53/9", "node": 2608, "naklon": 0 }, +{ "label": "53/10", "node": 2611, "naklon": 0 }, +{ "label": "53/11", "node": 2598, "naklon": 0 }, +{ "label": "53/12", "node": 3528, "naklon": 0 }, +{ "label": "53/13", "node": 3545, "naklon": 0 }, +{ "label": "53/14", "node": 2620, "naklon": 0 }, +{ "label": "53/15", "node": 2612, "naklon": 0 }, +{ "label": "53/16", "node": 2615, "naklon": 0 }, +{ "label": "53/17", "node": 3722, "naklon": 0 }, +{ "label": "53/18", "node": 2624, "naklon": 0 }, +{ "label": "53/19", "node": 2609, "naklon": 0 }, +{ "label": "53/20", "node": 2625, "naklon": 0 }, +{ "label": "53/21", "node": 2602, "naklon": 0 }, +{ "label": "53/22", "node": 2610, "naklon": 0 }, +{ "label": "53/23", "node": 2599, "naklon": 0 }, +{ "label": "53/24", "node": 2605, "naklon": 0 }, +{ "label": "53/25", "node": 2593, "naklon": 0 }, +{ "label": "53/26", "node": 3074, "naklon": 0 }, +{ "label": "53/27", "node": 2740, "naklon": 0 }, +{ "label": "53/28", "node": 2614, "naklon": 0 }, +{ "label": "53/29", "node": 2601, "naklon": 0 }, +{ "label": "53/30", "node": 4196, "naklon": 0 }, +{ "label": "53/31", "node": 2607, "naklon": 0 }, +{ "label": "53/32", "node": 2582, "naklon": 0 }, +{ "label": "53/33", "node": 2594, "naklon": 0 }, +{ "label": "53/34", "node": 2589, "naklon": 0 }, +{ "label": "53/35", "node": 2596, "naklon": 0 }, +{ "label": "53/36", "node": 2603, "naklon": 0 }, +{ "label": "53/37", "node": 2597, "naklon": 0 }, +{ "label": "53/38", "node": 2590, "naklon": 0 }, +{ "label": "53/39", "node": 2581, "naklon": 0 }, +{ "label": "53/40", "node": 2583, "naklon": 0 }, +{ "label": "53/41", "node": 2580, "naklon": 0 }, +{ "label": "53/42", "node": 2579, "naklon": 0 }, +{ "label": "53/43", "node": 2797, "naklon": 0 }, +{ "label": "53/44", "node": 2577, "naklon": 0 }, +{ "label": "53/45", "node": 2586, "naklon": 0 }, +{ "label": "53/46", "node": 2588, "naklon": 0 }, +{ "label": "53/47", "node": 2591, "naklon": 0 }, +{ "label": "53/48", "node": 2592, "naklon": 0 }, +{ "label": "53/49", "node": 2573, "naklon": 0 }, +{ "label": "53/50", "node": 2595, "naklon": 0 }, +{ "label": "53/51", "node": 2587, "naklon": 0 }, +{ "label": "53/52", "node": 2578, "naklon": 0 }, +{ "label": "53/53", "node": 2574, "naklon": 0 }, +{ "label": "53/54", "node": 2571, "naklon": 0 }, +{ "label": "53/55", "node": 2570, "naklon": 0 }, +{ "label": "53/56", "node": 2576, "naklon": 0 }, +{ "label": "53/57", "node": 2881, "naklon": 0 }, +{ "label": "53/58", "node": 2575, "naklon": 0 }, +{ "label": "53/59", "node": 2572, "naklon": 0 }, +{ "label": "53/60", "node": 2569, "naklon": 0 }, +{ "label": "55/1", "node": 4324, "naklon": 0 }, +{ "label": "55/2", "node": 4319, "naklon": 0 }, +{ "label": "55/3", "node": 4327, "naklon": 0 }, +{ "label": "55/4", "node": 4333, "naklon": 0 }, +{ "label": "55/5", "node": 4332, "naklon": 0 }, +{ "label": "55/6", "node": 4320, "naklon": 0 }, +{ "label": "55/7", "node": 4317, "naklon": 0 }, +{ "label": "55/8", "node": 4318, "naklon": 0 }, +{ "label": "55/9", "node": 4328, "naklon": 0 }, +{ "label": "55/10", "node": 4323, "naklon": 0 }, +{ "label": "55/11", "node": 4325, "naklon": 0 }, +{ "label": "55/12", "node": 4326, "naklon": 0 }, +{ "label": "55/13", "node": 4316, "naklon": 0 }, +{ "label": "55/14", "node": 4322, "naklon": 0 }, +{ "label": "55/15", "node": 4331, "naklon": 0 }, +{ "label": "55/16", "node": 4321, "naklon": 0 }, +{ "label": "55/17", "node": 4315, "naklon": 0 }, +{ "label": "55/18", "node": 4329, "naklon": 0 }, +{ "label": "55/19", "node": 4334, "naklon": 0 }, +{ "label": "55/20", "node": 4330, "naklon": 0 } +]; + +module.exports = { naklony }; diff --git a/RVO48/databases/modbus_config.js b/RVO48/databases/modbus_config.js new file mode 100755 index 0000000..b73116a --- /dev/null +++ b/RVO48/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/RVO48/databases/nodes.table b/RVO48/databases/nodes.table new file mode 100755 index 0000000..2453534 --- /dev/null +++ b/RVO48/databases/nodes.table @@ -0,0 +1,21 @@ +node:number|pole_number:string|node_type:string|tbname:string|line:number|profile:string|processed:boolean|status:boolean|time_of_last_communication:number ++|4051|1|NEMA|aw4eELG2DlPMdn1JW0B19qAqQXOZRN3xB5yp8VKr|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573916338|............. ++|4053|20|NEMA|PLBJzmK1r3Gynd6OW0gGOm0e5wV4vx9bDEqNgYR8|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573933673|............. ++|4042|19|NEMA|Nzp2OoJlqn6r1ZgvdA3Gd5AabBwP5G4eE3RQmyxD|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573913287|............. ++|4052|18|NEMA|wvKJdZML6mXP4DzWBAXW4p7jxNloa5g23Ve9Y1ry|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573916642|............. ++|4043|17|NEMA|EjgWGnXaLy9opPOz20n6lX086BlYM3w1deVQvbKr|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573914948|............. ++|4062|16|NEMA|3a5oqJN1bgnx4Ol9dk86ezAByE6jQ8mKDWMpGrLV|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573921355|............. ++|4058|9|NEMA|52dD6ZlV1QaOpRBmbAqK4MkKnGzWMLj4eJq38Pgo|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573919134|............. ++|4059|8|NEMA|PLBJzmK1r3Gynd6OW0gGOo0e5wV4vx9bDEqNgYR8|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573919614|............. ++|4060|7|NEMA|Nzp2OoJlqn6r1ZgvdA3GdjAabBwP5G4eE3RQmyxD|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573920237|............. ++|4047|6|NEMA|wvKJdZML6mXP4DzWBAXW4B7jxNloa5g23Ve9Y1ry|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573920428|............. ++|3883|5|NEMA|EjgWGnXaLy9opPOz20n6lm086BlYM3w1deVQvbKr|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573927139|............. ++|4063|15|NEMA|eod9aRWLVl34Gx1Dn7VoPyA2rz6qjgmpEXwQJN5Z|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573921738|............. ++|4048|14|NEMA|ZmRwd93QL4gaezxEbAxWxe71prn2XjlPvGyqJ6BO|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573916195|............. ++|3629|13|NEMA|nJL5lPMwBx23YpqRe0rlZw7damXvWVbOrD4gNzy8|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573911593|............. ++|3747|12|NEMA|roKgWqY95V3mXMRzyAjmEj7bLjexpJPvaGDBw826|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573917505|............. ++|3640|11|NEMA|E6Kg9oDnLWyzPRMva7vrYj7Jxp4VG58qO2w1lZYe|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573908957|............. ++|3635|10|NEMA|rDbQ84xzwgdqEoPm3kbJnrk9anOZY1RXyBv2LVM6|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573908558|............. ++|4041|2|NEMA|ZmRwd93QL4gaezxEbAxWxX71prn2XjlPvGyqJ6BO|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573917952|............. ++|4056|3|NEMA|eod9aRWLVl34Gx1Dn7VoPbA2rz6qjgmpEXwQJN5Z|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573917648|............. ++|3875|4|NEMA|3a5oqJN1bgnx4Ol9dk86ewAByE6jQ8mKDWMpGrLV|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:00"}],"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|1760573926867|............. diff --git a/RVO48/databases/nodes_original/nodes_original.table b/RVO48/databases/nodes_original/nodes_original.table new file mode 100755 index 0000000..01b2982 --- /dev/null +++ b/RVO48/databases/nodes_original/nodes_original.table @@ -0,0 +1 @@ +[{"4051": "aw4eELG2DlPMdn1JW0B19qAqQXOZRN3xB5yp8VKr"}, {"4053": "PLBJzmK1r3Gynd6OW0gGOm0e5wV4vx9bDEqNgYR8"}, {"4042": "Nzp2OoJlqn6r1ZgvdA3Gd5AabBwP5G4eE3RQmyxD"}, {"4052": "wvKJdZML6mXP4DzWBAXW4p7jxNloa5g23Ve9Y1ry"}, {"4043": "EjgWGnXaLy9opPOz20n6lX086BlYM3w1deVQvbKr"}, {"4062": "3a5oqJN1bgnx4Ol9dk86ezAByE6jQ8mKDWMpGrLV"}, {"4058": "52dD6ZlV1QaOpRBmbAqK4MkKnGzWMLj4eJq38Pgo"}, {"4059": "PLBJzmK1r3Gynd6OW0gGOo0e5wV4vx9bDEqNgYR8"}, {"4060": "Nzp2OoJlqn6r1ZgvdA3GdjAabBwP5G4eE3RQmyxD"}, {"4047": "wvKJdZML6mXP4DzWBAXW4B7jxNloa5g23Ve9Y1ry"}, {"3883": "EjgWGnXaLy9opPOz20n6lm086BlYM3w1deVQvbKr"}, {"4063": "eod9aRWLVl34Gx1Dn7VoPyA2rz6qjgmpEXwQJN5Z"}, {"4048": "ZmRwd93QL4gaezxEbAxWxe71prn2XjlPvGyqJ6BO"}, {"3629": "nJL5lPMwBx23YpqRe0rlZw7damXvWVbOrD4gNzy8"}, {"3747": "roKgWqY95V3mXMRzyAjmEj7bLjexpJPvaGDBw826"}, {"3640": "E6Kg9oDnLWyzPRMva7vrYj7Jxp4VG58qO2w1lZYe"}, {"3635": "rDbQ84xzwgdqEoPm3kbJnrk9anOZY1RXyBv2LVM6"}, {"4041": "ZmRwd93QL4gaezxEbAxWxX71prn2XjlPvGyqJ6BO"}, {"4056": "eod9aRWLVl34Gx1Dn7VoPbA2rz6qjgmpEXwQJN5Z"}, {"3875": "3a5oqJN1bgnx4Ol9dk86ewAByE6jQ8mKDWMpGrLV"}] \ No newline at end of file diff --git a/RVO48/databases/notifications.table b/RVO48/databases/notifications.table new file mode 100755 index 0000000..f7c96cb --- /dev/null +++ b/RVO48/databases/notifications.table @@ -0,0 +1,41 @@ +key:string|weight:string|sk:string|en:string ++|switching_profile_point_applied_to_line|INFORMATIONAL|Aplikovaný bod spínacieho profilu na línií č. ${line} : ${value}|Switching profile point applied to line no. ${line} : ${value}|............... ++|dusk_has_occured|INFORMATIONAL|Nastal súmrak: ${value}|Dusk has occured: ${value}|............... ++|dawn_has_occured|INFORMATIONAL|Nastal úsvit: ${value}|Dawn has occured: ${value}|............... ++|dimming_profile_was_successfully_received_by_node|NOTICE|Stmievací profil bol úspešne prijatý nodom č. ${node}|Dimming profile was successfully received by node no. ${node}|............... ++|master_node_is_responding_again|NOTICE|Master node začal znovu odpovedať|Master node is responding again|............... ++|command_was_sent_from_terminal_interface|DEBUG|Z terminálu bol odoslaný príkaz|A command was sent from terminal interface|............... ++|master_node_is_not_responding|ALERT|Master node neodpovedá|Master node is not responding|............... ++|configuration_of_dimming_profile_to_node_failed|ALERT|Konfigurácia stmievacieho profilu pre node č. ${node} zlyhala|Configuration of dimming profile to node no. ${node} has failed|............... ++|circuit_breaker_was_turned_on_line|NOTICE|Zapnutie ističa na línii č. ${line}|Circuit breaker was turned on - line no. ${line}|............... ++|circuit_breaker_was_turned_off_line|ERROR|Vypnutie ističa na línií č. ${line}|Circuit breaker was turned off - line no. ${line}|............... ++|dimming_profile_was_processed_for_node|INFORMATIONAL|Stmievací profil bol spracovaný pre node č. ${node}|Dimming profile was processed for node no. ${node}|............... ++|switching_profile_was_processed_for_line|INFORMATIONAL|Spínací profil bol spracovaný pre líniu č. ${line}|Switching profile was processed for line no. ${line}|............... ++|thermometer_is_not_responding|WARNING|Teplomer neodpovedá|Thermometer is not responding|............... ++|thermometer_is_responding_again|NOTICE|Teplomer znovu odpovedá|Thermometer is responding again|............... ++|thermometer_sends_invalid_data|WARNING|Teplomer posiela neplatné hodnoty|Thermometer sends invalid data|............... ++|main_switch_has_been_turned_off|CRITICAL|Hlavný vypínač bol vypnutý|Main switch has been turned off|............... ++|main_switch_has_been_turned_on|NOTICE|Hlavný vypínač bol zapnutý|Main switch has been turned on|............... ++|power_supply_has_disconnected_input|ALERT|Napájací zdroj nemá napätie na vstupe|Power supply has disconnected input|............... ++|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_main_open|NOTICE|Hlavné dvere boli otvorené|Main door has been opened|............... ++|door_em_open|NOTICE|Dvere silovej časti boli otvorené|Power door has been opened|............... ++|door_main_open_without_permission|WARNING|Hlavné dvere boli otvorené bez povolenia - zapnutá siréna|Main door has been opened without permission - alarm is on|............... ++|door_em_open_without_permission|WARNING|Dvere silovej časti boli otvorené bez povolenia|Power door has been opened without permission|............... ++|door_main_close|NOTICE|Hlavné dvere boli zatvorené|Main door has been closed|............... ++|door_em_close|NOTICE|Dvere silovej časti boli zatvorené|Power door has been closed|............... ++|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|............... ++|electrometer_ok|NOTICE|Elektromer znovu odpovedá|Electrometer is responding again|............... ++|no_voltage_on_phase|CRITICAL|Na fáze č. ${phase} nie je napätie|No voltage detected on phase no. ${phase}|............... ++|voltage_on_phase_restored|NOTICE|Napätie na fáze č. ${phase} bolo obnovené|Voltage on phase no. ${phase} has been restored|............... ++|flow_start|NOTICE|FLOW bol spustený|FLOW has been started |............... ++|twilight_sensor_nok|ERROR|Sensor súmraku neodpovedá|Twilight sensor is not responding|............... ++|twilight_sensor_ok|NOTICE|Sensor súmraku znovu odpovedá|Twilight sensor is responding again|............... ++|lamps_have_turned_on|NOTICE|Lampy sa zapli|Lamps have turned on|............... ++|lamps_have_turned_off|NOTICE|Lampy sa vypli|Lamps have turned off|............... ++|flow_restart|NOTICE|FLOW bol reštartovaný|FLOW has been restarted|............... ++|nodes_db_changed|NOTICE|Zmena v node databáze|Node db has changed|............... diff --git a/RVO48/databases/pins.table b/RVO48/databases/pins.table new file mode 100755 index 0000000..0eb3d05 --- /dev/null +++ b/RVO48/databases/pins.table @@ -0,0 +1,14 @@ +pin:string|type:string|line:number +*|input1_01|door_condition|0|........... +*|input1_02|rotary_switch_state|0|........... +*|input1_03|rotary_switch_state|0|........... +*|input1_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/RVO48/databases/relays.table b/RVO48/databases/relays.table new file mode 100755 index 0000000..34618df --- /dev/null +++ b/RVO48/databases/relays.table @@ -0,0 +1,5 @@ +line:number|tbname:string|contactor:number|profile:string ++|0|Z5KyJe9nEg1QNbWlX0w4nDkoDjBLdqzR83VGv624|1||........... ++|1|d5xjWYMwEJon6rLlK7yBVQAqgV4DaOeNB9ZX3Gzb|9|{"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|gRoJEyXVx4qD9er287LPzd7wBzGldaPjLWQKm3Mv|9|{"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|K94XLav1glVRnyQ6r01BGnkme3YJwBxM5oOzdP2j|9|{"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}|....................................................................................................................... diff --git a/RVO48/databases/settings.table b/RVO48/databases/settings.table new file mode 100755 index 0000000..294d482 --- /dev/null +++ b/RVO48/databases/settings.table @@ -0,0 +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|project_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|cloud_topic:string|has_main_switch:boolean|daily_report:boolean|send_changed_node_numbers:boolean ++|rvo_senica_48_10.0.0.135|en|28.EACE9C0E0000|48.70826502|17.28455203|192.168.252.1|rvo_senica_48_10.0.0.135|dPtTEWGRsm61v2gn6V9V|1883|0|71|unipi|ttyUSB0|1|20|5|6|3|u135|0|1|1|................................................... diff --git a/RVO48/databases/tbdata.nosql b/RVO48/databases/tbdata.nosql new file mode 100755 index 0000000..6802ebf --- /dev/null +++ b/RVO48/databases/tbdata.nosql @@ -0,0 +1,4 @@ +-"Z5KyJe9nEg1QNbWlX0w4nDkoDjBLdqzR83VGv624":[{"ts":1760530660612,"values":{"_event":{"type":"notice","status":"new","source":{"func":"modbus_reader","component":"1699965957410","component_name":"Modbus reader","edge":"Z5KyJe9nEg1QNbWlX0w4nDkoDjBLdqzR83VGv624"},"message":{"sk":"rvo_senica_48_10.0.0.135: FLOW bol reštartovaný","en":"rvo_senica_48_10.0.0.135: FLOW has been restarted"},"message_data":""}}}],"id":"3000318001rr71b"} +-"Z5KyJe9nEg1QNbWlX0w4nDkoDjBLdqzR83VGv624":[{"ts":1760530660703,"values":{"edge_fw_version":"2025-10-08","maintenance_mode":false}}],"id":"3000318002rr70b"} +-"Z5KyJe9nEg1QNbWlX0w4nDkoDjBLdqzR83VGv624":[{"ts":1760530660716,"values":{"statecode":2,"power_mode":"Automatic"}}],"id":"3000318004rr70b"} +-"Z5KyJe9nEg1QNbWlX0w4nDkoDjBLdqzR83VGv624":[{"ts":1760530660739,"values":{"_event":{"type":"notice","status":"new","source":{"func":"rsPort.open()","component":"1699963668903","component_name":"DIDO_Controller","edge":"Z5KyJe9nEg1QNbWlX0w4nDkoDjBLdqzR83VGv624"},"message":{"sk":"rvo_senica_48_10.0.0.135: FLOW bol spustený","en":"rvo_senica_48_10.0.0.135: FLOW has been started "},"message_data":""}}}],"id":"3000318006rr70b"} diff --git a/RVO48/databases/tbdatacloud.nosql b/RVO48/databases/tbdatacloud.nosql new file mode 100755 index 0000000..ca4536b --- /dev/null +++ b/RVO48/databases/tbdatacloud.nosql @@ -0,0 +1,3 @@ +-"Z5KyJe9nEg1QNbWlX0w4nDkoDjBLdqzR83VGv624":[{"ts":1760530660703,"values":{"edge_fw_version":"2025-10-08","maintenance_mode":false}}],"id":"3000318003rr71b"} +-"Z5KyJe9nEg1QNbWlX0w4nDkoDjBLdqzR83VGv624":[{"ts":1760530660716,"values":{"statecode":2,"power_mode":"Automatic"}}],"id":"3000318005rr71b"} +-"Z5KyJe9nEg1QNbWlX0w4nDkoDjBLdqzR83VGv624":[{"ts":1760530660739,"values":{"_event":{"type":"notice","status":"new","source":{"func":"rsPort.open()","component":"1699963668903","component_name":"DIDO_Controller","edge":"Z5KyJe9nEg1QNbWlX0w4nDkoDjBLdqzR83VGv624"},"message":{"sk":"rvo_senica_48_10.0.0.135: FLOW bol spustený","en":"rvo_senica_48_10.0.0.135: FLOW has been started "},"message_data":""}}}],"id":"3000318007rr71b"} diff --git a/RVO48/databases/total_energy.js b/RVO48/databases/total_energy.js new file mode 100755 index 0000000..dde340e --- /dev/null +++ b/RVO48/databases/total_energy.js @@ -0,0 +1,38 @@ +//key is rvo_number, value is max energy when lamps are on +const total_energy = { + 1: 580, + 2: 1100, + 3: 3700, + 4: 4100, + 7: 360, + 12: 1700, + 13: 5400, + 14: 440, + 15: 6100, + 16: 4800, + 20: 1600, + 21: 1000, + 22: 2600, + 23: 1000, + 25: 2600, + 33: 240, + 34: 4000, + 35: 2700, + 36: 820, + 37: 1400, + 35: 3500, + 39: 1170, + 41: 740, + 42: 660, + 43: 4900, + 45: 930, + 46: 700, + 47: 1100, + 48: 1500, + 50: 3200, + 53: 1250, + 55: 1000, + 56: 5500 +} + +module.exports = total_energy; diff --git a/RVO48/debug.js b/RVO48/debug.js new file mode 100755 index 0000000..9818194 --- /dev/null +++ b/RVO48/debug.js @@ -0,0 +1,16 @@ +// =================================================== +// FOR DEVELOPMENT +// Total.js - framework for Node.js platform +// https://www.totaljs.com +// =================================================== + +const options = {}; + +// options.ip = '127.0.0.1'; +// options.port = parseInt(process.argv[2]); +// options.config = { name: 'Total.js' }; +// options.sleep = 3000; +// options.inspector = 9229; +// options.watch = ['private']; + +require('total.js/debug')(options); \ No newline at end of file diff --git a/RVO48/err.txt b/RVO48/err.txt new file mode 100755 index 0000000..d76e892 --- /dev/null +++ b/RVO48/err.txt @@ -0,0 +1,126 @@ +[2024-10-24T22:58:16.895] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-24T23:11:36.495] [ERROR] errLogs - checkFinalRVOStatus: twilight sensor is NOK +[2024-10-25T00:02:29.722] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-25T00:13:18.329] [ERROR] errLogs - checkFinalRVOStatus: twilight sensor is NOK +[2024-10-25T01:04:17.376] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-25T01:15:02.111] [ERROR] errLogs - checkFinalRVOStatus: twilight sensor is NOK +[2024-10-25T02:05:59.216] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-25T02:16:32.295] [ERROR] errLogs - checkFinalRVOStatus: twilight sensor is NOK +[2024-10-25T03:07:25.507] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-25T03:18:08.284] [ERROR] errLogs - checkFinalRVOStatus: twilight sensor is NOK +[2024-10-25T04:08:50.794] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-25T04:19:37.465] [ERROR] errLogs - checkFinalRVOStatus: twilight sensor is NOK +[2024-10-25T05:10:15.169] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-25T05:20:59.891] [ERROR] errLogs - checkFinalRVOStatus: twilight sensor is NOK +[2024-10-25T06:14:37.673] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-25T06:22:35.883] [ERROR] errLogs - checkFinalRVOStatus: twilight sensor is NOK +[2024-10-25T07:15:54.286] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-25T07:23:52.488] [ERROR] errLogs - checkFinalRVOStatus: twilight sensor is NOK +[2024-10-25T08:25:18.801] [ERROR] errLogs - checkFinalRVOStatus: twilight sensor is NOK +[2024-10-25T08:25:18.802] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-25T09:26:35.374] [ERROR] errLogs - checkFinalRVOStatus: twilight sensor is NOK +[2024-10-25T09:29:18.005] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-25T10:28:19.112] [ERROR] errLogs - checkFinalRVOStatus: twilight sensor is NOK +[2024-10-25T10:30:59.806] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-25T11:29:33.756] [ERROR] errLogs - checkFinalRVOStatus: twilight sensor is NOK +[2024-10-25T11:32:14.451] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-25T12:31:00.028] [ERROR] errLogs - checkFinalRVOStatus: twilight sensor is NOK +[2024-10-25T12:33:36.846] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-25T13:32:36.054] [ERROR] errLogs - checkFinalRVOStatus: twilight sensor is NOK +[2024-10-25T13:35:14.809] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-25T14:33:58.469] [ERROR] errLogs - checkFinalRVOStatus: twilight sensor is NOK +[2024-10-25T14:39:15.978] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-25T15:35:09.260] [ERROR] errLogs - checkFinalRVOStatus: twilight sensor is NOK +[2024-10-25T15:40:22.891] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-25T16:36:14.201] [ERROR] errLogs - checkFinalRVOStatus: twilight sensor is NOK +[2024-10-25T16:44:14.350] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-25T17:37:38.557] [ERROR] errLogs - checkFinalRVOStatus: twilight sensor is NOK +[2024-10-25T17:45:42.582] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-25T18:39:00.971] [ERROR] errLogs - checkFinalRVOStatus: twilight sensor is NOK +[2024-10-25T18:46:57.244] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-25T19:40:19.540] [ERROR] errLogs - checkFinalRVOStatus: twilight sensor is NOK +[2024-10-25T19:48:27.450] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-25T20:42:03.281] [ERROR] errLogs - checkFinalRVOStatus: twilight sensor is NOK +[2024-10-25T20:50:11.182] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-25T21:43:25.692] [ERROR] errLogs - checkFinalRVOStatus: twilight sensor is NOK +[2024-10-25T21:51:27.782] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-25T22:44:40.365] [ERROR] errLogs - checkFinalRVOStatus: twilight sensor is NOK +[2024-10-25T22:52:40.500] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-25T23:45:49.286] [ERROR] errLogs - checkFinalRVOStatus: twilight sensor is NOK +[2024-10-25T23:53:47.501] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T00:47:02.089] [ERROR] errLogs - checkFinalRVOStatus: twilight sensor is NOK +[2024-10-26T00:55:02.239] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T01:48:45.880] [ERROR] errLogs - checkFinalRVOStatus: twilight sensor is NOK +[2024-10-26T01:59:26.765] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T02:50:18.091] [ERROR] errLogs - checkFinalRVOStatus: twilight sensor is NOK +[2024-10-26T03:01:04.765] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T03:51:45.470] [ERROR] errLogs - checkFinalRVOStatus: twilight sensor is NOK +[2024-10-26T04:02:26.327] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T04:53:17.631] [ERROR] errLogs - checkFinalRVOStatus: twilight sensor is NOK +[2024-10-26T05:03:58.477] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T05:54:43.965] [ERROR] errLogs - checkFinalRVOStatus: twilight sensor is NOK +[2024-10-26T06:05:22.884] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T06:56:14.217] [ERROR] errLogs - checkFinalRVOStatus: twilight sensor is NOK +[2024-10-26T07:06:55.071] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T07:57:38.699] [ERROR] errLogs - checkFinalRVOStatus: twilight sensor is NOK +[2024-10-26T08:11:04.143] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T08:59:30.309] [ERROR] errLogs - checkFinalRVOStatus: twilight sensor is NOK +[2024-10-26T09:12:57.685] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T10:01:31.632] [ERROR] errLogs - checkFinalRVOStatus: twilight sensor is NOK +[2024-10-26T10:14:57.073] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T11:03:11.607] [ERROR] errLogs - checkFinalRVOStatus: twilight sensor is NOK +[2024-10-26T11:16:33.164] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T12:04:57.394] [ERROR] errLogs - checkFinalRVOStatus: twilight sensor is NOK +[2024-10-26T12:18:11.178] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T13:06:39.290] [ERROR] errLogs - checkFinalRVOStatus: twilight sensor is NOK +[2024-10-26T13:20:02.796] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T14:08:21.194] [ERROR] errLogs - checkFinalRVOStatus: twilight sensor is NOK +[2024-10-26T14:21:40.800] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T15:09:47.519] [ERROR] errLogs - checkFinalRVOStatus: twilight sensor is NOK +[2024-10-26T15:23:03.252] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T16:11:09.989] [ERROR] errLogs - checkFinalRVOStatus: twilight sensor is NOK +[2024-10-26T16:24:31.547] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T17:12:57.690] [ERROR] errLogs - checkFinalRVOStatus: twilight sensor is NOK +[2024-10-26T17:29:03.811] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T18:14:29.850] [ERROR] errLogs - checkFinalRVOStatus: twilight sensor is NOK +[2024-10-26T18:30:28.228] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T19:15:56.200] [ERROR] errLogs - checkFinalRVOStatus: twilight sensor is NOK +[2024-10-26T19:31:50.698] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T20:17:28.363] [ERROR] errLogs - checkFinalRVOStatus: twilight sensor is NOK +[2024-10-26T20:33:32.536] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T21:18:54.712] [ERROR] errLogs - checkFinalRVOStatus: twilight sensor is NOK +[2024-10-26T21:34:58.889] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T22:20:21.039] [ERROR] errLogs - checkFinalRVOStatus: twilight sensor is NOK +[2025-09-23T14:06:53.407] [ERROR] errLogs - uncaughtException: Cannot read property 'getHours' of undefined +[2025-09-23T14:06:53.409] [ERROR] errLogs - TypeError: Cannot read property 'getHours' of undefined + at Timeout.emptyReportToSend [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:06:53.410] [ERROR] errLogs - uncaughtException: Cannot read property 'getHours' of undefined +[2025-09-23T14:06:53.411] [ERROR] errLogs - TypeError: Cannot read property 'getHours' of undefined + at Timeout.emptyReportToSend [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:06:53.416] [ERROR] errLogs - uncaughtException: Cannot read property 'getHours' of undefined +[2025-09-23T14:06:53.416] [ERROR] errLogs - TypeError: Cannot read property 'getHours' of undefined + at Timeout.emptyReportToSend [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:06:59.145] [ERROR] errLogs - uncaughtException: date.getHours is not a function +[2025-09-23T14:06:59.145] [ERROR] errLogs - TypeError: date.getHours is not a function + at emptyReportToSend (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at Timeout.dailyReportCheck [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1351:5) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:06:59.146] [ERROR] errLogs - uncaughtException: date.getHours is not a function +[2025-09-23T14:06:59.147] [ERROR] errLogs - TypeError: date.getHours is not a function + at emptyReportToSend (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at Timeout.dailyReportCheck [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1351:5) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:06:59.149] [ERROR] errLogs - uncaughtException: date.getHours is not a function +[2025-09-23T14:06:59.150] [ERROR] errLogs - TypeError: date.getHours is not a function + at emptyReportToSend (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at Timeout.dailyReportCheck [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1351:5) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) diff --git a/RVO48/flow/cloudmqttconnect.js b/RVO48/flow/cloudmqttconnect.js new file mode 100755 index 0000000..b03491f --- /dev/null +++ b/RVO48/flow/cloudmqttconnect.js @@ -0,0 +1,357 @@ +exports.id = 'cloudmqttconnect'; +exports.title = 'Cloud connect mqtt'; +exports.group = 'MQTT'; +exports.color = '#888600'; +exports.version = '1.0.2'; +exports.icon = 'sign-out'; +exports.input = 2; +exports.output = 2; +exports.options = { host: 'tb-stage.worksys.io', port: 1883, clientid: "", username: "" }; + +exports.html = `
+
+
+
Hostname or IP address (if not empty - setting will override db setting)
+
+
+
Port
+
+
+
+
+
@(Client id)
+
+
+
topic
+
+
+
`; + + + +const { promisifyBuilder } = require('./helper/db_helper'); +const fs = require('fs'); +const mqtt = require('mqtt'); +const nosql = NOSQL('tbdatacloud'); + +const SEND_TO = { + debug: 0, + rpcCall: 1, +} + +//CONFIG +let saveTelemetryOnError = true;//backup_on_failure overrides this value +//------------------------ + +const noSqlFileSizeLimit = 4194304;//use 5MB - 4194304 +let insertNoSqlCounter = 0; +let insertBackupNoSqlCounter = 0; +let processingData = false; + +let backup_on_failure = true;//== saveTelemetryOnError - create backup client send failure +let restore_from_backup = 50; //how many rows process at once? +let restore_backup_wait = 3;//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; + + +exports.install = function(instance) { + + var client; + var opts; + var clientReady = false; + + let o = {}; //options + + function main() { + loadSettings(); + } + + //set opts according to db settings + function loadSettings() { + + o = instance.options; + if (!o.topic) o.topic = FLOW.GLOBALS.settings.cloud_topic; + + opts = { + host: o.host, + port: o.port, + clientId: o.clientid, + username: o.username, + rejectUnauthorized: false, + resubscribe: false + }; + + console.log("wsmqttpublich -> loadSettings from instance.options", o); + + if (!o.topic) { + instance.status("Not configured", "white"); + console.log("Cloud mqtt connect: no topic selected"); + return; + } + + connectToTbServer(); + } + + function connectToTbServer() { + var url = "mqtt://" + opts.host + ":" + opts.port; + console.log("MQTT URL: ", url); + + client = mqtt.connect(url, opts); + + client.on('connect', function() { + client.subscribe(`${o.topic}_backward`, (err) => { + if (!err) { + console.log("MQTT subscribed"); + } + }); + instance.status("Connected", "green"); + clientReady = true; + sendClientError = true; + }); + + client.on('reconnect', function() { + instance.status("Reconnecting", "yellow"); + clientReady = false; + }); + + client.on('message', function(topic, message) { + // message is type of buffer + message = message.toString(); + if (message[0] === '{') { + TRY(function() { + + message = JSON.parse(message); + if (message.hasOwnProperty("device") && message.hasOwnProperty("data") && message.data.hasOwnProperty("id")) { + client.publish(`${o.topic}_forward`, `{"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 } }); + } + + }, () => instance.debug('MQTT: Error parsing data', message)); + } + + instance.send(SEND_TO.rpcCall, { "topic": o.topic, "content": message }); + }); + + client.on('close', function() { + clientReady = false; + + instance.status("Disconnected", "red"); + instance.send(SEND_TO.debug, { "message": "Client CLOSE signal received !" }); + }); + + client.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) { + console.log('MQTT client error', err); + sendClientError = false; + } + clientReady = false; + }); + + } + + + instance.on('0', function(data) { + + if (clientReady) { + //do we have some data in backup file? if any, process data from database + if (saveTelemetryOnError) { + //read telemetry data and send back to server + if (!processingData) processDataFromDatabase(); + } + + let stringifiedJson = JSON.stringify(data.data) + client.publish(`${o.topic}_forward`, stringifiedJson, { qos: 1 }); + } + 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 (saveTelemetryOnError && o.topic) { + //create new file from tbdata.nosql, if file size exceeds given limit, and clear tbdata.nosql + makeBackupFromDbFile(); + + //write to tb + data.data.id = UID(); + nosql.insert(data.data); + } + } + }); + + instance.on("1", _ => { + main(); + }) + + instance.close = function(done) { + if (clientReady) { + client.end(); + } + }; + + + function getDbBackupFileCounter(type) { + var files = fs.readdirSync(__dirname + "/../databases"); + + let counter = 0; + for (var i = 0; i < files.length; i++) { + + if (files[i] == "tbdatacloud.nosql") continue; + + if (files[i].endsWith(".nosql")) { + + let pos = files[i].indexOf("."); + if (pos > -1) { + + let fileCounter = counter; + let firstDigit = files[i].slice(0, pos); + + fileCounter = parseInt(firstDigit); + if (isNaN(fileCounter)) fileCounter = 0; + //console.log("getDbBackupFileCounter digit:", files[i], firstDigit, fileCounter, isNaN(fileCounter), type); + + if (type == "max") { + if (fileCounter > counter) { + counter = fileCounter; + } + } + else if (type == "min") { + if (counter == 0) counter = fileCounter; + + if (fileCounter < counter) { + counter = fileCounter; + } + } + } + } + + } + + if (type == "max") counter++; + + return counter; + } + + const makeBackupFromDbFile = async () => { + + if (!saveTelemetryOnError) return; + + //to avoid large file: tbdata.nosql + + //init value is 0! + if (insertNoSqlCounter > 0) { + --insertNoSqlCounter; + return; + } + + insertNoSqlCounter = 100; + + let source = __dirname + "/../databases/tbdatacloud.nosql"; + + var stats = fs.statSync(source); + var fileSizeInBytes = stats.size; + + if (fileSizeInBytes > noSqlFileSizeLimit) { + + let counter = 1; + counter = getDbBackupFileCounter("max"); + + let destination = __dirname + "/../databases/" + counter + "." + "tbdatacloud.nosql"; + + //make backup file + fs.copyFileSync(source, destination); + //fs.renameSync(p, p + "." + counter); + + //clear tbdata.nosql + fs.writeFileSync(source, ""); + fs.truncateSync(source, 0); + + } + } + + const processDataFromDatabase = async () => { + + if (restore_from_backup <= 0) return; + + //calculate diff + const now = new Date(); + let currentTime = now.getTime(); + let diff = currentTime - lastRestoreTime; + + if ((diff / 1000) < restore_backup_wait) { + //console.log("*********restore_backup_wait", diff, restore_backup_wait); + return; + } + + processingData = true; + + //get filename to process + let counter = getDbBackupFileCounter("min"); + + //we have some backup files + let dataBase = 'tbdata'; + + var nosql; + if (counter == 0) dataBase = 'tbdatacloud'; + else dataBase = counter + "." + 'tbdatacloud'; + + nosql = NOSQL(dataBase); + + //select all data - use limit restore_from_backup + let records = await promisifyBuilder(nosql.find().take(restore_from_backup)); + + for (let i = 0; i < records.length; i++) { + if (clientReady) { + + let item = records[i]; + let id = item.id; + + if (id !== undefined) { + //console.log("------------processDataFromDatabase - remove", id, dataBase, i); + + try { + + let message = JSON.parse(JSON.stringify(item)); + delete message.id; + client.publish(`${o.topic}_forward`, JSON.stringify(message), { qos: 1 }); + + //remove from database + await promisifyBuilder(nosql.remove().where("id", id)); + + } catch (error) { + //process error + console.log("processDataFromDatabase", error); + } + + } + + } + else { + processingData = false; + return; + } + } + + if (records.length > 0) { + //clean backup file + if (counter > 0) nosql.clean(); + } + + //no data in db, remove + if (records.length == 0) { + if (counter > 0) nosql.drop(); + } + + const d = new Date(); + lastRestoreTime = d.getTime(); + + processingData = false; + + } + + instance.on('options', main); + +}; diff --git a/RVO48/flow/cmd_manager.js b/RVO48/flow/cmd_manager.js new file mode 100755 index 0000000..25912df --- /dev/null +++ b/RVO48/flow/cmd_manager.js @@ -0,0 +1,3071 @@ +exports.id = 'cmd_manager'; +exports.title = 'CMD Manager'; +exports.group = 'Worksys'; +exports.color = '#5D9CEC'; +exports.version = '0.0.3'; +exports.output = ['red', 'blue', 'yellow', 'blue', 'white', 'green']; +exports.input = 3; +exports.icon = 'cloud-upload'; + +exports.html = ` +
+
+
+
RPC - run RPC calls

+
+
+
@(User)
+
+
+
@(Password)
+
+
+
@(My edge)
+
+
+
+`; +exports.readme = `Manager for CMD calls`; + + +exports.install = function(instance) { + + 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, isEmptyObject, emptyJsObject, writeToFile, addToArrayIfUnique } = require('./helper/utils'); + const bitwise = require('bitwise'); + + var SunCalc = require('./helper/suncalc'); + const DataToTbHandler = require('./helper/DataToTbHandler'); + const errorHandler = require('./helper/ErrorToServiceHandler'); + const { sendNotification } = require('./helper/notification_reporter'); + const process = require('process'); + const { errLogger, logger, monitor } = require('./helper/logger'); + + //for accelerometer purposes + const { naklony } = require("../databases/accelerometer_db"); + + const dbNodes = TABLE("nodes"); + const dbRelays = TABLE("relays"); + + let GLOBALS; + let SETTINGS; + let rsPort; + let tbHandler; + + // runTasks intervals + const SHORT_INTERVAL = 30; + const LONG_INTERVAL = 300; + + //send data to following instances: + const SEND_TO = { + debug: 0, + tb: 1, + http_response: 2, + dido_controller: 3, + infoSender: 4, + dailyReport: 5 + } + + 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 + } + + 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 sendNodeReadout = null; // interval for sending agregate data from node + + 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["1"] = minutes; // dimming + priorities["76"] = minutes; // power + + minutes = 5; + priorities["75"] = minutes; // current + priorities["79"] = minutes; // energy + priorities["87"] = minutes; // aktualny cas + //priorities["84"] = minutes; //accelerometer + + minutes = 10; + priorities["74"] = minutes; // voltage + priorities["77"] = minutes; // power factor + priorities["78"] = minutes; // frequency + + minutes = 60; + priorities["0"] = minutes; // statecode + priorities["6"] = minutes; // dusk + priorities["7"] = minutes; // dawn + priorities["8"] = minutes; // profile + + minutes = 60 * 24; + priorities["89"] = minutes; // verzia fw + priorities["80"] = minutes; // lifetime + + //prikazy kt sa budu spustat na dany node - see config.js in terminal-oms.app. (1 - dimming) + let listOfCommands = [0, 1, 6, 7, 8, 74, 75, 76, 77, 78, 79, 80, 87, 89]; + + 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; + + // holds dusk, dawn (and more) values + let sunCalcResult; + + //helper container for counting resolved group of commands (commands related to set profile) + let cmdCounter = {};//key is node, value is counter + + //TODO: is this set working?? According to previous checks, sets do not work + //if sending of profile to node fails, we send notification and push node into set, so we do not send notification twice + const nodeProfileSendFail = new Set(); + + //we expect to get current temperature in Senica from senica-prod01 + let temperatureInSenica = null; + let accelerometerInterval = null; + + //NOTE: daily reports senica: + //rvo_is_on status, we monitor all nodes - if true, power and dimming should be not 0, if false, 24/7 nodes should be 0, other rvo should not respond + let rvo_is_on; + let previous_rvo_is_on_value; + let handleDailyReport; //setInterval for dailyReportHandler function + let dailyReport = {}; //data needed for daily report + let reportToSend = {}; //final report which we send to cloud + let breakerCounter = null; // status of breakers after flow starts is not in report + let rvoPeriod; // interval of checking dusk dawn and if rvo_is_on + let initialReportStatus = false; + + const DAILY_REPORT_HANDLER_TIME = 3_600_000; + const SET_SUNCALC_RESULT_TIME = 3_600_000; + const SET_RVO_PERIOD_TIME = 300_000; + const ADD_NODE_TO_REPORT_TIME = 3_600_000; + + //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); + + let now = new Date(); + console.log("Cmd-mngr installed", now.toLocaleString("sk-SK")); + + sunCalcResult = calculateDuskDawn(); + + handleRsPort(); + + customTasksInterval = setInterval(reportEdgeDateTimeAndNumberOfLuminaires, 120_000); + setTimeout(reportEdgeDateTimeAndNumberOfLuminaires, 4000); + + //dailyReport related + emptyReportToSend(); + breakerCounter = Object.keys(relaysData).length - 1; // we get number of lines (breakers) except of line 0 + rvoPeriod = setInterval(setRvoPeriod, SET_RVO_PERIOD_TIME); + setTimeout(setRvoPeriod, 3000); + setInterval(setSunCalcResult, SET_SUNCALC_RESULT_TIME); + handleDailyReport = setInterval(dailyReportHandler, DAILY_REPORT_HANDLER_TIME); + + + setCorrectTime = setInterval(setCorrectPlcTimeOnceADay, 60000 * 60); // 1 hour + setCorrectPlcTimeOnceADay(); + + sendNodeReadout = setInterval(sendNodesData, 150_000); + accelerometerInterval = setInterval(accelerometerData, 60000 * 30); //30 min + } + + + 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" + //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 + // if node regular readout does not respond, we repeat request + params.repeatCounter = 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-mngr: 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.byte4 = 96; + params.recipient = 1; + params.register = 8; + params.rw = 1;//write + params.timestamp = timestamp; + 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.byte4 = 96; + params.recipient = 1; + params.register = 8; + params.rw = 1;//write + params.timestamp = timestamp; + 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). + */ + + 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.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.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 + { + + logger.debug("processNodeProfile: Threshold lux level for DUSK/DAWN", node); + + let params = getParams(); + params.type = "set_node_profile"; + params.address = node; + params.register = 96; + params.recipient = 1; + params.rw = 1;//write + params.timestamp = timestamp; + 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(); + params.type = "set_node_profile"; + params.address = node; + params.register = 97; + params.recipient = 1; + params.rw = 1;//write + params.timestamp = timestamp; + 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.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); + + 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); + + console.log("proces profile finished *********************") + } + + + 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; + }); + } + + + 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) { + for (let k in nodesData) { + 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`); + } + } + } + + + function loadRelaysData(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 (value.contactor == 1) processAllNodeProfilesOnLine(value.line); + } + } + + + function reportOnlineNodeStatus(line) { + //Po zapnutí línie broadcastovo aktualizovať predtým čas a o 3 sek neskor - status, brightness + + logger.debug("Cmd-mngr: ----->reportOnlineNodeStatus for line", line); + + const d = new Date(); + + // broadcast actual time + let params = getParams(); + params.address = 0xffffffff;//Broadcast + params.byte1 = d.getHours(); + params.byte2 = d.getMinutes(); + params.recipient = 2;//2 broadcast, address = 0 + params.register = 87;//Actual time + params.rw = 1;//write + params.type = "node-onetime-write"; + params.timestamp = d.getTime() + 30000; + params.info = "run broadcast: Actual time"; + //params.debug = true; + + tasks.push(params); + + let sec = 3; + setTimeout(function() { + //Po zapnutí línie - spraviť hromadný refresh stavu práve zapnutých svietidiel + + let time = Date.now(); + + for (let k in nodesData) { + + //potrebujem nody k danej linii + 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].node_status_before_offline === true || nodesData[k].status === true) { + status = "OK"; + nodesData[k].time_of_last_communication = time; + } + + nodesData[k].readout.status = status; + + updateNodeStatus(k, status === "OK" ? true : false); + if (nodesData[k].hasOwnProperty("node_status_before_offline")) delete nodesData[k].node_status_before_offline; + sendTelemetry({ status: status }, tbname, time); + + //vyreportovanie dimming, current, input power pre liniu pre vsetky nody + //Prud + { + let params = getParams(); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 75;//prud + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = time + 4000; + params.info = 'read current'; + //params.debug = true; + tasks.push(params); + } + + //vykon + { + let params = getParams(); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 76;//výkon + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = time + 4100; + params.info = 'read power'; + //params.debug = true; + + tasks.push(params); + } + //dimming + { + let params = getParams(); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 1;//dimming + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = time + 4200; + params.info = 'read dimming'; + //params.debug = true; + + tasks.push(params); + } + + } + } + + }, sec * 1000); + } + + + function reportOfflineNodeStatus(line) { + + logger.info("Cmd-mngr: ------>reportOffLineNodeStatus for line ", line); + + values = {}; + values["dimming"] = 0;//brightness + values["power"] = 0;//výkon + values["current"] = 0;//prúd + values["status"] = "OFFLINE"; + + const date = Date.now(); + + Object.keys(nodesData).forEach(node => { + + //potrebujem nody k danej linii + if (line == nodesData[node].line || line == undefined) { + + let tbname = nodesData[node].tbname; + let nodeStatus = nodesData[node].status; + + //in case we have reported offline node status, we return (continue with next node) + if (nodeStatus === "OFFLINE") return; + + nodesData[node].node_status_before_offline = nodeStatus; + nodesData[node].status = "OFFLINE"; + nodesData[node].readout = {}; + + sendTelemetry({ ...values }, tbname, date); + } + }); + + } + + + function turnLine(onOrOff, line, info) { + let obj = { + line: line, + command: onOrOff, + info: info + }; + + //to assure, handleDailyReportFunction do not run before rvo_is_on variable changes. So after every line switch we reset the timer + clearInterval(handleDailyReport); + handleDailyReport = setInterval(dailyReportHandler, DAILY_REPORT_HANDLER_TIME); + + //logger.debug("linia", line, obj); + instance.send(SEND_TO.dido_controller, obj); + } + + + 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"; + 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]) { + //CRC_ERROR + message = "NOK"; + error = "CRC_ERROR c1"; + instance.send(SEND_TO.debug, "CRC_ERROR c1"); + } + + 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") { + instance.send(SEND_TO.debug, bytes); + instance.send(SEND_TO.debug, "RESPONSE " + type + " - " + bytes[4]); + + //logger.debug(SEND_TO.debug, "RESPONSE " + type + " - " + bytes[4], bytes); + + error = "type is: " + type; + + message = "NOK"; + } + + return { message, type, error }; + } + + + //BUILD TASKS// + function buildTasks(params) { + + //return; + console.log("buidTAaasks start ****************", params); + monitor.info("buildTasks - params", params); + + let processLine; //defined line + let init = false; + let processLineProfiles = true; + let processBroadcast = true; + let processNodes = true; + + if (params == undefined) { + init = true; + tasks = []; + logger.debug("-->buildTasks clear tasks"); + } + else { + processLineProfiles = params.processLineProfiles; + processBroadcast = false; + processNodes = false; + + processLine = params.line; + } + + let now = new Date(); + + //process line profiles + if (processLineProfiles) { + + let keys = Object.keys(relaysData); + + for (let i = 0; i < keys.length; i++) { + + let line = parseInt(keys[i]); + let profilestr = relaysData[line].profile; + + if (processLine != undefined) { + if (processLine != line) continue; + } + + try { + + /** + * we process line profiles: timepoints, astro clock, lux_sensor, offsets ... + */ + if (profilestr === "") throw ("Profile is not defined"); + let profile = JSON.parse(profilestr); + 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; + + // add name to regular profile timepoint and delete unused end_time key: + time_points.forEach(point => { + point.name = "profileTimepoint" + delete point.end_time; + }); + + //monitor.info("buildTasks: time_points", time_points); + + + /** + * 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 astro clock true, we remove all regular profile points + time_points = []; + + //TODO: when astro clock == true, is offset calculated ??? + //let duskAstroClockOffset = profile.dusk_astro_clock_offset; + //let dawnAstroClockOffset = profile.dawn_astro_clock_offset; + //console.log("line astro clock offsets dusk a dawn: ", duskAstroClockOffset, dawnAstroClockOffset); + // maybe add dusk dawn offset to calculateDuskDawn ?? what dusk dawn will be if dawn_lux_sensor == true?? + //let sunCalcResult = calculateDuskDawn(new Date(), line, duskAstroClockOffset, dawnAstroClockOffset); + + 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 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); + + 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); + + 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(':'); + + let ad = new Date(); + ad.setHours(parseInt(ahours), parseInt(aminutes), 0); + + let bd = new Date(); + bd.setHours(parseInt(bhours), parseInt(bminutes), 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++) { + + let start_time = new Date(); + let [hours, minutes] = time_points[t].start_time.split(':'); + start_time.setHours(parseInt(hours), parseInt(minutes), 0); + + //task is in 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(); + params.type = "relay"; + params.line = parseInt(line); + params.value = time_points[t].value; + params.tbname = relaysData[line].tbname; + params.timestamp = start_time.getTime(); + + // 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; + + //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)) { + 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; + + params.debug = true; + + //turn on/off line + tasks.push(params); + monitor.info("TimePoint params: ", params.info, start_time); + } + + monitor.info("-->time_points final", line, time_points); + + //ensure to turn on/off according to calculated currentValue + let params = getParams(); + params.type = "relay"; + params.line = parseInt(line); + params.tbname = relaysData[line].tbname; + params.value = currentValue; + params.timestamp = i; + params.debug = true; + + //logger.debug(now.toLocaleString("sk-SK")); + 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; + + tasks.push(params); + + } catch (error) { + if (profilestr !== "") { + //errLogger.error(profilestr, error); + console.log(`Cmd_mngr: Unable to process line profile ${line}. Error: `, error); + errorHandler.sendMessageToService(profilestr + "-" + error, 0, "js_error"); + } else { + turnLine("off", line, "No line profile. Switching it off on startup"); + } + } + + } + //logger.debug("tasks:"); + //logger.debug(tasks); + } + + + //NOTE: PROCESS DEFAULT BROADCASTS - Time of dusk, Time of dawn, Actual Time + if (processBroadcast) { + + let d = new Date(); + let time = d.getTime(); + //let sunCalcResult = calculateDuskDawn(); + + { + let params = getParams(); + + params.address = 0xffffffff;//broadcast + params.byte1 = sunCalcResult["dusk_hours"]; + params.byte2 = sunCalcResult["dusk_minutes"]; + params.recipient = 2;//2 broadcast, + params.register = 6;//Time of dusk + params.rw = 1;//write + params.type = "node-regular-write"; + params.timestamp = time + 60000; + params.addMinutesToTimestamp = 60 * 3; //kazde 3 hodiny zisti novy dusk + params.info = "Broadcast-duskTime"; + + tasks.push(params); + } + + { + let params = getParams(); + + params.address = 0xffffffff;//broadcast + params.byte1 = sunCalcResult["dawn_hours"]; + params.byte2 = sunCalcResult["dawn_minutes"]; + params.recipient = 2; //2 broadcast + params.register = 7;//Time of dawn + params.rw = 1;//write + params.type = "node-regular-write"; + params.timestamp = time + 60001; + params.addMinutesToTimestamp = 60 * 3; //kazde 3 hodiny zisti novy dawn + params.info = "Broadcast-dawnTime"; + + tasks.push(params); + } + + { + let params = getParams(); + + params.address = 0xffffffff;//broadcast + params.byte1 = d.getHours(); + params.byte2 = d.getMinutes(); + params.recipient = 2; //2 broadcast + params.register = 87;//Actual time + params.rw = 1;//write + params.type = "node-regular-write"; + params.timestamp = time + 60002; + params.addMinutesToTimestamp = 5; + params.info = "run broadcast: Actual time"; + + tasks.push(params); + } + + } + + //process nodes & tasks - read node's data + if (processNodes) { + + let time = Date.now(); + + for (let k in nodesData) { + let address = parseInt(k); + let tbname = nodesData[k].tbname; + let register = 0; + + for (let i = 0; i < listOfCommands.length; i++) { + + register = listOfCommands[i]; + let addMinutesToTimestamp = priorities[register]; + + let params = getParams(); + + params.address = address; + params.recipient = 1; + params.register = register; + params.type = register == 1 ? "node-dimming-read" : "node-regular-read"; + params.tbname = tbname; + params.timestamp = time + 5000 + i * 500 + addMinutesToTimestamp * 1000; //to make slight time difference + params.addMinutesToTimestamp = addMinutesToTimestamp; + params.info = "Node regular read command"; + + tasks.push(params); + } + + } + } + + + //niektore ulohy sa vygeneruju iba 1x pri starte!!! + if (!init) return; + + + //Master node FW version - modifies SETTINGS.masterNodeIsResponding + { + let params = getParams(); + params.type = "cmd-master"; + params.register = 4; + params.address = 0; + params.timestamp = 0; + params.addMinutesToTimestamp = 5; + params.tbname = SETTINGS.rvoTbName; + params.info = "Master node FW verzia"; + //params.debug = true; + + tasks.push(params); + } + + //kazdu hodinu skontrolovat nastavenie profilov + { + let params = getParams(); + params.type = "process_profiles"; + params.timestamp = Date.now() + 60001; + params.addMinutesToTimestamp = 60;//60 = every hour + params.info = "detekcia nespracovaných profilov linie a nodov"; + //params.debug = true; + + tasks.push(params); + } + + monitor.info("tasks created:", tasks.length); + } + + + /** + * We process line profile, where "astro_clock": true + * example profile: + * + "dawn_lux_sensor": true, + "dusk_lux_sensor": true, + "dawn_lux_sensor_value": 5, + "dusk_lux_sensor_value": 5, + "dawn_astro_clock_offset": 0, + "dusk_astro_clock_offset": 10, + "dawn_lux_sensor_time_window": 30, + "dusk_lux_sensor_time_window": 30, + "dawn_astro_clock_time_window": 60, + "dusk_astro_clock_time_window": 60 + + * if dawn: if currentTimestamp is in timewindow "dawnTime + and - dawn_lux_sensor_time_window" and lux value >= lux_sensor_value, we switch off the line. + * if dusk: we do oposite + * + * dawn: usvit - lux je nad hranicou - vypnem + * dusk: sumrak - lux je pod hranicou - zapnem + */ + 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++) { + + let line = keys[i]; //line is turned off by default + let profilestr = relaysData[line].profile; + const contactor = relaysData[line].contactor; + + try { + + let profile = JSON.parse(profilestr); + if (Object.keys(profile).length === 0) throw ("turnOnOffLinesAccordingToLuxSensor - profile is not defined"); + + 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 (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"); + } + } + } + + //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 (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"); + } + } + } + + } + + } catch (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) { + //MASTER + if (node == 0) return; + + let nodeObj = nodesData[node]; + if (nodeObj == undefined) return; + + let nodeCurrentStatus = nodeObj.status; + const now = Date.now(); + + let data = null; + + if (nodeCurrentStatus === "OFFLINE") { + data = { status: newStatus }; + nodeDbStatusModify(node, data); + return; + } + else 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; + } + + } + + + 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 }; + } + }); + }); + } + + + function processDailyReport() { + + const now = Date.now(); + + for (const [key, value] of Object.entries(dailyReport)) { + + if (["name", "time", "dusk_and_dawn"].includes(key)) continue; + + let poleNumber = nodesData[key]["pole_number"]; + let line = dailyReport[key].line; + let nodeType = nodesData[key]["node_type"]; + let fullNodeName = key // key == nodeNumber + + if (poleNumber && nodeType) { + fullNodeName = SETTINGS.rvo_number + "/" + poleNumber + "_" + line + "L_" + key + "_" + nodeType; + } else { + fullNodeName = key; + } + + if (rvo_is_on) { + + if (value.initialTs) { + if (value.initialTs + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["night_no_data"], fullNodeName); + console.log('report nedostava ziadne data uz hodinu', fullNodeName); + value.initialTs = now; + } + } + if (value.dimmingIsZeroTime) { + if (value.dimmingIsZeroTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["night_dimming=0"], fullNodeName); + console.log("report node dimming je 0 ale ma svietit", fullNodeName); + value.dimmingIsZeroTime = now; + } + } + if (value.powerIsZeroTime) { + if (value.powerIsZeroTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["night_power=0"], fullNodeName); + console.log("report node power je 0 ale ma svietit", fullNodeName); + value.powerIsZeroTime = now; + } + } + + } else { + + let contactorStatus = relaysData[line].contactor; + if (contactorStatus === 1) { + + if (value.initialTs) { + if (value.initialTs + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["day_24/7_no_data"], fullNodeName); + console.log('node je na 24/7 ale nedostava ziadne data uz hodinu', fullNodeName); + value.initialTs = now; + } + } + if (value.dimmingIsOnButShouldBeOffTime) { + if (value.dimmingIsOnButShouldBeOffTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["day_24/7_dimming>0"], fullNodeName); + console.log("report dimming je > 0 ale nema svietit", fullNodeName); + value.dimmingIsOnButShouldBeOffTime = now; + } + } + if (value.powerIsOnButShouldBeOffTime) { + if (value.powerIsOnButShouldBeOffTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["day_24/7_power>0"], fullNodeName); + console.log("report power je > 0 ale nema svietit", fullNodeName); + value.powerIsOnButShouldBeOffTime = now; + } + } + + } + + } + + } + + let report = {}; + report["name"] = SETTINGS.rvo_name; + report["time"] = new Date(); + report["report"] = reportToSend; + + writeToFile(F.path.root("report_data.log"), report, true); + instance.send(SEND_TO.dailyReport, report); + } + + + function dailyReportHandler() { + + if (!SETTINGS.daily_report) return; + + // after dawn we empty reportToSend and start to get data for a new day + const date = new Date(); + const hour = date.getHours(); + const minute = date.getMinutes(); + + console.log("now: ", hour, minute, "suncalc: ", sunCalcResult.dawn_hours, sunCalcResult.dawn_minutes); + + if (hour === sunCalcResult.dawn_hours) { + + //NOTE: ak je este pred usvitom, spracujeme report a posleme na cloud, ak uz je po usvite, resetujeme report plnime data noveho dna + if (minute >= sunCalcResult.dawn_minutes - 2) { + emptyReportToSend(); + emptyDailyReport(); + console.log("Podmienka 1 v dailyReport handler"); + } else { + processDailyReport(); + emptyReportToSend(); + emptyDailyReport(); + console.log("Podmienka 2 v dailyReport handler"); + } + + initialReportStatus = true; + + // ak sa funkcia spusti o hodinu alebo 2 neskor, ako je usvit (moze sa to stat, kedze kazde zapnutie/vypnutie linii odznova spusti casovac. + } else if (hour === sunCalcResult.dawn_hours + 1 || hour === sunCalcResult.dawn_hours + 2) { + if (!initialReportStatus) { + emptyReportToSend(); + emptyDailyReport(); + initialReportStatus = true; + console.log("Podmienka 3 v dailyReport handler"); + } else { + processDailyReport(); + initialReportStatus = true; + console.log("Podmienka 4 v dailyReport handler"); + } + } else { + processDailyReport(); + initialReportStatus = false; + console.log("Podmienka 5 v dailyReport handler"); + } + + console.log("initialReportStatus: ", initialReportStatus); + + } + + function emptyReportToSend() { + emptyJsObject(reportToSend); + reportToSend["contactor"] = { off: [], on: [] }; + reportToSend["night_no_data"] = []; + reportToSend["night_dimming=0"] = []; + reportToSend["night_power=0"] = []; + reportToSend["day_24/7_no_data"] = []; + reportToSend["day_24/7_dimming>0"] = []; + reportToSend["day_24/7_power>0"] = []; + console.log(`resetuje sa reportToSend`); + } + + + //NOTE: ked je initialTs stale rovnaky a zistime ze linie su vypnute (relaysData.line.contactor) - zistim, ci je node na tej linii. Vieme, ze ak je linia vypnuta je to v poriadku lebo nie je na 24/7 linii + //ak je na 24/7 linii, reportujeme, ze neprijima data + function emptyDailyReport() { + const ts = Date.now(); + emptyJsObject(dailyReport); + + //NOTE: do dailyReport dame vsetky nody a pravidelne kontrolujeme ci maju data + //ked nastane sumrak/usvit a svetla maju zacat/prestat svietit, dailyReport spravime nanovo: + for (const [key, value] of Object.entries(nodesData)) { + dailyReport[value.node] = { line: value.line, initialTs: ts }; + } + + console.log("dailyReport: ", dailyReport); + } + + + async function runTasks() { + + clearInterval(interval); + + let currentTimestamp = Date.now(); + + //sort tasks based on timestamp + 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) { + instance.send(SEND_TO.debug, "no tasks created"); + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + if (!rsPort.isOpen) { + instance.send(SEND_TO.debug, "!rsPort.isOpen"); + //await rsPort.open(); + //console.log("Cmd-mngr: !rsPort.isOpen"); + } + + let currentTask = tasks[0]; + + if (currentTask.debug) { + //logger.debug("--->task to process", currentTask); + } + + if (currentTask.timestamp <= currentTimestamp) { + let params = { ...tasks[0] }; + + //allow terminal commands + if (SETTINGS.maintenance_mode && params.type !== "cmd-terminal") { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + let type = params.type; + let tbname = params.tbname; + let node = params.address; + let register = params.register; + let line = null; + let itIsNodeCommand; + + if (nodesData[node] !== undefined) { + line = nodesData[node].line; + itIsNodeCommand = true; + } + + if (params.line !== undefined) line = params.line; + + if (params.addMinutesToTimestamp > 0 || params.timePointName) { + tasks[0].timestamp = currentTimestamp + tasks[0].addMinutesToTimestamp * 60000; + } else { + tasks.shift(); + } + + //kontrola nespracovanych profilov nodov + //TODO: co ked niektore nody neprijimaju profily? kazdu hodinu zahltuju "tasks" array + if (type == "process_profiles") { + //na vsetky zapnutych liniach sa spracuju nespracovane profily nodov + loadRelaysData(); + interval = setInterval(runTasks, SHORT_INTERVAL); + return; + } + + //relay + if (type == "relay") { + + const timePointName = params.timePointName; + const value = params.value; + + let date = new Date(); + date.setDate(date.getDate() + 1);//next day + + let sunCalcResult; + if (timePointName) sunCalcResult = calculateDuskDawn(date, params.line); + + + if (timePointName == "dawn") { + tasks[0].timestamp = sunCalcResult.dawn_time; + } + else if (timePointName == "dusk") { + tasks[0].timestamp = sunCalcResult.dusk_time; + } + else if (timePointName == "luxOn") { + tasks[0].timestamp = sunCalcResult.dusk_time + params.dusk_lux_sensor_time_window * 60000; + } + else if (timePointName == "luxOff") { + tasks[0].timestamp = sunCalcResult.dawn_time + params.dawn_lux_sensor_time_window * 60000; + } + else if (timePointName == "profileTimepoint") { + tasks[0].timestamp = currentTimestamp + tasks[0].addMinutesToTimestamp * 60000; + } + + let info = "aplikovany bod profilu"; + let onOrOff = ""; + value == 1 ? onOrOff = "on" : onOrOff = "off"; + + turnLine(onOrOff, params.line, info); + + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + if (!SETTINGS.masterNodeIsResponding) { + //ak neodpoveda, nebudeme vykonavat ziadne commands, okrem cmd-terminal cmd-master + errorHandler.sendMessageToService("Master node is not responding"); + + let stop = true; + + if (type === "cmd-terminal" || type === "cmd-master") stop = false; + if (stop) { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + } + + let contactorStatus = 1; + if (relaysData[line] != undefined) contactorStatus = relaysData[line].contactor; + + if (line === 0 || contactorStatus === 0 || FLOW.deviceStatus.state_of_breaker[line] === "Off") { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + // TODO: -> status offline for rvo if rotary_switch_state is OFF, this is source of errors + // check if rotary_switch_state == "Off" + // state_of_braker: disconnected = true? + + if (!rsPort.isOpen) { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + //RE-CALCULATE VALUES + //set actual time for broadcast + if (register == 87 && params.recipient === 2) { + var d = new Date(); + params.byte1 = d.getHours();//h + params.byte2 = d.getMinutes();//m + } + + //SET DUSK/DAWN FOR BROADCAST + //Time of dusk + if (register == 6 && params.recipient === 2) { + + if (type != "cmd-terminal") { + params.byte1 = sunCalcResult["dusk_hours"];//h + params.byte2 = sunCalcResult["dusk_minutes"];//m + } + } + + //Time of dawn + if (register == 7 && params.recipient === 2) { + if (type != "cmd-terminal") { + params.byte1 = sunCalcResult["dawn_hours"];//h + params.byte2 = sunCalcResult["dawn_minutes"];//m + } + } + //----------------------- + + instance.send(SEND_TO.debug, "address: " + node + " register:" + register + "type: " + type); + + var startTime, endTime; + startTime = new Date(); + + let saveToTb = true; + if (!tbname) saveToTb = false; + + let resp = com_generic(node, params.recipient, params.rw, register, params.name, params.byte1, params.byte2, params.byte3, params.byte4); + let readBytes = 11; + let timeout = 4000; + + + // await keyword is important, otherwise incorrect data is returned! + await writeData(rsPort, resp, readBytes, timeout).then(function(data) { + + //sometimes happens, that status of node changes to OK, NOK even if line was turned off and should be status OFFLINE. To prevent this, we return if line contactor is 0: + if (itIsNodeCommand && line && relaysData[line].contactor !== 1) return; + + 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); + + //ak sa odpoved zacina 0 - je to v poriadku, inak je NOK + let message = result.message; // OK, NOK + let message_type = result.type; + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + console.log("detected response:", result); + logger.debug("Cmd-mngr: writeData done " + message_type + " duration: " + timeDiff + " type: " + params.debug, params, result); + } + } + + let values = {}; + + //CMD FINISHED + if (message == "OK") { + + updateNodeStatus(node, true); + + //write + if (type == "set_node_profile") { + let result = cmdCounterResolve(node); + if (result == 0) { + dbNodes.modify({ processed: true }).where("node", node).make(function(builder) { + builder.callback(function(err, response) { + + sendNotification("Cmd-mngr: process cmd", SETTINGS.rvoTbName, "dimming_profile_was_successfully_received_by_node", { node: node }, "", SEND_TO.tb, instance); + + logger.debug("--> profil úspešne odoslaný na node č. " + node); + nodesData[node].processed = true; + nodeProfileSendFail.delete(node); + }); + }); + } + } + + //parse read response + if (params.rw == 0) { + values = processResponse(register, dataBytes); //read + } + + if (itIsNodeCommand) { + values.comm_status = "OK"; + values.status = "OK"; + nodesData[node].readout = { ...nodesData[node].readout, ...values }; + + + if (SETTINGS.daily_report) { + //TODO: co ak nedostavame odpovede z nodu ? Musime vyreportovat!! + //v dailyReport teda musi byt kompletny zoznam nodov a neustale kontrolovat, ci maju data, ak nie report node - neodpoveda + if (register === 1) { + + let now = Date.now(); + + if (rvo_is_on === true) { + + if ("dimmingIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].dimmingIsOnButShouldBeOffTime; + + if (values.dimming > 0) { + if ("dimmingIsZeroTime" in dailyReport[node]) delete dailyReport[node].dimmingIsZeroTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if (!("dimmingIsZeroTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], dimmingIsZeroTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } else { + + if ("dimmingIsZeroTime" in dailyReport[node]) delete dailyReport[node].dimmingIsZeroTime; + + if (values.dimming > 0) { + if (!("dimmingIsOnButShouldBeOffTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], dimmingIsOnButShouldBeOffTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if ("dimmingIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].dimmingIsOnButShouldBeOffTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } + } + + if (register === 76) { + + let now = Date.now(); + + if (rvo_is_on === true) { + + if ("powerIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].powerIsOnButShouldBeOffTime; + + if (values.power > 1) { + if ("powerIsZeroTime" in dailyReport[node]) delete dailyReport[node].powerIsZeroTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if (!("powerIsZeroTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], powerIsZeroTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } else { + + if ("powerIsZeroTime" in dailyReport[node]) delete dailyReport[node].powerIsZeroTime; + + if (values.power > 1) { + if (!("powerIsOnButShouldBeOffTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], powerIsOnButShouldBeOffTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if ("powerIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].powerIsOnButShouldBeOffTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } + } + } + + } + + //master node + if (node == 0) { + sendNotification("Cmd-mngr: 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; + } + + if (params.debug) { + //logger.debug("saveToTb", saveToTb, tbname, values); + } + + if (saveToTb && type != "node-regular-read") { + sendTelemetry(values, tbname); + } + else { + if (type == "cmd-terminal") { + terminalCommandResponse(params, "SUCCESS", data); + } + } + + } + else { + terminalCommandResponse(params, "ERROR", data); + handleNokResponseOnRsPort("handleNOK else block", params, itIsNodeCommand, saveToTb); + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + //logger.debug("writeData err: ", error, result, params); + logger.debug("writeData err: ", tbname, node, register, values); + } + } + + //logger.debug(error, result, params); + } + }).catch(function(reason) { + + //console.log("writeData catch exception", reason); + instance.send(SEND_TO.debug, reason); + + terminalCommandResponse(params, "FAILURE", null, reason); + handleNokResponseOnRsPort("handleNOK catch block", params, itIsNodeCommand, saveToTb); + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + logger.debug("-->WRITE FAILED: " + reason, params.debug, params); + } + } + + }); + + } + 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); + } + + + // if node does not respond to request, we repeat request 3 times: + function repeatCommand(params) { + params.repeatCounter++; + if (params.repeatCounter < 4) { + params.timestamp = 0; + params.addMinutesToTimestamp = 0; + tasks.push(params); + } + } + + function handleNokResponseOnRsPort(message, params, itIsNodeCommand, saveToTb) { + + let node = params.address; + let register = params.register; + let type = params.type; + let tbName = params.tbname; + if (!tbName) return; + + let values = {}; + + let updateStatus = updateNodeStatus(node, false); + + if (itIsNodeCommand) { + values.comm_status = "NOK"; + nodesData[node].readout.comm_status = "NOK"; + repeatCommand(params); + } + + if (updateStatus) { + values.status = "NOK"; + nodesData[node].readout.status = "NOK"; + } + + if (type === "node-regular-read") return; + + //master node + if (node == 0) { + sendNotification("Cmd-mngr: 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; + + if (register == 4) values["master_node_version"] = "NOK"; + } + + if (type == "set_node_profile") { + delete cmdCounter[node]; + logger.debug("profil nebol úspešne odoslaný na node č. ", params); + + if (!nodeProfileSendFail.has(node)) { + sendNotification("Cmd-mngr: process cmd", tbName, "configuration_of_dimming_profile_to_node_failed", { node: node }, "", SEND_TO.tb, instance); + nodeProfileSendFail.add(node); + } + } + + // console.log("------",node, register, type, itIsNodeCommand, updateStatus, saveToTb, values); + if (saveToTb) { + sendTelemetry(values, tbName); + } + + } + + + function sendNodesData() { + Object.keys(nodesData).forEach(node => { + if (nodesData[node]["status"] !== "OFFLINE") { + sendTelemetry(nodesData[node].readout, nodesData[node].tbname); + nodesData[node].readout = {}; + } + }) + } + + + /** + * 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; + } + + 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); + + //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 === "OFFLINE") { + nodeObj.node_status_before_offline === true ? number_of_ok_luminaires++ : number_of_nok_luminaires++; + } + else if (nodeObj.status == true) 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 - ts % 60000 //round to full minute + }; + + sendTelemetry(values, SETTINGS.rvoTbName, ts); + } + + + function setSunCalcResult() { + //if next day, we get new dusk and dawn. To make sure, in local timezone 2:00 means 00:00 in utc (it means next day) + if (new Date().getHours() === 2) { + sunCalcResult = calculateDuskDawn(); + console.log("Novy suncalc: ", sunCalcResult); + } + } + + + function setRvoPeriod() { + + if (!SETTINGS.daily_report) return; + + const ts = Date.now(); + + previous_rvo_is_on_value = rvo_is_on; + + if (ts < sunCalcResult.dawn_time - 1_800_000) { // nodes should be on (00:00 -> 06:00 ( - pol hodina, lebo rvo vypina skor) + rvo_is_on = true; + } else if (sunCalcResult.dawn_time - 1_800_000 < ts && ts < sunCalcResult.dusk_time + 1_800_000) { // nodes should be off 06:00 -> 21:00 + rvo_is_on = false; + } else if (sunCalcResult.dusk_time + 1_800_000 < ts) { // nodes should be on 21:00 -> 00:00 + rvo_is_on = true; + } + + if (previous_rvo_is_on_value !== rvo_is_on) { + emptyDailyReport(); + console.log("rvo_is: ", rvo_is_on, previous_rvo_is_on_value); + } + } + + + function handleRsPort() { + + if (rsPort) { + rsPort.removeAllListeners(); + rsPort = null; + } + + //! 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-mngr: rsPort opened success"); + + 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); + + }).catch(function(reason) { + instance.send(SEND_TO.debug, "Cmd-mngr: RPC runSyncExec - promise rejected:" + reason); + }); + }); + + rsPort.on('error', function(err) { + errorHandler.sendMessageToService([exports.title, "unable to open port", SETTINGS.serial_port, err.message], 0); + monitor.info("Cmd-mngr: Error on rsPort", err.message); + }); + + rsPort.on("close", () => { + monitor.info("Cmd-mngr: rsPort closed, reconnecting..."); + setTimeout(handleRsPort, 1000); + }); + + rsPort.open(); + } + + + instance.on("close", () => { + clearInterval(interval); + clearInterval(customTasksInterval); + clearInterval(setCorrectTime); + clearInterval(sendNodeReadout); + clearInterval(accelerometerInterval); + rsPort.close(); + }); + + instance.on("0", _ => { + main(); + }) + + + instance.on("2", _ => { + console.log("dailyReport, reportToSend, rvo_is_on", dailyReport, reportToSend, rvo_is_on, previous_rvo_is_on_value); + }) + + instance.on("1", 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(); + return; + } + else if (flowdata.data == "close") { + rsPort.close(); + return; + } + else if (flowdata.data == "clean") { + tasks = []; + return; + } + else if (flowdata.data == "buildtasks") { + //build & run + return; + } + else if (flowdata.data == "run") { + //durations = []; + + if (tasks.length == 0) { + + buildTasks(); + + if (rsPort.isOpen) { + interval = setInterval(runTasks, 100); + } + else { + instance.send(SEND_TO.debug, "port is not opened!!!"); + } + } + } + else { + //terminal data - object + //logger.debug("flowdata", flowdata.data); + + if (typeof flowdata.data === 'object') { + //logger.debug("dido", flowdata.data); + if (flowdata.data.hasOwnProperty("sender")) { + //data from dido_controller + if (flowdata.data.sender == "dido_controller") { + + if (flowdata.data.hasOwnProperty("cmd")) { + let cmd = flowdata.data.cmd; + + if (cmd == "buildTasks") { + clearInterval(interval); + + logger.debug("-->Cmd-mngr: BUILD TASKS"); + buildTasks(); + + //logger.debug("tasks:"); + //logger.debug(tasks); + + logger.debug("-->Cmd-mngr: RUN TASKS"); + interval = setInterval(runTasks, 5000); + } + else if (cmd == "reload_relays") { + loadRelaysData(flowdata.data.line); + + if (flowdata.data.dataChanged) { + if (!flowdata.data.value) { + reportOfflineNodeStatus(flowdata.data.line); + } + else { + reportOnlineNodeStatus(flowdata.data.line); + } + } + + } + else if (cmd == "rotary_switch_state") { + let value = flowdata.data.value; + + //state was changed + if (rotary_switch_state != value) { + if (value == "Off") { + //vyreportovat vsetky svietdla + reportOfflineNodeStatus(); + } + + rotary_switch_state = value; + } + } + 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) { + + // we send lux_sensor value to all nodes: + let params = getParams(PRIORITY_TYPES.node_broadcast); + + params.recipient = 2;//2 broadcast, address = 0 + params.address = 0xffffffff;//Broadcast + + let ba = longToByteArray(lux_sensor); + + params.byte3 = ba[1];//msb + params.byte4 = ba[0]; + params.timestamp = PRIORITY_TYPES.node_broadcast; + params.info = "run broadcast: Actual Lux level from cabinet"; + params.register = 95;//Actual Lux level from cabinet + params.rw = 1;//write + + tasks.push(params); + + //process profiles + turnOnOffLinesAccordingToLuxSensor(lux_sensor); + } + } + else if (cmd == "state_of_breaker") { + //istic linie + + breakerCounter--; + + let value = flowdata.data.value; + let line = parseInt(flowdata.data.line); + + let dataChanged = false; + if (state_of_breaker[line] != value) dataChanged = true; + + state_of_breaker[line] = value; + + let status = "OK"; + if (value == "Off") status = "NOK"; + + if (dataChanged) { + + if (relaysData.hasOwnProperty(line)) { + let tbname = relaysData[line].tbname; + + if (value == "Off") { + sendNotification("Cmd-mngr: onData", tbname, "circuit_breaker_was_turned_off_line", { line: line }, "", SEND_TO.tb, instance, "circuit_breaker"); + if (breakerCounter < 0) reportToSend["contactor"]["off"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + else { + sendNotification("Cmd-mngr: onData", tbname, "circuit_breaker_was_turned_on_line", { line: line }, "", SEND_TO.tb, instance, "circuit_breaker"); + if (breakerCounter < 0) reportToSend["contactor"]["on"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + + //report status liniu + sendTelemetry({ status: status }, tbname) + + //current value + if (value == "Off") reportOfflineNodeStatus(line); //vyreportovat vsetky svietidla na linii + } + + } + } + else { + logger.debug("undefined cmd", cmd); + } + } + } + + return; + } + + //data from worksys + if (flowdata.data.hasOwnProperty("topic")) { + + let data = getNested(flowdata.data, "content", "data"); + + //if we get temperature in senica from senica-prod01 + let temperature = getNested(flowdata.data, "content", "senica_temperature"); + + if (temperature !== undefined) { + temperatureInSenica = temperature; + return; + } + + if (data === undefined) { + console.log("Invalid rpc command came from platform"); + return; + } + + let command = data.params.command; + let method = data.method; + let profile = data.params.payload; + if (profile == undefined) profile = ""; + let entity = data.params.entities[0]; + let entity_type = entity.entity_type; + let tbname = entity.tb_name; + + instance.send(SEND_TO.debug, flowdata.data); + 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") { + + //let command = data.params.command; + let value = data.params.payload.value; + + if (command == "dimming") { + + let nodeWasFound = false; + let keys = Object.keys(nodesData); + + //logger.debug("-----", keys); + + 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); + + value = parseInt(value); + if (value > 0) value = value + 128; + + params.type = "node-onetime-write"; + params.tbname = tbname; + params.address = node; + params.register = 1; + params.recipient = 1; + params.byte4 = value; + params.rw = 1; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'set dimming from platform'; + //params.debug = true; + + //debug(params); + logger.debug("dimming", params); + + tasks.push(params); + + 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); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 1; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read dimming (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + //pridame aj vyreportovanie - vykon + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 76; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read Input Power (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + //pridame aj vyreportovanie - prud svietidla + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 75; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read Input Current (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + //pridame aj vyreportovanie - power faktor - ucinnik + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 77; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read power factor (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + }, 4000); + + nodeWasFound = true; + break; + } + } + + if (!nodeWasFound) { + logger.debug("set dimming from platform", "unable to find tbname", tbname); + } + } + else { + instance.send(SEND_TO.debug, "undefined command " + command); + logger.debug("undefined command", command); + } + + return; + } + 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++) { + let node = keys[i]; + if (tbname == nodesData[node].tbname) { + + 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"); + + //profil úspešne prijatý pre node č. xx + sendNotification("Cmd-mngr", tbname, "dimming_profile_was_processed_for_node", { node: node }, profile, SEND_TO.tb, instance); + + nodesData[node].processed = false; + nodesData[node].profile = profile; + + processNodeProfile(node); + }); + }); + } + } + } + else { + + instance.send(SEND_TO.debug, "unknown method " + method); + logger.debug("unknown method", method); + + return; + } + } + + //nastav profil linie z platformy + 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") { + + 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++) { + let line = keys[i]; + if (tbname == relaysData[line].tbname) { + //zmazeme tasky + 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) { + + //update profile + logger.debug("worksys - update relay profile done:", profile); + instance.send(SEND_TO.debug, "worksys - update relay profile done"); + + relaysData[line].profile = profile; + + loadRelaysData(line) + logger.debug("loadRelaysData DONE for line", line); + + buildTasks({ processLineProfiles: true, line: line }); + + sendNotification("Cmd-mngr: set profile from worksys", tbname, "switching_profile_was_processed_for_line", { line: line }, profile, SEND_TO.tb, instance); + }); + }); + break; + } + } + } + else if (method == "set_command") { + let value = data.params.payload.value; + + 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; + + 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"); + if (line != 0) reportToSend["contactor"]["off"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + else { + turnLine("on", line, "command received from platform"); + if (line != 0) reportToSend["contactor"]["on"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + } + } + else { + instance.send(SEND_TO.debug, "undefined method " + method); + logger.debug("undefined method", method); + } + + return; + } + else { + instance.send(SEND_TO.debug, "UNKNOW entity_type " + entity_type); + logger.debug("UNKNOW entity_type", entity_type); + } + return; + } + + //terminal + if (!rsPort.isOpen) await rsPort.open(); + + let params = flowdata.data.body; + if (params == undefined) { + //logger.debug("Cmd-mngr: flowdata.data.body is undefined"); + return; + } + + params.priority = PRIORITY_TYPES.terminal; + params.type = "cmd-terminal"; + params.tbname = ""; + params.timestamp = PRIORITY_TYPES.terminal; + params.addMinutesToTimestamp = 0;// do not repeat task!!! + params.debug = true; + + let timestamp = Date.now(); + params.refFlowdataKey = timestamp; + //params.refFlowdata = flowdata; + //refFlowdata = flowdata; + + //console.log("flowdata", flowdata); + + cleanUpRefFlowdataObj(); + + refFlowdataObj[timestamp] = flowdata; + + //fix + //params.address = params.adress; + logger.debug("received from terminal", params); + logger.debug("date/time:", new Date()); + logger.debug("tasks length:", tasks.length); + + //tasks = []; + + //add to tasks + tasks.push(params); + + } + } + }) + + + //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) + } + + + /** + * 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; + + RESTBuilder.make(function(builder) { + + if (!builder) return; + + builder.method('GET'); + builder.url('http://192.168.252.2:8004/gettime?projects_id=1'); + + builder.callback(function(err, response, output) { + + 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); + } + + }); + } + + } 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); + + } else { + //console.log("Read-only", stdout); + + 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]: [ + { + "ts": date, + "values": values + } + ] + } + + tbHandler.sendToTb(dataToTb, instance); + } + + + function calculateDuskDawn(date, line, duskOffset = 0, dawnOffset = 0) { + + if (date === undefined) date = new Date(); + + 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); + } + + //if(profile.dawn_lux_sensor == false) + { + if (profile.hasOwnProperty("dawn_astro_clock_offset")) dawn_astro_clock_offset = parseInt(profile.dawn_astro_clock_offset); + } + + } + + } catch (error) { + if (profilestr != "") { + logger.debug(profilestr); + logger.debug(error); + } + } + + 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; + } + + //Dimming, CCT + else if (register == 1) { + let brightness = 0; + let dimming = byte0; + if (dimming > 128) { + //dimming = -128; + brightness = dimming - 128; + } + + //cct + //Ak Byte3 == 1: CCT = (Byte2*256)+Byte1 + let cct; + if (byte3 == 1) cct = byte2 * 256 + byte1; + else cct = bytesToInt(bytes.slice(0, 3)); + + //cct podla auditu + + values["dimming"] = brightness; + return values; + } + + // + else if (register == 4) { + values["master_node_version"] = bytes[1] + "." + bytes[2]; + //logger.debug("FW Version", register, bytes); + } + + //Napätie + else if (register == 74) { + let voltage = (bytesToInt(bytes) * 0.1).toFixed(1); + values["voltage"] = Number(voltage); + } + + //Prúd + else if (register == 75) { + let current = bytesToInt(bytes); + values["current"] = current; + } + + //výkon + else if (register == 76) { + let power = (bytesToInt(bytes) * 0.1).toFixed(2); + values["power"] = Number(power); + } + + //účinník + else if (register == 77) { + let power_factor = Math.cos(bytesToInt(bytes) * 0.1 * (Math.PI / 180)).toFixed(2); + values["power_factor"] = Number(power_factor); + } + + //frekvencia + else if (register == 78) { + let frequency = (bytesToInt(bytes) * 0.1).toFixed(2); + values["frequency"] = Number(frequency); + } + + //energia + else if (register == 79) { + let energy = bytesToInt(bytes); + values["energy"] = energy / 1000; //energia v kWh -> delit 1000 + } + + //doba života + else if (register == 80) { + let lifetime = (bytesToInt(bytes) / 60).toFixed(2); + values["lifetime"] = Number(lifetime); + } + + //nastavenie profilu + else if (register == 8) { + let time_schedule_settings = bytesToInt(bytes); + values["time_schedule_settings"] = time_schedule_settings; + } + + //naklon - nateraz sa z nodu nevycitava! kvoli problemom s accelerometrom a vracanymi hodnotami, posielame temp a x y z vo funkcii accelerometerData() + else if (register == 84) { + values["temperature"] = byte3 >= 128 ? (byte3 - 128) * (-1) : byte3; + values["inclination_x"] = byte2 >= 128 ? (byte2 - 128) * (-1) : byte2; + values["inclination_y"] = byte1 >= 128 ? (byte1 - 128) * (-1) : byte1; + values["inclination_z"] = byte0 >= 128 ? (byte0 - 128) * (-1) : byte0; + } + + //FW verzia nodu + else if (register == 89) { + //formát: "Byte3: Byte2.Byte1 (Byte0)" + values["fw_version"] = byte3 + ":" + byte2 + "." + byte1 + "(" + byte0 + ")"; + } + + else if (register == 87 || register == 6 || register == 7) { + var d = new Date(); + d.setHours(byte3, byte2, 0, 0); + let timestamp = d.getTime(); + + //aktuálny čas + if (register == 87) values["actual_time"] = timestamp; + //čas súmraku + else if (register == 6) values["dusk_time"] = timestamp; + //čas úsvitu + else if (register == 7) values["dawn_time"] = timestamp; + } + + 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; + + } + + + function getObjectByTbValue(object, tbname) { + return object[Object.keys(object).find(key => object[key].tbname === tbname)]; + } + + + function isObject(item) { + return (typeof item === "object" && !Array.isArray(item) && item !== null); + } + + + // we fake data, that should be received from accelerometer, as they are a bit unreliable. (temperature, x,y,z) + function accelerometerData() { + + if (temperatureInSenica === null) return; + + //clone nodesData and relaysData objects + let nodesData_clone = JSON.parse(JSON.stringify(nodesData)); + let relaysData_clone = JSON.parse(JSON.stringify(relaysData)); + + for (const key in relaysData_clone) { + + const lineData = relaysData_clone[key]; + const lineNumber = lineData.line; + const contactor = lineData.contactor; + + if (lineNumber === 0) continue; + + if (contactor === 1) { + + let date = Date.now(); + + Object.keys(nodesData_clone).forEach((node, index) => { + + setTimeout(function() { + + if (nodesData_clone[node].line === lineNumber) { + + // NOTE: if status of luminaire is NOK or OFFLINE, we do not send data; + let status = nodesData_clone[node].status; + if (status === "OFFLINE" || !status) return; + + let x = null; + if (naklony.hasOwnProperty(node)) x = naklony[node].naklon; + if (x === null) x = 0; + + sendTelemetry({ temperature: Math.round(temperatureInSenica + 10 + Math.floor(Math.random() * 3)), inclination_x: x, inclination_y: 0, inclination_z: 0 }, nodesData_clone[node].tbname, date); + } + + }, (index + 1) * 500); + }) + + } + } + } + + +} // end of instance.export + diff --git a/RVO48/flow/code.js b/RVO48/flow/code.js new file mode 100755 index 0000000..63b31bf --- /dev/null +++ b/RVO48/flow/code.js @@ -0,0 +1,90 @@ +exports.id = 'code'; +exports.title = 'Code'; +exports.group = 'Common'; +exports.color = '#656D78'; +exports.input = true; +exports.output = 1; +exports.author = 'Peter Širka'; +exports.icon = 'code'; +exports.version = '1.2.0'; +exports.options = { outputs: 1, code: 'send(0, value);', keepmessage: true }; + +exports.html = `
+
+
+
@(Number of outputs)
+
@(Minimum is 1)
+
+
+
@(Code)
+
@(Keep message instance)
+
+`; + +exports.readme = `# Code + +This component executes custom JavaScript code as it is and it doesn't contain any secure scope. + +\`\`\`javascript +// value {Object} contains received data +// send(outputIndex, newValue) sends a new value +// error(value) sends an error +// instance {Object} a current component instance +// flowdata {Object} a current flowdata +// repository {Object} a current repository of flowdata +// Example: + +// send() can be execute multiple times +send(0, value); +\`\`\``; + +exports.install = function(instance) { + + var fn; + + instance.on('data', function(response) { + if (fn) { + try { + fn(response.data, instance, response, instance.options, response.repository, require); + } catch (e) { + response.data = e; + instance.throw(response); + } + } + }); + + instance.reconfigure = function() { + try { + if (instance.options.code) { + instance.status(''); + var code = 'var send = function(index, value) { if (options.keepmessage) { flowdata.data = value; instance.send2(index, flowdata); } else instance.send2(index, value);}; var error = function(err) { instance.throw(err); }; ' + instance.options.code; + fn = new Function('value', 'instance', 'flowdata', 'options', 'repository', 'require', code); + } else { + instance.status('Not configured', 'red'); + fn = null; + } + } catch (e) { + fn = null; + instance.error('Code: ' + e.message); + } + }; + + instance.on('options', instance.reconfigure); + instance.reconfigure(); +}; \ No newline at end of file diff --git a/RVO48/flow/comment.js b/RVO48/flow/comment.js new file mode 100755 index 0000000..1e0cd13 --- /dev/null +++ b/RVO48/flow/comment.js @@ -0,0 +1,11 @@ +exports.id = 'comment'; +exports.title = 'Comment'; +exports.group = 'Common'; +exports.color = '#704cff'; +exports.author = 'Martin Smola'; +exports.icon = 'comment'; +exports.traffic = false; +exports.version = '1.0.0'; +exports.readme = '# Comment'; + +exports.install = function() {}; diff --git a/RVO48/flow/count.js b/RVO48/flow/count.js new file mode 100755 index 0000000..fa92ee9 --- /dev/null +++ b/RVO48/flow/count.js @@ -0,0 +1,60 @@ +exports.id = 'count'; +exports.title = 'Count'; +exports.version = '1.0.1'; +exports.author = 'John Graves'; +exports.color = '#656D78'; +exports.icon = 'plus-square'; +exports.input = 2; +exports.output = 1; +exports.options = { increment: 1, initialvalue: 1 }; +exports.readme = `# Counter + +Counter Number of times called.`; + +exports.html = `
+
@(Initial Value)
+
@(Increment)
+

Example Video

+
`; + +exports.readme = `# Count + +This component counts the number of messages received. + +__Response:__ + +Integer value based on the initial value and increment settings. + +__Arguments:__ +- Initial Value: What number should be output on the receipt of the first message. +- Increment: What should the increment be for each following message received.`; + +exports.install = function(instance) { + + var count = 0; + var initialCall = true; + + instance.on('data', function(flowdata) { + var index = flowdata.index; + if (index) { + instance.debug('Reset Count.'); + count = instance.options.initialvalue; + initialCall = true; + } else { + // If this is the first time, set the value to 'initial value' + if(initialCall) { + initialCall = false; + count = instance.options.initialvalue; + } else + count = count+instance.options.increment; + instance.status('Count:' + count); + instance.send2(count); + } + }); + + instance.on('options', function() { + count = instance.options.initialvalue; + initialCall = true; + }); + +}; diff --git a/RVO48/flow/db_connector.js b/RVO48/flow/db_connector.js new file mode 100755 index 0000000..65ee94b --- /dev/null +++ b/RVO48/flow/db_connector.js @@ -0,0 +1,286 @@ +exports.id = 'db_connector'; +exports.title = 'DbConnector'; +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.html = `
+
+
+
DbConnector
+
+
+
`; + +exports.readme = `# read/write data to tables`; + +const instanceSendTo = { + debug: 0, + http_response: 1, +} + +const { promisifyBuilder, makeMapFromDbResult } = require('./helper/db_helper.js'); + +function extractWhereParams(params) +{ + let name = params[0]; + let operator = '='; + let value = params[1]; + + if(params.length == 3) + { + operator = params[1]; + value = params[2]; + } + + return {name: name, operator: operator, value: value}; +} + +exports.install = function(instance) { + + let refFlowdata = null;//holds reference to httprequest flowdata + + instance.on("close", () => { + + }) + + + instance.on("data", async function(flowdata) { + + let params = flowdata.data.body; + console.log("DbConnector", params); + + refFlowdata = flowdata; + + if(refFlowdata != undefined) + { + //make http response + let responseObj = {}; + responseObj["type"] = "SUCESS"; + + try{ + + let table = params.table; + let action = params.action; + + + if(params.data != undefined) + { + let className = params.data.className; + + if(className == "SqlQueryBuilder") + { + let type = params.data.type; + + console.log("SqlQueryBuilder---->", params.data); + + if(type == "SELECT") + { + let table = params.data.queryData.tables[0].table; + + const db = TABLE(table); + var builder = db.find(); + + let result = await promisifyBuilder(builder); + + let response = {}; + response["result"] = result; + response["success"] = true; + + responseObj["data"] = response; + + //console.log(responseObj); + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + } + + return; + } + } + + + console.log("db_connector---->", table, action); + + //actions: read, replace, insert, delete, update... + + if(action == "read") + { + const db = TABLE(params.table); + + //where builder.where('age', '<', 15); + //builder.where('id', 3403); + + var builder = db.find(); + + //https://docs.totaljs.com/latest/en.html#api~DatabaseBuilder~builder.where + if(params.hasOwnProperty("where")) + { + //optionalCan contain "=", "<=", "<", ">=", ">". + //Default value: '=' + + //1.["production_line", 1] + //2. ["or", ["production_line", 1], ["production_line", 2], "end"] + + if (Array.isArray(params.where)) { + + let multipleConditions = false; + + if(params.where[0] == "or") multipleConditions = true; + if (Array.isArray(params.where[0])) multipleConditions = true; + + if(multipleConditions) + { + + for(var i = 0; i < params.where.length; i++) + { + const item = params.where[i]; + + if(item === "or") builder.or(); + + if (Array.isArray(item)) + { + const { name, operator, value } = extractWhereParams(item); + builder.where(name, operator, value); + } + + if(item === "end") builder.end(); + + } + + } + else + { + const { name, operator, value } = extractWhereParams(params.where); + builder.where(name, operator, value); + } + + } + + /* + if(params.where.length >=2 ) + { + let name = params.where[0]; + let operator = '='; + let value = params.where[1]; + + if(params.where.length == 3) + { + operator = params.where[1]; + value = params.where[2]; + } + + builder.where(name, operator, value); + } + */ + } + + if(params.hasOwnProperty("between")) + { + builder.between(params.between[0], params.between[1], params.between[2]); + } + + let response = await promisifyBuilder(builder); + responseObj["data"] = response; + + //console.log(responseObj); + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + + return; + } + + if(action == "delete") + { + + } + + + if(action == "update") + { + //! data receiving from terminal (params) + // { + // hostname: 'localhost', + // table: 'settings', + // action: 'update', + // body: { + // rvo_name: 'terrrr', + // lang: 'en', + // temperature_adress: '28.427B45920702', + // latitude: 48.70826502, + // longitude: 17.28455203, + // mqtt_host: '192.168.252.4', + // mqtt_clientid: 'showroom_test_panel_led', + // mqtt_username: 'xmRd6RJxW53WZe4vMFLU', + // mqtt_port: 1883, + // maintanace_mode: false + // } + // } + const tableToModify = TABLE(params.table); + const newValues = params.body; + + tableToModify.modify(newValues).make(function(builder) { + + builder.callback(function(err, response) { + + if(!err) + { + responseObj["data"] = response; + responseObj["tableUpdated"] = true; + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + } + }); + }); + + } + + if(action == "replace") + { + //truncate table + const db = TABLE(params.table); + var builder = db.remove(); + db.clean(); + + //insert data + let data = params.data; + + for(let i = 0; i < data.length; i++) + { + //console.log(data[i]); + db.insert(data[i]); + } + + console.log("insert done"); + + let responseObj = {}; + responseObj["type"] = "SUCESS"; + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + + + } + + + + } catch (error) { + //console.log(error); + responseObj["type"] = "ERROR"; + responseObj["message"] = error; + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + } + } + }) +} + + diff --git a/RVO48/flow/db_init.js b/RVO48/flow/db_init.js new file mode 100755 index 0000000..b399878 --- /dev/null +++ b/RVO48/flow/db_init.js @@ -0,0 +1,113 @@ +exports.id = 'db_init'; +exports.title = 'DB Initialization'; +exports.group = 'Worksys'; +exports.color = '#888600'; +exports.version = '1.0.2'; +exports.icon = 'sign-out'; +exports.output = 2; + +exports.readme = ` + # DB initialization +`; + +const { promisifyBuilder, makeMapFromDbResult } = require('./helper/db_helper.js'); +const { initNotification } = require('./helper/notification_reporter'); +const errorHandler = require('./helper/ErrorToServiceHandler'); +const total_energy = require('../databases/total_energy'); + +const SEND_TO = { + db_init: 0, + infoSender: 1 +}; + + +exports.install = async function(instance) { + const dbNodes = TABLE("nodes"); + const dbRelays = TABLE("relays"); + const dbSettings = TABLE("settings"); + 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 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.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"]; + Object.keys(dbs.nodesData).forEach(node => dbs.nodesData[node].readout = {}) + + let rvo_number = responseSettings[0]["rvo_name"].match(/\D+(\d{1,2})_/)[1]; + + dbs.settings = { + edge_fw_version: "2025-10-08", //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"], + phases: responseSettings[0]["phases"], + cloud_topic: responseSettings[0]["cloud_topic"], + has_main_switch: responseSettings[0]["has_main_switch"], + daily_report: responseSettings[0]["daily_report"], + send_changed_node_numbers: responseSettings[0]["send_changed_node_numbers"], + rvo_number: rvo_number, + + //dynamic values + masterNodeIsResponding: true, //cmd_manager + maintenance_mode: false, + } + + + dbs.settings.energy_to_switch_lamps = total_energy[rvo_number]; + if (dbs.settings.energy_to_switch_lamps === undefined) console.log('=============== db_init.js: energy_to_switch_lamps is undefined'); + + FLOW.dbLoaded = true; + errorHandler.setProjectId(dbs.settings.project_id); + initNotification(); + + //APP START - send to data services + const toService = { + id: dbs.settings.project_id, + name: dbs.settings.rvo_name, + fw_version: dbs.settings.edge_fw_version, + startdate: new Date().toISOString().slice(0, 19).replace('T', ' '), + js_error: "", + error_message: "" + }; + + instance.send(SEND_TO.infoSender, toService); + console.log("----------------> START - message send to service", toService); + + setTimeout(() => { + console.log("DB_INIT - data loaded"); + instance.send(SEND_TO.db_init, "_") + }, 5000) + +}; + diff --git a/RVO48/flow/debug.js b/RVO48/flow/debug.js new file mode 100755 index 0000000..00cb259 --- /dev/null +++ b/RVO48/flow/debug.js @@ -0,0 +1,100 @@ +exports.id = 'debug'; +exports.title = 'Debug'; +exports.author = 'Peter Širka'; +exports.color = '#967ADC'; +exports.click = true; +exports.input = true; +exports.icon = 'bug'; +exports.version = '2.0.4'; +exports.options = { enabled: true, repository: false, type: 'data' }; +exports.readme = `# Debug + +Prints data to the debug tab.`; + +exports.html = `
+
+
+
@(Output type)
+
@(Path to the property (leave empty to show the whole data object))
+
@(A group name)
+
@(Enabled)
+
+
+
`; + +exports.install = function(instance) { + + instance.on('data', function(response) { + if (instance.options.enabled) { + + var opt = instance.options; + var rep = response.repository; + var val = response.data; + var id = response.id; + + switch (instance.options.type){ + case 'both': + var data = {}; + data.repository = rep; + data.data = val instanceof Error ? { error: val.message, stack: val.stack } : val; + instance.debug(safeparse(opt.property ? U.get(data, opt.property) : data), undefined, opt.group, id); + break; + case 'repository': + instance.debug(safeparse(opt.property ? U.get(rep, opt.property) : rep), undefined, opt.group, id); + break; + case 'data': + default: + if (val instanceof Error) + instance.debug({ error: val.message, stack: val.stack }, undefined, opt.group, id); + else + instance.debug(safeparse(opt.property ? U.get(val, opt.property) : val), undefined, opt.group, id); + break; + } + } + }); + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + instance.save(); + }); + + instance.on('options', function() { + instance.custom.status(); + }); + + instance.custom.status = function() { + instance.status(instance.options.enabled ? 'Enabled' : 'Disabled'); + }; + + instance.custom.status(); + + function safeparse(o) { + + if (o instanceof Buffer) + return o; + + if (o === undefined) + return 'undefined'; + + if (o === null) + return 'null'; + + var cache = []; + var str = JSON.stringify(o, function(key, value) { + if (typeof value === 'object' && value !== null) { + if (cache.indexOf(value) !== -1) { + try { + return JSON.parse(JSON.stringify(value)); + } catch (error) { + return; + } + } + cache.push(value); + } + return value; + }); + cache = null; + return JSON.parse(str); + } +}; diff --git a/RVO48/flow/designer.json b/RVO48/flow/designer.json new file mode 100755 index 0000000..580f5a3 --- /dev/null +++ b/RVO48/flow/designer.json @@ -0,0 +1,3102 @@ +{ + "tabs": [ + { + "name": "MAIN PUSH", + "linker": "main-push", + "id": "1612772287426", + "index": 0 + }, + { + "name": "CMD manager", + "linker": "cmd-manager", + "id": "1615551125555", + "index": 1 + }, + { + "name": "Devices", + "linker": "devices", + "id": "1611921777196", + "index": 2 + } + ], + "components": [ + { + "id": "1611951142547", + "component": "debug", + "tab": "1611921777196", + "name": "ERROR", + "x": 598, + "y": 60, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#DA4453", + "notes": "" + }, + { + "id": "1612776786008", + "component": "wsmqttpublish", + "tab": "1612772287426", + "name": "WS MQTT publish", + "x": 281.75, + "y": 174, + "connections": { + "0": [ + { + "index": "0", + "id": "1615551060773" + } + ], + "1": [ + { + "index": "0", + "id": "1618300858252" + }, + { + "index": "0", + "id": "1618558465485" + } + ], + "2": [ + { + "index": "0", + "id": "1634303685503" + } + ], + "3": [ + { + "index": "0", + "id": "1731068754606" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Connected", + "color": "green" + }, + "options": { + "username": "", + "clientid": "", + "port": "1883", + "host": "" + }, + "color": "#888600", + "notes": "" + }, + { + "id": "1612778461252", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "tb-push", + "x": 72.75, + "y": 328, + "connections": { + "0": [ + { + "index": "0", + "id": "1612783322136" + }, + { + "index": "1", + "id": "1612776786008" + }, + { + "index": "0", + "id": "1731068754606" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1612783322136", + "component": "debug", + "tab": "1612772287426", + "name": "to TB", + "x": 283.75, + "y": 324, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615551060773", + "component": "debug", + "tab": "1612772287426", + "name": "errors from MQTT Broker", + "x": 594, + "y": 57, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#DA4453", + "notes": "" + }, + { + "id": "1615563373927", + "component": "debug", + "tab": "1615551125555", + "name": "Debug", + "x": 755, + "y": 155, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#DA4453", + "notes": "" + }, + { + "id": "1615566865233", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "tb-push", + "x": 755, + "y": 248, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1615798582262", + "component": "debug", + "tab": "1615551125555", + "name": "CMD_debug", + "x": 755, + "y": 346, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615802995322", + "component": "debug", + "tab": "1611921777196", + "name": "Debug", + "x": 596.8833312988281, + "y": 566.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Disabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": false + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615809128443", + "component": "debug", + "tab": "1611921777196", + "name": "tempToTb", + "x": 595.8833312988281, + "y": 658.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615809595184", + "component": "virtualwireout", + "tab": "1611921777196", + "name": "tb-push", + "x": 597.8833312988281, + "y": 377.25, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1616165795916", + "component": "httproute", + "tab": "1615551125555", + "name": "POST /terminal", + "x": 135, + "y": 547, + "connections": { + "0": [ + { + "index": "0", + "id": "1684060205000" + }, + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Listening", + "color": "green" + }, + "options": { + "timeout": 10, + "cachepolicy": 0, + "cacheexpire": "5 minutes", + "size": 5, + "url": "/terminal", + "method": "POST", + "name": "", + "flags": [ + "id:1616165795916", + "post", + 10000 + ], + "emptyresponse": false + }, + "color": "#5D9CEC", + "notes": "### Configuration\n\n- __POST /terminal__\n- flags: \n- maximum request data length: __5 kB__\n- empty response: __false__\n- cache policy: __no cache__\n- cache expire: __5 minutes__", + "cloning": false + }, + { + "id": "1616165824813", + "component": "httpresponse", + "tab": "1615551125555", + "name": "HTTP Response", + "x": 753, + "y": 423, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "json" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1617104731852", + "component": "debug", + "tab": "1615551125555", + "name": "DIDO_Debug", + "x": 669, + "y": 1040, + "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": "turnOff line", + "x": 133, + "y": 1161, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "object", + "data": "{line: 3, command: \"turnOff\", force: true}" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1617115013095", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "tb-push", + "x": 669, + "y": 1150, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1617284749681", + "component": "trigger", + "tab": "1615551125555", + "name": "update profile / node", + "x": 112, + "y": 208, + "connections": { + "0": [ + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "data": "profile_nodes", + "datatype": "string" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1618235171399", + "component": "trigger", + "tab": "1615551125555", + "name": "tun tasks", + "x": 184, + "y": 279, + "connections": { + "0": [ + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "data": "run" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1618300858252", + "component": "debug", + "tab": "1612772287426", + "name": "wsmqtt-exit1", + "x": 597.8833312988281, + "y": 149, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1618393583970", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "to-cmd-manager", + "x": 668.8833312988281, + "y": 1269, + "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": 132.88333129882812, + "y": 367, + "connections": { + "0": [ + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "platform-rpc-call", + "color": "gray" + }, + "options": { + "wirename": "platform-rpc-call" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1618393759854", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "cmd_to_dido", + "x": 119.88333129882812, + "y": 1007, + "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": 752.8833312988281, + "y": 527, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "cmd_to_dido", + "color": "gray" + }, + "options": { + "wirename": "cmd_to_dido" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1618558465485", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "platform-rpc-call", + "x": 597.8833312988281, + "y": 247, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "platform-rpc-call", + "color": "gray" + }, + "options": { + "wirename": "platform-rpc-call" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1618572059773", + "component": "trigger", + "tab": "1615551125555", + "name": "turnOn line", + "x": 132, + "y": 1085, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "data": "{line: 1, command: \"turnOn\", force: true}", + "datatype": "object" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1619515097737", + "component": "cmd_manager", + "tab": "1615551125555", + "name": "CMD Manager", + "x": 452.1091003417969, + "y": 341.05455017089844, + "connections": { + "0": [ + { + "index": "0", + "id": "1615563373927" + } + ], + "1": [ + { + "index": "0", + "id": "1615566865233" + }, + { + "index": "0", + "id": "1615798582262" + } + ], + "2": [ + { + "index": "0", + "id": "1616165824813" + } + ], + "3": [ + { + "index": "0", + "id": "1618393827655" + } + ], + "4": [ + { + "index": "0", + "id": "1635936391935" + } + ], + "5": [ + { + "index": "0", + "id": "1757006030239" + }, + { + "index": "0", + "id": "1757006060377" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1619605019281", + "component": "httproute", + "tab": "1615551125555", + "name": "GET db", + "x": 173, + "y": 653, + "connections": { + "0": [ + { + "index": "0", + "id": "1684060205000" + }, + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Listening", + "color": "green" + }, + "options": { + "timeout": 5, + "cachepolicy": 0, + "cacheexpire": "5 minutes", + "size": 5, + "url": "/db", + "method": "GET", + "name": "", + "flags": [ + "id:1619605019281", + "get", + 5000 + ] + }, + "color": "#5D9CEC", + "notes": "### Configuration\n\n- __GET /db__\n- flags: undefined\n- maximum request data length: __5 kB__\n- empty response: __undefined__\n- cache policy: __no cache__\n- cache expire: __5 minutes__", + "cloning": false + }, + { + "id": "1619784672383", + "component": "trigger", + "tab": "1615551125555", + "name": "turnOnAlarm", + "x": 120, + "y": 1234, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "object", + "data": "{command: \"turnOnAlarm\"}" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1619784812964", + "component": "trigger", + "tab": "1615551125555", + "name": "turnOffAlarm", + "x": 118, + "y": 1307, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "object", + "data": "{command: \"turnOffAlarm\"}" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1621340721628", + "component": "virtualwireout", + "tab": "1611921777196", + "name": "modbus_to_dido", + "x": 599, + "y": 471, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "modbus_to_dido", + "color": "gray" + }, + "options": { + "wirename": "modbus_to_dido" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1622640022885", + "component": "httproute", + "tab": "1615551125555", + "name": "POST /db_connector", + "x": 98, + "y": 1586, + "connections": { + "0": [ + { + "index": "0", + "id": "1622640073521" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Listening", + "color": "green" + }, + "options": { + "timeout": 5, + "cachepolicy": 0, + "cacheexpire": "5 minutes", + "size": 5, + "url": "/db_connector", + "method": "POST", + "flags": [ + "id:1622640022885", + "post", + 5000 + ] + }, + "color": "#5D9CEC", + "notes": "### Configuration\n\n- __POST /db_connector__\n- flags: \n- maximum request data length: __5 kB__\n- empty response: __undefined__\n- cache policy: __no cache__\n- cache expire: __5 minutes__", + "cloning": false + }, + { + "id": "1622640073521", + "component": "db_connector", + "tab": "1615551125555", + "name": "DbConnector", + "x": 372, + "y": 1572, + "connections": { + "1": [ + { + "index": "0", + "id": "1622641420685" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "edge": "undefined" + }, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1622641420685", + "component": "httpresponse", + "tab": "1615551125555", + "name": "HTTP Response", + "x": 596, + "y": 1586, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1634303504177", + "component": "monitormemory", + "tab": "1612772287426", + "name": "RAM", + "x": 69.88333129882812, + "y": 888.5, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465281992" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "858.88 MB / 985.68 MB", + "color": "gray" + }, + "options": { + "enabled": true, + "interval": 30000 + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1634303533779", + "component": "monitordisk", + "tab": "1612772287426", + "name": "disk", + "x": 70.88333129882812, + "y": 982.5, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465821120" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "5.78 GB / 7.26 GB", + "color": "gray" + }, + "options": { + "enabled": true, + "path": "/", + "interval": 30000 + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1634303595494", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "send-to-services", + "x": 51.883331298828125, + "y": 1400.5, + "connections": { + "0": [ + { + "index": "0", + "id": "1634463186563" + }, + { + "index": "1", + "id": "1634488120710" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1634303602169", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "send-to-services", + "x": 426.8833312988281, + "y": 878.5, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1634303685503", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "send-to-services", + "x": 600.8833312988281, + "y": 341.5, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1634303743260", + "component": "httprequest", + "tab": "1612772287426", + "name": "192.168.252.2:8004/sentmessage", + "reference": "", + "x": 506.8833312988281, + "y": 1331.7333374023438, + "connections": { + "0": [ + { + "index": "0", + "id": "1635327431236" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "url": "http://192.168.252.2:8004/sentmessage", + "method": "POST", + "stringify": "json" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1634463186563", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 305.75, + "y": 1442, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634464580289", + "component": "code", + "tab": "1612772287426", + "name": "Code", + "x": 245, + "y": 787, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465243324" + }, + { + "index": "0", + "id": "1634303602169" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "keepmessage": true, + "code": "let response = {};\nresponse.cpu = value.cpu;\nresponse.uptime = value.uptime;\n\nsend(0, response);", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1634465243324", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 428, + "y": 784, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634465281992", + "component": "code", + "tab": "1612772287426", + "name": "Code", + "x": 245, + "y": 884, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465338103" + }, + { + "index": "0", + "id": "1634303602169" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "keepmessage": true, + "code": "value.sender = \"ram\";\n\nlet response = {};\n\nresponse.memory_total = Math.round(value.total / (1024 ** 2));\nresponse.memory_free = Math.round(value.free / (1024 ** 2));\nresponse.memory_used = Math.round(value.used / (1024 ** 2));\n\nsend(0, response);", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1634465338103", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 429, + "y": 976, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634465821120", + "component": "code", + "tab": "1612772287426", + "name": "Code", + "x": 245, + "y": 978, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465892500" + }, + { + "index": "0", + "id": "1634303602169" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "keepmessage": true, + "code": "value.sender = \"hdd\";\n\nlet response = {};\n\nresponse.hdd_total = Math.round(value.total / (1024 ** 2));\nresponse.hdd_free = Math.round(value.free / (1024 ** 2));\nresponse.hdd_used = Math.round(value.used / (1024 ** 2));\n\nsend(0, response);", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1634465892500", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 432, + "y": 1068, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634484067516", + "component": "debug", + "tab": "1612772287426", + "name": "Send info", + "x": 513, + "y": 1441, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634488120710", + "component": "infosender", + "tab": "1612772287426", + "name": "Info sender", + "x": 301, + "y": 1336, + "connections": { + "0": [ + { + "index": "0", + "id": "1634484067516" + }, + { + "index": "0", + "id": "1634303743260" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "edge": "undefined" + }, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1635327431236", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 837.8833312988281, + "y": 1325.5, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1635936391935", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "send-to-services", + "x": 753, + "y": 623, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1637069803394", + "component": "monitorconsumption", + "tab": "1612772287426", + "name": "CPU", + "x": 69, + "y": 791, + "connections": { + "0": [ + { + "index": "0", + "id": "1634464580289" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "49.2% / 69.91 MB", + "color": "gray" + }, + "options": { + "monitorfiles": true, + "monitorconnections": true, + "monitorsize": true, + "monitorconsumption": true, + "enabled": true, + "interval": 30000 + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1683664161036", + "component": "debug", + "tab": "1615551125555", + "name": "CMDtoDIDO", + "x": 392, + "y": 1012, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1683981346282", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "from-dido-controller", + "x": 112, + "y": 459, + "connections": { + "0": [ + { + "index": "0", + "id": "1684055037116" + }, + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "from-dido-controller", + "color": "gray" + }, + "options": { + "wirename": "from-dido-controller" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1684055037116", + "component": "debug", + "tab": "1615551125555", + "name": "from dido to cmd", + "x": 451, + "y": 532, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1684060205000", + "component": "debug", + "tab": "1615551125555", + "name": "HTTP routes", + "x": 450, + "y": 639, + "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": "MDBToDido", + "x": 598, + "y": 147, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1699963668903", + "component": "dido_controller", + "tab": "1615551125555", + "name": "DIDO_Controller", + "x": 397, + "y": 1131, + "connections": { + "0": [ + { + "index": "0", + "id": "1617104731852" + } + ], + "1": [ + { + "index": "0", + "id": "1617104731852" + }, + { + "index": "0", + "id": "1617115013095" + } + ], + "2": [ + { + "index": "0", + "id": "1618393583970" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "edge": "undefined" + }, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1699964678894", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "modbus_to_dido", + "x": 96, + "y": 924, + "connections": { + "0": [ + { + "index": "0", + "id": "1699963668903" + }, + { + "index": "0", + "id": "1699964793925" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "modbus_to_dido", + "color": "gray" + }, + "options": { + "wirename": "modbus_to_dido" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1699964793925", + "component": "debug", + "tab": "1615551125555", + "name": "modbusToDido", + "x": 388, + "y": 920, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1699965957410", + "component": "modbus_reader", + "tab": "1611921777196", + "name": "Modbus reader", + "x": 232, + "y": 175, + "connections": { + "0": [ + { + "index": "0", + "id": "1611951142547" + } + ], + "1": [ + { + "index": "0", + "id": "1621340721628" + }, + { + "index": "0", + "id": "1684179110403" + }, + { + "index": "0", + "id": "1717441414646" + } + ], + "2": [ + { + "index": "0", + "id": "1615809595184" + }, + { + "index": "0", + "id": "1714752862828" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1700411878636", + "component": "thermometer", + "tab": "1611921777196", + "name": "Thermometer", + "x": 234.75, + "y": 444, + "connections": { + "0": [ + { + "index": "0", + "id": "1615802995322" + } + ], + "1": [ + { + "index": "0", + "id": "1615809595184" + }, + { + "index": "0", + "id": "1615809128443" + } + ], + "2": [ + { + "index": "0", + "id": "1621340721628" + }, + { + "index": "0", + "id": "1732889185927" + }, + { + "index": "0", + "id": "1717441414646" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#5CB36D", + "notes": "" + }, + { + "id": "1714752862828", + "component": "debug", + "tab": "1611921777196", + "name": "MDBToTb", + "x": 766, + "y": 324, + "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": 764.0833282470703, + "y": 222, + "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\telse if(value.status === \"NOK-thermometer\")\n\t{\n\t\tsend(0, {\"thermometer\": \"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\telse if(value.values.hasOwnProperty(\"temperature\"))\n\t{\n\t\tsend(0, {\"thermometer\": \"OK\"});\n\t}\n}", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1717442627834", + "component": "debug", + "tab": "1611921777196", + "name": "modbus service", + "x": 966.0833282470703, + "y": 165, + "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": 968.0833282470703, + "y": 268, + "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": 88.75, + "y": 1685, + "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": 296, + "y": 1671, + "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\", \"Flow has been restarted\", \"Node db has changed\"]", + "types": "[\"emergency\", \"critical\", \"error\", \"alert\"]", + "name": "" + }, + "color": "#30E193", + "notes": "" + }, + { + "id": "1718016073501", + "component": "httprequest", + "tab": "1612772287426", + "name": "http://192.168.252.2:8004/slack", + "x": 495, + "y": 1753, + "connections": { + "0": [ + { + "index": "0", + "id": "1718016086212" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "url": "http://192.168.252.2:8004/slack", + "method": "POST", + "stringify": "json" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1718016086212", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 832, + "y": 1664, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "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": 87, + "y": 1591, + "connections": { + "0": [ + { + "index": "0", + "id": "1718016052341" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "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\": \"\" } } } ] }", + "datatype": "object" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1729855334955", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "platform-rpc-call", + "x": 599.9333343505859, + "y": 541.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "platform-rpc-call", + "color": "gray" + }, + "options": { + "wirename": "platform-rpc-call" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1729855371093", + "component": "debug", + "tab": "1612772287426", + "name": "rpc cloud", + "x": 601.9333343505859, + "y": 440.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1731068658334", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 75.75, + "y": 184, + "connections": { + "0": [ + { + "index": "0", + "id": "1612776786008" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731068754606", + "component": "cloudmqttconnect", + "tab": "1612772287426", + "name": "MQTT to senica-prod01", + "x": 284.75, + "y": 452, + "connections": { + "1": [ + { + "index": "0", + "id": "1729855371093" + }, + { + "index": "0", + "id": "1729855334955" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Connected", + "color": "green" + }, + "options": { + "username": "", + "clientid": "", + "port": "2764", + "host": "192.168.252.2", + "topic": "" + }, + "color": "#888600", + "notes": "" + }, + { + "id": "1731069001548", + "component": "db_init", + "tab": "1612772287426", + "name": "DB Initialization", + "x": 1003.75, + "y": 240.25, + "connections": { + "0": [ + { + "index": "0", + "id": "1731069033416" + } + ], + "1": [ + { + "index": "0", + "id": "1747561603739" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#888600", + "notes": "" + }, + { + "id": "1731069033416", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "db-init", + "x": 1244.75, + "y": 233.25, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069059135", + "component": "showdb", + "tab": "1612772287426", + "name": "Show db data", + "x": 1186.75, + "y": 821.25, + "connections": { + "0": [ + { + "index": "0", + "id": "1731069079243" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#888600", + "notes": "" + }, + { + "id": "1731069079243", + "component": "debug", + "tab": "1612772287426", + "name": "dbData", + "x": 1390.75, + "y": 870.25, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1731069116691", + "component": "trigger", + "tab": "1612772287426", + "name": "settings", + "x": 934.75, + "y": 669.75, + "connections": { + "0": [ + { + "index": "0", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069131637", + "component": "trigger", + "tab": "1612772287426", + "name": "relaysData", + "x": 876.75, + "y": 733.75, + "connections": { + "0": [ + { + "index": "1", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069137374", + "component": "trigger", + "tab": "1612772287426", + "name": "nodesData", + "x": 852.75, + "y": 794.75, + "connections": { + "0": [ + { + "index": "2", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069179846", + "component": "trigger", + "tab": "1612772287426", + "name": "pinsData", + "x": 850.75, + "y": 861.75, + "connections": { + "0": [ + { + "index": "3", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069192937", + "component": "trigger", + "tab": "1612772287426", + "name": "sample data", + "x": 857.75, + "y": 928.75, + "connections": { + "0": [ + { + "index": "4", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069264443", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 63.75, + "y": 1279, + "connections": { + "0": [ + { + "index": "0", + "id": "1634488120710" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069334626", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "db-init", + "x": 172.88333129882812, + "y": 129, + "connections": { + "0": [ + { + "index": "0", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069548145", + "component": "virtualwirein", + "tab": "1611921777196", + "name": "db-init", + "x": 46.75, + "y": 192, + "connections": { + "0": [ + { + "index": "0", + "id": "1699965957410" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069567152", + "component": "virtualwirein", + "tab": "1611921777196", + "name": "db-init", + "x": 44.75, + "y": 465, + "connections": { + "0": [ + { + "index": "0", + "id": "1700411878636" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731070156936", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "db-init", + "x": 126.88333129882812, + "y": 1377, + "connections": { + "0": [ + { + "index": "2", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731234189516", + "component": "trigger", + "tab": "1612772287426", + "name": "monitor.txt", + "x": 882.75, + "y": 991.75, + "connections": { + "0": [ + { + "index": "5", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731234189551", + "component": "trigger", + "tab": "1612772287426", + "name": "err.txt", + "x": 904.75, + "y": 1053.75, + "connections": { + "0": [ + { + "index": "6", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1732700042559", + "component": "nodesdb_change_check", + "tab": "1612772287426", + "name": "Nodes DB change check", + "x": 266.8833312988281, + "y": 1980.2333984375, + "connections": { + "0": [ + { + "index": "0", + "id": "1732700071298" + }, + { + "index": "0", + "id": "1732700642917" + } + ], + "1": [ + { + "index": "0", + "id": "1759958914348" + }, + { + "index": "0", + "id": "1759959003114" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#888600", + "notes": "" + }, + { + "id": "1732700057052", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 76.75, + "y": 1988, + "connections": { + "0": [ + { + "index": "0", + "id": "1732700042559" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1732700071298", + "component": "debug", + "tab": "1612772287426", + "name": "nodesChange", + "x": 571.8833312988281, + "y": 2018.2333984375, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1732700642917", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "tb-push", + "x": 567.8833312988281, + "y": 1933, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1732889185927", + "component": "debug", + "tab": "1611921777196", + "name": "tempToDido", + "x": 594.8833312988281, + "y": 753, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1733574412965", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 72.75, + "y": 474, + "connections": { + "0": [ + { + "index": "1", + "id": "1731068754606" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1747561603739", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "send-to-services", + "x": 1243.8833312988281, + "y": 334.5, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1747562867845", + "component": "comment", + "tab": "1612772287426", + "name": "FLOW STARTING POINT", + "x": 1003.5666656494141, + "y": 178, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#704cff", + "notes": "" + }, + { + "id": "1749211698385", + "component": "trigger", + "tab": "1612772287426", + "name": "deviceStatus", + "x": 911.75, + "y": 1116.75, + "connections": { + "0": [ + { + "index": "7", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1757006030239", + "component": "httprequest", + "tab": "1615551125555", + "name": "192.168.252.2:8015/daily_report", + "x": 756.5666656494141, + "y": 715.4499969482422, + "connections": { + "0": [ + { + "index": "0", + "id": "1757006045804" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "stringify": "json", + "method": "POST", + "url": "http://192.168.252.2:8015/daily_report" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1757006045804", + "component": "debug", + "tab": "1615551125555", + "name": "ddd", + "x": 1091.566665649414, + "y": 711.4499969482422, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1757006060377", + "component": "debug", + "tab": "1615551125555", + "name": "reportDebug", + "x": 749.5666656494141, + "y": 799.4499969482422, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1759958914348", + "component": "httprequest", + "tab": "1612772287426", + "name": "http://192.168.252.2:8015/node_numbers", + "x": 571, + "y": 2111, + "connections": { + "0": [ + { + "index": "0", + "id": "1759958927094" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "stringify": "json", + "method": "POST", + "url": "http://192.168.252.2:8015/node_numbers" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1759958927094", + "component": "debug", + "tab": "1612772287426", + "name": "nodesChangeCloud", + "x": 951.8833312988281, + "y": 2109.2333984375, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1759959003114", + "component": "debug", + "tab": "1612772287426", + "name": "nodeChangeCloud1", + "x": 574, + "y": 2218, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1760020290879", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 84.75, + "y": 1787, + "connections": { + "0": [ + { + "index": "1", + "id": "1718016052341" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + } + ], + "version": 615 +} diff --git a/RVO48/flow/dido_controller.js b/RVO48/flow/dido_controller.js new file mode 100755 index 0000000..d16fb19 --- /dev/null +++ b/RVO48/flow/dido_controller.js @@ -0,0 +1,1486 @@ +exports.id = 'dido_controller'; +exports.title = 'DIDO_Controller'; +exports.version = '2.0.0'; +exports.group = 'Worksys'; +exports.color = '#2134B0'; +exports.input = 3; +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 + +state_of_main_switch - reportovat stav hlaveho istica : 0-> off 1-> on +rotary_switch_state - sem by sa mal reportovat stav vstupov manual a auto pola nasledovnej logiky: Manual = 1 a Auto = 0 -> Manu +Manual = 0 a Auto = 0 -> Off, Manual = 0 a Auto = 1 -> Automatic + +door_condition - pin 6, dverový kontakt -> 1 -> vyreportuje Closed, 0 -> vyreportuje Ope +twilight_sensor - hodnotu, ktoru vracia ten analogovy vstup (17) treba poslat sem ako float number. Zrejme tu potom pridame nejaky koeficient prevodu na luxy + +Na kazdu liniu +state_of_breaker - podla indexu istica sa reportuje jeho stav, teda istic na liniu 1: 0-> off, 1-> on +state_of_contactor - podla indexu stkaca sa reportuje jeho stav, teda stykac 1 na liniu 1: 0-> off, 1-> on +*/ + +const { errLogger, logger, monitor } = require('./helper/logger'); +const SerialPort = require('serialport'); +const WebSocket = require('ws'); +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 errorHandler = require('./helper/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 hasMainSwitch; + +let alarmStatus = "OFF"; + +const SEND_TO = { + debug: 0, + tb: 1, + cmd_manager: 2 +} + + +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 = {}; + let rsPortReceivedData = []; + + //to be able to get proper twilight values + let twilight_sensor_interval = 5;//minutes + let twilight_sensor = []; + const twilight_sensor_array = []; + let twilightError = false; + + monitor.info("DIDO_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-we make it global to see it from outside + FLOW.deviceStatus = { //key is device name: temperature,.... + "state_of_main_switch": "Off", //Hlavny istic (alebo druhy dverovy kontakt) + "rotary_switch_state": "Off", //Prevadzkovy + "door_condition": "closed", //Dverový kontakt + "em": "OK", //elektromer rvo + "temperature": "OK", //templomer + "battery": "OK", //Bateria + "power_supply": "OK", //Zdroj + "master_node": "OK", //MN - GLOBALS.settings.masterNodeIsResponding + "no_voltage": "OK", //GLOBALS.settings.no_voltage - vypadok napatia na faze + "state_of_breaker": {}, //"Off",//Istic + "state_of_contactor": {}, //"Off",//Stykac + "twilight_sensor": "OK" //lux sensor + }; + let deviceStatus = FLOW.deviceStatus; + + + function main() { + + GLOBALS = FLOW.GLOBALS; + SETTINGS = FLOW.GLOBALS.settings; + rvoTbName = SETTINGS.rvoTbName; + pinsData = GLOBALS.pinsData; + relaysData = GLOBALS.relaysData; + + tbHandler = new DataToTbHandler(SEND_TO.tb); + tbHandler.setSender(exports.title); + + controller_type = SETTINGS.controller_type; //"lm" or "unipi" + hasMainSwitch = SETTINGS.has_main_switch; + + if (controller_type == "") controller_type = "lm"; + + 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, "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; + } + } + + //report RVO version relaysData[0].tbname; + let values = {}; + values["edge_fw_version"] = SETTINGS.edge_fw_version; + values["maintenance_mode"] = SETTINGS.maintenance_mode; + + sendTelemetry(values, rvoTbName); + + 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); + } + + + function handleRsPort() { + + if (rsPort) { + rsPort.removeAllListeners(); + rsPort = null; + } + + //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('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) { + if (!err) { + monitor.info(exports.title + "--->Digital in_out has been set (runSyncExec was sucessfull)"); + + turnAlarm("off"); + 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('error', err => { + let message = "Dido: rsPort error: " + err.message; + logger.debug(message); + monitor.info(message); + errorHandler.sendMessageToService(message); + }) + + rsPort.on("close", () => { + let message = "Dido: rsPort closed - reconnecting ..."; + logger.debug(message); + monitor.info(message); + setTimeout(handleRsPort, 1000); + }) + + rsPort.open(); + } + + + function handleWebSocket() { + + if (ws) { + ws.removeAllListeners(); + ws = null; + } + + //to keep websocket opened, we send request every 150 seconds + let startRequests = null; + + console.log("handleWebSocket function called"); + ws = new WebSocket('ws:/0.0.0.0:1234/ws'); + + ws.onopen = function open() { + + instance.send(0, exports.title + " running"); + turnAlarm("off"); + + initialSetting(); + + setTimeout(function() { ws.send(JSON.stringify({ cmd: "all" })) }, 5000); + // we request dev info about neuron device from evok to keep websocket connection alive + // for some reason this request returns no data, but connection keeps alive + startRequests = setInterval(() => { + ws.send(JSON.stringify({ "cmd": "filter", "dev": ["neuron"] })); + }, 150000) + }; + + + // 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 = async 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; + + 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 => { + logger.debug('Dido: websocket error', err); + }) + + ws.onclose = function() { + logger.debug('Dido: websocket onclose, reconnecting...') + clearInterval(startRequests); + setTimeout(handleWebSocket, 1000); + } + } + + 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 turnAlarm(onOrOff) { + let value = 0; + if (onOrOff == "on") value = 1; + + if (value == 1 && SETTINGS.maintenance_mode) return; + + alarmStatus = "OFF"; + if (value == 1) alarmStatus = "ON"; + + if (rsPort) { + let arr = [0x55]; + arr.push(13); + arr.push(0); + arr.push(value); + + rsPort.write(Buffer.from(arr), function(err) { + logger.debug(`sirena - ${onOrOff}`); + }); + } + else if (ws) { + let cmd = { "cmd": "set", "dev": "relay", "circuit": "1_01", "value": value }; + ws.send(JSON.stringify(cmd)); + logger.debug(`sirena - ${onOrOff}`); + } + } + + + 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") { + bits.push(0); + } + else bits.push(1); + + if (deviceStatus["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); + } + + + // turn line on or off + function turnLine(onOrOff, line, pin, force, info) { + //onOrOff => "on" or "off" + let value = 0; + if (onOrOff == "on") value = 1; + + if (force == undefined) force = false; + + if (line == 0) { + if (value == 1 && alarmStatus == "ON") turnAlarm("off"); + SETTINGS.maintenance_mode = value ? true : false; + + 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); + return; + } + + if (pin === undefined) pin = getPin(line); + + if (pin === undefined) { + errLogger.error("pin is undefined!", line); + return; + } + + if (!force) { + if (relaysData[line].contactor == value) { + instance.send(SEND_TO.debug, `line is already ${onOrOff} ` + line); + logger.debug(`Dido: turnLine: line is already ${onOrOff} `, line); + return; + } + } + + // if(!rsPort.isOpen && !ws) + if (!rsPort && !ws) { + errLogger.error("Dido - port or websocket is not opened"); + return; + } + + if (rsPort) { + let arr = [0x55]; + arr.push(pin); + arr.push(0); + arr.push(value); + + rsPort.write(Buffer.from(arr), function(err) { + if (err === undefined) { + monitor.info(`Dido: turnLine ${onOrOff} zapisal do rsPort-u`, line, pin, arr, info); + switchLogic(arr); + } + else { + monitor.info(`Dido: turnLine ${onOrOff} WRITE error`, err); + } + }); + + } + else if (ws) { + //pin = "relay1_03" or "input1_01" ... we must make just "1_01" with slice method + monitor.info(`Dido: turnLine ${onOrOff} - (line, pin, force)`, line, pin, force, info); + let cmd = { "cmd": "set", "dev": "relay", "circuit": pin.slice(5), "value": value }; + ws.send(JSON.stringify(cmd)); + } + + //if rvo is 24/7, it has just one switching profile point at 13:00. we do not want to send notification as it repeats every day. + //const d = new Date(); + //if(d.getHours() != 13) sendNotification("Dido_controller: ", SETTINGS.rvoTbName, "switching_profile_point_applied_to_line", { line: line, value: onOrOff }, "", SEND_TO.tb, instance); + } + + + // 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; + + // 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) { + const status = flowdata.data.status; + if (status == "NOK-twilight_sensor") { + deviceStatus["twilight_sensor"] = "NOK"; + } + else if (status == "NOK-em340" || status == "NOK-em111") { + deviceStatus["em"] = "NOK"; + } + else if (status == "NOK-thermometer") { + deviceStatus["temperature"] = "NOK"; + } + } + else if ("values" in flowdata.data) { + 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" + } + else if (values.hasOwnProperty("temperature")) { + deviceStatus["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"; + } + + sendTelemetry(values, rvoTbName); + } + + sendRvoStatus(); + }) + + + + + // we expect array as flowdata.data + instance.on("1", flowdata => { + + //console.log(flowdata.data); + + if (!flowdata.data instanceof Object) return; + + let obj = flowdata.data; + let line = obj.line; + 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"); + }) + + + function calculateStateCode() { + + let bits = []; + + //Hlavny istic - state_of_main_switch => v rvo senica je to druhy door pre silovu cast (EM) + if (deviceStatus["state_of_main_switch"] === "closed" || deviceStatus["state_of_main_switch"] === "Off") { + bits.push(0); + } + else { + bits.push(1); + } + + //Prevadzkovy mod - Manual, Off, Automatic, maintenance_mode = true/false // DAVA 2 BITY + if (!SETTINGS.maintenance_mode) { + if (deviceStatus["rotary_switch_state"] === "Manual") { + bits.push(0); + bits.push(1); + } + + if (deviceStatus["rotary_switch_state"] === "Automatic") { + bits.push(0); + bits.push(0); + } + + if (deviceStatus["rotary_switch_state"] === "Off") { + bits.push(1); + bits.push(0); + } + } + else { + bits.push(1); + bits.push(1); + } + + //Dverovy kontakt + if (deviceStatus["door_condition"] === "closed") { + bits.push(0); + } + else { + bits.push(1); + } + + //EM + if (deviceStatus["em"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //Teplomer + if (deviceStatus["temperature"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //Batéria + if (deviceStatus["battery"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //Zdroj + if (deviceStatus["power_supply"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //MN + if (deviceStatus["master_node"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //výpadok napätia na fáze + if (deviceStatus["no_voltage"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + if (deviceStatus["twilight_sensor"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + // doplnime do 16 bitov (2 byty) + for (let i = bits.length; i < 16; i++) { + bits.push(0); + } + + // console.log("calculateStateCode - deviceStatus", deviceStatus); + // 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; + } + + + async function sendRvoStatus() { + + if (SETTINGS === undefined) return; + SETTINGS.masterNodeIsResponding ? deviceStatus["master_node"] = "OK" : deviceStatus["master_node"] = "NOK"; + + 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 pinsForRvoStatus(controllerType, hasMainSwitch) { + + let pins = []; + + if (controllerType === "lm") { + pins = [1, 4, 6]; + if (hasMainSwitch === 1) { + pins = [4, 6]; + } + } else if (controllerType === "unipi") { + pins = ["input1_01", "input1_04", "input1_05"]; + if (hasMainSwitch === 1) { + pins = ["input1_01", "input1_04"]; + } + } + + return pins; + } + + + function checkRvoStatus() { + + // 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 + //set RVO state + let status = "OK"; + + for (const [key, value] of Object.entries(deviceStatus)) { + if (["em", "twilight_sensor", "temperature", "master_node"].includes(key) && value === "NOK") status = "NOK"; + } + + if (status === "OK") { + + let pinIndexes = pinsForRvoStatus(controller_type, hasMainSwitch); + + for (const pinIndex of pinIndexes) { + if (previousValues[pinIndex] === 0) { + if ((pinIndex === 6 || pinIndex === 'input1_01' || pinIndex === 'input1_05') && SETTINGS.maintenance_mode) continue; + status = "NOK"; + break; + } + } + } + + // battery status. If value is 1 - battery is NOK + if (previousValues[5] === 1) status = "NOK"; + if (SETTINGS.no_voltage.size > 0) status = "NOK"; + + // console.log("rvo status",status) + return status; + } + + + // we pass array to function in case of rsPort ==> switchLogic([55,3,0,1]) ==> [[55,3,0,1]] + // we pass two values in case of websocket ==> switchLogic("relay1_03",1) ==> ["relay1_03",1] + const switchLogic = (...args) => { + + let values = {}; + let pinIndex, newPinValue, twilight; + + //data from rsPort + if (args.length == 1) { + pinIndex = args[0][1] + 1; + if (pinIndex === 17) pinIndex--; + newPinValue = args[0][3]; + twilight = args[0][2]; + } + //data from websocket + else { + pinIndex = args[0]; + newPinValue = args[1]; + } + + 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; + + //default value + let value = "On"; + if (newPinValue === 0) value = "Off"; + + //Hlavny istic + if (type === "state_of_main_switch" && hasMainSwitch) { + if (newPinValue === 0 && newPinValue !== previousValues[pinIndex]) { + sendNotification("switchLogic", rvoTbName, "main_switch_has_been_turned_off", {}, "", SEND_TO.tb, instance, "state_of_main_switch"); + 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"); + deviceStatus["state_of_main_switch"] = "On"; + } + } + + //Prevadzkovy mod + 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"; + + deviceStatus["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, "power_supply_has_disconnected_input", {}, "", SEND_TO.tb, instance, "power_supply"); + + deviceStatus["power_supply"] = "NOK"; + } + else if (newPinValue === 1 && newPinValue !== previousValues[pinIndex]) { + sendNotification("switchLogic", rvoTbName, "power_supply_works_correctly", {}, "", SEND_TO.tb, instance, "power_supply"); + + deviceStatus["power_supply"] = "OK"; + } + } + + //Bateria - 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"); + + deviceStatus["battery"] = "NOK"; + } + else if (newPinValue === 0 && newPinValue !== previousValues[pinIndex]) { + sendNotification("switchLogic", rvoTbName, "battery_level_is_ok", {}, "", SEND_TO.tb, instance, "battery_level"); + + deviceStatus["battery"] = "OK"; + } + } + + //Dverovy kontakt - pin 6 + //! Ak je rvo s dvoma dverovymi kontaktami, ked pride z evoku signal z input1_05, co bol predytm "state_of_main switch" handlujeme ho teraz ako 'door_condition' + else if (type == "door_condition" || type === "state_of_main_switch") { + newPinValue === 0 ? value = "open" : value = "closed"; + + let door = "door_main"; + if (type === "state_of_main_switch") door = "door_em"; + + if (value === "open") { + if (SETTINGS.maintenance_mode) { + sendNotification("switchLogic", rvoTbName, door + "_open", {}, "", SEND_TO.tb, instance, door); + } else { + sendNotification("switchLogic", rvoTbName, door + "_open_without_permission", {}, "", SEND_TO.tb, instance, door); + + // 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 (value === "closed") { + if (alarmStatus == "ON") turnAlarm("off"); + sendNotification("switchLogic", rvoTbName, door + "_close", {}, "", SEND_TO.tb, instance, door); + } + + deviceStatus[type] = value; + } + + //lux sensor + else if (type == "twilight_sensor") { + //! TODO - to show nok status, if lux value is not changing more then 10 times. + //Daylight is far more than 1000. So most of the day, when it is sunshine comes just value 1000. But lux sensor is not NOK. + //This is not the case in LM. If value from LM is the same 10x, there is 99% possibility, that sensor is NOK. + value = newPinValue; + + if (controller_type === 'lm') { + value = parseFloat(newPinValue + (256 * twilight)); + + 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 && !twilightError) { + twilightError = true; + let value = twilight_sensor_array.shift(); + + newPinValue = 0; + } + else if (set.size !== 1 && twilightError) { + //sendNotification("switchLogic", rvoTbName, 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) { + 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); + } + } + + 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); + } + + deviceStatus["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 (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 }); + + //mame iba 3 istice. vyreportujeme a ohandlujeme liniu na tom istom istici ako paralelna linia (napr linia 1, paralelna s nou je linia 4, key je string "4") + // ak je 7 linii, na 1 istici je linia 1,4,7 + + if (line == 1) { + + const lineOnSameBraker = [4, 7]; + + for (var i = 0; i < lineOnSameBraker.length; i++) { + if (!relaysData.hasOwnProperty(lineOnSameBraker[i])) continue; + + 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; + reportLineStatus(lineOnSameBraker[i]); + + values[type] = value; + const tbname = relaysData[lineOnSameBraker[i]].tbname; + sendTelemetry(values, tbname); + + delete values[type]; + } + + } + else { + const lineOnSameBraker = line + 3 + ""; + + if (relaysData.hasOwnProperty(lineOnSameBraker)) { + 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; + reportLineStatus(line + 3); + + values[type] = value; + const tbname = relaysData[lineOnSameBraker].tbname; + sendTelemetry(values, tbname); + + delete values[type]; + } + } + + } + + if (value == "Off") values["status"] = "NOK"; + deviceStatus["state_of_breaker"][line] = value; + + reportLineStatus(line); + } + else return; + + values[type] = value; + + if (type == "rotary_switch_state") { + if (SETTINGS.maintenance_mode) value = "maintenance"; + value = value.toLowerCase(); + values["power_mode"] = value; + } + + if (newPinValue != previousValues[pinIndex]) previousValues[pinIndex] = newPinValue; + if (Object.keys(values).length > 0 && tbname) sendTelemetry(values, tbname); + } + + + function sendTelemetry(values, tbname, date = Date.now()) { + let dataToTb = { + [tbname]: [ + { + "ts": date, + "values": values + } + ] + }; + + tbHandler.sendToTb(dataToTb, instance); + } + + + function isObject(item) { + return (typeof item === "object" && !Array.isArray(item) && item !== null); + } + +} //end of 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 +// *|input1_01|state_of_main_switch|0|........... +// *|input1_02|rotary_switch_state|0|........... +// *|input1_03|rotary_switch_state|0|........... +// *|intut1_04|power_supply|0|........... +// *|input1_05|door_condition|0|........... +// *|input1_06|state_of_breaker|1|........... +// *|input1_07|state_of_breaker|2|........... +// *|input1_08|state_of_breaker|3|........... +// *|relay1_02|state_of_contactor|1|........... +// *|relay1_03|state_of_contactor|2|........... +// *|relay1_04|state_of_contactor|3|........... +// *|287D8776E0013CE9|temperature|0|........... + + +//! pins_data --> from UNIPI +// { +// 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 } +// } + +//! relays_data +// { +// '0': { +// line: 0, +// tbname: 'KjbN4q7JPZmexgdnz2yKQ98YAWwO0Q3BMX6ERLoV', +// contactor: 1, +// profile: '' +// }, +// '1': { +// line: 1, +// tbname: 'RMgnK93rkoAazbqdQ4yBG95Z1YXGx6pmwBeVEP2O', +// contactor: 0, +// profile: '{"intervals":[{"value":0,"end_time":"20:00","start_time":"13:00"},{"value":1,"end_time":"10:00","start_time":"20:00"},{"value":0,"end_time":"10:20","start_time":"10:00"},{"value":1,"end_time":"10:40","start_time":"10:20"},{"value":0,"end_time":"11:00","start_time":"10:40"},{"value":1,"end_time":"11:30","start_time":"11:00"},{"value":0,"end_time":"11:50","start_time":"11:30"},{"value":1,"end_time":"13:00","start_time":"11:50"}],"astro_clock":false,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' +// }, +// '2': { +// line: 2, +// tbname: 'dlE1VQjYrNx9gZRmb38gG08oLBO4qaAk2M6JPnG7', +// contactor: 0, +// profile: '{"intervals":[{"value":0,"end_time":"20:00","start_time":"13:00"},{"value":1,"end_time":"10:00","start_time":"20:00"},{"value":0,"end_time":"10:20","start_time":"10:00"},{"value":1,"end_time":"10:40","start_time":"10:20"},{"value":0,"end_time":"11:00","start_time":"10:40"},{"value":1,"end_time":"11:30","start_time":"11:00"},{"value":0,"end_time":"11:50","start_time":"11:30"},{"value":1,"end_time":"13:00","start_time":"11:50"}],"astro_clock":false,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' +// }, +// '3': { +// line: 3, +// tbname: 'vnmG4kJxaXWNBgMQq0D7Aj5e9oZzOAlr6LdR3w2V', +// contactor: 0, +// profile: '{"intervals":[{"value":0,"end_time":"20:30","start_time":"13:00"},{"value":1,"end_time":"00:10","start_time":"20:30"},{"value":0,"end_time":"13:00","start_time":"05:40"},{"value":1,"end_time":"05:40","start_time":"00:10"}],"astro_clock":true,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' +// } +// } + + + + + +// { +// "jbN4q7JPZmexgdnz2yKbWGDYAWwO0Q3BMX6ERLoV": [ +// { +// "ts": 1700409326353, +// "values": { +// "_event": { +// "type": "notice", +// "status": "new", +// "source": { +// "func": "rsPort.open()", +// "component": "1700343402190", +// "component_name": "DIDO_Controller", +// "edge": "jbN4q7JPZmexgdnz2yKbWGDYAWwO0Q3BMX6ERLoV" +// }, +// "message": "al_shariff_10.0.0.38: FLOW has been started ", +// "message_data": "" +// } +// } +// } +// ] +// } diff --git a/RVO48/flow/helper/DataToTbHandler.js b/RVO48/flow/helper/DataToTbHandler.js new file mode 100755 index 0000000..716ef7b --- /dev/null +++ b/RVO48/flow/helper/DataToTbHandler.js @@ -0,0 +1,187 @@ +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; + this.itIsNodeReadout = false; + this.sender = ""; + + // if attribute change difference is less than limit value, we do not send to tb. + this.attributeChangeLimit = { + temperature: 0.5, + Phase_1_voltage: 2, + Phase_2_voltage: 2, + Phase_3_voltage: 2, + Phase_1_current: 0.1, + Phase_2_current: 0.1, + Phase_3_current: 0.1, + Phase_1_power: 2, + Phase_2_power: 2, + Phase_3_power: 2, + total_power: 2, + total_energy: 1, + Phase_1_pow_factor: 0.1, + Phase_2_pow_factor: 0.1, + Phase_3_pow_factor: 0.1, + power_factor: 0.1, + lifetime: 2, + voltage: 2, + power: 2, + frequency: 3, + energy: 0.1, + current: 2, + inclination_x: 10, + inclination_y: 10, + inclination_z: 10 + }; + + } + + dump() { + console.log("----------------------------"); + console.log("previousValues", this.previousValues); + console.log("----------------------------"); + } + + setSender(sender) { + this.sender = sender; + } + + isEmptyObject(obj) { + for (var _ in obj) { + return false; + } + return true; + } + + + sendToTb(data, instance) { + + //not to modify data object, we do deep copy: + let dataCopy = JSON.parse(JSON.stringify(data)); + + let keys = Object.keys(dataCopy); + + if (keys.length == 0) { + if (this.debug) console.log("sendToTb received empty object", dataCopy); + return; + } + + let tbname = keys[0]; + let ts; + + let arrayOfValues = dataCopy[tbname]; + let arrayOfValuesToSend = []; + + for (let i = 0; i < arrayOfValues.length; i++) { + + ts = arrayOfValues[i].ts; + let values = this.prepareValuesForTb(tbname, ts, arrayOfValues[i].values); + + if (!this.isEmptyObject(values)) { + arrayOfValuesToSend.push({ ts: ts, values: values }); + } + + } + + if (arrayOfValuesToSend.length == 0) { + //if(this.debug) console.log("data not sent - empty array"); + return; + } + + this.messageCounter++; + + let dataToTbModified = { + [tbname]: arrayOfValuesToSend + } + + //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); + instance.send(this.index, dataToTbModified); + } + + + getDiffTimestamp(key) { + //TODO set different value for given key!!! + //if(key == "status") this.timeToHoldTbValue = 2*60*60;//2h + return this.timeToHoldTbValue * 1000; + } + + + prepareValuesForTb(tbname, timestamp, values) { + + let keys = Object.keys(values); + + if (keys.includes("lifetime")) this.itIsNodeReadout = true; + + if (!this.previousValues.hasOwnProperty(tbname)) { + this.previousValues[tbname] = {}; + } + + //if(this.debug) console.log("prepareValuesForTb", tbname, timestamp, values); + + for (let i = 0; i < keys.length; i++) { + + let key = keys[i]; + let value = values[key]; + + if (!this.previousValues[tbname].hasOwnProperty(key)) { + this.previousValues[tbname][key] = { ts: timestamp, value: value }; + continue; + } + + // attributeData ==> {voltage: {ts:333333, value:5}} + let attributeData = this.previousValues[tbname][key]; + let attributeToChange = false; + if (key in this.attributeChangeLimit) attributeToChange = true; + let limit = this.attributeChangeLimit[key]; + let timestampDiffToRemoveKey; + + //this will ensure "node statecode" will be sent just once an hour + if (this.itIsNodeReadout && key === "statecode") { + attributeData.value = value; + this.itIsNodeReadout = false; + timestampDiffToRemoveKey = 1 * 60 * 60 * 1000; // 1 hour + } + + if (key === "twilight_sensor" && value > 100) { + attributeData.value = value; + } + + //if edge, master or node version do not change, send just once a day: + if (["edge_fw_version", "master_node_version", "fw_version"].includes(key)) { + timestampDiffToRemoveKey = 24 * 60 * 60 * 1000; + } + + if (attributeData.value === value || attributeToChange && Math.abs(attributeData.value - value) < limit) { + + let diff = timestamp - attributeData.ts; + if (!timestampDiffToRemoveKey) timestampDiffToRemoveKey = this.getDiffTimestamp(key); + + if (diff > timestampDiffToRemoveKey) { + attributeData.ts = Date.now(); + //if(this.debug) console.log(this.sender + ": update ts for key", key, "diff is", diff, "messageCounter", this.messageCounter); + } + else { + delete values[key]; + //if(this.debug) console.log(this.sender + ": delete key", key, "diff is", diff, "messageCounter", this.messageCounter, timestampDiffToRemoveKey); + } + } + else { + attributeData.value = value; + attributeData.ts = timestamp; + } + + } + + return values; + } +} + +module.exports = DataToTbHandler; + diff --git a/RVO48/flow/helper/ErrorToServiceHandler.js b/RVO48/flow/helper/ErrorToServiceHandler.js new file mode 100755 index 0000000..2b27c32 --- /dev/null +++ b/RVO48/flow/helper/ErrorToServiceHandler.js @@ -0,0 +1,91 @@ +const { MD5 } = require('./md5.js'); +const { networkInterfaces } = require('os'); + +class ErrorToServiceHandler { + constructor() { + this.previousValues = {}; + + this.project_id = undefined; + + const nets = networkInterfaces(); + this.ipAddresses = {}; + + for (const name of Object.keys(nets)) { + for (const net of nets[name]) { + // Skip over non-IPv4 and internal (i.e. 127.0.0.1) addresses + if (net.family === 'IPv4' && !net.internal) { + if (!this.ipAddresses[name]) { + this.ipAddresses[name] = []; + } + this.ipAddresses[name].push(net.address); + } + } + } + } + + setProjectId(project_id) { + this.project_id = project_id; + } + + processMessage(message, seconds) { + if (Array.isArray(message)) message = message.join(', '); + + let key = MD5(message); + let ts = Date.now(); + + //keep in memory - default value is 1h + if (seconds === undefined) seconds = 60 * 60; + + if (!this.previousValues.hasOwnProperty(key)) { + this.previousValues[key] = { ts: ts, duration: seconds }; + } + + let diff = (ts - this.previousValues[key].ts); + if (diff < this.previousValues[key].duration * 1000) return false; + + this.previousValues[key].ts = ts; + + return message; + } + + sendMessageToService(message, seconds, message_type) { + + // if error occures too early FLOW.GLOBALS.settings.project_id is still undefined + if (this.project_id === undefined) { + console.log("ErrorToServiceHandler.js: no project_id"); + return; + } + + let f = this.processMessage(message, seconds); + if (f === false) return; + + if (message_type === undefined) message_type = "error_message"; + + let toService = { + id: this.project_id, + ipAddresses: this.ipAddresses + }; + + //js_error || error_message + toService[message_type] = message; + + console.log("ErrorToServiceHandler------------------------>send to service", toService); + + RESTBuilder.make(function(builder) { + builder.method('POST'); + builder.post(toService); + builder.url('http://192.168.252.2:8004/sentmessage'); + + builder.callback(function(err, response, output) { + console.log("process.on error send", err, response, output, toService); + }); + }); + + } +} + +const errorHandler = new ErrorToServiceHandler(); + + +module.exports = errorHandler; +//module.exports = ErrorToServiceHandler; diff --git a/RVO48/flow/helper/db_helper.js b/RVO48/flow/helper/db_helper.js new file mode 100755 index 0000000..40e796c --- /dev/null +++ b/RVO48/flow/helper/db_helper.js @@ -0,0 +1,44 @@ +function promisifyBuilder(builder) +{ + return new Promise((resolve, reject) => { + + try{ + + builder.callback(function(err, response) { + + if(err != null) reject(err); + resolve(response); + }); + + } catch (error) { + reject(error); + } + }) +} + +function makeMapFromDbResult(response, ...keys) +{ + let s = "-"; + let data = {}; + + for(let i = 0; i < response.length; i++) + { + let record = response[i]; + + let k = []; + for(let j = 0; j < keys.length; j++) + { + k.push( record[keys[j]] ); + } + + let key = k.join(s); + data[ key ] = record; + } + + return data; +} + +module.exports = { + promisifyBuilder, + makeMapFromDbResult + } \ No newline at end of file diff --git a/RVO48/flow/helper/logger.js b/RVO48/flow/helper/logger.js new file mode 100755 index 0000000..2585639 --- /dev/null +++ b/RVO48/flow/helper/logger.js @@ -0,0 +1,30 @@ +//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/RVO48/flow/helper/md5.js b/RVO48/flow/helper/md5.js new file mode 100755 index 0000000..d3b0480 --- /dev/null +++ b/RVO48/flow/helper/md5.js @@ -0,0 +1,5 @@ +function MD5(d){var r = M(V(Y(X(d),8*d.length)));return r.toLowerCase()};function M(d){for(var _,m="0123456789ABCDEF",f="",r=0;r>>4&15)+m.charAt(15&_);return f}function X(d){for(var _=Array(d.length>>2),m=0;m<_.length;m++)_[m]=0;for(m=0;m<8*d.length;m+=8)_[m>>5]|=(255&d.charCodeAt(m/8))<>5]>>>m%32&255);return _}function Y(d,_){d[_>>5]|=128<<_%32,d[14+(_+64>>>9<<4)]=_;for(var m=1732584193,f=-271733879,r=-1732584194,i=271733878,n=0;n>16)+(_>>16)+(m>>16)<<16|65535&m}function bit_rol(d,_){return d<<_|d>>>32-_} + +module.exports = { + MD5 +} \ No newline at end of file diff --git a/RVO48/flow/helper/notification_reporter.js b/RVO48/flow/helper/notification_reporter.js new file mode 100755 index 0000000..839c12c --- /dev/null +++ b/RVO48/flow/helper/notification_reporter.js @@ -0,0 +1,121 @@ +//key is device, value = message {} +let sentValues = {}; +let notificationsData = null; +let rvoName; + +//sendNotification("CMD Manager: process cmd", SETTINGS.rvoTbName, "dimming_profile_was_successfully_received_by_node", { node: node }, "", SEND_TO.tb, instance); + +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 +}; + +function getKey(map, val) { + return Object.keys(map).findItem(key => map[key] === val); +} + +//https://stackoverflow.com/questions/41117799/string-interpolation-on-variable +var template = (tpl, args) => tpl.replace(/\${(\w+)}/g, (_, v) => args[v]); + + +function initNotification() { + notificationsData = FLOW.GLOBALS.notificationsData; + rvoName = FLOW.GLOBALS.settings.rvo_name; +} + + +function sendNotification(func, device, key, params, extra, tb_output, instance, saveKey) { + + let storeToSendValues = true; + if (saveKey == undefined) storeToSendValues = false; + + let weight = ""; + let message = {}; + + let notification = notificationsData[key]; + + if (notification) { + weight = notification.weight.toLowerCase(); + + Object.keys(notification).forEach(item => { + if (["en", "sk", "de", "cz", "it", "es"].includes(item)) { + message[item] = rvoName + ": " + template(notification[item], params); + } + }) + } + else { + //console.error("sendNotification: Notifications: undefined key", key, func, notificationsData); + console.error("sendNotification: Notifications: undefined key", key, func); + return false; + } + + //detect invalid err weight + if (getKey(ERRWEIGHT, weight) == undefined) { + console.error("sendNotification: Notifications: undefined weight", weight, key, func); + return false; + } + + if (sentValues.hasOwnProperty(saveKey)) { + if (JSON.stringify(sentValues[saveKey]) == JSON.stringify(message)) { + return false; + } + } + + if (sentValues[saveKey] == undefined) { + if (storeToSendValues) { + //do not send - flow is was started + sentValues[saveKey] = message; + return false; + } + } + + if (storeToSendValues) sentValues[saveKey] = message; + + let content = { + "type": weight, + "status": "new", + "source": { + "func": func, + "component": instance.id, + "component_name": instance.name, + "edge": device + }, + "message": message, + "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 + + return true; + +} + +module.exports = { + sendNotification, + ERRWEIGHT, + initNotification +} + diff --git a/RVO48/flow/helper/register.js b/RVO48/flow/helper/register.js new file mode 100755 index 0000000..fc1d008 --- /dev/null +++ b/RVO48/flow/helper/register.js @@ -0,0 +1,144 @@ +/* +0 - cislo registra / prikaz +1 - recepient - 0 = master, 1 = slave (slave je automaticky group a broadcast) +2 - r/rw - read/write +3- register name - nazov registra / prikazu (len pre info - zobrazenie v aplikacii) + +4,5,6,7, - jednotlive byte-y - nazov byte-u +4-7 - RES. a prazdny string "" sa nezobrazia!!! +*/ + +//124 zaznamov +const registers = [ + ["0","1","R","Status","","",""], + ["1","1","RW","Dimming","R-Channel ","G-Channel","B-Channel ","W - Channel"], + ["2","1","R","Device types","","",".",""], + ["3","1","RW","Group addresses 1-4","Groups Add. 4","Groups Add. 3","Groups Add. 2","Groups Add. 1"], + ["4","1","RW","Group addresses 5-8","Groups Add. 8","Groups Add. 7","Groups Add. 6","Groups Add. 5"], + ["5","1","RW","Serial number (MAC)","","","",""], + ["6","1","RW","Time of dusk","HH","MM","SS","EXTRA"], + ["7","1","RW","Time of dawn","HH","MM","SS","EXTRA"], + ["8","1","RW","Time Schedule settings","TBD","TBD","Movement sensor","Time Schedule"], + ["9","1","RW","TS1 Time point 1","HH","MM","SS","Ext. Device"], + ["10","1","RW","TS1 Time point 1 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["11","1","RW","TS1 Time point 2","HH","MM","SS","Ext. Device"], + ["12","1","RW","TS1 Time point 2 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["13","1","RW","TS1 Time point 3","HH","MM","SS","Ext. Device"], + ["14","1","RW","TS1 Time point 3 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["15","1","RW","TS1 Time point 4","HH","MM","SS","Ext. Device"], + ["16","1","RW","TS1 Time point 4 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["17","1","RW","TS1 Time point 5","HH","MM","SS","Ext. Device"], + ["18","1","RW","TS1 Time point 5 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["19","1","RW","TS1 Time point 6","HH","MM","SS","Ext. Device"], + ["20","1","RW","TS1 Time point 6 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["21","1","RW","TS1 Time point 7","HH","MM","SS","Ext. Device"], + ["22","1","RW","TS1 Time point 7 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["23","1","RW","TS1 Time point 8","HH","MM","SS","Ext. Device"], + ["24","1","RW","TS1 Time point 8 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["25","1","RW","TS1 Time point 9","HH","MM","SS","Ext. Device"], + ["26","1","RW","TS1 Time point 9 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["27","1","RW","TS1 Time point 10","HH","MM","SS","Ext. Device"], + ["28","1","RW","TS1 Time point 10 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["29","1","RW","TS1 Time point 11","HH","MM","SS","Ext. Device"], + ["30","1","RW","TS1 Time point 11 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["31","1","RW","TS1 Time point 12","HH","MM","SS","Ext. Device"], + ["32","1","RW","TS1 Time point 12 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["33","1","RW","TS1 Time point 13","HH","MM","SS","Ext. Device"], + ["34","1","RW","TS1 Time point 13 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["35","1","RW","TS1 Time point 14","HH","MM","SS","Ext. Device"], + ["36","1","RW","TS1 Time point 14 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["37","1","RW","TS1 Time point 15","HH","MM","SS","Ext. Device"], + ["38","1","RW","TS1 Time point 15 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["39","1","RW","TS1 Time point 16","HH","MM","SS","Ext. Device"], + ["40","1","RW","TS1 Time point 16 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["41","1","RW","TS2 Time point 1","HH","MM","SS","Ext. Device"], + ["42","1","RW","TS2 Time point 1 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["43","1","RW","TS2 Time point 2","HH","MM","SS","Ext. Device"], + ["44","1","RW","TS2 Time point 2 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["45","1","RW","TS2 Time point 3","HH","MM","SS","Ext. Device"], + ["46","1","RW","TS2 Time point 3 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["47","1","RW","TS2 Time point 4","HH","MM","SS","Ext. Device"], + ["48","1","RW","TS2 Time point 4 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["49","1","RW","TS2 Time point 5","HH","MM","SS","Ext. Device"], + ["50","1","RW","TS2 Time point 5 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["51","1","RW","TS2 Time point 6","HH","MM","SS","Ext. Device"], + ["52","1","RW","TS2 Time point 6 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["53","1","RW","TS2 Time point 7","HH","MM","SS","Ext. Device"], + ["54","1","RW","TS2 Time point 7 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["55","1","RW","TS2 Time point 8","HH","MM","SS","Ext. Device"], + ["56","1","RW","TS2 Time point 8 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["57","1","RW","TS2 Time point 9","HH","MM","SS","Ext. Device"], + ["58","1","RW","TS2 Time point 9 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["59","1","RW","TS2 Time point 10","HH","MM","SS","Ext. Device"], + ["60","1","RW","TS2 Time point 10 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["61","1","RW","TS2 Time point 11","HH","MM","SS","Ext. Device"], + ["62","1","RW","TS2 Time point 11 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["63","1","RW","TS2 Time point 12","HH","MM","SS","Ext. Device"], + ["64","1","RW","TS2 Time point 12 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["65","1","RW","TS2 Time point 13","HH","MM","SS","Ext. Device"], + ["66","1","RW","TS2 Time point 13 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["67","1","RW","TS2 Time point 14","HH","MM","SS","Ext. Device"], + ["68","1","RW","TS2 Time point 14 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["69","1","RW","TS2 Time point 15","HH","MM","SS","Ext. Device"], + ["70","1","RW","TS2 Time point 15 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["71","1","RW","TS2 Time point 16","HH","MM","SS","Ext. Device"], + ["72","1","RW","TS2 Time point 16 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["73","1","RW","Power meter status","TBD","","",""], + ["74","1","R","Input Voltage","","","",""], + ["75","1","R","Input Current","","","",""], + ["76","1","R","Input Power","","","",""], + ["77","1","R","Cos phi","","","",""], + ["78","1","R","Frequency","","","",""], + ["79","1","RW","Energy","","","",""], + ["80","1","RW","Lifetime","","","",""], + ["81","1","RW","Power on cycles (input)","","","",""], + ["82","1","RW","Power on cycles (relay)","","","",""], + ["83","1","R","Time since last power on","","","",""], + ["84","1","R","Accelerometer data","","","",""], + ["85","1","RW","GPS latitude","pos/neg","deg","min ","sec"], + ["86","1","RW","GPS longitude","pos/neg","deg","min ","sec"], + ["87","1","RW","Actual time","HH","MM","SS","RES."], + ["88","1","RW","Actual date","Day of week","Day","Month","Year"], + ["89","1","R","Production data 1","","","",""], + ["90","1","R","Production data 2","","","",""], + ["91","1","RW","Network ID","NID3","NID2","NID1","NID0"], + ["95","1","RW","Actual Lux level from cabinet","RES.","RES.","HB","LB"], + ["96","1","RW","Threshold lux level","Dusk HB","Dusk LB","Dawn HB","Dawn LB"], + ["97","1","RW","Adjust period","Dusk HB","Dusk LB","Dawn HB","Dawn LB"], + ["98","1","RW","Offset","RES.","RES.","Dusk","Dawn"], + ["99","1","RW","CCT min/max range","max-H","max-L","min-H","min-L"], + ["100","1","RW","DALI interface","Cmd ID","Add","Cmd","Resp"], + ["101","1","RW","Module FW ver","v1","v2","v3","v4"], + ["102","1","RW","Module MAC-H","unused","unused","M1","M2"], + ["103","1","RW","Module MAC-L","M3","M4","M5","M6"], + ["122","1","R","FW update status/control register","Byte3","Byte2","Byte1","Byte0"], + ["123","1","R","FW update - data index","Byte3","Byte2","Byte1","Byte0"], + ["124","1","R","FW update - data","Byte3","Byte2","Byte1","Byte0"], + ["0","0","R","Status","","","",""], + ["1","0","RW","Control register","RES.","RES.","RES.","init mode enable"], + ["2","0","R","Device types","","","",""], + ["3","0","R","Serial number (MAC)","","","",""], + ["4","0","R","Production data 1","","","",""], + ["5","0","R","Production data 2","","","",""], + ["6","0","RW","Network ID","NID3","NID2","NID1","NID0"], + ["7","0","RW","RS232 settings","param.","param.","Baudrate H","Baudrate L"], + ["8","0","R","Accelerometer data","","","",""], + ["9","0","RW","Module FW ver","v1","v2","v3","v4"], + ["10","0","RW","Module MAC-H","unused","unused","M1","M2"], + ["11","0","RW","Module MAC-L","M3","M4","M5","M6"], + ["32","0","RW","FW update status/control register","Byte3","Byte2","Byte1","Byte0"], + ["33","0","RW","FW update - data index","Byte3","Byte2","Byte1","Byte0"], + ["34","0","RW","FW update - data","Byte3","Byte2","Byte1","Byte0"], + ["125","0","RW","Debug Register","Byte3","Byte2","Byte1","Byte0"], + ["126","0","RW","Network Control Register","Byte3","Byte2","Byte1","Byte0"], + ["127","0","R","Network Status Register","Byte3","Byte2","Byte1","Byte0"], + ["128","0","RW","Node XX Serial Number Register","SER3","SER2","SER1","SER0"], + ["256","0","R","Node XX Network Status Register","","","",""] +]; + +let register = {}; + +module.exports = { + registers, + register +} \ No newline at end of file diff --git a/RVO48/flow/helper/serialport_helper.js b/RVO48/flow/helper/serialport_helper.js new file mode 100755 index 0000000..7f5920d --- /dev/null +++ b/RVO48/flow/helper/serialport_helper.js @@ -0,0 +1,99 @@ +const { exec } = require('child_process'); + +function openPort(port) { + return new Promise((resolve, reject) => { + + var callbackError = function(err) { + port.removeListener('error', callbackError); + port.removeListener('open', callbackError); + + reject(err.message); + }; + + var callbackOpen = function(data) { + port.removeListener('error', callbackError); + port.removeListener('open', callbackOpen); + + resolve("port open: ok"); + }; + + port.on('error', callbackError); + port.on('open', callbackOpen); + + port.open(); + + }) +} + +function runSyncExec(command) { + return new Promise((resolve, reject) => { + + exec(command, (error, stdout, stderr) => { + if (error == null) resolve(stdout); + reject(error); + }); + + }) +} + +async function writeData(port, data, readbytes, timeout) { + return new Promise((resolve, reject) => { + + // 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) { + + port.write(Buffer.from(data), function(err) { + if (err) { + reject(err.message); + } + }); + + 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 +} diff --git a/RVO48/flow/helper/suncalc.js b/RVO48/flow/helper/suncalc.js new file mode 100755 index 0000000..c9ca56d --- /dev/null +++ b/RVO48/flow/helper/suncalc.js @@ -0,0 +1,317 @@ +/* + (c) 2011-2015, Vladimir Agafonkin + SunCalc is a JavaScript library for calculating sun/moon position and light phases. + https://github.com/mourner/suncalc +*/ + +(function () { 'use strict'; + +// shortcuts for easier to read formulas + +var PI = Math.PI, + sin = Math.sin, + cos = Math.cos, + tan = Math.tan, + asin = Math.asin, + atan = Math.atan2, + acos = Math.acos, + rad = PI / 180; + +// sun calculations are based on http://aa.quae.nl/en/reken/zonpositie.html formulas + + +// date/time constants and conversions + +var dayMs = 1000 * 60 * 60 * 24, + J1970 = 2440588, + J2000 = 2451545; + +function toJulian(date) { return date.valueOf() / dayMs - 0.5 + J1970; } +function fromJulian(j) { return new Date((j + 0.5 - J1970) * dayMs); } +function toDays(date) { return toJulian(date) - J2000; } + + +// general calculations for position + +var e = rad * 23.4397; // obliquity of the Earth + +function rightAscension(l, b) { return atan(sin(l) * cos(e) - tan(b) * sin(e), cos(l)); } +function declination(l, b) { return asin(sin(b) * cos(e) + cos(b) * sin(e) * sin(l)); } + +function azimuth(H, phi, dec) { return atan(sin(H), cos(H) * sin(phi) - tan(dec) * cos(phi)); } +function altitude(H, phi, dec) { return asin(sin(phi) * sin(dec) + cos(phi) * cos(dec) * cos(H)); } + +function siderealTime(d, lw) { return rad * (280.16 + 360.9856235 * d) - lw; } + +function astroRefraction(h) { + if (h < 0) // the following formula works for positive altitudes only. + h = 0; // if h = -0.08901179 a div/0 would occur. + + // formula 16.4 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + // 1.02 / tan(h + 10.26 / (h + 5.10)) h in degrees, result in arc minutes -> converted to rad: + return 0.0002967 / Math.tan(h + 0.00312536 / (h + 0.08901179)); +} + +// general sun calculations + +function solarMeanAnomaly(d) { return rad * (357.5291 + 0.98560028 * d); } + +function eclipticLongitude(M) { + + var C = rad * (1.9148 * sin(M) + 0.02 * sin(2 * M) + 0.0003 * sin(3 * M)), // equation of center + P = rad * 102.9372; // perihelion of the Earth + + return M + C + P + PI; +} + +function sunCoords(d) { + + var M = solarMeanAnomaly(d), + L = eclipticLongitude(M); + + return { + dec: declination(L, 0), + ra: rightAscension(L, 0) + }; +} + + +var SunCalc = {}; + + +// calculates sun position for a given date and latitude/longitude + +SunCalc.getPosition = function (date, lat, lng) { + + var lw = rad * -lng, + phi = rad * lat, + d = toDays(date), + + c = sunCoords(d), + H = siderealTime(d, lw) - c.ra; + + return { + azimuth: azimuth(H, phi, c.dec), + altitude: altitude(H, phi, c.dec) + }; +}; + + +// sun times configuration (angle, morning name, evening name) + +var times = SunCalc.times = [ + [-0.833, 'sunrise', 'sunset' ], + [ -0.3, 'sunriseEnd', 'sunsetStart' ], + [ -6, 'dawn', 'dusk' ], + [ -12, 'nauticalDawn', 'nauticalDusk'], + [ -18, 'nightEnd', 'night' ], + [ 6, 'goldenHourEnd', 'goldenHour' ] +]; + +// adds a custom time to the times config + +SunCalc.addTime = function (angle, riseName, setName) { + times.push([angle, riseName, setName]); +}; + + +// calculations for sun times + +var J0 = 0.0009; + +function julianCycle(d, lw) { return Math.round(d - J0 - lw / (2 * PI)); } + +function approxTransit(Ht, lw, n) { return J0 + (Ht + lw) / (2 * PI) + n; } +function solarTransitJ(ds, M, L) { return J2000 + ds + 0.0053 * sin(M) - 0.0069 * sin(2 * L); } + +function hourAngle(h, phi, d) { return acos((sin(h) - sin(phi) * sin(d)) / (cos(phi) * cos(d))); } +function observerAngle(height) { return -2.076 * Math.sqrt(height) / 60; } + +// returns set time for the given sun altitude +function getSetJ(h, lw, phi, dec, n, M, L) { + + var w = hourAngle(h, phi, dec), + a = approxTransit(w, lw, n); + return solarTransitJ(a, M, L); +} + + +// calculates sun times for a given date, latitude/longitude, and, optionally, +// the observer height (in meters) relative to the horizon + +SunCalc.getTimes = function (date, lat, lng, height) { + + height = height || 0; + + var lw = rad * -lng, + phi = rad * lat, + + dh = observerAngle(height), + + d = toDays(date), + n = julianCycle(d, lw), + ds = approxTransit(0, lw, n), + + M = solarMeanAnomaly(ds), + L = eclipticLongitude(M), + dec = declination(L, 0), + + Jnoon = solarTransitJ(ds, M, L), + + i, len, time, h0, Jset, Jrise; + + + var result = { + solarNoon: fromJulian(Jnoon), + nadir: fromJulian(Jnoon - 0.5) + }; + + for (i = 0, len = times.length; i < len; i += 1) { + time = times[i]; + h0 = (time[0] + dh) * rad; + + Jset = getSetJ(h0, lw, phi, dec, n, M, L); + Jrise = Jnoon - (Jset - Jnoon); + + result[time[1]] = fromJulian(Jrise); + result[time[2]] = fromJulian(Jset); + } + + return result; +}; + + +// moon calculations, based on http://aa.quae.nl/en/reken/hemelpositie.html formulas + +function moonCoords(d) { // geocentric ecliptic coordinates of the moon + + var L = rad * (218.316 + 13.176396 * d), // ecliptic longitude + M = rad * (134.963 + 13.064993 * d), // mean anomaly + F = rad * (93.272 + 13.229350 * d), // mean distance + + l = L + rad * 6.289 * sin(M), // longitude + b = rad * 5.128 * sin(F), // latitude + dt = 385001 - 20905 * cos(M); // distance to the moon in km + + return { + ra: rightAscension(l, b), + dec: declination(l, b), + dist: dt + }; +} + +SunCalc.getMoonPosition = function (date, lat, lng) { + + var lw = rad * -lng, + phi = rad * lat, + d = toDays(date), + + c = moonCoords(d), + H = siderealTime(d, lw) - c.ra, + h = altitude(H, phi, c.dec), + // formula 14.1 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + pa = atan(sin(H), tan(phi) * cos(c.dec) - sin(c.dec) * cos(H)); + + h = h + astroRefraction(h); // altitude correction for refraction + + return { + azimuth: azimuth(H, phi, c.dec), + altitude: h, + distance: c.dist, + parallacticAngle: pa + }; +}; + + +// calculations for illumination parameters of the moon, +// based on http://idlastro.gsfc.nasa.gov/ftp/pro/astro/mphase.pro formulas and +// Chapter 48 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + +SunCalc.getMoonIllumination = function (date) { + + var d = toDays(date || new Date()), + s = sunCoords(d), + m = moonCoords(d), + + sdist = 149598000, // distance from Earth to Sun in km + + phi = acos(sin(s.dec) * sin(m.dec) + cos(s.dec) * cos(m.dec) * cos(s.ra - m.ra)), + inc = atan(sdist * sin(phi), m.dist - sdist * cos(phi)), + angle = atan(cos(s.dec) * sin(s.ra - m.ra), sin(s.dec) * cos(m.dec) - + cos(s.dec) * sin(m.dec) * cos(s.ra - m.ra)); + + return { + fraction: (1 + cos(inc)) / 2, + phase: 0.5 + 0.5 * inc * (angle < 0 ? -1 : 1) / Math.PI, + angle: angle + }; +}; + + +function hoursLater(date, h) { + return new Date(date.valueOf() + h * dayMs / 24); +} + +// calculations for moon rise/set times are based on http://www.stargazing.net/kepler/moonrise.html article + +SunCalc.getMoonTimes = function (date, lat, lng, inUTC) { + var t = new Date(date); + if (inUTC) t.setUTCHours(0, 0, 0, 0); + else t.setHours(0, 0, 0, 0); + + var hc = 0.133 * rad, + h0 = SunCalc.getMoonPosition(t, lat, lng).altitude - hc, + h1, h2, rise, set, a, b, xe, ye, d, roots, x1, x2, dx; + + // go in 2-hour chunks, each time seeing if a 3-point quadratic curve crosses zero (which means rise or set) + for (var i = 1; i <= 24; i += 2) { + h1 = SunCalc.getMoonPosition(hoursLater(t, i), lat, lng).altitude - hc; + h2 = SunCalc.getMoonPosition(hoursLater(t, i + 1), lat, lng).altitude - hc; + + a = (h0 + h2) / 2 - h1; + b = (h2 - h0) / 2; + xe = -b / (2 * a); + ye = (a * xe + b) * xe + h1; + d = b * b - 4 * a * h1; + roots = 0; + + if (d >= 0) { + dx = Math.sqrt(d) / (Math.abs(a) * 2); + x1 = xe - dx; + x2 = xe + dx; + if (Math.abs(x1) <= 1) roots++; + if (Math.abs(x2) <= 1) roots++; + if (x1 < -1) x1 = x2; + } + + if (roots === 1) { + if (h0 < 0) rise = i + x1; + else set = i + x1; + + } else if (roots === 2) { + rise = i + (ye < 0 ? x2 : x1); + set = i + (ye < 0 ? x1 : x2); + } + + if (rise && set) break; + + h0 = h2; + } + + var result = {}; + + if (rise) result.rise = hoursLater(t, rise); + if (set) result.set = hoursLater(t, set); + + if (!rise && !set) result[ye > 0 ? 'alwaysUp' : 'alwaysDown'] = true; + + return result; +}; + + +// export as Node module / AMD module / browser variable +if (typeof exports === 'object' && typeof module !== 'undefined') module.exports = SunCalc; +else if (typeof define === 'function' && define.amd) define(SunCalc); +else window.SunCalc = SunCalc; + +}()); diff --git a/RVO48/flow/helper/utils.js b/RVO48/flow/helper/utils.js new file mode 100755 index 0000000..dbffe45 --- /dev/null +++ b/RVO48/flow/helper/utils.js @@ -0,0 +1,161 @@ +const fs = require('fs').promises; + +function bytesToInt(bytes, numberOfBytes) { + let buffer = []; + if (Array.isArray(bytes)) { + buffer = bytes.slice(0); + if (numberOfBytes != undefined) { + buffer = bytes.slice(bytes.length - numberOfBytes); + } + } + else buffer.push(bytes); + + let result = 0; + for (let i = 0; i < buffer.length; i++) { + result = (result << 8) | buffer[i]; + } + + return result >>> 0; //ensure it's an unsigned 32-bit number +} + +function resizeArray(arr, newSize, defaultValue) { + while (newSize > arr.length) + arr.push(defaultValue); + arr.length = newSize; +} + +longToByteArray = function(/*long*/long) { + // we want to represent the input as a 8-bytes array + var byteArray = [0, 0, 0, 0, 0, 0, 0, 0]; + + for (var index = 0; index < byteArray.length; index++) { + var byte = long & 0xff; + byteArray[index] = byte; + long = (long - byte) / 256; + } + + return byteArray; +}; + +function addDays(date, days) { + var result = new Date(date); + result.setDate(result.getDate() + days); + return result; +} + +/* +sleep(2000).then(() => { + // Do something after the sleep! + + +}); +*/ + +function sleep(time) { + return new Promise((resolve) => setTimeout(resolve, time)); +} + +function isEmptyObject(obj) { + for (var name in obj) { + return false; + } + return true; +} + +function emptyJsObject(jsObject) { + Object.keys(jsObject).forEach(key => delete jsObject[key]); +} + +function convertUTCDateToLocalDate(date) { + var newDate = new Date(date); + newDate.setMinutes(date.getMinutes() + date.getTimezoneOffset()); + return newDate; +} + +function addZeroBefore(n) { + return (n < 10 ? '0' : '') + n; +} + + +/** + * Asynchronously writes data to a file. + * + * @param {string} filePath The path to the file. + * @param {string} data The data to write to the file. + * @param {boolean} [append=false] If true, appends the data to the file. If false, it overwrites the file. + */ +async function writeToFile(filePath, data, append = false) { + if (typeof data !== 'string') data = JSON.stringify(data, null, 2); + try { + if (append) { + // Append the data to the end of the file. This is the simplest way to append. + await fs.appendFile(filePath, data, 'utf8'); + console.log(`Successfully appended data to ${filePath} using fs.appendFile.`); + } else { + // Overwrite the file with the new data. + await fs.writeFile(filePath, data, 'utf8'); + console.log(`Successfully wrote (overwrote) data to ${filePath} using fs.writeFile.`); + } + } catch (error) { + console.error(`Error writing to file ${filePath}:`, error); + } +} + + + /** + * Checks if an item is present in an array and adds it if it's not. + * * @param {Array} arr The array to check. + * @param {*} item The item to add. + * @returns {Array} The modified array. + */ +const addToArrayIfUnique = (arr, item) => { + if (!arr.includes(item)) { + arr.push(item); + } + return arr; +}; + + +var convertBase = function() { + + function convertBase(baseFrom, baseTo) { + return function(num) { + return parseInt(num, baseFrom).toString(baseTo); + + }; + } + + // binary to decimal + convertBase.bin2dec = convertBase(2, 10); + + // binary to hexadecimal + convertBase.bin2hex = convertBase(2, 16); + + // decimal to binary + convertBase.dec2bin = convertBase(10, 2); + + // decimal to hexadecimal + convertBase.dec2hex = convertBase(10, 16); + + // hexadecimal to binary + convertBase.hex2bin = convertBase(16, 2); + + // hexadecimal to decimal + convertBase.hex2dec = convertBase(16, 10); + + return convertBase; +}(); + +module.exports = { + bytesToInt, + longToByteArray, + addDays, + addZeroBefore, + resizeArray, + isEmptyObject, + emptyJsObject, + sleep, + convertUTCDateToLocalDate, + writeToFile, + addToArrayIfUnique +} diff --git a/RVO48/flow/httprequest.js b/RVO48/flow/httprequest.js new file mode 100755 index 0000000..469c8cb --- /dev/null +++ b/RVO48/flow/httprequest.js @@ -0,0 +1,137 @@ +exports.id = 'httprequest'; +exports.title = 'HTTP Request'; +exports.group = 'HTTP'; +exports.color = '#5D9CEC'; +exports.input = true; +exports.version = '2.0.1'; +exports.output = 1; +exports.author = 'Peter Širka'; +exports.icon = 'cloud-upload'; + +exports.html = `
+
@(URL address)
+
+
+
@(HTTP method)
+
+
+
@(Serialization)
+
+
+
@(Download the content in chunks)
+
@(Keep persistent cookies)
+
@(Disable DNS cache)
+
@(Keep alive connection)
+
+
+
+
@(Custom headers)
+
@(Cookies)
+
+
+
+ +
+
+
+
@(User)
+
+
+
@(Password)
+
+
+
+
+
`; + +exports.readme = `# Request + +This component creates a request with received data. + +__Response:__ +\`\`\`javascript +{ + data: String, + headers: Object, + status: Number, + host: String +} +\`\`\` + +__Dynamic arguments__: +Are performed via FlowData repository and can be used for URL address or for custom headers/cookies/auth. Use \`repository\` component for creating of dynamic arguments. Dynamic values are replaced in the form \`{key}\`: + +- url address e.g. \`https://.../{key}/\` +- headers values e.g. \`{token}\` +- cookies values e.g. \`{token}\``; + +exports.install = function(instance) { + + var can = false; + var flags = null; + var cookies2 = null; + + instance.on('data', function(response) { + can && instance.custom.send(response); + }); + + instance.custom.send = function(response) { + var options = instance.options; + + var headers = null; + var cookies = null; + + options.headers && Object.keys(options.headers).forEach(function(key) { + !headers && (headers = {}); + headers[key] = response.arg(options.headers[key]); + }); + + if (options.username && options.userpassword) { + !headers && (headers = {}); + headers['Authorization'] = 'Basic ' + U.createBuffer(response.arg(options.username + ':' + options.userpassword)).toString('base64'); + } + + options.cookies && Object.keys(options.cookies).forEach(function(key) { + !cookies && (cookies = {}); + cookies[key] = response.arg(options.cookies[key]); + }); + + if (options.chunks) { + U.download(response.arg(options.url), flags, options.stringify === 'none' ? null : response.data, function(err, response) { + response.on('data', (chunks) => instance.send2(chunks)); + }, cookies || cookies2, headers); + } else { + U.request(response.arg(options.url), flags, options.stringify === 'none' ? null : response.data, 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) + instance.error(err, response); + }, cookies || cookies2, headers); + } + }; + + instance.reconfigure = function() { + var options = instance.options; + can = options.url && options.url && options.method && options.stringify ? true : false; + instance.status(can ? '' : 'Not configured', can ? undefined : 'red'); + + if (!can) + return; + + flags = []; + flags.push(options.method.toLowerCase()); + options.stringify === 'json' && flags.push('json'); + options.stringify === 'raw' && flags.push('raw'); + options.keepalive && flags.push('keepalive'); + !options.nodns && flags.push('dnscache'); + if (options.persistentcookies) { + flags.push('cookies'); + cookies2 = {}; + } else + cookies2 = null; + }; + + instance.on('options', instance.reconfigure); + instance.reconfigure(); +}; \ No newline at end of file diff --git a/RVO48/flow/httpresponse.js b/RVO48/flow/httpresponse.js new file mode 100755 index 0000000..160a3bb --- /dev/null +++ b/RVO48/flow/httpresponse.js @@ -0,0 +1,76 @@ +exports.id = 'httpresponse'; +exports.title = 'HTTP Response'; +exports.group = 'HTTP'; +exports.color = '#5D9CEC'; +exports.icon = 'arrow-right'; +exports.input = true; +exports.output = ['#666D76']; +exports.version = '2.0.0'; +exports.author = 'Martin Smola'; +exports.readme = `# HTTP response + +HTTP response will respond with data recieved using data-type set in Settings form or plain text if not set. Output is the message duration \`Number\` in seconds.`; + +exports.html = `
+
@(Response data-type)
+
JSON is by default.
+
`; + +exports.install = function(instance) { + + var dursum = 0; + var durcount = 0; + + instance.on('data', function(flowdata) { + + var ctrl = flowdata.repository.controller; + var data = flowdata.data; + + if (!ctrl) { + instance.throw('No controller to use for response!'); + return; + } + + durcount++; + dursum += ((new Date() - flowdata.begin) / 1000).floor(2); + setTimeout2(instance.id, instance.custom.duration, 500, 10); + + ctrl.$flowdata = flowdata; + + var datatype = instance.options.datatype || 'json'; + if (datatype === 'emptyresponse') + return ctrl.plain(''); + + if (datatype !== 'json' && typeof(data) !== 'string') { + instance.throw('Incorect type of data, expected string, got ' + typeof(data)); + ctrl.plain(data == null ? '' : data.toString()); + return; + } + + switch(datatype) { + case 'html': + ctrl.content(data, 'text/html'); + break; + case 'plain': + ctrl.plain(data); + break; + case 'xml': + ctrl.content(data, 'text/xml'); + break; + default: + ctrl.json(data); + break; + } + }); + + instance.on('service', function() { + dursum = 0; + durcount = 0; + }); + + instance.custom.duration = function() { + var avg = (dursum / durcount).floor(2); + instance.status(avg + ' sec.'); + instance.send2(0, avg); + }; +}; diff --git a/RVO48/flow/httproute.js b/RVO48/flow/httproute.js new file mode 100755 index 0000000..583a19d --- /dev/null +++ b/RVO48/flow/httproute.js @@ -0,0 +1,326 @@ +exports.id = 'httproute'; +exports.title = 'HTTP Route'; +exports.group = 'HTTP'; +exports.color = '#5D9CEC'; +exports.icon = 'globe'; +exports.input = false; +exports.output = ['#6CAC5A', '#37BC9B']; +exports.version = '1.2.3'; +exports.author = 'Martin Smola'; +exports.cloning = false; +exports.options = { method: 'GET', url: '', size: 5, cacheexpire: '5 minutes', cachepolicy: 0, timeout: 5 }; +exports.dateupdated = '2021-01-21 18:30d'; +exports.readme = `# HTTP route + +__Outputs__: +- first output: raw data (cache is empty or is disabled) +- second output: cached data + +If one of the outputs is disabled then automatic responce with code "503 service unavailable" is sent. + +When a request comes in bellow object is available at \`flowdata.data\`: + +\`\`\`javascript +{ + params: { id: '1' }, // params for dynamic routes, e.g. /test/{id} + query: { msg: 'Hello' }, // parsed query string, e.g. /test/1?msg=Hello + body: { test: 'OK' }, // object if json requests otherwise string + headers: {}, // headers data + session: {}, // session data + user: {}, // user data + files: [], // uploaded files + url: '/users/', // a relative URL address + referrer: '/', // referrer + mobile: false, // determines mobile device + robot: false, // determines search robots/crawlsers + language: 'en' // determines language +} +\`\`\` + +See [documentation for flags](https://docs.totaljs.com/latest/en.html#api~HttpRouteOptionsFlags~unauthorize). These method flags are set automatically e.g. \`get, post, put, patch or delete\` + +--- + +\`id:ROUTE_ID\` flag cannot be used since it's already used by this component internally`; + +exports.html = `
+
+ +
+ +
+
+
@(HTTP method)
+
+
+
@(URL address)
+
+
+
+
+
@(Additional flags)
+
@(Separate flags by comma e.g. json, authorize)
+
+
+
@(Max. request size)
+
@(In kB kilobytes)
+
+
+
@(Timeout)
+
@(In seconds.)
+
+
+
+
+
+
@(Automatically respond with 200 OK?)
+
@(If not checked you need to use HTTP response component to respond to the request.)
+
+
@(Custom headers)
+
@(Cookies)
+
+
+
+
+
+
@(Cache policy)
+
@(User instance must contain id property.)
+
+
+
@(Expiration)
+
@(E.g. 5 minutes)
+
+
+
+`; + +exports.install = function(instance) { + + var route; + + var uninstall = function(id) { + if (F.is4) { + route && route.remove(); + route = null; + } else + UNINSTALL('route', id); + }; + + instance.custom.emptyresponse = function(self) { + self.plain(); + }; + + instance.reconfigure = function() { + + var options = instance.options; + + if (!options.url) { + instance.status('Not configured', 'red'); + return; + } + + if (typeof(options.flags) === 'string') + options.flags = options.flags.split(',').trim(); + + uninstall('id:' + instance.id); + + var flags = options.flags || []; + + flags.push('id:' + instance.id); + + if (!F.is4) + flags.push(options.method.toLowerCase()); + + options.timeout && flags.push(options.timeout * 1000); + + // Make unique values + flags = flags.filter(function(v, i, a) { + if(F.is4 && v.toString().toLowerCase() === options.method.toLowerCase()) + return false; // remove method + return a.indexOf(v) === i; + }); + + options.flags = flags; + var handler = function() { + + if (instance.paused || (instance.isDisabled && (instance.isDisabled('output', 0) || instance.isDisabled('output', 1)))) { + instance.status('503 Service Unavailable'); + this.status = 503; + this.json(); + return; + } + + var key; + var self = this; + + if (instance.options.emptyresponse) { + instance.status('200 OK'); + setTimeout(instance.custom.emptyresponse, 100, self); + + if (instance.hasConnection(0)) { + var data = instance.make({ + query: self.query, + body: self.body, + session: self.session, + user: self.user, + files: self.files, + headers: self.req.headers, + url: self.url, + params: self.params + }); + instance.send2(0, data); + } + + return; + } + + switch (instance.options.cachepolicy) { + case 1: // URL + key = 'rro' + instance.id + self.url.hash(); + break; + case 2: // URL + query + case 3: // URL + query + user + key = self.url; + var keys = Object.keys(self.query); + keys.sort(); + for (var i = 0, length = keys.length; i < length; i++) + key += keys[i] + self.query[keys[i]] + '&'; + if (instance.options.cachepolicy === 3 && self.user) + key += 'iduser' + self.user.id; + key = 'rro' + instance.id + key.hash(); + break; + } + + if (key && F.cache.get2(key)) { + var data = instance.make(F.cache.get2(key)); + data.repository.controller = self; + instance.send2(1, data); + } else { + + var data = instance.make({ + query: self.query, + body: self.body, + session: self.session, + user: self.user, + files: self.files, + headers: self.req.headers, + url: self.url, + params: self.params, + mobile: self.mobile, + robot: self.robot, + referrer: self.referrer, + language: self.language + }); + + data.repository.controller = self; + instance.send2(0, data); + key && FINISHED(self.res, () => F.cache.set(key, self.$flowdata.data, instance.options.cacheexpire)); + } + }; + + if (F.is4) + route = ROUTE(options.method.toUpperCase() + ' ' + options.url, handler, flags, options.size || 5); + else + F.route(options.url, handler, flags, options.size || 5); + + instance.status('Listening', 'green'); + }; + + instance.reconfigure(); + instance.on('options', instance.reconfigure); + instance.on('close', function(){ + uninstall('id:' + instance.id); + }); +}; + +// check url exists +FLOW.trigger('httproutecheckurl', function(next, data) { + var url = data.url; + var method = data.method; + if (url[url.length - 1] !== '/') + url += '/'; + var exists = F.routes.web.findItem(r => r.urlraw === url && r.method === method); + next(exists != null); +}); + +exports.uninstall = function() { + FLOW.trigger('httproutecheckurl', null); +}; diff --git a/RVO48/flow/infosender.js b/RVO48/flow/infosender.js new file mode 100755 index 0000000..587724f --- /dev/null +++ b/RVO48/flow/infosender.js @@ -0,0 +1,81 @@ +exports.id = 'infosender'; +exports.title = 'Info sender'; +exports.version = '1.0.0'; +exports.group = 'Worksys'; +exports.color = '#2134B0'; +exports.input = 2; +exports.output = 1 +exports.icon = 'bolt'; + +const { networkInterfaces } = require('os'); + +exports.html = `
+
+
+
CSV Import
+
+
+
`; + +exports.readme = `# send all data to projects.worksys.io, required to monitor status of controller(unipi)`; + +exports.install = function(instance) { + + let id; + let allValues = {}; + let sendAllValuesInterval; + let configured = false; + + let now = new Date(); + console.log(exports.title, "INSTALLED", now.toLocaleString("sk-SK")); + + const nets = networkInterfaces(); + let ipAddresses = Object.create(null); // Or just '{}', an empty object + + for (const name of Object.keys(nets)) { + for (const net of nets[name]) { + // Skip over non-IPv4 and internal (i.e. 127.0.0.1) addresses + if (net.family === 'IPv4' && !net.internal) { + if (!ipAddresses[name]) { + ipAddresses[name] = []; + } + ipAddresses[name].push(net.address); + } + } + } + + function sendValues() { + if (!configured) return; + + if (Object.keys(allValues).length > 0) { + let dataToSend = { ...allValues }; + dataToSend.id = id; + dataToSend.ipAddresses = ipAddresses; + + instance.send(0, dataToSend); + + allValues = {}; + } + } + + instance.on("close", () => { + clearInterval(sendAllValuesInterval); + }) + + instance.on("0", _ => { + id = FLOW.GLOBALS.settings.project_id; + if (id) configured = true; + else console.log(exports.title, "InfoSender: Unable to send data, no id"); + }) + + instance.on("1", flowdata => { + allValues = { ...allValues, ...flowdata.data }; + //console.log("DATA RECEIVED", flowdata.data); + }) + + sendAllValuesInterval = setInterval(() => { + sendValues(); + }, 60000 * 3); + +} + diff --git a/RVO48/flow/modbus_reader.js b/RVO48/flow/modbus_reader.js new file mode 100755 index 0000000..d6d9dad --- /dev/null +++ b/RVO48/flow/modbus_reader.js @@ -0,0 +1,346 @@ +exports.id = 'modbus_reader'; +exports.title = 'Modbus reader'; +exports.version = '2.0.0'; +exports.group = 'Worksys'; +exports.color = '#2134B0'; +exports.input = 1; +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; +//number of phases inRVO +let phases; +//phases where voltage is 0 (set) +let noVoltage; +let energyToSwitchLamps; + +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.phases = this.buildPhases(); + + this.startSocket(); + } + + buildPhases = () => { + let a = []; + for (let i = 1; i <= phases; i++) { + a.push(`Phase_${i}_voltage`) + } + return a; + } + + startSocket = () => { + + let obj = this; + + if (this.socket) { + this.socket.removeAllListeners(); + this.socket = null; + } + + 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('Modbus_reader: Socket connection error', e); //'ECONNREFUSED' or 'ECONNRESET' ?? + }); + + this.socket.on('close', function() { + console.log('Modbus_reader: Socket connection closed - Waiting 10 seconds before connecting 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 we just start to loop devices from the beginning, or there is just 1 device in config, we wait whole timeoutInterval + if (this.indexInDeviceConfig == 0 || deviceConfig.length === 1) 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 (this.phases.includes(singleValue)) { + let l = singleValue.split("_"); + let phase = parseInt(l[1]); + + // console.log(values[singleValue], tbName); + + if (values[singleValue] == 0) { + noVoltage.add(phase); + sendNotification("modbus_reader: checkNullVoltage", tbName, "no_voltage_on_phase", { phase: phase }, "", SEND_TO.tb, instance, "voltage" + phase); + // console.log('no voltage') + } + else { + noVoltage.delete(phase); + // console.log('voltage detected') + sendNotification("modbus_reader: checkNullVoltage", tbName, "voltage_on_phase_restored", { phase: phase }, "", SEND_TO.tb, instance, "voltage" + phase); + } + } + }) + } + + /** + * function sends notification to slack and to tb, if EM total_power value changes more than numberOfNodes*15. This should show, that RVO lamps has been switched on or off + */ + lampSwitchNotification = (values) => { + + if (!values.hasOwnProperty("total_power")) return; + + const actualTotalPower = values.total_power; + + if (actualTotalPower > energyToSwitchLamps && 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 <= energyToSwitchLamps && 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; + } + + function main() { + + phases = FLOW.GLOBALS.settings.phases; + tbName = FLOW.GLOBALS.settings.rvoTbName; + noVoltage = FLOW.GLOBALS.settings.no_voltage; + energyToSwitchLamps = FLOW.GLOBALS.settings.energy_to_switch_lamps / 2.5; //half value is enought to show if lamps are turned on or off + if (deviceConfig.length) mainSocket = new SocketWithClients(); + else console.log("Modbus_reader: no modbus device in configuration"); + + // this notification is to show, that flow (unipi) has been restarted + sendNotification("modbus_reader", tbName, "flow_restart", {}, "", SEND_TO.slack, instance); + } + + instance.on("0", function(_) { + main(); + }) + +} + diff --git a/RVO48/flow/monitorconsumption.js b/RVO48/flow/monitorconsumption.js new file mode 100755 index 0000000..64cc58e --- /dev/null +++ b/RVO48/flow/monitorconsumption.js @@ -0,0 +1,156 @@ +exports.id = 'monitorconsumption'; +exports.title = 'Consumption'; +exports.version = '1.0.0'; +exports.author = 'Peter Širka'; +exports.group = 'Monitoring'; +exports.color = '#967ADC'; +exports.input = 0; +exports.output = 1; +exports.icon = 'bug'; +exports.options = { interval: 5000, enabled: true, monitorconsumption: true, monitorsize: true, monitorconnections: true, monitorfiles: true }; +exports.click = true; +exports.readme = `# Consumption monitoring + +This component measure CPU and memory consumption, open files and open connections of this application. It uses these Linux commands: \`ps\`, \`lsof\`, \`netstat\` and \`df\`. + +__Data Example__: + +\`\`\`javascript +{ + cpu: 0, // percentage + memory: 4096, // in bytes + size: 34303, // directory size in bytes + files: 34, // count of open files + connections: 343, // count of connections + uptime: '1-12:34:00' +} +\`\`\``; + +exports.html = `
+
+
+
@(Interval in milliseconds)
+
+
+
+
Monitor: Consumption + uptime
+
Monitor: Count of open files
+
Monitor: Count of open connections
+
Monitor: Directory size
+
`; + +exports.install = function(instance) { + + var current = { cpu: 0, memory: 0, files: 0, connections: 0, size: 0, uptime: '', counter: 0 }; + var tproc = null; + var Exec = require('child_process').exec; + var reg_empty = /\s{2,}/g; + var reg_appdisksize = /^[\d.,]+/; + + instance.custom.run = function() { + + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + + var arr = []; + + // Get CPU and Memory consumption + instance.options.monitorconsumption && arr.push(function(next) { + Exec('ps -p {0} -o %cpu,rss,etime'.format(process.pid), function(err, response) { + + if (err) { + instance.throw(err); + } else { + var line = response.split('\n')[1]; + line = line.trim().replace(reg_empty, ' ').split(' '); + var cpu = line[0].parseFloat(); + current.cpu = cpu.floor(1); + current.memory = line[1].parseInt2() * 1024; // kB to bytes + current.uptime = line[2]; + } + + next(); + }); + }); + + // Get count of open files + instance.options.monitorfiles && arr.push(function(next) { + Exec('lsof -a -p {0} | wc -l'.format(process.pid), function(err, response) { + if (err) + instance.throw(err); + else + current.files = response.trim().parseInt2(); + next(); + }); + }); + + // Get count of opened network connections + instance.options.monitorconnections && arr.push(function(next) { + Exec('netstat -an | grep :{0} | wc -l'.format(F.port), function(err, response) { + if (err) { + instance.throw(err); + } else { + current.connections = response.trim().parseInt2() - 1; + if (current.connections < 0) + current.connections = 0; + } + next(); + }); + }); + + // Get directory size + instance.options.monitorsize && current.counter % 5 !== 0 && arr.push(function(next) { + Exec('du -hsb ' + process.cwd(), function(err, response) { + if (err) { + instance.throw(err); + } else { + var match = response.trim().match(reg_appdisksize); + match && (current.size = match.toString().trim().parseInt2()); + } + next(); + }); + }); + + arr.async(function() { + + tproc && clearTimeout(tproc); + + if (instance.options.enabled) { + tproc = setTimeout(instance.custom.run, instance.options.interval); + instance.send2(current); + } + + instance.custom.status(); + current.counter++; + }); + }; + + instance.custom.status = function() { + if (instance.options.enabled) + instance.status('{0}% / {1}'.format(current.cpu, current.memory.filesize())); + else + instance.status('Disabled', 'red'); + }; + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + + if (instance.options.enabled) { + current.counter = 0; + instance.custom.run(); + } + + }); + + instance.on('close', function() { + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + }); + + setTimeout(instance.custom.run, 1000); +}; \ No newline at end of file diff --git a/RVO48/flow/monitordisk.js b/RVO48/flow/monitordisk.js new file mode 100755 index 0000000..f4fdaa0 --- /dev/null +++ b/RVO48/flow/monitordisk.js @@ -0,0 +1,96 @@ +exports.id = 'monitordisk'; +exports.title = 'Disk'; +exports.version = '1.0.0'; +exports.author = 'Peter Širka'; +exports.group = 'Monitoring'; +exports.color = '#F6BB42'; +exports.output = 1; +exports.icon = 'hdd-o'; +exports.click = true; +exports.options = { interval: 8000, path: '/', enabled: true }; +exports.readme = `# Disk monitoring + +This component monitors disk \`bytes\` consumption in Linux systems. It uses \`df\` command. + +__Data Example__: + +\`\`\`javascript +{ + total: 474549649408, + used: 39125245952, + free: 411294994432 +} +\`\`\``; + +exports.html = `
+
+
+
@(Interval in milliseconds)
+
+
+
@(Path)
+
+
+
`; + +exports.install = function(instance) { + + var current = { total: 0, used: 0, free: 0, path: '', type: '', percentUsed: 0 }; + var tproc = null; + + instance.custom.run = function() { + + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + + if (!instance.options.enabled) + return; + + require('child_process').exec('df -hTB1 ' + instance.options.path, function(err, response) { + + tproc = setTimeout(instance.custom.run, instance.options.interval); + + if (err) { + instance.error(err); + return; + } + + response.parseTerminal(function(line) { + if (line[0][0] !== '/') + return; + current.total = line[2].parseInt(); + current.free = line[4].parseInt(); + current.used = line[3].parseInt(); + current.path = instance.options.path || '/'; + current.type = line[1]; + current.percentUsed = line[5]; + instance.custom.status(); + instance.send2(current); + }); + }); + }; + + instance.custom.status = function() { + if (instance.options.enabled) + instance.status(current.free.filesize() + ' / ' + current.total.filesize()); + else + instance.status('Disabled', 'red'); + }; + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + instance.options.enabled && instance.custom.run(); + }); + + instance.on('close', function() { + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + }); + + setTimeout(instance.custom.run, 1000); +}; \ No newline at end of file diff --git a/RVO48/flow/monitormemory.js b/RVO48/flow/monitormemory.js new file mode 100755 index 0000000..2decbc4 --- /dev/null +++ b/RVO48/flow/monitormemory.js @@ -0,0 +1,87 @@ +exports.id = 'monitormemory'; +exports.title = 'Memory'; +exports.version = '1.0.0'; +exports.author = 'Peter Širka'; +exports.group = 'Monitoring'; +exports.color = '#F6BB42'; +exports.output = 1; +exports.click = true; +exports.icon = 'microchip'; +exports.options = { interval: 8000, enabled: true }; +exports.readme = `# Memory monitoring + +This component monitors memory \`bytes\` consumption in Linux systems. It uses \`free\` command. + +__Data Example__: + +\`\`\`javascript +{ + total: 33558769664, + used: 1998868480, + free: 2653708288 +} +\`\`\``; + +exports.html = `
+
+
+
@(Interval in milliseconds)
+
+
+
`; + +exports.install = function(instance) { + + var current = { total: 0, used: 0, free: 0 }; + var tproc = null; + + instance.custom.run = function() { + + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + + if (!instance.options.enabled) + return; + + require('child_process').exec('free -b -t', function(err, response) { + + tproc = setTimeout(instance.custom.run, instance.options.interval); + + if (err) { + instance.error(err); + return; + } + + var memory = response.split('\n')[1].match(/\d+/g); + current.total = memory[0].parseInt(); + current.used = memory[1].parseInt() - memory[3].parseInt(); + current.free = current.total - current.used; + instance.custom.status(); + instance.send2(current); + }); + }; + + instance.custom.status = function() { + if (instance.options.enabled) + instance.status(current.free.filesize() + ' / ' + current.total.filesize()); + else + instance.status('Disabled', 'red'); + }; + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + instance.options.enabled && instance.custom.run(); + }); + + instance.on('close', function() { + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + }); + + setTimeout(instance.custom.run, 1000); +}; \ No newline at end of file diff --git a/RVO48/flow/nodesdb_changecheck.js b/RVO48/flow/nodesdb_changecheck.js new file mode 100755 index 0000000..9adab62 --- /dev/null +++ b/RVO48/flow/nodesdb_changecheck.js @@ -0,0 +1,77 @@ +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 = 2; +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); + } + } + + //kedze do slacku posielame stringy, na cloud musime previest vsetky stringy spat na objekty: + // Funkcia na parsovanie všetkých reťazcov v poli + const parseArray = (arr) => { + return arr.map(jsonString => JSON.parse(jsonString)); + }; + + 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); + if (FLOW.GLOBALS.settings.send_changed_node_numbers) instance.send(1, { aktualneNody: parseArray(zmenene), originalne: parseArray(Array.from(set2)) }); + } + 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/RVO48/flow/show_dbdata.js b/RVO48/flow/show_dbdata.js new file mode 100755 index 0000000..1e23ff7 --- /dev/null +++ b/RVO48/flow/show_dbdata.js @@ -0,0 +1,243 @@ +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 = 8; +exports.output = 1; + +const { exec } = require('child_process'); + +exports.install = 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 }) + }) + instance.on("5", _ => { + exec("sudo tail -n 25 monitor.txt", (err, stdout, stderr) => { + if (err || stderr) instance.send(0, { err, stderr }); + else instance.send(0, stdout); + }) + }) + instance.on("6", _ => { + exec("sudo tail -n 25 err.txt", (err, stdout, stderr) => { + if (err || stderr) instance.send(0, { err, stderr }); + else instance.send(0, stdout); + }) + }) + instance.on("7", _ => { + instance.send(0, FLOW.deviceStatus); + }) +}; + + +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/RVO48/flow/slack_filter.js b/RVO48/flow/slack_filter.js new file mode 100755 index 0000000..6618523 --- /dev/null +++ b/RVO48/flow/slack_filter.js @@ -0,0 +1,188 @@ +exports.id = 'slack_filter'; +exports.title = 'Slack Filter'; +exports.group = 'Citysys'; +exports.color = '#30E193'; +exports.input = 2; +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 = `
+
+
+
@(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('0', 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']['en']; + 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"] = []; + } + + instance.options.name = FLOW.GLOBALS.settings.rvo_name; + if (instance.options.name) { + instance.status('Running'); + running = true; + } else { + instance.status('Please run options again', 'red'); + running = false; + } + } catch (e) { + instance.error('Citysys connector: ' + e.message); + } + }; + + instance.on('options', instance.reconfigure); + + instance.on("1", _ => { + instance.reconfigure(); + }) +}; diff --git a/RVO48/flow/thermometer.js b/RVO48/flow/thermometer.js new file mode 100755 index 0000000..fc7074d --- /dev/null +++ b/RVO48/flow/thermometer.js @@ -0,0 +1,99 @@ +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 = 5;//minutes +let NUMBER_OF_FAILURES_TO_SEND_ERROR = 13; + +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) => { + + 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); + setTimeout(main, 20000); + }) +}; diff --git a/RVO48/flow/trigger.js b/RVO48/flow/trigger.js new file mode 100755 index 0000000..27545a8 --- /dev/null +++ b/RVO48/flow/trigger.js @@ -0,0 +1,79 @@ +exports.id = 'trigger'; +exports.title = 'Trigger'; +exports.group = 'Inputs'; +exports.color = '#F6BB42'; +exports.click = true; +exports.output = 1; +exports.version = '1.1.0'; +exports.author = 'Martin Smola'; +exports.icon = 'play'; + +exports.html = `
+
@(Data type (String by default))
+
@(Data)
+
Trigger 5s after initialization.
+
@(Useful when there's a need to run certain flow when the app restarts, etc.)
+
`; + +exports.readme = `# Trigger + +- Clicking on the component starts the chain +- Settings allows to set a data-type and a value`; + +exports.install = function(instance) { + + var value; + + instance.on('click', () => instance.send2(value)); + + instance.reconfigure = function() { + var options = instance.options; + value = null; + switch (options.datatype) { + case 'integer': + value = options.data.parseInt2('error'); + value = value === 'error' ? NaN : value; + break; + case 'float': + value = options.data.parseFloat2('error'); + value = value === 'error' ? NaN : value; + break; + case 'date': + options.data = options.data.toString(); + var num = options.data.parseInt('error'); + num === 'error' && (num = options.data.parseDate('error')); + num === 'error' && (num = null); + value = num ? new Date(num).toUTCString() : num; + break; + case 'object': + try { + value = (new Function('return ' + options.data))(); + } catch (e) { + instance.error(e); + } + break; + case 'boolean': + value = options.data.parseBoolean(); + break; + case 'buffer': + try { + value = U.createBuffer(options.data); + } catch (e) { + instance.error(e); + } + break; + case 'string': + default: + value = '' + (options.data || ''); + break; + } + }; + + instance.on('options', instance.reconfigure); + instance.reconfigure(); + + if (instance.options.restart) + setTimeout(function(){ + instance.send2(value); + }, 5000); +}; diff --git a/RVO48/flow/variables.txt b/RVO48/flow/variables.txt new file mode 100755 index 0000000..e69de29 diff --git a/RVO48/flow/virtualwirein.js b/RVO48/flow/virtualwirein.js new file mode 100755 index 0000000..38a4e42 --- /dev/null +++ b/RVO48/flow/virtualwirein.js @@ -0,0 +1,43 @@ +exports.id = 'virtualwirein'; +exports.title = 'Virtual wire in'; +exports.version = '1.0.0'; +exports.author = 'Martin Smola'; +exports.color = '#303E4D'; +exports.icon = 'sign-in'; +exports.input = false; +exports.output = 1; +exports.options = {}; +exports.readme = `# Virtual wire in + +When the wires between the components are mess it's time to use Virtual wire.`; + +exports.html = `
+
@(Wire name)
+
+`; + +exports.install = function(instance) { + + instance.custom.reconfigure = function(options){ + if (instance.options.wirename) { + instance.status(instance.options.wirename); + } else + instance.status('Not configured', 'red'); + }; + + ON('virtualwire', function(wirename, flowdata){ + if (instance.options.wirename && instance.options.wirename === wirename) + instance.send(flowdata); + }); + + instance.on('options', instance.custom.reconfigure); + instance.custom.reconfigure(); +}; diff --git a/RVO48/flow/virtualwireout.js b/RVO48/flow/virtualwireout.js new file mode 100755 index 0000000..94a1e4f --- /dev/null +++ b/RVO48/flow/virtualwireout.js @@ -0,0 +1,41 @@ +exports.id = 'virtualwireout'; +exports.title = 'Virtual wire out'; +exports.version = '1.0.0'; +exports.author = 'Martin Smola'; +exports.color = '#303E4D'; +exports.icon = 'sign-out'; +exports.input = true; +exports.options = {}; +exports.readme = `# Virtual wire out + +When the wires between the components are mess it's time to use Virtual wire.`; + +exports.html = `
+
@(Wire name)
+
+`; + +exports.install = function(instance) { + + instance.custom.reconfigure = function(){ + if (instance.options.wirename) { + instance.status(instance.options.wirename); + } else + instance.status('Not configured', 'red'); + }; + + instance.on('data', function(flowdata) { + EMIT('virtualwire', instance.options.wirename, flowdata); + }); + + instance.on('options', instance.custom.reconfigure); + instance.custom.reconfigure(); +}; diff --git a/RVO48/flow/wsmqttpublish.js b/RVO48/flow/wsmqttpublish.js new file mode 100755 index 0000000..0eba804 --- /dev/null +++ b/RVO48/flow/wsmqttpublish.js @@ -0,0 +1,448 @@ +exports.id = 'wsmqttpublish'; +exports.title = 'WS MQTT publish'; +exports.group = 'MQTT'; +exports.color = '#888600'; +exports.version = '1.0.2'; +exports.icon = 'sign-out'; +exports.input = 2; +exports.output = 3; +exports.options = { host: 'tb-stage.worksys.io', port: 1883, clientid: "", username: "" }; + +exports.html = `
+
+
+
Hostname or IP address (if not empty - setting will override db setting)
+
+
+
Port
+
+
+
+
+
@(Client id)
+
+
+
@(Username)
+
+
+
`; + + +exports.readme = ` +# WS MQTT Publish + +Version 1.0.3. + +Added: +- database collections, +- 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 = { + debug: 0, + rpcCall: 1, + services: 2 +} + +//CONFIG +let createTelemetryBackup = true; +let saveTelemetryOnError = true;//backup_on_failure overrides this value +//------------------------ + +let rollers; +if (createTelemetryBackup) rollers = require('streamroller'); + +const noSqlFileSizeLimit = 4194304;//use 5MB - 4194304 +let insertNoSqlCounter = 0; +let insertBackupNoSqlCounter = 0; +let processingData = false; + +let backup_on_failure = false;//== saveTelemetryOnError - create backup client 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; + +process.on('uncaughtException', function(err) { + + errLogger.error('uncaughtException:', err.message) + errLogger.error(err.stack); + + //TODO + //send to service + + //process.exit(1); +}) + +const nosql = NOSQL('tbdata'); +const nosqlBackup = NOSQL('/backup/tbdata'); + + +exports.install = function(instance) { + + var client; + var opts; + var clientReady = false; + + // wsmqtt status for notification purposes on projects.worksys.io database + let wsmqttName = null; + let sendWsStatusVar = null; + let wsmqtt_status = 'disconnected'; + + 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'; + } + + function sendWsStatus() { + instance.send(SEND_TO.services, { [wsmqttName]: wsmqtt_status }); + } + + + function main() { + if (!FLOW.dbLoaded) return; + + loadSettings(); + clearInterval(sendWsStatus); + sendWsStatusVar = setInterval(sendWsStatus, 180000); + } + + //set opts according to db settings + function loadSettings() { + + if (instance.options.host !== "") { + //override settings from database + var o = instance.options; + opts = { + host: o.host, + port: o.port, + clientId: o.clientid, + username: o.username, + rejectUnauthorized: false, + resubscribe: false + }; + + wsmqttName = getWsmqttName(o.host); + + console.log("wsmqttpublich -> loadSettings from instance.options", instance.options); + } + else { + + const SETTINGS = FLOW.GLOBALS.settings; + backup_on_failure = SETTINGS.backup_on_failure; + saveTelemetryOnError = backup_on_failure; + + restore_from_backup = SETTINGS.restore_from_backup; + restore_backup_wait = SETTINGS.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; + + opts = { + host: mqtt_host, + port: mqtt_port, + keepalive: 10, + clientId: mqtt_clientid, + username: mqtt_username, + rejectUnauthorized: false, + resubscribe: false + }; + + wsmqttName = getWsmqttName(mqtt_host); + } + + connectToTbServer(); + } + + function connectToTbServer() { + 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"); + //monitor.info("MQTT client connected"); + + sendClientError = true; + clientReady = true; + wsmqtt_status = 'connected'; + }); + + client.on('reconnect', function() { + instance.status("Reconnecting", "yellow"); + clientReady = false; + }); + + client.on('message', function(topic, message) { + // message is type of buffer + message = message.toString(); + if (message[0] === '{') { + TRY(function() { + + message = JSON.parse(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 } }); + } + + }, () => instance.debug('MQTT: Error parsing data', message)); + } + + instance.send(SEND_TO.rpcCall, { "topic": topic, "content": message }); + }); + + client.on('close', function() { + clientReady = false; + wsmqtt_status = 'disconnected'; + + instance.status("Disconnected", "red"); + instance.send(SEND_TO.debug, { "message": "Client CLOSE signal received !" }); + }); + + client.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; + wsmqtt_status = 'disconnected'; + }); + + } + + + instance.on("0", _ => { + main(); + }) + + + instance.on('1', function(data) { + + if (clientReady) { + //do we have some data in backup file? if any, process data from database + if (saveTelemetryOnError) { + //read telemetry data and send back to server + if (!processingData) processDataFromDatabase(); + } + + let stringifiedJson = JSON.stringify(data.data); + client.publish("v1/gateway/telemetry", stringifiedJson, { qos: 1 }); + + //backup telemetry + if (createTelemetryBackup) { + data.data.id = UID(); + nosqlBackup.insert(data.data); + + insertBackupNoSqlCounter++; + if (insertBackupNoSqlCounter > 150) { + let options = { compress: true }; + let path = __dirname + "/../databases/backup/tbdata.nosql"; + var stream = new rollers.RollingFileStream(path, noSqlFileSizeLimit, 150, options); + stream.write(""); + stream.end(); + + insertBackupNoSqlCounter = 0; + } + } + + } + 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 (saveTelemetryOnError) { + //create new file from tbdata.nosql, if file size exceeds given limit, and clear tbdata.nosql + makeBackupFromDbFile(); + + //write to tb + data.data.id = UID(); + nosql.insert(data.data); + } + } + }); + + + instance.close = function(done) { + if (clientReady) { + client.end(); + clearInterval(sendWsStatusVar); + } + }; + + + function getDbBackupFileCounter(type) { + var files = fs.readdirSync(__dirname + "/../databases"); + + let counter = 0; + for (var i = 0; i < files.length; i++) { + + if (files[i] == "tbdata.nosql") continue; + + if (files[i].endsWith(".nosql")) { + + let pos = files[i].indexOf("."); + if (pos > -1) { + + let fileCounter = counter; + let firstDigit = files[i].slice(0, pos); + + fileCounter = parseInt(firstDigit); + if (isNaN(fileCounter)) fileCounter = 0; + //console.log("getDbBackupFileCounter digit:", files[i], firstDigit, fileCounter, isNaN(fileCounter), type); + + if (type == "max") { + if (fileCounter > counter) { + counter = fileCounter; + } + } + else if (type == "min") { + if (counter == 0) counter = fileCounter; + + if (fileCounter < counter) { + counter = fileCounter; + } + } + } + } + + } + + if (type == "max") counter++; + + return counter; + } + + const makeBackupFromDbFile = async () => { + + if (!saveTelemetryOnError) return; + + //to avoid large file: tbdata.nosql + + //init value is 0! + if (insertNoSqlCounter > 0) { + --insertNoSqlCounter; + return; + } + + insertNoSqlCounter = 100; + + let source = __dirname + "/../databases/tbdata.nosql"; + + var stats = fs.statSync(source); + var fileSizeInBytes = stats.size; + + if (fileSizeInBytes > noSqlFileSizeLimit) { + + let counter = 1; + counter = getDbBackupFileCounter("max"); + + let destination = __dirname + "/../databases/" + counter + "." + "tbdata.nosql"; + + //make backup file + fs.copyFileSync(source, destination); + //fs.renameSync(p, p + "." + counter); + + //clear tbdata.nosql + fs.writeFileSync(source, ""); + fs.truncateSync(source, 0); + + } + } + + const processDataFromDatabase = async () => { + + if (restore_from_backup <= 0) return; + + //calculate diff + const now = new Date(); + let currentTime = now.getTime(); + let diff = currentTime - lastRestoreTime; + + if ((diff / 1000) < restore_backup_wait) { + //console.log("*********restore_backup_wait", diff, restore_backup_wait); + return; + } + + processingData = true; + + //get filename to process + let counter = getDbBackupFileCounter("min"); + + //we have some backup files + let dataBase = 'tbdata'; + + var nosql; + if (counter == 0) dataBase = 'tbdata'; + else dataBase = counter + "." + 'tbdata'; + + nosql = NOSQL(dataBase); + + //select all data - use limit restore_from_backup + let records = await promisifyBuilder(nosql.find().take(restore_from_backup)); + + for (let i = 0; i < records.length; i++) { + if (clientReady) { + + let item = records[i]; + let id = item.id; + + if (id !== undefined) { + //console.log("------------processDataFromDatabase - remove", id, dataBase, i); + + try { + + let message = JSON.parse(JSON.stringify(item)); + delete message.id; + + client.publish("v1/gateway/telemetry", JSON.stringify(message), { qos: 1 }); + + //remove from database + await promisifyBuilder(nosql.remove().where("id", id)); + + } catch (error) { + //process error + console.log("processDataFromDatabase", error); + } + + } + + } + else { + processingData = false; + return; + } + } + + if (records.length > 0) { + //clean backup file + if (counter > 0) nosql.clean(); + } + + //no data in db, remove + if (records.length == 0) { + if (counter > 0) nosql.drop(); + } + + const d = new Date(); + lastRestoreTime = d.getTime(); + + processingData = false; + + } + + instance.on('options', main); + //instance.reconfigure(); +}; diff --git a/RVO48/monitor.txt b/RVO48/monitor.txt new file mode 100755 index 0000000..a471792 --- /dev/null +++ b/RVO48/monitor.txt @@ -0,0 +1,4562 @@ +[2024-10-11T13:29:52.582] [INFO] monitorLogs - MQTT broker error Error: connect ECONNREFUSED 192.168.252.1:1883 + at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1159:16) { + errno: -111, + code: 'ECONNREFUSED', + syscall: 'connect', + address: '192.168.252.1', + port: 1883 +} +[2024-10-11T13:30:22.813] [INFO] monitorLogs - MQTT broker connected +[2024-10-11T18:41:02.579] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-11T18:41:02.612] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-11T18:41:02.646] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-12T03:33:01.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-12 03:33:01 +[2024-10-12T07:37:52.347] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-12T07:37:52.381] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-12T07:37:52.414] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-12T14:55:27.405] [INFO] monitorLogs - MQTT broker connected +[2024-10-12T18:39:02.269] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-12T18:39:02.303] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-12T18:39:02.337] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-13T03:33:02.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-13 03:33:02 +[2024-10-13T07:39:20.275] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-13T07:39:20.308] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-13T07:39:20.342] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-13T18:37:02.843] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-13T18:37:02.881] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-13T18:37:02.915] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-14T03:33:03.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-14 03:33:03 +[2024-10-14T07:40:50.398] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-14T07:40:50.432] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-14T07:40:50.466] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-14T18:35:04.182] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-14T18:35:04.217] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-14T18:35:04.251] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-15T03:33:05.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-15 03:33:05 +[2024-10-15T06:43:40.932] [INFO] monitorLogs - MQTT broker connected +[2024-10-15T06:44:24.696] [INFO] monitorLogs - MQTT broker connected +[2024-10-15T06:47:29.751] [INFO] monitorLogs - MQTT broker connected +[2024-10-15T07:27:18.192] [INFO] monitorLogs - MQTT broker connected +[2024-10-15T07:29:39.176] [INFO] monitorLogs - MQTT broker connected +[2024-10-15T07:41:50.385] [INFO] monitorLogs - MQTT broker connected +[2024-10-15T07:42:21.154] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-15T07:42:21.190] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-15T07:42:21.223] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-15T07:42:46.658] [INFO] monitorLogs - MQTT broker connected +[2024-10-15T07:43:51.138] [INFO] monitorLogs - MQTT broker connected +[2024-10-15T08:01:53.916] [INFO] monitorLogs - MQTT broker connected +[2024-10-15T08:31:09.012] [INFO] monitorLogs - MQTT broker connected +[2024-10-15T18:33:06.323] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-15T18:33:06.358] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-15T18:33:06.392] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-16T03:33:06.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-16 03:33:06 +[2024-10-16T07:43:53.573] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-16T07:43:53.608] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-16T07:43:53.658] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-16T08:52:25.566] [INFO] monitorLogs - MQTT broker connected +[2024-10-16T08:52:46.122] [INFO] monitorLogs - MQTT broker connected +[2024-10-16T08:59:53.872] [INFO] monitorLogs - MQTT broker connected +[2024-10-16T09:00:33.156] [INFO] monitorLogs - MQTT broker connected +[2024-10-16T09:00:54.710] [INFO] monitorLogs - MQTT broker connected +[2024-10-16T09:01:22.241] [INFO] monitorLogs - MQTT broker connected +[2024-10-16T09:01:43.202] [INFO] monitorLogs - MQTT broker connected +[2024-10-16T09:03:03.629] [INFO] monitorLogs - MQTT broker connected +[2024-10-16T09:05:00.727] [INFO] monitorLogs - MQTT broker connected +[2024-10-16T09:06:17.580] [INFO] monitorLogs - MQTT broker connected +[2024-10-16T09:48:38.226] [INFO] monitorLogs - MQTT broker connected +[2024-10-16T09:48:40.895] [INFO] monitorLogs - MQTT broker connected +[2024-10-16T09:57:50.376] [INFO] monitorLogs - MQTT broker connected +[2024-10-16T09:58:53.160] [INFO] monitorLogs - MQTT broker connected +[2024-10-16T10:01:42.247] [INFO] monitorLogs - MQTT broker connected +[2024-10-16T10:02:06.444] [INFO] monitorLogs - MQTT broker connected +[2024-10-16T10:04:05.318] [INFO] monitorLogs - MQTT broker connected +[2024-10-16T10:05:22.278] [INFO] monitorLogs - MQTT broker connected +[2024-10-16T10:29:53.062] [INFO] monitorLogs - MQTT broker connected +[2024-10-16T10:32:04.058] [INFO] monitorLogs - MQTT broker connected +[2024-10-16T10:32:53.312] [INFO] monitorLogs - MQTT broker connected +[2024-10-16T10:33:45.001] [INFO] monitorLogs - MQTT broker connected +[2024-10-16T10:40:28.793] [INFO] monitorLogs - MQTT broker connected +[2024-10-16T10:41:54.861] [INFO] monitorLogs - MQTT broker connected +[2024-10-16T10:43:08.627] [INFO] monitorLogs - MQTT broker connected +[2024-10-16T10:46:15.479] [INFO] monitorLogs - MQTT broker connected +[2024-10-16T10:50:48.600] [INFO] monitorLogs - MQTT broker connected +[2024-10-16T10:56:37.479] [INFO] monitorLogs - MQTT broker connected +[2024-10-16T10:56:37.885] [INFO] monitorLogs - MQTT broker connected +[2024-10-16T18:31:09.281] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-16T18:31:09.316] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-16T18:31:09.349] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-17T03:33:07.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-17 03:33:07 +[2024-10-17T07:45:25.481] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-17T07:45:25.516] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-17T07:45:25.550] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-17T08:37:26.313] [INFO] monitorLogs - MQTT broker connected +[2024-10-17T08:38:29.543] [INFO] monitorLogs - MQTT broker connected +[2024-10-17T08:42:20.327] [INFO] monitorLogs - MQTT broker connected +[2024-10-17T08:45:00.492] [INFO] monitorLogs - MQTT broker connected +[2024-10-17T13:41:23.266] [INFO] monitorLogs - MQTT broker connected +[2024-10-17T13:42:36.544] [INFO] monitorLogs - MQTT broker connected +[2024-10-17T13:46:08.664] [INFO] monitorLogs - MQTT broker connected +[2024-10-17T13:49:18.932] [INFO] monitorLogs - MQTT broker connected +[2024-10-17T18:24:47.362] [INFO] monitorLogs - MQTT broker error Error: Connection refused: Server unavailable + at MqttClient._handleConnack (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:1388:17) + at MqttClient._handlePacket (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:549:12) + at work (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:438:12) + at Writable.writable._write (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:452:5) + at doWrite (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:409:139) + at writeOrBuffer (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:398:5) + at Writable.write (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:307:11) + at Socket.ondata (internal/streams/readable.js:731:22) + at Socket.emit (events.js:400:28) + at addChunk (internal/streams/readable.js:293:12) { + code: 3 +} +[2024-10-17T18:24:53.336] [INFO] monitorLogs - MQTT broker connected +[2024-10-17T18:29:13.273] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-17T18:29:13.307] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-17T18:29:13.341] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-18T03:33:08.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-18 03:33:08 +[2024-10-18T07:46:55.424] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-18T07:46:55.459] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-18T07:46:55.492] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-18T09:49:59.011] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T10:11:45.775] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T16:22:17.552] [INFO] monitorLogs - MQTT broker error Error: Connection refused: Server unavailable + at MqttClient._handleConnack (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:1388:17) + at MqttClient._handlePacket (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:549:12) + at work (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:438:12) + at Writable.writable._write (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:452:5) + at doWrite (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:409:139) + at writeOrBuffer (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:398:5) + at Writable.write (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:307:11) + at Socket.ondata (internal/streams/readable.js:731:22) + at Socket.emit (events.js:400:28) + at addChunk (internal/streams/readable.js:293:12) { + code: 3 +} +[2024-10-18T16:22:38.634] [INFO] monitorLogs - MQTT broker error Error: Connection refused: Server unavailable + at MqttClient._handleConnack (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:1388:17) + at MqttClient._handlePacket (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:549:12) + at work (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:438:12) + at Writable.writable._write (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:452:5) + at doWrite (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:409:139) + at writeOrBuffer (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:398:5) + at Writable.write (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:307:11) + at Socket.ondata (internal/streams/readable.js:731:22) + at Socket.emit (events.js:400:28) + at addChunk (internal/streams/readable.js:293:12) { + code: 3 +} +[2024-10-18T16:22:48.852] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T17:20:12.935] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T17:20:14.033] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T17:29:11.538] [INFO] monitorLogs - MQTT broker error Error: Connection refused: Server unavailable + at MqttClient._handleConnack (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:1388:17) + at MqttClient._handlePacket (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:549:12) + at work (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:438:12) + at Writable.writable._write (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:452:5) + at doWrite (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:409:139) + at writeOrBuffer (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:398:5) + at Writable.write (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:307:11) + at Socket.ondata (internal/streams/readable.js:731:22) + at Socket.emit (events.js:400:28) + at addChunk (internal/streams/readable.js:293:12) { + code: 3 +} +[2024-10-18T17:29:12.767] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T17:29:50.554] [INFO] monitorLogs - MQTT broker error Error: Connection refused: Server unavailable + at MqttClient._handleConnack (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:1388:17) + at MqttClient._handlePacket (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:549:12) + at work (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:438:12) + at Writable.writable._write (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:452:5) + at doWrite (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:409:139) + at writeOrBuffer (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:398:5) + at Writable.write (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:307:11) + at Socket.ondata (internal/streams/readable.js:731:22) + at Socket.emit (events.js:400:28) + at addChunk (internal/streams/readable.js:293:12) { + code: 3 +} +[2024-10-18T17:29:50.695] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T17:30:30.605] [INFO] monitorLogs - MQTT broker error Error: Connection refused: Server unavailable + at MqttClient._handleConnack (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:1388:17) + at MqttClient._handlePacket (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:549:12) + at work (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:438:12) + at Writable.writable._write (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:452:5) + at doWrite (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:409:139) + at writeOrBuffer (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:398:5) + at Writable.write (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:307:11) + at Socket.ondata (internal/streams/readable.js:731:22) + at Socket.emit (events.js:400:28) + at addChunk (internal/streams/readable.js:293:12) { + code: 3 +} +[2024-10-18T17:31:23.577] [INFO] monitorLogs - MQTT broker error Error: Connection refused: Server unavailable + at MqttClient._handleConnack (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:1388:17) + at MqttClient._handlePacket (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:549:12) + at work (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:438:12) + at Writable.writable._write (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:452:5) + at doWrite (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:409:139) + at writeOrBuffer (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:398:5) + at Writable.write (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:307:11) + at Socket.ondata (internal/streams/readable.js:731:22) + at Socket.emit (events.js:400:28) + at addChunk (internal/streams/readable.js:293:12) { + code: 3 +} +[2024-10-18T17:31:23.716] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T17:31:59.736] [INFO] monitorLogs - MQTT broker error Error: Connection refused: Server unavailable + at MqttClient._handleConnack (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:1388:17) + at MqttClient._handlePacket (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:549:12) + at work (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:438:12) + at Writable.writable._write (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:452:5) + at doWrite (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:409:139) + at writeOrBuffer (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:398:5) + at Writable.write (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:307:11) + at Socket.ondata (internal/streams/readable.js:731:22) + at Socket.emit (events.js:400:28) + at addChunk (internal/streams/readable.js:293:12) { + code: 3 +} +[2024-10-18T17:40:47.373] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T17:40:47.597] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T17:50:05.265] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T17:50:06.225] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T17:54:24.836] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T17:54:26.755] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T17:54:59.681] [INFO] monitorLogs - MQTT broker error Error: Connection refused: Server unavailable + at MqttClient._handleConnack (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:1388:17) + at MqttClient._handlePacket (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:549:12) + at work (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:438:12) + at Writable.writable._write (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:452:5) + at doWrite (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:409:139) + at writeOrBuffer (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:398:5) + at Writable.write (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:307:11) + at Socket.ondata (internal/streams/readable.js:731:22) + at Socket.emit (events.js:400:28) + at addChunk (internal/streams/readable.js:293:12) { + code: 3 +} +[2024-10-18T18:03:28.813] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T18:03:30.182] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T18:14:51.325] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T18:15:35.506] [INFO] monitorLogs - MQTT broker error Error: Connection refused: Server unavailable + at MqttClient._handleConnack (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:1388:17) + at MqttClient._handlePacket (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:549:12) + at work (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:438:12) + at Writable.writable._write (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:452:5) + at doWrite (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:409:139) + at writeOrBuffer (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:398:5) + at Writable.write (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:307:11) + at Socket.ondata (internal/streams/readable.js:731:22) + at Socket.emit (events.js:400:28) + at addChunk (internal/streams/readable.js:293:12) { + code: 3 +} +[2024-10-18T18:15:35.651] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T18:20:07.639] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T18:27:18.250] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-18T18:27:18.284] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-18T18:27:18.317] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-18T18:27:43.174] [INFO] monitorLogs - MQTT broker error Error: Connection refused: Server unavailable + at MqttClient._handleConnack (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:1388:17) + at MqttClient._handlePacket (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:549:12) + at work (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:438:12) + at Writable.writable._write (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:452:5) + at doWrite (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:409:139) + at writeOrBuffer (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:398:5) + at Writable.write (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:307:11) + at Socket.ondata (internal/streams/readable.js:731:22) + at Socket.emit (events.js:400:28) + at addChunk (internal/streams/readable.js:293:12) { + code: 3 +} +[2024-10-18T18:27:46.659] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T18:36:52.268] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T20:03:32.719] [INFO] monitorLogs - MQTT broker error Error: Connection refused: Server unavailable + at MqttClient._handleConnack (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:1388:17) + at MqttClient._handlePacket (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:549:12) + at work (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:438:12) + at Writable.writable._write (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:452:5) + at doWrite (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:409:139) + at writeOrBuffer (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:398:5) + at Writable.write (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:307:11) + at Socket.ondata (internal/streams/readable.js:731:22) + at Socket.emit (events.js:400:28) + at addChunk (internal/streams/readable.js:293:12) { + code: 3 +} +[2024-10-18T20:03:32.975] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T20:06:39.099] [INFO] monitorLogs - MQTT broker error Error: Connection refused: Server unavailable + at MqttClient._handleConnack (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:1388:17) + at MqttClient._handlePacket (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:549:12) + at work (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:438:12) + at Writable.writable._write (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:452:5) + at doWrite (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:409:139) + at writeOrBuffer (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:398:5) + at Writable.write (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:307:11) + at Socket.ondata (internal/streams/readable.js:731:22) + at Socket.emit (events.js:400:28) + at addChunk (internal/streams/readable.js:293:12) { + code: 3 +} +[2024-10-18T20:30:06.448] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T20:30:06.625] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T20:38:34.592] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T20:44:09.316] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T20:51:45.621] [INFO] monitorLogs - MQTT broker error Error: Connection refused: Server unavailable + at MqttClient._handleConnack (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:1388:17) + at MqttClient._handlePacket (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:549:12) + at work (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:438:12) + at Writable.writable._write (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:452:5) + at doWrite (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:409:139) + at writeOrBuffer (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:398:5) + at Writable.write (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:307:11) + at Socket.ondata (internal/streams/readable.js:731:22) + at Socket.emit (events.js:400:28) + at addChunk (internal/streams/readable.js:293:12) { + code: 3 +} +[2024-10-18T20:51:55.728] [INFO] monitorLogs - MQTT broker connected +[2024-10-19T03:33:09.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-19 03:33:09 +[2024-10-19T07:48:27.841] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-19T07:48:27.876] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-19T07:48:27.908] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-19T17:03:20.618] [INFO] monitorLogs - MQTT broker error Error: Connection refused: Server unavailable + at MqttClient._handleConnack (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:1388:17) + at MqttClient._handlePacket (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:549:12) + at work (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:438:12) + at Writable.writable._write (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:452:5) + at doWrite (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:409:139) + at writeOrBuffer (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:398:5) + at Writable.write (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:307:11) + at Socket.ondata (internal/streams/readable.js:731:22) + at Socket.emit (events.js:400:28) + at addChunk (internal/streams/readable.js:293:12) { + code: 3 +} +[2024-10-19T17:03:27.818] [INFO] monitorLogs - MQTT broker connected +[2024-10-19T18:25:24.118] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-19T18:25:24.153] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-19T18:25:24.187] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-20T03:33:11.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-20 03:33:11 +[2024-10-20T07:50:00.302] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-20T07:50:00.336] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-20T07:50:00.370] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-20T14:29:14.291] [INFO] monitorLogs - MQTT broker connected +[2024-10-20T14:29:37.001] [INFO] monitorLogs - MQTT broker error Error: Connection refused: Server unavailable + at MqttClient._handleConnack (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:1388:17) + at MqttClient._handlePacket (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:549:12) + at work (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:438:12) + at Writable.writable._write (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:452:5) + at doWrite (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:409:139) + at writeOrBuffer (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:398:5) + at Writable.write (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:307:11) + at Socket.ondata (internal/streams/readable.js:731:22) + at Socket.emit (events.js:400:28) + at addChunk (internal/streams/readable.js:293:12) { + code: 3 +} +[2024-10-20T14:29:37.140] [INFO] monitorLogs - MQTT broker connected +[2024-10-20T18:23:31.121] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-20T18:23:31.157] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-20T18:23:31.191] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-21T03:33:12.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-21 03:33:12 +[2024-10-21T03:51:33.514] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T03:51:33.946] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T04:10:10.541] [INFO] monitorLogs - MQTT broker error Error: Connection refused: Server unavailable + at MqttClient._handleConnack (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:1388:17) + at MqttClient._handlePacket (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:549:12) + at work (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:438:12) + at Writable.writable._write (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:452:5) + at doWrite (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:409:139) + at writeOrBuffer (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:398:5) + at Writable.write (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:307:11) + at Socket.ondata (internal/streams/readable.js:731:22) + at Socket.emit (events.js:400:28) + at addChunk (internal/streams/readable.js:293:12) { + code: 3 +} +[2024-10-21T04:10:17.835] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T04:10:17.988] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T04:21:07.800] [INFO] monitorLogs - MQTT broker error Error: Connection refused: Server unavailable + at MqttClient._handleConnack (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:1388:17) + at MqttClient._handlePacket (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:549:12) + at work (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:438:12) + at Writable.writable._write (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:452:5) + at doWrite (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:409:139) + at writeOrBuffer (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:398:5) + at Writable.write (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:307:11) + at Socket.ondata (internal/streams/readable.js:731:22) + at Socket.emit (events.js:400:28) + at addChunk (internal/streams/readable.js:293:12) { + code: 3 +} +[2024-10-21T04:21:19.984] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T04:37:30.846] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T04:37:32.069] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T06:58:34.687] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T06:59:55.319] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T07:51:32.934] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-21T07:51:32.968] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-21T07:51:33.001] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-21T07:59:58.141] [INFO] monitorLogs - MQTT broker error Error: Connection refused: Server unavailable + at MqttClient._handleConnack (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:1388:17) + at MqttClient._handlePacket (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:549:12) + at work (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:438:12) + at Writable.writable._write (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:452:5) + at doWrite (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:409:139) + at writeOrBuffer (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:398:5) + at Writable.write (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:307:11) + at Socket.ondata (internal/streams/readable.js:731:22) + at Socket.emit (events.js:400:28) + at addChunk (internal/streams/readable.js:293:12) { + code: 3 +} +[2024-10-21T08:00:08.061] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T09:11:24.274] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T09:55:22.218] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T09:55:22.394] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T10:02:56.611] [INFO] monitorLogs - MQTT broker error Error: Connection refused: Server unavailable + at MqttClient._handleConnack (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:1388:17) + at MqttClient._handlePacket (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:549:12) + at work (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:438:12) + at Writable.writable._write (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:452:5) + at doWrite (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:409:139) + at writeOrBuffer (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:398:5) + at Writable.write (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:307:11) + at Socket.ondata (internal/streams/readable.js:731:22) + at Socket.emit (events.js:400:28) + at addChunk (internal/streams/readable.js:293:12) { + code: 3 +} +[2024-10-21T10:02:57.693] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T10:04:14.382] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T10:06:57.561] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T10:07:34.546] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T10:08:29.417] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T10:23:09.770] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T10:23:11.095] [INFO] monitorLogs - MQTT broker error Error: read ECONNRESET + at TCP.onStreamRead (internal/stream_base_commons.js:209:20) { + errno: -104, + code: 'ECONNRESET', + syscall: 'read' +} +[2024-10-21T10:23:11.530] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T10:36:42.518] [INFO] monitorLogs - MQTT broker error Error: Connection refused: Server unavailable + at MqttClient._handleConnack (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:1388:17) + at MqttClient._handlePacket (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:549:12) + at work (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:438:12) + at Writable.writable._write (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:452:5) + at doWrite (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:409:139) + at writeOrBuffer (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:398:5) + at Writable.write (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:307:11) + at Socket.ondata (internal/streams/readable.js:731:22) + at Socket.emit (events.js:400:28) + at addChunk (internal/streams/readable.js:293:12) { + code: 3 +} +[2024-10-21T10:36:43.002] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T10:42:06.315] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T10:44:26.968] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T10:44:34.328] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T11:45:20.659] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T11:45:21.080] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T11:56:16.205] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T11:56:16.354] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T18:21:39.395] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-21T18:21:39.430] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-21T18:21:39.464] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-22T03:33:13.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-22 03:33:13 +[2024-10-22T07:53:06.292] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-22T07:53:06.327] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-22T07:53:06.361] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-22T14:48:02.997] [INFO] monitorLogs - DI_DO_Relay_Controller installed +[2024-10-22T14:48:03.326] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 true turn off on startup +[2024-10-22T14:48:03.328] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 true turn off on startup +[2024-10-22T14:48:03.329] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 true turn off on startup +[2024-10-22T14:48:05.201] [INFO] monitorLogs - MQTT broker connected +[2024-10-22T14:48:06.345] [INFO] monitorLogs - buildTasks - params undefined +[2024-10-22T14:48:06.347] [INFO] monitorLogs - buildTasks: profile for line 1 +[2024-10-22T14:48:06.348] [INFO] monitorLogs - profile: { + 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 +} +[2024-10-22T14:48:06.352] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-10-22T14:48:06.354] [INFO] monitorLogs - luxOff: turn off line: 1 2024-10-23T05:53:00.353Z +[2024-10-22T14:48:06.355] [INFO] monitorLogs - luxOn: turn on line: 1 2024-10-22T16:19:00.355Z +[2024-10-22T14:48:06.356] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:53', name: 'luxOff' }, + { value: 1, start_time: '18:19', name: 'luxOn' } +] +[2024-10-22T14:48:06.357] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2024-10-22T14:48:06.358] [INFO] monitorLogs - buildTasks: profile for line 2 +[2024-10-22T14:48:06.358] [INFO] monitorLogs - profile: { + 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 +} +[2024-10-22T14:48:06.360] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-10-22T14:48:06.361] [INFO] monitorLogs - luxOff: turn off line: 2 2024-10-23T05:53:00.361Z +[2024-10-22T14:48:06.362] [INFO] monitorLogs - luxOn: turn on line: 2 2024-10-22T16:19:00.362Z +[2024-10-22T14:48:06.363] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:53', name: 'luxOff' }, + { value: 1, start_time: '18:19', name: 'luxOn' } +] +[2024-10-22T14:48:06.364] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2024-10-22T14:48:06.364] [INFO] monitorLogs - buildTasks: profile for line 3 +[2024-10-22T14:48:06.365] [INFO] monitorLogs - profile: { + 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 +} +[2024-10-22T14:48:06.367] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-10-22T14:48:06.368] [INFO] monitorLogs - luxOff: turn off line: 3 2024-10-23T05:53:00.367Z +[2024-10-22T14:48:06.368] [INFO] monitorLogs - luxOn: turn on line: 3 2024-10-22T16:19:00.368Z +[2024-10-22T14:48:06.369] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:53', name: 'luxOff' }, + { value: 1, start_time: '18:19', name: 'luxOn' } +] +[2024-10-22T14:48:06.370] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2024-10-22T14:48:06.373] [INFO] monitorLogs - tasks created: 336 +[2024-10-22T14:48:06.380] [INFO] monitorLogs - -->FLOW bol spustený Z5KyJe9nEg1QNbWlX0w4nDkoDjBLdqzR83VGv624 2024-07-08 +[2024-10-22T14:48:06.683] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-22T14:48:06.719] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-22T14:48:06.754] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-22T18:19:00.453] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-22T18:19:00.488] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-22T18:19:00.523] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-23T03:48:03.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-23 03:48:03 +[2024-10-23T07:53:00.991] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-23T07:53:01.028] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-23T07:53:01.063] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-23T09:25:27.451] [INFO] monitorLogs - MQTT broker connected +[2024-10-23T18:17:58.601] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-23T18:17:58.637] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-23T18:17:58.670] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-24T03:48:05.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-24 03:48:05 +[2024-10-24T07:56:13.480] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-24T07:56:13.515] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-24T07:56:13.552] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-24T10:29:10.611] [INFO] monitorLogs - MQTT broker connected +[2024-10-24T18:16:10.320] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-24T18:16:10.356] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-24T18:16:10.390] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-25T03:48:06.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-25 03:48:06 +[2024-10-25T07:57:49.814] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-25T07:57:49.848] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-25T07:57:49.883] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-25T18:14:22.975] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-25T18:14:23.011] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-25T18:14:23.044] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-26T03:48:07.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-26 03:48:07 +[2024-10-26T07:37:30.118] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false command received form platform +[2024-10-26T07:37:47.339] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false command received form platform +[2024-10-26T07:37:59.818] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false command received form platform +[2024-10-26T07:59:22.070] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-26T07:59:22.106] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-26T07:59:22.141] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-26T18:12:36.845] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-26T18:12:36.880] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-26T18:12:36.913] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-27T16:39:28.085] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2024-10-27T16:39:28.400] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 true turn off on startup +[2024-10-27T16:39:28.416] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 true turn off on startup +[2024-10-27T16:39:28.422] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 true turn off on startup +[2024-10-27T16:39:28.566] [INFO] monitorLogs - MQTT broker connected +[2024-10-27T16:39:33.435] [INFO] monitorLogs - buildTasks - params undefined +[2024-10-27T16:39:33.437] [INFO] monitorLogs - buildTasks: profile for line 1 +[2024-10-27T16:39:33.438] [INFO] monitorLogs - profile: { + 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 +} +[2024-10-27T16:39:33.442] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-10-27T16:39:33.444] [INFO] monitorLogs - luxOff: turn off line: 1 2024-10-28T06:00:00.443Z +[2024-10-27T16:39:33.445] [INFO] monitorLogs - luxOn: turn on line: 1 2024-10-27T16:10:00.445Z +[2024-10-27T16:39:33.446] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:0', name: 'luxOff' }, + { value: 1, start_time: '17:10', name: 'luxOn' } +] +[2024-10-27T16:39:33.447] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2024-10-27T16:39:33.448] [INFO] monitorLogs - buildTasks: profile for line 2 +[2024-10-27T16:39:33.449] [INFO] monitorLogs - profile: { + 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 +} +[2024-10-27T16:39:33.451] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-10-27T16:39:33.452] [INFO] monitorLogs - luxOff: turn off line: 2 2024-10-28T06:00:00.452Z +[2024-10-27T16:39:33.453] [INFO] monitorLogs - luxOn: turn on line: 2 2024-10-27T16:10:00.453Z +[2024-10-27T16:39:33.454] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:0', name: 'luxOff' }, + { value: 1, start_time: '17:10', name: 'luxOn' } +] +[2024-10-27T16:39:33.455] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2024-10-27T16:39:33.455] [INFO] monitorLogs - buildTasks: profile for line 3 +[2024-10-27T16:39:33.456] [INFO] monitorLogs - profile: { + 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 +} +[2024-10-27T16:39:33.458] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-10-27T16:39:33.459] [INFO] monitorLogs - luxOff: turn off line: 3 2024-10-28T06:00:00.458Z +[2024-10-27T16:39:33.459] [INFO] monitorLogs - luxOn: turn on line: 3 2024-10-27T16:10:00.459Z +[2024-10-27T16:39:33.460] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:0', name: 'luxOff' }, + { value: 1, start_time: '17:10', name: 'luxOn' } +] +[2024-10-27T16:39:33.461] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2024-10-27T16:39:33.464] [INFO] monitorLogs - tasks created: 334 +[2024-10-27T16:39:33.467] [INFO] monitorLogs - -->FLOW bol spustený Z5KyJe9nEg1QNbWlX0w4nDkoDjBLdqzR83VGv624 2024-09-23 +[2024-10-27T16:39:33.773] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-27T16:39:33.811] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-27T16:39:33.847] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-27T17:10:00.648] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-27T17:10:00.707] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-27T17:10:00.746] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-28T03:39:29.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-28 03:39:29 +[2024-10-28T07:00:00.463] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-28T07:00:00.501] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-28T07:00:00.540] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-28T12:47:41.276] [INFO] monitorLogs - MQTT broker connected +[2024-10-28T13:40:20.720] [INFO] monitorLogs - MQTT broker connected +[2024-10-28T15:26:03.066] [INFO] monitorLogs - MQTT broker connected +[2024-10-28T17:09:08.761] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-28T17:09:08.799] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-28T17:09:08.837] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-29T03:39:30.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-29 03:39:30 +[2024-10-29T07:04:06.512] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-29T07:04:06.551] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-29T07:04:06.588] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-29T09:32:44.212] [INFO] monitorLogs - MQTT broker connected +[2024-10-29T17:07:26.738] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-29T17:07:26.779] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-29T17:07:26.818] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-30T03:39:32.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-30 03:39:32 +[2024-10-30T07:05:41.924] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-30T07:05:41.963] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-30T07:05:42.000] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-30T08:30:52.606] [INFO] monitorLogs - MQTT broker connected +[2024-10-30T09:02:01.446] [INFO] monitorLogs - MQTT broker connected +[2024-10-30T10:31:41.881] [INFO] monitorLogs - MQTT broker connected +[2024-10-30T11:11:29.421] [INFO] monitorLogs - MQTT broker connected +[2024-10-30T17:05:46.133] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-30T17:05:46.176] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-30T17:05:46.214] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-31T03:39:33.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-31 03:39:33 +[2024-10-31T07:07:18.039] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-31T07:07:18.080] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-31T07:07:18.116] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-31T17:04:07.121] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-31T17:04:07.162] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-31T17:04:07.200] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-01T03:39:34.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-01 03:39:34 +[2024-11-01T07:08:55.738] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-01T07:08:55.778] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-01T07:08:55.814] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-01T17:02:29.500] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-01T17:02:29.537] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-01T17:02:29.573] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-02T03:39:36.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-02 03:39:36 +[2024-11-02T07:10:28.729] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-02T07:10:28.769] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-02T07:10:28.806] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-02T17:00:53.483] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-02T17:00:53.520] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-02T17:00:53.557] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-03T03:39:37.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-03 03:39:37 +[2024-11-03T07:12:04.457] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-03T07:12:04.496] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-03T07:12:04.532] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-03T16:59:18.925] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-03T16:59:18.961] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-03T16:59:18.998] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-04T03:39:38.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-04 03:39:38 +[2024-11-04T07:13:40.208] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-04T07:13:40.247] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-04T07:13:40.283] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-04T10:24:11.471] [INFO] monitorLogs - MQTT broker connected +[2024-11-04T10:59:37.079] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2024-11-04T10:59:37.421] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 true turn off on startup +[2024-11-04T10:59:37.435] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 true turn off on startup +[2024-11-04T10:59:37.441] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 true turn off on startup +[2024-11-04T10:59:37.566] [INFO] monitorLogs - MQTT broker connected +[2024-11-04T10:59:42.454] [INFO] monitorLogs - buildTasks - params undefined +[2024-11-04T10:59:42.456] [INFO] monitorLogs - buildTasks: profile for line 1 +[2024-11-04T10:59:42.456] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2024-11-04T10:59:42.461] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-04T10:59:42.462] [INFO] monitorLogs - dawn: turn off line: 1 2024-11-05T05:23:00.461Z +[2024-11-04T10:59:42.464] [INFO] monitorLogs - dusk: turn on line: 1 2024-11-04T15:47:00.463Z +[2024-11-04T10:59:42.464] [INFO] monitorLogs - -->time_points final 1 [ + { start_time: '06:23', value: 0, name: 'dawn' }, + { start_time: '16:47', value: 1, name: 'dusk' } +] +[2024-11-04T10:59:42.466] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2024-11-04T10:59:42.467] [INFO] monitorLogs - buildTasks: profile for line 2 +[2024-11-04T10:59:42.467] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2024-11-04T10:59:42.470] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-04T10:59:42.470] [INFO] monitorLogs - dawn: turn off line: 2 2024-11-05T05:23:00.470Z +[2024-11-04T10:59:42.471] [INFO] monitorLogs - dusk: turn on line: 2 2024-11-04T15:47:00.471Z +[2024-11-04T10:59:42.472] [INFO] monitorLogs - -->time_points final 2 [ + { start_time: '06:23', value: 0, name: 'dawn' }, + { start_time: '16:47', value: 1, name: 'dusk' } +] +[2024-11-04T10:59:42.473] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2024-11-04T10:59:42.474] [INFO] monitorLogs - buildTasks: profile for line 3 +[2024-11-04T10:59:42.474] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2024-11-04T10:59:42.476] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-04T10:59:42.477] [INFO] monitorLogs - dawn: turn off line: 3 2024-11-05T05:23:00.477Z +[2024-11-04T10:59:42.478] [INFO] monitorLogs - dusk: turn on line: 3 2024-11-04T15:47:00.478Z +[2024-11-04T10:59:42.478] [INFO] monitorLogs - -->time_points final 3 [ + { start_time: '06:23', value: 0, name: 'dawn' }, + { start_time: '16:47', value: 1, name: 'dusk' } +] +[2024-11-04T10:59:42.479] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2024-11-04T10:59:42.483] [INFO] monitorLogs - tasks created: 334 +[2024-11-04T10:59:42.486] [INFO] monitorLogs - -->FLOW bol spustený Z5KyJe9nEg1QNbWlX0w4nDkoDjBLdqzR83VGv624 2024-09-23 +[2024-11-04T10:59:42.791] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-04T10:59:42.827] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-04T10:59:42.864] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-04T14:13:23.036] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2024-11-04T14:13:23.346] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 true turn off on startup +[2024-11-04T14:13:23.360] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 true turn off on startup +[2024-11-04T14:13:23.366] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 true turn off on startup +[2024-11-04T14:13:23.736] [INFO] monitorLogs - MQTT broker connected +[2024-11-04T14:13:28.378] [INFO] monitorLogs - buildTasks - params undefined +[2024-11-04T14:13:28.380] [INFO] monitorLogs - buildTasks: profile for line 1 +[2024-11-04T14:13:28.380] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2024-11-04T14:13:28.385] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-04T14:13:28.387] [INFO] monitorLogs - dawn: turn off line: 1 2024-11-05T05:23:00.386Z +[2024-11-04T14:13:28.388] [INFO] monitorLogs - dusk: turn on line: 1 2024-11-04T15:47:00.388Z +[2024-11-04T14:13:28.389] [INFO] monitorLogs - -->time_points final 1 [ + { start_time: '06:23', value: 0, name: 'dawn' }, + { start_time: '16:47', value: 1, name: 'dusk' } +] +[2024-11-04T14:13:28.390] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2024-11-04T14:13:28.391] [INFO] monitorLogs - buildTasks: profile for line 2 +[2024-11-04T14:13:28.391] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2024-11-04T14:13:28.394] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-04T14:13:28.395] [INFO] monitorLogs - dawn: turn off line: 2 2024-11-05T05:23:00.394Z +[2024-11-04T14:13:28.395] [INFO] monitorLogs - dusk: turn on line: 2 2024-11-04T15:47:00.395Z +[2024-11-04T14:13:28.396] [INFO] monitorLogs - -->time_points final 2 [ + { start_time: '06:23', value: 0, name: 'dawn' }, + { start_time: '16:47', value: 1, name: 'dusk' } +] +[2024-11-04T14:13:28.397] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2024-11-04T14:13:28.398] [INFO] monitorLogs - buildTasks: profile for line 3 +[2024-11-04T14:13:28.398] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2024-11-04T14:13:28.401] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-04T14:13:28.401] [INFO] monitorLogs - dawn: turn off line: 3 2024-11-05T05:23:00.401Z +[2024-11-04T14:13:28.402] [INFO] monitorLogs - dusk: turn on line: 3 2024-11-04T15:47:00.402Z +[2024-11-04T14:13:28.403] [INFO] monitorLogs - -->time_points final 3 [ + { start_time: '06:23', value: 0, name: 'dawn' }, + { start_time: '16:47', value: 1, name: 'dusk' } +] +[2024-11-04T14:13:28.404] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2024-11-04T14:13:28.407] [INFO] monitorLogs - tasks created: 334 +[2024-11-04T14:13:28.410] [INFO] monitorLogs - -->FLOW bol spustený Z5KyJe9nEg1QNbWlX0w4nDkoDjBLdqzR83VGv624 2024-09-23 +[2024-11-04T14:13:28.717] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-04T14:13:28.754] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-04T14:13:28.790] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-04T16:47:00.555] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-04T16:47:00.599] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-04T16:47:00.638] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-05T03:13:24.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-05 03:13:24 +[2024-11-05T06:23:00.407] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-05T06:23:00.446] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-05T06:23:00.484] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-05T08:08:21.032] [INFO] monitorLogs - MQTT broker connected +[2024-11-05T08:09:36.368] [INFO] monitorLogs - MQTT broker connected +[2024-11-05T16:46:14.989] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-05T16:46:15.026] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-05T16:46:15.063] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-05T22:55:58.611] [INFO] monitorLogs - MQTT broker connected +[2024-11-06T03:13:25.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-06 03:13:25 +[2024-11-06T06:26:53.908] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-06T06:26:53.947] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-06T06:26:53.984] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-06T16:44:45.561] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-06T16:44:45.598] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-06T16:44:45.634] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-07T01:40:57.902] [INFO] monitorLogs - MQTT broker connected +[2024-11-07T03:13:34.334] [INFO] monitorLogs - setCorrectPlcTimeOnceADay - function error SyntaxError: Unexpected token < in JSON at position 0 + at JSON.parse () + at /home/unipi/flowserver/flow/cmd_manager.js:2898:26 + at Object.exec_callback [as callback] (/home/unipi/flowserver/node_modules/total.js/builders.js:5803:3) + at IncomingMessage.request_process_end (/home/unipi/flowserver/node_modules/total.js/utils.js:1184:11) + at IncomingMessage.emit (events.js:412:35) + at endReadableNT (internal/streams/readable.js:1334:12) + at processTicksAndRejections (internal/process/task_queues.js:82:21) 503: Service Unavailable
503
Service Unavailable
+[2024-11-07T06:28:27.823] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-07T06:28:27.863] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-07T06:28:27.899] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-07T16:43:17.996] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-07T16:43:18.032] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-07T16:43:18.068] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-08T03:13:28.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-08 03:13:28 +[2024-11-08T06:30:03.244] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-08T06:30:03.284] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-08T06:30:03.320] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-08T16:41:52.116] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-08T16:41:52.152] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-08T16:41:52.188] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-08T19:03:07.041] [INFO] monitorLogs - MQTT broker connected +[2024-11-09T03:13:29.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-09 03:13:29 +[2024-11-09T06:31:38.945] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-09T06:31:38.984] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-09T06:31:39.021] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-09T16:40:28.166] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-09T16:40:28.203] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-09T16:40:28.239] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-10T03:13:28.888] [INFO] monitorLogs - failed timedatectl set-time Error: Command failed: sudo timedatectl set-time "1900-01-01 01:00:00" +Failed to parse time specification '1900-01-01 01:00:00': Invalid argument + + at ChildProcess.exithandler (child_process.js:383:12) + at ChildProcess.emit (events.js:400:28) + at maybeClose (internal/child_process.js:1058:16) + at Socket. (internal/child_process.js:443:11) + at Socket.emit (events.js:400:28) + at Pipe. (net.js:686:12) { + killed: false, + code: 1, + signal: null, + cmd: 'sudo timedatectl set-time "1900-01-01 01:00:00"' +} Failed to parse time specification '1900-01-01 01:00:00': Invalid argument + +[2024-11-10T06:33:14.087] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-10T06:33:14.127] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-10T06:33:14.164] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-10T15:19:36.955] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2024-11-10T15:19:42.349] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 true turn off on startup +[2024-11-10T15:19:42.351] [INFO] monitorLogs - turnLine: off pin (relay) relay1_02 +[2024-11-10T15:19:42.363] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 true turn off on startup +[2024-11-10T15:19:42.364] [INFO] monitorLogs - turnLine: off pin (relay) relay1_03 +[2024-11-10T15:19:42.369] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 true turn off on startup +[2024-11-10T15:19:42.370] [INFO] monitorLogs - turnLine: off pin (relay) relay1_04 +[2024-11-10T15:19:42.463] [INFO] monitorLogs - MQTT client connected +[2024-11-10T15:19:47.381] [INFO] monitorLogs - buildTasks - params undefined +[2024-11-10T15:19:47.382] [INFO] monitorLogs - buildTasks: profile for line 1 +[2024-11-10T15:19:47.383] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2024-11-10T15:19:47.388] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-10T15:19:47.390] [INFO] monitorLogs - dawn: turn off line: 1 2024-11-11T05:33:00.389Z +[2024-11-10T15:19:47.391] [INFO] monitorLogs - dusk: turn on line: 1 2024-11-10T15:39:00.391Z +[2024-11-10T15:19:47.392] [INFO] monitorLogs - -->time_points final 1 [ + { start_time: '06:33', value: 0, name: 'dawn' }, + { start_time: '16:39', value: 1, name: 'dusk' } +] +[2024-11-10T15:19:47.393] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2024-11-10T15:19:47.394] [INFO] monitorLogs - buildTasks: profile for line 2 +[2024-11-10T15:19:47.394] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2024-11-10T15:19:47.397] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-10T15:19:47.397] [INFO] monitorLogs - dawn: turn off line: 2 2024-11-11T05:33:00.397Z +[2024-11-10T15:19:47.398] [INFO] monitorLogs - dusk: turn on line: 2 2024-11-10T15:39:00.398Z +[2024-11-10T15:19:47.399] [INFO] monitorLogs - -->time_points final 2 [ + { start_time: '06:33', value: 0, name: 'dawn' }, + { start_time: '16:39', value: 1, name: 'dusk' } +] +[2024-11-10T15:19:47.400] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2024-11-10T15:19:47.400] [INFO] monitorLogs - buildTasks: profile for line 3 +[2024-11-10T15:19:47.401] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2024-11-10T15:19:47.403] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-10T15:19:47.404] [INFO] monitorLogs - dawn: turn off line: 3 2024-11-11T05:33:00.404Z +[2024-11-10T15:19:47.404] [INFO] monitorLogs - dusk: turn on line: 3 2024-11-10T15:39:00.404Z +[2024-11-10T15:19:47.405] [INFO] monitorLogs - -->time_points final 3 [ + { start_time: '06:33', value: 0, name: 'dawn' }, + { start_time: '16:39', value: 1, name: 'dusk' } +] +[2024-11-10T15:19:47.406] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2024-11-10T15:19:47.409] [INFO] monitorLogs - tasks created: 334 +[2024-11-10T15:19:47.412] [INFO] monitorLogs - -->FLOW bol spustený Z5KyJe9nEg1QNbWlX0w4nDkoDjBLdqzR83VGv624 2024-11-04 +[2024-11-10T15:19:47.717] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-10T15:19:47.753] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-10T15:19:47.789] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-10T16:39:00.565] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-10T16:39:00.566] [INFO] monitorLogs - turnLine: on pin (relay) relay1_02 +[2024-11-10T16:39:00.607] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-10T16:39:00.608] [INFO] monitorLogs - turnLine: on pin (relay) relay1_03 +[2024-11-10T16:39:00.648] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-10T16:39:00.649] [INFO] monitorLogs - turnLine: on pin (relay) relay1_04 +[2024-11-11T03:19:45.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-11 03:19:45 +[2024-11-11T06:33:01.860] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-11T06:33:01.862] [INFO] monitorLogs - turnLine: off pin (relay) relay1_02 +[2024-11-11T06:33:01.904] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-11T06:33:01.905] [INFO] monitorLogs - turnLine: off pin (relay) relay1_03 +[2024-11-11T06:33:01.944] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-11T06:33:01.944] [INFO] monitorLogs - turnLine: off pin (relay) relay1_04 +[2024-11-11T16:37:45.748] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-11T16:37:45.750] [INFO] monitorLogs - turnLine: on pin (relay) relay1_04 +[2024-11-11T16:37:45.793] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-11T16:37:45.793] [INFO] monitorLogs - turnLine: on pin (relay) relay1_03 +[2024-11-11T16:37:45.833] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-11T16:37:45.834] [INFO] monitorLogs - turnLine: on pin (relay) relay1_02 +[2024-11-11T23:08:42.268] [INFO] monitorLogs - MQTT client connected +[2024-11-12T03:19:46.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-12 03:19:46 +[2024-11-12T06:36:23.826] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-12T06:36:23.827] [INFO] monitorLogs - turnLine: off pin (relay) relay1_04 +[2024-11-12T06:36:23.869] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-12T06:36:23.869] [INFO] monitorLogs - turnLine: off pin (relay) relay1_03 +[2024-11-12T06:36:23.909] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-12T06:36:23.909] [INFO] monitorLogs - turnLine: off pin (relay) relay1_02 +[2024-11-12T16:36:27.392] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-12T16:36:27.393] [INFO] monitorLogs - turnLine: on pin (relay) relay1_02 +[2024-11-12T16:36:27.433] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-12T16:36:27.433] [INFO] monitorLogs - turnLine: on pin (relay) relay1_03 +[2024-11-12T16:36:27.471] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-12T16:36:27.472] [INFO] monitorLogs - turnLine: on pin (relay) relay1_04 +[2024-11-13T03:19:48.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-13 03:19:48 +[2024-11-13T06:38:00.495] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-13T06:38:00.497] [INFO] monitorLogs - turnLine: off pin (relay) relay1_02 +[2024-11-13T06:38:00.538] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-13T06:38:00.539] [INFO] monitorLogs - turnLine: off pin (relay) relay1_03 +[2024-11-13T06:38:00.577] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-13T06:38:00.578] [INFO] monitorLogs - turnLine: off pin (relay) relay1_04 +[2024-11-13T10:19:46.860] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2024-11-13T10:19:52.171] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 true turn off on startup +[2024-11-13T10:19:52.184] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 true turn off on startup +[2024-11-13T10:19:52.190] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 true turn off on startup +[2024-11-13T10:19:52.285] [INFO] monitorLogs - MQTT client connected +[2024-11-13T10:19:57.201] [INFO] monitorLogs - buildTasks - params undefined +[2024-11-13T10:19:57.202] [INFO] monitorLogs - buildTasks: profile for line 1 +[2024-11-13T10:19:57.203] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2024-11-13T10:19:57.209] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-13T10:19:57.211] [INFO] monitorLogs - dawn: turn off line: 1 2024-11-14T05:37:00.209Z +[2024-11-13T10:19:57.212] [INFO] monitorLogs - dusk: turn on line: 1 2024-11-13T15:35:00.212Z +[2024-11-13T10:19:57.213] [INFO] monitorLogs - -->time_points final 1 [ + { start_time: '06:37', value: 0, name: 'dawn' }, + { start_time: '16:35', value: 1, name: 'dusk' } +] +[2024-11-13T10:19:57.214] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2024-11-13T10:19:57.215] [INFO] monitorLogs - buildTasks: profile for line 2 +[2024-11-13T10:19:57.216] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2024-11-13T10:19:57.218] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-13T10:19:57.219] [INFO] monitorLogs - dawn: turn off line: 2 2024-11-14T05:37:00.219Z +[2024-11-13T10:19:57.220] [INFO] monitorLogs - dusk: turn on line: 2 2024-11-13T15:35:00.219Z +[2024-11-13T10:19:57.220] [INFO] monitorLogs - -->time_points final 2 [ + { start_time: '06:37', value: 0, name: 'dawn' }, + { start_time: '16:35', value: 1, name: 'dusk' } +] +[2024-11-13T10:19:57.221] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2024-11-13T10:19:57.222] [INFO] monitorLogs - buildTasks: profile for line 3 +[2024-11-13T10:19:57.222] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2024-11-13T10:19:57.225] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-13T10:19:57.225] [INFO] monitorLogs - dawn: turn off line: 3 2024-11-14T05:37:00.225Z +[2024-11-13T10:19:57.226] [INFO] monitorLogs - dusk: turn on line: 3 2024-11-13T15:35:00.226Z +[2024-11-13T10:19:57.227] [INFO] monitorLogs - -->time_points final 3 [ + { start_time: '06:37', value: 0, name: 'dawn' }, + { start_time: '16:35', value: 1, name: 'dusk' } +] +[2024-11-13T10:19:57.228] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2024-11-13T10:19:57.231] [INFO] monitorLogs - tasks created: 334 +[2024-11-13T10:19:57.234] [INFO] monitorLogs - -->FLOW bol spustený Z5KyJe9nEg1QNbWlX0w4nDkoDjBLdqzR83VGv624 2024-11-04 +[2024-11-13T16:35:00.316] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-13T16:35:00.362] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-13T16:35:00.403] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-14T03:19:53.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-14 03:19:53 +[2024-11-14T06:37:00.303] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-14T06:37:00.345] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-14T06:37:00.384] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-14T16:33:57.111] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-14T16:33:57.155] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-14T16:33:57.196] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-15T03:19:55.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-15 03:19:55 +[2024-11-15T06:41:05.490] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-15T06:41:05.532] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-15T06:41:05.571] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-15T16:32:45.074] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-15T16:32:45.114] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-15T16:32:45.152] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-16T03:19:56.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-16 03:19:56 +[2024-11-16T06:42:38.443] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-16T06:42:38.485] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-16T06:42:38.524] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-16T16:31:35.196] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-16T16:31:35.236] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-16T16:31:35.274] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-17T03:19:57.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-17 03:19:57 +[2024-11-17T06:44:10.881] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-17T06:44:10.923] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-17T06:44:10.962] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-17T16:30:27.395] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-17T16:30:27.437] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-17T16:30:27.476] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-18T03:19:58.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-18 03:19:58 +[2024-11-18T06:45:45.227] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-18T06:45:45.268] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-18T06:45:45.306] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-18T16:29:22.111] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-18T16:29:22.154] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-18T16:29:22.193] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-19T03:20:00.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-19 03:20:00 +[2024-11-19T06:47:13.363] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-19T06:47:13.404] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-19T06:47:13.443] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-19T16:28:18.993] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-19T16:28:19.034] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-19T16:28:19.073] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-20T03:20:01.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-20 03:20:01 +[2024-11-20T06:48:43.582] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-20T06:48:43.624] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-20T06:48:43.661] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-20T16:27:18.038] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-20T16:27:18.078] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-20T16:27:18.116] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-21T03:20:03.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-21 03:20:03 +[2024-11-21T06:50:12.905] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-21T06:50:12.947] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-21T06:50:12.985] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-21T13:37:21.506] [INFO] monitorLogs - MQTT client connected +[2024-11-21T16:26:19.436] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-21T16:26:19.476] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-21T16:26:19.514] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-22T03:20:04.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-22 03:20:04 +[2024-11-22T06:51:41.354] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-22T06:51:41.395] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-22T06:51:41.434] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-22T09:16:14.139] [INFO] monitorLogs - MQTT client connected +[2024-11-22T09:24:54.428] [INFO] monitorLogs - MQTT client connected +[2024-11-22T16:25:23.443] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-22T16:25:23.482] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-22T16:25:23.521] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-23T03:20:05.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-23 03:20:05 +[2024-11-23T06:53:08.725] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-23T06:53:08.767] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-23T06:53:08.805] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-23T16:24:29.907] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-23T16:24:29.947] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-23T16:24:29.986] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-23T21:14:43.989] [INFO] monitorLogs - MQTT client connected +[2024-11-23T21:16:03.655] [INFO] monitorLogs - MQTT client connected +[2024-11-23T21:16:59.629] [INFO] monitorLogs - MQTT client error Error: Connection refused: Server unavailable + at MqttClient._handleConnack (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:1388:17) + at MqttClient._handlePacket (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:549:12) + at work (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:438:12) + at Writable.writable._write (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:452:5) + at doWrite (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:409:139) + at writeOrBuffer (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:398:5) + at Writable.write (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:307:11) + at Socket.ondata (internal/streams/readable.js:731:22) + at Socket.emit (events.js:400:28) + at addChunk (internal/streams/readable.js:293:12) { + code: 3 +} +[2024-11-23T21:17:02.534] [INFO] monitorLogs - MQTT client connected +[2024-11-24T03:20:06.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-24 03:20:06 +[2024-11-24T06:54:35.237] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-24T06:54:35.279] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-24T06:54:35.317] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-24T16:23:38.767] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-24T16:23:38.806] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-24T16:23:38.843] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-25T02:14:42.170] [INFO] monitorLogs - MQTT client connected +[2024-11-25T03:20:07.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-25 03:20:07 +[2024-11-25T06:56:00.753] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-25T06:56:00.794] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-25T06:56:00.833] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-25T08:08:52.928] [INFO] monitorLogs - MQTT client connected +[2024-11-25T13:56:13.261] [INFO] monitorLogs - MQTT client connected +[2024-11-25T16:22:50.418] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-25T16:22:50.458] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-25T16:22:50.496] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-26T03:20:08.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-26 03:20:08 +[2024-11-26T06:57:24.369] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-26T06:57:24.410] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-26T06:57:24.449] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-26T16:22:04.426] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-26T16:22:04.466] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-26T16:22:04.505] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-27T03:20:10.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-27 03:20:10 +[2024-11-27T06:58:47.092] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-27T06:58:47.134] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-27T06:58:47.172] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-27T16:21:21.019] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-27T16:21:21.059] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-27T16:21:21.097] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-28T03:20:11.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-28 03:20:11 +[2024-11-28T07:00:08.453] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-28T07:00:08.495] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-28T07:00:08.534] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-28T16:20:40.202] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-28T16:20:40.242] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-28T16:20:40.280] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-29T03:20:12.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-29 03:20:12 +[2024-11-29T07:01:28.468] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-29T07:01:28.510] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-29T07:01:28.548] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-29T16:20:02.370] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-29T16:20:02.409] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-29T16:20:02.447] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-30T03:20:14.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-30 03:20:14 +[2024-11-30T07:02:47.091] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-30T07:02:47.133] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-30T07:02:47.172] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-30T15:32:53.342] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2024-11-30T15:32:58.659] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 true turn off on startup +[2024-11-30T15:32:58.675] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 true turn off on startup +[2024-11-30T15:32:58.682] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 true turn off on startup +[2024-11-30T15:32:58.786] [INFO] monitorLogs - MQTT client connected +[2024-11-30T15:33:03.695] [INFO] monitorLogs - buildTasks - params undefined +[2024-11-30T15:33:03.696] [INFO] monitorLogs - buildTasks: profile for line 1 +[2024-11-30T15:33:03.697] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2024-11-30T15:33:03.702] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-30T15:33:03.704] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 1 2024-12-01T06:02:00.703Z +[2024-11-30T15:33:03.706] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 1 2024-11-30T15:19:00.705Z +[2024-11-30T15:33:03.706] [INFO] monitorLogs - -->time_points final 1 [ + { start_time: '07:02', value: 0, name: 'dawn' }, + { start_time: '16:19', value: 1, name: 'dusk' } +] +[2024-11-30T15:33:03.708] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2024-11-30T15:33:03.709] [INFO] monitorLogs - buildTasks: profile for line 2 +[2024-11-30T15:33:03.709] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2024-11-30T15:33:03.712] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-30T15:33:03.712] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 2 2024-12-01T06:02:00.712Z +[2024-11-30T15:33:03.713] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 2 2024-11-30T15:19:00.713Z +[2024-11-30T15:33:03.714] [INFO] monitorLogs - -->time_points final 2 [ + { start_time: '07:02', value: 0, name: 'dawn' }, + { start_time: '16:19', value: 1, name: 'dusk' } +] +[2024-11-30T15:33:03.715] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2024-11-30T15:33:03.715] [INFO] monitorLogs - buildTasks: profile for line 3 +[2024-11-30T15:33:03.716] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2024-11-30T15:33:03.718] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-30T15:33:03.719] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 3 2024-12-01T06:02:00.719Z +[2024-11-30T15:33:03.719] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 3 2024-11-30T15:19:00.719Z +[2024-11-30T15:33:03.720] [INFO] monitorLogs - -->time_points final 3 [ + { start_time: '07:02', value: 0, name: 'dawn' }, + { start_time: '16:19', value: 1, name: 'dusk' } +] +[2024-11-30T15:33:03.721] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2024-11-30T15:33:03.724] [INFO] monitorLogs - tasks created: 334 +[2024-11-30T15:33:03.727] [INFO] monitorLogs - -->FLOW bol spustený Z5KyJe9nEg1QNbWlX0w4nDkoDjBLdqzR83VGv624 2024-11-04 +[2024-11-30T16:19:00.772] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-30T16:19:00.816] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-30T16:19:00.857] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-01T03:33:00.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-01 03:33:00 +[2024-12-01T07:02:01.005] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-01T07:02:01.046] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-01T07:02:01.085] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-01T16:18:54.442] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-01T16:18:54.482] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-01T16:18:54.521] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-02T03:33:01.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-02 03:33:01 +[2024-12-02T07:05:19.036] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-02T07:05:19.080] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-02T07:05:19.118] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-02T16:18:24.779] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-02T16:18:24.820] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-02T16:18:24.859] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-03T03:33:03.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-03 03:33:03 +[2024-12-03T07:06:32.460] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-03T07:06:32.502] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-03T07:06:32.541] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-03T09:43:02.380] [INFO] monitorLogs - MQTT client connected +[2024-12-03T16:17:57.728] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-03T16:17:57.767] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-03T16:17:57.806] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-04T00:19:14.412] [INFO] monitorLogs - MQTT client connected +[2024-12-04T03:33:04.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-04 03:33:04 +[2024-12-04T07:07:44.236] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-04T07:07:44.278] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-04T07:07:44.317] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-04T10:01:29.014] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2024-12-04T10:01:34.399] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 true turn off on startup +[2024-12-04T10:01:34.411] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 true turn off on startup +[2024-12-04T10:01:34.419] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 true turn off on startup +[2024-12-04T10:01:39.430] [INFO] monitorLogs - buildTasks - params undefined +[2024-12-04T10:01:39.431] [INFO] monitorLogs - buildTasks: profile for line 1 +[2024-12-04T10:01:39.432] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2024-12-04T10:01:39.435] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-12-04T10:01:39.437] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 1 2024-12-05T06:07:00.436Z +[2024-12-04T10:01:39.438] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 1 2024-12-04T15:17:00.438Z +[2024-12-04T10:01:39.439] [INFO] monitorLogs - -->time_points final 1 [ + { start_time: '07:07', value: 0, name: 'dawn' }, + { start_time: '16:17', value: 1, name: 'dusk' } +] +[2024-12-04T10:01:39.440] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2024-12-04T10:01:39.441] [INFO] monitorLogs - buildTasks: profile for line 2 +[2024-12-04T10:01:39.441] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2024-12-04T10:01:39.444] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-12-04T10:01:39.444] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 2 2024-12-05T06:07:00.444Z +[2024-12-04T10:01:39.445] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 2 2024-12-04T15:17:00.445Z +[2024-12-04T10:01:39.446] [INFO] monitorLogs - -->time_points final 2 [ + { start_time: '07:07', value: 0, name: 'dawn' }, + { start_time: '16:17', value: 1, name: 'dusk' } +] +[2024-12-04T10:01:39.447] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2024-12-04T10:01:39.447] [INFO] monitorLogs - buildTasks: profile for line 3 +[2024-12-04T10:01:39.448] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2024-12-04T10:01:39.450] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-12-04T10:01:39.451] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 3 2024-12-05T06:07:00.451Z +[2024-12-04T10:01:39.451] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 3 2024-12-04T15:17:00.451Z +[2024-12-04T10:01:39.452] [INFO] monitorLogs - -->time_points final 3 [ + { start_time: '07:07', value: 0, name: 'dawn' }, + { start_time: '16:17', value: 1, name: 'dusk' } +] +[2024-12-04T10:01:39.453] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2024-12-04T10:01:39.456] [INFO] monitorLogs - tasks created: 334 +[2024-12-04T10:01:39.458] [INFO] monitorLogs - -->FLOW bol spustený Z5KyJe9nEg1QNbWlX0w4nDkoDjBLdqzR83VGv624 2024-11-04 +[2024-12-04T10:06:14.065] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2024-12-04T10:06:19.462] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 true turn off on startup +[2024-12-04T10:06:19.475] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 true turn off on startup +[2024-12-04T10:06:19.480] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 true turn off on startup +[2024-12-04T10:06:19.709] [INFO] monitorLogs - MQTT client connected +[2024-12-04T10:06:24.491] [INFO] monitorLogs - buildTasks - params undefined +[2024-12-04T10:06:24.492] [INFO] monitorLogs - buildTasks: profile for line 1 +[2024-12-04T10:06:24.493] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2024-12-04T10:06:24.498] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-12-04T10:06:24.500] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 1 2024-12-05T06:07:00.499Z +[2024-12-04T10:06:24.501] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 1 2024-12-04T15:17:00.501Z +[2024-12-04T10:06:24.502] [INFO] monitorLogs - -->time_points final 1 [ + { start_time: '07:07', value: 0, name: 'dawn' }, + { start_time: '16:17', value: 1, name: 'dusk' } +] +[2024-12-04T10:06:24.503] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2024-12-04T10:06:24.504] [INFO] monitorLogs - buildTasks: profile for line 2 +[2024-12-04T10:06:24.504] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2024-12-04T10:06:24.507] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-12-04T10:06:24.507] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 2 2024-12-05T06:07:00.507Z +[2024-12-04T10:06:24.508] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 2 2024-12-04T15:17:00.508Z +[2024-12-04T10:06:24.509] [INFO] monitorLogs - -->time_points final 2 [ + { start_time: '07:07', value: 0, name: 'dawn' }, + { start_time: '16:17', value: 1, name: 'dusk' } +] +[2024-12-04T10:06:24.510] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2024-12-04T10:06:24.511] [INFO] monitorLogs - buildTasks: profile for line 3 +[2024-12-04T10:06:24.511] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2024-12-04T10:06:24.513] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-12-04T10:06:24.514] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 3 2024-12-05T06:07:00.514Z +[2024-12-04T10:06:24.515] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 3 2024-12-04T15:17:00.515Z +[2024-12-04T10:06:24.515] [INFO] monitorLogs - -->time_points final 3 [ + { start_time: '07:07', value: 0, name: 'dawn' }, + { start_time: '16:17', value: 1, name: 'dusk' } +] +[2024-12-04T10:06:24.516] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2024-12-04T10:06:24.520] [INFO] monitorLogs - tasks created: 334 +[2024-12-04T10:06:24.523] [INFO] monitorLogs - -->FLOW bol spustený Z5KyJe9nEg1QNbWlX0w4nDkoDjBLdqzR83VGv624 2024-11-04 +[2024-12-04T16:17:00.707] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-04T16:17:00.751] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-04T16:17:00.791] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-05T03:06:20.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-05 03:06:20 +[2024-12-05T07:07:00.681] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-05T07:07:00.723] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-05T07:07:00.763] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-05T16:17:12.787] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-05T16:17:12.830] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-05T16:17:12.870] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-06T03:06:27.118] [INFO] monitorLogs - setCorrectPlcTimeOnceADay - function error SyntaxError: Unexpected token < in JSON at position 0 + at JSON.parse () + at /home/unipi/flowserver/flow/cmd_manager.js:2525:28 + at Object.exec_callback [as callback] (/home/unipi/flowserver/node_modules/total.js/builders.js:5803:3) + at IncomingMessage.request_process_end (/home/unipi/flowserver/node_modules/total.js/utils.js:1184:11) + at IncomingMessage.emit (events.js:412:35) + at endReadableNT (internal/streams/readable.js:1334:12) + at processTicksAndRejections (internal/process/task_queues.js:82:21) 503: Service Unavailable
503
Service Unavailable
+[2024-12-06T07:10:03.564] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-06T07:10:03.607] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-06T07:10:03.646] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-06T16:16:54.327] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-06T16:16:54.368] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-06T16:16:54.407] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-07T03:06:23.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-07 03:06:23 +[2024-12-07T07:11:07.948] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-07T07:11:07.991] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-07T07:11:08.030] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-07T16:16:38.923] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-07T16:16:38.963] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-07T16:16:39.001] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-08T03:06:24.013] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-08 03:06:24 +[2024-12-08T07:12:11.618] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-08T07:12:11.663] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-08T07:12:11.701] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-08T16:16:26.790] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-08T16:16:26.833] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-08T16:16:26.872] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-09T03:06:25.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-09 03:06:25 +[2024-12-09T07:13:13.167] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-09T07:13:13.209] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-09T07:13:13.247] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-09T09:15:28.549] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-09T09:15:29.565] [INFO] monitorLogs - websocket error, reconnect +[2024-12-09T09:15:29.567] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-09T09:27:11.347] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2024-12-09T09:27:16.686] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 true turn off on startup +[2024-12-09T09:27:16.699] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 true turn off on startup +[2024-12-09T09:27:16.705] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 true turn off on startup +[2024-12-09T09:27:16.854] [INFO] monitorLogs - MQTT client connected +[2024-12-09T09:27:21.717] [INFO] monitorLogs - buildTasks - params undefined +[2024-12-09T09:27:21.719] [INFO] monitorLogs - buildTasks: profile for line 1 +[2024-12-09T09:27:21.719] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2024-12-09T09:27:21.725] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-12-09T09:27:21.726] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 1 2024-12-10T06:13:00.725Z +[2024-12-09T09:27:21.728] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 1 2024-12-09T15:16:00.727Z +[2024-12-09T09:27:21.728] [INFO] monitorLogs - -->time_points final 1 [ + { start_time: '07:13', value: 0, name: 'dawn' }, + { start_time: '16:16', value: 1, name: 'dusk' } +] +[2024-12-09T09:27:21.729] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2024-12-09T09:27:21.730] [INFO] monitorLogs - buildTasks: profile for line 2 +[2024-12-09T09:27:21.731] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2024-12-09T09:27:21.733] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-12-09T09:27:21.734] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 2 2024-12-10T06:13:00.734Z +[2024-12-09T09:27:21.735] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 2 2024-12-09T15:16:00.735Z +[2024-12-09T09:27:21.735] [INFO] monitorLogs - -->time_points final 2 [ + { start_time: '07:13', value: 0, name: 'dawn' }, + { start_time: '16:16', value: 1, name: 'dusk' } +] +[2024-12-09T09:27:21.736] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2024-12-09T09:27:21.737] [INFO] monitorLogs - buildTasks: profile for line 3 +[2024-12-09T09:27:21.738] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2024-12-09T09:27:21.740] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-12-09T09:27:21.741] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 3 2024-12-10T06:13:00.740Z +[2024-12-09T09:27:21.741] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 3 2024-12-09T15:16:00.741Z +[2024-12-09T09:27:21.742] [INFO] monitorLogs - -->time_points final 3 [ + { start_time: '07:13', value: 0, name: 'dawn' }, + { start_time: '16:16', value: 1, name: 'dusk' } +] +[2024-12-09T09:27:21.743] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2024-12-09T09:27:21.746] [INFO] monitorLogs - tasks created: 334 +[2024-12-09T09:27:21.749] [INFO] monitorLogs - -->FLOW bol spustený Z5KyJe9nEg1QNbWlX0w4nDkoDjBLdqzR83VGv624 2024-11-04 +[2024-12-09T11:38:45.067] [INFO] monitorLogs - MQTT client connected +[2024-12-09T12:58:06.587] [INFO] monitorLogs - MQTT client connected +[2024-12-09T13:13:27.882] [INFO] monitorLogs - MQTT client connected +[2024-12-09T16:16:00.777] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-09T16:16:00.819] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-09T16:16:00.856] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-09T19:41:06.521] [INFO] monitorLogs - MQTT client connected +[2024-12-09T23:22:05.831] [INFO] monitorLogs - MQTT client connected +[2024-12-10T02:50:58.852] [INFO] monitorLogs - MQTT client connected +[2024-12-10T03:13:22.449] [INFO] monitorLogs - MQTT client connected +[2024-12-10T04:50:04.394] [INFO] monitorLogs - MQTT client connected +[2024-12-10T05:41:32.354] [INFO] monitorLogs - MQTT client connected +[2024-12-10T07:13:00.875] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-10T07:13:00.916] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-10T07:13:00.953] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-10T07:13:01.778] [INFO] monitorLogs - MQTT client connected +[2024-12-10T16:16:10.821] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-10T16:16:10.863] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-10T16:16:10.904] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-11T03:27:20.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-11 03:27:20 +[2024-12-11T07:15:10.619] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-11T07:15:10.663] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-11T07:15:10.702] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-11T15:15:50.260] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2024-12-11T15:15:55.611] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 true turn off on startup +[2024-12-11T15:15:55.624] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 true turn off on startup +[2024-12-11T15:15:55.630] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 true turn off on startup +[2024-12-11T15:15:55.722] [INFO] monitorLogs - MQTT client connected +[2024-12-11T15:16:00.640] [INFO] monitorLogs - buildTasks - params undefined +[2024-12-11T15:16:00.641] [INFO] monitorLogs - buildTasks: profile for line 1 +[2024-12-11T15:16:00.642] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2024-12-11T15:16:00.646] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-12-11T15:16:00.648] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 1 2024-12-12T06:15:00.647Z +[2024-12-11T15:16:00.649] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 1 2024-12-11T15:16:00.649Z +[2024-12-11T15:16:00.650] [INFO] monitorLogs - -->time_points final 1 [ + { start_time: '07:15', value: 0, name: 'dawn' }, + { start_time: '16:16', value: 1, name: 'dusk' } +] +[2024-12-11T15:16:00.651] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2024-12-11T15:16:00.652] [INFO] monitorLogs - buildTasks: profile for line 2 +[2024-12-11T15:16:00.653] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2024-12-11T15:16:00.656] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-12-11T15:16:00.657] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 2 2024-12-12T06:15:00.656Z +[2024-12-11T15:16:00.657] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 2 2024-12-11T15:16:00.657Z +[2024-12-11T15:16:00.658] [INFO] monitorLogs - -->time_points final 2 [ + { start_time: '07:15', value: 0, name: 'dawn' }, + { start_time: '16:16', value: 1, name: 'dusk' } +] +[2024-12-11T15:16:00.659] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2024-12-11T15:16:00.660] [INFO] monitorLogs - buildTasks: profile for line 3 +[2024-12-11T15:16:00.660] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2024-12-11T15:16:00.662] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-12-11T15:16:00.663] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 3 2024-12-12T06:15:00.663Z +[2024-12-11T15:16:00.664] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 3 2024-12-11T15:16:00.664Z +[2024-12-11T15:16:00.664] [INFO] monitorLogs - -->time_points final 3 [ + { start_time: '07:15', value: 0, name: 'dawn' }, + { start_time: '16:16', value: 1, name: 'dusk' } +] +[2024-12-11T15:16:00.666] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2024-12-11T15:16:00.669] [INFO] monitorLogs - tasks created: 334 +[2024-12-11T15:16:00.671] [INFO] monitorLogs - -->FLOW bol spustený Z5KyJe9nEg1QNbWlX0w4nDkoDjBLdqzR83VGv624 2024-11-04 +[2024-12-11T16:16:00.942] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-11T16:16:00.985] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-11T16:16:01.026] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-12T03:15:56.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-12 03:15:56 +[2024-12-12T07:15:00.701] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-12T07:15:00.744] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-12T07:15:00.782] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-12T16:16:06.941] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-12T16:16:06.986] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-12T16:16:07.025] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-13T03:15:57.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-13 03:15:57 +[2024-12-13T07:16:56.830] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-13T07:16:56.873] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-13T07:16:56.913] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-13T16:16:09.627] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-13T16:16:09.669] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-13T16:16:09.708] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-14T03:15:58.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-14 03:15:58 +[2024-12-14T07:17:46.835] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-14T07:17:46.878] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-14T07:17:46.917] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-14T16:16:15.137] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-14T16:16:15.180] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-14T16:16:15.218] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-15T03:15:59.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-15 03:15:59 +[2024-12-15T07:18:36.375] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-15T07:18:36.417] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-15T07:18:36.456] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-15T16:16:23.715] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-15T16:16:23.758] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-15T16:16:23.797] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-16T03:16:01.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-16 03:16:01 +[2024-12-16T07:19:19.039] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-16T07:19:19.081] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-16T07:19:19.120] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-16T16:16:35.157] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-16T16:16:35.197] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-16T16:16:35.234] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-17T03:16:03.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-17 03:16:03 +[2024-12-17T07:20:01.178] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-17T07:20:01.219] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-17T07:20:01.257] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-17T13:11:33.206] [INFO] monitorLogs - MQTT client connected +[2024-12-17T16:16:49.862] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-17T16:16:49.909] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-17T16:16:49.950] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-18T03:16:03.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-18 03:16:03 +[2024-12-18T07:20:40.704] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-18T07:20:40.746] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-18T07:20:40.784] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-18T16:17:07.249] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-18T16:17:07.289] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-18T16:17:07.327] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-19T03:16:05.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-19 03:16:05 +[2024-12-19T07:21:19.474] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-19T07:21:19.520] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-19T07:21:19.561] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-19T16:17:28.072] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-19T16:17:28.116] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-19T16:17:28.156] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-20T03:16:07.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-20 03:16:07 +[2024-12-20T07:21:51.527] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-20T07:21:51.568] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-20T07:21:51.606] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-20T16:17:51.464] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-20T16:17:51.507] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-20T16:17:51.546] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-21T03:16:07.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-21 03:16:07 +[2024-12-21T07:22:22.815] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-21T07:22:22.857] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-21T07:22:22.894] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-21T16:18:17.934] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-21T16:18:17.975] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-21T16:18:18.013] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-22T03:16:12.019] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-22 03:16:12 +[2024-12-22T07:22:51.185] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-22T07:22:51.226] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-22T07:22:51.263] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-22T16:18:47.023] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-22T16:18:47.063] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-22T16:18:47.100] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-23T03:16:11.014] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-23 03:16:11 +[2024-12-23T07:23:17.956] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-23T07:23:18.002] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-23T07:23:18.041] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-23T16:19:19.443] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-23T16:19:19.484] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-23T16:19:19.523] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-24T03:16:11.013] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-24 03:16:11 +[2024-12-24T07:23:39.759] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-24T07:23:39.803] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-24T07:23:39.841] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-24T16:19:54.285] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-24T16:19:54.323] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-24T16:19:54.359] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-25T03:16:13.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-25 03:16:13 +[2024-12-25T07:23:59.314] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-25T07:23:59.355] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-25T07:23:59.393] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-25T16:20:32.315] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-25T16:20:32.355] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-25T16:20:32.394] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-26T03:16:14.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-26 03:16:14 +[2024-12-26T07:24:16.259] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-26T07:24:16.299] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-26T07:24:16.337] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-26T16:21:12.729] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-26T16:21:12.769] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-26T16:21:12.807] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-27T03:16:15.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-27 03:16:15 +[2024-12-27T07:24:30.406] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-27T07:24:30.449] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-27T07:24:30.488] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-27T14:33:32.112] [INFO] monitorLogs - MQTT client connected +[2024-12-27T16:21:56.066] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-27T16:21:56.106] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-27T16:21:56.144] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-28T03:16:16.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-28 03:16:16 +[2024-12-28T07:24:41.307] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-28T07:24:41.349] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-28T07:24:41.388] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-28T16:22:42.348] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-28T16:22:42.388] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-28T16:22:42.426] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-29T03:16:17.013] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-29 03:16:17 +[2024-12-29T07:24:49.412] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-29T07:24:49.455] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-29T07:24:49.493] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-29T16:23:30.915] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-29T16:23:30.957] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-29T16:23:30.995] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-30T03:16:19.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-30 03:16:19 +[2024-12-30T07:24:54.487] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-30T07:24:54.528] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-30T07:24:54.567] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-30T16:24:22.000] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-30T16:24:22.039] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-30T16:24:22.077] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-31T03:16:20.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-31 03:16:20 +[2024-12-31T07:24:56.558] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-12-31T07:24:56.601] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-31T07:24:56.638] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-31T16:25:16.024] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-12-31T16:25:16.064] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-12-31T16:25:16.102] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-01T03:16:21.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-01 03:16:21 +[2025-01-01T07:24:56.887] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-01T07:24:56.929] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-01T07:24:56.967] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-01T16:26:12.081] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-01T16:26:12.120] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-01T16:26:12.159] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-02T03:16:22.013] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-02 03:16:22 +[2025-01-02T07:24:52.036] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-02T07:24:52.078] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-02T07:24:52.116] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-02T08:47:38.566] [INFO] monitorLogs - MQTT client error Error: connect ECONNREFUSED 192.168.252.1:1883 + at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1159:16) { + errno: -111, + code: 'ECONNREFUSED', + syscall: 'connect', + address: '192.168.252.1', + port: 1883 +} +[2025-01-02T11:45:04.064] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-01-02T11:45:09.411] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 true turn off on startup +[2025-01-02T11:45:09.424] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 true turn off on startup +[2025-01-02T11:45:09.431] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 true turn off on startup +[2025-01-02T11:45:09.506] [INFO] monitorLogs - MQTT client error Error: connect ECONNREFUSED 192.168.252.1:1883 + at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1159:16) { + errno: -111, + code: 'ECONNREFUSED', + syscall: 'connect', + address: '192.168.252.1', + port: 1883 +} +[2025-01-02T11:45:14.442] [INFO] monitorLogs - buildTasks - params undefined +[2025-01-02T11:45:14.443] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-01-02T11:45:14.444] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-01-02T11:45:14.449] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-02T11:45:14.450] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 1 2025-01-03T06:24:00.449Z +[2025-01-02T11:45:14.451] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 1 2025-01-02T15:27:00.451Z +[2025-01-02T11:45:14.452] [INFO] monitorLogs - -->time_points final 1 [ + { start_time: '07:24', value: 0, name: 'dawn' }, + { start_time: '16:27', value: 1, name: 'dusk' } +] +[2025-01-02T11:45:14.453] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-01-02T11:45:14.454] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-01-02T11:45:14.455] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-01-02T11:45:14.457] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-02T11:45:14.458] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 2 2025-01-03T06:24:00.458Z +[2025-01-02T11:45:14.459] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 2 2025-01-02T15:27:00.459Z +[2025-01-02T11:45:14.460] [INFO] monitorLogs - -->time_points final 2 [ + { start_time: '07:24', value: 0, name: 'dawn' }, + { start_time: '16:27', value: 1, name: 'dusk' } +] +[2025-01-02T11:45:14.461] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-01-02T11:45:14.461] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-01-02T11:45:14.462] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-01-02T11:45:14.464] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-02T11:45:14.465] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 3 2025-01-03T06:24:00.465Z +[2025-01-02T11:45:14.465] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 3 2025-01-02T15:27:00.465Z +[2025-01-02T11:45:14.466] [INFO] monitorLogs - -->time_points final 3 [ + { start_time: '07:24', value: 0, name: 'dawn' }, + { start_time: '16:27', value: 1, name: 'dusk' } +] +[2025-01-02T11:45:14.467] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-01-02T11:45:14.476] [INFO] monitorLogs - tasks created: 334 +[2025-01-02T11:45:14.479] [INFO] monitorLogs - -->FLOW bol spustený Z5KyJe9nEg1QNbWlX0w4nDkoDjBLdqzR83VGv624 2025-01-02 +[2025-01-02T16:27:00.563] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-02T16:27:00.609] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-02T16:27:00.651] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-03T03:45:10.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-03 03:45:10 +[2025-01-03T07:24:00.693] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-03T07:24:00.736] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-03T07:24:00.776] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-03T10:17:00.391] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-01-03T10:17:05.728] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 true turn off on startup +[2025-01-03T10:17:05.742] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 true turn off on startup +[2025-01-03T10:17:05.749] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 true turn off on startup +[2025-01-03T10:17:05.776] [INFO] monitorLogs - MQTT client error Error: connect ECONNREFUSED 192.168.252.1:1883 + at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1159:16) { + errno: -111, + code: 'ECONNREFUSED', + syscall: 'connect', + address: '192.168.252.1', + port: 1883 +} +[2025-01-03T10:17:10.760] [INFO] monitorLogs - buildTasks - params undefined +[2025-01-03T10:17:10.762] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-01-03T10:17:10.763] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-01-03T10:17:10.768] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-03T10:17:10.769] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 1 2025-01-04T06:24:00.768Z +[2025-01-03T10:17:10.770] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 1 2025-01-03T15:28:00.770Z +[2025-01-03T10:17:10.771] [INFO] monitorLogs - -->time_points final 1 [ + { start_time: '07:24', value: 0, name: 'dawn' }, + { start_time: '16:28', value: 1, name: 'dusk' } +] +[2025-01-03T10:17:10.772] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-01-03T10:17:10.773] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-01-03T10:17:10.774] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-01-03T10:17:10.777] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-03T10:17:10.777] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 2 2025-01-04T06:24:00.777Z +[2025-01-03T10:17:10.778] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 2 2025-01-03T15:28:00.778Z +[2025-01-03T10:17:10.779] [INFO] monitorLogs - -->time_points final 2 [ + { start_time: '07:24', value: 0, name: 'dawn' }, + { start_time: '16:28', value: 1, name: 'dusk' } +] +[2025-01-03T10:17:10.780] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-01-03T10:17:10.781] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-01-03T10:17:10.781] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-01-03T10:17:10.783] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-03T10:17:10.784] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 3 2025-01-04T06:24:00.784Z +[2025-01-03T10:17:10.785] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 3 2025-01-03T15:28:00.784Z +[2025-01-03T10:17:10.785] [INFO] monitorLogs - -->time_points final 3 [ + { start_time: '07:24', value: 0, name: 'dawn' }, + { start_time: '16:28', value: 1, name: 'dusk' } +] +[2025-01-03T10:17:10.786] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-01-03T10:17:10.790] [INFO] monitorLogs - tasks created: 334 +[2025-01-03T10:17:10.792] [INFO] monitorLogs - -->FLOW bol spustený Z5KyJe9nEg1QNbWlX0w4nDkoDjBLdqzR83VGv624 2025-01-02 +[2025-01-03T16:28:01.549] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-03T16:28:01.593] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-03T16:28:01.632] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-04T03:17:08.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-04 03:17:08 +[2025-01-04T07:24:01.849] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-04T07:24:01.892] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-04T07:24:01.932] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-04T16:29:17.990] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-04T16:29:18.034] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-04T16:29:18.075] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-05T03:17:09.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-05 03:17:09 +[2025-01-05T07:24:25.196] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-05T07:24:25.238] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-05T07:24:25.277] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-05T16:30:23.428] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-05T16:30:23.469] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-05T16:30:23.507] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-06T03:17:10.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-06 03:17:10 +[2025-01-06T07:24:09.585] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-06T07:24:09.627] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-06T07:24:09.664] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-06T16:31:30.848] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-06T16:31:30.887] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-06T16:31:30.926] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-07T03:17:11.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-07 03:17:11 +[2025-01-07T07:23:49.161] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-07T07:23:49.204] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-07T07:23:49.242] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-07T16:32:39.298] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-07T16:32:39.338] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-07T16:32:39.377] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-08T03:17:12.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-08 03:17:12 +[2025-01-08T07:23:28.034] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-08T07:23:28.075] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-08T07:23:28.113] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-08T16:33:49.632] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-08T16:33:49.672] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-08T16:33:49.710] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-09T03:17:14.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-09 03:17:14 +[2025-01-09T07:23:03.693] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-09T07:23:03.735] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-09T07:23:03.774] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-09T15:28:23.605] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-01-09T15:28:28.946] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 true turn off on startup +[2025-01-09T15:28:28.959] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 true turn off on startup +[2025-01-09T15:28:28.965] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 true turn off on startup +[2025-01-09T15:28:28.979] [INFO] monitorLogs - MQTT client error Error: connect ECONNREFUSED 192.168.252.1:1883 + at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1159:16) { + errno: -111, + code: 'ECONNREFUSED', + syscall: 'connect', + address: '192.168.252.1', + port: 1883 +} +[2025-01-09T15:28:33.977] [INFO] monitorLogs - buildTasks - params undefined +[2025-01-09T15:28:33.979] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-01-09T15:28:33.979] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-01-09T15:28:33.984] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-09T15:28:33.986] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 1 2025-01-10T06:23:00.985Z +[2025-01-09T15:28:33.987] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 1 2025-01-09T15:35:00.987Z +[2025-01-09T15:28:33.988] [INFO] monitorLogs - -->time_points final 1 [ + { start_time: '07:23', value: 0, name: 'dawn' }, + { start_time: '16:35', value: 1, name: 'dusk' } +] +[2025-01-09T15:28:33.989] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-01-09T15:28:33.990] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-01-09T15:28:33.990] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-01-09T15:28:33.993] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-09T15:28:33.993] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 2 2025-01-10T06:23:00.993Z +[2025-01-09T15:28:33.994] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 2 2025-01-09T15:35:00.994Z +[2025-01-09T15:28:33.995] [INFO] monitorLogs - -->time_points final 2 [ + { start_time: '07:23', value: 0, name: 'dawn' }, + { start_time: '16:35', value: 1, name: 'dusk' } +] +[2025-01-09T15:28:33.996] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-01-09T15:28:33.997] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-01-09T15:28:33.997] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-01-09T15:28:33.999] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-09T15:28:34.000] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 3 2025-01-10T06:23:00.000Z +[2025-01-09T15:28:34.001] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 3 2025-01-09T15:35:00.001Z +[2025-01-09T15:28:34.001] [INFO] monitorLogs - -->time_points final 3 [ + { start_time: '07:23', value: 0, name: 'dawn' }, + { start_time: '16:35', value: 1, name: 'dusk' } +] +[2025-01-09T15:28:34.002] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-01-09T15:28:34.006] [INFO] monitorLogs - tasks created: 334 +[2025-01-09T15:28:34.008] [INFO] monitorLogs - -->FLOW bol spustený Z5KyJe9nEg1QNbWlX0w4nDkoDjBLdqzR83VGv624 2025-01-02 +[2025-01-09T16:35:00.238] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-09T16:35:01.184] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-09T16:35:01.223] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-10T03:28:30.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-10 03:28:30 +[2025-01-10T07:23:01.015] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-10T07:23:01.056] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-10T07:23:01.094] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-10T14:43:10.047] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-01-10T14:43:15.386] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 true turn off on startup +[2025-01-10T14:43:15.400] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 true turn off on startup +[2025-01-10T14:43:15.406] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 true turn off on startup +[2025-01-10T14:43:15.481] [INFO] monitorLogs - MQTT client error Error: connect ECONNREFUSED 192.168.252.1:1883 + at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1159:16) { + errno: -111, + code: 'ECONNREFUSED', + syscall: 'connect', + address: '192.168.252.1', + port: 1883 +} +[2025-01-10T14:43:20.417] [INFO] monitorLogs - buildTasks - params undefined +[2025-01-10T14:43:20.419] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-01-10T14:43:20.420] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-01-10T14:43:20.424] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-10T14:43:20.426] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 1 2025-01-11T06:22:00.425Z +[2025-01-10T14:43:20.427] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 1 2025-01-10T15:36:00.427Z +[2025-01-10T14:43:20.428] [INFO] monitorLogs - -->time_points final 1 [ + { start_time: '07:22', value: 0, name: 'dawn' }, + { start_time: '16:36', value: 1, name: 'dusk' } +] +[2025-01-10T14:43:20.429] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-01-10T14:43:20.430] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-01-10T14:43:20.431] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-01-10T14:43:20.433] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-10T14:43:20.434] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 2 2025-01-11T06:22:00.434Z +[2025-01-10T14:43:20.435] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 2 2025-01-10T15:36:00.435Z +[2025-01-10T14:43:20.435] [INFO] monitorLogs - -->time_points final 2 [ + { start_time: '07:22', value: 0, name: 'dawn' }, + { start_time: '16:36', value: 1, name: 'dusk' } +] +[2025-01-10T14:43:20.436] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-01-10T14:43:20.437] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-01-10T14:43:20.437] [INFO] monitorLogs - profile: { + 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: false, + dusk_lux_sensor: false, + dawn_lux_sensor_value: 15, + dusk_lux_sensor_value: 15, + 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 +} +[2025-01-10T14:43:20.440] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-10T14:43:20.440] [INFO] monitorLogs - TimePoint params: dawn: turn off line: 3 2025-01-11T06:22:00.440Z +[2025-01-10T14:43:20.441] [INFO] monitorLogs - TimePoint params: dusk: turn on line: 3 2025-01-10T15:36:00.441Z +[2025-01-10T14:43:20.442] [INFO] monitorLogs - -->time_points final 3 [ + { start_time: '07:22', value: 0, name: 'dawn' }, + { start_time: '16:36', value: 1, name: 'dusk' } +] +[2025-01-10T14:43:20.443] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-01-10T14:43:20.446] [INFO] monitorLogs - tasks created: 334 +[2025-01-10T14:43:20.449] [INFO] monitorLogs - -->FLOW bol spustený Z5KyJe9nEg1QNbWlX0w4nDkoDjBLdqzR83VGv624 2025-01-09 +[2025-01-10T15:58:15.075] [INFO] monitorLogs - MQTT client connected +[2025-01-10T16:36:00.588] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-10T16:36:00.634] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-10T16:36:00.681] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-11T03:43:17.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-11 03:43:17 +[2025-01-11T07:22:00.487] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-11T07:22:00.530] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-11T07:22:00.570] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-11T16:37:36.408] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-11T16:37:36.451] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-11T16:37:36.488] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-12T03:43:18.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-12 03:43:18 +[2025-01-12T07:21:35.020] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-12T07:21:35.064] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-12T07:21:35.108] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-12T16:38:55.256] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-12T16:38:55.300] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-12T16:38:55.337] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-13T03:43:20.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-13 03:43:20 +[2025-01-13T07:20:59.285] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-13T07:20:59.327] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-13T07:20:59.365] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-13T16:40:16.121] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-13T16:40:16.163] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-13T16:40:16.202] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-14T03:43:21.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-14 03:43:21 +[2025-01-14T07:20:21.277] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-14T07:20:21.319] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-14T07:20:21.356] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-14T16:41:38.430] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-14T16:41:38.474] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-14T16:41:38.516] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-15T03:43:22.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-15 03:43:22 +[2025-01-15T07:19:40.848] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-15T07:19:40.890] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-15T07:19:40.927] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-15T16:43:02.003] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-15T16:43:02.046] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-15T16:43:02.085] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-16T03:43:24.016] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-16 03:43:24 +[2025-01-16T07:18:57.372] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-16T07:18:57.421] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-16T07:18:57.460] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-16T16:44:27.326] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-16T16:44:27.369] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-16T16:44:27.407] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-17T03:43:25.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-17 03:43:25 +[2025-01-17T07:18:13.282] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-17T07:18:13.325] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-17T07:18:13.363] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-17T13:55:12.636] [INFO] monitorLogs - MQTT client connected +[2025-01-17T16:45:53.915] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-17T16:45:53.957] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-17T16:45:53.995] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-18T03:43:27.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-18 03:43:27 +[2025-01-18T07:17:23.600] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-18T07:17:23.643] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-18T07:17:23.682] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-18T16:47:21.628] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-18T16:47:21.674] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-18T16:47:21.712] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-19T03:43:28.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-19 03:43:28 +[2025-01-19T07:16:32.165] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-19T07:16:32.207] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-19T07:16:32.244] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-19T16:48:50.619] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-19T16:48:50.664] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-19T16:48:50.702] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-20T03:43:29.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-20 03:43:29 +[2025-01-20T07:15:40.711] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-20T07:15:40.754] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-20T07:15:40.791] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-20T16:50:20.730] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-20T16:50:20.778] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-20T16:50:20.820] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-21T03:43:30.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-21 03:43:30 +[2025-01-21T06:23:47.043] [INFO] monitorLogs - MQTT client connected +[2025-01-21T07:14:45.757] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-21T07:14:45.798] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-21T07:14:45.836] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-21T16:51:51.703] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-21T16:51:51.749] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-21T16:51:51.788] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-22T03:43:32.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-22 03:43:32 +[2025-01-22T07:13:47.599] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-22T07:13:47.644] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-22T07:13:47.683] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-22T13:29:53.587] [INFO] monitorLogs - MQTT client connected +[2025-01-22T13:33:52.182] [INFO] monitorLogs - MQTT client connected +[2025-01-22T13:38:23.210] [INFO] monitorLogs - MQTT client connected +[2025-01-22T16:53:23.974] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-22T16:53:24.016] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-22T16:53:24.054] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-23T03:43:33.018] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-23 03:43:33 +[2025-01-23T07:12:44.244] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-23T07:12:44.286] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-23T07:12:44.326] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-23T16:54:56.854] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-23T16:54:56.900] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-23T16:54:56.944] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-24T03:43:34.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-24 03:43:34 +[2025-01-24T07:11:41.204] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-24T07:11:41.247] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-24T07:11:41.285] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-24T16:56:30.763] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-24T16:56:30.808] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-24T16:56:30.854] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-25T03:43:36.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-25 03:43:36 +[2025-01-25T07:10:36.038] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-25T07:10:36.082] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-25T07:10:36.122] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-25T16:58:05.296] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-01-25T16:58:05.354] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-01-25T16:58:05.411] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-01-25T19:44:50.512] [INFO] monitorLogs - buildTasks - params { processLineProfiles: true, line: '1' } +[2025-01-25T19:44:50.514] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-01-25T19:44:50.515] [INFO] monitorLogs - 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 +} +[2025-01-25T19:44:50.517] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-25T19:44:50.518] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-01-26T12:00:00.517Z +[2025-01-25T19:44:50.519] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-01-25T19:44:50.520] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-01-25T19:45:27.416] [INFO] monitorLogs - buildTasks - params { processLineProfiles: true, line: '2' } +[2025-01-25T19:45:27.417] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-01-25T19:45:27.419] [INFO] monitorLogs - 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 +} +[2025-01-25T19:45:27.423] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-25T19:45:27.424] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-01-26T12:00:00.423Z +[2025-01-25T19:45:27.424] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-01-25T19:45:27.425] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-01-25T19:45:51.925] [INFO] monitorLogs - buildTasks - params { processLineProfiles: true, line: '3' } +[2025-01-25T19:45:51.926] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-01-25T19:45:51.926] [INFO] monitorLogs - 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 +} +[2025-01-25T19:45:51.927] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-25T19:45:51.931] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-01-26T12:00:00.928Z +[2025-01-25T19:45:51.931] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-01-25T19:45:51.932] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-01-25T21:38:15.408] [INFO] monitorLogs - buildTasks - params { processLineProfiles: true, line: '3' } +[2025-01-25T21:38:15.409] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-01-25T21:38:15.409] [INFO] monitorLogs - 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 +} +[2025-01-25T21:38:15.411] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-25T21:38:15.420] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-01-26T12:00:00.412Z +[2025-01-25T21:38:15.421] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-01-25T21:38:15.423] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-01-25T21:38:30.425] [INFO] monitorLogs - buildTasks - params { processLineProfiles: true, line: '2' } +[2025-01-25T21:38:30.426] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-01-25T21:38:30.427] [INFO] monitorLogs - 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 +} +[2025-01-25T21:38:30.428] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-25T21:38:30.429] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-01-26T12:00:00.429Z +[2025-01-25T21:38:30.429] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-01-25T21:38:30.430] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-01-25T21:38:43.237] [INFO] monitorLogs - buildTasks - params { processLineProfiles: true, line: '1' } +[2025-01-25T21:38:43.237] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-01-25T21:38:43.238] [INFO] monitorLogs - 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 +} +[2025-01-25T21:38:43.239] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-25T21:38:43.240] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-01-26T12:00:00.240Z +[2025-01-25T21:38:43.240] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-01-25T21:38:43.241] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-01-26T03:43:37.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-26 03:43:37 +[2025-01-27T03:43:39.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-27 03:43:39 +[2025-01-28T03:43:40.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-28 03:43:40 +[2025-01-29T03:43:41.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-29 03:43:41 +[2025-01-30T03:43:43.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-30 03:43:43 +[2025-01-31T03:43:44.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-31 03:43:44 +[2025-01-31T07:59:25.413] [INFO] monitorLogs - MQTT client connected +[2025-02-01T03:43:46.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-01 03:43:46 +[2025-02-02T03:43:47.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-02 03:43:47 +[2025-02-03T03:43:49.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-03 03:43:49 +[2025-02-03T06:59:49.240] [INFO] monitorLogs - MQTT client connected +[2025-02-03T07:06:12.646] [INFO] monitorLogs - MQTT client connected +[2025-02-03T10:36:12.434] [INFO] monitorLogs - MQTT client connected +[2025-02-04T03:43:50.238] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-04 03:43:50 +[2025-02-05T03:43:51.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-05 03:43:51 +[2025-02-06T03:43:53.018] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-06 03:43:53 +[2025-02-07T03:43:54.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-07 03:43:54 +[2025-02-07T08:39:28.573] [INFO] monitorLogs - MQTT client connected +[2025-02-07T08:43:59.347] [INFO] monitorLogs - MQTT client connected +[2025-02-08T02:40:37.867] [INFO] monitorLogs - MQTT client connected +[2025-02-08T03:43:55.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-08 03:43:55 +[2025-02-09T03:43:57.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-09 03:43:57 +[2025-02-09T13:22:31.060] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-02-09T13:22:36.423] [INFO] monitorLogs - buildTasks - params undefined +[2025-02-09T13:22:36.428] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-02-09T13:22:36.429] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-02-09T13:22:36.430] [INFO] monitorLogs - 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 +} +[2025-02-09T13:22:36.433] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-02-09T13:22:36.434] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-02-10T12:00:00.433Z +[2025-02-09T13:22:36.435] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-02-09T13:22:36.437] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-02-09T13:22:36.437] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-02-09T13:22:36.438] [INFO] monitorLogs - 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 +} +[2025-02-09T13:22:36.439] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-02-09T13:22:36.440] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-02-10T12:00:00.440Z +[2025-02-09T13:22:36.441] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-02-09T13:22:36.442] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-02-09T13:22:36.443] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-02-09T13:22:36.443] [INFO] monitorLogs - 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 +} +[2025-02-09T13:22:36.445] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-02-09T13:22:36.445] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-02-10T12:00:00.445Z +[2025-02-09T13:22:36.446] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-02-09T13:22:36.447] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-02-09T13:22:36.450] [INFO] monitorLogs - tasks created: 311 +[2025-02-09T13:22:36.452] [INFO] monitorLogs - -->FLOW bol spustený Z5KyJe9nEg1QNbWlX0w4nDkoDjBLdqzR83VGv624 2025-01-30 +[2025-02-09T13:22:36.611] [INFO] monitorLogs - MQTT client connected +[2025-02-09T13:22:36.757] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-02-09T13:22:37.060] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-02-09T13:22:37.365] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-02-10T03:22:37.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-10 03:22:37 +[2025-02-11T03:22:38.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-11 03:22:38 +[2025-02-12T03:22:40.013] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-12 03:22:40 +[2025-02-12T11:38:22.555] [INFO] monitorLogs - MQTT client connected +[2025-02-13T03:22:41.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-13 03:22:41 +[2025-02-13T13:17:37.912] [INFO] monitorLogs - MQTT client connected +[2025-02-13T13:18:05.744] [INFO] monitorLogs - MQTT client connected +[2025-02-13T13:19:12.034] [INFO] monitorLogs - MQTT client connected +[2025-02-13T13:21:33.523] [INFO] monitorLogs - MQTT client connected +[2025-02-13T13:22:10.584] [INFO] monitorLogs - MQTT client connected +[2025-02-13T13:24:02.286] [INFO] monitorLogs - MQTT client connected +[2025-02-13T13:24:33.770] [INFO] monitorLogs - MQTT client connected +[2025-02-13T13:28:32.670] [INFO] monitorLogs - MQTT client connected +[2025-02-13T13:31:31.947] [INFO] monitorLogs - MQTT client connected +[2025-02-13T15:23:03.415] [INFO] monitorLogs - MQTT client connected +[2025-02-14T03:22:42.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-14 03:22:42 +[2025-02-15T03:22:43.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-15 03:22:43 +[2025-02-16T03:22:44.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-16 03:22:44 +[2025-02-17T03:22:46.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-17 03:22:46 +[2025-02-17T07:03:34.854] [INFO] monitorLogs - MQTT client connected +[2025-02-17T07:04:02.356] [INFO] monitorLogs - MQTT client connected +[2025-02-17T07:05:02.213] [INFO] monitorLogs - MQTT client connected +[2025-02-17T08:04:03.932] [INFO] monitorLogs - MQTT client connected +[2025-02-17T08:04:58.408] [INFO] monitorLogs - MQTT client connected +[2025-02-17T08:56:14.224] [INFO] monitorLogs - MQTT client connected +[2025-02-18T03:22:47.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-18 03:22:47 +[2025-02-19T03:22:48.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-19 03:22:48 +[2025-02-19T15:06:43.516] [INFO] monitorLogs - MQTT client connected +[2025-02-19T15:10:02.693] [INFO] monitorLogs - MQTT client connected +[2025-02-19T15:12:55.805] [INFO] monitorLogs - MQTT client connected +[2025-02-20T03:22:49.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-20 03:22:49 +[2025-02-20T08:00:32.817] [INFO] monitorLogs - MQTT client connected +[2025-02-20T09:19:33.730] [INFO] monitorLogs - MQTT client connected +[2025-02-21T03:22:50.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-21 03:22:50 +[2025-02-22T03:22:51.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-22 03:22:51 +[2025-02-23T03:22:53.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-23 03:22:53 +[2025-02-24T03:22:53.014] [INFO] monitorLogs - failed timedatectl set-time Error: Command failed: sudo timedatectl set-time "1900-01-01 01:00:00" +Failed to parse time specification '1900-01-01 01:00:00': Invalid argument + + at ChildProcess.exithandler (child_process.js:383:12) + at ChildProcess.emit (events.js:400:28) + at maybeClose (internal/child_process.js:1058:16) + at Process.ChildProcess._handle.onexit (internal/child_process.js:293:5) { + killed: false, + code: 1, + signal: null, + cmd: 'sudo timedatectl set-time "1900-01-01 01:00:00"' +} Failed to parse time specification '1900-01-01 01:00:00': Invalid argument + +[2025-02-24T09:09:01.268] [INFO] monitorLogs - MQTT client connected +[2025-02-24T14:01:37.298] [INFO] monitorLogs - MQTT client connected +[2025-02-24T14:02:22.097] [INFO] monitorLogs - MQTT client connected +[2025-02-25T03:22:55.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-25 03:22:55 +[2025-02-25T06:51:51.006] [INFO] monitorLogs - MQTT client connected +[2025-02-25T06:52:33.997] [INFO] monitorLogs - MQTT client connected +[2025-02-25T06:54:53.636] [INFO] monitorLogs - MQTT client connected +[2025-02-25T06:56:10.075] [INFO] monitorLogs - MQTT client connected +[2025-02-25T06:58:06.616] [INFO] monitorLogs - MQTT client connected +[2025-02-25T06:58:33.313] [INFO] monitorLogs - MQTT client connected +[2025-02-25T07:11:05.389] [INFO] monitorLogs - MQTT client connected +[2025-02-25T07:11:50.982] [INFO] monitorLogs - MQTT client connected +[2025-02-25T07:12:12.525] [INFO] monitorLogs - MQTT client connected +[2025-02-25T07:15:21.939] [INFO] monitorLogs - MQTT client connected +[2025-02-25T07:16:20.068] [INFO] monitorLogs - MQTT client connected +[2025-02-25T07:17:16.171] [INFO] monitorLogs - MQTT client connected +[2025-02-25T12:36:39.128] [INFO] monitorLogs - MQTT client connected +[2025-02-25T12:37:19.401] [INFO] monitorLogs - MQTT client connected +[2025-02-25T12:38:51.525] [INFO] monitorLogs - MQTT client connected +[2025-02-25T12:39:18.572] [INFO] monitorLogs - MQTT client connected +[2025-02-25T14:06:58.323] [INFO] monitorLogs - MQTT client connected +[2025-02-25T14:08:44.160] [INFO] monitorLogs - MQTT client connected +[2025-02-25T14:09:55.972] [INFO] monitorLogs - MQTT client connected +[2025-02-25T14:10:42.088] [INFO] monitorLogs - MQTT client connected +[2025-02-25T14:12:30.250] [INFO] monitorLogs - MQTT client connected +[2025-02-25T14:14:01.652] [INFO] monitorLogs - MQTT client connected +[2025-02-25T14:14:16.607] [INFO] monitorLogs - MQTT client connected +[2025-02-25T14:16:04.226] [INFO] monitorLogs - MQTT client connected +[2025-02-25T14:20:50.973] [INFO] monitorLogs - MQTT client connected +[2025-02-26T03:22:57.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-26 03:22:57 +[2025-02-27T03:22:58.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-27 03:22:58 +[2025-02-28T03:22:59.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-28 03:22:59 +[2025-02-28T12:19:57.366] [INFO] monitorLogs - MQTT client connected +[2025-02-28T12:26:51.938] [INFO] monitorLogs - MQTT client connected +[2025-03-01T03:23:01.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-01 03:23:01 +[2025-03-02T03:23:02.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-02 03:23:02 +[2025-03-03T03:23:03.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-03 03:23:03 +[2025-03-04T03:23:04.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-04 03:23:04 +[2025-03-04T07:04:52.039] [INFO] monitorLogs - MQTT client error Error: read ECONNRESET + at TCP.onStreamRead (internal/stream_base_commons.js:209:20) { + errno: -104, + code: 'ECONNRESET', + syscall: 'read' +} +[2025-03-04T07:06:02.674] [INFO] monitorLogs - MQTT client connected +[2025-03-04T07:10:48.452] [INFO] monitorLogs - MQTT client connected +[2025-03-04T07:12:01.315] [INFO] monitorLogs - MQTT client connected +[2025-03-04T07:14:11.476] [INFO] monitorLogs - MQTT client connected +[2025-03-04T07:14:59.845] [INFO] monitorLogs - MQTT client connected +[2025-03-04T07:16:11.108] [INFO] monitorLogs - MQTT client connected +[2025-03-04T07:17:29.015] [INFO] monitorLogs - MQTT client connected +[2025-03-04T07:18:31.731] [INFO] monitorLogs - MQTT client connected +[2025-03-04T07:25:33.591] [INFO] monitorLogs - MQTT client connected +[2025-03-05T03:23:06.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-05 03:23:06 +[2025-03-06T03:23:07.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-06 03:23:07 +[2025-03-07T03:23:08.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-07 03:23:08 +[2025-03-08T03:23:10.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-08 03:23:10 +[2025-03-09T03:23:11.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-09 03:23:11 +[2025-03-10T03:23:13.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-10 03:23:13 +[2025-03-10T06:44:08.162] [INFO] monitorLogs - MQTT client connected +[2025-03-10T20:31:52.153] [INFO] monitorLogs - MQTT client connected +[2025-03-11T03:23:14.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-11 03:23:14 +[2025-03-11T08:20:24.277] [INFO] monitorLogs - MQTT client connected +[2025-03-11T08:21:22.134] [INFO] monitorLogs - MQTT client connected +[2025-03-11T08:21:56.733] [INFO] monitorLogs - MQTT client connected +[2025-03-11T08:24:53.652] [INFO] monitorLogs - MQTT client connected +[2025-03-12T03:23:15.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-12 03:23:15 +[2025-03-12T16:08:44.603] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-03-12T16:08:49.950] [INFO] monitorLogs - buildTasks - params undefined +[2025-03-12T16:08:49.955] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-03-12T16:08:49.956] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-03-12T16:08:49.957] [INFO] monitorLogs - 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 +} +[2025-03-12T16:08:49.960] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-03-12T16:08:49.961] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-03-13T12:00:00.960Z +[2025-03-12T16:08:49.962] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-03-12T16:08:49.963] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-03-12T16:08:49.964] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-03-12T16:08:49.965] [INFO] monitorLogs - 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 +} +[2025-03-12T16:08:49.966] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-03-12T16:08:49.967] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-03-13T12:00:00.967Z +[2025-03-12T16:08:49.968] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-03-12T16:08:49.969] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-03-12T16:08:49.970] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-03-12T16:08:49.970] [INFO] monitorLogs - 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 +} +[2025-03-12T16:08:49.972] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-03-12T16:08:49.972] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-03-13T12:00:00.972Z +[2025-03-12T16:08:49.973] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-03-12T16:08:49.974] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-03-12T16:08:49.977] [INFO] monitorLogs - tasks created: 311 +[2025-03-12T16:08:49.979] [INFO] monitorLogs - -->FLOW bol spustený Z5KyJe9nEg1QNbWlX0w4nDkoDjBLdqzR83VGv624 2025-01-30 +[2025-03-12T16:08:50.055] [INFO] monitorLogs - MQTT client connected +[2025-03-12T16:08:50.283] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-03-12T16:08:50.587] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-03-12T16:08:50.890] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-03-13T03:08:52.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-13 03:08:52 +[2025-03-13T08:04:00.641] [INFO] monitorLogs - MQTT client connected +[2025-03-13T09:03:14.249] [INFO] monitorLogs - MQTT client connected +[2025-03-13T09:44:34.610] [INFO] monitorLogs - MQTT client connected +[2025-03-13T09:46:17.227] [INFO] monitorLogs - MQTT client connected +[2025-03-13T09:47:24.425] [INFO] monitorLogs - MQTT client connected +[2025-03-13T09:47:39.585] [INFO] monitorLogs - MQTT client connected +[2025-03-13T09:48:33.186] [INFO] monitorLogs - MQTT client connected +[2025-03-13T10:13:30.280] [INFO] monitorLogs - MQTT client connected +[2025-03-13T10:41:19.677] [INFO] monitorLogs - MQTT client connected +[2025-03-14T03:08:53.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-14 03:08:53 +[2025-03-15T03:08:54.017] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-15 03:08:54 +[2025-03-16T03:08:55.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-16 03:08:55 +[2025-03-17T03:08:57.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-17 03:08:57 +[2025-03-17T06:44:59.730] [INFO] monitorLogs - MQTT client connected +[2025-03-17T07:05:04.902] [INFO] monitorLogs - MQTT client connected +[2025-03-17T07:06:42.092] [INFO] monitorLogs - MQTT client connected +[2025-03-18T03:08:58.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-18 03:08:58 +[2025-03-19T03:08:59.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-19 03:08:59 +[2025-03-20T03:09:00.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-20 03:09:00 +[2025-03-21T03:09:02.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-21 03:09:02 +[2025-03-22T03:09:03.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-22 03:09:03 +[2025-03-23T03:09:04.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-23 03:09:04 +[2025-03-24T03:09:06.013] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-24 03:09:06 +[2025-03-24T08:05:49.169] [INFO] monitorLogs - MQTT client connected +[2025-03-24T08:09:54.741] [INFO] monitorLogs - MQTT client connected +[2025-03-24T09:29:09.477] [INFO] monitorLogs - MQTT client connected +[2025-03-24T11:32:18.814] [INFO] monitorLogs - MQTT client connected +[2025-03-24T12:31:44.325] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-03-24T12:31:49.683] [INFO] monitorLogs - buildTasks - params undefined +[2025-03-24T12:31:49.688] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-03-24T12:31:49.690] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-03-24T12:31:49.690] [INFO] monitorLogs - 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 +} +[2025-03-24T12:31:49.693] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-03-24T12:31:49.694] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-03-24T12:00:00.694Z +[2025-03-24T12:31:49.696] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-03-24T12:31:49.697] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-03-24T12:31:49.698] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-03-24T12:31:49.698] [INFO] monitorLogs - 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 +} +[2025-03-24T12:31:49.700] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-03-24T12:31:49.701] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-03-24T12:00:00.701Z +[2025-03-24T12:31:49.702] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-03-24T12:31:49.703] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-03-24T12:31:49.704] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-03-24T12:31:49.705] [INFO] monitorLogs - 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 +} +[2025-03-24T12:31:49.707] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-03-24T12:31:49.707] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-03-24T12:00:00.707Z +[2025-03-24T12:31:49.708] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-03-24T12:31:49.709] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-03-24T12:31:49.712] [INFO] monitorLogs - tasks created: 311 +[2025-03-24T12:31:49.714] [INFO] monitorLogs - -->FLOW bol spustený Z5KyJe9nEg1QNbWlX0w4nDkoDjBLdqzR83VGv624 2025-01-30 +[2025-03-24T12:31:49.803] [INFO] monitorLogs - MQTT client connected +[2025-03-24T12:31:50.019] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-03-24T12:31:50.323] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-03-24T12:31:50.627] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-03-25T03:31:55.440] [INFO] monitorLogs - setCorrectPlcTimeOnceADay - function error SyntaxError: Unexpected token < in JSON at position 0 + at JSON.parse () + at /home/unipi/flowserver/flow/cmd_manager.js:2413:28 + at Object.exec_callback [as callback] (/home/unipi/flowserver/node_modules/total.js/builders.js:5803:3) + at IncomingMessage.request_process_end (/home/unipi/flowserver/node_modules/total.js/utils.js:1184:11) + at IncomingMessage.emit (events.js:412:35) + at endReadableNT (internal/streams/readable.js:1334:12) + at processTicksAndRejections (internal/process/task_queues.js:82:21) 503: Service Unavailable
503
Service Unavailable
+[2025-03-26T03:31:52.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-26 03:31:52 +[2025-03-26T07:09:19.306] [INFO] monitorLogs - MQTT client connected +[2025-03-27T03:31:53.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-27 03:31:53 +[2025-03-28T03:31:55.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-28 03:31:55 +[2025-03-28T07:34:52.775] [INFO] monitorLogs - MQTT client connected +[2025-03-28T07:35:24.674] [INFO] monitorLogs - MQTT client connected +[2025-03-28T07:36:54.565] [INFO] monitorLogs - MQTT client connected +[2025-03-28T09:13:26.828] [INFO] monitorLogs - MQTT client connected +[2025-03-29T03:31:56.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-29 03:31:56 +[2025-03-30T03:31:57.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-30 03:31:57 +[2025-03-31T03:31:59.013] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-31 03:31:59 +[2025-03-31T06:46:55.923] [INFO] monitorLogs - MQTT client error Error: read ECONNRESET + at TCP.onStreamRead (internal/stream_base_commons.js:209:20) { + errno: -104, + code: 'ECONNRESET', + syscall: 'read' +} +[2025-03-31T06:47:02.238] [INFO] monitorLogs - MQTT client connected +[2025-03-31T06:49:01.155] [INFO] monitorLogs - MQTT client connected +[2025-04-01T03:32:00.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-01 03:32:00 +[2025-04-01T07:40:38.466] [INFO] monitorLogs - MQTT client connected +[2025-04-01T07:55:26.066] [INFO] monitorLogs - MQTT client connected +[2025-04-02T03:32:01.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-02 03:32:01 +[2025-04-03T03:32:02.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-03 03:32:02 +[2025-04-04T03:32:04.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-04 03:32:04 +[2025-04-05T03:32:05.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-05 03:32:05 +[2025-04-06T03:32:06.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-06 03:32:06 +[2025-04-07T03:32:08.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-07 03:32:08 +[2025-04-07T08:29:51.328] [INFO] monitorLogs - MQTT client connected +[2025-04-07T08:30:49.777] [INFO] monitorLogs - MQTT client connected +[2025-04-07T08:31:33.922] [INFO] monitorLogs - MQTT client connected +[2025-04-07T08:37:03.950] [INFO] monitorLogs - MQTT client connected +[2025-04-07T08:38:09.549] [INFO] monitorLogs - MQTT client connected +[2025-04-07T10:55:27.032] [INFO] monitorLogs - MQTT client connected +[2025-04-08T03:32:09.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-08 03:32:09 +[2025-04-09T03:32:10.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-09 03:32:10 +[2025-04-10T03:32:12.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-10 03:32:12 +[2025-04-10T10:42:41.752] [INFO] monitorLogs - MQTT client connected +[2025-04-11T00:29:18.333] [INFO] monitorLogs - MQTT client connected +[2025-04-11T03:32:13.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-11 03:32:13 +[2025-04-12T03:32:14.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-12 03:32:14 +[2025-04-13T03:32:15.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-13 03:32:15 +[2025-04-14T03:32:17.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-14 03:32:17 +[2025-04-14T16:19:21.981] [INFO] monitorLogs - MQTT client connected +[2025-04-15T03:32:18.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-15 03:32:18 +[2025-04-15T11:19:32.774] [INFO] monitorLogs - MQTT client connected +[2025-04-16T03:32:19.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-16 03:32:19 +[2025-04-16T15:13:38.994] [INFO] monitorLogs - MQTT client connected +[2025-04-17T03:32:21.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-17 03:32:21 +[2025-04-18T03:32:22.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-18 03:32:22 +[2025-04-19T03:32:24.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-19 03:32:24 +[2025-04-20T03:32:25.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-20 03:32:25 +[2025-04-21T03:32:26.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-21 03:32:26 +[2025-04-22T03:32:28.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-22 03:32:28 +[2025-04-23T03:32:29.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-23 03:32:29 +[2025-04-24T03:32:31.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-24 03:32:31 +[2025-04-24T17:05:17.735] [INFO] monitorLogs - MQTT client connected +[2025-04-24T17:06:49.312] [INFO] monitorLogs - MQTT client connected +[2025-04-24T18:08:25.747] [INFO] monitorLogs - MQTT client connected +[2025-04-25T03:32:32.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-25 03:32:32 +[2025-04-25T08:30:48.897] [INFO] monitorLogs - MQTT client connected +[2025-04-25T10:30:55.381] [INFO] monitorLogs - MQTT client connected +[2025-04-25T10:31:44.427] [INFO] monitorLogs - MQTT client connected +[2025-04-26T03:32:33.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-26 03:32:33 +[2025-04-27T03:32:34.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-27 03:32:34 +[2025-04-28T03:32:36.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-28 03:32:36 +[2025-04-29T03:32:37.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-29 03:32:37 +[2025-04-29T06:53:41.168] [INFO] monitorLogs - MQTT client connected +[2025-04-29T06:56:21.192] [INFO] monitorLogs - MQTT client connected +[2025-04-29T07:48:05.788] [INFO] monitorLogs - MQTT client connected +[2025-04-29T07:49:50.746] [INFO] monitorLogs - MQTT client connected +[2025-04-29T07:50:54.181] [INFO] monitorLogs - MQTT client connected +[2025-04-29T07:52:06.482] [INFO] monitorLogs - MQTT client connected +[2025-04-29T07:54:20.471] [INFO] monitorLogs - MQTT client connected +[2025-04-29T07:54:37.057] [INFO] monitorLogs - MQTT client connected +[2025-04-29T10:48:05.288] [INFO] monitorLogs - MQTT client connected +[2025-04-30T03:32:39.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-30 03:32:39 +[2025-04-30T17:00:12.056] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-04-30T17:00:17.401] [INFO] monitorLogs - buildTasks - params undefined +[2025-04-30T17:00:17.406] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-04-30T17:00:17.407] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-04-30T17:00:17.408] [INFO] monitorLogs - 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 +} +[2025-04-30T17:00:17.411] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-04-30T17:00:17.412] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-05-01T11:00:00.411Z +[2025-04-30T17:00:17.413] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-04-30T17:00:17.414] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-04-30T17:00:17.415] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-04-30T17:00:17.416] [INFO] monitorLogs - 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 +} +[2025-04-30T17:00:17.417] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-04-30T17:00:17.418] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-05-01T11:00:00.418Z +[2025-04-30T17:00:17.419] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-04-30T17:00:17.420] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-04-30T17:00:17.420] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-04-30T17:00:17.421] [INFO] monitorLogs - 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 +} +[2025-04-30T17:00:17.422] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-04-30T17:00:17.423] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-05-01T11:00:00.423Z +[2025-04-30T17:00:17.424] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-04-30T17:00:17.425] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-04-30T17:00:17.427] [INFO] monitorLogs - tasks created: 291 +[2025-04-30T17:00:17.430] [INFO] monitorLogs - -->FLOW bol spustený Z5KyJe9nEg1QNbWlX0w4nDkoDjBLdqzR83VGv624 2025-04-24 +[2025-04-30T17:00:17.570] [INFO] monitorLogs - MQTT client connected +[2025-04-30T17:00:17.735] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-04-30T17:00:18.038] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-04-30T17:00:18.343] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-05-01T03:00:19.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-01 03:00:19 +[2025-05-02T03:00:20.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-02 03:00:20 +[2025-05-03T03:00:22.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-03 03:00:22 +[2025-05-04T03:00:23.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-04 03:00:23 +[2025-05-05T03:00:24.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-05 03:00:24 +[2025-05-05T06:39:33.932] [INFO] monitorLogs - MQTT client connected +[2025-05-06T03:00:26.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-06 03:00:26 +[2025-05-06T08:20:18.007] [INFO] monitorLogs - MQTT client connected +[2025-05-06T08:24:06.909] [INFO] monitorLogs - MQTT client connected +[2025-05-07T03:00:27.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-07 03:00:27 +[2025-05-07T19:30:14.124] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-05-07T19:30:19.460] [INFO] monitorLogs - buildTasks - params undefined +[2025-05-07T19:30:19.465] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-05-07T19:30:19.466] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-05-07T19:30:19.467] [INFO] monitorLogs - 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 +} +[2025-05-07T19:30:19.469] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-05-07T19:30:19.471] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-05-08T11:00:00.470Z +[2025-05-07T19:30:19.472] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-05-07T19:30:19.473] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-05-07T19:30:19.474] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-05-07T19:30:19.475] [INFO] monitorLogs - 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 +} +[2025-05-07T19:30:19.476] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-05-07T19:30:19.477] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-05-08T11:00:00.476Z +[2025-05-07T19:30:19.477] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-05-07T19:30:19.479] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-05-07T19:30:19.479] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-05-07T19:30:19.480] [INFO] monitorLogs - 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 +} +[2025-05-07T19:30:19.481] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-05-07T19:30:19.482] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-05-08T11:00:00.482Z +[2025-05-07T19:30:19.483] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-05-07T19:30:19.484] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-05-07T19:30:19.486] [INFO] monitorLogs - tasks created: 291 +[2025-05-07T19:30:19.488] [INFO] monitorLogs - -->FLOW bol spustený Z5KyJe9nEg1QNbWlX0w4nDkoDjBLdqzR83VGv624 2025-04-24 +[2025-05-07T19:30:19.647] [INFO] monitorLogs - MQTT client connected +[2025-05-07T19:30:19.794] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-05-07T19:30:20.097] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-05-07T19:30:20.400] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-05-08T03:30:20.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-08 03:30:20 +[2025-05-09T03:30:22.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-09 03:30:22 +[2025-05-10T03:30:23.017] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-10 03:30:23 +[2025-05-11T03:30:25.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-11 03:30:25 +[2025-05-12T03:30:26.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-12 03:30:26 +[2025-05-12T04:10:13.951] [INFO] monitorLogs - MQTT client connected +[2025-05-12T09:51:00.567] [INFO] monitorLogs - MQTT client connected +[2025-05-13T03:30:27.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-13 03:30:27 +[2025-05-13T09:59:19.661] [INFO] monitorLogs - MQTT client connected +[2025-05-14T03:30:29.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-14 03:30:29 +[2025-05-14T07:43:49.271] [INFO] monitorLogs - MQTT client connected +[2025-05-14T08:31:23.624] [INFO] monitorLogs - MQTT client connected +[2025-05-14T09:42:01.807] [INFO] monitorLogs - MQTT client connected +[2025-05-14T10:08:53.873] [INFO] monitorLogs - MQTT client connected +[2025-05-14T10:11:12.168] [INFO] monitorLogs - MQTT client connected +[2025-05-14T10:48:54.035] [INFO] monitorLogs - MQTT client connected +[2025-05-14T10:51:09.596] [INFO] monitorLogs - MQTT client connected +[2025-05-14T10:52:34.994] [INFO] monitorLogs - MQTT client connected +[2025-05-14T10:54:08.474] [INFO] monitorLogs - MQTT client connected +[2025-05-14T10:54:32.989] [INFO] monitorLogs - MQTT client connected +[2025-05-15T03:30:30.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-15 03:30:30 +[2025-05-15T08:48:49.889] [INFO] monitorLogs - MQTT client connected +[2025-05-16T03:30:32.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-16 03:30:32 +[2025-05-17T03:30:33.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-17 03:30:33 +[2025-05-18T03:30:34.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-18 03:30:34 +[2025-05-19T03:30:36.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-19 03:30:36 +[2025-05-20T03:30:37.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-20 03:30:37 +[2025-05-20T08:25:40.151] [INFO] monitorLogs - MQTT client connected +[2025-05-20T08:28:00.120] [INFO] monitorLogs - MQTT client connected +[2025-05-21T03:30:38.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-21 03:30:38 +[2025-05-22T03:30:40.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-22 03:30:40 +[2025-05-23T03:30:41.013] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-23 03:30:41 +[2025-05-24T03:30:43.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-24 03:30:43 +[2025-05-25T03:30:44.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-25 03:30:44 +[2025-05-26T03:30:45.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-26 03:30:45 +[2025-05-26T07:26:04.820] [INFO] monitorLogs - MQTT client connected +[2025-05-26T09:23:50.249] [INFO] monitorLogs - MQTT client connected +[2025-05-27T03:30:47.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-27 03:30:47 +[2025-05-27T12:46:34.728] [INFO] monitorLogs - MQTT client connected +[2025-05-27T12:48:03.477] [INFO] monitorLogs - MQTT client connected +[2025-05-27T12:50:01.185] [INFO] monitorLogs - MQTT client connected +[2025-05-28T03:30:48.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-28 03:30:48 +[2025-05-28T10:12:13.430] [INFO] monitorLogs - MQTT client connected +[2025-05-29T03:30:50.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-29 03:30:50 +[2025-05-29T10:22:36.680] [INFO] monitorLogs - MQTT client connected +[2025-05-30T03:30:51.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-30 03:30:51 +[2025-05-30T07:39:23.547] [INFO] monitorLogs - MQTT client connected +[2025-05-31T03:30:53.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-31 03:30:53 +[2025-05-31T13:45:26.207] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-05-31T13:45:31.542] [INFO] monitorLogs - buildTasks - params undefined +[2025-05-31T13:45:31.547] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-05-31T13:45:31.548] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-05-31T13:45:31.548] [INFO] monitorLogs - 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 +} +[2025-05-31T13:45:31.551] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-05-31T13:45:31.552] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-06-01T11:00:00.552Z +[2025-05-31T13:45:31.554] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-05-31T13:45:31.555] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-05-31T13:45:31.556] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-05-31T13:45:31.556] [INFO] monitorLogs - 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 +} +[2025-05-31T13:45:31.558] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-05-31T13:45:31.558] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-06-01T11:00:00.558Z +[2025-05-31T13:45:31.559] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-05-31T13:45:31.560] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-05-31T13:45:31.561] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-05-31T13:45:31.562] [INFO] monitorLogs - 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 +} +[2025-05-31T13:45:31.563] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-05-31T13:45:31.564] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-06-01T11:00:00.563Z +[2025-05-31T13:45:31.564] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-05-31T13:45:31.565] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-05-31T13:45:31.568] [INFO] monitorLogs - tasks created: 291 +[2025-05-31T13:45:31.570] [INFO] monitorLogs - -->FLOW bol spustený Z5KyJe9nEg1QNbWlX0w4nDkoDjBLdqzR83VGv624 2025-04-24 +[2025-05-31T13:45:36.575] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-01T03:45:33.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-01 03:45:33 +[2025-06-02T03:45:35.013] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-02 03:45:35 +[2025-06-03T03:45:36.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-03 03:45:36 +[2025-06-04T03:45:38.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-04 03:45:38 +[2025-06-04T16:59:13.089] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-06-04T16:59:18.429] [INFO] monitorLogs - buildTasks - params undefined +[2025-06-04T16:59:18.434] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-06-04T16:59:18.435] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-06-04T16:59:18.435] [INFO] monitorLogs - 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 +} +[2025-06-04T16:59:18.438] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-06-04T16:59:18.440] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-06-05T11:00:00.439Z +[2025-06-04T16:59:18.441] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-06-04T16:59:18.442] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-06-04T16:59:18.443] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-06-04T16:59:18.443] [INFO] monitorLogs - 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 +} +[2025-06-04T16:59:18.445] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-06-04T16:59:18.445] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-06-05T11:00:00.445Z +[2025-06-04T16:59:18.446] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-06-04T16:59:18.447] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-06-04T16:59:18.448] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-06-04T16:59:18.448] [INFO] monitorLogs - 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 +} +[2025-06-04T16:59:18.450] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-06-04T16:59:18.451] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-06-05T11:00:00.450Z +[2025-06-04T16:59:18.451] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-06-04T16:59:18.452] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-06-04T16:59:18.455] [INFO] monitorLogs - tasks created: 291 +[2025-06-04T16:59:18.458] [INFO] monitorLogs - -->FLOW bol spustený Z5KyJe9nEg1QNbWlX0w4nDkoDjBLdqzR83VGv624 2025-04-24 +[2025-06-04T16:59:23.461] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-05T03:59:21.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-05 03:59:21 +[2025-06-06T03:59:22.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-06 03:59:22 +[2025-06-07T03:59:24.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-07 03:59:24 +[2025-06-08T03:59:25.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-08 03:59:25 +[2025-06-09T03:59:27.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-09 03:59:27 +[2025-06-10T03:59:28.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-10 03:59:28 +[2025-06-11T03:59:30.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-11 03:59:30 +[2025-06-12T03:59:31.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-12 03:59:31 +[2025-06-13T03:59:33.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-13 03:59:33 +[2025-06-13T15:28:26.195] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-06-13T15:28:31.535] [INFO] monitorLogs - buildTasks - params undefined +[2025-06-13T15:28:31.539] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-06-13T15:28:31.540] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-06-13T15:28:31.541] [INFO] monitorLogs - 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 +} +[2025-06-13T15:28:31.544] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-06-13T15:28:31.545] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-06-14T11:00:00.544Z +[2025-06-13T15:28:31.546] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-06-13T15:28:31.547] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-06-13T15:28:31.548] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-06-13T15:28:31.549] [INFO] monitorLogs - 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 +} +[2025-06-13T15:28:31.550] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-06-13T15:28:31.551] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-06-14T11:00:00.551Z +[2025-06-13T15:28:31.552] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-06-13T15:28:31.553] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-06-13T15:28:31.554] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-06-13T15:28:31.554] [INFO] monitorLogs - 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 +} +[2025-06-13T15:28:31.555] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-06-13T15:28:31.556] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-06-14T11:00:00.556Z +[2025-06-13T15:28:31.557] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-06-13T15:28:31.558] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-06-13T15:28:31.561] [INFO] monitorLogs - tasks created: 291 +[2025-06-13T15:28:31.563] [INFO] monitorLogs - -->FLOW bol spustený Z5KyJe9nEg1QNbWlX0w4nDkoDjBLdqzR83VGv624 2025-04-24 +[2025-06-13T15:28:36.567] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-14T03:28:33.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-14 03:28:33 +[2025-06-15T03:28:35.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-15 03:28:35 +[2025-06-16T03:28:37.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-16 03:28:37 +[2025-06-17T03:28:38.015] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-17 03:28:38 +[2025-06-18T03:28:39.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-18 03:28:39 +[2025-06-19T03:28:41.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-19 03:28:41 +[2025-06-20T03:28:43.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-20 03:28:43 +[2025-06-21T03:28:44.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-21 03:28:44 +[2025-06-22T03:28:46.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-22 03:28:46 +[2025-06-23T03:28:47.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-23 03:28:47 +[2025-06-24T03:28:49.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-24 03:28:49 +[2025-06-25T03:28:50.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-25 03:28:50 +[2025-06-26T03:28:52.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-26 03:28:52 +[2025-06-27T03:28:54.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-27 03:28:54 +[2025-06-28T03:28:55.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-28 03:28:55 +[2025-06-29T03:28:57.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-29 03:28:57 +[2025-06-30T03:28:59.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-30 03:28:59 +[2025-07-01T03:29:00.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-01 03:29:00 +[2025-07-02T03:29:02.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-02 03:29:02 +[2025-07-03T03:29:03.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-03 03:29:03 +[2025-07-04T03:29:05.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-04 03:29:05 +[2025-07-05T03:29:07.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-05 03:29:07 +[2025-07-06T03:29:08.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-06 03:29:08 +[2025-07-07T03:29:10.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-07 03:29:10 +[2025-07-07T13:46:25.086] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-07-07T13:46:30.425] [INFO] monitorLogs - buildTasks - params undefined +[2025-07-07T13:46:30.429] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-07-07T13:46:30.430] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-07-07T13:46:30.431] [INFO] monitorLogs - 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 +} +[2025-07-07T13:46:30.434] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-07-07T13:46:30.436] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-07-08T11:00:00.435Z +[2025-07-07T13:46:30.437] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-07-07T13:46:30.438] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-07-07T13:46:30.439] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-07-07T13:46:30.440] [INFO] monitorLogs - 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 +} +[2025-07-07T13:46:30.441] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-07-07T13:46:30.442] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-07-08T11:00:00.442Z +[2025-07-07T13:46:30.443] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-07-07T13:46:30.444] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-07-07T13:46:30.444] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-07-07T13:46:30.445] [INFO] monitorLogs - 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 +} +[2025-07-07T13:46:30.446] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-07-07T13:46:30.447] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-07-08T11:00:00.447Z +[2025-07-07T13:46:30.448] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-07-07T13:46:30.449] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-07-07T13:46:30.451] [INFO] monitorLogs - tasks created: 291 +[2025-07-07T13:46:30.454] [INFO] monitorLogs - -->FLOW bol spustený Z5KyJe9nEg1QNbWlX0w4nDkoDjBLdqzR83VGv624 2025-07-08 +[2025-07-07T13:46:35.458] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-08T03:46:32.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-08 03:46:32 +[2025-07-09T03:46:33.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-09 03:46:33 +[2025-07-10T02:23:55.523] [INFO] monitorLogs - MQTT client error Error: connect ECONNREFUSED 192.168.252.1:1883 + at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1159:16) { + errno: -111, + code: 'ECONNREFUSED', + syscall: 'connect', + address: '192.168.252.1', + port: 1883 +} +[2025-07-10T03:46:35.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-10 03:46:35 +[2025-07-11T03:46:36.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-11 03:46:36 +[2025-07-12T03:46:38.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-12 03:46:38 +[2025-07-13T03:46:39.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-13 03:46:39 +[2025-07-14T03:46:41.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-14 03:46:41 +[2025-07-15T03:46:42.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-15 03:46:42 +[2025-07-16T03:46:44.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-16 03:46:44 +[2025-07-17T03:46:46.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-17 03:46:46 +[2025-07-18T03:46:47.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-18 03:46:47 +[2025-07-19T03:46:48.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-19 03:46:48 +[2025-07-20T03:46:50.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-20 03:46:50 +[2025-07-21T03:46:52.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-21 03:46:52 +[2025-07-22T03:46:53.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-22 03:46:53 +[2025-07-23T03:46:55.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-23 03:46:55 +[2025-07-24T03:46:56.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-24 03:46:56 +[2025-07-25T03:46:58.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-25 03:46:58 +[2025-07-26T03:46:59.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-26 03:46:59 +[2025-07-27T03:47:01.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-27 03:47:01 +[2025-07-28T03:47:02.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-28 03:47:02 +[2025-07-29T03:47:04.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-29 03:47:04 +[2025-07-29T12:19:38.296] [INFO] monitorLogs - MQTT client error Error: connect ECONNREFUSED 192.168.252.1:1883 + at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1159:16) { + errno: -111, + code: 'ECONNREFUSED', + syscall: 'connect', + address: '192.168.252.1', + port: 1883 +} +[2025-07-30T03:47:05.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-30 03:47:05 +[2025-07-31T03:47:07.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-31 03:47:07 +[2025-08-01T03:47:08.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-01 03:47:08 +[2025-08-02T03:47:10.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-02 03:47:10 +[2025-08-03T03:47:11.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-03 03:47:11 +[2025-08-04T03:47:13.024] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-04 03:47:13 +[2025-08-05T03:47:14.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-05 03:47:14 +[2025-08-06T03:47:16.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-06 03:47:16 +[2025-08-06T13:43:03.123] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-08-06T13:43:08.460] [INFO] monitorLogs - buildTasks - params undefined +[2025-08-06T13:43:08.464] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-08-06T13:43:08.465] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-08-06T13:43:08.466] [INFO] monitorLogs - 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 +} +[2025-08-06T13:43:08.469] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-08-06T13:43:08.470] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-08-07T11:00:00.469Z +[2025-08-06T13:43:08.471] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-08-06T13:43:08.472] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-08-06T13:43:08.473] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-08-06T13:43:08.474] [INFO] monitorLogs - 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 +} +[2025-08-06T13:43:08.475] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-08-06T13:43:08.476] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-08-07T11:00:00.476Z +[2025-08-06T13:43:08.477] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-08-06T13:43:08.478] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-08-06T13:43:08.479] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-08-06T13:43:08.479] [INFO] monitorLogs - 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 +} +[2025-08-06T13:43:08.481] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-08-06T13:43:08.481] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-08-07T11:00:00.481Z +[2025-08-06T13:43:08.482] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-08-06T13:43:08.483] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-08-06T13:43:08.486] [INFO] monitorLogs - tasks created: 291 +[2025-08-06T13:43:08.488] [INFO] monitorLogs - -->FLOW bol spustený Z5KyJe9nEg1QNbWlX0w4nDkoDjBLdqzR83VGv624 2025-08-08 +[2025-08-06T13:43:13.492] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-07T03:43:09.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-07 03:43:09 +[2025-08-08T03:43:11.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-08 03:43:11 +[2025-08-09T03:43:12.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-09 03:43:12 +[2025-08-10T03:43:14.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-10 03:43:14 +[2025-08-11T03:43:16.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-11 03:43:16 +[2025-08-12T03:43:17.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-12 03:43:17 +[2025-08-13T03:43:19.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-13 03:43:19 +[2025-08-14T03:43:20.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-14 03:43:20 +[2025-08-15T03:43:22.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-15 03:43:22 +[2025-08-16T03:43:24.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-16 03:43:24 +[2025-08-17T03:43:25.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-17 03:43:25 +[2025-08-18T03:43:27.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-18 03:43:27 +[2025-08-19T03:43:28.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-19 03:43:28 +[2025-08-20T03:43:30.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-20 03:43:30 +[2025-08-21T03:43:32.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-21 03:43:32 +[2025-08-22T03:43:33.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-22 03:43:33 +[2025-08-23T03:43:35.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-23 03:43:35 +[2025-08-24T03:43:36.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-24 03:43:36 +[2025-08-25T03:43:37.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-25 03:43:37 +[2025-08-26T03:43:39.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-26 03:43:39 +[2025-08-27T03:43:40.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-27 03:43:40 +[2025-08-28T03:43:42.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-28 03:43:42 +[2025-08-29T03:43:44.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-29 03:43:44 +[2025-08-30T03:43:45.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-30 03:43:45 +[2025-08-31T03:43:47.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-31 03:43:47 +[2025-09-01T03:43:48.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-01 03:43:48 +[2025-09-02T03:43:50.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-02 03:43:50 +[2025-09-03T03:43:51.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-03 03:43:51 +[2025-09-04T03:43:53.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-04 03:43:53 +[2025-09-05T03:43:54.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-05 03:43:54 +[2025-09-06T03:43:56.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-06 03:43:56 +[2025-09-07T03:43:57.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-07 03:43:57 +[2025-09-08T03:43:59.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-08 03:43:59 +[2025-09-09T03:44:00.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-09 03:44:00 +[2025-09-10T03:44:02.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-10 03:44:02 +[2025-09-11T03:44:03.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-11 03:44:03 +[2025-09-12T03:44:05.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-12 03:44:05 +[2025-09-13T03:44:06.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-13 03:44:06 +[2025-09-14T03:44:08.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-14 03:44:08 +[2025-09-15T03:44:09.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-15 03:44:09 +[2025-09-16T03:44:11.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-16 03:44:11 +[2025-09-16T15:44:39.859] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-09-16T15:44:45.199] [INFO] monitorLogs - buildTasks - params undefined +[2025-09-16T15:44:45.204] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-09-16T15:44:45.205] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-09-16T15:44:45.206] [INFO] monitorLogs - 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 +} +[2025-09-16T15:44:45.209] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-16T15:44:45.210] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-09-17T11:00:00.209Z +[2025-09-16T15:44:45.211] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-09-16T15:44:45.213] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-09-16T15:44:45.213] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-09-16T15:44:45.214] [INFO] monitorLogs - 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 +} +[2025-09-16T15:44:45.215] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-16T15:44:45.216] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-09-17T11:00:00.216Z +[2025-09-16T15:44:45.217] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-09-16T15:44:45.218] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-09-16T15:44:45.219] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-09-16T15:44:45.219] [INFO] monitorLogs - 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 +} +[2025-09-16T15:44:45.221] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-16T15:44:45.221] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-09-17T11:00:00.221Z +[2025-09-16T15:44:45.222] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-09-16T15:44:45.223] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-09-16T15:44:45.225] [INFO] monitorLogs - tasks created: 291 +[2025-09-16T15:44:45.228] [INFO] monitorLogs - -->FLOW bol spustený Z5KyJe9nEg1QNbWlX0w4nDkoDjBLdqzR83VGv624 2025-08-08 +[2025-09-16T15:44:50.248] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-17T03:44:46.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-17 03:44:46 +[2025-09-17T20:40:59.981] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-09-17T20:41:05.321] [INFO] monitorLogs - buildTasks - params undefined +[2025-09-17T20:41:05.325] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-09-17T20:41:05.326] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-09-17T20:41:05.327] [INFO] monitorLogs - 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 +} +[2025-09-17T20:41:05.330] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-17T20:41:05.331] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-09-18T11:00:00.330Z +[2025-09-17T20:41:05.332] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-09-17T20:41:05.334] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-09-17T20:41:05.334] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-09-17T20:41:05.335] [INFO] monitorLogs - 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 +} +[2025-09-17T20:41:05.336] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-17T20:41:05.337] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-09-18T11:00:00.337Z +[2025-09-17T20:41:05.338] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-09-17T20:41:05.339] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-09-17T20:41:05.340] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-09-17T20:41:05.340] [INFO] monitorLogs - 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 +} +[2025-09-17T20:41:05.342] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-17T20:41:05.342] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-09-18T11:00:00.342Z +[2025-09-17T20:41:05.343] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-09-17T20:41:05.344] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-09-17T20:41:05.346] [INFO] monitorLogs - tasks created: 291 +[2025-09-17T20:41:05.349] [INFO] monitorLogs - -->FLOW bol spustený Z5KyJe9nEg1QNbWlX0w4nDkoDjBLdqzR83VGv624 2025-08-08 +[2025-09-17T20:41:10.374] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-18T03:41:07.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-18 03:41:07 +[2025-09-19T03:41:09.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-19 03:41:09 +[2025-09-19T11:20:34.008] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-09-19T11:20:39.349] [INFO] monitorLogs - buildTasks - params undefined +[2025-09-19T11:20:39.353] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-09-19T11:20:39.354] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-09-19T11:20:39.355] [INFO] monitorLogs - 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 +} +[2025-09-19T11:20:39.358] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-19T11:20:39.359] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-09-19T11:00:00.358Z +[2025-09-19T11:20:39.360] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-09-19T11:20:39.361] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-09-19T11:20:39.362] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-09-19T11:20:39.363] [INFO] monitorLogs - 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 +} +[2025-09-19T11:20:39.365] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-19T11:20:39.366] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-09-19T11:00:00.366Z +[2025-09-19T11:20:39.367] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-09-19T11:20:39.368] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-09-19T11:20:39.369] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-09-19T11:20:39.369] [INFO] monitorLogs - 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 +} +[2025-09-19T11:20:39.371] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-19T11:20:39.371] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-09-19T11:00:00.371Z +[2025-09-19T11:20:39.372] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-09-19T11:20:39.373] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-09-19T11:20:39.375] [INFO] monitorLogs - tasks created: 291 +[2025-09-19T11:20:39.378] [INFO] monitorLogs - -->FLOW bol spustený Z5KyJe9nEg1QNbWlX0w4nDkoDjBLdqzR83VGv624 2025-08-08 +[2025-09-19T11:20:44.399] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-20T03:20:41.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-20 03:20:41 +[2025-09-21T01:29:16.886] [INFO] monitorLogs - MQTT client error Error: connect ECONNREFUSED 192.168.252.1:1883 + at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1159:16) { + errno: -111, + code: 'ECONNREFUSED', + syscall: 'connect', + address: '192.168.252.1', + port: 1883 +} +[2025-09-21T03:20:42.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-21 03:20:42 +[2025-09-21T18:11:38.435] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-09-21T18:11:43.774] [INFO] monitorLogs - buildTasks - params undefined +[2025-09-21T18:11:43.779] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-09-21T18:11:43.780] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-09-21T18:11:43.780] [INFO] monitorLogs - 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 +} +[2025-09-21T18:11:43.783] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-21T18:11:43.784] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-09-22T11:00:00.784Z +[2025-09-21T18:11:43.786] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-09-21T18:11:43.787] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-09-21T18:11:43.788] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-09-21T18:11:43.788] [INFO] monitorLogs - 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 +} +[2025-09-21T18:11:43.790] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-21T18:11:43.790] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-09-22T11:00:00.790Z +[2025-09-21T18:11:43.791] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-09-21T18:11:43.792] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-09-21T18:11:43.793] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-09-21T18:11:43.793] [INFO] monitorLogs - 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 +} +[2025-09-21T18:11:43.795] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-21T18:11:43.795] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-09-22T11:00:00.795Z +[2025-09-21T18:11:43.796] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-09-21T18:11:43.797] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-09-21T18:11:43.799] [INFO] monitorLogs - tasks created: 291 +[2025-09-21T18:11:43.802] [INFO] monitorLogs - -->FLOW bol spustený Z5KyJe9nEg1QNbWlX0w4nDkoDjBLdqzR83VGv624 2025-08-08 +[2025-09-21T18:11:48.824] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-22T03:11:46.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-22 03:11:46 +[2025-09-23T03:11:48.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-23 03:11:48 +[2025-09-23T13:06:48.149] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-09-23T13:06:53.489] [INFO] monitorLogs - buildTasks - params undefined +[2025-09-23T13:06:53.494] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-09-23T13:06:53.495] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-09-23T13:06:53.496] [INFO] monitorLogs - 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 +} +[2025-09-23T13:06:53.498] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-23T13:06:53.500] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-09-24T11:00:00.499Z +[2025-09-23T13:06:53.501] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-09-23T13:06:53.502] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-09-23T13:06:53.503] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-09-23T13:06:53.504] [INFO] monitorLogs - 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 +} +[2025-09-23T13:06:53.505] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-23T13:06:53.506] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-09-24T11:00:00.505Z +[2025-09-23T13:06:53.507] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-09-23T13:06:53.508] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-09-23T13:06:53.508] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-09-23T13:06:53.509] [INFO] monitorLogs - 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 +} +[2025-09-23T13:06:53.510] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-23T13:06:53.511] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-09-24T11:00:00.511Z +[2025-09-23T13:06:53.512] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-09-23T13:06:53.513] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-09-23T13:06:53.515] [INFO] monitorLogs - tasks created: 291 +[2025-09-23T13:06:53.517] [INFO] monitorLogs - -->FLOW bol spustený Z5KyJe9nEg1QNbWlX0w4nDkoDjBLdqzR83VGv624 2025-08-08 +[2025-09-23T13:06:58.538] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-23T14:33:19.452] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-09-23T14:33:24.792] [INFO] monitorLogs - buildTasks - params undefined +[2025-09-23T14:33:24.797] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-09-23T14:33:24.798] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-09-23T14:33:24.799] [INFO] monitorLogs - 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 +} +[2025-09-23T14:33:24.802] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-23T14:33:24.803] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-09-24T11:00:00.802Z +[2025-09-23T14:33:24.804] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-09-23T14:33:24.806] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-09-23T14:33:24.806] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-09-23T14:33:24.807] [INFO] monitorLogs - 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 +} +[2025-09-23T14:33:24.808] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-23T14:33:24.809] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-09-24T11:00:00.809Z +[2025-09-23T14:33:24.810] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-09-23T14:33:24.811] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-09-23T14:33:24.812] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-09-23T14:33:24.812] [INFO] monitorLogs - 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 +} +[2025-09-23T14:33:24.814] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-23T14:33:24.814] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-09-24T11:00:00.814Z +[2025-09-23T14:33:24.815] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-09-23T14:33:24.816] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-09-23T14:33:24.818] [INFO] monitorLogs - tasks created: 291 +[2025-09-23T14:33:24.821] [INFO] monitorLogs - -->FLOW bol spustený Z5KyJe9nEg1QNbWlX0w4nDkoDjBLdqzR83VGv624 2025-08-08 +[2025-09-23T14:33:29.842] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-24T03:33:26.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-24 03:33:26 +[2025-09-25T03:33:27.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-25 03:33:27 +[2025-09-25T16:33:06.458] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-09-25T16:33:11.820] [INFO] monitorLogs - buildTasks - params undefined +[2025-09-25T16:33:11.825] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-09-25T16:33:11.826] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-09-25T16:33:11.826] [INFO] monitorLogs - 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 +} +[2025-09-25T16:33:11.829] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-25T16:33:11.831] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-09-26T11:00:00.830Z +[2025-09-25T16:33:11.832] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-09-25T16:33:11.833] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-09-25T16:33:11.834] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-09-25T16:33:11.834] [INFO] monitorLogs - 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 +} +[2025-09-25T16:33:11.836] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-25T16:33:11.837] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-09-26T11:00:00.836Z +[2025-09-25T16:33:11.837] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-09-25T16:33:11.838] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-09-25T16:33:11.839] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-09-25T16:33:11.840] [INFO] monitorLogs - 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 +} +[2025-09-25T16:33:11.841] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-25T16:33:11.842] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-09-26T11:00:00.842Z +[2025-09-25T16:33:11.842] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-09-25T16:33:11.843] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-09-25T16:33:11.846] [INFO] monitorLogs - tasks created: 291 +[2025-09-25T16:33:11.848] [INFO] monitorLogs - -->FLOW bol spustený Z5KyJe9nEg1QNbWlX0w4nDkoDjBLdqzR83VGv624 2025-08-08 +[2025-09-25T16:33:16.852] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-26T03:33:13.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-26 03:33:13 +[2025-09-27T03:33:15.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-27 03:33:15 +[2025-09-28T03:33:16.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-28 03:33:16 +[2025-09-29T03:33:17.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-29 03:33:17 +[2025-09-30T03:33:19.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-30 03:33:19 +[2025-10-01T03:33:20.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-01 03:33:20 +[2025-10-02T03:33:22.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-02 03:33:22 +[2025-10-03T03:33:23.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-03 03:33:23 +[2025-10-03T14:48:50.055] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-03T14:48:55.393] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-03T14:48:55.398] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-03T14:48:55.399] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-03T14:48:55.400] [INFO] monitorLogs - 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 +} +[2025-10-03T14:48:55.403] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-03T14:48:55.404] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-10-04T11:00:00.403Z +[2025-10-03T14:48:55.406] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-03T14:48:55.407] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-10-03T14:48:55.407] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-03T14:48:55.408] [INFO] monitorLogs - 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 +} +[2025-10-03T14:48:55.409] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-03T14:48:55.410] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-10-04T11:00:00.410Z +[2025-10-03T14:48:55.411] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-03T14:48:55.412] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-10-03T14:48:55.413] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-03T14:48:55.413] [INFO] monitorLogs - 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 +} +[2025-10-03T14:48:55.415] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-03T14:48:55.416] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-10-04T11:00:00.415Z +[2025-10-03T14:48:55.416] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-03T14:48:55.417] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-10-03T14:48:55.420] [INFO] monitorLogs - tasks created: 291 +[2025-10-03T14:48:55.422] [INFO] monitorLogs - -->FLOW bol spustený Z5KyJe9nEg1QNbWlX0w4nDkoDjBLdqzR83VGv624 2025-08-08 +[2025-10-03T14:49:00.445] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-04T03:48:57.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-04 03:48:57 +[2025-10-05T03:48:58.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-05 03:48:58 +[2025-10-06T03:49:00.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-06 03:49:00 +[2025-10-07T03:49:01.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-07 03:49:01 +[2025-10-08T03:49:02.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-08 03:49:02 +[2025-10-09T03:49:04.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-09 03:49:04 +[2025-10-09T16:53:58.592] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-09T16:54:03.931] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-09T16:54:03.936] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-09T16:54:03.937] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-09T16:54:03.938] [INFO] monitorLogs - 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 +} +[2025-10-09T16:54:03.941] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T16:54:03.942] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-10-10T11:00:00.941Z +[2025-10-09T16:54:03.943] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-09T16:54:03.944] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-10-09T16:54:03.945] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-09T16:54:03.946] [INFO] monitorLogs - 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 +} +[2025-10-09T16:54:03.947] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T16:54:03.948] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-10-10T11:00:00.948Z +[2025-10-09T16:54:03.949] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-09T16:54:03.950] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-10-09T16:54:03.951] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-09T16:54:03.951] [INFO] monitorLogs - 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 +} +[2025-10-09T16:54:03.953] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T16:54:03.953] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-10-10T11:00:00.953Z +[2025-10-09T16:54:03.954] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-09T16:54:03.955] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-10-09T16:54:03.957] [INFO] monitorLogs - tasks created: 291 +[2025-10-09T16:54:03.960] [INFO] monitorLogs - -->FLOW bol spustený Z5KyJe9nEg1QNbWlX0w4nDkoDjBLdqzR83VGv624 2025-08-08 +[2025-10-09T16:54:08.980] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-09T19:06:31.442] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-09T19:06:36.781] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-09T19:06:36.786] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-09T19:06:36.787] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-09T19:06:36.787] [INFO] monitorLogs - 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 +} +[2025-10-09T19:06:36.790] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T19:06:36.792] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-10-10T11:00:00.791Z +[2025-10-09T19:06:36.793] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-09T19:06:36.794] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-10-09T19:06:36.795] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-09T19:06:36.796] [INFO] monitorLogs - 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 +} +[2025-10-09T19:06:36.799] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T19:06:36.799] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-10-10T11:00:00.799Z +[2025-10-09T19:06:36.800] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-09T19:06:36.801] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-10-09T19:06:36.802] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-09T19:06:36.803] [INFO] monitorLogs - 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 +} +[2025-10-09T19:06:36.804] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T19:06:36.805] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-10-10T11:00:00.805Z +[2025-10-09T19:06:36.805] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-09T19:06:36.806] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-10-09T19:06:36.809] [INFO] monitorLogs - tasks created: 291 +[2025-10-09T19:06:36.811] [INFO] monitorLogs - -->FLOW bol spustený Z5KyJe9nEg1QNbWlX0w4nDkoDjBLdqzR83VGv624 2025-08-08 +[2025-10-09T19:06:41.839] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-10T03:06:38.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-10 03:06:38 +[2025-10-11T03:06:39.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-11 03:06:39 +[2025-10-12T03:06:41.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-12 03:06:41 +[2025-10-13T03:06:42.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-13 03:06:42 +[2025-10-14T03:06:43.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-14 03:06:43 +[2025-10-15T03:06:45.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-15 03:06:45 +[2025-10-15T14:17:35.352] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-15T14:17:40.712] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-15T14:17:40.717] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-15T14:17:40.718] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-15T14:17:40.718] [INFO] monitorLogs - 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 +} +[2025-10-15T14:17:40.721] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-15T14:17:40.723] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 1 2025-10-16T11:00:00.722Z +[2025-10-15T14:17:40.724] [INFO] monitorLogs - -->time_points final 1 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-15T14:17:40.725] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-10-15T14:17:40.726] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-15T14:17:40.726] [INFO] monitorLogs - 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 +} +[2025-10-15T14:17:40.728] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-15T14:17:40.728] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 2 2025-10-16T11:00:00.728Z +[2025-10-15T14:17:40.729] [INFO] monitorLogs - -->time_points final 2 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-15T14:17:40.730] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-10-15T14:17:40.731] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-15T14:17:40.731] [INFO] monitorLogs - 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 +} +[2025-10-15T14:17:40.733] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-15T14:17:40.734] [INFO] monitorLogs - TimePoint params: profileTimepoint: turn on line: 3 2025-10-16T11:00:00.733Z +[2025-10-15T14:17:40.734] [INFO] monitorLogs - -->time_points final 3 [ { value: 1, start_time: '13:00', name: 'profileTimepoint' } ] +[2025-10-15T14:17:40.735] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-10-15T14:17:40.738] [INFO] monitorLogs - tasks created: 291 +[2025-10-15T14:17:40.740] [INFO] monitorLogs - -->FLOW bol spustený Z5KyJe9nEg1QNbWlX0w4nDkoDjBLdqzR83VGv624 2025-10-08 +[2025-10-15T14:17:45.749] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu diff --git a/RVO48/package-lock.json b/RVO48/package-lock.json new file mode 100755 index 0000000..cc5cfd9 --- /dev/null +++ b/RVO48/package-lock.json @@ -0,0 +1,2125 @@ +{ + "name": "emptyproject", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "emptyproject", + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "bitwise": "^2.1.0", + "easy-crc": "0.0.2", + "jsmodbus": "^4.0.6", + "log4js": "^6.3.0", + "mqtt": "^4.2.6", + "nodemailer": "^6.9.7", + "serialport": "^9.2.8", + "total.js": "^3.4.13" + } + }, + "node_modules/@serialport/binding-abstract": { + "version": "9.2.3", + "resolved": "https://registry.npmjs.org/@serialport/binding-abstract/-/binding-abstract-9.2.3.tgz", + "integrity": "sha512-cQs9tbIlG3P0IrOWyVirqlhWuJ7Ms2Zh9m2108z6Y5UW/iVj6wEOiW8EmK9QX9jmJXYllE7wgGgvVozP5oCj3w==", + "dependencies": { + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/binding-mock": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/binding-mock/-/binding-mock-9.2.4.tgz", + "integrity": "sha512-dpEhACCs44oQhh6ajJfJdvQdK38Vq0N4W6iD/gdplglDCK7qXRQCMUjJIeKdS/HSEiWkC3bwumUhUufdsOyT4g==", + "dependencies": { + "@serialport/binding-abstract": "9.2.3", + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/bindings": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/@serialport/bindings/-/bindings-9.2.8.tgz", + "integrity": "sha512-hSLxTe0tADZ3LMMGwvEJWOC/TaFQTyPeFalUCsJ1lSQ0k6bPF04JwrtB/C81GetmDBTNRY0GlD0SNtKCc7Dr5g==", + "hasInstallScript": true, + "dependencies": { + "@serialport/binding-abstract": "9.2.3", + "@serialport/parser-readline": "9.2.4", + "bindings": "^1.5.0", + "debug": "^4.3.2", + "nan": "^2.15.0", + "prebuild-install": "^7.0.0" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-byte-length": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-byte-length/-/parser-byte-length-9.2.4.tgz", + "integrity": "sha512-sQD/iw4ZMU3xW9PLi0/GlvU6Y623jGeWecbMkO7izUo/6P7gtfv1c9ikd5h0kwL8AoAOpQA1lxdHIKox+umBUg==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-cctalk": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-cctalk/-/parser-cctalk-9.2.4.tgz", + "integrity": "sha512-T4TU5vQMwmo9AB3gQLFDWbfJXlW5jd9guEsB/nqKjFHTv0FXPdZ7DQ2TpSp8RnHWxU3GX6kYTaDO20BKzc8GPQ==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-delimiter": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-delimiter/-/parser-delimiter-9.2.4.tgz", + "integrity": "sha512-4nvTAoYAgkxFiXrkI+3CA49Yd43CODjeszh89EK+I9c8wOZ+etZduRCzINYPiy26g7zO+GRAb9FoPCsY+sYcbQ==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-inter-byte-timeout": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-inter-byte-timeout/-/parser-inter-byte-timeout-9.2.4.tgz", + "integrity": "sha512-SOAdvr0oBQIOCXX198hiTlxs4JTKg9j5piapw5tNq52fwDOWdbYrFneT/wN04UTMKaDrJuEvXq6T4rv4j7nJ5A==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-readline": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-readline/-/parser-readline-9.2.4.tgz", + "integrity": "sha512-Z1/qrZTQUVhNSJP1hd9YfDvq0o7d87rNwAjjRKbVpa7Qi51tG5BnKt43IV3NFMyBlVcRe0rnIb3tJu57E0SOwg==", + "dependencies": { + "@serialport/parser-delimiter": "9.2.4" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-ready": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-ready/-/parser-ready-9.2.4.tgz", + "integrity": "sha512-Pyi94Itjl6qAURwIZr/gmZpMAyTmKXThm6vL5DoAWGQjcRHWB0gwv2TY2v7N+mQLJYUKU3cMnvnATXxHm7xjxw==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-regex": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-regex/-/parser-regex-9.2.4.tgz", + "integrity": "sha512-sI/cVvPOYz+Dbv4ZdnW16qAwvXiFf/1pGASQdbveRTlgJDdz7sRNlCBifzfTN2xljwvCTZYqiudKvDdC1TepRQ==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/stream": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/stream/-/stream-9.2.4.tgz", + "integrity": "sha512-bLye8Ub4vUFQGmkh8qEqehr7SE7EJs2yDs0h9jzuL5oKi+F34CFmWkEErO8GAOQ8YNn7p6b3GxUgs+0BrHHDZQ==", + "dependencies": { + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "node_modules/are-we-there-yet": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", + "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/base64-js": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", + "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==" + }, + "node_modules/bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "dependencies": { + "file-uri-to-path": "1.0.0" + } + }, + "node_modules/bitwise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/bitwise/-/bitwise-2.1.0.tgz", + "integrity": "sha512-XKgAhMXCh4H/3oNwAHAsAO0iC89s9cOiumgYwSHjSobGWxYjv62YhkL9QEdvGP151xypCtMlAfKK79GEcd2eRQ==" + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/bl/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/buffer": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz", + "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==", + "dependencies": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + }, + "node_modules/buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" + }, + "node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, + "node_modules/code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/commist": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/commist/-/commist-1.1.0.tgz", + "integrity": "sha512-rraC8NXWOEjhADbZe9QBNzLAN5Q3fsTPQtBV+fEVj6xKIgDgNiEVE6ZNfHpZOqfQ21YUzfVNUXLOEZquYvQPPg==", + "dependencies": { + "leven": "^2.1.0", + "minimist": "^1.1.0" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "node_modules/concat-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", + "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", + "engines": [ + "node >= 6.0" + ], + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.0.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/concat-stream/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" + }, + "node_modules/core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "node_modules/crc": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/crc/-/crc-3.4.0.tgz", + "integrity": "sha512-ycVC2+4/DLgXXq7QweYi2znhqDuZz6P5TQXnkQo8v15XY/5p/IWeZwsSE31Ifo8w15b8TWLsqhXOjXyilHuQxw==" + }, + "node_modules/date-format": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.11.tgz", + "integrity": "sha512-VS20KRyorrbMCQmpdl2hg5KaOUsda1RbnsJg461FfrcyCUg+pkd0b40BSW4niQyTheww4DBXQnS7HwSrKkipLw==", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" + }, + "node_modules/detect-libc": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz", + "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==", + "engines": { + "node": ">=8" + } + }, + "node_modules/duplexify": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.2.tgz", + "integrity": "sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw==", + "dependencies": { + "end-of-stream": "^1.4.1", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1", + "stream-shift": "^1.0.0" + } + }, + "node_modules/duplexify/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/easy-crc": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/easy-crc/-/easy-crc-0.0.2.tgz", + "integrity": "sha512-h6eqIdhJRe0p271/xZJbM/0klCi13mW5IB7ZEzEGH11yV4QXWAkD4yPErz0fXdhFrd6sZ4Q1k5Iky2kMsMNePw==" + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" + }, + "node_modules/flatted": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", + "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==" + }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, + "node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "node_modules/gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha512-14x4kjc6lkD3ltw589k0NrPD6cCNTD6CWoVUNpB85+DrtONoZn+Rug6xZU5RvSC4+TZPxA5AnBibQYAvZn41Hg==", + "dependencies": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "node_modules/github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==" + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" + }, + "node_modules/has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" + }, + "node_modules/help-me": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/help-me/-/help-me-3.0.0.tgz", + "integrity": "sha512-hx73jClhyk910sidBB7ERlnhMlFsJJIBqSVMFDwPN8o2v9nmp5KgLq1Xz1Bf1fCMMZ6mPrX159iG0VLy/fPMtQ==", + "dependencies": { + "glob": "^7.1.6", + "readable-stream": "^3.6.0" + } + }, + "node_modules/help-me/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, + "node_modules/is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==", + "dependencies": { + "number-is-nan": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "node_modules/js-sdsl": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz", + "integrity": "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/js-sdsl" + } + }, + "node_modules/jsmodbus": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/jsmodbus/-/jsmodbus-4.0.6.tgz", + "integrity": "sha512-gCmjoaERErK5Rn9Lu/BN07fY13MoWV7JKgGzrnkPlQPdPxYcwDhLtYcmpFFpZ4J9NPZZBSezi1UkLZO/DnNppA==", + "dependencies": { + "crc": "3.4.0", + "debug": "^3.1.0" + }, + "bin": { + "jsmodbus": "bin/jsmodbus.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/jsmodbus/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/leven": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", + "integrity": "sha1-wuep93IJTe6dNCAq6KzORoeHVYA=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/log4js": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.5.2.tgz", + "integrity": "sha512-DXtpNtt+KDOMT7RHUDIur/WsSA3rntlUh9Zg4XCdV42wUuMmbFkl38+LZ92Z5QvQA7mD5kAVkLiBSEH/tvUB8A==", + "dependencies": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "flatted": "^3.2.5", + "rfdc": "^1.3.0", + "streamroller": "^3.1.1" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" + }, + "node_modules/mqtt": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/mqtt/-/mqtt-4.3.7.tgz", + "integrity": "sha512-ew3qwG/TJRorTz47eW46vZ5oBw5MEYbQZVaEji44j5lAUSQSqIEoul7Kua/BatBW0H0kKQcC9kwUHa1qzaWHSw==", + "dependencies": { + "commist": "^1.0.0", + "concat-stream": "^2.0.0", + "debug": "^4.1.1", + "duplexify": "^4.1.1", + "help-me": "^3.0.0", + "inherits": "^2.0.3", + "lru-cache": "^6.0.0", + "minimist": "^1.2.5", + "mqtt-packet": "^6.8.0", + "number-allocator": "^1.0.9", + "pump": "^3.0.0", + "readable-stream": "^3.6.0", + "reinterval": "^1.1.0", + "rfdc": "^1.3.0", + "split2": "^3.1.0", + "ws": "^7.5.5", + "xtend": "^4.0.2" + }, + "bin": { + "mqtt": "bin/mqtt.js", + "mqtt_pub": "bin/pub.js", + "mqtt_sub": "bin/sub.js" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/mqtt-packet": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/mqtt-packet/-/mqtt-packet-6.10.0.tgz", + "integrity": "sha512-ja8+mFKIHdB1Tpl6vac+sktqy3gA8t9Mduom1BA75cI+R9AHnZOiaBQwpGiWnaVJLDGRdNhQmFaAqd7tkKSMGA==", + "dependencies": { + "bl": "^4.0.2", + "debug": "^4.1.1", + "process-nextick-args": "^2.0.1" + } + }, + "node_modules/mqtt/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/nan": { + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.16.0.tgz", + "integrity": "sha512-UdAqHyFngu7TfQKsCBgAA6pWDkT8MAO7d0jyOecVhN5354xbLqdn8mV9Tat9gepAupm0bt2DbeaSC8vS52MuFA==" + }, + "node_modules/napi-build-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", + "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==" + }, + "node_modules/node-abi": { + "version": "3.22.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.22.0.tgz", + "integrity": "sha512-u4uAs/4Zzmp/jjsD9cyFYDXeISfUWaAVWshPmDZOFOv4Xl4SbzTXm53I04C2uRueYJ+0t5PEtLH/owbn2Npf/w==", + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/nodemailer": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.7.tgz", + "integrity": "sha512-rUtR77ksqex/eZRLmQ21LKVH5nAAsVicAtAYudK7JgwenEDZ0UIQ1adUGqErz7sMkWYxWTTU1aeP2Jga6WQyJw==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "dependencies": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "node_modules/number-allocator": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/number-allocator/-/number-allocator-1.0.14.tgz", + "integrity": "sha512-OrL44UTVAvkKdOdRQZIJpLkAdjXGTRda052sN4sO77bKEzYYqWKMBjQvrJFzqygI99gL6Z4u2xctPW1tB8ErvA==", + "dependencies": { + "debug": "^4.3.1", + "js-sdsl": "4.3.0" + } + }, + "node_modules/number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/prebuild-install": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.0.tgz", + "integrity": "sha512-CNcMgI1xBypOyGqjp3wOc8AAo1nMhZS3Cwd3iHIxOdAUbb+YxdNuM4Z5iIrZ8RLvOsf3F3bl7b7xGq6DjQoNYA==", + "dependencies": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^1.0.1", + "node-abi": "^3.3.0", + "npmlog": "^4.0.1", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + }, + "bin": { + "prebuild-install": "bin.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/reinterval": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reinterval/-/reinterval-1.1.0.tgz", + "integrity": "sha1-M2Hs+jymwYKDOA3Qu5VG85D17Oc=" + }, + "node_modules/rfdc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==" + }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/serialport": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/serialport/-/serialport-9.2.8.tgz", + "integrity": "sha512-FsWpMQgSJxi93JgWl5xM1f9/Z8IjRJuaUEoHqLf8FPBLw7gMhInuHOBhI2onQufWIYPGTz3H3oGcu1nCaK1EfA==", + "dependencies": { + "@serialport/binding-mock": "9.2.4", + "@serialport/bindings": "9.2.8", + "@serialport/parser-byte-length": "9.2.4", + "@serialport/parser-cctalk": "9.2.4", + "@serialport/parser-delimiter": "9.2.4", + "@serialport/parser-inter-byte-timeout": "9.2.4", + "@serialport/parser-readline": "9.2.4", + "@serialport/parser-ready": "9.2.4", + "@serialport/parser-regex": "9.2.4", + "@serialport/stream": "9.2.4", + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "node_modules/split2": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", + "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", + "dependencies": { + "readable-stream": "^3.0.0" + } + }, + "node_modules/split2/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==" + }, + "node_modules/streamroller": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.1.1.tgz", + "integrity": "sha512-iPhtd9unZ6zKdWgMeYGfSBuqCngyJy1B/GPi/lTpwGpa3bajuX30GjUVd0/Tn/Xhg0mr4DOSENozz9Y06qyonQ==", + "dependencies": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "fs-extra": "^10.1.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dependencies": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/tar-fs": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "dependencies": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tar-stream/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/total.js": { + "version": "3.4.13", + "resolved": "https://registry.npmjs.org/total.js/-/total.js-3.4.13.tgz", + "integrity": "sha512-lAH4gEixlPFbrE3xfKADAcHfO79IFq2wKa9GTsrgRzIR5MTg3mNH7+4IxvX1pK8faoYb/0oYSJ1YTsAa5hIFFQ==", + "bin": { + "total": "bin/totaljs", + "total.js": "bin/totaljs", + "totaljs": "bin/totaljs", + "totalpackage": "bin/tpm", + "tpm": "bin/tpm" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, + "node_modules/universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "node_modules/wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "node_modules/ws": { + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } + }, + "dependencies": { + "@serialport/binding-abstract": { + "version": "9.2.3", + "resolved": "https://registry.npmjs.org/@serialport/binding-abstract/-/binding-abstract-9.2.3.tgz", + "integrity": "sha512-cQs9tbIlG3P0IrOWyVirqlhWuJ7Ms2Zh9m2108z6Y5UW/iVj6wEOiW8EmK9QX9jmJXYllE7wgGgvVozP5oCj3w==", + "requires": { + "debug": "^4.3.2" + } + }, + "@serialport/binding-mock": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/binding-mock/-/binding-mock-9.2.4.tgz", + "integrity": "sha512-dpEhACCs44oQhh6ajJfJdvQdK38Vq0N4W6iD/gdplglDCK7qXRQCMUjJIeKdS/HSEiWkC3bwumUhUufdsOyT4g==", + "requires": { + "@serialport/binding-abstract": "9.2.3", + "debug": "^4.3.2" + } + }, + "@serialport/bindings": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/@serialport/bindings/-/bindings-9.2.8.tgz", + "integrity": "sha512-hSLxTe0tADZ3LMMGwvEJWOC/TaFQTyPeFalUCsJ1lSQ0k6bPF04JwrtB/C81GetmDBTNRY0GlD0SNtKCc7Dr5g==", + "requires": { + "@serialport/binding-abstract": "9.2.3", + "@serialport/parser-readline": "9.2.4", + "bindings": "^1.5.0", + "debug": "^4.3.2", + "nan": "^2.15.0", + "prebuild-install": "^7.0.0" + } + }, + "@serialport/parser-byte-length": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-byte-length/-/parser-byte-length-9.2.4.tgz", + "integrity": "sha512-sQD/iw4ZMU3xW9PLi0/GlvU6Y623jGeWecbMkO7izUo/6P7gtfv1c9ikd5h0kwL8AoAOpQA1lxdHIKox+umBUg==" + }, + "@serialport/parser-cctalk": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-cctalk/-/parser-cctalk-9.2.4.tgz", + "integrity": "sha512-T4TU5vQMwmo9AB3gQLFDWbfJXlW5jd9guEsB/nqKjFHTv0FXPdZ7DQ2TpSp8RnHWxU3GX6kYTaDO20BKzc8GPQ==" + }, + "@serialport/parser-delimiter": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-delimiter/-/parser-delimiter-9.2.4.tgz", + "integrity": "sha512-4nvTAoYAgkxFiXrkI+3CA49Yd43CODjeszh89EK+I9c8wOZ+etZduRCzINYPiy26g7zO+GRAb9FoPCsY+sYcbQ==" + }, + "@serialport/parser-inter-byte-timeout": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-inter-byte-timeout/-/parser-inter-byte-timeout-9.2.4.tgz", + "integrity": "sha512-SOAdvr0oBQIOCXX198hiTlxs4JTKg9j5piapw5tNq52fwDOWdbYrFneT/wN04UTMKaDrJuEvXq6T4rv4j7nJ5A==" + }, + "@serialport/parser-readline": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-readline/-/parser-readline-9.2.4.tgz", + "integrity": "sha512-Z1/qrZTQUVhNSJP1hd9YfDvq0o7d87rNwAjjRKbVpa7Qi51tG5BnKt43IV3NFMyBlVcRe0rnIb3tJu57E0SOwg==", + "requires": { + "@serialport/parser-delimiter": "9.2.4" + } + }, + "@serialport/parser-ready": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-ready/-/parser-ready-9.2.4.tgz", + "integrity": "sha512-Pyi94Itjl6qAURwIZr/gmZpMAyTmKXThm6vL5DoAWGQjcRHWB0gwv2TY2v7N+mQLJYUKU3cMnvnATXxHm7xjxw==" + }, + "@serialport/parser-regex": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-regex/-/parser-regex-9.2.4.tgz", + "integrity": "sha512-sI/cVvPOYz+Dbv4ZdnW16qAwvXiFf/1pGASQdbveRTlgJDdz7sRNlCBifzfTN2xljwvCTZYqiudKvDdC1TepRQ==" + }, + "@serialport/stream": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/stream/-/stream-9.2.4.tgz", + "integrity": "sha512-bLye8Ub4vUFQGmkh8qEqehr7SE7EJs2yDs0h9jzuL5oKi+F34CFmWkEErO8GAOQ8YNn7p6b3GxUgs+0BrHHDZQ==", + "requires": { + "debug": "^4.3.2" + } + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==" + }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "are-we-there-yet": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", + "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "base64-js": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", + "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==" + }, + "bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "requires": { + "file-uri-to-path": "1.0.0" + } + }, + "bitwise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/bitwise/-/bitwise-2.1.0.tgz", + "integrity": "sha512-XKgAhMXCh4H/3oNwAHAsAO0iC89s9cOiumgYwSHjSobGWxYjv62YhkL9QEdvGP151xypCtMlAfKK79GEcd2eRQ==" + }, + "bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "requires": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "buffer": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz", + "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==", + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" + }, + "chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==" + }, + "commist": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/commist/-/commist-1.1.0.tgz", + "integrity": "sha512-rraC8NXWOEjhADbZe9QBNzLAN5Q3fsTPQtBV+fEVj6xKIgDgNiEVE6ZNfHpZOqfQ21YUzfVNUXLOEZquYvQPPg==", + "requires": { + "leven": "^2.1.0", + "minimist": "^1.1.0" + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "concat-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", + "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.0.2", + "typedarray": "^0.0.6" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "crc": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/crc/-/crc-3.4.0.tgz", + "integrity": "sha512-ycVC2+4/DLgXXq7QweYi2znhqDuZz6P5TQXnkQo8v15XY/5p/IWeZwsSE31Ifo8w15b8TWLsqhXOjXyilHuQxw==" + }, + "date-format": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.11.tgz", + "integrity": "sha512-VS20KRyorrbMCQmpdl2hg5KaOUsda1RbnsJg461FfrcyCUg+pkd0b40BSW4niQyTheww4DBXQnS7HwSrKkipLw==" + }, + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "requires": { + "ms": "2.1.2" + } + }, + "decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "requires": { + "mimic-response": "^3.1.0" + } + }, + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==" + }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" + }, + "detect-libc": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz", + "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==" + }, + "duplexify": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.2.tgz", + "integrity": "sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw==", + "requires": { + "end-of-stream": "^1.4.1", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1", + "stream-shift": "^1.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "easy-crc": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/easy-crc/-/easy-crc-0.0.2.tgz", + "integrity": "sha512-h6eqIdhJRe0p271/xZJbM/0klCi13mW5IB7ZEzEGH11yV4QXWAkD4yPErz0fXdhFrd6sZ4Q1k5Iky2kMsMNePw==" + }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "requires": { + "once": "^1.4.0" + } + }, + "expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==" + }, + "file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" + }, + "flatted": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", + "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==" + }, + "fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, + "fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha512-14x4kjc6lkD3ltw589k0NrPD6cCNTD6CWoVUNpB85+DrtONoZn+Rug6xZU5RvSC4+TZPxA5AnBibQYAvZn41Hg==", + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==" + }, + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" + }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" + }, + "help-me": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/help-me/-/help-me-3.0.0.tgz", + "integrity": "sha512-hx73jClhyk910sidBB7ERlnhMlFsJJIBqSVMFDwPN8o2v9nmp5KgLq1Xz1Bf1fCMMZ6mPrX159iG0VLy/fPMtQ==", + "requires": { + "glob": "^7.1.6", + "readable-stream": "^3.6.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==", + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "js-sdsl": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz", + "integrity": "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==" + }, + "jsmodbus": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/jsmodbus/-/jsmodbus-4.0.6.tgz", + "integrity": "sha512-gCmjoaERErK5Rn9Lu/BN07fY13MoWV7JKgGzrnkPlQPdPxYcwDhLtYcmpFFpZ4J9NPZZBSezi1UkLZO/DnNppA==", + "requires": { + "crc": "3.4.0", + "debug": "^3.1.0" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "requires": { + "ms": "^2.1.1" + } + } + } + }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, + "leven": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", + "integrity": "sha1-wuep93IJTe6dNCAq6KzORoeHVYA=" + }, + "log4js": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.5.2.tgz", + "integrity": "sha512-DXtpNtt+KDOMT7RHUDIur/WsSA3rntlUh9Zg4XCdV42wUuMmbFkl38+LZ92Z5QvQA7mD5kAVkLiBSEH/tvUB8A==", + "requires": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "flatted": "^3.2.5", + "rfdc": "^1.3.0", + "streamroller": "^3.1.1" + } + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "requires": { + "yallist": "^4.0.0" + } + }, + "mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==" + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==" + }, + "mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" + }, + "mqtt": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/mqtt/-/mqtt-4.3.7.tgz", + "integrity": "sha512-ew3qwG/TJRorTz47eW46vZ5oBw5MEYbQZVaEji44j5lAUSQSqIEoul7Kua/BatBW0H0kKQcC9kwUHa1qzaWHSw==", + "requires": { + "commist": "^1.0.0", + "concat-stream": "^2.0.0", + "debug": "^4.1.1", + "duplexify": "^4.1.1", + "help-me": "^3.0.0", + "inherits": "^2.0.3", + "lru-cache": "^6.0.0", + "minimist": "^1.2.5", + "mqtt-packet": "^6.8.0", + "number-allocator": "^1.0.9", + "pump": "^3.0.0", + "readable-stream": "^3.6.0", + "reinterval": "^1.1.0", + "rfdc": "^1.3.0", + "split2": "^3.1.0", + "ws": "^7.5.5", + "xtend": "^4.0.2" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "mqtt-packet": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/mqtt-packet/-/mqtt-packet-6.10.0.tgz", + "integrity": "sha512-ja8+mFKIHdB1Tpl6vac+sktqy3gA8t9Mduom1BA75cI+R9AHnZOiaBQwpGiWnaVJLDGRdNhQmFaAqd7tkKSMGA==", + "requires": { + "bl": "^4.0.2", + "debug": "^4.1.1", + "process-nextick-args": "^2.0.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "nan": { + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.16.0.tgz", + "integrity": "sha512-UdAqHyFngu7TfQKsCBgAA6pWDkT8MAO7d0jyOecVhN5354xbLqdn8mV9Tat9gepAupm0bt2DbeaSC8vS52MuFA==" + }, + "napi-build-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", + "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==" + }, + "node-abi": { + "version": "3.22.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.22.0.tgz", + "integrity": "sha512-u4uAs/4Zzmp/jjsD9cyFYDXeISfUWaAVWshPmDZOFOv4Xl4SbzTXm53I04C2uRueYJ+0t5PEtLH/owbn2Npf/w==", + "requires": { + "semver": "^7.3.5" + } + }, + "nodemailer": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.7.tgz", + "integrity": "sha512-rUtR77ksqex/eZRLmQ21LKVH5nAAsVicAtAYudK7JgwenEDZ0UIQ1adUGqErz7sMkWYxWTTU1aeP2Jga6WQyJw==" + }, + "npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "number-allocator": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/number-allocator/-/number-allocator-1.0.14.tgz", + "integrity": "sha512-OrL44UTVAvkKdOdRQZIJpLkAdjXGTRda052sN4sO77bKEzYYqWKMBjQvrJFzqygI99gL6Z4u2xctPW1tB8ErvA==", + "requires": { + "debug": "^4.3.1", + "js-sdsl": "4.3.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==" + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==" + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==" + }, + "prebuild-install": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.0.tgz", + "integrity": "sha512-CNcMgI1xBypOyGqjp3wOc8AAo1nMhZS3Cwd3iHIxOdAUbb+YxdNuM4Z5iIrZ8RLvOsf3F3bl7b7xGq6DjQoNYA==", + "requires": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^1.0.1", + "node-abi": "^3.3.0", + "npmlog": "^4.0.1", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + } + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + } + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "reinterval": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reinterval/-/reinterval-1.1.0.tgz", + "integrity": "sha1-M2Hs+jymwYKDOA3Qu5VG85D17Oc=" + }, + "rfdc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==" + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "requires": { + "lru-cache": "^6.0.0" + } + }, + "serialport": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/serialport/-/serialport-9.2.8.tgz", + "integrity": "sha512-FsWpMQgSJxi93JgWl5xM1f9/Z8IjRJuaUEoHqLf8FPBLw7gMhInuHOBhI2onQufWIYPGTz3H3oGcu1nCaK1EfA==", + "requires": { + "@serialport/binding-mock": "9.2.4", + "@serialport/bindings": "9.2.8", + "@serialport/parser-byte-length": "9.2.4", + "@serialport/parser-cctalk": "9.2.4", + "@serialport/parser-delimiter": "9.2.4", + "@serialport/parser-inter-byte-timeout": "9.2.4", + "@serialport/parser-readline": "9.2.4", + "@serialport/parser-ready": "9.2.4", + "@serialport/parser-regex": "9.2.4", + "@serialport/stream": "9.2.4", + "debug": "^4.3.2" + } + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==" + }, + "simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "requires": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "split2": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", + "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", + "requires": { + "readable-stream": "^3.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==" + }, + "streamroller": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.1.1.tgz", + "integrity": "sha512-iPhtd9unZ6zKdWgMeYGfSBuqCngyJy1B/GPi/lTpwGpa3bajuX30GjUVd0/Tn/Xhg0mr4DOSENozz9Y06qyonQ==", + "requires": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "fs-extra": "^10.1.0" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" + }, + "tar-fs": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "requires": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "requires": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "total.js": { + "version": "3.4.13", + "resolved": "https://registry.npmjs.org/total.js/-/total.js-3.4.13.tgz", + "integrity": "sha512-lAH4gEixlPFbrE3xfKADAcHfO79IFq2wKa9GTsrgRzIR5MTg3mNH7+4IxvX1pK8faoYb/0oYSJ1YTsAa5hIFFQ==" + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, + "universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==" + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "requires": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "ws": { + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "requires": {} + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } + } +} diff --git a/RVO48/package.json b/RVO48/package.json new file mode 100755 index 0000000..e524d7c --- /dev/null +++ b/RVO48/package.json @@ -0,0 +1,29 @@ +{ + "name": "emptyproject", + "description": "Total.js empty project.", + "version": "1.0.0", + "main": "debug.js", + "dependencies": { + "bitwise": "^2.1.0", + "easy-crc": "0.0.2", + "jsmodbus": "^4.0.6", + "log4js": "^6.3.0", + "mqtt": "^4.2.6", + "nodemailer": "^6.9.7", + "serialport": "^9.2.8", + "total.js": "^3.4.13" + }, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "https://github.com/totaljs/emptyproject-flow" + }, + "keywords": [ + "empty", + "project" + ], + "author": "Peter Širka", + "license": "MIT" +} diff --git a/RVO48/release.js b/RVO48/release.js new file mode 100755 index 0000000..02d52ff --- /dev/null +++ b/RVO48/release.js @@ -0,0 +1,15 @@ +// =================================================== +// FOR PRODUCTION +// Total.js - framework for Node.js platform +// https://www.totaljs.com +// =================================================== + +const options = {'ip':'0.0.0.0', 'port':12345}; + +// options.ip = '127.0.0.1'; +// options.port = parseInt(process.argv[2]); +// options.config = { name: 'Total.js' }; +// options.sleep = 3000; + +require('total.js').http('release', options); +// require('total.js').cluster.http(5, 'release', options); diff --git a/RVO48/release.js.json b/RVO48/release.js.json new file mode 100755 index 0000000..934b2ec --- /dev/null +++ b/RVO48/release.js.json @@ -0,0 +1,34 @@ +{ + "pid": 386, + "stats": [ + { + "id": null, + "version": { + "node": "v14.18.1", + "total": "3.4.13", + "app": "1.0.0" + }, + "pid": 386, + "thread": "", + "mode": "release", + "overload": 0, + "date": "2025-10-16T00:26:31.372Z", + "memory": 22.01, + "rm": 0, + "fm": 0, + "wm": 0, + "mm": 0, + "om": 2, + "em": 0, + "dbrm": 0, + "dbwm": 0, + "usage": 0, + "requests": 0, + "pending": 0, + "errors": 0, + "timeouts": 0, + "uptime": 730, + "online": 0 + } + ] +} \ No newline at end of file diff --git a/RVO48/report_data.log b/RVO48/report_data.log new file mode 100755 index 0000000..db24e64 --- /dev/null +++ b/RVO48/report_data.log @@ -0,0 +1,195 @@ +{ + "name": "rvo_senica_48_10.0.0.135", + "time": "2025-10-15T13:17:46.356Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_48_10.0.0.135", + "time": "2025-10-15T14:17:46.355Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_48_10.0.0.135", + "time": "2025-10-15T15:17:46.354Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_48_10.0.0.135", + "time": "2025-10-15T16:17:46.355Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_48_10.0.0.135", + "time": "2025-10-15T17:17:46.355Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_48_10.0.0.135", + "time": "2025-10-15T18:17:46.356Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [ + "48/17_1L_4043_NEMA" + ], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_48_10.0.0.135", + "time": "2025-10-15T19:17:46.355Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [ + "48/17_1L_4043_NEMA" + ], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_48_10.0.0.135", + "time": "2025-10-15T20:17:46.356Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [ + "48/17_1L_4043_NEMA" + ], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_48_10.0.0.135", + "time": "2025-10-15T21:17:46.355Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [ + "48/17_1L_4043_NEMA" + ], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_48_10.0.0.135", + "time": "2025-10-15T22:17:46.356Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [ + "48/17_1L_4043_NEMA" + ], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_48_10.0.0.135", + "time": "2025-10-15T23:17:46.355Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [ + "48/17_1L_4043_NEMA" + ], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_48_10.0.0.135", + "time": "2025-10-16T00:17:46.356Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [ + "48/17_1L_4043_NEMA" + ], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +} \ No newline at end of file From daa362b8aae68b3e9eb6e5cb55bf39521f3ca0a5 Mon Sep 17 00:00:00 2001 From: Jakub Klena Date: Thu, 16 Oct 2025 02:27:40 +0200 Subject: [PATCH 29/30] Backup senica-RVO50 on 16.10.2025 --- RVO50/addSwitch.py | 36 + RVO50/cloud_topic.py | 76 + RVO50/config | 12 + RVO50/createNode.py | 43 + RVO50/databases/accelerometer_db.js | 3055 ++++++++++++++++ RVO50/databases/modbus_config.js | 114 + RVO50/databases/nodes.table | 27 + .../nodes_original/nodes_original.table | 1 + RVO50/databases/notifications.table | 41 + RVO50/databases/pins.table | 14 + RVO50/databases/relays.table | 5 + RVO50/databases/settings.table | 2 + RVO50/databases/tbdata.nosql | 4 + RVO50/databases/tbdatacloud.nosql | 3 + RVO50/databases/total_energy.js | 38 + RVO50/debug.js | 16 + RVO50/err.txt | 39 + RVO50/flow/cloudmqttconnect.js | 357 ++ RVO50/flow/cmd_manager.js | 3071 ++++++++++++++++ RVO50/flow/code.js | 90 + RVO50/flow/comment.js | 11 + RVO50/flow/count.js | 60 + RVO50/flow/db_connector.js | 286 ++ RVO50/flow/db_init.js | 113 + RVO50/flow/debug.js | 100 + RVO50/flow/designer.json | 3102 +++++++++++++++++ RVO50/flow/dido_controller.js | 1486 ++++++++ RVO50/flow/helper/DataToTbHandler.js | 187 + RVO50/flow/helper/ErrorToServiceHandler.js | 91 + RVO50/flow/helper/db_helper.js | 44 + RVO50/flow/helper/logger.js | 30 + RVO50/flow/helper/md5.js | 5 + RVO50/flow/helper/notification_reporter.js | 121 + RVO50/flow/helper/register.js | 144 + RVO50/flow/helper/serialport_helper.js | 99 + RVO50/flow/helper/suncalc.js | 317 ++ RVO50/flow/helper/utils.js | 161 + RVO50/flow/httprequest.js | 137 + RVO50/flow/httpresponse.js | 76 + RVO50/flow/httproute.js | 326 ++ RVO50/flow/infosender.js | 81 + RVO50/flow/modbus_reader.js | 346 ++ RVO50/flow/monitorconsumption.js | 156 + RVO50/flow/monitordisk.js | 96 + RVO50/flow/monitormemory.js | 87 + RVO50/flow/nodesdb_changecheck.js | 77 + RVO50/flow/show_dbdata.js | 243 ++ RVO50/flow/slack_filter.js | 188 + RVO50/flow/thermometer.js | 99 + RVO50/flow/trigger.js | 79 + RVO50/flow/variables.txt | 0 RVO50/flow/virtualwirein.js | 43 + RVO50/flow/virtualwireout.js | 41 + RVO50/flow/wsmqttpublish.js | 448 +++ RVO50/monitor.txt | 506 +++ RVO50/package-lock.json | 2125 +++++++++++ RVO50/package.json | 29 + RVO50/release.js | 15 + RVO50/release.js.json | 34 + RVO50/report_data.log | 166 + 60 files changed, 18799 insertions(+) create mode 100755 RVO50/addSwitch.py create mode 100755 RVO50/cloud_topic.py create mode 100755 RVO50/config create mode 100755 RVO50/createNode.py create mode 100755 RVO50/databases/accelerometer_db.js create mode 100755 RVO50/databases/modbus_config.js create mode 100755 RVO50/databases/nodes.table create mode 100755 RVO50/databases/nodes_original/nodes_original.table create mode 100755 RVO50/databases/notifications.table create mode 100755 RVO50/databases/pins.table create mode 100755 RVO50/databases/relays.table create mode 100755 RVO50/databases/settings.table create mode 100755 RVO50/databases/tbdata.nosql create mode 100755 RVO50/databases/tbdatacloud.nosql create mode 100755 RVO50/databases/total_energy.js create mode 100755 RVO50/debug.js create mode 100755 RVO50/err.txt create mode 100755 RVO50/flow/cloudmqttconnect.js create mode 100755 RVO50/flow/cmd_manager.js create mode 100755 RVO50/flow/code.js create mode 100755 RVO50/flow/comment.js create mode 100755 RVO50/flow/count.js create mode 100755 RVO50/flow/db_connector.js create mode 100755 RVO50/flow/db_init.js create mode 100755 RVO50/flow/debug.js create mode 100755 RVO50/flow/designer.json create mode 100755 RVO50/flow/dido_controller.js create mode 100755 RVO50/flow/helper/DataToTbHandler.js create mode 100755 RVO50/flow/helper/ErrorToServiceHandler.js create mode 100755 RVO50/flow/helper/db_helper.js create mode 100755 RVO50/flow/helper/logger.js create mode 100755 RVO50/flow/helper/md5.js create mode 100755 RVO50/flow/helper/notification_reporter.js create mode 100755 RVO50/flow/helper/register.js create mode 100755 RVO50/flow/helper/serialport_helper.js create mode 100755 RVO50/flow/helper/suncalc.js create mode 100755 RVO50/flow/helper/utils.js create mode 100755 RVO50/flow/httprequest.js create mode 100755 RVO50/flow/httpresponse.js create mode 100755 RVO50/flow/httproute.js create mode 100755 RVO50/flow/infosender.js create mode 100755 RVO50/flow/modbus_reader.js create mode 100755 RVO50/flow/monitorconsumption.js create mode 100755 RVO50/flow/monitordisk.js create mode 100755 RVO50/flow/monitormemory.js create mode 100755 RVO50/flow/nodesdb_changecheck.js create mode 100755 RVO50/flow/show_dbdata.js create mode 100755 RVO50/flow/slack_filter.js create mode 100755 RVO50/flow/thermometer.js create mode 100755 RVO50/flow/trigger.js create mode 100755 RVO50/flow/variables.txt create mode 100755 RVO50/flow/virtualwirein.js create mode 100755 RVO50/flow/virtualwireout.js create mode 100755 RVO50/flow/wsmqttpublish.js create mode 100755 RVO50/monitor.txt create mode 100755 RVO50/package-lock.json create mode 100755 RVO50/package.json create mode 100755 RVO50/release.js create mode 100755 RVO50/release.js.json create mode 100755 RVO50/report_data.log diff --git a/RVO50/addSwitch.py b/RVO50/addSwitch.py new file mode 100755 index 0000000..c35e96b --- /dev/null +++ b/RVO50/addSwitch.py @@ -0,0 +1,36 @@ +import os + +def process_set_file(): + """ + Checks if /root/flowserver exists, reads set.txt, and modifies the second line. + """ + default_folder = "/root/flowserver" if os.path.exists("/root/flowserver") else "/home/unipi/flowserver" + flag = 1 if default_folder == "/root/flowserver" else 0 + + try: + with open("/home/unipi/flowserver/databases/settings.table", "r") as f: + lines = f.readlines() + + if len(lines) >= 2: + lines[0] = lines[0].rstrip('\n') + "|main_switch:boolean\n" + second_line = lines[1].strip() # remove trailing newline + last_pipe_index = second_line.rfind("|") + + if last_pipe_index != -1: + modified_line = second_line[:last_pipe_index + 1] + str(flag) + "|" + second_line[last_pipe_index + 1:] + lines[1] = modified_line + else: + print("Warning: No '|' character found in the second line of set.txt") + + with open("/home/unipi/flowserver/databases/settings.table", "w") as f: + f.writelines(lines) + else: + print("Warning: settings.table has less than two lines.") + + except FileNotFoundError: + print("Error: settings.table not found.") + except Exception as e: + print(e) + +# if __name__ == "__main__": +process_set_file() diff --git a/RVO50/cloud_topic.py b/RVO50/cloud_topic.py new file mode 100755 index 0000000..77c31f1 --- /dev/null +++ b/RVO50/cloud_topic.py @@ -0,0 +1,76 @@ +# import os +# +# def modify_file(file_path): +# """ +# Modifies the given file by: +# 1. Appending "|cloud_topic" to the first line. +# 2. Inserting the text from the third "." to the first "|" on the second line after the last "|" character. +# +# Args: +# file_path (str): The path to the file to be modified. +# """ +# +# with open(file_path, 'r+') as f: +# lines = f.readlines() +# +# # Modify the first line +# lines[0] += "|cloud_topic:string" +# +# # Modify the second line +# second_line = lines[1].strip() # Remove leading/trailing whitespace +# first_pipe_index = second_line.find('|') +# third_dot_index = second_line.find('.', second_line.find('.', second_line.find('.') + 1) + 1) +# text_to_insert = second_line[third_dot_index:first_pipe_index] +# +# last_pipe_index = second_line.rfind('|') +# lines[1] = second_line[:last_pipe_index + 1] + text_to_insert + "|" + second_line[last_pipe_index + 1:] +# +# print(first_pipe_index, third_dot_index, text_to_insert, last_pipe_index) +# # Write the modified lines back to the file +# # f.seek(0) +# # f.writelines(lines) +# # f.truncate() +# +# # Example usage: +# file_path = "settings.table" # Replace with the actual file path +# modify_file(file_path) +# + + +def modify_file(file_path): + """ + Modifies the given file by: + 1. Appending "|cloud_topic" to the first line. + 2. Inserting the text between the third "." and the second "|" on the second line after the last "|" character. + + Args: + file_path (str): The path to the file to be modified. + """ + + with open(file_path, 'r+') as f: + lines = f.readlines() + + first_line = lines[0].strip() + first_line += "|cloud_topic:string\n" + # Modify the first line + lines[0] = first_line + + # Modify the second line + second_line = lines[1].strip() # Remove leading/trailing whitespace + first_pipe_index = second_line.find('|') + second_pipe_index = second_line.find('|', first_pipe_index + 1) + third_dot_index = second_line.find('.', second_line.find('.', second_line.find('.') + 1) + 1) + text_to_insert = "u" + second_line[third_dot_index+1:second_pipe_index] + + last_pipe_index = second_line.rfind('|') + lines[1] = second_line[:last_pipe_index + 1] + text_to_insert + "|" + second_line[last_pipe_index + 1:] + + print(first_pipe_index, third_dot_index, text_to_insert, last_pipe_index) + # Write the modified lines back to the file + f.seek(0) + f.writelines(lines) + f.truncate() + +# Example usage: +file_path = "/home/unipi/flowserver/databases/settings.table" # Replace with the actual file path +modify_file(file_path) diff --git a/RVO50/config b/RVO50/config new file mode 100755 index 0000000..cd0a8a9 --- /dev/null +++ b/RVO50/config @@ -0,0 +1,12 @@ +name : Total.js Flow +default_timezone : Europe/Bratislava + +// Packages settings +package#flow (Object) : { url: '/' } + + +table.relays : line:number|tbname:string|contactor:number|profile:string +table.nodes : node:number|pole_number:string|node_type:string|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|project_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|cloud_topic:string|has_main_switch:boolean|daily_report:boolean|send_changed_node_numbers:boolean +table.pins : pin:string|type:string|line:number +table.notifications : key:string|weight:string|sk:string|en:string diff --git a/RVO50/createNode.py b/RVO50/createNode.py new file mode 100755 index 0000000..a8cea91 --- /dev/null +++ b/RVO50/createNode.py @@ -0,0 +1,43 @@ +print("zaciname") +import re, json + +search_str = '|' +final = [] +counter = 1 +with open("/home/unipi/flowserver/databases/nodes.table", 'r') as file: +# with open("/home/rasta5man/dev/oms/flowserver/databases/nodes.table", 'r') as file: + # Read each line in the file + for line in file: + # Print each line + line = line.strip() + print(line) + if counter != 1: + i = [m.start() for m in re.finditer(re.escape(search_str), line)] + node = line[ i[0] + 1 : i[1] ] + tbname = line[ i[3] + 1 : i[4] ] + final.append({node:tbname}) + counter += 1 +print(json.dumps(final)) +f = open("/home/unipi/flowserver/databases/nodes_original/nodes_original.table", "w") +f.write(json.dumps(final)) +f.close() + + +# +# # ``d`` has to be replaced with a different character +# old_character = "'" +# +# # ``t`` will replace ``d` +# new_character = '"' +# resultant_string = 0; +# with open("/home/unipi/flowserver/databases/nodes_original/nodes_original.table", 'r') as file: +# for line in file: +# resultant_string = re.sub("'", '"', line) +# +# resultant_string = re.sub(" ", "", resultant_string) +# print(resultant_string) +# +# f = open("/home/unipi/flowserver/databases/nodes_original/nodes_original.table", "w") +# f.write(str(resultant_string)) +# f.close() +# diff --git a/RVO50/databases/accelerometer_db.js b/RVO50/databases/accelerometer_db.js new file mode 100755 index 0000000..fdfc7fd --- /dev/null +++ b/RVO50/databases/accelerometer_db.js @@ -0,0 +1,3055 @@ +let naklony = { + "3993": { "label": "1/3A", "naklon": 0 }, + "3989": { "label": "1/3B", "naklon": 15 }, + "3976": { "label": "1/1", "naklon": 0 }, + "4181": { "label": "1/2", "naklon": 0 }, + "4376": { "label": "1/4", "naklon": 15 }, + "3868": { "label": "1/5", "naklon": 15 }, + "3728": { "label": "1/6", "naklon": 15 }, + "3730": { "label": "1/7", "naklon": 0 }, + "4374": { "label": "1/8", "naklon": 0 }, + "3718": { "label": "1/9", "naklon": 15 }, + "4375": { "label": "1/10", "naklon": 15 }, + "4172": { "label": "1/11", "naklon": 15 }, + "4176": { "label": "1/12", "naklon": 15 }, + "3800": { "label": "2/1", "naklon": 5 }, + "3823": { "label": "2/2", "naklon": 5 }, + "3905": { "label": "2/3", "naklon": 5 }, + "3803": { "label": "2/4", "naklon": 5 }, + "3817": { "label": "2/5", "naklon": 5 }, + "3818": { "label": "2/6", "naklon": 5 }, + "3811": { "label": "2/7", "naklon": 5 }, + "3915": { "label": "2/8", "naklon": 5 }, + "3843": { "label": "2/9", "naklon": 10 }, + "3827": { "label": "2/10", "naklon": 10 }, + "4220": { "label": "2/11", "naklon": 10 }, + "3826": { "label": "2/12", "naklon": 10 }, + "3834": { "label": "2/13", "naklon": 10 }, + "3838": { "label": "2/14", "naklon": 10 }, + "2823": { "label": "2/15", "naklon": 10 }, + "3750": { "label": "2/16", "naklon": 10 }, + "3378": { "label": "2/17", "naklon": 0 }, + "3376": { "label": "2/18", "naklon": 0 }, + "3379": { "label": "2/19", "naklon": 0 }, + "3285": { "label": "2/20", "naklon": 0 }, + "3382": { "label": "2/21", "naklon": 0 }, + "3383": { "label": "2/22", "naklon": 0 }, + "3375": { "label": "2/24", "naklon": 0 }, + "3381": { "label": "2/25", "naklon": 0 }, + "3380": { "label": "2/26", "naklon": 0 }, + "3828": { "label": "2/27", "naklon": 10 }, + "3377": { "label": "2/28", "naklon": 0 }, + "3591": { "label": "7/1", "naklon": 0 }, + "3587": { "label": "7/2", "naklon": 0 }, + "3468": { "label": "7/3", "naklon": 0 }, + "3466": { "label": "7/4", "naklon": 0 }, + "3474": { "label": "7/5", "naklon": 0 }, + "3481": { "label": "7/6", "naklon": 0 }, + "3589": { "label": "7/7", "naklon": 0 }, + "3472": { "label": "7/8", "naklon": 0 }, + "3473": { "label": "7/9", "naklon": 0 }, + "3584": { "label": "7/10", "naklon": 0 }, + "3571": { "label": "7/11", "naklon": 0 }, + "3476": { "label": "7/12", "naklon": 0 }, + "3590": { "label": "7/13", "naklon": 0 }, + "3478": { "label": "7/14", "naklon": 0 }, + "3471": { "label": "7/15", "naklon": 0 }, + "3467": { "label": "7/16", "naklon": 0 }, + "3479": { "label": "7/17", "naklon": 0 }, + "3480": { "label": "7/18", "naklon": 0 }, + "3477": { "label": "7/19", "naklon": 0 }, + "3362": { "label": "12/1", "naklon": 0 }, + "3355": { "label": "12/2", "naklon": 0 }, + "3356": { "label": "12/3", "naklon": 0 }, + "3349": { "label": "12/4", "naklon": 0 }, + "3357": { "label": "12/5", "naklon": 0 }, + "3350": { "label": "12/6", "naklon": 0 }, + "3353": { "label": "12/7", "naklon": 0 }, + "3539": { "label": "12/8", "naklon": 0 }, + "3050": { "label": "12/9", "naklon": 0 }, + "3361": { "label": "12/10", "naklon": 0 }, + "3360": { "label": "12/11", "naklon": 0 }, + "3358": { "label": "12/12", "naklon": 0 }, + "3541": { "label": "12/13", "naklon": 0 }, + "3551": { "label": "12/14", "naklon": 0 }, + "3514": { "label": "12/15", "naklon": 0 }, + "3547": { "label": "12/16", "naklon": 0 }, + "3562": { "label": "12/17", "naklon": 0 }, + "3525": { "label": "12/18", "naklon": 0 }, + "3558": { "label": "12/19", "naklon": 0 }, + "3511": { "label": "12/20", "naklon": 0 }, + "3058": { "label": "12/21", "naklon": 0 }, + "3062": { "label": "12/22", "naklon": 0 }, + "3070": { "label": "12/23", "naklon": 0 }, + "3447": { "label": "12/24", "naklon": 0 }, + "3056": { "label": "12/25", "naklon": 0 }, + "3057": { "label": "12/26", "naklon": 0 }, + "3071": { "label": "12/27", "naklon": 0 }, + "3061": { "label": "12/28", "naklon": 0 }, + "3069": { "label": "12/29", "naklon": 0 }, + "3077": { "label": "12/30", "naklon": 0 }, + "3080": { "label": "12/31", "naklon": 0 }, + "3081": { "label": "12/32", "naklon": 0 }, + "3078": { "label": "12/33", "naklon": 0 }, + "4037": { "label": "12/34", "naklon": 0 }, + "3067": { "label": "12/35", "naklon": 0 }, + "3051": { "label": "12/36", "naklon": 0 }, + "2924": { "label": "12/37", "naklon": 0 }, + "3060": { "label": "12/38", "naklon": 0 }, + "3073": { "label": "12/39", "naklon": 0 }, + "3469": { "label": "12/40", "naklon": 0 }, + "2923": { "label": "12/41", "naklon": 0 }, + "2925": { "label": "12/42", "naklon": 0 }, + "3359": { "label": "12/43", "naklon": 0 }, + "3055": { "label": "12/44", "naklon": 0 }, + "2922": { "label": "12/45", "naklon": 0 }, + "3084": { "label": "12/46", "naklon": 0 }, + "3064": { "label": "12/47", "naklon": 0 }, + "3066": { "label": "12/48", "naklon": 0 }, + "3072": { "label": "12/49", "naklon": 0 }, + "3415": { "label": "13/13A", "naklon": 0 }, + "3409": { "label": "13/13B", "naklon": 0 }, + "3399": { "label": "13/13C", "naklon": 0 }, + "3410": { "label": "13/29A", "naklon": 0 }, + "3407": { "label": "13/29B", "naklon": 0 }, + "3405": { "label": "13/34A", "naklon": 0 }, + "3404": { "label": "13/34B", "naklon": 0 }, + "3392": { "label": "13/45A", "naklon": 0 }, + "3386": { "label": "13/45B", "naklon": 0 }, + "3303": { "label": "13/60A", "naklon": 3 }, + "3302": { "label": "13/60B", "naklon": 3 }, + "3319": { "label": "13/70A", "naklon": 6 }, + "3317": { "label": "13/70B", "naklon": 6 }, + "3326": { "label": "13/70C", "naklon": 6 }, + "3351": { "label": "13/73A", "naklon": 6 }, + "3313": { "label": "13/73B", "naklon": 6 }, + "3316": { "label": "13/83A", "naklon": 0 }, + "3320": { "label": "13/83B", "naklon": 0 }, + "3336": { "label": "13/95A", "naklon": 0 }, + "3323": { "label": "13/95B", "naklon": 0 }, + "3339": { "label": "13/98A", "naklon": 0 }, + "3333": { "label": "13/98B", "naklon": 0 }, + "3425": { "label": "13/1", "naklon": 0 }, + "3419": { "label": "13/2", "naklon": 0 }, + "3416": { "label": "13/3", "naklon": 0 }, + "3332": { "label": "13/4", "naklon": 0 }, + "3422": { "label": "13/5", "naklon": 0 }, + "3417": { "label": "13/6", "naklon": 0 }, + "3418": { "label": "13/7", "naklon": 0 }, + "3424": { "label": "13/8", "naklon": 0 }, + "3334": { "label": "13/9", "naklon": 0 }, + "4363": { "label": "13/10", "naklon": 0 }, + "3423": { "label": "13/11", "naklon": 0 }, + "3406": { "label": "13/12", "naklon": 0 }, + "3411": { "label": "13/14", "naklon": 0 }, + "3412": { "label": "13/15", "naklon": 0 }, + "3413": { "label": "13/16", "naklon": 0 }, + "3414": { "label": "13/17", "naklon": 0 }, + "3391": { "label": "13/18", "naklon": 0 }, + "3370": { "label": "13/19", "naklon": 0 }, + "3369": { "label": "13/20", "naklon": 0 }, + "3408": { "label": "13/21", "naklon": 0 }, + "3393": { "label": "13/22", "naklon": 0 }, + "3128": { "label": "13/23", "naklon": 0 }, + "3197": { "label": "13/24", "naklon": 0 }, + "4364": { "label": "13/25", "naklon": 0 }, + "3155": { "label": "13/26", "naklon": 0 }, + "3196": { "label": "13/27", "naklon": 0 }, + "3144": { "label": "13/28", "naklon": 0 }, + "3150": { "label": "13/30", "naklon": 0 }, + "3390": { "label": "13/31", "naklon": 0 }, + "3401": { "label": "13/32", "naklon": 0 }, + "3275": { "label": "13/33", "naklon": 0 }, + "3371": { "label": "13/35", "naklon": 0 }, + "3389": { "label": "13/36", "naklon": 0 }, + "3388": { "label": "13/37", "naklon": 0 }, + "3365": { "label": "13/38", "naklon": 0 }, + "3363": { "label": "13/39", "naklon": 0 }, + "3397": { "label": "13/40", "naklon": 0 }, + "3567": { "label": "13/40/1", "naklon": 0 }, + "3387": { "label": "13/41", "naklon": 0 }, + "3403": { "label": "13/42", "naklon": 0 }, + "3147": { "label": "13/43", "naklon": 0 }, + "3141": { "label": "13/44", "naklon": 0 }, + "3364": { "label": "13/46", "naklon": 0 }, + "3367": { "label": "13/47", "naklon": 0 }, + "3368": { "label": "13/48", "naklon": 0 }, + "3402": { "label": "13/49", "naklon": 0 }, + "3366": { "label": "13/50", "naklon": 0 }, + "3395": { "label": "13/51", "naklon": 0 }, + "3372": { "label": "13/52", "naklon": 0 }, + "3394": { "label": "13/53", "naklon": 0 }, + "3308": { "label": "13/54", "naklon": 0 }, + "3847": { "label": "13/54/1", "naklon": 0 }, + "3312": { "label": "13/55", "naklon": 3 }, + "3309": { "label": "13/56", "naklon": 3 }, + "3311": { "label": "13/57", "naklon": 3 }, + "3310": { "label": "13/58", "naklon": 3 }, + "4365": { "label": "13/59", "naklon": 3 }, + "4093": { "label": "13/60/1", "naklon": 3 }, + "3304": { "label": "13/61", "naklon": 3 }, + "3307": { "label": "13/62", "naklon": 3 }, + "3271": { "label": "13/63", "naklon": 3 }, + "3301": { "label": "13/64", "naklon": 3 }, + "4366": { "label": "13/65", "naklon": 3 }, + "3300": { "label": "13/66", "naklon": 3 }, + "3185": { "label": "13/67", "naklon": 0 }, + "3184": { "label": "13/68", "naklon": 0 }, + "3188": { "label": "13/69", "naklon": 0 }, + "3343": { "label": "13/71", "naklon": 6 }, + "3819": { "label": "13/71/1", "naklon": 6 }, + "3880": { "label": "13/71/2", "naklon": 6 }, + "3348": { "label": "13/72", "naklon": 6 }, + "3344": { "label": "13/74", "naklon": 6 }, + "3346": { "label": "13/75", "naklon": 6 }, + "3597": { "label": "13/75/1", "naklon": 6 }, + "3345": { "label": "13/76", "naklon": 6 }, + "3322": { "label": "13/77", "naklon": 0 }, + "3325": { "label": "13/78", "naklon": 0 }, + "4310": { "label": "13/78/1", "naklon": 0 }, + "3315": { "label": "13/79", "naklon": 0 }, + "3328": { "label": "13/80", "naklon": 0 }, + "3321": { "label": "13/81", "naklon": 0 }, + "3324": { "label": "13/82", "naklon": 0 }, + "3140": { "label": "13/84", "naklon": 0 }, + "3153": { "label": "13/85", "naklon": 0 }, + "3145": { "label": "13/86", "naklon": 0 }, + "3134": { "label": "13/87", "naklon": 0 }, + "3151": { "label": "13/88", "naklon": 0 }, + "3143": { "label": "13/89", "naklon": 0 }, + "3318": { "label": "13/90", "naklon": 0 }, + "3347": { "label": "13/91", "naklon": 0 }, + "3314": { "label": "13/94", "naklon": 0 }, + "3331": { "label": "13/96", "naklon": 0 }, + "3327": { "label": "13/97", "naklon": 0 }, + "3329": { "label": "13/99", "naklon": 0 }, + "3337": { "label": "13/100", "naklon": 0 }, + "3330": { "label": "13/101", "naklon": 0 }, + "3335": { "label": "13/102", "naklon": 0 }, + "3420": { "label": "13/103", "naklon": 0 }, + "3421": { "label": "13/104", "naklon": 0 }, + "4361": { "label": "13/105", "naklon": 0 }, + "4362": { "label": "13/106", "naklon": 0 }, + "3526": { "label": "13/107", "naklon": 0 }, + "4424": { "label": "13/108", "naklon": null }, + "3561": { "label": "13/109", "naklon": null }, + "3527": { "label": "13/110", "naklon": null }, + "3521": { "label": "13/111", "naklon": null }, + "3552": { "label": "13/112", "naklon": null }, + "3544": { "label": "13/113", "naklon": null }, + "3534": { "label": "13/114", "naklon": null }, + "3516": { "label": "13/115", "naklon": null }, + "3513": { "label": "13/116", "naklon": null }, + "3565": { "label": "13/117", "naklon": null }, + "3866": { "label": "13/118", "naklon": null }, + "3136": { "label": "14/1", "naklon": 0 }, + "3137": { "label": "14/2", "naklon": 0 }, + "3135": { "label": "14/3", "naklon": 0 }, + "3149": { "label": "14/4", "naklon": 0 }, + "3142": { "label": "14/5", "naklon": 0 }, + "3342": { "label": "14/6", "naklon": 0 }, + "3340": { "label": "14/7", "naklon": 0 }, + "3152": { "label": "14/8", "naklon": 0 }, + "3886": { "label": "14/9", "naklon": 0 }, + "3341": { "label": "14/10", "naklon": null }, + "3352": { "label": "14/11", "naklon": null }, + "3396": { "label": "15/1", "naklon": 5 }, + "2784": { "label": "15/2", "naklon": 5 }, + "2788": { "label": "15/3", "naklon": 5 }, + "2801": { "label": "15/4", "naklon": 5 }, + "2815": { "label": "15/5", "naklon": 5 }, + "2829": { "label": "15/6", "naklon": 5 }, + "2796": { "label": "15/7", "naklon": 5 }, + "2803": { "label": "15/8", "naklon": 5 }, + "4304": { "label": "15/8/1", "naklon": 5 }, + "4311": { "label": "15/8/2", "naklon": 5 }, + "2821": { "label": "15/9", "naklon": 5 }, + "3400": { "label": "15/10", "naklon": 5 }, + "2799": { "label": "15/11", "naklon": 5 }, + "2804": { "label": "15/12", "naklon": 5 }, + "4303": { "label": "15/12/1", "naklon": 5 }, + "4309": { "label": "15/12/2", "naklon": 5 }, + "2806": { "label": "15/13", "naklon": 5 }, + "2787": { "label": "15/14", "naklon": 5 }, + "2809": { "label": "15/15", "naklon": 5 }, + "2814": { "label": "15/16", "naklon": 0 }, + "3934": { "label": "15/17", "naklon": 0 }, + "3192": { "label": "15/18", "naklon": 0 }, + "2812": { "label": "15/19", "naklon": 0 }, + "4070": { "label": "15/20", "naklon": 0 }, + "2826": { "label": "15/21", "naklon": 0 }, + "2808": { "label": "15/22", "naklon": 3 }, + "2795": { "label": "15/23", "naklon": 3 }, + "2807": { "label": "15/24", "naklon": 3 }, + "2831": { "label": "15/25", "naklon": 0 }, + "2862": { "label": "15/26", "naklon": null }, + "2861": { "label": "15/27", "naklon": 0 }, + "2866": { "label": "15/28", "naklon": 0 }, + "3546": { "label": "15/28/1", "naklon": 0 }, + "4146": { "label": "15/29", "naklon": 0 }, + "3001": { "label": "15/29/1", "naklon": 0 }, + "2835": { "label": "15/30", "naklon": 0 }, + "2874": { "label": "15/31", "naklon": 0 }, + "2852": { "label": "15/32", "naklon": 0 }, + "2851": { "label": "15/33", "naklon": 0 }, + "3560": { "label": "15/33/1", "naklon": 0 }, + "2858": { "label": "15/34", "naklon": 0 }, + "4306": { "label": "15/34/1", "naklon": 0 }, + "2856": { "label": "15/35", "naklon": 0 }, + "2847": { "label": "15/36", "naklon": 0 }, + "3556": { "label": "15/36/1", "naklon": 0 }, + "3950": { "label": "15/37", "naklon": 0 }, + "2848": { "label": "15/38", "naklon": 0 }, + "2863": { "label": "15/39", "naklon": 0 }, + "4313": { "label": "15/39/1", "naklon": 0 }, + "2873": { "label": "15/40", "naklon": 0 }, + "2984": { "label": "15/40/1", "naklon": 0 }, + "2854": { "label": "15/41", "naklon": 0 }, + "2859": { "label": "15/42", "naklon": 0 }, + "2872": { "label": "15/43", "naklon": 0 }, + "2849": { "label": "15/44", "naklon": 0 }, + "2864": { "label": "15/45", "naklon": 0 }, + "3553": { "label": "15/46", "naklon": null }, + "3021": { "label": "15/47", "naklon": null }, + "3008": { "label": "15/47/1", "naklon": null }, + "3017": { "label": "15/48", "naklon": null }, + "3014": { "label": "15/49", "naklon": null }, + "2981": { "label": "15/50", "naklon": null }, + "3020": { "label": "15/51", "naklon": null }, + "3027": { "label": "15/52", "naklon": null }, + "3006": { "label": "15/53", "naklon": null }, + "3012": { "label": "15/54", "naklon": null }, + "2738": { "label": "15/55", "naklon": 0 }, + "2725": { "label": "15/56", "naklon": 0 }, + "3016": { "label": "15/57", "naklon": null }, + "3005": { "label": "15/58", "naklon": null }, + "3009": { "label": "15/58/1", "naklon": null }, + "3010": { "label": "15/59", "naklon": 0 }, + "3538": { "label": "15/59/1", "naklon": 0 }, + "4145": { "label": "15/59/2", "naklon": 0 }, + "2713": { "label": "15/60", "naklon": 0 }, + "2789": { "label": "15/61", "naklon": 0 }, + "2736": { "label": "15/62", "naklon": 0 }, + "2739": { "label": "15/63", "naklon": 0 }, + "4346": { "label": "15/64", "naklon": 0 }, + "2731": { "label": "15/65", "naklon": 0 }, + "2818": { "label": "15/66", "naklon": 0 }, + "3557": { "label": "15/66/1", "naklon": 0 }, + "2822": { "label": "15/67", "naklon": 0 }, + "2833": { "label": "15/68", "naklon": 0 }, + "2834": { "label": "15/69", "naklon": 0 }, + "3097": { "label": "15/70", "naklon": 0 }, + "2824": { "label": "15/71", "naklon": 0 }, + "2828": { "label": "15/72", "naklon": 0 }, + "2600": { "label": "15/73", "naklon": 0 }, + "4314": { "label": "15/73/1", "naklon": 0 }, + "2832": { "label": "15/74", "naklon": 0 }, + "4360": { "label": "15/75", "naklon": 0 }, + "2846": { "label": "15/76", "naklon": 0 }, + "2584": { "label": "15/77", "naklon": 0 }, + "2843": { "label": "15/78", "naklon": 0 }, + "4308": { "label": "15/78/1", "naklon": 0 }, + "4144": { "label": "15/79", "naklon": null }, + "2844": { "label": "15/80", "naklon": 0 }, + "2842": { "label": "15/81", "naklon": 0 }, + "2838": { "label": "15/82", "naklon": 0 }, + "2837": { "label": "15/83", "naklon": null }, + "3555": { "label": "15/83/1", "naklon": null }, + "2839": { "label": "15/84", "naklon": 0 }, + "2830": { "label": "15/85", "naklon": 0 }, + "4066": { "label": "15/86", "naklon": 0 }, + "2836": { "label": "15/87", "naklon": 0 }, + "2911": { "label": "15/88", "naklon": 0 }, + "2825": { "label": "15/89", "naklon": 0 }, + "2811": { "label": "15/90", "naklon": 0 }, + "3740": { "label": "15/94", "naklon": 15 }, + "2734": { "label": "15/95", "naklon": 15 }, + "3105": { "label": "15/96", "naklon": 15 }, + "2732": { "label": "15/97", "naklon": 15 }, + "2727": { "label": "15/98", "naklon": 15 }, + "2735": { "label": "15/99", "naklon": 15 }, + "3926": { "label": "15/100", "naklon": 15 }, + "2918": { "label": "15/101", "naklon": 0 }, + "2705": { "label": "15/102", "naklon": 10 }, + "2708": { "label": "15/103", "naklon": 10 }, + "2721": { "label": "15/104", "naklon": 10 }, + "2719": { "label": "15/105", "naklon": 10 }, + "2919": { "label": "15/106", "naklon": 10 }, + "3101": { "label": "15/107", "naklon": 10 }, + "2853": { "label": "15/108", "naklon": 10 }, + "2715": { "label": "15/109", "naklon": 10 }, + "2712": { "label": "15/110", "naklon": 0 }, + "2711": { "label": "15/111", "naklon": 0 }, + "2709": { "label": "15/112", "naklon": 0 }, + "2710": { "label": "15/113", "naklon": 0 }, + "2907": { "label": "15/114", "naklon": 0 }, + "2906": { "label": "15/115", "naklon": 0 }, + "2908": { "label": "15/116", "naklon": 0 }, + "2901": { "label": "15/117", "naklon": 0 }, + "2913": { "label": "15/118", "naklon": 0 }, + "3656": { "label": "15/119", "naklon": 0 }, + "2781": { "label": "15/120", "naklon": 0 }, + "2802": { "label": "15/121", "naklon": 0 }, + "2791": { "label": "15/122", "naklon": 0 }, + "2783": { "label": "15/123", "naklon": 0 }, + "2794": { "label": "15/124", "naklon": 0 }, + "3139": { "label": "15/125", "naklon": 0 }, + "3229": { "label": "15/126", "naklon": 5 }, + "3239": { "label": "15/127", "naklon": 5 }, + "3230": { "label": "15/128", "naklon": 5 }, + "4016": { "label": "15/129", "naklon": null }, + "3608": { "label": "16/16A", "naklon": 0 }, + "4151": { "label": "16/16B", "naklon": 0 }, + "3710": { "label": "16/1", "naklon": 0 }, + "3726": { "label": "16/2", "naklon": 0 }, + "3743": { "label": "16/3", "naklon": 0 }, + "3724": { "label": "16/4", "naklon": 0 }, + "3712": { "label": "16/5", "naklon": 0 }, + "3739": { "label": "16/6", "naklon": 0 }, + "3742": { "label": "16/7", "naklon": 0 }, + "3731": { "label": "16/8", "naklon": 0 }, + "3727": { "label": "16/9", "naklon": 0 }, + "3729": { "label": "16/10", "naklon": 0 }, + "3736": { "label": "16/11", "naklon": 0 }, + "3713": { "label": "16/12", "naklon": 0 }, + "3715": { "label": "16/13", "naklon": 0 }, + "3733": { "label": "16/14", "naklon": 0 }, + "3732": { "label": "16/15", "naklon": 0 }, + "3634": { "label": "16/17", "naklon": 0 }, + "3610": { "label": "16/18", "naklon": 0 }, + "3626": { "label": "16/19", "naklon": 0 }, + "3618": { "label": "16/20", "naklon": 0 }, + "3619": { "label": "16/21", "naklon": 0 }, + "3628": { "label": "16/22", "naklon": 0 }, + "3615": { "label": "16/23", "naklon": 0 }, + "3609": { "label": "16/24", "naklon": 0 }, + "3606": { "label": "16/25", "naklon": 0 }, + "3624": { "label": "16/26", "naklon": 0 }, + "3627": { "label": "16/27", "naklon": 0 }, + "3607": { "label": "16/28", "naklon": 0 }, + "4370": { "label": "16/29", "naklon": 0 }, + "3692": { "label": "16/30", "naklon": 0 }, + "3614": { "label": "16/31", "naklon": 0 }, + "3623": { "label": "16/32", "naklon": 0 }, + "4373": { "label": "16/33", "naklon": 0 }, + "3620": { "label": "16/34", "naklon": 0 }, + "3685": { "label": "16/35", "naklon": 0 }, + "3616": { "label": "16/36", "naklon": 0 }, + "3686": { "label": "16/37", "naklon": 0 }, + "3688": { "label": "16/38", "naklon": 0 }, + "3684": { "label": "16/39", "naklon": 0 }, + "3825": { "label": "16/40", "naklon": 0 }, + "3865": { "label": "16/41", "naklon": 0 }, + "3824": { "label": "16/42", "naklon": 0 }, + "3871": { "label": "16/43", "naklon": 0 }, + "3801": { "label": "16/44", "naklon": 0 }, + "3862": { "label": "16/45", "naklon": 0 }, + "3876": { "label": "16/46", "naklon": 0 }, + "3861": { "label": "16/47", "naklon": 0 }, + "4215": { "label": "16/48", "naklon": 0 }, + "3605": { "label": "16/49", "naklon": 10 }, + "3603": { "label": "16/50", "naklon": 10 }, + "3592": { "label": "16/51", "naklon": 10 }, + "3598": { "label": "16/52", "naklon": 10 }, + "3594": { "label": "16/53", "naklon": 10 }, + "3593": { "label": "16/54", "naklon": 10 }, + "3630": { "label": "16/55", "naklon": 10 }, + "3763": { "label": "16/56", "naklon": 10 }, + "3746": { "label": "16/57", "naklon": 10 }, + "3699": { "label": "16/58", "naklon": 0 }, + "3698": { "label": "16/59", "naklon": 0 }, + "3709": { "label": "16/60", "naklon": null }, + "3708": { "label": "16/61", "naklon": 0 }, + "3703": { "label": "16/62", "naklon": null }, + "3700": { "label": "16/63", "naklon": 0 }, + "3701": { "label": "16/64", "naklon": null }, + "3704": { "label": "16/65", "naklon": 0 }, + "3707": { "label": "16/66", "naklon": null }, + "3810": { "label": "16/67", "naklon": 0 }, + "4208": { "label": "16/68", "naklon": null }, + "3867": { "label": "16/69", "naklon": 0 }, + "4372": { "label": "16/70", "naklon": null }, + "3881": { "label": "16/71", "naklon": 0 }, + "4204": { "label": "16/72", "naklon": null }, + "3869": { "label": "16/73", "naklon": 0 }, + "4202": { "label": "16/74", "naklon": null }, + "3830": { "label": "16/75", "naklon": 0 }, + "3870": { "label": "16/76", "naklon": null }, + "3964": { "label": "16/77", "naklon": 0 }, + "3849": { "label": "16/78", "naklon": 0 }, + "3694": { "label": "16/79", "naklon": null }, + "3717": { "label": "16/80", "naklon": 0 }, + "3877": { "label": "16/81", "naklon": null }, + "3755": { "label": "16/82", "naklon": 0 }, + "3725": { "label": "16/83", "naklon": null }, + "3716": { "label": "16/84", "naklon": 0 }, + "3696": { "label": "16/85", "naklon": null }, + "3702": { "label": "16/86", "naklon": 0 }, + "3706": { "label": "16/87", "naklon": null }, + "3850": { "label": "16/88", "naklon": 0 }, + "3848": { "label": "16/89", "naklon": null }, + "3737": { "label": "16/90", "naklon": null }, + "3705": { "label": "16/91", "naklon": 0 }, + "3723": { "label": "16/92", "naklon": null }, + "3842": { "label": "16/93", "naklon": 0 }, + "3735": { "label": "16/94", "naklon": null }, + "3719": { "label": "16/95", "naklon": 0 }, + "3697": { "label": "16/96", "naklon": 0 }, + "3711": { "label": "16/97", "naklon": 0 }, + "4107": { "label": "16/98", "naklon": null }, + "4112": { "label": "16/99", "naklon": 5 }, + "4106": { "label": "16/100", "naklon": 5 }, + "4111": { "label": "16/101", "naklon": 5 }, + "4091": { "label": "16/102", "naklon": null }, + "4104": { "label": "16/103", "naklon": 5 }, + "4094": { "label": "16/104", "naklon": null }, + "4089": { "label": "16/105", "naklon": 5 }, + "4095": { "label": "16/106", "naklon": null }, + "4102": { "label": "16/107", "naklon": 5 }, + "4105": { "label": "16/108", "naklon": null }, + "3859": { "label": "16/109", "naklon": null }, + "4090": { "label": "16/110", "naklon": 5 }, + "4110": { "label": "16/111", "naklon": null }, + "4097": { "label": "16/112", "naklon": 5 }, + "4099": { "label": "16/113", "naklon": null }, + "4096": { "label": "16/114", "naklon": null }, + "4101": { "label": "16/115", "naklon": 5 }, + "4109": { "label": "16/116", "naklon": null }, + "4092": { "label": "16/117", "naklon": 5 }, + "3631": { "label": "16/118", "naklon": null }, + "3632": { "label": "16/119", "naklon": 0 }, + "3641": { "label": "16/120", "naklon": null }, + "3638": { "label": "16/121", "naklon": 0 }, + "3637": { "label": "16/122", "naklon": null }, + "4142": { "label": "16/123", "naklon": null }, + "4147": { "label": "16/124", "naklon": 5 }, + "4139": { "label": "16/125", "naklon": 5 }, + "3172": { "label": "20/30A", "naklon": 2 }, + "3164": { "label": "20/30B", "naklon": 2 }, + "3247": { "label": "20/1", "naklon": 10 }, + "3296": { "label": "20/2", "naklon": 10 }, + "3246": { "label": "20/3", "naklon": 10 }, + "3270": { "label": "20/4", "naklon": 10 }, + "3294": { "label": "20/5", "naklon": 10 }, + "3298": { "label": "20/6", "naklon": 10 }, + "3297": { "label": "20/7", "naklon": 10 }, + "3293": { "label": "20/8", "naklon": 10 }, + "3299": { "label": "20/9", "naklon": 10 }, + "3295": { "label": "20/10", "naklon": 10 }, + "3244": { "label": "20/11", "naklon": 10 }, + "3249": { "label": "20/12", "naklon": 10 }, + "3268": { "label": "20/13", "naklon": 10 }, + "3245": { "label": "20/14", "naklon": 10 }, + "3278": { "label": "20/15", "naklon": 10 }, + "3280": { "label": "20/16", "naklon": 10 }, + "3292": { "label": "20/17", "naklon": 10 }, + "3287": { "label": "20/18", "naklon": 10 }, + "3282": { "label": "20/19", "naklon": 10 }, + "3273": { "label": "20/20", "naklon": 0 }, + "3157": { "label": "20/21", "naklon": 0 }, + "3283": { "label": "20/22", "naklon": 0 }, + "3159": { "label": "20/23", "naklon": 0 }, + "3289": { "label": "20/24", "naklon": 0 }, + "3163": { "label": "20/25", "naklon": 0 }, + "3126": { "label": "20/26", "naklon": 0 }, + "3171": { "label": "20/27", "naklon": 0 }, + "3162": { "label": "20/28", "naklon": 0 }, + "3279": { "label": "20/29", "naklon": 10 }, + "3173": { "label": "20/31", "naklon": 0 }, + "3127": { "label": "20/32", "naklon": 0 }, + "3131": { "label": "20/33", "naklon": 0 }, + "3129": { "label": "20/34", "naklon": 0 }, + "3276": { "label": "20/35", "naklon": 2 }, + "3290": { "label": "20/36", "naklon": 2 }, + "3132": { "label": "20/37", "naklon": 0 }, + "3138": { "label": "20/38", "naklon": 0 }, + "3272": { "label": "20/39", "naklon": 0 }, + "3291": { "label": "20/40", "naklon": 0 }, + "3277": { "label": "20/41", "naklon": 10 }, + "3286": { "label": "20/42", "naklon": 10 }, + "3281": { "label": "20/43", "naklon": 10 }, + "3288": { "label": "20/44", "naklon": 10 }, + "3284": { "label": "20/45", "naklon": 10 }, + "3167": { "label": "20/46", "naklon": 10 }, + "3872": { "label": "20/47", "naklon": 0 }, + "3124": { "label": "20/48", "naklon": 0 }, + "3133": { "label": "20/49", "naklon": 0 }, + "3158": { "label": "20/50", "naklon": 0 }, + "3169": { "label": "20/51", "naklon": 0 }, + "3146": { "label": "20/52", "naklon": 0 }, + "3160": { "label": "20/53", "naklon": 0 }, + "3248": { "label": "20/54", "naklon": 0 }, + "3156": { "label": "20/55", "naklon": 0 }, + "3161": { "label": "20/56", "naklon": 0 }, + "3170": { "label": "20/57", "naklon": 0 }, + "3168": { "label": "20/58", "naklon": 0 }, + "3125": { "label": "20/59", "naklon": 0 }, + "3166": { "label": "20/60", "naklon": 0 }, + "3130": { "label": "20/61", "naklon": 0 }, + "3563": { "label": "20/62", "naklon": 0 }, + "3550": { "label": "20/63", "naklon": null }, + "3269": { "label": "20/67", "naklon": 0 }, + "2921": { "label": "21/1", "naklon": 0 }, + "2707": { "label": "21/2", "naklon": 0 }, + "2723": { "label": "21/3", "naklon": 0 }, + "2716": { "label": "21/4", "naklon": 0 }, + "2717": { "label": "21/5", "naklon": 0 }, + "2720": { "label": "21/6", "naklon": 0 }, + "2722": { "label": "21/7", "naklon": 0 }, + "2718": { "label": "21/8", "naklon": 0 }, + "2724": { "label": "21/9", "naklon": 0 }, + "2742": { "label": "21/10", "naklon": 0 }, + "2743": { "label": "21/11", "naklon": 0 }, + "2733": { "label": "21/12", "naklon": 0 }, + "2903": { "label": "21/14", "naklon": 0 }, + "2917": { "label": "21/15", "naklon": 0 }, + "2897": { "label": "21/16", "naklon": 0 }, + "2914": { "label": "21/17", "naklon": 0 }, + "2898": { "label": "21/18", "naklon": 0 }, + "2773": { "label": "21/19", "naklon": 0 }, + "2895": { "label": "21/20", "naklon": 0 }, + "2896": { "label": "21/21", "naklon": 0 }, + "2771": { "label": "21/22", "naklon": 0 }, + "2772": { "label": "21/23", "naklon": 0 }, + "2793": { "label": "21/24", "naklon": 0 }, + "2902": { "label": "21/25", "naklon": 0 }, + "2910": { "label": "21/26", "naklon": 0 }, + "2909": { "label": "21/27", "naklon": 0 }, + "2920": { "label": "21/28", "naklon": 0 }, + "2916": { "label": "21/29", "naklon": 0 }, + "2904": { "label": "21/30", "naklon": 0 }, + "2915": { "label": "21/31", "naklon": 0 }, + "2905": { "label": "21/32", "naklon": 0 }, + "2900": { "label": "21/33", "naklon": 0 }, + "2899": { "label": "21/34", "naklon": 0 }, + "2741": { "label": "21/36", "naklon": 0 }, + "2714": { "label": "21/37", "naklon": 0 }, + "2701": { "label": "21/38", "naklon": 0 }, + "2703": { "label": "21/39", "naklon": 0 }, + "2704": { "label": "21/40", "naklon": 0 }, + "2702": { "label": "21/41", "naklon": 0 }, + "2706": { "label": "21/42", "naklon": 0 }, + "2776": { "label": "21/43", "naklon": 0 }, + "2770": { "label": "21/44", "naklon": 0 }, + "2786": { "label": "21/45", "naklon": 0 }, + "2779": { "label": "21/46", "naklon": 0 }, + "2782": { "label": "21/47", "naklon": 0 }, + "2785": { "label": "21/48", "naklon": 0 }, + "2769": { "label": "21/49", "naklon": 0 }, + "3354": { "label": "21/50", "naklon": 0 }, + "2778": { "label": "21/51", "naklon": 0 }, + "2775": { "label": "21/52", "naklon": 0 }, + "2780": { "label": "21/53", "naklon": 0 }, + "2790": { "label": "21/54", "naklon": 0 }, + "2792": { "label": "21/55", "naklon": 0 }, + "2774": { "label": "21/56", "naklon": 0 }, + "2630": { "label": "22/1", "naklon": 0 }, + "2631": { "label": "22/2", "naklon": 0 }, + "2632": { "label": "22/3", "naklon": 0 }, + "2633": { "label": "22/4", "naklon": 0 }, + "2634": { "label": "22/5", "naklon": 0 }, + "2636": { "label": "22/6", "naklon": 0 }, + "4367": { "label": "22/7", "naklon": 0 }, + "2637": { "label": "22/8", "naklon": 0 }, + "2638": { "label": "22/9", "naklon": 0 }, + "2639": { "label": "22/10", "naklon": 0 }, + "2640": { "label": "22/11", "naklon": 0 }, + "2641": { "label": "22/12", "naklon": 0 }, + "2642": { "label": "22/13", "naklon": 0 }, + "2643": { "label": "22/14", "naklon": 0 }, + "2644": { "label": "22/15", "naklon": 0 }, + "2645": { "label": "22/16", "naklon": 0 }, + "2646": { "label": "22/17", "naklon": 0 }, + "2647": { "label": "22/18", "naklon": 0 }, + "2648": { "label": "22/19", "naklon": 0 }, + "2649": { "label": "22/20", "naklon": 0 }, + "2650": { "label": "22/21", "naklon": 0 }, + "2651": { "label": "22/22", "naklon": 0 }, + "4103": { "label": "22/23", "naklon": 0 }, + "2653": { "label": "22/24", "naklon": 0 }, + "2654": { "label": "22/25", "naklon": 0 }, + "2655": { "label": "22/26", "naklon": 0 }, + "2656": { "label": "22/27", "naklon": 0 }, + "2657": { "label": "22/28", "naklon": 0 }, + "2658": { "label": "22/29", "naklon": 0 }, + "2659": { "label": "22/30", "naklon": 0 }, + "2660": { "label": "22/31", "naklon": 0 }, + "2661": { "label": "22/32", "naklon": 0 }, + "3015": { "label": "22/32/1", "naklon": 0 }, + "2662": { "label": "22/33", "naklon": 0 }, + "2663": { "label": "22/34", "naklon": 0 }, + "2664": { "label": "22/35", "naklon": 0 }, + "2665": { "label": "22/36", "naklon": 0 }, + "2666": { "label": "22/37", "naklon": 0 }, + "2667": { "label": "22/38", "naklon": 0 }, + "2668": { "label": "22/39", "naklon": 0 }, + "2669": { "label": "22/40", "naklon": null }, + "2670": { "label": "22/41", "naklon": null }, + "2671": { "label": "22/42", "naklon": null }, + "3087": { "label": "23/9A", "naklon": 10 }, + "3090": { "label": "23/9B", "naklon": 10 }, + "3075": { "label": "23/1", "naklon": 0 }, + "3089": { "label": "23/2", "naklon": 0 }, + "3088": { "label": "23/3", "naklon": 0 }, + "3228": { "label": "23/4", "naklon": 10 }, + "2751": { "label": "23/5", "naklon": 10 }, + "3243": { "label": "23/6", "naklon": 10 }, + "4349": { "label": "23/7", "naklon": 10 }, + "3102": { "label": "23/8", "naklon": 10 }, + "3099": { "label": "23/10", "naklon": 10 }, + "3103": { "label": "23/11", "naklon": 10 }, + "3093": { "label": "23/12", "naklon": 10 }, + "3098": { "label": "23/13", "naklon": 10 }, + "3092": { "label": "23/14", "naklon": 10 }, + "3233": { "label": "23/15", "naklon": 0 }, + "3095": { "label": "23/16", "naklon": 0 }, + "4074": { "label": "23/17", "naklon": 0 }, + "2729": { "label": "23/18", "naklon": 0 }, + "3234": { "label": "23/19", "naklon": 0 }, + "3094": { "label": "23/20", "naklon": 0 }, + "2817": { "label": "23/21", "naklon": 0 }, + "3226": { "label": "23/22", "naklon": 0 }, + "3225": { "label": "23/23", "naklon": 0 }, + "3237": { "label": "23/24", "naklon": 0 }, + "4250": { "label": "23/25", "naklon": 0 }, + "3059": { "label": "23/26", "naklon": 10 }, + "3238": { "label": "23/27", "naklon": 10 }, + "3242": { "label": "23/28", "naklon": 10 }, + "3236": { "label": "23/29", "naklon": 10 }, + "3112": { "label": "23/30", "naklon": 10 }, + "3224": { "label": "23/31", "naklon": 0 }, + "4298": { "label": "23/32", "naklon": 10 }, + "4150": { "label": "23/33", "naklon": 10 }, + "3091": { "label": "23/34", "naklon": 10 }, + "3771": { "label": "25/1", "naklon": 5 }, + "3777": { "label": "25/2", "naklon": 5 }, + "3749": { "label": "25/3", "naklon": 5 }, + "3769": { "label": "25/4", "naklon": 5 }, + "3765": { "label": "25/5", "naklon": 5 }, + "3785": { "label": "25/6", "naklon": 5 }, + "3761": { "label": "25/7", "naklon": 5 }, + "3758": { "label": "25/8", "naklon": 5 }, + "3766": { "label": "25/9", "naklon": 5 }, + "3779": { "label": "25/10", "naklon": 5 }, + "3899": { "label": "25/11", "naklon": 10 }, + "3922": { "label": "25/12", "naklon": 10 }, + "3912": { "label": "25/13", "naklon": 10 }, + "3933": { "label": "25/14", "naklon": 10 }, + "3921": { "label": "25/15", "naklon": 10 }, + "4300": { "label": "25/16", "naklon": 10 }, + "3927": { "label": "25/17", "naklon": 10 }, + "3212": { "label": "25/18", "naklon": 10 }, + "3208": { "label": "25/19", "naklon": 10 }, + "3207": { "label": "25/20", "naklon": 10 }, + "4294": { "label": "25/21", "naklon": 10 }, + "3209": { "label": "25/22", "naklon": 10 }, + "3745": { "label": "25/23", "naklon": 10 }, + "3762": { "label": "25/24", "naklon": 10 }, + "3215": { "label": "25/25", "naklon": 10 }, + "3210": { "label": "25/26", "naklon": 10 }, + "3211": { "label": "25/27", "naklon": 10 }, + "3206": { "label": "25/28", "naklon": 10 }, + "3918": { "label": "25/29", "naklon": 5 }, + "3928": { "label": "25/30", "naklon": 5 }, + "3917": { "label": "25/31", "naklon": 5 }, + "4029": { "label": "25/32", "naklon": 0 }, + "4038": { "label": "25/33", "naklon": 0 }, + "4022": { "label": "25/34", "naklon": 0 }, + "3937": { "label": "25/35", "naklon": 0 }, + "3190": { "label": "25/36", "naklon": 0 }, + "3835": { "label": "25/37", "naklon": 0 }, + "3201": { "label": "25/38", "naklon": 0 }, + "3193": { "label": "25/39", "naklon": 0 }, + "3191": { "label": "25/40", "naklon": 0 }, + "3203": { "label": "25/41", "naklon": 0 }, + "4301": { "label": "25/42", "naklon": 0 }, + "3223": { "label": "25/43", "naklon": 0 }, + "3202": { "label": "25/44", "naklon": 0 }, + "3205": { "label": "25/45", "naklon": 0 }, + "3194": { "label": "25/46", "naklon": 0 }, + "3198": { "label": "25/47", "naklon": 0 }, + "3204": { "label": "25/48", "naklon": 0 }, + "3200": { "label": "25/49", "naklon": 0 }, + "3216": { "label": "25/50", "naklon": 0 }, + "3932": { "label": "25/51", "naklon": 5 }, + "3923": { "label": "25/52", "naklon": 5 }, + "3913": { "label": "25/53", "naklon": 5 }, + "3900": { "label": "25/54", "naklon": 5 }, + "4189": { "label": "25/55", "naklon": 10 }, + "4191": { "label": "25/56", "naklon": 10 }, + "3790": { "label": "25/57", "naklon": 10 }, + "4190": { "label": "25/58", "naklon": 10 }, + "4302": { "label": "25/59", "naklon": 0 }, + "4351": { "label": "25/60", "naklon": 0 }, + "4075": { "label": "25/61", "naklon": 0 }, + "4071": { "label": "25/62", "naklon": 0 }, + "3784": { "label": "25/63", "naklon": 0 }, + "4065": { "label": "25/64", "naklon": 0 }, + "4297": { "label": "25/65", "naklon": 0 }, + "4295": { "label": "25/66", "naklon": 0 }, + "4299": { "label": "25/67", "naklon": 0 }, + "3772": { "label": "25/68", "naklon": 0 }, + "3941": { "label": "25/69", "naklon": 0 }, + "3782": { "label": "25/70", "naklon": 0 }, + "4068": { "label": "25/71", "naklon": 0 }, + "4073": { "label": "25/72", "naklon": 0 }, + "3901": { "label": "25/73", "naklon": 5 }, + "4296": { "label": "25/74", "naklon": 5 }, + "3910": { "label": "25/75", "naklon": 5 }, + "4293": { "label": "25/76", "naklon": 5 }, + "3919": { "label": "25/77", "naklon": 5 }, + "3924": { "label": "25/78", "naklon": 5 }, + "3909": { "label": "25/79", "naklon": 5 }, + "3896": { "label": "25/80", "naklon": 5 }, + "3911": { "label": "25/81", "naklon": 5 }, + "2819": { "label": "25/82", "naklon": 15 }, + "3776": { "label": "25/83", "naklon": 15 }, + "3752": { "label": "25/84", "naklon": 15 }, + "4353": { "label": "25/85", "naklon": 15 }, + "3791": { "label": "25/86", "naklon": 0 }, + "3770": { "label": "25/87", "naklon": 0 }, + "3760": { "label": "25/88", "naklon": 0 }, + "3115": { "label": "25/89", "naklon": 0 }, + "3738": { "label": "25/90", "naklon": 0 }, + "3748": { "label": "25/91", "naklon": 0 }, + "3753": { "label": "25/92", "naklon": 0 }, + "3775": { "label": "25/93", "naklon": 0 }, + "3778": { "label": "25/94", "naklon": 5 }, + "4078": { "label": "25/95", "naklon": 5 }, + "4088": { "label": "25/96", "naklon": 5 }, + "3856": { "label": "25/97", "naklon": 5 }, + "4084": { "label": "25/98", "naklon": 5 }, + "4069": { "label": "25/99", "naklon": 5 }, + "4188": { "label": "25/100", "naklon": 5 }, + "4064": { "label": "25/101", "naklon": 5 }, + "3792": { "label": "25/102", "naklon": 5 }, + "3780": { "label": "25/103", "naklon": 5 }, + "4034": { "label": "25/104", "naklon": 5 }, + "4072": { "label": "25/105", "naklon": 5 }, + "3884": { "label": "25/106", "naklon": 5 }, + "3793": { "label": "25/107", "naklon": 5 }, + "3863": { "label": "25/108", "naklon": 5 }, + "3855": { "label": "25/109", "naklon": 5 }, + "3846": { "label": "33/1", "naklon": 0 }, + "3943": { "label": "33/2", "naklon": 0 }, + "3903": { "label": "33/3", "naklon": 0 }, + "3982": { "label": "33/4", "naklon": 0 }, + "3879": { "label": "33/5", "naklon": 0 }, + "3887": { "label": "33/6", "naklon": 0 }, + "3920": { "label": "33/7", "naklon": 5 }, + "3942": { "label": "33/8", "naklon": 5 }, + "3829": { "label": "33/9", "naklon": null }, + "3452": { "label": "34/79A", "naklon": 6 }, + "3460": { "label": "34/79B", "naklon": 6 }, + "3443": { "label": "34/90A", "naklon": 6 }, + "3445": { "label": "34/90B", "naklon": 6 }, + "3457": { "label": "34/90C", "naklon": 6 }, + "3461": { "label": "34/97A", "naklon": 6 }, + "3463": { "label": "34/97B", "naklon": 6 }, + "3426": { "label": "34/98A", "naklon": 6 }, + "3444": { "label": "34/98B", "naklon": 6 }, + "3453": { "label": "34/99A", "naklon": 6 }, + "3455": { "label": "34/99B", "naklon": 6 }, + "4009": { "label": "34/1", "naklon": 0 }, + "3602": { "label": "34/2", "naklon": 0 }, + "3441": { "label": "34/3", "naklon": 0 }, + "3464": { "label": "34/4", "naklon": 0 }, + "3883": { "label": "34/5", "naklon": 0 }, + "4098": { "label": "34/6", "naklon": 0 }, + "4003": { "label": "34/7", "naklon": 0 }, + "4004": { "label": "34/8", "naklon": 0 }, + "3888": { "label": "34/9", "naklon": 0 }, + "3997": { "label": "34/10", "naklon": 0 }, + "4006": { "label": "34/11", "naklon": 0 }, + "4000": { "label": "34/12", "naklon": 0 }, + "4011": { "label": "34/13", "naklon": 0 }, + "3999": { "label": "34/14", "naklon": 0 }, + "3981": { "label": "34/15", "naklon": 0 }, + "3988": { "label": "34/16", "naklon": 0 }, + "3986": { "label": "34/17", "naklon": 0 }, + "3998": { "label": "34/18", "naklon": 0 }, + "3983": { "label": "34/19", "naklon": 0 }, + "4005": { "label": "34/20", "naklon": 0 }, + "4001": { "label": "34/21", "naklon": 0 }, + "4008": { "label": "34/22", "naklon": 0 }, + "4002": { "label": "34/23", "naklon": 0 }, + "3996": { "label": "34/24", "naklon": 0 }, + "4007": { "label": "34/25", "naklon": 0 }, + "4113": { "label": "34/26", "naklon": 15 }, + "3595": { "label": "34/27", "naklon": 5 }, + "3599": { "label": "34/28", "naklon": 5 }, + "3601": { "label": "34/29", "naklon": 5 }, + "4205": { "label": "34/30", "naklon": 0 }, + "3987": { "label": "34/31", "naklon": null }, + "4214": { "label": "34/32", "naklon": 0 }, + "4226": { "label": "34/33", "naklon": 0 }, + "4209": { "label": "34/34", "naklon": 0 }, + "4201": { "label": "34/35", "naklon": 0 }, + "3440": { "label": "34/36", "naklon": 0 }, + "3465": { "label": "34/37", "naklon": 0 }, + "3446": { "label": "34/38", "naklon": 0 }, + "4039": { "label": "34/39", "naklon": 5 }, + "4057": { "label": "34/40", "naklon": 5 }, + "3985": { "label": "34/41", "naklon": 0 }, + "3882": { "label": "34/42", "naklon": 0 }, + "4040": { "label": "34/43", "naklon": 5 }, + "3231": { "label": "34/44", "naklon": 0 }, + "3227": { "label": "34/45", "naklon": 0 }, + "3431": { "label": "34/46", "naklon": 0 }, + "4013": { "label": "34/47", "naklon": 0 }, + "4045": { "label": "34/48", "naklon": 0 }, + "3949": { "label": "34/49", "naklon": 0 }, + "3953": { "label": "34/50", "naklon": 0 }, + "3952": { "label": "34/51", "naklon": 0 }, + "3995": { "label": "34/52", "naklon": 0 }, + "3992": { "label": "34/53", "naklon": 0 }, + "4198": { "label": "34/54", "naklon": 0 }, + "3935": { "label": "34/55", "naklon": 0 }, + "4050": { "label": "34/56", "naklon": 0 }, + "4049": { "label": "34/57", "naklon": 0 }, + "4054": { "label": "34/58", "naklon": 0 }, + "3663": { "label": "34/59", "naklon": 6 }, + "3661": { "label": "34/60", "naklon": 6 }, + "3664": { "label": "34/61", "naklon": 6 }, + "3660": { "label": "34/62", "naklon": 6 }, + "3662": { "label": "34/63", "naklon": 6 }, + "3665": { "label": "34/65", "naklon": 6 }, + "3667": { "label": "34/66", "naklon": 6 }, + "3675": { "label": "34/67", "naklon": 6 }, + "3666": { "label": "34/68", "naklon": 6 }, + "3652": { "label": "34/69", "naklon": 6 }, + "3458": { "label": "34/70", "naklon": 6 }, + "4425": { "label": "34/70/1", "naklon": 6 }, + "3459": { "label": "34/71", "naklon": 6 }, + "3435": { "label": "34/72", "naklon": 6 }, + "3448": { "label": "34/73", "naklon": 6 }, + "3451": { "label": "34/74", "naklon": 6 }, + "3442": { "label": "34/75", "naklon": 6 }, + "3449": { "label": "34/76", "naklon": 6 }, + "3450": { "label": "34/77", "naklon": 6 }, + "3433": { "label": "34/78", "naklon": 6 }, + "3432": { "label": "34/80", "naklon": 12 }, + "3470": { "label": "34/81", "naklon": 12 }, + "3438": { "label": "34/82", "naklon": 12 }, + "3439": { "label": "34/83", "naklon": 12 }, + "4028": { "label": "34/84", "naklon": 5 }, + "3596": { "label": "34/85", "naklon": 5 }, + "4021": { "label": "34/86", "naklon": 5 }, + "3437": { "label": "34/87", "naklon": 12 }, + "3428": { "label": "34/88", "naklon": 12 }, + "3430": { "label": "34/89", "naklon": 12 }, + "3454": { "label": "34/91", "naklon": 6 }, + "3492": { "label": "34/92", "naklon": 6 }, + "3462": { "label": "34/93", "naklon": 6 }, + "3427": { "label": "34/94", "naklon": 6 }, + "3434": { "label": "34/95", "naklon": 6 }, + "3456": { "label": "34/96", "naklon": 6 }, + "4307": { "label": "34/98/1", "naklon": 6 }, + "3968": { "label": "35/1", "naklon": 0 }, + "3969": { "label": "35/2", "naklon": 0 }, + "3947": { "label": "35/3", "naklon": 0 }, + "3979": { "label": "35/4", "naklon": 0 }, + "3959": { "label": "35/5", "naklon": 0 }, + "3948": { "label": "35/6", "naklon": 0 }, + "3961": { "label": "35/7", "naklon": 0 }, + "3956": { "label": "35/8", "naklon": 0 }, + "3604": { "label": "35/9", "naklon": 0 }, + "3944": { "label": "35/10", "naklon": 0 }, + "3960": { "label": "35/11", "naklon": 0 }, + "3958": { "label": "35/12", "naklon": 0 }, + "4036": { "label": "35/13", "naklon": 5 }, + "3893": { "label": "35/18", "naklon": 5 }, + "4108": { "label": "35/19", "naklon": 5 }, + "4017": { "label": "35/20", "naklon": 5 }, + "3963": { "label": "35/21", "naklon": 0 }, + "3658": { "label": "35/22", "naklon": 0 }, + "3975": { "label": "35/23", "naklon": 0 }, + "3980": { "label": "35/24", "naklon": 0 }, + "4012": { "label": "35/25", "naklon": 0 }, + "3655": { "label": "35/26", "naklon": 0 }, + "3962": { "label": "35/27", "naklon": 0 }, + "3945": { "label": "35/28", "naklon": 0 }, + "3569": { "label": "35/29", "naklon": 0 }, + "3429": { "label": "35/30", "naklon": 0 }, + "3657": { "label": "35/31", "naklon": 0 }, + "3646": { "label": "35/32", "naklon": 0 }, + "3622": { "label": "35/33", "naklon": 0 }, + "3612": { "label": "35/34", "naklon": 0 }, + "3955": { "label": "35/35", "naklon": 0 }, + "3878": { "label": "35/37", "naklon": 0 }, + "3965": { "label": "35/38", "naklon": 0 }, + "3970": { "label": "35/39", "naklon": 0 }, + "3611": { "label": "35/40", "naklon": 0 }, + "2635": { "label": "35/41", "naklon": 0 }, + "3978": { "label": "35/42", "naklon": 0 }, + "4213": { "label": "35/43", "naklon": 0 }, + "3984": { "label": "35/44", "naklon": 0 }, + "4218": { "label": "35/45", "naklon": 0 }, + "3973": { "label": "35/46", "naklon": 0 }, + "3974": { "label": "35/47", "naklon": 0 }, + "3759": { "label": "35/48", "naklon": 0 }, + "3844": { "label": "35/49", "naklon": 0 }, + "3804": { "label": "35/50", "naklon": 0 }, + "3831": { "label": "35/51", "naklon": 0 }, + "3643": { "label": "35/52", "naklon": 0 }, + "3966": { "label": "35/53", "naklon": 0 }, + "3971": { "label": "35/54", "naklon": 0 }, + "3650": { "label": "35/55", "naklon": 6 }, + "3651": { "label": "35/56", "naklon": 6 }, + "3669": { "label": "35/57", "naklon": 6 }, + "3648": { "label": "35/58", "naklon": 6 }, + "3645": { "label": "35/59", "naklon": 6 }, + "3659": { "label": "35/60", "naklon": 6 }, + "3647": { "label": "35/61", "naklon": 6 }, + "3644": { "label": "35/62", "naklon": 6 }, + "3671": { "label": "35/63", "naklon": 6 }, + "3682": { "label": "35/64", "naklon": 6 }, + "3672": { "label": "35/65", "naklon": 6 }, + "3683": { "label": "35/66", "naklon": 6 }, + "3673": { "label": "35/67", "naklon": 6 }, + "3674": { "label": "35/68", "naklon": 6 }, + "3679": { "label": "35/69", "naklon": 6 }, + "3649": { "label": "35/70", "naklon": 6 }, + "3687": { "label": "35/71", "naklon": 6 }, + "3677": { "label": "35/72", "naklon": 6 }, + "3690": { "label": "35/73", "naklon": 6 }, + "3691": { "label": "35/74", "naklon": 6 }, + "3676": { "label": "35/75", "naklon": 6 }, + "3680": { "label": "35/76", "naklon": 6 }, + "3668": { "label": "35/77", "naklon": 6 }, + "3681": { "label": "35/78", "naklon": 6 }, + "3670": { "label": "35/79", "naklon": 6 }, + "3689": { "label": "35/80", "naklon": 6 }, + "3678": { "label": "35/81", "naklon": 6 }, + "3693": { "label": "35/82", "naklon": 6 }, + "3654": { "label": "35/83", "naklon": null }, + "4086": { "label": "36/1", "naklon": 0 }, + "4085": { "label": "36/2", "naklon": 0 }, + "4083": { "label": "36/3", "naklon": 0 }, + "4087": { "label": "36/4", "naklon": 0 }, + "4077": { "label": "36/5", "naklon": 0 }, + "4082": { "label": "36/6", "naklon": 0 }, + "4186": { "label": "36/7", "naklon": 0 }, + "4206": { "label": "36/8", "naklon": 0 }, + "4080": { "label": "36/9", "naklon": 0 }, + "4081": { "label": "36/10", "naklon": 0 }, + "4210": { "label": "36/11", "naklon": 0 }, + "4079": { "label": "36/12", "naklon": 0 }, + "4076": { "label": "36/13", "naklon": 0 }, + "3852": { "label": "36/14", "naklon": 0 }, + "2813": { "label": "36/15", "naklon": 0 }, + "4219": { "label": "36/16", "naklon": 0 }, + "3104": { "label": "37/1A", "naklon": 15 }, + "3121": { "label": "37/1B", "naklon": 15 }, + "3113": { "label": "37/2", "naklon": 10 }, + "3118": { "label": "37/3", "naklon": 10 }, + "3111": { "label": "37/4", "naklon": 10 }, + "4020": { "label": "37/5", "naklon": 10 }, + "3119": { "label": "37/6", "naklon": 10 }, + "3110": { "label": "37/7", "naklon": 10 }, + "3108": { "label": "37/8", "naklon": 10 }, + "3107": { "label": "37/12", "naklon": 0 }, + "3199": { "label": "37/13", "naklon": 0 }, + "3120": { "label": "37/14", "naklon": 0 }, + "3122": { "label": "37/15", "naklon": 0 }, + "3908": { "label": "37/16", "naklon": 0 }, + "3114": { "label": "37/17", "naklon": 0 }, + "3105": { "label": "37/18", "naklon": 0 }, + "3116": { "label": "37/19", "naklon": 0 }, + "3106": { "label": "37/20", "naklon": 0 }, + "2887": { "label": "37/21", "naklon": 5 }, + "2888": { "label": "37/22", "naklon": 5 }, + "2877": { "label": "37/23", "naklon": 5 }, + "2891": { "label": "37/24", "naklon": 5 }, + "2886": { "label": "37/25", "naklon": 5 }, + "2892": { "label": "37/26", "naklon": 5 }, + "2882": { "label": "37/27", "naklon": 5 }, + "2883": { "label": "37/28", "naklon": 5 }, + "2876": { "label": "37/29", "naklon": 5 }, + "3109": { "label": "37/30", "naklon": 5 }, + "4152": { "label": "37/31", "naklon": 5 }, + "3117": { "label": "37/32", "naklon": 5 }, + "2870": { "label": "37/33", "naklon": 5 }, + "2867": { "label": "37/34", "naklon": 0 }, + "2865": { "label": "37/35", "naklon": 0 }, + "3096": { "label": "37/36", "naklon": 0 }, + "2871": { "label": "37/37", "naklon": 0 }, + "2884": { "label": "37/38", "naklon": 0 }, + "2855": { "label": "37/39", "naklon": 0 }, + "2878": { "label": "37/40", "naklon": 0 }, + "2889": { "label": "37/41", "naklon": 0 }, + "2879": { "label": "37/42", "naklon": 0 }, + "2850": { "label": "37/43", "naklon": 0 }, + "2894": { "label": "37/44", "naklon": 0 }, + "2880": { "label": "37/45", "naklon": 0 }, + "2893": { "label": "37/46", "naklon": 0 }, + "2890": { "label": "37/47", "naklon": 0 }, + "4355": { "label": "37/48", "naklon": 0 }, + "2885": { "label": "37/49", "naklon": 0 }, + "2875": { "label": "37/50", "naklon": 0 }, + "3486": { "label": "38/30A", "naklon": 5 }, + "3714": { "label": "38/30B", "naklon": 0 }, + "3483": { "label": "38/32A", "naklon": 5 }, + "3496": { "label": "38/32B", "naklon": 0 }, + "3487": { "label": "38/35A", "naklon": 5 }, + "3498": { "label": "38/35B", "naklon": 5 }, + "3578": { "label": "38/38A", "naklon": 5 }, + "3508": { "label": "38/38B", "naklon": 5 }, + "3787": { "label": "38/59A", "naklon": 5 }, + "3491": { "label": "38/59B", "naklon": 5 }, + "3568": { "label": "38/1", "naklon": null }, + "3502": { "label": "38/2", "naklon": 0 }, + "3836": { "label": "38/3", "naklon": 0 }, + "3588": { "label": "38/4", "naklon": 0 }, + "3493": { "label": "38/5", "naklon": 0 }, + "3580": { "label": "38/6", "naklon": 0 }, + "3572": { "label": "38/7", "naklon": 0 }, + "3506": { "label": "38/8", "naklon": 0 }, + "3503": { "label": "38/9", "naklon": 0 }, + "3579": { "label": "38/10", "naklon": 0 }, + "3586": { "label": "38/11", "naklon": 0 }, + "3495": { "label": "38/12", "naklon": 5 }, + "3492": { "label": "38/13", "naklon": 5 }, + "3532": { "label": "38/14", "naklon": 5 }, + "3574": { "label": "38/15", "naklon": 5 }, + "4140": { "label": "38/16", "naklon": 5 }, + "3795": { "label": "38/17", "naklon": 5 }, + "3788": { "label": "38/18", "naklon": 5 }, + "3796": { "label": "38/19", "naklon": 5 }, + "3797": { "label": "38/20", "naklon": 5 }, + "3798": { "label": "38/21", "naklon": 5 }, + "3786": { "label": "38/22", "naklon": 5 }, + "4067": { "label": "38/23", "naklon": 5 }, + "3773": { "label": "38/24", "naklon": 5 }, + "3774": { "label": "38/25", "naklon": 5 }, + "3789": { "label": "38/26", "naklon": 5 }, + "3520": { "label": "38/27", "naklon": null }, + "3577": { "label": "38/29", "naklon": 5 }, + "3530": { "label": "38/31", "naklon": null }, + "3488": { "label": "38/33", "naklon": 5 }, + "3505": { "label": "38/34", "naklon": 5 }, + "3497": { "label": "38/36", "naklon": 5 }, + "3490": { "label": "38/37", "naklon": 5 }, + "3585": { "label": "38/39", "naklon": 5 }, + "3582": { "label": "38/40", "naklon": 5 }, + "3507": { "label": "38/41", "naklon": 5 }, + "3484": { "label": "38/42", "naklon": 5 }, + "3501": { "label": "38/43", "naklon": 5 }, + "3581": { "label": "38/44", "naklon": 5 }, + "4192": { "label": "38/45", "naklon": 5 }, + "3576": { "label": "38/46", "naklon": 5 }, + "3489": { "label": "38/47", "naklon": 5 }, + "3573": { "label": "38/48", "naklon": 5 }, + "3504": { "label": "38/49", "naklon": 5 }, + "3794": { "label": "38/50", "naklon": 5 }, + "3485": { "label": "38/51", "naklon": 5 }, + "3482": { "label": "38/52", "naklon": 5 }, + "3575": { "label": "38/53", "naklon": 5 }, + "3499": { "label": "38/54", "naklon": 5 }, + "3494": { "label": "38/55", "naklon": 5 }, + "3583": { "label": "38/56", "naklon": 5 }, + "3570": { "label": "38/57", "naklon": 5 }, + "3500": { "label": "38/58", "naklon": 0 }, + "3510": { "label": "38/63", "naklon": null }, + "3512": { "label": "38/64", "naklon": null }, + "3535": { "label": "38/67", "naklon": null }, + "3531": { "label": "38/68", "naklon": null }, + "3537": { "label": "38/69", "naklon": null }, + "3522": { "label": "39/1", "naklon": 10 }, + "4018": { "label": "39/2", "naklon": 10 }, + "4019": { "label": "39/3", "naklon": 10 }, + "4154": { "label": "39/4", "naklon": 5 }, + "3907": { "label": "39/5", "naklon": 5 }, + "4148": { "label": "39/6", "naklon": 0 }, + "4153": { "label": "39/7", "naklon": 0 }, + "3938": { "label": "39/8", "naklon": 0 }, + "3802": { "label": "39/9", "naklon": 0 }, + "4015": { "label": "39/10", "naklon": 0 }, + "3929": { "label": "39/11", "naklon": 0 }, + "3946": { "label": "39/12", "naklon": 0 }, + "4014": { "label": "39/13", "naklon": 0 }, + "4155": { "label": "39/14", "naklon": 0 }, + "4149": { "label": "39/15", "naklon": 0 }, + "3642": { "label": "39/16", "naklon": 0 }, + "3636": { "label": "39/17", "naklon": 5 }, + "3991": { "label": "39/18", "naklon": 0 }, + "3994": { "label": "39/19", "naklon": 0 }, + "3990": { "label": "39/20", "naklon": 0 }, + "3967": { "label": "39/21", "naklon": 0 }, + "3977": { "label": "39/22", "naklon": 0 }, + "3757": { "label": "39/23", "naklon": 15 }, + "3633": { "label": "39/24", "naklon": 15 }, + "3744": { "label": "39/25", "naklon": 15 }, + "4023": { "label": "39/26", "naklon": 5 }, + "3720": { "label": "39/27", "naklon": 5 }, + "3734": { "label": "39/28", "naklon": 5 }, + "3741": { "label": "39/29", "naklon": 5 }, + "3721": { "label": "39/30", "naklon": 5 }, + "3845": { "label": "39/31", "naklon": 0 }, + "3840": { "label": "39/32", "naklon": 0 }, + "3837": { "label": "39/33", "naklon": null }, + "3839": { "label": "39/34", "naklon": 0 }, + "3542": { "label": "41/1", "naklon": null }, + "3566": { "label": "41/2", "naklon": null }, + "3548": { "label": "41/3", "naklon": null }, + "3515": { "label": "41/4", "naklon": null }, + "3559": { "label": "41/5", "naklon": null }, + "3509": { "label": "41/6", "naklon": null }, + "3524": { "label": "41/7", "naklon": null }, + "3518": { "label": "41/8", "naklon": null }, + "3182": { "label": "41/9", "naklon": null }, + "3187": { "label": "41/10", "naklon": null }, + "3195": { "label": "41/11", "naklon": 0 }, + "3857": { "label": "41/12", "naklon": 0 }, + "3183": { "label": "41/13", "naklon": 0 }, + "3177": { "label": "41/14", "naklon": 0 }, + "3189": { "label": "41/15", "naklon": 0 }, + "3186": { "label": "41/16", "naklon": 0 }, + "3178": { "label": "42/1", "naklon": 0 }, + "3219": { "label": "42/2", "naklon": 0 }, + "3475": { "label": "42/3", "naklon": 0 }, + "3175": { "label": "42/4", "naklon": 0 }, + "3222": { "label": "42/5", "naklon": 0 }, + "3221": { "label": "42/6", "naklon": 0 }, + "3181": { "label": "42/7", "naklon": 0 }, + "3180": { "label": "42/8", "naklon": 0 }, + "3218": { "label": "42/9", "naklon": 0 }, + "3176": { "label": "42/10", "naklon": 0 }, + "3174": { "label": "42/11", "naklon": 0 }, + "3220": { "label": "42/12", "naklon": 0 }, + "3533": { "label": "42/13", "naklon": null }, + "3543": { "label": "42/14", "naklon": null }, + "3554": { "label": "42/15", "naklon": null }, + "3549": { "label": "42/16", "naklon": null }, + "2857": { "label": "43/1", "naklon": 5 }, + "2752": { "label": "43/2", "naklon": 5 }, + "2753": { "label": "43/3", "naklon": 5 }, + "3024": { "label": "43/4", "naklon": 5 }, + "2754": { "label": "43/5", "naklon": 5 }, + "4423": { "label": "43/6", "naklon": 5 }, + "4368": { "label": "43/7", "naklon": 5 }, + "2978": { "label": "43/8", "naklon": 5 }, + "2868": { "label": "43/9", "naklon": 5 }, + "4377": { "label": "43/10", "naklon": 5 }, + "2757": { "label": "43/11", "naklon": 5 }, + "2970": { "label": "43/12", "naklon": 5 }, + "2758": { "label": "43/13", "naklon": 5 }, + "4378": { "label": "43/14", "naklon": 5 }, + "2759": { "label": "43/15", "naklon": 5 }, + "4342": { "label": "43/16", "naklon": 5 }, + "3026": { "label": "43/17", "naklon": null }, + "2986": { "label": "43/18", "naklon": null }, + "4343": { "label": "43/19", "naklon": null }, + "2760": { "label": "43/20", "naklon": null }, + "4379": { "label": "43/21", "naklon": null }, + "2971": { "label": "43/22", "naklon": null }, + "2761": { "label": "43/23", "naklon": null }, + "2762": { "label": "43/24", "naklon": null }, + "4339": { "label": "43/25", "naklon": null }, + "4380": { "label": "43/26", "naklon": null }, + "2975": { "label": "43/27", "naklon": null }, + "3003": { "label": "43/28", "naklon": null }, + "4338": { "label": "43/29", "naklon": null }, + "3002": { "label": "43/30", "naklon": null }, + "4345": { "label": "43/31", "naklon": null }, + "2979": { "label": "43/32", "naklon": null }, + "2989": { "label": "43/33", "naklon": null }, + "2996": { "label": "43/34", "naklon": null }, + "2972": { "label": "43/35", "naklon": null }, + "2988": { "label": "43/36", "naklon": null }, + "4344": { "label": "43/37", "naklon": null }, + "3022": { "label": "43/38", "naklon": null }, + "4341": { "label": "43/39", "naklon": null }, + "2983": { "label": "43/40", "naklon": null }, + "2995": { "label": "43/41", "naklon": null }, + "2763": { "label": "43/42", "naklon": null }, + "2764": { "label": "43/43", "naklon": null }, + "2765": { "label": "43/44", "naklon": null }, + "2766": { "label": "43/45", "naklon": null }, + "2767": { "label": "43/46", "naklon": null }, + "2768": { "label": "43/47", "naklon": null }, + "3018": { "label": "43/48", "naklon": null }, + "2982": { "label": "43/49", "naklon": null }, + "3019": { "label": "43/50", "naklon": 0 }, + "3013": { "label": "43/51", "naklon": null }, + "3007": { "label": "43/52", "naklon": null }, + "2980": { "label": "43/53", "naklon": null }, + "3011": { "label": "43/54", "naklon": null }, + "2672": { "label": "43/55", "naklon": null }, + "2673": { "label": "43/56", "naklon": null }, + "2674": { "label": "43/57", "naklon": null }, + "2675": { "label": "43/58", "naklon": null }, + "2676": { "label": "43/59", "naklon": null }, + "2677": { "label": "43/60", "naklon": null }, + "2678": { "label": "43/61", "naklon": null }, + "2679": { "label": "43/62", "naklon": null }, + "2680": { "label": "43/63", "naklon": null }, + "2840": { "label": "43/64", "naklon": null }, + "2682": { "label": "43/65", "naklon": null }, + "2683": { "label": "43/66", "naklon": null }, + "2684": { "label": "43/67", "naklon": 0 }, + "2685": { "label": "43/68", "naklon": null }, + "2686": { "label": "43/69", "naklon": null }, + "2687": { "label": "43/70", "naklon": null }, + "2688": { "label": "43/71", "naklon": null }, + "2689": { "label": "43/72", "naklon": null }, + "2690": { "label": "43/73", "naklon": null }, + "2691": { "label": "43/74", "naklon": null }, + "2692": { "label": "43/75", "naklon": null }, + "2693": { "label": "43/76", "naklon": 0 }, + "2694": { "label": "43/77", "naklon": null }, + "2695": { "label": "43/78", "naklon": null }, + "2696": { "label": "43/79", "naklon": 0 }, + "2697": { "label": "43/80", "naklon": null }, + "2698": { "label": "43/81", "naklon": 0 }, + "2699": { "label": "43/82", "naklon": null }, + "2700": { "label": "43/83", "naklon": 0 }, + "2744": { "label": "43/84", "naklon": null }, + "2745": { "label": "43/85", "naklon": 0 }, + "2746": { "label": "43/86", "naklon": null }, + "2747": { "label": "43/87", "naklon": 0 }, + "2748": { "label": "43/88", "naklon": null }, + "2749": { "label": "43/89", "naklon": 0 }, + "2841": { "label": "43/90", "naklon": null }, + "4237": { "label": "45/1", "naklon": 5 }, + "4226": { "label": "45/2", "naklon": 5 }, + "4242": { "label": "45/3", "naklon": 5 }, + "4179": { "label": "45/4", "naklon": 5 }, + "4247": { "label": "45/5", "naklon": 5 }, + "4245": { "label": "45/6", "naklon": 5 }, + "3872": { "label": "45/7", "naklon": 5 }, + "4175": { "label": "45/8", "naklon": 5 }, + "4236": { "label": "45/9", "naklon": 5 }, + "4170": { "label": "45/10", "naklon": 5 }, + "4238": { "label": "45/11", "naklon": 5 }, + "4246": { "label": "45/12", "naklon": 5 }, + "4166": { "label": "45/13", "naklon": 5 }, + "4227": { "label": "45/14", "naklon": 5 }, + "4171": { "label": "45/15", "naklon": 5 }, + "4180": { "label": "45/16", "naklon": 5 }, + "4244": { "label": "45/17", "naklon": 5 }, + "4199": { "label": "45/18", "naklon": 5 }, + "4239": { "label": "45/19", "naklon": 5 }, + "4207": { "label": "45/20", "naklon": 5 }, + "4223": { "label": "45/21", "naklon": 5 }, + "4230": { "label": "45/22", "naklon": 5 }, + "4233": { "label": "45/23", "naklon": 5 }, + "4222": { "label": "45/24", "naklon": 5 }, + "4217": { "label": "45/25", "naklon": 5 }, + "4243": { "label": "45/26", "naklon": 5 }, + "4200": { "label": "45/27", "naklon": 5 }, + "4228": { "label": "45/28", "naklon": 5 }, + "4211": { "label": "45/29", "naklon": 5 }, + "4234": { "label": "45/30", "naklon": 5 }, + "4235": { "label": "45/31", "naklon": 5 }, + "4203": { "label": "45/32", "naklon": 5 }, + "4240": { "label": "45/33", "naklon": 5 }, + "4224": { "label": "45/34", "naklon": 5 }, + "4232": { "label": "45/35", "naklon": 5 }, + "4231": { "label": "45/36", "naklon": 5 }, + "4161": { "label": "45/37", "naklon": 5 }, + "4225": { "label": "45/38", "naklon": 5 }, + "4241": { "label": "45/39", "naklon": 5 }, + "4229": { "label": "45/40", "naklon": 5 }, + "4221": { "label": "45/41", "naklon": 5 }, + "4212": { "label": "45/42", "naklon": 5 }, + "4216": { "label": "45/43", "naklon": 5 }, + "3864": { "label": "45/44", "naklon": null }, + "3806": { "label": "46/1", "naklon": 5 }, + "3813": { "label": "46/2", "naklon": 5 }, + "3815": { "label": "46/3", "naklon": 5 }, + "3807": { "label": "46/4", "naklon": 5 }, + "3895": { "label": "46/5", "naklon": 5 }, + "3809": { "label": "46/6", "naklon": 5 }, + "3820": { "label": "46/7", "naklon": 5 }, + "3805": { "label": "46/8", "naklon": 5 }, + "3894": { "label": "46/9", "naklon": 0 }, + "4055": { "label": "46/10", "naklon": 0 }, + "3812": { "label": "46/11", "naklon": 5 }, + "3822": { "label": "46/12", "naklon": 5 }, + "3821": { "label": "46/13", "naklon": 5 }, + "3808": { "label": "46/14", "naklon": 5 }, + "3799": { "label": "46/15", "naklon": 5 }, + "3816": { "label": "46/16", "naklon": 5 }, + "3751": { "label": "46/17", "naklon": 5 }, + "3814": { "label": "46/18", "naklon": 5 }, + "4044": { "label": "46/19", "naklon": 0 }, + "3931": { "label": "46/20", "naklon": 0 }, + "3902": { "label": "46/21", "naklon": 5 }, + "3916": { "label": "46/22", "naklon": 5 }, + "3892": { "label": "46/23", "naklon": 5 }, + "3914": { "label": "46/24", "naklon": 5 }, + "3898": { "label": "46/25", "naklon": 5 }, + "3897": { "label": "46/26", "naklon": 5 }, + "3885": { "label": "46/27", "naklon": 5 }, + "3906": { "label": "46/28", "naklon": 5 }, + "3930": { "label": "46/29", "naklon": 0 }, + "3936": { "label": "46/30", "naklon": 0 }, + "3860": { "label": "46/31", "naklon": 5 }, + "3841": { "label": "46/32", "naklon": 5 }, + "3873": { "label": "46/33", "naklon": 5 }, + "3854": { "label": "46/34", "naklon": 5 }, + "3939": { "label": "46/35", "naklon": 5 }, + "3858": { "label": "46/36", "naklon": 5 }, + "3940": { "label": "46/37", "naklon": 5 }, + "4035": { "label": "46/38", "naklon": 5 }, + "3373": { "label": "47/1", "naklon": 0 }, + "3374": { "label": "47/2", "naklon": 0 }, + "3384": { "label": "47/3", "naklon": 0 }, + "3385": { "label": "47/4", "naklon": 0 }, + "4051": { "label": "48/1", "naklon": 5 }, + "4041": { "label": "48/2", "naklon": 5 }, + "4056": { "label": "48/3", "naklon": 5 }, + "3875": { "label": "48/4", "naklon": 5 }, + "4061": { "label": "48/5", "naklon": 5 }, + "4047": { "label": "48/6", "naklon": 5 }, + "4060": { "label": "48/7", "naklon": 5 }, + "4059": { "label": "48/8", "naklon": 5 }, + "4058": { "label": "48/9", "naklon": 5 }, + "3635": { "label": "48/10", "naklon": 5 }, + "3640": { "label": "48/11", "naklon": 5 }, + "3747": { "label": "48/12", "naklon": 5 }, + "3629": { "label": "48/13", "naklon": 5 }, + "4048": { "label": "48/14", "naklon": 5 }, + "4063": { "label": "48/15", "naklon": 5 }, + "4062": { "label": "48/16", "naklon": 5 }, + "4043": { "label": "48/17", "naklon": 5 }, + "4052": { "label": "48/18", "naklon": 5 }, + "4042": { "label": "48/19", "naklon": 5 }, + "4053": { "label": "48/20", "naklon": 5 }, + "4167": { "label": "50/15A", "naklon": null }, + "4159": { "label": "50/15B", "naklon": null }, + "4183": { "label": "50/1", "naklon": 0 }, + "4157": { "label": "50/2", "naklon": 0 }, + "4160": { "label": "50/3", "naklon": 0 }, + "4173": { "label": "50/4", "naklon": 0 }, + "4177": { "label": "50/5", "naklon": 0 }, + "4174": { "label": "50/6", "naklon": 0 }, + "4178": { "label": "50/7", "naklon": 0 }, + "4195": { "label": "50/8", "naklon": 0 }, + "4169": { "label": "50/9", "naklon": 0 }, + "4162": { "label": "50/10", "naklon": 0 }, + "4158": { "label": "50/11", "naklon": 0 }, + "4182": { "label": "50/12", "naklon": 0 }, + "4194": { "label": "50/13", "naklon": 0 }, + "4184": { "label": "50/14", "naklon": 0 }, + "4197": { "label": "50/16", "naklon": null }, + "4164": { "label": "50/17", "naklon": null }, + "3306": { "label": "50/18", "naklon": null }, + "4168": { "label": "50/19", "naklon": null }, + "4193": { "label": "50/20", "naklon": null }, + "4187": { "label": "50/21", "naklon": null }, + "4163": { "label": "50/22", "naklon": null }, + "4165": { "label": "50/23", "naklon": null }, + "4185": { "label": "50/24", "naklon": null }, + "3904": { "label": "50/25", "naklon": null }, + "2619": { "label": "53/1", "naklon": 0 }, + "2623": { "label": "53/2", "naklon": 0 }, + "2617": { "label": "53/3", "naklon": 0 }, + "2622": { "label": "53/4", "naklon": 0 }, + "2618": { "label": "53/5", "naklon": 0 }, + "2626": { "label": "53/6", "naklon": 0 }, + "2869": { "label": "53/7", "naklon": 0 }, + "2613": { "label": "53/8", "naklon": 0 }, + "2608": { "label": "53/9", "naklon": 0 }, + "2611": { "label": "53/10", "naklon": 0 }, + "2598": { "label": "53/11", "naklon": 0 }, + "3528": { "label": "53/12", "naklon": 0 }, + "3545": { "label": "53/13", "naklon": 0 }, + "2620": { "label": "53/14", "naklon": 0 }, + "2612": { "label": "53/15", "naklon": 0 }, + "2615": { "label": "53/16", "naklon": 0 }, + "3722": { "label": "53/17", "naklon": 0 }, + "2624": { "label": "53/18", "naklon": 0 }, + "2609": { "label": "53/19", "naklon": 0 }, + "2625": { "label": "53/20", "naklon": 0 }, + "2602": { "label": "53/21", "naklon": 0 }, + "2610": { "label": "53/22", "naklon": 0 }, + "2599": { "label": "53/23", "naklon": 0 }, + "2605": { "label": "53/24", "naklon": 0 }, + "2593": { "label": "53/25", "naklon": 0 }, + "3074": { "label": "53/26", "naklon": 0 }, + "2740": { "label": "53/27", "naklon": 0 }, + "2614": { "label": "53/28", "naklon": 0 }, + "2601": { "label": "53/29", "naklon": 0 }, + "4196": { "label": "53/30", "naklon": 0 }, + "2607": { "label": "53/31", "naklon": 0 }, + "2582": { "label": "53/32", "naklon": 0 }, + "2594": { "label": "53/33", "naklon": 0 }, + "2589": { "label": "53/34", "naklon": 0 }, + "2596": { "label": "53/35", "naklon": 0 }, + "2603": { "label": "53/36", "naklon": 0 }, + "2597": { "label": "53/37", "naklon": 0 }, + "2590": { "label": "53/38", "naklon": 0 }, + "2581": { "label": "53/39", "naklon": 0 }, + "2583": { "label": "53/40", "naklon": 0 }, + "2580": { "label": "53/41", "naklon": 0 }, + "2579": { "label": "53/42", "naklon": 0 }, + "2797": { "label": "53/43", "naklon": 0 }, + "2577": { "label": "53/44", "naklon": 0 }, + "2586": { "label": "53/45", "naklon": 0 }, + "2588": { "label": "53/46", "naklon": 0 }, + "2591": { "label": "53/47", "naklon": 0 }, + "2592": { "label": "53/48", "naklon": 0 }, + "2573": { "label": "53/49", "naklon": 0 }, + "2595": { "label": "53/50", "naklon": 0 }, + "2587": { "label": "53/51", "naklon": 0 }, + "2578": { "label": "53/52", "naklon": 0 }, + "2574": { "label": "53/53", "naklon": 0 }, + "2571": { "label": "53/54", "naklon": 0 }, + "2570": { "label": "53/55", "naklon": 0 }, + "2576": { "label": "53/56", "naklon": 0 }, + "2881": { "label": "53/57", "naklon": 0 }, + "2575": { "label": "53/58", "naklon": 0 }, + "2572": { "label": "53/59", "naklon": 0 }, + "2569": { "label": "53/60", "naklon": 0 }, + "4324": { "label": "55/1", "naklon": 0 }, + "4319": { "label": "55/2", "naklon": 0 }, + "4327": { "label": "55/3", "naklon": 0 }, + "4333": { "label": "55/4", "naklon": 0 }, + "4332": { "label": "55/5", "naklon": 0 }, + "4320": { "label": "55/6", "naklon": 0 }, + "4317": { "label": "55/7", "naklon": 0 }, + "4318": { "label": "55/8", "naklon": 0 }, + "4328": { "label": "55/9", "naklon": 0 }, + "4323": { "label": "55/10", "naklon": 0 }, + "4325": { "label": "55/11", "naklon": 0 }, + "4326": { "label": "55/12", "naklon": 0 }, + "4316": { "label": "55/13", "naklon": 0 }, + "4322": { "label": "55/14", "naklon": 0 }, + "4331": { "label": "55/15", "naklon": 0 }, + "4321": { "label": "55/16", "naklon": 0 }, + "4315": { "label": "55/17", "naklon": 0 }, + "4329": { "label": "55/18", "naklon": 0 }, + "4334": { "label": "55/19", "naklon": 0 }, + "4330": { "label": "55/20", "naklon": 0 } +}; + + +let svetlaSorted = [{ "label": "1/3A", "node": 3993, "naklon": 0 }, +{ "label": "1/3B", "node": 3989, "naklon": 15 }, +{ "label": "1/1", "node": 3976, "naklon": 0 }, +{ "label": "1/2", "node": 4181, "naklon": 0 }, +{ "label": "1/4", "node": 4376, "naklon": 15 }, +{ "label": "1/5", "node": 3868, "naklon": 15 }, +{ "label": "1/6", "node": 3728, "naklon": 15 }, +{ "label": "1/7", "node": 3730, "naklon": 0 }, +{ "label": "1/8", "node": 4374, "naklon": 0 }, +{ "label": "1/9", "node": 3718, "naklon": 15 }, +{ "label": "1/10", "node": 4375, "naklon": 15 }, +{ "label": "1/11", "node": 4172, "naklon": 15 }, +{ "label": "1/12", "node": 4176, "naklon": 15 }, +{ "label": "2/1", "node": 3800, "naklon": 5 }, +{ "label": "2/2", "node": 3823, "naklon": 5 }, +{ "label": "2/3", "node": 3905, "naklon": 5 }, +{ "label": "2/4", "node": 3803, "naklon": 5 }, +{ "label": "2/5", "node": 3817, "naklon": 5 }, +{ "label": "2/6", "node": 3818, "naklon": 5 }, +{ "label": "2/7", "node": 3811, "naklon": 5 }, +{ "label": "2/8", "node": 3915, "naklon": 5 }, +{ "label": "2/9", "node": 3843, "naklon": 10 }, +{ "label": "2/10", "node": 3827, "naklon": 10 }, +{ "label": "2/11", "node": 4220, "naklon": 10 }, +{ "label": "2/12", "node": 3826, "naklon": 10 }, +{ "label": "2/13", "node": 3834, "naklon": 10 }, +{ "label": "2/14", "node": 3838, "naklon": 10 }, +{ "label": "2/15", "node": 2823, "naklon": 10 }, +{ "label": "2/16", "node": 3750, "naklon": 10 }, +{ "label": "2/17", "node": 3378, "naklon": 0 }, +{ "label": "2/18", "node": 3376, "naklon": 0 }, +{ "label": "2/19", "node": 3379, "naklon": 0 }, +{ "label": "2/20", "node": 3285, "naklon": 0 }, +{ "label": "2/21", "node": 3382, "naklon": 0 }, +{ "label": "2/22", "node": 3383, "naklon": 0 }, +{ "label": "2/24", "node": 3375, "naklon": 0 }, +{ "label": "2/25", "node": 3381, "naklon": 0 }, +{ "label": "2/26", "node": 3380, "naklon": 0 }, +{ "label": "2/27", "node": 3828, "naklon": 10 }, +{ "label": "2/28", "node": 3377, "naklon": 0 }, +{ "label": "7/1", "node": 3591, "naklon": 0 }, +{ "label": "7/2", "node": 3587, "naklon": 0 }, +{ "label": "7/3", "node": 3468, "naklon": 0 }, +{ "label": "7/4", "node": 3466, "naklon": 0 }, +{ "label": "7/5", "node": 3474, "naklon": 0 }, +{ "label": "7/6", "node": 3481, "naklon": 0 }, +{ "label": "7/7", "node": 3589, "naklon": 0 }, +{ "label": "7/8", "node": 3472, "naklon": 0 }, +{ "label": "7/9", "node": 3473, "naklon": 0 }, +{ "label": "7/10", "node": 3584, "naklon": 0 }, +{ "label": "7/11", "node": 3571, "naklon": 0 }, +{ "label": "7/12", "node": 3476, "naklon": 0 }, +{ "label": "7/13", "node": 3590, "naklon": 0 }, +{ "label": "7/14", "node": 3478, "naklon": 0 }, +{ "label": "7/15", "node": 3471, "naklon": 0 }, +{ "label": "7/16", "node": 3467, "naklon": 0 }, +{ "label": "7/17", "node": 3479, "naklon": 0 }, +{ "label": "7/18", "node": 3480, "naklon": 0 }, +{ "label": "7/19", "node": 3477, "naklon": 0 }, +{ "label": "12/1", "node": 3362, "naklon": 0 }, +{ "label": "12/2", "node": 3355, "naklon": 0 }, +{ "label": "12/3", "node": 3356, "naklon": 0 }, +{ "label": "12/4", "node": 3349, "naklon": 0 }, +{ "label": "12/5", "node": 3357, "naklon": 0 }, +{ "label": "12/6", "node": 3350, "naklon": 0 }, +{ "label": "12/7", "node": 3353, "naklon": 0 }, +{ "label": "12/8", "node": 3539, "naklon": 0 }, +{ "label": "12/9", "node": 3050, "naklon": 0 }, +{ "label": "12/10", "node": 3361, "naklon": 0 }, +{ "label": "12/11", "node": 3360, "naklon": 0 }, +{ "label": "12/12", "node": 3358, "naklon": 0 }, +{ "label": "12/13", "node": 3541, "naklon": 0 }, +{ "label": "12/14", "node": 3551, "naklon": 0 }, +{ "label": "12/15", "node": 3514, "naklon": 0 }, +{ "label": "12/16", "node": 3547, "naklon": 0 }, +{ "label": "12/17", "node": 3562, "naklon": 0 }, +{ "label": "12/18", "node": 3525, "naklon": 0 }, +{ "label": "12/19", "node": 3558, "naklon": 0 }, +{ "label": "12/20", "node": 3511, "naklon": 0 }, +{ "label": "12/21", "node": 3058, "naklon": 0 }, +{ "label": "12/22", "node": 3062, "naklon": 0 }, +{ "label": "12/23", "node": 3070, "naklon": 0 }, +{ "label": "12/24", "node": 3447, "naklon": 0 }, +{ "label": "12/25", "node": 3056, "naklon": 0 }, +{ "label": "12/26", "node": 3057, "naklon": 0 }, +{ "label": "12/27", "node": 3071, "naklon": 0 }, +{ "label": "12/28", "node": 3061, "naklon": 0 }, +{ "label": "12/29", "node": 3069, "naklon": 0 }, +{ "label": "12/30", "node": 3077, "naklon": 0 }, +{ "label": "12/31", "node": 3080, "naklon": 0 }, +{ "label": "12/32", "node": 3081, "naklon": 0 }, +{ "label": "12/33", "node": 3078, "naklon": 0 }, +{ "label": "12/34", "node": 4037, "naklon": 0 }, +{ "label": "12/35", "node": 3067, "naklon": 0 }, +{ "label": "12/36", "node": 3051, "naklon": 0 }, +{ "label": "12/37", "node": 2924, "naklon": 0 }, +{ "label": "12/38", "node": 3060, "naklon": 0 }, +{ "label": "12/39", "node": 3073, "naklon": 0 }, +{ "label": "12/40", "node": 3469, "naklon": 0 }, +{ "label": "12/41", "node": 2923, "naklon": 0 }, +{ "label": "12/42", "node": 2925, "naklon": 0 }, +{ "label": "12/43", "node": 3359, "naklon": 0 }, +{ "label": "12/44", "node": 3055, "naklon": 0 }, +{ "label": "12/45", "node": 2922, "naklon": 0 }, +{ "label": "12/46", "node": 3084, "naklon": 0 }, +{ "label": "12/47", "node": 3064, "naklon": 0 }, +{ "label": "12/48", "node": 3066, "naklon": 0 }, +{ "label": "12/49", "node": 3072, "naklon": 0 }, +{ "label": "13/13A", "node": 3415, "naklon": 0 }, +{ "label": "13/13B", "node": 3409, "naklon": 0 }, +{ "label": "13/13C", "node": 3399, "naklon": 0 }, +{ "label": "13/29A", "node": 3410, "naklon": 0 }, +{ "label": "13/29B", "node": 3407, "naklon": 0 }, +{ "label": "13/34A", "node": 3405, "naklon": 0 }, +{ "label": "13/34B", "node": 3404, "naklon": 0 }, +{ "label": "13/45A", "node": 3392, "naklon": 0 }, +{ "label": "13/45B", "node": 3386, "naklon": 0 }, +{ "label": "13/60A", "node": 3303, "naklon": 3 }, +{ "label": "13/60B", "node": 3302, "naklon": 3 }, +{ "label": "13/70A", "node": 3319, "naklon": 6 }, +{ "label": "13/70B", "node": 3317, "naklon": 6 }, +{ "label": "13/70C", "node": 3326, "naklon": 6 }, +{ "label": "13/73A", "node": 3351, "naklon": 6 }, +{ "label": "13/73B", "node": 3313, "naklon": 6 }, +{ "label": "13/83A", "node": 3316, "naklon": 0 }, +{ "label": "13/83B", "node": 3320, "naklon": 0 }, +{ "label": "13/95A", "node": 3336, "naklon": 0 }, +{ "label": "13/95B", "node": 3323, "naklon": 0 }, +{ "label": "13/98A", "node": 3339, "naklon": 0 }, +{ "label": "13/98B", "node": 3333, "naklon": 0 }, +{ "label": "13/1", "node": 3425, "naklon": 0 }, +{ "label": "13/2", "node": 3419, "naklon": 0 }, +{ "label": "13/3", "node": 3416, "naklon": 0 }, +{ "label": "13/4", "node": 3332, "naklon": 0 }, +{ "label": "13/5", "node": 3422, "naklon": 0 }, +{ "label": "13/6", "node": 3417, "naklon": 0 }, +{ "label": "13/7", "node": 3418, "naklon": 0 }, +{ "label": "13/8", "node": 3424, "naklon": 0 }, +{ "label": "13/9", "node": 3334, "naklon": 0 }, +{ "label": "13/10", "node": 4363, "naklon": 0 }, +{ "label": "13/11", "node": 3423, "naklon": 0 }, +{ "label": "13/12", "node": 3406, "naklon": 0 }, +{ "label": "13/14", "node": 3411, "naklon": 0 }, +{ "label": "13/15", "node": 3412, "naklon": 0 }, +{ "label": "13/16", "node": 3413, "naklon": 0 }, +{ "label": "13/17", "node": 3414, "naklon": 0 }, +{ "label": "13/18", "node": 3391, "naklon": 0 }, +{ "label": "13/19", "node": 3370, "naklon": 0 }, +{ "label": "13/20", "node": 3369, "naklon": 0 }, +{ "label": "13/21", "node": 3408, "naklon": 0 }, +{ "label": "13/22", "node": 3393, "naklon": 0 }, +{ "label": "13/23", "node": 3128, "naklon": 0 }, +{ "label": "13/24", "node": 3197, "naklon": 0 }, +{ "label": "13/25", "node": 4364, "naklon": 0 }, +{ "label": "13/26", "node": 3155, "naklon": 0 }, +{ "label": "13/27", "node": 3196, "naklon": 0 }, +{ "label": "13/28", "node": 3144, "naklon": 0 }, +{ "label": "13/30", "node": 3150, "naklon": 0 }, +{ "label": "13/31", "node": 3390, "naklon": 0 }, +{ "label": "13/32", "node": 3401, "naklon": 0 }, +{ "label": "13/33", "node": 3275, "naklon": 0 }, +{ "label": "13/35", "node": 3371, "naklon": 0 }, +{ "label": "13/36", "node": 3389, "naklon": 0 }, +{ "label": "13/37", "node": 3388, "naklon": 0 }, +{ "label": "13/38", "node": 3365, "naklon": 0 }, +{ "label": "13/39", "node": 3363, "naklon": 0 }, +{ "label": "13/40", "node": 3397, "naklon": 0 }, +{ "label": "13/40/1", "node": 3567, "naklon": 0 }, +{ "label": "13/41", "node": 3387, "naklon": 0 }, +{ "label": "13/42", "node": 3403, "naklon": 0 }, +{ "label": "13/43", "node": 3147, "naklon": 0 }, +{ "label": "13/44", "node": 3141, "naklon": 0 }, +{ "label": "13/46", "node": 3364, "naklon": 0 }, +{ "label": "13/47", "node": 3367, "naklon": 0 }, +{ "label": "13/48", "node": 3368, "naklon": 0 }, +{ "label": "13/49", "node": 3402, "naklon": 0 }, +{ "label": "13/50", "node": 3366, "naklon": 0 }, +{ "label": "13/51", "node": 3395, "naklon": 0 }, +{ "label": "13/52", "node": 3372, "naklon": 0 }, +{ "label": "13/53", "node": 3394, "naklon": 0 }, +{ "label": "13/54", "node": 3308, "naklon": 0 }, +{ "label": "13/54/1", "node": 3847, "naklon": 0 }, +{ "label": "13/55", "node": 3312, "naklon": 3 }, +{ "label": "13/56", "node": 3309, "naklon": 3 }, +{ "label": "13/57", "node": 3311, "naklon": 3 }, +{ "label": "13/58", "node": 3310, "naklon": 3 }, +{ "label": "13/59", "node": 4365, "naklon": 3 }, +{ "label": "13/60/1", "node": 4093, "naklon": 3 }, +{ "label": "13/61", "node": 3304, "naklon": 3 }, +{ "label": "13/62", "node": 3307, "naklon": 3 }, +{ "label": "13/63", "node": 3271, "naklon": 3 }, +{ "label": "13/64", "node": 3301, "naklon": 3 }, +{ "label": "13/65", "node": 4366, "naklon": 3 }, +{ "label": "13/66", "node": 3300, "naklon": 3 }, +{ "label": "13/67", "node": 3185, "naklon": 0 }, +{ "label": "13/68", "node": 3184, "naklon": 0 }, +{ "label": "13/69", "node": 3188, "naklon": 0 }, +{ "label": "13/71", "node": 3343, "naklon": 6 }, +{ "label": "13/71/1", "node": 3819, "naklon": 6 }, +{ "label": "13/71/2", "node": 3880, "naklon": 6 }, +{ "label": "13/72", "node": 3348, "naklon": 6 }, +{ "label": "13/74", "node": 3344, "naklon": 6 }, +{ "label": "13/75", "node": 3346, "naklon": 6 }, +{ "label": "13/75/1", "node": 3597, "naklon": 6 }, +{ "label": "13/76", "node": 3345, "naklon": 6 }, +{ "label": "13/77", "node": 3322, "naklon": 0 }, +{ "label": "13/78", "node": 3325, "naklon": 0 }, +{ "label": "13/78/1", "node": 4310, "naklon": 0 }, +{ "label": "13/79", "node": 3315, "naklon": 0 }, +{ "label": "13/80", "node": 3328, "naklon": 0 }, +{ "label": "13/81", "node": 3321, "naklon": 0 }, +{ "label": "13/82", "node": 3324, "naklon": 0 }, +{ "label": "13/84", "node": 3140, "naklon": 0 }, +{ "label": "13/85", "node": 3153, "naklon": 0 }, +{ "label": "13/86", "node": 3145, "naklon": 0 }, +{ "label": "13/87", "node": 3134, "naklon": 0 }, +{ "label": "13/88", "node": 3151, "naklon": 0 }, +{ "label": "13/89", "node": 3143, "naklon": 0 }, +{ "label": "13/90", "node": 3318, "naklon": 0 }, +{ "label": "13/91", "node": 3347, "naklon": 0 }, +{ "label": "13/94", "node": 3314, "naklon": 0 }, +{ "label": "13/96", "node": 3331, "naklon": 0 }, +{ "label": "13/97", "node": 3327, "naklon": 0 }, +{ "label": "13/99", "node": 3329, "naklon": 0 }, +{ "label": "13/100", "node": 3337, "naklon": 0 }, +{ "label": "13/101", "node": 3330, "naklon": 0 }, +{ "label": "13/102", "node": 3335, "naklon": 0 }, +{ "label": "13/103", "node": 3420, "naklon": 0 }, +{ "label": "13/104", "node": 3421, "naklon": 0 }, +{ "label": "13/105", "node": 4361, "naklon": 0 }, +{ "label": "13/106", "node": 4362, "naklon": 0 }, +{ "label": "13/107", "node": 3526, "naklon": 0 }, +{ "label": "13/108", "node": 4424, "naklon": null }, +{ "label": "13/109", "node": 3561, "naklon": null }, +{ "label": "13/110", "node": 3527, "naklon": null }, +{ "label": "13/111", "node": 3521, "naklon": null }, +{ "label": "13/112", "node": 3552, "naklon": null }, +{ "label": "13/113", "node": 3544, "naklon": null }, +{ "label": "13/114", "node": 3534, "naklon": null }, +{ "label": "13/115", "node": 3516, "naklon": null }, +{ "label": "13/116", "node": 3513, "naklon": null }, +{ "label": "13/117", "node": 3565, "naklon": null }, +{ "label": "13/118", "node": 3866, "naklon": null }, +{ "label": "14/1", "node": 3136, "naklon": 0 }, +{ "label": "14/2", "node": 3137, "naklon": 0 }, +{ "label": "14/3", "node": 3135, "naklon": 0 }, +{ "label": "14/4", "node": 3149, "naklon": 0 }, +{ "label": "14/5", "node": 3142, "naklon": 0 }, +{ "label": "14/6", "node": 3342, "naklon": 0 }, +{ "label": "14/7", "node": 3340, "naklon": 0 }, +{ "label": "14/8", "node": 3152, "naklon": 0 }, +{ "label": "14/9", "node": 3886, "naklon": 0 }, +{ "label": "14/10", "node": 3341, "naklon": null }, +{ "label": "14/11", "node": 3352, "naklon": null }, +{ "label": "15/1", "node": 3396, "naklon": 5 }, +{ "label": "15/2", "node": 2784, "naklon": 5 }, +{ "label": "15/3", "node": 2788, "naklon": 5 }, +{ "label": "15/4", "node": 2801, "naklon": 5 }, +{ "label": "15/5", "node": 2815, "naklon": 5 }, +{ "label": "15/6", "node": 2829, "naklon": 5 }, +{ "label": "15/7", "node": 2796, "naklon": 5 }, +{ "label": "15/8", "node": 2803, "naklon": 5 }, +{ "label": "15/8/1", "node": 4304, "naklon": 5 }, +{ "label": "15/8/2", "node": 4311, "naklon": 5 }, +{ "label": "15/9", "node": 2821, "naklon": 5 }, +{ "label": "15/10", "node": 3400, "naklon": 5 }, +{ "label": "15/11", "node": 2799, "naklon": 5 }, +{ "label": "15/12", "node": 2804, "naklon": 5 }, +{ "label": "15/12/1", "node": 4303, "naklon": 5 }, +{ "label": "15/12/2", "node": 4309, "naklon": 5 }, +{ "label": "15/13", "node": 2806, "naklon": 5 }, +{ "label": "15/14", "node": 2787, "naklon": 5 }, +{ "label": "15/15", "node": 2809, "naklon": 5 }, +{ "label": "15/16", "node": 2814, "naklon": 0 }, +{ "label": "15/17", "node": 3934, "naklon": 0 }, +{ "label": "15/18", "node": 3192, "naklon": 0 }, +{ "label": "15/19", "node": 2812, "naklon": 0 }, +{ "label": "15/20", "node": 4070, "naklon": 0 }, +{ "label": "15/21", "node": 2826, "naklon": 0 }, +{ "label": "15/22", "node": 2808, "naklon": 3 }, +{ "label": "15/23", "node": 2795, "naklon": 3 }, +{ "label": "15/24", "node": 2807, "naklon": 3 }, +{ "label": "15/25", "node": 2831, "naklon": 0 }, +{ "label": "15/26", "node": 2862, "naklon": null }, +{ "label": "15/27", "node": 2861, "naklon": 0 }, +{ "label": "15/28", "node": 2866, "naklon": 0 }, +{ "label": "15/28/1", "node": 3546, "naklon": 0 }, +{ "label": "15/29", "node": 4146, "naklon": 0 }, +{ "label": "15/29/1", "node": 3001, "naklon": 0 }, +{ "label": "15/30", "node": 2835, "naklon": 0 }, +{ "label": "15/31", "node": 2874, "naklon": 0 }, +{ "label": "15/32", "node": 2852, "naklon": 0 }, +{ "label": "15/33", "node": 2851, "naklon": 0 }, +{ "label": "15/33/1", "node": 3560, "naklon": 0 }, +{ "label": "15/34", "node": 2858, "naklon": 0 }, +{ "label": "15/34/1", "node": 4306, "naklon": 0 }, +{ "label": "15/35", "node": 2856, "naklon": 0 }, +{ "label": "15/36", "node": 2847, "naklon": 0 }, +{ "label": "15/36/1", "node": 3556, "naklon": 0 }, +{ "label": "15/37", "node": 3950, "naklon": 0 }, +{ "label": "15/38", "node": 2848, "naklon": 0 }, +{ "label": "15/39", "node": 2863, "naklon": 0 }, +{ "label": "15/39/1", "node": 4313, "naklon": 0 }, +{ "label": "15/40", "node": 2873, "naklon": 0 }, +{ "label": "15/40/1", "node": 2984, "naklon": 0 }, +{ "label": "15/41", "node": 2854, "naklon": 0 }, +{ "label": "15/42", "node": 2859, "naklon": 0 }, +{ "label": "15/43", "node": 2872, "naklon": 0 }, +{ "label": "15/44", "node": 2849, "naklon": 0 }, +{ "label": "15/45", "node": 2864, "naklon": 0 }, +{ "label": "15/46", "node": 3553, "naklon": null }, +{ "label": "15/47", "node": 3021, "naklon": null }, +{ "label": "15/47/1", "node": 3008, "naklon": null }, +{ "label": "15/48", "node": 3017, "naklon": null }, +{ "label": "15/49", "node": 3014, "naklon": null }, +{ "label": "15/50", "node": 2981, "naklon": null }, +{ "label": "15/51", "node": 3020, "naklon": null }, +{ "label": "15/52", "node": 3027, "naklon": null }, +{ "label": "15/53", "node": 3006, "naklon": null }, +{ "label": "15/54", "node": 3012, "naklon": null }, +{ "label": "15/55", "node": 2738, "naklon": 0 }, +{ "label": "15/56", "node": 2725, "naklon": 0 }, +{ "label": "15/57", "node": 3016, "naklon": null }, +{ "label": "15/58", "node": 3005, "naklon": null }, +{ "label": "15/58/1", "node": 3009, "naklon": null }, +{ "label": "15/59", "node": 3010, "naklon": 0 }, +{ "label": "15/59/1", "node": 3538, "naklon": 0 }, +{ "label": "15/59/2", "node": 4145, "naklon": 0 }, +{ "label": "15/60", "node": 2713, "naklon": 0 }, +{ "label": "15/61", "node": 2789, "naklon": 0 }, +{ "label": "15/62", "node": 2736, "naklon": 0 }, +{ "label": "15/63", "node": 2739, "naklon": 0 }, +{ "label": "15/64", "node": 4346, "naklon": 0 }, +{ "label": "15/65", "node": 2731, "naklon": 0 }, +{ "label": "15/66", "node": 2818, "naklon": 0 }, +{ "label": "15/66/1", "node": 3557, "naklon": 0 }, +{ "label": "15/67", "node": 2822, "naklon": 0 }, +{ "label": "15/68", "node": 2833, "naklon": 0 }, +{ "label": "15/69", "node": 2834, "naklon": 0 }, +{ "label": "15/70", "node": 3097, "naklon": 0 }, +{ "label": "15/71", "node": 2824, "naklon": 0 }, +{ "label": "15/72", "node": 2828, "naklon": 0 }, +{ "label": "15/73", "node": 2600, "naklon": 0 }, +{ "label": "15/73/1", "node": 4314, "naklon": 0 }, +{ "label": "15/74", "node": 2832, "naklon": 0 }, +{ "label": "15/75", "node": 4360, "naklon": 0 }, +{ "label": "15/76", "node": 2846, "naklon": 0 }, +{ "label": "15/77", "node": 2584, "naklon": 0 }, +{ "label": "15/78", "node": 2843, "naklon": 0 }, +{ "label": "15/78/1", "node": 4308, "naklon": 0 }, +{ "label": "15/79", "node": 4144, "naklon": null }, +{ "label": "15/80", "node": 2844, "naklon": 0 }, +{ "label": "15/81", "node": 2842, "naklon": 0 }, +{ "label": "15/82", "node": 2838, "naklon": 0 }, +{ "label": "15/83", "node": 2837, "naklon": null }, +{ "label": "15/83/1", "node": 3555, "naklon": null }, +{ "label": "15/84", "node": 2839, "naklon": 0 }, +{ "label": "15/85", "node": 2830, "naklon": 0 }, +{ "label": "15/86", "node": 4066, "naklon": 0 }, +{ "label": "15/87", "node": 2836, "naklon": 0 }, +{ "label": "15/88", "node": 2911, "naklon": 0 }, +{ "label": "15/89", "node": 2825, "naklon": 0 }, +{ "label": "15/90", "node": 2811, "naklon": 0 }, +{ "label": "15/94", "node": 3740, "naklon": 15 }, +{ "label": "15/95", "node": 2734, "naklon": 15 }, +{ "label": "15/96", "node": 3105, "naklon": 15 }, +{ "label": "15/97", "node": 2732, "naklon": 15 }, +{ "label": "15/98", "node": 2727, "naklon": 15 }, +{ "label": "15/99", "node": 2735, "naklon": 15 }, +{ "label": "15/100", "node": 3926, "naklon": 15 }, +{ "label": "15/101", "node": 2918, "naklon": 0 }, +{ "label": "15/102", "node": 2705, "naklon": 10 }, +{ "label": "15/103", "node": 2708, "naklon": 10 }, +{ "label": "15/104", "node": 2721, "naklon": 10 }, +{ "label": "15/105", "node": 2719, "naklon": 10 }, +{ "label": "15/106", "node": 2919, "naklon": 10 }, +{ "label": "15/107", "node": 3101, "naklon": 10 }, +{ "label": "15/108", "node": 2853, "naklon": 10 }, +{ "label": "15/109", "node": 2715, "naklon": 10 }, +{ "label": "15/110", "node": 2712, "naklon": 0 }, +{ "label": "15/111", "node": 2711, "naklon": 0 }, +{ "label": "15/112", "node": 2709, "naklon": 0 }, +{ "label": "15/113", "node": 2710, "naklon": 0 }, +{ "label": "15/114", "node": 2907, "naklon": 0 }, +{ "label": "15/115", "node": 2906, "naklon": 0 }, +{ "label": "15/116", "node": 2908, "naklon": 0 }, +{ "label": "15/117", "node": 2901, "naklon": 0 }, +{ "label": "15/118", "node": 2913, "naklon": 0 }, +{ "label": "15/119", "node": 3656, "naklon": 0 }, +{ "label": "15/120", "node": 2781, "naklon": 0 }, +{ "label": "15/121", "node": 2802, "naklon": 0 }, +{ "label": "15/122", "node": 2791, "naklon": 0 }, +{ "label": "15/123", "node": 2783, "naklon": 0 }, +{ "label": "15/124", "node": 2794, "naklon": 0 }, +{ "label": "15/125", "node": 3139, "naklon": 0 }, +{ "label": "15/126", "node": 3229, "naklon": 5 }, +{ "label": "15/127", "node": 3239, "naklon": 5 }, +{ "label": "15/128", "node": 3230, "naklon": 5 }, +{ "label": "15/129", "node": 4016, "naklon": null }, +{ "label": "16/16A", "node": 3608, "naklon": 0 }, +{ "label": "16/16B", "node": 4151, "naklon": 0 }, +{ "label": "16/1", "node": 3710, "naklon": 0 }, +{ "label": "16/2", "node": 3726, "naklon": 0 }, +{ "label": "16/3", "node": 3743, "naklon": 0 }, +{ "label": "16/4", "node": 3724, "naklon": 0 }, +{ "label": "16/5", "node": 3712, "naklon": 0 }, +{ "label": "16/6", "node": 3739, "naklon": 0 }, +{ "label": "16/7", "node": 3742, "naklon": 0 }, +{ "label": "16/8", "node": 3731, "naklon": 0 }, +{ "label": "16/9", "node": 3727, "naklon": 0 }, +{ "label": "16/10", "node": 3729, "naklon": 0 }, +{ "label": "16/11", "node": 3736, "naklon": 0 }, +{ "label": "16/12", "node": 3713, "naklon": 0 }, +{ "label": "16/13", "node": 3715, "naklon": 0 }, +{ "label": "16/14", "node": 3733, "naklon": 0 }, +{ "label": "16/15", "node": 3732, "naklon": 0 }, +{ "label": "16/17", "node": 3634, "naklon": 0 }, +{ "label": "16/18", "node": 3610, "naklon": 0 }, +{ "label": "16/19", "node": 3626, "naklon": 0 }, +{ "label": "16/20", "node": 3618, "naklon": 0 }, +{ "label": "16/21", "node": 3619, "naklon": 0 }, +{ "label": "16/22", "node": 3628, "naklon": 0 }, +{ "label": "16/23", "node": 3615, "naklon": 0 }, +{ "label": "16/24", "node": 3609, "naklon": 0 }, +{ "label": "16/25", "node": 3606, "naklon": 0 }, +{ "label": "16/26", "node": 3624, "naklon": 0 }, +{ "label": "16/27", "node": 3627, "naklon": 0 }, +{ "label": "16/28", "node": 3607, "naklon": 0 }, +{ "label": "16/29", "node": 4370, "naklon": 0 }, +{ "label": "16/30", "node": 3692, "naklon": 0 }, +{ "label": "16/31", "node": 3614, "naklon": 0 }, +{ "label": "16/32", "node": 3623, "naklon": 0 }, +{ "label": "16/33", "node": 4373, "naklon": 0 }, +{ "label": "16/34", "node": 3620, "naklon": 0 }, +{ "label": "16/35", "node": 3685, "naklon": 0 }, +{ "label": "16/36", "node": 3616, "naklon": 0 }, +{ "label": "16/37", "node": 3686, "naklon": 0 }, +{ "label": "16/38", "node": 3688, "naklon": 0 }, +{ "label": "16/39", "node": 3684, "naklon": 0 }, +{ "label": "16/40", "node": 3825, "naklon": 0 }, +{ "label": "16/41", "node": 3865, "naklon": 0 }, +{ "label": "16/42", "node": 3824, "naklon": 0 }, +{ "label": "16/43", "node": 3871, "naklon": 0 }, +{ "label": "16/44", "node": 3801, "naklon": 0 }, +{ "label": "16/45", "node": 3862, "naklon": 0 }, +{ "label": "16/46", "node": 3876, "naklon": 0 }, +{ "label": "16/47", "node": 3861, "naklon": 0 }, +{ "label": "16/48", "node": 4215, "naklon": 0 }, +{ "label": "16/49", "node": 3605, "naklon": 10 }, +{ "label": "16/50", "node": 3603, "naklon": 10 }, +{ "label": "16/51", "node": 3592, "naklon": 10 }, +{ "label": "16/52", "node": 3598, "naklon": 10 }, +{ "label": "16/53", "node": 3594, "naklon": 10 }, +{ "label": "16/54", "node": 3593, "naklon": 10 }, +{ "label": "16/55", "node": 3630, "naklon": 10 }, +{ "label": "16/56", "node": 3763, "naklon": 10 }, +{ "label": "16/57", "node": 3746, "naklon": 10 }, +{ "label": "16/58", "node": 3699, "naklon": 0 }, +{ "label": "16/59", "node": 3698, "naklon": 0 }, +{ "label": "16/60", "node": 3709, "naklon": null }, +{ "label": "16/61", "node": 3708, "naklon": 0 }, +{ "label": "16/62", "node": 3703, "naklon": null }, +{ "label": "16/63", "node": 3700, "naklon": 0 }, +{ "label": "16/64", "node": 3701, "naklon": null }, +{ "label": "16/65", "node": 3704, "naklon": 0 }, +{ "label": "16/66", "node": 3707, "naklon": null }, +{ "label": "16/67", "node": 3810, "naklon": 0 }, +{ "label": "16/68", "node": 4208, "naklon": null }, +{ "label": "16/69", "node": 3867, "naklon": 0 }, +{ "label": "16/70", "node": 4372, "naklon": null }, +{ "label": "16/71", "node": 3881, "naklon": 0 }, +{ "label": "16/72", "node": 4204, "naklon": null }, +{ "label": "16/73", "node": 3869, "naklon": 0 }, +{ "label": "16/74", "node": 4202, "naklon": null }, +{ "label": "16/75", "node": 3830, "naklon": 0 }, +{ "label": "16/76", "node": 3870, "naklon": null }, +{ "label": "16/77", "node": 3964, "naklon": 0 }, +{ "label": "16/78", "node": 3849, "naklon": 0 }, +{ "label": "16/79", "node": 3694, "naklon": null }, +{ "label": "16/80", "node": 3717, "naklon": 0 }, +{ "label": "16/81", "node": 3877, "naklon": null }, +{ "label": "16/82", "node": 3755, "naklon": 0 }, +{ "label": "16/83", "node": 3725, "naklon": null }, +{ "label": "16/84", "node": 3716, "naklon": 0 }, +{ "label": "16/85", "node": 3696, "naklon": null }, +{ "label": "16/86", "node": 3702, "naklon": 0 }, +{ "label": "16/87", "node": 3706, "naklon": null }, +{ "label": "16/88", "node": 3850, "naklon": 0 }, +{ "label": "16/89", "node": 3848, "naklon": null }, +{ "label": "16/90", "node": 3737, "naklon": null }, +{ "label": "16/91", "node": 3705, "naklon": 0 }, +{ "label": "16/92", "node": 3723, "naklon": null }, +{ "label": "16/93", "node": 3842, "naklon": 0 }, +{ "label": "16/94", "node": 3735, "naklon": null }, +{ "label": "16/95", "node": 3719, "naklon": 0 }, +{ "label": "16/96", "node": 3697, "naklon": 0 }, +{ "label": "16/97", "node": 3711, "naklon": 0 }, +{ "label": "16/98", "node": 4107, "naklon": null }, +{ "label": "16/99", "node": 4112, "naklon": 5 }, +{ "label": "16/100", "node": 4106, "naklon": 5 }, +{ "label": "16/101", "node": 4111, "naklon": 5 }, +{ "label": "16/102", "node": 4091, "naklon": null }, +{ "label": "16/103", "node": 4104, "naklon": 5 }, +{ "label": "16/104", "node": 4094, "naklon": null }, +{ "label": "16/105", "node": 4089, "naklon": 5 }, +{ "label": "16/106", "node": 4095, "naklon": null }, +{ "label": "16/107", "node": 4102, "naklon": 5 }, +{ "label": "16/108", "node": 4105, "naklon": null }, +{ "label": "16/109", "node": 3859, "naklon": null }, +{ "label": "16/110", "node": 4090, "naklon": 5 }, +{ "label": "16/111", "node": 4110, "naklon": null }, +{ "label": "16/112", "node": 4097, "naklon": 5 }, +{ "label": "16/113", "node": 4099, "naklon": null }, +{ "label": "16/114", "node": 4096, "naklon": null }, +{ "label": "16/115", "node": 4101, "naklon": 5 }, +{ "label": "16/116", "node": 4109, "naklon": null }, +{ "label": "16/117", "node": 4092, "naklon": 5 }, +{ "label": "16/118", "node": 3631, "naklon": null }, +{ "label": "16/119", "node": 3632, "naklon": 0 }, +{ "label": "16/120", "node": 3641, "naklon": null }, +{ "label": "16/121", "node": 3638, "naklon": 0 }, +{ "label": "16/122", "node": 3637, "naklon": null }, +{ "label": "16/123", "node": 4142, "naklon": null }, +{ "label": "16/124", "node": 4147, "naklon": 5 }, +{ "label": "16/125", "node": 4139, "naklon": 5 }, +{ "label": "20/30A", "node": 3172, "naklon": 2 }, +{ "label": "20/30B", "node": 3164, "naklon": 2 }, +{ "label": "20/1", "node": 3247, "naklon": 10 }, +{ "label": "20/2", "node": 3296, "naklon": 10 }, +{ "label": "20/3", "node": 3246, "naklon": 10 }, +{ "label": "20/4", "node": 3270, "naklon": 10 }, +{ "label": "20/5", "node": 3294, "naklon": 10 }, +{ "label": "20/6", "node": 3298, "naklon": 10 }, +{ "label": "20/7", "node": 3297, "naklon": 10 }, +{ "label": "20/8", "node": 3293, "naklon": 10 }, +{ "label": "20/9", "node": 3299, "naklon": 10 }, +{ "label": "20/10", "node": 3295, "naklon": 10 }, +{ "label": "20/11", "node": 3244, "naklon": 10 }, +{ "label": "20/12", "node": 3249, "naklon": 10 }, +{ "label": "20/13", "node": 3268, "naklon": 10 }, +{ "label": "20/14", "node": 3245, "naklon": 10 }, +{ "label": "20/15", "node": 3278, "naklon": 10 }, +{ "label": "20/16", "node": 3280, "naklon": 10 }, +{ "label": "20/17", "node": 3292, "naklon": 10 }, +{ "label": "20/18", "node": 3287, "naklon": 10 }, +{ "label": "20/19", "node": 3282, "naklon": 10 }, +{ "label": "20/20", "node": 3273, "naklon": 0 }, +{ "label": "20/21", "node": 3157, "naklon": 0 }, +{ "label": "20/22", "node": 3283, "naklon": 0 }, +{ "label": "20/23", "node": 3159, "naklon": 0 }, +{ "label": "20/24", "node": 3289, "naklon": 0 }, +{ "label": "20/25", "node": 3163, "naklon": 0 }, +{ "label": "20/26", "node": 3126, "naklon": 0 }, +{ "label": "20/27", "node": 3171, "naklon": 0 }, +{ "label": "20/28", "node": 3162, "naklon": 0 }, +{ "label": "20/29", "node": 3279, "naklon": 10 }, +{ "label": "20/31", "node": 3173, "naklon": 0 }, +{ "label": "20/32", "node": 3127, "naklon": 0 }, +{ "label": "20/33", "node": 3131, "naklon": 0 }, +{ "label": "20/34", "node": 3129, "naklon": 0 }, +{ "label": "20/35", "node": 3276, "naklon": 2 }, +{ "label": "20/36", "node": 3290, "naklon": 2 }, +{ "label": "20/37", "node": 3132, "naklon": 0 }, +{ "label": "20/38", "node": 3138, "naklon": 0 }, +{ "label": "20/39", "node": 3272, "naklon": 0 }, +{ "label": "20/40", "node": 3291, "naklon": 0 }, +{ "label": "20/41", "node": 3277, "naklon": 10 }, +{ "label": "20/42", "node": 3286, "naklon": 10 }, +{ "label": "20/43", "node": 3281, "naklon": 10 }, +{ "label": "20/44", "node": 3288, "naklon": 10 }, +{ "label": "20/45", "node": 3284, "naklon": 10 }, +{ "label": "20/46", "node": 3167, "naklon": 10 }, +{ "label": "20/47", "node": 3872, "naklon": 0 }, +{ "label": "20/48", "node": 3124, "naklon": 0 }, +{ "label": "20/49", "node": 3133, "naklon": 0 }, +{ "label": "20/50", "node": 3158, "naklon": 0 }, +{ "label": "20/51", "node": 3169, "naklon": 0 }, +{ "label": "20/52", "node": 3146, "naklon": 0 }, +{ "label": "20/53", "node": 3160, "naklon": 0 }, +{ "label": "20/54", "node": 3248, "naklon": 0 }, +{ "label": "20/55", "node": 3156, "naklon": 0 }, +{ "label": "20/56", "node": 3161, "naklon": 0 }, +{ "label": "20/57", "node": 3170, "naklon": 0 }, +{ "label": "20/58", "node": 3168, "naklon": 0 }, +{ "label": "20/59", "node": 3125, "naklon": 0 }, +{ "label": "20/60", "node": 3166, "naklon": 0 }, +{ "label": "20/61", "node": 3130, "naklon": 0 }, +{ "label": "20/62", "node": 3563, "naklon": 0 }, +{ "label": "20/63", "node": 3550, "naklon": null }, +{ "label": "20/67", "node": 3269, "naklon": 0 }, +{ "label": "21/1", "node": 2921, "naklon": 0 }, +{ "label": "21/2", "node": 2707, "naklon": 0 }, +{ "label": "21/3", "node": 2723, "naklon": 0 }, +{ "label": "21/4", "node": 2716, "naklon": 0 }, +{ "label": "21/5", "node": 2717, "naklon": 0 }, +{ "label": "21/6", "node": 2720, "naklon": 0 }, +{ "label": "21/7", "node": 2722, "naklon": 0 }, +{ "label": "21/8", "node": 2718, "naklon": 0 }, +{ "label": "21/9", "node": 2724, "naklon": 0 }, +{ "label": "21/10", "node": 2742, "naklon": 0 }, +{ "label": "21/11", "node": 2743, "naklon": 0 }, +{ "label": "21/12", "node": 2733, "naklon": 0 }, +{ "label": "21/14", "node": 2903, "naklon": 0 }, +{ "label": "21/15", "node": 2917, "naklon": 0 }, +{ "label": "21/16", "node": 2897, "naklon": 0 }, +{ "label": "21/17", "node": 2914, "naklon": 0 }, +{ "label": "21/18", "node": 2898, "naklon": 0 }, +{ "label": "21/19", "node": 2773, "naklon": 0 }, +{ "label": "21/20", "node": 2895, "naklon": 0 }, +{ "label": "21/21", "node": 2896, "naklon": 0 }, +{ "label": "21/22", "node": 2771, "naklon": 0 }, +{ "label": "21/23", "node": 2772, "naklon": 0 }, +{ "label": "21/24", "node": 2793, "naklon": 0 }, +{ "label": "21/25", "node": 2902, "naklon": 0 }, +{ "label": "21/26", "node": 2910, "naklon": 0 }, +{ "label": "21/27", "node": 2909, "naklon": 0 }, +{ "label": "21/28", "node": 2920, "naklon": 0 }, +{ "label": "21/29", "node": 2916, "naklon": 0 }, +{ "label": "21/30", "node": 2904, "naklon": 0 }, +{ "label": "21/31", "node": 2915, "naklon": 0 }, +{ "label": "21/32", "node": 2905, "naklon": 0 }, +{ "label": "21/33", "node": 2900, "naklon": 0 }, +{ "label": "21/34", "node": 2899, "naklon": 0 }, +{ "label": "21/36", "node": 2741, "naklon": 0 }, +{ "label": "21/37", "node": 2714, "naklon": 0 }, +{ "label": "21/38", "node": 2701, "naklon": 0 }, +{ "label": "21/39", "node": 2703, "naklon": 0 }, +{ "label": "21/40", "node": 2704, "naklon": 0 }, +{ "label": "21/41", "node": 2702, "naklon": 0 }, +{ "label": "21/42", "node": 2706, "naklon": 0 }, +{ "label": "21/43", "node": 2776, "naklon": 0 }, +{ "label": "21/44", "node": 2770, "naklon": 0 }, +{ "label": "21/45", "node": 2786, "naklon": 0 }, +{ "label": "21/46", "node": 2779, "naklon": 0 }, +{ "label": "21/47", "node": 2782, "naklon": 0 }, +{ "label": "21/48", "node": 2785, "naklon": 0 }, +{ "label": "21/49", "node": 2769, "naklon": 0 }, +{ "label": "21/50", "node": 3354, "naklon": 0 }, +{ "label": "21/51", "node": 2778, "naklon": 0 }, +{ "label": "21/52", "node": 2775, "naklon": 0 }, +{ "label": "21/53", "node": 2780, "naklon": 0 }, +{ "label": "21/54", "node": 2790, "naklon": 0 }, +{ "label": "21/55", "node": 2792, "naklon": 0 }, +{ "label": "21/56", "node": 2774, "naklon": 0 }, +{ "label": "22/1", "node": 2630, "naklon": 0 }, +{ "label": "22/2", "node": 2631, "naklon": 0 }, +{ "label": "22/3", "node": 2632, "naklon": 0 }, +{ "label": "22/4", "node": 2633, "naklon": 0 }, +{ "label": "22/5", "node": 2634, "naklon": 0 }, +{ "label": "22/6", "node": 2636, "naklon": 0 }, +{ "label": "22/7", "node": 4367, "naklon": 0 }, +{ "label": "22/8", "node": 2637, "naklon": 0 }, +{ "label": "22/9", "node": 2638, "naklon": 0 }, +{ "label": "22/10", "node": 2639, "naklon": 0 }, +{ "label": "22/11", "node": 2640, "naklon": 0 }, +{ "label": "22/12", "node": 2641, "naklon": 0 }, +{ "label": "22/13", "node": 2642, "naklon": 0 }, +{ "label": "22/14", "node": 2643, "naklon": 0 }, +{ "label": "22/15", "node": 2644, "naklon": 0 }, +{ "label": "22/16", "node": 2645, "naklon": 0 }, +{ "label": "22/17", "node": 2646, "naklon": 0 }, +{ "label": "22/18", "node": 2647, "naklon": 0 }, +{ "label": "22/19", "node": 2648, "naklon": 0 }, +{ "label": "22/20", "node": 2649, "naklon": 0 }, +{ "label": "22/21", "node": 2650, "naklon": 0 }, +{ "label": "22/22", "node": 2651, "naklon": 0 }, +{ "label": "22/23", "node": 4103, "naklon": 0 }, +{ "label": "22/24", "node": 2653, "naklon": 0 }, +{ "label": "22/25", "node": 2654, "naklon": 0 }, +{ "label": "22/26", "node": 2655, "naklon": 0 }, +{ "label": "22/27", "node": 2656, "naklon": 0 }, +{ "label": "22/28", "node": 2657, "naklon": 0 }, +{ "label": "22/29", "node": 2658, "naklon": 0 }, +{ "label": "22/30", "node": 2659, "naklon": 0 }, +{ "label": "22/31", "node": 2660, "naklon": 0 }, +{ "label": "22/32", "node": 2661, "naklon": 0 }, +{ "label": "22/32/1", "node": 3015, "naklon": 0 }, +{ "label": "22/33", "node": 2662, "naklon": 0 }, +{ "label": "22/34", "node": 2663, "naklon": 0 }, +{ "label": "22/35", "node": 2664, "naklon": 0 }, +{ "label": "22/36", "node": 2665, "naklon": 0 }, +{ "label": "22/37", "node": 2666, "naklon": 0 }, +{ "label": "22/38", "node": 2667, "naklon": 0 }, +{ "label": "22/39", "node": 2668, "naklon": 0 }, +{ "label": "22/40", "node": 2669, "naklon": null }, +{ "label": "22/41", "node": 2670, "naklon": null }, +{ "label": "22/42", "node": 2671, "naklon": null }, +{ "label": "23/9A", "node": 3087, "naklon": 10 }, +{ "label": "23/9B", "node": 3090, "naklon": 10 }, +{ "label": "23/1", "node": 3075, "naklon": 0 }, +{ "label": "23/2", "node": 3089, "naklon": 0 }, +{ "label": "23/3", "node": 3088, "naklon": 0 }, +{ "label": "23/4", "node": 3228, "naklon": 10 }, +{ "label": "23/5", "node": 2751, "naklon": 10 }, +{ "label": "23/6", "node": 3243, "naklon": 10 }, +{ "label": "23/7", "node": 4349, "naklon": 10 }, +{ "label": "23/8", "node": 3102, "naklon": 10 }, +{ "label": "23/10", "node": 3099, "naklon": 10 }, +{ "label": "23/11", "node": 3103, "naklon": 10 }, +{ "label": "23/12", "node": 3093, "naklon": 10 }, +{ "label": "23/13", "node": 3098, "naklon": 10 }, +{ "label": "23/14", "node": 3092, "naklon": 10 }, +{ "label": "23/15", "node": 3233, "naklon": 0 }, +{ "label": "23/16", "node": 3095, "naklon": 0 }, +{ "label": "23/17", "node": 4074, "naklon": 0 }, +{ "label": "23/18", "node": 2729, "naklon": 0 }, +{ "label": "23/19", "node": 3234, "naklon": 0 }, +{ "label": "23/20", "node": 3094, "naklon": 0 }, +{ "label": "23/21", "node": 2817, "naklon": 0 }, +{ "label": "23/22", "node": 3226, "naklon": 0 }, +{ "label": "23/23", "node": 3225, "naklon": 0 }, +{ "label": "23/24", "node": 3237, "naklon": 0 }, +{ "label": "23/25", "node": 4250, "naklon": 0 }, +{ "label": "23/26", "node": 3059, "naklon": 10 }, +{ "label": "23/27", "node": 3238, "naklon": 10 }, +{ "label": "23/28", "node": 3242, "naklon": 10 }, +{ "label": "23/29", "node": 3236, "naklon": 10 }, +{ "label": "23/30", "node": 3112, "naklon": 10 }, +{ "label": "23/31", "node": 3224, "naklon": 0 }, +{ "label": "23/32", "node": 4298, "naklon": 10 }, +{ "label": "23/33", "node": 4150, "naklon": 10 }, +{ "label": "23/34", "node": 3091, "naklon": 10 }, +{ "label": "25/1", "node": 3771, "naklon": 5 }, +{ "label": "25/2", "node": 3777, "naklon": 5 }, +{ "label": "25/3", "node": 3749, "naklon": 5 }, +{ "label": "25/4", "node": 3769, "naklon": 5 }, +{ "label": "25/5", "node": 3765, "naklon": 5 }, +{ "label": "25/6", "node": 3785, "naklon": 5 }, +{ "label": "25/7", "node": 3761, "naklon": 5 }, +{ "label": "25/8", "node": 3758, "naklon": 5 }, +{ "label": "25/9", "node": 3766, "naklon": 5 }, +{ "label": "25/10", "node": 3779, "naklon": 5 }, +{ "label": "25/11", "node": 3899, "naklon": 10 }, +{ "label": "25/12", "node": 3922, "naklon": 10 }, +{ "label": "25/13", "node": 3912, "naklon": 10 }, +{ "label": "25/14", "node": 3933, "naklon": 10 }, +{ "label": "25/15", "node": 3921, "naklon": 10 }, +{ "label": "25/16", "node": 4300, "naklon": 10 }, +{ "label": "25/17", "node": 3927, "naklon": 10 }, +{ "label": "25/18", "node": 3212, "naklon": 10 }, +{ "label": "25/19", "node": 3208, "naklon": 10 }, +{ "label": "25/20", "node": 3207, "naklon": 10 }, +{ "label": "25/21", "node": 4294, "naklon": 10 }, +{ "label": "25/22", "node": 3209, "naklon": 10 }, +{ "label": "25/23", "node": 3745, "naklon": 10 }, +{ "label": "25/24", "node": 3762, "naklon": 10 }, +{ "label": "25/25", "node": 3215, "naklon": 10 }, +{ "label": "25/26", "node": 3210, "naklon": 10 }, +{ "label": "25/27", "node": 3211, "naklon": 10 }, +{ "label": "25/28", "node": 3206, "naklon": 10 }, +{ "label": "25/29", "node": 3918, "naklon": 5 }, +{ "label": "25/30", "node": 3928, "naklon": 5 }, +{ "label": "25/31", "node": 3917, "naklon": 5 }, +{ "label": "25/32", "node": 4029, "naklon": 0 }, +{ "label": "25/33", "node": 4038, "naklon": 0 }, +{ "label": "25/34", "node": 4022, "naklon": 0 }, +{ "label": "25/35", "node": 3937, "naklon": 0 }, +{ "label": "25/36", "node": 3190, "naklon": 0 }, +{ "label": "25/37", "node": 3835, "naklon": 0 }, +{ "label": "25/38", "node": 3201, "naklon": 0 }, +{ "label": "25/39", "node": 3193, "naklon": 0 }, +{ "label": "25/40", "node": 3191, "naklon": 0 }, +{ "label": "25/41", "node": 3203, "naklon": 0 }, +{ "label": "25/42", "node": 4301, "naklon": 0 }, +{ "label": "25/43", "node": 3223, "naklon": 0 }, +{ "label": "25/44", "node": 3202, "naklon": 0 }, +{ "label": "25/45", "node": 3205, "naklon": 0 }, +{ "label": "25/46", "node": 3194, "naklon": 0 }, +{ "label": "25/47", "node": 3198, "naklon": 0 }, +{ "label": "25/48", "node": 3204, "naklon": 0 }, +{ "label": "25/49", "node": 3200, "naklon": 0 }, +{ "label": "25/50", "node": 3216, "naklon": 0 }, +{ "label": "25/51", "node": 3932, "naklon": 5 }, +{ "label": "25/52", "node": 3923, "naklon": 5 }, +{ "label": "25/53", "node": 3913, "naklon": 5 }, +{ "label": "25/54", "node": 3900, "naklon": 5 }, +{ "label": "25/55", "node": 4189, "naklon": 10 }, +{ "label": "25/56", "node": 4191, "naklon": 10 }, +{ "label": "25/57", "node": 3790, "naklon": 10 }, +{ "label": "25/58", "node": 4190, "naklon": 10 }, +{ "label": "25/59", "node": 4302, "naklon": 0 }, +{ "label": "25/60", "node": 4351, "naklon": 0 }, +{ "label": "25/61", "node": 4075, "naklon": 0 }, +{ "label": "25/62", "node": 4071, "naklon": 0 }, +{ "label": "25/63", "node": 3784, "naklon": 0 }, +{ "label": "25/64", "node": 4065, "naklon": 0 }, +{ "label": "25/65", "node": 4297, "naklon": 0 }, +{ "label": "25/66", "node": 4295, "naklon": 0 }, +{ "label": "25/67", "node": 4299, "naklon": 0 }, +{ "label": "25/68", "node": 3772, "naklon": 0 }, +{ "label": "25/69", "node": 3941, "naklon": 0 }, +{ "label": "25/70", "node": 3782, "naklon": 0 }, +{ "label": "25/71", "node": 4068, "naklon": 0 }, +{ "label": "25/72", "node": 4073, "naklon": 0 }, +{ "label": "25/73", "node": 3901, "naklon": 5 }, +{ "label": "25/74", "node": 4296, "naklon": 5 }, +{ "label": "25/75", "node": 3910, "naklon": 5 }, +{ "label": "25/76", "node": 4293, "naklon": 5 }, +{ "label": "25/77", "node": 3919, "naklon": 5 }, +{ "label": "25/78", "node": 3924, "naklon": 5 }, +{ "label": "25/79", "node": 3909, "naklon": 5 }, +{ "label": "25/80", "node": 3896, "naklon": 5 }, +{ "label": "25/81", "node": 3911, "naklon": 5 }, +{ "label": "25/82", "node": 2819, "naklon": 15 }, +{ "label": "25/83", "node": 3776, "naklon": 15 }, +{ "label": "25/84", "node": 3752, "naklon": 15 }, +{ "label": "25/85", "node": 4353, "naklon": 15 }, +{ "label": "25/86", "node": 3791, "naklon": 0 }, +{ "label": "25/87", "node": 3770, "naklon": 0 }, +{ "label": "25/88", "node": 3760, "naklon": 0 }, +{ "label": "25/89", "node": 3115, "naklon": 0 }, +{ "label": "25/90", "node": 3738, "naklon": 0 }, +{ "label": "25/91", "node": 3748, "naklon": 0 }, +{ "label": "25/92", "node": 3753, "naklon": 0 }, +{ "label": "25/93", "node": 3775, "naklon": 0 }, +{ "label": "25/94", "node": 3778, "naklon": 5 }, +{ "label": "25/95", "node": 4078, "naklon": 5 }, +{ "label": "25/96", "node": 4088, "naklon": 5 }, +{ "label": "25/97", "node": 3856, "naklon": 5 }, +{ "label": "25/98", "node": 4084, "naklon": 5 }, +{ "label": "25/99", "node": 4069, "naklon": 5 }, +{ "label": "25/100", "node": 4188, "naklon": 5 }, +{ "label": "25/101", "node": 4064, "naklon": 5 }, +{ "label": "25/102", "node": 3792, "naklon": 5 }, +{ "label": "25/103", "node": 3780, "naklon": 5 }, +{ "label": "25/104", "node": 4034, "naklon": 5 }, +{ "label": "25/105", "node": 4072, "naklon": 5 }, +{ "label": "25/106", "node": 3884, "naklon": 5 }, +{ "label": "25/107", "node": 3793, "naklon": 5 }, +{ "label": "25/108", "node": 3863, "naklon": 5 }, +{ "label": "25/109", "node": 3855, "naklon": 5 }, +{ "label": "33/1", "node": 3846, "naklon": 0 }, +{ "label": "33/2", "node": 3943, "naklon": 0 }, +{ "label": "33/3", "node": 3903, "naklon": 0 }, +{ "label": "33/4", "node": 3982, "naklon": 0 }, +{ "label": "33/5", "node": 3879, "naklon": 0 }, +{ "label": "33/6", "node": 3887, "naklon": 0 }, +{ "label": "33/7", "node": 3920, "naklon": 5 }, +{ "label": "33/8", "node": 3942, "naklon": 5 }, +{ "label": "33/9", "node": 3829, "naklon": null }, +{ "label": "34/79A", "node": 3452, "naklon": 6 }, +{ "label": "34/79B", "node": 3460, "naklon": 6 }, +{ "label": "34/90A", "node": 3443, "naklon": 6 }, +{ "label": "34/90B", "node": 3445, "naklon": 6 }, +{ "label": "34/90C", "node": 3457, "naklon": 6 }, +{ "label": "34/97A", "node": 3461, "naklon": 6 }, +{ "label": "34/97B", "node": 3463, "naklon": 6 }, +{ "label": "34/98A", "node": 3426, "naklon": 6 }, +{ "label": "34/98B", "node": 3444, "naklon": 6 }, +{ "label": "34/99A", "node": 3453, "naklon": 6 }, +{ "label": "34/99B", "node": 3455, "naklon": 6 }, +{ "label": "34/1", "node": 4009, "naklon": 0 }, +{ "label": "34/2", "node": 3602, "naklon": 0 }, +{ "label": "34/3", "node": 3441, "naklon": 0 }, +{ "label": "34/4", "node": 3464, "naklon": 0 }, +{ "label": "34/5", "node": 3883, "naklon": 0 }, +{ "label": "34/6", "node": 4098, "naklon": 0 }, +{ "label": "34/7", "node": 4003, "naklon": 0 }, +{ "label": "34/8", "node": 4004, "naklon": 0 }, +{ "label": "34/9", "node": 3888, "naklon": 0 }, +{ "label": "34/10", "node": 3997, "naklon": 0 }, +{ "label": "34/11", "node": 4006, "naklon": 0 }, +{ "label": "34/12", "node": 4000, "naklon": 0 }, +{ "label": "34/13", "node": 4011, "naklon": 0 }, +{ "label": "34/14", "node": 3999, "naklon": 0 }, +{ "label": "34/15", "node": 3981, "naklon": 0 }, +{ "label": "34/16", "node": 3988, "naklon": 0 }, +{ "label": "34/17", "node": 3986, "naklon": 0 }, +{ "label": "34/18", "node": 3998, "naklon": 0 }, +{ "label": "34/19", "node": 3983, "naklon": 0 }, +{ "label": "34/20", "node": 4005, "naklon": 0 }, +{ "label": "34/21", "node": 4001, "naklon": 0 }, +{ "label": "34/22", "node": 4008, "naklon": 0 }, +{ "label": "34/23", "node": 4002, "naklon": 0 }, +{ "label": "34/24", "node": 3996, "naklon": 0 }, +{ "label": "34/25", "node": 4007, "naklon": 0 }, +{ "label": "34/26", "node": 4113, "naklon": 15 }, +{ "label": "34/27", "node": 3595, "naklon": 5 }, +{ "label": "34/28", "node": 3599, "naklon": 5 }, +{ "label": "34/29", "node": 3601, "naklon": 5 }, +{ "label": "34/30", "node": 4205, "naklon": 0 }, +{ "label": "34/31", "node": 3987, "naklon": null }, +{ "label": "34/32", "node": 4214, "naklon": 0 }, +{ "label": "34/33", "node": 4226, "naklon": 0 }, +{ "label": "34/34", "node": 4209, "naklon": 0 }, +{ "label": "34/35", "node": 4201, "naklon": 0 }, +{ "label": "34/36", "node": 3440, "naklon": 0 }, +{ "label": "34/37", "node": 3465, "naklon": 0 }, +{ "label": "34/38", "node": 3446, "naklon": 0 }, +{ "label": "34/39", "node": 4039, "naklon": 5 }, +{ "label": "34/40", "node": 4057, "naklon": 5 }, +{ "label": "34/41", "node": 3985, "naklon": 0 }, +{ "label": "34/42", "node": 3882, "naklon": 0 }, +{ "label": "34/43", "node": 4040, "naklon": 5 }, +{ "label": "34/44", "node": 3231, "naklon": 0 }, +{ "label": "34/45", "node": 3227, "naklon": 0 }, +{ "label": "34/46", "node": 3431, "naklon": 0 }, +{ "label": "34/47", "node": 4013, "naklon": 0 }, +{ "label": "34/48", "node": 4045, "naklon": 0 }, +{ "label": "34/49", "node": 3949, "naklon": 0 }, +{ "label": "34/50", "node": 3953, "naklon": 0 }, +{ "label": "34/51", "node": 3952, "naklon": 0 }, +{ "label": "34/52", "node": 3995, "naklon": 0 }, +{ "label": "34/53", "node": 3992, "naklon": 0 }, +{ "label": "34/54", "node": 4198, "naklon": 0 }, +{ "label": "34/55", "node": 3935, "naklon": 0 }, +{ "label": "34/56", "node": 4050, "naklon": 0 }, +{ "label": "34/57", "node": 4049, "naklon": 0 }, +{ "label": "34/58", "node": 4054, "naklon": 0 }, +{ "label": "34/59", "node": 3663, "naklon": 6 }, +{ "label": "34/60", "node": 3661, "naklon": 6 }, +{ "label": "34/61", "node": 3664, "naklon": 6 }, +{ "label": "34/62", "node": 3660, "naklon": 6 }, +{ "label": "34/63", "node": 3662, "naklon": 6 }, +{ "label": "34/65", "node": 3665, "naklon": 6 }, +{ "label": "34/66", "node": 3667, "naklon": 6 }, +{ "label": "34/67", "node": 3675, "naklon": 6 }, +{ "label": "34/68", "node": 3666, "naklon": 6 }, +{ "label": "34/69", "node": 3652, "naklon": 6 }, +{ "label": "34/70", "node": 3458, "naklon": 6 }, +{ "label": "34/70/1", "node": 4425, "naklon": 6 }, +{ "label": "34/71", "node": 3459, "naklon": 6 }, +{ "label": "34/72", "node": 3435, "naklon": 6 }, +{ "label": "34/73", "node": 3448, "naklon": 6 }, +{ "label": "34/74", "node": 3451, "naklon": 6 }, +{ "label": "34/75", "node": 3442, "naklon": 6 }, +{ "label": "34/76", "node": 3449, "naklon": 6 }, +{ "label": "34/77", "node": 3450, "naklon": 6 }, +{ "label": "34/78", "node": 3433, "naklon": 6 }, +{ "label": "34/80", "node": 3432, "naklon": 12 }, +{ "label": "34/81", "node": 3470, "naklon": 12 }, +{ "label": "34/82", "node": 3438, "naklon": 12 }, +{ "label": "34/83", "node": 3439, "naklon": 12 }, +{ "label": "34/84", "node": 4028, "naklon": 5 }, +{ "label": "34/85", "node": 3596, "naklon": 5 }, +{ "label": "34/86", "node": 4021, "naklon": 5 }, +{ "label": "34/87", "node": 3437, "naklon": 12 }, +{ "label": "34/88", "node": 3428, "naklon": 12 }, +{ "label": "34/89", "node": 3430, "naklon": 12 }, +{ "label": "34/91", "node": 3454, "naklon": 6 }, +{ "label": "34/92", "node": 3492, "naklon": 6 }, +{ "label": "34/93", "node": 3462, "naklon": 6 }, +{ "label": "34/94", "node": 3427, "naklon": 6 }, +{ "label": "34/95", "node": 3434, "naklon": 6 }, +{ "label": "34/96", "node": 3456, "naklon": 6 }, +{ "label": "34/98/1", "node": 4307, "naklon": 6 }, +{ "label": "35/1", "node": 3968, "naklon": 0 }, +{ "label": "35/2", "node": 3969, "naklon": 0 }, +{ "label": "35/3", "node": 3947, "naklon": 0 }, +{ "label": "35/4", "node": 3979, "naklon": 0 }, +{ "label": "35/5", "node": 3959, "naklon": 0 }, +{ "label": "35/6", "node": 3948, "naklon": 0 }, +{ "label": "35/7", "node": 3961, "naklon": 0 }, +{ "label": "35/8", "node": 3956, "naklon": 0 }, +{ "label": "35/9", "node": 3604, "naklon": 0 }, +{ "label": "35/10", "node": 3944, "naklon": 0 }, +{ "label": "35/11", "node": 3960, "naklon": 0 }, +{ "label": "35/12", "node": 3958, "naklon": 0 }, +{ "label": "35/13", "node": 4036, "naklon": 5 }, +{ "label": "35/18", "node": 3893, "naklon": 5 }, +{ "label": "35/19", "node": 4108, "naklon": 5 }, +{ "label": "35/20", "node": 4017, "naklon": 5 }, +{ "label": "35/21", "node": 3963, "naklon": 0 }, +{ "label": "35/22", "node": 3658, "naklon": 0 }, +{ "label": "35/23", "node": 3975, "naklon": 0 }, +{ "label": "35/24", "node": 3980, "naklon": 0 }, +{ "label": "35/25", "node": 4012, "naklon": 0 }, +{ "label": "35/26", "node": 3655, "naklon": 0 }, +{ "label": "35/27", "node": 3962, "naklon": 0 }, +{ "label": "35/28", "node": 3945, "naklon": 0 }, +{ "label": "35/29", "node": 3569, "naklon": 0 }, +{ "label": "35/30", "node": 3429, "naklon": 0 }, +{ "label": "35/31", "node": 3657, "naklon": 0 }, +{ "label": "35/32", "node": 3646, "naklon": 0 }, +{ "label": "35/33", "node": 3622, "naklon": 0 }, +{ "label": "35/34", "node": 3612, "naklon": 0 }, +{ "label": "35/35", "node": 3955, "naklon": 0 }, +{ "label": "35/37", "node": 3878, "naklon": 0 }, +{ "label": "35/38", "node": 3965, "naklon": 0 }, +{ "label": "35/39", "node": 3970, "naklon": 0 }, +{ "label": "35/40", "node": 3611, "naklon": 0 }, +{ "label": "35/41", "node": 2635, "naklon": 0 }, +{ "label": "35/42", "node": 3978, "naklon": 0 }, +{ "label": "35/43", "node": 4213, "naklon": 0 }, +{ "label": "35/44", "node": 3984, "naklon": 0 }, +{ "label": "35/45", "node": 4218, "naklon": 0 }, +{ "label": "35/46", "node": 3973, "naklon": 0 }, +{ "label": "35/47", "node": 3974, "naklon": 0 }, +{ "label": "35/48", "node": 3759, "naklon": 0 }, +{ "label": "35/49", "node": 3844, "naklon": 0 }, +{ "label": "35/50", "node": 3804, "naklon": 0 }, +{ "label": "35/51", "node": 3831, "naklon": 0 }, +{ "label": "35/52", "node": 3643, "naklon": 0 }, +{ "label": "35/53", "node": 3966, "naklon": 0 }, +{ "label": "35/54", "node": 3971, "naklon": 0 }, +{ "label": "35/55", "node": 3650, "naklon": 6 }, +{ "label": "35/56", "node": 3651, "naklon": 6 }, +{ "label": "35/57", "node": 3669, "naklon": 6 }, +{ "label": "35/58", "node": 3648, "naklon": 6 }, +{ "label": "35/59", "node": 3645, "naklon": 6 }, +{ "label": "35/60", "node": 3659, "naklon": 6 }, +{ "label": "35/61", "node": 3647, "naklon": 6 }, +{ "label": "35/62", "node": 3644, "naklon": 6 }, +{ "label": "35/63", "node": 3671, "naklon": 6 }, +{ "label": "35/64", "node": 3682, "naklon": 6 }, +{ "label": "35/65", "node": 3672, "naklon": 6 }, +{ "label": "35/66", "node": 3683, "naklon": 6 }, +{ "label": "35/67", "node": 3673, "naklon": 6 }, +{ "label": "35/68", "node": 3674, "naklon": 6 }, +{ "label": "35/69", "node": 3679, "naklon": 6 }, +{ "label": "35/70", "node": 3649, "naklon": 6 }, +{ "label": "35/71", "node": 3687, "naklon": 6 }, +{ "label": "35/72", "node": 3677, "naklon": 6 }, +{ "label": "35/73", "node": 3690, "naklon": 6 }, +{ "label": "35/74", "node": 3691, "naklon": 6 }, +{ "label": "35/75", "node": 3676, "naklon": 6 }, +{ "label": "35/76", "node": 3680, "naklon": 6 }, +{ "label": "35/77", "node": 3668, "naklon": 6 }, +{ "label": "35/78", "node": 3681, "naklon": 6 }, +{ "label": "35/79", "node": 3670, "naklon": 6 }, +{ "label": "35/80", "node": 3689, "naklon": 6 }, +{ "label": "35/81", "node": 3678, "naklon": 6 }, +{ "label": "35/82", "node": 3693, "naklon": 6 }, +{ "label": "35/83", "node": 3654, "naklon": null }, +{ "label": "36/1", "node": 4086, "naklon": 0 }, +{ "label": "36/2", "node": 4085, "naklon": 0 }, +{ "label": "36/3", "node": 4083, "naklon": 0 }, +{ "label": "36/4", "node": 4087, "naklon": 0 }, +{ "label": "36/5", "node": 4077, "naklon": 0 }, +{ "label": "36/6", "node": 4082, "naklon": 0 }, +{ "label": "36/7", "node": 4186, "naklon": 0 }, +{ "label": "36/8", "node": 4206, "naklon": 0 }, +{ "label": "36/9", "node": 4080, "naklon": 0 }, +{ "label": "36/10", "node": 4081, "naklon": 0 }, +{ "label": "36/11", "node": 4210, "naklon": 0 }, +{ "label": "36/12", "node": 4079, "naklon": 0 }, +{ "label": "36/13", "node": 4076, "naklon": 0 }, +{ "label": "36/14", "node": 3852, "naklon": 0 }, +{ "label": "36/15", "node": 2813, "naklon": 0 }, +{ "label": "36/16", "node": 4219, "naklon": 0 }, +{ "label": "37/1A", "node": 3104, "naklon": 15 }, +{ "label": "37/1B", "node": 3121, "naklon": 15 }, +{ "label": "37/2", "node": 3113, "naklon": 10 }, +{ "label": "37/3", "node": 3118, "naklon": 10 }, +{ "label": "37/4", "node": 3111, "naklon": 10 }, +{ "label": "37/5", "node": 4020, "naklon": 10 }, +{ "label": "37/6", "node": 3119, "naklon": 10 }, +{ "label": "37/7", "node": 3110, "naklon": 10 }, +{ "label": "37/8", "node": 3108, "naklon": 10 }, +{ "label": "37/12", "node": 3107, "naklon": 0 }, +{ "label": "37/13", "node": 3199, "naklon": 0 }, +{ "label": "37/14", "node": 3120, "naklon": 0 }, +{ "label": "37/15", "node": 3122, "naklon": 0 }, +{ "label": "37/16", "node": 3908, "naklon": 0 }, +{ "label": "37/17", "node": 3114, "naklon": 0 }, +{ "label": "37/18", "node": 3105, "naklon": 0 }, +{ "label": "37/19", "node": 3116, "naklon": 0 }, +{ "label": "37/20", "node": 3106, "naklon": 0 }, +{ "label": "37/21", "node": 2887, "naklon": 5 }, +{ "label": "37/22", "node": 2888, "naklon": 5 }, +{ "label": "37/23", "node": 2877, "naklon": 5 }, +{ "label": "37/24", "node": 2891, "naklon": 5 }, +{ "label": "37/25", "node": 2886, "naklon": 5 }, +{ "label": "37/26", "node": 2892, "naklon": 5 }, +{ "label": "37/27", "node": 2882, "naklon": 5 }, +{ "label": "37/28", "node": 2883, "naklon": 5 }, +{ "label": "37/29", "node": 2876, "naklon": 5 }, +{ "label": "37/30", "node": 3109, "naklon": 5 }, +{ "label": "37/31", "node": 4152, "naklon": 5 }, +{ "label": "37/32", "node": 3117, "naklon": 5 }, +{ "label": "37/33", "node": 2870, "naklon": 5 }, +{ "label": "37/34", "node": 2867, "naklon": 0 }, +{ "label": "37/35", "node": 2865, "naklon": 0 }, +{ "label": "37/36", "node": 3096, "naklon": 0 }, +{ "label": "37/37", "node": 2871, "naklon": 0 }, +{ "label": "37/38", "node": 2884, "naklon": 0 }, +{ "label": "37/39", "node": 2855, "naklon": 0 }, +{ "label": "37/40", "node": 2878, "naklon": 0 }, +{ "label": "37/41", "node": 2889, "naklon": 0 }, +{ "label": "37/42", "node": 2879, "naklon": 0 }, +{ "label": "37/43", "node": 2850, "naklon": 0 }, +{ "label": "37/44", "node": 2894, "naklon": 0 }, +{ "label": "37/45", "node": 2880, "naklon": 0 }, +{ "label": "37/46", "node": 2893, "naklon": 0 }, +{ "label": "37/47", "node": 2890, "naklon": 0 }, +{ "label": "37/48", "node": 4355, "naklon": 0 }, +{ "label": "37/49", "node": 2885, "naklon": 0 }, +{ "label": "37/50", "node": 2875, "naklon": 0 }, +{ "label": "38/30A", "node": 3486, "naklon": 5 }, +{ "label": "38/30B", "node": 3714, "naklon": 0 }, +{ "label": "38/32A", "node": 3483, "naklon": 5 }, +{ "label": "38/32B", "node": 3496, "naklon": 0 }, +{ "label": "38/35A", "node": 3487, "naklon": 5 }, +{ "label": "38/35B", "node": 3498, "naklon": 5 }, +{ "label": "38/38A", "node": 3578, "naklon": 5 }, +{ "label": "38/38B", "node": 3508, "naklon": 5 }, +{ "label": "38/59A", "node": 3787, "naklon": 5 }, +{ "label": "38/59B", "node": 3491, "naklon": 5 }, +{ "label": "38/1", "node": 3568, "naklon": null }, +{ "label": "38/2", "node": 3502, "naklon": 0 }, +{ "label": "38/3", "node": 3836, "naklon": 0 }, +{ "label": "38/4", "node": 3588, "naklon": 0 }, +{ "label": "38/5", "node": 3493, "naklon": 0 }, +{ "label": "38/6", "node": 3580, "naklon": 0 }, +{ "label": "38/7", "node": 3572, "naklon": 0 }, +{ "label": "38/8", "node": 3506, "naklon": 0 }, +{ "label": "38/9", "node": 3503, "naklon": 0 }, +{ "label": "38/10", "node": 3579, "naklon": 0 }, +{ "label": "38/11", "node": 3586, "naklon": 0 }, +{ "label": "38/12", "node": 3495, "naklon": 5 }, +{ "label": "38/13", "node": 3492, "naklon": 5 }, +{ "label": "38/14", "node": 3532, "naklon": 5 }, +{ "label": "38/15", "node": 3574, "naklon": 5 }, +{ "label": "38/16", "node": 4140, "naklon": 5 }, +{ "label": "38/17", "node": 3795, "naklon": 5 }, +{ "label": "38/18", "node": 3788, "naklon": 5 }, +{ "label": "38/19", "node": 3796, "naklon": 5 }, +{ "label": "38/20", "node": 3797, "naklon": 5 }, +{ "label": "38/21", "node": 3798, "naklon": 5 }, +{ "label": "38/22", "node": 3786, "naklon": 5 }, +{ "label": "38/23", "node": 4067, "naklon": 5 }, +{ "label": "38/24", "node": 3773, "naklon": 5 }, +{ "label": "38/25", "node": 3774, "naklon": 5 }, +{ "label": "38/26", "node": 3789, "naklon": 5 }, +{ "label": "38/27", "node": 3520, "naklon": null }, +{ "label": "38/29", "node": 3577, "naklon": 5 }, +{ "label": "38/31", "node": 3530, "naklon": null }, +{ "label": "38/33", "node": 3488, "naklon": 5 }, +{ "label": "38/34", "node": 3505, "naklon": 5 }, +{ "label": "38/36", "node": 3497, "naklon": 5 }, +{ "label": "38/37", "node": 3490, "naklon": 5 }, +{ "label": "38/39", "node": 3585, "naklon": 5 }, +{ "label": "38/40", "node": 3582, "naklon": 5 }, +{ "label": "38/41", "node": 3507, "naklon": 5 }, +{ "label": "38/42", "node": 3484, "naklon": 5 }, +{ "label": "38/43", "node": 3501, "naklon": 5 }, +{ "label": "38/44", "node": 3581, "naklon": 5 }, +{ "label": "38/45", "node": 4192, "naklon": 5 }, +{ "label": "38/46", "node": 3576, "naklon": 5 }, +{ "label": "38/47", "node": 3489, "naklon": 5 }, +{ "label": "38/48", "node": 3573, "naklon": 5 }, +{ "label": "38/49", "node": 3504, "naklon": 5 }, +{ "label": "38/50", "node": 3794, "naklon": 5 }, +{ "label": "38/51", "node": 3485, "naklon": 5 }, +{ "label": "38/52", "node": 3482, "naklon": 5 }, +{ "label": "38/53", "node": 3575, "naklon": 5 }, +{ "label": "38/54", "node": 3499, "naklon": 5 }, +{ "label": "38/55", "node": 3494, "naklon": 5 }, +{ "label": "38/56", "node": 3583, "naklon": 5 }, +{ "label": "38/57", "node": 3570, "naklon": 5 }, +{ "label": "38/58", "node": 3500, "naklon": 0 }, +{ "label": "38/63", "node": 3510, "naklon": null }, +{ "label": "38/64", "node": 3512, "naklon": null }, +{ "label": "38/67", "node": 3535, "naklon": null }, +{ "label": "38/68", "node": 3531, "naklon": null }, +{ "label": "38/69", "node": 3537, "naklon": null }, +{ "label": "39/1", "node": 3522, "naklon": 10 }, +{ "label": "39/2", "node": 4018, "naklon": 10 }, +{ "label": "39/3", "node": 4019, "naklon": 10 }, +{ "label": "39/4", "node": 4154, "naklon": 5 }, +{ "label": "39/5", "node": 3907, "naklon": 5 }, +{ "label": "39/6", "node": 4148, "naklon": 0 }, +{ "label": "39/7", "node": 4153, "naklon": 0 }, +{ "label": "39/8", "node": 3938, "naklon": 0 }, +{ "label": "39/9", "node": 3802, "naklon": 0 }, +{ "label": "39/10", "node": 4015, "naklon": 0 }, +{ "label": "39/11", "node": 3929, "naklon": 0 }, +{ "label": "39/12", "node": 3946, "naklon": 0 }, +{ "label": "39/13", "node": 4014, "naklon": 0 }, +{ "label": "39/14", "node": 4155, "naklon": 0 }, +{ "label": "39/15", "node": 4149, "naklon": 0 }, +{ "label": "39/16", "node": 3642, "naklon": 0 }, +{ "label": "39/17", "node": 3636, "naklon": 5 }, +{ "label": "39/18", "node": 3991, "naklon": 0 }, +{ "label": "39/19", "node": 3994, "naklon": 0 }, +{ "label": "39/20", "node": 3990, "naklon": 0 }, +{ "label": "39/21", "node": 3967, "naklon": 0 }, +{ "label": "39/22", "node": 3977, "naklon": 0 }, +{ "label": "39/23", "node": 3757, "naklon": 15 }, +{ "label": "39/24", "node": 3633, "naklon": 15 }, +{ "label": "39/25", "node": 3744, "naklon": 15 }, +{ "label": "39/26", "node": 4023, "naklon": 5 }, +{ "label": "39/27", "node": 3720, "naklon": 5 }, +{ "label": "39/28", "node": 3734, "naklon": 5 }, +{ "label": "39/29", "node": 3741, "naklon": 5 }, +{ "label": "39/30", "node": 3721, "naklon": 5 }, +{ "label": "39/31", "node": 3845, "naklon": 0 }, +{ "label": "39/32", "node": 3840, "naklon": 0 }, +{ "label": "39/33", "node": 3837, "naklon": null }, +{ "label": "39/34", "node": 3839, "naklon": 0 }, +{ "label": "41/1", "node": 3542, "naklon": null }, +{ "label": "41/2", "node": 3566, "naklon": null }, +{ "label": "41/3", "node": 3548, "naklon": null }, +{ "label": "41/4", "node": 3515, "naklon": null }, +{ "label": "41/5", "node": 3559, "naklon": null }, +{ "label": "41/6", "node": 3509, "naklon": null }, +{ "label": "41/7", "node": 3524, "naklon": null }, +{ "label": "41/8", "node": 3518, "naklon": null }, +{ "label": "41/9", "node": 3182, "naklon": null }, +{ "label": "41/10", "node": 3187, "naklon": null }, +{ "label": "41/11", "node": 3195, "naklon": 0 }, +{ "label": "41/12", "node": 3857, "naklon": 0 }, +{ "label": "41/13", "node": 3183, "naklon": 0 }, +{ "label": "41/14", "node": 3177, "naklon": 0 }, +{ "label": "41/15", "node": 3189, "naklon": 0 }, +{ "label": "41/16", "node": 3186, "naklon": 0 }, +{ "label": "42/1", "node": 3178, "naklon": 0 }, +{ "label": "42/2", "node": 3219, "naklon": 0 }, +{ "label": "42/3", "node": 3475, "naklon": 0 }, +{ "label": "42/4", "node": 3175, "naklon": 0 }, +{ "label": "42/5", "node": 3222, "naklon": 0 }, +{ "label": "42/6", "node": 3221, "naklon": 0 }, +{ "label": "42/7", "node": 3181, "naklon": 0 }, +{ "label": "42/8", "node": 3180, "naklon": 0 }, +{ "label": "42/9", "node": 3218, "naklon": 0 }, +{ "label": "42/10", "node": 3176, "naklon": 0 }, +{ "label": "42/11", "node": 3174, "naklon": 0 }, +{ "label": "42/12", "node": 3220, "naklon": 0 }, +{ "label": "42/13", "node": 3533, "naklon": null }, +{ "label": "42/14", "node": 3543, "naklon": null }, +{ "label": "42/15", "node": 3554, "naklon": null }, +{ "label": "42/16", "node": 3549, "naklon": null }, +{ "label": "43/1", "node": 2857, "naklon": 5 }, +{ "label": "43/2", "node": 2752, "naklon": 5 }, +{ "label": "43/3", "node": 2753, "naklon": 5 }, +{ "label": "43/4", "node": 3024, "naklon": 5 }, +{ "label": "43/5", "node": 2754, "naklon": 5 }, +{ "label": "43/6", "node": 4423, "naklon": 5 }, +{ "label": "43/7", "node": 4368, "naklon": 5 }, +{ "label": "43/8", "node": 2978, "naklon": 5 }, +{ "label": "43/9", "node": 2868, "naklon": 5 }, +{ "label": "43/10", "node": 4377, "naklon": 5 }, +{ "label": "43/11", "node": 2757, "naklon": 5 }, +{ "label": "43/12", "node": 2970, "naklon": 5 }, +{ "label": "43/13", "node": 2758, "naklon": 5 }, +{ "label": "43/14", "node": 4378, "naklon": 5 }, +{ "label": "43/15", "node": 2759, "naklon": 5 }, +{ "label": "43/16", "node": 4342, "naklon": 5 }, +{ "label": "43/17", "node": 3026, "naklon": null }, +{ "label": "43/18", "node": 2986, "naklon": null }, +{ "label": "43/19", "node": 4343, "naklon": null }, +{ "label": "43/20", "node": 2760, "naklon": null }, +{ "label": "43/21", "node": 4379, "naklon": null }, +{ "label": "43/22", "node": 2971, "naklon": null }, +{ "label": "43/23", "node": 2761, "naklon": null }, +{ "label": "43/24", "node": 2762, "naklon": null }, +{ "label": "43/25", "node": 4339, "naklon": null }, +{ "label": "43/26", "node": 4380, "naklon": null }, +{ "label": "43/27", "node": 2975, "naklon": null }, +{ "label": "43/28", "node": 3003, "naklon": null }, +{ "label": "43/29", "node": 4338, "naklon": null }, +{ "label": "43/30", "node": 3002, "naklon": null }, +{ "label": "43/31", "node": 4345, "naklon": null }, +{ "label": "43/32", "node": 2979, "naklon": null }, +{ "label": "43/33", "node": 2989, "naklon": null }, +{ "label": "43/34", "node": 2996, "naklon": null }, +{ "label": "43/35", "node": 2972, "naklon": null }, +{ "label": "43/36", "node": 2988, "naklon": null }, +{ "label": "43/37", "node": 4344, "naklon": null }, +{ "label": "43/38", "node": 3022, "naklon": null }, +{ "label": "43/39", "node": 4341, "naklon": null }, +{ "label": "43/40", "node": 2983, "naklon": null }, +{ "label": "43/41", "node": 2995, "naklon": null }, +{ "label": "43/42", "node": 2763, "naklon": null }, +{ "label": "43/43", "node": 2764, "naklon": null }, +{ "label": "43/44", "node": 2765, "naklon": null }, +{ "label": "43/45", "node": 2766, "naklon": null }, +{ "label": "43/46", "node": 2767, "naklon": null }, +{ "label": "43/47", "node": 2768, "naklon": null }, +{ "label": "43/48", "node": 3018, "naklon": null }, +{ "label": "43/49", "node": 2982, "naklon": null }, +{ "label": "43/50", "node": 3019, "naklon": 0 }, +{ "label": "43/51", "node": 3013, "naklon": null }, +{ "label": "43/52", "node": 3007, "naklon": null }, +{ "label": "43/53", "node": 2980, "naklon": null }, +{ "label": "43/54", "node": 3011, "naklon": null }, +{ "label": "43/55", "node": 2672, "naklon": null }, +{ "label": "43/56", "node": 2673, "naklon": null }, +{ "label": "43/57", "node": 2674, "naklon": null }, +{ "label": "43/58", "node": 2675, "naklon": null }, +{ "label": "43/59", "node": 2676, "naklon": null }, +{ "label": "43/60", "node": 2677, "naklon": null }, +{ "label": "43/61", "node": 2678, "naklon": null }, +{ "label": "43/62", "node": 2679, "naklon": null }, +{ "label": "43/63", "node": 2680, "naklon": null }, +{ "label": "43/64", "node": 2840, "naklon": null }, +{ "label": "43/65", "node": 2682, "naklon": null }, +{ "label": "43/66", "node": 2683, "naklon": null }, +{ "label": "43/67", "node": 2684, "naklon": 0 }, +{ "label": "43/68", "node": 2685, "naklon": null }, +{ "label": "43/69", "node": 2686, "naklon": null }, +{ "label": "43/70", "node": 2687, "naklon": null }, +{ "label": "43/71", "node": 2688, "naklon": null }, +{ "label": "43/72", "node": 2689, "naklon": null }, +{ "label": "43/73", "node": 2690, "naklon": null }, +{ "label": "43/74", "node": 2691, "naklon": null }, +{ "label": "43/75", "node": 2692, "naklon": null }, +{ "label": "43/76", "node": 2693, "naklon": 0 }, +{ "label": "43/77", "node": 2694, "naklon": null }, +{ "label": "43/78", "node": 2695, "naklon": null }, +{ "label": "43/79", "node": 2696, "naklon": 0 }, +{ "label": "43/80", "node": 2697, "naklon": null }, +{ "label": "43/81", "node": 2698, "naklon": 0 }, +{ "label": "43/82", "node": 2699, "naklon": null }, +{ "label": "43/83", "node": 2700, "naklon": 0 }, +{ "label": "43/84", "node": 2744, "naklon": null }, +{ "label": "43/85", "node": 2745, "naklon": 0 }, +{ "label": "43/86", "node": 2746, "naklon": null }, +{ "label": "43/87", "node": 2747, "naklon": 0 }, +{ "label": "43/88", "node": 2748, "naklon": null }, +{ "label": "43/89", "node": 2749, "naklon": 0 }, +{ "label": "43/90", "node": 2841, "naklon": null }, +{ "label": "45/1", "node": 4237, "naklon": 5 }, +{ "label": "45/2", "node": 4226, "naklon": 5 }, +{ "label": "45/3", "node": 4242, "naklon": 5 }, +{ "label": "45/4", "node": 4179, "naklon": 5 }, +{ "label": "45/5", "node": 4247, "naklon": 5 }, +{ "label": "45/6", "node": 4245, "naklon": 5 }, +{ "label": "45/7", "node": 3872, "naklon": 5 }, +{ "label": "45/8", "node": 4175, "naklon": 5 }, +{ "label": "45/9", "node": 4236, "naklon": 5 }, +{ "label": "45/10", "node": 4170, "naklon": 5 }, +{ "label": "45/11", "node": 4238, "naklon": 5 }, +{ "label": "45/12", "node": 4246, "naklon": 5 }, +{ "label": "45/13", "node": 4166, "naklon": 5 }, +{ "label": "45/14", "node": 4227, "naklon": 5 }, +{ "label": "45/15", "node": 4171, "naklon": 5 }, +{ "label": "45/16", "node": 4180, "naklon": 5 }, +{ "label": "45/17", "node": 4244, "naklon": 5 }, +{ "label": "45/18", "node": 4199, "naklon": 5 }, +{ "label": "45/19", "node": 4239, "naklon": 5 }, +{ "label": "45/20", "node": 4207, "naklon": 5 }, +{ "label": "45/21", "node": 4223, "naklon": 5 }, +{ "label": "45/22", "node": 4230, "naklon": 5 }, +{ "label": "45/23", "node": 4233, "naklon": 5 }, +{ "label": "45/24", "node": 4222, "naklon": 5 }, +{ "label": "45/25", "node": 4217, "naklon": 5 }, +{ "label": "45/26", "node": 4243, "naklon": 5 }, +{ "label": "45/27", "node": 4200, "naklon": 5 }, +{ "label": "45/28", "node": 4228, "naklon": 5 }, +{ "label": "45/29", "node": 4211, "naklon": 5 }, +{ "label": "45/30", "node": 4234, "naklon": 5 }, +{ "label": "45/31", "node": 4235, "naklon": 5 }, +{ "label": "45/32", "node": 4203, "naklon": 5 }, +{ "label": "45/33", "node": 4240, "naklon": 5 }, +{ "label": "45/34", "node": 4224, "naklon": 5 }, +{ "label": "45/35", "node": 4232, "naklon": 5 }, +{ "label": "45/36", "node": 4231, "naklon": 5 }, +{ "label": "45/37", "node": 4161, "naklon": 5 }, +{ "label": "45/38", "node": 4225, "naklon": 5 }, +{ "label": "45/39", "node": 4241, "naklon": 5 }, +{ "label": "45/40", "node": 4229, "naklon": 5 }, +{ "label": "45/41", "node": 4221, "naklon": 5 }, +{ "label": "45/42", "node": 4212, "naklon": 5 }, +{ "label": "45/43", "node": 4216, "naklon": 5 }, +{ "label": "45/44", "node": 3864, "naklon": null }, +{ "label": "46/1", "node": 3806, "naklon": 5 }, +{ "label": "46/2", "node": 3813, "naklon": 5 }, +{ "label": "46/3", "node": 3815, "naklon": 5 }, +{ "label": "46/4", "node": 3807, "naklon": 5 }, +{ "label": "46/5", "node": 3895, "naklon": 5 }, +{ "label": "46/6", "node": 3809, "naklon": 5 }, +{ "label": "46/7", "node": 3820, "naklon": 5 }, +{ "label": "46/8", "node": 3805, "naklon": 5 }, +{ "label": "46/9", "node": 3894, "naklon": 0 }, +{ "label": "46/10", "node": 4055, "naklon": 0 }, +{ "label": "46/11", "node": 3812, "naklon": 5 }, +{ "label": "46/12", "node": 3822, "naklon": 5 }, +{ "label": "46/13", "node": 3821, "naklon": 5 }, +{ "label": "46/14", "node": 3808, "naklon": 5 }, +{ "label": "46/15", "node": 3799, "naklon": 5 }, +{ "label": "46/16", "node": 3816, "naklon": 5 }, +{ "label": "46/17", "node": 3751, "naklon": 5 }, +{ "label": "46/18", "node": 3814, "naklon": 5 }, +{ "label": "46/19", "node": 4044, "naklon": 0 }, +{ "label": "46/20", "node": 3931, "naklon": 0 }, +{ "label": "46/21", "node": 3902, "naklon": 5 }, +{ "label": "46/22", "node": 3916, "naklon": 5 }, +{ "label": "46/23", "node": 3892, "naklon": 5 }, +{ "label": "46/24", "node": 3914, "naklon": 5 }, +{ "label": "46/25", "node": 3898, "naklon": 5 }, +{ "label": "46/26", "node": 3897, "naklon": 5 }, +{ "label": "46/27", "node": 3885, "naklon": 5 }, +{ "label": "46/28", "node": 3906, "naklon": 5 }, +{ "label": "46/29", "node": 3930, "naklon": 0 }, +{ "label": "46/30", "node": 3936, "naklon": 0 }, +{ "label": "46/31", "node": 3860, "naklon": 5 }, +{ "label": "46/32", "node": 3841, "naklon": 5 }, +{ "label": "46/33", "node": 3873, "naklon": 5 }, +{ "label": "46/34", "node": 3854, "naklon": 5 }, +{ "label": "46/35", "node": 3939, "naklon": 5 }, +{ "label": "46/36", "node": 3858, "naklon": 5 }, +{ "label": "46/37", "node": 3940, "naklon": 5 }, +{ "label": "46/38", "node": 4035, "naklon": 5 }, +{ "label": "47/1", "node": 3373, "naklon": 0 }, +{ "label": "47/2", "node": 3374, "naklon": 0 }, +{ "label": "47/3", "node": 3384, "naklon": 0 }, +{ "label": "47/4", "node": 3385, "naklon": 0 }, +{ "label": "48/1", "node": 4051, "naklon": 5 }, +{ "label": "48/2", "node": 4041, "naklon": 5 }, +{ "label": "48/3", "node": 4056, "naklon": 5 }, +{ "label": "48/4", "node": 3875, "naklon": 5 }, +{ "label": "48/5", "node": 4061, "naklon": 5 }, +{ "label": "48/6", "node": 4047, "naklon": 5 }, +{ "label": "48/7", "node": 4060, "naklon": 5 }, +{ "label": "48/8", "node": 4059, "naklon": 5 }, +{ "label": "48/9", "node": 4058, "naklon": 5 }, +{ "label": "48/10", "node": 3635, "naklon": 5 }, +{ "label": "48/11", "node": 3640, "naklon": 5 }, +{ "label": "48/12", "node": 3747, "naklon": 5 }, +{ "label": "48/13", "node": 3629, "naklon": 5 }, +{ "label": "48/14", "node": 4048, "naklon": 5 }, +{ "label": "48/15", "node": 4063, "naklon": 5 }, +{ "label": "48/16", "node": 4062, "naklon": 5 }, +{ "label": "48/17", "node": 4043, "naklon": 5 }, +{ "label": "48/18", "node": 4052, "naklon": 5 }, +{ "label": "48/19", "node": 4042, "naklon": 5 }, +{ "label": "48/20", "node": 4053, "naklon": 5 }, +{ "label": "50/15A", "node": 4167, "naklon": null }, +{ "label": "50/15B", "node": 4159, "naklon": null }, +{ "label": "50/1", "node": 4183, "naklon": 0 }, +{ "label": "50/2", "node": 4157, "naklon": 0 }, +{ "label": "50/3", "node": 4160, "naklon": 0 }, +{ "label": "50/4", "node": 4173, "naklon": 0 }, +{ "label": "50/5", "node": 4177, "naklon": 0 }, +{ "label": "50/6", "node": 4174, "naklon": 0 }, +{ "label": "50/7", "node": 4178, "naklon": 0 }, +{ "label": "50/8", "node": 4195, "naklon": 0 }, +{ "label": "50/9", "node": 4169, "naklon": 0 }, +{ "label": "50/10", "node": 4162, "naklon": 0 }, +{ "label": "50/11", "node": 4158, "naklon": 0 }, +{ "label": "50/12", "node": 4182, "naklon": 0 }, +{ "label": "50/13", "node": 4194, "naklon": 0 }, +{ "label": "50/14", "node": 4184, "naklon": 0 }, +{ "label": "50/16", "node": 4197, "naklon": null }, +{ "label": "50/17", "node": 4164, "naklon": null }, +{ "label": "50/18", "node": 3306, "naklon": null }, +{ "label": "50/19", "node": 4168, "naklon": null }, +{ "label": "50/20", "node": 4193, "naklon": null }, +{ "label": "50/21", "node": 4187, "naklon": null }, +{ "label": "50/22", "node": 4163, "naklon": null }, +{ "label": "50/23", "node": 4165, "naklon": null }, +{ "label": "50/24", "node": 4185, "naklon": null }, +{ "label": "50/25", "node": 3904, "naklon": null }, +{ "label": "53/1", "node": 2619, "naklon": 0 }, +{ "label": "53/2", "node": 2623, "naklon": 0 }, +{ "label": "53/3", "node": 2617, "naklon": 0 }, +{ "label": "53/4", "node": 2622, "naklon": 0 }, +{ "label": "53/5", "node": 2618, "naklon": 0 }, +{ "label": "53/6", "node": 2626, "naklon": 0 }, +{ "label": "53/7", "node": 2869, "naklon": 0 }, +{ "label": "53/8", "node": 2613, "naklon": 0 }, +{ "label": "53/9", "node": 2608, "naklon": 0 }, +{ "label": "53/10", "node": 2611, "naklon": 0 }, +{ "label": "53/11", "node": 2598, "naklon": 0 }, +{ "label": "53/12", "node": 3528, "naklon": 0 }, +{ "label": "53/13", "node": 3545, "naklon": 0 }, +{ "label": "53/14", "node": 2620, "naklon": 0 }, +{ "label": "53/15", "node": 2612, "naklon": 0 }, +{ "label": "53/16", "node": 2615, "naklon": 0 }, +{ "label": "53/17", "node": 3722, "naklon": 0 }, +{ "label": "53/18", "node": 2624, "naklon": 0 }, +{ "label": "53/19", "node": 2609, "naklon": 0 }, +{ "label": "53/20", "node": 2625, "naklon": 0 }, +{ "label": "53/21", "node": 2602, "naklon": 0 }, +{ "label": "53/22", "node": 2610, "naklon": 0 }, +{ "label": "53/23", "node": 2599, "naklon": 0 }, +{ "label": "53/24", "node": 2605, "naklon": 0 }, +{ "label": "53/25", "node": 2593, "naklon": 0 }, +{ "label": "53/26", "node": 3074, "naklon": 0 }, +{ "label": "53/27", "node": 2740, "naklon": 0 }, +{ "label": "53/28", "node": 2614, "naklon": 0 }, +{ "label": "53/29", "node": 2601, "naklon": 0 }, +{ "label": "53/30", "node": 4196, "naklon": 0 }, +{ "label": "53/31", "node": 2607, "naklon": 0 }, +{ "label": "53/32", "node": 2582, "naklon": 0 }, +{ "label": "53/33", "node": 2594, "naklon": 0 }, +{ "label": "53/34", "node": 2589, "naklon": 0 }, +{ "label": "53/35", "node": 2596, "naklon": 0 }, +{ "label": "53/36", "node": 2603, "naklon": 0 }, +{ "label": "53/37", "node": 2597, "naklon": 0 }, +{ "label": "53/38", "node": 2590, "naklon": 0 }, +{ "label": "53/39", "node": 2581, "naklon": 0 }, +{ "label": "53/40", "node": 2583, "naklon": 0 }, +{ "label": "53/41", "node": 2580, "naklon": 0 }, +{ "label": "53/42", "node": 2579, "naklon": 0 }, +{ "label": "53/43", "node": 2797, "naklon": 0 }, +{ "label": "53/44", "node": 2577, "naklon": 0 }, +{ "label": "53/45", "node": 2586, "naklon": 0 }, +{ "label": "53/46", "node": 2588, "naklon": 0 }, +{ "label": "53/47", "node": 2591, "naklon": 0 }, +{ "label": "53/48", "node": 2592, "naklon": 0 }, +{ "label": "53/49", "node": 2573, "naklon": 0 }, +{ "label": "53/50", "node": 2595, "naklon": 0 }, +{ "label": "53/51", "node": 2587, "naklon": 0 }, +{ "label": "53/52", "node": 2578, "naklon": 0 }, +{ "label": "53/53", "node": 2574, "naklon": 0 }, +{ "label": "53/54", "node": 2571, "naklon": 0 }, +{ "label": "53/55", "node": 2570, "naklon": 0 }, +{ "label": "53/56", "node": 2576, "naklon": 0 }, +{ "label": "53/57", "node": 2881, "naklon": 0 }, +{ "label": "53/58", "node": 2575, "naklon": 0 }, +{ "label": "53/59", "node": 2572, "naklon": 0 }, +{ "label": "53/60", "node": 2569, "naklon": 0 }, +{ "label": "55/1", "node": 4324, "naklon": 0 }, +{ "label": "55/2", "node": 4319, "naklon": 0 }, +{ "label": "55/3", "node": 4327, "naklon": 0 }, +{ "label": "55/4", "node": 4333, "naklon": 0 }, +{ "label": "55/5", "node": 4332, "naklon": 0 }, +{ "label": "55/6", "node": 4320, "naklon": 0 }, +{ "label": "55/7", "node": 4317, "naklon": 0 }, +{ "label": "55/8", "node": 4318, "naklon": 0 }, +{ "label": "55/9", "node": 4328, "naklon": 0 }, +{ "label": "55/10", "node": 4323, "naklon": 0 }, +{ "label": "55/11", "node": 4325, "naklon": 0 }, +{ "label": "55/12", "node": 4326, "naklon": 0 }, +{ "label": "55/13", "node": 4316, "naklon": 0 }, +{ "label": "55/14", "node": 4322, "naklon": 0 }, +{ "label": "55/15", "node": 4331, "naklon": 0 }, +{ "label": "55/16", "node": 4321, "naklon": 0 }, +{ "label": "55/17", "node": 4315, "naklon": 0 }, +{ "label": "55/18", "node": 4329, "naklon": 0 }, +{ "label": "55/19", "node": 4334, "naklon": 0 }, +{ "label": "55/20", "node": 4330, "naklon": 0 } +]; + +module.exports = { naklony }; diff --git a/RVO50/databases/modbus_config.js b/RVO50/databases/modbus_config.js new file mode 100755 index 0000000..b73116a --- /dev/null +++ b/RVO50/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/RVO50/databases/nodes.table b/RVO50/databases/nodes.table new file mode 100755 index 0000000..cbbd678 --- /dev/null +++ b/RVO50/databases/nodes.table @@ -0,0 +1,27 @@ +node:number|pole_number:string|node_type:string|tbname:string|line:number|profile:string|processed:boolean|status:boolean|time_of_last_communication:number ++|4169|9|NEMA|eod9aRWLVl34Gx1Dn7VoWPA2rz6qjgmpEXwQJN5Z|1||1|1|1760574243521|............. ++|4168|19|NEMA|XMBbew5z4ELrZa2mRAd5L108vPN6gy3DdVYlpKjq|1||1|1|1760574243377|............. ++|4162|10|NEMA|3a5oqJN1bgnx4Ol9dk868aAByE6jQ8mKDWMpGrLV|1||1|1|1760574224266|............. ++|2746|22|NEMA|WlVJBygjDZMeKX3vnAMz3208NqdmG2x1Y69LQ4P5|1||1|1|1760574226231|............. ++|4164|17|NEMA|roKgWqY95V3mXMRzyAjmp37bLjexpJPvaGDBw826|1||1|1|1760574229140|............. ++|4165|23|NEMA|5dBNwRp9graYJxZn409wnr7lVov1b2QLPDqGm6XK|1||1|1|1760574240836|............. ++|4167|15A|NEMA|52dD6ZlV1QaOpRBmbAqKaxkKnGzWMLj4eJq38Pgo|1||1|1|1760574242866|............. ++|4173|4|NEMA|K94XLav1glVRnyQ6r01BYNkme3YJwBxM5oOzdP2j|1||1|1|1760574244064|............. ++|4174|6|NEMA|B5EoxeMVp4zwr8nqW0GjEeARjvD1PNamOGbLg63Z|1||1|1|1760574245934|............. ++|4177|5|NEMA|d9x2V5LGYBzXp4mMRAOBqe7PloaqJwnQj6DgrNe3|1||1|1|1760574254019|............. ++|4350|7|NEMA|aw4eELG2DlPMdn1JW0B1mMAqQXOZRN3xB5yp8VKr|1||1|1|1760574263367|............. ++|4182|12|NEMA|wvKJdZML6mXP4DzWBAXWJz7jxNloa5g23Ve9Y1ry|1||1|1|1760574254179|............. ++|4183|1|NEMA|dz4ojlpP85JMgDLZWkQO5dAaKYqQexEr62GXRV1y|1||1|1|1760574254354|............. ++|4156|24|NEMA|zrR51V2ajQ9ZLygPKkEmE4kYDq38xOJolENBXGnv|1||1|1|1760574184078|............. ++|4100|21|NEMA|zdQO8GwxDqjRgP4137Y1wG7NyKlpem2nL65rvVJY|1||1|1|1760574232511|............. ++|4193|20|NEMA|gYbDLqlyZVoRerQpB72reR7WJnwM5z24POKa8Exj|1||1|1|1760574261929|............. ++|4194|13|NEMA|Nzp2OoJlqn6r1ZgvdA3GYYAabBwP5G4eE3RQmyxD|1||1|1|1760574255617|............. ++|4195|8|NEMA|ZmRwd93QL4gaezxEbAxWaW71prn2XjlPvGyqJ6BO|1||1|1|1760574255793|............. ++|3306|18|NEMA|nJL5lPMwBx23YpqRe0rlR37damXvWVbOrD4gNzy8|1||1|1|1760574257358|............. ++|4197|16|NEMA|E6Kg9oDnLWyzPRMva7vraB7Jxp4VG58qO2w1lZYe|1||1|1|1760574278531|............. ++|3904|25|NEMA|o9vbeQlLMVg8j5dq4keg45ANxZpEmnXzwYKO1ar2|1||1|1|1760574183759|............. ++|4157|2|NEMA|d5xjWYMwEJon6rLlK7yBpJAqgV4DaOeNB9ZX3Gzb|1||1|1|1760574184574|............. ++|4158|11|NEMA|EjgWGnXaLy9opPOz20n6pn086BlYM3w1deVQvbKr|1||1|1|1760574186236|............. ++|4159|15B|NEMA|rDbQ84xzwgdqEoPm3kbJbLk9anOZY1RXyBv2LVM6|1||1|1|1760574272011|............. ++|4160|3|NEMA|gRoJEyXVx4qD9er287LPW57wBzGldaPjLWQKm3Mv|1||1|1|1760574203094|............. ++|4184|14|NEMA|PLBJzmK1r3Gynd6OW0gG4Y0e5wV4vx9bDEqNgYR8|1||1|1|1760574254834|............. diff --git a/RVO50/databases/nodes_original/nodes_original.table b/RVO50/databases/nodes_original/nodes_original.table new file mode 100755 index 0000000..7e8bfa6 --- /dev/null +++ b/RVO50/databases/nodes_original/nodes_original.table @@ -0,0 +1 @@ +[{"4169": "eod9aRWLVl34Gx1Dn7VoWPA2rz6qjgmpEXwQJN5Z"}, {"4168": "XMBbew5z4ELrZa2mRAd5L108vPN6gy3DdVYlpKjq"}, {"4162": "3a5oqJN1bgnx4Ol9dk868aAByE6jQ8mKDWMpGrLV"}, {"2746": "WlVJBygjDZMeKX3vnAMz3208NqdmG2x1Y69LQ4P5"}, {"4164": "roKgWqY95V3mXMRzyAjmp37bLjexpJPvaGDBw826"}, {"4165": "5dBNwRp9graYJxZn409wnr7lVov1b2QLPDqGm6XK"}, {"4167": "52dD6ZlV1QaOpRBmbAqKaxkKnGzWMLj4eJq38Pgo"}, {"4173": "K94XLav1glVRnyQ6r01BYNkme3YJwBxM5oOzdP2j"}, {"4174": "B5EoxeMVp4zwr8nqW0GjEeARjvD1PNamOGbLg63Z"}, {"4177": "d9x2V5LGYBzXp4mMRAOBqe7PloaqJwnQj6DgrNe3"}, {"4350": "aw4eELG2DlPMdn1JW0B1mMAqQXOZRN3xB5yp8VKr"}, {"4182": "wvKJdZML6mXP4DzWBAXWJz7jxNloa5g23Ve9Y1ry"}, {"4183": "dz4ojlpP85JMgDLZWkQO5dAaKYqQexEr62GXRV1y"}, {"4156": "zrR51V2ajQ9ZLygPKkEmE4kYDq38xOJolENBXGnv"}, {"4100": "zdQO8GwxDqjRgP4137Y1wG7NyKlpem2nL65rvVJY"}, {"4193": "gYbDLqlyZVoRerQpB72reR7WJnwM5z24POKa8Exj"}, {"4194": "Nzp2OoJlqn6r1ZgvdA3GYYAabBwP5G4eE3RQmyxD"}, {"4195": "ZmRwd93QL4gaezxEbAxWaW71prn2XjlPvGyqJ6BO"}, {"3306": "nJL5lPMwBx23YpqRe0rlR37damXvWVbOrD4gNzy8"}, {"4197": "E6Kg9oDnLWyzPRMva7vraB7Jxp4VG58qO2w1lZYe"}, {"3904": "o9vbeQlLMVg8j5dq4keg45ANxZpEmnXzwYKO1ar2"}, {"4157": "d5xjWYMwEJon6rLlK7yBpJAqgV4DaOeNB9ZX3Gzb"}, {"4158": "EjgWGnXaLy9opPOz20n6pn086BlYM3w1deVQvbKr"}, {"4159": "rDbQ84xzwgdqEoPm3kbJbLk9anOZY1RXyBv2LVM6"}, {"4160": "gRoJEyXVx4qD9er287LPW57wBzGldaPjLWQKm3Mv"}, {"4184": "PLBJzmK1r3Gynd6OW0gG4Y0e5wV4vx9bDEqNgYR8"}] \ No newline at end of file diff --git a/RVO50/databases/notifications.table b/RVO50/databases/notifications.table new file mode 100755 index 0000000..f7c96cb --- /dev/null +++ b/RVO50/databases/notifications.table @@ -0,0 +1,41 @@ +key:string|weight:string|sk:string|en:string ++|switching_profile_point_applied_to_line|INFORMATIONAL|Aplikovaný bod spínacieho profilu na línií č. ${line} : ${value}|Switching profile point applied to line no. ${line} : ${value}|............... ++|dusk_has_occured|INFORMATIONAL|Nastal súmrak: ${value}|Dusk has occured: ${value}|............... ++|dawn_has_occured|INFORMATIONAL|Nastal úsvit: ${value}|Dawn has occured: ${value}|............... ++|dimming_profile_was_successfully_received_by_node|NOTICE|Stmievací profil bol úspešne prijatý nodom č. ${node}|Dimming profile was successfully received by node no. ${node}|............... ++|master_node_is_responding_again|NOTICE|Master node začal znovu odpovedať|Master node is responding again|............... ++|command_was_sent_from_terminal_interface|DEBUG|Z terminálu bol odoslaný príkaz|A command was sent from terminal interface|............... ++|master_node_is_not_responding|ALERT|Master node neodpovedá|Master node is not responding|............... ++|configuration_of_dimming_profile_to_node_failed|ALERT|Konfigurácia stmievacieho profilu pre node č. ${node} zlyhala|Configuration of dimming profile to node no. ${node} has failed|............... ++|circuit_breaker_was_turned_on_line|NOTICE|Zapnutie ističa na línii č. ${line}|Circuit breaker was turned on - line no. ${line}|............... ++|circuit_breaker_was_turned_off_line|ERROR|Vypnutie ističa na línií č. ${line}|Circuit breaker was turned off - line no. ${line}|............... ++|dimming_profile_was_processed_for_node|INFORMATIONAL|Stmievací profil bol spracovaný pre node č. ${node}|Dimming profile was processed for node no. ${node}|............... ++|switching_profile_was_processed_for_line|INFORMATIONAL|Spínací profil bol spracovaný pre líniu č. ${line}|Switching profile was processed for line no. ${line}|............... ++|thermometer_is_not_responding|WARNING|Teplomer neodpovedá|Thermometer is not responding|............... ++|thermometer_is_responding_again|NOTICE|Teplomer znovu odpovedá|Thermometer is responding again|............... ++|thermometer_sends_invalid_data|WARNING|Teplomer posiela neplatné hodnoty|Thermometer sends invalid data|............... ++|main_switch_has_been_turned_off|CRITICAL|Hlavný vypínač bol vypnutý|Main switch has been turned off|............... ++|main_switch_has_been_turned_on|NOTICE|Hlavný vypínač bol zapnutý|Main switch has been turned on|............... ++|power_supply_has_disconnected_input|ALERT|Napájací zdroj nemá napätie na vstupe|Power supply has disconnected input|............... ++|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_main_open|NOTICE|Hlavné dvere boli otvorené|Main door has been opened|............... ++|door_em_open|NOTICE|Dvere silovej časti boli otvorené|Power door has been opened|............... ++|door_main_open_without_permission|WARNING|Hlavné dvere boli otvorené bez povolenia - zapnutá siréna|Main door has been opened without permission - alarm is on|............... ++|door_em_open_without_permission|WARNING|Dvere silovej časti boli otvorené bez povolenia|Power door has been opened without permission|............... ++|door_main_close|NOTICE|Hlavné dvere boli zatvorené|Main door has been closed|............... ++|door_em_close|NOTICE|Dvere silovej časti boli zatvorené|Power door has been closed|............... ++|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|............... ++|electrometer_ok|NOTICE|Elektromer znovu odpovedá|Electrometer is responding again|............... ++|no_voltage_on_phase|CRITICAL|Na fáze č. ${phase} nie je napätie|No voltage detected on phase no. ${phase}|............... ++|voltage_on_phase_restored|NOTICE|Napätie na fáze č. ${phase} bolo obnovené|Voltage on phase no. ${phase} has been restored|............... ++|flow_start|NOTICE|FLOW bol spustený|FLOW has been started |............... ++|twilight_sensor_nok|ERROR|Sensor súmraku neodpovedá|Twilight sensor is not responding|............... ++|twilight_sensor_ok|NOTICE|Sensor súmraku znovu odpovedá|Twilight sensor is responding again|............... ++|lamps_have_turned_on|NOTICE|Lampy sa zapli|Lamps have turned on|............... ++|lamps_have_turned_off|NOTICE|Lampy sa vypli|Lamps have turned off|............... ++|flow_restart|NOTICE|FLOW bol reštartovaný|FLOW has been restarted|............... ++|nodes_db_changed|NOTICE|Zmena v node databáze|Node db has changed|............... diff --git a/RVO50/databases/pins.table b/RVO50/databases/pins.table new file mode 100755 index 0000000..0eb3d05 --- /dev/null +++ b/RVO50/databases/pins.table @@ -0,0 +1,14 @@ +pin:string|type:string|line:number +*|input1_01|door_condition|0|........... +*|input1_02|rotary_switch_state|0|........... +*|input1_03|rotary_switch_state|0|........... +*|input1_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/RVO50/databases/relays.table b/RVO50/databases/relays.table new file mode 100755 index 0000000..9f08e87 --- /dev/null +++ b/RVO50/databases/relays.table @@ -0,0 +1,5 @@ +line:number|tbname:string|contactor:number|profile:string ++|0|PjLblDgRBO6WQqnxmkJ1g60Jv3ewZN4p5a89yKdY|1||........... ++|1|apKVJBwOyrP35m2lv7Kz1qkYXbeWNd64En9GxRqg|9|{"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|o9vbeQlLMVg8j5dq4kegr5ANxZpEmnXzwYKO1ar2|9|{"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|gP1eOZVj3Q9lv5aDEk4EG47rdpqW8yLm2BbKzJxM|9|{"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/RVO50/databases/settings.table b/RVO50/databases/settings.table new file mode 100755 index 0000000..e537c9e --- /dev/null +++ b/RVO50/databases/settings.table @@ -0,0 +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|project_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|cloud_topic:string|has_main_switch:boolean|daily_report:boolean|send_changed_node_numbers:boolean ++|rvo_senica_50_10.0.0.139|en|28.990C9D0E0000|48.70826502|17.28455203|192.168.252.1|rvo_senica_50_10.0.0.139|1i30tVyg35Vlk4fHyiSk|1883|0|77|unipi|ttyUSB0|1|20|5|6|1|u139|0|1|1|................................................... diff --git a/RVO50/databases/tbdata.nosql b/RVO50/databases/tbdata.nosql new file mode 100755 index 0000000..c8555fd --- /dev/null +++ b/RVO50/databases/tbdata.nosql @@ -0,0 +1,4 @@ +-"PjLblDgRBO6WQqnxmkJ1g60Jv3ewZN4p5a89yKdY":[{"ts":1760530280599,"values":{"_event":{"type":"notice","status":"new","source":{"func":"modbus_reader","component":"1699965957410","component_name":"Modbus reader","edge":"PjLblDgRBO6WQqnxmkJ1g60Jv3ewZN4p5a89yKdY"},"message":{"sk":"rvo_senica_50_10.0.0.139: FLOW bol reštartovaný","en":"rvo_senica_50_10.0.0.139: FLOW has been restarted"},"message_data":""}}}],"id":"3000311001en71b"} +-"PjLblDgRBO6WQqnxmkJ1g60Jv3ewZN4p5a89yKdY":[{"ts":1760530280675,"values":{"edge_fw_version":"2025-10-08","maintenance_mode":false}}],"id":"3000311002en70b"} +-"PjLblDgRBO6WQqnxmkJ1g60Jv3ewZN4p5a89yKdY":[{"ts":1760530280688,"values":{"statecode":2,"power_mode":"Automatic"}}],"id":"3000311004en70b"} +-"PjLblDgRBO6WQqnxmkJ1g60Jv3ewZN4p5a89yKdY":[{"ts":1760530280718,"values":{"_event":{"type":"notice","status":"new","source":{"func":"rsPort.open()","component":"1699963668903","component_name":"DIDO_Controller","edge":"PjLblDgRBO6WQqnxmkJ1g60Jv3ewZN4p5a89yKdY"},"message":{"sk":"rvo_senica_50_10.0.0.139: FLOW bol spustený","en":"rvo_senica_50_10.0.0.139: FLOW has been started "},"message_data":""}}}],"id":"3000311006en70b"} diff --git a/RVO50/databases/tbdatacloud.nosql b/RVO50/databases/tbdatacloud.nosql new file mode 100755 index 0000000..d227ab3 --- /dev/null +++ b/RVO50/databases/tbdatacloud.nosql @@ -0,0 +1,3 @@ +-"PjLblDgRBO6WQqnxmkJ1g60Jv3ewZN4p5a89yKdY":[{"ts":1760530280675,"values":{"edge_fw_version":"2025-10-08","maintenance_mode":false}}],"id":"3000311003en71b"} +-"PjLblDgRBO6WQqnxmkJ1g60Jv3ewZN4p5a89yKdY":[{"ts":1760530280688,"values":{"statecode":2,"power_mode":"Automatic"}}],"id":"3000311005en71b"} +-"PjLblDgRBO6WQqnxmkJ1g60Jv3ewZN4p5a89yKdY":[{"ts":1760530280718,"values":{"_event":{"type":"notice","status":"new","source":{"func":"rsPort.open()","component":"1699963668903","component_name":"DIDO_Controller","edge":"PjLblDgRBO6WQqnxmkJ1g60Jv3ewZN4p5a89yKdY"},"message":{"sk":"rvo_senica_50_10.0.0.139: FLOW bol spustený","en":"rvo_senica_50_10.0.0.139: FLOW has been started "},"message_data":""}}}],"id":"3000311007en71b"} diff --git a/RVO50/databases/total_energy.js b/RVO50/databases/total_energy.js new file mode 100755 index 0000000..dde340e --- /dev/null +++ b/RVO50/databases/total_energy.js @@ -0,0 +1,38 @@ +//key is rvo_number, value is max energy when lamps are on +const total_energy = { + 1: 580, + 2: 1100, + 3: 3700, + 4: 4100, + 7: 360, + 12: 1700, + 13: 5400, + 14: 440, + 15: 6100, + 16: 4800, + 20: 1600, + 21: 1000, + 22: 2600, + 23: 1000, + 25: 2600, + 33: 240, + 34: 4000, + 35: 2700, + 36: 820, + 37: 1400, + 35: 3500, + 39: 1170, + 41: 740, + 42: 660, + 43: 4900, + 45: 930, + 46: 700, + 47: 1100, + 48: 1500, + 50: 3200, + 53: 1250, + 55: 1000, + 56: 5500 +} + +module.exports = total_energy; diff --git a/RVO50/debug.js b/RVO50/debug.js new file mode 100755 index 0000000..9818194 --- /dev/null +++ b/RVO50/debug.js @@ -0,0 +1,16 @@ +// =================================================== +// FOR DEVELOPMENT +// Total.js - framework for Node.js platform +// https://www.totaljs.com +// =================================================== + +const options = {}; + +// options.ip = '127.0.0.1'; +// options.port = parseInt(process.argv[2]); +// options.config = { name: 'Total.js' }; +// options.sleep = 3000; +// options.inspector = 9229; +// options.watch = ['private']; + +require('total.js/debug')(options); \ No newline at end of file diff --git a/RVO50/err.txt b/RVO50/err.txt new file mode 100755 index 0000000..c6f5af7 --- /dev/null +++ b/RVO50/err.txt @@ -0,0 +1,39 @@ +[2024-10-27T09:25:41.117] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T09:38:53.139] [ERROR] errLogs - no voltage detected Set(2) { 2, 3 } +[2024-10-27T10:25:55.018] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T10:39:02.850] [ERROR] errLogs - no voltage detected Set(2) { 2, 3 } +[2024-10-27T11:26:18.617] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-12-09T13:24:20.344] [ERROR] errLogs - Thermometer Thermometer: temperatureAddress is not defined +[2025-09-23T14:05:24.442] [ERROR] errLogs - uncaughtException: Cannot read property 'getHours' of undefined +[2025-09-23T14:05:24.443] [ERROR] errLogs - TypeError: Cannot read property 'getHours' of undefined + at Timeout.emptyReportToSend [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:05:24.444] [ERROR] errLogs - uncaughtException: Cannot read property 'getHours' of undefined +[2025-09-23T14:05:24.445] [ERROR] errLogs - TypeError: Cannot read property 'getHours' of undefined + at Timeout.emptyReportToSend [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:05:24.454] [ERROR] errLogs - uncaughtException: Cannot read property 'getHours' of undefined +[2025-09-23T14:05:24.454] [ERROR] errLogs - TypeError: Cannot read property 'getHours' of undefined + at Timeout.emptyReportToSend [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:05:30.177] [ERROR] errLogs - uncaughtException: date.getHours is not a function +[2025-09-23T14:05:30.178] [ERROR] errLogs - TypeError: date.getHours is not a function + at emptyReportToSend (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at Timeout.dailyReportCheck [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1351:5) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:05:30.179] [ERROR] errLogs - uncaughtException: date.getHours is not a function +[2025-09-23T14:05:30.180] [ERROR] errLogs - TypeError: date.getHours is not a function + at emptyReportToSend (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at Timeout.dailyReportCheck [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1351:5) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T14:05:30.185] [ERROR] errLogs - uncaughtException: date.getHours is not a function +[2025-09-23T14:05:30.186] [ERROR] errLogs - TypeError: date.getHours is not a function + at emptyReportToSend (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at Timeout.dailyReportCheck [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1351:5) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) diff --git a/RVO50/flow/cloudmqttconnect.js b/RVO50/flow/cloudmqttconnect.js new file mode 100755 index 0000000..b03491f --- /dev/null +++ b/RVO50/flow/cloudmqttconnect.js @@ -0,0 +1,357 @@ +exports.id = 'cloudmqttconnect'; +exports.title = 'Cloud connect mqtt'; +exports.group = 'MQTT'; +exports.color = '#888600'; +exports.version = '1.0.2'; +exports.icon = 'sign-out'; +exports.input = 2; +exports.output = 2; +exports.options = { host: 'tb-stage.worksys.io', port: 1883, clientid: "", username: "" }; + +exports.html = `
+
+
+
Hostname or IP address (if not empty - setting will override db setting)
+
+
+
Port
+
+
+
+
+
@(Client id)
+
+
+
topic
+
+
+
`; + + + +const { promisifyBuilder } = require('./helper/db_helper'); +const fs = require('fs'); +const mqtt = require('mqtt'); +const nosql = NOSQL('tbdatacloud'); + +const SEND_TO = { + debug: 0, + rpcCall: 1, +} + +//CONFIG +let saveTelemetryOnError = true;//backup_on_failure overrides this value +//------------------------ + +const noSqlFileSizeLimit = 4194304;//use 5MB - 4194304 +let insertNoSqlCounter = 0; +let insertBackupNoSqlCounter = 0; +let processingData = false; + +let backup_on_failure = true;//== saveTelemetryOnError - create backup client send failure +let restore_from_backup = 50; //how many rows process at once? +let restore_backup_wait = 3;//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; + + +exports.install = function(instance) { + + var client; + var opts; + var clientReady = false; + + let o = {}; //options + + function main() { + loadSettings(); + } + + //set opts according to db settings + function loadSettings() { + + o = instance.options; + if (!o.topic) o.topic = FLOW.GLOBALS.settings.cloud_topic; + + opts = { + host: o.host, + port: o.port, + clientId: o.clientid, + username: o.username, + rejectUnauthorized: false, + resubscribe: false + }; + + console.log("wsmqttpublich -> loadSettings from instance.options", o); + + if (!o.topic) { + instance.status("Not configured", "white"); + console.log("Cloud mqtt connect: no topic selected"); + return; + } + + connectToTbServer(); + } + + function connectToTbServer() { + var url = "mqtt://" + opts.host + ":" + opts.port; + console.log("MQTT URL: ", url); + + client = mqtt.connect(url, opts); + + client.on('connect', function() { + client.subscribe(`${o.topic}_backward`, (err) => { + if (!err) { + console.log("MQTT subscribed"); + } + }); + instance.status("Connected", "green"); + clientReady = true; + sendClientError = true; + }); + + client.on('reconnect', function() { + instance.status("Reconnecting", "yellow"); + clientReady = false; + }); + + client.on('message', function(topic, message) { + // message is type of buffer + message = message.toString(); + if (message[0] === '{') { + TRY(function() { + + message = JSON.parse(message); + if (message.hasOwnProperty("device") && message.hasOwnProperty("data") && message.data.hasOwnProperty("id")) { + client.publish(`${o.topic}_forward`, `{"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 } }); + } + + }, () => instance.debug('MQTT: Error parsing data', message)); + } + + instance.send(SEND_TO.rpcCall, { "topic": o.topic, "content": message }); + }); + + client.on('close', function() { + clientReady = false; + + instance.status("Disconnected", "red"); + instance.send(SEND_TO.debug, { "message": "Client CLOSE signal received !" }); + }); + + client.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) { + console.log('MQTT client error', err); + sendClientError = false; + } + clientReady = false; + }); + + } + + + instance.on('0', function(data) { + + if (clientReady) { + //do we have some data in backup file? if any, process data from database + if (saveTelemetryOnError) { + //read telemetry data and send back to server + if (!processingData) processDataFromDatabase(); + } + + let stringifiedJson = JSON.stringify(data.data) + client.publish(`${o.topic}_forward`, stringifiedJson, { qos: 1 }); + } + 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 (saveTelemetryOnError && o.topic) { + //create new file from tbdata.nosql, if file size exceeds given limit, and clear tbdata.nosql + makeBackupFromDbFile(); + + //write to tb + data.data.id = UID(); + nosql.insert(data.data); + } + } + }); + + instance.on("1", _ => { + main(); + }) + + instance.close = function(done) { + if (clientReady) { + client.end(); + } + }; + + + function getDbBackupFileCounter(type) { + var files = fs.readdirSync(__dirname + "/../databases"); + + let counter = 0; + for (var i = 0; i < files.length; i++) { + + if (files[i] == "tbdatacloud.nosql") continue; + + if (files[i].endsWith(".nosql")) { + + let pos = files[i].indexOf("."); + if (pos > -1) { + + let fileCounter = counter; + let firstDigit = files[i].slice(0, pos); + + fileCounter = parseInt(firstDigit); + if (isNaN(fileCounter)) fileCounter = 0; + //console.log("getDbBackupFileCounter digit:", files[i], firstDigit, fileCounter, isNaN(fileCounter), type); + + if (type == "max") { + if (fileCounter > counter) { + counter = fileCounter; + } + } + else if (type == "min") { + if (counter == 0) counter = fileCounter; + + if (fileCounter < counter) { + counter = fileCounter; + } + } + } + } + + } + + if (type == "max") counter++; + + return counter; + } + + const makeBackupFromDbFile = async () => { + + if (!saveTelemetryOnError) return; + + //to avoid large file: tbdata.nosql + + //init value is 0! + if (insertNoSqlCounter > 0) { + --insertNoSqlCounter; + return; + } + + insertNoSqlCounter = 100; + + let source = __dirname + "/../databases/tbdatacloud.nosql"; + + var stats = fs.statSync(source); + var fileSizeInBytes = stats.size; + + if (fileSizeInBytes > noSqlFileSizeLimit) { + + let counter = 1; + counter = getDbBackupFileCounter("max"); + + let destination = __dirname + "/../databases/" + counter + "." + "tbdatacloud.nosql"; + + //make backup file + fs.copyFileSync(source, destination); + //fs.renameSync(p, p + "." + counter); + + //clear tbdata.nosql + fs.writeFileSync(source, ""); + fs.truncateSync(source, 0); + + } + } + + const processDataFromDatabase = async () => { + + if (restore_from_backup <= 0) return; + + //calculate diff + const now = new Date(); + let currentTime = now.getTime(); + let diff = currentTime - lastRestoreTime; + + if ((diff / 1000) < restore_backup_wait) { + //console.log("*********restore_backup_wait", diff, restore_backup_wait); + return; + } + + processingData = true; + + //get filename to process + let counter = getDbBackupFileCounter("min"); + + //we have some backup files + let dataBase = 'tbdata'; + + var nosql; + if (counter == 0) dataBase = 'tbdatacloud'; + else dataBase = counter + "." + 'tbdatacloud'; + + nosql = NOSQL(dataBase); + + //select all data - use limit restore_from_backup + let records = await promisifyBuilder(nosql.find().take(restore_from_backup)); + + for (let i = 0; i < records.length; i++) { + if (clientReady) { + + let item = records[i]; + let id = item.id; + + if (id !== undefined) { + //console.log("------------processDataFromDatabase - remove", id, dataBase, i); + + try { + + let message = JSON.parse(JSON.stringify(item)); + delete message.id; + client.publish(`${o.topic}_forward`, JSON.stringify(message), { qos: 1 }); + + //remove from database + await promisifyBuilder(nosql.remove().where("id", id)); + + } catch (error) { + //process error + console.log("processDataFromDatabase", error); + } + + } + + } + else { + processingData = false; + return; + } + } + + if (records.length > 0) { + //clean backup file + if (counter > 0) nosql.clean(); + } + + //no data in db, remove + if (records.length == 0) { + if (counter > 0) nosql.drop(); + } + + const d = new Date(); + lastRestoreTime = d.getTime(); + + processingData = false; + + } + + instance.on('options', main); + +}; diff --git a/RVO50/flow/cmd_manager.js b/RVO50/flow/cmd_manager.js new file mode 100755 index 0000000..25912df --- /dev/null +++ b/RVO50/flow/cmd_manager.js @@ -0,0 +1,3071 @@ +exports.id = 'cmd_manager'; +exports.title = 'CMD Manager'; +exports.group = 'Worksys'; +exports.color = '#5D9CEC'; +exports.version = '0.0.3'; +exports.output = ['red', 'blue', 'yellow', 'blue', 'white', 'green']; +exports.input = 3; +exports.icon = 'cloud-upload'; + +exports.html = ` +
+
+
+
RPC - run RPC calls

+
+
+
@(User)
+
+
+
@(Password)
+
+
+
@(My edge)
+
+
+
+`; +exports.readme = `Manager for CMD calls`; + + +exports.install = function(instance) { + + 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, isEmptyObject, emptyJsObject, writeToFile, addToArrayIfUnique } = require('./helper/utils'); + const bitwise = require('bitwise'); + + var SunCalc = require('./helper/suncalc'); + const DataToTbHandler = require('./helper/DataToTbHandler'); + const errorHandler = require('./helper/ErrorToServiceHandler'); + const { sendNotification } = require('./helper/notification_reporter'); + const process = require('process'); + const { errLogger, logger, monitor } = require('./helper/logger'); + + //for accelerometer purposes + const { naklony } = require("../databases/accelerometer_db"); + + const dbNodes = TABLE("nodes"); + const dbRelays = TABLE("relays"); + + let GLOBALS; + let SETTINGS; + let rsPort; + let tbHandler; + + // runTasks intervals + const SHORT_INTERVAL = 30; + const LONG_INTERVAL = 300; + + //send data to following instances: + const SEND_TO = { + debug: 0, + tb: 1, + http_response: 2, + dido_controller: 3, + infoSender: 4, + dailyReport: 5 + } + + 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 + } + + 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 sendNodeReadout = null; // interval for sending agregate data from node + + 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["1"] = minutes; // dimming + priorities["76"] = minutes; // power + + minutes = 5; + priorities["75"] = minutes; // current + priorities["79"] = minutes; // energy + priorities["87"] = minutes; // aktualny cas + //priorities["84"] = minutes; //accelerometer + + minutes = 10; + priorities["74"] = minutes; // voltage + priorities["77"] = minutes; // power factor + priorities["78"] = minutes; // frequency + + minutes = 60; + priorities["0"] = minutes; // statecode + priorities["6"] = minutes; // dusk + priorities["7"] = minutes; // dawn + priorities["8"] = minutes; // profile + + minutes = 60 * 24; + priorities["89"] = minutes; // verzia fw + priorities["80"] = minutes; // lifetime + + //prikazy kt sa budu spustat na dany node - see config.js in terminal-oms.app. (1 - dimming) + let listOfCommands = [0, 1, 6, 7, 8, 74, 75, 76, 77, 78, 79, 80, 87, 89]; + + 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; + + // holds dusk, dawn (and more) values + let sunCalcResult; + + //helper container for counting resolved group of commands (commands related to set profile) + let cmdCounter = {};//key is node, value is counter + + //TODO: is this set working?? According to previous checks, sets do not work + //if sending of profile to node fails, we send notification and push node into set, so we do not send notification twice + const nodeProfileSendFail = new Set(); + + //we expect to get current temperature in Senica from senica-prod01 + let temperatureInSenica = null; + let accelerometerInterval = null; + + //NOTE: daily reports senica: + //rvo_is_on status, we monitor all nodes - if true, power and dimming should be not 0, if false, 24/7 nodes should be 0, other rvo should not respond + let rvo_is_on; + let previous_rvo_is_on_value; + let handleDailyReport; //setInterval for dailyReportHandler function + let dailyReport = {}; //data needed for daily report + let reportToSend = {}; //final report which we send to cloud + let breakerCounter = null; // status of breakers after flow starts is not in report + let rvoPeriod; // interval of checking dusk dawn and if rvo_is_on + let initialReportStatus = false; + + const DAILY_REPORT_HANDLER_TIME = 3_600_000; + const SET_SUNCALC_RESULT_TIME = 3_600_000; + const SET_RVO_PERIOD_TIME = 300_000; + const ADD_NODE_TO_REPORT_TIME = 3_600_000; + + //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); + + let now = new Date(); + console.log("Cmd-mngr installed", now.toLocaleString("sk-SK")); + + sunCalcResult = calculateDuskDawn(); + + handleRsPort(); + + customTasksInterval = setInterval(reportEdgeDateTimeAndNumberOfLuminaires, 120_000); + setTimeout(reportEdgeDateTimeAndNumberOfLuminaires, 4000); + + //dailyReport related + emptyReportToSend(); + breakerCounter = Object.keys(relaysData).length - 1; // we get number of lines (breakers) except of line 0 + rvoPeriod = setInterval(setRvoPeriod, SET_RVO_PERIOD_TIME); + setTimeout(setRvoPeriod, 3000); + setInterval(setSunCalcResult, SET_SUNCALC_RESULT_TIME); + handleDailyReport = setInterval(dailyReportHandler, DAILY_REPORT_HANDLER_TIME); + + + setCorrectTime = setInterval(setCorrectPlcTimeOnceADay, 60000 * 60); // 1 hour + setCorrectPlcTimeOnceADay(); + + sendNodeReadout = setInterval(sendNodesData, 150_000); + accelerometerInterval = setInterval(accelerometerData, 60000 * 30); //30 min + } + + + 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" + //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 + // if node regular readout does not respond, we repeat request + params.repeatCounter = 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-mngr: 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.byte4 = 96; + params.recipient = 1; + params.register = 8; + params.rw = 1;//write + params.timestamp = timestamp; + 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.byte4 = 96; + params.recipient = 1; + params.register = 8; + params.rw = 1;//write + params.timestamp = timestamp; + 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). + */ + + 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.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.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 + { + + logger.debug("processNodeProfile: Threshold lux level for DUSK/DAWN", node); + + let params = getParams(); + params.type = "set_node_profile"; + params.address = node; + params.register = 96; + params.recipient = 1; + params.rw = 1;//write + params.timestamp = timestamp; + 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(); + params.type = "set_node_profile"; + params.address = node; + params.register = 97; + params.recipient = 1; + params.rw = 1;//write + params.timestamp = timestamp; + 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.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); + + 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); + + console.log("proces profile finished *********************") + } + + + 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; + }); + } + + + 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) { + for (let k in nodesData) { + 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`); + } + } + } + + + function loadRelaysData(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 (value.contactor == 1) processAllNodeProfilesOnLine(value.line); + } + } + + + function reportOnlineNodeStatus(line) { + //Po zapnutí línie broadcastovo aktualizovať predtým čas a o 3 sek neskor - status, brightness + + logger.debug("Cmd-mngr: ----->reportOnlineNodeStatus for line", line); + + const d = new Date(); + + // broadcast actual time + let params = getParams(); + params.address = 0xffffffff;//Broadcast + params.byte1 = d.getHours(); + params.byte2 = d.getMinutes(); + params.recipient = 2;//2 broadcast, address = 0 + params.register = 87;//Actual time + params.rw = 1;//write + params.type = "node-onetime-write"; + params.timestamp = d.getTime() + 30000; + params.info = "run broadcast: Actual time"; + //params.debug = true; + + tasks.push(params); + + let sec = 3; + setTimeout(function() { + //Po zapnutí línie - spraviť hromadný refresh stavu práve zapnutých svietidiel + + let time = Date.now(); + + for (let k in nodesData) { + + //potrebujem nody k danej linii + 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].node_status_before_offline === true || nodesData[k].status === true) { + status = "OK"; + nodesData[k].time_of_last_communication = time; + } + + nodesData[k].readout.status = status; + + updateNodeStatus(k, status === "OK" ? true : false); + if (nodesData[k].hasOwnProperty("node_status_before_offline")) delete nodesData[k].node_status_before_offline; + sendTelemetry({ status: status }, tbname, time); + + //vyreportovanie dimming, current, input power pre liniu pre vsetky nody + //Prud + { + let params = getParams(); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 75;//prud + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = time + 4000; + params.info = 'read current'; + //params.debug = true; + tasks.push(params); + } + + //vykon + { + let params = getParams(); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 76;//výkon + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = time + 4100; + params.info = 'read power'; + //params.debug = true; + + tasks.push(params); + } + //dimming + { + let params = getParams(); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 1;//dimming + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = time + 4200; + params.info = 'read dimming'; + //params.debug = true; + + tasks.push(params); + } + + } + } + + }, sec * 1000); + } + + + function reportOfflineNodeStatus(line) { + + logger.info("Cmd-mngr: ------>reportOffLineNodeStatus for line ", line); + + values = {}; + values["dimming"] = 0;//brightness + values["power"] = 0;//výkon + values["current"] = 0;//prúd + values["status"] = "OFFLINE"; + + const date = Date.now(); + + Object.keys(nodesData).forEach(node => { + + //potrebujem nody k danej linii + if (line == nodesData[node].line || line == undefined) { + + let tbname = nodesData[node].tbname; + let nodeStatus = nodesData[node].status; + + //in case we have reported offline node status, we return (continue with next node) + if (nodeStatus === "OFFLINE") return; + + nodesData[node].node_status_before_offline = nodeStatus; + nodesData[node].status = "OFFLINE"; + nodesData[node].readout = {}; + + sendTelemetry({ ...values }, tbname, date); + } + }); + + } + + + function turnLine(onOrOff, line, info) { + let obj = { + line: line, + command: onOrOff, + info: info + }; + + //to assure, handleDailyReportFunction do not run before rvo_is_on variable changes. So after every line switch we reset the timer + clearInterval(handleDailyReport); + handleDailyReport = setInterval(dailyReportHandler, DAILY_REPORT_HANDLER_TIME); + + //logger.debug("linia", line, obj); + instance.send(SEND_TO.dido_controller, obj); + } + + + 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"; + 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]) { + //CRC_ERROR + message = "NOK"; + error = "CRC_ERROR c1"; + instance.send(SEND_TO.debug, "CRC_ERROR c1"); + } + + 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") { + instance.send(SEND_TO.debug, bytes); + instance.send(SEND_TO.debug, "RESPONSE " + type + " - " + bytes[4]); + + //logger.debug(SEND_TO.debug, "RESPONSE " + type + " - " + bytes[4], bytes); + + error = "type is: " + type; + + message = "NOK"; + } + + return { message, type, error }; + } + + + //BUILD TASKS// + function buildTasks(params) { + + //return; + console.log("buidTAaasks start ****************", params); + monitor.info("buildTasks - params", params); + + let processLine; //defined line + let init = false; + let processLineProfiles = true; + let processBroadcast = true; + let processNodes = true; + + if (params == undefined) { + init = true; + tasks = []; + logger.debug("-->buildTasks clear tasks"); + } + else { + processLineProfiles = params.processLineProfiles; + processBroadcast = false; + processNodes = false; + + processLine = params.line; + } + + let now = new Date(); + + //process line profiles + if (processLineProfiles) { + + let keys = Object.keys(relaysData); + + for (let i = 0; i < keys.length; i++) { + + let line = parseInt(keys[i]); + let profilestr = relaysData[line].profile; + + if (processLine != undefined) { + if (processLine != line) continue; + } + + try { + + /** + * we process line profiles: timepoints, astro clock, lux_sensor, offsets ... + */ + if (profilestr === "") throw ("Profile is not defined"); + let profile = JSON.parse(profilestr); + 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; + + // add name to regular profile timepoint and delete unused end_time key: + time_points.forEach(point => { + point.name = "profileTimepoint" + delete point.end_time; + }); + + //monitor.info("buildTasks: time_points", time_points); + + + /** + * 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 astro clock true, we remove all regular profile points + time_points = []; + + //TODO: when astro clock == true, is offset calculated ??? + //let duskAstroClockOffset = profile.dusk_astro_clock_offset; + //let dawnAstroClockOffset = profile.dawn_astro_clock_offset; + //console.log("line astro clock offsets dusk a dawn: ", duskAstroClockOffset, dawnAstroClockOffset); + // maybe add dusk dawn offset to calculateDuskDawn ?? what dusk dawn will be if dawn_lux_sensor == true?? + //let sunCalcResult = calculateDuskDawn(new Date(), line, duskAstroClockOffset, dawnAstroClockOffset); + + 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 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); + + 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); + + 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(':'); + + let ad = new Date(); + ad.setHours(parseInt(ahours), parseInt(aminutes), 0); + + let bd = new Date(); + bd.setHours(parseInt(bhours), parseInt(bminutes), 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++) { + + let start_time = new Date(); + let [hours, minutes] = time_points[t].start_time.split(':'); + start_time.setHours(parseInt(hours), parseInt(minutes), 0); + + //task is in 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(); + params.type = "relay"; + params.line = parseInt(line); + params.value = time_points[t].value; + params.tbname = relaysData[line].tbname; + params.timestamp = start_time.getTime(); + + // 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; + + //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)) { + 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; + + params.debug = true; + + //turn on/off line + tasks.push(params); + monitor.info("TimePoint params: ", params.info, start_time); + } + + monitor.info("-->time_points final", line, time_points); + + //ensure to turn on/off according to calculated currentValue + let params = getParams(); + params.type = "relay"; + params.line = parseInt(line); + params.tbname = relaysData[line].tbname; + params.value = currentValue; + params.timestamp = i; + params.debug = true; + + //logger.debug(now.toLocaleString("sk-SK")); + 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; + + tasks.push(params); + + } catch (error) { + if (profilestr !== "") { + //errLogger.error(profilestr, error); + console.log(`Cmd_mngr: Unable to process line profile ${line}. Error: `, error); + errorHandler.sendMessageToService(profilestr + "-" + error, 0, "js_error"); + } else { + turnLine("off", line, "No line profile. Switching it off on startup"); + } + } + + } + //logger.debug("tasks:"); + //logger.debug(tasks); + } + + + //NOTE: PROCESS DEFAULT BROADCASTS - Time of dusk, Time of dawn, Actual Time + if (processBroadcast) { + + let d = new Date(); + let time = d.getTime(); + //let sunCalcResult = calculateDuskDawn(); + + { + let params = getParams(); + + params.address = 0xffffffff;//broadcast + params.byte1 = sunCalcResult["dusk_hours"]; + params.byte2 = sunCalcResult["dusk_minutes"]; + params.recipient = 2;//2 broadcast, + params.register = 6;//Time of dusk + params.rw = 1;//write + params.type = "node-regular-write"; + params.timestamp = time + 60000; + params.addMinutesToTimestamp = 60 * 3; //kazde 3 hodiny zisti novy dusk + params.info = "Broadcast-duskTime"; + + tasks.push(params); + } + + { + let params = getParams(); + + params.address = 0xffffffff;//broadcast + params.byte1 = sunCalcResult["dawn_hours"]; + params.byte2 = sunCalcResult["dawn_minutes"]; + params.recipient = 2; //2 broadcast + params.register = 7;//Time of dawn + params.rw = 1;//write + params.type = "node-regular-write"; + params.timestamp = time + 60001; + params.addMinutesToTimestamp = 60 * 3; //kazde 3 hodiny zisti novy dawn + params.info = "Broadcast-dawnTime"; + + tasks.push(params); + } + + { + let params = getParams(); + + params.address = 0xffffffff;//broadcast + params.byte1 = d.getHours(); + params.byte2 = d.getMinutes(); + params.recipient = 2; //2 broadcast + params.register = 87;//Actual time + params.rw = 1;//write + params.type = "node-regular-write"; + params.timestamp = time + 60002; + params.addMinutesToTimestamp = 5; + params.info = "run broadcast: Actual time"; + + tasks.push(params); + } + + } + + //process nodes & tasks - read node's data + if (processNodes) { + + let time = Date.now(); + + for (let k in nodesData) { + let address = parseInt(k); + let tbname = nodesData[k].tbname; + let register = 0; + + for (let i = 0; i < listOfCommands.length; i++) { + + register = listOfCommands[i]; + let addMinutesToTimestamp = priorities[register]; + + let params = getParams(); + + params.address = address; + params.recipient = 1; + params.register = register; + params.type = register == 1 ? "node-dimming-read" : "node-regular-read"; + params.tbname = tbname; + params.timestamp = time + 5000 + i * 500 + addMinutesToTimestamp * 1000; //to make slight time difference + params.addMinutesToTimestamp = addMinutesToTimestamp; + params.info = "Node regular read command"; + + tasks.push(params); + } + + } + } + + + //niektore ulohy sa vygeneruju iba 1x pri starte!!! + if (!init) return; + + + //Master node FW version - modifies SETTINGS.masterNodeIsResponding + { + let params = getParams(); + params.type = "cmd-master"; + params.register = 4; + params.address = 0; + params.timestamp = 0; + params.addMinutesToTimestamp = 5; + params.tbname = SETTINGS.rvoTbName; + params.info = "Master node FW verzia"; + //params.debug = true; + + tasks.push(params); + } + + //kazdu hodinu skontrolovat nastavenie profilov + { + let params = getParams(); + params.type = "process_profiles"; + params.timestamp = Date.now() + 60001; + params.addMinutesToTimestamp = 60;//60 = every hour + params.info = "detekcia nespracovaných profilov linie a nodov"; + //params.debug = true; + + tasks.push(params); + } + + monitor.info("tasks created:", tasks.length); + } + + + /** + * We process line profile, where "astro_clock": true + * example profile: + * + "dawn_lux_sensor": true, + "dusk_lux_sensor": true, + "dawn_lux_sensor_value": 5, + "dusk_lux_sensor_value": 5, + "dawn_astro_clock_offset": 0, + "dusk_astro_clock_offset": 10, + "dawn_lux_sensor_time_window": 30, + "dusk_lux_sensor_time_window": 30, + "dawn_astro_clock_time_window": 60, + "dusk_astro_clock_time_window": 60 + + * if dawn: if currentTimestamp is in timewindow "dawnTime + and - dawn_lux_sensor_time_window" and lux value >= lux_sensor_value, we switch off the line. + * if dusk: we do oposite + * + * dawn: usvit - lux je nad hranicou - vypnem + * dusk: sumrak - lux je pod hranicou - zapnem + */ + 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++) { + + let line = keys[i]; //line is turned off by default + let profilestr = relaysData[line].profile; + const contactor = relaysData[line].contactor; + + try { + + let profile = JSON.parse(profilestr); + if (Object.keys(profile).length === 0) throw ("turnOnOffLinesAccordingToLuxSensor - profile is not defined"); + + 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 (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"); + } + } + } + + //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 (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"); + } + } + } + + } + + } catch (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) { + //MASTER + if (node == 0) return; + + let nodeObj = nodesData[node]; + if (nodeObj == undefined) return; + + let nodeCurrentStatus = nodeObj.status; + const now = Date.now(); + + let data = null; + + if (nodeCurrentStatus === "OFFLINE") { + data = { status: newStatus }; + nodeDbStatusModify(node, data); + return; + } + else 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; + } + + } + + + 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 }; + } + }); + }); + } + + + function processDailyReport() { + + const now = Date.now(); + + for (const [key, value] of Object.entries(dailyReport)) { + + if (["name", "time", "dusk_and_dawn"].includes(key)) continue; + + let poleNumber = nodesData[key]["pole_number"]; + let line = dailyReport[key].line; + let nodeType = nodesData[key]["node_type"]; + let fullNodeName = key // key == nodeNumber + + if (poleNumber && nodeType) { + fullNodeName = SETTINGS.rvo_number + "/" + poleNumber + "_" + line + "L_" + key + "_" + nodeType; + } else { + fullNodeName = key; + } + + if (rvo_is_on) { + + if (value.initialTs) { + if (value.initialTs + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["night_no_data"], fullNodeName); + console.log('report nedostava ziadne data uz hodinu', fullNodeName); + value.initialTs = now; + } + } + if (value.dimmingIsZeroTime) { + if (value.dimmingIsZeroTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["night_dimming=0"], fullNodeName); + console.log("report node dimming je 0 ale ma svietit", fullNodeName); + value.dimmingIsZeroTime = now; + } + } + if (value.powerIsZeroTime) { + if (value.powerIsZeroTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["night_power=0"], fullNodeName); + console.log("report node power je 0 ale ma svietit", fullNodeName); + value.powerIsZeroTime = now; + } + } + + } else { + + let contactorStatus = relaysData[line].contactor; + if (contactorStatus === 1) { + + if (value.initialTs) { + if (value.initialTs + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["day_24/7_no_data"], fullNodeName); + console.log('node je na 24/7 ale nedostava ziadne data uz hodinu', fullNodeName); + value.initialTs = now; + } + } + if (value.dimmingIsOnButShouldBeOffTime) { + if (value.dimmingIsOnButShouldBeOffTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["day_24/7_dimming>0"], fullNodeName); + console.log("report dimming je > 0 ale nema svietit", fullNodeName); + value.dimmingIsOnButShouldBeOffTime = now; + } + } + if (value.powerIsOnButShouldBeOffTime) { + if (value.powerIsOnButShouldBeOffTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["day_24/7_power>0"], fullNodeName); + console.log("report power je > 0 ale nema svietit", fullNodeName); + value.powerIsOnButShouldBeOffTime = now; + } + } + + } + + } + + } + + let report = {}; + report["name"] = SETTINGS.rvo_name; + report["time"] = new Date(); + report["report"] = reportToSend; + + writeToFile(F.path.root("report_data.log"), report, true); + instance.send(SEND_TO.dailyReport, report); + } + + + function dailyReportHandler() { + + if (!SETTINGS.daily_report) return; + + // after dawn we empty reportToSend and start to get data for a new day + const date = new Date(); + const hour = date.getHours(); + const minute = date.getMinutes(); + + console.log("now: ", hour, minute, "suncalc: ", sunCalcResult.dawn_hours, sunCalcResult.dawn_minutes); + + if (hour === sunCalcResult.dawn_hours) { + + //NOTE: ak je este pred usvitom, spracujeme report a posleme na cloud, ak uz je po usvite, resetujeme report plnime data noveho dna + if (minute >= sunCalcResult.dawn_minutes - 2) { + emptyReportToSend(); + emptyDailyReport(); + console.log("Podmienka 1 v dailyReport handler"); + } else { + processDailyReport(); + emptyReportToSend(); + emptyDailyReport(); + console.log("Podmienka 2 v dailyReport handler"); + } + + initialReportStatus = true; + + // ak sa funkcia spusti o hodinu alebo 2 neskor, ako je usvit (moze sa to stat, kedze kazde zapnutie/vypnutie linii odznova spusti casovac. + } else if (hour === sunCalcResult.dawn_hours + 1 || hour === sunCalcResult.dawn_hours + 2) { + if (!initialReportStatus) { + emptyReportToSend(); + emptyDailyReport(); + initialReportStatus = true; + console.log("Podmienka 3 v dailyReport handler"); + } else { + processDailyReport(); + initialReportStatus = true; + console.log("Podmienka 4 v dailyReport handler"); + } + } else { + processDailyReport(); + initialReportStatus = false; + console.log("Podmienka 5 v dailyReport handler"); + } + + console.log("initialReportStatus: ", initialReportStatus); + + } + + function emptyReportToSend() { + emptyJsObject(reportToSend); + reportToSend["contactor"] = { off: [], on: [] }; + reportToSend["night_no_data"] = []; + reportToSend["night_dimming=0"] = []; + reportToSend["night_power=0"] = []; + reportToSend["day_24/7_no_data"] = []; + reportToSend["day_24/7_dimming>0"] = []; + reportToSend["day_24/7_power>0"] = []; + console.log(`resetuje sa reportToSend`); + } + + + //NOTE: ked je initialTs stale rovnaky a zistime ze linie su vypnute (relaysData.line.contactor) - zistim, ci je node na tej linii. Vieme, ze ak je linia vypnuta je to v poriadku lebo nie je na 24/7 linii + //ak je na 24/7 linii, reportujeme, ze neprijima data + function emptyDailyReport() { + const ts = Date.now(); + emptyJsObject(dailyReport); + + //NOTE: do dailyReport dame vsetky nody a pravidelne kontrolujeme ci maju data + //ked nastane sumrak/usvit a svetla maju zacat/prestat svietit, dailyReport spravime nanovo: + for (const [key, value] of Object.entries(nodesData)) { + dailyReport[value.node] = { line: value.line, initialTs: ts }; + } + + console.log("dailyReport: ", dailyReport); + } + + + async function runTasks() { + + clearInterval(interval); + + let currentTimestamp = Date.now(); + + //sort tasks based on timestamp + 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) { + instance.send(SEND_TO.debug, "no tasks created"); + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + if (!rsPort.isOpen) { + instance.send(SEND_TO.debug, "!rsPort.isOpen"); + //await rsPort.open(); + //console.log("Cmd-mngr: !rsPort.isOpen"); + } + + let currentTask = tasks[0]; + + if (currentTask.debug) { + //logger.debug("--->task to process", currentTask); + } + + if (currentTask.timestamp <= currentTimestamp) { + let params = { ...tasks[0] }; + + //allow terminal commands + if (SETTINGS.maintenance_mode && params.type !== "cmd-terminal") { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + let type = params.type; + let tbname = params.tbname; + let node = params.address; + let register = params.register; + let line = null; + let itIsNodeCommand; + + if (nodesData[node] !== undefined) { + line = nodesData[node].line; + itIsNodeCommand = true; + } + + if (params.line !== undefined) line = params.line; + + if (params.addMinutesToTimestamp > 0 || params.timePointName) { + tasks[0].timestamp = currentTimestamp + tasks[0].addMinutesToTimestamp * 60000; + } else { + tasks.shift(); + } + + //kontrola nespracovanych profilov nodov + //TODO: co ked niektore nody neprijimaju profily? kazdu hodinu zahltuju "tasks" array + if (type == "process_profiles") { + //na vsetky zapnutych liniach sa spracuju nespracovane profily nodov + loadRelaysData(); + interval = setInterval(runTasks, SHORT_INTERVAL); + return; + } + + //relay + if (type == "relay") { + + const timePointName = params.timePointName; + const value = params.value; + + let date = new Date(); + date.setDate(date.getDate() + 1);//next day + + let sunCalcResult; + if (timePointName) sunCalcResult = calculateDuskDawn(date, params.line); + + + if (timePointName == "dawn") { + tasks[0].timestamp = sunCalcResult.dawn_time; + } + else if (timePointName == "dusk") { + tasks[0].timestamp = sunCalcResult.dusk_time; + } + else if (timePointName == "luxOn") { + tasks[0].timestamp = sunCalcResult.dusk_time + params.dusk_lux_sensor_time_window * 60000; + } + else if (timePointName == "luxOff") { + tasks[0].timestamp = sunCalcResult.dawn_time + params.dawn_lux_sensor_time_window * 60000; + } + else if (timePointName == "profileTimepoint") { + tasks[0].timestamp = currentTimestamp + tasks[0].addMinutesToTimestamp * 60000; + } + + let info = "aplikovany bod profilu"; + let onOrOff = ""; + value == 1 ? onOrOff = "on" : onOrOff = "off"; + + turnLine(onOrOff, params.line, info); + + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + if (!SETTINGS.masterNodeIsResponding) { + //ak neodpoveda, nebudeme vykonavat ziadne commands, okrem cmd-terminal cmd-master + errorHandler.sendMessageToService("Master node is not responding"); + + let stop = true; + + if (type === "cmd-terminal" || type === "cmd-master") stop = false; + if (stop) { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + } + + let contactorStatus = 1; + if (relaysData[line] != undefined) contactorStatus = relaysData[line].contactor; + + if (line === 0 || contactorStatus === 0 || FLOW.deviceStatus.state_of_breaker[line] === "Off") { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + // TODO: -> status offline for rvo if rotary_switch_state is OFF, this is source of errors + // check if rotary_switch_state == "Off" + // state_of_braker: disconnected = true? + + if (!rsPort.isOpen) { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + //RE-CALCULATE VALUES + //set actual time for broadcast + if (register == 87 && params.recipient === 2) { + var d = new Date(); + params.byte1 = d.getHours();//h + params.byte2 = d.getMinutes();//m + } + + //SET DUSK/DAWN FOR BROADCAST + //Time of dusk + if (register == 6 && params.recipient === 2) { + + if (type != "cmd-terminal") { + params.byte1 = sunCalcResult["dusk_hours"];//h + params.byte2 = sunCalcResult["dusk_minutes"];//m + } + } + + //Time of dawn + if (register == 7 && params.recipient === 2) { + if (type != "cmd-terminal") { + params.byte1 = sunCalcResult["dawn_hours"];//h + params.byte2 = sunCalcResult["dawn_minutes"];//m + } + } + //----------------------- + + instance.send(SEND_TO.debug, "address: " + node + " register:" + register + "type: " + type); + + var startTime, endTime; + startTime = new Date(); + + let saveToTb = true; + if (!tbname) saveToTb = false; + + let resp = com_generic(node, params.recipient, params.rw, register, params.name, params.byte1, params.byte2, params.byte3, params.byte4); + let readBytes = 11; + let timeout = 4000; + + + // await keyword is important, otherwise incorrect data is returned! + await writeData(rsPort, resp, readBytes, timeout).then(function(data) { + + //sometimes happens, that status of node changes to OK, NOK even if line was turned off and should be status OFFLINE. To prevent this, we return if line contactor is 0: + if (itIsNodeCommand && line && relaysData[line].contactor !== 1) return; + + 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); + + //ak sa odpoved zacina 0 - je to v poriadku, inak je NOK + let message = result.message; // OK, NOK + let message_type = result.type; + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + console.log("detected response:", result); + logger.debug("Cmd-mngr: writeData done " + message_type + " duration: " + timeDiff + " type: " + params.debug, params, result); + } + } + + let values = {}; + + //CMD FINISHED + if (message == "OK") { + + updateNodeStatus(node, true); + + //write + if (type == "set_node_profile") { + let result = cmdCounterResolve(node); + if (result == 0) { + dbNodes.modify({ processed: true }).where("node", node).make(function(builder) { + builder.callback(function(err, response) { + + sendNotification("Cmd-mngr: process cmd", SETTINGS.rvoTbName, "dimming_profile_was_successfully_received_by_node", { node: node }, "", SEND_TO.tb, instance); + + logger.debug("--> profil úspešne odoslaný na node č. " + node); + nodesData[node].processed = true; + nodeProfileSendFail.delete(node); + }); + }); + } + } + + //parse read response + if (params.rw == 0) { + values = processResponse(register, dataBytes); //read + } + + if (itIsNodeCommand) { + values.comm_status = "OK"; + values.status = "OK"; + nodesData[node].readout = { ...nodesData[node].readout, ...values }; + + + if (SETTINGS.daily_report) { + //TODO: co ak nedostavame odpovede z nodu ? Musime vyreportovat!! + //v dailyReport teda musi byt kompletny zoznam nodov a neustale kontrolovat, ci maju data, ak nie report node - neodpoveda + if (register === 1) { + + let now = Date.now(); + + if (rvo_is_on === true) { + + if ("dimmingIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].dimmingIsOnButShouldBeOffTime; + + if (values.dimming > 0) { + if ("dimmingIsZeroTime" in dailyReport[node]) delete dailyReport[node].dimmingIsZeroTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if (!("dimmingIsZeroTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], dimmingIsZeroTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } else { + + if ("dimmingIsZeroTime" in dailyReport[node]) delete dailyReport[node].dimmingIsZeroTime; + + if (values.dimming > 0) { + if (!("dimmingIsOnButShouldBeOffTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], dimmingIsOnButShouldBeOffTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if ("dimmingIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].dimmingIsOnButShouldBeOffTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } + } + + if (register === 76) { + + let now = Date.now(); + + if (rvo_is_on === true) { + + if ("powerIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].powerIsOnButShouldBeOffTime; + + if (values.power > 1) { + if ("powerIsZeroTime" in dailyReport[node]) delete dailyReport[node].powerIsZeroTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if (!("powerIsZeroTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], powerIsZeroTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } else { + + if ("powerIsZeroTime" in dailyReport[node]) delete dailyReport[node].powerIsZeroTime; + + if (values.power > 1) { + if (!("powerIsOnButShouldBeOffTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], powerIsOnButShouldBeOffTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if ("powerIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].powerIsOnButShouldBeOffTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } + } + } + + } + + //master node + if (node == 0) { + sendNotification("Cmd-mngr: 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; + } + + if (params.debug) { + //logger.debug("saveToTb", saveToTb, tbname, values); + } + + if (saveToTb && type != "node-regular-read") { + sendTelemetry(values, tbname); + } + else { + if (type == "cmd-terminal") { + terminalCommandResponse(params, "SUCCESS", data); + } + } + + } + else { + terminalCommandResponse(params, "ERROR", data); + handleNokResponseOnRsPort("handleNOK else block", params, itIsNodeCommand, saveToTb); + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + //logger.debug("writeData err: ", error, result, params); + logger.debug("writeData err: ", tbname, node, register, values); + } + } + + //logger.debug(error, result, params); + } + }).catch(function(reason) { + + //console.log("writeData catch exception", reason); + instance.send(SEND_TO.debug, reason); + + terminalCommandResponse(params, "FAILURE", null, reason); + handleNokResponseOnRsPort("handleNOK catch block", params, itIsNodeCommand, saveToTb); + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + logger.debug("-->WRITE FAILED: " + reason, params.debug, params); + } + } + + }); + + } + 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); + } + + + // if node does not respond to request, we repeat request 3 times: + function repeatCommand(params) { + params.repeatCounter++; + if (params.repeatCounter < 4) { + params.timestamp = 0; + params.addMinutesToTimestamp = 0; + tasks.push(params); + } + } + + function handleNokResponseOnRsPort(message, params, itIsNodeCommand, saveToTb) { + + let node = params.address; + let register = params.register; + let type = params.type; + let tbName = params.tbname; + if (!tbName) return; + + let values = {}; + + let updateStatus = updateNodeStatus(node, false); + + if (itIsNodeCommand) { + values.comm_status = "NOK"; + nodesData[node].readout.comm_status = "NOK"; + repeatCommand(params); + } + + if (updateStatus) { + values.status = "NOK"; + nodesData[node].readout.status = "NOK"; + } + + if (type === "node-regular-read") return; + + //master node + if (node == 0) { + sendNotification("Cmd-mngr: 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; + + if (register == 4) values["master_node_version"] = "NOK"; + } + + if (type == "set_node_profile") { + delete cmdCounter[node]; + logger.debug("profil nebol úspešne odoslaný na node č. ", params); + + if (!nodeProfileSendFail.has(node)) { + sendNotification("Cmd-mngr: process cmd", tbName, "configuration_of_dimming_profile_to_node_failed", { node: node }, "", SEND_TO.tb, instance); + nodeProfileSendFail.add(node); + } + } + + // console.log("------",node, register, type, itIsNodeCommand, updateStatus, saveToTb, values); + if (saveToTb) { + sendTelemetry(values, tbName); + } + + } + + + function sendNodesData() { + Object.keys(nodesData).forEach(node => { + if (nodesData[node]["status"] !== "OFFLINE") { + sendTelemetry(nodesData[node].readout, nodesData[node].tbname); + nodesData[node].readout = {}; + } + }) + } + + + /** + * 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; + } + + 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); + + //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 === "OFFLINE") { + nodeObj.node_status_before_offline === true ? number_of_ok_luminaires++ : number_of_nok_luminaires++; + } + else if (nodeObj.status == true) 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 - ts % 60000 //round to full minute + }; + + sendTelemetry(values, SETTINGS.rvoTbName, ts); + } + + + function setSunCalcResult() { + //if next day, we get new dusk and dawn. To make sure, in local timezone 2:00 means 00:00 in utc (it means next day) + if (new Date().getHours() === 2) { + sunCalcResult = calculateDuskDawn(); + console.log("Novy suncalc: ", sunCalcResult); + } + } + + + function setRvoPeriod() { + + if (!SETTINGS.daily_report) return; + + const ts = Date.now(); + + previous_rvo_is_on_value = rvo_is_on; + + if (ts < sunCalcResult.dawn_time - 1_800_000) { // nodes should be on (00:00 -> 06:00 ( - pol hodina, lebo rvo vypina skor) + rvo_is_on = true; + } else if (sunCalcResult.dawn_time - 1_800_000 < ts && ts < sunCalcResult.dusk_time + 1_800_000) { // nodes should be off 06:00 -> 21:00 + rvo_is_on = false; + } else if (sunCalcResult.dusk_time + 1_800_000 < ts) { // nodes should be on 21:00 -> 00:00 + rvo_is_on = true; + } + + if (previous_rvo_is_on_value !== rvo_is_on) { + emptyDailyReport(); + console.log("rvo_is: ", rvo_is_on, previous_rvo_is_on_value); + } + } + + + function handleRsPort() { + + if (rsPort) { + rsPort.removeAllListeners(); + rsPort = null; + } + + //! 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-mngr: rsPort opened success"); + + 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); + + }).catch(function(reason) { + instance.send(SEND_TO.debug, "Cmd-mngr: RPC runSyncExec - promise rejected:" + reason); + }); + }); + + rsPort.on('error', function(err) { + errorHandler.sendMessageToService([exports.title, "unable to open port", SETTINGS.serial_port, err.message], 0); + monitor.info("Cmd-mngr: Error on rsPort", err.message); + }); + + rsPort.on("close", () => { + monitor.info("Cmd-mngr: rsPort closed, reconnecting..."); + setTimeout(handleRsPort, 1000); + }); + + rsPort.open(); + } + + + instance.on("close", () => { + clearInterval(interval); + clearInterval(customTasksInterval); + clearInterval(setCorrectTime); + clearInterval(sendNodeReadout); + clearInterval(accelerometerInterval); + rsPort.close(); + }); + + instance.on("0", _ => { + main(); + }) + + + instance.on("2", _ => { + console.log("dailyReport, reportToSend, rvo_is_on", dailyReport, reportToSend, rvo_is_on, previous_rvo_is_on_value); + }) + + instance.on("1", 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(); + return; + } + else if (flowdata.data == "close") { + rsPort.close(); + return; + } + else if (flowdata.data == "clean") { + tasks = []; + return; + } + else if (flowdata.data == "buildtasks") { + //build & run + return; + } + else if (flowdata.data == "run") { + //durations = []; + + if (tasks.length == 0) { + + buildTasks(); + + if (rsPort.isOpen) { + interval = setInterval(runTasks, 100); + } + else { + instance.send(SEND_TO.debug, "port is not opened!!!"); + } + } + } + else { + //terminal data - object + //logger.debug("flowdata", flowdata.data); + + if (typeof flowdata.data === 'object') { + //logger.debug("dido", flowdata.data); + if (flowdata.data.hasOwnProperty("sender")) { + //data from dido_controller + if (flowdata.data.sender == "dido_controller") { + + if (flowdata.data.hasOwnProperty("cmd")) { + let cmd = flowdata.data.cmd; + + if (cmd == "buildTasks") { + clearInterval(interval); + + logger.debug("-->Cmd-mngr: BUILD TASKS"); + buildTasks(); + + //logger.debug("tasks:"); + //logger.debug(tasks); + + logger.debug("-->Cmd-mngr: RUN TASKS"); + interval = setInterval(runTasks, 5000); + } + else if (cmd == "reload_relays") { + loadRelaysData(flowdata.data.line); + + if (flowdata.data.dataChanged) { + if (!flowdata.data.value) { + reportOfflineNodeStatus(flowdata.data.line); + } + else { + reportOnlineNodeStatus(flowdata.data.line); + } + } + + } + else if (cmd == "rotary_switch_state") { + let value = flowdata.data.value; + + //state was changed + if (rotary_switch_state != value) { + if (value == "Off") { + //vyreportovat vsetky svietdla + reportOfflineNodeStatus(); + } + + rotary_switch_state = value; + } + } + 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) { + + // we send lux_sensor value to all nodes: + let params = getParams(PRIORITY_TYPES.node_broadcast); + + params.recipient = 2;//2 broadcast, address = 0 + params.address = 0xffffffff;//Broadcast + + let ba = longToByteArray(lux_sensor); + + params.byte3 = ba[1];//msb + params.byte4 = ba[0]; + params.timestamp = PRIORITY_TYPES.node_broadcast; + params.info = "run broadcast: Actual Lux level from cabinet"; + params.register = 95;//Actual Lux level from cabinet + params.rw = 1;//write + + tasks.push(params); + + //process profiles + turnOnOffLinesAccordingToLuxSensor(lux_sensor); + } + } + else if (cmd == "state_of_breaker") { + //istic linie + + breakerCounter--; + + let value = flowdata.data.value; + let line = parseInt(flowdata.data.line); + + let dataChanged = false; + if (state_of_breaker[line] != value) dataChanged = true; + + state_of_breaker[line] = value; + + let status = "OK"; + if (value == "Off") status = "NOK"; + + if (dataChanged) { + + if (relaysData.hasOwnProperty(line)) { + let tbname = relaysData[line].tbname; + + if (value == "Off") { + sendNotification("Cmd-mngr: onData", tbname, "circuit_breaker_was_turned_off_line", { line: line }, "", SEND_TO.tb, instance, "circuit_breaker"); + if (breakerCounter < 0) reportToSend["contactor"]["off"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + else { + sendNotification("Cmd-mngr: onData", tbname, "circuit_breaker_was_turned_on_line", { line: line }, "", SEND_TO.tb, instance, "circuit_breaker"); + if (breakerCounter < 0) reportToSend["contactor"]["on"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + + //report status liniu + sendTelemetry({ status: status }, tbname) + + //current value + if (value == "Off") reportOfflineNodeStatus(line); //vyreportovat vsetky svietidla na linii + } + + } + } + else { + logger.debug("undefined cmd", cmd); + } + } + } + + return; + } + + //data from worksys + if (flowdata.data.hasOwnProperty("topic")) { + + let data = getNested(flowdata.data, "content", "data"); + + //if we get temperature in senica from senica-prod01 + let temperature = getNested(flowdata.data, "content", "senica_temperature"); + + if (temperature !== undefined) { + temperatureInSenica = temperature; + return; + } + + if (data === undefined) { + console.log("Invalid rpc command came from platform"); + return; + } + + let command = data.params.command; + let method = data.method; + let profile = data.params.payload; + if (profile == undefined) profile = ""; + let entity = data.params.entities[0]; + let entity_type = entity.entity_type; + let tbname = entity.tb_name; + + instance.send(SEND_TO.debug, flowdata.data); + 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") { + + //let command = data.params.command; + let value = data.params.payload.value; + + if (command == "dimming") { + + let nodeWasFound = false; + let keys = Object.keys(nodesData); + + //logger.debug("-----", keys); + + 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); + + value = parseInt(value); + if (value > 0) value = value + 128; + + params.type = "node-onetime-write"; + params.tbname = tbname; + params.address = node; + params.register = 1; + params.recipient = 1; + params.byte4 = value; + params.rw = 1; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'set dimming from platform'; + //params.debug = true; + + //debug(params); + logger.debug("dimming", params); + + tasks.push(params); + + 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); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 1; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read dimming (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + //pridame aj vyreportovanie - vykon + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 76; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read Input Power (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + //pridame aj vyreportovanie - prud svietidla + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 75; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read Input Current (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + //pridame aj vyreportovanie - power faktor - ucinnik + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 77; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read power factor (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + }, 4000); + + nodeWasFound = true; + break; + } + } + + if (!nodeWasFound) { + logger.debug("set dimming from platform", "unable to find tbname", tbname); + } + } + else { + instance.send(SEND_TO.debug, "undefined command " + command); + logger.debug("undefined command", command); + } + + return; + } + 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++) { + let node = keys[i]; + if (tbname == nodesData[node].tbname) { + + 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"); + + //profil úspešne prijatý pre node č. xx + sendNotification("Cmd-mngr", tbname, "dimming_profile_was_processed_for_node", { node: node }, profile, SEND_TO.tb, instance); + + nodesData[node].processed = false; + nodesData[node].profile = profile; + + processNodeProfile(node); + }); + }); + } + } + } + else { + + instance.send(SEND_TO.debug, "unknown method " + method); + logger.debug("unknown method", method); + + return; + } + } + + //nastav profil linie z platformy + 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") { + + 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++) { + let line = keys[i]; + if (tbname == relaysData[line].tbname) { + //zmazeme tasky + 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) { + + //update profile + logger.debug("worksys - update relay profile done:", profile); + instance.send(SEND_TO.debug, "worksys - update relay profile done"); + + relaysData[line].profile = profile; + + loadRelaysData(line) + logger.debug("loadRelaysData DONE for line", line); + + buildTasks({ processLineProfiles: true, line: line }); + + sendNotification("Cmd-mngr: set profile from worksys", tbname, "switching_profile_was_processed_for_line", { line: line }, profile, SEND_TO.tb, instance); + }); + }); + break; + } + } + } + else if (method == "set_command") { + let value = data.params.payload.value; + + 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; + + 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"); + if (line != 0) reportToSend["contactor"]["off"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + else { + turnLine("on", line, "command received from platform"); + if (line != 0) reportToSend["contactor"]["on"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + } + } + else { + instance.send(SEND_TO.debug, "undefined method " + method); + logger.debug("undefined method", method); + } + + return; + } + else { + instance.send(SEND_TO.debug, "UNKNOW entity_type " + entity_type); + logger.debug("UNKNOW entity_type", entity_type); + } + return; + } + + //terminal + if (!rsPort.isOpen) await rsPort.open(); + + let params = flowdata.data.body; + if (params == undefined) { + //logger.debug("Cmd-mngr: flowdata.data.body is undefined"); + return; + } + + params.priority = PRIORITY_TYPES.terminal; + params.type = "cmd-terminal"; + params.tbname = ""; + params.timestamp = PRIORITY_TYPES.terminal; + params.addMinutesToTimestamp = 0;// do not repeat task!!! + params.debug = true; + + let timestamp = Date.now(); + params.refFlowdataKey = timestamp; + //params.refFlowdata = flowdata; + //refFlowdata = flowdata; + + //console.log("flowdata", flowdata); + + cleanUpRefFlowdataObj(); + + refFlowdataObj[timestamp] = flowdata; + + //fix + //params.address = params.adress; + logger.debug("received from terminal", params); + logger.debug("date/time:", new Date()); + logger.debug("tasks length:", tasks.length); + + //tasks = []; + + //add to tasks + tasks.push(params); + + } + } + }) + + + //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) + } + + + /** + * 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; + + RESTBuilder.make(function(builder) { + + if (!builder) return; + + builder.method('GET'); + builder.url('http://192.168.252.2:8004/gettime?projects_id=1'); + + builder.callback(function(err, response, output) { + + 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); + } + + }); + } + + } 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); + + } else { + //console.log("Read-only", stdout); + + 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]: [ + { + "ts": date, + "values": values + } + ] + } + + tbHandler.sendToTb(dataToTb, instance); + } + + + function calculateDuskDawn(date, line, duskOffset = 0, dawnOffset = 0) { + + if (date === undefined) date = new Date(); + + 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); + } + + //if(profile.dawn_lux_sensor == false) + { + if (profile.hasOwnProperty("dawn_astro_clock_offset")) dawn_astro_clock_offset = parseInt(profile.dawn_astro_clock_offset); + } + + } + + } catch (error) { + if (profilestr != "") { + logger.debug(profilestr); + logger.debug(error); + } + } + + 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; + } + + //Dimming, CCT + else if (register == 1) { + let brightness = 0; + let dimming = byte0; + if (dimming > 128) { + //dimming = -128; + brightness = dimming - 128; + } + + //cct + //Ak Byte3 == 1: CCT = (Byte2*256)+Byte1 + let cct; + if (byte3 == 1) cct = byte2 * 256 + byte1; + else cct = bytesToInt(bytes.slice(0, 3)); + + //cct podla auditu + + values["dimming"] = brightness; + return values; + } + + // + else if (register == 4) { + values["master_node_version"] = bytes[1] + "." + bytes[2]; + //logger.debug("FW Version", register, bytes); + } + + //Napätie + else if (register == 74) { + let voltage = (bytesToInt(bytes) * 0.1).toFixed(1); + values["voltage"] = Number(voltage); + } + + //Prúd + else if (register == 75) { + let current = bytesToInt(bytes); + values["current"] = current; + } + + //výkon + else if (register == 76) { + let power = (bytesToInt(bytes) * 0.1).toFixed(2); + values["power"] = Number(power); + } + + //účinník + else if (register == 77) { + let power_factor = Math.cos(bytesToInt(bytes) * 0.1 * (Math.PI / 180)).toFixed(2); + values["power_factor"] = Number(power_factor); + } + + //frekvencia + else if (register == 78) { + let frequency = (bytesToInt(bytes) * 0.1).toFixed(2); + values["frequency"] = Number(frequency); + } + + //energia + else if (register == 79) { + let energy = bytesToInt(bytes); + values["energy"] = energy / 1000; //energia v kWh -> delit 1000 + } + + //doba života + else if (register == 80) { + let lifetime = (bytesToInt(bytes) / 60).toFixed(2); + values["lifetime"] = Number(lifetime); + } + + //nastavenie profilu + else if (register == 8) { + let time_schedule_settings = bytesToInt(bytes); + values["time_schedule_settings"] = time_schedule_settings; + } + + //naklon - nateraz sa z nodu nevycitava! kvoli problemom s accelerometrom a vracanymi hodnotami, posielame temp a x y z vo funkcii accelerometerData() + else if (register == 84) { + values["temperature"] = byte3 >= 128 ? (byte3 - 128) * (-1) : byte3; + values["inclination_x"] = byte2 >= 128 ? (byte2 - 128) * (-1) : byte2; + values["inclination_y"] = byte1 >= 128 ? (byte1 - 128) * (-1) : byte1; + values["inclination_z"] = byte0 >= 128 ? (byte0 - 128) * (-1) : byte0; + } + + //FW verzia nodu + else if (register == 89) { + //formát: "Byte3: Byte2.Byte1 (Byte0)" + values["fw_version"] = byte3 + ":" + byte2 + "." + byte1 + "(" + byte0 + ")"; + } + + else if (register == 87 || register == 6 || register == 7) { + var d = new Date(); + d.setHours(byte3, byte2, 0, 0); + let timestamp = d.getTime(); + + //aktuálny čas + if (register == 87) values["actual_time"] = timestamp; + //čas súmraku + else if (register == 6) values["dusk_time"] = timestamp; + //čas úsvitu + else if (register == 7) values["dawn_time"] = timestamp; + } + + 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; + + } + + + function getObjectByTbValue(object, tbname) { + return object[Object.keys(object).find(key => object[key].tbname === tbname)]; + } + + + function isObject(item) { + return (typeof item === "object" && !Array.isArray(item) && item !== null); + } + + + // we fake data, that should be received from accelerometer, as they are a bit unreliable. (temperature, x,y,z) + function accelerometerData() { + + if (temperatureInSenica === null) return; + + //clone nodesData and relaysData objects + let nodesData_clone = JSON.parse(JSON.stringify(nodesData)); + let relaysData_clone = JSON.parse(JSON.stringify(relaysData)); + + for (const key in relaysData_clone) { + + const lineData = relaysData_clone[key]; + const lineNumber = lineData.line; + const contactor = lineData.contactor; + + if (lineNumber === 0) continue; + + if (contactor === 1) { + + let date = Date.now(); + + Object.keys(nodesData_clone).forEach((node, index) => { + + setTimeout(function() { + + if (nodesData_clone[node].line === lineNumber) { + + // NOTE: if status of luminaire is NOK or OFFLINE, we do not send data; + let status = nodesData_clone[node].status; + if (status === "OFFLINE" || !status) return; + + let x = null; + if (naklony.hasOwnProperty(node)) x = naklony[node].naklon; + if (x === null) x = 0; + + sendTelemetry({ temperature: Math.round(temperatureInSenica + 10 + Math.floor(Math.random() * 3)), inclination_x: x, inclination_y: 0, inclination_z: 0 }, nodesData_clone[node].tbname, date); + } + + }, (index + 1) * 500); + }) + + } + } + } + + +} // end of instance.export + diff --git a/RVO50/flow/code.js b/RVO50/flow/code.js new file mode 100755 index 0000000..63b31bf --- /dev/null +++ b/RVO50/flow/code.js @@ -0,0 +1,90 @@ +exports.id = 'code'; +exports.title = 'Code'; +exports.group = 'Common'; +exports.color = '#656D78'; +exports.input = true; +exports.output = 1; +exports.author = 'Peter Širka'; +exports.icon = 'code'; +exports.version = '1.2.0'; +exports.options = { outputs: 1, code: 'send(0, value);', keepmessage: true }; + +exports.html = `
+
+
+
@(Number of outputs)
+
@(Minimum is 1)
+
+
+
@(Code)
+
@(Keep message instance)
+
+`; + +exports.readme = `# Code + +This component executes custom JavaScript code as it is and it doesn't contain any secure scope. + +\`\`\`javascript +// value {Object} contains received data +// send(outputIndex, newValue) sends a new value +// error(value) sends an error +// instance {Object} a current component instance +// flowdata {Object} a current flowdata +// repository {Object} a current repository of flowdata +// Example: + +// send() can be execute multiple times +send(0, value); +\`\`\``; + +exports.install = function(instance) { + + var fn; + + instance.on('data', function(response) { + if (fn) { + try { + fn(response.data, instance, response, instance.options, response.repository, require); + } catch (e) { + response.data = e; + instance.throw(response); + } + } + }); + + instance.reconfigure = function() { + try { + if (instance.options.code) { + instance.status(''); + var code = 'var send = function(index, value) { if (options.keepmessage) { flowdata.data = value; instance.send2(index, flowdata); } else instance.send2(index, value);}; var error = function(err) { instance.throw(err); }; ' + instance.options.code; + fn = new Function('value', 'instance', 'flowdata', 'options', 'repository', 'require', code); + } else { + instance.status('Not configured', 'red'); + fn = null; + } + } catch (e) { + fn = null; + instance.error('Code: ' + e.message); + } + }; + + instance.on('options', instance.reconfigure); + instance.reconfigure(); +}; \ No newline at end of file diff --git a/RVO50/flow/comment.js b/RVO50/flow/comment.js new file mode 100755 index 0000000..1e0cd13 --- /dev/null +++ b/RVO50/flow/comment.js @@ -0,0 +1,11 @@ +exports.id = 'comment'; +exports.title = 'Comment'; +exports.group = 'Common'; +exports.color = '#704cff'; +exports.author = 'Martin Smola'; +exports.icon = 'comment'; +exports.traffic = false; +exports.version = '1.0.0'; +exports.readme = '# Comment'; + +exports.install = function() {}; diff --git a/RVO50/flow/count.js b/RVO50/flow/count.js new file mode 100755 index 0000000..fa92ee9 --- /dev/null +++ b/RVO50/flow/count.js @@ -0,0 +1,60 @@ +exports.id = 'count'; +exports.title = 'Count'; +exports.version = '1.0.1'; +exports.author = 'John Graves'; +exports.color = '#656D78'; +exports.icon = 'plus-square'; +exports.input = 2; +exports.output = 1; +exports.options = { increment: 1, initialvalue: 1 }; +exports.readme = `# Counter + +Counter Number of times called.`; + +exports.html = `
+
@(Initial Value)
+
@(Increment)
+

Example Video

+
`; + +exports.readme = `# Count + +This component counts the number of messages received. + +__Response:__ + +Integer value based on the initial value and increment settings. + +__Arguments:__ +- Initial Value: What number should be output on the receipt of the first message. +- Increment: What should the increment be for each following message received.`; + +exports.install = function(instance) { + + var count = 0; + var initialCall = true; + + instance.on('data', function(flowdata) { + var index = flowdata.index; + if (index) { + instance.debug('Reset Count.'); + count = instance.options.initialvalue; + initialCall = true; + } else { + // If this is the first time, set the value to 'initial value' + if(initialCall) { + initialCall = false; + count = instance.options.initialvalue; + } else + count = count+instance.options.increment; + instance.status('Count:' + count); + instance.send2(count); + } + }); + + instance.on('options', function() { + count = instance.options.initialvalue; + initialCall = true; + }); + +}; diff --git a/RVO50/flow/db_connector.js b/RVO50/flow/db_connector.js new file mode 100755 index 0000000..65ee94b --- /dev/null +++ b/RVO50/flow/db_connector.js @@ -0,0 +1,286 @@ +exports.id = 'db_connector'; +exports.title = 'DbConnector'; +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.html = `
+
+
+
DbConnector
+
+
+
`; + +exports.readme = `# read/write data to tables`; + +const instanceSendTo = { + debug: 0, + http_response: 1, +} + +const { promisifyBuilder, makeMapFromDbResult } = require('./helper/db_helper.js'); + +function extractWhereParams(params) +{ + let name = params[0]; + let operator = '='; + let value = params[1]; + + if(params.length == 3) + { + operator = params[1]; + value = params[2]; + } + + return {name: name, operator: operator, value: value}; +} + +exports.install = function(instance) { + + let refFlowdata = null;//holds reference to httprequest flowdata + + instance.on("close", () => { + + }) + + + instance.on("data", async function(flowdata) { + + let params = flowdata.data.body; + console.log("DbConnector", params); + + refFlowdata = flowdata; + + if(refFlowdata != undefined) + { + //make http response + let responseObj = {}; + responseObj["type"] = "SUCESS"; + + try{ + + let table = params.table; + let action = params.action; + + + if(params.data != undefined) + { + let className = params.data.className; + + if(className == "SqlQueryBuilder") + { + let type = params.data.type; + + console.log("SqlQueryBuilder---->", params.data); + + if(type == "SELECT") + { + let table = params.data.queryData.tables[0].table; + + const db = TABLE(table); + var builder = db.find(); + + let result = await promisifyBuilder(builder); + + let response = {}; + response["result"] = result; + response["success"] = true; + + responseObj["data"] = response; + + //console.log(responseObj); + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + } + + return; + } + } + + + console.log("db_connector---->", table, action); + + //actions: read, replace, insert, delete, update... + + if(action == "read") + { + const db = TABLE(params.table); + + //where builder.where('age', '<', 15); + //builder.where('id', 3403); + + var builder = db.find(); + + //https://docs.totaljs.com/latest/en.html#api~DatabaseBuilder~builder.where + if(params.hasOwnProperty("where")) + { + //optionalCan contain "=", "<=", "<", ">=", ">". + //Default value: '=' + + //1.["production_line", 1] + //2. ["or", ["production_line", 1], ["production_line", 2], "end"] + + if (Array.isArray(params.where)) { + + let multipleConditions = false; + + if(params.where[0] == "or") multipleConditions = true; + if (Array.isArray(params.where[0])) multipleConditions = true; + + if(multipleConditions) + { + + for(var i = 0; i < params.where.length; i++) + { + const item = params.where[i]; + + if(item === "or") builder.or(); + + if (Array.isArray(item)) + { + const { name, operator, value } = extractWhereParams(item); + builder.where(name, operator, value); + } + + if(item === "end") builder.end(); + + } + + } + else + { + const { name, operator, value } = extractWhereParams(params.where); + builder.where(name, operator, value); + } + + } + + /* + if(params.where.length >=2 ) + { + let name = params.where[0]; + let operator = '='; + let value = params.where[1]; + + if(params.where.length == 3) + { + operator = params.where[1]; + value = params.where[2]; + } + + builder.where(name, operator, value); + } + */ + } + + if(params.hasOwnProperty("between")) + { + builder.between(params.between[0], params.between[1], params.between[2]); + } + + let response = await promisifyBuilder(builder); + responseObj["data"] = response; + + //console.log(responseObj); + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + + return; + } + + if(action == "delete") + { + + } + + + if(action == "update") + { + //! data receiving from terminal (params) + // { + // hostname: 'localhost', + // table: 'settings', + // action: 'update', + // body: { + // rvo_name: 'terrrr', + // lang: 'en', + // temperature_adress: '28.427B45920702', + // latitude: 48.70826502, + // longitude: 17.28455203, + // mqtt_host: '192.168.252.4', + // mqtt_clientid: 'showroom_test_panel_led', + // mqtt_username: 'xmRd6RJxW53WZe4vMFLU', + // mqtt_port: 1883, + // maintanace_mode: false + // } + // } + const tableToModify = TABLE(params.table); + const newValues = params.body; + + tableToModify.modify(newValues).make(function(builder) { + + builder.callback(function(err, response) { + + if(!err) + { + responseObj["data"] = response; + responseObj["tableUpdated"] = true; + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + } + }); + }); + + } + + if(action == "replace") + { + //truncate table + const db = TABLE(params.table); + var builder = db.remove(); + db.clean(); + + //insert data + let data = params.data; + + for(let i = 0; i < data.length; i++) + { + //console.log(data[i]); + db.insert(data[i]); + } + + console.log("insert done"); + + let responseObj = {}; + responseObj["type"] = "SUCESS"; + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + + + } + + + + } catch (error) { + //console.log(error); + responseObj["type"] = "ERROR"; + responseObj["message"] = error; + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + } + } + }) +} + + diff --git a/RVO50/flow/db_init.js b/RVO50/flow/db_init.js new file mode 100755 index 0000000..b399878 --- /dev/null +++ b/RVO50/flow/db_init.js @@ -0,0 +1,113 @@ +exports.id = 'db_init'; +exports.title = 'DB Initialization'; +exports.group = 'Worksys'; +exports.color = '#888600'; +exports.version = '1.0.2'; +exports.icon = 'sign-out'; +exports.output = 2; + +exports.readme = ` + # DB initialization +`; + +const { promisifyBuilder, makeMapFromDbResult } = require('./helper/db_helper.js'); +const { initNotification } = require('./helper/notification_reporter'); +const errorHandler = require('./helper/ErrorToServiceHandler'); +const total_energy = require('../databases/total_energy'); + +const SEND_TO = { + db_init: 0, + infoSender: 1 +}; + + +exports.install = async function(instance) { + const dbNodes = TABLE("nodes"); + const dbRelays = TABLE("relays"); + const dbSettings = TABLE("settings"); + 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 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.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"]; + Object.keys(dbs.nodesData).forEach(node => dbs.nodesData[node].readout = {}) + + let rvo_number = responseSettings[0]["rvo_name"].match(/\D+(\d{1,2})_/)[1]; + + dbs.settings = { + edge_fw_version: "2025-10-08", //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"], + phases: responseSettings[0]["phases"], + cloud_topic: responseSettings[0]["cloud_topic"], + has_main_switch: responseSettings[0]["has_main_switch"], + daily_report: responseSettings[0]["daily_report"], + send_changed_node_numbers: responseSettings[0]["send_changed_node_numbers"], + rvo_number: rvo_number, + + //dynamic values + masterNodeIsResponding: true, //cmd_manager + maintenance_mode: false, + } + + + dbs.settings.energy_to_switch_lamps = total_energy[rvo_number]; + if (dbs.settings.energy_to_switch_lamps === undefined) console.log('=============== db_init.js: energy_to_switch_lamps is undefined'); + + FLOW.dbLoaded = true; + errorHandler.setProjectId(dbs.settings.project_id); + initNotification(); + + //APP START - send to data services + const toService = { + id: dbs.settings.project_id, + name: dbs.settings.rvo_name, + fw_version: dbs.settings.edge_fw_version, + startdate: new Date().toISOString().slice(0, 19).replace('T', ' '), + js_error: "", + error_message: "" + }; + + instance.send(SEND_TO.infoSender, toService); + console.log("----------------> START - message send to service", toService); + + setTimeout(() => { + console.log("DB_INIT - data loaded"); + instance.send(SEND_TO.db_init, "_") + }, 5000) + +}; + diff --git a/RVO50/flow/debug.js b/RVO50/flow/debug.js new file mode 100755 index 0000000..00cb259 --- /dev/null +++ b/RVO50/flow/debug.js @@ -0,0 +1,100 @@ +exports.id = 'debug'; +exports.title = 'Debug'; +exports.author = 'Peter Širka'; +exports.color = '#967ADC'; +exports.click = true; +exports.input = true; +exports.icon = 'bug'; +exports.version = '2.0.4'; +exports.options = { enabled: true, repository: false, type: 'data' }; +exports.readme = `# Debug + +Prints data to the debug tab.`; + +exports.html = `
+
+
+
@(Output type)
+
@(Path to the property (leave empty to show the whole data object))
+
@(A group name)
+
@(Enabled)
+
+
+
`; + +exports.install = function(instance) { + + instance.on('data', function(response) { + if (instance.options.enabled) { + + var opt = instance.options; + var rep = response.repository; + var val = response.data; + var id = response.id; + + switch (instance.options.type){ + case 'both': + var data = {}; + data.repository = rep; + data.data = val instanceof Error ? { error: val.message, stack: val.stack } : val; + instance.debug(safeparse(opt.property ? U.get(data, opt.property) : data), undefined, opt.group, id); + break; + case 'repository': + instance.debug(safeparse(opt.property ? U.get(rep, opt.property) : rep), undefined, opt.group, id); + break; + case 'data': + default: + if (val instanceof Error) + instance.debug({ error: val.message, stack: val.stack }, undefined, opt.group, id); + else + instance.debug(safeparse(opt.property ? U.get(val, opt.property) : val), undefined, opt.group, id); + break; + } + } + }); + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + instance.save(); + }); + + instance.on('options', function() { + instance.custom.status(); + }); + + instance.custom.status = function() { + instance.status(instance.options.enabled ? 'Enabled' : 'Disabled'); + }; + + instance.custom.status(); + + function safeparse(o) { + + if (o instanceof Buffer) + return o; + + if (o === undefined) + return 'undefined'; + + if (o === null) + return 'null'; + + var cache = []; + var str = JSON.stringify(o, function(key, value) { + if (typeof value === 'object' && value !== null) { + if (cache.indexOf(value) !== -1) { + try { + return JSON.parse(JSON.stringify(value)); + } catch (error) { + return; + } + } + cache.push(value); + } + return value; + }); + cache = null; + return JSON.parse(str); + } +}; diff --git a/RVO50/flow/designer.json b/RVO50/flow/designer.json new file mode 100755 index 0000000..580f5a3 --- /dev/null +++ b/RVO50/flow/designer.json @@ -0,0 +1,3102 @@ +{ + "tabs": [ + { + "name": "MAIN PUSH", + "linker": "main-push", + "id": "1612772287426", + "index": 0 + }, + { + "name": "CMD manager", + "linker": "cmd-manager", + "id": "1615551125555", + "index": 1 + }, + { + "name": "Devices", + "linker": "devices", + "id": "1611921777196", + "index": 2 + } + ], + "components": [ + { + "id": "1611951142547", + "component": "debug", + "tab": "1611921777196", + "name": "ERROR", + "x": 598, + "y": 60, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#DA4453", + "notes": "" + }, + { + "id": "1612776786008", + "component": "wsmqttpublish", + "tab": "1612772287426", + "name": "WS MQTT publish", + "x": 281.75, + "y": 174, + "connections": { + "0": [ + { + "index": "0", + "id": "1615551060773" + } + ], + "1": [ + { + "index": "0", + "id": "1618300858252" + }, + { + "index": "0", + "id": "1618558465485" + } + ], + "2": [ + { + "index": "0", + "id": "1634303685503" + } + ], + "3": [ + { + "index": "0", + "id": "1731068754606" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Connected", + "color": "green" + }, + "options": { + "username": "", + "clientid": "", + "port": "1883", + "host": "" + }, + "color": "#888600", + "notes": "" + }, + { + "id": "1612778461252", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "tb-push", + "x": 72.75, + "y": 328, + "connections": { + "0": [ + { + "index": "0", + "id": "1612783322136" + }, + { + "index": "1", + "id": "1612776786008" + }, + { + "index": "0", + "id": "1731068754606" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1612783322136", + "component": "debug", + "tab": "1612772287426", + "name": "to TB", + "x": 283.75, + "y": 324, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615551060773", + "component": "debug", + "tab": "1612772287426", + "name": "errors from MQTT Broker", + "x": 594, + "y": 57, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#DA4453", + "notes": "" + }, + { + "id": "1615563373927", + "component": "debug", + "tab": "1615551125555", + "name": "Debug", + "x": 755, + "y": 155, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#DA4453", + "notes": "" + }, + { + "id": "1615566865233", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "tb-push", + "x": 755, + "y": 248, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1615798582262", + "component": "debug", + "tab": "1615551125555", + "name": "CMD_debug", + "x": 755, + "y": 346, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615802995322", + "component": "debug", + "tab": "1611921777196", + "name": "Debug", + "x": 596.8833312988281, + "y": 566.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Disabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": false + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615809128443", + "component": "debug", + "tab": "1611921777196", + "name": "tempToTb", + "x": 595.8833312988281, + "y": 658.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615809595184", + "component": "virtualwireout", + "tab": "1611921777196", + "name": "tb-push", + "x": 597.8833312988281, + "y": 377.25, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1616165795916", + "component": "httproute", + "tab": "1615551125555", + "name": "POST /terminal", + "x": 135, + "y": 547, + "connections": { + "0": [ + { + "index": "0", + "id": "1684060205000" + }, + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Listening", + "color": "green" + }, + "options": { + "timeout": 10, + "cachepolicy": 0, + "cacheexpire": "5 minutes", + "size": 5, + "url": "/terminal", + "method": "POST", + "name": "", + "flags": [ + "id:1616165795916", + "post", + 10000 + ], + "emptyresponse": false + }, + "color": "#5D9CEC", + "notes": "### Configuration\n\n- __POST /terminal__\n- flags: \n- maximum request data length: __5 kB__\n- empty response: __false__\n- cache policy: __no cache__\n- cache expire: __5 minutes__", + "cloning": false + }, + { + "id": "1616165824813", + "component": "httpresponse", + "tab": "1615551125555", + "name": "HTTP Response", + "x": 753, + "y": 423, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "json" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1617104731852", + "component": "debug", + "tab": "1615551125555", + "name": "DIDO_Debug", + "x": 669, + "y": 1040, + "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": "turnOff line", + "x": 133, + "y": 1161, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "object", + "data": "{line: 3, command: \"turnOff\", force: true}" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1617115013095", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "tb-push", + "x": 669, + "y": 1150, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1617284749681", + "component": "trigger", + "tab": "1615551125555", + "name": "update profile / node", + "x": 112, + "y": 208, + "connections": { + "0": [ + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "data": "profile_nodes", + "datatype": "string" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1618235171399", + "component": "trigger", + "tab": "1615551125555", + "name": "tun tasks", + "x": 184, + "y": 279, + "connections": { + "0": [ + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "data": "run" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1618300858252", + "component": "debug", + "tab": "1612772287426", + "name": "wsmqtt-exit1", + "x": 597.8833312988281, + "y": 149, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1618393583970", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "to-cmd-manager", + "x": 668.8833312988281, + "y": 1269, + "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": 132.88333129882812, + "y": 367, + "connections": { + "0": [ + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "platform-rpc-call", + "color": "gray" + }, + "options": { + "wirename": "platform-rpc-call" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1618393759854", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "cmd_to_dido", + "x": 119.88333129882812, + "y": 1007, + "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": 752.8833312988281, + "y": 527, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "cmd_to_dido", + "color": "gray" + }, + "options": { + "wirename": "cmd_to_dido" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1618558465485", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "platform-rpc-call", + "x": 597.8833312988281, + "y": 247, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "platform-rpc-call", + "color": "gray" + }, + "options": { + "wirename": "platform-rpc-call" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1618572059773", + "component": "trigger", + "tab": "1615551125555", + "name": "turnOn line", + "x": 132, + "y": 1085, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "data": "{line: 1, command: \"turnOn\", force: true}", + "datatype": "object" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1619515097737", + "component": "cmd_manager", + "tab": "1615551125555", + "name": "CMD Manager", + "x": 452.1091003417969, + "y": 341.05455017089844, + "connections": { + "0": [ + { + "index": "0", + "id": "1615563373927" + } + ], + "1": [ + { + "index": "0", + "id": "1615566865233" + }, + { + "index": "0", + "id": "1615798582262" + } + ], + "2": [ + { + "index": "0", + "id": "1616165824813" + } + ], + "3": [ + { + "index": "0", + "id": "1618393827655" + } + ], + "4": [ + { + "index": "0", + "id": "1635936391935" + } + ], + "5": [ + { + "index": "0", + "id": "1757006030239" + }, + { + "index": "0", + "id": "1757006060377" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1619605019281", + "component": "httproute", + "tab": "1615551125555", + "name": "GET db", + "x": 173, + "y": 653, + "connections": { + "0": [ + { + "index": "0", + "id": "1684060205000" + }, + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Listening", + "color": "green" + }, + "options": { + "timeout": 5, + "cachepolicy": 0, + "cacheexpire": "5 minutes", + "size": 5, + "url": "/db", + "method": "GET", + "name": "", + "flags": [ + "id:1619605019281", + "get", + 5000 + ] + }, + "color": "#5D9CEC", + "notes": "### Configuration\n\n- __GET /db__\n- flags: undefined\n- maximum request data length: __5 kB__\n- empty response: __undefined__\n- cache policy: __no cache__\n- cache expire: __5 minutes__", + "cloning": false + }, + { + "id": "1619784672383", + "component": "trigger", + "tab": "1615551125555", + "name": "turnOnAlarm", + "x": 120, + "y": 1234, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "object", + "data": "{command: \"turnOnAlarm\"}" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1619784812964", + "component": "trigger", + "tab": "1615551125555", + "name": "turnOffAlarm", + "x": 118, + "y": 1307, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "object", + "data": "{command: \"turnOffAlarm\"}" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1621340721628", + "component": "virtualwireout", + "tab": "1611921777196", + "name": "modbus_to_dido", + "x": 599, + "y": 471, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "modbus_to_dido", + "color": "gray" + }, + "options": { + "wirename": "modbus_to_dido" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1622640022885", + "component": "httproute", + "tab": "1615551125555", + "name": "POST /db_connector", + "x": 98, + "y": 1586, + "connections": { + "0": [ + { + "index": "0", + "id": "1622640073521" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Listening", + "color": "green" + }, + "options": { + "timeout": 5, + "cachepolicy": 0, + "cacheexpire": "5 minutes", + "size": 5, + "url": "/db_connector", + "method": "POST", + "flags": [ + "id:1622640022885", + "post", + 5000 + ] + }, + "color": "#5D9CEC", + "notes": "### Configuration\n\n- __POST /db_connector__\n- flags: \n- maximum request data length: __5 kB__\n- empty response: __undefined__\n- cache policy: __no cache__\n- cache expire: __5 minutes__", + "cloning": false + }, + { + "id": "1622640073521", + "component": "db_connector", + "tab": "1615551125555", + "name": "DbConnector", + "x": 372, + "y": 1572, + "connections": { + "1": [ + { + "index": "0", + "id": "1622641420685" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "edge": "undefined" + }, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1622641420685", + "component": "httpresponse", + "tab": "1615551125555", + "name": "HTTP Response", + "x": 596, + "y": 1586, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1634303504177", + "component": "monitormemory", + "tab": "1612772287426", + "name": "RAM", + "x": 69.88333129882812, + "y": 888.5, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465281992" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "858.88 MB / 985.68 MB", + "color": "gray" + }, + "options": { + "enabled": true, + "interval": 30000 + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1634303533779", + "component": "monitordisk", + "tab": "1612772287426", + "name": "disk", + "x": 70.88333129882812, + "y": 982.5, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465821120" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "5.78 GB / 7.26 GB", + "color": "gray" + }, + "options": { + "enabled": true, + "path": "/", + "interval": 30000 + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1634303595494", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "send-to-services", + "x": 51.883331298828125, + "y": 1400.5, + "connections": { + "0": [ + { + "index": "0", + "id": "1634463186563" + }, + { + "index": "1", + "id": "1634488120710" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1634303602169", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "send-to-services", + "x": 426.8833312988281, + "y": 878.5, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1634303685503", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "send-to-services", + "x": 600.8833312988281, + "y": 341.5, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1634303743260", + "component": "httprequest", + "tab": "1612772287426", + "name": "192.168.252.2:8004/sentmessage", + "reference": "", + "x": 506.8833312988281, + "y": 1331.7333374023438, + "connections": { + "0": [ + { + "index": "0", + "id": "1635327431236" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "url": "http://192.168.252.2:8004/sentmessage", + "method": "POST", + "stringify": "json" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1634463186563", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 305.75, + "y": 1442, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634464580289", + "component": "code", + "tab": "1612772287426", + "name": "Code", + "x": 245, + "y": 787, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465243324" + }, + { + "index": "0", + "id": "1634303602169" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "keepmessage": true, + "code": "let response = {};\nresponse.cpu = value.cpu;\nresponse.uptime = value.uptime;\n\nsend(0, response);", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1634465243324", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 428, + "y": 784, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634465281992", + "component": "code", + "tab": "1612772287426", + "name": "Code", + "x": 245, + "y": 884, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465338103" + }, + { + "index": "0", + "id": "1634303602169" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "keepmessage": true, + "code": "value.sender = \"ram\";\n\nlet response = {};\n\nresponse.memory_total = Math.round(value.total / (1024 ** 2));\nresponse.memory_free = Math.round(value.free / (1024 ** 2));\nresponse.memory_used = Math.round(value.used / (1024 ** 2));\n\nsend(0, response);", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1634465338103", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 429, + "y": 976, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634465821120", + "component": "code", + "tab": "1612772287426", + "name": "Code", + "x": 245, + "y": 978, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465892500" + }, + { + "index": "0", + "id": "1634303602169" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "keepmessage": true, + "code": "value.sender = \"hdd\";\n\nlet response = {};\n\nresponse.hdd_total = Math.round(value.total / (1024 ** 2));\nresponse.hdd_free = Math.round(value.free / (1024 ** 2));\nresponse.hdd_used = Math.round(value.used / (1024 ** 2));\n\nsend(0, response);", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1634465892500", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 432, + "y": 1068, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634484067516", + "component": "debug", + "tab": "1612772287426", + "name": "Send info", + "x": 513, + "y": 1441, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634488120710", + "component": "infosender", + "tab": "1612772287426", + "name": "Info sender", + "x": 301, + "y": 1336, + "connections": { + "0": [ + { + "index": "0", + "id": "1634484067516" + }, + { + "index": "0", + "id": "1634303743260" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "edge": "undefined" + }, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1635327431236", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 837.8833312988281, + "y": 1325.5, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1635936391935", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "send-to-services", + "x": 753, + "y": 623, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1637069803394", + "component": "monitorconsumption", + "tab": "1612772287426", + "name": "CPU", + "x": 69, + "y": 791, + "connections": { + "0": [ + { + "index": "0", + "id": "1634464580289" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "49.2% / 69.91 MB", + "color": "gray" + }, + "options": { + "monitorfiles": true, + "monitorconnections": true, + "monitorsize": true, + "monitorconsumption": true, + "enabled": true, + "interval": 30000 + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1683664161036", + "component": "debug", + "tab": "1615551125555", + "name": "CMDtoDIDO", + "x": 392, + "y": 1012, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1683981346282", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "from-dido-controller", + "x": 112, + "y": 459, + "connections": { + "0": [ + { + "index": "0", + "id": "1684055037116" + }, + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "from-dido-controller", + "color": "gray" + }, + "options": { + "wirename": "from-dido-controller" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1684055037116", + "component": "debug", + "tab": "1615551125555", + "name": "from dido to cmd", + "x": 451, + "y": 532, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1684060205000", + "component": "debug", + "tab": "1615551125555", + "name": "HTTP routes", + "x": 450, + "y": 639, + "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": "MDBToDido", + "x": 598, + "y": 147, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1699963668903", + "component": "dido_controller", + "tab": "1615551125555", + "name": "DIDO_Controller", + "x": 397, + "y": 1131, + "connections": { + "0": [ + { + "index": "0", + "id": "1617104731852" + } + ], + "1": [ + { + "index": "0", + "id": "1617104731852" + }, + { + "index": "0", + "id": "1617115013095" + } + ], + "2": [ + { + "index": "0", + "id": "1618393583970" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "edge": "undefined" + }, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1699964678894", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "modbus_to_dido", + "x": 96, + "y": 924, + "connections": { + "0": [ + { + "index": "0", + "id": "1699963668903" + }, + { + "index": "0", + "id": "1699964793925" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "modbus_to_dido", + "color": "gray" + }, + "options": { + "wirename": "modbus_to_dido" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1699964793925", + "component": "debug", + "tab": "1615551125555", + "name": "modbusToDido", + "x": 388, + "y": 920, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1699965957410", + "component": "modbus_reader", + "tab": "1611921777196", + "name": "Modbus reader", + "x": 232, + "y": 175, + "connections": { + "0": [ + { + "index": "0", + "id": "1611951142547" + } + ], + "1": [ + { + "index": "0", + "id": "1621340721628" + }, + { + "index": "0", + "id": "1684179110403" + }, + { + "index": "0", + "id": "1717441414646" + } + ], + "2": [ + { + "index": "0", + "id": "1615809595184" + }, + { + "index": "0", + "id": "1714752862828" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1700411878636", + "component": "thermometer", + "tab": "1611921777196", + "name": "Thermometer", + "x": 234.75, + "y": 444, + "connections": { + "0": [ + { + "index": "0", + "id": "1615802995322" + } + ], + "1": [ + { + "index": "0", + "id": "1615809595184" + }, + { + "index": "0", + "id": "1615809128443" + } + ], + "2": [ + { + "index": "0", + "id": "1621340721628" + }, + { + "index": "0", + "id": "1732889185927" + }, + { + "index": "0", + "id": "1717441414646" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#5CB36D", + "notes": "" + }, + { + "id": "1714752862828", + "component": "debug", + "tab": "1611921777196", + "name": "MDBToTb", + "x": 766, + "y": 324, + "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": 764.0833282470703, + "y": 222, + "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\telse if(value.status === \"NOK-thermometer\")\n\t{\n\t\tsend(0, {\"thermometer\": \"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\telse if(value.values.hasOwnProperty(\"temperature\"))\n\t{\n\t\tsend(0, {\"thermometer\": \"OK\"});\n\t}\n}", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1717442627834", + "component": "debug", + "tab": "1611921777196", + "name": "modbus service", + "x": 966.0833282470703, + "y": 165, + "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": 968.0833282470703, + "y": 268, + "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": 88.75, + "y": 1685, + "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": 296, + "y": 1671, + "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\", \"Flow has been restarted\", \"Node db has changed\"]", + "types": "[\"emergency\", \"critical\", \"error\", \"alert\"]", + "name": "" + }, + "color": "#30E193", + "notes": "" + }, + { + "id": "1718016073501", + "component": "httprequest", + "tab": "1612772287426", + "name": "http://192.168.252.2:8004/slack", + "x": 495, + "y": 1753, + "connections": { + "0": [ + { + "index": "0", + "id": "1718016086212" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "url": "http://192.168.252.2:8004/slack", + "method": "POST", + "stringify": "json" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1718016086212", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 832, + "y": 1664, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "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": 87, + "y": 1591, + "connections": { + "0": [ + { + "index": "0", + "id": "1718016052341" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "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\": \"\" } } } ] }", + "datatype": "object" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1729855334955", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "platform-rpc-call", + "x": 599.9333343505859, + "y": 541.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "platform-rpc-call", + "color": "gray" + }, + "options": { + "wirename": "platform-rpc-call" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1729855371093", + "component": "debug", + "tab": "1612772287426", + "name": "rpc cloud", + "x": 601.9333343505859, + "y": 440.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1731068658334", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 75.75, + "y": 184, + "connections": { + "0": [ + { + "index": "0", + "id": "1612776786008" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731068754606", + "component": "cloudmqttconnect", + "tab": "1612772287426", + "name": "MQTT to senica-prod01", + "x": 284.75, + "y": 452, + "connections": { + "1": [ + { + "index": "0", + "id": "1729855371093" + }, + { + "index": "0", + "id": "1729855334955" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Connected", + "color": "green" + }, + "options": { + "username": "", + "clientid": "", + "port": "2764", + "host": "192.168.252.2", + "topic": "" + }, + "color": "#888600", + "notes": "" + }, + { + "id": "1731069001548", + "component": "db_init", + "tab": "1612772287426", + "name": "DB Initialization", + "x": 1003.75, + "y": 240.25, + "connections": { + "0": [ + { + "index": "0", + "id": "1731069033416" + } + ], + "1": [ + { + "index": "0", + "id": "1747561603739" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#888600", + "notes": "" + }, + { + "id": "1731069033416", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "db-init", + "x": 1244.75, + "y": 233.25, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069059135", + "component": "showdb", + "tab": "1612772287426", + "name": "Show db data", + "x": 1186.75, + "y": 821.25, + "connections": { + "0": [ + { + "index": "0", + "id": "1731069079243" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#888600", + "notes": "" + }, + { + "id": "1731069079243", + "component": "debug", + "tab": "1612772287426", + "name": "dbData", + "x": 1390.75, + "y": 870.25, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1731069116691", + "component": "trigger", + "tab": "1612772287426", + "name": "settings", + "x": 934.75, + "y": 669.75, + "connections": { + "0": [ + { + "index": "0", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069131637", + "component": "trigger", + "tab": "1612772287426", + "name": "relaysData", + "x": 876.75, + "y": 733.75, + "connections": { + "0": [ + { + "index": "1", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069137374", + "component": "trigger", + "tab": "1612772287426", + "name": "nodesData", + "x": 852.75, + "y": 794.75, + "connections": { + "0": [ + { + "index": "2", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069179846", + "component": "trigger", + "tab": "1612772287426", + "name": "pinsData", + "x": 850.75, + "y": 861.75, + "connections": { + "0": [ + { + "index": "3", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069192937", + "component": "trigger", + "tab": "1612772287426", + "name": "sample data", + "x": 857.75, + "y": 928.75, + "connections": { + "0": [ + { + "index": "4", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069264443", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 63.75, + "y": 1279, + "connections": { + "0": [ + { + "index": "0", + "id": "1634488120710" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069334626", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "db-init", + "x": 172.88333129882812, + "y": 129, + "connections": { + "0": [ + { + "index": "0", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069548145", + "component": "virtualwirein", + "tab": "1611921777196", + "name": "db-init", + "x": 46.75, + "y": 192, + "connections": { + "0": [ + { + "index": "0", + "id": "1699965957410" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069567152", + "component": "virtualwirein", + "tab": "1611921777196", + "name": "db-init", + "x": 44.75, + "y": 465, + "connections": { + "0": [ + { + "index": "0", + "id": "1700411878636" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731070156936", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "db-init", + "x": 126.88333129882812, + "y": 1377, + "connections": { + "0": [ + { + "index": "2", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731234189516", + "component": "trigger", + "tab": "1612772287426", + "name": "monitor.txt", + "x": 882.75, + "y": 991.75, + "connections": { + "0": [ + { + "index": "5", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731234189551", + "component": "trigger", + "tab": "1612772287426", + "name": "err.txt", + "x": 904.75, + "y": 1053.75, + "connections": { + "0": [ + { + "index": "6", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1732700042559", + "component": "nodesdb_change_check", + "tab": "1612772287426", + "name": "Nodes DB change check", + "x": 266.8833312988281, + "y": 1980.2333984375, + "connections": { + "0": [ + { + "index": "0", + "id": "1732700071298" + }, + { + "index": "0", + "id": "1732700642917" + } + ], + "1": [ + { + "index": "0", + "id": "1759958914348" + }, + { + "index": "0", + "id": "1759959003114" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#888600", + "notes": "" + }, + { + "id": "1732700057052", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 76.75, + "y": 1988, + "connections": { + "0": [ + { + "index": "0", + "id": "1732700042559" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1732700071298", + "component": "debug", + "tab": "1612772287426", + "name": "nodesChange", + "x": 571.8833312988281, + "y": 2018.2333984375, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1732700642917", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "tb-push", + "x": 567.8833312988281, + "y": 1933, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1732889185927", + "component": "debug", + "tab": "1611921777196", + "name": "tempToDido", + "x": 594.8833312988281, + "y": 753, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1733574412965", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 72.75, + "y": 474, + "connections": { + "0": [ + { + "index": "1", + "id": "1731068754606" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1747561603739", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "send-to-services", + "x": 1243.8833312988281, + "y": 334.5, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1747562867845", + "component": "comment", + "tab": "1612772287426", + "name": "FLOW STARTING POINT", + "x": 1003.5666656494141, + "y": 178, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#704cff", + "notes": "" + }, + { + "id": "1749211698385", + "component": "trigger", + "tab": "1612772287426", + "name": "deviceStatus", + "x": 911.75, + "y": 1116.75, + "connections": { + "0": [ + { + "index": "7", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1757006030239", + "component": "httprequest", + "tab": "1615551125555", + "name": "192.168.252.2:8015/daily_report", + "x": 756.5666656494141, + "y": 715.4499969482422, + "connections": { + "0": [ + { + "index": "0", + "id": "1757006045804" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "stringify": "json", + "method": "POST", + "url": "http://192.168.252.2:8015/daily_report" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1757006045804", + "component": "debug", + "tab": "1615551125555", + "name": "ddd", + "x": 1091.566665649414, + "y": 711.4499969482422, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1757006060377", + "component": "debug", + "tab": "1615551125555", + "name": "reportDebug", + "x": 749.5666656494141, + "y": 799.4499969482422, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1759958914348", + "component": "httprequest", + "tab": "1612772287426", + "name": "http://192.168.252.2:8015/node_numbers", + "x": 571, + "y": 2111, + "connections": { + "0": [ + { + "index": "0", + "id": "1759958927094" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "stringify": "json", + "method": "POST", + "url": "http://192.168.252.2:8015/node_numbers" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1759958927094", + "component": "debug", + "tab": "1612772287426", + "name": "nodesChangeCloud", + "x": 951.8833312988281, + "y": 2109.2333984375, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1759959003114", + "component": "debug", + "tab": "1612772287426", + "name": "nodeChangeCloud1", + "x": 574, + "y": 2218, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1760020290879", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 84.75, + "y": 1787, + "connections": { + "0": [ + { + "index": "1", + "id": "1718016052341" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + } + ], + "version": 615 +} diff --git a/RVO50/flow/dido_controller.js b/RVO50/flow/dido_controller.js new file mode 100755 index 0000000..d16fb19 --- /dev/null +++ b/RVO50/flow/dido_controller.js @@ -0,0 +1,1486 @@ +exports.id = 'dido_controller'; +exports.title = 'DIDO_Controller'; +exports.version = '2.0.0'; +exports.group = 'Worksys'; +exports.color = '#2134B0'; +exports.input = 3; +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 + +state_of_main_switch - reportovat stav hlaveho istica : 0-> off 1-> on +rotary_switch_state - sem by sa mal reportovat stav vstupov manual a auto pola nasledovnej logiky: Manual = 1 a Auto = 0 -> Manu +Manual = 0 a Auto = 0 -> Off, Manual = 0 a Auto = 1 -> Automatic + +door_condition - pin 6, dverový kontakt -> 1 -> vyreportuje Closed, 0 -> vyreportuje Ope +twilight_sensor - hodnotu, ktoru vracia ten analogovy vstup (17) treba poslat sem ako float number. Zrejme tu potom pridame nejaky koeficient prevodu na luxy + +Na kazdu liniu +state_of_breaker - podla indexu istica sa reportuje jeho stav, teda istic na liniu 1: 0-> off, 1-> on +state_of_contactor - podla indexu stkaca sa reportuje jeho stav, teda stykac 1 na liniu 1: 0-> off, 1-> on +*/ + +const { errLogger, logger, monitor } = require('./helper/logger'); +const SerialPort = require('serialport'); +const WebSocket = require('ws'); +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 errorHandler = require('./helper/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 hasMainSwitch; + +let alarmStatus = "OFF"; + +const SEND_TO = { + debug: 0, + tb: 1, + cmd_manager: 2 +} + + +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 = {}; + let rsPortReceivedData = []; + + //to be able to get proper twilight values + let twilight_sensor_interval = 5;//minutes + let twilight_sensor = []; + const twilight_sensor_array = []; + let twilightError = false; + + monitor.info("DIDO_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-we make it global to see it from outside + FLOW.deviceStatus = { //key is device name: temperature,.... + "state_of_main_switch": "Off", //Hlavny istic (alebo druhy dverovy kontakt) + "rotary_switch_state": "Off", //Prevadzkovy + "door_condition": "closed", //Dverový kontakt + "em": "OK", //elektromer rvo + "temperature": "OK", //templomer + "battery": "OK", //Bateria + "power_supply": "OK", //Zdroj + "master_node": "OK", //MN - GLOBALS.settings.masterNodeIsResponding + "no_voltage": "OK", //GLOBALS.settings.no_voltage - vypadok napatia na faze + "state_of_breaker": {}, //"Off",//Istic + "state_of_contactor": {}, //"Off",//Stykac + "twilight_sensor": "OK" //lux sensor + }; + let deviceStatus = FLOW.deviceStatus; + + + function main() { + + GLOBALS = FLOW.GLOBALS; + SETTINGS = FLOW.GLOBALS.settings; + rvoTbName = SETTINGS.rvoTbName; + pinsData = GLOBALS.pinsData; + relaysData = GLOBALS.relaysData; + + tbHandler = new DataToTbHandler(SEND_TO.tb); + tbHandler.setSender(exports.title); + + controller_type = SETTINGS.controller_type; //"lm" or "unipi" + hasMainSwitch = SETTINGS.has_main_switch; + + if (controller_type == "") controller_type = "lm"; + + 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, "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; + } + } + + //report RVO version relaysData[0].tbname; + let values = {}; + values["edge_fw_version"] = SETTINGS.edge_fw_version; + values["maintenance_mode"] = SETTINGS.maintenance_mode; + + sendTelemetry(values, rvoTbName); + + 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); + } + + + function handleRsPort() { + + if (rsPort) { + rsPort.removeAllListeners(); + rsPort = null; + } + + //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('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) { + if (!err) { + monitor.info(exports.title + "--->Digital in_out has been set (runSyncExec was sucessfull)"); + + turnAlarm("off"); + 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('error', err => { + let message = "Dido: rsPort error: " + err.message; + logger.debug(message); + monitor.info(message); + errorHandler.sendMessageToService(message); + }) + + rsPort.on("close", () => { + let message = "Dido: rsPort closed - reconnecting ..."; + logger.debug(message); + monitor.info(message); + setTimeout(handleRsPort, 1000); + }) + + rsPort.open(); + } + + + function handleWebSocket() { + + if (ws) { + ws.removeAllListeners(); + ws = null; + } + + //to keep websocket opened, we send request every 150 seconds + let startRequests = null; + + console.log("handleWebSocket function called"); + ws = new WebSocket('ws:/0.0.0.0:1234/ws'); + + ws.onopen = function open() { + + instance.send(0, exports.title + " running"); + turnAlarm("off"); + + initialSetting(); + + setTimeout(function() { ws.send(JSON.stringify({ cmd: "all" })) }, 5000); + // we request dev info about neuron device from evok to keep websocket connection alive + // for some reason this request returns no data, but connection keeps alive + startRequests = setInterval(() => { + ws.send(JSON.stringify({ "cmd": "filter", "dev": ["neuron"] })); + }, 150000) + }; + + + // 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 = async 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; + + 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 => { + logger.debug('Dido: websocket error', err); + }) + + ws.onclose = function() { + logger.debug('Dido: websocket onclose, reconnecting...') + clearInterval(startRequests); + setTimeout(handleWebSocket, 1000); + } + } + + 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 turnAlarm(onOrOff) { + let value = 0; + if (onOrOff == "on") value = 1; + + if (value == 1 && SETTINGS.maintenance_mode) return; + + alarmStatus = "OFF"; + if (value == 1) alarmStatus = "ON"; + + if (rsPort) { + let arr = [0x55]; + arr.push(13); + arr.push(0); + arr.push(value); + + rsPort.write(Buffer.from(arr), function(err) { + logger.debug(`sirena - ${onOrOff}`); + }); + } + else if (ws) { + let cmd = { "cmd": "set", "dev": "relay", "circuit": "1_01", "value": value }; + ws.send(JSON.stringify(cmd)); + logger.debug(`sirena - ${onOrOff}`); + } + } + + + 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") { + bits.push(0); + } + else bits.push(1); + + if (deviceStatus["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); + } + + + // turn line on or off + function turnLine(onOrOff, line, pin, force, info) { + //onOrOff => "on" or "off" + let value = 0; + if (onOrOff == "on") value = 1; + + if (force == undefined) force = false; + + if (line == 0) { + if (value == 1 && alarmStatus == "ON") turnAlarm("off"); + SETTINGS.maintenance_mode = value ? true : false; + + 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); + return; + } + + if (pin === undefined) pin = getPin(line); + + if (pin === undefined) { + errLogger.error("pin is undefined!", line); + return; + } + + if (!force) { + if (relaysData[line].contactor == value) { + instance.send(SEND_TO.debug, `line is already ${onOrOff} ` + line); + logger.debug(`Dido: turnLine: line is already ${onOrOff} `, line); + return; + } + } + + // if(!rsPort.isOpen && !ws) + if (!rsPort && !ws) { + errLogger.error("Dido - port or websocket is not opened"); + return; + } + + if (rsPort) { + let arr = [0x55]; + arr.push(pin); + arr.push(0); + arr.push(value); + + rsPort.write(Buffer.from(arr), function(err) { + if (err === undefined) { + monitor.info(`Dido: turnLine ${onOrOff} zapisal do rsPort-u`, line, pin, arr, info); + switchLogic(arr); + } + else { + monitor.info(`Dido: turnLine ${onOrOff} WRITE error`, err); + } + }); + + } + else if (ws) { + //pin = "relay1_03" or "input1_01" ... we must make just "1_01" with slice method + monitor.info(`Dido: turnLine ${onOrOff} - (line, pin, force)`, line, pin, force, info); + let cmd = { "cmd": "set", "dev": "relay", "circuit": pin.slice(5), "value": value }; + ws.send(JSON.stringify(cmd)); + } + + //if rvo is 24/7, it has just one switching profile point at 13:00. we do not want to send notification as it repeats every day. + //const d = new Date(); + //if(d.getHours() != 13) sendNotification("Dido_controller: ", SETTINGS.rvoTbName, "switching_profile_point_applied_to_line", { line: line, value: onOrOff }, "", SEND_TO.tb, instance); + } + + + // 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; + + // 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) { + const status = flowdata.data.status; + if (status == "NOK-twilight_sensor") { + deviceStatus["twilight_sensor"] = "NOK"; + } + else if (status == "NOK-em340" || status == "NOK-em111") { + deviceStatus["em"] = "NOK"; + } + else if (status == "NOK-thermometer") { + deviceStatus["temperature"] = "NOK"; + } + } + else if ("values" in flowdata.data) { + 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" + } + else if (values.hasOwnProperty("temperature")) { + deviceStatus["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"; + } + + sendTelemetry(values, rvoTbName); + } + + sendRvoStatus(); + }) + + + + + // we expect array as flowdata.data + instance.on("1", flowdata => { + + //console.log(flowdata.data); + + if (!flowdata.data instanceof Object) return; + + let obj = flowdata.data; + let line = obj.line; + 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"); + }) + + + function calculateStateCode() { + + let bits = []; + + //Hlavny istic - state_of_main_switch => v rvo senica je to druhy door pre silovu cast (EM) + if (deviceStatus["state_of_main_switch"] === "closed" || deviceStatus["state_of_main_switch"] === "Off") { + bits.push(0); + } + else { + bits.push(1); + } + + //Prevadzkovy mod - Manual, Off, Automatic, maintenance_mode = true/false // DAVA 2 BITY + if (!SETTINGS.maintenance_mode) { + if (deviceStatus["rotary_switch_state"] === "Manual") { + bits.push(0); + bits.push(1); + } + + if (deviceStatus["rotary_switch_state"] === "Automatic") { + bits.push(0); + bits.push(0); + } + + if (deviceStatus["rotary_switch_state"] === "Off") { + bits.push(1); + bits.push(0); + } + } + else { + bits.push(1); + bits.push(1); + } + + //Dverovy kontakt + if (deviceStatus["door_condition"] === "closed") { + bits.push(0); + } + else { + bits.push(1); + } + + //EM + if (deviceStatus["em"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //Teplomer + if (deviceStatus["temperature"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //Batéria + if (deviceStatus["battery"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //Zdroj + if (deviceStatus["power_supply"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //MN + if (deviceStatus["master_node"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //výpadok napätia na fáze + if (deviceStatus["no_voltage"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + if (deviceStatus["twilight_sensor"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + // doplnime do 16 bitov (2 byty) + for (let i = bits.length; i < 16; i++) { + bits.push(0); + } + + // console.log("calculateStateCode - deviceStatus", deviceStatus); + // 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; + } + + + async function sendRvoStatus() { + + if (SETTINGS === undefined) return; + SETTINGS.masterNodeIsResponding ? deviceStatus["master_node"] = "OK" : deviceStatus["master_node"] = "NOK"; + + 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 pinsForRvoStatus(controllerType, hasMainSwitch) { + + let pins = []; + + if (controllerType === "lm") { + pins = [1, 4, 6]; + if (hasMainSwitch === 1) { + pins = [4, 6]; + } + } else if (controllerType === "unipi") { + pins = ["input1_01", "input1_04", "input1_05"]; + if (hasMainSwitch === 1) { + pins = ["input1_01", "input1_04"]; + } + } + + return pins; + } + + + function checkRvoStatus() { + + // 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 + //set RVO state + let status = "OK"; + + for (const [key, value] of Object.entries(deviceStatus)) { + if (["em", "twilight_sensor", "temperature", "master_node"].includes(key) && value === "NOK") status = "NOK"; + } + + if (status === "OK") { + + let pinIndexes = pinsForRvoStatus(controller_type, hasMainSwitch); + + for (const pinIndex of pinIndexes) { + if (previousValues[pinIndex] === 0) { + if ((pinIndex === 6 || pinIndex === 'input1_01' || pinIndex === 'input1_05') && SETTINGS.maintenance_mode) continue; + status = "NOK"; + break; + } + } + } + + // battery status. If value is 1 - battery is NOK + if (previousValues[5] === 1) status = "NOK"; + if (SETTINGS.no_voltage.size > 0) status = "NOK"; + + // console.log("rvo status",status) + return status; + } + + + // we pass array to function in case of rsPort ==> switchLogic([55,3,0,1]) ==> [[55,3,0,1]] + // we pass two values in case of websocket ==> switchLogic("relay1_03",1) ==> ["relay1_03",1] + const switchLogic = (...args) => { + + let values = {}; + let pinIndex, newPinValue, twilight; + + //data from rsPort + if (args.length == 1) { + pinIndex = args[0][1] + 1; + if (pinIndex === 17) pinIndex--; + newPinValue = args[0][3]; + twilight = args[0][2]; + } + //data from websocket + else { + pinIndex = args[0]; + newPinValue = args[1]; + } + + 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; + + //default value + let value = "On"; + if (newPinValue === 0) value = "Off"; + + //Hlavny istic + if (type === "state_of_main_switch" && hasMainSwitch) { + if (newPinValue === 0 && newPinValue !== previousValues[pinIndex]) { + sendNotification("switchLogic", rvoTbName, "main_switch_has_been_turned_off", {}, "", SEND_TO.tb, instance, "state_of_main_switch"); + 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"); + deviceStatus["state_of_main_switch"] = "On"; + } + } + + //Prevadzkovy mod + 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"; + + deviceStatus["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, "power_supply_has_disconnected_input", {}, "", SEND_TO.tb, instance, "power_supply"); + + deviceStatus["power_supply"] = "NOK"; + } + else if (newPinValue === 1 && newPinValue !== previousValues[pinIndex]) { + sendNotification("switchLogic", rvoTbName, "power_supply_works_correctly", {}, "", SEND_TO.tb, instance, "power_supply"); + + deviceStatus["power_supply"] = "OK"; + } + } + + //Bateria - 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"); + + deviceStatus["battery"] = "NOK"; + } + else if (newPinValue === 0 && newPinValue !== previousValues[pinIndex]) { + sendNotification("switchLogic", rvoTbName, "battery_level_is_ok", {}, "", SEND_TO.tb, instance, "battery_level"); + + deviceStatus["battery"] = "OK"; + } + } + + //Dverovy kontakt - pin 6 + //! Ak je rvo s dvoma dverovymi kontaktami, ked pride z evoku signal z input1_05, co bol predytm "state_of_main switch" handlujeme ho teraz ako 'door_condition' + else if (type == "door_condition" || type === "state_of_main_switch") { + newPinValue === 0 ? value = "open" : value = "closed"; + + let door = "door_main"; + if (type === "state_of_main_switch") door = "door_em"; + + if (value === "open") { + if (SETTINGS.maintenance_mode) { + sendNotification("switchLogic", rvoTbName, door + "_open", {}, "", SEND_TO.tb, instance, door); + } else { + sendNotification("switchLogic", rvoTbName, door + "_open_without_permission", {}, "", SEND_TO.tb, instance, door); + + // 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 (value === "closed") { + if (alarmStatus == "ON") turnAlarm("off"); + sendNotification("switchLogic", rvoTbName, door + "_close", {}, "", SEND_TO.tb, instance, door); + } + + deviceStatus[type] = value; + } + + //lux sensor + else if (type == "twilight_sensor") { + //! TODO - to show nok status, if lux value is not changing more then 10 times. + //Daylight is far more than 1000. So most of the day, when it is sunshine comes just value 1000. But lux sensor is not NOK. + //This is not the case in LM. If value from LM is the same 10x, there is 99% possibility, that sensor is NOK. + value = newPinValue; + + if (controller_type === 'lm') { + value = parseFloat(newPinValue + (256 * twilight)); + + 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 && !twilightError) { + twilightError = true; + let value = twilight_sensor_array.shift(); + + newPinValue = 0; + } + else if (set.size !== 1 && twilightError) { + //sendNotification("switchLogic", rvoTbName, 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) { + 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); + } + } + + 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); + } + + deviceStatus["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 (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 }); + + //mame iba 3 istice. vyreportujeme a ohandlujeme liniu na tom istom istici ako paralelna linia (napr linia 1, paralelna s nou je linia 4, key je string "4") + // ak je 7 linii, na 1 istici je linia 1,4,7 + + if (line == 1) { + + const lineOnSameBraker = [4, 7]; + + for (var i = 0; i < lineOnSameBraker.length; i++) { + if (!relaysData.hasOwnProperty(lineOnSameBraker[i])) continue; + + 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; + reportLineStatus(lineOnSameBraker[i]); + + values[type] = value; + const tbname = relaysData[lineOnSameBraker[i]].tbname; + sendTelemetry(values, tbname); + + delete values[type]; + } + + } + else { + const lineOnSameBraker = line + 3 + ""; + + if (relaysData.hasOwnProperty(lineOnSameBraker)) { + 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; + reportLineStatus(line + 3); + + values[type] = value; + const tbname = relaysData[lineOnSameBraker].tbname; + sendTelemetry(values, tbname); + + delete values[type]; + } + } + + } + + if (value == "Off") values["status"] = "NOK"; + deviceStatus["state_of_breaker"][line] = value; + + reportLineStatus(line); + } + else return; + + values[type] = value; + + if (type == "rotary_switch_state") { + if (SETTINGS.maintenance_mode) value = "maintenance"; + value = value.toLowerCase(); + values["power_mode"] = value; + } + + if (newPinValue != previousValues[pinIndex]) previousValues[pinIndex] = newPinValue; + if (Object.keys(values).length > 0 && tbname) sendTelemetry(values, tbname); + } + + + function sendTelemetry(values, tbname, date = Date.now()) { + let dataToTb = { + [tbname]: [ + { + "ts": date, + "values": values + } + ] + }; + + tbHandler.sendToTb(dataToTb, instance); + } + + + function isObject(item) { + return (typeof item === "object" && !Array.isArray(item) && item !== null); + } + +} //end of 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 +// *|input1_01|state_of_main_switch|0|........... +// *|input1_02|rotary_switch_state|0|........... +// *|input1_03|rotary_switch_state|0|........... +// *|intut1_04|power_supply|0|........... +// *|input1_05|door_condition|0|........... +// *|input1_06|state_of_breaker|1|........... +// *|input1_07|state_of_breaker|2|........... +// *|input1_08|state_of_breaker|3|........... +// *|relay1_02|state_of_contactor|1|........... +// *|relay1_03|state_of_contactor|2|........... +// *|relay1_04|state_of_contactor|3|........... +// *|287D8776E0013CE9|temperature|0|........... + + +//! pins_data --> from UNIPI +// { +// 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 } +// } + +//! relays_data +// { +// '0': { +// line: 0, +// tbname: 'KjbN4q7JPZmexgdnz2yKQ98YAWwO0Q3BMX6ERLoV', +// contactor: 1, +// profile: '' +// }, +// '1': { +// line: 1, +// tbname: 'RMgnK93rkoAazbqdQ4yBG95Z1YXGx6pmwBeVEP2O', +// contactor: 0, +// profile: '{"intervals":[{"value":0,"end_time":"20:00","start_time":"13:00"},{"value":1,"end_time":"10:00","start_time":"20:00"},{"value":0,"end_time":"10:20","start_time":"10:00"},{"value":1,"end_time":"10:40","start_time":"10:20"},{"value":0,"end_time":"11:00","start_time":"10:40"},{"value":1,"end_time":"11:30","start_time":"11:00"},{"value":0,"end_time":"11:50","start_time":"11:30"},{"value":1,"end_time":"13:00","start_time":"11:50"}],"astro_clock":false,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' +// }, +// '2': { +// line: 2, +// tbname: 'dlE1VQjYrNx9gZRmb38gG08oLBO4qaAk2M6JPnG7', +// contactor: 0, +// profile: '{"intervals":[{"value":0,"end_time":"20:00","start_time":"13:00"},{"value":1,"end_time":"10:00","start_time":"20:00"},{"value":0,"end_time":"10:20","start_time":"10:00"},{"value":1,"end_time":"10:40","start_time":"10:20"},{"value":0,"end_time":"11:00","start_time":"10:40"},{"value":1,"end_time":"11:30","start_time":"11:00"},{"value":0,"end_time":"11:50","start_time":"11:30"},{"value":1,"end_time":"13:00","start_time":"11:50"}],"astro_clock":false,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' +// }, +// '3': { +// line: 3, +// tbname: 'vnmG4kJxaXWNBgMQq0D7Aj5e9oZzOAlr6LdR3w2V', +// contactor: 0, +// profile: '{"intervals":[{"value":0,"end_time":"20:30","start_time":"13:00"},{"value":1,"end_time":"00:10","start_time":"20:30"},{"value":0,"end_time":"13:00","start_time":"05:40"},{"value":1,"end_time":"05:40","start_time":"00:10"}],"astro_clock":true,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' +// } +// } + + + + + +// { +// "jbN4q7JPZmexgdnz2yKbWGDYAWwO0Q3BMX6ERLoV": [ +// { +// "ts": 1700409326353, +// "values": { +// "_event": { +// "type": "notice", +// "status": "new", +// "source": { +// "func": "rsPort.open()", +// "component": "1700343402190", +// "component_name": "DIDO_Controller", +// "edge": "jbN4q7JPZmexgdnz2yKbWGDYAWwO0Q3BMX6ERLoV" +// }, +// "message": "al_shariff_10.0.0.38: FLOW has been started ", +// "message_data": "" +// } +// } +// } +// ] +// } diff --git a/RVO50/flow/helper/DataToTbHandler.js b/RVO50/flow/helper/DataToTbHandler.js new file mode 100755 index 0000000..716ef7b --- /dev/null +++ b/RVO50/flow/helper/DataToTbHandler.js @@ -0,0 +1,187 @@ +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; + this.itIsNodeReadout = false; + this.sender = ""; + + // if attribute change difference is less than limit value, we do not send to tb. + this.attributeChangeLimit = { + temperature: 0.5, + Phase_1_voltage: 2, + Phase_2_voltage: 2, + Phase_3_voltage: 2, + Phase_1_current: 0.1, + Phase_2_current: 0.1, + Phase_3_current: 0.1, + Phase_1_power: 2, + Phase_2_power: 2, + Phase_3_power: 2, + total_power: 2, + total_energy: 1, + Phase_1_pow_factor: 0.1, + Phase_2_pow_factor: 0.1, + Phase_3_pow_factor: 0.1, + power_factor: 0.1, + lifetime: 2, + voltage: 2, + power: 2, + frequency: 3, + energy: 0.1, + current: 2, + inclination_x: 10, + inclination_y: 10, + inclination_z: 10 + }; + + } + + dump() { + console.log("----------------------------"); + console.log("previousValues", this.previousValues); + console.log("----------------------------"); + } + + setSender(sender) { + this.sender = sender; + } + + isEmptyObject(obj) { + for (var _ in obj) { + return false; + } + return true; + } + + + sendToTb(data, instance) { + + //not to modify data object, we do deep copy: + let dataCopy = JSON.parse(JSON.stringify(data)); + + let keys = Object.keys(dataCopy); + + if (keys.length == 0) { + if (this.debug) console.log("sendToTb received empty object", dataCopy); + return; + } + + let tbname = keys[0]; + let ts; + + let arrayOfValues = dataCopy[tbname]; + let arrayOfValuesToSend = []; + + for (let i = 0; i < arrayOfValues.length; i++) { + + ts = arrayOfValues[i].ts; + let values = this.prepareValuesForTb(tbname, ts, arrayOfValues[i].values); + + if (!this.isEmptyObject(values)) { + arrayOfValuesToSend.push({ ts: ts, values: values }); + } + + } + + if (arrayOfValuesToSend.length == 0) { + //if(this.debug) console.log("data not sent - empty array"); + return; + } + + this.messageCounter++; + + let dataToTbModified = { + [tbname]: arrayOfValuesToSend + } + + //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); + instance.send(this.index, dataToTbModified); + } + + + getDiffTimestamp(key) { + //TODO set different value for given key!!! + //if(key == "status") this.timeToHoldTbValue = 2*60*60;//2h + return this.timeToHoldTbValue * 1000; + } + + + prepareValuesForTb(tbname, timestamp, values) { + + let keys = Object.keys(values); + + if (keys.includes("lifetime")) this.itIsNodeReadout = true; + + if (!this.previousValues.hasOwnProperty(tbname)) { + this.previousValues[tbname] = {}; + } + + //if(this.debug) console.log("prepareValuesForTb", tbname, timestamp, values); + + for (let i = 0; i < keys.length; i++) { + + let key = keys[i]; + let value = values[key]; + + if (!this.previousValues[tbname].hasOwnProperty(key)) { + this.previousValues[tbname][key] = { ts: timestamp, value: value }; + continue; + } + + // attributeData ==> {voltage: {ts:333333, value:5}} + let attributeData = this.previousValues[tbname][key]; + let attributeToChange = false; + if (key in this.attributeChangeLimit) attributeToChange = true; + let limit = this.attributeChangeLimit[key]; + let timestampDiffToRemoveKey; + + //this will ensure "node statecode" will be sent just once an hour + if (this.itIsNodeReadout && key === "statecode") { + attributeData.value = value; + this.itIsNodeReadout = false; + timestampDiffToRemoveKey = 1 * 60 * 60 * 1000; // 1 hour + } + + if (key === "twilight_sensor" && value > 100) { + attributeData.value = value; + } + + //if edge, master or node version do not change, send just once a day: + if (["edge_fw_version", "master_node_version", "fw_version"].includes(key)) { + timestampDiffToRemoveKey = 24 * 60 * 60 * 1000; + } + + if (attributeData.value === value || attributeToChange && Math.abs(attributeData.value - value) < limit) { + + let diff = timestamp - attributeData.ts; + if (!timestampDiffToRemoveKey) timestampDiffToRemoveKey = this.getDiffTimestamp(key); + + if (diff > timestampDiffToRemoveKey) { + attributeData.ts = Date.now(); + //if(this.debug) console.log(this.sender + ": update ts for key", key, "diff is", diff, "messageCounter", this.messageCounter); + } + else { + delete values[key]; + //if(this.debug) console.log(this.sender + ": delete key", key, "diff is", diff, "messageCounter", this.messageCounter, timestampDiffToRemoveKey); + } + } + else { + attributeData.value = value; + attributeData.ts = timestamp; + } + + } + + return values; + } +} + +module.exports = DataToTbHandler; + diff --git a/RVO50/flow/helper/ErrorToServiceHandler.js b/RVO50/flow/helper/ErrorToServiceHandler.js new file mode 100755 index 0000000..2b27c32 --- /dev/null +++ b/RVO50/flow/helper/ErrorToServiceHandler.js @@ -0,0 +1,91 @@ +const { MD5 } = require('./md5.js'); +const { networkInterfaces } = require('os'); + +class ErrorToServiceHandler { + constructor() { + this.previousValues = {}; + + this.project_id = undefined; + + const nets = networkInterfaces(); + this.ipAddresses = {}; + + for (const name of Object.keys(nets)) { + for (const net of nets[name]) { + // Skip over non-IPv4 and internal (i.e. 127.0.0.1) addresses + if (net.family === 'IPv4' && !net.internal) { + if (!this.ipAddresses[name]) { + this.ipAddresses[name] = []; + } + this.ipAddresses[name].push(net.address); + } + } + } + } + + setProjectId(project_id) { + this.project_id = project_id; + } + + processMessage(message, seconds) { + if (Array.isArray(message)) message = message.join(', '); + + let key = MD5(message); + let ts = Date.now(); + + //keep in memory - default value is 1h + if (seconds === undefined) seconds = 60 * 60; + + if (!this.previousValues.hasOwnProperty(key)) { + this.previousValues[key] = { ts: ts, duration: seconds }; + } + + let diff = (ts - this.previousValues[key].ts); + if (diff < this.previousValues[key].duration * 1000) return false; + + this.previousValues[key].ts = ts; + + return message; + } + + sendMessageToService(message, seconds, message_type) { + + // if error occures too early FLOW.GLOBALS.settings.project_id is still undefined + if (this.project_id === undefined) { + console.log("ErrorToServiceHandler.js: no project_id"); + return; + } + + let f = this.processMessage(message, seconds); + if (f === false) return; + + if (message_type === undefined) message_type = "error_message"; + + let toService = { + id: this.project_id, + ipAddresses: this.ipAddresses + }; + + //js_error || error_message + toService[message_type] = message; + + console.log("ErrorToServiceHandler------------------------>send to service", toService); + + RESTBuilder.make(function(builder) { + builder.method('POST'); + builder.post(toService); + builder.url('http://192.168.252.2:8004/sentmessage'); + + builder.callback(function(err, response, output) { + console.log("process.on error send", err, response, output, toService); + }); + }); + + } +} + +const errorHandler = new ErrorToServiceHandler(); + + +module.exports = errorHandler; +//module.exports = ErrorToServiceHandler; diff --git a/RVO50/flow/helper/db_helper.js b/RVO50/flow/helper/db_helper.js new file mode 100755 index 0000000..40e796c --- /dev/null +++ b/RVO50/flow/helper/db_helper.js @@ -0,0 +1,44 @@ +function promisifyBuilder(builder) +{ + return new Promise((resolve, reject) => { + + try{ + + builder.callback(function(err, response) { + + if(err != null) reject(err); + resolve(response); + }); + + } catch (error) { + reject(error); + } + }) +} + +function makeMapFromDbResult(response, ...keys) +{ + let s = "-"; + let data = {}; + + for(let i = 0; i < response.length; i++) + { + let record = response[i]; + + let k = []; + for(let j = 0; j < keys.length; j++) + { + k.push( record[keys[j]] ); + } + + let key = k.join(s); + data[ key ] = record; + } + + return data; +} + +module.exports = { + promisifyBuilder, + makeMapFromDbResult + } \ No newline at end of file diff --git a/RVO50/flow/helper/logger.js b/RVO50/flow/helper/logger.js new file mode 100755 index 0000000..2585639 --- /dev/null +++ b/RVO50/flow/helper/logger.js @@ -0,0 +1,30 @@ +//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/RVO50/flow/helper/md5.js b/RVO50/flow/helper/md5.js new file mode 100755 index 0000000..d3b0480 --- /dev/null +++ b/RVO50/flow/helper/md5.js @@ -0,0 +1,5 @@ +function MD5(d){var r = M(V(Y(X(d),8*d.length)));return r.toLowerCase()};function M(d){for(var _,m="0123456789ABCDEF",f="",r=0;r>>4&15)+m.charAt(15&_);return f}function X(d){for(var _=Array(d.length>>2),m=0;m<_.length;m++)_[m]=0;for(m=0;m<8*d.length;m+=8)_[m>>5]|=(255&d.charCodeAt(m/8))<>5]>>>m%32&255);return _}function Y(d,_){d[_>>5]|=128<<_%32,d[14+(_+64>>>9<<4)]=_;for(var m=1732584193,f=-271733879,r=-1732584194,i=271733878,n=0;n>16)+(_>>16)+(m>>16)<<16|65535&m}function bit_rol(d,_){return d<<_|d>>>32-_} + +module.exports = { + MD5 +} \ No newline at end of file diff --git a/RVO50/flow/helper/notification_reporter.js b/RVO50/flow/helper/notification_reporter.js new file mode 100755 index 0000000..839c12c --- /dev/null +++ b/RVO50/flow/helper/notification_reporter.js @@ -0,0 +1,121 @@ +//key is device, value = message {} +let sentValues = {}; +let notificationsData = null; +let rvoName; + +//sendNotification("CMD Manager: process cmd", SETTINGS.rvoTbName, "dimming_profile_was_successfully_received_by_node", { node: node }, "", SEND_TO.tb, instance); + +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 +}; + +function getKey(map, val) { + return Object.keys(map).findItem(key => map[key] === val); +} + +//https://stackoverflow.com/questions/41117799/string-interpolation-on-variable +var template = (tpl, args) => tpl.replace(/\${(\w+)}/g, (_, v) => args[v]); + + +function initNotification() { + notificationsData = FLOW.GLOBALS.notificationsData; + rvoName = FLOW.GLOBALS.settings.rvo_name; +} + + +function sendNotification(func, device, key, params, extra, tb_output, instance, saveKey) { + + let storeToSendValues = true; + if (saveKey == undefined) storeToSendValues = false; + + let weight = ""; + let message = {}; + + let notification = notificationsData[key]; + + if (notification) { + weight = notification.weight.toLowerCase(); + + Object.keys(notification).forEach(item => { + if (["en", "sk", "de", "cz", "it", "es"].includes(item)) { + message[item] = rvoName + ": " + template(notification[item], params); + } + }) + } + else { + //console.error("sendNotification: Notifications: undefined key", key, func, notificationsData); + console.error("sendNotification: Notifications: undefined key", key, func); + return false; + } + + //detect invalid err weight + if (getKey(ERRWEIGHT, weight) == undefined) { + console.error("sendNotification: Notifications: undefined weight", weight, key, func); + return false; + } + + if (sentValues.hasOwnProperty(saveKey)) { + if (JSON.stringify(sentValues[saveKey]) == JSON.stringify(message)) { + return false; + } + } + + if (sentValues[saveKey] == undefined) { + if (storeToSendValues) { + //do not send - flow is was started + sentValues[saveKey] = message; + return false; + } + } + + if (storeToSendValues) sentValues[saveKey] = message; + + let content = { + "type": weight, + "status": "new", + "source": { + "func": func, + "component": instance.id, + "component_name": instance.name, + "edge": device + }, + "message": message, + "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 + + return true; + +} + +module.exports = { + sendNotification, + ERRWEIGHT, + initNotification +} + diff --git a/RVO50/flow/helper/register.js b/RVO50/flow/helper/register.js new file mode 100755 index 0000000..fc1d008 --- /dev/null +++ b/RVO50/flow/helper/register.js @@ -0,0 +1,144 @@ +/* +0 - cislo registra / prikaz +1 - recepient - 0 = master, 1 = slave (slave je automaticky group a broadcast) +2 - r/rw - read/write +3- register name - nazov registra / prikazu (len pre info - zobrazenie v aplikacii) + +4,5,6,7, - jednotlive byte-y - nazov byte-u +4-7 - RES. a prazdny string "" sa nezobrazia!!! +*/ + +//124 zaznamov +const registers = [ + ["0","1","R","Status","","",""], + ["1","1","RW","Dimming","R-Channel ","G-Channel","B-Channel ","W - Channel"], + ["2","1","R","Device types","","",".",""], + ["3","1","RW","Group addresses 1-4","Groups Add. 4","Groups Add. 3","Groups Add. 2","Groups Add. 1"], + ["4","1","RW","Group addresses 5-8","Groups Add. 8","Groups Add. 7","Groups Add. 6","Groups Add. 5"], + ["5","1","RW","Serial number (MAC)","","","",""], + ["6","1","RW","Time of dusk","HH","MM","SS","EXTRA"], + ["7","1","RW","Time of dawn","HH","MM","SS","EXTRA"], + ["8","1","RW","Time Schedule settings","TBD","TBD","Movement sensor","Time Schedule"], + ["9","1","RW","TS1 Time point 1","HH","MM","SS","Ext. Device"], + ["10","1","RW","TS1 Time point 1 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["11","1","RW","TS1 Time point 2","HH","MM","SS","Ext. Device"], + ["12","1","RW","TS1 Time point 2 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["13","1","RW","TS1 Time point 3","HH","MM","SS","Ext. Device"], + ["14","1","RW","TS1 Time point 3 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["15","1","RW","TS1 Time point 4","HH","MM","SS","Ext. Device"], + ["16","1","RW","TS1 Time point 4 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["17","1","RW","TS1 Time point 5","HH","MM","SS","Ext. Device"], + ["18","1","RW","TS1 Time point 5 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["19","1","RW","TS1 Time point 6","HH","MM","SS","Ext. Device"], + ["20","1","RW","TS1 Time point 6 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["21","1","RW","TS1 Time point 7","HH","MM","SS","Ext. Device"], + ["22","1","RW","TS1 Time point 7 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["23","1","RW","TS1 Time point 8","HH","MM","SS","Ext. Device"], + ["24","1","RW","TS1 Time point 8 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["25","1","RW","TS1 Time point 9","HH","MM","SS","Ext. Device"], + ["26","1","RW","TS1 Time point 9 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["27","1","RW","TS1 Time point 10","HH","MM","SS","Ext. Device"], + ["28","1","RW","TS1 Time point 10 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["29","1","RW","TS1 Time point 11","HH","MM","SS","Ext. Device"], + ["30","1","RW","TS1 Time point 11 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["31","1","RW","TS1 Time point 12","HH","MM","SS","Ext. Device"], + ["32","1","RW","TS1 Time point 12 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["33","1","RW","TS1 Time point 13","HH","MM","SS","Ext. Device"], + ["34","1","RW","TS1 Time point 13 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["35","1","RW","TS1 Time point 14","HH","MM","SS","Ext. Device"], + ["36","1","RW","TS1 Time point 14 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["37","1","RW","TS1 Time point 15","HH","MM","SS","Ext. Device"], + ["38","1","RW","TS1 Time point 15 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["39","1","RW","TS1 Time point 16","HH","MM","SS","Ext. Device"], + ["40","1","RW","TS1 Time point 16 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["41","1","RW","TS2 Time point 1","HH","MM","SS","Ext. Device"], + ["42","1","RW","TS2 Time point 1 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["43","1","RW","TS2 Time point 2","HH","MM","SS","Ext. Device"], + ["44","1","RW","TS2 Time point 2 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["45","1","RW","TS2 Time point 3","HH","MM","SS","Ext. Device"], + ["46","1","RW","TS2 Time point 3 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["47","1","RW","TS2 Time point 4","HH","MM","SS","Ext. Device"], + ["48","1","RW","TS2 Time point 4 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["49","1","RW","TS2 Time point 5","HH","MM","SS","Ext. Device"], + ["50","1","RW","TS2 Time point 5 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["51","1","RW","TS2 Time point 6","HH","MM","SS","Ext. Device"], + ["52","1","RW","TS2 Time point 6 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["53","1","RW","TS2 Time point 7","HH","MM","SS","Ext. Device"], + ["54","1","RW","TS2 Time point 7 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["55","1","RW","TS2 Time point 8","HH","MM","SS","Ext. Device"], + ["56","1","RW","TS2 Time point 8 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["57","1","RW","TS2 Time point 9","HH","MM","SS","Ext. Device"], + ["58","1","RW","TS2 Time point 9 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["59","1","RW","TS2 Time point 10","HH","MM","SS","Ext. Device"], + ["60","1","RW","TS2 Time point 10 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["61","1","RW","TS2 Time point 11","HH","MM","SS","Ext. Device"], + ["62","1","RW","TS2 Time point 11 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["63","1","RW","TS2 Time point 12","HH","MM","SS","Ext. Device"], + ["64","1","RW","TS2 Time point 12 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["65","1","RW","TS2 Time point 13","HH","MM","SS","Ext. Device"], + ["66","1","RW","TS2 Time point 13 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["67","1","RW","TS2 Time point 14","HH","MM","SS","Ext. Device"], + ["68","1","RW","TS2 Time point 14 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["69","1","RW","TS2 Time point 15","HH","MM","SS","Ext. Device"], + ["70","1","RW","TS2 Time point 15 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["71","1","RW","TS2 Time point 16","HH","MM","SS","Ext. Device"], + ["72","1","RW","TS2 Time point 16 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["73","1","RW","Power meter status","TBD","","",""], + ["74","1","R","Input Voltage","","","",""], + ["75","1","R","Input Current","","","",""], + ["76","1","R","Input Power","","","",""], + ["77","1","R","Cos phi","","","",""], + ["78","1","R","Frequency","","","",""], + ["79","1","RW","Energy","","","",""], + ["80","1","RW","Lifetime","","","",""], + ["81","1","RW","Power on cycles (input)","","","",""], + ["82","1","RW","Power on cycles (relay)","","","",""], + ["83","1","R","Time since last power on","","","",""], + ["84","1","R","Accelerometer data","","","",""], + ["85","1","RW","GPS latitude","pos/neg","deg","min ","sec"], + ["86","1","RW","GPS longitude","pos/neg","deg","min ","sec"], + ["87","1","RW","Actual time","HH","MM","SS","RES."], + ["88","1","RW","Actual date","Day of week","Day","Month","Year"], + ["89","1","R","Production data 1","","","",""], + ["90","1","R","Production data 2","","","",""], + ["91","1","RW","Network ID","NID3","NID2","NID1","NID0"], + ["95","1","RW","Actual Lux level from cabinet","RES.","RES.","HB","LB"], + ["96","1","RW","Threshold lux level","Dusk HB","Dusk LB","Dawn HB","Dawn LB"], + ["97","1","RW","Adjust period","Dusk HB","Dusk LB","Dawn HB","Dawn LB"], + ["98","1","RW","Offset","RES.","RES.","Dusk","Dawn"], + ["99","1","RW","CCT min/max range","max-H","max-L","min-H","min-L"], + ["100","1","RW","DALI interface","Cmd ID","Add","Cmd","Resp"], + ["101","1","RW","Module FW ver","v1","v2","v3","v4"], + ["102","1","RW","Module MAC-H","unused","unused","M1","M2"], + ["103","1","RW","Module MAC-L","M3","M4","M5","M6"], + ["122","1","R","FW update status/control register","Byte3","Byte2","Byte1","Byte0"], + ["123","1","R","FW update - data index","Byte3","Byte2","Byte1","Byte0"], + ["124","1","R","FW update - data","Byte3","Byte2","Byte1","Byte0"], + ["0","0","R","Status","","","",""], + ["1","0","RW","Control register","RES.","RES.","RES.","init mode enable"], + ["2","0","R","Device types","","","",""], + ["3","0","R","Serial number (MAC)","","","",""], + ["4","0","R","Production data 1","","","",""], + ["5","0","R","Production data 2","","","",""], + ["6","0","RW","Network ID","NID3","NID2","NID1","NID0"], + ["7","0","RW","RS232 settings","param.","param.","Baudrate H","Baudrate L"], + ["8","0","R","Accelerometer data","","","",""], + ["9","0","RW","Module FW ver","v1","v2","v3","v4"], + ["10","0","RW","Module MAC-H","unused","unused","M1","M2"], + ["11","0","RW","Module MAC-L","M3","M4","M5","M6"], + ["32","0","RW","FW update status/control register","Byte3","Byte2","Byte1","Byte0"], + ["33","0","RW","FW update - data index","Byte3","Byte2","Byte1","Byte0"], + ["34","0","RW","FW update - data","Byte3","Byte2","Byte1","Byte0"], + ["125","0","RW","Debug Register","Byte3","Byte2","Byte1","Byte0"], + ["126","0","RW","Network Control Register","Byte3","Byte2","Byte1","Byte0"], + ["127","0","R","Network Status Register","Byte3","Byte2","Byte1","Byte0"], + ["128","0","RW","Node XX Serial Number Register","SER3","SER2","SER1","SER0"], + ["256","0","R","Node XX Network Status Register","","","",""] +]; + +let register = {}; + +module.exports = { + registers, + register +} \ No newline at end of file diff --git a/RVO50/flow/helper/serialport_helper.js b/RVO50/flow/helper/serialport_helper.js new file mode 100755 index 0000000..7f5920d --- /dev/null +++ b/RVO50/flow/helper/serialport_helper.js @@ -0,0 +1,99 @@ +const { exec } = require('child_process'); + +function openPort(port) { + return new Promise((resolve, reject) => { + + var callbackError = function(err) { + port.removeListener('error', callbackError); + port.removeListener('open', callbackError); + + reject(err.message); + }; + + var callbackOpen = function(data) { + port.removeListener('error', callbackError); + port.removeListener('open', callbackOpen); + + resolve("port open: ok"); + }; + + port.on('error', callbackError); + port.on('open', callbackOpen); + + port.open(); + + }) +} + +function runSyncExec(command) { + return new Promise((resolve, reject) => { + + exec(command, (error, stdout, stderr) => { + if (error == null) resolve(stdout); + reject(error); + }); + + }) +} + +async function writeData(port, data, readbytes, timeout) { + return new Promise((resolve, reject) => { + + // 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) { + + port.write(Buffer.from(data), function(err) { + if (err) { + reject(err.message); + } + }); + + 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 +} diff --git a/RVO50/flow/helper/suncalc.js b/RVO50/flow/helper/suncalc.js new file mode 100755 index 0000000..c9ca56d --- /dev/null +++ b/RVO50/flow/helper/suncalc.js @@ -0,0 +1,317 @@ +/* + (c) 2011-2015, Vladimir Agafonkin + SunCalc is a JavaScript library for calculating sun/moon position and light phases. + https://github.com/mourner/suncalc +*/ + +(function () { 'use strict'; + +// shortcuts for easier to read formulas + +var PI = Math.PI, + sin = Math.sin, + cos = Math.cos, + tan = Math.tan, + asin = Math.asin, + atan = Math.atan2, + acos = Math.acos, + rad = PI / 180; + +// sun calculations are based on http://aa.quae.nl/en/reken/zonpositie.html formulas + + +// date/time constants and conversions + +var dayMs = 1000 * 60 * 60 * 24, + J1970 = 2440588, + J2000 = 2451545; + +function toJulian(date) { return date.valueOf() / dayMs - 0.5 + J1970; } +function fromJulian(j) { return new Date((j + 0.5 - J1970) * dayMs); } +function toDays(date) { return toJulian(date) - J2000; } + + +// general calculations for position + +var e = rad * 23.4397; // obliquity of the Earth + +function rightAscension(l, b) { return atan(sin(l) * cos(e) - tan(b) * sin(e), cos(l)); } +function declination(l, b) { return asin(sin(b) * cos(e) + cos(b) * sin(e) * sin(l)); } + +function azimuth(H, phi, dec) { return atan(sin(H), cos(H) * sin(phi) - tan(dec) * cos(phi)); } +function altitude(H, phi, dec) { return asin(sin(phi) * sin(dec) + cos(phi) * cos(dec) * cos(H)); } + +function siderealTime(d, lw) { return rad * (280.16 + 360.9856235 * d) - lw; } + +function astroRefraction(h) { + if (h < 0) // the following formula works for positive altitudes only. + h = 0; // if h = -0.08901179 a div/0 would occur. + + // formula 16.4 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + // 1.02 / tan(h + 10.26 / (h + 5.10)) h in degrees, result in arc minutes -> converted to rad: + return 0.0002967 / Math.tan(h + 0.00312536 / (h + 0.08901179)); +} + +// general sun calculations + +function solarMeanAnomaly(d) { return rad * (357.5291 + 0.98560028 * d); } + +function eclipticLongitude(M) { + + var C = rad * (1.9148 * sin(M) + 0.02 * sin(2 * M) + 0.0003 * sin(3 * M)), // equation of center + P = rad * 102.9372; // perihelion of the Earth + + return M + C + P + PI; +} + +function sunCoords(d) { + + var M = solarMeanAnomaly(d), + L = eclipticLongitude(M); + + return { + dec: declination(L, 0), + ra: rightAscension(L, 0) + }; +} + + +var SunCalc = {}; + + +// calculates sun position for a given date and latitude/longitude + +SunCalc.getPosition = function (date, lat, lng) { + + var lw = rad * -lng, + phi = rad * lat, + d = toDays(date), + + c = sunCoords(d), + H = siderealTime(d, lw) - c.ra; + + return { + azimuth: azimuth(H, phi, c.dec), + altitude: altitude(H, phi, c.dec) + }; +}; + + +// sun times configuration (angle, morning name, evening name) + +var times = SunCalc.times = [ + [-0.833, 'sunrise', 'sunset' ], + [ -0.3, 'sunriseEnd', 'sunsetStart' ], + [ -6, 'dawn', 'dusk' ], + [ -12, 'nauticalDawn', 'nauticalDusk'], + [ -18, 'nightEnd', 'night' ], + [ 6, 'goldenHourEnd', 'goldenHour' ] +]; + +// adds a custom time to the times config + +SunCalc.addTime = function (angle, riseName, setName) { + times.push([angle, riseName, setName]); +}; + + +// calculations for sun times + +var J0 = 0.0009; + +function julianCycle(d, lw) { return Math.round(d - J0 - lw / (2 * PI)); } + +function approxTransit(Ht, lw, n) { return J0 + (Ht + lw) / (2 * PI) + n; } +function solarTransitJ(ds, M, L) { return J2000 + ds + 0.0053 * sin(M) - 0.0069 * sin(2 * L); } + +function hourAngle(h, phi, d) { return acos((sin(h) - sin(phi) * sin(d)) / (cos(phi) * cos(d))); } +function observerAngle(height) { return -2.076 * Math.sqrt(height) / 60; } + +// returns set time for the given sun altitude +function getSetJ(h, lw, phi, dec, n, M, L) { + + var w = hourAngle(h, phi, dec), + a = approxTransit(w, lw, n); + return solarTransitJ(a, M, L); +} + + +// calculates sun times for a given date, latitude/longitude, and, optionally, +// the observer height (in meters) relative to the horizon + +SunCalc.getTimes = function (date, lat, lng, height) { + + height = height || 0; + + var lw = rad * -lng, + phi = rad * lat, + + dh = observerAngle(height), + + d = toDays(date), + n = julianCycle(d, lw), + ds = approxTransit(0, lw, n), + + M = solarMeanAnomaly(ds), + L = eclipticLongitude(M), + dec = declination(L, 0), + + Jnoon = solarTransitJ(ds, M, L), + + i, len, time, h0, Jset, Jrise; + + + var result = { + solarNoon: fromJulian(Jnoon), + nadir: fromJulian(Jnoon - 0.5) + }; + + for (i = 0, len = times.length; i < len; i += 1) { + time = times[i]; + h0 = (time[0] + dh) * rad; + + Jset = getSetJ(h0, lw, phi, dec, n, M, L); + Jrise = Jnoon - (Jset - Jnoon); + + result[time[1]] = fromJulian(Jrise); + result[time[2]] = fromJulian(Jset); + } + + return result; +}; + + +// moon calculations, based on http://aa.quae.nl/en/reken/hemelpositie.html formulas + +function moonCoords(d) { // geocentric ecliptic coordinates of the moon + + var L = rad * (218.316 + 13.176396 * d), // ecliptic longitude + M = rad * (134.963 + 13.064993 * d), // mean anomaly + F = rad * (93.272 + 13.229350 * d), // mean distance + + l = L + rad * 6.289 * sin(M), // longitude + b = rad * 5.128 * sin(F), // latitude + dt = 385001 - 20905 * cos(M); // distance to the moon in km + + return { + ra: rightAscension(l, b), + dec: declination(l, b), + dist: dt + }; +} + +SunCalc.getMoonPosition = function (date, lat, lng) { + + var lw = rad * -lng, + phi = rad * lat, + d = toDays(date), + + c = moonCoords(d), + H = siderealTime(d, lw) - c.ra, + h = altitude(H, phi, c.dec), + // formula 14.1 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + pa = atan(sin(H), tan(phi) * cos(c.dec) - sin(c.dec) * cos(H)); + + h = h + astroRefraction(h); // altitude correction for refraction + + return { + azimuth: azimuth(H, phi, c.dec), + altitude: h, + distance: c.dist, + parallacticAngle: pa + }; +}; + + +// calculations for illumination parameters of the moon, +// based on http://idlastro.gsfc.nasa.gov/ftp/pro/astro/mphase.pro formulas and +// Chapter 48 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + +SunCalc.getMoonIllumination = function (date) { + + var d = toDays(date || new Date()), + s = sunCoords(d), + m = moonCoords(d), + + sdist = 149598000, // distance from Earth to Sun in km + + phi = acos(sin(s.dec) * sin(m.dec) + cos(s.dec) * cos(m.dec) * cos(s.ra - m.ra)), + inc = atan(sdist * sin(phi), m.dist - sdist * cos(phi)), + angle = atan(cos(s.dec) * sin(s.ra - m.ra), sin(s.dec) * cos(m.dec) - + cos(s.dec) * sin(m.dec) * cos(s.ra - m.ra)); + + return { + fraction: (1 + cos(inc)) / 2, + phase: 0.5 + 0.5 * inc * (angle < 0 ? -1 : 1) / Math.PI, + angle: angle + }; +}; + + +function hoursLater(date, h) { + return new Date(date.valueOf() + h * dayMs / 24); +} + +// calculations for moon rise/set times are based on http://www.stargazing.net/kepler/moonrise.html article + +SunCalc.getMoonTimes = function (date, lat, lng, inUTC) { + var t = new Date(date); + if (inUTC) t.setUTCHours(0, 0, 0, 0); + else t.setHours(0, 0, 0, 0); + + var hc = 0.133 * rad, + h0 = SunCalc.getMoonPosition(t, lat, lng).altitude - hc, + h1, h2, rise, set, a, b, xe, ye, d, roots, x1, x2, dx; + + // go in 2-hour chunks, each time seeing if a 3-point quadratic curve crosses zero (which means rise or set) + for (var i = 1; i <= 24; i += 2) { + h1 = SunCalc.getMoonPosition(hoursLater(t, i), lat, lng).altitude - hc; + h2 = SunCalc.getMoonPosition(hoursLater(t, i + 1), lat, lng).altitude - hc; + + a = (h0 + h2) / 2 - h1; + b = (h2 - h0) / 2; + xe = -b / (2 * a); + ye = (a * xe + b) * xe + h1; + d = b * b - 4 * a * h1; + roots = 0; + + if (d >= 0) { + dx = Math.sqrt(d) / (Math.abs(a) * 2); + x1 = xe - dx; + x2 = xe + dx; + if (Math.abs(x1) <= 1) roots++; + if (Math.abs(x2) <= 1) roots++; + if (x1 < -1) x1 = x2; + } + + if (roots === 1) { + if (h0 < 0) rise = i + x1; + else set = i + x1; + + } else if (roots === 2) { + rise = i + (ye < 0 ? x2 : x1); + set = i + (ye < 0 ? x1 : x2); + } + + if (rise && set) break; + + h0 = h2; + } + + var result = {}; + + if (rise) result.rise = hoursLater(t, rise); + if (set) result.set = hoursLater(t, set); + + if (!rise && !set) result[ye > 0 ? 'alwaysUp' : 'alwaysDown'] = true; + + return result; +}; + + +// export as Node module / AMD module / browser variable +if (typeof exports === 'object' && typeof module !== 'undefined') module.exports = SunCalc; +else if (typeof define === 'function' && define.amd) define(SunCalc); +else window.SunCalc = SunCalc; + +}()); diff --git a/RVO50/flow/helper/utils.js b/RVO50/flow/helper/utils.js new file mode 100755 index 0000000..dbffe45 --- /dev/null +++ b/RVO50/flow/helper/utils.js @@ -0,0 +1,161 @@ +const fs = require('fs').promises; + +function bytesToInt(bytes, numberOfBytes) { + let buffer = []; + if (Array.isArray(bytes)) { + buffer = bytes.slice(0); + if (numberOfBytes != undefined) { + buffer = bytes.slice(bytes.length - numberOfBytes); + } + } + else buffer.push(bytes); + + let result = 0; + for (let i = 0; i < buffer.length; i++) { + result = (result << 8) | buffer[i]; + } + + return result >>> 0; //ensure it's an unsigned 32-bit number +} + +function resizeArray(arr, newSize, defaultValue) { + while (newSize > arr.length) + arr.push(defaultValue); + arr.length = newSize; +} + +longToByteArray = function(/*long*/long) { + // we want to represent the input as a 8-bytes array + var byteArray = [0, 0, 0, 0, 0, 0, 0, 0]; + + for (var index = 0; index < byteArray.length; index++) { + var byte = long & 0xff; + byteArray[index] = byte; + long = (long - byte) / 256; + } + + return byteArray; +}; + +function addDays(date, days) { + var result = new Date(date); + result.setDate(result.getDate() + days); + return result; +} + +/* +sleep(2000).then(() => { + // Do something after the sleep! + + +}); +*/ + +function sleep(time) { + return new Promise((resolve) => setTimeout(resolve, time)); +} + +function isEmptyObject(obj) { + for (var name in obj) { + return false; + } + return true; +} + +function emptyJsObject(jsObject) { + Object.keys(jsObject).forEach(key => delete jsObject[key]); +} + +function convertUTCDateToLocalDate(date) { + var newDate = new Date(date); + newDate.setMinutes(date.getMinutes() + date.getTimezoneOffset()); + return newDate; +} + +function addZeroBefore(n) { + return (n < 10 ? '0' : '') + n; +} + + +/** + * Asynchronously writes data to a file. + * + * @param {string} filePath The path to the file. + * @param {string} data The data to write to the file. + * @param {boolean} [append=false] If true, appends the data to the file. If false, it overwrites the file. + */ +async function writeToFile(filePath, data, append = false) { + if (typeof data !== 'string') data = JSON.stringify(data, null, 2); + try { + if (append) { + // Append the data to the end of the file. This is the simplest way to append. + await fs.appendFile(filePath, data, 'utf8'); + console.log(`Successfully appended data to ${filePath} using fs.appendFile.`); + } else { + // Overwrite the file with the new data. + await fs.writeFile(filePath, data, 'utf8'); + console.log(`Successfully wrote (overwrote) data to ${filePath} using fs.writeFile.`); + } + } catch (error) { + console.error(`Error writing to file ${filePath}:`, error); + } +} + + + /** + * Checks if an item is present in an array and adds it if it's not. + * * @param {Array} arr The array to check. + * @param {*} item The item to add. + * @returns {Array} The modified array. + */ +const addToArrayIfUnique = (arr, item) => { + if (!arr.includes(item)) { + arr.push(item); + } + return arr; +}; + + +var convertBase = function() { + + function convertBase(baseFrom, baseTo) { + return function(num) { + return parseInt(num, baseFrom).toString(baseTo); + + }; + } + + // binary to decimal + convertBase.bin2dec = convertBase(2, 10); + + // binary to hexadecimal + convertBase.bin2hex = convertBase(2, 16); + + // decimal to binary + convertBase.dec2bin = convertBase(10, 2); + + // decimal to hexadecimal + convertBase.dec2hex = convertBase(10, 16); + + // hexadecimal to binary + convertBase.hex2bin = convertBase(16, 2); + + // hexadecimal to decimal + convertBase.hex2dec = convertBase(16, 10); + + return convertBase; +}(); + +module.exports = { + bytesToInt, + longToByteArray, + addDays, + addZeroBefore, + resizeArray, + isEmptyObject, + emptyJsObject, + sleep, + convertUTCDateToLocalDate, + writeToFile, + addToArrayIfUnique +} diff --git a/RVO50/flow/httprequest.js b/RVO50/flow/httprequest.js new file mode 100755 index 0000000..469c8cb --- /dev/null +++ b/RVO50/flow/httprequest.js @@ -0,0 +1,137 @@ +exports.id = 'httprequest'; +exports.title = 'HTTP Request'; +exports.group = 'HTTP'; +exports.color = '#5D9CEC'; +exports.input = true; +exports.version = '2.0.1'; +exports.output = 1; +exports.author = 'Peter Širka'; +exports.icon = 'cloud-upload'; + +exports.html = `
+
@(URL address)
+
+
+
@(HTTP method)
+
+
+
@(Serialization)
+
+
+
@(Download the content in chunks)
+
@(Keep persistent cookies)
+
@(Disable DNS cache)
+
@(Keep alive connection)
+
+
+
+
@(Custom headers)
+
@(Cookies)
+
+
+
+ +
+
+
+
@(User)
+
+
+
@(Password)
+
+
+
+
+
`; + +exports.readme = `# Request + +This component creates a request with received data. + +__Response:__ +\`\`\`javascript +{ + data: String, + headers: Object, + status: Number, + host: String +} +\`\`\` + +__Dynamic arguments__: +Are performed via FlowData repository and can be used for URL address or for custom headers/cookies/auth. Use \`repository\` component for creating of dynamic arguments. Dynamic values are replaced in the form \`{key}\`: + +- url address e.g. \`https://.../{key}/\` +- headers values e.g. \`{token}\` +- cookies values e.g. \`{token}\``; + +exports.install = function(instance) { + + var can = false; + var flags = null; + var cookies2 = null; + + instance.on('data', function(response) { + can && instance.custom.send(response); + }); + + instance.custom.send = function(response) { + var options = instance.options; + + var headers = null; + var cookies = null; + + options.headers && Object.keys(options.headers).forEach(function(key) { + !headers && (headers = {}); + headers[key] = response.arg(options.headers[key]); + }); + + if (options.username && options.userpassword) { + !headers && (headers = {}); + headers['Authorization'] = 'Basic ' + U.createBuffer(response.arg(options.username + ':' + options.userpassword)).toString('base64'); + } + + options.cookies && Object.keys(options.cookies).forEach(function(key) { + !cookies && (cookies = {}); + cookies[key] = response.arg(options.cookies[key]); + }); + + if (options.chunks) { + U.download(response.arg(options.url), flags, options.stringify === 'none' ? null : response.data, function(err, response) { + response.on('data', (chunks) => instance.send2(chunks)); + }, cookies || cookies2, headers); + } else { + U.request(response.arg(options.url), flags, options.stringify === 'none' ? null : response.data, 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) + instance.error(err, response); + }, cookies || cookies2, headers); + } + }; + + instance.reconfigure = function() { + var options = instance.options; + can = options.url && options.url && options.method && options.stringify ? true : false; + instance.status(can ? '' : 'Not configured', can ? undefined : 'red'); + + if (!can) + return; + + flags = []; + flags.push(options.method.toLowerCase()); + options.stringify === 'json' && flags.push('json'); + options.stringify === 'raw' && flags.push('raw'); + options.keepalive && flags.push('keepalive'); + !options.nodns && flags.push('dnscache'); + if (options.persistentcookies) { + flags.push('cookies'); + cookies2 = {}; + } else + cookies2 = null; + }; + + instance.on('options', instance.reconfigure); + instance.reconfigure(); +}; \ No newline at end of file diff --git a/RVO50/flow/httpresponse.js b/RVO50/flow/httpresponse.js new file mode 100755 index 0000000..160a3bb --- /dev/null +++ b/RVO50/flow/httpresponse.js @@ -0,0 +1,76 @@ +exports.id = 'httpresponse'; +exports.title = 'HTTP Response'; +exports.group = 'HTTP'; +exports.color = '#5D9CEC'; +exports.icon = 'arrow-right'; +exports.input = true; +exports.output = ['#666D76']; +exports.version = '2.0.0'; +exports.author = 'Martin Smola'; +exports.readme = `# HTTP response + +HTTP response will respond with data recieved using data-type set in Settings form or plain text if not set. Output is the message duration \`Number\` in seconds.`; + +exports.html = `
+
@(Response data-type)
+
JSON is by default.
+
`; + +exports.install = function(instance) { + + var dursum = 0; + var durcount = 0; + + instance.on('data', function(flowdata) { + + var ctrl = flowdata.repository.controller; + var data = flowdata.data; + + if (!ctrl) { + instance.throw('No controller to use for response!'); + return; + } + + durcount++; + dursum += ((new Date() - flowdata.begin) / 1000).floor(2); + setTimeout2(instance.id, instance.custom.duration, 500, 10); + + ctrl.$flowdata = flowdata; + + var datatype = instance.options.datatype || 'json'; + if (datatype === 'emptyresponse') + return ctrl.plain(''); + + if (datatype !== 'json' && typeof(data) !== 'string') { + instance.throw('Incorect type of data, expected string, got ' + typeof(data)); + ctrl.plain(data == null ? '' : data.toString()); + return; + } + + switch(datatype) { + case 'html': + ctrl.content(data, 'text/html'); + break; + case 'plain': + ctrl.plain(data); + break; + case 'xml': + ctrl.content(data, 'text/xml'); + break; + default: + ctrl.json(data); + break; + } + }); + + instance.on('service', function() { + dursum = 0; + durcount = 0; + }); + + instance.custom.duration = function() { + var avg = (dursum / durcount).floor(2); + instance.status(avg + ' sec.'); + instance.send2(0, avg); + }; +}; diff --git a/RVO50/flow/httproute.js b/RVO50/flow/httproute.js new file mode 100755 index 0000000..583a19d --- /dev/null +++ b/RVO50/flow/httproute.js @@ -0,0 +1,326 @@ +exports.id = 'httproute'; +exports.title = 'HTTP Route'; +exports.group = 'HTTP'; +exports.color = '#5D9CEC'; +exports.icon = 'globe'; +exports.input = false; +exports.output = ['#6CAC5A', '#37BC9B']; +exports.version = '1.2.3'; +exports.author = 'Martin Smola'; +exports.cloning = false; +exports.options = { method: 'GET', url: '', size: 5, cacheexpire: '5 minutes', cachepolicy: 0, timeout: 5 }; +exports.dateupdated = '2021-01-21 18:30d'; +exports.readme = `# HTTP route + +__Outputs__: +- first output: raw data (cache is empty or is disabled) +- second output: cached data + +If one of the outputs is disabled then automatic responce with code "503 service unavailable" is sent. + +When a request comes in bellow object is available at \`flowdata.data\`: + +\`\`\`javascript +{ + params: { id: '1' }, // params for dynamic routes, e.g. /test/{id} + query: { msg: 'Hello' }, // parsed query string, e.g. /test/1?msg=Hello + body: { test: 'OK' }, // object if json requests otherwise string + headers: {}, // headers data + session: {}, // session data + user: {}, // user data + files: [], // uploaded files + url: '/users/', // a relative URL address + referrer: '/', // referrer + mobile: false, // determines mobile device + robot: false, // determines search robots/crawlsers + language: 'en' // determines language +} +\`\`\` + +See [documentation for flags](https://docs.totaljs.com/latest/en.html#api~HttpRouteOptionsFlags~unauthorize). These method flags are set automatically e.g. \`get, post, put, patch or delete\` + +--- + +\`id:ROUTE_ID\` flag cannot be used since it's already used by this component internally`; + +exports.html = `
+
+ +
+ +
+
+
@(HTTP method)
+
+
+
@(URL address)
+
+
+
+
+
@(Additional flags)
+
@(Separate flags by comma e.g. json, authorize)
+
+
+
@(Max. request size)
+
@(In kB kilobytes)
+
+
+
@(Timeout)
+
@(In seconds.)
+
+
+
+
+
+
@(Automatically respond with 200 OK?)
+
@(If not checked you need to use HTTP response component to respond to the request.)
+
+
@(Custom headers)
+
@(Cookies)
+
+
+
+
+
+
@(Cache policy)
+
@(User instance must contain id property.)
+
+
+
@(Expiration)
+
@(E.g. 5 minutes)
+
+
+
+`; + +exports.install = function(instance) { + + var route; + + var uninstall = function(id) { + if (F.is4) { + route && route.remove(); + route = null; + } else + UNINSTALL('route', id); + }; + + instance.custom.emptyresponse = function(self) { + self.plain(); + }; + + instance.reconfigure = function() { + + var options = instance.options; + + if (!options.url) { + instance.status('Not configured', 'red'); + return; + } + + if (typeof(options.flags) === 'string') + options.flags = options.flags.split(',').trim(); + + uninstall('id:' + instance.id); + + var flags = options.flags || []; + + flags.push('id:' + instance.id); + + if (!F.is4) + flags.push(options.method.toLowerCase()); + + options.timeout && flags.push(options.timeout * 1000); + + // Make unique values + flags = flags.filter(function(v, i, a) { + if(F.is4 && v.toString().toLowerCase() === options.method.toLowerCase()) + return false; // remove method + return a.indexOf(v) === i; + }); + + options.flags = flags; + var handler = function() { + + if (instance.paused || (instance.isDisabled && (instance.isDisabled('output', 0) || instance.isDisabled('output', 1)))) { + instance.status('503 Service Unavailable'); + this.status = 503; + this.json(); + return; + } + + var key; + var self = this; + + if (instance.options.emptyresponse) { + instance.status('200 OK'); + setTimeout(instance.custom.emptyresponse, 100, self); + + if (instance.hasConnection(0)) { + var data = instance.make({ + query: self.query, + body: self.body, + session: self.session, + user: self.user, + files: self.files, + headers: self.req.headers, + url: self.url, + params: self.params + }); + instance.send2(0, data); + } + + return; + } + + switch (instance.options.cachepolicy) { + case 1: // URL + key = 'rro' + instance.id + self.url.hash(); + break; + case 2: // URL + query + case 3: // URL + query + user + key = self.url; + var keys = Object.keys(self.query); + keys.sort(); + for (var i = 0, length = keys.length; i < length; i++) + key += keys[i] + self.query[keys[i]] + '&'; + if (instance.options.cachepolicy === 3 && self.user) + key += 'iduser' + self.user.id; + key = 'rro' + instance.id + key.hash(); + break; + } + + if (key && F.cache.get2(key)) { + var data = instance.make(F.cache.get2(key)); + data.repository.controller = self; + instance.send2(1, data); + } else { + + var data = instance.make({ + query: self.query, + body: self.body, + session: self.session, + user: self.user, + files: self.files, + headers: self.req.headers, + url: self.url, + params: self.params, + mobile: self.mobile, + robot: self.robot, + referrer: self.referrer, + language: self.language + }); + + data.repository.controller = self; + instance.send2(0, data); + key && FINISHED(self.res, () => F.cache.set(key, self.$flowdata.data, instance.options.cacheexpire)); + } + }; + + if (F.is4) + route = ROUTE(options.method.toUpperCase() + ' ' + options.url, handler, flags, options.size || 5); + else + F.route(options.url, handler, flags, options.size || 5); + + instance.status('Listening', 'green'); + }; + + instance.reconfigure(); + instance.on('options', instance.reconfigure); + instance.on('close', function(){ + uninstall('id:' + instance.id); + }); +}; + +// check url exists +FLOW.trigger('httproutecheckurl', function(next, data) { + var url = data.url; + var method = data.method; + if (url[url.length - 1] !== '/') + url += '/'; + var exists = F.routes.web.findItem(r => r.urlraw === url && r.method === method); + next(exists != null); +}); + +exports.uninstall = function() { + FLOW.trigger('httproutecheckurl', null); +}; diff --git a/RVO50/flow/infosender.js b/RVO50/flow/infosender.js new file mode 100755 index 0000000..587724f --- /dev/null +++ b/RVO50/flow/infosender.js @@ -0,0 +1,81 @@ +exports.id = 'infosender'; +exports.title = 'Info sender'; +exports.version = '1.0.0'; +exports.group = 'Worksys'; +exports.color = '#2134B0'; +exports.input = 2; +exports.output = 1 +exports.icon = 'bolt'; + +const { networkInterfaces } = require('os'); + +exports.html = `
+
+
+
CSV Import
+
+
+
`; + +exports.readme = `# send all data to projects.worksys.io, required to monitor status of controller(unipi)`; + +exports.install = function(instance) { + + let id; + let allValues = {}; + let sendAllValuesInterval; + let configured = false; + + let now = new Date(); + console.log(exports.title, "INSTALLED", now.toLocaleString("sk-SK")); + + const nets = networkInterfaces(); + let ipAddresses = Object.create(null); // Or just '{}', an empty object + + for (const name of Object.keys(nets)) { + for (const net of nets[name]) { + // Skip over non-IPv4 and internal (i.e. 127.0.0.1) addresses + if (net.family === 'IPv4' && !net.internal) { + if (!ipAddresses[name]) { + ipAddresses[name] = []; + } + ipAddresses[name].push(net.address); + } + } + } + + function sendValues() { + if (!configured) return; + + if (Object.keys(allValues).length > 0) { + let dataToSend = { ...allValues }; + dataToSend.id = id; + dataToSend.ipAddresses = ipAddresses; + + instance.send(0, dataToSend); + + allValues = {}; + } + } + + instance.on("close", () => { + clearInterval(sendAllValuesInterval); + }) + + instance.on("0", _ => { + id = FLOW.GLOBALS.settings.project_id; + if (id) configured = true; + else console.log(exports.title, "InfoSender: Unable to send data, no id"); + }) + + instance.on("1", flowdata => { + allValues = { ...allValues, ...flowdata.data }; + //console.log("DATA RECEIVED", flowdata.data); + }) + + sendAllValuesInterval = setInterval(() => { + sendValues(); + }, 60000 * 3); + +} + diff --git a/RVO50/flow/modbus_reader.js b/RVO50/flow/modbus_reader.js new file mode 100755 index 0000000..d6d9dad --- /dev/null +++ b/RVO50/flow/modbus_reader.js @@ -0,0 +1,346 @@ +exports.id = 'modbus_reader'; +exports.title = 'Modbus reader'; +exports.version = '2.0.0'; +exports.group = 'Worksys'; +exports.color = '#2134B0'; +exports.input = 1; +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; +//number of phases inRVO +let phases; +//phases where voltage is 0 (set) +let noVoltage; +let energyToSwitchLamps; + +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.phases = this.buildPhases(); + + this.startSocket(); + } + + buildPhases = () => { + let a = []; + for (let i = 1; i <= phases; i++) { + a.push(`Phase_${i}_voltage`) + } + return a; + } + + startSocket = () => { + + let obj = this; + + if (this.socket) { + this.socket.removeAllListeners(); + this.socket = null; + } + + 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('Modbus_reader: Socket connection error', e); //'ECONNREFUSED' or 'ECONNRESET' ?? + }); + + this.socket.on('close', function() { + console.log('Modbus_reader: Socket connection closed - Waiting 10 seconds before connecting 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 we just start to loop devices from the beginning, or there is just 1 device in config, we wait whole timeoutInterval + if (this.indexInDeviceConfig == 0 || deviceConfig.length === 1) 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 (this.phases.includes(singleValue)) { + let l = singleValue.split("_"); + let phase = parseInt(l[1]); + + // console.log(values[singleValue], tbName); + + if (values[singleValue] == 0) { + noVoltage.add(phase); + sendNotification("modbus_reader: checkNullVoltage", tbName, "no_voltage_on_phase", { phase: phase }, "", SEND_TO.tb, instance, "voltage" + phase); + // console.log('no voltage') + } + else { + noVoltage.delete(phase); + // console.log('voltage detected') + sendNotification("modbus_reader: checkNullVoltage", tbName, "voltage_on_phase_restored", { phase: phase }, "", SEND_TO.tb, instance, "voltage" + phase); + } + } + }) + } + + /** + * function sends notification to slack and to tb, if EM total_power value changes more than numberOfNodes*15. This should show, that RVO lamps has been switched on or off + */ + lampSwitchNotification = (values) => { + + if (!values.hasOwnProperty("total_power")) return; + + const actualTotalPower = values.total_power; + + if (actualTotalPower > energyToSwitchLamps && 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 <= energyToSwitchLamps && 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; + } + + function main() { + + phases = FLOW.GLOBALS.settings.phases; + tbName = FLOW.GLOBALS.settings.rvoTbName; + noVoltage = FLOW.GLOBALS.settings.no_voltage; + energyToSwitchLamps = FLOW.GLOBALS.settings.energy_to_switch_lamps / 2.5; //half value is enought to show if lamps are turned on or off + if (deviceConfig.length) mainSocket = new SocketWithClients(); + else console.log("Modbus_reader: no modbus device in configuration"); + + // this notification is to show, that flow (unipi) has been restarted + sendNotification("modbus_reader", tbName, "flow_restart", {}, "", SEND_TO.slack, instance); + } + + instance.on("0", function(_) { + main(); + }) + +} + diff --git a/RVO50/flow/monitorconsumption.js b/RVO50/flow/monitorconsumption.js new file mode 100755 index 0000000..64cc58e --- /dev/null +++ b/RVO50/flow/monitorconsumption.js @@ -0,0 +1,156 @@ +exports.id = 'monitorconsumption'; +exports.title = 'Consumption'; +exports.version = '1.0.0'; +exports.author = 'Peter Širka'; +exports.group = 'Monitoring'; +exports.color = '#967ADC'; +exports.input = 0; +exports.output = 1; +exports.icon = 'bug'; +exports.options = { interval: 5000, enabled: true, monitorconsumption: true, monitorsize: true, monitorconnections: true, monitorfiles: true }; +exports.click = true; +exports.readme = `# Consumption monitoring + +This component measure CPU and memory consumption, open files and open connections of this application. It uses these Linux commands: \`ps\`, \`lsof\`, \`netstat\` and \`df\`. + +__Data Example__: + +\`\`\`javascript +{ + cpu: 0, // percentage + memory: 4096, // in bytes + size: 34303, // directory size in bytes + files: 34, // count of open files + connections: 343, // count of connections + uptime: '1-12:34:00' +} +\`\`\``; + +exports.html = `
+
+
+
@(Interval in milliseconds)
+
+
+
+
Monitor: Consumption + uptime
+
Monitor: Count of open files
+
Monitor: Count of open connections
+
Monitor: Directory size
+
`; + +exports.install = function(instance) { + + var current = { cpu: 0, memory: 0, files: 0, connections: 0, size: 0, uptime: '', counter: 0 }; + var tproc = null; + var Exec = require('child_process').exec; + var reg_empty = /\s{2,}/g; + var reg_appdisksize = /^[\d.,]+/; + + instance.custom.run = function() { + + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + + var arr = []; + + // Get CPU and Memory consumption + instance.options.monitorconsumption && arr.push(function(next) { + Exec('ps -p {0} -o %cpu,rss,etime'.format(process.pid), function(err, response) { + + if (err) { + instance.throw(err); + } else { + var line = response.split('\n')[1]; + line = line.trim().replace(reg_empty, ' ').split(' '); + var cpu = line[0].parseFloat(); + current.cpu = cpu.floor(1); + current.memory = line[1].parseInt2() * 1024; // kB to bytes + current.uptime = line[2]; + } + + next(); + }); + }); + + // Get count of open files + instance.options.monitorfiles && arr.push(function(next) { + Exec('lsof -a -p {0} | wc -l'.format(process.pid), function(err, response) { + if (err) + instance.throw(err); + else + current.files = response.trim().parseInt2(); + next(); + }); + }); + + // Get count of opened network connections + instance.options.monitorconnections && arr.push(function(next) { + Exec('netstat -an | grep :{0} | wc -l'.format(F.port), function(err, response) { + if (err) { + instance.throw(err); + } else { + current.connections = response.trim().parseInt2() - 1; + if (current.connections < 0) + current.connections = 0; + } + next(); + }); + }); + + // Get directory size + instance.options.monitorsize && current.counter % 5 !== 0 && arr.push(function(next) { + Exec('du -hsb ' + process.cwd(), function(err, response) { + if (err) { + instance.throw(err); + } else { + var match = response.trim().match(reg_appdisksize); + match && (current.size = match.toString().trim().parseInt2()); + } + next(); + }); + }); + + arr.async(function() { + + tproc && clearTimeout(tproc); + + if (instance.options.enabled) { + tproc = setTimeout(instance.custom.run, instance.options.interval); + instance.send2(current); + } + + instance.custom.status(); + current.counter++; + }); + }; + + instance.custom.status = function() { + if (instance.options.enabled) + instance.status('{0}% / {1}'.format(current.cpu, current.memory.filesize())); + else + instance.status('Disabled', 'red'); + }; + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + + if (instance.options.enabled) { + current.counter = 0; + instance.custom.run(); + } + + }); + + instance.on('close', function() { + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + }); + + setTimeout(instance.custom.run, 1000); +}; \ No newline at end of file diff --git a/RVO50/flow/monitordisk.js b/RVO50/flow/monitordisk.js new file mode 100755 index 0000000..f4fdaa0 --- /dev/null +++ b/RVO50/flow/monitordisk.js @@ -0,0 +1,96 @@ +exports.id = 'monitordisk'; +exports.title = 'Disk'; +exports.version = '1.0.0'; +exports.author = 'Peter Širka'; +exports.group = 'Monitoring'; +exports.color = '#F6BB42'; +exports.output = 1; +exports.icon = 'hdd-o'; +exports.click = true; +exports.options = { interval: 8000, path: '/', enabled: true }; +exports.readme = `# Disk monitoring + +This component monitors disk \`bytes\` consumption in Linux systems. It uses \`df\` command. + +__Data Example__: + +\`\`\`javascript +{ + total: 474549649408, + used: 39125245952, + free: 411294994432 +} +\`\`\``; + +exports.html = `
+
+
+
@(Interval in milliseconds)
+
+
+
@(Path)
+
+
+
`; + +exports.install = function(instance) { + + var current = { total: 0, used: 0, free: 0, path: '', type: '', percentUsed: 0 }; + var tproc = null; + + instance.custom.run = function() { + + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + + if (!instance.options.enabled) + return; + + require('child_process').exec('df -hTB1 ' + instance.options.path, function(err, response) { + + tproc = setTimeout(instance.custom.run, instance.options.interval); + + if (err) { + instance.error(err); + return; + } + + response.parseTerminal(function(line) { + if (line[0][0] !== '/') + return; + current.total = line[2].parseInt(); + current.free = line[4].parseInt(); + current.used = line[3].parseInt(); + current.path = instance.options.path || '/'; + current.type = line[1]; + current.percentUsed = line[5]; + instance.custom.status(); + instance.send2(current); + }); + }); + }; + + instance.custom.status = function() { + if (instance.options.enabled) + instance.status(current.free.filesize() + ' / ' + current.total.filesize()); + else + instance.status('Disabled', 'red'); + }; + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + instance.options.enabled && instance.custom.run(); + }); + + instance.on('close', function() { + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + }); + + setTimeout(instance.custom.run, 1000); +}; \ No newline at end of file diff --git a/RVO50/flow/monitormemory.js b/RVO50/flow/monitormemory.js new file mode 100755 index 0000000..2decbc4 --- /dev/null +++ b/RVO50/flow/monitormemory.js @@ -0,0 +1,87 @@ +exports.id = 'monitormemory'; +exports.title = 'Memory'; +exports.version = '1.0.0'; +exports.author = 'Peter Širka'; +exports.group = 'Monitoring'; +exports.color = '#F6BB42'; +exports.output = 1; +exports.click = true; +exports.icon = 'microchip'; +exports.options = { interval: 8000, enabled: true }; +exports.readme = `# Memory monitoring + +This component monitors memory \`bytes\` consumption in Linux systems. It uses \`free\` command. + +__Data Example__: + +\`\`\`javascript +{ + total: 33558769664, + used: 1998868480, + free: 2653708288 +} +\`\`\``; + +exports.html = `
+
+
+
@(Interval in milliseconds)
+
+
+
`; + +exports.install = function(instance) { + + var current = { total: 0, used: 0, free: 0 }; + var tproc = null; + + instance.custom.run = function() { + + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + + if (!instance.options.enabled) + return; + + require('child_process').exec('free -b -t', function(err, response) { + + tproc = setTimeout(instance.custom.run, instance.options.interval); + + if (err) { + instance.error(err); + return; + } + + var memory = response.split('\n')[1].match(/\d+/g); + current.total = memory[0].parseInt(); + current.used = memory[1].parseInt() - memory[3].parseInt(); + current.free = current.total - current.used; + instance.custom.status(); + instance.send2(current); + }); + }; + + instance.custom.status = function() { + if (instance.options.enabled) + instance.status(current.free.filesize() + ' / ' + current.total.filesize()); + else + instance.status('Disabled', 'red'); + }; + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + instance.options.enabled && instance.custom.run(); + }); + + instance.on('close', function() { + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + }); + + setTimeout(instance.custom.run, 1000); +}; \ No newline at end of file diff --git a/RVO50/flow/nodesdb_changecheck.js b/RVO50/flow/nodesdb_changecheck.js new file mode 100755 index 0000000..9adab62 --- /dev/null +++ b/RVO50/flow/nodesdb_changecheck.js @@ -0,0 +1,77 @@ +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 = 2; +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); + } + } + + //kedze do slacku posielame stringy, na cloud musime previest vsetky stringy spat na objekty: + // Funkcia na parsovanie všetkých reťazcov v poli + const parseArray = (arr) => { + return arr.map(jsonString => JSON.parse(jsonString)); + }; + + 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); + if (FLOW.GLOBALS.settings.send_changed_node_numbers) instance.send(1, { aktualneNody: parseArray(zmenene), originalne: parseArray(Array.from(set2)) }); + } + 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/RVO50/flow/show_dbdata.js b/RVO50/flow/show_dbdata.js new file mode 100755 index 0000000..1e23ff7 --- /dev/null +++ b/RVO50/flow/show_dbdata.js @@ -0,0 +1,243 @@ +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 = 8; +exports.output = 1; + +const { exec } = require('child_process'); + +exports.install = 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 }) + }) + instance.on("5", _ => { + exec("sudo tail -n 25 monitor.txt", (err, stdout, stderr) => { + if (err || stderr) instance.send(0, { err, stderr }); + else instance.send(0, stdout); + }) + }) + instance.on("6", _ => { + exec("sudo tail -n 25 err.txt", (err, stdout, stderr) => { + if (err || stderr) instance.send(0, { err, stderr }); + else instance.send(0, stdout); + }) + }) + instance.on("7", _ => { + instance.send(0, FLOW.deviceStatus); + }) +}; + + +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/RVO50/flow/slack_filter.js b/RVO50/flow/slack_filter.js new file mode 100755 index 0000000..6618523 --- /dev/null +++ b/RVO50/flow/slack_filter.js @@ -0,0 +1,188 @@ +exports.id = 'slack_filter'; +exports.title = 'Slack Filter'; +exports.group = 'Citysys'; +exports.color = '#30E193'; +exports.input = 2; +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 = `
+
+
+
@(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('0', 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']['en']; + 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"] = []; + } + + instance.options.name = FLOW.GLOBALS.settings.rvo_name; + if (instance.options.name) { + instance.status('Running'); + running = true; + } else { + instance.status('Please run options again', 'red'); + running = false; + } + } catch (e) { + instance.error('Citysys connector: ' + e.message); + } + }; + + instance.on('options', instance.reconfigure); + + instance.on("1", _ => { + instance.reconfigure(); + }) +}; diff --git a/RVO50/flow/thermometer.js b/RVO50/flow/thermometer.js new file mode 100755 index 0000000..fc7074d --- /dev/null +++ b/RVO50/flow/thermometer.js @@ -0,0 +1,99 @@ +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 = 5;//minutes +let NUMBER_OF_FAILURES_TO_SEND_ERROR = 13; + +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) => { + + 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); + setTimeout(main, 20000); + }) +}; diff --git a/RVO50/flow/trigger.js b/RVO50/flow/trigger.js new file mode 100755 index 0000000..27545a8 --- /dev/null +++ b/RVO50/flow/trigger.js @@ -0,0 +1,79 @@ +exports.id = 'trigger'; +exports.title = 'Trigger'; +exports.group = 'Inputs'; +exports.color = '#F6BB42'; +exports.click = true; +exports.output = 1; +exports.version = '1.1.0'; +exports.author = 'Martin Smola'; +exports.icon = 'play'; + +exports.html = `
+
@(Data type (String by default))
+
@(Data)
+
Trigger 5s after initialization.
+
@(Useful when there's a need to run certain flow when the app restarts, etc.)
+
`; + +exports.readme = `# Trigger + +- Clicking on the component starts the chain +- Settings allows to set a data-type and a value`; + +exports.install = function(instance) { + + var value; + + instance.on('click', () => instance.send2(value)); + + instance.reconfigure = function() { + var options = instance.options; + value = null; + switch (options.datatype) { + case 'integer': + value = options.data.parseInt2('error'); + value = value === 'error' ? NaN : value; + break; + case 'float': + value = options.data.parseFloat2('error'); + value = value === 'error' ? NaN : value; + break; + case 'date': + options.data = options.data.toString(); + var num = options.data.parseInt('error'); + num === 'error' && (num = options.data.parseDate('error')); + num === 'error' && (num = null); + value = num ? new Date(num).toUTCString() : num; + break; + case 'object': + try { + value = (new Function('return ' + options.data))(); + } catch (e) { + instance.error(e); + } + break; + case 'boolean': + value = options.data.parseBoolean(); + break; + case 'buffer': + try { + value = U.createBuffer(options.data); + } catch (e) { + instance.error(e); + } + break; + case 'string': + default: + value = '' + (options.data || ''); + break; + } + }; + + instance.on('options', instance.reconfigure); + instance.reconfigure(); + + if (instance.options.restart) + setTimeout(function(){ + instance.send2(value); + }, 5000); +}; diff --git a/RVO50/flow/variables.txt b/RVO50/flow/variables.txt new file mode 100755 index 0000000..e69de29 diff --git a/RVO50/flow/virtualwirein.js b/RVO50/flow/virtualwirein.js new file mode 100755 index 0000000..38a4e42 --- /dev/null +++ b/RVO50/flow/virtualwirein.js @@ -0,0 +1,43 @@ +exports.id = 'virtualwirein'; +exports.title = 'Virtual wire in'; +exports.version = '1.0.0'; +exports.author = 'Martin Smola'; +exports.color = '#303E4D'; +exports.icon = 'sign-in'; +exports.input = false; +exports.output = 1; +exports.options = {}; +exports.readme = `# Virtual wire in + +When the wires between the components are mess it's time to use Virtual wire.`; + +exports.html = `
+
@(Wire name)
+
+`; + +exports.install = function(instance) { + + instance.custom.reconfigure = function(options){ + if (instance.options.wirename) { + instance.status(instance.options.wirename); + } else + instance.status('Not configured', 'red'); + }; + + ON('virtualwire', function(wirename, flowdata){ + if (instance.options.wirename && instance.options.wirename === wirename) + instance.send(flowdata); + }); + + instance.on('options', instance.custom.reconfigure); + instance.custom.reconfigure(); +}; diff --git a/RVO50/flow/virtualwireout.js b/RVO50/flow/virtualwireout.js new file mode 100755 index 0000000..94a1e4f --- /dev/null +++ b/RVO50/flow/virtualwireout.js @@ -0,0 +1,41 @@ +exports.id = 'virtualwireout'; +exports.title = 'Virtual wire out'; +exports.version = '1.0.0'; +exports.author = 'Martin Smola'; +exports.color = '#303E4D'; +exports.icon = 'sign-out'; +exports.input = true; +exports.options = {}; +exports.readme = `# Virtual wire out + +When the wires between the components are mess it's time to use Virtual wire.`; + +exports.html = `
+
@(Wire name)
+
+`; + +exports.install = function(instance) { + + instance.custom.reconfigure = function(){ + if (instance.options.wirename) { + instance.status(instance.options.wirename); + } else + instance.status('Not configured', 'red'); + }; + + instance.on('data', function(flowdata) { + EMIT('virtualwire', instance.options.wirename, flowdata); + }); + + instance.on('options', instance.custom.reconfigure); + instance.custom.reconfigure(); +}; diff --git a/RVO50/flow/wsmqttpublish.js b/RVO50/flow/wsmqttpublish.js new file mode 100755 index 0000000..0eba804 --- /dev/null +++ b/RVO50/flow/wsmqttpublish.js @@ -0,0 +1,448 @@ +exports.id = 'wsmqttpublish'; +exports.title = 'WS MQTT publish'; +exports.group = 'MQTT'; +exports.color = '#888600'; +exports.version = '1.0.2'; +exports.icon = 'sign-out'; +exports.input = 2; +exports.output = 3; +exports.options = { host: 'tb-stage.worksys.io', port: 1883, clientid: "", username: "" }; + +exports.html = `
+
+
+
Hostname or IP address (if not empty - setting will override db setting)
+
+
+
Port
+
+
+
+
+
@(Client id)
+
+
+
@(Username)
+
+
+
`; + + +exports.readme = ` +# WS MQTT Publish + +Version 1.0.3. + +Added: +- database collections, +- 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 = { + debug: 0, + rpcCall: 1, + services: 2 +} + +//CONFIG +let createTelemetryBackup = true; +let saveTelemetryOnError = true;//backup_on_failure overrides this value +//------------------------ + +let rollers; +if (createTelemetryBackup) rollers = require('streamroller'); + +const noSqlFileSizeLimit = 4194304;//use 5MB - 4194304 +let insertNoSqlCounter = 0; +let insertBackupNoSqlCounter = 0; +let processingData = false; + +let backup_on_failure = false;//== saveTelemetryOnError - create backup client 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; + +process.on('uncaughtException', function(err) { + + errLogger.error('uncaughtException:', err.message) + errLogger.error(err.stack); + + //TODO + //send to service + + //process.exit(1); +}) + +const nosql = NOSQL('tbdata'); +const nosqlBackup = NOSQL('/backup/tbdata'); + + +exports.install = function(instance) { + + var client; + var opts; + var clientReady = false; + + // wsmqtt status for notification purposes on projects.worksys.io database + let wsmqttName = null; + let sendWsStatusVar = null; + let wsmqtt_status = 'disconnected'; + + 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'; + } + + function sendWsStatus() { + instance.send(SEND_TO.services, { [wsmqttName]: wsmqtt_status }); + } + + + function main() { + if (!FLOW.dbLoaded) return; + + loadSettings(); + clearInterval(sendWsStatus); + sendWsStatusVar = setInterval(sendWsStatus, 180000); + } + + //set opts according to db settings + function loadSettings() { + + if (instance.options.host !== "") { + //override settings from database + var o = instance.options; + opts = { + host: o.host, + port: o.port, + clientId: o.clientid, + username: o.username, + rejectUnauthorized: false, + resubscribe: false + }; + + wsmqttName = getWsmqttName(o.host); + + console.log("wsmqttpublich -> loadSettings from instance.options", instance.options); + } + else { + + const SETTINGS = FLOW.GLOBALS.settings; + backup_on_failure = SETTINGS.backup_on_failure; + saveTelemetryOnError = backup_on_failure; + + restore_from_backup = SETTINGS.restore_from_backup; + restore_backup_wait = SETTINGS.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; + + opts = { + host: mqtt_host, + port: mqtt_port, + keepalive: 10, + clientId: mqtt_clientid, + username: mqtt_username, + rejectUnauthorized: false, + resubscribe: false + }; + + wsmqttName = getWsmqttName(mqtt_host); + } + + connectToTbServer(); + } + + function connectToTbServer() { + 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"); + //monitor.info("MQTT client connected"); + + sendClientError = true; + clientReady = true; + wsmqtt_status = 'connected'; + }); + + client.on('reconnect', function() { + instance.status("Reconnecting", "yellow"); + clientReady = false; + }); + + client.on('message', function(topic, message) { + // message is type of buffer + message = message.toString(); + if (message[0] === '{') { + TRY(function() { + + message = JSON.parse(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 } }); + } + + }, () => instance.debug('MQTT: Error parsing data', message)); + } + + instance.send(SEND_TO.rpcCall, { "topic": topic, "content": message }); + }); + + client.on('close', function() { + clientReady = false; + wsmqtt_status = 'disconnected'; + + instance.status("Disconnected", "red"); + instance.send(SEND_TO.debug, { "message": "Client CLOSE signal received !" }); + }); + + client.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; + wsmqtt_status = 'disconnected'; + }); + + } + + + instance.on("0", _ => { + main(); + }) + + + instance.on('1', function(data) { + + if (clientReady) { + //do we have some data in backup file? if any, process data from database + if (saveTelemetryOnError) { + //read telemetry data and send back to server + if (!processingData) processDataFromDatabase(); + } + + let stringifiedJson = JSON.stringify(data.data); + client.publish("v1/gateway/telemetry", stringifiedJson, { qos: 1 }); + + //backup telemetry + if (createTelemetryBackup) { + data.data.id = UID(); + nosqlBackup.insert(data.data); + + insertBackupNoSqlCounter++; + if (insertBackupNoSqlCounter > 150) { + let options = { compress: true }; + let path = __dirname + "/../databases/backup/tbdata.nosql"; + var stream = new rollers.RollingFileStream(path, noSqlFileSizeLimit, 150, options); + stream.write(""); + stream.end(); + + insertBackupNoSqlCounter = 0; + } + } + + } + 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 (saveTelemetryOnError) { + //create new file from tbdata.nosql, if file size exceeds given limit, and clear tbdata.nosql + makeBackupFromDbFile(); + + //write to tb + data.data.id = UID(); + nosql.insert(data.data); + } + } + }); + + + instance.close = function(done) { + if (clientReady) { + client.end(); + clearInterval(sendWsStatusVar); + } + }; + + + function getDbBackupFileCounter(type) { + var files = fs.readdirSync(__dirname + "/../databases"); + + let counter = 0; + for (var i = 0; i < files.length; i++) { + + if (files[i] == "tbdata.nosql") continue; + + if (files[i].endsWith(".nosql")) { + + let pos = files[i].indexOf("."); + if (pos > -1) { + + let fileCounter = counter; + let firstDigit = files[i].slice(0, pos); + + fileCounter = parseInt(firstDigit); + if (isNaN(fileCounter)) fileCounter = 0; + //console.log("getDbBackupFileCounter digit:", files[i], firstDigit, fileCounter, isNaN(fileCounter), type); + + if (type == "max") { + if (fileCounter > counter) { + counter = fileCounter; + } + } + else if (type == "min") { + if (counter == 0) counter = fileCounter; + + if (fileCounter < counter) { + counter = fileCounter; + } + } + } + } + + } + + if (type == "max") counter++; + + return counter; + } + + const makeBackupFromDbFile = async () => { + + if (!saveTelemetryOnError) return; + + //to avoid large file: tbdata.nosql + + //init value is 0! + if (insertNoSqlCounter > 0) { + --insertNoSqlCounter; + return; + } + + insertNoSqlCounter = 100; + + let source = __dirname + "/../databases/tbdata.nosql"; + + var stats = fs.statSync(source); + var fileSizeInBytes = stats.size; + + if (fileSizeInBytes > noSqlFileSizeLimit) { + + let counter = 1; + counter = getDbBackupFileCounter("max"); + + let destination = __dirname + "/../databases/" + counter + "." + "tbdata.nosql"; + + //make backup file + fs.copyFileSync(source, destination); + //fs.renameSync(p, p + "." + counter); + + //clear tbdata.nosql + fs.writeFileSync(source, ""); + fs.truncateSync(source, 0); + + } + } + + const processDataFromDatabase = async () => { + + if (restore_from_backup <= 0) return; + + //calculate diff + const now = new Date(); + let currentTime = now.getTime(); + let diff = currentTime - lastRestoreTime; + + if ((diff / 1000) < restore_backup_wait) { + //console.log("*********restore_backup_wait", diff, restore_backup_wait); + return; + } + + processingData = true; + + //get filename to process + let counter = getDbBackupFileCounter("min"); + + //we have some backup files + let dataBase = 'tbdata'; + + var nosql; + if (counter == 0) dataBase = 'tbdata'; + else dataBase = counter + "." + 'tbdata'; + + nosql = NOSQL(dataBase); + + //select all data - use limit restore_from_backup + let records = await promisifyBuilder(nosql.find().take(restore_from_backup)); + + for (let i = 0; i < records.length; i++) { + if (clientReady) { + + let item = records[i]; + let id = item.id; + + if (id !== undefined) { + //console.log("------------processDataFromDatabase - remove", id, dataBase, i); + + try { + + let message = JSON.parse(JSON.stringify(item)); + delete message.id; + + client.publish("v1/gateway/telemetry", JSON.stringify(message), { qos: 1 }); + + //remove from database + await promisifyBuilder(nosql.remove().where("id", id)); + + } catch (error) { + //process error + console.log("processDataFromDatabase", error); + } + + } + + } + else { + processingData = false; + return; + } + } + + if (records.length > 0) { + //clean backup file + if (counter > 0) nosql.clean(); + } + + //no data in db, remove + if (records.length == 0) { + if (counter > 0) nosql.drop(); + } + + const d = new Date(); + lastRestoreTime = d.getTime(); + + processingData = false; + + } + + instance.on('options', main); + //instance.reconfigure(); +}; diff --git a/RVO50/monitor.txt b/RVO50/monitor.txt new file mode 100755 index 0000000..823b2a9 --- /dev/null +++ b/RVO50/monitor.txt @@ -0,0 +1,506 @@ +[2025-10-03T14:47:02.149] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-03T14:47:07.486] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-03T14:47:07.491] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-03T14:47:07.492] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-03T14:47:07.493] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-03T14:47:07.497] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-03T14:47:07.498] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-10-04T05:24:00.498Z +[2025-10-03T14:47:07.500] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-10-03T16:58:00.499Z +[2025-10-03T14:47:07.500] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:24', name: 'luxOff' }, + { value: 1, start_time: '18:58', name: 'luxOn' } +] +[2025-10-03T14:47:07.502] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-10-03T14:47:07.502] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-03T14:47:07.503] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-03T14:47:07.506] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-03T14:47:07.506] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-10-04T05:24:00.506Z +[2025-10-03T14:47:07.507] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-10-03T16:58:00.507Z +[2025-10-03T14:47:07.508] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:24', name: 'luxOff' }, + { value: 1, start_time: '18:58', name: 'luxOn' } +] +[2025-10-03T14:47:07.509] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-10-03T14:47:07.509] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-03T14:47:07.510] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-03T14:47:07.512] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-03T14:47:07.513] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-10-04T05:24:00.513Z +[2025-10-03T14:47:07.514] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-10-03T16:58:00.514Z +[2025-10-03T14:47:07.514] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:24', name: 'luxOff' }, + { value: 1, start_time: '18:58', name: 'luxOn' } +] +[2025-10-03T14:47:07.515] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-10-03T14:47:07.518] [INFO] monitorLogs - tasks created: 378 +[2025-10-03T14:47:07.520] [INFO] monitorLogs - -->FLOW bol spustený PjLblDgRBO6WQqnxmkJ1g60Jv3ewZN4p5a89yKdY 2025-08-08 +[2025-10-03T14:47:12.527] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-03T18:50:55.963] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-03T18:50:55.969] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-03T18:50:55.972] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-04T03:47:09.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-04 03:47:09 +[2025-10-04T06:36:14.850] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-04T06:36:14.853] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-04T06:36:14.856] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-04T06:38:51.641] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-04T18:37:11.574] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-04T18:37:11.577] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-04T18:37:11.579] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-05T03:47:10.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-05 03:47:10 +[2025-10-05T06:40:12.686] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-05T06:40:12.689] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-05T06:40:12.692] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-05T18:46:24.490] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-05T18:46:24.492] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-05T18:46:24.494] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-06T03:47:12.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-06 03:47:12 +[2025-10-06T06:46:18.583] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-06T06:46:18.589] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-06T06:46:18.592] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-06T18:29:48.349] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-06T18:29:48.354] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-06T18:29:48.356] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-07T03:47:13.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-07 03:47:13 +[2025-10-07T06:43:57.387] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-07T06:43:57.390] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-07T06:43:57.392] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-07T18:36:07.489] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-07T18:36:07.492] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-07T18:36:07.494] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-08T03:47:15.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-08 03:47:15 +[2025-10-08T06:41:34.414] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-08T06:41:34.418] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-08T06:41:34.420] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-08T18:36:19.414] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-08T18:36:19.416] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-08T18:36:19.418] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-09T03:47:16.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-09 03:47:16 +[2025-10-09T06:54:26.342] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-09T06:54:26.345] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-09T06:54:26.347] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-09T16:52:10.547] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-09T16:52:15.887] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-09T16:52:15.892] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-09T16:52:15.893] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-09T16:52:15.894] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-09T16:52:15.898] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T16:52:15.900] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-10-10T05:32:00.899Z +[2025-10-09T16:52:15.901] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-10-09T16:45:00.901Z +[2025-10-09T16:52:15.902] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T16:52:15.903] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-10-09T16:52:15.904] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-09T16:52:15.904] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-09T16:52:15.907] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T16:52:15.907] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-10-10T05:32:00.907Z +[2025-10-09T16:52:15.908] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-10-09T16:45:00.908Z +[2025-10-09T16:52:15.909] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T16:52:15.910] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-10-09T16:52:15.911] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-09T16:52:15.912] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-09T16:52:15.914] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T16:52:15.915] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-10-10T05:32:00.915Z +[2025-10-09T16:52:15.915] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-10-09T16:45:00.915Z +[2025-10-09T16:52:15.916] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T16:52:15.917] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-10-09T16:52:15.920] [INFO] monitorLogs - tasks created: 378 +[2025-10-09T16:52:15.922] [INFO] monitorLogs - -->FLOW bol spustený PjLblDgRBO6WQqnxmkJ1g60Jv3ewZN4p5a89yKdY 2025-08-08 +[2025-10-09T16:52:20.927] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-09T18:29:28.622] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-09T18:29:28.626] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-09T18:29:28.629] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-09T19:04:42.906] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-09T19:04:48.247] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-09T19:04:48.252] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-09T19:04:48.253] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-09T19:04:48.254] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-09T19:04:48.258] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T19:04:48.259] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-10-10T05:32:00.258Z +[2025-10-09T19:04:48.261] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-10-10T16:45:00.260Z +[2025-10-09T19:04:48.261] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T19:04:48.263] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-10-09T19:04:48.263] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-09T19:04:48.264] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-09T19:04:48.266] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T19:04:48.267] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-10-10T05:32:00.267Z +[2025-10-09T19:04:48.268] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-10-10T16:45:00.268Z +[2025-10-09T19:04:48.269] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T19:04:48.270] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-10-09T19:04:48.270] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-09T19:04:48.271] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-09T19:04:48.273] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T19:04:48.274] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-10-10T05:32:00.274Z +[2025-10-09T19:04:48.275] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-10-10T16:45:00.274Z +[2025-10-09T19:04:48.275] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T19:04:48.276] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-10-09T19:04:48.279] [INFO] monitorLogs - tasks created: 378 +[2025-10-09T19:04:48.281] [INFO] monitorLogs - -->FLOW bol spustený PjLblDgRBO6WQqnxmkJ1g60Jv3ewZN4p5a89yKdY 2025-08-08 +[2025-10-09T19:04:53.286] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-10T03:04:50.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-10 03:04:50 +[2025-10-10T06:51:41.597] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-10T06:51:41.601] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-10T06:51:41.603] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-10T18:23:57.424] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-10T18:23:57.426] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-10T18:23:57.428] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-10T20:04:49.875] [INFO] monitorLogs - Thermometer is not responding Error: Command failed: owread -C 28.990C9D0E0000/temperature +ServerRead: Data error on 28.990C9D0E0000/temperature + + at ChildProcess.exithandler (child_process.js:383:12) + at ChildProcess.emit (events.js:400:28) + at maybeClose (internal/child_process.js:1058:16) + at Socket. (internal/child_process.js:443:11) + at Socket.emit (events.js:400:28) + at Pipe. (net.js:686:12) { + killed: false, + code: 1, + signal: null, + cmd: 'owread -C 28.990C9D0E0000/temperature' +} +[2025-10-11T03:04:51.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-11 03:04:51 +[2025-10-11T06:54:03.155] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-11T06:54:03.158] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-11T06:54:03.160] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-11T18:27:08.049] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-11T18:27:08.057] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-11T18:27:08.059] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-12T03:04:52.021] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-12 03:04:52 +[2025-10-12T06:52:25.365] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-12T06:52:25.368] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-12T06:52:25.370] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-12T18:23:53.036] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-12T18:23:53.039] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-12T18:23:53.041] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-13T03:04:54.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-13 03:04:54 +[2025-10-13T06:50:36.992] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-13T06:50:36.995] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-13T06:50:36.997] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-13T10:59:54.076] [INFO] monitorLogs - Thermometer is not responding Error: Command failed: owread -C 28.990C9D0E0000/temperature +ServerRead: Data error on 28.990C9D0E0000/temperature + + at ChildProcess.exithandler (child_process.js:383:12) + at ChildProcess.emit (events.js:400:28) + at maybeClose (internal/child_process.js:1058:16) + at Socket. (internal/child_process.js:443:11) + at Socket.emit (events.js:400:28) + at Pipe. (net.js:686:12) { + killed: false, + code: 1, + signal: null, + cmd: 'owread -C 28.990C9D0E0000/temperature' +} +[2025-10-13T18:33:12.562] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-13T18:33:12.565] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-13T18:33:12.567] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-14T03:04:55.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-14 03:04:55 +[2025-10-14T06:53:13.723] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-14T06:53:13.726] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-14T06:53:13.728] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-14T18:22:02.546] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-14T18:22:02.548] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-14T18:22:02.550] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-14T23:54:55.194] [INFO] monitorLogs - Thermometer is not responding Error: Command failed: owread -C 28.990C9D0E0000/temperature +ServerRead: Data error on 28.990C9D0E0000/temperature + + at ChildProcess.exithandler (child_process.js:383:12) + at ChildProcess.emit (events.js:400:28) + at maybeClose (internal/child_process.js:1058:16) + at Socket. (internal/child_process.js:443:11) + at Socket.emit (events.js:400:28) + at Pipe. (net.js:686:12) { + killed: false, + code: 1, + signal: null, + cmd: 'owread -C 28.990C9D0E0000/temperature' +} +[2025-10-15T03:04:57.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-15 03:04:57 +[2025-10-15T05:34:57.226] [INFO] monitorLogs - Thermometer is not responding Error: Command failed: owread -C 28.990C9D0E0000/temperature +ServerRead: Data error on 28.990C9D0E0000/temperature + + at ChildProcess.exithandler (child_process.js:383:12) + at ChildProcess.emit (events.js:400:28) + at maybeClose (internal/child_process.js:1058:16) + at Socket. (internal/child_process.js:443:11) + at Socket.emit (events.js:400:28) + at Pipe. (net.js:686:12) { + killed: false, + code: 1, + signal: null, + cmd: 'owread -C 28.990C9D0E0000/temperature' +} +[2025-10-15T06:56:15.146] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-15T06:56:15.148] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-15T06:56:15.150] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-15T14:11:15.348] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-15T14:11:20.685] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-15T14:11:20.690] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-15T14:11:20.691] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-15T14:11:20.691] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-15T14:11:20.695] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-15T14:11:20.697] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-10-16T05:41:00.696Z +[2025-10-15T14:11:20.698] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-10-15T16:33:00.698Z +[2025-10-15T14:11:20.699] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:41', name: 'luxOff' }, + { value: 1, start_time: '18:33', name: 'luxOn' } +] +[2025-10-15T14:11:20.700] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-10-15T14:11:20.701] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-15T14:11:20.702] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-15T14:11:20.704] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-15T14:11:20.705] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-10-16T05:41:00.704Z +[2025-10-15T14:11:20.706] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-10-15T16:33:00.705Z +[2025-10-15T14:11:20.706] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:41', name: 'luxOff' }, + { value: 1, start_time: '18:33', name: 'luxOn' } +] +[2025-10-15T14:11:20.707] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-10-15T14:11:20.708] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-15T14:11:20.708] [INFO] monitorLogs - profile: { + 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 +} +[2025-10-15T14:11:20.711] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-15T14:11:20.711] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-10-16T05:41:00.711Z +[2025-10-15T14:11:20.712] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-10-15T16:33:00.712Z +[2025-10-15T14:11:20.713] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:41', name: 'luxOff' }, + { value: 1, start_time: '18:33', name: 'luxOn' } +] +[2025-10-15T14:11:20.714] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-10-15T14:11:20.716] [INFO] monitorLogs - tasks created: 378 +[2025-10-15T14:11:20.719] [INFO] monitorLogs - -->FLOW bol spustený PjLblDgRBO6WQqnxmkJ1g60Jv3ewZN4p5a89yKdY 2025-10-08 +[2025-10-15T14:11:25.740] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-15T18:19:34.296] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-15T18:19:34.302] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-15T18:19:34.305] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-16T00:56:20.714] [INFO] monitorLogs - Thermometer is not responding Error: Command failed: owread -C 28.990C9D0E0000/temperature +ServerRead: Data error on 28.990C9D0E0000/temperature + + at ChildProcess.exithandler (child_process.js:383:12) + at ChildProcess.emit (events.js:400:28) + at maybeClose (internal/child_process.js:1058:16) + at Socket. (internal/child_process.js:443:11) + at Socket.emit (events.js:400:28) + at Pipe. (net.js:686:12) { + killed: false, + code: 1, + signal: null, + cmd: 'owread -C 28.990C9D0E0000/temperature' +} diff --git a/RVO50/package-lock.json b/RVO50/package-lock.json new file mode 100755 index 0000000..cc5cfd9 --- /dev/null +++ b/RVO50/package-lock.json @@ -0,0 +1,2125 @@ +{ + "name": "emptyproject", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "emptyproject", + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "bitwise": "^2.1.0", + "easy-crc": "0.0.2", + "jsmodbus": "^4.0.6", + "log4js": "^6.3.0", + "mqtt": "^4.2.6", + "nodemailer": "^6.9.7", + "serialport": "^9.2.8", + "total.js": "^3.4.13" + } + }, + "node_modules/@serialport/binding-abstract": { + "version": "9.2.3", + "resolved": "https://registry.npmjs.org/@serialport/binding-abstract/-/binding-abstract-9.2.3.tgz", + "integrity": "sha512-cQs9tbIlG3P0IrOWyVirqlhWuJ7Ms2Zh9m2108z6Y5UW/iVj6wEOiW8EmK9QX9jmJXYllE7wgGgvVozP5oCj3w==", + "dependencies": { + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/binding-mock": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/binding-mock/-/binding-mock-9.2.4.tgz", + "integrity": "sha512-dpEhACCs44oQhh6ajJfJdvQdK38Vq0N4W6iD/gdplglDCK7qXRQCMUjJIeKdS/HSEiWkC3bwumUhUufdsOyT4g==", + "dependencies": { + "@serialport/binding-abstract": "9.2.3", + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/bindings": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/@serialport/bindings/-/bindings-9.2.8.tgz", + "integrity": "sha512-hSLxTe0tADZ3LMMGwvEJWOC/TaFQTyPeFalUCsJ1lSQ0k6bPF04JwrtB/C81GetmDBTNRY0GlD0SNtKCc7Dr5g==", + "hasInstallScript": true, + "dependencies": { + "@serialport/binding-abstract": "9.2.3", + "@serialport/parser-readline": "9.2.4", + "bindings": "^1.5.0", + "debug": "^4.3.2", + "nan": "^2.15.0", + "prebuild-install": "^7.0.0" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-byte-length": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-byte-length/-/parser-byte-length-9.2.4.tgz", + "integrity": "sha512-sQD/iw4ZMU3xW9PLi0/GlvU6Y623jGeWecbMkO7izUo/6P7gtfv1c9ikd5h0kwL8AoAOpQA1lxdHIKox+umBUg==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-cctalk": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-cctalk/-/parser-cctalk-9.2.4.tgz", + "integrity": "sha512-T4TU5vQMwmo9AB3gQLFDWbfJXlW5jd9guEsB/nqKjFHTv0FXPdZ7DQ2TpSp8RnHWxU3GX6kYTaDO20BKzc8GPQ==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-delimiter": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-delimiter/-/parser-delimiter-9.2.4.tgz", + "integrity": "sha512-4nvTAoYAgkxFiXrkI+3CA49Yd43CODjeszh89EK+I9c8wOZ+etZduRCzINYPiy26g7zO+GRAb9FoPCsY+sYcbQ==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-inter-byte-timeout": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-inter-byte-timeout/-/parser-inter-byte-timeout-9.2.4.tgz", + "integrity": "sha512-SOAdvr0oBQIOCXX198hiTlxs4JTKg9j5piapw5tNq52fwDOWdbYrFneT/wN04UTMKaDrJuEvXq6T4rv4j7nJ5A==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-readline": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-readline/-/parser-readline-9.2.4.tgz", + "integrity": "sha512-Z1/qrZTQUVhNSJP1hd9YfDvq0o7d87rNwAjjRKbVpa7Qi51tG5BnKt43IV3NFMyBlVcRe0rnIb3tJu57E0SOwg==", + "dependencies": { + "@serialport/parser-delimiter": "9.2.4" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-ready": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-ready/-/parser-ready-9.2.4.tgz", + "integrity": "sha512-Pyi94Itjl6qAURwIZr/gmZpMAyTmKXThm6vL5DoAWGQjcRHWB0gwv2TY2v7N+mQLJYUKU3cMnvnATXxHm7xjxw==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-regex": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-regex/-/parser-regex-9.2.4.tgz", + "integrity": "sha512-sI/cVvPOYz+Dbv4ZdnW16qAwvXiFf/1pGASQdbveRTlgJDdz7sRNlCBifzfTN2xljwvCTZYqiudKvDdC1TepRQ==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/stream": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/stream/-/stream-9.2.4.tgz", + "integrity": "sha512-bLye8Ub4vUFQGmkh8qEqehr7SE7EJs2yDs0h9jzuL5oKi+F34CFmWkEErO8GAOQ8YNn7p6b3GxUgs+0BrHHDZQ==", + "dependencies": { + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "node_modules/are-we-there-yet": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", + "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/base64-js": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", + "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==" + }, + "node_modules/bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "dependencies": { + "file-uri-to-path": "1.0.0" + } + }, + "node_modules/bitwise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/bitwise/-/bitwise-2.1.0.tgz", + "integrity": "sha512-XKgAhMXCh4H/3oNwAHAsAO0iC89s9cOiumgYwSHjSobGWxYjv62YhkL9QEdvGP151xypCtMlAfKK79GEcd2eRQ==" + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/bl/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/buffer": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz", + "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==", + "dependencies": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + }, + "node_modules/buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" + }, + "node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, + "node_modules/code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/commist": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/commist/-/commist-1.1.0.tgz", + "integrity": "sha512-rraC8NXWOEjhADbZe9QBNzLAN5Q3fsTPQtBV+fEVj6xKIgDgNiEVE6ZNfHpZOqfQ21YUzfVNUXLOEZquYvQPPg==", + "dependencies": { + "leven": "^2.1.0", + "minimist": "^1.1.0" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "node_modules/concat-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", + "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", + "engines": [ + "node >= 6.0" + ], + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.0.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/concat-stream/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" + }, + "node_modules/core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "node_modules/crc": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/crc/-/crc-3.4.0.tgz", + "integrity": "sha512-ycVC2+4/DLgXXq7QweYi2znhqDuZz6P5TQXnkQo8v15XY/5p/IWeZwsSE31Ifo8w15b8TWLsqhXOjXyilHuQxw==" + }, + "node_modules/date-format": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.11.tgz", + "integrity": "sha512-VS20KRyorrbMCQmpdl2hg5KaOUsda1RbnsJg461FfrcyCUg+pkd0b40BSW4niQyTheww4DBXQnS7HwSrKkipLw==", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" + }, + "node_modules/detect-libc": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz", + "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==", + "engines": { + "node": ">=8" + } + }, + "node_modules/duplexify": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.2.tgz", + "integrity": "sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw==", + "dependencies": { + "end-of-stream": "^1.4.1", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1", + "stream-shift": "^1.0.0" + } + }, + "node_modules/duplexify/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/easy-crc": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/easy-crc/-/easy-crc-0.0.2.tgz", + "integrity": "sha512-h6eqIdhJRe0p271/xZJbM/0klCi13mW5IB7ZEzEGH11yV4QXWAkD4yPErz0fXdhFrd6sZ4Q1k5Iky2kMsMNePw==" + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" + }, + "node_modules/flatted": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", + "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==" + }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, + "node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "node_modules/gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha512-14x4kjc6lkD3ltw589k0NrPD6cCNTD6CWoVUNpB85+DrtONoZn+Rug6xZU5RvSC4+TZPxA5AnBibQYAvZn41Hg==", + "dependencies": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "node_modules/github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==" + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" + }, + "node_modules/has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" + }, + "node_modules/help-me": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/help-me/-/help-me-3.0.0.tgz", + "integrity": "sha512-hx73jClhyk910sidBB7ERlnhMlFsJJIBqSVMFDwPN8o2v9nmp5KgLq1Xz1Bf1fCMMZ6mPrX159iG0VLy/fPMtQ==", + "dependencies": { + "glob": "^7.1.6", + "readable-stream": "^3.6.0" + } + }, + "node_modules/help-me/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, + "node_modules/is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==", + "dependencies": { + "number-is-nan": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "node_modules/js-sdsl": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz", + "integrity": "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/js-sdsl" + } + }, + "node_modules/jsmodbus": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/jsmodbus/-/jsmodbus-4.0.6.tgz", + "integrity": "sha512-gCmjoaERErK5Rn9Lu/BN07fY13MoWV7JKgGzrnkPlQPdPxYcwDhLtYcmpFFpZ4J9NPZZBSezi1UkLZO/DnNppA==", + "dependencies": { + "crc": "3.4.0", + "debug": "^3.1.0" + }, + "bin": { + "jsmodbus": "bin/jsmodbus.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/jsmodbus/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/leven": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", + "integrity": "sha1-wuep93IJTe6dNCAq6KzORoeHVYA=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/log4js": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.5.2.tgz", + "integrity": "sha512-DXtpNtt+KDOMT7RHUDIur/WsSA3rntlUh9Zg4XCdV42wUuMmbFkl38+LZ92Z5QvQA7mD5kAVkLiBSEH/tvUB8A==", + "dependencies": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "flatted": "^3.2.5", + "rfdc": "^1.3.0", + "streamroller": "^3.1.1" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" + }, + "node_modules/mqtt": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/mqtt/-/mqtt-4.3.7.tgz", + "integrity": "sha512-ew3qwG/TJRorTz47eW46vZ5oBw5MEYbQZVaEji44j5lAUSQSqIEoul7Kua/BatBW0H0kKQcC9kwUHa1qzaWHSw==", + "dependencies": { + "commist": "^1.0.0", + "concat-stream": "^2.0.0", + "debug": "^4.1.1", + "duplexify": "^4.1.1", + "help-me": "^3.0.0", + "inherits": "^2.0.3", + "lru-cache": "^6.0.0", + "minimist": "^1.2.5", + "mqtt-packet": "^6.8.0", + "number-allocator": "^1.0.9", + "pump": "^3.0.0", + "readable-stream": "^3.6.0", + "reinterval": "^1.1.0", + "rfdc": "^1.3.0", + "split2": "^3.1.0", + "ws": "^7.5.5", + "xtend": "^4.0.2" + }, + "bin": { + "mqtt": "bin/mqtt.js", + "mqtt_pub": "bin/pub.js", + "mqtt_sub": "bin/sub.js" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/mqtt-packet": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/mqtt-packet/-/mqtt-packet-6.10.0.tgz", + "integrity": "sha512-ja8+mFKIHdB1Tpl6vac+sktqy3gA8t9Mduom1BA75cI+R9AHnZOiaBQwpGiWnaVJLDGRdNhQmFaAqd7tkKSMGA==", + "dependencies": { + "bl": "^4.0.2", + "debug": "^4.1.1", + "process-nextick-args": "^2.0.1" + } + }, + "node_modules/mqtt/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/nan": { + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.16.0.tgz", + "integrity": "sha512-UdAqHyFngu7TfQKsCBgAA6pWDkT8MAO7d0jyOecVhN5354xbLqdn8mV9Tat9gepAupm0bt2DbeaSC8vS52MuFA==" + }, + "node_modules/napi-build-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", + "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==" + }, + "node_modules/node-abi": { + "version": "3.22.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.22.0.tgz", + "integrity": "sha512-u4uAs/4Zzmp/jjsD9cyFYDXeISfUWaAVWshPmDZOFOv4Xl4SbzTXm53I04C2uRueYJ+0t5PEtLH/owbn2Npf/w==", + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/nodemailer": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.7.tgz", + "integrity": "sha512-rUtR77ksqex/eZRLmQ21LKVH5nAAsVicAtAYudK7JgwenEDZ0UIQ1adUGqErz7sMkWYxWTTU1aeP2Jga6WQyJw==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "dependencies": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "node_modules/number-allocator": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/number-allocator/-/number-allocator-1.0.14.tgz", + "integrity": "sha512-OrL44UTVAvkKdOdRQZIJpLkAdjXGTRda052sN4sO77bKEzYYqWKMBjQvrJFzqygI99gL6Z4u2xctPW1tB8ErvA==", + "dependencies": { + "debug": "^4.3.1", + "js-sdsl": "4.3.0" + } + }, + "node_modules/number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/prebuild-install": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.0.tgz", + "integrity": "sha512-CNcMgI1xBypOyGqjp3wOc8AAo1nMhZS3Cwd3iHIxOdAUbb+YxdNuM4Z5iIrZ8RLvOsf3F3bl7b7xGq6DjQoNYA==", + "dependencies": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^1.0.1", + "node-abi": "^3.3.0", + "npmlog": "^4.0.1", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + }, + "bin": { + "prebuild-install": "bin.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/reinterval": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reinterval/-/reinterval-1.1.0.tgz", + "integrity": "sha1-M2Hs+jymwYKDOA3Qu5VG85D17Oc=" + }, + "node_modules/rfdc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==" + }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/serialport": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/serialport/-/serialport-9.2.8.tgz", + "integrity": "sha512-FsWpMQgSJxi93JgWl5xM1f9/Z8IjRJuaUEoHqLf8FPBLw7gMhInuHOBhI2onQufWIYPGTz3H3oGcu1nCaK1EfA==", + "dependencies": { + "@serialport/binding-mock": "9.2.4", + "@serialport/bindings": "9.2.8", + "@serialport/parser-byte-length": "9.2.4", + "@serialport/parser-cctalk": "9.2.4", + "@serialport/parser-delimiter": "9.2.4", + "@serialport/parser-inter-byte-timeout": "9.2.4", + "@serialport/parser-readline": "9.2.4", + "@serialport/parser-ready": "9.2.4", + "@serialport/parser-regex": "9.2.4", + "@serialport/stream": "9.2.4", + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "node_modules/split2": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", + "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", + "dependencies": { + "readable-stream": "^3.0.0" + } + }, + "node_modules/split2/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==" + }, + "node_modules/streamroller": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.1.1.tgz", + "integrity": "sha512-iPhtd9unZ6zKdWgMeYGfSBuqCngyJy1B/GPi/lTpwGpa3bajuX30GjUVd0/Tn/Xhg0mr4DOSENozz9Y06qyonQ==", + "dependencies": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "fs-extra": "^10.1.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dependencies": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/tar-fs": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "dependencies": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tar-stream/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/total.js": { + "version": "3.4.13", + "resolved": "https://registry.npmjs.org/total.js/-/total.js-3.4.13.tgz", + "integrity": "sha512-lAH4gEixlPFbrE3xfKADAcHfO79IFq2wKa9GTsrgRzIR5MTg3mNH7+4IxvX1pK8faoYb/0oYSJ1YTsAa5hIFFQ==", + "bin": { + "total": "bin/totaljs", + "total.js": "bin/totaljs", + "totaljs": "bin/totaljs", + "totalpackage": "bin/tpm", + "tpm": "bin/tpm" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, + "node_modules/universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "node_modules/wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "node_modules/ws": { + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } + }, + "dependencies": { + "@serialport/binding-abstract": { + "version": "9.2.3", + "resolved": "https://registry.npmjs.org/@serialport/binding-abstract/-/binding-abstract-9.2.3.tgz", + "integrity": "sha512-cQs9tbIlG3P0IrOWyVirqlhWuJ7Ms2Zh9m2108z6Y5UW/iVj6wEOiW8EmK9QX9jmJXYllE7wgGgvVozP5oCj3w==", + "requires": { + "debug": "^4.3.2" + } + }, + "@serialport/binding-mock": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/binding-mock/-/binding-mock-9.2.4.tgz", + "integrity": "sha512-dpEhACCs44oQhh6ajJfJdvQdK38Vq0N4W6iD/gdplglDCK7qXRQCMUjJIeKdS/HSEiWkC3bwumUhUufdsOyT4g==", + "requires": { + "@serialport/binding-abstract": "9.2.3", + "debug": "^4.3.2" + } + }, + "@serialport/bindings": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/@serialport/bindings/-/bindings-9.2.8.tgz", + "integrity": "sha512-hSLxTe0tADZ3LMMGwvEJWOC/TaFQTyPeFalUCsJ1lSQ0k6bPF04JwrtB/C81GetmDBTNRY0GlD0SNtKCc7Dr5g==", + "requires": { + "@serialport/binding-abstract": "9.2.3", + "@serialport/parser-readline": "9.2.4", + "bindings": "^1.5.0", + "debug": "^4.3.2", + "nan": "^2.15.0", + "prebuild-install": "^7.0.0" + } + }, + "@serialport/parser-byte-length": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-byte-length/-/parser-byte-length-9.2.4.tgz", + "integrity": "sha512-sQD/iw4ZMU3xW9PLi0/GlvU6Y623jGeWecbMkO7izUo/6P7gtfv1c9ikd5h0kwL8AoAOpQA1lxdHIKox+umBUg==" + }, + "@serialport/parser-cctalk": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-cctalk/-/parser-cctalk-9.2.4.tgz", + "integrity": "sha512-T4TU5vQMwmo9AB3gQLFDWbfJXlW5jd9guEsB/nqKjFHTv0FXPdZ7DQ2TpSp8RnHWxU3GX6kYTaDO20BKzc8GPQ==" + }, + "@serialport/parser-delimiter": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-delimiter/-/parser-delimiter-9.2.4.tgz", + "integrity": "sha512-4nvTAoYAgkxFiXrkI+3CA49Yd43CODjeszh89EK+I9c8wOZ+etZduRCzINYPiy26g7zO+GRAb9FoPCsY+sYcbQ==" + }, + "@serialport/parser-inter-byte-timeout": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-inter-byte-timeout/-/parser-inter-byte-timeout-9.2.4.tgz", + "integrity": "sha512-SOAdvr0oBQIOCXX198hiTlxs4JTKg9j5piapw5tNq52fwDOWdbYrFneT/wN04UTMKaDrJuEvXq6T4rv4j7nJ5A==" + }, + "@serialport/parser-readline": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-readline/-/parser-readline-9.2.4.tgz", + "integrity": "sha512-Z1/qrZTQUVhNSJP1hd9YfDvq0o7d87rNwAjjRKbVpa7Qi51tG5BnKt43IV3NFMyBlVcRe0rnIb3tJu57E0SOwg==", + "requires": { + "@serialport/parser-delimiter": "9.2.4" + } + }, + "@serialport/parser-ready": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-ready/-/parser-ready-9.2.4.tgz", + "integrity": "sha512-Pyi94Itjl6qAURwIZr/gmZpMAyTmKXThm6vL5DoAWGQjcRHWB0gwv2TY2v7N+mQLJYUKU3cMnvnATXxHm7xjxw==" + }, + "@serialport/parser-regex": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-regex/-/parser-regex-9.2.4.tgz", + "integrity": "sha512-sI/cVvPOYz+Dbv4ZdnW16qAwvXiFf/1pGASQdbveRTlgJDdz7sRNlCBifzfTN2xljwvCTZYqiudKvDdC1TepRQ==" + }, + "@serialport/stream": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/stream/-/stream-9.2.4.tgz", + "integrity": "sha512-bLye8Ub4vUFQGmkh8qEqehr7SE7EJs2yDs0h9jzuL5oKi+F34CFmWkEErO8GAOQ8YNn7p6b3GxUgs+0BrHHDZQ==", + "requires": { + "debug": "^4.3.2" + } + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==" + }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "are-we-there-yet": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", + "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "base64-js": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", + "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==" + }, + "bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "requires": { + "file-uri-to-path": "1.0.0" + } + }, + "bitwise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/bitwise/-/bitwise-2.1.0.tgz", + "integrity": "sha512-XKgAhMXCh4H/3oNwAHAsAO0iC89s9cOiumgYwSHjSobGWxYjv62YhkL9QEdvGP151xypCtMlAfKK79GEcd2eRQ==" + }, + "bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "requires": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "buffer": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz", + "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==", + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" + }, + "chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==" + }, + "commist": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/commist/-/commist-1.1.0.tgz", + "integrity": "sha512-rraC8NXWOEjhADbZe9QBNzLAN5Q3fsTPQtBV+fEVj6xKIgDgNiEVE6ZNfHpZOqfQ21YUzfVNUXLOEZquYvQPPg==", + "requires": { + "leven": "^2.1.0", + "minimist": "^1.1.0" + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "concat-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", + "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.0.2", + "typedarray": "^0.0.6" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "crc": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/crc/-/crc-3.4.0.tgz", + "integrity": "sha512-ycVC2+4/DLgXXq7QweYi2znhqDuZz6P5TQXnkQo8v15XY/5p/IWeZwsSE31Ifo8w15b8TWLsqhXOjXyilHuQxw==" + }, + "date-format": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.11.tgz", + "integrity": "sha512-VS20KRyorrbMCQmpdl2hg5KaOUsda1RbnsJg461FfrcyCUg+pkd0b40BSW4niQyTheww4DBXQnS7HwSrKkipLw==" + }, + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "requires": { + "ms": "2.1.2" + } + }, + "decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "requires": { + "mimic-response": "^3.1.0" + } + }, + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==" + }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" + }, + "detect-libc": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz", + "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==" + }, + "duplexify": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.2.tgz", + "integrity": "sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw==", + "requires": { + "end-of-stream": "^1.4.1", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1", + "stream-shift": "^1.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "easy-crc": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/easy-crc/-/easy-crc-0.0.2.tgz", + "integrity": "sha512-h6eqIdhJRe0p271/xZJbM/0klCi13mW5IB7ZEzEGH11yV4QXWAkD4yPErz0fXdhFrd6sZ4Q1k5Iky2kMsMNePw==" + }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "requires": { + "once": "^1.4.0" + } + }, + "expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==" + }, + "file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" + }, + "flatted": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", + "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==" + }, + "fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, + "fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha512-14x4kjc6lkD3ltw589k0NrPD6cCNTD6CWoVUNpB85+DrtONoZn+Rug6xZU5RvSC4+TZPxA5AnBibQYAvZn41Hg==", + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==" + }, + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" + }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" + }, + "help-me": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/help-me/-/help-me-3.0.0.tgz", + "integrity": "sha512-hx73jClhyk910sidBB7ERlnhMlFsJJIBqSVMFDwPN8o2v9nmp5KgLq1Xz1Bf1fCMMZ6mPrX159iG0VLy/fPMtQ==", + "requires": { + "glob": "^7.1.6", + "readable-stream": "^3.6.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==", + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "js-sdsl": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz", + "integrity": "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==" + }, + "jsmodbus": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/jsmodbus/-/jsmodbus-4.0.6.tgz", + "integrity": "sha512-gCmjoaERErK5Rn9Lu/BN07fY13MoWV7JKgGzrnkPlQPdPxYcwDhLtYcmpFFpZ4J9NPZZBSezi1UkLZO/DnNppA==", + "requires": { + "crc": "3.4.0", + "debug": "^3.1.0" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "requires": { + "ms": "^2.1.1" + } + } + } + }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, + "leven": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", + "integrity": "sha1-wuep93IJTe6dNCAq6KzORoeHVYA=" + }, + "log4js": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.5.2.tgz", + "integrity": "sha512-DXtpNtt+KDOMT7RHUDIur/WsSA3rntlUh9Zg4XCdV42wUuMmbFkl38+LZ92Z5QvQA7mD5kAVkLiBSEH/tvUB8A==", + "requires": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "flatted": "^3.2.5", + "rfdc": "^1.3.0", + "streamroller": "^3.1.1" + } + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "requires": { + "yallist": "^4.0.0" + } + }, + "mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==" + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==" + }, + "mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" + }, + "mqtt": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/mqtt/-/mqtt-4.3.7.tgz", + "integrity": "sha512-ew3qwG/TJRorTz47eW46vZ5oBw5MEYbQZVaEji44j5lAUSQSqIEoul7Kua/BatBW0H0kKQcC9kwUHa1qzaWHSw==", + "requires": { + "commist": "^1.0.0", + "concat-stream": "^2.0.0", + "debug": "^4.1.1", + "duplexify": "^4.1.1", + "help-me": "^3.0.0", + "inherits": "^2.0.3", + "lru-cache": "^6.0.0", + "minimist": "^1.2.5", + "mqtt-packet": "^6.8.0", + "number-allocator": "^1.0.9", + "pump": "^3.0.0", + "readable-stream": "^3.6.0", + "reinterval": "^1.1.0", + "rfdc": "^1.3.0", + "split2": "^3.1.0", + "ws": "^7.5.5", + "xtend": "^4.0.2" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "mqtt-packet": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/mqtt-packet/-/mqtt-packet-6.10.0.tgz", + "integrity": "sha512-ja8+mFKIHdB1Tpl6vac+sktqy3gA8t9Mduom1BA75cI+R9AHnZOiaBQwpGiWnaVJLDGRdNhQmFaAqd7tkKSMGA==", + "requires": { + "bl": "^4.0.2", + "debug": "^4.1.1", + "process-nextick-args": "^2.0.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "nan": { + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.16.0.tgz", + "integrity": "sha512-UdAqHyFngu7TfQKsCBgAA6pWDkT8MAO7d0jyOecVhN5354xbLqdn8mV9Tat9gepAupm0bt2DbeaSC8vS52MuFA==" + }, + "napi-build-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", + "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==" + }, + "node-abi": { + "version": "3.22.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.22.0.tgz", + "integrity": "sha512-u4uAs/4Zzmp/jjsD9cyFYDXeISfUWaAVWshPmDZOFOv4Xl4SbzTXm53I04C2uRueYJ+0t5PEtLH/owbn2Npf/w==", + "requires": { + "semver": "^7.3.5" + } + }, + "nodemailer": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.7.tgz", + "integrity": "sha512-rUtR77ksqex/eZRLmQ21LKVH5nAAsVicAtAYudK7JgwenEDZ0UIQ1adUGqErz7sMkWYxWTTU1aeP2Jga6WQyJw==" + }, + "npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "number-allocator": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/number-allocator/-/number-allocator-1.0.14.tgz", + "integrity": "sha512-OrL44UTVAvkKdOdRQZIJpLkAdjXGTRda052sN4sO77bKEzYYqWKMBjQvrJFzqygI99gL6Z4u2xctPW1tB8ErvA==", + "requires": { + "debug": "^4.3.1", + "js-sdsl": "4.3.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==" + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==" + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==" + }, + "prebuild-install": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.0.tgz", + "integrity": "sha512-CNcMgI1xBypOyGqjp3wOc8AAo1nMhZS3Cwd3iHIxOdAUbb+YxdNuM4Z5iIrZ8RLvOsf3F3bl7b7xGq6DjQoNYA==", + "requires": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^1.0.1", + "node-abi": "^3.3.0", + "npmlog": "^4.0.1", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + } + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + } + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "reinterval": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reinterval/-/reinterval-1.1.0.tgz", + "integrity": "sha1-M2Hs+jymwYKDOA3Qu5VG85D17Oc=" + }, + "rfdc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==" + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "requires": { + "lru-cache": "^6.0.0" + } + }, + "serialport": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/serialport/-/serialport-9.2.8.tgz", + "integrity": "sha512-FsWpMQgSJxi93JgWl5xM1f9/Z8IjRJuaUEoHqLf8FPBLw7gMhInuHOBhI2onQufWIYPGTz3H3oGcu1nCaK1EfA==", + "requires": { + "@serialport/binding-mock": "9.2.4", + "@serialport/bindings": "9.2.8", + "@serialport/parser-byte-length": "9.2.4", + "@serialport/parser-cctalk": "9.2.4", + "@serialport/parser-delimiter": "9.2.4", + "@serialport/parser-inter-byte-timeout": "9.2.4", + "@serialport/parser-readline": "9.2.4", + "@serialport/parser-ready": "9.2.4", + "@serialport/parser-regex": "9.2.4", + "@serialport/stream": "9.2.4", + "debug": "^4.3.2" + } + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==" + }, + "simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "requires": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "split2": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", + "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", + "requires": { + "readable-stream": "^3.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==" + }, + "streamroller": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.1.1.tgz", + "integrity": "sha512-iPhtd9unZ6zKdWgMeYGfSBuqCngyJy1B/GPi/lTpwGpa3bajuX30GjUVd0/Tn/Xhg0mr4DOSENozz9Y06qyonQ==", + "requires": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "fs-extra": "^10.1.0" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" + }, + "tar-fs": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "requires": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "requires": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "total.js": { + "version": "3.4.13", + "resolved": "https://registry.npmjs.org/total.js/-/total.js-3.4.13.tgz", + "integrity": "sha512-lAH4gEixlPFbrE3xfKADAcHfO79IFq2wKa9GTsrgRzIR5MTg3mNH7+4IxvX1pK8faoYb/0oYSJ1YTsAa5hIFFQ==" + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, + "universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==" + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "requires": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "ws": { + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "requires": {} + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } + } +} diff --git a/RVO50/package.json b/RVO50/package.json new file mode 100755 index 0000000..e524d7c --- /dev/null +++ b/RVO50/package.json @@ -0,0 +1,29 @@ +{ + "name": "emptyproject", + "description": "Total.js empty project.", + "version": "1.0.0", + "main": "debug.js", + "dependencies": { + "bitwise": "^2.1.0", + "easy-crc": "0.0.2", + "jsmodbus": "^4.0.6", + "log4js": "^6.3.0", + "mqtt": "^4.2.6", + "nodemailer": "^6.9.7", + "serialport": "^9.2.8", + "total.js": "^3.4.13" + }, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "https://github.com/totaljs/emptyproject-flow" + }, + "keywords": [ + "empty", + "project" + ], + "author": "Peter Širka", + "license": "MIT" +} diff --git a/RVO50/release.js b/RVO50/release.js new file mode 100755 index 0000000..02d52ff --- /dev/null +++ b/RVO50/release.js @@ -0,0 +1,15 @@ +// =================================================== +// FOR PRODUCTION +// Total.js - framework for Node.js platform +// https://www.totaljs.com +// =================================================== + +const options = {'ip':'0.0.0.0', 'port':12345}; + +// options.ip = '127.0.0.1'; +// options.port = parseInt(process.argv[2]); +// options.config = { name: 'Total.js' }; +// options.sleep = 3000; + +require('total.js').http('release', options); +// require('total.js').cluster.http(5, 'release', options); diff --git a/RVO50/release.js.json b/RVO50/release.js.json new file mode 100755 index 0000000..4669435 --- /dev/null +++ b/RVO50/release.js.json @@ -0,0 +1,34 @@ +{ + "pid": 379, + "stats": [ + { + "id": null, + "version": { + "node": "v14.18.1", + "total": "3.4.13", + "app": "1.0.0" + }, + "pid": 379, + "thread": "", + "mode": "release", + "overload": 0, + "date": "2025-10-16T00:27:11.342Z", + "memory": 23.95, + "rm": 0, + "fm": 0, + "wm": 0, + "mm": 0, + "om": 2, + "em": 1, + "dbrm": 0, + "dbwm": 0, + "usage": 0, + "requests": 0, + "pending": 0, + "errors": 0, + "timeouts": 0, + "uptime": 737, + "online": 0 + } + ] +} \ No newline at end of file diff --git a/RVO50/report_data.log b/RVO50/report_data.log new file mode 100755 index 0000000..ca8f563 --- /dev/null +++ b/RVO50/report_data.log @@ -0,0 +1,166 @@ +{ + "name": "rvo_senica_50_10.0.0.139", + "time": "2025-10-15T13:11:26.350Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_50_10.0.0.139", + "time": "2025-10-15T14:11:26.347Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_50_10.0.0.139", + "time": "2025-10-15T15:11:26.348Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_50_10.0.0.139", + "time": "2025-10-15T16:11:26.348Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_50_10.0.0.139", + "time": "2025-10-15T17:33:01.878Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_50_10.0.0.139", + "time": "2025-10-15T18:33:01.878Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_50_10.0.0.139", + "time": "2025-10-15T19:33:01.877Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_50_10.0.0.139", + "time": "2025-10-15T20:33:01.877Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_50_10.0.0.139", + "time": "2025-10-15T21:33:01.877Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_50_10.0.0.139", + "time": "2025-10-15T22:33:01.878Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_50_10.0.0.139", + "time": "2025-10-15T23:33:01.878Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +} \ No newline at end of file From 429a705bb889ff3f322691ede6d5a478249b07d4 Mon Sep 17 00:00:00 2001 From: Jakub Klena Date: Thu, 16 Oct 2025 02:27:50 +0200 Subject: [PATCH 30/30] Backup senica-RVO53 on 16.10.2025 --- RVO53/addSwitch.py | 36 + RVO53/cloud_topic.py | 76 + RVO53/config | 12 + RVO53/createNode.py | 43 + RVO53/databases/accelerometer_db.js | 3055 ++++++ RVO53/databases/modbus_config.js | 114 + RVO53/databases/nodes.table | 61 + .../nodes_original/nodes_original.table | 1 + RVO53/databases/notifications.table | 41 + RVO53/databases/pins.table | 14 + RVO53/databases/relays.table | 5 + RVO53/databases/settings.table | 2 + RVO53/databases/tbdata.nosql | 0 RVO53/databases/tbdatacloud.nosql | 0 RVO53/databases/total_energy.js | 38 + RVO53/debug.js | 16 + RVO53/err.txt | 70 + RVO53/flow/cloudmqttconnect.js | 357 + RVO53/flow/cmd_manager.js | 3071 ++++++ RVO53/flow/code.js | 90 + RVO53/flow/comment.js | 11 + RVO53/flow/count.js | 60 + RVO53/flow/db_connector.js | 286 + RVO53/flow/db_init.js | 113 + RVO53/flow/debug.js | 100 + RVO53/flow/designer.json | 3102 ++++++ RVO53/flow/dido_controller.js | 1486 +++ RVO53/flow/helper/DataToTbHandler.js | 187 + RVO53/flow/helper/ErrorToServiceHandler.js | 91 + RVO53/flow/helper/db_helper.js | 44 + RVO53/flow/helper/logger.js | 30 + RVO53/flow/helper/md5.js | 5 + RVO53/flow/helper/notification_reporter.js | 121 + RVO53/flow/helper/register.js | 144 + RVO53/flow/helper/serialport_helper.js | 99 + RVO53/flow/helper/suncalc.js | 317 + RVO53/flow/helper/utils.js | 161 + RVO53/flow/httprequest.js | 137 + RVO53/flow/httpresponse.js | 76 + RVO53/flow/httproute.js | 326 + RVO53/flow/infosender.js | 81 + RVO53/flow/modbus_reader.js | 346 + RVO53/flow/monitorconsumption.js | 156 + RVO53/flow/monitordisk.js | 96 + RVO53/flow/monitormemory.js | 87 + RVO53/flow/nodesdb_changecheck.js | 77 + RVO53/flow/show_dbdata.js | 243 + RVO53/flow/slack_filter.js | 188 + RVO53/flow/thermometer.js | 99 + RVO53/flow/trigger.js | 79 + RVO53/flow/variables.txt | 0 RVO53/flow/virtualwirein.js | 43 + RVO53/flow/virtualwireout.js | 41 + RVO53/flow/wsmqttpublish.js | 448 + RVO53/monitor.txt | 8309 +++++++++++++++++ RVO53/package-lock.json | 2139 +++++ RVO53/package.json | 30 + RVO53/release.js | 15 + RVO53/release.js.json | 34 + RVO53/report_data.log | 2274 +++++ 60 files changed, 28783 insertions(+) create mode 100755 RVO53/addSwitch.py create mode 100755 RVO53/cloud_topic.py create mode 100755 RVO53/config create mode 100755 RVO53/createNode.py create mode 100755 RVO53/databases/accelerometer_db.js create mode 100755 RVO53/databases/modbus_config.js create mode 100755 RVO53/databases/nodes.table create mode 100755 RVO53/databases/nodes_original/nodes_original.table create mode 100755 RVO53/databases/notifications.table create mode 100755 RVO53/databases/pins.table create mode 100755 RVO53/databases/relays.table create mode 100755 RVO53/databases/settings.table create mode 100755 RVO53/databases/tbdata.nosql create mode 100755 RVO53/databases/tbdatacloud.nosql create mode 100755 RVO53/databases/total_energy.js create mode 100755 RVO53/debug.js create mode 100755 RVO53/err.txt create mode 100755 RVO53/flow/cloudmqttconnect.js create mode 100755 RVO53/flow/cmd_manager.js create mode 100755 RVO53/flow/code.js create mode 100755 RVO53/flow/comment.js create mode 100755 RVO53/flow/count.js create mode 100755 RVO53/flow/db_connector.js create mode 100755 RVO53/flow/db_init.js create mode 100755 RVO53/flow/debug.js create mode 100755 RVO53/flow/designer.json create mode 100755 RVO53/flow/dido_controller.js create mode 100755 RVO53/flow/helper/DataToTbHandler.js create mode 100755 RVO53/flow/helper/ErrorToServiceHandler.js create mode 100755 RVO53/flow/helper/db_helper.js create mode 100755 RVO53/flow/helper/logger.js create mode 100755 RVO53/flow/helper/md5.js create mode 100755 RVO53/flow/helper/notification_reporter.js create mode 100755 RVO53/flow/helper/register.js create mode 100755 RVO53/flow/helper/serialport_helper.js create mode 100755 RVO53/flow/helper/suncalc.js create mode 100755 RVO53/flow/helper/utils.js create mode 100755 RVO53/flow/httprequest.js create mode 100755 RVO53/flow/httpresponse.js create mode 100755 RVO53/flow/httproute.js create mode 100755 RVO53/flow/infosender.js create mode 100755 RVO53/flow/modbus_reader.js create mode 100755 RVO53/flow/monitorconsumption.js create mode 100755 RVO53/flow/monitordisk.js create mode 100755 RVO53/flow/monitormemory.js create mode 100755 RVO53/flow/nodesdb_changecheck.js create mode 100755 RVO53/flow/show_dbdata.js create mode 100755 RVO53/flow/slack_filter.js create mode 100755 RVO53/flow/thermometer.js create mode 100755 RVO53/flow/trigger.js create mode 100755 RVO53/flow/variables.txt create mode 100755 RVO53/flow/virtualwirein.js create mode 100755 RVO53/flow/virtualwireout.js create mode 100755 RVO53/flow/wsmqttpublish.js create mode 100755 RVO53/monitor.txt create mode 100755 RVO53/package-lock.json create mode 100755 RVO53/package.json create mode 100755 RVO53/release.js create mode 100755 RVO53/release.js.json create mode 100755 RVO53/report_data.log diff --git a/RVO53/addSwitch.py b/RVO53/addSwitch.py new file mode 100755 index 0000000..c35e96b --- /dev/null +++ b/RVO53/addSwitch.py @@ -0,0 +1,36 @@ +import os + +def process_set_file(): + """ + Checks if /root/flowserver exists, reads set.txt, and modifies the second line. + """ + default_folder = "/root/flowserver" if os.path.exists("/root/flowserver") else "/home/unipi/flowserver" + flag = 1 if default_folder == "/root/flowserver" else 0 + + try: + with open("/home/unipi/flowserver/databases/settings.table", "r") as f: + lines = f.readlines() + + if len(lines) >= 2: + lines[0] = lines[0].rstrip('\n') + "|main_switch:boolean\n" + second_line = lines[1].strip() # remove trailing newline + last_pipe_index = second_line.rfind("|") + + if last_pipe_index != -1: + modified_line = second_line[:last_pipe_index + 1] + str(flag) + "|" + second_line[last_pipe_index + 1:] + lines[1] = modified_line + else: + print("Warning: No '|' character found in the second line of set.txt") + + with open("/home/unipi/flowserver/databases/settings.table", "w") as f: + f.writelines(lines) + else: + print("Warning: settings.table has less than two lines.") + + except FileNotFoundError: + print("Error: settings.table not found.") + except Exception as e: + print(e) + +# if __name__ == "__main__": +process_set_file() diff --git a/RVO53/cloud_topic.py b/RVO53/cloud_topic.py new file mode 100755 index 0000000..77c31f1 --- /dev/null +++ b/RVO53/cloud_topic.py @@ -0,0 +1,76 @@ +# import os +# +# def modify_file(file_path): +# """ +# Modifies the given file by: +# 1. Appending "|cloud_topic" to the first line. +# 2. Inserting the text from the third "." to the first "|" on the second line after the last "|" character. +# +# Args: +# file_path (str): The path to the file to be modified. +# """ +# +# with open(file_path, 'r+') as f: +# lines = f.readlines() +# +# # Modify the first line +# lines[0] += "|cloud_topic:string" +# +# # Modify the second line +# second_line = lines[1].strip() # Remove leading/trailing whitespace +# first_pipe_index = second_line.find('|') +# third_dot_index = second_line.find('.', second_line.find('.', second_line.find('.') + 1) + 1) +# text_to_insert = second_line[third_dot_index:first_pipe_index] +# +# last_pipe_index = second_line.rfind('|') +# lines[1] = second_line[:last_pipe_index + 1] + text_to_insert + "|" + second_line[last_pipe_index + 1:] +# +# print(first_pipe_index, third_dot_index, text_to_insert, last_pipe_index) +# # Write the modified lines back to the file +# # f.seek(0) +# # f.writelines(lines) +# # f.truncate() +# +# # Example usage: +# file_path = "settings.table" # Replace with the actual file path +# modify_file(file_path) +# + + +def modify_file(file_path): + """ + Modifies the given file by: + 1. Appending "|cloud_topic" to the first line. + 2. Inserting the text between the third "." and the second "|" on the second line after the last "|" character. + + Args: + file_path (str): The path to the file to be modified. + """ + + with open(file_path, 'r+') as f: + lines = f.readlines() + + first_line = lines[0].strip() + first_line += "|cloud_topic:string\n" + # Modify the first line + lines[0] = first_line + + # Modify the second line + second_line = lines[1].strip() # Remove leading/trailing whitespace + first_pipe_index = second_line.find('|') + second_pipe_index = second_line.find('|', first_pipe_index + 1) + third_dot_index = second_line.find('.', second_line.find('.', second_line.find('.') + 1) + 1) + text_to_insert = "u" + second_line[third_dot_index+1:second_pipe_index] + + last_pipe_index = second_line.rfind('|') + lines[1] = second_line[:last_pipe_index + 1] + text_to_insert + "|" + second_line[last_pipe_index + 1:] + + print(first_pipe_index, third_dot_index, text_to_insert, last_pipe_index) + # Write the modified lines back to the file + f.seek(0) + f.writelines(lines) + f.truncate() + +# Example usage: +file_path = "/home/unipi/flowserver/databases/settings.table" # Replace with the actual file path +modify_file(file_path) diff --git a/RVO53/config b/RVO53/config new file mode 100755 index 0000000..cd0a8a9 --- /dev/null +++ b/RVO53/config @@ -0,0 +1,12 @@ +name : Total.js Flow +default_timezone : Europe/Bratislava + +// Packages settings +package#flow (Object) : { url: '/' } + + +table.relays : line:number|tbname:string|contactor:number|profile:string +table.nodes : node:number|pole_number:string|node_type:string|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|project_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|cloud_topic:string|has_main_switch:boolean|daily_report:boolean|send_changed_node_numbers:boolean +table.pins : pin:string|type:string|line:number +table.notifications : key:string|weight:string|sk:string|en:string diff --git a/RVO53/createNode.py b/RVO53/createNode.py new file mode 100755 index 0000000..21406cc --- /dev/null +++ b/RVO53/createNode.py @@ -0,0 +1,43 @@ +print("zaciname") +import re, json + +search_str = '|' +final = [] +counter = 1 +with open("/home/unipi/flowserver/databases/nodes.table", 'r') as file: +# with open("/home/rasta5man/dev/oms/flowserver/databases/nodes.table", 'r') as file: + # Read each line in the file + for line in file: + # Print each line + line = line.strip() + print(line) + if counter != 1: + i = [m.start() for m in re.finditer(re.escape(search_str), line)] + node = line[ i[0] + 1 : i[1] ] + tbname = line[ i[1] + 1 : i[2] ] + final.append({node:tbname}) + counter += 1 +print(json.dumps(final)) +f = open("/home/unipi/flowserver/databases/nodes_original/nodes_original.table", "w") +f.write(json.dumps(final)) +f.close() + + +# +# # ``d`` has to be replaced with a different character +# old_character = "'" +# +# # ``t`` will replace ``d` +# new_character = '"' +# resultant_string = 0; +# with open("/home/unipi/flowserver/databases/nodes_original/nodes_original.table", 'r') as file: +# for line in file: +# resultant_string = re.sub("'", '"', line) +# +# resultant_string = re.sub(" ", "", resultant_string) +# print(resultant_string) +# +# f = open("/home/unipi/flowserver/databases/nodes_original/nodes_original.table", "w") +# f.write(str(resultant_string)) +# f.close() +# diff --git a/RVO53/databases/accelerometer_db.js b/RVO53/databases/accelerometer_db.js new file mode 100755 index 0000000..fdfc7fd --- /dev/null +++ b/RVO53/databases/accelerometer_db.js @@ -0,0 +1,3055 @@ +let naklony = { + "3993": { "label": "1/3A", "naklon": 0 }, + "3989": { "label": "1/3B", "naklon": 15 }, + "3976": { "label": "1/1", "naklon": 0 }, + "4181": { "label": "1/2", "naklon": 0 }, + "4376": { "label": "1/4", "naklon": 15 }, + "3868": { "label": "1/5", "naklon": 15 }, + "3728": { "label": "1/6", "naklon": 15 }, + "3730": { "label": "1/7", "naklon": 0 }, + "4374": { "label": "1/8", "naklon": 0 }, + "3718": { "label": "1/9", "naklon": 15 }, + "4375": { "label": "1/10", "naklon": 15 }, + "4172": { "label": "1/11", "naklon": 15 }, + "4176": { "label": "1/12", "naklon": 15 }, + "3800": { "label": "2/1", "naklon": 5 }, + "3823": { "label": "2/2", "naklon": 5 }, + "3905": { "label": "2/3", "naklon": 5 }, + "3803": { "label": "2/4", "naklon": 5 }, + "3817": { "label": "2/5", "naklon": 5 }, + "3818": { "label": "2/6", "naklon": 5 }, + "3811": { "label": "2/7", "naklon": 5 }, + "3915": { "label": "2/8", "naklon": 5 }, + "3843": { "label": "2/9", "naklon": 10 }, + "3827": { "label": "2/10", "naklon": 10 }, + "4220": { "label": "2/11", "naklon": 10 }, + "3826": { "label": "2/12", "naklon": 10 }, + "3834": { "label": "2/13", "naklon": 10 }, + "3838": { "label": "2/14", "naklon": 10 }, + "2823": { "label": "2/15", "naklon": 10 }, + "3750": { "label": "2/16", "naklon": 10 }, + "3378": { "label": "2/17", "naklon": 0 }, + "3376": { "label": "2/18", "naklon": 0 }, + "3379": { "label": "2/19", "naklon": 0 }, + "3285": { "label": "2/20", "naklon": 0 }, + "3382": { "label": "2/21", "naklon": 0 }, + "3383": { "label": "2/22", "naklon": 0 }, + "3375": { "label": "2/24", "naklon": 0 }, + "3381": { "label": "2/25", "naklon": 0 }, + "3380": { "label": "2/26", "naklon": 0 }, + "3828": { "label": "2/27", "naklon": 10 }, + "3377": { "label": "2/28", "naklon": 0 }, + "3591": { "label": "7/1", "naklon": 0 }, + "3587": { "label": "7/2", "naklon": 0 }, + "3468": { "label": "7/3", "naklon": 0 }, + "3466": { "label": "7/4", "naklon": 0 }, + "3474": { "label": "7/5", "naklon": 0 }, + "3481": { "label": "7/6", "naklon": 0 }, + "3589": { "label": "7/7", "naklon": 0 }, + "3472": { "label": "7/8", "naklon": 0 }, + "3473": { "label": "7/9", "naklon": 0 }, + "3584": { "label": "7/10", "naklon": 0 }, + "3571": { "label": "7/11", "naklon": 0 }, + "3476": { "label": "7/12", "naklon": 0 }, + "3590": { "label": "7/13", "naklon": 0 }, + "3478": { "label": "7/14", "naklon": 0 }, + "3471": { "label": "7/15", "naklon": 0 }, + "3467": { "label": "7/16", "naklon": 0 }, + "3479": { "label": "7/17", "naklon": 0 }, + "3480": { "label": "7/18", "naklon": 0 }, + "3477": { "label": "7/19", "naklon": 0 }, + "3362": { "label": "12/1", "naklon": 0 }, + "3355": { "label": "12/2", "naklon": 0 }, + "3356": { "label": "12/3", "naklon": 0 }, + "3349": { "label": "12/4", "naklon": 0 }, + "3357": { "label": "12/5", "naklon": 0 }, + "3350": { "label": "12/6", "naklon": 0 }, + "3353": { "label": "12/7", "naklon": 0 }, + "3539": { "label": "12/8", "naklon": 0 }, + "3050": { "label": "12/9", "naklon": 0 }, + "3361": { "label": "12/10", "naklon": 0 }, + "3360": { "label": "12/11", "naklon": 0 }, + "3358": { "label": "12/12", "naklon": 0 }, + "3541": { "label": "12/13", "naklon": 0 }, + "3551": { "label": "12/14", "naklon": 0 }, + "3514": { "label": "12/15", "naklon": 0 }, + "3547": { "label": "12/16", "naklon": 0 }, + "3562": { "label": "12/17", "naklon": 0 }, + "3525": { "label": "12/18", "naklon": 0 }, + "3558": { "label": "12/19", "naklon": 0 }, + "3511": { "label": "12/20", "naklon": 0 }, + "3058": { "label": "12/21", "naklon": 0 }, + "3062": { "label": "12/22", "naklon": 0 }, + "3070": { "label": "12/23", "naklon": 0 }, + "3447": { "label": "12/24", "naklon": 0 }, + "3056": { "label": "12/25", "naklon": 0 }, + "3057": { "label": "12/26", "naklon": 0 }, + "3071": { "label": "12/27", "naklon": 0 }, + "3061": { "label": "12/28", "naklon": 0 }, + "3069": { "label": "12/29", "naklon": 0 }, + "3077": { "label": "12/30", "naklon": 0 }, + "3080": { "label": "12/31", "naklon": 0 }, + "3081": { "label": "12/32", "naklon": 0 }, + "3078": { "label": "12/33", "naklon": 0 }, + "4037": { "label": "12/34", "naklon": 0 }, + "3067": { "label": "12/35", "naklon": 0 }, + "3051": { "label": "12/36", "naklon": 0 }, + "2924": { "label": "12/37", "naklon": 0 }, + "3060": { "label": "12/38", "naklon": 0 }, + "3073": { "label": "12/39", "naklon": 0 }, + "3469": { "label": "12/40", "naklon": 0 }, + "2923": { "label": "12/41", "naklon": 0 }, + "2925": { "label": "12/42", "naklon": 0 }, + "3359": { "label": "12/43", "naklon": 0 }, + "3055": { "label": "12/44", "naklon": 0 }, + "2922": { "label": "12/45", "naklon": 0 }, + "3084": { "label": "12/46", "naklon": 0 }, + "3064": { "label": "12/47", "naklon": 0 }, + "3066": { "label": "12/48", "naklon": 0 }, + "3072": { "label": "12/49", "naklon": 0 }, + "3415": { "label": "13/13A", "naklon": 0 }, + "3409": { "label": "13/13B", "naklon": 0 }, + "3399": { "label": "13/13C", "naklon": 0 }, + "3410": { "label": "13/29A", "naklon": 0 }, + "3407": { "label": "13/29B", "naklon": 0 }, + "3405": { "label": "13/34A", "naklon": 0 }, + "3404": { "label": "13/34B", "naklon": 0 }, + "3392": { "label": "13/45A", "naklon": 0 }, + "3386": { "label": "13/45B", "naklon": 0 }, + "3303": { "label": "13/60A", "naklon": 3 }, + "3302": { "label": "13/60B", "naklon": 3 }, + "3319": { "label": "13/70A", "naklon": 6 }, + "3317": { "label": "13/70B", "naklon": 6 }, + "3326": { "label": "13/70C", "naklon": 6 }, + "3351": { "label": "13/73A", "naklon": 6 }, + "3313": { "label": "13/73B", "naklon": 6 }, + "3316": { "label": "13/83A", "naklon": 0 }, + "3320": { "label": "13/83B", "naklon": 0 }, + "3336": { "label": "13/95A", "naklon": 0 }, + "3323": { "label": "13/95B", "naklon": 0 }, + "3339": { "label": "13/98A", "naklon": 0 }, + "3333": { "label": "13/98B", "naklon": 0 }, + "3425": { "label": "13/1", "naklon": 0 }, + "3419": { "label": "13/2", "naklon": 0 }, + "3416": { "label": "13/3", "naklon": 0 }, + "3332": { "label": "13/4", "naklon": 0 }, + "3422": { "label": "13/5", "naklon": 0 }, + "3417": { "label": "13/6", "naklon": 0 }, + "3418": { "label": "13/7", "naklon": 0 }, + "3424": { "label": "13/8", "naklon": 0 }, + "3334": { "label": "13/9", "naklon": 0 }, + "4363": { "label": "13/10", "naklon": 0 }, + "3423": { "label": "13/11", "naklon": 0 }, + "3406": { "label": "13/12", "naklon": 0 }, + "3411": { "label": "13/14", "naklon": 0 }, + "3412": { "label": "13/15", "naklon": 0 }, + "3413": { "label": "13/16", "naklon": 0 }, + "3414": { "label": "13/17", "naklon": 0 }, + "3391": { "label": "13/18", "naklon": 0 }, + "3370": { "label": "13/19", "naklon": 0 }, + "3369": { "label": "13/20", "naklon": 0 }, + "3408": { "label": "13/21", "naklon": 0 }, + "3393": { "label": "13/22", "naklon": 0 }, + "3128": { "label": "13/23", "naklon": 0 }, + "3197": { "label": "13/24", "naklon": 0 }, + "4364": { "label": "13/25", "naklon": 0 }, + "3155": { "label": "13/26", "naklon": 0 }, + "3196": { "label": "13/27", "naklon": 0 }, + "3144": { "label": "13/28", "naklon": 0 }, + "3150": { "label": "13/30", "naklon": 0 }, + "3390": { "label": "13/31", "naklon": 0 }, + "3401": { "label": "13/32", "naklon": 0 }, + "3275": { "label": "13/33", "naklon": 0 }, + "3371": { "label": "13/35", "naklon": 0 }, + "3389": { "label": "13/36", "naklon": 0 }, + "3388": { "label": "13/37", "naklon": 0 }, + "3365": { "label": "13/38", "naklon": 0 }, + "3363": { "label": "13/39", "naklon": 0 }, + "3397": { "label": "13/40", "naklon": 0 }, + "3567": { "label": "13/40/1", "naklon": 0 }, + "3387": { "label": "13/41", "naklon": 0 }, + "3403": { "label": "13/42", "naklon": 0 }, + "3147": { "label": "13/43", "naklon": 0 }, + "3141": { "label": "13/44", "naklon": 0 }, + "3364": { "label": "13/46", "naklon": 0 }, + "3367": { "label": "13/47", "naklon": 0 }, + "3368": { "label": "13/48", "naklon": 0 }, + "3402": { "label": "13/49", "naklon": 0 }, + "3366": { "label": "13/50", "naklon": 0 }, + "3395": { "label": "13/51", "naklon": 0 }, + "3372": { "label": "13/52", "naklon": 0 }, + "3394": { "label": "13/53", "naklon": 0 }, + "3308": { "label": "13/54", "naklon": 0 }, + "3847": { "label": "13/54/1", "naklon": 0 }, + "3312": { "label": "13/55", "naklon": 3 }, + "3309": { "label": "13/56", "naklon": 3 }, + "3311": { "label": "13/57", "naklon": 3 }, + "3310": { "label": "13/58", "naklon": 3 }, + "4365": { "label": "13/59", "naklon": 3 }, + "4093": { "label": "13/60/1", "naklon": 3 }, + "3304": { "label": "13/61", "naklon": 3 }, + "3307": { "label": "13/62", "naklon": 3 }, + "3271": { "label": "13/63", "naklon": 3 }, + "3301": { "label": "13/64", "naklon": 3 }, + "4366": { "label": "13/65", "naklon": 3 }, + "3300": { "label": "13/66", "naklon": 3 }, + "3185": { "label": "13/67", "naklon": 0 }, + "3184": { "label": "13/68", "naklon": 0 }, + "3188": { "label": "13/69", "naklon": 0 }, + "3343": { "label": "13/71", "naklon": 6 }, + "3819": { "label": "13/71/1", "naklon": 6 }, + "3880": { "label": "13/71/2", "naklon": 6 }, + "3348": { "label": "13/72", "naklon": 6 }, + "3344": { "label": "13/74", "naklon": 6 }, + "3346": { "label": "13/75", "naklon": 6 }, + "3597": { "label": "13/75/1", "naklon": 6 }, + "3345": { "label": "13/76", "naklon": 6 }, + "3322": { "label": "13/77", "naklon": 0 }, + "3325": { "label": "13/78", "naklon": 0 }, + "4310": { "label": "13/78/1", "naklon": 0 }, + "3315": { "label": "13/79", "naklon": 0 }, + "3328": { "label": "13/80", "naklon": 0 }, + "3321": { "label": "13/81", "naklon": 0 }, + "3324": { "label": "13/82", "naklon": 0 }, + "3140": { "label": "13/84", "naklon": 0 }, + "3153": { "label": "13/85", "naklon": 0 }, + "3145": { "label": "13/86", "naklon": 0 }, + "3134": { "label": "13/87", "naklon": 0 }, + "3151": { "label": "13/88", "naklon": 0 }, + "3143": { "label": "13/89", "naklon": 0 }, + "3318": { "label": "13/90", "naklon": 0 }, + "3347": { "label": "13/91", "naklon": 0 }, + "3314": { "label": "13/94", "naklon": 0 }, + "3331": { "label": "13/96", "naklon": 0 }, + "3327": { "label": "13/97", "naklon": 0 }, + "3329": { "label": "13/99", "naklon": 0 }, + "3337": { "label": "13/100", "naklon": 0 }, + "3330": { "label": "13/101", "naklon": 0 }, + "3335": { "label": "13/102", "naklon": 0 }, + "3420": { "label": "13/103", "naklon": 0 }, + "3421": { "label": "13/104", "naklon": 0 }, + "4361": { "label": "13/105", "naklon": 0 }, + "4362": { "label": "13/106", "naklon": 0 }, + "3526": { "label": "13/107", "naklon": 0 }, + "4424": { "label": "13/108", "naklon": null }, + "3561": { "label": "13/109", "naklon": null }, + "3527": { "label": "13/110", "naklon": null }, + "3521": { "label": "13/111", "naklon": null }, + "3552": { "label": "13/112", "naklon": null }, + "3544": { "label": "13/113", "naklon": null }, + "3534": { "label": "13/114", "naklon": null }, + "3516": { "label": "13/115", "naklon": null }, + "3513": { "label": "13/116", "naklon": null }, + "3565": { "label": "13/117", "naklon": null }, + "3866": { "label": "13/118", "naklon": null }, + "3136": { "label": "14/1", "naklon": 0 }, + "3137": { "label": "14/2", "naklon": 0 }, + "3135": { "label": "14/3", "naklon": 0 }, + "3149": { "label": "14/4", "naklon": 0 }, + "3142": { "label": "14/5", "naklon": 0 }, + "3342": { "label": "14/6", "naklon": 0 }, + "3340": { "label": "14/7", "naklon": 0 }, + "3152": { "label": "14/8", "naklon": 0 }, + "3886": { "label": "14/9", "naklon": 0 }, + "3341": { "label": "14/10", "naklon": null }, + "3352": { "label": "14/11", "naklon": null }, + "3396": { "label": "15/1", "naklon": 5 }, + "2784": { "label": "15/2", "naklon": 5 }, + "2788": { "label": "15/3", "naklon": 5 }, + "2801": { "label": "15/4", "naklon": 5 }, + "2815": { "label": "15/5", "naklon": 5 }, + "2829": { "label": "15/6", "naklon": 5 }, + "2796": { "label": "15/7", "naklon": 5 }, + "2803": { "label": "15/8", "naklon": 5 }, + "4304": { "label": "15/8/1", "naklon": 5 }, + "4311": { "label": "15/8/2", "naklon": 5 }, + "2821": { "label": "15/9", "naklon": 5 }, + "3400": { "label": "15/10", "naklon": 5 }, + "2799": { "label": "15/11", "naklon": 5 }, + "2804": { "label": "15/12", "naklon": 5 }, + "4303": { "label": "15/12/1", "naklon": 5 }, + "4309": { "label": "15/12/2", "naklon": 5 }, + "2806": { "label": "15/13", "naklon": 5 }, + "2787": { "label": "15/14", "naklon": 5 }, + "2809": { "label": "15/15", "naklon": 5 }, + "2814": { "label": "15/16", "naklon": 0 }, + "3934": { "label": "15/17", "naklon": 0 }, + "3192": { "label": "15/18", "naklon": 0 }, + "2812": { "label": "15/19", "naklon": 0 }, + "4070": { "label": "15/20", "naklon": 0 }, + "2826": { "label": "15/21", "naklon": 0 }, + "2808": { "label": "15/22", "naklon": 3 }, + "2795": { "label": "15/23", "naklon": 3 }, + "2807": { "label": "15/24", "naklon": 3 }, + "2831": { "label": "15/25", "naklon": 0 }, + "2862": { "label": "15/26", "naklon": null }, + "2861": { "label": "15/27", "naklon": 0 }, + "2866": { "label": "15/28", "naklon": 0 }, + "3546": { "label": "15/28/1", "naklon": 0 }, + "4146": { "label": "15/29", "naklon": 0 }, + "3001": { "label": "15/29/1", "naklon": 0 }, + "2835": { "label": "15/30", "naklon": 0 }, + "2874": { "label": "15/31", "naklon": 0 }, + "2852": { "label": "15/32", "naklon": 0 }, + "2851": { "label": "15/33", "naklon": 0 }, + "3560": { "label": "15/33/1", "naklon": 0 }, + "2858": { "label": "15/34", "naklon": 0 }, + "4306": { "label": "15/34/1", "naklon": 0 }, + "2856": { "label": "15/35", "naklon": 0 }, + "2847": { "label": "15/36", "naklon": 0 }, + "3556": { "label": "15/36/1", "naklon": 0 }, + "3950": { "label": "15/37", "naklon": 0 }, + "2848": { "label": "15/38", "naklon": 0 }, + "2863": { "label": "15/39", "naklon": 0 }, + "4313": { "label": "15/39/1", "naklon": 0 }, + "2873": { "label": "15/40", "naklon": 0 }, + "2984": { "label": "15/40/1", "naklon": 0 }, + "2854": { "label": "15/41", "naklon": 0 }, + "2859": { "label": "15/42", "naklon": 0 }, + "2872": { "label": "15/43", "naklon": 0 }, + "2849": { "label": "15/44", "naklon": 0 }, + "2864": { "label": "15/45", "naklon": 0 }, + "3553": { "label": "15/46", "naklon": null }, + "3021": { "label": "15/47", "naklon": null }, + "3008": { "label": "15/47/1", "naklon": null }, + "3017": { "label": "15/48", "naklon": null }, + "3014": { "label": "15/49", "naklon": null }, + "2981": { "label": "15/50", "naklon": null }, + "3020": { "label": "15/51", "naklon": null }, + "3027": { "label": "15/52", "naklon": null }, + "3006": { "label": "15/53", "naklon": null }, + "3012": { "label": "15/54", "naklon": null }, + "2738": { "label": "15/55", "naklon": 0 }, + "2725": { "label": "15/56", "naklon": 0 }, + "3016": { "label": "15/57", "naklon": null }, + "3005": { "label": "15/58", "naklon": null }, + "3009": { "label": "15/58/1", "naklon": null }, + "3010": { "label": "15/59", "naklon": 0 }, + "3538": { "label": "15/59/1", "naklon": 0 }, + "4145": { "label": "15/59/2", "naklon": 0 }, + "2713": { "label": "15/60", "naklon": 0 }, + "2789": { "label": "15/61", "naklon": 0 }, + "2736": { "label": "15/62", "naklon": 0 }, + "2739": { "label": "15/63", "naklon": 0 }, + "4346": { "label": "15/64", "naklon": 0 }, + "2731": { "label": "15/65", "naklon": 0 }, + "2818": { "label": "15/66", "naklon": 0 }, + "3557": { "label": "15/66/1", "naklon": 0 }, + "2822": { "label": "15/67", "naklon": 0 }, + "2833": { "label": "15/68", "naklon": 0 }, + "2834": { "label": "15/69", "naklon": 0 }, + "3097": { "label": "15/70", "naklon": 0 }, + "2824": { "label": "15/71", "naklon": 0 }, + "2828": { "label": "15/72", "naklon": 0 }, + "2600": { "label": "15/73", "naklon": 0 }, + "4314": { "label": "15/73/1", "naklon": 0 }, + "2832": { "label": "15/74", "naklon": 0 }, + "4360": { "label": "15/75", "naklon": 0 }, + "2846": { "label": "15/76", "naklon": 0 }, + "2584": { "label": "15/77", "naklon": 0 }, + "2843": { "label": "15/78", "naklon": 0 }, + "4308": { "label": "15/78/1", "naklon": 0 }, + "4144": { "label": "15/79", "naklon": null }, + "2844": { "label": "15/80", "naklon": 0 }, + "2842": { "label": "15/81", "naklon": 0 }, + "2838": { "label": "15/82", "naklon": 0 }, + "2837": { "label": "15/83", "naklon": null }, + "3555": { "label": "15/83/1", "naklon": null }, + "2839": { "label": "15/84", "naklon": 0 }, + "2830": { "label": "15/85", "naklon": 0 }, + "4066": { "label": "15/86", "naklon": 0 }, + "2836": { "label": "15/87", "naklon": 0 }, + "2911": { "label": "15/88", "naklon": 0 }, + "2825": { "label": "15/89", "naklon": 0 }, + "2811": { "label": "15/90", "naklon": 0 }, + "3740": { "label": "15/94", "naklon": 15 }, + "2734": { "label": "15/95", "naklon": 15 }, + "3105": { "label": "15/96", "naklon": 15 }, + "2732": { "label": "15/97", "naklon": 15 }, + "2727": { "label": "15/98", "naklon": 15 }, + "2735": { "label": "15/99", "naklon": 15 }, + "3926": { "label": "15/100", "naklon": 15 }, + "2918": { "label": "15/101", "naklon": 0 }, + "2705": { "label": "15/102", "naklon": 10 }, + "2708": { "label": "15/103", "naklon": 10 }, + "2721": { "label": "15/104", "naklon": 10 }, + "2719": { "label": "15/105", "naklon": 10 }, + "2919": { "label": "15/106", "naklon": 10 }, + "3101": { "label": "15/107", "naklon": 10 }, + "2853": { "label": "15/108", "naklon": 10 }, + "2715": { "label": "15/109", "naklon": 10 }, + "2712": { "label": "15/110", "naklon": 0 }, + "2711": { "label": "15/111", "naklon": 0 }, + "2709": { "label": "15/112", "naklon": 0 }, + "2710": { "label": "15/113", "naklon": 0 }, + "2907": { "label": "15/114", "naklon": 0 }, + "2906": { "label": "15/115", "naklon": 0 }, + "2908": { "label": "15/116", "naklon": 0 }, + "2901": { "label": "15/117", "naklon": 0 }, + "2913": { "label": "15/118", "naklon": 0 }, + "3656": { "label": "15/119", "naklon": 0 }, + "2781": { "label": "15/120", "naklon": 0 }, + "2802": { "label": "15/121", "naklon": 0 }, + "2791": { "label": "15/122", "naklon": 0 }, + "2783": { "label": "15/123", "naklon": 0 }, + "2794": { "label": "15/124", "naklon": 0 }, + "3139": { "label": "15/125", "naklon": 0 }, + "3229": { "label": "15/126", "naklon": 5 }, + "3239": { "label": "15/127", "naklon": 5 }, + "3230": { "label": "15/128", "naklon": 5 }, + "4016": { "label": "15/129", "naklon": null }, + "3608": { "label": "16/16A", "naklon": 0 }, + "4151": { "label": "16/16B", "naklon": 0 }, + "3710": { "label": "16/1", "naklon": 0 }, + "3726": { "label": "16/2", "naklon": 0 }, + "3743": { "label": "16/3", "naklon": 0 }, + "3724": { "label": "16/4", "naklon": 0 }, + "3712": { "label": "16/5", "naklon": 0 }, + "3739": { "label": "16/6", "naklon": 0 }, + "3742": { "label": "16/7", "naklon": 0 }, + "3731": { "label": "16/8", "naklon": 0 }, + "3727": { "label": "16/9", "naklon": 0 }, + "3729": { "label": "16/10", "naklon": 0 }, + "3736": { "label": "16/11", "naklon": 0 }, + "3713": { "label": "16/12", "naklon": 0 }, + "3715": { "label": "16/13", "naklon": 0 }, + "3733": { "label": "16/14", "naklon": 0 }, + "3732": { "label": "16/15", "naklon": 0 }, + "3634": { "label": "16/17", "naklon": 0 }, + "3610": { "label": "16/18", "naklon": 0 }, + "3626": { "label": "16/19", "naklon": 0 }, + "3618": { "label": "16/20", "naklon": 0 }, + "3619": { "label": "16/21", "naklon": 0 }, + "3628": { "label": "16/22", "naklon": 0 }, + "3615": { "label": "16/23", "naklon": 0 }, + "3609": { "label": "16/24", "naklon": 0 }, + "3606": { "label": "16/25", "naklon": 0 }, + "3624": { "label": "16/26", "naklon": 0 }, + "3627": { "label": "16/27", "naklon": 0 }, + "3607": { "label": "16/28", "naklon": 0 }, + "4370": { "label": "16/29", "naklon": 0 }, + "3692": { "label": "16/30", "naklon": 0 }, + "3614": { "label": "16/31", "naklon": 0 }, + "3623": { "label": "16/32", "naklon": 0 }, + "4373": { "label": "16/33", "naklon": 0 }, + "3620": { "label": "16/34", "naklon": 0 }, + "3685": { "label": "16/35", "naklon": 0 }, + "3616": { "label": "16/36", "naklon": 0 }, + "3686": { "label": "16/37", "naklon": 0 }, + "3688": { "label": "16/38", "naklon": 0 }, + "3684": { "label": "16/39", "naklon": 0 }, + "3825": { "label": "16/40", "naklon": 0 }, + "3865": { "label": "16/41", "naklon": 0 }, + "3824": { "label": "16/42", "naklon": 0 }, + "3871": { "label": "16/43", "naklon": 0 }, + "3801": { "label": "16/44", "naklon": 0 }, + "3862": { "label": "16/45", "naklon": 0 }, + "3876": { "label": "16/46", "naklon": 0 }, + "3861": { "label": "16/47", "naklon": 0 }, + "4215": { "label": "16/48", "naklon": 0 }, + "3605": { "label": "16/49", "naklon": 10 }, + "3603": { "label": "16/50", "naklon": 10 }, + "3592": { "label": "16/51", "naklon": 10 }, + "3598": { "label": "16/52", "naklon": 10 }, + "3594": { "label": "16/53", "naklon": 10 }, + "3593": { "label": "16/54", "naklon": 10 }, + "3630": { "label": "16/55", "naklon": 10 }, + "3763": { "label": "16/56", "naklon": 10 }, + "3746": { "label": "16/57", "naklon": 10 }, + "3699": { "label": "16/58", "naklon": 0 }, + "3698": { "label": "16/59", "naklon": 0 }, + "3709": { "label": "16/60", "naklon": null }, + "3708": { "label": "16/61", "naklon": 0 }, + "3703": { "label": "16/62", "naklon": null }, + "3700": { "label": "16/63", "naklon": 0 }, + "3701": { "label": "16/64", "naklon": null }, + "3704": { "label": "16/65", "naklon": 0 }, + "3707": { "label": "16/66", "naklon": null }, + "3810": { "label": "16/67", "naklon": 0 }, + "4208": { "label": "16/68", "naklon": null }, + "3867": { "label": "16/69", "naklon": 0 }, + "4372": { "label": "16/70", "naklon": null }, + "3881": { "label": "16/71", "naklon": 0 }, + "4204": { "label": "16/72", "naklon": null }, + "3869": { "label": "16/73", "naklon": 0 }, + "4202": { "label": "16/74", "naklon": null }, + "3830": { "label": "16/75", "naklon": 0 }, + "3870": { "label": "16/76", "naklon": null }, + "3964": { "label": "16/77", "naklon": 0 }, + "3849": { "label": "16/78", "naklon": 0 }, + "3694": { "label": "16/79", "naklon": null }, + "3717": { "label": "16/80", "naklon": 0 }, + "3877": { "label": "16/81", "naklon": null }, + "3755": { "label": "16/82", "naklon": 0 }, + "3725": { "label": "16/83", "naklon": null }, + "3716": { "label": "16/84", "naklon": 0 }, + "3696": { "label": "16/85", "naklon": null }, + "3702": { "label": "16/86", "naklon": 0 }, + "3706": { "label": "16/87", "naklon": null }, + "3850": { "label": "16/88", "naklon": 0 }, + "3848": { "label": "16/89", "naklon": null }, + "3737": { "label": "16/90", "naklon": null }, + "3705": { "label": "16/91", "naklon": 0 }, + "3723": { "label": "16/92", "naklon": null }, + "3842": { "label": "16/93", "naklon": 0 }, + "3735": { "label": "16/94", "naklon": null }, + "3719": { "label": "16/95", "naklon": 0 }, + "3697": { "label": "16/96", "naklon": 0 }, + "3711": { "label": "16/97", "naklon": 0 }, + "4107": { "label": "16/98", "naklon": null }, + "4112": { "label": "16/99", "naklon": 5 }, + "4106": { "label": "16/100", "naklon": 5 }, + "4111": { "label": "16/101", "naklon": 5 }, + "4091": { "label": "16/102", "naklon": null }, + "4104": { "label": "16/103", "naklon": 5 }, + "4094": { "label": "16/104", "naklon": null }, + "4089": { "label": "16/105", "naklon": 5 }, + "4095": { "label": "16/106", "naklon": null }, + "4102": { "label": "16/107", "naklon": 5 }, + "4105": { "label": "16/108", "naklon": null }, + "3859": { "label": "16/109", "naklon": null }, + "4090": { "label": "16/110", "naklon": 5 }, + "4110": { "label": "16/111", "naklon": null }, + "4097": { "label": "16/112", "naklon": 5 }, + "4099": { "label": "16/113", "naklon": null }, + "4096": { "label": "16/114", "naklon": null }, + "4101": { "label": "16/115", "naklon": 5 }, + "4109": { "label": "16/116", "naklon": null }, + "4092": { "label": "16/117", "naklon": 5 }, + "3631": { "label": "16/118", "naklon": null }, + "3632": { "label": "16/119", "naklon": 0 }, + "3641": { "label": "16/120", "naklon": null }, + "3638": { "label": "16/121", "naklon": 0 }, + "3637": { "label": "16/122", "naklon": null }, + "4142": { "label": "16/123", "naklon": null }, + "4147": { "label": "16/124", "naklon": 5 }, + "4139": { "label": "16/125", "naklon": 5 }, + "3172": { "label": "20/30A", "naklon": 2 }, + "3164": { "label": "20/30B", "naklon": 2 }, + "3247": { "label": "20/1", "naklon": 10 }, + "3296": { "label": "20/2", "naklon": 10 }, + "3246": { "label": "20/3", "naklon": 10 }, + "3270": { "label": "20/4", "naklon": 10 }, + "3294": { "label": "20/5", "naklon": 10 }, + "3298": { "label": "20/6", "naklon": 10 }, + "3297": { "label": "20/7", "naklon": 10 }, + "3293": { "label": "20/8", "naklon": 10 }, + "3299": { "label": "20/9", "naklon": 10 }, + "3295": { "label": "20/10", "naklon": 10 }, + "3244": { "label": "20/11", "naklon": 10 }, + "3249": { "label": "20/12", "naklon": 10 }, + "3268": { "label": "20/13", "naklon": 10 }, + "3245": { "label": "20/14", "naklon": 10 }, + "3278": { "label": "20/15", "naklon": 10 }, + "3280": { "label": "20/16", "naklon": 10 }, + "3292": { "label": "20/17", "naklon": 10 }, + "3287": { "label": "20/18", "naklon": 10 }, + "3282": { "label": "20/19", "naklon": 10 }, + "3273": { "label": "20/20", "naklon": 0 }, + "3157": { "label": "20/21", "naklon": 0 }, + "3283": { "label": "20/22", "naklon": 0 }, + "3159": { "label": "20/23", "naklon": 0 }, + "3289": { "label": "20/24", "naklon": 0 }, + "3163": { "label": "20/25", "naklon": 0 }, + "3126": { "label": "20/26", "naklon": 0 }, + "3171": { "label": "20/27", "naklon": 0 }, + "3162": { "label": "20/28", "naklon": 0 }, + "3279": { "label": "20/29", "naklon": 10 }, + "3173": { "label": "20/31", "naklon": 0 }, + "3127": { "label": "20/32", "naklon": 0 }, + "3131": { "label": "20/33", "naklon": 0 }, + "3129": { "label": "20/34", "naklon": 0 }, + "3276": { "label": "20/35", "naklon": 2 }, + "3290": { "label": "20/36", "naklon": 2 }, + "3132": { "label": "20/37", "naklon": 0 }, + "3138": { "label": "20/38", "naklon": 0 }, + "3272": { "label": "20/39", "naklon": 0 }, + "3291": { "label": "20/40", "naklon": 0 }, + "3277": { "label": "20/41", "naklon": 10 }, + "3286": { "label": "20/42", "naklon": 10 }, + "3281": { "label": "20/43", "naklon": 10 }, + "3288": { "label": "20/44", "naklon": 10 }, + "3284": { "label": "20/45", "naklon": 10 }, + "3167": { "label": "20/46", "naklon": 10 }, + "3872": { "label": "20/47", "naklon": 0 }, + "3124": { "label": "20/48", "naklon": 0 }, + "3133": { "label": "20/49", "naklon": 0 }, + "3158": { "label": "20/50", "naklon": 0 }, + "3169": { "label": "20/51", "naklon": 0 }, + "3146": { "label": "20/52", "naklon": 0 }, + "3160": { "label": "20/53", "naklon": 0 }, + "3248": { "label": "20/54", "naklon": 0 }, + "3156": { "label": "20/55", "naklon": 0 }, + "3161": { "label": "20/56", "naklon": 0 }, + "3170": { "label": "20/57", "naklon": 0 }, + "3168": { "label": "20/58", "naklon": 0 }, + "3125": { "label": "20/59", "naklon": 0 }, + "3166": { "label": "20/60", "naklon": 0 }, + "3130": { "label": "20/61", "naklon": 0 }, + "3563": { "label": "20/62", "naklon": 0 }, + "3550": { "label": "20/63", "naklon": null }, + "3269": { "label": "20/67", "naklon": 0 }, + "2921": { "label": "21/1", "naklon": 0 }, + "2707": { "label": "21/2", "naklon": 0 }, + "2723": { "label": "21/3", "naklon": 0 }, + "2716": { "label": "21/4", "naklon": 0 }, + "2717": { "label": "21/5", "naklon": 0 }, + "2720": { "label": "21/6", "naklon": 0 }, + "2722": { "label": "21/7", "naklon": 0 }, + "2718": { "label": "21/8", "naklon": 0 }, + "2724": { "label": "21/9", "naklon": 0 }, + "2742": { "label": "21/10", "naklon": 0 }, + "2743": { "label": "21/11", "naklon": 0 }, + "2733": { "label": "21/12", "naklon": 0 }, + "2903": { "label": "21/14", "naklon": 0 }, + "2917": { "label": "21/15", "naklon": 0 }, + "2897": { "label": "21/16", "naklon": 0 }, + "2914": { "label": "21/17", "naklon": 0 }, + "2898": { "label": "21/18", "naklon": 0 }, + "2773": { "label": "21/19", "naklon": 0 }, + "2895": { "label": "21/20", "naklon": 0 }, + "2896": { "label": "21/21", "naklon": 0 }, + "2771": { "label": "21/22", "naklon": 0 }, + "2772": { "label": "21/23", "naklon": 0 }, + "2793": { "label": "21/24", "naklon": 0 }, + "2902": { "label": "21/25", "naklon": 0 }, + "2910": { "label": "21/26", "naklon": 0 }, + "2909": { "label": "21/27", "naklon": 0 }, + "2920": { "label": "21/28", "naklon": 0 }, + "2916": { "label": "21/29", "naklon": 0 }, + "2904": { "label": "21/30", "naklon": 0 }, + "2915": { "label": "21/31", "naklon": 0 }, + "2905": { "label": "21/32", "naklon": 0 }, + "2900": { "label": "21/33", "naklon": 0 }, + "2899": { "label": "21/34", "naklon": 0 }, + "2741": { "label": "21/36", "naklon": 0 }, + "2714": { "label": "21/37", "naklon": 0 }, + "2701": { "label": "21/38", "naklon": 0 }, + "2703": { "label": "21/39", "naklon": 0 }, + "2704": { "label": "21/40", "naklon": 0 }, + "2702": { "label": "21/41", "naklon": 0 }, + "2706": { "label": "21/42", "naklon": 0 }, + "2776": { "label": "21/43", "naklon": 0 }, + "2770": { "label": "21/44", "naklon": 0 }, + "2786": { "label": "21/45", "naklon": 0 }, + "2779": { "label": "21/46", "naklon": 0 }, + "2782": { "label": "21/47", "naklon": 0 }, + "2785": { "label": "21/48", "naklon": 0 }, + "2769": { "label": "21/49", "naklon": 0 }, + "3354": { "label": "21/50", "naklon": 0 }, + "2778": { "label": "21/51", "naklon": 0 }, + "2775": { "label": "21/52", "naklon": 0 }, + "2780": { "label": "21/53", "naklon": 0 }, + "2790": { "label": "21/54", "naklon": 0 }, + "2792": { "label": "21/55", "naklon": 0 }, + "2774": { "label": "21/56", "naklon": 0 }, + "2630": { "label": "22/1", "naklon": 0 }, + "2631": { "label": "22/2", "naklon": 0 }, + "2632": { "label": "22/3", "naklon": 0 }, + "2633": { "label": "22/4", "naklon": 0 }, + "2634": { "label": "22/5", "naklon": 0 }, + "2636": { "label": "22/6", "naklon": 0 }, + "4367": { "label": "22/7", "naklon": 0 }, + "2637": { "label": "22/8", "naklon": 0 }, + "2638": { "label": "22/9", "naklon": 0 }, + "2639": { "label": "22/10", "naklon": 0 }, + "2640": { "label": "22/11", "naklon": 0 }, + "2641": { "label": "22/12", "naklon": 0 }, + "2642": { "label": "22/13", "naklon": 0 }, + "2643": { "label": "22/14", "naklon": 0 }, + "2644": { "label": "22/15", "naklon": 0 }, + "2645": { "label": "22/16", "naklon": 0 }, + "2646": { "label": "22/17", "naklon": 0 }, + "2647": { "label": "22/18", "naklon": 0 }, + "2648": { "label": "22/19", "naklon": 0 }, + "2649": { "label": "22/20", "naklon": 0 }, + "2650": { "label": "22/21", "naklon": 0 }, + "2651": { "label": "22/22", "naklon": 0 }, + "4103": { "label": "22/23", "naklon": 0 }, + "2653": { "label": "22/24", "naklon": 0 }, + "2654": { "label": "22/25", "naklon": 0 }, + "2655": { "label": "22/26", "naklon": 0 }, + "2656": { "label": "22/27", "naklon": 0 }, + "2657": { "label": "22/28", "naklon": 0 }, + "2658": { "label": "22/29", "naklon": 0 }, + "2659": { "label": "22/30", "naklon": 0 }, + "2660": { "label": "22/31", "naklon": 0 }, + "2661": { "label": "22/32", "naklon": 0 }, + "3015": { "label": "22/32/1", "naklon": 0 }, + "2662": { "label": "22/33", "naklon": 0 }, + "2663": { "label": "22/34", "naklon": 0 }, + "2664": { "label": "22/35", "naklon": 0 }, + "2665": { "label": "22/36", "naklon": 0 }, + "2666": { "label": "22/37", "naklon": 0 }, + "2667": { "label": "22/38", "naklon": 0 }, + "2668": { "label": "22/39", "naklon": 0 }, + "2669": { "label": "22/40", "naklon": null }, + "2670": { "label": "22/41", "naklon": null }, + "2671": { "label": "22/42", "naklon": null }, + "3087": { "label": "23/9A", "naklon": 10 }, + "3090": { "label": "23/9B", "naklon": 10 }, + "3075": { "label": "23/1", "naklon": 0 }, + "3089": { "label": "23/2", "naklon": 0 }, + "3088": { "label": "23/3", "naklon": 0 }, + "3228": { "label": "23/4", "naklon": 10 }, + "2751": { "label": "23/5", "naklon": 10 }, + "3243": { "label": "23/6", "naklon": 10 }, + "4349": { "label": "23/7", "naklon": 10 }, + "3102": { "label": "23/8", "naklon": 10 }, + "3099": { "label": "23/10", "naklon": 10 }, + "3103": { "label": "23/11", "naklon": 10 }, + "3093": { "label": "23/12", "naklon": 10 }, + "3098": { "label": "23/13", "naklon": 10 }, + "3092": { "label": "23/14", "naklon": 10 }, + "3233": { "label": "23/15", "naklon": 0 }, + "3095": { "label": "23/16", "naklon": 0 }, + "4074": { "label": "23/17", "naklon": 0 }, + "2729": { "label": "23/18", "naklon": 0 }, + "3234": { "label": "23/19", "naklon": 0 }, + "3094": { "label": "23/20", "naklon": 0 }, + "2817": { "label": "23/21", "naklon": 0 }, + "3226": { "label": "23/22", "naklon": 0 }, + "3225": { "label": "23/23", "naklon": 0 }, + "3237": { "label": "23/24", "naklon": 0 }, + "4250": { "label": "23/25", "naklon": 0 }, + "3059": { "label": "23/26", "naklon": 10 }, + "3238": { "label": "23/27", "naklon": 10 }, + "3242": { "label": "23/28", "naklon": 10 }, + "3236": { "label": "23/29", "naklon": 10 }, + "3112": { "label": "23/30", "naklon": 10 }, + "3224": { "label": "23/31", "naklon": 0 }, + "4298": { "label": "23/32", "naklon": 10 }, + "4150": { "label": "23/33", "naklon": 10 }, + "3091": { "label": "23/34", "naklon": 10 }, + "3771": { "label": "25/1", "naklon": 5 }, + "3777": { "label": "25/2", "naklon": 5 }, + "3749": { "label": "25/3", "naklon": 5 }, + "3769": { "label": "25/4", "naklon": 5 }, + "3765": { "label": "25/5", "naklon": 5 }, + "3785": { "label": "25/6", "naklon": 5 }, + "3761": { "label": "25/7", "naklon": 5 }, + "3758": { "label": "25/8", "naklon": 5 }, + "3766": { "label": "25/9", "naklon": 5 }, + "3779": { "label": "25/10", "naklon": 5 }, + "3899": { "label": "25/11", "naklon": 10 }, + "3922": { "label": "25/12", "naklon": 10 }, + "3912": { "label": "25/13", "naklon": 10 }, + "3933": { "label": "25/14", "naklon": 10 }, + "3921": { "label": "25/15", "naklon": 10 }, + "4300": { "label": "25/16", "naklon": 10 }, + "3927": { "label": "25/17", "naklon": 10 }, + "3212": { "label": "25/18", "naklon": 10 }, + "3208": { "label": "25/19", "naklon": 10 }, + "3207": { "label": "25/20", "naklon": 10 }, + "4294": { "label": "25/21", "naklon": 10 }, + "3209": { "label": "25/22", "naklon": 10 }, + "3745": { "label": "25/23", "naklon": 10 }, + "3762": { "label": "25/24", "naklon": 10 }, + "3215": { "label": "25/25", "naklon": 10 }, + "3210": { "label": "25/26", "naklon": 10 }, + "3211": { "label": "25/27", "naklon": 10 }, + "3206": { "label": "25/28", "naklon": 10 }, + "3918": { "label": "25/29", "naklon": 5 }, + "3928": { "label": "25/30", "naklon": 5 }, + "3917": { "label": "25/31", "naklon": 5 }, + "4029": { "label": "25/32", "naklon": 0 }, + "4038": { "label": "25/33", "naklon": 0 }, + "4022": { "label": "25/34", "naklon": 0 }, + "3937": { "label": "25/35", "naklon": 0 }, + "3190": { "label": "25/36", "naklon": 0 }, + "3835": { "label": "25/37", "naklon": 0 }, + "3201": { "label": "25/38", "naklon": 0 }, + "3193": { "label": "25/39", "naklon": 0 }, + "3191": { "label": "25/40", "naklon": 0 }, + "3203": { "label": "25/41", "naklon": 0 }, + "4301": { "label": "25/42", "naklon": 0 }, + "3223": { "label": "25/43", "naklon": 0 }, + "3202": { "label": "25/44", "naklon": 0 }, + "3205": { "label": "25/45", "naklon": 0 }, + "3194": { "label": "25/46", "naklon": 0 }, + "3198": { "label": "25/47", "naklon": 0 }, + "3204": { "label": "25/48", "naklon": 0 }, + "3200": { "label": "25/49", "naklon": 0 }, + "3216": { "label": "25/50", "naklon": 0 }, + "3932": { "label": "25/51", "naklon": 5 }, + "3923": { "label": "25/52", "naklon": 5 }, + "3913": { "label": "25/53", "naklon": 5 }, + "3900": { "label": "25/54", "naklon": 5 }, + "4189": { "label": "25/55", "naklon": 10 }, + "4191": { "label": "25/56", "naklon": 10 }, + "3790": { "label": "25/57", "naklon": 10 }, + "4190": { "label": "25/58", "naklon": 10 }, + "4302": { "label": "25/59", "naklon": 0 }, + "4351": { "label": "25/60", "naklon": 0 }, + "4075": { "label": "25/61", "naklon": 0 }, + "4071": { "label": "25/62", "naklon": 0 }, + "3784": { "label": "25/63", "naklon": 0 }, + "4065": { "label": "25/64", "naklon": 0 }, + "4297": { "label": "25/65", "naklon": 0 }, + "4295": { "label": "25/66", "naklon": 0 }, + "4299": { "label": "25/67", "naklon": 0 }, + "3772": { "label": "25/68", "naklon": 0 }, + "3941": { "label": "25/69", "naklon": 0 }, + "3782": { "label": "25/70", "naklon": 0 }, + "4068": { "label": "25/71", "naklon": 0 }, + "4073": { "label": "25/72", "naklon": 0 }, + "3901": { "label": "25/73", "naklon": 5 }, + "4296": { "label": "25/74", "naklon": 5 }, + "3910": { "label": "25/75", "naklon": 5 }, + "4293": { "label": "25/76", "naklon": 5 }, + "3919": { "label": "25/77", "naklon": 5 }, + "3924": { "label": "25/78", "naklon": 5 }, + "3909": { "label": "25/79", "naklon": 5 }, + "3896": { "label": "25/80", "naklon": 5 }, + "3911": { "label": "25/81", "naklon": 5 }, + "2819": { "label": "25/82", "naklon": 15 }, + "3776": { "label": "25/83", "naklon": 15 }, + "3752": { "label": "25/84", "naklon": 15 }, + "4353": { "label": "25/85", "naklon": 15 }, + "3791": { "label": "25/86", "naklon": 0 }, + "3770": { "label": "25/87", "naklon": 0 }, + "3760": { "label": "25/88", "naklon": 0 }, + "3115": { "label": "25/89", "naklon": 0 }, + "3738": { "label": "25/90", "naklon": 0 }, + "3748": { "label": "25/91", "naklon": 0 }, + "3753": { "label": "25/92", "naklon": 0 }, + "3775": { "label": "25/93", "naklon": 0 }, + "3778": { "label": "25/94", "naklon": 5 }, + "4078": { "label": "25/95", "naklon": 5 }, + "4088": { "label": "25/96", "naklon": 5 }, + "3856": { "label": "25/97", "naklon": 5 }, + "4084": { "label": "25/98", "naklon": 5 }, + "4069": { "label": "25/99", "naklon": 5 }, + "4188": { "label": "25/100", "naklon": 5 }, + "4064": { "label": "25/101", "naklon": 5 }, + "3792": { "label": "25/102", "naklon": 5 }, + "3780": { "label": "25/103", "naklon": 5 }, + "4034": { "label": "25/104", "naklon": 5 }, + "4072": { "label": "25/105", "naklon": 5 }, + "3884": { "label": "25/106", "naklon": 5 }, + "3793": { "label": "25/107", "naklon": 5 }, + "3863": { "label": "25/108", "naklon": 5 }, + "3855": { "label": "25/109", "naklon": 5 }, + "3846": { "label": "33/1", "naklon": 0 }, + "3943": { "label": "33/2", "naklon": 0 }, + "3903": { "label": "33/3", "naklon": 0 }, + "3982": { "label": "33/4", "naklon": 0 }, + "3879": { "label": "33/5", "naklon": 0 }, + "3887": { "label": "33/6", "naklon": 0 }, + "3920": { "label": "33/7", "naklon": 5 }, + "3942": { "label": "33/8", "naklon": 5 }, + "3829": { "label": "33/9", "naklon": null }, + "3452": { "label": "34/79A", "naklon": 6 }, + "3460": { "label": "34/79B", "naklon": 6 }, + "3443": { "label": "34/90A", "naklon": 6 }, + "3445": { "label": "34/90B", "naklon": 6 }, + "3457": { "label": "34/90C", "naklon": 6 }, + "3461": { "label": "34/97A", "naklon": 6 }, + "3463": { "label": "34/97B", "naklon": 6 }, + "3426": { "label": "34/98A", "naklon": 6 }, + "3444": { "label": "34/98B", "naklon": 6 }, + "3453": { "label": "34/99A", "naklon": 6 }, + "3455": { "label": "34/99B", "naklon": 6 }, + "4009": { "label": "34/1", "naklon": 0 }, + "3602": { "label": "34/2", "naklon": 0 }, + "3441": { "label": "34/3", "naklon": 0 }, + "3464": { "label": "34/4", "naklon": 0 }, + "3883": { "label": "34/5", "naklon": 0 }, + "4098": { "label": "34/6", "naklon": 0 }, + "4003": { "label": "34/7", "naklon": 0 }, + "4004": { "label": "34/8", "naklon": 0 }, + "3888": { "label": "34/9", "naklon": 0 }, + "3997": { "label": "34/10", "naklon": 0 }, + "4006": { "label": "34/11", "naklon": 0 }, + "4000": { "label": "34/12", "naklon": 0 }, + "4011": { "label": "34/13", "naklon": 0 }, + "3999": { "label": "34/14", "naklon": 0 }, + "3981": { "label": "34/15", "naklon": 0 }, + "3988": { "label": "34/16", "naklon": 0 }, + "3986": { "label": "34/17", "naklon": 0 }, + "3998": { "label": "34/18", "naklon": 0 }, + "3983": { "label": "34/19", "naklon": 0 }, + "4005": { "label": "34/20", "naklon": 0 }, + "4001": { "label": "34/21", "naklon": 0 }, + "4008": { "label": "34/22", "naklon": 0 }, + "4002": { "label": "34/23", "naklon": 0 }, + "3996": { "label": "34/24", "naklon": 0 }, + "4007": { "label": "34/25", "naklon": 0 }, + "4113": { "label": "34/26", "naklon": 15 }, + "3595": { "label": "34/27", "naklon": 5 }, + "3599": { "label": "34/28", "naklon": 5 }, + "3601": { "label": "34/29", "naklon": 5 }, + "4205": { "label": "34/30", "naklon": 0 }, + "3987": { "label": "34/31", "naklon": null }, + "4214": { "label": "34/32", "naklon": 0 }, + "4226": { "label": "34/33", "naklon": 0 }, + "4209": { "label": "34/34", "naklon": 0 }, + "4201": { "label": "34/35", "naklon": 0 }, + "3440": { "label": "34/36", "naklon": 0 }, + "3465": { "label": "34/37", "naklon": 0 }, + "3446": { "label": "34/38", "naklon": 0 }, + "4039": { "label": "34/39", "naklon": 5 }, + "4057": { "label": "34/40", "naklon": 5 }, + "3985": { "label": "34/41", "naklon": 0 }, + "3882": { "label": "34/42", "naklon": 0 }, + "4040": { "label": "34/43", "naklon": 5 }, + "3231": { "label": "34/44", "naklon": 0 }, + "3227": { "label": "34/45", "naklon": 0 }, + "3431": { "label": "34/46", "naklon": 0 }, + "4013": { "label": "34/47", "naklon": 0 }, + "4045": { "label": "34/48", "naklon": 0 }, + "3949": { "label": "34/49", "naklon": 0 }, + "3953": { "label": "34/50", "naklon": 0 }, + "3952": { "label": "34/51", "naklon": 0 }, + "3995": { "label": "34/52", "naklon": 0 }, + "3992": { "label": "34/53", "naklon": 0 }, + "4198": { "label": "34/54", "naklon": 0 }, + "3935": { "label": "34/55", "naklon": 0 }, + "4050": { "label": "34/56", "naklon": 0 }, + "4049": { "label": "34/57", "naklon": 0 }, + "4054": { "label": "34/58", "naklon": 0 }, + "3663": { "label": "34/59", "naklon": 6 }, + "3661": { "label": "34/60", "naklon": 6 }, + "3664": { "label": "34/61", "naklon": 6 }, + "3660": { "label": "34/62", "naklon": 6 }, + "3662": { "label": "34/63", "naklon": 6 }, + "3665": { "label": "34/65", "naklon": 6 }, + "3667": { "label": "34/66", "naklon": 6 }, + "3675": { "label": "34/67", "naklon": 6 }, + "3666": { "label": "34/68", "naklon": 6 }, + "3652": { "label": "34/69", "naklon": 6 }, + "3458": { "label": "34/70", "naklon": 6 }, + "4425": { "label": "34/70/1", "naklon": 6 }, + "3459": { "label": "34/71", "naklon": 6 }, + "3435": { "label": "34/72", "naklon": 6 }, + "3448": { "label": "34/73", "naklon": 6 }, + "3451": { "label": "34/74", "naklon": 6 }, + "3442": { "label": "34/75", "naklon": 6 }, + "3449": { "label": "34/76", "naklon": 6 }, + "3450": { "label": "34/77", "naklon": 6 }, + "3433": { "label": "34/78", "naklon": 6 }, + "3432": { "label": "34/80", "naklon": 12 }, + "3470": { "label": "34/81", "naklon": 12 }, + "3438": { "label": "34/82", "naklon": 12 }, + "3439": { "label": "34/83", "naklon": 12 }, + "4028": { "label": "34/84", "naklon": 5 }, + "3596": { "label": "34/85", "naklon": 5 }, + "4021": { "label": "34/86", "naklon": 5 }, + "3437": { "label": "34/87", "naklon": 12 }, + "3428": { "label": "34/88", "naklon": 12 }, + "3430": { "label": "34/89", "naklon": 12 }, + "3454": { "label": "34/91", "naklon": 6 }, + "3492": { "label": "34/92", "naklon": 6 }, + "3462": { "label": "34/93", "naklon": 6 }, + "3427": { "label": "34/94", "naklon": 6 }, + "3434": { "label": "34/95", "naklon": 6 }, + "3456": { "label": "34/96", "naklon": 6 }, + "4307": { "label": "34/98/1", "naklon": 6 }, + "3968": { "label": "35/1", "naklon": 0 }, + "3969": { "label": "35/2", "naklon": 0 }, + "3947": { "label": "35/3", "naklon": 0 }, + "3979": { "label": "35/4", "naklon": 0 }, + "3959": { "label": "35/5", "naklon": 0 }, + "3948": { "label": "35/6", "naklon": 0 }, + "3961": { "label": "35/7", "naklon": 0 }, + "3956": { "label": "35/8", "naklon": 0 }, + "3604": { "label": "35/9", "naklon": 0 }, + "3944": { "label": "35/10", "naklon": 0 }, + "3960": { "label": "35/11", "naklon": 0 }, + "3958": { "label": "35/12", "naklon": 0 }, + "4036": { "label": "35/13", "naklon": 5 }, + "3893": { "label": "35/18", "naklon": 5 }, + "4108": { "label": "35/19", "naklon": 5 }, + "4017": { "label": "35/20", "naklon": 5 }, + "3963": { "label": "35/21", "naklon": 0 }, + "3658": { "label": "35/22", "naklon": 0 }, + "3975": { "label": "35/23", "naklon": 0 }, + "3980": { "label": "35/24", "naklon": 0 }, + "4012": { "label": "35/25", "naklon": 0 }, + "3655": { "label": "35/26", "naklon": 0 }, + "3962": { "label": "35/27", "naklon": 0 }, + "3945": { "label": "35/28", "naklon": 0 }, + "3569": { "label": "35/29", "naklon": 0 }, + "3429": { "label": "35/30", "naklon": 0 }, + "3657": { "label": "35/31", "naklon": 0 }, + "3646": { "label": "35/32", "naklon": 0 }, + "3622": { "label": "35/33", "naklon": 0 }, + "3612": { "label": "35/34", "naklon": 0 }, + "3955": { "label": "35/35", "naklon": 0 }, + "3878": { "label": "35/37", "naklon": 0 }, + "3965": { "label": "35/38", "naklon": 0 }, + "3970": { "label": "35/39", "naklon": 0 }, + "3611": { "label": "35/40", "naklon": 0 }, + "2635": { "label": "35/41", "naklon": 0 }, + "3978": { "label": "35/42", "naklon": 0 }, + "4213": { "label": "35/43", "naklon": 0 }, + "3984": { "label": "35/44", "naklon": 0 }, + "4218": { "label": "35/45", "naklon": 0 }, + "3973": { "label": "35/46", "naklon": 0 }, + "3974": { "label": "35/47", "naklon": 0 }, + "3759": { "label": "35/48", "naklon": 0 }, + "3844": { "label": "35/49", "naklon": 0 }, + "3804": { "label": "35/50", "naklon": 0 }, + "3831": { "label": "35/51", "naklon": 0 }, + "3643": { "label": "35/52", "naklon": 0 }, + "3966": { "label": "35/53", "naklon": 0 }, + "3971": { "label": "35/54", "naklon": 0 }, + "3650": { "label": "35/55", "naklon": 6 }, + "3651": { "label": "35/56", "naklon": 6 }, + "3669": { "label": "35/57", "naklon": 6 }, + "3648": { "label": "35/58", "naklon": 6 }, + "3645": { "label": "35/59", "naklon": 6 }, + "3659": { "label": "35/60", "naklon": 6 }, + "3647": { "label": "35/61", "naklon": 6 }, + "3644": { "label": "35/62", "naklon": 6 }, + "3671": { "label": "35/63", "naklon": 6 }, + "3682": { "label": "35/64", "naklon": 6 }, + "3672": { "label": "35/65", "naklon": 6 }, + "3683": { "label": "35/66", "naklon": 6 }, + "3673": { "label": "35/67", "naklon": 6 }, + "3674": { "label": "35/68", "naklon": 6 }, + "3679": { "label": "35/69", "naklon": 6 }, + "3649": { "label": "35/70", "naklon": 6 }, + "3687": { "label": "35/71", "naklon": 6 }, + "3677": { "label": "35/72", "naklon": 6 }, + "3690": { "label": "35/73", "naklon": 6 }, + "3691": { "label": "35/74", "naklon": 6 }, + "3676": { "label": "35/75", "naklon": 6 }, + "3680": { "label": "35/76", "naklon": 6 }, + "3668": { "label": "35/77", "naklon": 6 }, + "3681": { "label": "35/78", "naklon": 6 }, + "3670": { "label": "35/79", "naklon": 6 }, + "3689": { "label": "35/80", "naklon": 6 }, + "3678": { "label": "35/81", "naklon": 6 }, + "3693": { "label": "35/82", "naklon": 6 }, + "3654": { "label": "35/83", "naklon": null }, + "4086": { "label": "36/1", "naklon": 0 }, + "4085": { "label": "36/2", "naklon": 0 }, + "4083": { "label": "36/3", "naklon": 0 }, + "4087": { "label": "36/4", "naklon": 0 }, + "4077": { "label": "36/5", "naklon": 0 }, + "4082": { "label": "36/6", "naklon": 0 }, + "4186": { "label": "36/7", "naklon": 0 }, + "4206": { "label": "36/8", "naklon": 0 }, + "4080": { "label": "36/9", "naklon": 0 }, + "4081": { "label": "36/10", "naklon": 0 }, + "4210": { "label": "36/11", "naklon": 0 }, + "4079": { "label": "36/12", "naklon": 0 }, + "4076": { "label": "36/13", "naklon": 0 }, + "3852": { "label": "36/14", "naklon": 0 }, + "2813": { "label": "36/15", "naklon": 0 }, + "4219": { "label": "36/16", "naklon": 0 }, + "3104": { "label": "37/1A", "naklon": 15 }, + "3121": { "label": "37/1B", "naklon": 15 }, + "3113": { "label": "37/2", "naklon": 10 }, + "3118": { "label": "37/3", "naklon": 10 }, + "3111": { "label": "37/4", "naklon": 10 }, + "4020": { "label": "37/5", "naklon": 10 }, + "3119": { "label": "37/6", "naklon": 10 }, + "3110": { "label": "37/7", "naklon": 10 }, + "3108": { "label": "37/8", "naklon": 10 }, + "3107": { "label": "37/12", "naklon": 0 }, + "3199": { "label": "37/13", "naklon": 0 }, + "3120": { "label": "37/14", "naklon": 0 }, + "3122": { "label": "37/15", "naklon": 0 }, + "3908": { "label": "37/16", "naklon": 0 }, + "3114": { "label": "37/17", "naklon": 0 }, + "3105": { "label": "37/18", "naklon": 0 }, + "3116": { "label": "37/19", "naklon": 0 }, + "3106": { "label": "37/20", "naklon": 0 }, + "2887": { "label": "37/21", "naklon": 5 }, + "2888": { "label": "37/22", "naklon": 5 }, + "2877": { "label": "37/23", "naklon": 5 }, + "2891": { "label": "37/24", "naklon": 5 }, + "2886": { "label": "37/25", "naklon": 5 }, + "2892": { "label": "37/26", "naklon": 5 }, + "2882": { "label": "37/27", "naklon": 5 }, + "2883": { "label": "37/28", "naklon": 5 }, + "2876": { "label": "37/29", "naklon": 5 }, + "3109": { "label": "37/30", "naklon": 5 }, + "4152": { "label": "37/31", "naklon": 5 }, + "3117": { "label": "37/32", "naklon": 5 }, + "2870": { "label": "37/33", "naklon": 5 }, + "2867": { "label": "37/34", "naklon": 0 }, + "2865": { "label": "37/35", "naklon": 0 }, + "3096": { "label": "37/36", "naklon": 0 }, + "2871": { "label": "37/37", "naklon": 0 }, + "2884": { "label": "37/38", "naklon": 0 }, + "2855": { "label": "37/39", "naklon": 0 }, + "2878": { "label": "37/40", "naklon": 0 }, + "2889": { "label": "37/41", "naklon": 0 }, + "2879": { "label": "37/42", "naklon": 0 }, + "2850": { "label": "37/43", "naklon": 0 }, + "2894": { "label": "37/44", "naklon": 0 }, + "2880": { "label": "37/45", "naklon": 0 }, + "2893": { "label": "37/46", "naklon": 0 }, + "2890": { "label": "37/47", "naklon": 0 }, + "4355": { "label": "37/48", "naklon": 0 }, + "2885": { "label": "37/49", "naklon": 0 }, + "2875": { "label": "37/50", "naklon": 0 }, + "3486": { "label": "38/30A", "naklon": 5 }, + "3714": { "label": "38/30B", "naklon": 0 }, + "3483": { "label": "38/32A", "naklon": 5 }, + "3496": { "label": "38/32B", "naklon": 0 }, + "3487": { "label": "38/35A", "naklon": 5 }, + "3498": { "label": "38/35B", "naklon": 5 }, + "3578": { "label": "38/38A", "naklon": 5 }, + "3508": { "label": "38/38B", "naklon": 5 }, + "3787": { "label": "38/59A", "naklon": 5 }, + "3491": { "label": "38/59B", "naklon": 5 }, + "3568": { "label": "38/1", "naklon": null }, + "3502": { "label": "38/2", "naklon": 0 }, + "3836": { "label": "38/3", "naklon": 0 }, + "3588": { "label": "38/4", "naklon": 0 }, + "3493": { "label": "38/5", "naklon": 0 }, + "3580": { "label": "38/6", "naklon": 0 }, + "3572": { "label": "38/7", "naklon": 0 }, + "3506": { "label": "38/8", "naklon": 0 }, + "3503": { "label": "38/9", "naklon": 0 }, + "3579": { "label": "38/10", "naklon": 0 }, + "3586": { "label": "38/11", "naklon": 0 }, + "3495": { "label": "38/12", "naklon": 5 }, + "3492": { "label": "38/13", "naklon": 5 }, + "3532": { "label": "38/14", "naklon": 5 }, + "3574": { "label": "38/15", "naklon": 5 }, + "4140": { "label": "38/16", "naklon": 5 }, + "3795": { "label": "38/17", "naklon": 5 }, + "3788": { "label": "38/18", "naklon": 5 }, + "3796": { "label": "38/19", "naklon": 5 }, + "3797": { "label": "38/20", "naklon": 5 }, + "3798": { "label": "38/21", "naklon": 5 }, + "3786": { "label": "38/22", "naklon": 5 }, + "4067": { "label": "38/23", "naklon": 5 }, + "3773": { "label": "38/24", "naklon": 5 }, + "3774": { "label": "38/25", "naklon": 5 }, + "3789": { "label": "38/26", "naklon": 5 }, + "3520": { "label": "38/27", "naklon": null }, + "3577": { "label": "38/29", "naklon": 5 }, + "3530": { "label": "38/31", "naklon": null }, + "3488": { "label": "38/33", "naklon": 5 }, + "3505": { "label": "38/34", "naklon": 5 }, + "3497": { "label": "38/36", "naklon": 5 }, + "3490": { "label": "38/37", "naklon": 5 }, + "3585": { "label": "38/39", "naklon": 5 }, + "3582": { "label": "38/40", "naklon": 5 }, + "3507": { "label": "38/41", "naklon": 5 }, + "3484": { "label": "38/42", "naklon": 5 }, + "3501": { "label": "38/43", "naklon": 5 }, + "3581": { "label": "38/44", "naklon": 5 }, + "4192": { "label": "38/45", "naklon": 5 }, + "3576": { "label": "38/46", "naklon": 5 }, + "3489": { "label": "38/47", "naklon": 5 }, + "3573": { "label": "38/48", "naklon": 5 }, + "3504": { "label": "38/49", "naklon": 5 }, + "3794": { "label": "38/50", "naklon": 5 }, + "3485": { "label": "38/51", "naklon": 5 }, + "3482": { "label": "38/52", "naklon": 5 }, + "3575": { "label": "38/53", "naklon": 5 }, + "3499": { "label": "38/54", "naklon": 5 }, + "3494": { "label": "38/55", "naklon": 5 }, + "3583": { "label": "38/56", "naklon": 5 }, + "3570": { "label": "38/57", "naklon": 5 }, + "3500": { "label": "38/58", "naklon": 0 }, + "3510": { "label": "38/63", "naklon": null }, + "3512": { "label": "38/64", "naklon": null }, + "3535": { "label": "38/67", "naklon": null }, + "3531": { "label": "38/68", "naklon": null }, + "3537": { "label": "38/69", "naklon": null }, + "3522": { "label": "39/1", "naklon": 10 }, + "4018": { "label": "39/2", "naklon": 10 }, + "4019": { "label": "39/3", "naklon": 10 }, + "4154": { "label": "39/4", "naklon": 5 }, + "3907": { "label": "39/5", "naklon": 5 }, + "4148": { "label": "39/6", "naklon": 0 }, + "4153": { "label": "39/7", "naklon": 0 }, + "3938": { "label": "39/8", "naklon": 0 }, + "3802": { "label": "39/9", "naklon": 0 }, + "4015": { "label": "39/10", "naklon": 0 }, + "3929": { "label": "39/11", "naklon": 0 }, + "3946": { "label": "39/12", "naklon": 0 }, + "4014": { "label": "39/13", "naklon": 0 }, + "4155": { "label": "39/14", "naklon": 0 }, + "4149": { "label": "39/15", "naklon": 0 }, + "3642": { "label": "39/16", "naklon": 0 }, + "3636": { "label": "39/17", "naklon": 5 }, + "3991": { "label": "39/18", "naklon": 0 }, + "3994": { "label": "39/19", "naklon": 0 }, + "3990": { "label": "39/20", "naklon": 0 }, + "3967": { "label": "39/21", "naklon": 0 }, + "3977": { "label": "39/22", "naklon": 0 }, + "3757": { "label": "39/23", "naklon": 15 }, + "3633": { "label": "39/24", "naklon": 15 }, + "3744": { "label": "39/25", "naklon": 15 }, + "4023": { "label": "39/26", "naklon": 5 }, + "3720": { "label": "39/27", "naklon": 5 }, + "3734": { "label": "39/28", "naklon": 5 }, + "3741": { "label": "39/29", "naklon": 5 }, + "3721": { "label": "39/30", "naklon": 5 }, + "3845": { "label": "39/31", "naklon": 0 }, + "3840": { "label": "39/32", "naklon": 0 }, + "3837": { "label": "39/33", "naklon": null }, + "3839": { "label": "39/34", "naklon": 0 }, + "3542": { "label": "41/1", "naklon": null }, + "3566": { "label": "41/2", "naklon": null }, + "3548": { "label": "41/3", "naklon": null }, + "3515": { "label": "41/4", "naklon": null }, + "3559": { "label": "41/5", "naklon": null }, + "3509": { "label": "41/6", "naklon": null }, + "3524": { "label": "41/7", "naklon": null }, + "3518": { "label": "41/8", "naklon": null }, + "3182": { "label": "41/9", "naklon": null }, + "3187": { "label": "41/10", "naklon": null }, + "3195": { "label": "41/11", "naklon": 0 }, + "3857": { "label": "41/12", "naklon": 0 }, + "3183": { "label": "41/13", "naklon": 0 }, + "3177": { "label": "41/14", "naklon": 0 }, + "3189": { "label": "41/15", "naklon": 0 }, + "3186": { "label": "41/16", "naklon": 0 }, + "3178": { "label": "42/1", "naklon": 0 }, + "3219": { "label": "42/2", "naklon": 0 }, + "3475": { "label": "42/3", "naklon": 0 }, + "3175": { "label": "42/4", "naklon": 0 }, + "3222": { "label": "42/5", "naklon": 0 }, + "3221": { "label": "42/6", "naklon": 0 }, + "3181": { "label": "42/7", "naklon": 0 }, + "3180": { "label": "42/8", "naklon": 0 }, + "3218": { "label": "42/9", "naklon": 0 }, + "3176": { "label": "42/10", "naklon": 0 }, + "3174": { "label": "42/11", "naklon": 0 }, + "3220": { "label": "42/12", "naklon": 0 }, + "3533": { "label": "42/13", "naklon": null }, + "3543": { "label": "42/14", "naklon": null }, + "3554": { "label": "42/15", "naklon": null }, + "3549": { "label": "42/16", "naklon": null }, + "2857": { "label": "43/1", "naklon": 5 }, + "2752": { "label": "43/2", "naklon": 5 }, + "2753": { "label": "43/3", "naklon": 5 }, + "3024": { "label": "43/4", "naklon": 5 }, + "2754": { "label": "43/5", "naklon": 5 }, + "4423": { "label": "43/6", "naklon": 5 }, + "4368": { "label": "43/7", "naklon": 5 }, + "2978": { "label": "43/8", "naklon": 5 }, + "2868": { "label": "43/9", "naklon": 5 }, + "4377": { "label": "43/10", "naklon": 5 }, + "2757": { "label": "43/11", "naklon": 5 }, + "2970": { "label": "43/12", "naklon": 5 }, + "2758": { "label": "43/13", "naklon": 5 }, + "4378": { "label": "43/14", "naklon": 5 }, + "2759": { "label": "43/15", "naklon": 5 }, + "4342": { "label": "43/16", "naklon": 5 }, + "3026": { "label": "43/17", "naklon": null }, + "2986": { "label": "43/18", "naklon": null }, + "4343": { "label": "43/19", "naklon": null }, + "2760": { "label": "43/20", "naklon": null }, + "4379": { "label": "43/21", "naklon": null }, + "2971": { "label": "43/22", "naklon": null }, + "2761": { "label": "43/23", "naklon": null }, + "2762": { "label": "43/24", "naklon": null }, + "4339": { "label": "43/25", "naklon": null }, + "4380": { "label": "43/26", "naklon": null }, + "2975": { "label": "43/27", "naklon": null }, + "3003": { "label": "43/28", "naklon": null }, + "4338": { "label": "43/29", "naklon": null }, + "3002": { "label": "43/30", "naklon": null }, + "4345": { "label": "43/31", "naklon": null }, + "2979": { "label": "43/32", "naklon": null }, + "2989": { "label": "43/33", "naklon": null }, + "2996": { "label": "43/34", "naklon": null }, + "2972": { "label": "43/35", "naklon": null }, + "2988": { "label": "43/36", "naklon": null }, + "4344": { "label": "43/37", "naklon": null }, + "3022": { "label": "43/38", "naklon": null }, + "4341": { "label": "43/39", "naklon": null }, + "2983": { "label": "43/40", "naklon": null }, + "2995": { "label": "43/41", "naklon": null }, + "2763": { "label": "43/42", "naklon": null }, + "2764": { "label": "43/43", "naklon": null }, + "2765": { "label": "43/44", "naklon": null }, + "2766": { "label": "43/45", "naklon": null }, + "2767": { "label": "43/46", "naklon": null }, + "2768": { "label": "43/47", "naklon": null }, + "3018": { "label": "43/48", "naklon": null }, + "2982": { "label": "43/49", "naklon": null }, + "3019": { "label": "43/50", "naklon": 0 }, + "3013": { "label": "43/51", "naklon": null }, + "3007": { "label": "43/52", "naklon": null }, + "2980": { "label": "43/53", "naklon": null }, + "3011": { "label": "43/54", "naklon": null }, + "2672": { "label": "43/55", "naklon": null }, + "2673": { "label": "43/56", "naklon": null }, + "2674": { "label": "43/57", "naklon": null }, + "2675": { "label": "43/58", "naklon": null }, + "2676": { "label": "43/59", "naklon": null }, + "2677": { "label": "43/60", "naklon": null }, + "2678": { "label": "43/61", "naklon": null }, + "2679": { "label": "43/62", "naklon": null }, + "2680": { "label": "43/63", "naklon": null }, + "2840": { "label": "43/64", "naklon": null }, + "2682": { "label": "43/65", "naklon": null }, + "2683": { "label": "43/66", "naklon": null }, + "2684": { "label": "43/67", "naklon": 0 }, + "2685": { "label": "43/68", "naklon": null }, + "2686": { "label": "43/69", "naklon": null }, + "2687": { "label": "43/70", "naklon": null }, + "2688": { "label": "43/71", "naklon": null }, + "2689": { "label": "43/72", "naklon": null }, + "2690": { "label": "43/73", "naklon": null }, + "2691": { "label": "43/74", "naklon": null }, + "2692": { "label": "43/75", "naklon": null }, + "2693": { "label": "43/76", "naklon": 0 }, + "2694": { "label": "43/77", "naklon": null }, + "2695": { "label": "43/78", "naklon": null }, + "2696": { "label": "43/79", "naklon": 0 }, + "2697": { "label": "43/80", "naklon": null }, + "2698": { "label": "43/81", "naklon": 0 }, + "2699": { "label": "43/82", "naklon": null }, + "2700": { "label": "43/83", "naklon": 0 }, + "2744": { "label": "43/84", "naklon": null }, + "2745": { "label": "43/85", "naklon": 0 }, + "2746": { "label": "43/86", "naklon": null }, + "2747": { "label": "43/87", "naklon": 0 }, + "2748": { "label": "43/88", "naklon": null }, + "2749": { "label": "43/89", "naklon": 0 }, + "2841": { "label": "43/90", "naklon": null }, + "4237": { "label": "45/1", "naklon": 5 }, + "4226": { "label": "45/2", "naklon": 5 }, + "4242": { "label": "45/3", "naklon": 5 }, + "4179": { "label": "45/4", "naklon": 5 }, + "4247": { "label": "45/5", "naklon": 5 }, + "4245": { "label": "45/6", "naklon": 5 }, + "3872": { "label": "45/7", "naklon": 5 }, + "4175": { "label": "45/8", "naklon": 5 }, + "4236": { "label": "45/9", "naklon": 5 }, + "4170": { "label": "45/10", "naklon": 5 }, + "4238": { "label": "45/11", "naklon": 5 }, + "4246": { "label": "45/12", "naklon": 5 }, + "4166": { "label": "45/13", "naklon": 5 }, + "4227": { "label": "45/14", "naklon": 5 }, + "4171": { "label": "45/15", "naklon": 5 }, + "4180": { "label": "45/16", "naklon": 5 }, + "4244": { "label": "45/17", "naklon": 5 }, + "4199": { "label": "45/18", "naklon": 5 }, + "4239": { "label": "45/19", "naklon": 5 }, + "4207": { "label": "45/20", "naklon": 5 }, + "4223": { "label": "45/21", "naklon": 5 }, + "4230": { "label": "45/22", "naklon": 5 }, + "4233": { "label": "45/23", "naklon": 5 }, + "4222": { "label": "45/24", "naklon": 5 }, + "4217": { "label": "45/25", "naklon": 5 }, + "4243": { "label": "45/26", "naklon": 5 }, + "4200": { "label": "45/27", "naklon": 5 }, + "4228": { "label": "45/28", "naklon": 5 }, + "4211": { "label": "45/29", "naklon": 5 }, + "4234": { "label": "45/30", "naklon": 5 }, + "4235": { "label": "45/31", "naklon": 5 }, + "4203": { "label": "45/32", "naklon": 5 }, + "4240": { "label": "45/33", "naklon": 5 }, + "4224": { "label": "45/34", "naklon": 5 }, + "4232": { "label": "45/35", "naklon": 5 }, + "4231": { "label": "45/36", "naklon": 5 }, + "4161": { "label": "45/37", "naklon": 5 }, + "4225": { "label": "45/38", "naklon": 5 }, + "4241": { "label": "45/39", "naklon": 5 }, + "4229": { "label": "45/40", "naklon": 5 }, + "4221": { "label": "45/41", "naklon": 5 }, + "4212": { "label": "45/42", "naklon": 5 }, + "4216": { "label": "45/43", "naklon": 5 }, + "3864": { "label": "45/44", "naklon": null }, + "3806": { "label": "46/1", "naklon": 5 }, + "3813": { "label": "46/2", "naklon": 5 }, + "3815": { "label": "46/3", "naklon": 5 }, + "3807": { "label": "46/4", "naklon": 5 }, + "3895": { "label": "46/5", "naklon": 5 }, + "3809": { "label": "46/6", "naklon": 5 }, + "3820": { "label": "46/7", "naklon": 5 }, + "3805": { "label": "46/8", "naklon": 5 }, + "3894": { "label": "46/9", "naklon": 0 }, + "4055": { "label": "46/10", "naklon": 0 }, + "3812": { "label": "46/11", "naklon": 5 }, + "3822": { "label": "46/12", "naklon": 5 }, + "3821": { "label": "46/13", "naklon": 5 }, + "3808": { "label": "46/14", "naklon": 5 }, + "3799": { "label": "46/15", "naklon": 5 }, + "3816": { "label": "46/16", "naklon": 5 }, + "3751": { "label": "46/17", "naklon": 5 }, + "3814": { "label": "46/18", "naklon": 5 }, + "4044": { "label": "46/19", "naklon": 0 }, + "3931": { "label": "46/20", "naklon": 0 }, + "3902": { "label": "46/21", "naklon": 5 }, + "3916": { "label": "46/22", "naklon": 5 }, + "3892": { "label": "46/23", "naklon": 5 }, + "3914": { "label": "46/24", "naklon": 5 }, + "3898": { "label": "46/25", "naklon": 5 }, + "3897": { "label": "46/26", "naklon": 5 }, + "3885": { "label": "46/27", "naklon": 5 }, + "3906": { "label": "46/28", "naklon": 5 }, + "3930": { "label": "46/29", "naklon": 0 }, + "3936": { "label": "46/30", "naklon": 0 }, + "3860": { "label": "46/31", "naklon": 5 }, + "3841": { "label": "46/32", "naklon": 5 }, + "3873": { "label": "46/33", "naklon": 5 }, + "3854": { "label": "46/34", "naklon": 5 }, + "3939": { "label": "46/35", "naklon": 5 }, + "3858": { "label": "46/36", "naklon": 5 }, + "3940": { "label": "46/37", "naklon": 5 }, + "4035": { "label": "46/38", "naklon": 5 }, + "3373": { "label": "47/1", "naklon": 0 }, + "3374": { "label": "47/2", "naklon": 0 }, + "3384": { "label": "47/3", "naklon": 0 }, + "3385": { "label": "47/4", "naklon": 0 }, + "4051": { "label": "48/1", "naklon": 5 }, + "4041": { "label": "48/2", "naklon": 5 }, + "4056": { "label": "48/3", "naklon": 5 }, + "3875": { "label": "48/4", "naklon": 5 }, + "4061": { "label": "48/5", "naklon": 5 }, + "4047": { "label": "48/6", "naklon": 5 }, + "4060": { "label": "48/7", "naklon": 5 }, + "4059": { "label": "48/8", "naklon": 5 }, + "4058": { "label": "48/9", "naklon": 5 }, + "3635": { "label": "48/10", "naklon": 5 }, + "3640": { "label": "48/11", "naklon": 5 }, + "3747": { "label": "48/12", "naklon": 5 }, + "3629": { "label": "48/13", "naklon": 5 }, + "4048": { "label": "48/14", "naklon": 5 }, + "4063": { "label": "48/15", "naklon": 5 }, + "4062": { "label": "48/16", "naklon": 5 }, + "4043": { "label": "48/17", "naklon": 5 }, + "4052": { "label": "48/18", "naklon": 5 }, + "4042": { "label": "48/19", "naklon": 5 }, + "4053": { "label": "48/20", "naklon": 5 }, + "4167": { "label": "50/15A", "naklon": null }, + "4159": { "label": "50/15B", "naklon": null }, + "4183": { "label": "50/1", "naklon": 0 }, + "4157": { "label": "50/2", "naklon": 0 }, + "4160": { "label": "50/3", "naklon": 0 }, + "4173": { "label": "50/4", "naklon": 0 }, + "4177": { "label": "50/5", "naklon": 0 }, + "4174": { "label": "50/6", "naklon": 0 }, + "4178": { "label": "50/7", "naklon": 0 }, + "4195": { "label": "50/8", "naklon": 0 }, + "4169": { "label": "50/9", "naklon": 0 }, + "4162": { "label": "50/10", "naklon": 0 }, + "4158": { "label": "50/11", "naklon": 0 }, + "4182": { "label": "50/12", "naklon": 0 }, + "4194": { "label": "50/13", "naklon": 0 }, + "4184": { "label": "50/14", "naklon": 0 }, + "4197": { "label": "50/16", "naklon": null }, + "4164": { "label": "50/17", "naklon": null }, + "3306": { "label": "50/18", "naklon": null }, + "4168": { "label": "50/19", "naklon": null }, + "4193": { "label": "50/20", "naklon": null }, + "4187": { "label": "50/21", "naklon": null }, + "4163": { "label": "50/22", "naklon": null }, + "4165": { "label": "50/23", "naklon": null }, + "4185": { "label": "50/24", "naklon": null }, + "3904": { "label": "50/25", "naklon": null }, + "2619": { "label": "53/1", "naklon": 0 }, + "2623": { "label": "53/2", "naklon": 0 }, + "2617": { "label": "53/3", "naklon": 0 }, + "2622": { "label": "53/4", "naklon": 0 }, + "2618": { "label": "53/5", "naklon": 0 }, + "2626": { "label": "53/6", "naklon": 0 }, + "2869": { "label": "53/7", "naklon": 0 }, + "2613": { "label": "53/8", "naklon": 0 }, + "2608": { "label": "53/9", "naklon": 0 }, + "2611": { "label": "53/10", "naklon": 0 }, + "2598": { "label": "53/11", "naklon": 0 }, + "3528": { "label": "53/12", "naklon": 0 }, + "3545": { "label": "53/13", "naklon": 0 }, + "2620": { "label": "53/14", "naklon": 0 }, + "2612": { "label": "53/15", "naklon": 0 }, + "2615": { "label": "53/16", "naklon": 0 }, + "3722": { "label": "53/17", "naklon": 0 }, + "2624": { "label": "53/18", "naklon": 0 }, + "2609": { "label": "53/19", "naklon": 0 }, + "2625": { "label": "53/20", "naklon": 0 }, + "2602": { "label": "53/21", "naklon": 0 }, + "2610": { "label": "53/22", "naklon": 0 }, + "2599": { "label": "53/23", "naklon": 0 }, + "2605": { "label": "53/24", "naklon": 0 }, + "2593": { "label": "53/25", "naklon": 0 }, + "3074": { "label": "53/26", "naklon": 0 }, + "2740": { "label": "53/27", "naklon": 0 }, + "2614": { "label": "53/28", "naklon": 0 }, + "2601": { "label": "53/29", "naklon": 0 }, + "4196": { "label": "53/30", "naklon": 0 }, + "2607": { "label": "53/31", "naklon": 0 }, + "2582": { "label": "53/32", "naklon": 0 }, + "2594": { "label": "53/33", "naklon": 0 }, + "2589": { "label": "53/34", "naklon": 0 }, + "2596": { "label": "53/35", "naklon": 0 }, + "2603": { "label": "53/36", "naklon": 0 }, + "2597": { "label": "53/37", "naklon": 0 }, + "2590": { "label": "53/38", "naklon": 0 }, + "2581": { "label": "53/39", "naklon": 0 }, + "2583": { "label": "53/40", "naklon": 0 }, + "2580": { "label": "53/41", "naklon": 0 }, + "2579": { "label": "53/42", "naklon": 0 }, + "2797": { "label": "53/43", "naklon": 0 }, + "2577": { "label": "53/44", "naklon": 0 }, + "2586": { "label": "53/45", "naklon": 0 }, + "2588": { "label": "53/46", "naklon": 0 }, + "2591": { "label": "53/47", "naklon": 0 }, + "2592": { "label": "53/48", "naklon": 0 }, + "2573": { "label": "53/49", "naklon": 0 }, + "2595": { "label": "53/50", "naklon": 0 }, + "2587": { "label": "53/51", "naklon": 0 }, + "2578": { "label": "53/52", "naklon": 0 }, + "2574": { "label": "53/53", "naklon": 0 }, + "2571": { "label": "53/54", "naklon": 0 }, + "2570": { "label": "53/55", "naklon": 0 }, + "2576": { "label": "53/56", "naklon": 0 }, + "2881": { "label": "53/57", "naklon": 0 }, + "2575": { "label": "53/58", "naklon": 0 }, + "2572": { "label": "53/59", "naklon": 0 }, + "2569": { "label": "53/60", "naklon": 0 }, + "4324": { "label": "55/1", "naklon": 0 }, + "4319": { "label": "55/2", "naklon": 0 }, + "4327": { "label": "55/3", "naklon": 0 }, + "4333": { "label": "55/4", "naklon": 0 }, + "4332": { "label": "55/5", "naklon": 0 }, + "4320": { "label": "55/6", "naklon": 0 }, + "4317": { "label": "55/7", "naklon": 0 }, + "4318": { "label": "55/8", "naklon": 0 }, + "4328": { "label": "55/9", "naklon": 0 }, + "4323": { "label": "55/10", "naklon": 0 }, + "4325": { "label": "55/11", "naklon": 0 }, + "4326": { "label": "55/12", "naklon": 0 }, + "4316": { "label": "55/13", "naklon": 0 }, + "4322": { "label": "55/14", "naklon": 0 }, + "4331": { "label": "55/15", "naklon": 0 }, + "4321": { "label": "55/16", "naklon": 0 }, + "4315": { "label": "55/17", "naklon": 0 }, + "4329": { "label": "55/18", "naklon": 0 }, + "4334": { "label": "55/19", "naklon": 0 }, + "4330": { "label": "55/20", "naklon": 0 } +}; + + +let svetlaSorted = [{ "label": "1/3A", "node": 3993, "naklon": 0 }, +{ "label": "1/3B", "node": 3989, "naklon": 15 }, +{ "label": "1/1", "node": 3976, "naklon": 0 }, +{ "label": "1/2", "node": 4181, "naklon": 0 }, +{ "label": "1/4", "node": 4376, "naklon": 15 }, +{ "label": "1/5", "node": 3868, "naklon": 15 }, +{ "label": "1/6", "node": 3728, "naklon": 15 }, +{ "label": "1/7", "node": 3730, "naklon": 0 }, +{ "label": "1/8", "node": 4374, "naklon": 0 }, +{ "label": "1/9", "node": 3718, "naklon": 15 }, +{ "label": "1/10", "node": 4375, "naklon": 15 }, +{ "label": "1/11", "node": 4172, "naklon": 15 }, +{ "label": "1/12", "node": 4176, "naklon": 15 }, +{ "label": "2/1", "node": 3800, "naklon": 5 }, +{ "label": "2/2", "node": 3823, "naklon": 5 }, +{ "label": "2/3", "node": 3905, "naklon": 5 }, +{ "label": "2/4", "node": 3803, "naklon": 5 }, +{ "label": "2/5", "node": 3817, "naklon": 5 }, +{ "label": "2/6", "node": 3818, "naklon": 5 }, +{ "label": "2/7", "node": 3811, "naklon": 5 }, +{ "label": "2/8", "node": 3915, "naklon": 5 }, +{ "label": "2/9", "node": 3843, "naklon": 10 }, +{ "label": "2/10", "node": 3827, "naklon": 10 }, +{ "label": "2/11", "node": 4220, "naklon": 10 }, +{ "label": "2/12", "node": 3826, "naklon": 10 }, +{ "label": "2/13", "node": 3834, "naklon": 10 }, +{ "label": "2/14", "node": 3838, "naklon": 10 }, +{ "label": "2/15", "node": 2823, "naklon": 10 }, +{ "label": "2/16", "node": 3750, "naklon": 10 }, +{ "label": "2/17", "node": 3378, "naklon": 0 }, +{ "label": "2/18", "node": 3376, "naklon": 0 }, +{ "label": "2/19", "node": 3379, "naklon": 0 }, +{ "label": "2/20", "node": 3285, "naklon": 0 }, +{ "label": "2/21", "node": 3382, "naklon": 0 }, +{ "label": "2/22", "node": 3383, "naklon": 0 }, +{ "label": "2/24", "node": 3375, "naklon": 0 }, +{ "label": "2/25", "node": 3381, "naklon": 0 }, +{ "label": "2/26", "node": 3380, "naklon": 0 }, +{ "label": "2/27", "node": 3828, "naklon": 10 }, +{ "label": "2/28", "node": 3377, "naklon": 0 }, +{ "label": "7/1", "node": 3591, "naklon": 0 }, +{ "label": "7/2", "node": 3587, "naklon": 0 }, +{ "label": "7/3", "node": 3468, "naklon": 0 }, +{ "label": "7/4", "node": 3466, "naklon": 0 }, +{ "label": "7/5", "node": 3474, "naklon": 0 }, +{ "label": "7/6", "node": 3481, "naklon": 0 }, +{ "label": "7/7", "node": 3589, "naklon": 0 }, +{ "label": "7/8", "node": 3472, "naklon": 0 }, +{ "label": "7/9", "node": 3473, "naklon": 0 }, +{ "label": "7/10", "node": 3584, "naklon": 0 }, +{ "label": "7/11", "node": 3571, "naklon": 0 }, +{ "label": "7/12", "node": 3476, "naklon": 0 }, +{ "label": "7/13", "node": 3590, "naklon": 0 }, +{ "label": "7/14", "node": 3478, "naklon": 0 }, +{ "label": "7/15", "node": 3471, "naklon": 0 }, +{ "label": "7/16", "node": 3467, "naklon": 0 }, +{ "label": "7/17", "node": 3479, "naklon": 0 }, +{ "label": "7/18", "node": 3480, "naklon": 0 }, +{ "label": "7/19", "node": 3477, "naklon": 0 }, +{ "label": "12/1", "node": 3362, "naklon": 0 }, +{ "label": "12/2", "node": 3355, "naklon": 0 }, +{ "label": "12/3", "node": 3356, "naklon": 0 }, +{ "label": "12/4", "node": 3349, "naklon": 0 }, +{ "label": "12/5", "node": 3357, "naklon": 0 }, +{ "label": "12/6", "node": 3350, "naklon": 0 }, +{ "label": "12/7", "node": 3353, "naklon": 0 }, +{ "label": "12/8", "node": 3539, "naklon": 0 }, +{ "label": "12/9", "node": 3050, "naklon": 0 }, +{ "label": "12/10", "node": 3361, "naklon": 0 }, +{ "label": "12/11", "node": 3360, "naklon": 0 }, +{ "label": "12/12", "node": 3358, "naklon": 0 }, +{ "label": "12/13", "node": 3541, "naklon": 0 }, +{ "label": "12/14", "node": 3551, "naklon": 0 }, +{ "label": "12/15", "node": 3514, "naklon": 0 }, +{ "label": "12/16", "node": 3547, "naklon": 0 }, +{ "label": "12/17", "node": 3562, "naklon": 0 }, +{ "label": "12/18", "node": 3525, "naklon": 0 }, +{ "label": "12/19", "node": 3558, "naklon": 0 }, +{ "label": "12/20", "node": 3511, "naklon": 0 }, +{ "label": "12/21", "node": 3058, "naklon": 0 }, +{ "label": "12/22", "node": 3062, "naklon": 0 }, +{ "label": "12/23", "node": 3070, "naklon": 0 }, +{ "label": "12/24", "node": 3447, "naklon": 0 }, +{ "label": "12/25", "node": 3056, "naklon": 0 }, +{ "label": "12/26", "node": 3057, "naklon": 0 }, +{ "label": "12/27", "node": 3071, "naklon": 0 }, +{ "label": "12/28", "node": 3061, "naklon": 0 }, +{ "label": "12/29", "node": 3069, "naklon": 0 }, +{ "label": "12/30", "node": 3077, "naklon": 0 }, +{ "label": "12/31", "node": 3080, "naklon": 0 }, +{ "label": "12/32", "node": 3081, "naklon": 0 }, +{ "label": "12/33", "node": 3078, "naklon": 0 }, +{ "label": "12/34", "node": 4037, "naklon": 0 }, +{ "label": "12/35", "node": 3067, "naklon": 0 }, +{ "label": "12/36", "node": 3051, "naklon": 0 }, +{ "label": "12/37", "node": 2924, "naklon": 0 }, +{ "label": "12/38", "node": 3060, "naklon": 0 }, +{ "label": "12/39", "node": 3073, "naklon": 0 }, +{ "label": "12/40", "node": 3469, "naklon": 0 }, +{ "label": "12/41", "node": 2923, "naklon": 0 }, +{ "label": "12/42", "node": 2925, "naklon": 0 }, +{ "label": "12/43", "node": 3359, "naklon": 0 }, +{ "label": "12/44", "node": 3055, "naklon": 0 }, +{ "label": "12/45", "node": 2922, "naklon": 0 }, +{ "label": "12/46", "node": 3084, "naklon": 0 }, +{ "label": "12/47", "node": 3064, "naklon": 0 }, +{ "label": "12/48", "node": 3066, "naklon": 0 }, +{ "label": "12/49", "node": 3072, "naklon": 0 }, +{ "label": "13/13A", "node": 3415, "naklon": 0 }, +{ "label": "13/13B", "node": 3409, "naklon": 0 }, +{ "label": "13/13C", "node": 3399, "naklon": 0 }, +{ "label": "13/29A", "node": 3410, "naklon": 0 }, +{ "label": "13/29B", "node": 3407, "naklon": 0 }, +{ "label": "13/34A", "node": 3405, "naklon": 0 }, +{ "label": "13/34B", "node": 3404, "naklon": 0 }, +{ "label": "13/45A", "node": 3392, "naklon": 0 }, +{ "label": "13/45B", "node": 3386, "naklon": 0 }, +{ "label": "13/60A", "node": 3303, "naklon": 3 }, +{ "label": "13/60B", "node": 3302, "naklon": 3 }, +{ "label": "13/70A", "node": 3319, "naklon": 6 }, +{ "label": "13/70B", "node": 3317, "naklon": 6 }, +{ "label": "13/70C", "node": 3326, "naklon": 6 }, +{ "label": "13/73A", "node": 3351, "naklon": 6 }, +{ "label": "13/73B", "node": 3313, "naklon": 6 }, +{ "label": "13/83A", "node": 3316, "naklon": 0 }, +{ "label": "13/83B", "node": 3320, "naklon": 0 }, +{ "label": "13/95A", "node": 3336, "naklon": 0 }, +{ "label": "13/95B", "node": 3323, "naklon": 0 }, +{ "label": "13/98A", "node": 3339, "naklon": 0 }, +{ "label": "13/98B", "node": 3333, "naklon": 0 }, +{ "label": "13/1", "node": 3425, "naklon": 0 }, +{ "label": "13/2", "node": 3419, "naklon": 0 }, +{ "label": "13/3", "node": 3416, "naklon": 0 }, +{ "label": "13/4", "node": 3332, "naklon": 0 }, +{ "label": "13/5", "node": 3422, "naklon": 0 }, +{ "label": "13/6", "node": 3417, "naklon": 0 }, +{ "label": "13/7", "node": 3418, "naklon": 0 }, +{ "label": "13/8", "node": 3424, "naklon": 0 }, +{ "label": "13/9", "node": 3334, "naklon": 0 }, +{ "label": "13/10", "node": 4363, "naklon": 0 }, +{ "label": "13/11", "node": 3423, "naklon": 0 }, +{ "label": "13/12", "node": 3406, "naklon": 0 }, +{ "label": "13/14", "node": 3411, "naklon": 0 }, +{ "label": "13/15", "node": 3412, "naklon": 0 }, +{ "label": "13/16", "node": 3413, "naklon": 0 }, +{ "label": "13/17", "node": 3414, "naklon": 0 }, +{ "label": "13/18", "node": 3391, "naklon": 0 }, +{ "label": "13/19", "node": 3370, "naklon": 0 }, +{ "label": "13/20", "node": 3369, "naklon": 0 }, +{ "label": "13/21", "node": 3408, "naklon": 0 }, +{ "label": "13/22", "node": 3393, "naklon": 0 }, +{ "label": "13/23", "node": 3128, "naklon": 0 }, +{ "label": "13/24", "node": 3197, "naklon": 0 }, +{ "label": "13/25", "node": 4364, "naklon": 0 }, +{ "label": "13/26", "node": 3155, "naklon": 0 }, +{ "label": "13/27", "node": 3196, "naklon": 0 }, +{ "label": "13/28", "node": 3144, "naklon": 0 }, +{ "label": "13/30", "node": 3150, "naklon": 0 }, +{ "label": "13/31", "node": 3390, "naklon": 0 }, +{ "label": "13/32", "node": 3401, "naklon": 0 }, +{ "label": "13/33", "node": 3275, "naklon": 0 }, +{ "label": "13/35", "node": 3371, "naklon": 0 }, +{ "label": "13/36", "node": 3389, "naklon": 0 }, +{ "label": "13/37", "node": 3388, "naklon": 0 }, +{ "label": "13/38", "node": 3365, "naklon": 0 }, +{ "label": "13/39", "node": 3363, "naklon": 0 }, +{ "label": "13/40", "node": 3397, "naklon": 0 }, +{ "label": "13/40/1", "node": 3567, "naklon": 0 }, +{ "label": "13/41", "node": 3387, "naklon": 0 }, +{ "label": "13/42", "node": 3403, "naklon": 0 }, +{ "label": "13/43", "node": 3147, "naklon": 0 }, +{ "label": "13/44", "node": 3141, "naklon": 0 }, +{ "label": "13/46", "node": 3364, "naklon": 0 }, +{ "label": "13/47", "node": 3367, "naklon": 0 }, +{ "label": "13/48", "node": 3368, "naklon": 0 }, +{ "label": "13/49", "node": 3402, "naklon": 0 }, +{ "label": "13/50", "node": 3366, "naklon": 0 }, +{ "label": "13/51", "node": 3395, "naklon": 0 }, +{ "label": "13/52", "node": 3372, "naklon": 0 }, +{ "label": "13/53", "node": 3394, "naklon": 0 }, +{ "label": "13/54", "node": 3308, "naklon": 0 }, +{ "label": "13/54/1", "node": 3847, "naklon": 0 }, +{ "label": "13/55", "node": 3312, "naklon": 3 }, +{ "label": "13/56", "node": 3309, "naklon": 3 }, +{ "label": "13/57", "node": 3311, "naklon": 3 }, +{ "label": "13/58", "node": 3310, "naklon": 3 }, +{ "label": "13/59", "node": 4365, "naklon": 3 }, +{ "label": "13/60/1", "node": 4093, "naklon": 3 }, +{ "label": "13/61", "node": 3304, "naklon": 3 }, +{ "label": "13/62", "node": 3307, "naklon": 3 }, +{ "label": "13/63", "node": 3271, "naklon": 3 }, +{ "label": "13/64", "node": 3301, "naklon": 3 }, +{ "label": "13/65", "node": 4366, "naklon": 3 }, +{ "label": "13/66", "node": 3300, "naklon": 3 }, +{ "label": "13/67", "node": 3185, "naklon": 0 }, +{ "label": "13/68", "node": 3184, "naklon": 0 }, +{ "label": "13/69", "node": 3188, "naklon": 0 }, +{ "label": "13/71", "node": 3343, "naklon": 6 }, +{ "label": "13/71/1", "node": 3819, "naklon": 6 }, +{ "label": "13/71/2", "node": 3880, "naklon": 6 }, +{ "label": "13/72", "node": 3348, "naklon": 6 }, +{ "label": "13/74", "node": 3344, "naklon": 6 }, +{ "label": "13/75", "node": 3346, "naklon": 6 }, +{ "label": "13/75/1", "node": 3597, "naklon": 6 }, +{ "label": "13/76", "node": 3345, "naklon": 6 }, +{ "label": "13/77", "node": 3322, "naklon": 0 }, +{ "label": "13/78", "node": 3325, "naklon": 0 }, +{ "label": "13/78/1", "node": 4310, "naklon": 0 }, +{ "label": "13/79", "node": 3315, "naklon": 0 }, +{ "label": "13/80", "node": 3328, "naklon": 0 }, +{ "label": "13/81", "node": 3321, "naklon": 0 }, +{ "label": "13/82", "node": 3324, "naklon": 0 }, +{ "label": "13/84", "node": 3140, "naklon": 0 }, +{ "label": "13/85", "node": 3153, "naklon": 0 }, +{ "label": "13/86", "node": 3145, "naklon": 0 }, +{ "label": "13/87", "node": 3134, "naklon": 0 }, +{ "label": "13/88", "node": 3151, "naklon": 0 }, +{ "label": "13/89", "node": 3143, "naklon": 0 }, +{ "label": "13/90", "node": 3318, "naklon": 0 }, +{ "label": "13/91", "node": 3347, "naklon": 0 }, +{ "label": "13/94", "node": 3314, "naklon": 0 }, +{ "label": "13/96", "node": 3331, "naklon": 0 }, +{ "label": "13/97", "node": 3327, "naklon": 0 }, +{ "label": "13/99", "node": 3329, "naklon": 0 }, +{ "label": "13/100", "node": 3337, "naklon": 0 }, +{ "label": "13/101", "node": 3330, "naklon": 0 }, +{ "label": "13/102", "node": 3335, "naklon": 0 }, +{ "label": "13/103", "node": 3420, "naklon": 0 }, +{ "label": "13/104", "node": 3421, "naklon": 0 }, +{ "label": "13/105", "node": 4361, "naklon": 0 }, +{ "label": "13/106", "node": 4362, "naklon": 0 }, +{ "label": "13/107", "node": 3526, "naklon": 0 }, +{ "label": "13/108", "node": 4424, "naklon": null }, +{ "label": "13/109", "node": 3561, "naklon": null }, +{ "label": "13/110", "node": 3527, "naklon": null }, +{ "label": "13/111", "node": 3521, "naklon": null }, +{ "label": "13/112", "node": 3552, "naklon": null }, +{ "label": "13/113", "node": 3544, "naklon": null }, +{ "label": "13/114", "node": 3534, "naklon": null }, +{ "label": "13/115", "node": 3516, "naklon": null }, +{ "label": "13/116", "node": 3513, "naklon": null }, +{ "label": "13/117", "node": 3565, "naklon": null }, +{ "label": "13/118", "node": 3866, "naklon": null }, +{ "label": "14/1", "node": 3136, "naklon": 0 }, +{ "label": "14/2", "node": 3137, "naklon": 0 }, +{ "label": "14/3", "node": 3135, "naklon": 0 }, +{ "label": "14/4", "node": 3149, "naklon": 0 }, +{ "label": "14/5", "node": 3142, "naklon": 0 }, +{ "label": "14/6", "node": 3342, "naklon": 0 }, +{ "label": "14/7", "node": 3340, "naklon": 0 }, +{ "label": "14/8", "node": 3152, "naklon": 0 }, +{ "label": "14/9", "node": 3886, "naklon": 0 }, +{ "label": "14/10", "node": 3341, "naklon": null }, +{ "label": "14/11", "node": 3352, "naklon": null }, +{ "label": "15/1", "node": 3396, "naklon": 5 }, +{ "label": "15/2", "node": 2784, "naklon": 5 }, +{ "label": "15/3", "node": 2788, "naklon": 5 }, +{ "label": "15/4", "node": 2801, "naklon": 5 }, +{ "label": "15/5", "node": 2815, "naklon": 5 }, +{ "label": "15/6", "node": 2829, "naklon": 5 }, +{ "label": "15/7", "node": 2796, "naklon": 5 }, +{ "label": "15/8", "node": 2803, "naklon": 5 }, +{ "label": "15/8/1", "node": 4304, "naklon": 5 }, +{ "label": "15/8/2", "node": 4311, "naklon": 5 }, +{ "label": "15/9", "node": 2821, "naklon": 5 }, +{ "label": "15/10", "node": 3400, "naklon": 5 }, +{ "label": "15/11", "node": 2799, "naklon": 5 }, +{ "label": "15/12", "node": 2804, "naklon": 5 }, +{ "label": "15/12/1", "node": 4303, "naklon": 5 }, +{ "label": "15/12/2", "node": 4309, "naklon": 5 }, +{ "label": "15/13", "node": 2806, "naklon": 5 }, +{ "label": "15/14", "node": 2787, "naklon": 5 }, +{ "label": "15/15", "node": 2809, "naklon": 5 }, +{ "label": "15/16", "node": 2814, "naklon": 0 }, +{ "label": "15/17", "node": 3934, "naklon": 0 }, +{ "label": "15/18", "node": 3192, "naklon": 0 }, +{ "label": "15/19", "node": 2812, "naklon": 0 }, +{ "label": "15/20", "node": 4070, "naklon": 0 }, +{ "label": "15/21", "node": 2826, "naklon": 0 }, +{ "label": "15/22", "node": 2808, "naklon": 3 }, +{ "label": "15/23", "node": 2795, "naklon": 3 }, +{ "label": "15/24", "node": 2807, "naklon": 3 }, +{ "label": "15/25", "node": 2831, "naklon": 0 }, +{ "label": "15/26", "node": 2862, "naklon": null }, +{ "label": "15/27", "node": 2861, "naklon": 0 }, +{ "label": "15/28", "node": 2866, "naklon": 0 }, +{ "label": "15/28/1", "node": 3546, "naklon": 0 }, +{ "label": "15/29", "node": 4146, "naklon": 0 }, +{ "label": "15/29/1", "node": 3001, "naklon": 0 }, +{ "label": "15/30", "node": 2835, "naklon": 0 }, +{ "label": "15/31", "node": 2874, "naklon": 0 }, +{ "label": "15/32", "node": 2852, "naklon": 0 }, +{ "label": "15/33", "node": 2851, "naklon": 0 }, +{ "label": "15/33/1", "node": 3560, "naklon": 0 }, +{ "label": "15/34", "node": 2858, "naklon": 0 }, +{ "label": "15/34/1", "node": 4306, "naklon": 0 }, +{ "label": "15/35", "node": 2856, "naklon": 0 }, +{ "label": "15/36", "node": 2847, "naklon": 0 }, +{ "label": "15/36/1", "node": 3556, "naklon": 0 }, +{ "label": "15/37", "node": 3950, "naklon": 0 }, +{ "label": "15/38", "node": 2848, "naklon": 0 }, +{ "label": "15/39", "node": 2863, "naklon": 0 }, +{ "label": "15/39/1", "node": 4313, "naklon": 0 }, +{ "label": "15/40", "node": 2873, "naklon": 0 }, +{ "label": "15/40/1", "node": 2984, "naklon": 0 }, +{ "label": "15/41", "node": 2854, "naklon": 0 }, +{ "label": "15/42", "node": 2859, "naklon": 0 }, +{ "label": "15/43", "node": 2872, "naklon": 0 }, +{ "label": "15/44", "node": 2849, "naklon": 0 }, +{ "label": "15/45", "node": 2864, "naklon": 0 }, +{ "label": "15/46", "node": 3553, "naklon": null }, +{ "label": "15/47", "node": 3021, "naklon": null }, +{ "label": "15/47/1", "node": 3008, "naklon": null }, +{ "label": "15/48", "node": 3017, "naklon": null }, +{ "label": "15/49", "node": 3014, "naklon": null }, +{ "label": "15/50", "node": 2981, "naklon": null }, +{ "label": "15/51", "node": 3020, "naklon": null }, +{ "label": "15/52", "node": 3027, "naklon": null }, +{ "label": "15/53", "node": 3006, "naklon": null }, +{ "label": "15/54", "node": 3012, "naklon": null }, +{ "label": "15/55", "node": 2738, "naklon": 0 }, +{ "label": "15/56", "node": 2725, "naklon": 0 }, +{ "label": "15/57", "node": 3016, "naklon": null }, +{ "label": "15/58", "node": 3005, "naklon": null }, +{ "label": "15/58/1", "node": 3009, "naklon": null }, +{ "label": "15/59", "node": 3010, "naklon": 0 }, +{ "label": "15/59/1", "node": 3538, "naklon": 0 }, +{ "label": "15/59/2", "node": 4145, "naklon": 0 }, +{ "label": "15/60", "node": 2713, "naklon": 0 }, +{ "label": "15/61", "node": 2789, "naklon": 0 }, +{ "label": "15/62", "node": 2736, "naklon": 0 }, +{ "label": "15/63", "node": 2739, "naklon": 0 }, +{ "label": "15/64", "node": 4346, "naklon": 0 }, +{ "label": "15/65", "node": 2731, "naklon": 0 }, +{ "label": "15/66", "node": 2818, "naklon": 0 }, +{ "label": "15/66/1", "node": 3557, "naklon": 0 }, +{ "label": "15/67", "node": 2822, "naklon": 0 }, +{ "label": "15/68", "node": 2833, "naklon": 0 }, +{ "label": "15/69", "node": 2834, "naklon": 0 }, +{ "label": "15/70", "node": 3097, "naklon": 0 }, +{ "label": "15/71", "node": 2824, "naklon": 0 }, +{ "label": "15/72", "node": 2828, "naklon": 0 }, +{ "label": "15/73", "node": 2600, "naklon": 0 }, +{ "label": "15/73/1", "node": 4314, "naklon": 0 }, +{ "label": "15/74", "node": 2832, "naklon": 0 }, +{ "label": "15/75", "node": 4360, "naklon": 0 }, +{ "label": "15/76", "node": 2846, "naklon": 0 }, +{ "label": "15/77", "node": 2584, "naklon": 0 }, +{ "label": "15/78", "node": 2843, "naklon": 0 }, +{ "label": "15/78/1", "node": 4308, "naklon": 0 }, +{ "label": "15/79", "node": 4144, "naklon": null }, +{ "label": "15/80", "node": 2844, "naklon": 0 }, +{ "label": "15/81", "node": 2842, "naklon": 0 }, +{ "label": "15/82", "node": 2838, "naklon": 0 }, +{ "label": "15/83", "node": 2837, "naklon": null }, +{ "label": "15/83/1", "node": 3555, "naklon": null }, +{ "label": "15/84", "node": 2839, "naklon": 0 }, +{ "label": "15/85", "node": 2830, "naklon": 0 }, +{ "label": "15/86", "node": 4066, "naklon": 0 }, +{ "label": "15/87", "node": 2836, "naklon": 0 }, +{ "label": "15/88", "node": 2911, "naklon": 0 }, +{ "label": "15/89", "node": 2825, "naklon": 0 }, +{ "label": "15/90", "node": 2811, "naklon": 0 }, +{ "label": "15/94", "node": 3740, "naklon": 15 }, +{ "label": "15/95", "node": 2734, "naklon": 15 }, +{ "label": "15/96", "node": 3105, "naklon": 15 }, +{ "label": "15/97", "node": 2732, "naklon": 15 }, +{ "label": "15/98", "node": 2727, "naklon": 15 }, +{ "label": "15/99", "node": 2735, "naklon": 15 }, +{ "label": "15/100", "node": 3926, "naklon": 15 }, +{ "label": "15/101", "node": 2918, "naklon": 0 }, +{ "label": "15/102", "node": 2705, "naklon": 10 }, +{ "label": "15/103", "node": 2708, "naklon": 10 }, +{ "label": "15/104", "node": 2721, "naklon": 10 }, +{ "label": "15/105", "node": 2719, "naklon": 10 }, +{ "label": "15/106", "node": 2919, "naklon": 10 }, +{ "label": "15/107", "node": 3101, "naklon": 10 }, +{ "label": "15/108", "node": 2853, "naklon": 10 }, +{ "label": "15/109", "node": 2715, "naklon": 10 }, +{ "label": "15/110", "node": 2712, "naklon": 0 }, +{ "label": "15/111", "node": 2711, "naklon": 0 }, +{ "label": "15/112", "node": 2709, "naklon": 0 }, +{ "label": "15/113", "node": 2710, "naklon": 0 }, +{ "label": "15/114", "node": 2907, "naklon": 0 }, +{ "label": "15/115", "node": 2906, "naklon": 0 }, +{ "label": "15/116", "node": 2908, "naklon": 0 }, +{ "label": "15/117", "node": 2901, "naklon": 0 }, +{ "label": "15/118", "node": 2913, "naklon": 0 }, +{ "label": "15/119", "node": 3656, "naklon": 0 }, +{ "label": "15/120", "node": 2781, "naklon": 0 }, +{ "label": "15/121", "node": 2802, "naklon": 0 }, +{ "label": "15/122", "node": 2791, "naklon": 0 }, +{ "label": "15/123", "node": 2783, "naklon": 0 }, +{ "label": "15/124", "node": 2794, "naklon": 0 }, +{ "label": "15/125", "node": 3139, "naklon": 0 }, +{ "label": "15/126", "node": 3229, "naklon": 5 }, +{ "label": "15/127", "node": 3239, "naklon": 5 }, +{ "label": "15/128", "node": 3230, "naklon": 5 }, +{ "label": "15/129", "node": 4016, "naklon": null }, +{ "label": "16/16A", "node": 3608, "naklon": 0 }, +{ "label": "16/16B", "node": 4151, "naklon": 0 }, +{ "label": "16/1", "node": 3710, "naklon": 0 }, +{ "label": "16/2", "node": 3726, "naklon": 0 }, +{ "label": "16/3", "node": 3743, "naklon": 0 }, +{ "label": "16/4", "node": 3724, "naklon": 0 }, +{ "label": "16/5", "node": 3712, "naklon": 0 }, +{ "label": "16/6", "node": 3739, "naklon": 0 }, +{ "label": "16/7", "node": 3742, "naklon": 0 }, +{ "label": "16/8", "node": 3731, "naklon": 0 }, +{ "label": "16/9", "node": 3727, "naklon": 0 }, +{ "label": "16/10", "node": 3729, "naklon": 0 }, +{ "label": "16/11", "node": 3736, "naklon": 0 }, +{ "label": "16/12", "node": 3713, "naklon": 0 }, +{ "label": "16/13", "node": 3715, "naklon": 0 }, +{ "label": "16/14", "node": 3733, "naklon": 0 }, +{ "label": "16/15", "node": 3732, "naklon": 0 }, +{ "label": "16/17", "node": 3634, "naklon": 0 }, +{ "label": "16/18", "node": 3610, "naklon": 0 }, +{ "label": "16/19", "node": 3626, "naklon": 0 }, +{ "label": "16/20", "node": 3618, "naklon": 0 }, +{ "label": "16/21", "node": 3619, "naklon": 0 }, +{ "label": "16/22", "node": 3628, "naklon": 0 }, +{ "label": "16/23", "node": 3615, "naklon": 0 }, +{ "label": "16/24", "node": 3609, "naklon": 0 }, +{ "label": "16/25", "node": 3606, "naklon": 0 }, +{ "label": "16/26", "node": 3624, "naklon": 0 }, +{ "label": "16/27", "node": 3627, "naklon": 0 }, +{ "label": "16/28", "node": 3607, "naklon": 0 }, +{ "label": "16/29", "node": 4370, "naklon": 0 }, +{ "label": "16/30", "node": 3692, "naklon": 0 }, +{ "label": "16/31", "node": 3614, "naklon": 0 }, +{ "label": "16/32", "node": 3623, "naklon": 0 }, +{ "label": "16/33", "node": 4373, "naklon": 0 }, +{ "label": "16/34", "node": 3620, "naklon": 0 }, +{ "label": "16/35", "node": 3685, "naklon": 0 }, +{ "label": "16/36", "node": 3616, "naklon": 0 }, +{ "label": "16/37", "node": 3686, "naklon": 0 }, +{ "label": "16/38", "node": 3688, "naklon": 0 }, +{ "label": "16/39", "node": 3684, "naklon": 0 }, +{ "label": "16/40", "node": 3825, "naklon": 0 }, +{ "label": "16/41", "node": 3865, "naklon": 0 }, +{ "label": "16/42", "node": 3824, "naklon": 0 }, +{ "label": "16/43", "node": 3871, "naklon": 0 }, +{ "label": "16/44", "node": 3801, "naklon": 0 }, +{ "label": "16/45", "node": 3862, "naklon": 0 }, +{ "label": "16/46", "node": 3876, "naklon": 0 }, +{ "label": "16/47", "node": 3861, "naklon": 0 }, +{ "label": "16/48", "node": 4215, "naklon": 0 }, +{ "label": "16/49", "node": 3605, "naklon": 10 }, +{ "label": "16/50", "node": 3603, "naklon": 10 }, +{ "label": "16/51", "node": 3592, "naklon": 10 }, +{ "label": "16/52", "node": 3598, "naklon": 10 }, +{ "label": "16/53", "node": 3594, "naklon": 10 }, +{ "label": "16/54", "node": 3593, "naklon": 10 }, +{ "label": "16/55", "node": 3630, "naklon": 10 }, +{ "label": "16/56", "node": 3763, "naklon": 10 }, +{ "label": "16/57", "node": 3746, "naklon": 10 }, +{ "label": "16/58", "node": 3699, "naklon": 0 }, +{ "label": "16/59", "node": 3698, "naklon": 0 }, +{ "label": "16/60", "node": 3709, "naklon": null }, +{ "label": "16/61", "node": 3708, "naklon": 0 }, +{ "label": "16/62", "node": 3703, "naklon": null }, +{ "label": "16/63", "node": 3700, "naklon": 0 }, +{ "label": "16/64", "node": 3701, "naklon": null }, +{ "label": "16/65", "node": 3704, "naklon": 0 }, +{ "label": "16/66", "node": 3707, "naklon": null }, +{ "label": "16/67", "node": 3810, "naklon": 0 }, +{ "label": "16/68", "node": 4208, "naklon": null }, +{ "label": "16/69", "node": 3867, "naklon": 0 }, +{ "label": "16/70", "node": 4372, "naklon": null }, +{ "label": "16/71", "node": 3881, "naklon": 0 }, +{ "label": "16/72", "node": 4204, "naklon": null }, +{ "label": "16/73", "node": 3869, "naklon": 0 }, +{ "label": "16/74", "node": 4202, "naklon": null }, +{ "label": "16/75", "node": 3830, "naklon": 0 }, +{ "label": "16/76", "node": 3870, "naklon": null }, +{ "label": "16/77", "node": 3964, "naklon": 0 }, +{ "label": "16/78", "node": 3849, "naklon": 0 }, +{ "label": "16/79", "node": 3694, "naklon": null }, +{ "label": "16/80", "node": 3717, "naklon": 0 }, +{ "label": "16/81", "node": 3877, "naklon": null }, +{ "label": "16/82", "node": 3755, "naklon": 0 }, +{ "label": "16/83", "node": 3725, "naklon": null }, +{ "label": "16/84", "node": 3716, "naklon": 0 }, +{ "label": "16/85", "node": 3696, "naklon": null }, +{ "label": "16/86", "node": 3702, "naklon": 0 }, +{ "label": "16/87", "node": 3706, "naklon": null }, +{ "label": "16/88", "node": 3850, "naklon": 0 }, +{ "label": "16/89", "node": 3848, "naklon": null }, +{ "label": "16/90", "node": 3737, "naklon": null }, +{ "label": "16/91", "node": 3705, "naklon": 0 }, +{ "label": "16/92", "node": 3723, "naklon": null }, +{ "label": "16/93", "node": 3842, "naklon": 0 }, +{ "label": "16/94", "node": 3735, "naklon": null }, +{ "label": "16/95", "node": 3719, "naklon": 0 }, +{ "label": "16/96", "node": 3697, "naklon": 0 }, +{ "label": "16/97", "node": 3711, "naklon": 0 }, +{ "label": "16/98", "node": 4107, "naklon": null }, +{ "label": "16/99", "node": 4112, "naklon": 5 }, +{ "label": "16/100", "node": 4106, "naklon": 5 }, +{ "label": "16/101", "node": 4111, "naklon": 5 }, +{ "label": "16/102", "node": 4091, "naklon": null }, +{ "label": "16/103", "node": 4104, "naklon": 5 }, +{ "label": "16/104", "node": 4094, "naklon": null }, +{ "label": "16/105", "node": 4089, "naklon": 5 }, +{ "label": "16/106", "node": 4095, "naklon": null }, +{ "label": "16/107", "node": 4102, "naklon": 5 }, +{ "label": "16/108", "node": 4105, "naklon": null }, +{ "label": "16/109", "node": 3859, "naklon": null }, +{ "label": "16/110", "node": 4090, "naklon": 5 }, +{ "label": "16/111", "node": 4110, "naklon": null }, +{ "label": "16/112", "node": 4097, "naklon": 5 }, +{ "label": "16/113", "node": 4099, "naklon": null }, +{ "label": "16/114", "node": 4096, "naklon": null }, +{ "label": "16/115", "node": 4101, "naklon": 5 }, +{ "label": "16/116", "node": 4109, "naklon": null }, +{ "label": "16/117", "node": 4092, "naklon": 5 }, +{ "label": "16/118", "node": 3631, "naklon": null }, +{ "label": "16/119", "node": 3632, "naklon": 0 }, +{ "label": "16/120", "node": 3641, "naklon": null }, +{ "label": "16/121", "node": 3638, "naklon": 0 }, +{ "label": "16/122", "node": 3637, "naklon": null }, +{ "label": "16/123", "node": 4142, "naklon": null }, +{ "label": "16/124", "node": 4147, "naklon": 5 }, +{ "label": "16/125", "node": 4139, "naklon": 5 }, +{ "label": "20/30A", "node": 3172, "naklon": 2 }, +{ "label": "20/30B", "node": 3164, "naklon": 2 }, +{ "label": "20/1", "node": 3247, "naklon": 10 }, +{ "label": "20/2", "node": 3296, "naklon": 10 }, +{ "label": "20/3", "node": 3246, "naklon": 10 }, +{ "label": "20/4", "node": 3270, "naklon": 10 }, +{ "label": "20/5", "node": 3294, "naklon": 10 }, +{ "label": "20/6", "node": 3298, "naklon": 10 }, +{ "label": "20/7", "node": 3297, "naklon": 10 }, +{ "label": "20/8", "node": 3293, "naklon": 10 }, +{ "label": "20/9", "node": 3299, "naklon": 10 }, +{ "label": "20/10", "node": 3295, "naklon": 10 }, +{ "label": "20/11", "node": 3244, "naklon": 10 }, +{ "label": "20/12", "node": 3249, "naklon": 10 }, +{ "label": "20/13", "node": 3268, "naklon": 10 }, +{ "label": "20/14", "node": 3245, "naklon": 10 }, +{ "label": "20/15", "node": 3278, "naklon": 10 }, +{ "label": "20/16", "node": 3280, "naklon": 10 }, +{ "label": "20/17", "node": 3292, "naklon": 10 }, +{ "label": "20/18", "node": 3287, "naklon": 10 }, +{ "label": "20/19", "node": 3282, "naklon": 10 }, +{ "label": "20/20", "node": 3273, "naklon": 0 }, +{ "label": "20/21", "node": 3157, "naklon": 0 }, +{ "label": "20/22", "node": 3283, "naklon": 0 }, +{ "label": "20/23", "node": 3159, "naklon": 0 }, +{ "label": "20/24", "node": 3289, "naklon": 0 }, +{ "label": "20/25", "node": 3163, "naklon": 0 }, +{ "label": "20/26", "node": 3126, "naklon": 0 }, +{ "label": "20/27", "node": 3171, "naklon": 0 }, +{ "label": "20/28", "node": 3162, "naklon": 0 }, +{ "label": "20/29", "node": 3279, "naklon": 10 }, +{ "label": "20/31", "node": 3173, "naklon": 0 }, +{ "label": "20/32", "node": 3127, "naklon": 0 }, +{ "label": "20/33", "node": 3131, "naklon": 0 }, +{ "label": "20/34", "node": 3129, "naklon": 0 }, +{ "label": "20/35", "node": 3276, "naklon": 2 }, +{ "label": "20/36", "node": 3290, "naklon": 2 }, +{ "label": "20/37", "node": 3132, "naklon": 0 }, +{ "label": "20/38", "node": 3138, "naklon": 0 }, +{ "label": "20/39", "node": 3272, "naklon": 0 }, +{ "label": "20/40", "node": 3291, "naklon": 0 }, +{ "label": "20/41", "node": 3277, "naklon": 10 }, +{ "label": "20/42", "node": 3286, "naklon": 10 }, +{ "label": "20/43", "node": 3281, "naklon": 10 }, +{ "label": "20/44", "node": 3288, "naklon": 10 }, +{ "label": "20/45", "node": 3284, "naklon": 10 }, +{ "label": "20/46", "node": 3167, "naklon": 10 }, +{ "label": "20/47", "node": 3872, "naklon": 0 }, +{ "label": "20/48", "node": 3124, "naklon": 0 }, +{ "label": "20/49", "node": 3133, "naklon": 0 }, +{ "label": "20/50", "node": 3158, "naklon": 0 }, +{ "label": "20/51", "node": 3169, "naklon": 0 }, +{ "label": "20/52", "node": 3146, "naklon": 0 }, +{ "label": "20/53", "node": 3160, "naklon": 0 }, +{ "label": "20/54", "node": 3248, "naklon": 0 }, +{ "label": "20/55", "node": 3156, "naklon": 0 }, +{ "label": "20/56", "node": 3161, "naklon": 0 }, +{ "label": "20/57", "node": 3170, "naklon": 0 }, +{ "label": "20/58", "node": 3168, "naklon": 0 }, +{ "label": "20/59", "node": 3125, "naklon": 0 }, +{ "label": "20/60", "node": 3166, "naklon": 0 }, +{ "label": "20/61", "node": 3130, "naklon": 0 }, +{ "label": "20/62", "node": 3563, "naklon": 0 }, +{ "label": "20/63", "node": 3550, "naklon": null }, +{ "label": "20/67", "node": 3269, "naklon": 0 }, +{ "label": "21/1", "node": 2921, "naklon": 0 }, +{ "label": "21/2", "node": 2707, "naklon": 0 }, +{ "label": "21/3", "node": 2723, "naklon": 0 }, +{ "label": "21/4", "node": 2716, "naklon": 0 }, +{ "label": "21/5", "node": 2717, "naklon": 0 }, +{ "label": "21/6", "node": 2720, "naklon": 0 }, +{ "label": "21/7", "node": 2722, "naklon": 0 }, +{ "label": "21/8", "node": 2718, "naklon": 0 }, +{ "label": "21/9", "node": 2724, "naklon": 0 }, +{ "label": "21/10", "node": 2742, "naklon": 0 }, +{ "label": "21/11", "node": 2743, "naklon": 0 }, +{ "label": "21/12", "node": 2733, "naklon": 0 }, +{ "label": "21/14", "node": 2903, "naklon": 0 }, +{ "label": "21/15", "node": 2917, "naklon": 0 }, +{ "label": "21/16", "node": 2897, "naklon": 0 }, +{ "label": "21/17", "node": 2914, "naklon": 0 }, +{ "label": "21/18", "node": 2898, "naklon": 0 }, +{ "label": "21/19", "node": 2773, "naklon": 0 }, +{ "label": "21/20", "node": 2895, "naklon": 0 }, +{ "label": "21/21", "node": 2896, "naklon": 0 }, +{ "label": "21/22", "node": 2771, "naklon": 0 }, +{ "label": "21/23", "node": 2772, "naklon": 0 }, +{ "label": "21/24", "node": 2793, "naklon": 0 }, +{ "label": "21/25", "node": 2902, "naklon": 0 }, +{ "label": "21/26", "node": 2910, "naklon": 0 }, +{ "label": "21/27", "node": 2909, "naklon": 0 }, +{ "label": "21/28", "node": 2920, "naklon": 0 }, +{ "label": "21/29", "node": 2916, "naklon": 0 }, +{ "label": "21/30", "node": 2904, "naklon": 0 }, +{ "label": "21/31", "node": 2915, "naklon": 0 }, +{ "label": "21/32", "node": 2905, "naklon": 0 }, +{ "label": "21/33", "node": 2900, "naklon": 0 }, +{ "label": "21/34", "node": 2899, "naklon": 0 }, +{ "label": "21/36", "node": 2741, "naklon": 0 }, +{ "label": "21/37", "node": 2714, "naklon": 0 }, +{ "label": "21/38", "node": 2701, "naklon": 0 }, +{ "label": "21/39", "node": 2703, "naklon": 0 }, +{ "label": "21/40", "node": 2704, "naklon": 0 }, +{ "label": "21/41", "node": 2702, "naklon": 0 }, +{ "label": "21/42", "node": 2706, "naklon": 0 }, +{ "label": "21/43", "node": 2776, "naklon": 0 }, +{ "label": "21/44", "node": 2770, "naklon": 0 }, +{ "label": "21/45", "node": 2786, "naklon": 0 }, +{ "label": "21/46", "node": 2779, "naklon": 0 }, +{ "label": "21/47", "node": 2782, "naklon": 0 }, +{ "label": "21/48", "node": 2785, "naklon": 0 }, +{ "label": "21/49", "node": 2769, "naklon": 0 }, +{ "label": "21/50", "node": 3354, "naklon": 0 }, +{ "label": "21/51", "node": 2778, "naklon": 0 }, +{ "label": "21/52", "node": 2775, "naklon": 0 }, +{ "label": "21/53", "node": 2780, "naklon": 0 }, +{ "label": "21/54", "node": 2790, "naklon": 0 }, +{ "label": "21/55", "node": 2792, "naklon": 0 }, +{ "label": "21/56", "node": 2774, "naklon": 0 }, +{ "label": "22/1", "node": 2630, "naklon": 0 }, +{ "label": "22/2", "node": 2631, "naklon": 0 }, +{ "label": "22/3", "node": 2632, "naklon": 0 }, +{ "label": "22/4", "node": 2633, "naklon": 0 }, +{ "label": "22/5", "node": 2634, "naklon": 0 }, +{ "label": "22/6", "node": 2636, "naklon": 0 }, +{ "label": "22/7", "node": 4367, "naklon": 0 }, +{ "label": "22/8", "node": 2637, "naklon": 0 }, +{ "label": "22/9", "node": 2638, "naklon": 0 }, +{ "label": "22/10", "node": 2639, "naklon": 0 }, +{ "label": "22/11", "node": 2640, "naklon": 0 }, +{ "label": "22/12", "node": 2641, "naklon": 0 }, +{ "label": "22/13", "node": 2642, "naklon": 0 }, +{ "label": "22/14", "node": 2643, "naklon": 0 }, +{ "label": "22/15", "node": 2644, "naklon": 0 }, +{ "label": "22/16", "node": 2645, "naklon": 0 }, +{ "label": "22/17", "node": 2646, "naklon": 0 }, +{ "label": "22/18", "node": 2647, "naklon": 0 }, +{ "label": "22/19", "node": 2648, "naklon": 0 }, +{ "label": "22/20", "node": 2649, "naklon": 0 }, +{ "label": "22/21", "node": 2650, "naklon": 0 }, +{ "label": "22/22", "node": 2651, "naklon": 0 }, +{ "label": "22/23", "node": 4103, "naklon": 0 }, +{ "label": "22/24", "node": 2653, "naklon": 0 }, +{ "label": "22/25", "node": 2654, "naklon": 0 }, +{ "label": "22/26", "node": 2655, "naklon": 0 }, +{ "label": "22/27", "node": 2656, "naklon": 0 }, +{ "label": "22/28", "node": 2657, "naklon": 0 }, +{ "label": "22/29", "node": 2658, "naklon": 0 }, +{ "label": "22/30", "node": 2659, "naklon": 0 }, +{ "label": "22/31", "node": 2660, "naklon": 0 }, +{ "label": "22/32", "node": 2661, "naklon": 0 }, +{ "label": "22/32/1", "node": 3015, "naklon": 0 }, +{ "label": "22/33", "node": 2662, "naklon": 0 }, +{ "label": "22/34", "node": 2663, "naklon": 0 }, +{ "label": "22/35", "node": 2664, "naklon": 0 }, +{ "label": "22/36", "node": 2665, "naklon": 0 }, +{ "label": "22/37", "node": 2666, "naklon": 0 }, +{ "label": "22/38", "node": 2667, "naklon": 0 }, +{ "label": "22/39", "node": 2668, "naklon": 0 }, +{ "label": "22/40", "node": 2669, "naklon": null }, +{ "label": "22/41", "node": 2670, "naklon": null }, +{ "label": "22/42", "node": 2671, "naklon": null }, +{ "label": "23/9A", "node": 3087, "naklon": 10 }, +{ "label": "23/9B", "node": 3090, "naklon": 10 }, +{ "label": "23/1", "node": 3075, "naklon": 0 }, +{ "label": "23/2", "node": 3089, "naklon": 0 }, +{ "label": "23/3", "node": 3088, "naklon": 0 }, +{ "label": "23/4", "node": 3228, "naklon": 10 }, +{ "label": "23/5", "node": 2751, "naklon": 10 }, +{ "label": "23/6", "node": 3243, "naklon": 10 }, +{ "label": "23/7", "node": 4349, "naklon": 10 }, +{ "label": "23/8", "node": 3102, "naklon": 10 }, +{ "label": "23/10", "node": 3099, "naklon": 10 }, +{ "label": "23/11", "node": 3103, "naklon": 10 }, +{ "label": "23/12", "node": 3093, "naklon": 10 }, +{ "label": "23/13", "node": 3098, "naklon": 10 }, +{ "label": "23/14", "node": 3092, "naklon": 10 }, +{ "label": "23/15", "node": 3233, "naklon": 0 }, +{ "label": "23/16", "node": 3095, "naklon": 0 }, +{ "label": "23/17", "node": 4074, "naklon": 0 }, +{ "label": "23/18", "node": 2729, "naklon": 0 }, +{ "label": "23/19", "node": 3234, "naklon": 0 }, +{ "label": "23/20", "node": 3094, "naklon": 0 }, +{ "label": "23/21", "node": 2817, "naklon": 0 }, +{ "label": "23/22", "node": 3226, "naklon": 0 }, +{ "label": "23/23", "node": 3225, "naklon": 0 }, +{ "label": "23/24", "node": 3237, "naklon": 0 }, +{ "label": "23/25", "node": 4250, "naklon": 0 }, +{ "label": "23/26", "node": 3059, "naklon": 10 }, +{ "label": "23/27", "node": 3238, "naklon": 10 }, +{ "label": "23/28", "node": 3242, "naklon": 10 }, +{ "label": "23/29", "node": 3236, "naklon": 10 }, +{ "label": "23/30", "node": 3112, "naklon": 10 }, +{ "label": "23/31", "node": 3224, "naklon": 0 }, +{ "label": "23/32", "node": 4298, "naklon": 10 }, +{ "label": "23/33", "node": 4150, "naklon": 10 }, +{ "label": "23/34", "node": 3091, "naklon": 10 }, +{ "label": "25/1", "node": 3771, "naklon": 5 }, +{ "label": "25/2", "node": 3777, "naklon": 5 }, +{ "label": "25/3", "node": 3749, "naklon": 5 }, +{ "label": "25/4", "node": 3769, "naklon": 5 }, +{ "label": "25/5", "node": 3765, "naklon": 5 }, +{ "label": "25/6", "node": 3785, "naklon": 5 }, +{ "label": "25/7", "node": 3761, "naklon": 5 }, +{ "label": "25/8", "node": 3758, "naklon": 5 }, +{ "label": "25/9", "node": 3766, "naklon": 5 }, +{ "label": "25/10", "node": 3779, "naklon": 5 }, +{ "label": "25/11", "node": 3899, "naklon": 10 }, +{ "label": "25/12", "node": 3922, "naklon": 10 }, +{ "label": "25/13", "node": 3912, "naklon": 10 }, +{ "label": "25/14", "node": 3933, "naklon": 10 }, +{ "label": "25/15", "node": 3921, "naklon": 10 }, +{ "label": "25/16", "node": 4300, "naklon": 10 }, +{ "label": "25/17", "node": 3927, "naklon": 10 }, +{ "label": "25/18", "node": 3212, "naklon": 10 }, +{ "label": "25/19", "node": 3208, "naklon": 10 }, +{ "label": "25/20", "node": 3207, "naklon": 10 }, +{ "label": "25/21", "node": 4294, "naklon": 10 }, +{ "label": "25/22", "node": 3209, "naklon": 10 }, +{ "label": "25/23", "node": 3745, "naklon": 10 }, +{ "label": "25/24", "node": 3762, "naklon": 10 }, +{ "label": "25/25", "node": 3215, "naklon": 10 }, +{ "label": "25/26", "node": 3210, "naklon": 10 }, +{ "label": "25/27", "node": 3211, "naklon": 10 }, +{ "label": "25/28", "node": 3206, "naklon": 10 }, +{ "label": "25/29", "node": 3918, "naklon": 5 }, +{ "label": "25/30", "node": 3928, "naklon": 5 }, +{ "label": "25/31", "node": 3917, "naklon": 5 }, +{ "label": "25/32", "node": 4029, "naklon": 0 }, +{ "label": "25/33", "node": 4038, "naklon": 0 }, +{ "label": "25/34", "node": 4022, "naklon": 0 }, +{ "label": "25/35", "node": 3937, "naklon": 0 }, +{ "label": "25/36", "node": 3190, "naklon": 0 }, +{ "label": "25/37", "node": 3835, "naklon": 0 }, +{ "label": "25/38", "node": 3201, "naklon": 0 }, +{ "label": "25/39", "node": 3193, "naklon": 0 }, +{ "label": "25/40", "node": 3191, "naklon": 0 }, +{ "label": "25/41", "node": 3203, "naklon": 0 }, +{ "label": "25/42", "node": 4301, "naklon": 0 }, +{ "label": "25/43", "node": 3223, "naklon": 0 }, +{ "label": "25/44", "node": 3202, "naklon": 0 }, +{ "label": "25/45", "node": 3205, "naklon": 0 }, +{ "label": "25/46", "node": 3194, "naklon": 0 }, +{ "label": "25/47", "node": 3198, "naklon": 0 }, +{ "label": "25/48", "node": 3204, "naklon": 0 }, +{ "label": "25/49", "node": 3200, "naklon": 0 }, +{ "label": "25/50", "node": 3216, "naklon": 0 }, +{ "label": "25/51", "node": 3932, "naklon": 5 }, +{ "label": "25/52", "node": 3923, "naklon": 5 }, +{ "label": "25/53", "node": 3913, "naklon": 5 }, +{ "label": "25/54", "node": 3900, "naklon": 5 }, +{ "label": "25/55", "node": 4189, "naklon": 10 }, +{ "label": "25/56", "node": 4191, "naklon": 10 }, +{ "label": "25/57", "node": 3790, "naklon": 10 }, +{ "label": "25/58", "node": 4190, "naklon": 10 }, +{ "label": "25/59", "node": 4302, "naklon": 0 }, +{ "label": "25/60", "node": 4351, "naklon": 0 }, +{ "label": "25/61", "node": 4075, "naklon": 0 }, +{ "label": "25/62", "node": 4071, "naklon": 0 }, +{ "label": "25/63", "node": 3784, "naklon": 0 }, +{ "label": "25/64", "node": 4065, "naklon": 0 }, +{ "label": "25/65", "node": 4297, "naklon": 0 }, +{ "label": "25/66", "node": 4295, "naklon": 0 }, +{ "label": "25/67", "node": 4299, "naklon": 0 }, +{ "label": "25/68", "node": 3772, "naklon": 0 }, +{ "label": "25/69", "node": 3941, "naklon": 0 }, +{ "label": "25/70", "node": 3782, "naklon": 0 }, +{ "label": "25/71", "node": 4068, "naklon": 0 }, +{ "label": "25/72", "node": 4073, "naklon": 0 }, +{ "label": "25/73", "node": 3901, "naklon": 5 }, +{ "label": "25/74", "node": 4296, "naklon": 5 }, +{ "label": "25/75", "node": 3910, "naklon": 5 }, +{ "label": "25/76", "node": 4293, "naklon": 5 }, +{ "label": "25/77", "node": 3919, "naklon": 5 }, +{ "label": "25/78", "node": 3924, "naklon": 5 }, +{ "label": "25/79", "node": 3909, "naklon": 5 }, +{ "label": "25/80", "node": 3896, "naklon": 5 }, +{ "label": "25/81", "node": 3911, "naklon": 5 }, +{ "label": "25/82", "node": 2819, "naklon": 15 }, +{ "label": "25/83", "node": 3776, "naklon": 15 }, +{ "label": "25/84", "node": 3752, "naklon": 15 }, +{ "label": "25/85", "node": 4353, "naklon": 15 }, +{ "label": "25/86", "node": 3791, "naklon": 0 }, +{ "label": "25/87", "node": 3770, "naklon": 0 }, +{ "label": "25/88", "node": 3760, "naklon": 0 }, +{ "label": "25/89", "node": 3115, "naklon": 0 }, +{ "label": "25/90", "node": 3738, "naklon": 0 }, +{ "label": "25/91", "node": 3748, "naklon": 0 }, +{ "label": "25/92", "node": 3753, "naklon": 0 }, +{ "label": "25/93", "node": 3775, "naklon": 0 }, +{ "label": "25/94", "node": 3778, "naklon": 5 }, +{ "label": "25/95", "node": 4078, "naklon": 5 }, +{ "label": "25/96", "node": 4088, "naklon": 5 }, +{ "label": "25/97", "node": 3856, "naklon": 5 }, +{ "label": "25/98", "node": 4084, "naklon": 5 }, +{ "label": "25/99", "node": 4069, "naklon": 5 }, +{ "label": "25/100", "node": 4188, "naklon": 5 }, +{ "label": "25/101", "node": 4064, "naklon": 5 }, +{ "label": "25/102", "node": 3792, "naklon": 5 }, +{ "label": "25/103", "node": 3780, "naklon": 5 }, +{ "label": "25/104", "node": 4034, "naklon": 5 }, +{ "label": "25/105", "node": 4072, "naklon": 5 }, +{ "label": "25/106", "node": 3884, "naklon": 5 }, +{ "label": "25/107", "node": 3793, "naklon": 5 }, +{ "label": "25/108", "node": 3863, "naklon": 5 }, +{ "label": "25/109", "node": 3855, "naklon": 5 }, +{ "label": "33/1", "node": 3846, "naklon": 0 }, +{ "label": "33/2", "node": 3943, "naklon": 0 }, +{ "label": "33/3", "node": 3903, "naklon": 0 }, +{ "label": "33/4", "node": 3982, "naklon": 0 }, +{ "label": "33/5", "node": 3879, "naklon": 0 }, +{ "label": "33/6", "node": 3887, "naklon": 0 }, +{ "label": "33/7", "node": 3920, "naklon": 5 }, +{ "label": "33/8", "node": 3942, "naklon": 5 }, +{ "label": "33/9", "node": 3829, "naklon": null }, +{ "label": "34/79A", "node": 3452, "naklon": 6 }, +{ "label": "34/79B", "node": 3460, "naklon": 6 }, +{ "label": "34/90A", "node": 3443, "naklon": 6 }, +{ "label": "34/90B", "node": 3445, "naklon": 6 }, +{ "label": "34/90C", "node": 3457, "naklon": 6 }, +{ "label": "34/97A", "node": 3461, "naklon": 6 }, +{ "label": "34/97B", "node": 3463, "naklon": 6 }, +{ "label": "34/98A", "node": 3426, "naklon": 6 }, +{ "label": "34/98B", "node": 3444, "naklon": 6 }, +{ "label": "34/99A", "node": 3453, "naklon": 6 }, +{ "label": "34/99B", "node": 3455, "naklon": 6 }, +{ "label": "34/1", "node": 4009, "naklon": 0 }, +{ "label": "34/2", "node": 3602, "naklon": 0 }, +{ "label": "34/3", "node": 3441, "naklon": 0 }, +{ "label": "34/4", "node": 3464, "naklon": 0 }, +{ "label": "34/5", "node": 3883, "naklon": 0 }, +{ "label": "34/6", "node": 4098, "naklon": 0 }, +{ "label": "34/7", "node": 4003, "naklon": 0 }, +{ "label": "34/8", "node": 4004, "naklon": 0 }, +{ "label": "34/9", "node": 3888, "naklon": 0 }, +{ "label": "34/10", "node": 3997, "naklon": 0 }, +{ "label": "34/11", "node": 4006, "naklon": 0 }, +{ "label": "34/12", "node": 4000, "naklon": 0 }, +{ "label": "34/13", "node": 4011, "naklon": 0 }, +{ "label": "34/14", "node": 3999, "naklon": 0 }, +{ "label": "34/15", "node": 3981, "naklon": 0 }, +{ "label": "34/16", "node": 3988, "naklon": 0 }, +{ "label": "34/17", "node": 3986, "naklon": 0 }, +{ "label": "34/18", "node": 3998, "naklon": 0 }, +{ "label": "34/19", "node": 3983, "naklon": 0 }, +{ "label": "34/20", "node": 4005, "naklon": 0 }, +{ "label": "34/21", "node": 4001, "naklon": 0 }, +{ "label": "34/22", "node": 4008, "naklon": 0 }, +{ "label": "34/23", "node": 4002, "naklon": 0 }, +{ "label": "34/24", "node": 3996, "naklon": 0 }, +{ "label": "34/25", "node": 4007, "naklon": 0 }, +{ "label": "34/26", "node": 4113, "naklon": 15 }, +{ "label": "34/27", "node": 3595, "naklon": 5 }, +{ "label": "34/28", "node": 3599, "naklon": 5 }, +{ "label": "34/29", "node": 3601, "naklon": 5 }, +{ "label": "34/30", "node": 4205, "naklon": 0 }, +{ "label": "34/31", "node": 3987, "naklon": null }, +{ "label": "34/32", "node": 4214, "naklon": 0 }, +{ "label": "34/33", "node": 4226, "naklon": 0 }, +{ "label": "34/34", "node": 4209, "naklon": 0 }, +{ "label": "34/35", "node": 4201, "naklon": 0 }, +{ "label": "34/36", "node": 3440, "naklon": 0 }, +{ "label": "34/37", "node": 3465, "naklon": 0 }, +{ "label": "34/38", "node": 3446, "naklon": 0 }, +{ "label": "34/39", "node": 4039, "naklon": 5 }, +{ "label": "34/40", "node": 4057, "naklon": 5 }, +{ "label": "34/41", "node": 3985, "naklon": 0 }, +{ "label": "34/42", "node": 3882, "naklon": 0 }, +{ "label": "34/43", "node": 4040, "naklon": 5 }, +{ "label": "34/44", "node": 3231, "naklon": 0 }, +{ "label": "34/45", "node": 3227, "naklon": 0 }, +{ "label": "34/46", "node": 3431, "naklon": 0 }, +{ "label": "34/47", "node": 4013, "naklon": 0 }, +{ "label": "34/48", "node": 4045, "naklon": 0 }, +{ "label": "34/49", "node": 3949, "naklon": 0 }, +{ "label": "34/50", "node": 3953, "naklon": 0 }, +{ "label": "34/51", "node": 3952, "naklon": 0 }, +{ "label": "34/52", "node": 3995, "naklon": 0 }, +{ "label": "34/53", "node": 3992, "naklon": 0 }, +{ "label": "34/54", "node": 4198, "naklon": 0 }, +{ "label": "34/55", "node": 3935, "naklon": 0 }, +{ "label": "34/56", "node": 4050, "naklon": 0 }, +{ "label": "34/57", "node": 4049, "naklon": 0 }, +{ "label": "34/58", "node": 4054, "naklon": 0 }, +{ "label": "34/59", "node": 3663, "naklon": 6 }, +{ "label": "34/60", "node": 3661, "naklon": 6 }, +{ "label": "34/61", "node": 3664, "naklon": 6 }, +{ "label": "34/62", "node": 3660, "naklon": 6 }, +{ "label": "34/63", "node": 3662, "naklon": 6 }, +{ "label": "34/65", "node": 3665, "naklon": 6 }, +{ "label": "34/66", "node": 3667, "naklon": 6 }, +{ "label": "34/67", "node": 3675, "naklon": 6 }, +{ "label": "34/68", "node": 3666, "naklon": 6 }, +{ "label": "34/69", "node": 3652, "naklon": 6 }, +{ "label": "34/70", "node": 3458, "naklon": 6 }, +{ "label": "34/70/1", "node": 4425, "naklon": 6 }, +{ "label": "34/71", "node": 3459, "naklon": 6 }, +{ "label": "34/72", "node": 3435, "naklon": 6 }, +{ "label": "34/73", "node": 3448, "naklon": 6 }, +{ "label": "34/74", "node": 3451, "naklon": 6 }, +{ "label": "34/75", "node": 3442, "naklon": 6 }, +{ "label": "34/76", "node": 3449, "naklon": 6 }, +{ "label": "34/77", "node": 3450, "naklon": 6 }, +{ "label": "34/78", "node": 3433, "naklon": 6 }, +{ "label": "34/80", "node": 3432, "naklon": 12 }, +{ "label": "34/81", "node": 3470, "naklon": 12 }, +{ "label": "34/82", "node": 3438, "naklon": 12 }, +{ "label": "34/83", "node": 3439, "naklon": 12 }, +{ "label": "34/84", "node": 4028, "naklon": 5 }, +{ "label": "34/85", "node": 3596, "naklon": 5 }, +{ "label": "34/86", "node": 4021, "naklon": 5 }, +{ "label": "34/87", "node": 3437, "naklon": 12 }, +{ "label": "34/88", "node": 3428, "naklon": 12 }, +{ "label": "34/89", "node": 3430, "naklon": 12 }, +{ "label": "34/91", "node": 3454, "naklon": 6 }, +{ "label": "34/92", "node": 3492, "naklon": 6 }, +{ "label": "34/93", "node": 3462, "naklon": 6 }, +{ "label": "34/94", "node": 3427, "naklon": 6 }, +{ "label": "34/95", "node": 3434, "naklon": 6 }, +{ "label": "34/96", "node": 3456, "naklon": 6 }, +{ "label": "34/98/1", "node": 4307, "naklon": 6 }, +{ "label": "35/1", "node": 3968, "naklon": 0 }, +{ "label": "35/2", "node": 3969, "naklon": 0 }, +{ "label": "35/3", "node": 3947, "naklon": 0 }, +{ "label": "35/4", "node": 3979, "naklon": 0 }, +{ "label": "35/5", "node": 3959, "naklon": 0 }, +{ "label": "35/6", "node": 3948, "naklon": 0 }, +{ "label": "35/7", "node": 3961, "naklon": 0 }, +{ "label": "35/8", "node": 3956, "naklon": 0 }, +{ "label": "35/9", "node": 3604, "naklon": 0 }, +{ "label": "35/10", "node": 3944, "naklon": 0 }, +{ "label": "35/11", "node": 3960, "naklon": 0 }, +{ "label": "35/12", "node": 3958, "naklon": 0 }, +{ "label": "35/13", "node": 4036, "naklon": 5 }, +{ "label": "35/18", "node": 3893, "naklon": 5 }, +{ "label": "35/19", "node": 4108, "naklon": 5 }, +{ "label": "35/20", "node": 4017, "naklon": 5 }, +{ "label": "35/21", "node": 3963, "naklon": 0 }, +{ "label": "35/22", "node": 3658, "naklon": 0 }, +{ "label": "35/23", "node": 3975, "naklon": 0 }, +{ "label": "35/24", "node": 3980, "naklon": 0 }, +{ "label": "35/25", "node": 4012, "naklon": 0 }, +{ "label": "35/26", "node": 3655, "naklon": 0 }, +{ "label": "35/27", "node": 3962, "naklon": 0 }, +{ "label": "35/28", "node": 3945, "naklon": 0 }, +{ "label": "35/29", "node": 3569, "naklon": 0 }, +{ "label": "35/30", "node": 3429, "naklon": 0 }, +{ "label": "35/31", "node": 3657, "naklon": 0 }, +{ "label": "35/32", "node": 3646, "naklon": 0 }, +{ "label": "35/33", "node": 3622, "naklon": 0 }, +{ "label": "35/34", "node": 3612, "naklon": 0 }, +{ "label": "35/35", "node": 3955, "naklon": 0 }, +{ "label": "35/37", "node": 3878, "naklon": 0 }, +{ "label": "35/38", "node": 3965, "naklon": 0 }, +{ "label": "35/39", "node": 3970, "naklon": 0 }, +{ "label": "35/40", "node": 3611, "naklon": 0 }, +{ "label": "35/41", "node": 2635, "naklon": 0 }, +{ "label": "35/42", "node": 3978, "naklon": 0 }, +{ "label": "35/43", "node": 4213, "naklon": 0 }, +{ "label": "35/44", "node": 3984, "naklon": 0 }, +{ "label": "35/45", "node": 4218, "naklon": 0 }, +{ "label": "35/46", "node": 3973, "naklon": 0 }, +{ "label": "35/47", "node": 3974, "naklon": 0 }, +{ "label": "35/48", "node": 3759, "naklon": 0 }, +{ "label": "35/49", "node": 3844, "naklon": 0 }, +{ "label": "35/50", "node": 3804, "naklon": 0 }, +{ "label": "35/51", "node": 3831, "naklon": 0 }, +{ "label": "35/52", "node": 3643, "naklon": 0 }, +{ "label": "35/53", "node": 3966, "naklon": 0 }, +{ "label": "35/54", "node": 3971, "naklon": 0 }, +{ "label": "35/55", "node": 3650, "naklon": 6 }, +{ "label": "35/56", "node": 3651, "naklon": 6 }, +{ "label": "35/57", "node": 3669, "naklon": 6 }, +{ "label": "35/58", "node": 3648, "naklon": 6 }, +{ "label": "35/59", "node": 3645, "naklon": 6 }, +{ "label": "35/60", "node": 3659, "naklon": 6 }, +{ "label": "35/61", "node": 3647, "naklon": 6 }, +{ "label": "35/62", "node": 3644, "naklon": 6 }, +{ "label": "35/63", "node": 3671, "naklon": 6 }, +{ "label": "35/64", "node": 3682, "naklon": 6 }, +{ "label": "35/65", "node": 3672, "naklon": 6 }, +{ "label": "35/66", "node": 3683, "naklon": 6 }, +{ "label": "35/67", "node": 3673, "naklon": 6 }, +{ "label": "35/68", "node": 3674, "naklon": 6 }, +{ "label": "35/69", "node": 3679, "naklon": 6 }, +{ "label": "35/70", "node": 3649, "naklon": 6 }, +{ "label": "35/71", "node": 3687, "naklon": 6 }, +{ "label": "35/72", "node": 3677, "naklon": 6 }, +{ "label": "35/73", "node": 3690, "naklon": 6 }, +{ "label": "35/74", "node": 3691, "naklon": 6 }, +{ "label": "35/75", "node": 3676, "naklon": 6 }, +{ "label": "35/76", "node": 3680, "naklon": 6 }, +{ "label": "35/77", "node": 3668, "naklon": 6 }, +{ "label": "35/78", "node": 3681, "naklon": 6 }, +{ "label": "35/79", "node": 3670, "naklon": 6 }, +{ "label": "35/80", "node": 3689, "naklon": 6 }, +{ "label": "35/81", "node": 3678, "naklon": 6 }, +{ "label": "35/82", "node": 3693, "naklon": 6 }, +{ "label": "35/83", "node": 3654, "naklon": null }, +{ "label": "36/1", "node": 4086, "naklon": 0 }, +{ "label": "36/2", "node": 4085, "naklon": 0 }, +{ "label": "36/3", "node": 4083, "naklon": 0 }, +{ "label": "36/4", "node": 4087, "naklon": 0 }, +{ "label": "36/5", "node": 4077, "naklon": 0 }, +{ "label": "36/6", "node": 4082, "naklon": 0 }, +{ "label": "36/7", "node": 4186, "naklon": 0 }, +{ "label": "36/8", "node": 4206, "naklon": 0 }, +{ "label": "36/9", "node": 4080, "naklon": 0 }, +{ "label": "36/10", "node": 4081, "naklon": 0 }, +{ "label": "36/11", "node": 4210, "naklon": 0 }, +{ "label": "36/12", "node": 4079, "naklon": 0 }, +{ "label": "36/13", "node": 4076, "naklon": 0 }, +{ "label": "36/14", "node": 3852, "naklon": 0 }, +{ "label": "36/15", "node": 2813, "naklon": 0 }, +{ "label": "36/16", "node": 4219, "naklon": 0 }, +{ "label": "37/1A", "node": 3104, "naklon": 15 }, +{ "label": "37/1B", "node": 3121, "naklon": 15 }, +{ "label": "37/2", "node": 3113, "naklon": 10 }, +{ "label": "37/3", "node": 3118, "naklon": 10 }, +{ "label": "37/4", "node": 3111, "naklon": 10 }, +{ "label": "37/5", "node": 4020, "naklon": 10 }, +{ "label": "37/6", "node": 3119, "naklon": 10 }, +{ "label": "37/7", "node": 3110, "naklon": 10 }, +{ "label": "37/8", "node": 3108, "naklon": 10 }, +{ "label": "37/12", "node": 3107, "naklon": 0 }, +{ "label": "37/13", "node": 3199, "naklon": 0 }, +{ "label": "37/14", "node": 3120, "naklon": 0 }, +{ "label": "37/15", "node": 3122, "naklon": 0 }, +{ "label": "37/16", "node": 3908, "naklon": 0 }, +{ "label": "37/17", "node": 3114, "naklon": 0 }, +{ "label": "37/18", "node": 3105, "naklon": 0 }, +{ "label": "37/19", "node": 3116, "naklon": 0 }, +{ "label": "37/20", "node": 3106, "naklon": 0 }, +{ "label": "37/21", "node": 2887, "naklon": 5 }, +{ "label": "37/22", "node": 2888, "naklon": 5 }, +{ "label": "37/23", "node": 2877, "naklon": 5 }, +{ "label": "37/24", "node": 2891, "naklon": 5 }, +{ "label": "37/25", "node": 2886, "naklon": 5 }, +{ "label": "37/26", "node": 2892, "naklon": 5 }, +{ "label": "37/27", "node": 2882, "naklon": 5 }, +{ "label": "37/28", "node": 2883, "naklon": 5 }, +{ "label": "37/29", "node": 2876, "naklon": 5 }, +{ "label": "37/30", "node": 3109, "naklon": 5 }, +{ "label": "37/31", "node": 4152, "naklon": 5 }, +{ "label": "37/32", "node": 3117, "naklon": 5 }, +{ "label": "37/33", "node": 2870, "naklon": 5 }, +{ "label": "37/34", "node": 2867, "naklon": 0 }, +{ "label": "37/35", "node": 2865, "naklon": 0 }, +{ "label": "37/36", "node": 3096, "naklon": 0 }, +{ "label": "37/37", "node": 2871, "naklon": 0 }, +{ "label": "37/38", "node": 2884, "naklon": 0 }, +{ "label": "37/39", "node": 2855, "naklon": 0 }, +{ "label": "37/40", "node": 2878, "naklon": 0 }, +{ "label": "37/41", "node": 2889, "naklon": 0 }, +{ "label": "37/42", "node": 2879, "naklon": 0 }, +{ "label": "37/43", "node": 2850, "naklon": 0 }, +{ "label": "37/44", "node": 2894, "naklon": 0 }, +{ "label": "37/45", "node": 2880, "naklon": 0 }, +{ "label": "37/46", "node": 2893, "naklon": 0 }, +{ "label": "37/47", "node": 2890, "naklon": 0 }, +{ "label": "37/48", "node": 4355, "naklon": 0 }, +{ "label": "37/49", "node": 2885, "naklon": 0 }, +{ "label": "37/50", "node": 2875, "naklon": 0 }, +{ "label": "38/30A", "node": 3486, "naklon": 5 }, +{ "label": "38/30B", "node": 3714, "naklon": 0 }, +{ "label": "38/32A", "node": 3483, "naklon": 5 }, +{ "label": "38/32B", "node": 3496, "naklon": 0 }, +{ "label": "38/35A", "node": 3487, "naklon": 5 }, +{ "label": "38/35B", "node": 3498, "naklon": 5 }, +{ "label": "38/38A", "node": 3578, "naklon": 5 }, +{ "label": "38/38B", "node": 3508, "naklon": 5 }, +{ "label": "38/59A", "node": 3787, "naklon": 5 }, +{ "label": "38/59B", "node": 3491, "naklon": 5 }, +{ "label": "38/1", "node": 3568, "naklon": null }, +{ "label": "38/2", "node": 3502, "naklon": 0 }, +{ "label": "38/3", "node": 3836, "naklon": 0 }, +{ "label": "38/4", "node": 3588, "naklon": 0 }, +{ "label": "38/5", "node": 3493, "naklon": 0 }, +{ "label": "38/6", "node": 3580, "naklon": 0 }, +{ "label": "38/7", "node": 3572, "naklon": 0 }, +{ "label": "38/8", "node": 3506, "naklon": 0 }, +{ "label": "38/9", "node": 3503, "naklon": 0 }, +{ "label": "38/10", "node": 3579, "naklon": 0 }, +{ "label": "38/11", "node": 3586, "naklon": 0 }, +{ "label": "38/12", "node": 3495, "naklon": 5 }, +{ "label": "38/13", "node": 3492, "naklon": 5 }, +{ "label": "38/14", "node": 3532, "naklon": 5 }, +{ "label": "38/15", "node": 3574, "naklon": 5 }, +{ "label": "38/16", "node": 4140, "naklon": 5 }, +{ "label": "38/17", "node": 3795, "naklon": 5 }, +{ "label": "38/18", "node": 3788, "naklon": 5 }, +{ "label": "38/19", "node": 3796, "naklon": 5 }, +{ "label": "38/20", "node": 3797, "naklon": 5 }, +{ "label": "38/21", "node": 3798, "naklon": 5 }, +{ "label": "38/22", "node": 3786, "naklon": 5 }, +{ "label": "38/23", "node": 4067, "naklon": 5 }, +{ "label": "38/24", "node": 3773, "naklon": 5 }, +{ "label": "38/25", "node": 3774, "naklon": 5 }, +{ "label": "38/26", "node": 3789, "naklon": 5 }, +{ "label": "38/27", "node": 3520, "naklon": null }, +{ "label": "38/29", "node": 3577, "naklon": 5 }, +{ "label": "38/31", "node": 3530, "naklon": null }, +{ "label": "38/33", "node": 3488, "naklon": 5 }, +{ "label": "38/34", "node": 3505, "naklon": 5 }, +{ "label": "38/36", "node": 3497, "naklon": 5 }, +{ "label": "38/37", "node": 3490, "naklon": 5 }, +{ "label": "38/39", "node": 3585, "naklon": 5 }, +{ "label": "38/40", "node": 3582, "naklon": 5 }, +{ "label": "38/41", "node": 3507, "naklon": 5 }, +{ "label": "38/42", "node": 3484, "naklon": 5 }, +{ "label": "38/43", "node": 3501, "naklon": 5 }, +{ "label": "38/44", "node": 3581, "naklon": 5 }, +{ "label": "38/45", "node": 4192, "naklon": 5 }, +{ "label": "38/46", "node": 3576, "naklon": 5 }, +{ "label": "38/47", "node": 3489, "naklon": 5 }, +{ "label": "38/48", "node": 3573, "naklon": 5 }, +{ "label": "38/49", "node": 3504, "naklon": 5 }, +{ "label": "38/50", "node": 3794, "naklon": 5 }, +{ "label": "38/51", "node": 3485, "naklon": 5 }, +{ "label": "38/52", "node": 3482, "naklon": 5 }, +{ "label": "38/53", "node": 3575, "naklon": 5 }, +{ "label": "38/54", "node": 3499, "naklon": 5 }, +{ "label": "38/55", "node": 3494, "naklon": 5 }, +{ "label": "38/56", "node": 3583, "naklon": 5 }, +{ "label": "38/57", "node": 3570, "naklon": 5 }, +{ "label": "38/58", "node": 3500, "naklon": 0 }, +{ "label": "38/63", "node": 3510, "naklon": null }, +{ "label": "38/64", "node": 3512, "naklon": null }, +{ "label": "38/67", "node": 3535, "naklon": null }, +{ "label": "38/68", "node": 3531, "naklon": null }, +{ "label": "38/69", "node": 3537, "naklon": null }, +{ "label": "39/1", "node": 3522, "naklon": 10 }, +{ "label": "39/2", "node": 4018, "naklon": 10 }, +{ "label": "39/3", "node": 4019, "naklon": 10 }, +{ "label": "39/4", "node": 4154, "naklon": 5 }, +{ "label": "39/5", "node": 3907, "naklon": 5 }, +{ "label": "39/6", "node": 4148, "naklon": 0 }, +{ "label": "39/7", "node": 4153, "naklon": 0 }, +{ "label": "39/8", "node": 3938, "naklon": 0 }, +{ "label": "39/9", "node": 3802, "naklon": 0 }, +{ "label": "39/10", "node": 4015, "naklon": 0 }, +{ "label": "39/11", "node": 3929, "naklon": 0 }, +{ "label": "39/12", "node": 3946, "naklon": 0 }, +{ "label": "39/13", "node": 4014, "naklon": 0 }, +{ "label": "39/14", "node": 4155, "naklon": 0 }, +{ "label": "39/15", "node": 4149, "naklon": 0 }, +{ "label": "39/16", "node": 3642, "naklon": 0 }, +{ "label": "39/17", "node": 3636, "naklon": 5 }, +{ "label": "39/18", "node": 3991, "naklon": 0 }, +{ "label": "39/19", "node": 3994, "naklon": 0 }, +{ "label": "39/20", "node": 3990, "naklon": 0 }, +{ "label": "39/21", "node": 3967, "naklon": 0 }, +{ "label": "39/22", "node": 3977, "naklon": 0 }, +{ "label": "39/23", "node": 3757, "naklon": 15 }, +{ "label": "39/24", "node": 3633, "naklon": 15 }, +{ "label": "39/25", "node": 3744, "naklon": 15 }, +{ "label": "39/26", "node": 4023, "naklon": 5 }, +{ "label": "39/27", "node": 3720, "naklon": 5 }, +{ "label": "39/28", "node": 3734, "naklon": 5 }, +{ "label": "39/29", "node": 3741, "naklon": 5 }, +{ "label": "39/30", "node": 3721, "naklon": 5 }, +{ "label": "39/31", "node": 3845, "naklon": 0 }, +{ "label": "39/32", "node": 3840, "naklon": 0 }, +{ "label": "39/33", "node": 3837, "naklon": null }, +{ "label": "39/34", "node": 3839, "naklon": 0 }, +{ "label": "41/1", "node": 3542, "naklon": null }, +{ "label": "41/2", "node": 3566, "naklon": null }, +{ "label": "41/3", "node": 3548, "naklon": null }, +{ "label": "41/4", "node": 3515, "naklon": null }, +{ "label": "41/5", "node": 3559, "naklon": null }, +{ "label": "41/6", "node": 3509, "naklon": null }, +{ "label": "41/7", "node": 3524, "naklon": null }, +{ "label": "41/8", "node": 3518, "naklon": null }, +{ "label": "41/9", "node": 3182, "naklon": null }, +{ "label": "41/10", "node": 3187, "naklon": null }, +{ "label": "41/11", "node": 3195, "naklon": 0 }, +{ "label": "41/12", "node": 3857, "naklon": 0 }, +{ "label": "41/13", "node": 3183, "naklon": 0 }, +{ "label": "41/14", "node": 3177, "naklon": 0 }, +{ "label": "41/15", "node": 3189, "naklon": 0 }, +{ "label": "41/16", "node": 3186, "naklon": 0 }, +{ "label": "42/1", "node": 3178, "naklon": 0 }, +{ "label": "42/2", "node": 3219, "naklon": 0 }, +{ "label": "42/3", "node": 3475, "naklon": 0 }, +{ "label": "42/4", "node": 3175, "naklon": 0 }, +{ "label": "42/5", "node": 3222, "naklon": 0 }, +{ "label": "42/6", "node": 3221, "naklon": 0 }, +{ "label": "42/7", "node": 3181, "naklon": 0 }, +{ "label": "42/8", "node": 3180, "naklon": 0 }, +{ "label": "42/9", "node": 3218, "naklon": 0 }, +{ "label": "42/10", "node": 3176, "naklon": 0 }, +{ "label": "42/11", "node": 3174, "naklon": 0 }, +{ "label": "42/12", "node": 3220, "naklon": 0 }, +{ "label": "42/13", "node": 3533, "naklon": null }, +{ "label": "42/14", "node": 3543, "naklon": null }, +{ "label": "42/15", "node": 3554, "naklon": null }, +{ "label": "42/16", "node": 3549, "naklon": null }, +{ "label": "43/1", "node": 2857, "naklon": 5 }, +{ "label": "43/2", "node": 2752, "naklon": 5 }, +{ "label": "43/3", "node": 2753, "naklon": 5 }, +{ "label": "43/4", "node": 3024, "naklon": 5 }, +{ "label": "43/5", "node": 2754, "naklon": 5 }, +{ "label": "43/6", "node": 4423, "naklon": 5 }, +{ "label": "43/7", "node": 4368, "naklon": 5 }, +{ "label": "43/8", "node": 2978, "naklon": 5 }, +{ "label": "43/9", "node": 2868, "naklon": 5 }, +{ "label": "43/10", "node": 4377, "naklon": 5 }, +{ "label": "43/11", "node": 2757, "naklon": 5 }, +{ "label": "43/12", "node": 2970, "naklon": 5 }, +{ "label": "43/13", "node": 2758, "naklon": 5 }, +{ "label": "43/14", "node": 4378, "naklon": 5 }, +{ "label": "43/15", "node": 2759, "naklon": 5 }, +{ "label": "43/16", "node": 4342, "naklon": 5 }, +{ "label": "43/17", "node": 3026, "naklon": null }, +{ "label": "43/18", "node": 2986, "naklon": null }, +{ "label": "43/19", "node": 4343, "naklon": null }, +{ "label": "43/20", "node": 2760, "naklon": null }, +{ "label": "43/21", "node": 4379, "naklon": null }, +{ "label": "43/22", "node": 2971, "naklon": null }, +{ "label": "43/23", "node": 2761, "naklon": null }, +{ "label": "43/24", "node": 2762, "naklon": null }, +{ "label": "43/25", "node": 4339, "naklon": null }, +{ "label": "43/26", "node": 4380, "naklon": null }, +{ "label": "43/27", "node": 2975, "naklon": null }, +{ "label": "43/28", "node": 3003, "naklon": null }, +{ "label": "43/29", "node": 4338, "naklon": null }, +{ "label": "43/30", "node": 3002, "naklon": null }, +{ "label": "43/31", "node": 4345, "naklon": null }, +{ "label": "43/32", "node": 2979, "naklon": null }, +{ "label": "43/33", "node": 2989, "naklon": null }, +{ "label": "43/34", "node": 2996, "naklon": null }, +{ "label": "43/35", "node": 2972, "naklon": null }, +{ "label": "43/36", "node": 2988, "naklon": null }, +{ "label": "43/37", "node": 4344, "naklon": null }, +{ "label": "43/38", "node": 3022, "naklon": null }, +{ "label": "43/39", "node": 4341, "naklon": null }, +{ "label": "43/40", "node": 2983, "naklon": null }, +{ "label": "43/41", "node": 2995, "naklon": null }, +{ "label": "43/42", "node": 2763, "naklon": null }, +{ "label": "43/43", "node": 2764, "naklon": null }, +{ "label": "43/44", "node": 2765, "naklon": null }, +{ "label": "43/45", "node": 2766, "naklon": null }, +{ "label": "43/46", "node": 2767, "naklon": null }, +{ "label": "43/47", "node": 2768, "naklon": null }, +{ "label": "43/48", "node": 3018, "naklon": null }, +{ "label": "43/49", "node": 2982, "naklon": null }, +{ "label": "43/50", "node": 3019, "naklon": 0 }, +{ "label": "43/51", "node": 3013, "naklon": null }, +{ "label": "43/52", "node": 3007, "naklon": null }, +{ "label": "43/53", "node": 2980, "naklon": null }, +{ "label": "43/54", "node": 3011, "naklon": null }, +{ "label": "43/55", "node": 2672, "naklon": null }, +{ "label": "43/56", "node": 2673, "naklon": null }, +{ "label": "43/57", "node": 2674, "naklon": null }, +{ "label": "43/58", "node": 2675, "naklon": null }, +{ "label": "43/59", "node": 2676, "naklon": null }, +{ "label": "43/60", "node": 2677, "naklon": null }, +{ "label": "43/61", "node": 2678, "naklon": null }, +{ "label": "43/62", "node": 2679, "naklon": null }, +{ "label": "43/63", "node": 2680, "naklon": null }, +{ "label": "43/64", "node": 2840, "naklon": null }, +{ "label": "43/65", "node": 2682, "naklon": null }, +{ "label": "43/66", "node": 2683, "naklon": null }, +{ "label": "43/67", "node": 2684, "naklon": 0 }, +{ "label": "43/68", "node": 2685, "naklon": null }, +{ "label": "43/69", "node": 2686, "naklon": null }, +{ "label": "43/70", "node": 2687, "naklon": null }, +{ "label": "43/71", "node": 2688, "naklon": null }, +{ "label": "43/72", "node": 2689, "naklon": null }, +{ "label": "43/73", "node": 2690, "naklon": null }, +{ "label": "43/74", "node": 2691, "naklon": null }, +{ "label": "43/75", "node": 2692, "naklon": null }, +{ "label": "43/76", "node": 2693, "naklon": 0 }, +{ "label": "43/77", "node": 2694, "naklon": null }, +{ "label": "43/78", "node": 2695, "naklon": null }, +{ "label": "43/79", "node": 2696, "naklon": 0 }, +{ "label": "43/80", "node": 2697, "naklon": null }, +{ "label": "43/81", "node": 2698, "naklon": 0 }, +{ "label": "43/82", "node": 2699, "naklon": null }, +{ "label": "43/83", "node": 2700, "naklon": 0 }, +{ "label": "43/84", "node": 2744, "naklon": null }, +{ "label": "43/85", "node": 2745, "naklon": 0 }, +{ "label": "43/86", "node": 2746, "naklon": null }, +{ "label": "43/87", "node": 2747, "naklon": 0 }, +{ "label": "43/88", "node": 2748, "naklon": null }, +{ "label": "43/89", "node": 2749, "naklon": 0 }, +{ "label": "43/90", "node": 2841, "naklon": null }, +{ "label": "45/1", "node": 4237, "naklon": 5 }, +{ "label": "45/2", "node": 4226, "naklon": 5 }, +{ "label": "45/3", "node": 4242, "naklon": 5 }, +{ "label": "45/4", "node": 4179, "naklon": 5 }, +{ "label": "45/5", "node": 4247, "naklon": 5 }, +{ "label": "45/6", "node": 4245, "naklon": 5 }, +{ "label": "45/7", "node": 3872, "naklon": 5 }, +{ "label": "45/8", "node": 4175, "naklon": 5 }, +{ "label": "45/9", "node": 4236, "naklon": 5 }, +{ "label": "45/10", "node": 4170, "naklon": 5 }, +{ "label": "45/11", "node": 4238, "naklon": 5 }, +{ "label": "45/12", "node": 4246, "naklon": 5 }, +{ "label": "45/13", "node": 4166, "naklon": 5 }, +{ "label": "45/14", "node": 4227, "naklon": 5 }, +{ "label": "45/15", "node": 4171, "naklon": 5 }, +{ "label": "45/16", "node": 4180, "naklon": 5 }, +{ "label": "45/17", "node": 4244, "naklon": 5 }, +{ "label": "45/18", "node": 4199, "naklon": 5 }, +{ "label": "45/19", "node": 4239, "naklon": 5 }, +{ "label": "45/20", "node": 4207, "naklon": 5 }, +{ "label": "45/21", "node": 4223, "naklon": 5 }, +{ "label": "45/22", "node": 4230, "naklon": 5 }, +{ "label": "45/23", "node": 4233, "naklon": 5 }, +{ "label": "45/24", "node": 4222, "naklon": 5 }, +{ "label": "45/25", "node": 4217, "naklon": 5 }, +{ "label": "45/26", "node": 4243, "naklon": 5 }, +{ "label": "45/27", "node": 4200, "naklon": 5 }, +{ "label": "45/28", "node": 4228, "naklon": 5 }, +{ "label": "45/29", "node": 4211, "naklon": 5 }, +{ "label": "45/30", "node": 4234, "naklon": 5 }, +{ "label": "45/31", "node": 4235, "naklon": 5 }, +{ "label": "45/32", "node": 4203, "naklon": 5 }, +{ "label": "45/33", "node": 4240, "naklon": 5 }, +{ "label": "45/34", "node": 4224, "naklon": 5 }, +{ "label": "45/35", "node": 4232, "naklon": 5 }, +{ "label": "45/36", "node": 4231, "naklon": 5 }, +{ "label": "45/37", "node": 4161, "naklon": 5 }, +{ "label": "45/38", "node": 4225, "naklon": 5 }, +{ "label": "45/39", "node": 4241, "naklon": 5 }, +{ "label": "45/40", "node": 4229, "naklon": 5 }, +{ "label": "45/41", "node": 4221, "naklon": 5 }, +{ "label": "45/42", "node": 4212, "naklon": 5 }, +{ "label": "45/43", "node": 4216, "naklon": 5 }, +{ "label": "45/44", "node": 3864, "naklon": null }, +{ "label": "46/1", "node": 3806, "naklon": 5 }, +{ "label": "46/2", "node": 3813, "naklon": 5 }, +{ "label": "46/3", "node": 3815, "naklon": 5 }, +{ "label": "46/4", "node": 3807, "naklon": 5 }, +{ "label": "46/5", "node": 3895, "naklon": 5 }, +{ "label": "46/6", "node": 3809, "naklon": 5 }, +{ "label": "46/7", "node": 3820, "naklon": 5 }, +{ "label": "46/8", "node": 3805, "naklon": 5 }, +{ "label": "46/9", "node": 3894, "naklon": 0 }, +{ "label": "46/10", "node": 4055, "naklon": 0 }, +{ "label": "46/11", "node": 3812, "naklon": 5 }, +{ "label": "46/12", "node": 3822, "naklon": 5 }, +{ "label": "46/13", "node": 3821, "naklon": 5 }, +{ "label": "46/14", "node": 3808, "naklon": 5 }, +{ "label": "46/15", "node": 3799, "naklon": 5 }, +{ "label": "46/16", "node": 3816, "naklon": 5 }, +{ "label": "46/17", "node": 3751, "naklon": 5 }, +{ "label": "46/18", "node": 3814, "naklon": 5 }, +{ "label": "46/19", "node": 4044, "naklon": 0 }, +{ "label": "46/20", "node": 3931, "naklon": 0 }, +{ "label": "46/21", "node": 3902, "naklon": 5 }, +{ "label": "46/22", "node": 3916, "naklon": 5 }, +{ "label": "46/23", "node": 3892, "naklon": 5 }, +{ "label": "46/24", "node": 3914, "naklon": 5 }, +{ "label": "46/25", "node": 3898, "naklon": 5 }, +{ "label": "46/26", "node": 3897, "naklon": 5 }, +{ "label": "46/27", "node": 3885, "naklon": 5 }, +{ "label": "46/28", "node": 3906, "naklon": 5 }, +{ "label": "46/29", "node": 3930, "naklon": 0 }, +{ "label": "46/30", "node": 3936, "naklon": 0 }, +{ "label": "46/31", "node": 3860, "naklon": 5 }, +{ "label": "46/32", "node": 3841, "naklon": 5 }, +{ "label": "46/33", "node": 3873, "naklon": 5 }, +{ "label": "46/34", "node": 3854, "naklon": 5 }, +{ "label": "46/35", "node": 3939, "naklon": 5 }, +{ "label": "46/36", "node": 3858, "naklon": 5 }, +{ "label": "46/37", "node": 3940, "naklon": 5 }, +{ "label": "46/38", "node": 4035, "naklon": 5 }, +{ "label": "47/1", "node": 3373, "naklon": 0 }, +{ "label": "47/2", "node": 3374, "naklon": 0 }, +{ "label": "47/3", "node": 3384, "naklon": 0 }, +{ "label": "47/4", "node": 3385, "naklon": 0 }, +{ "label": "48/1", "node": 4051, "naklon": 5 }, +{ "label": "48/2", "node": 4041, "naklon": 5 }, +{ "label": "48/3", "node": 4056, "naklon": 5 }, +{ "label": "48/4", "node": 3875, "naklon": 5 }, +{ "label": "48/5", "node": 4061, "naklon": 5 }, +{ "label": "48/6", "node": 4047, "naklon": 5 }, +{ "label": "48/7", "node": 4060, "naklon": 5 }, +{ "label": "48/8", "node": 4059, "naklon": 5 }, +{ "label": "48/9", "node": 4058, "naklon": 5 }, +{ "label": "48/10", "node": 3635, "naklon": 5 }, +{ "label": "48/11", "node": 3640, "naklon": 5 }, +{ "label": "48/12", "node": 3747, "naklon": 5 }, +{ "label": "48/13", "node": 3629, "naklon": 5 }, +{ "label": "48/14", "node": 4048, "naklon": 5 }, +{ "label": "48/15", "node": 4063, "naklon": 5 }, +{ "label": "48/16", "node": 4062, "naklon": 5 }, +{ "label": "48/17", "node": 4043, "naklon": 5 }, +{ "label": "48/18", "node": 4052, "naklon": 5 }, +{ "label": "48/19", "node": 4042, "naklon": 5 }, +{ "label": "48/20", "node": 4053, "naklon": 5 }, +{ "label": "50/15A", "node": 4167, "naklon": null }, +{ "label": "50/15B", "node": 4159, "naklon": null }, +{ "label": "50/1", "node": 4183, "naklon": 0 }, +{ "label": "50/2", "node": 4157, "naklon": 0 }, +{ "label": "50/3", "node": 4160, "naklon": 0 }, +{ "label": "50/4", "node": 4173, "naklon": 0 }, +{ "label": "50/5", "node": 4177, "naklon": 0 }, +{ "label": "50/6", "node": 4174, "naklon": 0 }, +{ "label": "50/7", "node": 4178, "naklon": 0 }, +{ "label": "50/8", "node": 4195, "naklon": 0 }, +{ "label": "50/9", "node": 4169, "naklon": 0 }, +{ "label": "50/10", "node": 4162, "naklon": 0 }, +{ "label": "50/11", "node": 4158, "naklon": 0 }, +{ "label": "50/12", "node": 4182, "naklon": 0 }, +{ "label": "50/13", "node": 4194, "naklon": 0 }, +{ "label": "50/14", "node": 4184, "naklon": 0 }, +{ "label": "50/16", "node": 4197, "naklon": null }, +{ "label": "50/17", "node": 4164, "naklon": null }, +{ "label": "50/18", "node": 3306, "naklon": null }, +{ "label": "50/19", "node": 4168, "naklon": null }, +{ "label": "50/20", "node": 4193, "naklon": null }, +{ "label": "50/21", "node": 4187, "naklon": null }, +{ "label": "50/22", "node": 4163, "naklon": null }, +{ "label": "50/23", "node": 4165, "naklon": null }, +{ "label": "50/24", "node": 4185, "naklon": null }, +{ "label": "50/25", "node": 3904, "naklon": null }, +{ "label": "53/1", "node": 2619, "naklon": 0 }, +{ "label": "53/2", "node": 2623, "naklon": 0 }, +{ "label": "53/3", "node": 2617, "naklon": 0 }, +{ "label": "53/4", "node": 2622, "naklon": 0 }, +{ "label": "53/5", "node": 2618, "naklon": 0 }, +{ "label": "53/6", "node": 2626, "naklon": 0 }, +{ "label": "53/7", "node": 2869, "naklon": 0 }, +{ "label": "53/8", "node": 2613, "naklon": 0 }, +{ "label": "53/9", "node": 2608, "naklon": 0 }, +{ "label": "53/10", "node": 2611, "naklon": 0 }, +{ "label": "53/11", "node": 2598, "naklon": 0 }, +{ "label": "53/12", "node": 3528, "naklon": 0 }, +{ "label": "53/13", "node": 3545, "naklon": 0 }, +{ "label": "53/14", "node": 2620, "naklon": 0 }, +{ "label": "53/15", "node": 2612, "naklon": 0 }, +{ "label": "53/16", "node": 2615, "naklon": 0 }, +{ "label": "53/17", "node": 3722, "naklon": 0 }, +{ "label": "53/18", "node": 2624, "naklon": 0 }, +{ "label": "53/19", "node": 2609, "naklon": 0 }, +{ "label": "53/20", "node": 2625, "naklon": 0 }, +{ "label": "53/21", "node": 2602, "naklon": 0 }, +{ "label": "53/22", "node": 2610, "naklon": 0 }, +{ "label": "53/23", "node": 2599, "naklon": 0 }, +{ "label": "53/24", "node": 2605, "naklon": 0 }, +{ "label": "53/25", "node": 2593, "naklon": 0 }, +{ "label": "53/26", "node": 3074, "naklon": 0 }, +{ "label": "53/27", "node": 2740, "naklon": 0 }, +{ "label": "53/28", "node": 2614, "naklon": 0 }, +{ "label": "53/29", "node": 2601, "naklon": 0 }, +{ "label": "53/30", "node": 4196, "naklon": 0 }, +{ "label": "53/31", "node": 2607, "naklon": 0 }, +{ "label": "53/32", "node": 2582, "naklon": 0 }, +{ "label": "53/33", "node": 2594, "naklon": 0 }, +{ "label": "53/34", "node": 2589, "naklon": 0 }, +{ "label": "53/35", "node": 2596, "naklon": 0 }, +{ "label": "53/36", "node": 2603, "naklon": 0 }, +{ "label": "53/37", "node": 2597, "naklon": 0 }, +{ "label": "53/38", "node": 2590, "naklon": 0 }, +{ "label": "53/39", "node": 2581, "naklon": 0 }, +{ "label": "53/40", "node": 2583, "naklon": 0 }, +{ "label": "53/41", "node": 2580, "naklon": 0 }, +{ "label": "53/42", "node": 2579, "naklon": 0 }, +{ "label": "53/43", "node": 2797, "naklon": 0 }, +{ "label": "53/44", "node": 2577, "naklon": 0 }, +{ "label": "53/45", "node": 2586, "naklon": 0 }, +{ "label": "53/46", "node": 2588, "naklon": 0 }, +{ "label": "53/47", "node": 2591, "naklon": 0 }, +{ "label": "53/48", "node": 2592, "naklon": 0 }, +{ "label": "53/49", "node": 2573, "naklon": 0 }, +{ "label": "53/50", "node": 2595, "naklon": 0 }, +{ "label": "53/51", "node": 2587, "naklon": 0 }, +{ "label": "53/52", "node": 2578, "naklon": 0 }, +{ "label": "53/53", "node": 2574, "naklon": 0 }, +{ "label": "53/54", "node": 2571, "naklon": 0 }, +{ "label": "53/55", "node": 2570, "naklon": 0 }, +{ "label": "53/56", "node": 2576, "naklon": 0 }, +{ "label": "53/57", "node": 2881, "naklon": 0 }, +{ "label": "53/58", "node": 2575, "naklon": 0 }, +{ "label": "53/59", "node": 2572, "naklon": 0 }, +{ "label": "53/60", "node": 2569, "naklon": 0 }, +{ "label": "55/1", "node": 4324, "naklon": 0 }, +{ "label": "55/2", "node": 4319, "naklon": 0 }, +{ "label": "55/3", "node": 4327, "naklon": 0 }, +{ "label": "55/4", "node": 4333, "naklon": 0 }, +{ "label": "55/5", "node": 4332, "naklon": 0 }, +{ "label": "55/6", "node": 4320, "naklon": 0 }, +{ "label": "55/7", "node": 4317, "naklon": 0 }, +{ "label": "55/8", "node": 4318, "naklon": 0 }, +{ "label": "55/9", "node": 4328, "naklon": 0 }, +{ "label": "55/10", "node": 4323, "naklon": 0 }, +{ "label": "55/11", "node": 4325, "naklon": 0 }, +{ "label": "55/12", "node": 4326, "naklon": 0 }, +{ "label": "55/13", "node": 4316, "naklon": 0 }, +{ "label": "55/14", "node": 4322, "naklon": 0 }, +{ "label": "55/15", "node": 4331, "naklon": 0 }, +{ "label": "55/16", "node": 4321, "naklon": 0 }, +{ "label": "55/17", "node": 4315, "naklon": 0 }, +{ "label": "55/18", "node": 4329, "naklon": 0 }, +{ "label": "55/19", "node": 4334, "naklon": 0 }, +{ "label": "55/20", "node": 4330, "naklon": 0 } +]; + +module.exports = { naklony }; diff --git a/RVO53/databases/modbus_config.js b/RVO53/databases/modbus_config.js new file mode 100755 index 0000000..b73116a --- /dev/null +++ b/RVO53/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/RVO53/databases/nodes.table b/RVO53/databases/nodes.table new file mode 100755 index 0000000..20b13f8 --- /dev/null +++ b/RVO53/databases/nodes.table @@ -0,0 +1,61 @@ +node:number|pole_number:string|node_type:string|tbname:string|line:number|profile:string|processed:boolean|status:boolean|time_of_last_communication:number ++|2569|60|3f|roKgWqY95V3mXMRzyAjK5P0bLjexpJPvaGDBw826|1||1|1|1760574226604|............. ++|2570|55|1f|PLBJzmK1r3Gynd6OW0gKN20e5wV4vx9bDEqNgYR8|1||1|1|1760574226764|............. ++|2571|54|3f|Nzp2OoJlqn6r1ZgvdA3BXW7abBwP5G4eE3RQmyxD|1||1|1|1760574226924|............. ++|2572|59|2f|roKgWqY95V3mXMRzyAjKa20bLjexpJPvaGDBw826|1||1|1|1760574227084|............. ++|2573|49|1f|ZmRwd93QL4gaezxEbAx2vKk1prn2XjlPvGyqJ6BO|1||1|1|1760574227259|............. ++|2574|53|2f|wvKJdZML6mXP4DzWBAXxE9AjxNloa5g23Ve9Y1ry|1||1|1|1760574227435|............. ++|2575|58|1f|E6Kg9oDnLWyzPRMva7v53YkJxp4VG58qO2w1lZYe|1||1|1|1760574227563|............. ++|2576|56|2f|52dD6ZlV1QaOpRBmbAqGxGkKnGzWMLj4eJq38Pgo|1||1|1|1760574227707|............. ++|3606|52|1f|EjgWGnXaLy9opPOz20n4w3786BlYM3w1deVQvbKr|1||1|1|1760574097694|............. ++|2579|42|3f|dz4ojlpP85JMgDLZWkQJxg7aKYqQexEr62GXRV1y|1||1|1|1760574237179|............. ++|2586|45|3f|K94XLav1glVRnyQ6r01P1yAme3YJwBxM5oOzdP2j|1||1|1|1760574254255|............. ++|2587|51|3f|3a5oqJN1bgnx4Ol9dk89327ByE6jQ8mKDWMpGrLV|1||1|1|1760574254447|............. ++|2588|46|1f|d9x2V5LGYBzXp4mMRAOmbykPloaqJwnQj6DgrNe3|1||1|1|1760573912525|............. ++|2592|48|3f|aw4eELG2DlPMdn1JW0BM3OAqQXOZRN3xB5yp8VKr|1||1|1|1760574267178|............. ++|2594|33|3f|g9OxBZ5KRwNznlY6pAppVGAWXvjdEL4eGQobMDy2|1||1|1|1760573920703|............. ++|2595|50|2f|eod9aRWLVl34Gx1Dn7VN3E72rz6qjgmpEXwQJN5Z|1||1|1|1760574297592|............. ++|2596|35|2f|JX1ObgmqGZ54DMyYL7aDmMkEVdve38WKRzwjNrQ9|1||1|1|1760574297832|............. ++|2597|37|1f|RO8rjaBDy21qPQJzW7omxW0pK3xmNleVZg9Ed4Gw|1||1|1|1760574298088|............. ++|2603|36|3f|RvmwNz8QPblKp41GD7lKM9kJrLVYoBO92dMegn6W|1||1|1|1760573870162|............. ++|2797|43|1f|d5xjWYMwEJon6rLlK7yEwP7qgV4DaOeNB9ZX3Gzb|1||1|1|1760574074708|............. ++|2577|44|2f|gRoJEyXVx4qD9er287L43l7wBzGldaPjLWQKm3Mv|1||1|1|1760574234432|............. ++|2581|39|3f|Z5KyJe9nEg1QNbWlX0w4b8koDjBLdqzR83VGv624|1||1|1|1760574237594|............. ++|2582|32|2f|JzwxZXOvDj1bVrN4nkW5gRA8qdyBl3MRKLpGPgaQ|1||1|1|1760574249000|............. ++|2583|40|1f|1JMYvnx2RzKEo4aWQ7DGBLkL8yZV3m9NBePXbrdj|1||1|1|1760574251971|............. ++|2589|34|1f|OzNMgZ9n43qPbjXmy7zwmyA2DKdYvW5e6pxGRrVa|1||1|1|1760573915799|............. ++|2590|38|2f|3JjOWdylwgNLzxVab7NaqbkZ2vG64rq8PEB5QmDo|1||1|1|1760574263760|............. ++|2591|47|2f|B5EoxeMVp4zwr8nqW0GBxgARjvD1PNamOGbLg63Z|1||1|1|1760574263951|............. ++|2615|16|3f|nJL5lPMwBx23YpqRe0rpne7damXvWVbOrD4gNzy8|1||1|0|1759551936694|............. ++|3993|17|1f|XMBbew5z4ELrZa2mRAd3rq78vPN6gy3DdVYlpKjq|1||1|1|1760574404729|............. ++|2869|7|1f|3a5oqJN1bgnx4Ol9dk89827ByE6jQ8mKDWMpGrLV|1||1|1|1760574075187|............. ++|2593|25|3f|apKVJBwOyrP35m2lv7KYX60YXbeWNd64En9GxRqg|1||1|1|1760574324333|............. ++|2605|24|1f|DbQY6zyveZRwK5drV0Z8vr7joE4XJM83N9xl2nWq|1||1|1|1760573870753|............. ++|3074|26|2f|o9vbeQlLMVg8j5dq4keLBD0NxZpEmnXzwYKO1ar2|1||1|1|1760574084947|............. ++|2609|19|2f|zdQO8GwxDqjRgP4137YVbbANyKlpem2nL65rvVJY|1||1|1|1760574360657|............. ++|2610|22|2f|zrR51V2ajQ9ZLygPKkEMbKkYDq38xOJolENBXGnv|1||1|1|1760574230454|............. ++|2602|21|1f|5dBNwRp9graYJxZn409NgqklVov1b2QLPDqGm6XK|1||1|1|1760573857591|............. ++|2620|14|1f|E6Kg9oDnLWyzPRMva7v5qYkJxp4VG58qO2w1lZYe|1||1|1|1760574056034|............. ++|2622|4|1f|aw4eELG2DlPMdn1JW0BMmOAqQXOZRN3xB5yp8VKr|1||1|1|1760573983593|............. ++|4196|30|3f|6lQGaY9RDywdVzObj0PavXkPg4NBn3exEK51LWZq|1||1|1|1760574251476|............. ++|2663|31|01-Repeater|m6EYyZoJ4gWexdjVPAR5V37RDOq9wv2N5XzKGplr|1||0|1|1760571106798|............. ++|2611|10|1f|Nzp2OoJlqn6r1ZgvdA3BxW7abBwP5G4eE3RQmyxD|1||1|1|1760574372126|............. ++|2608|9|3f|wvKJdZML6mXP4DzWBAXxq9AjxNloa5g23Ve9Y1ry|1||1|1|1760574249878|............. ++|2612|15|3f|roKgWqY95V3mXMRzyAjKD20bLjexpJPvaGDBw826|1||1|1|1760574245022|............. ++|2618|5|2f|ZmRwd93QL4gaezxEbAx2aKk1prn2XjlPvGyqJ6BO|1||1|1|1760573937205|............. ++|2619|1|1f|K94XLav1glVRnyQ6r01PYyAme3YJwBxM5oOzdP2j|1||1|1|1760574287209|............. ++|2623|2|2f|d9x2V5LGYBzXp4mMRAOmqykPloaqJwnQj6DgrNe3|1||1|1|1760574442124|............. ++|2598|11|2f|PLBJzmK1r3Gynd6OW0gKY20e5wV4vx9bDEqNgYR8|1||1|1|1760574451549|............. ++|2624|18|1f|gYbDLqlyZVoRerQpB72MzekWJnwM5z24POKa8Exj|1||1|1|1760573999886|............. ++|2625|20|3f|WlVJBygjDZMeKX3vnAMRgO08NqdmG2x1Y69LQ4P5|1||1|1|1760574336026|............. ++|2626|6|3f|eod9aRWLVl34Gx1Dn7VNWE72rz6qjgmpEXwQJN5Z|1||1|1|1760574337543|............. ++|2740|27|3f|gP1eOZVj3Q9lv5aDEk45Vn7rdpqW8yLm2BbKzJxM|1||1|1|1760573850035|............. ++|2599|23|1f|BaY3Xpy1EbKGjLq2O7maYb7rx8owgQz9P4dDJRmN|1||1|1|1760573833997|............. ++|2601|29|2f|pE5X8NQPaow6vlOZxk6anb0q42ezGBMyWgDVjR3L|1||1|1|1760574370321|............. ++|2614|28|1f|2O14VBzl8aDmWdNw3A598DAGyZ5qLJoEMpj6R9ng|1||1|1|1760574250262|............. ++|3528|12|2f|52dD6ZlV1QaOpRBmbAqG8GkKnGzWMLj4eJq38Pgo|1||1|1|1760573710582|............. ++|3545|13|1f|roKgWqY95V3mXMRzyAjmD37bLjexpJPvaGDBw826|1||1|1|1760574376376|............. ++|2639|57|3f|rDbQ84xzwgdqEoPm3kbEqJ09anOZY1RXyBv2LVM6|1||1|0|1757907649845|............. ++|2580|41|2f|PjLblDgRBO6WQqnxmkJ1nB0Jv3ewZN4p5a89yKdY|1||1|1|1760574237387|............. ++|3975|3|3f|B5EoxeMVp4zwr8nqW0GBEgARjvD1PNamOGbLg63Z|1||1|1|1760574392285|............. ++|4172|8|2f|EjgWGnXaLy9opPOz20n4p3786BlYM3w1deVQvbKr|1||1|1|1760574149977|............. diff --git a/RVO53/databases/nodes_original/nodes_original.table b/RVO53/databases/nodes_original/nodes_original.table new file mode 100755 index 0000000..e0dec9d --- /dev/null +++ b/RVO53/databases/nodes_original/nodes_original.table @@ -0,0 +1 @@ +[{"2569": "roKgWqY95V3mXMRzyAjK5P0bLjexpJPvaGDBw826"}, {"2570": "PLBJzmK1r3Gynd6OW0gKN20e5wV4vx9bDEqNgYR8"}, {"2571": "Nzp2OoJlqn6r1ZgvdA3BXW7abBwP5G4eE3RQmyxD"}, {"2572": "roKgWqY95V3mXMRzyAjKa20bLjexpJPvaGDBw826"}, {"2573": "ZmRwd93QL4gaezxEbAx2vKk1prn2XjlPvGyqJ6BO"}, {"2574": "wvKJdZML6mXP4DzWBAXxE9AjxNloa5g23Ve9Y1ry"}, {"2575": "E6Kg9oDnLWyzPRMva7v53YkJxp4VG58qO2w1lZYe"}, {"2576": "52dD6ZlV1QaOpRBmbAqGxGkKnGzWMLj4eJq38Pgo"}, {"3606": "EjgWGnXaLy9opPOz20n4w3786BlYM3w1deVQvbKr"}, {"2579": "dz4ojlpP85JMgDLZWkQJxg7aKYqQexEr62GXRV1y"}, {"2586": "K94XLav1glVRnyQ6r01P1yAme3YJwBxM5oOzdP2j"}, {"2587": "3a5oqJN1bgnx4Ol9dk89327ByE6jQ8mKDWMpGrLV"}, {"2588": "d9x2V5LGYBzXp4mMRAOmbykPloaqJwnQj6DgrNe3"}, {"2592": "aw4eELG2DlPMdn1JW0BM3OAqQXOZRN3xB5yp8VKr"}, {"2594": "g9OxBZ5KRwNznlY6pAppVGAWXvjdEL4eGQobMDy2"}, {"2595": "eod9aRWLVl34Gx1Dn7VN3E72rz6qjgmpEXwQJN5Z"}, {"2596": "JX1ObgmqGZ54DMyYL7aDmMkEVdve38WKRzwjNrQ9"}, {"2597": "RO8rjaBDy21qPQJzW7omxW0pK3xmNleVZg9Ed4Gw"}, {"2603": "RvmwNz8QPblKp41GD7lKM9kJrLVYoBO92dMegn6W"}, {"2797": "d5xjWYMwEJon6rLlK7yEwP7qgV4DaOeNB9ZX3Gzb"}, {"2577": "gRoJEyXVx4qD9er287L43l7wBzGldaPjLWQKm3Mv"}, {"2581": "Z5KyJe9nEg1QNbWlX0w4b8koDjBLdqzR83VGv624"}, {"2582": "JzwxZXOvDj1bVrN4nkW5gRA8qdyBl3MRKLpGPgaQ"}, {"2583": "1JMYvnx2RzKEo4aWQ7DGBLkL8yZV3m9NBePXbrdj"}, {"2589": "OzNMgZ9n43qPbjXmy7zwmyA2DKdYvW5e6pxGRrVa"}, {"2590": "3JjOWdylwgNLzxVab7NaqbkZ2vG64rq8PEB5QmDo"}, {"2591": "B5EoxeMVp4zwr8nqW0GBxgARjvD1PNamOGbLg63Z"}, {"2615": "nJL5lPMwBx23YpqRe0rpne7damXvWVbOrD4gNzy8"}, {"3634": "XMBbew5z4ELrZa2mRAd3rq78vPN6gy3DdVYlpKjq"}, {"2869": "3a5oqJN1bgnx4Ol9dk89827ByE6jQ8mKDWMpGrLV"}, {"2593": "apKVJBwOyrP35m2lv7KYX60YXbeWNd64En9GxRqg"}, {"2605": "DbQY6zyveZRwK5drV0Z8vr7joE4XJM83N9xl2nWq"}, {"3074": "o9vbeQlLMVg8j5dq4keLBD0NxZpEmnXzwYKO1ar2"}, {"2609": "zdQO8GwxDqjRgP4137YVbbANyKlpem2nL65rvVJY"}, {"2610": "zrR51V2ajQ9ZLygPKkEMbKkYDq38xOJolENBXGnv"}, {"2602": "5dBNwRp9graYJxZn409NgqklVov1b2QLPDqGm6XK"}, {"2620": "E6Kg9oDnLWyzPRMva7v5qYkJxp4VG58qO2w1lZYe"}, {"2622": "aw4eELG2DlPMdn1JW0BMmOAqQXOZRN3xB5yp8VKr"}, {"4196": "6lQGaY9RDywdVzObj0PavXkPg4NBn3exEK51LWZq"}, {"3619": "m6EYyZoJ4gWexdjVPAR5V37RDOq9wv2N5XzKGplr"}, {"2611": "Nzp2OoJlqn6r1ZgvdA3BxW7abBwP5G4eE3RQmyxD"}, {"2608": "wvKJdZML6mXP4DzWBAXxq9AjxNloa5g23Ve9Y1ry"}, {"2612": "roKgWqY95V3mXMRzyAjKD20bLjexpJPvaGDBw826"}, {"2618": "ZmRwd93QL4gaezxEbAx2aKk1prn2XjlPvGyqJ6BO"}, {"2619": "K94XLav1glVRnyQ6r01PYyAme3YJwBxM5oOzdP2j"}, {"2623": "d9x2V5LGYBzXp4mMRAOmqykPloaqJwnQj6DgrNe3"}, {"2598": "PLBJzmK1r3Gynd6OW0gKY20e5wV4vx9bDEqNgYR8"}, {"2624": "gYbDLqlyZVoRerQpB72MzekWJnwM5z24POKa8Exj"}, {"2625": "WlVJBygjDZMeKX3vnAMRgO08NqdmG2x1Y69LQ4P5"}, {"2626": "eod9aRWLVl34Gx1Dn7VNWE72rz6qjgmpEXwQJN5Z"}, {"2740": "gP1eOZVj3Q9lv5aDEk45Vn7rdpqW8yLm2BbKzJxM"}, {"2599": "BaY3Xpy1EbKGjLq2O7maYb7rx8owgQz9P4dDJRmN"}, {"2601": "pE5X8NQPaow6vlOZxk6anb0q42ezGBMyWgDVjR3L"}, {"2614": "2O14VBzl8aDmWdNw3A598DAGyZ5qLJoEMpj6R9ng"}, {"3528": "52dD6ZlV1QaOpRBmbAqG8GkKnGzWMLj4eJq38Pgo"}, {"3545": "roKgWqY95V3mXMRzyAjmD37bLjexpJPvaGDBw826"}, {"2881": "rDbQ84xzwgdqEoPm3kbEqJ09anOZY1RXyBv2LVM6"}, {"2580": "PjLblDgRBO6WQqnxmkJ1nB0Jv3ewZN4p5a89yKdY"}, {"3975": "B5EoxeMVp4zwr8nqW0GBEgARjvD1PNamOGbLg63Z"}, {"4172": "EjgWGnXaLy9opPOz20n4p3786BlYM3w1deVQvbKr"}] \ No newline at end of file diff --git a/RVO53/databases/notifications.table b/RVO53/databases/notifications.table new file mode 100755 index 0000000..f7c96cb --- /dev/null +++ b/RVO53/databases/notifications.table @@ -0,0 +1,41 @@ +key:string|weight:string|sk:string|en:string ++|switching_profile_point_applied_to_line|INFORMATIONAL|Aplikovaný bod spínacieho profilu na línií č. ${line} : ${value}|Switching profile point applied to line no. ${line} : ${value}|............... ++|dusk_has_occured|INFORMATIONAL|Nastal súmrak: ${value}|Dusk has occured: ${value}|............... ++|dawn_has_occured|INFORMATIONAL|Nastal úsvit: ${value}|Dawn has occured: ${value}|............... ++|dimming_profile_was_successfully_received_by_node|NOTICE|Stmievací profil bol úspešne prijatý nodom č. ${node}|Dimming profile was successfully received by node no. ${node}|............... ++|master_node_is_responding_again|NOTICE|Master node začal znovu odpovedať|Master node is responding again|............... ++|command_was_sent_from_terminal_interface|DEBUG|Z terminálu bol odoslaný príkaz|A command was sent from terminal interface|............... ++|master_node_is_not_responding|ALERT|Master node neodpovedá|Master node is not responding|............... ++|configuration_of_dimming_profile_to_node_failed|ALERT|Konfigurácia stmievacieho profilu pre node č. ${node} zlyhala|Configuration of dimming profile to node no. ${node} has failed|............... ++|circuit_breaker_was_turned_on_line|NOTICE|Zapnutie ističa na línii č. ${line}|Circuit breaker was turned on - line no. ${line}|............... ++|circuit_breaker_was_turned_off_line|ERROR|Vypnutie ističa na línií č. ${line}|Circuit breaker was turned off - line no. ${line}|............... ++|dimming_profile_was_processed_for_node|INFORMATIONAL|Stmievací profil bol spracovaný pre node č. ${node}|Dimming profile was processed for node no. ${node}|............... ++|switching_profile_was_processed_for_line|INFORMATIONAL|Spínací profil bol spracovaný pre líniu č. ${line}|Switching profile was processed for line no. ${line}|............... ++|thermometer_is_not_responding|WARNING|Teplomer neodpovedá|Thermometer is not responding|............... ++|thermometer_is_responding_again|NOTICE|Teplomer znovu odpovedá|Thermometer is responding again|............... ++|thermometer_sends_invalid_data|WARNING|Teplomer posiela neplatné hodnoty|Thermometer sends invalid data|............... ++|main_switch_has_been_turned_off|CRITICAL|Hlavný vypínač bol vypnutý|Main switch has been turned off|............... ++|main_switch_has_been_turned_on|NOTICE|Hlavný vypínač bol zapnutý|Main switch has been turned on|............... ++|power_supply_has_disconnected_input|ALERT|Napájací zdroj nemá napätie na vstupe|Power supply has disconnected input|............... ++|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_main_open|NOTICE|Hlavné dvere boli otvorené|Main door has been opened|............... ++|door_em_open|NOTICE|Dvere silovej časti boli otvorené|Power door has been opened|............... ++|door_main_open_without_permission|WARNING|Hlavné dvere boli otvorené bez povolenia - zapnutá siréna|Main door has been opened without permission - alarm is on|............... ++|door_em_open_without_permission|WARNING|Dvere silovej časti boli otvorené bez povolenia|Power door has been opened without permission|............... ++|door_main_close|NOTICE|Hlavné dvere boli zatvorené|Main door has been closed|............... ++|door_em_close|NOTICE|Dvere silovej časti boli zatvorené|Power door has been closed|............... ++|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|............... ++|electrometer_ok|NOTICE|Elektromer znovu odpovedá|Electrometer is responding again|............... ++|no_voltage_on_phase|CRITICAL|Na fáze č. ${phase} nie je napätie|No voltage detected on phase no. ${phase}|............... ++|voltage_on_phase_restored|NOTICE|Napätie na fáze č. ${phase} bolo obnovené|Voltage on phase no. ${phase} has been restored|............... ++|flow_start|NOTICE|FLOW bol spustený|FLOW has been started |............... ++|twilight_sensor_nok|ERROR|Sensor súmraku neodpovedá|Twilight sensor is not responding|............... ++|twilight_sensor_ok|NOTICE|Sensor súmraku znovu odpovedá|Twilight sensor is responding again|............... ++|lamps_have_turned_on|NOTICE|Lampy sa zapli|Lamps have turned on|............... ++|lamps_have_turned_off|NOTICE|Lampy sa vypli|Lamps have turned off|............... ++|flow_restart|NOTICE|FLOW bol reštartovaný|FLOW has been restarted|............... ++|nodes_db_changed|NOTICE|Zmena v node databáze|Node db has changed|............... diff --git a/RVO53/databases/pins.table b/RVO53/databases/pins.table new file mode 100755 index 0000000..6190f9c --- /dev/null +++ b/RVO53/databases/pins.table @@ -0,0 +1,14 @@ +pin:string|type:string|line:number +*|input1_01|door_condition|0|........... +*|input1_02|rotary_switch_state|0|........... +*|input1_03|rotary_switch_state|0|........... +*|input1_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|........... +*|28A6A2660E00002D|temperature|0|........... +*|twilight_sensor|twilight_sensor|0|........... diff --git a/RVO53/databases/relays.table b/RVO53/databases/relays.table new file mode 100755 index 0000000..27eb584 --- /dev/null +++ b/RVO53/databases/relays.table @@ -0,0 +1,5 @@ +line:number|tbname:string|contactor:number|profile:string ++|0|d5xjWYMwEJon6rLlK7yEaP7qgV4DaOeNB9ZX3Gzb|1||........... ++|3|nJL5lPMwBx23YpqRe0rp597damXvWVbOrD4gNzy8|9|{"intervals":[{"value":0,"end_time":"20:00","start_time":"13:00"},{"value":0,"end_time":"13:00","start_time":"08:00"},{"value":1,"end_time":"08:00","start_time":"20: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}|................................................................................................................................................................................................................................................................................................................................... ++|1|gRoJEyXVx4qD9er287L4Xl7wBzGldaPjLWQKm3Mv|9|{"intervals":[{"value":0,"end_time":"20:00","start_time":"13:00"},{"value":0,"end_time":"13:00","start_time":"08:00"},{"value":1,"end_time":"08:00","start_time":"20: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|roKgWqY95V3mXMRzyAjK5o0bLjexpJPvaGDBw826|9|{"intervals":[{"value":0,"end_time":"20:00","start_time":"13:00"},{"value":0,"end_time":"13:00","start_time":"08:00"},{"value":1,"end_time":"08:00","start_time":"20: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/RVO53/databases/settings.table b/RVO53/databases/settings.table new file mode 100755 index 0000000..44cf15a --- /dev/null +++ b/RVO53/databases/settings.table @@ -0,0 +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|project_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|cloud_topic:string|has_main_switch:boolean|daily_report:boolean|send_changed_node_numbers:boolean ++|rvo_senica_53_ip107|en|28.A6A2660E0000|48.70826502|17.28455203|192.168.252.1|rvo_senica_53_ip107|mcynFvfnb0ZRMMUNSauR|1883|0|46|unipi|ttyUSB0|1|20|5|6|3|u107|0|1|1|................................................... diff --git a/RVO53/databases/tbdata.nosql b/RVO53/databases/tbdata.nosql new file mode 100755 index 0000000..e69de29 diff --git a/RVO53/databases/tbdatacloud.nosql b/RVO53/databases/tbdatacloud.nosql new file mode 100755 index 0000000..e69de29 diff --git a/RVO53/databases/total_energy.js b/RVO53/databases/total_energy.js new file mode 100755 index 0000000..dde340e --- /dev/null +++ b/RVO53/databases/total_energy.js @@ -0,0 +1,38 @@ +//key is rvo_number, value is max energy when lamps are on +const total_energy = { + 1: 580, + 2: 1100, + 3: 3700, + 4: 4100, + 7: 360, + 12: 1700, + 13: 5400, + 14: 440, + 15: 6100, + 16: 4800, + 20: 1600, + 21: 1000, + 22: 2600, + 23: 1000, + 25: 2600, + 33: 240, + 34: 4000, + 35: 2700, + 36: 820, + 37: 1400, + 35: 3500, + 39: 1170, + 41: 740, + 42: 660, + 43: 4900, + 45: 930, + 46: 700, + 47: 1100, + 48: 1500, + 50: 3200, + 53: 1250, + 55: 1000, + 56: 5500 +} + +module.exports = total_energy; diff --git a/RVO53/debug.js b/RVO53/debug.js new file mode 100755 index 0000000..9818194 --- /dev/null +++ b/RVO53/debug.js @@ -0,0 +1,16 @@ +// =================================================== +// FOR DEVELOPMENT +// Total.js - framework for Node.js platform +// https://www.totaljs.com +// =================================================== + +const options = {}; + +// options.ip = '127.0.0.1'; +// options.port = parseInt(process.argv[2]); +// options.config = { name: 'Total.js' }; +// options.sleep = 3000; +// options.inspector = 9229; +// options.watch = ['private']; + +require('total.js/debug')(options); \ No newline at end of file diff --git a/RVO53/err.txt b/RVO53/err.txt new file mode 100755 index 0000000..955695f --- /dev/null +++ b/RVO53/err.txt @@ -0,0 +1,70 @@ +[2024-10-26T03:26:04.579] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T04:26:16.815] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T05:26:29.040] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T06:26:41.196] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T07:29:23.935] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T08:29:36.061] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T09:29:48.208] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T10:35:01.356] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T11:35:13.482] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T12:37:56.121] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T13:38:08.220] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T14:38:20.308] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T15:38:32.465] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T16:46:16.105] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T17:46:28.235] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T18:46:40.462] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T19:46:52.584] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T20:47:04.814] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T21:49:47.630] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T22:49:59.925] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-26T23:50:12.240] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T00:50:24.478] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T01:50:36.711] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T02:53:19.444] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T02:56:02.119] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T03:58:45.773] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T04:58:57.984] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T06:01:40.857] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T07:01:53.193] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T08:02:05.325] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T09:02:17.443] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T10:05:00.064] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T11:05:12.189] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T12:07:54.799] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T13:08:06.905] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T14:08:19.054] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2024-10-27T15:13:32.179] [ERROR] errLogs - checkFinalRVOStatus: temperature status is NOK +[2025-09-23T13:59:53.425] [ERROR] errLogs - uncaughtException: Cannot read property 'getHours' of undefined +[2025-09-23T13:59:53.426] [ERROR] errLogs - TypeError: Cannot read property 'getHours' of undefined + at Timeout.emptyReportToSend [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T13:59:53.427] [ERROR] errLogs - uncaughtException: Cannot read property 'getHours' of undefined +[2025-09-23T13:59:53.428] [ERROR] errLogs - TypeError: Cannot read property 'getHours' of undefined + at Timeout.emptyReportToSend [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T13:59:53.437] [ERROR] errLogs - uncaughtException: Cannot read property 'getHours' of undefined +[2025-09-23T13:59:53.438] [ERROR] errLogs - TypeError: Cannot read property 'getHours' of undefined + at Timeout.emptyReportToSend [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T13:59:59.201] [ERROR] errLogs - uncaughtException: date.getHours is not a function +[2025-09-23T13:59:59.202] [ERROR] errLogs - TypeError: date.getHours is not a function + at emptyReportToSend (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at Timeout.dailyReportCheck [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1351:5) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T13:59:59.203] [ERROR] errLogs - uncaughtException: date.getHours is not a function +[2025-09-23T13:59:59.203] [ERROR] errLogs - TypeError: date.getHours is not a function + at emptyReportToSend (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at Timeout.dailyReportCheck [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1351:5) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) +[2025-09-23T13:59:59.208] [ERROR] errLogs - uncaughtException: date.getHours is not a function +[2025-09-23T13:59:59.209] [ERROR] errLogs - TypeError: date.getHours is not a function + at emptyReportToSend (/home/unipi/flowserver/flow/cmd_manager.js:1419:14) + at Timeout.dailyReportCheck [as _onTimeout] (/home/unipi/flowserver/flow/cmd_manager.js:1351:5) + at listOnTimeout (internal/timers.js:557:17) + at processTimers (internal/timers.js:500:7) diff --git a/RVO53/flow/cloudmqttconnect.js b/RVO53/flow/cloudmqttconnect.js new file mode 100755 index 0000000..b03491f --- /dev/null +++ b/RVO53/flow/cloudmqttconnect.js @@ -0,0 +1,357 @@ +exports.id = 'cloudmqttconnect'; +exports.title = 'Cloud connect mqtt'; +exports.group = 'MQTT'; +exports.color = '#888600'; +exports.version = '1.0.2'; +exports.icon = 'sign-out'; +exports.input = 2; +exports.output = 2; +exports.options = { host: 'tb-stage.worksys.io', port: 1883, clientid: "", username: "" }; + +exports.html = `
+
+
+
Hostname or IP address (if not empty - setting will override db setting)
+
+
+
Port
+
+
+
+
+
@(Client id)
+
+
+
topic
+
+
+
`; + + + +const { promisifyBuilder } = require('./helper/db_helper'); +const fs = require('fs'); +const mqtt = require('mqtt'); +const nosql = NOSQL('tbdatacloud'); + +const SEND_TO = { + debug: 0, + rpcCall: 1, +} + +//CONFIG +let saveTelemetryOnError = true;//backup_on_failure overrides this value +//------------------------ + +const noSqlFileSizeLimit = 4194304;//use 5MB - 4194304 +let insertNoSqlCounter = 0; +let insertBackupNoSqlCounter = 0; +let processingData = false; + +let backup_on_failure = true;//== saveTelemetryOnError - create backup client send failure +let restore_from_backup = 50; //how many rows process at once? +let restore_backup_wait = 3;//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; + + +exports.install = function(instance) { + + var client; + var opts; + var clientReady = false; + + let o = {}; //options + + function main() { + loadSettings(); + } + + //set opts according to db settings + function loadSettings() { + + o = instance.options; + if (!o.topic) o.topic = FLOW.GLOBALS.settings.cloud_topic; + + opts = { + host: o.host, + port: o.port, + clientId: o.clientid, + username: o.username, + rejectUnauthorized: false, + resubscribe: false + }; + + console.log("wsmqttpublich -> loadSettings from instance.options", o); + + if (!o.topic) { + instance.status("Not configured", "white"); + console.log("Cloud mqtt connect: no topic selected"); + return; + } + + connectToTbServer(); + } + + function connectToTbServer() { + var url = "mqtt://" + opts.host + ":" + opts.port; + console.log("MQTT URL: ", url); + + client = mqtt.connect(url, opts); + + client.on('connect', function() { + client.subscribe(`${o.topic}_backward`, (err) => { + if (!err) { + console.log("MQTT subscribed"); + } + }); + instance.status("Connected", "green"); + clientReady = true; + sendClientError = true; + }); + + client.on('reconnect', function() { + instance.status("Reconnecting", "yellow"); + clientReady = false; + }); + + client.on('message', function(topic, message) { + // message is type of buffer + message = message.toString(); + if (message[0] === '{') { + TRY(function() { + + message = JSON.parse(message); + if (message.hasOwnProperty("device") && message.hasOwnProperty("data") && message.data.hasOwnProperty("id")) { + client.publish(`${o.topic}_forward`, `{"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 } }); + } + + }, () => instance.debug('MQTT: Error parsing data', message)); + } + + instance.send(SEND_TO.rpcCall, { "topic": o.topic, "content": message }); + }); + + client.on('close', function() { + clientReady = false; + + instance.status("Disconnected", "red"); + instance.send(SEND_TO.debug, { "message": "Client CLOSE signal received !" }); + }); + + client.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) { + console.log('MQTT client error', err); + sendClientError = false; + } + clientReady = false; + }); + + } + + + instance.on('0', function(data) { + + if (clientReady) { + //do we have some data in backup file? if any, process data from database + if (saveTelemetryOnError) { + //read telemetry data and send back to server + if (!processingData) processDataFromDatabase(); + } + + let stringifiedJson = JSON.stringify(data.data) + client.publish(`${o.topic}_forward`, stringifiedJson, { qos: 1 }); + } + 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 (saveTelemetryOnError && o.topic) { + //create new file from tbdata.nosql, if file size exceeds given limit, and clear tbdata.nosql + makeBackupFromDbFile(); + + //write to tb + data.data.id = UID(); + nosql.insert(data.data); + } + } + }); + + instance.on("1", _ => { + main(); + }) + + instance.close = function(done) { + if (clientReady) { + client.end(); + } + }; + + + function getDbBackupFileCounter(type) { + var files = fs.readdirSync(__dirname + "/../databases"); + + let counter = 0; + for (var i = 0; i < files.length; i++) { + + if (files[i] == "tbdatacloud.nosql") continue; + + if (files[i].endsWith(".nosql")) { + + let pos = files[i].indexOf("."); + if (pos > -1) { + + let fileCounter = counter; + let firstDigit = files[i].slice(0, pos); + + fileCounter = parseInt(firstDigit); + if (isNaN(fileCounter)) fileCounter = 0; + //console.log("getDbBackupFileCounter digit:", files[i], firstDigit, fileCounter, isNaN(fileCounter), type); + + if (type == "max") { + if (fileCounter > counter) { + counter = fileCounter; + } + } + else if (type == "min") { + if (counter == 0) counter = fileCounter; + + if (fileCounter < counter) { + counter = fileCounter; + } + } + } + } + + } + + if (type == "max") counter++; + + return counter; + } + + const makeBackupFromDbFile = async () => { + + if (!saveTelemetryOnError) return; + + //to avoid large file: tbdata.nosql + + //init value is 0! + if (insertNoSqlCounter > 0) { + --insertNoSqlCounter; + return; + } + + insertNoSqlCounter = 100; + + let source = __dirname + "/../databases/tbdatacloud.nosql"; + + var stats = fs.statSync(source); + var fileSizeInBytes = stats.size; + + if (fileSizeInBytes > noSqlFileSizeLimit) { + + let counter = 1; + counter = getDbBackupFileCounter("max"); + + let destination = __dirname + "/../databases/" + counter + "." + "tbdatacloud.nosql"; + + //make backup file + fs.copyFileSync(source, destination); + //fs.renameSync(p, p + "." + counter); + + //clear tbdata.nosql + fs.writeFileSync(source, ""); + fs.truncateSync(source, 0); + + } + } + + const processDataFromDatabase = async () => { + + if (restore_from_backup <= 0) return; + + //calculate diff + const now = new Date(); + let currentTime = now.getTime(); + let diff = currentTime - lastRestoreTime; + + if ((diff / 1000) < restore_backup_wait) { + //console.log("*********restore_backup_wait", diff, restore_backup_wait); + return; + } + + processingData = true; + + //get filename to process + let counter = getDbBackupFileCounter("min"); + + //we have some backup files + let dataBase = 'tbdata'; + + var nosql; + if (counter == 0) dataBase = 'tbdatacloud'; + else dataBase = counter + "." + 'tbdatacloud'; + + nosql = NOSQL(dataBase); + + //select all data - use limit restore_from_backup + let records = await promisifyBuilder(nosql.find().take(restore_from_backup)); + + for (let i = 0; i < records.length; i++) { + if (clientReady) { + + let item = records[i]; + let id = item.id; + + if (id !== undefined) { + //console.log("------------processDataFromDatabase - remove", id, dataBase, i); + + try { + + let message = JSON.parse(JSON.stringify(item)); + delete message.id; + client.publish(`${o.topic}_forward`, JSON.stringify(message), { qos: 1 }); + + //remove from database + await promisifyBuilder(nosql.remove().where("id", id)); + + } catch (error) { + //process error + console.log("processDataFromDatabase", error); + } + + } + + } + else { + processingData = false; + return; + } + } + + if (records.length > 0) { + //clean backup file + if (counter > 0) nosql.clean(); + } + + //no data in db, remove + if (records.length == 0) { + if (counter > 0) nosql.drop(); + } + + const d = new Date(); + lastRestoreTime = d.getTime(); + + processingData = false; + + } + + instance.on('options', main); + +}; diff --git a/RVO53/flow/cmd_manager.js b/RVO53/flow/cmd_manager.js new file mode 100755 index 0000000..25912df --- /dev/null +++ b/RVO53/flow/cmd_manager.js @@ -0,0 +1,3071 @@ +exports.id = 'cmd_manager'; +exports.title = 'CMD Manager'; +exports.group = 'Worksys'; +exports.color = '#5D9CEC'; +exports.version = '0.0.3'; +exports.output = ['red', 'blue', 'yellow', 'blue', 'white', 'green']; +exports.input = 3; +exports.icon = 'cloud-upload'; + +exports.html = ` +
+
+
+
RPC - run RPC calls

+
+
+
@(User)
+
+
+
@(Password)
+
+
+
@(My edge)
+
+
+
+`; +exports.readme = `Manager for CMD calls`; + + +exports.install = function(instance) { + + 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, isEmptyObject, emptyJsObject, writeToFile, addToArrayIfUnique } = require('./helper/utils'); + const bitwise = require('bitwise'); + + var SunCalc = require('./helper/suncalc'); + const DataToTbHandler = require('./helper/DataToTbHandler'); + const errorHandler = require('./helper/ErrorToServiceHandler'); + const { sendNotification } = require('./helper/notification_reporter'); + const process = require('process'); + const { errLogger, logger, monitor } = require('./helper/logger'); + + //for accelerometer purposes + const { naklony } = require("../databases/accelerometer_db"); + + const dbNodes = TABLE("nodes"); + const dbRelays = TABLE("relays"); + + let GLOBALS; + let SETTINGS; + let rsPort; + let tbHandler; + + // runTasks intervals + const SHORT_INTERVAL = 30; + const LONG_INTERVAL = 300; + + //send data to following instances: + const SEND_TO = { + debug: 0, + tb: 1, + http_response: 2, + dido_controller: 3, + infoSender: 4, + dailyReport: 5 + } + + 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 + } + + 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 sendNodeReadout = null; // interval for sending agregate data from node + + 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["1"] = minutes; // dimming + priorities["76"] = minutes; // power + + minutes = 5; + priorities["75"] = minutes; // current + priorities["79"] = minutes; // energy + priorities["87"] = minutes; // aktualny cas + //priorities["84"] = minutes; //accelerometer + + minutes = 10; + priorities["74"] = minutes; // voltage + priorities["77"] = minutes; // power factor + priorities["78"] = minutes; // frequency + + minutes = 60; + priorities["0"] = minutes; // statecode + priorities["6"] = minutes; // dusk + priorities["7"] = minutes; // dawn + priorities["8"] = minutes; // profile + + minutes = 60 * 24; + priorities["89"] = minutes; // verzia fw + priorities["80"] = minutes; // lifetime + + //prikazy kt sa budu spustat na dany node - see config.js in terminal-oms.app. (1 - dimming) + let listOfCommands = [0, 1, 6, 7, 8, 74, 75, 76, 77, 78, 79, 80, 87, 89]; + + 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; + + // holds dusk, dawn (and more) values + let sunCalcResult; + + //helper container for counting resolved group of commands (commands related to set profile) + let cmdCounter = {};//key is node, value is counter + + //TODO: is this set working?? According to previous checks, sets do not work + //if sending of profile to node fails, we send notification and push node into set, so we do not send notification twice + const nodeProfileSendFail = new Set(); + + //we expect to get current temperature in Senica from senica-prod01 + let temperatureInSenica = null; + let accelerometerInterval = null; + + //NOTE: daily reports senica: + //rvo_is_on status, we monitor all nodes - if true, power and dimming should be not 0, if false, 24/7 nodes should be 0, other rvo should not respond + let rvo_is_on; + let previous_rvo_is_on_value; + let handleDailyReport; //setInterval for dailyReportHandler function + let dailyReport = {}; //data needed for daily report + let reportToSend = {}; //final report which we send to cloud + let breakerCounter = null; // status of breakers after flow starts is not in report + let rvoPeriod; // interval of checking dusk dawn and if rvo_is_on + let initialReportStatus = false; + + const DAILY_REPORT_HANDLER_TIME = 3_600_000; + const SET_SUNCALC_RESULT_TIME = 3_600_000; + const SET_RVO_PERIOD_TIME = 300_000; + const ADD_NODE_TO_REPORT_TIME = 3_600_000; + + //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); + + let now = new Date(); + console.log("Cmd-mngr installed", now.toLocaleString("sk-SK")); + + sunCalcResult = calculateDuskDawn(); + + handleRsPort(); + + customTasksInterval = setInterval(reportEdgeDateTimeAndNumberOfLuminaires, 120_000); + setTimeout(reportEdgeDateTimeAndNumberOfLuminaires, 4000); + + //dailyReport related + emptyReportToSend(); + breakerCounter = Object.keys(relaysData).length - 1; // we get number of lines (breakers) except of line 0 + rvoPeriod = setInterval(setRvoPeriod, SET_RVO_PERIOD_TIME); + setTimeout(setRvoPeriod, 3000); + setInterval(setSunCalcResult, SET_SUNCALC_RESULT_TIME); + handleDailyReport = setInterval(dailyReportHandler, DAILY_REPORT_HANDLER_TIME); + + + setCorrectTime = setInterval(setCorrectPlcTimeOnceADay, 60000 * 60); // 1 hour + setCorrectPlcTimeOnceADay(); + + sendNodeReadout = setInterval(sendNodesData, 150_000); + accelerometerInterval = setInterval(accelerometerData, 60000 * 30); //30 min + } + + + 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" + //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 + // if node regular readout does not respond, we repeat request + params.repeatCounter = 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-mngr: 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.byte4 = 96; + params.recipient = 1; + params.register = 8; + params.rw = 1;//write + params.timestamp = timestamp; + 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.byte4 = 96; + params.recipient = 1; + params.register = 8; + params.rw = 1;//write + params.timestamp = timestamp; + 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). + */ + + 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.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.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 + { + + logger.debug("processNodeProfile: Threshold lux level for DUSK/DAWN", node); + + let params = getParams(); + params.type = "set_node_profile"; + params.address = node; + params.register = 96; + params.recipient = 1; + params.rw = 1;//write + params.timestamp = timestamp; + 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(); + params.type = "set_node_profile"; + params.address = node; + params.register = 97; + params.recipient = 1; + params.rw = 1;//write + params.timestamp = timestamp; + 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.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); + + 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); + + console.log("proces profile finished *********************") + } + + + 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; + }); + } + + + 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) { + for (let k in nodesData) { + 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`); + } + } + } + + + function loadRelaysData(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 (value.contactor == 1) processAllNodeProfilesOnLine(value.line); + } + } + + + function reportOnlineNodeStatus(line) { + //Po zapnutí línie broadcastovo aktualizovať predtým čas a o 3 sek neskor - status, brightness + + logger.debug("Cmd-mngr: ----->reportOnlineNodeStatus for line", line); + + const d = new Date(); + + // broadcast actual time + let params = getParams(); + params.address = 0xffffffff;//Broadcast + params.byte1 = d.getHours(); + params.byte2 = d.getMinutes(); + params.recipient = 2;//2 broadcast, address = 0 + params.register = 87;//Actual time + params.rw = 1;//write + params.type = "node-onetime-write"; + params.timestamp = d.getTime() + 30000; + params.info = "run broadcast: Actual time"; + //params.debug = true; + + tasks.push(params); + + let sec = 3; + setTimeout(function() { + //Po zapnutí línie - spraviť hromadný refresh stavu práve zapnutých svietidiel + + let time = Date.now(); + + for (let k in nodesData) { + + //potrebujem nody k danej linii + 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].node_status_before_offline === true || nodesData[k].status === true) { + status = "OK"; + nodesData[k].time_of_last_communication = time; + } + + nodesData[k].readout.status = status; + + updateNodeStatus(k, status === "OK" ? true : false); + if (nodesData[k].hasOwnProperty("node_status_before_offline")) delete nodesData[k].node_status_before_offline; + sendTelemetry({ status: status }, tbname, time); + + //vyreportovanie dimming, current, input power pre liniu pre vsetky nody + //Prud + { + let params = getParams(); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 75;//prud + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = time + 4000; + params.info = 'read current'; + //params.debug = true; + tasks.push(params); + } + + //vykon + { + let params = getParams(); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 76;//výkon + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = time + 4100; + params.info = 'read power'; + //params.debug = true; + + tasks.push(params); + } + //dimming + { + let params = getParams(); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 1;//dimming + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = time + 4200; + params.info = 'read dimming'; + //params.debug = true; + + tasks.push(params); + } + + } + } + + }, sec * 1000); + } + + + function reportOfflineNodeStatus(line) { + + logger.info("Cmd-mngr: ------>reportOffLineNodeStatus for line ", line); + + values = {}; + values["dimming"] = 0;//brightness + values["power"] = 0;//výkon + values["current"] = 0;//prúd + values["status"] = "OFFLINE"; + + const date = Date.now(); + + Object.keys(nodesData).forEach(node => { + + //potrebujem nody k danej linii + if (line == nodesData[node].line || line == undefined) { + + let tbname = nodesData[node].tbname; + let nodeStatus = nodesData[node].status; + + //in case we have reported offline node status, we return (continue with next node) + if (nodeStatus === "OFFLINE") return; + + nodesData[node].node_status_before_offline = nodeStatus; + nodesData[node].status = "OFFLINE"; + nodesData[node].readout = {}; + + sendTelemetry({ ...values }, tbname, date); + } + }); + + } + + + function turnLine(onOrOff, line, info) { + let obj = { + line: line, + command: onOrOff, + info: info + }; + + //to assure, handleDailyReportFunction do not run before rvo_is_on variable changes. So after every line switch we reset the timer + clearInterval(handleDailyReport); + handleDailyReport = setInterval(dailyReportHandler, DAILY_REPORT_HANDLER_TIME); + + //logger.debug("linia", line, obj); + instance.send(SEND_TO.dido_controller, obj); + } + + + 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"; + 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]) { + //CRC_ERROR + message = "NOK"; + error = "CRC_ERROR c1"; + instance.send(SEND_TO.debug, "CRC_ERROR c1"); + } + + 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") { + instance.send(SEND_TO.debug, bytes); + instance.send(SEND_TO.debug, "RESPONSE " + type + " - " + bytes[4]); + + //logger.debug(SEND_TO.debug, "RESPONSE " + type + " - " + bytes[4], bytes); + + error = "type is: " + type; + + message = "NOK"; + } + + return { message, type, error }; + } + + + //BUILD TASKS// + function buildTasks(params) { + + //return; + console.log("buidTAaasks start ****************", params); + monitor.info("buildTasks - params", params); + + let processLine; //defined line + let init = false; + let processLineProfiles = true; + let processBroadcast = true; + let processNodes = true; + + if (params == undefined) { + init = true; + tasks = []; + logger.debug("-->buildTasks clear tasks"); + } + else { + processLineProfiles = params.processLineProfiles; + processBroadcast = false; + processNodes = false; + + processLine = params.line; + } + + let now = new Date(); + + //process line profiles + if (processLineProfiles) { + + let keys = Object.keys(relaysData); + + for (let i = 0; i < keys.length; i++) { + + let line = parseInt(keys[i]); + let profilestr = relaysData[line].profile; + + if (processLine != undefined) { + if (processLine != line) continue; + } + + try { + + /** + * we process line profiles: timepoints, astro clock, lux_sensor, offsets ... + */ + if (profilestr === "") throw ("Profile is not defined"); + let profile = JSON.parse(profilestr); + 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; + + // add name to regular profile timepoint and delete unused end_time key: + time_points.forEach(point => { + point.name = "profileTimepoint" + delete point.end_time; + }); + + //monitor.info("buildTasks: time_points", time_points); + + + /** + * 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 astro clock true, we remove all regular profile points + time_points = []; + + //TODO: when astro clock == true, is offset calculated ??? + //let duskAstroClockOffset = profile.dusk_astro_clock_offset; + //let dawnAstroClockOffset = profile.dawn_astro_clock_offset; + //console.log("line astro clock offsets dusk a dawn: ", duskAstroClockOffset, dawnAstroClockOffset); + // maybe add dusk dawn offset to calculateDuskDawn ?? what dusk dawn will be if dawn_lux_sensor == true?? + //let sunCalcResult = calculateDuskDawn(new Date(), line, duskAstroClockOffset, dawnAstroClockOffset); + + 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 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); + + 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); + + 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(':'); + + let ad = new Date(); + ad.setHours(parseInt(ahours), parseInt(aminutes), 0); + + let bd = new Date(); + bd.setHours(parseInt(bhours), parseInt(bminutes), 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++) { + + let start_time = new Date(); + let [hours, minutes] = time_points[t].start_time.split(':'); + start_time.setHours(parseInt(hours), parseInt(minutes), 0); + + //task is in 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(); + params.type = "relay"; + params.line = parseInt(line); + params.value = time_points[t].value; + params.tbname = relaysData[line].tbname; + params.timestamp = start_time.getTime(); + + // 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; + + //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)) { + 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; + + params.debug = true; + + //turn on/off line + tasks.push(params); + monitor.info("TimePoint params: ", params.info, start_time); + } + + monitor.info("-->time_points final", line, time_points); + + //ensure to turn on/off according to calculated currentValue + let params = getParams(); + params.type = "relay"; + params.line = parseInt(line); + params.tbname = relaysData[line].tbname; + params.value = currentValue; + params.timestamp = i; + params.debug = true; + + //logger.debug(now.toLocaleString("sk-SK")); + 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; + + tasks.push(params); + + } catch (error) { + if (profilestr !== "") { + //errLogger.error(profilestr, error); + console.log(`Cmd_mngr: Unable to process line profile ${line}. Error: `, error); + errorHandler.sendMessageToService(profilestr + "-" + error, 0, "js_error"); + } else { + turnLine("off", line, "No line profile. Switching it off on startup"); + } + } + + } + //logger.debug("tasks:"); + //logger.debug(tasks); + } + + + //NOTE: PROCESS DEFAULT BROADCASTS - Time of dusk, Time of dawn, Actual Time + if (processBroadcast) { + + let d = new Date(); + let time = d.getTime(); + //let sunCalcResult = calculateDuskDawn(); + + { + let params = getParams(); + + params.address = 0xffffffff;//broadcast + params.byte1 = sunCalcResult["dusk_hours"]; + params.byte2 = sunCalcResult["dusk_minutes"]; + params.recipient = 2;//2 broadcast, + params.register = 6;//Time of dusk + params.rw = 1;//write + params.type = "node-regular-write"; + params.timestamp = time + 60000; + params.addMinutesToTimestamp = 60 * 3; //kazde 3 hodiny zisti novy dusk + params.info = "Broadcast-duskTime"; + + tasks.push(params); + } + + { + let params = getParams(); + + params.address = 0xffffffff;//broadcast + params.byte1 = sunCalcResult["dawn_hours"]; + params.byte2 = sunCalcResult["dawn_minutes"]; + params.recipient = 2; //2 broadcast + params.register = 7;//Time of dawn + params.rw = 1;//write + params.type = "node-regular-write"; + params.timestamp = time + 60001; + params.addMinutesToTimestamp = 60 * 3; //kazde 3 hodiny zisti novy dawn + params.info = "Broadcast-dawnTime"; + + tasks.push(params); + } + + { + let params = getParams(); + + params.address = 0xffffffff;//broadcast + params.byte1 = d.getHours(); + params.byte2 = d.getMinutes(); + params.recipient = 2; //2 broadcast + params.register = 87;//Actual time + params.rw = 1;//write + params.type = "node-regular-write"; + params.timestamp = time + 60002; + params.addMinutesToTimestamp = 5; + params.info = "run broadcast: Actual time"; + + tasks.push(params); + } + + } + + //process nodes & tasks - read node's data + if (processNodes) { + + let time = Date.now(); + + for (let k in nodesData) { + let address = parseInt(k); + let tbname = nodesData[k].tbname; + let register = 0; + + for (let i = 0; i < listOfCommands.length; i++) { + + register = listOfCommands[i]; + let addMinutesToTimestamp = priorities[register]; + + let params = getParams(); + + params.address = address; + params.recipient = 1; + params.register = register; + params.type = register == 1 ? "node-dimming-read" : "node-regular-read"; + params.tbname = tbname; + params.timestamp = time + 5000 + i * 500 + addMinutesToTimestamp * 1000; //to make slight time difference + params.addMinutesToTimestamp = addMinutesToTimestamp; + params.info = "Node regular read command"; + + tasks.push(params); + } + + } + } + + + //niektore ulohy sa vygeneruju iba 1x pri starte!!! + if (!init) return; + + + //Master node FW version - modifies SETTINGS.masterNodeIsResponding + { + let params = getParams(); + params.type = "cmd-master"; + params.register = 4; + params.address = 0; + params.timestamp = 0; + params.addMinutesToTimestamp = 5; + params.tbname = SETTINGS.rvoTbName; + params.info = "Master node FW verzia"; + //params.debug = true; + + tasks.push(params); + } + + //kazdu hodinu skontrolovat nastavenie profilov + { + let params = getParams(); + params.type = "process_profiles"; + params.timestamp = Date.now() + 60001; + params.addMinutesToTimestamp = 60;//60 = every hour + params.info = "detekcia nespracovaných profilov linie a nodov"; + //params.debug = true; + + tasks.push(params); + } + + monitor.info("tasks created:", tasks.length); + } + + + /** + * We process line profile, where "astro_clock": true + * example profile: + * + "dawn_lux_sensor": true, + "dusk_lux_sensor": true, + "dawn_lux_sensor_value": 5, + "dusk_lux_sensor_value": 5, + "dawn_astro_clock_offset": 0, + "dusk_astro_clock_offset": 10, + "dawn_lux_sensor_time_window": 30, + "dusk_lux_sensor_time_window": 30, + "dawn_astro_clock_time_window": 60, + "dusk_astro_clock_time_window": 60 + + * if dawn: if currentTimestamp is in timewindow "dawnTime + and - dawn_lux_sensor_time_window" and lux value >= lux_sensor_value, we switch off the line. + * if dusk: we do oposite + * + * dawn: usvit - lux je nad hranicou - vypnem + * dusk: sumrak - lux je pod hranicou - zapnem + */ + 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++) { + + let line = keys[i]; //line is turned off by default + let profilestr = relaysData[line].profile; + const contactor = relaysData[line].contactor; + + try { + + let profile = JSON.parse(profilestr); + if (Object.keys(profile).length === 0) throw ("turnOnOffLinesAccordingToLuxSensor - profile is not defined"); + + 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 (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"); + } + } + } + + //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 (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"); + } + } + } + + } + + } catch (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) { + //MASTER + if (node == 0) return; + + let nodeObj = nodesData[node]; + if (nodeObj == undefined) return; + + let nodeCurrentStatus = nodeObj.status; + const now = Date.now(); + + let data = null; + + if (nodeCurrentStatus === "OFFLINE") { + data = { status: newStatus }; + nodeDbStatusModify(node, data); + return; + } + else 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; + } + + } + + + 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 }; + } + }); + }); + } + + + function processDailyReport() { + + const now = Date.now(); + + for (const [key, value] of Object.entries(dailyReport)) { + + if (["name", "time", "dusk_and_dawn"].includes(key)) continue; + + let poleNumber = nodesData[key]["pole_number"]; + let line = dailyReport[key].line; + let nodeType = nodesData[key]["node_type"]; + let fullNodeName = key // key == nodeNumber + + if (poleNumber && nodeType) { + fullNodeName = SETTINGS.rvo_number + "/" + poleNumber + "_" + line + "L_" + key + "_" + nodeType; + } else { + fullNodeName = key; + } + + if (rvo_is_on) { + + if (value.initialTs) { + if (value.initialTs + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["night_no_data"], fullNodeName); + console.log('report nedostava ziadne data uz hodinu', fullNodeName); + value.initialTs = now; + } + } + if (value.dimmingIsZeroTime) { + if (value.dimmingIsZeroTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["night_dimming=0"], fullNodeName); + console.log("report node dimming je 0 ale ma svietit", fullNodeName); + value.dimmingIsZeroTime = now; + } + } + if (value.powerIsZeroTime) { + if (value.powerIsZeroTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["night_power=0"], fullNodeName); + console.log("report node power je 0 ale ma svietit", fullNodeName); + value.powerIsZeroTime = now; + } + } + + } else { + + let contactorStatus = relaysData[line].contactor; + if (contactorStatus === 1) { + + if (value.initialTs) { + if (value.initialTs + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["day_24/7_no_data"], fullNodeName); + console.log('node je na 24/7 ale nedostava ziadne data uz hodinu', fullNodeName); + value.initialTs = now; + } + } + if (value.dimmingIsOnButShouldBeOffTime) { + if (value.dimmingIsOnButShouldBeOffTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["day_24/7_dimming>0"], fullNodeName); + console.log("report dimming je > 0 ale nema svietit", fullNodeName); + value.dimmingIsOnButShouldBeOffTime = now; + } + } + if (value.powerIsOnButShouldBeOffTime) { + if (value.powerIsOnButShouldBeOffTime + ADD_NODE_TO_REPORT_TIME < now) { + addToArrayIfUnique(reportToSend["day_24/7_power>0"], fullNodeName); + console.log("report power je > 0 ale nema svietit", fullNodeName); + value.powerIsOnButShouldBeOffTime = now; + } + } + + } + + } + + } + + let report = {}; + report["name"] = SETTINGS.rvo_name; + report["time"] = new Date(); + report["report"] = reportToSend; + + writeToFile(F.path.root("report_data.log"), report, true); + instance.send(SEND_TO.dailyReport, report); + } + + + function dailyReportHandler() { + + if (!SETTINGS.daily_report) return; + + // after dawn we empty reportToSend and start to get data for a new day + const date = new Date(); + const hour = date.getHours(); + const minute = date.getMinutes(); + + console.log("now: ", hour, minute, "suncalc: ", sunCalcResult.dawn_hours, sunCalcResult.dawn_minutes); + + if (hour === sunCalcResult.dawn_hours) { + + //NOTE: ak je este pred usvitom, spracujeme report a posleme na cloud, ak uz je po usvite, resetujeme report plnime data noveho dna + if (minute >= sunCalcResult.dawn_minutes - 2) { + emptyReportToSend(); + emptyDailyReport(); + console.log("Podmienka 1 v dailyReport handler"); + } else { + processDailyReport(); + emptyReportToSend(); + emptyDailyReport(); + console.log("Podmienka 2 v dailyReport handler"); + } + + initialReportStatus = true; + + // ak sa funkcia spusti o hodinu alebo 2 neskor, ako je usvit (moze sa to stat, kedze kazde zapnutie/vypnutie linii odznova spusti casovac. + } else if (hour === sunCalcResult.dawn_hours + 1 || hour === sunCalcResult.dawn_hours + 2) { + if (!initialReportStatus) { + emptyReportToSend(); + emptyDailyReport(); + initialReportStatus = true; + console.log("Podmienka 3 v dailyReport handler"); + } else { + processDailyReport(); + initialReportStatus = true; + console.log("Podmienka 4 v dailyReport handler"); + } + } else { + processDailyReport(); + initialReportStatus = false; + console.log("Podmienka 5 v dailyReport handler"); + } + + console.log("initialReportStatus: ", initialReportStatus); + + } + + function emptyReportToSend() { + emptyJsObject(reportToSend); + reportToSend["contactor"] = { off: [], on: [] }; + reportToSend["night_no_data"] = []; + reportToSend["night_dimming=0"] = []; + reportToSend["night_power=0"] = []; + reportToSend["day_24/7_no_data"] = []; + reportToSend["day_24/7_dimming>0"] = []; + reportToSend["day_24/7_power>0"] = []; + console.log(`resetuje sa reportToSend`); + } + + + //NOTE: ked je initialTs stale rovnaky a zistime ze linie su vypnute (relaysData.line.contactor) - zistim, ci je node na tej linii. Vieme, ze ak je linia vypnuta je to v poriadku lebo nie je na 24/7 linii + //ak je na 24/7 linii, reportujeme, ze neprijima data + function emptyDailyReport() { + const ts = Date.now(); + emptyJsObject(dailyReport); + + //NOTE: do dailyReport dame vsetky nody a pravidelne kontrolujeme ci maju data + //ked nastane sumrak/usvit a svetla maju zacat/prestat svietit, dailyReport spravime nanovo: + for (const [key, value] of Object.entries(nodesData)) { + dailyReport[value.node] = { line: value.line, initialTs: ts }; + } + + console.log("dailyReport: ", dailyReport); + } + + + async function runTasks() { + + clearInterval(interval); + + let currentTimestamp = Date.now(); + + //sort tasks based on timestamp + 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) { + instance.send(SEND_TO.debug, "no tasks created"); + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + if (!rsPort.isOpen) { + instance.send(SEND_TO.debug, "!rsPort.isOpen"); + //await rsPort.open(); + //console.log("Cmd-mngr: !rsPort.isOpen"); + } + + let currentTask = tasks[0]; + + if (currentTask.debug) { + //logger.debug("--->task to process", currentTask); + } + + if (currentTask.timestamp <= currentTimestamp) { + let params = { ...tasks[0] }; + + //allow terminal commands + if (SETTINGS.maintenance_mode && params.type !== "cmd-terminal") { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + let type = params.type; + let tbname = params.tbname; + let node = params.address; + let register = params.register; + let line = null; + let itIsNodeCommand; + + if (nodesData[node] !== undefined) { + line = nodesData[node].line; + itIsNodeCommand = true; + } + + if (params.line !== undefined) line = params.line; + + if (params.addMinutesToTimestamp > 0 || params.timePointName) { + tasks[0].timestamp = currentTimestamp + tasks[0].addMinutesToTimestamp * 60000; + } else { + tasks.shift(); + } + + //kontrola nespracovanych profilov nodov + //TODO: co ked niektore nody neprijimaju profily? kazdu hodinu zahltuju "tasks" array + if (type == "process_profiles") { + //na vsetky zapnutych liniach sa spracuju nespracovane profily nodov + loadRelaysData(); + interval = setInterval(runTasks, SHORT_INTERVAL); + return; + } + + //relay + if (type == "relay") { + + const timePointName = params.timePointName; + const value = params.value; + + let date = new Date(); + date.setDate(date.getDate() + 1);//next day + + let sunCalcResult; + if (timePointName) sunCalcResult = calculateDuskDawn(date, params.line); + + + if (timePointName == "dawn") { + tasks[0].timestamp = sunCalcResult.dawn_time; + } + else if (timePointName == "dusk") { + tasks[0].timestamp = sunCalcResult.dusk_time; + } + else if (timePointName == "luxOn") { + tasks[0].timestamp = sunCalcResult.dusk_time + params.dusk_lux_sensor_time_window * 60000; + } + else if (timePointName == "luxOff") { + tasks[0].timestamp = sunCalcResult.dawn_time + params.dawn_lux_sensor_time_window * 60000; + } + else if (timePointName == "profileTimepoint") { + tasks[0].timestamp = currentTimestamp + tasks[0].addMinutesToTimestamp * 60000; + } + + let info = "aplikovany bod profilu"; + let onOrOff = ""; + value == 1 ? onOrOff = "on" : onOrOff = "off"; + + turnLine(onOrOff, params.line, info); + + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + if (!SETTINGS.masterNodeIsResponding) { + //ak neodpoveda, nebudeme vykonavat ziadne commands, okrem cmd-terminal cmd-master + errorHandler.sendMessageToService("Master node is not responding"); + + let stop = true; + + if (type === "cmd-terminal" || type === "cmd-master") stop = false; + if (stop) { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + } + + let contactorStatus = 1; + if (relaysData[line] != undefined) contactorStatus = relaysData[line].contactor; + + if (line === 0 || contactorStatus === 0 || FLOW.deviceStatus.state_of_breaker[line] === "Off") { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + // TODO: -> status offline for rvo if rotary_switch_state is OFF, this is source of errors + // check if rotary_switch_state == "Off" + // state_of_braker: disconnected = true? + + if (!rsPort.isOpen) { + interval = setInterval(runTasks, LONG_INTERVAL); + return; + } + + //RE-CALCULATE VALUES + //set actual time for broadcast + if (register == 87 && params.recipient === 2) { + var d = new Date(); + params.byte1 = d.getHours();//h + params.byte2 = d.getMinutes();//m + } + + //SET DUSK/DAWN FOR BROADCAST + //Time of dusk + if (register == 6 && params.recipient === 2) { + + if (type != "cmd-terminal") { + params.byte1 = sunCalcResult["dusk_hours"];//h + params.byte2 = sunCalcResult["dusk_minutes"];//m + } + } + + //Time of dawn + if (register == 7 && params.recipient === 2) { + if (type != "cmd-terminal") { + params.byte1 = sunCalcResult["dawn_hours"];//h + params.byte2 = sunCalcResult["dawn_minutes"];//m + } + } + //----------------------- + + instance.send(SEND_TO.debug, "address: " + node + " register:" + register + "type: " + type); + + var startTime, endTime; + startTime = new Date(); + + let saveToTb = true; + if (!tbname) saveToTb = false; + + let resp = com_generic(node, params.recipient, params.rw, register, params.name, params.byte1, params.byte2, params.byte3, params.byte4); + let readBytes = 11; + let timeout = 4000; + + + // await keyword is important, otherwise incorrect data is returned! + await writeData(rsPort, resp, readBytes, timeout).then(function(data) { + + //sometimes happens, that status of node changes to OK, NOK even if line was turned off and should be status OFFLINE. To prevent this, we return if line contactor is 0: + if (itIsNodeCommand && line && relaysData[line].contactor !== 1) return; + + 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); + + //ak sa odpoved zacina 0 - je to v poriadku, inak je NOK + let message = result.message; // OK, NOK + let message_type = result.type; + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + console.log("detected response:", result); + logger.debug("Cmd-mngr: writeData done " + message_type + " duration: " + timeDiff + " type: " + params.debug, params, result); + } + } + + let values = {}; + + //CMD FINISHED + if (message == "OK") { + + updateNodeStatus(node, true); + + //write + if (type == "set_node_profile") { + let result = cmdCounterResolve(node); + if (result == 0) { + dbNodes.modify({ processed: true }).where("node", node).make(function(builder) { + builder.callback(function(err, response) { + + sendNotification("Cmd-mngr: process cmd", SETTINGS.rvoTbName, "dimming_profile_was_successfully_received_by_node", { node: node }, "", SEND_TO.tb, instance); + + logger.debug("--> profil úspešne odoslaný na node č. " + node); + nodesData[node].processed = true; + nodeProfileSendFail.delete(node); + }); + }); + } + } + + //parse read response + if (params.rw == 0) { + values = processResponse(register, dataBytes); //read + } + + if (itIsNodeCommand) { + values.comm_status = "OK"; + values.status = "OK"; + nodesData[node].readout = { ...nodesData[node].readout, ...values }; + + + if (SETTINGS.daily_report) { + //TODO: co ak nedostavame odpovede z nodu ? Musime vyreportovat!! + //v dailyReport teda musi byt kompletny zoznam nodov a neustale kontrolovat, ci maju data, ak nie report node - neodpoveda + if (register === 1) { + + let now = Date.now(); + + if (rvo_is_on === true) { + + if ("dimmingIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].dimmingIsOnButShouldBeOffTime; + + if (values.dimming > 0) { + if ("dimmingIsZeroTime" in dailyReport[node]) delete dailyReport[node].dimmingIsZeroTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if (!("dimmingIsZeroTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], dimmingIsZeroTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } else { + + if ("dimmingIsZeroTime" in dailyReport[node]) delete dailyReport[node].dimmingIsZeroTime; + + if (values.dimming > 0) { + if (!("dimmingIsOnButShouldBeOffTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], dimmingIsOnButShouldBeOffTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if ("dimmingIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].dimmingIsOnButShouldBeOffTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } + } + + if (register === 76) { + + let now = Date.now(); + + if (rvo_is_on === true) { + + if ("powerIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].powerIsOnButShouldBeOffTime; + + if (values.power > 1) { + if ("powerIsZeroTime" in dailyReport[node]) delete dailyReport[node].powerIsZeroTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if (!("powerIsZeroTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], powerIsZeroTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } else { + + if ("powerIsZeroTime" in dailyReport[node]) delete dailyReport[node].powerIsZeroTime; + + if (values.power > 1) { + if (!("powerIsOnButShouldBeOffTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], powerIsOnButShouldBeOffTime: now, initialTs: now }; + else dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } else { + if ("powerIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].powerIsOnButShouldBeOffTime; + dailyReport[node] = { ...dailyReport[node], initialTs: now }; + } + + } + } + } + + } + + //master node + if (node == 0) { + sendNotification("Cmd-mngr: 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; + } + + if (params.debug) { + //logger.debug("saveToTb", saveToTb, tbname, values); + } + + if (saveToTb && type != "node-regular-read") { + sendTelemetry(values, tbname); + } + else { + if (type == "cmd-terminal") { + terminalCommandResponse(params, "SUCCESS", data); + } + } + + } + else { + terminalCommandResponse(params, "ERROR", data); + handleNokResponseOnRsPort("handleNOK else block", params, itIsNodeCommand, saveToTb); + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + //logger.debug("writeData err: ", error, result, params); + logger.debug("writeData err: ", tbname, node, register, values); + } + } + + //logger.debug(error, result, params); + } + }).catch(function(reason) { + + //console.log("writeData catch exception", reason); + instance.send(SEND_TO.debug, reason); + + terminalCommandResponse(params, "FAILURE", null, reason); + handleNokResponseOnRsPort("handleNOK catch block", params, itIsNodeCommand, saveToTb); + + if (params.hasOwnProperty("debug")) { + if (params.debug) { + logger.debug("-->WRITE FAILED: " + reason, params.debug, params); + } + } + + }); + + } + 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); + } + + + // if node does not respond to request, we repeat request 3 times: + function repeatCommand(params) { + params.repeatCounter++; + if (params.repeatCounter < 4) { + params.timestamp = 0; + params.addMinutesToTimestamp = 0; + tasks.push(params); + } + } + + function handleNokResponseOnRsPort(message, params, itIsNodeCommand, saveToTb) { + + let node = params.address; + let register = params.register; + let type = params.type; + let tbName = params.tbname; + if (!tbName) return; + + let values = {}; + + let updateStatus = updateNodeStatus(node, false); + + if (itIsNodeCommand) { + values.comm_status = "NOK"; + nodesData[node].readout.comm_status = "NOK"; + repeatCommand(params); + } + + if (updateStatus) { + values.status = "NOK"; + nodesData[node].readout.status = "NOK"; + } + + if (type === "node-regular-read") return; + + //master node + if (node == 0) { + sendNotification("Cmd-mngr: 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; + + if (register == 4) values["master_node_version"] = "NOK"; + } + + if (type == "set_node_profile") { + delete cmdCounter[node]; + logger.debug("profil nebol úspešne odoslaný na node č. ", params); + + if (!nodeProfileSendFail.has(node)) { + sendNotification("Cmd-mngr: process cmd", tbName, "configuration_of_dimming_profile_to_node_failed", { node: node }, "", SEND_TO.tb, instance); + nodeProfileSendFail.add(node); + } + } + + // console.log("------",node, register, type, itIsNodeCommand, updateStatus, saveToTb, values); + if (saveToTb) { + sendTelemetry(values, tbName); + } + + } + + + function sendNodesData() { + Object.keys(nodesData).forEach(node => { + if (nodesData[node]["status"] !== "OFFLINE") { + sendTelemetry(nodesData[node].readout, nodesData[node].tbname); + nodesData[node].readout = {}; + } + }) + } + + + /** + * 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; + } + + 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); + + //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 === "OFFLINE") { + nodeObj.node_status_before_offline === true ? number_of_ok_luminaires++ : number_of_nok_luminaires++; + } + else if (nodeObj.status == true) 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 - ts % 60000 //round to full minute + }; + + sendTelemetry(values, SETTINGS.rvoTbName, ts); + } + + + function setSunCalcResult() { + //if next day, we get new dusk and dawn. To make sure, in local timezone 2:00 means 00:00 in utc (it means next day) + if (new Date().getHours() === 2) { + sunCalcResult = calculateDuskDawn(); + console.log("Novy suncalc: ", sunCalcResult); + } + } + + + function setRvoPeriod() { + + if (!SETTINGS.daily_report) return; + + const ts = Date.now(); + + previous_rvo_is_on_value = rvo_is_on; + + if (ts < sunCalcResult.dawn_time - 1_800_000) { // nodes should be on (00:00 -> 06:00 ( - pol hodina, lebo rvo vypina skor) + rvo_is_on = true; + } else if (sunCalcResult.dawn_time - 1_800_000 < ts && ts < sunCalcResult.dusk_time + 1_800_000) { // nodes should be off 06:00 -> 21:00 + rvo_is_on = false; + } else if (sunCalcResult.dusk_time + 1_800_000 < ts) { // nodes should be on 21:00 -> 00:00 + rvo_is_on = true; + } + + if (previous_rvo_is_on_value !== rvo_is_on) { + emptyDailyReport(); + console.log("rvo_is: ", rvo_is_on, previous_rvo_is_on_value); + } + } + + + function handleRsPort() { + + if (rsPort) { + rsPort.removeAllListeners(); + rsPort = null; + } + + //! 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-mngr: rsPort opened success"); + + 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); + + }).catch(function(reason) { + instance.send(SEND_TO.debug, "Cmd-mngr: RPC runSyncExec - promise rejected:" + reason); + }); + }); + + rsPort.on('error', function(err) { + errorHandler.sendMessageToService([exports.title, "unable to open port", SETTINGS.serial_port, err.message], 0); + monitor.info("Cmd-mngr: Error on rsPort", err.message); + }); + + rsPort.on("close", () => { + monitor.info("Cmd-mngr: rsPort closed, reconnecting..."); + setTimeout(handleRsPort, 1000); + }); + + rsPort.open(); + } + + + instance.on("close", () => { + clearInterval(interval); + clearInterval(customTasksInterval); + clearInterval(setCorrectTime); + clearInterval(sendNodeReadout); + clearInterval(accelerometerInterval); + rsPort.close(); + }); + + instance.on("0", _ => { + main(); + }) + + + instance.on("2", _ => { + console.log("dailyReport, reportToSend, rvo_is_on", dailyReport, reportToSend, rvo_is_on, previous_rvo_is_on_value); + }) + + instance.on("1", 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(); + return; + } + else if (flowdata.data == "close") { + rsPort.close(); + return; + } + else if (flowdata.data == "clean") { + tasks = []; + return; + } + else if (flowdata.data == "buildtasks") { + //build & run + return; + } + else if (flowdata.data == "run") { + //durations = []; + + if (tasks.length == 0) { + + buildTasks(); + + if (rsPort.isOpen) { + interval = setInterval(runTasks, 100); + } + else { + instance.send(SEND_TO.debug, "port is not opened!!!"); + } + } + } + else { + //terminal data - object + //logger.debug("flowdata", flowdata.data); + + if (typeof flowdata.data === 'object') { + //logger.debug("dido", flowdata.data); + if (flowdata.data.hasOwnProperty("sender")) { + //data from dido_controller + if (flowdata.data.sender == "dido_controller") { + + if (flowdata.data.hasOwnProperty("cmd")) { + let cmd = flowdata.data.cmd; + + if (cmd == "buildTasks") { + clearInterval(interval); + + logger.debug("-->Cmd-mngr: BUILD TASKS"); + buildTasks(); + + //logger.debug("tasks:"); + //logger.debug(tasks); + + logger.debug("-->Cmd-mngr: RUN TASKS"); + interval = setInterval(runTasks, 5000); + } + else if (cmd == "reload_relays") { + loadRelaysData(flowdata.data.line); + + if (flowdata.data.dataChanged) { + if (!flowdata.data.value) { + reportOfflineNodeStatus(flowdata.data.line); + } + else { + reportOnlineNodeStatus(flowdata.data.line); + } + } + + } + else if (cmd == "rotary_switch_state") { + let value = flowdata.data.value; + + //state was changed + if (rotary_switch_state != value) { + if (value == "Off") { + //vyreportovat vsetky svietdla + reportOfflineNodeStatus(); + } + + rotary_switch_state = value; + } + } + 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) { + + // we send lux_sensor value to all nodes: + let params = getParams(PRIORITY_TYPES.node_broadcast); + + params.recipient = 2;//2 broadcast, address = 0 + params.address = 0xffffffff;//Broadcast + + let ba = longToByteArray(lux_sensor); + + params.byte3 = ba[1];//msb + params.byte4 = ba[0]; + params.timestamp = PRIORITY_TYPES.node_broadcast; + params.info = "run broadcast: Actual Lux level from cabinet"; + params.register = 95;//Actual Lux level from cabinet + params.rw = 1;//write + + tasks.push(params); + + //process profiles + turnOnOffLinesAccordingToLuxSensor(lux_sensor); + } + } + else if (cmd == "state_of_breaker") { + //istic linie + + breakerCounter--; + + let value = flowdata.data.value; + let line = parseInt(flowdata.data.line); + + let dataChanged = false; + if (state_of_breaker[line] != value) dataChanged = true; + + state_of_breaker[line] = value; + + let status = "OK"; + if (value == "Off") status = "NOK"; + + if (dataChanged) { + + if (relaysData.hasOwnProperty(line)) { + let tbname = relaysData[line].tbname; + + if (value == "Off") { + sendNotification("Cmd-mngr: onData", tbname, "circuit_breaker_was_turned_off_line", { line: line }, "", SEND_TO.tb, instance, "circuit_breaker"); + if (breakerCounter < 0) reportToSend["contactor"]["off"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + else { + sendNotification("Cmd-mngr: onData", tbname, "circuit_breaker_was_turned_on_line", { line: line }, "", SEND_TO.tb, instance, "circuit_breaker"); + if (breakerCounter < 0) reportToSend["contactor"]["on"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + + //report status liniu + sendTelemetry({ status: status }, tbname) + + //current value + if (value == "Off") reportOfflineNodeStatus(line); //vyreportovat vsetky svietidla na linii + } + + } + } + else { + logger.debug("undefined cmd", cmd); + } + } + } + + return; + } + + //data from worksys + if (flowdata.data.hasOwnProperty("topic")) { + + let data = getNested(flowdata.data, "content", "data"); + + //if we get temperature in senica from senica-prod01 + let temperature = getNested(flowdata.data, "content", "senica_temperature"); + + if (temperature !== undefined) { + temperatureInSenica = temperature; + return; + } + + if (data === undefined) { + console.log("Invalid rpc command came from platform"); + return; + } + + let command = data.params.command; + let method = data.method; + let profile = data.params.payload; + if (profile == undefined) profile = ""; + let entity = data.params.entities[0]; + let entity_type = entity.entity_type; + let tbname = entity.tb_name; + + instance.send(SEND_TO.debug, flowdata.data); + 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") { + + //let command = data.params.command; + let value = data.params.payload.value; + + if (command == "dimming") { + + let nodeWasFound = false; + let keys = Object.keys(nodesData); + + //logger.debug("-----", keys); + + 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); + + value = parseInt(value); + if (value > 0) value = value + 128; + + params.type = "node-onetime-write"; + params.tbname = tbname; + params.address = node; + params.register = 1; + params.recipient = 1; + params.byte4 = value; + params.rw = 1; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'set dimming from platform'; + //params.debug = true; + + //debug(params); + logger.debug("dimming", params); + + tasks.push(params); + + 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); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 1; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read dimming (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + //pridame aj vyreportovanie - vykon + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 76; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read Input Power (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + //pridame aj vyreportovanie - prud svietidla + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 75; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read Input Current (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + //pridame aj vyreportovanie - power faktor - ucinnik + { + let params = getParams(PRIORITY_TYPES.high_priority); + + params.type = "node-onetime-read"; + params.tbname = tbname; + params.address = node; + params.register = 77; + params.recipient = 1; + params.rw = 0; + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read power factor (after set dimming from platform)'; + //params.debug = true; + + tasks.push(params); + } + + }, 4000); + + nodeWasFound = true; + break; + } + } + + if (!nodeWasFound) { + logger.debug("set dimming from platform", "unable to find tbname", tbname); + } + } + else { + instance.send(SEND_TO.debug, "undefined command " + command); + logger.debug("undefined command", command); + } + + return; + } + 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++) { + let node = keys[i]; + if (tbname == nodesData[node].tbname) { + + 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"); + + //profil úspešne prijatý pre node č. xx + sendNotification("Cmd-mngr", tbname, "dimming_profile_was_processed_for_node", { node: node }, profile, SEND_TO.tb, instance); + + nodesData[node].processed = false; + nodesData[node].profile = profile; + + processNodeProfile(node); + }); + }); + } + } + } + else { + + instance.send(SEND_TO.debug, "unknown method " + method); + logger.debug("unknown method", method); + + return; + } + } + + //nastav profil linie z platformy + 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") { + + 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++) { + let line = keys[i]; + if (tbname == relaysData[line].tbname) { + //zmazeme tasky + 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) { + + //update profile + logger.debug("worksys - update relay profile done:", profile); + instance.send(SEND_TO.debug, "worksys - update relay profile done"); + + relaysData[line].profile = profile; + + loadRelaysData(line) + logger.debug("loadRelaysData DONE for line", line); + + buildTasks({ processLineProfiles: true, line: line }); + + sendNotification("Cmd-mngr: set profile from worksys", tbname, "switching_profile_was_processed_for_line", { line: line }, profile, SEND_TO.tb, instance); + }); + }); + break; + } + } + } + else if (method == "set_command") { + let value = data.params.payload.value; + + 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; + + 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"); + if (line != 0) reportToSend["contactor"]["off"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + else { + turnLine("on", line, "command received from platform"); + if (line != 0) reportToSend["contactor"]["on"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode }); + } + } + } + else { + instance.send(SEND_TO.debug, "undefined method " + method); + logger.debug("undefined method", method); + } + + return; + } + else { + instance.send(SEND_TO.debug, "UNKNOW entity_type " + entity_type); + logger.debug("UNKNOW entity_type", entity_type); + } + return; + } + + //terminal + if (!rsPort.isOpen) await rsPort.open(); + + let params = flowdata.data.body; + if (params == undefined) { + //logger.debug("Cmd-mngr: flowdata.data.body is undefined"); + return; + } + + params.priority = PRIORITY_TYPES.terminal; + params.type = "cmd-terminal"; + params.tbname = ""; + params.timestamp = PRIORITY_TYPES.terminal; + params.addMinutesToTimestamp = 0;// do not repeat task!!! + params.debug = true; + + let timestamp = Date.now(); + params.refFlowdataKey = timestamp; + //params.refFlowdata = flowdata; + //refFlowdata = flowdata; + + //console.log("flowdata", flowdata); + + cleanUpRefFlowdataObj(); + + refFlowdataObj[timestamp] = flowdata; + + //fix + //params.address = params.adress; + logger.debug("received from terminal", params); + logger.debug("date/time:", new Date()); + logger.debug("tasks length:", tasks.length); + + //tasks = []; + + //add to tasks + tasks.push(params); + + } + } + }) + + + //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) + } + + + /** + * 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; + + RESTBuilder.make(function(builder) { + + if (!builder) return; + + builder.method('GET'); + builder.url('http://192.168.252.2:8004/gettime?projects_id=1'); + + builder.callback(function(err, response, output) { + + 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); + } + + }); + } + + } 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); + + } else { + //console.log("Read-only", stdout); + + 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]: [ + { + "ts": date, + "values": values + } + ] + } + + tbHandler.sendToTb(dataToTb, instance); + } + + + function calculateDuskDawn(date, line, duskOffset = 0, dawnOffset = 0) { + + if (date === undefined) date = new Date(); + + 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); + } + + //if(profile.dawn_lux_sensor == false) + { + if (profile.hasOwnProperty("dawn_astro_clock_offset")) dawn_astro_clock_offset = parseInt(profile.dawn_astro_clock_offset); + } + + } + + } catch (error) { + if (profilestr != "") { + logger.debug(profilestr); + logger.debug(error); + } + } + + 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; + } + + //Dimming, CCT + else if (register == 1) { + let brightness = 0; + let dimming = byte0; + if (dimming > 128) { + //dimming = -128; + brightness = dimming - 128; + } + + //cct + //Ak Byte3 == 1: CCT = (Byte2*256)+Byte1 + let cct; + if (byte3 == 1) cct = byte2 * 256 + byte1; + else cct = bytesToInt(bytes.slice(0, 3)); + + //cct podla auditu + + values["dimming"] = brightness; + return values; + } + + // + else if (register == 4) { + values["master_node_version"] = bytes[1] + "." + bytes[2]; + //logger.debug("FW Version", register, bytes); + } + + //Napätie + else if (register == 74) { + let voltage = (bytesToInt(bytes) * 0.1).toFixed(1); + values["voltage"] = Number(voltage); + } + + //Prúd + else if (register == 75) { + let current = bytesToInt(bytes); + values["current"] = current; + } + + //výkon + else if (register == 76) { + let power = (bytesToInt(bytes) * 0.1).toFixed(2); + values["power"] = Number(power); + } + + //účinník + else if (register == 77) { + let power_factor = Math.cos(bytesToInt(bytes) * 0.1 * (Math.PI / 180)).toFixed(2); + values["power_factor"] = Number(power_factor); + } + + //frekvencia + else if (register == 78) { + let frequency = (bytesToInt(bytes) * 0.1).toFixed(2); + values["frequency"] = Number(frequency); + } + + //energia + else if (register == 79) { + let energy = bytesToInt(bytes); + values["energy"] = energy / 1000; //energia v kWh -> delit 1000 + } + + //doba života + else if (register == 80) { + let lifetime = (bytesToInt(bytes) / 60).toFixed(2); + values["lifetime"] = Number(lifetime); + } + + //nastavenie profilu + else if (register == 8) { + let time_schedule_settings = bytesToInt(bytes); + values["time_schedule_settings"] = time_schedule_settings; + } + + //naklon - nateraz sa z nodu nevycitava! kvoli problemom s accelerometrom a vracanymi hodnotami, posielame temp a x y z vo funkcii accelerometerData() + else if (register == 84) { + values["temperature"] = byte3 >= 128 ? (byte3 - 128) * (-1) : byte3; + values["inclination_x"] = byte2 >= 128 ? (byte2 - 128) * (-1) : byte2; + values["inclination_y"] = byte1 >= 128 ? (byte1 - 128) * (-1) : byte1; + values["inclination_z"] = byte0 >= 128 ? (byte0 - 128) * (-1) : byte0; + } + + //FW verzia nodu + else if (register == 89) { + //formát: "Byte3: Byte2.Byte1 (Byte0)" + values["fw_version"] = byte3 + ":" + byte2 + "." + byte1 + "(" + byte0 + ")"; + } + + else if (register == 87 || register == 6 || register == 7) { + var d = new Date(); + d.setHours(byte3, byte2, 0, 0); + let timestamp = d.getTime(); + + //aktuálny čas + if (register == 87) values["actual_time"] = timestamp; + //čas súmraku + else if (register == 6) values["dusk_time"] = timestamp; + //čas úsvitu + else if (register == 7) values["dawn_time"] = timestamp; + } + + 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; + + } + + + function getObjectByTbValue(object, tbname) { + return object[Object.keys(object).find(key => object[key].tbname === tbname)]; + } + + + function isObject(item) { + return (typeof item === "object" && !Array.isArray(item) && item !== null); + } + + + // we fake data, that should be received from accelerometer, as they are a bit unreliable. (temperature, x,y,z) + function accelerometerData() { + + if (temperatureInSenica === null) return; + + //clone nodesData and relaysData objects + let nodesData_clone = JSON.parse(JSON.stringify(nodesData)); + let relaysData_clone = JSON.parse(JSON.stringify(relaysData)); + + for (const key in relaysData_clone) { + + const lineData = relaysData_clone[key]; + const lineNumber = lineData.line; + const contactor = lineData.contactor; + + if (lineNumber === 0) continue; + + if (contactor === 1) { + + let date = Date.now(); + + Object.keys(nodesData_clone).forEach((node, index) => { + + setTimeout(function() { + + if (nodesData_clone[node].line === lineNumber) { + + // NOTE: if status of luminaire is NOK or OFFLINE, we do not send data; + let status = nodesData_clone[node].status; + if (status === "OFFLINE" || !status) return; + + let x = null; + if (naklony.hasOwnProperty(node)) x = naklony[node].naklon; + if (x === null) x = 0; + + sendTelemetry({ temperature: Math.round(temperatureInSenica + 10 + Math.floor(Math.random() * 3)), inclination_x: x, inclination_y: 0, inclination_z: 0 }, nodesData_clone[node].tbname, date); + } + + }, (index + 1) * 500); + }) + + } + } + } + + +} // end of instance.export + diff --git a/RVO53/flow/code.js b/RVO53/flow/code.js new file mode 100755 index 0000000..63b31bf --- /dev/null +++ b/RVO53/flow/code.js @@ -0,0 +1,90 @@ +exports.id = 'code'; +exports.title = 'Code'; +exports.group = 'Common'; +exports.color = '#656D78'; +exports.input = true; +exports.output = 1; +exports.author = 'Peter Širka'; +exports.icon = 'code'; +exports.version = '1.2.0'; +exports.options = { outputs: 1, code: 'send(0, value);', keepmessage: true }; + +exports.html = `
+
+
+
@(Number of outputs)
+
@(Minimum is 1)
+
+
+
@(Code)
+
@(Keep message instance)
+
+`; + +exports.readme = `# Code + +This component executes custom JavaScript code as it is and it doesn't contain any secure scope. + +\`\`\`javascript +// value {Object} contains received data +// send(outputIndex, newValue) sends a new value +// error(value) sends an error +// instance {Object} a current component instance +// flowdata {Object} a current flowdata +// repository {Object} a current repository of flowdata +// Example: + +// send() can be execute multiple times +send(0, value); +\`\`\``; + +exports.install = function(instance) { + + var fn; + + instance.on('data', function(response) { + if (fn) { + try { + fn(response.data, instance, response, instance.options, response.repository, require); + } catch (e) { + response.data = e; + instance.throw(response); + } + } + }); + + instance.reconfigure = function() { + try { + if (instance.options.code) { + instance.status(''); + var code = 'var send = function(index, value) { if (options.keepmessage) { flowdata.data = value; instance.send2(index, flowdata); } else instance.send2(index, value);}; var error = function(err) { instance.throw(err); }; ' + instance.options.code; + fn = new Function('value', 'instance', 'flowdata', 'options', 'repository', 'require', code); + } else { + instance.status('Not configured', 'red'); + fn = null; + } + } catch (e) { + fn = null; + instance.error('Code: ' + e.message); + } + }; + + instance.on('options', instance.reconfigure); + instance.reconfigure(); +}; \ No newline at end of file diff --git a/RVO53/flow/comment.js b/RVO53/flow/comment.js new file mode 100755 index 0000000..1e0cd13 --- /dev/null +++ b/RVO53/flow/comment.js @@ -0,0 +1,11 @@ +exports.id = 'comment'; +exports.title = 'Comment'; +exports.group = 'Common'; +exports.color = '#704cff'; +exports.author = 'Martin Smola'; +exports.icon = 'comment'; +exports.traffic = false; +exports.version = '1.0.0'; +exports.readme = '# Comment'; + +exports.install = function() {}; diff --git a/RVO53/flow/count.js b/RVO53/flow/count.js new file mode 100755 index 0000000..fa92ee9 --- /dev/null +++ b/RVO53/flow/count.js @@ -0,0 +1,60 @@ +exports.id = 'count'; +exports.title = 'Count'; +exports.version = '1.0.1'; +exports.author = 'John Graves'; +exports.color = '#656D78'; +exports.icon = 'plus-square'; +exports.input = 2; +exports.output = 1; +exports.options = { increment: 1, initialvalue: 1 }; +exports.readme = `# Counter + +Counter Number of times called.`; + +exports.html = `
+
@(Initial Value)
+
@(Increment)
+

Example Video

+
`; + +exports.readme = `# Count + +This component counts the number of messages received. + +__Response:__ + +Integer value based on the initial value and increment settings. + +__Arguments:__ +- Initial Value: What number should be output on the receipt of the first message. +- Increment: What should the increment be for each following message received.`; + +exports.install = function(instance) { + + var count = 0; + var initialCall = true; + + instance.on('data', function(flowdata) { + var index = flowdata.index; + if (index) { + instance.debug('Reset Count.'); + count = instance.options.initialvalue; + initialCall = true; + } else { + // If this is the first time, set the value to 'initial value' + if(initialCall) { + initialCall = false; + count = instance.options.initialvalue; + } else + count = count+instance.options.increment; + instance.status('Count:' + count); + instance.send2(count); + } + }); + + instance.on('options', function() { + count = instance.options.initialvalue; + initialCall = true; + }); + +}; diff --git a/RVO53/flow/db_connector.js b/RVO53/flow/db_connector.js new file mode 100755 index 0000000..65ee94b --- /dev/null +++ b/RVO53/flow/db_connector.js @@ -0,0 +1,286 @@ +exports.id = 'db_connector'; +exports.title = 'DbConnector'; +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.html = `
+
+
+
DbConnector
+
+
+
`; + +exports.readme = `# read/write data to tables`; + +const instanceSendTo = { + debug: 0, + http_response: 1, +} + +const { promisifyBuilder, makeMapFromDbResult } = require('./helper/db_helper.js'); + +function extractWhereParams(params) +{ + let name = params[0]; + let operator = '='; + let value = params[1]; + + if(params.length == 3) + { + operator = params[1]; + value = params[2]; + } + + return {name: name, operator: operator, value: value}; +} + +exports.install = function(instance) { + + let refFlowdata = null;//holds reference to httprequest flowdata + + instance.on("close", () => { + + }) + + + instance.on("data", async function(flowdata) { + + let params = flowdata.data.body; + console.log("DbConnector", params); + + refFlowdata = flowdata; + + if(refFlowdata != undefined) + { + //make http response + let responseObj = {}; + responseObj["type"] = "SUCESS"; + + try{ + + let table = params.table; + let action = params.action; + + + if(params.data != undefined) + { + let className = params.data.className; + + if(className == "SqlQueryBuilder") + { + let type = params.data.type; + + console.log("SqlQueryBuilder---->", params.data); + + if(type == "SELECT") + { + let table = params.data.queryData.tables[0].table; + + const db = TABLE(table); + var builder = db.find(); + + let result = await promisifyBuilder(builder); + + let response = {}; + response["result"] = result; + response["success"] = true; + + responseObj["data"] = response; + + //console.log(responseObj); + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + } + + return; + } + } + + + console.log("db_connector---->", table, action); + + //actions: read, replace, insert, delete, update... + + if(action == "read") + { + const db = TABLE(params.table); + + //where builder.where('age', '<', 15); + //builder.where('id', 3403); + + var builder = db.find(); + + //https://docs.totaljs.com/latest/en.html#api~DatabaseBuilder~builder.where + if(params.hasOwnProperty("where")) + { + //optionalCan contain "=", "<=", "<", ">=", ">". + //Default value: '=' + + //1.["production_line", 1] + //2. ["or", ["production_line", 1], ["production_line", 2], "end"] + + if (Array.isArray(params.where)) { + + let multipleConditions = false; + + if(params.where[0] == "or") multipleConditions = true; + if (Array.isArray(params.where[0])) multipleConditions = true; + + if(multipleConditions) + { + + for(var i = 0; i < params.where.length; i++) + { + const item = params.where[i]; + + if(item === "or") builder.or(); + + if (Array.isArray(item)) + { + const { name, operator, value } = extractWhereParams(item); + builder.where(name, operator, value); + } + + if(item === "end") builder.end(); + + } + + } + else + { + const { name, operator, value } = extractWhereParams(params.where); + builder.where(name, operator, value); + } + + } + + /* + if(params.where.length >=2 ) + { + let name = params.where[0]; + let operator = '='; + let value = params.where[1]; + + if(params.where.length == 3) + { + operator = params.where[1]; + value = params.where[2]; + } + + builder.where(name, operator, value); + } + */ + } + + if(params.hasOwnProperty("between")) + { + builder.between(params.between[0], params.between[1], params.between[2]); + } + + let response = await promisifyBuilder(builder); + responseObj["data"] = response; + + //console.log(responseObj); + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + + return; + } + + if(action == "delete") + { + + } + + + if(action == "update") + { + //! data receiving from terminal (params) + // { + // hostname: 'localhost', + // table: 'settings', + // action: 'update', + // body: { + // rvo_name: 'terrrr', + // lang: 'en', + // temperature_adress: '28.427B45920702', + // latitude: 48.70826502, + // longitude: 17.28455203, + // mqtt_host: '192.168.252.4', + // mqtt_clientid: 'showroom_test_panel_led', + // mqtt_username: 'xmRd6RJxW53WZe4vMFLU', + // mqtt_port: 1883, + // maintanace_mode: false + // } + // } + const tableToModify = TABLE(params.table); + const newValues = params.body; + + tableToModify.modify(newValues).make(function(builder) { + + builder.callback(function(err, response) { + + if(!err) + { + responseObj["data"] = response; + responseObj["tableUpdated"] = true; + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + } + }); + }); + + } + + if(action == "replace") + { + //truncate table + const db = TABLE(params.table); + var builder = db.remove(); + db.clean(); + + //insert data + let data = params.data; + + for(let i = 0; i < data.length; i++) + { + //console.log(data[i]); + db.insert(data[i]); + } + + console.log("insert done"); + + let responseObj = {}; + responseObj["type"] = "SUCESS"; + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + + + } + + + + } catch (error) { + //console.log(error); + responseObj["type"] = "ERROR"; + responseObj["message"] = error; + + refFlowdata.data = responseObj; + instance.send(instanceSendTo.http_response, refFlowdata); + } + } + }) +} + + diff --git a/RVO53/flow/db_init.js b/RVO53/flow/db_init.js new file mode 100755 index 0000000..b399878 --- /dev/null +++ b/RVO53/flow/db_init.js @@ -0,0 +1,113 @@ +exports.id = 'db_init'; +exports.title = 'DB Initialization'; +exports.group = 'Worksys'; +exports.color = '#888600'; +exports.version = '1.0.2'; +exports.icon = 'sign-out'; +exports.output = 2; + +exports.readme = ` + # DB initialization +`; + +const { promisifyBuilder, makeMapFromDbResult } = require('./helper/db_helper.js'); +const { initNotification } = require('./helper/notification_reporter'); +const errorHandler = require('./helper/ErrorToServiceHandler'); +const total_energy = require('../databases/total_energy'); + +const SEND_TO = { + db_init: 0, + infoSender: 1 +}; + + +exports.install = async function(instance) { + const dbNodes = TABLE("nodes"); + const dbRelays = TABLE("relays"); + const dbSettings = TABLE("settings"); + 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 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.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"]; + Object.keys(dbs.nodesData).forEach(node => dbs.nodesData[node].readout = {}) + + let rvo_number = responseSettings[0]["rvo_name"].match(/\D+(\d{1,2})_/)[1]; + + dbs.settings = { + edge_fw_version: "2025-10-08", //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"], + phases: responseSettings[0]["phases"], + cloud_topic: responseSettings[0]["cloud_topic"], + has_main_switch: responseSettings[0]["has_main_switch"], + daily_report: responseSettings[0]["daily_report"], + send_changed_node_numbers: responseSettings[0]["send_changed_node_numbers"], + rvo_number: rvo_number, + + //dynamic values + masterNodeIsResponding: true, //cmd_manager + maintenance_mode: false, + } + + + dbs.settings.energy_to_switch_lamps = total_energy[rvo_number]; + if (dbs.settings.energy_to_switch_lamps === undefined) console.log('=============== db_init.js: energy_to_switch_lamps is undefined'); + + FLOW.dbLoaded = true; + errorHandler.setProjectId(dbs.settings.project_id); + initNotification(); + + //APP START - send to data services + const toService = { + id: dbs.settings.project_id, + name: dbs.settings.rvo_name, + fw_version: dbs.settings.edge_fw_version, + startdate: new Date().toISOString().slice(0, 19).replace('T', ' '), + js_error: "", + error_message: "" + }; + + instance.send(SEND_TO.infoSender, toService); + console.log("----------------> START - message send to service", toService); + + setTimeout(() => { + console.log("DB_INIT - data loaded"); + instance.send(SEND_TO.db_init, "_") + }, 5000) + +}; + diff --git a/RVO53/flow/debug.js b/RVO53/flow/debug.js new file mode 100755 index 0000000..00cb259 --- /dev/null +++ b/RVO53/flow/debug.js @@ -0,0 +1,100 @@ +exports.id = 'debug'; +exports.title = 'Debug'; +exports.author = 'Peter Širka'; +exports.color = '#967ADC'; +exports.click = true; +exports.input = true; +exports.icon = 'bug'; +exports.version = '2.0.4'; +exports.options = { enabled: true, repository: false, type: 'data' }; +exports.readme = `# Debug + +Prints data to the debug tab.`; + +exports.html = `
+
+
+
@(Output type)
+
@(Path to the property (leave empty to show the whole data object))
+
@(A group name)
+
@(Enabled)
+
+
+
`; + +exports.install = function(instance) { + + instance.on('data', function(response) { + if (instance.options.enabled) { + + var opt = instance.options; + var rep = response.repository; + var val = response.data; + var id = response.id; + + switch (instance.options.type){ + case 'both': + var data = {}; + data.repository = rep; + data.data = val instanceof Error ? { error: val.message, stack: val.stack } : val; + instance.debug(safeparse(opt.property ? U.get(data, opt.property) : data), undefined, opt.group, id); + break; + case 'repository': + instance.debug(safeparse(opt.property ? U.get(rep, opt.property) : rep), undefined, opt.group, id); + break; + case 'data': + default: + if (val instanceof Error) + instance.debug({ error: val.message, stack: val.stack }, undefined, opt.group, id); + else + instance.debug(safeparse(opt.property ? U.get(val, opt.property) : val), undefined, opt.group, id); + break; + } + } + }); + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + instance.save(); + }); + + instance.on('options', function() { + instance.custom.status(); + }); + + instance.custom.status = function() { + instance.status(instance.options.enabled ? 'Enabled' : 'Disabled'); + }; + + instance.custom.status(); + + function safeparse(o) { + + if (o instanceof Buffer) + return o; + + if (o === undefined) + return 'undefined'; + + if (o === null) + return 'null'; + + var cache = []; + var str = JSON.stringify(o, function(key, value) { + if (typeof value === 'object' && value !== null) { + if (cache.indexOf(value) !== -1) { + try { + return JSON.parse(JSON.stringify(value)); + } catch (error) { + return; + } + } + cache.push(value); + } + return value; + }); + cache = null; + return JSON.parse(str); + } +}; diff --git a/RVO53/flow/designer.json b/RVO53/flow/designer.json new file mode 100755 index 0000000..580f5a3 --- /dev/null +++ b/RVO53/flow/designer.json @@ -0,0 +1,3102 @@ +{ + "tabs": [ + { + "name": "MAIN PUSH", + "linker": "main-push", + "id": "1612772287426", + "index": 0 + }, + { + "name": "CMD manager", + "linker": "cmd-manager", + "id": "1615551125555", + "index": 1 + }, + { + "name": "Devices", + "linker": "devices", + "id": "1611921777196", + "index": 2 + } + ], + "components": [ + { + "id": "1611951142547", + "component": "debug", + "tab": "1611921777196", + "name": "ERROR", + "x": 598, + "y": 60, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#DA4453", + "notes": "" + }, + { + "id": "1612776786008", + "component": "wsmqttpublish", + "tab": "1612772287426", + "name": "WS MQTT publish", + "x": 281.75, + "y": 174, + "connections": { + "0": [ + { + "index": "0", + "id": "1615551060773" + } + ], + "1": [ + { + "index": "0", + "id": "1618300858252" + }, + { + "index": "0", + "id": "1618558465485" + } + ], + "2": [ + { + "index": "0", + "id": "1634303685503" + } + ], + "3": [ + { + "index": "0", + "id": "1731068754606" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Connected", + "color": "green" + }, + "options": { + "username": "", + "clientid": "", + "port": "1883", + "host": "" + }, + "color": "#888600", + "notes": "" + }, + { + "id": "1612778461252", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "tb-push", + "x": 72.75, + "y": 328, + "connections": { + "0": [ + { + "index": "0", + "id": "1612783322136" + }, + { + "index": "1", + "id": "1612776786008" + }, + { + "index": "0", + "id": "1731068754606" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1612783322136", + "component": "debug", + "tab": "1612772287426", + "name": "to TB", + "x": 283.75, + "y": 324, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615551060773", + "component": "debug", + "tab": "1612772287426", + "name": "errors from MQTT Broker", + "x": 594, + "y": 57, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#DA4453", + "notes": "" + }, + { + "id": "1615563373927", + "component": "debug", + "tab": "1615551125555", + "name": "Debug", + "x": 755, + "y": 155, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#DA4453", + "notes": "" + }, + { + "id": "1615566865233", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "tb-push", + "x": 755, + "y": 248, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1615798582262", + "component": "debug", + "tab": "1615551125555", + "name": "CMD_debug", + "x": 755, + "y": 346, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615802995322", + "component": "debug", + "tab": "1611921777196", + "name": "Debug", + "x": 596.8833312988281, + "y": 566.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Disabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": false + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615809128443", + "component": "debug", + "tab": "1611921777196", + "name": "tempToTb", + "x": 595.8833312988281, + "y": 658.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1615809595184", + "component": "virtualwireout", + "tab": "1611921777196", + "name": "tb-push", + "x": 597.8833312988281, + "y": 377.25, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1616165795916", + "component": "httproute", + "tab": "1615551125555", + "name": "POST /terminal", + "x": 135, + "y": 547, + "connections": { + "0": [ + { + "index": "0", + "id": "1684060205000" + }, + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Listening", + "color": "green" + }, + "options": { + "timeout": 10, + "cachepolicy": 0, + "cacheexpire": "5 minutes", + "size": 5, + "url": "/terminal", + "method": "POST", + "name": "", + "flags": [ + "id:1616165795916", + "post", + 10000 + ], + "emptyresponse": false + }, + "color": "#5D9CEC", + "notes": "### Configuration\n\n- __POST /terminal__\n- flags: \n- maximum request data length: __5 kB__\n- empty response: __false__\n- cache policy: __no cache__\n- cache expire: __5 minutes__", + "cloning": false + }, + { + "id": "1616165824813", + "component": "httpresponse", + "tab": "1615551125555", + "name": "HTTP Response", + "x": 753, + "y": 423, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "json" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1617104731852", + "component": "debug", + "tab": "1615551125555", + "name": "DIDO_Debug", + "x": 669, + "y": 1040, + "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": "turnOff line", + "x": 133, + "y": 1161, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "object", + "data": "{line: 3, command: \"turnOff\", force: true}" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1617115013095", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "tb-push", + "x": 669, + "y": 1150, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1617284749681", + "component": "trigger", + "tab": "1615551125555", + "name": "update profile / node", + "x": 112, + "y": 208, + "connections": { + "0": [ + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "data": "profile_nodes", + "datatype": "string" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1618235171399", + "component": "trigger", + "tab": "1615551125555", + "name": "tun tasks", + "x": 184, + "y": 279, + "connections": { + "0": [ + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "data": "run" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1618300858252", + "component": "debug", + "tab": "1612772287426", + "name": "wsmqtt-exit1", + "x": 597.8833312988281, + "y": 149, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1618393583970", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "to-cmd-manager", + "x": 668.8833312988281, + "y": 1269, + "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": 132.88333129882812, + "y": 367, + "connections": { + "0": [ + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "platform-rpc-call", + "color": "gray" + }, + "options": { + "wirename": "platform-rpc-call" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1618393759854", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "cmd_to_dido", + "x": 119.88333129882812, + "y": 1007, + "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": 752.8833312988281, + "y": 527, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "cmd_to_dido", + "color": "gray" + }, + "options": { + "wirename": "cmd_to_dido" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1618558465485", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "platform-rpc-call", + "x": 597.8833312988281, + "y": 247, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "platform-rpc-call", + "color": "gray" + }, + "options": { + "wirename": "platform-rpc-call" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1618572059773", + "component": "trigger", + "tab": "1615551125555", + "name": "turnOn line", + "x": 132, + "y": 1085, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "data": "{line: 1, command: \"turnOn\", force: true}", + "datatype": "object" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1619515097737", + "component": "cmd_manager", + "tab": "1615551125555", + "name": "CMD Manager", + "x": 452.1091003417969, + "y": 341.05455017089844, + "connections": { + "0": [ + { + "index": "0", + "id": "1615563373927" + } + ], + "1": [ + { + "index": "0", + "id": "1615566865233" + }, + { + "index": "0", + "id": "1615798582262" + } + ], + "2": [ + { + "index": "0", + "id": "1616165824813" + } + ], + "3": [ + { + "index": "0", + "id": "1618393827655" + } + ], + "4": [ + { + "index": "0", + "id": "1635936391935" + } + ], + "5": [ + { + "index": "0", + "id": "1757006030239" + }, + { + "index": "0", + "id": "1757006060377" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1619605019281", + "component": "httproute", + "tab": "1615551125555", + "name": "GET db", + "x": 173, + "y": 653, + "connections": { + "0": [ + { + "index": "0", + "id": "1684060205000" + }, + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Listening", + "color": "green" + }, + "options": { + "timeout": 5, + "cachepolicy": 0, + "cacheexpire": "5 minutes", + "size": 5, + "url": "/db", + "method": "GET", + "name": "", + "flags": [ + "id:1619605019281", + "get", + 5000 + ] + }, + "color": "#5D9CEC", + "notes": "### Configuration\n\n- __GET /db__\n- flags: undefined\n- maximum request data length: __5 kB__\n- empty response: __undefined__\n- cache policy: __no cache__\n- cache expire: __5 minutes__", + "cloning": false + }, + { + "id": "1619784672383", + "component": "trigger", + "tab": "1615551125555", + "name": "turnOnAlarm", + "x": 120, + "y": 1234, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "object", + "data": "{command: \"turnOnAlarm\"}" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1619784812964", + "component": "trigger", + "tab": "1615551125555", + "name": "turnOffAlarm", + "x": 118, + "y": 1307, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "object", + "data": "{command: \"turnOffAlarm\"}" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1621340721628", + "component": "virtualwireout", + "tab": "1611921777196", + "name": "modbus_to_dido", + "x": 599, + "y": 471, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "modbus_to_dido", + "color": "gray" + }, + "options": { + "wirename": "modbus_to_dido" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1622640022885", + "component": "httproute", + "tab": "1615551125555", + "name": "POST /db_connector", + "x": 98, + "y": 1586, + "connections": { + "0": [ + { + "index": "0", + "id": "1622640073521" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Listening", + "color": "green" + }, + "options": { + "timeout": 5, + "cachepolicy": 0, + "cacheexpire": "5 minutes", + "size": 5, + "url": "/db_connector", + "method": "POST", + "flags": [ + "id:1622640022885", + "post", + 5000 + ] + }, + "color": "#5D9CEC", + "notes": "### Configuration\n\n- __POST /db_connector__\n- flags: \n- maximum request data length: __5 kB__\n- empty response: __undefined__\n- cache policy: __no cache__\n- cache expire: __5 minutes__", + "cloning": false + }, + { + "id": "1622640073521", + "component": "db_connector", + "tab": "1615551125555", + "name": "DbConnector", + "x": 372, + "y": 1572, + "connections": { + "1": [ + { + "index": "0", + "id": "1622641420685" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "edge": "undefined" + }, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1622641420685", + "component": "httpresponse", + "tab": "1615551125555", + "name": "HTTP Response", + "x": 596, + "y": 1586, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1634303504177", + "component": "monitormemory", + "tab": "1612772287426", + "name": "RAM", + "x": 69.88333129882812, + "y": 888.5, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465281992" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "858.88 MB / 985.68 MB", + "color": "gray" + }, + "options": { + "enabled": true, + "interval": 30000 + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1634303533779", + "component": "monitordisk", + "tab": "1612772287426", + "name": "disk", + "x": 70.88333129882812, + "y": 982.5, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465821120" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "5.78 GB / 7.26 GB", + "color": "gray" + }, + "options": { + "enabled": true, + "path": "/", + "interval": 30000 + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1634303595494", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "send-to-services", + "x": 51.883331298828125, + "y": 1400.5, + "connections": { + "0": [ + { + "index": "0", + "id": "1634463186563" + }, + { + "index": "1", + "id": "1634488120710" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1634303602169", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "send-to-services", + "x": 426.8833312988281, + "y": 878.5, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1634303685503", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "send-to-services", + "x": 600.8833312988281, + "y": 341.5, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1634303743260", + "component": "httprequest", + "tab": "1612772287426", + "name": "192.168.252.2:8004/sentmessage", + "reference": "", + "x": 506.8833312988281, + "y": 1331.7333374023438, + "connections": { + "0": [ + { + "index": "0", + "id": "1635327431236" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "url": "http://192.168.252.2:8004/sentmessage", + "method": "POST", + "stringify": "json" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1634463186563", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 305.75, + "y": 1442, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634464580289", + "component": "code", + "tab": "1612772287426", + "name": "Code", + "x": 245, + "y": 787, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465243324" + }, + { + "index": "0", + "id": "1634303602169" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "keepmessage": true, + "code": "let response = {};\nresponse.cpu = value.cpu;\nresponse.uptime = value.uptime;\n\nsend(0, response);", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1634465243324", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 428, + "y": 784, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634465281992", + "component": "code", + "tab": "1612772287426", + "name": "Code", + "x": 245, + "y": 884, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465338103" + }, + { + "index": "0", + "id": "1634303602169" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "keepmessage": true, + "code": "value.sender = \"ram\";\n\nlet response = {};\n\nresponse.memory_total = Math.round(value.total / (1024 ** 2));\nresponse.memory_free = Math.round(value.free / (1024 ** 2));\nresponse.memory_used = Math.round(value.used / (1024 ** 2));\n\nsend(0, response);", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1634465338103", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 429, + "y": 976, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634465821120", + "component": "code", + "tab": "1612772287426", + "name": "Code", + "x": 245, + "y": 978, + "connections": { + "0": [ + { + "index": "0", + "id": "1634465892500" + }, + { + "index": "0", + "id": "1634303602169" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "keepmessage": true, + "code": "value.sender = \"hdd\";\n\nlet response = {};\n\nresponse.hdd_total = Math.round(value.total / (1024 ** 2));\nresponse.hdd_free = Math.round(value.free / (1024 ** 2));\nresponse.hdd_used = Math.round(value.used / (1024 ** 2));\n\nsend(0, response);", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1634465892500", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 432, + "y": 1068, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634484067516", + "component": "debug", + "tab": "1612772287426", + "name": "Send info", + "x": 513, + "y": 1441, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1634488120710", + "component": "infosender", + "tab": "1612772287426", + "name": "Info sender", + "x": 301, + "y": 1336, + "connections": { + "0": [ + { + "index": "0", + "id": "1634484067516" + }, + { + "index": "0", + "id": "1634303743260" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "edge": "undefined" + }, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1635327431236", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 837.8833312988281, + "y": 1325.5, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1635936391935", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "send-to-services", + "x": 753, + "y": 623, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1637069803394", + "component": "monitorconsumption", + "tab": "1612772287426", + "name": "CPU", + "x": 69, + "y": 791, + "connections": { + "0": [ + { + "index": "0", + "id": "1634464580289" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "49.2% / 69.91 MB", + "color": "gray" + }, + "options": { + "monitorfiles": true, + "monitorconnections": true, + "monitorsize": true, + "monitorconsumption": true, + "enabled": true, + "interval": 30000 + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1683664161036", + "component": "debug", + "tab": "1615551125555", + "name": "CMDtoDIDO", + "x": 392, + "y": 1012, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1683981346282", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "from-dido-controller", + "x": 112, + "y": 459, + "connections": { + "0": [ + { + "index": "0", + "id": "1684055037116" + }, + { + "index": "1", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "from-dido-controller", + "color": "gray" + }, + "options": { + "wirename": "from-dido-controller" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1684055037116", + "component": "debug", + "tab": "1615551125555", + "name": "from dido to cmd", + "x": 451, + "y": 532, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1684060205000", + "component": "debug", + "tab": "1615551125555", + "name": "HTTP routes", + "x": 450, + "y": 639, + "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": "MDBToDido", + "x": 598, + "y": 147, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1699963668903", + "component": "dido_controller", + "tab": "1615551125555", + "name": "DIDO_Controller", + "x": 397, + "y": 1131, + "connections": { + "0": [ + { + "index": "0", + "id": "1617104731852" + } + ], + "1": [ + { + "index": "0", + "id": "1617104731852" + }, + { + "index": "0", + "id": "1617115013095" + } + ], + "2": [ + { + "index": "0", + "id": "1618393583970" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "edge": "undefined" + }, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1699964678894", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "modbus_to_dido", + "x": 96, + "y": 924, + "connections": { + "0": [ + { + "index": "0", + "id": "1699963668903" + }, + { + "index": "0", + "id": "1699964793925" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "modbus_to_dido", + "color": "gray" + }, + "options": { + "wirename": "modbus_to_dido" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1699964793925", + "component": "debug", + "tab": "1615551125555", + "name": "modbusToDido", + "x": 388, + "y": 920, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1699965957410", + "component": "modbus_reader", + "tab": "1611921777196", + "name": "Modbus reader", + "x": 232, + "y": 175, + "connections": { + "0": [ + { + "index": "0", + "id": "1611951142547" + } + ], + "1": [ + { + "index": "0", + "id": "1621340721628" + }, + { + "index": "0", + "id": "1684179110403" + }, + { + "index": "0", + "id": "1717441414646" + } + ], + "2": [ + { + "index": "0", + "id": "1615809595184" + }, + { + "index": "0", + "id": "1714752862828" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1700411878636", + "component": "thermometer", + "tab": "1611921777196", + "name": "Thermometer", + "x": 234.75, + "y": 444, + "connections": { + "0": [ + { + "index": "0", + "id": "1615802995322" + } + ], + "1": [ + { + "index": "0", + "id": "1615809595184" + }, + { + "index": "0", + "id": "1615809128443" + } + ], + "2": [ + { + "index": "0", + "id": "1621340721628" + }, + { + "index": "0", + "id": "1732889185927" + }, + { + "index": "0", + "id": "1717441414646" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#5CB36D", + "notes": "" + }, + { + "id": "1714752862828", + "component": "debug", + "tab": "1611921777196", + "name": "MDBToTb", + "x": 766, + "y": 324, + "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": 764.0833282470703, + "y": 222, + "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\telse if(value.status === \"NOK-thermometer\")\n\t{\n\t\tsend(0, {\"thermometer\": \"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\telse if(value.values.hasOwnProperty(\"temperature\"))\n\t{\n\t\tsend(0, {\"thermometer\": \"OK\"});\n\t}\n}", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1717442627834", + "component": "debug", + "tab": "1611921777196", + "name": "modbus service", + "x": 966.0833282470703, + "y": 165, + "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": 968.0833282470703, + "y": 268, + "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": 88.75, + "y": 1685, + "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": 296, + "y": 1671, + "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\", \"Flow has been restarted\", \"Node db has changed\"]", + "types": "[\"emergency\", \"critical\", \"error\", \"alert\"]", + "name": "" + }, + "color": "#30E193", + "notes": "" + }, + { + "id": "1718016073501", + "component": "httprequest", + "tab": "1612772287426", + "name": "http://192.168.252.2:8004/slack", + "x": 495, + "y": 1753, + "connections": { + "0": [ + { + "index": "0", + "id": "1718016086212" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "url": "http://192.168.252.2:8004/slack", + "method": "POST", + "stringify": "json" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1718016086212", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 832, + "y": 1664, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "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": 87, + "y": 1591, + "connections": { + "0": [ + { + "index": "0", + "id": "1718016052341" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "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\": \"\" } } } ] }", + "datatype": "object" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1729855334955", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "platform-rpc-call", + "x": 599.9333343505859, + "y": 541.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "platform-rpc-call", + "color": "gray" + }, + "options": { + "wirename": "platform-rpc-call" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1729855371093", + "component": "debug", + "tab": "1612772287426", + "name": "rpc cloud", + "x": 601.9333343505859, + "y": 440.3500061035156, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1731068658334", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 75.75, + "y": 184, + "connections": { + "0": [ + { + "index": "0", + "id": "1612776786008" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731068754606", + "component": "cloudmqttconnect", + "tab": "1612772287426", + "name": "MQTT to senica-prod01", + "x": 284.75, + "y": 452, + "connections": { + "1": [ + { + "index": "0", + "id": "1729855371093" + }, + { + "index": "0", + "id": "1729855334955" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Connected", + "color": "green" + }, + "options": { + "username": "", + "clientid": "", + "port": "2764", + "host": "192.168.252.2", + "topic": "" + }, + "color": "#888600", + "notes": "" + }, + { + "id": "1731069001548", + "component": "db_init", + "tab": "1612772287426", + "name": "DB Initialization", + "x": 1003.75, + "y": 240.25, + "connections": { + "0": [ + { + "index": "0", + "id": "1731069033416" + } + ], + "1": [ + { + "index": "0", + "id": "1747561603739" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#888600", + "notes": "" + }, + { + "id": "1731069033416", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "db-init", + "x": 1244.75, + "y": 233.25, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069059135", + "component": "showdb", + "tab": "1612772287426", + "name": "Show db data", + "x": 1186.75, + "y": 821.25, + "connections": { + "0": [ + { + "index": "0", + "id": "1731069079243" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#888600", + "notes": "" + }, + { + "id": "1731069079243", + "component": "debug", + "tab": "1612772287426", + "name": "dbData", + "x": 1390.75, + "y": 870.25, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1731069116691", + "component": "trigger", + "tab": "1612772287426", + "name": "settings", + "x": 934.75, + "y": 669.75, + "connections": { + "0": [ + { + "index": "0", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069131637", + "component": "trigger", + "tab": "1612772287426", + "name": "relaysData", + "x": 876.75, + "y": 733.75, + "connections": { + "0": [ + { + "index": "1", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069137374", + "component": "trigger", + "tab": "1612772287426", + "name": "nodesData", + "x": 852.75, + "y": 794.75, + "connections": { + "0": [ + { + "index": "2", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069179846", + "component": "trigger", + "tab": "1612772287426", + "name": "pinsData", + "x": 850.75, + "y": 861.75, + "connections": { + "0": [ + { + "index": "3", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069192937", + "component": "trigger", + "tab": "1612772287426", + "name": "sample data", + "x": 857.75, + "y": 928.75, + "connections": { + "0": [ + { + "index": "4", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731069264443", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 63.75, + "y": 1279, + "connections": { + "0": [ + { + "index": "0", + "id": "1634488120710" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069334626", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "db-init", + "x": 172.88333129882812, + "y": 129, + "connections": { + "0": [ + { + "index": "0", + "id": "1619515097737" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069548145", + "component": "virtualwirein", + "tab": "1611921777196", + "name": "db-init", + "x": 46.75, + "y": 192, + "connections": { + "0": [ + { + "index": "0", + "id": "1699965957410" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731069567152", + "component": "virtualwirein", + "tab": "1611921777196", + "name": "db-init", + "x": 44.75, + "y": 465, + "connections": { + "0": [ + { + "index": "0", + "id": "1700411878636" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731070156936", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "db-init", + "x": 126.88333129882812, + "y": 1377, + "connections": { + "0": [ + { + "index": "2", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1731234189516", + "component": "trigger", + "tab": "1612772287426", + "name": "monitor.txt", + "x": 882.75, + "y": 991.75, + "connections": { + "0": [ + { + "index": "5", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1731234189551", + "component": "trigger", + "tab": "1612772287426", + "name": "err.txt", + "x": 904.75, + "y": 1053.75, + "connections": { + "0": [ + { + "index": "6", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1732700042559", + "component": "nodesdb_change_check", + "tab": "1612772287426", + "name": "Nodes DB change check", + "x": 266.8833312988281, + "y": 1980.2333984375, + "connections": { + "0": [ + { + "index": "0", + "id": "1732700071298" + }, + { + "index": "0", + "id": "1732700642917" + } + ], + "1": [ + { + "index": "0", + "id": "1759958914348" + }, + { + "index": "0", + "id": "1759959003114" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#888600", + "notes": "" + }, + { + "id": "1732700057052", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 76.75, + "y": 1988, + "connections": { + "0": [ + { + "index": "0", + "id": "1732700042559" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1732700071298", + "component": "debug", + "tab": "1612772287426", + "name": "nodesChange", + "x": 571.8833312988281, + "y": 2018.2333984375, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1732700642917", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "tb-push", + "x": 567.8833312988281, + "y": 1933, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1732889185927", + "component": "debug", + "tab": "1611921777196", + "name": "tempToDido", + "x": 594.8833312988281, + "y": 753, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1733574412965", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 72.75, + "y": 474, + "connections": { + "0": [ + { + "index": "1", + "id": "1731068754606" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1747561603739", + "component": "virtualwireout", + "tab": "1612772287426", + "name": "send-to-services", + "x": 1243.8833312988281, + "y": 334.5, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1747562867845", + "component": "comment", + "tab": "1612772287426", + "name": "FLOW STARTING POINT", + "x": 1003.5666656494141, + "y": 178, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#704cff", + "notes": "" + }, + { + "id": "1749211698385", + "component": "trigger", + "tab": "1612772287426", + "name": "deviceStatus", + "x": 911.75, + "y": 1116.75, + "connections": { + "0": [ + { + "index": "7", + "id": "1731069059135" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1757006030239", + "component": "httprequest", + "tab": "1615551125555", + "name": "192.168.252.2:8015/daily_report", + "x": 756.5666656494141, + "y": 715.4499969482422, + "connections": { + "0": [ + { + "index": "0", + "id": "1757006045804" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "stringify": "json", + "method": "POST", + "url": "http://192.168.252.2:8015/daily_report" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1757006045804", + "component": "debug", + "tab": "1615551125555", + "name": "ddd", + "x": 1091.566665649414, + "y": 711.4499969482422, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1757006060377", + "component": "debug", + "tab": "1615551125555", + "name": "reportDebug", + "x": 749.5666656494141, + "y": 799.4499969482422, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1759958914348", + "component": "httprequest", + "tab": "1612772287426", + "name": "http://192.168.252.2:8015/node_numbers", + "x": 571, + "y": 2111, + "connections": { + "0": [ + { + "index": "0", + "id": "1759958927094" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "stringify": "json", + "method": "POST", + "url": "http://192.168.252.2:8015/node_numbers" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1759958927094", + "component": "debug", + "tab": "1612772287426", + "name": "nodesChangeCloud", + "x": 951.8833312988281, + "y": 2109.2333984375, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1759959003114", + "component": "debug", + "tab": "1612772287426", + "name": "nodeChangeCloud1", + "x": 574, + "y": 2218, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1760020290879", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "db-init", + "x": 84.75, + "y": 1787, + "connections": { + "0": [ + { + "index": "1", + "id": "1718016052341" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "db-init", + "color": "gray" + }, + "options": { + "wirename": "db-init" + }, + "color": "#303E4D", + "notes": "" + } + ], + "version": 615 +} diff --git a/RVO53/flow/dido_controller.js b/RVO53/flow/dido_controller.js new file mode 100755 index 0000000..d16fb19 --- /dev/null +++ b/RVO53/flow/dido_controller.js @@ -0,0 +1,1486 @@ +exports.id = 'dido_controller'; +exports.title = 'DIDO_Controller'; +exports.version = '2.0.0'; +exports.group = 'Worksys'; +exports.color = '#2134B0'; +exports.input = 3; +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 + +state_of_main_switch - reportovat stav hlaveho istica : 0-> off 1-> on +rotary_switch_state - sem by sa mal reportovat stav vstupov manual a auto pola nasledovnej logiky: Manual = 1 a Auto = 0 -> Manu +Manual = 0 a Auto = 0 -> Off, Manual = 0 a Auto = 1 -> Automatic + +door_condition - pin 6, dverový kontakt -> 1 -> vyreportuje Closed, 0 -> vyreportuje Ope +twilight_sensor - hodnotu, ktoru vracia ten analogovy vstup (17) treba poslat sem ako float number. Zrejme tu potom pridame nejaky koeficient prevodu na luxy + +Na kazdu liniu +state_of_breaker - podla indexu istica sa reportuje jeho stav, teda istic na liniu 1: 0-> off, 1-> on +state_of_contactor - podla indexu stkaca sa reportuje jeho stav, teda stykac 1 na liniu 1: 0-> off, 1-> on +*/ + +const { errLogger, logger, monitor } = require('./helper/logger'); +const SerialPort = require('serialport'); +const WebSocket = require('ws'); +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 errorHandler = require('./helper/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 hasMainSwitch; + +let alarmStatus = "OFF"; + +const SEND_TO = { + debug: 0, + tb: 1, + cmd_manager: 2 +} + + +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 = {}; + let rsPortReceivedData = []; + + //to be able to get proper twilight values + let twilight_sensor_interval = 5;//minutes + let twilight_sensor = []; + const twilight_sensor_array = []; + let twilightError = false; + + monitor.info("DIDO_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-we make it global to see it from outside + FLOW.deviceStatus = { //key is device name: temperature,.... + "state_of_main_switch": "Off", //Hlavny istic (alebo druhy dverovy kontakt) + "rotary_switch_state": "Off", //Prevadzkovy + "door_condition": "closed", //Dverový kontakt + "em": "OK", //elektromer rvo + "temperature": "OK", //templomer + "battery": "OK", //Bateria + "power_supply": "OK", //Zdroj + "master_node": "OK", //MN - GLOBALS.settings.masterNodeIsResponding + "no_voltage": "OK", //GLOBALS.settings.no_voltage - vypadok napatia na faze + "state_of_breaker": {}, //"Off",//Istic + "state_of_contactor": {}, //"Off",//Stykac + "twilight_sensor": "OK" //lux sensor + }; + let deviceStatus = FLOW.deviceStatus; + + + function main() { + + GLOBALS = FLOW.GLOBALS; + SETTINGS = FLOW.GLOBALS.settings; + rvoTbName = SETTINGS.rvoTbName; + pinsData = GLOBALS.pinsData; + relaysData = GLOBALS.relaysData; + + tbHandler = new DataToTbHandler(SEND_TO.tb); + tbHandler.setSender(exports.title); + + controller_type = SETTINGS.controller_type; //"lm" or "unipi" + hasMainSwitch = SETTINGS.has_main_switch; + + if (controller_type == "") controller_type = "lm"; + + 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, "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; + } + } + + //report RVO version relaysData[0].tbname; + let values = {}; + values["edge_fw_version"] = SETTINGS.edge_fw_version; + values["maintenance_mode"] = SETTINGS.maintenance_mode; + + sendTelemetry(values, rvoTbName); + + 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); + } + + + function handleRsPort() { + + if (rsPort) { + rsPort.removeAllListeners(); + rsPort = null; + } + + //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('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) { + if (!err) { + monitor.info(exports.title + "--->Digital in_out has been set (runSyncExec was sucessfull)"); + + turnAlarm("off"); + 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('error', err => { + let message = "Dido: rsPort error: " + err.message; + logger.debug(message); + monitor.info(message); + errorHandler.sendMessageToService(message); + }) + + rsPort.on("close", () => { + let message = "Dido: rsPort closed - reconnecting ..."; + logger.debug(message); + monitor.info(message); + setTimeout(handleRsPort, 1000); + }) + + rsPort.open(); + } + + + function handleWebSocket() { + + if (ws) { + ws.removeAllListeners(); + ws = null; + } + + //to keep websocket opened, we send request every 150 seconds + let startRequests = null; + + console.log("handleWebSocket function called"); + ws = new WebSocket('ws:/0.0.0.0:1234/ws'); + + ws.onopen = function open() { + + instance.send(0, exports.title + " running"); + turnAlarm("off"); + + initialSetting(); + + setTimeout(function() { ws.send(JSON.stringify({ cmd: "all" })) }, 5000); + // we request dev info about neuron device from evok to keep websocket connection alive + // for some reason this request returns no data, but connection keeps alive + startRequests = setInterval(() => { + ws.send(JSON.stringify({ "cmd": "filter", "dev": ["neuron"] })); + }, 150000) + }; + + + // 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 = async 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; + + 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 => { + logger.debug('Dido: websocket error', err); + }) + + ws.onclose = function() { + logger.debug('Dido: websocket onclose, reconnecting...') + clearInterval(startRequests); + setTimeout(handleWebSocket, 1000); + } + } + + 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 turnAlarm(onOrOff) { + let value = 0; + if (onOrOff == "on") value = 1; + + if (value == 1 && SETTINGS.maintenance_mode) return; + + alarmStatus = "OFF"; + if (value == 1) alarmStatus = "ON"; + + if (rsPort) { + let arr = [0x55]; + arr.push(13); + arr.push(0); + arr.push(value); + + rsPort.write(Buffer.from(arr), function(err) { + logger.debug(`sirena - ${onOrOff}`); + }); + } + else if (ws) { + let cmd = { "cmd": "set", "dev": "relay", "circuit": "1_01", "value": value }; + ws.send(JSON.stringify(cmd)); + logger.debug(`sirena - ${onOrOff}`); + } + } + + + 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") { + bits.push(0); + } + else bits.push(1); + + if (deviceStatus["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); + } + + + // turn line on or off + function turnLine(onOrOff, line, pin, force, info) { + //onOrOff => "on" or "off" + let value = 0; + if (onOrOff == "on") value = 1; + + if (force == undefined) force = false; + + if (line == 0) { + if (value == 1 && alarmStatus == "ON") turnAlarm("off"); + SETTINGS.maintenance_mode = value ? true : false; + + 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); + return; + } + + if (pin === undefined) pin = getPin(line); + + if (pin === undefined) { + errLogger.error("pin is undefined!", line); + return; + } + + if (!force) { + if (relaysData[line].contactor == value) { + instance.send(SEND_TO.debug, `line is already ${onOrOff} ` + line); + logger.debug(`Dido: turnLine: line is already ${onOrOff} `, line); + return; + } + } + + // if(!rsPort.isOpen && !ws) + if (!rsPort && !ws) { + errLogger.error("Dido - port or websocket is not opened"); + return; + } + + if (rsPort) { + let arr = [0x55]; + arr.push(pin); + arr.push(0); + arr.push(value); + + rsPort.write(Buffer.from(arr), function(err) { + if (err === undefined) { + monitor.info(`Dido: turnLine ${onOrOff} zapisal do rsPort-u`, line, pin, arr, info); + switchLogic(arr); + } + else { + monitor.info(`Dido: turnLine ${onOrOff} WRITE error`, err); + } + }); + + } + else if (ws) { + //pin = "relay1_03" or "input1_01" ... we must make just "1_01" with slice method + monitor.info(`Dido: turnLine ${onOrOff} - (line, pin, force)`, line, pin, force, info); + let cmd = { "cmd": "set", "dev": "relay", "circuit": pin.slice(5), "value": value }; + ws.send(JSON.stringify(cmd)); + } + + //if rvo is 24/7, it has just one switching profile point at 13:00. we do not want to send notification as it repeats every day. + //const d = new Date(); + //if(d.getHours() != 13) sendNotification("Dido_controller: ", SETTINGS.rvoTbName, "switching_profile_point_applied_to_line", { line: line, value: onOrOff }, "", SEND_TO.tb, instance); + } + + + // 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; + + // 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) { + const status = flowdata.data.status; + if (status == "NOK-twilight_sensor") { + deviceStatus["twilight_sensor"] = "NOK"; + } + else if (status == "NOK-em340" || status == "NOK-em111") { + deviceStatus["em"] = "NOK"; + } + else if (status == "NOK-thermometer") { + deviceStatus["temperature"] = "NOK"; + } + } + else if ("values" in flowdata.data) { + 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" + } + else if (values.hasOwnProperty("temperature")) { + deviceStatus["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"; + } + + sendTelemetry(values, rvoTbName); + } + + sendRvoStatus(); + }) + + + + + // we expect array as flowdata.data + instance.on("1", flowdata => { + + //console.log(flowdata.data); + + if (!flowdata.data instanceof Object) return; + + let obj = flowdata.data; + let line = obj.line; + 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"); + }) + + + function calculateStateCode() { + + let bits = []; + + //Hlavny istic - state_of_main_switch => v rvo senica je to druhy door pre silovu cast (EM) + if (deviceStatus["state_of_main_switch"] === "closed" || deviceStatus["state_of_main_switch"] === "Off") { + bits.push(0); + } + else { + bits.push(1); + } + + //Prevadzkovy mod - Manual, Off, Automatic, maintenance_mode = true/false // DAVA 2 BITY + if (!SETTINGS.maintenance_mode) { + if (deviceStatus["rotary_switch_state"] === "Manual") { + bits.push(0); + bits.push(1); + } + + if (deviceStatus["rotary_switch_state"] === "Automatic") { + bits.push(0); + bits.push(0); + } + + if (deviceStatus["rotary_switch_state"] === "Off") { + bits.push(1); + bits.push(0); + } + } + else { + bits.push(1); + bits.push(1); + } + + //Dverovy kontakt + if (deviceStatus["door_condition"] === "closed") { + bits.push(0); + } + else { + bits.push(1); + } + + //EM + if (deviceStatus["em"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //Teplomer + if (deviceStatus["temperature"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //Batéria + if (deviceStatus["battery"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //Zdroj + if (deviceStatus["power_supply"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //MN + if (deviceStatus["master_node"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + //výpadok napätia na fáze + if (deviceStatus["no_voltage"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + if (deviceStatus["twilight_sensor"] === "NOK") { + bits.push(1); + } + else { + bits.push(0); + } + + // doplnime do 16 bitov (2 byty) + for (let i = bits.length; i < 16; i++) { + bits.push(0); + } + + // console.log("calculateStateCode - deviceStatus", deviceStatus); + // 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; + } + + + async function sendRvoStatus() { + + if (SETTINGS === undefined) return; + SETTINGS.masterNodeIsResponding ? deviceStatus["master_node"] = "OK" : deviceStatus["master_node"] = "NOK"; + + 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 pinsForRvoStatus(controllerType, hasMainSwitch) { + + let pins = []; + + if (controllerType === "lm") { + pins = [1, 4, 6]; + if (hasMainSwitch === 1) { + pins = [4, 6]; + } + } else if (controllerType === "unipi") { + pins = ["input1_01", "input1_04", "input1_05"]; + if (hasMainSwitch === 1) { + pins = ["input1_01", "input1_04"]; + } + } + + return pins; + } + + + function checkRvoStatus() { + + // 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 + //set RVO state + let status = "OK"; + + for (const [key, value] of Object.entries(deviceStatus)) { + if (["em", "twilight_sensor", "temperature", "master_node"].includes(key) && value === "NOK") status = "NOK"; + } + + if (status === "OK") { + + let pinIndexes = pinsForRvoStatus(controller_type, hasMainSwitch); + + for (const pinIndex of pinIndexes) { + if (previousValues[pinIndex] === 0) { + if ((pinIndex === 6 || pinIndex === 'input1_01' || pinIndex === 'input1_05') && SETTINGS.maintenance_mode) continue; + status = "NOK"; + break; + } + } + } + + // battery status. If value is 1 - battery is NOK + if (previousValues[5] === 1) status = "NOK"; + if (SETTINGS.no_voltage.size > 0) status = "NOK"; + + // console.log("rvo status",status) + return status; + } + + + // we pass array to function in case of rsPort ==> switchLogic([55,3,0,1]) ==> [[55,3,0,1]] + // we pass two values in case of websocket ==> switchLogic("relay1_03",1) ==> ["relay1_03",1] + const switchLogic = (...args) => { + + let values = {}; + let pinIndex, newPinValue, twilight; + + //data from rsPort + if (args.length == 1) { + pinIndex = args[0][1] + 1; + if (pinIndex === 17) pinIndex--; + newPinValue = args[0][3]; + twilight = args[0][2]; + } + //data from websocket + else { + pinIndex = args[0]; + newPinValue = args[1]; + } + + 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; + + //default value + let value = "On"; + if (newPinValue === 0) value = "Off"; + + //Hlavny istic + if (type === "state_of_main_switch" && hasMainSwitch) { + if (newPinValue === 0 && newPinValue !== previousValues[pinIndex]) { + sendNotification("switchLogic", rvoTbName, "main_switch_has_been_turned_off", {}, "", SEND_TO.tb, instance, "state_of_main_switch"); + 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"); + deviceStatus["state_of_main_switch"] = "On"; + } + } + + //Prevadzkovy mod + 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"; + + deviceStatus["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, "power_supply_has_disconnected_input", {}, "", SEND_TO.tb, instance, "power_supply"); + + deviceStatus["power_supply"] = "NOK"; + } + else if (newPinValue === 1 && newPinValue !== previousValues[pinIndex]) { + sendNotification("switchLogic", rvoTbName, "power_supply_works_correctly", {}, "", SEND_TO.tb, instance, "power_supply"); + + deviceStatus["power_supply"] = "OK"; + } + } + + //Bateria - 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"); + + deviceStatus["battery"] = "NOK"; + } + else if (newPinValue === 0 && newPinValue !== previousValues[pinIndex]) { + sendNotification("switchLogic", rvoTbName, "battery_level_is_ok", {}, "", SEND_TO.tb, instance, "battery_level"); + + deviceStatus["battery"] = "OK"; + } + } + + //Dverovy kontakt - pin 6 + //! Ak je rvo s dvoma dverovymi kontaktami, ked pride z evoku signal z input1_05, co bol predytm "state_of_main switch" handlujeme ho teraz ako 'door_condition' + else if (type == "door_condition" || type === "state_of_main_switch") { + newPinValue === 0 ? value = "open" : value = "closed"; + + let door = "door_main"; + if (type === "state_of_main_switch") door = "door_em"; + + if (value === "open") { + if (SETTINGS.maintenance_mode) { + sendNotification("switchLogic", rvoTbName, door + "_open", {}, "", SEND_TO.tb, instance, door); + } else { + sendNotification("switchLogic", rvoTbName, door + "_open_without_permission", {}, "", SEND_TO.tb, instance, door); + + // 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 (value === "closed") { + if (alarmStatus == "ON") turnAlarm("off"); + sendNotification("switchLogic", rvoTbName, door + "_close", {}, "", SEND_TO.tb, instance, door); + } + + deviceStatus[type] = value; + } + + //lux sensor + else if (type == "twilight_sensor") { + //! TODO - to show nok status, if lux value is not changing more then 10 times. + //Daylight is far more than 1000. So most of the day, when it is sunshine comes just value 1000. But lux sensor is not NOK. + //This is not the case in LM. If value from LM is the same 10x, there is 99% possibility, that sensor is NOK. + value = newPinValue; + + if (controller_type === 'lm') { + value = parseFloat(newPinValue + (256 * twilight)); + + 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 && !twilightError) { + twilightError = true; + let value = twilight_sensor_array.shift(); + + newPinValue = 0; + } + else if (set.size !== 1 && twilightError) { + //sendNotification("switchLogic", rvoTbName, 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) { + 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); + } + } + + 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); + } + + deviceStatus["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 (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 }); + + //mame iba 3 istice. vyreportujeme a ohandlujeme liniu na tom istom istici ako paralelna linia (napr linia 1, paralelna s nou je linia 4, key je string "4") + // ak je 7 linii, na 1 istici je linia 1,4,7 + + if (line == 1) { + + const lineOnSameBraker = [4, 7]; + + for (var i = 0; i < lineOnSameBraker.length; i++) { + if (!relaysData.hasOwnProperty(lineOnSameBraker[i])) continue; + + 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; + reportLineStatus(lineOnSameBraker[i]); + + values[type] = value; + const tbname = relaysData[lineOnSameBraker[i]].tbname; + sendTelemetry(values, tbname); + + delete values[type]; + } + + } + else { + const lineOnSameBraker = line + 3 + ""; + + if (relaysData.hasOwnProperty(lineOnSameBraker)) { + 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; + reportLineStatus(line + 3); + + values[type] = value; + const tbname = relaysData[lineOnSameBraker].tbname; + sendTelemetry(values, tbname); + + delete values[type]; + } + } + + } + + if (value == "Off") values["status"] = "NOK"; + deviceStatus["state_of_breaker"][line] = value; + + reportLineStatus(line); + } + else return; + + values[type] = value; + + if (type == "rotary_switch_state") { + if (SETTINGS.maintenance_mode) value = "maintenance"; + value = value.toLowerCase(); + values["power_mode"] = value; + } + + if (newPinValue != previousValues[pinIndex]) previousValues[pinIndex] = newPinValue; + if (Object.keys(values).length > 0 && tbname) sendTelemetry(values, tbname); + } + + + function sendTelemetry(values, tbname, date = Date.now()) { + let dataToTb = { + [tbname]: [ + { + "ts": date, + "values": values + } + ] + }; + + tbHandler.sendToTb(dataToTb, instance); + } + + + function isObject(item) { + return (typeof item === "object" && !Array.isArray(item) && item !== null); + } + +} //end of 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 +// *|input1_01|state_of_main_switch|0|........... +// *|input1_02|rotary_switch_state|0|........... +// *|input1_03|rotary_switch_state|0|........... +// *|intut1_04|power_supply|0|........... +// *|input1_05|door_condition|0|........... +// *|input1_06|state_of_breaker|1|........... +// *|input1_07|state_of_breaker|2|........... +// *|input1_08|state_of_breaker|3|........... +// *|relay1_02|state_of_contactor|1|........... +// *|relay1_03|state_of_contactor|2|........... +// *|relay1_04|state_of_contactor|3|........... +// *|287D8776E0013CE9|temperature|0|........... + + +//! pins_data --> from UNIPI +// { +// 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 } +// } + +//! relays_data +// { +// '0': { +// line: 0, +// tbname: 'KjbN4q7JPZmexgdnz2yKQ98YAWwO0Q3BMX6ERLoV', +// contactor: 1, +// profile: '' +// }, +// '1': { +// line: 1, +// tbname: 'RMgnK93rkoAazbqdQ4yBG95Z1YXGx6pmwBeVEP2O', +// contactor: 0, +// profile: '{"intervals":[{"value":0,"end_time":"20:00","start_time":"13:00"},{"value":1,"end_time":"10:00","start_time":"20:00"},{"value":0,"end_time":"10:20","start_time":"10:00"},{"value":1,"end_time":"10:40","start_time":"10:20"},{"value":0,"end_time":"11:00","start_time":"10:40"},{"value":1,"end_time":"11:30","start_time":"11:00"},{"value":0,"end_time":"11:50","start_time":"11:30"},{"value":1,"end_time":"13:00","start_time":"11:50"}],"astro_clock":false,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' +// }, +// '2': { +// line: 2, +// tbname: 'dlE1VQjYrNx9gZRmb38gG08oLBO4qaAk2M6JPnG7', +// contactor: 0, +// profile: '{"intervals":[{"value":0,"end_time":"20:00","start_time":"13:00"},{"value":1,"end_time":"10:00","start_time":"20:00"},{"value":0,"end_time":"10:20","start_time":"10:00"},{"value":1,"end_time":"10:40","start_time":"10:20"},{"value":0,"end_time":"11:00","start_time":"10:40"},{"value":1,"end_time":"11:30","start_time":"11:00"},{"value":0,"end_time":"11:50","start_time":"11:30"},{"value":1,"end_time":"13:00","start_time":"11:50"}],"astro_clock":false,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' +// }, +// '3': { +// line: 3, +// tbname: 'vnmG4kJxaXWNBgMQq0D7Aj5e9oZzOAlr6LdR3w2V', +// contactor: 0, +// profile: '{"intervals":[{"value":0,"end_time":"20:30","start_time":"13:00"},{"value":1,"end_time":"00:10","start_time":"20:30"},{"value":0,"end_time":"13:00","start_time":"05:40"},{"value":1,"end_time":"05:40","start_time":"00:10"}],"astro_clock":true,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' +// } +// } + + + + + +// { +// "jbN4q7JPZmexgdnz2yKbWGDYAWwO0Q3BMX6ERLoV": [ +// { +// "ts": 1700409326353, +// "values": { +// "_event": { +// "type": "notice", +// "status": "new", +// "source": { +// "func": "rsPort.open()", +// "component": "1700343402190", +// "component_name": "DIDO_Controller", +// "edge": "jbN4q7JPZmexgdnz2yKbWGDYAWwO0Q3BMX6ERLoV" +// }, +// "message": "al_shariff_10.0.0.38: FLOW has been started ", +// "message_data": "" +// } +// } +// } +// ] +// } diff --git a/RVO53/flow/helper/DataToTbHandler.js b/RVO53/flow/helper/DataToTbHandler.js new file mode 100755 index 0000000..716ef7b --- /dev/null +++ b/RVO53/flow/helper/DataToTbHandler.js @@ -0,0 +1,187 @@ +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; + this.itIsNodeReadout = false; + this.sender = ""; + + // if attribute change difference is less than limit value, we do not send to tb. + this.attributeChangeLimit = { + temperature: 0.5, + Phase_1_voltage: 2, + Phase_2_voltage: 2, + Phase_3_voltage: 2, + Phase_1_current: 0.1, + Phase_2_current: 0.1, + Phase_3_current: 0.1, + Phase_1_power: 2, + Phase_2_power: 2, + Phase_3_power: 2, + total_power: 2, + total_energy: 1, + Phase_1_pow_factor: 0.1, + Phase_2_pow_factor: 0.1, + Phase_3_pow_factor: 0.1, + power_factor: 0.1, + lifetime: 2, + voltage: 2, + power: 2, + frequency: 3, + energy: 0.1, + current: 2, + inclination_x: 10, + inclination_y: 10, + inclination_z: 10 + }; + + } + + dump() { + console.log("----------------------------"); + console.log("previousValues", this.previousValues); + console.log("----------------------------"); + } + + setSender(sender) { + this.sender = sender; + } + + isEmptyObject(obj) { + for (var _ in obj) { + return false; + } + return true; + } + + + sendToTb(data, instance) { + + //not to modify data object, we do deep copy: + let dataCopy = JSON.parse(JSON.stringify(data)); + + let keys = Object.keys(dataCopy); + + if (keys.length == 0) { + if (this.debug) console.log("sendToTb received empty object", dataCopy); + return; + } + + let tbname = keys[0]; + let ts; + + let arrayOfValues = dataCopy[tbname]; + let arrayOfValuesToSend = []; + + for (let i = 0; i < arrayOfValues.length; i++) { + + ts = arrayOfValues[i].ts; + let values = this.prepareValuesForTb(tbname, ts, arrayOfValues[i].values); + + if (!this.isEmptyObject(values)) { + arrayOfValuesToSend.push({ ts: ts, values: values }); + } + + } + + if (arrayOfValuesToSend.length == 0) { + //if(this.debug) console.log("data not sent - empty array"); + return; + } + + this.messageCounter++; + + let dataToTbModified = { + [tbname]: arrayOfValuesToSend + } + + //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); + instance.send(this.index, dataToTbModified); + } + + + getDiffTimestamp(key) { + //TODO set different value for given key!!! + //if(key == "status") this.timeToHoldTbValue = 2*60*60;//2h + return this.timeToHoldTbValue * 1000; + } + + + prepareValuesForTb(tbname, timestamp, values) { + + let keys = Object.keys(values); + + if (keys.includes("lifetime")) this.itIsNodeReadout = true; + + if (!this.previousValues.hasOwnProperty(tbname)) { + this.previousValues[tbname] = {}; + } + + //if(this.debug) console.log("prepareValuesForTb", tbname, timestamp, values); + + for (let i = 0; i < keys.length; i++) { + + let key = keys[i]; + let value = values[key]; + + if (!this.previousValues[tbname].hasOwnProperty(key)) { + this.previousValues[tbname][key] = { ts: timestamp, value: value }; + continue; + } + + // attributeData ==> {voltage: {ts:333333, value:5}} + let attributeData = this.previousValues[tbname][key]; + let attributeToChange = false; + if (key in this.attributeChangeLimit) attributeToChange = true; + let limit = this.attributeChangeLimit[key]; + let timestampDiffToRemoveKey; + + //this will ensure "node statecode" will be sent just once an hour + if (this.itIsNodeReadout && key === "statecode") { + attributeData.value = value; + this.itIsNodeReadout = false; + timestampDiffToRemoveKey = 1 * 60 * 60 * 1000; // 1 hour + } + + if (key === "twilight_sensor" && value > 100) { + attributeData.value = value; + } + + //if edge, master or node version do not change, send just once a day: + if (["edge_fw_version", "master_node_version", "fw_version"].includes(key)) { + timestampDiffToRemoveKey = 24 * 60 * 60 * 1000; + } + + if (attributeData.value === value || attributeToChange && Math.abs(attributeData.value - value) < limit) { + + let diff = timestamp - attributeData.ts; + if (!timestampDiffToRemoveKey) timestampDiffToRemoveKey = this.getDiffTimestamp(key); + + if (diff > timestampDiffToRemoveKey) { + attributeData.ts = Date.now(); + //if(this.debug) console.log(this.sender + ": update ts for key", key, "diff is", diff, "messageCounter", this.messageCounter); + } + else { + delete values[key]; + //if(this.debug) console.log(this.sender + ": delete key", key, "diff is", diff, "messageCounter", this.messageCounter, timestampDiffToRemoveKey); + } + } + else { + attributeData.value = value; + attributeData.ts = timestamp; + } + + } + + return values; + } +} + +module.exports = DataToTbHandler; + diff --git a/RVO53/flow/helper/ErrorToServiceHandler.js b/RVO53/flow/helper/ErrorToServiceHandler.js new file mode 100755 index 0000000..2b27c32 --- /dev/null +++ b/RVO53/flow/helper/ErrorToServiceHandler.js @@ -0,0 +1,91 @@ +const { MD5 } = require('./md5.js'); +const { networkInterfaces } = require('os'); + +class ErrorToServiceHandler { + constructor() { + this.previousValues = {}; + + this.project_id = undefined; + + const nets = networkInterfaces(); + this.ipAddresses = {}; + + for (const name of Object.keys(nets)) { + for (const net of nets[name]) { + // Skip over non-IPv4 and internal (i.e. 127.0.0.1) addresses + if (net.family === 'IPv4' && !net.internal) { + if (!this.ipAddresses[name]) { + this.ipAddresses[name] = []; + } + this.ipAddresses[name].push(net.address); + } + } + } + } + + setProjectId(project_id) { + this.project_id = project_id; + } + + processMessage(message, seconds) { + if (Array.isArray(message)) message = message.join(', '); + + let key = MD5(message); + let ts = Date.now(); + + //keep in memory - default value is 1h + if (seconds === undefined) seconds = 60 * 60; + + if (!this.previousValues.hasOwnProperty(key)) { + this.previousValues[key] = { ts: ts, duration: seconds }; + } + + let diff = (ts - this.previousValues[key].ts); + if (diff < this.previousValues[key].duration * 1000) return false; + + this.previousValues[key].ts = ts; + + return message; + } + + sendMessageToService(message, seconds, message_type) { + + // if error occures too early FLOW.GLOBALS.settings.project_id is still undefined + if (this.project_id === undefined) { + console.log("ErrorToServiceHandler.js: no project_id"); + return; + } + + let f = this.processMessage(message, seconds); + if (f === false) return; + + if (message_type === undefined) message_type = "error_message"; + + let toService = { + id: this.project_id, + ipAddresses: this.ipAddresses + }; + + //js_error || error_message + toService[message_type] = message; + + console.log("ErrorToServiceHandler------------------------>send to service", toService); + + RESTBuilder.make(function(builder) { + builder.method('POST'); + builder.post(toService); + builder.url('http://192.168.252.2:8004/sentmessage'); + + builder.callback(function(err, response, output) { + console.log("process.on error send", err, response, output, toService); + }); + }); + + } +} + +const errorHandler = new ErrorToServiceHandler(); + + +module.exports = errorHandler; +//module.exports = ErrorToServiceHandler; diff --git a/RVO53/flow/helper/db_helper.js b/RVO53/flow/helper/db_helper.js new file mode 100755 index 0000000..40e796c --- /dev/null +++ b/RVO53/flow/helper/db_helper.js @@ -0,0 +1,44 @@ +function promisifyBuilder(builder) +{ + return new Promise((resolve, reject) => { + + try{ + + builder.callback(function(err, response) { + + if(err != null) reject(err); + resolve(response); + }); + + } catch (error) { + reject(error); + } + }) +} + +function makeMapFromDbResult(response, ...keys) +{ + let s = "-"; + let data = {}; + + for(let i = 0; i < response.length; i++) + { + let record = response[i]; + + let k = []; + for(let j = 0; j < keys.length; j++) + { + k.push( record[keys[j]] ); + } + + let key = k.join(s); + data[ key ] = record; + } + + return data; +} + +module.exports = { + promisifyBuilder, + makeMapFromDbResult + } \ No newline at end of file diff --git a/RVO53/flow/helper/logger.js b/RVO53/flow/helper/logger.js new file mode 100755 index 0000000..2585639 --- /dev/null +++ b/RVO53/flow/helper/logger.js @@ -0,0 +1,30 @@ +//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/RVO53/flow/helper/md5.js b/RVO53/flow/helper/md5.js new file mode 100755 index 0000000..d3b0480 --- /dev/null +++ b/RVO53/flow/helper/md5.js @@ -0,0 +1,5 @@ +function MD5(d){var r = M(V(Y(X(d),8*d.length)));return r.toLowerCase()};function M(d){for(var _,m="0123456789ABCDEF",f="",r=0;r>>4&15)+m.charAt(15&_);return f}function X(d){for(var _=Array(d.length>>2),m=0;m<_.length;m++)_[m]=0;for(m=0;m<8*d.length;m+=8)_[m>>5]|=(255&d.charCodeAt(m/8))<>5]>>>m%32&255);return _}function Y(d,_){d[_>>5]|=128<<_%32,d[14+(_+64>>>9<<4)]=_;for(var m=1732584193,f=-271733879,r=-1732584194,i=271733878,n=0;n>16)+(_>>16)+(m>>16)<<16|65535&m}function bit_rol(d,_){return d<<_|d>>>32-_} + +module.exports = { + MD5 +} \ No newline at end of file diff --git a/RVO53/flow/helper/notification_reporter.js b/RVO53/flow/helper/notification_reporter.js new file mode 100755 index 0000000..839c12c --- /dev/null +++ b/RVO53/flow/helper/notification_reporter.js @@ -0,0 +1,121 @@ +//key is device, value = message {} +let sentValues = {}; +let notificationsData = null; +let rvoName; + +//sendNotification("CMD Manager: process cmd", SETTINGS.rvoTbName, "dimming_profile_was_successfully_received_by_node", { node: node }, "", SEND_TO.tb, instance); + +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 +}; + +function getKey(map, val) { + return Object.keys(map).findItem(key => map[key] === val); +} + +//https://stackoverflow.com/questions/41117799/string-interpolation-on-variable +var template = (tpl, args) => tpl.replace(/\${(\w+)}/g, (_, v) => args[v]); + + +function initNotification() { + notificationsData = FLOW.GLOBALS.notificationsData; + rvoName = FLOW.GLOBALS.settings.rvo_name; +} + + +function sendNotification(func, device, key, params, extra, tb_output, instance, saveKey) { + + let storeToSendValues = true; + if (saveKey == undefined) storeToSendValues = false; + + let weight = ""; + let message = {}; + + let notification = notificationsData[key]; + + if (notification) { + weight = notification.weight.toLowerCase(); + + Object.keys(notification).forEach(item => { + if (["en", "sk", "de", "cz", "it", "es"].includes(item)) { + message[item] = rvoName + ": " + template(notification[item], params); + } + }) + } + else { + //console.error("sendNotification: Notifications: undefined key", key, func, notificationsData); + console.error("sendNotification: Notifications: undefined key", key, func); + return false; + } + + //detect invalid err weight + if (getKey(ERRWEIGHT, weight) == undefined) { + console.error("sendNotification: Notifications: undefined weight", weight, key, func); + return false; + } + + if (sentValues.hasOwnProperty(saveKey)) { + if (JSON.stringify(sentValues[saveKey]) == JSON.stringify(message)) { + return false; + } + } + + if (sentValues[saveKey] == undefined) { + if (storeToSendValues) { + //do not send - flow is was started + sentValues[saveKey] = message; + return false; + } + } + + if (storeToSendValues) sentValues[saveKey] = message; + + let content = { + "type": weight, + "status": "new", + "source": { + "func": func, + "component": instance.id, + "component_name": instance.name, + "edge": device + }, + "message": message, + "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 + + return true; + +} + +module.exports = { + sendNotification, + ERRWEIGHT, + initNotification +} + diff --git a/RVO53/flow/helper/register.js b/RVO53/flow/helper/register.js new file mode 100755 index 0000000..fc1d008 --- /dev/null +++ b/RVO53/flow/helper/register.js @@ -0,0 +1,144 @@ +/* +0 - cislo registra / prikaz +1 - recepient - 0 = master, 1 = slave (slave je automaticky group a broadcast) +2 - r/rw - read/write +3- register name - nazov registra / prikazu (len pre info - zobrazenie v aplikacii) + +4,5,6,7, - jednotlive byte-y - nazov byte-u +4-7 - RES. a prazdny string "" sa nezobrazia!!! +*/ + +//124 zaznamov +const registers = [ + ["0","1","R","Status","","",""], + ["1","1","RW","Dimming","R-Channel ","G-Channel","B-Channel ","W - Channel"], + ["2","1","R","Device types","","",".",""], + ["3","1","RW","Group addresses 1-4","Groups Add. 4","Groups Add. 3","Groups Add. 2","Groups Add. 1"], + ["4","1","RW","Group addresses 5-8","Groups Add. 8","Groups Add. 7","Groups Add. 6","Groups Add. 5"], + ["5","1","RW","Serial number (MAC)","","","",""], + ["6","1","RW","Time of dusk","HH","MM","SS","EXTRA"], + ["7","1","RW","Time of dawn","HH","MM","SS","EXTRA"], + ["8","1","RW","Time Schedule settings","TBD","TBD","Movement sensor","Time Schedule"], + ["9","1","RW","TS1 Time point 1","HH","MM","SS","Ext. Device"], + ["10","1","RW","TS1 Time point 1 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["11","1","RW","TS1 Time point 2","HH","MM","SS","Ext. Device"], + ["12","1","RW","TS1 Time point 2 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["13","1","RW","TS1 Time point 3","HH","MM","SS","Ext. Device"], + ["14","1","RW","TS1 Time point 3 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["15","1","RW","TS1 Time point 4","HH","MM","SS","Ext. Device"], + ["16","1","RW","TS1 Time point 4 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["17","1","RW","TS1 Time point 5","HH","MM","SS","Ext. Device"], + ["18","1","RW","TS1 Time point 5 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["19","1","RW","TS1 Time point 6","HH","MM","SS","Ext. Device"], + ["20","1","RW","TS1 Time point 6 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["21","1","RW","TS1 Time point 7","HH","MM","SS","Ext. Device"], + ["22","1","RW","TS1 Time point 7 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["23","1","RW","TS1 Time point 8","HH","MM","SS","Ext. Device"], + ["24","1","RW","TS1 Time point 8 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["25","1","RW","TS1 Time point 9","HH","MM","SS","Ext. Device"], + ["26","1","RW","TS1 Time point 9 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["27","1","RW","TS1 Time point 10","HH","MM","SS","Ext. Device"], + ["28","1","RW","TS1 Time point 10 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["29","1","RW","TS1 Time point 11","HH","MM","SS","Ext. Device"], + ["30","1","RW","TS1 Time point 11 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["31","1","RW","TS1 Time point 12","HH","MM","SS","Ext. Device"], + ["32","1","RW","TS1 Time point 12 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["33","1","RW","TS1 Time point 13","HH","MM","SS","Ext. Device"], + ["34","1","RW","TS1 Time point 13 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["35","1","RW","TS1 Time point 14","HH","MM","SS","Ext. Device"], + ["36","1","RW","TS1 Time point 14 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["37","1","RW","TS1 Time point 15","HH","MM","SS","Ext. Device"], + ["38","1","RW","TS1 Time point 15 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["39","1","RW","TS1 Time point 16","HH","MM","SS","Ext. Device"], + ["40","1","RW","TS1 Time point 16 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["41","1","RW","TS2 Time point 1","HH","MM","SS","Ext. Device"], + ["42","1","RW","TS2 Time point 1 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["43","1","RW","TS2 Time point 2","HH","MM","SS","Ext. Device"], + ["44","1","RW","TS2 Time point 2 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["45","1","RW","TS2 Time point 3","HH","MM","SS","Ext. Device"], + ["46","1","RW","TS2 Time point 3 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["47","1","RW","TS2 Time point 4","HH","MM","SS","Ext. Device"], + ["48","1","RW","TS2 Time point 4 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["49","1","RW","TS2 Time point 5","HH","MM","SS","Ext. Device"], + ["50","1","RW","TS2 Time point 5 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["51","1","RW","TS2 Time point 6","HH","MM","SS","Ext. Device"], + ["52","1","RW","TS2 Time point 6 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["53","1","RW","TS2 Time point 7","HH","MM","SS","Ext. Device"], + ["54","1","RW","TS2 Time point 7 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["55","1","RW","TS2 Time point 8","HH","MM","SS","Ext. Device"], + ["56","1","RW","TS2 Time point 8 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["57","1","RW","TS2 Time point 9","HH","MM","SS","Ext. Device"], + ["58","1","RW","TS2 Time point 9 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["59","1","RW","TS2 Time point 10","HH","MM","SS","Ext. Device"], + ["60","1","RW","TS2 Time point 10 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["61","1","RW","TS2 Time point 11","HH","MM","SS","Ext. Device"], + ["62","1","RW","TS2 Time point 11 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["63","1","RW","TS2 Time point 12","HH","MM","SS","Ext. Device"], + ["64","1","RW","TS2 Time point 12 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["65","1","RW","TS2 Time point 13","HH","MM","SS","Ext. Device"], + ["66","1","RW","TS2 Time point 13 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["67","1","RW","TS2 Time point 14","HH","MM","SS","Ext. Device"], + ["68","1","RW","TS2 Time point 14 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["69","1","RW","TS2 Time point 15","HH","MM","SS","Ext. Device"], + ["70","1","RW","TS2 Time point 15 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["71","1","RW","TS2 Time point 16","HH","MM","SS","Ext. Device"], + ["72","1","RW","TS2 Time point 16 Levels","R-Channel","G-Channel","B-Channel","W - Channel"], + ["73","1","RW","Power meter status","TBD","","",""], + ["74","1","R","Input Voltage","","","",""], + ["75","1","R","Input Current","","","",""], + ["76","1","R","Input Power","","","",""], + ["77","1","R","Cos phi","","","",""], + ["78","1","R","Frequency","","","",""], + ["79","1","RW","Energy","","","",""], + ["80","1","RW","Lifetime","","","",""], + ["81","1","RW","Power on cycles (input)","","","",""], + ["82","1","RW","Power on cycles (relay)","","","",""], + ["83","1","R","Time since last power on","","","",""], + ["84","1","R","Accelerometer data","","","",""], + ["85","1","RW","GPS latitude","pos/neg","deg","min ","sec"], + ["86","1","RW","GPS longitude","pos/neg","deg","min ","sec"], + ["87","1","RW","Actual time","HH","MM","SS","RES."], + ["88","1","RW","Actual date","Day of week","Day","Month","Year"], + ["89","1","R","Production data 1","","","",""], + ["90","1","R","Production data 2","","","",""], + ["91","1","RW","Network ID","NID3","NID2","NID1","NID0"], + ["95","1","RW","Actual Lux level from cabinet","RES.","RES.","HB","LB"], + ["96","1","RW","Threshold lux level","Dusk HB","Dusk LB","Dawn HB","Dawn LB"], + ["97","1","RW","Adjust period","Dusk HB","Dusk LB","Dawn HB","Dawn LB"], + ["98","1","RW","Offset","RES.","RES.","Dusk","Dawn"], + ["99","1","RW","CCT min/max range","max-H","max-L","min-H","min-L"], + ["100","1","RW","DALI interface","Cmd ID","Add","Cmd","Resp"], + ["101","1","RW","Module FW ver","v1","v2","v3","v4"], + ["102","1","RW","Module MAC-H","unused","unused","M1","M2"], + ["103","1","RW","Module MAC-L","M3","M4","M5","M6"], + ["122","1","R","FW update status/control register","Byte3","Byte2","Byte1","Byte0"], + ["123","1","R","FW update - data index","Byte3","Byte2","Byte1","Byte0"], + ["124","1","R","FW update - data","Byte3","Byte2","Byte1","Byte0"], + ["0","0","R","Status","","","",""], + ["1","0","RW","Control register","RES.","RES.","RES.","init mode enable"], + ["2","0","R","Device types","","","",""], + ["3","0","R","Serial number (MAC)","","","",""], + ["4","0","R","Production data 1","","","",""], + ["5","0","R","Production data 2","","","",""], + ["6","0","RW","Network ID","NID3","NID2","NID1","NID0"], + ["7","0","RW","RS232 settings","param.","param.","Baudrate H","Baudrate L"], + ["8","0","R","Accelerometer data","","","",""], + ["9","0","RW","Module FW ver","v1","v2","v3","v4"], + ["10","0","RW","Module MAC-H","unused","unused","M1","M2"], + ["11","0","RW","Module MAC-L","M3","M4","M5","M6"], + ["32","0","RW","FW update status/control register","Byte3","Byte2","Byte1","Byte0"], + ["33","0","RW","FW update - data index","Byte3","Byte2","Byte1","Byte0"], + ["34","0","RW","FW update - data","Byte3","Byte2","Byte1","Byte0"], + ["125","0","RW","Debug Register","Byte3","Byte2","Byte1","Byte0"], + ["126","0","RW","Network Control Register","Byte3","Byte2","Byte1","Byte0"], + ["127","0","R","Network Status Register","Byte3","Byte2","Byte1","Byte0"], + ["128","0","RW","Node XX Serial Number Register","SER3","SER2","SER1","SER0"], + ["256","0","R","Node XX Network Status Register","","","",""] +]; + +let register = {}; + +module.exports = { + registers, + register +} \ No newline at end of file diff --git a/RVO53/flow/helper/serialport_helper.js b/RVO53/flow/helper/serialport_helper.js new file mode 100755 index 0000000..7f5920d --- /dev/null +++ b/RVO53/flow/helper/serialport_helper.js @@ -0,0 +1,99 @@ +const { exec } = require('child_process'); + +function openPort(port) { + return new Promise((resolve, reject) => { + + var callbackError = function(err) { + port.removeListener('error', callbackError); + port.removeListener('open', callbackError); + + reject(err.message); + }; + + var callbackOpen = function(data) { + port.removeListener('error', callbackError); + port.removeListener('open', callbackOpen); + + resolve("port open: ok"); + }; + + port.on('error', callbackError); + port.on('open', callbackOpen); + + port.open(); + + }) +} + +function runSyncExec(command) { + return new Promise((resolve, reject) => { + + exec(command, (error, stdout, stderr) => { + if (error == null) resolve(stdout); + reject(error); + }); + + }) +} + +async function writeData(port, data, readbytes, timeout) { + return new Promise((resolve, reject) => { + + // 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) { + + port.write(Buffer.from(data), function(err) { + if (err) { + reject(err.message); + } + }); + + 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 +} diff --git a/RVO53/flow/helper/suncalc.js b/RVO53/flow/helper/suncalc.js new file mode 100755 index 0000000..c9ca56d --- /dev/null +++ b/RVO53/flow/helper/suncalc.js @@ -0,0 +1,317 @@ +/* + (c) 2011-2015, Vladimir Agafonkin + SunCalc is a JavaScript library for calculating sun/moon position and light phases. + https://github.com/mourner/suncalc +*/ + +(function () { 'use strict'; + +// shortcuts for easier to read formulas + +var PI = Math.PI, + sin = Math.sin, + cos = Math.cos, + tan = Math.tan, + asin = Math.asin, + atan = Math.atan2, + acos = Math.acos, + rad = PI / 180; + +// sun calculations are based on http://aa.quae.nl/en/reken/zonpositie.html formulas + + +// date/time constants and conversions + +var dayMs = 1000 * 60 * 60 * 24, + J1970 = 2440588, + J2000 = 2451545; + +function toJulian(date) { return date.valueOf() / dayMs - 0.5 + J1970; } +function fromJulian(j) { return new Date((j + 0.5 - J1970) * dayMs); } +function toDays(date) { return toJulian(date) - J2000; } + + +// general calculations for position + +var e = rad * 23.4397; // obliquity of the Earth + +function rightAscension(l, b) { return atan(sin(l) * cos(e) - tan(b) * sin(e), cos(l)); } +function declination(l, b) { return asin(sin(b) * cos(e) + cos(b) * sin(e) * sin(l)); } + +function azimuth(H, phi, dec) { return atan(sin(H), cos(H) * sin(phi) - tan(dec) * cos(phi)); } +function altitude(H, phi, dec) { return asin(sin(phi) * sin(dec) + cos(phi) * cos(dec) * cos(H)); } + +function siderealTime(d, lw) { return rad * (280.16 + 360.9856235 * d) - lw; } + +function astroRefraction(h) { + if (h < 0) // the following formula works for positive altitudes only. + h = 0; // if h = -0.08901179 a div/0 would occur. + + // formula 16.4 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + // 1.02 / tan(h + 10.26 / (h + 5.10)) h in degrees, result in arc minutes -> converted to rad: + return 0.0002967 / Math.tan(h + 0.00312536 / (h + 0.08901179)); +} + +// general sun calculations + +function solarMeanAnomaly(d) { return rad * (357.5291 + 0.98560028 * d); } + +function eclipticLongitude(M) { + + var C = rad * (1.9148 * sin(M) + 0.02 * sin(2 * M) + 0.0003 * sin(3 * M)), // equation of center + P = rad * 102.9372; // perihelion of the Earth + + return M + C + P + PI; +} + +function sunCoords(d) { + + var M = solarMeanAnomaly(d), + L = eclipticLongitude(M); + + return { + dec: declination(L, 0), + ra: rightAscension(L, 0) + }; +} + + +var SunCalc = {}; + + +// calculates sun position for a given date and latitude/longitude + +SunCalc.getPosition = function (date, lat, lng) { + + var lw = rad * -lng, + phi = rad * lat, + d = toDays(date), + + c = sunCoords(d), + H = siderealTime(d, lw) - c.ra; + + return { + azimuth: azimuth(H, phi, c.dec), + altitude: altitude(H, phi, c.dec) + }; +}; + + +// sun times configuration (angle, morning name, evening name) + +var times = SunCalc.times = [ + [-0.833, 'sunrise', 'sunset' ], + [ -0.3, 'sunriseEnd', 'sunsetStart' ], + [ -6, 'dawn', 'dusk' ], + [ -12, 'nauticalDawn', 'nauticalDusk'], + [ -18, 'nightEnd', 'night' ], + [ 6, 'goldenHourEnd', 'goldenHour' ] +]; + +// adds a custom time to the times config + +SunCalc.addTime = function (angle, riseName, setName) { + times.push([angle, riseName, setName]); +}; + + +// calculations for sun times + +var J0 = 0.0009; + +function julianCycle(d, lw) { return Math.round(d - J0 - lw / (2 * PI)); } + +function approxTransit(Ht, lw, n) { return J0 + (Ht + lw) / (2 * PI) + n; } +function solarTransitJ(ds, M, L) { return J2000 + ds + 0.0053 * sin(M) - 0.0069 * sin(2 * L); } + +function hourAngle(h, phi, d) { return acos((sin(h) - sin(phi) * sin(d)) / (cos(phi) * cos(d))); } +function observerAngle(height) { return -2.076 * Math.sqrt(height) / 60; } + +// returns set time for the given sun altitude +function getSetJ(h, lw, phi, dec, n, M, L) { + + var w = hourAngle(h, phi, dec), + a = approxTransit(w, lw, n); + return solarTransitJ(a, M, L); +} + + +// calculates sun times for a given date, latitude/longitude, and, optionally, +// the observer height (in meters) relative to the horizon + +SunCalc.getTimes = function (date, lat, lng, height) { + + height = height || 0; + + var lw = rad * -lng, + phi = rad * lat, + + dh = observerAngle(height), + + d = toDays(date), + n = julianCycle(d, lw), + ds = approxTransit(0, lw, n), + + M = solarMeanAnomaly(ds), + L = eclipticLongitude(M), + dec = declination(L, 0), + + Jnoon = solarTransitJ(ds, M, L), + + i, len, time, h0, Jset, Jrise; + + + var result = { + solarNoon: fromJulian(Jnoon), + nadir: fromJulian(Jnoon - 0.5) + }; + + for (i = 0, len = times.length; i < len; i += 1) { + time = times[i]; + h0 = (time[0] + dh) * rad; + + Jset = getSetJ(h0, lw, phi, dec, n, M, L); + Jrise = Jnoon - (Jset - Jnoon); + + result[time[1]] = fromJulian(Jrise); + result[time[2]] = fromJulian(Jset); + } + + return result; +}; + + +// moon calculations, based on http://aa.quae.nl/en/reken/hemelpositie.html formulas + +function moonCoords(d) { // geocentric ecliptic coordinates of the moon + + var L = rad * (218.316 + 13.176396 * d), // ecliptic longitude + M = rad * (134.963 + 13.064993 * d), // mean anomaly + F = rad * (93.272 + 13.229350 * d), // mean distance + + l = L + rad * 6.289 * sin(M), // longitude + b = rad * 5.128 * sin(F), // latitude + dt = 385001 - 20905 * cos(M); // distance to the moon in km + + return { + ra: rightAscension(l, b), + dec: declination(l, b), + dist: dt + }; +} + +SunCalc.getMoonPosition = function (date, lat, lng) { + + var lw = rad * -lng, + phi = rad * lat, + d = toDays(date), + + c = moonCoords(d), + H = siderealTime(d, lw) - c.ra, + h = altitude(H, phi, c.dec), + // formula 14.1 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + pa = atan(sin(H), tan(phi) * cos(c.dec) - sin(c.dec) * cos(H)); + + h = h + astroRefraction(h); // altitude correction for refraction + + return { + azimuth: azimuth(H, phi, c.dec), + altitude: h, + distance: c.dist, + parallacticAngle: pa + }; +}; + + +// calculations for illumination parameters of the moon, +// based on http://idlastro.gsfc.nasa.gov/ftp/pro/astro/mphase.pro formulas and +// Chapter 48 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + +SunCalc.getMoonIllumination = function (date) { + + var d = toDays(date || new Date()), + s = sunCoords(d), + m = moonCoords(d), + + sdist = 149598000, // distance from Earth to Sun in km + + phi = acos(sin(s.dec) * sin(m.dec) + cos(s.dec) * cos(m.dec) * cos(s.ra - m.ra)), + inc = atan(sdist * sin(phi), m.dist - sdist * cos(phi)), + angle = atan(cos(s.dec) * sin(s.ra - m.ra), sin(s.dec) * cos(m.dec) - + cos(s.dec) * sin(m.dec) * cos(s.ra - m.ra)); + + return { + fraction: (1 + cos(inc)) / 2, + phase: 0.5 + 0.5 * inc * (angle < 0 ? -1 : 1) / Math.PI, + angle: angle + }; +}; + + +function hoursLater(date, h) { + return new Date(date.valueOf() + h * dayMs / 24); +} + +// calculations for moon rise/set times are based on http://www.stargazing.net/kepler/moonrise.html article + +SunCalc.getMoonTimes = function (date, lat, lng, inUTC) { + var t = new Date(date); + if (inUTC) t.setUTCHours(0, 0, 0, 0); + else t.setHours(0, 0, 0, 0); + + var hc = 0.133 * rad, + h0 = SunCalc.getMoonPosition(t, lat, lng).altitude - hc, + h1, h2, rise, set, a, b, xe, ye, d, roots, x1, x2, dx; + + // go in 2-hour chunks, each time seeing if a 3-point quadratic curve crosses zero (which means rise or set) + for (var i = 1; i <= 24; i += 2) { + h1 = SunCalc.getMoonPosition(hoursLater(t, i), lat, lng).altitude - hc; + h2 = SunCalc.getMoonPosition(hoursLater(t, i + 1), lat, lng).altitude - hc; + + a = (h0 + h2) / 2 - h1; + b = (h2 - h0) / 2; + xe = -b / (2 * a); + ye = (a * xe + b) * xe + h1; + d = b * b - 4 * a * h1; + roots = 0; + + if (d >= 0) { + dx = Math.sqrt(d) / (Math.abs(a) * 2); + x1 = xe - dx; + x2 = xe + dx; + if (Math.abs(x1) <= 1) roots++; + if (Math.abs(x2) <= 1) roots++; + if (x1 < -1) x1 = x2; + } + + if (roots === 1) { + if (h0 < 0) rise = i + x1; + else set = i + x1; + + } else if (roots === 2) { + rise = i + (ye < 0 ? x2 : x1); + set = i + (ye < 0 ? x1 : x2); + } + + if (rise && set) break; + + h0 = h2; + } + + var result = {}; + + if (rise) result.rise = hoursLater(t, rise); + if (set) result.set = hoursLater(t, set); + + if (!rise && !set) result[ye > 0 ? 'alwaysUp' : 'alwaysDown'] = true; + + return result; +}; + + +// export as Node module / AMD module / browser variable +if (typeof exports === 'object' && typeof module !== 'undefined') module.exports = SunCalc; +else if (typeof define === 'function' && define.amd) define(SunCalc); +else window.SunCalc = SunCalc; + +}()); diff --git a/RVO53/flow/helper/utils.js b/RVO53/flow/helper/utils.js new file mode 100755 index 0000000..dbffe45 --- /dev/null +++ b/RVO53/flow/helper/utils.js @@ -0,0 +1,161 @@ +const fs = require('fs').promises; + +function bytesToInt(bytes, numberOfBytes) { + let buffer = []; + if (Array.isArray(bytes)) { + buffer = bytes.slice(0); + if (numberOfBytes != undefined) { + buffer = bytes.slice(bytes.length - numberOfBytes); + } + } + else buffer.push(bytes); + + let result = 0; + for (let i = 0; i < buffer.length; i++) { + result = (result << 8) | buffer[i]; + } + + return result >>> 0; //ensure it's an unsigned 32-bit number +} + +function resizeArray(arr, newSize, defaultValue) { + while (newSize > arr.length) + arr.push(defaultValue); + arr.length = newSize; +} + +longToByteArray = function(/*long*/long) { + // we want to represent the input as a 8-bytes array + var byteArray = [0, 0, 0, 0, 0, 0, 0, 0]; + + for (var index = 0; index < byteArray.length; index++) { + var byte = long & 0xff; + byteArray[index] = byte; + long = (long - byte) / 256; + } + + return byteArray; +}; + +function addDays(date, days) { + var result = new Date(date); + result.setDate(result.getDate() + days); + return result; +} + +/* +sleep(2000).then(() => { + // Do something after the sleep! + + +}); +*/ + +function sleep(time) { + return new Promise((resolve) => setTimeout(resolve, time)); +} + +function isEmptyObject(obj) { + for (var name in obj) { + return false; + } + return true; +} + +function emptyJsObject(jsObject) { + Object.keys(jsObject).forEach(key => delete jsObject[key]); +} + +function convertUTCDateToLocalDate(date) { + var newDate = new Date(date); + newDate.setMinutes(date.getMinutes() + date.getTimezoneOffset()); + return newDate; +} + +function addZeroBefore(n) { + return (n < 10 ? '0' : '') + n; +} + + +/** + * Asynchronously writes data to a file. + * + * @param {string} filePath The path to the file. + * @param {string} data The data to write to the file. + * @param {boolean} [append=false] If true, appends the data to the file. If false, it overwrites the file. + */ +async function writeToFile(filePath, data, append = false) { + if (typeof data !== 'string') data = JSON.stringify(data, null, 2); + try { + if (append) { + // Append the data to the end of the file. This is the simplest way to append. + await fs.appendFile(filePath, data, 'utf8'); + console.log(`Successfully appended data to ${filePath} using fs.appendFile.`); + } else { + // Overwrite the file with the new data. + await fs.writeFile(filePath, data, 'utf8'); + console.log(`Successfully wrote (overwrote) data to ${filePath} using fs.writeFile.`); + } + } catch (error) { + console.error(`Error writing to file ${filePath}:`, error); + } +} + + + /** + * Checks if an item is present in an array and adds it if it's not. + * * @param {Array} arr The array to check. + * @param {*} item The item to add. + * @returns {Array} The modified array. + */ +const addToArrayIfUnique = (arr, item) => { + if (!arr.includes(item)) { + arr.push(item); + } + return arr; +}; + + +var convertBase = function() { + + function convertBase(baseFrom, baseTo) { + return function(num) { + return parseInt(num, baseFrom).toString(baseTo); + + }; + } + + // binary to decimal + convertBase.bin2dec = convertBase(2, 10); + + // binary to hexadecimal + convertBase.bin2hex = convertBase(2, 16); + + // decimal to binary + convertBase.dec2bin = convertBase(10, 2); + + // decimal to hexadecimal + convertBase.dec2hex = convertBase(10, 16); + + // hexadecimal to binary + convertBase.hex2bin = convertBase(16, 2); + + // hexadecimal to decimal + convertBase.hex2dec = convertBase(16, 10); + + return convertBase; +}(); + +module.exports = { + bytesToInt, + longToByteArray, + addDays, + addZeroBefore, + resizeArray, + isEmptyObject, + emptyJsObject, + sleep, + convertUTCDateToLocalDate, + writeToFile, + addToArrayIfUnique +} diff --git a/RVO53/flow/httprequest.js b/RVO53/flow/httprequest.js new file mode 100755 index 0000000..469c8cb --- /dev/null +++ b/RVO53/flow/httprequest.js @@ -0,0 +1,137 @@ +exports.id = 'httprequest'; +exports.title = 'HTTP Request'; +exports.group = 'HTTP'; +exports.color = '#5D9CEC'; +exports.input = true; +exports.version = '2.0.1'; +exports.output = 1; +exports.author = 'Peter Širka'; +exports.icon = 'cloud-upload'; + +exports.html = `
+
@(URL address)
+
+
+
@(HTTP method)
+
+
+
@(Serialization)
+
+
+
@(Download the content in chunks)
+
@(Keep persistent cookies)
+
@(Disable DNS cache)
+
@(Keep alive connection)
+
+
+
+
@(Custom headers)
+
@(Cookies)
+
+
+
+ +
+
+
+
@(User)
+
+
+
@(Password)
+
+
+
+
+
`; + +exports.readme = `# Request + +This component creates a request with received data. + +__Response:__ +\`\`\`javascript +{ + data: String, + headers: Object, + status: Number, + host: String +} +\`\`\` + +__Dynamic arguments__: +Are performed via FlowData repository and can be used for URL address or for custom headers/cookies/auth. Use \`repository\` component for creating of dynamic arguments. Dynamic values are replaced in the form \`{key}\`: + +- url address e.g. \`https://.../{key}/\` +- headers values e.g. \`{token}\` +- cookies values e.g. \`{token}\``; + +exports.install = function(instance) { + + var can = false; + var flags = null; + var cookies2 = null; + + instance.on('data', function(response) { + can && instance.custom.send(response); + }); + + instance.custom.send = function(response) { + var options = instance.options; + + var headers = null; + var cookies = null; + + options.headers && Object.keys(options.headers).forEach(function(key) { + !headers && (headers = {}); + headers[key] = response.arg(options.headers[key]); + }); + + if (options.username && options.userpassword) { + !headers && (headers = {}); + headers['Authorization'] = 'Basic ' + U.createBuffer(response.arg(options.username + ':' + options.userpassword)).toString('base64'); + } + + options.cookies && Object.keys(options.cookies).forEach(function(key) { + !cookies && (cookies = {}); + cookies[key] = response.arg(options.cookies[key]); + }); + + if (options.chunks) { + U.download(response.arg(options.url), flags, options.stringify === 'none' ? null : response.data, function(err, response) { + response.on('data', (chunks) => instance.send2(chunks)); + }, cookies || cookies2, headers); + } else { + U.request(response.arg(options.url), flags, options.stringify === 'none' ? null : response.data, 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) + instance.error(err, response); + }, cookies || cookies2, headers); + } + }; + + instance.reconfigure = function() { + var options = instance.options; + can = options.url && options.url && options.method && options.stringify ? true : false; + instance.status(can ? '' : 'Not configured', can ? undefined : 'red'); + + if (!can) + return; + + flags = []; + flags.push(options.method.toLowerCase()); + options.stringify === 'json' && flags.push('json'); + options.stringify === 'raw' && flags.push('raw'); + options.keepalive && flags.push('keepalive'); + !options.nodns && flags.push('dnscache'); + if (options.persistentcookies) { + flags.push('cookies'); + cookies2 = {}; + } else + cookies2 = null; + }; + + instance.on('options', instance.reconfigure); + instance.reconfigure(); +}; \ No newline at end of file diff --git a/RVO53/flow/httpresponse.js b/RVO53/flow/httpresponse.js new file mode 100755 index 0000000..160a3bb --- /dev/null +++ b/RVO53/flow/httpresponse.js @@ -0,0 +1,76 @@ +exports.id = 'httpresponse'; +exports.title = 'HTTP Response'; +exports.group = 'HTTP'; +exports.color = '#5D9CEC'; +exports.icon = 'arrow-right'; +exports.input = true; +exports.output = ['#666D76']; +exports.version = '2.0.0'; +exports.author = 'Martin Smola'; +exports.readme = `# HTTP response + +HTTP response will respond with data recieved using data-type set in Settings form or plain text if not set. Output is the message duration \`Number\` in seconds.`; + +exports.html = `
+
@(Response data-type)
+
JSON is by default.
+
`; + +exports.install = function(instance) { + + var dursum = 0; + var durcount = 0; + + instance.on('data', function(flowdata) { + + var ctrl = flowdata.repository.controller; + var data = flowdata.data; + + if (!ctrl) { + instance.throw('No controller to use for response!'); + return; + } + + durcount++; + dursum += ((new Date() - flowdata.begin) / 1000).floor(2); + setTimeout2(instance.id, instance.custom.duration, 500, 10); + + ctrl.$flowdata = flowdata; + + var datatype = instance.options.datatype || 'json'; + if (datatype === 'emptyresponse') + return ctrl.plain(''); + + if (datatype !== 'json' && typeof(data) !== 'string') { + instance.throw('Incorect type of data, expected string, got ' + typeof(data)); + ctrl.plain(data == null ? '' : data.toString()); + return; + } + + switch(datatype) { + case 'html': + ctrl.content(data, 'text/html'); + break; + case 'plain': + ctrl.plain(data); + break; + case 'xml': + ctrl.content(data, 'text/xml'); + break; + default: + ctrl.json(data); + break; + } + }); + + instance.on('service', function() { + dursum = 0; + durcount = 0; + }); + + instance.custom.duration = function() { + var avg = (dursum / durcount).floor(2); + instance.status(avg + ' sec.'); + instance.send2(0, avg); + }; +}; diff --git a/RVO53/flow/httproute.js b/RVO53/flow/httproute.js new file mode 100755 index 0000000..583a19d --- /dev/null +++ b/RVO53/flow/httproute.js @@ -0,0 +1,326 @@ +exports.id = 'httproute'; +exports.title = 'HTTP Route'; +exports.group = 'HTTP'; +exports.color = '#5D9CEC'; +exports.icon = 'globe'; +exports.input = false; +exports.output = ['#6CAC5A', '#37BC9B']; +exports.version = '1.2.3'; +exports.author = 'Martin Smola'; +exports.cloning = false; +exports.options = { method: 'GET', url: '', size: 5, cacheexpire: '5 minutes', cachepolicy: 0, timeout: 5 }; +exports.dateupdated = '2021-01-21 18:30d'; +exports.readme = `# HTTP route + +__Outputs__: +- first output: raw data (cache is empty or is disabled) +- second output: cached data + +If one of the outputs is disabled then automatic responce with code "503 service unavailable" is sent. + +When a request comes in bellow object is available at \`flowdata.data\`: + +\`\`\`javascript +{ + params: { id: '1' }, // params for dynamic routes, e.g. /test/{id} + query: { msg: 'Hello' }, // parsed query string, e.g. /test/1?msg=Hello + body: { test: 'OK' }, // object if json requests otherwise string + headers: {}, // headers data + session: {}, // session data + user: {}, // user data + files: [], // uploaded files + url: '/users/', // a relative URL address + referrer: '/', // referrer + mobile: false, // determines mobile device + robot: false, // determines search robots/crawlsers + language: 'en' // determines language +} +\`\`\` + +See [documentation for flags](https://docs.totaljs.com/latest/en.html#api~HttpRouteOptionsFlags~unauthorize). These method flags are set automatically e.g. \`get, post, put, patch or delete\` + +--- + +\`id:ROUTE_ID\` flag cannot be used since it's already used by this component internally`; + +exports.html = `
+
+ +
+ +
+
+
@(HTTP method)
+
+
+
@(URL address)
+
+
+
+
+
@(Additional flags)
+
@(Separate flags by comma e.g. json, authorize)
+
+
+
@(Max. request size)
+
@(In kB kilobytes)
+
+
+
@(Timeout)
+
@(In seconds.)
+
+
+
+
+
+
@(Automatically respond with 200 OK?)
+
@(If not checked you need to use HTTP response component to respond to the request.)
+
+
@(Custom headers)
+
@(Cookies)
+
+
+
+
+
+
@(Cache policy)
+
@(User instance must contain id property.)
+
+
+
@(Expiration)
+
@(E.g. 5 minutes)
+
+
+
+`; + +exports.install = function(instance) { + + var route; + + var uninstall = function(id) { + if (F.is4) { + route && route.remove(); + route = null; + } else + UNINSTALL('route', id); + }; + + instance.custom.emptyresponse = function(self) { + self.plain(); + }; + + instance.reconfigure = function() { + + var options = instance.options; + + if (!options.url) { + instance.status('Not configured', 'red'); + return; + } + + if (typeof(options.flags) === 'string') + options.flags = options.flags.split(',').trim(); + + uninstall('id:' + instance.id); + + var flags = options.flags || []; + + flags.push('id:' + instance.id); + + if (!F.is4) + flags.push(options.method.toLowerCase()); + + options.timeout && flags.push(options.timeout * 1000); + + // Make unique values + flags = flags.filter(function(v, i, a) { + if(F.is4 && v.toString().toLowerCase() === options.method.toLowerCase()) + return false; // remove method + return a.indexOf(v) === i; + }); + + options.flags = flags; + var handler = function() { + + if (instance.paused || (instance.isDisabled && (instance.isDisabled('output', 0) || instance.isDisabled('output', 1)))) { + instance.status('503 Service Unavailable'); + this.status = 503; + this.json(); + return; + } + + var key; + var self = this; + + if (instance.options.emptyresponse) { + instance.status('200 OK'); + setTimeout(instance.custom.emptyresponse, 100, self); + + if (instance.hasConnection(0)) { + var data = instance.make({ + query: self.query, + body: self.body, + session: self.session, + user: self.user, + files: self.files, + headers: self.req.headers, + url: self.url, + params: self.params + }); + instance.send2(0, data); + } + + return; + } + + switch (instance.options.cachepolicy) { + case 1: // URL + key = 'rro' + instance.id + self.url.hash(); + break; + case 2: // URL + query + case 3: // URL + query + user + key = self.url; + var keys = Object.keys(self.query); + keys.sort(); + for (var i = 0, length = keys.length; i < length; i++) + key += keys[i] + self.query[keys[i]] + '&'; + if (instance.options.cachepolicy === 3 && self.user) + key += 'iduser' + self.user.id; + key = 'rro' + instance.id + key.hash(); + break; + } + + if (key && F.cache.get2(key)) { + var data = instance.make(F.cache.get2(key)); + data.repository.controller = self; + instance.send2(1, data); + } else { + + var data = instance.make({ + query: self.query, + body: self.body, + session: self.session, + user: self.user, + files: self.files, + headers: self.req.headers, + url: self.url, + params: self.params, + mobile: self.mobile, + robot: self.robot, + referrer: self.referrer, + language: self.language + }); + + data.repository.controller = self; + instance.send2(0, data); + key && FINISHED(self.res, () => F.cache.set(key, self.$flowdata.data, instance.options.cacheexpire)); + } + }; + + if (F.is4) + route = ROUTE(options.method.toUpperCase() + ' ' + options.url, handler, flags, options.size || 5); + else + F.route(options.url, handler, flags, options.size || 5); + + instance.status('Listening', 'green'); + }; + + instance.reconfigure(); + instance.on('options', instance.reconfigure); + instance.on('close', function(){ + uninstall('id:' + instance.id); + }); +}; + +// check url exists +FLOW.trigger('httproutecheckurl', function(next, data) { + var url = data.url; + var method = data.method; + if (url[url.length - 1] !== '/') + url += '/'; + var exists = F.routes.web.findItem(r => r.urlraw === url && r.method === method); + next(exists != null); +}); + +exports.uninstall = function() { + FLOW.trigger('httproutecheckurl', null); +}; diff --git a/RVO53/flow/infosender.js b/RVO53/flow/infosender.js new file mode 100755 index 0000000..587724f --- /dev/null +++ b/RVO53/flow/infosender.js @@ -0,0 +1,81 @@ +exports.id = 'infosender'; +exports.title = 'Info sender'; +exports.version = '1.0.0'; +exports.group = 'Worksys'; +exports.color = '#2134B0'; +exports.input = 2; +exports.output = 1 +exports.icon = 'bolt'; + +const { networkInterfaces } = require('os'); + +exports.html = `
+
+
+
CSV Import
+
+
+
`; + +exports.readme = `# send all data to projects.worksys.io, required to monitor status of controller(unipi)`; + +exports.install = function(instance) { + + let id; + let allValues = {}; + let sendAllValuesInterval; + let configured = false; + + let now = new Date(); + console.log(exports.title, "INSTALLED", now.toLocaleString("sk-SK")); + + const nets = networkInterfaces(); + let ipAddresses = Object.create(null); // Or just '{}', an empty object + + for (const name of Object.keys(nets)) { + for (const net of nets[name]) { + // Skip over non-IPv4 and internal (i.e. 127.0.0.1) addresses + if (net.family === 'IPv4' && !net.internal) { + if (!ipAddresses[name]) { + ipAddresses[name] = []; + } + ipAddresses[name].push(net.address); + } + } + } + + function sendValues() { + if (!configured) return; + + if (Object.keys(allValues).length > 0) { + let dataToSend = { ...allValues }; + dataToSend.id = id; + dataToSend.ipAddresses = ipAddresses; + + instance.send(0, dataToSend); + + allValues = {}; + } + } + + instance.on("close", () => { + clearInterval(sendAllValuesInterval); + }) + + instance.on("0", _ => { + id = FLOW.GLOBALS.settings.project_id; + if (id) configured = true; + else console.log(exports.title, "InfoSender: Unable to send data, no id"); + }) + + instance.on("1", flowdata => { + allValues = { ...allValues, ...flowdata.data }; + //console.log("DATA RECEIVED", flowdata.data); + }) + + sendAllValuesInterval = setInterval(() => { + sendValues(); + }, 60000 * 3); + +} + diff --git a/RVO53/flow/modbus_reader.js b/RVO53/flow/modbus_reader.js new file mode 100755 index 0000000..d6d9dad --- /dev/null +++ b/RVO53/flow/modbus_reader.js @@ -0,0 +1,346 @@ +exports.id = 'modbus_reader'; +exports.title = 'Modbus reader'; +exports.version = '2.0.0'; +exports.group = 'Worksys'; +exports.color = '#2134B0'; +exports.input = 1; +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; +//number of phases inRVO +let phases; +//phases where voltage is 0 (set) +let noVoltage; +let energyToSwitchLamps; + +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.phases = this.buildPhases(); + + this.startSocket(); + } + + buildPhases = () => { + let a = []; + for (let i = 1; i <= phases; i++) { + a.push(`Phase_${i}_voltage`) + } + return a; + } + + startSocket = () => { + + let obj = this; + + if (this.socket) { + this.socket.removeAllListeners(); + this.socket = null; + } + + 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('Modbus_reader: Socket connection error', e); //'ECONNREFUSED' or 'ECONNRESET' ?? + }); + + this.socket.on('close', function() { + console.log('Modbus_reader: Socket connection closed - Waiting 10 seconds before connecting 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 we just start to loop devices from the beginning, or there is just 1 device in config, we wait whole timeoutInterval + if (this.indexInDeviceConfig == 0 || deviceConfig.length === 1) 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 (this.phases.includes(singleValue)) { + let l = singleValue.split("_"); + let phase = parseInt(l[1]); + + // console.log(values[singleValue], tbName); + + if (values[singleValue] == 0) { + noVoltage.add(phase); + sendNotification("modbus_reader: checkNullVoltage", tbName, "no_voltage_on_phase", { phase: phase }, "", SEND_TO.tb, instance, "voltage" + phase); + // console.log('no voltage') + } + else { + noVoltage.delete(phase); + // console.log('voltage detected') + sendNotification("modbus_reader: checkNullVoltage", tbName, "voltage_on_phase_restored", { phase: phase }, "", SEND_TO.tb, instance, "voltage" + phase); + } + } + }) + } + + /** + * function sends notification to slack and to tb, if EM total_power value changes more than numberOfNodes*15. This should show, that RVO lamps has been switched on or off + */ + lampSwitchNotification = (values) => { + + if (!values.hasOwnProperty("total_power")) return; + + const actualTotalPower = values.total_power; + + if (actualTotalPower > energyToSwitchLamps && 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 <= energyToSwitchLamps && 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; + } + + function main() { + + phases = FLOW.GLOBALS.settings.phases; + tbName = FLOW.GLOBALS.settings.rvoTbName; + noVoltage = FLOW.GLOBALS.settings.no_voltage; + energyToSwitchLamps = FLOW.GLOBALS.settings.energy_to_switch_lamps / 2.5; //half value is enought to show if lamps are turned on or off + if (deviceConfig.length) mainSocket = new SocketWithClients(); + else console.log("Modbus_reader: no modbus device in configuration"); + + // this notification is to show, that flow (unipi) has been restarted + sendNotification("modbus_reader", tbName, "flow_restart", {}, "", SEND_TO.slack, instance); + } + + instance.on("0", function(_) { + main(); + }) + +} + diff --git a/RVO53/flow/monitorconsumption.js b/RVO53/flow/monitorconsumption.js new file mode 100755 index 0000000..64cc58e --- /dev/null +++ b/RVO53/flow/monitorconsumption.js @@ -0,0 +1,156 @@ +exports.id = 'monitorconsumption'; +exports.title = 'Consumption'; +exports.version = '1.0.0'; +exports.author = 'Peter Širka'; +exports.group = 'Monitoring'; +exports.color = '#967ADC'; +exports.input = 0; +exports.output = 1; +exports.icon = 'bug'; +exports.options = { interval: 5000, enabled: true, monitorconsumption: true, monitorsize: true, monitorconnections: true, monitorfiles: true }; +exports.click = true; +exports.readme = `# Consumption monitoring + +This component measure CPU and memory consumption, open files and open connections of this application. It uses these Linux commands: \`ps\`, \`lsof\`, \`netstat\` and \`df\`. + +__Data Example__: + +\`\`\`javascript +{ + cpu: 0, // percentage + memory: 4096, // in bytes + size: 34303, // directory size in bytes + files: 34, // count of open files + connections: 343, // count of connections + uptime: '1-12:34:00' +} +\`\`\``; + +exports.html = `
+
+
+
@(Interval in milliseconds)
+
+
+
+
Monitor: Consumption + uptime
+
Monitor: Count of open files
+
Monitor: Count of open connections
+
Monitor: Directory size
+
`; + +exports.install = function(instance) { + + var current = { cpu: 0, memory: 0, files: 0, connections: 0, size: 0, uptime: '', counter: 0 }; + var tproc = null; + var Exec = require('child_process').exec; + var reg_empty = /\s{2,}/g; + var reg_appdisksize = /^[\d.,]+/; + + instance.custom.run = function() { + + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + + var arr = []; + + // Get CPU and Memory consumption + instance.options.monitorconsumption && arr.push(function(next) { + Exec('ps -p {0} -o %cpu,rss,etime'.format(process.pid), function(err, response) { + + if (err) { + instance.throw(err); + } else { + var line = response.split('\n')[1]; + line = line.trim().replace(reg_empty, ' ').split(' '); + var cpu = line[0].parseFloat(); + current.cpu = cpu.floor(1); + current.memory = line[1].parseInt2() * 1024; // kB to bytes + current.uptime = line[2]; + } + + next(); + }); + }); + + // Get count of open files + instance.options.monitorfiles && arr.push(function(next) { + Exec('lsof -a -p {0} | wc -l'.format(process.pid), function(err, response) { + if (err) + instance.throw(err); + else + current.files = response.trim().parseInt2(); + next(); + }); + }); + + // Get count of opened network connections + instance.options.monitorconnections && arr.push(function(next) { + Exec('netstat -an | grep :{0} | wc -l'.format(F.port), function(err, response) { + if (err) { + instance.throw(err); + } else { + current.connections = response.trim().parseInt2() - 1; + if (current.connections < 0) + current.connections = 0; + } + next(); + }); + }); + + // Get directory size + instance.options.monitorsize && current.counter % 5 !== 0 && arr.push(function(next) { + Exec('du -hsb ' + process.cwd(), function(err, response) { + if (err) { + instance.throw(err); + } else { + var match = response.trim().match(reg_appdisksize); + match && (current.size = match.toString().trim().parseInt2()); + } + next(); + }); + }); + + arr.async(function() { + + tproc && clearTimeout(tproc); + + if (instance.options.enabled) { + tproc = setTimeout(instance.custom.run, instance.options.interval); + instance.send2(current); + } + + instance.custom.status(); + current.counter++; + }); + }; + + instance.custom.status = function() { + if (instance.options.enabled) + instance.status('{0}% / {1}'.format(current.cpu, current.memory.filesize())); + else + instance.status('Disabled', 'red'); + }; + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + + if (instance.options.enabled) { + current.counter = 0; + instance.custom.run(); + } + + }); + + instance.on('close', function() { + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + }); + + setTimeout(instance.custom.run, 1000); +}; \ No newline at end of file diff --git a/RVO53/flow/monitordisk.js b/RVO53/flow/monitordisk.js new file mode 100755 index 0000000..f4fdaa0 --- /dev/null +++ b/RVO53/flow/monitordisk.js @@ -0,0 +1,96 @@ +exports.id = 'monitordisk'; +exports.title = 'Disk'; +exports.version = '1.0.0'; +exports.author = 'Peter Širka'; +exports.group = 'Monitoring'; +exports.color = '#F6BB42'; +exports.output = 1; +exports.icon = 'hdd-o'; +exports.click = true; +exports.options = { interval: 8000, path: '/', enabled: true }; +exports.readme = `# Disk monitoring + +This component monitors disk \`bytes\` consumption in Linux systems. It uses \`df\` command. + +__Data Example__: + +\`\`\`javascript +{ + total: 474549649408, + used: 39125245952, + free: 411294994432 +} +\`\`\``; + +exports.html = `
+
+
+
@(Interval in milliseconds)
+
+
+
@(Path)
+
+
+
`; + +exports.install = function(instance) { + + var current = { total: 0, used: 0, free: 0, path: '', type: '', percentUsed: 0 }; + var tproc = null; + + instance.custom.run = function() { + + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + + if (!instance.options.enabled) + return; + + require('child_process').exec('df -hTB1 ' + instance.options.path, function(err, response) { + + tproc = setTimeout(instance.custom.run, instance.options.interval); + + if (err) { + instance.error(err); + return; + } + + response.parseTerminal(function(line) { + if (line[0][0] !== '/') + return; + current.total = line[2].parseInt(); + current.free = line[4].parseInt(); + current.used = line[3].parseInt(); + current.path = instance.options.path || '/'; + current.type = line[1]; + current.percentUsed = line[5]; + instance.custom.status(); + instance.send2(current); + }); + }); + }; + + instance.custom.status = function() { + if (instance.options.enabled) + instance.status(current.free.filesize() + ' / ' + current.total.filesize()); + else + instance.status('Disabled', 'red'); + }; + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + instance.options.enabled && instance.custom.run(); + }); + + instance.on('close', function() { + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + }); + + setTimeout(instance.custom.run, 1000); +}; \ No newline at end of file diff --git a/RVO53/flow/monitormemory.js b/RVO53/flow/monitormemory.js new file mode 100755 index 0000000..2decbc4 --- /dev/null +++ b/RVO53/flow/monitormemory.js @@ -0,0 +1,87 @@ +exports.id = 'monitormemory'; +exports.title = 'Memory'; +exports.version = '1.0.0'; +exports.author = 'Peter Širka'; +exports.group = 'Monitoring'; +exports.color = '#F6BB42'; +exports.output = 1; +exports.click = true; +exports.icon = 'microchip'; +exports.options = { interval: 8000, enabled: true }; +exports.readme = `# Memory monitoring + +This component monitors memory \`bytes\` consumption in Linux systems. It uses \`free\` command. + +__Data Example__: + +\`\`\`javascript +{ + total: 33558769664, + used: 1998868480, + free: 2653708288 +} +\`\`\``; + +exports.html = `
+
+
+
@(Interval in milliseconds)
+
+
+
`; + +exports.install = function(instance) { + + var current = { total: 0, used: 0, free: 0 }; + var tproc = null; + + instance.custom.run = function() { + + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + + if (!instance.options.enabled) + return; + + require('child_process').exec('free -b -t', function(err, response) { + + tproc = setTimeout(instance.custom.run, instance.options.interval); + + if (err) { + instance.error(err); + return; + } + + var memory = response.split('\n')[1].match(/\d+/g); + current.total = memory[0].parseInt(); + current.used = memory[1].parseInt() - memory[3].parseInt(); + current.free = current.total - current.used; + instance.custom.status(); + instance.send2(current); + }); + }; + + instance.custom.status = function() { + if (instance.options.enabled) + instance.status(current.free.filesize() + ' / ' + current.total.filesize()); + else + instance.status('Disabled', 'red'); + }; + + instance.on('click', function() { + instance.options.enabled = !instance.options.enabled; + instance.custom.status(); + instance.options.enabled && instance.custom.run(); + }); + + instance.on('close', function() { + if (tproc) { + clearTimeout(tproc); + tproc = null; + } + }); + + setTimeout(instance.custom.run, 1000); +}; \ No newline at end of file diff --git a/RVO53/flow/nodesdb_changecheck.js b/RVO53/flow/nodesdb_changecheck.js new file mode 100755 index 0000000..9adab62 --- /dev/null +++ b/RVO53/flow/nodesdb_changecheck.js @@ -0,0 +1,77 @@ +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 = 2; +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); + } + } + + //kedze do slacku posielame stringy, na cloud musime previest vsetky stringy spat na objekty: + // Funkcia na parsovanie všetkých reťazcov v poli + const parseArray = (arr) => { + return arr.map(jsonString => JSON.parse(jsonString)); + }; + + 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); + if (FLOW.GLOBALS.settings.send_changed_node_numbers) instance.send(1, { aktualneNody: parseArray(zmenene), originalne: parseArray(Array.from(set2)) }); + } + 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/RVO53/flow/show_dbdata.js b/RVO53/flow/show_dbdata.js new file mode 100755 index 0000000..1e23ff7 --- /dev/null +++ b/RVO53/flow/show_dbdata.js @@ -0,0 +1,243 @@ +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 = 8; +exports.output = 1; + +const { exec } = require('child_process'); + +exports.install = 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 }) + }) + instance.on("5", _ => { + exec("sudo tail -n 25 monitor.txt", (err, stdout, stderr) => { + if (err || stderr) instance.send(0, { err, stderr }); + else instance.send(0, stdout); + }) + }) + instance.on("6", _ => { + exec("sudo tail -n 25 err.txt", (err, stdout, stderr) => { + if (err || stderr) instance.send(0, { err, stderr }); + else instance.send(0, stdout); + }) + }) + instance.on("7", _ => { + instance.send(0, FLOW.deviceStatus); + }) +}; + + +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/RVO53/flow/slack_filter.js b/RVO53/flow/slack_filter.js new file mode 100755 index 0000000..6618523 --- /dev/null +++ b/RVO53/flow/slack_filter.js @@ -0,0 +1,188 @@ +exports.id = 'slack_filter'; +exports.title = 'Slack Filter'; +exports.group = 'Citysys'; +exports.color = '#30E193'; +exports.input = 2; +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 = `
+
+
+
@(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('0', 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']['en']; + 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"] = []; + } + + instance.options.name = FLOW.GLOBALS.settings.rvo_name; + if (instance.options.name) { + instance.status('Running'); + running = true; + } else { + instance.status('Please run options again', 'red'); + running = false; + } + } catch (e) { + instance.error('Citysys connector: ' + e.message); + } + }; + + instance.on('options', instance.reconfigure); + + instance.on("1", _ => { + instance.reconfigure(); + }) +}; diff --git a/RVO53/flow/thermometer.js b/RVO53/flow/thermometer.js new file mode 100755 index 0000000..fc7074d --- /dev/null +++ b/RVO53/flow/thermometer.js @@ -0,0 +1,99 @@ +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 = 5;//minutes +let NUMBER_OF_FAILURES_TO_SEND_ERROR = 13; + +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) => { + + 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); + setTimeout(main, 20000); + }) +}; diff --git a/RVO53/flow/trigger.js b/RVO53/flow/trigger.js new file mode 100755 index 0000000..27545a8 --- /dev/null +++ b/RVO53/flow/trigger.js @@ -0,0 +1,79 @@ +exports.id = 'trigger'; +exports.title = 'Trigger'; +exports.group = 'Inputs'; +exports.color = '#F6BB42'; +exports.click = true; +exports.output = 1; +exports.version = '1.1.0'; +exports.author = 'Martin Smola'; +exports.icon = 'play'; + +exports.html = `
+
@(Data type (String by default))
+
@(Data)
+
Trigger 5s after initialization.
+
@(Useful when there's a need to run certain flow when the app restarts, etc.)
+
`; + +exports.readme = `# Trigger + +- Clicking on the component starts the chain +- Settings allows to set a data-type and a value`; + +exports.install = function(instance) { + + var value; + + instance.on('click', () => instance.send2(value)); + + instance.reconfigure = function() { + var options = instance.options; + value = null; + switch (options.datatype) { + case 'integer': + value = options.data.parseInt2('error'); + value = value === 'error' ? NaN : value; + break; + case 'float': + value = options.data.parseFloat2('error'); + value = value === 'error' ? NaN : value; + break; + case 'date': + options.data = options.data.toString(); + var num = options.data.parseInt('error'); + num === 'error' && (num = options.data.parseDate('error')); + num === 'error' && (num = null); + value = num ? new Date(num).toUTCString() : num; + break; + case 'object': + try { + value = (new Function('return ' + options.data))(); + } catch (e) { + instance.error(e); + } + break; + case 'boolean': + value = options.data.parseBoolean(); + break; + case 'buffer': + try { + value = U.createBuffer(options.data); + } catch (e) { + instance.error(e); + } + break; + case 'string': + default: + value = '' + (options.data || ''); + break; + } + }; + + instance.on('options', instance.reconfigure); + instance.reconfigure(); + + if (instance.options.restart) + setTimeout(function(){ + instance.send2(value); + }, 5000); +}; diff --git a/RVO53/flow/variables.txt b/RVO53/flow/variables.txt new file mode 100755 index 0000000..e69de29 diff --git a/RVO53/flow/virtualwirein.js b/RVO53/flow/virtualwirein.js new file mode 100755 index 0000000..38a4e42 --- /dev/null +++ b/RVO53/flow/virtualwirein.js @@ -0,0 +1,43 @@ +exports.id = 'virtualwirein'; +exports.title = 'Virtual wire in'; +exports.version = '1.0.0'; +exports.author = 'Martin Smola'; +exports.color = '#303E4D'; +exports.icon = 'sign-in'; +exports.input = false; +exports.output = 1; +exports.options = {}; +exports.readme = `# Virtual wire in + +When the wires between the components are mess it's time to use Virtual wire.`; + +exports.html = `
+
@(Wire name)
+
+`; + +exports.install = function(instance) { + + instance.custom.reconfigure = function(options){ + if (instance.options.wirename) { + instance.status(instance.options.wirename); + } else + instance.status('Not configured', 'red'); + }; + + ON('virtualwire', function(wirename, flowdata){ + if (instance.options.wirename && instance.options.wirename === wirename) + instance.send(flowdata); + }); + + instance.on('options', instance.custom.reconfigure); + instance.custom.reconfigure(); +}; diff --git a/RVO53/flow/virtualwireout.js b/RVO53/flow/virtualwireout.js new file mode 100755 index 0000000..94a1e4f --- /dev/null +++ b/RVO53/flow/virtualwireout.js @@ -0,0 +1,41 @@ +exports.id = 'virtualwireout'; +exports.title = 'Virtual wire out'; +exports.version = '1.0.0'; +exports.author = 'Martin Smola'; +exports.color = '#303E4D'; +exports.icon = 'sign-out'; +exports.input = true; +exports.options = {}; +exports.readme = `# Virtual wire out + +When the wires between the components are mess it's time to use Virtual wire.`; + +exports.html = `
+
@(Wire name)
+
+`; + +exports.install = function(instance) { + + instance.custom.reconfigure = function(){ + if (instance.options.wirename) { + instance.status(instance.options.wirename); + } else + instance.status('Not configured', 'red'); + }; + + instance.on('data', function(flowdata) { + EMIT('virtualwire', instance.options.wirename, flowdata); + }); + + instance.on('options', instance.custom.reconfigure); + instance.custom.reconfigure(); +}; diff --git a/RVO53/flow/wsmqttpublish.js b/RVO53/flow/wsmqttpublish.js new file mode 100755 index 0000000..0eba804 --- /dev/null +++ b/RVO53/flow/wsmqttpublish.js @@ -0,0 +1,448 @@ +exports.id = 'wsmqttpublish'; +exports.title = 'WS MQTT publish'; +exports.group = 'MQTT'; +exports.color = '#888600'; +exports.version = '1.0.2'; +exports.icon = 'sign-out'; +exports.input = 2; +exports.output = 3; +exports.options = { host: 'tb-stage.worksys.io', port: 1883, clientid: "", username: "" }; + +exports.html = `
+
+
+
Hostname or IP address (if not empty - setting will override db setting)
+
+
+
Port
+
+
+
+
+
@(Client id)
+
+
+
@(Username)
+
+
+
`; + + +exports.readme = ` +# WS MQTT Publish + +Version 1.0.3. + +Added: +- database collections, +- 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 = { + debug: 0, + rpcCall: 1, + services: 2 +} + +//CONFIG +let createTelemetryBackup = true; +let saveTelemetryOnError = true;//backup_on_failure overrides this value +//------------------------ + +let rollers; +if (createTelemetryBackup) rollers = require('streamroller'); + +const noSqlFileSizeLimit = 4194304;//use 5MB - 4194304 +let insertNoSqlCounter = 0; +let insertBackupNoSqlCounter = 0; +let processingData = false; + +let backup_on_failure = false;//== saveTelemetryOnError - create backup client 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; + +process.on('uncaughtException', function(err) { + + errLogger.error('uncaughtException:', err.message) + errLogger.error(err.stack); + + //TODO + //send to service + + //process.exit(1); +}) + +const nosql = NOSQL('tbdata'); +const nosqlBackup = NOSQL('/backup/tbdata'); + + +exports.install = function(instance) { + + var client; + var opts; + var clientReady = false; + + // wsmqtt status for notification purposes on projects.worksys.io database + let wsmqttName = null; + let sendWsStatusVar = null; + let wsmqtt_status = 'disconnected'; + + 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'; + } + + function sendWsStatus() { + instance.send(SEND_TO.services, { [wsmqttName]: wsmqtt_status }); + } + + + function main() { + if (!FLOW.dbLoaded) return; + + loadSettings(); + clearInterval(sendWsStatus); + sendWsStatusVar = setInterval(sendWsStatus, 180000); + } + + //set opts according to db settings + function loadSettings() { + + if (instance.options.host !== "") { + //override settings from database + var o = instance.options; + opts = { + host: o.host, + port: o.port, + clientId: o.clientid, + username: o.username, + rejectUnauthorized: false, + resubscribe: false + }; + + wsmqttName = getWsmqttName(o.host); + + console.log("wsmqttpublich -> loadSettings from instance.options", instance.options); + } + else { + + const SETTINGS = FLOW.GLOBALS.settings; + backup_on_failure = SETTINGS.backup_on_failure; + saveTelemetryOnError = backup_on_failure; + + restore_from_backup = SETTINGS.restore_from_backup; + restore_backup_wait = SETTINGS.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; + + opts = { + host: mqtt_host, + port: mqtt_port, + keepalive: 10, + clientId: mqtt_clientid, + username: mqtt_username, + rejectUnauthorized: false, + resubscribe: false + }; + + wsmqttName = getWsmqttName(mqtt_host); + } + + connectToTbServer(); + } + + function connectToTbServer() { + 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"); + //monitor.info("MQTT client connected"); + + sendClientError = true; + clientReady = true; + wsmqtt_status = 'connected'; + }); + + client.on('reconnect', function() { + instance.status("Reconnecting", "yellow"); + clientReady = false; + }); + + client.on('message', function(topic, message) { + // message is type of buffer + message = message.toString(); + if (message[0] === '{') { + TRY(function() { + + message = JSON.parse(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 } }); + } + + }, () => instance.debug('MQTT: Error parsing data', message)); + } + + instance.send(SEND_TO.rpcCall, { "topic": topic, "content": message }); + }); + + client.on('close', function() { + clientReady = false; + wsmqtt_status = 'disconnected'; + + instance.status("Disconnected", "red"); + instance.send(SEND_TO.debug, { "message": "Client CLOSE signal received !" }); + }); + + client.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; + wsmqtt_status = 'disconnected'; + }); + + } + + + instance.on("0", _ => { + main(); + }) + + + instance.on('1', function(data) { + + if (clientReady) { + //do we have some data in backup file? if any, process data from database + if (saveTelemetryOnError) { + //read telemetry data and send back to server + if (!processingData) processDataFromDatabase(); + } + + let stringifiedJson = JSON.stringify(data.data); + client.publish("v1/gateway/telemetry", stringifiedJson, { qos: 1 }); + + //backup telemetry + if (createTelemetryBackup) { + data.data.id = UID(); + nosqlBackup.insert(data.data); + + insertBackupNoSqlCounter++; + if (insertBackupNoSqlCounter > 150) { + let options = { compress: true }; + let path = __dirname + "/../databases/backup/tbdata.nosql"; + var stream = new rollers.RollingFileStream(path, noSqlFileSizeLimit, 150, options); + stream.write(""); + stream.end(); + + insertBackupNoSqlCounter = 0; + } + } + + } + 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 (saveTelemetryOnError) { + //create new file from tbdata.nosql, if file size exceeds given limit, and clear tbdata.nosql + makeBackupFromDbFile(); + + //write to tb + data.data.id = UID(); + nosql.insert(data.data); + } + } + }); + + + instance.close = function(done) { + if (clientReady) { + client.end(); + clearInterval(sendWsStatusVar); + } + }; + + + function getDbBackupFileCounter(type) { + var files = fs.readdirSync(__dirname + "/../databases"); + + let counter = 0; + for (var i = 0; i < files.length; i++) { + + if (files[i] == "tbdata.nosql") continue; + + if (files[i].endsWith(".nosql")) { + + let pos = files[i].indexOf("."); + if (pos > -1) { + + let fileCounter = counter; + let firstDigit = files[i].slice(0, pos); + + fileCounter = parseInt(firstDigit); + if (isNaN(fileCounter)) fileCounter = 0; + //console.log("getDbBackupFileCounter digit:", files[i], firstDigit, fileCounter, isNaN(fileCounter), type); + + if (type == "max") { + if (fileCounter > counter) { + counter = fileCounter; + } + } + else if (type == "min") { + if (counter == 0) counter = fileCounter; + + if (fileCounter < counter) { + counter = fileCounter; + } + } + } + } + + } + + if (type == "max") counter++; + + return counter; + } + + const makeBackupFromDbFile = async () => { + + if (!saveTelemetryOnError) return; + + //to avoid large file: tbdata.nosql + + //init value is 0! + if (insertNoSqlCounter > 0) { + --insertNoSqlCounter; + return; + } + + insertNoSqlCounter = 100; + + let source = __dirname + "/../databases/tbdata.nosql"; + + var stats = fs.statSync(source); + var fileSizeInBytes = stats.size; + + if (fileSizeInBytes > noSqlFileSizeLimit) { + + let counter = 1; + counter = getDbBackupFileCounter("max"); + + let destination = __dirname + "/../databases/" + counter + "." + "tbdata.nosql"; + + //make backup file + fs.copyFileSync(source, destination); + //fs.renameSync(p, p + "." + counter); + + //clear tbdata.nosql + fs.writeFileSync(source, ""); + fs.truncateSync(source, 0); + + } + } + + const processDataFromDatabase = async () => { + + if (restore_from_backup <= 0) return; + + //calculate diff + const now = new Date(); + let currentTime = now.getTime(); + let diff = currentTime - lastRestoreTime; + + if ((diff / 1000) < restore_backup_wait) { + //console.log("*********restore_backup_wait", diff, restore_backup_wait); + return; + } + + processingData = true; + + //get filename to process + let counter = getDbBackupFileCounter("min"); + + //we have some backup files + let dataBase = 'tbdata'; + + var nosql; + if (counter == 0) dataBase = 'tbdata'; + else dataBase = counter + "." + 'tbdata'; + + nosql = NOSQL(dataBase); + + //select all data - use limit restore_from_backup + let records = await promisifyBuilder(nosql.find().take(restore_from_backup)); + + for (let i = 0; i < records.length; i++) { + if (clientReady) { + + let item = records[i]; + let id = item.id; + + if (id !== undefined) { + //console.log("------------processDataFromDatabase - remove", id, dataBase, i); + + try { + + let message = JSON.parse(JSON.stringify(item)); + delete message.id; + + client.publish("v1/gateway/telemetry", JSON.stringify(message), { qos: 1 }); + + //remove from database + await promisifyBuilder(nosql.remove().where("id", id)); + + } catch (error) { + //process error + console.log("processDataFromDatabase", error); + } + + } + + } + else { + processingData = false; + return; + } + } + + if (records.length > 0) { + //clean backup file + if (counter > 0) nosql.clean(); + } + + //no data in db, remove + if (records.length == 0) { + if (counter > 0) nosql.drop(); + } + + const d = new Date(); + lastRestoreTime = d.getTime(); + + processingData = false; + + } + + instance.on('options', main); + //instance.reconfigure(); +}; diff --git a/RVO53/monitor.txt b/RVO53/monitor.txt new file mode 100755 index 0000000..1f29883 --- /dev/null +++ b/RVO53/monitor.txt @@ -0,0 +1,8309 @@ +[2024-10-11T13:29:55.962] [INFO] monitorLogs - MQTT broker error Error: connect ECONNREFUSED 192.168.252.1:1883 + at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1159:16) { + errno: -111, + code: 'ECONNREFUSED', + syscall: 'connect', + address: '192.168.252.1', + port: 1883 +} +[2024-10-11T13:30:05.910] [INFO] monitorLogs - MQTT broker connected +[2024-10-11T18:28:57.282] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-10-11T18:28:57.286] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-10-11T18:28:57.289] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-10-11T18:41:03.980] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-11T18:41:04.015] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-11T18:41:04.051] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-12T03:31:50.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-12 03:31:50 +[2024-10-12T06:43:55.376] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-10-12T06:43:55.389] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-10-12T06:43:55.391] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-10-12T07:37:50.155] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-12T07:37:50.188] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-12T07:37:50.222] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-12T14:55:22.438] [INFO] monitorLogs - MQTT broker connected +[2024-10-12T18:26:16.894] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-10-12T18:26:16.897] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-10-12T18:26:16.900] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-10-12T18:39:02.616] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-12T18:39:02.650] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-12T18:39:02.684] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-13T03:31:51.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-13 03:31:51 +[2024-10-13T06:53:49.657] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-10-13T06:53:49.660] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-10-13T06:53:49.663] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-10-13T07:14:41.742] [INFO] monitorLogs - MQTT broker connected +[2024-10-13T07:39:20.109] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-13T07:39:20.143] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-13T07:39:20.177] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-13T18:21:08.536] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-10-13T18:21:08.539] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-10-13T18:21:08.542] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-10-13T18:37:04.051] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-13T18:37:04.086] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-13T18:37:04.121] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-14T03:31:52.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-14 03:31:52 +[2024-10-14T06:43:39.091] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-10-14T06:43:39.094] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-10-14T06:43:39.096] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-10-14T07:40:50.419] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-14T07:40:50.454] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-14T07:40:50.488] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-14T18:20:59.572] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-10-14T18:20:59.575] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-10-14T18:20:59.578] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-10-14T18:35:04.059] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-14T18:35:04.093] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-14T18:35:04.127] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-15T03:31:53.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-15 03:31:53 +[2024-10-15T06:44:13.107] [INFO] monitorLogs - MQTT broker connected +[2024-10-15T06:46:51.011] [INFO] monitorLogs - MQTT broker connected +[2024-10-15T06:48:53.562] [INFO] monitorLogs - MQTT broker connected +[2024-10-15T07:03:35.263] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-10-15T07:03:35.265] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-10-15T07:03:35.267] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-10-15T07:25:27.658] [INFO] monitorLogs - MQTT broker connected +[2024-10-15T07:27:49.057] [INFO] monitorLogs - MQTT broker connected +[2024-10-15T07:29:28.291] [INFO] monitorLogs - MQTT broker connected +[2024-10-15T07:32:58.896] [INFO] monitorLogs - MQTT broker connected +[2024-10-15T07:39:18.788] [INFO] monitorLogs - MQTT broker connected +[2024-10-15T07:42:21.136] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-15T07:42:21.171] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-15T07:42:21.205] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-15T07:44:50.601] [INFO] monitorLogs - MQTT broker connected +[2024-10-15T07:45:29.286] [INFO] monitorLogs - MQTT broker connected +[2024-10-15T07:46:16.429] [INFO] monitorLogs - MQTT broker connected +[2024-10-15T07:51:01.737] [INFO] monitorLogs - MQTT broker connected +[2024-10-15T07:52:43.957] [INFO] monitorLogs - MQTT broker connected +[2024-10-15T08:00:55.555] [INFO] monitorLogs - MQTT broker connected +[2024-10-15T08:07:49.389] [INFO] monitorLogs - MQTT broker connected +[2024-10-15T18:20:52.109] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-10-15T18:20:52.112] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-10-15T18:20:52.115] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-10-15T18:33:09.242] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-15T18:33:09.276] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-15T18:33:09.311] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-16T03:31:54.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-16 03:31:54 +[2024-10-16T06:48:23.733] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-10-16T06:48:23.735] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-10-16T06:48:23.737] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-10-16T07:43:52.169] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-16T07:43:52.202] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-16T07:43:52.236] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-16T08:52:36.603] [INFO] monitorLogs - MQTT broker connected +[2024-10-16T09:01:31.045] [INFO] monitorLogs - MQTT broker connected +[2024-10-16T09:02:11.839] [INFO] monitorLogs - MQTT broker connected +[2024-10-16T09:04:14.498] [INFO] monitorLogs - MQTT broker connected +[2024-10-16T09:06:33.078] [INFO] monitorLogs - MQTT broker connected +[2024-10-16T09:50:06.976] [INFO] monitorLogs - MQTT broker connected +[2024-10-16T09:57:56.551] [INFO] monitorLogs - MQTT broker connected +[2024-10-16T09:58:30.397] [INFO] monitorLogs - MQTT broker connected +[2024-10-16T10:02:49.090] [INFO] monitorLogs - MQTT broker connected +[2024-10-16T10:03:36.707] [INFO] monitorLogs - MQTT broker connected +[2024-10-16T10:04:54.386] [INFO] monitorLogs - MQTT broker connected +[2024-10-16T10:05:31.208] [INFO] monitorLogs - MQTT broker connected +[2024-10-16T10:30:04.676] [INFO] monitorLogs - MQTT broker connected +[2024-10-16T10:33:22.293] [INFO] monitorLogs - MQTT broker connected +[2024-10-16T10:34:25.404] [INFO] monitorLogs - MQTT broker connected +[2024-10-16T10:36:06.522] [INFO] monitorLogs - MQTT broker connected +[2024-10-16T10:40:24.179] [INFO] monitorLogs - MQTT broker connected +[2024-10-16T10:43:26.874] [INFO] monitorLogs - MQTT broker connected +[2024-10-16T10:49:50.499] [INFO] monitorLogs - MQTT broker connected +[2024-10-16T10:54:15.246] [INFO] monitorLogs - MQTT broker connected +[2024-10-16T10:55:07.459] [INFO] monitorLogs - MQTT broker connected +[2024-10-16T10:56:23.299] [INFO] monitorLogs - MQTT broker connected +[2024-10-16T13:54:29.001] [INFO] monitorLogs - MQTT broker connected +[2024-10-16T18:18:12.701] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-10-16T18:18:12.703] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-10-16T18:18:12.706] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-10-16T18:31:10.811] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-16T18:31:10.846] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-16T18:31:10.880] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-17T03:31:54.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-17 03:31:54 +[2024-10-17T06:53:15.133] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-10-17T06:53:15.135] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-10-17T06:53:15.138] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-10-17T07:45:23.808] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-17T07:45:23.844] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-17T07:45:23.879] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-17T08:32:22.690] [INFO] monitorLogs - MQTT broker connected +[2024-10-17T08:32:59.623] [INFO] monitorLogs - MQTT broker connected +[2024-10-17T08:36:38.643] [INFO] monitorLogs - MQTT broker connected +[2024-10-17T08:38:58.219] [INFO] monitorLogs - MQTT broker connected +[2024-10-17T08:43:10.853] [INFO] monitorLogs - MQTT broker connected +[2024-10-17T13:37:20.946] [INFO] monitorLogs - MQTT broker connected +[2024-10-17T13:38:53.971] [INFO] monitorLogs - MQTT broker connected +[2024-10-17T13:42:40.411] [INFO] monitorLogs - MQTT broker connected +[2024-10-17T13:43:59.336] [INFO] monitorLogs - MQTT broker connected +[2024-10-17T13:46:28.770] [INFO] monitorLogs - MQTT broker connected +[2024-10-17T13:48:59.414] [INFO] monitorLogs - MQTT broker connected +[2024-10-17T18:15:33.628] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-10-17T18:15:33.648] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-10-17T18:15:33.651] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-10-17T18:29:15.763] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-17T18:29:15.798] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-17T18:29:15.833] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-18T03:31:55.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-18 03:31:55 +[2024-10-18T06:50:37.079] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-10-18T06:50:37.082] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-10-18T06:50:37.084] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-10-18T07:46:55.471] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-18T07:46:55.506] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-18T07:46:55.541] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-18T16:22:17.793] [INFO] monitorLogs - MQTT broker error Error: Connection refused: Server unavailable + at MqttClient._handleConnack (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:1388:17) + at MqttClient._handlePacket (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:549:12) + at work (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:438:12) + at Writable.writable._write (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:452:5) + at doWrite (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:409:139) + at writeOrBuffer (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:398:5) + at Writable.write (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:307:11) + at Socket.ondata (internal/streams/readable.js:731:22) + at Socket.emit (events.js:400:28) + at addChunk (internal/streams/readable.js:293:12) { + code: 3 +} +[2024-10-18T16:22:38.868] [INFO] monitorLogs - MQTT broker error Error: Connection refused: Server unavailable + at MqttClient._handleConnack (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:1388:17) + at MqttClient._handlePacket (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:549:12) + at work (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:438:12) + at Writable.writable._write (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:452:5) + at doWrite (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:409:139) + at writeOrBuffer (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:398:5) + at Writable.write (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:307:11) + at Socket.ondata (internal/streams/readable.js:731:22) + at Socket.emit (events.js:400:28) + at addChunk (internal/streams/readable.js:293:12) { + code: 3 +} +[2024-10-18T16:22:52.308] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T17:20:13.414] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T17:20:14.153] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T17:27:58.501] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T17:29:24.903] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T17:30:30.543] [INFO] monitorLogs - MQTT broker error Error: Connection refused: Server unavailable + at MqttClient._handleConnack (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:1388:17) + at MqttClient._handlePacket (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:549:12) + at work (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:438:12) + at Writable.writable._write (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:452:5) + at doWrite (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:409:139) + at writeOrBuffer (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:398:5) + at Writable.write (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:307:11) + at Socket.ondata (internal/streams/readable.js:731:22) + at Socket.emit (events.js:400:28) + at addChunk (internal/streams/readable.js:293:12) { + code: 3 +} +[2024-10-18T17:30:30.692] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T17:31:23.933] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T17:31:59.960] [INFO] monitorLogs - MQTT broker error Error: Connection refused: Server unavailable + at MqttClient._handleConnack (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:1388:17) + at MqttClient._handlePacket (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:549:12) + at work (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:438:12) + at Writable.writable._write (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:452:5) + at doWrite (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:409:139) + at writeOrBuffer (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:398:5) + at Writable.write (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:307:11) + at Socket.ondata (internal/streams/readable.js:731:22) + at Socket.emit (events.js:400:28) + at addChunk (internal/streams/readable.js:293:12) { + code: 3 +} +[2024-10-18T17:40:47.665] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T17:40:47.826] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T17:50:05.537] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T17:50:06.231] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T17:54:27.084] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T17:54:27.246] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T18:03:30.459] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T18:03:30.615] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T18:14:51.598] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T18:15:26.223] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-10-18T18:15:26.226] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-10-18T18:15:26.228] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-10-18T18:15:35.757] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T18:20:06.070] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T18:27:20.562] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-18T18:27:20.598] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-18T18:27:20.633] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-18T18:36:52.531] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T18:36:52.772] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T18:36:52.995] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T20:02:00.005] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T20:03:33.140] [INFO] monitorLogs - MQTT broker error Error: Connection refused: Server unavailable + at MqttClient._handleConnack (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:1388:17) + at MqttClient._handlePacket (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:549:12) + at work (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:438:12) + at Writable.writable._write (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:452:5) + at doWrite (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:409:139) + at writeOrBuffer (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:398:5) + at Writable.write (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:307:11) + at Socket.ondata (internal/streams/readable.js:731:22) + at Socket.emit (events.js:400:28) + at addChunk (internal/streams/readable.js:293:12) { + code: 3 +} +[2024-10-18T20:03:33.304] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T20:06:39.381] [INFO] monitorLogs - MQTT broker error Error: Connection refused: Server unavailable + at MqttClient._handleConnack (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:1388:17) + at MqttClient._handlePacket (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:549:12) + at work (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:438:12) + at Writable.writable._write (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:452:5) + at doWrite (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:409:139) + at writeOrBuffer (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:398:5) + at Writable.write (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:307:11) + at Socket.ondata (internal/streams/readable.js:731:22) + at Socket.emit (events.js:400:28) + at addChunk (internal/streams/readable.js:293:12) { + code: 3 +} +[2024-10-18T20:30:06.934] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T20:30:07.112] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T20:44:10.239] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T20:51:56.152] [INFO] monitorLogs - MQTT broker connected +[2024-10-18T23:24:51.176] [INFO] monitorLogs - MQTT broker error Error: Connection refused: Server unavailable + at MqttClient._handleConnack (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:1388:17) + at MqttClient._handlePacket (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:549:12) + at work (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:438:12) + at Writable.writable._write (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:452:5) + at doWrite (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:409:139) + at writeOrBuffer (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:398:5) + at Writable.write (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:307:11) + at Socket.ondata (internal/streams/readable.js:731:22) + at Socket.emit (events.js:400:28) + at addChunk (internal/streams/readable.js:293:12) { + code: 3 +} +[2024-10-18T23:24:58.536] [INFO] monitorLogs - MQTT broker connected +[2024-10-19T03:31:56.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-19 03:31:56 +[2024-10-19T06:58:01.128] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-10-19T06:58:01.130] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-10-19T06:58:01.132] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-10-19T07:48:27.661] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-19T07:48:27.695] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-19T07:48:27.729] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-19T17:03:21.418] [INFO] monitorLogs - MQTT broker error Error: Connection refused: Server unavailable + at MqttClient._handleConnack (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:1388:17) + at MqttClient._handlePacket (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:549:12) + at work (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:438:12) + at Writable.writable._write (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:452:5) + at doWrite (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:409:139) + at writeOrBuffer (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:398:5) + at Writable.write (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:307:11) + at Socket.ondata (internal/streams/readable.js:731:22) + at Socket.emit (events.js:400:28) + at addChunk (internal/streams/readable.js:293:12) { + code: 3 +} +[2024-10-19T17:03:28.783] [INFO] monitorLogs - MQTT broker connected +[2024-10-19T18:10:16.341] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-10-19T18:10:16.344] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-10-19T18:10:16.347] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-10-19T18:25:25.828] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-19T18:25:25.863] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-19T18:25:25.897] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-20T03:31:56.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-20 03:31:56 +[2024-10-20T06:52:50.238] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-10-20T06:52:50.240] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-10-20T06:52:50.243] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-10-20T07:50:00.161] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-20T07:50:00.197] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-20T07:50:00.232] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-20T14:29:13.280] [INFO] monitorLogs - MQTT broker error Error: Connection refused: Server unavailable + at MqttClient._handleConnack (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:1388:17) + at MqttClient._handlePacket (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:549:12) + at work (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:438:12) + at Writable.writable._write (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:452:5) + at doWrite (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:409:139) + at writeOrBuffer (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:398:5) + at Writable.write (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:307:11) + at Socket.ondata (internal/streams/readable.js:731:22) + at Socket.emit (events.js:400:28) + at addChunk (internal/streams/readable.js:293:12) { + code: 3 +} +[2024-10-20T14:29:13.443] [INFO] monitorLogs - MQTT broker connected +[2024-10-20T18:10:06.679] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-10-20T18:10:06.681] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-10-20T18:10:06.684] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-10-20T18:23:31.841] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-20T18:23:31.876] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-20T18:23:31.911] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-21T03:22:57.269] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T03:23:48.419] [INFO] monitorLogs - MQTT broker error Error: Connection refused: Server unavailable + at MqttClient._handleConnack (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:1388:17) + at MqttClient._handlePacket (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:549:12) + at work (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:438:12) + at Writable.writable._write (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:452:5) + at doWrite (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:409:139) + at writeOrBuffer (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:398:5) + at Writable.write (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:307:11) + at Socket.ondata (internal/streams/readable.js:731:22) + at Socket.emit (events.js:400:28) + at addChunk (internal/streams/readable.js:293:12) { + code: 3 +} +[2024-10-21T03:23:57.440] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T03:24:28.833] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T03:31:57.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-21 03:31:57 +[2024-10-21T03:51:33.526] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T03:51:33.671] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T04:10:17.502] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T04:10:17.632] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T04:21:07.437] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T04:37:31.779] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T04:45:55.018] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T06:55:11.983] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-10-21T06:55:11.986] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-10-21T06:55:11.988] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-10-21T06:58:34.443] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T06:59:56.413] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T06:59:56.537] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T07:51:32.930] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-21T07:51:32.965] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-21T07:51:33.000] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-21T07:59:58.250] [INFO] monitorLogs - MQTT broker error Error: Connection refused: Server unavailable + at MqttClient._handleConnack (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:1388:17) + at MqttClient._handlePacket (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:549:12) + at work (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:438:12) + at Writable.writable._write (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:452:5) + at doWrite (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:409:139) + at writeOrBuffer (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:398:5) + at Writable.write (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:307:11) + at Socket.ondata (internal/streams/readable.js:731:22) + at Socket.emit (events.js:400:28) + at addChunk (internal/streams/readable.js:293:12) { + code: 3 +} +[2024-10-21T08:00:07.955] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T09:11:23.609] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T09:11:24.158] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T09:22:04.302] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T09:55:21.715] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T09:55:22.123] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T10:04:14.211] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T10:06:57.023] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T10:07:34.405] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T10:23:09.717] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T10:23:10.604] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T10:36:42.335] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T10:40:55.134] [INFO] monitorLogs - MQTT broker error Error: Connection refused: Server unavailable + at MqttClient._handleConnack (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:1388:17) + at MqttClient._handlePacket (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:549:12) + at work (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:438:12) + at Writable.writable._write (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:452:5) + at doWrite (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:409:139) + at writeOrBuffer (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:398:5) + at Writable.write (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:307:11) + at Socket.ondata (internal/streams/readable.js:731:22) + at Socket.emit (events.js:400:28) + at addChunk (internal/streams/readable.js:293:12) { + code: 3 +} +[2024-10-21T10:44:26.754] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T10:44:36.262] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T11:45:20.703] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T11:45:20.941] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T11:54:51.573] [INFO] monitorLogs - MQTT broker error Error: Connection refused: Server unavailable + at MqttClient._handleConnack (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:1388:17) + at MqttClient._handlePacket (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:549:12) + at work (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:438:12) + at Writable.writable._write (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:452:5) + at doWrite (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:409:139) + at writeOrBuffer (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:398:5) + at Writable.write (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:307:11) + at Socket.ondata (internal/streams/readable.js:731:22) + at Socket.emit (events.js:400:28) + at addChunk (internal/streams/readable.js:293:12) { + code: 3 +} +[2024-10-21T11:56:16.049] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T11:56:16.198] [INFO] monitorLogs - MQTT broker connected +[2024-10-21T18:09:58.030] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-10-21T18:09:58.033] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-10-21T18:09:58.035] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-10-21T18:21:39.222] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-21T18:21:39.258] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-21T18:21:39.292] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-22T03:31:58.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-22 03:31:58 +[2024-10-22T06:57:34.509] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-10-22T06:57:34.512] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-10-22T06:57:34.515] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-10-22T07:53:06.251] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-22T07:53:06.285] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-22T07:53:06.319] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-22T18:09:50.468] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-10-22T18:09:50.471] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-10-22T18:09:50.474] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-10-22T18:19:49.983] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-22T18:19:50.018] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-22T18:19:50.052] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-23T03:31:59.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-23 03:31:59 +[2024-10-23T07:07:28.216] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-10-23T07:07:28.219] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-10-23T07:07:28.221] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-10-23T07:54:39.787] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-23T07:54:39.821] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-23T07:54:39.855] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-23T18:02:10.246] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-10-23T18:02:10.249] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-10-23T18:02:10.251] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-10-23T18:17:58.700] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-23T18:17:58.734] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-23T18:17:58.769] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-24T03:32:00.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-24 03:32:00 +[2024-10-24T07:04:49.070] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-10-24T07:04:49.073] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-10-24T07:04:49.075] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-10-24T07:56:13.416] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-24T07:56:13.450] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-24T07:56:13.484] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-24T10:29:10.532] [INFO] monitorLogs - MQTT broker connected +[2024-10-24T18:02:01.456] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-10-24T18:02:01.458] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-10-24T18:02:01.461] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-10-24T18:16:12.050] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-24T18:16:12.086] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-24T18:16:12.120] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-25T03:32:00.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-25 03:32:00 +[2024-10-25T07:09:41.731] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-10-25T07:09:41.734] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-10-25T07:09:41.736] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-10-25T07:57:47.523] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-25T07:57:47.558] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-25T07:57:47.592] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-25T14:15:21.147] [INFO] monitorLogs - DI_DO_Relay_Controller installed +[2024-10-25T14:15:21.505] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 true turn off on startup +[2024-10-25T14:15:21.507] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 true turn off on startup +[2024-10-25T14:15:21.508] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 true turn off on startup +[2024-10-25T14:15:23.230] [INFO] monitorLogs - MQTT broker connected +[2024-10-25T14:15:24.523] [INFO] monitorLogs - buildTasks - params undefined +[2024-10-25T14:15:24.525] [INFO] monitorLogs - buildTasks: profile for line 1 +[2024-10-25T14:15:24.525] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2024-10-25T14:15:24.530] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-10-25T14:15:24.532] [INFO] monitorLogs - luxOff: turn off line: 1 2024-10-26T05:57:00.531Z +[2024-10-25T14:15:24.533] [INFO] monitorLogs - luxOn: turn on line: 1 2024-10-25T16:14:00.533Z +[2024-10-25T14:15:24.533] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:57', name: 'luxOff' }, + { value: 1, start_time: '18:14', name: 'luxOn' } +] +[2024-10-25T14:15:24.534] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2024-10-25T14:15:24.535] [INFO] monitorLogs - buildTasks: profile for line 2 +[2024-10-25T14:15:24.536] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2024-10-25T14:15:24.538] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-10-25T14:15:24.539] [INFO] monitorLogs - luxOff: turn off line: 2 2024-10-26T05:57:00.539Z +[2024-10-25T14:15:24.539] [INFO] monitorLogs - luxOn: turn on line: 2 2024-10-25T16:14:00.539Z +[2024-10-25T14:15:24.540] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:57', name: 'luxOff' }, + { value: 1, start_time: '18:14', name: 'luxOn' } +] +[2024-10-25T14:15:24.541] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2024-10-25T14:15:24.542] [INFO] monitorLogs - buildTasks: profile for line 3 +[2024-10-25T14:15:24.542] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2024-10-25T14:15:24.544] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-10-25T14:15:24.545] [INFO] monitorLogs - luxOff: turn off line: 3 2024-10-26T05:57:00.545Z +[2024-10-25T14:15:24.546] [INFO] monitorLogs - luxOn: turn on line: 3 2024-10-25T16:14:00.546Z +[2024-10-25T14:15:24.546] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:57', name: 'luxOff' }, + { value: 1, start_time: '18:14', name: 'luxOn' } +] +[2024-10-25T14:15:24.547] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2024-10-25T14:15:24.554] [INFO] monitorLogs - tasks created: 976 +[2024-10-25T14:15:24.561] [INFO] monitorLogs - -->FLOW bol spustený d5xjWYMwEJon6rLlK7yEaP7qgV4DaOeNB9ZX3Gzb 2024-07-08 +[2024-10-25T14:15:24.865] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-25T14:15:24.902] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-25T14:15:24.939] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-25T16:35:40.799] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false command received form platform +[2024-10-25T16:35:48.474] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false command received form platform +[2024-10-25T16:35:54.547] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false command received form platform +[2024-10-25T17:56:47.084] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-10-25T17:56:47.088] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-10-25T17:56:47.092] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-10-25T18:14:01.236] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-25T18:14:01.273] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-25T18:14:01.309] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-26T03:15:22.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-26 03:15:22 +[2024-10-26T07:27:03.452] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-10-26T07:27:03.456] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-10-26T07:27:03.458] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-10-26T07:57:00.731] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-26T07:57:00.767] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-26T07:57:00.803] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-26T17:56:40.324] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-10-26T17:56:40.328] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-10-26T17:56:40.331] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-10-26T18:12:39.778] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-26T18:12:39.812] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-26T18:12:39.847] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-27T03:15:23.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-27 03:15:23 +[2024-10-27T06:11:52.982] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-10-27T06:11:52.985] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-10-27T06:11:52.988] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-10-27T07:00:56.668] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-27T07:00:56.702] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-27T07:00:56.737] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-27T16:41:50.649] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2024-10-27T16:41:50.991] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 true turn off on startup +[2024-10-27T16:41:51.006] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 true turn off on startup +[2024-10-27T16:41:51.012] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 true turn off on startup +[2024-10-27T16:41:51.155] [INFO] monitorLogs - MQTT broker connected +[2024-10-27T16:41:56.024] [INFO] monitorLogs - buildTasks - params undefined +[2024-10-27T16:41:56.026] [INFO] monitorLogs - buildTasks: profile for line 1 +[2024-10-27T16:41:56.027] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2024-10-27T16:41:56.032] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-10-27T16:41:56.033] [INFO] monitorLogs - luxOff: turn off line: 1 2024-10-28T06:00:00.033Z +[2024-10-27T16:41:56.035] [INFO] monitorLogs - luxOn: turn on line: 1 2024-10-27T16:10:00.035Z +[2024-10-27T16:41:56.036] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:0', name: 'luxOff' }, + { value: 1, start_time: '17:10', name: 'luxOn' } +] +[2024-10-27T16:41:56.037] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2024-10-27T16:41:56.037] [INFO] monitorLogs - buildTasks: profile for line 2 +[2024-10-27T16:41:56.038] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2024-10-27T16:41:56.040] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-10-27T16:41:56.041] [INFO] monitorLogs - luxOff: turn off line: 2 2024-10-28T06:00:00.041Z +[2024-10-27T16:41:56.042] [INFO] monitorLogs - luxOn: turn on line: 2 2024-10-27T16:10:00.042Z +[2024-10-27T16:41:56.043] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:0', name: 'luxOff' }, + { value: 1, start_time: '17:10', name: 'luxOn' } +] +[2024-10-27T16:41:56.044] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2024-10-27T16:41:56.045] [INFO] monitorLogs - buildTasks: profile for line 3 +[2024-10-27T16:41:56.046] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2024-10-27T16:41:56.048] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-10-27T16:41:56.049] [INFO] monitorLogs - luxOff: turn off line: 3 2024-10-28T06:00:00.049Z +[2024-10-27T16:41:56.050] [INFO] monitorLogs - luxOn: turn on line: 3 2024-10-27T16:10:00.050Z +[2024-10-27T16:41:56.050] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:0', name: 'luxOff' }, + { value: 1, start_time: '17:10', name: 'luxOn' } +] +[2024-10-27T16:41:56.051] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2024-10-27T16:41:56.058] [INFO] monitorLogs - tasks created: 974 +[2024-10-27T16:41:56.061] [INFO] monitorLogs - -->FLOW bol spustený d5xjWYMwEJon6rLlK7yEaP7qgV4DaOeNB9ZX3Gzb 2024-09-23 +[2024-10-27T16:41:56.367] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-27T16:41:56.408] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-27T16:41:56.444] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-27T16:55:03.844] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-10-27T16:55:03.851] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-10-27T16:55:03.858] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-10-27T17:10:01.050] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-27T17:10:01.088] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-27T17:10:01.124] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-28T03:41:51.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-28 03:41:51 +[2024-10-28T06:10:16.095] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-10-28T06:10:16.115] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-10-28T06:10:16.120] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-10-28T07:00:00.222] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-28T07:00:00.257] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-28T07:00:00.293] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-28T12:43:22.106] [INFO] monitorLogs - MQTT broker connected +[2024-10-28T12:45:02.430] [INFO] monitorLogs - MQTT broker connected +[2024-10-28T12:47:06.273] [INFO] monitorLogs - MQTT broker connected +[2024-10-28T12:47:45.936] [INFO] monitorLogs - MQTT broker connected +[2024-10-28T12:51:11.164] [INFO] monitorLogs - MQTT broker connected +[2024-10-28T15:26:02.995] [INFO] monitorLogs - MQTT broker connected +[2024-10-28T15:35:28.643] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false command received form platform +[2024-10-28T15:35:57.544] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false command received form platform +[2024-10-28T15:36:07.794] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false command received form platform +[2024-10-28T16:33:44.121] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2024-10-28T16:33:44.553] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 true turn off on startup +[2024-10-28T16:33:44.567] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 true turn off on startup +[2024-10-28T16:33:44.573] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 true turn off on startup +[2024-10-28T16:33:46.029] [INFO] monitorLogs - MQTT broker connected +[2024-10-28T16:33:49.584] [INFO] monitorLogs - buildTasks - params undefined +[2024-10-28T16:33:49.585] [INFO] monitorLogs - buildTasks: profile for line 1 +[2024-10-28T16:33:49.586] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2024-10-28T16:33:49.591] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-10-28T16:33:49.593] [INFO] monitorLogs - luxOff: turn off line: 1 2024-10-29T06:02:00.592Z +[2024-10-28T16:33:49.595] [INFO] monitorLogs - luxOn: turn on line: 1 2024-10-28T16:09:00.595Z +[2024-10-28T16:33:49.596] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:2', name: 'luxOff' }, + { value: 1, start_time: '17:9', name: 'luxOn' } +] +[2024-10-28T16:33:49.597] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2024-10-28T16:33:49.598] [INFO] monitorLogs - buildTasks: profile for line 2 +[2024-10-28T16:33:49.598] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2024-10-28T16:33:49.600] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-10-28T16:33:49.601] [INFO] monitorLogs - luxOff: turn off line: 2 2024-10-29T06:02:00.601Z +[2024-10-28T16:33:49.602] [INFO] monitorLogs - luxOn: turn on line: 2 2024-10-28T16:09:00.602Z +[2024-10-28T16:33:49.602] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:2', name: 'luxOff' }, + { value: 1, start_time: '17:9', name: 'luxOn' } +] +[2024-10-28T16:33:49.603] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2024-10-28T16:33:49.604] [INFO] monitorLogs - buildTasks: profile for line 3 +[2024-10-28T16:33:49.605] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2024-10-28T16:33:49.607] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-10-28T16:33:49.607] [INFO] monitorLogs - luxOff: turn off line: 3 2024-10-29T06:02:00.607Z +[2024-10-28T16:33:49.608] [INFO] monitorLogs - luxOn: turn on line: 3 2024-10-28T16:09:00.608Z +[2024-10-28T16:33:49.609] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:2', name: 'luxOff' }, + { value: 1, start_time: '17:9', name: 'luxOn' } +] +[2024-10-28T16:33:49.610] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2024-10-28T16:33:49.616] [INFO] monitorLogs - tasks created: 974 +[2024-10-28T16:33:49.623] [INFO] monitorLogs - -->FLOW bol spustený d5xjWYMwEJon6rLlK7yEaP7qgV4DaOeNB9ZX3Gzb 2024-09-23 +[2024-10-28T16:33:49.926] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-28T16:33:49.963] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-28T16:33:50.001] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-28T16:54:28.864] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-10-28T16:54:28.872] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-10-28T16:54:28.879] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-10-28T17:09:01.152] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-28T17:09:01.189] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-28T17:09:01.225] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-28T19:38:55.117] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2024-10-28T19:38:55.539] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 true turn off on startup +[2024-10-28T19:38:55.553] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 true turn off on startup +[2024-10-28T19:38:55.559] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 true turn off on startup +[2024-10-28T19:38:56.816] [INFO] monitorLogs - MQTT broker connected +[2024-10-28T19:39:00.570] [INFO] monitorLogs - buildTasks - params undefined +[2024-10-28T19:39:00.572] [INFO] monitorLogs - buildTasks: profile for line 1 +[2024-10-28T19:39:00.573] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2024-10-28T19:39:00.577] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-10-28T19:39:00.579] [INFO] monitorLogs - luxOff: turn off line: 1 2024-10-29T06:02:00.578Z +[2024-10-28T19:39:00.580] [INFO] monitorLogs - luxOn: turn on line: 1 2024-10-29T16:09:00.580Z +[2024-10-28T19:39:00.581] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:2', name: 'luxOff' }, + { value: 1, start_time: '17:9', name: 'luxOn' } +] +[2024-10-28T19:39:00.583] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2024-10-28T19:39:00.583] [INFO] monitorLogs - buildTasks: profile for line 2 +[2024-10-28T19:39:00.584] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2024-10-28T19:39:00.586] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-10-28T19:39:00.587] [INFO] monitorLogs - luxOff: turn off line: 2 2024-10-29T06:02:00.587Z +[2024-10-28T19:39:00.588] [INFO] monitorLogs - luxOn: turn on line: 2 2024-10-29T16:09:00.588Z +[2024-10-28T19:39:00.588] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:2', name: 'luxOff' }, + { value: 1, start_time: '17:9', name: 'luxOn' } +] +[2024-10-28T19:39:00.589] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2024-10-28T19:39:00.590] [INFO] monitorLogs - buildTasks: profile for line 3 +[2024-10-28T19:39:00.591] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2024-10-28T19:39:00.593] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-10-28T19:39:00.593] [INFO] monitorLogs - luxOff: turn off line: 3 2024-10-29T06:02:00.593Z +[2024-10-28T19:39:00.594] [INFO] monitorLogs - luxOn: turn on line: 3 2024-10-29T16:09:00.594Z +[2024-10-28T19:39:00.595] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:2', name: 'luxOff' }, + { value: 1, start_time: '17:9', name: 'luxOn' } +] +[2024-10-28T19:39:00.595] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2024-10-28T19:39:00.602] [INFO] monitorLogs - tasks created: 974 +[2024-10-28T19:39:00.605] [INFO] monitorLogs - -->FLOW bol spustený d5xjWYMwEJon6rLlK7yEaP7qgV4DaOeNB9ZX3Gzb 2024-09-23 +[2024-10-28T19:39:00.913] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-28T19:39:00.953] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-28T19:39:00.996] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-29T03:38:55.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-29 03:38:55 +[2024-10-29T06:19:16.477] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-10-29T06:19:16.508] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-10-29T06:19:16.515] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-10-29T07:02:00.581] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-29T07:02:00.617] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-29T07:02:00.653] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-29T09:23:12.066] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2024-10-29T09:23:12.475] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 true turn off on startup +[2024-10-29T09:23:12.491] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 true turn off on startup +[2024-10-29T09:23:12.496] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 true turn off on startup +[2024-10-29T09:23:14.065] [INFO] monitorLogs - MQTT broker connected +[2024-10-29T09:23:17.508] [INFO] monitorLogs - buildTasks - params undefined +[2024-10-29T09:23:17.510] [INFO] monitorLogs - buildTasks: profile for line 1 +[2024-10-29T09:23:17.510] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2024-10-29T09:23:17.515] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-10-29T09:23:17.517] [INFO] monitorLogs - luxOff: turn off line: 1 2024-10-30T06:04:00.516Z +[2024-10-29T09:23:17.518] [INFO] monitorLogs - luxOn: turn on line: 1 2024-10-29T16:07:00.518Z +[2024-10-29T09:23:17.519] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:4', name: 'luxOff' }, + { value: 1, start_time: '17:7', name: 'luxOn' } +] +[2024-10-29T09:23:17.520] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2024-10-29T09:23:17.521] [INFO] monitorLogs - buildTasks: profile for line 2 +[2024-10-29T09:23:17.521] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2024-10-29T09:23:17.524] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-10-29T09:23:17.525] [INFO] monitorLogs - luxOff: turn off line: 2 2024-10-30T06:04:00.524Z +[2024-10-29T09:23:17.525] [INFO] monitorLogs - luxOn: turn on line: 2 2024-10-29T16:07:00.525Z +[2024-10-29T09:23:17.526] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:4', name: 'luxOff' }, + { value: 1, start_time: '17:7', name: 'luxOn' } +] +[2024-10-29T09:23:17.527] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2024-10-29T09:23:17.527] [INFO] monitorLogs - buildTasks: profile for line 3 +[2024-10-29T09:23:17.528] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2024-10-29T09:23:17.530] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-10-29T09:23:17.531] [INFO] monitorLogs - luxOff: turn off line: 3 2024-10-30T06:04:00.531Z +[2024-10-29T09:23:17.531] [INFO] monitorLogs - luxOn: turn on line: 3 2024-10-29T16:07:00.531Z +[2024-10-29T09:23:17.532] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:4', name: 'luxOff' }, + { value: 1, start_time: '17:7', name: 'luxOn' } +] +[2024-10-29T09:23:17.533] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2024-10-29T09:23:17.539] [INFO] monitorLogs - tasks created: 974 +[2024-10-29T09:23:17.542] [INFO] monitorLogs - -->FLOW bol spustený d5xjWYMwEJon6rLlK7yEaP7qgV4DaOeNB9ZX3Gzb 2024-09-23 +[2024-10-29T09:23:17.849] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-29T09:23:17.889] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-29T09:23:17.927] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-29T09:24:49.129] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false command received form platform +[2024-10-29T09:25:03.367] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false command received form platform +[2024-10-29T09:25:15.691] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false command received form platform +[2024-10-29T09:32:21.346] [INFO] monitorLogs - MQTT broker connected +[2024-10-29T09:50:39.310] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false command received form platform +[2024-10-29T09:50:53.545] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false command received form platform +[2024-10-29T09:51:08.924] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false command received form platform +[2024-10-29T09:56:39.923] [INFO] monitorLogs - MQTT broker connected +[2024-10-29T16:52:55.057] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-10-29T16:52:55.065] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-10-29T16:52:55.072] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-10-29T17:07:01.284] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-29T17:07:01.320] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-29T17:07:01.356] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-30T03:23:13.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-30 03:23:13 +[2024-10-30T06:15:39.412] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-10-30T06:15:39.423] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-10-30T06:15:39.428] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-10-30T07:04:00.819] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-30T07:04:00.855] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-30T07:04:00.897] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-30T10:53:22.734] [INFO] monitorLogs - MQTT broker connected +[2024-10-30T12:54:26.170] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false command received form platform +[2024-10-30T12:54:46.523] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false command received form platform +[2024-10-30T12:54:52.772] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false command received form platform +[2024-10-30T13:08:02.913] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false command received form platform +[2024-10-30T13:08:09.692] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false command received form platform +[2024-10-30T13:08:16.115] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false command received form platform +[2024-10-30T16:52:48.141] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-10-30T16:52:48.152] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-10-30T16:52:48.157] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-10-30T17:05:46.111] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-30T17:05:46.147] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-30T17:05:46.182] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-31T03:23:14.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-10-31 03:23:14 +[2024-10-31T06:28:04.761] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-10-31T06:28:04.800] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-10-31T06:28:04.806] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-10-31T07:07:17.508] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-10-31T07:07:17.543] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-31T07:07:17.577] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-31T16:47:40.642] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-10-31T16:47:40.652] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-10-31T16:47:40.657] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-10-31T17:04:09.707] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-10-31T17:04:09.743] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-10-31T17:04:09.778] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-01T03:23:14.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-01 03:23:14 +[2024-11-01T06:25:25.455] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-11-01T06:25:25.476] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-11-01T06:25:25.482] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-11-01T07:08:52.993] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-01T07:08:53.027] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-01T07:08:53.062] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-01T16:47:30.892] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-11-01T16:47:30.909] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-11-01T16:47:30.914] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-11-01T17:02:32.012] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-01T17:02:32.047] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-01T17:02:32.081] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-02T03:23:15.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-02 03:23:15 +[2024-11-02T06:35:18.824] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-11-02T06:35:18.833] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-11-02T06:35:18.847] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-11-02T07:10:28.764] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-02T07:10:28.799] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-02T07:10:28.834] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-02T16:44:51.562] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-11-02T16:44:51.568] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-11-02T16:44:51.572] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-11-02T17:00:53.592] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-02T17:00:53.626] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-02T17:00:53.661] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-03T03:23:16.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-03 03:23:16 +[2024-11-03T06:22:37.891] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-11-03T06:22:37.899] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-11-03T06:22:37.904] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-11-03T07:12:04.360] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-03T07:12:04.395] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-03T07:12:04.429] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-03T16:44:43.531] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-11-03T16:44:43.542] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-11-03T16:44:43.546] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-11-03T16:59:21.646] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-03T16:59:21.680] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-03T16:59:21.715] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-04T03:23:17.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-04 03:23:17 +[2024-11-04T06:19:58.888] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-11-04T06:19:58.902] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-11-04T06:19:58.909] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-11-04T07:13:40.316] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-04T07:13:40.350] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-04T07:13:40.385] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-04T10:33:01.369] [INFO] monitorLogs - MQTT broker connected +[2024-11-04T14:12:44.436] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2024-11-04T14:12:44.767] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 true turn off on startup +[2024-11-04T14:12:44.782] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 true turn off on startup +[2024-11-04T14:12:44.788] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 true turn off on startup +[2024-11-04T14:12:45.015] [INFO] monitorLogs - MQTT broker connected +[2024-11-04T14:12:49.801] [INFO] monitorLogs - buildTasks - params undefined +[2024-11-04T14:12:49.803] [INFO] monitorLogs - buildTasks: profile for line 1 +[2024-11-04T14:12:49.804] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2024-11-04T14:12:49.809] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-04T14:12:49.810] [INFO] monitorLogs - luxOff: turn off line: 1 2024-11-05T06:13:00.809Z +[2024-11-04T14:12:49.812] [INFO] monitorLogs - luxOn: turn on line: 1 2024-11-04T15:57:00.812Z +[2024-11-04T14:12:49.813] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:13', name: 'luxOff' }, + { value: 1, start_time: '16:57', name: 'luxOn' } +] +[2024-11-04T14:12:49.814] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2024-11-04T14:12:49.814] [INFO] monitorLogs - buildTasks: profile for line 2 +[2024-11-04T14:12:49.815] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2024-11-04T14:12:49.818] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-04T14:12:49.818] [INFO] monitorLogs - luxOff: turn off line: 2 2024-11-05T06:13:00.818Z +[2024-11-04T14:12:49.819] [INFO] monitorLogs - luxOn: turn on line: 2 2024-11-04T15:57:00.819Z +[2024-11-04T14:12:49.820] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:13', name: 'luxOff' }, + { value: 1, start_time: '16:57', name: 'luxOn' } +] +[2024-11-04T14:12:49.821] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2024-11-04T14:12:49.821] [INFO] monitorLogs - buildTasks: profile for line 3 +[2024-11-04T14:12:49.822] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2024-11-04T14:12:49.824] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-04T14:12:49.825] [INFO] monitorLogs - luxOff: turn off line: 3 2024-11-05T06:13:00.825Z +[2024-11-04T14:12:49.826] [INFO] monitorLogs - luxOn: turn on line: 3 2024-11-04T15:57:00.825Z +[2024-11-04T14:12:49.826] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:13', name: 'luxOff' }, + { value: 1, start_time: '16:57', name: 'luxOn' } +] +[2024-11-04T14:12:49.827] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2024-11-04T14:12:49.834] [INFO] monitorLogs - tasks created: 974 +[2024-11-04T14:12:49.837] [INFO] monitorLogs - -->FLOW bol spustený d5xjWYMwEJon6rLlK7yEaP7qgV4DaOeNB9ZX3Gzb 2024-09-23 +[2024-11-04T14:12:50.144] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-04T14:12:50.181] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-04T14:12:50.219] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-04T16:43:56.129] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-11-04T16:43:56.141] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-11-04T16:43:56.148] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-11-04T16:57:01.368] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-04T16:57:01.405] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-04T16:57:01.442] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-05T03:12:44.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-05 03:12:44 +[2024-11-05T06:19:10.997] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-11-05T06:19:11.011] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-11-05T06:19:11.016] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-11-05T07:13:01.016] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-05T07:13:01.050] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-05T07:13:01.086] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-05T08:05:52.159] [INFO] monitorLogs - MQTT broker connected +[2024-11-05T08:34:01.553] [INFO] monitorLogs - MQTT broker connected +[2024-11-05T16:41:17.690] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-11-05T16:41:17.700] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-11-05T16:41:17.705] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-11-05T16:56:17.891] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-05T16:56:17.928] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-05T16:56:17.963] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-05T22:56:07.185] [INFO] monitorLogs - MQTT broker connected +[2024-11-06T03:12:45.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-06 03:12:45 +[2024-11-06T06:21:34.370] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-11-06T06:21:34.379] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-11-06T06:21:34.384] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-11-06T07:16:51.975] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-06T07:16:52.011] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-06T07:16:52.045] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-06T16:41:09.507] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-11-06T16:41:09.514] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-11-06T16:41:09.520] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-11-06T16:54:47.475] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-06T16:54:47.510] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-06T16:54:47.545] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-07T01:40:58.595] [INFO] monitorLogs - MQTT broker connected +[2024-11-07T03:12:46.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-07 03:12:46 +[2024-11-07T06:23:58.290] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-11-07T06:23:58.313] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-11-07T06:23:58.318] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-11-07T07:18:27.863] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-07T07:18:27.897] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-07T07:18:27.932] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-07T16:41:04.238] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-11-07T16:41:04.265] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-11-07T16:41:04.271] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-11-07T16:53:19.679] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-07T16:53:19.714] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-07T16:53:19.748] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-08T03:12:47.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-08 03:12:47 +[2024-11-08T06:26:24.527] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-11-08T06:26:24.536] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-11-08T06:26:24.541] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-11-08T07:20:03.227] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-08T07:20:03.263] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-08T07:20:03.299] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-08T16:38:59.006] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-11-08T16:38:59.014] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-11-08T16:38:59.019] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-11-08T16:51:54.552] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-08T16:51:54.587] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-08T16:51:54.622] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-09T03:12:47.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-09 03:12:47 +[2024-11-09T06:26:45.475] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-11-09T06:26:45.493] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-11-09T06:26:45.497] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-11-09T07:21:38.972] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-09T07:21:39.007] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-09T07:21:39.043] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-09T16:36:18.157] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-11-09T16:36:18.165] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-11-09T16:36:18.170] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-11-09T16:50:28.806] [INFO] monitorLogs - turnOnLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-09T16:50:28.841] [INFO] monitorLogs - turnOnLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-09T16:50:28.878] [INFO] monitorLogs - turnOnLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-10T03:12:48.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-10 03:12:48 +[2024-11-10T06:34:07.660] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-11-10T06:34:07.675] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-11-10T06:34:07.680] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-11-10T07:23:14.149] [INFO] monitorLogs - turnOffLine (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-10T07:23:14.184] [INFO] monitorLogs - turnOffLine (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-10T07:23:14.219] [INFO] monitorLogs - turnOffLine (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-10T15:35:24.149] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2024-11-10T15:35:29.547] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 true turn off on startup +[2024-11-10T15:35:29.549] [INFO] monitorLogs - turnLine: off pin (relay) relay1_02 +[2024-11-10T15:35:29.562] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 true turn off on startup +[2024-11-10T15:35:29.563] [INFO] monitorLogs - turnLine: off pin (relay) relay1_03 +[2024-11-10T15:35:29.568] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 true turn off on startup +[2024-11-10T15:35:29.569] [INFO] monitorLogs - turnLine: off pin (relay) relay1_04 +[2024-11-10T15:35:29.676] [INFO] monitorLogs - MQTT client connected +[2024-11-10T15:35:34.580] [INFO] monitorLogs - buildTasks - params undefined +[2024-11-10T15:35:34.582] [INFO] monitorLogs - buildTasks: profile for line 1 +[2024-11-10T15:35:34.583] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2024-11-10T15:35:34.587] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-10T15:35:34.589] [INFO] monitorLogs - luxOff: turn off line: 1 2024-11-11T06:23:00.588Z +[2024-11-10T15:35:34.590] [INFO] monitorLogs - luxOn: turn on line: 1 2024-11-10T15:49:00.590Z +[2024-11-10T15:35:34.591] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:23', name: 'luxOff' }, + { value: 1, start_time: '16:49', name: 'luxOn' } +] +[2024-11-10T15:35:34.593] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2024-11-10T15:35:34.594] [INFO] monitorLogs - buildTasks: profile for line 2 +[2024-11-10T15:35:34.594] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2024-11-10T15:35:34.597] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-10T15:35:34.597] [INFO] monitorLogs - luxOff: turn off line: 2 2024-11-11T06:23:00.597Z +[2024-11-10T15:35:34.598] [INFO] monitorLogs - luxOn: turn on line: 2 2024-11-10T15:49:00.598Z +[2024-11-10T15:35:34.599] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:23', name: 'luxOff' }, + { value: 1, start_time: '16:49', name: 'luxOn' } +] +[2024-11-10T15:35:34.600] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2024-11-10T15:35:34.601] [INFO] monitorLogs - buildTasks: profile for line 3 +[2024-11-10T15:35:34.601] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2024-11-10T15:35:34.603] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-10T15:35:34.604] [INFO] monitorLogs - luxOff: turn off line: 3 2024-11-11T06:23:00.604Z +[2024-11-10T15:35:34.605] [INFO] monitorLogs - luxOn: turn on line: 3 2024-11-10T15:49:00.605Z +[2024-11-10T15:35:34.606] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:23', name: 'luxOff' }, + { value: 1, start_time: '16:49', name: 'luxOn' } +] +[2024-11-10T15:35:34.607] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2024-11-10T15:35:34.615] [INFO] monitorLogs - tasks created: 974 +[2024-11-10T15:35:34.618] [INFO] monitorLogs - -->FLOW bol spustený d5xjWYMwEJon6rLlK7yEaP7qgV4DaOeNB9ZX3Gzb 2024-11-04 +[2024-11-10T15:35:34.924] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-10T15:35:34.960] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-10T15:35:34.998] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-10T16:35:57.624] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-11-10T16:35:57.626] [INFO] monitorLogs - turnLine: on pin (relay) relay1_02 +[2024-11-10T16:35:57.665] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-11-10T16:35:57.665] [INFO] monitorLogs - turnLine: on pin (relay) relay1_03 +[2024-11-10T16:35:57.674] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-11-10T16:35:57.675] [INFO] monitorLogs - turnLine: on pin (relay) relay1_04 +[2024-11-10T16:49:01.467] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-10T16:49:01.512] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-10T16:49:01.549] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-11T03:35:31.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-11 03:35:31 +[2024-11-11T06:48:52.142] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-11-11T06:48:52.144] [INFO] monitorLogs - turnLine: off pin (relay) relay1_02 +[2024-11-11T06:48:52.183] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-11-11T06:48:52.184] [INFO] monitorLogs - turnLine: off pin (relay) relay1_03 +[2024-11-11T06:48:52.190] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-11-11T06:48:52.191] [INFO] monitorLogs - turnLine: off pin (relay) relay1_04 +[2024-11-11T07:23:00.781] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-11T07:23:00.817] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-11T07:23:00.852] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-11T16:20:48.824] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-11-11T16:20:48.825] [INFO] monitorLogs - turnLine: on pin (relay) relay1_02 +[2024-11-11T16:20:48.863] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-11-11T16:20:48.863] [INFO] monitorLogs - turnLine: on pin (relay) relay1_03 +[2024-11-11T16:20:48.870] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-11-11T16:20:48.870] [INFO] monitorLogs - turnLine: on pin (relay) relay1_04 +[2024-11-11T16:47:46.529] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-11T16:47:46.565] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-11T16:47:46.601] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-11T23:08:44.984] [INFO] monitorLogs - MQTT client connected +[2024-11-12T03:35:31.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-12 03:35:31 +[2024-11-12T06:51:15.154] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-11-12T06:51:15.155] [INFO] monitorLogs - turnLine: off pin (relay) relay1_02 +[2024-11-12T06:51:15.168] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-11-12T06:51:15.168] [INFO] monitorLogs - turnLine: off pin (relay) relay1_03 +[2024-11-12T06:51:15.175] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-11-12T06:51:15.176] [INFO] monitorLogs - turnLine: off pin (relay) relay1_04 +[2024-11-12T07:26:23.821] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-12T07:26:23.856] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-12T07:26:23.891] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-12T16:18:09.283] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-11-12T16:18:09.284] [INFO] monitorLogs - turnLine: on pin (relay) relay1_02 +[2024-11-12T16:18:09.312] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-11-12T16:18:09.312] [INFO] monitorLogs - turnLine: on pin (relay) relay1_03 +[2024-11-12T16:18:09.318] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-11-12T16:18:09.319] [INFO] monitorLogs - turnLine: on pin (relay) relay1_04 +[2024-11-12T16:46:28.176] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-12T16:46:28.211] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-12T16:46:28.246] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-13T03:35:32.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-13 03:35:32 +[2024-11-13T06:56:06.959] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-11-13T06:56:06.960] [INFO] monitorLogs - turnLine: off pin (relay) relay1_02 +[2024-11-13T06:56:06.971] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-11-13T06:56:06.972] [INFO] monitorLogs - turnLine: off pin (relay) relay1_03 +[2024-11-13T06:56:06.979] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-11-13T06:56:06.979] [INFO] monitorLogs - turnLine: off pin (relay) relay1_04 +[2024-11-13T07:27:58.262] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2024-11-13T07:27:58.299] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2024-11-13T07:27:58.333] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2024-11-13T10:20:57.479] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2024-11-13T10:21:02.803] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 true turn off on startup +[2024-11-13T10:21:02.817] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 true turn off on startup +[2024-11-13T10:21:02.823] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 true turn off on startup +[2024-11-13T10:21:02.903] [INFO] monitorLogs - MQTT client connected +[2024-11-13T10:21:07.835] [INFO] monitorLogs - buildTasks - params undefined +[2024-11-13T10:21:07.837] [INFO] monitorLogs - buildTasks: profile for line 1 +[2024-11-13T10:21:07.838] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2024-11-13T10:21:07.843] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-13T10:21:07.844] [INFO] monitorLogs - luxOff: turn off line: 1 2024-11-14T06:27:00.843Z +[2024-11-13T10:21:07.846] [INFO] monitorLogs - luxOn: turn on line: 1 2024-11-13T15:45:00.846Z +[2024-11-13T10:21:07.846] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:27', name: 'luxOff' }, + { value: 1, start_time: '16:45', name: 'luxOn' } +] +[2024-11-13T10:21:07.848] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2024-11-13T10:21:07.848] [INFO] monitorLogs - buildTasks: profile for line 2 +[2024-11-13T10:21:07.849] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2024-11-13T10:21:07.852] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-13T10:21:07.852] [INFO] monitorLogs - luxOff: turn off line: 2 2024-11-14T06:27:00.852Z +[2024-11-13T10:21:07.853] [INFO] monitorLogs - luxOn: turn on line: 2 2024-11-13T15:45:00.853Z +[2024-11-13T10:21:07.854] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:27', name: 'luxOff' }, + { value: 1, start_time: '16:45', name: 'luxOn' } +] +[2024-11-13T10:21:07.855] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2024-11-13T10:21:07.855] [INFO] monitorLogs - buildTasks: profile for line 3 +[2024-11-13T10:21:07.856] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2024-11-13T10:21:07.858] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-13T10:21:07.859] [INFO] monitorLogs - luxOff: turn off line: 3 2024-11-14T06:27:00.859Z +[2024-11-13T10:21:07.860] [INFO] monitorLogs - luxOn: turn on line: 3 2024-11-13T15:45:00.859Z +[2024-11-13T10:21:07.860] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:27', name: 'luxOff' }, + { value: 1, start_time: '16:45', name: 'luxOn' } +] +[2024-11-13T10:21:07.861] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2024-11-13T10:21:07.868] [INFO] monitorLogs - tasks created: 974 +[2024-11-13T10:21:07.871] [INFO] monitorLogs - -->FLOW bol spustený d5xjWYMwEJon6rLlK7yEaP7qgV4DaOeNB9ZX3Gzb 2024-11-04 +[2024-11-13T11:59:50.979] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2024-11-13T11:59:56.306] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 true turn off on startup +[2024-11-13T11:59:56.321] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 true turn off on startup +[2024-11-13T11:59:56.326] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 true turn off on startup +[2024-11-13T11:59:56.466] [INFO] monitorLogs - MQTT client connected +[2024-11-13T12:00:01.337] [INFO] monitorLogs - buildTasks - params undefined +[2024-11-13T12:00:01.339] [INFO] monitorLogs - buildTasks: profile for line 1 +[2024-11-13T12:00:01.340] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2024-11-13T12:00:01.344] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-13T12:00:01.346] [INFO] monitorLogs - luxOff: turn off line: 1 2024-11-14T06:27:00.345Z +[2024-11-13T12:00:01.347] [INFO] monitorLogs - luxOn: turn on line: 1 2024-11-13T15:45:00.347Z +[2024-11-13T12:00:01.348] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:27', name: 'luxOff' }, + { value: 1, start_time: '16:45', name: 'luxOn' } +] +[2024-11-13T12:00:01.349] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2024-11-13T12:00:01.350] [INFO] monitorLogs - buildTasks: profile for line 2 +[2024-11-13T12:00:01.351] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2024-11-13T12:00:01.353] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-13T12:00:01.354] [INFO] monitorLogs - luxOff: turn off line: 2 2024-11-14T06:27:00.354Z +[2024-11-13T12:00:01.355] [INFO] monitorLogs - luxOn: turn on line: 2 2024-11-13T15:45:00.355Z +[2024-11-13T12:00:01.355] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:27', name: 'luxOff' }, + { value: 1, start_time: '16:45', name: 'luxOn' } +] +[2024-11-13T12:00:01.356] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2024-11-13T12:00:01.357] [INFO] monitorLogs - buildTasks: profile for line 3 +[2024-11-13T12:00:01.358] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2024-11-13T12:00:01.360] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-13T12:00:01.360] [INFO] monitorLogs - luxOff: turn off line: 3 2024-11-14T06:27:00.360Z +[2024-11-13T12:00:01.361] [INFO] monitorLogs - luxOn: turn on line: 3 2024-11-13T15:45:00.361Z +[2024-11-13T12:00:01.362] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:27', name: 'luxOff' }, + { value: 1, start_time: '16:45', name: 'luxOn' } +] +[2024-11-13T12:00:01.363] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2024-11-13T12:00:01.373] [INFO] monitorLogs - tasks created: 974 +[2024-11-13T12:00:01.376] [INFO] monitorLogs - -->FLOW bol spustený d5xjWYMwEJon6rLlK7yEaP7qgV4DaOeNB9ZX3Gzb 2024-11-04 +[2024-11-13T16:16:04.741] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-11-13T16:16:04.780] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-11-13T16:16:04.787] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-11-14T03:59:58.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-14 03:59:58 +[2024-11-14T06:54:03.929] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-11-14T06:54:03.940] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-11-14T06:54:03.947] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-11-14T16:23:28.741] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-11-14T16:23:28.771] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-11-14T16:23:28.778] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-11-15T03:59:58.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-15 03:59:58 +[2024-11-15T06:43:53.356] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-11-15T06:43:53.388] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-11-15T06:43:53.397] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-11-15T16:23:20.202] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-11-15T16:23:20.239] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-11-15T16:23:20.245] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-11-16T03:59:59.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-16 03:59:59 +[2024-11-16T06:36:13.001] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-11-16T06:36:13.031] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-11-16T06:36:13.038] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-11-16T16:30:42.867] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-11-16T16:30:42.914] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-11-16T16:30:42.925] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-11-16T16:54:56.337] [INFO] monitorLogs - MQTT client connected +[2024-11-17T04:00:00.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-17 04:00:00 +[2024-11-17T06:48:36.537] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-11-17T06:48:36.616] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-11-17T06:48:36.624] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-11-17T16:25:32.932] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-11-17T16:25:32.972] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-11-17T16:25:32.978] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-11-18T04:00:01.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-18 04:00:01 +[2024-11-18T06:45:58.578] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-11-18T06:45:58.589] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-11-18T06:45:58.595] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-11-18T16:15:24.804] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-11-18T16:15:24.839] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-11-18T16:15:24.848] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-11-19T03:00:07.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-19 03:00:07 +[2024-11-19T06:55:53.931] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-11-19T06:55:53.985] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-11-19T06:55:53.992] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-11-19T16:17:47.369] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-11-19T16:17:47.403] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-11-19T16:17:47.409] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-11-20T03:00:02.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-20 03:00:02 +[2024-11-20T07:08:17.387] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-11-20T07:08:17.428] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-11-20T07:08:17.436] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-11-20T16:25:10.232] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-11-20T16:25:10.266] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-11-20T16:25:10.273] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-11-21T03:00:04.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-21 03:00:04 +[2024-11-21T06:55:37.889] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-11-21T06:55:37.905] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-11-21T06:55:37.913] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-11-21T12:23:31.237] [INFO] monitorLogs - MQTT client connected +[2024-11-21T13:34:43.811] [INFO] monitorLogs - MQTT client connected +[2024-11-21T13:37:24.606] [INFO] monitorLogs - MQTT client connected +[2024-11-21T16:20:01.995] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-11-21T16:20:02.030] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-11-21T16:20:02.036] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-11-22T03:00:03.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-22 03:00:03 +[2024-11-22T06:46:35.115] [INFO] monitorLogs - MQTT client connected +[2024-11-22T07:20:53.250] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-11-22T07:20:53.262] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-11-22T07:20:53.270] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-11-22T10:07:47.061] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2024-11-22T10:07:52.455] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 true turn off on startup +[2024-11-22T10:07:52.470] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 true turn off on startup +[2024-11-22T10:07:52.475] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 true turn off on startup +[2024-11-22T10:07:52.577] [INFO] monitorLogs - MQTT client connected +[2024-11-22T10:07:57.487] [INFO] monitorLogs - buildTasks - params undefined +[2024-11-22T10:07:57.489] [INFO] monitorLogs - buildTasks: profile for line 1 +[2024-11-22T10:07:57.489] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2024-11-22T10:07:57.494] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-22T10:07:57.495] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2024-11-23T06:41:00.494Z +[2024-11-22T10:07:57.497] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2024-11-22T15:35:00.496Z +[2024-11-22T10:07:57.497] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:41', name: 'luxOff' }, + { value: 1, start_time: '16:35', name: 'luxOn' } +] +[2024-11-22T10:07:57.499] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2024-11-22T10:07:57.500] [INFO] monitorLogs - buildTasks: profile for line 2 +[2024-11-22T10:07:57.501] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2024-11-22T10:07:57.503] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-22T10:07:57.504] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2024-11-23T06:41:00.503Z +[2024-11-22T10:07:57.504] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2024-11-22T15:35:00.504Z +[2024-11-22T10:07:57.505] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:41', name: 'luxOff' }, + { value: 1, start_time: '16:35', name: 'luxOn' } +] +[2024-11-22T10:07:57.506] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2024-11-22T10:07:57.507] [INFO] monitorLogs - buildTasks: profile for line 3 +[2024-11-22T10:07:57.507] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2024-11-22T10:07:57.509] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-22T10:07:57.510] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2024-11-23T06:41:00.510Z +[2024-11-22T10:07:57.511] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2024-11-22T15:35:00.511Z +[2024-11-22T10:07:57.511] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:41', name: 'luxOff' }, + { value: 1, start_time: '16:35', name: 'luxOn' } +] +[2024-11-22T10:07:57.512] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2024-11-22T10:07:57.519] [INFO] monitorLogs - tasks created: 974 +[2024-11-22T10:07:57.522] [INFO] monitorLogs - -->FLOW bol spustený d5xjWYMwEJon6rLlK7yEaP7qgV4DaOeNB9ZX3Gzb 2024-11-04 +[2024-11-22T10:28:32.021] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false command received from platform +[2024-11-22T10:28:44.514] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false command received from platform +[2024-11-22T10:29:03.880] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false command received from platform +[2024-11-22T11:23:34.822] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false command received from platform +[2024-11-22T11:23:44.173] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false command received from platform +[2024-11-22T11:24:13.283] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false command received from platform +[2024-11-22T16:21:54.856] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-11-22T16:21:54.889] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-11-22T16:21:54.896] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-11-23T03:07:54.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-23 03:07:54 +[2024-11-23T06:57:23.486] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-11-23T06:57:23.497] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-11-23T06:57:23.504] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-11-23T16:21:47.865] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-11-23T16:21:47.901] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-11-23T16:21:47.907] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-11-23T21:10:28.704] [INFO] monitorLogs - MQTT client error Error: Connection refused: Server unavailable + at MqttClient._handleConnack (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:1388:17) + at MqttClient._handlePacket (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:549:12) + at work (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:438:12) + at Writable.writable._write (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:452:5) + at doWrite (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:409:139) + at writeOrBuffer (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:398:5) + at Writable.write (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:307:11) + at Socket.ondata (internal/streams/readable.js:731:22) + at Socket.emit (events.js:400:28) + at addChunk (internal/streams/readable.js:293:12) { + code: 3 +} +[2024-11-23T21:10:40.968] [INFO] monitorLogs - MQTT client connected +[2024-11-23T21:13:55.682] [INFO] monitorLogs - MQTT client error Error: Connection refused: Server unavailable + at MqttClient._handleConnack (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:1388:17) + at MqttClient._handlePacket (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:549:12) + at work (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:438:12) + at Writable.writable._write (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:452:5) + at doWrite (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:409:139) + at writeOrBuffer (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:398:5) + at Writable.write (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:307:11) + at Socket.ondata (internal/streams/readable.js:731:22) + at Socket.emit (events.js:400:28) + at addChunk (internal/streams/readable.js:293:12) { + code: 3 +} +[2024-11-23T21:13:58.563] [INFO] monitorLogs - MQTT client connected +[2024-11-23T21:14:44.323] [INFO] monitorLogs - MQTT client connected +[2024-11-23T21:16:01.586] [INFO] monitorLogs - MQTT client connected +[2024-11-23T21:16:58.797] [INFO] monitorLogs - MQTT client error Error: Connection refused: Server unavailable + at MqttClient._handleConnack (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:1388:17) + at MqttClient._handlePacket (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:549:12) + at work (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:438:12) + at Writable.writable._write (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:452:5) + at doWrite (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:409:139) + at writeOrBuffer (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:398:5) + at Writable.write (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:307:11) + at Socket.ondata (internal/streams/readable.js:731:22) + at Socket.emit (events.js:400:28) + at addChunk (internal/streams/readable.js:293:12) { + code: 3 +} +[2024-11-23T21:17:08.077] [INFO] monitorLogs - MQTT client connected +[2024-11-23T21:21:38.155] [INFO] monitorLogs - MQTT client error Error: Connection refused: Server unavailable + at MqttClient._handleConnack (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:1388:17) + at MqttClient._handlePacket (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:549:12) + at work (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:438:12) + at Writable.writable._write (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:452:5) + at doWrite (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:409:139) + at writeOrBuffer (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:398:5) + at Writable.write (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:307:11) + at Socket.ondata (internal/streams/readable.js:731:22) + at Socket.emit (events.js:400:28) + at addChunk (internal/streams/readable.js:293:12) { + code: 3 +} +[2024-11-23T21:21:39.435] [INFO] monitorLogs - MQTT client connected +[2024-11-23T21:23:48.394] [INFO] monitorLogs - MQTT client connected +[2024-11-24T03:07:55.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-24 03:07:55 +[2024-11-24T07:02:16.393] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-11-24T07:02:16.404] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-11-24T07:02:16.410] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-11-24T16:14:07.513] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-11-24T16:14:07.608] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-11-24T16:14:07.614] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-11-25T03:07:56.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-25 03:07:56 +[2024-11-25T06:52:05.370] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-11-25T06:52:05.413] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-11-25T06:52:05.420] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-11-25T07:10:03.993] [INFO] monitorLogs - MQTT client error Error: Connection refused: Server unavailable + at MqttClient._handleConnack (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:1388:17) + at MqttClient._handlePacket (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:549:12) + at work (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:438:12) + at Writable.writable._write (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:452:5) + at doWrite (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:409:139) + at writeOrBuffer (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:398:5) + at Writable.write (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:307:11) + at Socket.ondata (internal/streams/readable.js:731:22) + at Socket.emit (events.js:400:28) + at addChunk (internal/streams/readable.js:293:12) { + code: 3 +} +[2024-11-25T07:10:06.324] [INFO] monitorLogs - MQTT client connected +[2024-11-25T07:12:32.235] [INFO] monitorLogs - MQTT client error Error: Connection refused: Server unavailable + at MqttClient._handleConnack (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:1388:17) + at MqttClient._handlePacket (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:549:12) + at work (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:438:12) + at Writable.writable._write (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:452:5) + at doWrite (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:409:139) + at writeOrBuffer (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:398:5) + at Writable.write (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:307:11) + at Socket.ondata (internal/streams/readable.js:731:22) + at Socket.emit (events.js:400:28) + at addChunk (internal/streams/readable.js:293:12) { + code: 3 +} +[2024-11-25T07:12:33.514] [INFO] monitorLogs - MQTT client connected +[2024-11-25T07:13:33.993] [INFO] monitorLogs - MQTT client error Error: Connection refused: Server unavailable + at MqttClient._handleConnack (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:1388:17) + at MqttClient._handlePacket (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:549:12) + at work (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:438:12) + at Writable.writable._write (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:452:5) + at doWrite (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:409:139) + at writeOrBuffer (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:398:5) + at Writable.write (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:307:11) + at Socket.ondata (internal/streams/readable.js:731:22) + at Socket.emit (events.js:400:28) + at addChunk (internal/streams/readable.js:293:12) { + code: 3 +} +[2024-11-25T07:13:35.797] [INFO] monitorLogs - MQTT client connected +[2024-11-25T08:06:51.322] [INFO] monitorLogs - MQTT client connected +[2024-11-25T08:08:52.581] [INFO] monitorLogs - MQTT client connected +[2024-11-25T14:00:22.446] [INFO] monitorLogs - MQTT client error Error: Connection refused: Server unavailable + at MqttClient._handleConnack (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:1388:17) + at MqttClient._handlePacket (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:549:12) + at work (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:438:12) + at Writable.writable._write (/home/unipi/flowserver/node_modules/mqtt/lib/client.js:452:5) + at doWrite (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:409:139) + at writeOrBuffer (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:398:5) + at Writable.write (/home/unipi/flowserver/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:307:11) + at Socket.ondata (internal/streams/readable.js:731:22) + at Socket.emit (events.js:400:28) + at addChunk (internal/streams/readable.js:293:12) { + code: 3 +} +[2024-11-25T14:00:23.727] [INFO] monitorLogs - MQTT client connected +[2024-11-25T16:18:59.525] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-11-25T16:18:59.629] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-11-25T16:18:59.636] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-11-26T03:07:57.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-26 03:07:57 +[2024-11-26T07:01:58.223] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-11-26T07:01:58.258] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-11-26T07:01:58.265] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-11-26T16:16:20.121] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-11-26T16:16:20.160] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-11-26T16:16:20.166] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-11-27T03:07:57.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-27 03:07:57 +[2024-11-27T07:01:48.522] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-11-27T07:01:48.558] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-11-27T07:01:48.566] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-11-27T16:18:40.777] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-11-27T16:18:40.827] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-11-27T16:18:40.833] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-11-28T03:07:58.015] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-28 03:07:58 +[2024-11-28T07:16:42.498] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-11-28T07:16:42.551] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-11-28T07:16:42.557] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-11-28T16:18:31.678] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-11-28T16:18:31.757] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-11-28T16:18:31.763] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-11-29T03:07:59.014] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-29 03:07:59 +[2024-11-29T07:11:32.437] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-11-29T07:11:32.448] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-11-29T07:11:32.455] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-11-29T16:08:21.172] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-11-29T16:08:21.237] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-11-29T16:08:21.243] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-11-30T03:08:00.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-11-30 03:08:00 +[2024-11-30T06:56:25.596] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-11-30T06:56:25.661] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-11-30T06:56:25.667] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-11-30T15:34:04.200] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2024-11-30T15:34:09.522] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 true turn off on startup +[2024-11-30T15:34:09.535] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 true turn off on startup +[2024-11-30T15:34:09.541] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 true turn off on startup +[2024-11-30T15:34:09.629] [INFO] monitorLogs - MQTT client connected +[2024-11-30T15:34:14.552] [INFO] monitorLogs - buildTasks - params undefined +[2024-11-30T15:34:14.554] [INFO] monitorLogs - buildTasks: profile for line 1 +[2024-11-30T15:34:14.555] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2024-11-30T15:34:14.560] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-30T15:34:14.561] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2024-12-01T06:52:00.560Z +[2024-11-30T15:34:14.563] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2024-11-30T15:29:00.562Z +[2024-11-30T15:34:14.563] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:52', name: 'luxOff' }, + { value: 1, start_time: '16:29', name: 'luxOn' } +] +[2024-11-30T15:34:14.564] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2024-11-30T15:34:14.565] [INFO] monitorLogs - buildTasks: profile for line 2 +[2024-11-30T15:34:14.566] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2024-11-30T15:34:14.568] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-30T15:34:14.569] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2024-12-01T06:52:00.569Z +[2024-11-30T15:34:14.570] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2024-11-30T15:29:00.569Z +[2024-11-30T15:34:14.570] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:52', name: 'luxOff' }, + { value: 1, start_time: '16:29', name: 'luxOn' } +] +[2024-11-30T15:34:14.571] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2024-11-30T15:34:14.572] [INFO] monitorLogs - buildTasks: profile for line 3 +[2024-11-30T15:34:14.573] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2024-11-30T15:34:14.575] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-11-30T15:34:14.575] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2024-12-01T06:52:00.575Z +[2024-11-30T15:34:14.576] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2024-11-30T15:29:00.576Z +[2024-11-30T15:34:14.577] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:52', name: 'luxOff' }, + { value: 1, start_time: '16:29', name: 'luxOn' } +] +[2024-11-30T15:34:14.578] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2024-11-30T15:34:14.584] [INFO] monitorLogs - tasks created: 974 +[2024-11-30T15:34:14.587] [INFO] monitorLogs - -->FLOW bol spustený d5xjWYMwEJon6rLlK7yEaP7qgV4DaOeNB9ZX3Gzb 2024-11-04 +[2024-11-30T16:19:34.487] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-11-30T16:19:34.525] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-11-30T16:19:34.532] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-12-01T03:34:10.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-01 03:34:10 +[2024-12-01T06:55:02.453] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-12-01T06:55:02.464] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-12-01T06:55:02.470] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-12-01T16:19:26.779] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-12-01T16:19:26.817] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-12-01T16:19:26.824] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-12-02T03:34:11.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-02 03:34:11 +[2024-12-02T06:57:25.243] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-12-02T06:57:25.280] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-12-02T06:57:25.286] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-12-02T16:19:18.345] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-12-02T16:19:18.376] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-12-02T16:19:18.382] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-12-03T03:34:12.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-03 03:34:12 +[2024-12-03T06:59:46.408] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-12-03T06:59:46.462] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-12-03T06:59:46.469] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-12-03T16:11:37.550] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-12-03T16:11:37.583] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-12-03T16:11:37.589] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-12-04T00:19:06.266] [INFO] monitorLogs - MQTT client connected +[2024-12-04T03:34:13.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-04 03:34:13 +[2024-12-04T07:17:11.580] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-12-04T07:17:11.631] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-12-04T07:17:11.639] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-12-04T16:08:58.730] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-12-04T16:08:58.761] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-12-04T16:08:58.767] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-12-05T03:34:13.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-05 03:34:13 +[2024-12-05T07:01:59.016] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-12-05T07:01:59.027] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-12-05T07:01:59.034] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-12-05T15:08:20.442] [INFO] monitorLogs - MQTT client connected +[2024-12-05T16:18:51.478] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-12-05T16:18:51.512] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-12-05T16:18:51.518] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-12-06T03:34:14.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-06 03:34:14 +[2024-12-06T07:21:56.192] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-12-06T07:21:56.225] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-12-06T07:21:56.234] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-12-06T15:56:10.019] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-12-06T15:56:10.055] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-12-06T15:56:10.062] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-12-07T03:34:15.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-07 03:34:15 +[2024-12-07T07:16:46.338] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-12-07T07:16:46.385] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-12-07T07:16:46.392] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-12-07T16:08:33.642] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-12-07T16:08:33.679] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-12-07T16:08:33.686] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-12-08T03:34:15.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-08 03:34:15 +[2024-12-08T07:19:08.449] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-12-08T07:19:08.488] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-12-08T07:19:08.496] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-12-08T16:18:27.480] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-12-08T16:18:27.516] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-12-08T16:18:27.522] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-12-09T03:34:16.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-09 03:34:16 +[2024-12-09T07:21:47.075] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-12-09T07:21:47.088] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-12-09T07:21:47.094] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-12-09T09:15:22.840] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-09T09:15:23.892] [INFO] monitorLogs - websocket error, reconnect +[2024-12-09T09:15:23.894] [INFO] monitorLogs - websocket onclose, reconnect +[2024-12-09T09:29:06.095] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2024-12-09T09:29:11.438] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 true turn off on startup +[2024-12-09T09:29:11.452] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 true turn off on startup +[2024-12-09T09:29:11.458] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 true turn off on startup +[2024-12-09T09:29:11.624] [INFO] monitorLogs - MQTT client connected +[2024-12-09T09:29:16.469] [INFO] monitorLogs - buildTasks - params undefined +[2024-12-09T09:29:16.470] [INFO] monitorLogs - buildTasks: profile for line 1 +[2024-12-09T09:29:16.471] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2024-12-09T09:29:16.476] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-12-09T09:29:16.478] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2024-12-10T07:03:00.477Z +[2024-12-09T09:29:16.479] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2024-12-09T15:26:00.479Z +[2024-12-09T09:29:16.480] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '8:3', name: 'luxOff' }, + { value: 1, start_time: '16:26', name: 'luxOn' } +] +[2024-12-09T09:29:16.481] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2024-12-09T09:29:16.482] [INFO] monitorLogs - buildTasks: profile for line 2 +[2024-12-09T09:29:16.482] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2024-12-09T09:29:16.485] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-12-09T09:29:16.485] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2024-12-10T07:03:00.485Z +[2024-12-09T09:29:16.486] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2024-12-09T15:26:00.486Z +[2024-12-09T09:29:16.487] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '8:3', name: 'luxOff' }, + { value: 1, start_time: '16:26', name: 'luxOn' } +] +[2024-12-09T09:29:16.488] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2024-12-09T09:29:16.489] [INFO] monitorLogs - buildTasks: profile for line 3 +[2024-12-09T09:29:16.489] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2024-12-09T09:29:16.491] [INFO] monitorLogs - -->comming events turn on/off lines: +[2024-12-09T09:29:16.492] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2024-12-10T07:03:00.492Z +[2024-12-09T09:29:16.493] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2024-12-09T15:26:00.493Z +[2024-12-09T09:29:16.493] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '8:3', name: 'luxOff' }, + { value: 1, start_time: '16:26', name: 'luxOn' } +] +[2024-12-09T09:29:16.494] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2024-12-09T09:29:16.501] [INFO] monitorLogs - tasks created: 974 +[2024-12-09T09:29:16.504] [INFO] monitorLogs - -->FLOW bol spustený d5xjWYMwEJon6rLlK7yEaP7qgV4DaOeNB9ZX3Gzb 2024-11-04 +[2024-12-09T16:15:50.700] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-12-09T16:15:50.740] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-12-09T16:15:50.747] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-12-10T03:29:13.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-10 03:29:13 +[2024-12-10T06:40:56.111] [INFO] monitorLogs - MQTT client connected +[2024-12-10T07:18:54.230] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-12-10T07:18:54.243] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-12-10T07:18:54.251] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-12-10T16:13:12.406] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-12-10T16:13:12.443] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-12-10T16:13:12.449] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-12-11T03:29:14.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-11 03:29:14 +[2024-12-11T07:21:16.862] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-12-11T07:21:16.882] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-12-11T07:21:16.889] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-12-11T16:08:03.035] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-12-11T16:08:03.104] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-12-11T16:08:03.110] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-12-12T03:29:14.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-12 03:29:14 +[2024-12-12T07:11:05.839] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-12-12T07:11:05.896] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-12-12T07:11:05.902] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-12-12T16:10:24.471] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-12-12T16:10:24.527] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-12-12T16:10:24.535] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-12-13T03:29:15.013] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-13 03:29:15 +[2024-12-13T07:08:51.044] [INFO] monitorLogs - MQTT client connected +[2024-12-13T07:18:28.546] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-12-13T07:18:28.558] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-12-13T07:18:28.564] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-12-13T16:12:46.480] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-12-13T16:12:46.517] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-12-13T16:12:46.524] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-12-14T03:29:16.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-14 03:29:16 +[2024-12-14T07:30:52.935] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-12-14T07:30:52.972] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-12-14T07:30:52.981] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-12-14T16:10:08.397] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-12-14T16:10:08.434] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-12-14T16:10:08.440] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-12-15T03:29:17.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-15 03:29:17 +[2024-12-15T07:28:14.547] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-12-15T07:28:14.602] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-12-15T07:28:14.609] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-12-15T16:12:30.453] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-12-15T16:12:30.495] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-12-15T16:12:30.501] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-12-16T03:29:17.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-16 03:29:17 +[2024-12-16T07:30:36.053] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-12-16T07:30:36.103] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-12-16T07:30:36.110] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-12-16T09:45:43.117] [INFO] monitorLogs - MQTT client connected +[2024-12-16T16:10:18.262] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-12-16T16:10:18.339] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-12-16T16:10:18.345] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-12-17T03:29:18.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-17 03:29:18 +[2024-12-17T07:23:23.075] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-12-17T07:23:23.086] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-12-17T07:23:23.092] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-12-17T16:10:09.122] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-12-17T16:10:09.188] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-12-17T16:10:09.194] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-12-18T03:29:19.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-18 03:29:19 +[2024-12-18T07:15:43.668] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-12-18T07:15:43.733] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-12-18T07:15:43.739] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-12-18T16:17:32.969] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-12-18T16:17:33.025] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-12-18T16:17:33.031] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-12-19T03:29:20.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-19 03:29:20 +[2024-12-19T07:13:04.974] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-12-19T07:13:04.986] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-12-19T07:13:04.995] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-12-19T16:12:24.449] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-12-19T16:12:24.508] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-12-19T16:12:24.514] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-12-20T03:29:20.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-20 03:29:20 +[2024-12-20T07:25:28.673] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-12-20T07:25:28.727] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-12-20T07:25:28.734] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-12-20T16:14:45.443] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-12-20T16:14:45.491] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-12-20T16:14:45.498] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-12-21T03:29:22.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-21 03:29:22 +[2024-12-21T07:22:49.384] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-12-21T07:22:49.424] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-12-21T07:22:49.431] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-12-21T16:22:08.823] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-12-21T16:22:08.859] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-12-21T16:22:08.865] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-12-22T03:29:22.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-22 03:29:22 +[2024-12-22T07:27:42.067] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-12-22T07:27:42.080] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-12-22T07:27:42.087] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-12-22T15:59:25.467] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-12-22T15:59:25.531] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-12-22T15:59:25.538] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-12-23T03:29:22.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-23 03:29:22 +[2024-12-23T07:30:04.207] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-12-23T07:30:04.220] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-12-23T07:30:04.226] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-12-23T16:16:50.444] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-12-23T16:16:50.480] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-12-23T16:16:50.486] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-12-24T03:29:23.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-24 03:29:23 +[2024-12-24T07:29:55.859] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-12-24T07:29:55.892] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-12-24T07:29:55.898] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-12-24T16:11:42.022] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-12-24T16:11:42.055] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-12-24T16:11:42.061] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-12-25T03:29:24.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-25 03:29:24 +[2024-12-25T07:14:45.045] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-12-25T07:14:45.096] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-12-25T07:14:45.103] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-12-25T16:24:06.599] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-12-25T16:24:06.636] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-12-25T16:24:06.642] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-12-26T03:29:25.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-26 03:29:25 +[2024-12-26T07:19:38.086] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-12-26T07:19:38.156] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-12-26T07:19:38.162] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-12-26T16:26:28.730] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-12-26T16:26:28.777] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-12-26T16:26:28.784] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-12-27T03:29:25.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-27 03:29:25 +[2024-12-27T07:19:29.518] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-12-27T07:19:29.543] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-12-27T07:19:29.550] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-12-27T16:26:19.691] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-12-27T16:26:19.778] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-12-27T16:26:19.785] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-12-28T03:29:26.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-28 03:29:26 +[2024-12-28T07:16:50.784] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-12-28T07:16:50.827] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-12-28T07:16:50.835] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-12-28T16:26:11.697] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-12-28T16:26:11.759] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-12-28T16:26:11.765] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-12-29T03:29:27.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-29 03:29:27 +[2024-12-29T07:16:41.880] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-12-29T07:16:41.912] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-12-29T07:16:41.919] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-12-29T16:28:34.803] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-12-29T16:28:34.839] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-12-29T16:28:34.845] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-12-30T03:29:28.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-30 03:29:28 +[2024-12-30T07:16:35.055] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-12-30T07:16:35.105] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-12-30T07:16:35.112] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-12-30T16:28:26.377] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-12-30T16:28:26.478] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-12-30T16:28:26.484] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2024-12-31T03:29:28.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2024-12-31 03:29:28 +[2024-12-31T07:26:27.097] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2024-12-31T07:26:27.123] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2024-12-31T07:26:27.128] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2024-12-31T16:20:45.122] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2024-12-31T16:20:45.198] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2024-12-31T16:20:45.204] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-01-01T03:29:29.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-01 03:29:29 +[2025-01-01T07:28:49.045] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-01-01T07:28:49.100] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-01-01T07:28:49.106] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-01-01T16:28:08.786] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-01-01T16:28:08.820] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-01-01T16:28:08.826] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-01-02T03:29:30.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-02 03:29:30 +[2025-01-02T07:23:40.356] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-01-02T07:23:40.367] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-01-02T07:23:40.374] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-01-02T08:47:39.243] [INFO] monitorLogs - MQTT client error Error: connect ECONNREFUSED 192.168.252.1:1883 + at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1159:16) { + errno: -111, + code: 'ECONNREFUSED', + syscall: 'connect', + address: '192.168.252.1', + port: 1883 +} +[2025-01-02T11:44:30.588] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-01-02T11:44:36.007] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 true turn off on startup +[2025-01-02T11:44:36.022] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 true turn off on startup +[2025-01-02T11:44:36.030] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 true turn off on startup +[2025-01-02T11:44:36.071] [INFO] monitorLogs - MQTT client error Error: connect ECONNREFUSED 192.168.252.1:1883 + at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1159:16) { + errno: -111, + code: 'ECONNREFUSED', + syscall: 'connect', + address: '192.168.252.1', + port: 1883 +} +[2025-01-02T11:44:41.042] [INFO] monitorLogs - buildTasks - params undefined +[2025-01-02T11:44:41.043] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-01-02T11:44:41.044] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-01-02T11:44:41.048] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-02T11:44:41.050] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-01-03T07:14:00.049Z +[2025-01-02T11:44:41.051] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-01-02T15:37:00.051Z +[2025-01-02T11:44:41.052] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '8:14', name: 'luxOff' }, + { value: 1, start_time: '16:37', name: 'luxOn' } +] +[2025-01-02T11:44:41.053] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-01-02T11:44:41.054] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-01-02T11:44:41.054] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-01-02T11:44:41.057] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-02T11:44:41.057] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-01-03T07:14:00.057Z +[2025-01-02T11:44:41.058] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-01-02T15:37:00.058Z +[2025-01-02T11:44:41.059] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '8:14', name: 'luxOff' }, + { value: 1, start_time: '16:37', name: 'luxOn' } +] +[2025-01-02T11:44:41.060] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-01-02T11:44:41.061] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-01-02T11:44:41.061] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-01-02T11:44:41.063] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-02T11:44:41.064] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-01-03T07:14:00.064Z +[2025-01-02T11:44:41.065] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-01-02T15:37:00.064Z +[2025-01-02T11:44:41.065] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '8:14', name: 'luxOff' }, + { value: 1, start_time: '16:37', name: 'luxOn' } +] +[2025-01-02T11:44:41.066] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-01-02T11:44:41.073] [INFO] monitorLogs - tasks created: 974 +[2025-01-02T11:44:41.075] [INFO] monitorLogs - -->FLOW bol spustený d5xjWYMwEJon6rLlK7yEaP7qgV4DaOeNB9ZX3Gzb 2025-01-02 +[2025-01-02T16:18:18.934] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-01-02T16:18:18.990] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-01-02T16:18:18.997] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-01-03T03:44:37.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-03 03:44:37 +[2025-01-03T07:24:00.007] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-01-03T07:24:00.019] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-01-03T07:24:00.026] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-01-03T10:06:55.548] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-01-03T10:07:00.891] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 true turn off on startup +[2025-01-03T10:07:00.906] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 true turn off on startup +[2025-01-03T10:07:00.912] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 true turn off on startup +[2025-01-03T10:07:00.927] [INFO] monitorLogs - MQTT client error Error: connect ECONNREFUSED 192.168.252.1:1883 + at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1159:16) { + errno: -111, + code: 'ECONNREFUSED', + syscall: 'connect', + address: '192.168.252.1', + port: 1883 +} +[2025-01-03T10:07:05.925] [INFO] monitorLogs - buildTasks - params undefined +[2025-01-03T10:07:05.927] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-01-03T10:07:05.927] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-01-03T10:07:05.932] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-03T10:07:05.933] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-01-04T07:14:00.932Z +[2025-01-03T10:07:05.934] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-01-03T15:38:00.934Z +[2025-01-03T10:07:05.935] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '8:14', name: 'luxOff' }, + { value: 1, start_time: '16:38', name: 'luxOn' } +] +[2025-01-03T10:07:05.936] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-01-03T10:07:05.937] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-01-03T10:07:05.938] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-01-03T10:07:05.940] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-03T10:07:05.940] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-01-04T07:14:00.940Z +[2025-01-03T10:07:05.941] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-01-03T15:38:00.941Z +[2025-01-03T10:07:05.942] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '8:14', name: 'luxOff' }, + { value: 1, start_time: '16:38', name: 'luxOn' } +] +[2025-01-03T10:07:05.942] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-01-03T10:07:05.943] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-01-03T10:07:05.943] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-01-03T10:07:05.946] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-03T10:07:05.946] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-01-04T07:14:00.946Z +[2025-01-03T10:07:05.947] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-01-03T15:38:00.947Z +[2025-01-03T10:07:05.947] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '8:14', name: 'luxOff' }, + { value: 1, start_time: '16:38', name: 'luxOn' } +] +[2025-01-03T10:07:05.948] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-01-03T10:07:05.954] [INFO] monitorLogs - tasks created: 974 +[2025-01-03T10:07:05.957] [INFO] monitorLogs - -->FLOW bol spustený d5xjWYMwEJon6rLlK7yEaP7qgV4DaOeNB9ZX3Gzb 2025-01-02 +[2025-01-03T10:08:29.722] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-01-03T10:08:35.091] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 true turn off on startup +[2025-01-03T10:08:35.106] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 true turn off on startup +[2025-01-03T10:08:35.113] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 true turn off on startup +[2025-01-03T10:08:35.127] [INFO] monitorLogs - MQTT client error Error: connect ECONNREFUSED 192.168.252.1:1883 + at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1159:16) { + errno: -111, + code: 'ECONNREFUSED', + syscall: 'connect', + address: '192.168.252.1', + port: 1883 +} +[2025-01-03T10:08:40.125] [INFO] monitorLogs - buildTasks - params undefined +[2025-01-03T10:08:40.126] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-01-03T10:08:40.127] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-01-03T10:08:40.131] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-03T10:08:40.133] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-01-04T07:14:00.132Z +[2025-01-03T10:08:40.134] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-01-03T15:38:00.133Z +[2025-01-03T10:08:40.134] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '8:14', name: 'luxOff' }, + { value: 1, start_time: '16:38', name: 'luxOn' } +] +[2025-01-03T10:08:40.136] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-01-03T10:08:40.136] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-01-03T10:08:40.137] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-01-03T10:08:40.140] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-03T10:08:40.141] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-01-04T07:14:00.141Z +[2025-01-03T10:08:40.142] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-01-03T15:38:00.142Z +[2025-01-03T10:08:40.143] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '8:14', name: 'luxOff' }, + { value: 1, start_time: '16:38', name: 'luxOn' } +] +[2025-01-03T10:08:40.145] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-01-03T10:08:40.146] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-01-03T10:08:40.146] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-01-03T10:08:40.148] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-03T10:08:40.149] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-01-04T07:14:00.149Z +[2025-01-03T10:08:40.150] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-01-03T15:38:00.150Z +[2025-01-03T10:08:40.150] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '8:14', name: 'luxOff' }, + { value: 1, start_time: '16:38', name: 'luxOn' } +] +[2025-01-03T10:08:40.151] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-01-03T10:08:40.158] [INFO] monitorLogs - tasks created: 974 +[2025-01-03T10:08:40.161] [INFO] monitorLogs - -->FLOW bol spustený d5xjWYMwEJon6rLlK7yEaP7qgV4DaOeNB9ZX3Gzb 2025-01-02 +[2025-01-03T16:32:39.141] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-01-03T16:32:39.180] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-01-03T16:32:39.190] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-01-04T03:08:36.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-04 03:08:36 +[2025-01-04T07:18:08.785] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-01-04T07:18:08.799] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-01-04T07:18:08.807] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-01-04T16:27:29.934] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-01-04T16:27:30.000] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-01-04T16:27:30.014] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-01-05T03:08:37.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-05 03:08:37 +[2025-01-05T07:30:34.910] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-01-05T07:30:34.941] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-01-05T07:30:34.948] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-01-05T16:19:52.054] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-01-05T16:19:52.111] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-01-05T16:19:52.119] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-01-06T03:08:38.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-06 03:08:38 +[2025-01-06T07:30:26.275] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-01-06T07:30:26.287] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-01-06T07:30:26.293] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-01-06T16:32:15.755] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-01-06T16:32:15.794] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-01-06T16:32:15.801] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-01-07T03:08:38.014] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-07 03:08:38 +[2025-01-07T07:30:16.507] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-01-07T07:30:16.538] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-01-07T07:30:16.546] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-01-07T16:24:34.051] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-01-07T16:24:34.088] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-01-07T16:24:34.095] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-01-08T03:08:39.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-08 03:08:39 +[2025-01-08T07:22:35.888] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-01-08T07:22:35.931] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-01-08T07:22:35.938] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-01-08T16:31:57.755] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-01-08T16:31:57.809] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-01-08T16:31:57.817] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-01-09T03:08:40.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-09 03:08:40 +[2025-01-09T07:27:28.731] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-01-09T07:27:28.743] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-01-09T07:27:28.750] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-01-09T15:18:47.031] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-01-09T15:18:52.374] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 true turn off on startup +[2025-01-09T15:18:52.391] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 true turn off on startup +[2025-01-09T15:18:52.397] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 true turn off on startup +[2025-01-09T15:18:52.411] [INFO] monitorLogs - MQTT client error Error: connect ECONNREFUSED 192.168.252.1:1883 + at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1159:16) { + errno: -111, + code: 'ECONNREFUSED', + syscall: 'connect', + address: '192.168.252.1', + port: 1883 +} +[2025-01-09T15:18:57.410] [INFO] monitorLogs - buildTasks - params undefined +[2025-01-09T15:18:57.412] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-01-09T15:18:57.412] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-01-09T15:18:57.416] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-09T15:18:57.418] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-01-10T07:13:00.417Z +[2025-01-09T15:18:57.419] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-01-09T15:45:00.419Z +[2025-01-09T15:18:57.420] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '8:13', name: 'luxOff' }, + { value: 1, start_time: '16:45', name: 'luxOn' } +] +[2025-01-09T15:18:57.421] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-01-09T15:18:57.422] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-01-09T15:18:57.422] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-01-09T15:18:57.425] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-09T15:18:57.426] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-01-10T07:13:00.425Z +[2025-01-09T15:18:57.426] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-01-09T15:45:00.426Z +[2025-01-09T15:18:57.427] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '8:13', name: 'luxOff' }, + { value: 1, start_time: '16:45', name: 'luxOn' } +] +[2025-01-09T15:18:57.428] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-01-09T15:18:57.429] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-01-09T15:18:57.429] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-01-09T15:18:57.431] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-09T15:18:57.432] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-01-10T07:13:00.432Z +[2025-01-09T15:18:57.433] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-01-09T15:45:00.432Z +[2025-01-09T15:18:57.433] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '8:13', name: 'luxOff' }, + { value: 1, start_time: '16:45', name: 'luxOn' } +] +[2025-01-09T15:18:57.434] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-01-09T15:18:57.440] [INFO] monitorLogs - tasks created: 974 +[2025-01-09T15:18:57.443] [INFO] monitorLogs - -->FLOW bol spustený d5xjWYMwEJon6rLlK7yEaP7qgV4DaOeNB9ZX3Gzb 2025-01-02 +[2025-01-09T16:34:23.532] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-01-09T16:34:23.574] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-01-09T16:34:23.581] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-01-10T03:18:53.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-10 03:18:53 +[2025-01-10T07:29:55.167] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-01-10T07:29:55.214] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-01-10T07:29:55.220] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-01-10T14:30:31.136] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-01-10T14:30:36.481] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 true turn off on startup +[2025-01-10T14:30:36.495] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 true turn off on startup +[2025-01-10T14:30:36.501] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 true turn off on startup +[2025-01-10T14:30:36.571] [INFO] monitorLogs - MQTT client error Error: connect ECONNREFUSED 192.168.252.1:1883 + at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1159:16) { + errno: -111, + code: 'ECONNREFUSED', + syscall: 'connect', + address: '192.168.252.1', + port: 1883 +} +[2025-01-10T14:30:41.513] [INFO] monitorLogs - buildTasks - params undefined +[2025-01-10T14:30:41.515] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-01-10T14:30:41.515] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-01-10T14:30:41.520] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-10T14:30:41.522] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-01-11T07:12:00.521Z +[2025-01-10T14:30:41.523] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-01-10T15:46:00.523Z +[2025-01-10T14:30:41.523] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '8:12', name: 'luxOff' }, + { value: 1, start_time: '16:46', name: 'luxOn' } +] +[2025-01-10T14:30:41.525] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-01-10T14:30:41.526] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-01-10T14:30:41.526] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-01-10T14:30:41.529] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-10T14:30:41.529] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-01-11T07:12:00.529Z +[2025-01-10T14:30:41.530] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-01-10T15:46:00.530Z +[2025-01-10T14:30:41.531] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '8:12', name: 'luxOff' }, + { value: 1, start_time: '16:46', name: 'luxOn' } +] +[2025-01-10T14:30:41.532] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-01-10T14:30:41.532] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-01-10T14:30:41.533] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-01-10T14:30:41.535] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-01-10T14:30:41.536] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-01-11T07:12:00.535Z +[2025-01-10T14:30:41.536] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-01-10T15:46:00.536Z +[2025-01-10T14:30:41.537] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '8:12', name: 'luxOff' }, + { value: 1, start_time: '16:46', name: 'luxOn' } +] +[2025-01-10T14:30:41.538] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-01-10T14:30:41.544] [INFO] monitorLogs - tasks created: 974 +[2025-01-10T14:30:41.547] [INFO] monitorLogs - -->FLOW bol spustený d5xjWYMwEJon6rLlK7yEaP7qgV4DaOeNB9ZX3Gzb 2025-01-09 +[2025-01-10T15:58:14.683] [INFO] monitorLogs - MQTT client connected +[2025-01-10T16:31:17.392] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-01-10T16:31:17.431] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-01-10T16:31:17.438] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-01-11T03:30:38.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-11 03:30:38 +[2025-01-11T07:21:49.806] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-01-11T07:21:49.857] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-01-11T07:21:49.864] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-01-11T16:36:11.954] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-01-11T16:36:11.989] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-01-11T16:36:11.995] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-01-12T03:30:39.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-12 03:30:39 +[2025-01-12T07:29:13.813] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-01-12T07:29:13.853] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-01-12T07:29:13.860] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-01-12T16:33:33.928] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-01-12T16:33:33.966] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-01-12T16:33:33.972] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-01-13T03:30:40.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-13 03:30:40 +[2025-01-13T07:36:37.038] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-01-13T07:36:37.051] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-01-13T07:36:37.060] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-01-13T08:08:12.792] [INFO] monitorLogs - MQTT client connected +[2025-01-13T16:35:55.833] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-01-13T16:35:55.871] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-01-13T16:35:55.878] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-01-14T03:30:41.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-14 03:30:41 +[2025-01-14T07:13:54.797] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-01-14T07:13:54.809] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-01-14T07:13:54.816] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-01-14T16:40:49.090] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-01-14T16:40:49.127] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-01-14T16:40:49.133] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-01-15T03:30:41.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-15 03:30:41 +[2025-01-15T07:23:26.977] [INFO] monitorLogs - MQTT client connected +[2025-01-15T07:23:46.939] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-01-15T07:23:46.952] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-01-15T07:23:46.960] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-01-15T16:38:08.838] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-01-15T16:38:08.873] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-01-15T16:38:08.879] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-01-16T03:30:42.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-16 03:30:42 +[2025-01-16T07:21:07.714] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-01-16T07:21:07.757] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-01-16T07:21:07.763] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-01-16T16:37:59.851] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-01-16T16:37:59.885] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-01-16T16:37:59.893] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-01-17T03:30:43.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-17 03:30:43 +[2025-01-17T07:23:29.285] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-01-17T07:23:29.297] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-01-17T07:23:29.302] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-01-17T16:42:52.187] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-01-17T16:42:52.231] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-01-17T16:42:52.238] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-01-18T03:30:44.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-18 03:30:44 +[2025-01-18T07:20:50.909] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-01-18T07:20:50.943] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-01-18T07:20:50.949] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-01-18T16:47:45.393] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-01-18T16:47:45.430] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-01-18T16:47:45.436] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-01-19T03:30:44.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-19 03:30:44 +[2025-01-19T07:20:41.333] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-01-19T07:20:41.345] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-01-19T07:20:41.351] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-01-19T16:45:05.083] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-01-19T16:45:05.118] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-01-19T16:45:05.125] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-01-20T01:30:23.144] [INFO] monitorLogs - MQTT client connected +[2025-01-20T03:30:45.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-20 03:30:45 +[2025-01-20T07:20:33.009] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-01-20T07:20:33.021] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-01-20T07:20:33.029] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-01-20T16:44:56.710] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-01-20T16:44:56.746] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-01-20T16:44:56.752] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-01-21T03:30:46.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-21 03:30:46 +[2025-01-21T06:22:00.011] [INFO] monitorLogs - MQTT client connected +[2025-01-21T07:25:24.852] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-01-21T07:25:24.863] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-01-21T07:25:24.870] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-01-21T16:47:19.169] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-01-21T16:47:19.213] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-01-21T16:47:19.219] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-01-22T03:30:47.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-22 03:30:47 +[2025-01-22T07:22:46.848] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-01-22T07:22:46.882] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-01-22T07:22:46.892] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-01-22T13:29:45.333] [INFO] monitorLogs - MQTT client connected +[2025-01-22T13:30:13.173] [INFO] monitorLogs - MQTT client connected +[2025-01-22T13:35:35.928] [INFO] monitorLogs - MQTT client connected +[2025-01-22T13:39:02.030] [INFO] monitorLogs - MQTT client connected +[2025-01-22T16:42:09.592] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-01-22T16:42:09.630] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-01-22T16:42:09.636] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-01-23T03:30:47.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-23 03:30:47 +[2025-01-23T07:17:35.899] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-01-23T07:17:35.910] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-01-23T07:17:35.915] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-01-23T16:49:31.879] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-01-23T16:49:31.916] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-01-23T16:49:31.922] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-01-24T01:21:47.276] [INFO] monitorLogs - MQTT client connected +[2025-01-24T03:30:48.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-24 03:30:48 +[2025-01-24T07:04:56.435] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-01-24T07:04:56.447] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-01-24T07:04:56.454] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-01-24T16:56:55.725] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-01-24T16:56:55.763] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-01-24T16:56:55.769] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-01-25T03:30:49.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-25 03:30:49 +[2025-01-25T07:12:18.801] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-01-25T07:12:18.862] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-01-25T07:12:18.869] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-01-25T16:49:15.200] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-01-25T16:49:15.236] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-01-25T16:49:15.242] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-01-26T03:30:50.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-26 03:30:50 +[2025-01-26T07:12:10.742] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-01-26T07:12:10.754] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-01-26T07:12:10.761] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-01-26T16:56:38.368] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-01-26T16:56:38.404] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-01-26T16:56:38.410] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-01-27T03:30:50.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-27 03:30:50 +[2025-01-27T07:04:29.180] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-01-27T07:04:29.216] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-01-27T07:04:29.222] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-01-27T17:01:30.589] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-01-27T17:01:30.626] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-01-27T17:01:30.632] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-01-28T03:30:51.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-28 03:30:51 +[2025-01-28T07:14:23.984] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-01-28T07:14:24.017] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-01-28T07:14:24.024] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-01-28T16:53:50.646] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-01-28T16:53:50.683] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-01-28T16:53:50.689] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-01-29T03:30:52.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-29 03:30:52 +[2025-01-29T07:04:13.197] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-01-29T07:04:13.207] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-01-29T07:04:13.213] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-01-29T17:06:14.497] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-01-29T17:06:14.535] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-01-29T17:06:14.541] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-01-30T03:30:53.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-30 03:30:53 +[2025-01-30T06:56:33.340] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-01-30T06:56:33.353] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-01-30T06:56:33.359] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-01-30T17:08:36.496] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-01-30T17:08:36.532] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-01-30T17:08:36.538] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-01-31T03:30:53.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-01-31 03:30:53 +[2025-01-31T06:58:54.140] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-01-31T06:58:54.152] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-01-31T06:58:54.160] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-01-31T08:10:51.645] [INFO] monitorLogs - MQTT client connected +[2025-01-31T17:08:26.846] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-01-31T17:08:26.881] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-01-31T17:08:26.888] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-02-01T03:30:54.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-01 03:30:54 +[2025-02-01T06:53:44.264] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-02-01T06:53:44.279] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-02-01T06:53:44.289] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-02-01T17:08:18.702] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-02-01T17:08:18.739] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-02-01T17:08:18.745] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-02-02T03:30:55.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-02 03:30:55 +[2025-02-02T07:06:08.581] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-02-02T07:06:08.593] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-02-02T07:06:08.600] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-02-02T17:10:40.498] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-02-02T17:10:40.535] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-02-02T17:10:40.541] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-02-03T03:30:55.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-03 03:30:55 +[2025-02-03T06:50:56.569] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-02-03T06:50:56.580] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-02-03T06:50:56.586] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-02-03T07:00:02.064] [INFO] monitorLogs - MQTT client connected +[2025-02-03T07:01:48.576] [INFO] monitorLogs - MQTT client connected +[2025-02-03T07:02:14.514] [INFO] monitorLogs - MQTT client connected +[2025-02-03T07:05:03.832] [INFO] monitorLogs - MQTT client connected +[2025-02-03T10:36:51.247] [INFO] monitorLogs - MQTT client connected +[2025-02-03T17:13:02.360] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-02-03T17:13:02.395] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-02-03T17:13:02.401] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-02-04T03:30:56.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-04 03:30:56 +[2025-02-04T06:50:48.547] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-02-04T06:50:48.580] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-02-04T06:50:48.588] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-02-04T17:15:25.421] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-02-04T17:15:25.458] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-02-04T17:15:25.464] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-02-05T03:30:57.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-05 03:30:57 +[2025-02-05T06:48:10.585] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-02-05T06:48:10.597] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-02-05T06:48:10.604] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-02-05T17:17:47.192] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-02-05T17:17:47.230] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-02-05T17:17:47.236] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-02-06T03:30:58.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-06 03:30:58 +[2025-02-06T06:50:31.704] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-02-06T06:50:31.724] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-02-06T06:50:31.730] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-02-06T17:15:07.473] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-02-06T17:15:07.508] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-02-06T17:15:07.514] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-02-07T03:30:59.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-07 03:30:59 +[2025-02-07T06:50:22.657] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-02-07T06:50:22.671] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-02-07T06:50:22.676] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-02-07T08:39:32.748] [INFO] monitorLogs - MQTT client connected +[2025-02-07T08:41:28.249] [INFO] monitorLogs - MQTT client connected +[2025-02-07T08:41:46.932] [INFO] monitorLogs - MQTT client connected +[2025-02-07T08:43:25.735] [INFO] monitorLogs - MQTT client connected +[2025-02-07T08:44:35.127] [INFO] monitorLogs - MQTT client connected +[2025-02-07T08:45:30.169] [INFO] monitorLogs - MQTT client connected +[2025-02-07T08:46:22.485] [INFO] monitorLogs - MQTT client connected +[2025-02-07T17:12:28.766] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-02-07T17:12:28.802] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-02-07T17:12:28.808] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-02-08T02:40:36.046] [INFO] monitorLogs - MQTT client connected +[2025-02-08T03:30:59.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-08 03:30:59 +[2025-02-08T06:47:43.153] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-02-08T06:47:43.164] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-02-08T06:47:43.170] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-02-08T17:22:22.061] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-02-08T17:22:22.096] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-02-08T17:22:22.103] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-02-09T03:31:00.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-09 03:31:00 +[2025-02-09T06:52:36.550] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-02-09T06:52:36.586] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-02-09T06:52:36.592] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-02-09T12:01:08.497] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-02-09T12:01:13.862] [INFO] monitorLogs - buildTasks - params undefined +[2025-02-09T12:01:13.867] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-02-09T12:01:13.868] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-02-09T12:01:13.869] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-02-09T12:01:13.873] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-02-09T12:01:13.875] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-02-10T06:40:00.874Z +[2025-02-09T12:01:13.876] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-02-09T16:32:00.876Z +[2025-02-09T12:01:13.877] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:40', name: 'luxOff' }, + { value: 1, start_time: '17:32', name: 'luxOn' } +] +[2025-02-09T12:01:13.878] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-02-09T12:01:13.879] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-02-09T12:01:13.880] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-02-09T12:01:13.882] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-02-09T12:01:13.883] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-02-10T06:40:00.883Z +[2025-02-09T12:01:13.883] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-02-09T16:32:00.883Z +[2025-02-09T12:01:13.884] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:40', name: 'luxOff' }, + { value: 1, start_time: '17:32', name: 'luxOn' } +] +[2025-02-09T12:01:13.885] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-02-09T12:01:13.886] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-02-09T12:01:13.886] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-02-09T12:01:13.888] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-02-09T12:01:13.889] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-02-10T06:40:00.889Z +[2025-02-09T12:01:13.890] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-02-09T16:32:00.890Z +[2025-02-09T12:01:13.891] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:40', name: 'luxOff' }, + { value: 1, start_time: '17:32', name: 'luxOn' } +] +[2025-02-09T12:01:13.892] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-02-09T12:01:13.897] [INFO] monitorLogs - tasks created: 914 +[2025-02-09T12:01:13.899] [INFO] monitorLogs - -->FLOW bol spustený d5xjWYMwEJon6rLlK7yEaP7qgV4DaOeNB9ZX3Gzb 2025-01-30 +[2025-02-09T12:01:13.988] [INFO] monitorLogs - MQTT client connected +[2025-02-09T12:01:14.209] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-02-09T12:01:14.513] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-02-09T12:01:14.818] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-02-09T12:17:55.108] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-02-09T12:18:00.472] [INFO] monitorLogs - buildTasks - params undefined +[2025-02-09T12:18:00.477] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-02-09T12:18:00.478] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-02-09T12:18:00.479] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-02-09T12:18:00.483] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-02-09T12:18:00.485] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-02-10T06:40:00.484Z +[2025-02-09T12:18:00.486] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-02-09T16:32:00.486Z +[2025-02-09T12:18:00.487] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:40', name: 'luxOff' }, + { value: 1, start_time: '17:32', name: 'luxOn' } +] +[2025-02-09T12:18:00.488] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-02-09T12:18:00.489] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-02-09T12:18:00.489] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-02-09T12:18:00.492] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-02-09T12:18:00.493] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-02-10T06:40:00.493Z +[2025-02-09T12:18:00.494] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-02-09T16:32:00.494Z +[2025-02-09T12:18:00.495] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:40', name: 'luxOff' }, + { value: 1, start_time: '17:32', name: 'luxOn' } +] +[2025-02-09T12:18:00.496] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-02-09T12:18:00.497] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-02-09T12:18:00.497] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-02-09T12:18:00.499] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-02-09T12:18:00.500] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-02-10T06:40:00.500Z +[2025-02-09T12:18:00.501] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-02-09T16:32:00.501Z +[2025-02-09T12:18:00.502] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:40', name: 'luxOff' }, + { value: 1, start_time: '17:32', name: 'luxOn' } +] +[2025-02-09T12:18:00.503] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-02-09T12:18:00.508] [INFO] monitorLogs - tasks created: 914 +[2025-02-09T12:18:00.510] [INFO] monitorLogs - -->FLOW bol spustený d5xjWYMwEJon6rLlK7yEaP7qgV4DaOeNB9ZX3Gzb 2025-01-30 +[2025-02-09T12:18:00.600] [INFO] monitorLogs - MQTT client connected +[2025-02-09T12:18:00.819] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-02-09T12:18:01.123] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-02-09T12:18:01.428] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-02-09T17:14:16.804] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-02-09T17:14:16.807] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-02-09T17:14:16.810] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-02-10T03:18:02.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-10 03:18:02 +[2025-02-10T06:44:31.929] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-02-10T06:44:31.931] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-02-10T06:44:31.933] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-02-10T17:24:10.453] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-02-10T17:24:10.456] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-02-10T17:24:10.458] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-02-11T03:18:03.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-11 03:18:03 +[2025-02-11T06:41:54.229] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-02-11T06:41:54.231] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-02-11T06:41:54.233] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-02-11T17:24:05.186] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-02-11T17:24:05.207] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-02-11T17:24:05.209] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-02-12T03:18:04.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-12 03:18:04 +[2025-02-12T06:51:49.020] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-02-12T06:51:49.022] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-02-12T06:51:49.024] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-02-12T17:16:24.401] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-02-12T17:16:24.403] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-02-12T17:16:24.405] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-02-13T03:18:05.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-13 03:18:05 +[2025-02-13T06:51:39.598] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-02-13T06:51:39.601] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-02-13T06:51:39.604] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-02-13T13:18:38.518] [INFO] monitorLogs - MQTT client connected +[2025-02-13T13:19:55.549] [INFO] monitorLogs - MQTT client connected +[2025-02-13T13:20:37.338] [INFO] monitorLogs - MQTT client connected +[2025-02-13T13:22:06.460] [INFO] monitorLogs - MQTT client connected +[2025-02-13T13:23:36.308] [INFO] monitorLogs - MQTT client connected +[2025-02-13T13:23:55.163] [INFO] monitorLogs - MQTT client connected +[2025-02-13T15:23:07.837] [INFO] monitorLogs - MQTT client connected +[2025-02-13T17:18:46.857] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-02-13T17:18:46.859] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-02-13T17:18:46.861] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-02-14T03:18:05.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-14 03:18:05 +[2025-02-14T06:36:28.833] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-02-14T06:36:28.835] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-02-14T06:36:28.837] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-02-14T17:21:08.817] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-02-14T17:21:08.826] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-02-14T17:21:08.827] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-02-15T03:18:06.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-15 03:18:06 +[2025-02-15T06:46:21.945] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-02-15T06:46:21.947] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-02-15T06:46:21.949] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-02-15T17:28:30.847] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-02-15T17:28:30.849] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-02-15T17:28:30.851] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-02-16T03:18:07.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-16 03:18:07 +[2025-02-16T06:36:10.536] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-02-16T06:36:10.538] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-02-16T06:36:10.539] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-02-16T17:28:21.419] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-02-16T17:28:21.421] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-02-16T17:28:21.423] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-02-17T03:18:08.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-17 03:18:08 +[2025-02-17T06:36:01.240] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-02-17T06:36:01.242] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-02-17T06:36:01.243] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-02-17T07:05:03.256] [INFO] monitorLogs - MQTT client connected +[2025-02-17T08:04:41.880] [INFO] monitorLogs - MQTT client connected +[2025-02-17T08:56:38.514] [INFO] monitorLogs - MQTT client connected +[2025-02-17T10:02:43.287] [INFO] monitorLogs - MQTT client connected +[2025-02-17T17:28:12.160] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-02-17T17:28:12.162] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-02-17T17:28:12.164] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-02-18T03:18:09.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-18 03:18:09 +[2025-02-18T06:38:22.311] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-02-18T06:38:22.313] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-02-18T06:38:22.314] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-02-18T17:38:04.904] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-02-18T17:38:04.911] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-02-18T17:38:04.913] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-02-19T03:18:09.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-19 03:18:09 +[2025-02-19T06:25:39.839] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-02-19T06:25:39.842] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-02-19T06:25:39.844] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-02-19T14:18:32.279] [INFO] monitorLogs - MQTT client connected +[2025-02-19T15:06:41.519] [INFO] monitorLogs - MQTT client connected +[2025-02-19T15:09:54.326] [INFO] monitorLogs - MQTT client connected +[2025-02-19T15:13:08.668] [INFO] monitorLogs - MQTT client connected +[2025-02-19T17:37:55.586] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-02-19T17:37:55.590] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-02-19T17:37:55.592] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-02-20T03:18:10.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-20 03:18:10 +[2025-02-20T06:25:32.445] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-02-20T06:25:32.447] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-02-20T06:25:32.449] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-02-20T09:20:19.447] [INFO] monitorLogs - MQTT client connected +[2025-02-20T17:40:18.088] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-02-20T17:40:18.090] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-02-20T17:40:18.092] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-02-21T03:18:11.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-21 03:18:11 +[2025-02-21T06:22:53.150] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-02-21T06:22:53.152] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-02-21T06:22:53.154] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-02-21T06:56:11.273] [INFO] monitorLogs - MQTT client connected +[2025-02-21T17:40:09.823] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-02-21T17:40:09.829] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-02-21T17:40:09.831] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-02-22T03:18:11.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-22 03:18:11 +[2025-02-22T06:22:44.137] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-02-22T06:22:44.139] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-02-22T06:22:44.141] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-02-22T17:42:30.699] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-02-22T17:42:30.709] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-02-22T17:42:30.711] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-02-23T03:18:12.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-23 03:18:12 +[2025-02-23T06:22:34.788] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-02-23T06:22:34.804] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-02-23T06:22:34.807] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-02-23T17:34:49.655] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-02-23T17:34:49.657] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-02-23T17:34:49.659] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-02-24T03:18:13.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-24 03:18:13 +[2025-02-24T06:22:25.349] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-02-24T06:22:25.351] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-02-24T06:22:25.353] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-02-24T09:08:57.419] [INFO] monitorLogs - MQTT client connected +[2025-02-24T14:02:34.421] [INFO] monitorLogs - MQTT client connected +[2025-02-24T17:44:42.444] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-02-24T17:44:42.455] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-02-24T17:44:42.457] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-02-25T03:18:14.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-25 03:18:14 +[2025-02-25T06:24:47.399] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-02-25T06:24:47.401] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-02-25T06:24:47.403] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-02-25T06:50:39.097] [INFO] monitorLogs - MQTT client connected +[2025-02-25T06:51:10.775] [INFO] monitorLogs - MQTT client connected +[2025-02-25T06:51:58.461] [INFO] monitorLogs - MQTT client connected +[2025-02-25T06:53:16.854] [INFO] monitorLogs - MQTT client connected +[2025-02-25T06:54:57.012] [INFO] monitorLogs - MQTT client connected +[2025-02-25T06:55:41.011] [INFO] monitorLogs - MQTT client connected +[2025-02-25T06:57:23.712] [INFO] monitorLogs - MQTT client connected +[2025-02-25T06:57:54.726] [INFO] monitorLogs - MQTT client connected +[2025-02-25T06:58:17.225] [INFO] monitorLogs - MQTT client connected +[2025-02-25T07:11:52.200] [INFO] monitorLogs - MQTT client connected +[2025-02-25T07:13:23.553] [INFO] monitorLogs - MQTT client connected +[2025-02-25T07:15:19.720] [INFO] monitorLogs - MQTT client connected +[2025-02-25T07:16:59.149] [INFO] monitorLogs - MQTT client connected +[2025-02-25T07:18:10.682] [INFO] monitorLogs - MQTT client connected +[2025-02-25T12:36:46.388] [INFO] monitorLogs - MQTT client connected +[2025-02-25T12:37:24.205] [INFO] monitorLogs - MQTT client connected +[2025-02-25T12:37:51.722] [INFO] monitorLogs - MQTT client connected +[2025-02-25T14:05:09.067] [INFO] monitorLogs - MQTT client connected +[2025-02-25T14:05:33.156] [INFO] monitorLogs - MQTT client connected +[2025-02-25T14:07:11.075] [INFO] monitorLogs - MQTT client connected +[2025-02-25T14:07:45.668] [INFO] monitorLogs - MQTT client connected +[2025-02-25T14:08:54.216] [INFO] monitorLogs - MQTT client connected +[2025-02-25T14:11:56.192] [INFO] monitorLogs - MQTT client connected +[2025-02-25T14:12:53.104] [INFO] monitorLogs - MQTT client connected +[2025-02-25T14:13:38.977] [INFO] monitorLogs - MQTT client connected +[2025-02-25T14:14:14.218] [INFO] monitorLogs - MQTT client connected +[2025-02-25T14:20:51.861] [INFO] monitorLogs - MQTT client connected +[2025-02-25T17:44:34.304] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-02-25T17:44:34.307] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-02-25T17:44:34.308] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-02-26T03:18:14.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-26 03:18:14 +[2025-02-26T06:34:40.206] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-02-26T06:34:40.208] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-02-26T06:34:40.210] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-02-26T17:41:54.305] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-02-26T17:41:54.307] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-02-26T17:41:54.309] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-02-27T03:18:15.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-27 03:18:15 +[2025-02-27T06:24:29.665] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-02-27T06:24:29.667] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-02-27T06:24:29.669] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-02-27T17:41:46.981] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-02-27T17:41:47.008] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-02-27T17:41:47.009] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-02-28T03:18:16.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-02-28 03:18:16 +[2025-02-28T06:14:19.612] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-02-28T06:14:19.614] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-02-28T06:14:19.616] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-02-28T12:19:28.718] [INFO] monitorLogs - MQTT client connected +[2025-02-28T12:26:52.498] [INFO] monitorLogs - MQTT client connected +[2025-02-28T17:51:39.419] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-02-28T17:51:39.432] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-02-28T17:51:39.434] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-03-01T03:18:17.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-01 03:18:17 +[2025-03-01T06:11:39.930] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-03-01T06:11:39.951] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-03-01T06:11:39.953] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-03-01T17:54:00.811] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-03-01T17:54:00.817] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-03-01T17:54:00.819] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-03-02T03:18:17.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-02 03:18:17 +[2025-03-02T06:08:58.800] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-03-02T06:08:58.803] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-03-02T06:08:58.804] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-03-02T17:56:21.667] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-03-02T17:56:21.669] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-03-02T17:56:21.671] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-03-03T03:18:18.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-03 03:18:18 +[2025-03-03T06:03:49.904] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-03-03T06:03:49.917] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-03-03T06:03:49.918] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-03-03T08:06:46.599] [INFO] monitorLogs - MQTT client connected +[2025-03-03T17:58:44.272] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-03-03T17:58:44.287] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-03-03T17:58:44.289] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-03-04T03:18:19.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-04 03:18:19 +[2025-03-04T06:03:41.265] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-03-04T06:03:41.267] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-03-04T06:03:41.269] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-03-04T07:04:05.636] [INFO] monitorLogs - MQTT client connected +[2025-03-04T07:04:55.941] [INFO] monitorLogs - MQTT client connected +[2025-03-04T07:06:47.227] [INFO] monitorLogs - MQTT client connected +[2025-03-04T07:08:46.592] [INFO] monitorLogs - MQTT client connected +[2025-03-04T07:09:18.825] [INFO] monitorLogs - MQTT client connected +[2025-03-04T07:14:19.291] [INFO] monitorLogs - MQTT client connected +[2025-03-04T07:14:47.782] [INFO] monitorLogs - MQTT client connected +[2025-03-04T07:15:41.862] [INFO] monitorLogs - MQTT client connected +[2025-03-04T07:17:06.120] [INFO] monitorLogs - MQTT client connected +[2025-03-04T07:18:32.620] [INFO] monitorLogs - MQTT client connected +[2025-03-04T07:19:00.547] [INFO] monitorLogs - MQTT client connected +[2025-03-04T07:25:26.115] [INFO] monitorLogs - MQTT client connected +[2025-03-04T17:58:35.134] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-03-04T17:58:35.139] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-03-04T17:58:35.141] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-03-05T03:18:20.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-05 03:18:20 +[2025-03-05T06:01:01.606] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-03-05T06:01:01.608] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-03-05T06:01:01.610] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-03-05T13:17:32.680] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false command received from platform +[2025-03-05T13:17:50.518] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false command received from platform +[2025-03-05T13:18:15.558] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false command received from platform +[2025-03-05T14:25:44.157] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false command received from platform +[2025-03-05T14:26:07.517] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false command received from platform +[2025-03-05T14:26:21.407] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false command received from platform +[2025-03-05T14:26:54.556] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false command received from platform +[2025-03-05T14:27:09.924] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false command received from platform +[2025-03-05T14:27:26.556] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false command received from platform +[2025-03-05T14:31:38.812] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false command received from platform +[2025-03-05T14:31:55.771] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false command received from platform +[2025-03-05T14:32:13.371] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false command received from platform +[2025-03-05T15:01:40.127] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false command received from platform +[2025-03-05T15:02:14.632] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false command received from platform +[2025-03-05T15:02:33.511] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false command received from platform +[2025-03-05T15:37:12.208] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false command received from platform +[2025-03-05T15:37:21.496] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false command received from platform +[2025-03-05T15:37:32.167] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false command received from platform +[2025-03-05T18:01:52.959] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-03-05T18:01:52.964] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-03-05T18:01:52.966] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-03-06T03:18:21.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-06 03:18:21 +[2025-03-06T05:59:19.892] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-03-06T05:59:19.894] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-03-06T05:59:19.896] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-03-06T18:01:45.721] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-03-06T18:01:45.737] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-03-06T18:01:45.738] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-03-07T03:18:22.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-07 03:18:22 +[2025-03-07T06:01:42.290] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-03-07T06:01:42.292] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-03-07T06:01:42.294] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-03-07T18:04:07.804] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-03-07T18:04:07.806] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-03-07T18:04:07.808] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-03-08T03:18:22.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-08 03:18:22 +[2025-03-08T05:56:31.270] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-03-08T05:56:31.287] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-03-08T05:56:31.289] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-03-08T18:03:57.288] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-03-08T18:03:57.307] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-03-08T18:03:57.308] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-03-09T03:18:23.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-09 03:18:23 +[2025-03-09T05:58:52.424] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-03-09T05:58:52.426] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-03-09T05:58:52.428] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-03-09T18:06:18.439] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-03-09T18:06:18.475] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-03-09T18:06:18.477] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-03-10T03:18:24.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-10 03:18:24 +[2025-03-10T05:58:42.995] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-03-10T05:58:42.997] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-03-10T05:58:42.999] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-03-10T09:02:12.124] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false command received from platform +[2025-03-10T09:02:36.116] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false command received from platform +[2025-03-10T09:02:47.948] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false command received from platform +[2025-03-10T09:55:34.638] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false command received from platform +[2025-03-10T09:55:48.811] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false command received from platform +[2025-03-10T09:56:08.238] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false command received from platform +[2025-03-10T09:56:27.766] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false command received from platform +[2025-03-10T10:00:56.235] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false command received from platform +[2025-03-10T10:48:45.968] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false command received from platform +[2025-03-10T11:18:57.790] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false command received from platform +[2025-03-10T11:19:06.117] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false command received from platform +[2025-03-10T11:21:21.097] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-03-10T11:21:26.465] [INFO] monitorLogs - buildTasks - params undefined +[2025-03-10T11:21:26.469] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-03-10T11:21:26.471] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-03-10T11:21:26.471] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-03-10T11:21:26.476] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-03-10T11:21:26.477] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-03-11T05:46:00.476Z +[2025-03-10T11:21:26.478] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-03-10T17:19:00.478Z +[2025-03-10T11:21:26.479] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '6:46', name: 'luxOff' }, + { value: 1, start_time: '18:19', name: 'luxOn' } +] +[2025-03-10T11:21:26.480] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-03-10T11:21:26.481] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-03-10T11:21:26.482] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-03-10T11:21:26.484] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-03-10T11:21:26.485] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-03-11T05:46:00.485Z +[2025-03-10T11:21:26.486] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-03-10T17:19:00.485Z +[2025-03-10T11:21:26.486] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '6:46', name: 'luxOff' }, + { value: 1, start_time: '18:19', name: 'luxOn' } +] +[2025-03-10T11:21:26.487] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-03-10T11:21:26.488] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-03-10T11:21:26.489] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-03-10T11:21:26.491] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-03-10T11:21:26.491] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-03-11T05:46:00.491Z +[2025-03-10T11:21:26.492] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-03-10T17:19:00.492Z +[2025-03-10T11:21:26.493] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '6:46', name: 'luxOff' }, + { value: 1, start_time: '18:19', name: 'luxOn' } +] +[2025-03-10T11:21:26.494] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-03-10T11:21:26.499] [INFO] monitorLogs - tasks created: 914 +[2025-03-10T11:21:26.502] [INFO] monitorLogs - -->FLOW bol spustený d5xjWYMwEJon6rLlK7yEaP7qgV4DaOeNB9ZX3Gzb 2025-01-30 +[2025-03-10T11:21:26.811] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-03-10T11:21:26.884] [INFO] monitorLogs - MQTT client connected +[2025-03-10T11:21:27.115] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-03-10T11:21:27.419] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-03-10T11:22:07.275] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false command received from platform +[2025-03-10T11:22:12.765] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false command received from platform +[2025-03-10T11:22:18.736] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false command received from platform +[2025-03-10T11:25:35.986] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false command received from platform +[2025-03-10T11:25:42.233] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false command received from platform +[2025-03-10T11:25:48.400] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false command received from platform +[2025-03-10T14:29:42.828] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false command received from platform +[2025-03-10T14:29:50.053] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false command received from platform +[2025-03-10T14:29:55.962] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false command received from platform +[2025-03-10T14:44:01.698] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false command received from platform +[2025-03-10T14:44:06.818] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false command received from platform +[2025-03-10T14:44:11.938] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false command received from platform +[2025-03-10T17:53:02.205] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-03-10T17:53:02.208] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-03-10T17:53:02.210] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-03-10T20:31:54.782] [INFO] monitorLogs - MQTT client connected +[2025-03-11T03:21:28.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-11 03:21:28 +[2025-03-11T05:52:58.940] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-03-11T05:52:58.943] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-03-11T05:52:58.945] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-03-11T08:18:57.865] [INFO] monitorLogs - MQTT client connected +[2025-03-11T08:20:10.231] [INFO] monitorLogs - MQTT client connected +[2025-03-11T08:21:12.842] [INFO] monitorLogs - MQTT client connected +[2025-03-11T08:21:50.763] [INFO] monitorLogs - MQTT client connected +[2025-03-11T08:24:21.068] [INFO] monitorLogs - MQTT client connected +[2025-03-11T13:01:35.238] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false command received from platform +[2025-03-11T13:01:44.835] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false command received from platform +[2025-03-11T13:01:51.844] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false command received from platform +[2025-03-11T13:11:12.799] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false command received from platform +[2025-03-11T13:11:18.886] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false command received from platform +[2025-03-11T13:11:26.558] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false command received from platform +[2025-03-11T18:02:56.790] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-03-11T18:02:56.792] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-03-11T18:02:56.794] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-03-12T03:21:28.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-12 03:21:28 +[2025-03-12T05:52:50.020] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-03-12T05:52:50.023] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-03-12T05:52:50.025] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-03-12T14:16:02.145] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false command received from platform +[2025-03-12T14:16:15.558] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false command received from platform +[2025-03-12T14:16:22.485] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false command received from platform +[2025-03-12T14:34:42.105] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false command received from platform +[2025-03-12T14:34:48.185] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false command received from platform +[2025-03-12T14:34:53.945] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false command received from platform +[2025-03-12T15:53:52.874] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-03-12T15:53:58.220] [INFO] monitorLogs - buildTasks - params undefined +[2025-03-12T15:53:58.225] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-03-12T15:53:58.227] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-03-12T15:53:58.227] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-03-12T15:53:58.232] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-03-12T15:53:58.233] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-03-13T05:41:00.232Z +[2025-03-12T15:53:58.235] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-03-12T17:22:00.234Z +[2025-03-12T15:53:58.235] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '6:41', name: 'luxOff' }, + { value: 1, start_time: '18:22', name: 'luxOn' } +] +[2025-03-12T15:53:58.237] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-03-12T15:53:58.237] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-03-12T15:53:58.238] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-03-12T15:53:58.240] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-03-12T15:53:58.241] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-03-13T05:41:00.241Z +[2025-03-12T15:53:58.242] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-03-12T17:22:00.242Z +[2025-03-12T15:53:58.243] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '6:41', name: 'luxOff' }, + { value: 1, start_time: '18:22', name: 'luxOn' } +] +[2025-03-12T15:53:58.244] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-03-12T15:53:58.244] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-03-12T15:53:58.245] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-03-12T15:53:58.247] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-03-12T15:53:58.248] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-03-13T05:41:00.248Z +[2025-03-12T15:53:58.249] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-03-12T17:22:00.248Z +[2025-03-12T15:53:58.249] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '6:41', name: 'luxOff' }, + { value: 1, start_time: '18:22', name: 'luxOn' } +] +[2025-03-12T15:53:58.250] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-03-12T15:53:58.256] [INFO] monitorLogs - tasks created: 914 +[2025-03-12T15:53:58.258] [INFO] monitorLogs - -->FLOW bol spustený d5xjWYMwEJon6rLlK7yEaP7qgV4DaOeNB9ZX3Gzb 2025-01-30 +[2025-03-12T15:53:58.486] [INFO] monitorLogs - MQTT client connected +[2025-03-12T15:53:58.568] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-03-12T15:53:58.872] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-03-12T15:53:59.176] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-03-12T18:09:41.701] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-03-12T18:09:41.704] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-03-12T18:09:41.706] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-03-13T03:54:00.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-13 03:54:00 +[2025-03-13T06:04:38.522] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-03-13T06:04:38.524] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-03-13T06:04:38.526] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-03-13T08:26:51.568] [INFO] monitorLogs - MQTT client connected +[2025-03-13T09:45:02.034] [INFO] monitorLogs - MQTT client connected +[2025-03-13T09:45:43.622] [INFO] monitorLogs - MQTT client connected +[2025-03-13T09:46:53.737] [INFO] monitorLogs - MQTT client connected +[2025-03-13T09:48:25.335] [INFO] monitorLogs - MQTT client connected +[2025-03-13T09:49:42.376] [INFO] monitorLogs - MQTT client connected +[2025-03-13T10:13:28.385] [INFO] monitorLogs - MQTT client connected +[2025-03-13T15:59:00.293] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false command received from platform +[2025-03-13T15:59:07.955] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false command received from platform +[2025-03-13T15:59:13.074] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false command received from platform +[2025-03-13T16:04:37.233] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false command received from platform +[2025-03-13T16:04:44.592] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false command received from platform +[2025-03-13T16:04:50.672] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false command received from platform +[2025-03-13T18:12:06.017] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-03-13T18:12:06.019] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-03-13T18:12:06.021] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-03-14T03:54:01.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-14 03:54:01 +[2025-03-14T05:56:59.936] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-03-14T05:56:59.938] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-03-14T05:56:59.940] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-03-14T18:06:56.699] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-03-14T18:06:56.702] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-03-14T18:06:56.704] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-03-15T03:54:01.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-15 03:54:01 +[2025-03-15T05:59:20.271] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-03-15T05:59:20.274] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-03-15T05:59:20.276] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-03-15T18:11:50.852] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-03-15T18:11:50.855] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-03-15T18:11:50.857] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-03-16T03:54:02.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-16 03:54:02 +[2025-03-16T05:46:44.057] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-03-16T05:46:44.059] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-03-16T05:46:44.061] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-03-16T18:16:44.971] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-03-16T18:16:44.974] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-03-16T18:16:44.976] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-03-17T03:54:03.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-17 03:54:03 +[2025-03-17T05:49:06.089] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-03-17T05:49:06.091] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-03-17T05:49:06.093] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-03-17T06:45:04.622] [INFO] monitorLogs - MQTT client connected +[2025-03-17T07:03:46.210] [INFO] monitorLogs - MQTT client connected +[2025-03-17T07:05:34.555] [INFO] monitorLogs - MQTT client connected +[2025-03-17T18:16:37.367] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-03-17T18:16:37.385] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-03-17T18:16:37.387] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-03-18T03:54:04.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-18 03:54:04 +[2025-03-18T05:33:54.994] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-03-18T05:33:54.997] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-03-18T05:33:54.998] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-03-18T18:21:30.105] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-03-18T18:21:30.126] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-03-18T18:21:30.128] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-03-19T03:54:04.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-19 03:54:04 +[2025-03-19T05:31:15.443] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-03-19T05:31:15.446] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-03-19T05:31:15.448] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-03-19T18:23:50.602] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-03-19T18:23:50.612] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-03-19T18:23:50.614] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-03-20T03:54:05.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-20 03:54:05 +[2025-03-20T05:28:36.709] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-03-20T05:28:36.711] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-03-20T05:28:36.713] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-03-20T11:08:33.608] [INFO] monitorLogs - MQTT client connected +[2025-03-20T18:23:43.127] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-03-20T18:23:43.153] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-03-20T18:23:43.155] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-03-21T03:54:06.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-21 03:54:06 +[2025-03-21T05:28:28.357] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-03-21T05:28:28.359] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-03-21T05:28:28.361] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-03-21T18:23:34.267] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-03-21T18:23:34.286] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-03-21T18:23:34.287] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-03-22T03:54:07.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-22 03:54:07 +[2025-03-22T05:25:48.655] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-03-22T05:25:48.657] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-03-22T05:25:48.659] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-03-22T18:18:23.764] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-03-22T18:18:23.767] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-03-22T18:18:23.769] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-03-23T03:54:08.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-23 03:54:08 +[2025-03-23T05:35:42.074] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-03-23T05:35:42.076] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-03-23T05:35:42.078] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-03-23T18:25:46.733] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-03-23T18:25:46.736] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-03-23T18:25:46.738] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-03-24T03:54:09.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-24 03:54:09 +[2025-03-24T05:33:02.616] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-03-24T05:33:02.619] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-03-24T05:33:02.621] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-03-24T07:54:56.038] [INFO] monitorLogs - MQTT client connected +[2025-03-24T08:03:02.798] [INFO] monitorLogs - MQTT client connected +[2025-03-24T08:05:54.236] [INFO] monitorLogs - MQTT client connected +[2025-03-24T08:07:41.104] [INFO] monitorLogs - MQTT client connected +[2025-03-24T08:10:03.509] [INFO] monitorLogs - MQTT client connected +[2025-03-24T12:17:08.294] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-03-24T12:17:13.649] [INFO] monitorLogs - buildTasks - params undefined +[2025-03-24T12:17:13.654] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-03-24T12:17:13.655] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-03-24T12:17:13.656] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-03-24T12:17:13.660] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-03-24T12:17:13.661] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-03-25T05:16:00.660Z +[2025-03-24T12:17:13.663] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-03-24T17:40:00.662Z +[2025-03-24T12:17:13.663] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '6:16', name: 'luxOff' }, + { value: 1, start_time: '18:40', name: 'luxOn' } +] +[2025-03-24T12:17:13.665] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-03-24T12:17:13.666] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-03-24T12:17:13.666] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-03-24T12:17:13.669] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-03-24T12:17:13.669] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-03-25T05:16:00.669Z +[2025-03-24T12:17:13.670] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-03-24T17:40:00.670Z +[2025-03-24T12:17:13.671] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '6:16', name: 'luxOff' }, + { value: 1, start_time: '18:40', name: 'luxOn' } +] +[2025-03-24T12:17:13.672] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-03-24T12:17:13.673] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-03-24T12:17:13.674] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-03-24T12:17:13.676] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-03-24T12:17:13.676] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-03-25T05:16:00.676Z +[2025-03-24T12:17:13.677] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-03-24T17:40:00.677Z +[2025-03-24T12:17:13.678] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '6:16', name: 'luxOff' }, + { value: 1, start_time: '18:40', name: 'luxOn' } +] +[2025-03-24T12:17:13.679] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-03-24T12:17:13.684] [INFO] monitorLogs - tasks created: 914 +[2025-03-24T12:17:13.687] [INFO] monitorLogs - -->FLOW bol spustený d5xjWYMwEJon6rLlK7yEaP7qgV4DaOeNB9ZX3Gzb 2025-01-30 +[2025-03-24T12:17:13.773] [INFO] monitorLogs - MQTT client connected +[2025-03-24T12:17:13.995] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-03-24T12:17:14.300] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-03-24T12:17:14.604] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-03-24T18:26:15.030] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-03-24T18:26:15.045] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-03-24T18:26:15.048] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-03-25T03:17:14.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-25 03:17:14 +[2025-03-25T05:25:58.556] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-03-25T05:25:58.558] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-03-25T05:25:58.560] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-03-25T08:01:05.263] [INFO] monitorLogs - MQTT client connected +[2025-03-25T13:14:36.142] [INFO] monitorLogs - MQTT client connected +[2025-03-25T18:31:07.952] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-03-25T18:31:07.957] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-03-25T18:31:07.959] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-03-26T03:17:15.013] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-26 03:17:15 +[2025-03-26T05:20:49.908] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-03-26T05:20:49.911] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-03-26T05:20:49.913] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-03-26T11:56:26.884] [INFO] monitorLogs - MQTT client connected +[2025-03-26T18:30:59.840] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-03-26T18:30:59.842] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-03-26T18:30:59.844] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-03-27T03:17:16.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-27 03:17:16 +[2025-03-27T05:20:41.808] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-03-27T05:20:41.811] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-03-27T05:20:41.813] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-03-27T18:33:20.994] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-03-27T18:33:20.997] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-03-27T18:33:20.999] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-03-28T03:17:17.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-28 03:17:17 +[2025-03-28T05:18:01.999] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-03-28T05:18:02.001] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-03-28T05:18:02.003] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-03-28T07:33:01.024] [INFO] monitorLogs - MQTT client connected +[2025-03-28T07:34:43.902] [INFO] monitorLogs - MQTT client connected +[2025-03-28T07:35:20.840] [INFO] monitorLogs - MQTT client connected +[2025-03-28T18:25:40.285] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-03-28T18:25:40.298] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-03-28T18:25:40.300] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-03-29T03:17:18.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-29 03:17:18 +[2025-03-29T05:25:24.839] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-03-29T05:25:24.842] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-03-29T05:25:24.843] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-03-29T18:23:01.116] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-03-29T18:23:01.118] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-03-29T18:23:01.120] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-03-30T03:17:19.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-30 03:17:19 +[2025-03-30T06:22:45.078] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-03-30T06:22:45.081] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-03-30T06:22:45.083] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-03-30T19:27:53.362] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-03-30T19:27:53.394] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-03-30T19:27:53.397] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-03-31T03:17:19.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-03-31 03:17:19 +[2025-03-31T06:10:03.994] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-03-31T06:10:03.996] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-03-31T06:10:03.998] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-03-31T06:46:50.502] [INFO] monitorLogs - MQTT client connected +[2025-03-31T06:47:44.120] [INFO] monitorLogs - MQTT client connected +[2025-03-31T06:48:10.248] [INFO] monitorLogs - MQTT client connected +[2025-03-31T06:49:16.833] [INFO] monitorLogs - MQTT client connected +[2025-03-31T06:50:15.498] [INFO] monitorLogs - MQTT client connected +[2025-03-31T14:42:35.521] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-03-31T14:42:40.881] [INFO] monitorLogs - buildTasks - params undefined +[2025-03-31T14:42:40.885] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-03-31T14:42:40.887] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-03-31T14:42:40.887] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-03-31T14:42:40.892] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-03-31T14:42:40.893] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-04-01T05:02:00.892Z +[2025-03-31T14:42:40.894] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-03-31T17:50:00.894Z +[2025-03-31T14:42:40.895] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:2', name: 'luxOff' }, + { value: 1, start_time: '19:50', name: 'luxOn' } +] +[2025-03-31T14:42:40.896] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-03-31T14:42:40.897] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-03-31T14:42:40.898] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-03-31T14:42:40.900] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-03-31T14:42:40.901] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-04-01T05:02:00.901Z +[2025-03-31T14:42:40.902] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-03-31T17:50:00.902Z +[2025-03-31T14:42:40.902] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:2', name: 'luxOff' }, + { value: 1, start_time: '19:50', name: 'luxOn' } +] +[2025-03-31T14:42:40.903] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-03-31T14:42:40.904] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-03-31T14:42:40.905] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-03-31T14:42:40.907] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-03-31T14:42:40.908] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-04-01T05:02:00.908Z +[2025-03-31T14:42:40.909] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-03-31T17:50:00.908Z +[2025-03-31T14:42:40.909] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:2', name: 'luxOff' }, + { value: 1, start_time: '19:50', name: 'luxOn' } +] +[2025-03-31T14:42:40.910] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-03-31T14:42:40.916] [INFO] monitorLogs - tasks created: 914 +[2025-03-31T14:42:40.919] [INFO] monitorLogs - -->FLOW bol spustený d5xjWYMwEJon6rLlK7yEaP7qgV4DaOeNB9ZX3Gzb 2025-01-30 +[2025-03-31T14:42:41.010] [INFO] monitorLogs - MQTT client connected +[2025-03-31T14:42:41.228] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-03-31T14:42:41.532] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-03-31T14:42:41.836] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-03-31T17:34:52.711] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false command received from platform +[2025-03-31T17:35:00.064] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false command received from platform +[2025-03-31T17:35:05.829] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false command received from platform +[2025-03-31T17:43:36.531] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false command received from platform +[2025-03-31T17:43:48.693] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false command received from platform +[2025-03-31T17:43:59.258] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false command received from platform +[2025-03-31T19:38:57.219] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-03-31T19:38:57.222] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-03-31T19:38:57.224] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-04-01T03:42:43.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-01 03:42:43 +[2025-04-01T06:13:37.685] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-04-01T06:13:37.687] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-04-01T06:13:37.690] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-04-01T07:40:19.847] [INFO] monitorLogs - MQTT client connected +[2025-04-01T07:56:51.604] [INFO] monitorLogs - MQTT client connected +[2025-04-01T12:23:57.842] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false command received from platform +[2025-04-01T12:24:10.316] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false command received from platform +[2025-04-01T12:24:17.356] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false command received from platform +[2025-04-01T12:32:50.311] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false command received from platform +[2025-04-01T12:32:55.430] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false command received from platform +[2025-04-01T12:33:01.511] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false command received from platform +[2025-04-01T14:25:11.045] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-04-01T14:25:16.409] [INFO] monitorLogs - buildTasks - params undefined +[2025-04-01T14:25:16.414] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-04-01T14:25:16.415] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-04-01T14:25:16.416] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-04-01T14:25:16.420] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-04-01T14:25:16.421] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-04-02T04:59:00.420Z +[2025-04-01T14:25:16.423] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-04-01T17:51:00.422Z +[2025-04-01T14:25:16.423] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '6:59', name: 'luxOff' }, + { value: 1, start_time: '19:51', name: 'luxOn' } +] +[2025-04-01T14:25:16.424] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-04-01T14:25:16.425] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-04-01T14:25:16.426] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-04-01T14:25:16.428] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-04-01T14:25:16.429] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-04-02T04:59:00.429Z +[2025-04-01T14:25:16.430] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-04-01T17:51:00.430Z +[2025-04-01T14:25:16.430] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '6:59', name: 'luxOff' }, + { value: 1, start_time: '19:51', name: 'luxOn' } +] +[2025-04-01T14:25:16.431] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-04-01T14:25:16.432] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-04-01T14:25:16.433] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-04-01T14:25:16.435] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-04-01T14:25:16.436] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-04-02T04:59:00.435Z +[2025-04-01T14:25:16.436] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-04-01T17:51:00.436Z +[2025-04-01T14:25:16.437] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '6:59', name: 'luxOff' }, + { value: 1, start_time: '19:51', name: 'luxOn' } +] +[2025-04-01T14:25:16.438] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-04-01T14:25:16.443] [INFO] monitorLogs - tasks created: 914 +[2025-04-01T14:25:16.446] [INFO] monitorLogs - -->FLOW bol spustený d5xjWYMwEJon6rLlK7yEaP7qgV4DaOeNB9ZX3Gzb 2025-01-30 +[2025-04-01T14:25:16.529] [INFO] monitorLogs - MQTT client connected +[2025-04-01T14:25:16.755] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-04-01T14:25:17.059] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-04-01T14:25:17.363] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-04-01T19:39:06.387] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-04-01T19:39:06.391] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-04-01T19:39:06.393] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-04-02T02:18:36.233] [INFO] monitorLogs - MQTT client connected +[2025-04-02T03:21:43.894] [INFO] monitorLogs - MQTT client connected +[2025-04-02T03:25:19.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-02 03:25:19 +[2025-04-02T06:06:16.090] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-04-02T06:06:16.093] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-04-02T06:06:16.095] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-04-02T19:39:00.266] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-04-02T19:39:00.277] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-04-02T19:39:00.279] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-04-03T03:25:20.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-03 03:25:20 +[2025-04-03T06:01:07.698] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-04-03T06:01:07.701] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-04-03T06:01:07.703] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-04-03T19:46:24.459] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-04-03T19:46:24.467] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-04-03T19:46:24.469] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-04-04T03:25:21.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-04 03:25:21 +[2025-04-04T05:58:29.508] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-04-04T05:58:29.511] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-04-04T05:58:29.514] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-04-04T19:46:16.014] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-04-04T19:46:16.026] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-04-04T19:46:16.027] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-04-05T03:25:22.015] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-05 03:25:22 +[2025-04-05T06:00:51.014] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-04-05T06:00:51.017] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-04-05T06:00:51.020] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-04-05T19:46:06.766] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-04-05T19:46:06.768] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-04-05T19:46:06.770] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-04-06T03:25:22.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-06 03:25:22 +[2025-04-06T05:55:40.083] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-04-06T05:55:40.086] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-04-06T05:55:40.088] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-04-06T19:48:28.628] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-04-06T19:48:28.641] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-04-06T19:48:28.643] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-04-07T03:25:23.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-07 03:25:23 +[2025-04-07T06:05:34.328] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-04-07T06:05:34.336] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-04-07T06:05:34.338] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-04-07T08:35:31.443] [INFO] monitorLogs - MQTT client connected +[2025-04-07T08:37:45.263] [INFO] monitorLogs - MQTT client connected +[2025-04-07T19:38:18.062] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-04-07T19:38:18.078] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-04-07T19:38:18.080] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-04-08T03:25:24.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-08 03:25:24 +[2025-04-08T06:05:25.606] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-04-08T06:05:25.609] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-04-08T06:05:25.611] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-04-08T19:50:41.252] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-04-08T19:50:41.263] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-04-08T19:50:41.265] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-04-09T03:25:25.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-09 03:25:25 +[2025-04-09T05:50:12.980] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-04-09T05:50:12.983] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-04-09T05:50:12.985] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-04-09T08:28:51.569] [INFO] monitorLogs - MQTT client connected +[2025-04-09T19:53:02.318] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-04-09T19:53:02.333] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-04-09T19:53:02.335] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-04-10T03:25:26.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-10 03:25:26 +[2025-04-10T06:00:05.626] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-04-10T06:00:05.629] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-04-10T06:00:05.631] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-04-10T07:05:26.974] [INFO] monitorLogs - MQTT client connected +[2025-04-10T07:09:02.887] [INFO] monitorLogs - MQTT client connected +[2025-04-10T10:37:12.159] [INFO] monitorLogs - MQTT client connected +[2025-04-10T19:52:52.870] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-04-10T19:52:52.883] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-04-10T19:52:52.885] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-04-11T00:29:24.915] [INFO] monitorLogs - MQTT client connected +[2025-04-11T03:25:26.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-11 03:25:26 +[2025-04-11T05:47:22.769] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-04-11T05:47:22.772] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-04-11T05:47:22.773] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-04-11T19:50:12.214] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-04-11T19:50:12.235] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-04-11T19:50:12.237] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-04-12T03:25:27.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-12 03:25:27 +[2025-04-12T05:49:44.022] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-04-12T05:49:44.025] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-04-12T05:49:44.027] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-04-12T19:57:34.321] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-04-12T19:57:34.328] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-04-12T19:57:34.331] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-04-13T03:25:28.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-13 03:25:28 +[2025-04-13T05:39:33.049] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-04-13T05:39:33.052] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-04-13T05:39:33.054] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-04-13T19:52:24.803] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-04-13T19:52:24.811] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-04-13T19:52:24.813] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-04-14T03:25:29.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-14 03:25:29 +[2025-04-14T05:41:54.613] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-04-14T05:41:54.616] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-04-14T05:41:54.618] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-04-14T16:19:22.010] [INFO] monitorLogs - MQTT client connected +[2025-04-14T19:59:46.863] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-04-14T19:59:46.866] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-04-14T19:59:46.868] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-04-15T03:25:30.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-15 03:25:30 +[2025-04-15T05:54:17.870] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-04-15T05:54:17.873] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-04-15T05:54:17.875] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-04-15T11:19:25.716] [INFO] monitorLogs - MQTT client connected +[2025-04-15T19:59:37.712] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-04-15T19:59:37.715] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-04-15T19:59:37.717] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-04-16T03:25:31.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-16 03:25:31 +[2025-04-16T05:34:05.120] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-04-16T05:34:05.123] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-04-16T05:34:05.125] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-04-16T20:04:30.070] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-04-16T20:04:30.077] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-04-16T20:04:30.078] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-04-17T03:25:32.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-17 03:25:32 +[2025-04-17T05:36:26.762] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-04-17T05:36:26.765] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-04-17T05:36:26.767] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-04-17T19:56:50.014] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-04-17T19:56:50.021] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-04-17T19:56:50.023] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-04-18T03:25:33.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-18 03:25:33 +[2025-04-18T05:46:20.479] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-04-18T05:46:20.483] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-04-18T05:46:20.485] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-04-18T19:49:10.424] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-04-18T19:49:10.427] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-04-18T19:49:10.429] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-04-19T03:25:33.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-19 03:25:33 +[2025-04-19T05:28:37.072] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-04-19T05:28:37.075] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-04-19T05:28:37.077] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-04-19T20:09:03.978] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-04-19T20:09:03.984] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-04-19T20:09:03.986] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-04-20T03:25:34.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-20 03:25:34 +[2025-04-20T05:28:27.630] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-04-20T05:28:27.634] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-04-20T05:28:27.635] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-04-20T20:08:54.384] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-04-20T20:08:54.391] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-04-20T20:08:54.393] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-04-21T03:25:35.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-21 03:25:35 +[2025-04-21T05:28:18.937] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-04-21T05:28:18.940] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-04-21T05:28:18.943] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-04-21T20:11:16.844] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-04-21T20:11:16.850] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-04-21T20:11:16.852] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-04-22T03:25:36.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-22 03:25:36 +[2025-04-22T05:25:40.291] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-04-22T05:25:40.294] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-04-22T05:25:40.297] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-04-22T13:39:23.784] [INFO] monitorLogs - MQTT client connected +[2025-04-22T20:13:38.915] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-04-22T20:13:38.919] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-04-22T20:13:38.921] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-04-23T03:25:37.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-23 03:25:37 +[2025-04-23T05:30:32.985] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-04-23T05:30:32.989] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-04-23T05:30:32.991] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-04-23T20:11:00.191] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-04-23T20:11:00.198] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-04-23T20:11:00.200] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-04-24T03:25:38.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-24 03:25:38 +[2025-04-24T05:25:22.890] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-04-24T05:25:22.894] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-04-24T05:25:22.896] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-04-24T17:06:06.143] [INFO] monitorLogs - MQTT client connected +[2025-04-24T17:06:29.788] [INFO] monitorLogs - MQTT client connected +[2025-04-24T17:07:22.370] [INFO] monitorLogs - MQTT client connected +[2025-04-24T18:02:05.161] [INFO] monitorLogs - MQTT client connected +[2025-04-24T18:05:24.235] [INFO] monitorLogs - MQTT client connected +[2025-04-24T18:05:54.417] [INFO] monitorLogs - MQTT client connected +[2025-04-24T20:10:50.863] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-04-24T20:10:50.867] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-04-24T20:10:50.869] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-04-25T03:25:39.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-25 03:25:39 +[2025-04-25T05:35:16.370] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-04-25T05:35:16.374] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-04-25T05:35:16.376] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-04-25T10:31:49.182] [INFO] monitorLogs - MQTT client connected +[2025-04-25T20:13:13.230] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-04-25T20:13:13.232] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-04-25T20:13:13.234] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-04-26T03:25:40.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-26 03:25:40 +[2025-04-26T05:22:35.229] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-04-26T05:22:35.233] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-04-26T05:22:35.235] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-04-26T20:20:36.596] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-04-26T20:20:36.602] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-04-26T20:20:36.604] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-04-27T03:25:41.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-27 03:25:41 +[2025-04-27T05:14:55.998] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-04-27T05:14:56.001] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-04-27T05:14:56.003] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-04-27T20:20:27.954] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-04-27T20:20:27.961] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-04-27T20:20:27.963] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-04-28T03:25:42.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-28 03:25:42 +[2025-04-28T05:12:16.136] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-04-28T05:12:16.142] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-04-28T05:12:16.144] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-04-28T20:22:49.026] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-04-28T20:22:49.032] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-04-28T20:22:49.034] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-04-29T03:25:43.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-29 03:25:43 +[2025-04-29T05:12:06.579] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-04-29T05:12:06.583] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-04-29T05:12:06.585] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-04-29T06:55:15.370] [INFO] monitorLogs - MQTT client connected +[2025-04-29T06:56:01.449] [INFO] monitorLogs - MQTT client connected +[2025-04-29T07:48:21.119] [INFO] monitorLogs - MQTT client connected +[2025-04-29T07:49:03.639] [INFO] monitorLogs - MQTT client connected +[2025-04-29T07:49:33.301] [INFO] monitorLogs - MQTT client connected +[2025-04-29T07:50:19.985] [INFO] monitorLogs - MQTT client connected +[2025-04-29T07:50:59.262] [INFO] monitorLogs - MQTT client connected +[2025-04-29T07:52:11.656] [INFO] monitorLogs - MQTT client connected +[2025-04-29T07:53:25.700] [INFO] monitorLogs - MQTT client connected +[2025-04-29T07:54:02.700] [INFO] monitorLogs - MQTT client connected +[2025-04-29T20:25:10.178] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-04-29T20:25:10.181] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-04-29T20:25:10.182] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-04-30T03:25:44.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-04-30 03:25:44 +[2025-04-30T05:11:57.392] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-04-30T05:11:57.396] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-04-30T05:11:57.398] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-04-30T16:44:34.578] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-04-30T16:44:39.981] [INFO] monitorLogs - buildTasks - params undefined +[2025-04-30T16:44:39.985] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-04-30T16:44:39.987] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-04-30T16:44:39.987] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-04-30T16:44:39.992] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-04-30T16:44:39.993] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-05-01T04:03:00.992Z +[2025-04-30T16:44:39.994] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-04-30T18:34:00.994Z +[2025-04-30T16:44:39.995] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '6:3', name: 'luxOff' }, + { value: 1, start_time: '20:34', name: 'luxOn' } +] +[2025-04-30T16:44:39.996] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-04-30T16:44:39.997] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-04-30T16:44:39.998] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-04-30T16:44:40.000] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-04-30T16:44:40.001] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-05-01T04:03:00.001Z +[2025-04-30T16:44:40.002] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-04-30T18:34:00.002Z +[2025-04-30T16:44:40.002] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '6:3', name: 'luxOff' }, + { value: 1, start_time: '20:34', name: 'luxOn' } +] +[2025-04-30T16:44:40.003] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-04-30T16:44:40.004] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-04-30T16:44:40.005] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-04-30T16:44:40.007] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-04-30T16:44:40.007] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-05-01T04:03:00.007Z +[2025-04-30T16:44:40.008] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-04-30T18:34:00.008Z +[2025-04-30T16:44:40.009] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '6:3', name: 'luxOff' }, + { value: 1, start_time: '20:34', name: 'luxOn' } +] +[2025-04-30T16:44:40.010] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-04-30T16:44:40.036] [INFO] monitorLogs - tasks created: 854 +[2025-04-30T16:44:40.038] [INFO] monitorLogs - -->FLOW bol spustený d5xjWYMwEJon6rLlK7yEaP7qgV4DaOeNB9ZX3Gzb 2025-04-24 +[2025-04-30T16:44:40.159] [INFO] monitorLogs - MQTT client connected +[2025-04-30T16:44:40.347] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-04-30T16:44:40.652] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-04-30T16:44:40.957] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-04-30T20:25:40.994] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-04-30T20:25:40.997] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-04-30T20:25:41.000] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-05-01T03:44:42.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-01 03:44:42 +[2025-05-01T05:07:28.799] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-05-01T05:07:28.803] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-05-01T05:07:28.806] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-05-01T20:28:03.845] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-05-01T20:28:03.853] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-05-01T20:28:03.855] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-05-02T03:44:43.015] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-02 03:44:43 +[2025-05-02T05:04:49.271] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-05-02T05:04:49.275] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-05-02T05:04:49.278] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-05-02T20:27:56.534] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-05-02T20:27:56.542] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-05-02T20:27:56.545] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-05-03T03:44:44.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-03 03:44:44 +[2025-05-03T05:04:42.102] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-05-03T05:04:42.106] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-05-03T05:04:42.108] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-05-03T20:20:16.994] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-05-03T20:20:17.002] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-05-03T20:20:17.004] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-05-04T03:44:45.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-04 03:44:45 +[2025-05-04T05:09:34.627] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-05-04T05:09:34.631] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-05-04T05:09:34.633] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-05-04T20:30:09.817] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-05-04T20:30:09.825] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-05-04T20:30:09.828] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-05-05T03:44:46.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-05 03:44:46 +[2025-05-05T05:14:27.116] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-05-05T05:14:27.120] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-05-05T05:14:27.122] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-05-05T20:17:29.243] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-05-05T20:17:29.250] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-05-05T20:17:29.252] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-05-06T03:44:47.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-06 03:44:47 +[2025-05-06T05:09:17.473] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-05-06T05:09:17.477] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-05-06T05:09:17.479] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-05-06T08:11:34.442] [INFO] monitorLogs - MQTT client connected +[2025-05-06T20:29:53.564] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-05-06T20:29:53.572] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-05-06T20:29:53.574] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-05-07T03:44:48.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-07 03:44:48 +[2025-05-07T05:06:39.280] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-05-07T05:06:39.284] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-05-07T05:06:39.286] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-05-07T19:13:05.160] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-05-07T19:13:10.506] [INFO] monitorLogs - buildTasks - params undefined +[2025-05-07T19:13:10.511] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-05-07T19:13:10.512] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-05-07T19:13:10.513] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-05-07T19:13:10.517] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-05-07T19:13:10.518] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-05-08T03:52:00.518Z +[2025-05-07T19:13:10.520] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-05-07T18:44:00.519Z +[2025-05-07T19:13:10.520] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '5:52', name: 'luxOff' }, + { value: 1, start_time: '20:44', name: 'luxOn' } +] +[2025-05-07T19:13:10.522] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-05-07T19:13:10.522] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-05-07T19:13:10.523] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-05-07T19:13:10.525] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-05-07T19:13:10.526] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-05-08T03:52:00.526Z +[2025-05-07T19:13:10.527] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-05-07T18:44:00.527Z +[2025-05-07T19:13:10.528] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '5:52', name: 'luxOff' }, + { value: 1, start_time: '20:44', name: 'luxOn' } +] +[2025-05-07T19:13:10.529] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-05-07T19:13:10.529] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-05-07T19:13:10.530] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-05-07T19:13:10.532] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-05-07T19:13:10.533] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-05-08T03:52:00.533Z +[2025-05-07T19:13:10.534] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-05-07T18:44:00.533Z +[2025-05-07T19:13:10.534] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '5:52', name: 'luxOff' }, + { value: 1, start_time: '20:44', name: 'luxOn' } +] +[2025-05-07T19:13:10.535] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-05-07T19:13:10.557] [INFO] monitorLogs - tasks created: 854 +[2025-05-07T19:13:10.559] [INFO] monitorLogs - -->FLOW bol spustený d5xjWYMwEJon6rLlK7yEaP7qgV4DaOeNB9ZX3Gzb 2025-04-24 +[2025-05-07T19:13:10.694] [INFO] monitorLogs - MQTT client connected +[2025-05-07T19:13:10.867] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-05-07T19:13:11.173] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-05-07T19:13:11.476] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-05-07T20:31:12.187] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-05-07T20:31:12.190] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-05-07T20:31:12.193] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-05-08T03:13:12.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-08 03:13:12 +[2025-05-08T05:07:58.641] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-05-08T05:07:58.646] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-05-08T05:07:58.648] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-05-08T20:36:05.449] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-05-08T20:36:05.456] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-05-08T20:36:05.458] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-05-09T03:13:13.020] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-09 03:13:13 +[2025-05-09T04:55:19.089] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-05-09T04:55:19.093] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-05-09T04:55:19.096] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-05-09T20:40:59.386] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-05-09T20:40:59.394] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-05-09T20:40:59.396] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-05-10T03:13:14.013] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-10 03:13:14 +[2025-05-10T04:52:39.568] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-05-10T04:52:39.572] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-05-10T04:52:39.575] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-05-10T20:38:20.109] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-05-10T20:38:20.116] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-05-10T20:38:20.119] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-05-11T03:13:15.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-11 03:13:15 +[2025-05-11T05:00:02.642] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-05-11T05:00:02.645] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-05-11T05:00:02.648] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-05-11T20:43:11.869] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-05-11T20:43:11.872] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-05-11T20:43:11.874] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-05-12T03:13:16.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-12 03:13:16 +[2025-05-12T04:49:51.830] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-05-12T04:49:51.834] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-05-12T04:49:51.836] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-05-12T10:48:51.943] [INFO] monitorLogs - MQTT client connected +[2025-05-12T10:52:55.305] [INFO] monitorLogs - MQTT client connected +[2025-05-12T20:45:34.947] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-05-12T20:45:34.974] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-05-12T20:45:34.976] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-05-13T03:13:17.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-13 03:13:17 +[2025-05-13T04:49:43.454] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-05-13T04:49:43.457] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-05-13T04:49:43.459] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-05-13T20:45:25.461] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-05-13T20:45:25.479] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-05-13T20:45:25.481] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-05-14T03:13:18.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-14 03:13:18 +[2025-05-14T04:49:34.346] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-05-14T04:49:34.350] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-05-14T04:49:34.352] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-05-14T09:41:14.565] [INFO] monitorLogs - MQTT client connected +[2025-05-14T10:08:33.483] [INFO] monitorLogs - MQTT client connected +[2025-05-14T10:44:55.718] [INFO] monitorLogs - MQTT client connected +[2025-05-14T10:46:18.595] [INFO] monitorLogs - MQTT client connected +[2025-05-14T10:47:40.196] [INFO] monitorLogs - MQTT client connected +[2025-05-14T10:48:19.588] [INFO] monitorLogs - MQTT client connected +[2025-05-14T10:52:21.631] [INFO] monitorLogs - MQTT client connected +[2025-05-14T10:54:11.586] [INFO] monitorLogs - MQTT client connected +[2025-05-14T20:45:16.814] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-05-14T20:45:16.818] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-05-14T20:45:16.820] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-05-15T03:13:19.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-15 03:13:19 +[2025-05-15T04:59:27.233] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-05-15T04:59:27.237] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-05-15T04:59:27.239] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-05-15T20:37:35.858] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-05-15T20:37:35.861] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-05-15T20:37:35.863] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-05-16T03:13:20.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-16 03:13:20 +[2025-05-16T04:44:15.893] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-05-16T04:44:15.897] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-05-16T04:44:15.898] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-05-16T06:48:24.950] [INFO] monitorLogs - MQTT client connected +[2025-05-16T20:50:01.194] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-05-16T20:50:01.203] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-05-16T20:50:01.206] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-05-17T03:13:21.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-17 03:13:21 +[2025-05-17T04:56:40.205] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-05-17T04:56:40.209] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-05-17T04:56:40.212] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-05-17T20:49:51.813] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-05-17T20:49:51.816] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-05-17T20:49:51.818] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-05-18T03:13:21.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-18 03:13:21 +[2025-05-18T05:01:31.458] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-05-18T05:01:31.461] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-05-18T05:01:31.463] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-05-18T13:23:40.158] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-05-18T13:23:45.515] [INFO] monitorLogs - buildTasks - params undefined +[2025-05-18T13:23:45.520] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-05-18T13:23:45.521] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-05-18T13:23:45.521] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-05-18T13:23:45.525] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-05-18T13:23:45.527] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-05-19T03:37:00.526Z +[2025-05-18T13:23:45.528] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-05-18T19:00:00.528Z +[2025-05-18T13:23:45.529] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '5:37', name: 'luxOff' }, + { value: 1, start_time: '21:0', name: 'luxOn' } +] +[2025-05-18T13:23:45.530] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-05-18T13:23:45.531] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-05-18T13:23:45.531] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-05-18T13:23:45.534] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-05-18T13:23:45.534] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-05-19T03:37:00.534Z +[2025-05-18T13:23:45.535] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-05-18T19:00:00.535Z +[2025-05-18T13:23:45.536] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '5:37', name: 'luxOff' }, + { value: 1, start_time: '21:0', name: 'luxOn' } +] +[2025-05-18T13:23:45.537] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-05-18T13:23:45.538] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-05-18T13:23:45.538] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-05-18T13:23:45.540] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-05-18T13:23:45.541] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-05-19T03:37:00.541Z +[2025-05-18T13:23:45.542] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-05-18T19:00:00.542Z +[2025-05-18T13:23:45.542] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '5:37', name: 'luxOff' }, + { value: 1, start_time: '21:0', name: 'luxOn' } +] +[2025-05-18T13:23:45.543] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-05-18T13:23:45.565] [INFO] monitorLogs - tasks created: 854 +[2025-05-18T13:23:45.567] [INFO] monitorLogs - -->FLOW bol spustený d5xjWYMwEJon6rLlK7yEaP7qgV4DaOeNB9ZX3Gzb 2025-04-24 +[2025-05-18T13:23:50.576] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-05-18T20:48:01.909] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-05-18T20:48:01.918] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-05-18T20:48:01.921] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-05-19T03:23:48.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-19 03:23:48 +[2025-05-19T04:59:43.635] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-05-19T04:59:43.639] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-05-19T04:59:43.641] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-05-19T20:40:24.234] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-05-19T20:40:24.242] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-05-19T20:40:24.245] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-05-20T03:23:49.057] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-20 03:23:49 +[2025-05-20T04:54:35.042] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-05-20T04:54:35.046] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-05-20T04:54:35.048] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-05-20T20:55:18.387] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-05-20T20:55:18.402] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-05-20T20:55:18.404] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-05-21T03:23:50.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-21 03:23:50 +[2025-05-21T04:39:22.991] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-05-21T04:39:22.994] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-05-21T04:39:22.996] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-05-21T20:52:38.643] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-05-21T20:52:38.651] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-05-21T20:52:38.654] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-05-22T03:23:51.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-22 03:23:51 +[2025-05-22T04:41:44.477] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-05-22T04:41:44.481] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-05-22T04:41:44.483] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-05-22T20:47:29.095] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-05-22T20:47:29.105] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-05-22T20:47:29.107] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-05-23T03:23:52.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-23 03:23:52 +[2025-05-23T04:44:06.854] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-05-23T04:44:06.857] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-05-23T04:44:06.860] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-05-23T20:57:23.011] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-05-23T20:57:23.018] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-05-23T20:57:23.020] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-05-24T03:23:53.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-24 03:23:53 +[2025-05-24T04:36:27.147] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-05-24T04:36:27.151] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-05-24T04:36:27.154] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-05-24T20:59:44.817] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-05-24T20:59:44.830] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-05-24T20:59:44.832] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-05-25T03:23:54.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-25 03:23:54 +[2025-05-25T04:33:48.206] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-05-25T04:33:48.210] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-05-25T04:33:48.212] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-05-25T20:59:37.342] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-05-25T20:59:37.352] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-05-25T20:59:37.354] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-05-26T03:23:55.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-26 03:23:55 +[2025-05-26T04:46:12.978] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-05-26T04:46:12.986] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-05-26T04:46:12.988] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-05-26T21:02:00.208] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-05-26T21:02:00.215] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-05-26T21:02:00.217] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-05-27T03:23:56.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-27 03:23:56 +[2025-05-27T04:36:02.836] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-05-27T04:36:02.840] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-05-27T04:36:02.842] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-05-27T21:01:51.007] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-05-27T21:01:51.015] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-05-27T21:01:51.017] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-05-28T03:23:57.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-28 03:23:57 +[2025-05-28T04:30:52.498] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-05-28T04:30:52.501] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-05-28T04:30:52.504] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-05-28T21:04:13.370] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-05-28T21:04:13.378] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-05-28T21:04:13.380] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-05-29T03:23:58.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-29 03:23:58 +[2025-05-29T04:35:45.353] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-05-29T04:35:45.357] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-05-29T04:35:45.359] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-05-29T21:04:04.292] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-05-29T21:04:04.297] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-05-29T21:04:04.299] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-05-30T03:23:58.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-30 03:23:58 +[2025-05-30T04:33:04.778] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-05-30T04:33:04.782] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-05-30T04:33:04.784] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-05-30T16:20:15.611] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-05-30T16:20:20.981] [INFO] monitorLogs - buildTasks - params undefined +[2025-05-30T16:20:20.986] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-05-30T16:20:20.988] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-05-30T16:20:20.988] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-05-30T16:20:20.993] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-05-30T16:20:20.994] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-05-31T03:25:00.993Z +[2025-05-30T16:20:20.995] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-05-30T19:14:00.995Z +[2025-05-30T16:20:20.996] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '5:25', name: 'luxOff' }, + { value: 1, start_time: '21:14', name: 'luxOn' } +] +[2025-05-30T16:20:20.997] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-05-30T16:20:20.998] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-05-30T16:20:20.999] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-05-30T16:20:21.001] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-05-30T16:20:21.002] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-05-31T03:25:00.002Z +[2025-05-30T16:20:21.003] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-05-30T19:14:00.003Z +[2025-05-30T16:20:21.003] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '5:25', name: 'luxOff' }, + { value: 1, start_time: '21:14', name: 'luxOn' } +] +[2025-05-30T16:20:21.004] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-05-30T16:20:21.005] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-05-30T16:20:21.006] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-05-30T16:20:21.008] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-05-30T16:20:21.009] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-05-31T03:25:00.008Z +[2025-05-30T16:20:21.009] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-05-30T19:14:00.009Z +[2025-05-30T16:20:21.010] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '5:25', name: 'luxOff' }, + { value: 1, start_time: '21:14', name: 'luxOn' } +] +[2025-05-30T16:20:21.011] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-05-30T16:20:21.032] [INFO] monitorLogs - tasks created: 854 +[2025-05-30T16:20:21.034] [INFO] monitorLogs - -->FLOW bol spustený d5xjWYMwEJon6rLlK7yEaP7qgV4DaOeNB9ZX3Gzb 2025-04-24 +[2025-05-30T16:20:26.042] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-05-30T21:09:05.798] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-05-30T21:09:05.806] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-05-30T21:09:05.809] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-05-31T03:20:24.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-05-31 03:20:24 +[2025-05-31T04:28:07.566] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-05-31T04:28:07.570] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-05-31T04:28:07.573] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-05-31T21:01:27.071] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-05-31T21:01:27.079] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-05-31T21:01:27.081] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-06-01T03:20:25.026] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-01 03:20:25 +[2025-06-01T04:30:29.094] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-06-01T04:30:29.098] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-06-01T04:30:29.100] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-06-01T21:03:51.147] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-06-01T21:03:51.155] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-06-01T21:03:51.158] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-06-02T03:20:26.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-02 03:20:26 +[2025-06-02T04:27:51.618] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-06-02T04:27:51.622] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-06-02T04:27:51.625] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-06-02T20:51:09.304] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-06-02T20:51:09.311] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-06-02T20:51:09.313] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-06-03T03:20:27.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-03 03:20:27 +[2025-06-03T04:37:44.294] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-06-03T04:37:44.299] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-06-03T04:37:44.301] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-06-03T21:08:33.391] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-06-03T21:08:33.393] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-06-03T21:08:33.396] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-06-04T03:20:28.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-04 03:20:28 +[2025-06-04T04:27:32.895] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-06-04T04:27:32.899] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-06-04T04:27:32.901] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-06-04T17:08:37.178] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-06-04T17:08:42.539] [INFO] monitorLogs - buildTasks - params undefined +[2025-06-04T17:08:42.544] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-06-04T17:08:42.545] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-06-04T17:08:42.546] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-06-04T17:08:42.550] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-06-04T17:08:42.551] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-06-05T03:22:00.551Z +[2025-06-04T17:08:42.553] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-06-04T19:19:00.553Z +[2025-06-04T17:08:42.553] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '5:22', name: 'luxOff' }, + { value: 1, start_time: '21:19', name: 'luxOn' } +] +[2025-06-04T17:08:42.555] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-06-04T17:08:42.555] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-06-04T17:08:42.556] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-06-04T17:08:42.558] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-06-04T17:08:42.559] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-06-05T03:22:00.559Z +[2025-06-04T17:08:42.560] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-06-04T19:19:00.560Z +[2025-06-04T17:08:42.561] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '5:22', name: 'luxOff' }, + { value: 1, start_time: '21:19', name: 'luxOn' } +] +[2025-06-04T17:08:42.562] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-06-04T17:08:42.562] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-06-04T17:08:42.563] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-06-04T17:08:42.565] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-06-04T17:08:42.566] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-06-05T03:22:00.566Z +[2025-06-04T17:08:42.566] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-06-04T19:19:00.566Z +[2025-06-04T17:08:42.567] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '5:22', name: 'luxOff' }, + { value: 1, start_time: '21:19', name: 'luxOn' } +] +[2025-06-04T17:08:42.568] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-06-04T17:08:42.590] [INFO] monitorLogs - tasks created: 854 +[2025-06-04T17:08:42.592] [INFO] monitorLogs - -->FLOW bol spustený d5xjWYMwEJon6rLlK7yEaP7qgV4DaOeNB9ZX3Gzb 2025-04-24 +[2025-06-04T17:08:47.600] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-04T21:09:47.646] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-06-04T21:09:47.654] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-06-04T21:09:47.656] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-06-05T03:08:45.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-05 03:08:45 +[2025-06-05T04:28:48.948] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-06-05T04:28:48.951] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-06-05T04:28:48.953] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-06-05T15:04:37.951] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false command received from platform +[2025-06-05T15:04:48.193] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false command received from platform +[2025-06-05T15:04:54.585] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false command received from platform +[2025-06-05T15:21:11.113] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-06-05T15:21:16.462] [INFO] monitorLogs - buildTasks - params undefined +[2025-06-05T15:21:16.467] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-06-05T15:21:16.468] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-06-05T15:21:16.468] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-06-05T15:21:16.473] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-06-05T15:21:16.474] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-06-06T03:21:00.473Z +[2025-06-05T15:21:16.475] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-06-05T19:19:00.475Z +[2025-06-05T15:21:16.476] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '5:21', name: 'luxOff' }, + { value: 1, start_time: '21:19', name: 'luxOn' } +] +[2025-06-05T15:21:16.477] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-06-05T15:21:16.478] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-06-05T15:21:16.479] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-06-05T15:21:16.481] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-06-05T15:21:16.482] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-06-06T03:21:00.482Z +[2025-06-05T15:21:16.483] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-06-05T19:19:00.483Z +[2025-06-05T15:21:16.483] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '5:21', name: 'luxOff' }, + { value: 1, start_time: '21:19', name: 'luxOn' } +] +[2025-06-05T15:21:16.485] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-06-05T15:21:16.485] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-06-05T15:21:16.486] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-06-05T15:21:16.488] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-06-05T15:21:16.489] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-06-06T03:21:00.489Z +[2025-06-05T15:21:16.490] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-06-05T19:19:00.489Z +[2025-06-05T15:21:16.490] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '5:21', name: 'luxOff' }, + { value: 1, start_time: '21:19', name: 'luxOn' } +] +[2025-06-05T15:21:16.491] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-06-05T15:21:16.496] [INFO] monitorLogs - tasks created: 854 +[2025-06-05T15:21:16.515] [INFO] monitorLogs - -->FLOW bol spustený d5xjWYMwEJon6rLlK7yEaP7qgV4DaOeNB9ZX3Gzb 2025-04-24 +[2025-06-05T15:21:21.524] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-06-05T15:21:21.828] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-06-05T15:21:22.131] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-06-05T21:07:43.156] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-06-05T21:07:43.165] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-06-05T21:07:43.168] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-06-06T03:21:20.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-06 03:21:20 +[2025-06-06T04:29:15.807] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-06-06T04:29:15.811] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-06-06T04:29:15.813] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-06-06T21:10:08.438] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-06-06T21:10:08.445] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-06-06T21:10:08.448] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-06-07T03:21:21.017] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-07 03:21:21 +[2025-06-07T04:29:08.276] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-06-07T04:29:08.280] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-06-07T04:29:08.283] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-06-07T20:59:57.684] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-06-07T20:59:57.692] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-06-07T20:59:57.694] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-06-08T03:21:22.024] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-08 03:21:22 +[2025-06-08T04:23:58.154] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-06-08T04:23:58.158] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-06-08T04:23:58.160] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-06-08T21:14:52.310] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-06-08T21:14:52.318] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-06-08T21:14:52.320] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-06-09T03:21:23.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-09 03:21:23 +[2025-06-09T04:26:20.289] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-06-09T04:26:20.293] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-06-09T04:26:20.295] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-06-09T21:14:43.184] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-06-09T21:14:43.192] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-06-09T21:14:43.194] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-06-10T03:21:24.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-10 03:21:24 +[2025-06-10T04:26:11.188] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-06-10T04:26:11.191] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-06-10T04:26:11.194] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-06-10T21:14:34.194] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-06-10T21:14:34.202] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-06-10T21:14:34.204] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-06-11T03:21:25.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-11 03:21:25 +[2025-06-11T04:28:33.109] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-06-11T04:28:33.113] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-06-11T04:28:33.115] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-06-11T21:16:56.318] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-06-11T21:16:56.324] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-06-11T21:16:56.326] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-06-12T03:21:26.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-12 03:21:26 +[2025-06-12T04:23:23.268] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-06-12T04:23:23.272] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-06-12T04:23:23.274] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-06-12T21:19:17.644] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-06-12T21:19:17.651] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-06-12T21:19:17.653] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-06-13T03:21:27.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-13 03:21:27 +[2025-06-13T04:23:14.036] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-06-13T04:23:14.038] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-06-13T04:23:14.041] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-06-13T21:19:08.382] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-06-13T21:19:08.385] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-06-13T21:19:08.387] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-06-14T03:21:28.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-14 03:21:28 +[2025-06-14T04:20:34.427] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-06-14T04:20:34.430] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-06-14T04:20:34.432] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-06-14T21:18:59.134] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-06-14T21:18:59.137] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-06-14T21:18:59.139] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-06-15T03:21:37.345] [INFO] monitorLogs - setCorrectPlcTimeOnceADay - function error SyntaxError: Unexpected token < in JSON at position 0 + at JSON.parse () + at /home/unipi/flowserver/flow/cmd_manager.js:2411:28 + at Object.exec_callback [as callback] (/home/unipi/flowserver/node_modules/total.js/builders.js:5803:3) + at IncomingMessage.request_process_end (/home/unipi/flowserver/node_modules/total.js/utils.js:1184:11) + at IncomingMessage.emit (events.js:412:35) + at endReadableNT (internal/streams/readable.js:1334:12) + at processTicksAndRejections (internal/process/task_queues.js:82:21) 503: Service Unavailable
503
Service Unavailable
+[2025-06-15T04:22:54.858] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-06-15T04:22:54.862] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-06-15T04:22:54.864] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-06-15T21:18:49.007] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-06-15T21:18:49.011] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-06-15T21:18:49.013] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-06-16T03:21:30.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-16 03:21:30 +[2025-06-16T04:20:16.343] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-06-16T04:20:16.347] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-06-16T04:20:16.349] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-06-16T20:56:07.274] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-06-16T20:56:07.288] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-06-16T20:56:07.291] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-06-17T03:21:31.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-17 03:21:31 +[2025-06-17T04:30:10.569] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-06-17T04:30:10.572] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-06-17T04:30:10.575] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-06-17T21:18:33.559] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-06-17T21:18:33.567] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-06-17T21:18:33.569] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-06-18T03:21:32.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-18 03:21:32 +[2025-06-18T04:22:30.720] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-06-18T04:22:30.723] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-06-18T04:22:30.725] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-06-18T21:20:55.742] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-06-18T21:20:55.749] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-06-18T21:20:55.751] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-06-19T03:21:33.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-19 03:21:33 +[2025-06-19T04:22:21.786] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-06-19T04:22:21.790] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-06-19T04:22:21.793] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-06-19T21:20:46.490] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-06-19T21:20:46.496] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-06-19T21:20:46.498] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-06-20T03:21:34.013] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-20 03:21:34 +[2025-06-20T04:22:12.504] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-06-20T04:22:12.508] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-06-20T04:22:12.510] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-06-20T21:23:07.700] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-06-20T21:23:07.708] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-06-20T21:23:07.710] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-06-21T03:21:35.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-21 03:21:35 +[2025-06-21T04:24:33.748] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-06-21T04:24:33.751] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-06-21T04:24:33.754] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-06-21T21:20:27.947] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-06-21T21:20:27.949] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-06-21T21:20:27.951] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-06-22T03:21:37.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-22 03:21:37 +[2025-06-22T04:24:25.509] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-06-22T04:24:25.512] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-06-22T04:24:25.514] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-06-22T21:20:20.600] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-06-22T21:20:20.609] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-06-22T21:20:20.611] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-06-23T03:21:38.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-23 03:21:38 +[2025-06-23T04:24:17.554] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-06-23T04:24:17.557] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-06-23T04:24:17.560] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-06-23T21:10:09.842] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-06-23T21:10:09.848] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-06-23T21:10:09.851] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-06-24T03:21:39.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-24 03:21:39 +[2025-06-24T04:24:08.301] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-06-24T04:24:08.305] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-06-24T04:24:08.307] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-06-24T21:22:33.015] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-06-24T21:22:33.022] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-06-24T21:22:33.024] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-06-25T03:21:40.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-25 03:21:40 +[2025-06-25T04:23:59.318] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-06-25T04:23:59.321] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-06-25T04:23:59.323] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-06-25T21:22:24.643] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-06-25T21:22:24.651] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-06-25T21:22:24.653] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-06-26T03:21:41.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-26 03:21:41 +[2025-06-26T04:23:51.359] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-06-26T04:23:51.362] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-06-26T04:23:51.365] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-06-26T21:02:12.261] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-06-26T21:02:12.269] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-06-26T21:02:12.271] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-06-27T03:21:42.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-27 03:21:42 +[2025-06-27T04:31:14.579] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-06-27T04:31:14.583] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-06-27T04:31:14.585] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-06-27T21:14:37.235] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-06-27T21:14:37.241] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-06-27T21:14:37.244] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-06-28T03:21:44.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-28 03:21:44 +[2025-06-28T04:38:39.262] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-06-28T04:38:39.266] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-06-28T04:38:39.268] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-06-28T21:24:32.131] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-06-28T21:24:32.139] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-06-28T21:24:32.141] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-06-29T03:21:45.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-29 03:21:45 +[2025-06-29T04:25:58.497] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-06-29T04:25:58.501] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-06-29T04:25:58.503] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-06-29T21:21:53.269] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-06-29T21:21:53.277] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-06-29T21:21:53.280] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-06-30T03:21:46.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-06-30 03:21:46 +[2025-06-30T04:25:50.499] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-06-30T04:25:50.502] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-06-30T04:25:50.504] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-06-30T21:24:15.758] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-06-30T21:24:15.765] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-06-30T21:24:15.767] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-01T03:21:47.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-01 03:21:47 +[2025-07-01T04:25:42.291] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-01T04:25:42.294] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-01T04:25:42.297] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-01T21:24:07.413] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-01T21:24:07.421] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-01T21:24:07.423] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-02T03:21:48.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-02 03:21:48 +[2025-07-02T04:25:33.548] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-02T04:25:33.552] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-02T04:25:33.554] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-02T21:21:27.514] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-02T21:21:27.522] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-02T21:21:27.525] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-03T03:21:49.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-03 03:21:49 +[2025-07-03T04:25:24.103] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-03T04:25:24.107] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-03T04:25:24.109] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-03T21:11:16.196] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-03T21:11:16.204] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-03T21:11:16.206] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-04T03:21:51.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-04 03:21:51 +[2025-07-04T04:42:49.888] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-04T04:42:49.892] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-04T04:42:49.894] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-04T21:18:40.702] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-04T21:18:40.709] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-04T21:18:40.711] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-05T03:21:52.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-05 03:21:52 +[2025-07-05T04:27:38.352] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-05T04:27:38.355] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-05T04:27:38.357] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-05T21:18:31.295] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-05T21:18:31.301] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-05T21:18:31.304] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-06T03:21:53.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-06 03:21:53 +[2025-07-06T04:29:59.537] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-06T04:29:59.540] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-06T04:29:59.542] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-06T20:33:13.184] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-06T20:33:13.186] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-06T20:33:13.188] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-07T03:21:54.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-07 03:21:54 +[2025-07-07T04:47:23.818] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-07T04:47:23.821] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-07T04:47:23.823] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-07T14:25:37.258] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-07-07T14:25:42.605] [INFO] monitorLogs - buildTasks - params undefined +[2025-07-07T14:25:42.609] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-07-07T14:25:42.610] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-07-07T14:25:42.611] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-07-07T14:25:42.615] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-07-07T14:25:42.617] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-07-08T03:27:00.616Z +[2025-07-07T14:25:42.618] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-07-07T19:26:00.618Z +[2025-07-07T14:25:42.619] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '5:27', name: 'luxOff' }, + { value: 1, start_time: '21:26', name: 'luxOn' } +] +[2025-07-07T14:25:42.620] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-07-07T14:25:42.621] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-07-07T14:25:42.621] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-07-07T14:25:42.624] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-07-07T14:25:42.624] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-07-08T03:27:00.624Z +[2025-07-07T14:25:42.625] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-07-07T19:26:00.625Z +[2025-07-07T14:25:42.626] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '5:27', name: 'luxOff' }, + { value: 1, start_time: '21:26', name: 'luxOn' } +] +[2025-07-07T14:25:42.627] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-07-07T14:25:42.628] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-07-07T14:25:42.628] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-07-07T14:25:42.631] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-07-07T14:25:42.631] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-07-08T03:27:00.631Z +[2025-07-07T14:25:42.632] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-07-07T19:26:00.632Z +[2025-07-07T14:25:42.633] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '5:27', name: 'luxOff' }, + { value: 1, start_time: '21:26', name: 'luxOn' } +] +[2025-07-07T14:25:42.634] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-07-07T14:25:42.659] [INFO] monitorLogs - tasks created: 854 +[2025-07-07T14:25:42.661] [INFO] monitorLogs - -->FLOW bol spustený d5xjWYMwEJon6rLlK7yEaP7qgV4DaOeNB9ZX3Gzb 2025-04-24 +[2025-07-07T14:25:47.669] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-07T21:17:22.596] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-07T21:17:22.606] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-07T21:17:22.608] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-08T03:25:44.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-08 03:25:44 +[2025-07-08T04:46:24.567] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-08T04:46:24.570] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-08T04:46:24.572] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-08T20:59:41.072] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-08T20:59:41.080] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-08T20:59:41.083] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-09T03:25:45.040] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-09 03:25:45 +[2025-07-09T04:56:18.319] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-09T04:56:18.322] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-09T04:56:18.324] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-09T21:14:35.448] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-09T21:14:35.457] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-09T21:14:35.459] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-10T02:23:58.552] [INFO] monitorLogs - MQTT client error Error: connect ECONNREFUSED 192.168.252.1:1883 + at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1159:16) { + errno: -111, + code: 'ECONNREFUSED', + syscall: 'connect', + address: '192.168.252.1', + port: 1883 +} +[2025-07-10T03:25:46.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-10 03:25:46 +[2025-07-10T04:36:06.430] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-10T04:36:06.433] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-10T04:36:06.435] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-10T21:09:26.724] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-10T21:09:26.733] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-10T21:09:26.735] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-11T03:25:47.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-11 03:25:47 +[2025-07-11T04:38:28.246] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-11T04:38:28.249] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-11T04:38:28.251] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-11T21:14:19.708] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-11T21:14:19.721] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-11T21:14:19.724] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-12T03:25:48.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-12 03:25:48 +[2025-07-12T04:40:51.094] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-12T04:40:51.097] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-12T04:40:51.099] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-12T21:11:40.146] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-12T21:11:40.169] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-12T21:11:40.172] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-13T03:25:49.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-13 03:25:49 +[2025-07-13T04:40:41.933] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-13T04:40:41.935] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-13T04:40:41.937] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-13T21:11:31.366] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-13T21:11:31.374] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-13T21:11:31.376] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-14T03:25:51.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-14 03:25:51 +[2025-07-14T04:38:03.929] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-14T04:38:03.932] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-14T04:38:03.934] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-14T21:11:23.818] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-14T21:11:23.826] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-14T21:11:23.828] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-15T03:25:52.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-15 03:25:52 +[2025-07-15T04:42:55.986] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-15T04:42:55.988] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-15T04:42:55.990] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-15T21:06:13.984] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-15T21:06:14.003] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-15T21:06:14.005] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-16T03:25:53.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-16 03:25:53 +[2025-07-16T04:42:47.058] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-16T04:42:47.061] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-16T04:42:47.063] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-16T21:06:04.997] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-16T21:06:05.007] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-16T21:06:05.009] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-17T03:25:54.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-17 03:25:54 +[2025-07-17T04:50:10.440] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-17T04:50:10.442] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-17T04:50:10.444] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-17T21:05:57.456] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-17T21:05:57.475] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-17T21:05:57.477] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-18T03:25:55.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-18 03:25:55 +[2025-07-18T04:57:34.733] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-18T04:57:34.736] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-18T04:57:34.738] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-18T21:10:50.735] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-18T21:10:50.742] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-18T21:10:50.744] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-19T03:25:56.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-19 03:25:56 +[2025-07-19T04:49:54.389] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-19T04:49:54.391] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-19T04:49:54.393] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-19T21:08:11.295] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-19T21:08:11.306] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-19T21:08:11.308] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-20T03:25:57.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-20 03:25:57 +[2025-07-20T04:47:14.903] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-20T04:47:14.906] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-20T04:47:14.908] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-20T21:05:32.528] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-20T21:05:32.536] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-20T21:05:32.538] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-21T03:25:58.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-21 03:25:58 +[2025-07-21T04:47:06.693] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-21T04:47:06.695] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-21T04:47:06.697] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-21T20:35:18.231] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-21T20:35:18.234] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-21T20:35:18.236] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-22T03:26:00.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-22 03:26:00 +[2025-07-22T04:46:59.642] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-22T04:46:59.644] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-22T04:46:59.646] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-22T21:05:16.678] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-22T21:05:16.690] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-22T21:05:16.692] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-23T03:26:01.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-23 03:26:01 +[2025-07-23T04:46:51.165] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-23T04:46:51.167] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-23T04:46:51.169] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-23T08:29:27.120] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-07-23T08:29:32.471] [INFO] monitorLogs - buildTasks - params undefined +[2025-07-23T08:29:32.475] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-07-23T08:29:32.476] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-07-23T08:29:32.477] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-07-23T08:29:32.481] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-07-23T08:29:32.483] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-07-24T03:44:00.482Z +[2025-07-23T08:29:32.484] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-07-23T19:12:00.484Z +[2025-07-23T08:29:32.485] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '5:44', name: 'luxOff' }, + { value: 1, start_time: '21:12', name: 'luxOn' } +] +[2025-07-23T08:29:32.486] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-07-23T08:29:32.487] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-07-23T08:29:32.487] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-07-23T08:29:32.490] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-07-23T08:29:32.491] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-07-24T03:44:00.490Z +[2025-07-23T08:29:32.491] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-07-23T19:12:00.491Z +[2025-07-23T08:29:32.492] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '5:44', name: 'luxOff' }, + { value: 1, start_time: '21:12', name: 'luxOn' } +] +[2025-07-23T08:29:32.493] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-07-23T08:29:32.494] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-07-23T08:29:32.494] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-07-23T08:29:32.497] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-07-23T08:29:32.497] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-07-24T03:44:00.497Z +[2025-07-23T08:29:32.498] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-07-23T19:12:00.498Z +[2025-07-23T08:29:32.499] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '5:44', name: 'luxOff' }, + { value: 1, start_time: '21:12', name: 'luxOn' } +] +[2025-07-23T08:29:32.500] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-07-23T08:29:32.505] [INFO] monitorLogs - tasks created: 854 +[2025-07-23T08:29:32.524] [INFO] monitorLogs - -->FLOW bol spustený d5xjWYMwEJon6rLlK7yEaP7qgV4DaOeNB9ZX3Gzb 2025-04-24 +[2025-07-23T08:29:37.532] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-23T21:02:21.265] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-23T21:02:21.273] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-23T21:02:21.276] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-24T03:29:35.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-24 03:29:35 +[2025-07-24T04:53:58.695] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-24T04:53:58.697] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-24T04:53:58.699] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-24T09:41:48.648] [INFO] monitorLogs - turnLine on - (line, SETTINGS.maintenance_mode) 0 true command received from platform +[2025-07-24T09:47:46.681] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false command received from platform +[2025-07-24T09:48:07.480] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false command received from platform +[2025-07-24T09:49:27.656] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false command received from platform +[2025-07-24T09:49:37.930] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false command received from platform +[2025-07-24T09:53:05.396] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false command received from platform +[2025-07-24T09:55:41.554] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false command received from platform +[2025-07-24T09:56:12.914] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false command received from platform +[2025-07-24T10:03:02.513] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false command received from platform +[2025-07-24T10:04:39.147] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false command received from platform +[2025-07-24T10:05:10.187] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false command received from platform +[2025-07-24T10:05:32.906] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false command received from platform +[2025-07-24T20:52:11.701] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-24T20:52:11.703] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-25T03:29:36.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-25 03:29:36 +[2025-07-25T04:56:20.351] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-25T04:56:20.353] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-25T04:56:20.355] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-25T20:52:03.998] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-25T20:52:04.004] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-25T20:52:04.006] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-26T03:29:37.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-26 03:29:37 +[2025-07-26T04:58:43.101] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-26T04:58:43.103] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-26T04:58:43.106] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-26T20:56:55.871] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-26T20:56:55.878] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-26T20:56:55.880] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-27T03:29:38.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-27 03:29:38 +[2025-07-27T05:01:04.592] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-27T05:01:04.595] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-27T05:01:04.597] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-27T20:44:14.314] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-27T20:44:14.326] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-27T20:44:14.328] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-28T03:29:39.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-28 03:29:39 +[2025-07-28T05:00:55.702] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-28T05:00:55.705] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-28T05:00:55.707] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-28T13:35:05.034] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false command received from platform +[2025-07-28T13:47:54.586] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false command received from platform +[2025-07-28T13:53:45.941] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false command received from platform +[2025-07-28T14:28:00.510] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-28T14:28:00.813] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-28T14:28:01.117] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-28T14:28:01.421] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false aplikovany bod profilu +[2025-07-28T14:28:01.723] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false aplikovany bod profilu +[2025-07-28T14:28:02.026] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-07-28T20:49:06.523] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-28T20:49:06.525] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-28T20:49:06.527] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-29T03:29:40.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-29 03:29:40 +[2025-07-29T05:00:46.785] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-29T05:00:46.787] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-29T05:00:46.789] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-29T12:19:34.307] [INFO] monitorLogs - MQTT client error Error: connect ECONNREFUSED 192.168.252.1:1883 + at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1159:16) { + errno: -111, + code: 'ECONNREFUSED', + syscall: 'connect', + address: '192.168.252.1', + port: 1883 +} +[2025-07-29T20:54:01.069] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-29T20:54:01.115] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-29T20:54:01.117] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-30T03:29:42.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-30 03:29:42 +[2025-07-30T04:58:11.318] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-30T04:58:11.321] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-30T04:58:11.323] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-30T20:48:52.603] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-30T20:48:52.612] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-30T20:48:52.614] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-07-31T03:29:43.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-07-31 03:29:43 +[2025-07-31T05:00:32.796] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-07-31T05:00:32.798] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-07-31T05:00:32.800] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-07-31T20:51:14.079] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-07-31T20:51:14.087] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-07-31T20:51:14.089] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-01T03:29:44.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-01 03:29:44 +[2025-08-01T05:00:24.100] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-01T05:00:24.102] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-01T05:00:24.104] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-01T20:38:33.580] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-01T20:38:33.592] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-01T20:38:33.601] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-02T03:29:45.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-02 03:29:45 +[2025-08-02T05:02:46.236] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-02T05:02:46.238] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-02T05:02:46.240] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-02T20:40:55.018] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-02T20:40:55.027] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-02T20:40:55.034] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-03T03:29:46.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-03 03:29:46 +[2025-08-03T05:15:10.052] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-03T05:15:10.054] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-03T05:15:10.056] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-03T20:45:48.209] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-03T20:45:48.215] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-03T20:45:48.217] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-04T03:29:47.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-04 03:29:47 +[2025-08-04T05:04:59.892] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-04T05:04:59.894] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-04T05:04:59.896] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-04T20:45:39.080] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-04T20:45:39.094] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-04T20:45:39.096] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-05T03:29:48.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-05 03:29:48 +[2025-08-05T05:12:22.386] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-05T05:12:22.388] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-05T05:12:22.390] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-05T20:40:29.273] [INFO] monitorLogs - turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-05T20:40:29.294] [INFO] monitorLogs - turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-05T20:40:29.296] [INFO] monitorLogs - turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-06T03:29:49.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-06 03:29:49 +[2025-08-06T05:09:43.009] [INFO] monitorLogs - turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-06T05:09:43.011] [INFO] monitorLogs - turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-06T05:09:43.013] [INFO] monitorLogs - turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-06T14:13:54.088] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-08-06T14:13:59.445] [INFO] monitorLogs - buildTasks - params undefined +[2025-08-06T14:13:59.449] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-08-06T14:13:59.450] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-08-06T14:13:59.451] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-08-06T14:13:59.455] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-08-06T14:13:59.457] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-08-07T04:02:00.456Z +[2025-08-06T14:13:59.458] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-08-06T18:53:00.458Z +[2025-08-06T14:13:59.459] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '6:2', name: 'luxOff' }, + { value: 1, start_time: '20:53', name: 'luxOn' } +] +[2025-08-06T14:13:59.460] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-08-06T14:13:59.461] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-08-06T14:13:59.461] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-08-06T14:13:59.464] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-08-06T14:13:59.464] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-08-07T04:02:00.464Z +[2025-08-06T14:13:59.465] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-08-06T18:53:00.465Z +[2025-08-06T14:13:59.466] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '6:2', name: 'luxOff' }, + { value: 1, start_time: '20:53', name: 'luxOn' } +] +[2025-08-06T14:13:59.467] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-08-06T14:13:59.468] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-08-06T14:13:59.468] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-08-06T14:13:59.470] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-08-06T14:13:59.471] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-08-07T04:02:00.471Z +[2025-08-06T14:13:59.472] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-08-06T18:53:00.472Z +[2025-08-06T14:13:59.472] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '6:2', name: 'luxOff' }, + { value: 1, start_time: '20:53', name: 'luxOn' } +] +[2025-08-06T14:13:59.473] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-08-06T14:13:59.495] [INFO] monitorLogs - tasks created: 854 +[2025-08-06T14:13:59.498] [INFO] monitorLogs - -->FLOW bol spustený d5xjWYMwEJon6rLlK7yEaP7qgV4DaOeNB9ZX3Gzb 2025-08-08 +[2025-08-06T14:14:04.505] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-06T20:40:34.517] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-06T20:40:34.532] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-06T20:40:34.534] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-07T03:14:01.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-07 03:14:01 +[2025-08-07T05:12:19.353] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-07T05:12:19.356] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-07T05:12:19.358] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-07T07:52:45.277] [INFO] monitorLogs - turnLine on - (line, SETTINGS.maintenance_mode) 0 true command received from platform +[2025-08-07T07:52:52.904] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false command received from platform +[2025-08-07T07:53:17.854] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false command received from platform +[2025-08-07T07:53:24.897] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false command received from platform +[2025-08-07T16:34:44.148] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-08-07T16:34:49.515] [INFO] monitorLogs - buildTasks - params undefined +[2025-08-07T16:34:49.520] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-08-07T16:34:49.521] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-08-07T16:34:49.522] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-08-07T16:34:49.526] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-08-07T16:34:49.527] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-08-08T04:03:00.526Z +[2025-08-07T16:34:49.529] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-08-07T18:51:00.528Z +[2025-08-07T16:34:49.529] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '6:3', name: 'luxOff' }, + { value: 1, start_time: '20:51', name: 'luxOn' } +] +[2025-08-07T16:34:49.530] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-08-07T16:34:49.531] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-08-07T16:34:49.532] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-08-07T16:34:49.534] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-08-07T16:34:49.535] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-08-08T04:03:00.535Z +[2025-08-07T16:34:49.536] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-08-07T18:51:00.536Z +[2025-08-07T16:34:49.536] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '6:3', name: 'luxOff' }, + { value: 1, start_time: '20:51', name: 'luxOn' } +] +[2025-08-07T16:34:49.538] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-08-07T16:34:49.538] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-08-07T16:34:49.539] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-08-07T16:34:49.541] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-08-07T16:34:49.542] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-08-08T04:03:00.541Z +[2025-08-07T16:34:49.542] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-08-07T18:51:00.542Z +[2025-08-07T16:34:49.543] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '6:3', name: 'luxOff' }, + { value: 1, start_time: '20:51', name: 'luxOn' } +] +[2025-08-07T16:34:49.544] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-08-07T16:34:49.568] [INFO] monitorLogs - tasks created: 854 +[2025-08-07T16:34:49.571] [INFO] monitorLogs - -->FLOW bol spustený d5xjWYMwEJon6rLlK7yEaP7qgV4DaOeNB9ZX3Gzb 2025-08-08 +[2025-08-07T16:34:54.579] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-08-07T20:38:25.169] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-07T20:38:25.176] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-07T20:38:25.179] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-08T03:34:52.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-08 03:34:52 +[2025-08-08T05:12:41.723] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-08T05:12:41.725] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-08T05:12:41.728] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-08T20:38:18.100] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-08T20:38:18.113] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-08T20:38:18.115] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-09T03:34:53.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-09 03:34:53 +[2025-08-09T05:12:34.004] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-09T05:12:34.007] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-09T05:12:34.009] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-09T20:38:10.377] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-09T20:38:10.405] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-09T20:38:10.407] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-10T03:34:54.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-10 03:34:54 +[2025-08-10T05:12:25.207] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-10T05:12:25.209] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-10T05:12:25.212] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-10T20:35:30.629] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-10T20:35:30.647] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-10T20:35:30.649] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-11T03:34:55.018] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-11 03:34:55 +[2025-08-11T05:14:46.527] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-11T05:14:46.530] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-11T05:14:46.532] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-11T20:35:21.743] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-11T20:35:21.747] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-11T20:35:21.748] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-12T03:34:57.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-12 03:34:57 +[2025-08-12T05:14:38.619] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-12T05:14:38.621] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-12T05:14:38.623] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-12T20:32:43.283] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-12T20:32:43.290] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-12T20:32:43.292] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-13T03:34:58.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-13 03:34:58 +[2025-08-13T05:17:00.043] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-13T05:17:00.046] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-13T05:17:00.048] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-13T07:16:12.623] [INFO] monitorLogs - turnLine on - (line, SETTINGS.maintenance_mode) 0 true command received from platform +[2025-08-13T07:26:41.721] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false command received from platform +[2025-08-13T20:28:48.214] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-13T20:28:48.221] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-13T20:28:48.223] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-14T03:34:59.013] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-14 03:34:59 +[2025-08-14T05:20:36.675] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-14T05:20:36.677] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-14T05:20:36.679] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-14T20:28:39.905] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-14T20:28:39.912] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-14T20:28:39.914] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-15T03:35:00.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-15 03:35:00 +[2025-08-15T05:22:59.176] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-15T05:22:59.178] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-15T05:22:59.180] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-15T20:26:01.545] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-15T20:26:01.554] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-15T20:26:01.556] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-16T03:35:01.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-16 03:35:01 +[2025-08-16T05:22:50.972] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-16T05:22:50.974] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-16T05:22:50.976] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-16T20:23:22.183] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-16T20:23:22.190] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-16T20:23:22.192] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-17T03:35:03.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-17 03:35:03 +[2025-08-17T05:27:43.847] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-17T05:27:43.849] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-17T05:27:43.851] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-17T20:23:14.253] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-17T20:23:14.261] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-17T20:23:14.263] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-18T03:35:04.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-18 03:35:04 +[2025-08-18T05:25:05.487] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-18T05:25:05.489] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-18T05:25:05.491] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-18T06:25:05.002] [INFO] monitorLogs - Thermometer is not responding Error: Command failed: owread -C 28.A6A2660E0000/temperature +ServerRead: Data error on 28.A6A2660E0000/temperature + + at ChildProcess.exithandler (child_process.js:383:12) + at ChildProcess.emit (events.js:400:28) + at maybeClose (internal/child_process.js:1058:16) + at Socket. (internal/child_process.js:443:11) + at Socket.emit (events.js:400:28) + at Pipe. (net.js:686:12) { + killed: false, + code: 1, + signal: null, + cmd: 'owread -C 28.A6A2660E0000/temperature' +} +[2025-08-18T20:23:06.972] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-18T20:23:06.982] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-18T20:23:06.984] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-19T03:35:05.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-19 03:35:05 +[2025-08-19T05:24:57.476] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-19T05:24:57.478] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-19T05:24:57.480] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-19T20:20:27.806] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-19T20:20:27.834] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-19T20:20:27.836] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-20T03:35:06.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-20 03:35:06 +[2025-08-20T05:27:20.050] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-20T05:27:20.052] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-20T05:27:20.054] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-20T20:15:19.297] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-20T20:15:19.303] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-20T20:15:19.305] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-21T03:35:07.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-21 03:35:07 +[2025-08-21T05:37:14.031] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-21T05:37:14.033] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-21T05:37:14.035] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-21T20:00:07.589] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-21T20:00:07.613] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-21T20:00:07.615] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-22T03:35:08.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-22 03:35:08 +[2025-08-22T05:42:06.086] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-22T05:42:06.088] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-22T05:42:06.090] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-22T20:12:31.234] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-22T20:12:31.242] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-22T20:12:31.244] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-23T03:35:09.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-23 03:35:09 +[2025-08-23T05:36:56.164] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-23T05:36:56.167] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-23T05:36:56.168] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-23T20:09:51.806] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-23T20:09:51.809] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-23T20:09:51.811] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-24T03:35:10.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-24 03:35:10 +[2025-08-24T05:34:16.519] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-24T05:34:16.522] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-24T05:34:16.525] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-24T20:09:43.845] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-24T20:09:43.852] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-24T20:09:43.855] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-25T03:35:11.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-25 03:35:11 +[2025-08-25T05:39:09.881] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-25T05:39:09.883] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-25T05:39:09.885] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-25T20:07:04.367] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-25T20:07:04.382] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-25T20:07:04.384] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-26T03:35:12.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-26 03:35:12 +[2025-08-26T05:39:01.299] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-26T05:39:01.302] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-26T05:39:01.303] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-26T20:04:25.674] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-26T20:04:25.681] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-26T20:04:25.683] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-27T03:35:14.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-27 03:35:14 +[2025-08-27T05:38:53.607] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-27T05:38:53.609] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-27T05:38:53.611] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-27T20:01:47.177] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-27T20:01:47.214] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-27T20:01:47.216] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-28T03:35:15.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-28 03:35:15 +[2025-08-28T05:38:44.653] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-28T05:38:44.656] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-28T05:38:44.658] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-28T19:59:07.919] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-28T19:59:07.926] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-28T19:59:07.928] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-29T03:35:16.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-29 03:35:16 +[2025-08-29T05:43:36.760] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-29T05:43:36.762] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-29T05:43:36.764] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-29T19:48:56.533] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-29T19:48:56.558] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-29T19:48:56.560] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-30T03:35:17.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-30 03:35:17 +[2025-08-30T05:40:57.162] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-30T05:40:57.164] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-30T05:40:57.167] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-30T19:43:47.550] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-30T19:43:47.563] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-30T19:43:47.565] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-08-31T03:35:18.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-08-31 03:35:18 +[2025-08-31T06:00:53.016] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-08-31T06:00:53.018] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-08-31T06:00:53.020] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-08-31T19:56:11.126] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-08-31T19:56:11.132] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-08-31T19:56:11.134] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-01T03:35:19.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-01 03:35:19 +[2025-09-01T05:50:42.383] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-01T05:50:42.386] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-01T05:50:42.387] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-01T19:51:01.952] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-01T19:51:01.958] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-01T19:51:01.960] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-02T03:35:20.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-02 03:35:20 +[2025-09-02T05:45:32.982] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-02T05:45:32.985] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-02T05:45:32.987] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-02T19:43:22.537] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-02T19:43:22.579] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-02T19:43:22.581] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-03T03:35:22.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-03 03:35:22 +[2025-09-03T05:55:28.352] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-03T05:55:28.354] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-03T05:55:28.356] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-03T19:48:16.494] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-03T19:48:16.503] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-03T19:48:16.505] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-04T03:35:23.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-04 03:35:23 +[2025-09-04T05:50:19.409] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-04T05:50:19.412] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-04T05:50:19.414] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-04T19:47:01.005] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-04T19:47:01.008] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-04T19:47:01.010] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-05T03:35:24.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-05 03:35:24 +[2025-09-05T05:54:04.735] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-05T05:54:04.737] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-05T05:54:04.739] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-05T19:44:21.851] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-05T19:44:21.870] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-05T19:44:21.872] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-06T03:35:25.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-06 03:35:25 +[2025-09-06T06:11:29.235] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-06T06:11:29.238] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-06T06:11:29.240] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-06T11:16:33.153] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-09-06T11:16:38.511] [INFO] monitorLogs - buildTasks - params undefined +[2025-09-06T11:16:38.516] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-09-06T11:16:38.517] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-09-06T11:16:38.517] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-09-06T11:16:38.522] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-06T11:16:38.523] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-09-07T04:46:00.522Z +[2025-09-06T11:16:38.525] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-09-06T17:55:00.524Z +[2025-09-06T11:16:38.525] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '6:46', name: 'luxOff' }, + { value: 1, start_time: '19:55', name: 'luxOn' } +] +[2025-09-06T11:16:38.527] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-09-06T11:16:38.527] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-09-06T11:16:38.528] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-09-06T11:16:38.530] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-06T11:16:38.531] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-09-07T04:46:00.531Z +[2025-09-06T11:16:38.532] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-09-06T17:55:00.532Z +[2025-09-06T11:16:38.533] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '6:46', name: 'luxOff' }, + { value: 1, start_time: '19:55', name: 'luxOn' } +] +[2025-09-06T11:16:38.534] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-09-06T11:16:38.535] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-09-06T11:16:38.535] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-09-06T11:16:38.537] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-06T11:16:38.538] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-09-07T04:46:00.538Z +[2025-09-06T11:16:38.539] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-09-06T17:55:00.539Z +[2025-09-06T11:16:38.539] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '6:46', name: 'luxOff' }, + { value: 1, start_time: '19:55', name: 'luxOn' } +] +[2025-09-06T11:16:38.540] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-09-06T11:16:38.563] [INFO] monitorLogs - tasks created: 854 +[2025-09-06T11:16:38.565] [INFO] monitorLogs - -->FLOW bol spustený d5xjWYMwEJon6rLlK7yEaP7qgV4DaOeNB9ZX3Gzb 2025-08-08 +[2025-09-06T11:16:43.574] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-06T18:04:32.213] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-09-06T18:04:37.569] [INFO] monitorLogs - buildTasks - params undefined +[2025-09-06T18:04:37.573] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-09-06T18:04:37.574] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-09-06T18:04:37.575] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-09-06T18:04:37.579] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-06T18:04:37.580] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-09-07T04:46:00.579Z +[2025-09-06T18:04:37.582] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-09-06T17:55:00.581Z +[2025-09-06T18:04:37.582] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '6:46', name: 'luxOff' }, + { value: 1, start_time: '19:55', name: 'luxOn' } +] +[2025-09-06T18:04:37.584] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-09-06T18:04:37.584] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-09-06T18:04:37.585] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-09-06T18:04:37.587] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-06T18:04:37.588] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-09-07T04:46:00.588Z +[2025-09-06T18:04:37.589] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-09-06T17:55:00.589Z +[2025-09-06T18:04:37.590] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '6:46', name: 'luxOff' }, + { value: 1, start_time: '19:55', name: 'luxOn' } +] +[2025-09-06T18:04:37.591] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-09-06T18:04:37.591] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-09-06T18:04:37.592] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-09-06T18:04:37.594] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-06T18:04:37.595] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-09-07T04:46:00.595Z +[2025-09-06T18:04:37.596] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-09-06T17:55:00.595Z +[2025-09-06T18:04:37.596] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '6:46', name: 'luxOff' }, + { value: 1, start_time: '19:55', name: 'luxOn' } +] +[2025-09-06T18:04:37.597] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-09-06T18:04:37.599] [INFO] monitorLogs - tasks created: 134 +[2025-09-06T18:04:37.601] [INFO] monitorLogs - -->FLOW bol spustený d5xjWYMwEJon6rLlK7yEaP7qgV4DaOeNB9ZX3Gzb 2025-08-08 +[2025-09-06T18:04:42.604] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-06T19:42:43.390] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-06T19:42:43.393] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-06T19:42:43.395] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-07T03:04:40.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-07 03:04:40 +[2025-09-07T05:52:19.650] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-07T05:52:19.654] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-07T05:52:19.655] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-07T19:40:06.678] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-07T19:40:06.704] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-07T19:40:06.707] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-07T23:39:10.675] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-09-07T23:39:16.042] [INFO] monitorLogs - buildTasks - params undefined +[2025-09-07T23:39:16.046] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-09-07T23:39:16.047] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-09-07T23:39:16.048] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-09-07T23:39:16.052] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-07T23:39:16.053] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-09-08T04:47:00.053Z +[2025-09-07T23:39:16.055] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-09-08T17:53:00.055Z +[2025-09-07T23:39:16.055] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '6:47', name: 'luxOff' }, + { value: 1, start_time: '19:53', name: 'luxOn' } +] +[2025-09-07T23:39:16.057] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-09-07T23:39:16.057] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-09-07T23:39:16.058] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-09-07T23:39:16.060] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-07T23:39:16.061] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-09-08T04:47:00.061Z +[2025-09-07T23:39:16.062] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-09-08T17:53:00.062Z +[2025-09-07T23:39:16.063] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '6:47', name: 'luxOff' }, + { value: 1, start_time: '19:53', name: 'luxOn' } +] +[2025-09-07T23:39:16.064] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-09-07T23:39:16.064] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-09-07T23:39:16.065] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-09-07T23:39:16.067] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-07T23:39:16.068] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-09-08T04:47:00.068Z +[2025-09-07T23:39:16.069] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-09-08T17:53:00.068Z +[2025-09-07T23:39:16.069] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '6:47', name: 'luxOff' }, + { value: 1, start_time: '19:53', name: 'luxOn' } +] +[2025-09-07T23:39:16.070] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-09-07T23:39:16.072] [INFO] monitorLogs - tasks created: 134 +[2025-09-07T23:39:16.074] [INFO] monitorLogs - -->FLOW bol spustený d5xjWYMwEJon6rLlK7yEaP7qgV4DaOeNB9ZX3Gzb 2025-08-08 +[2025-09-07T23:39:21.077] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-08T03:39:18.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-08 03:39:18 +[2025-09-08T05:55:50.247] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-08T05:55:50.250] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-08T05:55:50.259] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-08T16:00:23.134] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-09-08T16:00:28.507] [INFO] monitorLogs - buildTasks - params undefined +[2025-09-08T16:00:28.511] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-09-08T16:00:28.513] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-09-08T16:00:28.513] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-09-08T16:00:28.517] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-08T16:00:28.519] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-09-09T04:48:00.518Z +[2025-09-08T16:00:28.520] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-09-08T17:51:00.520Z +[2025-09-08T16:00:28.521] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '6:48', name: 'luxOff' }, + { value: 1, start_time: '19:51', name: 'luxOn' } +] +[2025-09-08T16:00:28.523] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-09-08T16:00:28.524] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-09-08T16:00:28.524] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-09-08T16:00:28.527] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-08T16:00:28.527] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-09-09T04:48:00.527Z +[2025-09-08T16:00:28.528] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-09-08T17:51:00.528Z +[2025-09-08T16:00:28.529] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '6:48', name: 'luxOff' }, + { value: 1, start_time: '19:51', name: 'luxOn' } +] +[2025-09-08T16:00:28.530] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-09-08T16:00:28.531] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-09-08T16:00:28.531] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-09-08T16:00:28.534] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-08T16:00:28.534] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-09-09T04:48:00.534Z +[2025-09-08T16:00:28.535] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-09-08T17:51:00.535Z +[2025-09-08T16:00:28.536] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '6:48', name: 'luxOff' }, + { value: 1, start_time: '19:51', name: 'luxOn' } +] +[2025-09-08T16:00:28.537] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-09-08T16:00:28.558] [INFO] monitorLogs - tasks created: 854 +[2025-09-08T16:00:28.560] [INFO] monitorLogs - -->FLOW bol spustený d5xjWYMwEJon6rLlK7yEaP7qgV4DaOeNB9ZX3Gzb 2025-08-08 +[2025-09-08T16:00:33.567] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-08T19:38:59.032] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-08T19:38:59.038] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-08T19:38:59.041] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-09T03:00:30.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-09 03:00:30 +[2025-09-09T05:58:35.903] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-09T05:58:35.906] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-09T05:58:35.908] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-09T19:31:20.074] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-09T19:31:20.080] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-09T19:31:20.082] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-10T03:00:31.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-10 03:00:31 +[2025-09-10T06:03:29.399] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-10T06:03:29.401] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-10T06:03:29.403] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-10T09:12:45.345] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-09-10T09:12:50.694] [INFO] monitorLogs - buildTasks - params undefined +[2025-09-10T09:12:50.699] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-09-10T09:12:50.700] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-09-10T09:12:50.700] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-09-10T09:12:50.704] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-10T09:12:50.706] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-09-11T04:51:00.705Z +[2025-09-10T09:12:50.707] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-09-10T17:46:00.707Z +[2025-09-10T09:12:50.708] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '6:51', name: 'luxOff' }, + { value: 1, start_time: '19:46', name: 'luxOn' } +] +[2025-09-10T09:12:50.709] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-09-10T09:12:50.710] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-09-10T09:12:50.710] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-09-10T09:12:50.713] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-10T09:12:50.713] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-09-11T04:51:00.713Z +[2025-09-10T09:12:50.714] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-09-10T17:46:00.714Z +[2025-09-10T09:12:50.715] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '6:51', name: 'luxOff' }, + { value: 1, start_time: '19:46', name: 'luxOn' } +] +[2025-09-10T09:12:50.716] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-09-10T09:12:50.717] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-09-10T09:12:50.717] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-09-10T09:12:50.720] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-10T09:12:50.720] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-09-11T04:51:00.720Z +[2025-09-10T09:12:50.721] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-09-10T17:46:00.721Z +[2025-09-10T09:12:50.722] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '6:51', name: 'luxOff' }, + { value: 1, start_time: '19:46', name: 'luxOn' } +] +[2025-09-10T09:12:50.723] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-09-10T09:12:50.743] [INFO] monitorLogs - tasks created: 854 +[2025-09-10T09:12:50.746] [INFO] monitorLogs - -->FLOW bol spustený d5xjWYMwEJon6rLlK7yEaP7qgV4DaOeNB9ZX3Gzb 2025-08-08 +[2025-09-10T09:12:55.753] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-10T16:25:28.255] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-09-10T16:25:33.618] [INFO] monitorLogs - buildTasks - params undefined +[2025-09-10T16:25:33.622] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-09-10T16:25:33.623] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-09-10T16:25:33.624] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-09-10T16:25:33.628] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-10T16:25:33.630] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-09-11T04:51:00.629Z +[2025-09-10T16:25:33.631] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-09-10T17:46:00.631Z +[2025-09-10T16:25:33.632] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '6:51', name: 'luxOff' }, + { value: 1, start_time: '19:46', name: 'luxOn' } +] +[2025-09-10T16:25:33.633] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-09-10T16:25:33.634] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-09-10T16:25:33.634] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-09-10T16:25:33.637] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-10T16:25:33.637] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-09-11T04:51:00.637Z +[2025-09-10T16:25:33.638] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-09-10T17:46:00.638Z +[2025-09-10T16:25:33.639] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '6:51', name: 'luxOff' }, + { value: 1, start_time: '19:46', name: 'luxOn' } +] +[2025-09-10T16:25:33.640] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-09-10T16:25:33.641] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-09-10T16:25:33.641] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-09-10T16:25:33.643] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-10T16:25:33.644] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-09-11T04:51:00.644Z +[2025-09-10T16:25:33.645] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-09-10T17:46:00.645Z +[2025-09-10T16:25:33.646] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '6:51', name: 'luxOff' }, + { value: 1, start_time: '19:46', name: 'luxOn' } +] +[2025-09-10T16:25:33.647] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-09-10T16:25:33.669] [INFO] monitorLogs - tasks created: 854 +[2025-09-10T16:25:33.672] [INFO] monitorLogs - -->FLOW bol spustený d5xjWYMwEJon6rLlK7yEaP7qgV4DaOeNB9ZX3Gzb 2025-08-08 +[2025-09-10T16:25:38.679] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-10T19:18:54.964] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-10T19:18:54.970] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-10T19:18:54.973] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-11T03:25:35.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-11 03:25:35 +[2025-09-11T06:11:08.574] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-11T06:11:08.576] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-11T06:11:08.578] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-11T19:31:19.589] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-11T19:31:19.606] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-11T19:31:19.608] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-12T03:25:36.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-12 03:25:36 +[2025-09-12T06:03:28.747] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-12T06:03:28.750] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-12T06:03:28.752] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-12T19:21:09.896] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-12T19:21:09.908] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-12T19:21:09.911] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-13T03:25:37.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-13 03:25:37 +[2025-09-13T06:18:23.692] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-13T06:18:23.694] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-13T06:18:23.696] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-13T19:21:01.988] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-13T19:21:02.013] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-13T19:21:02.015] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-14T03:25:39.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-14 03:25:39 +[2025-09-14T06:20:47.291] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-14T06:20:47.293] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-14T06:20:47.295] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-14T19:23:24.729] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-14T19:23:24.739] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-14T19:23:24.741] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-14T22:44:07.703] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-09-14T22:44:13.066] [INFO] monitorLogs - buildTasks - params undefined +[2025-09-14T22:44:13.071] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-09-14T22:44:13.072] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-09-14T22:44:13.072] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-09-14T22:44:13.076] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-14T22:44:13.078] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-09-15T04:57:00.077Z +[2025-09-14T22:44:13.079] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-09-15T17:38:00.079Z +[2025-09-14T22:44:13.080] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '6:57', name: 'luxOff' }, + { value: 1, start_time: '19:38', name: 'luxOn' } +] +[2025-09-14T22:44:13.081] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-09-14T22:44:13.082] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-09-14T22:44:13.082] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-09-14T22:44:13.085] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-14T22:44:13.086] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-09-15T04:57:00.085Z +[2025-09-14T22:44:13.086] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-09-15T17:38:00.086Z +[2025-09-14T22:44:13.087] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '6:57', name: 'luxOff' }, + { value: 1, start_time: '19:38', name: 'luxOn' } +] +[2025-09-14T22:44:13.088] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-09-14T22:44:13.089] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-09-14T22:44:13.089] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-09-14T22:44:13.092] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-14T22:44:13.092] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-09-15T04:57:00.092Z +[2025-09-14T22:44:13.093] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-09-15T17:38:00.093Z +[2025-09-14T22:44:13.094] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '6:57', name: 'luxOff' }, + { value: 1, start_time: '19:38', name: 'luxOn' } +] +[2025-09-14T22:44:13.095] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-09-14T22:44:13.116] [INFO] monitorLogs - tasks created: 854 +[2025-09-14T22:44:13.119] [INFO] monitorLogs - -->FLOW bol spustený d5xjWYMwEJon6rLlK7yEaP7qgV4DaOeNB9ZX3Gzb 2025-08-08 +[2025-09-14T22:44:18.125] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-15T03:44:14.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-15 03:44:14 +[2025-09-15T06:05:59.526] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-15T06:05:59.528] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-15T06:05:59.530] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-15T19:23:40.430] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-15T19:23:40.435] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-15T19:23:40.436] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-16T03:44:15.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-16 03:44:15 +[2025-09-16T06:25:55.814] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-16T06:25:55.817] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-16T06:25:55.818] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-16T19:18:32.082] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-16T19:18:32.088] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-16T19:18:32.090] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-17T03:44:16.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-17 03:44:16 +[2025-09-17T06:15:46.144] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-17T06:15:46.146] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-17T06:15:46.148] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-17T19:20:58.200] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-17T19:20:58.207] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-17T19:20:58.209] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-17T20:31:23.726] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-09-17T20:31:29.093] [INFO] monitorLogs - buildTasks - params undefined +[2025-09-17T20:31:29.098] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-09-17T20:31:29.099] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-09-17T20:31:29.099] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-09-17T20:31:29.103] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-17T20:31:29.105] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-09-18T05:01:00.104Z +[2025-09-17T20:31:29.106] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-09-18T17:32:00.106Z +[2025-09-17T20:31:29.107] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:1', name: 'luxOff' }, + { value: 1, start_time: '19:32', name: 'luxOn' } +] +[2025-09-17T20:31:29.108] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-09-17T20:31:29.109] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-09-17T20:31:29.110] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-09-17T20:31:29.113] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-17T20:31:29.114] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-09-18T05:01:00.113Z +[2025-09-17T20:31:29.115] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-09-18T17:32:00.114Z +[2025-09-17T20:31:29.115] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:1', name: 'luxOff' }, + { value: 1, start_time: '19:32', name: 'luxOn' } +] +[2025-09-17T20:31:29.116] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-09-17T20:31:29.117] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-09-17T20:31:29.117] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-09-17T20:31:29.120] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-17T20:31:29.120] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-09-18T05:01:00.120Z +[2025-09-17T20:31:29.121] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-09-18T17:32:00.121Z +[2025-09-17T20:31:29.122] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:1', name: 'luxOff' }, + { value: 1, start_time: '19:32', name: 'luxOn' } +] +[2025-09-17T20:31:29.123] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-09-17T20:31:29.143] [INFO] monitorLogs - tasks created: 854 +[2025-09-17T20:31:29.146] [INFO] monitorLogs - -->FLOW bol spustený d5xjWYMwEJon6rLlK7yEaP7qgV4DaOeNB9ZX3Gzb 2025-08-08 +[2025-09-17T20:31:34.153] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-18T03:31:30.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-18 03:31:30 +[2025-09-18T06:16:14.519] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-18T06:16:14.522] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-18T06:16:14.524] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-18T19:18:52.897] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-18T19:18:52.903] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-18T19:18:52.905] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-19T03:31:32.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-19 03:31:32 +[2025-09-19T06:08:36.343] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-19T06:08:36.346] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-19T06:08:36.347] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-19T11:10:53.706] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-09-19T11:10:59.074] [INFO] monitorLogs - buildTasks - params undefined +[2025-09-19T11:10:59.078] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-09-19T11:10:59.079] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-09-19T11:10:59.080] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-09-19T11:10:59.084] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-19T11:10:59.086] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-09-20T05:04:00.085Z +[2025-09-19T11:10:59.087] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-09-19T17:27:00.087Z +[2025-09-19T11:10:59.088] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:4', name: 'luxOff' }, + { value: 1, start_time: '19:27', name: 'luxOn' } +] +[2025-09-19T11:10:59.089] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-09-19T11:10:59.090] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-09-19T11:10:59.090] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-09-19T11:10:59.093] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-19T11:10:59.093] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-09-20T05:04:00.093Z +[2025-09-19T11:10:59.094] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-09-19T17:27:00.094Z +[2025-09-19T11:10:59.095] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:4', name: 'luxOff' }, + { value: 1, start_time: '19:27', name: 'luxOn' } +] +[2025-09-19T11:10:59.096] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-09-19T11:10:59.097] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-09-19T11:10:59.097] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-09-19T11:10:59.099] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-19T11:10:59.100] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-09-20T05:04:00.100Z +[2025-09-19T11:10:59.101] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-09-19T17:27:00.101Z +[2025-09-19T11:10:59.101] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:4', name: 'luxOff' }, + { value: 1, start_time: '19:27', name: 'luxOn' } +] +[2025-09-19T11:10:59.102] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-09-19T11:10:59.126] [INFO] monitorLogs - tasks created: 854 +[2025-09-19T11:10:59.128] [INFO] monitorLogs - -->FLOW bol spustený d5xjWYMwEJon6rLlK7yEaP7qgV4DaOeNB9ZX3Gzb 2025-08-08 +[2025-09-19T11:11:04.136] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-19T19:15:23.843] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-19T19:15:23.852] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-19T19:15:23.854] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-20T03:11:00.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-20 03:11:00 +[2025-09-20T06:10:06.696] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-20T06:10:06.699] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-20T06:10:06.701] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-20T19:12:44.240] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-20T19:12:44.244] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-20T19:12:44.246] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-21T01:29:25.051] [INFO] monitorLogs - MQTT client error Error: connect ECONNREFUSED 192.168.252.1:1883 + at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1159:16) { + errno: -111, + code: 'ECONNREFUSED', + syscall: 'connect', + address: '192.168.252.1', + port: 1883 +} +[2025-09-21T03:11:01.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-21 03:11:01 +[2025-09-21T06:12:29.203] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-21T06:12:29.207] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-21T06:12:29.209] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-21T18:05:03.577] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-09-21T18:05:08.923] [INFO] monitorLogs - buildTasks - params undefined +[2025-09-21T18:05:08.928] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-09-21T18:05:08.929] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-09-21T18:05:08.930] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-09-21T18:05:08.934] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-21T18:05:08.935] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-09-22T05:07:00.935Z +[2025-09-21T18:05:08.937] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-09-21T17:23:00.937Z +[2025-09-21T18:05:08.937] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:7', name: 'luxOff' }, + { value: 1, start_time: '19:23', name: 'luxOn' } +] +[2025-09-21T18:05:08.939] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-09-21T18:05:08.940] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-09-21T18:05:08.940] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-09-21T18:05:08.943] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-21T18:05:08.943] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-09-22T05:07:00.943Z +[2025-09-21T18:05:08.944] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-09-21T17:23:00.944Z +[2025-09-21T18:05:08.945] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:7', name: 'luxOff' }, + { value: 1, start_time: '19:23', name: 'luxOn' } +] +[2025-09-21T18:05:08.946] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-09-21T18:05:08.947] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-09-21T18:05:08.947] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-09-21T18:05:08.949] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-21T18:05:08.950] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-09-22T05:07:00.950Z +[2025-09-21T18:05:08.951] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-09-21T17:23:00.951Z +[2025-09-21T18:05:08.951] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:7', name: 'luxOff' }, + { value: 1, start_time: '19:23', name: 'luxOn' } +] +[2025-09-21T18:05:08.952] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-09-21T18:05:08.976] [INFO] monitorLogs - tasks created: 854 +[2025-09-21T18:05:08.978] [INFO] monitorLogs - -->FLOW bol spustený d5xjWYMwEJon6rLlK7yEaP7qgV4DaOeNB9ZX3Gzb 2025-08-08 +[2025-09-21T18:05:13.985] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-21T19:08:07.493] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-21T19:08:07.501] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-21T19:08:07.504] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-22T03:05:11.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-22 03:05:11 +[2025-09-22T06:12:54.501] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-22T06:12:54.503] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-22T06:12:54.506] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-22T19:05:30.914] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-22T19:05:30.925] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-22T19:05:30.928] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-23T03:05:12.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-23 03:05:12 +[2025-09-23T06:22:48.776] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-23T06:22:48.779] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-23T06:22:48.781] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-23T12:59:48.161] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-09-23T12:59:53.531] [INFO] monitorLogs - buildTasks - params undefined +[2025-09-23T12:59:53.535] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-09-23T12:59:53.536] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-09-23T12:59:53.537] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-09-23T12:59:53.541] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-23T12:59:53.543] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-09-24T05:09:00.542Z +[2025-09-23T12:59:53.544] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-09-23T17:19:00.544Z +[2025-09-23T12:59:53.545] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:9', name: 'luxOff' }, + { value: 1, start_time: '19:19', name: 'luxOn' } +] +[2025-09-23T12:59:53.546] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-09-23T12:59:53.547] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-09-23T12:59:53.547] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-09-23T12:59:53.550] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-23T12:59:53.550] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-09-24T05:09:00.550Z +[2025-09-23T12:59:53.551] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-09-23T17:19:00.551Z +[2025-09-23T12:59:53.552] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:9', name: 'luxOff' }, + { value: 1, start_time: '19:19', name: 'luxOn' } +] +[2025-09-23T12:59:53.553] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-09-23T12:59:53.554] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-09-23T12:59:53.554] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-09-23T12:59:53.556] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-23T12:59:53.557] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-09-24T05:09:00.557Z +[2025-09-23T12:59:53.558] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-09-23T17:19:00.558Z +[2025-09-23T12:59:53.558] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:9', name: 'luxOff' }, + { value: 1, start_time: '19:19', name: 'luxOn' } +] +[2025-09-23T12:59:53.559] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-09-23T12:59:53.582] [INFO] monitorLogs - tasks created: 854 +[2025-09-23T12:59:53.585] [INFO] monitorLogs - -->FLOW bol spustený d5xjWYMwEJon6rLlK7yEaP7qgV4DaOeNB9ZX3Gzb 2025-08-08 +[2025-09-23T12:59:58.592] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-23T14:26:20.584] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-09-23T14:26:25.955] [INFO] monitorLogs - buildTasks - params undefined +[2025-09-23T14:26:25.960] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-09-23T14:26:25.961] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-09-23T14:26:25.962] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-09-23T14:26:25.966] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-23T14:26:25.967] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-09-24T05:09:00.966Z +[2025-09-23T14:26:25.968] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-09-23T17:19:00.968Z +[2025-09-23T14:26:25.969] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:9', name: 'luxOff' }, + { value: 1, start_time: '19:19', name: 'luxOn' } +] +[2025-09-23T14:26:25.970] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-09-23T14:26:25.971] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-09-23T14:26:25.972] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-09-23T14:26:25.975] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-23T14:26:25.976] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-09-24T05:09:00.976Z +[2025-09-23T14:26:25.977] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-09-23T17:19:00.977Z +[2025-09-23T14:26:25.978] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:9', name: 'luxOff' }, + { value: 1, start_time: '19:19', name: 'luxOn' } +] +[2025-09-23T14:26:25.979] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-09-23T14:26:25.980] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-09-23T14:26:25.980] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-09-23T14:26:25.983] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-23T14:26:25.983] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-09-24T05:09:00.983Z +[2025-09-23T14:26:25.984] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-09-23T17:19:00.984Z +[2025-09-23T14:26:25.985] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:9', name: 'luxOff' }, + { value: 1, start_time: '19:19', name: 'luxOn' } +] +[2025-09-23T14:26:25.986] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-09-23T14:26:26.008] [INFO] monitorLogs - tasks created: 854 +[2025-09-23T14:26:26.011] [INFO] monitorLogs - -->FLOW bol spustený d5xjWYMwEJon6rLlK7yEaP7qgV4DaOeNB9ZX3Gzb 2025-08-08 +[2025-09-23T14:26:31.019] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-23T18:57:37.318] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-23T18:57:37.326] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-23T18:57:37.328] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-24T03:26:27.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-24 03:26:27 +[2025-09-24T06:40:00.334] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-24T06:40:00.338] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-24T06:40:00.340] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-24T18:54:58.788] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-24T18:54:58.794] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-24T18:54:58.796] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-25T03:26:28.027] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-25 03:26:28 +[2025-09-25T06:39:53.618] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-25T06:39:53.621] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-25T06:39:53.623] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-25T16:24:32.448] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-09-25T16:24:37.827] [INFO] monitorLogs - buildTasks - params undefined +[2025-09-25T16:24:37.832] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-09-25T16:24:37.833] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-09-25T16:24:37.834] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-09-25T16:24:37.838] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-25T16:24:37.840] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-09-26T05:12:00.839Z +[2025-09-25T16:24:37.841] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-09-25T17:14:00.841Z +[2025-09-25T16:24:37.842] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:12', name: 'luxOff' }, + { value: 1, start_time: '19:14', name: 'luxOn' } +] +[2025-09-25T16:24:37.843] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-09-25T16:24:37.844] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-09-25T16:24:37.844] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-09-25T16:24:37.847] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-25T16:24:37.847] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-09-26T05:12:00.847Z +[2025-09-25T16:24:37.848] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-09-25T17:14:00.848Z +[2025-09-25T16:24:37.849] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:12', name: 'luxOff' }, + { value: 1, start_time: '19:14', name: 'luxOn' } +] +[2025-09-25T16:24:37.850] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-09-25T16:24:37.851] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-09-25T16:24:37.851] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-09-25T16:24:37.853] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-09-25T16:24:37.854] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-09-26T05:12:00.854Z +[2025-09-25T16:24:37.855] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-09-25T17:14:00.855Z +[2025-09-25T16:24:37.855] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:12', name: 'luxOff' }, + { value: 1, start_time: '19:14', name: 'luxOn' } +] +[2025-09-25T16:24:37.856] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-09-25T16:24:37.878] [INFO] monitorLogs - tasks created: 854 +[2025-09-25T16:24:37.881] [INFO] monitorLogs - -->FLOW bol spustený d5xjWYMwEJon6rLlK7yEaP7qgV4DaOeNB9ZX3Gzb 2025-08-08 +[2025-09-25T16:24:42.889] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-09-25T18:50:23.490] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-25T18:50:23.496] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-25T18:50:23.499] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-26T03:24:39.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-26 03:24:39 +[2025-09-26T06:35:17.711] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-26T06:35:17.714] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-26T06:35:17.716] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-26T18:57:47.275] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-26T18:57:47.285] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-26T18:57:47.288] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-27T03:24:40.010] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-27 03:24:40 +[2025-09-27T06:32:38.603] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-27T06:32:38.605] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-27T06:32:38.607] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-27T18:57:39.315] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-27T18:57:39.320] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-27T18:57:39.322] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-28T03:24:41.007] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-28 03:24:41 +[2025-09-28T06:32:30.881] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-28T06:32:30.884] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-28T06:32:30.886] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-28T18:55:00.061] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-28T18:55:00.070] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-28T18:55:00.072] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-29T03:24:42.023] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-29 03:24:42 +[2025-09-29T06:24:50.374] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-29T06:24:50.376] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-29T06:24:50.378] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-29T18:54:51.110] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-29T18:54:51.118] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-29T18:54:51.120] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-09-30T03:24:43.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-09-30 03:24:43 +[2025-09-30T06:27:12.153] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-09-30T06:27:12.156] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-09-30T06:27:12.158] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-09-30T18:52:12.699] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-09-30T18:52:12.709] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-09-30T18:52:12.711] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-01T03:24:44.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-01 03:24:44 +[2025-10-01T06:34:35.863] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-01T06:34:35.865] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-01T06:34:35.867] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-01T18:49:33.695] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-01T18:49:33.698] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-01T18:49:33.700] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-02T03:24:45.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-02 03:24:45 +[2025-10-02T06:29:25.751] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-02T06:29:25.754] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-02T06:29:25.756] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-02T18:46:54.114] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-02T18:46:54.116] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-02T18:46:54.119] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-03T03:24:46.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-03 03:24:46 +[2025-10-03T06:31:47.834] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-03T06:31:47.837] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-03T06:31:47.839] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-03T14:40:16.680] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-03T14:40:22.039] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-03T14:40:22.044] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-03T14:40:22.045] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-03T14:40:22.046] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-10-03T14:40:22.050] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-03T14:40:22.052] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-10-04T05:24:00.051Z +[2025-10-03T14:40:22.053] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-10-03T16:58:00.053Z +[2025-10-03T14:40:22.054] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:24', name: 'luxOff' }, + { value: 1, start_time: '18:58', name: 'luxOn' } +] +[2025-10-03T14:40:22.055] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-10-03T14:40:22.056] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-03T14:40:22.056] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-10-03T14:40:22.059] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-03T14:40:22.059] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-10-04T05:24:00.059Z +[2025-10-03T14:40:22.060] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-10-03T16:58:00.060Z +[2025-10-03T14:40:22.061] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:24', name: 'luxOff' }, + { value: 1, start_time: '18:58', name: 'luxOn' } +] +[2025-10-03T14:40:22.062] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-10-03T14:40:22.063] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-03T14:40:22.063] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-10-03T14:40:22.065] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-03T14:40:22.066] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-10-04T05:24:00.066Z +[2025-10-03T14:40:22.067] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-10-03T16:58:00.067Z +[2025-10-03T14:40:22.067] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:24', name: 'luxOff' }, + { value: 1, start_time: '18:58', name: 'luxOn' } +] +[2025-10-03T14:40:22.068] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-10-03T14:40:22.089] [INFO] monitorLogs - tasks created: 854 +[2025-10-03T14:40:22.092] [INFO] monitorLogs - -->FLOW bol spustený d5xjWYMwEJon6rLlK7yEaP7qgV4DaOeNB9ZX3Gzb 2025-08-08 +[2025-10-03T14:40:27.100] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-03T18:43:57.760] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-03T18:43:57.767] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-03T18:43:57.769] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-04T03:40:23.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-04 03:40:23 +[2025-10-04T06:31:21.791] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-04T06:31:21.793] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-04T06:31:21.795] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-04T18:36:18.321] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-04T18:36:18.327] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-04T18:36:18.330] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-05T03:40:24.012] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-05 03:40:24 +[2025-10-05T06:38:45.474] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-05T06:38:45.476] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-05T06:38:45.478] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-05T18:38:40.544] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-05T18:38:40.547] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-05T18:38:40.549] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-06T03:40:25.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-06 03:40:25 +[2025-10-06T06:46:08.031] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-06T06:46:08.034] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-06T06:46:08.035] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-06T18:30:59.929] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-06T18:30:59.931] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-06T18:30:59.933] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-07T03:40:26.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-07 03:40:26 +[2025-10-07T06:45:58.921] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-07T06:45:58.923] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-07T06:45:58.925] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-07T18:35:51.835] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-07T18:35:51.842] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-07T18:35:51.844] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-08T03:40:27.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-08 03:40:27 +[2025-10-08T06:38:19.620] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-08T06:38:19.623] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-08T06:38:19.625] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-08T18:33:14.048] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-08T18:33:14.051] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-08T18:33:14.053] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-09T03:40:28.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-09 03:40:28 +[2025-10-09T06:55:45.254] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-09T06:55:45.256] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-09T06:55:45.258] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-09T16:45:51.580] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-09T16:45:56.940] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-09T16:45:56.945] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-09T16:45:56.946] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-09T16:45:56.947] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-10-09T16:45:56.951] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T16:45:56.953] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-10-10T05:32:00.952Z +[2025-10-09T16:45:56.954] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-10-09T16:45:00.954Z +[2025-10-09T16:45:56.955] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T16:45:56.957] [INFO] monitorLogs - -->currentValue for relay 1 0 +[2025-10-09T16:45:56.958] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-09T16:45:56.958] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-10-09T16:45:56.961] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T16:45:56.962] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-10-10T05:32:00.962Z +[2025-10-09T16:45:56.963] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-10-09T16:45:00.963Z +[2025-10-09T16:45:56.963] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T16:45:56.965] [INFO] monitorLogs - -->currentValue for relay 2 0 +[2025-10-09T16:45:56.966] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-09T16:45:56.966] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-10-09T16:45:56.969] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T16:45:56.970] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-10-10T05:32:00.969Z +[2025-10-09T16:45:56.970] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-10-09T16:45:00.970Z +[2025-10-09T16:45:56.971] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T16:45:56.972] [INFO] monitorLogs - -->currentValue for relay 3 0 +[2025-10-09T16:45:56.980] [INFO] monitorLogs - tasks created: 854 +[2025-10-09T16:45:56.983] [INFO] monitorLogs - -->FLOW bol spustený d5xjWYMwEJon6rLlK7yEaP7qgV4DaOeNB9ZX3Gzb 2025-08-08 +[2025-10-09T16:46:01.990] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-09T18:26:33.334] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-09T18:26:33.340] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-09T18:26:33.342] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-09T18:57:57.395] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-09T18:58:02.760] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-09T18:58:02.766] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-09T18:58:02.767] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-09T18:58:02.768] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-10-09T18:58:02.772] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T18:58:02.773] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-10-10T05:32:00.772Z +[2025-10-09T18:58:02.775] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-10-10T16:45:00.774Z +[2025-10-09T18:58:02.775] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T18:58:02.776] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-10-09T18:58:02.777] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-09T18:58:02.778] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-10-09T18:58:02.780] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T18:58:02.781] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-10-10T05:32:00.781Z +[2025-10-09T18:58:02.782] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-10-10T16:45:00.782Z +[2025-10-09T18:58:02.782] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T18:58:02.783] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-10-09T18:58:02.784] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-09T18:58:02.785] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-10-09T18:58:02.787] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-09T18:58:02.787] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-10-10T05:32:00.787Z +[2025-10-09T18:58:02.788] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-10-10T16:45:00.788Z +[2025-10-09T18:58:02.789] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:32', name: 'luxOff' }, + { value: 1, start_time: '18:45', name: 'luxOn' } +] +[2025-10-09T18:58:02.790] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-10-09T18:58:02.812] [INFO] monitorLogs - tasks created: 854 +[2025-10-09T18:58:02.814] [INFO] monitorLogs - -->FLOW bol spustený d5xjWYMwEJon6rLlK7yEaP7qgV4DaOeNB9ZX3Gzb 2025-08-08 +[2025-10-09T18:58:07.821] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-10T03:58:04.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-10 03:58:04 +[2025-10-10T06:53:15.084] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-10T06:53:15.086] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-10T06:53:15.088] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-10T18:23:04.283] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-10T18:23:04.310] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-10T18:23:04.313] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-11T03:58:05.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-11 03:58:05 +[2025-10-11T06:55:37.902] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-11T06:55:37.904] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-11T06:55:37.906] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-11T18:25:26.703] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-11T18:25:26.706] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-11T18:25:26.708] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-12T03:58:06.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-12 03:58:06 +[2025-10-12T06:52:58.405] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-12T06:52:58.408] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-12T06:52:58.410] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-12T18:22:47.047] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-12T18:22:47.050] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-12T18:22:47.052] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-13T03:58:07.009] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-13 03:58:07 +[2025-10-13T06:47:49.091] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-13T06:47:49.094] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-13T06:47:49.096] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-13T18:27:40.043] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-13T18:27:40.081] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-13T18:27:40.083] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-14T03:58:08.008] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-14 03:58:08 +[2025-10-14T06:50:11.587] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-14T06:50:11.589] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-14T06:50:11.591] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-14T18:20:00.491] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-14T18:20:00.493] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-14T18:20:00.495] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor +[2025-10-14T22:23:49.694] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-14T22:23:55.060] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-14T22:23:55.065] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-14T22:23:55.066] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-14T22:23:55.067] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-10-14T22:23:55.071] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-14T22:23:55.072] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-10-15T05:40:00.072Z +[2025-10-14T22:23:55.074] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-10-15T16:35:00.074Z +[2025-10-14T22:23:55.074] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:40', name: 'luxOff' }, + { value: 1, start_time: '18:35', name: 'luxOn' } +] +[2025-10-14T22:23:55.076] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-10-14T22:23:55.076] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-14T22:23:55.077] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-10-14T22:23:55.079] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-14T22:23:55.080] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-10-15T05:40:00.080Z +[2025-10-14T22:23:55.081] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-10-15T16:35:00.081Z +[2025-10-14T22:23:55.081] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:40', name: 'luxOff' }, + { value: 1, start_time: '18:35', name: 'luxOn' } +] +[2025-10-14T22:23:55.082] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-10-14T22:23:55.083] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-14T22:23:55.083] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-10-14T22:23:55.086] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-14T22:23:55.086] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-10-15T05:40:00.086Z +[2025-10-14T22:23:55.087] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-10-15T16:35:00.087Z +[2025-10-14T22:23:55.088] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:40', name: 'luxOff' }, + { value: 1, start_time: '18:35', name: 'luxOn' } +] +[2025-10-14T22:23:55.088] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-10-14T22:23:55.093] [INFO] monitorLogs - tasks created: 840 +[2025-10-14T22:23:55.114] [INFO] monitorLogs - -->FLOW bol spustený d5xjWYMwEJon6rLlK7yEaP7qgV4DaOeNB9ZX3Gzb 2025-10-08 +[2025-10-14T22:24:00.103] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-14T22:27:37.560] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-14T22:27:42.929] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-14T22:27:42.933] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-14T22:27:42.935] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-14T22:27:42.935] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-10-14T22:27:42.939] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-14T22:27:42.941] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-10-15T05:40:00.940Z +[2025-10-14T22:27:42.942] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-10-15T16:35:00.942Z +[2025-10-14T22:27:42.943] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:40', name: 'luxOff' }, + { value: 1, start_time: '18:35', name: 'luxOn' } +] +[2025-10-14T22:27:42.944] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-10-14T22:27:42.945] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-14T22:27:42.945] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-10-14T22:27:42.948] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-14T22:27:42.948] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-10-15T05:40:00.948Z +[2025-10-14T22:27:42.949] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-10-15T16:35:00.949Z +[2025-10-14T22:27:42.949] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:40', name: 'luxOff' }, + { value: 1, start_time: '18:35', name: 'luxOn' } +] +[2025-10-14T22:27:42.950] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-10-14T22:27:42.951] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-14T22:27:42.952] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-10-14T22:27:42.954] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-14T22:27:42.954] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-10-15T05:40:00.954Z +[2025-10-14T22:27:42.955] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-10-15T16:35:00.955Z +[2025-10-14T22:27:42.956] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:40', name: 'luxOff' }, + { value: 1, start_time: '18:35', name: 'luxOn' } +] +[2025-10-14T22:27:42.956] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-10-14T22:27:42.978] [INFO] monitorLogs - tasks created: 854 +[2025-10-14T22:27:42.980] [INFO] monitorLogs - -->FLOW bol spustený d5xjWYMwEJon6rLlK7yEaP7qgV4DaOeNB9ZX3Gzb 2025-10-08 +[2025-10-14T22:27:47.987] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-14T22:32:50.261] [INFO] monitorLogs - DIDO_Relay_Controller installed +[2025-10-14T22:32:55.603] [INFO] monitorLogs - buildTasks - params undefined +[2025-10-14T22:32:55.608] [INFO] monitorLogs - turnLine off - (line, SETTINGS.maintenance_mode) 0 false No line profile. Switching it off on startup +[2025-10-14T22:32:55.609] [INFO] monitorLogs - buildTasks: profile for line 1 +[2025-10-14T22:32:55.610] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-10-14T22:32:55.614] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-14T22:32:55.616] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 1 2025-10-15T05:40:00.615Z +[2025-10-14T22:32:55.617] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 1 2025-10-15T16:35:00.617Z +[2025-10-14T22:32:55.618] [INFO] monitorLogs - -->time_points final 1 [ + { value: 0, start_time: '7:40', name: 'luxOff' }, + { value: 1, start_time: '18:35', name: 'luxOn' } +] +[2025-10-14T22:32:55.619] [INFO] monitorLogs - -->currentValue for relay 1 1 +[2025-10-14T22:32:55.620] [INFO] monitorLogs - buildTasks: profile for line 2 +[2025-10-14T22:32:55.620] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-10-14T22:32:55.623] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-14T22:32:55.623] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 2 2025-10-15T05:40:00.623Z +[2025-10-14T22:32:55.624] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 2 2025-10-15T16:35:00.624Z +[2025-10-14T22:32:55.625] [INFO] monitorLogs - -->time_points final 2 [ + { value: 0, start_time: '7:40', name: 'luxOff' }, + { value: 1, start_time: '18:35', name: 'luxOn' } +] +[2025-10-14T22:32:55.626] [INFO] monitorLogs - -->currentValue for relay 2 1 +[2025-10-14T22:32:55.627] [INFO] monitorLogs - buildTasks: profile for line 3 +[2025-10-14T22:32:55.627] [INFO] monitorLogs - profile: { + intervals: [ + { value: 0, end_time: '20:00', start_time: '13:00' }, + { value: 0, end_time: '13:00', start_time: '08:00' }, + { value: 1, end_time: '08:00', start_time: '20: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 +} +[2025-10-14T22:32:55.629] [INFO] monitorLogs - -->comming events turn on/off lines: +[2025-10-14T22:32:55.630] [INFO] monitorLogs - TimePoint params: luxOff: turn off line: 3 2025-10-15T05:40:00.630Z +[2025-10-14T22:32:55.631] [INFO] monitorLogs - TimePoint params: luxOn: turn on line: 3 2025-10-15T16:35:00.631Z +[2025-10-14T22:32:55.631] [INFO] monitorLogs - -->time_points final 3 [ + { value: 0, start_time: '7:40', name: 'luxOff' }, + { value: 1, start_time: '18:35', name: 'luxOn' } +] +[2025-10-14T22:32:55.632] [INFO] monitorLogs - -->currentValue for relay 3 1 +[2025-10-14T22:32:55.654] [INFO] monitorLogs - tasks created: 854 +[2025-10-14T22:32:55.657] [INFO] monitorLogs - -->FLOW bol spustený d5xjWYMwEJon6rLlK7yEaP7qgV4DaOeNB9ZX3Gzb 2025-10-08 +[2025-10-14T22:33:00.665] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false aplikovany bod profilu +[2025-10-15T03:32:56.011] [INFO] monitorLogs - setCorrectPlcTimeOnceADay() --> Nastaveny cas na: 2025-10-15 03:32:56 +[2025-10-15T06:57:24.298] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 1 relay1_02 false Profile: dawn - turnOff line according to lux sensor +[2025-10-15T06:57:24.300] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 2 relay1_03 false Profile: dawn - turnOff line according to lux sensor +[2025-10-15T06:57:24.302] [INFO] monitorLogs - Dido: turnLine off - (line, pin, force) 3 relay1_04 false Profile: dawn - turnOff line according to lux sensor +[2025-10-15T18:17:11.036] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 1 relay1_02 false Profile: dusk - turnOn line according to lux sensor +[2025-10-15T18:17:11.039] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 2 relay1_03 false Profile: dusk - turnOn line according to lux sensor +[2025-10-15T18:17:11.041] [INFO] monitorLogs - Dido: turnLine on - (line, pin, force) 3 relay1_04 false Profile: dusk - turnOn line according to lux sensor diff --git a/RVO53/package-lock.json b/RVO53/package-lock.json new file mode 100755 index 0000000..3c5c1ba --- /dev/null +++ b/RVO53/package-lock.json @@ -0,0 +1,2139 @@ +{ + "name": "emptyproject", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "emptyproject", + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "bitwise": "^2.1.0", + "easy-crc": "0.0.2", + "jsmodbus": "^4.0.6", + "log4js": "^6.3.0", + "moment": "^2.30.1", + "mqtt": "^4.2.6", + "nodemailer": "^6.9.7", + "serialport": "^9.2.8", + "total.js": "^3.4.13" + } + }, + "node_modules/@serialport/binding-abstract": { + "version": "9.2.3", + "resolved": "https://registry.npmjs.org/@serialport/binding-abstract/-/binding-abstract-9.2.3.tgz", + "integrity": "sha512-cQs9tbIlG3P0IrOWyVirqlhWuJ7Ms2Zh9m2108z6Y5UW/iVj6wEOiW8EmK9QX9jmJXYllE7wgGgvVozP5oCj3w==", + "dependencies": { + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/binding-mock": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/binding-mock/-/binding-mock-9.2.4.tgz", + "integrity": "sha512-dpEhACCs44oQhh6ajJfJdvQdK38Vq0N4W6iD/gdplglDCK7qXRQCMUjJIeKdS/HSEiWkC3bwumUhUufdsOyT4g==", + "dependencies": { + "@serialport/binding-abstract": "9.2.3", + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/bindings": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/@serialport/bindings/-/bindings-9.2.8.tgz", + "integrity": "sha512-hSLxTe0tADZ3LMMGwvEJWOC/TaFQTyPeFalUCsJ1lSQ0k6bPF04JwrtB/C81GetmDBTNRY0GlD0SNtKCc7Dr5g==", + "hasInstallScript": true, + "dependencies": { + "@serialport/binding-abstract": "9.2.3", + "@serialport/parser-readline": "9.2.4", + "bindings": "^1.5.0", + "debug": "^4.3.2", + "nan": "^2.15.0", + "prebuild-install": "^7.0.0" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-byte-length": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-byte-length/-/parser-byte-length-9.2.4.tgz", + "integrity": "sha512-sQD/iw4ZMU3xW9PLi0/GlvU6Y623jGeWecbMkO7izUo/6P7gtfv1c9ikd5h0kwL8AoAOpQA1lxdHIKox+umBUg==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-cctalk": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-cctalk/-/parser-cctalk-9.2.4.tgz", + "integrity": "sha512-T4TU5vQMwmo9AB3gQLFDWbfJXlW5jd9guEsB/nqKjFHTv0FXPdZ7DQ2TpSp8RnHWxU3GX6kYTaDO20BKzc8GPQ==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-delimiter": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-delimiter/-/parser-delimiter-9.2.4.tgz", + "integrity": "sha512-4nvTAoYAgkxFiXrkI+3CA49Yd43CODjeszh89EK+I9c8wOZ+etZduRCzINYPiy26g7zO+GRAb9FoPCsY+sYcbQ==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-inter-byte-timeout": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-inter-byte-timeout/-/parser-inter-byte-timeout-9.2.4.tgz", + "integrity": "sha512-SOAdvr0oBQIOCXX198hiTlxs4JTKg9j5piapw5tNq52fwDOWdbYrFneT/wN04UTMKaDrJuEvXq6T4rv4j7nJ5A==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-readline": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-readline/-/parser-readline-9.2.4.tgz", + "integrity": "sha512-Z1/qrZTQUVhNSJP1hd9YfDvq0o7d87rNwAjjRKbVpa7Qi51tG5BnKt43IV3NFMyBlVcRe0rnIb3tJu57E0SOwg==", + "dependencies": { + "@serialport/parser-delimiter": "9.2.4" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-ready": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-ready/-/parser-ready-9.2.4.tgz", + "integrity": "sha512-Pyi94Itjl6qAURwIZr/gmZpMAyTmKXThm6vL5DoAWGQjcRHWB0gwv2TY2v7N+mQLJYUKU3cMnvnATXxHm7xjxw==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-regex": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-regex/-/parser-regex-9.2.4.tgz", + "integrity": "sha512-sI/cVvPOYz+Dbv4ZdnW16qAwvXiFf/1pGASQdbveRTlgJDdz7sRNlCBifzfTN2xljwvCTZYqiudKvDdC1TepRQ==", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/stream": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/stream/-/stream-9.2.4.tgz", + "integrity": "sha512-bLye8Ub4vUFQGmkh8qEqehr7SE7EJs2yDs0h9jzuL5oKi+F34CFmWkEErO8GAOQ8YNn7p6b3GxUgs+0BrHHDZQ==", + "dependencies": { + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "node_modules/are-we-there-yet": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", + "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/base64-js": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", + "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==" + }, + "node_modules/bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "dependencies": { + "file-uri-to-path": "1.0.0" + } + }, + "node_modules/bitwise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/bitwise/-/bitwise-2.1.0.tgz", + "integrity": "sha512-XKgAhMXCh4H/3oNwAHAsAO0iC89s9cOiumgYwSHjSobGWxYjv62YhkL9QEdvGP151xypCtMlAfKK79GEcd2eRQ==" + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/bl/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/buffer": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz", + "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==", + "dependencies": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + }, + "node_modules/buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" + }, + "node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, + "node_modules/code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/commist": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/commist/-/commist-1.1.0.tgz", + "integrity": "sha512-rraC8NXWOEjhADbZe9QBNzLAN5Q3fsTPQtBV+fEVj6xKIgDgNiEVE6ZNfHpZOqfQ21YUzfVNUXLOEZquYvQPPg==", + "dependencies": { + "leven": "^2.1.0", + "minimist": "^1.1.0" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "node_modules/concat-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", + "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", + "engines": [ + "node >= 6.0" + ], + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.0.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/concat-stream/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" + }, + "node_modules/core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "node_modules/crc": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/crc/-/crc-3.4.0.tgz", + "integrity": "sha512-ycVC2+4/DLgXXq7QweYi2znhqDuZz6P5TQXnkQo8v15XY/5p/IWeZwsSE31Ifo8w15b8TWLsqhXOjXyilHuQxw==" + }, + "node_modules/date-format": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.11.tgz", + "integrity": "sha512-VS20KRyorrbMCQmpdl2hg5KaOUsda1RbnsJg461FfrcyCUg+pkd0b40BSW4niQyTheww4DBXQnS7HwSrKkipLw==", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" + }, + "node_modules/detect-libc": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz", + "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==", + "engines": { + "node": ">=8" + } + }, + "node_modules/duplexify": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.2.tgz", + "integrity": "sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw==", + "dependencies": { + "end-of-stream": "^1.4.1", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1", + "stream-shift": "^1.0.0" + } + }, + "node_modules/duplexify/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/easy-crc": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/easy-crc/-/easy-crc-0.0.2.tgz", + "integrity": "sha512-h6eqIdhJRe0p271/xZJbM/0klCi13mW5IB7ZEzEGH11yV4QXWAkD4yPErz0fXdhFrd6sZ4Q1k5Iky2kMsMNePw==" + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" + }, + "node_modules/flatted": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", + "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==" + }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, + "node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "node_modules/gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha512-14x4kjc6lkD3ltw589k0NrPD6cCNTD6CWoVUNpB85+DrtONoZn+Rug6xZU5RvSC4+TZPxA5AnBibQYAvZn41Hg==", + "dependencies": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "node_modules/github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==" + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" + }, + "node_modules/has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" + }, + "node_modules/help-me": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/help-me/-/help-me-3.0.0.tgz", + "integrity": "sha512-hx73jClhyk910sidBB7ERlnhMlFsJJIBqSVMFDwPN8o2v9nmp5KgLq1Xz1Bf1fCMMZ6mPrX159iG0VLy/fPMtQ==", + "dependencies": { + "glob": "^7.1.6", + "readable-stream": "^3.6.0" + } + }, + "node_modules/help-me/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, + "node_modules/is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==", + "dependencies": { + "number-is-nan": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "node_modules/js-sdsl": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz", + "integrity": "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/js-sdsl" + } + }, + "node_modules/jsmodbus": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/jsmodbus/-/jsmodbus-4.0.6.tgz", + "integrity": "sha512-gCmjoaERErK5Rn9Lu/BN07fY13MoWV7JKgGzrnkPlQPdPxYcwDhLtYcmpFFpZ4J9NPZZBSezi1UkLZO/DnNppA==", + "dependencies": { + "crc": "3.4.0", + "debug": "^3.1.0" + }, + "bin": { + "jsmodbus": "bin/jsmodbus.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/jsmodbus/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/leven": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", + "integrity": "sha1-wuep93IJTe6dNCAq6KzORoeHVYA=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/log4js": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.5.2.tgz", + "integrity": "sha512-DXtpNtt+KDOMT7RHUDIur/WsSA3rntlUh9Zg4XCdV42wUuMmbFkl38+LZ92Z5QvQA7mD5kAVkLiBSEH/tvUB8A==", + "dependencies": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "flatted": "^3.2.5", + "rfdc": "^1.3.0", + "streamroller": "^3.1.1" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" + }, + "node_modules/moment": { + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", + "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==", + "engines": { + "node": "*" + } + }, + "node_modules/mqtt": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/mqtt/-/mqtt-4.3.7.tgz", + "integrity": "sha512-ew3qwG/TJRorTz47eW46vZ5oBw5MEYbQZVaEji44j5lAUSQSqIEoul7Kua/BatBW0H0kKQcC9kwUHa1qzaWHSw==", + "dependencies": { + "commist": "^1.0.0", + "concat-stream": "^2.0.0", + "debug": "^4.1.1", + "duplexify": "^4.1.1", + "help-me": "^3.0.0", + "inherits": "^2.0.3", + "lru-cache": "^6.0.0", + "minimist": "^1.2.5", + "mqtt-packet": "^6.8.0", + "number-allocator": "^1.0.9", + "pump": "^3.0.0", + "readable-stream": "^3.6.0", + "reinterval": "^1.1.0", + "rfdc": "^1.3.0", + "split2": "^3.1.0", + "ws": "^7.5.5", + "xtend": "^4.0.2" + }, + "bin": { + "mqtt": "bin/mqtt.js", + "mqtt_pub": "bin/pub.js", + "mqtt_sub": "bin/sub.js" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/mqtt-packet": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/mqtt-packet/-/mqtt-packet-6.10.0.tgz", + "integrity": "sha512-ja8+mFKIHdB1Tpl6vac+sktqy3gA8t9Mduom1BA75cI+R9AHnZOiaBQwpGiWnaVJLDGRdNhQmFaAqd7tkKSMGA==", + "dependencies": { + "bl": "^4.0.2", + "debug": "^4.1.1", + "process-nextick-args": "^2.0.1" + } + }, + "node_modules/mqtt/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/nan": { + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.16.0.tgz", + "integrity": "sha512-UdAqHyFngu7TfQKsCBgAA6pWDkT8MAO7d0jyOecVhN5354xbLqdn8mV9Tat9gepAupm0bt2DbeaSC8vS52MuFA==" + }, + "node_modules/napi-build-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", + "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==" + }, + "node_modules/node-abi": { + "version": "3.22.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.22.0.tgz", + "integrity": "sha512-u4uAs/4Zzmp/jjsD9cyFYDXeISfUWaAVWshPmDZOFOv4Xl4SbzTXm53I04C2uRueYJ+0t5PEtLH/owbn2Npf/w==", + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/nodemailer": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.7.tgz", + "integrity": "sha512-rUtR77ksqex/eZRLmQ21LKVH5nAAsVicAtAYudK7JgwenEDZ0UIQ1adUGqErz7sMkWYxWTTU1aeP2Jga6WQyJw==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "dependencies": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "node_modules/number-allocator": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/number-allocator/-/number-allocator-1.0.14.tgz", + "integrity": "sha512-OrL44UTVAvkKdOdRQZIJpLkAdjXGTRda052sN4sO77bKEzYYqWKMBjQvrJFzqygI99gL6Z4u2xctPW1tB8ErvA==", + "dependencies": { + "debug": "^4.3.1", + "js-sdsl": "4.3.0" + } + }, + "node_modules/number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/prebuild-install": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.0.tgz", + "integrity": "sha512-CNcMgI1xBypOyGqjp3wOc8AAo1nMhZS3Cwd3iHIxOdAUbb+YxdNuM4Z5iIrZ8RLvOsf3F3bl7b7xGq6DjQoNYA==", + "dependencies": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^1.0.1", + "node-abi": "^3.3.0", + "npmlog": "^4.0.1", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + }, + "bin": { + "prebuild-install": "bin.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/reinterval": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reinterval/-/reinterval-1.1.0.tgz", + "integrity": "sha1-M2Hs+jymwYKDOA3Qu5VG85D17Oc=" + }, + "node_modules/rfdc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==" + }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/serialport": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/serialport/-/serialport-9.2.8.tgz", + "integrity": "sha512-FsWpMQgSJxi93JgWl5xM1f9/Z8IjRJuaUEoHqLf8FPBLw7gMhInuHOBhI2onQufWIYPGTz3H3oGcu1nCaK1EfA==", + "dependencies": { + "@serialport/binding-mock": "9.2.4", + "@serialport/bindings": "9.2.8", + "@serialport/parser-byte-length": "9.2.4", + "@serialport/parser-cctalk": "9.2.4", + "@serialport/parser-delimiter": "9.2.4", + "@serialport/parser-inter-byte-timeout": "9.2.4", + "@serialport/parser-readline": "9.2.4", + "@serialport/parser-ready": "9.2.4", + "@serialport/parser-regex": "9.2.4", + "@serialport/stream": "9.2.4", + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "node_modules/split2": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", + "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", + "dependencies": { + "readable-stream": "^3.0.0" + } + }, + "node_modules/split2/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==" + }, + "node_modules/streamroller": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.1.1.tgz", + "integrity": "sha512-iPhtd9unZ6zKdWgMeYGfSBuqCngyJy1B/GPi/lTpwGpa3bajuX30GjUVd0/Tn/Xhg0mr4DOSENozz9Y06qyonQ==", + "dependencies": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "fs-extra": "^10.1.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dependencies": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/tar-fs": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "dependencies": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tar-stream/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/total.js": { + "version": "3.4.13", + "resolved": "https://registry.npmjs.org/total.js/-/total.js-3.4.13.tgz", + "integrity": "sha512-lAH4gEixlPFbrE3xfKADAcHfO79IFq2wKa9GTsrgRzIR5MTg3mNH7+4IxvX1pK8faoYb/0oYSJ1YTsAa5hIFFQ==", + "bin": { + "total": "bin/totaljs", + "total.js": "bin/totaljs", + "totaljs": "bin/totaljs", + "totalpackage": "bin/tpm", + "tpm": "bin/tpm" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, + "node_modules/universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "node_modules/wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "node_modules/ws": { + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } + }, + "dependencies": { + "@serialport/binding-abstract": { + "version": "9.2.3", + "resolved": "https://registry.npmjs.org/@serialport/binding-abstract/-/binding-abstract-9.2.3.tgz", + "integrity": "sha512-cQs9tbIlG3P0IrOWyVirqlhWuJ7Ms2Zh9m2108z6Y5UW/iVj6wEOiW8EmK9QX9jmJXYllE7wgGgvVozP5oCj3w==", + "requires": { + "debug": "^4.3.2" + } + }, + "@serialport/binding-mock": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/binding-mock/-/binding-mock-9.2.4.tgz", + "integrity": "sha512-dpEhACCs44oQhh6ajJfJdvQdK38Vq0N4W6iD/gdplglDCK7qXRQCMUjJIeKdS/HSEiWkC3bwumUhUufdsOyT4g==", + "requires": { + "@serialport/binding-abstract": "9.2.3", + "debug": "^4.3.2" + } + }, + "@serialport/bindings": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/@serialport/bindings/-/bindings-9.2.8.tgz", + "integrity": "sha512-hSLxTe0tADZ3LMMGwvEJWOC/TaFQTyPeFalUCsJ1lSQ0k6bPF04JwrtB/C81GetmDBTNRY0GlD0SNtKCc7Dr5g==", + "requires": { + "@serialport/binding-abstract": "9.2.3", + "@serialport/parser-readline": "9.2.4", + "bindings": "^1.5.0", + "debug": "^4.3.2", + "nan": "^2.15.0", + "prebuild-install": "^7.0.0" + } + }, + "@serialport/parser-byte-length": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-byte-length/-/parser-byte-length-9.2.4.tgz", + "integrity": "sha512-sQD/iw4ZMU3xW9PLi0/GlvU6Y623jGeWecbMkO7izUo/6P7gtfv1c9ikd5h0kwL8AoAOpQA1lxdHIKox+umBUg==" + }, + "@serialport/parser-cctalk": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-cctalk/-/parser-cctalk-9.2.4.tgz", + "integrity": "sha512-T4TU5vQMwmo9AB3gQLFDWbfJXlW5jd9guEsB/nqKjFHTv0FXPdZ7DQ2TpSp8RnHWxU3GX6kYTaDO20BKzc8GPQ==" + }, + "@serialport/parser-delimiter": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-delimiter/-/parser-delimiter-9.2.4.tgz", + "integrity": "sha512-4nvTAoYAgkxFiXrkI+3CA49Yd43CODjeszh89EK+I9c8wOZ+etZduRCzINYPiy26g7zO+GRAb9FoPCsY+sYcbQ==" + }, + "@serialport/parser-inter-byte-timeout": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-inter-byte-timeout/-/parser-inter-byte-timeout-9.2.4.tgz", + "integrity": "sha512-SOAdvr0oBQIOCXX198hiTlxs4JTKg9j5piapw5tNq52fwDOWdbYrFneT/wN04UTMKaDrJuEvXq6T4rv4j7nJ5A==" + }, + "@serialport/parser-readline": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-readline/-/parser-readline-9.2.4.tgz", + "integrity": "sha512-Z1/qrZTQUVhNSJP1hd9YfDvq0o7d87rNwAjjRKbVpa7Qi51tG5BnKt43IV3NFMyBlVcRe0rnIb3tJu57E0SOwg==", + "requires": { + "@serialport/parser-delimiter": "9.2.4" + } + }, + "@serialport/parser-ready": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-ready/-/parser-ready-9.2.4.tgz", + "integrity": "sha512-Pyi94Itjl6qAURwIZr/gmZpMAyTmKXThm6vL5DoAWGQjcRHWB0gwv2TY2v7N+mQLJYUKU3cMnvnATXxHm7xjxw==" + }, + "@serialport/parser-regex": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-regex/-/parser-regex-9.2.4.tgz", + "integrity": "sha512-sI/cVvPOYz+Dbv4ZdnW16qAwvXiFf/1pGASQdbveRTlgJDdz7sRNlCBifzfTN2xljwvCTZYqiudKvDdC1TepRQ==" + }, + "@serialport/stream": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/stream/-/stream-9.2.4.tgz", + "integrity": "sha512-bLye8Ub4vUFQGmkh8qEqehr7SE7EJs2yDs0h9jzuL5oKi+F34CFmWkEErO8GAOQ8YNn7p6b3GxUgs+0BrHHDZQ==", + "requires": { + "debug": "^4.3.2" + } + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==" + }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "are-we-there-yet": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", + "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "base64-js": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", + "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==" + }, + "bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "requires": { + "file-uri-to-path": "1.0.0" + } + }, + "bitwise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/bitwise/-/bitwise-2.1.0.tgz", + "integrity": "sha512-XKgAhMXCh4H/3oNwAHAsAO0iC89s9cOiumgYwSHjSobGWxYjv62YhkL9QEdvGP151xypCtMlAfKK79GEcd2eRQ==" + }, + "bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "requires": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "buffer": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz", + "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==", + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" + }, + "chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==" + }, + "commist": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/commist/-/commist-1.1.0.tgz", + "integrity": "sha512-rraC8NXWOEjhADbZe9QBNzLAN5Q3fsTPQtBV+fEVj6xKIgDgNiEVE6ZNfHpZOqfQ21YUzfVNUXLOEZquYvQPPg==", + "requires": { + "leven": "^2.1.0", + "minimist": "^1.1.0" + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "concat-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", + "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.0.2", + "typedarray": "^0.0.6" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "crc": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/crc/-/crc-3.4.0.tgz", + "integrity": "sha512-ycVC2+4/DLgXXq7QweYi2znhqDuZz6P5TQXnkQo8v15XY/5p/IWeZwsSE31Ifo8w15b8TWLsqhXOjXyilHuQxw==" + }, + "date-format": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.11.tgz", + "integrity": "sha512-VS20KRyorrbMCQmpdl2hg5KaOUsda1RbnsJg461FfrcyCUg+pkd0b40BSW4niQyTheww4DBXQnS7HwSrKkipLw==" + }, + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "requires": { + "ms": "2.1.2" + } + }, + "decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "requires": { + "mimic-response": "^3.1.0" + } + }, + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==" + }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" + }, + "detect-libc": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz", + "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==" + }, + "duplexify": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.2.tgz", + "integrity": "sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw==", + "requires": { + "end-of-stream": "^1.4.1", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1", + "stream-shift": "^1.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "easy-crc": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/easy-crc/-/easy-crc-0.0.2.tgz", + "integrity": "sha512-h6eqIdhJRe0p271/xZJbM/0klCi13mW5IB7ZEzEGH11yV4QXWAkD4yPErz0fXdhFrd6sZ4Q1k5Iky2kMsMNePw==" + }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "requires": { + "once": "^1.4.0" + } + }, + "expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==" + }, + "file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" + }, + "flatted": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", + "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==" + }, + "fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, + "fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha512-14x4kjc6lkD3ltw589k0NrPD6cCNTD6CWoVUNpB85+DrtONoZn+Rug6xZU5RvSC4+TZPxA5AnBibQYAvZn41Hg==", + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==" + }, + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" + }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" + }, + "help-me": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/help-me/-/help-me-3.0.0.tgz", + "integrity": "sha512-hx73jClhyk910sidBB7ERlnhMlFsJJIBqSVMFDwPN8o2v9nmp5KgLq1Xz1Bf1fCMMZ6mPrX159iG0VLy/fPMtQ==", + "requires": { + "glob": "^7.1.6", + "readable-stream": "^3.6.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==", + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "js-sdsl": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz", + "integrity": "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==" + }, + "jsmodbus": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/jsmodbus/-/jsmodbus-4.0.6.tgz", + "integrity": "sha512-gCmjoaERErK5Rn9Lu/BN07fY13MoWV7JKgGzrnkPlQPdPxYcwDhLtYcmpFFpZ4J9NPZZBSezi1UkLZO/DnNppA==", + "requires": { + "crc": "3.4.0", + "debug": "^3.1.0" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "requires": { + "ms": "^2.1.1" + } + } + } + }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, + "leven": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", + "integrity": "sha1-wuep93IJTe6dNCAq6KzORoeHVYA=" + }, + "log4js": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.5.2.tgz", + "integrity": "sha512-DXtpNtt+KDOMT7RHUDIur/WsSA3rntlUh9Zg4XCdV42wUuMmbFkl38+LZ92Z5QvQA7mD5kAVkLiBSEH/tvUB8A==", + "requires": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "flatted": "^3.2.5", + "rfdc": "^1.3.0", + "streamroller": "^3.1.1" + } + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "requires": { + "yallist": "^4.0.0" + } + }, + "mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==" + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==" + }, + "mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" + }, + "moment": { + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", + "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==" + }, + "mqtt": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/mqtt/-/mqtt-4.3.7.tgz", + "integrity": "sha512-ew3qwG/TJRorTz47eW46vZ5oBw5MEYbQZVaEji44j5lAUSQSqIEoul7Kua/BatBW0H0kKQcC9kwUHa1qzaWHSw==", + "requires": { + "commist": "^1.0.0", + "concat-stream": "^2.0.0", + "debug": "^4.1.1", + "duplexify": "^4.1.1", + "help-me": "^3.0.0", + "inherits": "^2.0.3", + "lru-cache": "^6.0.0", + "minimist": "^1.2.5", + "mqtt-packet": "^6.8.0", + "number-allocator": "^1.0.9", + "pump": "^3.0.0", + "readable-stream": "^3.6.0", + "reinterval": "^1.1.0", + "rfdc": "^1.3.0", + "split2": "^3.1.0", + "ws": "^7.5.5", + "xtend": "^4.0.2" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "mqtt-packet": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/mqtt-packet/-/mqtt-packet-6.10.0.tgz", + "integrity": "sha512-ja8+mFKIHdB1Tpl6vac+sktqy3gA8t9Mduom1BA75cI+R9AHnZOiaBQwpGiWnaVJLDGRdNhQmFaAqd7tkKSMGA==", + "requires": { + "bl": "^4.0.2", + "debug": "^4.1.1", + "process-nextick-args": "^2.0.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "nan": { + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.16.0.tgz", + "integrity": "sha512-UdAqHyFngu7TfQKsCBgAA6pWDkT8MAO7d0jyOecVhN5354xbLqdn8mV9Tat9gepAupm0bt2DbeaSC8vS52MuFA==" + }, + "napi-build-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", + "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==" + }, + "node-abi": { + "version": "3.22.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.22.0.tgz", + "integrity": "sha512-u4uAs/4Zzmp/jjsD9cyFYDXeISfUWaAVWshPmDZOFOv4Xl4SbzTXm53I04C2uRueYJ+0t5PEtLH/owbn2Npf/w==", + "requires": { + "semver": "^7.3.5" + } + }, + "nodemailer": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.7.tgz", + "integrity": "sha512-rUtR77ksqex/eZRLmQ21LKVH5nAAsVicAtAYudK7JgwenEDZ0UIQ1adUGqErz7sMkWYxWTTU1aeP2Jga6WQyJw==" + }, + "npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "number-allocator": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/number-allocator/-/number-allocator-1.0.14.tgz", + "integrity": "sha512-OrL44UTVAvkKdOdRQZIJpLkAdjXGTRda052sN4sO77bKEzYYqWKMBjQvrJFzqygI99gL6Z4u2xctPW1tB8ErvA==", + "requires": { + "debug": "^4.3.1", + "js-sdsl": "4.3.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==" + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==" + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==" + }, + "prebuild-install": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.0.tgz", + "integrity": "sha512-CNcMgI1xBypOyGqjp3wOc8AAo1nMhZS3Cwd3iHIxOdAUbb+YxdNuM4Z5iIrZ8RLvOsf3F3bl7b7xGq6DjQoNYA==", + "requires": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^1.0.1", + "node-abi": "^3.3.0", + "npmlog": "^4.0.1", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + } + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + } + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "reinterval": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reinterval/-/reinterval-1.1.0.tgz", + "integrity": "sha1-M2Hs+jymwYKDOA3Qu5VG85D17Oc=" + }, + "rfdc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==" + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "requires": { + "lru-cache": "^6.0.0" + } + }, + "serialport": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/serialport/-/serialport-9.2.8.tgz", + "integrity": "sha512-FsWpMQgSJxi93JgWl5xM1f9/Z8IjRJuaUEoHqLf8FPBLw7gMhInuHOBhI2onQufWIYPGTz3H3oGcu1nCaK1EfA==", + "requires": { + "@serialport/binding-mock": "9.2.4", + "@serialport/bindings": "9.2.8", + "@serialport/parser-byte-length": "9.2.4", + "@serialport/parser-cctalk": "9.2.4", + "@serialport/parser-delimiter": "9.2.4", + "@serialport/parser-inter-byte-timeout": "9.2.4", + "@serialport/parser-readline": "9.2.4", + "@serialport/parser-ready": "9.2.4", + "@serialport/parser-regex": "9.2.4", + "@serialport/stream": "9.2.4", + "debug": "^4.3.2" + } + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==" + }, + "simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "requires": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "split2": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", + "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", + "requires": { + "readable-stream": "^3.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==" + }, + "streamroller": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.1.1.tgz", + "integrity": "sha512-iPhtd9unZ6zKdWgMeYGfSBuqCngyJy1B/GPi/lTpwGpa3bajuX30GjUVd0/Tn/Xhg0mr4DOSENozz9Y06qyonQ==", + "requires": { + "date-format": "^4.0.10", + "debug": "^4.3.4", + "fs-extra": "^10.1.0" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" + }, + "tar-fs": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "requires": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "requires": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "total.js": { + "version": "3.4.13", + "resolved": "https://registry.npmjs.org/total.js/-/total.js-3.4.13.tgz", + "integrity": "sha512-lAH4gEixlPFbrE3xfKADAcHfO79IFq2wKa9GTsrgRzIR5MTg3mNH7+4IxvX1pK8faoYb/0oYSJ1YTsAa5hIFFQ==" + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, + "universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==" + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "requires": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "ws": { + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "requires": {} + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } + } +} diff --git a/RVO53/package.json b/RVO53/package.json new file mode 100755 index 0000000..7f7c795 --- /dev/null +++ b/RVO53/package.json @@ -0,0 +1,30 @@ +{ + "name": "emptyproject", + "description": "Total.js empty project.", + "version": "1.0.0", + "main": "debug.js", + "dependencies": { + "bitwise": "^2.1.0", + "easy-crc": "0.0.2", + "jsmodbus": "^4.0.6", + "log4js": "^6.3.0", + "moment": "^2.30.1", + "mqtt": "^4.2.6", + "nodemailer": "^6.9.7", + "serialport": "^9.2.8", + "total.js": "^3.4.13" + }, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "https://github.com/totaljs/emptyproject-flow" + }, + "keywords": [ + "empty", + "project" + ], + "author": "Peter Širka", + "license": "MIT" +} diff --git a/RVO53/release.js b/RVO53/release.js new file mode 100755 index 0000000..02d52ff --- /dev/null +++ b/RVO53/release.js @@ -0,0 +1,15 @@ +// =================================================== +// FOR PRODUCTION +// Total.js - framework for Node.js platform +// https://www.totaljs.com +// =================================================== + +const options = {'ip':'0.0.0.0', 'port':12345}; + +// options.ip = '127.0.0.1'; +// options.port = parseInt(process.argv[2]); +// options.config = { name: 'Total.js' }; +// options.sleep = 3000; + +require('total.js').http('release', options); +// require('total.js').cluster.http(5, 'release', options); diff --git a/RVO53/release.js.json b/RVO53/release.js.json new file mode 100755 index 0000000..40fb4a8 --- /dev/null +++ b/RVO53/release.js.json @@ -0,0 +1,34 @@ +{ + "pid": 7880, + "stats": [ + { + "id": null, + "version": { + "node": "v14.18.1", + "total": "3.4.13", + "app": "1.0.0" + }, + "pid": 7880, + "thread": "", + "mode": "release", + "overload": 0, + "date": "2025-10-16T00:26:47.750Z", + "memory": 24.48, + "rm": 0, + "fm": 0, + "wm": 0, + "mm": 0, + "om": 14, + "em": 0, + "dbrm": 0, + "dbwm": 0, + "usage": 0, + "requests": 0, + "pending": 0, + "errors": 0, + "timeouts": 0, + "uptime": 1675, + "online": 0 + } + ] +} \ No newline at end of file diff --git a/RVO53/report_data.log b/RVO53/report_data.log new file mode 100755 index 0000000..bbffc2d --- /dev/null +++ b/RVO53/report_data.log @@ -0,0 +1,2274 @@ +{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-09T17:58:08.433Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "2615", + "2639", + "2663" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-09T18:58:08.431Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "2615", + "2639", + "2663" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-09T19:58:08.431Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "2615", + "2639", + "2663" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-09T20:58:08.431Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "2615", + "2639", + "2663" + ], + "night_dimming=0": [], + "night_power=0": [ + "2597" + ], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-09T21:58:08.438Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "2615", + "2639", + "2663" + ], + "night_dimming=0": [], + "night_power=0": [ + "2597" + ], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-09T22:58:08.431Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "2615", + "2639", + "2663" + ], + "night_dimming=0": [], + "night_power=0": [ + "2597" + ], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-09T23:58:08.431Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "2615", + "2639", + "2663" + ], + "night_dimming=0": [], + "night_power=0": [ + "2597" + ], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-10T00:58:08.432Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "2615", + "2639", + "2663" + ], + "night_dimming=0": [], + "night_power=0": [ + "2597" + ], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-10T01:58:09.323Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "2615", + "2639", + "2663" + ], + "night_dimming=0": [], + "night_power=0": [ + "2597" + ], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-10T02:58:09.321Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "2615", + "2639", + "2663" + ], + "night_dimming=0": [], + "night_power=0": [ + "2597" + ], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-10T03:58:09.321Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "2615", + "2639", + "2663" + ], + "night_dimming=0": [], + "night_power=0": [ + "2597" + ], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-10T07:32:01.861Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-10T08:32:01.861Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-10T09:32:01.862Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-10T10:32:01.863Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-10T11:32:01.864Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-10T12:32:01.864Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-10T13:32:01.865Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-10T14:32:01.865Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-10T15:32:01.865Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-10T17:55:59.721Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "2615", + "2639", + "2663" + ], + "night_dimming=0": [], + "night_power=0": [ + "2597" + ], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-10T18:55:59.719Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "2615", + "2639", + "2663" + ], + "night_dimming=0": [], + "night_power=0": [ + "2597" + ], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-10T19:55:59.721Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "2615", + "2639", + "2663" + ], + "night_dimming=0": [], + "night_power=0": [ + "2597" + ], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-10T20:55:59.722Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "2615", + "2639", + "2663" + ], + "night_dimming=0": [], + "night_power=0": [ + "2597" + ], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-10T21:55:59.725Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "2615", + "2639", + "2663" + ], + "night_dimming=0": [], + "night_power=0": [ + "2597" + ], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-10T22:55:59.723Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "2615", + "2639", + "2663" + ], + "night_dimming=0": [], + "night_power=0": [ + "2597" + ], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-10T23:55:59.725Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "2615", + "2639", + "2663" + ], + "night_dimming=0": [], + "night_power=0": [ + "2597" + ], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-11T00:55:59.726Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "2615", + "2639", + "2663" + ], + "night_dimming=0": [], + "night_power=0": [ + "2597" + ], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-11T01:55:59.726Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "2615", + "2639", + "2663" + ], + "night_dimming=0": [], + "night_power=0": [ + "2597" + ], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-11T02:56:00.695Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "2615", + "2639", + "2663" + ], + "night_dimming=0": [], + "night_power=0": [ + "2597" + ], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-11T03:56:00.694Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "2615", + "2639", + "2663" + ], + "night_dimming=0": [], + "night_power=0": [ + "2597" + ], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-11T07:35:58.088Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-11T08:35:58.088Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-11T09:35:58.089Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-11T10:35:58.088Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-11T11:35:58.088Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-11T12:35:58.089Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-11T13:35:58.088Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-11T14:35:58.088Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-11T15:35:58.089Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-11T17:48:58.822Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "2615", + "2639", + "2663" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-11T18:48:58.822Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "2615", + "2639", + "2663" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-11T19:48:58.823Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "2615", + "2639", + "2663" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-11T20:48:58.825Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "2615", + "2639", + "2663" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-11T21:48:58.824Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "2615", + "2639", + "2663" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-11T22:48:58.826Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "2615", + "2639", + "2663" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-11T23:48:58.835Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "2615", + "2639", + "2663" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-12T00:48:58.835Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "2615", + "2639", + "2663" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-12T01:48:58.837Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "2615", + "2639", + "2663" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-12T02:48:59.833Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "2615", + "2639", + "2663" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-12T03:48:59.832Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "2615", + "2639", + "2663" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-12T04:48:59.833Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "2615", + "2639", + "2663" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-12T07:37:27.369Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-12T08:37:27.368Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-12T09:37:27.369Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-12T10:37:27.369Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-12T11:37:27.370Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-12T12:37:27.370Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-12T13:37:27.370Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-12T14:37:27.370Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-12T15:37:27.370Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-12T17:48:15.501Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "2615", + "2639", + "2663" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-12T18:48:15.502Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "2615", + "2639", + "2663" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-12T19:48:15.503Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "2615", + "2639", + "2663" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-12T20:48:15.504Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "2615", + "2639", + "2663" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-12T21:48:15.504Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "2615", + "2639", + "2663" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-12T22:48:15.505Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "2615", + "2639", + "2663" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-12T23:48:15.506Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "2615", + "2639", + "2663" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-13T00:48:15.507Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "2615", + "2639", + "2663" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-13T01:48:15.508Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "2615", + "2639", + "2663" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-13T02:48:16.432Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "2615", + "2639", + "2663" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-13T03:48:16.432Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "2615", + "2639", + "2663" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-13T07:39:00.045Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-13T08:39:00.046Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-13T09:39:00.046Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-13T10:39:00.047Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-13T11:39:00.047Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-13T12:39:00.047Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-13T13:39:00.047Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-13T14:39:00.048Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-13T15:39:00.047Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-13T17:48:43.950Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "2615", + "2639", + "2663" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-13T18:48:43.951Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "2615", + "2639", + "2663" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-13T19:48:43.951Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "2615", + "2639", + "2663" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-13T20:48:43.951Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "2615", + "2639", + "2663" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-13T21:48:43.952Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "2615", + "2639", + "2663" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-13T22:48:43.953Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "2615", + "2639", + "2663" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-13T23:48:43.953Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "2615", + "2639", + "2663" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-14T00:48:43.953Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "2615", + "2639", + "2663" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-14T01:48:43.954Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "2615", + "2639", + "2663" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-14T02:48:45.052Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "2615", + "2639", + "2663" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-14T03:48:45.052Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "2615", + "2639", + "2663" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-14T04:48:45.054Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "2615", + "2639", + "2663" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-14T07:40:28.019Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-14T08:40:28.019Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-14T09:40:28.020Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-14T10:40:28.020Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-14T11:40:28.020Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-14T12:40:28.020Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-14T13:40:28.020Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-14T14:40:28.020Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-14T15:40:28.021Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-14T17:43:20.856Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "2615", + "2639", + "2663" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-14T18:43:20.857Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "2615", + "2639", + "2663" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-14T19:43:20.857Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "2615", + "2639", + "2663" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-14T21:33:01.276Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "53/16_1L_2615_3f", + "53/57_1L_2639_3f", + "53/31_1L_2663_01-Repeater" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-14T22:33:01.274Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "53/16_1L_2615_3f", + "53/57_1L_2639_3f", + "53/31_1L_2663_01-Repeater" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-14T23:33:01.275Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "53/16_1L_2615_3f", + "53/57_1L_2639_3f", + "53/31_1L_2663_01-Repeater" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-15T00:33:01.275Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "53/16_1L_2615_3f", + "53/57_1L_2639_3f", + "53/31_1L_2663_01-Repeater" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-15T01:33:01.331Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "53/16_1L_2615_3f", + "53/57_1L_2639_3f", + "53/31_1L_2663_01-Repeater" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-15T02:33:01.332Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "53/16_1L_2615_3f", + "53/57_1L_2639_3f", + "53/31_1L_2663_01-Repeater" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-15T03:33:01.333Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "53/16_1L_2615_3f", + "53/57_1L_2639_3f", + "53/31_1L_2663_01-Repeater" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-15T04:33:01.333Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "53/16_1L_2615_3f", + "53/57_1L_2639_3f", + "53/31_1L_2663_01-Repeater" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-15T07:40:04.735Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-15T08:40:04.735Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-15T09:40:04.736Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-15T10:40:04.736Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-15T11:40:04.737Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-15T12:40:04.738Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-15T13:40:04.738Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-15T14:40:04.738Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-15T15:40:04.738Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-15T17:42:26.377Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "53/16_1L_2615_3f", + "53/57_1L_2639_3f", + "53/31_1L_2663_01-Repeater" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-15T18:42:26.377Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "53/16_1L_2615_3f", + "53/57_1L_2639_3f", + "53/31_1L_2663_01-Repeater" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-15T19:42:26.377Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "53/16_1L_2615_3f", + "53/57_1L_2639_3f", + "53/31_1L_2663_01-Repeater" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-15T20:42:26.378Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "53/16_1L_2615_3f", + "53/57_1L_2639_3f", + "53/31_1L_2663_01-Repeater" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-15T21:42:26.377Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "53/16_1L_2615_3f", + "53/57_1L_2639_3f", + "53/31_1L_2663_01-Repeater" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-15T22:42:26.378Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "53/16_1L_2615_3f", + "53/57_1L_2639_3f", + "53/31_1L_2663_01-Repeater" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +}{ + "name": "rvo_senica_53_ip107", + "time": "2025-10-15T23:42:26.378Z", + "report": { + "contactor": { + "off": [], + "on": [] + }, + "night_no_data": [ + "53/16_1L_2615_3f", + "53/57_1L_2639_3f", + "53/31_1L_2663_01-Repeater" + ], + "night_dimming=0": [], + "night_power=0": [], + "day_24/7_no_data": [], + "day_24/7_dimming>0": [], + "day_24/7_power>0": [] + } +} \ No newline at end of file